diff --git a/.github/file-filter.yml b/.github/file-filter.yml index b19f45c68b..66c6ba58a6 100644 --- a/.github/file-filter.yml +++ b/.github/file-filter.yml @@ -33,3 +33,17 @@ tee_test: &tee_test - 'tee-worker/cli/*.sh' - 'docker/**' - 'tee-worker/docker/*.yml' + +bitacross_src: &bitacross_src + - 'bitacross-worker/**/*.rs' + - 'bitacross-worker/**/Cargo.toml' + - 'bitacross-worker/**/Cargo.lock' + - 'bitacross-worker/**/rust-toolchain.toml' + - 'bitacross-worker/build.Dockerfile' + - 'bitacross-worker/enclave-runtime/**' + +bitacross_test: &bitacross_src + - 'bitacross-worker/ts-tests/**' + - 'bitacross-worker/cli/*.sh' + - 'docker/**' + - 'bitacross-worker/docker/*.yml' diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e4a60199bc..37d6fb6c2e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -84,9 +84,11 @@ jobs: outputs: rebuild_parachain: ${{ steps.env.outputs.rebuild_parachain }} rebuild_tee: ${{ steps.env.outputs.rebuild_tee }} + rebuild_bitacross: ${{ steps.env.outputs.rebuild_bitacross }} push_docker: ${{ steps.env.outputs.push_docker }} run_parachain_test: ${{ steps.env.outputs.run_parachain_test }} run_tee_test: ${{ steps.env.outputs.run_tee_test }} + run_bitacross_test: ${{ steps.env.outputs.run_bitacross_test }} steps: - uses: actions/checkout@v4 with: @@ -105,6 +107,7 @@ jobs: run: | rebuild_parachain=false rebuild_tee=false + rebuild_bitacross=false push_docker=false run_parachain_test=false run_tee_test=false @@ -114,6 +117,9 @@ jobs: if [ "${{ github.event.inputs.rebuild-tee-docker }}" = "true" ] || [ "${{ steps.filter.outputs.tee_src }}" = "true" ]; then rebuild_tee=true fi + if [ "${{ github.event.inputs.rebuild-bitacross-docker }}" = "true" ] || [ "${{ steps.filter.outputs.bitacross_src }}" = "true" ]; then + rebuild_bitacross=true + fi if [ "${{ github.event.inputs.push-docker }}" = "true" ]; then push_docker=true elif [ "${{ github.event_name }}" = 'push' ] && [ "${{ github.ref }}" = 'refs/heads/dev' ]; then @@ -125,11 +131,16 @@ jobs: if [ "${{ steps.filter.outputs.tee_test }}" = "true" ] || [ "$rebuild_parachain" = "true" ] || [ "$rebuild_tee" = "true" ]; then run_tee_test=true fi + if [ "${{ steps.filter.outputs.bitacross_test }}" = "true" ] || [ "$rebuild_parachain" = "true" ] || [ "$rebuild_bitacross" = "true" ]; then + run_bitacross_test=true + fi echo "rebuild_parachain=$rebuild_parachain" | tee -a $GITHUB_OUTPUT echo "rebuild_tee=$rebuild_tee" | tee -a $GITHUB_OUTPUT + echo "rebuild_bitacross=$rebuild_bitacross" | tee -a $GITHUB_OUTPUT echo "push_docker=$push_docker" | tee -a $GITHUB_OUTPUT echo "run_parachain_test=$run_parachain_test" | tee -a $GITHUB_OUTPUT echo "run_tee_test=$run_tee_test" | tee -a $GITHUB_OUTPUT + echo "run_bitacross_test=$$run_tee_test" | tee -a $GITHUB_OUTPUT fmt: runs-on: ubuntu-latest @@ -159,11 +170,22 @@ jobs: cargo fmt --all -- --check taplo fmt --check - - name: Enclave-runtime fmt check + - name: Tee-worker enclave-runtime fmt check working-directory: ./tee-worker/enclave-runtime run: | cargo fmt --all -- --check + - name: bitacross-worker fmt check + working-directory: ./bitacross-worker + run: | + cargo fmt --all -- --check + taplo fmt --check + + - name: bitacross-worker enclave-runtime fmt check + working-directory: ./bitacross-worker/enclave-runtime + run: | + cargo fmt --all -- --check + - name: Enable corepack and pnpm run: corepack enable && corepack enable pnpm @@ -282,6 +304,66 @@ jobs: if: failure() uses: andymckay/cancel-action@0.3 + bitacross-clippy: + runs-on: ubuntu-latest + needs: + - fmt + - set-condition + - sequentialise + if: needs.set-condition.outputs.rebuild_bitacross == 'true' +# todo: we might want to change this image in the future + container: "litentry/litentry-tee-dev:latest" + steps: + - uses: actions/checkout@v4 + + - name: Install dependencies + run: | + sudo apt-get update && \ + sudo apt-get install -yq openssl clang libclang-dev cmake protobuf-compiler + + - name: bitacross-worker clippy + working-directory: ./bitacross-worker + run: | + echo "::group::cargo clippy all" + cargo clippy --release -- -D warnings + echo "::endgroup::" + echo "::group::cargo clippy sidechain" + cargo clippy --release --features sidechain -- -D warnings + echo "::endgroup::" + echo "::group::cargo clippy offchain-worker" + cargo clean --profile release + cargo clippy --release --features offchain-worker -- -D warnings + echo "::endgroup::" + + - name: Clean up disk + working-directory: ./bitacross-worker + run: | + echo "::group::Show disk usage" + df -h . + echo "::endgroup::" + cargo clean --profile release + echo "::group::Show disk usage" + df -h . + echo "::endgroup::" + + - name: bitacross-enclave clippy + working-directory: ./bitacross-worker/enclave-runtime + run: | + echo "::group::cargo clippy all" + cargo clippy --release -- -D warnings + echo "::endgroup::" + echo "::group::cargo clippy sidechain" + cargo clippy --release --features sidechain -- -D warnings + echo "::endgroup::" + echo "::group::cargo clippy offchain-worker" + cargo clean --profile release + cargo clippy --release --features offchain-worker -- -D warnings + echo "::endgroup::" + + - name: Fail early + if: failure() + uses: andymckay/cancel-action@0.3 + parachain-build-dev: runs-on: ubuntu-latest needs: @@ -378,7 +460,6 @@ jobs: echo "::group::Show disk usage" df -h . echo "::endgroup::" - # cache mount in buildkit won't be exported as image layers, so it doesn't work well with GHA cache, see # https://github.com/moby/buildkit/issues/1512 # https://www.reddit.com/r/rust/comments/126xeyx/exploring_the_problem_of_faster_cargo_docker/ @@ -468,7 +549,6 @@ jobs: name: litentry-tee path: litentry-tee.tar.gz if-no-files-found: error - - name: Fail early if: failure() uses: andymckay/cancel-action@0.3 diff --git a/Makefile b/Makefile index 2572c54712..2fa14b1e8a 100644 --- a/Makefile +++ b/Makefile @@ -195,6 +195,8 @@ fmt-cargo: @cargo fmt --all @cd tee-worker && cargo fmt --all @cd tee-worker/enclave-runtime && cargo fmt --all + @cd bitacross-worker && cargo fmt --all + @cd bitacross-worker/enclave-runtime && cargo fmt --all .PHONY: fmt-taplo ## taplo fmt fmt-taplo: diff --git a/bitacross-worker/.dockerignore b/bitacross-worker/.dockerignore new file mode 100644 index 0000000000..10a8164af1 --- /dev/null +++ b/bitacross-worker/.dockerignore @@ -0,0 +1,16 @@ +# Litentry note: this file is unused +# Please edit the ../.dockerignore directly +.git +.githooks +.github +.idea +ci/ +docker/*yml +docs/ +local-setup/ +scripts/ +target/ +enclave-runtime/target/ +tmp/ +*.Dockerfile +Dockerfile \ No newline at end of file diff --git a/bitacross-worker/.editorconfig b/bitacross-worker/.editorconfig new file mode 100644 index 0000000000..de2a30a350 --- /dev/null +++ b/bitacross-worker/.editorconfig @@ -0,0 +1,27 @@ +root = true + +[*] +indent_style = tab +indent_size = 4 +tab_width = 4 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +max_line_length = 100 +insert_final_newline = true + +[*.yml] +indent_style = space +indent_size = 4 +tab_width = 4 +end_of_line = lf + +[*.ts] +indent_style = space +indent_size = 4 +tab_width = 4 +end_of_line = lf + + +[*.toml] +indent_style = space \ No newline at end of file diff --git a/bitacross-worker/.env.dev b/bitacross-worker/.env.dev new file mode 100644 index 0000000000..6ffad948b4 --- /dev/null +++ b/bitacross-worker/.env.dev @@ -0,0 +1,14 @@ +AliceWSPort=9946 +AliceRPCPort=9936 +AlicePort=30336 +BobWSPort=9947 +BobRPCPort=9937 +BobPort=30337 +CollatorWSPort=9944 +CollatorRPCPort=9933 +CollatorPort=30333 +TrustedWorkerPort=2000 +UntrustedWorkerPort=2001 +MuRaPort=3443 +UntrustedHttpPort=4545 +NODE_ENV=local \ No newline at end of file diff --git a/bitacross-worker/.gitattributes.orig b/bitacross-worker/.gitattributes.orig new file mode 100644 index 0000000000..00c1715114 --- /dev/null +++ b/bitacross-worker/.gitattributes.orig @@ -0,0 +1,18 @@ +# TODO: why do we need binary mode for Cargo.lock? +# Cargo.lock linguist-generated=true -diff + +[attr]rust text eol=lf whitespace=tab-in-indent,trailing-space,tabwidth=4 + +* text=auto eol=lf +*.cpp rust +*.h rust +*.rs rust +*.fixed linguist-language=Rust +src/etc/installer/gfx/* binary +*.woff binary +src/vendor/** -text +Cargo.lock -merge linguist-generated=false + +# Older git versions try to fix line endings on images, this prevents it. +*.png binary +*.ico binary diff --git a/bitacross-worker/.githooks/pre-commit b/bitacross-worker/.githooks/pre-commit new file mode 100755 index 0000000000..399188a65d --- /dev/null +++ b/bitacross-worker/.githooks/pre-commit @@ -0,0 +1,17 @@ +#!/bin/bash + +# This pre-commit hook uses cargo fmt to check the code style +# Install it either with `make githooks` or copy the file to .git/hooks + +echo '+cargo fmt -- --check' +cargo fmt -- --check +result=$? + +if [[ ${result} -ne 0 ]] ; then + cat <<\EOF +There are some code style issues, run `cargo fmt` first. +EOF + exit 1 +fi + +exit 0 \ No newline at end of file diff --git a/bitacross-worker/.github/workflows/build_and_test.yml b/bitacross-worker/.github/workflows/build_and_test.yml new file mode 100644 index 0000000000..d007fe1eb4 --- /dev/null +++ b/bitacross-worker/.github/workflows/build_and_test.yml @@ -0,0 +1,599 @@ +name: Build, Test, Clippy + +on: + workflow_dispatch: + push: + branches: + - master + - 'sdk-v[0-9]+.[0-9]+.[0-9]+-*' + tags: + - 'v[0-9]+.[0-9]+.[0-9]+*' + pull_request: + branches: + - master + - 'sdk-v[0-9]+.[0-9]+.[0-9]+-*' + +env: + CARGO_TERM_COLOR: always + LOG_DIR: logs + BUILD_CONTAINER_NAME: integritee_worker_enclave_test + +jobs: + cancel_previous_runs: + name: Cancel Previous Runs + runs-on: ubuntu-latest + steps: + - uses: styfle/cancel-workflow-action@0.11.0 + with: + access_token: ${{ secrets.GITHUB_TOKEN }} + + build-test: + runs-on: ${{ matrix.host }} + strategy: + fail-fast: false + matrix: + include: + - flavor_id: sidechain + mode: sidechain + host: integritee-builder-sgx + sgx_mode: HW + additional_features: dcap + - flavor_id: offchain-worker + mode: offchain-worker + host: integritee-builder-sgx + sgx_mode: HW + additional_features: dcap + - flavor_id: teeracle + mode: teeracle + host: integritee-builder-sgx + sgx_mode: HW + additional_features: dcap + - flavor_id: sidechain-evm + mode: sidechain + additional_features: evm,dcap + host: integritee-builder-sgx + sgx_mode: HW + + steps: + - uses: actions/checkout@v3 + + - name: Set env + run: | + fingerprint=$RANDOM + echo "FINGERPRINT=$fingerprint" >> $GITHUB_ENV + SGX_MODE_LOWERCASE=$(echo "${${{ matrix.sgx_mode }},,}") + echo "IMAGE_SUFFIX=$SGX_MODE_LOWERCASE-${{ matrix.flavor_id }}-${{ github.sha }}" >> $GITHUB_ENV + if [[ ${{ matrix.sgx_mode }} == 'HW' ]]; then + echo "DOCKER_DEVICES=--device=/dev/sgx/enclave --device=/dev/sgx/provision" >> $GITHUB_ENV + echo "DOCKER_VOLUMES=--volume /var/run/aesmd:/var/run/aesmd --volume /etc/sgx_default_qcnl.conf:/etc/sgx_default_qcnl.conf" >> $GITHUB_ENV + else + echo "DOCKER_DEVICES=" >> $GITHUB_ENV + echo "DOCKER_VOLUMES=" >> $GITHUB_ENV + fi + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + with: + buildkitd-flags: --debug + driver: docker-container + + - name: Build Worker + env: + DOCKER_BUILDKIT: 1 + run: > + docker build -t integritee-worker-${{ env.IMAGE_SUFFIX }} + --target deployed-worker + --build-arg WORKER_MODE_ARG=${{ matrix.mode }} --build-arg FINGERPRINT=${FINGERPRINT} --build-arg ADDITIONAL_FEATURES_ARG=${{ matrix.additional_features }} --build-arg SGX_MODE=${{ matrix.sgx_mode }} + -f build.Dockerfile . + + - run: docker images --all + + - name: Test Enclave # cargo test is not supported in the enclave, see: https://github.com/apache/incubator-teaclave-sgx-sdk/issues/232 + run: docker run --rm ${{ env.DOCKER_DEVICES }} ${{ env.DOCKER_VOLUMES }} integritee-worker-${{ env.IMAGE_SUFFIX }} test --all + + - name: Export worker image + run: | + docker image save integritee-worker-${{ env.IMAGE_SUFFIX }} | gzip > integritee-worker-${{ env.IMAGE_SUFFIX }}.tar.gz + + - name: Upload worker image + uses: actions/upload-artifact@v3 + with: + name: integritee-worker-${{ env.IMAGE_SUFFIX }}.tar.gz + path: integritee-worker-${{ env.IMAGE_SUFFIX }}.tar.gz + + - name: Create Enclave Digest File + run: | + mrenclave_hex=$(docker run integritee-worker-${{ env.IMAGE_SUFFIX }} mrenclave | grep -oP ':\s*\K[a-fA-F0-9]+') + echo "$mrenclave_hex" > mrenclave-${{ env.IMAGE_SUFFIX }}.hex + + - name: Upload Enclave Digest File + uses: actions/upload-artifact@v3 + with: + name: mrenclave-${{ env.IMAGE_SUFFIX }}.hex + path: mrenclave-${{ env.IMAGE_SUFFIX }}.hex + + - name: Delete images + run: | + if [[ "$(docker images -q integritee-worker-${{ env.IMAGE_SUFFIX }} 2> /dev/null)" != "" ]]; then + docker image rmi --force integritee-worker-${{ env.IMAGE_SUFFIX }} 2>/dev/null + fi + docker images --all + + build-client: + runs-on: ${{ matrix.host }} + strategy: + fail-fast: false + matrix: + include: + - flavor_id: sidechain + mode: sidechain + host: integritee-builder-sgx + sgx_mode: HW + additional_features: dcap + - flavor_id: offchain-worker + mode: offchain-worker + host: integritee-builder-sgx + sgx_mode: HW + additional_features: dcap + - flavor_id: teeracle + mode: teeracle + host: integritee-builder-sgx + sgx_mode: HW + additional_features: dcap + - flavor_id: sidechain-evm + mode: sidechain + additional_features: evm,dcap + host: integritee-builder-sgx + sgx_mode: HW + + steps: + - uses: actions/checkout@v3 + + - name: Set env + run: | + fingerprint=$RANDOM + echo "FINGERPRINT=$fingerprint" >> $GITHUB_ENV + SGX_MODE_LOWERCASE=$(echo "${${{ matrix.sgx_mode }},,}") + echo "IMAGE_SUFFIX=$SGX_MODE_LOWERCASE-${{ matrix.flavor_id }}-${{ github.sha }}" >> $GITHUB_ENV + if [[ ${{ matrix.sgx_mode }} == 'HW' ]]; then + echo "DOCKER_DEVICES=--device=/dev/sgx/enclave --device=/dev/sgx/provision" >> $GITHUB_ENV + echo "DOCKER_VOLUMES=--volume /var/run/aesmd:/var/run/aesmd --volume /etc/sgx_default_qcnl.conf:/etc/sgx_default_qcnl.conf" >> $GITHUB_ENV + else + echo "DOCKER_DEVICES=" >> $GITHUB_ENV + echo "DOCKER_VOLUMES=" >> $GITHUB_ENV + fi + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + with: + buildkitd-flags: --debug + driver: docker-container + + - name: Build CLI client + env: + DOCKER_BUILDKIT: 1 + run: > + docker build -t integritee-cli-client-${{ env.IMAGE_SUFFIX }} + --target deployed-client + --build-arg WORKER_MODE_ARG=${{ matrix.mode }} --build-arg ADDITIONAL_FEATURES_ARG=${{ matrix.additional_features }} + -f build.Dockerfile . + + - run: docker images --all + + - name: Export client image + run: | + docker image save integritee-cli-client-${{ env.IMAGE_SUFFIX }} | gzip > integritee-cli-client-${{ env.IMAGE_SUFFIX }}.tar.gz + + - name: Upload CLI client image + uses: actions/upload-artifact@v3 + with: + name: integritee-cli-client-${{ env.IMAGE_SUFFIX }}.tar.gz + path: integritee-cli-client-${{ env.IMAGE_SUFFIX }}.tar.gz + + - name: Delete images + run: | + if [[ "$(docker images -q integritee-cli-client-${{ env.IMAGE_SUFFIX }} 2> /dev/null)" != "" ]]; then + docker image rmi --force integritee-cli-client-${{ env.IMAGE_SUFFIX }} 2>/dev/null + fi + docker images --all + + code-quality: + runs-on: ubuntu-latest + container: "integritee/integritee-dev:0.2.2" + strategy: + fail-fast: false + matrix: + check: [ + # Workspace + cargo test --release, + # Worker + # Use release mode as the CI runs out of disk space otherwise. + cargo clippy --release -- -D warnings, + cargo clippy --release --features evm -- -D warnings, + cargo clippy --release --features sidechain -- -D warnings, + cargo clippy --release --features teeracle -- -D warnings, + cargo clippy --release --features offchain-worker -- -D warnings, + + # Enclave + cd enclave-runtime && cargo clippy -- -D warnings, + cd enclave-runtime && cargo clippy --features evm -- -D warnings, + cd enclave-runtime && cargo clippy --features sidechain -- -D warnings, + cd enclave-runtime && cargo clippy --features teeracle -- -D warnings, + cd enclave-runtime && cargo clippy --features offchain-worker -- -D warnings, + + # Fmt + cargo fmt --all -- --check, + cd enclave-runtime && cargo fmt --all -- --check, + ] + steps: + - uses: actions/checkout@v3 + - name: init-rust-target + # Enclave is not in the same workspace + run: rustup show && cd enclave-runtime && rustup show + + - uses: Swatinem/rust-cache@v2 + with: + key: ${{ matrix.check }} + + - name: ${{ matrix.check }} + run: ${{ matrix.check }} + + toml-fmt: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: init rust + run: rustup show + + - name: Install taplo + run: cargo install taplo-cli --locked + - name: Cargo.toml fmt + run: taplo fmt --check + + - name: Fail-fast; cancel other jobs + if: failure() + uses: andymckay/cancel-action@0.3 + + integration-tests: + runs-on: ${{ matrix.host }} + if: ${{ always() }} + needs: [build-test, build-client] + env: + WORKER_IMAGE_TAG: integritee-worker:dev + CLIENT_IMAGE_TAG: integritee-cli:dev + COINMARKETCAP_KEY: ${{ secrets.COINMARKETCAP_KEY }} + # IAS_EPID_SPID: ${{ secrets.IAS_SPID }} + # IAS_EPID_KEY: ${{ secrets.IAS_PRIMARY_KEY }} + TEERACLE_INTERVAL_SECONDS: 10 + + strategy: + fail-fast: false + matrix: + include: + - test: M6 + flavor_id: sidechain + demo_name: demo-shielding-unshielding-multiworker + host: test-runner-sgx + sgx_mode: HW + - test: M8 + flavor_id: sidechain + demo_name: demo-direct-call + host: test-runner-sgx + sgx_mode: HW + - test: Sidechain + flavor_id: sidechain + demo_name: demo-sidechain + host: test-runner-sgx + sgx_mode: HW + - test: M6 + flavor_id: offchain-worker + demo_name: demo-shielding-unshielding-multiworker + host: test-runner-sgx + sgx_mode: HW + - test: Teeracle + flavor_id: teeracle + demo_name: demo-teeracle + host: test-runner-sgx + sgx_mode: HW + - test: Teeracle + flavor_id: teeracle + demo_name: demo-teeracle-generic + host: test-runner-sgx + sgx_mode: HW + - test: Benchmark + flavor_id: sidechain + demo_name: sidechain-benchmark + host: test-runner-sgx + sgx_mode: HW + - test: EVM + flavor_id: sidechain-evm + demo_name: demo-smart-contract + host: test-runner-sgx + sgx_mode: HW + + steps: + - uses: actions/checkout@v3 + + - name: Set env + run: | + version=$RANDOM + SGX_MODE_LOWERCASE=$(echo "${${{ matrix.sgx_mode }},,}") + echo "IMAGE_SUFFIX=$SGX_MODE_LOWERCASE-${{ matrix.flavor_id }}-${{ github.sha }}" >> $GITHUB_ENV + echo "FLAVOR_ID=${{ matrix.flavor_id }}" >> $GITHUB_ENV + echo "PROJECT=${{ matrix.flavor_id }}-${{ matrix.demo_name }}" >> $GITHUB_ENV + echo "VERSION=dev.$version" >> $GITHUB_ENV + echo "WORKER_IMAGE_TAG=integritee-worker:dev.$version" >> $GITHUB_ENV + echo "INTEGRITEE_NODE=integritee-node:1.1.3.$version" >> $GITHUB_ENV + echo "CLIENT_IMAGE_TAG=integritee-cli:dev.$version" >> $GITHUB_ENV + if [[ ${{ matrix.sgx_mode }} == 'HW' ]]; then + echo "SGX_PROVISION=/dev/sgx/provision" >> $GITHUB_ENV + echo "SGX_ENCLAVE=/dev/sgx/enclave" >> $GITHUB_ENV + echo "AESMD=/var/run/aesmd" >> $GITHUB_ENV + echo "SGX_QCNL=/etc/sgx_default_qcnl.conf" >> $GITHUB_ENV + fi + + echo "LOG_DIR=./logs-$version" >> $GITHUB_ENV + + - name: Download Worker Image + uses: actions/download-artifact@v3 + with: + name: integritee-worker-${{ env.IMAGE_SUFFIX }}.tar.gz + path: . + + - name: Download CLI client Image + uses: actions/download-artifact@v3 + with: + name: integritee-cli-client-${{ env.IMAGE_SUFFIX }}.tar.gz + path: . + + - name: Load Worker & Client Images + env: + DOCKER_BUILDKIT: 1 + run: | + docker image load --input integritee-worker-${{ env.IMAGE_SUFFIX }}.tar.gz + docker image load --input integritee-cli-client-${{ env.IMAGE_SUFFIX }}.tar.gz + docker images --all + + ## + # Before tagging, delete the old "stuck" ones to be sure that the newly created ones are the latest + # Without if the docker image rmi throws an error if the image doesn't exist. + ## + - name: Re-name Image Tags + run: | + if [[ "$(docker images -q ${{ env.WORKER_IMAGE_TAG }} 2> /dev/null)" == "" ]]; then + docker image rmi --force ${{ env.WORKER_IMAGE_TAG }} 2>/dev/null + fi + if [[ "$(docker images -q ${{ env.CLIENT_IMAGE_TAG }} 2> /dev/null)" == "" ]]; then + docker image rmi --force ${{ env.CLIENT_IMAGE_TAG }} 2>/dev/null + fi + docker tag integritee-worker-${{ env.IMAGE_SUFFIX }} ${{ env.WORKER_IMAGE_TAG }} + docker tag integritee-cli-client-${{ env.IMAGE_SUFFIX }} ${{ env.CLIENT_IMAGE_TAG }} + docker pull integritee/integritee-node:1.1.3 + docker tag integritee/integritee-node:1.1.3 ${{ env.INTEGRITEE_NODE }} + docker images --all + + ## + # Stop any stucked/running compose projects + ## + - name: Stop docker containers + if: always() + continue-on-error: true + run: | + cd docker + docker compose -f <(envsubst < docker-compose.yml) -f <(envsubst < ${{ matrix.demo_name }}.yml) -p ${PROJECT} stop + + - name: Integration Test ${{ matrix.test }}-${{ matrix.flavor_id }} + run: | + cd docker + docker compose -f <(envsubst < docker-compose.yml) -f <(envsubst < ${{ matrix.demo_name }}.yml) -p ${PROJECT} up ${{ matrix.demo_name }} --no-build --exit-code-from ${{ matrix.demo_name }} --remove-orphans + + + - name: Collect Docker Logs + continue-on-error: true + if: always() + uses: jwalton/gh-docker-logs@v2 + with: + images: '${{ env.WORKER_IMAGE_TAG }},${{ env.CLIENT_IMAGE_TAG }},${{ env.INTEGRITEE_NODE }}' + tail: all + dest: ${{ env.LOG_DIR }} + + - name: Upload logs + if: always() + uses: actions/upload-artifact@v3 + with: + name: logs-${{ matrix.test }}-${{ matrix.flavor_id }} + path: ${{ env.LOG_DIR }} + + - name: Stop docker containers + if: always() + continue-on-error: true + run: | + cd docker + docker compose -f <(envsubst < docker-compose.yml) -f <(envsubst < ${{ matrix.demo_name }}.yml) -p ${PROJECT} stop + + - name: Delete images + run: | + if [[ "$(docker images -q integritee-worker-${{ env.IMAGE_SUFFIX }} 2> /dev/null)" != "" ]]; then + docker image rmi --force integritee-worker-${{ env.IMAGE_SUFFIX }} 2>/dev/null + fi + if [[ "$(docker images -q integritee-cli-client-${{ env.IMAGE_SUFFIX }} 2> /dev/null)" != "" ]]; then + docker image rmi --force integritee-cli-client-${{ env.IMAGE_SUFFIX }} 2>/dev/null + fi + if [[ "$(docker images -q ${{ env.WORKER_IMAGE_TAG }} 2> /dev/null)" != "" ]]; then + docker image rmi --force ${{ env.WORKER_IMAGE_TAG }} 2>/dev/null + fi + if [[ "$(docker images -q ${{ env.CLIENT_IMAGE_TAG }} 2> /dev/null)" != "" ]]; then + docker image rmi --force ${{ env.CLIENT_IMAGE_TAG }} 2>/dev/null + fi + if [[ "$(docker images -q ${{ env.INTEGRITEE_NODE }} 2> /dev/null)" != "" ]]; then + docker image rmi --force ${{ env.INTEGRITEE_NODE }} 2>/dev/null + fi + docker images --all + + release-build: + runs-on: integritee-builder-sgx + name: Release Build of teeracle + if: startsWith(github.ref, 'refs/tags/') + needs: [ build-test, integration-tests ] + + strategy: + fail-fast: false + matrix: + include: + - flavor_id: teeracle + mode: teeracle + sgx_mode: HW + additional_features: dcap + - flavor_id: sidechain + mode: sidechain + sgx_mode: HW + additional_features: dcap + + steps: + - uses: actions/checkout@v3 + + - name: Add masks + run: | + echo "::add-mask::$VAULT_TOKEN" + echo "::add-mask::$PRIVKEY_B64" + echo "::add-mask::$PRIVKEY_PASS" + + - name: Set env + run: | + fingerprint=$RANDOM + echo "FINGERPRINT=$fingerprint" >> $GITHUB_ENV + SGX_MODE_LOWERCASE=$(echo "${${{ matrix.sgx_mode }},,}") + echo "IMAGE_SUFFIX=$SGX_MODE_LOWERCASE-${{ matrix.flavor_id }}-${{ github.sha }}" >> $GITHUB_ENV + if [[ ${{ matrix.sgx_mode }} == 'HW' ]]; then + echo "DOCKER_DEVICES=--device=/dev/sgx/enclave --device=/dev/sgx/provision" >> $GITHUB_ENV + echo "DOCKER_VOLUMES=--volume /var/run/aesmd:/var/run/aesmd --volume /etc/sgx_default_qcnl.conf:/etc/sgx_default_qcnl.conf" >> $GITHUB_ENV + else + echo "DOCKER_DEVICES=" >> $GITHUB_ENV + echo "DOCKER_VOLUMES=" >> $GITHUB_ENV + fi + echo "VAULT_TOKEN=$VAULT_TOKEN" >> "$GITHUB_ENV" + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + with: + buildkitd-flags: --debug + driver: docker-container + + - name: Import secrets + uses: hashicorp/vault-action@v2 + id: import-secrets + with: + url: ${{ secrets.VAULT_URL }} + tlsSkipVerify: false + token: ${{ env.VAULT_TOKEN }} + exportEnv: false + secrets: | + ${{ secrets.VAULT_PATH }} intel_sgx_pem_base64 | PRIVKEY_B64 ; + ${{ secrets.VAULT_PATH }} password | PRIVKEY_PASS + + - name: Get secrets + env: + PRIVKEY_B64: ${{ steps.import-secrets.outputs.PRIVKEY_B64 }} + PRIVKEY_PASS: ${{ steps.import-secrets.outputs.PRIVKEY_PASS }} + run: | + echo $PRIVKEY_B64 | base64 --ignore-garbage --decode > enclave-runtime/intel_sgx.pem + echo $PRIVKEY_PASS > enclave-runtime/passfile.txt + + - name: Build Worker & Run Cargo Test + env: + DOCKER_BUILDKIT: 1 + run: > + docker build -t integritee/${{ matrix.flavor_id }}:${{ github.ref_name }} + --target deployed-worker + --build-arg WORKER_MODE_ARG=${{ matrix.mode }} --build-arg SGX_COMMERCIAL_KEY=enclave-runtime/intel_sgx.pem --build-arg SGX_PASSFILE=enclave-runtime/passfile.txt --build-arg SGX_PRODUCTION=1 --build-arg ADDITIONAL_FEATURES_ARG=${{ matrix.additional_features }} --build-arg SGX_MODE=${{ matrix.sgx_mode }} + -f build.Dockerfile . + + - name: Save released teeracle + run: | + docker image save integritee/${{ matrix.flavor_id }}:${{ github.ref_name }} | gzip > integritee-worker-${{ matrix.flavor_id }}-${{ github.ref_name }}.tar.gz + docker images --all + + - name: Upload teeracle image + uses: actions/upload-artifact@v3 + with: + name: integritee-worker-${{ matrix.flavor_id }}-${{ github.ref_name }}.tar.gz + path: integritee-worker-${{ matrix.flavor_id }}-${{ github.ref_name }}.tar.gz + + - name: Delete images + run: | + if [[ "$(docker images -q integritee/${{ matrix.flavor_id }}:${{ github.ref_name }} 2> /dev/null)" != "" ]]; then + docker image rmi --force integritee/${{ matrix.flavor_id }}:${{ github.ref_name }} 2>/dev/null + fi + docker images --all + + release: + runs-on: ubuntu-latest + name: Draft Release + if: startsWith(github.ref, 'refs/tags/') + needs: [ build-test, integration-tests, release-build ] + outputs: + release_url: ${{ steps.create-release.outputs.html_url }} + asset_upload_url: ${{ steps.create-release.outputs.upload_url }} + steps: + - uses: actions/checkout@v3 + + - name: Download Worker Image + uses: actions/download-artifact@v3 + with: + name: integritee-worker-teeracle-${{ github.ref_name }}.tar.gz + path: . + + - name: Download Worker Image + uses: actions/download-artifact@v3 + with: + name: integritee-worker-sidechain-${{ github.ref_name }}.tar.gz + path: . + + # + # Temporary comment out until we decide what to release + # + # - name: Download Integritee Client + # uses: actions/download-artifact@v3 + # with: + # name: integritee-client-sidechain-${{ github.sha }} + # path: integritee-client-tmp + + # - name: Download Enclave Signed + # uses: actions/download-artifact@v3 + # with: + # name: enclave-signed-sidechain-${{ github.sha }} + # path: enclave-signed-tmp + + # - name: Move service binaries + # run: mv integritee-worker-tmp/integritee-service ./integritee-demo-validateer + + # - name: Move service client binaries + # run: mv integritee-client-tmp/integritee-cli ./integritee-client + + # - name: Move service client binaries + # run: mv enclave-signed-tmp/enclave.signed.so ./enclave.signed.so + + - name: Changelog + uses: scottbrenner/generate-changelog-action@master + id: Changelog + + - name: Display structure of downloaded files + run: ls -R + working-directory: . + + - name: Release + id: create-release + uses: softprops/action-gh-release@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + body: | + ${{ steps.Changelog.outputs.changelog }} + draft: true + name: Docker ${{ github.ref_name }} + files: | + integritee-worker-teeracle-${{ github.ref_name }}.tar.gz + integritee-worker-sidechain-${{ github.ref_name }}.tar.gz + integritee-client + integritee-demo-validateer + enclave.signed.so diff --git a/bitacross-worker/.github/workflows/check_labels.yml b/bitacross-worker/.github/workflows/check_labels.yml new file mode 100644 index 0000000000..9511ed0b93 --- /dev/null +++ b/bitacross-worker/.github/workflows/check_labels.yml @@ -0,0 +1,24 @@ +name: Labels Check +on: + pull_request: + types: [opened, labeled, unlabeled, synchronize, ready_for_review] +jobs: + A-label-check: + uses: ./.github/workflows/label-checker.yml + with: + predefined_labels: "A0-core,A1-cli,A2-applibs,A3-sidechain,A4-offchain,A5-teeracle,A6-evm,A7-somethingelse" + + B-label-check: + uses: ./.github/workflows/label-checker.yml + with: + predefined_labels: "B0-silent,B1-releasenotes" + + C-label-check: + uses: ./.github/workflows/label-checker.yml + with: + predefined_labels: "C1-low 📌,C3-medium 📣,C7-high ❗️,C9-critical ‼️" + + E-label-check: + uses: ./.github/workflows/label-checker.yml + with: + predefined_labels: "E0-breaksnothing,E3-hardmerge,E5-publicapi,E6-parentchain,E8-breakseverything" diff --git a/bitacross-worker/.github/workflows/delete-release.yml b/bitacross-worker/.github/workflows/delete-release.yml new file mode 100644 index 0000000000..53fbdbb0f3 --- /dev/null +++ b/bitacross-worker/.github/workflows/delete-release.yml @@ -0,0 +1,70 @@ +name: Delete-Release + +on: + release: + types: [deleted] # should be deleted + +jobs: + purge-image: + name: Delete image from ghcr.io + runs-on: ubuntu-latest + strategy: + matrix: + #binary: ["integritee-client", "integritee-demo-validateer"] + binary: ["teeracle"] + steps: + - uses: actions/checkout@v2 + + - name: Set output + id: vars + run: echo "{tag}={$GITHUB_REF#refs/*/}" >> $GITHUB_OUTPUT + + - name: Get Tag + id: get_tag + run: echo ::set-output name=TAG::${GITHUB_REF/refs\/tags\//} + + - name: Check output + env: + RELEASE_VERSION: ${{ steps.get_tag.outputs.TAG }} + run: | + echo $RELEASE_VERSION + echo ${{ steps.vars.outputs.tag }} + echo ${{github.event.pull_request.number}} + + - name: Login to DockerHub + if: github.event_name != 'pull_request' + uses: docker/login-action@v1 + with: + username: ${{ secrets.DOCKER_HUB_USERNAME }} + password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }} + + # Unfortunately accessing the repo with personal access token is not possible + # Workaround: disable 2FA and user password instead of TOKEN + - name: Delete docker tag + run: | + ORGANIZATION="integritee" + IMAGE="${{ matrix.binary }}" + TAG="${{ steps.get_tag.outputs.TAG }}" + + login_data() { + cat < /dev/null)" != "" ]]; then + docker image rmi --force integritee/sidechain:${{ github.event.release.tag_name }} 2>/dev/null + fi + docker images --all diff --git a/bitacross-worker/.github/workflows/publish-docker-teeracle.yml b/bitacross-worker/.github/workflows/publish-docker-teeracle.yml new file mode 100644 index 0000000000..01a9a6f8b0 --- /dev/null +++ b/bitacross-worker/.github/workflows/publish-docker-teeracle.yml @@ -0,0 +1,43 @@ +name: Publish Docker image for new teeracle release + +on: + release: + types: + - published + +jobs: + main: + name: Push Integritee Teeracle to Dockerhub + runs-on: [ self-hosted ] + steps: + - uses: actions/checkout@v3 + + - name: Download teeracle from release + uses: dsaltares/fetch-gh-release-asset@master + with: + version: "tags/${{ github.event.release.tag_name }}" + file: integritee-worker-teeracle-${{ github.event.release.tag_name }}.tar.gz + target: "integritee-worker-teeracle.tar.gz" + token: ${{ secrets.GITHUB_TOKEN }} + + + - name: Login to Dockerhub + uses: docker/login-action@v1 + with: + username: ${{ secrets.DOCKER_HUB_USERNAME }} + password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }} + + - name: Load Worker & Push + env: + DOCKER_BUILDKIT: 1 + run: | + docker image load --input integritee-worker-teeracle.tar.gz + docker images --all + docker push integritee/teeracle:${{ github.event.release.tag_name }} + + - name: Delete images + run: | + if [[ "$(docker images -q integritee/teeracle:${{ github.event.release.tag_name }} 2> /dev/null)" != "" ]]; then + docker image rmi --force integritee/teeracle:${{ github.event.release.tag_name }} 2>/dev/null + fi + docker images --all diff --git a/bitacross-worker/.github/workflows/publish-draft-release.yml b/bitacross-worker/.github/workflows/publish-draft-release.yml new file mode 100644 index 0000000000..0e8c72dd6c --- /dev/null +++ b/bitacross-worker/.github/workflows/publish-draft-release.yml @@ -0,0 +1,69 @@ +name: Release - Publish draft + +on: + push: + tags: + # Catches only v1.2.3 (-dev,-rc1 etc won't be released as SDK) + - v[0-9]+.[0-9]+.[0-9]+ + +jobs: + publish-draft-release: + runs-on: ubuntu-latest + steps: + - name: Checkout sources + uses: actions/checkout@v3 + with: + fetch-depth: 0 + path: worker + + - name: Set up Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: 3.0.0 + + - name: Download srtool json output + uses: actions/download-artifact@v3 + + - name: Prepare tooling + run: | + cd worker/scripts/changelog + gem install bundler changelogerator:0.9.1 + bundle install + changelogerator --help + URL=https://github.com/chevdor/tera-cli/releases/download/v0.2.1/tera-cli_linux_amd64.deb + wget $URL -O tera.deb + sudo dpkg -i tera.deb + tera --version + + - name: Generate release notes + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + DEBUG: 1 + PRE_RELEASE: ${{ github.event.inputs.pre_release }} + run: | + find ${{env.GITHUB_WORKSPACE}} -type f -name "*_srtool_output.json" + + cd worker/scripts/changelog + + ./bin/changelog ${GITHUB_REF} + ls -al release-notes.md + ls -al context.json + + - name: Archive artifact context.json + uses: actions/upload-artifact@v3 + with: + name: release-notes-context + path: | + worker/scripts/changelog/context.json + **/*_srtool_output.json + + - name: Create draft release + id: create-release + uses: actions/create-release@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + tag_name: ${{ github.ref }} + release_name: SDK ${{ github.ref }} + body_path: ./worker/scripts/changelog/release-notes.md + draft: true diff --git a/bitacross-worker/.gitignore b/bitacross-worker/.gitignore new file mode 100644 index 0000000000..a14498c6eb --- /dev/null +++ b/bitacross-worker/.gitignore @@ -0,0 +1,78 @@ +# Generated by Cargo +# will have compiled files and executables +**/target/ + +**/__pycache__/ +/log/* +log* +**/tmp/* + +**/node_modules/* + +# These are backup files generated by rustfmt +**/*.rs.bk + +# binaries +bin/*.so +bin/bitacross-* +bin/*.wasm + +# sealed data +bin/*.bin + +# public RSA key +bin/rsa_pubkey.txt +bin/ecc_pubkey.txt + +# VS Code settings +.vscode + +#intelliJ +.idea/ +*.iml + +*.log + +# vim +*.swp + +# keystores +my_keystore/* +my_trusted_keystore/* + +# generated enclave files +service/Enclave_u.* +service/libEnclave_u.* +enclave-runtime/Enclave_t.* +enclave-runtime/enclave.so +lib/libEnclave_u.* +lib/libcompiler-rt-patch.a +lib/libenclave.a + +# certificate, key, spid and generated report for remote attestation +bin/client.crt +bin/client.key +bin/spid.txt +bin/spid_production.txt +bin/key.txt +bin/key_production.txt +bin/attestation_report.json +bin/shards +bin/*.der +bin/enclave-shielding-pubkey.json +bin/sidechain_db +bin/my_trusted_keystore + +# client +cli/my_keystore +cli/my_trusted_keystore +bin/light_client_db.bin.1 + +# generated upstream patch +upstream.patch + +# backup log files +log-backup + +# env files and configs +.env diff --git a/bitacross-worker/.taplo.toml b/bitacross-worker/.taplo.toml new file mode 100644 index 0000000000..a1de67fb52 --- /dev/null +++ b/bitacross-worker/.taplo.toml @@ -0,0 +1,21 @@ +include = ["**/Cargo.toml"] + +[formatting] +array_auto_expand = false +array_auto_collapse = false +indent_string = " " +inline_table_expand = false + +[[rule]] +include = ["**/Cargo.toml"] +keys = ["dependencies", "target", "patch"] + +[rule.formatting] +reorder_keys = true + +[[rule]] +include = ["**/Cargo.toml"] +keys = ["features"] + +[rule.formatting] +array_auto_expand = true \ No newline at end of file diff --git a/bitacross-worker/Cargo.lock b/bitacross-worker/Cargo.lock new file mode 100644 index 0000000000..9e85f8180c --- /dev/null +++ b/bitacross-worker/Cargo.lock @@ -0,0 +1,16436 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "Inflector" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3" +dependencies = [ + "lazy_static", + "regex 1.9.5", +] + +[[package]] +name = "ac-compose-macros" +version = "0.4.2" +source = "git+https://github.com/scs/substrate-api-client.git?branch=polkadot-v0.9.42-tag-v0.14.0#e4ed74b0fb6c2fd5585f55c2702b97b56d99c7f6" +dependencies = [ + "ac-primitives", + "log 0.4.20", + "maybe-async", +] + +[[package]] +name = "ac-node-api" +version = "0.5.1" +source = "git+https://github.com/scs/substrate-api-client.git?branch=polkadot-v0.9.42-tag-v0.14.0#e4ed74b0fb6c2fd5585f55c2702b97b56d99c7f6" +dependencies = [ + "ac-primitives", + "bitvec", + "derive_more", + "either", + "frame-metadata", + "hex", + "log 0.4.20", + "parity-scale-codec", + "scale-bits 0.4.0", + "scale-decode 0.8.0", + "scale-encode", + "scale-info", + "serde 1.0.193", + "serde_json 1.0.103", + "sp-application-crypto", + "sp-core", + "sp-runtime", + "sp-runtime-interface", +] + +[[package]] +name = "ac-primitives" +version = "0.9.0" +source = "git+https://github.com/scs/substrate-api-client.git?branch=polkadot-v0.9.42-tag-v0.14.0#e4ed74b0fb6c2fd5585f55c2702b97b56d99c7f6" +dependencies = [ + "frame-system", + "impl-serde", + "pallet-assets", + "pallet-balances", + "parity-scale-codec", + "primitive-types", + "scale-info", + "serde 1.0.193", + "serde_json 1.0.103", + "sp-application-crypto", + "sp-core", + "sp-core-hashing 5.0.0", + "sp-runtime", + "sp-runtime-interface", + "sp-staking", + "sp-version", + "sp-weights", +] + +[[package]] +name = "addr2line" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b" +dependencies = [ + "gimli 0.26.2", +] + +[[package]] +name = "addr2line" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4fa78e18c64fce05e902adecd7a5eed15a5e0a3439f7b0e169f0252214865e3" +dependencies = [ + "gimli 0.27.3", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "aead" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fc95d1bdb8e6666b2b217308eeeb09f2d6728d104be3e31916cc74d15420331" +dependencies = [ + "generic-array 0.14.7", +] + +[[package]] +name = "aead" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b613b8e1e3cf911a086f53f03bf286f52fd7a7258e4fa606f0ef220d39d8877" +dependencies = [ + "generic-array 0.14.7", + "rand_core 0.6.4", +] + +[[package]] +name = "aead" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" +dependencies = [ + "crypto-common", + "generic-array 0.14.7", +] + +[[package]] +name = "aes" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "884391ef1066acaa41e766ba8f596341b96e93ce34f9a43e7d24bf0a0eaf0561" +dependencies = [ + "aes-soft", + "aesni", + "cipher 0.2.5", +] + +[[package]] +name = "aes" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8" +dependencies = [ + "cfg-if 1.0.0", + "cipher 0.3.0", + "cpufeatures", + "opaque-debug 0.3.0", +] + +[[package]] +name = "aes" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac1f845298e95f983ff1944b728ae08b8cebab80d684f0a832ed0fc74dfa27e2" +dependencies = [ + "cfg-if 1.0.0", + "cipher 0.4.4", + "cpufeatures", +] + +[[package]] +name = "aes-gcm" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df5f85a83a7d8b0442b6aa7b504b8212c1733da07b98aae43d4bc21b2cb3cdf6" +dependencies = [ + "aead 0.4.3", + "aes 0.7.5", + "cipher 0.3.0", + "ctr 0.8.0", + "ghash 0.4.4", + "subtle", +] + +[[package]] +name = "aes-gcm" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "209b47e8954a928e1d72e86eca7000ebb6655fe1436d33eefc2201cad027e237" +dependencies = [ + "aead 0.5.2", + "aes 0.8.3", + "cipher 0.4.4", + "ctr 0.9.2", + "ghash 0.5.0", + "subtle", +] + +[[package]] +name = "aes-soft" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be14c7498ea50828a38d0e24a765ed2effe92a705885b57d029cd67d45744072" +dependencies = [ + "cipher 0.2.5", + "opaque-debug 0.3.0", +] + +[[package]] +name = "aesni" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea2e11f5e94c2f7d386164cc2aa1f97823fed6f259e486940a71c174dd01b0ce" +dependencies = [ + "cipher 0.2.5", + "opaque-debug 0.3.0", +] + +[[package]] +name = "ahash" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" +dependencies = [ + "getrandom 0.2.10", + "once_cell 1.18.0", + "version_check", +] + +[[package]] +name = "ahash" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" +dependencies = [ + "cfg-if 1.0.0", + "getrandom 0.2.10", + "once_cell 1.18.0", + "version_check", +] + +[[package]] +name = "aho-corasick" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43f6cb1bf222025340178f382c426f13757b2960e89779dfcb319c32542a5a41" +dependencies = [ + "memchr 2.6.3", +] + +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "ansi_term" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" +dependencies = [ + "winapi 0.3.9", +] + +[[package]] +name = "anyhow" +version = "1.0.72" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b13c32d80ecc7ab747b80c3784bce54ee8a7a0cc4fbda9bf4cda2cf6fe90854" + +[[package]] +name = "approx" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6" +dependencies = [ + "num-traits 0.2.16", +] + +[[package]] +name = "arc-swap" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bddcadddf5e9015d310179a59bb28c4d4b9920ad0f11e8e14dbadf654890c9a6" + +[[package]] +name = "array-bytes" +version = "4.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f52f63c5c1316a16a4b35eaac8b76a98248961a533f061684cb2a7cb0eafb6c6" + +[[package]] +name = "array-bytes" +version = "6.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b1c5a481ec30a5abd8dfbd94ab5cf1bb4e9a66be7f1b3b322f2f1170c200fd" + +[[package]] +name = "arrayref" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" + +[[package]] +name = "arrayvec" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd9fd44efafa8690358b7408d253adf110036b88f55672a933f01d616ad9b1b9" +dependencies = [ + "nodrop", +] + +[[package]] +name = "arrayvec" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" + +[[package]] +name = "arrayvec" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" + +[[package]] +name = "asn1-rs" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30ff05a702273012438132f449575dbc804e27b2f3cbe3069aa237d26c98fa33" +dependencies = [ + "asn1-rs-derive 0.1.0", + "asn1-rs-impl", + "displaydoc", + "nom", + "num-traits 0.2.16", + "rusticata-macros", + "thiserror 1.0.44", + "time 0.3.22", +] + +[[package]] +name = "asn1-rs" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f6fd5ddaf0351dff5b8da21b2fb4ff8e08ddd02857f0bf69c47639106c0fff0" +dependencies = [ + "asn1-rs-derive 0.4.0", + "asn1-rs-impl", + "displaydoc", + "nom", + "num-traits 0.2.16", + "rusticata-macros", + "thiserror 1.0.44", + "time 0.3.22", +] + +[[package]] +name = "asn1-rs-derive" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db8b7511298d5b7784b40b092d9e9dcd3a627a5707e4b5e507931ab0d44eeebf" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", + "synstructure", +] + +[[package]] +name = "asn1-rs-derive" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "726535892e8eae7e70657b4c8ea93d26b8553afb1ce617caee529ef96d7dee6c" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", + "synstructure", +] + +[[package]] +name = "asn1-rs-impl" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2777730b2039ac0f95f093556e61b6d26cebed5393ca6f152717777cec3a42ed" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "asn1_der" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "155a5a185e42c6b77ac7b88a15143d930a9e9727a5b7b77eed417404ab15c247" + +[[package]] +name = "assert_matches" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b34d609dfbaf33d6889b2b7106d3ca345eacad44200913df5ba02bfd31d2ba9" + +[[package]] +name = "async-channel" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35" +dependencies = [ + "concurrent-queue", + "event-listener", + "futures-core 0.3.28", +] + +[[package]] +name = "async-io" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af" +dependencies = [ + "async-lock", + "autocfg 1.1.0", + "cfg-if 1.0.0", + "concurrent-queue", + "futures-lite", + "log 0.4.20", + "parking", + "polling", + "rustix 0.37.23", + "slab 0.4.8", + "socket2 0.4.9", + "waker-fn", +] + +[[package]] +name = "async-lock" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa24f727524730b077666307f2734b4a1a1c57acb79193127dcc8914d5242dd7" +dependencies = [ + "event-listener", +] + +[[package]] +name = "async-trait" +version = "0.1.72" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc6dde6e4ed435a4c1ee4e73592f5ba9da2151af10076cc04858746af9352d09" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.32", +] + +[[package]] +name = "asynchronous-codec" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06a0daa378f5fd10634e44b0a29b2a87b890657658e072a30d6f26e57ddee182" +dependencies = [ + "bytes 1.4.0", + "futures-sink 0.3.28", + "futures-util 0.3.28", + "memchr 2.6.3", + "pin-project-lite 0.2.10", +] + +[[package]] +name = "atomic-waker" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1181e1e0d1fce796a03db1ae795d67167da795f9cf4a39c37589e85ef57f26d3" + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi 0.1.19", + "libc", + "winapi 0.3.9", +] + +[[package]] +name = "auto_impl" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fee3da8ef1276b0bee5dd1c7258010d8fffd31801447323115a25560e1327b89" +dependencies = [ + "proc-macro-error", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "autocfg" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dde43e75fd43e8a1bf86103336bc699aa8d17ad1be60c76c0bdfd4828e19b78" +dependencies = [ + "autocfg 1.1.0", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "backtrace" +version = "0.3.68" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4319208da049c43661739c5fade2ba182f09d1dc2299b32298d3a31692b17e12" +dependencies = [ + "addr2line 0.20.0", + "cc", + "cfg-if 1.0.0", + "libc", + "miniz_oxide", + "object 0.31.1", + "rustc-demangle", +] + +[[package]] +name = "base-x" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cbbc9d0964165b47557570cce6c952866c2678457aca742aafc9fb771d30270" + +[[package]] +name = "base16ct" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349a06037c7bf932dd7e7d1f653678b2038b9ad46a74102f1fc7bd7872678cce" + +[[package]] +name = "base16ct" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" + +[[package]] +name = "base58" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6107fe1be6682a68940da878d9e9f5e90ca5745b3dec9fd1bb393c8777d4f581" + +[[package]] +name = "base64" +version = "0.13.0" +source = "git+https://github.com/mesalock-linux/rust-base64-sgx?tag=sgx_1.1.3#dc7389e10817b078f289386b3b6a852ab6c4c021" +dependencies = [ + "sgx_tstd", +] + +[[package]] +name = "base64" +version = "0.13.0" +source = "git+https://github.com/mesalock-linux/rust-base64-sgx?rev=sgx_1.1.3#dc7389e10817b078f289386b3b6a852ab6c4c021" +dependencies = [ + "sgx_tstd", +] + +[[package]] +name = "base64" +version = "0.13.0" +source = "git+https://github.com/mesalock-linux/rust-base64-sgx#dc7389e10817b078f289386b3b6a852ab6c4c021" +dependencies = [ + "sgx_tstd", +] + +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + +[[package]] +name = "base64" +version = "0.21.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d" + +[[package]] +name = "base64ct" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" + +[[package]] +name = "bech32" +version = "0.10.0-beta" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98f7eed2b2781a6f0b5c903471d48e15f56fb4e1165df8a9a2337fd1a59d45ea" + +[[package]] +name = "beef" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a8241f3ebb85c056b509d4327ad0358fbbba6ffb340bf388f26350aeda225b1" +dependencies = [ + "serde 1.0.193", +] + +[[package]] +name = "binary-merkle-tree" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "hash-db 0.16.0", + "log 0.4.20", +] + +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde 1.0.193", +] + +[[package]] +name = "bindgen" +version = "0.64.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4243e6031260db77ede97ad86c27e501d646a27ab57b59a574f725d98ab1fb4" +dependencies = [ + "bitflags 1.3.2", + "cexpr", + "clang-sys", + "lazy_static", + "lazycell", + "peeking_take_while", + "proc-macro2", + "quote", + "regex 1.9.5", + "rustc-hash", + "shlex", + "syn 1.0.109", +] + +[[package]] +name = "bit-vec" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" + +[[package]] +name = "bitacross-cli" +version = "0.0.1" +dependencies = [ + "array-bytes 6.1.0", + "base58", + "chrono 0.4.26", + "clap 4.1.0", + "env_logger 0.9.3", + "frame-metadata", + "hdrhistogram", + "hex", + "ita-sgx-runtime", + "ita-stf", + "itc-rpc-client", + "itp-node-api", + "itp-rpc", + "itp-sgx-crypto", + "itp-stf-primitives", + "itp-time-utils", + "itp-types", + "itp-utils", + "litentry-primitives", + "log 0.4.20", + "pallet-balances", + "pallet-evm 6.0.0-dev (git+https://github.com/integritee-network/frontier.git?branch=bar/polkadot-v0.9.42)", + "pallet-teerex", + "parity-scale-codec", + "rand 0.8.5", + "rayon", + "regex 1.9.5", + "reqwest", + "rococo-parachain-runtime", + "scale-value", + "serde 1.0.193", + "serde_json 1.0.103", + "sgx_crypto_helper", + "sp-application-crypto", + "sp-core", + "sp-core-hashing 6.0.0", + "sp-keyring", + "sp-keystore", + "sp-runtime", + "substrate-api-client", + "substrate-client-keystore", + "thiserror 1.0.44", + "urlencoding", +] + +[[package]] +name = "bitacross-worker" +version = "0.0.1" +dependencies = [ + "anyhow", + "async-trait", + "base58", + "clap 2.34.0", + "config", + "dirs", + "env_logger 0.9.3", + "frame-support", + "futures 0.3.28", + "hex", + "ipfs-api", + "ita-stf", + "itc-parentchain", + "itc-parentchain-test", + "itc-rest-client", + "itc-rpc-client", + "itc-rpc-server", + "itp-api-client-types", + "itp-enclave-api", + "itp-enclave-metrics", + "itp-node-api", + "itp-settings", + "itp-storage", + "itp-types", + "itp-utils", + "its-consensus-slots", + "its-peer-fetch", + "its-primitives", + "its-rpc-handler", + "its-storage", + "its-test", + "jsonrpsee 0.2.0", + "lazy_static", + "litentry-primitives", + "log 0.4.20", + "mockall", + "pallet-balances", + "parity-scale-codec", + "parking_lot 0.12.1", + "parse_duration", + "primitive-types", + "prometheus", + "regex 1.9.5", + "rococo-parachain-runtime", + "scale-info", + "serde 1.0.193", + "serde_derive 1.0.193", + "serde_json 1.0.103", + "sgx-verify", + "sgx_crypto_helper", + "sgx_types", + "sp-consensus-grandpa", + "sp-core", + "sp-keyring", + "sp-runtime", + "substrate-api-client", + "teerex-primitives", + "thiserror 1.0.44", + "tokio", + "warp", +] + +[[package]] +name = "bitcoin" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5973a027b341b462105675962214dfe3c938ad9afd395d84b28602608bdcec7b" +dependencies = [ + "bech32", + "bitcoin-internals", + "bitcoin_hashes", + "core2 0.3.3", + "hex-conservative", + "hex_lit", + "secp256k1 0.28.0", +] + +[[package]] +name = "bitcoin-internals" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9425c3bf7089c983facbae04de54513cce73b41c7f9ff8c845b54e7bc64ebbfb" + +[[package]] +name = "bitcoin_hashes" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1930a4dabfebb8d7d9992db18ebe3ae2876f0a305fab206fd168df931ede293b" +dependencies = [ + "bitcoin-internals", + "core2 0.3.3", + "hex-conservative", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42" + +[[package]] +name = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + +[[package]] +name = "blake2" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" +dependencies = [ + "digest 0.10.7", +] + +[[package]] +name = "blake2-rfc" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d6d530bdd2d52966a6d03b7a964add7ae1a288d25214066fd4b600f0f796400" +dependencies = [ + "arrayvec 0.4.12", + "constant_time_eq 0.1.5", +] + +[[package]] +name = "blake2b_simd" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c2f0dc9a68c6317d884f97cc36cf5a3d20ba14ce404227df55e1af708ab04bc" +dependencies = [ + "arrayref", + "arrayvec 0.7.4", + "constant_time_eq 0.2.6", +] + +[[package]] +name = "blake2s_simd" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6637f448b9e61dfadbdcbae9a885fadee1f3eaffb1f8d3c1965d3ade8bdfd44f" +dependencies = [ + "arrayref", + "arrayvec 0.7.4", + "constant_time_eq 0.2.6", +] + +[[package]] +name = "blake3" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "729b71f35bd3fa1a4c86b85d32c8b9069ea7fe14f7a53cfabb65f62d4265b888" +dependencies = [ + "arrayref", + "arrayvec 0.7.4", + "cc", + "cfg-if 1.0.0", + "constant_time_eq 0.2.6", + "digest 0.10.7", +] + +[[package]] +name = "block-buffer" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" +dependencies = [ + "block-padding 0.1.5", + "byte-tools", + "byteorder 1.4.3", + "generic-array 0.12.4", +] + +[[package]] +name = "block-buffer" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" +dependencies = [ + "generic-array 0.14.7", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array 0.14.7", +] + +[[package]] +name = "block-modes" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57a0e8073e8baa88212fb5823574c02ebccb395136ba9a164ab89379ec6072f0" +dependencies = [ + "block-padding 0.2.1", + "cipher 0.2.5", +] + +[[package]] +name = "block-padding" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" +dependencies = [ + "byte-tools", +] + +[[package]] +name = "block-padding" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" + +[[package]] +name = "bounded-collections" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb5b05133427c07c4776906f673ccf36c21b102c9829c641a5b56bd151d44fd6" +dependencies = [ + "log 0.4.20", + "parity-scale-codec", + "scale-info", + "serde 1.0.193", +] + +[[package]] +name = "bounded-vec" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68534a48cbf63a4b1323c433cf21238c9ec23711e0df13b08c33e5c2082663ce" +dependencies = [ + "thiserror 1.0.44", +] + +[[package]] +name = "bs58" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3" + +[[package]] +name = "bstr" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6798148dccfbff0fae41c7574d2fa8f1ef3492fba0face179de5d8d447d67b05" +dependencies = [ + "memchr 2.6.3", + "serde 1.0.193", +] + +[[package]] +name = "build-helper" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdce191bf3fa4995ce948c8c83b4640a1745457a149e73c6db75b4ffe36aad5f" +dependencies = [ + "semver 0.6.0", +] + +[[package]] +name = "bumpalo" +version = "3.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" + +[[package]] +name = "byte-slice-cast" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" + +[[package]] +name = "byte-tools" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" + +[[package]] +name = "bytemuck" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17febce684fd15d89027105661fec94afb475cb995fbc59d2865198446ba2eea" + +[[package]] +name = "byteorder" +version = "1.3.4" +source = "git+https://github.com/mesalock-linux/byteorder-sgx?tag=sgx_1.1.3#325f392dcd294109eb05f0a3c45e4141514c7784" +dependencies = [ + "sgx_tstd", +] + +[[package]] +name = "byteorder" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" + +[[package]] +name = "bytes" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" +dependencies = [ + "byteorder 1.4.3", + "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "bytes" +version = "1.0.1" +source = "git+https://github.com/integritee-network/bytes-sgx?branch=sgx-experimental#62ed3082be2e23cb9bc8cc7ee9983a523de69292" +dependencies = [ + "sgx_tstd", +] + +[[package]] +name = "bytes" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" + +[[package]] +name = "bzip2-sys" +version = "0.1.11+1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "736a955f3fa7875102d57c82b8cac37ec45224a07fd32d58f9f7a186b6cd4cdc" +dependencies = [ + "cc", + "libc", + "pkg-config", +] + +[[package]] +name = "camino" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c530edf18f37068ac2d977409ed5cd50d53d73bc653c7647b48eb78976ac9ae2" +dependencies = [ + "serde 1.0.193", +] + +[[package]] +name = "cargo-platform" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbdb825da8a5df079a43676dbe042702f1707b1109f713a01420fbb4cc71fa27" +dependencies = [ + "serde 1.0.193", +] + +[[package]] +name = "cargo_metadata" +version = "0.15.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eee4243f1f26fc7a42710e7439c149e2b10b05472f88090acce52632f231a73a" +dependencies = [ + "camino", + "cargo-platform", + "semver 1.0.18", + "serde 1.0.193", + "serde_json 1.0.103", + "thiserror 1.0.44", +] + +[[package]] +name = "cargo_toml" +version = "0.16.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3f9629bc6c4388ea699781dc988c2b99766d7679b151c81990b4fa1208fafd3" +dependencies = [ + "serde 1.0.193", + "toml 0.8.2", +] + +[[package]] +name = "cc" +version = "1.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" +dependencies = [ + "jobserver", +] + +[[package]] +name = "ccm" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aca1a8fbc20b50ac9673ff014abfb2b5f4085ee1a850d408f14a159c5853ac7" +dependencies = [ + "aead 0.3.2", + "cipher 0.2.5", + "subtle", +] + +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom", +] + +[[package]] +name = "cfg-expr" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0aacacf4d96c24b2ad6eb8ee6df040e4f27b0d0b39a5710c30091baa830485db" +dependencies = [ + "smallvec 1.11.0", +] + +[[package]] +name = "cfg-if" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "cfg_aliases" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" + +[[package]] +name = "chacha20" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c80e5460aa66fe3b91d40bcbdab953a597b60053e34d684ac6903f863b680a6" +dependencies = [ + "cfg-if 1.0.0", + "cipher 0.3.0", + "cpufeatures", + "zeroize", +] + +[[package]] +name = "chacha20poly1305" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a18446b09be63d457bbec447509e85f662f32952b035ce892290396bc0b0cff5" +dependencies = [ + "aead 0.4.3", + "chacha20", + "cipher 0.3.0", + "poly1305", + "zeroize", +] + +[[package]] +name = "chrono" +version = "0.4.11" +source = "git+https://github.com/mesalock-linux/chrono-sgx#f964ae7f5f65bd2c9cd6f44a067e7980afc08ca0" +dependencies = [ + "num-integer 0.1.41", + "num-traits 0.2.10", + "sgx_tstd", +] + +[[package]] +name = "chrono" +version = "0.4.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec837a71355b28f6556dbd569b37b3f363091c0bd4b2e735674521b4c5fd9bc5" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "js-sys", + "num-traits 0.2.16", + "serde 1.0.193", + "time 0.1.45", + "wasm-bindgen", + "winapi 0.3.9", +] + +[[package]] +name = "cid" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6ed9c8b2d17acb8110c46f1da5bf4a696d745e1474a16db0cd2b49cd0249bf2" +dependencies = [ + "core2 0.4.0", + "multibase", + "multihash 0.16.3", + "serde 1.0.193", + "unsigned-varint 0.7.1", +] + +[[package]] +name = "cipher" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12f8e7987cbd042a63249497f41aed09f8e65add917ea6566effbc56578d6801" +dependencies = [ + "generic-array 0.14.7", +] + +[[package]] +name = "cipher" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7" +dependencies = [ + "generic-array 0.14.7", +] + +[[package]] +name = "cipher" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +dependencies = [ + "crypto-common", + "inout", +] + +[[package]] +name = "clang-sys" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c688fc74432808e3eb684cae8830a86be1d66a2bd58e1f248ed0960a590baf6f" +dependencies = [ + "glob", + "libc", + "libloading", +] + +[[package]] +name = "clap" +version = "2.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" +dependencies = [ + "ansi_term", + "atty", + "bitflags 1.3.2", + "strsim 0.8.0", + "textwrap", + "unicode-width", + "vec_map", + "yaml-rust 0.3.5", +] + +[[package]] +name = "clap" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa91278560fc226a5d9d736cc21e485ff9aad47d26b8ffe1f54cba868b684b9f" +dependencies = [ + "bitflags 1.3.2", + "clap_derive", + "clap_lex", + "is-terminal", + "once_cell 1.18.0", + "strsim 0.10.0", + "termcolor", +] + +[[package]] +name = "clap_derive" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "684a277d672e91966334af371f1a7b5833f9aa00b07c84e92fbce95e00208ce8" +dependencies = [ + "heck", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "clap_lex" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "033f6b7a4acb1f358c742aaca805c939ee73b4c6209ae4318ec7aca81c42e646" +dependencies = [ + "os_str_bytes", +] + +[[package]] +name = "coarsetime" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a90d114103adbc625300f346d4d09dfb4ab1c4a8df6868435dd903392ecf4354" +dependencies = [ + "libc", + "once_cell 1.18.0", + "wasi 0.11.0+wasi-snapshot-preview1", + "wasm-bindgen", +] + +[[package]] +name = "codespan-reporting" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" +dependencies = [ + "termcolor", + "unicode-width", +] + +[[package]] +name = "common-multipart-rfc7578" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76d0a7a42b9c13f2b2a1a7e64b949a19bcb56a49b190076e60261001ceaa5304" +dependencies = [ + "bytes 1.4.0", + "futures 0.3.28", + "http 0.2.9", + "mime", + "mime_guess", + "rand 0.8.5", + "thiserror 1.0.44", +] + +[[package]] +name = "common-primitives" +version = "0.1.0" +dependencies = [ + "sp-std 5.0.0", +] + +[[package]] +name = "concurrent-queue" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62ec6771ecfa0762d24683ee5a32ad78487a3d3afdc0fb8cae19d2c5deb50b7c" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "config" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d379af7f68bfc21714c6c7dea883544201741d2ce8274bb12fa54f89507f52a7" +dependencies = [ + "async-trait", + "json5", + "lazy_static", + "nom", + "pathdiff", + "ron", + "rust-ini", + "serde 1.0.193", + "serde_json 1.0.103", + "toml 0.5.11", + "yaml-rust 0.4.5", +] + +[[package]] +name = "const-oid" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "795bc6e66a8e340f075fcf6227e417a2dc976b92b91f3cdc778bb858778b6747" + +[[package]] +name = "constant_time_eq" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" + +[[package]] +name = "constant_time_eq" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21a53c0a4d288377e7415b53dcfc3c04da5cdc2cc95c8d5ac178b58f0b861ad6" + +[[package]] +name = "convert_case" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" + +[[package]] +name = "core-foundation" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" + +[[package]] +name = "core-primitives" +version = "0.9.12" +dependencies = [ + "frame-support", + "litentry-hex-utils", + "litentry-macros 0.9.12", + "litentry-proc-macros", + "pallet-evm 6.0.0-dev (git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42)", + "parity-scale-codec", + "ring 0.16.20", + "scale-info", + "serde 1.0.193", + "sp-core", + "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", + "sp-runtime", + "sp-std 5.0.0", + "strum 0.25.0", + "strum_macros 0.25.3", +] + +[[package]] +name = "core2" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "239fa3ae9b63c2dc74bd3fa852d4792b8b305ae64eeede946265b6af62f1fff3" +dependencies = [ + "memchr 2.6.3", +] + +[[package]] +name = "core2" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b49ba7ef1ad6107f8824dbe97de947cbaac53c44e7f9756a1fba0d37c1eec505" +dependencies = [ + "memchr 2.6.3", +] + +[[package]] +name = "cpp_demangle" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eeaa953eaad386a53111e47172c2fedba671e5684c8dd601a5f474f4f118710f" +dependencies = [ + "cfg-if 1.0.0", +] + +[[package]] +name = "cpufeatures" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" +dependencies = [ + "libc", +] + +[[package]] +name = "cranelift-bforest" +version = "0.93.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bc42ba2e232e5b20ff7dc299a812d53337dadce9a7e39a238e6a5cb82d2e57b" +dependencies = [ + "cranelift-entity", +] + +[[package]] +name = "cranelift-codegen" +version = "0.93.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "253531aca9b6f56103c9420369db3263e784df39aa1c90685a1f69cfbba0623e" +dependencies = [ + "arrayvec 0.7.4", + "bumpalo", + "cranelift-bforest", + "cranelift-codegen-meta", + "cranelift-codegen-shared", + "cranelift-entity", + "cranelift-isle", + "gimli 0.26.2", + "hashbrown 0.12.3", + "log 0.4.20", + "regalloc2", + "smallvec 1.11.0", + "target-lexicon", +] + +[[package]] +name = "cranelift-codegen-meta" +version = "0.93.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72f2154365e2bff1b1b8537a7181591fdff50d8e27fa6e40d5c69c3bad0ca7c8" +dependencies = [ + "cranelift-codegen-shared", +] + +[[package]] +name = "cranelift-codegen-shared" +version = "0.93.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "687e14e3f5775248930e0d5a84195abef8b829958e9794bf8d525104993612b4" + +[[package]] +name = "cranelift-entity" +version = "0.93.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f42ea692c7b450ad18b8c9889661505d51c09ec4380cf1c2d278dbb2da22cae1" +dependencies = [ + "serde 1.0.193", +] + +[[package]] +name = "cranelift-frontend" +version = "0.93.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8483c2db6f45fe9ace984e5adc5d058102227e4c62e5aa2054e16b0275fd3a6e" +dependencies = [ + "cranelift-codegen", + "log 0.4.20", + "smallvec 1.11.0", + "target-lexicon", +] + +[[package]] +name = "cranelift-isle" +version = "0.93.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9793158837678902446c411741d87b43f57dadfb944f2440db4287cda8cbd59" + +[[package]] +name = "cranelift-native" +version = "0.93.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72668c7755f2b880665cb422c8ad2d56db58a88b9bebfef0b73edc2277c13c49" +dependencies = [ + "cranelift-codegen", + "libc", + "target-lexicon", +] + +[[package]] +name = "cranelift-wasm" +version = "0.93.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3852ce4b088b44ac4e29459573943009a70d1b192c8d77ef949b4e814f656fc1" +dependencies = [ + "cranelift-codegen", + "cranelift-entity", + "cranelift-frontend", + "itertools 0.10.5", + "log 0.4.20", + "smallvec 1.11.0", + "wasmparser", + "wasmtime-types", +] + +[[package]] +name = "crc" +version = "3.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86ec7a15cbe22e59248fc7eadb1907dab5ba09372595da4d73dd805ed4417dfe" +dependencies = [ + "crc-catalog", +] + +[[package]] +name = "crc-catalog" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cace84e55f07e7301bae1c519df89cdad8cc3cd868413d3fdbdeca9ff3db484" + +[[package]] +name = "crc32fast" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +dependencies = [ + "cfg-if 1.0.0", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" +dependencies = [ + "cfg-if 1.0.0", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" +dependencies = [ + "cfg-if 1.0.0", + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" +dependencies = [ + "autocfg 1.1.0", + "cfg-if 1.0.0", + "crossbeam-utils", + "memoffset 0.9.0", + "scopeguard", +] + +[[package]] +name = "crossbeam-queue" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1cfb3ea8a53f37c40dea2c7bedcbd88bdfae54f5e2175d6ecaff1c988353add" +dependencies = [ + "cfg-if 1.0.0", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" +dependencies = [ + "cfg-if 1.0.0", +] + +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + +[[package]] +name = "crypto-bigint" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef2b4b23cddf68b89b8f8069890e8c270d54e2d5fe1b143820234805e4cb17ef" +dependencies = [ + "generic-array 0.14.7", + "rand_core 0.6.4", + "subtle", + "zeroize", +] + +[[package]] +name = "crypto-bigint" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "740fe28e594155f10cfc383984cbefd529d7396050557148f79cb0f621204124" +dependencies = [ + "generic-array 0.14.7", + "rand_core 0.6.4", + "subtle", + "zeroize", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array 0.14.7", + "rand_core 0.6.4", + "typenum 1.16.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crypto-mac" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab" +dependencies = [ + "generic-array 0.14.7", + "subtle", +] + +[[package]] +name = "crypto-mac" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1d1a86f49236c215f271d40892d5fc950490551400b02ef360692c29815c714" +dependencies = [ + "generic-array 0.14.7", + "subtle", +] + +[[package]] +name = "ct-logs" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1a816186fa68d9e426e3cb4ae4dff1fcd8e4a2c34b781bf7a822574a0d0aac8" +dependencies = [ + "sct 0.6.1", +] + +[[package]] +name = "ctr" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "049bb91fb4aaf0e3c7efa6cd5ef877dbbbd15b39dad06d9948de4ec8a75761ea" +dependencies = [ + "cipher 0.3.0", +] + +[[package]] +name = "ctr" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835" +dependencies = [ + "cipher 0.4.4", +] + +[[package]] +name = "cumulus-pallet-aura-ext" +version = "0.1.0" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.42#f603a61ff370fc33740c9373833c3c6ba1486846" +dependencies = [ + "frame-support", + "frame-system", + "pallet-aura", + "parity-scale-codec", + "scale-info", + "sp-application-crypto", + "sp-consensus-aura", + "sp-runtime", + "sp-std 5.0.0", +] + +[[package]] +name = "cumulus-pallet-dmp-queue" +version = "0.1.0" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.42#f603a61ff370fc33740c9373833c3c6ba1486846" +dependencies = [ + "cumulus-primitives-core", + "frame-support", + "frame-system", + "log 0.4.20", + "parity-scale-codec", + "scale-info", + "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", + "sp-runtime", + "sp-std 5.0.0", + "xcm", +] + +[[package]] +name = "cumulus-pallet-parachain-system" +version = "0.1.0" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.42#f603a61ff370fc33740c9373833c3c6ba1486846" +dependencies = [ + "bytes 1.4.0", + "cumulus-pallet-parachain-system-proc-macro", + "cumulus-primitives-core", + "cumulus-primitives-parachain-inherent", + "environmental 1.1.4", + "frame-support", + "frame-system", + "impl-trait-for-tuples", + "log 0.4.20", + "parity-scale-codec", + "polkadot-parachain", + "scale-info", + "sp-core", + "sp-externalities", + "sp-inherents", + "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", + "sp-runtime", + "sp-state-machine", + "sp-std 5.0.0", + "sp-trie", + "sp-version", + "xcm", +] + +[[package]] +name = "cumulus-pallet-parachain-system-proc-macro" +version = "0.1.0" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.42#f603a61ff370fc33740c9373833c3c6ba1486846" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.32", +] + +[[package]] +name = "cumulus-pallet-xcm" +version = "0.1.0" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.42#f603a61ff370fc33740c9373833c3c6ba1486846" +dependencies = [ + "cumulus-primitives-core", + "frame-support", + "frame-system", + "parity-scale-codec", + "scale-info", + "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", + "sp-runtime", + "sp-std 5.0.0", + "xcm", +] + +[[package]] +name = "cumulus-pallet-xcmp-queue" +version = "0.1.0" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.42#f603a61ff370fc33740c9373833c3c6ba1486846" +dependencies = [ + "cumulus-primitives-core", + "frame-support", + "frame-system", + "log 0.4.20", + "parity-scale-codec", + "polkadot-runtime-common", + "rand_chacha 0.3.1", + "scale-info", + "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", + "sp-runtime", + "sp-std 5.0.0", + "xcm", + "xcm-executor", +] + +[[package]] +name = "cumulus-primitives-core" +version = "0.1.0" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.42#f603a61ff370fc33740c9373833c3c6ba1486846" +dependencies = [ + "parity-scale-codec", + "polkadot-core-primitives", + "polkadot-parachain", + "polkadot-primitives", + "scale-info", + "sp-api", + "sp-runtime", + "sp-std 5.0.0", + "sp-trie", + "xcm", +] + +[[package]] +name = "cumulus-primitives-parachain-inherent" +version = "0.1.0" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.42#f603a61ff370fc33740c9373833c3c6ba1486846" +dependencies = [ + "async-trait", + "cumulus-primitives-core", + "cumulus-relay-chain-interface", + "cumulus-test-relay-sproof-builder", + "parity-scale-codec", + "sc-client-api", + "scale-info", + "sp-api", + "sp-core", + "sp-inherents", + "sp-runtime", + "sp-state-machine", + "sp-std 5.0.0", + "sp-storage", + "sp-trie", + "tracing", +] + +[[package]] +name = "cumulus-primitives-timestamp" +version = "0.1.0" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.42#f603a61ff370fc33740c9373833c3c6ba1486846" +dependencies = [ + "cumulus-primitives-core", + "futures 0.3.28", + "parity-scale-codec", + "sp-inherents", + "sp-std 5.0.0", + "sp-timestamp", +] + +[[package]] +name = "cumulus-primitives-utility" +version = "0.1.0" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.42#f603a61ff370fc33740c9373833c3c6ba1486846" +dependencies = [ + "cumulus-primitives-core", + "frame-support", + "log 0.4.20", + "parity-scale-codec", + "polkadot-runtime-common", + "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", + "sp-runtime", + "sp-std 5.0.0", + "xcm", + "xcm-builder", + "xcm-executor", +] + +[[package]] +name = "cumulus-relay-chain-interface" +version = "0.1.0" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.42#f603a61ff370fc33740c9373833c3c6ba1486846" +dependencies = [ + "async-trait", + "cumulus-primitives-core", + "futures 0.3.28", + "jsonrpsee-core", + "parity-scale-codec", + "polkadot-overseer", + "sc-client-api", + "sp-api", + "sp-blockchain", + "sp-state-machine", + "thiserror 1.0.44", +] + +[[package]] +name = "cumulus-test-relay-sproof-builder" +version = "0.1.0" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.42#f603a61ff370fc33740c9373833c3c6ba1486846" +dependencies = [ + "cumulus-primitives-core", + "parity-scale-codec", + "polkadot-primitives", + "sp-runtime", + "sp-state-machine", + "sp-std 5.0.0", +] + +[[package]] +name = "curve25519-dalek" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a9b85542f99a2dfa2a1b8e192662741c9859a846b296bef1c92ef9b58b5a216" +dependencies = [ + "byteorder 1.4.3", + "digest 0.8.1", + "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "subtle", + "zeroize", +] + +[[package]] +name = "curve25519-dalek" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b9fdf9972b2bd6af2d913799d9ebc165ea4d2e65878e329d9c6b372c4491b61" +dependencies = [ + "byteorder 1.4.3", + "digest 0.9.0", + "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "subtle", + "zeroize", +] + +[[package]] +name = "curve25519-dalek" +version = "4.0.0-rc.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d4ba9852b42210c7538b75484f9daa0655e9a3ac04f693747bb0f02cf3cfe16" +dependencies = [ + "cfg-if 1.0.0", + "fiat-crypto", + "packed_simd_2", + "platforms", + "subtle", + "zeroize", +] + +[[package]] +name = "cxx" +version = "1.0.97" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e88abab2f5abbe4c56e8f1fb431b784d710b709888f35755a160e62e33fe38e8" +dependencies = [ + "cc", + "cxxbridge-flags", + "cxxbridge-macro", + "link-cplusplus", +] + +[[package]] +name = "cxx-build" +version = "1.0.97" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c0c11acd0e63bae27dcd2afced407063312771212b7a823b4fd72d633be30fb" +dependencies = [ + "cc", + "codespan-reporting", + "once_cell 1.18.0", + "proc-macro2", + "quote", + "scratch", + "syn 2.0.32", +] + +[[package]] +name = "cxxbridge-flags" +version = "1.0.97" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d3816ed957c008ccd4728485511e3d9aaf7db419aa321e3d2c5a2f3411e36c8" + +[[package]] +name = "cxxbridge-macro" +version = "1.0.97" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a26acccf6f445af85ea056362561a24ef56cdc15fcc685f03aec50b9c702cb6d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.32", +] + +[[package]] +name = "darling" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "109c1ca6e6b7f82cc233a97004ea8ed7ca123a9af07a8230878fcfda9b158bf0" +dependencies = [ + "fnv 1.0.7", + "ident_case", + "proc-macro2", + "quote", + "strsim 0.10.0", + "syn 1.0.109", +] + +[[package]] +name = "darling_macro" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e" +dependencies = [ + "darling_core", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "data-encoding" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308" + +[[package]] +name = "data-encoding-macro" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c904b33cc60130e1aeea4956ab803d08a3f4a0ca82d64ed757afac3891f2bb99" +dependencies = [ + "data-encoding", + "data-encoding-macro-internal", +] + +[[package]] +name = "data-encoding-macro-internal" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fdf3fce3ce863539ec1d7fd1b6dcc3c645663376b43ed376bbf887733e4f772" +dependencies = [ + "data-encoding", + "syn 1.0.109", +] + +[[package]] +name = "der" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1a467a65c5e759bce6e65eaf91cc29f466cdc57cb65777bd646872a8a1fd4de" +dependencies = [ + "const-oid", + "der_derive", + "flagset", + "pem-rfc7468", + "zeroize", +] + +[[package]] +name = "der" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fffa369a668c8af7dbf8b5e56c9f744fbd399949ed171606040001947de40b1c" +dependencies = [ + "const-oid", + "zeroize", +] + +[[package]] +name = "der-parser" +version = "7.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe398ac75057914d7d07307bf67dc7f3f574a26783b4fc7805a20ffa9f506e82" +dependencies = [ + "asn1-rs 0.3.1", + "displaydoc", + "nom", + "num-bigint 0.4.3", + "num-traits 0.2.16", + "rusticata-macros", +] + +[[package]] +name = "der-parser" +version = "8.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbd676fbbab537128ef0278adb5576cf363cff6aa22a7b24effe97347cfab61e" +dependencies = [ + "asn1-rs 0.5.2", + "displaydoc", + "nom", + "num-bigint 0.4.3", + "num-traits 0.2.16", + "rusticata-macros", +] + +[[package]] +name = "der_derive" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ef71ddb5b3a1f53dee24817c8f70dfa1cb29e804c18d88c228d4bc9c86ee3b9" +dependencies = [ + "proc-macro-error", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "derive-syn-parse" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e79116f119dd1dba1abf1f3405f03b9b0e79a27a3883864bfebded8a3dc768cd" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "derive_builder" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d07adf7be193b71cc36b193d0f5fe60b918a3a9db4dad0449f57bcfd519704a3" +dependencies = [ + "derive_builder_macro", +] + +[[package]] +name = "derive_builder_core" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f91d4cfa921f1c05904dc3c57b4a32c38aed3340cce209f3a6fd1478babafc4" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "derive_builder_macro" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f0314b72bed045f3a68671b3c86328386762c93f82d98c65c3cb5e5f573dd68" +dependencies = [ + "derive_builder_core", + "syn 1.0.109", +] + +[[package]] +name = "derive_more" +version = "0.99.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +dependencies = [ + "convert_case", + "proc-macro2", + "quote", + "rustc_version", + "syn 1.0.109", +] + +[[package]] +name = "difflib" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8" + +[[package]] +name = "digest" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" +dependencies = [ + "generic-array 0.12.4", +] + +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array 0.14.7", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer 0.10.4", + "const-oid", + "crypto-common", + "subtle", +] + +[[package]] +name = "directories" +version = "4.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f51c5d4ddabd36886dd3e1438cb358cdcb0d7c499cb99cb4ac2e38e18b5cb210" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "directories-next" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "339ee130d97a610ea5a5872d2bbb130fdf68884ff09d3028b81bec8a1ac23bbc" +dependencies = [ + "cfg-if 1.0.0", + "dirs-sys-next", +] + +[[package]] +name = "dirs" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30baa043103c9d0c2a57cf537cc2f35623889dc0d405e6c3cccfadbc81c71309" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" +dependencies = [ + "libc", + "redox_users", + "winapi 0.3.9", +] + +[[package]] +name = "dirs-sys-next" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" +dependencies = [ + "libc", + "redox_users", + "winapi 0.3.9", +] + +[[package]] +name = "displaydoc" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.32", +] + +[[package]] +name = "dlv-list" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0688c2a7f92e427f44895cd63841bff7b29f8d7a1648b9e7e07a4a365b2e1257" + +[[package]] +name = "downcast" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1435fa1053d8b2fbbe9be7e97eca7f33d37b28409959813daefc1446a14247f1" + +[[package]] +name = "downcast-rs" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" + +[[package]] +name = "dtoa" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65d09067bfacaa79114679b279d7f5885b53295b1e2cfb4e79c8e4bd3d633169" + +[[package]] +name = "dyn-clonable" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e9232f0e607a262ceb9bd5141a3dfb3e4db6994b31989bbfd845878cba59fd4" +dependencies = [ + "dyn-clonable-impl", + "dyn-clone", +] + +[[package]] +name = "dyn-clonable-impl" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "558e40ea573c374cf53507fd240b7ee2f5477df7cfebdb97323ec61c719399c5" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "dyn-clone" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "304e6508efa593091e97a9abbc10f90aa7ca635b6d2784feff3c89d41dd12272" + +[[package]] +name = "ecdsa" +version = "0.14.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413301934810f597c1d19ca71c8710e99a3f1ba28a0d2ebc01551a2daeea3c5c" +dependencies = [ + "der 0.6.1", + "elliptic-curve 0.12.3", + "rfc6979 0.3.1", + "signature 1.6.4", +] + +[[package]] +name = "ecdsa" +version = "0.16.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4b1e0c257a9e9f25f90ff76d7a68360ed497ee519c8e428d1825ef0000799d4" +dependencies = [ + "der 0.7.8", + "digest 0.10.7", + "elliptic-curve 0.13.5", + "rfc6979 0.4.0", + "signature 2.1.0", + "spki 0.7.2", +] + +[[package]] +name = "ed25519" +version = "1.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91cff35c70bba8a626e3185d8cd48cc11b5437e1a5bcd15b9b5fa3c64b6dfee7" +dependencies = [ + "signature 1.6.4", +] + +[[package]] +name = "ed25519-dalek" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c762bae6dcaf24c4c84667b8579785430908723d5c889f469d76a41d59cc7a9d" +dependencies = [ + "curve25519-dalek 3.2.0", + "ed25519", + "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.193", + "sha2 0.9.9", + "zeroize", +] + +[[package]] +name = "ed25519-zebra" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c24f403d068ad0b359e577a77f92392118be3f3c927538f2bb544a5ecd828c6" +dependencies = [ + "curve25519-dalek 3.2.0", + "hashbrown 0.12.3", + "hex", + "rand_core 0.6.4", + "sha2 0.9.9", + "zeroize", +] + +[[package]] +name = "either" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" + +[[package]] +name = "elliptic-curve" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7bb888ab5300a19b8e5bceef25ac745ad065f3c9f7efc6de1b91958110891d3" +dependencies = [ + "base16ct 0.1.1", + "crypto-bigint 0.4.9", + "der 0.6.1", + "digest 0.10.7", + "ff 0.12.1", + "generic-array 0.14.7", + "group 0.12.1", + "hkdf", + "pem-rfc7468", + "pkcs8 0.9.0", + "rand_core 0.6.4", + "sec1 0.3.0", + "subtle", + "zeroize", +] + +[[package]] +name = "elliptic-curve" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "968405c8fdc9b3bf4df0a6638858cc0b52462836ab6b1c87377785dd09cf1c0b" +dependencies = [ + "base16ct 0.2.0", + "crypto-bigint 0.5.3", + "digest 0.10.7", + "ff 0.13.0", + "generic-array 0.14.7", + "group 0.13.0", + "pkcs8 0.10.2", + "rand_core 0.6.4", + "sec1 0.7.3", + "subtle", + "zeroize", +] + +[[package]] +name = "encoding_rs" +version = "0.8.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071a31f4ee85403370b58aca746f01041ede6f0da2730960ad001edc2b71b394" +dependencies = [ + "cfg-if 1.0.0", +] + +[[package]] +name = "enum-as-inner" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9720bba047d567ffc8a3cba48bf19126600e249ab7f128e9233e6376976a116" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "enumflags2" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c041f5090df68b32bcd905365fd51769c8b9d553fe87fde0b683534f10c01bd2" +dependencies = [ + "enumflags2_derive", +] + +[[package]] +name = "enumflags2_derive" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e9a1f9f7d83e59740248a6e14ecf93929ade55027844dfcea78beafccc15745" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.32", +] + +[[package]] +name = "enumn" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48016319042fb7c87b78d2993084a831793a897a5cd1a2a67cab9d1eeb4b7d76" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.32", +] + +[[package]] +name = "env_logger" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a12e6657c4c97ebab115a42dcee77225f7f482cdd841cf7088c657a42e9e00e7" +dependencies = [ + "atty", + "humantime", + "log 0.4.20", + "regex 1.9.5", + "termcolor", +] + +[[package]] +name = "env_logger" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0" +dependencies = [ + "humantime", + "is-terminal", + "log 0.4.20", + "regex 1.9.5", + "termcolor", +] + +[[package]] +name = "environmental" +version = "1.1.3" +dependencies = [ + "sgx_tstd", +] + +[[package]] +name = "environmental" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e48c92028aaa870e83d51c64e5d4e0b6981b360c522198c23959f219a4e1b15b" + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "errno" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" +dependencies = [ + "errno-dragonfly", + "libc", + "windows-sys 0.48.0", +] + +[[package]] +name = "errno-dragonfly" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "ethbloom" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c22d4b5885b6aa2fe5e8b9329fb8d232bf739e434e6b87347c63bdd00c120f60" +dependencies = [ + "crunchy", + "fixed-hash", + "impl-codec", + "impl-rlp", + "impl-serde", + "scale-info", + "tiny-keccak", +] + +[[package]] +name = "ethereum" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a89fb87a9e103f71b903b80b670200b54cc67a07578f070681f1fffb7396fb7" +dependencies = [ + "bytes 1.4.0", + "ethereum-types", + "hash-db 0.15.2", + "hash256-std-hasher", + "parity-scale-codec", + "rlp", + "scale-info", + "serde 1.0.193", + "sha3", + "triehash", +] + +[[package]] +name = "ethereum-types" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02d215cbf040552efcbe99a38372fe80ab9d00268e20012b79fcd0f073edd8ee" +dependencies = [ + "ethbloom", + "fixed-hash", + "impl-codec", + "impl-rlp", + "impl-serde", + "primitive-types", + "scale-info", + "uint", +] + +[[package]] +name = "event-listener" +version = "2.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" + +[[package]] +name = "evm" +version = "0.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4448c65b71e8e2b9718232d84d09045eeaaccb2320494e6bd6dbf7e58fec8ff" +dependencies = [ + "auto_impl", + "environmental 1.1.4", + "ethereum", + "evm-core 0.37.0", + "evm-gasometer 0.37.0", + "evm-runtime 0.37.0", + "log 0.4.20", + "parity-scale-codec", + "primitive-types", + "rlp", + "scale-info", + "serde 1.0.193", + "sha3", +] + +[[package]] +name = "evm" +version = "0.39.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a49a4e11987c51220aa89dbe1a5cc877f5079fa6864c0a5b4533331db44e9365" +dependencies = [ + "auto_impl", + "environmental 1.1.4", + "ethereum", + "evm-core 0.39.0 (registry+https://github.com/rust-lang/crates.io-index)", + "evm-gasometer 0.39.0 (registry+https://github.com/rust-lang/crates.io-index)", + "evm-runtime 0.39.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.20", + "parity-scale-codec", + "primitive-types", + "rlp", + "scale-info", + "serde 1.0.193", + "sha3", +] + +[[package]] +name = "evm" +version = "0.39.1" +source = "git+https://github.com/rust-blockchain/evm?rev=b7b82c7e1fc57b7449d6dfa6826600de37cc1e65#b7b82c7e1fc57b7449d6dfa6826600de37cc1e65" +dependencies = [ + "auto_impl", + "environmental 1.1.4", + "ethereum", + "evm-core 0.39.0 (git+https://github.com/rust-blockchain/evm?rev=b7b82c7e1fc57b7449d6dfa6826600de37cc1e65)", + "evm-gasometer 0.39.0 (git+https://github.com/rust-blockchain/evm?rev=b7b82c7e1fc57b7449d6dfa6826600de37cc1e65)", + "evm-runtime 0.39.0 (git+https://github.com/rust-blockchain/evm?rev=b7b82c7e1fc57b7449d6dfa6826600de37cc1e65)", + "log 0.4.20", + "parity-scale-codec", + "primitive-types", + "rlp", + "scale-info", + "serde 1.0.193", + "sha3", +] + +[[package]] +name = "evm-core" +version = "0.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64c51bec0eb68a891c2575c758eaaa1d61373fc51f7caaf216b1fb5c3fea3b5d" +dependencies = [ + "parity-scale-codec", + "primitive-types", + "scale-info", + "serde 1.0.193", +] + +[[package]] +name = "evm-core" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f1f13264b044cb66f0602180f0bc781c29accb41ff560669a3ec15858d5b606" +dependencies = [ + "parity-scale-codec", + "primitive-types", + "scale-info", + "serde 1.0.193", +] + +[[package]] +name = "evm-core" +version = "0.39.0" +source = "git+https://github.com/rust-blockchain/evm?rev=b7b82c7e1fc57b7449d6dfa6826600de37cc1e65#b7b82c7e1fc57b7449d6dfa6826600de37cc1e65" +dependencies = [ + "parity-scale-codec", + "primitive-types", + "scale-info", + "serde 1.0.193", +] + +[[package]] +name = "evm-gasometer" +version = "0.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8b93c59c54fc26522d842f0e0d3f8e8be331c776df18ff3e540b53c2f64d509" +dependencies = [ + "environmental 1.1.4", + "evm-core 0.37.0", + "evm-runtime 0.37.0", + "primitive-types", +] + +[[package]] +name = "evm-gasometer" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d43eadc395bd1a52990787ca1495c26b0248165444912be075c28909a853b8c" +dependencies = [ + "environmental 1.1.4", + "evm-core 0.39.0 (registry+https://github.com/rust-lang/crates.io-index)", + "evm-runtime 0.39.0 (registry+https://github.com/rust-lang/crates.io-index)", + "primitive-types", +] + +[[package]] +name = "evm-gasometer" +version = "0.39.0" +source = "git+https://github.com/rust-blockchain/evm?rev=b7b82c7e1fc57b7449d6dfa6826600de37cc1e65#b7b82c7e1fc57b7449d6dfa6826600de37cc1e65" +dependencies = [ + "environmental 1.1.4", + "evm-core 0.39.0 (git+https://github.com/rust-blockchain/evm?rev=b7b82c7e1fc57b7449d6dfa6826600de37cc1e65)", + "evm-runtime 0.39.0 (git+https://github.com/rust-blockchain/evm?rev=b7b82c7e1fc57b7449d6dfa6826600de37cc1e65)", + "primitive-types", +] + +[[package]] +name = "evm-runtime" +version = "0.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c79b9459ce64f1a28688397c4013764ce53cd57bb84efc16b5187fa9b05b13ad" +dependencies = [ + "auto_impl", + "environmental 1.1.4", + "evm-core 0.37.0", + "primitive-types", + "sha3", +] + +[[package]] +name = "evm-runtime" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2aa5b32f59ec582a5651978004e5c784920291263b7dcb6de418047438e37f4f" +dependencies = [ + "auto_impl", + "environmental 1.1.4", + "evm-core 0.39.0 (registry+https://github.com/rust-lang/crates.io-index)", + "primitive-types", + "sha3", +] + +[[package]] +name = "evm-runtime" +version = "0.39.0" +source = "git+https://github.com/rust-blockchain/evm?rev=b7b82c7e1fc57b7449d6dfa6826600de37cc1e65#b7b82c7e1fc57b7449d6dfa6826600de37cc1e65" +dependencies = [ + "auto_impl", + "environmental 1.1.4", + "evm-core 0.39.0 (git+https://github.com/rust-blockchain/evm?rev=b7b82c7e1fc57b7449d6dfa6826600de37cc1e65)", + "primitive-types", + "sha3", +] + +[[package]] +name = "evm-tracing-events" +version = "0.1.0" +source = "git+https://github.com/litentry/astar-frame?branch=polkadot-v0.9.42#d9a49c58f248f49e274b0730b8f4ef7f1e72c4b5" +dependencies = [ + "environmental 1.1.4", + "ethereum", + "ethereum-types", + "evm 0.37.0", + "evm-gasometer 0.37.0", + "evm-runtime 0.37.0", + "parity-scale-codec", + "sp-runtime-interface", +] + +[[package]] +name = "exit-future" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e43f2f1833d64e33f15592464d6fdd70f349dda7b1a53088eb83cd94014008c5" +dependencies = [ + "futures 0.3.28", +] + +[[package]] +name = "expander" +version = "0.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a718c0675c555c5f976fff4ea9e2c150fa06cefa201cadef87cfbf9324075881" +dependencies = [ + "blake3", + "fs-err", + "proc-macro2", + "quote", +] + +[[package]] +name = "expander" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3774182a5df13c3d1690311ad32fbe913feef26baba609fa2dd5f72042bd2ab6" +dependencies = [ + "blake2", + "fs-err", + "proc-macro2", + "quote", +] + +[[package]] +name = "expander" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f360349150728553f92e4c997a16af8915f418d3a0f21b440d34c5632f16ed84" +dependencies = [ + "blake2", + "fs-err", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "expander" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f86a749cf851891866c10515ef6c299b5c69661465e9c3bbe7e07a2b77fb0f7" +dependencies = [ + "blake2", + "fs-err", + "proc-macro2", + "quote", + "syn 2.0.32", +] + +[[package]] +name = "failure" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d32e9bd16cc02eae7db7ef620b392808b89f6a5e16bb3497d159c6b92a0f4f86" +dependencies = [ + "backtrace", + "failure_derive", +] + +[[package]] +name = "failure_derive" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", + "synstructure", +] + +[[package]] +name = "fake-simd" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" + +[[package]] +name = "fallible-iterator" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" + +[[package]] +name = "fastrand" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" +dependencies = [ + "instant", +] + +[[package]] +name = "fastrand" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764" + +[[package]] +name = "fatality" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ad875162843b0d046276327afe0136e9ed3a23d5a754210fb6f1f33610d39ab" +dependencies = [ + "fatality-proc-macro", + "thiserror 1.0.44", +] + +[[package]] +name = "fatality-proc-macro" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5aa1e3ae159e592ad222dc90c5acbad632b527779ba88486abe92782ab268bd" +dependencies = [ + "expander 0.0.4", + "indexmap 1.9.3", + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 1.0.109", + "thiserror 1.0.44", +] + +[[package]] +name = "fdlimit" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c4c9e43643f5a3be4ca5b67d26b98031ff9db6806c3440ae32e02e3ceac3f1b" +dependencies = [ + "libc", +] + +[[package]] +name = "ff" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d013fc25338cc558c5c2cfbad646908fb23591e2404481826742b651c9af7160" +dependencies = [ + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "ff" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" +dependencies = [ + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "fiat-crypto" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e825f6987101665dea6ec934c09ec6d721de7bc1bf92248e1d5810c8cd636b77" + +[[package]] +name = "file-per-thread-logger" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84f2e425d9790201ba4af4630191feac6dcc98765b118d4d18e91d23c2353866" +dependencies = [ + "env_logger 0.10.0", + "log 0.4.20", +] + +[[package]] +name = "filetime" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cbc844cecaee9d4443931972e1289c8ff485cb4cc2767cb03ca139ed6885153" +dependencies = [ + "cfg-if 1.0.0", + "libc", + "redox_syscall 0.2.16", + "windows-sys 0.48.0", +] + +[[package]] +name = "finality-grandpa" +version = "0.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36530797b9bf31cd4ff126dcfee8170f86b00cfdcea3269d73133cc0415945c3" +dependencies = [ + "either", + "futures 0.3.28", + "futures-timer", + "log 0.4.20", + "num-traits 0.2.16", + "parity-scale-codec", + "parking_lot 0.12.1", + "scale-info", +] + +[[package]] +name = "fixed-hash" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" +dependencies = [ + "byteorder 1.4.3", + "rand 0.8.5", + "rustc-hex", + "static_assertions", +] + +[[package]] +name = "fixedbitset" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" + +[[package]] +name = "flagset" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cda653ca797810c02f7ca4b804b40b8b95ae046eb989d356bce17919a8c25499" + +[[package]] +name = "flate2" +version = "1.0.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b9429470923de8e8cbd4d2dc513535400b4b3fef0319fb5c4e1f520a7bef743" +dependencies = [ + "crc32fast", + "libz-sys", + "miniz_oxide", +] + +[[package]] +name = "float-cmp" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98de4bbd547a563b716d8dfa9aad1cb19bfab00f4fa09a6a4ed21dbcf44ce9c4" +dependencies = [ + "num-traits 0.2.16", +] + +[[package]] +name = "fnv" +version = "1.0.6" +source = "git+https://github.com/mesalock-linux/rust-fnv-sgx#c3bd6153c1403c1fa32fa54be5544d91f5efb017" +dependencies = [ + "hashbrown 0.3.1", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + +[[package]] +name = "fork-tree" +version = "3.0.0" +dependencies = [ + "parity-scale-codec", + "sgx_tstd", +] + +[[package]] +name = "fork-tree" +version = "3.0.0" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "parity-scale-codec", +] + +[[package]] +name = "form_urlencoded" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" +dependencies = [ + "percent-encoding 2.3.0", +] + +[[package]] +name = "fp-account" +version = "1.0.0-dev" +source = "git+https://github.com/integritee-network/frontier.git?branch=bar/polkadot-v0.9.42#a5a5e1e6ec08cd542a6084c310863150fb8841b1" +dependencies = [ + "hex", + "impl-serde", + "libsecp256k1", + "log 0.4.20", + "parity-scale-codec", + "scale-info", + "serde 1.0.193", + "sp-core", + "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", + "sp-runtime", + "sp-std 5.0.0", +] + +[[package]] +name = "fp-account" +version = "1.0.0-dev" +source = "git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42#2499d18c936edbcb7fcb711827db7abb9b4f4da4" +dependencies = [ + "hex", + "impl-serde", + "libsecp256k1", + "log 0.4.20", + "parity-scale-codec", + "scale-info", + "serde 1.0.193", + "sp-core", + "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", + "sp-runtime", + "sp-runtime-interface", + "sp-std 5.0.0", +] + +[[package]] +name = "fp-consensus" +version = "2.0.0-dev" +source = "git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42#2499d18c936edbcb7fcb711827db7abb9b4f4da4" +dependencies = [ + "ethereum", + "parity-scale-codec", + "sp-core", + "sp-runtime", + "sp-std 5.0.0", +] + +[[package]] +name = "fp-ethereum" +version = "1.0.0-dev" +source = "git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42#2499d18c936edbcb7fcb711827db7abb9b4f4da4" +dependencies = [ + "ethereum", + "ethereum-types", + "fp-evm 3.0.0-dev (git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42)", + "frame-support", + "num_enum 0.6.1", + "parity-scale-codec", + "sp-std 5.0.0", +] + +[[package]] +name = "fp-evm" +version = "3.0.0-dev" +source = "git+https://github.com/integritee-network/frontier.git?branch=bar/polkadot-v0.9.42#a5a5e1e6ec08cd542a6084c310863150fb8841b1" +dependencies = [ + "evm 0.39.1 (registry+https://github.com/rust-lang/crates.io-index)", + "frame-support", + "parity-scale-codec", + "scale-info", + "serde 1.0.193", + "sp-core", + "sp-runtime", + "sp-std 5.0.0", +] + +[[package]] +name = "fp-evm" +version = "3.0.0-dev" +source = "git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42#2499d18c936edbcb7fcb711827db7abb9b4f4da4" +dependencies = [ + "evm 0.39.1 (git+https://github.com/rust-blockchain/evm?rev=b7b82c7e1fc57b7449d6dfa6826600de37cc1e65)", + "frame-support", + "parity-scale-codec", + "scale-info", + "serde 1.0.193", + "sp-core", + "sp-runtime", + "sp-std 5.0.0", +] + +[[package]] +name = "fp-rpc" +version = "3.0.0-dev" +source = "git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42#2499d18c936edbcb7fcb711827db7abb9b4f4da4" +dependencies = [ + "ethereum", + "ethereum-types", + "fp-evm 3.0.0-dev (git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42)", + "parity-scale-codec", + "scale-info", + "sp-api", + "sp-core", + "sp-runtime", + "sp-state-machine", + "sp-std 5.0.0", +] + +[[package]] +name = "fp-self-contained" +version = "1.0.0-dev" +source = "git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42#2499d18c936edbcb7fcb711827db7abb9b4f4da4" +dependencies = [ + "frame-support", + "parity-scale-codec", + "scale-info", + "serde 1.0.193", + "sp-runtime", +] + +[[package]] +name = "fp-storage" +version = "2.0.0" +source = "git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42#2499d18c936edbcb7fcb711827db7abb9b4f4da4" +dependencies = [ + "parity-scale-codec", + "serde 1.0.193", +] + +[[package]] +name = "fragile" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c2141d6d6c8512188a7891b4b01590a45f6dac67afb4f255c4124dbb86d4eaa" + +[[package]] +name = "frame-benchmarking" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "frame-support", + "frame-support-procedural", + "frame-system", + "linregress", + "log 0.4.20", + "parity-scale-codec", + "paste", + "scale-info", + "serde 1.0.193", + "sp-api", + "sp-application-crypto", + "sp-core", + "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", + "sp-runtime", + "sp-runtime-interface", + "sp-std 5.0.0", + "sp-storage", + "static_assertions", +] + +[[package]] +name = "frame-election-provider-solution-type" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.32", +] + +[[package]] +name = "frame-election-provider-support" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "frame-election-provider-solution-type", + "frame-support", + "frame-system", + "parity-scale-codec", + "scale-info", + "sp-arithmetic", + "sp-core", + "sp-npos-elections", + "sp-runtime", + "sp-std 5.0.0", +] + +[[package]] +name = "frame-executive" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "frame-support", + "frame-system", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", + "sp-runtime", + "sp-std 5.0.0", + "sp-tracing", +] + +[[package]] +name = "frame-metadata" +version = "15.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "878babb0b136e731cc77ec2fd883ff02745ff21e6fb662729953d44923df009c" +dependencies = [ + "cfg-if 1.0.0", + "parity-scale-codec", + "scale-info", + "serde 1.0.193", +] + +[[package]] +name = "frame-support" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "bitflags 1.3.2", + "environmental 1.1.4", + "frame-metadata", + "frame-support-procedural", + "impl-trait-for-tuples", + "k256", + "log 0.4.20", + "once_cell 1.18.0", + "parity-scale-codec", + "paste", + "scale-info", + "serde 1.0.193", + "smallvec 1.11.0", + "sp-api", + "sp-arithmetic", + "sp-core", + "sp-core-hashing-proc-macro", + "sp-inherents", + "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", + "sp-runtime", + "sp-staking", + "sp-state-machine", + "sp-std 5.0.0", + "sp-tracing", + "sp-weights", + "tt-call", +] + +[[package]] +name = "frame-support-procedural" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "Inflector", + "cfg-expr", + "derive-syn-parse", + "frame-support-procedural-tools", + "itertools 0.10.5", + "proc-macro-warning", + "proc-macro2", + "quote", + "syn 2.0.32", +] + +[[package]] +name = "frame-support-procedural-tools" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "frame-support-procedural-tools-derive", + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.32", +] + +[[package]] +name = "frame-support-procedural-tools-derive" +version = "3.0.0" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.32", +] + +[[package]] +name = "frame-system" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "frame-support", + "log 0.4.20", + "parity-scale-codec", + "scale-info", + "serde 1.0.193", + "sp-core", + "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", + "sp-runtime", + "sp-std 5.0.0", + "sp-version", + "sp-weights", +] + +[[package]] +name = "frame-system-benchmarking" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-runtime", + "sp-std 5.0.0", +] + +[[package]] +name = "frame-system-rpc-runtime-api" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "parity-scale-codec", + "sp-api", +] + +[[package]] +name = "frame-try-runtime" +version = "0.10.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "frame-support", + "parity-scale-codec", + "sp-api", + "sp-runtime", + "sp-std 5.0.0", +] + +[[package]] +name = "fs-err" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0845fa252299212f0389d64ba26f34fa32cfe41588355f21ed507c59a0f64541" + +[[package]] +name = "fs2" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213" +dependencies = [ + "libc", + "winapi 0.3.9", +] + +[[package]] +name = "fs4" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2eeb4ed9e12f43b7fa0baae3f9cdda28352770132ef2e09a23760c29cae8bd47" +dependencies = [ + "rustix 0.38.4", + "windows-sys 0.48.0", +] + +[[package]] +name = "fuchsia-zircon" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" +dependencies = [ + "bitflags 1.3.2", + "fuchsia-zircon-sys", +] + +[[package]] +name = "fuchsia-zircon-sys" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" + +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + +[[package]] +name = "futures" +version = "0.3.8" +source = "git+https://github.com/mesalock-linux/futures-rs-sgx#d54882f24ddf7d61327a067b2f608d6940a36444" +dependencies = [ + "futures-channel 0.3.8", + "futures-core 0.3.8", + "futures-executor 0.3.8", + "futures-io 0.3.8", + "futures-sink 0.3.8", + "futures-task 0.3.8", + "futures-util 0.3.8", + "sgx_tstd", +] + +[[package]] +name = "futures" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40" +dependencies = [ + "futures-channel 0.3.28", + "futures-core 0.3.28", + "futures-executor 0.3.28", + "futures-io 0.3.28", + "futures-sink 0.3.28", + "futures-task 0.3.28", + "futures-util 0.3.28", +] + +[[package]] +name = "futures-channel" +version = "0.3.8" +source = "git+https://github.com/mesalock-linux/futures-rs-sgx#d54882f24ddf7d61327a067b2f608d6940a36444" +dependencies = [ + "futures-core 0.3.8", + "futures-sink 0.3.8", + "sgx_tstd", +] + +[[package]] +name = "futures-channel" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" +dependencies = [ + "futures-core 0.3.28", + "futures-sink 0.3.28", +] + +[[package]] +name = "futures-core" +version = "0.3.8" +source = "git+https://github.com/mesalock-linux/futures-rs-sgx#d54882f24ddf7d61327a067b2f608d6940a36444" +dependencies = [ + "sgx_tstd", +] + +[[package]] +name = "futures-core" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" + +[[package]] +name = "futures-executor" +version = "0.3.8" +source = "git+https://github.com/mesalock-linux/futures-rs-sgx#d54882f24ddf7d61327a067b2f608d6940a36444" +dependencies = [ + "futures-core 0.3.8", + "futures-task 0.3.8", + "futures-util 0.3.8", + "sgx_tstd", +] + +[[package]] +name = "futures-executor" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0" +dependencies = [ + "futures-core 0.3.28", + "futures-task 0.3.28", + "futures-util 0.3.28", + "num_cpus", +] + +[[package]] +name = "futures-io" +version = "0.3.8" +source = "git+https://github.com/mesalock-linux/futures-rs-sgx#d54882f24ddf7d61327a067b2f608d6940a36444" +dependencies = [ + "sgx_tstd", +] + +[[package]] +name = "futures-io" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" + +[[package]] +name = "futures-lite" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" +dependencies = [ + "fastrand 1.9.0", + "futures-core 0.3.28", + "futures-io 0.3.28", + "memchr 2.6.3", + "parking", + "pin-project-lite 0.2.10", + "waker-fn", +] + +[[package]] +name = "futures-macro" +version = "0.3.8" +source = "git+https://github.com/mesalock-linux/futures-rs-sgx#d54882f24ddf7d61327a067b2f608d6940a36444" +dependencies = [ + "proc-macro-hack", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "futures-macro" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.32", +] + +[[package]] +name = "futures-rustls" +version = "0.22.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2411eed028cdf8c8034eaf21f9915f956b6c3abec4d4c7949ee67f0721127bd" +dependencies = [ + "futures-io 0.3.28", + "rustls 0.20.8", + "webpki 0.22.0", +] + +[[package]] +name = "futures-sink" +version = "0.3.8" +source = "git+https://github.com/mesalock-linux/futures-rs-sgx#d54882f24ddf7d61327a067b2f608d6940a36444" + +[[package]] +name = "futures-sink" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" + +[[package]] +name = "futures-task" +version = "0.3.8" +source = "git+https://github.com/mesalock-linux/futures-rs-sgx#d54882f24ddf7d61327a067b2f608d6940a36444" +dependencies = [ + "once_cell 1.4.0", + "sgx_tstd", +] + +[[package]] +name = "futures-task" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" + +[[package]] +name = "futures-timer" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e64b03909df88034c26dc1547e8970b91f98bdb65165d6a4e9110d94263dbb2c" + +[[package]] +name = "futures-util" +version = "0.3.8" +source = "git+https://github.com/mesalock-linux/futures-rs-sgx#d54882f24ddf7d61327a067b2f608d6940a36444" +dependencies = [ + "futures-channel 0.3.8", + "futures-core 0.3.8", + "futures-io 0.3.8", + "futures-macro 0.3.8", + "futures-sink 0.3.8", + "futures-task 0.3.8", + "memchr 2.2.1", + "pin-project-lite 0.2.10", + "pin-utils", + "proc-macro-hack", + "proc-macro-nested", + "sgx_tstd", + "slab 0.4.2", +] + +[[package]] +name = "futures-util" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" +dependencies = [ + "futures-channel 0.3.28", + "futures-core 0.3.28", + "futures-io 0.3.28", + "futures-macro 0.3.28", + "futures-sink 0.3.28", + "futures-task 0.3.28", + "memchr 2.6.3", + "pin-project-lite 0.2.10", + "pin-utils", + "slab 0.4.8", +] + +[[package]] +name = "fxhash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" +dependencies = [ + "byteorder 1.4.3", +] + +[[package]] +name = "generic-array" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd" +dependencies = [ + "typenum 1.16.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum 1.16.0 (registry+https://github.com/rust-lang/crates.io-index)", + "version_check", + "zeroize", +] + +[[package]] +name = "getrandom" +version = "0.1.14" +source = "git+https://github.com/mesalock-linux/getrandom-sgx#0aa9cc20c7dea713ccaac2c44430d625a395ebae" +dependencies = [ + "cfg-if 0.1.10", + "sgx_libc", + "sgx_trts", + "sgx_tstd", +] + +[[package]] +name = "getrandom" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" +dependencies = [ + "cfg-if 1.0.0", + "libc", + "wasi 0.9.0+wasi-snapshot-preview1", +] + +[[package]] +name = "getrandom" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" +dependencies = [ + "cfg-if 1.0.0", + "libc", + "wasi 0.11.0+wasi-snapshot-preview1", +] + +[[package]] +name = "ghash" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1583cc1656d7839fd3732b80cf4f38850336cdb9b8ded1cd399ca62958de3c99" +dependencies = [ + "opaque-debug 0.3.0", + "polyval 0.5.3", +] + +[[package]] +name = "ghash" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d930750de5717d2dd0b8c0d42c076c0e884c81a73e6cab859bbd2339c71e3e40" +dependencies = [ + "opaque-debug 0.3.0", + "polyval 0.6.1", +] + +[[package]] +name = "gimli" +version = "0.26.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d" +dependencies = [ + "fallible-iterator", + "indexmap 1.9.3", + "stable_deref_trait", +] + +[[package]] +name = "gimli" +version = "0.27.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e" + +[[package]] +name = "glob" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" + +[[package]] +name = "globset" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1391ab1f92ffcc08911957149833e682aa3fe252b9f45f966d2ef972274c97df" +dependencies = [ + "aho-corasick", + "bstr", + "fnv 1.0.7", + "log 0.4.20", + "regex 1.9.5", +] + +[[package]] +name = "group" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dfbfb3a6cfbd390d5c9564ab283a0349b9b9fcd46a706c1eb10e0db70bfbac7" +dependencies = [ + "ff 0.12.1", + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "group" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" +dependencies = [ + "ff 0.13.0", + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "h2" +version = "0.3.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97ec8491ebaf99c8eaa73058b045fe58073cd6be7f596ac993ced0b0a0c01049" +dependencies = [ + "bytes 1.4.0", + "fnv 1.0.7", + "futures-core 0.3.28", + "futures-sink 0.3.28", + "futures-util 0.3.28", + "http 0.2.9", + "indexmap 1.9.3", + "slab 0.4.8", + "tokio", + "tokio-util 0.7.8", + "tracing", +] + +[[package]] +name = "hash-db" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d23bd4e7b5eda0d0f3a307e8b381fdc8ba9000f26fbe912250c0a4cc3956364a" + +[[package]] +name = "hash-db" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e7d7786361d7425ae2fe4f9e407eb0efaa0840f5212d109cc018c40c35c6ab4" + +[[package]] +name = "hash256-std-hasher" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92c171d55b98633f4ed3860808f004099b36c1cc29c42cfc53aa8591b21efcf2" +dependencies = [ + "crunchy", +] + +[[package]] +name = "hashbrown" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29fba9abe4742d586dfd0c06ae4f7e73a1c2d86b856933509b269d82cdf06e18" + +[[package]] +name = "hashbrown" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04" + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +dependencies = [ + "ahash 0.7.6", +] + +[[package]] +name = "hashbrown" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" +dependencies = [ + "ahash 0.8.3", +] + +[[package]] +name = "hashbrown" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" + +[[package]] +name = "hashbrown_tstd" +version = "0.12.0" +source = "git+https://github.com/apache/incubator-teaclave-sgx-sdk?branch=master#3c903bdac4e503dd27b9b1f761c4abfc55f2464c" + +[[package]] +name = "hdrhistogram" +version = "7.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f19b9f54f7c7f55e31401bb647626ce0cf0f67b0004982ce815b3ee72a02aa8" +dependencies = [ + "base64 0.13.1", + "byteorder 1.4.3", + "crossbeam-channel", + "flate2", + "nom", + "num-traits 0.2.16", +] + +[[package]] +name = "headers" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3e372db8e5c0d213e0cd0b9be18be2aca3d44cf2fe30a9d46a65581cd454584" +dependencies = [ + "base64 0.13.1", + "bitflags 1.3.2", + "bytes 1.4.0", + "headers-core", + "http 0.2.9", + "httpdate", + "mime", + "sha1 0.10.5", +] + +[[package]] +name = "headers-core" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7f66481bfee273957b1f20485a4ff3362987f85b2c236580d81b4eb7a326429" +dependencies = [ + "http 0.2.9", +] + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "hermit-abi" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +dependencies = [ + "serde 1.0.193", +] + +[[package]] +name = "hex-conservative" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30ed443af458ccb6d81c1e7e661545f94d3176752fb1df2f543b902a1e0f51e2" +dependencies = [ + "core2 0.3.3", +] + +[[package]] +name = "hex-literal" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46" + +[[package]] +name = "hex_lit" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3011d1213f159867b13cfd6ac92d2cd5f1345762c63be3554e84092d85a50bbd" + +[[package]] +name = "hkdf" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "791a029f6b9fc27657f6f188ec6e5e43f6911f6f878e0dc5501396e09809d437" +dependencies = [ + "hmac 0.12.1", +] + +[[package]] +name = "hmac" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "126888268dcc288495a26bf004b38c5fdbb31682f992c84ceb046a1f0fe38840" +dependencies = [ + "crypto-mac 0.8.0", + "digest 0.9.0", +] + +[[package]] +name = "hmac" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a2a2320eb7ec0ebe8da8f744d7812d9fc4cb4d09344ac01898dbcb6a20ae69b" +dependencies = [ + "crypto-mac 0.11.1", + "digest 0.9.0", +] + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest 0.10.7", +] + +[[package]] +name = "hmac-drbg" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17ea0a1394df5b6574da6e0c1ade9e78868c9fb0a4e5ef4428e32da4676b85b1" +dependencies = [ + "digest 0.9.0", + "generic-array 0.14.7", + "hmac 0.8.1", +] + +[[package]] +name = "hostname" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c731c3e10504cc8ed35cfe2f1db4c9274c3d35fa486e3b31df46f068ef3e867" +dependencies = [ + "libc", + "match_cfg", + "winapi 0.3.9", +] + +[[package]] +name = "http" +version = "0.2.1" +source = "git+https://github.com/integritee-network/http-sgx.git?branch=sgx-experimental#307b5421fb7a489a114bede0dc05c8d32b804f49" +dependencies = [ + "bytes 1.0.1", + "fnv 1.0.6", + "itoa 0.4.5", + "sgx_tstd", +] + +[[package]] +name = "http" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" +dependencies = [ + "bytes 1.4.0", + "fnv 1.0.7", + "itoa 1.0.9", +] + +[[package]] +name = "http-body" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" +dependencies = [ + "bytes 1.4.0", + "http 0.2.9", + "pin-project-lite 0.2.10", +] + +[[package]] +name = "http-range-header" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bfe8eed0a9285ef776bb792479ea3834e8b94e13d615c2f66d03dd50a435a29" + +[[package]] +name = "http_req" +version = "0.8.1" +source = "git+https://github.com/integritee-network/http_req?branch=master#3723e88235f2b29bc1a31835853b072ffd0455fd" +dependencies = [ + "log 0.4.20", + "rustls 0.19.1", + "unicase 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "webpki 0.21.4 (registry+https://github.com/rust-lang/crates.io-index)", + "webpki-roots 0.21.1", +] + +[[package]] +name = "http_req" +version = "0.8.1" +source = "git+https://github.com/integritee-network/http_req#3723e88235f2b29bc1a31835853b072ffd0455fd" +dependencies = [ + "log 0.4.20", + "rustls 0.19.0 (git+https://github.com/mesalock-linux/rustls?branch=mesalock_sgx)", + "sgx_tstd", + "unicase 2.6.0 (git+https://github.com/mesalock-linux/unicase-sgx)", + "webpki 0.21.4 (git+https://github.com/mesalock-linux/webpki?branch=mesalock_sgx)", + "webpki-roots 0.21.0 (git+https://github.com/mesalock-linux/webpki-roots?branch=mesalock_sgx)", +] + +[[package]] +name = "httparse" +version = "1.4.1" +source = "git+https://github.com/integritee-network/httparse-sgx?branch=sgx-experimental#cc97e4b34d2c44a1e3df5bdebef446b9771f5cc3" +dependencies = [ + "sgx_tstd", +] + +[[package]] +name = "httparse" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" + +[[package]] +name = "httpdate" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" + +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + +[[package]] +name = "hyper" +version = "0.14.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" +dependencies = [ + "bytes 1.4.0", + "futures-channel 0.3.28", + "futures-core 0.3.28", + "futures-util 0.3.28", + "h2", + "http 0.2.9", + "http-body", + "httparse 1.8.0", + "httpdate", + "itoa 1.0.9", + "pin-project-lite 0.2.10", + "socket2 0.4.9", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "hyper-multipart-rfc7578" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3538ce6aeb81f7cd0d547a42435944d2283714a3f696630318bc47bd839fcfc9" +dependencies = [ + "bytes 1.4.0", + "common-multipart-rfc7578", + "futures 0.3.28", + "http 0.2.9", + "hyper", +] + +[[package]] +name = "hyper-rustls" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f9f7a97316d44c0af9b0301e65010573a853a9fc97046d7331d7f6bc0fd5a64" +dependencies = [ + "ct-logs", + "futures-util 0.3.28", + "hyper", + "log 0.4.20", + "rustls 0.19.1", + "rustls-native-certs 0.5.0", + "tokio", + "tokio-rustls 0.22.0", + "webpki 0.21.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "hyper-rustls" +version = "0.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1788965e61b367cd03a62950836d5cd41560c3577d90e40e0819373194d1661c" +dependencies = [ + "http 0.2.9", + "hyper", + "log 0.4.20", + "rustls 0.20.8", + "rustls-native-certs 0.6.3", + "tokio", + "tokio-rustls 0.23.4", +] + +[[package]] +name = "hyper-tls" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" +dependencies = [ + "bytes 1.4.0", + "hyper", + "native-tls", + "tokio", + "tokio-native-tls", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fad5b825842d2b38bd206f3e81d6957625fd7f0a361e345c30e01a0ae2dd613" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows 0.48.0", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "idna" +version = "0.2.0" +source = "git+https://github.com/mesalock-linux/rust-url-sgx?tag=sgx_1.1.3#23832f3191456c2d4a0faab10952e1747be58ca8" +dependencies = [ + "matches 0.1.8", + "sgx_tstd", + "unicode-bidi 0.3.4", + "unicode-normalization 0.1.12", +] + +[[package]] +name = "idna" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" +dependencies = [ + "matches 0.1.10", + "unicode-bidi 0.3.13", + "unicode-normalization 0.1.22", +] + +[[package]] +name = "idna" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" +dependencies = [ + "unicode-bidi 0.3.13", + "unicode-normalization 0.1.22", +] + +[[package]] +name = "if-addrs" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbc0fa01ffc752e9dbc72818cdb072cd028b86be5e09dd04c5a643704fe101a9" +dependencies = [ + "libc", + "winapi 0.3.9", +] + +[[package]] +name = "if-watch" +version = "3.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9465340214b296cd17a0009acdb890d6160010b8adf8f78a00d0d7ab270f79f" +dependencies = [ + "async-io", + "core-foundation", + "fnv 1.0.7", + "futures 0.3.28", + "if-addrs", + "ipnet", + "log 0.4.20", + "rtnetlink", + "system-configuration", + "tokio", + "windows 0.34.0", +] + +[[package]] +name = "impl-codec" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba6a270039626615617f3f36d15fc827041df3b78c439da2cadfa47455a77f2f" +dependencies = [ + "parity-scale-codec", +] + +[[package]] +name = "impl-rlp" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f28220f89297a075ddc7245cd538076ee98b01f2a9c23a53a4f1105d5a322808" +dependencies = [ + "rlp", +] + +[[package]] +name = "impl-serde" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc88fc67028ae3db0c853baa36269d398d5f45b6982f95549ff5def78c935cd" +dependencies = [ + "serde 1.0.193", +] + +[[package]] +name = "impl-trait-for-tuples" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "indexmap" +version = "1.6.1" +source = "git+https://github.com/mesalock-linux/indexmap-sgx#19f52458ba64dd7349a5d3a62227619a17e4db85" +dependencies = [ + "autocfg 1.1.0", + "hashbrown 0.9.1", + "sgx_tstd", +] + +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg 1.1.0", + "hashbrown 0.12.3", + "serde 1.0.193", +] + +[[package]] +name = "indexmap" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d" +dependencies = [ + "equivalent", + "hashbrown 0.14.0", +] + +[[package]] +name = "inout" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" +dependencies = [ + "generic-array 0.14.7", +] + +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if 1.0.0", +] + +[[package]] +name = "integer-encoding" +version = "3.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8bb03732005da905c88227371639bf1ad885cc712789c011c31c5fb3ab3ccf02" + +[[package]] +name = "integer-sqrt" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "276ec31bcb4a9ee45f58bec6f9ec700ae4cf4f4f8f2fa7e06cb406bd5ffdd770" +dependencies = [ + "num-traits 0.2.16", +] + +[[package]] +name = "interceptor" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e8a11ae2da61704edada656798b61c94b35ecac2c58eb955156987d5e6be90b" +dependencies = [ + "async-trait", + "bytes 1.4.0", + "log 0.4.20", + "rand 0.8.5", + "rtcp", + "rtp", + "thiserror 1.0.44", + "tokio", + "waitgroup", + "webrtc-srtp", + "webrtc-util", +] + +[[package]] +name = "io-lifetimes" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" +dependencies = [ + "hermit-abi 0.3.2", + "libc", + "windows-sys 0.48.0", +] + +[[package]] +name = "iovec" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" +dependencies = [ + "libc", +] + +[[package]] +name = "iovec" +version = "0.1.4" +source = "git+https://github.com/mesalock-linux/iovec-sgx#5c2f8e81925b4c06c556d856f3237461b00e27c9" +dependencies = [ + "sgx_libc", +] + +[[package]] +name = "ip_network" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa2f047c0a98b2f299aa5d6d7088443570faae494e9ae1305e48be000c9e0eb1" + +[[package]] +name = "ipconfig" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b58db92f96b720de98181bbbe63c831e87005ab460c1bf306eb2622b4707997f" +dependencies = [ + "socket2 0.5.3", + "widestring", + "windows-sys 0.48.0", + "winreg", +] + +[[package]] +name = "ipfs-api" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c3824538e42e84c792988098df4ad5a35b47be98b19e31454e09f4e322f00fc" +dependencies = [ + "bytes 1.4.0", + "dirs", + "failure", + "futures 0.3.28", + "http 0.2.9", + "hyper", + "hyper-multipart-rfc7578", + "hyper-tls", + "parity-multiaddr", + "serde 1.0.193", + "serde_json 1.0.103", + "serde_urlencoded", + "tokio", + "tokio-util 0.6.10", + "tracing", + "typed-builder", + "walkdir", +] + +[[package]] +name = "ipnet" +version = "2.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12b6ee2129af8d4fb011108c73d99a1b83a85977f23b82460c0ae2e25bb4b57f" + +[[package]] +name = "is-terminal" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" +dependencies = [ + "hermit-abi 0.3.2", + "rustix 0.38.4", + "windows-sys 0.48.0", +] + +[[package]] +name = "ita-oracle" +version = "0.9.0" +dependencies = [ + "itc-rest-client", + "itp-enclave-metrics", + "itp-ocall-api", + "lazy_static", + "log 0.4.20", + "parity-scale-codec", + "serde 1.0.193", + "sgx_tstd", + "substrate-fixed 0.5.9 (git+https://github.com/encointer/substrate-fixed?tag=v0.5.9)", + "thiserror 1.0.44", + "thiserror 1.0.9", + "url 2.1.1", + "url 2.4.0", +] + +[[package]] +name = "ita-parentchain-interface" +version = "0.9.0" +dependencies = [ + "bs58", + "env_logger 0.9.3", + "ita-sgx-runtime", + "ita-stf", + "itc-parentchain-indirect-calls-executor", + "itc-parentchain-test", + "itp-api-client-types", + "itp-node-api", + "itp-sgx-crypto", + "itp-stf-executor", + "itp-stf-primitives", + "itp-test", + "itp-top-pool-author", + "itp-types", + "itp-utils", + "lc-scheduled-enclave", + "litentry-primitives", + "log 0.4.20", + "parity-scale-codec", + "sgx_tstd", + "sp-core", + "sp-runtime", + "sp-std 5.0.0", +] + +[[package]] +name = "ita-sgx-runtime" +version = "0.9.0" +dependencies = [ + "frame-executive", + "frame-support", + "frame-system", + "itp-sgx-runtime-primitives", + "pallet-balances", + "pallet-evm 6.0.0-dev (git+https://github.com/integritee-network/frontier.git?branch=bar/polkadot-v0.9.42)", + "pallet-parentchain", + "pallet-sudo", + "pallet-timestamp", + "pallet-transaction-payment", + "parity-scale-codec", + "scale-info", + "sp-api", + "sp-core", + "sp-runtime", + "sp-std 5.0.0", + "sp-version", +] + +[[package]] +name = "ita-stf" +version = "0.9.0" +dependencies = [ + "frame-support", + "frame-system", + "hex", + "hex-literal", + "ita-sgx-runtime", + "itp-hashing", + "itp-node-api", + "itp-node-api-metadata", + "itp-node-api-metadata-provider", + "itp-sgx-externalities", + "itp-stf-interface", + "itp-stf-primitives", + "itp-storage", + "itp-types", + "itp-utils", + "litentry-primitives", + "log 0.4.20", + "pallet-balances", + "pallet-parentchain", + "pallet-sudo", + "parity-scale-codec", + "rlp", + "sgx_tstd", + "sha3", + "sp-core", + "sp-io 7.0.0", + "sp-keyring", + "sp-runtime", + "sp-std 5.0.0", +] + +[[package]] +name = "itc-direct-rpc-client" +version = "0.1.0" +dependencies = [ + "itp-rpc", + "itp-types", + "itp-utils", + "litentry-primitives", + "log 0.4.20", + "parity-scale-codec", + "rustls 0.19.0 (git+https://github.com/mesalock-linux/rustls?tag=sgx_1.1.3)", + "rustls 0.19.1", + "serde_json 1.0.103", + "sgx_tstd", + "tungstenite 0.14.0", + "tungstenite 0.15.0", + "url 2.1.1", + "url 2.4.0", + "webpki 0.21.4 (registry+https://github.com/rust-lang/crates.io-index)", + "webpki 0.21.4 (git+https://github.com/mesalock-linux/webpki?branch=mesalock_sgx)", +] + +[[package]] +name = "itc-direct-rpc-server" +version = "0.9.0" +dependencies = [ + "itc-tls-websocket-server", + "itp-rpc", + "itp-types", + "itp-utils", + "jsonrpc-core 18.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 18.0.0 (git+https://github.com/scs/jsonrpc?branch=no_std_v18)", + "log 0.4.20", + "parity-scale-codec", + "serde_json 1.0.103", + "sgx_tstd", + "sp-runtime", + "thiserror 1.0.44", + "thiserror 1.0.9", +] + +[[package]] +name = "itc-offchain-worker-executor" +version = "0.9.0" +dependencies = [ + "itc-parentchain-light-client", + "itp-extrinsics-factory", + "itp-sgx-externalities", + "itp-stf-executor", + "itp-stf-interface", + "itp-stf-primitives", + "itp-stf-state-handler", + "itp-test", + "itp-top-pool-author", + "itp-types", + "log 0.4.20", + "parity-scale-codec", + "sgx_tstd", + "sp-core", + "sp-runtime", + "thiserror 1.0.44", + "thiserror 1.0.9", +] + +[[package]] +name = "itc-parentchain" +version = "0.9.0" +dependencies = [ + "itc-parentchain-block-import-dispatcher", + "itc-parentchain-block-importer", + "itc-parentchain-indirect-calls-executor", + "itc-parentchain-light-client", + "itp-types", + "parity-scale-codec", + "sp-runtime", +] + +[[package]] +name = "itc-parentchain-block-import-dispatcher" +version = "0.9.0" +dependencies = [ + "itc-parentchain-block-importer", + "itp-import-queue", + "log 0.4.20", + "sgx_tstd", + "sgx_types", + "thiserror 1.0.44", + "thiserror 1.0.9", +] + +[[package]] +name = "itc-parentchain-block-importer" +version = "0.9.0" +dependencies = [ + "ita-stf", + "itc-parentchain-indirect-calls-executor", + "itc-parentchain-light-client", + "itp-enclave-metrics", + "itp-extrinsics-factory", + "itp-ocall-api", + "itp-stf-executor", + "itp-types", + "log 0.4.20", + "parity-scale-codec", + "sgx_tstd", + "sgx_types", + "sp-runtime", + "thiserror 1.0.44", + "thiserror 1.0.9", +] + +[[package]] +name = "itc-parentchain-indirect-calls-executor" +version = "0.9.0" +dependencies = [ + "binary-merkle-tree", + "bs58", + "core-primitives", + "env_logger 0.9.3", + "futures 0.3.28", + "futures 0.3.8", + "itc-parentchain-test", + "itp-api-client-types", + "itp-node-api", + "itp-sgx-crypto", + "itp-sgx-runtime-primitives", + "itp-stf-executor", + "itp-stf-primitives", + "itp-test", + "itp-top-pool-author", + "itp-types", + "itp-utils", + "lc-scheduled-enclave", + "litentry-primitives", + "log 0.4.20", + "parity-scale-codec", + "sgx_tstd", + "sgx_types", + "sp-core", + "sp-runtime", + "sp-std 5.0.0", + "thiserror 1.0.44", + "thiserror 1.0.9", +] + +[[package]] +name = "itc-parentchain-light-client" +version = "0.9.0" +dependencies = [ + "finality-grandpa", + "itc-parentchain-test", + "itp-ocall-api", + "itp-sgx-io", + "itp-sgx-temp-dir", + "itp-storage", + "itp-test", + "itp-types", + "log 0.4.20", + "parity-scale-codec", + "sgx_tstd", + "sgx_types", + "sp-consensus-grandpa", + "sp-runtime", + "thiserror 1.0.44", + "thiserror 1.0.9", +] + +[[package]] +name = "itc-parentchain-test" +version = "0.9.0" +dependencies = [ + "itp-types", + "sp-runtime", +] + +[[package]] +name = "itc-peer-top-broadcaster" +version = "0.1.0" +dependencies = [ + "itc-direct-rpc-client", + "itc-direct-rpc-server", + "itp-rpc", + "itp-stf-primitives", + "itp-types", + "itp-utils", + "litentry-primitives", + "log 0.4.20", + "sgx_tstd", +] + +[[package]] +name = "itc-rest-client" +version = "0.9.0" +dependencies = [ + "base64 0.13.1", + "http 0.2.1", + "http 0.2.9", + "http_req 0.8.1 (git+https://github.com/integritee-network/http_req?branch=master)", + "http_req 0.8.1 (git+https://github.com/integritee-network/http_req)", + "log 0.4.20", + "serde 1.0.193", + "serde_json 1.0.103", + "sgx_tstd", + "thiserror 1.0.44", + "thiserror 1.0.9", + "url 2.1.1", + "url 2.4.0", +] + +[[package]] +name = "itc-rpc-client" +version = "0.9.0" +dependencies = [ + "base58", + "env_logger 0.9.3", + "frame-metadata", + "ita-stf", + "itc-tls-websocket-server", + "itp-api-client-types", + "itp-networking-utils", + "itp-rpc", + "itp-stf-primitives", + "itp-types", + "itp-utils", + "litentry-primitives", + "log 0.4.20", + "openssl", + "parity-scale-codec", + "parking_lot 0.12.1", + "rustls 0.19.1", + "serde_json 1.0.103", + "sgx_crypto_helper", + "sp-core", + "teerex-primitives", + "thiserror 1.0.44", + "url 2.4.0", + "ws", +] + +[[package]] +name = "itc-rpc-server" +version = "0.9.0" +dependencies = [ + "anyhow", + "env_logger 0.10.0", + "itp-enclave-api", + "itp-rpc", + "itp-utils", + "its-peer-fetch", + "its-primitives", + "its-rpc-handler", + "its-storage", + "its-test", + "jsonrpsee 0.2.0", + "log 0.4.20", + "parity-scale-codec", + "sp-core", + "tokio", +] + +[[package]] +name = "itc-tls-websocket-server" +version = "0.9.0" +dependencies = [ + "bit-vec", + "chrono 0.4.26", + "env_logger 0.9.3", + "log 0.4.20", + "mio 0.6.21", + "mio 0.6.23", + "mio-extras 2.0.6 (git+https://github.com/integritee-network/mio-extras-sgx?rev=963234b)", + "rcgen 0.9.2", + "rustls 0.19.0 (git+https://github.com/mesalock-linux/rustls?branch=mesalock_sgx)", + "rustls 0.19.1", + "sgx_tstd", + "sp-core", + "thiserror 1.0.44", + "thiserror 1.0.9", + "tungstenite 0.14.0", + "tungstenite 0.15.0", + "url 2.4.0", + "webpki 0.21.4 (registry+https://github.com/rust-lang/crates.io-index)", + "webpki 0.21.4 (git+https://github.com/mesalock-linux/webpki?branch=mesalock_sgx)", + "yasna 0.3.1", + "yasna 0.4.0", +] + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "0.4.5" +source = "git+https://github.com/mesalock-linux/itoa-sgx#295ee451f5ec74f25c299552b481beb445ea3eb7" +dependencies = [ + "sgx_tstd", +] + +[[package]] +name = "itoa" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" + +[[package]] +name = "itp-api-client-extensions" +version = "0.9.0" +dependencies = [ + "hex", + "itp-api-client-types", + "itp-types", + "sp-consensus-grandpa", + "sp-core", + "sp-runtime", + "substrate-api-client", +] + +[[package]] +name = "itp-api-client-types" +version = "0.9.0" +dependencies = [ + "itp-types", + "rococo-parachain-runtime", + "sp-runtime", + "substrate-api-client", +] + +[[package]] +name = "itp-attestation-handler" +version = "0.8.0" +dependencies = [ + "arrayvec 0.7.4", + "base64 0.13.0 (git+https://github.com/mesalock-linux/rust-base64-sgx?rev=sgx_1.1.3)", + "base64 0.13.1", + "bit-vec", + "chrono 0.4.11", + "chrono 0.4.26", + "hex", + "httparse 1.4.1", + "itertools 0.10.5", + "itp-ocall-api", + "itp-settings", + "itp-sgx-crypto", + "itp-sgx-io", + "itp-time-utils", + "log 0.4.20", + "num-bigint 0.2.5", + "parity-scale-codec", + "rustls 0.19.0 (git+https://github.com/mesalock-linux/rustls?rev=sgx_1.1.3)", + "rustls 0.19.1", + "serde_json 1.0.103", + "serde_json 1.0.60 (git+https://github.com/mesalock-linux/serde-json-sgx?tag=sgx_1.1.3)", + "sgx_rand", + "sgx_tcrypto", + "sgx_tse", + "sgx_tstd", + "sgx_types", + "sp-core", + "thiserror 1.0.44", + "thiserror 1.0.9", + "webpki 0.21.4 (registry+https://github.com/rust-lang/crates.io-index)", + "webpki 0.21.4 (git+https://github.com/mesalock-linux/webpki?branch=mesalock_sgx)", + "webpki-roots 0.21.0 (git+https://github.com/mesalock-linux/webpki-roots?branch=mesalock_sgx)", + "yasna 0.3.1", +] + +[[package]] +name = "itp-component-container" +version = "0.8.0" +dependencies = [ + "sgx_tstd", + "thiserror 1.0.44", + "thiserror 1.0.9", +] + +[[package]] +name = "itp-enclave-api" +version = "0.9.0" +dependencies = [ + "frame-support", + "hex", + "itc-parentchain", + "itp-enclave-api-ffi", + "itp-settings", + "itp-storage", + "itp-types", + "log 0.4.20", + "parity-scale-codec", + "serde_json 1.0.103", + "sgx_crypto_helper", + "sgx_types", + "sgx_urts", + "sp-core", + "sp-runtime", + "teerex-primitives", + "thiserror 1.0.44", +] + +[[package]] +name = "itp-enclave-api-ffi" +version = "0.9.0" +dependencies = [ + "sgx_types", +] + +[[package]] +name = "itp-enclave-metrics" +version = "0.9.0" +dependencies = [ + "parity-scale-codec", + "sgx_tstd", + "substrate-fixed 0.5.9 (git+https://github.com/encointer/substrate-fixed?tag=v0.5.9)", +] + +[[package]] +name = "itp-extrinsics-factory" +version = "0.9.0" +dependencies = [ + "itp-node-api", + "itp-nonce-cache", + "itp-types", + "log 0.4.20", + "parity-scale-codec", + "sgx_tstd", + "sgx_types", + "sp-core", + "sp-runtime", + "substrate-api-client", + "thiserror 1.0.44", + "thiserror 1.0.9", +] + +[[package]] +name = "itp-hashing" +version = "0.9.0" +dependencies = [ + "sp-core", +] + +[[package]] +name = "itp-import-queue" +version = "0.8.0" +dependencies = [ + "sgx_tstd", + "sgx_types", + "thiserror 1.0.44", + "thiserror 1.0.9", +] + +[[package]] +name = "itp-networking-utils" +version = "0.9.0" +dependencies = [ + "sgx_tstd", +] + +[[package]] +name = "itp-node-api" +version = "0.9.0" +dependencies = [ + "itp-api-client-extensions", + "itp-api-client-types", + "itp-node-api-factory", + "itp-node-api-metadata", + "itp-node-api-metadata-provider", +] + +[[package]] +name = "itp-node-api-factory" +version = "0.9.0" +dependencies = [ + "itp-api-client-types", + "sp-core", + "thiserror 1.0.44", +] + +[[package]] +name = "itp-node-api-metadata" +version = "0.9.0" +dependencies = [ + "derive_more", + "itp-api-client-types", + "itp-stf-primitives", + "parity-scale-codec", + "sp-core", +] + +[[package]] +name = "itp-node-api-metadata-provider" +version = "0.9.0" +dependencies = [ + "itp-node-api-metadata", + "itp-stf-primitives", + "sgx_tstd", + "thiserror 1.0.44", + "thiserror 1.0.9", +] + +[[package]] +name = "itp-nonce-cache" +version = "0.8.0" +dependencies = [ + "sgx_tstd", + "thiserror 1.0.44", + "thiserror 1.0.9", +] + +[[package]] +name = "itp-ocall-api" +version = "0.9.0" +dependencies = [ + "derive_more", + "itp-storage", + "itp-types", + "parity-scale-codec", + "sgx_types", + "sp-core", + "sp-runtime", + "sp-std 5.0.0", +] + +[[package]] +name = "itp-primitives-cache" +version = "0.9.0" +dependencies = [ + "lazy_static", + "sgx_tstd", + "thiserror 1.0.44", + "thiserror 1.0.9", +] + +[[package]] +name = "itp-rpc" +version = "0.9.0" +dependencies = [ + "itp-types", + "parity-scale-codec", + "serde 1.0.193", + "serde_json 1.0.103", + "sgx_tstd", +] + +[[package]] +name = "itp-settings" +version = "0.9.0" + +[[package]] +name = "itp-sgx-crypto" +version = "0.9.0" +dependencies = [ + "aes 0.6.0", + "derive_more", + "itp-sgx-io", + "itp-sgx-temp-dir", + "log 0.4.20", + "ofb", + "parity-scale-codec", + "serde_json 1.0.103", + "serde_json 1.0.60 (git+https://github.com/mesalock-linux/serde-json-sgx?tag=sgx_1.1.3)", + "sgx_crypto_helper", + "sgx_rand", + "sgx_tstd", + "sgx_types", + "sp-core", +] + +[[package]] +name = "itp-sgx-externalities" +version = "0.9.0" +dependencies = [ + "derive_more", + "environmental 1.1.3", + "itp-hashing", + "itp-storage", + "log 0.4.20", + "parity-scale-codec", + "postcard", + "serde 1.0.193", + "sgx_tstd", + "sp-core", +] + +[[package]] +name = "itp-sgx-io" +version = "0.8.0" +dependencies = [ + "sgx_tstd", +] + +[[package]] +name = "itp-sgx-runtime-primitives" +version = "0.9.0" +dependencies = [ + "frame-system", + "litentry-primitives", + "pallet-balances", + "sp-core", + "sp-runtime", +] + +[[package]] +name = "itp-sgx-temp-dir" +version = "0.1.0" +dependencies = [ + "lazy_static", + "safe-lock", + "sgx_tstd", +] + +[[package]] +name = "itp-stf-executor" +version = "0.9.0" +dependencies = [ + "hex", + "itc-parentchain-test", + "itp-enclave-metrics", + "itp-node-api", + "itp-ocall-api", + "itp-sgx-crypto", + "itp-sgx-externalities", + "itp-stf-interface", + "itp-stf-primitives", + "itp-stf-state-handler", + "itp-stf-state-observer", + "itp-test", + "itp-time-utils", + "itp-top-pool", + "itp-top-pool-author", + "itp-types", + "litentry-primitives", + "log 0.4.20", + "parity-scale-codec", + "sgx_tstd", + "sgx_types", + "sp-core", + "sp-runtime", + "thiserror 1.0.44", + "thiserror 1.0.9", +] + +[[package]] +name = "itp-stf-interface" +version = "0.8.0" +dependencies = [ + "itp-node-api-metadata", + "itp-node-api-metadata-provider", + "itp-stf-primitives", + "itp-types", + "parity-scale-codec", +] + +[[package]] +name = "itp-stf-primitives" +version = "0.9.0" +dependencies = [ + "derive_more", + "itp-sgx-runtime-primitives", + "litentry-primitives", + "parity-scale-codec", + "sp-core", + "sp-runtime", + "sp-std 5.0.0", +] + +[[package]] +name = "itp-stf-state-handler" +version = "0.9.0" +dependencies = [ + "itp-hashing", + "itp-settings", + "itp-sgx-crypto", + "itp-sgx-externalities", + "itp-sgx-io", + "itp-sgx-temp-dir", + "itp-stf-interface", + "itp-stf-state-observer", + "itp-time-utils", + "itp-types", + "log 0.4.20", + "parity-scale-codec", + "rust-base58 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "rust-base58 0.0.4 (git+https://github.com/mesalock-linux/rust-base58-sgx?rev=sgx_1.1.3)", + "sgx_tstd", + "sgx_types", + "sp-core", + "thiserror 1.0.44", + "thiserror 1.0.9", +] + +[[package]] +name = "itp-stf-state-observer" +version = "0.9.0" +dependencies = [ + "itp-types", + "log 0.4.20", + "sgx_tstd", + "thiserror 1.0.44", + "thiserror 1.0.9", +] + +[[package]] +name = "itp-storage" +version = "0.9.0" +dependencies = [ + "derive_more", + "frame-metadata", + "frame-support", + "hash-db 0.15.2", + "itp-types", + "parity-scale-codec", + "sgx_tstd", + "sp-core", + "sp-runtime", + "sp-state-machine", + "sp-std 5.0.0", + "sp-trie", + "thiserror 1.0.44", + "thiserror 1.0.9", +] + +[[package]] +name = "itp-teerex-storage" +version = "0.9.0" +dependencies = [ + "itp-storage", + "sp-std 5.0.0", +] + +[[package]] +name = "itp-test" +version = "0.9.0" +dependencies = [ + "hex", + "itp-node-api", + "itp-node-api-metadata-provider", + "itp-ocall-api", + "itp-sgx-crypto", + "itp-sgx-externalities", + "itp-stf-interface", + "itp-stf-primitives", + "itp-stf-state-handler", + "itp-storage", + "itp-teerex-storage", + "itp-time-utils", + "itp-types", + "jsonrpc-core 18.0.0 (git+https://github.com/scs/jsonrpc?branch=no_std_v18)", + "litentry-primitives", + "log 0.4.20", + "parity-scale-codec", + "sgx_crypto_helper", + "sgx_tstd", + "sgx_types", + "sp-core", + "sp-io 7.0.0", + "sp-runtime", + "sp-std 5.0.0", +] + +[[package]] +name = "itp-time-utils" +version = "0.9.0" +dependencies = [ + "chrono 0.4.11", + "chrono 0.4.26", + "sgx_tstd", +] + +[[package]] +name = "itp-top-pool" +version = "0.9.0" +dependencies = [ + "byteorder 1.4.3", + "derive_more", + "itc-direct-rpc-server", + "itp-stf-primitives", + "itp-test", + "itp-types", + "its-primitives", + "jsonrpc-core 18.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 18.0.0 (git+https://github.com/scs/jsonrpc?branch=no_std_v18)", + "linked-hash-map 0.5.2", + "linked-hash-map 0.5.6", + "litentry-primitives", + "log 0.4.20", + "parity-scale-codec", + "parity-util-mem", + "serde 1.0.193", + "sgx_tstd", + "sp-application-crypto", + "sp-core", + "sp-runtime", +] + +[[package]] +name = "itp-top-pool-author" +version = "0.9.0" +dependencies = [ + "derive_more", + "futures 0.3.28", + "itp-enclave-metrics", + "itp-ocall-api", + "itp-sgx-crypto", + "itp-stf-primitives", + "itp-stf-state-handler", + "itp-test", + "itp-top-pool", + "itp-types", + "itp-utils", + "jsonrpc-core 18.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 18.0.0 (git+https://github.com/scs/jsonrpc?branch=no_std_v18)", + "lazy_static", + "litentry-primitives", + "log 0.4.20", + "parity-scale-codec", + "sgx_crypto_helper", + "sgx_tstd", + "sp-core", + "sp-keyring", + "sp-runtime", +] + +[[package]] +name = "itp-types" +version = "0.9.0" +dependencies = [ + "frame-system", + "itp-sgx-crypto", + "itp-sgx-runtime-primitives", + "itp-stf-primitives", + "itp-utils", + "litentry-primitives", + "pallet-balances", + "parity-scale-codec", + "sp-core", + "sp-runtime", + "sp-std 5.0.0", + "substrate-api-client", +] + +[[package]] +name = "itp-utils" +version = "0.9.0" +dependencies = [ + "hex", + "parity-scale-codec", +] + +[[package]] +name = "its-block-composer" +version = "0.9.0" +dependencies = [ + "itp-node-api", + "itp-settings", + "itp-sgx-crypto", + "itp-sgx-externalities", + "itp-stf-executor", + "itp-stf-primitives", + "itp-time-utils", + "itp-top-pool-author", + "itp-types", + "its-primitives", + "its-state", + "log 0.4.20", + "parity-scale-codec", + "sgx_tstd", + "sgx_types", + "sp-core", + "sp-runtime", + "thiserror 1.0.44", + "thiserror 1.0.9", +] + +[[package]] +name = "its-block-verification" +version = "0.9.0" +dependencies = [ + "frame-support", + "itc-parentchain-test", + "itp-types", + "itp-utils", + "its-primitives", + "its-test", + "log 0.4.20", + "sgx_tstd", + "sp-consensus-slots", + "sp-core", + "sp-keyring", + "sp-runtime", + "thiserror 1.0.44", + "thiserror 1.0.9", +] + +[[package]] +name = "its-consensus-aura" +version = "0.9.0" +dependencies = [ + "env_logger 0.9.3", + "finality-grandpa", + "ita-stf", + "itc-parentchain-block-import-dispatcher", + "itc-parentchain-test", + "itc-peer-top-broadcaster", + "itp-enclave-metrics", + "itp-ocall-api", + "itp-settings", + "itp-sgx-crypto", + "itp-sgx-externalities", + "itp-stf-executor", + "itp-stf-primitives", + "itp-stf-state-handler", + "itp-storage", + "itp-test", + "itp-time-utils", + "itp-top-pool-author", + "itp-types", + "itp-utils", + "its-block-composer", + "its-block-verification", + "its-consensus-common", + "its-consensus-slots", + "its-primitives", + "its-state", + "its-test", + "its-validateer-fetch", + "lc-scheduled-enclave", + "log 0.4.20", + "parity-scale-codec", + "sgx_tstd", + "sp-core", + "sp-keyring", + "sp-runtime", +] + +[[package]] +name = "its-consensus-common" +version = "0.9.0" +dependencies = [ + "fork-tree 3.0.0", + "itc-parentchain-light-client", + "itc-parentchain-test", + "itp-enclave-metrics", + "itp-extrinsics-factory", + "itp-import-queue", + "itp-node-api-metadata", + "itp-node-api-metadata-provider", + "itp-ocall-api", + "itp-settings", + "itp-sgx-crypto", + "itp-sgx-externalities", + "itp-test", + "itp-types", + "its-block-verification", + "its-primitives", + "its-state", + "its-test", + "log 0.4.20", + "parity-scale-codec", + "sgx_tstd", + "sgx_types", + "sp-core", + "sp-runtime", + "thiserror 1.0.44", + "thiserror 1.0.9", +] + +[[package]] +name = "its-consensus-slots" +version = "0.9.0" +dependencies = [ + "derive_more", + "futures-timer", + "hex", + "itc-parentchain-test", + "itp-settings", + "itp-sgx-externalities", + "itp-stf-state-handler", + "itp-test", + "itp-time-utils", + "itp-types", + "its-block-verification", + "its-consensus-common", + "its-primitives", + "its-state", + "its-test", + "lazy_static", + "lc-scheduled-enclave", + "log 0.4.20", + "parity-scale-codec", + "sgx_tstd", + "sp-consensus-slots", + "sp-keyring", + "sp-runtime", + "tokio", +] + +[[package]] +name = "its-peer-fetch" +version = "0.9.0" +dependencies = [ + "anyhow", + "async-trait", + "itc-rpc-client", + "itp-node-api", + "itp-test", + "its-primitives", + "its-rpc-handler", + "its-storage", + "its-test", + "jsonrpsee 0.2.0", + "log 0.4.20", + "serde 1.0.193", + "serde_json 1.0.103", + "thiserror 1.0.44", + "tokio", +] + +[[package]] +name = "its-primitives" +version = "0.1.0" +dependencies = [ + "itp-types", + "parity-scale-codec", + "scale-info", + "serde 1.0.193", + "sp-core", + "sp-runtime", + "sp-std 5.0.0", +] + +[[package]] +name = "its-rpc-handler" +version = "0.9.0" +dependencies = [ + "futures 0.3.28", + "futures 0.3.8", + "itp-rpc", + "itp-stf-primitives", + "itp-top-pool-author", + "itp-types", + "itp-utils", + "its-primitives", + "jsonrpc-core 18.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 18.0.0 (git+https://github.com/scs/jsonrpc?branch=no_std_v18)", + "litentry-primitives", + "log 0.4.20", + "parity-scale-codec", + "rust-base58 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "rust-base58 0.0.4 (git+https://github.com/mesalock-linux/rust-base58-sgx?rev=sgx_1.1.3)", + "sgx_tstd", + "sp-core", +] + +[[package]] +name = "its-sidechain" +version = "0.9.0" +dependencies = [ + "its-block-composer", + "its-consensus-aura", + "its-consensus-common", + "its-consensus-slots", + "its-primitives", + "its-rpc-handler", + "its-state", + "its-validateer-fetch", +] + +[[package]] +name = "its-state" +version = "0.9.0" +dependencies = [ + "frame-support", + "itp-sgx-externalities", + "itp-storage", + "its-primitives", + "log 0.4.20", + "parity-scale-codec", + "sgx_tstd", + "sp-core", + "sp-io 7.0.0", + "sp-runtime", + "thiserror 1.0.44", + "thiserror 1.0.9", +] + +[[package]] +name = "its-storage" +version = "0.9.0" +dependencies = [ + "itp-settings", + "itp-time-utils", + "itp-types", + "its-primitives", + "its-test", + "log 0.4.20", + "mockall", + "parity-scale-codec", + "parking_lot 0.12.1", + "rocksdb", + "serde 1.0.193", + "sp-core", + "temp-dir", + "thiserror 1.0.44", +] + +[[package]] +name = "its-test" +version = "0.9.0" +dependencies = [ + "itp-types", + "its-primitives", + "sgx_tstd", + "sp-core", +] + +[[package]] +name = "its-validateer-fetch" +version = "0.9.0" +dependencies = [ + "derive_more", + "frame-support", + "itc-parentchain-test", + "itp-ocall-api", + "itp-teerex-storage", + "itp-test", + "itp-types", + "parity-scale-codec", + "sp-core", + "sp-runtime", + "sp-std 5.0.0", +] + +[[package]] +name = "jobserver" +version = "0.1.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "936cfd212a0155903bcbc060e316fb6cc7cbf2e1907329391ebadc1fe0ce77c2" +dependencies = [ + "libc", +] + +[[package]] +name = "js-sys" +version = "0.3.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "json5" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96b0db21af676c1ce64250b5f40f3ce2cf27e4e47cb91ed91eb6fe9350b430c1" +dependencies = [ + "pest", + "pest_derive", + "serde 1.0.193", +] + +[[package]] +name = "jsonrpc-core" +version = "18.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14f7f76aef2d054868398427f6c54943cf3d1caa9a7ec7d0c38d69df97a965eb" +dependencies = [ + "futures 0.3.28", + "futures-executor 0.3.28", + "futures-util 0.3.28", + "log 0.4.20", + "serde 1.0.193", + "serde_derive 1.0.193", + "serde_json 1.0.103", +] + +[[package]] +name = "jsonrpc-core" +version = "18.0.0" +source = "git+https://github.com/scs/jsonrpc?branch=no_std_v18#0faf53c491c3222b96242a973d902dd06e9b6674" +dependencies = [ + "futures 0.3.8", + "log 0.4.14 (git+https://github.com/mesalock-linux/log-sgx)", + "serde 1.0.118", + "serde_derive 1.0.118", + "serde_json 1.0.60 (git+https://github.com/mesalock-linux/serde-json-sgx)", +] + +[[package]] +name = "jsonrpsee" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "316a89048d2ea5530ab5502aa31e1128f6429b524a37e4c0bc54903bcdf3d342" +dependencies = [ + "jsonrpsee-http-client", + "jsonrpsee-http-server", + "jsonrpsee-proc-macros 0.2.0", + "jsonrpsee-types 0.2.0", + "jsonrpsee-utils", + "jsonrpsee-ws-client", + "jsonrpsee-ws-server", +] + +[[package]] +name = "jsonrpsee" +version = "0.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d291e3a5818a2384645fd9756362e6d89cf0541b0b916fa7702ea4a9833608e" +dependencies = [ + "jsonrpsee-core", + "jsonrpsee-proc-macros 0.16.2", + "jsonrpsee-server", + "jsonrpsee-types 0.16.2", + "tracing", +] + +[[package]] +name = "jsonrpsee-core" +version = "0.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4e70b4439a751a5de7dd5ed55eacff78ebf4ffe0fc009cb1ebb11417f5b536b" +dependencies = [ + "anyhow", + "arrayvec 0.7.4", + "async-trait", + "beef", + "futures-channel 0.3.28", + "futures-util 0.3.28", + "globset", + "hyper", + "jsonrpsee-types 0.16.2", + "parking_lot 0.12.1", + "rand 0.8.5", + "rustc-hash", + "serde 1.0.193", + "serde_json 1.0.103", + "soketto 0.7.1", + "thiserror 1.0.44", + "tokio", + "tracing", +] + +[[package]] +name = "jsonrpsee-http-client" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7275601ba6f9f6feaa82d3c66b51e34d190e75f1cf23d5c40f7801f3a7610a6" +dependencies = [ + "async-trait", + "fnv 1.0.7", + "hyper", + "hyper-rustls 0.22.1", + "jsonrpsee-types 0.2.0", + "jsonrpsee-utils", + "log 0.4.20", + "serde 1.0.193", + "serde_json 1.0.103", + "thiserror 1.0.44", + "url 2.4.0", +] + +[[package]] +name = "jsonrpsee-http-server" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d22372378f63f7d16de453e786afc740fca5ee80bd260be024a616b6ac2cefe5" +dependencies = [ + "futures-channel 0.3.28", + "futures-util 0.3.28", + "globset", + "hyper", + "jsonrpsee-types 0.2.0", + "jsonrpsee-utils", + "lazy_static", + "log 0.4.20", + "serde 1.0.193", + "serde_json 1.0.103", + "socket2 0.4.9", + "thiserror 1.0.44", + "tokio", + "unicase 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "jsonrpsee-proc-macros" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b4c85cfa6767333f3e5f3b2f2f765dad2727b0033ee270ae07c599bf43ed5ae" +dependencies = [ + "Inflector", + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "jsonrpsee-proc-macros" +version = "0.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baa6da1e4199c10d7b1d0a6e5e8bd8e55f351163b6f4b3cbb044672a69bd4c1c" +dependencies = [ + "heck", + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "jsonrpsee-server" +version = "0.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fb69dad85df79527c019659a992498d03f8495390496da2f07e6c24c2b356fc" +dependencies = [ + "futures-channel 0.3.28", + "futures-util 0.3.28", + "http 0.2.9", + "hyper", + "jsonrpsee-core", + "jsonrpsee-types 0.16.2", + "serde 1.0.193", + "serde_json 1.0.103", + "soketto 0.7.1", + "tokio", + "tokio-stream", + "tokio-util 0.7.8", + "tower", + "tracing", +] + +[[package]] +name = "jsonrpsee-types" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0cf7bd4e93b3b56e59131de7f24afbea871faf914e97bcdd942c86927ab0172" +dependencies = [ + "async-trait", + "beef", + "futures-channel 0.3.28", + "futures-util 0.3.28", + "hyper", + "log 0.4.20", + "serde 1.0.193", + "serde_json 1.0.103", + "soketto 0.5.0", + "thiserror 1.0.44", +] + +[[package]] +name = "jsonrpsee-types" +version = "0.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5bd522fe1ce3702fd94812965d7bb7a3364b1c9aba743944c5a00529aae80f8c" +dependencies = [ + "anyhow", + "beef", + "serde 1.0.193", + "serde_json 1.0.103", + "thiserror 1.0.44", + "tracing", +] + +[[package]] +name = "jsonrpsee-utils" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47554ecaacb479285da68799d9b6afc258c32b332cc8b85829c6a9304ee98776" +dependencies = [ + "futures-channel 0.3.28", + "futures-util 0.3.28", + "hyper", + "jsonrpsee-types 0.2.0", + "log 0.4.20", + "parking_lot 0.11.2", + "rand 0.8.5", + "rustc-hash", + "serde 1.0.193", + "serde_json 1.0.103", + "thiserror 1.0.44", +] + +[[package]] +name = "jsonrpsee-ws-client" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ec51150965544e1a4468f372bdab8545243a1b045d4ab272023aac74c60de32" +dependencies = [ + "async-trait", + "fnv 1.0.7", + "futures 0.3.28", + "jsonrpsee-types 0.2.0", + "log 0.4.20", + "pin-project", + "rustls 0.19.1", + "rustls-native-certs 0.5.0", + "serde 1.0.193", + "serde_json 1.0.103", + "soketto 0.5.0", + "thiserror 1.0.44", + "tokio", + "tokio-rustls 0.22.0", + "tokio-util 0.6.10", + "url 2.4.0", +] + +[[package]] +name = "jsonrpsee-ws-server" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b512c3c679a89d20f97802f69188a2d01f6234491b7513076e21e8424efccafe" +dependencies = [ + "futures-channel 0.3.28", + "futures-util 0.3.28", + "jsonrpsee-types 0.2.0", + "jsonrpsee-utils", + "log 0.4.20", + "rustc-hash", + "serde 1.0.193", + "serde_json 1.0.103", + "soketto 0.5.0", + "thiserror 1.0.44", + "tokio", + "tokio-stream", + "tokio-util 0.6.10", +] + +[[package]] +name = "k256" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cadb76004ed8e97623117f3df85b17aaa6626ab0b0831e6573f104df16cd1bcc" +dependencies = [ + "cfg-if 1.0.0", + "ecdsa 0.16.8", + "elliptic-curve 0.13.5", + "once_cell 1.18.0", + "sha2 0.10.7", +] + +[[package]] +name = "keccak" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f6d5ed8676d904364de097082f4e7d240b571b67989ced0240f08b7f966f940" +dependencies = [ + "cpufeatures", +] + +[[package]] +name = "kernel32-sys" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" +dependencies = [ + "winapi 0.2.8", + "winapi-build", +] + +[[package]] +name = "kvdb" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7d770dcb02bf6835887c3a979b5107a04ff4bbde97a5f0928d27404a155add9" +dependencies = [ + "smallvec 1.11.0", +] + +[[package]] +name = "kvdb-memorydb" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf7a85fe66f9ff9cd74e169fdd2c94c6e1e74c412c99a73b4df3200b5d3760b2" +dependencies = [ + "kvdb", + "parking_lot 0.12.1", +] + +[[package]] +name = "kvdb-rocksdb" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe7a749456510c45f795e8b04a6a3e0976d0139213ecbf465843830ad55e2217" +dependencies = [ + "kvdb", + "num_cpus", + "parking_lot 0.12.1", + "regex 1.9.5", + "rocksdb", + "smallvec 1.11.0", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +dependencies = [ + "spin 0.5.2", +] + +[[package]] +name = "lazycell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + +[[package]] +name = "lc-scheduled-enclave" +version = "0.8.0" +dependencies = [ + "itp-settings", + "itp-sgx-io", + "itp-types", + "lazy_static", + "log 0.4.20", + "parity-scale-codec", + "sgx_tstd", + "sp-std 5.0.0", + "thiserror 1.0.44", + "thiserror 1.0.9", +] + +[[package]] +name = "libc" +version = "0.2.147" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" + +[[package]] +name = "libloading" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" +dependencies = [ + "cfg-if 1.0.0", + "winapi 0.3.9", +] + +[[package]] +name = "libm" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fc7aa29613bd6a620df431842069224d8bc9011086b1db4c0e0cd47fa03ec9a" + +[[package]] +name = "libm" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7012b1bbb0719e1097c47611d3898568c546d597c2e74d66f6087edd5233ff4" + +[[package]] +name = "libp2p" +version = "0.50.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c7b0104790be871edcf97db9bd2356604984e623a08d825c3f27852290266b8" +dependencies = [ + "bytes 1.4.0", + "futures 0.3.28", + "futures-timer", + "getrandom 0.2.10", + "instant", + "libp2p-core 0.38.0", + "libp2p-dns", + "libp2p-identify", + "libp2p-kad", + "libp2p-mdns", + "libp2p-metrics", + "libp2p-mplex", + "libp2p-noise", + "libp2p-ping", + "libp2p-quic", + "libp2p-request-response", + "libp2p-swarm", + "libp2p-tcp", + "libp2p-wasm-ext", + "libp2p-webrtc", + "libp2p-websocket", + "libp2p-yamux", + "multiaddr 0.16.0", + "parking_lot 0.12.1", + "pin-project", + "smallvec 1.11.0", +] + +[[package]] +name = "libp2p-core" +version = "0.38.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6a8fcd392ff67af6cc3f03b1426c41f7f26b6b9aff2dc632c1c56dd649e571f" +dependencies = [ + "asn1_der", + "bs58", + "ed25519-dalek", + "either", + "fnv 1.0.7", + "futures 0.3.28", + "futures-timer", + "instant", + "log 0.4.20", + "multiaddr 0.16.0", + "multihash 0.16.3", + "multistream-select", + "once_cell 1.18.0", + "parking_lot 0.12.1", + "pin-project", + "prost", + "prost-build", + "rand 0.8.5", + "rw-stream-sink", + "sec1 0.3.0", + "sha2 0.10.7", + "smallvec 1.11.0", + "thiserror 1.0.44", + "unsigned-varint 0.7.1", + "void", + "zeroize", +] + +[[package]] +name = "libp2p-core" +version = "0.39.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c1df63c0b582aa434fb09b2d86897fa2b419ffeccf934b36f87fcedc8e835c2" +dependencies = [ + "either", + "fnv 1.0.7", + "futures 0.3.28", + "futures-timer", + "instant", + "libp2p-identity", + "log 0.4.20", + "multiaddr 0.17.1", + "multihash 0.17.0", + "multistream-select", + "once_cell 1.18.0", + "parking_lot 0.12.1", + "pin-project", + "quick-protobuf", + "rand 0.8.5", + "rw-stream-sink", + "smallvec 1.11.0", + "thiserror 1.0.44", + "unsigned-varint 0.7.1", + "void", +] + +[[package]] +name = "libp2p-dns" +version = "0.38.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e42a271c1b49f789b92f7fc87749fa79ce5c7bdc88cbdfacb818a4bca47fec5" +dependencies = [ + "futures 0.3.28", + "libp2p-core 0.38.0", + "log 0.4.20", + "parking_lot 0.12.1", + "smallvec 1.11.0", + "trust-dns-resolver", +] + +[[package]] +name = "libp2p-identify" +version = "0.41.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c052d0026f4817b44869bfb6810f4e1112f43aec8553f2cb38881c524b563abf" +dependencies = [ + "asynchronous-codec", + "futures 0.3.28", + "futures-timer", + "libp2p-core 0.38.0", + "libp2p-swarm", + "log 0.4.20", + "lru 0.8.1", + "prost", + "prost-build", + "prost-codec", + "smallvec 1.11.0", + "thiserror 1.0.44", + "void", +] + +[[package]] +name = "libp2p-identity" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e2d584751cecb2aabaa56106be6be91338a60a0f4e420cf2af639204f596fc1" +dependencies = [ + "bs58", + "ed25519-dalek", + "log 0.4.20", + "multiaddr 0.17.1", + "multihash 0.17.0", + "quick-protobuf", + "rand 0.8.5", + "sha2 0.10.7", + "thiserror 1.0.44", + "zeroize", +] + +[[package]] +name = "libp2p-kad" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2766dcd2be8c87d5e1f35487deb22d765f49c6ae1251b3633efe3b25698bd3d2" +dependencies = [ + "arrayvec 0.7.4", + "asynchronous-codec", + "bytes 1.4.0", + "either", + "fnv 1.0.7", + "futures 0.3.28", + "futures-timer", + "instant", + "libp2p-core 0.38.0", + "libp2p-swarm", + "log 0.4.20", + "prost", + "prost-build", + "rand 0.8.5", + "sha2 0.10.7", + "smallvec 1.11.0", + "thiserror 1.0.44", + "uint", + "unsigned-varint 0.7.1", + "void", +] + +[[package]] +name = "libp2p-mdns" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04f378264aade9872d6ccd315c0accc18be3a35d15fc1b9c36e5b6f983b62b5b" +dependencies = [ + "data-encoding", + "futures 0.3.28", + "if-watch", + "libp2p-core 0.38.0", + "libp2p-swarm", + "log 0.4.20", + "rand 0.8.5", + "smallvec 1.11.0", + "socket2 0.4.9", + "tokio", + "trust-dns-proto", + "void", +] + +[[package]] +name = "libp2p-metrics" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ad8a64f29da86005c86a4d2728b8a0719e9b192f4092b609fd8790acb9dec55" +dependencies = [ + "libp2p-core 0.38.0", + "libp2p-identify", + "libp2p-kad", + "libp2p-ping", + "libp2p-swarm", + "prometheus-client", +] + +[[package]] +name = "libp2p-mplex" +version = "0.38.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03805b44107aa013e7cbbfa5627b31c36cbedfdfb00603c0311998882bc4bace" +dependencies = [ + "asynchronous-codec", + "bytes 1.4.0", + "futures 0.3.28", + "libp2p-core 0.38.0", + "log 0.4.20", + "nohash-hasher", + "parking_lot 0.12.1", + "rand 0.8.5", + "smallvec 1.11.0", + "unsigned-varint 0.7.1", +] + +[[package]] +name = "libp2p-noise" +version = "0.41.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a978cb57efe82e892ec6f348a536bfbd9fee677adbe5689d7a93ad3a9bffbf2e" +dependencies = [ + "bytes 1.4.0", + "curve25519-dalek 3.2.0", + "futures 0.3.28", + "libp2p-core 0.38.0", + "log 0.4.20", + "once_cell 1.18.0", + "prost", + "prost-build", + "rand 0.8.5", + "sha2 0.10.7", + "snow", + "static_assertions", + "thiserror 1.0.44", + "x25519-dalek 1.1.1", + "zeroize", +] + +[[package]] +name = "libp2p-ping" +version = "0.41.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "929fcace45a112536e22b3dcfd4db538723ef9c3cb79f672b98be2cc8e25f37f" +dependencies = [ + "futures 0.3.28", + "futures-timer", + "instant", + "libp2p-core 0.38.0", + "libp2p-swarm", + "log 0.4.20", + "rand 0.8.5", + "void", +] + +[[package]] +name = "libp2p-quic" +version = "0.7.0-alpha" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01e7c867e95c8130667b24409d236d37598270e6da69b3baf54213ba31ffca59" +dependencies = [ + "bytes 1.4.0", + "futures 0.3.28", + "futures-timer", + "if-watch", + "libp2p-core 0.38.0", + "libp2p-tls", + "log 0.4.20", + "parking_lot 0.12.1", + "quinn-proto", + "rand 0.8.5", + "rustls 0.20.8", + "thiserror 1.0.44", + "tokio", +] + +[[package]] +name = "libp2p-request-response" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3236168796727bfcf4927f766393415361e2c644b08bedb6a6b13d957c9a4884" +dependencies = [ + "async-trait", + "bytes 1.4.0", + "futures 0.3.28", + "instant", + "libp2p-core 0.38.0", + "libp2p-swarm", + "log 0.4.20", + "rand 0.8.5", + "smallvec 1.11.0", + "unsigned-varint 0.7.1", +] + +[[package]] +name = "libp2p-swarm" +version = "0.41.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2a35472fe3276b3855c00f1c032ea8413615e030256429ad5349cdf67c6e1a0" +dependencies = [ + "either", + "fnv 1.0.7", + "futures 0.3.28", + "futures-timer", + "instant", + "libp2p-core 0.38.0", + "libp2p-swarm-derive", + "log 0.4.20", + "pin-project", + "rand 0.8.5", + "smallvec 1.11.0", + "thiserror 1.0.44", + "tokio", + "void", +] + +[[package]] +name = "libp2p-swarm-derive" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d527d5827582abd44a6d80c07ff8b50b4ee238a8979e05998474179e79dc400" +dependencies = [ + "heck", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "libp2p-tcp" +version = "0.38.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4b257baf6df8f2df39678b86c578961d48cc8b68642a12f0f763f56c8e5858d" +dependencies = [ + "futures 0.3.28", + "futures-timer", + "if-watch", + "libc", + "libp2p-core 0.38.0", + "log 0.4.20", + "socket2 0.4.9", + "tokio", +] + +[[package]] +name = "libp2p-tls" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff08d13d0dc66e5e9ba6279c1de417b84fa0d0adc3b03e5732928c180ec02781" +dependencies = [ + "futures 0.3.28", + "futures-rustls", + "libp2p-core 0.39.2", + "libp2p-identity", + "rcgen 0.10.0", + "ring 0.16.20", + "rustls 0.20.8", + "thiserror 1.0.44", + "webpki 0.22.0", + "x509-parser 0.14.0", + "yasna 0.5.2", +] + +[[package]] +name = "libp2p-wasm-ext" +version = "0.38.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bb1a35299860e0d4b3c02a3e74e3b293ad35ae0cee8a056363b0c862d082069" +dependencies = [ + "futures 0.3.28", + "js-sys", + "libp2p-core 0.38.0", + "parity-send-wrapper", + "wasm-bindgen", + "wasm-bindgen-futures", +] + +[[package]] +name = "libp2p-webrtc" +version = "0.4.0-alpha" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb6cd86dd68cba72308ea05de1cebf3ba0ae6e187c40548167955d4e3970f6a" +dependencies = [ + "async-trait", + "asynchronous-codec", + "bytes 1.4.0", + "futures 0.3.28", + "futures-timer", + "hex", + "if-watch", + "libp2p-core 0.38.0", + "libp2p-noise", + "log 0.4.20", + "multihash 0.16.3", + "prost", + "prost-build", + "prost-codec", + "rand 0.8.5", + "rcgen 0.9.3", + "serde 1.0.193", + "stun", + "thiserror 1.0.44", + "tinytemplate", + "tokio", + "tokio-util 0.7.8", + "webrtc", +] + +[[package]] +name = "libp2p-websocket" +version = "0.40.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d705506030d5c0aaf2882437c70dab437605f21c5f9811978f694e6917a3b54" +dependencies = [ + "either", + "futures 0.3.28", + "futures-rustls", + "libp2p-core 0.38.0", + "log 0.4.20", + "parking_lot 0.12.1", + "quicksink", + "rw-stream-sink", + "soketto 0.7.1", + "url 2.4.0", + "webpki-roots 0.22.6", +] + +[[package]] +name = "libp2p-yamux" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f63594a0aa818642d9d4915c791945053877253f08a3626f13416b5cd928a29" +dependencies = [ + "futures 0.3.28", + "libp2p-core 0.38.0", + "log 0.4.20", + "parking_lot 0.12.1", + "thiserror 1.0.44", + "yamux", +] + +[[package]] +name = "librocksdb-sys" +version = "0.10.0+7.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fe4d5874f5ff2bc616e55e8c6086d478fcda13faf9495768a4aa1c22042d30b" +dependencies = [ + "bindgen", + "bzip2-sys", + "cc", + "glob", + "libc", + "libz-sys", + "tikv-jemalloc-sys", +] + +[[package]] +name = "libsecp256k1" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95b09eff1b35ed3b33b877ced3a691fc7a481919c7e29c53c906226fcf55e2a1" +dependencies = [ + "arrayref", + "base64 0.13.1", + "digest 0.9.0", + "hmac-drbg", + "libsecp256k1-core", + "libsecp256k1-gen-ecmult", + "libsecp256k1-gen-genmult", + "rand 0.8.5", + "serde 1.0.193", + "sha2 0.9.9", + "typenum 1.16.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libsecp256k1-core" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5be9b9bb642d8522a44d533eab56c16c738301965504753b03ad1de3425d5451" +dependencies = [ + "crunchy", + "digest 0.9.0", + "subtle", +] + +[[package]] +name = "libsecp256k1-gen-ecmult" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3038c808c55c87e8a172643a7d87187fc6c4174468159cb3090659d55bcb4809" +dependencies = [ + "libsecp256k1-core", +] + +[[package]] +name = "libsecp256k1-gen-genmult" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3db8d6ba2cec9eacc40e6e8ccc98931840301f1006e95647ceb2dd5c3aa06f7c" +dependencies = [ + "libsecp256k1-core", +] + +[[package]] +name = "libz-sys" +version = "1.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24e6ab01971eb092ffe6a7d42f49f9ff42662f17604681e2843ad65077ba47dc" +dependencies = [ + "cc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "link-cplusplus" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecd207c9c713c34f95a097a5b029ac2ce6010530c7b49d7fea24d977dede04f5" +dependencies = [ + "cc", +] + +[[package]] +name = "linked-hash-map" +version = "0.5.2" +source = "git+https://github.com/mesalock-linux/linked-hash-map-sgx#03e763f7c251c16e0b85e2fb058ba47be52f2a49" +dependencies = [ + "sgx_tstd", +] + +[[package]] +name = "linked-hash-map" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" + +[[package]] +name = "linked_hash_set" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47186c6da4d81ca383c7c47c1bfc80f4b95f4720514d860a5407aaf4233f9588" +dependencies = [ + "linked-hash-map 0.5.6", +] + +[[package]] +name = "linregress" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4de0b5f52a9f84544d268f5fabb71b38962d6aa3c6600b8bcd27d44ccf9c9c45" +dependencies = [ + "nalgebra", +] + +[[package]] +name = "linux-raw-sys" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4" + +[[package]] +name = "linux-raw-sys" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" + +[[package]] +name = "linux-raw-sys" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09fc20d2ca12cb9f044c93e3bd6d32d523e6e2ec3db4f7b2939cd99026ecd3f0" + +[[package]] +name = "litentry-hex-utils" +version = "0.9.12" +dependencies = [ + "hex", +] + +[[package]] +name = "litentry-macros" +version = "0.1.0" +dependencies = [ + "cargo_toml", + "quote", +] + +[[package]] +name = "litentry-macros" +version = "0.9.12" + +[[package]] +name = "litentry-primitives" +version = "0.1.0" +dependencies = [ + "base64 0.13.0 (git+https://github.com/mesalock-linux/rust-base64-sgx?rev=sgx_1.1.3)", + "base64 0.13.1", + "bitcoin", + "core-primitives", + "hex", + "itp-sgx-crypto", + "itp-utils", + "log 0.4.20", + "pallet-evm 6.0.0-dev (git+https://github.com/integritee-network/frontier.git?branch=bar/polkadot-v0.9.42)", + "parity-scale-codec", + "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.3 (git+https://github.com/mesalock-linux/rand-sgx?tag=sgx_1.1.3)", + "ring 0.16.20", + "scale-info", + "secp256k1 0.28.0", + "serde 1.0.193", + "sgx_tstd", + "sp-core", + "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", + "sp-runtime", + "sp-std 5.0.0", + "strum 0.25.0", + "strum_macros 0.25.3", + "teerex-primitives", +] + +[[package]] +name = "litentry-proc-macros" +version = "0.9.12" +dependencies = [ + "cargo_toml", + "proc-macro2", + "quote", + "syn 2.0.32", +] + +[[package]] +name = "lock_api" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" +dependencies = [ + "autocfg 1.1.0", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.14" +source = "git+https://github.com/mesalock-linux/log-sgx?tag=sgx_1.1.3#2ca9039a9ebba0ed90ed2ad57425917d4b3a2a24" +dependencies = [ + "cfg-if 1.0.0", + "sgx_tstd", +] + +[[package]] +name = "log" +version = "0.4.14" +source = "git+https://github.com/mesalock-linux/log-sgx#2ca9039a9ebba0ed90ed2ad57425917d4b3a2a24" +dependencies = [ + "cfg-if 1.0.0", + "sgx_tstd", +] + +[[package]] +name = "log" +version = "0.4.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" + +[[package]] +name = "lru" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6e8aaa3f231bb4bd57b84b2d5dc3ae7f350265df8aa96492e0bc394a1571909" +dependencies = [ + "hashbrown 0.12.3", +] + +[[package]] +name = "lru" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71e7d46de488603ffdd5f30afbc64fbba2378214a2c3a2fb83abf3d33126df17" +dependencies = [ + "hashbrown 0.13.2", +] + +[[package]] +name = "lru-cache" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c" +dependencies = [ + "linked-hash-map 0.5.6", +] + +[[package]] +name = "lz4" +version = "1.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e9e2dd86df36ce760a60f6ff6ad526f7ba1f14ba0356f8254fb6905e6494df1" +dependencies = [ + "libc", + "lz4-sys", +] + +[[package]] +name = "lz4-sys" +version = "1.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57d27b317e207b10f69f5e75494119e391a96f48861ae870d1da6edac98ca900" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "mach" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b823e83b2affd8f40a9ee8c29dbc56404c1e34cd2710921f2801e2cf29527afa" +dependencies = [ + "libc", +] + +[[package]] +name = "match_cfg" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4" + +[[package]] +name = "matchers" +version = "0.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f099785f7595cc4b4553a174ce30dd7589ef93391ff414dbb67f62392b9e0ce1" +dependencies = [ + "regex-automata 0.1.10", +] + +[[package]] +name = "matches" +version = "0.1.8" +source = "git+https://github.com/mesalock-linux/rust-std-candidates-sgx#5747bcf37f3e18687758838da0339ff0f2c83924" + +[[package]] +name = "matches" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" + +[[package]] +name = "matrixmultiply" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "090126dc04f95dc0d1c1c91f61bdd474b3930ca064c1edc8a849da2c6cbe1e77" +dependencies = [ + "autocfg 1.1.0", + "rawpointer", +] + +[[package]] +name = "maybe-async" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f1b8c13cb1f814b634a96b2c725449fe7ed464a7b8781de8688be5ffbd3f305" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "md-5" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6365506850d44bff6e2fbcb5176cf63650e48bd45ef2fe2665ae1570e0f4b9ca" +dependencies = [ + "digest 0.10.7", +] + +[[package]] +name = "memchr" +version = "2.2.1" +source = "git+https://github.com/mesalock-linux/rust-memchr-sgx#fb51ee32766cb9a2be39b7fb2b5de26bb86dcdeb" +dependencies = [ + "sgx_libc", + "sgx_tstd", + "sgx_types", +] + +[[package]] +name = "memchr" +version = "2.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f232d6ef707e1956a43342693d2a31e72989554d58299d7a88738cc95b0d35c" + +[[package]] +name = "memfd" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffc89ccdc6e10d6907450f753537ebc5c5d3460d2e4e62ea74bd571db62c0f9e" +dependencies = [ + "rustix 0.37.23", +] + +[[package]] +name = "memmap2" +version = "0.5.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83faa42c0a078c393f6b29d5db232d8be22776a891f8f56e5284faee4a20b327" +dependencies = [ + "libc", +] + +[[package]] +name = "memoffset" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" +dependencies = [ + "autocfg 1.1.0", +] + +[[package]] +name = "memoffset" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" +dependencies = [ + "autocfg 1.1.0", +] + +[[package]] +name = "memory-db" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "808b50db46293432a45e63bc15ea51e0ab4c0a1647b8eb114e31a3e698dd6fbe" +dependencies = [ + "hash-db 0.16.0", +] + +[[package]] +name = "memory_units" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8452105ba047068f40ff7093dd1d9da90898e63dd61736462e9cdda6a90ad3c3" + +[[package]] +name = "merlin" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e261cf0f8b3c42ded9f7d2bb59dea03aa52bc8a1cbc7482f9fc3fd1229d3b42" +dependencies = [ + "byteorder 1.4.3", + "keccak", + "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "zeroize", +] + +[[package]] +name = "mick-jaeger" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69672161530e8aeca1d1400fbf3f1a1747ff60ea604265a4e906c2442df20532" +dependencies = [ + "futures 0.3.28", + "rand 0.8.5", + "thrift", +] + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "mime_guess" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef" +dependencies = [ + "mime", + "unicase 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "miniz_oxide" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +dependencies = [ + "adler", +] + +[[package]] +name = "mio" +version = "0.6.21" +source = "git+https://github.com/mesalock-linux/mio-sgx?tag=sgx_1.1.3#5b0e56a3066231c7a8d1876c7be3a19b08ffdfd5" +dependencies = [ + "iovec 0.1.4 (git+https://github.com/mesalock-linux/iovec-sgx)", + "log 0.4.14 (git+https://github.com/mesalock-linux/log-sgx)", + "net2 0.2.33", + "sgx_libc", + "sgx_trts", + "sgx_tstd", + "slab 0.4.2", +] + +[[package]] +name = "mio" +version = "0.6.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4afd66f5b91bf2a3bc13fad0e21caedac168ca4c707504e75585648ae80e4cc4" +dependencies = [ + "cfg-if 0.1.10", + "fuchsia-zircon", + "fuchsia-zircon-sys", + "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "kernel32-sys", + "libc", + "log 0.4.20", + "miow", + "net2 0.2.39", + "slab 0.4.8", + "winapi 0.2.8", +] + +[[package]] +name = "mio" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" +dependencies = [ + "libc", + "wasi 0.11.0+wasi-snapshot-preview1", + "windows-sys 0.48.0", +] + +[[package]] +name = "mio-extras" +version = "2.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52403fe290012ce777c4626790c8951324a2b9e3316b3143779c72b029742f19" +dependencies = [ + "lazycell", + "log 0.4.20", + "mio 0.6.23", + "slab 0.4.8", +] + +[[package]] +name = "mio-extras" +version = "2.0.6" +source = "git+https://github.com/integritee-network/mio-extras-sgx?rev=963234b#963234bf55e44f9efff921938255126c48deef3a" +dependencies = [ + "lazycell", + "log 0.4.20", + "mio 0.6.21", + "mio 0.6.23", + "sgx_tstd", + "sgx_types", + "slab 0.4.8", +] + +[[package]] +name = "miow" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebd808424166322d4a38da87083bfddd3ac4c131334ed55856112eb06d46944d" +dependencies = [ + "kernel32-sys", + "net2 0.2.39", + "winapi 0.2.8", + "ws2_32-sys", +] + +[[package]] +name = "mockall" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c84490118f2ee2d74570d114f3d0493cbf02790df303d2707606c3e14e07c96" +dependencies = [ + "cfg-if 1.0.0", + "downcast", + "fragile", + "lazy_static", + "mockall_derive", + "predicates", + "predicates-tree", +] + +[[package]] +name = "mockall_derive" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22ce75669015c4f47b289fd4d4f56e894e4c96003ffdf3ac51313126f94c6cbb" +dependencies = [ + "cfg-if 1.0.0", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "moonbeam-evm-tracer" +version = "0.1.0" +source = "git+https://github.com/litentry/astar-frame?branch=polkadot-v0.9.42#d9a49c58f248f49e274b0730b8f4ef7f1e72c4b5" +dependencies = [ + "ethereum-types", + "evm 0.37.0", + "evm-gasometer 0.37.0", + "evm-runtime 0.37.0", + "evm-tracing-events", + "fp-evm 3.0.0-dev (git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42)", + "moonbeam-primitives-ext", + "pallet-evm 6.0.0-dev (git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42)", + "parity-scale-codec", + "sp-core", + "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", + "sp-runtime", + "sp-std 5.0.0", +] + +[[package]] +name = "moonbeam-primitives-ext" +version = "0.1.0" +source = "git+https://github.com/litentry/astar-frame?branch=polkadot-v0.9.42#d9a49c58f248f49e274b0730b8f4ef7f1e72c4b5" +dependencies = [ + "ethereum-types", + "evm-tracing-events", + "parity-scale-codec", + "sp-externalities", + "sp-runtime-interface", + "sp-std 5.0.0", +] + +[[package]] +name = "moonbeam-rpc-primitives-debug" +version = "0.1.0" +source = "git+https://github.com/litentry/astar-frame?branch=polkadot-v0.9.42#d9a49c58f248f49e274b0730b8f4ef7f1e72c4b5" +dependencies = [ + "environmental 1.1.4", + "ethereum", + "ethereum-types", + "hex", + "parity-scale-codec", + "serde 1.0.193", + "serde_json 1.0.103", + "sp-api", + "sp-core", + "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", + "sp-runtime", + "sp-std 5.0.0", +] + +[[package]] +name = "moonbeam-rpc-primitives-txpool" +version = "0.6.0" +source = "git+https://github.com/litentry/astar-frame?branch=polkadot-v0.9.42#d9a49c58f248f49e274b0730b8f4ef7f1e72c4b5" +dependencies = [ + "ethereum", + "parity-scale-codec", + "scale-info", + "sp-api", + "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", + "sp-runtime", + "sp-std 5.0.0", +] + +[[package]] +name = "multer" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01acbdc23469fd8fe07ab135923371d5f5a422fbf9c522158677c8eb15bc51c2" +dependencies = [ + "bytes 1.4.0", + "encoding_rs", + "futures-util 0.3.28", + "http 0.2.9", + "httparse 1.8.0", + "log 0.4.20", + "memchr 2.6.3", + "mime", + "spin 0.9.8", + "version_check", +] + +[[package]] +name = "multiaddr" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4aebdb21e90f81d13ed01dc84123320838e53963c2ca94b60b305d3fa64f31e" +dependencies = [ + "arrayref", + "byteorder 1.4.3", + "data-encoding", + "multibase", + "multihash 0.16.3", + "percent-encoding 2.3.0", + "serde 1.0.193", + "static_assertions", + "unsigned-varint 0.7.1", + "url 2.4.0", +] + +[[package]] +name = "multiaddr" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b36f567c7099511fa8612bbbb52dda2419ce0bdbacf31714e3a5ffdb766d3bd" +dependencies = [ + "arrayref", + "byteorder 1.4.3", + "data-encoding", + "log 0.4.20", + "multibase", + "multihash 0.17.0", + "percent-encoding 2.3.0", + "serde 1.0.193", + "static_assertions", + "unsigned-varint 0.7.1", + "url 2.4.0", +] + +[[package]] +name = "multibase" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b3539ec3c1f04ac9748a260728e855f261b4977f5c3406612c884564f329404" +dependencies = [ + "base-x", + "data-encoding", + "data-encoding-macro", +] + +[[package]] +name = "multihash" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dac63698b887d2d929306ea48b63760431ff8a24fac40ddb22f9c7f49fb7cab" +dependencies = [ + "generic-array 0.14.7", + "multihash-derive 0.7.2", + "unsigned-varint 0.5.1", +] + +[[package]] +name = "multihash" +version = "0.16.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c346cf9999c631f002d8f977c4eaeaa0e6386f16007202308d0b3757522c2cc" +dependencies = [ + "blake2b_simd", + "blake2s_simd", + "blake3", + "core2 0.4.0", + "digest 0.10.7", + "multihash-derive 0.8.0", + "sha2 0.10.7", + "sha3", + "unsigned-varint 0.7.1", +] + +[[package]] +name = "multihash" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "835d6ff01d610179fbce3de1694d007e500bf33a7f29689838941d6bf783ae40" +dependencies = [ + "core2 0.4.0", + "multihash-derive 0.8.0", + "unsigned-varint 0.7.1", +] + +[[package]] +name = "multihash-derive" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "424f6e86263cd5294cbd7f1e95746b95aca0e0d66bff31e5a40d6baa87b4aa99" +dependencies = [ + "proc-macro-crate", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 1.0.109", + "synstructure", +] + +[[package]] +name = "multihash-derive" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc076939022111618a5026d3be019fd8b366e76314538ff9a1b59ffbcbf98bcd" +dependencies = [ + "proc-macro-crate", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 1.0.109", + "synstructure", +] + +[[package]] +name = "multimap" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" + +[[package]] +name = "multistream-select" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8552ab875c1313b97b8d20cb857b9fd63e2d1d6a0a1b53ce9821e575405f27a" +dependencies = [ + "bytes 1.4.0", + "futures 0.3.28", + "log 0.4.20", + "pin-project", + "smallvec 1.11.0", + "unsigned-varint 0.7.1", +] + +[[package]] +name = "nalgebra" +version = "0.32.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "307ed9b18cc2423f29e83f84fd23a8e73628727990181f18641a8b5dc2ab1caa" +dependencies = [ + "approx", + "matrixmultiply", + "nalgebra-macros", + "num-complex 0.4.3", + "num-rational 0.4.1", + "num-traits 0.2.16", + "simba", + "typenum 1.16.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "nalgebra-macros" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91761aed67d03ad966ef783ae962ef9bbaca728d2dd7ceb7939ec110fffad998" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "names" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7d66043b25d4a6cccb23619d10c19c25304b355a7dccd4a8e11423dd2382146" +dependencies = [ + "rand 0.8.5", +] + +[[package]] +name = "nanorand" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a51313c5820b0b02bd422f4b44776fbf47961755c74ce64afc73bfad10226c3" + +[[package]] +name = "native-tls" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" +dependencies = [ + "lazy_static", + "libc", + "log 0.4.20", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + +[[package]] +name = "net2" +version = "0.2.33" +source = "git+https://github.com/mesalock-linux/net2-rs-sgx#554583d15f3c9dff5d862a6ae64e227bb38fa729" +dependencies = [ + "cfg-if 0.1.10", + "sgx_libc", + "sgx_tstd", +] + +[[package]] +name = "net2" +version = "0.2.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b13b648036a2339d06de780866fbdfda0dde886de7b3af2ddeba8b14f4ee34ac" +dependencies = [ + "cfg-if 0.1.10", + "libc", + "winapi 0.3.9", +] + +[[package]] +name = "netlink-packet-core" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "345b8ab5bd4e71a2986663e88c56856699d060e78e152e6e9d7966fcd5491297" +dependencies = [ + "anyhow", + "byteorder 1.4.3", + "libc", + "netlink-packet-utils", +] + +[[package]] +name = "netlink-packet-route" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9ea4302b9759a7a88242299225ea3688e63c85ea136371bb6cf94fd674efaab" +dependencies = [ + "anyhow", + "bitflags 1.3.2", + "byteorder 1.4.3", + "libc", + "netlink-packet-core", + "netlink-packet-utils", +] + +[[package]] +name = "netlink-packet-utils" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ede8a08c71ad5a95cdd0e4e52facd37190977039a4704eb82a283f713747d34" +dependencies = [ + "anyhow", + "byteorder 1.4.3", + "paste", + "thiserror 1.0.44", +] + +[[package]] +name = "netlink-proto" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65b4b14489ab424703c092062176d52ba55485a89c076b4f9db05092b7223aa6" +dependencies = [ + "bytes 1.4.0", + "futures 0.3.28", + "log 0.4.20", + "netlink-packet-core", + "netlink-sys", + "thiserror 1.0.44", + "tokio", +] + +[[package]] +name = "netlink-sys" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6471bf08e7ac0135876a9581bf3217ef0333c191c128d34878079f42ee150411" +dependencies = [ + "bytes 1.4.0", + "futures 0.3.28", + "libc", + "log 0.4.20", + "tokio", +] + +[[package]] +name = "nix" +version = "0.24.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa52e972a9a719cecb6864fb88568781eb706bac2cd1d4f04a648542dbf78069" +dependencies = [ + "bitflags 1.3.2", + "cfg-if 1.0.0", + "libc", + "memoffset 0.6.5", +] + +[[package]] +name = "nodrop" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" + +[[package]] +name = "nohash-hasher" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451" + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr 2.6.3", + "minimal-lexical", +] + +[[package]] +name = "normalize-line-endings" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be" + +[[package]] +name = "num" +version = "0.2.0" +source = "git+https://github.com/mesalock-linux/num-sgx#22645415542cc67551890dfdd34f4d5638b9ec78" +dependencies = [ + "num-bigint 0.2.5", + "num-complex 0.2.3", + "num-integer 0.1.41", + "num-iter 0.1.39", + "num-rational 0.2.2", + "num-traits 0.2.10", +] + +[[package]] +name = "num" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8536030f9fea7127f841b45bb6243b27255787fb4eb83958aa1ef9d2fdc0c36" +dependencies = [ + "num-bigint 0.2.6", + "num-complex 0.2.4", + "num-integer 0.1.45", + "num-iter 0.1.43", + "num-rational 0.2.4", + "num-traits 0.2.16", +] + +[[package]] +name = "num" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b05180d69e3da0e530ba2a1dae5110317e49e3b7f3d41be227dc5f92e49ee7af" +dependencies = [ + "num-bigint 0.4.3", + "num-complex 0.4.3", + "num-integer 0.1.45", + "num-iter 0.1.43", + "num-rational 0.4.1", + "num-traits 0.2.16", +] + +[[package]] +name = "num-bigint" +version = "0.2.5" +source = "git+https://github.com/mesalock-linux/num-bigint-sgx#76a5bed94dc31c32bd1670dbf72877abcf9bbc09" +dependencies = [ + "autocfg 1.1.0", + "num-integer 0.1.41", + "num-traits 0.2.10", + "sgx_tstd", +] + +[[package]] +name = "num-bigint" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "090c7f9998ee0ff65aa5b723e4009f7b217707f1fb5ea551329cc4d6231fb304" +dependencies = [ + "autocfg 1.1.0", + "num-integer 0.1.45", + "num-traits 0.2.16", +] + +[[package]] +name = "num-bigint" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f" +dependencies = [ + "autocfg 1.1.0", + "num-integer 0.1.45", + "num-traits 0.2.16", +] + +[[package]] +name = "num-complex" +version = "0.2.3" +source = "git+https://github.com/mesalock-linux/num-complex-sgx#19700ad6de079ebc5560db472c282d1591e0d84f" +dependencies = [ + "autocfg 0.1.8", + "num-traits 0.2.10", + "sgx_tstd", +] + +[[package]] +name = "num-complex" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6b19411a9719e753aff12e5187b74d60d3dc449ec3f4dc21e3989c3f554bc95" +dependencies = [ + "autocfg 1.1.0", + "num-traits 0.2.16", +] + +[[package]] +name = "num-complex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02e0d21255c828d6f128a1e41534206671e8c3ea0c62f32291e808dc82cff17d" +dependencies = [ + "num-traits 0.2.16", +] + +[[package]] +name = "num-derive" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "num-format" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a652d9771a63711fd3c3deb670acfbe5c30a4072e664d7a3bf5a9e1056ac72c3" +dependencies = [ + "arrayvec 0.7.4", + "itoa 1.0.9", +] + +[[package]] +name = "num-integer" +version = "0.1.41" +source = "git+https://github.com/mesalock-linux/num-integer-sgx#404c50e5378ca635261688b080dee328ff42b6bd" +dependencies = [ + "autocfg 0.1.8", + "num-traits 0.2.10", + "sgx_tstd", +] + +[[package]] +name = "num-integer" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +dependencies = [ + "autocfg 1.1.0", + "num-traits 0.2.16", +] + +[[package]] +name = "num-iter" +version = "0.1.39" +source = "git+https://github.com/mesalock-linux/num-iter-sgx#f19fc44fcad0b82a040e5a24c511e5049cc04b60" +dependencies = [ + "num-integer 0.1.41", + "num-traits 0.2.10", + "sgx_tstd", +] + +[[package]] +name = "num-iter" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" +dependencies = [ + "autocfg 1.1.0", + "num-integer 0.1.45", + "num-traits 0.2.16", +] + +[[package]] +name = "num-rational" +version = "0.2.2" +source = "git+https://github.com/mesalock-linux/num-rational-sgx#be65f9ce439f3c9ec850d8041635ab6c3309b816" +dependencies = [ + "autocfg 0.1.8", + "num-bigint 0.2.5", + "num-integer 0.1.41", + "num-traits 0.2.10", + "sgx_tstd", +] + +[[package]] +name = "num-rational" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c000134b5dbf44adc5cb772486d335293351644b801551abe8f75c84cfa4aef" +dependencies = [ + "autocfg 1.1.0", + "num-bigint 0.2.6", + "num-integer 0.1.45", + "num-traits 0.2.16", +] + +[[package]] +name = "num-rational" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" +dependencies = [ + "autocfg 1.1.0", + "num-bigint 0.4.3", + "num-integer 0.1.45", + "num-traits 0.2.16", +] + +[[package]] +name = "num-traits" +version = "0.2.10" +source = "git+https://github.com/mesalock-linux/num-traits-sgx#af046e0b15c594c960007418097dd4ff37ec3f7a" +dependencies = [ + "autocfg 0.1.8", + "sgx_tstd", +] + +[[package]] +name = "num-traits" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2" +dependencies = [ + "autocfg 1.1.0", +] + +[[package]] +name = "num_cpus" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +dependencies = [ + "hermit-abi 0.3.2", + "libc", +] + +[[package]] +name = "num_enum" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a015b430d3c108a207fd776d2e2196aaf8b1cf8cf93253e3a097ff3085076a1" +dependencies = [ + "num_enum_derive 0.6.1", +] + +[[package]] +name = "num_enum" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02339744ee7253741199f897151b38e72257d13802d4ee837285cc2990a90845" +dependencies = [ + "num_enum_derive 0.7.2", +] + +[[package]] +name = "num_enum_derive" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96667db765a921f7b295ffee8b60472b686a51d4f21c2ee4ffdb94c7013b65a6" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.32", +] + +[[package]] +name = "num_enum_derive" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "681030a937600a36906c185595136d26abfebb4aa9c65701cefcaf8578bb982b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.32", +] + +[[package]] +name = "object" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53" +dependencies = [ + "crc32fast", + "hashbrown 0.12.3", + "indexmap 1.9.3", + "memchr 2.6.3", +] + +[[package]] +name = "object" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8bda667d9f2b5051b8833f59f3bf748b28ef54f850f4fcb389a252aa383866d1" +dependencies = [ + "memchr 2.6.3", +] + +[[package]] +name = "ofb" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5e609fc8b72da3dabd56427be9489d8a9f4bd2e4dc41660dd033c3c8e90b93c" +dependencies = [ + "cipher 0.2.5", +] + +[[package]] +name = "oid-registry" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38e20717fa0541f39bd146692035c37bedfa532b3e5071b35761082407546b2a" +dependencies = [ + "asn1-rs 0.3.1", +] + +[[package]] +name = "oid-registry" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bedf36ffb6ba96c2eb7144ef6270557b52e54b20c0a8e1eb2ff99a6c6959bff" +dependencies = [ + "asn1-rs 0.5.2", +] + +[[package]] +name = "once_cell" +version = "1.4.0" +source = "git+https://github.com/mesalock-linux/once_cell-sgx#cefcaa03fed4d85276b3235d875f1b45d399cc3c" +dependencies = [ + "sgx_tstd", +] + +[[package]] +name = "once_cell" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" + +[[package]] +name = "opaque-debug" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" + +[[package]] +name = "opaque-debug" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" + +[[package]] +name = "openssl" +version = "0.10.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "345df152bc43501c5eb9e4654ff05f794effb78d4efe3d53abc158baddc0703d" +dependencies = [ + "bitflags 1.3.2", + "cfg-if 1.0.0", + "foreign-types", + "libc", + "once_cell 1.18.0", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.32", +] + +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + +[[package]] +name = "openssl-sys" +version = "0.9.90" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "374533b0e45f3a7ced10fcaeccca020e66656bc03dac384f852e4e5a7a8104a6" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "orchestra" +version = "0.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "227585216d05ba65c7ab0a0450a3cf2cbd81a98862a54c4df8e14d5ac6adb015" +dependencies = [ + "async-trait", + "dyn-clonable", + "futures 0.3.28", + "futures-timer", + "orchestra-proc-macro", + "pin-project", + "prioritized-metered-channel", + "thiserror 1.0.44", + "tracing", +] + +[[package]] +name = "orchestra-proc-macro" +version = "0.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2871aadd82a2c216ee68a69837a526dfe788ecbe74c4c5038a6acdbff6653066" +dependencies = [ + "expander 0.0.6", + "itertools 0.10.5", + "petgraph", + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ordered-float" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3305af35278dd29f46fcdd139e0b1fbfae2153f0e5928b39b035542dd31e37b7" +dependencies = [ + "num-traits 0.2.16", +] + +[[package]] +name = "ordered-multimap" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccd746e37177e1711c20dd619a1620f34f5c8b569c53590a72dedd5344d8924a" +dependencies = [ + "dlv-list", + "hashbrown 0.12.3", +] + +[[package]] +name = "orml-tokens" +version = "0.4.1-dev" +source = "git+https://github.com/open-web3-stack/open-runtime-module-library?branch=polkadot-v0.9.42#4ae0372e2c624e6acc98305564b9d395f70814c0" +dependencies = [ + "frame-support", + "frame-system", + "orml-traits", + "parity-scale-codec", + "scale-info", + "serde 1.0.193", + "sp-arithmetic", + "sp-runtime", + "sp-std 5.0.0", +] + +[[package]] +name = "orml-traits" +version = "0.4.1-dev" +source = "git+https://github.com/open-web3-stack/open-runtime-module-library?branch=polkadot-v0.9.42#4ae0372e2c624e6acc98305564b9d395f70814c0" +dependencies = [ + "frame-support", + "impl-trait-for-tuples", + "num-traits 0.2.16", + "orml-utilities", + "parity-scale-codec", + "scale-info", + "serde 1.0.193", + "sp-core", + "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", + "sp-runtime", + "sp-std 5.0.0", + "xcm", +] + +[[package]] +name = "orml-utilities" +version = "0.4.1-dev" +source = "git+https://github.com/open-web3-stack/open-runtime-module-library?branch=polkadot-v0.9.42#4ae0372e2c624e6acc98305564b9d395f70814c0" +dependencies = [ + "frame-support", + "parity-scale-codec", + "scale-info", + "serde 1.0.193", + "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", + "sp-runtime", + "sp-std 5.0.0", +] + +[[package]] +name = "orml-xcm-support" +version = "0.4.1-dev" +source = "git+https://github.com/open-web3-stack/open-runtime-module-library?branch=polkadot-v0.9.42#4ae0372e2c624e6acc98305564b9d395f70814c0" +dependencies = [ + "frame-support", + "orml-traits", + "parity-scale-codec", + "sp-runtime", + "sp-std 5.0.0", + "xcm", + "xcm-executor", +] + +[[package]] +name = "orml-xtokens" +version = "0.4.1-dev" +source = "git+https://github.com/open-web3-stack/open-runtime-module-library?branch=polkadot-v0.9.42#4ae0372e2c624e6acc98305564b9d395f70814c0" +dependencies = [ + "cumulus-primitives-core", + "frame-support", + "frame-system", + "orml-traits", + "orml-xcm-support", + "pallet-xcm", + "parity-scale-codec", + "scale-info", + "serde 1.0.193", + "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", + "sp-runtime", + "sp-std 5.0.0", + "xcm", + "xcm-executor", +] + +[[package]] +name = "os_str_bytes" +version = "6.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d5d9eb14b174ee9aa2ef96dc2b94637a2d4b6e7cb873c7e171f0c20c6cf3eac" + +[[package]] +name = "p256" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51f44edd08f51e2ade572f141051021c5af22677e42b7dd28a88155151c33594" +dependencies = [ + "ecdsa 0.14.8", + "elliptic-curve 0.12.3", + "sha2 0.10.7", +] + +[[package]] +name = "p384" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfc8c5bf642dde52bb9e87c0ecd8ca5a76faac2eeed98dedb7c717997e1080aa" +dependencies = [ + "ecdsa 0.14.8", + "elliptic-curve 0.12.3", + "sha2 0.10.7", +] + +[[package]] +name = "packed_simd_2" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1914cd452d8fccd6f9db48147b29fd4ae05bea9dc5d9ad578509f72415de282" +dependencies = [ + "cfg-if 1.0.0", + "libm 0.1.4", +] + +[[package]] +name = "pallet-asset-manager" +version = "0.1.0" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "orml-traits", + "parity-scale-codec", + "scale-info", + "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", + "sp-runtime", + "sp-std 5.0.0", + "xcm", +] + +[[package]] +name = "pallet-assets" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-runtime", + "sp-std 5.0.0", +] + +[[package]] +name = "pallet-aura" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "frame-support", + "frame-system", + "pallet-timestamp", + "parity-scale-codec", + "scale-info", + "sp-application-crypto", + "sp-consensus-aura", + "sp-runtime", + "sp-std 5.0.0", +] + +[[package]] +name = "pallet-authority-discovery" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "frame-support", + "frame-system", + "pallet-session", + "parity-scale-codec", + "scale-info", + "sp-application-crypto", + "sp-authority-discovery", + "sp-runtime", + "sp-std 5.0.0", +] + +[[package]] +name = "pallet-authorship" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "frame-support", + "frame-system", + "impl-trait-for-tuples", + "parity-scale-codec", + "scale-info", + "sp-runtime", + "sp-std 5.0.0", +] + +[[package]] +name = "pallet-babe" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "log 0.4.20", + "pallet-authorship", + "pallet-session", + "pallet-timestamp", + "parity-scale-codec", + "scale-info", + "sp-application-crypto", + "sp-consensus-babe", + "sp-core", + "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", + "sp-runtime", + "sp-session", + "sp-staking", + "sp-std 5.0.0", +] + +[[package]] +name = "pallet-balances" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "log 0.4.20", + "parity-scale-codec", + "scale-info", + "sp-runtime", + "sp-std 5.0.0", +] + +[[package]] +name = "pallet-bounties" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "log 0.4.20", + "pallet-treasury", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", + "sp-runtime", + "sp-std 5.0.0", +] + +[[package]] +name = "pallet-bridge" +version = "0.1.0" +dependencies = [ + "blake2-rfc", + "frame-benchmarking", + "frame-support", + "frame-system", + "pallet-balances", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", + "sp-runtime", + "sp-std 5.0.0", +] + +[[package]] +name = "pallet-bridge-transfer" +version = "0.1.0" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "pallet-bridge", + "pallet-parachain-staking", + "parity-scale-codec", + "scale-info", + "sp-arithmetic", + "sp-core", + "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", + "sp-runtime", + "sp-std 5.0.0", +] + +[[package]] +name = "pallet-collective" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "log 0.4.20", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", + "sp-runtime", + "sp-std 5.0.0", +] + +[[package]] +name = "pallet-democracy" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "log 0.4.20", + "parity-scale-codec", + "scale-info", + "serde 1.0.193", + "sp-core", + "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", + "sp-runtime", + "sp-std 5.0.0", +] + +[[package]] +name = "pallet-drop3" +version = "0.1.0" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "pallet-balances", + "parity-scale-codec", + "scale-info", + "sp-runtime", + "sp-std 5.0.0", +] + +[[package]] +name = "pallet-election-provider-multi-phase" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "frame-benchmarking", + "frame-election-provider-support", + "frame-support", + "frame-system", + "log 0.4.20", + "pallet-election-provider-support-benchmarking", + "parity-scale-codec", + "rand 0.8.5", + "scale-info", + "sp-arithmetic", + "sp-core", + "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", + "sp-npos-elections", + "sp-runtime", + "sp-std 5.0.0", + "strum 0.24.1", +] + +[[package]] +name = "pallet-election-provider-support-benchmarking" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "frame-benchmarking", + "frame-election-provider-support", + "frame-system", + "parity-scale-codec", + "sp-npos-elections", + "sp-runtime", +] + +[[package]] +name = "pallet-ethereum" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42#2499d18c936edbcb7fcb711827db7abb9b4f4da4" +dependencies = [ + "ethereum", + "ethereum-types", + "evm 0.39.1 (git+https://github.com/rust-blockchain/evm?rev=b7b82c7e1fc57b7449d6dfa6826600de37cc1e65)", + "fp-consensus", + "fp-ethereum", + "fp-evm 3.0.0-dev (git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42)", + "fp-rpc", + "fp-storage", + "frame-support", + "frame-system", + "pallet-evm 6.0.0-dev (git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42)", + "parity-scale-codec", + "scale-info", + "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", + "sp-runtime", + "sp-std 5.0.0", +] + +[[package]] +name = "pallet-evm" +version = "6.0.0-dev" +source = "git+https://github.com/integritee-network/frontier.git?branch=bar/polkadot-v0.9.42#a5a5e1e6ec08cd542a6084c310863150fb8841b1" +dependencies = [ + "environmental 1.1.4", + "evm 0.39.1 (registry+https://github.com/rust-lang/crates.io-index)", + "fp-account 1.0.0-dev (git+https://github.com/integritee-network/frontier.git?branch=bar/polkadot-v0.9.42)", + "fp-evm 3.0.0-dev (git+https://github.com/integritee-network/frontier.git?branch=bar/polkadot-v0.9.42)", + "frame-benchmarking", + "frame-support", + "frame-system", + "hex", + "impl-trait-for-tuples", + "log 0.4.20", + "parity-scale-codec", + "rlp", + "scale-info", + "sp-core", + "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", + "sp-runtime", + "sp-std 5.0.0", +] + +[[package]] +name = "pallet-evm" +version = "6.0.0-dev" +source = "git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42#2499d18c936edbcb7fcb711827db7abb9b4f4da4" +dependencies = [ + "environmental 1.1.4", + "evm 0.39.1 (git+https://github.com/rust-blockchain/evm?rev=b7b82c7e1fc57b7449d6dfa6826600de37cc1e65)", + "fp-account 1.0.0-dev (git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42)", + "fp-evm 3.0.0-dev (git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42)", + "frame-benchmarking", + "frame-support", + "frame-system", + "hex", + "hex-literal", + "impl-trait-for-tuples", + "log 0.4.20", + "parity-scale-codec", + "rlp", + "scale-info", + "sp-core", + "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", + "sp-runtime", + "sp-std 5.0.0", +] + +[[package]] +name = "pallet-evm-precompile-blake2" +version = "2.0.0-dev" +source = "git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42#2499d18c936edbcb7fcb711827db7abb9b4f4da4" +dependencies = [ + "fp-evm 3.0.0-dev (git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42)", +] + +[[package]] +name = "pallet-evm-precompile-bn128" +version = "2.0.0-dev" +source = "git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42#2499d18c936edbcb7fcb711827db7abb9b4f4da4" +dependencies = [ + "fp-evm 3.0.0-dev (git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42)", + "sp-core", + "substrate-bn", +] + +[[package]] +name = "pallet-evm-precompile-bridge-transfer" +version = "0.9.17" +dependencies = [ + "fp-evm 3.0.0-dev (git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42)", + "frame-support", + "frame-system", + "log 0.4.20", + "num_enum 0.7.2", + "pallet-bridge", + "pallet-bridge-transfer", + "pallet-evm 6.0.0-dev (git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42)", + "parity-scale-codec", + "precompile-utils", + "rustc-hex", + "sp-core", + "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", + "sp-runtime", + "sp-std 5.0.0", +] + +[[package]] +name = "pallet-evm-precompile-dispatch" +version = "2.0.0-dev" +source = "git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42#2499d18c936edbcb7fcb711827db7abb9b4f4da4" +dependencies = [ + "fp-evm 3.0.0-dev (git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42)", + "frame-support", + "pallet-evm 6.0.0-dev (git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42)", +] + +[[package]] +name = "pallet-evm-precompile-ed25519" +version = "2.0.0-dev" +source = "git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42#2499d18c936edbcb7fcb711827db7abb9b4f4da4" +dependencies = [ + "ed25519-dalek", + "fp-evm 3.0.0-dev (git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42)", +] + +[[package]] +name = "pallet-evm-precompile-modexp" +version = "2.0.0-dev" +source = "git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42#2499d18c936edbcb7fcb711827db7abb9b4f4da4" +dependencies = [ + "fp-evm 3.0.0-dev (git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42)", + "num 0.4.1", +] + +[[package]] +name = "pallet-evm-precompile-parachain-staking" +version = "0.9.17" +dependencies = [ + "fp-evm 3.0.0-dev (git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42)", + "frame-support", + "frame-system", + "log 0.4.20", + "num_enum 0.7.2", + "pallet-evm 6.0.0-dev (git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42)", + "pallet-parachain-staking", + "parity-scale-codec", + "precompile-utils", + "rustc-hex", + "sp-core", + "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", + "sp-runtime", + "sp-std 5.0.0", +] + +[[package]] +name = "pallet-evm-precompile-sha3fips" +version = "2.0.0-dev" +source = "git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42#2499d18c936edbcb7fcb711827db7abb9b4f4da4" +dependencies = [ + "fp-evm 3.0.0-dev (git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42)", + "tiny-keccak", +] + +[[package]] +name = "pallet-evm-precompile-simple" +version = "2.0.0-dev" +source = "git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42#2499d18c936edbcb7fcb711827db7abb9b4f4da4" +dependencies = [ + "fp-evm 3.0.0-dev (git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42)", + "ripemd", + "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", +] + +[[package]] +name = "pallet-extrinsic-filter" +version = "0.1.0" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "parity-scale-codec", + "scale-info", + "sp-runtime", + "sp-std 5.0.0", +] + +[[package]] +name = "pallet-fast-unstake" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "frame-benchmarking", + "frame-election-provider-support", + "frame-support", + "frame-system", + "log 0.4.20", + "parity-scale-codec", + "scale-info", + "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", + "sp-runtime", + "sp-staking", + "sp-std 5.0.0", +] + +[[package]] +name = "pallet-group" +version = "0.1.0" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "pallet-balances", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", + "sp-runtime", + "sp-std 5.0.0", +] + +[[package]] +name = "pallet-identity" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "enumflags2", + "frame-benchmarking", + "frame-support", + "frame-system", + "parity-scale-codec", + "scale-info", + "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", + "sp-runtime", + "sp-std 5.0.0", +] + +[[package]] +name = "pallet-identity-management" +version = "0.1.0" +dependencies = [ + "core-primitives", + "frame-benchmarking", + "frame-support", + "frame-system", + "pallet-teerex", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-runtime", + "sp-std 5.0.0", + "teerex-primitives", +] + +[[package]] +name = "pallet-membership" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "log 0.4.20", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", + "sp-runtime", + "sp-std 5.0.0", +] + +[[package]] +name = "pallet-multisig" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "log 0.4.20", + "parity-scale-codec", + "scale-info", + "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", + "sp-runtime", + "sp-std 5.0.0", +] + +[[package]] +name = "pallet-parachain-staking" +version = "0.1.0" +dependencies = [ + "core-primitives", + "frame-benchmarking", + "frame-support", + "frame-system", + "log 0.4.20", + "pallet-authorship", + "pallet-balances", + "pallet-session", + "parity-scale-codec", + "scale-info", + "serde 1.0.193", + "sp-runtime", + "sp-staking", + "sp-std 5.0.0", + "substrate-fixed 0.5.9 (git+https://github.com/encointer/substrate-fixed)", +] + +[[package]] +name = "pallet-parentchain" +version = "0.9.0" +dependencies = [ + "frame-support", + "frame-system", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", + "sp-runtime", +] + +[[package]] +name = "pallet-preimage" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "log 0.4.20", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", + "sp-runtime", + "sp-std 5.0.0", +] + +[[package]] +name = "pallet-proxy" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "parity-scale-codec", + "scale-info", + "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", + "sp-runtime", + "sp-std 5.0.0", +] + +[[package]] +name = "pallet-scheduler" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "log 0.4.20", + "parity-scale-codec", + "scale-info", + "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", + "sp-runtime", + "sp-std 5.0.0", + "sp-weights", +] + +[[package]] +name = "pallet-session" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "frame-support", + "frame-system", + "impl-trait-for-tuples", + "log 0.4.20", + "pallet-timestamp", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", + "sp-runtime", + "sp-session", + "sp-staking", + "sp-std 5.0.0", + "sp-trie", +] + +[[package]] +name = "pallet-sidechain" +version = "0.9.0" +dependencies = [ + "frame-support", + "frame-system", + "log 0.4.20", + "pallet-teerex", + "pallet-timestamp", + "parity-scale-codec", + "scale-info", + "serde 1.0.193", + "sidechain-primitives", + "sp-core", + "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", + "sp-runtime", + "sp-std 5.0.0", + "teerex-primitives", +] + +[[package]] +name = "pallet-staking" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "frame-benchmarking", + "frame-election-provider-support", + "frame-support", + "frame-system", + "log 0.4.20", + "pallet-authorship", + "pallet-session", + "parity-scale-codec", + "scale-info", + "serde 1.0.193", + "sp-application-crypto", + "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", + "sp-runtime", + "sp-staking", + "sp-std 5.0.0", +] + +[[package]] +name = "pallet-staking-reward-fn" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "log 0.4.20", + "sp-arithmetic", +] + +[[package]] +name = "pallet-sudo" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "frame-support", + "frame-system", + "parity-scale-codec", + "scale-info", + "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", + "sp-runtime", + "sp-std 5.0.0", +] + +[[package]] +name = "pallet-teeracle" +version = "0.1.0" +dependencies = [ + "frame-support", + "frame-system", + "log 0.4.20", + "pallet-teerex", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", + "sp-runtime", + "sp-std 5.0.0", + "substrate-fixed 0.5.9 (git+https://github.com/encointer/substrate-fixed?tag=v0.5.9)", + "teeracle-primitives", +] + +[[package]] +name = "pallet-teerex" +version = "0.9.0" +dependencies = [ + "frame-support", + "frame-system", + "log 0.4.20", + "pallet-timestamp", + "parity-scale-codec", + "rustls-webpki", + "scale-info", + "sgx-verify", + "sp-core", + "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", + "sp-runtime", + "sp-std 5.0.0", + "teerex-primitives", +] + +[[package]] +name = "pallet-timestamp" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "log 0.4.20", + "parity-scale-codec", + "scale-info", + "sp-inherents", + "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", + "sp-runtime", + "sp-std 5.0.0", + "sp-timestamp", +] + +[[package]] +name = "pallet-tips" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "log 0.4.20", + "pallet-treasury", + "parity-scale-codec", + "scale-info", + "serde 1.0.193", + "sp-core", + "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", + "sp-runtime", + "sp-std 5.0.0", +] + +[[package]] +name = "pallet-transaction-payment" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "frame-support", + "frame-system", + "parity-scale-codec", + "scale-info", + "serde 1.0.193", + "sp-core", + "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", + "sp-runtime", + "sp-std 5.0.0", +] + +[[package]] +name = "pallet-transaction-payment-rpc-runtime-api" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "pallet-transaction-payment", + "parity-scale-codec", + "sp-api", + "sp-runtime", + "sp-weights", +] + +[[package]] +name = "pallet-treasury" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "impl-trait-for-tuples", + "pallet-balances", + "parity-scale-codec", + "scale-info", + "serde 1.0.193", + "sp-runtime", + "sp-std 5.0.0", +] + +[[package]] +name = "pallet-utility" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", + "sp-runtime", + "sp-std 5.0.0", +] + +[[package]] +name = "pallet-vc-management" +version = "0.1.0" +dependencies = [ + "core-primitives", + "frame-benchmarking", + "frame-support", + "frame-system", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-runtime", + "sp-std 5.0.0", + "teerex-primitives", +] + +[[package]] +name = "pallet-vesting" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "log 0.4.20", + "parity-scale-codec", + "scale-info", + "sp-runtime", + "sp-std 5.0.0", +] + +[[package]] +name = "pallet-xcm" +version = "0.9.42" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" +dependencies = [ + "bounded-collections", + "frame-benchmarking", + "frame-support", + "frame-system", + "log 0.4.20", + "parity-scale-codec", + "scale-info", + "serde 1.0.193", + "sp-core", + "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", + "sp-runtime", + "sp-std 5.0.0", + "xcm", + "xcm-executor", +] + +[[package]] +name = "parachain-info" +version = "0.1.0" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.42#f603a61ff370fc33740c9373833c3c6ba1486846" +dependencies = [ + "cumulus-primitives-core", + "frame-support", + "frame-system", + "parity-scale-codec", + "scale-info", +] + +[[package]] +name = "parity-db" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4890dcb9556136a4ec2b0c51fa4a08c8b733b829506af8fff2e853f3a065985b" +dependencies = [ + "blake2", + "crc32fast", + "fs2", + "hex", + "libc", + "log 0.4.20", + "lz4", + "memmap2", + "parking_lot 0.12.1", + "rand 0.8.5", + "siphasher", + "snap", +] + +[[package]] +name = "parity-multiaddr" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58341485071825827b7f03cf7efd1cb21e6a709bea778fb50227fd45d2f361b4" +dependencies = [ + "arrayref", + "bs58", + "byteorder 1.4.3", + "data-encoding", + "multihash 0.13.2", + "percent-encoding 2.3.0", + "serde 1.0.193", + "static_assertions", + "unsigned-varint 0.7.1", + "url 2.4.0", +] + +[[package]] +name = "parity-scale-codec" +version = "3.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd8e946cc0cc711189c0b0249fb8b599cbeeab9784d83c415719368bb8d4ac64" +dependencies = [ + "arrayvec 0.7.4", + "bitvec", + "byte-slice-cast", + "bytes 1.4.0", + "impl-trait-for-tuples", + "parity-scale-codec-derive", + "serde 1.0.193", +] + +[[package]] +name = "parity-scale-codec-derive" +version = "3.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a296c3079b5fefbc499e1de58dc26c09b1b9a5952d26694ee89f04a43ebbb3e" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "parity-send-wrapper" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa9777aa91b8ad9dd5aaa04a9b6bcb02c7f1deb952fca5a66034d5e63afc5c6f" + +[[package]] +name = "parity-util-mem" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d32c34f4f5ca7f9196001c0aba5a1f9a5a12382c8944b8b0f90233282d1e8f8" +dependencies = [ + "cfg-if 1.0.0", + "impl-trait-for-tuples", + "parity-util-mem-derive", + "primitive-types", + "winapi 0.3.9", +] + +[[package]] +name = "parity-util-mem-derive" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f557c32c6d268a07c921471619c0295f5efad3a0e76d4f97a05c091a51d110b2" +dependencies = [ + "proc-macro2", + "syn 1.0.109", + "synstructure", +] + +[[package]] +name = "parity-wasm" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1ad0aff30c1da14b1254fcb2af73e1fa9a28670e584a626f53a369d0e157304" + +[[package]] +name = "parking" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14f2252c834a40ed9bb5422029649578e63aa341ac401f74e719dd1afda8394e" + +[[package]] +name = "parking_lot" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" +dependencies = [ + "instant", + "lock_api", + "parking_lot_core 0.8.6", +] + +[[package]] +name = "parking_lot" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +dependencies = [ + "lock_api", + "parking_lot_core 0.9.8", +] + +[[package]] +name = "parking_lot_core" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc" +dependencies = [ + "cfg-if 1.0.0", + "instant", + "libc", + "redox_syscall 0.2.16", + "smallvec 1.11.0", + "winapi 0.3.9", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" +dependencies = [ + "cfg-if 1.0.0", + "libc", + "redox_syscall 0.3.5", + "smallvec 1.11.0", + "windows-targets 0.48.1", +] + +[[package]] +name = "parse_duration" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7037e5e93e0172a5a96874380bf73bc6ecef022e26fa25f2be26864d6b3ba95d" +dependencies = [ + "lazy_static", + "num 0.2.1", + "regex 1.9.5", +] + +[[package]] +name = "paste" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" + +[[package]] +name = "pathdiff" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd" + +[[package]] +name = "pbkdf2" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d95f5254224e617595d2cc3cc73ff0a5eaf2637519e25f03388154e9378b6ffa" +dependencies = [ + "crypto-mac 0.11.1", +] + +[[package]] +name = "pbkdf2" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" +dependencies = [ + "digest 0.10.7", +] + +[[package]] +name = "peeking_take_while" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" + +[[package]] +name = "pem" +version = "0.8.2" +source = "git+https://github.com/mesalock-linux/pem-rs-sgx#fdfef4f24a9fb3fa72e8a71bb28bd8ff15feff2f" +dependencies = [ + "base64 0.13.0 (git+https://github.com/mesalock-linux/rust-base64-sgx)", + "once_cell 1.4.0", + "regex 1.3.1", + "sgx_tstd", +] + +[[package]] +name = "pem" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8835c273a76a90455d7344889b0964598e3316e2a79ede8e36f16bdcf2228b8" +dependencies = [ + "base64 0.13.1", +] + +[[package]] +name = "pem-rfc7468" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d159833a9105500e0398934e205e0773f0b27529557134ecfc51c27646adac" +dependencies = [ + "base64ct", +] + +[[package]] +name = "percent-encoding" +version = "2.1.0" +source = "git+https://github.com/mesalock-linux/rust-url-sgx?tag=sgx_1.1.3#23832f3191456c2d4a0faab10952e1747be58ca8" + +[[package]] +name = "percent-encoding" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" + +[[package]] +name = "pest" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d2d1d55045829d65aad9d389139882ad623b33b904e7c9f1b10c5b8927298e5" +dependencies = [ + "thiserror 1.0.44", + "ucd-trie", +] + +[[package]] +name = "pest_derive" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f94bca7e7a599d89dea5dfa309e217e7906c3c007fb9c3299c40b10d6a315d3" +dependencies = [ + "pest", + "pest_generator", +] + +[[package]] +name = "pest_generator" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99d490fe7e8556575ff6911e45567ab95e71617f43781e5c05490dc8d75c965c" +dependencies = [ + "pest", + "pest_meta", + "proc-macro2", + "quote", + "syn 2.0.32", +] + +[[package]] +name = "pest_meta" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2674c66ebb4b4d9036012091b537aae5878970d6999f81a265034d85b136b341" +dependencies = [ + "once_cell 1.18.0", + "pest", + "sha2 0.10.7", +] + +[[package]] +name = "petgraph" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dd7d28ee937e54fe3080c91faa1c3a46c06de6252988a7f4592ba2310ef22a4" +dependencies = [ + "fixedbitset", + "indexmap 1.9.3", +] + +[[package]] +name = "pin-project" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "030ad2bc4db10a8944cb0d837f158bdfec4d4a4873ab701a95046770d11f8842" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec2e072ecce94ec471b13398d5402c188e76ac03cf74dd1a975161b23a3f6d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.32", +] + +[[package]] +name = "pin-project-lite" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "257b64915a082f7811703966789728173279bdebb956b143dbcd23f6f970a777" + +[[package]] +name = "pin-project-lite" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c40d25201921e5ff0c862a505c6557ea88568a4e3ace775ab55e93f2f4f9d57" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkcs8" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9eca2c590a5f85da82668fa685c09ce2888b9430e83299debf1f34b65fd4a4ba" +dependencies = [ + "der 0.6.1", + "spki 0.6.0", +] + +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der 0.7.8", + "spki 0.7.2", +] + +[[package]] +name = "pkg-config" +version = "0.3.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" + +[[package]] +name = "platforms" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3d7ddaed09e0eb771a79ab0fd64609ba0afb0a8366421957936ad14cbd13630" + +[[package]] +name = "polkadot-core-primitives" +version = "0.9.42" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" +dependencies = [ + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-runtime", + "sp-std 5.0.0", +] + +[[package]] +name = "polkadot-node-jaeger" +version = "0.9.42" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" +dependencies = [ + "lazy_static", + "log 0.4.20", + "mick-jaeger", + "parity-scale-codec", + "parking_lot 0.12.1", + "polkadot-node-primitives", + "polkadot-primitives", + "sc-network", + "sp-core", + "thiserror 1.0.44", + "tokio", +] + +[[package]] +name = "polkadot-node-metrics" +version = "0.9.42" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" +dependencies = [ + "bs58", + "futures 0.3.28", + "futures-timer", + "log 0.4.20", + "parity-scale-codec", + "polkadot-primitives", + "prioritized-metered-channel", + "sc-cli", + "sc-service", + "sc-tracing", + "substrate-prometheus-endpoint", + "tracing-gum", +] + +[[package]] +name = "polkadot-node-network-protocol" +version = "0.9.42" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" +dependencies = [ + "async-trait", + "derive_more", + "fatality", + "futures 0.3.28", + "hex", + "parity-scale-codec", + "polkadot-node-jaeger", + "polkadot-node-primitives", + "polkadot-primitives", + "rand 0.8.5", + "sc-authority-discovery", + "sc-network", + "strum 0.24.1", + "thiserror 1.0.44", + "tracing-gum", +] + +[[package]] +name = "polkadot-node-primitives" +version = "0.9.42" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" +dependencies = [ + "bounded-vec", + "futures 0.3.28", + "parity-scale-codec", + "polkadot-parachain", + "polkadot-primitives", + "schnorrkel", + "serde 1.0.193", + "sp-application-crypto", + "sp-consensus-babe", + "sp-core", + "sp-keystore", + "sp-maybe-compressed-blob", + "sp-runtime", + "thiserror 1.0.44", + "zstd 0.11.2+zstd.1.5.2", +] + +[[package]] +name = "polkadot-node-subsystem-types" +version = "0.9.42" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" +dependencies = [ + "async-trait", + "derive_more", + "futures 0.3.28", + "orchestra", + "polkadot-node-jaeger", + "polkadot-node-network-protocol", + "polkadot-node-primitives", + "polkadot-primitives", + "polkadot-statement-table", + "sc-network", + "smallvec 1.11.0", + "sp-api", + "sp-authority-discovery", + "sp-consensus-babe", + "substrate-prometheus-endpoint", + "thiserror 1.0.44", +] + +[[package]] +name = "polkadot-overseer" +version = "0.9.42" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" +dependencies = [ + "async-trait", + "futures 0.3.28", + "futures-timer", + "lru 0.9.0", + "orchestra", + "parking_lot 0.12.1", + "polkadot-node-metrics", + "polkadot-node-network-protocol", + "polkadot-node-primitives", + "polkadot-node-subsystem-types", + "polkadot-primitives", + "sc-client-api", + "sp-api", + "sp-core", + "tikv-jemalloc-ctl", + "tracing-gum", +] + +[[package]] +name = "polkadot-parachain" +version = "0.9.42" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" +dependencies = [ + "bounded-collections", + "derive_more", + "frame-support", + "parity-scale-codec", + "polkadot-core-primitives", + "scale-info", + "serde 1.0.193", + "sp-core", + "sp-runtime", + "sp-std 5.0.0", +] + +[[package]] +name = "polkadot-primitives" +version = "0.9.42" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" +dependencies = [ + "bitvec", + "hex-literal", + "parity-scale-codec", + "polkadot-core-primitives", + "polkadot-parachain", + "scale-info", + "serde 1.0.193", + "sp-api", + "sp-application-crypto", + "sp-arithmetic", + "sp-authority-discovery", + "sp-consensus-slots", + "sp-core", + "sp-inherents", + "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", + "sp-keystore", + "sp-runtime", + "sp-staking", + "sp-std 5.0.0", +] + +[[package]] +name = "polkadot-runtime-common" +version = "0.9.42" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" +dependencies = [ + "bitvec", + "frame-election-provider-support", + "frame-support", + "frame-system", + "impl-trait-for-tuples", + "libsecp256k1", + "log 0.4.20", + "pallet-authorship", + "pallet-balances", + "pallet-election-provider-multi-phase", + "pallet-fast-unstake", + "pallet-session", + "pallet-staking", + "pallet-staking-reward-fn", + "pallet-timestamp", + "pallet-transaction-payment", + "pallet-treasury", + "pallet-vesting", + "parity-scale-codec", + "polkadot-primitives", + "polkadot-runtime-parachains", + "rustc-hex", + "scale-info", + "serde 1.0.193", + "serde_derive 1.0.193", + "slot-range-helper", + "sp-api", + "sp-core", + "sp-inherents", + "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", + "sp-npos-elections", + "sp-runtime", + "sp-session", + "sp-staking", + "sp-std 5.0.0", + "static_assertions", + "xcm", +] + +[[package]] +name = "polkadot-runtime-metrics" +version = "0.9.42" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" +dependencies = [ + "bs58", + "parity-scale-codec", + "polkadot-primitives", + "sp-std 5.0.0", + "sp-tracing", +] + +[[package]] +name = "polkadot-runtime-parachains" +version = "0.9.42" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" +dependencies = [ + "bitflags 1.3.2", + "bitvec", + "derive_more", + "frame-support", + "frame-system", + "log 0.4.20", + "pallet-authority-discovery", + "pallet-authorship", + "pallet-babe", + "pallet-balances", + "pallet-session", + "pallet-staking", + "pallet-timestamp", + "pallet-vesting", + "parity-scale-codec", + "polkadot-parachain", + "polkadot-primitives", + "polkadot-runtime-metrics", + "rand 0.8.5", + "rand_chacha 0.3.1", + "rustc-hex", + "scale-info", + "serde 1.0.193", + "sp-api", + "sp-core", + "sp-inherents", + "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", + "sp-keystore", + "sp-runtime", + "sp-session", + "sp-staking", + "sp-std 5.0.0", + "xcm", + "xcm-executor", +] + +[[package]] +name = "polkadot-statement-table" +version = "0.9.42" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" +dependencies = [ + "parity-scale-codec", + "polkadot-primitives", + "sp-core", +] + +[[package]] +name = "polling" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce" +dependencies = [ + "autocfg 1.1.0", + "bitflags 1.3.2", + "cfg-if 1.0.0", + "concurrent-queue", + "libc", + "log 0.4.20", + "pin-project-lite 0.2.10", + "windows-sys 0.48.0", +] + +[[package]] +name = "poly1305" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "048aeb476be11a4b6ca432ca569e375810de9294ae78f4774e78ea98a9246ede" +dependencies = [ + "cpufeatures", + "opaque-debug 0.3.0", + "universal-hash 0.4.1", +] + +[[package]] +name = "polyval" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8419d2b623c7c0896ff2d5d96e2cb4ede590fed28fcc34934f4c33c036e620a1" +dependencies = [ + "cfg-if 1.0.0", + "cpufeatures", + "opaque-debug 0.3.0", + "universal-hash 0.4.1", +] + +[[package]] +name = "polyval" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d52cff9d1d4dee5fe6d03729099f4a310a41179e0a10dbf542039873f2e826fb" +dependencies = [ + "cfg-if 1.0.0", + "cpufeatures", + "opaque-debug 0.3.0", + "universal-hash 0.5.1", +] + +[[package]] +name = "postcard" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a25c0b0ae06fcffe600ad392aabfa535696c8973f2253d9ac83171924c58a858" +dependencies = [ + "postcard-cobs", + "serde 1.0.193", +] + +[[package]] +name = "postcard-cobs" +version = "0.1.5-pre" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c68cb38ed13fd7bc9dd5db8f165b7c8d9c1a315104083a2b10f11354c2af97f" + +[[package]] +name = "ppv-lite86" +version = "0.2.6" +source = "git+https://github.com/mesalock-linux/cryptocorrosion-sgx#32d7de50b5f03a10fe5a42167410be2dd3c2e389" + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "precompile-utils" +version = "0.9.17" +dependencies = [ + "assert_matches", + "evm 0.39.1 (git+https://github.com/rust-blockchain/evm?rev=b7b82c7e1fc57b7449d6dfa6826600de37cc1e65)", + "fp-evm 3.0.0-dev (git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42)", + "frame-support", + "frame-system", + "impl-trait-for-tuples", + "log 0.4.20", + "num_enum 0.7.2", + "pallet-evm 6.0.0-dev (git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42)", + "parity-scale-codec", + "precompile-utils-macro", + "sha3", + "sp-core", + "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", + "sp-runtime", + "sp-std 5.0.0", + "xcm", +] + +[[package]] +name = "precompile-utils-macro" +version = "0.9.17" +dependencies = [ + "num_enum 0.7.2", + "proc-macro2", + "quote", + "sha3", + "syn 2.0.32", +] + +[[package]] +name = "predicates" +version = "2.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59230a63c37f3e18569bdb90e4a89cbf5bf8b06fea0b84e65ea10cc4df47addd" +dependencies = [ + "difflib", + "float-cmp", + "itertools 0.10.5", + "normalize-line-endings", + "predicates-core", + "regex 1.9.5", +] + +[[package]] +name = "predicates-core" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b794032607612e7abeb4db69adb4e33590fa6cf1149e95fd7cb00e634b92f174" + +[[package]] +name = "predicates-tree" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "368ba315fb8c5052ab692e68a0eefec6ec57b23a36959c14496f0b0df2c0cecf" +dependencies = [ + "predicates-core", + "termtree", +] + +[[package]] +name = "prettyplease" +version = "0.1.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8646e95016a7a6c4adea95bafa8a16baab64b583356217f2c85db4a39d9a86" +dependencies = [ + "proc-macro2", + "syn 1.0.109", +] + +[[package]] +name = "primitive-types" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f3486ccba82358b11a77516035647c34ba167dfa53312630de83b12bd4f3d66" +dependencies = [ + "fixed-hash", + "impl-codec", + "impl-rlp", + "impl-serde", + "scale-info", + "uint", +] + +[[package]] +name = "prioritized-metered-channel" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "382698e48a268c832d0b181ed438374a6bb708a82a8ca273bb0f61c74cf209c4" +dependencies = [ + "coarsetime", + "crossbeam-queue", + "derive_more", + "futures 0.3.28", + "futures-timer", + "nanorand", + "thiserror 1.0.44", + "tracing", +] + +[[package]] +name = "proc-macro-crate" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" +dependencies = [ + "once_cell 1.18.0", + "toml_edit 0.19.15", +] + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn 1.0.109", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro-hack" +version = "0.5.20+deprecated" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" + +[[package]] +name = "proc-macro-nested" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc881b2c22681370c6a780e47af9840ef841837bc98118431d4e1868bd0c1086" + +[[package]] +name = "proc-macro-warning" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e99670bafb56b9a106419397343bdbc8b8742c3cc449fec6345f86173f47cd4" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.32", +] + +[[package]] +name = "proc-macro2" +version = "1.0.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "procfs" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1de8dacb0873f77e6aefc6d71e044761fcc68060290f5b1089fcdf84626bb69" +dependencies = [ + "bitflags 1.3.2", + "byteorder 1.4.3", + "hex", + "lazy_static", + "rustix 0.36.15", +] + +[[package]] +name = "prometheus" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "449811d15fbdf5ceb5c1144416066429cf82316e2ec8ce0c1f6f8a02e7bbcf8c" +dependencies = [ + "cfg-if 1.0.0", + "fnv 1.0.7", + "lazy_static", + "libc", + "memchr 2.6.3", + "parking_lot 0.12.1", + "procfs", + "thiserror 1.0.44", +] + +[[package]] +name = "prometheus-client" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83cd1b99916654a69008fd66b4f9397fbe08e6e51dfe23d4417acf5d3b8cb87c" +dependencies = [ + "dtoa", + "itoa 1.0.9", + "parking_lot 0.12.1", + "prometheus-client-derive-text-encode", +] + +[[package]] +name = "prometheus-client-derive-text-encode" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66a455fbcb954c1a7decf3c586e860fd7889cddf4b8e164be736dbac95a953cd" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "prost" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b82eaa1d779e9a4bc1c3217db8ffbeabaae1dca241bf70183242128d48681cd" +dependencies = [ + "bytes 1.4.0", + "prost-derive", +] + +[[package]] +name = "prost-build" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "119533552c9a7ffacc21e099c24a0ac8bb19c2a2a3f363de84cd9b844feab270" +dependencies = [ + "bytes 1.4.0", + "heck", + "itertools 0.10.5", + "lazy_static", + "log 0.4.20", + "multimap", + "petgraph", + "prettyplease", + "prost", + "prost-types", + "regex 1.9.5", + "syn 1.0.109", + "tempfile", + "which", +] + +[[package]] +name = "prost-codec" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dc34979ff898b6e141106178981ce2596c387ea6e62533facfc61a37fc879c0" +dependencies = [ + "asynchronous-codec", + "bytes 1.4.0", + "prost", + "thiserror 1.0.44", + "unsigned-varint 0.7.1", +] + +[[package]] +name = "prost-derive" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5d2d8d10f3c6ded6da8b05b5fb3b8a5082514344d56c9f871412d29b4e075b4" +dependencies = [ + "anyhow", + "itertools 0.10.5", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "prost-types" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "213622a1460818959ac1181aaeb2dc9c7f63df720db7d788b3e24eacd1983e13" +dependencies = [ + "prost", +] + +[[package]] +name = "psm" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5787f7cda34e3033a72192c018bc5883100330f362ef279a8cbccfce8bb4e874" +dependencies = [ + "cc", +] + +[[package]] +name = "ptr_meta" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0738ccf7ea06b608c10564b31debd4f5bc5e197fc8bfe088f68ae5ce81e7a4f1" +dependencies = [ + "ptr_meta_derive", +] + +[[package]] +name = "ptr_meta_derive" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16b845dbfca988fa33db069c0e230574d15a3088f147a87b64c7589eb662c9ac" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" + +[[package]] +name = "quick-protobuf" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d6da84cc204722a989e01ba2f6e1e276e190f22263d0cb6ce8526fcdb0d2e1f" +dependencies = [ + "byteorder 1.4.3", +] + +[[package]] +name = "quicksink" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77de3c815e5a160b1539c6592796801df2043ae35e123b46d73380cfa57af858" +dependencies = [ + "futures-core 0.3.28", + "futures-sink 0.3.28", + "pin-project-lite 0.1.12", +] + +[[package]] +name = "quinn-proto" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67c10f662eee9c94ddd7135043e544f3c82fa839a1e7b865911331961b53186c" +dependencies = [ + "bytes 1.4.0", + "rand 0.8.5", + "ring 0.16.20", + "rustc-hash", + "rustls 0.20.8", + "slab 0.4.8", + "thiserror 1.0.44", + "tinyvec", + "tracing", + "webpki 0.22.0", +] + +[[package]] +name = "quote" +version = "1.0.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + +[[package]] +name = "rand" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" +dependencies = [ + "getrandom 0.1.16", + "libc", + "rand_chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_hc", +] + +[[package]] +name = "rand" +version = "0.7.3" +source = "git+https://github.com/mesalock-linux/rand-sgx?tag=sgx_1.1.3#83583f073de3b4f75c3c3ef5e174d484ed941f85" +dependencies = [ + "getrandom 0.1.14", + "rand_chacha 0.2.2 (git+https://github.com/mesalock-linux/rand-sgx?tag=sgx_1.1.3)", + "rand_core 0.5.1 (git+https://github.com/mesalock-linux/rand-sgx?tag=sgx_1.1.3)", + "sgx_tstd", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" +dependencies = [ + "ppv-lite86 0.2.17", + "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_chacha" +version = "0.2.2" +source = "git+https://github.com/mesalock-linux/rand-sgx?tag=sgx_1.1.3#83583f073de3b4f75c3c3ef5e174d484ed941f85" +dependencies = [ + "ppv-lite86 0.2.6", + "rand_core 0.5.1 (git+https://github.com/mesalock-linux/rand-sgx?tag=sgx_1.1.3)", + "sgx_tstd", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86 0.2.17", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_core" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" +dependencies = [ + "rand_core 0.4.2", +] + +[[package]] +name = "rand_core" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +dependencies = [ + "getrandom 0.1.16", +] + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "git+https://github.com/mesalock-linux/rand-sgx?tag=sgx_1.1.3#83583f073de3b4f75c3c3ef5e174d484ed941f85" +dependencies = [ + "getrandom 0.1.14", + "sgx_tstd", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.10", +] + +[[package]] +name = "rand_hc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +dependencies = [ + "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_pcg" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59cad018caf63deb318e5a4586d99a24424a364f40f1e5778c29aca23f4fc73e" +dependencies = [ + "rand_core 0.6.4", +] + +[[package]] +name = "rawpointer" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3" + +[[package]] +name = "rayon" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d" +dependencies = [ + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-utils", + "num_cpus", +] + +[[package]] +name = "rcgen" +version = "0.9.2" +source = "git+https://github.com/integritee-network/rcgen#1852c8dbeb74de36a422d218254b659497daf717" +dependencies = [ + "chrono 0.4.11", + "chrono 0.4.26", + "pem 0.8.2", + "pem 1.1.1", + "ring 0.16.19", + "ring 0.16.20", + "sgx_tstd", + "yasna 0.3.1", + "yasna 0.4.0", +] + +[[package]] +name = "rcgen" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6413f3de1edee53342e6138e75b56d32e7bc6e332b3bd62d497b1929d4cfbcdd" +dependencies = [ + "pem 1.1.1", + "ring 0.16.20", + "time 0.3.22", + "x509-parser 0.13.2", + "yasna 0.5.2", +] + +[[package]] +name = "rcgen" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffbe84efe2f38dea12e9bfc1f65377fdf03e53a18cb3b995faedf7934c7e785b" +dependencies = [ + "pem 1.1.1", + "ring 0.16.20", + "time 0.3.22", + "yasna 0.5.2", +] + +[[package]] +name = "rdrand" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5014f842b5515f60c15d3bca398477951f785883f73e7f9bc8a9d9c9bb6821c7" +dependencies = [ + "rand_core 0.4.2", +] + +[[package]] +name = "redox_syscall" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "redox_syscall" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "redox_users" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" +dependencies = [ + "getrandom 0.2.10", + "redox_syscall 0.2.16", + "thiserror 1.0.44", +] + +[[package]] +name = "ref-cast" +version = "1.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61ef7e18e8841942ddb1cf845054f8008410030a3997875d9e49b7a363063df1" +dependencies = [ + "ref-cast-impl", +] + +[[package]] +name = "ref-cast-impl" +version = "1.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dfaf0c85b766276c797f3791f5bc6d5bd116b41d53049af2789666b0c0bc9fa" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.32", +] + +[[package]] +name = "regalloc2" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "300d4fbfb40c1c66a78ba3ddd41c1110247cf52f97b87d0f2fc9209bd49b030c" +dependencies = [ + "fxhash", + "log 0.4.20", + "slice-group-by", + "smallvec 1.11.0", +] + +[[package]] +name = "regex" +version = "1.3.1" +source = "git+https://github.com/mesalock-linux/regex-sgx#76aef86f9836532d17764523d0fa23bb7d2e31cf" +dependencies = [ + "regex-syntax 0.6.12", + "sgx_tstd", +] + +[[package]] +name = "regex" +version = "1.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "697061221ea1b4a94a624f67d0ae2bfe4e22b8a17b6a192afb11046542cc8c47" +dependencies = [ + "aho-corasick", + "memchr 2.6.3", + "regex-automata 0.3.8", + "regex-syntax 0.7.5", +] + +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax 0.6.29", +] + +[[package]] +name = "regex-automata" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2f401f4955220693b56f8ec66ee9c78abffd8d1c4f23dc41a23839eb88f0795" +dependencies = [ + "aho-corasick", + "memchr 2.6.3", + "regex-syntax 0.7.5", +] + +[[package]] +name = "regex-syntax" +version = "0.6.12" +source = "git+https://github.com/mesalock-linux/regex-sgx#76aef86f9836532d17764523d0fa23bb7d2e31cf" +dependencies = [ + "sgx_tstd", +] + +[[package]] +name = "regex-syntax" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + +[[package]] +name = "regex-syntax" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" + +[[package]] +name = "region" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76e189c2369884dce920945e2ddf79b3dff49e071a167dd1817fa9c4c00d512e" +dependencies = [ + "bitflags 1.3.2", + "libc", + "mach", + "winapi 0.3.9", +] + +[[package]] +name = "reqwest" +version = "0.11.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e9ad3fe7488d7e34558a2033d45a0c90b72d97b4f80705666fea71472e2e6a1" +dependencies = [ + "base64 0.21.2", + "bytes 1.4.0", + "encoding_rs", + "futures-core 0.3.28", + "futures-util 0.3.28", + "h2", + "http 0.2.9", + "http-body", + "hyper", + "hyper-tls", + "ipnet", + "js-sys", + "log 0.4.20", + "mime", + "native-tls", + "once_cell 1.18.0", + "percent-encoding 2.3.0", + "pin-project-lite 0.2.10", + "serde 1.0.193", + "serde_json 1.0.103", + "serde_urlencoded", + "tokio", + "tokio-native-tls", + "tower-service", + "url 2.4.0", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "winreg", +] + +[[package]] +name = "resolv-conf" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52e44394d2086d010551b14b53b1f24e31647570cd1deb0379e2c21b329aba00" +dependencies = [ + "hostname", + "quick-error", +] + +[[package]] +name = "rfc6979" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7743f17af12fa0b03b803ba12cd6a8d9483a587e89c69445e3909655c0b9fabb" +dependencies = [ + "crypto-bigint 0.4.9", + "hmac 0.12.1", + "zeroize", +] + +[[package]] +name = "rfc6979" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" +dependencies = [ + "hmac 0.12.1", + "subtle", +] + +[[package]] +name = "ring" +version = "0.16.19" +source = "git+https://github.com/mesalock-linux/ring-sgx?tag=v0.16.5#844efe271ed78a399d803b2579f5f2424d543c9f" +dependencies = [ + "cc", + "sgx_tstd", + "spin 0.5.2", + "untrusted 0.7.1", +] + +[[package]] +name = "ring" +version = "0.16.20" +source = "git+https://github.com/betrusted-io/ring-xous?branch=0.16.20-cleanup#4296c2e7904898766cf7d8d589759a129794783b" +dependencies = [ + "cc", + "libc", + "log 0.4.20", + "once_cell 1.18.0", + "rkyv", + "spin 0.5.2", + "untrusted 0.7.1", + "winapi 0.3.9", + "xous", + "xous-api-names", + "xous-ipc", +] + +[[package]] +name = "ripemd" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd124222d17ad93a644ed9d011a40f4fb64aa54275c08cc216524a9ea82fb09f" +dependencies = [ + "digest 0.10.7", +] + +[[package]] +name = "rkyv" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70de01b38fe7baba4ecdd33b777096d2b326993d8ea99bc5b6ede691883d3010" +dependencies = [ + "memoffset 0.6.5", + "ptr_meta", + "rkyv_derive", +] + +[[package]] +name = "rkyv_derive" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95a169f6bc5a81033e86ed39d0f4150e2608160b73d2b93c6e8e6a3efa873f14" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "rlp" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb919243f34364b6bd2fc10ef797edbfa75f33c252e7998527479c6d6b47e1ec" +dependencies = [ + "bytes 1.4.0", + "rlp-derive", + "rustc-hex", +] + +[[package]] +name = "rlp-derive" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e33d7b2abe0c340d8797fe2907d3f20d3b5ea5908683618bfe80df7f621f672a" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "rocksdb" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "015439787fce1e75d55f279078d33ff14b4af5d93d995e8838ee4631301c8a99" +dependencies = [ + "libc", + "librocksdb-sys", +] + +[[package]] +name = "rococo-parachain-runtime" +version = "0.9.17" +dependencies = [ + "core-primitives", + "cumulus-pallet-aura-ext", + "cumulus-pallet-dmp-queue", + "cumulus-pallet-parachain-system", + "cumulus-pallet-xcm", + "cumulus-pallet-xcmp-queue", + "cumulus-primitives-core", + "cumulus-primitives-timestamp", + "cumulus-primitives-utility", + "fp-rpc", + "fp-self-contained", + "frame-benchmarking", + "frame-executive", + "frame-support", + "frame-system", + "frame-system-benchmarking", + "frame-system-rpc-runtime-api", + "frame-try-runtime", + "hex-literal", + "log 0.4.20", + "moonbeam-evm-tracer", + "moonbeam-rpc-primitives-debug", + "moonbeam-rpc-primitives-txpool", + "orml-tokens", + "orml-traits", + "orml-xtokens", + "pallet-asset-manager", + "pallet-aura", + "pallet-authorship", + "pallet-balances", + "pallet-bounties", + "pallet-bridge", + "pallet-bridge-transfer", + "pallet-collective", + "pallet-democracy", + "pallet-drop3", + "pallet-ethereum", + "pallet-evm 6.0.0-dev (git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42)", + "pallet-evm-precompile-blake2", + "pallet-evm-precompile-bn128", + "pallet-evm-precompile-bridge-transfer", + "pallet-evm-precompile-dispatch", + "pallet-evm-precompile-ed25519", + "pallet-evm-precompile-modexp", + "pallet-evm-precompile-parachain-staking", + "pallet-evm-precompile-sha3fips", + "pallet-evm-precompile-simple", + "pallet-extrinsic-filter", + "pallet-group", + "pallet-identity", + "pallet-identity-management", + "pallet-membership", + "pallet-multisig", + "pallet-parachain-staking", + "pallet-preimage", + "pallet-proxy", + "pallet-scheduler", + "pallet-session", + "pallet-sidechain", + "pallet-sudo", + "pallet-teeracle", + "pallet-teerex", + "pallet-timestamp", + "pallet-tips", + "pallet-transaction-payment", + "pallet-transaction-payment-rpc-runtime-api", + "pallet-treasury", + "pallet-utility", + "pallet-vc-management", + "pallet-vesting", + "pallet-xcm", + "parachain-info", + "parity-scale-codec", + "polkadot-parachain", + "runtime-common", + "scale-info", + "sp-api", + "sp-block-builder", + "sp-consensus-aura", + "sp-core", + "sp-inherents", + "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", + "sp-offchain", + "sp-runtime", + "sp-session", + "sp-std 5.0.0", + "sp-transaction-pool", + "sp-version", + "substrate-wasm-builder", + "xcm", + "xcm-builder", + "xcm-executor", +] + +[[package]] +name = "ron" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88073939a61e5b7680558e6be56b419e208420c2adb92be54921fa6b72283f1a" +dependencies = [ + "base64 0.13.1", + "bitflags 1.3.2", + "serde 1.0.193", +] + +[[package]] +name = "rpassword" +version = "7.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6678cf63ab3491898c0d021b493c94c9b221d91295294a2a5746eacbe5928322" +dependencies = [ + "libc", + "rtoolbox", + "winapi 0.3.9", +] + +[[package]] +name = "rtcp" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1919efd6d4a6a85d13388f9487549bb8e359f17198cc03ffd72f79b553873691" +dependencies = [ + "bytes 1.4.0", + "thiserror 1.0.44", + "webrtc-util", +] + +[[package]] +name = "rtnetlink" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "322c53fd76a18698f1c27381d58091de3a043d356aa5bd0d510608b565f469a0" +dependencies = [ + "futures 0.3.28", + "log 0.4.20", + "netlink-packet-route", + "netlink-proto", + "nix", + "thiserror 1.0.44", + "tokio", +] + +[[package]] +name = "rtoolbox" +version = "0.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "034e22c514f5c0cb8a10ff341b9b048b5ceb21591f31c8f44c43b960f9b3524a" +dependencies = [ + "libc", + "winapi 0.3.9", +] + +[[package]] +name = "rtp" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2a095411ff00eed7b12e4c6a118ba984d113e1079582570d56a5ee723f11f80" +dependencies = [ + "async-trait", + "bytes 1.4.0", + "rand 0.8.5", + "serde 1.0.193", + "thiserror 1.0.44", + "webrtc-util", +] + +[[package]] +name = "runtime-common" +version = "0.9.17" +dependencies = [ + "core-primitives", + "cumulus-pallet-parachain-system", + "cumulus-primitives-core", + "cumulus-primitives-parachain-inherent", + "frame-support", + "frame-system", + "log 0.4.20", + "orml-tokens", + "orml-traits", + "orml-xtokens", + "pallet-asset-manager", + "pallet-authorship", + "pallet-balances", + "pallet-collective", + "pallet-extrinsic-filter", + "pallet-group", + "pallet-membership", + "pallet-multisig", + "pallet-teerex", + "pallet-transaction-payment", + "pallet-treasury", + "pallet-vesting", + "pallet-xcm", + "parachain-info", + "parity-scale-codec", + "polkadot-parachain", + "polkadot-primitives", + "polkadot-runtime-parachains", + "scale-info", + "sp-core", + "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", + "sp-runtime", + "sp-state-machine", + "sp-std 5.0.0", + "teerex-primitives", + "xcm", + "xcm-builder", + "xcm-executor", +] + +[[package]] +name = "rust-base58" +version = "0.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b313b91fcdc6719ad41fa2dad2b7e810b03833fae4bf911950e15529a5f04439" +dependencies = [ + "num 0.4.1", +] + +[[package]] +name = "rust-base58" +version = "0.0.4" +source = "git+https://github.com/mesalock-linux/rust-base58-sgx?rev=sgx_1.1.3#13fb3e0a543690e6e19332f37ba85fd74c56cb2f" +dependencies = [ + "num 0.2.0", + "sgx_tstd", +] + +[[package]] +name = "rust-ini" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6d5f2436026b4f6e79dc829837d467cc7e9a55ee40e750d716713540715a2df" +dependencies = [ + "cfg-if 1.0.0", + "ordered-multimap", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustc-hex" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" + +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver 1.0.18", +] + +[[package]] +name = "rusticata-macros" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "faf0c4a6ece9950b9abdb62b1cfcf2a68b3b67a10ba445b3bb85be2a293d0632" +dependencies = [ + "nom", +] + +[[package]] +name = "rustix" +version = "0.36.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c37f1bd5ef1b5422177b7646cba67430579cfe2ace80f284fee876bca52ad941" +dependencies = [ + "bitflags 1.3.2", + "errno", + "io-lifetimes", + "libc", + "linux-raw-sys 0.1.4", + "windows-sys 0.45.0", +] + +[[package]] +name = "rustix" +version = "0.37.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d69718bf81c6127a49dc64e44a742e8bb9213c0ff8869a22c308f84c1d4ab06" +dependencies = [ + "bitflags 1.3.2", + "errno", + "io-lifetimes", + "libc", + "linux-raw-sys 0.3.8", + "windows-sys 0.48.0", +] + +[[package]] +name = "rustix" +version = "0.38.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a962918ea88d644592894bc6dc55acc6c0956488adcebbfb6e273506b7fd6e5" +dependencies = [ + "bitflags 2.3.3", + "errno", + "libc", + "linux-raw-sys 0.4.3", + "windows-sys 0.48.0", +] + +[[package]] +name = "rustls" +version = "0.19.0" +source = "git+https://github.com/mesalock-linux/rustls?tag=sgx_1.1.3#95b5e79dc24b02f3ce424437eb9698509d0baf58" +dependencies = [ + "base64 0.13.0 (git+https://github.com/mesalock-linux/rust-base64-sgx)", + "log 0.4.14 (git+https://github.com/mesalock-linux/log-sgx)", + "ring 0.16.19", + "sct 0.6.0", + "sgx_tstd", + "webpki 0.21.4 (git+https://github.com/mesalock-linux/webpki?branch=mesalock_sgx)", +] + +[[package]] +name = "rustls" +version = "0.19.0" +source = "git+https://github.com/mesalock-linux/rustls?branch=mesalock_sgx#95b5e79dc24b02f3ce424437eb9698509d0baf58" +dependencies = [ + "base64 0.13.0 (git+https://github.com/mesalock-linux/rust-base64-sgx)", + "log 0.4.14 (git+https://github.com/mesalock-linux/log-sgx)", + "ring 0.16.19", + "sct 0.6.0", + "sgx_tstd", + "webpki 0.21.4 (git+https://github.com/mesalock-linux/webpki?branch=mesalock_sgx)", +] + +[[package]] +name = "rustls" +version = "0.19.0" +source = "git+https://github.com/mesalock-linux/rustls?rev=sgx_1.1.3#95b5e79dc24b02f3ce424437eb9698509d0baf58" +dependencies = [ + "base64 0.13.0 (git+https://github.com/mesalock-linux/rust-base64-sgx)", + "log 0.4.14 (git+https://github.com/mesalock-linux/log-sgx)", + "ring 0.16.19", + "sct 0.6.0", + "sgx_tstd", + "webpki 0.21.4 (git+https://github.com/mesalock-linux/webpki?branch=mesalock_sgx)", +] + +[[package]] +name = "rustls" +version = "0.19.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35edb675feee39aec9c99fa5ff985081995a06d594114ae14cbe797ad7b7a6d7" +dependencies = [ + "base64 0.13.1", + "log 0.4.20", + "ring 0.16.20", + "sct 0.6.1", + "webpki 0.21.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rustls" +version = "0.20.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fff78fc74d175294f4e83b28343315ffcfb114b156f0185e9741cb5570f50e2f" +dependencies = [ + "log 0.4.20", + "ring 0.16.20", + "sct 0.7.0", + "webpki 0.22.0", +] + +[[package]] +name = "rustls-native-certs" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a07b7c1885bd8ed3831c289b7870b13ef46fe0e856d288c30d9cc17d75a2092" +dependencies = [ + "openssl-probe", + "rustls 0.19.1", + "schannel", + "security-framework", +] + +[[package]] +name = "rustls-native-certs" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9aace74cb666635c918e9c12bc0d348266037aa8eb599b5cba565709a8dff00" +dependencies = [ + "openssl-probe", + "rustls-pemfile", + "schannel", + "security-framework", +] + +[[package]] +name = "rustls-pemfile" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d3987094b1d07b653b7dfdc3f70ce9a1da9c51ac18c1b06b662e4f9a0e9f4b2" +dependencies = [ + "base64 0.21.2", +] + +[[package]] +name = "rustls-pki-types" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a47003264dea418db67060fa420ad16d0d2f8f0a0360d825c00e177ac52cb5d8" + +[[package]] +name = "rustls-webpki" +version = "0.102.0-alpha.3" +source = "git+https://github.com/rustls/webpki?rev=da923ed#da923edaab56f599971e58773617fb574cd019dc" +dependencies = [ + "ring 0.16.20", + "rustls-pki-types", + "untrusted 0.9.0", +] + +[[package]] +name = "rustversion" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" + +[[package]] +name = "rw-stream-sink" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26338f5e09bb721b85b135ea05af7767c90b52f6de4f087d4f4a3a9d64e7dc04" +dependencies = [ + "futures 0.3.28", + "pin-project", + "static_assertions", +] + +[[package]] +name = "ryu" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" + +[[package]] +name = "safe-lock" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "077d73db7973cccf63eb4aff1e5a34dc2459baa867512088269ea5f2f4253c90" + +[[package]] +name = "safe_arch" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f398075ce1e6a179b46f51bd88d0598b92b00d3551f1a2d4ac49e771b56ac354" +dependencies = [ + "bytemuck", +] + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "sc-allocator" +version = "4.1.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "log 0.4.20", + "sp-core", + "sp-wasm-interface", + "thiserror 1.0.44", +] + +[[package]] +name = "sc-authority-discovery" +version = "0.10.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "async-trait", + "futures 0.3.28", + "futures-timer", + "ip_network", + "libp2p", + "log 0.4.20", + "parity-scale-codec", + "prost", + "prost-build", + "rand 0.8.5", + "sc-client-api", + "sc-network", + "sc-network-common", + "sp-api", + "sp-authority-discovery", + "sp-blockchain", + "sp-core", + "sp-keystore", + "sp-runtime", + "substrate-prometheus-endpoint", + "thiserror 1.0.44", +] + +[[package]] +name = "sc-block-builder" +version = "0.10.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "parity-scale-codec", + "sc-client-api", + "sp-api", + "sp-block-builder", + "sp-blockchain", + "sp-core", + "sp-inherents", + "sp-runtime", +] + +[[package]] +name = "sc-chain-spec" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "memmap2", + "sc-chain-spec-derive", + "sc-client-api", + "sc-executor", + "sc-network", + "sc-telemetry", + "serde 1.0.193", + "serde_json 1.0.103", + "sp-blockchain", + "sp-core", + "sp-runtime", + "sp-state-machine", +] + +[[package]] +name = "sc-chain-spec-derive" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.32", +] + +[[package]] +name = "sc-cli" +version = "0.10.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "array-bytes 4.2.0", + "chrono 0.4.26", + "clap 4.1.0", + "fdlimit", + "futures 0.3.28", + "libp2p", + "log 0.4.20", + "names", + "parity-scale-codec", + "rand 0.8.5", + "regex 1.9.5", + "rpassword", + "sc-client-api", + "sc-client-db", + "sc-keystore", + "sc-network", + "sc-network-common", + "sc-service", + "sc-telemetry", + "sc-tracing", + "sc-utils", + "serde 1.0.193", + "serde_json 1.0.103", + "sp-blockchain", + "sp-core", + "sp-keyring", + "sp-keystore", + "sp-panic-handler", + "sp-runtime", + "sp-version", + "thiserror 1.0.44", + "tiny-bip39", + "tokio", +] + +[[package]] +name = "sc-client-api" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "fnv 1.0.7", + "futures 0.3.28", + "log 0.4.20", + "parity-scale-codec", + "parking_lot 0.12.1", + "sc-executor", + "sc-transaction-pool-api", + "sc-utils", + "sp-api", + "sp-blockchain", + "sp-consensus", + "sp-core", + "sp-database", + "sp-externalities", + "sp-keystore", + "sp-runtime", + "sp-state-machine", + "sp-storage", + "substrate-prometheus-endpoint", +] + +[[package]] +name = "sc-client-db" +version = "0.10.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "hash-db 0.16.0", + "kvdb", + "kvdb-memorydb", + "kvdb-rocksdb", + "linked-hash-map 0.5.6", + "log 0.4.20", + "parity-db", + "parity-scale-codec", + "parking_lot 0.12.1", + "sc-client-api", + "sc-state-db", + "schnellru", + "sp-arithmetic", + "sp-blockchain", + "sp-core", + "sp-database", + "sp-runtime", + "sp-state-machine", + "sp-trie", +] + +[[package]] +name = "sc-consensus" +version = "0.10.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "async-trait", + "futures 0.3.28", + "futures-timer", + "libp2p", + "log 0.4.20", + "mockall", + "parking_lot 0.12.1", + "sc-client-api", + "sc-utils", + "serde 1.0.193", + "sp-api", + "sp-blockchain", + "sp-consensus", + "sp-core", + "sp-runtime", + "sp-state-machine", + "substrate-prometheus-endpoint", + "thiserror 1.0.44", +] + +[[package]] +name = "sc-executor" +version = "0.10.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "lru 0.8.1", + "parity-scale-codec", + "parking_lot 0.12.1", + "sc-executor-common", + "sc-executor-wasmi", + "sc-executor-wasmtime", + "sp-api", + "sp-core", + "sp-externalities", + "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", + "sp-panic-handler", + "sp-runtime-interface", + "sp-trie", + "sp-version", + "sp-wasm-interface", + "tracing", + "wasmi", +] + +[[package]] +name = "sc-executor-common" +version = "0.10.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "sc-allocator", + "sp-maybe-compressed-blob", + "sp-wasm-interface", + "thiserror 1.0.44", + "wasm-instrument", + "wasmi", +] + +[[package]] +name = "sc-executor-wasmi" +version = "0.10.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "log 0.4.20", + "sc-allocator", + "sc-executor-common", + "sp-runtime-interface", + "sp-wasm-interface", + "wasmi", +] + +[[package]] +name = "sc-executor-wasmtime" +version = "0.10.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "anyhow", + "cfg-if 1.0.0", + "libc", + "log 0.4.20", + "once_cell 1.18.0", + "rustix 0.36.15", + "sc-allocator", + "sc-executor-common", + "sp-runtime-interface", + "sp-wasm-interface", + "wasmtime", +] + +[[package]] +name = "sc-informant" +version = "0.10.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "ansi_term", + "futures 0.3.28", + "futures-timer", + "log 0.4.20", + "sc-client-api", + "sc-network", + "sc-network-common", + "sp-blockchain", + "sp-runtime", +] + +[[package]] +name = "sc-keystore" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "array-bytes 4.2.0", + "async-trait", + "parking_lot 0.12.1", + "serde_json 1.0.103", + "sp-application-crypto", + "sp-core", + "sp-keystore", + "thiserror 1.0.44", +] + +[[package]] +name = "sc-network" +version = "0.10.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "array-bytes 4.2.0", + "async-channel", + "async-trait", + "asynchronous-codec", + "bytes 1.4.0", + "either", + "fnv 1.0.7", + "futures 0.3.28", + "futures-timer", + "ip_network", + "libp2p", + "linked_hash_set", + "log 0.4.20", + "lru 0.8.1", + "mockall", + "parity-scale-codec", + "parking_lot 0.12.1", + "pin-project", + "rand 0.8.5", + "sc-block-builder", + "sc-client-api", + "sc-consensus", + "sc-network-common", + "sc-peerset", + "sc-utils", + "serde 1.0.193", + "serde_json 1.0.103", + "smallvec 1.11.0", + "snow", + "sp-arithmetic", + "sp-blockchain", + "sp-consensus", + "sp-core", + "sp-runtime", + "substrate-prometheus-endpoint", + "thiserror 1.0.44", + "unsigned-varint 0.7.1", + "zeroize", +] + +[[package]] +name = "sc-network-bitswap" +version = "0.10.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "cid", + "futures 0.3.28", + "libp2p", + "log 0.4.20", + "prost", + "prost-build", + "sc-client-api", + "sc-network", + "sc-network-common", + "sp-blockchain", + "sp-runtime", + "thiserror 1.0.44", + "unsigned-varint 0.7.1", +] + +[[package]] +name = "sc-network-common" +version = "0.10.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "array-bytes 4.2.0", + "async-trait", + "bitflags 1.3.2", + "bytes 1.4.0", + "futures 0.3.28", + "futures-timer", + "libp2p", + "parity-scale-codec", + "prost-build", + "sc-consensus", + "sc-peerset", + "sc-utils", + "serde 1.0.193", + "smallvec 1.11.0", + "sp-blockchain", + "sp-consensus", + "sp-consensus-grandpa", + "sp-runtime", + "substrate-prometheus-endpoint", + "thiserror 1.0.44", + "zeroize", +] + +[[package]] +name = "sc-network-light" +version = "0.10.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "array-bytes 4.2.0", + "futures 0.3.28", + "libp2p", + "log 0.4.20", + "parity-scale-codec", + "prost", + "prost-build", + "sc-client-api", + "sc-network", + "sc-network-common", + "sc-peerset", + "sp-blockchain", + "sp-core", + "sp-runtime", + "thiserror 1.0.44", +] + +[[package]] +name = "sc-network-sync" +version = "0.10.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "array-bytes 4.2.0", + "async-trait", + "fork-tree 3.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", + "futures 0.3.28", + "futures-timer", + "libp2p", + "log 0.4.20", + "lru 0.8.1", + "mockall", + "parity-scale-codec", + "prost", + "prost-build", + "sc-client-api", + "sc-consensus", + "sc-network", + "sc-network-common", + "sc-peerset", + "sc-utils", + "smallvec 1.11.0", + "sp-arithmetic", + "sp-blockchain", + "sp-consensus", + "sp-consensus-grandpa", + "sp-core", + "sp-runtime", + "substrate-prometheus-endpoint", + "thiserror 1.0.44", +] + +[[package]] +name = "sc-network-transactions" +version = "0.10.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "array-bytes 4.2.0", + "futures 0.3.28", + "libp2p", + "log 0.4.20", + "parity-scale-codec", + "pin-project", + "sc-network", + "sc-network-common", + "sc-peerset", + "sc-utils", + "sp-consensus", + "sp-runtime", + "substrate-prometheus-endpoint", +] + +[[package]] +name = "sc-offchain" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "array-bytes 4.2.0", + "bytes 1.4.0", + "fnv 1.0.7", + "futures 0.3.28", + "futures-timer", + "hyper", + "hyper-rustls 0.23.2", + "libp2p", + "num_cpus", + "once_cell 1.18.0", + "parity-scale-codec", + "parking_lot 0.12.1", + "rand 0.8.5", + "sc-client-api", + "sc-network", + "sc-network-common", + "sc-peerset", + "sc-utils", + "sp-api", + "sp-core", + "sp-offchain", + "sp-runtime", + "threadpool", + "tracing", +] + +[[package]] +name = "sc-peerset" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "futures 0.3.28", + "libp2p", + "log 0.4.20", + "sc-utils", + "serde_json 1.0.103", + "wasm-timer", +] + +[[package]] +name = "sc-rpc" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "futures 0.3.28", + "jsonrpsee 0.16.2", + "log 0.4.20", + "parity-scale-codec", + "parking_lot 0.12.1", + "sc-block-builder", + "sc-chain-spec", + "sc-client-api", + "sc-rpc-api", + "sc-tracing", + "sc-transaction-pool-api", + "sc-utils", + "serde_json 1.0.103", + "sp-api", + "sp-blockchain", + "sp-core", + "sp-keystore", + "sp-offchain", + "sp-rpc", + "sp-runtime", + "sp-session", + "sp-version", + "tokio", +] + +[[package]] +name = "sc-rpc-api" +version = "0.10.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "jsonrpsee 0.16.2", + "parity-scale-codec", + "sc-chain-spec", + "sc-transaction-pool-api", + "scale-info", + "serde 1.0.193", + "serde_json 1.0.103", + "sp-core", + "sp-rpc", + "sp-runtime", + "sp-version", + "thiserror 1.0.44", +] + +[[package]] +name = "sc-rpc-server" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "http 0.2.9", + "jsonrpsee 0.16.2", + "log 0.4.20", + "serde_json 1.0.103", + "substrate-prometheus-endpoint", + "tokio", + "tower", + "tower-http", +] + +[[package]] +name = "sc-rpc-spec-v2" +version = "0.10.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "array-bytes 4.2.0", + "futures 0.3.28", + "futures-util 0.3.28", + "hex", + "jsonrpsee 0.16.2", + "log 0.4.20", + "parity-scale-codec", + "parking_lot 0.12.1", + "sc-chain-spec", + "sc-client-api", + "sc-transaction-pool-api", + "serde 1.0.193", + "sp-api", + "sp-blockchain", + "sp-core", + "sp-runtime", + "sp-version", + "thiserror 1.0.44", + "tokio-stream", +] + +[[package]] +name = "sc-service" +version = "0.10.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "async-trait", + "directories", + "exit-future", + "futures 0.3.28", + "futures-timer", + "jsonrpsee 0.16.2", + "log 0.4.20", + "parity-scale-codec", + "parking_lot 0.12.1", + "pin-project", + "rand 0.8.5", + "sc-block-builder", + "sc-chain-spec", + "sc-client-api", + "sc-client-db", + "sc-consensus", + "sc-executor", + "sc-informant", + "sc-keystore", + "sc-network", + "sc-network-bitswap", + "sc-network-common", + "sc-network-light", + "sc-network-sync", + "sc-network-transactions", + "sc-offchain", + "sc-rpc", + "sc-rpc-server", + "sc-rpc-spec-v2", + "sc-storage-monitor", + "sc-sysinfo", + "sc-telemetry", + "sc-tracing", + "sc-transaction-pool", + "sc-transaction-pool-api", + "sc-utils", + "serde 1.0.193", + "serde_json 1.0.103", + "sp-api", + "sp-blockchain", + "sp-consensus", + "sp-core", + "sp-externalities", + "sp-keystore", + "sp-runtime", + "sp-session", + "sp-state-machine", + "sp-storage", + "sp-transaction-pool", + "sp-transaction-storage-proof", + "sp-trie", + "sp-version", + "static_init", + "substrate-prometheus-endpoint", + "tempfile", + "thiserror 1.0.44", + "tokio", + "tracing", + "tracing-futures", +] + +[[package]] +name = "sc-state-db" +version = "0.10.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "log 0.4.20", + "parity-scale-codec", + "parking_lot 0.12.1", + "sp-core", +] + +[[package]] +name = "sc-storage-monitor" +version = "0.1.0" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "clap 4.1.0", + "fs4", + "futures 0.3.28", + "log 0.4.20", + "sc-client-db", + "sc-utils", + "sp-core", + "thiserror 1.0.44", + "tokio", +] + +[[package]] +name = "sc-sysinfo" +version = "6.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "futures 0.3.28", + "libc", + "log 0.4.20", + "rand 0.8.5", + "rand_pcg", + "regex 1.9.5", + "sc-telemetry", + "serde 1.0.193", + "serde_json 1.0.103", + "sp-core", + "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", + "sp-std 5.0.0", +] + +[[package]] +name = "sc-telemetry" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "chrono 0.4.26", + "futures 0.3.28", + "libp2p", + "log 0.4.20", + "parking_lot 0.12.1", + "pin-project", + "rand 0.8.5", + "sc-utils", + "serde 1.0.193", + "serde_json 1.0.103", + "thiserror 1.0.44", + "wasm-timer", +] + +[[package]] +name = "sc-tracing" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "ansi_term", + "atty", + "chrono 0.4.26", + "lazy_static", + "libc", + "log 0.4.20", + "once_cell 1.18.0", + "parking_lot 0.12.1", + "regex 1.9.5", + "rustc-hash", + "sc-client-api", + "sc-rpc-server", + "sc-tracing-proc-macro", + "serde 1.0.193", + "sp-api", + "sp-blockchain", + "sp-core", + "sp-rpc", + "sp-runtime", + "sp-tracing", + "thiserror 1.0.44", + "tracing", + "tracing-log", + "tracing-subscriber", +] + +[[package]] +name = "sc-tracing-proc-macro" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.32", +] + +[[package]] +name = "sc-transaction-pool" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "async-trait", + "futures 0.3.28", + "futures-timer", + "linked-hash-map 0.5.6", + "log 0.4.20", + "num-traits 0.2.16", + "parity-scale-codec", + "parking_lot 0.12.1", + "sc-client-api", + "sc-transaction-pool-api", + "sc-utils", + "serde 1.0.193", + "sp-api", + "sp-blockchain", + "sp-core", + "sp-runtime", + "sp-tracing", + "sp-transaction-pool", + "substrate-prometheus-endpoint", + "thiserror 1.0.44", +] + +[[package]] +name = "sc-transaction-pool-api" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "async-trait", + "futures 0.3.28", + "log 0.4.20", + "serde 1.0.193", + "sp-blockchain", + "sp-runtime", + "thiserror 1.0.44", +] + +[[package]] +name = "sc-utils" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "async-channel", + "futures 0.3.28", + "futures-timer", + "lazy_static", + "log 0.4.20", + "parking_lot 0.12.1", + "prometheus", + "sp-arithmetic", +] + +[[package]] +name = "scale-bits" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8dd7aca73785181cc41f0bbe017263e682b585ca660540ba569133901d013ecf" +dependencies = [ + "parity-scale-codec", + "scale-info", + "serde 1.0.193", +] + +[[package]] +name = "scale-bits" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "036575c29af9b6e4866ffb7fa055dbf623fe7a9cc159b33786de6013a6969d89" +dependencies = [ + "parity-scale-codec", + "scale-info", + "serde 1.0.193", +] + +[[package]] +name = "scale-decode" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d823d4be477fc33321f93d08fb6c2698273d044f01362dc27573a750deb7c233" +dependencies = [ + "parity-scale-codec", + "scale-bits 0.3.0", + "scale-info", + "thiserror 1.0.44", +] + +[[package]] +name = "scale-decode" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea509715113edab351e1f4d51fba6b186653259049a1155b52e2e994dd2f0e6d" +dependencies = [ + "parity-scale-codec", + "primitive-types", + "scale-bits 0.4.0", + "scale-decode-derive", + "scale-info", + "smallvec 1.11.0", +] + +[[package]] +name = "scale-decode-derive" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66c9d7a1341497e9d016722144310de3dc6c933909c0376017c88f65092fff37" +dependencies = [ + "darling", + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "scale-encode" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f6f51bc8cd927dab2f4567b1a8a8e9d7fd5d0866f2dbc7c84fc97cfa9383a26" +dependencies = [ + "parity-scale-codec", + "primitive-types", + "scale-bits 0.4.0", + "scale-encode-derive", + "scale-info", + "smallvec 1.11.0", +] + +[[package]] +name = "scale-encode-derive" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f28be1877787156a2df01be3c029b92bdffa6b6a9748d4996e383fff218c88f3" +dependencies = [ + "darling", + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "scale-info" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f7d66a1128282b7ef025a8ead62a4a9fcf017382ec53b8ffbf4d7bf77bd3c60" +dependencies = [ + "bitvec", + "cfg-if 1.0.0", + "derive_more", + "parity-scale-codec", + "scale-info-derive", + "serde 1.0.193", +] + +[[package]] +name = "scale-info-derive" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abf2c68b89cafb3b8d918dd07b42be0da66ff202cf1155c5739a4e0c1ea0dc19" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "scale-value" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16a5e7810815bd295da73e4216d1dfbced3c7c7c7054d70fa5f6e4c58123fff4" +dependencies = [ + "either", + "frame-metadata", + "parity-scale-codec", + "scale-bits 0.3.0", + "scale-decode 0.4.0", + "scale-info", + "serde 1.0.193", + "thiserror 1.0.44", + "yap", +] + +[[package]] +name = "schannel" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88" +dependencies = [ + "windows-sys 0.48.0", +] + +[[package]] +name = "schnellru" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "772575a524feeb803e5b0fcbc6dd9f367e579488197c94c6e4023aad2305774d" +dependencies = [ + "ahash 0.8.3", + "cfg-if 1.0.0", + "hashbrown 0.13.2", +] + +[[package]] +name = "schnorrkel" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "021b403afe70d81eea68f6ea12f6b3c9588e5d536a94c3bf80f15e7faa267862" +dependencies = [ + "arrayref", + "arrayvec 0.5.2", + "curve25519-dalek 2.1.3", + "getrandom 0.1.16", + "merlin", + "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.8.2", + "subtle", + "zeroize", +] + +[[package]] +name = "scoped-tls" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "scratch" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1792db035ce95be60c3f8853017b3999209281c24e2ba5bc8e59bf97a0c590c1" + +[[package]] +name = "sct" +version = "0.6.0" +source = "git+https://github.com/mesalock-linux/sct.rs?branch=mesalock_sgx#c4d859cca232e6c9d88ca12048df3bc26e1ed4ad" +dependencies = [ + "ring 0.16.19", + "sgx_tstd", + "untrusted 0.7.1", +] + +[[package]] +name = "sct" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b362b83898e0e69f38515b82ee15aa80636befe47c3b6d3d89a911e78fc228ce" +dependencies = [ + "ring 0.16.20", + "untrusted 0.7.1", +] + +[[package]] +name = "sct" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" +dependencies = [ + "ring 0.16.20", + "untrusted 0.7.1", +] + +[[package]] +name = "sdp" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d22a5ef407871893fd72b4562ee15e4742269b173959db4b8df6f538c414e13" +dependencies = [ + "rand 0.8.5", + "substring", + "thiserror 1.0.44", + "url 2.4.0", +] + +[[package]] +name = "sec1" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3be24c1842290c45df0a7bf069e0c268a747ad05a192f2fd7dcfdbc1cba40928" +dependencies = [ + "base16ct 0.1.1", + "der 0.6.1", + "generic-array 0.14.7", + "pkcs8 0.9.0", + "subtle", + "zeroize", +] + +[[package]] +name = "sec1" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" +dependencies = [ + "base16ct 0.2.0", + "der 0.7.8", + "generic-array 0.14.7", + "pkcs8 0.10.2", + "subtle", + "zeroize", +] + +[[package]] +name = "secp256k1" +version = "0.24.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b1629c9c557ef9b293568b338dddfc8208c98a18c59d722a9d53f859d9c9b62" +dependencies = [ + "secp256k1-sys 0.6.1", +] + +[[package]] +name = "secp256k1" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2acea373acb8c21ecb5a23741452acd2593ed44ee3d343e72baaa143bc89d0d5" +dependencies = [ + "bitcoin_hashes", + "secp256k1-sys 0.9.1", +] + +[[package]] +name = "secp256k1-sys" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83080e2c2fc1006e625be82e5d1eb6a43b7fd9578b617fcc55814daf286bba4b" +dependencies = [ + "cc", +] + +[[package]] +name = "secp256k1-sys" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dd97a086ec737e30053fd5c46f097465d25bb81dd3608825f65298c4c98be83" +dependencies = [ + "cc", +] + +[[package]] +name = "secrecy" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bd1c54ea06cfd2f6b63219704de0b9b4f72dcc2b8fdef820be6cd799780e91e" +dependencies = [ + "zeroize", +] + +[[package]] +name = "security-framework" +version = "2.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "semver" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a3186ec9e65071a2095434b1f5bb24838d4e8e130f584c790f6033c79943537" +dependencies = [ + "semver-parser", +] + +[[package]] +name = "semver" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0293b4b29daaf487284529cc2f5675b8e57c61f70167ba415a463651fd6a918" +dependencies = [ + "serde 1.0.193", +] + +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" + +[[package]] +name = "serde" +version = "1.0.118" +source = "git+https://github.com/mesalock-linux/serde-sgx#db0226f1d5d70fca6b96af2c285851502204e21c" +dependencies = [ + "serde_derive 1.0.118", + "sgx_tstd", +] + +[[package]] +name = "serde" +version = "1.0.193" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" +dependencies = [ + "serde_derive 1.0.193", +] + +[[package]] +name = "serde-big-array" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b926cfbabfe8011609dda0350cb24d884955d294909ac71c0db7027366c77e3e" +dependencies = [ + "serde 1.0.193", + "serde_derive 1.0.193", +] + +[[package]] +name = "serde-big-array" +version = "0.3.0" +source = "git+https://github.com/mesalock-linux/serde-big-array-sgx#94122c5167aee38b39b09a620a60db2c28cf7428" +dependencies = [ + "serde 1.0.118", + "serde_derive 1.0.118", +] + +[[package]] +name = "serde_derive" +version = "1.0.118" +source = "git+https://github.com/mesalock-linux/serde-sgx#db0226f1d5d70fca6b96af2c285851502204e21c" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "serde_derive" +version = "1.0.193" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.32", +] + +[[package]] +name = "serde_json" +version = "1.0.60" +source = "git+https://github.com/mesalock-linux/serde-json-sgx?tag=sgx_1.1.3#380893814ad2a057758d825bab798aa117f7362a" +dependencies = [ + "indexmap 1.6.1", + "itoa 0.4.5", + "ryu", + "serde 1.0.118", + "sgx_tstd", +] + +[[package]] +name = "serde_json" +version = "1.0.60" +source = "git+https://github.com/mesalock-linux/serde-json-sgx#380893814ad2a057758d825bab798aa117f7362a" +dependencies = [ + "itoa 0.4.5", + "ryu", + "serde 1.0.118", + "sgx_tstd", +] + +[[package]] +name = "serde_json" +version = "1.0.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d03b412469450d4404fe8499a268edd7f8b79fecb074b0d812ad64ca21f4031b" +dependencies = [ + "indexmap 2.0.0", + "itoa 1.0.9", + "ryu", + "serde 1.0.193", +] + +[[package]] +name = "serde_spanned" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96426c9936fd7a0124915f9185ea1d20aa9445cc9821142f0a73bc9207a2e186" +dependencies = [ + "serde 1.0.193", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa 1.0.9", + "ryu", + "serde 1.0.193", +] + +[[package]] +name = "sgx-verify" +version = "0.1.4" +dependencies = [ + "base64 0.13.1", + "chrono 0.4.26", + "der 0.6.1", + "frame-support", + "hex", + "parity-scale-codec", + "ring 0.16.20", + "rustls-webpki", + "scale-info", + "serde 1.0.193", + "serde_json 1.0.103", + "sp-core", + "sp-std 5.0.0", + "teerex-primitives", + "x509-cert", +] + +[[package]] +name = "sgx_alloc" +version = "1.1.6" +source = "git+https://github.com/apache/incubator-teaclave-sgx-sdk?branch=master#3c903bdac4e503dd27b9b1f761c4abfc55f2464c" + +[[package]] +name = "sgx_backtrace_sys" +version = "1.1.6" +source = "git+https://github.com/apache/incubator-teaclave-sgx-sdk?branch=master#3c903bdac4e503dd27b9b1f761c4abfc55f2464c" +dependencies = [ + "cc", + "sgx_build_helper", + "sgx_libc", +] + +[[package]] +name = "sgx_build_helper" +version = "1.1.6" +source = "git+https://github.com/apache/incubator-teaclave-sgx-sdk?branch=master#3c903bdac4e503dd27b9b1f761c4abfc55f2464c" + +[[package]] +name = "sgx_crypto_helper" +version = "1.1.6" +source = "git+https://github.com/apache/incubator-teaclave-sgx-sdk?branch=master#3c903bdac4e503dd27b9b1f761c4abfc55f2464c" +dependencies = [ + "itertools 0.11.0", + "libc", + "serde 1.0.118", + "serde 1.0.193", + "serde-big-array 0.1.5", + "serde-big-array 0.3.0", + "serde_derive 1.0.118", + "serde_derive 1.0.193", + "sgx_tcrypto", + "sgx_tstd", + "sgx_types", + "sgx_ucrypto", +] + +[[package]] +name = "sgx_demangle" +version = "1.1.6" +source = "git+https://github.com/apache/incubator-teaclave-sgx-sdk?branch=master#3c903bdac4e503dd27b9b1f761c4abfc55f2464c" + +[[package]] +name = "sgx_libc" +version = "1.1.6" +source = "git+https://github.com/apache/incubator-teaclave-sgx-sdk?branch=master#3c903bdac4e503dd27b9b1f761c4abfc55f2464c" +dependencies = [ + "sgx_types", +] + +[[package]] +name = "sgx_rand" +version = "1.1.6" +source = "git+https://github.com/apache/incubator-teaclave-sgx-sdk?branch=master#3c903bdac4e503dd27b9b1f761c4abfc55f2464c" +dependencies = [ + "sgx_trts", + "sgx_tstd", + "sgx_types", +] + +[[package]] +name = "sgx_tcrypto" +version = "1.1.6" +source = "git+https://github.com/apache/incubator-teaclave-sgx-sdk?branch=master#3c903bdac4e503dd27b9b1f761c4abfc55f2464c" +dependencies = [ + "sgx_types", +] + +[[package]] +name = "sgx_tprotected_fs" +version = "1.1.6" +source = "git+https://github.com/apache/incubator-teaclave-sgx-sdk?branch=master#3c903bdac4e503dd27b9b1f761c4abfc55f2464c" +dependencies = [ + "sgx_trts", + "sgx_types", +] + +[[package]] +name = "sgx_trts" +version = "1.1.6" +source = "git+https://github.com/apache/incubator-teaclave-sgx-sdk?branch=master#3c903bdac4e503dd27b9b1f761c4abfc55f2464c" +dependencies = [ + "sgx_libc", + "sgx_types", +] + +[[package]] +name = "sgx_tse" +version = "1.1.6" +source = "git+https://github.com/apache/teaclave-sgx-sdk.git?branch=master#3c903bdac4e503dd27b9b1f761c4abfc55f2464c" +dependencies = [ + "sgx_types", +] + +[[package]] +name = "sgx_tstd" +version = "1.1.6" +source = "git+https://github.com/apache/incubator-teaclave-sgx-sdk?branch=master#3c903bdac4e503dd27b9b1f761c4abfc55f2464c" +dependencies = [ + "hashbrown_tstd", + "sgx_alloc", + "sgx_backtrace_sys", + "sgx_demangle", + "sgx_libc", + "sgx_tprotected_fs", + "sgx_trts", + "sgx_types", + "sgx_unwind", +] + +[[package]] +name = "sgx_types" +version = "1.1.6" +source = "git+https://github.com/apache/incubator-teaclave-sgx-sdk?branch=master#3c903bdac4e503dd27b9b1f761c4abfc55f2464c" + +[[package]] +name = "sgx_ucrypto" +version = "1.1.6" +source = "git+https://github.com/apache/incubator-teaclave-sgx-sdk?branch=master#3c903bdac4e503dd27b9b1f761c4abfc55f2464c" +dependencies = [ + "libc", + "rand_core 0.3.1", + "rdrand", + "sgx_types", +] + +[[package]] +name = "sgx_unwind" +version = "1.1.6" +source = "git+https://github.com/apache/incubator-teaclave-sgx-sdk?branch=master#3c903bdac4e503dd27b9b1f761c4abfc55f2464c" +dependencies = [ + "sgx_build_helper", +] + +[[package]] +name = "sgx_urts" +version = "1.1.6" +source = "git+https://github.com/apache/incubator-teaclave-sgx-sdk?branch=master#3c903bdac4e503dd27b9b1f761c4abfc55f2464c" +dependencies = [ + "libc", + "sgx_types", +] + +[[package]] +name = "sha-1" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df" +dependencies = [ + "block-buffer 0.7.3", + "digest 0.8.1", + "fake-simd", + "opaque-debug 0.2.3", +] + +[[package]] +name = "sha-1" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99cd6713db3cf16b6c84e06321e049a9b9f699826e16096d23bbcc44d15d51a6" +dependencies = [ + "block-buffer 0.9.0", + "cfg-if 1.0.0", + "cpufeatures", + "digest 0.9.0", + "opaque-debug 0.3.0", +] + +[[package]] +name = "sha1" +version = "0.6.0" +source = "git+https://github.com/mesalock-linux/rust-sha1-sgx?tag=sgx_1.1.3#482a4d489e860d63a21662aaea988f600f8e20a4" +dependencies = [ + "sgx_tstd", +] + +[[package]] +name = "sha1" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" +dependencies = [ + "cfg-if 1.0.0", + "cpufeatures", + "digest 0.10.7", +] + +[[package]] +name = "sha2" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a256f46ea78a0c0d9ff00077504903ac881a1dafdc20da66545699e7776b3e69" +dependencies = [ + "block-buffer 0.7.3", + "digest 0.8.1", + "fake-simd", + "opaque-debug 0.2.3", +] + +[[package]] +name = "sha2" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" +dependencies = [ + "block-buffer 0.9.0", + "cfg-if 1.0.0", + "cpufeatures", + "digest 0.9.0", + "opaque-debug 0.3.0", +] + +[[package]] +name = "sha2" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8" +dependencies = [ + "cfg-if 1.0.0", + "cpufeatures", + "digest 0.10.7", +] + +[[package]] +name = "sha3" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" +dependencies = [ + "digest 0.10.7", + "keccak", +] + +[[package]] +name = "sharded-slab" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "shlex" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3" + +[[package]] +name = "sidechain-primitives" +version = "0.1.0" +dependencies = [ + "parity-scale-codec", + "scale-info", + "serde 1.0.193", + "sp-core", +] + +[[package]] +name = "signal-hook-registry" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +dependencies = [ + "libc", +] + +[[package]] +name = "signature" +version = "1.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" +dependencies = [ + "digest 0.10.7", + "rand_core 0.6.4", +] + +[[package]] +name = "signature" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e1788eed21689f9cf370582dfc467ef36ed9c707f073528ddafa8d83e3b8500" +dependencies = [ + "digest 0.10.7", + "rand_core 0.6.4", +] + +[[package]] +name = "simba" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "061507c94fc6ab4ba1c9a0305018408e312e17c041eb63bef8aa726fa33aceae" +dependencies = [ + "approx", + "num-complex 0.4.3", + "num-traits 0.2.16", + "paste", + "wide", +] + +[[package]] +name = "siphasher" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de" + +[[package]] +name = "slab" +version = "0.4.2" +source = "git+https://github.com/mesalock-linux/slab-sgx#0b0e6ec2abd588afd2f40fd082bc473d100d0f40" +dependencies = [ + "sgx_tstd", +] + +[[package]] +name = "slab" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" +dependencies = [ + "autocfg 1.1.0", +] + +[[package]] +name = "slice-group-by" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "826167069c09b99d56f31e9ae5c99049e932a98c9dc2dac47645b08dbbf76ba7" + +[[package]] +name = "slot-range-helper" +version = "0.9.42" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" +dependencies = [ + "enumn", + "parity-scale-codec", + "paste", + "sp-runtime", + "sp-std 5.0.0", +] + +[[package]] +name = "smallvec" +version = "1.6.1" +source = "git+https://github.com/mesalock-linux/rust-smallvec-sgx#b5925f10aa5bc3370a0fb339140ee063f5a888dd" +dependencies = [ + "sgx_tstd", +] + +[[package]] +name = "smallvec" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9" + +[[package]] +name = "snap" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e9f0ab6ef7eb7353d9119c170a436d1bf248eea575ac42d19d12f4e34130831" + +[[package]] +name = "snow" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ccba027ba85743e09d15c03296797cad56395089b832b48b5a5217880f57733" +dependencies = [ + "aes-gcm 0.9.4", + "blake2", + "chacha20poly1305", + "curve25519-dalek 4.0.0-rc.1", + "rand_core 0.6.4", + "ring 0.16.20", + "rustc_version", + "sha2 0.10.7", + "subtle", +] + +[[package]] +name = "socket2" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" +dependencies = [ + "libc", + "winapi 0.3.9", +] + +[[package]] +name = "socket2" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2538b18701741680e0322a2302176d3253a35388e2e62f172f64f4f16605f877" +dependencies = [ + "libc", + "windows-sys 0.48.0", +] + +[[package]] +name = "soketto" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4919971d141dbadaa0e82b5d369e2d7666c98e4625046140615ca363e50d4daa" +dependencies = [ + "base64 0.13.1", + "bytes 1.4.0", + "futures 0.3.28", + "httparse 1.8.0", + "log 0.4.20", + "rand 0.8.5", + "sha-1 0.9.8", +] + +[[package]] +name = "soketto" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d1c5305e39e09653383c2c7244f2f78b3bcae37cf50c64cb4789c9f5096ec2" +dependencies = [ + "base64 0.13.1", + "bytes 1.4.0", + "flate2", + "futures 0.3.28", + "http 0.2.9", + "httparse 1.8.0", + "log 0.4.20", + "rand 0.8.5", + "sha-1 0.9.8", +] + +[[package]] +name = "sp-api" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "hash-db 0.16.0", + "log 0.4.20", + "parity-scale-codec", + "scale-info", + "sp-api-proc-macro", + "sp-core", + "sp-metadata-ir", + "sp-runtime", + "sp-state-machine", + "sp-std 5.0.0", + "sp-trie", + "sp-version", + "thiserror 1.0.44", +] + +[[package]] +name = "sp-api-proc-macro" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "Inflector", + "blake2", + "expander 1.0.0", + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.32", +] + +[[package]] +name = "sp-application-crypto" +version = "7.0.0" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "parity-scale-codec", + "scale-info", + "serde 1.0.193", + "sp-core", + "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", + "sp-std 5.0.0", +] + +[[package]] +name = "sp-arithmetic" +version = "6.0.0" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "integer-sqrt", + "num-traits 0.2.16", + "parity-scale-codec", + "scale-info", + "serde 1.0.193", + "sp-std 5.0.0", + "static_assertions", +] + +[[package]] +name = "sp-authority-discovery" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "parity-scale-codec", + "scale-info", + "sp-api", + "sp-application-crypto", + "sp-runtime", + "sp-std 5.0.0", +] + +[[package]] +name = "sp-block-builder" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "parity-scale-codec", + "sp-api", + "sp-inherents", + "sp-runtime", + "sp-std 5.0.0", +] + +[[package]] +name = "sp-blockchain" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "futures 0.3.28", + "log 0.4.20", + "lru 0.8.1", + "parity-scale-codec", + "parking_lot 0.12.1", + "sp-api", + "sp-consensus", + "sp-database", + "sp-runtime", + "sp-state-machine", + "thiserror 1.0.44", +] + +[[package]] +name = "sp-consensus" +version = "0.10.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "async-trait", + "futures 0.3.28", + "log 0.4.20", + "sp-core", + "sp-inherents", + "sp-runtime", + "sp-state-machine", + "thiserror 1.0.44", +] + +[[package]] +name = "sp-consensus-aura" +version = "0.10.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "async-trait", + "parity-scale-codec", + "scale-info", + "sp-api", + "sp-application-crypto", + "sp-consensus", + "sp-consensus-slots", + "sp-inherents", + "sp-runtime", + "sp-std 5.0.0", + "sp-timestamp", +] + +[[package]] +name = "sp-consensus-babe" +version = "0.10.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "async-trait", + "parity-scale-codec", + "scale-info", + "serde 1.0.193", + "sp-api", + "sp-application-crypto", + "sp-consensus", + "sp-consensus-slots", + "sp-core", + "sp-inherents", + "sp-keystore", + "sp-runtime", + "sp-std 5.0.0", + "sp-timestamp", +] + +[[package]] +name = "sp-consensus-grandpa" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "finality-grandpa", + "log 0.4.20", + "parity-scale-codec", + "scale-info", + "serde 1.0.193", + "sp-api", + "sp-application-crypto", + "sp-core", + "sp-keystore", + "sp-runtime", + "sp-std 5.0.0", +] + +[[package]] +name = "sp-consensus-slots" +version = "0.10.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "parity-scale-codec", + "scale-info", + "serde 1.0.193", + "sp-std 5.0.0", + "sp-timestamp", +] + +[[package]] +name = "sp-core" +version = "7.0.0" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "array-bytes 4.2.0", + "bitflags 1.3.2", + "blake2", + "bounded-collections", + "bs58", + "dyn-clonable", + "ed25519-zebra", + "futures 0.3.28", + "hash-db 0.16.0", + "hash256-std-hasher", + "impl-serde", + "lazy_static", + "libsecp256k1", + "log 0.4.20", + "merlin", + "parity-scale-codec", + "parking_lot 0.12.1", + "paste", + "primitive-types", + "rand 0.8.5", + "regex 1.9.5", + "scale-info", + "schnorrkel", + "secp256k1 0.24.3", + "secrecy", + "serde 1.0.193", + "sp-core-hashing 5.0.0", + "sp-debug-derive", + "sp-externalities", + "sp-runtime-interface", + "sp-std 5.0.0", + "sp-storage", + "ss58-registry", + "substrate-bip39", + "thiserror 1.0.44", + "tiny-bip39", + "zeroize", +] + +[[package]] +name = "sp-core-hashing" +version = "5.0.0" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "blake2b_simd", + "byteorder 1.4.3", + "digest 0.10.7", + "sha2 0.10.7", + "sha3", + "sp-std 5.0.0", + "twox-hash", +] + +[[package]] +name = "sp-core-hashing" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbc2d1947252b7a4e403b0a260f596920443742791765ec111daa2bbf98eff25" +dependencies = [ + "blake2", + "byteorder 1.4.3", + "digest 0.10.7", + "sha2 0.10.7", + "sha3", + "sp-std 6.0.0", + "twox-hash", +] + +[[package]] +name = "sp-core-hashing-proc-macro" +version = "5.0.0" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "proc-macro2", + "quote", + "sp-core-hashing 5.0.0", + "syn 2.0.32", +] + +[[package]] +name = "sp-database" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "kvdb", + "parking_lot 0.12.1", +] + +[[package]] +name = "sp-debug-derive" +version = "5.0.0" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.32", +] + +[[package]] +name = "sp-externalities" +version = "0.13.0" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "environmental 1.1.4", + "parity-scale-codec", + "sp-std 5.0.0", + "sp-storage", +] + +[[package]] +name = "sp-inherents" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "async-trait", + "impl-trait-for-tuples", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-runtime", + "sp-std 5.0.0", + "thiserror 1.0.44", +] + +[[package]] +name = "sp-io" +version = "7.0.0" +dependencies = [ + "itp-sgx-externalities", + "libsecp256k1", + "log 0.4.20", + "parity-scale-codec", + "sgx_tstd", + "sp-core", +] + +[[package]] +name = "sp-io" +version = "7.0.0" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "bytes 1.4.0", + "ed25519", + "ed25519-dalek", + "futures 0.3.28", + "libsecp256k1", + "log 0.4.20", + "parity-scale-codec", + "rustversion", + "secp256k1 0.24.3", + "sp-core", + "sp-externalities", + "sp-keystore", + "sp-runtime-interface", + "sp-state-machine", + "sp-std 5.0.0", + "sp-tracing", + "sp-trie", + "tracing", + "tracing-core", +] + +[[package]] +name = "sp-keyring" +version = "7.0.0" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "lazy_static", + "sp-core", + "sp-runtime", + "strum 0.24.1", +] + +[[package]] +name = "sp-keystore" +version = "0.13.0" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "futures 0.3.28", + "parity-scale-codec", + "parking_lot 0.12.1", + "serde 1.0.193", + "sp-core", + "sp-externalities", + "thiserror 1.0.44", +] + +[[package]] +name = "sp-maybe-compressed-blob" +version = "4.1.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "thiserror 1.0.44", + "zstd 0.12.4", +] + +[[package]] +name = "sp-metadata-ir" +version = "0.1.0" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "frame-metadata", + "parity-scale-codec", + "scale-info", + "sp-std 5.0.0", +] + +[[package]] +name = "sp-npos-elections" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "parity-scale-codec", + "scale-info", + "serde 1.0.193", + "sp-arithmetic", + "sp-core", + "sp-runtime", + "sp-std 5.0.0", +] + +[[package]] +name = "sp-offchain" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "sp-api", + "sp-core", + "sp-runtime", +] + +[[package]] +name = "sp-panic-handler" +version = "5.0.0" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "backtrace", + "lazy_static", + "regex 1.9.5", +] + +[[package]] +name = "sp-rpc" +version = "6.0.0" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "rustc-hash", + "serde 1.0.193", + "sp-core", +] + +[[package]] +name = "sp-runtime" +version = "7.0.0" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "either", + "hash256-std-hasher", + "impl-trait-for-tuples", + "log 0.4.20", + "parity-scale-codec", + "paste", + "rand 0.8.5", + "scale-info", + "serde 1.0.193", + "sp-application-crypto", + "sp-arithmetic", + "sp-core", + "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", + "sp-std 5.0.0", + "sp-weights", +] + +[[package]] +name = "sp-runtime-interface" +version = "7.0.0" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "bytes 1.4.0", + "impl-trait-for-tuples", + "parity-scale-codec", + "primitive-types", + "sp-externalities", + "sp-runtime-interface-proc-macro", + "sp-std 5.0.0", + "sp-storage", + "sp-tracing", + "sp-wasm-interface", + "static_assertions", +] + +[[package]] +name = "sp-runtime-interface-proc-macro" +version = "6.0.0" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "Inflector", + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.32", +] + +[[package]] +name = "sp-session" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "parity-scale-codec", + "scale-info", + "sp-api", + "sp-core", + "sp-runtime", + "sp-staking", + "sp-std 5.0.0", +] + +[[package]] +name = "sp-staking" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "parity-scale-codec", + "scale-info", + "serde 1.0.193", + "sp-core", + "sp-runtime", + "sp-std 5.0.0", +] + +[[package]] +name = "sp-state-machine" +version = "0.13.0" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "hash-db 0.16.0", + "log 0.4.20", + "parity-scale-codec", + "parking_lot 0.12.1", + "rand 0.8.5", + "smallvec 1.11.0", + "sp-core", + "sp-externalities", + "sp-panic-handler", + "sp-std 5.0.0", + "sp-trie", + "thiserror 1.0.44", + "tracing", +] + +[[package]] +name = "sp-std" +version = "5.0.0" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" + +[[package]] +name = "sp-std" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af0ee286f98455272f64ac5bb1384ff21ac029fbb669afbaf48477faff12760e" + +[[package]] +name = "sp-storage" +version = "7.0.0" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "impl-serde", + "parity-scale-codec", + "ref-cast", + "serde 1.0.193", + "sp-debug-derive", + "sp-std 5.0.0", +] + +[[package]] +name = "sp-timestamp" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "async-trait", + "futures-timer", + "log 0.4.20", + "parity-scale-codec", + "sp-inherents", + "sp-runtime", + "sp-std 5.0.0", + "thiserror 1.0.44", +] + +[[package]] +name = "sp-tracing" +version = "6.0.0" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "parity-scale-codec", + "sp-std 5.0.0", + "tracing", + "tracing-core", + "tracing-subscriber", +] + +[[package]] +name = "sp-transaction-pool" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "sp-api", + "sp-runtime", +] + +[[package]] +name = "sp-transaction-storage-proof" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "async-trait", + "log 0.4.20", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-inherents", + "sp-runtime", + "sp-std 5.0.0", + "sp-trie", +] + +[[package]] +name = "sp-trie" +version = "7.0.0" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "ahash 0.8.3", + "hash-db 0.16.0", + "hashbrown 0.13.2", + "lazy_static", + "memory-db", + "nohash-hasher", + "parity-scale-codec", + "parking_lot 0.12.1", + "scale-info", + "schnellru", + "sp-core", + "sp-std 5.0.0", + "thiserror 1.0.44", + "tracing", + "trie-db", + "trie-root", +] + +[[package]] +name = "sp-version" +version = "5.0.0" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "impl-serde", + "parity-scale-codec", + "parity-wasm", + "scale-info", + "serde 1.0.193", + "sp-core-hashing-proc-macro", + "sp-runtime", + "sp-std 5.0.0", + "sp-version-proc-macro", + "thiserror 1.0.44", +] + +[[package]] +name = "sp-version-proc-macro" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "parity-scale-codec", + "proc-macro2", + "quote", + "syn 2.0.32", +] + +[[package]] +name = "sp-wasm-interface" +version = "7.0.0" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "anyhow", + "impl-trait-for-tuples", + "log 0.4.20", + "parity-scale-codec", + "sp-std 5.0.0", + "wasmi", + "wasmtime", +] + +[[package]] +name = "sp-weights" +version = "4.0.0" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "parity-scale-codec", + "scale-info", + "serde 1.0.193", + "smallvec 1.11.0", + "sp-arithmetic", + "sp-core", + "sp-debug-derive", + "sp-std 5.0.0", +] + +[[package]] +name = "spin" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + +[[package]] +name = "spki" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67cf02bbac7a337dc36e4f5a693db6c21e7863f45070f7064577eb4367a3212b" +dependencies = [ + "base64ct", + "der 0.6.1", +] + +[[package]] +name = "spki" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d1e996ef02c474957d681f1b05213dfb0abab947b446a62d37770b23500184a" +dependencies = [ + "base64ct", + "der 0.7.8", +] + +[[package]] +name = "ss58-registry" +version = "1.41.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfc443bad666016e012538782d9e3006213a7db43e9fb1dda91657dc06a6fa08" +dependencies = [ + "Inflector", + "num-format", + "proc-macro2", + "quote", + "serde 1.0.193", + "serde_json 1.0.103", + "unicode-xid", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "static_init" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a2a1c578e98c1c16fc3b8ec1328f7659a500737d7a0c6d625e73e830ff9c1f6" +dependencies = [ + "bitflags 1.3.2", + "cfg_aliases", + "libc", + "parking_lot 0.11.2", + "parking_lot_core 0.8.6", + "static_init_macro", + "winapi 0.3.9", +] + +[[package]] +name = "static_init_macro" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70a2595fc3aa78f2d0e45dd425b22282dd863273761cc77780914b2cf3003acf" +dependencies = [ + "cfg_aliases", + "memchr 2.6.3", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "strsim" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "strum" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f" +dependencies = [ + "strum_macros 0.24.3", +] + +[[package]] +name = "strum" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125" + +[[package]] +name = "strum_macros" +version = "0.24.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "rustversion", + "syn 1.0.109", +] + +[[package]] +name = "strum_macros" +version = "0.25.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23dc1fa9ac9c169a78ba62f0b841814b7abae11bdd047b9c58f893439e309ea0" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.32", +] + +[[package]] +name = "stun" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7e94b1ec00bad60e6410e058b52f1c66de3dc5fe4d62d09b3e52bb7d3b73e25" +dependencies = [ + "base64 0.13.1", + "crc", + "lazy_static", + "md-5", + "rand 0.8.5", + "ring 0.16.20", + "subtle", + "thiserror 1.0.44", + "tokio", + "url 2.4.0", + "webrtc-util", +] + +[[package]] +name = "substrate-api-client" +version = "0.14.0" +source = "git+https://github.com/scs/substrate-api-client.git?branch=polkadot-v0.9.42-tag-v0.14.0#e4ed74b0fb6c2fd5585f55c2702b97b56d99c7f6" +dependencies = [ + "ac-compose-macros", + "ac-node-api", + "ac-primitives", + "async-trait", + "derive_more", + "frame-metadata", + "frame-support", + "hex", + "log 0.4.20", + "maybe-async", + "parity-scale-codec", + "serde 1.0.193", + "serde_json 1.0.103", + "sp-core", + "sp-runtime", + "sp-runtime-interface", + "tungstenite 0.18.0", + "url 2.4.0", +] + +[[package]] +name = "substrate-bip39" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49eee6965196b32f882dd2ee85a92b1dbead41b04e53907f269de3b0dc04733c" +dependencies = [ + "hmac 0.11.0", + "pbkdf2 0.8.0", + "schnorrkel", + "sha2 0.9.9", + "zeroize", +] + +[[package]] +name = "substrate-bn" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b5bbfa79abbae15dd642ea8176a21a635ff3c00059961d1ea27ad04e5b441c" +dependencies = [ + "byteorder 1.4.3", + "crunchy", + "lazy_static", + "rand 0.8.5", + "rustc-hex", +] + +[[package]] +name = "substrate-client-keystore" +version = "0.9.1" +source = "git+https://github.com/scs/substrate-api-client.git?branch=polkadot-v0.9.42-tag-v0.14.0#e4ed74b0fb6c2fd5585f55c2702b97b56d99c7f6" +dependencies = [ + "array-bytes 4.2.0", + "async-trait", + "parking_lot 0.12.1", + "sc-keystore", + "serde_json 1.0.103", + "sp-application-crypto", + "sp-core", + "sp-keyring", + "sp-keystore", +] + +[[package]] +name = "substrate-fixed" +version = "0.5.9" +source = "git+https://github.com/encointer/substrate-fixed?tag=v0.5.9#a4fb461aae6205ffc55bed51254a40c52be04e5d" +dependencies = [ + "parity-scale-codec", + "scale-info", + "serde 1.0.193", + "typenum 1.16.0 (git+https://github.com/encointer/typenum?tag=v1.16.0)", +] + +[[package]] +name = "substrate-fixed" +version = "0.5.9" +source = "git+https://github.com/encointer/substrate-fixed#a4fb461aae6205ffc55bed51254a40c52be04e5d" +dependencies = [ + "parity-scale-codec", + "scale-info", + "typenum 1.16.0 (git+https://github.com/encointer/typenum?tag=v1.16.0)", +] + +[[package]] +name = "substrate-prometheus-endpoint" +version = "0.10.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "hyper", + "log 0.4.20", + "prometheus", + "thiserror 1.0.44", + "tokio", +] + +[[package]] +name = "substrate-wasm-builder" +version = "5.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "ansi_term", + "build-helper", + "cargo_metadata", + "filetime", + "sp-maybe-compressed-blob", + "strum 0.24.1", + "tempfile", + "toml 0.7.8", + "walkdir", + "wasm-opt", +] + +[[package]] +name = "substring" +version = "1.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ee6433ecef213b2e72f587ef64a2f5943e7cd16fbd82dbe8bc07486c534c86" +dependencies = [ + "autocfg 1.1.0", +] + +[[package]] +name = "subtle" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "239814284fd6f1a4ffe4ca893952cdd93c224b6a1571c9a9eadd670295c0c9e2" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "synstructure" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", + "unicode-xid", +] + +[[package]] +name = "system-configuration" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + +[[package]] +name = "target-lexicon" +version = "0.12.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d2faeef5759ab89935255b1a4cd98e0baf99d1085e37d36599c625dac49ae8e" + +[[package]] +name = "teeracle-primitives" +version = "0.1.0" +dependencies = [ + "common-primitives", + "substrate-fixed 0.5.9 (git+https://github.com/encointer/substrate-fixed?tag=v0.5.9)", +] + +[[package]] +name = "teerex-primitives" +version = "0.1.0" +dependencies = [ + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-std 5.0.0", +] + +[[package]] +name = "temp-dir" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af547b166dd1ea4b472165569fc456cfb6818116f854690b0ff205e636523dab" + +[[package]] +name = "tempfile" +version = "3.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5486094ee78b2e5038a6382ed7645bc084dc2ec433426ca4c3cb61e2007b8998" +dependencies = [ + "cfg-if 1.0.0", + "fastrand 2.0.0", + "redox_syscall 0.3.5", + "rustix 0.38.4", + "windows-sys 0.48.0", +] + +[[package]] +name = "termcolor" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "termtree" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3369f5ac52d5eb6ab48c6b4ffdc8efbcad6b89c765749064ba298f2c68a16a76" + +[[package]] +name = "textwrap" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" +dependencies = [ + "unicode-width", +] + +[[package]] +name = "thiserror" +version = "1.0.9" +source = "git+https://github.com/mesalock-linux/thiserror-sgx?tag=sgx_1.1.3#c2f806b88616e06aab0af770366a76885d974fdc" +dependencies = [ + "sgx_tstd", + "thiserror-impl 1.0.9", +] + +[[package]] +name = "thiserror" +version = "1.0.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "611040a08a0439f8248d1990b111c95baa9c704c805fa1f62104b39655fd7f90" +dependencies = [ + "thiserror-impl 1.0.44", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.9" +source = "git+https://github.com/mesalock-linux/thiserror-sgx?tag=sgx_1.1.3#c2f806b88616e06aab0af770366a76885d974fdc" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "090198534930841fab3a5d1bb637cde49e339654e606195f8d9c76eeb081dc96" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.32", +] + +[[package]] +name = "thread_local" +version = "1.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" +dependencies = [ + "cfg-if 1.0.0", + "once_cell 1.18.0", +] + +[[package]] +name = "threadpool" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" +dependencies = [ + "num_cpus", +] + +[[package]] +name = "thrift" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b82ca8f46f95b3ce96081fe3dd89160fdea970c254bb72925255d1b62aae692e" +dependencies = [ + "byteorder 1.4.3", + "integer-encoding", + "log 0.4.20", + "ordered-float", + "threadpool", +] + +[[package]] +name = "tikv-jemalloc-ctl" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e37706572f4b151dff7a0146e040804e9c26fe3a3118591112f05cf12a4216c1" +dependencies = [ + "libc", + "paste", + "tikv-jemalloc-sys", +] + +[[package]] +name = "tikv-jemalloc-sys" +version = "0.5.3+5.3.0-patched" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a678df20055b43e57ef8cddde41cdfda9a3c1a060b67f4c5836dfb1d78543ba8" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "time" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" +dependencies = [ + "libc", + "wasi 0.10.0+wasi-snapshot-preview1", + "winapi 0.3.9", +] + +[[package]] +name = "time" +version = "0.3.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea9e1b3cf1243ae005d9e74085d4d542f3125458f3a81af210d901dcd7411efd" +dependencies = [ + "itoa 1.0.9", + "serde 1.0.193", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb" + +[[package]] +name = "time-macros" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "372950940a5f07bf38dbe211d7283c9e6d7327df53794992d293e534c733d09b" +dependencies = [ + "time-core", +] + +[[package]] +name = "tiny-bip39" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62cc94d358b5a1e84a5cb9109f559aa3c4d634d2b1b4de3d0fa4adc7c78e2861" +dependencies = [ + "anyhow", + "hmac 0.12.1", + "once_cell 1.18.0", + "pbkdf2 0.11.0", + "rand 0.8.5", + "rustc-hash", + "sha2 0.10.7", + "thiserror 1.0.44", + "unicode-normalization 0.1.22", + "wasm-bindgen", + "zeroize", +] + +[[package]] +name = "tiny-keccak" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] + +[[package]] +name = "tinytemplate" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" +dependencies = [ + "serde 1.0.193", + "serde_json 1.0.103", +] + +[[package]] +name = "tinyvec" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tokio" +version = "1.29.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "532826ff75199d5833b9d2c5fe410f29235e25704ee5f0ef599fb51c21f4a4da" +dependencies = [ + "autocfg 1.1.0", + "backtrace", + "bytes 1.4.0", + "libc", + "mio 0.8.8", + "num_cpus", + "parking_lot 0.12.1", + "pin-project-lite 0.2.10", + "signal-hook-registry", + "socket2 0.4.9", + "tokio-macros", + "windows-sys 0.48.0", +] + +[[package]] +name = "tokio-macros" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.32", +] + +[[package]] +name = "tokio-native-tls" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +dependencies = [ + "native-tls", + "tokio", +] + +[[package]] +name = "tokio-rustls" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc6844de72e57df1980054b38be3a9f4702aba4858be64dd700181a8a6d0e1b6" +dependencies = [ + "rustls 0.19.1", + "tokio", + "webpki 0.21.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-rustls" +version = "0.23.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59" +dependencies = [ + "rustls 0.20.8", + "tokio", + "webpki 0.22.0", +] + +[[package]] +name = "tokio-stream" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842" +dependencies = [ + "futures-core 0.3.28", + "pin-project-lite 0.2.10", + "tokio", + "tokio-util 0.7.8", +] + +[[package]] +name = "tokio-tungstenite" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54319c93411147bced34cb5609a80e0a8e44c5999c93903a81cd866630ec0bfd" +dependencies = [ + "futures-util 0.3.28", + "log 0.4.20", + "tokio", + "tungstenite 0.18.0", +] + +[[package]] +name = "tokio-util" +version = "0.6.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36943ee01a6d67977dd3f84a5a1d2efeb4ada3a1ae771cadfaa535d9d9fc6507" +dependencies = [ + "bytes 1.4.0", + "futures-core 0.3.28", + "futures-io 0.3.28", + "futures-sink 0.3.28", + "log 0.4.20", + "pin-project-lite 0.2.10", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "806fe8c2c87eccc8b3267cbae29ed3ab2d0bd37fca70ab622e46aaa9375ddb7d" +dependencies = [ + "bytes 1.4.0", + "futures-core 0.3.28", + "futures-io 0.3.28", + "futures-sink 0.3.28", + "pin-project-lite 0.2.10", + "tokio", + "tracing", +] + +[[package]] +name = "toml" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" +dependencies = [ + "serde 1.0.193", +] + +[[package]] +name = "toml" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd79e69d3b627db300ff956027cc6c3798cef26d22526befdfcd12feeb6d2257" +dependencies = [ + "serde 1.0.193", + "serde_spanned", + "toml_datetime", + "toml_edit 0.19.15", +] + +[[package]] +name = "toml" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "185d8ab0dfbb35cf1399a6344d8484209c088f75f8f68230da55d48d95d43e3d" +dependencies = [ + "serde 1.0.193", + "serde_spanned", + "toml_datetime", + "toml_edit 0.20.2", +] + +[[package]] +name = "toml_datetime" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" +dependencies = [ + "serde 1.0.193", +] + +[[package]] +name = "toml_edit" +version = "0.19.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" +dependencies = [ + "indexmap 2.0.0", + "serde 1.0.193", + "serde_spanned", + "toml_datetime", + "winnow", +] + +[[package]] +name = "toml_edit" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338" +dependencies = [ + "indexmap 2.0.0", + "serde 1.0.193", + "serde_spanned", + "toml_datetime", + "winnow", +] + +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-http" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f873044bf02dd1e8239e9c1293ea39dad76dc594ec16185d0a1bf31d8dc8d858" +dependencies = [ + "bitflags 1.3.2", + "bytes 1.4.0", + "futures-core 0.3.28", + "futures-util 0.3.28", + "http 0.2.9", + "http-body", + "http-range-header", + "pin-project-lite 0.2.10", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-layer" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" + +[[package]] +name = "tower-service" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" + +[[package]] +name = "tracing" +version = "0.1.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" +dependencies = [ + "cfg-if 1.0.0", + "log 0.4.20", + "pin-project-lite 0.2.10", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.32", +] + +[[package]] +name = "tracing-core" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" +dependencies = [ + "once_cell 1.18.0", + "valuable", +] + +[[package]] +name = "tracing-futures" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2" +dependencies = [ + "pin-project", + "tracing", +] + +[[package]] +name = "tracing-gum" +version = "0.9.42" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" +dependencies = [ + "polkadot-node-jaeger", + "polkadot-primitives", + "tracing", + "tracing-gum-proc-macro", +] + +[[package]] +name = "tracing-gum-proc-macro" +version = "0.9.42" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" +dependencies = [ + "expander 2.0.0", + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.32", +] + +[[package]] +name = "tracing-log" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922" +dependencies = [ + "lazy_static", + "log 0.4.20", + "tracing-core", +] + +[[package]] +name = "tracing-serde" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc6b213177105856957181934e4920de57730fc69bf42c37ee5bb664d406d9e1" +dependencies = [ + "serde 1.0.193", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.2.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e0d2eaa99c3c2e41547cfa109e910a68ea03823cccad4a0525dcbc9b01e8c71" +dependencies = [ + "ansi_term", + "chrono 0.4.26", + "lazy_static", + "matchers", + "parking_lot 0.11.2", + "regex 1.9.5", + "serde 1.0.193", + "serde_json 1.0.103", + "sharded-slab", + "smallvec 1.11.0", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", + "tracing-serde", +] + +[[package]] +name = "trie-db" +version = "0.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "767abe6ffed88a1889671a102c2861ae742726f52e0a5a425b92c9fbfa7e9c85" +dependencies = [ + "hash-db 0.16.0", + "hashbrown 0.13.2", + "log 0.4.20", + "rustc-hex", + "smallvec 1.11.0", +] + +[[package]] +name = "trie-root" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4ed310ef5ab98f5fa467900ed906cb9232dd5376597e00fd4cba2a449d06c0b" +dependencies = [ + "hash-db 0.16.0", +] + +[[package]] +name = "triehash" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1631b201eb031b563d2e85ca18ec8092508e262a3196ce9bd10a67ec87b9f5c" +dependencies = [ + "hash-db 0.15.2", + "rlp", +] + +[[package]] +name = "trust-dns-proto" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f7f83d1e4a0e4358ac54c5c3681e5d7da5efc5a7a632c90bb6d6669ddd9bc26" +dependencies = [ + "async-trait", + "cfg-if 1.0.0", + "data-encoding", + "enum-as-inner", + "futures-channel 0.3.28", + "futures-io 0.3.28", + "futures-util 0.3.28", + "idna 0.2.3", + "ipnet", + "lazy_static", + "rand 0.8.5", + "smallvec 1.11.0", + "socket2 0.4.9", + "thiserror 1.0.44", + "tinyvec", + "tokio", + "tracing", + "url 2.4.0", +] + +[[package]] +name = "trust-dns-resolver" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aff21aa4dcefb0a1afbfac26deb0adc93888c7d295fb63ab273ef276ba2b7cfe" +dependencies = [ + "cfg-if 1.0.0", + "futures-util 0.3.28", + "ipconfig", + "lazy_static", + "lru-cache", + "parking_lot 0.12.1", + "resolv-conf", + "smallvec 1.11.0", + "thiserror 1.0.44", + "tokio", + "tracing", + "trust-dns-proto", +] + +[[package]] +name = "try-lock" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" + +[[package]] +name = "tt-call" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4f195fd851901624eee5a58c4bb2b4f06399148fcd0ed336e6f1cb60a9881df" + +[[package]] +name = "tungstenite" +version = "0.14.0" +source = "git+https://github.com/integritee-network/tungstenite-rs-sgx?branch=sgx-experimental#c87a2c08ea00897bb8b127ca0a5c30c3671492b0" +dependencies = [ + "base64 0.13.0 (git+https://github.com/mesalock-linux/rust-base64-sgx?tag=sgx_1.1.3)", + "byteorder 1.3.4", + "bytes 1.0.1", + "http 0.2.1", + "httparse 1.4.1", + "log 0.4.14 (git+https://github.com/mesalock-linux/log-sgx?tag=sgx_1.1.3)", + "rand 0.7.3 (git+https://github.com/mesalock-linux/rand-sgx?tag=sgx_1.1.3)", + "rustls 0.19.0 (git+https://github.com/mesalock-linux/rustls?tag=sgx_1.1.3)", + "sgx_tstd", + "sha1 0.6.0", + "thiserror 1.0.9", + "url 2.1.1", + "utf-8 0.7.4", + "webpki 0.21.4 (git+https://github.com/mesalock-linux/webpki?branch=mesalock_sgx)", + "webpki-roots 0.21.0 (git+https://github.com/mesalock-linux/webpki-roots?tag=sgx_1.1.3)", +] + +[[package]] +name = "tungstenite" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "983d40747bce878d2fb67d910dcb8bd3eca2b2358540c3cc1b98c027407a3ae3" +dependencies = [ + "base64 0.13.1", + "byteorder 1.4.3", + "bytes 1.4.0", + "http 0.2.9", + "httparse 1.8.0", + "log 0.4.20", + "rand 0.8.5", + "rustls 0.19.1", + "sha-1 0.9.8", + "thiserror 1.0.44", + "url 2.4.0", + "utf-8 0.7.6", + "webpki 0.21.4 (registry+https://github.com/rust-lang/crates.io-index)", + "webpki-roots 0.21.1", +] + +[[package]] +name = "tungstenite" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30ee6ab729cd4cf0fd55218530c4522ed30b7b6081752839b68fcec8d0960788" +dependencies = [ + "base64 0.13.1", + "byteorder 1.4.3", + "bytes 1.4.0", + "http 0.2.9", + "httparse 1.8.0", + "log 0.4.20", + "native-tls", + "rand 0.8.5", + "sha1 0.10.5", + "thiserror 1.0.44", + "url 2.4.0", + "utf-8 0.7.6", +] + +[[package]] +name = "turn" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4712ee30d123ec7ae26d1e1b218395a16c87cdbaf4b3925d170d684af62ea5e8" +dependencies = [ + "async-trait", + "base64 0.13.1", + "futures 0.3.28", + "log 0.4.20", + "md-5", + "rand 0.8.5", + "ring 0.16.20", + "stun", + "thiserror 1.0.44", + "tokio", + "webrtc-util", +] + +[[package]] +name = "twox-hash" +version = "1.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" +dependencies = [ + "cfg-if 1.0.0", + "digest 0.10.7", + "rand 0.8.5", + "static_assertions", +] + +[[package]] +name = "typed-builder" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a46ee5bd706ff79131be9c94e7edcb82b703c487766a114434e5790361cf08c5" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "typenum" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" + +[[package]] +name = "typenum" +version = "1.16.0" +source = "git+https://github.com/encointer/typenum?tag=v1.16.0#4c8dddaa8bdd13130149e43b4085ad14e960617f" +dependencies = [ + "parity-scale-codec", + "scale-info", +] + +[[package]] +name = "ucd-trie" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" + +[[package]] +name = "uint" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76f64bba2c53b04fcab63c01a7d7427eadc821e3bc48c34dc9ba29c501164b52" +dependencies = [ + "byteorder 1.4.3", + "crunchy", + "hex", + "static_assertions", +] + +[[package]] +name = "unicase" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" +dependencies = [ + "version_check", +] + +[[package]] +name = "unicase" +version = "2.6.0" +source = "git+https://github.com/mesalock-linux/unicase-sgx#0b0519348572927118af47af3da4da9ffdca8ec6" +dependencies = [ + "sgx_tstd", + "version_check", +] + +[[package]] +name = "unicode-bidi" +version = "0.3.4" +source = "git+https://github.com/mesalock-linux/unicode-bidi-sgx#eb10728a635a046e75747849fbc680cbbb7832c7" +dependencies = [ + "matches 0.1.8", + "sgx_tstd", +] + +[[package]] +name = "unicode-bidi" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" + +[[package]] +name = "unicode-ident" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" + +[[package]] +name = "unicode-normalization" +version = "0.1.12" +source = "git+https://github.com/mesalock-linux/unicode-normalization-sgx#c1b030611969f87d75782c1df77975167cbbd509" +dependencies = [ + "smallvec 1.6.1", +] + +[[package]] +name = "unicode-normalization" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-width" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" + +[[package]] +name = "unicode-xid" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" + +[[package]] +name = "universal-hash" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f214e8f697e925001e66ec2c6e37a4ef93f0f78c2eed7814394e10c62025b05" +dependencies = [ + "generic-array 0.14.7", + "subtle", +] + +[[package]] +name = "universal-hash" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" +dependencies = [ + "crypto-common", + "subtle", +] + +[[package]] +name = "unsigned-varint" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7fdeedbf205afadfe39ae559b75c3240f24e257d0ca27e85f85cb82aa19ac35" + +[[package]] +name = "unsigned-varint" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d86a8dc7f45e4c1b0d30e43038c38f274e77af056aa5f74b93c2cf9eb3c1c836" +dependencies = [ + "asynchronous-codec", + "bytes 1.4.0", + "futures-io 0.3.28", + "futures-util 0.3.28", +] + +[[package]] +name = "untrusted" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "url" +version = "2.1.1" +source = "git+https://github.com/mesalock-linux/rust-url-sgx?tag=sgx_1.1.3#23832f3191456c2d4a0faab10952e1747be58ca8" +dependencies = [ + "idna 0.2.0", + "matches 0.1.8", + "percent-encoding 2.1.0", + "sgx_tstd", +] + +[[package]] +name = "url" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50bff7831e19200a85b17131d085c25d7811bc4e186efdaf54bbd132994a88cb" +dependencies = [ + "form_urlencoded", + "idna 0.4.0", + "percent-encoding 2.3.0", +] + +[[package]] +name = "urlencoding" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" + +[[package]] +name = "utf-8" +version = "0.7.4" +source = "git+https://github.com/integritee-network/rust-utf8-sgx?branch=sgx-experimental#b026700da83a2f00f0e9f36f813ef28e447a719e" +dependencies = [ + "sgx_tstd", +] + +[[package]] +name = "utf-8" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" + +[[package]] +name = "uuid" +version = "1.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa2982af2eec27de306107c027578ff7f423d65f7250e40ce0fea8f45248b81" +dependencies = [ + "getrandom 0.2.10", +] + +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "vec_map" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "void" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" + +[[package]] +name = "waitgroup" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1f50000a783467e6c0200f9d10642f4bc424e39efc1b770203e88b488f79292" +dependencies = [ + "atomic-waker", +] + +[[package]] +name = "waker-fn" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" + +[[package]] +name = "walkdir" +version = "2.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[package]] +name = "warp" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba431ef570df1287f7f8b07e376491ad54f84d26ac473489427231e1718e1f69" +dependencies = [ + "bytes 1.4.0", + "futures-channel 0.3.28", + "futures-util 0.3.28", + "headers", + "http 0.2.9", + "hyper", + "log 0.4.20", + "mime", + "mime_guess", + "multer", + "percent-encoding 2.3.0", + "pin-project", + "rustls-pemfile", + "scoped-tls", + "serde 1.0.193", + "serde_json 1.0.103", + "serde_urlencoded", + "tokio", + "tokio-stream", + "tokio-tungstenite", + "tokio-util 0.7.8", + "tower-service", + "tracing", +] + +[[package]] +name = "wasi" +version = "0.9.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" + +[[package]] +name = "wasi" +version = "0.10.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" +dependencies = [ + "cfg-if 1.0.0", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" +dependencies = [ + "bumpalo", + "log 0.4.20", + "once_cell 1.18.0", + "proc-macro2", + "quote", + "syn 2.0.32", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c02dbc21516f9f1f04f187958890d7e6026df8d16540b7ad9492bc34a67cea03" +dependencies = [ + "cfg-if 1.0.0", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.32", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" + +[[package]] +name = "wasm-instrument" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa1dafb3e60065305741e83db35c6c2584bb3725b692b5b66148a38d72ace6cd" +dependencies = [ + "parity-wasm", +] + +[[package]] +name = "wasm-opt" +version = "0.111.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84a303793cbc01fb96551badfc7367db6007396bba6bac97936b3c8b6f7fdb41" +dependencies = [ + "anyhow", + "libc", + "strum 0.24.1", + "strum_macros 0.24.3", + "tempfile", + "thiserror 1.0.44", + "wasm-opt-cxx-sys", + "wasm-opt-sys", +] + +[[package]] +name = "wasm-opt-cxx-sys" +version = "0.111.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c9deb56f8a9f2ec177b3bd642a8205621835944ed5da55f2388ef216aca5a4" +dependencies = [ + "anyhow", + "cxx", + "cxx-build", + "wasm-opt-sys", +] + +[[package]] +name = "wasm-opt-sys" +version = "0.111.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4432e28b542738a9776cedf92e8a99d8991c7b4667ee2c7ccddfb479dd2856a7" +dependencies = [ + "anyhow", + "cc", + "cxx", + "cxx-build", + "regex 1.9.5", +] + +[[package]] +name = "wasm-timer" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be0ecb0db480561e9a7642b5d3e4187c128914e58aa84330b9493e3eb68c5e7f" +dependencies = [ + "futures 0.3.28", + "js-sys", + "parking_lot 0.11.2", + "pin-utils", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "wasmi" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06c326c93fbf86419608361a2c925a31754cf109da1b8b55737070b4d6669422" +dependencies = [ + "parity-wasm", + "wasmi-validation", + "wasmi_core", +] + +[[package]] +name = "wasmi-validation" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91ff416ad1ff0c42e5a926ed5d5fab74c0f098749aa0ad8b2a34b982ce0e867b" +dependencies = [ + "parity-wasm", +] + +[[package]] +name = "wasmi_core" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57d20cb3c59b788653d99541c646c561c9dd26506f25c0cebfe810659c54c6d7" +dependencies = [ + "downcast-rs", + "libm 0.2.7", + "memory_units", + "num-rational 0.4.1", + "num-traits 0.2.16", + "region", +] + +[[package]] +name = "wasmparser" +version = "0.100.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64b20236ab624147dfbb62cf12a19aaf66af0e41b8398838b66e997d07d269d4" +dependencies = [ + "indexmap 1.9.3", + "url 2.4.0", +] + +[[package]] +name = "wasmtime" +version = "6.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76a222f5fa1e14b2cefc286f1b68494d7a965f4bf57ec04c59bb62673d639af6" +dependencies = [ + "anyhow", + "bincode", + "cfg-if 1.0.0", + "indexmap 1.9.3", + "libc", + "log 0.4.20", + "object 0.29.0", + "once_cell 1.18.0", + "paste", + "psm", + "rayon", + "serde 1.0.193", + "target-lexicon", + "wasmparser", + "wasmtime-cache", + "wasmtime-cranelift", + "wasmtime-environ", + "wasmtime-jit", + "wasmtime-runtime", + "windows-sys 0.42.0", +] + +[[package]] +name = "wasmtime-asm-macros" +version = "6.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4407a7246e7d2f3d8fb1cf0c72fda8dbafdb6dd34d555ae8bea0e5ae031089cc" +dependencies = [ + "cfg-if 1.0.0", +] + +[[package]] +name = "wasmtime-cache" +version = "6.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ceb3adf61d654be0be67fffdce42447b0880481348785be5fe40b5dd7663a4c" +dependencies = [ + "anyhow", + "base64 0.13.1", + "bincode", + "directories-next", + "file-per-thread-logger", + "log 0.4.20", + "rustix 0.36.15", + "serde 1.0.193", + "sha2 0.10.7", + "toml 0.5.11", + "windows-sys 0.42.0", + "zstd 0.11.2+zstd.1.5.2", +] + +[[package]] +name = "wasmtime-cranelift" +version = "6.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c366bb8647e01fd08cb5589976284b00abfded5529b33d7e7f3f086c68304a4" +dependencies = [ + "anyhow", + "cranelift-codegen", + "cranelift-entity", + "cranelift-frontend", + "cranelift-native", + "cranelift-wasm", + "gimli 0.26.2", + "log 0.4.20", + "object 0.29.0", + "target-lexicon", + "thiserror 1.0.44", + "wasmparser", + "wasmtime-environ", +] + +[[package]] +name = "wasmtime-environ" +version = "6.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47b8b50962eae38ee319f7b24900b7cf371f03eebdc17400c1dc8575fc10c9a7" +dependencies = [ + "anyhow", + "cranelift-entity", + "gimli 0.26.2", + "indexmap 1.9.3", + "log 0.4.20", + "object 0.29.0", + "serde 1.0.193", + "target-lexicon", + "thiserror 1.0.44", + "wasmparser", + "wasmtime-types", +] + +[[package]] +name = "wasmtime-jit" +version = "6.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffaed4f9a234ba5225d8e64eac7b4a5d13b994aeb37353cde2cbeb3febda9eaa" +dependencies = [ + "addr2line 0.17.0", + "anyhow", + "bincode", + "cfg-if 1.0.0", + "cpp_demangle", + "gimli 0.26.2", + "log 0.4.20", + "object 0.29.0", + "rustc-demangle", + "serde 1.0.193", + "target-lexicon", + "wasmtime-environ", + "wasmtime-jit-debug", + "wasmtime-jit-icache-coherence", + "wasmtime-runtime", + "windows-sys 0.42.0", +] + +[[package]] +name = "wasmtime-jit-debug" +version = "6.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eed41cbcbf74ce3ff6f1d07d1b707888166dc408d1a880f651268f4f7c9194b2" +dependencies = [ + "object 0.29.0", + "once_cell 1.18.0", + "rustix 0.36.15", +] + +[[package]] +name = "wasmtime-jit-icache-coherence" +version = "6.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a28ae1e648461bfdbb79db3efdaee1bca5b940872e4175390f465593a2e54c" +dependencies = [ + "cfg-if 1.0.0", + "libc", + "windows-sys 0.42.0", +] + +[[package]] +name = "wasmtime-runtime" +version = "6.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e704b126e4252788ccfc3526d4d4511d4b23c521bf123e447ac726c14545217b" +dependencies = [ + "anyhow", + "cc", + "cfg-if 1.0.0", + "indexmap 1.9.3", + "libc", + "log 0.4.20", + "mach", + "memfd", + "memoffset 0.6.5", + "paste", + "rand 0.8.5", + "rustix 0.36.15", + "wasmtime-asm-macros", + "wasmtime-environ", + "wasmtime-jit-debug", + "windows-sys 0.42.0", +] + +[[package]] +name = "wasmtime-types" +version = "6.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83e5572c5727c1ee7e8f28717aaa8400e4d22dcbd714ea5457d85b5005206568" +dependencies = [ + "cranelift-entity", + "serde 1.0.193", + "thiserror 1.0.44", + "wasmparser", +] + +[[package]] +name = "web-sys" +version = "0.3.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webpki" +version = "0.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8e38c0608262c46d4a56202ebabdeb094cef7e560ca7a226c6bf055188aa4ea" +dependencies = [ + "ring 0.16.20", + "untrusted 0.7.1", +] + +[[package]] +name = "webpki" +version = "0.21.4" +source = "git+https://github.com/mesalock-linux/webpki?branch=mesalock_sgx#8dbe6fbeefadf05582ae47c7fa818b04db49c61e" +dependencies = [ + "ring 0.16.19", + "sgx_tstd", + "untrusted 0.7.1", +] + +[[package]] +name = "webpki" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd" +dependencies = [ + "ring 0.16.20", + "untrusted 0.7.1", +] + +[[package]] +name = "webpki-roots" +version = "0.21.0" +source = "git+https://github.com/mesalock-linux/webpki-roots?tag=sgx_1.1.3#6ff3be547ac13ccd46ae55605ad6506ce30688ef" +dependencies = [ + "sgx_tstd", + "webpki 0.21.4 (git+https://github.com/mesalock-linux/webpki?branch=mesalock_sgx)", +] + +[[package]] +name = "webpki-roots" +version = "0.21.0" +source = "git+https://github.com/mesalock-linux/webpki-roots?branch=mesalock_sgx#6ff3be547ac13ccd46ae55605ad6506ce30688ef" +dependencies = [ + "sgx_tstd", + "webpki 0.21.4 (git+https://github.com/mesalock-linux/webpki?branch=mesalock_sgx)", +] + +[[package]] +name = "webpki-roots" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aabe153544e473b775453675851ecc86863d2a81d786d741f6b76778f2a48940" +dependencies = [ + "webpki 0.21.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "webpki-roots" +version = "0.22.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c71e40d7d2c34a5106301fb632274ca37242cd0c9d3e64dbece371a40a2d87" +dependencies = [ + "webpki 0.22.0", +] + +[[package]] +name = "webrtc" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d3bc9049bdb2cea52f5fd4f6f728184225bdb867ed0dc2410eab6df5bdd67bb" +dependencies = [ + "arc-swap", + "async-trait", + "bytes 1.4.0", + "hex", + "interceptor", + "lazy_static", + "log 0.4.20", + "rand 0.8.5", + "rcgen 0.9.3", + "regex 1.9.5", + "ring 0.16.20", + "rtcp", + "rtp", + "rustls 0.19.1", + "sdp", + "serde 1.0.193", + "serde_json 1.0.103", + "sha2 0.10.7", + "stun", + "thiserror 1.0.44", + "time 0.3.22", + "tokio", + "turn", + "url 2.4.0", + "waitgroup", + "webrtc-data", + "webrtc-dtls", + "webrtc-ice", + "webrtc-mdns", + "webrtc-media", + "webrtc-sctp", + "webrtc-srtp", + "webrtc-util", +] + +[[package]] +name = "webrtc-data" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ef36a4d12baa6e842582fe9ec16a57184ba35e1a09308307b67d43ec8883100" +dependencies = [ + "bytes 1.4.0", + "derive_builder", + "log 0.4.20", + "thiserror 1.0.44", + "tokio", + "webrtc-sctp", + "webrtc-util", +] + +[[package]] +name = "webrtc-dtls" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "942be5bd85f072c3128396f6e5a9bfb93ca8c1939ded735d177b7bcba9a13d05" +dependencies = [ + "aes 0.6.0", + "aes-gcm 0.10.2", + "async-trait", + "bincode", + "block-modes", + "byteorder 1.4.3", + "ccm", + "curve25519-dalek 3.2.0", + "der-parser 8.2.0", + "elliptic-curve 0.12.3", + "hkdf", + "hmac 0.12.1", + "log 0.4.20", + "oid-registry 0.6.1", + "p256", + "p384", + "rand 0.8.5", + "rand_core 0.6.4", + "rcgen 0.9.3", + "ring 0.16.20", + "rustls 0.19.1", + "sec1 0.3.0", + "serde 1.0.193", + "sha1 0.10.5", + "sha2 0.10.7", + "signature 1.6.4", + "subtle", + "thiserror 1.0.44", + "tokio", + "webpki 0.21.4 (registry+https://github.com/rust-lang/crates.io-index)", + "webrtc-util", + "x25519-dalek 2.0.0-pre.1", + "x509-parser 0.13.2", +] + +[[package]] +name = "webrtc-ice" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "465a03cc11e9a7d7b4f9f99870558fe37a102b65b93f8045392fef7c67b39e80" +dependencies = [ + "arc-swap", + "async-trait", + "crc", + "log 0.4.20", + "rand 0.8.5", + "serde 1.0.193", + "serde_json 1.0.103", + "stun", + "thiserror 1.0.44", + "tokio", + "turn", + "url 2.4.0", + "uuid", + "waitgroup", + "webrtc-mdns", + "webrtc-util", +] + +[[package]] +name = "webrtc-mdns" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f08dfd7a6e3987e255c4dbe710dde5d94d0f0574f8a21afa95d171376c143106" +dependencies = [ + "log 0.4.20", + "socket2 0.4.9", + "thiserror 1.0.44", + "tokio", + "webrtc-util", +] + +[[package]] +name = "webrtc-media" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f72e1650a8ae006017d1a5280efb49e2610c19ccc3c0905b03b648aee9554991" +dependencies = [ + "byteorder 1.4.3", + "bytes 1.4.0", + "rand 0.8.5", + "rtp", + "thiserror 1.0.44", +] + +[[package]] +name = "webrtc-sctp" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d47adcd9427eb3ede33d5a7f3424038f63c965491beafcc20bc650a2f6679c0" +dependencies = [ + "arc-swap", + "async-trait", + "bytes 1.4.0", + "crc", + "log 0.4.20", + "rand 0.8.5", + "thiserror 1.0.44", + "tokio", + "webrtc-util", +] + +[[package]] +name = "webrtc-srtp" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6183edc4c1c6c0175f8812eefdce84dfa0aea9c3ece71c2bf6ddd3c964de3da5" +dependencies = [ + "aead 0.4.3", + "aes 0.7.5", + "aes-gcm 0.9.4", + "async-trait", + "byteorder 1.4.3", + "bytes 1.4.0", + "ctr 0.8.0", + "hmac 0.11.0", + "log 0.4.20", + "rtcp", + "rtp", + "sha-1 0.9.8", + "subtle", + "thiserror 1.0.44", + "tokio", + "webrtc-util", +] + +[[package]] +name = "webrtc-util" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93f1db1727772c05cf7a2cfece52c3aca8045ca1e176cd517d323489aa3c6d87" +dependencies = [ + "async-trait", + "bitflags 1.3.2", + "bytes 1.4.0", + "cc", + "ipnet", + "lazy_static", + "libc", + "log 0.4.20", + "nix", + "rand 0.8.5", + "thiserror 1.0.44", + "tokio", + "winapi 0.3.9", +] + +[[package]] +name = "which" +version = "4.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2441c784c52b289a054b7201fc93253e288f094e2f4be9058343127c4226a269" +dependencies = [ + "either", + "libc", + "once_cell 1.18.0", +] + +[[package]] +name = "wide" +version = "0.7.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa469ffa65ef7e0ba0f164183697b89b854253fd31aeb92358b7b6155177d62f" +dependencies = [ + "bytemuck", + "safe_arch", +] + +[[package]] +name = "widestring" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "653f141f39ec16bba3c5abe400a0c60da7468261cc2cbf36805022876bc721a8" + +[[package]] +name = "winapi" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-build" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" + +[[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-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi 0.3.9", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45296b64204227616fdbf2614cefa4c236b98ee64dfaaaa435207ed99fe7829f" +dependencies = [ + "windows_aarch64_msvc 0.34.0", + "windows_i686_gnu 0.34.0", + "windows_i686_msvc 0.34.0", + "windows_x86_64_gnu 0.34.0", + "windows_x86_64_msvc 0.34.0", +] + +[[package]] +name = "windows" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" +dependencies = [ + "windows-targets 0.48.1", +] + +[[package]] +name = "windows-sys" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets 0.42.2", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.1", +] + +[[package]] +name = "windows-targets" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + +[[package]] +name = "windows-targets" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" +dependencies = [ + "windows_aarch64_gnullvm 0.48.0", + "windows_aarch64_msvc 0.48.0", + "windows_i686_gnu 0.48.0", + "windows_i686_msvc 0.48.0", + "windows_x86_64_gnu 0.48.0", + "windows_x86_64_gnullvm 0.48.0", + "windows_x86_64_msvc 0.48.0", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17cffbe740121affb56fad0fc0e421804adf0ae00891205213b5cecd30db881d" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" + +[[package]] +name = "windows_i686_gnu" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2564fde759adb79129d9b4f54be42b32c89970c18ebf93124ca8870a498688ed" + +[[package]] +name = "windows_i686_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" + +[[package]] +name = "windows_i686_msvc" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cd9d32ba70453522332c14d38814bceeb747d80b3958676007acadd7e166956" + +[[package]] +name = "windows_i686_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfce6deae227ee8d356d19effc141a509cc503dfd1f850622ec4b0f84428e1f4" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d19538ccc21819d01deaf88d6a17eae6596a12e9aafdbb97916fb49896d89de9" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" + +[[package]] +name = "winnow" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25b5872fa2e10bd067ae946f927e726d7d603eaeb6e02fa6a350e0722d2b8c11" +dependencies = [ + "memchr 2.6.3", +] + +[[package]] +name = "winreg" +version = "0.50.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" +dependencies = [ + "cfg-if 1.0.0", + "windows-sys 0.48.0", +] + +[[package]] +name = "ws" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25fe90c75f236a0a00247d5900226aea4f2d7b05ccc34da9e7a8880ff59b5848" +dependencies = [ + "byteorder 1.4.3", + "bytes 0.4.12", + "httparse 1.8.0", + "log 0.4.20", + "mio 0.6.23", + "mio-extras 2.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl", + "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", + "sha-1 0.8.2", + "slab 0.4.8", + "url 2.4.0", +] + +[[package]] +name = "ws2_32-sys" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" +dependencies = [ + "winapi 0.2.8", + "winapi-build", +] + +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + +[[package]] +name = "x25519-dalek" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a0c105152107e3b96f6a00a65e86ce82d9b125230e1c4302940eca58ff71f4f" +dependencies = [ + "curve25519-dalek 3.2.0", + "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "zeroize", +] + +[[package]] +name = "x25519-dalek" +version = "2.0.0-pre.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5da623d8af10a62342bcbbb230e33e58a63255a58012f8653c578e54bab48df" +dependencies = [ + "curve25519-dalek 3.2.0", + "rand_core 0.6.4", + "zeroize", +] + +[[package]] +name = "x509-cert" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99d224a125dec5adda27d0346b9cae9794830279c4f9c27e4ab0b6c408d54012" +dependencies = [ + "const-oid", + "der 0.6.1", + "flagset", + "spki 0.6.0", +] + +[[package]] +name = "x509-parser" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fb9bace5b5589ffead1afb76e43e34cff39cd0f3ce7e170ae0c29e53b88eb1c" +dependencies = [ + "asn1-rs 0.3.1", + "base64 0.13.1", + "data-encoding", + "der-parser 7.0.0", + "lazy_static", + "nom", + "oid-registry 0.4.0", + "ring 0.16.20", + "rusticata-macros", + "thiserror 1.0.44", + "time 0.3.22", +] + +[[package]] +name = "x509-parser" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0ecbeb7b67ce215e40e3cc7f2ff902f94a223acf44995934763467e7b1febc8" +dependencies = [ + "asn1-rs 0.5.2", + "base64 0.13.1", + "data-encoding", + "der-parser 8.2.0", + "lazy_static", + "nom", + "oid-registry 0.6.1", + "rusticata-macros", + "thiserror 1.0.44", + "time 0.3.22", +] + +[[package]] +name = "xcm" +version = "0.9.42" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" +dependencies = [ + "bounded-collections", + "derivative", + "impl-trait-for-tuples", + "log 0.4.20", + "parity-scale-codec", + "scale-info", + "serde 1.0.193", + "sp-weights", + "xcm-procedural", +] + +[[package]] +name = "xcm-builder" +version = "0.9.42" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" +dependencies = [ + "frame-support", + "frame-system", + "impl-trait-for-tuples", + "log 0.4.20", + "pallet-transaction-payment", + "parity-scale-codec", + "polkadot-parachain", + "scale-info", + "sp-arithmetic", + "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", + "sp-runtime", + "sp-std 5.0.0", + "xcm", + "xcm-executor", +] + +[[package]] +name = "xcm-executor" +version = "0.9.42" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" +dependencies = [ + "environmental 1.1.4", + "frame-support", + "impl-trait-for-tuples", + "log 0.4.20", + "parity-scale-codec", + "sp-arithmetic", + "sp-core", + "sp-io 7.0.0 (git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42)", + "sp-runtime", + "sp-std 5.0.0", + "sp-weights", + "xcm", +] + +[[package]] +name = "xcm-procedural" +version = "0.9.42" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" +dependencies = [ + "Inflector", + "proc-macro2", + "quote", + "syn 2.0.32", +] + +[[package]] +name = "xous" +version = "0.9.54" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8a9f0a696320940ab2652fa1d20c98dc59eb7ba4591eeb91a3b8e40bc9255a1" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "xous-api-log" +version = "0.1.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03e07c190c743d6d9e076f715333e94c48de41b99078343d174c707803df28c7" +dependencies = [ + "log 0.4.20", + "num-derive", + "num-traits 0.2.16", + "xous", + "xous-ipc", +] + +[[package]] +name = "xous-api-names" +version = "0.9.52" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32d8361077e67966d25922056284d17d042cbb1c96a7ebc2584eb8181427cbb0" +dependencies = [ + "log 0.4.20", + "num-derive", + "num-traits 0.2.16", + "rkyv", + "xous", + "xous-api-log", + "xous-ipc", +] + +[[package]] +name = "xous-ipc" +version = "0.9.54" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ee1d318dacbd6242e4e2291dee7c4532249e5a0845de05d264c20fc871a0a1a" +dependencies = [ + "bitflags 1.3.2", + "rkyv", + "xous", +] + +[[package]] +name = "yaml-rust" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e66366e18dc58b46801afbf2ca7661a9f59cc8c5962c29892b6039b4f86fa992" + +[[package]] +name = "yaml-rust" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" +dependencies = [ + "linked-hash-map 0.5.6", +] + +[[package]] +name = "yamux" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5d9ba232399af1783a58d8eb26f6b5006fbefe2dc9ef36bd283324792d03ea5" +dependencies = [ + "futures 0.3.28", + "log 0.4.20", + "nohash-hasher", + "parking_lot 0.12.1", + "rand 0.8.5", + "static_assertions", +] + +[[package]] +name = "yap" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fc77f52dc9e9b10d55d3f4462c3b7fc393c4f17975d641542833ab2d3bc26ef" + +[[package]] +name = "yasna" +version = "0.3.1" +source = "git+https://github.com/mesalock-linux/yasna.rs-sgx?rev=sgx_1.1.3#a1f50714cd3eb29608ecf7888cacedc173edfdb2" +dependencies = [ + "bit-vec", + "chrono 0.4.11", + "num-bigint 0.2.5", + "sgx_tstd", +] + +[[package]] +name = "yasna" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e262a29d0e61ccf2b6190d7050d4b237535fc76ce4c1210d9caa316f71dffa75" +dependencies = [ + "bit-vec", + "chrono 0.4.26", + "num-bigint 0.4.3", +] + +[[package]] +name = "yasna" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e17bb3549cc1321ae1296b9cdc2698e2b6cb1992adfa19a8c72e5b7a738f44cd" +dependencies = [ + "time 0.3.22", +] + +[[package]] +name = "zeroize" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.32", +] + +[[package]] +name = "zstd" +version = "0.11.2+zstd.1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20cc960326ece64f010d2d2107537f26dc589a6573a316bd5b1dba685fa5fde4" +dependencies = [ + "zstd-safe 5.0.2+zstd.1.5.2", +] + +[[package]] +name = "zstd" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a27595e173641171fc74a1232b7b1c7a7cb6e18222c11e9dfb9888fa424c53c" +dependencies = [ + "zstd-safe 6.0.6", +] + +[[package]] +name = "zstd-safe" +version = "5.0.2+zstd.1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d2a5585e04f9eea4b2a3d1eca508c4dee9592a89ef6f450c11719da0726f4db" +dependencies = [ + "libc", + "zstd-sys", +] + +[[package]] +name = "zstd-safe" +version = "6.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee98ffd0b48ee95e6c5168188e44a54550b1564d9d530ee21d5f0eaed1069581" +dependencies = [ + "libc", + "zstd-sys", +] + +[[package]] +name = "zstd-sys" +version = "2.0.8+zstd.1.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5556e6ee25d32df2586c098bbfa278803692a20d0ab9565e049480d52707ec8c" +dependencies = [ + "cc", + "libc", + "pkg-config", +] diff --git a/bitacross-worker/Cargo.toml b/bitacross-worker/Cargo.toml new file mode 100644 index 0000000000..2ad3682233 --- /dev/null +++ b/bitacross-worker/Cargo.toml @@ -0,0 +1,112 @@ +[workspace] + +members = [ + "app-libs/oracle", + "app-libs/parentchain-interface", + "app-libs/sgx-runtime", + "app-libs/stf", + "cli", + "core/direct-rpc-client", + "core/direct-rpc-server", + "core/peer-top-broadcaster", + "core/offchain-worker-executor", + "core/parentchain/block-import-dispatcher", + "core/parentchain/block-importer", + "core/parentchain/indirect-calls-executor", + "core/parentchain/light-client", + "core/parentchain/parentchain-crate", + "core/rest-client", + "core/rpc-client", + "core/rpc-server", + "core/tls-websocket-server", + "core-primitives/attestation-handler", + "core-primitives/import-queue", + "core-primitives/component-container", + "core-primitives/enclave-api", + "core-primitives/enclave-api/ffi", + "core-primitives/enclave-metrics", + "core-primitives/extrinsics-factory", + "core-primitives/hashing", + "core-primitives/networking-utils", + "core-primitives/node-api", + "core-primitives/node-api/api-client-extensions", + "core-primitives/node-api/api-client-types", + "core-primitives/node-api/factory", + "core-primitives/node-api/metadata", + "core-primitives/node-api/metadata-provider", + "core-primitives/nonce-cache", + "core-primitives/ocall-api", + "core-primitives/primitives-cache", + "core-primitives/rpc", + "core-primitives/settings", + "core-primitives/sgx/crypto", + "core-primitives/sgx/io", + "core-primitives/sgx-runtime-primitives", + "core-primitives/stf-executor", + "core-primitives/stf-interface", + "core-primitives/stf-primitives", + "core-primitives/stf-state-handler", + "core-primitives/stf-state-observer", + "core-primitives/storage", + "core-primitives/substrate-sgx/environmental", + "core-primitives/substrate-sgx/externalities", + "core-primitives/substrate-sgx/sp-io", + "core-primitives/teerex-storage", + "core-primitives/test", + "core-primitives/time-utils", + "core-primitives/top-pool", + "core-primitives/top-pool-author", + "core-primitives/types", + "core-primitives/utils", + "service", + "sidechain/block-composer", + "sidechain/block-verification", + "sidechain/consensus/aura", + "sidechain/consensus/common", + "sidechain/consensus/slots", + "sidechain/fork-tree", + "sidechain/peer-fetch", + "sidechain/primitives", + "sidechain/rpc-handler", + "sidechain/sidechain-crate", + "sidechain/state", + "sidechain/validateer-fetch", + "litentry/primitives", + "litentry/macros", +] + +[patch."https://github.com/apache/teaclave-sgx-sdk.git"] +sgx_alloc = { version = "1.1.6", git = "https://github.com/apache/incubator-teaclave-sgx-sdk", branch = "master" } +sgx_crypto_helper = { version = "1.1.6", git = "https://github.com/apache/incubator-teaclave-sgx-sdk", branch = "master" } +sgx_libc = { version = "1.1.6", git = "https://github.com/apache/incubator-teaclave-sgx-sdk", branch = "master" } +sgx_rand = { version = "1.1.6", git = "https://github.com/apache/incubator-teaclave-sgx-sdk", branch = "master" } +sgx_tcrypto = { version = "1.1.6", git = "https://github.com/apache/incubator-teaclave-sgx-sdk", branch = "master" } +sgx_trts = { version = "1.1.6", git = "https://github.com/apache/incubator-teaclave-sgx-sdk", branch = "master" } +sgx_tstd = { version = "1.1.6", git = "https://github.com/apache/incubator-teaclave-sgx-sdk", branch = "master" } +sgx_types = { version = "1.1.6", git = "https://github.com/apache/incubator-teaclave-sgx-sdk", branch = "master" } +sgx_ucrypto = { version = "1.1.6", git = "https://github.com/apache/incubator-teaclave-sgx-sdk", branch = "master" } +sgx_urts = { version = "1.1.6", git = "https://github.com/apache/incubator-teaclave-sgx-sdk", branch = "master" } + +[patch.crates-io] +ring = { git = "https://github.com/betrusted-io/ring-xous", branch = "0.16.20-cleanup" } + +#[patch."https://github.com/integritee-network/integritee-node"] +#my-node-runtime = { package = "integritee-node-runtime", git = "https://github.com/integritee-network//integritee-node", branch = "ab/integrate-pallet-teerex-refactoring" } + +#[patch."https://github.com/scs/substrate-api-client"] +#substrate-api-client = { path = "../../scs/substrate-api-client" } +#substrate-client-keystore = { path = "../../scs/substrate-api-client/client-keystore" } + +#[patch."https://github.com/integritee-network/pallets.git"] +#pallet-claims = { git = "https://github.com/integritee-network//pallets", branch = "ab/shard-config-upgradability-2" } +#pallet-enclave-bridge = { git = "https://github.com/integritee-network//pallets", branch = "ab/shard-config-upgradability-2" } +#pallet-teerex = { git = "https://github.com/integritee-network//pallets", branch = "ab/shard-config-upgradability-2" } +#pallet-sidechain = { git = "https://github.com/integritee-network//pallets", branch = "ab/shard-config-upgradability-2" } +#sgx-verify = { git = "https://github.com/integritee-network//pallets", branch = "ab/shard-config-upgradability-2" } +#pallet-teeracle = { git = "https://github.com/integritee-network//pallets", branch = "ab/shard-config-upgradability-2" } +#test-utils = { git = "https://github.com/integritee-network//pallets", branch = "ab/shard-config-upgradability-2" } +#claims-primitives = { git = "https://github.com/integritee-network//pallets", branch = "ab/shard-config-upgradability-2" } +#enclave-bridge-primitives = { git = "https://github.com/integritee-network//pallets", branch = "ab/shard-config-upgradability-2" } +#teerex-primitives = { git = "https://github.com/integritee-network//pallets", branch = "ab/shard-config-upgradability-2" } +#teeracle-primitives = { git = "https://github.com/integritee-network//pallets", branch = "ab/shard-config-upgradability-2" } +#common-primitives = { git = "https://github.com/integritee-network//pallets", branch = "ab/shard-config-upgradability-2" } diff --git a/bitacross-worker/DESIGN.md b/bitacross-worker/DESIGN.md new file mode 100644 index 0000000000..8d579d96b7 --- /dev/null +++ b/bitacross-worker/DESIGN.md @@ -0,0 +1,72 @@ +# sidechain startup internal view +```mermaid +sequenceDiagram + participant integritee_network + participant service + participant slotworker + participant parentsync + participant enclave + participant enclave_rpc + participant provisioningserver + participant isinitializedserver + participant metrics + service ->> enclave: EnclaveBase.get_mrenclave + service ->> provisioningserver: spawn (`--mu-ra-port` | 3443) + activate provisioningserver + service ->> enclave: get_ecc_signing_pubkey + service ->> isinitializedserver: spawn (`--untrusted-http-port | 4545) + activate isinitializedserver + service ->> metrics: spawn (`--metrics-port`| 8787) + activate metrics + service ->> enclave_rpc: spawn (`--trusted-worker-port`| 2000) + activate enclave_rpc + + service ->> enclave: generate_dcap_ra_extrinsic + service ->> integritee_network: send register_sgx_enclave extrinsic + service ->> integritee_network: get ShardStatus + service ->> isinitializedserver: registered_on_parentchain +# schedule teeracle re-registration and updates + loop while blocks to sync + service ->> integritee_network: get_block + service ->> enclave: sync_parentchain(blocks, events, proofs) + end + service ->> enclave: init_enclave_sidechain_components + service ->> slotworker: spawn + loop forever + slotworker ->> enclave: execute_trusted_calls + activate enclave + enclave ->> enclave: propose_sidechain_block + enclave ->> integritee_network: send_extrinsics + deactivate enclave + end + service ->> parentsync: spawn + loop forever + parentsync ->> integritee_network: subscribe new headers + parentsync ->> enclave: sync_parentchain + end + service ->> service: poll worker_for_shard + service ->> isinitializedserver: worker_for_shard_registered + + deactivate enclave_rpc + deactivate metrics + deactivate isinitializedserver + deactivate provisioningserver +``` + +# sidechain lifetime external view + +```mermaid +sequenceDiagram + participant integritee_network + participant validateer_1 + participant validateer_2 + actor alice + + validateer_1 ->> integritee_network: register_sgx_enclave() + + validateer_2 ->> integritee_network: register_sgx_enclave() + + validateer_2 ->> validateer_1: sidechain_fetchBlocksFromPeer() + + validateer_1 ->> validateer_2: sidechain_importBlock() +``` diff --git a/bitacross-worker/Dockerfile b/bitacross-worker/Dockerfile new file mode 100644 index 0000000000..95bd8a9d60 --- /dev/null +++ b/bitacross-worker/Dockerfile @@ -0,0 +1,23 @@ +FROM integritee/integritee-dev:0.2.2 +LABEL maintainer="zoltan@integritee.network" + +# By default we warp the service +ARG BINARY_FILE=integritee-service + +COPY bin/enclave.signed.so /usr/local/bin/ +COPY bin/${BINARY_FILE} /usr/local/bin/integritee + +RUN chmod +x /usr/local/bin/integritee + +WORKDIR /usr/local/bin +RUN touch spid.txt key.txt +RUN if [[ "x$BINARY_FILE" != "xintegritee-client" ]] ; then ./integritee init-shard; fi +RUN if [[ "x$BINARY_FILE" != "xintegritee-client" ]] ; then ./integritee shielding-key; fi +RUN if [[ "x$BINARY_FILE" != "xintegritee-client" ]] ; then ./integritee signing-key; fi +RUN if [[ "x$BINARY_FILE" != "xintegritee-client" ]] ; then ./integritee mrenclave > ~/mrenclave.b58; fi + +# checks +RUN ldd /usr/local/bin/integritee && \ + /usr/local/bin/integritee --version + +ENTRYPOINT ["/usr/local/bin/integritee"] diff --git a/bitacross-worker/Jenkinsfile b/bitacross-worker/Jenkinsfile new file mode 100755 index 0000000000..62c9197d68 --- /dev/null +++ b/bitacross-worker/Jenkinsfile @@ -0,0 +1,104 @@ +pipeline { + agent { + docker { + image 'integritee/integritee-dev:0.2.2' + args ''' + -u root + --privileged + ''' + } + } + options { + timeout(time: 2, unit: 'HOURS') + buildDiscarder(logRotator(numToKeepStr: '14')) + } + stages { + stage('Init rust') { + steps { + sh 'cargo --version' + sh 'rustup show' + sh 'env' + } + } + stage('Build') { + steps { + sh 'export SGX_SDK=/opt/intel/sgxsdk' + sh 'make' + } + } + stage('Archive build output') { + steps { + archiveArtifacts artifacts: 'bin/enclave.signed.so, bin/integritee-*', caseSensitive: false, fingerprint: true, onlyIfSuccessful: true + } + } + stage('Test') { + steps { + sh 'cd cli && cargo test 2>&1 | tee ${WORKSPACE}/test_client.log' + sh 'cd service && cargo test 2>&1 | tee ${WORKSPACE}/test_server.log' + sh 'cd enclave-runtime && cargo test 2>&1 | tee ${WORKSPACE}/test_enclave.log' + } + } + stage('Clippy') { + steps { + sh 'cargo clean' + catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') { + sh 'cd cli && cargo clippy 2>&1 | tee ${WORKSPACE}/clippy_client.log' + } + catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') { + sh 'cd worker && cargo clippy 2>&1 | tee ${WORKSPACE}/clippy_worker.log' + } + catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') { + sh 'cd enclave && cargo clippy 2>&1 | tee ${WORKSPACE}/clippy_enclave.log' + } + } + } + stage('Formatter') { + steps { + catchError(buildResult: 'SUCCESS', stageResult: 'SUCCESS') { + sh 'cargo fmt -- --check > ${WORKSPACE}/fmt.log' + } + } + } + stage('Results') { + steps { + recordIssues( + aggregatingResults: true, + enabledForFailure: true, + qualityGates: [[threshold: 1, type: 'TOTAL', unstable: true]], + tools: [ + groovyScript( + parserId:'clippy-warnings', + pattern: 'clippy_*.log', + reportEncoding: 'UTF-8' + ), + groovyScript( + parserId:'clippy-errors', + pattern: 'clippy_*.log', + reportEncoding: 'UTF-8' + ) + ] + ) + catchError(buildResult: 'SUCCESS', stageResult: 'SUCCESS') { + sh './ci/check_fmt_log.sh' + } + } + } + stage('Archive logs') { + steps { + archiveArtifacts artifacts: '*.log' + } + } + } + post { + unsuccessful { + emailext ( + subject: "Jenkins Build '${env.JOB_NAME} [${env.BUILD_NUMBER}]' is ${currentBuild.currentResult}", + body: "${env.JOB_NAME} build ${env.BUILD_NUMBER} is ${currentBuild.currentResult}\n\nMore info at: ${env.BUILD_URL}", + to: "${env.RECIPIENTS_SUBSTRATEE}" + ) + } + always { + cleanWs() + } + } +} diff --git a/bitacross-worker/LICENSE b/bitacross-worker/LICENSE new file mode 100644 index 0000000000..261eeb9e9f --- /dev/null +++ b/bitacross-worker/LICENSE @@ -0,0 +1,201 @@ + 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. diff --git a/bitacross-worker/Makefile b/bitacross-worker/Makefile new file mode 100755 index 0000000000..7c65260557 --- /dev/null +++ b/bitacross-worker/Makefile @@ -0,0 +1,287 @@ +# Copyright 2021 Integritee AG and Supercomputing Systems AG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +######## Update SGX SDK ######## +# use this manually to update sdk +#include UpdateRustSGXSDK.mk + +######## SGX SDK Settings ######## +SGX_SDK ?= /opt/intel/sgxsdk +SGX_MODE ?= HW +SGX_ARCH ?= x64 +SGX_DEBUG ?= 0 +SGX_PRERELEASE ?= 0 +SGX_PRODUCTION ?= 0 + +######## Worker Feature Settings ######## +# Set offchain-worker as default feature mode +WORKER_MODE ?= offchain-worker + +SKIP_WASM_BUILD = 1 +# include the build settings from rust-sgx-sdk +include rust-sgx-sdk/buildenv.mk + +ifeq ($(shell getconf LONG_BIT), 32) + SGX_ARCH := x86 +else ifeq ($(findstring -m32, $(CXXFLAGS)), -m32) + SGX_ARCH := x86 +endif + +ifeq ($(SGX_ARCH), x86) + SGX_COMMON_CFLAGS := -m32 + SGX_LIBRARY_PATH := $(SGX_SDK)/lib + SGX_ENCLAVE_SIGNER := $(SGX_SDK)/bin/x86/sgx_sign + SGX_EDGER8R := $(SGX_SDK)/bin/x86/sgx_edger8r +else + SGX_COMMON_CFLAGS := -m64 + SGX_LIBRARY_PATH := $(SGX_SDK)/lib64 + SGX_ENCLAVE_SIGNER := $(SGX_SDK)/bin/x64/sgx_sign + SGX_EDGER8R := $(SGX_SDK)/bin/x64/sgx_edger8r +endif + +ifeq ($(SGX_DEBUG), 1) +ifeq ($(SGX_PRERELEASE), 1) +$(error Cannot set SGX_DEBUG and SGX_PRERELEASE at the same time!!) +endif +ifeq ($(SGX_PRODUCTION), 1) +$(error Cannot set SGX_DEBUG and SGX_PRODUCTION at the same time!!) +endif +endif + +ifeq ($(SGX_DEBUG), 1) + SGX_COMMON_CFLAGS += -O0 -g -ggdb + OUTPUT_PATH := debug + CARGO_TARGET := +else + SGX_COMMON_CFLAGS += -O2 + OUTPUT_PATH := release + CARGO_TARGET := --release +endif + +SGX_COMMON_CFLAGS += -fstack-protector + +ifeq ($(SGX_PRODUCTION), 1) + SGX_ENCLAVE_MODE = "Production Mode" + SGX_ENCLAVE_CONFIG = "enclave-runtime/Enclave.config.production.xml" + SGX_SIGN_KEY = $(SGX_COMMERCIAL_KEY) + SGX_SIGN_PASSFILE = $(SGX_PASSFILE) + WORKER_FEATURES := --features=production,link-binary,$(WORKER_MODE),$(WORKER_FEATURES),$(ADDITIONAL_FEATURES) +else + SGX_ENCLAVE_MODE = "Development Mode" + SGX_ENCLAVE_CONFIG = "enclave-runtime/Enclave.config.xml" + SGX_SIGN_KEY = "enclave-runtime/Enclave_private.pem" + SGX_SIGN_PASSFILE = "" + WORKER_FEATURES := --features=default,link-binary,$(WORKER_MODE),$(WORKER_FEATURES),$(ADDITIONAL_FEATURES) +endif + +CLIENT_FEATURES = --features=$(WORKER_MODE),$(ADDITIONAL_FEATURES) + +# check if running on Jenkins +ifdef BUILD_ID + CARGO_TARGET += --verbose +endif + +######## CUSTOM settings ######## +CUSTOM_LIBRARY_PATH := ./lib +CUSTOM_BIN_PATH := ./bin +CUSTOM_EDL_PATH := ./rust-sgx-sdk/edl +CUSTOM_COMMON_PATH := ./rust-sgx-sdk/common + +######## EDL settings ######## +Enclave_EDL_Files := enclave-runtime/Enclave_t.c enclave-runtime/Enclave_t.h service/Enclave_u.c service/Enclave_u.h + +######## bitacross-worker settings ######## +SRC_Files := $(shell find . -type f -name '*.rs') $(shell find . -type f -name 'Cargo.toml') +Worker_Rust_Flags := $(CARGO_TARGET) $(WORKER_FEATURES) +Worker_Include_Paths := -I ./service -I./include -I$(SGX_SDK)/include -I$(CUSTOM_EDL_PATH) +Worker_C_Flags := $(SGX_COMMON_CFLAGS) -fPIC -Wno-attributes $(Worker_Include_Paths) + +Worker_Rust_Path := target/$(OUTPUT_PATH) +Worker_Enclave_u_Object :=service/libEnclave_u.a +Worker_Name := bin/app + +######## bitacross-cli settings ######## +Client_Rust_Flags := $(CARGO_TARGET) $(CLIENT_FEATURES) + +Client_Rust_Path := target/$(OUTPUT_PATH) +Client_Path := bin +Client_Binary := bitacross-cli +Client_Name := $(Client_Path)/$(Client_Binary) + +######## Enclave settings ######## +ifneq ($(SGX_MODE), HW) + Trts_Library_Name := sgx_trts_sim + Service_Library_Name := sgx_tservice_sim +else + Trts_Library_Name := sgx_trts + Service_Library_Name := sgx_tservice +endif +Crypto_Library_Name := sgx_tcrypto +KeyExchange_Library_Name := sgx_tkey_exchange +ProtectedFs_Library_Name := sgx_tprotected_fs + +RustEnclave_C_Files := $(wildcard ./enclave-runtime/*.c) +RustEnclave_C_Objects := $(RustEnclave_C_Files:.c=.o) +RustEnclave_Include_Paths := -I$(CUSTOM_COMMON_PATH)/inc -I$(CUSTOM_EDL_PATH) -I$(SGX_SDK)/include -I$(SGX_SDK)/include/tlibc -I$(SGX_SDK)/include/stlport -I$(SGX_SDK)/include/epid -I ./enclave-runtime -I./include + +RustEnclave_Link_Libs := -L$(CUSTOM_LIBRARY_PATH) -lenclave +RustEnclave_Compile_Flags := $(SGX_COMMON_CFLAGS) $(ENCLAVE_CFLAGS) $(RustEnclave_Include_Paths) +RustEnclave_Link_Flags := -Wl,--no-undefined -nostdlib -nodefaultlibs -nostartfiles -L$(SGX_LIBRARY_PATH) \ + -Wl,--whole-archive -l$(Trts_Library_Name) -Wl,--no-whole-archive \ + -Wl,--start-group -lsgx_tstdc -lsgx_tcxx -lsgx_dcap_tvl -l$(Crypto_Library_Name) -l$(Service_Library_Name) -l$(ProtectedFs_Library_Name) $(RustEnclave_Link_Libs) -Wl,--end-group \ + -Wl,--version-script=enclave-runtime/Enclave.lds \ + $(ENCLAVE_LDFLAGS) + +RustEnclave_Name := enclave-runtime/enclave.so +Signed_RustEnclave_Name := bin/enclave.signed.so + +######## Targets ######## +.PHONY: all +all: $(Worker_Name) $(Client_Name) $(Signed_RustEnclave_Name) +service: $(Worker_Name) +client: $(Client_Name) +githooks: .git/hooks/pre-commit + +######## EDL objects ######## +$(Enclave_EDL_Files): $(SGX_EDGER8R) enclave-runtime/Enclave.edl + $(SGX_EDGER8R) --trusted enclave-runtime/Enclave.edl --search-path $(SGX_SDK)/include --search-path $(CUSTOM_EDL_PATH) --trusted-dir enclave-runtime + $(SGX_EDGER8R) --untrusted enclave-runtime/Enclave.edl --search-path $(SGX_SDK)/include --search-path $(CUSTOM_EDL_PATH) --untrusted-dir service + @echo "GEN => $(Enclave_EDL_Files)" + +######## bitacross-worker objects ######## +service/Enclave_u.o: $(Enclave_EDL_Files) + @$(CC) $(Worker_C_Flags) -c service/Enclave_u.c -o $@ + @echo "CC <= $<" + +$(Worker_Enclave_u_Object): service/Enclave_u.o + $(AR) rcsD $@ $^ + cp $(Worker_Enclave_u_Object) ./lib + +$(Worker_Name): $(Worker_Enclave_u_Object) $(SRC_Files) + @echo + @echo "Building the bitacross-worker: $(Worker_Rust_Flags)" + @SGX_SDK=$(SGX_SDK) SGX_MODE=$(SGX_MODE) cargo build -p bitacross-worker $(Worker_Rust_Flags) + @echo "Cargo => $@" + cp $(Worker_Rust_Path)/bitacross-worker ./bin + +######## bitacross-client objects ######## +$(Client_Name): $(SRC_Files) + @echo + @echo "Building the bitacross-cli $(Client_Rust_Flags)" + @cargo build -p bitacross-cli $(Client_Rust_Flags) + @echo "Cargo => $@" + cp $(Client_Rust_Path)/$(Client_Binary) ./bin + +######## Enclave objects ######## +enclave-runtime/Enclave_t.o: $(Enclave_EDL_Files) + @$(CC) $(RustEnclave_Compile_Flags) -c enclave-runtime/Enclave_t.c -o $@ + @echo "CC <= $<" + +$(RustEnclave_Name): enclave enclave-runtime/Enclave_t.o + @echo Compiling $(RustEnclave_Name) + @$(CXX) enclave-runtime/Enclave_t.o -o $@ $(RustEnclave_Link_Flags) + @echo "LINK => $@" + +$(Signed_RustEnclave_Name): $(RustEnclave_Name) + @echo + @echo "Signing the enclave: $(SGX_ENCLAVE_MODE)" + @echo "SGX_ENCLAVE_SIGNER: $(SGX_ENCLAVE_SIGNER)" + @echo "RustEnclave_Name: $(RustEnclave_Name)" + @echo "SGX_ENCLAVE_CONFIG: $(SGX_ENCLAVE_CONFIG)" + @echo "SGX_SIGN_PASSFILE: $(SGX_SIGN_PASSFILE)" + @echo "SGX_SIGN_KEY: $(SGX_SIGN_KEY)" + + +# TODO: figure out if/how to use the passphrase file in PROD +ifeq ($(SGX_PRODUCTION), 1) + $(SGX_ENCLAVE_SIGNER) gendata -enclave $(RustEnclave_Name) -out enclave_sig.dat -config $(SGX_ENCLAVE_CONFIG) + openssl rsa -pubout -in $(SGX_SIGN_KEY) -out intel_sgx.pub + openssl dgst -sha256 -sign $(SGX_SIGN_KEY) -out signature.dat enclave_sig.dat + openssl dgst -sha256 -verify intel_sgx.pub -signature signature.dat enclave_sig.dat + $(SGX_ENCLAVE_SIGNER) catsig -enclave $(RustEnclave_Name) -config $(SGX_ENCLAVE_CONFIG) -out $@ -key intel_sgx.pub -sig signature.dat -unsigned enclave_sig.dat +else + $(SGX_ENCLAVE_SIGNER) sign -key $(SGX_SIGN_KEY) -enclave $(RustEnclave_Name) -out $@ -config $(SGX_ENCLAVE_CONFIG) +endif + @echo "SIGN => $@" + @echo + @echo "Enclave is in $(SGX_ENCLAVE_MODE)" + +.PHONY: enclave +enclave: + @echo + @echo "Building the enclave" + $(MAKE) -C ./enclave-runtime/ + +.git/hooks/pre-commit: .githooks/pre-commit + @echo "Installing git hooks" + cp .githooks/pre-commit .git/hooks + +.PHONY: clean +clean: + @echo "Removing the compiled files" + @rm -f $(Client_Name) $(Worker_Name) $(RustEnclave_Name) $(Signed_RustEnclave_Name) \ + enclave-runtime/*_t.* \ + service/*_u.* \ + lib/*.a \ + bin/*.bin + @echo "cargo clean in enclave directory" + @cd enclave-runtime && cargo clean + @echo "cargo clean in root directory" + @cargo clean + +.PHONY: fmt +fmt: + @echo "Cargo format all ..." + @cargo fmt --all + @cd enclave-runtime && cargo fmt --all + +.PHONY: pin-sgx +pin-sgx: + @echo "Pin sgx dependencies to 594806f827b57e6c4c9a0611fa4cbf2d83aabd2e" + @cd enclave-runtime && cargo update -p sgx_tstd --precise 594806f827b57e6c4c9a0611fa4cbf2d83aabd2e + @cargo update -p sgx_tstd --precise 594806f827b57e6c4c9a0611fa4cbf2d83aabd2e + +mrenclave: + @$(SGX_ENCLAVE_SIGNER) dump -enclave ./bin/enclave.signed.so -dumpfile df.out && ./extract_identity < df.out && rm df.out + +mrsigner: + @$(SGX_ENCLAVE_SIGNER) dump -enclave ./bin/enclave.signed.so -dumpfile df.out && ./extract_identity --mrsigner < df.out && rm df.out + +.PHONY: identity +identity: mrenclave mrsigner + +.PHONY: release-pkg +release-pkg: + @./scripts/litentry/release/generate_release_pkg.sh + +.PHONY: help +help: + @echo "Available targets" + @echo " all - builds all targets (default)" + @echo " service - builds the bitacross-worker" + @echo " client - builds the bitacross-cli" + @echo " githooks - installs the git hooks (copy .githooks/pre-commit to .git/hooks)" + @echo "" + @echo " clean - cleanup" + @echo "" + @echo "Compilation options. Prepend them to the make command. Example: 'SGX_MODE=SW make'" + @echo " SGX_MODE" + @echo " HW (default): Use SGX hardware" + @echo " SW: Simulation mode" + @echo " SGX_DEBUG" + @echo " 0 (default): No debug information, optimization level 2, cargo release build" + @echo " 1: Debug information, optimization level 0, cargo debug build" + @echo " SGX_PRODUCTION" + @echo " 0 (default): Using SGX development environment" + @echo " 1: Using SGX production environment" diff --git a/bitacross-worker/README.md b/bitacross-worker/README.md new file mode 100755 index 0000000000..e2be743ff3 --- /dev/null +++ b/bitacross-worker/README.md @@ -0,0 +1 @@ +# bitacross worker \ No newline at end of file diff --git a/bitacross-worker/UpdateRustSGXSDK.mk b/bitacross-worker/UpdateRustSGXSDK.mk new file mode 100755 index 0000000000..88c95d5dc6 --- /dev/null +++ b/bitacross-worker/UpdateRustSGXSDK.mk @@ -0,0 +1,33 @@ +# helper script to update the files in rust-sgx-sdk to the lastest version + +GIT = git +CP = cp + +REPO = https://github.com/apache/incubator-teaclave-sgx-sdk +SDK_PATH_GIT = rust-sgx-sdk-github +SDK_PATH = rust-sgx-sdk +VERSION_FILE = rust-sgx-sdk/version +LOCAL_VERSION = $(shell cat $(VERSION_FILE)) +COMMAND = git ls-remote $(REPO) HEAD | awk '{ print $$1 }' +REMOTE_VERSION = $(shell $(COMMAND)) +# or specify the exact hash if you need a non-default branch / tag / commit etc. +#REMOTE_VERSION = 9c1bbd52f188f600a212b57c916124245da1b7fd + +# update the SDK files +all: updatesdk + +updatesdk: +# check for already updated version +ifneq ('$(LOCAL_VERSION)','$(REMOTE_VERSION)') + @echo Local version = $(LOCAL_VERSION) + @echo Remote version = $(REMOTE_VERSION) + + @rm -rf $(SDK_PATH_GIT) + @$(GIT) clone $(REPO) $(SDK_PATH_GIT) + @$(GIT) -C $(SDK_PATH_GIT) checkout $(REMOTE_VERSION) + rsync -a $(SDK_PATH_GIT)/edl $(SDK_PATH) + rsync -a $(SDK_PATH_GIT)/common $(SDK_PATH) + rm -rf $(SDK_PATH_GIT) + @echo $(REMOTE_VERSION) > $(VERSION_FILE) + +endif diff --git a/bitacross-worker/app-libs/oracle/Cargo.toml b/bitacross-worker/app-libs/oracle/Cargo.toml new file mode 100644 index 0000000000..eb8fa135e2 --- /dev/null +++ b/bitacross-worker/app-libs/oracle/Cargo.toml @@ -0,0 +1,48 @@ +[package] +name = "ita-oracle" +version = "0.9.0" +authors = ['Trust Computing GmbH ', 'Integritee AG '] +edition = "2021" + +[dependencies] + +# std dependencies +thiserror = { version = "1.0.26", optional = true } +url = { version = "2.0.0", optional = true } + +# sgx dependencies +sgx_tstd = { rev = "v1.1.3", git = "https://github.com/apache/teaclave-sgx-sdk.git", optional = true } +thiserror_sgx = { package = "thiserror", git = "https://github.com/mesalock-linux/thiserror-sgx", tag = "sgx_1.1.3", optional = true } +url_sgx = { package = "url", git = "https://github.com/mesalock-linux/rust-url-sgx", tag = "sgx_1.1.3", optional = true } + +# no_std dependencies +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +lazy_static = { version = "1.1.0", features = ["spin_no_std"] } +log = { version = "0.4", default-features = false } +serde = { version = "1.0", default-features = false, features = ["derive", "alloc"] } +substrate-fixed = { default-features = false, git = "https://github.com/encointer/substrate-fixed", tag = "v0.5.9" } + +# internal dependencies +itc-rest-client = { path = "../../core/rest-client", default-features = false } +itp-enclave-metrics = { path = "../../core-primitives/enclave-metrics", default-features = false } +itp-ocall-api = { path = "../../core-primitives/ocall-api", default-features = false } + +[features] +default = ["std"] +std = [ + "itc-rest-client/std", + "itp-enclave-metrics/std", + "itp-ocall-api/std", + "log/std", + "serde/std", + "substrate-fixed/std", + "thiserror", + "url", +] +sgx = [ + "itc-rest-client/sgx", + "itp-enclave-metrics/sgx", + "sgx_tstd", + "thiserror_sgx", + "url_sgx", +] diff --git a/bitacross-worker/app-libs/oracle/src/certificates/amazon_root_ca_a.pem b/bitacross-worker/app-libs/oracle/src/certificates/amazon_root_ca_a.pem new file mode 100644 index 0000000000..a6f3e92af5 --- /dev/null +++ b/bitacross-worker/app-libs/oracle/src/certificates/amazon_root_ca_a.pem @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsF +ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6 +b24gUm9vdCBDQSAxMB4XDTE1MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTEL +MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv +b3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ4gHHKeNXj +ca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgHFzZM +9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qw +IFAGbHrQgLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6 +VOujw5H5SNz/0egwLX0tdHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L +93FcXmn/6pUCyziKrlA4b9v7LWIbxcceVOF34GfID5yHI9Y/QCB/IIDEgEw+OyQm +jgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC +AYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3DQEBCwUA +A4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDI +U5PMCCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUs +N+gDS63pYaACbvXy8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vv +o/ufQJVtMVT8QtPHRh8jrdkPSHCa2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU +5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2xJNDd2ZhwLnoQdeXeGADbkpy +rqXRfboQnoZsG4q5WTP468SQvvG5 +-----END CERTIFICATE----- diff --git a/bitacross-worker/app-libs/oracle/src/certificates/baltimore_cyber_trust_root_v3.pem b/bitacross-worker/app-libs/oracle/src/certificates/baltimore_cyber_trust_root_v3.pem new file mode 100644 index 0000000000..519028c63b --- /dev/null +++ b/bitacross-worker/app-libs/oracle/src/certificates/baltimore_cyber_trust_root_v3.pem @@ -0,0 +1,21 @@ +-----BEGIN CERTIFICATE----- +MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJ +RTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYD +VQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoX +DTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMCSUUxEjAQBgNVBAoTCUJhbHRpbW9y +ZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFsdGltb3JlIEN5YmVy +VHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKMEuyKr +mD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjr +IZ3AQSsBUnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeK +mpYcqWe4PwzV9/lSEy/CG9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSu +XmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9XbIGevOF6uvUA65ehD5f/xXtabz5OTZy +dc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjprl3RjM71oGDHweI12v/ye +jl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoIVDaGezq1 +BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3 +DQEBBQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT92 +9hkTI7gQCvlYpNRhcL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3Wgx +jkzSswF07r51XgdIGn9w/xZchMB5hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0 +Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsaY71k5h+3zvDyny67G7fyUIhz +ksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9HRCwBXbsdtTLS +R9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp +-----END CERTIFICATE----- diff --git a/bitacross-worker/app-libs/oracle/src/certificates/lets_encrypt_root_cert.pem b/bitacross-worker/app-libs/oracle/src/certificates/lets_encrypt_root_cert.pem new file mode 100644 index 0000000000..57d4a3766c --- /dev/null +++ b/bitacross-worker/app-libs/oracle/src/certificates/lets_encrypt_root_cert.pem @@ -0,0 +1,31 @@ +-----BEGIN CERTIFICATE----- +MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw +TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh +cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4 +WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu +ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY +MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc +h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+ +0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U +A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW +T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH +B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC +B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv +KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn +OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn +jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw +qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI +rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV +HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq +hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL +ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ +3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK +NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5 +ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur +TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC +jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc +oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq +4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA +mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d +emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc= +-----END CERTIFICATE----- \ No newline at end of file diff --git a/bitacross-worker/app-libs/oracle/src/certificates/open_meteo_root.pem b/bitacross-worker/app-libs/oracle/src/certificates/open_meteo_root.pem new file mode 100644 index 0000000000..b85c8037f6 --- /dev/null +++ b/bitacross-worker/app-libs/oracle/src/certificates/open_meteo_root.pem @@ -0,0 +1,31 @@ +-----BEGIN CERTIFICATE----- +MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw +TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh +cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4 +WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu +ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY +MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc +h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+ +0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U +A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW +T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH +B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC +B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv +KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn +OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn +jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw +qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI +rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV +HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq +hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL +ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ +3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK +NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5 +ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur +TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC +jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc +oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq +4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA +mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d +emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc= +-----END CERTIFICATE----- diff --git a/bitacross-worker/app-libs/oracle/src/error.rs b/bitacross-worker/app-libs/oracle/src/error.rs new file mode 100644 index 0000000000..df72280f34 --- /dev/null +++ b/bitacross-worker/app-libs/oracle/src/error.rs @@ -0,0 +1,39 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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(all(not(feature = "std"), feature = "sgx"))] +use crate::sgx_reexport_prelude::*; + +use crate::types::TradingPair; +use std::{boxed::Box, string::String}; + +/// Exchange rate error +#[derive(Debug, thiserror::Error)] +pub enum Error { + #[error("Rest client error")] + RestClient(#[from] itc_rest_client::error::Error), + #[error("Could not retrieve any data from {0} for {1}")] + NoValidData(String, String), + #[error("Value for exchange rate is null")] + EmptyExchangeRate(TradingPair), + #[error("Invalid id for crypto currency")] + InvalidCryptoCurrencyId, + #[error("Invalid id for fiat currency")] + InvalidFiatCurrencyId, + #[error(transparent)] + Other(#[from] Box), +} diff --git a/bitacross-worker/app-libs/oracle/src/lib.rs b/bitacross-worker/app-libs/oracle/src/lib.rs new file mode 100644 index 0000000000..6faee79a63 --- /dev/null +++ b/bitacross-worker/app-libs/oracle/src/lib.rs @@ -0,0 +1,84 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +#![cfg_attr(not(feature = "std"), no_std)] +#![cfg_attr(test, feature(assert_matches))] + +#[cfg(all(feature = "std", feature = "sgx"))] +compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the same time"); + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +#[macro_use] +extern crate sgx_tstd as std; + +// re-export module to properly feature gate sgx and regular std environment +#[cfg(all(not(feature = "std"), feature = "sgx"))] +pub mod sgx_reexport_prelude { + pub use thiserror_sgx as thiserror; + pub use url_sgx as url; +} + +use crate::{error::Error, metrics_exporter::MetricsExporter}; +use itp_ocall_api::EnclaveMetricsOCallApi; +use std::sync::Arc; + +pub mod error; +pub mod metrics_exporter; +pub mod traits; +pub mod types; + +pub mod oracles; +pub use oracles::{exchange_rate_oracle::ExchangeRateOracle, weather_oracle::WeatherOracle}; + +pub mod oracle_sources; +pub use oracle_sources::{ + coin_gecko::CoinGeckoSource, coin_market_cap::CoinMarketCapSource, + weather_oracle_source::WeatherOracleSource, +}; + +#[cfg(test)] +mod mock; + +#[cfg(test)] +mod test; + +pub type CoinGeckoExchangeRateOracle = + ExchangeRateOracle>; + +pub type CoinMarketCapExchangeRateOracle = + ExchangeRateOracle>; + +pub type OpenMeteoWeatherOracle = + WeatherOracle>; + +pub fn create_coin_gecko_oracle( + ocall_api: Arc, +) -> CoinGeckoExchangeRateOracle { + ExchangeRateOracle::new(CoinGeckoSource {}, Arc::new(MetricsExporter::new(ocall_api))) +} + +pub fn create_coin_market_cap_oracle( + ocall_api: Arc, +) -> CoinMarketCapExchangeRateOracle { + ExchangeRateOracle::new(CoinMarketCapSource {}, Arc::new(MetricsExporter::new(ocall_api))) +} + +pub fn create_open_meteo_weather_oracle( + ocall_api: Arc, +) -> OpenMeteoWeatherOracle { + WeatherOracle::new(WeatherOracleSource {}, Arc::new(MetricsExporter::new(ocall_api))) +} diff --git a/bitacross-worker/app-libs/oracle/src/metrics_exporter.rs b/bitacross-worker/app-libs/oracle/src/metrics_exporter.rs new file mode 100644 index 0000000000..aa10516fd1 --- /dev/null +++ b/bitacross-worker/app-libs/oracle/src/metrics_exporter.rs @@ -0,0 +1,104 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::types::{ExchangeRate, TradingPair}; +use itp_enclave_metrics::{EnclaveMetric, ExchangeRateOracleMetric, OracleMetric}; +use itp_ocall_api::EnclaveMetricsOCallApi; +use log::error; +use std::{string::String, sync::Arc, time::Instant}; + +/// Trait to export metrics for any Teeracle. +pub trait ExportMetrics { + fn increment_number_requests(&self, source: String); + + fn record_response_time(&self, source: String, timer: Instant); + + fn update_exchange_rate( + &self, + source: String, + exchange_rate: ExchangeRate, + trading_pair: TradingPair, + ); + + fn update_weather(&self, source: String, metrics_info: MetricsInfo); +} + +pub trait UpdateMetric { + fn update_metric(&self, metric: OracleMetric); +} + +/// Metrics exporter implementation. +pub struct MetricsExporter { + ocall_api: Arc, +} + +impl UpdateMetric for MetricsExporter +where + OCallApi: EnclaveMetricsOCallApi, +{ + fn update_metric(&self, _metric: OracleMetric) { + // TODO: Implement me + } +} + +impl MetricsExporter +where + OCallApi: EnclaveMetricsOCallApi, +{ + pub fn new(ocall_api: Arc) -> Self { + MetricsExporter { ocall_api } + } + + fn update_metric(&self, metric: ExchangeRateOracleMetric) { + if let Err(e) = self.ocall_api.update_metric(EnclaveMetric::ExchangeRateOracle(metric)) { + error!("Failed to update enclave metric, sgx_status_t: {}", e) + } + } +} + +impl ExportMetrics for MetricsExporter +where + OCallApi: EnclaveMetricsOCallApi, +{ + fn increment_number_requests(&self, source: String) { + self.update_metric(ExchangeRateOracleMetric::NumberRequestsIncrement(source)); + } + + fn record_response_time(&self, source: String, timer: Instant) { + self.update_metric(ExchangeRateOracleMetric::ResponseTime( + source, + timer.elapsed().as_millis(), + )); + } + + fn update_exchange_rate( + &self, + source: String, + exchange_rate: ExchangeRate, + trading_pair: TradingPair, + ) { + self.update_metric(ExchangeRateOracleMetric::ExchangeRate( + source, + trading_pair.key(), + exchange_rate, + )); + } + + fn update_weather(&self, _source: String, _metrics_info: MetricsInfo) { + // TODO: Implement me + } +} diff --git a/bitacross-worker/app-libs/oracle/src/mock.rs b/bitacross-worker/app-libs/oracle/src/mock.rs new file mode 100644 index 0000000000..f12224b0ea --- /dev/null +++ b/bitacross-worker/app-libs/oracle/src/mock.rs @@ -0,0 +1,120 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 = "sgx")] +use std::sync::SgxRwLock as RwLock; + +#[cfg(feature = "std")] +use std::sync::RwLock; + +use crate::{ + error::Error, + metrics_exporter::ExportMetrics, + traits::OracleSource, + types::{ExchangeRate, TradingPair}, +}; +use itc_rest_client::{ + http_client::{HttpClient, SendWithCertificateVerification}, + rest_client::RestClient, +}; +use std::{ + time::{Duration, Instant}, + vec, + vec::Vec, +}; +use url::Url; + +/// Mock metrics exporter. +#[derive(Default)] +pub(crate) struct MetricsExporterMock { + number_requests: RwLock, + response_times: RwLock>, + exchange_rates: RwLock>, +} + +impl MetricsExporterMock { + pub fn get_number_request(&self) -> u64 { + *self.number_requests.read().unwrap() + } + + pub fn get_response_times(&self) -> Vec { + self.response_times.read().unwrap().clone() + } + + pub fn get_exchange_rates(&self) -> Vec<(TradingPair, ExchangeRate)> { + self.exchange_rates.read().unwrap().clone() + } +} + +impl ExportMetrics for MetricsExporterMock { + fn increment_number_requests(&self, _source: String) { + (*self.number_requests.write().unwrap()) += 1; + } + + fn record_response_time(&self, _source: String, timer: Instant) { + self.response_times.write().unwrap().push(timer.elapsed().as_millis()); + } + + fn update_exchange_rate( + &self, + _source: String, + exchange_rate: ExchangeRate, + trading_pair: TradingPair, + ) { + self.exchange_rates.write().unwrap().push((trading_pair, exchange_rate)); + } + + fn update_weather(&self, _source: String, _metrics_info: MetricsInfo) {} +} + +/// Mock oracle source. +#[derive(Default)] +pub(crate) struct OracleSourceMock; + +impl OracleSource for OracleSourceMock { + type OracleRequestResult = Result; + + fn metrics_id(&self) -> String { + "source_mock".to_string() + } + + fn request_timeout(&self) -> Option { + None + } + + fn base_url(&self) -> Result { + Url::parse("https://mock.base.url").map_err(|e| Error::Other(format!("{:?}", e).into())) + } + + fn root_certificates_content(&self) -> Vec { + vec!["MOCK_CERTIFICATE".to_string()] + } + fn execute_exchange_rate_request( + &self, + _rest_client: &mut RestClient>, + _trading_pair: TradingPair, + ) -> Result { + Ok(ExchangeRate::from_num(42.3f32)) + } + + fn execute_request( + _rest_client: &mut RestClient>, + _source_info: OracleSourceInfo, + ) -> Self::OracleRequestResult { + Ok(42.3f32) + } +} diff --git a/bitacross-worker/app-libs/oracle/src/oracle_sources/coin_gecko.rs b/bitacross-worker/app-libs/oracle/src/oracle_sources/coin_gecko.rs new file mode 100644 index 0000000000..d9b8ad91ee --- /dev/null +++ b/bitacross-worker/app-libs/oracle/src/oracle_sources/coin_gecko.rs @@ -0,0 +1,220 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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(all(not(feature = "std"), feature = "sgx"))] +use crate::sgx_reexport_prelude::*; + +use crate::{ + error::Error, + traits::OracleSource, + types::{ExchangeRate, TradingInfo, TradingPair}, +}; +use itc_rest_client::{ + http_client::{HttpClient, SendWithCertificateVerification}, + rest_client::RestClient, + RestGet, RestPath, +}; +use lazy_static::lazy_static; +use log::{debug, error}; +use serde::{Deserialize, Serialize}; +use std::{ + collections::HashMap, + string::{String, ToString}, + time::Duration, + vec::Vec, +}; +use url::Url; + +const COINGECKO_URL: &str = "https://api.coingecko.com"; +const COINGECKO_PARAM_CURRENCY: &str = "vs_currency"; +const COINGECKO_PARAM_COIN: &str = "ids"; +const COINGECKO_PATH: &str = "api/v3/coins/markets"; +const COINGECKO_TIMEOUT: Duration = Duration::from_secs(20u64); +const COINGECKO_ROOT_CERTIFICATE_BALTIMORE: &str = + include_str!("../certificates/baltimore_cyber_trust_root_v3.pem"); +const COINGECKO_ROOT_CERTIFICATE_LETSENCRYPT: &str = + include_str!("../certificates/lets_encrypt_root_cert.pem"); + +lazy_static! { + static ref SYMBOL_ID_MAP: HashMap<&'static str, &'static str> = HashMap::from([ + ("DOT", "polkadot"), + ("TEER", "integritee"), + ("KSM", "kusama"), + ("BTC", "bitcoin"), + ]); +} + +/// CoinGecko oracle source. +#[derive(Default)] +pub struct CoinGeckoSource; + +impl CoinGeckoSource { + fn map_crypto_currency_id(trading_pair: &TradingPair) -> Result { + let key = &trading_pair.crypto_currency; + match SYMBOL_ID_MAP.get(key.as_str()) { + Some(v) => Ok(v.to_string()), + None => Err(Error::InvalidCryptoCurrencyId), + } + } +} + +impl> OracleSource for CoinGeckoSource { + type OracleRequestResult = Result<(), Error>; + + fn metrics_id(&self) -> String { + "coin_gecko".to_string() + } + + fn request_timeout(&self) -> Option { + Some(COINGECKO_TIMEOUT) + } + + fn base_url(&self) -> Result { + Url::parse(COINGECKO_URL).map_err(|e| Error::Other(format!("{:?}", e).into())) + } + + fn root_certificates_content(&self) -> Vec { + vec![ + COINGECKO_ROOT_CERTIFICATE_LETSENCRYPT.to_string(), + COINGECKO_ROOT_CERTIFICATE_BALTIMORE.to_string(), + ] + } + + fn execute_request( + _rest_client: &mut RestClient>, + source_info: OracleSourceInfo, + ) -> Self::OracleRequestResult { + let _trading_info: TradingInfo = source_info.into(); + // TODO Implement me + Ok(()) + } + + fn execute_exchange_rate_request( + &self, + rest_client: &mut RestClient>, + trading_pair: TradingPair, + ) -> Result { + let fiat_id = trading_pair.fiat_currency.clone(); + let crypto_id = Self::map_crypto_currency_id(&trading_pair)?; + + let response = rest_client.get_with::( + COINGECKO_PATH.to_string(), + &[(COINGECKO_PARAM_CURRENCY, &fiat_id), (COINGECKO_PARAM_COIN, &crypto_id)], + ); + + let response = match response { + Ok(response) => response, + Err(e) => { + error!("coingecko execute_exchange_rate_request() failed with: {:?}", &e); + return Err(Error::RestClient(e)) + }, + }; + + debug!("coingecko received response: {:?}", &response); + let list = response.0; + if list.is_empty() { + return Err(Error::NoValidData(COINGECKO_URL.to_string(), trading_pair.key())) + } + + match list[0].current_price { + Some(r) => Ok(ExchangeRate::from_num(r)), + None => Err(Error::EmptyExchangeRate(trading_pair)), + } + } +} + +#[derive(Serialize, Deserialize, Debug)] +struct CoinGeckoMarketStruct { + id: String, + symbol: String, + name: String, + current_price: Option, + last_updated: Option, +} + +#[derive(Serialize, Deserialize, Debug)] +struct CoinGeckoMarket(pub Vec); + +impl RestPath for CoinGeckoMarket { + fn get_path(path: String) -> Result { + Ok(path) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::{ + mock::MetricsExporterMock, + oracles::exchange_rate_oracle::{ExchangeRateOracle, GetExchangeRate}, + }; + use core::assert_matches::assert_matches; + use std::sync::Arc; + + type TestCoinGeckoClient = ExchangeRateOracle; + + fn get_coin_gecko_crypto_currency_id(crypto_currency: &str) -> Result { + let trading_pair = TradingPair { + crypto_currency: crypto_currency.to_string(), + fiat_currency: "USD".to_string(), + }; + CoinGeckoSource::map_crypto_currency_id(&trading_pair) + } + + #[test] + fn crypto_currency_id_works_for_dot() { + let coin_id = get_coin_gecko_crypto_currency_id("DOT").unwrap(); + assert_eq!(&coin_id, "polkadot"); + } + + #[test] + fn crypto_currency_id_works_for_teer() { + let coin_id = get_coin_gecko_crypto_currency_id("TEER").unwrap(); + assert_eq!(&coin_id, "integritee"); + } + + #[test] + fn crypto_currency_id_works_for_ksm() { + let coin_id = get_coin_gecko_crypto_currency_id("KSM").unwrap(); + assert_eq!(&coin_id, "kusama"); + } + + #[test] + fn crypto_currency_id_works_for_btc() { + let coin_id = get_coin_gecko_crypto_currency_id("BTC").unwrap(); + assert_eq!(&coin_id, "bitcoin"); + } + + #[test] + fn crypto_currency_id_fails_for_undefined_crypto_currency() { + let result = get_coin_gecko_crypto_currency_id("Undefined"); + assert_matches!(result, Err(Error::InvalidCryptoCurrencyId)); + } + + #[test] + fn get_exchange_rate_for_undefined_fiat_currency_fails() { + let coin_gecko_client = create_coin_gecko_client(); + let trading_pair = + TradingPair { crypto_currency: "DOT".to_string(), fiat_currency: "CH".to_string() }; + let result = coin_gecko_client.get_exchange_rate(trading_pair); + assert_matches!(result, Err(Error::RestClient(_))); + } + + fn create_coin_gecko_client() -> TestCoinGeckoClient { + TestCoinGeckoClient::new(CoinGeckoSource {}, Arc::new(MetricsExporterMock::default())) + } +} diff --git a/bitacross-worker/app-libs/oracle/src/oracle_sources/coin_market_cap.rs b/bitacross-worker/app-libs/oracle/src/oracle_sources/coin_market_cap.rs new file mode 100644 index 0000000000..a0e053b8e6 --- /dev/null +++ b/bitacross-worker/app-libs/oracle/src/oracle_sources/coin_market_cap.rs @@ -0,0 +1,242 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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(all(not(feature = "std"), feature = "sgx"))] +use crate::sgx_reexport_prelude::*; + +use crate::{ + error::Error, + traits::OracleSource, + types::{ExchangeRate, TradingInfo, TradingPair}, +}; +use itc_rest_client::{ + http_client::{HttpClient, SendWithCertificateVerification}, + rest_client::RestClient, + RestGet, RestPath, +}; +use lazy_static::lazy_static; +use serde::{Deserialize, Serialize}; +use std::{ + collections::{BTreeMap, HashMap}, + env, + string::{String, ToString}, + time::Duration, + vec::Vec, +}; +use url::Url; + +const COINMARKETCAP_URL: &str = "https://pro-api.coinmarketcap.com"; +const COINMARKETCAP_KEY_PARAM: &str = "CMC_PRO_API_KEY"; +const FIAT_CURRENCY_PARAM: &str = "convert_id"; +const CRYPTO_CURRENCY_PARAM: &str = "id"; +const COINMARKETCAP_PATH: &str = "v2/cryptocurrency/quotes/latest"; // API endpoint to get the exchange rate with a basic API plan (free) +const COINMARKETCAP_TIMEOUT: Duration = Duration::from_secs(3u64); +const COINMARKETCAP_ROOT_CERTIFICATE: &str = include_str!("../certificates/amazon_root_ca_a.pem"); + +lazy_static! { + static ref CRYPTO_SYMBOL_ID_MAP: HashMap<&'static str, &'static str> = + HashMap::from([("DOT", "6636"), ("TEER", "13323"), ("KSM", "5034"), ("BTC", "1"),]); + static ref COINMARKETCAP_KEY: String = env::var("COINMARKETCAP_KEY").unwrap_or_default(); +} + +lazy_static! { + static ref FIAT_SYMBOL_ID_MAP: HashMap<&'static str, &'static str> = + HashMap::from([("USD", "2781"), ("EUR", "2790"), ("CHF", "2785"), ("JPY", "2797"),]); +} + +#[derive(Default)] +pub struct CoinMarketCapSource; + +impl CoinMarketCapSource { + fn map_crypto_currency_id(trading_pair: &TradingPair) -> Result { + CRYPTO_SYMBOL_ID_MAP + .get(trading_pair.crypto_currency.as_str()) + .map(|v| v.to_string()) + .ok_or(Error::InvalidCryptoCurrencyId) + } + + fn map_fiat_currency_id(trading_pair: &TradingPair) -> Result { + FIAT_SYMBOL_ID_MAP + .get(trading_pair.fiat_currency.as_str()) + .map(|v| v.to_string()) + .ok_or(Error::InvalidFiatCurrencyId) + } +} + +impl> OracleSource for CoinMarketCapSource { + // TODO Change this to return something useful? + type OracleRequestResult = Result<(), Error>; + + fn metrics_id(&self) -> String { + "coin_market_cap".to_string() + } + + fn request_timeout(&self) -> Option { + Some(COINMARKETCAP_TIMEOUT) + } + + fn base_url(&self) -> Result { + Url::parse(COINMARKETCAP_URL).map_err(|e| Error::Other(format!("{:?}", e).into())) + } + + fn root_certificates_content(&self) -> Vec { + vec![COINMARKETCAP_ROOT_CERTIFICATE.to_string()] + } + + fn execute_request( + _rest_client: &mut RestClient>, + source_info: OracleSourceInfo, + ) -> Self::OracleRequestResult { + let trading_info: TradingInfo = source_info.into(); + let _fiat_currency = trading_info.trading_pair.fiat_currency; + let _crypto_currency = trading_info.trading_pair.crypto_currency; + // TODO Implement me + Ok(()) + } + + fn execute_exchange_rate_request( + &self, + rest_client: &mut RestClient>, + trading_pair: TradingPair, + ) -> Result { + let fiat_id = Self::map_fiat_currency_id(&trading_pair)?; + let crypto_id = Self::map_crypto_currency_id(&trading_pair)?; + + let response = rest_client + .get_with::( + COINMARKETCAP_PATH.to_string(), + &[ + (FIAT_CURRENCY_PARAM, &fiat_id), + (CRYPTO_CURRENCY_PARAM, &crypto_id), + (COINMARKETCAP_KEY_PARAM, &COINMARKETCAP_KEY), + ], + ) + .map_err(Error::RestClient)?; + + let data_struct = response.0; + + let data = match data_struct.data.get(&crypto_id) { + Some(d) => d, + None => + return Err(Error::NoValidData( + COINMARKETCAP_URL.to_string(), + trading_pair.crypto_currency, + )), + }; + + let quote = match data.quote.get(&fiat_id) { + Some(q) => q, + None => + return Err(Error::NoValidData(COINMARKETCAP_URL.to_string(), trading_pair.key())), + }; + match quote.price { + Some(r) => Ok(ExchangeRate::from_num(r)), + None => Err(Error::EmptyExchangeRate(trading_pair)), + } + } +} + +#[derive(Serialize, Deserialize, Debug)] +struct DataStruct { + id: Option, + name: String, + symbol: String, + quote: BTreeMap, +} + +#[derive(Serialize, Deserialize, Debug)] +struct QuoteStruct { + price: Option, + last_updated: Option, +} + +#[derive(Serialize, Deserialize, Debug)] +struct CoinMarketCapMarketStruct { + data: BTreeMap, +} + +#[derive(Serialize, Deserialize, Debug)] +struct CoinMarketCapMarket(pub CoinMarketCapMarketStruct); + +impl RestPath for CoinMarketCapMarket { + fn get_path(path: String) -> Result { + Ok(path) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::{ + mock::MetricsExporterMock, + oracles::exchange_rate_oracle::{ExchangeRateOracle, GetExchangeRate}, + }; + use core::assert_matches::assert_matches; + use std::sync::Arc; + + type TestClient = ExchangeRateOracle; + + fn get_coin_market_cap_crypto_currency_id(crypto_currency: &str) -> Result { + let trading_pair = TradingPair { + crypto_currency: crypto_currency.to_string(), + fiat_currency: "USD".to_string(), + }; + CoinMarketCapSource::map_crypto_currency_id(&trading_pair) + } + + #[test] + fn crypto_currency_id_works_for_dot() { + let coin_id = get_coin_market_cap_crypto_currency_id("DOT").unwrap(); + assert_eq!(&coin_id, "6636"); + } + + #[test] + fn crypto_currency_id_works_for_teer() { + let coin_id = get_coin_market_cap_crypto_currency_id("TEER").unwrap(); + assert_eq!(&coin_id, "13323"); + } + + #[test] + fn crypto_currency_id_works_for_ksm() { + let coin_id = get_coin_market_cap_crypto_currency_id("KSM").unwrap(); + assert_eq!(&coin_id, "5034"); + } + + #[test] + fn crypto_currency_id_works_for_btc() { + let coin_id = get_coin_market_cap_crypto_currency_id("BTC").unwrap(); + assert_eq!(&coin_id, "1"); + } + + #[test] + fn crypto_currency_id_fails_for_undefined_crypto_currency() { + let coin_id = get_coin_market_cap_crypto_currency_id("Undefined"); + assert_matches!(coin_id, Err(Error::InvalidCryptoCurrencyId)); + } + + #[test] + fn get_exchange_rate_for_undefined_fiat_currency_fails() { + let coin_market_cap_client = create_client(); + let trading_pair = + TradingPair { crypto_currency: "DOT".to_string(), fiat_currency: "CH".to_string() }; + let result = coin_market_cap_client.get_exchange_rate(trading_pair); + assert_matches!(result, Err(Error::InvalidFiatCurrencyId)); + } + + fn create_client() -> TestClient { + TestClient::new(CoinMarketCapSource {}, Arc::new(MetricsExporterMock::default())) + } +} diff --git a/bitacross-worker/app-libs/oracle/src/oracle_sources/mod.rs b/bitacross-worker/app-libs/oracle/src/oracle_sources/mod.rs new file mode 100644 index 0000000000..d2d88153c3 --- /dev/null +++ b/bitacross-worker/app-libs/oracle/src/oracle_sources/mod.rs @@ -0,0 +1,19 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 coin_gecko; +pub mod coin_market_cap; +pub mod weather_oracle_source; diff --git a/bitacross-worker/app-libs/oracle/src/oracle_sources/weather_oracle_source.rs b/bitacross-worker/app-libs/oracle/src/oracle_sources/weather_oracle_source.rs new file mode 100644 index 0000000000..9f199be5dc --- /dev/null +++ b/bitacross-worker/app-libs/oracle/src/oracle_sources/weather_oracle_source.rs @@ -0,0 +1,120 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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(all(not(feature = "std"), feature = "sgx"))] +use crate::sgx_reexport_prelude::*; + +use crate::{ + error::Error, + traits::OracleSource, + types::{ExchangeRate, TradingPair, WeatherInfo}, +}; +use itc_rest_client::{ + http_client::{HttpClient, SendWithCertificateVerification}, + rest_client::RestClient, + RestGet, RestPath, +}; +use serde::{Deserialize, Serialize}; +use std::{ + string::{String, ToString}, + time::Duration, + vec::Vec, +}; +use url::Url; + +const WEATHER_URL: &str = "https://api.open-meteo.com"; +const WEATHER_PARAM_LONGITUDE: &str = "longitude"; +const WEATHER_PARAM_LATITUDE: &str = "latitude"; +// const WEATHER_PARAM_HOURLY: &str = "hourly"; // TODO: Add to Query +const WEATHER_PATH: &str = "v1/forecast"; +const WEATHER_TIMEOUT: Duration = Duration::from_secs(3u64); +const WEATHER_ROOT_CERTIFICATE: &str = include_str!("../certificates/open_meteo_root.pem"); + +// TODO: Change f32 types to appropriate Substrate Fixed Type +#[derive(Default)] +pub struct WeatherOracleSource; + +impl> OracleSource for WeatherOracleSource { + type OracleRequestResult = Result; // TODO: Change from f32 type + + fn metrics_id(&self) -> String { + "weather".to_string() + } + + fn request_timeout(&self) -> Option { + Some(WEATHER_TIMEOUT) + } + + fn base_url(&self) -> Result { + Url::parse(WEATHER_URL).map_err(|e| Error::Other(format!("{:?}", e).into())) + } + + /// The server's root certificate. A valid certificate is required to open a tls connection + fn root_certificates_content(&self) -> Vec { + vec![WEATHER_ROOT_CERTIFICATE.to_string()] + } + + fn execute_exchange_rate_request( + &self, + _rest_client: &mut RestClient>, + _trading_pair: TradingPair, + ) -> Result { + Err(Error::NoValidData("None".into(), "None".into())) + } + + // TODO: Make this take a variant perhaps or a Closure so that it is more generic + fn execute_request( + rest_client: &mut RestClient>, + source_info: OracleSourceInfo, + ) -> Self::OracleRequestResult { + let weather_info: WeatherInfo = source_info.into(); + let query = weather_info.weather_query; + + // TODO: + // This part is opinionated towards a hard coded query need to make more generic + let response = rest_client + .get_with::( + WEATHER_PATH.into(), + &[ + (WEATHER_PARAM_LATITUDE, &query.latitude), + (WEATHER_PARAM_LONGITUDE, &query.longitude), + //(WEATHER_PARAM_HOURLY), &query.hourly), + ], + ) + .map_err(Error::RestClient)?; + + let open_meteo_weather_struct = response.0; + + Ok(open_meteo_weather_struct.longitude) + } +} + +#[derive(Serialize, Deserialize, Debug)] +struct OpenMeteoWeatherStruct { + latitude: f32, + longitude: f32, + //hourly: String, +} + +#[derive(Serialize, Deserialize, Debug)] +struct OpenMeteo(pub OpenMeteoWeatherStruct); + +impl RestPath for OpenMeteo { + fn get_path(path: String) -> Result { + Ok(path) + } +} diff --git a/bitacross-worker/app-libs/oracle/src/oracles/exchange_rate_oracle.rs b/bitacross-worker/app-libs/oracle/src/oracles/exchange_rate_oracle.rs new file mode 100644 index 0000000000..0198a5fe1b --- /dev/null +++ b/bitacross-worker/app-libs/oracle/src/oracles/exchange_rate_oracle.rs @@ -0,0 +1,154 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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(all(not(feature = "std"), feature = "sgx"))] +use crate::sgx_reexport_prelude::*; + +use crate::{ + metrics_exporter::ExportMetrics, + traits::OracleSource, + types::{ExchangeRate, TradingInfo, TradingPair}, + Error, +}; +use itc_rest_client::{ + http_client::{HttpClient, SendWithCertificateVerification}, + rest_client::RestClient, +}; +use log::*; +use std::{ + sync::Arc, + thread, + time::{Duration, Instant}, +}; +use url::Url; + +#[allow(unused)] +pub struct ExchangeRateOracle { + oracle_source: OracleSourceType, + metrics_exporter: Arc, +} + +impl ExchangeRateOracle { + pub fn new(oracle_source: OracleSourceType, metrics_exporter: Arc) -> Self { + ExchangeRateOracle { oracle_source, metrics_exporter } + } +} + +pub trait GetExchangeRate { + /// Get the cryptocurrency/fiat_currency exchange rate + fn get_exchange_rate(&self, trading_pair: TradingPair) -> Result<(ExchangeRate, Url), Error>; +} + +impl GetExchangeRate + for ExchangeRateOracle +where + OracleSourceType: OracleSource, + MetricsExporter: ExportMetrics, +{ + fn get_exchange_rate(&self, trading_pair: TradingPair) -> Result<(ExchangeRate, Url), Error> { + let source_id = self.oracle_source.metrics_id(); + self.metrics_exporter.increment_number_requests(source_id.clone()); + + let base_url = self.oracle_source.base_url()?; + let root_certificates = self.oracle_source.root_certificates_content(); + let request_timeout = self.oracle_source.request_timeout(); + + debug!("Get exchange rate from URI: {}, trading pair: {:?}", base_url, trading_pair); + + let http_client = HttpClient::new( + SendWithCertificateVerification::new(root_certificates), + true, + request_timeout, + None, + None, + ); + let mut rest_client = RestClient::new(http_client, base_url.clone()); + + // Due to possible failures that may be temporarily this function tries to fetch the exchange rates `number_of_tries` times. + // If it still fails for the last attempt, then only in that case will it be considered a non-recoverable error. + let number_of_tries = 3; + let timer_start = Instant::now(); + + let mut tries = 0; + let result = loop { + tries += 1; + let exchange_result = self + .oracle_source + .execute_exchange_rate_request(&mut rest_client, trading_pair.clone()); + + match exchange_result { + Ok(exchange_rate) => { + self.metrics_exporter.record_response_time(source_id.clone(), timer_start); + self.metrics_exporter.update_exchange_rate( + source_id, + exchange_rate, + trading_pair, + ); + + debug!("Successfully executed exchange rate request"); + break Ok((exchange_rate, base_url)) + }, + Err(e) => + if tries < number_of_tries { + error!( + "Getting exchange rate from {} failed with {}, trying again in {:?}.", + &base_url, e, request_timeout + ); + debug!("Check that the API endpoint is available, for coingecko: https://status.coingecko.com/"); + thread::sleep( + request_timeout.unwrap_or_else(|| Duration::from_secs(number_of_tries)), + ); + } else { + error!( + "Getting exchange rate from {} failed {} times, latest error is: {}.", + &base_url, number_of_tries, &e + ); + break Err(e) + }, + } + }; + result + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::mock::{MetricsExporterMock, OracleSourceMock}; + + type TestOracle = ExchangeRateOracle; + + #[test] + fn get_exchange_rate_updates_metrics() { + let metrics_exporter = Arc::new(MetricsExporterMock::default()); + let test_client = TestOracle::new(OracleSourceMock {}, metrics_exporter.clone()); + + let trading_pair = + TradingPair { crypto_currency: "BTC".to_string(), fiat_currency: "USD".to_string() }; + let _bit_usd = test_client.get_exchange_rate(trading_pair.clone()).unwrap(); + + assert_eq!(1, metrics_exporter.get_number_request()); + assert_eq!(1, metrics_exporter.get_response_times().len()); + assert_eq!(1, metrics_exporter.get_exchange_rates().len()); + + let (metric_trading_pair, exchange_rate) = + metrics_exporter.get_exchange_rates().first().unwrap().clone(); + + assert_eq!(trading_pair, metric_trading_pair); + assert_eq!(ExchangeRate::from_num(42.3f32), exchange_rate); + } +} diff --git a/bitacross-worker/app-libs/oracle/src/oracles/mod.rs b/bitacross-worker/app-libs/oracle/src/oracles/mod.rs new file mode 100644 index 0000000000..d6100d2469 --- /dev/null +++ b/bitacross-worker/app-libs/oracle/src/oracles/mod.rs @@ -0,0 +1,18 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 exchange_rate_oracle; +pub mod weather_oracle; diff --git a/bitacross-worker/app-libs/oracle/src/oracles/weather_oracle.rs b/bitacross-worker/app-libs/oracle/src/oracles/weather_oracle.rs new file mode 100644 index 0000000000..66809f7f3a --- /dev/null +++ b/bitacross-worker/app-libs/oracle/src/oracles/weather_oracle.rs @@ -0,0 +1,83 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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(all(not(feature = "std"), feature = "sgx"))] +use crate::sgx_reexport_prelude::*; + +use crate::{metrics_exporter::ExportMetrics, traits::OracleSource, types::WeatherInfo, Error}; +use itc_rest_client::{ + http_client::{HttpClient, SendWithCertificateVerification}, + rest_client::RestClient, +}; +use log::*; +use std::sync::Arc; +use url::Url; + +#[allow(unused)] +pub struct WeatherOracle { + oracle_source: OracleSourceType, + metrics_exporter: Arc, +} + +impl WeatherOracle +where + OracleSourceType: OracleSource, +{ + pub fn new(oracle_source: OracleSourceType, metrics_exporter: Arc) -> Self { + WeatherOracle { oracle_source, metrics_exporter } + } + + pub fn get_base_url(&self) -> Result { + self.oracle_source.base_url() + } +} + +pub trait GetLongitude { + type LongitudeResult; + fn get_longitude(&self, weather_info: WeatherInfo) -> Self::LongitudeResult; +} + +impl GetLongitude + for WeatherOracle +where + OracleSourceType: OracleSource>, + MetricsExporter: ExportMetrics, +{ + type LongitudeResult = Result; + + fn get_longitude(&self, weather_info: WeatherInfo) -> Self::LongitudeResult { + let query = weather_info.weather_query.clone(); + + let base_url = self.oracle_source.base_url()?; + let root_certificates = self.oracle_source.root_certificates_content(); + + debug!("Get longitude from URI: {}, query: {:?}", base_url, query); + + let http_client = HttpClient::new( + SendWithCertificateVerification::new(root_certificates), + true, + self.oracle_source.request_timeout(), + None, + None, + ); + let mut rest_client = RestClient::new(http_client, base_url); + >::execute_request( + &mut rest_client, + weather_info, + ) + } +} diff --git a/bitacross-worker/app-libs/oracle/src/test.rs b/bitacross-worker/app-libs/oracle/src/test.rs new file mode 100644 index 0000000000..8d083a18a0 --- /dev/null +++ b/bitacross-worker/app-libs/oracle/src/test.rs @@ -0,0 +1,125 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 concrete exchange rate oracle implementations. +//! Uses real HTTP requests, so the sites must be available for these tests. + +use crate::{ + error::Error, + mock::MetricsExporterMock, + oracle_sources::{ + coin_gecko::CoinGeckoSource, coin_market_cap::CoinMarketCapSource, + weather_oracle_source::WeatherOracleSource, + }, + oracles::{ + exchange_rate_oracle::{ExchangeRateOracle, GetExchangeRate}, + weather_oracle::{GetLongitude, WeatherOracle}, + }, + traits::OracleSource, + types::{TradingInfo, TradingPair, WeatherInfo, WeatherQuery}, +}; +use core::assert_matches::assert_matches; +use std::sync::Arc; +use substrate_fixed::transcendental::ZERO; + +type TestOracle = ExchangeRateOracle; +type TestWeatherOracle = WeatherOracle; + +#[test] +#[ignore = "requires API key for CoinMarketCap"] +fn get_exchange_rate_from_coin_market_cap_works() { + test_suite_exchange_rates::(); +} + +#[test] +#[ignore = "requires external coin gecko service, disabled temporarily"] +fn get_exchange_rate_from_coin_gecko_works() { + test_suite_exchange_rates::(); +} + +#[test] +fn get_longitude_from_open_meteo_works() { + let oracle = create_weather_oracle::(); + let weather_query = + WeatherQuery { latitude: "52.52".into(), longitude: "13.41".into(), hourly: "none".into() }; + // Todo: hourly param is temperature_2m to get temp or relativehumidity_2m to get humidity + let weather_info = WeatherInfo { weather_query }; + let expected_longitude = 13.41f32; + let response_longitude = + oracle.get_longitude(weather_info).expect("Can grab longitude from oracle"); + assert!((response_longitude - expected_longitude) < 0.5); +} + +#[test] +fn get_exchange_rate_for_undefined_coin_market_cap_crypto_currency_fails() { + get_exchange_rate_for_undefined_crypto_currency_fails::(); +} + +#[test] +fn get_exchange_rate_for_undefined_coin_gecko_crypto_currency_fails() { + get_exchange_rate_for_undefined_crypto_currency_fails::(); +} + +fn create_weather_oracle>( +) -> TestWeatherOracle { + let oracle_source = OracleSourceType::default(); + WeatherOracle::new(oracle_source, Arc::new(MetricsExporterMock::default())) +} + +fn create_exchange_rate_oracle>( +) -> TestOracle { + let oracle_source = OracleSourceType::default(); + ExchangeRateOracle::new(oracle_source, Arc::new(MetricsExporterMock::default())) +} + +fn get_exchange_rate_for_undefined_crypto_currency_fails< + OracleSourceType: OracleSource, +>() { + let oracle = create_exchange_rate_oracle::(); + let trading_pair = TradingPair { + crypto_currency: "invalid_coin".to_string(), + fiat_currency: "USD".to_string(), + }; + let result = oracle.get_exchange_rate(trading_pair); + assert_matches!(result, Err(Error::InvalidCryptoCurrencyId)); +} + +fn test_suite_exchange_rates>() { + let oracle = create_exchange_rate_oracle::(); + let dot_to_usd = + TradingPair { crypto_currency: "DOT".to_string(), fiat_currency: "USD".to_string() }; + let dot_usd = oracle.get_exchange_rate(dot_to_usd).unwrap().0; + assert!(dot_usd > 0f32); + let btc_to_usd = + TradingPair { crypto_currency: "BTC".to_string(), fiat_currency: "USD".to_string() }; + let bit_usd = oracle.get_exchange_rate(btc_to_usd).unwrap().0; + assert!(bit_usd > 0f32); + let dot_to_chf = + TradingPair { crypto_currency: "DOT".to_string(), fiat_currency: "CHF".to_string() }; + let dot_chf = oracle.get_exchange_rate(dot_to_chf).unwrap().0; + assert!(dot_chf > 0f32); + let bit_to_chf = + TradingPair { crypto_currency: "BTC".to_string(), fiat_currency: "CHF".to_string() }; + let bit_chf = oracle.get_exchange_rate(bit_to_chf).unwrap().0; + + // Ensure that get_exchange_rate returns a positive rate + assert!(dot_usd > ZERO); + + // Ensure that get_exchange_rate returns a valid value by checking + // that the values obtained for DOT/BIT from different exchange rates are the same + assert_eq!((dot_usd / bit_usd).round(), (dot_chf / bit_chf).round()); +} diff --git a/bitacross-worker/app-libs/oracle/src/traits.rs b/bitacross-worker/app-libs/oracle/src/traits.rs new file mode 100644 index 0000000000..1ca1d21428 --- /dev/null +++ b/bitacross-worker/app-libs/oracle/src/traits.rs @@ -0,0 +1,55 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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(all(not(feature = "std"), feature = "sgx"))] +use crate::sgx_reexport_prelude::*; + +use crate::{ + types::{ExchangeRate, TradingPair}, + Error, +}; +use core::time::Duration; +use itc_rest_client::{ + http_client::{HttpClient, SendWithCertificateVerification}, + rest_client::RestClient, +}; +use std::{string::String, vec::Vec}; +use url::Url; + +pub trait OracleSource: Default { + type OracleRequestResult; + + fn metrics_id(&self) -> String; + + fn request_timeout(&self) -> Option; + + fn base_url(&self) -> Result; + + /// The server's root certificate(s). A valid certificate is required to open a tls connection + fn root_certificates_content(&self) -> Vec; + + fn execute_exchange_rate_request( + &self, + rest_client: &mut RestClient>, + trading_pair: TradingPair, + ) -> Result; + + fn execute_request( + rest_client: &mut RestClient>, + source_info: OracleSourceInfo, + ) -> Self::OracleRequestResult; +} diff --git a/bitacross-worker/app-libs/oracle/src/types.rs b/bitacross-worker/app-libs/oracle/src/types.rs new file mode 100644 index 0000000000..ef969ccb90 --- /dev/null +++ b/bitacross-worker/app-libs/oracle/src/types.rs @@ -0,0 +1,61 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 std::string::String; +use substrate_fixed::types::U32F32; + +#[derive(Debug, Clone, Encode, Decode, Eq, PartialEq)] +pub struct WeatherInfo { + pub weather_query: WeatherQuery, +} + +#[derive(Debug, Clone, Encode, Decode, Eq, PartialEq)] +pub struct WeatherQuery { + pub longitude: String, + pub latitude: String, + pub hourly: String, +} + +impl WeatherQuery { + pub fn key(self) -> String { + format!("{}/{}", self.latitude, self.longitude) + } +} + +#[derive(Debug, Clone, Encode, Decode, Eq, PartialEq)] +pub struct TradingInfo { + pub trading_pair: TradingPair, + pub exchange_rate: ExchangeRate, +} +/// Market identifier for order +#[derive(Debug, Clone, Encode, Decode, Eq, PartialEq)] +pub struct TradingPair { + pub crypto_currency: String, + pub fiat_currency: String, +} + +impl TradingPair { + pub fn key(self) -> String { + format!("{}/{}", self.crypto_currency, self.fiat_currency) + } +} + +/// TODO Fix https://github.com/integritee-network/pallets/issues/71 and get it from https://github.com/integritee-network/pallets.git +/// Teeracle types +pub type ExchangeRate = U32F32; +// pub type Coordinate = U32F32; diff --git a/bitacross-worker/app-libs/parentchain-interface/Cargo.toml b/bitacross-worker/app-libs/parentchain-interface/Cargo.toml new file mode 100644 index 0000000000..39e4827588 --- /dev/null +++ b/bitacross-worker/app-libs/parentchain-interface/Cargo.toml @@ -0,0 +1,79 @@ +[package] +name = "ita-parentchain-interface" +version = "0.9.0" +authors = ["Integritee AG "] +edition = "2021" + +[dependencies] +# sgx dependencies +sgx_tstd = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git", optional = true } + +# local dependencies +ita-sgx-runtime = { path = "../sgx-runtime", default-features = false } +ita-stf = { path = "../stf", default-features = false } +itc-parentchain-indirect-calls-executor = { path = "../../core/parentchain/indirect-calls-executor", default-features = false } +itp-api-client-types = { path = "../../core-primitives/node-api/api-client-types", default-features = false } +itp-node-api = { path = "../../core-primitives/node-api", default-features = false } +itp-stf-primitives = { path = "../../core-primitives/stf-primitives", default-features = false } +itp-types = { path = "../../core-primitives/types", default-features = false } +itp-utils = { path = "../../core-primitives/utils", default-features = false } + +# no-std compatible libraries +bs58 = { version = "0.4.0", default-features = false, features = ["alloc"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +log = { version = "0.4", default-features = false } + +# substrate dep +sp-core = { default-features = false, features = ["full_crypto"], git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } +sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } + +# litentry +lc-scheduled-enclave = { path = "../../litentry/core/scheduled-enclave", default-features = false, optional = true } +litentry-primitives = { path = "../../litentry/primitives", default-features = false } +sp-std = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } + +[dev-dependencies] +env_logger = "0.9.0" +itp-node-api = { path = "../../core-primitives/node-api", features = ["mocks"] } +itp-sgx-crypto = { path = "../../core-primitives/sgx/crypto", features = ["mocks"] } +itp-stf-executor = { path = "../../core-primitives/stf-executor", features = ["mocks"] } +itp-test = { path = "../../core-primitives/test" } +itp-top-pool-author = { path = "../../core-primitives/top-pool-author", features = ["mocks"] } +itc-parentchain-test = { path = "../../core/parentchain/test" } + + +[features] +default = ["std"] +std = [ + "bs58/std", + "codec/std", + "ita-sgx-runtime/std", + "ita-stf/std", + "itc-parentchain-indirect-calls-executor/std", + "itp-api-client-types/std", + "itp-node-api/std", + "itp-sgx-crypto/std", + "itp-stf-executor/std", + "itp-stf-primitives/std", + "itp-top-pool-author/std", + "itp-types/std", + "itp-utils/std", + "log/std", + #substrate + "sp-core/std", + "sp-runtime/std", + "litentry-primitives/std", + "lc-scheduled-enclave/std", + "sp-std/std", +] +sgx = [ + "sgx_tstd", + "ita-stf/sgx", + "itc-parentchain-indirect-calls-executor/sgx", + "itp-node-api/sgx", + "itp-sgx-crypto/sgx", + "itp-stf-executor/sgx", + "itp-top-pool-author/sgx", + "litentry-primitives/sgx", + "lc-scheduled-enclave/sgx", +] diff --git a/bitacross-worker/app-libs/parentchain-interface/src/indirect_calls/invoke.rs b/bitacross-worker/app-libs/parentchain-interface/src/indirect_calls/invoke.rs new file mode 100644 index 0000000000..af3bb0c088 --- /dev/null +++ b/bitacross-worker/app-libs/parentchain-interface/src/indirect_calls/invoke.rs @@ -0,0 +1,41 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 ita_stf::TrustedCallSigned; +use itc_parentchain_indirect_calls_executor::{ + error::{Error, Result}, + IndirectDispatch, +}; +use itp_stf_primitives::traits::IndirectExecutor; +use itp_types::{DecryptableRequest, RsaRequest}; + +#[derive(Debug, Clone, Encode, Decode, Eq, PartialEq)] +pub struct InvokeArgs { + request: RsaRequest, +} + +impl> + IndirectDispatch for InvokeArgs +{ + type Args = (); + fn dispatch(&self, executor: &Executor, _args: Self::Args) -> Result<()> { + log::debug!("Found trusted call extrinsic, submitting it to the top pool"); + executor.submit_trusted_call(self.request.shard(), self.request.payload().to_vec()); + Ok(()) + } +} diff --git a/bitacross-worker/app-libs/parentchain-interface/src/indirect_calls/litentry/args_executor.rs b/bitacross-worker/app-libs/parentchain-interface/src/indirect_calls/litentry/args_executor.rs new file mode 100644 index 0000000000..05084bfee0 --- /dev/null +++ b/bitacross-worker/app-libs/parentchain-interface/src/indirect_calls/litentry/args_executor.rs @@ -0,0 +1,62 @@ +// Copyright 2020-2023 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . + +use codec::Encode; +use ita_stf::{Getter, TrustedCall, TrustedCallSigned, TrustedOperation}; +use itc_parentchain_indirect_calls_executor::error::{Error, Result}; +use itp_stf_primitives::traits::IndirectExecutor; +use itp_types::{ShardIdentifier, H256}; +use sp_core::crypto::AccountId32; +use sp_runtime::MultiAddress; + +pub trait ArgsExecutor { + fn error(&self) -> Error; + fn name() -> &'static str; + fn shard(&self) -> ShardIdentifier; + fn prepare_trusted_call>( + &self, + executor: &Executor, + address: MultiAddress, + hash: H256, + ) -> Result; + fn execute>( + &self, + executor: &Executor, + address: Option>, + hash: H256, + ) -> Result<()> { + if let Some(address) = address { + self.submit(executor, address, hash)? + } + Ok(()) + } + + fn submit>( + &self, + executor: &Executor, + address: MultiAddress, + hash: H256, + ) -> Result<()> { + let trusted_call = self.prepare_trusted_call(executor, address, hash)?; + let signed_trusted_call = executor.sign_call_with_self(&trusted_call, &self.shard())?; + let trusted_operation = + TrustedOperation::::indirect_call(signed_trusted_call); + + let encrypted_trusted_call = executor.encrypt(&trusted_operation.encode())?; + executor.submit_trusted_call(self.shard(), encrypted_trusted_call); + Ok(()) + } +} diff --git a/bitacross-worker/app-libs/parentchain-interface/src/indirect_calls/litentry/mod.rs b/bitacross-worker/app-libs/parentchain-interface/src/indirect_calls/litentry/mod.rs new file mode 100644 index 0000000000..830f452476 --- /dev/null +++ b/bitacross-worker/app-libs/parentchain-interface/src/indirect_calls/litentry/mod.rs @@ -0,0 +1,18 @@ +// Copyright 2020-2023 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . + +mod args_executor; +pub mod scheduled_enclave; diff --git a/bitacross-worker/app-libs/parentchain-interface/src/indirect_calls/litentry/scheduled_enclave.rs b/bitacross-worker/app-libs/parentchain-interface/src/indirect_calls/litentry/scheduled_enclave.rs new file mode 100644 index 0000000000..a0d1ff65bc --- /dev/null +++ b/bitacross-worker/app-libs/parentchain-interface/src/indirect_calls/litentry/scheduled_enclave.rs @@ -0,0 +1,62 @@ +// Copyright 2020-2023 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . + +use codec::{Decode, Encode}; +use ita_stf::TrustedCallSigned; +use itc_parentchain_indirect_calls_executor::{ + error::{Error, Result}, + IndirectDispatch, +}; +use itp_stf_primitives::traits::IndirectExecutor; +use itp_types::{MrEnclave, SidechainBlockNumber}; +use lc_scheduled_enclave::{ScheduledEnclaveUpdater, GLOBAL_SCHEDULED_ENCLAVE}; +use log::debug; + +#[derive(Debug, Clone, Encode, Decode, Eq, PartialEq)] +pub struct UpdateScheduledEnclaveArgs { + sbn: codec::Compact, + mrenclave: MrEnclave, +} + +impl> + IndirectDispatch for UpdateScheduledEnclaveArgs +{ + type Args = (); + fn dispatch(&self, _executor: &Executor, _args: Self::Args) -> Result<()> { + debug!("execute indirect call: UpdateScheduledEnclave, sidechain_block_number: {:?}, mrenclave: {:?}", self.sbn, self.mrenclave); + GLOBAL_SCHEDULED_ENCLAVE.update(self.sbn.into(), self.mrenclave)?; + Ok(()) + } +} + +#[derive(Debug, Clone, Encode, Decode, Eq, PartialEq)] +pub struct RemoveScheduledEnclaveArgs { + sbn: codec::Compact, +} + +impl> + IndirectDispatch for RemoveScheduledEnclaveArgs +{ + type Args = (); + fn dispatch(&self, _executor: &Executor, _args: Self::Args) -> Result<()> { + debug!( + "execute indirect call: RemoveScheduledEnclave, sidechain_block_number: {:?}", + self.sbn + ); + GLOBAL_SCHEDULED_ENCLAVE.remove(self.sbn.into())?; + Ok(()) + } +} diff --git a/bitacross-worker/app-libs/parentchain-interface/src/indirect_calls/mod.rs b/bitacross-worker/app-libs/parentchain-interface/src/indirect_calls/mod.rs new file mode 100644 index 0000000000..88fe8aab4d --- /dev/null +++ b/bitacross-worker/app-libs/parentchain-interface/src/indirect_calls/mod.rs @@ -0,0 +1,26 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 invoke; +mod litentry; +pub mod shield_funds; +pub mod transfer_to_alice_shields_funds; + +pub use invoke::InvokeArgs; +pub use litentry::scheduled_enclave::{RemoveScheduledEnclaveArgs, UpdateScheduledEnclaveArgs}; +pub use shield_funds::ShieldFundsArgs; +pub use transfer_to_alice_shields_funds::{TransferToAliceShieldsFundsArgs, ALICE_ACCOUNT_ID}; diff --git a/bitacross-worker/app-libs/parentchain-interface/src/indirect_calls/shield_funds.rs b/bitacross-worker/app-libs/parentchain-interface/src/indirect_calls/shield_funds.rs new file mode 100644 index 0000000000..0204c0b80b --- /dev/null +++ b/bitacross-worker/app-libs/parentchain-interface/src/indirect_calls/shield_funds.rs @@ -0,0 +1,62 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 ita_stf::{Getter, TrustedCall, TrustedCallSigned}; +use itc_parentchain_indirect_calls_executor::{ + error::{Error, Result}, + IndirectDispatch, +}; +use itp_stf_primitives::{ + traits::IndirectExecutor, + types::{AccountId, TrustedOperation}, +}; +use itp_types::{Balance, ShardIdentifier}; +use log::{debug, info}; +use std::vec::Vec; +/// Arguments of the Integritee-Parachain's shield fund dispatchable. +#[derive(Debug, Clone, Encode, Decode, Eq, PartialEq)] +pub struct ShieldFundsArgs { + account_encrypted: Vec, + amount: Balance, + shard: ShardIdentifier, +} + +impl> + IndirectDispatch for ShieldFundsArgs +{ + type Args = (); + fn dispatch(&self, executor: &Executor, _args: Self::Args) -> Result<()> { + info!("Found ShieldFunds extrinsic in block: \nAccount Encrypted {:?} \nAmount: {} \nShard: {}", + self.account_encrypted, self.amount, bs58::encode(self.shard.encode()).into_string()); + + debug!("decrypt the account id"); + let account_vec = executor.decrypt(&self.account_encrypted)?; + let account = AccountId::decode(&mut account_vec.as_slice())?; + + let enclave_account_id = executor.get_enclave_account()?; + let trusted_call = + TrustedCall::balance_shield(enclave_account_id.into(), account, self.amount); + let signed_trusted_call = executor.sign_call_with_self(&trusted_call, &self.shard)?; + let trusted_operation = + TrustedOperation::::indirect_call(signed_trusted_call); + + let encrypted_trusted_call = executor.encrypt(&trusted_operation.encode())?; + executor.submit_trusted_call(self.shard, encrypted_trusted_call); + Ok(()) + } +} diff --git a/bitacross-worker/app-libs/parentchain-interface/src/indirect_calls/transfer_to_alice_shields_funds.rs b/bitacross-worker/app-libs/parentchain-interface/src/indirect_calls/transfer_to_alice_shields_funds.rs new file mode 100644 index 0000000000..7aef56cddd --- /dev/null +++ b/bitacross-worker/app-libs/parentchain-interface/src/indirect_calls/transfer_to_alice_shields_funds.rs @@ -0,0 +1,98 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 core::fmt::Debug; +use ita_stf::{Getter, TrustedCall, TrustedCallSigned}; +use itc_parentchain_indirect_calls_executor::{ + error::{Error, Result}, + IndirectDispatch, +}; +use itp_stf_primitives::{ + traits::IndirectExecutor, + types::{AccountId, TrustedOperation}, +}; +use itp_types::Balance; +use log::info; +use sp_runtime::MultiAddress; +/// Arguments of a parentchains `transfer` or `transfer_allow_death` dispatchable. +/// +/// This is a simple demo indirect call where a transfer to alice on chain will transfer +/// funds to alice on sidechain. +#[derive(Debug, Clone, Encode, Decode, Eq, PartialEq)] +pub struct TransferToAliceShieldsFundsArgs { + // () is just a placeholder for index, which we don't use + pub destination: MultiAddress, + #[codec(compact)] + pub value: Balance, +} + +/// AccountId for `//Alice` because we can't derive the alice account in `no-std` otherwise. +/// +/// The following seed has been obtained by: +/// +/// ``` +/// use sp_core::{sr25519, Pair}; +/// use ita_parentchain_interface::indirect_calls::ALICE_ACCOUNT_ID; +/// let alice = sr25519::Pair::from_string_with_seed("//Alice", None).unwrap(); +/// println!("{:?}", alice.0.public().to_vec()); +/// assert_eq!(ALICE_ACCOUNT_ID, alice.0.public().into()) +/// ``` +pub const ALICE_ACCOUNT_ID: AccountId = AccountId::new([ + 212, 53, 147, 199, 21, 253, 211, 28, 97, 20, 26, 189, 4, 169, 159, 214, 130, 44, 133, 88, 133, + 76, 205, 227, 154, 86, 132, 231, 165, 109, 162, 125, +]); + +impl> + IndirectDispatch for TransferToAliceShieldsFundsArgs +{ + type Args = (); + fn dispatch(&self, executor: &Executor, _args: Self::Args) -> Result<()> { + if self.destination == ALICE_ACCOUNT_ID.into() { + info!("Found Transfer to Alice extrinsic in block: \nAmount: {}", self.value); + + let shard = executor.get_default_shard(); + let trusted_call = TrustedCall::balance_shield( + executor.get_enclave_account()?.into(), + ALICE_ACCOUNT_ID, + self.value, + ); + let signed_trusted_call = executor.sign_call_with_self(&trusted_call, &shard)?; + let trusted_operation = + TrustedOperation::::indirect_call(signed_trusted_call); + + let encrypted_trusted_call = executor.encrypt(&trusted_operation.encode())?; + executor.submit_trusted_call(shard, encrypted_trusted_call); + } else { + log::trace!("Transfer on parentchain was not for alice") + } + + Ok(()) + } +} + +#[cfg(test)] +mod test { + use crate::indirect_calls::transfer_to_alice_shields_funds::ALICE_ACCOUNT_ID; + use sp_core::{sr25519, Pair}; + + #[test] + fn alice_account_is_correct() { + let alice = sr25519::Pair::from_string_with_seed("//Alice", None).unwrap(); + assert_eq!(ALICE_ACCOUNT_ID, alice.0.public().into()); + } +} diff --git a/bitacross-worker/app-libs/parentchain-interface/src/integritee/event_filter.rs b/bitacross-worker/app-libs/parentchain-interface/src/integritee/event_filter.rs new file mode 100644 index 0000000000..d403a93948 --- /dev/null +++ b/bitacross-worker/app-libs/parentchain-interface/src/integritee/event_filter.rs @@ -0,0 +1,85 @@ +/* + Copyright 2021 Integritee AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 way to filter Parentchain events + +use itc_parentchain_indirect_calls_executor::event_filter::ToEvents; +use itp_api_client_types::Events; + +use itp_types::{ + parentchain::{ + BalanceTransfer, ExtrinsicFailed, ExtrinsicStatus, ExtrinsicSuccess, FilterEvents, + }, + H256, +}; +use std::vec::Vec; + +#[derive(Clone)] +pub struct FilterableEvents(pub Events); + +// todo: improve: https://github.com/integritee-network/worker/pull/1378#discussion_r1393933766 +impl ToEvents> for FilterableEvents { + fn to_events(&self) -> &Events { + &self.0 + } +} + +impl From> for FilterableEvents { + fn from(ev: Events) -> Self { + Self(ev) + } +} + +impl FilterEvents for FilterableEvents { + type Error = itc_parentchain_indirect_calls_executor::Error; + + fn get_extrinsic_statuses(&self) -> core::result::Result, Self::Error> { + Ok(self + .to_events() + .iter() + .filter_map(|ev| { + ev.and_then(|ev| { + if (ev.as_event::()?).is_some() { + return Ok(Some(ExtrinsicStatus::Success)) + } + + if (ev.as_event::()?).is_some() { + return Ok(Some(ExtrinsicStatus::Failed)) + } + + Ok(None) + }) + .ok() + .flatten() + }) + .collect()) + } + + fn get_transfer_events(&self) -> core::result::Result, Self::Error> { + Ok(self + .to_events() + .iter() + .flatten() // flatten filters out the nones + .filter_map(|ev| match ev.as_event::() { + Ok(maybe_event) => maybe_event, + Err(e) => { + log::error!("Could not decode event: {:?}", e); + None + }, + }) + .collect()) + } +} diff --git a/bitacross-worker/app-libs/parentchain-interface/src/integritee/event_handler.rs b/bitacross-worker/app-libs/parentchain-interface/src/integritee/event_handler.rs new file mode 100644 index 0000000000..1cc6cd3d0e --- /dev/null +++ b/bitacross-worker/app-libs/parentchain-interface/src/integritee/event_handler.rs @@ -0,0 +1,83 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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; + +pub use ita_sgx_runtime::{Balance, Index}; +use ita_stf::{Getter, TrustedCall, TrustedCallSigned}; +use itc_parentchain_indirect_calls_executor::error::Error; +use itp_stf_primitives::{traits::IndirectExecutor, types::TrustedOperation}; +use itp_types::parentchain::{AccountId, FilterEvents, HandleParentchainEvents, ParentchainError}; +use itp_utils::hex::hex_encode; +use log::*; + +pub struct ParentchainEventHandler {} + +impl ParentchainEventHandler { + fn shield_funds>( + executor: &Executor, + account: &AccountId, + amount: Balance, + ) -> Result<(), Error> { + log::info!("shielding for {:?} amount {}", account, amount,); + let shard = executor.get_default_shard(); + let trusted_call = TrustedCall::balance_shield( + executor.get_enclave_account()?.into(), + account.clone(), + amount, + ); + let signed_trusted_call = executor.sign_call_with_self(&trusted_call, &shard)?; + let trusted_operation = + TrustedOperation::::indirect_call(signed_trusted_call); + + let encrypted_trusted_call = executor.encrypt(&trusted_operation.encode())?; + executor.submit_trusted_call(shard, encrypted_trusted_call); + + Ok(()) + } +} + +impl HandleParentchainEvents + for ParentchainEventHandler +where + Executor: IndirectExecutor, +{ + fn handle_events( + executor: &Executor, + events: impl FilterEvents, + vault_account: &AccountId, + ) -> Result<(), Error> { + let filter_events = events.get_transfer_events(); + trace!( + "filtering transfer events to shard vault account: {}", + hex_encode(vault_account.encode().as_slice()) + ); + if let Ok(events) = filter_events { + events + .iter() + .filter(|&event| event.to == *vault_account) + .try_for_each(|event| { + info!("found transfer_event to vault account: {}", event); + //debug!("shielding from Integritee suppressed"); + Self::shield_funds(executor, &event.from, event.amount) + //Err(ParentchainError::FunctionalityDisabled) + }) + .map_err(|_| ParentchainError::ShieldFundsFailure)?; + } + Ok(()) + } +} diff --git a/bitacross-worker/app-libs/parentchain-interface/src/integritee/extrinsic_parser.rs b/bitacross-worker/app-libs/parentchain-interface/src/integritee/extrinsic_parser.rs new file mode 100644 index 0000000000..8e6520477e --- /dev/null +++ b/bitacross-worker/app-libs/parentchain-interface/src/integritee/extrinsic_parser.rs @@ -0,0 +1,83 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 core::marker::PhantomData; +use itc_parentchain_indirect_calls_executor::hash_of; +use itp_node_api::api_client::{ + Address, CallIndex, PairSignature, ParentchainSignedExtra, Signature, UncheckedExtrinsicV4, +}; +use itp_types::H256; + +pub struct ExtrinsicParser { + _phantom: PhantomData, +} + +/// Parses the extrinsics corresponding to the parentchain. +pub type ParentchainExtrinsicParser = ExtrinsicParser; + +/// Partially interpreted extrinsic containing the `signature` and the `call_index` whereas +/// the `call_args` remain in encoded form. +/// +/// Intended for usage, where the actual `call_args` form is unknown. +pub struct SemiOpaqueExtrinsic<'a, SignedExtra> { + /// Signature of the Extrinsic. + pub signature: Signature, + /// Call index of the dispatchable. + pub call_index: CallIndex, + /// Encoded arguments of the dispatchable corresponding to the `call_index`. + pub call_args: &'a [u8], + /// Hashed Extrinsic + pub hashed_extrinsic: H256, +} + +/// Trait to extract signature and call indexes of an encoded [UncheckedExtrinsicV4]. +pub trait ParseExtrinsic { + /// Signed extra of the extrinsic. + type SignedExtra; + + fn parse(encoded_call: &[u8]) -> Result, codec::Error>; +} + +impl ParseExtrinsic for ExtrinsicParser +where + SignedExtra: Decode + Encode, +{ + type SignedExtra = SignedExtra; + + /// Extract a call index of an encoded call. + fn parse(encoded_call: &[u8]) -> Result, codec::Error> { + let call_mut = &mut &encoded_call[..]; + + // `()` is a trick to stop decoding after the call index. So the remaining bytes + // of `call` after decoding only contain the parentchain's dispatchable's arguments. + let xt = UncheckedExtrinsicV4::< + Address, + (CallIndex, ()), + PairSignature, + Self::SignedExtra, + >::decode(call_mut)?; + let hashed_xt = hash_of(&xt); + + Ok(SemiOpaqueExtrinsic { + signature: xt.signature, + call_index: xt.function.0, + call_args: call_mut, + hashed_extrinsic: hashed_xt, + }) + } +} diff --git a/bitacross-worker/app-libs/parentchain-interface/src/integritee/mod.rs b/bitacross-worker/app-libs/parentchain-interface/src/integritee/mod.rs new file mode 100644 index 0000000000..f27609698c --- /dev/null +++ b/bitacross-worker/app-libs/parentchain-interface/src/integritee/mod.rs @@ -0,0 +1,173 @@ +/* + Copyright 2021 Integritee AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 event_filter; +mod event_handler; +mod extrinsic_parser; + +use crate::{ + decode_and_log_error, + indirect_calls::{ + InvokeArgs, RemoveScheduledEnclaveArgs, ShieldFundsArgs, UpdateScheduledEnclaveArgs, + }, + integritee::extrinsic_parser::ParseExtrinsic, +}; +use codec::{Decode, Encode}; +use core::marker::PhantomData; +pub use event_filter::FilterableEvents; +pub use event_handler::ParentchainEventHandler; +pub use extrinsic_parser::ParentchainExtrinsicParser; +use ita_stf::TrustedCallSigned; +use itc_parentchain_indirect_calls_executor::{ + error::{Error, Result}, + filter_metadata::FilterIntoDataFrom, + IndirectDispatch, +}; +use itp_node_api::metadata::NodeMetadataTrait; +use itp_stf_primitives::traits::IndirectExecutor; +use itp_types::CallIndex; +use log::trace; +use sp_std::vec::Vec; + +/// The default indirect call (extrinsic-triggered) of the Integritee-Parachain. +#[derive(Debug, Clone, Encode, Decode, Eq, PartialEq)] +pub enum IndirectCall { + #[codec(index = 0)] + ShieldFunds(ShieldFundsArgs), + #[codec(index = 1)] + Invoke(InvokeArgs), + // Litentry + #[codec(index = 6)] + UpdateScheduledEnclave(UpdateScheduledEnclaveArgs), + #[codec(index = 7)] + RemoveScheduledEnclave(RemoveScheduledEnclaveArgs), + #[codec(index = 8)] + BatchAll(Vec), +} + +impl> + IndirectDispatch for IndirectCall +{ + type Args = (); + fn dispatch(&self, executor: &Executor, _args: Self::Args) -> Result<()> { + trace!("dispatching indirect call {:?}", self); + match self { + IndirectCall::ShieldFunds(shieldfunds_args) => shieldfunds_args.dispatch(executor, ()), + IndirectCall::Invoke(invoke_args) => invoke_args.dispatch(executor, ()), + // Litentry + IndirectCall::UpdateScheduledEnclave(update_enclave_args) => + update_enclave_args.dispatch(executor, ()), + IndirectCall::RemoveScheduledEnclave(remove_enclave_args) => + remove_enclave_args.dispatch(executor, ()), + IndirectCall::BatchAll(calls) => { + for x in calls.clone() { + if let Err(e) = x.dispatch(executor, ()) { + log::warn!("Failed to execute indirect call in batch all due to: {:?}", e); + continue + } + } + Ok(()) + }, + } + } +} + +/// Default filter we use for the Integritee-Parachain. +pub struct ShieldFundsAndInvokeFilter { + _phantom: PhantomData, +} + +impl FilterIntoDataFrom + for ShieldFundsAndInvokeFilter +where + ExtrinsicParser: ParseExtrinsic, +{ + type Output = IndirectCall; + type ParseParentchainMetadata = ExtrinsicParser; + + fn filter_into_from_metadata( + encoded_data: &[u8], + metadata: &NodeMetadata, + ) -> Option { + let call_mut = &mut &encoded_data[..]; + + // Todo: the filter should not need to parse, only filter. This should directly be configured + // in the indirect executor. + let xt = match Self::ParseParentchainMetadata::parse(call_mut) { + Ok(xt) => xt, + Err(e) => { + log::error!( + "[ShieldFundsAndInvokeFilter] Could not parse parentchain extrinsic: {:?}", + e + ); + return None + }, + }; + let index = xt.call_index; + let call_args = &mut &xt.call_args[..]; + log::trace!( + "[ShieldFundsAndInvokeFilter] attempting to execute indirect call with index {:?}", + index + ); + if index == metadata.shield_funds_call_indexes().ok()? { + log::debug!("executing shield funds call"); + let args = decode_and_log_error::(call_args)?; + Some(IndirectCall::ShieldFunds(args)) + } else if index == metadata.invoke_call_indexes().ok()? { + log::debug!("executing invoke call"); + let args = decode_and_log_error::(call_args)?; + Some(IndirectCall::Invoke(args)) + // Litentry + } else if index == metadata.update_scheduled_enclave().ok()? { + let args = decode_and_log_error::(call_args)?; + Some(IndirectCall::UpdateScheduledEnclave(args)) + } else if index == metadata.remove_scheduled_enclave().ok()? { + let args = decode_and_log_error::(call_args)?; + Some(IndirectCall::RemoveScheduledEnclave(args)) + } else if index == metadata.batch_all_call_indexes().ok()? { + parse_batch_all(call_args, metadata) + } else { + None + } + } +} + +fn parse_batch_all( + call_args: &mut &[u8], + metadata: &NodeMetadata, +) -> Option { + let call_count: sp_std::vec::Vec<()> = Decode::decode(call_args).ok()?; + let mut calls: Vec = Vec::new(); + log::debug!("Received BatchAll including {} calls", call_count.len()); + for _i in 0..call_count.len() { + let index: CallIndex = Decode::decode(call_args).ok()?; + if index == metadata.shield_funds_call_indexes().ok()? { + let args = decode_and_log_error::(call_args)?; + calls.push(IndirectCall::ShieldFunds(args)) + } else if index == metadata.invoke_call_indexes().ok()? { + let args = decode_and_log_error::(call_args)?; + calls.push(IndirectCall::Invoke(args)) + } else if index == metadata.update_scheduled_enclave().ok()? { + let args = decode_and_log_error::(call_args)?; + calls.push(IndirectCall::UpdateScheduledEnclave(args)) + } else if index == metadata.remove_scheduled_enclave().ok()? { + let args = decode_and_log_error::(call_args)?; + calls.push(IndirectCall::RemoveScheduledEnclave(args)) + } + } + Some(IndirectCall::BatchAll(calls)) +} diff --git a/bitacross-worker/app-libs/parentchain-interface/src/lib.rs b/bitacross-worker/app-libs/parentchain-interface/src/lib.rs new file mode 100644 index 0000000000..2aa70c6447 --- /dev/null +++ b/bitacross-worker/app-libs/parentchain-interface/src/lib.rs @@ -0,0 +1,39 @@ +/* + Copyright 2021 Integritee AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +#![cfg_attr(all(not(target_env = "sgx"), not(feature = "std")), no_std)] +#![cfg_attr(target_env = "sgx", feature(rustc_private))] + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +extern crate sgx_tstd as std; + +use codec::Decode; + +pub mod indirect_calls; +pub mod integritee; +pub mod target_a; +pub mod target_b; + +pub fn decode_and_log_error(encoded: &mut &[u8]) -> Option { + match V::decode(encoded) { + Ok(v) => Some(v), + Err(e) => { + log::warn!("Could not decode. {:?}", e); + None + }, + } +} diff --git a/bitacross-worker/app-libs/parentchain-interface/src/target_a/event_filter.rs b/bitacross-worker/app-libs/parentchain-interface/src/target_a/event_filter.rs new file mode 100644 index 0000000000..b3efc37129 --- /dev/null +++ b/bitacross-worker/app-libs/parentchain-interface/src/target_a/event_filter.rs @@ -0,0 +1,89 @@ +/* + Copyright 2021 Integritee AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 way to filter Parentchain events + +use itc_parentchain_indirect_calls_executor::event_filter::ToEvents; +use itp_api_client_types::Events; + +use itp_types::{ + parentchain::{ + BalanceTransfer, ExtrinsicFailed, ExtrinsicStatus, ExtrinsicSuccess, FilterEvents, + }, + H256, +}; +use std::vec::Vec; + +#[derive(Clone)] +pub struct FilterableEvents(pub Events); + +impl ToEvents> for FilterableEvents { + fn to_events(&self) -> &Events { + &self.0 + } +} + +impl From> for FilterableEvents { + fn from(ev: Events) -> Self { + Self(ev) + } +} + +impl FilterEvents for FilterableEvents { + type Error = itc_parentchain_indirect_calls_executor::Error; + + fn get_extrinsic_statuses(&self) -> core::result::Result, Self::Error> { + Ok(self + .to_events() + .iter() + .filter_map(|ev| { + ev.and_then(|ev| { + if (ev.as_event::()?).is_some() { + return Ok(Some(ExtrinsicStatus::Success)) + } + + if (ev.as_event::()?).is_some() { + return Ok(Some(ExtrinsicStatus::Failed)) + } + + Ok(None) + }) + .ok() + .flatten() + }) + .collect()) + } + + fn get_transfer_events(&self) -> core::result::Result, Self::Error> { + Ok(self + .to_events() + .iter() + .flatten() // flatten filters out the nones + .filter_map(|ev| match ev.as_event::() { + Ok(maybe_event) => { + if maybe_event.is_none() { + log::warn!("Transfer event does not exist in parentchain metadata"); + }; + maybe_event + }, + Err(e) => { + log::error!("Could not decode event: {:?}", e); + None + }, + }) + .collect()) + } +} diff --git a/bitacross-worker/app-libs/parentchain-interface/src/target_a/event_handler.rs b/bitacross-worker/app-libs/parentchain-interface/src/target_a/event_handler.rs new file mode 100644 index 0000000000..7ea752aa55 --- /dev/null +++ b/bitacross-worker/app-libs/parentchain-interface/src/target_a/event_handler.rs @@ -0,0 +1,81 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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; +pub use ita_sgx_runtime::{Balance, Index}; + +use ita_stf::{Getter, TrustedCall, TrustedCallSigned}; +use itc_parentchain_indirect_calls_executor::error::Error; +use itp_stf_primitives::{traits::IndirectExecutor, types::TrustedOperation}; +use itp_types::parentchain::{AccountId, FilterEvents, HandleParentchainEvents, ParentchainError}; +use itp_utils::hex::hex_encode; +use log::*; + +pub struct ParentchainEventHandler {} + +impl ParentchainEventHandler { + fn shield_funds>( + executor: &Executor, + account: &AccountId, + amount: Balance, + ) -> Result<(), Error> { + trace!("[TargetA] shielding for {:?} amount {}", account, amount,); + let shard = executor.get_default_shard(); + let trusted_call = TrustedCall::balance_shield( + executor.get_enclave_account()?.into(), + account.clone(), + amount, + ); + let signed_trusted_call = executor.sign_call_with_self(&trusted_call, &shard)?; + let trusted_operation = + TrustedOperation::::indirect_call(signed_trusted_call); + + let encrypted_trusted_call = executor.encrypt(&trusted_operation.encode())?; + executor.submit_trusted_call(shard, encrypted_trusted_call); + + Ok(()) + } +} + +impl HandleParentchainEvents + for ParentchainEventHandler +where + Executor: IndirectExecutor, +{ + fn handle_events( + executor: &Executor, + events: impl FilterEvents, + vault_account: &AccountId, + ) -> Result<(), Error> { + let filter_events = events.get_transfer_events(); + trace!( + "[TargetA] filtering transfer events to shard vault account: {}", + hex_encode(vault_account.encode().as_slice()) + ); + if let Ok(events) = filter_events { + events + .iter() + .filter(|&event| event.to == *vault_account) + .try_for_each(|event| { + std::println!("⣿TargetA⣿ 🛡 found transfer event to shard vault account: {} will shield to {}", event.amount, hex_encode(event.from.encode().as_ref())); + Self::shield_funds(executor, &event.from, event.amount) + }) + .map_err(|_| ParentchainError::ShieldFundsFailure)?; + } + Ok(()) + } +} diff --git a/bitacross-worker/app-libs/parentchain-interface/src/target_a/extrinsic_parser.rs b/bitacross-worker/app-libs/parentchain-interface/src/target_a/extrinsic_parser.rs new file mode 100644 index 0000000000..925aca30ee --- /dev/null +++ b/bitacross-worker/app-libs/parentchain-interface/src/target_a/extrinsic_parser.rs @@ -0,0 +1,77 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 core::marker::PhantomData; +use itp_node_api::api_client::{ + Address, CallIndex, PairSignature, ParentchainSignedExtra, Signature, UncheckedExtrinsicV4, +}; + +pub struct ExtrinsicParser { + _phantom: PhantomData, +} + +/// Parses the extrinsics corresponding to the parentchain. +pub type ParentchainExtrinsicParser = ExtrinsicParser; + +/// Partially interpreted extrinsic containing the `signature` and the `call_index` whereas +/// the `call_args` remain in encoded form. +/// +/// Intended for usage, where the actual `call_args` form is unknown. +pub struct SemiOpaqueExtrinsic<'a, SignedExtra> { + /// Signature of the Extrinsic. + pub signature: Signature, + /// Call index of the dispatchable. + pub call_index: CallIndex, + /// Encoded arguments of the dispatchable corresponding to the `call_index`. + pub call_args: &'a [u8], +} + +/// Trait to extract signature and call indexes of an encoded [UncheckedExtrinsicV4]. +pub trait ParseExtrinsic { + /// Signed extra of the extrinsic. + type SignedExtra; + + fn parse(encoded_call: &[u8]) -> Result, codec::Error>; +} + +impl ParseExtrinsic for ExtrinsicParser +where + SignedExtra: Decode + Encode, +{ + type SignedExtra = SignedExtra; + + /// Extract a call index of an encoded call. + fn parse(encoded_call: &[u8]) -> Result, codec::Error> { + let call_mut = &mut &encoded_call[..]; + + // `()` is a trick to stop decoding after the call index. So the remaining bytes + // of `call` after decoding only contain the parentchain's dispatchable's arguments. + let xt = UncheckedExtrinsicV4::< + Address, + (CallIndex, ()), + PairSignature, + Self::SignedExtra, + >::decode(call_mut)?; + + Ok(SemiOpaqueExtrinsic { + signature: xt.signature, + call_index: xt.function.0, + call_args: call_mut, + }) + } +} diff --git a/bitacross-worker/app-libs/parentchain-interface/src/target_a/mod.rs b/bitacross-worker/app-libs/parentchain-interface/src/target_a/mod.rs new file mode 100644 index 0000000000..56a7be3927 --- /dev/null +++ b/bitacross-worker/app-libs/parentchain-interface/src/target_a/mod.rs @@ -0,0 +1,116 @@ +/* + Copyright 2021 Integritee AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 event_filter; +mod event_handler; +mod extrinsic_parser; +use crate::{ + decode_and_log_error, + indirect_calls::{ + transfer_to_alice_shields_funds::TransferToAliceShieldsFundsArgs, ALICE_ACCOUNT_ID, + }, +}; +use codec::{Decode, Encode}; +use core::marker::PhantomData; +pub use event_filter::FilterableEvents; +pub use event_handler::ParentchainEventHandler; +pub use extrinsic_parser::ParentchainExtrinsicParser; +use extrinsic_parser::ParseExtrinsic; +use ita_stf::TrustedCallSigned; +use itc_parentchain_indirect_calls_executor::{ + error::{Error, Result}, + filter_metadata::FilterIntoDataFrom, + IndirectDispatch, +}; +use itp_node_api::metadata::pallet_balances::BalancesCallIndexes; +use itp_stf_primitives::traits::IndirectExecutor; +use log::{debug, trace}; + +/// The default indirect call (extrinsic-triggered) of the Target-A-Parachain. +#[derive(Debug, Clone, Encode, Decode, Eq, PartialEq)] +pub enum IndirectCall { + TransferToAliceShieldsFunds(TransferToAliceShieldsFundsArgs), +} + +impl> + IndirectDispatch for IndirectCall +{ + type Args = (); + fn dispatch(&self, _executor: &Executor, _args: Self::Args) -> Result<()> { + debug!("shielding from TargetA extrinsic to Alice suppressed"); + /* + trace!("dispatching indirect call {:?}", self); + match self { + IndirectCall::TransferToAliceShieldsFunds(args) => args.dispatch(executor, ()), + } + + */ + Ok(()) + } +} + +/// Simple demo filter for testing. +/// +/// A transfer to Alice will issue the corresponding balance to Alice in the enclave. +/// It does not do anything else. +pub struct TransferToAliceShieldsFundsFilter { + _phantom: PhantomData, +} + +impl FilterIntoDataFrom + for TransferToAliceShieldsFundsFilter +where + ExtrinsicParser: ParseExtrinsic, +{ + type Output = IndirectCall; + type ParseParentchainMetadata = ExtrinsicParser; + + fn filter_into_from_metadata( + encoded_data: &[u8], + metadata: &NodeMetadata, + ) -> Option { + let call_mut = &mut &encoded_data[..]; + + // Todo: the filter should not need to parse, only filter. This should directly be configured + // in the indirect executor. + let xt = match Self::ParseParentchainMetadata::parse(call_mut) { + Ok(xt) => xt, + Err(e) => { + log::error!("[TransferToAliceShieldsFundsFilter] Could not parse parentchain extrinsic: {:?}", e); + return None + }, + }; + let index = xt.call_index; + let call_args = &mut &xt.call_args[..]; + trace!("[TransferToAliceShieldsFundsFilter] attempting to execute indirect call with index {:?}", index); + if index == metadata.transfer_call_indexes().ok()? + || index == metadata.transfer_keep_alive_call_indexes().ok()? + || index == metadata.transfer_allow_death_call_indexes().ok()? + { + debug!("found `transfer` or `transfer_allow_death` or `transfer_keep_alive` call."); + let args = decode_and_log_error::(call_args)?; + if args.destination == ALICE_ACCOUNT_ID.into() { + Some(IndirectCall::TransferToAliceShieldsFunds(args)) + } else { + debug!("Parentchain transfer extrinsic was not for Alice; ignoring..."); + // No need to put it into the top pool if it isn't executed in the first place. + None + } + } else { + None + } + } +} diff --git a/bitacross-worker/app-libs/parentchain-interface/src/target_b/event_filter.rs b/bitacross-worker/app-libs/parentchain-interface/src/target_b/event_filter.rs new file mode 100644 index 0000000000..b3efc37129 --- /dev/null +++ b/bitacross-worker/app-libs/parentchain-interface/src/target_b/event_filter.rs @@ -0,0 +1,89 @@ +/* + Copyright 2021 Integritee AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 way to filter Parentchain events + +use itc_parentchain_indirect_calls_executor::event_filter::ToEvents; +use itp_api_client_types::Events; + +use itp_types::{ + parentchain::{ + BalanceTransfer, ExtrinsicFailed, ExtrinsicStatus, ExtrinsicSuccess, FilterEvents, + }, + H256, +}; +use std::vec::Vec; + +#[derive(Clone)] +pub struct FilterableEvents(pub Events); + +impl ToEvents> for FilterableEvents { + fn to_events(&self) -> &Events { + &self.0 + } +} + +impl From> for FilterableEvents { + fn from(ev: Events) -> Self { + Self(ev) + } +} + +impl FilterEvents for FilterableEvents { + type Error = itc_parentchain_indirect_calls_executor::Error; + + fn get_extrinsic_statuses(&self) -> core::result::Result, Self::Error> { + Ok(self + .to_events() + .iter() + .filter_map(|ev| { + ev.and_then(|ev| { + if (ev.as_event::()?).is_some() { + return Ok(Some(ExtrinsicStatus::Success)) + } + + if (ev.as_event::()?).is_some() { + return Ok(Some(ExtrinsicStatus::Failed)) + } + + Ok(None) + }) + .ok() + .flatten() + }) + .collect()) + } + + fn get_transfer_events(&self) -> core::result::Result, Self::Error> { + Ok(self + .to_events() + .iter() + .flatten() // flatten filters out the nones + .filter_map(|ev| match ev.as_event::() { + Ok(maybe_event) => { + if maybe_event.is_none() { + log::warn!("Transfer event does not exist in parentchain metadata"); + }; + maybe_event + }, + Err(e) => { + log::error!("Could not decode event: {:?}", e); + None + }, + }) + .collect()) + } +} diff --git a/bitacross-worker/app-libs/parentchain-interface/src/target_b/event_handler.rs b/bitacross-worker/app-libs/parentchain-interface/src/target_b/event_handler.rs new file mode 100644 index 0000000000..39a5555973 --- /dev/null +++ b/bitacross-worker/app-libs/parentchain-interface/src/target_b/event_handler.rs @@ -0,0 +1,41 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 ita_sgx_runtime::{Balance, Index}; + +use ita_stf::TrustedCallSigned; +use itc_parentchain_indirect_calls_executor::error::Error; +use itp_stf_primitives::traits::IndirectExecutor; +use itp_types::parentchain::{AccountId, FilterEvents, HandleParentchainEvents}; +use log::*; + +pub struct ParentchainEventHandler {} + +impl HandleParentchainEvents + for ParentchainEventHandler +where + Executor: IndirectExecutor, +{ + fn handle_events( + _executor: &Executor, + _events: impl FilterEvents, + _vault_account: &AccountId, + ) -> Result<(), Error> { + debug!("not handling any events for target B"); + Ok(()) + } +} diff --git a/bitacross-worker/app-libs/parentchain-interface/src/target_b/extrinsic_parser.rs b/bitacross-worker/app-libs/parentchain-interface/src/target_b/extrinsic_parser.rs new file mode 100644 index 0000000000..925aca30ee --- /dev/null +++ b/bitacross-worker/app-libs/parentchain-interface/src/target_b/extrinsic_parser.rs @@ -0,0 +1,77 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 core::marker::PhantomData; +use itp_node_api::api_client::{ + Address, CallIndex, PairSignature, ParentchainSignedExtra, Signature, UncheckedExtrinsicV4, +}; + +pub struct ExtrinsicParser { + _phantom: PhantomData, +} + +/// Parses the extrinsics corresponding to the parentchain. +pub type ParentchainExtrinsicParser = ExtrinsicParser; + +/// Partially interpreted extrinsic containing the `signature` and the `call_index` whereas +/// the `call_args` remain in encoded form. +/// +/// Intended for usage, where the actual `call_args` form is unknown. +pub struct SemiOpaqueExtrinsic<'a, SignedExtra> { + /// Signature of the Extrinsic. + pub signature: Signature, + /// Call index of the dispatchable. + pub call_index: CallIndex, + /// Encoded arguments of the dispatchable corresponding to the `call_index`. + pub call_args: &'a [u8], +} + +/// Trait to extract signature and call indexes of an encoded [UncheckedExtrinsicV4]. +pub trait ParseExtrinsic { + /// Signed extra of the extrinsic. + type SignedExtra; + + fn parse(encoded_call: &[u8]) -> Result, codec::Error>; +} + +impl ParseExtrinsic for ExtrinsicParser +where + SignedExtra: Decode + Encode, +{ + type SignedExtra = SignedExtra; + + /// Extract a call index of an encoded call. + fn parse(encoded_call: &[u8]) -> Result, codec::Error> { + let call_mut = &mut &encoded_call[..]; + + // `()` is a trick to stop decoding after the call index. So the remaining bytes + // of `call` after decoding only contain the parentchain's dispatchable's arguments. + let xt = UncheckedExtrinsicV4::< + Address, + (CallIndex, ()), + PairSignature, + Self::SignedExtra, + >::decode(call_mut)?; + + Ok(SemiOpaqueExtrinsic { + signature: xt.signature, + call_index: xt.function.0, + call_args: call_mut, + }) + } +} diff --git a/bitacross-worker/app-libs/parentchain-interface/src/target_b/mod.rs b/bitacross-worker/app-libs/parentchain-interface/src/target_b/mod.rs new file mode 100644 index 0000000000..f0e81c4c54 --- /dev/null +++ b/bitacross-worker/app-libs/parentchain-interface/src/target_b/mod.rs @@ -0,0 +1,86 @@ +/* + Copyright 2021 Integritee AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +/* + Copyright 2021 Integritee AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 event_filter; +mod event_handler; +mod extrinsic_parser; + +use codec::{Decode, Encode}; +use core::marker::PhantomData; +pub use event_filter::FilterableEvents; +pub use event_handler::ParentchainEventHandler; +pub use extrinsic_parser::ParentchainExtrinsicParser; +use extrinsic_parser::ParseExtrinsic; +use ita_stf::TrustedCallSigned; +use itc_parentchain_indirect_calls_executor::{ + error::{Error, Result}, + filter_metadata::FilterIntoDataFrom, + IndirectDispatch, +}; +use itp_node_api::metadata::pallet_balances::BalancesCallIndexes; +use itp_stf_primitives::traits::IndirectExecutor; +use log::error; + +/// The default indirect call (extrinsic-triggered) of the Target-A-Parachain. +#[derive(Debug, Clone, Encode, Decode, Eq, PartialEq)] +pub enum IndirectCall {} + +impl> + IndirectDispatch for IndirectCall +{ + type Args = (); + fn dispatch(&self, _executor: &Executor, _args: Self::Args) -> Result<()> { + Err(Error::Other("no indirect calls defined for target_b".into())) + } +} + +pub struct TargetBExtrinsicFilter { + _phantom: PhantomData, +} + +impl FilterIntoDataFrom + for TargetBExtrinsicFilter +where + ExtrinsicParser: ParseExtrinsic, +{ + type Output = IndirectCall; + type ParseParentchainMetadata = ExtrinsicParser; + + fn filter_into_from_metadata( + _encoded_data: &[u8], + _metadata: &NodeMetadata, + ) -> Option { + error!("no indirect calls filter has been implemented for target_b"); + None + } +} diff --git a/bitacross-worker/app-libs/sgx-runtime/Cargo.toml b/bitacross-worker/app-libs/sgx-runtime/Cargo.toml new file mode 100644 index 0000000000..7b94576e4c --- /dev/null +++ b/bitacross-worker/app-libs/sgx-runtime/Cargo.toml @@ -0,0 +1,70 @@ +[package] +name = "ita-sgx-runtime" +version = "0.9.0" +authors = ['Trust Computing GmbH ', 'Integritee AG '] +edition = "2021" + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } + +# local dependencies +itp-sgx-runtime-primitives = { path = "../../core-primitives/sgx-runtime-primitives", default-features = false } + +# Substrate dependencies +frame-executive = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } +frame-support = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } +frame-system = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } +pallet-balances = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } +pallet-sudo = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } +pallet-timestamp = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } +pallet-transaction-payment = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } +sp-api = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } +sp-core = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } +sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } +sp-std = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } +sp-version = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } + +# Integritee dependencies +pallet-evm = { default-features = false, optional = true, git = "https://github.com/integritee-network/frontier.git", branch = "bar/polkadot-v0.9.42" } + +pallet-parentchain = { path = "../../../pallets/parentchain", default-features = false } + +[features] +default = ["std"] +# Compile the sgx-runtime with evm-pallet support in `no_std`. +evm = ["pallet-evm"] +# Compile the sgx-runtime with evm-pallet support in `std`. +evm_std = [ + "evm", # Activate the `feature = evm` for the compiler flags. + "std", + "pallet-evm/std", +] +runtime-benchmarks = [ + "frame-support/runtime-benchmarks", + "frame-system/runtime-benchmarks", + "pallet-balances/runtime-benchmarks", + "pallet-timestamp/runtime-benchmarks", + "sp-runtime/runtime-benchmarks", +] +std = [ + "codec/std", + "scale-info/std", + "itp-sgx-runtime-primitives/std", + "frame-executive/std", + "frame-support/std", + "frame-system/std", + "pallet-balances/std", + "pallet-sudo/std", + "pallet-timestamp/std", + "pallet-transaction-payment/std", + "pallet-parentchain/std", + "sp-api/std", + "sp-core/std", + "sp-runtime/std", + "sp-std/std", + "sp-version/std", +] diff --git a/bitacross-worker/app-libs/sgx-runtime/src/evm.rs b/bitacross-worker/app-libs/sgx-runtime/src/evm.rs new file mode 100644 index 0000000000..990fdd1492 --- /dev/null +++ b/bitacross-worker/app-libs/sgx-runtime/src/evm.rs @@ -0,0 +1,91 @@ +//! Adds the `pallet-evm` support for the `sgx-runtime. + +// Import types from the crate root including the ones generated by the `construct_runtime!` macro. +use crate::{Balances, Runtime, RuntimeEvent, Timestamp, NORMAL_DISPATCH_RATIO}; +use frame_support::{ + pallet_prelude::Weight, parameter_types, weights::constants::WEIGHT_REF_TIME_PER_SECOND, +}; +use sp_core::{H160, U256}; +use sp_runtime::traits::BlakeTwo256; + +pub use pallet_evm::{ + AddressMapping, Call as EvmCall, EnsureAddressTruncated, FeeCalculator, GasWeightMapping, + HashedAddressMapping as GenericHashedAddressMapping, SubstrateBlockHashMapping, +}; + +pub type HashedAddressMapping = GenericHashedAddressMapping; + +/// Maximum weight per block +pub const MAXIMUM_BLOCK_WEIGHT: Weight = + Weight::from_parts(WEIGHT_REF_TIME_PER_SECOND.saturating_div(2), u64::MAX); + +// FIXME: For now just a random value. +pub struct FixedGasPrice; +impl FeeCalculator for FixedGasPrice { + fn min_gas_price() -> (U256, Weight) { + (1.into(), Weight::from_parts(1, 0u64)) + } +} + +/// Current approximation of the gas/s consumption considering +/// EVM execution over compiled WASM (on 4.4Ghz CPU). +/// Given the 500ms Weight, from which 75% only are used for transactions, +/// the total EVM execution gas limit is: GAS_PER_SECOND * 0.500 * 0.75 ~= 15_000_000. +pub const GAS_PER_SECOND: u64 = 40_000_000; + +/// Approximate ratio of the amount of Weight per Gas. +/// u64 works for approximations because Weight is a very small unit compared to gas. +pub const WEIGHT_PER_GAS: u64 = WEIGHT_REF_TIME_PER_SECOND / GAS_PER_SECOND; + +pub struct FixedGasWeightMapping; + +impl GasWeightMapping for FixedGasWeightMapping { + fn gas_to_weight(gas: u64, _without_base_weight: bool) -> Weight { + Weight::from_parts(gas.saturating_mul(WEIGHT_PER_GAS), 0u64) + } + fn weight_to_gas(weight: Weight) -> u64 { + weight.ref_time().wrapping_div(WEIGHT_PER_GAS) + } +} + +/// An ipmlementation of Frontier's AddressMapping trait for Sgx Accounts. +/// This is basically identical to Frontier's own IdentityAddressMapping, but it works for any type +/// that is Into like AccountId20 for example. +pub struct IntoAddressMapping; + +impl> AddressMapping for IntoAddressMapping { + fn into_account_id(address: H160) -> T { + address.into() + } +} + +parameter_types! { + pub const ChainId: u64 = 42; + pub BlockGasLimit: U256 = U256::from(NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT.ref_time() / WEIGHT_PER_GAS); + pub const GasLimitPovSizeRatio: u64 = 150_000_000 / (5 * 1024 * 1024); + //pub PrecompilesValue: FrontierPrecompiles = FrontierPrecompiles::<_>::new(); +} + +impl pallet_evm::Config for Runtime { + type FeeCalculator = FixedGasPrice; + type GasWeightMapping = FixedGasWeightMapping; + type BlockHashMapping = SubstrateBlockHashMapping; + type CallOrigin = EnsureAddressTruncated; + type WithdrawOrigin = EnsureAddressTruncated; + type AddressMapping = HashedAddressMapping; + type Currency = Balances; + type RuntimeEvent = RuntimeEvent; + type Runner = pallet_evm::runner::stack::Runner; + type PrecompilesType = (); + type PrecompilesValue = (); + type ChainId = ChainId; + type OnChargeTransaction = (); + type BlockGasLimit = BlockGasLimit; + type FindAuthor = (); // Currently not available. Would need some more thoughts how prioritisation fees could be handled. + // BlockGasLimit / MAX_POV_SIZE + // type GasLimitPovSizeRatio = GasLimitPovSizeRatio; + type WeightPerGas = (); + type OnCreate = (); + type Timestamp = Timestamp; + type WeightInfo = (); +} diff --git a/bitacross-worker/app-libs/sgx-runtime/src/lib.rs b/bitacross-worker/app-libs/sgx-runtime/src/lib.rs new file mode 100644 index 0000000000..0a653c3ab1 --- /dev/null +++ b/bitacross-worker/app-libs/sgx-runtime/src/lib.rs @@ -0,0 +1,335 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 Node Template sgx-runtime for SGX. +//! This is only meant to be used inside an SGX enclave with `#[no_std]` +//! +//! you should assemble your sgx-runtime to be used with your STF here +//! and get all your needed pallets in + +#![cfg_attr(not(feature = "std"), no_std)] +#![feature(prelude_import)] +#![feature(structural_match)] +#![feature(core_intrinsics)] +#![feature(derive_eq)] +// `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256. +#![recursion_limit = "256"] + +#[cfg(feature = "evm")] +mod evm; +#[cfg(feature = "evm")] +pub use evm::{ + AddressMapping, EnsureAddressTruncated, EvmCall, FeeCalculator, FixedGasPrice, + FixedGasWeightMapping, GasWeightMapping, HashedAddressMapping, IntoAddressMapping, + SubstrateBlockHashMapping, GAS_PER_SECOND, MAXIMUM_BLOCK_WEIGHT, WEIGHT_PER_GAS, +}; + +use core::convert::{TryFrom, TryInto}; +use frame_support::{traits::ConstU32, weights::ConstantMultiplier}; +use pallet_transaction_payment::CurrencyAdapter; +use sp_api::impl_runtime_apis; +use sp_core::OpaqueMetadata; +use sp_runtime::{ + create_runtime_str, generic, + traits::{AccountIdLookup, BlakeTwo256, Block as BlockT}, +}; +use sp_std::prelude::*; +use sp_version::RuntimeVersion; + +// Re-exports from itp-sgx-runtime-primitives. +pub use itp_sgx_runtime_primitives::{ + constants::SLOT_DURATION, + types::{ + AccountData, AccountId, Address, Balance, BlockNumber, ConvertAccountId, Hash, Header, + Index, SgxParentchainTypeConverter, Signature, + }, +}; + +// A few exports that help ease life for downstream crates. +pub use frame_support::{ + construct_runtime, parameter_types, + traits::{KeyOwnerProofSystem, Randomness}, + weights::{ + constants::{ + BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_REF_TIME_PER_SECOND, + }, + IdentityFee, Weight, + }, + StorageValue, +}; +pub use pallet_balances::Call as BalancesCall; +pub use pallet_parentchain::Call as ParentchainPalletCall; +pub use pallet_timestamp::Call as TimestampCall; +#[cfg(any(feature = "std", test))] +pub use sp_runtime::BuildStorage; +pub use sp_runtime::{Perbill, Permill}; + +/// Block type as expected by this sgx-runtime. +pub type Block = generic::Block; +/// A Block signed with a Justification +pub type SignedBlock = generic::SignedBlock; +/// BlockId type as expected by this sgx-runtime. +pub type BlockId = generic::BlockId; + +/// The SignedExtension to the basic transaction logic. +pub type SignedExtra = ( + frame_system::CheckNonZeroSender, + frame_system::CheckSpecVersion, + frame_system::CheckTxVersion, + frame_system::CheckGenesis, + frame_system::CheckEra, + frame_system::CheckNonce, + frame_system::CheckWeight, + pallet_transaction_payment::ChargeTransactionPayment, +); +/// Unchecked extrinsic type as expected by this sgx-runtime. +pub type UncheckedExtrinsic = + generic::UncheckedExtrinsic; +/// Extrinsic type that has already been checked. +pub type CheckedExtrinsic = generic::CheckedExtrinsic; + +/// Executive: handles dispatch to the various modules. +pub type Executive = frame_executive::Executive< + Runtime, + Block, + frame_system::ChainContext, + Runtime, + AllPalletsWithSystem, +>; + +/// Opaque types. These are used by the CLI to instantiate machinery that don't need to know +/// the specifics of the sgx-runtime. They can then be made to be agnostic over specific formats +/// of data like extrinsics, allowing for them to continue syncing the network through upgrades +/// to even the core data structures. +pub mod opaque { + + use sp_runtime::generic; + pub use sp_runtime::OpaqueExtrinsic as UncheckedExtrinsic; + + /// Opaque block header type. + pub type Header = itp_sgx_runtime_primitives::types::Header; + /// Opaque block type. + pub type Block = super::Block; + /// Opaque block identifier type. + pub type BlockId = generic::BlockId; +} + +pub const VERSION: RuntimeVersion = RuntimeVersion { + spec_name: create_runtime_str!("node-template"), + impl_name: create_runtime_str!("node-template"), + authoring_version: 1, + spec_version: 102, + impl_version: 1, + apis: RUNTIME_API_VERSIONS, + transaction_version: 1, + state_version: 0, +}; + +const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75); + +parameter_types! { + pub const Version: RuntimeVersion = VERSION; + pub const BlockHashCount: BlockNumber = 2400; + /// We allow for 2 seconds of compute with a 6 second average block time. + pub BlockWeights: frame_system::limits::BlockWeights = frame_system::limits::BlockWeights + ::with_sensible_defaults(Weight::from_parts(WEIGHT_REF_TIME_PER_SECOND, u64::MAX), NORMAL_DISPATCH_RATIO); + pub BlockLength: frame_system::limits::BlockLength = frame_system::limits::BlockLength + ::max_with_normal_ratio(5 * 1024 * 1024, NORMAL_DISPATCH_RATIO); + pub const SS58Prefix: u8 = 42; +} + +// Configure FRAME pallets to include in sgx-runtime. + +impl frame_system::Config for Runtime { + /// The basic call filter to use in dispatchable. + type BaseCallFilter = frame_support::traits::Everything; + /// Block & extrinsics weights: base values and limits. + type BlockWeights = BlockWeights; + /// The maximum length of a block (in bytes). + type BlockLength = BlockLength; + /// The identifier used to distinguish between accounts. + type AccountId = AccountId; + /// The aggregated dispatch type that is available for extrinsics. + type RuntimeCall = RuntimeCall; + /// The lookup mechanism to get account ID from whatever is passed in dispatchers. + type Lookup = AccountIdLookup; + /// The index type for storing how many extrinsics an account has signed. + type Index = Index; + /// The index type for blocks. + type BlockNumber = BlockNumber; + /// The type for hashing blocks and tries. + type Hash = Hash; + /// The hashing algorithm used. + type Hashing = BlakeTwo256; + /// The header type. + type Header = Header; + /// The ubiquitous event type. + type RuntimeEvent = RuntimeEvent; + /// The ubiquitous origin type. + type RuntimeOrigin = RuntimeOrigin; + /// Maximum number of block number to block hash mappings to keep (oldest pruned first). + type BlockHashCount = BlockHashCount; + /// The weight of database operations that the sgx-runtime can invoke. + type DbWeight = RocksDbWeight; + /// Version of the sgx-runtime. + type Version = Version; + /// Converts a module to the index of the module in `construct_runtime!`. + /// + /// This type is being generated by `construct_runtime!`. + type PalletInfo = PalletInfo; + /// What to do if a new account is created. + type OnNewAccount = (); + /// What to do if an account is fully reaped from the system. + type OnKilledAccount = (); + /// The data to be stored in an account. + type AccountData = AccountData; + /// Weight information for the extrinsics of this pallet. + type SystemWeightInfo = (); + /// This is used as an identifier of the chain. 42 is the generic substrate prefix. + type SS58Prefix = SS58Prefix; + /// The set code logic, just the default since we're not a parachain. + type OnSetCode = (); + /// The maximum number of consumers allowed on a single account. + type MaxConsumers = frame_support::traits::ConstU32<16>; +} + +parameter_types! { + pub const MinimumPeriod: u64 = SLOT_DURATION / 2; +} + +impl pallet_timestamp::Config for Runtime { + /// A timestamp: milliseconds since the unix epoch. + type Moment = u64; + type OnTimestampSet = (); + type MinimumPeriod = MinimumPeriod; + type WeightInfo = (); +} + +parameter_types! { + pub const ExistentialDeposit: u128 = 500; + pub const MaxLocks: u32 = 50; +} + +impl pallet_balances::Config for Runtime { + type MaxLocks = MaxLocks; + type MaxReserves = (); + type ReserveIdentifier = [u8; 8]; + /// The type for recording an account's balance. + type Balance = Balance; + /// The ubiquitous event type. + type RuntimeEvent = RuntimeEvent; + type DustRemoval = (); + type ExistentialDeposit = ExistentialDeposit; + type AccountStore = System; + type WeightInfo = (); + type HoldIdentifier = (); + type FreezeIdentifier = (); + type MaxHolds = ConstU32<0>; + type MaxFreezes = ConstU32<0>; +} + +parameter_types! { + pub const TransactionByteFee: Balance = 1; + pub const OperationalFeeMultiplier: u8 = 5; +} + +impl pallet_transaction_payment::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type OnChargeTransaction = CurrencyAdapter; + type OperationalFeeMultiplier = OperationalFeeMultiplier; + type WeightToFee = IdentityFee; + type LengthToFee = ConstantMultiplier; + type FeeMultiplierUpdate = (); +} + +impl pallet_sudo::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type RuntimeCall = RuntimeCall; +} + +impl pallet_parentchain::Config for Runtime { + type WeightInfo = (); +} + +// The plain sgx-runtime without the `evm-pallet` +#[cfg(not(feature = "evm"))] +construct_runtime!( + pub enum Runtime where + Block = Block, + NodeBlock = opaque::Block, + UncheckedExtrinsic = UncheckedExtrinsic + { + System: frame_system::{Pallet, Call, Config, Storage, Event}, + Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent}, + Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, + TransactionPayment: pallet_transaction_payment::{Pallet, Storage, Event}, + Sudo: pallet_sudo::{Pallet, Call, Config, Storage, Event}, + Parentchain: pallet_parentchain::{Pallet, Call, Storage}, + } +); + +// Runtime constructed with the evm pallet. +// +// We need add the compiler-flag for the whole macro because it does not support +// compiler flags withing the macro. +#[cfg(feature = "evm")] +construct_runtime!( + pub enum Runtime where + Block = Block, + NodeBlock = opaque::Block, + UncheckedExtrinsic = UncheckedExtrinsic + { + System: frame_system::{Pallet, Call, Config, Storage, Event}, + Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent}, + Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, + TransactionPayment: pallet_transaction_payment::{Pallet, Storage, Event}, + Sudo: pallet_sudo::{Pallet, Call, Config, Storage, Event}, + Parentchain: pallet_parentchain::{Pallet, Call, Storage}, + + Evm: pallet_evm::{Pallet, Call, Storage, Config, Event}, + } +); + +impl_runtime_apis! { + impl sp_api::Core for Runtime { + fn version() -> RuntimeVersion { + VERSION + } + + fn execute_block(block: Block) { + Executive::execute_block(block); + } + + fn initialize_block(header: &::Header) { + Executive::initialize_block(header) + } + } + + impl sp_api::Metadata for Runtime { + fn metadata() -> OpaqueMetadata { + OpaqueMetadata::new(Runtime::metadata().into()) + } + + fn metadata_at_version(version: u32) -> Option { + Runtime::metadata_at_version(version) + } + + fn metadata_versions() -> sp_std::vec::Vec { + Runtime::metadata_versions() + } + } + +} diff --git a/bitacross-worker/app-libs/stf/Cargo.toml b/bitacross-worker/app-libs/stf/Cargo.toml new file mode 100644 index 0000000000..ddec15630a --- /dev/null +++ b/bitacross-worker/app-libs/stf/Cargo.toml @@ -0,0 +1,89 @@ +[package] +name = "ita-stf" +version = "0.9.0" +authors = ['Trust Computing GmbH ', 'Integritee AG '] +edition = "2021" + +[dependencies] +# crates.io +codec = { version = "3.0.0", default-features = false, features = ["derive"], package = "parity-scale-codec" } +hex = { version = "0.4", default-features = false } +hex-literal = { version = "0.4" } +log = { version = "0.4", default-features = false } +rlp = { version = "0.5", default-features = false } +sha3 = { version = "0.10", default-features = false } + +# sgx deps +sgx_tstd = { branch = "master", features = ["untrusted_fs", "net", "backtrace"], git = "https://github.com/apache/teaclave-sgx-sdk.git", optional = true } + +# local crates +ita-sgx-runtime = { default-features = false, path = "../sgx-runtime" } +itp-hashing = { default-features = false, path = "../../core-primitives/hashing" } +itp-node-api = { default-features = false, path = "../../core-primitives/node-api" } +itp-node-api-metadata = { default-features = false, path = "../../core-primitives/node-api/metadata" } +itp-sgx-externalities = { default-features = false, path = "../../core-primitives/substrate-sgx/externalities" } +itp-stf-interface = { default-features = false, path = "../../core-primitives/stf-interface" } +itp-stf-primitives = { default-features = false, path = "../../core-primitives/stf-primitives" } +itp-storage = { default-features = false, path = "../../core-primitives/storage" } +itp-types = { default-features = false, path = "../../core-primitives/types" } +itp-utils = { default-features = false, path = "../../core-primitives/utils" } +sp-io = { default-features = false, features = ["disable_oom", "disable_panic_handler", "disable_allocator"], path = "../../core-primitives/substrate-sgx/sp-io" } + +# Substrate dependencies +frame-support = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } +frame-system = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } +pallet-balances = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } +pallet-sudo = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } +sp-core = { default-features = false, features = ["full_crypto"], git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } +sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } +sp-std = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } + +# litentry +itp-node-api-metadata-provider = { path = "../../core-primitives/node-api/metadata-provider", default-features = false } +litentry-primitives = { path = "../../litentry/primitives", default-features = false } +pallet-parentchain = { path = "../../../pallets/parentchain", default-features = false } + +[dev-dependencies] +sp-keyring = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } + +[features] +default = ["std"] +evm = ["ita-sgx-runtime/evm"] +evm_std = ["evm", "ita-sgx-runtime/evm_std"] +sgx = [ + "sgx_tstd", + "itp-sgx-externalities/sgx", + "sp-io/sgx", + "itp-node-api/sgx", + # litentry + "litentry-primitives/sgx", + "itp-node-api-metadata-provider/sgx", +] +std = [ + # crates.io + "codec/std", + "log/std", + # local + "ita-sgx-runtime/std", + "itp-hashing/std", + "itp-sgx-externalities/std", + "itp-stf-interface/std", + "itp-storage/std", + "itp-types/std", + "itp-node-api/std", + "itp-node-api-metadata/std", + # substrate + "sp-core/std", + "pallet-balances/std", + "pallet-sudo/std", + "frame-system/std", + "frame-support/std", + "sp-runtime/std", + # scs/integritee + "pallet-parentchain/std", + "sp-io/std", + # litentry + "litentry-primitives/std", + "itp-node-api-metadata-provider/std", +] +test = [] diff --git a/bitacross-worker/app-libs/stf/src/evm_helpers.rs b/bitacross-worker/app-libs/stf/src/evm_helpers.rs new file mode 100644 index 0000000000..f0e96d1f87 --- /dev/null +++ b/bitacross-worker/app-libs/stf/src/evm_helpers.rs @@ -0,0 +1,66 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::helpers::{get_storage_double_map, get_storage_map}; +use itp_stf_primitives::types::Nonce; +use itp_storage::StorageHasher; +use itp_types::AccountId; +use sha3::{Digest, Keccak256}; +use sp_core::{H160, H256}; +use std::prelude::v1::*; + +pub fn get_evm_account_codes(evm_account: &H160) -> Option> { + get_storage_map("Evm", "AccountCodes", evm_account, &StorageHasher::Blake2_128Concat) +} + +pub fn get_evm_account_storages(evm_account: &H160, index: &H256) -> Option { + get_storage_double_map( + "Evm", + "AccountStorages", + evm_account, + &StorageHasher::Blake2_128Concat, + index, + &StorageHasher::Blake2_128Concat, + ) +} + +// FIXME: Once events are available, these addresses should be read from events. +pub fn evm_create_address(caller: H160, nonce: Nonce) -> H160 { + let mut stream = rlp::RlpStream::new_list(2); + stream.append(&caller); + stream.append(&nonce); + H256::from_slice(Keccak256::digest(&stream.out()).as_slice()).into() +} + +// FIXME: Once events are available, these addresses should be read from events. +pub fn evm_create2_address(caller: H160, salt: H256, code_hash: H256) -> H160 { + let mut hasher = Keccak256::new(); + hasher.update([0xff]); + hasher.update(&caller[..]); + hasher.update(&salt[..]); + hasher.update(&code_hash[..]); + H256::from_slice(hasher.finalize().as_slice()).into() +} + +pub fn create_code_hash(code: &[u8]) -> H256 { + H256::from_slice(Keccak256::digest(code).as_slice()) +} + +pub fn get_evm_account(account: &AccountId) -> H160 { + let mut evm_acc_slice: [u8; 20] = [0; 20]; + evm_acc_slice.copy_from_slice((<[u8; 32]>::from(account.clone())).get(0..20).unwrap()); + evm_acc_slice.into() +} diff --git a/bitacross-worker/app-libs/stf/src/getter.rs b/bitacross-worker/app-libs/stf/src/getter.rs new file mode 100644 index 0000000000..de8d466189 --- /dev/null +++ b/bitacross-worker/app-libs/stf/src/getter.rs @@ -0,0 +1,269 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 ita_sgx_runtime::System; +use itp_stf_interface::ExecuteGetter; +use itp_stf_primitives::{traits::GetterAuthorization, types::KeyPair}; +use itp_utils::{if_production_or, stringify::account_id_to_string}; +use litentry_primitives::{Identity, LitentryMultiSignature}; +use log::*; +use sp_std::vec; +use std::prelude::v1::*; + +#[cfg(feature = "evm")] +use ita_sgx_runtime::{AddressMapping, HashedAddressMapping}; + +#[cfg(feature = "evm")] +use crate::evm_helpers::{get_evm_account, get_evm_account_codes, get_evm_account_storages}; + +use itp_stf_primitives::traits::PoolTransactionValidation; +#[cfg(feature = "evm")] +use sp_core::{H160, H256}; +use sp_runtime::transaction_validity::{ + TransactionValidityError, UnknownTransaction, ValidTransaction, +}; + +#[cfg(not(feature = "production"))] +use crate::helpers::ALICE_ACCOUNTID32; + +#[derive(Encode, Decode, Clone, Debug, PartialEq, Eq)] +#[allow(non_camel_case_types)] +pub enum Getter { + #[codec(index = 0)] + public(PublicGetter), + #[codec(index = 1)] + trusted(TrustedGetterSigned), +} + +impl Default for Getter { + fn default() -> Self { + Getter::public(PublicGetter::some_value) + } +} +impl From for Getter { + fn from(item: PublicGetter) -> Self { + Getter::public(item) + } +} + +impl From for Getter { + fn from(item: TrustedGetterSigned) -> Self { + Getter::trusted(item) + } +} + +impl GetterAuthorization for Getter { + fn is_authorized(&self) -> bool { + match self { + Self::trusted(ref getter) => getter.verify_signature(), + Self::public(_) => true, + } + } +} + +impl PoolTransactionValidation for Getter { + fn validate(&self) -> Result { + match self { + Self::public(_) => + Err(TransactionValidityError::Unknown(UnknownTransaction::CannotLookup)), + Self::trusted(trusted_getter_signed) => Ok(ValidTransaction { + priority: 1 << 20, + requires: vec![], + provides: vec![trusted_getter_signed.signature.encode()], + longevity: 64, + propagate: true, + }), + } + } +} + +#[derive(Encode, Decode, Clone, Debug, PartialEq, Eq)] +#[allow(non_camel_case_types)] +pub enum PublicGetter { + #[codec(index = 0)] + some_value, + #[codec(index = 1)] + nonce(Identity), +} + +#[derive(Encode, Decode, Clone, Debug, PartialEq, Eq)] +#[allow(non_camel_case_types)] +pub enum TrustedGetter { + #[codec(index = 0)] + free_balance(Identity), + #[codec(index = 1)] + reserved_balance(Identity), + #[cfg(feature = "evm")] + #[codec(index = 2)] + evm_nonce(Identity), + #[cfg(feature = "evm")] + #[codec(index = 3)] + evm_account_codes(Identity, H160), + #[cfg(feature = "evm")] + #[codec(index = 4)] + evm_account_storages(Identity, H160, H256), +} + +impl TrustedGetter { + pub fn sender_identity(&self) -> &Identity { + match self { + TrustedGetter::free_balance(sender_identity) => sender_identity, + TrustedGetter::reserved_balance(sender_identity) => sender_identity, + #[cfg(feature = "evm")] + TrustedGetter::evm_nonce(sender_identity) => sender_identity, + #[cfg(feature = "evm")] + TrustedGetter::evm_account_codes(sender_identity, _) => sender_identity, + #[cfg(feature = "evm")] + TrustedGetter::evm_account_storages(sender_identity, ..) => sender_identity, + } + } + + pub fn sign(&self, pair: &KeyPair) -> TrustedGetterSigned { + let signature = pair.sign(self.encode().as_slice()); + TrustedGetterSigned { getter: self.clone(), signature } + } +} + +#[derive(Encode, Decode, Clone, Debug, PartialEq, Eq)] +pub struct TrustedGetterSigned { + pub getter: TrustedGetter, + pub signature: LitentryMultiSignature, +} + +impl TrustedGetterSigned { + pub fn new(getter: TrustedGetter, signature: LitentryMultiSignature) -> Self { + TrustedGetterSigned { getter, signature } + } + + pub fn verify_signature(&self) -> bool { + // in non-prod, we accept signature from Alice too + if_production_or!( + { + self.signature + .verify(self.getter.encode().as_slice(), self.getter.sender_identity()) + }, + { + self.signature + .verify(self.getter.encode().as_slice(), self.getter.sender_identity()) + || self + .signature + .verify(self.getter.encode().as_slice(), &ALICE_ACCOUNTID32.into()) + } + ) + } +} + +impl ExecuteGetter for Getter { + fn execute(self) -> Option> { + match self { + Getter::trusted(g) => g.execute(), + Getter::public(g) => g.execute(), + } + } + + fn get_storage_hashes_to_update(self) -> Vec> { + match self { + Getter::trusted(g) => g.get_storage_hashes_to_update(), + Getter::public(g) => g.get_storage_hashes_to_update(), + } + } +} + +impl ExecuteGetter for TrustedGetterSigned { + fn execute(self) -> Option> { + match self.getter { + TrustedGetter::free_balance(who) => + if let Some(account_id) = who.to_account_id() { + let info = System::account(&account_id); + debug!("TrustedGetter free_balance"); + debug!("AccountInfo for {} is {:?}", account_id_to_string(&who), info); + std::println!("⣿STF⣿ 🔍 TrustedGetter query: free balance for ⣿⣿⣿ is ⣿⣿⣿",); + Some(info.data.free.encode()) + } else { + None + }, + TrustedGetter::reserved_balance(who) => + if let Some(account_id) = who.to_account_id() { + let info = System::account(&account_id); + debug!("TrustedGetter reserved_balance"); + debug!("AccountInfo for {} is {:?}", account_id_to_string(&who), info); + debug!("Account reserved balance is {}", info.data.reserved); + Some(info.data.reserved.encode()) + } else { + None + }, + #[cfg(feature = "evm")] + TrustedGetter::evm_nonce(who) => + if let Some(account_id) = who.to_account_id() { + let evm_account = get_evm_account(&account_id); + let evm_account = HashedAddressMapping::into_account_id(evm_account); + let nonce = System::account_nonce(&evm_account); + debug!("TrustedGetter evm_nonce"); + debug!("Account nonce is {}", nonce); + Some(nonce.encode()) + } else { + None + }, + #[cfg(feature = "evm")] + TrustedGetter::evm_account_codes(_who, evm_account) => + // TODO: This probably needs some security check if who == evm_account (or assosciated) + if let Some(info) = get_evm_account_codes(&evm_account) { + debug!("TrustedGetter Evm Account Codes"); + debug!("AccountCodes for {} is {:?}", evm_account, info); + Some(info) // TOOD: encoded? + } else { + None + }, + #[cfg(feature = "evm")] + TrustedGetter::evm_account_storages(_who, evm_account, index) => + // TODO: This probably needs some security check if who == evm_account (or assosciated) + if let Some(value) = get_evm_account_storages(&evm_account, &index) { + debug!("TrustedGetter Evm Account Storages"); + debug!("AccountStorages for {} is {:?}", evm_account, value); + Some(value.encode()) + } else { + None + }, + } + } + + fn get_storage_hashes_to_update(self) -> Vec> { + Vec::new() + } +} + +impl ExecuteGetter for PublicGetter { + fn execute(self) -> Option> { + match self { + PublicGetter::some_value => Some(42u32.encode()), + PublicGetter::nonce(identity) => + if let Some(account_id) = identity.to_account_id() { + let nonce = System::account_nonce(&account_id); + debug!("PublicGetter nonce"); + debug!("Account nonce is {}", nonce); + Some(nonce.encode()) + } else { + None + }, + } + } + + fn get_storage_hashes_to_update(self) -> Vec> { + Vec::new() + } +} diff --git a/bitacross-worker/app-libs/stf/src/hash.rs b/bitacross-worker/app-libs/stf/src/hash.rs new file mode 100644 index 0000000000..f3cde9fa32 --- /dev/null +++ b/bitacross-worker/app-libs/stf/src/hash.rs @@ -0,0 +1,29 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::TrustedGetter; +use codec::Encode; +pub use itp_hashing::Hash; + +use itp_types::H256; +use sp_core::blake2_256; + +impl Hash for TrustedGetter { + fn hash(&self) -> H256 { + blake2_256(&self.encode()).into() + } +} diff --git a/bitacross-worker/app-libs/stf/src/helpers.rs b/bitacross-worker/app-libs/stf/src/helpers.rs new file mode 100644 index 0000000000..0c6fd39896 --- /dev/null +++ b/bitacross-worker/app-libs/stf/src/helpers.rs @@ -0,0 +1,175 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::ENCLAVE_ACCOUNT_KEY; +use codec::{Decode, Encode}; +use frame_support::ensure; +use hex_literal::hex; +use itp_stf_primitives::error::{StfError, StfResult}; +use itp_storage::{storage_double_map_key, storage_map_key, storage_value_key, StorageHasher}; +use itp_types::Index; +use itp_utils::stringify::account_id_to_string; +use litentry_primitives::{ErrorDetail, Identity, Web3ValidationData}; +use log::*; +use sp_core::blake2_256; +use sp_runtime::AccountId32; +use std::prelude::v1::*; + +pub const ALICE_ACCOUNTID32: AccountId32 = + AccountId32::new(hex!["d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d"]); + +pub fn get_storage_value( + storage_prefix: &'static str, + storage_key_name: &'static str, +) -> Option { + let key = storage_value_key(storage_prefix, storage_key_name); + get_storage_by_key_hash(key) +} + +pub fn get_storage_map( + storage_prefix: &'static str, + storage_key_name: &'static str, + map_key: &K, + hasher: &StorageHasher, +) -> Option { + let key = storage_map_key::(storage_prefix, storage_key_name, map_key, hasher); + get_storage_by_key_hash(key) +} + +pub fn get_storage_double_map( + storage_prefix: &'static str, + storage_key_name: &'static str, + first: &K, + first_hasher: &StorageHasher, + second: &Q, + second_hasher: &StorageHasher, +) -> Option { + let key = storage_double_map_key::( + storage_prefix, + storage_key_name, + first, + first_hasher, + second, + second_hasher, + ); + get_storage_by_key_hash(key) +} + +/// Get value in storage. +pub fn get_storage_by_key_hash(key: Vec) -> Option { + if let Some(value_encoded) = sp_io::storage::get(&key) { + if let Ok(value) = Decode::decode(&mut value_encoded.as_slice()) { + Some(value) + } else { + error!("could not decode state for key {:x?}", key); + None + } + } else { + info!("key not found in state {:x?}", key); + None + } +} + +/// Get the AccountInfo key where the account is stored. +pub fn account_key_hash(account: &AccountId) -> Vec { + storage_map_key("System", "Account", account, &StorageHasher::Blake2_128Concat) +} + +pub fn enclave_signer_account() -> AccountId { + get_storage_value("Sudo", ENCLAVE_ACCOUNT_KEY).expect("No enclave account") +} + +/// Ensures an account is a registered enclave account. +pub fn ensure_enclave_signer_account( + account: &AccountId, +) -> StfResult<()> { + let expected_enclave_account: AccountId = enclave_signer_account(); + if &expected_enclave_account == account { + Ok(()) + } else { + error!( + "Expected enclave account {}, but found {}", + account_id_to_string(&expected_enclave_account), + account_id_to_string(account) + ); + Err(StfError::RequireEnclaveSignerAccount) + } +} + +pub fn set_block_number(block_number: u32) { + sp_io::storage::set(&storage_value_key("System", "Number"), &block_number.encode()); +} + +pub fn ensure_self(signer: &AccountId, who: &AccountId) -> bool { + signer == who +} + +pub fn ensure_enclave_signer_or_self( + signer: &AccountId, + who: Option, +) -> bool { + match who { + Some(ref who) => + signer == &enclave_signer_account::() || ensure_self(signer, who), + None => false, + } +} + +#[cfg(not(feature = "production"))] +pub fn ensure_alice(signer: &AccountId32) -> bool { + signer == &ALICE_ACCOUNTID32 +} + +#[cfg(not(feature = "production"))] +pub fn ensure_enclave_signer_or_alice(signer: &AccountId32) -> bool { + signer == &enclave_signer_account::() || ensure_alice(signer) +} + +// verification message format: +// ``` +// blake2_256( + + ) +// ``` +// where <> means SCALE-encoded +// see https://github.com/litentry/litentry-parachain/issues/1739 and P-174 +pub fn get_expected_raw_message( + who: &Identity, + identity: &Identity, + sidechain_nonce: Index, +) -> Vec { + let mut payload = Vec::new(); + payload.append(&mut sidechain_nonce.encode()); + payload.append(&mut who.encode()); + payload.append(&mut identity.encode()); + blake2_256(payload.as_slice()).to_vec() +} + +pub fn verify_web3_identity( + identity: &Identity, + raw_msg: &[u8], + data: &Web3ValidationData, +) -> StfResult<()> { + ensure!( + raw_msg == data.message().as_slice(), + StfError::LinkIdentityFailed(ErrorDetail::UnexpectedMessage) + ); + + ensure!( + data.signature().verify(raw_msg, identity), + StfError::LinkIdentityFailed(ErrorDetail::VerifyWeb3SignatureFailed) + ); + + Ok(()) +} diff --git a/bitacross-worker/app-libs/stf/src/lib.rs b/bitacross-worker/app-libs/stf/src/lib.rs new file mode 100644 index 0000000000..894633b49f --- /dev/null +++ b/bitacross-worker/app-libs/stf/src/lib.rs @@ -0,0 +1,53 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +///////////////////////////////////////////////////////////////////////////// +#![feature(structural_match)] +#![feature(rustc_attrs)] +#![feature(core_intrinsics)] +#![feature(derive_eq)] +#![cfg_attr(all(not(target_env = "sgx"), not(feature = "std")), no_std)] +#![cfg_attr(target_env = "sgx", feature(rustc_private))] +#![allow(clippy::large_enum_variant)] +#![allow(clippy::result_large_err)] + +extern crate core; +#[cfg(all(not(feature = "std"), feature = "sgx"))] +extern crate sgx_tstd as std; + +pub use getter::*; +pub use stf_sgx_primitives::{types::*, Stf}; +pub use trusted_call::*; + +#[cfg(feature = "evm")] +pub mod evm_helpers; +pub mod getter; +pub mod hash; +pub mod helpers; +pub mod stf_sgx; +pub mod stf_sgx_primitives; +#[cfg(all(feature = "test", feature = "sgx"))] +pub mod stf_sgx_tests; +#[cfg(all(feature = "test", feature = "sgx"))] +pub mod test_genesis; +pub mod trusted_call; +pub mod trusted_call_result; + +pub(crate) const ENCLAVE_ACCOUNT_KEY: &str = "Enclave_Account_Key"; + +// fixme: this if a temporary hack only +pub const STF_TX_FEE: Balance = 100000000; diff --git a/bitacross-worker/app-libs/stf/src/stf_sgx.rs b/bitacross-worker/app-libs/stf/src/stf_sgx.rs new file mode 100644 index 0000000000..8af7217ec2 --- /dev/null +++ b/bitacross-worker/app-libs/stf/src/stf_sgx.rs @@ -0,0 +1,334 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 = "test")] +use crate::test_genesis::test_genesis_setup; +use crate::{helpers::enclave_signer_account, Stf, ENCLAVE_ACCOUNT_KEY}; +use codec::{Decode, Encode}; +use frame_support::traits::{OriginTrait, UnfilteredDispatchable}; +use ita_sgx_runtime::Executive; +use itp_node_api::metadata::{provider::AccessNodeMetadata, NodeMetadataTrait}; +use itp_sgx_externalities::SgxExternalitiesTrait; +use itp_stf_interface::{ + parentchain_pallet::ParentchainPalletInterface, + runtime_upgrade::RuntimeUpgradeInterface, + sudo_pallet::SudoPalletInterface, + system_pallet::{SystemPalletAccountInterface, SystemPalletEventInterface}, + ExecuteCall, ExecuteGetter, InitState, ShardVaultQuery, StateCallInterface, + StateGetterInterface, UpdateState, SHARD_VAULT_KEY, +}; +use itp_stf_primitives::{ + error::StfError, traits::TrustedCallVerification, types::ShardIdentifier, +}; +use itp_storage::storage_value_key; +use itp_types::{ + parentchain::{AccountId, ParentchainCall, ParentchainId}, + H256, +}; +use itp_utils::stringify::account_id_to_string; +use log::*; +use sp_runtime::traits::StaticLookup; +use std::{fmt::Debug, format, prelude::v1::*, sync::Arc, vec}; + +impl InitState for Stf +where + State: SgxExternalitiesTrait + Debug, + ::SgxExternalitiesType: core::default::Default, + Runtime: frame_system::Config + pallet_balances::Config, + <::Lookup as StaticLookup>::Source: + std::convert::From, + AccountId: Encode, +{ + fn init_state(enclave_account: AccountId) -> State { + debug!("initializing stf state, account id {}", account_id_to_string(&enclave_account)); + let mut state = State::new(Default::default()); + + state.execute_with(|| { + // Do not set genesis for pallets that are meant to be on-chain + // use get_storage_hashes_to_update instead. + + sp_io::storage::set(&storage_value_key("Balances", "TotalIssuance"), &11u128.encode()); + sp_io::storage::set(&storage_value_key("Balances", "CreationFee"), &1u128.encode()); + sp_io::storage::set(&storage_value_key("Balances", "TransferFee"), &1u128.encode()); + sp_io::storage::set( + &storage_value_key("Balances", "TransactionBaseFee"), + &1u128.encode(), + ); + sp_io::storage::set( + &storage_value_key("Balances", "TransactionByteFee"), + &1u128.encode(), + ); + sp_io::storage::set( + &storage_value_key("Balances", "ExistentialDeposit"), + &1u128.encode(), + ); + }); + + #[cfg(feature = "test")] + test_genesis_setup(&mut state); + + state.execute_with(|| { + sp_io::storage::set( + &storage_value_key("Sudo", ENCLAVE_ACCOUNT_KEY), + &enclave_account.encode(), + ); + + if let Err(e) = create_enclave_self_account::(enclave_account) { + error!("Failed to initialize the enclave signer account: {:?}", e); + } + }); + + trace!("Returning updated state: {:?}", state); + state + } +} + +impl + UpdateState::SgxExternalitiesDiffType> + for Stf +where + State: SgxExternalitiesTrait + Debug, + ::SgxExternalitiesType: core::default::Default, + ::SgxExternalitiesDiffType: + IntoIterator, Option>)>, +{ + fn apply_state_diff( + state: &mut State, + map_update: ::SgxExternalitiesDiffType, + ) { + state.execute_with(|| { + map_update.into_iter().for_each(|(k, v)| { + match v { + Some(value) => sp_io::storage::set(&k, &value), + None => sp_io::storage::clear(&k), + }; + }); + }); + } + + fn storage_hashes_to_update_on_block(parentchain_id: &ParentchainId) -> Vec> { + // Get all shards that are currently registered. + match parentchain_id { + ParentchainId::Litentry => vec![], // shards_key_hash() moved to stf_executor and is currently unused + ParentchainId::TargetA => vec![], + ParentchainId::TargetB => vec![], + } + } +} + +impl + StateCallInterface for Stf +where + TCS: PartialEq + + ExecuteCall + + Encode + + Decode + + Debug + + Clone + + Sync + + Send + + TrustedCallVerification, + State: SgxExternalitiesTrait + Debug, + NodeMetadataRepository: AccessNodeMetadata, + NodeMetadataRepository::MetadataType: NodeMetadataTrait, +{ + type Error = TCS::Error; + type Result = TCS::Result; + + fn execute_call( + state: &mut State, + shard: &ShardIdentifier, + call: TCS, + top_hash: H256, + calls: &mut Vec, + node_metadata_repo: Arc, + ) -> Result { + state.execute_with(|| call.execute(shard, top_hash, calls, node_metadata_repo)) + } +} + +impl StateGetterInterface for Stf +where + G: PartialEq + ExecuteGetter, + State: SgxExternalitiesTrait + Debug, +{ + fn execute_getter(state: &mut State, getter: G) -> Option> { + state.execute_with(|| getter.execute()) + } +} + +impl ShardVaultQuery for Stf +where + State: SgxExternalitiesTrait + Debug, +{ + fn get_vault(state: &mut State) -> Option { + state + .get(SHARD_VAULT_KEY.as_bytes()) + .and_then(|v| Decode::decode(&mut v.clone().as_slice()).ok()) + } +} + +impl SudoPalletInterface for Stf +where + State: SgxExternalitiesTrait, + Runtime: frame_system::Config + pallet_sudo::Config, +{ + type AccountId = Runtime::AccountId; + + fn get_root(state: &mut State) -> Self::AccountId { + state.execute_with(|| pallet_sudo::Pallet::::key().expect("No root account")) + } + + fn get_enclave_account(state: &mut State) -> Self::AccountId { + state.execute_with(enclave_signer_account::) + } +} + +impl SystemPalletAccountInterface + for Stf +where + State: SgxExternalitiesTrait, + Runtime: frame_system::Config, + AccountId: Encode, +{ + type Index = Runtime::Index; + type AccountData = Runtime::AccountData; + + fn get_account_nonce(state: &mut State, account: &AccountId) -> Self::Index { + state.execute_with(|| { + let nonce = frame_system::Pallet::::account_nonce(account); + debug!("Account {} nonce is {:?}", account_id_to_string(account), nonce); + nonce + }) + } + + fn get_account_data(state: &mut State, account: &AccountId) -> Self::AccountData { + state.execute_with(|| frame_system::Pallet::::account(account).data) + } +} + +impl SystemPalletEventInterface for Stf +where + State: SgxExternalitiesTrait, + Runtime: frame_system::Config, +{ + type EventRecord = frame_system::EventRecord; + type EventIndex = u32; // For some reason this is not a pub type in frame_system + type BlockNumber = Runtime::BlockNumber; + type Hash = Runtime::Hash; + + fn get_events(state: &mut State) -> Vec> { + // Fixme: Not nice to have to call collect here, but we can't use impl Iterator<..> + // in trait method return types yet, see: + // https://rust-lang.github.io/impl-trait-initiative/RFCs/rpit-in-traits.html + state.execute_with(|| frame_system::Pallet::::read_events_no_consensus().collect()) + } + + fn get_event_count(state: &mut State) -> Self::EventIndex { + state.execute_with(|| frame_system::Pallet::::event_count()) + } + + fn get_event_topics( + state: &mut State, + topic: &Self::Hash, + ) -> Vec<(Self::BlockNumber, Self::EventIndex)> { + state.execute_with(|| frame_system::Pallet::::event_topics(topic)) + } + + fn reset_events(state: &mut State) { + state.execute_with(|| frame_system::Pallet::::reset_events()) + } +} + +impl ParentchainPalletInterface + for Stf +where + State: SgxExternalitiesTrait, + Runtime: frame_system::Config
+ pallet_parentchain::Config, +{ + type Error = StfError; + + fn update_parentchain_block( + state: &mut State, + header: ParentchainHeader, + ) -> Result<(), Self::Error> { + state.execute_with(|| { + pallet_parentchain::Call::::set_block { header } + .dispatch_bypass_filter(Runtime::RuntimeOrigin::root()) + .map_err(|e| { + Self::Error::Dispatch(format!("Update parentchain block error: {:?}", e.error)) + }) + })?; + Ok(()) + } +} + +impl RuntimeUpgradeInterface for Stf +where + State: SgxExternalitiesTrait, + Runtime: frame_system::Config, +{ + type Error = StfError; + + fn on_runtime_upgrade(state: &mut State) -> Result<(), Self::Error> { + // Returns if the runtime was upgraded since the last time this function was called. + let runtime_upgraded = || -> bool { + let last = frame_system::LastRuntimeUpgrade::::get(); + let current = + <::Version as frame_support::traits::Get<_>>::get( + ); + + if last.as_ref().map(|v| v.was_upgraded(¤t)).unwrap_or(true) { + frame_system::LastRuntimeUpgrade::::put( + frame_system::LastRuntimeUpgradeInfo::from(current.clone()), + ); + debug!("Do some migrations, last: {:?}, current: {:?}", last, current.spec_version); + true + } else { + false + } + }; + + state.execute_with(|| { + if runtime_upgraded() { + Executive::execute_on_runtime_upgrade(); + } + }); + Ok(()) + } +} + +/// Creates valid enclave account with a balance that is above the existential deposit. +/// !! Requires a root to be set. +fn create_enclave_self_account( + enclave_account: AccountId, +) -> Result<(), StfError> +where + Runtime: frame_system::Config + pallet_balances::Config, + <::Lookup as StaticLookup>::Source: From, + Runtime::Balance: From, +{ + pallet_balances::Call::::force_set_balance { + who: enclave_account.into(), + new_free: 1000.into(), + } + .dispatch_bypass_filter(Runtime::RuntimeOrigin::root()) + .map_err(|e| { + StfError::Dispatch(format!("Set Balance for enclave signer account error: {:?}", e.error)) + }) + .map(|_| ()) +} diff --git a/bitacross-worker/app-libs/stf/src/stf_sgx_primitives.rs b/bitacross-worker/app-libs/stf/src/stf_sgx_primitives.rs new file mode 100644 index 0000000000..8ccfccc787 --- /dev/null +++ b/bitacross-worker/app-libs/stf/src/stf_sgx_primitives.rs @@ -0,0 +1,30 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::marker::PhantomData; + +pub mod types { + pub use itp_types::{AccountData, AccountInfo, BlockNumber, Header as ParentchainHeader}; + + pub type State = itp_sgx_externalities::SgxExternalities; + pub type StateType = itp_sgx_externalities::SgxExternalitiesType; + pub type StateDiffType = itp_sgx_externalities::SgxExternalitiesDiffType; +} + +pub struct Stf { + phantom_data: PhantomData<(TCS, G, State, Runtime)>, +} diff --git a/bitacross-worker/app-libs/stf/src/stf_sgx_tests.rs b/bitacross-worker/app-libs/stf/src/stf_sgx_tests.rs new file mode 100644 index 0000000000..7c3a6e4b7c --- /dev/null +++ b/bitacross-worker/app-libs/stf/src/stf_sgx_tests.rs @@ -0,0 +1,82 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{Getter, State, Stf, TrustedCall, TrustedCallSigned}; +use ita_sgx_runtime::Runtime; +use itp_node_api::metadata::{metadata_mocks::NodeMetadataMock, provider::NodeMetadataRepository}; +use itp_stf_interface::{ + sudo_pallet::SudoPalletInterface, system_pallet::SystemPalletAccountInterface, InitState, + StateCallInterface, +}; +use itp_stf_primitives::types::{AccountId, ShardIdentifier}; +use litentry_primitives::LitentryMultiSignature; +use sp_core::{ + ed25519::{Pair as Ed25519Pair, Signature as Ed25519Signature}, + Pair, +}; +use std::{sync::Arc, vec::Vec}; + +pub type StfState = Stf; + +pub fn enclave_account_initialization_works() { + let enclave_account = AccountId::new([2u8; 32]); + let mut state = StfState::init_state(enclave_account.clone()); + let _root = StfState::get_root(&mut state); + let account_data = StfState::get_account_data(&mut state, &enclave_account); + + assert_eq!(0, StfState::get_account_nonce(&mut state, &enclave_account)); + assert_eq!(enclave_account, StfState::get_enclave_account(&mut state)); + assert_eq!(1000, account_data.free); +} + +pub fn shield_funds_increments_signer_account_nonce() { + let enclave_call_signer = Ed25519Pair::from_seed(b"14672678901234567890123456789012"); + let enclave_signer_account_id: AccountId = enclave_call_signer.public().into(); + let mut state = StfState::init_state(enclave_signer_account_id.clone()); + + let shield_funds_call = TrustedCallSigned::new( + TrustedCall::balance_shield( + enclave_call_signer.public().into(), + AccountId::new([1u8; 32]), + 500u128, + ), + 0, + LitentryMultiSignature::Ed25519(Ed25519Signature([0u8; 64])), + ); + + let repo = Arc::new(NodeMetadataRepository::new(NodeMetadataMock::new())); + let shard = ShardIdentifier::default(); + StfState::execute_call( + &mut state, + &shard, + shield_funds_call, + Default::default(), + &mut Vec::new(), + repo, + ) + .unwrap(); + assert_eq!(1, StfState::get_account_nonce(&mut state, &enclave_signer_account_id)); +} + +pub fn test_root_account_exists_after_initialization() { + let enclave_account = AccountId::new([2u8; 32]); + let mut state = StfState::init_state(enclave_account); + let root_account = StfState::get_root(&mut state); + + let account_data = StfState::get_account_data(&mut state, &root_account); + assert!(account_data.free > 0); +} diff --git a/bitacross-worker/app-libs/stf/src/test_genesis.rs b/bitacross-worker/app-libs/stf/src/test_genesis.rs new file mode 100644 index 0000000000..161dec8e5e --- /dev/null +++ b/bitacross-worker/app-libs/stf/src/test_genesis.rs @@ -0,0 +1,114 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::traits::UnfilteredDispatchable; +use ita_sgx_runtime::{Balance, Runtime, System}; +use itp_sgx_externalities::SgxExternalitiesTrait; +use itp_stf_primitives::error::StfError; +use itp_storage::storage_value_key; +use log::*; +use sgx_tstd as std; +use sp_core::{crypto::AccountId32, ed25519, Pair}; +use sp_runtime::MultiAddress; +use std::{format, vec, vec::Vec}; + +#[cfg(feature = "evm")] +use ita_sgx_runtime::{AddressMapping, HashedAddressMapping}; + +#[cfg(feature = "evm")] +use crate::evm_helpers::get_evm_account; + +type Seed = [u8; 32]; + +const ALICE_ENCODED: Seed = [ + 212, 53, 147, 199, 21, 253, 211, 28, 97, 20, 26, 189, 4, 169, 159, 214, 130, 44, 133, 88, 133, + 76, 205, 227, 154, 86, 132, 231, 165, 109, 162, 125, +]; + +const ENDOWED_SEED: Seed = *b"12345678901234567890123456789012"; +const SECOND_ENDOWED_SEED: Seed = *b"22345678901234567890123456789012"; +const UNENDOWED_SEED: Seed = *b"92345678901234567890123456789012"; + +const ALICE_FUNDS: Balance = 10_000_000_000_000_000; +pub const ENDOWED_ACC_FUNDS: Balance = 2_000_000_000_000; +pub const SECOND_ENDOWED_ACC_FUNDS: Balance = 1_000_000_000_000; + +pub fn endowed_account() -> ed25519::Pair { + ed25519::Pair::from_seed(&ENDOWED_SEED) +} +pub fn second_endowed_account() -> ed25519::Pair { + ed25519::Pair::from_seed(&SECOND_ENDOWED_SEED) +} + +pub fn unendowed_account() -> ed25519::Pair { + ed25519::Pair::from_seed(&UNENDOWED_SEED) +} + +pub fn test_genesis_setup(state: &mut impl SgxExternalitiesTrait) { + // set alice sudo account + set_sudo_account(state, &ALICE_ENCODED); + trace!("Set new sudo account: {:?}", &ALICE_ENCODED); + + let mut endowees: Vec<(AccountId32, Balance)> = vec![ + (endowed_account().public().into(), ENDOWED_ACC_FUNDS), + (second_endowed_account().public().into(), SECOND_ENDOWED_ACC_FUNDS), + (ALICE_ENCODED.into(), ALICE_FUNDS), + ]; + + append_funded_alice_evm_account(&mut endowees); + + endow(state, endowees); +} + +#[cfg(feature = "evm")] +fn append_funded_alice_evm_account(endowees: &mut Vec<(AccountId32, Balance)>) { + let alice_evm = get_evm_account(&ALICE_ENCODED.into()); + let alice_evm_substrate_version = HashedAddressMapping::into_account_id(alice_evm); + let mut other: Vec<(AccountId32, Balance)> = vec![(alice_evm_substrate_version, ALICE_FUNDS)]; + endowees.append(other.as_mut()); +} + +#[cfg(not(feature = "evm"))] +fn append_funded_alice_evm_account(_: &mut Vec<(AccountId32, Balance)>) {} + +fn set_sudo_account(state: &mut impl SgxExternalitiesTrait, account_encoded: &[u8]) { + state.execute_with(|| { + sp_io::storage::set(&storage_value_key("Sudo", "Key"), account_encoded); + }) +} + +pub fn endow( + state: &mut impl SgxExternalitiesTrait, + endowees: impl IntoIterator, +) { + state.execute_with(|| { + for e in endowees.into_iter() { + let account = e.0; + + ita_sgx_runtime::BalancesCall::::force_set_balance { + who: MultiAddress::Id(account.clone()), + new_free: e.1, + } + .dispatch_bypass_filter(ita_sgx_runtime::RuntimeOrigin::root()) + .map_err(|e| StfError::Dispatch(format!("Balance Set Balance error: {:?}", e.error))) + .unwrap(); + + let print_public: [u8; 32] = account.clone().into(); + let account_info = System::account(&&print_public.into()); + debug!("{:?} balance is {}", print_public, account_info.data.free); + } + }); +} diff --git a/bitacross-worker/app-libs/stf/src/trusted_call.rs b/bitacross-worker/app-libs/stf/src/trusted_call.rs new file mode 100644 index 0000000000..2ebeb97741 --- /dev/null +++ b/bitacross-worker/app-libs/stf/src/trusted_call.rs @@ -0,0 +1,686 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 = "evm")] +use sp_core::{H160, U256}; + +#[cfg(feature = "evm")] +use std::vec::Vec; + +#[cfg(feature = "evm")] +use crate::evm_helpers::{create_code_hash, evm_create2_address, evm_create_address}; +use crate::{ + helpers::{enclave_signer_account, ensure_enclave_signer_account, get_storage_by_key_hash}, + trusted_call_result::TrustedCallResult, + Getter, +}; +use codec::{Compact, Decode, Encode}; +use frame_support::{ensure, traits::UnfilteredDispatchable}; +#[cfg(feature = "evm")] +use ita_sgx_runtime::{AddressMapping, HashedAddressMapping}; +pub use ita_sgx_runtime::{Balance, Index, Runtime, System}; +use itp_node_api::metadata::{provider::AccessNodeMetadata, NodeMetadataTrait}; +use itp_node_api_metadata::{ + pallet_balances::BalancesCallIndexes, pallet_imp::IMPCallIndexes, + pallet_proxy::ProxyCallIndexes, pallet_teerex::TeerexCallIndexes, pallet_vcmp::VCMPCallIndexes, +}; +use itp_stf_interface::{ExecuteCall, SHARD_VAULT_KEY}; +pub use itp_stf_primitives::{ + error::{StfError, StfResult}, + traits::{TrustedCallSigning, TrustedCallVerification}, + types::{AccountId, KeyPair, ShardIdentifier, TrustedOperation}, +}; +use itp_types::{ + parentchain::{ParentchainCall, ProxyType}, + Address, +}; +pub use itp_types::{OpaqueCall, H256}; +use itp_utils::stringify::account_id_to_string; +pub use litentry_primitives::{ + aes_encrypt_default, all_evm_web3networks, all_substrate_web3networks, AesOutput, Assertion, + ErrorDetail, IMPError, Identity, LitentryMultiSignature, ParentchainBlockNumber, RequestAesKey, + RequestAesKeyNonce, VCMPError, ValidationData, Web3Network, +}; +use log::*; +use sp_core::{ + crypto::{AccountId32, UncheckedFrom}, + ed25519, +}; +use sp_io::hashing::blake2_256; +use sp_runtime::MultiAddress; +use std::{format, prelude::v1::*, sync::Arc}; + +#[derive(Encode, Decode, Clone, Debug, PartialEq, Eq)] +#[allow(non_camel_case_types)] +pub enum TrustedCall { + // original integritee trusted calls, starting from index 50 + #[codec(index = 50)] + noop(Identity), + #[codec(index = 51)] + balance_set_balance(Identity, AccountId, Balance, Balance), + #[codec(index = 52)] + balance_transfer(Identity, AccountId, Balance), + #[codec(index = 53)] + balance_unshield(Identity, AccountId, Balance, ShardIdentifier), // (AccountIncognito, BeneficiaryPublicAccount, Amount, Shard) + #[codec(index = 54)] + balance_shield(Identity, AccountId, Balance), // (Root, AccountIncognito, Amount) + #[cfg(feature = "evm")] + #[codec(index = 55)] + evm_withdraw(Identity, H160, Balance), // (Origin, Address EVM Account, Value) + // (Origin, Source, Target, Input, Value, Gas limit, Max fee per gas, Max priority fee per gas, Nonce, Access list) + #[cfg(feature = "evm")] + #[codec(index = 56)] + evm_call( + Identity, + H160, + H160, + Vec, + U256, + u64, + U256, + Option, + Option, + Vec<(H160, Vec)>, + ), + // (Origin, Source, Init, Value, Gas limit, Max fee per gas, Max priority fee per gas, Nonce, Access list) + #[cfg(feature = "evm")] + #[codec(index = 57)] + evm_create( + Identity, + H160, + Vec, + U256, + u64, + U256, + Option, + Option, + Vec<(H160, Vec)>, + ), + // (Origin, Source, Init, Salt, Value, Gas limit, Max fee per gas, Max priority fee per gas, Nonce, Access list) + #[cfg(feature = "evm")] + #[codec(index = 58)] + evm_create2( + Identity, + H160, + Vec, + H256, + U256, + u64, + U256, + Option, + Option, + Vec<(H160, Vec)>, + ), +} + +impl TrustedCall { + pub fn sender_identity(&self) -> &Identity { + match self { + Self::noop(sender_identity) => sender_identity, + Self::balance_set_balance(sender_identity, ..) => sender_identity, + Self::balance_transfer(sender_identity, ..) => sender_identity, + Self::balance_unshield(sender_identity, ..) => sender_identity, + Self::balance_shield(sender_identity, ..) => sender_identity, + #[cfg(feature = "evm")] + Self::evm_withdraw(sender_identity, ..) => sender_identity, + #[cfg(feature = "evm")] + Self::evm_call(sender_identity, ..) => sender_identity, + #[cfg(feature = "evm")] + Self::evm_create(sender_identity, ..) => sender_identity, + #[cfg(feature = "evm")] + Self::evm_create2(sender_identity, ..) => sender_identity, + } + } +} + +impl TrustedCallSigning for TrustedCall { + fn sign( + &self, + pair: &KeyPair, + nonce: Index, + mrenclave: &[u8; 32], + shard: &ShardIdentifier, + ) -> TrustedCallSigned { + let mut payload = self.encode(); + payload.append(&mut nonce.encode()); + payload.append(&mut mrenclave.encode()); + payload.append(&mut shard.encode()); + + TrustedCallSigned { call: self.clone(), nonce, signature: pair.sign(payload.as_slice()) } + } +} + +#[derive(Encode, Decode, Clone, Debug, PartialEq, Eq)] +pub struct TrustedCallSigned { + pub call: TrustedCall, + pub nonce: Index, + pub signature: LitentryMultiSignature, +} + +impl TrustedCallSigned { + pub fn new(call: TrustedCall, nonce: Index, signature: LitentryMultiSignature) -> Self { + TrustedCallSigned { call, nonce, signature } + } + + pub fn into_trusted_operation( + self, + direct: bool, + ) -> TrustedOperation { + match direct { + true => TrustedOperation::direct_call(self), + false => TrustedOperation::indirect_call(self), + } + } +} + +impl Default for TrustedCallSigned { + fn default() -> Self { + Self { + call: TrustedCall::noop(AccountId32::unchecked_from([0u8; 32].into()).into()), + nonce: 0, + signature: LitentryMultiSignature::Ed25519(ed25519::Signature::unchecked_from( + [0u8; 64], + )), + } + } +} +impl TrustedCallVerification for TrustedCallSigned { + fn sender_identity(&self) -> &Identity { + self.call.sender_identity() + } + + fn nonce(&self) -> Index { + self.nonce + } + + fn verify_signature(&self, mrenclave: &[u8; 32], shard: &ShardIdentifier) -> bool { + let mut payload = self.call.encode(); + payload.append(&mut self.nonce.encode()); + payload.append(&mut mrenclave.encode()); + payload.append(&mut shard.encode()); + + self.signature.verify(payload.as_slice(), self.call.sender_identity()) + } +} + +impl ExecuteCall for TrustedCallSigned +where + NodeMetadataRepository: AccessNodeMetadata, + NodeMetadataRepository::MetadataType: NodeMetadataTrait, +{ + type Error = StfError; + type Result = TrustedCallResult; + + // TODO(Kai@litentry): + // If this function returns Err(), it will feed the executor with Ok(ExecutedOperation::failed()), + // which will remove the failed op from its **own** top pool while preventing it from being included + // in a sidechain block - see `execute_trusted_call_on_stf`. + // + // As a result, when other workers import sidechain blocks, they will treat the op as + // "not yet executed" (before it's not recorded in the sidechain block) and try to execute it again from + // its own top pool (if the op is added to the top pool upon e.g. parentchain block import). + // + // The execution will most likely fail again. However, the state could have been changed already by applying + // the state diff from the imported sidechain block. This could cause an inconsistent/mismatching state, + // for example, the nonce. See the nonce handling below: we increased the nonce no matter the STF is executed + // successfully or not. + // + // This is probably the reason why the nonce-handling test in `demo_shielding_unshielding.sh` sometimes fails. + // + // Update: + // see discussion in https://github.com/integritee-network/worker/issues/1232 + // my current thoughts are: + // - we should return Err() if the STF execution fails, the parentchain effect will get applied regardless + // - the failed top should be removed from the pool + // - however, the failed top hash needs to be included in the sidechain block (still TODO) + // + // Almost every (Litentry) trusted call has a `H256` as parameter, this is used as the request identifier. + // It should be generated by the client (requester), and checked against when getting the response. + // It might seem redundant for direct invocation (DI) as the response is synchronous, however, we do need it + // when the request is handled asynchronously interanlly, which leads to streamed responses. Without it, it's + // impossible to pair the request and response. `top_hash` won't suffice as you can't know all hashes from + // client side beforehand (e.g. those trusted calls signed by enclave signer). + // + // TODO: + // - shall we add `req_ext_hash` in RpcReturnValue and use it to find streamed trustedCalls? + // - show error details for "Invalid" synchronous responses + fn execute( + self, + _shard: &ShardIdentifier, + _top_hash: H256, + calls: &mut Vec, + node_metadata_repo: Arc, + ) -> Result { + let sender = self.call.sender_identity().clone(); + let call_hash = blake2_256(&self.call.encode()); + let account_id: AccountId = sender.to_account_id().ok_or(Self::Error::InvalidAccount)?; + let system_nonce = System::account_nonce(&account_id); + ensure!(self.nonce == system_nonce, Self::Error::InvalidNonce(self.nonce, system_nonce)); + + // Increment the nonce no matter if the call succeeds or fails. + // We consider the call "valid" once it reaches here (= it entered the tx pool) + System::inc_account_nonce(&account_id); + + // TODO: maybe we can further simplify this by effacing the duplicate code + match self.call { + TrustedCall::noop(who) => { + debug!("noop called by {}", account_id_to_string(&who),); + Ok(TrustedCallResult::Empty) + }, + TrustedCall::balance_set_balance(root, who, free_balance, reserved_balance) => { + let root_account_id: AccountId = + root.to_account_id().ok_or(Self::Error::InvalidAccount)?; + ensure!( + is_root::(&root_account_id), + Self::Error::MissingPrivileges(root_account_id) + ); + debug!( + "balance_set_balance({}, {}, {})", + account_id_to_string(&who), + free_balance, + reserved_balance + ); + ita_sgx_runtime::BalancesCall::::force_set_balance { + who: MultiAddress::Id(who), + new_free: free_balance, + } + .dispatch_bypass_filter(ita_sgx_runtime::RuntimeOrigin::root()) + .map_err(|e| { + Self::Error::Dispatch(format!("Balance Set Balance error: {:?}", e.error)) + })?; + // This explicit Error type is somehow still needed, otherwise the compiler complains + // multiple `impl`s satisfying `StfError: std::convert::From<_>` + // note: and another `impl` found in the `core` crate: `impl std::convert::From for T;` + // the impl From<..> for StfError conflicts with the standard convert + // + // Alternatively, removing the customised "impl From<..> for StfError" and use map_err directly + // would also work + Ok(TrustedCallResult::Empty) + }, + TrustedCall::balance_transfer(from, to, value) => { + let origin = ita_sgx_runtime::RuntimeOrigin::signed( + from.to_account_id().ok_or(Self::Error::InvalidAccount)?, + ); + std::println!("⣿STF⣿ 🔄 balance_transfer from ⣿⣿⣿ to ⣿⣿⣿ amount ⣿⣿⣿"); + // endow fee to enclave (self) + let fee_recipient: AccountId = enclave_signer_account(); + // fixme: apply fees through standard frame process and tune it + let fee = crate::STF_TX_FEE; + info!( + "from {}, to {}, amount {}, fee {}", + account_id_to_string(&from), + account_id_to_string(&to), + value, + fee + ); + ita_sgx_runtime::BalancesCall::::transfer { + dest: MultiAddress::Id(fee_recipient), + value: fee, + } + .dispatch_bypass_filter(origin.clone()) + .map_err(|e| { + Self::Error::Dispatch(format!("Balance Transfer error: {:?}", e.error)) + })?; + ita_sgx_runtime::BalancesCall::::transfer { + dest: MultiAddress::Id(to), + value, + } + .dispatch_bypass_filter(origin) + .map_err(|e| { + Self::Error::Dispatch(format!("Balance Transfer error: {:?}", e.error)) + })?; + Ok(TrustedCallResult::Empty) + }, + TrustedCall::balance_unshield(account_incognito, beneficiary, value, shard) => { + std::println!( + "⣿STF⣿ 🛡👐 balance_unshield from ⣿⣿⣿ to {}, amount {}", + account_id_to_string(&beneficiary), + value + ); + // endow fee to enclave (self) + let fee_recipient: AccountId = enclave_signer_account(); + // fixme: apply fees through standard frame process and tune it. has to be at least two L1 transfer's fees + let fee = crate::STF_TX_FEE * 3; + + info!( + "balance_unshield(from (L2): {}, to (L1): {}, amount {} (+fee: {}), shard {})", + account_id_to_string(&account_incognito), + account_id_to_string(&beneficiary), + value, + fee, + shard + ); + + let origin = ita_sgx_runtime::RuntimeOrigin::signed( + account_incognito.to_account_id().ok_or(StfError::InvalidAccount)?, + ); + ita_sgx_runtime::BalancesCall::::transfer { + dest: MultiAddress::Id(fee_recipient), + value: fee, + } + .dispatch_bypass_filter(origin) + .map_err(|e| { + Self::Error::Dispatch(format!("Balance Unshielding error: {:?}", e.error)) + })?; + burn_funds( + account_incognito.to_account_id().ok_or(StfError::InvalidAccount)?, + value, + )?; + + let vault_pubkey: [u8; 32] = get_storage_by_key_hash(SHARD_VAULT_KEY.into()) + .ok_or_else(|| { + StfError::Dispatch("shard vault key hasn't been set".to_string()) + })?; + let vault_address = Address::from(AccountId::from(vault_pubkey)); + let vault_transfer_call = OpaqueCall::from_tuple(&( + node_metadata_repo + .get_from_metadata(|m| m.transfer_keep_alive_call_indexes()) + .map_err(|_| StfError::InvalidMetadata)? + .map_err(|_| StfError::InvalidMetadata)?, + Address::from(beneficiary), + Compact(value), + )); + let proxy_call = OpaqueCall::from_tuple(&( + node_metadata_repo + .get_from_metadata(|m| m.proxy_call_indexes()) + .map_err(|_| StfError::InvalidMetadata)? + .map_err(|_| StfError::InvalidMetadata)?, + vault_address, + None::, + vault_transfer_call, + )); + calls.push(ParentchainCall::TargetA(proxy_call)); + Ok(TrustedCallResult::Empty) + }, + TrustedCall::balance_shield(enclave_account, who, value) => { + let account_id: AccountId32 = + enclave_account.to_account_id().ok_or(Self::Error::InvalidAccount)?; + ensure_enclave_signer_account(&account_id)?; + debug!("balance_shield({}, {})", account_id_to_string(&who), value); + shield_funds(who, value)?; + + // Send proof of execution on chain. + calls.push(ParentchainCall::Litentry(OpaqueCall::from_tuple(&( + node_metadata_repo + .get_from_metadata(|m| m.publish_hash_call_indexes()) + .map_err(|_| StfError::InvalidMetadata)? + .map_err(|_| StfError::InvalidMetadata)?, + call_hash, + Vec::::new(), + b"shielded some funds!".to_vec(), + )))); + Ok(TrustedCallResult::Empty) + }, + #[cfg(feature = "evm")] + TrustedCall::evm_withdraw(from, address, value) => { + debug!("evm_withdraw({}, {}, {})", account_id_to_string(&from), address, value); + ita_sgx_runtime::EvmCall::::withdraw { address, value } + .dispatch_bypass_filter(ita_sgx_runtime::RuntimeOrigin::signed( + from.to_account_id().ok_or(Self::Error::InvalidAccount)?, + )) + .map_err(|e| { + Self::Error::Dispatch(format!("Evm Withdraw error: {:?}", e.error)) + })?; + Ok(TrustedCallResult::Empty) + }, + #[cfg(feature = "evm")] + TrustedCall::evm_call( + from, + source, + target, + input, + value, + gas_limit, + max_fee_per_gas, + max_priority_fee_per_gas, + nonce, + access_list, + ) => { + debug!( + "evm_call(from: {}, source: {}, target: {})", + account_id_to_string(&from), + source, + target + ); + ita_sgx_runtime::EvmCall::::call { + source, + target, + input, + value, + gas_limit, + max_fee_per_gas, + max_priority_fee_per_gas, + nonce, + access_list, + } + .dispatch_bypass_filter(ita_sgx_runtime::RuntimeOrigin::signed( + from.to_account_id().ok_or(Self::Error::InvalidAccount)?, + )) + .map_err(|e| Self::Error::Dispatch(format!("Evm Call error: {:?}", e.error)))?; + Ok(TrustedCallResult::Empty) + }, + #[cfg(feature = "evm")] + TrustedCall::evm_create( + from, + source, + init, + value, + gas_limit, + max_fee_per_gas, + max_priority_fee_per_gas, + nonce, + access_list, + ) => { + debug!( + "evm_create(from: {}, source: {}, value: {})", + account_id_to_string(&from), + source, + value + ); + let nonce_evm_account = + System::account_nonce(&HashedAddressMapping::into_account_id(source)); + ita_sgx_runtime::EvmCall::::create { + source, + init, + value, + gas_limit, + max_fee_per_gas, + max_priority_fee_per_gas, + nonce, + access_list, + } + .dispatch_bypass_filter(ita_sgx_runtime::RuntimeOrigin::signed( + from.to_account_id().ok_or(Self::Error::InvalidAccount)?, + )) + .map_err(|e| Self::Error::Dispatch(format!("Evm Create error: {:?}", e.error)))?; + let contract_address = evm_create_address(source, nonce_evm_account); + info!("Trying to create evm contract with address {:?}", contract_address); + Ok(TrustedCallResult::Empty) + }, + #[cfg(feature = "evm")] + TrustedCall::evm_create2( + from, + source, + init, + salt, + value, + gas_limit, + max_fee_per_gas, + max_priority_fee_per_gas, + nonce, + access_list, + ) => { + debug!( + "evm_create2(from: {}, source: {}, value: {})", + account_id_to_string(&from), + source, + value + ); + let code_hash = create_code_hash(&init); + ita_sgx_runtime::EvmCall::::create2 { + source, + init, + salt, + value, + gas_limit, + max_fee_per_gas, + max_priority_fee_per_gas, + nonce, + access_list, + } + .dispatch_bypass_filter(ita_sgx_runtime::RuntimeOrigin::signed( + from.to_account_id().ok_or(Self::Error::InvalidAccount)?, + )) + .map_err(|e| Self::Error::Dispatch(format!("Evm Create2 error: {:?}", e.error)))?; + let contract_address = evm_create2_address(source, salt, code_hash); + info!("Trying to create evm contract with address {:?}", contract_address); + Ok(TrustedCallResult::Empty) + }, + } + } + + fn get_storage_hashes_to_update(self) -> Vec> { + debug!("No storage updates needed..."); + Vec::new() + } +} + +fn burn_funds(account: AccountId, amount: u128) -> Result<(), StfError> { + let account_info = System::account(&account); + if account_info.data.free < amount { + return Err(StfError::MissingFunds) + } + + ita_sgx_runtime::BalancesCall::::force_set_balance { + who: MultiAddress::Id(account), + new_free: account_info.data.free - amount, + } + .dispatch_bypass_filter(ita_sgx_runtime::RuntimeOrigin::root()) + .map_err(|e| StfError::Dispatch(format!("Burn funds error: {:?}", e.error)))?; + Ok(()) +} + +fn shield_funds(account: AccountId, amount: u128) -> Result<(), StfError> { + //fixme: make fee configurable and send fee to vault account on L2 + let fee = amount / 571; // approx 0.175% + + // endow fee to enclave (self) + let fee_recipient: AccountId = enclave_signer_account(); + + let account_info = System::account(&fee_recipient); + ita_sgx_runtime::BalancesCall::::force_set_balance { + who: MultiAddress::Id(fee_recipient), + new_free: account_info.data.free + fee, + } + .dispatch_bypass_filter(ita_sgx_runtime::RuntimeOrigin::root()) + .map_err(|e| StfError::Dispatch(format!("Shield funds error: {:?}", e.error)))?; + + // endow shieding amount - fee to beneficiary + let account_info = System::account(&account); + ita_sgx_runtime::BalancesCall::::force_set_balance { + who: MultiAddress::Id(account), + new_free: account_info.data.free + amount - fee, + } + .dispatch_bypass_filter(ita_sgx_runtime::RuntimeOrigin::root()) + .map_err(|e| StfError::Dispatch(format!("Shield funds error: {:?}", e.error)))?; + + Ok(()) +} + +pub(crate) fn is_root(account: &AccountId) -> bool +where + Runtime: frame_system::Config + pallet_sudo::Config, + AccountId: PartialEq, +{ + pallet_sudo::Pallet::::key().map_or(false, |k| account == &k) +} + +pub fn push_call_imp_some_error( + calls: &mut Vec, + node_metadata_repo: Arc, + identity: Option, + e: IMPError, + req_ext_hash: H256, +) where + NodeMetadataRepository: AccessNodeMetadata, + NodeMetadataRepository::MetadataType: NodeMetadataTrait, +{ + debug!("pushing IMP::some_error call ..."); + // TODO: anyway to simplify this? `and_then` won't be applicable here + match node_metadata_repo.get_from_metadata(|m| m.imp_some_error_call_indexes()) { + Ok(Ok(call_index)) => calls.push(ParentchainCall::Litentry(OpaqueCall::from_tuple(&( + call_index, + identity, + e, + req_ext_hash, + )))), + Ok(e) => warn!("error getting IMP::some_error call indexes: {:?}", e), + Err(e) => warn!("error getting IMP::some_error call indexes: {:?}", e), + } +} + +pub fn push_call_vcmp_some_error( + calls: &mut Vec, + node_metadata_repo: Arc, + identity: Option, + e: VCMPError, + req_ext_hash: H256, +) where + NodeMetadataRepository: AccessNodeMetadata, + NodeMetadataRepository::MetadataType: NodeMetadataTrait, +{ + debug!("pushing VCMP::some_error call ..."); + match node_metadata_repo.get_from_metadata(|m| m.vcmp_some_error_call_indexes()) { + Ok(Ok(call_index)) => calls.push(ParentchainCall::Litentry(OpaqueCall::from_tuple(&( + call_index, + identity, + e, + req_ext_hash, + )))), + Ok(e) => warn!("error getting VCMP::some_error call indexes: {:?}", e), + Err(e) => warn!("error getting VCMP::some_error call indexes: {:?}", e), + } +} + +#[cfg(test)] +mod tests { + use super::*; + use itp_stf_primitives::types::KeyPair; + use sp_keyring::AccountKeyring; + + #[test] + fn verify_signature_works() { + let nonce = 21; + let mrenclave = [0u8; 32]; + let shard = ShardIdentifier::default(); + + let call = TrustedCall::balance_set_balance( + AccountKeyring::Alice.public().into(), + AccountKeyring::Alice.public().into(), + 42, + 42, + ); + let signed_call = call.sign( + &KeyPair::Sr25519(Box::new(AccountKeyring::Alice.pair())), + nonce, + &mrenclave, + &shard, + ); + + assert!(signed_call.verify_signature(&mrenclave, &shard)); + } +} diff --git a/bitacross-worker/app-libs/stf/src/trusted_call_result.rs b/bitacross-worker/app-libs/stf/src/trusted_call_result.rs new file mode 100644 index 0000000000..f9cbbeff95 --- /dev/null +++ b/bitacross-worker/app-libs/stf/src/trusted_call_result.rs @@ -0,0 +1,44 @@ +// Copyright 2020-2023 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . + +// This file contain the RPC response struct which will be encoded and +// passed back to the requester of trustedCall direct invocation (DI). +// They are mostly translated from the callback extrinsics in IMP. + +use codec::{Decode, Encode}; +use itp_stf_interface::StfExecutionResult; +use std::vec::Vec; + +#[derive(Encode, Decode, Debug)] +pub enum TrustedCallResult { + #[codec(index = 0)] + Empty, + #[codec(index = 1)] + Streamed, +} + +impl StfExecutionResult for TrustedCallResult { + fn get_encoded_result(self) -> Vec { + match self { + Self::Empty => Vec::default(), + Self::Streamed => Vec::default(), + } + } + + fn force_connection_wait(&self) -> bool { + matches!(self, Self::Streamed) + } +} diff --git a/bitacross-worker/bin/README.md b/bitacross-worker/bin/README.md new file mode 100644 index 0000000000..9cf10b5eb8 --- /dev/null +++ b/bitacross-worker/bin/README.md @@ -0,0 +1 @@ +Output directory for the binaries \ No newline at end of file diff --git a/bitacross-worker/build.Dockerfile b/bitacross-worker/build.Dockerfile new file mode 100644 index 0000000000..f417478865 --- /dev/null +++ b/bitacross-worker/build.Dockerfile @@ -0,0 +1,122 @@ +# syntax=docker/dockerfile:1 +# Copyright 2021 Integritee AG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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 is a multi-stage docker file, where the first stage is used +# for building and the second deploys the built application. + +### Builder Stage +################################################## +# todo: we might need to change this image in future +FROM litentry/litentry-tee-dev:latest AS builder +LABEL maintainer="Trust Computing GmbH " + +# set environment variables +ENV SGX_SDK /opt/sgxsdk +ENV PATH "$PATH:${SGX_SDK}/bin:${SGX_SDK}/bin/x64:/opt/rust/bin" +ENV PKG_CONFIG_PATH "${PKG_CONFIG_PATH}:${SGX_SDK}/pkgconfig" +ENV LD_LIBRARY_PATH "${LD_LIBRARY_PATH}:${SGX_SDK}/sdk_libs" +ENV CARGO_NET_GIT_FETCH_WITH_CLI true + +ENV SCCACHE_CACHE_SIZE="20G" +ENV SCCACHE_DIR="/opt/rust/sccache" +ENV RUSTC_WRAPPER="/opt/rust/bin/sccache" + +# Default SGX MODE is software mode +ARG SGX_MODE=SW +ENV SGX_MODE=$SGX_MODE + +ARG SGX_PRODUCTION=0 +ENV SGX_PRODUCTION=$SGX_PRODUCTION + +ENV HOME=/home/ubuntu + +ARG WORKER_MODE_ARG +ENV WORKER_MODE=$WORKER_MODE_ARG + +ARG ADDITIONAL_FEATURES_ARG +ENV ADDITIONAL_FEATURES=$ADDITIONAL_FEATURES_ARG + +ARG FINGERPRINT=none + +WORKDIR $HOME/bitacross-worker +COPY . $HOME + +RUN \ + rm -rf /opt/rust/registry/cache && mv /home/ubuntu/worker-cache/registry/cache /opt/rust/registry && \ + rm -rf /opt/rust/registry/index && mv /home/ubuntu/worker-cache/registry/index /opt/rust/registry && \ + rm -rf /opt/rust/git/db && mv /home/ubuntu/worker-cache/git/db /opt/rust/git && \ + rm -rf /opt/rust/sccache && mv /home/ubuntu/worker-cache/sccache /opt/rust && \ + make && sccache --show-stats + +RUN cargo test --release + + +### Base Runner Stage +################################################## +FROM node:18-bookworm-slim AS runner + +RUN apt update && apt install -y libssl-dev iproute2 jq curl +RUN corepack enable && corepack prepare pnpm@8.7.6 --activate && corepack enable pnpm + + +### Deployed CLI client +################################################## +FROM runner AS deployed-client +LABEL maintainer="Trust Computing GmbH " + +ARG SCRIPT_DIR=/usr/local/worker-cli +ARG LOG_DIR=/usr/local/log + +ENV SCRIPT_DIR ${SCRIPT_DIR} +ENV LOG_DIR ${LOG_DIR} + +COPY --from=local-builder:latest /home/ubuntu/bitacross-worker/bin/bitacross-cli /usr/local/bin +COPY --from=local-builder:latest /home/ubuntu/bitacross-worker/cli/*.sh /usr/local/worker-cli/ + +RUN chmod +x /usr/local/bin/bitacross-cli ${SCRIPT_DIR}/*.sh +RUN mkdir ${LOG_DIR} + +RUN ldd /usr/local/bin/bitacross-cli && /usr/local/bin/bitacross-cli --version + +ENTRYPOINT ["/usr/local/bin/bitacross-cli"] + + +### Deployed worker service +################################################## +FROM runner AS deployed-worker +LABEL maintainer="Trust Computing GmbH " + +WORKDIR /usr/local/bin + +COPY --from=local-builder:latest /opt/sgxsdk /opt/sgxsdk +COPY --from=local-builder:latest /home/ubuntu/bitacross-worker/bin/* /usr/local/bin +COPY --from=local-builder:latest /home/ubuntu/bitacross-worker/cli/*.sh /usr/local/worker-cli/ +COPY --from=local-builder:latest /lib/x86_64-linux-gnu/libsgx* /lib/x86_64-linux-gnu/ +COPY --from=local-builder:latest /lib/x86_64-linux-gnu/libdcap* /lib/x86_64-linux-gnu/ + +RUN touch spid.txt key.txt +RUN chmod +x /usr/local/bin/bitacross-worker +RUN ls -al /usr/local/bin + +# checks +ENV SGX_SDK /opt/sgxsdk +ENV SGX_ENCLAVE_SIGNER $SGX_SDK/bin/x64/sgx_sign +ENV LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/opt/intel/sgx-aesm-service/aesm:$SGX_SDK/sdk_libs +ENV AESM_PATH=/opt/intel/sgx-aesm-service/aesm + +RUN ldd /usr/local/bin/bitacross-worker && /usr/local/bin/bitacross-worker --version + +# TODO: use entrypoint and aesm service launch, see P-295 too +ENTRYPOINT ["/usr/local/bin/bitacross-worker"] \ No newline at end of file diff --git a/bitacross-worker/cli/Cargo.toml b/bitacross-worker/cli/Cargo.toml new file mode 100644 index 0000000000..6e42a13d52 --- /dev/null +++ b/bitacross-worker/cli/Cargo.toml @@ -0,0 +1,69 @@ +[package] +name = "bitacross-cli" +version = "0.0.1" +authors = ['Trust Computing GmbH ', 'Integritee AG '] +edition = "2021" + +[dependencies] +array-bytes = { version = "6.0.0" } +base58 = "0.2" +chrono = "*" +clap = { version = "=4.1.0", features = ["derive"] } +codec = { version = "3.0.0", package = "parity-scale-codec", features = ["derive"] } +env_logger = "0.9" +hdrhistogram = "7.5.0" +hex = "0.4.2" +log = "0.4" +rand = "0.8.5" +rayon = "1.5.1" +regex = "1.9.5" +reqwest = { version = "0.11", features = ["blocking", "json"] } +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" +sgx_crypto_helper = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git" } +thiserror = "1.0" +urlencoding = "2.1.3" + +# scs / integritee +pallet-evm = { optional = true, git = "https://github.com/integritee-network/frontier.git", branch = "bar/polkadot-v0.9.42" } +# `default-features = false` to remove the jsonrpsee dependency. +substrate-api-client = { default-features = false, features = ["std", "sync-api"], git = "https://github.com/scs/substrate-api-client.git", branch = "polkadot-v0.9.42-tag-v0.14.0" } +substrate-client-keystore = { git = "https://github.com/scs/substrate-api-client.git", branch = "polkadot-v0.9.42-tag-v0.14.0" } + +# substrate dependencies +pallet-balances = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } +sp-application-crypto = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } +sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } +sp-keyring = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } +sp-keystore = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } +sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } + +# local dependencies +ita-stf = { path = "../app-libs/stf" } +itc-rpc-client = { path = "../core/rpc-client" } +itp-node-api = { path = "../core-primitives/node-api" } +itp-rpc = { path = "../core-primitives/rpc" } +itp-sgx-crypto = { path = "../core-primitives/sgx/crypto" } +itp-stf-primitives = { path = "../core-primitives/stf-primitives" } +itp-time-utils = { path = "../core-primitives/time-utils" } +itp-types = { path = "../core-primitives/types" } +itp-utils = { path = "../core-primitives/utils" } + +# litentry +frame-metadata = "15.0.0" +ita-sgx-runtime = { path = "../app-libs/sgx-runtime" } +litentry-primitives = { path = "../litentry/primitives" } +my-node-runtime = { package = "rococo-parachain-runtime", path = "../../runtime/rococo" } +pallet-teerex = { path = "../../pallets/teerex", default-features = false } +scale-value = "0.6.0" +sp-core-hashing = "6.0.0" + +[features] +default = [] +evm = ["ita-stf/evm_std", "pallet-evm"] +teeracle = [] +sidechain = [] +offchain-worker = [] +production = [] +# dcap feature flag is not used in this crate, but for easier build purposes only it present here as well +dcap = [] diff --git a/bitacross-worker/cli/README.md b/bitacross-worker/cli/README.md new file mode 100644 index 0000000000..a1eb6463f5 --- /dev/null +++ b/bitacross-worker/cli/README.md @@ -0,0 +1,35 @@ +# Integritee CLI client +Interact with the Integritee chain and workers from the command line + +Includes +* keystore (incompatible with polkadot js app json) +* basic balance transfer +* Integritee-specific calls + +## examples +``` +> ./bitacross-cli transfer //Bob //Alice 12345 +> ./bitacross-cli -u ws://127.0.0.1 list-workers +number of workers registered: 1 +Enclave 1 + AccountId: 5HN8RGEiJuc9iNA3vfiYj7Lk6ULWzBZXvSDheohBu3usSUqn + MRENCLAVE: 4GMb72Acyg8hnnnGEJ89jZK5zxNC4LvSe2ME96wLRV6J + RA timestamp: 2022-03-16 10:43:12.001 UTC + URL: wss://127.0.0.1:2345 +> ./bitacross-cli -P 2345 trusted --direct --mrenclave 4GMb72Acyg8hnnn +GE4LvSe2ME96wLRV6J unshield-funds //Bob //Alice 12345 +from ss58 is 5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty +to ss58 is 5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY +send trusted call unshield_funds from 5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty to 5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY: 12345 +Trusted call 0x69ddfd1698bd2d629180c2dca34ce7add087526c51f43cf68245241b3f13154e is Submitted +Trusted call 0x69ddfd1698bd2d629180c2dca34ce7add087526c51f43cf68245241b3f13154e is Invalid + +``` + +## housekeeping tasks + +populate all TCBinfo's Intel has published +``` +../target/release/bitacross-cli register-tcb-info //Alice --fmspc 00606a000000 +../target/release/bitacross-cli register-tcb-info //Alice --all +``` diff --git a/bitacross-worker/cli/benchmark.sh b/bitacross-worker/cli/benchmark.sh new file mode 100755 index 0000000000..080651fdc6 --- /dev/null +++ b/bitacross-worker/cli/benchmark.sh @@ -0,0 +1,61 @@ +#!/bin/bash + +while getopts ":m:p:A:u:V:C:" opt; do + case $opt in + m) + READMRENCLAVE=$OPTARG + ;; + p) + NPORT=$OPTARG + ;; + A) + WORKER1PORT=$OPTARG + ;; + u) + NODEURL=$OPTARG + ;; + V) + WORKER1URL=$OPTARG + ;; + C) + CLIENT_BIN=$OPTARG + ;; + *) + ;; + esac +done + +# using default port if none given as arguments +NPORT=${NPORT:-9944} +NODEURL=${NODEURL:-"ws://127.0.0.1"} + +WORKER1PORT=${WORKER1PORT:-2000} +WORKER1URL=${WORKER1URL:-"wss://127.0.0.1"} + +CLIENT_BIN=${CLIENT_BIN:-"./../bin/bitacross-cli"} + +echo "Using client binary ${CLIENT_BIN}" +echo "Using node uri ${NODEURL}:${NPORT}" +echo "Using trusted-worker uri ${WORKER1URL}:${WORKER1PORT}" + +CLIENTWORKER1="${CLIENT_BIN} -p ${NPORT} -P ${WORKER1PORT} -u ${NODEURL} -U ${WORKER1URL}" + +if [ "$READMRENCLAVE" = "file" ] +then + read -r MRENCLAVE <<< "$(cat ~/mrenclave.b58)" + echo "Reading MRENCLAVE from file: ${MRENCLAVE}" +else + # this will always take the first MRENCLAVE found in the registry !! + read -r MRENCLAVE <<< "$($CLIENTWORKER1 list-workers | awk '/ MRENCLAVE: / { print $2; exit }')" + echo "Reading MRENCLAVE from worker list: ${MRENCLAVE}" +fi +[[ -z $MRENCLAVE ]] && { echo "MRENCLAVE is empty. cannot continue" ; exit 1; } + +# needed when many clients are started +ulimit -S -n 4096 + +echo "Starting benchmark" +${CLIENTWORKER1} trusted --direct --mrenclave "${MRENCLAVE}" benchmark 20 100 -w +echo "" + +exit 0 diff --git a/bitacross-worker/cli/demo_direct_call.sh b/bitacross-worker/cli/demo_direct_call.sh new file mode 100755 index 0000000000..a3c816bd93 --- /dev/null +++ b/bitacross-worker/cli/demo_direct_call.sh @@ -0,0 +1,144 @@ +#!/bin/bash + +# Executes a direct call on a worker and checks the balance afterwards. +# +# setup: +# run all on localhost: +# litentry-node purge-chain --dev +# litentry-node --tmp --dev -lruntime=debug +# rm light_client_db.bin +# export RUST_LOG=litentry_worker=info,ita_stf=debug +# bitacross-worker init_shard +# bitacross-worker shielding-key +# bitacross-worker signing-key +# bitacross-worker run +# +# then run this script + +# usage: +# demo_direct_call.sh -p -P -t -m file +# +# TEST_BALANCE_RUN is either "first" or "second" +# if -m file is set, the mrenclave will be read from file + +while getopts ":m:p:P:t:u:V:C:" opt; do + case $opt in + t) + TEST=$OPTARG + ;; + m) + READ_MRENCLAVE=$OPTARG + ;; + p) + LITENTRY_RPC_PORT=$OPTARG + ;; + P) + WORKER_1_PORT=$OPTARG + ;; + u) + LITENTRY_RPC_URL=$OPTARG + ;; + V) + WORKER_1_URL=$OPTARG + ;; + C) + CLIENT_BIN=$OPTARG + ;; + *) + echo "invalid arg ${OPTARG}" + exit 1 + esac +done + +# Using default port if none given as arguments. +LITENTRY_RPC_PORT=${LITENTRY_RPC_PORT:-9944} +LITENTRY_RPC_URL=${LITENTRY_RPC_URL:-"ws://127.0.0.1"} + +WORKER_1_PORT=${WORKER_1_PORT:-2000} +WORKER_1_URL=${WORKER_1_URL:-"wss://127.0.0.1"} + +CLIENT_BIN=${CLIENT_BIN:-"./../bin/bitacross-cli"} + +echo "Using client binary ${CLIENT_BIN}" +${CLIENT_BIN} --version +echo "Using node uri ${LITENTRY_RPC_URL}:${LITENTRY_RPC_PORT}" +echo "Using trusted-worker uri ${WORKER_1_URL}:${WORKER_1_PORT}" +echo "" + + +AMOUNTSHIELD=50000000000 +AMOUNTTRANSFER=40000000000 + +CLIENT="${CLIENT_BIN} -p ${LITENTRY_RPC_PORT} -P ${WORKER_1_PORT} -u ${LITENTRY_RPC_URL} -U ${WORKER_1_URL}" +read -r MRENCLAVE <<< "$($CLIENT list-workers | awk '/ MRENCLAVE: / { print $2; exit }')" + +echo "" +echo "* Create a new incognito account for Alice" +ICGACCOUNTALICE=//AliceIncognito +ICGACCOUNTALICE_PUBKEY=0x50503350955afe8a107d6f115dc253eb5d75a3fe37a90b373db26cc12e3c6661 +echo " Alice's incognito account = ${ICGACCOUNTALICE}" +echo "" + +echo "* Create a new incognito account for Bob" +ICGACCOUNTBOB=//BobIncognito +ICGACCOUNTBOB_PUBKEY=0xc24c5b3969d8ec4ca8a655a98dcc136d5d4c29d1206ffe7721e80ebdfa1d0b77 +echo " Bob's incognito account = ${ICGACCOUNTBOB}" +echo "" + +echo "* Issue ${AMOUNTSHIELD} tokens to Alice's incognito account" +${CLIENT} trusted --mrenclave ${MRENCLAVE} --direct set-balance ${ICGACCOUNTALICE} ${AMOUNTSHIELD} +echo "" + +echo "Get balance of Alice's incognito account" +${CLIENT} trusted --mrenclave ${MRENCLAVE} balance ${ICGACCOUNTALICE} +echo "" + +# Send funds from Alice to Bob's account. +echo "* Send ${AMOUNTTRANSFER} funds from Alice's incognito account to Bob's incognito account" +$CLIENT trusted --mrenclave ${MRENCLAVE} --direct transfer ${ICGACCOUNTALICE} ${ICGACCOUNTBOB} ${AMOUNTTRANSFER} +echo "" + +# Prevent getter being executed too early and returning an outdated result, before the transfer was made. +echo "* Waiting 6 seconds" +sleep 6 +echo "" + +echo "* Get balance of Alice's incognito account" +# RESULT=$(${CLIENT} trusted --mrenclave ${MRENCLAVE} balance ${ICGACCOUNTALICE} | xargs) +RESULT=$(${CLIENT} trusted --mrenclave ${MRENCLAVE} get-storage System Account ${ICGACCOUNTALICE_PUBKEY} | jq ".data.free" | xargs) +echo $RESULT +echo "" + +echo "* Bob's incognito account balance" +# RESULT=$(${CLIENT} trusted --mrenclave ${MRENCLAVE} balance ${ICGACCOUNTBOB} | xargs) +RESULT=$(${CLIENT} trusted --mrenclave ${MRENCLAVE} get-storage System Account ${ICGACCOUNTBOB_PUBKEY} | jq ".data.free" | xargs) +echo $RESULT +echo "" + + +# The following tests are for automated CI. +# They only work if you're running from fresh genesis. +case $TEST in + first) + if [ "40000000000" = "$RESULT" ]; then + echo "test passed (1st time)" + echo "" + exit 0 + else + echo "test ran through but balance is wrong. have you run the script from fresh genesis?" + exit 1 + fi + ;; + second) + if [ "80000000000" = "$RESULT" ]; then + echo "test passed (2nd time)" + echo "" + exit 0 + else + echo "test ran through but balance is wrong. is this really the second time you run this since genesis?" + exit 1 + fi + ;; +esac + +exit 0 diff --git a/bitacross-worker/cli/demo_direct_call_2_workers.sh b/bitacross-worker/cli/demo_direct_call_2_workers.sh new file mode 100755 index 0000000000..3375efa0fd --- /dev/null +++ b/bitacross-worker/cli/demo_direct_call_2_workers.sh @@ -0,0 +1,63 @@ +#!/bin/bash +set -euo pipefail + +# Runs the `demo_direct_call.sh` twice once with worker1 and worker2. +# This verifies that the two workers are successfully sharing state updates +# by broadcasting sidechain blocks. +# +# It does the same as `scripts/m8.sh`, but is mainly used in the docker tests. + +while getopts ":p:A:B:u:W:V:C:" opt; do + case $opt in + p) + NPORT=$OPTARG + ;; + A) + WORKER1PORT=$OPTARG + ;; + B) + WORKER2PORT=$OPTARG + ;; + u) + NODEURL=$OPTARG + ;; + V) + WORKER1URL=$OPTARG + ;; + W) + WORKER2URL=$OPTARG + ;; + C) + CLIENT_BIN=$OPTARG + ;; + *) + echo "invalid arg ${OPTARG}" + exit 1 + esac +done + +# Using default port if none given as arguments. +NPORT=${NPORT:-9944} +NODEURL=${NODEURL:-"ws://127.0.0.1"} + +WORKER1PORT=${WORKER1PORT:-2000} +WORKER1URL=${WORKER1URL:-"wss://127.0.0.1"} + +WORKER2PORT=${WORKER2PORT:-3000} +WORKER2URL=${WORKER2URL:-"wss://127.0.0.1"} + +CLIENT_BIN=${CLIENT_BIN:-"./../bin/bitacross-cli"} + +echo "Using client binary ${CLIENT_BIN}" +${CLIENT_BIN} --version +echo "Using node uri ${NODEURL}:${NPORT}" +echo "Using trusted-worker uri 1 ${WORKER1URL}:${WORKER1PORT}" +echo "Using trusted-worker uri 2 ${WORKER2URL}:${WORKER2PORT}" +echo "" + +SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) + +"${SCRIPT_DIR}"/demo_direct_call.sh -p "${NPORT}" -u "${NODEURL}" -V "${WORKER1URL}" -P "${WORKER1PORT}" -C "${CLIENT_BIN}" -t first +"${SCRIPT_DIR}"/demo_direct_call.sh -p "${NPORT}" -u "${NODEURL}" -V "${WORKER2URL}" -P "${WORKER2PORT}" -C "${CLIENT_BIN}" -t second + +exit 0 diff --git a/bitacross-worker/cli/demo_shielding_unshielding.sh b/bitacross-worker/cli/demo_shielding_unshielding.sh new file mode 100755 index 0000000000..33ccc1b394 --- /dev/null +++ b/bitacross-worker/cli/demo_shielding_unshielding.sh @@ -0,0 +1,275 @@ +#!/bin/bash + +# to make sure the script aborts when (sub-)function exits abnormally +set -e + +# Demonstrates how to shield tokens from the parentchain into the sidechain. +# +# setup: +# run all on localhost: +# litentry-node purge-chain --dev +# litentry-node --dev -lruntime=debug +# rm light_client_db.bin +# export RUST_LOG=litentry_worker=info,ita_stf=debug +# bitacross-worker init_shard +# bitacross-worker shielding-key +# bitacross-worker signing-key +# bitacross-worker run +# +# then run this script + +# usage: +# demo_shielding_unshielding.sh -p -P -t -m file +# +# TEST_BALANCE_RUN is either "first" or "second" +# if -m file is set, the mrenclave will be read from file + +while getopts ":m:p:P:t:u:V:C:" opt; do + case $opt in + t) + TEST=$OPTARG + ;; + m) + READ_MRENCLAVE=$OPTARG + ;; + p) + LITENTRY_RPC_PORT=$OPTARG + ;; + P) + WORKER_1_PORT=$OPTARG + ;; + u) + LITENTRY_RPC_URL=$OPTARG + ;; + V) + WORKER_1_URL=$OPTARG + ;; + C) + CLIENT_BIN=$OPTARG + ;; + *) + echo "invalid arg ${OPTARG}" + exit 1 + esac +done + +# Using default port if none given as arguments. +LITENTRY_RPC_PORT=${LITENTRY_RPC_PORT:-9944} +LITENTRY_RPC_URL=${LITENTRY_RPC_URL:-"ws://127.0.0.1"} + +WORKER_1_PORT=${WORKER_1_PORT:-2000} +WORKER_1_URL=${WORKER_1_URL:-"wss://127.0.0.1"} + +CLIENT_BIN=${CLIENT_BIN:-"./../bin/bitacross-cli"} + +echo "Using client binary ${CLIENT_BIN}" +${CLIENT_BIN} --version +echo "Using node uri ${LITENTRY_RPC_URL}:${LITENTRY_RPC_PORT}" +echo "Using trusted-worker uri ${WORKER_1_URL}:${WORKER_1_PORT}" +echo "" + +# the parentchain token is 12 decimal +UNIT=$(( 10 ** 12 )) +FEE_TOLERANCE=$((10 ** 11)) + +# we have to make these amounts greater than ED, see +# https://github.com/litentry/litentry-parachain/issues/1162 +AMOUNT_SHIELD=$(( 6 * UNIT )) +AMOUNT_TRANSFER=$(( 2 * UNIT )) +AMOUNT_UNSHIELD=$(( 1 * UNIT )) + +CLIENT="${CLIENT_BIN} -p ${LITENTRY_RPC_PORT} -P ${WORKER_1_PORT} -u ${LITENTRY_RPC_URL} -U ${WORKER_1_URL}" + +# interval and max rounds to wait to check the given account balance in sidechain +WAIT_INTERVAL_SECONDS=10 +WAIT_ROUNDS=20 + +# Do a live query and assert the given account's balance is equal to expected +# usage: +# assert_account_balance +function assert_account_balance() +{ + for i in $(seq 1 $WAIT_ROUNDS); do + state=$(${CLIENT} trusted --mrenclave "$1" balance "$2") + if (( $3 >= state ? $3 - state < FEE_TOLERANCE : state - $3 < FEE_TOLERANCE)); then + return + else + sleep $WAIT_INTERVAL_SECONDS + fi + done + echo + echo "Assert $2 failed, expected = $3, actual = $state, tolerance = $FEE_TOLERANCE" + exit 1 +} + + +# Do a live query and assert the given account's nonce is equal to expected +# usage: +# assert_account_nonce +function assert_account_nonce() +{ + for i in $(seq 1 $WAIT_ROUNDS); do + state=$(${CLIENT} trusted --mrenclave "$1" nonce "$2") + echo $state + if [ $state -eq "$3" ]; then + return + else + sleep $WAIT_INTERVAL_SECONDS + fi + done + echo + echo "Assert $2 failed, expected = $3, actual = $state" + exit 1 +} + +# Do a live query and assert the given account's state is equal to expected +# usage: +# assert_account_state +function assert_account_state() +{ + state=$(${CLIENT} trusted --mrenclave "$1" get-storage System Account "$2" | jq "$3") + if [ -z "$state" ]; then + echo "Query Account $2 $3 failed" + exit 1 + fi + + if [ $state -eq "$4" ]; then + return + fi + echo + echo "Assert $2 $3 failed, expected = $4, actual = $state" + exit 1 +} + +echo "* Query on-chain enclave registry:" +${CLIENT} list-workers +echo "" + +if [ "$READ_MRENCLAVE" = "file" ] +then + read MRENCLAVE <<< $(cat ~/mrenclave.b58) + echo "Reading MRENCLAVE from file: ${MRENCLAVE}" +else + # this will always take the first MRENCLAVE found in the registry !! + read MRENCLAVE <<< $($CLIENT list-workers | awk '/ MRENCLAVE: / { print $2; exit }') + echo "Reading MRENCLAVE from worker list: ${MRENCLAVE}" +fi +[[ -z $MRENCLAVE ]] && { echo "MRENCLAVE is empty. cannot continue" ; exit 1; } + +echo "* Create a new incognito account for Alice" +ICGACCOUNTALICE=//AliceIncognito +echo " Alice's incognito account = ${ICGACCOUNTALICE}" +echo "" + +# Asssert the initial balance of Alice incognito +# We create different (new) accounts for Bob incognito, hence his initial balance is always 0 +BALANCE_INCOGNITO_ALICE=0 +case $TEST in + first) + assert_account_balance ${MRENCLAVE} ${ICGACCOUNTALICE} 0 + ICGACCOUNTBOB=//BobIncognitoFirst ;; + second) + assert_account_balance ${MRENCLAVE} ${ICGACCOUNTALICE} $(( AMOUNT_SHIELD - AMOUNT_TRANSFER - AMOUNT_UNSHIELD )) + BALANCE_INCOGNITO_ALICE=$(( AMOUNT_SHIELD - AMOUNT_TRANSFER - AMOUNT_UNSHIELD )) + ICGACCOUNTBOB=//BobIncognitoSecond ;; + *) + echo "unsupported test mode" + exit 1 ;; +esac + +echo "* Create a new incognito account for Bob" +echo " Bob's incognito account = ${ICGACCOUNTBOB}" +echo "" + +echo "* Shield ${AMOUNT_SHIELD} tokens to Alice's incognito account" +${CLIENT} shield-funds //Alice ${ICGACCOUNTALICE} ${AMOUNT_SHIELD} ${MRENCLAVE} +echo "" + +echo "* Wait and assert Alice's incognito account balance... " +assert_account_balance ${MRENCLAVE} ${ICGACCOUNTALICE} $(( BALANCE_INCOGNITO_ALICE + AMOUNT_SHIELD )) +echo "✔ ok" + +echo "* Wait and assert Bob's incognito account balance... " +assert_account_balance ${MRENCLAVE} ${ICGACCOUNTBOB} 0 +echo "✔ ok" +echo "" + +echo "* Send ${AMOUNT_TRANSFER} funds from Alice's incognito account to Bob's incognito account" +$CLIENT trusted --mrenclave ${MRENCLAVE} transfer ${ICGACCOUNTALICE} ${ICGACCOUNTBOB} ${AMOUNT_TRANSFER} +echo "" + +echo "* Wait and assert Alice's incognito account balance... " +assert_account_balance ${MRENCLAVE} ${ICGACCOUNTALICE} $(( BALANCE_INCOGNITO_ALICE + AMOUNT_SHIELD - AMOUNT_TRANSFER )) +echo "✔ ok" + +echo "* Wait and assert Bob's incognito account balance... " +assert_account_balance ${MRENCLAVE} ${ICGACCOUNTBOB} ${AMOUNT_TRANSFER} +echo "✔ ok" +echo "" + +echo "* Un-shield ${AMOUNT_UNSHIELD} tokens from Alice's incognito account to Ferie's L1 account" +${CLIENT} trusted --mrenclave ${MRENCLAVE} unshield-funds ${ICGACCOUNTALICE} //Ferdie ${AMOUNT_UNSHIELD} +echo "" + +echo "* Wait and assert Alice's incognito account balance... " +assert_account_balance ${MRENCLAVE} ${ICGACCOUNTALICE} $(( BALANCE_INCOGNITO_ALICE + AMOUNT_SHIELD - AMOUNT_TRANSFER - AMOUNT_UNSHIELD )) +echo "✔ ok" + +echo "* Wait and assert Bob's incognito account balance... " +assert_account_balance ${MRENCLAVE} ${ICGACCOUNTBOB} ${AMOUNT_TRANSFER} +echo "✔ ok" + +# Test the nonce handling, using Bob's incognito account as the sender as Alice's +# balance needs to be verified in the second round while Bob is newly created each time + +echo "* Create a new incognito account for Charlie" +ICGACCOUNTCHARLIE=$(${CLIENT} trusted --mrenclave ${MRENCLAVE} new-account) +echo " Charlie's incognito account = ${ICGACCOUNTCHARLIE}" +echo "" + +echo "* Assert Bob's incognito initial nonce..." +assert_account_nonce ${MRENCLAVE} ${ICGACCOUNTBOB} 0 +echo "✔ ok" +echo "" + +echo "* Send 3 consecutive 0.2 UNIT balance Transfer Bob -> Charlie" +for i in $(seq 1 3); do + # use direct calls so they are submitted to the top pool synchronously + $CLIENT trusted --direct --mrenclave ${MRENCLAVE} transfer ${ICGACCOUNTBOB} ${ICGACCOUNTCHARLIE} $(( AMOUNT_TRANSFER / 10 )) +done +echo "" + +echo "* Assert Bob's incognito current nonce..." +assert_account_nonce ${MRENCLAVE} ${ICGACCOUNTBOB} 3 +echo "✔ ok" +echo "" + +echo "* Send a 2 UNIT balance Transfer Bob -> Charlie (that will fail)" +$CLIENT trusted --direct --mrenclave ${MRENCLAVE} transfer ${ICGACCOUNTBOB} ${ICGACCOUNTCHARLIE} ${AMOUNT_TRANSFER} || true +echo "" + +echo "* Assert Bob's incognito nonce..." +# the nonce should be increased nontheless, even for the failed tx +assert_account_nonce ${MRENCLAVE} ${ICGACCOUNTBOB} 4 +echo "✔ ok" +echo "" + +echo "* Send another 0.2 UNIT balance Transfer Bob -> Charlie" +$CLIENT trusted --direct --mrenclave ${MRENCLAVE} transfer ${ICGACCOUNTBOB} ${ICGACCOUNTCHARLIE} $(( AMOUNT_TRANSFER / 10 )) +echo "" + +echo "* Assert Bob's incognito nonce..." +assert_account_nonce ${MRENCLAVE} ${ICGACCOUNTBOB} 5 +echo "✔ ok" +echo "" + +echo "* Wait and assert Bob's incognito account balance... " +# in total 4 balance transfer should go through => 1.2 UNIT remaining +assert_account_balance ${MRENCLAVE} ${ICGACCOUNTBOB} $(( AMOUNT_TRANSFER * 6 / 10 )) +echo "✔ ok" + +echo "" +echo "-----------------------" +echo "✔ The $TEST test passed!" +echo "-----------------------" +echo "" diff --git a/bitacross-worker/cli/demo_shielding_unshielding_multiworker.sh b/bitacross-worker/cli/demo_shielding_unshielding_multiworker.sh new file mode 100755 index 0000000000..476a64a87d --- /dev/null +++ b/bitacross-worker/cli/demo_shielding_unshielding_multiworker.sh @@ -0,0 +1,69 @@ +#!/bin/bash +set -euo pipefail + +# Runs the direct call demo twice, with worker 1 and worker 2. +# +# It does the same as `./scripts/m6.sh`, but is mainly used in the docker tests. + +while getopts ":p:A:B:u:W:V:C:" opt; do + case $opt in + p) + INTEGRITEE_RPC_PORT=$OPTARG + ;; + A) + WORKER_1_PORT=$OPTARG + ;; + B) + WORKER_2_PORT=$OPTARG + ;; + u) + INTEGRITEE_RPC_URL=$OPTARG + ;; + V) + WORKER_1_URL=$OPTARG + ;; + W) + WORKER_2_URL=$OPTARG + ;; + C) + CLIENT_BIN=$OPTARG + ;; + *) + echo "invalid arg ${OPTARG}" + exit 1 + esac +done + +# Using default port if none given as arguments. +INTEGRITEE_RPC_PORT=${INTEGRITEE_RPC_PORT:-9944} +INTEGRITEE_RPC_URL=${INTEGRITEE_RPC_URL:-"ws://127.0.0.1"} + +WORKER_1_PORT=${WORKER_1_PORT:-2000} +WORKER_1_URL=${WORKER_1_URL:-"wss://127.0.0.1"} + +WORKER_2_PORT=${WORKER_2_PORT:-3000} +WORKER_2_URL=${WORKER_2_URL:-"wss://127.0.0.1"} + +CLIENT_BIN=${CLIENT_BIN:-"./../bin/integritee-cli"} + +echo "Using client binary ${CLIENT_BIN}" +${CLIENT_BIN} --version +echo "Using node uri ${INTEGRITEE_RPC_URL}:${INTEGRITEE_RPC_PORT}" +echo "Using trusted-worker 1 uri ${WORKER_1_URL}:${WORKER_1_PORT}" +echo "Using trusted-worker 2 uri ${WORKER_2_URL}:${WORKER_2_PORT}" +echo "" + +SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) + +"${SCRIPT_DIR}"/demo_shielding_unshielding.sh -p "${INTEGRITEE_RPC_PORT}" -u "${INTEGRITEE_RPC_URL}" -V "${WORKER_1_URL}" -P "${WORKER_1_PORT}" -C "${CLIENT_BIN}" -t first +"${SCRIPT_DIR}"/demo_shielding_unshielding.sh -p "${INTEGRITEE_RPC_PORT}" -u "${INTEGRITEE_RPC_URL}" -V "${WORKER_2_URL}" -P "${WORKER_2_PORT}" -C "${CLIENT_BIN}" -t second + +if [ "$FLAVOR_ID" = offchain-worker ]; then + echo "offchain-worker does not support shard vault shielding, therefore we skip those tests" + exit 0 +fi + +"${SCRIPT_DIR}"/demo_shielding_unshielding_using_shard_vault.sh -p "${INTEGRITEE_RPC_PORT}" -u "${INTEGRITEE_RPC_URL}" -V "${WORKER_1_URL}" -P "${WORKER_1_PORT}" -C "${CLIENT_BIN}" -t first +"${SCRIPT_DIR}"/demo_shielding_unshielding_using_shard_vault.sh -p "${INTEGRITEE_RPC_PORT}" -u "${INTEGRITEE_RPC_URL}" -V "${WORKER_2_URL}" -P "${WORKER_2_PORT}" -C "${CLIENT_BIN}" -t second + +exit 0 \ No newline at end of file diff --git a/bitacross-worker/cli/demo_shielding_unshielding_using_shard_vault.sh b/bitacross-worker/cli/demo_shielding_unshielding_using_shard_vault.sh new file mode 100755 index 0000000000..82399f7cc3 --- /dev/null +++ b/bitacross-worker/cli/demo_shielding_unshielding_using_shard_vault.sh @@ -0,0 +1,266 @@ +#!/bin/bash + +# to make sure the script aborts when (sub-)function exits abnormally +set -e + +# Demonstrates how to shield tokens from the parentchain into the sidechain. +# +# setup: +# run all on localhost: +# integritee-node purge-chain --dev +# integritee-node --dev -lruntime=debug +# rm light_client_db.bin +# export RUST_LOG=integritee_service=info,ita_stf=debug +# integritee-service init_shard +# integritee-service shielding-key +# integritee-service signing-key +# integritee-service run +# +# then run this script + +# usage: +# demo_shielding_unshielding.sh -p -P -t -m file +# +# TEST_BALANCE_RUN is either "first" or "second" +# if -m file is set, the mrenclave will be read from file + +while getopts ":m:p:P:t:u:V:C:" opt; do + case $opt in + t) + TEST=$OPTARG + ;; + m) + READ_MRENCLAVE=$OPTARG + ;; + p) + INTEGRITEE_RPC_PORT=$OPTARG + ;; + P) + WORKER_1_PORT=$OPTARG + ;; + u) + INTEGRITEE_RPC_URL=$OPTARG + ;; + V) + WORKER_1_URL=$OPTARG + ;; + C) + CLIENT_BIN=$OPTARG + ;; + *) + echo "invalid arg ${OPTARG}" + exit 1 + esac +done + +# Using default port if none given as arguments. +INTEGRITEE_RPC_PORT=${INTEGRITEE_RPC_PORT:-9944} +INTEGRITEE_RPC_URL=${INTEGRITEE_RPC_URL:-"ws://127.0.0.1"} + +WORKER_1_PORT=${WORKER_1_PORT:-2000} +WORKER_1_URL=${WORKER_1_URL:-"wss://127.0.0.1"} + +CLIENT_BIN=${CLIENT_BIN:-"./../bin/integritee-cli"} + +echo "Using client binary ${CLIENT_BIN}" +${CLIENT_BIN} --version +echo "Using node uri ${INTEGRITEE_RPC_URL}:${INTEGRITEE_RPC_PORT}" +echo "Using trusted-worker uri ${WORKER_1_URL}:${WORKER_1_PORT}" +echo "" + +# the parentchain token is 12 decimal +UNIT=$(( 10 ** 12 )) +FEE_TOLERANCE=$((10 ** 11)) + +# make these amounts greater than ED +AMOUNT_SHIELD=$(( 6 * UNIT )) +AMOUNT_TRANSFER=$(( 2 * UNIT )) +AMOUNT_UNSHIELD=$(( 1 * UNIT )) + +CLIENT="${CLIENT_BIN} -p ${INTEGRITEE_RPC_PORT} -P ${WORKER_1_PORT} -u ${INTEGRITEE_RPC_URL} -U ${WORKER_1_URL}" + +# offchain-worker only suppports indirect calls +CALLTYPE= +case "$FLAVOR_ID" in + sidechain) CALLTYPE="--direct" ;; + offchain-worker) : ;; + *) CALLTYPE="--direct" ;; +esac +echo "using call type: ${CALLTYPE} (empty means indirect)" + +# interval and max rounds to wait to check the given account balance in sidechain +WAIT_INTERVAL_SECONDS=10 +WAIT_ROUNDS=20 + +# Poll and assert the given account's state is equal to expected, +# with timeout WAIT_INTERVAL_SECONDS * WAIT_ROUNDS +# usage: +# wait_assert_state +# the `state-name` has to be the supported subcommand, e.g. `balance`, `nonce` +function wait_assert_state() +{ + for i in $(seq 1 $WAIT_ROUNDS); do + sleep $WAIT_INTERVAL_SECONDS + state=$(${CLIENT} trusted --mrenclave "$1" "$3" "$2") + if (( $4 >= state ? $4 - state < FEE_TOLERANCE : state - $4 < FEE_TOLERANCE)); then + return + else + : + fi + done + echo + echo "Assert $2 $3 failed, expected = $4, actual = $state, tolerance = $FEE_TOLERANCE" + exit 1 +} + +# Do a live query and assert the given account's state is equal to expected +# usage: +# assert_state +function assert_state() +{ + state=$(${CLIENT} trusted --mrenclave "$1" "$3" "$2") + if [ -z "$state" ]; then + echo "Query $2 $3 failed" + exit 1 + fi + + if [ $state -eq "$4" ]; then + return + fi + echo + echo "Assert $2 $3 failed, expected = $4, actual = $state" + exit 1 +} + +echo "* Query on-chain enclave registry:" +${CLIENT} list-workers +echo "" + +if [ "$READ_MRENCLAVE" = "file" ] +then + read MRENCLAVE <<< $(cat ~/mrenclave.b58) + echo "Reading MRENCLAVE from file: ${MRENCLAVE}" +else + # this will always take the first MRENCLAVE found in the registry !! + read MRENCLAVE <<< $($CLIENT list-workers | awk '/ MRENCLAVE: / { print $2; exit }') + echo "Reading MRENCLAVE from worker list: ${MRENCLAVE}" +fi +[[ -z $MRENCLAVE ]] && { echo "MRENCLAVE is empty. cannot continue" ; exit 1; } + + +echo "* Create a new incognito account for Bob" +ICGACCOUNTBOB=$(${CLIENT} trusted --mrenclave ${MRENCLAVE} new-account) +echo " Bob's incognito account = ${ICGACCOUNTBOB}" +echo "" + +echo "* Query shard vault account" +VAULT=$(${CLIENT} trusted get-shard-vault) +echo " shard vault account = ${VAULT}" +echo "" + +# Asssert the initial balance of Charlie incognito +# The initial balance of Bob incognito should always be 0, as Bob is newly created +BALANCE_INCOGNITO_CHARLIE=0 +case $TEST in + first) + wait_assert_state ${MRENCLAVE} //Charlie balance 0 ;; + second) + wait_assert_state ${MRENCLAVE} //Charlie balance $(( AMOUNT_SHIELD - AMOUNT_TRANSFER - AMOUNT_UNSHIELD )) + BALANCE_INCOGNITO_CHARLIE=$(( AMOUNT_SHIELD - AMOUNT_TRANSFER - AMOUNT_UNSHIELD )) ;; + *) + echo "assuming first run of test" + wait_assert_state ${MRENCLAVE} //Charlie balance 0 ;; +esac + +echo "* Shield ${AMOUNT_SHIELD} tokens to Charlie's account on L2" +${CLIENT} transfer //Charlie ${VAULT} ${AMOUNT_SHIELD} +echo "" + +echo "* Wait and assert Charlie's L2 account balance... " +wait_assert_state ${MRENCLAVE} //Charlie balance $(( BALANCE_INCOGNITO_CHARLIE + AMOUNT_SHIELD )) +echo "✔ ok" + +echo "* Wait and assert Bob's incognito account balance... " +wait_assert_state ${MRENCLAVE} ${ICGACCOUNTBOB} balance 0 +echo "✔ ok" +echo "" + +echo "* Send ${AMOUNT_TRANSFER} funds from Charlie's L2 account to Bob's incognito account" +$CLIENT trusted --mrenclave ${MRENCLAVE} transfer //Charlie ${ICGACCOUNTBOB} ${AMOUNT_TRANSFER} +echo "" + +echo "* Wait and assert Charlie's L2 account balance... " +wait_assert_state ${MRENCLAVE} //Charlie balance $(( BALANCE_INCOGNITO_CHARLIE + AMOUNT_SHIELD - AMOUNT_TRANSFER )) +echo "✔ ok" + +echo "* Wait and assert Bob's incognito account balance... " +wait_assert_state ${MRENCLAVE} ${ICGACCOUNTBOB} balance ${AMOUNT_TRANSFER} +echo "✔ ok" +echo "" + +echo "* Un-shield ${AMOUNT_UNSHIELD} tokens from Charlie's incognito account to Ferie's L1 account" +${CLIENT} trusted --mrenclave ${MRENCLAVE} unshield-funds //Charlie //Ferdie ${AMOUNT_UNSHIELD} +echo "" + +echo "* Wait and assert Charlie's incognito account balance... " +wait_assert_state ${MRENCLAVE} //Charlie balance $(( BALANCE_INCOGNITO_CHARLIE + AMOUNT_SHIELD - AMOUNT_TRANSFER - AMOUNT_UNSHIELD )) +echo "✔ ok" + +echo "* Wait and assert Bob's incognito account balance... " +wait_assert_state ${MRENCLAVE} ${ICGACCOUNTBOB} balance ${AMOUNT_TRANSFER} +echo "✔ ok" + +# Test the nonce handling, using Bob's incognito account as the sender as Charlie's +# balance needs to be verified in the second round while Bob is newly created each time + +echo "* Create a new incognito account for Charlie" +ICGACCOUNTCHARLIE=$(${CLIENT} trusted --mrenclave ${MRENCLAVE} new-account) +echo " Charlie's incognito account = ${ICGACCOUNTCHARLIE}" +echo "" + +echo "* Assert Bob's incognito initial nonce..." +assert_state ${MRENCLAVE} ${ICGACCOUNTBOB} nonce 0 +echo "✔ ok" +echo "" + +echo "* Send 3 consecutive 0.2 UNIT balance Transfer Bob -> Charlie" +for i in $(seq 1 3); do + # use direct calls so they are submitted to the top pool synchronously + $CLIENT trusted $CALLTYPE --mrenclave ${MRENCLAVE} transfer ${ICGACCOUNTBOB} ${ICGACCOUNTCHARLIE} $(( AMOUNT_TRANSFER / 10 )) +done +echo "" + +echo "* Assert Bob's incognito current nonce..." +wait_assert_state ${MRENCLAVE} ${ICGACCOUNTBOB} nonce 3 +echo "✔ ok" +echo "" + +echo "* Send a 2 UNIT balance Transfer Bob -> Charlie (that will fail)" +$CLIENT trusted $CALLTYPE --mrenclave ${MRENCLAVE} transfer ${ICGACCOUNTBOB} ${ICGACCOUNTCHARLIE} ${AMOUNT_TRANSFER} +echo "" + +echo "* Assert Bob's incognito nonce..." +# the nonce should be increased nontheless, even for the failed tx +wait_assert_state ${MRENCLAVE} ${ICGACCOUNTBOB} nonce 4 +echo "✔ ok" +echo "" + +echo "* Send another 0.2 UNIT balance Transfer Bob -> Charlie" +$CLIENT trusted $CALLTYPE --mrenclave ${MRENCLAVE} transfer ${ICGACCOUNTBOB} ${ICGACCOUNTCHARLIE} $(( AMOUNT_TRANSFER / 10 )) +echo "" + +echo "* Assert Bob's incognito nonce..." +wait_assert_state ${MRENCLAVE} ${ICGACCOUNTBOB} nonce 5 +echo "✔ ok" +echo "" + +echo "* Wait and assert Bob's incognito account balance... " +# in total 4 balance transfer should go through => 1.2 UNIT remaining +wait_assert_state ${MRENCLAVE} ${ICGACCOUNTBOB} balance $(( AMOUNT_TRANSFER * 6 / 10 )) +echo "✔ ok" + +echo "" +echo "-----------------------" +echo "✔ The $TEST test passed!" +echo "-----------------------" +echo "" \ No newline at end of file diff --git a/bitacross-worker/cli/demo_shielding_unshielding_using_shard_vault_on_target_a.sh b/bitacross-worker/cli/demo_shielding_unshielding_using_shard_vault_on_target_a.sh new file mode 100755 index 0000000000..9ccf34c84d --- /dev/null +++ b/bitacross-worker/cli/demo_shielding_unshielding_using_shard_vault_on_target_a.sh @@ -0,0 +1,302 @@ +#!/bin/bash + +# to make sure the script aborts when (sub-)function exits abnormally +set -e + +# Demonstrates how to shield tokens from the parentchain into the sidechain. +# +# setup: +# run all on localhost: +# integritee-node purge-chain --dev +# integritee-node --dev -lruntime=debug +# rm light_client_db.bin +# export RUST_LOG=integritee_service=info,ita_stf=debug +# integritee-service init_shard +# integritee-service shielding-key +# integritee-service signing-key +# integritee-service run +# +# then run this script + +# usage: +# demo_shielding_unshielding.sh -p -P -t -m file +# +# TEST_BALANCE_RUN is either "first" or "second" +# if -m file is set, the mrenclave will be read from file + +while getopts ":m:p:P:t:u:V:C:a:A:" opt; do + case $opt in + t) + TEST=$OPTARG + ;; + m) + READ_MRENCLAVE=$OPTARG + ;; + p) + INTEGRITEE_RPC_PORT=$OPTARG + ;; + a) + TARGET_A_RPC_PORT=$OPTARG + ;; + P) + WORKER_1_PORT=$OPTARG + ;; + u) + INTEGRITEE_RPC_URL=$OPTARG + ;; + A) + TARGET_A_RPC_URL=$OPTARG + ;; + V) + WORKER_1_URL=$OPTARG + ;; + C) + CLIENT_BIN=$OPTARG + ;; + *) + echo "invalid arg ${OPTARG}" + exit 1 + esac +done + +# Using default port if none given as arguments. +INTEGRITEE_RPC_PORT=${INTEGRITEE_RPC_PORT:-9944} +INTEGRITEE_RPC_URL=${INTEGRITEE_RPC_URL:-"ws://127.0.0.1"} + +TARGET_A_RPC_PORT=${TARGET_A_RPC_PORT:-9954} +TARGET_A_RPC_URL=${TARGET_A_RPC_URL:-"ws://127.0.0.1"} + +WORKER_1_PORT=${WORKER_1_PORT:-2000} +WORKER_1_URL=${WORKER_1_URL:-"wss://127.0.0.1"} + +CLIENT_BIN=${CLIENT_BIN:-"./../bin/integritee-cli"} + +echo "Using client binary ${CLIENT_BIN}" +${CLIENT_BIN} --version +echo "Using integritee node uri ${INTEGRITEE_RPC_URL}:${INTEGRITEE_RPC_PORT}" +echo "Using target_a node uri ${TARGET_A_RPC_URL}:${TARGET_A_RPC_PORT}" +echo "Using trusted-worker uri ${WORKER_1_URL}:${WORKER_1_PORT}" +echo "" + +# the parentchain token is 12 decimal +UNIT=$(( 10 ** 12 )) +FEE_TOLERANCE=$((10 ** 11)) + +# make these amounts greater than ED +AMOUNT_SHIELD=$(( 6 * UNIT )) +AMOUNT_TRANSFER=$(( 2 * UNIT )) +AMOUNT_UNSHIELD=$(( 1 * UNIT )) + +CLIENT="${CLIENT_BIN} -p ${INTEGRITEE_RPC_PORT} -P ${WORKER_1_PORT} -u ${INTEGRITEE_RPC_URL} -U ${WORKER_1_URL}" + +# for talking to TARGET_A L1 +CLIENT_A="${CLIENT_BIN} -p ${TARGET_A_RPC_PORT} -P ${WORKER_1_PORT} -u ${TARGET_A_RPC_URL} -U ${WORKER_1_URL}" + +# offchain-worker only suppports indirect calls +CALLTYPE= +case "$FLAVOR_ID" in + sidechain) CALLTYPE="--direct" ;; + offchain-worker) : ;; + *) CALLTYPE="--direct" ;; +esac +echo "using call type: ${CALLTYPE} (empty means indirect)" + +# interval and max rounds to wait to check the given account balance in sidechain +WAIT_INTERVAL_SECONDS=6 +WAIT_ROUNDS=20 + +# Poll and assert the given account's state is equal to expected, +# with timeout WAIT_INTERVAL_SECONDS * WAIT_ROUNDS +# usage: +# wait_assert_state +# the `state-name` has to be the supported subcommand, e.g. `balance`, `nonce` +function wait_assert_state() +{ + for i in $(seq 1 $WAIT_ROUNDS); do + sleep $WAIT_INTERVAL_SECONDS + state=$(${CLIENT} trusted --mrenclave "$1" "$3" "$2") + if (( $4 >= state ? $4 - state < FEE_TOLERANCE : state - $4 < FEE_TOLERANCE)); then + return + else + echo -n "." + fi + done + echo + echo "Assert $2 $3 failed, expected = $4, actual = $state, tolerance = $FEE_TOLERANCE" + exit 1 +} + +function wait_assert_state_target_a() +{ + for i in $(seq 1 $WAIT_ROUNDS); do + sleep $WAIT_INTERVAL_SECONDS + state=$(${CLIENT_A} "$2" "$1") + if (( $4 >= state ? $4 - state < FEE_TOLERANCE : state - $4 < FEE_TOLERANCE)); then + return + else + echo -n "." + fi + done + echo + echo "Assert $2 $3 failed, expected = $4, actual = $state, tolerance = $FEE_TOLERANCE" + exit 1 +} +# Do a live query and assert the given account's state is equal to expected +# usage: +# assert_state +function assert_state() +{ + state=$(${CLIENT} trusted --mrenclave "$1" "$3" "$2") + if [ -z "$state" ]; then + echo "Query $2 $3 failed" + exit 1 + fi + + if [ $state -eq "$4" ]; then + return + fi + echo + echo "Assert $2 $3 failed, expected = $4, actual = $state" + exit 1 +} + +echo "* Query on-chain enclave registry:" +${CLIENT} list-workers +echo "" + +if [ "$READ_MRENCLAVE" = "file" ] +then + read MRENCLAVE <<< $(cat ~/mrenclave.b58) + echo "Reading MRENCLAVE from file: ${MRENCLAVE}" +else + # this will always take the first MRENCLAVE found in the registry !! + read MRENCLAVE <<< $($CLIENT list-workers | awk '/ MRENCLAVE: / { print $2; exit }') + echo "Reading MRENCLAVE from worker list: ${MRENCLAVE}" +fi +[[ -z $MRENCLAVE ]] && { echo "MRENCLAVE is empty. cannot continue" ; exit 1; } + + +echo "* Create a new incognito account for Bob" +ICGACCOUNTBOB=$(${CLIENT} trusted --mrenclave ${MRENCLAVE} new-account) +echo " Bob's incognito account = ${ICGACCOUNTBOB}" +echo "" + +echo "* Query shard vault account" +VAULT=$(${CLIENT} trusted get-shard-vault) +echo " shard vault account = ${VAULT}" +echo "" + +# Asssert the initial balance of Charlie incognito +# The initial balance of Bob incognito should always be 0, as Bob is newly created +BALANCE_INCOGNITO_CHARLIE=0 +BALANCE_A_FERDIE=$(${CLIENT_A} balance //Ferdie) + +case $TEST in + first) + wait_assert_state ${MRENCLAVE} //Charlie balance 0 ;; + second) + wait_assert_state ${MRENCLAVE} //Charlie balance $(( AMOUNT_SHIELD - AMOUNT_TRANSFER - AMOUNT_UNSHIELD )) + BALANCE_INCOGNITO_CHARLIE=$(( AMOUNT_SHIELD - AMOUNT_TRANSFER - AMOUNT_UNSHIELD )) ;; + *) + echo "assuming first run of test" + wait_assert_state ${MRENCLAVE} //Charlie balance 0 ;; +esac + +echo "* Shield ${AMOUNT_SHIELD} tokens from TARGET_A to Charlie's account on L2" +${CLIENT_A} transfer //Alice //Charlie $((AMOUNT_SHIELD * 2)) +${CLIENT_A} transfer //Charlie ${VAULT} ${AMOUNT_SHIELD} +echo "" + +echo "* Wait and assert Charlie's L2 account balance... " +wait_assert_state ${MRENCLAVE} //Charlie balance $(( BALANCE_INCOGNITO_CHARLIE + AMOUNT_SHIELD )) +echo "✔ ok" + +echo "* Wait and assert Bob's incognito account balance... " +wait_assert_state ${MRENCLAVE} ${ICGACCOUNTBOB} balance 0 +echo "✔ ok" +echo "" + +echo "* Send ${AMOUNT_TRANSFER} funds from Charlie's L2 account to Bob's incognito account" +$CLIENT trusted $CALLTYPE --mrenclave ${MRENCLAVE} transfer //Charlie ${ICGACCOUNTBOB} ${AMOUNT_TRANSFER} +echo "" + +echo "* Wait and assert Charlie's L2 account balance... " +wait_assert_state ${MRENCLAVE} //Charlie balance $(( BALANCE_INCOGNITO_CHARLIE + AMOUNT_SHIELD - AMOUNT_TRANSFER )) +echo "✔ ok" + +echo "* Wait and assert Bob's incognito account balance... " +wait_assert_state ${MRENCLAVE} ${ICGACCOUNTBOB} balance ${AMOUNT_TRANSFER} +echo "✔ ok" +echo "" + +echo "* Un-shield ${AMOUNT_UNSHIELD} tokens from Charlie's incognito account to Ferie's L1 account" +${CLIENT} trusted $CALLTYPE --mrenclave ${MRENCLAVE} unshield-funds //Charlie //Ferdie ${AMOUNT_UNSHIELD} +echo "" + +echo "* Wait and assert Charlie's incognito account balance... " +wait_assert_state ${MRENCLAVE} //Charlie balance $(( BALANCE_INCOGNITO_CHARLIE + AMOUNT_SHIELD - AMOUNT_TRANSFER - AMOUNT_UNSHIELD )) +echo "✔ ok" + +echo "* Wait and assert Ferdie's Target A account balance... " +wait_assert_state_target_a //Ferdie balance $(( BALANCE_A_FERDIE + AMOUNT_UNSHIELD )) +echo "✔ ok" + +echo "* Wait and assert Bob's incognito account balance... " +wait_assert_state ${MRENCLAVE} ${ICGACCOUNTBOB} balance ${AMOUNT_TRANSFER} +echo "✔ ok" + +# Test the nonce handling, using Bob's incognito account as the sender as Charlie's +# balance needs to be verified in the second round while Bob is newly created each time + +echo "* Create a new incognito account for Charlie" +ICGACCOUNTCHARLIE=$(${CLIENT} trusted --mrenclave ${MRENCLAVE} new-account) +echo " Charlie's incognito account = ${ICGACCOUNTCHARLIE}" +echo "" + + +echo "* Assert Bob's incognito initial nonce..." +assert_state ${MRENCLAVE} ${ICGACCOUNTBOB} nonce 0 +echo "✔ ok" +echo "" + +echo "* Send 3 consecutive 0.2 UNIT balance Transfer Bob -> Charlie" +for i in $(seq 1 3); do + # use direct calls so they are submitted to the top pool synchronously + $CLIENT trusted $CALLTYPE --mrenclave ${MRENCLAVE} transfer ${ICGACCOUNTBOB} ${ICGACCOUNTCHARLIE} $(( AMOUNT_TRANSFER / 10 )) +done +echo "" + +echo "* Assert Bob's incognito current nonce..." +wait_assert_state ${MRENCLAVE} ${ICGACCOUNTBOB} nonce 3 +echo "✔ ok" +echo "" + +echo "* Send a 2 UNIT balance Transfer Bob -> Charlie (that will fail)" +$CLIENT trusted $CALLTYPE --mrenclave ${MRENCLAVE} transfer ${ICGACCOUNTBOB} ${ICGACCOUNTCHARLIE} ${AMOUNT_TRANSFER} +echo "" + +echo "* Assert Bob's incognito nonce..." +# the nonce should be increased nontheless, even for the failed tx +wait_assert_state ${MRENCLAVE} ${ICGACCOUNTBOB} nonce 4 +echo "✔ ok" +echo "" + +echo "* Send another 0.2 UNIT balance Transfer Bob -> Charlie" +$CLIENT trusted $CALLTYPE --mrenclave ${MRENCLAVE} transfer ${ICGACCOUNTBOB} ${ICGACCOUNTCHARLIE} $(( AMOUNT_TRANSFER / 10 )) +echo "" + +echo "* Assert Bob's incognito nonce..." +wait_assert_state ${MRENCLAVE} ${ICGACCOUNTBOB} nonce 5 +echo "✔ ok" +echo "" + +echo "* Wait and assert Bob's incognito account balance... " +# in total 4 balance transfer should go through => 1.2 UNIT remaining +wait_assert_state ${MRENCLAVE} ${ICGACCOUNTBOB} balance $(( AMOUNT_TRANSFER * 6 / 10 )) +echo "✔ ok" + +echo "" +echo "-----------------------" +echo "✔ The $TEST test passed!" +echo "-----------------------" +echo "" diff --git a/bitacross-worker/cli/demo_sidechain.sh b/bitacross-worker/cli/demo_sidechain.sh new file mode 100755 index 0000000000..dceb28503e --- /dev/null +++ b/bitacross-worker/cli/demo_sidechain.sh @@ -0,0 +1,178 @@ +#!/bin/bash + +# Sidechain Demo: +# +# Demonstrates that transfers happening on worker1 are communicated via sidechain blocks to worker2. +# It does essentially the same as `m8.sh`, but in one script and more streamlined. +# +# setup: +# run all on localhost: +# litentry-node purge-chain --dev +# litentry-node --tmp --dev -lruntime=debug +# rm light_client_db.bin +# export RUST_LOG=bitacross_worker=info,ita_stf=debug +# bitacross-worker init_shard +# bitacross-worker shielding-key +# bitacross-worker signing-key +# bitacross-worker run +# +# Then run this script. +# +# usage: +# export RUST_LOG_LOG=bitacross-cli=info,ita_stf=info +# demo_sidechain.sh -p -A -B -m file +# +# TEST_BALANCE_RUN is either "first" or "second" +# if -m file is set, the mrenclave will be read from file. + +while getopts ":m:p:A:B:t:u:W:V:C:" opt; do + case $opt in + m) + READ_MRENCLAVE=$OPTARG + ;; + p) + LITENTRY_RPC_PORT=$OPTARG + ;; + A) + WORKER_1_PORT=$OPTARG + ;; + B) + WORKER_2_PORT=$OPTARG + ;; + u) + LITENTRY_RPC_URL=$OPTARG + ;; + V) + WORKER_1_URL=$OPTARG + ;; + W) + WORKER_2_URL=$OPTARG + ;; + C) + CLIENT_BIN=$OPTARG + ;; + *) + echo "invalid arg ${OPTARG}" + exit 1 + esac +done + +# Using default port if none given as arguments. +LITENTRY_RPC_PORT=${LITENTRY_RPC_PORT:-9944} +LITENTRY_RPC_URL=${LITENTRY_RPC_URL:-"ws://127.0.0.1"} + +WORKER_1_PORT=${WORKER_1_PORT:-2000} +WORKER_1_URL=${WORKER_1_URL:-"wss://127.0.0.1"} + +WORKER_2_PORT=${WORKER_2_PORT:-3000} +WORKER_2_URL=${WORKER_2_URL:-"wss://127.0.0.1"} + +CLIENT_BIN=${CLIENT_BIN:-"./../bin/bitacross-cli"} + +echo "Using client binary ${CLIENT_BIN}" +${CLIENT_BIN} --version +echo "Using node uri ${LITENTRY_RPC_URL}:${LITENTRY_RPC_PORT}" +echo "Using trusted-worker 1 uri ${WORKER_1_URL}:${WORKER_1_PORT}" +echo "Using trusted-worker 2 uri ${WORKER_2_URL}:${WORKER_2_PORT}" + +# the parentchain token is 12 decimal +UNIT=$(( 10 ** 12 )) +FEE_TOLERANCE=$((10 ** 11)) + +INITIALFUNDS=$((5 * UNIT)) +AMOUNTTRANSFER=$((2 * UNIT)) + +CLIENTWORKER1="${CLIENT_BIN} -p ${LITENTRY_RPC_PORT} -P ${WORKER_1_PORT} -u ${LITENTRY_RPC_URL} -U ${WORKER_1_URL}" +CLIENTWORKER2="${CLIENT_BIN} -p ${LITENTRY_RPC_PORT} -P ${WORKER_2_PORT} -u ${LITENTRY_RPC_URL} -U ${WORKER_2_URL}" + +if [ "$READ_MRENCLAVE" = "file" ] +then + read MRENCLAVE <<< $(cat ~/mrenclave.b58) + echo "Reading MRENCLAVE from file: ${MRENCLAVE}" +else + # This will always take the first MRENCLAVE found in the registry !! + read MRENCLAVE <<< $($CLIENTWORKER1 list-workers | awk '/ MRENCLAVE: / { print $2; exit }') + echo "Reading MRENCLAVE from worker list: ${MRENCLAVE}" +fi +[[ -z $MRENCLAVE ]] && { echo "MRENCLAVE is empty. cannot continue" ; exit 1; } + +echo "" +echo "* Create a new incognito account for Alice" +ICGACCOUNTALICE=//AliceIncognito +ICGACCOUNTALICE_PUBKEY=0x50503350955afe8a107d6f115dc253eb5d75a3fe37a90b373db26cc12e3c6661 +echo " Alice's incognito account = ${ICGACCOUNTALICE}" +echo "" + +echo "* Create a new incognito account for Bob" +ICGACCOUNTBOB=//BobIncognito +ICGACCOUNTBOB_PUBKEY=0xc24c5b3969d8ec4ca8a655a98dcc136d5d4c29d1206ffe7721e80ebdfa1d0b77 +echo " Bob's incognito account = ${ICGACCOUNTBOB}" +echo "" + +echo "* Issue ${INITIALFUNDS} tokens to Alice's incognito account (on worker 1)" +${CLIENTWORKER1} trusted --mrenclave ${MRENCLAVE} --direct set-balance ${ICGACCOUNTALICE} ${INITIALFUNDS} +echo "" + +# see bob's initial balance to 0 +${CLIENTWORKER1} trusted --mrenclave ${MRENCLAVE} --direct set-balance ${ICGACCOUNTBOB} 0 + +echo "Get balance of Alice's incognito account (on worker 1)" +# ${CLIENTWORKER1} trusted --mrenclave ${MRENCLAVE} balance ${ICGACCOUNTALICE} +# ICGACCOUNTALICE's public key is 0x50503350955afe8a107d6f115dc253eb5d75a3fe37a90b373db26cc12e3c6661 +${CLIENTWORKER1} trusted --mrenclave ${MRENCLAVE} get-storage System Account ${ICGACCOUNTALICE_PUBKEY} +echo "" + +# Send funds from Alice to Bobs account, on worker 1. +echo "* First transfer: Send ${AMOUNTTRANSFER} funds from Alice's incognito account to Bob's incognito account (on worker 1)" +$CLIENTWORKER1 trusted --mrenclave ${MRENCLAVE} --direct transfer ${ICGACCOUNTALICE} ${ICGACCOUNTBOB} ${AMOUNTTRANSFER} +echo "" + +# Prevent nonce clash when sending direct trusted calls to different workers. +echo "* Waiting 2 seconds" +sleep 2 +echo "" + +# Send funds from Alice to Bobs account, on worker 2. +echo "* Second transfer: Send ${AMOUNTTRANSFER} funds from Alice's incognito account to Bob's incognito account (on worker 2)" +$CLIENTWORKER2 trusted --mrenclave ${MRENCLAVE} --direct transfer ${ICGACCOUNTALICE} ${ICGACCOUNTBOB} ${AMOUNTTRANSFER} +echo "" + +# Prevent getter being executed too early and returning an outdated result, before the transfer was made. +echo "* Waiting 6 seconds" +sleep 6 +echo "" + +echo "* Get balance of Alice's incognito account (on worker 1)" +# ALICE_BALANCE=$(${CLIENTWORKER1} trusted --mrenclave ${MRENCLAVE} balance ${ICGACCOUNTALICE} | xargs) +ALICE_BALANCE=$(${CLIENTWORKER1} trusted --mrenclave ${MRENCLAVE} get-storage System Account ${ICGACCOUNTALICE_PUBKEY} | jq ".data.free" | xargs) +echo "$ALICE_BALANCE" +echo "" + +echo "* Get balance of Bob's incognito account (on worker 1)" +# BOB_BALANCE=$(${CLIENTWORKER1} trusted --mrenclave ${MRENCLAVE} balance ${ICGACCOUNTBOB} | xargs) +BOB_BALANCE=$(${CLIENTWORKER1} trusted --mrenclave ${MRENCLAVE} get-storage System Account ${ICGACCOUNTBOB_PUBKEY} | jq ".data.free" | xargs) +echo "$BOB_BALANCE" +echo "" + +ALICE_EXPECTED_BALANCE=$(( 1 * UNIT )) +BOB_EXPECTED_BALANCE=$(( 4 * UNIT )) + +echo "* Verifying Alice's balance" +if (( ALICE_BALANCE >= ALICE_EXPECTED_BALANCE ? ALICE_BALANCE - ALICE_EXPECTED_BALANCE > FEE_TOLERANCE : ALICE_EXPECTED_BALANCE - ALICE_BALANCE > FEE_TOLERANCE)); then + echo "Alice's balance is wrong (expected: $ALICE_EXPECTED_BALANCE, actual: $ALICE_BALANCE), tolerance = $FEE_TOLERANCE" + exit 1 +else + echo "Alice's balance is correct ($ALICE_BALANCE)" +fi +echo "" + +echo "* Verifying Bob's balance" +if [ "$BOB_BALANCE" -ne "$BOB_EXPECTED_BALANCE" ]; then + echo "Bob's balance is wrong (expected: $BOB_EXPECTED_BALANCE, actual: $BOB_BALANCE)" + exit 1 +else + echo "Bob's balance is correct ($BOB_BALANCE)" +fi +echo "" + +exit 0 \ No newline at end of file diff --git a/bitacross-worker/cli/demo_smart_contract.sh b/bitacross-worker/cli/demo_smart_contract.sh new file mode 100755 index 0000000000..dd0aad2508 --- /dev/null +++ b/bitacross-worker/cli/demo_smart_contract.sh @@ -0,0 +1,108 @@ +#!/bin/bash + +# Deploys a simple counter smart contract on our EVM sidechain and increments the value. +# +# setup: +# run all on localhost: +# litentry-node purge-chain --dev +# litentry-node --tmp --dev -lruntime=debug +# export RUST_LOG=litentry_worker=info,ita_stf=debug +# bitacross-worker run +# +# then run this script + +# usage: +# export RUST_LOG_LOG=bitacross-cli=info,ita_stf=info +# demo_smart_contract.sh -p -P + +while getopts ":p:A:u:V:C:" opt; do + case $opt in + p) + LITENTRY_RPC_PORT=$OPTARG + ;; + A) + WORKER_PORT=$OPTARG + ;; + u) + LITENTRY_RPC_URL=$OPTARG + ;; + V) + WORKER_URL=$OPTARG + ;; + C) + CLIENT_BIN=$OPTARG + ;; + *) + echo "invalid arg ${OPTARG}" + exit 1 + esac +done + +# Bytecode from Counter.sol with slightly modified values +SMARTCONTRACT="608060405234801561001057600080fd5b50602260008190555033600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550610378806100696000396000f3fe6080604052600436106100435760003560e01c80631003e2d21461004e57806333cf508014610077578063371303c0146100a257806358992216146100b957610044565b5b6042600081905550005b34801561005a57600080fd5b50610075600480360381019061007091906101e4565b6100e4565b005b34801561008357600080fd5b5061008c610140565b604051610099919061024a565b60405180910390f35b3480156100ae57600080fd5b506100b7610149565b005b3480156100c557600080fd5b506100ce6101a5565b6040516100db919061022f565b60405180910390f35b806000808282546100f59190610265565b9250508190555033600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60008054905090565b600160008082825461015b9190610265565b9250508190555033600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000813590506101de8161032b565b92915050565b6000602082840312156101fa576101f9610326565b5b6000610208848285016101cf565b91505092915050565b61021a816102bb565b82525050565b610229816102ed565b82525050565b60006020820190506102446000830184610211565b92915050565b600060208201905061025f6000830184610220565b92915050565b6000610270826102ed565b915061027b836102ed565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038211156102b0576102af6102f7565b5b828201905092915050565b60006102c6826102cd565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600080fd5b610334816102ed565b811461033f57600080fd5b5056fea26469706673582212206242c58933a5e80fcfdd7f0044569af44caa21c61740067483a287cc361fc5b464736f6c63430008070033" +INCFUNTION="371303c0" +DEFAULTFUNCTION="371303c1" +ADDFUNCTION="1003e2d20000000000000000000000000000000000000000000000000000000000000003" + + +# using default port if none given as arguments +LITENTRY_RPC_PORT=${LITENTRY_RPC_PORT:-9944} +LITENTRY_RPC_URL=${LITENTRY_RPC_URL:-"ws://127.0.0.1"} + +WORKER_PORT=${WORKER_PORT:-2000} +WORKER_URL=${WORKER_URL:-"wss://127.0.0.1"} + + +CLIENT_BIN=${CLIENT_BIN:-"./../bin/bitacross-cli"} + +echo "Using client binary ${CLIENT_BIN}" +${CLIENT_BIN} --version +echo "Using node uri ${LITENTRY_RPC_URL}:${LITENTRY_RPC_PORT}" +echo "Using trusted-worker uri ${WORKER_URL}:${WORKER_PORT}" + +CLIENTWORKER="${CLIENT_BIN} -p ${LITENTRY_RPC_PORT} -P ${WORKER_PORT} -u ${LITENTRY_RPC_URL} -U ${WORKER_URL}" + + +# this will always take the first MRENCLAVE found in the registry !! +read -r MRENCLAVE <<< "$($CLIENTWORKER list-workers | awk '/ MRENCLAVE: / { print $2; exit }')" +echo "Reading MRENCLAVE from worker list: ${MRENCLAVE}" + +ACCOUNTALICE=//Alice + +echo "Create smart contract" +${CLIENTWORKER} trusted --mrenclave ${MRENCLAVE} --direct evm-create ${ACCOUNTALICE} ${SMARTCONTRACT} +echo "" + +echo "Get storage" +${CLIENTWORKER} trusted --mrenclave ${MRENCLAVE} evm-read ${ACCOUNTALICE} 0x8a50db1e0f9452cfd91be8dc004ceb11cb08832f +echo "" + +echo "Call inc function" +${CLIENTWORKER} trusted --mrenclave ${MRENCLAVE} --direct evm-call ${ACCOUNTALICE} 0x8a50db1e0f9452cfd91be8dc004ceb11cb08832f ${INCFUNTION} +echo "" + +echo "Get storage" +${CLIENTWORKER} trusted --mrenclave ${MRENCLAVE} evm-read ${ACCOUNTALICE} 0x8a50db1e0f9452cfd91be8dc004ceb11cb08832f +echo "" + +echo "Call add 3 function" +${CLIENTWORKER} trusted --mrenclave ${MRENCLAVE} --direct evm-call ${ACCOUNTALICE} 0x8a50db1e0f9452cfd91be8dc004ceb11cb08832f ${ADDFUNCTION} +echo "" + +echo "Get storage" +RESULT=$(${CLIENTWORKER} trusted --mrenclave ${MRENCLAVE} evm-read ${ACCOUNTALICE} 0x8a50db1e0f9452cfd91be8dc004ceb11cb08832f | xargs) +echo $RESULT +echo "" + +EXPECTED_RETURN_VALUE="0x0000000000000000000000000000000000000000000000000000000000000026" + +echo "* Verifying correct return value" +if (("$RESULT" == "$EXPECTED_RETURN_VALUE")); then + echo "Smart contract return value is correct ($RESULT)" + exit 0 +else + echo "Smart contract return value is wrong (expected: $EXPECTED_RETURN_VALUE, actual: $RESULT)" + exit 1 +fi + +exit 0 diff --git a/bitacross-worker/cli/demo_teeracle_generic.sh b/bitacross-worker/cli/demo_teeracle_generic.sh new file mode 100755 index 0000000000..8c2de3bf87 --- /dev/null +++ b/bitacross-worker/cli/demo_teeracle_generic.sh @@ -0,0 +1,136 @@ +#!/bin/bash +set -euo pipefail + +trap "echo The demo is terminated (SIGINT); exit 1" SIGINT +trap "echo The demo is terminated (SIGTERM); exit 1" SIGTERM + +# Registers a teeracle with the parentchain, and publish some oracle data. +# +# Demo to show that an enclave can update the exchange rate only when +# 1. the enclave is registered at the pallet-teerex. +# 2. and that the code used is reliable -> the enclave has been put the teeracle whitelist via a governance or sudo +# call. +# +# The teeracle's whitelist has to be empty at the start. So the script needs to run with a clean node state. +# A registered mrenclave will be added in the whitelist by a sudo account. Here //Alice +# +# setup: +# run all on localhost: +# integritee-node purge-chain --dev +# integritee-node --dev -lpallet_teeracle=debug,parity_ws=error,aura=error,sc_basic_authorship=error +# integritee-service --clean-reset run (--skip-ra --dev) +# +# then run this script +# +# usage: +# demo_teeracle_generic.sh -p -P -d -i -u -V -C + +while getopts ":p:P:d:i:u:V:C:" opt; do + case $opt in + p) + LITENTRY_RPC_PORT=$OPTARG + ;; + P) + WORKER_1_PORT=$OPTARG + ;; + d) + DURATION=$OPTARG + ;; + i) + INTERVAL=$OPTARG + ;; + u) + LITENTRY_RPC_URL=$OPTARG + ;; + V) + WORKER_1_URL=$OPTARG + ;; + C) + CLIENT_BIN=$OPTARG + ;; + *) + echo "invalid arg ${OPTARG}" + exit 1 + esac +done + +# using default port if none given as arguments +LITENTRY_RPC_PORT=${LITENTRY_RPC_PORT:-9944} +LITENTRY_RPC_URL=${LITENTRY_RPC_URL:-"ws://127.0.0.1"} + +WORKER_1_PORT=${WORKER_1_PORT:-2000} +WORKER_1_URL=${WORKER_1_URL:-"wss://127.0.0.1"} + +CLIENT_BIN=${CLIENT_BIN:-"./../bin/bitacross-cli"} + +DURATION=${DURATION:-48} +INTERVAL=${INTERVAL:-86400} + +LISTEN_TO_ORACLE_EVENTS_CMD="oracle listen-to-oracle-events" +ADD_TO_WHITELIST_CMD="oracle add-to-whitelist" + +echo "Using client binary ${CLIENT_BIN}" +${CLIENT_BIN} --version +echo "Using node uri ${LITENTRY_RPC_URL}:${LITENTRY_RPC_PORT}" +echo "Using trusted-worker uri ${WORKER_1_URL}:${WORKER_1_PORT}" +echo "Using worker data update interval ${INTERVAL}" +echo "Count the update events for ${DURATION}" +echo "" + +OPEN_METEO="https://api.open-meteo.com/" +let "MIN_EXPECTED_NUM_OF_EVENTS=$DURATION/$INTERVAL-3" +echo "Minimum expected number of events with a single oracle source: ${MIN_EXPECTED_NUM_OF_EVENTS}" + +# let "MIN_EXPECTED_NUM_OF_EVENTS_2 = 2*$MIN_EXPECTED_NUM_OF_EVENTS" +# echo "Minimum expected number of events with two oracle sources: ${MIN_EXPECTED_NUM_OF_EVENTS_2}" + +CLIENT="${CLIENT_BIN} -p ${LITENTRY_RPC_PORT} -P ${WORKER_1_PORT} -u ${LITENTRY_RPC_URL} -U ${WORKER_1_URL}" + +echo "* Query on-chain enclave registry:" +${CLIENT} list-workers +echo "" + +# this will always take the first MRENCLAVE found in the registry !! +read MRENCLAVE <<< $($CLIENT list-workers | awk '/ MRENCLAVE: / { print $2; exit }') +echo "Reading MRENCLAVE from worker list: ${MRENCLAVE}" + +[[ -z $MRENCLAVE ]] && { echo "MRENCLAVE is empty. cannot continue" ; exit 1; } +echo "" + +echo "Listen to OracleUpdated events for ${DURATION} seconds. There should be no trusted oracle source!" + +read NO_EVENTS <<< $(${CLIENT} ${LISTEN_TO_ORACLE_EVENTS_CMD} ${DURATION} | awk '/ EVENTS_COUNT: / { print $2; exit }') +echo "Got ${NO_EVENTS} oracle updates when no trusted oracle source is in the whitelist" +echo "" + +echo "Add ${OPEN_METEO} for ${MRENCLAVE} as trusted oracle source" +${CLIENT} ${ADD_TO_WHITELIST_CMD} //Alice ${OPEN_METEO} ${MRENCLAVE} +echo "MRENCLAVE in whitelist for ${OPEN_METEO}" +echo "" + +echo "Listen to OracleUpdated events for ${DURATION} seconds, after a trusted oracle source has been added to the whitelist." +#${CLIENT} ${LISTEN_TO_ORACLE_EVENTS_CMD} ${DURATION} +#echo "" + +read EVENTS_COUNT <<< $($CLIENT ${LISTEN_TO_ORACLE_EVENTS_CMD} ${DURATION} | awk '/ EVENTS_COUNT: / { print $2; exit }') +echo "Got ${EVENTS_COUNT} oracle updates from the trusted oracle source in ${DURATION} second(s)" +echo "" + +echo "Results :" + +# the following test is for automated CI +# it only works if the teeracle's whitelist is empty at the start (run it from genesis) +if [ $EVENTS_COUNT -ge $MIN_EXPECTED_NUM_OF_EVENTS ]; then + if [ 0 -eq $NO_EVENTS ]; then + echo "test passed" + exit 0 + else + echo "The test ran through but we received OracleUpdated events before the enclave was added to the whitelist. Was the enclave previously whitelisted? Perhaps by another teeracle?" + exit 1 + fi +else +echo "test failed: Not enough events received for single oracle source: $EVENTS_COUNT. Should be greater than $MIN_EXPECTED_NUM_OF_EVENTS" +exit 1 +fi + +exit 1 diff --git a/bitacross-worker/cli/demo_teeracle_whitelist.sh b/bitacross-worker/cli/demo_teeracle_whitelist.sh new file mode 100755 index 0000000000..cfe48f8545 --- /dev/null +++ b/bitacross-worker/cli/demo_teeracle_whitelist.sh @@ -0,0 +1,157 @@ +#!/bin/bash +set -euo pipefail + +trap "echo The demo is terminated (SIGINT); exit 1" SIGINT +trap "echo The demo is terminated (SIGTERM); exit 1" SIGTERM + +# Registers a teeracle with the parentchain, and publish some oracle data. +# +# Demo to show that an enclave can update the exchange rate only when +# 1. the enclave is registered at the pallet-teerex. +# 2. and that the code used is reliable -> the enclave has been put the teeracle whitelist via a governance or sudo +# call. +# +# The teeracle's whitelist has to be empty at the start. So the script needs to run with a clean node state. +# A registered mrenclave will be added in the whitelist by a sudo account. Here //Alice +# +# setup: +# run all on localhost: +# integritee-node purge-chain --dev +# integritee-node --dev -lpallet_teeracle=debug,parity_ws=error,aura=error,sc_basic_authorship=error +# integritee-service --clean-reset run (--skip-ra --dev) +# +# then run this script +# +# usage: +# demo_teeracle_whitelist.sh -p -P -d -i -u -V -C + +while getopts ":p:P:d:i:u:V:C:" opt; do + case $opt in + p) + LITENTRY_RPC_PORT=$OPTARG + ;; + P) + WORKER_1_PORT=$OPTARG + ;; + d) + DURATION=$OPTARG + ;; + i) + INTERVAL=$OPTARG + ;; + u) + LITENTRY_RPC_URL=$OPTARG + ;; + V) + WORKER_1_URL=$OPTARG + ;; + C) + CLIENT_BIN=$OPTARG + ;; + *) + echo "invalid arg ${OPTARG}" + exit 1 + esac +done + +# using default port if none given as arguments +LITENTRY_RPC_PORT=${LITENTRY_RPC_PORT:-9944} +LITENTRY_RPC_URL=${LITENTRY_RPC_URL:-"ws://127.0.0.1"} + +WORKER_1_PORT=${WORKER_1_PORT:-2000} +WORKER_1_URL=${WORKER_1_URL:-"wss://127.0.0.1"} + +CLIENT_BIN=${CLIENT_BIN:-"./../bin/bitacross-cli"} + +DURATION=${DURATION:-48} +INTERVAL=${INTERVAL:-86400} + +LISTEN_TO_EXCHANGE_RATE_EVENTS_CMD="oracle listen-to-exchange-rate-events" +ADD_TO_WHITELIST_CMD="oracle add-to-whitelist" + +echo "Using client binary ${CLIENT_BIN}" +${CLIENT_BIN} --version +echo "Using node uri ${LITENTRY_RPC_URL}:${LITENTRY_RPC_PORT}" +echo "Using trusted-worker uri ${WORKER_1_URL}:${WORKER_1_PORT}" +echo "Using worker market data update interval ${INTERVAL}" +echo "Count the update events for ${DURATION} blocks" +echo "" + +COIN_GECKO="https://api.coingecko.com/" +COIN_MARKET_CAP="https://pro-api.coinmarketcap.com/" +let "MIN_EXPECTED_NUM_OF_EVENTS=$DURATION*6/$INTERVAL-3" +echo "Minimum expected number of events with a single oracle source: ${MIN_EXPECTED_NUM_OF_EVENTS}" + +let "MIN_EXPECTED_NUM_OF_EVENTS_2 = 2*$MIN_EXPECTED_NUM_OF_EVENTS" +echo "Minimum expected number of events with two oracle sources: ${MIN_EXPECTED_NUM_OF_EVENTS_2}" + +CLIENT="${CLIENT_BIN} -p ${LITENTRY_RPC_PORT} -P ${WORKER_1_PORT} -u ${LITENTRY_RPC_URL} -U ${WORKER_1_URL}" + +echo "* Query on-chain enclave registry:" +${CLIENT} list-workers +echo "" + +# this will always take the first MRENCLAVE found in the registry !! +read MRENCLAVE <<< $($CLIENT list-workers | awk '/ MRENCLAVE: / { print $2; exit }') +echo "Reading MRENCLAVE from worker list: ${MRENCLAVE}" + +[[ -z $MRENCLAVE ]] && { echo "MRENCLAVE is empty. cannot continue" ; exit 1; } +echo "" + +echo "Listen to ExchangeRateUpdated events for ${DURATION} blocks. There should be no trusted oracle source!" +#${CLIENT} ${LISTEN_TO_EXCHANGE_RATE_EVENTS_CMD} ${DURATION} +#echo "" + +read NO_EVENTS <<< $(${CLIENT} ${LISTEN_TO_EXCHANGE_RATE_EVENTS_CMD} ${DURATION} | awk '/ EVENTS_COUNT: / { print $2; exit }') +echo "Got ${NO_EVENTS} exchange rate updates when no trusted oracle source is in the whitelist" +echo "" + +echo "Add ${COIN_GECKO} for ${MRENCLAVE} as trusted oracle source" +${CLIENT} ${ADD_TO_WHITELIST_CMD} //Alice ${COIN_GECKO} ${MRENCLAVE} +echo "MRENCLAVE in whitelist for ${COIN_GECKO}" +echo "" + +echo "Listen to ExchangeRateUpdated events for ${DURATION} blocks, after a trusted oracle source has been added to the whitelist." +#${CLIENT} ${LISTEN_TO_EXCHANGE_RATE_EVENTS_CMD} ${DURATION} +#echo "" + +read EVENTS_COUNT <<< $($CLIENT ${LISTEN_TO_EXCHANGE_RATE_EVENTS_CMD} ${DURATION} | awk '/ EVENTS_COUNT: / { print $2; exit }') +echo "Got ${EVENTS_COUNT} exchange rate updates from the trusted oracle source in ${DURATION} blocks(s)" +echo "" + +echo "Add ${COIN_MARKET_CAP} for ${MRENCLAVE} as trusted oracle source" +${CLIENT} ${ADD_TO_WHITELIST_CMD} //Alice ${COIN_MARKET_CAP} ${MRENCLAVE} +echo "MRENCLAVE in whitelist for ${COIN_MARKET_CAP}" +echo "" + +echo "Listen to ExchangeRateUpdated events for ${DURATION} blocks, after a second trusted oracle source has been added to the whitelist." +#${CLIENT} ${LISTEN_TO_EXCHANGE_RATE_EVENTS_CMD} ${DURATION} +#echo "" + +read EVENTS_COUNT_2 <<< $($CLIENT ${LISTEN_TO_EXCHANGE_RATE_EVENTS_CMD} ${DURATION} | awk '/ EVENTS_COUNT: / { print $2; exit }') +echo "Got ${EVENTS_COUNT_2} exchange rate updates from 2 trusted oracle sources in ${DURATION} blocks(s)" +echo "" + +echo "Results :" + +# the following test is for automated CI +# it only works if the teeracle's whitelist is empty at the start (run it from genesis) +if [ $EVENTS_COUNT_2 -ge $MIN_EXPECTED_NUM_OF_EVENTS_2 ]; then + if [ $EVENTS_COUNT -ge $MIN_EXPECTED_NUM_OF_EVENTS ]; then + if [ 0 -eq $NO_EVENTS ]; then + echo "test passed" + exit 0 + else + echo "The test ran through but we received ExchangeRateUpdated events before the enclave was added to the whitelist. Was the enclave previously whitelisted? Perhaps by another teeracle?" + exit 1 + fi + else + echo "test failed: Not enough events received for single oracle source: $EVENTS_COUNT. Should be greater than $MIN_EXPECTED_NUM_OF_EVENTS" + exit 1 + fi +else + echo "test failed: Not enough events received for 2 oracle sources: $EVENTS_COUNT_2. Should be greater than $MIN_EXPECTED_NUM_OF_EVENTS_2" + exit 1 +fi + +exit 1 diff --git a/bitacross-worker/cli/lit_parentchain_nonce.sh b/bitacross-worker/cli/lit_parentchain_nonce.sh new file mode 100755 index 0000000000..505469f11b --- /dev/null +++ b/bitacross-worker/cli/lit_parentchain_nonce.sh @@ -0,0 +1,69 @@ +#!/bin/bash + +# Copyright 2020-2023 Trust Computing GmbH. + +while getopts ":p:A:B:u:W:V:C:" opt; do + case $opt in + p) + NPORT=$OPTARG + ;; + A) + WORKER1PORT=$OPTARG + ;; + u) + NODEURL=$OPTARG + ;; + V) + WORKER1URL=$OPTARG + ;; + C) + CLIENT_BIN=$OPTARG + ;; + esac +done + +# Using default port if none given as arguments. +NPORT=${NPORT:-9944} +NODEURL=${NODEURL:-"ws://127.0.0.1"} + +WORKER1PORT=${WORKER1PORT:-2000} +WORKER1URL=${WORKER1URL:-"wss://127.0.0.1"} + +CLIENT_BIN=${CLIENT_BIN:-"./../bin/bitacross-cli"} + +echo "Using client binary $CLIENT_BIN" +echo "Using node uri $NODEURL:$NPORT" +echo "Using trusted-worker uri $WORKER1URL:$WORKER1PORT" +echo "" + +CLIENT="$CLIENT_BIN -p $NPORT -P $WORKER1PORT -u $NODEURL -U $WORKER1URL" +echo "CLIENT is: $CLIENT" + +echo "* Query on-chain enclave registry:" +WORKERS=$($CLIENT list-workers) +echo "WORKERS: " +echo "${WORKERS}" +echo "" + +if [ "$READMRENCLAVE" = "file" ] +then + read MRENCLAVE <<< $(cat ~/mrenclave.b58) + echo "Reading MRENCLAVE from file: ${MRENCLAVE}" +else + # This will always take the first MRENCLAVE found in the registry !! + read MRENCLAVE <<< $(echo "$WORKERS" | awk '/ MRENCLAVE: / { print $2; exit }') + echo "Reading MRENCLAVE from worker list: ${MRENCLAVE}" +fi +[[ -z $MRENCLAVE ]] && { echo "MRENCLAVE is empty. cannot continue" ; exit 1; } + +sleep 10 +echo "* Send wrong parentchain extrinsic" +${CLIENT} trusted --mrenclave $MRENCLAVE --direct send-erroneous-parentchain-call +echo "" + +sleep 20 +# wait for 10 `ProcessedParentchainBlock` events, which should take around 2 min (1 worker) +# if the incoming parentchain extrinsic is blocked (due to the wrong nonce), there won't be +# such many events. +set -e +timeout -v --foreground 150s $CLIENT listen -e 10 diff --git a/bitacross-worker/cli/lit_set_heartbeat_timeout.sh b/bitacross-worker/cli/lit_set_heartbeat_timeout.sh new file mode 100755 index 0000000000..f062118c0a --- /dev/null +++ b/bitacross-worker/cli/lit_set_heartbeat_timeout.sh @@ -0,0 +1,85 @@ +#!/bin/bash + +# Copyright 2020-2023 Trust Computing GmbH. + +while getopts ":p:A:B:u:W:V:C:" opt; do + case $opt in + p) + NPORT=$OPTARG + ;; + A) + WORKER1PORT=$OPTARG + ;; + B) + WORKER2PORT=$OPTARG + ;; + u) + NODEURL=$OPTARG + ;; + V) + WORKER1URL=$OPTARG + ;; + W) + WORKER2URL=$OPTARG + ;; + C) + CLIENT_BIN=$OPTARG + ;; + esac +done + +# Using default port if none given as arguments. +NPORT=${NPORT:-9944} +NODEURL=${NODEURL:-"ws://127.0.0.1"} + +WORKER1PORT=${WORKER1PORT:-2000} +WORKER1URL=${WORKER1URL:-"wss://127.0.0.1"} + +CLIENT_BIN=${CLIENT_BIN:-"../bin/bitacross-cli"} + +LOG_FOLDER="./../log" + +echo "Using client binary $CLIENT_BIN" +echo "Using node uri $NODEURL:$NPORT" +echo "Using trusted-worker uri $WORKER1URL:$WORKER1PORT" +echo "" + +TIMEOUT=5000 # 5 seconds, smaller than 12s (the block duration) + +CLIENT="$CLIENT_BIN -p $NPORT -P $WORKER1PORT -u $NODEURL -U $WORKER1URL" +echo "CLIENT is: $CLIENT" + +echo "* Query on-chain enclave registry:" +WORKERS=$($CLIENT list-workers) +echo "WORKERS: " +echo "${WORKERS}" +echo "" + +if [ "$READMRENCLAVE" = "file" ] +then + read MRENCLAVE <<< $(cat ~/mrenclave.b58) + echo "Reading MRENCLAVE from file: ${MRENCLAVE}" +else + # This will always take the first MRENCLAVE found in the registry !! + read MRENCLAVE <<< $(echo "$WORKERS" | awk '/ MRENCLAVE: / { print $2; exit }') + echo "Reading MRENCLAVE from worker list: ${MRENCLAVE}" +fi +[[ -z $MRENCLAVE ]] && { echo "MRENCLAVE is empty. cannot continue" ; exit 1; } + + +# indirect call that will be sent to the parachain, it will be synchronously handled +sleep 10 +echo "* Set heartbeat timeout to $TIMEOUT" +${CLIENT} set-heartbeat-timeout "$TIMEOUT" +echo "" + +sleep 120 + +read MRENCLAVE <<< $($CLIENT list-workers | awk '/ MRENCLAVE: / { print $2; exit }') +if [[ -z $MRENCLAVE ]] +then + echo "All workers removed, test passed" +else + echo "Worker(s) still exist(s), test fail" + exit 1 +fi diff --git a/bitacross-worker/cli/src/attesteer/commands/mod.rs b/bitacross-worker/cli/src/attesteer/commands/mod.rs new file mode 100644 index 0000000000..70119bf399 --- /dev/null +++ b/bitacross-worker/cli/src/attesteer/commands/mod.rs @@ -0,0 +1,23 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 send_dcap_quote; +mod send_ias_attestation; + +pub use self::{ + send_dcap_quote::SendDcapQuoteCmd, send_ias_attestation::SendIasAttestationReportCmd, +}; diff --git a/bitacross-worker/cli/src/attesteer/commands/send_dcap_quote.rs b/bitacross-worker/cli/src/attesteer/commands/send_dcap_quote.rs new file mode 100644 index 0000000000..6ee0baf02f --- /dev/null +++ b/bitacross-worker/cli/src/attesteer/commands/send_dcap_quote.rs @@ -0,0 +1,65 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{command_utils::get_worker_api_direct, Cli}; +use itc_rpc_client::direct_client::DirectApi; +use itp_rpc::{Id, RpcRequest, RpcResponse, RpcReturnValue}; +use itp_types::DirectRequestStatus; +use itp_utils::FromHexPrefixed; +use log::*; +use std::fs::read_to_string; + +/// Forward DCAP quote for verification. +#[derive(Debug, Clone, Parser)] +pub struct SendDcapQuoteCmd { + /// Hex encoded DCAP quote filename. + quote: String, +} + +impl SendDcapQuoteCmd { + pub fn run(&self, cli: &Cli) { + let direct_api = get_worker_api_direct(cli); + let hex_encoded_quote = match read_to_string(&self.quote) { + Ok(hex_encoded_quote) => hex_encoded_quote, + Err(e) => panic!("Opening hex encoded DCAP quote file failed: {:?}", e), + }; + + let rpc_method = "attesteer_forwardDcapQuote".to_owned(); + let jsonrpc_call: String = RpcRequest::compose_jsonrpc_call( + Id::Text("1".to_string()), + rpc_method, + vec![hex_encoded_quote], + ) + .unwrap(); + + let rpc_response_str = direct_api.get(&jsonrpc_call).unwrap(); + + // Decode RPC response. + let Ok(rpc_response) = serde_json::from_str::(&rpc_response_str) else { + panic!("Can't parse RPC response: '{rpc_response_str}'"); + }; + let rpc_return_value = match RpcReturnValue::from_hex(&rpc_response.result) { + Ok(rpc_return_value) => rpc_return_value, + Err(e) => panic!("Failed to decode RpcReturnValue: {:?}", e), + }; + + match rpc_return_value.status { + DirectRequestStatus::Ok => println!("DCAP quote verification succeded."), + _ => error!("DCAP quote verification failed"), + } + } +} diff --git a/bitacross-worker/cli/src/attesteer/commands/send_ias_attestation.rs b/bitacross-worker/cli/src/attesteer/commands/send_ias_attestation.rs new file mode 100644 index 0000000000..af4128b138 --- /dev/null +++ b/bitacross-worker/cli/src/attesteer/commands/send_ias_attestation.rs @@ -0,0 +1,66 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 itc_rpc_client::direct_client::DirectApi; +use itp_rpc::{Id, RpcRequest, RpcResponse, RpcReturnValue}; +use itp_types::DirectRequestStatus; +use itp_utils::FromHexPrefixed; +use log::*; +use std::fs::read_to_string; + +use crate::{command_utils::get_worker_api_direct, Cli}; + +/// Forward IAS attestation report for verification. +#[derive(Debug, Clone, Parser)] +pub struct SendIasAttestationReportCmd { + /// Hex encoded IAS attestation report filename. + report: String, +} + +impl SendIasAttestationReportCmd { + pub fn run(&self, cli: &Cli) { + let direct_api = get_worker_api_direct(cli); + let hex_encoded_report = match read_to_string(&self.report) { + Ok(hex_encoded_report) => hex_encoded_report, + Err(e) => panic!("Opening hex encoded IAS attestation report file failed: {:?}", e), + }; + + let rpc_method = "attesteer_forwardIasAttestationReport".to_owned(); + let jsonrpc_call: String = RpcRequest::compose_jsonrpc_call( + Id::Text("1".to_string()), + rpc_method, + vec![hex_encoded_report], + ) + .unwrap(); + + let rpc_response_str = direct_api.get(&jsonrpc_call).unwrap(); + + // Decode RPC response. + let Ok(rpc_response) = serde_json::from_str::(&rpc_response_str) else { + panic!("Can't parse RPC response: '{rpc_response_str}'"); + }; + let rpc_return_value = match RpcReturnValue::from_hex(&rpc_response.result) { + Ok(rpc_return_value) => rpc_return_value, + Err(e) => panic!("Failed to decode RpcReturnValue: {:?}", e), + }; + + match rpc_return_value.status { + DirectRequestStatus::Ok => println!("IAS attestation report verification succeded."), + _ => error!("IAS attestation report verification failed"), + } + } +} diff --git a/bitacross-worker/cli/src/attesteer/mod.rs b/bitacross-worker/cli/src/attesteer/mod.rs new file mode 100644 index 0000000000..9f03c59065 --- /dev/null +++ b/bitacross-worker/cli/src/attesteer/mod.rs @@ -0,0 +1,41 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::Cli; + +use self::commands::{SendDcapQuoteCmd, SendIasAttestationReportCmd}; + +mod commands; + +/// Attesteer subcommands for the CLI. +#[derive(Debug, clap::Subcommand)] +pub enum AttesteerCommand { + /// Forward DCAP quote for verification. + SendDCAPQuote(SendDcapQuoteCmd), + + /// Forward IAS attestation report for verification. + SendIASAttestationReport(SendIasAttestationReportCmd), +} + +impl AttesteerCommand { + pub fn run(&self, cli: &Cli) { + match self { + AttesteerCommand::SendDCAPQuote(cmd) => cmd.run(cli), + AttesteerCommand::SendIASAttestationReport(cmd) => cmd.run(cli), + } + } +} diff --git a/bitacross-worker/cli/src/base_cli/commands/balance.rs b/bitacross-worker/cli/src/base_cli/commands/balance.rs new file mode 100644 index 0000000000..cea86ae48b --- /dev/null +++ b/bitacross-worker/cli/src/base_cli/commands/balance.rs @@ -0,0 +1,39 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{ + command_utils::{get_accountid_from_str, get_chain_api}, + Cli, CliResult, CliResultOk, +}; +use substrate_api_client::GetAccountInformation; + +#[derive(Parser)] +pub struct BalanceCommand { + /// AccountId in ss58check format + account: String, +} + +impl BalanceCommand { + pub(crate) fn run(&self, cli: &Cli) -> CliResult { + let api = get_chain_api(cli); + let accountid = get_accountid_from_str(&self.account); + let balance = + if let Some(data) = api.get_account_data(&accountid).unwrap() { data.free } else { 0 }; + println!("{}", balance); + Ok(CliResultOk::Balance { balance }) + } +} diff --git a/bitacross-worker/cli/src/base_cli/commands/faucet.rs b/bitacross-worker/cli/src/base_cli/commands/faucet.rs new file mode 100644 index 0000000000..be33b3bf86 --- /dev/null +++ b/bitacross-worker/cli/src/base_cli/commands/faucet.rs @@ -0,0 +1,61 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{ + command_utils::{get_accountid_from_str, get_chain_api}, + Cli, CliResult, CliResultOk, +}; +use my_node_runtime::{BalancesCall, RuntimeCall}; +use sp_keyring::AccountKeyring; +use sp_runtime::MultiAddress; +use std::vec::Vec; +use substrate_api_client::{ac_compose_macros::compose_extrinsic_offline, SubmitExtrinsic}; + +const PREFUNDING_AMOUNT: u128 = 1_000_000_000; + +#[derive(Parser)] +pub struct FaucetCommand { + /// Account(s) to be funded, ss58check encoded + #[clap(num_args = 1.., required = true)] + accounts: Vec, +} + +impl FaucetCommand { + pub(crate) fn run(&self, cli: &Cli) -> CliResult { + let mut api = get_chain_api(cli); + api.set_signer(AccountKeyring::Alice.pair().into()); + let mut nonce = api.get_nonce().unwrap(); + for account in &self.accounts { + let to = get_accountid_from_str(account); + #[allow(clippy::redundant_clone)] + let xt = compose_extrinsic_offline!( + api.signer().unwrap(), + RuntimeCall::Balances(BalancesCall::transfer { + dest: MultiAddress::Id(to.clone()), + value: PREFUNDING_AMOUNT + }), + api.extrinsic_params(nonce) + ); + // send and watch extrinsic until finalized + println!("Faucet drips to {} (Alice's nonce={})", to, nonce); + let _blockh = api.submit_extrinsic(xt).unwrap(); + nonce += 1; + } + + Ok(CliResultOk::None) + } +} diff --git a/bitacross-worker/cli/src/base_cli/commands/listen.rs b/bitacross-worker/cli/src/base_cli/commands/listen.rs new file mode 100644 index 0000000000..27a9b15811 --- /dev/null +++ b/bitacross-worker/cli/src/base_cli/commands/listen.rs @@ -0,0 +1,149 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{command_utils::get_chain_api, Cli, CliResult, CliResultOk}; +use base58::ToBase58; +use codec::Encode; +use log::*; +use my_node_runtime::{Hash, RuntimeEvent}; +use substrate_api_client::SubscribeEvents; + +#[derive(Parser)] +pub struct ListenCommand { + /// exit after given number of parentchain events + #[clap(short, long = "exit-after")] + events: Option, + + /// exit after given number of blocks + #[clap(short, long = "await-blocks")] + blocks: Option, +} + +impl ListenCommand { + pub(crate) fn run(&self, cli: &Cli) -> CliResult { + println!("{:?} {:?}", self.events, self.blocks); + let api = get_chain_api(cli); + info!("Subscribing to events"); + let mut count = 0u32; + let mut blocks = 0u32; + let mut subscription = api.subscribe_events().unwrap(); + loop { + if let Some(e) = self.events { + if count >= e { + return Ok(CliResultOk::None) + } + }; + if let Some(b) = self.blocks { + if blocks >= b { + return Ok(CliResultOk::None) + } + }; + + let event_results = subscription.next_events::().unwrap(); + blocks += 1; + match event_results { + Ok(evts) => + for evr in &evts { + println!("decoded: phase {:?} event {:?}", evr.phase, evr.event); + match &evr.event { + RuntimeEvent::Balances(be) => { + println!(">>>>>>>>>> balances event: {:?}", be); + match &be { + pallet_balances::Event::Transfer { from, to, amount } => { + println!("From: {:?}", from); + println!("To: {:?}", to); + println!("Value: {:?}", amount); + }, + _ => { + debug!("ignoring unsupported balances event"); + }, + } + }, + RuntimeEvent::Teerex(ee) => { + println!(">>>>>>>>>> integritee teerex event: {:?}", ee); + count += 1; + match &ee { + my_node_runtime::pallet_teerex::Event::AddedEnclave( + accountid, + url, + ) => { + println!( + "AddedEnclave: {:?} at url {}", + accountid, + String::from_utf8(url.to_vec()) + .unwrap_or_else(|_| "error".to_string()) + ); + }, + my_node_runtime::pallet_teerex::Event::RemovedEnclave( + accountid, + ) => { + println!("RemovedEnclave: {:?}", accountid); + }, + my_node_runtime::pallet_teerex::Event::Forwarded(shard) => { + println!( + "Forwarded request for shard {}", + shard.encode().to_base58() + ); + }, + my_node_runtime::pallet_teerex::Event::ProcessedParentchainBlock( + accountid, + block_hash, + merkle_root, + block_number, + ) => { + println!( + "ProcessedParentchainBlock from {} with hash {:?}, number {} and merkle root {:?}", + accountid, block_hash, merkle_root, block_number + ); + }, + my_node_runtime::pallet_teerex::Event::ShieldFunds( + incognito_account, + ) => { + println!("ShieldFunds for {:?}", incognito_account); + }, + my_node_runtime::pallet_teerex::Event::UnshieldedFunds( + public_account, + ) => { + println!("UnshieldFunds for {:?}", public_account); + }, + _ => debug!("ignoring unsupported teerex event: {:?}", ee), + } + }, + RuntimeEvent::Sidechain(ee) => { + println!(">>>>>>>>>> integritee sidechain event: {:?}", ee); + count += 1; + match &ee { + my_node_runtime::pallet_sidechain::Event::ProposedSidechainBlock( + accountid, + block_hash, + ) => { + println!( + "ProposedSidechainBlock from {} with hash {:?}", + accountid, block_hash + ); + }, + _ => debug!("ignoring unsupported sidechain event: {:?}", ee), + } + }, + _ => debug!("ignoring unsupported module event: {:?}", evr.event), + } + }, + Err(_) => error!("couldn't decode event record list"), + } + } + } +} diff --git a/bitacross-worker/cli/src/base_cli/commands/litentry/mod.rs b/bitacross-worker/cli/src/base_cli/commands/litentry/mod.rs new file mode 100644 index 0000000000..b5700e1258 --- /dev/null +++ b/bitacross-worker/cli/src/base_cli/commands/litentry/mod.rs @@ -0,0 +1,17 @@ +// Copyright 2020-2023 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . + +pub mod set_heartbeat_timeout; diff --git a/bitacross-worker/cli/src/base_cli/commands/litentry/set_heartbeat_timeout.rs b/bitacross-worker/cli/src/base_cli/commands/litentry/set_heartbeat_timeout.rs new file mode 100644 index 0000000000..f4efb49ae7 --- /dev/null +++ b/bitacross-worker/cli/src/base_cli/commands/litentry/set_heartbeat_timeout.rs @@ -0,0 +1,54 @@ +// Copyright 2020-2023 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . + +use crate::{command_utils::get_chain_api, Cli}; + +use crate::{CliResult, CliResultOk}; +use itp_node_api::api_client::TEEREX; +use log::*; +use sp_keyring::AccountKeyring; +use substrate_api_client::{ac_compose_macros::compose_extrinsic, SubmitAndWatch, XtStatus}; +#[derive(Parser)] +pub struct SetHeartbeatTimeoutCommand { + /// Heartbeat timeout + timeout: u64, +} + +impl SetHeartbeatTimeoutCommand { + pub(crate) fn run(&self, cli: &Cli) -> CliResult { + let mut chain_api = get_chain_api(cli); + + // has to be //Alice as this is the genesis admin for teerex pallet, + // otherwise `set_heartbeat_timeout` call won't work + chain_api.set_signer(AccountKeyring::Alice.pair().into()); + + // call set_heartbeat_timeout + let xt = compose_extrinsic!( + chain_api, + TEEREX, + "set_heartbeat_timeout", + codec::Compact(self.timeout) + ); + + let tx_hash = chain_api.submit_and_watch_extrinsic_until(xt, XtStatus::Finalized).unwrap(); + println!( + "[+] SetHeartbeatTimeoutCommand TrustedOperation got finalized. Hash: {:?}\n", + tx_hash + ); + + Ok(CliResultOk::None) + } +} diff --git a/bitacross-worker/cli/src/base_cli/commands/mod.rs b/bitacross-worker/cli/src/base_cli/commands/mod.rs new file mode 100644 index 0000000000..313a32249c --- /dev/null +++ b/bitacross-worker/cli/src/base_cli/commands/mod.rs @@ -0,0 +1,7 @@ +pub mod balance; +pub mod faucet; +pub mod listen; +pub mod litentry; +pub mod register_tcb_info; +pub mod shield_funds; +pub mod transfer; diff --git a/bitacross-worker/cli/src/base_cli/commands/register_tcb_info.rs b/bitacross-worker/cli/src/base_cli/commands/register_tcb_info.rs new file mode 100644 index 0000000000..7802794a09 --- /dev/null +++ b/bitacross-worker/cli/src/base_cli/commands/register_tcb_info.rs @@ -0,0 +1,146 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{ + command_utils::{get_chain_api, *}, + Cli, CliResult, CliResultOk, +}; +use itp_node_api::api_client::TEEREX; +use itp_types::{parentchain::Hash, OpaqueCall}; +use itp_utils::ToHexPrefixed; +use log::*; +use regex::Regex; +use serde::Deserialize; +use substrate_api_client::{ + ac_compose_macros::{compose_call, compose_extrinsic_offline}, + SubmitAndWatch, XtStatus, +}; +use urlencoding; + +#[derive(Debug, Deserialize)] +struct Platform { + fmspc: String, + #[serde(rename = "platform")] + _platform: String, +} + +#[derive(Parser)] +pub struct RegisterTcbInfoCommand { + /// Sender's parentchain AccountId in ss58check format. + sender: String, + /// Intel's Family-Model-Stepping-Platform-Custom SKU. 6-Byte non-prefixed hex value + #[clap(short, long, action, conflicts_with = "all")] + fmspc: Option, + /// registers all fmspc currently published by Intel + #[clap(short, long, action)] + all: bool, +} + +impl RegisterTcbInfoCommand { + pub(crate) fn run(&self, cli: &Cli) -> CliResult { + let mut chain_api = get_chain_api(cli); + + // Get the sender. + let from = get_pair_from_str(&self.sender); + chain_api.set_signer(from.into()); + + let fmspcs = if self.all { + trace!("fetching all fmspc's from api.trustedservices.intel.com"); + let fmspcs = reqwest::blocking::get( + "https://api.trustedservices.intel.com/sgx/certification/v4/fmspcs", + ) + .unwrap(); + let fmspcs: Vec = fmspcs.json().expect("Error parsing JSON"); + println!("{:?}", fmspcs); + fmspcs.into_iter().map(|f| f.fmspc).collect() + } else if let Some(fmspc) = self.fmspc.clone() { + vec![fmspc] + } else { + panic!("must specify either '--all' or '--fmspc'"); + }; + let mut nonce = chain_api.get_nonce().unwrap(); + let xt_hashes: Vec<(String, Option)> = fmspcs + .into_iter() + .map(|fmspc| { + println!( + "fetching tcb info for fmspc {} from api.trustedservices.intel.com", + fmspc + ); + let response = reqwest::blocking::get(format!( + "https://api.trustedservices.intel.com/sgx/certification/v4/tcb?fmspc={}", + fmspc + )) + .unwrap(); + //extract certificate chain from header + let certificate_chain = urlencoding::decode( + response.headers().get("TCB-Info-Issuer-Chain").unwrap().to_str().unwrap(), + ) + .unwrap() + .to_string(); + trace!("certificate chain: \n{}", certificate_chain); + + let body = response.text().unwrap(); + trace!("raw json: \n{}", body); + let re = Regex::new(r#"tcbInfo\"\s?:(\{.*\}),\s?\"signature"#).unwrap(); + let tcb_info = &re.captures(&body).unwrap()[1]; + let re = Regex::new(r#"\"signature\"\s?:\s?\"(.*)\"\}"#).unwrap(); + let intel_signature_hex = &re.captures(&body).unwrap()[1]; + trace!("TCB info: {}", tcb_info); + trace!("signature: {}", intel_signature_hex); + + let intel_signature = hex::decode(intel_signature_hex).unwrap(); + + let call = OpaqueCall::from_tuple(&compose_call!( + chain_api.metadata(), + TEEREX, + "register_tcb_info", + tcb_info, + intel_signature, + certificate_chain + )); + + trace!( + "encoded call to be sent as extrinsic with nonce {}: {}", + nonce, + call.to_hex() + ); + + let xt = compose_extrinsic_offline!( + chain_api.clone().signer().unwrap(), + call, + chain_api.extrinsic_params(nonce) + ); + nonce += 1; + match chain_api.submit_and_watch_extrinsic_until(xt, XtStatus::InBlock) { + Ok(xt_report) => { + println!( + "[+] register_tcb_info. extrinsic hash: {:?} / status: {:?}", + xt_report.extrinsic_hash, xt_report.status, + ); + (fmspc, Some(xt_report.extrinsic_hash)) + }, + Err(e) => { + error!("register_tcb_info extrinsic failed {:?}", e); + (fmspc, None) + }, + } + }) + .collect(); + println!("{:?}", xt_hashes); + Ok(CliResultOk::None) + } +} diff --git a/bitacross-worker/cli/src/base_cli/commands/shield_funds.rs b/bitacross-worker/cli/src/base_cli/commands/shield_funds.rs new file mode 100644 index 0000000000..ec45da50fb --- /dev/null +++ b/bitacross-worker/cli/src/base_cli/commands/shield_funds.rs @@ -0,0 +1,92 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{ + command_utils::{get_accountid_from_str, get_chain_api, *}, + Cli, CliError, CliResult, CliResultOk, +}; +use base58::FromBase58; +use codec::{Decode, Encode}; +use itp_node_api::api_client::TEEREX; +use itp_sgx_crypto::ShieldingCryptoEncrypt; +use itp_stf_primitives::types::ShardIdentifier; +use litentry_primitives::ParentchainBalance as Balance; +use log::*; +use sp_core::sr25519 as sr25519_core; +use substrate_api_client::{ac_compose_macros::compose_extrinsic, SubmitAndWatch, XtStatus}; + +#[derive(Parser)] +pub struct ShieldFundsCommand { + /// Sender's parentchain AccountId in ss58check format. + from: String, + /// Recipient's incognito AccountId in ss58check format. + to: String, + /// Amount to be transferred. + amount: Balance, + /// Shard identifier. + shard: String, +} + +impl ShieldFundsCommand { + pub(crate) fn run(&self, cli: &Cli) -> CliResult { + let mut chain_api = get_chain_api(cli); + + let shard_opt = match self.shard.from_base58() { + Ok(s) => ShardIdentifier::decode(&mut &s[..]), + _ => panic!("shard argument must be base58 encoded"), + }; + + let shard = match shard_opt { + Ok(shard) => shard, + Err(e) => panic!("{}", e), + }; + + // Get the sender. + let from = get_pair_from_str(&self.from); + chain_api.set_signer(sr25519_core::Pair::from(from).into()); + + // Get the recipient. + let to = get_accountid_from_str(&self.to); + + let encryption_key = get_shielding_key(cli).unwrap(); + let encrypted_recevier = encryption_key.encrypt(&to.encode()).unwrap(); + + // Compose the extrinsic. + let xt = compose_extrinsic!( + chain_api, + TEEREX, + "shield_funds", + encrypted_recevier, + self.amount, + shard + ); + + match chain_api.submit_and_watch_extrinsic_until(xt, XtStatus::Finalized) { + Ok(xt_report) => { + println!( + "[+] shield funds success. extrinsic hash: {:?} / status: {:?} / block hash: {:?}", + xt_report.extrinsic_hash, xt_report.status, xt_report.block_hash.unwrap() + ); + Ok(CliResultOk::H256 { hash: xt_report.block_hash.unwrap() }) + }, + Err(e) => { + error!("shield_funds extrinsic failed {:?}", e); + Err(CliError::Extrinsic { msg: format!("{:?}", e) }) + }, + } + } +} diff --git a/bitacross-worker/cli/src/base_cli/commands/transfer.rs b/bitacross-worker/cli/src/base_cli/commands/transfer.rs new file mode 100644 index 0000000000..58cfb19ece --- /dev/null +++ b/bitacross-worker/cli/src/base_cli/commands/transfer.rs @@ -0,0 +1,61 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{ + command_utils::{get_accountid_from_str, get_chain_api, *}, + Cli, CliResult, CliResultOk, +}; +use litentry_primitives::ParentchainBalance as Balance; +use log::*; +use sp_core::{crypto::Ss58Codec, Pair}; +use substrate_api_client::{ + extrinsic::BalancesExtrinsics, GetAccountInformation, SubmitAndWatch, XtStatus, +}; + +#[derive(Parser)] +pub struct TransferCommand { + /// sender's AccountId in ss58check format + from: String, + + /// recipient's AccountId in ss58check format + to: String, + + /// amount to be transferred + amount: Balance, +} + +impl TransferCommand { + pub(crate) fn run(&self, cli: &Cli) -> CliResult { + let from_account = get_pair_from_str(&self.from); + let to_account = get_accountid_from_str(&self.to); + info!("from ss58 is {}", from_account.public().to_ss58check()); + info!("to ss58 is {}", to_account.to_ss58check()); + let mut api = get_chain_api(cli); + api.set_signer(from_account.into()); + let xt = api.balance_transfer_allow_death(to_account.clone().into(), self.amount); + let tx_report = api.submit_and_watch_extrinsic_until(xt, XtStatus::InBlock).unwrap(); + println!( + "[+] L1 extrinsic success. extrinsic hash: {:?} / status: {:?}", + tx_report.extrinsic_hash, tx_report.status + ); + let result = api.get_account_data(&to_account).unwrap().unwrap(); + let balance = result.free; + println!("balance for {} is now {}", to_account, balance); + + Ok(CliResultOk::Balance { balance }) + } +} diff --git a/bitacross-worker/cli/src/base_cli/mod.rs b/bitacross-worker/cli/src/base_cli/mod.rs new file mode 100644 index 0000000000..9ba67f94f7 --- /dev/null +++ b/bitacross-worker/cli/src/base_cli/mod.rs @@ -0,0 +1,192 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{ + base_cli::commands::{ + balance::BalanceCommand, faucet::FaucetCommand, listen::ListenCommand, + litentry::set_heartbeat_timeout::SetHeartbeatTimeoutCommand, + register_tcb_info::RegisterTcbInfoCommand, shield_funds::ShieldFundsCommand, + transfer::TransferCommand, + }, + command_utils::*, + Cli, CliResult, CliResultOk, ED25519_KEY_TYPE, SR25519_KEY_TYPE, +}; +use base58::ToBase58; +use chrono::{DateTime, Utc}; +use clap::Subcommand; +use itc_rpc_client::direct_client::DirectApi; +use itp_node_api::api_client::PalletTeerexApi; +use sp_core::crypto::Ss58Codec; +use sp_keystore::Keystore; +use std::{ + path::PathBuf, + time::{Duration, UNIX_EPOCH}, +}; +use substrate_client_keystore::LocalKeystore; + +mod commands; + +#[derive(Subcommand)] +pub enum BaseCommand { + /// query parentchain balance for AccountId + Balance(BalanceCommand), + + /// generates a new account for the integritee chain in your local keystore + NewAccount, + + /// lists all accounts in your local keystore for the integritee chain + ListAccounts, + + /// query node metadata and print it as json to stdout + PrintMetadata, + + /// query sgx-runtime metadata and print it as json to stdout + PrintSgxMetadata, + + /// send some bootstrapping funds to supplied account(s) + Faucet(FaucetCommand), + + /// transfer funds from one parentchain account to another + Transfer(TransferCommand), + + /// query enclave registry and list all workers + ListWorkers, + + /// listen to parentchain events + Listen(ListenCommand), + + /// Register TCB info for FMSPC + RegisterTcbInfo(RegisterTcbInfoCommand), + + /// Transfer funds from an parentchain account to an incognito account + ShieldFunds(ShieldFundsCommand), + + // Litentry's commands below + /// query sgx-runtime metadata and print the raw (hex-encoded) metadata to stdout + /// we could have added a parameter like `--raw` to `PrintSgxMetadata`, but + /// we want to keep our changes isolated + PrintSgxMetadataRaw, + + /// set heartbeat timeout storage + SetHeartbeatTimeout(SetHeartbeatTimeoutCommand), +} + +impl BaseCommand { + pub fn run(&self, cli: &Cli) -> CliResult { + match self { + BaseCommand::Balance(cmd) => cmd.run(cli), + BaseCommand::NewAccount => new_account(), + BaseCommand::ListAccounts => list_accounts(), + BaseCommand::PrintMetadata => print_metadata(cli), + BaseCommand::PrintSgxMetadata => print_sgx_metadata(cli), + BaseCommand::Faucet(cmd) => cmd.run(cli), + BaseCommand::Transfer(cmd) => cmd.run(cli), + BaseCommand::ListWorkers => list_workers(cli), + BaseCommand::Listen(cmd) => cmd.run(cli), + BaseCommand::RegisterTcbInfo(cmd) => cmd.run(cli), + BaseCommand::ShieldFunds(cmd) => cmd.run(cli), + // Litentry's commands below + BaseCommand::PrintSgxMetadataRaw => print_sgx_metadata_raw(cli), + BaseCommand::SetHeartbeatTimeout(cmd) => cmd.run(cli), + } + } +} + +fn new_account() -> CliResult { + let store = LocalKeystore::open(PathBuf::from(&KEYSTORE_PATH), None).unwrap(); + let key = LocalKeystore::sr25519_generate_new(&store, SR25519_KEY_TYPE, None).unwrap(); + let key_base58 = key.to_ss58check(); + drop(store); + println!("{}", key_base58); + Ok(CliResultOk::PubKeysBase58 { + pubkeys_sr25519: Some(vec![key_base58]), + pubkeys_ed25519: None, + }) +} + +fn list_accounts() -> CliResult { + let store = LocalKeystore::open(PathBuf::from(&KEYSTORE_PATH), None).unwrap(); + println!("sr25519 keys:"); + let mut keys_sr25519 = vec![]; + for pubkey in store.sr25519_public_keys(SR25519_KEY_TYPE).into_iter() { + let key_ss58 = pubkey.to_ss58check(); + println!("{}", key_ss58); + keys_sr25519.push(key_ss58); + } + println!("ed25519 keys:"); + let mut keys_ed25519 = vec![]; + for pubkey in store.ed25519_public_keys(ED25519_KEY_TYPE).into_iter() { + let key_ss58 = pubkey.to_ss58check(); + println!("{}", key_ss58); + keys_ed25519.push(key_ss58); + } + drop(store); + + Ok(CliResultOk::PubKeysBase58 { + pubkeys_sr25519: Some(keys_sr25519), + pubkeys_ed25519: Some(keys_ed25519), + }) +} + +fn print_metadata(cli: &Cli) -> CliResult { + let api = get_chain_api(cli); + let meta = api.metadata(); + println!("Metadata:\n {}", &meta.pretty_format().unwrap()); + Ok(CliResultOk::Metadata { metadata: meta.clone() }) +} +fn print_sgx_metadata(cli: &Cli) -> CliResult { + let worker_api_direct = get_worker_api_direct(cli); + let metadata = worker_api_direct.get_state_metadata().unwrap(); + println!("Metadata:\n {}", metadata.pretty_format().unwrap()); + Ok(CliResultOk::Metadata { metadata }) +} + +fn print_sgx_metadata_raw(cli: &Cli) -> CliResult { + let worker_api_direct = get_worker_api_direct(cli); + let metadata = worker_api_direct.get_state_metadata_raw().unwrap(); + println!("{metadata}"); + Ok(CliResultOk::None) +} + +fn list_workers(cli: &Cli) -> CliResult { + let api = get_chain_api(cli); + let wcount = api.enclave_count(None).unwrap(); + println!("number of workers registered: {}", wcount); + + let mut mr_enclaves = Vec::with_capacity(wcount as usize); + + for w in 1..=wcount { + let enclave = api.enclave(w, None).unwrap(); + if enclave.is_none() { + println!("error reading enclave data"); + continue + }; + let enclave = enclave.unwrap(); + let timestamp = + DateTime::::from(UNIX_EPOCH + Duration::from_millis(enclave.timestamp)); + let mr_enclave = enclave.mr_enclave.to_base58(); + println!("Enclave {}", w); + println!(" AccountId: {}", enclave.pubkey.to_ss58check()); + println!(" MRENCLAVE: {}", mr_enclave); + println!(" RA timestamp: {}", timestamp); + println!(" URL: {}", enclave.url); + + mr_enclaves.push(mr_enclave); + } + + Ok(CliResultOk::MrEnclaveBase58 { mr_enclaves }) +} diff --git a/bitacross-worker/cli/src/benchmark/mod.rs b/bitacross-worker/cli/src/benchmark/mod.rs new file mode 100644 index 0000000000..04e1694f21 --- /dev/null +++ b/bitacross-worker/cli/src/benchmark/mod.rs @@ -0,0 +1,378 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{ + command_utils::get_worker_api_direct, + get_layer_two_nonce, + trusted_cli::TrustedCli, + trusted_command_utils::{get_identifiers, get_keystore_path, get_pair_from_str}, + trusted_operation::{get_json_request, get_state, wait_until}, + Cli, CliResult, CliResultOk, SR25519_KEY_TYPE, +}; +use codec::Decode; +use hdrhistogram::Histogram; +use ita_stf::{ + Getter, Index, PublicGetter, TrustedCall, TrustedCallSigned, TrustedGetter, STF_TX_FEE, +}; +use itc_rpc_client::direct_client::{DirectApi, DirectClient}; +use itp_stf_primitives::{ + traits::TrustedCallSigning, + types::{KeyPair, TrustedOperation}, +}; +use itp_types::{ + Balance, ShardIdentifier, TrustedOperationStatus, + TrustedOperationStatus::{InSidechainBlock, Submitted}, +}; +use log::*; +use rand::Rng; +use rayon::prelude::*; +use sgx_crypto_helper::rsa3072::Rsa3072PubKey; +use sp_application_crypto::sr25519; +use sp_core::{sr25519 as sr25519_core, Pair}; +use sp_keystore::Keystore; +use std::{ + boxed::Box, + string::ToString, + sync::mpsc::{channel, Receiver}, + thread, time, + time::Instant, + vec::Vec, +}; +use substrate_client_keystore::LocalKeystore; + +// Needs to be above the existential deposit minimum, otherwise an account will not +// be created and the state is not increased. +const EXISTENTIAL_DEPOSIT: Balance = 1000; + +#[derive(Parser)] +pub struct BenchmarkCommand { + /// The number of clients (=threads) to be used in the benchmark + #[clap(default_value_t = 10)] + number_clients: u32, + + /// The number of iterations to execute for each client + #[clap(default_value_t = 30)] + number_iterations: u128, + + /// Adds a random wait before each transaction. This is the lower bound for the interval in ms. + #[clap(default_value_t = 0)] + random_wait_before_transaction_min_ms: u32, + + /// Adds a random wait before each transaction. This is the upper bound for the interval in ms. + #[clap(default_value_t = 0)] + random_wait_before_transaction_max_ms: u32, + + /// Whether to wait for "InSidechainBlock" confirmation for each transaction + #[clap(short, long)] + wait_for_confirmation: bool, + + /// Account to be used for initial funding of generated accounts used in benchmark + #[clap(default_value_t = String::from("//Alice"))] + funding_account: String, +} + +struct BenchmarkClient { + account: sr25519_core::Pair, + current_balance: u128, + client_api: DirectClient, + receiver: Receiver, +} + +impl BenchmarkClient { + fn new( + account: sr25519_core::Pair, + initial_balance: u128, + initial_request: String, + cli: &Cli, + ) -> Self { + debug!("get direct api"); + let client_api = get_worker_api_direct(cli); + + debug!("setup sender and receiver"); + let (sender, receiver) = channel(); + client_api.watch(initial_request, sender); + BenchmarkClient { account, current_balance: initial_balance, client_api, receiver } + } +} + +/// Stores timing information about a specific transaction +struct BenchmarkTransaction { + started: Instant, + submitted: Instant, + confirmed: Option, +} + +impl BenchmarkCommand { + pub(crate) fn run(&self, cli: &Cli, trusted_args: &TrustedCli) -> CliResult { + let random_wait_before_transaction_ms: (u32, u32) = ( + self.random_wait_before_transaction_min_ms, + self.random_wait_before_transaction_max_ms, + ); + let store = LocalKeystore::open(get_keystore_path(trusted_args, cli), None).unwrap(); + let funding_account_keys = get_pair_from_str(trusted_args, &self.funding_account, cli); + + let (mrenclave, shard) = get_identifiers(trusted_args, cli); + + // Get shielding pubkey. + let worker_api_direct = get_worker_api_direct(cli); + let shielding_pubkey: Rsa3072PubKey = match worker_api_direct.get_rsa_pubkey() { + Ok(key) => key, + Err(err_msg) => panic!("{}", err_msg.to_string()), + }; + + let nonce_start = get_layer_two_nonce!(funding_account_keys, cli, trusted_args); + println!("Nonce for account {}: {}", self.funding_account, nonce_start); + + let mut accounts = Vec::new(); + let initial_balance = (self.number_iterations + 1) * (STF_TX_FEE + EXISTENTIAL_DEPOSIT); + // Setup new accounts and initialize them with money from Alice. + for i in 0..self.number_clients { + let nonce = i + nonce_start; + println!("Initializing account {} with initial amount {:?}", i, initial_balance); + + // Create new account to use. + let a = LocalKeystore::sr25519_generate_new(&store, SR25519_KEY_TYPE, None).unwrap(); + let account = get_pair_from_str(trusted_args, a.to_string().as_str(), cli); + + // Transfer amount from Alice to new account. + let top: TrustedOperation = TrustedCall::balance_transfer( + funding_account_keys.public().into(), + account.public().into(), + initial_balance, + ) + .sign( + &KeyPair::Sr25519(Box::new(funding_account_keys.clone())), + nonce, + &mrenclave, + &shard, + ) + .into_trusted_operation(trusted_args.direct); + + // For the last account we wait for confirmation in order to ensure all accounts were setup correctly + let wait_for_confirmation = i == self.number_clients - 1; + let account_funding_request = get_json_request(shard, &top, shielding_pubkey); + + let client = + BenchmarkClient::new(account, initial_balance, account_funding_request, cli); + let _result = wait_for_top_confirmation(wait_for_confirmation, &client); + accounts.push(client); + } + + rayon::ThreadPoolBuilder::new() + .num_threads(self.number_clients as usize) + .build_global() + .unwrap(); + + let overall_start = Instant::now(); + + // Run actual benchmark logic, in parallel, for each account initialized above. + let outputs: Vec> = accounts + .into_par_iter() + .map(move |mut client| { + let mut output: Vec = Vec::new(); + + for i in 0..self.number_iterations { + println!("Iteration: {}", i); + + if random_wait_before_transaction_ms.1 > 0 { + random_wait(random_wait_before_transaction_ms); + } + + // Create new account. + let account_keys = LocalKeystore::sr25519_generate_new(&store, SR25519_KEY_TYPE, None).unwrap(); + + let new_account = + get_pair_from_str(trusted_args, account_keys.to_string().as_str(), cli); + + println!(" Transfer amount: {}", EXISTENTIAL_DEPOSIT); + println!(" From: {:?}", client.account.public()); + println!(" To: {:?}", new_account.public()); + + // Get nonce of account. + let nonce = get_nonce(client.account.clone(), shard, &client.client_api); + + // Transfer money from client account to new account. + let top: TrustedOperation = TrustedCall::balance_transfer( + client.account.public().into(), + new_account.public().into(), + EXISTENTIAL_DEPOSIT, + ) + .sign(&KeyPair::Sr25519(Box::new(client.account.clone())), nonce, &mrenclave, &shard) + .into_trusted_operation(trusted_args.direct); + + let last_iteration = i == self.number_iterations - 1; + let jsonrpc_call = get_json_request(shard, &top, shielding_pubkey); + client.client_api.send(&jsonrpc_call).unwrap(); + let result = wait_for_top_confirmation( + self.wait_for_confirmation || last_iteration, + &client, + ); + + client.current_balance -= EXISTENTIAL_DEPOSIT; + + let balance = get_balance(client.account.clone(), shard, &client.client_api); + println!("Balance: {}", balance.unwrap_or_default()); + assert_eq!(client.current_balance, balance.unwrap()); + + output.push(result); + + // FIXME: We probably should re-fund the account in this case. + if client.current_balance <= EXISTENTIAL_DEPOSIT + STF_TX_FEE { + error!("Account {:?} does not have enough balance anymore. Finishing benchmark early", client.account.public()); + break; + } + } + + client.client_api.close().unwrap(); + + output + }) + .collect(); + + println!( + "Finished benchmark with {} clients and {} transactions in {} ms", + self.number_clients, + self.number_iterations, + overall_start.elapsed().as_millis() + ); + + print_benchmark_statistic(outputs, self.wait_for_confirmation); + + Ok(CliResultOk::None) + } +} + +fn get_balance( + account: sr25519::Pair, + shard: ShardIdentifier, + direct_client: &DirectClient, +) -> Option { + let getter = Getter::trusted( + TrustedGetter::free_balance(account.public().into()) + .sign(&KeyPair::Sr25519(Box::new(account.clone()))), + ); + + let getter_start_timer = Instant::now(); + let getter_result = direct_client.get_state(shard, &getter); + let getter_execution_time = getter_start_timer.elapsed().as_millis(); + + let balance = decode_balance(getter_result); + info!("Balance getter execution took {} ms", getter_execution_time,); + debug!("Retrieved {:?} Balance for {:?}", balance.unwrap_or_default(), account.public()); + balance +} + +fn get_nonce( + account: sr25519::Pair, + shard: ShardIdentifier, + direct_client: &DirectClient, +) -> Index { + let getter = Getter::public(PublicGetter::nonce(account.public().into())); + + let getter_start_timer = Instant::now(); + let nonce = get_state::(direct_client, shard, &getter).ok().unwrap_or_default(); + let getter_execution_time = getter_start_timer.elapsed().as_millis(); + info!("Nonce getter execution took {} ms", getter_execution_time,); + debug!("Retrieved {:?} nonce for {:?}", nonce, account.public()); + nonce +} + +fn print_benchmark_statistic(outputs: Vec>, wait_for_confirmation: bool) { + let mut hist = Histogram::::new(1).unwrap(); + for output in outputs { + for t in output { + let benchmarked_timestamp = + if wait_for_confirmation { t.confirmed } else { Some(t.submitted) }; + if let Some(confirmed) = benchmarked_timestamp { + hist += confirmed.duration_since(t.started).as_millis() as u64; + } else { + println!("Missing measurement data"); + } + } + } + + for i in (5..=100).step_by(5) { + let text = format!( + "{} percent are done within {} ms", + i, + hist.value_at_quantile(i as f64 / 100.0) + ); + println!("{}", text); + } +} + +fn random_wait(random_wait_before_transaction_ms: (u32, u32)) { + let mut rng = rand::thread_rng(); + let sleep_time = time::Duration::from_millis( + rng.gen_range(random_wait_before_transaction_ms.0..=random_wait_before_transaction_ms.1) + .into(), + ); + println!("Sleep for: {}ms", sleep_time.as_millis()); + thread::sleep(sleep_time); +} + +fn wait_for_top_confirmation( + wait_for_sidechain_block: bool, + client: &BenchmarkClient, +) -> BenchmarkTransaction { + let started = Instant::now(); + + let submitted = wait_until(&client.receiver, is_submitted); + + let confirmed = if wait_for_sidechain_block { + // We wait for the transaction hash that actually matches the submitted hash + loop { + let transaction_information = wait_until(&client.receiver, is_sidechain_block); + if let Some((hash, _)) = transaction_information { + if hash == submitted.unwrap().0 { + break transaction_information + } + } + } + } else { + None + }; + if let (Some(s), Some(c)) = (submitted, confirmed) { + // Assert the two hashes are identical + assert_eq!(s.0, c.0); + } + + BenchmarkTransaction { + started, + submitted: submitted.unwrap().1, + confirmed: confirmed.map(|v| v.1), + } +} + +fn is_submitted(s: TrustedOperationStatus) -> bool { + matches!(s, Submitted) +} + +fn is_sidechain_block(s: TrustedOperationStatus) -> bool { + matches!(s, InSidechainBlock(_)) +} + +fn decode_balance(maybe_encoded_balance: Option>) -> Option { + maybe_encoded_balance.and_then(|encoded_balance| { + if let Ok(vd) = Balance::decode(&mut encoded_balance.as_slice()) { + Some(vd) + } else { + warn!("Could not decode balance. maybe hasn't been set? {:x?}", encoded_balance); + None + } + }) +} diff --git a/bitacross-worker/cli/src/command_utils.rs b/bitacross-worker/cli/src/command_utils.rs new file mode 100644 index 0000000000..1779a6aebf --- /dev/null +++ b/bitacross-worker/cli/src/command_utils.rs @@ -0,0 +1,87 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::Cli; +use base58::FromBase58; +use itc_rpc_client::direct_client::{DirectApi, DirectClient as DirectWorkerApi}; +use itp_node_api::api_client::{ParentchainApi, TungsteniteRpcClient}; +use litentry_primitives::{ParentchainAccountId as AccountId, ParentchainSignature as Signature}; +use log::*; +use sgx_crypto_helper::rsa3072::Rsa3072PubKey; +use sp_application_crypto::sr25519; +use sp_core::{crypto::Ss58Codec, Pair}; +use sp_runtime::traits::{IdentifyAccount, Verify}; +use std::path::PathBuf; +use substrate_client_keystore::LocalKeystore; + +type AccountPublic = ::Signer; +pub(crate) const KEYSTORE_PATH: &str = "my_keystore"; + +/// Retrieves the public shielding key via the enclave websocket server. +pub(crate) fn get_shielding_key(cli: &Cli) -> Result { + let worker_api_direct = get_worker_api_direct(cli); + worker_api_direct.get_rsa_pubkey().map_err(|e| e.to_string()) +} + +pub(crate) fn get_chain_api(cli: &Cli) -> ParentchainApi { + let url = format!("{}:{}", cli.node_url, cli.node_port); + info!("connecting to {}", url); + ParentchainApi::new(TungsteniteRpcClient::new(&url, 5).unwrap()).unwrap() +} + +pub(crate) fn get_accountid_from_str(account: &str) -> AccountId { + match &account[..2] { + "//" => AccountPublic::from(sr25519::Pair::from_string(account, None).unwrap().public()) + .into_account(), + _ => AccountPublic::from(sr25519::Public::from_ss58check(account).unwrap()).into_account(), + } +} + +pub(crate) fn get_worker_api_direct(cli: &Cli) -> DirectWorkerApi { + let url = format!("{}:{}", cli.worker_url, cli.trusted_worker_port); + info!("Connecting to bitacross-worker-direct-port on '{}'", url); + DirectWorkerApi::new(url) +} + +/// get a pair either form keyring (well known keys) or from the store +pub(crate) fn get_pair_from_str(account: &str) -> sr25519::AppPair { + info!("getting pair for {}", account); + match &account[..2] { + "//" => sr25519::AppPair::from_string(account, None).unwrap(), + _ => { + info!("fetching from keystore at {}", &KEYSTORE_PATH); + // open store without password protection + let store = LocalKeystore::open(PathBuf::from(&KEYSTORE_PATH), None) + .expect("store should exist"); + info!("store opened"); + let _pair = store + .key_pair::( + &sr25519::Public::from_ss58check(account).unwrap().into(), + ) + .unwrap() + .unwrap(); + drop(store); + _pair + }, + } +} + +pub(crate) fn mrenclave_from_base58(src: &str) -> [u8; 32] { + let mut mrenclave = [0u8; 32]; + mrenclave.copy_from_slice(&src.from_base58().expect("mrenclave has to be base58 encoded")); + mrenclave +} diff --git a/bitacross-worker/cli/src/commands.rs b/bitacross-worker/cli/src/commands.rs new file mode 100644 index 0000000000..e01a79d930 --- /dev/null +++ b/bitacross-worker/cli/src/commands.rs @@ -0,0 +1,60 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +extern crate chrono; +use crate::{base_cli::BaseCommand, trusted_cli::TrustedCli, Cli, CliResult, CliResultOk}; +use clap::Subcommand; + +#[cfg(feature = "teeracle")] +use crate::oracle::OracleCommand; + +use crate::attesteer::AttesteerCommand; + +#[derive(Subcommand)] +pub enum Commands { + #[clap(flatten)] + Base(BaseCommand), + + /// trusted calls to worker enclave + #[clap(after_help = "stf subcommands depend on the stf crate this has been built against")] + Trusted(TrustedCli), + + /// Subcommands for the oracle. + #[cfg(feature = "teeracle")] + #[clap(subcommand)] + Oracle(OracleCommand), + + /// Subcommand for the attesteer. + #[clap(subcommand)] + Attesteer(AttesteerCommand), +} + +pub fn match_command(cli: &Cli) -> CliResult { + match &cli.command { + Commands::Base(cmd) => cmd.run(cli), + Commands::Trusted(trusted_cli) => trusted_cli.run(cli), + #[cfg(feature = "teeracle")] + Commands::Oracle(cmd) => { + cmd.run(cli); + Ok(CliResultOk::None) + }, + Commands::Attesteer(cmd) => { + cmd.run(cli); + Ok(CliResultOk::None) + }, + } +} diff --git a/bitacross-worker/cli/src/error.rs b/bitacross-worker/cli/src/error.rs new file mode 100644 index 0000000000..ad64fb4ca1 --- /dev/null +++ b/bitacross-worker/cli/src/error.rs @@ -0,0 +1,36 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 itp_node_api::api_client::ApiClientError; +use itp_types::parentchain::{BlockHash, BlockNumber}; + +#[derive(Debug, thiserror::Error)] +pub enum Error { + #[error("{0:?}")] + ApiClient(ApiClientError), + #[error("Could not retrieve Header from node")] + MissingBlock, + #[error("Confirmed Block Number ({0:?}) exceeds expected one ({0:?})")] + ConfirmedBlockNumberTooHigh(BlockNumber, BlockNumber), + #[error("Confirmed Block Hash ({0:?}) does not match expected one ({0:?})")] + ConfirmedBlockHashDoesNotMatchExpected(BlockHash, BlockHash), +} + +impl From for Error { + fn from(error: ApiClientError) -> Self { + Error::ApiClient(error) + } +} diff --git a/bitacross-worker/cli/src/evm/commands/evm_call.rs b/bitacross-worker/cli/src/evm/commands/evm_call.rs new file mode 100644 index 0000000000..04a7b56879 --- /dev/null +++ b/bitacross-worker/cli/src/evm/commands/evm_call.rs @@ -0,0 +1,87 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{ + get_layer_two_evm_nonce, get_layer_two_nonce, + trusted_cli::TrustedCli, + trusted_command_utils::{get_identifiers, get_pair_from_str}, + trusted_operation::perform_trusted_operation, + Cli, CliResult, CliResultOk, +}; +use ita_stf::{Index, TrustedCall, TrustedGetter}; +use itp_stf_primitives::{ + traits::TrustedCallSigning, + types::{KeyPair, TrustedOperation}, +}; +use itp_types::AccountId; +use log::*; +use sp_core::{crypto::Ss58Codec, Pair, H160, U256}; +use std::{boxed::Box, vec::Vec}; +#[derive(Parser)] +pub struct EvmCallCommands { + /// Sender's incognito AccountId in ss58check format + from: String, + + /// Execution address of the smart contract + execution_address: String, + + /// Function hash + function: String, +} + +impl EvmCallCommands { + pub(crate) fn run(&self, cli: &Cli, trusted_args: &TrustedCli) -> CliResult { + let sender = get_pair_from_str(trusted_args, &self.from, cli); + let sender_acc: AccountId = sender.public().into(); + + info!("senders ss58 is {}", sender.public().to_ss58check()); + + let mut sender_evm_acc_slice: [u8; 20] = [0; 20]; + sender_evm_acc_slice + .copy_from_slice((<[u8; 32]>::from(sender_acc.clone())).get(0..20).unwrap()); + let sender_evm_acc: H160 = sender_evm_acc_slice.into(); + + info!("senders evm account is {}", sender_evm_acc); + + let execution_address = + H160::from_slice(&array_bytes::hex2bytes(&self.execution_address).unwrap()); + + let function_hash = array_bytes::hex2bytes(&self.function).unwrap(); + + let (mrenclave, shard) = get_identifiers(trusted_args, cli); + let nonce = get_layer_two_nonce!(sender, cli, trusted_args); + let evm_nonce = get_layer_two_evm_nonce!(sender, cli, trusted_args); + + println!("calling smart contract function"); + let function_call = TrustedCall::evm_call( + sender_acc.into(), + sender_evm_acc, + execution_address, + function_hash, + U256::from(0), + 10_000_000, // gas limit + U256::from(1), // max_fee_per_gas !>= min_gas_price defined in runtime + None, + Some(U256::from(evm_nonce)), + Vec::new(), + ) + .sign(&KeyPair::Sr25519(Box::new(sender)), nonce, &mrenclave, &shard) + .into_trusted_operation(trusted_args.direct); + Ok(perform_trusted_operation::<()>(cli, trusted_args, &function_call) + .map(|_| CliResultOk::None)?) + } +} diff --git a/bitacross-worker/cli/src/evm/commands/evm_command_utils.rs b/bitacross-worker/cli/src/evm/commands/evm_command_utils.rs new file mode 100644 index 0000000000..cc8c5fff34 --- /dev/null +++ b/bitacross-worker/cli/src/evm/commands/evm_command_utils.rs @@ -0,0 +1,32 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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_export] +macro_rules! get_layer_two_evm_nonce { + ($signer_pair:ident, $cli:ident, $trusted_args:ident ) => {{ + use ita_stf::{Getter, TrustedCallSigned}; + + let top = TrustedOperation::::get(Getter::trusted( + TrustedGetter::evm_nonce($signer_pair.public().into()) + .sign(&KeyPair::Sr25519(Box::new($signer_pair.clone()))), + )); + let res = perform_trusted_operation::($cli, $trusted_args, &top); + let nonce = res.ok().unwrap_or(0); + debug!("got evm nonce: {:?}", nonce); + nonce + }}; +} diff --git a/bitacross-worker/cli/src/evm/commands/evm_create.rs b/bitacross-worker/cli/src/evm/commands/evm_create.rs new file mode 100644 index 0000000000..acce77e3e5 --- /dev/null +++ b/bitacross-worker/cli/src/evm/commands/evm_create.rs @@ -0,0 +1,89 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{ + get_layer_two_evm_nonce, get_layer_two_nonce, + trusted_cli::TrustedCli, + trusted_command_utils::{get_identifiers, get_pair_from_str}, + trusted_operation::perform_trusted_operation, + Cli, CliResult, CliResultOk, +}; +use ita_stf::{evm_helpers::evm_create_address, Index, TrustedCall, TrustedGetter}; +use itp_stf_primitives::{ + traits::TrustedCallSigning, + types::{KeyPair, TrustedOperation}, +}; +use itp_types::AccountId; +use log::*; +use pallet_evm::{AddressMapping, HashedAddressMapping}; +use sp_core::{crypto::Ss58Codec, Pair, H160, U256}; +use sp_runtime::traits::BlakeTwo256; +use std::vec::Vec; +#[derive(Parser)] +pub struct EvmCreateCommands { + /// Sender's incognito AccountId in ss58check format + from: String, + + /// Smart Contract in Hex format + smart_contract: String, +} + +impl EvmCreateCommands { + pub(crate) fn run(&self, cli: &Cli, trusted_args: &TrustedCli) -> CliResult { + let from = get_pair_from_str(trusted_args, &self.from, cli); + let from_acc: AccountId = from.public().into(); + println!("from ss58 is {}", from.public().to_ss58check()); + + let mut sender_evm_acc_slice: [u8; 20] = [0; 20]; + sender_evm_acc_slice + .copy_from_slice((<[u8; 32]>::from(from_acc.clone())).get(0..20).unwrap()); + let sender_evm_acc: H160 = sender_evm_acc_slice.into(); + + let (mrenclave, shard) = get_identifiers(trusted_args, cli); + + let sender_evm_substrate_addr = + HashedAddressMapping::::into_account_id(sender_evm_acc); + println!( + "Trying to get nonce of evm account {:?}", + sender_evm_substrate_addr.to_ss58check() + ); + + let nonce = get_layer_two_nonce!(from, cli, trusted_args); + let evm_account_nonce = get_layer_two_evm_nonce!(from, cli, trusted_args); + + let top = TrustedCall::evm_create( + from_acc.into(), + sender_evm_acc, + array_bytes::hex2bytes(&self.smart_contract).unwrap().to_vec(), + U256::from(0), + 967295, // gas limit + U256::from(1), // max_fee_per_gas !>= min_gas_price defined in runtime + None, + None, + Vec::new(), + ) + .sign(&from.into(), nonce, &mrenclave, &shard) + .into_trusted_operation(trusted_args.direct); + + perform_trusted_operation::<()>(cli, trusted_args, &top)?; + + let execution_address = evm_create_address(sender_evm_acc, evm_account_nonce); + info!("trusted call evm_create executed"); + println!("Created the smart contract with address {:?}", execution_address); + Ok(CliResultOk::H160 { hash: execution_address }) + } +} diff --git a/bitacross-worker/cli/src/evm/commands/evm_read.rs b/bitacross-worker/cli/src/evm/commands/evm_read.rs new file mode 100644 index 0000000000..b863533860 --- /dev/null +++ b/bitacross-worker/cli/src/evm/commands/evm_read.rs @@ -0,0 +1,69 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{ + trusted_cli::TrustedCli, trusted_command_utils::get_pair_from_str, + trusted_operation::perform_trusted_operation, Cli, CliError, CliResult, CliResultOk, +}; +use ita_stf::{Getter, TrustedCallSigned, TrustedGetter}; +use itp_stf_primitives::types::{KeyPair, TrustedOperation}; +use itp_types::AccountId; +use log::*; +use sp_core::{crypto::Ss58Codec, Pair, H160, H256}; + +#[derive(Parser)] +pub struct EvmReadCommands { + /// Sender's incognito AccountId in ss58check format + from: String, + + /// Execution address of the smart contract + execution_address: String, +} + +impl EvmReadCommands { + pub(crate) fn run(&self, cli: &Cli, trusted_args: &TrustedCli) -> CliResult { + let sender = get_pair_from_str(trusted_args, &self.from, cli); + let sender_acc: AccountId = sender.public().into(); + + info!("senders ss58 is {}", sender.public().to_ss58check()); + + let mut sender_evm_acc_slice: [u8; 20] = [0; 20]; + sender_evm_acc_slice + .copy_from_slice((<[u8; 32]>::from(sender_acc.clone())).get(0..20).unwrap()); + let sender_evm_acc: H160 = sender_evm_acc_slice.into(); + + info!("senders evm account is {}", sender_evm_acc); + + let execution_address = + H160::from_slice(&array_bytes::hex2bytes(&self.execution_address).unwrap()); + + let top = TrustedOperation::::get(Getter::trusted( + TrustedGetter::evm_account_storages(sender_acc.into(), execution_address, H256::zero()) + .sign(&KeyPair::Sr25519(Box::new(sender))), + )); + match perform_trusted_operation::(cli, trusted_args, &top) { + Ok(hash) => { + println!("{:?}", hash); + Ok(CliResultOk::H256 { hash }) + }, + Err(e) => { + error!("Nothing in state! Reason: {:?} !", e); + Err(CliError::EvmRead { msg: "Nothing in state!".to_string() }) + }, + } + } +} diff --git a/bitacross-worker/cli/src/evm/commands/mod.rs b/bitacross-worker/cli/src/evm/commands/mod.rs new file mode 100644 index 0000000000..014b093832 --- /dev/null +++ b/bitacross-worker/cli/src/evm/commands/mod.rs @@ -0,0 +1,6 @@ +pub mod evm_call; +pub mod evm_command_utils; +pub mod evm_create; +pub mod evm_read; + +pub use crate::get_layer_two_evm_nonce; diff --git a/bitacross-worker/cli/src/evm/mod.rs b/bitacross-worker/cli/src/evm/mod.rs new file mode 100644 index 0000000000..0b1ff31d47 --- /dev/null +++ b/bitacross-worker/cli/src/evm/mod.rs @@ -0,0 +1,49 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{ + evm::commands::{ + evm_call::EvmCallCommands, evm_create::EvmCreateCommands, evm_read::EvmReadCommands, + }, + trusted_cli::TrustedCli, + Cli, CliResult, +}; + +mod commands; + +#[allow(clippy::enum_variant_names)] +#[derive(Subcommand)] +pub enum EvmCommand { + /// Create smart contract + EvmCreate(EvmCreateCommands), + + /// Read smart contract storage + EvmRead(EvmReadCommands), + + /// Create smart contract + EvmCall(EvmCallCommands), +} + +impl EvmCommand { + pub fn run(&self, cli: &Cli, trusted_args: &TrustedCli) -> CliResult { + match self { + EvmCommand::EvmCreate(cmd) => cmd.run(cli, trusted_args), + EvmCommand::EvmRead(cmd) => cmd.run(cli, trusted_args), + EvmCommand::EvmCall(cmd) => cmd.run(cli, trusted_args), + } + } +} diff --git a/bitacross-worker/cli/src/lib.rs b/bitacross-worker/cli/src/lib.rs new file mode 100644 index 0000000000..0738cc6dd4 --- /dev/null +++ b/bitacross-worker/cli/src/lib.rs @@ -0,0 +1,137 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 RPC client to Integritee using websockets +//! +//! examples +//! litentry_cli 127.0.0.1:9944 transfer //Alice 5G9RtsTbiYJYQYMHbWfyPoeuuxNaCbC16tZ2JGrZ4gRKwz14 1000 +//! +#![feature(rustc_private)] +#[macro_use] +extern crate clap; +extern crate chrono; + +extern crate env_logger; +extern crate log; + +mod attesteer; +mod base_cli; +mod benchmark; +mod command_utils; +mod error; +#[cfg(feature = "evm")] +mod evm; +#[cfg(feature = "teeracle")] +mod oracle; +mod trusted_base_cli; +mod trusted_cli; +mod trusted_command_utils; +mod trusted_operation; + +pub mod commands; + +use crate::commands::Commands; +use clap::Parser; +use itp_node_api::api_client::Metadata; +use sp_application_crypto::KeyTypeId; +use sp_core::{H160, H256}; +use thiserror::Error; + +const VERSION: &str = env!("CARGO_PKG_VERSION"); + +pub(crate) const SR25519_KEY_TYPE: KeyTypeId = KeyTypeId(*b"sr25"); +pub(crate) const ED25519_KEY_TYPE: KeyTypeId = KeyTypeId(*b"ed25"); + +#[derive(Parser)] +#[clap(name = "bitacross-cli")] +#[clap(version = VERSION)] +#[clap(author = "Trust Computing GmbH ")] +#[clap(about = "cli tool to interact with litentry-parachain and workers", long_about = None)] +#[cfg_attr(feature = "teeracle", clap(about = "interact with litentry-parachain and teeracle", long_about = None))] +#[cfg_attr(feature = "sidechain", clap(about = "interact with litentry-parachain and sidechain", long_about = None))] +#[cfg_attr(feature = "offchain-worker", clap(about = "interact with litentry-parachain and offchain-worker", long_about = None))] +#[clap(after_help = "stf subcommands depend on the stf crate this has been built against")] +pub struct Cli { + /// node url + #[clap(short = 'u', long, default_value_t = String::from("ws://127.0.0.1"))] + node_url: String, + + /// node port + #[clap(short = 'p', long, default_value_t = String::from("9944"))] + node_port: String, + + /// worker url + #[clap(short = 'U', long, default_value_t = String::from("wss://127.0.0.1"))] + worker_url: String, + + /// worker direct invocation port + #[clap(short = 'P', long, default_value_t = String::from("2000"))] + trusted_worker_port: String, + + #[clap(subcommand)] + command: Commands, +} + +pub enum CliResultOk { + PubKeysBase58 { + pubkeys_sr25519: Option>, + pubkeys_ed25519: Option>, + }, + Balance { + balance: u128, + }, + MrEnclaveBase58 { + mr_enclaves: Vec, + }, + Metadata { + metadata: Metadata, + }, + H256 { + hash: H256, + }, + /// Result of "EvmCreateCommands": execution_address + H160 { + hash: H160, + }, + // TODO should ideally be removed; or at least drastically less used + // We WANT all commands exposed by the cli to return something useful for the caller(ie instead of printing) + None, +} + +#[derive(Debug, Error)] +pub enum CliError { + #[error("extrinsic error: {:?}", msg)] + Extrinsic { msg: String }, + #[error("trusted operation error: {:?}", msg)] + TrustedOp { msg: String }, + #[error("EvmReadCommands error: {:?}", msg)] + EvmRead { msg: String }, + #[error("worker rpc api error: {:?}", msg)] + WorkerRpcApi { msg: String }, +} + +pub type CliResult = Result; + +/// This is used for the commands that directly call `perform_trusted_operation` +/// which typically return `CliResultOk::None` +/// +/// eg: `SetBalanceCommand`,`TransferCommand`,`UnshieldFundsCommand` +impl From for CliError { + fn from(value: trusted_operation::TrustedOperationError) -> Self { + CliError::TrustedOp { msg: value.to_string() } + } +} diff --git a/bitacross-worker/cli/src/main.rs b/bitacross-worker/cli/src/main.rs new file mode 100644 index 0000000000..2e4652612a --- /dev/null +++ b/bitacross-worker/cli/src/main.rs @@ -0,0 +1,27 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 bitacross_cli::{commands, Cli}; +use clap::Parser; + +fn main() { + env_logger::init(); + + let cli = Cli::parse(); + + commands::match_command(&cli).unwrap(); +} diff --git a/bitacross-worker/cli/src/oracle/commands/add_to_whitelist.rs b/bitacross-worker/cli/src/oracle/commands/add_to_whitelist.rs new file mode 100644 index 0000000000..98afeb801d --- /dev/null +++ b/bitacross-worker/cli/src/oracle/commands/add_to_whitelist.rs @@ -0,0 +1,67 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{ + command_utils::{get_chain_api, get_pair_from_str, mrenclave_from_base58}, + Cli, +}; +use itp_node_api::api_client::{ADD_TO_WHITELIST, TEERACLE}; +use substrate_api_client::{ + ac_compose_macros::{compose_call, compose_extrinsic}, + SubmitAndWatch, XtStatus, +}; + +/// Add a trusted market data source to the on-chain whitelist. +#[derive(Debug, Clone, Parser)] +pub struct AddToWhitelistCmd { + /// Sender's on-chain AccountId in ss58check format. + /// + /// It has to be a sudo account. + from: String, + + /// Market data URL + source: String, + + /// MRENCLAVE of the oracle worker base58 encoded. + mrenclave: String, +} + +impl AddToWhitelistCmd { + pub fn run(&self, cli: &Cli) { + let mut api = get_chain_api(cli); + let mrenclave = mrenclave_from_base58(&self.mrenclave); + let from = get_pair_from_str(&self.from); + + let market_data_source = self.source.clone(); + + api.set_signer(from.into()); + + let call = compose_call!( + api.metadata(), + TEERACLE, + ADD_TO_WHITELIST, + market_data_source, + mrenclave + ); + + // compose the extrinsic + let xt = compose_extrinsic!(api, "Sudo", "sudo", call); + + let report = api.submit_and_watch_extrinsic_until(xt, XtStatus::Finalized).unwrap(); + println!("[+] Add to whitelist got finalized. Hash: {:?}\n", report.extrinsic_hash); + } +} diff --git a/bitacross-worker/cli/src/oracle/commands/listen_to_exchange.rs b/bitacross-worker/cli/src/oracle/commands/listen_to_exchange.rs new file mode 100644 index 0000000000..181be4febd --- /dev/null +++ b/bitacross-worker/cli/src/oracle/commands/listen_to_exchange.rs @@ -0,0 +1,79 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{command_utils::get_chain_api, Cli}; +use itp_node_api::api_client::ParentchainApi; +use itp_time_utils::{duration_now, remaining_time}; +use log::{debug, info, trace}; +use my_node_runtime::{Hash, RuntimeEvent}; +use std::time::Duration; +use substrate_api_client::SubscribeEvents; + +/// Listen to exchange rate events. +#[derive(Debug, Clone, Parser)] +pub struct ListenToExchangeRateEventsCmd { + /// Listen for `duration` in seconds. + duration: u64, +} + +impl ListenToExchangeRateEventsCmd { + pub fn run(&self, cli: &Cli) { + let api = get_chain_api(cli); + let duration = Duration::from_secs(self.duration); + + let count = count_exchange_rate_update_events(&api, duration); + + println!("Number of ExchangeRateUpdated events received : "); + println!(" EVENTS_COUNT: {}", count); + } +} + +pub fn count_exchange_rate_update_events(api: &ParentchainApi, duration: Duration) -> u32 { + let stop = duration_now() + duration; + + //subscribe to events + let mut subscription = api.subscribe_events().unwrap(); + let mut count = 0; + + while remaining_time(stop).unwrap_or_default() > Duration::ZERO { + let events_result = subscription.next_events::().unwrap(); + if let Ok(events) = events_result { + for event_record in &events { + info!("received event {:?}", event_record.event); + if let RuntimeEvent::Teeracle(event) = &event_record.event { + match &event { + my_node_runtime::pallet_teeracle::Event::ExchangeRateUpdated( + data_source, + trading_pair, + exchange_rate, + ) => { + count += 1; + debug!("Received ExchangeRateUpdated event"); + println!( + "ExchangeRateUpdated: TRADING_PAIR : {}, SRC : {}, VALUE :{:?}", + trading_pair, data_source, exchange_rate + ); + }, + _ => trace!("ignoring teeracle event: {:?}", event), + } + } + } + } + } + debug!("Received {} ExchangeRateUpdated event(s) in total", count); + count +} diff --git a/bitacross-worker/cli/src/oracle/commands/listen_to_oracle.rs b/bitacross-worker/cli/src/oracle/commands/listen_to_oracle.rs new file mode 100644 index 0000000000..87cc334040 --- /dev/null +++ b/bitacross-worker/cli/src/oracle/commands/listen_to_oracle.rs @@ -0,0 +1,91 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{command_utils::get_chain_api, Cli}; +use itp_node_api::api_client::ParentchainApi; +use itp_time_utils::{duration_now, remaining_time}; +use log::{debug, info}; +use my_node_runtime::{Hash, RuntimeEvent}; +use std::time::Duration; +use substrate_api_client::{ac_node_api::EventRecord, SubscribeEvents}; + +/// Listen to exchange rate events. +#[derive(Debug, Clone, Parser)] +pub struct ListenToOracleEventsCmd { + /// Listen for `duration` in seconds. + duration: u64, +} + +type EventCount = u32; +type Event = EventRecord; + +impl ListenToOracleEventsCmd { + pub fn run(&self, cli: &Cli) { + let api = get_chain_api(cli); + let duration = Duration::from_secs(self.duration); + let count = count_oracle_update_events(&api, duration); + println!("Number of Oracle events received : "); + println!(" EVENTS_COUNT: {}", count); + } +} + +fn count_oracle_update_events(api: &ParentchainApi, duration: Duration) -> EventCount { + let stop = duration_now() + duration; + + //subscribe to events + let mut subscription = api.subscribe_events().unwrap(); + let mut count = 0; + + while remaining_time(stop).unwrap_or_default() > Duration::ZERO { + let events_result = subscription.next_events::(); + let event_count = match events_result { + Some(Ok(event_records)) => { + debug!("Could not successfully decode event_bytes {:?}", event_records); + report_event_count(event_records) + }, + _ => 0, + }; + count += event_count; + } + debug!("Received {} ExchangeRateUpdated event(s) in total", count); + count +} + +fn report_event_count(event_records: Vec) -> EventCount { + let mut count = 0; + event_records.iter().for_each(|event_record| { + info!("received event {:?}", event_record.event); + if let RuntimeEvent::Teeracle(event) = &event_record.event { + match &event { + my_node_runtime::pallet_teeracle::Event::OracleUpdated( + oracle_data_name, + data_source, + ) => { + count += 1; + debug!("Received OracleUpdated event"); + println!( + "OracleUpdated: ORACLE_NAME : {}, SRC : {}", + oracle_data_name, data_source + ); + }, + // Can just remove this and ignore handling this case + _ => debug!("ignoring teeracle event: {:?}", event), + } + } + }); + count +} diff --git a/bitacross-worker/cli/src/oracle/commands/mod.rs b/bitacross-worker/cli/src/oracle/commands/mod.rs new file mode 100644 index 0000000000..22b0a326c6 --- /dev/null +++ b/bitacross-worker/cli/src/oracle/commands/mod.rs @@ -0,0 +1,25 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 add_to_whitelist; +mod listen_to_exchange; +mod listen_to_oracle; + +pub use self::{ + add_to_whitelist::AddToWhitelistCmd, listen_to_exchange::ListenToExchangeRateEventsCmd, + listen_to_oracle::ListenToOracleEventsCmd, +}; diff --git a/bitacross-worker/cli/src/oracle/mod.rs b/bitacross-worker/cli/src/oracle/mod.rs new file mode 100644 index 0000000000..e12f117cd4 --- /dev/null +++ b/bitacross-worker/cli/src/oracle/mod.rs @@ -0,0 +1,49 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +//! Add cli commands for the oracle +//! +//! Todo: This shall be a standalone crate in app-libs/oracle. However, this needs: +//! https://github.com/integritee-network/worker/issues/852 + +use crate::Cli; +use commands::{AddToWhitelistCmd, ListenToExchangeRateEventsCmd, ListenToOracleEventsCmd}; + +mod commands; + +/// Oracle subcommands for the cli. +#[derive(Debug, clap::Subcommand)] +pub enum OracleCommand { + /// Add a market source to the teeracle's whitelist. + AddToWhitelist(AddToWhitelistCmd), + + /// Listen to exchange rate events + ListenToExchangeRateEvents(ListenToExchangeRateEventsCmd), + + /// Listen to all oracles event updates + ListenToOracleEvents(ListenToOracleEventsCmd), +} + +impl OracleCommand { + pub fn run(&self, cli: &Cli) { + match self { + OracleCommand::AddToWhitelist(cmd) => cmd.run(cli), + OracleCommand::ListenToExchangeRateEvents(cmd) => cmd.run(cli), + OracleCommand::ListenToOracleEvents(cmd) => cmd.run(cli), + } + } +} diff --git a/bitacross-worker/cli/src/trusted_base_cli/commands/balance.rs b/bitacross-worker/cli/src/trusted_base_cli/commands/balance.rs new file mode 100644 index 0000000000..3b5b9f4f33 --- /dev/null +++ b/bitacross-worker/cli/src/trusted_base_cli/commands/balance.rs @@ -0,0 +1,34 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{ + trusted_cli::TrustedCli, trusted_command_utils::get_balance, Cli, CliResult, CliResultOk, +}; + +#[derive(Parser)] +pub struct BalanceCommand { + /// AccountId in ss58check format + account: String, +} + +impl BalanceCommand { + pub(crate) fn run(&self, cli: &Cli, trusted_args: &TrustedCli) -> CliResult { + let balance = get_balance(cli, trusted_args, &self.account).unwrap_or_default(); + println!("{}", balance); + Ok(CliResultOk::Balance { balance }) + } +} diff --git a/bitacross-worker/cli/src/trusted_base_cli/commands/get_shard.rs b/bitacross-worker/cli/src/trusted_base_cli/commands/get_shard.rs new file mode 100644 index 0000000000..fd16136cdb --- /dev/null +++ b/bitacross-worker/cli/src/trusted_base_cli/commands/get_shard.rs @@ -0,0 +1,69 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{ + command_utils::get_worker_api_direct, trusted_cli::TrustedCli, Cli, CliError, CliResult, + CliResultOk, +}; +use base58::ToBase58; +use codec::{Decode, Encode}; + +use itc_rpc_client::direct_client::DirectApi; +use itp_rpc::{Id, RpcRequest, RpcResponse, RpcReturnValue}; + +use itp_types::DirectRequestStatus; +use itp_utils::FromHexPrefixed; +use log::*; + +use sp_core::H256; + +#[derive(Parser)] +pub struct GetShardCommand {} + +impl GetShardCommand { + pub(crate) fn run(&self, cli: &Cli, _trusted_args: &TrustedCli) -> CliResult { + let direct_api = get_worker_api_direct(cli); + let rpc_method = "author_getShard".to_owned(); + let jsonrpc_call: String = + RpcRequest::compose_jsonrpc_call(Id::Text("1".to_string()), rpc_method, vec![]) + .unwrap(); + let rpc_response_str = direct_api.get(&jsonrpc_call).unwrap(); + // Decode RPC response. + let rpc_response: RpcResponse = serde_json::from_str(&rpc_response_str) + .map_err(|err| CliError::WorkerRpcApi { msg: err.to_string() })?; + let rpc_return_value = RpcReturnValue::from_hex(&rpc_response.result) + // Replace with `inspect_err` once it's stable. + .map_err(|err| { + error!("Failed to decode RpcReturnValue: {:?}", err); + CliError::WorkerRpcApi { msg: "failed to decode RpcReturnValue".to_string() } + })?; + + if rpc_return_value.status == DirectRequestStatus::Error { + println!("[Error] {}", String::decode(&mut rpc_return_value.value.as_slice()).unwrap()); + return Err(CliError::WorkerRpcApi { msg: "rpc error".to_string() }) + } + + let shard = H256::decode(&mut rpc_return_value.value.as_slice()) + // Replace with `inspect_err` once it's stable. + .map_err(|err| { + error!("Failed to decode shard: {:?}", err); + CliError::WorkerRpcApi { msg: err.to_string() } + })?; + println!("{}", shard.encode().to_base58()); + Ok(CliResultOk::H256 { hash: shard }) + } +} diff --git a/bitacross-worker/cli/src/trusted_base_cli/commands/get_shard_vault.rs b/bitacross-worker/cli/src/trusted_base_cli/commands/get_shard_vault.rs new file mode 100644 index 0000000000..a4af8a2ec8 --- /dev/null +++ b/bitacross-worker/cli/src/trusted_base_cli/commands/get_shard_vault.rs @@ -0,0 +1,73 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{ + command_utils::get_worker_api_direct, trusted_cli::TrustedCli, Cli, CliError, CliResult, + CliResultOk, +}; + +use codec::Decode; + +use itc_rpc_client::direct_client::DirectApi; +use itp_rpc::{Id, RpcRequest, RpcResponse, RpcReturnValue}; + +use itp_types::{AccountId, DirectRequestStatus}; +use itp_utils::FromHexPrefixed; +use log::*; + +use sp_core::crypto::Ss58Codec; + +#[derive(Parser)] +pub struct GetShardVaultCommand {} + +impl GetShardVaultCommand { + pub(crate) fn run(&self, cli: &Cli, _trusted_args: &TrustedCli) -> CliResult { + let direct_api = get_worker_api_direct(cli); + let rpc_method = "author_getShardVault".to_owned(); + let jsonrpc_call: String = + RpcRequest::compose_jsonrpc_call(Id::Text("1".to_string()), rpc_method, vec![]) + .unwrap(); + let rpc_response_str = direct_api.get(&jsonrpc_call).unwrap(); + // Decode RPC response. + let rpc_response: RpcResponse = serde_json::from_str(&rpc_response_str) + .map_err(|err| CliError::WorkerRpcApi { msg: err.to_string() })?; + let rpc_return_value = RpcReturnValue::from_hex(&rpc_response.result) + // Replace with `inspect_err` once it's stable. + .map_err(|err| { + error!("Failed to decode RpcReturnValue: {:?}", err); + CliError::WorkerRpcApi { msg: "failed to decode RpcReturnValue".to_string() } + })?; + + if rpc_return_value.status == DirectRequestStatus::Error { + println!("[Error] {}", String::decode(&mut rpc_return_value.value.as_slice()).unwrap()); + return Err(CliError::WorkerRpcApi { msg: "rpc error".to_string() }) + } + + let vault = AccountId::decode(&mut rpc_return_value.value.as_slice()) + // Replace with `inspect_err` once it's stable. + .map_err(|err| { + error!("Failed to decode vault account: {:?}", err); + CliError::WorkerRpcApi { msg: err.to_string() } + })?; + let vault_ss58 = vault.to_ss58check(); + println!("{}", vault_ss58); + Ok(CliResultOk::PubKeysBase58 { + pubkeys_sr25519: None, + pubkeys_ed25519: Some(vec![vault_ss58]), + }) + } +} diff --git a/bitacross-worker/cli/src/trusted_base_cli/commands/mod.rs b/bitacross-worker/cli/src/trusted_base_cli/commands/mod.rs new file mode 100644 index 0000000000..0687a4fe1d --- /dev/null +++ b/bitacross-worker/cli/src/trusted_base_cli/commands/mod.rs @@ -0,0 +1,7 @@ +pub mod balance; +pub mod get_shard; +pub mod get_shard_vault; +pub mod nonce; +pub mod set_balance; +pub mod transfer; +pub mod unshield_funds; diff --git a/bitacross-worker/cli/src/trusted_base_cli/commands/nonce.rs b/bitacross-worker/cli/src/trusted_base_cli/commands/nonce.rs new file mode 100644 index 0000000000..f8abee5519 --- /dev/null +++ b/bitacross-worker/cli/src/trusted_base_cli/commands/nonce.rs @@ -0,0 +1,44 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{ + command_utils::get_worker_api_direct, + trusted_cli::TrustedCli, + trusted_command_utils::{get_identifiers, get_pair_from_str}, + Cli, CliResult, CliResultOk, +}; +use itc_rpc_client::direct_client::DirectApi; +use sp_core::Pair; + +#[derive(Parser)] +pub struct NonceCommand { + /// AccountId in ss58check format + account: String, +} + +impl NonceCommand { + pub(crate) fn run(&self, cli: &Cli, trusted_args: &TrustedCli) -> CliResult { + let (_mrenclave, shard) = get_identifiers(trusted_args, cli); + let who = get_pair_from_str(trusted_args, &self.account, cli); + let worker_api_direct = get_worker_api_direct(cli); + let nonce_ret = worker_api_direct.get_next_nonce(&shard, &(who.public().into())); + let nonce = nonce_ret.expect("get nonce error!"); + println!("{}", nonce); + worker_api_direct.close().unwrap(); + Ok(CliResultOk::None) + } +} diff --git a/bitacross-worker/cli/src/trusted_base_cli/commands/set_balance.rs b/bitacross-worker/cli/src/trusted_base_cli/commands/set_balance.rs new file mode 100644 index 0000000000..5fd5f6c900 --- /dev/null +++ b/bitacross-worker/cli/src/trusted_base_cli/commands/set_balance.rs @@ -0,0 +1,64 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{ + get_layer_two_nonce, + trusted_cli::TrustedCli, + trusted_command_utils::{get_identifiers, get_pair_from_str}, + trusted_operation::perform_trusted_operation, + Cli, CliResult, CliResultOk, +}; +use ita_stf::{Getter, Index, TrustedCall, TrustedCallSigned}; +use itp_stf_primitives::{ + traits::TrustedCallSigning, + types::{KeyPair, TrustedOperation}, +}; +use litentry_primitives::ParentchainBalance as Balance; +use log::*; +use sp_core::{crypto::Ss58Codec, Pair}; +use std::boxed::Box; + +#[derive(Parser)] +pub struct SetBalanceCommand { + /// sender's AccountId in ss58check format + account: String, + + /// amount to be transferred + amount: Balance, +} + +impl SetBalanceCommand { + pub(crate) fn run(&self, cli: &Cli, trusted_args: &TrustedCli) -> CliResult { + let who = get_pair_from_str(trusted_args, &self.account, cli); + let signer = get_pair_from_str(trusted_args, "//Alice", cli); + info!("account ss58 is {}", who.public().to_ss58check()); + + println!("send trusted call set-balance({}, {})", who.public(), self.amount); + + let (mrenclave, shard) = get_identifiers(trusted_args, cli); + let nonce = get_layer_two_nonce!(signer, cli, trusted_args); + let top: TrustedOperation = TrustedCall::balance_set_balance( + signer.public().into(), + who.public().into(), + self.amount, + self.amount, + ) + .sign(&KeyPair::Sr25519(Box::new(signer)), nonce, &mrenclave, &shard) + .into_trusted_operation(trusted_args.direct); + Ok(perform_trusted_operation::<()>(cli, trusted_args, &top).map(|_| CliResultOk::None)?) + } +} diff --git a/bitacross-worker/cli/src/trusted_base_cli/commands/transfer.rs b/bitacross-worker/cli/src/trusted_base_cli/commands/transfer.rs new file mode 100644 index 0000000000..770833ffa5 --- /dev/null +++ b/bitacross-worker/cli/src/trusted_base_cli/commands/transfer.rs @@ -0,0 +1,72 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{ + get_layer_two_nonce, + trusted_cli::TrustedCli, + trusted_command_utils::{get_accountid_from_str, get_identifiers, get_pair_from_str}, + trusted_operation::perform_trusted_operation, + Cli, CliResult, CliResultOk, +}; +use ita_stf::{Getter, Index, TrustedCall, TrustedCallSigned}; +use itp_stf_primitives::{ + traits::TrustedCallSigning, + types::{KeyPair, TrustedOperation}, +}; +use litentry_primitives::ParentchainBalance as Balance; +use log::*; +use sp_core::{crypto::Ss58Codec, Pair}; +use std::boxed::Box; + +#[derive(Parser)] +pub struct TransferCommand { + /// sender's AccountId in ss58check format + from: String, + + /// recipient's AccountId in ss58check format + to: String, + + /// amount to be transferred + amount: Balance, +} + +impl TransferCommand { + pub(crate) fn run(&self, cli: &Cli, trusted_args: &TrustedCli) -> CliResult { + let from = get_pair_from_str(trusted_args, &self.from, cli); + let to = get_accountid_from_str(&self.to); + info!("from ss58 is {}", from.public().to_ss58check()); + info!("to ss58 is {}", to.to_ss58check()); + + let (mrenclave, shard) = get_identifiers(trusted_args, cli); + let nonce = get_layer_two_nonce!(from, cli, trusted_args); + println!( + "send trusted call transfer from {} to {}: {}, nonce: {}", + from.public(), + to, + self.amount, + nonce + ); + let top: TrustedOperation = + TrustedCall::balance_transfer(from.public().into(), to, self.amount) + .sign(&KeyPair::Sr25519(Box::new(from)), nonce, &mrenclave, &shard) + .into_trusted_operation(trusted_args.direct); + let res = + perform_trusted_operation::<()>(cli, trusted_args, &top).map(|_| CliResultOk::None)?; + info!("trusted call transfer executed"); + Ok(res) + } +} diff --git a/bitacross-worker/cli/src/trusted_base_cli/commands/unshield_funds.rs b/bitacross-worker/cli/src/trusted_base_cli/commands/unshield_funds.rs new file mode 100644 index 0000000000..6e78c54401 --- /dev/null +++ b/bitacross-worker/cli/src/trusted_base_cli/commands/unshield_funds.rs @@ -0,0 +1,67 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{ + get_layer_two_nonce, + trusted_cli::TrustedCli, + trusted_command_utils::{get_accountid_from_str, get_identifiers, get_pair_from_str}, + trusted_operation::perform_trusted_operation, + Cli, CliResult, CliResultOk, +}; +use ita_stf::{Getter, Index, TrustedCall, TrustedCallSigned}; +use itp_stf_primitives::{ + traits::TrustedCallSigning, + types::{KeyPair, TrustedOperation}, +}; +use litentry_primitives::ParentchainBalance as Balance; +use sp_core::{crypto::Ss58Codec, Pair}; +use std::boxed::Box; +#[derive(Parser)] +pub struct UnshieldFundsCommand { + /// Sender's incognito AccountId in ss58check format + from: String, + + /// Recipient's parentchain AccountId in ss58check format + to: String, + + /// amount to be transferred + amount: Balance, +} + +impl UnshieldFundsCommand { + pub(crate) fn run(&self, cli: &Cli, trusted_args: &TrustedCli) -> CliResult { + let from = get_pair_from_str(trusted_args, &self.from, cli); + let to = get_accountid_from_str(&self.to); + println!("from ss58 is {}", from.public().to_ss58check()); + println!("to ss58 is {}", to.to_ss58check()); + + println!( + "send trusted call unshield_funds from {} to {}: {}", + from.public(), + to, + self.amount + ); + + let (mrenclave, shard) = get_identifiers(trusted_args, cli); + let nonce = get_layer_two_nonce!(from, cli, trusted_args); + let top: TrustedOperation = + TrustedCall::balance_unshield(from.public().into(), to, self.amount, shard) + .sign(&KeyPair::Sr25519(Box::new(from)), nonce, &mrenclave, &shard) + .into_trusted_operation(trusted_args.direct); + Ok(perform_trusted_operation::<()>(cli, trusted_args, &top).map(|_| CliResultOk::None)?) + } +} diff --git a/bitacross-worker/cli/src/trusted_base_cli/mod.rs b/bitacross-worker/cli/src/trusted_base_cli/mod.rs new file mode 100644 index 0000000000..e964e1f3df --- /dev/null +++ b/bitacross-worker/cli/src/trusted_base_cli/mod.rs @@ -0,0 +1,111 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{ + trusted_base_cli::commands::{ + balance::BalanceCommand, get_shard::GetShardCommand, get_shard_vault::GetShardVaultCommand, + nonce::NonceCommand, set_balance::SetBalanceCommand, transfer::TransferCommand, + unshield_funds::UnshieldFundsCommand, + }, + trusted_cli::TrustedCli, + trusted_command_utils::get_keystore_path, + Cli, CliResult, CliResultOk, ED25519_KEY_TYPE, SR25519_KEY_TYPE, +}; +use log::*; +use sp_core::crypto::Ss58Codec; +use sp_keystore::Keystore; +use substrate_client_keystore::LocalKeystore; + +mod commands; + +#[derive(Subcommand)] +pub enum TrustedBaseCommand { + /// generates a new incognito account for the given shard + NewAccount, + + /// lists all incognito accounts in a given shard + ListAccounts, + + /// send funds from one incognito account to another + Transfer(TransferCommand), + + /// ROOT call to set some account balance to an arbitrary number + SetBalance(SetBalanceCommand), + + /// query balance for incognito account in keystore + Balance(BalanceCommand), + + /// Transfer funds from an incognito account to an parentchain account + UnshieldFunds(UnshieldFundsCommand), + + /// gets the nonce of a given account, taking the pending trusted calls + /// in top pool in consideration + Nonce(NonceCommand), + + /// get shard for this worker + GetShard(GetShardCommand), + + /// get shard vault for shielding (if defined for this worker) + GetShardVault(GetShardVaultCommand), +} + +impl TrustedBaseCommand { + pub fn run(&self, cli: &Cli, trusted_cli: &TrustedCli) -> CliResult { + match self { + TrustedBaseCommand::NewAccount => new_account(trusted_cli, cli), + TrustedBaseCommand::ListAccounts => list_accounts(trusted_cli, cli), + TrustedBaseCommand::Transfer(cmd) => cmd.run(cli, trusted_cli), + TrustedBaseCommand::SetBalance(cmd) => cmd.run(cli, trusted_cli), + TrustedBaseCommand::Balance(cmd) => cmd.run(cli, trusted_cli), + TrustedBaseCommand::UnshieldFunds(cmd) => cmd.run(cli, trusted_cli), + TrustedBaseCommand::Nonce(cmd) => cmd.run(cli, trusted_cli), + TrustedBaseCommand::GetShard(cmd) => cmd.run(cli, trusted_cli), + TrustedBaseCommand::GetShardVault(cmd) => cmd.run(cli, trusted_cli), + } + } +} + +fn new_account(trusted_args: &TrustedCli, cli: &Cli) -> CliResult { + let store = LocalKeystore::open(get_keystore_path(trusted_args, cli), None).unwrap(); + let key = LocalKeystore::sr25519_generate_new(&store, SR25519_KEY_TYPE, None).unwrap(); + drop(store); + info!("new account {}", key.to_ss58check()); + let key_str = key.to_ss58check(); + println!("{}", key_str); + + Ok(CliResultOk::PubKeysBase58 { pubkeys_sr25519: Some(vec![key_str]), pubkeys_ed25519: None }) +} + +fn list_accounts(trusted_args: &TrustedCli, cli: &Cli) -> CliResult { + let store = LocalKeystore::open(get_keystore_path(trusted_args, cli), None).unwrap(); + info!("sr25519 keys:"); + for pubkey in store.sr25519_public_keys(SR25519_KEY_TYPE).into_iter() { + println!("{}", pubkey.to_ss58check()); + } + info!("ed25519 keys:"); + let pubkeys: Vec = store + .ed25519_public_keys(ED25519_KEY_TYPE) + .into_iter() + .map(|pubkey| pubkey.to_ss58check()) + .collect(); + for pubkey in &pubkeys { + println!("{}", pubkey); + } + drop(store); + + Ok(CliResultOk::PubKeysBase58 { pubkeys_sr25519: None, pubkeys_ed25519: Some(pubkeys) }) +} diff --git a/bitacross-worker/cli/src/trusted_cli.rs b/bitacross-worker/cli/src/trusted_cli.rs new file mode 100644 index 0000000000..5c1f5d6553 --- /dev/null +++ b/bitacross-worker/cli/src/trusted_cli.rs @@ -0,0 +1,68 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{benchmark::BenchmarkCommand, Cli, CliResult}; + +#[cfg(feature = "evm")] +use crate::evm::EvmCommand; +use crate::trusted_base_cli::TrustedBaseCommand; + +#[derive(Args)] +pub struct TrustedCli { + /// targeted worker MRENCLAVE + #[clap(short, long)] + pub(crate) mrenclave: Option, + + /// shard identifier + #[clap(short, long)] + pub(crate) shard: Option, + + /// signer for publicly observable extrinsic + #[clap(short='a', long, default_value_t = String::from("//Alice"))] + pub(crate) xt_signer: String, + + /// insert if direct invocation call is desired + #[clap(short, long)] + pub(crate) direct: bool, + + #[clap(subcommand)] + pub(crate) command: TrustedCommand, +} + +#[derive(Subcommand)] +pub enum TrustedCommand { + #[clap(flatten)] + BaseTrusted(TrustedBaseCommand), + + #[cfg(feature = "evm")] + #[clap(flatten)] + EvmCommands(EvmCommand), + + /// Run Benchmark + Benchmark(BenchmarkCommand), +} + +impl TrustedCli { + pub(crate) fn run(&self, cli: &Cli) -> CliResult { + match &self.command { + TrustedCommand::BaseTrusted(cmd) => cmd.run(cli, self), + TrustedCommand::Benchmark(cmd) => cmd.run(cli, self), + #[cfg(feature = "evm")] + TrustedCommand::EvmCommands(cmd) => cmd.run(cli, self), + } + } +} diff --git a/bitacross-worker/cli/src/trusted_command_utils.rs b/bitacross-worker/cli/src/trusted_command_utils.rs new file mode 100644 index 0000000000..57704b982c --- /dev/null +++ b/bitacross-worker/cli/src/trusted_command_utils.rs @@ -0,0 +1,164 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{ + command_utils::{get_worker_api_direct, mrenclave_from_base58}, + trusted_cli::TrustedCli, + trusted_operation::{perform_trusted_operation, read_shard}, + Cli, +}; +use base58::{FromBase58, ToBase58}; +use codec::{Decode, Encode}; +use ita_stf::{Getter, TrustedCallSigned, TrustedGetter}; +use itc_rpc_client::direct_client::DirectApi; +use itp_rpc::{Id, RpcRequest, RpcResponse, RpcReturnValue}; +use itp_stf_primitives::types::{AccountId, KeyPair, ShardIdentifier, TrustedOperation}; +use itp_types::DirectRequestStatus; +use itp_utils::{FromHexPrefixed, ToHexPrefixed}; +use litentry_primitives::ParentchainBalance as Balance; +use log::*; +use sp_application_crypto::sr25519; +use sp_core::{crypto::Ss58Codec, sr25519 as sr25519_core, Pair}; +use sp_runtime::traits::IdentifyAccount; +use std::{boxed::Box, path::PathBuf}; +use substrate_client_keystore::LocalKeystore; + +#[macro_export] +macro_rules! get_layer_two_nonce { + ($signer_pair:ident, $cli: ident, $trusted_args:ident ) => {{ + use ita_stf::{Getter, PublicGetter, TrustedCallSigned}; + use itp_stf_primitives::types::TrustedOperation; + use litentry_primitives::Identity; + use $crate::{ + trusted_command_utils::get_pending_trusted_calls_for, + trusted_operation::perform_trusted_operation, + }; + let top = TrustedOperation::::get(Getter::public( + PublicGetter::nonce(Identity::Substrate($signer_pair.public().into())), + )); + // final nonce = current system nonce + pending tx count, panic early + let nonce = perform_trusted_operation::($cli, $trusted_args, &top) + .ok() + .unwrap_or_default(); + log::debug!("got system nonce: {:?}", nonce); + let pending_tx_count = + get_pending_trusted_calls_for($cli, $trusted_args, &$signer_pair.public().into()).len(); + let pending_tx_count = Index::try_from(pending_tx_count).unwrap(); + nonce + pending_tx_count + }}; +} + +const TRUSTED_KEYSTORE_PATH: &str = "my_trusted_keystore"; + +pub(crate) fn get_balance(cli: &Cli, trusted_args: &TrustedCli, arg_who: &str) -> Option { + debug!("arg_who = {:?}", arg_who); + let who = get_pair_from_str(trusted_args, arg_who, cli); + let top = TrustedOperation::::get(Getter::trusted( + TrustedGetter::free_balance(who.public().into()).sign(&KeyPair::Sr25519(Box::new(who))), + )); + perform_trusted_operation::(cli, trusted_args, &top).ok() +} + +pub(crate) fn get_keystore_path(trusted_args: &TrustedCli, cli: &Cli) -> PathBuf { + let (_mrenclave, shard) = get_identifiers(trusted_args, cli); + PathBuf::from(&format!("{}/{}", TRUSTED_KEYSTORE_PATH, shard.encode().to_base58())) +} + +pub(crate) fn get_identifiers(trusted_args: &TrustedCli, cli: &Cli) -> ([u8; 32], ShardIdentifier) { + let mrenclave = if let Some(mrenclave) = &trusted_args.mrenclave { + mrenclave_from_base58(mrenclave) + } else { + let direct_api = get_worker_api_direct(cli); + direct_api + .get_state_mrenclave() + .expect("Unable to retrieve MRENCLAVE from endpoint") + }; + let shard = match &trusted_args.shard { + Some(val) => + ShardIdentifier::from_slice(&val.from_base58().expect("shard has to be base58 encoded")), + None => ShardIdentifier::from_slice(&mrenclave), + }; + (mrenclave, shard) +} + +// TODO this function is redundant with client::main +pub(crate) fn get_accountid_from_str(account: &str) -> AccountId { + match &account[..2] { + "//" => sr25519::Pair::from_string(account, None) + .unwrap() + .public() + .into_account() + .into(), + _ => sr25519::Public::from_ss58check(account).unwrap().into_account().into(), + } +} + +// TODO this function is ALMOST redundant with client::main +// get a pair either form keyring (well known keys) or from the store +pub(crate) fn get_pair_from_str( + trusted_args: &TrustedCli, + account: &str, + cli: &Cli, +) -> sr25519_core::Pair { + info!("getting pair for {}", account); + match &account[..2] { + "//" => sr25519_core::Pair::from_string(account, None).unwrap(), + _ => { + info!("fetching from keystore at {}", &TRUSTED_KEYSTORE_PATH); + // open store without password protection + let store = LocalKeystore::open(get_keystore_path(trusted_args, cli), None) + .expect("store should exist"); + info!("store opened"); + let public_key = &sr25519::AppPublic::from_ss58check(account).unwrap(); + info!("public_key: {:?}", &public_key); + let _pair = store.key_pair::(public_key).unwrap().unwrap(); + info!("key pair fetched"); + drop(store); + _pair.into() + }, + } +} + +// helper method to get the pending trusted calls for a given account via direct RPC +pub(crate) fn get_pending_trusted_calls_for( + cli: &Cli, + trusted_args: &TrustedCli, + who: &AccountId, +) -> Vec> { + let shard = read_shard(trusted_args, cli).unwrap(); + let direct_api = get_worker_api_direct(cli); + let rpc_method = "author_pendingTrustedCallsFor".to_owned(); + let jsonrpc_call: String = RpcRequest::compose_jsonrpc_call( + Id::Text("1".to_string()), + rpc_method, + vec![shard.encode().to_base58(), who.to_hex()], + ) + .unwrap(); + + let rpc_response_str = direct_api.get(&jsonrpc_call).unwrap(); + let rpc_response: RpcResponse = serde_json::from_str(&rpc_response_str).unwrap(); + let rpc_return_value = RpcReturnValue::from_hex(&rpc_response.result).unwrap(); + + if rpc_return_value.status == DirectRequestStatus::Error { + println!("[Error] {}", String::decode(&mut rpc_return_value.value.as_slice()).unwrap()); + direct_api.close().unwrap(); + return vec![] + } + + direct_api.close().unwrap(); + Decode::decode(&mut rpc_return_value.value.as_slice()).unwrap_or_default() +} diff --git a/bitacross-worker/cli/src/trusted_operation.rs b/bitacross-worker/cli/src/trusted_operation.rs new file mode 100644 index 0000000000..bfbb18c221 --- /dev/null +++ b/bitacross-worker/cli/src/trusted_operation.rs @@ -0,0 +1,420 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{ + command_utils::{get_chain_api, get_pair_from_str, get_shielding_key, get_worker_api_direct}, + error::Error, + trusted_cli::TrustedCli, + Cli, +}; +use base58::{FromBase58, ToBase58}; +use codec::{Decode, Encode, Input}; +use ita_stf::{Getter, StfError, TrustedCallSigned}; +use itc_rpc_client::direct_client::{DirectApi, DirectClient}; +use itp_node_api::api_client::{ParentchainApi, TEEREX}; +use itp_rpc::{Id, RpcRequest, RpcResponse, RpcReturnValue}; +use itp_sgx_crypto::ShieldingCryptoEncrypt; +use itp_stf_primitives::types::{ShardIdentifier, TrustedOperation}; +use itp_types::{BlockNumber, DirectRequestStatus, RsaRequest, TrustedOperationStatus}; +use itp_utils::{FromHexPrefixed, ToHexPrefixed}; +use litentry_primitives::ParentchainHash as Hash; +use log::*; +use my_node_runtime::RuntimeEvent; +use pallet_teerex::Event as TeerexEvent; +use sp_core::H256; +use std::{ + fmt::Debug, + result::Result as StdResult, + sync::mpsc::{channel, Receiver}, + time::Instant, +}; +use substrate_api_client::{ + ac_compose_macros::compose_extrinsic, GetChainInfo, SubmitAndWatch, SubscribeEvents, XtStatus, +}; +use thiserror::Error; + +#[derive(Debug, Error)] +pub(crate) enum TrustedOperationError { + #[error("extrinsic L1 error: {msg:?}")] + Extrinsic { msg: String }, + #[error("default error: {msg:?}")] + Default { msg: String }, +} + +pub(crate) type TrustedOpResult = StdResult; + +pub(crate) fn perform_trusted_operation( + cli: &Cli, + trusted_args: &TrustedCli, + top: &TrustedOperation, +) -> TrustedOpResult { + match top { + TrustedOperation::indirect_call(_) => send_indirect_request::(cli, trusted_args, top), + TrustedOperation::direct_call(_) => send_direct_request::(cli, trusted_args, top), + TrustedOperation::get(getter) => + execute_getter_from_cli_args::(cli, trusted_args, getter), + } +} + +fn execute_getter_from_cli_args( + cli: &Cli, + trusted_args: &TrustedCli, + getter: &Getter, +) -> TrustedOpResult { + let shard = read_shard(trusted_args, cli).unwrap(); + let direct_api = get_worker_api_direct(cli); + get_state(&direct_api, shard, getter) +} + +pub(crate) fn get_state( + direct_api: &DirectClient, + shard: ShardIdentifier, + getter: &Getter, +) -> TrustedOpResult { + // Compose jsonrpc call. + let data = RsaRequest::new(shard, getter.encode()); + let rpc_method = "state_executeGetter".to_owned(); + let jsonrpc_call: String = RpcRequest::compose_jsonrpc_call( + Id::Text("1".to_string()), + rpc_method, + vec![data.to_hex()], + ) + .unwrap(); + + let rpc_response_str = direct_api.get(&jsonrpc_call).unwrap(); + + // Decode RPC response. + let rpc_response: RpcResponse = serde_json::from_str(&rpc_response_str) + .map_err(|err| TrustedOperationError::Default { msg: err.to_string() })?; + let rpc_return_value = RpcReturnValue::from_hex(&rpc_response.result) + // Replace with `inspect_err` once it's stable. + .map_err(|err| { + error!("Failed to decode RpcReturnValue: {:?}", err); + TrustedOperationError::Default { msg: "RpcReturnValue::from_hex".to_string() } + })?; + + if rpc_return_value.status == DirectRequestStatus::Error { + println!("[Error] {}", String::decode(&mut rpc_return_value.value.as_slice()).unwrap()); + return Err(TrustedOperationError::Default { + msg: "[Error] DirectRequestStatus::Error".to_string(), + }) + } + + let maybe_state: Option> = Option::decode(&mut rpc_return_value.value.as_slice()) + // Replace with `inspect_err` once it's stable. + .map_err(|err| { + error!("Failed to decode return value: {:?}", err); + TrustedOperationError::Default { msg: "Option::decode".to_string() } + })?; + + match maybe_state { + Some(state) => { + let decoded = decode_response_value(&mut state.as_slice())?; + Ok(decoded) + }, + None => Err(TrustedOperationError::Default { msg: "Value not present".to_string() }), + } +} + +fn send_indirect_request( + cli: &Cli, + trusted_args: &TrustedCli, + trusted_operation: &TrustedOperation, +) -> TrustedOpResult { + let mut chain_api = get_chain_api(cli); + let encryption_key = get_shielding_key(cli).unwrap(); + let call_encrypted = encryption_key.encrypt(&trusted_operation.encode()).unwrap(); + + let shard = read_shard(trusted_args, cli).unwrap(); + debug!( + "invoke indirect send_request: trusted operation: {:?}, shard: {}", + trusted_operation, + shard.encode().to_base58() + ); + let arg_signer = &trusted_args.xt_signer; + let signer = get_pair_from_str(arg_signer); + chain_api.set_signer(signer.into()); + + let request = RsaRequest::new(shard, call_encrypted); + let xt = compose_extrinsic!(&chain_api, TEEREX, "call_worker", request); + + let block_hash = match chain_api.submit_and_watch_extrinsic_until(xt, XtStatus::InBlock) { + Ok(xt_report) => { + println!( + "[+] invoke TrustedOperation extrinsic success. extrinsic hash: {:?} / status: {:?} / block hash: {:?}", + xt_report.extrinsic_hash, xt_report.status, xt_report.block_hash.unwrap() + ); + xt_report.block_hash.unwrap() + }, + Err(e) => { + error!("invoke TrustedOperation extrinsic failed {:?}", e); + return Err(TrustedOperationError::Extrinsic { msg: format!("{:?}", e) }) + }, + }; + + info!( + "Trusted call extrinsic sent and successfully included in parentchain block with hash {:?}.", + block_hash + ); + info!("Waiting for execution confirmation from enclave..."); + let mut subscription = chain_api.subscribe_events().unwrap(); + loop { + let event_result = subscription.next_events::(); + if let Some(Ok(event_records)) = event_result { + for event_record in event_records { + if let RuntimeEvent::Teerex(TeerexEvent::ProcessedParentchainBlock( + _signer, + confirmed_block_hash, + trusted_calls_merkle_root, + confirmed_block_number, + )) = event_record.event + { + info!("Confirmation of ProcessedParentchainBlock received"); + debug!("shard: {:?}", shard); + debug!("confirmed parentchain block Hash: {:?}", block_hash); + debug!("trusted calls merkle root: {:?}", trusted_calls_merkle_root); + debug!("Confirmed stf block Hash: {:?}", confirmed_block_hash); + if let Err(e) = check_if_received_event_exceeds_expected( + &chain_api, + block_hash, + confirmed_block_hash, + confirmed_block_number, + ) { + error!("ProcessedParentchainBlock event: {:?}", e); + return Err(TrustedOperationError::Default { + msg: format!("ProcessedParentchainBlock event: {:?}", e), + }) + }; + + if confirmed_block_hash == block_hash { + let value = decode_response_value(&mut block_hash.encode().as_slice())?; + return Ok(value) + } + } + } + } else { + warn!("Error in event subscription: {:?}", event_result) + } + } +} + +fn check_if_received_event_exceeds_expected( + chain_api: &ParentchainApi, + block_hash: Hash, + confirmed_block_hash: Hash, + confirmed_block_number: BlockNumber, +) -> Result<(), Error> { + let block_number = chain_api.get_header(Some(block_hash))?.ok_or(Error::MissingBlock)?.number; + + info!("Expected block Number: {:?}", block_number); + info!("Confirmed block Number: {:?}", confirmed_block_number); + // The returned block number belongs to a subsequent event. We missed our event and can break the loop. + if confirmed_block_number > block_number { + return Err(Error::ConfirmedBlockNumberTooHigh(confirmed_block_number, block_number)) + } + // The block number is correct, but the block hash does not fit. + if block_number == confirmed_block_number && block_hash != confirmed_block_hash { + return Err(Error::ConfirmedBlockHashDoesNotMatchExpected(confirmed_block_hash, block_hash)) + } + Ok(()) +} + +pub fn read_shard(trusted_args: &TrustedCli, cli: &Cli) -> Result { + match &trusted_args.shard { + Some(s) => match s.from_base58() { + Ok(s) => ShardIdentifier::decode(&mut &s[..]), + _ => panic!("shard argument must be base58 encoded"), + }, + None => match trusted_args.mrenclave.clone() { + Some(mrenclave) => + if let Ok(s) = mrenclave.from_base58() { + ShardIdentifier::decode(&mut &s[..]) + } else { + panic!("Mrenclave argument must be base58 encoded") + }, + None => { + // Fetch mrenclave from worker + let direct_api = get_worker_api_direct(cli); + if let Ok(s) = direct_api.get_state_mrenclave() { + ShardIdentifier::decode(&mut &s[..]) + } else { + panic!("Unable to fetch MRENCLAVE from worker endpoint"); + } + }, + }, + } +} + +/// sends a rpc watch request to the worker api server +fn send_direct_request( + cli: &Cli, + trusted_args: &TrustedCli, + top: &TrustedOperation, +) -> TrustedOpResult { + let encryption_key = get_shielding_key(cli).unwrap(); + let shard = read_shard(trusted_args, cli).unwrap(); + let jsonrpc_call: String = get_json_request(shard, top, encryption_key); + + debug!("get direct api"); + let direct_api = get_worker_api_direct(cli); + + debug!("setup sender and receiver"); + let (sender, receiver) = channel(); + direct_api.watch(jsonrpc_call, sender); + + debug!("waiting for rpc response"); + loop { + match receiver.recv() { + Ok(response) => { + debug!("received response"); + let response: RpcResponse = serde_json::from_str(&response).unwrap(); + if let Ok(return_value) = RpcReturnValue::from_hex(&response.result) { + match return_value.status { + DirectRequestStatus::Error => { + debug!("request status is error"); + if let Ok(value) = String::decode(&mut return_value.value.as_slice()) { + println!("[Error] {}", value); + } + direct_api.close().unwrap(); + return Err(TrustedOperationError::Default { + msg: "[Error] DirectRequestStatus::Error".to_string(), + }) + }, + DirectRequestStatus::TrustedOperationStatus(status, top_hash) => { + debug!("request status is: {:?}, top_hash: {:?}", status, top_hash); + + if matches!(status, TrustedOperationStatus::Invalid) { + let error = StfError::decode(&mut return_value.value.as_slice()) + .map_err(|e| TrustedOperationError::Default { + msg: format!("Could not decode error value: {:?}", e), + })?; + return Err(TrustedOperationError::Default { + msg: format!( + "[Error] Error occurred while executing trusted call: {:?}", + error + ), + }) + } + if let Ok(value) = Hash::decode(&mut return_value.value.as_slice()) { + println!("Trusted call {:?} is {:?}", value, status); + } + if !return_value.do_watch { + direct_api.close().unwrap(); + let value = + decode_response_value(&mut return_value.value.as_slice())?; + return Ok(value) + } + }, + DirectRequestStatus::Ok => { + debug!("request status is ignored"); + direct_api.close().unwrap(); + return Err(TrustedOperationError::Default { + msg: "Unexpected status: DirectRequestStatus::Ok".to_string(), + }) + }, + } + }; + }, + Err(e) => { + error!("failed to receive rpc response: {:?}", e); + direct_api.close().unwrap(); + return Err(TrustedOperationError::Default { + msg: "failed to receive rpc response".to_string(), + }) + }, + }; + } +} + +fn decode_response_value( + value: &mut I, +) -> StdResult { + T::decode(value).map_err(|e| TrustedOperationError::Default { + msg: format!("Could not decode result value: {:?}", e), + }) +} + +pub(crate) fn get_json_request( + shard: ShardIdentifier, + top: &TrustedOperation, + shielding_pubkey: sgx_crypto_helper::rsa3072::Rsa3072PubKey, +) -> String { + let encrypted_top = shielding_pubkey.encrypt(&top.encode()).unwrap(); + + // compose jsonrpc call + let request = RsaRequest::new(shard, encrypted_top); + RpcRequest::compose_jsonrpc_call( + Id::Text("1".to_string()), + "author_submitAndWatchRsaRequest".to_string(), + vec![request.to_hex()], + ) + .unwrap() +} + +pub(crate) fn wait_until( + receiver: &Receiver, + until: impl Fn(TrustedOperationStatus) -> bool, +) -> Option<(H256, Instant)> { + debug!("waiting for rpc response"); + loop { + match receiver.recv() { + Ok(response) => { + debug!("received response: {}", response); + let parse_result: Result = serde_json::from_str(&response); + if let Ok(response) = parse_result { + if let Ok(return_value) = RpcReturnValue::from_hex(&response.result) { + debug!("successfully decoded rpc response: {:?}", return_value); + match return_value.status { + DirectRequestStatus::Error => { + debug!("request status is error"); + if let Ok(value) = + String::decode(&mut return_value.value.as_slice()) + { + println!("[Error] {}", value); + } + return None + }, + DirectRequestStatus::TrustedOperationStatus(status, top_hash) => { + debug!("request status is: {:?}, top_hash: {:?}", status, top_hash); + if let Ok(value) = Hash::decode(&mut return_value.value.as_slice()) + { + println!("Trusted call {:?} is {:?}", value, status); + if until(status.clone()) { + return Some((top_hash, Instant::now())) + } else if status == TrustedOperationStatus::Invalid { + error!("Invalid request"); + return None + } + } + }, + DirectRequestStatus::Ok => { + debug!("request status is ignored"); + return None + }, + } + }; + } else { + error!("Could not parse response"); + }; + }, + Err(e) => { + error!("failed to receive rpc response: {:?}", e); + return None + }, + }; + } +} diff --git a/bitacross-worker/cli/test_auto_shielding_with_transfer_bob.sh b/bitacross-worker/cli/test_auto_shielding_with_transfer_bob.sh new file mode 100644 index 0000000000..255d3f5bbc --- /dev/null +++ b/bitacross-worker/cli/test_auto_shielding_with_transfer_bob.sh @@ -0,0 +1,141 @@ +#!/bin/bash +set -euo pipefail + +# Verifies that auto shielding transfers sent to vault account: //Alice are verified from sender //Bob +# + +while getopts ":m:p:A:u:V:w:x:y:z:C:" opt; do + case $opt in + p) + INTEGRITEE_RPC_PORT=$OPTARG + ;; + A) + WORKER_1_PORT=$OPTARG + ;; + u) + INTEGRITEE_RPC_URL=$OPTARG + ;; + V) + WORKER_1_URL=$OPTARG + ;; + w) + TARGET_A_PARENTCHAIN_RPC_URL=$OPTARG + ;; + x) + TARGET_A_PARENTCHAIN_RPC_PORT=$OPTARG + ;; + C) + CLIENT_BIN=$OPTARG + ;; + *) + echo "invalid arg ${OPTARG}" + exit 1 + esac +done + +# Using default port if none given as arguments. +INTEGRITEE_RPC_PORT=${INTEGRITEE_RPC_PORT:-9944} +INTEGRITEE_RPC_URL=${INTEGRITEE_RPC_URL:-"ws://127.0.0.1"} +TARGET_A_PARENTCHAIN_RPC_PORT=${TARGET_A_PARENTCHAIN_RPC_PORT:-9966} +TARGET_A_PARENTCHAIN_RPC_URL=${TARGET_A_PARENTCHAIN_RPC_URL:-"ws://127.0.0.1"} + +WORKER_1_PORT=${WORKER_1_PORT:-2000} +WORKER_1_URL=${WORKER_1_URL:-"wss://127.0.0.1"} + +CLIENT_BIN=${CLIENT_BIN:-"./../bin/integritee-cli"} + +echo "Using client binary ${CLIENT_BIN}" +${CLIENT_BIN} --version +echo "Using Integritee RPC uri ${INTEGRITEE_RPC_URL}:${INTEGRITEE_RPC_PORT}" +echo "Using Target A RPC uri ${TARGET_A_PARENTCHAIN_RPC_URL}:${TARGET_A_PARENTCHAIN_RPC_PORT}" +echo "Using trusted-worker 1 uri ${WORKER_1_URL}:${WORKER_1_PORT}" +echo "" + +# the parentchain token is 12 decimal +UNIT=$(( 10 ** 12 )) +FEE_TOLERANCE=$((10 ** 11)) + +# make these amounts greater than ED +AMOUNT_SHIELD=$(( 6 * UNIT )) + +CLIENT="${CLIENT_BIN} -p ${INTEGRITEE_RPC_PORT} -P ${WORKER_1_PORT} -u ${INTEGRITEE_RPC_URL} -U ${WORKER_1_URL}" +CLIENT2="${CLIENT_BIN} -p ${TARGET_A_PARENTCHAIN_RPC_PORT} -P ${WORKER_1_PORT} -u ${TARGET_A_PARENTCHAIN_RPC_URL} -U ${WORKER_1_URL}" + +# interval and max rounds to wait to check the given account balance in sidechain +WAIT_INTERVAL_SECONDS=10 +WAIT_ROUNDS=20 + +# Poll and assert the given account's state is equal to expected, +# with timeout WAIT_INTERVAL_SECONDS * WAIT_ROUNDS +# usage: +# wait_assert_state +# the `state-name` has to be the supported subcommand, e.g. `balance`, `nonce` +function wait_assert_state() +{ + for i in $(seq 1 $WAIT_ROUNDS); do + sleep $WAIT_INTERVAL_SECONDS + state=$(${CLIENT} trusted --mrenclave "$1" "$3" "$2") + if (( $4 >= state ? $4 - state < FEE_TOLERANCE : state - $4 < FEE_TOLERANCE)); then + return + else + : + fi + done + echo + echo "Assert $2 $3 failed, expected = $4, actual = $state, tolerance = $FEE_TOLERANCE" + exit 1 +} + +# Do a live query and assert the given account's state is equal to expected +# usage: +# assert_state +function assert_state() +{ + state=$(${CLIENT} trusted --mrenclave "$1" "$3" "$2") + if [ -z "$state" ]; then + echo "Query $2 $3 failed" + exit 1 + fi + + if [ $state -eq "$4" ]; then + return + fi + echo + echo "Assert $2 $3 failed, expected = $4, actual = $state" + exit 1 +} + +echo "* Query on-chain enclave registry:" +${CLIENT} list-workers +echo "" + +# this will always take the first MRENCLAVE found in the registry !! +read MRENCLAVE <<< $($CLIENT list-workers | awk '/ MRENCLAVE: / { print $2; exit }') +echo "Reading MRENCLAVE from worker list: ${MRENCLAVE}" + +[[ -z $MRENCLAVE ]] && { echo "MRENCLAVE is empty. cannot continue" ; exit 1; } + +VAULTACCOUNT=//Alice +## Sender account to shield for +BOBTRUSTEDACCOUNT=//Bob +echo " Bob's trusted account (same as public account) = ${BOBTRUSTEDACCOUNT}" +echo "" + +# Assert the initial trusted balance of Alice incognito +TRUSTED_BALANCE_BOB=1000000000000000 +wait_assert_state ${MRENCLAVE} ${BOBTRUSTEDACCOUNT} balance ${TRUSTED_BALANCE_BOB} + + +echo "* Send ${AMOUNT_SHIELD} from //Bob to //Alice on the Target A parentchain, which should trigger the shield process" +${CLIENT2} transfer //Bob ${VAULTACCOUNT} ${AMOUNT_SHIELD} +echo "" + +echo "* Wait and assert Bob's incognito account balance, should be $(( TRUSTED_BALANCE_BOB + AMOUNT_SHIELD ))" +wait_assert_state ${MRENCLAVE} ${BOBTRUSTEDACCOUNT} balance $(( TRUSTED_BALANCE_BOB + AMOUNT_SHIELD )) +echo "✔ ok" + +echo "" +echo "-----------------------" +echo "✔ The test passed!" +echo "-----------------------" +echo "" diff --git a/bitacross-worker/cli/test_shield_on_target_nodes_with_transfer_to_alice.sh b/bitacross-worker/cli/test_shield_on_target_nodes_with_transfer_to_alice.sh new file mode 100755 index 0000000000..b1670e5bb8 --- /dev/null +++ b/bitacross-worker/cli/test_shield_on_target_nodes_with_transfer_to_alice.sh @@ -0,0 +1,159 @@ +#!/bin/bash +set -euo pipefail + +# Verifies that shielding from the Target A and B parentchains works by sending a transfer to //Alice. +# +# Note: This test does not do anything meaningful. It only verifies the basic functionality of the Target parentchain +# connections. + +while getopts ":m:p:A:u:V:w:x:y:z:C:" opt; do + case $opt in + p) + LITENTRY_RPC_PORT=$OPTARG + ;; + A) + WORKER_1_PORT=$OPTARG + ;; + u) + LITENTRY_RPC_URL=$OPTARG + ;; + V) + WORKER_1_URL=$OPTARG + ;; + w) + TARGET_A_PARENTCHAIN_RPC_URL=$OPTARG + ;; + x) + TARGET_A_PARENTCHAIN_RPC_PORT=$OPTARG + ;; + y) + TARGET_B_PARENTCHAIN_RPC_URL=$OPTARG + ;; + z) + TARGET_B_PARENTCHAIN_RPC_PORT=$OPTARG + ;; + C) + CLIENT_BIN=$OPTARG + ;; + *) + echo "invalid arg ${OPTARG}" + exit 1 + esac +done + +# Using default port if none given as arguments. +LITENTRY_RPC_PORT=${LITENTRY_RPC_PORT:-9944} +LITENTRY_RPC_URL=${LITENTRY_RPC_URL:-"ws://127.0.0.1"} +TARGET_A_PARENTCHAIN_RPC_PORT=${TARGET_A_PARENTCHAIN_RPC_PORT:-9966} +TARGET_A_PARENTCHAIN_RPC_URL=${TARGET_A_PARENTCHAIN_RPC_URL:-"ws://127.0.0.1"} +TARGET_B_PARENTCHAIN_RPC_PORT=${TARGET_B_PARENTCHAIN_RPC_PORT:-9988} +TARGET_B_PARENTCHAIN_RPC_URL=${TARGET_B_PARENTCHAIN_RPC_URL:-"ws://127.0.0.1"} + +WORKER_1_PORT=${WORKER_1_PORT:-2000} +WORKER_1_URL=${WORKER_1_URL:-"wss://127.0.0.1"} + +CLIENT_BIN=${CLIENT_BIN:-"./../bin/bitacross-cli"} + +echo "Using client binary ${CLIENT_BIN}" +${CLIENT_BIN} --version +echo "Using Integritee RPC uri ${LITENTRY_RPC_URL}:${LITENTRY_RPC_PORT}" +echo "Using Target A RPC uri ${TARGET_A_PARENTCHAIN_RPC_URL}:${TARGET_A_PARENTCHAIN_RPC_PORT}" +echo "Using Target B RPC uri ${TARGET_B_PARENTCHAIN_RPC_URL}:${TARGET_B_PARENTCHAIN_RPC_PORT}" +echo "Using trusted-worker 1 uri ${WORKER_1_URL}:${WORKER_1_PORT}" +echo "" + +# the parentchain token is 12 decimal +UNIT=$(( 10 ** 12 )) +FEE_TOLERANCE=$((10 ** 11)) + +# make these amounts greater than ED +AMOUNT_SHIELD=$(( 6 * UNIT )) + +CLIENT="${CLIENT_BIN} -p ${LITENTRY_RPC_PORT} -P ${WORKER_1_PORT} -u ${LITENTRY_RPC_URL} -U ${WORKER_1_URL}" +CLIENT2="${CLIENT_BIN} -p ${TARGET_A_PARENTCHAIN_RPC_PORT} -P ${WORKER_1_PORT} -u ${TARGET_A_PARENTCHAIN_RPC_URL} -U ${WORKER_1_URL}" +CLIENT3="${CLIENT_BIN} -p ${TARGET_B_PARENTCHAIN_RPC_PORT} -P ${WORKER_1_PORT} -u ${TARGET_B_PARENTCHAIN_RPC_URL} -U ${WORKER_1_URL}" + +# interval and max rounds to wait to check the given account balance in sidechain +WAIT_INTERVAL_SECONDS=10 +WAIT_ROUNDS=20 + +# Poll and assert the given account's state is equal to expected, +# with timeout WAIT_INTERVAL_SECONDS * WAIT_ROUNDS +# usage: +# wait_assert_state +# the `state-name` has to be the supported subcommand, e.g. `balance`, `nonce` +function wait_assert_state() +{ + for i in $(seq 1 $WAIT_ROUNDS); do + sleep $WAIT_INTERVAL_SECONDS + state=$(${CLIENT} trusted --mrenclave "$1" "$3" "$2") + if (( $4 >= state ? $4 - state < FEE_TOLERANCE : state - $4 < FEE_TOLERANCE)); then + return + else + : + fi + done + echo + echo "Assert $2 $3 failed, expected = $4, actual = $state, tolerance = $FEE_TOLERANCE" + exit 1 +} + +# Do a live query and assert the given account's state is equal to expected +# usage: +# assert_state +function assert_state() +{ + state=$(${CLIENT} trusted --mrenclave "$1" "$3" "$2") + if [ -z "$state" ]; then + echo "Query $2 $3 failed" + exit 1 + fi + + if [ $state -eq "$4" ]; then + return + fi + echo + echo "Assert $2 $3 failed, expected = $4, actual = $state" + exit 1 +} + +echo "* Query on-chain enclave registry:" +${CLIENT} list-workers +echo "" + +# this will always take the first MRENCLAVE found in the registry !! +read MRENCLAVE <<< $($CLIENT list-workers | awk '/ MRENCLAVE: / { print $2; exit }') +echo "Reading MRENCLAVE from worker list: ${MRENCLAVE}" + +[[ -z $MRENCLAVE ]] && { echo "MRENCLAVE is empty. cannot continue" ; exit 1; } + +ALICETRUSTEDACCOUNT=//Alice +echo " Alice's trusted account (same as public account) = ${ALICETRUSTEDACCOUNT}" +echo "" + +# Assert the initial trusted balance of Alice incognito +TRUSTED_BALANCE_ALICE=1000000000000000 +wait_assert_state ${MRENCLAVE} ${ALICETRUSTEDACCOUNT} balance ${TRUSTED_BALANCE_ALICE} + + +echo "* Send ${AMOUNT_SHIELD} from //Alice to //Alice on the Target A parentchain, which should trigger the shield process" +${CLIENT2} transfer //Alice ${ALICETRUSTEDACCOUNT} ${AMOUNT_SHIELD} +echo "" + +echo "* Wait and assert Alice's incognito account balance, should be $(( TRUSTED_BALANCE_ALICE + AMOUNT_SHIELD ))" +wait_assert_state ${MRENCLAVE} ${ALICETRUSTEDACCOUNT} balance $(( TRUSTED_BALANCE_ALICE + AMOUNT_SHIELD )) +echo "✔ ok" + +echo "* Send ${AMOUNT_SHIELD} from //Alice to //Alice on the Target B Parentchain, which should trigger the shield process again" +${CLIENT3} transfer //Alice ${ALICETRUSTEDACCOUNT} ${AMOUNT_SHIELD} +echo "" + +echo "* Wait and assert Alice's incognito account balance, should be $(( TRUSTED_BALANCE_ALICE + 2*AMOUNT_SHIELD ))" +wait_assert_state ${MRENCLAVE} ${ALICETRUSTEDACCOUNT} balance $(( TRUSTED_BALANCE_ALICE + 2*AMOUNT_SHIELD )) +echo "✔ ok" + +echo "" +echo "-----------------------" +echo "✔ The test passed!" +echo "-----------------------" +echo "" diff --git a/bitacross-worker/cli/tests/basic_tests.rs b/bitacross-worker/cli/tests/basic_tests.rs new file mode 100644 index 0000000000..d063b36072 --- /dev/null +++ b/bitacross-worker/cli/tests/basic_tests.rs @@ -0,0 +1,24 @@ +use bitacross_cli::Cli; +use clap::Parser; + +fn init() { + let _ = env_logger::try_init(); +} + +#[test] +fn test_version() { + init(); + + let res = Cli::try_parse_from(vec!["placeholder_cli_path", "--version"]); + let err = clap::Error::new(clap::error::ErrorKind::DisplayVersion); + assert!(matches!(res, Err(err))); +} + +#[test] +fn test_help() { + init(); + + let res = Cli::try_parse_from(vec!["placeholder_cli_path", "--help"]); + let err = clap::Error::new(clap::error::ErrorKind::DisplayHelp); + assert!(matches!(res, Err(err))); +} diff --git a/bitacross-worker/core-primitives/attestation-handler/AttestationReportSigningCACert.pem b/bitacross-worker/core-primitives/attestation-handler/AttestationReportSigningCACert.pem new file mode 100644 index 0000000000..948b4c0cdd --- /dev/null +++ b/bitacross-worker/core-primitives/attestation-handler/AttestationReportSigningCACert.pem @@ -0,0 +1,31 @@ +-----BEGIN CERTIFICATE----- +MIIFSzCCA7OgAwIBAgIJANEHdl0yo7CUMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNV +BAYTAlVTMQswCQYDVQQIDAJDQTEUMBIGA1UEBwwLU2FudGEgQ2xhcmExGjAYBgNV +BAoMEUludGVsIENvcnBvcmF0aW9uMTAwLgYDVQQDDCdJbnRlbCBTR1ggQXR0ZXN0 +YXRpb24gUmVwb3J0IFNpZ25pbmcgQ0EwIBcNMTYxMTE0MTUzNzMxWhgPMjA0OTEy +MzEyMzU5NTlaMH4xCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEUMBIGA1UEBwwL +U2FudGEgQ2xhcmExGjAYBgNVBAoMEUludGVsIENvcnBvcmF0aW9uMTAwLgYDVQQD +DCdJbnRlbCBTR1ggQXR0ZXN0YXRpb24gUmVwb3J0IFNpZ25pbmcgQ0EwggGiMA0G +CSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQCfPGR+tXc8u1EtJzLA10Feu1Wg+p7e +LmSRmeaCHbkQ1TF3Nwl3RmpqXkeGzNLd69QUnWovYyVSndEMyYc3sHecGgfinEeh +rgBJSEdsSJ9FpaFdesjsxqzGRa20PYdnnfWcCTvFoulpbFR4VBuXnnVLVzkUvlXT +L/TAnd8nIZk0zZkFJ7P5LtePvykkar7LcSQO85wtcQe0R1Raf/sQ6wYKaKmFgCGe +NpEJUmg4ktal4qgIAxk+QHUxQE42sxViN5mqglB0QJdUot/o9a/V/mMeH8KvOAiQ +byinkNndn+Bgk5sSV5DFgF0DffVqmVMblt5p3jPtImzBIH0QQrXJq39AT8cRwP5H +afuVeLHcDsRp6hol4P+ZFIhu8mmbI1u0hH3W/0C2BuYXB5PC+5izFFh/nP0lc2Lf +6rELO9LZdnOhpL1ExFOq9H/B8tPQ84T3Sgb4nAifDabNt/zu6MmCGo5U8lwEFtGM +RoOaX4AS+909x00lYnmtwsDVWv9vBiJCXRsCAwEAAaOByTCBxjBgBgNVHR8EWTBX +MFWgU6BRhk9odHRwOi8vdHJ1c3RlZHNlcnZpY2VzLmludGVsLmNvbS9jb250ZW50 +L0NSTC9TR1gvQXR0ZXN0YXRpb25SZXBvcnRTaWduaW5nQ0EuY3JsMB0GA1UdDgQW +BBR4Q3t2pn680K9+QjfrNXw7hwFRPDAfBgNVHSMEGDAWgBR4Q3t2pn680K9+Qjfr +NXw7hwFRPDAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBADANBgkq +hkiG9w0BAQsFAAOCAYEAeF8tYMXICvQqeXYQITkV2oLJsp6J4JAqJabHWxYJHGir +IEqucRiJSSx+HjIJEUVaj8E0QjEud6Y5lNmXlcjqRXaCPOqK0eGRz6hi+ripMtPZ +sFNaBwLQVV905SDjAzDzNIDnrcnXyB4gcDFCvwDFKKgLRjOB/WAqgscDUoGq5ZVi +zLUzTqiQPmULAQaB9c6Oti6snEFJiCQ67JLyW/E83/frzCmO5Ru6WjU4tmsmy8Ra +Ud4APK0wZTGtfPXU7w+IBdG5Ez0kE1qzxGQaL4gINJ1zMyleDnbuS8UicjJijvqA +152Sq049ESDz+1rRGc2NVEqh1KaGXmtXvqxXcTB+Ljy5Bw2ke0v8iGngFBPqCTVB +3op5KBG3RjbF6RRSzwzuWfL7QErNC8WEy5yDVARzTA5+xmBc388v9Dm21HGfcC8O +DD+gT9sSpssq0ascmvH49MOgjt1yoysLtdCtJW/9FZpoOypaHx0R+mJTLwPXVMrv +DaVzWh5aiEx+idkSGMnX +-----END CERTIFICATE----- diff --git a/bitacross-worker/core-primitives/attestation-handler/Cargo.toml b/bitacross-worker/core-primitives/attestation-handler/Cargo.toml new file mode 100644 index 0000000000..a00ec0affb --- /dev/null +++ b/bitacross-worker/core-primitives/attestation-handler/Cargo.toml @@ -0,0 +1,102 @@ +[package] +name = "itp-attestation-handler" +version = "0.8.0" +authors = ['Trust Computing GmbH ', 'Integritee AG '] +edition = "2021" + +[dependencies] +# crates-io no_std deps +arrayvec = { version = "0.7.1", default-features = false } +bit-vec = { version = "0.6", default-features = false } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +hex = { version = "0.4.3", default-features = false, features = ["alloc"] } +itertools = { default-features = false, version = "0.10.1" } +log = { version = "0.4", default-features = false } + +# std only deps +base64 = { version = "0.13", features = ["alloc"], optional = true } +chrono = { version = "0.4.19", features = ["alloc"], optional = true } +rustls = { version = "0.19", optional = true } +serde_json = { version = "1.0", features = ["preserve_order"], optional = true } +thiserror = { version = "1.0", optional = true } +webpki = { version = "0.21", optional = true } + +# mesalock +base64_sgx = { package = "base64", rev = "sgx_1.1.3", git = "https://github.com/mesalock-linux/rust-base64-sgx", optional = true } +chrono_sgx = { package = "chrono", git = "https://github.com/mesalock-linux/chrono-sgx", optional = true } +num-bigint = { optional = true, git = "https://github.com/mesalock-linux/num-bigint-sgx" } +rustls_sgx = { package = "rustls", rev = "sgx_1.1.3", features = ["dangerous_configuration"], git = "https://github.com/mesalock-linux/rustls", optional = true } +serde_json_sgx = { package = "serde_json", tag = "sgx_1.1.3", features = ["preserve_order"], git = "https://github.com/mesalock-linux/serde-json-sgx", optional = true } +thiserror_sgx = { package = "thiserror", git = "https://github.com/mesalock-linux/thiserror-sgx", tag = "sgx_1.1.3", optional = true } +webpki-roots = { git = "https://github.com/mesalock-linux/webpki-roots", branch = "mesalock_sgx" } +webpki_sgx = { package = "webpki", git = "https://github.com/mesalock-linux/webpki", branch = "mesalock_sgx", optional = true } +yasna_sgx = { package = "yasna", optional = true, default-features = false, features = ["bit-vec", "num-bigint", "chrono", "mesalock_sgx"], git = "https://github.com/mesalock-linux/yasna.rs-sgx", rev = "sgx_1.1.3" } + +# sgx +sgx_rand = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git", optional = true } +sgx_tcrypto = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git", optional = true } +sgx_tse = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git", optional = true } +sgx_tstd = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git", features = ["untrusted_fs", "net", "backtrace"], optional = true } +sgx_types = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git", features = ["extra_traits"] } + +# local deps +itp-ocall-api = { path = "../ocall-api", default-features = false } +itp-settings = { path = "../settings" } +itp-sgx-crypto = { path = "../sgx/crypto", default-features = false } +itp-sgx-io = { path = "../sgx/io", default-features = false } +itp-time-utils = { path = "../time-utils", default-features = false } + +# integritee +httparse = { default-features = false, git = "https://github.com/integritee-network/httparse-sgx", branch = "sgx-experimental" } + +# substrate deps +sp-core = { default-features = false, features = ["full_crypto"], git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } + +[features] +default = ["std"] +std = [ + # crates-io no_std + "arrayvec/std", + "codec/std", + "hex/std", + "log/std", + "itertools/use_std", + # optional std only + "base64", + "chrono", + "rustls", + "serde_json", + "thiserror", + "webpki", + # local + "itp-ocall-api/std", + "itp-sgx-io/std", + "itp-sgx-crypto/std", + # substrate + "sp-core/std", + # integritee + "httparse/std", +] + +sgx = [ + # sgx-only + "base64_sgx", + "chrono_sgx", + "rustls_sgx", + "serde_json_sgx", + "thiserror_sgx", + "webpki_sgx", + "yasna_sgx", + "sgx_tse", + "sgx_tstd", + "sgx_rand", + "sgx_tcrypto", + "num-bigint", + # local + "itp-sgx-io/sgx", + "itp-sgx-crypto/sgx", + # integritee + "httparse/mesalock_sgx", +] +test = [] +production = [] diff --git a/bitacross-worker/core-primitives/attestation-handler/src/attestation_handler.rs b/bitacross-worker/core-primitives/attestation-handler/src/attestation_handler.rs new file mode 100644 index 0000000000..9657db5edc --- /dev/null +++ b/bitacross-worker/core-primitives/attestation-handler/src/attestation_handler.rs @@ -0,0 +1,853 @@ +// Copyright 2022 Integritee AG and Supercomputing Systems AG +// Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in +// the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Baidu, Inc., nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +use crate::sgx_reexport_prelude::*; + +use crate::{cert, Error as EnclaveError, Error, Result as EnclaveResult}; +use codec::Encode; +use core::{convert::TryInto, default::Default}; +use itertools::Itertools; +use itp_ocall_api::EnclaveAttestationOCallApi; +use itp_settings::{ + files::{RA_API_KEY_FILE, RA_DUMP_CERT_DER_FILE, RA_SPID_FILE}, + worker::MR_ENCLAVE_SIZE, +}; +use itp_sgx_crypto::key_repository::AccessKey; +use itp_sgx_io as io; +use itp_time_utils::now_as_secs; +use log::*; +use sgx_rand::{os, Rng}; +use sgx_tcrypto::{rsgx_sha256_slice, SgxEccHandle}; +use sgx_tse::{rsgx_create_report, rsgx_verify_report}; +use sgx_types::{ + c_int, sgx_epid_group_id_t, sgx_quote_nonce_t, sgx_quote_sign_type_t, sgx_report_data_t, + sgx_spid_t, sgx_status_t, sgx_target_info_t, SgxResult, *, +}; +use sp_core::{ed25519, Pair}; +use std::{ + borrow::ToOwned, + env, format, + io::{Read, Write}, + net::TcpStream, + prelude::v1::*, + println, str, + string::{String, ToString}, + sync::Arc, + vec::Vec, +}; + +pub const DEV_HOSTNAME: &str = "api.trustedservices.intel.com"; + +// Litentry TODO: use `dev` for production temporary. Will switch to dcap later. +#[cfg(feature = "production")] +pub const SIGRL_SUFFIX: &str = "/sgx/dev/attestation/v4/sigrl/"; +#[cfg(feature = "production")] +pub const REPORT_SUFFIX: &str = "/sgx/dev/attestation/v4/report"; + +#[cfg(not(feature = "production"))] +pub const SIGRL_SUFFIX: &str = "/sgx/dev/attestation/v4/sigrl/"; +#[cfg(not(feature = "production"))] +pub const REPORT_SUFFIX: &str = "/sgx/dev/attestation/v4/report"; + +/// Trait to provide an abstraction to the attestation logic +pub trait AttestationHandler { + /// Generates an encoded remote attestation certificate. Returns DER encoded certificate. + /// If skip_ra is set, it will not perform a remote attestation via IAS + /// but instead generate a mock certificate. + fn generate_ias_ra_cert(&self, skip_ra: bool) -> EnclaveResult>; + + /// Returns the DER encoded private_key, DER encoded certificate and the raw DCAP quote. + /// If skip_ra is set, it will not perform a remote attestation via IAS + /// but instead generate a mock certificate. + fn generate_dcap_ra_cert( + &self, + quoting_enclave_target_info: Option<&sgx_target_info_t>, + quote_size: Option<&u32>, + skip_ra: bool, + ) -> EnclaveResult<(Vec, Vec, Vec)>; + + /// Get the measurement register value of the enclave + fn get_mrenclave(&self) -> EnclaveResult<[u8; MR_ENCLAVE_SIZE]>; + + /// Write the remote attestation report to the disk + fn dump_ias_ra_cert_to_disk(&self) -> EnclaveResult<()>; + + /// Write the remote attestation report to the disk + fn dump_dcap_ra_cert_to_disk( + &self, + quoting_enclave_target_info: &sgx_target_info_t, + quote_size: u32, + ) -> EnclaveResult<()>; + + /// Create the remote attestation report and encapsulate it in a DER certificate + /// Returns a pair consisting of (private key DER, certificate DER) + fn create_epid_ra_report_and_signature( + &self, + sign_type: sgx_quote_sign_type_t, + skip_ra: bool, + ) -> EnclaveResult<(Vec, Vec)>; +} + +pub struct IntelAttestationHandler { + pub(crate) ocall_api: Arc, + pub(crate) signing_key_repo: Arc, +} + +impl IntelAttestationHandler +where + OCallApi: EnclaveAttestationOCallApi, + AccessSigningKey: AccessKey, +{ + fn create_payload_epid( + &self, + pub_k: &[u8; 32], + sign_type: sgx_quote_sign_type_t, + ) -> EnclaveResult { + info!(" [Enclave] Create attestation report"); + let (attn_report, sig, cert) = match self.create_epid_attestation_report(&pub_k, sign_type) + { + Ok(r) => r, + Err(e) => { + error!(" [Enclave] Error in create_attestation_report: {:?}", e); + return Err(e.into()) + }, + }; + println!(" [Enclave] Create attestation report successful"); + debug!(" attn_report = {:?}", attn_report); + debug!(" sig = {:?}", sig); + debug!(" cert = {:?}", cert); + + // concat the information + Ok(attn_report + "|" + &sig + "|" + &cert) + } +} + +impl AttestationHandler + for IntelAttestationHandler +where + OCallApi: EnclaveAttestationOCallApi, + AccessSigningKey: AccessKey, +{ + fn generate_ias_ra_cert(&self, skip_ra: bool) -> EnclaveResult> { + // Our certificate is unlinkable. + let sign_type = sgx_quote_sign_type_t::SGX_UNLINKABLE_SIGNATURE; + + // FIXME: should call `create_ra_report_and_signature` in skip_ra mode as well: + // https://github.com/integritee-network/worker/issues/321. + let cert_der = if !skip_ra { + match self.create_epid_ra_report_and_signature(sign_type, skip_ra) { + Ok((_key_der, cert_der)) => cert_der, + Err(e) => return Err(e), + } + } else { + self.get_mrenclave()?.encode() + }; + + Ok(cert_der) + } + + fn get_mrenclave(&self) -> EnclaveResult<[u8; MR_ENCLAVE_SIZE]> { + match self.ocall_api.get_mrenclave_of_self() { + Ok(m) => Ok(m.m), + Err(e) => Err(EnclaveError::Sgx(e)), + } + } + + fn dump_ias_ra_cert_to_disk(&self) -> EnclaveResult<()> { + // our certificate is unlinkable + let sign_type = sgx_quote_sign_type_t::SGX_UNLINKABLE_SIGNATURE; + + let (_key_der, cert_der) = match self.create_epid_ra_report_and_signature(sign_type, false) + { + Ok(r) => r, + Err(e) => return Err(e), + }; + + if let Err(err) = io::write(&cert_der, RA_DUMP_CERT_DER_FILE) { + error!( + " [Enclave] failed to write RA file ({}), status: {:?}", + RA_DUMP_CERT_DER_FILE, err + ); + return Err(Error::IoError(err)) + } + info!(" [Enclave] dumped ra cert to {}", RA_DUMP_CERT_DER_FILE); + Ok(()) + } + + fn dump_dcap_ra_cert_to_disk( + &self, + quoting_enclave_target_info: &sgx_target_info_t, + quote_size: u32, + ) -> EnclaveResult<()> { + let (_priv_key_der, _cert_der, dcap_quote) = match self.generate_dcap_ra_cert( + Some(quoting_enclave_target_info), + Some("e_size), + false, + ) { + Ok(r) => r, + Err(e) => return Err(e), + }; + + if let Err(err) = io::write(&dcap_quote, RA_DUMP_CERT_DER_FILE) { + error!( + " [Enclave] failed to write RA file ({}), status: {:?}", + RA_DUMP_CERT_DER_FILE, err + ); + return Err(Error::IoError(err)) + } + info!(" [Enclave] dumped ra cert to {}", RA_DUMP_CERT_DER_FILE); + Ok(()) + } + + fn create_epid_ra_report_and_signature( + &self, + sign_type: sgx_quote_sign_type_t, + skip_ra: bool, + ) -> EnclaveResult<(Vec, Vec)> { + let chain_signer = self.signing_key_repo.retrieve_key()?; + info!("[Enclave Attestation] Ed25519 pub raw : {:?}", chain_signer.public().0); + + info!(" [Enclave] Generate keypair"); + let ecc_handle = SgxEccHandle::new(); + let _result = ecc_handle.open(); + let (prv_k, pub_k) = ecc_handle.create_key_pair()?; + info!(" [Enclave] Generate ephemeral ECDSA keypair successful"); + debug!(" pubkey X is {:02x}", pub_k.gx.iter().format("")); + debug!(" pubkey Y is {:02x}", pub_k.gy.iter().format("")); + + let payload = if !skip_ra { + self.create_payload_epid(&chain_signer.public().0, sign_type)? + } else { + Default::default() + }; + + // generate an ECC certificate + info!(" [Enclave] Generate ECC Certificate"); + let (key_der, cert_der) = match cert::gen_ecc_cert(&payload, &prv_k, &pub_k, &ecc_handle) { + Ok(r) => r, + Err(e) => { + error!(" [Enclave] gen_ecc_cert failed: {:?}", e); + return Err(e.into()) + }, + }; + + let _ = ecc_handle.close(); + info!(" [Enclave] Generate ECC Certificate successful"); + Ok((key_der, cert_der)) + } + + fn generate_dcap_ra_cert( + &self, + quoting_enclave_target_info: Option<&sgx_target_info_t>, + quote_size: Option<&u32>, + skip_ra: bool, + ) -> EnclaveResult<(Vec, Vec, Vec)> { + if !skip_ra && quoting_enclave_target_info.is_none() && quote_size.is_none() { + error!("Enclave Attestation] remote attestation not skipped, but Quoting Enclave (QE) data is not available"); + return Err(EnclaveError::Sgx(sgx_status_t::SGX_ERROR_UNEXPECTED)) + } + let chain_signer = self.signing_key_repo.retrieve_key()?; + info!("[Enclave Attestation] Ed25519 signer pub key: {:?}", chain_signer.public().0); + + let ecc_handle = SgxEccHandle::new(); + let _result = ecc_handle.open(); + let (prv_k, pub_k) = ecc_handle.create_key_pair()?; + info!("Enclave Attestation] Generated ephemeral ECDSA keypair:"); + debug!(" pubkey X is {:02x}", pub_k.gx.iter().format("")); + debug!(" pubkey Y is {:02x}", pub_k.gy.iter().format("")); + + let qe_quote = if !skip_ra { + let qe_quote = match self.retrieve_qe_dcap_quote( + &chain_signer.public().0, + quoting_enclave_target_info.unwrap(), + *quote_size.unwrap(), + ) { + Ok(quote) => quote, + Err(e) => { + error!("[Enclave] Error in create_dcap_attestation_report: {:?}", e); + return Err(e.into()) + }, + }; + qe_quote + } else { + Default::default() + }; + + let qe_quote_base_64 = base64::encode(&qe_quote[..]); + // generate an ECC certificate + debug!("[Enclave] Generate ECC Certificate"); + let (key_der, cert_der) = + match cert::gen_ecc_cert(&qe_quote_base_64, &prv_k, &pub_k, &ecc_handle) { + Ok(r) => r, + Err(e) => { + error!("[Enclave] gen_ecc_cert failed: {:?}", e); + return Err(e.into()) + }, + }; + + let _ = ecc_handle.close(); + + debug!("[Enclave] Generated ECC cert info:"); + trace!("[Enclave] Generated ECC cert info: key_der={:?}", &key_der); + trace!("[Enclave] Generated ECC cert info: cert_der={:?}", &cert_der); + trace!("[Enclave] Generated ECC cert info: qe_quote={:?}", &qe_quote); + Ok((key_der, cert_der, qe_quote)) + } +} + +impl IntelAttestationHandler { + pub fn new(ocall_api: Arc, signing_key_repo: Arc) -> Self { + Self { ocall_api, signing_key_repo } + } +} + +impl IntelAttestationHandler +where + OCallApi: EnclaveAttestationOCallApi, + AccessSigningKey: AccessKey, +{ + fn parse_response_attn_report(&self, resp: &[u8]) -> EnclaveResult<(String, String, String)> { + debug!(" [Enclave] Entering parse_response_attn_report"); + let mut headers = [httparse::EMPTY_HEADER; 16]; + let mut respp = httparse::Response::new(&mut headers); + let result = respp.parse(resp); + debug!(" [Enclave] respp.parse result {:?}", result); + + self.log_resp_code(&mut respp.code); + + let mut len_num: u32 = 0; + + let mut sig = String::new(); + let mut cert = String::new(); + let mut attn_report = String::new(); + + for i in 0..respp.headers.len() { + let h = respp.headers[i]; + //println!("{} : {}", h.name, str::from_utf8(h.value).unwrap()); + match h.name { + "Content-Length" => { + let len_str = String::from_utf8(h.value.to_vec()) + .map_err(|e| EnclaveError::Other(e.into()))?; + len_num = len_str.parse::().map_err(|e| EnclaveError::Other(e.into()))?; + debug!(" [Enclave] Content length = {}", len_num); + }, + "X-IASReport-Signature" => + sig = String::from_utf8(h.value.to_vec()) + .map_err(|e| EnclaveError::Other(e.into()))?, + "X-IASReport-Signing-Certificate" => + cert = String::from_utf8(h.value.to_vec()) + .map_err(|e| EnclaveError::Other(e.into()))?, + _ => (), + } + } + + // Remove %0A from cert, and only obtain the signing cert + cert = cert.replace("%0A", ""); + cert = cert::percent_decode(cert)?; + let v: Vec<&str> = cert.split("-----").collect(); + let sig_cert = v[2].to_string(); + + if len_num != 0 { + // The unwrap is safe. It resolves to the https::Status' unwrap function which only panics + // if the the response is not complete, which cannot happen if the result is Ok(). + let header_len = result.map_err(|e| EnclaveError::Other(e.into()))?.unwrap(); + let resp_body = &resp[header_len..]; + attn_report = + String::from_utf8(resp_body.to_vec()).map_err(|e| EnclaveError::Other(e.into()))?; + debug!(" [Enclave] Attestation report = {}", attn_report); + } + + // len_num == 0 + Ok((attn_report, sig, sig_cert)) + } + + fn log_resp_code(&self, resp_code: &mut Option) { + let msg = match resp_code { + Some(200) => "OK, operation successful", + Some(400) => "Bad request, quote is invalid, or linkability of quote/subscription does not match.", + Some(401) => "Unauthorized, failed to authenticate or authorize request.", + Some(404) => "Not found, GID does not refer to a valid EPID group ID.", + Some(500) => "Internal error occurred.", + Some(503) => + "Service is currently not able to process the request (due to + a temporary overloading or maintenance). This is a + temporary state – the same request can be repeated after + some time.", + _ => { + error!("Error, received unknown HTTP response: {:?}", resp_code); + "Unknown error occured" + }, + }; + debug!(" [Enclave] msg = {}", msg); + } + + fn parse_response_sigrl(&self, resp: &[u8]) -> EnclaveResult> { + debug!(" [Enclave] Entering parse_response_sigrl"); + let mut headers = [httparse::EMPTY_HEADER; 16]; + let mut respp = httparse::Response::new(&mut headers); + let result = respp.parse(resp); + debug!(" [Enclave] Parse result {:?}", result); + debug!(" [Enclave] Parse response {:?}", respp); + + self.log_resp_code(&mut respp.code); + + let mut len_num: u32 = 0; + + for i in 0..respp.headers.len() { + let h = respp.headers[i]; + if h.name == "content-length" { + let len_str = String::from_utf8(h.value.to_vec()) + .map_err(|e| EnclaveError::Other(e.into()))?; + len_num = len_str.parse::().map_err(|e| EnclaveError::Other(e.into()))?; + debug!(" [Enclave] Content length = {}", len_num); + } + } + + if len_num != 0 { + // The unwrap is safe. It resolves to the https::Status' unwrap function which only panics + // if the the response is not complete, which cannot happen if the result is Ok(). + let header_len = result.map_err(|e| EnclaveError::Other(e.into()))?.unwrap(); + let resp_body = &resp[header_len..]; + debug!(" [Enclave] Base64-encoded SigRL: {:?}", resp_body); + + let resp_str = str::from_utf8(resp_body).map_err(|e| EnclaveError::Other(e.into()))?; + return base64::decode(resp_str).map_err(|e| EnclaveError::Other(e.into())) + } + + // len_num == 0 + Ok(Vec::new()) + } + + fn make_ias_client_config() -> rustls::ClientConfig { + let mut config = rustls::ClientConfig::new(); + + config.root_store.add_server_trust_anchors(&webpki_roots::TLS_SERVER_ROOTS); + config + } + + fn get_sigrl_from_intel(&self, fd: c_int, gid: u32) -> EnclaveResult> { + debug!(" [Enclave] Entering get_sigrl_from_intel. fd = {:?}", fd); + let config = Self::make_ias_client_config(); + //let sigrl_arg = SigRLArg { group_id : gid }; + //let sigrl_req = sigrl_arg.to_httpreq(); + let ias_key = Self::get_ias_api_key()?; + + let req = format!("GET {}{:08x} HTTP/1.1\r\nHOST: {}\r\nOcp-Apim-Subscription-Key: {}\r\nConnection: Close\r\n\r\n", + SIGRL_SUFFIX, + gid, + DEV_HOSTNAME, + ias_key); + debug!(" [Enclave] request = {}", req); + + let dns_name = webpki::DNSNameRef::try_from_ascii_str(DEV_HOSTNAME) + .map_err(|e| EnclaveError::Other(e.into()))?; + let mut sess = rustls::ClientSession::new(&Arc::new(config), dns_name); + let mut sock = TcpStream::new(fd)?; + let mut tls = rustls::Stream::new(&mut sess, &mut sock); + + let _result = tls.write(req.as_bytes()); + let mut plaintext = Vec::new(); + + debug!(" [Enclave] tls.write complete"); + + tls.read_to_end(&mut plaintext)?; + + debug!(" [Enclave] tls.read_to_end complete"); + let resp_string = + String::from_utf8(plaintext.clone()).map_err(|e| EnclaveError::Other(e.into()))?; + + debug!(" [Enclave] resp_string = {}", resp_string); + + self.parse_response_sigrl(&plaintext) + } + + // TODO: support pse + fn get_report_from_intel( + &self, + fd: c_int, + quote: Vec, + ) -> EnclaveResult<(String, String, String)> { + debug!(" [Enclave] Entering get_report_from_intel. fd = {:?}", fd); + let config = Self::make_ias_client_config(); + let encoded_quote = base64::encode("e[..]); + let encoded_json = format!("{{\"isvEnclaveQuote\":\"{}\"}}\r\n", encoded_quote); + + let ias_key = Self::get_ias_api_key()?; + + let req = format!("POST {} HTTP/1.1\r\nHOST: {}\r\nOcp-Apim-Subscription-Key:{}\r\nContent-Length:{}\r\nContent-Type: application/json\r\nConnection: close\r\n\r\n{}", + REPORT_SUFFIX, + DEV_HOSTNAME, + ias_key, + encoded_json.len(), + encoded_json); + debug!(" [Enclave] Req = {}", req); + let dns_name = webpki::DNSNameRef::try_from_ascii_str(DEV_HOSTNAME).map_err(|e| { + error!("Invalid DEV_HOSTNAME"); + EnclaveError::Other(e.into()) + })?; + let mut sess = rustls::ClientSession::new(&Arc::new(config), dns_name); + let mut sock = TcpStream::new(fd)?; + let mut tls = rustls::Stream::new(&mut sess, &mut sock); + + let _result = tls.write(req.as_bytes()); + let mut plaintext = Vec::new(); + + debug!(" [Enclave] tls.write complete"); + + tls.read_to_end(&mut plaintext)?; + debug!(" [Enclave] tls.read_to_end complete"); + let resp_string = String::from_utf8(plaintext.clone()).map_err(|e| { + error!(" [Enclave] error decoding tls answer to string"); + EnclaveError::Other(e.into()) + })?; + + debug!(" [Enclave] resp_string = {}", resp_string); + + self.parse_response_attn_report(&plaintext) + } + + fn as_u32_le(&self, array: [u8; 4]) -> u32 { + u32::from(array[0]) + + (u32::from(array[1]) << 8) + + (u32::from(array[2]) << 16) + + (u32::from(array[3]) << 24) + } + + fn create_epid_attestation_report( + &self, + pub_k: &[u8; 32], + sign_type: sgx_quote_sign_type_t, + ) -> SgxResult<(String, String, String)> { + // Workflow: + // (1) ocall to get the target_info structure (ti) and epid group id (eg) + // (1.5) get sigrl + // (2) call sgx_create_report with ti+data, produce an sgx_report_t + // (3) ocall to sgx_get_quote to generate (*mut sgx-quote_t, uint32_t) + + // (1) get ti + eg + let init_quote = self.ocall_api.sgx_init_quote()?; + + let epid_group_id: sgx_epid_group_id_t = init_quote.1; + let target_info: sgx_target_info_t = init_quote.0; + + debug!(" [Enclave] EPID group id = {:?}", epid_group_id); + + let eg_num = self.as_u32_le(epid_group_id); + + // (1.5) get sigrl + let ias_socket = self.ocall_api.get_ias_socket()?; + + info!(" [Enclave] ias_sock = {}", ias_socket); + + // Now sigrl_vec is the revocation list, a vec + let sigrl_vec: Vec = self.get_sigrl_from_intel(ias_socket, eg_num)?; + + // (2) Generate the report + let mut report_data: sgx_report_data_t = sgx_report_data_t::default(); + report_data.d[..32].clone_from_slice(&pub_k[..]); + + let report = match rsgx_create_report(&target_info, &report_data) { + Ok(r) => { + debug!( + " [Enclave] Report creation successful. mr_signer.m = {:x?}", + r.body.mr_signer.m + ); + r + }, + Err(e) => { + error!(" [Enclave] Report creation failed. {:?}", e); + return Err(e) + }, + }; + + let mut quote_nonce = sgx_quote_nonce_t { rand: [0; 16] }; + let mut os_rng = os::SgxRng::new().map_err(|e| EnclaveError::Other(e.into()))?; + os_rng.fill_bytes(&mut quote_nonce.rand); + + // (3) Generate the quote + // Args: + // 1. sigrl: ptr + len + // 2. report: ptr 432bytes + // 3. linkable: u32, unlinkable=0, linkable=1 + // 4. spid: sgx_spid_t ptr 16bytes + // 5. sgx_quote_nonce_t ptr 16bytes + // 6. p_sig_rl + sigrl size ( same to sigrl) + // 7. [out]p_qe_report need further check + // 8. [out]p_quote + // 9. quote_size + + let spid: sgx_spid_t = Self::load_spid(RA_SPID_FILE)?; + + let quote_result = + self.ocall_api.get_quote(sigrl_vec, report, sign_type, spid, quote_nonce)?; + + let qe_report = quote_result.0; + let quote_content = quote_result.1; + + // Added 09-28-2018 + // Perform a check on qe_report to verify if the qe_report is valid + match rsgx_verify_report(&qe_report) { + Ok(()) => debug!(" [Enclave] rsgx_verify_report success!"), + Err(x) => { + error!(" [Enclave] rsgx_verify_report failed. {:?}", x); + return Err(x) + }, + } + + // Check if the qe_report is produced on the same platform + if target_info.mr_enclave.m != qe_report.body.mr_enclave.m + || target_info.attributes.flags != qe_report.body.attributes.flags + || target_info.attributes.xfrm != qe_report.body.attributes.xfrm + { + error!(" [Enclave] qe_report does not match current target_info!"); + return Err(sgx_status_t::SGX_ERROR_UNEXPECTED) + } + + debug!(" [Enclave] qe_report check success"); + + // Check qe_report to defend against replay attack + // The purpose of p_qe_report is for the ISV enclave to confirm the QUOTE + // it received is not modified by the untrusted SW stack, and not a replay. + // The implementation in QE is to generate a REPORT targeting the ISV + // enclave (target info from p_report) , with the lower 32Bytes in + // report.data = SHA256(p_nonce||p_quote). The ISV enclave can verify the + // p_qe_report and report.data to confirm the QUOTE has not be modified and + // is not a replay. It is optional. + + // need to call this a second time (first time is when we get the sigrl revocation list) + // (has some internal state that needs to be reset)! + let ias_socket = self.ocall_api.get_ias_socket()?; + + let mut rhs_vec: Vec = quote_nonce.rand.to_vec(); + rhs_vec.extend("e_content); + let rhs_hash = rsgx_sha256_slice(&rhs_vec[..])?; + let lhs_hash = &qe_report.body.report_data.d[..32]; + + debug!(" [Enclave] rhs hash = {:02X}", rhs_hash.iter().format("")); + debug!(" [Enclave] lhs hash = {:02X}", lhs_hash.iter().format("")); + + if rhs_hash != lhs_hash { + error!(" [Enclave] Quote is tampered!"); + return Err(sgx_status_t::SGX_ERROR_UNEXPECTED) + } + + let (attn_report, sig, cert) = self.get_report_from_intel(ias_socket, quote_content)?; + Ok((attn_report, sig, cert)) + } + + fn load_spid(filename: &str) -> SgxResult { + // Check if set as an environment variable + match env::var("IAS_EPID_SPID").or_else(|_| io::read_to_string(filename)) { + Ok(spid) => decode_spid(&spid), + Err(e) => { + error!("Failed to load SPID: {:?}", e); + Err(sgx_status_t::SGX_ERROR_UNEXPECTED) + }, + } + } + + fn get_ias_api_key() -> EnclaveResult { + // Check if set as an environment variable + env::var("IAS_EPID_KEY") + .or_else(|_| io::read_to_string(RA_API_KEY_FILE)) + .map(|key| key.trim_end().to_owned()) + .map_err(|e| EnclaveError::Other(e.into())) + } + + /// Returns Ok if the verification of the quote by the quote verification enclave (QVE) was successful + pub fn ecdsa_quote_verification(&self, quote: Vec) -> SgxResult<()> { + let mut app_enclave_target_info: sgx_target_info_t = unsafe { std::mem::zeroed() }; + let quote_collateral: sgx_ql_qve_collateral_t = unsafe { std::mem::zeroed() }; + let mut qve_report_info: sgx_ql_qe_report_info_t = unsafe { std::mem::zeroed() }; + let supplemental_data_size = std::mem::size_of::() as u32; + + // Get target info of the app enclave. QvE will target the generated report to this enclave. + let ret_val = + unsafe { sgx_self_target(&mut app_enclave_target_info as *mut sgx_target_info_t) }; + if ret_val != sgx_status_t::SGX_SUCCESS { + error!("sgx_self_target returned: {:?}", ret_val); + return Err(sgx_status_t::SGX_ERROR_UNEXPECTED) + } + + // Set current time, which is needed to check against the expiration date of the certificate. + let current_time: i64 = now_as_secs().try_into().unwrap_or_else(|e| { + panic!("Could not convert SystemTime from u64 into i64: {:?}", e); + }); + + // Set random nonce. + let mut rand_nonce = vec![0u8; 16]; + let ret_val = unsafe { sgx_read_rand(rand_nonce.as_mut_ptr(), rand_nonce.len()) }; + if ret_val != sgx_status_t::SGX_SUCCESS { + error!("sgx_read_rand returned: {:?}", ret_val); + return Err(sgx_status_t::SGX_ERROR_UNEXPECTED) + } + debug!("Retrieved random nonce {:?}", rand_nonce); + qve_report_info.nonce.rand.copy_from_slice(rand_nonce.as_slice()); + qve_report_info.app_enclave_target_info = app_enclave_target_info; + + // Ocall to call Quote verification Enclave (QvE), which verifies the generated quote. + let ( + collateral_expiration_status, + quote_verification_result, + qve_report_info_return_value, + supplemental_data, + ) = self.ocall_api.get_qve_report_on_quote( + quote.clone(), + current_time, + quote_collateral, + qve_report_info, + supplemental_data_size, + )?; + + // Check nonce of qve report to protect against replay attacks, as the qve report + // is coming from the untrusted side. + if qve_report_info_return_value.nonce.rand != qve_report_info.nonce.rand { + error!( + "Nonce of input value and return value are not matching. Input: {:?}, Output: {:?}", + qve_report_info.nonce.rand, qve_report_info_return_value.nonce.rand + ); + return Err(sgx_status_t::SGX_ERROR_UNEXPECTED) + } + + // Set the threshold of QvE ISV SVN. The ISV SVN of QvE used to verify quote must be greater or equal to this threshold + // e.g. You can check latest QvE ISVSVN from QvE configuration file on Github + // https://github.com/intel/SGXDataCenterAttestationPrimitives/blob/master/QuoteVerification/QvE/Enclave/linux/config.xml#L4 + // or you can get latest QvE ISVSVN in QvE Identity JSON file from + // https://api.trustedservices.intel.com/sgx/certification/v3/qve/identity + // Make sure you are using trusted & latest QvE ISV SVN as threshold + // Warning: The function may return erroneous result if QvE ISV SVN has been modified maliciously. + let qve_isvsvn_threshold: sgx_isv_svn_t = 6; + + // Verify the qve report to validate that it is coming from a legit quoting verification enclave + // and has not been tampered with. + let ret_val = unsafe { + sgx_tvl_verify_qve_report_and_identity( + quote.as_ptr(), + quote.len() as u32, + &qve_report_info_return_value as *const sgx_ql_qe_report_info_t, + current_time, + collateral_expiration_status, + quote_verification_result, + supplemental_data.as_ptr(), + supplemental_data_size, + qve_isvsvn_threshold, + ) + }; + + if ret_val != sgx_quote3_error_t::SGX_QL_SUCCESS { + error!("sgx_tvl_verify_qve_report_and_identity returned: {:?}", ret_val); + return Err(sgx_status_t::SGX_ERROR_UNEXPECTED) + } + + Ok(()) + } + + pub fn retrieve_qe_dcap_quote( + &self, + pub_k: &[u8; 32], + quoting_enclave_target_info: &sgx_target_info_t, + quote_size: u32, + ) -> SgxResult> { + // Generate app enclave report and include the enclave public key. + // The quote will be generated on top of this report and validate that the + // report as well as the public key inside it are coming from a legit + // intel sgx enclave. + let mut report_data: sgx_report_data_t = sgx_report_data_t::default(); + report_data.d[..32].clone_from_slice(&pub_k[..]); + + let app_report = match rsgx_create_report(quoting_enclave_target_info, &report_data) { + Ok(report) => { + debug!( + "rsgx_create_report creation successful. mr_signer: {:?}", + report.body.mr_signer.m + ); + report + }, + Err(e) => { + error!("rsgx_create_report creation failed. {:?}", e); + return Err(e) + }, + }; + + // Retrieve quote from pccs for our app enclave. + debug!("Entering ocall_api.get_dcap_quote with quote size: {:?} ", quote_size); + let quote_vec = self.ocall_api.get_dcap_quote(app_report, quote_size)?; + + // Check mrenclave of quote, to ensure the quote has not been tampered with + // while being on the untrusted side. + // This step is probably obsolete, as the QvE will check the quote as well on behalf + // of the target enclave. + let p_quote3: *const sgx_quote3_t = quote_vec.as_ptr() as *const sgx_quote3_t; + let quote3: sgx_quote3_t = unsafe { *p_quote3 }; + if quote3.report_body.mr_enclave.m != app_report.body.mr_enclave.m { + error!("mr_enclave of quote and app_report are not matching"); + error!("mr_enclave of quote: {:?}", quote3.report_body.mr_enclave.m); + error!("mr_enclave of quote: {:?}", app_report.body.mr_enclave.m); + return Err(sgx_status_t::SGX_ERROR_UNEXPECTED) + } + + Ok(quote_vec) + } +} + +fn decode_spid(hex_encoded_string: &str) -> SgxResult { + let mut spid = sgx_spid_t::default(); + let hex = hex_encoded_string.trim(); + + if hex.len() < itp_settings::files::SPID_MIN_LENGTH { + error!( + "Input spid length ({}) is incorrect, minimum length required is {}", + hex.len(), + itp_settings::files::SPID_MIN_LENGTH + ); + return Err(sgx_status_t::SGX_ERROR_UNEXPECTED) + } + + let decoded_vec = hex::decode(hex).map_err(|_| sgx_status_t::SGX_ERROR_UNEXPECTED)?; + + spid.id.copy_from_slice(&decoded_vec[..16]); + Ok(spid) +} + +#[cfg(feature = "test")] +pub mod tests { + + use super::*; + + pub fn decode_spid_works() { + let spid_encoded = "F39ABCF95015A5BF6C7D360EF5035E12"; + let expected_spid = sgx_spid_t { + id: [243, 154, 188, 249, 80, 21, 165, 191, 108, 125, 54, 14, 245, 3, 94, 18], + }; + + let decoded_spid = decode_spid(spid_encoded).unwrap(); + assert_eq!(decoded_spid.id, expected_spid.id); + } +} diff --git a/bitacross-worker/core-primitives/attestation-handler/src/cert.rs b/bitacross-worker/core-primitives/attestation-handler/src/cert.rs new file mode 100644 index 0000000000..7d1a2d6064 --- /dev/null +++ b/bitacross-worker/core-primitives/attestation-handler/src/cert.rs @@ -0,0 +1,497 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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(all(not(feature = "std"), feature = "sgx"))] +use crate::sgx_reexport_prelude::*; + +use crate::{Error as EnclaveError, Result as EnclaveResult}; +use arrayvec::ArrayVec; +use chrono::DateTime; +use itertools::Itertools; +use itp_ocall_api::EnclaveAttestationOCallApi; +use log::*; +use serde_json::Value; +use sgx_types::{ + sgx_platform_info_t, sgx_quote_t, sgx_status_t, SgxResult, SGX_PLATFORM_INFO_SIZE, +}; +use std::{ + io::BufReader, + ptr, str, + string::String, + time::{SystemTime, UNIX_EPOCH}, + vec::Vec, +}; + +type SignatureAlgorithms = &'static [&'static webpki::SignatureAlgorithm]; +static SUPPORTED_SIG_ALGS: SignatureAlgorithms = &[ + &webpki::ECDSA_P256_SHA256, + &webpki::ECDSA_P256_SHA384, + &webpki::ECDSA_P384_SHA256, + &webpki::ECDSA_P384_SHA384, + &webpki::RSA_PSS_2048_8192_SHA256_LEGACY_KEY, + &webpki::RSA_PSS_2048_8192_SHA384_LEGACY_KEY, + &webpki::RSA_PSS_2048_8192_SHA512_LEGACY_KEY, + &webpki::RSA_PKCS1_2048_8192_SHA256, + &webpki::RSA_PKCS1_2048_8192_SHA384, + &webpki::RSA_PKCS1_2048_8192_SHA512, + &webpki::RSA_PKCS1_3072_8192_SHA384, +]; + +pub const CERTEXPIRYDAYS: i64 = 90i64; +pub const IAS_REPORT_CA: &[u8] = include_bytes!("../AttestationReportSigningCACert.pem"); + +#[cfg(feature = "sgx")] +pub use sgx::*; + +#[cfg(feature = "sgx")] +pub mod sgx { + use super::*; + use bit_vec::BitVec; + use chrono::{Duration, TimeZone, Utc as TzUtc}; + use num_bigint::BigUint; + use sgx_tcrypto::SgxEccHandle; + use sgx_types::{sgx_ec256_private_t, sgx_ec256_public_t}; + use yasna::models::ObjectIdentifier; + + const ISSUER: &str = "Integritee"; + const SUBJECT: &str = "Integritee ephemeral"; + + /// `payload` must be a valid a string, not just arbitrary data. + pub fn gen_ecc_cert( + payload: &str, + prv_k: &sgx_ec256_private_t, + pub_k: &sgx_ec256_public_t, + ecc_handle: &SgxEccHandle, + ) -> Result<(Vec, Vec), sgx_status_t> { + // Generate public key bytes since both DER will use it + let mut pub_key_bytes: Vec = vec![4]; + let mut pk_gx = pub_k.gx; + pk_gx.reverse(); + let mut pk_gy = pub_k.gy; + pk_gy.reverse(); + pub_key_bytes.extend_from_slice(&pk_gx); + pub_key_bytes.extend_from_slice(&pk_gy); + + // Generate Certificate DER + let cert_der = yasna::construct_der(|writer| { + writer.write_sequence(|writer| { + writer.next().write_sequence(|writer| { + // Certificate Version + writer.next().write_tagged(yasna::Tag::context(0), |writer| { + writer.write_i8(2); + }); + // Certificate Serial Number (unused but required) + writer.next().write_u8(1); + // Signature Algorithm: ecdsa-with-SHA256 + writer.next().write_sequence(|writer| { + writer + .next() + .write_oid(&ObjectIdentifier::from_slice(&[1, 2, 840, 10045, 4, 3, 2])); + }); + // Issuer: CN=MesaTEE (unused but required) + writer.next().write_sequence(|writer| { + writer.next().write_set(|writer| { + writer.next().write_sequence(|writer| { + writer + .next() + .write_oid(&ObjectIdentifier::from_slice(&[2, 5, 4, 3])); + writer.next().write_utf8_string(ISSUER); + }); + }); + }); + // Validity: Issuing/Expiring Time (unused but required) + let now = SystemTime::now().duration_since(UNIX_EPOCH).unwrap(); + let issue_ts = TzUtc.timestamp(now.as_secs() as i64, 0); + let expire = now + Duration::days(CERTEXPIRYDAYS).to_std().unwrap(); + let expire_ts = TzUtc.timestamp(expire.as_secs() as i64, 0); + writer.next().write_sequence(|writer| { + writer + .next() + .write_utctime(&yasna::models::UTCTime::from_datetime(&issue_ts)); + writer + .next() + .write_utctime(&yasna::models::UTCTime::from_datetime(&expire_ts)); + }); + // Subject: CN=MesaTEE (unused but required) + writer.next().write_sequence(|writer| { + writer.next().write_set(|writer| { + writer.next().write_sequence(|writer| { + writer + .next() + .write_oid(&ObjectIdentifier::from_slice(&[2, 5, 4, 3])); + writer.next().write_utf8_string(SUBJECT); + }); + }); + }); + writer.next().write_sequence(|writer| { + // Public Key Algorithm + writer.next().write_sequence(|writer| { + // id-ecPublicKey + writer.next().write_oid(&ObjectIdentifier::from_slice(&[ + 1, 2, 840, 10045, 2, 1, + ])); + // prime256v1 + writer.next().write_oid(&ObjectIdentifier::from_slice(&[ + 1, 2, 840, 10045, 3, 1, 7, + ])); + }); + // Public Key + writer.next().write_bitvec(&BitVec::from_bytes(&pub_key_bytes)); + }); + // Certificate V3 Extension + writer.next().write_tagged(yasna::Tag::context(3), |writer| { + writer.write_sequence(|writer| { + writer.next().write_sequence(|writer| { + writer.next().write_oid(&ObjectIdentifier::from_slice(&[ + 2, 16, 840, 1, 113_730, 1, 13, + ])); + writer.next().write_bytes(payload.as_bytes()); + }); + }); + }); + }); + // Signature Algorithm: ecdsa-with-SHA256 + writer.next().write_sequence(|writer| { + writer + .next() + .write_oid(&ObjectIdentifier::from_slice(&[1, 2, 840, 10045, 4, 3, 2])); + }); + // Signature + let sig = { + let tbs = &writer.buf[4..]; + ecc_handle.ecdsa_sign_slice(tbs, prv_k).unwrap() + }; + let sig_der = yasna::construct_der(|writer| { + writer.write_sequence(|writer| { + let mut sig_x = sig.x; + sig_x.reverse(); + let mut sig_y = sig.y; + sig_y.reverse(); + writer.next().write_biguint(&BigUint::from_slice(&sig_x)); + writer.next().write_biguint(&BigUint::from_slice(&sig_y)); + }); + }); + writer.next().write_bitvec(&BitVec::from_bytes(&sig_der)); + }); + }); + + // Generate Private Key DER + let key_der = yasna::construct_der(|writer| { + writer.write_sequence(|writer| { + writer.next().write_u8(0); + writer.next().write_sequence(|writer| { + writer + .next() + .write_oid(&ObjectIdentifier::from_slice(&[1, 2, 840, 10045, 2, 1])); + writer + .next() + .write_oid(&ObjectIdentifier::from_slice(&[1, 2, 840, 10045, 3, 1, 7])); + }); + let inner_key_der = yasna::construct_der(|writer| { + writer.write_sequence(|writer| { + writer.next().write_u8(1); + let mut prv_k_r = prv_k.r; + prv_k_r.reverse(); + writer.next().write_bytes(&prv_k_r); + writer.next().write_tagged(yasna::Tag::context(1), |writer| { + writer.write_bitvec(&BitVec::from_bytes(&pub_key_bytes)); + }); + }); + }); + writer.next().write_bytes(&inner_key_der); + }); + }); + + Ok((key_der, cert_der)) + } +} + +pub fn percent_decode(orig: String) -> EnclaveResult { + let v: Vec<&str> = orig.split('%').collect(); + let mut ret = String::new(); + ret.push_str(v[0]); + if v.len() > 1 { + for s in v[1..].iter() { + ret.push(u8::from_str_radix(&s[0..2], 16).map_err(|e| EnclaveError::Other(e.into()))? + as char); + ret.push_str(&s[2..]); + } + } + Ok(ret) +} + +pub fn parse_cert_issuer(cert_der: &[u8]) -> SgxResult> { + // Before we reach here, Webpki already verified the cert is properly signed + + // Search for Public Key prime256v1 OID + let prime256v1_oid = &[0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07]; + let mut offset = cert_der + .windows(prime256v1_oid.len()) + .position(|window| window == prime256v1_oid) + .ok_or(sgx_status_t::SGX_ERROR_UNEXPECTED)?; + offset += 11; // 10 + TAG (0x03) + + // Obtain Public Key length + let mut len = cert_der[offset] as usize; + if len > 0x80 { + len = (cert_der[offset + 1] as usize) * 0x100 + (cert_der[offset + 2] as usize); + offset += 2; + } + + // Obtain Public Key + offset += 1; + let pub_k = cert_der[offset + 2..offset + len].to_vec(); // skip "00 04" + + Ok(pub_k) +} + +// FIXME: This code is redundant with the host call of the integritee-node +pub fn verify_mra_cert( + cert_der: &[u8], + is_payload_base64_encoded: bool, + is_dcap: bool, + attestation_ocall: &A, +) -> SgxResult<()> +where + A: EnclaveAttestationOCallApi, +{ + // Before we reach here, Webpki already verified the cert is properly signed + + // Search for Public Key prime256v1 OID + let prime256v1_oid = &[0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07]; + let mut offset = cert_der + .windows(prime256v1_oid.len()) + .position(|window| window == prime256v1_oid) + .ok_or(sgx_status_t::SGX_ERROR_UNEXPECTED)?; + offset += 11; // 10 + TAG (0x03) + + // Obtain Public Key length + let mut len = cert_der[offset] as usize; + if len > 0x80 { + len = (cert_der[offset + 1] as usize) * 0x100 + (cert_der[offset + 2] as usize); + offset += 2; + } + + // Obtain Public Key + offset += 1; + let pub_k = cert_der[offset + 2..offset + len].to_vec(); // skip "00 04" + + // Search for Netscape Comment OID + let ns_cmt_oid = &[0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x86, 0xF8, 0x42, 0x01, 0x0D]; + let mut offset = cert_der + .windows(ns_cmt_oid.len()) + .position(|window| window == ns_cmt_oid) + .ok_or(sgx_status_t::SGX_ERROR_UNEXPECTED)?; + offset += 12; // 11 + TAG (0x04) + + // Obtain Netscape Comment length + let mut len = cert_der[offset] as usize; + if len > 0x80 { + len = (cert_der[offset + 1] as usize) * 0x100 + (cert_der[offset + 2] as usize); + offset += 2; + } + + // Obtain Netscape Comment + offset += 1; + let mut payload = cert_der[offset..offset + len].to_vec(); + trace!("payload in mra cert verifier is: {:?}", &payload); + if is_payload_base64_encoded { + payload = base64::decode(&payload[..]).or(Err(sgx_status_t::SGX_ERROR_UNEXPECTED))?; + } + trace!("payload in mra cert verifier is: {:?}", &payload); + if !is_dcap { + // Extract each field + let mut iter = payload.split(|x| *x == b'|'); + let attn_report_raw = iter.next().ok_or(sgx_status_t::SGX_ERROR_UNEXPECTED)?; + let sig_raw = iter.next().ok_or(sgx_status_t::SGX_ERROR_UNEXPECTED)?; + let sig = base64::decode(sig_raw).map_err(|e| EnclaveError::Other(e.into()))?; + + let sig_cert_raw = iter.next().ok_or(sgx_status_t::SGX_ERROR_UNEXPECTED)?; + let sig_cert_dec = base64::decode_config(sig_cert_raw, base64::STANDARD) + .map_err(|e| EnclaveError::Other(e.into()))?; + let sig_cert = webpki::EndEntityCert::from(&sig_cert_dec).expect("Bad DER"); + + // Verify if the signing cert is issued by Intel CA + let mut ias_ca_stripped = IAS_REPORT_CA.to_vec(); + ias_ca_stripped.retain(|&x| x != b'\r' && x != b'\n'); + let head_len = "-----BEGIN CERTIFICATE-----".len(); + let tail_len = "-----END CERTIFICATE-----".len(); + let full_len = ias_ca_stripped.len(); + let ias_ca_core: &[u8] = &ias_ca_stripped[head_len..full_len - tail_len]; + let ias_cert_dec = base64::decode_config(ias_ca_core, base64::STANDARD) + .map_err(|e| EnclaveError::Other(e.into()))?; + + let mut ca_reader = BufReader::new(IAS_REPORT_CA); + + let mut root_store = rustls::RootCertStore::empty(); + root_store.add_pem_file(&mut ca_reader).expect("Failed to add CA"); + + let trust_anchors: Vec = + root_store.roots.iter().map(|cert| cert.to_trust_anchor()).collect(); + + let now_func = webpki::Time::try_from(SystemTime::now()); + + match sig_cert.verify_is_valid_tls_server_cert( + SUPPORTED_SIG_ALGS, + &webpki::TLSServerTrustAnchors(&trust_anchors), + &[ias_cert_dec.as_slice()], + now_func.map_err(|_e| EnclaveError::Time)?, + ) { + Ok(_) => info!("Cert is good"), + Err(e) => { + error!("Cert verification error {:?}", e); + return Err(sgx_status_t::SGX_ERROR_UNEXPECTED) + }, + } + + // Verify the signature against the signing cert + match sig_cert.verify_signature(&webpki::RSA_PKCS1_2048_8192_SHA256, attn_report_raw, &sig) + { + Ok(_) => info!("Signature good"), + Err(e) => { + error!("Signature verification error {:?}", e); + return Err(sgx_status_t::SGX_ERROR_UNEXPECTED) + }, + } + + verify_attn_report(attn_report_raw, pub_k, attestation_ocall) + } else { + // TODO Refactor state provisioning to not use MURA #1385 + // TODO DCAP is currently just passed through! SECURITY!!! + Ok(()) + } +} + +pub fn verify_attn_report( + report_raw: &[u8], + pub_k: Vec, + attestation_ocall: &A, +) -> SgxResult<()> +where + A: EnclaveAttestationOCallApi, +{ + // Verify attestation report + // 1. Check timestamp is within 24H (90day is recommended by Intel) + let attn_report: Value = + serde_json::from_slice(report_raw).map_err(|e| EnclaveError::Other(e.into()))?; + if let Value::String(time) = &attn_report["timestamp"] { + let time_fixed = time.clone() + "+0000"; + let ts = DateTime::parse_from_str(&time_fixed, "%Y-%m-%dT%H:%M:%S%.f%z") + .map_err(|e| EnclaveError::Other(e.into()))? + .timestamp(); + let now = SystemTime::now() + .duration_since(UNIX_EPOCH) + .map_err(|e| EnclaveError::Other(e.into()))? + .as_secs() as i64; + info!("Time diff = {}", now - ts); + } else { + error!("Failed to fetch timestamp from attestation report"); + return Err(sgx_status_t::SGX_ERROR_UNEXPECTED) + } + + // 2. Verify quote status (mandatory field) + if let Value::String(quote_status) = &attn_report["isvEnclaveQuoteStatus"] { + debug!("isvEnclaveQuoteStatus = {}", quote_status); + match quote_status.as_ref() { + "OK" => (), + "SW_HARDENING_NEEDED" => info!("Status in attestation report is SW_HARDENING_NEEDED, which is considered acceptable."), + "GROUP_OUT_OF_DATE" | "GROUP_REVOKED" | "CONFIGURATION_NEEDED" => { + // Verify platformInfoBlob for further info if status not OK + if let Value::String(pib) = &attn_report["platformInfoBlob"] { + let mut buf = ArrayVec::<_, SGX_PLATFORM_INFO_SIZE>::new(); + + // the TLV Header (4 bytes/8 hexes) should be skipped + let n = (pib.len() - 8) / 2; + for i in 0..n { + buf.try_push( + u8::from_str_radix(&pib[(i * 2 + 8)..(i * 2 + 10)], 16) + .map_err(|e| EnclaveError::Other(e.into()))?, + ) + .map_err(|e| { + error!("failed to push element to platform info blob buffer, exceeding buffer size ({})", e); + sgx_status_t::SGX_ERROR_UNEXPECTED + })?; + } + + // ArrayVec .into_inner() requires that all elements are occupied by a value + // if that's not the case, the following error will occur + let platform_info = buf.into_inner().map_err(|e| { + error!("Failed to extract platform info from InfoBlob, result does not contain enough elements (require: {}, found: {})", e.capacity(), e.len()); + sgx_status_t::SGX_ERROR_UNEXPECTED + })?; + + attestation_ocall.get_update_info(sgx_platform_info_t { platform_info }, 1)?; + } else { + error!("Failed to fetch platformInfoBlob from attestation report"); + return Err(sgx_status_t::SGX_ERROR_UNEXPECTED) + } + }, + status => { + error!("Unexpected status in attestation report: {}", status); + return Err(sgx_status_t::SGX_ERROR_UNEXPECTED) + }, + } + } else { + error!("Failed to fetch isvEnclaveQuoteStatus from attestation report"); + return Err(sgx_status_t::SGX_ERROR_UNEXPECTED) + } + + // 3. Verify quote body + if let Value::String(quote_raw) = &attn_report["isvEnclaveQuoteBody"] { + let quote = base64::decode(quote_raw).map_err(|e| EnclaveError::Other(e.into()))?; + debug!("Quote = {:?}", quote); + // TODO: lack security check here + let sgx_quote: sgx_quote_t = unsafe { ptr::read(quote.as_ptr() as *const _) }; + + let ti = attestation_ocall.get_mrenclave_of_self()?; + if sgx_quote.report_body.mr_enclave.m != ti.m { + error!( + "mr_enclave is not equal to self {:?} != {:?}", + sgx_quote.report_body.mr_enclave.m, ti.m + ); + return Err(sgx_status_t::SGX_ERROR_UNEXPECTED) + } + + // ATTENTION + // DO SECURITY CHECK ON DEMAND + // DO SECURITY CHECK ON DEMAND + // DO SECURITY CHECK ON DEMAND + + // Curly braces to copy `unaligned_references` of packed fields into properly aligned temporary: + // https://github.com/rust-lang/rust/issues/82523 + debug!("sgx quote version = {}", { sgx_quote.version }); + debug!("sgx quote signature type = {}", { sgx_quote.sign_type }); + debug!( + "sgx quote report_data = {:02x}", + sgx_quote.report_body.report_data.d.iter().format("") + ); + debug!( + "sgx quote mr_enclave = {:02x}", + sgx_quote.report_body.mr_enclave.m.iter().format("") + ); + debug!("sgx quote mr_signer = {:02x}", sgx_quote.report_body.mr_signer.m.iter().format("")); + debug!("Anticipated public key = {:02x}", pub_k.iter().format("")); + if sgx_quote.report_body.report_data.d.to_vec() == pub_k.to_vec() { + info!("Mutual RA done!"); + } + } else { + error!("Failed to fetch isvEnclaveQuoteBody from attestation report"); + return Err(sgx_status_t::SGX_ERROR_UNEXPECTED) + } + + Ok(()) +} diff --git a/bitacross-worker/core-primitives/attestation-handler/src/collateral.rs b/bitacross-worker/core-primitives/attestation-handler/src/collateral.rs new file mode 100644 index 0000000000..a4713c5c94 --- /dev/null +++ b/bitacross-worker/core-primitives/attestation-handler/src/collateral.rs @@ -0,0 +1,158 @@ +/* + Copyright 2022 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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(all(not(feature = "std"), feature = "sgx"))] +use crate::sgx_reexport_prelude::serde_json; +use sgx_types::sgx_ql_qve_collateral_t; +use std::{io::Write, string::String, vec::Vec}; + +/// This is a rust-ified version of the type sgx_ql_qve_collateral_t. +/// See Appendix A.3 in the document +/// "Intel® Software Guard Extensions (Intel® SGX) Data Center Attestation Primitives: ECDSA Quote Library API" +/// https://download.01.org/intel-sgx/latest/dcap-latest/linux/docs/Intel_SGX_ECDSA_QuoteLibReference_DCAP_API.pdf +pub struct SgxQlQveCollateral { + pub version: u32, // version = 1. PCK Cert chain is in the Quote. + /* intel DCAP 1.13 */ + pub tee_type: u32, // 0x00000000: SGX or 0x00000081: TDX + pub pck_crl_issuer_chain: Vec, + pub root_ca_crl: Vec, + pub pck_crl: Vec, + pub tcb_info_issuer_chain: Vec, + pub tcb_info: Vec, + pub qe_identity_issuer_chain: Vec, + pub qe_identity: Vec, +} + +impl SgxQlQveCollateral { + /// # Safety + /// + /// The caller is in charge of ensuring that `c` is properly initialized and all + /// its members have a value that is not nullptr + pub unsafe fn from_c_type(c: &sgx_ql_qve_collateral_t) -> Self { + let pck_crl_issuer_chain = std::slice::from_raw_parts( + c.pck_crl_issuer_chain as *const u8, + c.pck_crl_issuer_chain_size as usize, + ) + .to_vec(); + let root_ca_crl = + std::slice::from_raw_parts(c.root_ca_crl as *const u8, c.root_ca_crl_size as usize) + .to_vec(); + let pck_crl = + std::slice::from_raw_parts(c.pck_crl as *const u8, c.pck_crl_size as usize).to_vec(); + let tcb_info_issuer_chain = std::slice::from_raw_parts( + c.tcb_info_issuer_chain as *const u8, + c.tcb_info_issuer_chain_size as usize, + ) + .to_vec(); + let tcb_info = + std::slice::from_raw_parts(c.tcb_info as *const u8, c.tcb_info_size as usize).to_vec(); + let qe_identity_issuer_chain = std::slice::from_raw_parts( + c.qe_identity_issuer_chain as *const u8, + c.qe_identity_issuer_chain_size as usize, + ) + .to_vec(); + let qe_identity = + std::slice::from_raw_parts(c.qe_identity as *const u8, c.qe_identity_size as usize) + .to_vec(); + SgxQlQveCollateral { + version: c.version, + tee_type: c.tee_type, + pck_crl_issuer_chain, + root_ca_crl, + pck_crl, + tcb_info_issuer_chain, + tcb_info, + qe_identity_issuer_chain, + qe_identity, + } + } + + pub fn dump_to_disk(&self) { + Self::write_data_to_disk("pck_crl_issuer_chain", &self.pck_crl_issuer_chain); + Self::write_data_to_disk("root_ca_crl", &self.root_ca_crl); + Self::write_data_to_disk("pck_crl", &self.pck_crl); + Self::write_data_to_disk("tcb_info_issuer_chain", &self.tcb_info_issuer_chain); + Self::write_data_to_disk("tcb_info", &self.tcb_info); + Self::write_data_to_disk("qe_identity_issuer_chain", &self.qe_identity_issuer_chain); + Self::write_data_to_disk("qe_identity", &self.qe_identity); + } + + /// Returns the tcb_info split into two parts: json_data and signature + pub fn get_tcb_info_split(&self) -> Option<(String, Vec)> { + let (json_data, signature) = + Self::separate_json_data_and_signature("tcbInfo", &self.tcb_info)?; + match hex::decode(signature) { + Ok(hex_signature) => Some((json_data, hex_signature)), + Err(_) => None, + } + } + + /// Returns the tcb_info split into two parts: json_data and signature + pub fn get_quoting_enclave_split(&self) -> Option<(String, Vec)> { + let (json_data, signature) = + Self::separate_json_data_and_signature("enclaveIdentity", &self.qe_identity)?; + match hex::decode(signature) { + Ok(hex_signature) => Some((json_data, hex_signature)), + Err(_) => None, + } + } + + /// Separates the actual data part from the signature for an Intel collateral in JSON format + /// Returns the data part and signature as a pair + fn separate_json_data_and_signature(data_name: &str, data: &[u8]) -> Option<(String, String)> { + let json = String::from_utf8_lossy(data); + // Remove potential C-style null terminators + let json = json.trim_matches(char::from(0)); + let value: serde_json::Value = serde_json::from_str(json).ok()?; + if value[data_name].is_null() || value["signature"].is_null() { + return None + } + let data_json = serde_json::to_string(&value[data_name]).ok()?; + let signature = serde_json::to_string(&value["signature"]).ok()?; + // We want the signature without leading/ending " + let signature = signature.replace('\"', ""); + Some((data_json, signature)) + } + + fn write_data_to_disk(filename: &str, contents: &[u8]) { + let mut file = std::fs::File::create(filename).unwrap(); + file.write_all(contents).unwrap(); + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn separate_json_data_and_signature() { + // A bit more complex json to ensure the ordering stays the same + let json = br#"{"tcbInfo":{"id":"SGX","version":3,"issueDate":"2022-11-17T12:45:32Z"},"signature":"71746f2"}"#; + let (data, signature) = + SgxQlQveCollateral::separate_json_data_and_signature("tcbInfo", json).unwrap(); + assert_eq!(data, r#"{"id":"SGX","version":3,"issueDate":"2022-11-17T12:45:32Z"}"#); + assert_eq!(signature, "71746f2"); + + let json = br#"{"tcbInfo":{not_a_valid_json},"nosignature":"thesignature"}"#; + assert!(SgxQlQveCollateral::separate_json_data_and_signature("tcbInfo", json).is_none()); + + let json = br#"{"tcbInfo":{"id":"SGX"},"nosignature":"thesignature"}"#; + assert!(SgxQlQveCollateral::separate_json_data_and_signature("tcbInfo", json).is_none()); + + let json = br#"{"tcbInfo":{"id":"SGX"},"signature":""#; + assert!(SgxQlQveCollateral::separate_json_data_and_signature("tcbInfo", json).is_none()); + } +} diff --git a/bitacross-worker/core-primitives/attestation-handler/src/error.rs b/bitacross-worker/core-primitives/attestation-handler/src/error.rs new file mode 100644 index 0000000000..e681ce8c2a --- /dev/null +++ b/bitacross-worker/core-primitives/attestation-handler/src/error.rs @@ -0,0 +1,64 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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(all(not(feature = "std"), feature = "sgx"))] +use crate::sgx_reexport_prelude::*; + +use sgx_types::sgx_status_t; +use std::boxed::Box; + +pub type Result = core::result::Result; + +/// Parentchain block importer error. +#[derive(Debug, thiserror::Error)] +pub enum Error { + #[error("SGX error, status: {0}")] + Sgx(sgx_status_t), + #[error("{0}")] + IoError(#[from] std::io::Error), + #[error("Crypto error: {0}")] + Crypto(itp_sgx_crypto::Error), + #[error("Error specifying time")] + Time, + #[error(transparent)] + Other(#[from] Box), +} + +impl From for Error { + fn from(sgx_status: sgx_status_t) -> Self { + Self::Sgx(sgx_status) + } +} + +impl From for Error { + fn from(error: itp_sgx_crypto::error::Error) -> Self { + Self::Crypto(error) + } +} + +impl From for sgx_status_t { + /// return sgx_status for top level enclave functions + fn from(error: Error) -> sgx_status_t { + match error { + Error::Sgx(status) => status, + _ => { + log::error!("Returning error {:?} as sgx unexpected.", error); + sgx_status_t::SGX_ERROR_UNEXPECTED + }, + } + } +} diff --git a/bitacross-worker/core-primitives/attestation-handler/src/lib.rs b/bitacross-worker/core-primitives/attestation-handler/src/lib.rs new file mode 100644 index 0000000000..c6763b3d9a --- /dev/null +++ b/bitacross-worker/core-primitives/attestation-handler/src/lib.rs @@ -0,0 +1,58 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg(all(feature = "std", feature = "sgx"))] +compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the same time"); + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +#[macro_use] +extern crate sgx_tstd as std; + +// re-export module to properly feature gate sgx and regular std environment +#[cfg(all(not(feature = "std"), feature = "sgx"))] +pub mod sgx_reexport_prelude { + pub use base64_sgx as base64; + pub use chrono_sgx as chrono; + pub use rustls_sgx as rustls; + pub use serde_json_sgx as serde_json; + pub use thiserror_sgx as thiserror; + pub use webpki_sgx as webpki; + pub use yasna_sgx as yasna; +} + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +pub mod attestation_handler; + +pub mod collateral; + +pub mod cert; + +pub mod error; + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +pub use attestation_handler::{AttestationHandler, IntelAttestationHandler, DEV_HOSTNAME}; +pub use collateral::SgxQlQveCollateral; + +pub use error::{Error, Result}; + +#[derive(Clone, Eq, PartialEq, Debug)] +pub enum RemoteAttestationType { + Epid, + Dcap, +} diff --git a/bitacross-worker/core-primitives/component-container/Cargo.toml b/bitacross-worker/core-primitives/component-container/Cargo.toml new file mode 100644 index 0000000000..cb5d3b5541 --- /dev/null +++ b/bitacross-worker/core-primitives/component-container/Cargo.toml @@ -0,0 +1,26 @@ +[package] +name = "itp-component-container" +version = "0.8.0" +authors = ['Trust Computing GmbH ', 'Integritee AG '] +edition = "2021" + +[dependencies] +# sgx dependencies +sgx_tstd = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git", optional = true } + +# sgx enabled external libraries +thiserror_sgx = { package = "thiserror", git = "https://github.com/mesalock-linux/thiserror-sgx", tag = "sgx_1.1.3", optional = true } + +# std compatible external libraries (make sure these versions match with the sgx-enabled ones above) +thiserror = { version = "1.0", optional = true } + +[features] +default = ["std"] +std = [ + "thiserror", +] +sgx = [ + # sgx + "sgx_tstd", + "thiserror_sgx", +] diff --git a/bitacross-worker/core-primitives/component-container/src/atomic_container.rs b/bitacross-worker/core-primitives/component-container/src/atomic_container.rs new file mode 100644 index 0000000000..3f52ab291a --- /dev/null +++ b/bitacross-worker/core-primitives/component-container/src/atomic_container.rs @@ -0,0 +1,100 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +//! Container for a generic item, held by an AtomicPtr. + +#[cfg(feature = "sgx")] +use std::sync::SgxMutex as Mutex; + +#[cfg(feature = "std")] +use std::sync::Mutex; + +use std::{ + default::Default, + sync::{ + atomic::{AtomicPtr, Ordering}, + Arc, + }, +}; + +/// Generic atomic container that holds an item in a container. +pub struct AtomicContainer { + atomic_ptr: AtomicPtr<()>, +} + +impl AtomicContainer { + pub const fn new() -> Self { + AtomicContainer { atomic_ptr: AtomicPtr::new(0 as *mut ()) } + } + + /// Store and item in the container. + pub fn store(&self, item: T) { + let pool_ptr = Arc::new(Mutex::::new(item)); + let ptr = Arc::into_raw(pool_ptr); + self.atomic_ptr.store(ptr as *mut (), Ordering::SeqCst); + } + + /// Load an item from the container, returning a mutex. + pub fn load(&self) -> Option<&Mutex> { + let ptr = self.atomic_ptr.load(Ordering::SeqCst) as *mut Mutex; + if ptr.is_null() { + None + } else { + Some(unsafe { &*ptr }) + } + } +} + +impl Default for AtomicContainer { + fn default() -> Self { + Self::new() + } +} + +#[cfg(test)] +pub mod tests { + + use super::*; + use std::{ + ops::Deref, + string::{String, ToString}, + vec::Vec, + }; + + #[derive(PartialEq, Eq, Clone, Debug)] + struct TestPayload { + name: String, + data: Vec, + } + + #[test] + pub fn store_and_load_works() { + let atomic_container = AtomicContainer::new(); + + let test_payload = TestPayload { + name: "Payload".to_string(), + data: Vec::from("lots_of_data_to_be_stored".as_bytes()), + }; + + atomic_container.store(test_payload.clone()); + + let retrieved_mutex = atomic_container.load::().unwrap().lock().unwrap(); + let retrieved_payload = retrieved_mutex.deref(); + + assert_eq!(&test_payload, retrieved_payload); + } +} diff --git a/bitacross-worker/core-primitives/component-container/src/component_container.rs b/bitacross-worker/core-primitives/component-container/src/component_container.rs new file mode 100644 index 0000000000..ec0a16d50e --- /dev/null +++ b/bitacross-worker/core-primitives/component-container/src/component_container.rs @@ -0,0 +1,100 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 component containers. + +#[cfg(feature = "sgx")] +use std::sync::SgxMutex as Mutex; + +#[cfg(feature = "std")] +use std::sync::Mutex; + +use crate::{ + atomic_container::AtomicContainer, + error::{Error, Result}, +}; +use std::{ + format, + marker::PhantomData, + string::{String, ToString}, + sync::Arc, +}; + +/// Trait to initialize a generic component. +pub trait ComponentInitializer { + type ComponentType; + + fn initialize(&self, component: Arc); +} + +/// Trait to retrieve a generic component. +pub trait ComponentGetter { + type ComponentType; + + /// Try to get a specific component, returns `None` if component has not been initialized. + fn get(&self) -> Result>; +} + +/// Workaround to make `new()` a `const fn`. +/// Is required in order to have the `ComponentContainer` in a static variable. +struct Invariant(T); + +/// Component container implementation. Can be used in a global static context. +pub struct ComponentContainer { + container: AtomicContainer, + component_name: &'static str, + _phantom: PhantomData>, +} + +impl ComponentContainer { + /// Create a new container instance. + /// + /// Has to be `const` in order to be used in a `static` context. + pub const fn new(component_name: &'static str) -> Self { + ComponentContainer { + container: AtomicContainer::new(), + component_name, + _phantom: PhantomData, + } + } +} + +impl ComponentInitializer for ComponentContainer { + type ComponentType = Component; + + fn initialize(&self, component: Arc) { + self.container.store(component) + } +} + +impl ToString for ComponentContainer { + fn to_string(&self) -> String { + format!("{} component", self.component_name) + } +} + +impl ComponentGetter for ComponentContainer { + type ComponentType = Component; + + fn get(&self) -> Result> { + let component_mutex: &Mutex> = self + .container + .load() + .ok_or_else(|| Error::ComponentNotInitialized(self.to_string()))?; + Ok(component_mutex.lock().expect("Lock poisoning").clone()) + } +} diff --git a/bitacross-worker/core-primitives/component-container/src/error.rs b/bitacross-worker/core-primitives/component-container/src/error.rs new file mode 100644 index 0000000000..9ca0ac0b20 --- /dev/null +++ b/bitacross-worker/core-primitives/component-container/src/error.rs @@ -0,0 +1,32 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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(all(not(feature = "std"), feature = "sgx"))] +use crate::sgx_reexport_prelude::*; + +use std::{boxed::Box, string::String}; + +pub type Result = core::result::Result; + +/// extrinsics factory error +#[derive(Debug, thiserror::Error)] +pub enum Error { + #[error("Component is not initialized: {0}")] + ComponentNotInitialized(String), + #[error(transparent)] + Other(#[from] Box), +} diff --git a/bitacross-worker/core-primitives/component-container/src/lib.rs b/bitacross-worker/core-primitives/component-container/src/lib.rs new file mode 100644 index 0000000000..9c684e4361 --- /dev/null +++ b/bitacross-worker/core-primitives/component-container/src/lib.rs @@ -0,0 +1,36 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg(all(feature = "std", feature = "sgx"))] +compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the same time"); + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +extern crate sgx_tstd as std; + +// re-export module to properly feature gate sgx and regular std environment +#[cfg(all(not(feature = "std"), feature = "sgx"))] +pub mod sgx_reexport_prelude { + pub use thiserror_sgx as thiserror; +} + +mod atomic_container; +pub mod component_container; +pub mod error; + +pub use component_container::*; diff --git a/bitacross-worker/core-primitives/enclave-api/Cargo.toml b/bitacross-worker/core-primitives/enclave-api/Cargo.toml new file mode 100644 index 0000000000..c9dfaa9dff --- /dev/null +++ b/bitacross-worker/core-primitives/enclave-api/Cargo.toml @@ -0,0 +1,36 @@ +[package] +name = "itp-enclave-api" +version = "0.9.0" +authors = ['Trust Computing GmbH ', 'Integritee AG '] +edition = "2021" + +[dependencies] +codec = { package = "parity-scale-codec", version = "3.0.0", features = ["derive"] } +hex = "0.4" +log = "0.4" +serde_json = "1.0" +thiserror = "1.0.25" + +sgx_crypto_helper = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git" } +sgx_types = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git" } +sgx_urts = { optional = true, branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git" } + +frame-support = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } +sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } +sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } + +itc-parentchain = { path = "../../core/parentchain/parentchain-crate" } +itp-enclave-api-ffi = { path = "ffi" } +itp-settings = { path = "../settings" } +itp-storage = { path = "../storage" } +itp-types = { path = "../types" } + +# litentry +teerex-primitives = { path = "../../../primitives/teerex", default-features = false } + +[features] +default = [] +implement-ffi = [ + "sgx_urts", + "itp-enclave-api-ffi/link-sgx-libs", +] diff --git a/bitacross-worker/core-primitives/enclave-api/build.rs b/bitacross-worker/core-primitives/enclave-api/build.rs new file mode 100644 index 0000000000..1c20ea4c84 --- /dev/null +++ b/bitacross-worker/core-primitives/enclave-api/build.rs @@ -0,0 +1,24 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +fn main() { + // If the linker failed to find libsgx_dcap_ql.so, please make sure that + // (1) libsgx-dcap-ql is installed + // (2) libsgx_dcap_ql.so exists. typicall at /usr/lib/x86_64-linux-gnu + // if libsgx_dcap_ql.so.1 is there, but no libsgx-dcap_ql, + // just create a symlink by + // ln -s libsgx_dcap_ql.so.1 libsgx_dcap_ql.so + println!("cargo:rustc-link-lib=dylib=sgx_dcap_ql"); + println!("cargo:rustc-link-lib=dylib=sgx_dcap_quoteverify"); + println!("cargo:rustc-link-lib=dylib=dcap_quoteprov"); +} diff --git a/bitacross-worker/core-primitives/enclave-api/ffi/Cargo.toml b/bitacross-worker/core-primitives/enclave-api/ffi/Cargo.toml new file mode 100644 index 0000000000..4ce7be0e66 --- /dev/null +++ b/bitacross-worker/core-primitives/enclave-api/ffi/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "itp-enclave-api-ffi" +version = "0.9.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +sgx_types = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git" } + +[features] +# necessary to run cargo tests without any preliminaries +# See: https://github.com/rust-lang/cargo/issues/2549 +link-sgx-libs = [] diff --git a/bitacross-worker/core-primitives/enclave-api/ffi/build.rs b/bitacross-worker/core-primitives/enclave-api/ffi/build.rs new file mode 100644 index 0000000000..766abb3eb4 --- /dev/null +++ b/bitacross-worker/core-primitives/enclave-api/ffi/build.rs @@ -0,0 +1,44 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +fn main() { + if cfg!(feature = "link-sgx-libs") { + use std::env; + + let sdk_dir = env::var("SGX_SDK").unwrap_or_else(|_| "/opt/intel/sgxsdk".to_string()); + let is_sim = env::var("SGX_MODE").unwrap_or_else(|_| "HW".to_string()); + + // NOTE: if the crate is a workspace member rustc-paths are relative from the root directory + println!("cargo:rustc-link-search=native=./lib"); + println!("cargo:rustc-link-lib=static=Enclave_u"); + + println!("cargo:rustc-link-search=native={}/lib64", sdk_dir); + println!("cargo:rustc-link-lib=static=sgx_uprotected_fs"); + match is_sim.as_ref() { + "SW" => { + println!("cargo:rustc-link-lib=dylib=sgx_urts_sim"); + println!("cargo:rustc-link-lib=dylib=sgx_uae_service_sim"); + }, + _ => { + // HW by default + println!("cargo:rustc-link-lib=dylib=sgx_urts"); + println!("cargo:rustc-link-lib=dylib=sgx_uae_service"); + }, + } + } +} diff --git a/bitacross-worker/core-primitives/enclave-api/ffi/src/lib.rs b/bitacross-worker/core-primitives/enclave-api/ffi/src/lib.rs new file mode 100644 index 0000000000..2dbb8fb016 --- /dev/null +++ b/bitacross-worker/core-primitives/enclave-api/ffi/src/lib.rs @@ -0,0 +1,279 @@ +///! FFI's that call into the enclave. These functions need to be added to the +/// enclave edl file and be implemented within the enclave. +use sgx_types::{ + c_int, sgx_enclave_id_t, sgx_ql_qve_collateral_t, sgx_quote_sign_type_t, sgx_status_t, + sgx_target_info_t, +}; + +extern "C" { + + pub fn generate_dcap_ra_extrinsic_from_quote( + eid: sgx_enclave_id_t, + retval: *mut sgx_status_t, + w_url: *const u8, + w_url_size: u32, + quote: *const u8, + quote_size: u32, + unchecked_extrinsic: *mut u8, + unchecked_extrinsic_max_size: u32, + unchecked_extrinsic_size: *mut u32, + ) -> sgx_status_t; + + pub fn init( + eid: sgx_enclave_id_t, + retval: *mut sgx_status_t, + mu_ra_addr: *const u8, + mu_ra_addr_size: u32, + untrusted_worker_addr: *const u8, + untrusted_worker_addr_size: u32, + encoded_base_dir_str: *const u8, + encoded_base_dir_size: u32, + ) -> sgx_status_t; + + pub fn init_enclave_sidechain_components( + eid: sgx_enclave_id_t, + retval: *mut sgx_status_t, + fail_mode: *const u8, + fail_mode_size: u32, + fail_at: *const u8, + fail_at_size: u32, + ) -> sgx_status_t; + + pub fn init_direct_invocation_server( + eid: sgx_enclave_id_t, + retval: *mut sgx_status_t, + server_addr: *const u8, + server_addr_size: u32, + ) -> sgx_status_t; + + pub fn init_parentchain_components( + eid: sgx_enclave_id_t, + retval: *mut sgx_status_t, + params: *const u8, + params_size: usize, + latest_header: *mut u8, + latest_header_size: usize, + ) -> sgx_status_t; + + pub fn init_shard( + eid: sgx_enclave_id_t, + retval: *mut sgx_status_t, + shard: *const u8, + shard_size: u32, + ) -> sgx_status_t; + + pub fn init_proxied_shard_vault( + eid: sgx_enclave_id_t, + retval: *mut sgx_status_t, + shard: *const u8, + shard_size: u32, + parentchain_id: *const u8, + parentchain_id_size: u32, + ) -> sgx_status_t; + + pub fn execute_trusted_calls(eid: sgx_enclave_id_t, retval: *mut sgx_status_t) -> sgx_status_t; + + pub fn sync_parentchain( + eid: sgx_enclave_id_t, + retval: *mut sgx_status_t, + blocks: *const u8, + blocks_size: usize, + events: *const u8, + events_size: usize, + events_proofs: *const u8, + events_proofs_size: usize, + parentchain_id: *const u8, + parentchain_id_size: u32, + is_syncing: c_int, + ) -> sgx_status_t; + + pub fn set_nonce( + eid: sgx_enclave_id_t, + retval: *mut sgx_status_t, + nonce: *const u32, + parentchain_id: *const u8, + parentchain_id_size: u32, + ) -> sgx_status_t; + + pub fn set_node_metadata( + eid: sgx_enclave_id_t, + retval: *mut sgx_status_t, + node_metadata: *const u8, + node_metadata_size: u32, + parentchain_id: *const u8, + parentchain_id_size: u32, + ) -> sgx_status_t; + + pub fn get_rsa_encryption_pubkey( + eid: sgx_enclave_id_t, + retval: *mut sgx_status_t, + pubkey: *mut u8, + pubkey_size: u32, + ) -> sgx_status_t; + + pub fn get_ecc_signing_pubkey( + eid: sgx_enclave_id_t, + retval: *mut sgx_status_t, + pubkey: *mut u8, + pubkey_size: u32, + ) -> sgx_status_t; + + pub fn get_ecc_vault_pubkey( + eid: sgx_enclave_id_t, + retval: *mut sgx_status_t, + shard: *const u8, + shard_size: u32, + pubkey: *mut u8, + pubkey_size: u32, + ) -> sgx_status_t; + + pub fn get_mrenclave( + eid: sgx_enclave_id_t, + retval: *mut sgx_status_t, + mrenclave: *mut u8, + mrenclave_size: u32, + ) -> sgx_status_t; + + pub fn generate_ias_ra_extrinsic( + eid: sgx_enclave_id_t, + retval: *mut sgx_status_t, + w_url: *const u8, + w_url_size: u32, + unchecked_extrinsic: *mut u8, + unchecked_extrinsic_max_size: u32, + unchecked_extrinsic_size: *mut u32, + skip_ra: c_int, + ) -> sgx_status_t; + + pub fn generate_dcap_ra_extrinsic( + eid: sgx_enclave_id_t, + retval: *mut sgx_status_t, + w_url: *const u8, + w_url_size: u32, + unchecked_extrinsic: *mut u8, + unchecked_extrinsic_max_size: u32, + unchecked_extrinsic_size: *mut u32, + skip_ra: c_int, + quoting_enclave_target_info: Option<&sgx_target_info_t>, + quote_size: Option<&u32>, + ) -> sgx_status_t; + + pub fn generate_dcap_ra_quote( + eid: sgx_enclave_id_t, + retval: *mut sgx_status_t, + skip_ra: c_int, + quoting_enclave_target_info: &sgx_target_info_t, + quote_size: u32, + dcap_quote_p: *mut u8, + dcap_quote_size: u32, + ) -> sgx_status_t; + + pub fn generate_register_quoting_enclave_extrinsic( + eid: sgx_enclave_id_t, + retval: *mut sgx_status_t, + collateral: *const sgx_ql_qve_collateral_t, + unchecked_extrinsic: *mut u8, + unchecked_extrinsic_max_size: u32, + unchecked_extrinsic_size: *mut u32, + ) -> sgx_status_t; + + pub fn generate_register_tcb_info_extrinsic( + eid: sgx_enclave_id_t, + retval: *mut sgx_status_t, + collateral: *const sgx_ql_qve_collateral_t, + unchecked_extrinsic: *mut u8, + unchecked_extrinsic_max_size: u32, + unchecked_extrinsic_size: *mut u32, + ) -> sgx_status_t; + + pub fn dump_ias_ra_cert_to_disk( + eid: sgx_enclave_id_t, + retval: *mut sgx_status_t, + ) -> sgx_status_t; + + pub fn dump_dcap_ra_cert_to_disk( + eid: sgx_enclave_id_t, + retval: *mut sgx_status_t, + quoting_enclave_target_info: &sgx_target_info_t, + quote_size: u32, + ) -> sgx_status_t; + + pub fn dump_dcap_collateral_to_disk( + eid: sgx_enclave_id_t, + retval: *mut sgx_status_t, + collateral: *const sgx_ql_qve_collateral_t, + ) -> sgx_status_t; + + pub fn test_main_entrance(eid: sgx_enclave_id_t, retval: *mut sgx_status_t) -> sgx_status_t; + + pub fn call_rpc_methods( + eid: sgx_enclave_id_t, + retval: *mut sgx_status_t, + request: *const u8, + request_len: u32, + response: *mut u8, + response_len: u32, + ) -> sgx_status_t; + + pub fn update_market_data_xt( + eid: sgx_enclave_id_t, + retval: *mut sgx_status_t, + crypto_currency: *const u8, + crypto_currency_size: u32, + fiat_currency: *const u8, + fiat_currency_size: u32, + unchecked_extrinsic: *mut u8, + unchecked_extrinsic_max_size: u32, + unchecked_extrinsic_size: *mut u32, + ) -> sgx_status_t; + + pub fn update_weather_data_xt( + eid: sgx_enclave_id_t, + retval: *mut sgx_status_t, + weather_info_longitude: *const u8, + weather_info_longitude_size: u32, + weather_info_latitude: *const u8, + weather_info_latitude_size: u32, + unchecked_extrinsic: *mut u8, + unchecked_extrinsic_max_size: u32, + unchecked_extrinsic_size: *mut u32, + ) -> sgx_status_t; + + pub fn run_state_provisioning_server( + eid: sgx_enclave_id_t, + retval: *mut sgx_status_t, + socket_fd: c_int, + sign_type: sgx_quote_sign_type_t, + quoting_enclave_target_info: Option<&sgx_target_info_t>, + quote_size: Option<&u32>, + skip_ra: c_int, + ) -> sgx_status_t; + + pub fn request_state_provisioning( + eid: sgx_enclave_id_t, + retval: *mut sgx_status_t, + socket_fd: c_int, + sign_type: sgx_quote_sign_type_t, + quoting_enclave_target_info: Option<&sgx_target_info_t>, + quote_size: Option<&u32>, + shard: *const u8, + shard_size: u32, + skip_ra: c_int, + ) -> sgx_status_t; + + // litentry + pub fn migrate_shard( + eid: sgx_enclave_id_t, + retval: *mut sgx_status_t, + old_shard: *const u8, + new_shard: *const u8, + shard_size: u32, + ) -> sgx_status_t; + + pub fn ignore_parentchain_block_import_validation_until( + eid: sgx_enclave_id_t, + retval: *mut sgx_status_t, + until: *const u32, + ) -> sgx_status_t; + +} diff --git a/bitacross-worker/core-primitives/enclave-api/src/direct_request.rs b/bitacross-worker/core-primitives/enclave-api/src/direct_request.rs new file mode 100644 index 0000000000..f3fff3388a --- /dev/null +++ b/bitacross-worker/core-primitives/enclave-api/src/direct_request.rs @@ -0,0 +1,58 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::EnclaveResult; + +pub trait DirectRequest: Send + Sync + 'static { + // Todo: Vec shall be replaced by D: Decode, E: Encode but this is currently + // not compatible with the direct_api_server... + fn rpc(&self, request: Vec) -> EnclaveResult>; +} + +#[cfg(feature = "implement-ffi")] +mod impl_ffi { + use super::DirectRequest; + use crate::{error::Error, Enclave, EnclaveResult}; + use frame_support::ensure; + use itp_enclave_api_ffi as ffi; + use sgx_types::sgx_status_t; + + impl DirectRequest for Enclave { + fn rpc(&self, request: Vec) -> EnclaveResult> { + let mut retval = sgx_status_t::SGX_SUCCESS; + let response_len = 8192; + let mut response: Vec = vec![0u8; response_len as usize]; + + let res = unsafe { + ffi::call_rpc_methods( + self.eid, + &mut retval, + request.as_ptr(), + request.len() as u32, + response.as_mut_ptr(), + response_len, + ) + }; + + ensure!(res == sgx_status_t::SGX_SUCCESS, Error::Sgx(res)); + ensure!(retval == sgx_status_t::SGX_SUCCESS, Error::Sgx(retval)); + + Ok(response) + } + } +} diff --git a/bitacross-worker/core-primitives/enclave-api/src/enclave_base.rs b/bitacross-worker/core-primitives/enclave-api/src/enclave_base.rs new file mode 100644 index 0000000000..4e79a6f902 --- /dev/null +++ b/bitacross-worker/core-primitives/enclave-api/src/enclave_base.rs @@ -0,0 +1,409 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::EnclaveResult; +use codec::Decode; +use core::fmt::Debug; +use itc_parentchain::primitives::{ParentchainId, ParentchainInitParams}; +use itp_types::ShardIdentifier; +use sgx_crypto_helper::rsa3072::Rsa3072PubKey; +use sp_core::ed25519; +use teerex_primitives::EnclaveFingerprint; + +/// Trait for base/common Enclave API functions +pub trait EnclaveBase: Send + Sync + 'static { + /// Initialize the enclave (needs to be called once at application startup). + fn init( + &self, + mu_ra_addr: &str, + untrusted_worker_addr: &str, + base_dir: &str, + ) -> EnclaveResult<()>; + + /// Initialize the enclave sidechain components. + fn init_enclave_sidechain_components( + &self, + fail_mode: Option, + fail_at: u64, + ) -> EnclaveResult<()>; + + /// Initialize the direct invocation RPC server. + fn init_direct_invocation_server(&self, rpc_server_addr: String) -> EnclaveResult<()>; + + /// Initialize the light client (needs to be called once at application startup). + fn init_parentchain_components( + &self, + params: ParentchainInitParams, + ) -> EnclaveResult
; + + /// Initialize a new shard. + fn init_shard(&self, shard: Vec) -> EnclaveResult<()>; + + /// Initialize a new shard vault account and register enclave signer as its proxy. + fn init_proxied_shard_vault( + &self, + shard: &ShardIdentifier, + parentchain_id: &ParentchainId, + ) -> EnclaveResult<()>; + + fn set_nonce(&self, nonce: u32, parentchain_id: ParentchainId) -> EnclaveResult<()>; + + fn set_node_metadata( + &self, + metadata: Vec, + parentchain_id: ParentchainId, + ) -> EnclaveResult<()>; + + fn get_rsa_shielding_pubkey(&self) -> EnclaveResult; + + fn get_ecc_signing_pubkey(&self) -> EnclaveResult; + + /// retrieve vault account from shard state + fn get_ecc_vault_pubkey(&self, shard: &ShardIdentifier) -> EnclaveResult; + + fn get_fingerprint(&self) -> EnclaveResult; + + // litentry + fn migrate_shard(&self, old_shard: Vec, new_shard: Vec) -> EnclaveResult<()>; +} + +/// EnclaveApi implementation for Enclave struct +#[cfg(feature = "implement-ffi")] +mod impl_ffi { + use super::EnclaveBase; + use crate::{error::Error, Enclave, EnclaveResult}; + use codec::{Decode, Encode}; + use core::fmt::Debug; + use frame_support::ensure; + use itc_parentchain::primitives::{ParentchainId, ParentchainInitParams}; + use itp_enclave_api_ffi as ffi; + use itp_settings::worker::{ + HEADER_MAX_SIZE, MR_ENCLAVE_SIZE, SHIELDING_KEY_SIZE, SIGNING_KEY_SIZE, + }; + use itp_types::ShardIdentifier; + use log::*; + use sgx_crypto_helper::rsa3072::Rsa3072PubKey; + use sgx_types::*; + use sp_core::ed25519; + use teerex_primitives::EnclaveFingerprint; + + impl EnclaveBase for Enclave { + fn init( + &self, + mu_ra_addr: &str, + untrusted_worker_addr: &str, + base_dir: &str, + ) -> EnclaveResult<()> { + let mut retval = sgx_status_t::SGX_SUCCESS; + + let encoded_mu_ra_addr = mu_ra_addr.encode(); + let encoded_untrusted_worker_addr = untrusted_worker_addr.encode(); + let encoded_base_dir = base_dir.encode(); + + let result = unsafe { + ffi::init( + self.eid, + &mut retval, + encoded_mu_ra_addr.as_ptr(), + encoded_mu_ra_addr.len() as u32, + encoded_untrusted_worker_addr.as_ptr(), + encoded_untrusted_worker_addr.len() as u32, + encoded_base_dir.as_ptr(), + encoded_base_dir.len() as u32, + ) + }; + + ensure!(result == sgx_status_t::SGX_SUCCESS, Error::Sgx(result)); + ensure!(retval == sgx_status_t::SGX_SUCCESS, Error::Sgx(retval)); + + Ok(()) + } + + fn init_enclave_sidechain_components( + &self, + fail_mode: Option, + fail_at: u64, + ) -> EnclaveResult<()> { + let mut retval = sgx_status_t::SGX_SUCCESS; + let encoded_fail_mode = fail_mode.encode(); + let encoded_fail_at = fail_at.encode(); + + let result = unsafe { + ffi::init_enclave_sidechain_components( + self.eid, + &mut retval, + encoded_fail_mode.as_ptr(), + encoded_fail_mode.len() as u32, + encoded_fail_at.as_ptr(), + encoded_fail_at.len() as u32, + ) + }; + + ensure!(result == sgx_status_t::SGX_SUCCESS, Error::Sgx(result)); + ensure!(retval == sgx_status_t::SGX_SUCCESS, Error::Sgx(retval)); + + Ok(()) + } + + fn init_direct_invocation_server(&self, rpc_server_addr: String) -> EnclaveResult<()> { + let mut retval = sgx_status_t::SGX_SUCCESS; + + let encoded_rpc_server_addr = rpc_server_addr.encode(); + + let result = unsafe { + ffi::init_direct_invocation_server( + self.eid, + &mut retval, + encoded_rpc_server_addr.as_ptr(), + encoded_rpc_server_addr.len() as u32, + ) + }; + + ensure!(result == sgx_status_t::SGX_SUCCESS, Error::Sgx(result)); + ensure!(retval == sgx_status_t::SGX_SUCCESS, Error::Sgx(retval)); + + Ok(()) + } + + fn init_parentchain_components( + &self, + params: ParentchainInitParams, + ) -> EnclaveResult
{ + let latest_header_encoded = init_parentchain_components_ffi(self.eid, params.encode())?; + + let latest = Header::decode(&mut latest_header_encoded.as_slice())?; + info!("Latest Header {:?}", latest); + + Ok(latest) + } + + fn init_shard(&self, shard: Vec) -> EnclaveResult<()> { + let mut retval = sgx_status_t::SGX_SUCCESS; + + let result = unsafe { + ffi::init_shard(self.eid, &mut retval, shard.as_ptr(), shard.len() as u32) + }; + + ensure!(result == sgx_status_t::SGX_SUCCESS, Error::Sgx(result)); + ensure!(retval == sgx_status_t::SGX_SUCCESS, Error::Sgx(retval)); + + Ok(()) + } + + fn init_proxied_shard_vault( + &self, + shard: &ShardIdentifier, + parentchain_id: &ParentchainId, + ) -> EnclaveResult<()> { + let mut retval = sgx_status_t::SGX_SUCCESS; + let parentchain_id_enc = parentchain_id.encode(); + let shard_bytes = shard.encode(); + let result = unsafe { + ffi::init_proxied_shard_vault( + self.eid, + &mut retval, + shard_bytes.as_ptr(), + shard_bytes.len() as u32, + parentchain_id_enc.as_ptr(), + parentchain_id_enc.len() as u32, + ) + }; + + ensure!(result == sgx_status_t::SGX_SUCCESS, Error::Sgx(result)); + ensure!(retval == sgx_status_t::SGX_SUCCESS, Error::Sgx(retval)); + + Ok(()) + } + + fn set_nonce(&self, nonce: u32, parentchain_id: ParentchainId) -> EnclaveResult<()> { + let mut retval = sgx_status_t::SGX_SUCCESS; + + let parentchain_id_enc = parentchain_id.encode(); + + let result = unsafe { + ffi::set_nonce( + self.eid, + &mut retval, + &nonce, + parentchain_id_enc.as_ptr(), + parentchain_id_enc.len() as u32, + ) + }; + + ensure!(result == sgx_status_t::SGX_SUCCESS, Error::Sgx(result)); + ensure!(retval == sgx_status_t::SGX_SUCCESS, Error::Sgx(retval)); + + Ok(()) + } + + fn set_node_metadata( + &self, + metadata: Vec, + parentchain_id: ParentchainId, + ) -> EnclaveResult<()> { + let mut retval = sgx_status_t::SGX_SUCCESS; + + let parentchain_id_enc = parentchain_id.encode(); + + let result = unsafe { + ffi::set_node_metadata( + self.eid, + &mut retval, + metadata.as_ptr(), + metadata.len() as u32, + parentchain_id_enc.as_ptr(), + parentchain_id_enc.len() as u32, + ) + }; + + ensure!(result == sgx_status_t::SGX_SUCCESS, Error::Sgx(result)); + ensure!(retval == sgx_status_t::SGX_SUCCESS, Error::Sgx(retval)); + + Ok(()) + } + + fn get_rsa_shielding_pubkey(&self) -> EnclaveResult { + let mut retval = sgx_status_t::SGX_SUCCESS; + + let pubkey_size = SHIELDING_KEY_SIZE; + let mut pubkey = vec![0u8; pubkey_size]; + + let result = unsafe { + ffi::get_rsa_encryption_pubkey( + self.eid, + &mut retval, + pubkey.as_mut_ptr(), + pubkey.len() as u32, + ) + }; + + ensure!(result == sgx_status_t::SGX_SUCCESS, Error::Sgx(result)); + ensure!(retval == sgx_status_t::SGX_SUCCESS, Error::Sgx(retval)); + + let rsa_pubkey: Rsa3072PubKey = + serde_json::from_slice(pubkey.as_slice()).expect("Invalid public key"); + debug!("got RSA pubkey {:?}", rsa_pubkey); + Ok(rsa_pubkey) + } + + fn get_ecc_signing_pubkey(&self) -> EnclaveResult { + let mut retval = sgx_status_t::SGX_SUCCESS; + let mut pubkey = [0u8; SIGNING_KEY_SIZE]; + + let result = unsafe { + ffi::get_ecc_signing_pubkey( + self.eid, + &mut retval, + pubkey.as_mut_ptr(), + pubkey.len() as u32, + ) + }; + + ensure!(result == sgx_status_t::SGX_SUCCESS, Error::Sgx(result)); + ensure!(retval == sgx_status_t::SGX_SUCCESS, Error::Sgx(retval)); + + Ok(ed25519::Public::from_raw(pubkey)) + } + + fn get_ecc_vault_pubkey(&self, shard: &ShardIdentifier) -> EnclaveResult { + let mut retval = sgx_status_t::SGX_SUCCESS; + let mut pubkey = [0u8; SIGNING_KEY_SIZE]; + let shard_bytes = shard.encode(); + + let result = unsafe { + ffi::get_ecc_vault_pubkey( + self.eid, + &mut retval, + shard_bytes.as_ptr(), + shard_bytes.len() as u32, + pubkey.as_mut_ptr(), + pubkey.len() as u32, + ) + }; + + ensure!(result == sgx_status_t::SGX_SUCCESS, Error::Sgx(result)); + ensure!(retval == sgx_status_t::SGX_SUCCESS, Error::Sgx(retval)); + + Ok(ed25519::Public::from_raw(pubkey)) + } + + fn get_fingerprint(&self) -> EnclaveResult { + let mut retval = sgx_status_t::SGX_SUCCESS; + let mut mr_enclave = [0u8; MR_ENCLAVE_SIZE]; + + let result = unsafe { + ffi::get_mrenclave( + self.eid, + &mut retval, + mr_enclave.as_mut_ptr(), + mr_enclave.len() as u32, + ) + }; + + ensure!(result == sgx_status_t::SGX_SUCCESS, Error::Sgx(result)); + ensure!(retval == sgx_status_t::SGX_SUCCESS, Error::Sgx(retval)); + + Ok(mr_enclave.into()) + } + + fn migrate_shard(&self, old_shard: Vec, new_shard: Vec) -> EnclaveResult<()> { + let mut retval = sgx_status_t::SGX_SUCCESS; + + let result = unsafe { + ffi::migrate_shard( + self.eid, + &mut retval, + old_shard.as_ptr(), + new_shard.as_ptr(), + old_shard.len() as u32, + ) + }; + + ensure!(result == sgx_status_t::SGX_SUCCESS, Error::Sgx(result)); + ensure!(retval == sgx_status_t::SGX_SUCCESS, Error::Sgx(retval)); + + Ok(()) + } + } + + fn init_parentchain_components_ffi( + enclave_id: sgx_enclave_id_t, + params: Vec, + ) -> EnclaveResult> { + let mut retval = sgx_status_t::SGX_SUCCESS; + + let latest_header_size = HEADER_MAX_SIZE; + let mut latest_header = vec![0u8; latest_header_size]; + + let result = unsafe { + ffi::init_parentchain_components( + enclave_id, + &mut retval, + params.as_ptr(), + params.len(), + latest_header.as_mut_ptr(), + latest_header.len(), + ) + }; + + ensure!(result == sgx_status_t::SGX_SUCCESS, Error::Sgx(result)); + ensure!(retval == sgx_status_t::SGX_SUCCESS, Error::Sgx(retval)); + + Ok(latest_header) + } +} diff --git a/bitacross-worker/core-primitives/enclave-api/src/enclave_test.rs b/bitacross-worker/core-primitives/enclave-api/src/enclave_test.rs new file mode 100644 index 0000000000..aaf3a8e97d --- /dev/null +++ b/bitacross-worker/core-primitives/enclave-api/src/enclave_test.rs @@ -0,0 +1,48 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::EnclaveResult; + +pub trait EnclaveTest: Send + Sync + 'static { + fn test_main_entrance(&self) -> EnclaveResult<()>; +} + +#[cfg(feature = "implement-ffi")] +mod impl_ffi { + use super::EnclaveTest; + use crate::{error::Error, Enclave, EnclaveResult}; + use frame_support::ensure; + use itp_enclave_api_ffi as ffi; + use log::*; + use sgx_types::sgx_status_t; + + impl EnclaveTest for Enclave { + fn test_main_entrance(&self) -> EnclaveResult<()> { + let mut retval = sgx_status_t::SGX_SUCCESS; + + let result = unsafe { ffi::test_main_entrance(self.eid, &mut retval) }; + + ensure!(result == sgx_status_t::SGX_SUCCESS, Error::Sgx(result)); + ensure!(retval == sgx_status_t::SGX_SUCCESS, Error::Sgx(retval)); + + debug!("[+] successfully executed enclave test main"); + + Ok(()) + } + } +} diff --git a/bitacross-worker/core-primitives/enclave-api/src/error.rs b/bitacross-worker/core-primitives/enclave-api/src/error.rs new file mode 100644 index 0000000000..d510c56db4 --- /dev/null +++ b/bitacross-worker/core-primitives/enclave-api/src/error.rs @@ -0,0 +1,14 @@ +use codec::Error as CodecError; +use sgx_types::{sgx_quote3_error_t, sgx_status_t}; + +#[derive(Debug, thiserror::Error)] +pub enum Error { + #[error("{0}")] + Codec(#[from] CodecError), + #[error("Enclave Error: {0}")] + Sgx(sgx_status_t), + #[error("Enclave Quote Error: {0}")] + SgxQuote(sgx_quote3_error_t), + #[error("Error, other: {0}")] + Other(Box), +} diff --git a/bitacross-worker/core-primitives/enclave-api/src/lib.rs b/bitacross-worker/core-primitives/enclave-api/src/lib.rs new file mode 100644 index 0000000000..38c810624f --- /dev/null +++ b/bitacross-worker/core-primitives/enclave-api/src/lib.rs @@ -0,0 +1,49 @@ +//! Some definitions and traits that facilitate interaction with the enclave. +//! +//! This serves as a proof of concept on how we could design the interface between the worker and +//! the enclave. +//! +//! Design principle here should be to keep the traits as slim as possible - because then the +//! worker can also define slim interfaces with less demanding trait bounds. +//! +//! This can further be simplified once https://github.com/integritee-network/worker/issues/254 +//! is implemented. Then we can replace the several ffi:: and the boilerplate code +//! around it with a simple `fn ecall(call: CallEnum) -> Result`, which wraps one single +//! ffi function. + +use crate::error::Error; + +pub mod direct_request; +pub mod enclave_base; +pub mod enclave_test; +pub mod error; +pub mod remote_attestation; +pub mod sidechain; +pub mod teeracle_api; +pub mod utils; + +#[cfg(feature = "implement-ffi")] +pub use sgx_urts::SgxEnclave; + +#[cfg(feature = "implement-ffi")] +use sgx_types::sgx_enclave_id_t; + +pub type EnclaveResult = Result; + +#[cfg(feature = "implement-ffi")] +#[derive(Clone, Debug, Default)] +pub struct Enclave { + eid: sgx_enclave_id_t, + sgx_enclave: SgxEnclave, +} + +#[cfg(feature = "implement-ffi")] +impl Enclave { + pub fn new(sgx_enclave: SgxEnclave) -> Self { + Enclave { eid: sgx_enclave.geteid(), sgx_enclave } + } + + pub fn destroy(self) { + self.sgx_enclave.destroy() + } +} diff --git a/bitacross-worker/core-primitives/enclave-api/src/remote_attestation.rs b/bitacross-worker/core-primitives/enclave-api/src/remote_attestation.rs new file mode 100644 index 0000000000..9aa32cb631 --- /dev/null +++ b/bitacross-worker/core-primitives/enclave-api/src/remote_attestation.rs @@ -0,0 +1,857 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::EnclaveResult; +use itp_types::ShardIdentifier; +use sgx_types::*; +use teerex_primitives::Fmspc; + +/// Struct that unites all relevant data reported by the QVE +pub struct QveReport { + pub supplemental_data: Vec, + pub qve_report_info_return_value: sgx_ql_qe_report_info_t, + pub quote_verification_result: sgx_ql_qv_result_t, + pub collateral_expiration_status: u32, +} + +/// general remote attestation methods +pub trait RemoteAttestation { + fn generate_ias_ra_extrinsic(&self, w_url: &str, skip_ra: bool) -> EnclaveResult>; + + fn generate_dcap_ra_extrinsic(&self, w_url: &str, skip_ra: bool) -> EnclaveResult>; + fn generate_dcap_ra_extrinsic_from_quote( + &self, + url: String, + quote: &[u8], + ) -> EnclaveResult>; + fn generate_dcap_ra_quote(&self, skip_ra: bool) -> EnclaveResult>; + + fn generate_register_quoting_enclave_extrinsic(&self, fmspc: Fmspc) -> EnclaveResult>; + + fn generate_register_tcb_info_extrinsic(&self, fmspc: Fmspc) -> EnclaveResult>; + + fn dump_ias_ra_cert_to_disk(&self) -> EnclaveResult<()>; + + fn dump_dcap_ra_cert_to_disk(&self) -> EnclaveResult<()>; + + fn dump_dcap_collateral_to_disk(&self, fmspc: Fmspc) -> EnclaveResult<()>; + + fn set_ql_qe_enclave_paths(&self) -> EnclaveResult<()>; + + fn set_sgx_qpl_logging(&self) -> EnclaveResult<()>; + + fn qe_get_target_info(&self) -> EnclaveResult; + + fn qe_get_quote_size(&self) -> EnclaveResult; + + fn get_dcap_collateral(&self, fmspc: Fmspc) -> EnclaveResult<*const sgx_ql_qve_collateral_t>; +} + +/// call-backs that are made from inside the enclave (using o-call), to e-calls again inside the enclave +pub trait RemoteAttestationCallBacks { + fn init_quote(&self) -> EnclaveResult<(sgx_target_info_t, sgx_epid_group_id_t)>; + + fn calc_quote_size(&self, revocation_list: Vec) -> EnclaveResult; + + fn get_quote( + &self, + revocation_list: Vec, + report: sgx_report_t, + quote_type: sgx_quote_sign_type_t, + spid: sgx_spid_t, + quote_nonce: sgx_quote_nonce_t, + quote_length: u32, + ) -> EnclaveResult<(sgx_report_t, Vec)>; + + fn get_dcap_quote(&self, report: sgx_report_t, quote_size: u32) -> EnclaveResult>; + + fn get_qve_report_on_quote( + &self, + quote: Vec, + current_time: i64, + quote_collateral: &sgx_ql_qve_collateral_t, + qve_report_info: sgx_ql_qe_report_info_t, + supplemental_data_size: u32, + ) -> EnclaveResult; + + fn get_update_info( + &self, + platform_blob: sgx_platform_info_t, + enclave_trusted: i32, + ) -> EnclaveResult; +} + +/// TLS remote attestations methods +pub trait TlsRemoteAttestation { + fn run_state_provisioning_server( + &self, + socket_fd: c_int, + sign_type: sgx_quote_sign_type_t, + quoting_enclave_target_info: Option<&sgx_target_info_t>, + quote_size: Option<&u32>, + skip_ra: bool, + ) -> EnclaveResult<()>; + + fn request_state_provisioning( + &self, + socket_fd: c_int, + sign_type: sgx_quote_sign_type_t, + quoting_enclave_target_info: Option<&sgx_target_info_t>, + quote_size: Option<&u32>, + shard: &ShardIdentifier, + skip_ra: bool, + ) -> EnclaveResult<()>; +} + +#[cfg(feature = "implement-ffi")] +mod impl_ffi { + use super::{QveReport, RemoteAttestation, RemoteAttestationCallBacks, TlsRemoteAttestation}; + use crate::{error::Error, utils, Enclave, EnclaveResult}; + use codec::Encode; + use frame_support::ensure; + use itp_enclave_api_ffi as ffi; + use itp_settings::worker::EXTRINSIC_MAX_SIZE; + use itp_types::ShardIdentifier; + use log::*; + use sgx_types::*; + use teerex_primitives::Fmspc; + + const OS_SYSTEM_PATH: &str = "/usr/lib/x86_64-linux-gnu/"; + const C_STRING_ENDING: &str = "\0"; + const PCE_ENCLAVE: &str = "libsgx_pce.signed.so.1"; + const QE3_ENCLAVE: &str = "libsgx_qe3.signed.so.1"; + const ID_ENCLAVE: &str = "libsgx_id_enclave.signed.so.1"; + const LIBDCAP_QUOTEPROV: &str = "libdcap_quoteprov.so.1"; + const QVE_ENCLAVE: &str = "libsgx_qve.signed.so.1"; + + impl RemoteAttestation for Enclave { + fn generate_ias_ra_extrinsic(&self, w_url: &str, skip_ra: bool) -> EnclaveResult> { + let mut retval = sgx_status_t::SGX_SUCCESS; + + let mut unchecked_extrinsic: Vec = vec![0u8; EXTRINSIC_MAX_SIZE]; + let mut unchecked_extrinsic_size: u32 = 0; + + trace!("Generating ias_ra_extrinsic with URL: {}", w_url); + + let url = w_url.encode(); + + let result = unsafe { + ffi::generate_ias_ra_extrinsic( + self.eid, + &mut retval, + url.as_ptr(), + url.len() as u32, + unchecked_extrinsic.as_mut_ptr(), + unchecked_extrinsic.len() as u32, + &mut unchecked_extrinsic_size as *mut u32, + skip_ra.into(), + ) + }; + + ensure!(result == sgx_status_t::SGX_SUCCESS, Error::Sgx(result)); + ensure!(retval == sgx_status_t::SGX_SUCCESS, Error::Sgx(retval)); + + Ok(Vec::from(&unchecked_extrinsic[..unchecked_extrinsic_size as usize])) + } + fn generate_dcap_ra_extrinsic_from_quote( + &self, + url: String, + quote: &[u8], + ) -> EnclaveResult> { + let mut retval = sgx_status_t::SGX_SUCCESS; + let mut unchecked_extrinsic: Vec = vec![0u8; EXTRINSIC_MAX_SIZE]; + let mut unchecked_extrinsic_size: u32 = 0; + let url = url.encode(); + + let result = unsafe { + ffi::generate_dcap_ra_extrinsic_from_quote( + self.eid, + &mut retval, + url.as_ptr(), + url.len() as u32, + quote.as_ptr(), + quote.len() as u32, + unchecked_extrinsic.as_mut_ptr(), + unchecked_extrinsic.len() as u32, + &mut unchecked_extrinsic_size as *mut u32, + ) + }; + + ensure!(result == sgx_status_t::SGX_SUCCESS, Error::Sgx(result)); + ensure!(retval == sgx_status_t::SGX_SUCCESS, Error::Sgx(retval)); + + Ok(Vec::from(&unchecked_extrinsic[..unchecked_extrinsic_size as usize])) + } + + fn generate_dcap_ra_quote(&self, skip_ra: bool) -> EnclaveResult> { + let mut retval = sgx_status_t::SGX_SUCCESS; + let quoting_enclave_target_info = self.qe_get_target_info()?; + let quote_size = self.qe_get_quote_size()?; + + let mut dcap_quote_vec: Vec = vec![0; quote_size as usize]; + let (dcap_quote_p, dcap_quote_size) = + (dcap_quote_vec.as_mut_ptr(), dcap_quote_vec.len() as u32); + + let result = unsafe { + ffi::generate_dcap_ra_quote( + self.eid, + &mut retval, + skip_ra.into(), + "ing_enclave_target_info, + quote_size, + dcap_quote_p, + dcap_quote_size, + ) + }; + + ensure!(result == sgx_status_t::SGX_SUCCESS, Error::Sgx(result)); + ensure!(retval == sgx_status_t::SGX_SUCCESS, Error::Sgx(retval)); + + unsafe { + trace!("Generating DCAP RA Quote: {}", *dcap_quote_p); + } + + Ok(dcap_quote_vec) + } + + fn generate_dcap_ra_extrinsic(&self, w_url: &str, skip_ra: bool) -> EnclaveResult> { + let mut retval = sgx_status_t::SGX_SUCCESS; + + self.set_ql_qe_enclave_paths()?; + let quoting_enclave_target_info = if !skip_ra { + match self.qe_get_target_info() { + Ok(target_info) => Some(target_info), + Err(e) => return Err(e), + } + } else { + None + }; + let quote_size = if !skip_ra { + match self.qe_get_quote_size() { + Ok(quote_size) => Some(quote_size), + Err(e) => return Err(e), + } + } else { + None + }; + info!("Retrieved quote size of {:?}", quote_size); + + trace!("Generating dcap_ra_extrinsic with URL: {}", w_url); + + let mut unchecked_extrinsic: Vec = vec![0u8; EXTRINSIC_MAX_SIZE]; + let mut unchecked_extrinsic_size: u32 = 0; + let url = w_url.encode(); + + let result = unsafe { + ffi::generate_dcap_ra_extrinsic( + self.eid, + &mut retval, + url.as_ptr(), + url.len() as u32, + unchecked_extrinsic.as_mut_ptr(), + unchecked_extrinsic.len() as u32, + &mut unchecked_extrinsic_size as *mut u32, + skip_ra.into(), + quoting_enclave_target_info.as_ref(), + quote_size.as_ref(), + ) + }; + + ensure!(result == sgx_status_t::SGX_SUCCESS, Error::Sgx(result)); + ensure!(retval == sgx_status_t::SGX_SUCCESS, Error::Sgx(retval)); + + Ok(Vec::from(&unchecked_extrinsic[..unchecked_extrinsic_size as usize])) + } + + fn generate_register_quoting_enclave_extrinsic( + &self, + fmspc: Fmspc, + ) -> EnclaveResult> { + let mut retval = sgx_status_t::SGX_SUCCESS; + let mut unchecked_extrinsic: Vec = vec![0u8; EXTRINSIC_MAX_SIZE]; + let mut unchecked_extrinsic_size: u32 = 0; + + trace!("Generating register quoting enclave"); + + let collateral_ptr = self.get_dcap_collateral(fmspc)?; + + let result = unsafe { + ffi::generate_register_quoting_enclave_extrinsic( + self.eid, + &mut retval, + collateral_ptr, + unchecked_extrinsic.as_mut_ptr(), + unchecked_extrinsic.len() as u32, + &mut unchecked_extrinsic_size as *mut u32, + ) + }; + let free_status = unsafe { sgx_ql_free_quote_verification_collateral(collateral_ptr) }; + ensure!(result == sgx_status_t::SGX_SUCCESS, Error::Sgx(result)); + ensure!(retval == sgx_status_t::SGX_SUCCESS, Error::Sgx(retval)); + ensure!( + free_status == sgx_quote3_error_t::SGX_QL_SUCCESS, + Error::SgxQuote(free_status) + ); + + Ok(Vec::from(&unchecked_extrinsic[..unchecked_extrinsic_size as usize])) + } + + fn generate_register_tcb_info_extrinsic(&self, fmspc: Fmspc) -> EnclaveResult> { + let mut retval = sgx_status_t::SGX_SUCCESS; + let mut unchecked_extrinsic: Vec = vec![0u8; EXTRINSIC_MAX_SIZE]; + let mut unchecked_extrinsic_size: u32 = 0; + + trace!("Generating tcb_info registration"); + + let collateral_ptr = self.get_dcap_collateral(fmspc)?; + + let result = unsafe { + ffi::generate_register_tcb_info_extrinsic( + self.eid, + &mut retval, + collateral_ptr, + unchecked_extrinsic.as_mut_ptr(), + unchecked_extrinsic.len() as u32, + &mut unchecked_extrinsic_size as *mut u32, + ) + }; + let free_status = unsafe { sgx_ql_free_quote_verification_collateral(collateral_ptr) }; + ensure!(result == sgx_status_t::SGX_SUCCESS, Error::Sgx(result)); + ensure!(retval == sgx_status_t::SGX_SUCCESS, Error::Sgx(retval)); + ensure!( + free_status == sgx_quote3_error_t::SGX_QL_SUCCESS, + Error::SgxQuote(free_status) + ); + + Ok(Vec::from(&unchecked_extrinsic[..unchecked_extrinsic_size as usize])) + } + + fn dump_ias_ra_cert_to_disk(&self) -> EnclaveResult<()> { + let mut retval = sgx_status_t::SGX_SUCCESS; + + let result = unsafe { ffi::dump_ias_ra_cert_to_disk(self.eid, &mut retval) }; + + ensure!(result == sgx_status_t::SGX_SUCCESS, Error::Sgx(result)); + ensure!(retval == sgx_status_t::SGX_SUCCESS, Error::Sgx(retval)); + + Ok(()) + } + + fn dump_dcap_ra_cert_to_disk(&self) -> EnclaveResult<()> { + let mut retval = sgx_status_t::SGX_SUCCESS; + + self.set_ql_qe_enclave_paths()?; + let quoting_enclave_target_info = self.qe_get_target_info()?; + let quote_size = self.qe_get_quote_size()?; + + let result = unsafe { + ffi::dump_dcap_ra_cert_to_disk( + self.eid, + &mut retval, + "ing_enclave_target_info, + quote_size, + ) + }; + + ensure!(result == sgx_status_t::SGX_SUCCESS, Error::Sgx(result)); + ensure!(retval == sgx_status_t::SGX_SUCCESS, Error::Sgx(retval)); + + Ok(()) + } + + fn set_ql_qe_enclave_paths(&self) -> EnclaveResult<()> { + set_ql_path(sgx_ql_path_type_t::SGX_QL_PCE_PATH, PCE_ENCLAVE)?; + set_ql_path(sgx_ql_path_type_t::SGX_QL_QE3_PATH, QE3_ENCLAVE)?; + set_ql_path(sgx_ql_path_type_t::SGX_QL_IDE_PATH, ID_ENCLAVE)?; + if set_ql_path(sgx_ql_path_type_t::SGX_QL_QPL_PATH, LIBDCAP_QUOTEPROV).is_err() { + // Ignore the error, because user may want to get cert type=3 quote. + warn!("Cannot set QPL directory, you may get ECDSA quote with `Encrypted PPID` cert type.\n"); + }; + set_qv_path(sgx_qv_path_type_t::SGX_QV_QVE_PATH, QVE_ENCLAVE)?; + + Ok(()) + } + + fn set_sgx_qpl_logging(&self) -> EnclaveResult<()> { + let log_level = sgx_ql_log_level_t::SGX_QL_LOG_INFO; + let res = unsafe { sgx_ql_set_logging_callback(forward_qpl_log, log_level) }; + if res == sgx_quote3_error_t::SGX_QL_SUCCESS { + Ok(()) + } else { + error!("Setting logging function failed with: {:?}", res); + Err(Error::SgxQuote(res)) + } + } + + fn qe_get_target_info(&self) -> EnclaveResult { + let mut quoting_enclave_target_info: sgx_target_info_t = sgx_target_info_t::default(); + let qe3_ret = + unsafe { sgx_qe_get_target_info(&mut quoting_enclave_target_info as *mut _) }; + ensure!(qe3_ret == sgx_quote3_error_t::SGX_QL_SUCCESS, Error::SgxQuote(qe3_ret)); + + Ok(quoting_enclave_target_info) + } + + fn qe_get_quote_size(&self) -> EnclaveResult { + let mut quote_size: u32 = 0; + let qe3_ret = unsafe { sgx_qe_get_quote_size(&mut quote_size as *mut _) }; + ensure!(qe3_ret == sgx_quote3_error_t::SGX_QL_SUCCESS, Error::SgxQuote(qe3_ret)); + + Ok(quote_size) + } + + fn dump_dcap_collateral_to_disk(&self, fmspc: Fmspc) -> EnclaveResult<()> { + let mut retval = sgx_status_t::SGX_SUCCESS; + let collateral_ptr = self.get_dcap_collateral(fmspc)?; + let result = + unsafe { ffi::dump_dcap_collateral_to_disk(self.eid, &mut retval, collateral_ptr) }; + let free_status = unsafe { sgx_ql_free_quote_verification_collateral(collateral_ptr) }; + ensure!(result == sgx_status_t::SGX_SUCCESS, Error::Sgx(result)); + ensure!(retval == sgx_status_t::SGX_SUCCESS, Error::Sgx(result)); + ensure!( + free_status == sgx_quote3_error_t::SGX_QL_SUCCESS, + Error::SgxQuote(free_status) + ); + Ok(()) + } + + fn get_dcap_collateral( + &self, + fmspc: Fmspc, + ) -> EnclaveResult<*const sgx_ql_qve_collateral_t> { + let pck_ra = b"processor\x00"; + + // SAFETY: Just get a nullptr for the FFI to overwrite later + let mut collateral_ptr: *mut sgx_ql_qve_collateral_t = unsafe { std::mem::zeroed() }; + + let collateral_ptr_ptr: *mut *mut sgx_ql_qve_collateral_t = &mut collateral_ptr; + // SAFETY: All parameters are properly initialized so the FFI call should be fine + let sgx_status = unsafe { + sgx_ql_get_quote_verification_collateral( + fmspc.as_ptr(), + fmspc.len() as uint16_t, //fmspc len is fixed in the function signature + pck_ra.as_ptr() as _, + collateral_ptr_ptr, + ) + }; + + trace!("FMSPC: {:?}", hex::encode(fmspc)); + + if collateral_ptr.is_null() { + error!("PCK quote collateral data is null, sgx_status is: {}", sgx_status); + return Err(Error::SgxQuote(sgx_status)) + } + + trace!("collateral:"); + // SAFETY: the previous block checks for `collateral_ptr` being null. + // SAFETY: the fields should be nul terminated C strings. + unsafe { + let collateral = &*collateral_ptr; + trace!( + "version: {}\n, \ + tee_type: {}\n, \ + pck_crl_issuer_chain: {:?}\n, \ + pck_crl_issuer_chain_size: {}\n, \ + root_ca_crl: {:?}\n, \ + root_ca_crl_size: {}\n, \ + pck_crl: {:?}\n, \ + pck_crl_size: {}\n, \ + tcb_info_issuer_chain: {:?}\n, \ + tcb_info_issuer_chain_size: {}\n, \ + tcb_info: {}\n, \ + tcb_info_size: {}\n, \ + qe_identity_issuer_chain: {:?}\n, \ + qe_identity_issuer_chain_size: {}\n, \ + qe_identity: {}\n, \ + qe_identity_size: {}\n", + collateral.version, + collateral.tee_type, + std::ffi::CStr::from_ptr(collateral.pck_crl_issuer_chain).to_string_lossy(), + collateral.pck_crl_issuer_chain_size, + std::ffi::CStr::from_ptr(collateral.root_ca_crl).to_string_lossy(), + collateral.root_ca_crl_size, + std::ffi::CStr::from_ptr(collateral.pck_crl).to_string_lossy(), + collateral.pck_crl_size, + std::ffi::CStr::from_ptr(collateral.tcb_info_issuer_chain).to_string_lossy(), + collateral.tcb_info_issuer_chain_size, + std::ffi::CStr::from_ptr(collateral.tcb_info).to_string_lossy(), + collateral.tcb_info_size, + std::ffi::CStr::from_ptr(collateral.qe_identity_issuer_chain).to_string_lossy(), + collateral.qe_identity_issuer_chain_size, + std::ffi::CStr::from_ptr(collateral.qe_identity).to_string_lossy(), + collateral.qe_identity_size, + ); + }; + + ensure!(sgx_status == sgx_quote3_error_t::SGX_QL_SUCCESS, Error::SgxQuote(sgx_status)); + Ok(collateral_ptr) + } + } + + #[cfg(feature = "implement-ffi")] + impl RemoteAttestationCallBacks for Enclave { + fn init_quote(&self) -> EnclaveResult<(sgx_target_info_t, sgx_epid_group_id_t)> { + let mut ti: sgx_target_info_t = sgx_target_info_t::default(); + let mut eg: sgx_epid_group_id_t = sgx_epid_group_id_t::default(); + + let result = unsafe { + sgx_init_quote( + &mut ti as *mut sgx_target_info_t, + &mut eg as *mut sgx_epid_group_id_t, + ) + }; + + ensure!(result == sgx_status_t::SGX_SUCCESS, Error::Sgx(result)); + + Ok((ti, eg)) + } + + fn calc_quote_size(&self, revocation_list: Vec) -> EnclaveResult { + let mut real_quote_len: u32 = 0; + + let (p_sig_rl, sig_rl_size) = utils::vec_to_c_pointer_with_len(revocation_list); + + let result = unsafe { + sgx_calc_quote_size(p_sig_rl, sig_rl_size, &mut real_quote_len as *mut u32) + }; + + ensure!(result == sgx_status_t::SGX_SUCCESS, Error::Sgx(result)); + + Ok(real_quote_len) + } + + fn get_quote( + &self, + revocation_list: Vec, + report: sgx_report_t, + quote_type: sgx_quote_sign_type_t, + spid: sgx_spid_t, + quote_nonce: sgx_quote_nonce_t, + quote_length: u32, + ) -> EnclaveResult<(sgx_report_t, Vec)> { + let (p_sig_rl, sig_rl_size) = utils::vec_to_c_pointer_with_len(revocation_list); + let p_report = &report as *const sgx_report_t; + let p_spid = &spid as *const sgx_spid_t; + let p_nonce = "e_nonce as *const sgx_quote_nonce_t; + + let mut qe_report = sgx_report_t::default(); + let p_qe_report = &mut qe_report as *mut sgx_report_t; + + let mut return_quote_buf = vec![0u8; quote_length as usize]; + let p_quote = return_quote_buf.as_mut_ptr(); + + let ret = unsafe { + sgx_get_quote( + p_report, + quote_type, + p_spid, + p_nonce, + p_sig_rl, + sig_rl_size, + p_qe_report, + p_quote as *mut sgx_quote_t, + quote_length, + ) + }; + + ensure!(ret == sgx_status_t::SGX_SUCCESS, Error::Sgx(ret)); + + Ok((qe_report, return_quote_buf)) + } + + fn get_dcap_quote(&self, report: sgx_report_t, quote_size: u32) -> EnclaveResult> { + let mut quote_vec: Vec = vec![0; quote_size as usize]; + let qe3_ret = + unsafe { sgx_qe_get_quote(&report, quote_size, quote_vec.as_mut_ptr() as _) }; + + ensure!(qe3_ret == sgx_quote3_error_t::SGX_QL_SUCCESS, Error::SgxQuote(qe3_ret)); + + Ok(quote_vec) + } + + fn get_qve_report_on_quote( + &self, + quote: Vec, + current_time: i64, + quote_collateral: &sgx_ql_qve_collateral_t, + qve_report_info: sgx_ql_qe_report_info_t, + supplemental_data_size: u32, + ) -> EnclaveResult { + let mut collateral_expiration_status = 1u32; + let mut quote_verification_result = sgx_ql_qv_result_t::SGX_QL_QV_RESULT_OK; + let mut supplemental_data: Vec = vec![0; supplemental_data_size as usize]; + let mut qve_report_info_return_value: sgx_ql_qe_report_info_t = qve_report_info; + + // Set QvE (Quote verification Enclave) loading policy. + let dcap_ret = unsafe { + sgx_qv_set_enclave_load_policy(sgx_ql_request_policy_t::SGX_QL_EPHEMERAL) + }; + + if dcap_ret != sgx_quote3_error_t::SGX_QL_SUCCESS { + error!("sgx_qv_set_enclave_load_policy failed: {:#04x}", dcap_ret as u32); + return Err(Error::SgxQuote(dcap_ret)) + } + + // Retrieve supplemental data size from QvE. + let mut qve_supplemental_data_size = 0u32; + let dcap_ret = + unsafe { sgx_qv_get_quote_supplemental_data_size(&mut qve_supplemental_data_size) }; + + if dcap_ret != sgx_quote3_error_t::SGX_QL_SUCCESS { + error!("sgx_qv_get_quote_supplemental_data_size failed: {:?}", dcap_ret); + return Err(Error::SgxQuote(dcap_ret)) + } + if qve_supplemental_data_size != supplemental_data_size { + warn!("Quote supplemental data size is different between DCAP QVL and QvE, please make sure you installed DCAP QVL and QvE from same release."); + return Err(Error::Sgx(sgx_status_t::SGX_ERROR_INVALID_PARAMETER)) + } + + // Check if a collateral has been given, or if it's a simple zero assignment. + // If it's zero, let the pointer point to null. The collateral will then be retrieved + // directly by the QvE in `sgx_qv_verify_quote`. + let p_quote_collateral: *const sgx_ql_qve_collateral_t = + if quote_collateral.version == 0 { + std::ptr::null() + } else { + quote_collateral as *const sgx_ql_qve_collateral_t + }; + + // Call the QvE for quote verification + // here you can choose 'trusted' or 'untrusted' quote verification by specifying parameter '&qve_report_info' + // if '&qve_report_info' is NOT NULL, this API will call Intel QvE to verify quote + // if '&qve_report_info' is NULL, this API will call 'untrusted quote verify lib' to verify quote, + // this mode doesn't rely on SGX capable system, but the results can not be cryptographically authenticated + let dcap_ret = unsafe { + sgx_qv_verify_quote( + quote.as_ptr(), + quote.len() as u32, + p_quote_collateral, + current_time, + &mut collateral_expiration_status as *mut u32, + &mut quote_verification_result as *mut sgx_ql_qv_result_t, + &mut qve_report_info_return_value as *mut sgx_ql_qe_report_info_t, + supplemental_data_size, + supplemental_data.as_mut_ptr(), + ) + }; + + if sgx_quote3_error_t::SGX_QL_SUCCESS != dcap_ret { + error!("sgx_qv_verify_quote failed: {:?}", dcap_ret); + error!("quote_verification_result: {:?}", quote_verification_result); + return Err(Error::SgxQuote(dcap_ret)) + } + + // Check and print verification result. + match quote_verification_result { + sgx_ql_qv_result_t::SGX_QL_QV_RESULT_OK => { + // Check verification collateral expiration status. + // This value should be considered in your own attestation/verification policy. + if 0u32 == collateral_expiration_status { + info!("QvE verification completed successfully."); + } else { + warn!("QvE verification completed, but collateral is out of date based on 'expiration_check_date' you provided."); + } + }, + sgx_ql_qv_result_t::SGX_QL_QV_RESULT_CONFIG_NEEDED + | sgx_ql_qv_result_t::SGX_QL_QV_RESULT_OUT_OF_DATE + | sgx_ql_qv_result_t::SGX_QL_QV_RESULT_OUT_OF_DATE_CONFIG_NEEDED + | sgx_ql_qv_result_t::SGX_QL_QV_RESULT_SW_HARDENING_NEEDED + | sgx_ql_qv_result_t::SGX_QL_QV_RESULT_CONFIG_AND_SW_HARDENING_NEEDED => { + warn!( + "QvE verification completed with Non-terminal result: {:?}", + quote_verification_result + ); + }, + _ => { + error!( + "QvE verification completed with Terminal result: {:?}", + quote_verification_result + ); + }, + } + + // Check supplemental data. + if supplemental_data_size > 0 { + // For now we simply print it, no checks done. + let p_supplemental_data: *const sgx_ql_qv_supplemental_t = + supplemental_data.as_ptr() as *const sgx_ql_qv_supplemental_t; + let qv_supplemental_data: sgx_ql_qv_supplemental_t = + unsafe { *p_supplemental_data }; + info!( + "QvE verification: Supplemental data version: {}", + qv_supplemental_data.version + ); + } + + Ok(QveReport { + collateral_expiration_status, + quote_verification_result, + qve_report_info_return_value, + supplemental_data, + }) + } + + fn get_update_info( + &self, + platform_blob: sgx_platform_info_t, + enclave_trusted: i32, + ) -> EnclaveResult { + let mut update_info: sgx_update_info_bit_t = sgx_update_info_bit_t::default(); + + let result = unsafe { + sgx_report_attestation_status( + &platform_blob as *const sgx_platform_info_t, + enclave_trusted, + &mut update_info as *mut sgx_update_info_bit_t, + ) + }; + + ensure!(result == sgx_status_t::SGX_SUCCESS, Error::Sgx(result)); + + Ok(update_info) + } + } + + #[cfg(feature = "implement-ffi")] + impl TlsRemoteAttestation for Enclave { + fn run_state_provisioning_server( + &self, + socket_fd: c_int, + sign_type: sgx_quote_sign_type_t, + quoting_enclave_target_info: Option<&sgx_target_info_t>, + quote_size: Option<&u32>, + skip_ra: bool, + ) -> EnclaveResult<()> { + let mut retval = sgx_status_t::SGX_SUCCESS; + + let result = unsafe { + ffi::run_state_provisioning_server( + self.eid, + &mut retval, + socket_fd, + sign_type, + quoting_enclave_target_info, + quote_size, + skip_ra.into(), + ) + }; + + ensure!(result == sgx_status_t::SGX_SUCCESS, Error::Sgx(result)); + ensure!(retval == sgx_status_t::SGX_SUCCESS, Error::Sgx(retval)); + + Ok(()) + } + + fn request_state_provisioning( + &self, + socket_fd: c_int, + sign_type: sgx_quote_sign_type_t, + quoting_enclave_target_info: Option<&sgx_target_info_t>, + quote_size: Option<&u32>, + shard: &ShardIdentifier, + skip_ra: bool, + ) -> EnclaveResult<()> { + let mut retval = sgx_status_t::SGX_SUCCESS; + + let encoded_shard = shard.encode(); + + let result = unsafe { + ffi::request_state_provisioning( + self.eid, + &mut retval, + socket_fd, + sign_type, + quoting_enclave_target_info, + quote_size, + encoded_shard.as_ptr(), + encoded_shard.len() as u32, + skip_ra.into(), + ) + }; + + ensure!(result == sgx_status_t::SGX_SUCCESS, Error::Sgx(result)); + ensure!(retval == sgx_status_t::SGX_SUCCESS, Error::Sgx(retval)); + + Ok(()) + } + } + + fn create_system_path(file_name: &str) -> String { + info!("create_system_path:: file_name={}", &file_name); + let default_path = format!("{}{}", OS_SYSTEM_PATH, file_name); + + let full_path = find_library_by_name(file_name).unwrap_or(default_path); + + let c_terminated_path = format!("{}{}", full_path, C_STRING_ENDING); + info!("create_system_path:: created path={}", &c_terminated_path); + c_terminated_path + } + + fn find_library_by_name(lib_name: &str) -> Option { + use std::process::Command; + // ldconfig -p | grep libsgx_pce_logic.so.1 + + let ldconfig_output = Command::new("ldconfig").args(["-p"]).output().ok()?; + let possible_path = String::from_utf8(ldconfig_output.stdout) + .ok()? + .lines() + .filter(|line| line.contains(lib_name)) + .map(|lib_name_and_path| { + lib_name_and_path + .rsplit_once("=>") + .map(|(_, lib_path)| lib_path.trim().to_owned()) + }) + .next()?; + + possible_path + } + + fn set_ql_path(path_type: sgx_ql_path_type_t, path: &str) -> EnclaveResult<()> { + let ret_val = unsafe { sgx_ql_set_path(path_type, create_system_path(path).as_ptr() as _) }; + if ret_val != sgx_quote3_error_t::SGX_QL_SUCCESS { + error!("Could not set {:?}", path_type); + return Err(Error::SgxQuote(ret_val)) + } + Ok(()) + } + + fn set_qv_path(path_type: sgx_qv_path_type_t, path: &str) -> EnclaveResult<()> { + let ret_val = unsafe { sgx_qv_set_path(path_type, create_system_path(path).as_ptr() as _) }; + if ret_val != sgx_quote3_error_t::SGX_QL_SUCCESS { + error!("Could not set {:?}", path_type); + return Err(Error::SgxQuote(ret_val)) + } + Ok(()) + } + + #[allow(clippy::not_unsafe_ptr_arg_deref)] + /// Make sure that the `log_slice_ptr` points to a null terminated string. + // This function must not be marked as `unsafe`, because `sgx_ql_set_logging_callback` expects a safe (i.e. not `unsafe`) function. + pub extern "C" fn forward_qpl_log(log_level: sgx_ql_log_level_t, log_slice_ptr: *const c_char) { + if log_slice_ptr.is_null() { + error!("[QPL - ERROR], slice to print was NULL"); + return + } + // This is safe, as the previous block checks for `NULL` pointer. + let slice = unsafe { core::ffi::CStr::from_ptr(log_slice_ptr) }; + match log_level { + sgx_ql_log_level_t::SGX_QL_LOG_INFO => info!("[QPL - INFO], {:?}", slice), + sgx_ql_log_level_t::SGX_QL_LOG_ERROR => error!("[QPL - ERROR], {:?}", slice), + } + } +} diff --git a/bitacross-worker/core-primitives/enclave-api/src/sidechain.rs b/bitacross-worker/core-primitives/enclave-api/src/sidechain.rs new file mode 100644 index 0000000000..877460075b --- /dev/null +++ b/bitacross-worker/core-primitives/enclave-api/src/sidechain.rs @@ -0,0 +1,122 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::EnclaveResult; +use codec::Encode; +use itp_storage::StorageProof; +use itp_types::parentchain::ParentchainId; +use sp_runtime::generic::SignedBlock; + +/// trait for handling blocks on the side chain +pub trait Sidechain: Send + Sync + 'static { + /// Sync parentchain blocks and events. Execute pending tops + /// and events proof in the enclave. + fn sync_parentchain( + &self, + blocks: &[SignedBlock], + events: &[Vec], + events_proofs: &[StorageProof], + parentchain_id: &ParentchainId, + is_syncing: bool, + ) -> EnclaveResult<()>; + + fn execute_trusted_calls(&self) -> EnclaveResult<()>; + + // litentry + /// Ignore the parentchain block import validation until the given block number + /// TODO: use the generic Header::Number trait + fn ignore_parentchain_block_import_validation_until(&self, until: u32) -> EnclaveResult<()>; +} + +#[cfg(feature = "implement-ffi")] +mod impl_ffi { + use super::Sidechain; + use crate::{error::Error, Enclave, EnclaveResult}; + use codec::Encode; + use frame_support::ensure; + use itp_enclave_api_ffi as ffi; + use itp_storage::StorageProof; + use itp_types::parentchain::ParentchainId; + use sgx_types::sgx_status_t; + use sp_runtime::generic::SignedBlock; + + impl Sidechain for Enclave { + fn sync_parentchain( + &self, + blocks: &[SignedBlock], + events: &[Vec], + events_proofs: &[StorageProof], + parentchain_id: &ParentchainId, + is_syncing: bool, + ) -> EnclaveResult<()> { + let mut retval = sgx_status_t::SGX_SUCCESS; + let blocks_enc = blocks.encode(); + let events_enc = events.encode(); + let events_proofs_enc = events_proofs.encode(); + let parentchain_id_enc = parentchain_id.encode(); + + let result = unsafe { + ffi::sync_parentchain( + self.eid, + &mut retval, + blocks_enc.as_ptr(), + blocks_enc.len(), + events_enc.as_ptr(), + events_enc.len(), + events_proofs_enc.as_ptr(), + events_proofs_enc.len(), + parentchain_id_enc.as_ptr(), + parentchain_id_enc.len() as u32, + is_syncing.into(), + ) + }; + + ensure!(result == sgx_status_t::SGX_SUCCESS, Error::Sgx(result)); + ensure!(retval == sgx_status_t::SGX_SUCCESS, Error::Sgx(retval)); + + Ok(()) + } + + fn execute_trusted_calls(&self) -> EnclaveResult<()> { + let mut retval = sgx_status_t::SGX_SUCCESS; + + let result = unsafe { ffi::execute_trusted_calls(self.eid, &mut retval) }; + + ensure!(result == sgx_status_t::SGX_SUCCESS, Error::Sgx(result)); + ensure!(retval == sgx_status_t::SGX_SUCCESS, Error::Sgx(retval)); + + Ok(()) + } + + fn ignore_parentchain_block_import_validation_until( + &self, + until: u32, + ) -> EnclaveResult<()> { + let mut retval = sgx_status_t::SGX_SUCCESS; + + let result = unsafe { + ffi::ignore_parentchain_block_import_validation_until(self.eid, &mut retval, &until) + }; + + ensure!(result == sgx_status_t::SGX_SUCCESS, Error::Sgx(result)); + ensure!(retval == sgx_status_t::SGX_SUCCESS, Error::Sgx(retval)); + + Ok(()) + } + } +} diff --git a/bitacross-worker/core-primitives/enclave-api/src/teeracle_api.rs b/bitacross-worker/core-primitives/enclave-api/src/teeracle_api.rs new file mode 100644 index 0000000000..530e2ff127 --- /dev/null +++ b/bitacross-worker/core-primitives/enclave-api/src/teeracle_api.rs @@ -0,0 +1,114 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::EnclaveResult; + +pub trait TeeracleApi: Send + Sync + 'static { + /// Update the currency market data for the token oracle. + fn update_market_data_xt( + &self, + crypto_currency: &str, + fiat_currency: &str, + ) -> EnclaveResult>; + + /// Update weather data for the corresponding coordinates. + fn update_weather_data_xt(&self, longitude: &str, latitude: &str) -> EnclaveResult>; +} + +#[cfg(feature = "implement-ffi")] +mod impl_ffi { + use super::TeeracleApi; + use crate::{error::Error, Enclave, EnclaveResult}; + use codec::Encode; + use frame_support::ensure; + use itp_enclave_api_ffi as ffi; + use log::*; + use sgx_types::*; + impl TeeracleApi for Enclave { + fn update_market_data_xt( + &self, + crypto_currency: &str, + fiat_currency: &str, + ) -> EnclaveResult> { + info!( + "TeeracleApi update_market_data_xt in with crypto {} and fiat {}", + crypto_currency, fiat_currency + ); + let mut retval = sgx_status_t::SGX_SUCCESS; + let response_max_len = 8192; + let mut response: Vec = vec![0u8; response_max_len as usize]; + let mut response_len: u32 = 0; + + let crypto_curr = crypto_currency.encode(); + let fiat_curr = fiat_currency.encode(); + + let res = unsafe { + ffi::update_market_data_xt( + self.eid, + &mut retval, + crypto_curr.as_ptr(), + crypto_curr.len() as u32, + fiat_curr.as_ptr(), + fiat_curr.len() as u32, + response.as_mut_ptr(), + response_max_len, + &mut response_len as *mut u32, + ) + }; + + ensure!(res == sgx_status_t::SGX_SUCCESS, Error::Sgx(res)); + ensure!(retval == sgx_status_t::SGX_SUCCESS, Error::Sgx(retval)); + + Ok(Vec::from(&response[..response_len as usize])) + } + fn update_weather_data_xt( + &self, + longitude: &str, + latitude: &str, + ) -> EnclaveResult> { + info!( + "TeeracleApi update_weather_data_xt in with latitude: {}, longitude: {}", + latitude, longitude + ); + let mut retval = sgx_status_t::SGX_SUCCESS; + let response_max_len = 8192; + let mut response: Vec = vec![0u8; response_max_len as usize]; + let mut response_len: u32 = 0; + + let longitude_encoded: Vec = longitude.encode(); + let latitude_encoded: Vec = latitude.encode(); + + let res = unsafe { + ffi::update_weather_data_xt( + self.eid, + &mut retval, + longitude_encoded.as_ptr(), + longitude_encoded.len() as u32, + latitude_encoded.as_ptr(), + latitude_encoded.len() as u32, + response.as_mut_ptr(), + response_max_len, + &mut response_len as *mut u32, + ) + }; + + ensure!(res == sgx_status_t::SGX_SUCCESS, Error::Sgx(res)); + ensure!(retval == sgx_status_t::SGX_SUCCESS, Error::Sgx(retval)); + Ok(Vec::from(&response[..response_len as usize])) + } + } +} diff --git a/bitacross-worker/core-primitives/enclave-api/src/utils.rs b/bitacross-worker/core-primitives/enclave-api/src/utils.rs new file mode 100644 index 0000000000..e36764f7ac --- /dev/null +++ b/bitacross-worker/core-primitives/enclave-api/src/utils.rs @@ -0,0 +1,27 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::ptr; + +pub fn vec_to_c_pointer_with_len(input: Vec) -> (*const A, u32) { + if input.is_empty() { + (ptr::null(), 0) + } else { + (input.as_ptr(), input.len() as u32) + } +} diff --git a/bitacross-worker/core-primitives/enclave-bridge-storage/Cargo.toml b/bitacross-worker/core-primitives/enclave-bridge-storage/Cargo.toml new file mode 100644 index 0000000000..8b191f3458 --- /dev/null +++ b/bitacross-worker/core-primitives/enclave-bridge-storage/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "itp-enclave-bridge-storage" +version = "0.9.0" +authors = ["Integritee AG "] +edition = "2021" + +[dependencies] +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +sp-std = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } + +#local deps +itp-storage = { path = "../storage", default-features = false } + +[features] +default = ["std"] +std = [ + "codec/std", + "sp-std/std", + "itp-storage/std", +] diff --git a/bitacross-worker/core-primitives/enclave-bridge-storage/src/lib.rs b/bitacross-worker/core-primitives/enclave-bridge-storage/src/lib.rs new file mode 100644 index 0000000000..9077d756b6 --- /dev/null +++ b/bitacross-worker/core-primitives/enclave-bridge-storage/src/lib.rs @@ -0,0 +1,31 @@ +#![cfg_attr(not(feature = "std"), no_std)] + +use codec::Encode; +use itp_storage::{storage_map_key, StorageHasher}; +use sp_std::prelude::Vec; + +pub struct EnclaveBridgeStorage; + +// Separate the prefix from the rest because in our case we changed the storage prefix due to +// the rebranding. With the below implementation of the `TeerexStorageKeys`, we could simply +// define another struct `OtherStorage`, implement `StoragePrefix` for it, and get the +// `TeerexStorageKeys` implementation for free. +pub trait StoragePrefix { + fn prefix() -> &'static str; +} + +impl StoragePrefix for EnclaveBridgeStorage { + fn prefix() -> &'static str { + "EnclaveBridge" + } +} + +pub trait EnclaveBridgeStorageKeys { + fn shard_status(shard: T) -> Vec; +} + +impl EnclaveBridgeStorageKeys for S { + fn shard_status(shard: T) -> Vec { + storage_map_key(Self::prefix(), "ShardStatus", &shard, &StorageHasher::Blake2_128Concat) + } +} diff --git a/bitacross-worker/core-primitives/enclave-metrics/Cargo.toml b/bitacross-worker/core-primitives/enclave-metrics/Cargo.toml new file mode 100644 index 0000000000..b6f3ae3e29 --- /dev/null +++ b/bitacross-worker/core-primitives/enclave-metrics/Cargo.toml @@ -0,0 +1,25 @@ +[package] +name = "itp-enclave-metrics" +version = "0.9.0" +authors = ['Trust Computing GmbH ', 'Integritee AG '] +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +# sgx +sgx_tstd = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git", optional = true } + +# no-std dependencies +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive", "full"] } +substrate-fixed = { default-features = false, git = "https://github.com/encointer/substrate-fixed", tag = "v0.5.9" } + +[features] +default = ["std"] +std = [ + "substrate-fixed/std", + "codec/std", +] +sgx = [ + "sgx_tstd", +] diff --git a/bitacross-worker/core-primitives/enclave-metrics/src/lib.rs b/bitacross-worker/core-primitives/enclave-metrics/src/lib.rs new file mode 100644 index 0000000000..ae7f253adc --- /dev/null +++ b/bitacross-worker/core-primitives/enclave-metrics/src/lib.rs @@ -0,0 +1,68 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg(all(feature = "std", feature = "sgx"))] +compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the same time"); + +extern crate core; +#[cfg(all(not(feature = "std"), feature = "sgx"))] +extern crate sgx_tstd as std; + +use codec::{Decode, Encode}; +use core::time::Duration; +use std::string::String; +use substrate_fixed::types::U32F32; + +// FIXME: Copied from ita-oracle because of cyclic deps. Should be removed after integritee-network/pallets#71 +pub type ExchangeRate = U32F32; + +#[derive(Encode, Decode, Debug)] +pub enum EnclaveMetric { + SetSidechainBlockHeight(u64), + TopPoolSizeSet(u64), + TopPoolSizeIncrement, + TopPoolSizeDecrement, + ExchangeRateOracle(ExchangeRateOracleMetric), + SuccessfulTrustedOperationIncrement(String), + FailedTrustedOperationIncrement(String), + ParentchainBlockImportTime(Duration), + SidechainBlockImportTime(Duration), + SidechainSlotPrepareTime(Duration), + SidechainSlotStfExecutionTime(Duration), + SidechainSlotBlockCompositionTime(Duration), + SidechainBlockBroadcastingTime(Duration), + // OracleMetric(OracleMetric), +} + +#[derive(Encode, Decode, Debug)] +pub enum ExchangeRateOracleMetric { + /// Exchange Rate from CoinGecko - (Source, TradingPair, ExchangeRate) + ExchangeRate(String, String, ExchangeRate), + /// Response time of the request in [ms]. (Source, ResponseTime) + ResponseTime(String, u128), + /// Increment the number of requests (Source) + NumberRequestsIncrement(String), +} + +#[derive(Encode, Decode, Debug)] +pub enum OracleMetric { + OracleSpecificMetric(MetricsInfo), + ResponseTime(String, u128), + NumberRequestsIncrement(String), +} diff --git a/bitacross-worker/core-primitives/extrinsics-factory/Cargo.toml b/bitacross-worker/core-primitives/extrinsics-factory/Cargo.toml new file mode 100644 index 0000000000..56ae7283d1 --- /dev/null +++ b/bitacross-worker/core-primitives/extrinsics-factory/Cargo.toml @@ -0,0 +1,46 @@ +[package] +name = "itp-extrinsics-factory" +version = "0.9.0" +authors = ['Trust Computing GmbH ', 'Integritee AG '] +edition = "2021" + +[dependencies] +# sgx dependencies +sgx_tstd = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git", optional = true } +sgx_types = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git" } +substrate-api-client = { default-features = false, features = ["sync-api"], git = "https://github.com/scs/substrate-api-client.git", branch = "polkadot-v0.9.42-tag-v0.14.0" } + +# local dependencies +itp-node-api = { path = "../node-api", default-features = false } +itp-nonce-cache = { path = "../nonce-cache", default-features = false } +itp-types = { path = "../types", default-features = false } + +# sgx enabled external libraries +thiserror_sgx = { package = "thiserror", git = "https://github.com/mesalock-linux/thiserror-sgx", tag = "sgx_1.1.3", optional = true } + +# std compatible external libraries (make sure these versions match with the sgx-enabled ones above) +thiserror = { version = "1.0", optional = true } + +# no-std dependencies +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +log = { version = "0.4", default-features = false } +sp-core = { default-features = false, features = ["full_crypto"], git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } +sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } + +[features] +default = ["std"] +std = [ + "itp-node-api/std", + "itp-nonce-cache/std", + "itp-types/std", + "log/std", + "substrate-api-client/std", + "thiserror", +] +sgx = [ + "itp-node-api/sgx", + "itp-nonce-cache/sgx", + "sgx_tstd", + "thiserror_sgx", +] +mocks = [] diff --git a/bitacross-worker/core-primitives/extrinsics-factory/src/error.rs b/bitacross-worker/core-primitives/extrinsics-factory/src/error.rs new file mode 100644 index 0000000000..4f052b9f94 --- /dev/null +++ b/bitacross-worker/core-primitives/extrinsics-factory/src/error.rs @@ -0,0 +1,49 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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(all(not(feature = "std"), feature = "sgx"))] +use crate::sgx_reexport_prelude::*; + +use sgx_types::sgx_status_t; +use std::{boxed::Box, format}; + +pub type Result = core::result::Result; + +/// extrinsics factory error +#[derive(Debug, thiserror::Error)] +pub enum Error { + #[error("Nonce cache error: {0}")] + NonceCache(#[from] itp_nonce_cache::error::Error), + #[error("Node API error: {0:?}")] + NodeMetadataProvider(#[from] itp_node_api::metadata::provider::Error), + #[error("SGX error, status: {0}")] + Sgx(sgx_status_t), + #[error(transparent)] + Other(#[from] Box), +} + +impl From for Error { + fn from(sgx_status: sgx_status_t) -> Self { + Self::Sgx(sgx_status) + } +} + +impl From for Error { + fn from(e: codec::Error) -> Self { + Self::Other(format!("{:?}", e).into()) + } +} diff --git a/bitacross-worker/core-primitives/extrinsics-factory/src/lib.rs b/bitacross-worker/core-primitives/extrinsics-factory/src/lib.rs new file mode 100644 index 0000000000..dd4180fee8 --- /dev/null +++ b/bitacross-worker/core-primitives/extrinsics-factory/src/lib.rs @@ -0,0 +1,241 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg(all(feature = "std", feature = "sgx"))] +compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the same time"); + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +extern crate sgx_tstd as std; + +// re-export module to properly feature gate sgx and regular std environment +#[cfg(all(not(feature = "std"), feature = "sgx"))] +pub mod sgx_reexport_prelude { + pub use thiserror_sgx as thiserror; +} + +use codec::Encode; +use error::Result; +use itp_node_api::{ + api_client::{ + ExtrinsicParams, ParentchainAdditionalParams, ParentchainExtrinsicParams, SignExtrinsic, + }, + metadata::{provider::AccessNodeMetadata, NodeMetadata}, +}; +use itp_nonce_cache::{MutateNonce, Nonce}; +use itp_types::{parentchain::AccountId, OpaqueCall}; +use sp_core::H256; +use sp_runtime::{generic::Era, OpaqueExtrinsic}; +use std::{sync::Arc, vec::Vec}; +use substrate_api_client::ac_compose_macros::compose_extrinsic_offline; + +pub mod error; + +#[cfg(feature = "mocks")] +pub mod mock; + +/// Create extrinsics from opaque calls +/// +/// Also increases the nonce counter for each extrinsic that is created. +pub trait CreateExtrinsics { + fn create_extrinsics( + &self, + calls: &[OpaqueCall], + extrinsics_params: Option, + ) -> Result>; +} + +/// Extrinsics factory +pub struct ExtrinsicsFactory +where + Signer: SignExtrinsic, + NonceCache: MutateNonce, + NodeMetadataRepository: AccessNodeMetadata, +{ + genesis_hash: H256, + signer: Signer, + nonce_cache: Arc, + node_metadata_repository: Arc, +} + +impl + ExtrinsicsFactory +where + Signer: SignExtrinsic, + NonceCache: MutateNonce, + NodeMetadataRepository: AccessNodeMetadata, +{ + pub fn new( + genesis_hash: H256, + signer: Signer, + nonce_cache: Arc, + node_metadata_repository: Arc, + ) -> Self { + ExtrinsicsFactory { genesis_hash, signer, nonce_cache, node_metadata_repository } + } + + pub fn with_signer(&self, signer: Signer, nonce_cache: Arc) -> Self { + ExtrinsicsFactory { + genesis_hash: self.genesis_hash, + signer, + nonce_cache, + node_metadata_repository: self.node_metadata_repository.clone(), + } + } +} + +impl CreateExtrinsics + for ExtrinsicsFactory +where + Signer: SignExtrinsic, + NonceCache: MutateNonce, + NodeMetadataRepository: AccessNodeMetadata, +{ + fn create_extrinsics( + &self, + calls: &[OpaqueCall], + extrinsics_params: Option, + ) -> Result> { + let mut nonce_lock = self.nonce_cache.load_for_mutation()?; + let mut nonce_value = nonce_lock.0; + + let additional_extrinsic_params = extrinsics_params.unwrap_or_else(|| { + ParentchainAdditionalParams::new().era(Era::Immortal, self.genesis_hash).tip(0) + }); + + let (runtime_spec_version, runtime_transaction_version) = + self.node_metadata_repository.get_from_metadata(|m| { + (m.get_runtime_version(), m.get_runtime_transaction_version()) + })?; + + let extrinsics_buffer: Vec = calls + .iter() + .map(|call| { + log::info!("Creating extrinsics using nonce: {}", nonce_value); + let extrinsic_params = ParentchainExtrinsicParams::new( + runtime_spec_version, + runtime_transaction_version, + nonce_value, + self.genesis_hash, + additional_extrinsic_params, + ); + let xt = compose_extrinsic_offline!(&self.signer, call, extrinsic_params).encode(); + nonce_value += 1; + xt + }) + .map(|xt| { + OpaqueExtrinsic::from_bytes(&xt) + .expect("A previously encoded extrinsic has valid codec; qed.") + }) + .collect(); + + *nonce_lock = Nonce(nonce_value); + + Ok(extrinsics_buffer) + } +} + +#[cfg(test)] +pub mod tests { + + use super::*; + use itp_node_api::{ + api_client::{PairSignature, StaticExtrinsicSigner}, + metadata::provider::NodeMetadataRepository, + }; + use itp_nonce_cache::{GetNonce, Nonce, NonceCache, NonceValue}; + use sp_core::{ed25519, Pair}; + //use substrate_api_client::extrinsic::xt_primitives::UncheckedExtrinsicV4; + + #[test] + pub fn creating_xts_increases_nonce_for_each_xt() { + let nonce_cache = Arc::new(NonceCache::default()); + let node_metadata_repo = Arc::new(NodeMetadataRepository::new(NodeMetadata::default())); + let extrinsics_factory = ExtrinsicsFactory::new( + test_genesis_hash(), + StaticExtrinsicSigner::<_, PairSignature>::new(test_account()), + nonce_cache.clone(), + node_metadata_repo, + ); + + let opaque_calls = [OpaqueCall(vec![3u8; 42]), OpaqueCall(vec![12u8, 78])]; + let xts = extrinsics_factory.create_extrinsics(&opaque_calls, None).unwrap(); + + assert_eq!(opaque_calls.len(), xts.len()); + assert_eq!(nonce_cache.get_nonce().unwrap(), Nonce(opaque_calls.len() as NonceValue)); + } + + #[test] + pub fn with_signer_works() { + let nonce_cache1 = Arc::new(NonceCache::default()); + *nonce_cache1.load_for_mutation().unwrap() = Nonce(42); + + let node_metadata_repo = Arc::new(NodeMetadataRepository::new(NodeMetadata::default())); + let extrinsics_factory = ExtrinsicsFactory::new( + test_genesis_hash(), + StaticExtrinsicSigner::<_, PairSignature>::new(test_account()), + nonce_cache1.clone(), + node_metadata_repo, + ); + + let nonce_cache2 = Arc::new(NonceCache::default()); + let extrinsics_factory = extrinsics_factory.with_signer( + StaticExtrinsicSigner::<_, PairSignature>::new(test_account2()), + nonce_cache2.clone(), + ); + + let opaque_calls = [OpaqueCall(vec![3u8; 42]), OpaqueCall(vec![12u8, 78])]; + let xts = extrinsics_factory.create_extrinsics(&opaque_calls, None).unwrap(); + + assert_eq!(opaque_calls.len(), xts.len()); + assert_eq!(nonce_cache2.get_nonce().unwrap(), Nonce(opaque_calls.len() as NonceValue)); + assert_eq!(nonce_cache1.get_nonce().unwrap(), Nonce(42)); + } + + // #[test] + // pub fn xts_have_increasing_nonce() { + // let nonce_cache = Arc::new(NonceCache::default()); + // nonce_cache.set_nonce(Nonce(34)).unwrap(); + // let extrinsics_factory = + // ExtrinsicsFactory::new(test_genesis_hash(), test_account(), nonce_cache); + // + // let opaque_calls = + // [OpaqueCall(vec![3u8; 42]), OpaqueCall(vec![12u8, 78]), OpaqueCall(vec![15u8, 12])]; + // let xts: Vec> = extrinsics_factory + // .create_extrinsics(&opaque_calls) + // .unwrap() + // .iter() + // .map(|mut x| UncheckedExtrinsicV4::::decode(&mut x)) + // .collect(); + // + // assert_eq!(xts.len(), opaque_calls.len()); + // assert_eq!(xts[0].signature.unwrap().2 .2, 34u128); + // } + + fn test_account() -> ed25519::Pair { + ed25519::Pair::from_seed(b"42315678901234567890123456789012") + } + + fn test_account2() -> ed25519::Pair { + ed25519::Pair::from_seed(b"12315678901234567890123456789012") + } + + fn test_genesis_hash() -> H256 { + H256::from_slice(&[56u8; 32]) + } +} diff --git a/bitacross-worker/core-primitives/extrinsics-factory/src/mock.rs b/bitacross-worker/core-primitives/extrinsics-factory/src/mock.rs new file mode 100644 index 0000000000..4e1923210e --- /dev/null +++ b/bitacross-worker/core-primitives/extrinsics-factory/src/mock.rs @@ -0,0 +1,46 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{error::Result, CreateExtrinsics}; +use itp_node_api::api_client::ParentchainAdditionalParams; +use itp_types::OpaqueCall; +use sp_runtime::OpaqueExtrinsic; +use std::vec::Vec; + +/// Mock of an extrinsics factory. To be used in unit tests. +/// +/// Returns an empty extrinsic. +#[derive(Default, Clone)] +pub struct ExtrinsicsFactoryMock; + +impl CreateExtrinsics for ExtrinsicsFactoryMock { + fn create_extrinsics( + &self, + _calls: &[OpaqueCall], + _additional_params: Option, + ) -> Result> { + // Intention was to map an OpaqueCall to some dummy OpaqueExtrinsic, + // so the output vector has the same size as the input one (and thus can be tested from the outside). + // However, it doesn't seem to be possible to construct an empty of dummy OpaqueExtrinsic, + // `from_bytes` expects a valid encoded OpaqueExtrinsic. + // Ok(calls + // .iter() + // .map(|_| OpaqueExtrinsic::from_bytes(Vec::new().as_slice()).unwrap()) + // .collect()) + Ok(Vec::new()) + } +} diff --git a/bitacross-worker/core-primitives/hashing/Cargo.toml b/bitacross-worker/core-primitives/hashing/Cargo.toml new file mode 100644 index 0000000000..5caa95d92b --- /dev/null +++ b/bitacross-worker/core-primitives/hashing/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "itp-hashing" +version = "0.9.0" +authors = ['Trust Computing GmbH ', 'Integritee AG '] +edition = "2021" + +[dependencies] +# substrate +sp-core = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } + +[features] +default = ["std"] +std = [] diff --git a/bitacross-worker/core-primitives/hashing/src/lib.rs b/bitacross-worker/core-primitives/hashing/src/lib.rs new file mode 100644 index 0000000000..6e44afbcaa --- /dev/null +++ b/bitacross-worker/core-primitives/hashing/src/lib.rs @@ -0,0 +1,46 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 traits and utilities. + +#![cfg_attr(not(feature = "std"), no_std)] + +use sp_core::H256; + +#[cfg(feature = "std")] +pub mod std_hash; + +/// Trait to compute a hash of self. +pub trait Hash { + fn hash(&self) -> Output; +} + +// Cannot use the implementation below unfortunately, because our externalities +// have their own hash implementation which ignores the state diff. +// /// Implement Hash for any types that implement encode. +// /// +// /// +// impl Hash for T { +// fn hash(&self) -> H256 { +// blake2_256(&self.encode()).into() +// } +// } + +pub fn hash_from_slice(hash_slize: &[u8]) -> H256 { + let mut g = [0; 32]; + g.copy_from_slice(hash_slize); + H256::from(&mut g) +} diff --git a/bitacross-worker/core-primitives/hashing/src/std_hash.rs b/bitacross-worker/core-primitives/hashing/src/std_hash.rs new file mode 100644 index 0000000000..2a6524a800 --- /dev/null +++ b/bitacross-worker/core-primitives/hashing/src/std_hash.rs @@ -0,0 +1,31 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::Hash; +use std::{ + collections::hash_map::DefaultHasher, + hash::{Hash as StdHash, Hasher}, +}; + +/// Implement Hash for all types implementing core::hash::Hash. +impl Hash for T { + fn hash(&self) -> u64 { + let mut hasher = DefaultHasher::new(); + self.hash(&mut hasher); + hasher.finish() + } +} diff --git a/bitacross-worker/core-primitives/import-queue/Cargo.toml b/bitacross-worker/core-primitives/import-queue/Cargo.toml new file mode 100644 index 0000000000..2d358d8102 --- /dev/null +++ b/bitacross-worker/core-primitives/import-queue/Cargo.toml @@ -0,0 +1,32 @@ +[package] +name = "itp-import-queue" +version = "0.8.0" +authors = ['Trust Computing GmbH ', 'Integritee AG '] +edition = "2021" + +[dependencies] +# sgx dependencies +sgx_tstd = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git", optional = true } +sgx_types = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git" } + +# sgx enabled external libraries +thiserror_sgx = { package = "thiserror", git = "https://github.com/mesalock-linux/thiserror-sgx", tag = "sgx_1.1.3", optional = true } + +# crates.io std-only compatible external libraries (make sure these versions match with the sgx-enabled ones above) +thiserror = { version = "1.0", optional = true } + +# crates.io no-std compatible libraries + +[features] +default = ["std"] +std = [ + # no-std compatible libraries + # std compatible external libraries + "thiserror", +] +sgx = [ + # sgx + "sgx_tstd", + # sgx enabled external libraries + "thiserror_sgx", +] diff --git a/bitacross-worker/core-primitives/import-queue/src/error.rs b/bitacross-worker/core-primitives/import-queue/src/error.rs new file mode 100644 index 0000000000..c1492cf550 --- /dev/null +++ b/bitacross-worker/core-primitives/import-queue/src/error.rs @@ -0,0 +1,41 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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(all(not(feature = "std"), feature = "sgx"))] +use crate::sgx_reexport_prelude::*; + +use sgx_types::sgx_status_t; +use std::boxed::Box; + +pub type Result = core::result::Result; + +/// Parentchain block importer error. +#[derive(Debug, thiserror::Error)] +pub enum Error { + #[error("SGX error, status: {0}")] + Sgx(sgx_status_t), + #[error("Queue lock is poisoned")] + PoisonedLock, + #[error(transparent)] + Other(#[from] Box), +} + +impl From for Error { + fn from(sgx_status: sgx_status_t) -> Self { + Self::Sgx(sgx_status) + } +} diff --git a/bitacross-worker/core-primitives/import-queue/src/import_queue.rs b/bitacross-worker/core-primitives/import-queue/src/import_queue.rs new file mode 100644 index 0000000000..2555d3b5a3 --- /dev/null +++ b/bitacross-worker/core-primitives/import-queue/src/import_queue.rs @@ -0,0 +1,273 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 implementation + +#[cfg(feature = "sgx")] +use std::sync::SgxRwLock as RwLock; + +#[cfg(feature = "std")] +use std::sync::RwLock; + +use crate::{ + error::{Error, Result}, + PeekQueue, PopFromQueue, PushToQueue, +}; +use std::{collections::VecDeque, vec::Vec}; + +/// Any import queue. +/// +/// Uses RwLock internally to guard against concurrent access and ensure all operations are atomic. +pub struct ImportQueue { + queue: RwLock>, +} + +impl ImportQueue { + pub fn is_empty(&self) -> Result { + let queue_lock = self.queue.read().map_err(|_| Error::PoisonedLock)?; + Ok(queue_lock.is_empty()) + } +} + +impl Default for ImportQueue { + fn default() -> Self { + ImportQueue { queue: Default::default() } + } +} + +impl PushToQueue for ImportQueue { + fn push_multiple(&self, items: Vec) -> Result<()> { + let mut queue_lock = self.queue.write().map_err(|_| Error::PoisonedLock)?; + queue_lock.extend(items); + Ok(()) + } + + fn push_single(&self, item: Item) -> Result<()> { + let mut queue_lock = self.queue.write().map_err(|_| Error::PoisonedLock)?; + queue_lock.push_back(item); + Ok(()) + } +} + +impl PopFromQueue for ImportQueue { + type ItemType = Item; + + fn pop_all_but_last(&self) -> Result> { + let mut queue_lock = self.queue.write().map_err(|_| Error::PoisonedLock)?; + let queue_length = queue_lock.len(); + if queue_length < 2 { + return Ok(Vec::::default()) + } + Ok(queue_lock.drain(..queue_length - 1).collect::>()) + } + + fn pop_all(&self) -> Result> { + let mut queue_lock = self.queue.write().map_err(|_| Error::PoisonedLock)?; + Ok(queue_lock.drain(..).collect::>()) + } + + fn pop_until(&self, predicate: Predicate) -> Result> + where + Predicate: FnMut(&Self::ItemType) -> bool, + { + let mut queue_lock = self.queue.write().map_err(|_| Error::PoisonedLock)?; + match queue_lock.iter().position(predicate) { + None => Ok(Vec::new()), + Some(p) => Ok(queue_lock.drain(..p + 1).collect::>()), + } + } + + fn pop_front(&self) -> Result> { + let mut queue_lock = self.queue.write().map_err(|_| Error::PoisonedLock)?; + Ok(queue_lock.pop_front()) + } + + fn pop_from_front_until(&self, amount: usize) -> Result> { + let mut queue_lock = self.queue.write().map_err(|_| Error::PoisonedLock)?; + if amount > queue_lock.len() { + return Err(Error::Other( + "Cannot Pop more items from the queue than are available".into(), + )) + } + Ok(queue_lock.drain(..amount).collect::>()) + } +} + +impl PeekQueue for ImportQueue +where + Item: Clone, +{ + type ItemType = Item; + + fn peek_find(&self, predicate: Predicate) -> Result> + where + Predicate: Fn(&Self::ItemType) -> bool, + { + let queue_lock = self.queue.read().map_err(|_| Error::PoisonedLock)?; + let maybe_item = queue_lock.iter().find(|&b| predicate(b)); + Ok(maybe_item.cloned()) + } + + fn peek_last(&self) -> Result> { + let queue_lock = self.queue.read().map_err(|_| Error::PoisonedLock)?; + Ok(queue_lock.back().cloned()) + } + + fn peek_queue_size(&self) -> Result { + let queue_lock = self.queue.read().map_err(|_| Error::PoisonedLock)?; + Ok(queue_lock.len()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use core::assert_matches::assert_matches; + + type TestBlock = u32; + + #[test] + fn default_queue_is_empty() { + let queue = ImportQueue::::default(); + assert!(queue.is_empty().unwrap()); + } + + #[test] + fn pop_all_on_default_returns_empty_vec() { + let queue = ImportQueue::::default(); + assert!(queue.pop_all().unwrap().is_empty()); + } + + #[test] + fn after_inserting_queue_is_not_empty() { + let queue = ImportQueue::::default(); + queue.push_single(TestBlock::default()).unwrap(); + assert!(!queue.is_empty().unwrap()); + } + + #[test] + fn pop_all_after_inserting_leaves_empty_queue() { + let queue = ImportQueue::::default(); + queue + .push_multiple(vec![TestBlock::default(), TestBlock::default(), TestBlock::default()]) + .unwrap(); + + let all_popped = queue.pop_all().unwrap(); + assert_eq!(3, all_popped.len()); + assert!(queue.is_empty().unwrap()); + } + + #[test] + fn pop_all_except_last_on_default_returns_empty_vec() { + let queue = ImportQueue::::default(); + assert!(queue.pop_all_but_last().unwrap().is_empty()); + } + + #[test] + fn pop_all_except_last_with_single_element_returns_empty_vec() { + let queue = ImportQueue::::default(); + queue.push_single(TestBlock::default()).unwrap(); + assert!(queue.pop_all_but_last().unwrap().is_empty()); + } + + #[test] + fn pop_all_except_last_with_multiple_elements_returns_all_but_last_inserted() { + let queue = ImportQueue::::default(); + queue.push_multiple(vec![1, 3, 5, 7]).unwrap(); + assert_eq!(3, queue.pop_all_but_last().unwrap().len()); + assert!(!queue.is_empty().unwrap()); + assert_eq!(7, queue.pop_all().unwrap()[0]); + } + + #[test] + fn pop_until_returns_empty_vec_if_nothing_matches() { + let queue = ImportQueue::::default(); + queue.push_multiple(vec![1, 3, 5, 7]).unwrap(); + + let popped_elements = queue.pop_until(|i| i > &10u32).unwrap(); + assert!(popped_elements.is_empty()); + } + + #[test] + fn pop_until_returns_elements_until_and_including_match() { + let queue = ImportQueue::::default(); + queue.push_multiple(vec![1, 2, 3, 10]).unwrap(); + + assert_eq!(queue.pop_until(|i| i == &3).unwrap(), vec![1, 2, 3]); + } + + #[test] + fn pop_until_returns_all_elements_if_last_matches() { + let queue = ImportQueue::::default(); + queue.push_multiple(vec![1, 2, 3, 10]).unwrap(); + + assert_eq!(queue.pop_until(|i| i == &10).unwrap(), vec![1, 2, 3, 10]); + } + + #[test] + fn pop_until_returns_first_element_if_it_matches() { + let queue = ImportQueue::::default(); + queue.push_single(4).unwrap(); + assert_eq!(queue.pop_until(|i| i == &4).unwrap(), vec![4]) + } + + #[test] + fn pop_front_returns_none_if_queue_is_empty() { + let queue = ImportQueue::::default(); + assert_matches!(queue.pop_front().unwrap(), None); + } + + #[test] + fn pop_front_works() { + let queue = ImportQueue::::default(); + queue.push_multiple(vec![1, 2, 3, 5]).unwrap(); + assert_eq!(queue.pop_front().unwrap(), Some(1)); + assert_eq!(queue.pop_front().unwrap(), Some(2)); + assert_eq!(queue.pop_front().unwrap(), Some(3)); + assert_eq!(queue.pop_front().unwrap(), Some(5)); + assert_eq!(queue.pop_front().unwrap(), None); + } + + #[test] + fn peek_find_works() { + let queue = ImportQueue::::default(); + queue.push_multiple(vec![1, 2, 3, 5]).unwrap(); + + assert_eq!(None, queue.peek_find(|i| i == &4).unwrap()); + assert!(queue.peek_find(|i| i == &1).unwrap().is_some()); + assert!(queue.peek_find(|i| i == &5).unwrap().is_some()); + } + + #[test] + fn peek_find_on_empty_queue_returns_none() { + let queue = ImportQueue::::default(); + assert_eq!(None, queue.peek_find(|i| i == &1).unwrap()); + } + + #[test] + fn peek_last_works() { + let queue = ImportQueue::::default(); + queue.push_multiple(vec![1, 2, 3, 5, 6, 9, 10]).unwrap(); + assert_eq!(queue.peek_last().unwrap(), Some(10)); + } + + #[test] + fn peek_last_on_empty_queue_returns_none() { + let queue = ImportQueue::::default(); + assert_eq!(None, queue.peek_last().unwrap()); + } +} diff --git a/bitacross-worker/core-primitives/import-queue/src/lib.rs b/bitacross-worker/core-primitives/import-queue/src/lib.rs new file mode 100644 index 0000000000..d223317f78 --- /dev/null +++ b/bitacross-worker/core-primitives/import-queue/src/lib.rs @@ -0,0 +1,89 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ +//! Queueing of item imports. + +#![cfg_attr(not(feature = "std"), no_std)] +#![cfg_attr(test, feature(assert_matches))] + +#[cfg(all(feature = "std", feature = "sgx"))] +compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the same time"); + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +extern crate sgx_tstd as std; + +// re-export module to properly feature gate sgx and regular std environment +#[cfg(all(not(feature = "std"), feature = "sgx"))] +pub mod sgx_reexport_prelude { + pub use thiserror_sgx as thiserror; +} + +pub mod error; +pub mod import_queue; + +pub use import_queue::*; + +use error::Result; +use std::vec::Vec; + +/// Trait to push items such as blocks to an import queue. +pub trait PushToQueue { + /// Push multiple items to the queue, ordering from the Vec is preserved. + fn push_multiple(&self, item: Vec) -> Result<()>; + + /// Push a single item to the queue. + fn push_single(&self, item: Item) -> Result<()>; +} + +/// Trait to pop items from the import queue. +pub trait PopFromQueue { + type ItemType; + + /// Pop (i.e. removes and returns) all but the last item from the import queue. + fn pop_all_but_last(&self) -> Result>; + + /// Pop (i.e. removes and returns) all items from the import queue. + fn pop_all(&self) -> Result>; + + /// Pop (front) until specified item is found. If no item matches, empty Vec is returned. + fn pop_until(&self, predicate: Predicate) -> Result> + where + Predicate: Fn(&Self::ItemType) -> bool; + + /// Pop (front) queue. Returns None if queue is empty. + fn pop_front(&self) -> Result>; + + /// Pop (front) queue until a specific amount of pops has been reached + fn pop_from_front_until(&self, amount: usize) -> Result>; +} + +/// Trait to peek items in the import queue without altering the queue. +pub trait PeekQueue { + type ItemType: Clone; + + /// Search the queue with a given predicate and return a reference to the first element that matches. + /// Returns None if nothing matches. + fn peek_find(&self, predicate: Predicate) -> Result> + where + Predicate: Fn(&Self::ItemType) -> bool; + + /// Peeks the last element in the queue (aka the newest one, last to be popped). + /// Returns None if queue is empty. + fn peek_last(&self) -> Result>; + + /// Peek the queue size (i.e. number of elements the queue contains). + fn peek_queue_size(&self) -> Result; +} diff --git a/bitacross-worker/core-primitives/networking-utils/Cargo.toml b/bitacross-worker/core-primitives/networking-utils/Cargo.toml new file mode 100644 index 0000000000..c94ad8f685 --- /dev/null +++ b/bitacross-worker/core-primitives/networking-utils/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "itp-networking-utils" +version = "0.9.0" +authors = ['Trust Computing GmbH ', 'Integritee AG '] +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +# sgx dependencies +sgx_tstd = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git", optional = true } + +[features] +default = ["std"] +std = [ + +] +sgx = [ + "sgx_tstd", +] diff --git a/bitacross-worker/core-primitives/networking-utils/src/lib.rs b/bitacross-worker/core-primitives/networking-utils/src/lib.rs new file mode 100644 index 0000000000..46b8ab91d3 --- /dev/null +++ b/bitacross-worker/core-primitives/networking-utils/src/lib.rs @@ -0,0 +1,26 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg(all(feature = "std", feature = "sgx"))] +compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the same time"); + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +extern crate sgx_tstd as std; + +pub mod ports; diff --git a/bitacross-worker/core-primitives/networking-utils/src/ports.rs b/bitacross-worker/core-primitives/networking-utils/src/ports.rs new file mode 100644 index 0000000000..4b8a523b27 --- /dev/null +++ b/bitacross-worker/core-primitives/networking-utils/src/ports.rs @@ -0,0 +1,48 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{net::TcpListener, ops::Range}; + +/// Gets the first available port in a range. +/// Returns None if no port in range is available. +/// +pub fn get_available_port_in_range(mut port_range: Range) -> Option { + port_range.find(|port| port_is_available(*port)) +} + +fn port_is_available(port: u16) -> bool { + TcpListener::bind(("127.0.0.1", port)).is_ok() +} + +#[cfg(test)] +mod tests { + use super::*; + use std::mem::drop; + + #[test] + fn port_is_not_available_when_bound() { + let available_port = get_available_port_in_range(12000..13000).unwrap(); + + let tcp_listener = TcpListener::bind(("127.0.0.1", available_port)).unwrap(); + + assert!(!port_is_available(available_port)); + + drop(tcp_listener); + + assert!(port_is_available(available_port)); + } +} diff --git a/bitacross-worker/core-primitives/node-api/Cargo.toml b/bitacross-worker/core-primitives/node-api/Cargo.toml new file mode 100644 index 0000000000..b836b98427 --- /dev/null +++ b/bitacross-worker/core-primitives/node-api/Cargo.toml @@ -0,0 +1,28 @@ +[package] +name = "itp-node-api" +version = "0.9.0" +authors = ['Trust Computing GmbH ', 'Integritee AG '] +edition = "2021" + +[dependencies] +itp-api-client-extensions = { optional = true, path = "api-client-extensions" } +itp-api-client-types = { default-features = false, path = "api-client-types" } +itp-node-api-factory = { optional = true, path = "factory" } +itp-node-api-metadata = { default-features = false, path = "metadata" } +itp-node-api-metadata-provider = { default-features = false, path = "metadata-provider" } + +[features] +default = ["std"] +std = [ + "itp-api-client-extensions", + "itp-api-client-types/std", + "itp-node-api-factory", + "itp-node-api-metadata/std", + "itp-node-api-metadata-provider/std", +] +sgx = [ + "itp-node-api-metadata-provider/sgx", +] +mocks = [ + "itp-node-api-metadata/mocks", +] diff --git a/bitacross-worker/core-primitives/node-api/api-client-extensions/Cargo.toml b/bitacross-worker/core-primitives/node-api/api-client-extensions/Cargo.toml new file mode 100644 index 0000000000..8ebf52e504 --- /dev/null +++ b/bitacross-worker/core-primitives/node-api/api-client-extensions/Cargo.toml @@ -0,0 +1,27 @@ +[package] +name = "itp-api-client-extensions" +version = "0.9.0" +authors = ['Trust Computing GmbH ', 'Integritee AG '] +edition = "2021" + +[dependencies] + +# substrate +sp-consensus-grandpa = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } +sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } + +# scs +# `default-features = false` to remove the jsonrpsee dependency. +substrate-api-client = { default-features = false, features = ["std", "sync-api"], git = "https://github.com/scs/substrate-api-client.git", branch = "polkadot-v0.9.42-tag-v0.14.0" } + +# local deps +itp-api-client-types = { path = "../api-client-types" } +itp-types = { path = "../../types" } + +# litentry +hex = "0.4" +sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } + +[features] +# used for unit testing only! +mocks = [] diff --git a/bitacross-worker/core-primitives/node-api/api-client-extensions/src/account.rs b/bitacross-worker/core-primitives/node-api/api-client-extensions/src/account.rs new file mode 100644 index 0000000000..8834f942bb --- /dev/null +++ b/bitacross-worker/core-primitives/node-api/api-client-extensions/src/account.rs @@ -0,0 +1,54 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::ApiResult; +use itp_api_client_types::{ + traits::GetAccountInformation, Api, Config, ParentchainRuntimeConfig, Request, +}; + +/// ApiClient extension that contains some convenience methods around accounts. +// Todo: make generic over `Config` type instead? +pub trait AccountApi { + type AccountId; + type Index; + type Balance; + + fn get_nonce_of(&self, who: &Self::AccountId) -> ApiResult; + fn get_free_balance(&self, who: &Self::AccountId) -> ApiResult; + fn get_account_next_index(&self, who: &Self::AccountId) -> ApiResult; +} + +impl AccountApi for Api +where + Client: Request, +{ + type AccountId = ::AccountId; + type Index = ::Index; + type Balance = ::Balance; + + fn get_nonce_of(&self, who: &Self::AccountId) -> ApiResult { + Ok(self.get_account_info(who)?.map(|info| info.nonce).unwrap_or_default()) + } + + fn get_free_balance(&self, who: &Self::AccountId) -> ApiResult { + Ok(self.get_account_data(who)?.map(|data| data.free).unwrap_or_default()) + } + + fn get_account_next_index(&self, who: &Self::AccountId) -> ApiResult { + self.get_system_account_next_index(who.clone()) + } +} diff --git a/bitacross-worker/core-primitives/node-api/api-client-extensions/src/chain.rs b/bitacross-worker/core-primitives/node-api/api-client-extensions/src/chain.rs new file mode 100644 index 0000000000..89321b0034 --- /dev/null +++ b/bitacross-worker/core-primitives/node-api/api-client-extensions/src/chain.rs @@ -0,0 +1,142 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{ApiClientError, ApiResult}; +use itp_api_client_types::{ + storage_key, + traits::{GetChainInfo, GetStorage}, + Api, Config, Request, StorageKey, +}; +use itp_types::parentchain::{BlockNumber, StorageProof}; +use sp_consensus_grandpa::{AuthorityList, VersionedAuthorityList, GRANDPA_AUTHORITIES_KEY}; +use sp_runtime::generic::SignedBlock as GenericSignedBlock; + +type RawEvents = Vec; + +/// ApiClient extension that simplifies chain data access. +pub trait ChainApi { + type Hash; + type Block; + type Header; + type BlockNumber; + + fn last_finalized_block(&self) -> ApiResult>>; + fn signed_block( + &self, + hash: Option, + ) -> ApiResult>>; + fn get_genesis_hash(&self) -> ApiResult; + fn header(&self, header_hash: Option) -> ApiResult>; + /// Fetch blocks from parentchain with blocknumber from until to, including both boundaries. + /// Returns a vector with one element if from equals to. + /// Returns an empty vector if from is greater than to. + fn get_blocks( + &self, + from: Self::BlockNumber, + to: Self::BlockNumber, + ) -> ApiResult>>; + fn is_grandpa_available(&self) -> ApiResult; + fn grandpa_authorities(&self, hash: Option) -> ApiResult; + fn grandpa_authorities_proof(&self, hash: Option) -> ApiResult; + fn get_events_value_proof(&self, block_hash: Option) -> ApiResult; + fn get_events_for_block(&self, block_hash: Option) -> ApiResult; +} + +impl ChainApi for Api +where + RuntimeConfig: Config, + Client: Request, +{ + type Hash = RuntimeConfig::Hash; + type Header = RuntimeConfig::Header; + type Block = RuntimeConfig::Block; + type BlockNumber = RuntimeConfig::BlockNumber; + + fn last_finalized_block(&self) -> ApiResult>> { + self.get_finalized_head()? + .map_or_else(|| Ok(None), |hash| self.signed_block(Some(hash))) + } + + fn signed_block( + &self, + hash: Option, + ) -> ApiResult>> { + Ok(self.get_signed_block(hash)?.map(|block| block.into())) + } + + fn get_genesis_hash(&self) -> ApiResult { + self.get_block_hash(Some(0u32))?.ok_or(ApiClientError::BlockHashNotFound) + } + + fn header(&self, header_hash: Option) -> ApiResult> { + self.get_header(header_hash) + } + + fn get_blocks( + &self, + from: Self::BlockNumber, + to: Self::BlockNumber, + ) -> ApiResult>> { + let mut blocks = Vec::>::new(); + + for n in from..=to { + if let Some(block) = self.get_signed_block_by_num(Some(n))? { + blocks.push(block.into()); + } + } + Ok(blocks) + } + + fn is_grandpa_available(&self) -> ApiResult { + let genesis_hash = Some(self.get_genesis_hash().expect("Failed to get genesis hash")); + Ok(self + .get_storage_by_key(StorageKey(GRANDPA_AUTHORITIES_KEY.to_vec()), genesis_hash)? + .map(|v: VersionedAuthorityList| v.into()) + .map(|v: AuthorityList| !v.is_empty()) + .unwrap_or(false)) + } + + fn grandpa_authorities(&self, at_block: Option) -> ApiResult { + Ok(self + .get_storage_by_key(StorageKey(GRANDPA_AUTHORITIES_KEY.to_vec()), at_block)? + .map(|g: VersionedAuthorityList| g.into()) + .unwrap_or_default()) + } + + fn grandpa_authorities_proof(&self, at_block: Option) -> ApiResult { + Ok(self + .get_storage_proof_by_keys( + vec![StorageKey(GRANDPA_AUTHORITIES_KEY.to_vec())], + at_block, + )? + .map(|read_proof| read_proof.proof.into_iter().map(|bytes| bytes.0).collect()) + .unwrap_or_default()) + } + + fn get_events_value_proof(&self, block_hash: Option) -> ApiResult { + let key = storage_key("System", "Events"); + Ok(self + .get_storage_proof_by_keys(Vec::from([key]), block_hash)? + .map(|read_proof| read_proof.proof.into_iter().map(|bytes| bytes.0).collect()) + .unwrap_or_default()) + } + + fn get_events_for_block(&self, block_hash: Option) -> ApiResult { + let key = storage_key("System", "Events"); + Ok(self.get_opaque_storage_by_key(key, block_hash)?.unwrap_or_default()) + } +} diff --git a/bitacross-worker/core-primitives/node-api/api-client-extensions/src/lib.rs b/bitacross-worker/core-primitives/node-api/api-client-extensions/src/lib.rs new file mode 100644 index 0000000000..2829b53c1c --- /dev/null +++ b/bitacross-worker/core-primitives/node-api/api-client-extensions/src/lib.rs @@ -0,0 +1,32 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 substrate-api-client extension traits. + +pub use substrate_api_client::{api::Error as ApiClientError, rpc::TungsteniteRpcClient, Api}; + +pub mod account; +pub mod chain; +pub mod pallet_teeracle; +pub mod pallet_teerex; + +pub use account::*; +pub use chain::*; +pub use pallet_teeracle::*; +pub use pallet_teerex::*; + +pub type ApiResult = Result; diff --git a/bitacross-worker/core-primitives/node-api/api-client-extensions/src/pallet_teeracle.rs b/bitacross-worker/core-primitives/node-api/api-client-extensions/src/pallet_teeracle.rs new file mode 100644 index 0000000000..3f1ad2d198 --- /dev/null +++ b/bitacross-worker/core-primitives/node-api/api-client-extensions/src/pallet_teeracle.rs @@ -0,0 +1,19 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 const TEERACLE: &str = "Teeracle"; +pub const ADD_TO_WHITELIST: &str = "add_to_whitelist"; diff --git a/bitacross-worker/core-primitives/node-api/api-client-extensions/src/pallet_teerex.rs b/bitacross-worker/core-primitives/node-api/api-client-extensions/src/pallet_teerex.rs new file mode 100644 index 0000000000..222e249402 --- /dev/null +++ b/bitacross-worker/core-primitives/node-api/api-client-extensions/src/pallet_teerex.rs @@ -0,0 +1,105 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::ApiResult; +use itp_api_client_types::{storage_key, traits::GetStorage, Api, Config, Request}; +use itp_types::{Enclave, IpfsHash, MrEnclave, ShardIdentifier}; +use sp_core::storage::StorageKey; + +pub const TEEREX: &str = "Teerex"; +pub const SIDECHAIN: &str = "Sidechain"; + +/// ApiClient extension that enables communication with the `teerex` pallet. +// Todo: make generic over `Config` type instead? +pub trait PalletTeerexApi { + type Hash; + + fn enclave(&self, index: u64, at_block: Option) -> ApiResult>; + fn enclave_count(&self, at_block: Option) -> ApiResult; + fn all_enclaves(&self, at_block: Option) -> ApiResult>; + fn worker_for_shard( + &self, + shard: &ShardIdentifier, + at_block: Option, + ) -> ApiResult>; + fn latest_ipfs_hash( + &self, + shard: &ShardIdentifier, + at_block: Option, + ) -> ApiResult>; + + // litentry + fn all_scheduled_mrenclaves(&self, at_block: Option) -> ApiResult>; +} + +impl PalletTeerexApi for Api +where + RuntimeConfig: Config, + Client: Request, +{ + type Hash = RuntimeConfig::Hash; + + fn enclave(&self, index: u64, at_block: Option) -> ApiResult> { + self.get_storage_map(TEEREX, "EnclaveRegistry", index, at_block) + } + + fn enclave_count(&self, at_block: Option) -> ApiResult { + Ok(self.get_storage(TEEREX, "EnclaveCount", at_block)?.unwrap_or(0u64)) + } + + fn all_enclaves(&self, at_block: Option) -> ApiResult> { + let count = self.enclave_count(at_block)?; + let mut enclaves = Vec::with_capacity(count as usize); + for n in 1..=count { + enclaves.push(self.enclave(n, at_block)?.expect("None enclave")) + } + Ok(enclaves) + } + + fn worker_for_shard( + &self, + shard: &ShardIdentifier, + at_block: Option, + ) -> ApiResult> { + self.get_storage_map(SIDECHAIN, "WorkerForShard", shard, at_block)? + .map_or_else(|| Ok(None), |w_index| self.enclave(w_index, at_block)) + } + + fn latest_ipfs_hash( + &self, + shard: &ShardIdentifier, + at_block: Option, + ) -> ApiResult> { + self.get_storage_map(TEEREX, "LatestIPFSHash", shard, at_block) + } + + fn all_scheduled_mrenclaves(&self, at_block: Option) -> ApiResult> { + let keys: Vec<_> = self + .get_keys(storage_key(TEEREX, "ScheduledEnclave"), at_block)? + .unwrap_or_default() + .iter() + .map(|key| { + let key = key.strip_prefix("0x").unwrap_or(key); + let raw_key = hex::decode(key).unwrap(); + self.get_storage_by_key::(StorageKey(raw_key).into(), at_block) + }) + .filter(|enclave| matches!(enclave, Ok(Some(_)))) + .map(|enclave| enclave.unwrap().unwrap()) + .collect(); + Ok(keys) + } +} diff --git a/bitacross-worker/core-primitives/node-api/api-client-extensions/src/pallet_teerex_api_mock.rs b/bitacross-worker/core-primitives/node-api/api-client-extensions/src/pallet_teerex_api_mock.rs new file mode 100644 index 0000000000..df5bf3646f --- /dev/null +++ b/bitacross-worker/core-primitives/node-api/api-client-extensions/src/pallet_teerex_api_mock.rs @@ -0,0 +1,70 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +use crate::{pallet_teerex::PalletTeerexApi, ApiResult}; +use itp_types::{parentchain::Hash, AccountId, IpfsHash, MrEnclave, MultiEnclave, ShardIdentifier}; +use std::collections::HashMap; + +#[derive(Default)] +pub struct PalletTeerexApiMock { + registered_enclaves: HashMap>>, +} + +impl PalletTeerexApiMock { + pub fn with_enclaves(mut self, enclaves: Vec>>) -> Self { + enclaves.iter().map(|enclave| self.registered_enclaves.insert(enclave)); + self + } +} + +impl PalletTeerexApi for PalletTeerexApiMock { + fn enclave( + &self, + account: AccountId, + _at_block: Option, + ) -> ApiResult>>> { + Ok(self.registered_enclaves.get(index as usize).cloned()) + } + + fn enclave_count(&self, _at_block: Option) -> ApiResult { + Ok(self.registered_enclaves.len() as u64) + } + + fn all_enclaves(&self, _at_block: Option) -> ApiResult>>> { + Ok(self.registered_enclaves.clone()) + } + + fn primary_worker_for_shard( + &self, + _shard: &ShardIdentifier, + _at_block: Option, + ) -> ApiResult>>> { + todo!() + } + + fn latest_ipfs_hash( + &self, + _shard: &ShardIdentifier, + _at_block: Option, + ) -> ApiResult> { + todo!() + } + + fn all_scheduled_mrenclaves(&self, _at_block: Option) -> ApiResult> { + Ok(self.registered_enclaves.iter().map(|k| k.mr_enclave).collect()) + } +} diff --git a/bitacross-worker/core-primitives/node-api/api-client-types/Cargo.toml b/bitacross-worker/core-primitives/node-api/api-client-types/Cargo.toml new file mode 100644 index 0000000000..babeae9d38 --- /dev/null +++ b/bitacross-worker/core-primitives/node-api/api-client-types/Cargo.toml @@ -0,0 +1,28 @@ +[package] +name = "itp-api-client-types" +version = "0.9.0" +authors = ['Trust Computing GmbH ', 'Integritee AG '] +edition = "2021" + +[dependencies] +# scs +substrate-api-client = { default-features = false, features = ["sync-api"], git = "https://github.com/scs/substrate-api-client.git", branch = "polkadot-v0.9.42-tag-v0.14.0" } + +# substrate +sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } + +# local +itp-types = { default-features = false, path = "../../types" } + +# litentry +my-node-runtime = { package = "rococo-parachain-runtime", path = "../../../../runtime/rococo", optional = true } + +[features] +default = ["std"] +std = [ + "itp-types/std", + "substrate-api-client/std", + "substrate-api-client/tungstenite-client", + "sp-runtime/std", + "my-node-runtime/std", +] diff --git a/bitacross-worker/core-primitives/node-api/api-client-types/src/lib.rs b/bitacross-worker/core-primitives/node-api/api-client-types/src/lib.rs new file mode 100644 index 0000000000..f3bee4590d --- /dev/null +++ b/bitacross-worker/core-primitives/node-api/api-client-types/src/lib.rs @@ -0,0 +1,98 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 type definitions to talk to the node. +//! +//! You need to update this if you have a signed extension in your node that +//! is different from the integritee-node, e.g., if you use the `pallet_asset_tx_payment`. + +#![cfg_attr(not(feature = "std"), no_std)] + +pub use itp_types::parentchain::{ + AccountData, AccountId, AccountInfo, Address, Balance, Hash, Index, Signature as PairSignature, +}; +pub use substrate_api_client::{ + ac_node_api::{ + metadata::{InvalidMetadataError, Metadata, MetadataError}, + EventDetails, Events, StaticEvent, + }, + ac_primitives::{ + config::{AssetRuntimeConfig, Config, DefaultRuntimeConfig}, + extrinsics::{ + AssetTip, CallIndex, ExtrinsicParams, GenericAdditionalParams, GenericAdditionalSigned, + GenericExtrinsicParams, GenericSignedExtra, PlainTip, UncheckedExtrinsicV4, + }, + serde_impls::StorageKey, + signer::{SignExtrinsic, StaticExtrinsicSigner}, + }, + rpc::Request, + storage_key, Api, +}; + +// traits from the api-client +pub mod traits { + pub use substrate_api_client::{GetAccountInformation, GetChainInfo, GetStorage}; +} + +pub type ParentchainPlainTip = PlainTip; +pub type ParentchainAssetTip = AssetTip; + +/// Configuration for the ExtrinsicParams. +/// +/// Valid for the default integritee node +pub type ParentchainExtrinsicParams = + GenericExtrinsicParams; +pub type ParentchainAdditionalParams = GenericAdditionalParams; +pub use DefaultRuntimeConfig as ParentchainRuntimeConfig; + +// Pay in asset fees. +// +// This needs to be used if the node uses the `pallet_asset_tx_payment`. +//pub type ParentchainExtrinsicParams = GenericExtrinsicParams; +// pub type ParentchainAdditionalParams = GenericAdditionalParams; + +pub type ParentchainUncheckedExtrinsic = + UncheckedExtrinsicV4; +pub type ParentchainSignedExtra = GenericSignedExtra; +pub type ParentchainSignature = Signature; + +/// Signature type of the [UncheckedExtrinsicV4]. +pub type Signature = Option<(Address, PairSignature, SignedExtra)>; + +#[cfg(feature = "std")] +pub use api::*; + +#[cfg(feature = "std")] +mod api { + use super::ParentchainRuntimeConfig; + use sp_runtime::generic::SignedBlock as GenericSignedBlock; + use substrate_api_client::Api; + + // We should probably switch to the opaque block, then we can get rid of the + // runtime dependency here. + // pub use itp_types::Block; + pub use my_node_runtime::{Block, Runtime, UncheckedExtrinsic}; + + pub use substrate_api_client::{ + api::Error as ApiClientError, + rpc::{tungstenite_client::TungsteniteRpcClient, Error as RpcClientError}, + }; + + pub type SignedBlock = GenericSignedBlock; + + pub type ParentchainApi = Api; +} diff --git a/bitacross-worker/core-primitives/node-api/factory/Cargo.toml b/bitacross-worker/core-primitives/node-api/factory/Cargo.toml new file mode 100644 index 0000000000..dc6084a8d9 --- /dev/null +++ b/bitacross-worker/core-primitives/node-api/factory/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "itp-node-api-factory" +version = "0.9.0" +authors = ['Trust Computing GmbH ', 'Integritee AG '] +edition = "2021" + +[dependencies] +thiserror = { version = "1.0" } + +# substrate +sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } + +# local +itp-api-client-types = { path = "../api-client-types" } diff --git a/bitacross-worker/core-primitives/node-api/factory/src/lib.rs b/bitacross-worker/core-primitives/node-api/factory/src/lib.rs new file mode 100644 index 0000000000..2afea5f423 --- /dev/null +++ b/bitacross-worker/core-primitives/node-api/factory/src/lib.rs @@ -0,0 +1,73 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 itp_api_client_types::{ParentchainApi, TungsteniteRpcClient}; +use sp_core::sr25519; + +/// Trait to create a node API, based on a node URL and signer. +pub trait CreateNodeApi: Send + Sync + 'static { + fn create_api(&self) -> Result; +} + +/// Node API factory error. +#[derive(Debug, thiserror::Error)] +pub enum NodeApiFactoryError { + #[error("Could not connect to node with rpc client")] + FailedToCreateRpcClient(itp_api_client_types::RpcClientError), + #[error("Failed to create a node API")] + FailedToCreateNodeApi(itp_api_client_types::ApiClientError), + #[error(transparent)] + Other(#[from] Box), +} + +impl From for NodeApiFactoryError { + fn from(error: itp_api_client_types::RpcClientError) -> Self { + NodeApiFactoryError::FailedToCreateRpcClient(error) + } +} + +impl From for NodeApiFactoryError { + fn from(error: itp_api_client_types::ApiClientError) -> Self { + NodeApiFactoryError::FailedToCreateNodeApi(error) + } +} + +pub type Result = std::result::Result; + +/// Node API factory implementation. +pub struct NodeApiFactory { + node_url: String, + signer: sr25519::Pair, +} + +impl NodeApiFactory { + pub fn new(url: String, signer: sr25519::Pair) -> Self { + NodeApiFactory { node_url: url, signer } + } +} + +impl CreateNodeApi for NodeApiFactory { + fn create_api(&self) -> Result { + let rpc_client = TungsteniteRpcClient::new(self.node_url.as_str(), 5) + .map_err(NodeApiFactoryError::FailedToCreateRpcClient)?; + let mut api = + ParentchainApi::new(rpc_client).map_err(NodeApiFactoryError::FailedToCreateNodeApi)?; + api.set_signer(self.signer.clone().into()); + Ok(api) + } +} diff --git a/bitacross-worker/core-primitives/node-api/metadata-provider/Cargo.toml b/bitacross-worker/core-primitives/node-api/metadata-provider/Cargo.toml new file mode 100644 index 0000000000..dfcfd8f3f4 --- /dev/null +++ b/bitacross-worker/core-primitives/node-api/metadata-provider/Cargo.toml @@ -0,0 +1,34 @@ +[package] +name = "itp-node-api-metadata-provider" +version = "0.9.0" +authors = ['Trust Computing GmbH ', 'Integritee AG '] +edition = "2021" + +[dependencies] +# crates.io + +# sgx dependencies +sgx_tstd = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git", optional = true } + +# sgx enabled external libraries +thiserror_sgx = { optional = true, package = "thiserror", git = "https://github.com/mesalock-linux/thiserror-sgx", tag = "sgx_1.1.3" } + +# std compatible external libraries (make sure these versions match with the sgx-enabled ones above) +thiserror = { version = "1.0", optional = true } + +# local dependencies +itp-node-api-metadata = { default-features = false, path = "../metadata" } +itp-stf-primitives = { default-features = false, path = "../../stf-primitives" } + +[features] +default = ["std"] +std = [ + "thiserror", + "itp-stf-primitives/std", +] +sgx = [ + "sgx_tstd", + "thiserror_sgx", +] +# used for unit testing only! +mocks = [] diff --git a/bitacross-worker/core-primitives/node-api/metadata-provider/src/error.rs b/bitacross-worker/core-primitives/node-api/metadata-provider/src/error.rs new file mode 100644 index 0000000000..fc45ff5f92 --- /dev/null +++ b/bitacross-worker/core-primitives/node-api/metadata-provider/src/error.rs @@ -0,0 +1,45 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 = "sgx")] +extern crate thiserror_sgx as thiserror; + +use itp_stf_primitives::error::StfError; + +#[derive(Debug, PartialEq, Eq, thiserror::Error)] +pub enum Error { + /// Metadata has not been set + #[error("Metadata has no been set")] + MetadataNotSet, + /// Node metadata error + #[error("Metadata Error: {0:?}")] + MetadataError(itp_node_api_metadata::error::Error), +} + +pub type Result = core::result::Result; + +impl From for Error { + fn from(e: itp_node_api_metadata::error::Error) -> Self { + Self::MetadataError(e) + } +} + +impl From for StfError { + fn from(_e: Error) -> Self { + StfError::InvalidMetadata + } +} diff --git a/bitacross-worker/core-primitives/node-api/metadata-provider/src/lib.rs b/bitacross-worker/core-primitives/node-api/metadata-provider/src/lib.rs new file mode 100644 index 0000000000..9d2f16d54d --- /dev/null +++ b/bitacross-worker/core-primitives/node-api/metadata-provider/src/lib.rs @@ -0,0 +1,114 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +//! Minimalistic crate for global metadata access withing the enclave. + +#![cfg_attr(not(feature = "std"), no_std)] +#![cfg_attr(test, feature(assert_matches))] + +#[cfg(all(feature = "std", feature = "sgx"))] +compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the same time"); + +#[cfg(feature = "sgx")] +extern crate sgx_tstd as std; + +#[cfg(feature = "sgx")] +use std::sync::SgxRwLock as RwLock; + +#[cfg(feature = "std")] +use std::sync::RwLock; + +pub use crate::error::Error; + +use crate::error::Result; +use std::ops::Deref; + +pub mod error; + +/// Trait to get access to the node API metadata. +pub trait AccessNodeMetadata { + type MetadataType; + + fn get_from_metadata(&self, getter_function: F) -> Result + where + F: FnOnce(&Self::MetadataType) -> R; +} + +/// Repository to manage the node metadata. +/// +/// Provides simple means to set the metadata and read from it, guarded by a lock. +#[derive(Default)] +pub struct NodeMetadataRepository { + metadata_lock: RwLock>, +} + +impl NodeMetadataRepository { + pub fn new(metadata: NodeMetadata) -> Self { + NodeMetadataRepository { metadata_lock: RwLock::new(Some(metadata)) } + } + + pub fn set_metadata(&self, metadata: NodeMetadata) { + let mut metadata_lock = self.metadata_lock.write().expect("Lock poisoning"); + *metadata_lock = Some(metadata) + } +} + +impl AccessNodeMetadata for NodeMetadataRepository +where + NodeMetadata:, +{ + type MetadataType = NodeMetadata; + + fn get_from_metadata(&self, getter_function: F) -> Result + where + F: FnOnce(&Self::MetadataType) -> R, + { + match self.metadata_lock.read().expect("Lock poisoning").deref() { + Some(metadata) => Ok(getter_function(metadata)), + None => Err(Error::MetadataNotSet), + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use std::assert_matches::assert_matches; + + #[derive(Default)] + struct NodeMetadataMock; + + impl NodeMetadataMock { + fn get_one(&self) -> u32 { + 1 + } + } + #[test] + fn get_from_meta_data_returns_error_if_not_set() { + let repo = NodeMetadataRepository::::default(); + + assert_matches!(repo.get_from_metadata(|m| m.get_one()), Err(Error::MetadataNotSet)); + } + + #[test] + fn get_from_metadata_works() { + let repo = NodeMetadataRepository::::default(); + repo.set_metadata(NodeMetadataMock); + + assert_eq!(1, repo.get_from_metadata(|m| m.get_one()).unwrap()); + } +} diff --git a/bitacross-worker/core-primitives/node-api/metadata/Cargo.toml b/bitacross-worker/core-primitives/node-api/metadata/Cargo.toml new file mode 100644 index 0000000000..2e6e9f3268 --- /dev/null +++ b/bitacross-worker/core-primitives/node-api/metadata/Cargo.toml @@ -0,0 +1,29 @@ +[package] +name = "itp-node-api-metadata" +version = "0.9.0" +authors = ['Trust Computing GmbH ', 'Integritee AG '] +edition = "2021" + +[dependencies] +# crates.io +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +derive_more = { version = "0.99.5" } + +# local +itp-api-client-types = { default-features = false, path = "../api-client-types" } +itp-stf-primitives = { default-features = false, path = "../../stf-primitives" } + +# substrate +sp-core = { git = "https://github.com/paritytech/substrate.git", default-features = false, branch = "polkadot-v0.9.42" } + +[features] +default = ["std"] +std = [ + "codec/std", + "itp-api-client-types/std", + "sp-core/std", + "itp-stf-primitives/std", +] + +# used for unit testing only! +mocks = [] diff --git a/bitacross-worker/core-primitives/node-api/metadata/src/error.rs b/bitacross-worker/core-primitives/node-api/metadata/src/error.rs new file mode 100644 index 0000000000..c0bcf39355 --- /dev/null +++ b/bitacross-worker/core-primitives/node-api/metadata/src/error.rs @@ -0,0 +1,37 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 derive_more::From; +use itp_stf_primitives::error::StfError; + +#[derive(Debug, PartialEq, Eq, From)] +pub enum Error { + /// Metadata has not been set + MetadataNotSet, + /// Api-client metadata error + NodeMetadata(itp_api_client_types::MetadataError), + // litentry + /// Invalid Metadata + InvalidMetadata, +} + +pub type Result = core::result::Result; + +impl From for StfError { + fn from(_e: Error) -> Self { + StfError::InvalidMetadata + } +} diff --git a/bitacross-worker/core-primitives/node-api/metadata/src/lib.rs b/bitacross-worker/core-primitives/node-api/metadata/src/lib.rs new file mode 100644 index 0000000000..0a069c0277 --- /dev/null +++ b/bitacross-worker/core-primitives/node-api/metadata/src/lib.rs @@ -0,0 +1,173 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +//! Handle SGX compatible substrate chain metadata. + +#![cfg_attr(not(feature = "std"), no_std)] + +use crate::{ + error::Result, pallet_balances::BalancesCallIndexes, pallet_imp::IMPCallIndexes, + pallet_proxy::ProxyCallIndexes, pallet_sidechain::SidechainCallIndexes, + pallet_system::SystemSs58Prefix, pallet_teerex::TeerexCallIndexes, + pallet_utility::UtilityCallIndexes, pallet_vcmp::VCMPCallIndexes, +}; +use codec::{Decode, Encode}; +use sp_core::storage::StorageKey; + +pub use crate::error::Error; +pub use itp_api_client_types::{Metadata, MetadataError}; + +pub mod error; +pub mod pallet_balances; +pub mod pallet_imp; +pub mod pallet_proxy; +pub mod pallet_sidechain; +pub mod pallet_system; +pub mod pallet_teeracle; +pub mod pallet_teerex; +pub mod pallet_utility; +pub mod pallet_vcmp; +pub mod runtime_call; + +#[cfg(feature = "mocks")] +pub mod metadata_mocks; + +pub trait NodeMetadataTrait: + TeerexCallIndexes + + SidechainCallIndexes + + IMPCallIndexes + + VCMPCallIndexes + + SystemSs58Prefix + + UtilityCallIndexes + + ProxyCallIndexes + + BalancesCallIndexes +{ +} +impl< + T: TeerexCallIndexes + + SidechainCallIndexes + + IMPCallIndexes + + VCMPCallIndexes + + SystemSs58Prefix + + UtilityCallIndexes + + ProxyCallIndexes + + BalancesCallIndexes, + > NodeMetadataTrait for T +{ +} + +impl TryFrom for Metadata { + type Error = crate::error::Error; + + fn try_from(value: NodeMetadata) -> core::result::Result { + value.node_metadata.ok_or(Error::MetadataNotSet) + } +} + +#[derive(Default, Encode, Decode, Debug, Clone)] +pub struct NodeMetadata { + node_metadata: Option, + runtime_spec_version: u32, + runtime_transaction_version: u32, +} + +impl NodeMetadata { + pub fn new( + node_metadata: Metadata, + runtime_spec_version: u32, + runtime_transaction_version: u32, + ) -> Self { + Self { + node_metadata: Some(node_metadata), + runtime_spec_version, + runtime_transaction_version, + } + } + /// Return the substrate chain runtime version. + pub fn get_runtime_version(&self) -> u32 { + self.runtime_spec_version + } + + /// Return the substrate chain runtime transaction version. + pub fn get_runtime_transaction_version(&self) -> u32 { + self.runtime_transaction_version + } + + /// Generic call indexes: + /// Get the array [pallet index, call index] corresponding to a pallet's call over the metadata. + pub fn call_indexes( + &self, + pallet_name: &'static str, + call_name: &'static str, + ) -> Result<[u8; 2]> { + let pallet = match &self.node_metadata { + None => return Err(Error::MetadataNotSet), + Some(m) => m.pallet_by_name_err(pallet_name)?, + }; + let call_index = pallet + .call_variant_by_name(call_name) + .ok_or(Error::NodeMetadata(MetadataError::CallNotFound(call_name)))?; + Ok([pallet.index(), call_index.index]) + } + + /// Generic storages: + /// Get the storage keys corresponding to a storage over the metadata: + pub fn storage_value_key( + &self, + storage_prefix: &'static str, + storage_key_name: &'static str, + ) -> Result { + match &self.node_metadata { + None => Err(Error::MetadataNotSet), + Some(m) => m + .storage_value_key(storage_prefix, storage_key_name) + .map(|key| key.into()) + .map_err(Error::NodeMetadata), + } + } + + pub fn storage_map_key( + &self, + storage_prefix: &'static str, + storage_key_name: &'static str, + map_key: K, + ) -> Result { + match &self.node_metadata { + None => Err(Error::MetadataNotSet), + Some(m) => m + .storage_map_key::(storage_prefix, storage_key_name, map_key) + .map(|key| key.into()) + .map_err(Error::NodeMetadata), + } + } + + pub fn storage_double_map_key( + &self, + storage_prefix: &'static str, + storage_key_name: &'static str, + first: K, + second: Q, + ) -> Result { + match &self.node_metadata { + None => Err(Error::MetadataNotSet), + Some(m) => m + .storage_double_map_key(storage_prefix, storage_key_name, first, second) + .map(|key| key.into()) + .map_err(Error::NodeMetadata), + } + } +} diff --git a/bitacross-worker/core-primitives/node-api/metadata/src/metadata_mocks.rs b/bitacross-worker/core-primitives/node-api/metadata/src/metadata_mocks.rs new file mode 100644 index 0000000000..cdf24e4fcc --- /dev/null +++ b/bitacross-worker/core-primitives/node-api/metadata/src/metadata_mocks.rs @@ -0,0 +1,317 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{ + error::Result, pallet_balances::BalancesCallIndexes, pallet_imp::IMPCallIndexes, + pallet_proxy::ProxyCallIndexes, pallet_sidechain::SidechainCallIndexes, + pallet_system::SystemSs58Prefix, pallet_teerex::TeerexCallIndexes, + pallet_utility::UtilityCallIndexes, pallet_vcmp::VCMPCallIndexes, runtime_call::RuntimeCall, +}; +use codec::{Decode, Encode}; + +use itp_api_client_types::Metadata; + +impl TryFrom for Metadata { + type Error = (); + + fn try_from(_: NodeMetadataMock) -> core::result::Result { + Err(()) + } +} + +#[derive(Default, Encode, Decode, Debug, Clone)] +pub struct NodeMetadataMock { + teerex_module: u8, + register_enclave: u8, + unregister_sovereign_enclave: u8, + unregister_proxied_enclave: u8, + register_quoting_enclave: u8, + register_tcb_info: u8, + enclave_bridge_module: u8, + invoke: u8, + confirm_processed_parentchain_block: u8, + shield_funds: u8, + unshield_funds: u8, + publish_hash: u8, + update_shard_config: u8, + sidechain_module: u8, + // litentry + update_scheduled_enclave: u8, + remove_scheduled_enclave: u8, + // IMP + imp_module: u8, + imp_link_identity: u8, + imp_deactivate_identity: u8, + imp_activate_identity: u8, + imp_update_id_graph_hash: u8, + imp_identity_linked: u8, + imp_identity_deactivated: u8, + imp_identity_activated: u8, + imp_identity_networks_set: u8, + imp_some_error: u8, + // VCMP + vcmp_module: u8, + vcmp_request_vc: u8, + vcmp_vc_issued: u8, + vcmp_some_error: u8, + + utility_module: u8, + utility_batch: u8, + utility_as_derivative: u8, + utility_batch_all: u8, + utility_dispatch_as: u8, + utility_force_batch: u8, + + imported_sidechain_block: u8, + proxy_module: u8, + add_proxy: u8, + proxy: u8, + balances_module: u8, + transfer: u8, + transfer_keep_alive: u8, + transfer_allow_death: u8, + runtime_spec_version: u32, + runtime_transaction_version: u32, +} + +impl NodeMetadataMock { + pub fn new() -> Self { + NodeMetadataMock { + teerex_module: 50u8, + register_enclave: 0u8, + unregister_sovereign_enclave: 1u8, + unregister_proxied_enclave: 2u8, + register_quoting_enclave: 3, + register_tcb_info: 4, + enclave_bridge_module: 54u8, + invoke: 0u8, + confirm_processed_parentchain_block: 1u8, + shield_funds: 2u8, + unshield_funds: 3u8, + publish_hash: 4u8, + update_shard_config: 5u8, + sidechain_module: 53u8, + // litentry + update_scheduled_enclave: 10u8, + remove_scheduled_enclave: 11u8, + + imp_module: 64u8, + imp_link_identity: 1u8, + imp_deactivate_identity: 2u8, + imp_activate_identity: 3u8, + imp_update_id_graph_hash: 4u8, + imp_identity_linked: 6u8, + imp_identity_deactivated: 7u8, + imp_identity_activated: 8u8, + imp_identity_networks_set: 9u8, + imp_some_error: 10u8, + + vcmp_module: 66u8, + vcmp_request_vc: 0u8, + vcmp_vc_issued: 3u8, + vcmp_some_error: 9u8, + + utility_module: 80u8, + utility_batch: 0u8, + utility_as_derivative: 1u8, + utility_batch_all: 2u8, + utility_dispatch_as: 3u8, + utility_force_batch: 4u8, + + imported_sidechain_block: 0u8, + proxy_module: 7u8, + add_proxy: 1u8, + proxy: 0u8, + balances_module: 10u8, + transfer: 7u8, + transfer_keep_alive: 3u8, + transfer_allow_death: 0u8, + runtime_spec_version: 25, + runtime_transaction_version: 4, + } + } +} + +impl TeerexCallIndexes for NodeMetadataMock { + fn register_enclave_call_indexes(&self) -> Result<[u8; 2]> { + Ok([self.teerex_module, self.register_enclave]) + } + + fn unregister_sovereign_enclave_call_indexes(&self) -> Result<[u8; 2]> { + Ok([self.teerex_module, self.unregister_sovereign_enclave]) + } + + fn unregister_proxied_enclave_call_indexes(&self) -> Result<[u8; 2]> { + Ok([self.teerex_module, self.unregister_proxied_enclave]) + } + + fn register_quoting_enclave_call_indexes(&self) -> Result<[u8; 2]> { + Ok([self.teerex_module, self.register_quoting_enclave]) + } + + fn register_tcb_info_call_indexes(&self) -> Result<[u8; 2]> { + Ok([self.teerex_module, self.register_tcb_info]) + } + + fn invoke_call_indexes(&self) -> Result<[u8; 2]> { + Ok([self.teerex_module, self.invoke]) + } + + fn confirm_processed_parentchain_block_call_indexes(&self) -> Result<[u8; 2]> { + Ok([self.teerex_module, self.confirm_processed_parentchain_block]) + } + + fn shield_funds_call_indexes(&self) -> Result<[u8; 2]> { + Ok([self.teerex_module, self.shield_funds]) + } + + fn unshield_funds_call_indexes(&self) -> Result<[u8; 2]> { + Ok([self.teerex_module, self.unshield_funds]) + } + + fn publish_hash_call_indexes(&self) -> Result<[u8; 2]> { + Ok([self.teerex_module, self.publish_hash]) + } + + // fn update_shard_config_call_indexes(&self) -> Result<[u8; 2]> { + // Ok([self.teerex_module, self.update_shard_config]) + // } + + fn update_scheduled_enclave(&self) -> Result<[u8; 2]> { + Ok([self.teerex_module, self.update_scheduled_enclave]) + } + + fn remove_scheduled_enclave(&self) -> Result<[u8; 2]> { + Ok([self.teerex_module, self.remove_scheduled_enclave]) + } +} + +impl SidechainCallIndexes for NodeMetadataMock { + fn confirm_imported_sidechain_block_indexes(&self) -> Result<[u8; 2]> { + Ok([self.sidechain_module, self.imported_sidechain_block]) + } +} + +impl IMPCallIndexes for NodeMetadataMock { + fn link_identity_call_indexes(&self) -> Result<[u8; 2]> { + Ok([self.imp_module, self.imp_link_identity]) + } + + fn deactivate_identity_call_indexes(&self) -> Result<[u8; 2]> { + Ok([self.imp_module, self.imp_deactivate_identity]) + } + + fn activate_identity_call_indexes(&self) -> Result<[u8; 2]> { + Ok([self.imp_module, self.imp_activate_identity]) + } + + fn update_id_graph_hash_call_indexes(&self) -> Result<[u8; 2]> { + Ok([self.imp_module, self.imp_update_id_graph_hash]) + } + + fn identity_linked_call_indexes(&self) -> Result<[u8; 2]> { + Ok([self.imp_module, self.imp_identity_linked]) + } + + fn identity_deactivated_call_indexes(&self) -> Result<[u8; 2]> { + Ok([self.imp_module, self.imp_identity_deactivated]) + } + + fn identity_activated_call_indexes(&self) -> Result<[u8; 2]> { + Ok([self.imp_module, self.imp_identity_activated]) + } + + fn identity_networks_set_call_indexes(&self) -> Result<[u8; 2]> { + Ok([self.imp_module, self.imp_identity_networks_set]) + } + + fn imp_some_error_call_indexes(&self) -> Result<[u8; 2]> { + Ok([self.imp_module, self.imp_some_error]) + } +} + +impl VCMPCallIndexes for NodeMetadataMock { + fn request_vc_call_indexes(&self) -> Result<[u8; 2]> { + Ok([self.vcmp_module, self.vcmp_request_vc]) + } + + fn vc_issued_call_indexes(&self) -> Result<[u8; 2]> { + Ok([self.vcmp_module, self.vcmp_vc_issued]) + } + + fn vcmp_some_error_call_indexes(&self) -> Result<[u8; 2]> { + Ok([self.vcmp_module, self.vcmp_some_error]) + } +} + +impl UtilityCallIndexes for NodeMetadataMock { + fn batch_call_indexes(&self) -> Result<[u8; 2]> { + Ok([self.utility_module, self.utility_batch]) + } + + fn as_derivative_call_indexes(&self) -> Result<[u8; 2]> { + Ok([self.utility_module, self.utility_as_derivative]) + } + + fn batch_all_call_indexes(&self) -> Result<[u8; 2]> { + Ok([self.utility_module, self.utility_batch_all]) + } + + fn dispatch_as_call_indexes(&self) -> Result<[u8; 2]> { + Ok([self.utility_module, self.utility_dispatch_as]) + } + + fn force_batch_call_indexes(&self) -> Result<[u8; 2]> { + Ok([self.utility_module, self.utility_force_batch]) + } +} + +impl RuntimeCall for NodeMetadataMock { + fn retrieve(&self) -> Result { + Err(crate::Error::MetadataNotSet) + } +} + +impl SystemSs58Prefix for NodeMetadataMock { + fn system_ss58_prefix(&self) -> Result { + Ok(131) + } +} + +impl ProxyCallIndexes for NodeMetadataMock { + fn add_proxy_call_indexes(&self) -> Result<[u8; 2]> { + Ok([self.proxy_module, self.add_proxy]) + } + + fn proxy_call_indexes(&self) -> Result<[u8; 2]> { + Ok([self.proxy_module, self.proxy]) + } +} + +impl BalancesCallIndexes for NodeMetadataMock { + fn transfer_call_indexes(&self) -> Result<[u8; 2]> { + Ok([self.balances_module, self.transfer]) + } + + fn transfer_keep_alive_call_indexes(&self) -> Result<[u8; 2]> { + Ok([self.balances_module, self.transfer_keep_alive]) + } + + fn transfer_allow_death_call_indexes(&self) -> Result<[u8; 2]> { + Ok([self.balances_module, self.transfer_allow_death]) + } +} diff --git a/bitacross-worker/core-primitives/node-api/metadata/src/pallet_balances.rs b/bitacross-worker/core-primitives/node-api/metadata/src/pallet_balances.rs new file mode 100644 index 0000000000..9ae88dd742 --- /dev/null +++ b/bitacross-worker/core-primitives/node-api/metadata/src/pallet_balances.rs @@ -0,0 +1,43 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{error::Result, NodeMetadata}; + +/// Pallet name: +const BALANCES: &str = "Balances"; + +pub trait BalancesCallIndexes { + fn transfer_call_indexes(&self) -> Result<[u8; 2]>; + + fn transfer_keep_alive_call_indexes(&self) -> Result<[u8; 2]>; + + fn transfer_allow_death_call_indexes(&self) -> Result<[u8; 2]>; +} + +impl BalancesCallIndexes for NodeMetadata { + fn transfer_call_indexes(&self) -> Result<[u8; 2]> { + self.call_indexes(BALANCES, "transfer") + } + + fn transfer_keep_alive_call_indexes(&self) -> Result<[u8; 2]> { + self.call_indexes(BALANCES, "transfer_keep_alive") + } + + fn transfer_allow_death_call_indexes(&self) -> Result<[u8; 2]> { + self.call_indexes(BALANCES, "transfer_allow_death") + } +} diff --git a/bitacross-worker/core-primitives/node-api/metadata/src/pallet_imp.rs b/bitacross-worker/core-primitives/node-api/metadata/src/pallet_imp.rs new file mode 100644 index 0000000000..636d93cdab --- /dev/null +++ b/bitacross-worker/core-primitives/node-api/metadata/src/pallet_imp.rs @@ -0,0 +1,71 @@ +// Copyright 2020-2023 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . + +// TODO: maybe use macros to simplify this +use crate::{error::Result, NodeMetadata}; + +/// Pallet' name: +const IMP: &str = "IdentityManagement"; + +pub trait IMPCallIndexes { + fn link_identity_call_indexes(&self) -> Result<[u8; 2]>; + fn deactivate_identity_call_indexes(&self) -> Result<[u8; 2]>; + fn activate_identity_call_indexes(&self) -> Result<[u8; 2]>; + fn update_id_graph_hash_call_indexes(&self) -> Result<[u8; 2]>; + fn identity_linked_call_indexes(&self) -> Result<[u8; 2]>; + fn identity_deactivated_call_indexes(&self) -> Result<[u8; 2]>; + fn identity_activated_call_indexes(&self) -> Result<[u8; 2]>; + fn identity_networks_set_call_indexes(&self) -> Result<[u8; 2]>; + fn imp_some_error_call_indexes(&self) -> Result<[u8; 2]>; +} + +impl IMPCallIndexes for NodeMetadata { + fn link_identity_call_indexes(&self) -> Result<[u8; 2]> { + self.call_indexes(IMP, "link_identity") + } + + fn deactivate_identity_call_indexes(&self) -> Result<[u8; 2]> { + self.call_indexes(IMP, "deactivate_identity") + } + + fn activate_identity_call_indexes(&self) -> Result<[u8; 2]> { + self.call_indexes(IMP, "activate_identity") + } + + fn update_id_graph_hash_call_indexes(&self) -> Result<[u8; 2]> { + self.call_indexes(IMP, "update_id_graph_hash") + } + + fn identity_linked_call_indexes(&self) -> Result<[u8; 2]> { + self.call_indexes(IMP, "identity_linked") + } + + fn identity_deactivated_call_indexes(&self) -> Result<[u8; 2]> { + self.call_indexes(IMP, "identity_deactivated") + } + + fn identity_activated_call_indexes(&self) -> Result<[u8; 2]> { + self.call_indexes(IMP, "identity_activated") + } + + fn identity_networks_set_call_indexes(&self) -> Result<[u8; 2]> { + self.call_indexes(IMP, "identity_networks_set") + } + + fn imp_some_error_call_indexes(&self) -> Result<[u8; 2]> { + self.call_indexes(IMP, "some_error") + } +} diff --git a/bitacross-worker/core-primitives/node-api/metadata/src/pallet_proxy.rs b/bitacross-worker/core-primitives/node-api/metadata/src/pallet_proxy.rs new file mode 100644 index 0000000000..6a7aa14b08 --- /dev/null +++ b/bitacross-worker/core-primitives/node-api/metadata/src/pallet_proxy.rs @@ -0,0 +1,39 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{error::Result, NodeMetadata}; + +/// Pallet name: +const PROXY: &str = "Proxy"; +/// the deposit needed to register up to 20 proxies in native parentchain token +pub const PROXY_DEPOSIT: u128 = 21_000_000_000_000; + +pub trait ProxyCallIndexes { + fn add_proxy_call_indexes(&self) -> Result<[u8; 2]>; + + fn proxy_call_indexes(&self) -> Result<[u8; 2]>; +} + +impl ProxyCallIndexes for NodeMetadata { + fn add_proxy_call_indexes(&self) -> Result<[u8; 2]> { + self.call_indexes(PROXY, "add_proxy") + } + + fn proxy_call_indexes(&self) -> Result<[u8; 2]> { + self.call_indexes(PROXY, "proxy") + } +} diff --git a/bitacross-worker/core-primitives/node-api/metadata/src/pallet_sidechain.rs b/bitacross-worker/core-primitives/node-api/metadata/src/pallet_sidechain.rs new file mode 100644 index 0000000000..c014227dd9 --- /dev/null +++ b/bitacross-worker/core-primitives/node-api/metadata/src/pallet_sidechain.rs @@ -0,0 +1,30 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{error::Result, NodeMetadata}; +/// Pallet' name: +pub const SIDECHAIN: &str = "Sidechain"; + +pub trait SidechainCallIndexes { + fn confirm_imported_sidechain_block_indexes(&self) -> Result<[u8; 2]>; +} + +impl SidechainCallIndexes for NodeMetadata { + fn confirm_imported_sidechain_block_indexes(&self) -> Result<[u8; 2]> { + self.call_indexes(SIDECHAIN, "confirm_imported_sidechain_block") + } +} diff --git a/bitacross-worker/core-primitives/node-api/metadata/src/pallet_system.rs b/bitacross-worker/core-primitives/node-api/metadata/src/pallet_system.rs new file mode 100644 index 0000000000..5005fdbecb --- /dev/null +++ b/bitacross-worker/core-primitives/node-api/metadata/src/pallet_system.rs @@ -0,0 +1,52 @@ +/* +Copyright 2021 Integritee AG and Supercomputing Systems AG +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT 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::{error::Result, Error, NodeMetadata}; +use codec::Decode; +use sp_core::storage::StorageKey; + +/// Pallet' name: +const SYSTEM: &str = "System"; + +pub trait SystemStorageIndexes { + fn system_account_storage_key(&self) -> Result; + + fn system_account_storage_map_key(&self, index: u64) -> Result; +} + +impl SystemStorageIndexes for NodeMetadata { + fn system_account_storage_key(&self) -> Result { + self.storage_value_key(SYSTEM, "Account") + } + + fn system_account_storage_map_key(&self, index: u64) -> Result { + self.storage_map_key(SYSTEM, "Account", index) + } +} + +// litentry +pub trait SystemSs58Prefix { + fn system_ss58_prefix(&self) -> Result; +} + +impl SystemSs58Prefix for NodeMetadata { + fn system_ss58_prefix(&self) -> Result { + match &self.node_metadata { + None => Err(Error::MetadataNotSet), + Some(meta_data) => { + let pallet = meta_data.pallet_by_name(SYSTEM).ok_or(Error::MetadataNotSet)?; + let mut raw = pallet.constant_by_name("SS58Prefix").unwrap().value.as_slice(); + u16::decode(&mut raw).map_err(|_| Error::InvalidMetadata) + }, + } + } +} diff --git a/bitacross-worker/core-primitives/node-api/metadata/src/pallet_teeracle.rs b/bitacross-worker/core-primitives/node-api/metadata/src/pallet_teeracle.rs new file mode 100644 index 0000000000..0d10003514 --- /dev/null +++ b/bitacross-worker/core-primitives/node-api/metadata/src/pallet_teeracle.rs @@ -0,0 +1,46 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{error::Result, NodeMetadata}; + +/// Pallet' name: +pub const TEERACLE: &str = "Teeracle"; + +pub trait TeeracleCallIndexes { + fn add_to_whitelist_call_indexes(&self) -> Result<[u8; 2]>; + fn remove_from_whitelist_call_indexes(&self) -> Result<[u8; 2]>; + fn update_exchange_rate_call_indexes(&self) -> Result<[u8; 2]>; + fn update_oracle_call_indexes(&self) -> Result<[u8; 2]>; +} + +impl TeeracleCallIndexes for NodeMetadata { + fn add_to_whitelist_call_indexes(&self) -> Result<[u8; 2]> { + self.call_indexes(TEERACLE, "add_to_whitelist") + } + + fn remove_from_whitelist_call_indexes(&self) -> Result<[u8; 2]> { + self.call_indexes(TEERACLE, "remove_from_whitelist") + } + + fn update_exchange_rate_call_indexes(&self) -> Result<[u8; 2]> { + self.call_indexes(TEERACLE, "update_exchange_rate") + } + + fn update_oracle_call_indexes(&self) -> Result<[u8; 2]> { + self.call_indexes(TEERACLE, "update_oracle") + } +} diff --git a/bitacross-worker/core-primitives/node-api/metadata/src/pallet_teerex.rs b/bitacross-worker/core-primitives/node-api/metadata/src/pallet_teerex.rs new file mode 100644 index 0000000000..d2cd618e80 --- /dev/null +++ b/bitacross-worker/core-primitives/node-api/metadata/src/pallet_teerex.rs @@ -0,0 +1,114 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{error::Result, NodeMetadata}; +use sp_core::storage::StorageKey; + +/// Pallet' name: +pub const TEEREX: &str = "Teerex"; + +pub trait TeerexCallIndexes { + fn register_enclave_call_indexes(&self) -> Result<[u8; 2]>; + + fn unregister_sovereign_enclave_call_indexes(&self) -> Result<[u8; 2]>; + + fn unregister_proxied_enclave_call_indexes(&self) -> Result<[u8; 2]>; + + fn register_quoting_enclave_call_indexes(&self) -> Result<[u8; 2]>; + + fn register_tcb_info_call_indexes(&self) -> Result<[u8; 2]>; + + fn invoke_call_indexes(&self) -> Result<[u8; 2]>; + + fn confirm_processed_parentchain_block_call_indexes(&self) -> Result<[u8; 2]>; + + fn shield_funds_call_indexes(&self) -> Result<[u8; 2]>; + + fn unshield_funds_call_indexes(&self) -> Result<[u8; 2]>; + + fn publish_hash_call_indexes(&self) -> Result<[u8; 2]>; + + // litentry + fn update_scheduled_enclave(&self) -> Result<[u8; 2]>; + + fn remove_scheduled_enclave(&self) -> Result<[u8; 2]>; +} + +pub trait TeerexStorageKey { + fn sovereign_enclaves_storage_map_key(&self, index: u64) -> Result; + + fn proxied_enclaves_storage_map_key(&self, index: u64) -> Result; +} + +impl TeerexCallIndexes for NodeMetadata { + fn register_enclave_call_indexes(&self) -> Result<[u8; 2]> { + self.call_indexes(TEEREX, "register_enclave") + } + + fn unregister_sovereign_enclave_call_indexes(&self) -> Result<[u8; 2]> { + self.call_indexes(TEEREX, "unregister_sovereign_enclave") + } + + fn unregister_proxied_enclave_call_indexes(&self) -> Result<[u8; 2]> { + self.call_indexes(TEEREX, "unregister_proxied_enclave") + } + + fn register_quoting_enclave_call_indexes(&self) -> Result<[u8; 2]> { + self.call_indexes(TEEREX, "register_quoting_enclave") + } + + fn register_tcb_info_call_indexes(&self) -> Result<[u8; 2]> { + self.call_indexes(TEEREX, "register_tcb_info") + } + + /* Keep parachain extrinsic name untouched. Keep alignment with upstream worker */ + fn invoke_call_indexes(&self) -> Result<[u8; 2]> { + self.call_indexes(TEEREX, "call_worker") + } + + fn confirm_processed_parentchain_block_call_indexes(&self) -> Result<[u8; 2]> { + self.call_indexes(TEEREX, "confirm_processed_parentchain_block") + } + + fn shield_funds_call_indexes(&self) -> Result<[u8; 2]> { + self.call_indexes(TEEREX, "shield_funds") + } + + fn unshield_funds_call_indexes(&self) -> Result<[u8; 2]> { + self.call_indexes(TEEREX, "unshield_funds") + } + + fn publish_hash_call_indexes(&self) -> Result<[u8; 2]> { + self.call_indexes(TEEREX, "publish_hash") + } + + fn update_scheduled_enclave(&self) -> Result<[u8; 2]> { + self.call_indexes(TEEREX, "update_scheduled_enclave") + } + + fn remove_scheduled_enclave(&self) -> Result<[u8; 2]> { + self.call_indexes(TEEREX, "remove_scheduled_enclave") + } +} + +impl TeerexStorageKey for NodeMetadata { + fn sovereign_enclaves_storage_map_key(&self, index: u64) -> Result { + self.storage_map_key(TEEREX, "SovereignEnclaves", index) + } + fn proxied_enclaves_storage_map_key(&self, index: u64) -> Result { + self.storage_map_key(TEEREX, "ProxiedEnclaves", index) + } +} diff --git a/bitacross-worker/core-primitives/node-api/metadata/src/pallet_utility.rs b/bitacross-worker/core-primitives/node-api/metadata/src/pallet_utility.rs new file mode 100644 index 0000000000..909e4a7d30 --- /dev/null +++ b/bitacross-worker/core-primitives/node-api/metadata/src/pallet_utility.rs @@ -0,0 +1,50 @@ +// Copyright 2020-2023 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . + +use crate::{error::Result, NodeMetadata}; + +/// Pallet' name: +const UTIL: &str = "Utility"; + +pub trait UtilityCallIndexes { + fn batch_call_indexes(&self) -> Result<[u8; 2]>; + fn as_derivative_call_indexes(&self) -> Result<[u8; 2]>; + fn batch_all_call_indexes(&self) -> Result<[u8; 2]>; + fn dispatch_as_call_indexes(&self) -> Result<[u8; 2]>; + fn force_batch_call_indexes(&self) -> Result<[u8; 2]>; +} + +impl UtilityCallIndexes for NodeMetadata { + fn batch_call_indexes(&self) -> Result<[u8; 2]> { + self.call_indexes(UTIL, "batch") + } + + fn as_derivative_call_indexes(&self) -> Result<[u8; 2]> { + self.call_indexes(UTIL, "as_derivative") + } + + fn batch_all_call_indexes(&self) -> Result<[u8; 2]> { + self.call_indexes(UTIL, "batch_all") + } + + fn dispatch_as_call_indexes(&self) -> Result<[u8; 2]> { + self.call_indexes(UTIL, "dispatch_as") + } + + fn force_batch_call_indexes(&self) -> Result<[u8; 2]> { + self.call_indexes(UTIL, "force_batch") + } +} diff --git a/bitacross-worker/core-primitives/node-api/metadata/src/pallet_vcmp.rs b/bitacross-worker/core-primitives/node-api/metadata/src/pallet_vcmp.rs new file mode 100644 index 0000000000..210d55e74f --- /dev/null +++ b/bitacross-worker/core-primitives/node-api/metadata/src/pallet_vcmp.rs @@ -0,0 +1,42 @@ +// Copyright 2020-2023 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . + +// TODO: maybe use macros to simplify this +use crate::{error::Result, NodeMetadata}; + +const VCMP: &str = "VCManagement"; + +pub trait VCMPCallIndexes { + fn request_vc_call_indexes(&self) -> Result<[u8; 2]>; + + fn vc_issued_call_indexes(&self) -> Result<[u8; 2]>; + + fn vcmp_some_error_call_indexes(&self) -> Result<[u8; 2]>; +} + +impl VCMPCallIndexes for NodeMetadata { + fn request_vc_call_indexes(&self) -> Result<[u8; 2]> { + self.call_indexes(VCMP, "request_vc") + } + + fn vc_issued_call_indexes(&self) -> Result<[u8; 2]> { + self.call_indexes(VCMP, "vc_issued") + } + + fn vcmp_some_error_call_indexes(&self) -> Result<[u8; 2]> { + self.call_indexes(VCMP, "some_error") + } +} diff --git a/bitacross-worker/core-primitives/node-api/metadata/src/runtime_call.rs b/bitacross-worker/core-primitives/node-api/metadata/src/runtime_call.rs new file mode 100644 index 0000000000..a484e6f779 --- /dev/null +++ b/bitacross-worker/core-primitives/node-api/metadata/src/runtime_call.rs @@ -0,0 +1,41 @@ +// Copyright 2020-2023 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . + +use crate::{error::Result, Error, NodeMetadata}; +use itp_api_client_types::MetadataError; + +pub trait RuntimeCall { + fn retrieve(&self) -> Result; +} + +impl RuntimeCall for NodeMetadata { + fn retrieve(&self) -> Result { + if self.node_metadata.as_ref().is_none() { + return Err(Error::MetadataNotSet) + } + let node_metadata = self.node_metadata.as_ref().unwrap(); + + let runtime_call = node_metadata.types().types.iter().find(|ty| { + let path = &ty.ty.path.segments; + path.len() == 2 && path[1].as_str() == "RuntimeCall" + }); + + match runtime_call { + Some(runtime_call) => Ok(runtime_call.id), + None => Err(Error::NodeMetadata(MetadataError::CallNotFound("RuntimeCall not found"))), + } + } +} diff --git a/bitacross-worker/core-primitives/node-api/src/lib.rs b/bitacross-worker/core-primitives/node-api/src/lib.rs new file mode 100644 index 0000000000..aea624c771 --- /dev/null +++ b/bitacross-worker/core-primitives/node-api/src/lib.rs @@ -0,0 +1,37 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +//! Re-export crate for all the node-api stuff to simplify downstream imports. + +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg(all(feature = "std", feature = "sgx"))] +compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the same time"); + +#[cfg(feature = "std")] +pub use itp_node_api_factory as node_api_factory; + +pub mod api_client { + #[cfg(feature = "std")] + pub use itp_api_client_extensions::*; + pub use itp_api_client_types::*; +} + +pub mod metadata { + pub use itp_node_api_metadata::*; + pub use itp_node_api_metadata_provider as provider; +} diff --git a/bitacross-worker/core-primitives/nonce-cache/Cargo.toml b/bitacross-worker/core-primitives/nonce-cache/Cargo.toml new file mode 100644 index 0000000000..e7f3f012fb --- /dev/null +++ b/bitacross-worker/core-primitives/nonce-cache/Cargo.toml @@ -0,0 +1,27 @@ +[package] +name = "itp-nonce-cache" +version = "0.8.0" +authors = ['Trust Computing GmbH ', 'Integritee AG '] +edition = "2021" + +[dependencies] +# sgx dependencies +sgx_tstd = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git", optional = true } + +# local dependencies + +# sgx enabled external libraries +thiserror_sgx = { package = "thiserror", git = "https://github.com/mesalock-linux/thiserror-sgx", tag = "sgx_1.1.3", optional = true } + +# std compatible external libraries (make sure these versions match with the sgx-enabled ones above) +thiserror = { version = "1.0", optional = true } + +[features] +default = ["std"] +std = [ + "thiserror", +] +sgx = [ + "sgx_tstd", + "thiserror_sgx", +] diff --git a/bitacross-worker/core-primitives/nonce-cache/src/error.rs b/bitacross-worker/core-primitives/nonce-cache/src/error.rs new file mode 100644 index 0000000000..6b1731a77e --- /dev/null +++ b/bitacross-worker/core-primitives/nonce-cache/src/error.rs @@ -0,0 +1,32 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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(all(not(feature = "std"), feature = "sgx"))] +use crate::sgx_reexport_prelude::*; + +use std::boxed::Box; + +pub type Result = core::result::Result; + +/// nonce cache error +#[derive(Debug, thiserror::Error)] +pub enum Error { + #[error("Nonce lock is poisoned")] + LockPoisoning, + #[error(transparent)] + Other(#[from] Box), +} diff --git a/bitacross-worker/core-primitives/nonce-cache/src/lib.rs b/bitacross-worker/core-primitives/nonce-cache/src/lib.rs new file mode 100644 index 0000000000..a1e515ac65 --- /dev/null +++ b/bitacross-worker/core-primitives/nonce-cache/src/lib.rs @@ -0,0 +1,64 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +#![cfg_attr(not(feature = "std"), no_std)] +#![feature(assert_matches)] + +#[cfg(all(feature = "std", feature = "sgx"))] +compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the same time"); + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +extern crate sgx_tstd as std; + +// re-export module to properly feature gate sgx and regular std environment +#[cfg(all(not(feature = "std"), feature = "sgx"))] +pub mod sgx_reexport_prelude { + pub use thiserror_sgx as thiserror; +} + +#[cfg(feature = "std")] +use std::sync::RwLockWriteGuard; +#[cfg(all(not(feature = "std"), feature = "sgx"))] +use std::sync::SgxRwLockWriteGuard as RwLockWriteGuard; + +use crate::error::Result; + +pub use nonce_cache::NonceCache; + +pub mod error; +pub mod nonce_cache; + +pub type NonceValue = u32; + +/// Nonce type (newtype wrapper for NonceValue) +#[derive(Default, Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)] +pub struct Nonce(pub NonceValue); +/// Trait to mutate a nonce. +/// +/// Used in a combination of loading a lock and then writing the updated +/// value back, returning the lock again. +pub trait MutateNonce { + /// load a nonce with the intention to mutate it. lock is released once it goes out of scope + fn load_for_mutation(&self) -> Result>; +} + +/// Trait to get a nonce. +/// +/// +pub trait GetNonce { + fn get_nonce(&self) -> Result; +} diff --git a/bitacross-worker/core-primitives/nonce-cache/src/nonce_cache.rs b/bitacross-worker/core-primitives/nonce-cache/src/nonce_cache.rs new file mode 100644 index 0000000000..af55045cd0 --- /dev/null +++ b/bitacross-worker/core-primitives/nonce-cache/src/nonce_cache.rs @@ -0,0 +1,101 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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(all(not(feature = "std"), feature = "sgx"))] +use std::sync::SgxRwLock as RwLock; +#[cfg(all(not(feature = "std"), feature = "sgx"))] +use std::sync::SgxRwLockWriteGuard as RwLockWriteGuard; + +#[cfg(feature = "std")] +use std::sync::RwLock; +#[cfg(feature = "std")] +use std::sync::RwLockWriteGuard; + +use crate::{ + error::{Error, Result}, + GetNonce, MutateNonce, Nonce, +}; + +/// Local nonce cache +/// +/// stores the nonce internally, protected by a RW lock for concurrent access +#[derive(Default)] +pub struct NonceCache { + nonce_lock: RwLock, +} + +impl NonceCache { + pub fn new(nonce_lock: RwLock) -> Self { + NonceCache { nonce_lock } + } +} + +impl MutateNonce for NonceCache { + fn load_for_mutation(&self) -> Result> { + self.nonce_lock.write().map_err(|_| Error::LockPoisoning) + } +} + +impl GetNonce for NonceCache { + fn get_nonce(&self) -> Result { + let nonce_lock = self.nonce_lock.read().map_err(|_| Error::LockPoisoning)?; + Ok(*nonce_lock) + } +} + +#[cfg(test)] +pub mod tests { + use super::*; + use std::{sync::Arc, thread}; + + #[test] + pub fn nonce_defaults_to_zero() { + let nonce_cache = NonceCache::default(); + assert_eq!(Nonce(0), nonce_cache.get_nonce().unwrap()); + } + + #[test] + pub fn set_nonce_works() { + let nonce_cache = NonceCache::default(); + let mut nonce_lock = nonce_cache.load_for_mutation().unwrap(); + *nonce_lock = Nonce(42); + std::mem::drop(nonce_lock); + assert_eq!(Nonce(42), nonce_cache.get_nonce().unwrap()); + } + + #[test] + pub fn concurrent_read_access_blocks_until_write_is_done() { + let nonce_cache = Arc::new(NonceCache::default()); + + let mut nonce_write_lock = nonce_cache.load_for_mutation().unwrap(); + + // spawn a new thread that reads the nonce + // this thread should be blocked until the write lock is released, i.e. until + // the new nonce is written. We can verify this, by trying to read that nonce variable + // that will be inserted further down below + let new_thread_nonce_cache = nonce_cache.clone(); + let join_handle = thread::spawn(move || { + let nonce_read = new_thread_nonce_cache.get_nonce().unwrap(); + assert_eq!(Nonce(3108), nonce_read); + }); + + *nonce_write_lock = Nonce(3108); + std::mem::drop(nonce_write_lock); + + join_handle.join().unwrap(); + } +} diff --git a/bitacross-worker/core-primitives/ocall-api/Cargo.toml b/bitacross-worker/core-primitives/ocall-api/Cargo.toml new file mode 100644 index 0000000000..ef11a2a828 --- /dev/null +++ b/bitacross-worker/core-primitives/ocall-api/Cargo.toml @@ -0,0 +1,32 @@ +[package] +name = "itp-ocall-api" +version = "0.9.0" +authors = ['Trust Computing GmbH ', 'Integritee AG '] +edition = "2021" + +[dependencies] +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +derive_more = { version = "0.99.5" } + +# sgx deps +sgx_types = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git" } + +# substrate deps +sp-core = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } +sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } +sp-std = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } + +# local deps +itp-storage = { path = "../storage", default-features = false } +itp-types = { path = "../types", default-features = false } + +[features] +default = ["std"] +std = [ + "codec/std", + "sp-core/std", + "sp-runtime/std", + "sp-std/std", + "itp-storage/std", + "itp-types/std", +] diff --git a/bitacross-worker/core-primitives/ocall-api/src/lib.rs b/bitacross-worker/core-primitives/ocall-api/src/lib.rs new file mode 100644 index 0000000000..d4a0a9b944 --- /dev/null +++ b/bitacross-worker/core-primitives/ocall-api/src/lib.rs @@ -0,0 +1,158 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +#![cfg_attr(not(feature = "std"), no_std)] + +pub extern crate alloc; + +use alloc::{string::String, vec::Vec}; +use codec::{Decode, Encode}; +use core::result::Result as StdResult; +use derive_more::{Display, From}; +use itp_storage::Error as StorageError; +use itp_types::{ + parentchain::ParentchainId, storage::StorageEntryVerified, BlockHash, ShardIdentifier, + TrustedOperationStatus, WorkerRequest, WorkerResponse, +}; +use sgx_types::*; +use sp_core::H256; +use sp_runtime::{traits::Header, OpaqueExtrinsic}; +use sp_std::prelude::*; + +#[derive(Debug, Display, From)] +pub enum Error { + Storage(StorageError), + Codec(codec::Error), + Sgx(sgx_types::sgx_status_t), +} + +pub type Result = StdResult; +/// Trait for the enclave to make o-calls related to remote attestation +pub trait EnclaveAttestationOCallApi: Clone + Send + Sync { + fn sgx_init_quote(&self) -> SgxResult<(sgx_target_info_t, sgx_epid_group_id_t)>; + + fn get_ias_socket(&self) -> SgxResult; + + fn get_quote( + &self, + sig_rl: Vec, + report: sgx_report_t, + sign_type: sgx_quote_sign_type_t, + spid: sgx_spid_t, + quote_nonce: sgx_quote_nonce_t, + ) -> SgxResult<(sgx_report_t, Vec)>; + + fn get_dcap_quote(&self, report: sgx_report_t, quote_size: u32) -> SgxResult>; + + fn get_qve_report_on_quote( + &self, + quote: Vec, + current_time: i64, + quote_collateral: sgx_ql_qve_collateral_t, + qve_report_info: sgx_ql_qe_report_info_t, + supplemental_data_size: u32, + ) -> SgxResult<(u32, sgx_ql_qv_result_t, sgx_ql_qe_report_info_t, Vec)>; + + fn get_update_info( + &self, + platform_info: sgx_platform_info_t, + enclave_trusted: i32, + ) -> SgxResult; + + fn get_mrenclave_of_self(&self) -> SgxResult; +} + +/// trait for o-calls related to RPC +pub trait EnclaveRpcOCallApi: Clone + Send + Sync + Default { + fn update_status_event( + &self, + hash: H, + status_update: TrustedOperationStatus, + ) -> SgxResult<()>; + + fn send_state(&self, hash: H, value_opt: Option>) -> SgxResult<()>; +} + +/// trait for o-calls related to on-chain interactions +pub trait EnclaveOnChainOCallApi: Clone + Send + Sync { + fn send_to_parentchain( + &self, + extrinsics: Vec, + parentchain_id: &ParentchainId, + await_each_inclusion: bool, + ) -> SgxResult<()>; + + fn worker_request( + &self, + req: Vec, + parentchain_id: &ParentchainId, + ) -> SgxResult>>; + + fn get_storage_verified, V: Decode>( + &self, + storage_hash: Vec, + header: &H, + parentchain_id: &ParentchainId, + ) -> Result>; + + fn get_multiple_storages_verified, V: Decode>( + &self, + storage_hashes: Vec>, + header: &H, + parentchain_id: &ParentchainId, + ) -> Result>>; + + // Litentry + // given a key prefix, get all storage keys + fn get_storage_keys(&self, key_prefix: Vec) -> Result>>; +} + +/// Trait for sending metric updates. +pub trait EnclaveMetricsOCallApi: Clone + Send + Sync { + fn update_metric(&self, metric: Metric) -> SgxResult<()>; +} + +pub trait EnclaveSidechainOCallApi: Clone + Send + Sync { + fn propose_sidechain_blocks( + &self, + signed_blocks: Vec, + ) -> SgxResult<()>; + + fn store_sidechain_blocks( + &self, + signed_blocks: Vec, + ) -> SgxResult<()>; + + fn fetch_sidechain_blocks_from_peer( + &self, + last_imported_block_hash: BlockHash, + maybe_until_block_hash: Option, + shard_identifier: ShardIdentifier, + ) -> SgxResult>; + + fn get_trusted_peers_urls(&self) -> SgxResult>; +} + +/// Newtype for IPFS CID +pub struct IpfsCid(pub [u8; 46]); + +/// trait for o-call related to IPFS +pub trait EnclaveIpfsOCallApi: Clone + Send + Sync { + fn write_ipfs(&self, encoded_state: &[u8]) -> SgxResult; + + fn read_ipfs(&self, cid: &IpfsCid) -> SgxResult<()>; +} diff --git a/bitacross-worker/core-primitives/primitives-cache/Cargo.toml b/bitacross-worker/core-primitives/primitives-cache/Cargo.toml new file mode 100644 index 0000000000..6b9f8e40e5 --- /dev/null +++ b/bitacross-worker/core-primitives/primitives-cache/Cargo.toml @@ -0,0 +1,30 @@ +[package] +name = "itp-primitives-cache" +version = "0.9.0" +authors = ['Trust Computing GmbH ', 'Integritee AG '] +edition = "2021" + +[dependencies] +# sgx dependencies +sgx_tstd = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git", optional = true } + +# local dependencies + +# sgx enabled external libraries +thiserror_sgx = { package = "thiserror", git = "https://github.com/mesalock-linux/thiserror-sgx", tag = "sgx_1.1.3", optional = true } + +# std compatible external libraries (make sure these versions match with the sgx-enabled ones above) +thiserror = { version = "1.0", optional = true } + +# no-std dependencies +lazy_static = { version = "1.1.0", features = ["spin_no_std"] } + +[features] +default = ["std"] +std = [ + "thiserror", +] +sgx = [ + "sgx_tstd", + "thiserror_sgx", +] diff --git a/bitacross-worker/core-primitives/primitives-cache/src/error.rs b/bitacross-worker/core-primitives/primitives-cache/src/error.rs new file mode 100644 index 0000000000..2873dd8156 --- /dev/null +++ b/bitacross-worker/core-primitives/primitives-cache/src/error.rs @@ -0,0 +1,31 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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(all(not(feature = "std"), feature = "sgx"))] +use crate::sgx_reexport_prelude::*; + +use std::boxed::Box; + +pub type Result = core::result::Result; + +#[derive(Debug, thiserror::Error)] +pub enum Error { + #[error("Primitives lock is poisoned")] + LockPoisoning, + #[error(transparent)] + Other(#[from] Box), +} diff --git a/bitacross-worker/core-primitives/primitives-cache/src/lib.rs b/bitacross-worker/core-primitives/primitives-cache/src/lib.rs new file mode 100644 index 0000000000..e4a2724e3f --- /dev/null +++ b/bitacross-worker/core-primitives/primitives-cache/src/lib.rs @@ -0,0 +1,114 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 all primitives of the enclave that do need to be accessed often, but are +//! not be frequently mutated, such as keys and server urls. +//! +//! TODO: For now only the mu-ra server and untrusted worker url is stored here. Keys and such could also be stored here. + +#![cfg_attr(not(feature = "std"), no_std)] +#![feature(assert_matches)] + +#[cfg(all(feature = "std", feature = "sgx"))] +compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the same time"); + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +extern crate sgx_tstd as std; + +// Re-export module to properly feature gate sgx and regular std environment. +#[cfg(all(not(feature = "std"), feature = "sgx"))] +pub mod sgx_reexport_prelude { + pub use thiserror_sgx as thiserror; +} + +#[cfg(feature = "std")] +use std::sync::RwLockReadGuard; +#[cfg(feature = "std")] +use std::sync::RwLockWriteGuard; + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +use std::sync::SgxRwLockReadGuard as RwLockReadGuard; +#[cfg(all(not(feature = "std"), feature = "sgx"))] +use std::sync::SgxRwLockWriteGuard as RwLockWriteGuard; + +use crate::error::Result; +use lazy_static::lazy_static; +use std::{string::String, sync::Arc}; + +pub use primitives_cache::PrimitivesCache; + +lazy_static! { + /// Global instance of the primitives cache. + /// + /// Concurrent access is managed internally, using RW locks. + pub static ref GLOBAL_PRIMITIVES_CACHE: Arc = Default::default(); +} + +pub mod error; +pub mod primitives_cache; + +#[derive(Default, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)] +pub struct Primitives { + mu_ra_url: String, + untrusted_worker_url: String, +} + +impl Primitives { + pub fn new(mu_ra_url: String, untrusted_worker_url: String) -> Primitives { + Primitives { mu_ra_url, untrusted_worker_url } + } + + pub fn mu_ra_url(&self) -> &str { + &self.mu_ra_url + } + + pub fn untrusted_worker_url(&self) -> &str { + &self.untrusted_worker_url + } +} + +/// Trait to mutate the primitives. +/// +/// Used in a combination of loading a lock and then writing the updated +/// value back, returning the lock again. +pub trait MutatePrimitives { + fn load_for_mutation(&self) -> Result>; +} + +/// Trait to get the primitives. +pub trait GetPrimitives { + /// Returns a clone of the full Primitives struct. + fn get_primitives(&self) -> Result>; + + fn get_mu_ra_url(&self) -> Result; + + fn get_untrusted_worker_url(&self) -> Result; +} + +// Helper function to set primitives of a given cache. +pub fn set_primitives( + cache: &E, + mu_ra_url: String, + untrusted_worker_url: String, +) -> Result<()> { + let primitives = Primitives::new(mu_ra_url, untrusted_worker_url); + let mut rw_lock = cache.load_for_mutation()?; + + *rw_lock = primitives; + + Ok(()) +} diff --git a/bitacross-worker/core-primitives/primitives-cache/src/primitives_cache.rs b/bitacross-worker/core-primitives/primitives-cache/src/primitives_cache.rs new file mode 100644 index 0000000000..40bc516f51 --- /dev/null +++ b/bitacross-worker/core-primitives/primitives-cache/src/primitives_cache.rs @@ -0,0 +1,117 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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(all(not(feature = "std"), feature = "sgx"))] +use std::sync::SgxRwLock as RwLock; +#[cfg(all(not(feature = "std"), feature = "sgx"))] +use std::sync::SgxRwLockReadGuard as RwLockReadGuard; +#[cfg(all(not(feature = "std"), feature = "sgx"))] +use std::sync::SgxRwLockWriteGuard as RwLockWriteGuard; + +#[cfg(feature = "std")] +use std::sync::RwLock; +#[cfg(feature = "std")] +use std::sync::RwLockReadGuard; +#[cfg(feature = "std")] +use std::sync::RwLockWriteGuard; + +use std::string::{String, ToString}; + +use crate::{ + error::{Error, Result}, + GetPrimitives, MutatePrimitives, Primitives, +}; + +/// Local primitives cache. +/// +/// Stores the primitives internally, protected by a RW lock for concurrent access. +#[derive(Default)] +pub struct PrimitivesCache { + primitives_lock: RwLock, +} + +impl PrimitivesCache { + pub fn new(primitives_lock: RwLock) -> Self { + PrimitivesCache { primitives_lock } + } +} + +impl MutatePrimitives for PrimitivesCache { + fn load_for_mutation(&self) -> Result> { + self.primitives_lock.write().map_err(|_| Error::LockPoisoning) + } +} + +impl GetPrimitives for PrimitivesCache { + fn get_primitives(&self) -> Result> { + self.primitives_lock.read().map_err(|_| Error::LockPoisoning) + } + + fn get_mu_ra_url(&self) -> Result { + let primitives_lock = self.primitives_lock.read().map_err(|_| Error::LockPoisoning)?; + Ok(primitives_lock.mu_ra_url().to_string()) + } + + fn get_untrusted_worker_url(&self) -> Result { + let primitives_lock = self.primitives_lock.read().map_err(|_| Error::LockPoisoning)?; + Ok(primitives_lock.untrusted_worker_url().to_string()) + } +} + +#[cfg(test)] +pub mod tests { + use super::*; + use std::{sync::Arc, thread}; + + #[test] + pub fn set_primitives_works() { + let cache = PrimitivesCache::default(); + let mut lock = cache.load_for_mutation().unwrap(); + let mu_ra_url = "hello".to_string(); + let untrusted_url = "world".to_string(); + let primitives = Primitives::new(mu_ra_url, untrusted_url); + *lock = primitives.clone(); + std::mem::drop(lock); + assert_eq!(primitives, *cache.get_primitives().unwrap()); + } + + #[test] + pub fn concurrent_read_access_blocks_until_write_is_done() { + let cache = Arc::new(PrimitivesCache::default()); + let mu_ra_url = "hello".to_string(); + let untrusted_url = "world".to_string(); + let primitives = Primitives::new(mu_ra_url, untrusted_url); + + let mut write_lock = cache.load_for_mutation().unwrap(); + + // Spawn a new thread that reads the primitives. + // This thread should be blocked until the write lock is released, i.e. until + // the new primitves are written. We can verify this, by trying to read the primitives variable + // that will be inserted further down below. + let new_thread_cache = cache.clone(); + let primitives_one = primitives.clone(); + let join_handle = thread::spawn(move || { + let read = new_thread_cache.get_primitives().unwrap(); + assert_eq!(primitives_one, *read); + }); + + *write_lock = primitives; + std::mem::drop(write_lock); + + join_handle.join().unwrap(); + } +} diff --git a/bitacross-worker/core-primitives/rpc/Cargo.toml b/bitacross-worker/core-primitives/rpc/Cargo.toml new file mode 100644 index 0000000000..784d850495 --- /dev/null +++ b/bitacross-worker/core-primitives/rpc/Cargo.toml @@ -0,0 +1,26 @@ +[package] +name = "itp-rpc" +version = "0.9.0" +authors = ['Trust Computing GmbH ', 'Integritee AG '] +edition = "2021" + +[dependencies] +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +itp-types = { default-features = false, path = "../types" } +serde = { version = "1.0", default-features = false, features = ["alloc", "derive"] } +serde_json = { version = "1.0", default-features = false, features = ["alloc"] } + +# sgx deps +sgx_tstd = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git", optional = true } + +[features] +default = ["std"] +std = [ + "codec/std", + "itp-types/std", + "serde/std", + "serde_json/std", +] +sgx = [ + "sgx_tstd", +] diff --git a/bitacross-worker/core-primitives/rpc/src/lib.rs b/bitacross-worker/core-primitives/rpc/src/lib.rs new file mode 100644 index 0000000000..4169196010 --- /dev/null +++ b/bitacross-worker/core-primitives/rpc/src/lib.rs @@ -0,0 +1,114 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg(all(feature = "std", feature = "sgx"))] +compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the same time"); + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +extern crate sgx_tstd as std; + +use codec::{Decode, Encode}; +use itp_types::DirectRequestStatus; +use serde::{Deserialize, Serialize}; +use std::{borrow::ToOwned, string::String, vec::Vec}; + +#[derive(Encode, Decode, Debug, Eq, PartialEq)] +pub struct RpcReturnValue { + pub value: Vec, + pub do_watch: bool, + pub status: DirectRequestStatus, +} +impl RpcReturnValue { + pub fn new(val: Vec, watch: bool, status: DirectRequestStatus) -> Self { + Self { value: val, do_watch: watch, status } + } + + pub fn from_error_message(error_msg: &str) -> Self { + RpcReturnValue { + value: error_msg.encode(), + do_watch: false, + status: DirectRequestStatus::Error, + } + } +} + +#[derive(Clone, Encode, Decode, Debug, Serialize, Deserialize, Eq, PartialEq, Hash)] +#[serde(untagged)] +pub enum Id { + #[codec(index = 0)] + Number(u32), + #[codec(index = 1)] + Text(String), +} + +#[derive(Clone, Encode, Decode, Debug, Serialize, Deserialize)] +pub struct RpcResponse { + pub jsonrpc: String, + pub result: String, // hex encoded RpcReturnValue + pub id: Id, +} + +#[derive(Clone, Encode, Decode, Serialize, Deserialize)] +pub struct RpcRequest { + pub jsonrpc: String, + pub method: String, + pub params: Vec, + pub id: Id, +} + +impl RpcRequest { + pub fn compose_jsonrpc_call( + id: Id, + method: String, + params: Vec, + ) -> Result { + serde_json::to_string(&RpcRequest { jsonrpc: "2.0".to_owned(), method, params, id }) + } +} + +#[cfg(test)] +pub mod tests { + use crate::Id; + + #[test] + pub fn deserialize_string_id() { + let id: Id = serde_json::from_str(r#""1""#).unwrap(); + assert!(matches!(id, Id::Text(t) if t == "1")) + } + + #[test] + pub fn deserialize_number_id() { + let id: Id = serde_json::from_str(r#"1"#).unwrap(); + assert!(matches!(id, Id::Number(t) if t == 1)) + } + + #[test] + pub fn serialize_string_id() { + let id = Id::Text("1".to_string()); + let serialized = serde_json::to_string(&id).unwrap(); + assert_eq!(serialized, r#""1""#) + } + + #[test] + pub fn serialize_number_id() { + let id = Id::Number(1); + let serialized = serde_json::to_string(&id).unwrap(); + assert_eq!(serialized, r#"1"#) + } +} diff --git a/bitacross-worker/core-primitives/settings/Cargo.toml b/bitacross-worker/core-primitives/settings/Cargo.toml new file mode 100644 index 0000000000..bf48cd4ec2 --- /dev/null +++ b/bitacross-worker/core-primitives/settings/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "itp-settings" +version = "0.9.0" +authors = ['Trust Computing GmbH ', 'Integritee AG '] +edition = "2021" + +[dependencies] + + +[features] +production = [] +sidechain = [] +offchain-worker = [] +teeracle = [] diff --git a/bitacross-worker/core-primitives/settings/src/lib.rs b/bitacross-worker/core-primitives/settings/src/lib.rs new file mode 100644 index 0000000000..bc3ca98dcf --- /dev/null +++ b/bitacross-worker/core-primitives/settings/src/lib.rs @@ -0,0 +1,120 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 settings for the worker and the enclave. It is strictly `no_std` + +#![no_std] + +#[cfg(any( + all(feature = "sidechain", feature = "offchain-worker"), + all(feature = "sidechain", feature = "teeracle"), + all(feature = "teeracle", feature = "offchain-worker") +))] +compile_error!( + "feature \"sidechain\" , \"offchain-worker\" or \"teeracle\" cannot be enabled at the same time" +); + +pub mod worker_mode; + +pub mod files { + // used by worker + pub static ENCLAVE_TOKEN: &str = "enclave.token"; + pub static ENCLAVE_FILE: &str = "enclave.signed.so"; + pub static SHIELDING_KEY_FILE: &str = "enclave-shielding-pubkey.json"; + pub static SIGNING_KEY_FILE: &str = "enclave-signing-pubkey.bin"; + /// sidechain database path + pub static SIDECHAIN_STORAGE_PATH: &str = "sidechain_db"; + pub static SIDECHAIN_PURGE_INTERVAL: u64 = 7200; // purge sidechain every .. s + pub static SIDECHAIN_PURGE_LIMIT: u64 = 100; // keep the last.. sidechainblocks when purging + + // used by enclave + /// Path to the light-client db for the Integritee parentchain. + pub const LITENTRY_PARENTCHAIN_LIGHT_CLIENT_DB_PATH: &str = "integritee_lcdb"; + + /// Path to the light-client db for the Target A parentchain. + pub const TARGET_A_PARENTCHAIN_LIGHT_CLIENT_DB_PATH: &str = "target_a_lcdb"; + + /// Path to the light-client db for the Target B parentchain. + pub const TARGET_B_PARENTCHAIN_LIGHT_CLIENT_DB_PATH: &str = "target_b_lcdb"; + + // litentry + pub const SCHEDULED_ENCLAVE_FILE: &str = "scheduled_enclave_sealed.bin"; + + pub const RA_DUMP_CERT_DER_FILE: &str = "ra_dump_cert.der"; + + // used by worker and enclave + pub const SHARDS_PATH: &str = "shards"; + + #[cfg(feature = "production")] + pub static RA_SPID_FILE: &str = "spid_production.txt"; + #[cfg(feature = "production")] + pub static RA_API_KEY_FILE: &str = "key_production.txt"; + + #[cfg(not(feature = "production"))] + pub static RA_SPID_FILE: &str = "spid.txt"; + #[cfg(not(feature = "production"))] + pub static RA_API_KEY_FILE: &str = "key.txt"; + + pub const SPID_MIN_LENGTH: usize = 32; + pub const STATE_SNAPSHOTS_CACHE_SIZE: usize = 4; +} + +/// Settings concerning the worker +pub mod worker { + // the maximum size of any extrinsic that the enclave will ever generate in B + pub const EXTRINSIC_MAX_SIZE: usize = 13_000; + // the maximum size of the header + // Litentry: change it to 300 after the evm pallet being fused + // see https://github.com/litentry/litentry-parachain/actions/runs/6168159073/job/16742757562 + pub const HEADER_MAX_SIZE: usize = 300; + // maximum size of shielding key + pub const SHIELDING_KEY_SIZE: usize = 8192; + // maximum size of signing key + pub const SIGNING_KEY_SIZE: usize = 32; + // size of the MR enclave + pub const MR_ENCLAVE_SIZE: usize = 32; + // Factors to tune the initial amount of enclave funding: + // Should be set to a value that ensures that the enclave can register itself + // and the worker can run for a certain time. Only for development. + pub const EXISTENTIAL_DEPOSIT_FACTOR_FOR_INIT_FUNDS: u128 = 1_000; + // Should be set to a value that ensures that the enclave can register itself + // and that the worker can start. + pub const REGISTERING_FEE_FACTOR_FOR_INIT_FUNDS: u128 = 10; + // Should be set to a value that ensures that at least 2 sidechain blocks are finalized per + // parentchain block. + pub const BLOCK_NUMBER_FINALIZATION_DIFF: u64 = 20; +} + +pub mod sidechain { + use core::time::Duration; + + pub static SLOT_DURATION: Duration = Duration::from_millis(6000); +} + +/// Settings concerning the enclave +pub mod enclave {} + +/// Settings for the Teeracle +pub mod teeracle { + use core::time::Duration; + // Send extrinsic to update market exchange rate on the parentchain once per day + pub static DEFAULT_MARKET_DATA_UPDATE_INTERVAL: Duration = ONE_DAY; + + pub static ONE_DAY: Duration = Duration::from_secs(86400); + + pub static THIRTY_MINUTES: Duration = Duration::from_secs(1800); +} diff --git a/bitacross-worker/core-primitives/settings/src/worker_mode.rs b/bitacross-worker/core-primitives/settings/src/worker_mode.rs new file mode 100644 index 0000000000..7eef1144fa --- /dev/null +++ b/bitacross-worker/core-primitives/settings/src/worker_mode.rs @@ -0,0 +1,59 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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(Eq, PartialEq, Debug, Clone)] +pub enum WorkerMode { + OffChainWorker, + Sidechain, + Teeracle, +} + +pub trait ProvideWorkerMode { + fn worker_mode() -> WorkerMode; +} + +#[derive(Default, Copy, Clone)] +pub struct WorkerModeProvider; + +#[cfg(feature = "offchain-worker")] +impl ProvideWorkerMode for WorkerModeProvider { + fn worker_mode() -> WorkerMode { + WorkerMode::OffChainWorker + } +} + +#[cfg(feature = "teeracle")] +impl ProvideWorkerMode for WorkerModeProvider { + fn worker_mode() -> WorkerMode { + WorkerMode::Teeracle + } +} + +#[cfg(feature = "sidechain")] +impl ProvideWorkerMode for WorkerModeProvider { + fn worker_mode() -> WorkerMode { + WorkerMode::Sidechain + } +} + +// Default to `Sidechain` worker mode when no cargo features are set. +#[cfg(not(any(feature = "sidechain", feature = "teeracle", feature = "offchain-worker")))] +impl ProvideWorkerMode for WorkerModeProvider { + fn worker_mode() -> WorkerMode { + WorkerMode::Sidechain + } +} diff --git a/bitacross-worker/core-primitives/sgx-runtime-primitives/Cargo.toml b/bitacross-worker/core-primitives/sgx-runtime-primitives/Cargo.toml new file mode 100644 index 0000000000..8ec87045fa --- /dev/null +++ b/bitacross-worker/core-primitives/sgx-runtime-primitives/Cargo.toml @@ -0,0 +1,27 @@ +[package] +name = "itp-sgx-runtime-primitives" +version = "0.9.0" +authors = ['Trust Computing GmbH ', 'Integritee AG '] +edition = "2021" + +[dependencies] + +# Substrate dependencies +frame-system = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } +pallet-balances = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } +sp-core = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } +sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } + +# litentry +litentry-primitives = { path = "../../litentry/primitives", default-features = false } + +[features] +default = ["std"] +std = [ + "frame-system/std", + "pallet-balances/std", + "sp-core/std", + "sp-runtime/std", + # litentry + "litentry-primitives/std", +] diff --git a/bitacross-worker/core-primitives/sgx-runtime-primitives/src/constants.rs b/bitacross-worker/core-primitives/sgx-runtime-primitives/src/constants.rs new file mode 100644 index 0000000000..75eac384f1 --- /dev/null +++ b/bitacross-worker/core-primitives/sgx-runtime-primitives/src/constants.rs @@ -0,0 +1,29 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::types::{BlockNumber, Moment}; + +pub const ONE_DAY: Moment = 86_400_000; + +pub const MILLISECS_PER_BLOCK: u64 = 6000; + +pub const SLOT_DURATION: u64 = MILLISECS_PER_BLOCK; + +// Time is measured by number of blocks. +pub const MINUTES: BlockNumber = 60_000 / (MILLISECS_PER_BLOCK as BlockNumber); +pub const HOURS: BlockNumber = MINUTES * 60; +pub const DAYS: BlockNumber = HOURS * 24; diff --git a/bitacross-worker/core-primitives/sgx-runtime-primitives/src/lib.rs b/bitacross-worker/core-primitives/sgx-runtime-primitives/src/lib.rs new file mode 100644 index 0000000000..74007111ba --- /dev/null +++ b/bitacross-worker/core-primitives/sgx-runtime-primitives/src/lib.rs @@ -0,0 +1,21 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +#![cfg_attr(not(feature = "std"), no_std)] + +pub mod constants; +pub mod types; diff --git a/bitacross-worker/core-primitives/sgx-runtime-primitives/src/types.rs b/bitacross-worker/core-primitives/sgx-runtime-primitives/src/types.rs new file mode 100644 index 0000000000..bad667791e --- /dev/null +++ b/bitacross-worker/core-primitives/sgx-runtime-primitives/src/types.rs @@ -0,0 +1,86 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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_runtime::{ + generic::{self, Block as BlockG, SignedBlock as SignedBlockG}, + traits::{BlakeTwo256, IdentifyAccount, Verify}, + MultiSignature, OpaqueExtrinsic, +}; + +use litentry_primitives::ParentchainAccountId; + +/// The address format for describing accounts. +pub type Address = sp_runtime::MultiAddress; +/// Block header type as expected by this sgx-runtime. +pub type Header = generic::Header; + +/// An index to a block. +pub type BlockNumber = u32; +pub type SidechainBlockNumber = u64; +pub type SidechainTimestamp = u64; + +/// Alias to 512-bit hash when used in the context of a transaction signature on the chain. +pub type Signature = MultiSignature; + +/// Some way of identifying an account on the chain. We intentionally make it equivalent +/// to the public key of our transaction signing scheme. +pub type AccountId = <::Signer as IdentifyAccount>::AccountId; + +pub type AccountData = pallet_balances::AccountData; +pub type AccountInfo = frame_system::AccountInfo; + +/// The type for looking up accounts. We don't expect more than 4 billion of them, but you +/// never know... +pub type AccountIndex = u32; + +/// Balance of an account. +pub type Balance = u128; + +/// Index of a transaction in the chain. +pub type Index = u32; + +/// A hash of some data used by the chain. +pub type Hash = sp_core::H256; + +/// Digest item type. +pub type DigestItem = generic::DigestItem; + +/// A type to hold UTC unix epoch [ms] +pub type Moment = u64; + +pub type Block = BlockG; +pub type SignedBlock = SignedBlockG; +pub type BlockHash = sp_core::H256; +pub type ShardIdentifier = sp_core::H256; + +// litentry +pub trait ConvertAccountId { + type Input; + type Output; + fn convert(input: Self::Input) -> Self::Output; +} + +pub struct SgxParentchainTypeConverter; + +impl ConvertAccountId for SgxParentchainTypeConverter { + type Input = AccountId; + type Output = ParentchainAccountId; + fn convert(a: AccountId) -> ParentchainAccountId { + // it's an identity converter + a as ParentchainAccountId + } +} diff --git a/bitacross-worker/core-primitives/sgx/crypto/Cargo.toml b/bitacross-worker/core-primitives/sgx/crypto/Cargo.toml new file mode 100644 index 0000000000..fd8a971e49 --- /dev/null +++ b/bitacross-worker/core-primitives/sgx/crypto/Cargo.toml @@ -0,0 +1,56 @@ +[package] +name = "itp-sgx-crypto" +version = "0.9.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +aes = { version = "0.6.0" } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +derive_more = { version = "0.99.5" } +log = { version = "0.4", default-features = false } +ofb = { version = "0.4.0" } +serde_json = { version = "1.0", default-features = false, features = ["alloc"], optional = true } + +# sgx deps +serde_json-sgx = { package = "serde_json", tag = "sgx_1.1.3", git = "https://github.com/mesalock-linux/serde-json-sgx", optional = true } +sgx-crypto-helper = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git", package = "sgx_crypto_helper", default-features = false } +sgx_rand = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git", optional = true } +sgx_tstd = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git", optional = true } +sgx_types = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git" } + +# substrate +sp-core = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } + +# local deps +itp-sgx-io = { path = "../io", default-features = false } + +# test sgx deps +itp-sgx-temp-dir = { default-features = false, optional = true, path = "../temp-dir" } + +[features] +default = ["std"] +std = [ + "codec/std", + "log/std", + "itp-sgx-io/std", + "sp-core/std", + "serde_json/std", + "sgx-crypto-helper/default", +] +sgx = [ + "sgx-crypto-helper/mesalock_sgx", + "sgx_tstd", + "sgx_rand", + "itp-sgx-io/sgx", + "serde_json-sgx", +] +mocks = [] +test = [ + # features + "mocks", + "sgx", + # deps + "itp-sgx-temp-dir", +] diff --git a/bitacross-worker/core-primitives/sgx/crypto/src/aes.rs b/bitacross-worker/core-primitives/sgx/crypto/src/aes.rs new file mode 100644 index 0000000000..0c1414e84c --- /dev/null +++ b/bitacross-worker/core-primitives/sgx/crypto/src/aes.rs @@ -0,0 +1,203 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{ + error::{Error, Result}, + traits::StateCrypto, +}; +use aes::Aes128; +use codec::{Decode, Encode}; +use ofb::{ + cipher::{NewStreamCipher, SyncStreamCipher}, + Ofb, +}; +use std::{ + convert::{TryFrom, TryInto}, + path::PathBuf, +}; + +type AesOfb = Ofb; + +/// File name of the sealed AES key data. +pub const AES_KEY_FILE_AND_INIT_V: &str = "aes_key_and_iv_sealed_data.bin"; + +#[derive(Debug, Default, Encode, Decode, Clone, Copy, PartialEq, Eq)] +pub struct Aes { + pub key: [u8; 16], + pub init_vec: [u8; 16], +} + +impl Aes { + pub fn new(key: [u8; 16], init_vec: [u8; 16]) -> Self { + Self { key, init_vec } + } +} + +#[derive(Clone, Debug)] +pub struct AesSeal { + base_path: PathBuf, +} + +impl AesSeal { + pub fn new(base_path: PathBuf) -> Self { + Self { base_path } + } + + pub fn path(&self) -> PathBuf { + self.base_path.join(AES_KEY_FILE_AND_INIT_V) + } +} + +impl StateCrypto for Aes { + type Error = Error; + + fn encrypt(&self, data: &mut [u8]) -> Result<()> { + de_or_encrypt(self, data) + } + + fn decrypt(&self, data: &mut [u8]) -> Result<()> { + de_or_encrypt(self, data) + } +} + +impl TryFrom<&Aes> for AesOfb { + type Error = Error; + + fn try_from(aes: &Aes) -> std::result::Result { + AesOfb::new_var(&aes.key, &aes.init_vec).map_err(|_| Error::InvalidNonceKeyLength) + } +} + +/// If AES acts on the encrypted data it decrypts and vice versa +pub fn de_or_encrypt(aes: &Aes, data: &mut [u8]) -> Result<()> { + aes.try_into().map(|mut ofb: AesOfb| ofb.apply_keystream(data)) +} + +pub trait AesSealing { + fn unseal_key(&self) -> Result; + + fn exists(&self) -> bool; + + fn create_sealed_if_absent(&self) -> Result<()>; + + fn create_sealed(&self) -> Result<()>; +} + +#[cfg(feature = "sgx")] +pub use sgx::*; + +#[cfg(feature = "sgx")] +pub mod sgx { + use super::*; + use crate::key_repository::KeyRepository; + use itp_sgx_io::{seal, unseal, SealedIO}; + use log::info; + use sgx_rand::{Rng, StdRng}; + use std::sgxfs::SgxFile; + + /// Gets a repository for an AES key and initializes + /// a fresh key if it doesn't exist at `path`. + pub fn get_aes_repository(path: PathBuf) -> Result> { + let aes_seal = AesSeal::new(path); + aes_seal.create_sealed_if_absent()?; + let aes_key = aes_seal.unseal_key()?; + Ok(KeyRepository::new(aes_key, aes_seal.into())) + } + + impl AesSealing for AesSeal { + fn unseal_key(&self) -> Result { + self.unseal() + } + + fn exists(&self) -> bool { + SgxFile::open(self.path()).is_ok() + } + + fn create_sealed_if_absent(&self) -> Result<()> { + if !self.exists() { + info!("Keyfile not found, creating new! {}", self.path().display()); + return self.create_sealed() + } + Ok(()) + } + + fn create_sealed(&self) -> Result<()> { + let mut key = [0u8; 16]; + let mut iv = [0u8; 16]; + let mut rand = StdRng::new()?; + + rand.fill_bytes(&mut key); + rand.fill_bytes(&mut iv); + + Ok(self.seal(&Aes::new(key, iv))?) + } + } + + impl SealedIO for AesSeal { + type Error = Error; + type Unsealed = Aes; + + fn unseal(&self) -> Result { + Ok(unseal(self.path()).map(|b| Decode::decode(&mut b.as_slice()))??) + } + + fn seal(&self, unsealed: &Self::Unsealed) -> Result<()> { + Ok(unsealed.using_encoded(|bytes| seal(bytes, self.path()))?) + } + } +} + +#[cfg(feature = "test")] +pub mod sgx_tests { + use super::sgx::*; + use crate::{key_repository::AccessKey, AesSeal, AesSealing}; + use itp_sgx_temp_dir::TempDir; + + pub fn using_get_aes_repository_twice_initializes_key_only_once() { + let temp_dir = + TempDir::with_prefix("using_get_aes_repository_twice_initializes_key_only_once") + .unwrap(); + let temp_path = temp_dir.path().to_path_buf(); + let key1 = get_aes_repository(temp_path.clone()).unwrap().retrieve_key().unwrap(); + let key2 = get_aes_repository(temp_path).unwrap().retrieve_key().unwrap(); + assert_eq!(key1, key2); + } + + pub fn aes_sealing_works() { + let temp_dir = TempDir::with_prefix("aes_sealing_works").unwrap(); + let seal = AesSeal::new(temp_dir.path().to_path_buf()); + + // Create new sealed keys and unseal them + assert!(!seal.exists()); + seal.create_sealed_if_absent().unwrap(); + let key = seal.unseal_key().unwrap(); + + assert!(seal.exists()); + + // Should not change anything because the key is already there. + seal.create_sealed_if_absent().unwrap(); + let key_same = seal.unseal_key().unwrap(); + + assert_eq!(key, key_same); + + // Should overwrite previous keys. + seal.create_sealed().unwrap(); + let key_different = seal.unseal_key().unwrap(); + + assert_ne!(key_different, key); + } +} diff --git a/bitacross-worker/core-primitives/sgx/crypto/src/ed25519.rs b/bitacross-worker/core-primitives/sgx/crypto/src/ed25519.rs new file mode 100644 index 0000000000..153314eb4f --- /dev/null +++ b/bitacross-worker/core-primitives/sgx/crypto/src/ed25519.rs @@ -0,0 +1,180 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{ + error::{Error, Result}, + ToPubkey, +}; +use sp_core::ed25519; + +#[cfg(feature = "sgx")] +pub use sgx::*; + +/// File name of the sealed Ed25519 seed file. +pub const SEALED_SIGNER_SEED_FILE: &str = "ed25519_key_sealed.bin"; + +pub trait Ed25519Sealing { + fn unseal_pubkey(&self) -> Result; + + fn unseal_pair(&self) -> Result; + + fn exists(&self) -> bool; + + fn create_sealed_if_absent(&self) -> Result<()>; + + fn create_sealed(&self) -> Result<()>; +} + +impl ToPubkey for ed25519::Pair { + type Error = Error; + type Pubkey = ed25519::Public; + + fn pubkey(&self) -> Result { + Ok((*self).into()) + } +} + +#[cfg(feature = "sgx")] +pub mod sgx { + use super::SEALED_SIGNER_SEED_FILE; + use crate::{ + error::{Error, Result}, + key_repository::KeyRepository, + Ed25519Sealing, + }; + use codec::Encode; + use itp_sgx_io::{seal, unseal, SealedIO}; + use log::*; + use sgx_rand::{Rng, StdRng}; + use sp_core::{crypto::Pair, ed25519}; + use std::path::PathBuf; + + /// Gets a repository for an Ed25519 keypair and initializes + /// a fresh key pair if it doesn't exist at `path`. + pub fn get_ed25519_repository( + path: PathBuf, + ) -> Result> { + let ed25519_seal = Ed25519Seal::new(path); + ed25519_seal.create_sealed_if_absent()?; + let signing_pair = ed25519_seal.unseal_pair()?; + Ok(KeyRepository::new(signing_pair, ed25519_seal.into())) + } + + #[derive(Clone, Debug)] + pub struct Ed25519Seal { + base_path: PathBuf, + } + + impl Ed25519Seal { + pub fn new(base_path: PathBuf) -> Self { + Self { base_path } + } + + pub fn path(&self) -> PathBuf { + self.base_path.join(SEALED_SIGNER_SEED_FILE) + } + } + + impl Ed25519Sealing for Ed25519Seal { + fn unseal_pubkey(&self) -> Result { + self.unseal().map(Into::into) + } + + fn unseal_pair(&self) -> Result { + self.unseal() + } + + fn exists(&self) -> bool { + self.path().exists() + } + + fn create_sealed_if_absent(&self) -> Result<()> { + if !self.exists() { + info!("Keyfile not found, creating new! {}", self.path().display()); + return self.create_sealed() + } + Ok(()) + } + + fn create_sealed(&self) -> Result<()> { + let mut seed = [0u8; 32]; + let mut rand = StdRng::new()?; + rand.fill_bytes(&mut seed); + + Ok(seal(&seed, self.path())?) + } + } + + impl SealedIO for Ed25519Seal { + type Error = Error; + type Unsealed = ed25519::Pair; + + fn unseal(&self) -> Result { + let raw = unseal(self.path())?; + + ed25519::Pair::from_seed_slice(&raw) + .map_err(|e| Error::Other(format!("{:?}", e).into())) + } + + fn seal(&self, unsealed: &Self::Unsealed) -> Result<()> { + Ok(unsealed.seed().using_encoded(|bytes| seal(bytes, self.path()))?) + } + } +} + +#[cfg(feature = "test")] +pub mod sgx_tests { + use super::sgx::*; + use crate::{key_repository::AccessKey, Ed25519Sealing, ToPubkey}; + use itp_sgx_temp_dir::TempDir; + + pub fn using_get_ed25519_repository_twice_initializes_key_only_once() { + let temp_dir = + TempDir::with_prefix("using_get_rsa3072_repository_twice_initializes_key_only_once") + .unwrap(); + let temp_path = temp_dir.path().to_path_buf(); + let key1 = get_ed25519_repository(temp_path.clone()).unwrap().retrieve_key().unwrap(); + let key2 = get_ed25519_repository(temp_path).unwrap().retrieve_key().unwrap(); + assert_eq!(key1.pubkey().unwrap(), key2.pubkey().unwrap()); + } + + pub fn ed25529_sealing_works() { + let temp_dir = TempDir::with_prefix("ed25529_sealing_works").unwrap(); + let seal = Ed25519Seal::new(temp_dir.path().to_path_buf()); + + // Create new sealed keys and unseal them. + assert!(!seal.exists()); + seal.create_sealed_if_absent().unwrap(); + let pair = seal.unseal_pair().unwrap(); + let pubkey = seal.unseal_pubkey().unwrap(); + + assert!(seal.exists()); + assert_eq!(pair.pubkey().unwrap(), pubkey); + + // Should not change anything because the key is already there. + seal.create_sealed_if_absent().unwrap(); + let pair_same = seal.unseal_pair().unwrap(); + + assert_eq!(pair.pubkey().unwrap(), pair_same.pubkey().unwrap()); + + // Should overwrite previous keys. + seal.create_sealed().unwrap(); + let pair_different = seal.unseal_pair().unwrap(); + + assert_ne!(pair_different.pubkey().unwrap(), pair.pubkey().unwrap()); + } +} diff --git a/bitacross-worker/core-primitives/sgx/crypto/src/ed25519_derivation.rs b/bitacross-worker/core-primitives/sgx/crypto/src/ed25519_derivation.rs new file mode 100644 index 0000000000..25e51279c7 --- /dev/null +++ b/bitacross-worker/core-primitives/sgx/crypto/src/ed25519_derivation.rs @@ -0,0 +1,36 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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(all(not(feature = "std"), feature = "sgx"))] +use crate::sgx_reexport_prelude::*; + +use crate::error::Result; +use sgx_crypto_helper::rsa3072::Rsa3072KeyPair; +use sp_core::{blake2_256, ed25519::Pair as Ed25519Pair, Pair}; + +/// Trait to derive an Ed25519 key pair. +pub trait DeriveEd25519 { + fn derive_ed25519(&self) -> Result; +} + +impl DeriveEd25519 for Rsa3072KeyPair { + fn derive_ed25519(&self) -> Result { + let encoded_key = serde_json::to_vec(self)?; + let seed = blake2_256(&encoded_key); + Ok(Ed25519Pair::from_seed(&seed)) + } +} diff --git a/bitacross-worker/core-primitives/sgx/crypto/src/error.rs b/bitacross-worker/core-primitives/sgx/crypto/src/error.rs new file mode 100644 index 0000000000..4fa619d136 --- /dev/null +++ b/bitacross-worker/core-primitives/sgx/crypto/src/error.rs @@ -0,0 +1,43 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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(all(not(feature = "std"), feature = "sgx"))] +use crate::sgx_reexport_prelude::*; + +use derive_more::{Display, From}; +use sgx_types::sgx_status_t; +use std::prelude::v1::Box; + +#[derive(Debug, Display, From)] +pub enum Error { + IO(std::io::Error), + InvalidNonceKeyLength, + Codec(codec::Error), + Serialization(serde_json::Error), + LockPoisoning, + Other(Box), +} + +pub type Result = core::result::Result; + +impl From for sgx_status_t { + /// return sgx_status for top level enclave functions + fn from(error: Error) -> sgx_status_t { + log::warn!("Transform non-sgx-error into `SGX_ERROR_UNEXPECTED`: {:?}", error); + sgx_status_t::SGX_ERROR_UNEXPECTED + } +} diff --git a/bitacross-worker/core-primitives/sgx/crypto/src/key_repository.rs b/bitacross-worker/core-primitives/sgx/crypto/src/key_repository.rs new file mode 100644 index 0000000000..41ca5ae860 --- /dev/null +++ b/bitacross-worker/core-primitives/sgx/crypto/src/key_repository.rs @@ -0,0 +1,122 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 = "sgx")] +use std::sync::SgxRwLock as RwLock; + +#[cfg(feature = "std")] +use std::sync::RwLock; + +use crate::{ + error::{Error, Result}, + ToPubkey, +}; +use itp_sgx_io::SealedIO; +use std::sync::Arc; + +/// Access a cryptographic key. +pub trait AccessKey { + type KeyType; + + fn retrieve_key(&self) -> Result; +} + +/// Access a cryptographic public key. +pub trait AccessPubkey { + type KeyType; + + fn retrieve_pubkey(&self) -> Result; +} + +/// Mutate a cryptographic key. +pub trait MutateKey { + fn update_key(&self, key: KeyType) -> Result<()>; +} + +/// Repository implementation. Stores a cryptographic key in-memory and in a file backed. +/// Uses the SealedIO trait for the file backend. +pub struct KeyRepository { + key_lock: RwLock, + sealed_io: Arc, +} + +impl KeyRepository { + pub fn new(key: KeyType, sealed_io: Arc) -> Self { + KeyRepository { key_lock: RwLock::new(key), sealed_io } + } +} + +impl AccessKey for KeyRepository +where + KeyType: Clone, + SealedIo: SealedIO, +{ + type KeyType = KeyType; + + fn retrieve_key(&self) -> Result { + self.key_lock.read().map_err(|_| Error::LockPoisoning).map(|l| l.clone()) + } +} + +impl AccessPubkey for KeyRepository +where + Pair: ToPubkey + Clone, + SealedIo: SealedIO, +{ + type KeyType = ::Pubkey; + + fn retrieve_pubkey(&self) -> Result { + self.key_lock.read().map_err(|_| Error::LockPoisoning).map(|p| p.pubkey())? + } +} + +impl MutateKey for KeyRepository +where + KeyType: Clone, + SealedIo: SealedIO, +{ + fn update_key(&self, key: KeyType) -> Result<()> { + let mut key_lock = self.key_lock.write().map_err(|_| Error::LockPoisoning)?; + + self.sealed_io.seal(&key)?; + *key_lock = self.sealed_io.unseal()?; + + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::{aes::Aes, mocks::AesSealMock}; + + type TestKeyRepository = KeyRepository; + + #[test] + fn update_and_retrieve_key_works() { + let seal_mock = Arc::new(AesSealMock::default()); + let key_repository = TestKeyRepository::new(seal_mock.unseal().unwrap(), seal_mock.clone()); + + assert_eq!(seal_mock.unseal().unwrap(), key_repository.retrieve_key().unwrap()); + + let updated_key = Aes::new([2u8; 16], [0u8; 16]); + key_repository.update_key(updated_key).unwrap(); + + assert_eq!(updated_key, key_repository.retrieve_key().unwrap()); + assert_eq!(updated_key, seal_mock.unseal().unwrap()); + } +} diff --git a/bitacross-worker/core-primitives/sgx/crypto/src/lib.rs b/bitacross-worker/core-primitives/sgx/crypto/src/lib.rs new file mode 100644 index 0000000000..832239c027 --- /dev/null +++ b/bitacross-worker/core-primitives/sgx/crypto/src/lib.rs @@ -0,0 +1,63 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 different crypto schemes that we use in sgx + +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg(all(feature = "std", feature = "sgx"))] +compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the same time"); + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +#[macro_use] +extern crate sgx_tstd as std; + +// re-export module to properly feature gate sgx and regular std environment +#[cfg(all(not(feature = "std"), feature = "sgx"))] +pub mod sgx_reexport_prelude { + pub use serde_json_sgx as serde_json; +} + +pub mod aes; +pub mod ed25519; +pub mod ed25519_derivation; +pub mod error; +pub mod key_repository; +pub mod rsa3072; +pub mod traits; + +pub use self::{aes::*, ed25519::*, rsa3072::*}; +pub use error::*; +pub use traits::*; + +#[cfg(feature = "mocks")] +pub mod mocks; + +#[cfg(feature = "test")] +pub mod tests { + pub use super::ed25519::sgx_tests::{ + ed25529_sealing_works, using_get_ed25519_repository_twice_initializes_key_only_once, + }; + + pub use super::rsa3072::sgx_tests::{ + rsa3072_sealing_works, using_get_rsa3072_repository_twice_initializes_key_only_once, + }; + + pub use super::aes::sgx_tests::{ + aes_sealing_works, using_get_aes_repository_twice_initializes_key_only_once, + }; +} diff --git a/bitacross-worker/core-primitives/sgx/crypto/src/mocks.rs b/bitacross-worker/core-primitives/sgx/crypto/src/mocks.rs new file mode 100644 index 0000000000..0e199378fd --- /dev/null +++ b/bitacross-worker/core-primitives/sgx/crypto/src/mocks.rs @@ -0,0 +1,118 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 = "sgx")] +use std::sync::SgxRwLock as RwLock; + +#[cfg(feature = "std")] +use std::sync::RwLock; + +use crate::{ + aes::Aes, + error::{Error, Result}, + key_repository::{AccessKey, MutateKey}, +}; +use itp_sgx_io::{SealedIO, StaticSealedIO}; +use sgx_crypto_helper::rsa3072::Rsa3072KeyPair; + +#[derive(Default)] +pub struct KeyRepositoryMock +where + KeyType: Clone + Default, +{ + key: RwLock, +} + +impl KeyRepositoryMock +where + KeyType: Clone + Default, +{ + pub fn new(key: KeyType) -> Self { + KeyRepositoryMock { key: RwLock::new(key) } + } +} + +impl AccessKey for KeyRepositoryMock +where + KeyType: Clone + Default, +{ + type KeyType = KeyType; + + fn retrieve_key(&self) -> Result { + Ok(self.key.read().unwrap().clone()) + } +} + +impl MutateKey for KeyRepositoryMock +where + KeyType: Clone + Default, +{ + fn update_key(&self, key: KeyType) -> Result<()> { + let mut lock = self.key.write().unwrap(); + *lock = key; + Ok(()) + } +} + +#[derive(Default)] +pub struct AesSealMock { + aes: RwLock, +} + +impl StaticSealedIO for AesSealMock { + type Error = Error; + type Unsealed = Aes; + + fn unseal_from_static_file() -> Result { + Ok(Aes::default()) + } + + fn seal_to_static_file(_unsealed: &Self::Unsealed) -> Result<()> { + Ok(()) + } +} + +impl SealedIO for AesSealMock { + type Error = Error; + type Unsealed = Aes; + + fn unseal(&self) -> std::result::Result { + self.aes.read().map_err(|e| Error::Other(format!("{:?}", e).into())).map(|k| *k) + } + + fn seal(&self, unsealed: &Self::Unsealed) -> Result<()> { + let mut aes_lock = self.aes.write().map_err(|e| Error::Other(format!("{:?}", e).into()))?; + *aes_lock = *unsealed; + Ok(()) + } +} + +#[derive(Default)] +pub struct Rsa3072SealMock {} + +impl StaticSealedIO for Rsa3072SealMock { + type Error = Error; + type Unsealed = Rsa3072KeyPair; + + fn unseal_from_static_file() -> Result { + Ok(Rsa3072KeyPair::default()) + } + + fn seal_to_static_file(_unsealed: &Self::Unsealed) -> Result<()> { + Ok(()) + } +} diff --git a/bitacross-worker/core-primitives/sgx/crypto/src/rsa3072.rs b/bitacross-worker/core-primitives/sgx/crypto/src/rsa3072.rs new file mode 100644 index 0000000000..3a63a0d11d --- /dev/null +++ b/bitacross-worker/core-primitives/sgx/crypto/src/rsa3072.rs @@ -0,0 +1,221 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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(all(not(feature = "std"), feature = "sgx"))] +use crate::sgx_reexport_prelude::*; + +use crate::{ + error::{Error, Result}, + traits::{ShieldingCryptoDecrypt, ShieldingCryptoEncrypt}, + ToPubkey, +}; +use sgx_crypto_helper::{ + rsa3072::{Rsa3072KeyPair, Rsa3072PubKey}, + RsaKeyPair, +}; +use std::vec::Vec; + +// Reexport sgx module +#[cfg(feature = "sgx")] +pub use sgx::*; + +/// File name of the sealed RSA key file. +pub const RSA3072_SEALED_KEY_FILE: &str = "rsa3072_key_sealed.bin"; + +impl ShieldingCryptoEncrypt for Rsa3072KeyPair { + type Error = Error; + + fn encrypt(&self, data: &[u8]) -> Result> { + let mut cipher_buffer = Vec::new(); + self.encrypt_buffer(data, &mut cipher_buffer) + .map_err(|e| Error::Other(format!("{:?}", e).into()))?; + Ok(cipher_buffer) + } +} + +impl ShieldingCryptoDecrypt for Rsa3072KeyPair { + type Error = Error; + + fn decrypt(&self, data: &[u8]) -> Result> { + let mut decrypted_buffer = Vec::new(); + self.decrypt_buffer(data, &mut decrypted_buffer) + .map_err(|e| Error::Other(format!("{:?}", e).into()))?; + Ok(decrypted_buffer) + } +} + +impl ShieldingCryptoEncrypt for Rsa3072PubKey { + type Error = Error; + + fn encrypt(&self, data: &[u8]) -> Result> { + let mut cipher_buffer = Vec::new(); + self.encrypt_buffer(data, &mut cipher_buffer) + .map_err(|e| Error::Other(format!("{:?}", e).into()))?; + Ok(cipher_buffer) + } +} + +impl ToPubkey for Rsa3072KeyPair { + type Error = Error; + type Pubkey = Rsa3072PubKey; + + fn pubkey(&self) -> Result { + self.export_pubkey().map_err(|e| Error::Other(format!("{:?}", e).into())) + } +} + +pub trait RsaSealing { + fn unseal_pubkey(&self) -> Result; + + fn unseal_pair(&self) -> Result; + + fn exists(&self) -> bool; + + fn create_sealed_if_absent(&self) -> Result<()>; + + fn create_sealed(&self) -> Result<()>; +} + +#[cfg(feature = "sgx")] +pub mod sgx { + use super::*; + use crate::key_repository::KeyRepository; + use itp_sgx_io::{seal, unseal, SealedIO}; + use log::*; + use std::path::PathBuf; + + /// Gets a repository for an Rsa3072 keypair and initializes + /// a fresh key pair if it doesn't exist at `path`. + pub fn get_rsa3072_repository( + path: PathBuf, + ) -> Result> { + let rsa_seal = Rsa3072Seal::new(path); + rsa_seal.create_sealed_if_absent()?; + let shielding_key = rsa_seal.unseal_pair()?; + Ok(KeyRepository::new(shielding_key, rsa_seal.into())) + } + + #[derive(Clone, Debug)] + pub struct Rsa3072Seal { + base_path: PathBuf, + } + + impl Rsa3072Seal { + pub fn new(base_path: PathBuf) -> Self { + Self { base_path } + } + + pub fn path(&self) -> PathBuf { + self.base_path.join(RSA3072_SEALED_KEY_FILE) + } + } + + impl RsaSealing for Rsa3072Seal { + fn unseal_pubkey(&self) -> Result { + self.unseal()?.pubkey() + } + + fn unseal_pair(&self) -> Result { + self.unseal() + } + + fn exists(&self) -> bool { + self.path().exists() + } + + fn create_sealed_if_absent(&self) -> Result<()> { + if !self.exists() { + info!("Keyfile not found, creating new! {}", self.path().display()); + return self.create_sealed() + } + Ok(()) + } + + fn create_sealed(&self) -> Result<()> { + let rsa_keypair = + Rsa3072KeyPair::new().map_err(|e| Error::Other(format!("{:?}", e).into()))?; + info!("Generated RSA3072 key pair. PubKey: {:?}", rsa_keypair.pubkey()?); + self.seal(&rsa_keypair) + } + } + + impl SealedIO for Rsa3072Seal { + type Error = Error; + type Unsealed = Rsa3072KeyPair; + + fn unseal(&self) -> Result { + let raw = unseal(self.path())?; + let key: Rsa3072KeyPair = serde_json::from_slice(&raw) + .map_err(|e| Error::Other(format!("{:?}", e).into()))?; + Ok(key.into()) + } + + fn seal(&self, unsealed: &Self::Unsealed) -> Result<()> { + let key_json = serde_json::to_vec(&unsealed) + .map_err(|e| Error::Other(format!("{:?}", e).into()))?; + Ok(seal(&key_json, self.path())?) + } + } +} + +#[cfg(feature = "test")] +pub mod sgx_tests { + use super::{serde_json, sgx::*}; + use crate::{key_repository::AccessKey, RsaSealing, ToPubkey}; + use itp_sgx_temp_dir::TempDir; + use sgx_crypto_helper::rsa3072::Rsa3072PubKey; + + /// Helper method because Rsa3072 does not implement `Eq`. + pub fn equal(pubkey1: &Rsa3072PubKey, pubkey2: &Rsa3072PubKey) -> bool { + serde_json::to_vec(pubkey1).unwrap() == serde_json::to_vec(pubkey2).unwrap() + } + + pub fn using_get_rsa3072_repository_twice_initializes_key_only_once() { + let temp_dir = + TempDir::with_prefix("using_get_rsa3072_repository_twice_initializes_key_only_once") + .unwrap(); + let temp_path = temp_dir.path().to_path_buf(); + let key1 = get_rsa3072_repository(temp_path.clone()).unwrap().retrieve_key().unwrap(); + let key2 = get_rsa3072_repository(temp_path).unwrap().retrieve_key().unwrap(); + assert!(equal(&key1.pubkey().unwrap(), &key2.pubkey().unwrap())); + } + + pub fn rsa3072_sealing_works() { + let temp_dir = TempDir::with_prefix("rsa3072_sealing_works").unwrap(); + let seal = Rsa3072Seal::new(temp_dir.path().to_path_buf()); + + // Create new sealed keys and unseal them + assert!(!seal.exists()); + seal.create_sealed_if_absent().unwrap(); + let pair = seal.unseal_pair().unwrap(); + let pubkey = seal.unseal_pubkey().unwrap(); + + assert!(seal.exists()); + assert!(equal(&pair.pubkey().unwrap(), &pubkey)); + + // Should not change anything because the key is already there. + seal.create_sealed_if_absent().unwrap(); + let pair_same = seal.unseal_pair().unwrap(); + + assert!(equal(&pair.pubkey().unwrap(), &pair_same.pubkey().unwrap())); + + // Should overwrite previous keys. + seal.create_sealed().unwrap(); + let pair_different = seal.unseal_pair().unwrap(); + + assert!(!equal(&pair_different.pubkey().unwrap(), &pair.pubkey().unwrap())); + } +} diff --git a/bitacross-worker/core-primitives/sgx/crypto/src/traits.rs b/bitacross-worker/core-primitives/sgx/crypto/src/traits.rs new file mode 100644 index 0000000000..1d0aef5798 --- /dev/null +++ b/bitacross-worker/core-primitives/sgx/crypto/src/traits.rs @@ -0,0 +1,42 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +//! Abstraction over the state crypto that is used in the enclave +use std::{fmt::Debug, vec::Vec}; + +pub trait StateCrypto { + type Error: Debug; + fn encrypt(&self, data: &mut [u8]) -> Result<(), Self::Error>; + fn decrypt(&self, data: &mut [u8]) -> Result<(), Self::Error>; +} + +pub trait ShieldingCryptoEncrypt { + type Error: Debug; + fn encrypt(&self, data: &[u8]) -> Result, Self::Error>; +} + +pub trait ShieldingCryptoDecrypt { + type Error: Debug; + fn decrypt(&self, data: &[u8]) -> Result, Self::Error>; +} + +pub trait ToPubkey { + type Error: Debug; + type Pubkey; + + fn pubkey(&self) -> Result; +} diff --git a/bitacross-worker/core-primitives/sgx/io/Cargo.toml b/bitacross-worker/core-primitives/sgx/io/Cargo.toml new file mode 100644 index 0000000000..9c358d438b --- /dev/null +++ b/bitacross-worker/core-primitives/sgx/io/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "itp-sgx-io" +version = "0.8.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] + +# sgx deps +sgx_tstd = { optional = true, features = ["untrusted_fs"], branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git" } + +[features] +default = ["std"] +std = [] +sgx = [ + "sgx_tstd", +] diff --git a/bitacross-worker/core-primitives/sgx/io/src/lib.rs b/bitacross-worker/core-primitives/sgx/io/src/lib.rs new file mode 100644 index 0000000000..4f6d4eaa35 --- /dev/null +++ b/bitacross-worker/core-primitives/sgx/io/src/lib.rs @@ -0,0 +1,94 @@ +//! SGX file IO abstractions + +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg(all(feature = "std", feature = "sgx"))] +compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the same time"); + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +extern crate sgx_tstd as std; + +use std::{ + convert::AsRef, + fs, + io::{Read, Result as IOResult, Write}, + path::Path, + string::String, + vec::Vec, +}; + +#[cfg(feature = "sgx")] +pub use sgx::*; + +/// Abstraction around IO that is supposed to use the `std::io::File` +pub trait IO: Sized { + type Error: From + std::fmt::Debug + 'static; + + fn read() -> Result; + fn write(&self) -> Result<(), Self::Error>; +} + +/// Abstraction around IO that is supposed to use `SgxFile`. We expose it also in `std` to +/// be able to put it as trait bounds in `std` and use it in tests. +/// +/// This is the static method (or associated function) version, should be made obsolete over time, +/// since it has state, but hides it in a global state. Makes it difficult to mock. +pub trait StaticSealedIO: Sized { + type Error: From + std::fmt::Debug + 'static; + + /// Type that is unsealed. + type Unsealed; + + fn unseal_from_static_file() -> Result; + fn seal_to_static_file(unsealed: &Self::Unsealed) -> Result<(), Self::Error>; +} + +/// Abstraction around IO that is supposed to use `SgxFile`. We expose it also in `std` to +/// be able to put it as trait bounds in `std` and use it in tests. +/// +pub trait SealedIO: Sized { + type Error: From + std::fmt::Debug + 'static; + + /// Type that is unsealed. + type Unsealed; + + fn unseal(&self) -> Result; + fn seal(&self, unsealed: &Self::Unsealed) -> Result<(), Self::Error>; +} + +pub fn read>(path: P) -> IOResult> { + let mut buf = Vec::new(); + fs::File::open(path).map(|mut f| f.read_to_end(&mut buf))??; + Ok(buf) +} + +pub fn write>(bytes: &[u8], path: P) -> IOResult<()> { + fs::File::create(path).map(|mut f| f.write_all(bytes))? +} + +pub fn read_to_string>(filepath: P) -> IOResult { + let mut contents = String::new(); + fs::File::open(filepath).map(|mut f| f.read_to_string(&mut contents))??; + Ok(contents) +} + +#[cfg(feature = "sgx")] +mod sgx { + use std::{ + convert::AsRef, + io::{Read, Result, Write}, + path::Path, + sgxfs::SgxFile, + vec::Vec, + }; + + pub fn unseal>(path: P) -> Result> { + let mut buf = Vec::new(); + SgxFile::open(path).map(|mut f| f.read_to_end(&mut buf))??; + Ok(buf) + } + + pub fn seal>(bytes: &[u8], path: P) -> Result<()> { + SgxFile::create(path).map(|mut f| f.write_all(bytes))? + } +} diff --git a/bitacross-worker/core-primitives/sgx/temp-dir/Cargo.toml b/bitacross-worker/core-primitives/sgx/temp-dir/Cargo.toml new file mode 100644 index 0000000000..c86fcafbd1 --- /dev/null +++ b/bitacross-worker/core-primitives/sgx/temp-dir/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "itp-sgx-temp-dir" +version = "0.1.0" +edition = "2021" + +[dependencies] +lazy_static = { version = "1.1.0", features = ["spin_no_std"] } + +# sgx deps +sgx_tstd = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git", optional = true } + +[dev-dependencies.safe-lock] +version = "^0.1" + +[features] +default = ["std"] +std = [] +sgx = [ + "sgx_tstd", +] diff --git a/bitacross-worker/core-primitives/sgx/temp-dir/src/lib.rs b/bitacross-worker/core-primitives/sgx/temp-dir/src/lib.rs new file mode 100644 index 0000000000..f8332fb74f --- /dev/null +++ b/bitacross-worker/core-primitives/sgx/temp-dir/src/lib.rs @@ -0,0 +1,192 @@ +//! # temp-dir +//! +//! Copied from the original tempdir crate with tiny adjustments for SGX-compatibility. +//! +//! Note: The temp-dir is deprecated and there might be uncovered security aspects. If we want to +//! use this in production, we should run some checks. + +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg(all(feature = "std", feature = "sgx"))] +compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the same time"); + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +extern crate sgx_tstd as std; + +use core::sync::atomic::{AtomicU32, Ordering}; +use std::{ + borrow::ToOwned, + collections::hash_map::RandomState, + format, + hash::{BuildHasher, Hasher}, + path::{Path, PathBuf}, + string::String, +}; + +/// Serve some low-security random ID to prevent temp-dir clashes across multiple processes. +fn rand_id() -> String { + // u64 always has more than 4 bytes so this never panics. + format!("{:x}", RandomState::new().build_hasher().finish())[..4].to_owned() +} + +lazy_static::lazy_static! { + /// A unique identifier, which is instanciated upon process start, but it is + /// not the process id itself. + /// + /// This is a workaround for `sgx_tstd` lib not exposing the `process::id()`. + pub static ref PROCESS_UNIQUE_ID: String = rand_id(); +} + +static COUNTER: AtomicU32 = AtomicU32::new(0); + +/// The path of an existing writable directory in a system temporary directory. +/// +/// Drop the struct to delete the directory and everything under it. +/// Deletes symbolic links and does not follow them. +/// +/// Ignores any error while deleting. +/// See [`TempDir::panic_on_cleanup_error`](struct.TempDir.html#method.panic_on_cleanup_error). +/// +/// # Example +/// ```rust +/// use itp_sgx_temp_dir::TempDir; +/// let d = TempDir::new().unwrap(); +/// // Prints "/tmp/t1a9b-0". +/// println!("{:?}", d.path()); +/// let f = d.child("file1"); +/// // Prints "/tmp/t1a9b-0/file1". +/// println!("{:?}", f); +/// std::fs::write(&f, b"abc").unwrap(); +/// assert_eq!( +/// "abc", +/// std::fs::read_to_string(&f).unwrap(), +/// ); +/// // Prints "/tmp/t1a9b-1". +/// println!("{:?}", TempDir::new().unwrap().path()); +/// ``` +#[derive(Clone, PartialOrd, Ord, PartialEq, Eq, Hash, Debug)] +pub struct TempDir { + path_buf: Option, + panic_on_delete_err: bool, +} +impl TempDir { + fn remove_dir(path: &Path) -> Result<(), std::io::Error> { + match std::fs::remove_dir_all(path) { + Ok(()) => Ok(()), + Err(e) if e.kind() == std::io::ErrorKind::NotFound => Ok(()), + Err(e) => Err(std::io::Error::new( + e.kind(), + format!("error removing directory and contents {:?}: {}", path, e), + )), + } + } + + /// Create a new empty directory in a system temporary directory. + /// + /// Drop the struct to delete the directory and everything under it. + /// Deletes symbolic links and does not follow them. + /// + /// Ignores any error while deleting. + /// See [`TempDir::panic_on_cleanup_error`](struct.TempDir.html#method.panic_on_cleanup_error). + /// + /// # Errors + /// Returns `Err` when it fails to create the directory. + /// + /// # Example + /// ```rust + /// // Prints "/tmp/t1a9b-0". + /// println!("{:?}", itp_sgx_temp_dir::TempDir::new().unwrap().path()); + /// ``` + pub fn new() -> Result { + // Prefix with 't' to avoid name collisions with `temp-file` crate. + Self::with_prefix("t") + } + + /// Create a new empty directory in a system temporary directory. + /// Use `prefix` as the first part of the directory's name. + /// + /// Drop the struct to delete the directory and everything under it. + /// Deletes symbolic links and does not follow them. + /// + /// Ignores any error while deleting. + /// See [`TempDir::panic_on_cleanup_error`](struct.TempDir.html#method.panic_on_cleanup_error). + /// + /// # Errors + /// Returns `Err` when it fails to create the directory. + /// + /// # Example + /// ```rust + /// // Prints "/tmp/ok1a9b-0". + /// println!("{:?}", itp_sgx_temp_dir::TempDir::with_prefix("ok").unwrap().path()); + /// ``` + pub fn with_prefix(prefix: impl AsRef) -> Result { + let path_buf = std::env::temp_dir().join(format!( + "{}{}-{:x}", + prefix.as_ref(), + // std::process::id(), -> The original tempdir crate had this, but the sgx-std lib does not expose it. + *PROCESS_UNIQUE_ID, + COUNTER.fetch_add(1, Ordering::AcqRel), + )); + std::fs::create_dir(&path_buf).map_err(|e| { + std::io::Error::new( + e.kind(), + format!("error creating directory {:?}: {}", &path_buf, e), + ) + })?; + Ok(Self { path_buf: Some(path_buf), panic_on_delete_err: false }) + } + + /// Remove the directory on its contents now. Do nothing later on drop. + /// + /// # Errors + /// Returns an error if the directory exists and we fail to remove it and its contents. + #[allow(clippy::missing_panics_doc)] + pub fn cleanup(mut self) -> Result<(), std::io::Error> { + Self::remove_dir(&self.path_buf.take().unwrap()) + } + + /// Make the struct panic on Drop if it hits an error while + /// removing the directory or its contents. + #[must_use] + pub fn panic_on_cleanup_error(mut self) -> Self { + Self { path_buf: self.path_buf.take(), panic_on_delete_err: true } + } + + /// Do not delete the directory or its contents. + /// + /// This is useful when debugging a test. + pub fn leak(mut self) { + self.path_buf.take(); + } + + /// The path to the directory. + #[must_use] + #[allow(clippy::missing_panics_doc)] + pub fn path(&self) -> &Path { + self.path_buf.as_ref().unwrap() + } + + /// The path to `name` under the directory. + #[must_use] + #[allow(clippy::missing_panics_doc)] + pub fn child(&self, name: impl AsRef) -> PathBuf { + let mut result = self.path_buf.as_ref().unwrap().clone(); + result.push(name.as_ref()); + result + } +} +impl Drop for TempDir { + fn drop(&mut self) { + if let Some(path) = self.path_buf.take() { + let result = Self::remove_dir(&path); + if self.panic_on_delete_err { + if let Err(e) = result { + panic!("{}", e); + } + } + } + } +} + +#[cfg(test)] +mod test; diff --git a/bitacross-worker/core-primitives/sgx/temp-dir/src/test.rs b/bitacross-worker/core-primitives/sgx/temp-dir/src/test.rs new file mode 100644 index 0000000000..8b3ac50c43 --- /dev/null +++ b/bitacross-worker/core-primitives/sgx/temp-dir/src/test.rs @@ -0,0 +1,231 @@ +use crate::{TempDir, COUNTER}; +use core::sync::atomic::Ordering; +use safe_lock::SafeLock; +use std::{io::ErrorKind, path::Path}; + +// The error tests require all tests to run single-threaded. +static LOCK: SafeLock = SafeLock::new(); + +fn make_non_writable(path: &Path) { + assert!(std::process::Command::new("chmod") + .arg("-w") + .arg(path) + .status() + .unwrap() + .success()); +} + +fn make_writable(path: &Path) { + assert!(std::process::Command::new("chmod") + .arg("u+w") + .arg(path) + .status() + .unwrap() + .success()); +} + +fn should_skip_cleanup_test() -> bool { + // On Gitlab's shared CI runners, the cleanup always succeeds and the + // test fails. So we skip these tests when it's running on Gitlab CI. + // if std::env::current_dir().unwrap().starts_with("/builds/") { + // println!("Running on Gitlab CI. Skipping test."); + // return true; + // } + // false + + // The above code was from the original. However, for some reason the + // cleanup always succeeds on my local machine too. I am not sure why + // this is the case. So we skip them always for now. + true +} + +#[test] +fn new() { + let _guard = LOCK.lock(); + let temp_dir = TempDir::new().unwrap(); + println!("{:?}", temp_dir); + println!("{:?}", TempDir::new().unwrap()); + let metadata = std::fs::metadata(temp_dir.path()).unwrap(); + assert!(metadata.is_dir()); + let temp_dir2 = TempDir::new().unwrap(); + assert_ne!(temp_dir.path(), temp_dir2.path()); +} + +#[test] +fn new_error() { + let _guard = LOCK.lock(); + let previous_counter_value = COUNTER.load(Ordering::SeqCst); + let temp_dir = TempDir::new().unwrap(); + let dir_path = temp_dir.path().to_path_buf(); + COUNTER.store(previous_counter_value, Ordering::SeqCst); + let e = TempDir::new().unwrap_err(); + assert_eq!(std::io::ErrorKind::AlreadyExists, e.kind()); + assert!( + e.to_string().starts_with(&format!("error creating directory {:?}: ", dir_path)), + "unexpected error {:?}", + e + ); +} + +#[test] +fn with_prefix() { + let _guard = LOCK.lock(); + let temp_dir = TempDir::with_prefix("prefix1").unwrap(); + let name = temp_dir.path().file_name().unwrap(); + assert!(name.to_str().unwrap().starts_with("prefix1"), "{:?}", temp_dir); + let metadata = std::fs::metadata(temp_dir.path()).unwrap(); + assert!(metadata.is_dir()); + let temp_dir2 = TempDir::new().unwrap(); + assert_ne!(temp_dir.path(), temp_dir2.path()); +} + +#[test] +fn with_prefix_error() { + let _guard = LOCK.lock(); + let previous_counter_value = COUNTER.load(Ordering::SeqCst); + let temp_dir = TempDir::with_prefix("prefix1").unwrap(); + COUNTER.store(previous_counter_value, Ordering::SeqCst); + let e = TempDir::with_prefix("prefix1").unwrap_err(); + assert_eq!(std::io::ErrorKind::AlreadyExists, e.kind()); + assert!( + e.to_string() + .starts_with(&format!("error creating directory {:?}: ", temp_dir.path())), + "unexpected error {:?}", + e + ); +} + +#[test] +fn child() { + let _guard = LOCK.lock(); + let temp_dir = TempDir::new().unwrap(); + let file1_path = temp_dir.child("file1"); + assert!(file1_path.ends_with("file1"), "{:?}", file1_path.to_string_lossy()); + assert!(file1_path.starts_with(temp_dir.path()), "{:?}", file1_path.to_string_lossy()); + std::fs::write(&file1_path, b"abc").unwrap(); +} + +#[test] +fn cleanup() { + let _guard = LOCK.lock(); + let temp_dir = TempDir::new().unwrap(); + std::fs::write(&temp_dir.child("file1"), b"abc").unwrap(); + let dir_path = temp_dir.path().to_path_buf(); + std::fs::metadata(&dir_path).unwrap(); + temp_dir.cleanup().unwrap(); + assert_eq!(ErrorKind::NotFound, std::fs::metadata(&dir_path).unwrap_err().kind()); +} + +#[test] +fn cleanup_already_deleted() { + let _guard = LOCK.lock(); + let temp_dir = TempDir::new().unwrap(); + std::fs::remove_dir_all(temp_dir.path()).unwrap(); + temp_dir.cleanup().unwrap(); +} + +#[cfg(unix)] +#[test] +fn cleanup_error() { + if should_skip_cleanup_test() { + return + } + let _guard = LOCK.lock(); + let temp_dir = TempDir::new().unwrap(); + let dir_path = temp_dir.path().to_path_buf(); + let file1_path = temp_dir.child("file1"); + std::fs::write(&file1_path, b"abc").unwrap(); + make_non_writable(&dir_path); + let result = temp_dir.cleanup(); + std::fs::metadata(&dir_path).unwrap(); + std::fs::metadata(&file1_path).unwrap(); + make_writable(&dir_path); + std::fs::remove_dir_all(&dir_path).unwrap(); + let e = result.unwrap_err(); + assert_eq!(std::io::ErrorKind::PermissionDenied, e.kind()); + assert!( + e.to_string() + .starts_with(&format!("error removing directory and contents {:?}: ", dir_path)), + "unexpected error {:?}", + e + ); +} + +#[test] +fn test_drop() { + let _guard = LOCK.lock(); + let temp_dir = TempDir::new().unwrap(); + let dir_path = temp_dir.path().to_path_buf(); + let file1_path = temp_dir.child("file1"); + std::fs::write(&file1_path, b"abc").unwrap(); + TempDir::new().unwrap(); + std::fs::metadata(&dir_path).unwrap(); + std::fs::metadata(&file1_path).unwrap(); + drop(temp_dir); + assert_eq!(ErrorKind::NotFound, std::fs::metadata(&dir_path).unwrap_err().kind()); + assert_eq!(ErrorKind::NotFound, std::fs::metadata(&file1_path).unwrap_err().kind()); +} + +#[test] +fn drop_already_deleted() { + let _guard = LOCK.lock(); + let temp_dir = TempDir::new().unwrap(); + std::fs::remove_dir(temp_dir.path()).unwrap(); +} + +#[cfg(unix)] +#[test] +fn drop_error_ignored() { + if should_skip_cleanup_test() { + return + } + let _guard = LOCK.lock(); + let temp_dir = TempDir::new().unwrap(); + let dir_path = temp_dir.path().to_path_buf(); + let file1_path = temp_dir.child("file1"); + std::fs::write(&file1_path, b"abc").unwrap(); + make_non_writable(&dir_path); + drop(temp_dir); + std::fs::metadata(&dir_path).unwrap(); + std::fs::metadata(&file1_path).unwrap(); + make_writable(&dir_path); + std::fs::remove_dir_all(&dir_path).unwrap(); +} + +#[cfg(unix)] +#[test] +fn drop_error_panic() { + if should_skip_cleanup_test() { + return + } + let _guard = LOCK.lock(); + let temp_dir = TempDir::new().unwrap().panic_on_cleanup_error(); + let dir_path = temp_dir.path().to_path_buf(); + let file1_path = temp_dir.child("file1"); + std::fs::write(&file1_path, b"abc").unwrap(); + make_non_writable(&dir_path); + let result = std::panic::catch_unwind(move || drop(temp_dir)); + std::fs::metadata(&dir_path).unwrap(); + std::fs::metadata(&file1_path).unwrap(); + make_writable(&dir_path); + std::fs::remove_dir_all(&dir_path).unwrap(); + let msg = result.unwrap_err().downcast::().unwrap(); + assert!( + msg.contains("error removing directory and contents ",), + "unexpected panic message {:?}", + msg + ); +} + +#[test] +fn leak() { + let _guard = LOCK.lock(); + let temp_dir = TempDir::new().unwrap(); + let dir_path = temp_dir.path().to_path_buf(); + let file1_path = temp_dir.child("file1"); + std::fs::write(&file1_path, b"abc").unwrap(); + temp_dir.leak(); + std::fs::metadata(&dir_path).unwrap(); + std::fs::metadata(&file1_path).unwrap(); + std::fs::remove_dir_all(&dir_path).unwrap(); +} diff --git a/bitacross-worker/core-primitives/stf-executor/Cargo.toml b/bitacross-worker/core-primitives/stf-executor/Cargo.toml new file mode 100644 index 0000000000..0b34106bc4 --- /dev/null +++ b/bitacross-worker/core-primitives/stf-executor/Cargo.toml @@ -0,0 +1,97 @@ +[package] +name = "itp-stf-executor" +version = "0.9.0" +authors = ['Trust Computing GmbH ', 'Integritee AG '] +edition = "2021" + +[dependencies] +hex = { version = "0.4.3", default-features = false, features = ["alloc"] } + +# sgx dependencies +sgx_tstd = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git", optional = true, features = ["untrusted_time"] } +sgx_types = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git" } + +# local dependencies +itp-enclave-metrics = { path = "../enclave-metrics", default-features = false } +itp-node-api = { path = "../node-api", default-features = false } +itp-ocall-api = { path = "../ocall-api", default-features = false } +itp-sgx-crypto = { path = "../sgx/crypto", default-features = false } +itp-sgx-externalities = { default-features = false, path = "../substrate-sgx/externalities" } +itp-stf-interface = { path = "../stf-interface", default-features = false } +itp-stf-primitives = { path = "../stf-primitives", default-features = false } +itp-stf-state-handler = { path = "../stf-state-handler", default-features = false } +itp-stf-state-observer = { path = "../stf-state-observer", default-features = false } +itp-time-utils = { path = "../time-utils", default-features = false } +itp-top-pool-author = { path = "../top-pool-author", default-features = false } +itp-types = { path = "../types", default-features = false } + +# sgx enabled external libraries +thiserror_sgx = { optional = true, package = "thiserror", git = "https://github.com/mesalock-linux/thiserror-sgx", tag = "sgx_1.1.3" } + +# std compatible external libraries (make sure these versions match with the sgx-enabled ones above) +thiserror = { version = "1.0", optional = true } + +# no-std dependencies +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +log = { version = "0.4", default-features = false } + +# substrate dependencies +sp-core = { default-features = false, features = ["full_crypto"], git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } +sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } + +# dev dependencies +itc-parentchain-test = { path = "../../core/parentchain/test", optional = true, default-features = false } +itp-test = { path = "../test", default-features = false, optional = true } + +# litentry +litentry-primitives = { path = "../../litentry/primitives", default-features = false } + +[dev-dependencies] +itp-stf-state-observer = { path = "../stf-state-observer", features = ["mocks"] } +itp-stf-interface = { path = "../stf-interface", features = ["mocks"] } +itp-top-pool = { path = "../top-pool", features = ["mocks"] } +itp-test = { path = "../test" } + +[features] +default = ["std"] +std = [ + # local + "itp-node-api/std", + "itp-ocall-api/std", + "itp-sgx-crypto/std", + "itp-sgx-externalities/std", + "itp-stf-interface/std", + "itp-stf-state-handler/std", + "itp-stf-state-observer/std", + "itp-top-pool-author/std", + "itp-types/std", + "itp-time-utils/std", + # crates.io + "log/std", + "codec/std", + # substrate + "sp-core/std", + "sp-runtime/std", + "thiserror", + # litentry + "litentry-primitives/std", +] +sgx = [ + "sgx_tstd", + "itp-node-api/sgx", + "itp-sgx-crypto/sgx", + "itp-sgx-externalities/sgx", + "itp-stf-state-handler/sgx", + "itp-stf-state-observer/sgx", + "itp-top-pool-author/sgx", + "itp-time-utils/sgx", + "thiserror_sgx", + # litentry + "litentry-primitives/sgx", +] +test = [ + "itc-parentchain-test", + "itp-node-api/mocks", + "itp-test", +] +mocks = [] diff --git a/bitacross-worker/core-primitives/stf-executor/src/enclave_signer.rs b/bitacross-worker/core-primitives/stf-executor/src/enclave_signer.rs new file mode 100644 index 0000000000..7de6a1ff4c --- /dev/null +++ b/bitacross-worker/core-primitives/stf-executor/src/enclave_signer.rs @@ -0,0 +1,177 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{ + error::{Error, Result}, + traits::{StfEnclaveSigning, StfShardVaultQuery}, + H256, +}; +use codec::{Decode, Encode}; +use core::{fmt::Debug, marker::PhantomData}; +use itp_ocall_api::EnclaveAttestationOCallApi; +use itp_sgx_crypto::{ed25519_derivation::DeriveEd25519, key_repository::AccessKey}; +use itp_sgx_externalities::SgxExternalitiesTrait; +use itp_stf_interface::{system_pallet::SystemPalletAccountInterface, ShardVaultQuery}; +use itp_stf_primitives::{ + traits::TrustedCallSigning, + types::{AccountId, KeyPair}, +}; +use itp_stf_state_observer::traits::ObserveState; +use itp_top_pool_author::traits::AuthorApi; +use itp_types::{Index, ShardIdentifier}; +use log::*; +use sp_core::{ed25519::Pair as Ed25519Pair, Pair}; +use std::{boxed::Box, sync::Arc, vec::Vec}; + +pub struct StfEnclaveSigner< + OCallApi, + StateObserver, + ShieldingKeyRepository, + Stf, + TopPoolAuthor, + TCS, + G, +> { + state_observer: Arc, + ocall_api: Arc, + shielding_key_repo: Arc, + top_pool_author: Arc, + _phantom: PhantomData<(Stf, TCS, G)>, +} + +impl + StfEnclaveSigner +where + OCallApi: EnclaveAttestationOCallApi, + StateObserver: ObserveState, + StateObserver::StateType: SgxExternalitiesTrait, + ShieldingKeyRepository: AccessKey, + ::KeyType: DeriveEd25519, + Stf: SystemPalletAccountInterface + + ShardVaultQuery, + Stf::Index: Into, + TopPoolAuthor: AuthorApi + Send + Sync + 'static, + TCS: PartialEq + Encode + Decode + Debug + Send + Sync, + G: PartialEq + Encode + Decode + Debug + Send + Sync, +{ + pub fn new( + state_observer: Arc, + ocall_api: Arc, + shielding_key_repo: Arc, + top_pool_author: Arc, + ) -> Self { + Self { + state_observer, + ocall_api, + shielding_key_repo, + top_pool_author, + _phantom: Default::default(), + } + } + + fn get_enclave_account_nonce(&self, shard: &ShardIdentifier) -> Result { + let enclave_account = self.get_enclave_account()?; + let nonce = self + .state_observer + .observe_state(shard, move |state| Stf::get_account_nonce(state, &enclave_account))?; + + Ok(nonce) + } + + fn get_enclave_call_signing_key(&self) -> Result { + let shielding_key = self.shielding_key_repo.retrieve_key()?; + shielding_key.derive_ed25519().map_err(|e| e.into()) + } +} + +impl + StfEnclaveSigning + for StfEnclaveSigner +where + OCallApi: EnclaveAttestationOCallApi, + StateObserver: ObserveState, + StateObserver::StateType: SgxExternalitiesTrait, + ShieldingKeyRepository: AccessKey, + ::KeyType: DeriveEd25519, + Stf: SystemPalletAccountInterface + + ShardVaultQuery, + Stf::Index: Into, + TopPoolAuthor: AuthorApi + Send + Sync + 'static, + TCS: PartialEq + Encode + Decode + Debug + Send + Sync, + G: PartialEq + Encode + Decode + Debug + Send + Sync, +{ + fn get_enclave_account(&self) -> Result { + let enclave_call_signing_key = self.get_enclave_call_signing_key()?; + Ok(enclave_call_signing_key.public().into()) + } + + fn sign_call_with_self>( + &self, + trusted_call: &TC, + shard: &ShardIdentifier, + ) -> Result { + let mr_enclave = self.ocall_api.get_mrenclave_of_self()?; + let enclave_account = self.get_enclave_account()?; + let enclave_call_signing_key = self.get_enclave_call_signing_key()?; + + let current_nonce = self.get_enclave_account_nonce(shard)?; + let pending_tx_count = self + .top_pool_author + .get_pending_trusted_calls_for(*shard, &enclave_account) + .len(); + let pending_tx_count = + Index::try_from(pending_tx_count).map_err(|e| Error::Other(e.into()))?; + let adjusted_nonce: Index = current_nonce.into() + pending_tx_count; + + Ok(trusted_call.sign( + &KeyPair::Ed25519(Box::new(enclave_call_signing_key)), + adjusted_nonce, + &mr_enclave.m, + shard, + )) + } + + fn sign(&self, payload: &[u8]) -> Result<(AccountId, Vec)> { + let enclave_account = self.get_enclave_account()?; + let enclave_call_signing_key = self.get_enclave_call_signing_key()?; + + debug!(" [EnclaveSigner] VC pubkey: {:?}", enclave_call_signing_key.public().to_vec()); + Ok((enclave_account, enclave_call_signing_key.sign(payload).0.to_vec())) + } +} + +impl StfShardVaultQuery + for StfEnclaveSigner +where + OCallApi: EnclaveAttestationOCallApi, + StateObserver: ObserveState, + StateObserver::StateType: SgxExternalitiesTrait, + ShieldingKeyRepository: AccessKey, + ::KeyType: DeriveEd25519, + Stf: SystemPalletAccountInterface + + ShardVaultQuery, + Stf::Index: Into, + TopPoolAuthor: AuthorApi + Send + Sync + 'static, + TCS: PartialEq + Encode + Decode + Debug + Send + Sync, + G: PartialEq + Encode + Decode + Debug + Send + Sync, +{ + fn get_shard_vault(&self, shard: &ShardIdentifier) -> Result { + let vault = self.state_observer.observe_state(shard, move |state| Stf::get_vault(state))?; + + vault.ok_or_else(|| Error::Other("shard vault undefined".into())) + } +} diff --git a/bitacross-worker/core-primitives/stf-executor/src/error.rs b/bitacross-worker/core-primitives/stf-executor/src/error.rs new file mode 100644 index 0000000000..ec46defdcd --- /dev/null +++ b/bitacross-worker/core-primitives/stf-executor/src/error.rs @@ -0,0 +1,88 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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(all(not(feature = "std"), feature = "sgx"))] +use crate::sgx_reexport_prelude::*; + +use itp_stf_primitives::error::StfError; +use sgx_types::sgx_status_t; +use std::{boxed::Box, format}; + +pub type Result = core::result::Result; + +/// STF-Executor error +#[derive(Debug, thiserror::Error)] +pub enum Error { + #[error("Trusted operation has invalid signature")] + GetterIsNotAuthorized, + #[error("Invalid or unsupported trusted call type")] + InvalidTrustedCallType, + #[error("SGX error, status: {0}")] + Sgx(sgx_status_t), + #[error("State handling error: {0}")] + StateHandler(#[from] itp_stf_state_handler::error::Error), + #[error("State observer error: {0}")] + StateObserver(#[from] itp_stf_state_observer::error::Error), + #[error("Node metadata error: {0:?}")] + NodeMetadata(itp_node_api::metadata::Error), + #[error("Node metadata provider error: {0:?}")] + NodeMetadataProvider(#[from] itp_node_api::metadata::provider::Error), + #[error("STF error: {0}")] + Stf(StfError), + #[error("Ocall Api error: {0}")] + OcallApi(itp_ocall_api::Error), + #[error("Crypto error: {0}")] + Crypto(itp_sgx_crypto::error::Error), + #[error(transparent)] + Other(#[from] Box), +} + +impl From for Error { + fn from(sgx_status: sgx_status_t) -> Self { + Self::Sgx(sgx_status) + } +} + +impl From for Error { + fn from(e: codec::Error) -> Self { + Self::Other(format!("{:?}", e).into()) + } +} + +impl From for Error { + fn from(error: StfError) -> Self { + Self::Stf(error) + } +} + +impl From for Error { + fn from(error: itp_ocall_api::Error) -> Self { + Self::OcallApi(error) + } +} + +impl From for Error { + fn from(error: itp_sgx_crypto::error::Error) -> Self { + Self::Crypto(error) + } +} + +impl From for Error { + fn from(e: itp_node_api::metadata::Error) -> Self { + Self::NodeMetadata(e) + } +} diff --git a/bitacross-worker/core-primitives/stf-executor/src/executor.rs b/bitacross-worker/core-primitives/stf-executor/src/executor.rs new file mode 100644 index 0000000000..a980563774 --- /dev/null +++ b/bitacross-worker/core-primitives/stf-executor/src/executor.rs @@ -0,0 +1,381 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{ + error::{Error, Result}, + traits::{StatePostProcessing, StateUpdateProposer, StfUpdateState}, + BatchExecutionResult, ExecutedOperation, +}; +use codec::{Decode, Encode}; +use itp_enclave_metrics::EnclaveMetric; +use itp_node_api::metadata::{provider::AccessNodeMetadata, NodeMetadataTrait}; +use itp_ocall_api::{EnclaveAttestationOCallApi, EnclaveMetricsOCallApi, EnclaveOnChainOCallApi}; +use itp_sgx_externalities::{SgxExternalitiesTrait, StateHash}; +use itp_stf_interface::{ + parentchain_pallet::ParentchainPalletInterface, runtime_upgrade::RuntimeUpgradeInterface, + StateCallInterface, StfExecutionResult, UpdateState, +}; +use itp_stf_primitives::{ + traits::TrustedCallVerification, + types::{ShardIdentifier, TrustedOperation, TrustedOperationOrHash}, +}; +use itp_stf_state_handler::{handle_state::HandleState, query_shard_state::QueryShardState}; +use itp_time_utils::duration_now; +use itp_types::{ + parentchain::{Header as ParentchainHeader, ParentchainCall, ParentchainId}, + storage::StorageEntryVerified, + H256, +}; +use log::*; +use sp_runtime::traits::Header as HeaderTrait; +use std::{ + collections::BTreeMap, fmt::Debug, marker::PhantomData, string::ToString, sync::Arc, + time::Duration, vec, vec::Vec, +}; + +pub struct StfExecutor +where + TCS: PartialEq + Encode + Decode + Debug + Clone + Send + Sync + TrustedCallVerification, + G: PartialEq + Encode + Decode + Debug + Clone + Send + Sync, +{ + ocall_api: Arc, + state_handler: Arc, + node_metadata_repo: Arc, + _phantom: PhantomData<(Stf, TCS, G)>, +} + +impl + StfExecutor +where + OCallApi: EnclaveAttestationOCallApi + EnclaveOnChainOCallApi + EnclaveMetricsOCallApi, + StateHandler: HandleState, + StateHandler::StateT: SgxExternalitiesTrait + Encode, + NodeMetadataRepository: AccessNodeMetadata, + NodeMetadataRepository::MetadataType: NodeMetadataTrait, + Stf: UpdateState< + StateHandler::StateT, + ::SgxExternalitiesDiffType, + > + StateCallInterface, + ::SgxExternalitiesDiffType: + IntoIterator, Option>)> + From, Option>>>, + >::Error: Debug, + TCS: PartialEq + Encode + Decode + Debug + Clone + Send + Sync + TrustedCallVerification, + G: PartialEq + Encode + Decode + Debug + Clone + Send + Sync, +{ + pub fn new( + ocall_api: Arc, + state_handler: Arc, + node_metadata_repo: Arc, + ) -> Self { + StfExecutor { ocall_api, state_handler, node_metadata_repo, _phantom: PhantomData } + } + + /// Execute a trusted call on the STF + /// + /// We distinguish between an error in the execution, which maps to `Err` and + /// an invalid trusted call, which results in `Ok(ExecutionStatus::Failure)`. The latter + /// can be used to remove the trusted call from a queue. In the former case we might keep the + /// trusted call and just re-try the operation. + fn execute_trusted_call_on_stf( + &self, + state: &mut StateHandler::StateT, + trusted_operation: &TrustedOperation, + _header: &PH, + shard: &ShardIdentifier, + post_processing: StatePostProcessing, + ) -> Result> + where + PH: HeaderTrait, + { + debug!("query mrenclave of self"); + let mrenclave = self.ocall_api.get_mrenclave_of_self()?; + + let top_or_hash = TrustedOperationOrHash::from_top(trusted_operation.clone()); + let operation_hash = trusted_operation.hash(); + debug!("Operation hash {:?}", operation_hash); + + // TODO(Litentry): do we need to send any error notification to parachain? + let trusted_call = match trusted_operation.to_call().ok_or(Error::InvalidTrustedCallType) { + Ok(c) => c, + Err(e) => { + error!("Error: {:?}", e); + return Ok(ExecutedOperation::failed(operation_hash, top_or_hash, vec![], vec![])) + }, + }; + + if !trusted_call.verify_signature(&mrenclave.m, &shard) { + error!("TrustedCallSigned: bad signature"); + return Ok(ExecutedOperation::failed(operation_hash, top_or_hash, vec![], vec![])) + } + + debug!("execute on STF, call with nonce {}", trusted_call.nonce()); + let mut extrinsic_call_backs: Vec = Vec::new(); + return match Stf::execute_call( + state, + shard, + trusted_call.clone(), + trusted_operation.hash(), + &mut extrinsic_call_backs, + self.node_metadata_repo.clone(), + ) { + Err(e) => { + error!("Stf execute failed: {:?}", e); + let rpc_response_value: Vec = e.encode(); + Ok(ExecutedOperation::failed( + operation_hash, + top_or_hash, + extrinsic_call_backs, + rpc_response_value, + )) + }, + Ok(result) => { + let force_connection_wait = result.force_connection_wait(); + let rpc_response_value: Vec = result.get_encoded_result(); + if let StatePostProcessing::Prune = post_processing { + state.prune_state_diff(); + } + for call in extrinsic_call_backs.clone() { + trace!( + "trusted_call wants to send encoded call: 0x{}", + hex::encode(call.encode()) + ); + } + Ok(ExecutedOperation::success( + operation_hash, + top_or_hash, + extrinsic_call_backs, + rpc_response_value, + force_connection_wait, + )) + }, + } + } +} + +impl + StfUpdateState + for StfExecutor +where + OCallApi: EnclaveAttestationOCallApi + EnclaveOnChainOCallApi, + StateHandler: HandleState + QueryShardState, + StateHandler::StateT: SgxExternalitiesTrait + Encode, + NodeMetadataRepository: AccessNodeMetadata, + Stf: UpdateState< + StateHandler::StateT, + ::SgxExternalitiesDiffType, + > + ParentchainPalletInterface, + ::SgxExternalitiesDiffType: + IntoIterator, Option>)>, + >::Error: Debug, + ::SgxExternalitiesDiffType: + From, Option>>>, + TCS: PartialEq + Encode + Decode + Debug + Clone + Send + Sync + TrustedCallVerification, + G: PartialEq + Encode + Decode + Debug + Clone + Send + Sync, +{ + fn update_states( + &self, + header: &ParentchainHeader, + parentchain_id: &ParentchainId, + ) -> Result<()> { + debug!("Update STF storage upon block import!"); + let storage_hashes = Stf::storage_hashes_to_update_on_block(parentchain_id); + + if storage_hashes.is_empty() { + return Ok(()) + } + + // global requests they are the same for every shard + let state_diff_update = self + .ocall_api + .get_multiple_storages_verified(storage_hashes, header, parentchain_id) + .map(into_map)?; + + // Update parentchain block on all states. + // TODO: Investigate if this is still necessary. We load and clone the entire state here, + // which scales badly for increasing state size. + let shards = self.state_handler.list_shards()?; + for shard_id in shards { + let (state_lock, mut state) = self.state_handler.load_for_mutation(&shard_id)?; + match Stf::update_parentchain_block(&mut state, header.clone()) { + Ok(_) => { + self.state_handler.write_after_mutation(state, state_lock, &shard_id)?; + }, + Err(e) => error!("Could not update parentchain block. {:?}: {:?}", shard_id, e), + } + } + + if parentchain_id != &ParentchainId::Litentry { + // nothing else to do + return Ok(()) + } + + // look for new shards and initialize them + if let Some(maybe_shards) = state_diff_update.get(&shards_key_hash()) { + match maybe_shards { + Some(shards) => self.initialize_new_shards(header, &state_diff_update, &shards)?, + None => debug!("No shards are on the chain yet"), + }; + }; + Ok(()) + } +} + +impl + StfExecutor +where + ::SgxExternalitiesDiffType: + From, Option>>> + IntoIterator, Option>)>, + >::Error: Debug, + NodeMetadataRepository: AccessNodeMetadata, + OCallApi: EnclaveAttestationOCallApi + EnclaveOnChainOCallApi, + StateHandler: HandleState + QueryShardState, + StateHandler::StateT: Encode + SgxExternalitiesTrait, + Stf: ParentchainPalletInterface + + UpdateState< + StateHandler::StateT, + ::SgxExternalitiesDiffType, + >, + TCS: PartialEq + Encode + Decode + Debug + Clone + Send + Sync + TrustedCallVerification, + G: PartialEq + Encode + Decode + Debug + Clone + Send + Sync, +{ + fn initialize_new_shards( + &self, + header: &ParentchainHeader, + state_diff_update: &BTreeMap, Option>>, + shards: &Vec, + ) -> Result<()> { + let shards: Vec = Decode::decode(&mut shards.as_slice())?; + + for shard_id in shards { + let (state_lock, mut state) = self.state_handler.load_for_mutation(&shard_id)?; + trace!("Successfully loaded state, updating states ..."); + + // per shard (cid) requests + let per_shard_hashes = storage_hashes_to_update_per_shard(&shard_id); + let per_shard_update = self + .ocall_api + .get_multiple_storages_verified(per_shard_hashes, header, &ParentchainId::Litentry) + .map(into_map)?; + + Stf::apply_state_diff(&mut state, per_shard_update.into()); + Stf::apply_state_diff(&mut state, state_diff_update.clone().into()); + if let Err(e) = Stf::update_parentchain_block(&mut state, header.clone()) { + error!("Could not update parentchain block. {:?}: {:?}", shard_id, e) + } + + self.state_handler.write_after_mutation(state, state_lock, &shard_id)?; + } + Ok(()) + } +} + +impl StateUpdateProposer + for StfExecutor +where + OCallApi: EnclaveAttestationOCallApi + EnclaveOnChainOCallApi + EnclaveMetricsOCallApi, + StateHandler: HandleState, + StateHandler::StateT: SgxExternalitiesTrait + Encode + StateHash, + ::SgxExternalitiesType: Encode, + NodeMetadataRepository: AccessNodeMetadata, + NodeMetadataRepository::MetadataType: NodeMetadataTrait, + Stf: UpdateState< + StateHandler::StateT, + ::SgxExternalitiesDiffType, + > + StateCallInterface + + RuntimeUpgradeInterface, + ::SgxExternalitiesDiffType: + IntoIterator, Option>)>, + ::SgxExternalitiesDiffType: + From, Option>>>, + >::Error: Debug, + >::Error: Debug, + TCS: PartialEq + Encode + Decode + Debug + Clone + Send + Sync + TrustedCallVerification, + G: PartialEq + Encode + Decode + Debug + Clone + Send + Sync, +{ + type Externalities = StateHandler::StateT; + + fn propose_state_update( + &self, + trusted_calls: &[TrustedOperation], + header: &PH, + shard: &ShardIdentifier, + max_exec_duration: Duration, + prepare_state_function: F, + ) -> Result> + where + PH: HeaderTrait, + F: FnOnce(Self::Externalities) -> Self::Externalities, + { + let ends_at = duration_now() + max_exec_duration; + + let (state, state_hash_before_execution) = self.state_handler.load_cloned(shard)?; + + // Execute any pre-processing steps. + let mut state = prepare_state_function(state); + let mut executed_and_failed_calls = Vec::>::new(); + + // TODO: maybe we can move it to `prepare_state_function`. It seems more reasonable. + let _ = Stf::on_runtime_upgrade(&mut state); + + // Iterate through all calls until time is over. + for trusted_call_signed in trusted_calls.into_iter() { + // Break if allowed time window is over. + if ends_at < duration_now() { + info!("Aborting execution of trusted calls because slot time is up"); + break + } + + match self.execute_trusted_call_on_stf( + &mut state, + &trusted_call_signed, + header, + shard, + StatePostProcessing::None, + ) { + Ok(executed_or_failed_call) => { + executed_and_failed_calls.push(executed_or_failed_call); + }, + Err(e) => { + error!("Fatal Error. Failed to attempt call execution: {:?}", e); + }, + }; + } + + Ok(BatchExecutionResult { + executed_operations: executed_and_failed_calls, + state_hash_before_execution, + state_after_execution: state, + }) + } +} + +fn into_map( + storage_entries: Vec>>, +) -> BTreeMap, Option>> { + storage_entries.into_iter().map(|e| e.into_tuple()).collect() +} + +// todo: we need to clarify where these functions belong and if we need them at all. moved them from ita-stf but we can no longer depend on that +pub fn storage_hashes_to_update_per_shard(_shard: &ShardIdentifier) -> Vec> { + Vec::new() +} + +pub fn shards_key_hash() -> Vec { + // here you have to point to a storage value containing a Vec of + // ShardIdentifiers the enclave uses this to autosubscribe to no shards + vec![] +} diff --git a/bitacross-worker/core-primitives/stf-executor/src/executor_tests.rs b/bitacross-worker/core-primitives/stf-executor/src/executor_tests.rs new file mode 100644 index 0000000000..458adc04b5 --- /dev/null +++ b/bitacross-worker/core-primitives/stf-executor/src/executor_tests.rs @@ -0,0 +1,279 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{executor::StfExecutor, traits::StateUpdateProposer}; +use codec::Encode; +use itc_parentchain_test::ParentchainHeaderBuilder; +use itp_node_api::metadata::{metadata_mocks::NodeMetadataMock, provider::NodeMetadataRepository}; +use itp_ocall_api::EnclaveAttestationOCallApi; +use itp_sgx_externalities::{SgxExternalities as State, SgxExternalitiesTrait}; +use itp_stf_primitives::{traits::TrustedCallSigning, types::ShardIdentifier}; +use itp_stf_state_handler::handle_state::HandleState; +use itp_test::mock::{ + handle_state_mock::HandleStateMock, + onchain_mock::OnchainMock, + stf_mock::{GetterMock, StfMock, TrustedCallMock, TrustedCallSignedMock}, +}; +use itp_types::H256; +use sp_core::{ed25519, Pair}; +use sp_runtime::app_crypto::sp_core::blake2_256; +use std::{sync::Arc, time::Duration, vec}; +// FIXME: Create unit tests for update_states, execute_shield_funds, execute_trusted_call, execute_trusted_call_on_stf #554 + +pub fn propose_state_update_executes_all_calls_given_enough_time() { + // given + let (stf_executor, ocall_api, state_handler) = stf_executor(); + let mrenclave = ocall_api.get_mrenclave_of_self().unwrap().m; + let (_, shard) = init_state_and_shard_with_state_handler(state_handler.as_ref()); + let sender = endowed_account(); + let signed_call_1 = TrustedCallMock::balance_transfer( + sender.public().into(), + sender.public().into(), + 42, + ) + .sign(&sender.clone().into(), 0, &mrenclave, &shard); + let trusted_operation_1 = signed_call_1.into_trusted_operation(true); + let call_operation_hash_1: H256 = blake2_256(&trusted_operation_1.encode()).into(); + let signed_call_2 = + TrustedCallMock::balance_transfer(sender.public().into(), sender.public().into(), 100) + .sign(&sender.clone().into(), 1, &mrenclave, &shard); + let trusted_operation_2 = signed_call_2.into_trusted_operation(true); + let call_operation_hash_2: H256 = blake2_256(&trusted_operation_2.encode()).into(); + + let (_, old_state_hash) = state_handler.load_cloned(&shard).unwrap(); + + // when + let batch_execution_result = stf_executor + .propose_state_update( + &vec![trusted_operation_1, trusted_operation_2], + &ParentchainHeaderBuilder::default().build(), + &shard, + Duration::from_secs(1000), + |state| state, + ) + .unwrap(); + + // then + assert_eq!(old_state_hash, batch_execution_result.state_hash_before_execution); + assert_eq!(batch_execution_result.executed_operations.len(), 2); + assert_eq!( + batch_execution_result.get_executed_operation_hashes(), + vec![call_operation_hash_1, call_operation_hash_2] + ); + // Ensure that state has been updated and not actually written. + assert_ne!( + state_handler.load_cloned(&shard).unwrap().0, + batch_execution_result.state_after_execution + ); +} + +pub fn propose_state_update_executes_only_one_trusted_call_given_not_enough_time() { + // given + let (stf_executor, ocall_api, state_handler) = stf_executor(); + let mrenclave = ocall_api.get_mrenclave_of_self().unwrap().m; + let (_, shard) = init_state_and_shard_with_state_handler(state_handler.as_ref()); + let sender = endowed_account(); + let signed_call_1 = TrustedCallMock::waste_time_ms(sender.public().into(), 10).sign( + &sender.clone().into(), + 0, + &mrenclave, + &shard, + ); + let trusted_operation_1 = signed_call_1.into_trusted_operation(true); + let call_operation_hash_1: H256 = blake2_256(&trusted_operation_1.encode()).into(); + + let signed_call_2 = TrustedCallMock::waste_time_ms(sender.public().into(), 10).sign( + &sender.clone().into(), + 0, + &mrenclave, + &shard, + ); + let trusted_operation_2 = signed_call_2.into_trusted_operation(true); + + let (_, old_state_hash) = state_handler.load_cloned(&shard).unwrap(); + // when + let batch_execution_result = stf_executor + .propose_state_update( + &vec![trusted_operation_1.clone(), trusted_operation_2.clone()], + &ParentchainHeaderBuilder::default().build(), + &shard, + Duration::from_millis(5), + |state| state, + ) + .unwrap(); + + // then + assert_eq!(old_state_hash, batch_execution_result.state_hash_before_execution); + assert_eq!(batch_execution_result.executed_operations.len(), 1); + assert_eq!(batch_execution_result.get_executed_operation_hashes(), vec![call_operation_hash_1]); + // Ensure that state has been updated and not actually written. + assert_ne!( + state_handler.load_cloned(&shard).unwrap().0, + batch_execution_result.state_after_execution + ); +} + +pub fn propose_state_update_executes_noop_leaving_state_untouched() { + // given + let (stf_executor, ocall_api, state_handler) = stf_executor(); + let mrenclave = ocall_api.get_mrenclave_of_self().unwrap().m; + let (_, shard) = init_state_and_shard_with_state_handler(state_handler.as_ref()); + let sender = endowed_account(); + let signed_call_1 = TrustedCallMock::noop(sender.public().into()).sign( + &sender.clone().into(), + 0, + &mrenclave, + &shard, + ); + let trusted_operation_1 = signed_call_1.into_trusted_operation(true); + let call_operation_hash_1: H256 = blake2_256(&trusted_operation_1.encode()).into(); + + let (_, old_state_hash) = state_handler.load_cloned(&shard).unwrap(); + // when + let batch_execution_result = stf_executor + .propose_state_update( + &vec![trusted_operation_1.clone()], + &ParentchainHeaderBuilder::default().build(), + &shard, + Duration::from_millis(5), // 1000 yields 0, 2000 yields 1, 4000 yields 1, 25_000 yields 2 + |state| state, + ) + .unwrap(); + + // then + assert_eq!(old_state_hash, batch_execution_result.state_hash_before_execution); + assert_eq!(batch_execution_result.executed_operations.len(), 1); + assert_eq!(batch_execution_result.get_executed_operation_hashes(), vec![call_operation_hash_1]); + assert_eq!( + state_handler.load_cloned(&shard).unwrap().0, + batch_execution_result.state_after_execution + ); +} + +pub fn propose_state_update_executes_no_trusted_calls_given_no_time() { + // given + let (stf_executor, ocall_api, state_handler) = stf_executor(); + let mrenclave = ocall_api.get_mrenclave_of_self().unwrap().m; + let (_, shard) = init_state_and_shard_with_state_handler(state_handler.as_ref()); + let sender = endowed_account(); + let signed_call_1 = TrustedCallMock::balance_transfer( + sender.public().into(), + sender.public().into(), + 42, + ) + .sign(&sender.clone().into(), 0, &mrenclave, &shard); + let trusted_operation_1 = signed_call_1.into_trusted_operation(true); + + let signed_call_2 = + TrustedCallMock::balance_transfer(sender.public().into(), sender.public().into(), 100) + .sign(&sender.clone().into(), 0, &mrenclave, &shard); + let trusted_operation_2 = signed_call_2.into_trusted_operation(true); + + let (_, old_state_hash) = state_handler.load_cloned(&shard).unwrap(); + + // when + let batch_execution_result = stf_executor + .propose_state_update( + &vec![trusted_operation_1.clone(), trusted_operation_2.clone()], + &ParentchainHeaderBuilder::default().build(), + &shard, + Duration::ZERO, + |state| state, + ) + .unwrap(); + + // then + assert_eq!(old_state_hash, batch_execution_result.state_hash_before_execution); + assert_eq!(batch_execution_result.executed_operations.len(), 0); + assert_eq!(batch_execution_result.get_executed_operation_hashes(), vec![]); +} + +pub fn propose_state_update_always_executes_preprocessing_step() { + // given + let shard = ShardIdentifier::default(); + let (stf_executor, _, state_handler) = stf_executor(); + let _init_hash = state_handler.initialize_shard(shard).unwrap(); + let key = "my_key".encode(); + let value = "my_value".encode(); + let (old_state, old_state_hash) = state_handler.load_cloned(&shard).unwrap(); + + // when + let batch_execution_result = stf_executor + .propose_state_update( + &vec![], + &ParentchainHeaderBuilder::default().build(), + &shard, + Duration::ZERO, + |mut state| { + state.insert(key.clone(), value.clone()); + state + }, + ) + .unwrap(); + + // then + assert_eq!(old_state_hash, batch_execution_result.state_hash_before_execution); + + // Ensure that state has been updated. + let retrieved_value = batch_execution_result.state_after_execution.get(key.as_slice()).unwrap(); + assert_eq!(*retrieved_value, value); + // Ensure that state has not been actually written. + assert_ne!(old_state, batch_execution_result.state_after_execution); +} + +// Helper Functions +fn stf_executor() -> ( + StfExecutor< + OnchainMock, + HandleStateMock, + NodeMetadataRepository, + StfMock, + TrustedCallSignedMock, + GetterMock, + >, + Arc, + Arc, +) { + let ocall_api = Arc::new(OnchainMock::default()); + let state_handler = Arc::new(HandleStateMock::default()); + let node_metadata_repo = Arc::new(NodeMetadataRepository::new(NodeMetadataMock::new())); + let executor = StfExecutor::new(ocall_api.clone(), state_handler.clone(), node_metadata_repo); + (executor, ocall_api, state_handler) +} + +/// Returns a test setup initialized `State` with the corresponding `ShardIdentifier`. +pub(crate) fn init_state_and_shard_with_state_handler>( + state_handler: &S, +) -> (State, ShardIdentifier) { + let shard = ShardIdentifier::default(); + let _hash = state_handler.initialize_shard(shard).unwrap(); + + let (lock, mut state) = state_handler.load_for_mutation(&shard).unwrap(); + test_genesis_setup(&mut state); + + state_handler.write_after_mutation(state.clone(), lock, &shard).unwrap(); + + (state, shard) +} + +pub fn endowed_account() -> ed25519::Pair { + ed25519::Pair::from_seed(&[42u8; 32].into()) +} + +pub fn test_genesis_setup(_state: &mut impl SgxExternalitiesTrait) { + // set alice sudo account +} diff --git a/bitacross-worker/core-primitives/stf-executor/src/getter_executor.rs b/bitacross-worker/core-primitives/stf-executor/src/getter_executor.rs new file mode 100644 index 0000000000..b968efc18b --- /dev/null +++ b/bitacross-worker/core-primitives/stf-executor/src/getter_executor.rs @@ -0,0 +1,137 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +//! Getter executor uses the state observer to get the most recent state and runs the getter on it. +//! The getter is verified (signature verfification) inside the `GetState` implementation. + +use crate::{error::Result, state_getter::GetState}; +use codec::Decode; +use itp_stf_primitives::traits::GetterAuthorization; +use itp_stf_state_observer::traits::ObserveState; +use itp_types::ShardIdentifier; +use log::*; +use std::{marker::PhantomData, sync::Arc, time::Instant, vec::Vec}; + +/// Trait to execute a getter for a specific shard. +pub trait ExecuteGetter { + fn execute_getter( + &self, + shard: &ShardIdentifier, + encoded_signed_getter: Vec, + ) -> Result>>; +} + +pub struct GetterExecutor +where + G: PartialEq, +{ + state_observer: Arc, + _phantom: PhantomData, + _phantom_getter: PhantomData, +} + +impl GetterExecutor +where + G: PartialEq, +{ + pub fn new(state_observer: Arc) -> Self { + Self { state_observer, _phantom: Default::default(), _phantom_getter: Default::default() } + } +} + +impl ExecuteGetter for GetterExecutor +where + StateObserver: ObserveState, + StateGetter: GetState, + G: PartialEq + Decode + GetterAuthorization, +{ + fn execute_getter( + &self, + shard: &ShardIdentifier, + encoded_signed_getter: Vec, + ) -> Result>> { + let getter = G::decode(&mut encoded_signed_getter.as_slice())?; + trace!("Successfully decoded trusted getter"); + + let getter_timer_start = Instant::now(); + let state_result = self + .state_observer + .observe_state(shard, |state| StateGetter::get_state(getter, state))??; + + debug!("Getter executed in {} ms", getter_timer_start.elapsed().as_millis()); + + Ok(state_result) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use codec::{Decode, Encode}; + + use itp_stf_state_observer::mock::ObserveStateMock; + use itp_test::mock::stf_mock::{ + GetterMock, PublicGetterMock, TrustedGetterMock, TrustedGetterSignedMock, + }; + + type TestState = u64; + type TestStateObserver = ObserveStateMock; + + struct TestStateGetter; + impl GetState for TestStateGetter { + fn get_state(_getter: GetterMock, state: &mut TestState) -> Result>> { + Ok(Some(state.encode())) + } + } + + type TestGetterExecutor = GetterExecutor; + + #[test] + fn executing_getters_works() { + let test_state = 23489u64; + let state_observer = Arc::new(TestStateObserver::new(test_state)); + let getter_executor = TestGetterExecutor::new(state_observer); + let getter = GetterMock::trusted(dummy_trusted_getter()); + + let state_result = getter_executor + .execute_getter(&ShardIdentifier::default(), getter.encode()) + .unwrap() + .unwrap(); + let decoded_state: TestState = Decode::decode(&mut state_result.as_slice()).unwrap(); + assert_eq!(decoded_state, test_state); + } + + #[test] + fn executing_public_getter_works() { + let test_state = 23489u64; + let state_observer = Arc::new(TestStateObserver::new(test_state)); + let getter_executor = TestGetterExecutor::new(state_observer); + let getter = GetterMock::public(PublicGetterMock::some_value); + + let state_result = getter_executor + .execute_getter(&ShardIdentifier::default(), getter.encode()) + .unwrap() + .unwrap(); + let decoded_state: TestState = Decode::decode(&mut state_result.as_slice()).unwrap(); + assert_eq!(decoded_state, test_state); + } + fn dummy_trusted_getter() -> TrustedGetterSignedMock { + TrustedGetterSignedMock { getter: TrustedGetterMock::some_value, signature: true } + // TrustedGetter::nonce(AccountId::new([0u8; 32])), + // MultiSignature::Ed25519(Signature::from_raw([0u8; 64])), + } +} diff --git a/bitacross-worker/core-primitives/stf-executor/src/lib.rs b/bitacross-worker/core-primitives/stf-executor/src/lib.rs new file mode 100644 index 0000000000..90e04cff44 --- /dev/null +++ b/bitacross-worker/core-primitives/stf-executor/src/lib.rs @@ -0,0 +1,305 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +#![cfg_attr(not(feature = "std"), no_std)] +#![cfg_attr(test, feature(assert_matches))] + +#[cfg(all(feature = "std", feature = "sgx"))] +compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the same time"); + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +extern crate sgx_tstd as std; + +use codec::{Decode, Encode}; +use core::fmt::Debug; +use itp_sgx_externalities::SgxExternalitiesTrait; +use itp_stf_primitives::types::TrustedOperationOrHash; +use itp_types::{parentchain::ParentchainCall, H256}; +use std::vec::Vec; + +// re-export module to properly feature gate sgx and regular std environment +#[cfg(all(not(feature = "std"), feature = "sgx"))] +pub mod sgx_reexport_prelude { + pub use thiserror_sgx as thiserror; +} + +pub mod error; +pub mod getter_executor; +pub mod state_getter; +pub mod traits; + +#[cfg(feature = "sgx")] +pub mod executor; + +#[cfg(feature = "sgx")] +pub mod enclave_signer; + +#[cfg(all(feature = "sgx", feature = "test"))] +pub mod executor_tests; + +#[cfg(feature = "mocks")] +pub mod mocks; + +pub type RpcResponseValue = Vec; + +/// Execution status of a trusted operation +/// +/// In case of success, it includes the operation hash, as well as +/// any extrinsic callbacks (e.g. unshield extrinsics) that need to be executed on-chain +/// +/// Litentry: +/// we have made a few changes: +/// - we add the encoded rpc response that will be passed back to the requester +/// - for failed top, we apply the parachain effects too +#[derive(Clone, Debug, PartialEq)] +pub enum ExecutionStatus { + Success(H256, Vec, RpcResponseValue, bool), + Failure(H256, Vec, RpcResponseValue), +} + +impl ExecutionStatus { + pub fn get_extrinsic_callbacks(&self) -> Vec { + match self { + ExecutionStatus::Success(_, opaque_calls, _, _) => opaque_calls.clone(), + ExecutionStatus::Failure(_, opaque_calls, _) => opaque_calls.clone(), + } + } + + pub fn get_executed_operation_hash(&self) -> Option { + match self { + ExecutionStatus::Success(operation_hash, _, _, _) => Some(*operation_hash), + _ => None, + } + } + + pub fn get_operation_hash(&self) -> H256 { + match self { + ExecutionStatus::Success(operation_hash, _, _, _) => *operation_hash, + ExecutionStatus::Failure(operation_hash, _, _) => *operation_hash, + } + } + + pub fn get_rpc_response_value(&self) -> RpcResponseValue { + match self { + ExecutionStatus::Success(_, _, res, _) => res.clone(), + ExecutionStatus::Failure(_, _, res) => res.clone(), + } + } + + pub fn get_force_wait(&self) -> bool { + match self { + ExecutionStatus::Success(_, _, _, wait) => *wait, + _ => false, + } + } +} + +/// Information about an executed trusted operation +/// +/// +#[derive(Clone, Debug, PartialEq)] +pub struct ExecutedOperation +where + TCS: PartialEq + Encode + Decode + Debug + Send + Sync, + G: PartialEq + Encode + Decode + Debug + Send + Sync, +{ + pub status: ExecutionStatus, + pub trusted_operation_or_hash: TrustedOperationOrHash, +} + +impl ExecutedOperation +where + TCS: PartialEq + Encode + Decode + Debug + Send + Sync, + G: PartialEq + Encode + Decode + Debug + Send + Sync, +{ + /// Constructor for a successfully executed trusted operation. + pub fn success( + operation_hash: H256, + trusted_operation_or_hash: TrustedOperationOrHash, + extrinsic_call_backs: Vec, + rpc_response_value: RpcResponseValue, + force_connection_wait: bool, + ) -> Self { + ExecutedOperation { + status: ExecutionStatus::Success( + operation_hash, + extrinsic_call_backs, + rpc_response_value, + force_connection_wait, + ), + trusted_operation_or_hash, + } + } + + /// Constructor for a failed trusted operation execution. + pub fn failed( + operation_hash: H256, + trusted_operation_or_hash: TrustedOperationOrHash, + extrinsic_call_backs: Vec, + rpc_response_value: RpcResponseValue, + ) -> Self { + ExecutedOperation { + status: ExecutionStatus::Failure( + operation_hash, + extrinsic_call_backs, + rpc_response_value, + ), + trusted_operation_or_hash, + } + } + + /// Returns true if the executed operation was a success. + pub fn is_success(&self) -> bool { + matches!(self.status, ExecutionStatus::Success(..)) + } +} + +/// Result of an execution on the STF +/// +/// Contains multiple executed operations +#[derive(Clone, Debug)] +pub struct BatchExecutionResult +where + TCS: PartialEq + Encode + Decode + Debug + Send + Sync, + G: PartialEq + Encode + Decode + Debug + Send + Sync, +{ + pub state_hash_before_execution: H256, + pub executed_operations: Vec>, + pub state_after_execution: Externalities, +} + +impl BatchExecutionResult +where + Externalities: SgxExternalitiesTrait + Encode, + TCS: PartialEq + Encode + Decode + Debug + Clone + Send + Sync, + G: PartialEq + Encode + Decode + Debug + Clone + Send + Sync, +{ + pub fn get_extrinsic_callbacks(&self) -> Vec { + self.executed_operations + .iter() + .flat_map(|e| e.status.get_extrinsic_callbacks()) + .collect() + } + + /// Returns all successfully exectued operation hashes. + pub fn get_executed_operation_hashes(&self) -> Vec { + self.executed_operations + .iter() + .flat_map(|ec| ec.status.get_executed_operation_hash()) + .collect() + } + + /// Returns all operations that were not executed. + pub fn get_failed_operations(&self) -> Vec> { + self.executed_operations.iter().filter(|ec| !ec.is_success()).cloned().collect() + } + + // Litentry: returns all (top_hash, (rpc_response_value, force_wait) tuples + pub fn get_connection_updates(&self) -> Vec<(H256, (RpcResponseValue, bool))> { + self.executed_operations + .iter() + .map(|ec| { + ( + ec.status.get_operation_hash(), + (ec.status.get_rpc_response_value(), ec.status.get_force_wait()), + ) + }) + .collect() + } +} + +#[cfg(test)] +mod tests { + use super::*; + use itp_sgx_externalities::SgxExternalities; + use itp_test::mock::stf_mock::{GetterMock, TrustedCallSignedMock}; + use itp_types::OpaqueCall; + + #[test] + fn is_success_works() { + let (success, _) = create_success_operation_from_u8(1); + let failed = create_failed_operation_from_u8(7); + + assert!(success.is_success()); + assert!(!failed.is_success()); + } + + #[test] + fn get_executed_operation_hashes_works() { + let (success_one, hash_success_one) = create_success_operation_from_u8(1); + let (success_two, hash_success_two) = create_success_operation_from_u8(3); + let failed = create_failed_operation_from_u8(7); + let result = batch_execution_result(vec![success_one, failed, success_two]); + + let success_operations = result.get_executed_operation_hashes(); + + assert_eq!(success_operations.len(), 2); + assert!(success_operations.contains(&hash_success_one)); + assert!(success_operations.contains(&hash_success_two)); + } + + #[test] + fn get_failed_operations_works() { + let failed_one = create_failed_operation_from_u8(1); + let failed_two = create_failed_operation_from_u8(3); + let (success, _) = create_success_operation_from_u8(10); + let result = batch_execution_result(vec![failed_one.clone(), failed_two.clone(), success]); + + let failed_operations = result.get_failed_operations(); + + assert_eq!(failed_operations.len(), 2); + assert!(failed_operations.contains(&failed_one)); + assert!(failed_operations.contains(&failed_two)); + } + + fn batch_execution_result( + executed_calls: Vec>, + ) -> BatchExecutionResult { + BatchExecutionResult { + executed_operations: executed_calls, + state_hash_before_execution: H256::default(), + state_after_execution: SgxExternalities::default(), + } + } + + fn create_failed_operation_from_u8( + int: u8, + ) -> ExecutedOperation { + ExecutedOperation::failed( + H256::from([int; 32]), + TrustedOperationOrHash::Hash(H256::from([int; 32])), + vec![], + vec![], + ) + } + + fn create_success_operation_from_u8( + int: u8, + ) -> (ExecutedOperation, H256) { + let hash = H256::from([int; 32]); + let opaque_call: Vec = + vec![ParentchainCall::Litentry(OpaqueCall(vec![int; 10]))]; + let operation = ExecutedOperation::success( + hash, + TrustedOperationOrHash::Hash(hash), + opaque_call, + vec![], + false, + ); + (operation, hash) + } +} diff --git a/bitacross-worker/core-primitives/stf-executor/src/mocks.rs b/bitacross-worker/core-primitives/stf-executor/src/mocks.rs new file mode 100644 index 0000000000..fb4079a331 --- /dev/null +++ b/bitacross-worker/core-primitives/stf-executor/src/mocks.rs @@ -0,0 +1,170 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{ + error::Result, + state_getter::GetState, + traits::{StateUpdateProposer, StfEnclaveSigning}, + BatchExecutionResult, ExecutedOperation, +}; +use codec::{Decode, Encode}; +use core::fmt::Debug; +use itp_sgx_externalities::SgxExternalitiesTrait; +use itp_stf_primitives::{ + traits::TrustedCallSigning, + types::{AccountId, KeyPair, ShardIdentifier, TrustedOperationOrHash}, +}; +use itp_types::H256; +use sp_core::Pair; +use sp_runtime::traits::Header as HeaderTrait; +#[cfg(feature = "std")] +use std::sync::RwLock; +use std::{boxed::Box, marker::PhantomData, ops::Deref, time::Duration, vec::Vec}; + +use crate::traits::StfShardVaultQuery; +use itp_stf_primitives::{ + traits::{GetterAuthorization, TrustedCallVerification}, + types::TrustedOperation, +}; +#[cfg(feature = "sgx")] +use std::sync::SgxRwLock as RwLock; + +/// Mock for the StfExecutor. +#[derive(Default)] +pub struct StfExecutorMock { + pub state: RwLock, +} + +impl StfExecutorMock { + pub fn new(state: State) -> Self { + Self { state: RwLock::new(state) } + } + + pub fn get_state(&self) -> State { + (*self.state.read().unwrap().deref()).clone() + } +} + +impl StateUpdateProposer for StfExecutorMock +where + State: SgxExternalitiesTrait + Encode + Clone, + TCS: PartialEq + Encode + Decode + Clone + Debug + Send + Sync + TrustedCallVerification, + G: PartialEq + Encode + Decode + Clone + Debug + Send + Sync, +{ + type Externalities = State; + + fn propose_state_update( + &self, + trusted_calls: &[TrustedOperation], + _header: &PH, + _shard: &ShardIdentifier, + _max_exec_duration: Duration, + prepare_state_function: F, + ) -> Result> + where + PH: HeaderTrait, + F: FnOnce(Self::Externalities) -> Self::Externalities, + { + let mut lock = self.state.write().unwrap(); + + let updated_state = prepare_state_function((*lock.deref()).clone()); + + *lock = updated_state.clone(); + + let executed_operations: Vec> = trusted_calls + .iter() + .map(|c| { + let operation_hash = c.hash(); + let top_or_hash = TrustedOperationOrHash::::from_top(c.clone()); + ExecutedOperation::success( + operation_hash, + top_or_hash, + Vec::new(), + Vec::new(), + false, + ) + }) + .collect(); + + Ok(BatchExecutionResult { + executed_operations, + state_hash_before_execution: H256::default(), + state_after_execution: updated_state, + }) + } +} + +/// Enclave signer mock. +pub struct StfEnclaveSignerMock { + mr_enclave: [u8; 32], + signer: sp_core::ed25519::Pair, +} + +impl StfEnclaveSignerMock { + pub fn new(mr_enclave: [u8; 32]) -> Self { + type Seed = [u8; 32]; + const TEST_SEED: Seed = *b"42345678901234567890123456789012"; + + Self { mr_enclave, signer: sp_core::ed25519::Pair::from_seed(&TEST_SEED) } + } +} + +impl Default for StfEnclaveSignerMock { + fn default() -> Self { + Self::new([0u8; 32]) + } +} + +impl StfEnclaveSigning for StfEnclaveSignerMock { + fn get_enclave_account(&self) -> Result { + Ok(self.signer.public().into()) + } + + fn sign_call_with_self>( + &self, + trusted_call: &TC, + shard: &ShardIdentifier, + ) -> Result { + Ok(trusted_call.sign(&KeyPair::Ed25519(Box::new(self.signer)), 1, &self.mr_enclave, shard)) + } + + fn sign(&self, _payload: &[u8]) -> Result<(AccountId, Vec)> { + Ok((self.signer.public().into(), [0u8; 32].to_vec())) + } +} + +impl StfShardVaultQuery for StfEnclaveSignerMock { + fn get_shard_vault(&self, _shard: &ShardIdentifier) -> Result { + Err(crate::error::Error::Other("shard vault undefined".into())) + } +} + +/// GetState mock +#[derive(Default)] +pub struct GetStateMock { + _phantom: PhantomData, +} + +impl GetState for GetStateMock +where + StateType: Encode, + G: PartialEq + Decode + GetterAuthorization, +{ + fn get_state(_getter: G, state: &mut StateType) -> Result>> { + Ok(Some(state.encode())) + } +} diff --git a/bitacross-worker/core-primitives/stf-executor/src/state_getter.rs b/bitacross-worker/core-primitives/stf-executor/src/state_getter.rs new file mode 100644 index 0000000000..ca047a36eb --- /dev/null +++ b/bitacross-worker/core-primitives/stf-executor/src/state_getter.rs @@ -0,0 +1,85 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::error::{Error, Result}; +use codec::Decode; +use core::marker::PhantomData; +use itp_sgx_externalities::SgxExternalities; +use itp_stf_interface::StateGetterInterface; +use itp_stf_primitives::traits::GetterAuthorization; +use log::*; +use std::vec::Vec; + +/// Abstraction for accessing state with a getter. +pub trait GetState { + /// Executes a trusted getter on a state and return its value, if available. + /// + /// Also verifies the signature of the trusted getter and returns an error + /// if it's invalid. + fn get_state(getter: G, state: &mut StateType) -> Result>>; +} + +pub struct StfStateGetter { + _phantom: PhantomData, +} + +impl GetState for StfStateGetter +where + Stf: StateGetterInterface, + G: PartialEq + Decode + GetterAuthorization, +{ + fn get_state(getter: G, state: &mut SgxExternalities) -> Result>> { + if !getter.is_authorized() { + error!("getter authorization failed"); + return Err(Error::GetterIsNotAuthorized) + } + debug!("getter authorized. calling into STF to get state"); + Ok(Stf::execute_getter(state, getter)) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use core::assert_matches::assert_matches; + + use itp_test::mock::stf_mock::{ + GetterMock, StfMock, TrustedGetterMock, TrustedGetterSignedMock, + }; + + type TestStateGetter = StfStateGetter; + + #[test] + fn upon_false_signature_get_stf_state_errs() { + let getter = + TrustedGetterSignedMock { getter: TrustedGetterMock::some_value, signature: false }; + let mut state = SgxExternalities::default(); + + assert_matches!( + TestStateGetter::get_state(GetterMock::trusted(getter), &mut state), + Err(Error::GetterIsNotAuthorized) + ); + } + + #[test] + fn state_getter_is_executed_if_signature_is_correct() { + let getter = + TrustedGetterSignedMock { getter: TrustedGetterMock::some_value, signature: true }; + let mut state = SgxExternalities::default(); + assert!(TestStateGetter::get_state(GetterMock::trusted(getter), &mut state).is_ok()); + } +} diff --git a/bitacross-worker/core-primitives/stf-executor/src/traits.rs b/bitacross-worker/core-primitives/stf-executor/src/traits.rs new file mode 100644 index 0000000000..4f7efd1532 --- /dev/null +++ b/bitacross-worker/core-primitives/stf-executor/src/traits.rs @@ -0,0 +1,89 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{error::Result, BatchExecutionResult}; +use codec::{Decode, Encode}; +use core::fmt::Debug; +use itp_sgx_externalities::SgxExternalitiesTrait; +use itp_stf_primitives::{ + traits::TrustedCallSigning, + types::{AccountId, ShardIdentifier, TrustedOperation}, +}; +use itp_types::H256; +use sp_runtime::traits::Header as HeaderTrait; +use std::{time::Duration, vec::Vec}; + +/// Post-processing steps after executing STF +pub enum StatePostProcessing { + None, + Prune, +} + +/// Allows signing of a trusted call or a raw bytes with the enclave account that is registered in the STF. +/// +/// The signing key is derived from the shielding key, which guarantees that all enclaves sign the same key. +pub trait StfEnclaveSigning +where + TCS: PartialEq + Encode + Debug, +{ + fn get_enclave_account(&self) -> Result; + + fn sign_call_with_self>( + &self, + trusted_call: &TC, + shard: &ShardIdentifier, + ) -> Result; + + // litentry + fn sign(&self, payload: &[u8]) -> Result<(AccountId, Vec)>; +} + +pub trait StfShardVaultQuery { + fn get_shard_vault(&self, shard: &ShardIdentifier) -> Result; +} + +/// Proposes a state update to `Externalities`. +pub trait StateUpdateProposer +where + TCS: PartialEq + Encode + Decode + Debug + Send + Sync, + G: PartialEq + Encode + Decode + Debug + Send + Sync, +{ + type Externalities: SgxExternalitiesTrait + Encode; + + /// Executes trusted calls within a given time frame without permanent state mutation. + /// + /// All executed call hashes and the mutated state are returned. + /// If the time expires, any remaining trusted calls within the batch will be ignored. + fn propose_state_update( + &self, + trusted_calls: &[TrustedOperation], + header: &PH, + shard: &ShardIdentifier, + max_exec_duration: Duration, + prepare_state_function: F, + ) -> Result> + where + PH: HeaderTrait, + F: FnOnce(Self::Externalities) -> Self::Externalities; +} + +/// Updates the STF state for a specific header. +/// +/// Cannot be implemented for a generic header currently, because the runtime expects a ParentchainHeader. +pub trait StfUpdateState { + fn update_states(&self, header: &PCH, parentchain_id: &PCID) -> Result<()>; +} diff --git a/bitacross-worker/core-primitives/stf-interface/Cargo.toml b/bitacross-worker/core-primitives/stf-interface/Cargo.toml new file mode 100644 index 0000000000..1fc86aaed9 --- /dev/null +++ b/bitacross-worker/core-primitives/stf-interface/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "itp-stf-interface" +version = "0.8.0" +authors = ['Trust Computing GmbH ', 'Integritee AG '] +edition = "2021" + +[dependencies] +codec = { version = "3.0.0", default-features = false, features = ["derive"], package = "parity-scale-codec" } + +itp-node-api-metadata = { path = "../node-api/metadata", default-features = false, features = ["mocks"] } +itp-node-api-metadata-provider = { path = "../node-api/metadata-provider", default-features = false } +itp-stf-primitives = { path = "../stf-primitives", default-features = false } +itp-types = { default-features = false, path = "../types" } + +[features] +default = ["std"] +std = [ + "itp-node-api-metadata/std", + "itp-node-api-metadata-provider/std", + "itp-stf-primitives/std", + "itp-types/std", +] +mocks = [] diff --git a/bitacross-worker/core-primitives/stf-interface/src/lib.rs b/bitacross-worker/core-primitives/stf-interface/src/lib.rs new file mode 100644 index 0000000000..a265ecd38c --- /dev/null +++ b/bitacross-worker/core-primitives/stf-interface/src/lib.rs @@ -0,0 +1,141 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 a state interface. +//! This allow to easily mock the stf and exchange it with another storage. + +#![cfg_attr(not(feature = "std"), no_std)] + +extern crate alloc; + +use alloc::{sync::Arc, vec::Vec}; +use codec::{Decode, Encode}; +use core::fmt::Debug; +use itp_node_api_metadata::NodeMetadataTrait; +use itp_node_api_metadata_provider::AccessNodeMetadata; +use itp_stf_primitives::traits::TrustedCallVerification; +use itp_types::{ + parentchain::{AccountId, ParentchainCall, ParentchainId}, + ShardIdentifier, H256, +}; + +#[cfg(feature = "mocks")] +pub mod mocks; +pub mod parentchain_pallet; +pub mod runtime_upgrade; +pub mod sudo_pallet; +pub mod system_pallet; + +pub const SHARD_VAULT_KEY: &str = "ShardVaultPubKey"; + +/// Interface to initialize a new state. +pub trait InitState { + /// Initialize a new state for a given enclave account. + fn init_state(enclave_account: AccountId) -> State; +} + +/// Interface to query shard vault account for shard +pub trait ShardVaultQuery { + fn get_vault(state: &mut S) -> Option; +} + +/// Interface for all functions calls necessary to update an already +/// initialized state. +pub trait UpdateState { + /// Updates a given state for + fn apply_state_diff(state: &mut State, state_diff: StateDiff); + fn storage_hashes_to_update_on_block(parentchain_id: &ParentchainId) -> Vec>; +} + +/// Interface to execute state mutating calls on a state. +pub trait StateCallInterface +where + NodeMetadataRepository: AccessNodeMetadata, + NodeMetadataRepository::MetadataType: NodeMetadataTrait, + TCS: PartialEq + Encode + Decode + Debug + Clone + Send + Sync + TrustedCallVerification, +{ + type Error: Encode; + type Result: StfExecutionResult; + + /// Execute a call on a specific state. Callbacks are added as an `OpaqueCall`. + /// + /// Litentry: + /// 1. add a parameter to pass the top_hash around + /// 2. returns the encoded rpc response value field that should be passed + /// back to the requester when the call is triggered synchronously + fn execute_call( + state: &mut State, + shard: &ShardIdentifier, + call: TCS, + top_hash: H256, + calls: &mut Vec, + node_metadata_repo: Arc, + ) -> Result; +} + +/// Interface to execute state reading getters on a state. +pub trait StateGetterInterface { + /// Execute a getter on a specific state. + fn execute_getter(state: &mut S, getter: G) -> Option>; +} + +/// Trait used to abstract the call execution. +pub trait ExecuteCall +where + NodeMetadataRepository: AccessNodeMetadata, + NodeMetadataRepository::MetadataType: NodeMetadataTrait, +{ + type Error: Encode; + type Result: StfExecutionResult; + + /// Execute a call. Callbacks are added as an `OpaqueCall`. + /// + /// Litentry: returns the encoded rpc response that should be passed back to + /// the requester when the call is triggered synchronously + fn execute( + self, + shard: &ShardIdentifier, + top_hash: H256, + calls: &mut Vec, + node_metadata_repo: Arc, + ) -> Result; + + /// Get storages hashes that should be updated for a specific call. + fn get_storage_hashes_to_update(self) -> Vec>; +} + +/// Trait used to abstract the getter execution. +pub trait ExecuteGetter { + /// Execute a getter. + fn execute(self) -> Option>; + /// Get storages hashes that should be updated for a specific getter. + fn get_storage_hashes_to_update(self) -> Vec>; +} + +pub trait StfExecutionResult { + fn get_encoded_result(self) -> Vec; + fn force_connection_wait(&self) -> bool; +} + +impl StfExecutionResult for () { + fn get_encoded_result(self) -> Vec { + Vec::default() + } + fn force_connection_wait(&self) -> bool { + false + } +} diff --git a/bitacross-worker/core-primitives/stf-interface/src/mocks.rs b/bitacross-worker/core-primitives/stf-interface/src/mocks.rs new file mode 100644 index 0000000000..44bda77d36 --- /dev/null +++ b/bitacross-worker/core-primitives/stf-interface/src/mocks.rs @@ -0,0 +1,132 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 a mock which implements all traits within this crate. + +extern crate alloc; +use crate::{ + system_pallet::SystemPalletAccountInterface, ExecuteCall, ExecuteGetter, InitState, + StateCallInterface, StateGetterInterface, UpdateState, +}; +use alloc::{string::String, sync::Arc, vec::Vec}; +use codec::{Decode, Encode}; +use core::{fmt::Debug, marker::PhantomData}; +use itp_node_api_metadata::metadata_mocks::NodeMetadataMock; +use itp_node_api_metadata_provider::NodeMetadataRepository; +use itp_stf_primitives::traits::TrustedCallVerification; +use itp_types::{ + parentchain::{ParentchainCall, ParentchainId}, + AccountId, Index, ShardIdentifier, H256, +}; + +#[derive(Default)] +pub struct StateInterfaceMock { + _phantom: PhantomData<(State, StateDiff)>, +} + +impl InitState + for StateInterfaceMock +{ + fn init_state(_enclave_account: AccountId) -> State { + unimplemented!() + } +} + +impl UpdateState for StateInterfaceMock { + fn apply_state_diff(_state: &mut State, _state_diff: StateDiff) { + unimplemented!() + } + + fn storage_hashes_to_update_on_block(_: &ParentchainId) -> Vec> { + unimplemented!() + } +} + +impl StateCallInterface> + for StateInterfaceMock +where + TCS: PartialEq + Encode + Decode + Debug + Clone + Send + Sync + TrustedCallVerification, +{ + type Error = String; + type Result = (); + + fn execute_call( + _state: &mut State, + _shard: &ShardIdentifier, + _call: TCS, + _top_hash: H256, + _calls: &mut Vec, + _node_metadata_repo: Arc>, + ) -> Result { + unimplemented!() + } +} + +impl StateGetterInterface + for StateInterfaceMock +{ + fn execute_getter(_state: &mut State, _getter: Getter) -> Option> { + None + } +} + +impl SystemPalletAccountInterface + for StateInterfaceMock +{ + type AccountData = String; + type Index = Index; + + fn get_account_nonce(_state: &mut State, _account_id: &AccountId) -> Self::Index { + unimplemented!() + } + fn get_account_data(_state: &mut State, _account_id: &AccountId) -> Self::AccountData { + unimplemented!() + } +} + +pub struct CallExecutorMock; + +impl ExecuteCall> for CallExecutorMock { + type Error = String; + type Result = (); + + fn execute( + self, + _shard: &ShardIdentifier, + _top_hash: H256, + _calls: &mut Vec, + _node_metadata_repo: Arc>, + ) -> Result<(), Self::Error> { + unimplemented!() + } + + fn get_storage_hashes_to_update(self) -> Vec> { + unimplemented!() + } +} + +pub struct GetterExecutorMock; + +impl ExecuteGetter for GetterExecutorMock { + fn execute(self) -> Option> { + unimplemented!() + } + + fn get_storage_hashes_to_update(self) -> Vec> { + unimplemented!() + } +} diff --git a/bitacross-worker/core-primitives/stf-interface/src/parentchain_pallet.rs b/bitacross-worker/core-primitives/stf-interface/src/parentchain_pallet.rs new file mode 100644 index 0000000000..c89138c25e --- /dev/null +++ b/bitacross-worker/core-primitives/stf-interface/src/parentchain_pallet.rs @@ -0,0 +1,27 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +/// Interface trait of the parentchain pallet. +pub trait ParentchainPalletInterface { + type Error; + + /// Updates the block number, block hash and parent hash of the parentchain block. + fn update_parentchain_block( + state: &mut State, + header: ParentchainHeader, + ) -> Result<(), Self::Error>; +} diff --git a/bitacross-worker/core-primitives/stf-interface/src/runtime_upgrade.rs b/bitacross-worker/core-primitives/stf-interface/src/runtime_upgrade.rs new file mode 100644 index 0000000000..30ee22140e --- /dev/null +++ b/bitacross-worker/core-primitives/stf-interface/src/runtime_upgrade.rs @@ -0,0 +1,21 @@ +// Copyright 2020-2023 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . + +pub trait RuntimeUpgradeInterface { + type Error; + + fn on_runtime_upgrade(state: &mut State) -> Result<(), Self::Error>; +} diff --git a/bitacross-worker/core-primitives/stf-interface/src/sudo_pallet.rs b/bitacross-worker/core-primitives/stf-interface/src/sudo_pallet.rs new file mode 100644 index 0000000000..afd2ed1dec --- /dev/null +++ b/bitacross-worker/core-primitives/stf-interface/src/sudo_pallet.rs @@ -0,0 +1,27 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +/// Interface trait of the sudo pallet. +pub trait SudoPalletInterface { + type AccountId; + + /// Get the root account for a given state. + fn get_root(state: &mut State) -> Self::AccountId; + + /// Get the enclave account for a given state. + fn get_enclave_account(state: &mut State) -> Self::AccountId; +} diff --git a/bitacross-worker/core-primitives/stf-interface/src/system_pallet.rs b/bitacross-worker/core-primitives/stf-interface/src/system_pallet.rs new file mode 100644 index 0000000000..82166e846e --- /dev/null +++ b/bitacross-worker/core-primitives/stf-interface/src/system_pallet.rs @@ -0,0 +1,53 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ +extern crate alloc; +use alloc::{boxed::Box, vec::Vec}; + +/// Interface trait of the system pallet for account specific data. +pub trait SystemPalletAccountInterface { + type Index; + type AccountData; + + /// Get the nonce for a given account and state. + fn get_account_nonce(state: &mut State, account_id: &AccountId) -> Self::Index; + + /// Get the account date for a given account and state. + fn get_account_data(state: &mut State, account: &AccountId) -> Self::AccountData; +} + +/// Interface trait of the system pallet for event specific interactions. +pub trait SystemPalletEventInterface { + type EventRecord; + type EventIndex; + type BlockNumber; + type Hash; + + /// Get a Vec of bounded events. + fn get_events(state: &mut State) -> Vec>; + + /// Get the count of the currently stored events. + fn get_event_count(state: &mut State) -> Self::EventIndex; + + /// Get the event topics + fn get_event_topics( + state: &mut State, + topic: &Self::Hash, + ) -> Vec<(Self::BlockNumber, Self::EventIndex)>; + + /// Reset everything event related. + fn reset_events(state: &mut State); +} diff --git a/bitacross-worker/core-primitives/stf-primitives/Cargo.toml b/bitacross-worker/core-primitives/stf-primitives/Cargo.toml new file mode 100644 index 0000000000..edbbf47968 --- /dev/null +++ b/bitacross-worker/core-primitives/stf-primitives/Cargo.toml @@ -0,0 +1,31 @@ +[package] +name = "itp-stf-primitives" +version = "0.9.0" +authors = ['Trust Computing GmbH ', 'Integritee AG '] +edition = "2021" + +[dependencies] +# crates.io +codec = { version = "3.0.0", default-features = false, features = ["derive"], package = "parity-scale-codec" } +derive_more = { version = "0.99.5" } +itp-sgx-runtime-primitives = { path = "../../core-primitives/sgx-runtime-primitives", default-features = false } +sp-core = { default-features = false, features = ["full_crypto"], git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } +sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } +sp-std = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } + +# litentry +litentry-primitives = { path = "../../litentry/primitives", default-features = false } + +[features] +default = ["std"] +std = [ + # crates.io + "codec/std", + # substrate + "sp-core/std", + "sp-std/std", + "sp-runtime/std", + "itp-sgx-runtime-primitives/std", + # litentry + "litentry-primitives/std", +] diff --git a/bitacross-worker/core-primitives/stf-primitives/src/error.rs b/bitacross-worker/core-primitives/stf-primitives/src/error.rs new file mode 100644 index 0000000000..c69514f109 --- /dev/null +++ b/bitacross-worker/core-primitives/stf-primitives/src/error.rs @@ -0,0 +1,118 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::types::{AccountId, Nonce}; +use alloc::{format, string::String}; +use codec::{Decode, Encode}; +use derive_more::Display; +use litentry_primitives::{Assertion, ErrorDetail, ErrorString, IMPError, VCMPError}; + +pub type StfResult = Result; + +#[derive(Debug, Display, PartialEq, Eq, Encode, Decode, Clone)] +pub enum StfError { + #[codec(index = 0)] + #[display(fmt = "Insufficient privileges {:?}, are you sure you are root?", _0)] + MissingPrivileges(AccountId), + #[codec(index = 1)] + #[display(fmt = "Valid enclave signer account is required")] + RequireEnclaveSignerAccount, + #[codec(index = 2)] + #[display(fmt = "Error dispatching runtime call. {:?}", _0)] + Dispatch(String), + #[codec(index = 3)] + #[display(fmt = "Not enough funds to perform operation")] + MissingFunds, + #[codec(index = 4)] + #[display(fmt = "Invalid Nonce {:?} != {:?}", _0, _1)] + InvalidNonce(Nonce, Nonce), + #[codec(index = 5)] + StorageHashMismatch, + #[codec(index = 6)] + InvalidStorageDiff, + #[codec(index = 7)] + InvalidMetadata, + // litentry + #[codec(index = 8)] + #[display(fmt = "LinkIdentityFailed: {:?}", _0)] + LinkIdentityFailed(ErrorDetail), + #[codec(index = 9)] + #[display(fmt = "DeactivateIdentityFailed: {:?}", _0)] + DeactivateIdentityFailed(ErrorDetail), + #[codec(index = 10)] + #[display(fmt = "ActivateIdentityFailed: {:?}", _0)] + ActivateIdentityFailed(ErrorDetail), + #[codec(index = 11)] + #[display(fmt = "RequestVCFailed: {:?} {:?}", _0, _1)] + RequestVCFailed(Assertion, ErrorDetail), + #[codec(index = 12)] + SetScheduledMrEnclaveFailed, + #[codec(index = 13)] + #[display(fmt = "SetIdentityNetworksFailed: {:?}", _0)] + SetIdentityNetworksFailed(ErrorDetail), + #[codec(index = 14)] + InvalidAccount, + #[codec(index = 15)] + UnclassifiedError, + #[codec(index = 16)] + #[display(fmt = "RemovingIdentityFailed: {:?}", _0)] + RemoveIdentityFailed(ErrorDetail), + #[codec(index = 17)] + EmptyIDGraph, +} + +impl From for StfError { + fn from(e: IMPError) -> Self { + match e { + IMPError::LinkIdentityFailed(d) => StfError::LinkIdentityFailed(d), + IMPError::DeactivateIdentityFailed(d) => StfError::DeactivateIdentityFailed(d), + IMPError::ActivateIdentityFailed(d) => StfError::ActivateIdentityFailed(d), + _ => StfError::UnclassifiedError, + } + } +} + +impl From for StfError { + fn from(e: VCMPError) -> Self { + match e { + VCMPError::RequestVCFailed(a, d) => StfError::RequestVCFailed(a, d), + _ => StfError::UnclassifiedError, + } + } +} + +impl StfError { + // Convert StfError to IMPError that would be sent to parentchain + pub fn to_imp_error(&self) -> IMPError { + match self { + StfError::LinkIdentityFailed(d) => IMPError::LinkIdentityFailed(d.clone()), + StfError::DeactivateIdentityFailed(d) => IMPError::DeactivateIdentityFailed(d.clone()), + StfError::ActivateIdentityFailed(d) => IMPError::ActivateIdentityFailed(d.clone()), + _ => IMPError::UnclassifiedError(ErrorDetail::StfError(ErrorString::truncate_from( + format!("{:?}", self).as_bytes().to_vec(), + ))), + } + } + // Convert StfError to VCMPError that would be sent to parentchain + pub fn to_vcmp_error(&self) -> VCMPError { + match self { + StfError::RequestVCFailed(a, d) => VCMPError::RequestVCFailed(a.clone(), d.clone()), + _ => VCMPError::UnclassifiedError(ErrorDetail::StfError(ErrorString::truncate_from( + format!("{:?}", self).as_bytes().to_vec(), + ))), + } + } +} diff --git a/bitacross-worker/core-primitives/stf-primitives/src/lib.rs b/bitacross-worker/core-primitives/stf-primitives/src/lib.rs new file mode 100644 index 0000000000..8e5ce6b1c0 --- /dev/null +++ b/bitacross-worker/core-primitives/stf-primitives/src/lib.rs @@ -0,0 +1,22 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ +#![cfg_attr(not(feature = "std"), no_std)] +extern crate alloc; + +pub mod error; +pub mod traits; +pub mod types; diff --git a/bitacross-worker/core-primitives/stf-primitives/src/traits.rs b/bitacross-worker/core-primitives/stf-primitives/src/traits.rs new file mode 100644 index 0000000000..eaad1e3563 --- /dev/null +++ b/bitacross-worker/core-primitives/stf-primitives/src/traits.rs @@ -0,0 +1,76 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::types::{AccountId, KeyPair, ShardIdentifier}; +use alloc::vec::Vec; +use codec::{Decode, Encode}; +use core::fmt::Debug; +use itp_sgx_runtime_primitives::types::Index; +use litentry_primitives::Identity; +use sp_runtime::transaction_validity::{TransactionValidityError, ValidTransaction}; + +/// checks authorization of stf getters +pub trait GetterAuthorization { + fn is_authorized(&self) -> bool; +} + +/// knows how to sign a trusted call input and provides a signed output +pub trait TrustedCallSigning { + fn sign( + &self, + pair: &KeyPair, + nonce: Index, + mrenclave: &[u8; 32], + shard: &ShardIdentifier, + ) -> TCS; +} + +/// enables TrustedCallSigned verification +pub trait TrustedCallVerification { + fn sender_identity(&self) -> &Identity; + + fn nonce(&self) -> Index; + + fn verify_signature(&self, mrenclave: &[u8; 32], shard: &ShardIdentifier) -> bool; +} + +/// validation for top pool +pub trait PoolTransactionValidation { + fn validate(&self) -> Result; +} + +/// Trait to be implemented on the executor to serve helper methods of the executor +/// to the `IndirectDispatch` implementation. +pub trait IndirectExecutor +where + TCS: PartialEq + Encode + Decode + Debug + Clone + Send + Sync + TrustedCallVerification, +{ + fn submit_trusted_call(&self, shard: ShardIdentifier, encrypted_trusted_call: Vec); + + fn decrypt(&self, encrypted: &[u8]) -> Result, Error>; + + fn encrypt(&self, value: &[u8]) -> Result, Error>; + + fn get_enclave_account(&self) -> Result; + + fn get_default_shard(&self) -> ShardIdentifier; + + fn sign_call_with_self>( + &self, + trusted_call: &TC, + shard: &ShardIdentifier, + ) -> Result; +} diff --git a/bitacross-worker/core-primitives/stf-primitives/src/types.rs b/bitacross-worker/core-primitives/stf-primitives/src/types.rs new file mode 100644 index 0000000000..a96da4087c --- /dev/null +++ b/bitacross-worker/core-primitives/stf-primitives/src/types.rs @@ -0,0 +1,211 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ +extern crate alloc; +use crate::traits::{PoolTransactionValidation, TrustedCallVerification}; +use alloc::boxed::Box; +use codec::{Compact, Decode, Encode}; +use core::fmt::Debug; +use litentry_primitives::LitentryMultiSignature; +use sp_core::{blake2_256, crypto::AccountId32, ed25519, sr25519, Pair, H256}; +use sp_runtime::{ + traits::Verify, + transaction_validity::{TransactionValidityError, ValidTransaction}, + MultiSignature, +}; +use sp_std::{vec, vec::Vec}; + +pub type Signature = MultiSignature; +pub type AuthorityId = ::Signer; +pub type AccountId = AccountId32; +pub type Nonce = u32; +pub type Hash = H256; +pub type BalanceTransferFn = ([u8; 2], AccountId, Compact); +pub type ShardIdentifier = H256; + +#[derive(Clone)] +pub enum KeyPair { + Sr25519(Box), + Ed25519(Box), +} + +impl KeyPair { + pub fn sign(&self, payload: &[u8]) -> LitentryMultiSignature { + match self { + Self::Sr25519(pair) => pair.sign(payload).into(), + Self::Ed25519(pair) => pair.sign(payload).into(), + } + } + pub fn account_id(&self) -> AccountId { + match self { + Self::Sr25519(pair) => pair.public().into(), + Self::Ed25519(pair) => pair.public().into(), + } + } +} + +impl From for KeyPair { + fn from(x: ed25519::Pair) -> Self { + KeyPair::Ed25519(Box::new(x)) + } +} + +impl From for KeyPair { + fn from(x: sr25519::Pair) -> Self { + KeyPair::Sr25519(Box::new(x)) + } +} + +#[derive(Encode, Decode, Clone, Debug, PartialEq, Eq)] +#[allow(non_camel_case_types)] +pub enum TrustedOperation +where + TCS: PartialEq + Encode + Debug, + G: PartialEq + Encode + Debug, +{ + #[codec(index = 0)] + indirect_call(TCS), + #[codec(index = 1)] + direct_call(TCS), + #[codec(index = 2)] + get(G), +} + +impl From for TrustedOperation +where + TCS: PartialEq + Encode + Debug, + G: PartialEq + Encode + Debug, +{ + fn from(item: G) -> Self { + TrustedOperation::get(item) + } +} + +impl TrustedOperation +where + TCS: PartialEq + TrustedCallVerification + Encode + Debug, + G: PartialEq + Encode + Debug, +{ + pub fn to_call(&self) -> Option<&TCS> { + match self { + TrustedOperation::direct_call(c) => Some(c), + TrustedOperation::indirect_call(c) => Some(c), + _ => None, + } + } + + pub fn signed_caller_account(&self) -> Option { + match self { + TrustedOperation::direct_call(c) => c.sender_identity().to_account_id(), + TrustedOperation::indirect_call(c) => c.sender_identity().to_account_id(), + _ => None, + } + } + + fn validate_trusted_call(trusted_call_signed: &TCS) -> ValidTransaction { + let from = trusted_call_signed.sender_identity(); + let requires = vec![]; + let provides = vec![(from, trusted_call_signed.nonce()).encode()]; + + ValidTransaction { priority: 1 << 20, requires, provides, longevity: 64, propagate: true } + } + + pub fn hash(&self) -> H256 { + blake2_256(&self.encode()).into() + } +} + +impl PoolTransactionValidation for TrustedOperation +where + TCS: PartialEq + TrustedCallVerification + Encode + Debug, + G: PartialEq + Encode + PoolTransactionValidation + Debug, +{ + fn validate(&self) -> Result { + match self { + TrustedOperation::direct_call(trusted_call_signed) => + Ok(Self::validate_trusted_call(trusted_call_signed)), + TrustedOperation::indirect_call(trusted_call_signed) => + Ok(Self::validate_trusted_call(trusted_call_signed)), + TrustedOperation::get(getter) => getter.validate(), + } + } +} + +/// Trusted operation Or hash +/// +/// Allows to refer to trusted calls either by its raw representation or its hash. +#[derive(Clone, Debug, Encode, Decode, PartialEq)] +pub enum TrustedOperationOrHash +where + TCS: PartialEq + Encode + Debug + Send + Sync, + G: PartialEq + Encode + Debug + Send + Sync, +{ + /// The hash of the call. + #[codec(index = 0)] + Hash(H256), + /// Raw extrinsic bytes. + #[codec(index = 1)] + OperationEncoded(Vec), + /// Raw extrinsic + #[codec(index = 2)] + Operation(Box>), +} + +impl TrustedOperationOrHash +where + TCS: PartialEq + Encode + Debug + Send + Sync, + G: PartialEq + Encode + Debug + Send + Sync, +{ + pub fn from_top(top: TrustedOperation) -> Self { + TrustedOperationOrHash::Operation(Box::new(top)) + } +} + +/// Payload to be sent to peers for a state update. +#[derive(PartialEq, Eq, Clone, Debug, Encode, Decode)] +pub struct StatePayload { + /// State hash before the `state_update` was applied. + state_hash_apriori: H256, + /// State hash after the `state_update` was applied. + state_hash_aposteriori: H256, + /// State diff applied to state with hash `state_hash_apriori` + /// leading to state with hash `state_hash_aposteriori`. + state_update: StateUpdate, +} + +impl StatePayload { + /// Get state hash before the `state_update` was applied. + pub fn state_hash_apriori(&self) -> H256 { + self.state_hash_apriori + } + /// Get state hash after the `state_update` was applied. + pub fn state_hash_aposteriori(&self) -> H256 { + self.state_hash_aposteriori + } + /// Reference to the `state_update`. + pub fn state_update(&self) -> &StateUpdate { + &self.state_update + } + + /// Create new `StatePayload` instance. + pub fn new(apriori: H256, aposteriori: H256, update: StateUpdate) -> Self { + Self { + state_hash_apriori: apriori, + state_hash_aposteriori: aposteriori, + state_update: update, + } + } +} diff --git a/bitacross-worker/core-primitives/stf-state-handler/Cargo.toml b/bitacross-worker/core-primitives/stf-state-handler/Cargo.toml new file mode 100644 index 0000000000..b06d923053 --- /dev/null +++ b/bitacross-worker/core-primitives/stf-state-handler/Cargo.toml @@ -0,0 +1,72 @@ +[package] +name = "itp-stf-state-handler" +version = "0.9.0" +authors = ['Trust Computing GmbH ', 'Integritee AG '] +edition = "2021" + +[dependencies] +# sgx dependencies +sgx_tstd = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git", optional = true } +sgx_types = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git" } + +# local dependencies +itp-hashing = { path = "../../core-primitives/hashing", default-features = false } +itp-settings = { path = "../../core-primitives/settings" } +itp-sgx-crypto = { path = "../../core-primitives/sgx/crypto", default-features = false } +itp-sgx-externalities = { default-features = false, path = "../../core-primitives/substrate-sgx/externalities" } +itp-sgx-io = { path = "../../core-primitives/sgx/io", default-features = false } +itp-stf-interface = { default-features = false, path = "../../core-primitives/stf-interface" } +itp-stf-state-observer = { path = "../stf-state-observer", default-features = false } +itp-time-utils = { path = "../../core-primitives/time-utils", default-features = false } +itp-types = { path = "../types", default-features = false } + +# for tests +itp-sgx-temp-dir = { version = "0.1", default-features = false, optional = true, path = "../../core-primitives/sgx/temp-dir" } + +# sgx enabled external libraries +rust-base58_sgx = { package = "rust-base58", rev = "sgx_1.1.3", git = "https://github.com/mesalock-linux/rust-base58-sgx", optional = true, default-features = false, features = ["mesalock_sgx"] } +thiserror_sgx = { package = "thiserror", git = "https://github.com/mesalock-linux/thiserror-sgx", tag = "sgx_1.1.3", optional = true } + +# std compatible external libraries (make sure these versions match with the sgx-enabled ones above) +rust-base58 = { package = "rust-base58", version = "0.0.4", optional = true } +thiserror = { version = "1.0", optional = true } + +# no-std dependencies +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +log = { version = "0.4", default-features = false } +sp-core = { default-features = false, features = ["full_crypto"], git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } + +[dev-dependencies] +itp-sgx-crypto = { path = "../../core-primitives/sgx/crypto", features = ["mocks"] } +itp-stf-state-observer = { path = "../stf-state-observer", features = ["mocks"] } +itp-hashing = { path = "../../core-primitives/hashing", features = ["std"] } + +[features] +default = ["std"] +std = [ + "rust-base58", + "itp-sgx-crypto/std", + "itp-sgx-externalities/std", + "itp-sgx-io/std", + "itp-stf-interface/std", + "itp-stf-state-observer/std", + "itp-time-utils/std", + "itp-types/std", + "thiserror", + "log/std", +] +sgx = [ + "sgx_tstd", + "rust-base58_sgx", + "itp-sgx-crypto/sgx", + "itp-sgx-externalities/sgx", + "itp-sgx-io/sgx", + "itp-stf-state-observer/sgx", + "itp-time-utils/sgx", + "thiserror_sgx", +] +test = [ + "itp-sgx-crypto/mocks", + "itp-stf-interface/mocks", + "itp-sgx-temp-dir", +] diff --git a/bitacross-worker/core-primitives/stf-state-handler/src/error.rs b/bitacross-worker/core-primitives/stf-state-handler/src/error.rs new file mode 100644 index 0000000000..e283c657a8 --- /dev/null +++ b/bitacross-worker/core-primitives/stf-state-handler/src/error.rs @@ -0,0 +1,90 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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(all(not(feature = "std"), feature = "sgx"))] +use crate::sgx_reexport_prelude::*; + +#[cfg(feature = "std")] +use rust_base58::base58::FromBase58Error; + +#[cfg(feature = "sgx")] +use base58::FromBase58Error; + +use crate::state_snapshot_primitives::StateId; +use itp_types::ShardIdentifier; +use sgx_types::sgx_status_t; +use std::{boxed::Box, format, string::String}; + +pub type Result = core::result::Result; + +#[derive(Debug, thiserror::Error)] +pub enum Error { + #[error("Empty state repository")] + EmptyRepository, + #[error("State ID is invalid and does not exist: {0}")] + InvalidStateId(StateId), + #[error("Shard is invalid and does not exist: {0}")] + InvalidShard(ShardIdentifier), + #[error("State with hash {0} could not be found in the state repository")] + StateNotFoundInRepository(String), + #[error("State observer error: {0}")] + StateObserver(#[from] itp_stf_state_observer::error::Error), + #[error("Cache size for registry is zero")] + ZeroCacheSize, + #[error("Could not acquire lock, lock is poisoned")] + LockPoisoning, + #[error("OsString conversion error")] + OsStringConversion, + #[error("SGX crypto error: {0}")] + CryptoError(itp_sgx_crypto::Error), + #[error("IO error: {0}")] + IO(std::io::Error), + #[error("SGX error, status: {0}")] + SgxError(sgx_status_t), + #[error(transparent)] + Other(#[from] Box), +} + +impl From for Error { + fn from(e: std::io::Error) -> Self { + Self::IO(e) + } +} + +impl From for Error { + fn from(e: codec::Error) -> Self { + Self::Other(format!("{:?}", e).into()) + } +} + +impl From for Error { + fn from(sgx_status: sgx_status_t) -> Self { + Self::SgxError(sgx_status) + } +} + +impl From for Error { + fn from(crypto_error: itp_sgx_crypto::Error) -> Self { + Self::CryptoError(crypto_error) + } +} + +impl From for Error { + fn from(e: FromBase58Error) -> Self { + Self::Other(format!("{:?}", e).into()) + } +} diff --git a/bitacross-worker/core-primitives/stf-state-handler/src/file_io.rs b/bitacross-worker/core-primitives/stf-state-handler/src/file_io.rs new file mode 100644 index 0000000000..c0de994cb5 --- /dev/null +++ b/bitacross-worker/core-primitives/stf-state-handler/src/file_io.rs @@ -0,0 +1,428 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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(all(not(feature = "std"), feature = "sgx"))] +use crate::sgx_reexport_prelude::*; + +#[cfg(any(test, feature = "std"))] +use rust_base58::base58::{FromBase58, ToBase58}; + +#[cfg(feature = "sgx")] +use base58::{FromBase58, ToBase58}; + +#[cfg(any(test, feature = "sgx"))] +use std::string::String; + +use crate::{error::Result, state_snapshot_primitives::StateId}; +use codec::{Decode, Encode}; +// Todo: Can be migrated to here in the course of #1292. +use itp_settings::files::SHARDS_PATH; +use itp_types::ShardIdentifier; +use log::error; +use std::{ + format, + path::{Path, PathBuf}, + vec::Vec, +}; + +/// File name of the encrypted state file. +/// +/// It is also the suffix of all past snapshots. +pub const ENCRYPTED_STATE_FILE: &str = "state.bin"; + +/// Helps with file system operations of all files relevant for the State. +#[derive(Debug, Clone, Eq, PartialEq)] +pub struct StateDir { + base_path: PathBuf, +} + +impl StateDir { + pub fn new(base_path: PathBuf) -> Self { + Self { base_path } + } + + pub fn shards_directory(&self) -> PathBuf { + self.base_path.join(SHARDS_PATH) + } + + pub fn shard_path(&self, shard: &ShardIdentifier) -> PathBuf { + self.shards_directory().join(shard.encode().to_base58()) + } + + pub fn list_shards(&self) -> Result> { + Ok(list_shards(&self.shards_directory()) + .map(|iter| iter.collect()) + // return an empty vec in case the directory does not exist. + .unwrap_or_default()) + } + + pub fn list_state_ids_for_shard( + &self, + shard_identifier: &ShardIdentifier, + ) -> Result> { + let shard_path = self.shard_path(shard_identifier); + Ok(state_ids_for_shard(shard_path.as_path())?.collect()) + } + + pub fn purge_shard_dir(&self, shard: &ShardIdentifier) { + let shard_dir_path = self.shard_path(shard); + if let Err(e) = std::fs::remove_dir_all(&shard_dir_path) { + error!("Failed to remove shard directory {:?}: {:?}", shard_dir_path, e); + } + } + + pub fn shard_exists(&self, shard: &ShardIdentifier) -> bool { + let shard_path = self.shard_path(shard); + shard_path.exists() && shard_contains_valid_state_id(&shard_path) + } + + pub fn create_shard(&self, shard: &ShardIdentifier) -> Result<()> { + Ok(std::fs::create_dir_all(self.shard_path(shard))?) + } + + pub fn state_file_path(&self, shard: &ShardIdentifier, state_id: StateId) -> PathBuf { + self.shard_path(shard).join(to_file_name(state_id)) + } + + pub fn file_for_state_exists(&self, shard: &ShardIdentifier, state_id: StateId) -> bool { + self.state_file_path(shard, state_id).exists() + } + + #[cfg(feature = "test")] + pub fn given_initialized_shard(&self, shard: &ShardIdentifier) { + if self.shard_exists(shard) { + self.purge_shard_dir(shard); + } + self.create_shard(&shard).unwrap() + } +} + +/// Trait to abstract file I/O for state. +pub trait StateFileIo { + type StateType; + type HashType; + + /// Load a state (returns error if it does not exist). + fn load( + &self, + shard_identifier: &ShardIdentifier, + state_id: StateId, + ) -> Result; + + /// Compute the state hash of a specific state (returns error if it does not exist). + /// + /// Requires loading and decoding of the state. Use only when loading the state repository on + /// initialization of the worker. Computing the state hash in other cases is the + /// StateHandler's responsibility. + fn compute_hash( + &self, + shard_identifier: &ShardIdentifier, + state_id: StateId, + ) -> Result; + + /// Initialize a new shard with a given state. + fn initialize_shard( + &self, + shard_identifier: &ShardIdentifier, + state_id: StateId, + state: &Self::StateType, + ) -> Result; + + /// Write the state. + fn write( + &self, + shard_identifier: &ShardIdentifier, + state_id: StateId, + state: &Self::StateType, + ) -> Result; + + /// Remove a state. + fn remove(&self, shard_identifier: &ShardIdentifier, state_id: StateId) -> Result<()>; + + /// Checks if a given shard directory exists and contains at least one state instance. + fn shard_exists(&self, shard_identifier: &ShardIdentifier) -> bool; + + /// Lists all shards. + fn list_shards(&self) -> Result>; + + /// List all states for a shard. + fn list_state_ids_for_shard(&self, shard_identifier: &ShardIdentifier) -> Result>; +} + +#[cfg(feature = "sgx")] +pub mod sgx { + use super::*; + use crate::error::Error; + use codec::Decode; + use core::fmt::Debug; + use itp_hashing::Hash; + use itp_sgx_crypto::{key_repository::AccessKey, StateCrypto}; + use itp_sgx_externalities::SgxExternalitiesTrait; + use itp_sgx_io::{read as io_read, write as io_write}; + use itp_types::H256; + use log::*; + use std::{fs, marker::PhantomData, path::Path, sync::Arc}; + + /// SGX state file I/O. + pub struct SgxStateFileIo { + state_key_repository: Arc, + state_dir: StateDir, + _phantom: PhantomData, + } + + impl SgxStateFileIo + where + StateKeyRepository: AccessKey, + ::KeyType: StateCrypto, + State: SgxExternalitiesTrait, + { + pub fn new(state_key_repository: Arc, state_dir: StateDir) -> Self { + SgxStateFileIo { state_key_repository, state_dir, _phantom: PhantomData } + } + + fn read(&self, path: &Path) -> Result> { + let mut bytes = io_read(path)?; + + if bytes.is_empty() { + return Ok(bytes) + } + + let state_key = self.state_key_repository.retrieve_key()?; + + state_key + .decrypt(&mut bytes) + .map_err(|e| Error::Other(format!("{:?}", e).into()))?; + trace!("buffer decrypted = {:?}", bytes); + + Ok(bytes) + } + + fn encrypt(&self, mut state: Vec) -> Result> { + let state_key = self.state_key_repository.retrieve_key()?; + + state_key + .encrypt(&mut state) + .map_err(|e| Error::Other(format!("{:?}", e).into()))?; + Ok(state) + } + } + + impl StateFileIo for SgxStateFileIo + where + StateKeyRepository: AccessKey, + ::KeyType: StateCrypto, + State: SgxExternalitiesTrait + Hash + Debug, + ::SgxExternalitiesType: Encode + Decode, + { + type StateType = State; + type HashType = H256; + + fn load( + &self, + shard_identifier: &ShardIdentifier, + state_id: StateId, + ) -> Result { + if !self.state_dir.file_for_state_exists(shard_identifier, state_id) { + return Err(Error::InvalidStateId(state_id)) + } + + let state_path = self.state_dir.state_file_path(shard_identifier, state_id); + trace!("loading state from: {:?}", state_path); + let state_encoded = self.read(&state_path)?; + + // State is now decrypted. + debug!( + "State loaded from {:?} with size {}B, deserializing...", + state_path, + state_encoded.len() + ); + let state = ::SgxExternalitiesType::decode( + &mut state_encoded.as_slice(), + )?; + + trace!("state decoded successfully"); + // Add empty state-diff. + let state_with_diff = State::new(state); + trace!("New state created: {:?}", state_with_diff); + Ok(state_with_diff) + } + + fn compute_hash( + &self, + shard_identifier: &ShardIdentifier, + state_id: StateId, + ) -> Result { + let state = self.load(shard_identifier, state_id)?; + Ok(state.hash()) + } + + fn initialize_shard( + &self, + shard_identifier: &ShardIdentifier, + state_id: StateId, + state: &Self::StateType, + ) -> Result { + self.state_dir.create_shard(&shard_identifier)?; + self.write(shard_identifier, state_id, state) + } + + /// Writes the state (without the state diff) encrypted into the enclave storage. + /// Returns the hash of the saved state (independent of the diff!). + fn write( + &self, + shard_identifier: &ShardIdentifier, + state_id: StateId, + state: &Self::StateType, + ) -> Result { + let state_path = self.state_dir.state_file_path(shard_identifier, state_id); + trace!("writing state to: {:?}", state_path); + + // Only save the state, the state diff is pruned. + let cyphertext = self.encrypt(state.state().encode())?; + + let state_hash = state.hash(); + + io_write(&cyphertext, &state_path)?; + + Ok(state_hash) + } + + fn remove(&self, shard_identifier: &ShardIdentifier, state_id: StateId) -> Result<()> { + Ok(fs::remove_file(self.state_dir.state_file_path(shard_identifier, state_id))?) + } + + fn shard_exists(&self, shard_identifier: &ShardIdentifier) -> bool { + self.state_dir.shard_exists(shard_identifier) + } + + fn list_shards(&self) -> Result> { + self.state_dir.list_shards() + } + + fn list_state_ids_for_shard(&self, shard: &ShardIdentifier) -> Result> { + self.state_dir.list_state_ids_for_shard(shard) + } + } +} + +/// Lists all files with a valid state snapshot naming pattern. +pub(crate) fn state_ids_for_shard(shard_path: &Path) -> Result> { + Ok(items_in_directory(shard_path)?.filter_map(|item| { + match extract_state_id_from_file_name(&item) { + Some(state_id) => Some(state_id), + None => { + log::warn!( + "Found item ({}) that does not match state snapshot naming pattern, ignoring it", + item + ); + None + }, + } + })) +} + +/// Returns an iterator over all valid shards in a directory. +/// +/// Ignore any items (files, directories) that are not valid shard identifiers. +pub(crate) fn list_shards(path: &Path) -> Result> { + Ok(items_in_directory(path)?.filter_map(|base58| match shard_from_base58(&base58) { + Ok(shard) => Some(shard), + Err(e) => { + error!("Found invalid shard ({}). Error: {:?}", base58, e); + None + }, + })) +} + +fn shard_from_base58(base58: &str) -> Result { + let vec = base58.from_base58()?; + Ok(Decode::decode(&mut vec.as_slice())?) +} + +/// Returns an iterator over all filenames in a directory. +fn items_in_directory(directory: &Path) -> Result> { + Ok(directory + .read_dir()? + .filter_map(|fr| fr.ok().and_then(|de| de.file_name().into_string().ok()))) +} + +fn shard_contains_valid_state_id(path: &Path) -> bool { + // If at least on item can be decoded into a state id, the shard is not empty. + match state_ids_for_shard(path) { + Ok(mut iter) => iter.next().is_some(), + Err(e) => { + error!("Error in reading shard dir: {:?}", e); + false + }, + } +} + +fn to_file_name(state_id: StateId) -> String { + format!("{}_{}", state_id, ENCRYPTED_STATE_FILE) +} + +fn extract_state_id_from_file_name(file_name: &str) -> Option { + let state_id_str = file_name.strip_suffix(format!("_{}", ENCRYPTED_STATE_FILE).as_str())?; + state_id_str.parse::().ok() +} + +#[cfg(test)] +mod tests { + + use super::*; + use crate::state_snapshot_primitives::generate_current_timestamp_state_id; + + #[test] + fn state_id_to_file_name_works() { + assert!(to_file_name(generate_current_timestamp_state_id()).ends_with(ENCRYPTED_STATE_FILE)); + assert!(to_file_name(generate_current_timestamp_state_id()) + .strip_suffix(format!("_{}", ENCRYPTED_STATE_FILE).as_str()) + .is_some()); + + let now_time_stamp = generate_current_timestamp_state_id(); + assert_eq!( + extract_state_id_from_file_name(to_file_name(now_time_stamp).as_str()).unwrap(), + now_time_stamp + ); + } + + #[test] + fn extract_timestamp_from_file_name_works() { + assert_eq!( + 123456u128, + extract_state_id_from_file_name(format!("123456_{}", ENCRYPTED_STATE_FILE).as_str()) + .unwrap() + ); + assert_eq!( + 0u128, + extract_state_id_from_file_name(format!("0_{}", ENCRYPTED_STATE_FILE).as_str()) + .unwrap() + ); + + assert!(extract_state_id_from_file_name( + format!("987345{}", ENCRYPTED_STATE_FILE).as_str() + ) + .is_none()); + assert!( + extract_state_id_from_file_name(format!("{}", ENCRYPTED_STATE_FILE).as_str()).is_none() + ); + assert!(extract_state_id_from_file_name( + format!("1234_{}-other", ENCRYPTED_STATE_FILE).as_str() + ) + .is_none()); + } +} diff --git a/bitacross-worker/core-primitives/stf-state-handler/src/handle_state.rs b/bitacross-worker/core-primitives/stf-state-handler/src/handle_state.rs new file mode 100644 index 0000000000..8dae3c1f43 --- /dev/null +++ b/bitacross-worker/core-primitives/stf-state-handler/src/handle_state.rs @@ -0,0 +1,83 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 = "sgx")] +use std::sync::SgxRwLockWriteGuard as RwLockWriteGuard; + +#[cfg(feature = "std")] +use std::sync::RwLockWriteGuard; + +use crate::error::Result; +use itp_types::ShardIdentifier; + +/// Facade for handling STF state loading and storing (e.g. from file). +pub trait HandleState { + type WriteLockPayload; + type StateT; + type HashType; + + /// Initialize a new shard. + /// + /// Initializes a default state for the shard and returns its hash. + fn initialize_shard(&self, shard: ShardIdentifier) -> Result; + + /// Execute a function that acts (immutably) on the current state. + /// + /// This allows access to the state, without any cloning. + fn execute_on_current(&self, shard: &ShardIdentifier, executing_function: E) -> Result + where + E: FnOnce(&Self::StateT, Self::HashType) -> R; + + /// Load a clone of the current state for a given shard. + /// + /// Requires the shard to exist and be initialized, otherwise returns an error. + /// Because it results in a clone, prefer using `execute_on_current` whenever possible. + fn load_cloned(&self, shard: &ShardIdentifier) -> Result<(Self::StateT, Self::HashType)>; + + /// Load the state in order to mutate it. + /// + /// Returns a write lock to protect against any concurrent access as long as + /// the lock is held. Finalize the operation by calling `write` and returning + /// the lock again. + fn load_for_mutation( + &self, + shard: &ShardIdentifier, + ) -> Result<(RwLockWriteGuard<'_, Self::WriteLockPayload>, Self::StateT)>; + + /// Writes the state (without the state diff) encrypted into the enclave. + /// + /// Returns the hash of the saved state (independent of the diff!). + fn write_after_mutation( + &self, + state: Self::StateT, + state_lock: RwLockWriteGuard<'_, Self::WriteLockPayload>, + shard: &ShardIdentifier, + ) -> Result; + + /// Reset (or override) a state. + /// + /// Use in cases where the previous state is of no interest. Otherwise use `load_for_mutation` and `write_after_mutation`. + fn reset(&self, state: Self::StateT, shard: &ShardIdentifier) -> Result; + + // litentry + /// Migrate state from old shard to new shard + fn migrate_shard( + &self, + old_shard: ShardIdentifier, + new_shard: ShardIdentifier, + ) -> Result; +} diff --git a/bitacross-worker/core-primitives/stf-state-handler/src/in_memory_state_file_io.rs b/bitacross-worker/core-primitives/stf-state-handler/src/in_memory_state_file_io.rs new file mode 100644 index 0000000000..702ccac0ab --- /dev/null +++ b/bitacross-worker/core-primitives/stf-state-handler/src/in_memory_state_file_io.rs @@ -0,0 +1,418 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 = "sgx")] +use std::sync::SgxRwLock as RwLock; + +#[cfg(feature = "std")] +use std::sync::RwLock; + +use crate::{ + error::{Error, Result}, + file_io::StateFileIo, + state_snapshot_primitives::StateId, +}; +use codec::Encode; +use itp_sgx_externalities::{SgxExternalities, SgxExternalitiesType}; +use itp_types::{ShardIdentifier, H256}; +use sp_core::blake2_256; +use std::{boxed::Box, collections::HashMap, sync::Arc, vec::Vec}; + +type StateHash = H256; +type ShardDirectory = HashMap; +type ShardsRootDirectory = HashMap>; +type InnerStateSelector = + Box State + Send + Sync + 'static>; +type ExternalStateGenerator = + Box ExternalState + Send + Sync + 'static>; + +/// State file I/O using (unencrypted) in-memory representation of the state files. +/// Can be used as mock for testing. +pub struct InMemoryStateFileIo +where + State: Clone + Default + Encode, +{ + emulated_shard_directory: RwLock>, + state_selector: InnerStateSelector, + external_state_generator: ExternalStateGenerator, +} + +impl InMemoryStateFileIo +where + State: Clone + Default + Encode, +{ + #[allow(unused)] + pub fn new( + shards: &[ShardIdentifier], + state_selector: InnerStateSelector, + external_state_generator: ExternalStateGenerator, + ) -> Self { + let shard_hash_map: HashMap<_, _> = + shards.iter().map(|s| (*s, ShardDirectory::::default())).collect(); + + InMemoryStateFileIo { + emulated_shard_directory: RwLock::new(shard_hash_map), + state_selector, + external_state_generator, + } + } + + #[cfg(any(test, feature = "test"))] + pub fn get_states_for_shard( + &self, + shard_identifier: &ShardIdentifier, + ) -> Result> { + let files_lock = self.emulated_shard_directory.read().map_err(|_| Error::LockPoisoning)?; + files_lock + .get(shard_identifier) + .cloned() + .ok_or_else(|| Error::InvalidShard(*shard_identifier)) + } + + fn compute_state_hash(&self, state: &State) -> StateHash { + let encoded_state = state.encode(); + blake2_256(&encoded_state).into() + } + + fn generate_state_entry(&self, state: State) -> (StateHash, State) { + let state_hash = self.compute_state_hash(&state); + (state_hash, state) + } +} + +impl StateFileIo for InMemoryStateFileIo +where + State: Clone + Default + Encode, +{ + type StateType = ExternalState; + type HashType = StateHash; + + fn load( + &self, + shard_identifier: &ShardIdentifier, + state_id: StateId, + ) -> Result { + let directory_lock = + self.emulated_shard_directory.read().map_err(|_| Error::LockPoisoning)?; + let states_for_shard = directory_lock + .get(shard_identifier) + .ok_or_else(|| Error::InvalidShard(*shard_identifier))?; + let inner_state = states_for_shard + .get(&state_id) + .map(|(_, s)| -> State { s.clone() }) + .ok_or_else(|| Error::InvalidStateId(state_id))?; + + Ok((self.external_state_generator)(inner_state)) + } + + fn compute_hash( + &self, + shard_identifier: &ShardIdentifier, + state_id: StateId, + ) -> Result { + let state = self.load(shard_identifier, state_id)?; + Ok(self.compute_state_hash(&(self.state_selector)(&state))) + } + + fn initialize_shard( + &self, + shard_identifier: &ShardIdentifier, + state_id: StateId, + external_state: &Self::StateType, + ) -> Result { + let mut directory_lock = + self.emulated_shard_directory.write().map_err(|_| Error::LockPoisoning)?; + + let states_for_shard = directory_lock.entry(*shard_identifier).or_default(); + let state_entry = states_for_shard + .entry(state_id) + .or_insert_with(|| self.generate_state_entry((self.state_selector)(external_state))); + Ok(state_entry.0) + } + + fn write( + &self, + shard_identifier: &ShardIdentifier, + state_id: StateId, + external_state: &Self::StateType, + ) -> Result { + let mut directory_lock = + self.emulated_shard_directory.write().map_err(|_| Error::LockPoisoning)?; + + let states_for_shard = directory_lock.entry(*shard_identifier).or_default(); + + let inner_state = (self.state_selector)(external_state); + let state_hash = self.compute_state_hash(&inner_state); + + *states_for_shard.entry(state_id).or_default() = (state_hash, inner_state); + + Ok(state_hash) + } + + fn remove(&self, shard_identifier: &ShardIdentifier, state_id: StateId) -> Result<()> { + let mut directory_lock = + self.emulated_shard_directory.write().map_err(|_| Error::LockPoisoning)?; + + let states_for_shard = directory_lock + .get_mut(shard_identifier) + .ok_or_else(|| Error::InvalidShard(*shard_identifier))?; + + states_for_shard + .remove(&state_id) + .ok_or_else(|| Error::InvalidStateId(state_id)) + .map(|_| {}) + } + + fn shard_exists(&self, shard_identifier: &ShardIdentifier) -> bool { + let directory_lock = self.emulated_shard_directory.read().unwrap(); + directory_lock.contains_key(shard_identifier) + } + + fn list_shards(&self) -> Result> { + let directory_lock = + self.emulated_shard_directory.read().map_err(|_| Error::LockPoisoning)?; + Ok(directory_lock.keys().copied().collect()) + } + + fn list_state_ids_for_shard(&self, shard_identifier: &ShardIdentifier) -> Result> { + let directory_lock = + self.emulated_shard_directory.read().map_err(|_| Error::LockPoisoning)?; + let shard_directory = directory_lock + .get(shard_identifier) + .ok_or_else(|| Error::InvalidShard(*shard_identifier))?; + Ok(shard_directory.keys().cloned().collect()) + } +} + +pub fn create_sgx_externalities_in_memory_state_io( +) -> Arc> { + create_in_memory_externalities_state_io(&[]) +} + +fn create_in_memory_externalities_state_io( + shards: &[ShardIdentifier], +) -> Arc> { + Arc::new(InMemoryStateFileIo::new( + shards, + sgx_externalities_selector(), + sgx_externalities_wrapper(), + )) +} + +fn sgx_externalities_selector() -> InnerStateSelector { + Box::new(|s| s.state.clone()) +} + +fn sgx_externalities_wrapper() -> ExternalStateGenerator { + Box::new(|s| SgxExternalities { state: s, state_diff: Default::default() }) +} + +#[cfg(feature = "sgx")] +pub mod sgx { + use super::*; + use crate::file_io::list_shards; + use std::path::Path; + + pub fn create_in_memory_state_io_from_shards_directories( + path: &Path, + ) -> Result>> { + let shards: Vec = + list_shards(path).map(|iter| iter.collect()).unwrap_or_default(); + Ok(create_in_memory_externalities_state_io(&shards)) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use std::assert_matches::assert_matches; + + type TestState = u64; + type TestStateFileIo = InMemoryStateFileIo; + + #[test] + fn shard_directory_is_empty_after_initialization() { + let state_file_io = create_empty_in_memory_state_file_io(); + assert!(state_file_io.list_shards().unwrap().is_empty()); + } + + #[test] + fn load_on_empty_directory_and_shard_returns_error() { + let state_file_io = create_empty_in_memory_state_file_io(); + + assert_matches!( + state_file_io.load(&ShardIdentifier::random(), 1234), + Err(Error::InvalidShard(_)) + ); + } + + #[test] + fn initialize_with_shard_creates_empty_directory() { + let shard = ShardIdentifier::from([2u8; 32]); + let state_file_io = create_in_memory_state_file_io(&[shard]); + + assert!(state_file_io.list_state_ids_for_shard(&shard).unwrap().is_empty()); + assert!(state_file_io + .list_state_ids_for_shard(&ShardIdentifier::from([3u8; 32])) + .is_err()); + } + + #[test] + fn load_when_state_does_not_exist_returns_error() { + let state_file_io = create_empty_in_memory_state_file_io(); + let shard_id = ShardIdentifier::random(); + let _ = state_file_io.initialize_shard(&shard_id, 1234, &Default::default()).unwrap(); + + assert_matches!(state_file_io.load(&shard_id, 12345), Err(Error::InvalidStateId(12345))); + } + + #[test] + fn create_initialized_when_shard_already_exists_works() { + let shard = ShardIdentifier::random(); + let state_file_io = create_in_memory_state_file_io(&[shard]); + + assert!(state_file_io.initialize_shard(&shard, 1245, &Default::default()).is_ok()); + } + + #[test] + fn create_initialized_adds_default_state() { + let state_file_io = create_empty_in_memory_state_file_io(); + let shard_id = ShardIdentifier::random(); + let state_id = 31081984u128; + let state_hash = state_file_io + .initialize_shard(&shard_id, state_id, &Default::default()) + .unwrap(); + + assert_eq!(1, state_file_io.list_shards().unwrap().len()); + assert_eq!(TestState::default(), state_file_io.load(&shard_id, state_id).unwrap()); + assert_eq!(1, state_file_io.list_state_ids_for_shard(&shard_id).unwrap().len()); + + assert_entry(&state_file_io, &shard_id, state_id, &TestState::default(), &state_hash); + } + + #[test] + fn write_works_when_no_previous_shard_or_file_exists() { + let state_file_io = create_empty_in_memory_state_file_io(); + let shard_id = ShardIdentifier::random(); + let state_id = 23u128; + let test_state = 42u64; + + let state_hash = state_file_io.write(&shard_id, state_id, &test_state).unwrap(); + + assert_eq!(1, state_file_io.list_shards().unwrap().len()); + assert_eq!(test_state, state_file_io.load(&shard_id, state_id).unwrap()); + assert_eq!(1, state_file_io.list_state_ids_for_shard(&shard_id).unwrap().len()); + assert_entry(&state_file_io, &shard_id, state_id, &test_state, &state_hash); + } + + #[test] + fn write_overwrites_existing_state() { + let state_file_io = create_empty_in_memory_state_file_io(); + let shard_id = ShardIdentifier::random(); + let state_id = 123456u128; + let _ = state_file_io + .initialize_shard(&shard_id, state_id, &Default::default()) + .unwrap(); + + let test_state = 4256u64; + let state_hash = state_file_io.write(&shard_id, state_id, &test_state).unwrap(); + + assert_eq!(1, state_file_io.list_shards().unwrap().len()); + assert_eq!(test_state, state_file_io.load(&shard_id, state_id).unwrap()); + assert_eq!(1, state_file_io.list_state_ids_for_shard(&shard_id).unwrap().len()); + assert_entry(&state_file_io, &shard_id, state_id, &test_state, &state_hash); + } + + #[test] + fn remove_files_works() { + let state_file_io = create_empty_in_memory_state_file_io(); + let shard_id = ShardIdentifier::random(); + let initial_state_id = 42u128; + let _ = state_file_io + .initialize_shard(&shard_id, initial_state_id, &Default::default()) + .unwrap(); + + let state_ids = vec![1u128, 2u128, 3u128]; + + for state_id in state_ids.iter() { + let _ = state_file_io.write(&shard_id, *state_id, &987345).unwrap(); + } + + let mut expected_size = state_ids.len() + 1; + assert_eq!(expected_size, state_file_io.list_state_ids_for_shard(&shard_id).unwrap().len()); + expected_size -= 1; + + for state_id in state_ids.iter() { + state_file_io.remove(&shard_id, *state_id).unwrap(); + assert_matches!( + state_file_io.load(&shard_id, *state_id), + Err(Error::InvalidStateId(_)) + ); + assert_eq!( + expected_size, + state_file_io.list_state_ids_for_shard(&shard_id).unwrap().len() + ); + expected_size -= 1; + } + } + + #[test] + fn initialize_with_shards_creates_empty_maps() { + let shards = vec![ShardIdentifier::random(), ShardIdentifier::random()]; + let state_file_io = create_in_memory_state_file_io(shards.as_slice()); + + assert_eq!(shards.len(), state_file_io.list_shards().unwrap().len()); + for shard in shards { + assert!(state_file_io.list_state_ids_for_shard(&shard).unwrap().is_empty()); + } + } + + fn assert_entry( + state_file_io: &TestStateFileIo, + shard_id: &ShardIdentifier, + state_id: StateId, + state: &TestState, + state_hash: &StateHash, + ) { + let (retrieved_hash, retrieved_state) = + get_state_entry(&state_file_io, &shard_id, state_id); + assert!(state_file_io.shard_exists(shard_id)); + assert_eq!(state_hash, &retrieved_hash); + assert_eq!(state, &retrieved_state); + } + + fn get_state_entry( + state_file_io: &TestStateFileIo, + shard_id: &ShardIdentifier, + state_id: StateId, + ) -> (StateHash, TestState) { + state_file_io + .get_states_for_shard(shard_id) + .unwrap() + .get(&state_id) + .unwrap() + .clone() + } + + fn create_in_memory_state_file_io(shards: &[ShardIdentifier]) -> TestStateFileIo { + InMemoryStateFileIo::new(shards, Box::new(|x| *x), Box::new(|x| x)) + } + + fn create_empty_in_memory_state_file_io() -> TestStateFileIo { + create_in_memory_state_file_io(&[]) + } +} diff --git a/bitacross-worker/core-primitives/stf-state-handler/src/lib.rs b/bitacross-worker/core-primitives/stf-state-handler/src/lib.rs new file mode 100644 index 0000000000..4b6235f9c0 --- /dev/null +++ b/bitacross-worker/core-primitives/stf-state-handler/src/lib.rs @@ -0,0 +1,46 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +#![cfg_attr(not(feature = "std"), no_std)] +#![feature(assert_matches)] + +#[cfg(all(feature = "std", feature = "sgx"))] +compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the same time"); + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +extern crate sgx_tstd as std; + +// re-export module to properly feature gate sgx and regular std environment +#[cfg(all(not(feature = "std"), feature = "sgx"))] +pub mod sgx_reexport_prelude { + pub use rust_base58_sgx as base58; + pub use thiserror_sgx as thiserror; +} + +pub mod error; +pub mod file_io; +pub mod handle_state; +pub mod in_memory_state_file_io; +pub mod query_shard_state; +pub mod state_handler; +pub mod state_initializer; +mod state_snapshot_primitives; +pub mod state_snapshot_repository; +pub mod state_snapshot_repository_loader; +pub mod test; + +pub use state_handler::StateHandler; diff --git a/bitacross-worker/core-primitives/stf-state-handler/src/query_shard_state.rs b/bitacross-worker/core-primitives/stf-state-handler/src/query_shard_state.rs new file mode 100644 index 0000000000..11ff46d044 --- /dev/null +++ b/bitacross-worker/core-primitives/stf-state-handler/src/query_shard_state.rs @@ -0,0 +1,32 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::error::Result; +use itp_types::ShardIdentifier; +use std::vec::Vec; + +/// Trait for querying shard information on the state +/// +/// The reason this is a separate trait, is that it does not require any +/// SGX exclusive data structures (feature sgx) +pub trait QueryShardState { + /// Query whether a given shard exists + fn shard_exists(&self, shard: &ShardIdentifier) -> Result; + + /// List all available shards + fn list_shards(&self) -> Result>; +} diff --git a/bitacross-worker/core-primitives/stf-state-handler/src/state_handler.rs b/bitacross-worker/core-primitives/stf-state-handler/src/state_handler.rs new file mode 100644 index 0000000000..6acf2c579d --- /dev/null +++ b/bitacross-worker/core-primitives/stf-state-handler/src/state_handler.rs @@ -0,0 +1,423 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 = "sgx")] +use std::sync::{SgxRwLock as RwLock, SgxRwLockWriteGuard as RwLockWriteGuard}; + +#[cfg(feature = "std")] +use std::sync::{RwLock, RwLockWriteGuard}; + +use crate::{ + error::{Error, Result}, + handle_state::HandleState, + query_shard_state::QueryShardState, + state_initializer::InitializeState, + state_snapshot_repository::VersionedStateAccess, +}; +use core::fmt::Debug; +use itp_hashing::Hash; +use itp_sgx_externalities::SgxExternalitiesTrait; +use itp_stf_state_observer::traits::UpdateState; +use itp_types::ShardIdentifier; +use log::{debug, trace}; +use std::{collections::HashMap, sync::Arc, vec::Vec}; + +type StatesMap = HashMap; + +/// Implementation of the `HandleState` trait. +/// +/// Responsible for handling any state instances. Holds a map with all the latest states for each shard. +/// In addition, uses the snapshot repository to save file snapshots of a state. +pub struct StateHandler +where + Repository: VersionedStateAccess, +{ + state_snapshot_repository: RwLock, + states_map_lock: RwLock>, + state_observer: Arc, + state_initializer: Arc, +} + +impl + StateHandler +where + Repository: VersionedStateAccess, + Repository::StateType: Hash, + StateObserver: UpdateState, + StateInitializer: InitializeState, +{ + /// Creates a new instance WITHOUT loading any state from the repository. + /// Results in an empty states map. + pub fn new( + state_snapshot_repository: Repository, + state_observer: Arc, + state_initializer: Arc, + ) -> Self { + Self::new_with_states_map( + state_snapshot_repository, + state_observer, + state_initializer, + Default::default(), + ) + } + + /// Create a new state handler and initialize its state map with the + /// states that are available in the snapshot repository. + pub fn load_from_repository( + state_snapshot_repository: Repository, + state_observer: Arc, + state_initializer: Arc, + ) -> Result { + let states_map = Self::load_all_latest_snapshots(&state_snapshot_repository)?; + Ok(Self::new_with_states_map( + state_snapshot_repository, + state_observer, + state_initializer, + states_map, + )) + } + + fn new_with_states_map( + state_snapshot_repository: Repository, + state_observer: Arc, + state_initializer: Arc, + states_map: StatesMap, + ) -> Self { + StateHandler { + state_snapshot_repository: RwLock::new(state_snapshot_repository), + states_map_lock: RwLock::new(states_map), + state_observer, + state_initializer, + } + } + + fn load_all_latest_snapshots( + state_snapshot_repository: &Repository, + ) -> Result> { + let shards = state_snapshot_repository.list_shards()?; + + let r = shards + .into_iter() + .map(|shard| state_snapshot_repository.load_latest(&shard).map(|state| (state, shard))) + // Fill the pairs for state and shard into a map. + // Log an error for cases where state could not be loaded. + .fold(StatesMap::default(), |mut map, x| { + match x { + Ok((state, shard)) => { + let state_hash = state.hash(); + map.insert(shard, (state, state_hash)); + }, + Err(e) => { + log::error!("Failed to load state from snapshot repository {:?}", e); + }, + }; + map + }); + + Ok(r) + } + + fn update_state_snapshot( + &self, + shard: &ShardIdentifier, + state: &Repository::StateType, + state_hash: Repository::HashType, + ) -> Result<()> { + let mut state_snapshots_lock = + self.state_snapshot_repository.write().map_err(|_| Error::LockPoisoning)?; + + state_snapshots_lock.update(shard, state, state_hash) + } +} + +impl HandleState + for StateHandler +where + Repository: VersionedStateAccess, + Repository::StateType: SgxExternalitiesTrait + Hash + Debug, + Repository::HashType: Copy, + StateObserver: UpdateState, + StateInitializer: InitializeState, +{ + type WriteLockPayload = StatesMap; + type StateT = Repository::StateType; + type HashType = Repository::HashType; + + fn initialize_shard(&self, shard: ShardIdentifier) -> Result { + let initialized_state = self.state_initializer.initialize()?; + self.reset(initialized_state, &shard) + } + + fn execute_on_current(&self, shard: &ShardIdentifier, executing_function: E) -> Result + where + E: FnOnce(&Self::StateT, Self::HashType) -> R, + { + self.states_map_lock + .read() + .map_err(|_| Error::LockPoisoning)? + .get(shard) + .map(|(state, state_hash)| executing_function(state, *state_hash)) + .ok_or_else(|| Error::InvalidShard(*shard)) + } + + fn load_cloned(&self, shard: &ShardIdentifier) -> Result<(Self::StateT, Self::HashType)> { + let state = self + .states_map_lock + .read() + .map_err(|_| Error::LockPoisoning)? + .get(shard) + .ok_or_else(|| Error::InvalidShard(*shard))? + .clone(); + + Ok(state) + } + + fn load_for_mutation( + &self, + shard: &ShardIdentifier, + ) -> Result<(RwLockWriteGuard<'_, Self::WriteLockPayload>, Self::StateT)> { + let state_write_lock = self.states_map_lock.write().map_err(|_| Error::LockPoisoning)?; + let state_clone = state_write_lock + .get(shard) + .ok_or_else(|| Error::InvalidShard(*shard))? + .0 + .clone(); + + Ok((state_write_lock, state_clone)) + } + + fn write_after_mutation( + &self, + mut state: Self::StateT, + mut state_lock: RwLockWriteGuard<'_, Self::WriteLockPayload>, + shard: &ShardIdentifier, + ) -> Result { + debug!("Writing state"); + trace!("State: {:?}", state); + state.prune_state_diff(); // Remove state diff before storing. + let state_hash = state.hash(); + // We create a state copy here, in order to serve the state observer. This does not scale + // well and we will want a better solution in the future, maybe with #459. + state_lock.insert(*shard, (state.clone(), state_hash)); + drop(state_lock); // Drop the write lock as early as possible. + + self.update_state_snapshot(shard, &state, state_hash)?; + + self.state_observer.queue_state_update(*shard, state)?; + Ok(state_hash) + } + + fn reset(&self, state: Self::StateT, shard: &ShardIdentifier) -> Result { + debug!("Resetting state"); + trace!("Resetting state: {:?}", state); + let state_write_lock = self.states_map_lock.write().map_err(|_| Error::LockPoisoning)?; + self.write_after_mutation(state, state_write_lock, shard) + } + + fn migrate_shard( + &self, + old_shard: ShardIdentifier, + new_shard: ShardIdentifier, + ) -> Result { + let (state, _) = self.load_cloned(&old_shard)?; + self.reset(state, &new_shard) + } +} + +impl QueryShardState + for StateHandler +where + Repository: VersionedStateAccess, + Repository::StateType: Hash, + StateObserver: UpdateState, + StateInitializer: InitializeState, +{ + fn shard_exists(&self, shard: &ShardIdentifier) -> Result { + let states_map_lock = self.states_map_lock.read().map_err(|_| Error::LockPoisoning)?; + Ok(states_map_lock.contains_key(shard)) + } + + fn list_shards(&self) -> Result> { + let states_map_lock = self.states_map_lock.read().map_err(|_| Error::LockPoisoning)?; + Ok(states_map_lock.keys().cloned().collect()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::test::mocks::{ + initialize_state_mock::InitializeStateMock, + versioned_state_access_mock::VersionedStateAccessMock, + }; + use codec::Encode; + use itp_sgx_externalities::{SgxExternalities, SgxExternalitiesType}; + use itp_stf_state_observer::mock::UpdateStateMock; + use itp_types::H256; + use std::{collections::VecDeque, sync::Arc, thread}; + + type TestState = SgxExternalities; + type TestHash = H256; + type TestStateRepository = VersionedStateAccessMock; + type TestStateObserver = UpdateStateMock; + type TestStateInitializer = InitializeStateMock; + type TestStateHandler = + StateHandler; + + fn create_state(content: u64) -> TestState { + let mut state = TestState::new(SgxExternalitiesType::default()); + state.insert("key_1".encode(), content.encode()); + state + } + + fn create_state_without_diff(content: u64) -> TestState { + let state = create_state(content); + prune_diff(state) + } + + fn prune_diff(mut state: TestState) -> TestState { + state.prune_state_diff(); + state + } + + #[test] + fn load_for_mutation_blocks_any_concurrent_access() { + let shard_id = ShardIdentifier::random(); + let state_handler = default_state_handler(); + state_handler.initialize_shard(shard_id).unwrap(); + + let (lock, _s) = state_handler.load_for_mutation(&shard_id).unwrap(); + + let state_handler_clone = state_handler.clone(); + let join_handle = thread::spawn(move || { + let (latest_state, _) = state_handler_clone.load_cloned(&shard_id).unwrap(); + assert_eq!(create_state_without_diff(4u64), latest_state); + }); + + let _hash = + state_handler.write_after_mutation(create_state(4u64), lock, &shard_id).unwrap(); + + join_handle.join().unwrap(); + } + + #[test] + fn write_and_reset_queue_observer_update() { + let shard_id = ShardIdentifier::default(); + let state_observer = Arc::new(TestStateObserver::default()); + let state_initializer = Arc::new(TestStateInitializer::new(Default::default())); + let state_handler = Arc::new(TestStateHandler::new( + default_repository(), + state_observer.clone(), + state_initializer, + )); + state_handler.initialize_shard(shard_id).unwrap(); + + let (lock, _s) = state_handler.load_for_mutation(&shard_id).unwrap(); + let new_state = create_state(4u64); + state_handler.write_after_mutation(new_state.clone(), lock, &shard_id).unwrap(); + + let reset_state = create_state(5u64); + state_handler.reset(reset_state.clone(), &shard_id).unwrap(); + + let observer_updates = state_observer.queued_updates.read().unwrap().clone(); + assert_eq!(3, observer_updates.len()); + assert_eq!((shard_id, prune_diff(new_state)), observer_updates[1]); + assert_eq!((shard_id, prune_diff(reset_state)), observer_updates[2]); + } + + #[test] + fn load_initialized_works() { + let shard_id = ShardIdentifier::random(); + let state_handler = default_state_handler(); + state_handler.initialize_shard(shard_id).unwrap(); + assert!(state_handler.load_cloned(&shard_id).is_ok()); + assert!(state_handler.load_cloned(&ShardIdentifier::random()).is_err()); + } + + #[test] + fn list_shards_works() { + let shard_id = ShardIdentifier::random(); + let state_handler = default_state_handler(); + state_handler.initialize_shard(shard_id).unwrap(); + assert_eq!(1, state_handler.list_shards().unwrap().len()); + } + + #[test] + fn shard_exists_works() { + let shard_id = ShardIdentifier::random(); + let state_handler = default_state_handler(); + state_handler.initialize_shard(shard_id).unwrap(); + assert!(state_handler.shard_exists(&shard_id).unwrap()); + assert!(!state_handler.shard_exists(&ShardIdentifier::random()).unwrap()); + } + + #[test] + fn load_from_repository_works() { + let state_observer = Arc::new(TestStateObserver::default()); + let state_initializer = Arc::new(TestStateInitializer::new(Default::default())); + + let repository = TestStateRepository::new(HashMap::from([ + ( + ShardIdentifier::from([1u8; 32]), + VecDeque::from([create_state(3), create_state(2), create_state(1)]), + ), + (ShardIdentifier::from([2u8; 32]), VecDeque::from([create_state(5)])), + (ShardIdentifier::from([3u8; 32]), VecDeque::new()), + ])); + + assert_eq!(3, repository.list_shards().unwrap().len()); + assert!(repository.load_latest(&ShardIdentifier::from([3u8; 32])).is_err()); + + let state_handler = + TestStateHandler::load_from_repository(repository, state_observer, state_initializer) + .unwrap(); + + assert_eq!( + 2, + state_handler.list_shards().unwrap().len(), + "Only 2 shards, not 3, because 3rd was empty" + ); + } + + #[test] + fn ensure_state_diff_is_discarded() { + let shard_id = ShardIdentifier::random(); + let state_handler = default_state_handler(); + + let state = create_state(3u64); + let state_without_diff = { + let mut state_clone = state.clone(); + state_clone.prune_state_diff(); + state_clone + }; + + state_handler.reset(state, &shard_id).unwrap(); + let (loaded_state, _) = state_handler.load_cloned(&shard_id).unwrap(); + + assert_eq!(state_without_diff, loaded_state); + } + + fn default_state_handler() -> Arc { + let state_observer = Arc::new(TestStateObserver::default()); + let state_initializer = Arc::new(TestStateInitializer::new(Default::default())); + Arc::new(TestStateHandler::new(default_repository(), state_observer, state_initializer)) + } + + fn default_repository() -> TestStateRepository { + TestStateRepository::default() + } +} diff --git a/bitacross-worker/core-primitives/stf-state-handler/src/state_initializer.rs b/bitacross-worker/core-primitives/stf-state-handler/src/state_initializer.rs new file mode 100644 index 0000000000..5799c20823 --- /dev/null +++ b/bitacross-worker/core-primitives/stf-state-handler/src/state_initializer.rs @@ -0,0 +1,64 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::error::Result; +use core::marker::PhantomData; +use itp_sgx_crypto::{ed25519_derivation::DeriveEd25519, key_repository::AccessKey}; +use itp_stf_interface::InitState; +use itp_types::AccountId; +use sp_core::Pair; +use std::sync::Arc; + +/// Create and initialize a new state instance. +pub trait InitializeState { + type StateType; + + fn initialize(&self) -> Result; +} + +pub struct StateInitializer { + shielding_key_repository: Arc, + _phantom: PhantomData<(State, Stf)>, +} + +impl StateInitializer +where + Stf: InitState, + ShieldingKeyRepository: AccessKey, + ShieldingKeyRepository::KeyType: DeriveEd25519, +{ + pub fn new(shielding_key_repository: Arc) -> Self { + Self { shielding_key_repository, _phantom: Default::default() } + } +} + +impl InitializeState + for StateInitializer +where + Stf: InitState, + ShieldingKeyRepository: AccessKey, + ShieldingKeyRepository::KeyType: DeriveEd25519, +{ + type StateType = State; + + fn initialize(&self) -> Result { + // This implementation basically exists because it is non-trivial to initialize the state with + // an enclave account that is derived from the shielding key. + let enclave_account = self.shielding_key_repository.retrieve_key()?.derive_ed25519()?; + Ok(Stf::init_state(enclave_account.public().into())) + } +} diff --git a/bitacross-worker/core-primitives/stf-state-handler/src/state_snapshot_primitives.rs b/bitacross-worker/core-primitives/stf-state-handler/src/state_snapshot_primitives.rs new file mode 100644 index 0000000000..50c3f00afc --- /dev/null +++ b/bitacross-worker/core-primitives/stf-state-handler/src/state_snapshot_primitives.rs @@ -0,0 +1,56 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{error::Result, file_io::StateFileIo}; +use itp_time_utils::now_as_nanos; +use itp_types::ShardIdentifier; +use std::collections::{HashMap, VecDeque}; + +pub type StateId = u128; + +pub(crate) type SnapshotHistory = + HashMap>>; + +/// Internal wrapper for a state hash and state ID. +#[derive(Clone)] +pub(crate) struct StateSnapshotMetaData { + pub(crate) state_hash: HashType, + pub(crate) state_id: StateId, +} + +impl StateSnapshotMetaData { + pub fn new(state_hash: HashType, state_id: StateId) -> Self { + StateSnapshotMetaData { state_hash, state_id } + } +} + +pub(crate) fn initialize_shard_with_snapshot( + shard_identifier: &ShardIdentifier, + file_io: &FileIo, + state: &FileIo::StateType, +) -> Result> +where + FileIo: StateFileIo, +{ + let state_id = generate_current_timestamp_state_id(); + let state_hash = file_io.initialize_shard(shard_identifier, state_id, state)?; + Ok(StateSnapshotMetaData::new(state_hash, state_id)) +} + +pub(crate) fn generate_current_timestamp_state_id() -> StateId { + now_as_nanos() +} diff --git a/bitacross-worker/core-primitives/stf-state-handler/src/state_snapshot_repository.rs b/bitacross-worker/core-primitives/stf-state-handler/src/state_snapshot_repository.rs new file mode 100644 index 0000000000..1b60a88741 --- /dev/null +++ b/bitacross-worker/core-primitives/stf-state-handler/src/state_snapshot_repository.rs @@ -0,0 +1,484 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{ + error::{Error, Result}, + file_io::StateFileIo, + state_snapshot_primitives::{ + generate_current_timestamp_state_id, initialize_shard_with_snapshot, SnapshotHistory, + StateId, StateSnapshotMetaData, + }, +}; +use core::ops::RangeBounds; +use itp_types::ShardIdentifier; +use log::*; +use std::{collections::VecDeque, fmt::Debug, format, sync::Arc, vec::Vec}; + +/// Trait for versioned state access. Manages history of state snapshots. +pub trait VersionedStateAccess { + type StateType: Clone; + type HashType; + + /// Load the latest version of the state. + fn load_latest(&self, shard_identifier: &ShardIdentifier) -> Result; + + /// Update the state, returning the hash of the state. + fn update( + &mut self, + shard_identifier: &ShardIdentifier, + state: &Self::StateType, + state_hash: Self::HashType, + ) -> Result<()>; + + /// Reverts the state of a given shard to a state version identified by a state hash. + fn revert_to( + &mut self, + shard_identifier: &ShardIdentifier, + state_hash: &Self::HashType, + ) -> Result; + + /// Initialize a new shard. + /// + /// If the shard already exists, it will re-initialize it. + fn initialize_new_shard( + &mut self, + shard_identifier: ShardIdentifier, + state: &Self::StateType, + ) -> Result; + + /// Checks if a shard for a given identifier exists. + fn shard_exists(&self, shard_identifier: &ShardIdentifier) -> bool; + + /// Lists all shards. + fn list_shards(&self) -> Result>; +} + +/// State snapshot repository. +/// +/// Keeps versions of state snapshots, cycles them in a fixed-size circular buffer. +/// Creates a state snapshot for each write/update operation. Allows reverting to a specific snapshot, +/// identified by a state hash. Snapshot files names includes a timestamp to be unique. +pub struct StateSnapshotRepository +where + FileIo: StateFileIo, + ::HashType: Copy + Eq + Debug, + ::StateType: Clone, +{ + file_io: Arc, + snapshot_history_cache_size: usize, + snapshot_history: SnapshotHistory, +} + +impl StateSnapshotRepository +where + FileIo: StateFileIo, + ::HashType: Copy + Eq + Debug, + ::StateType: Clone, +{ + /// Constructor, initialized with no shards or snapshot history. + pub fn empty(file_io: Arc, snapshot_history_cache_size: usize) -> Result { + Self::new(file_io, snapshot_history_cache_size, SnapshotHistory::default()) + } + + /// Constructor to initialize the repository with shards and snapshot history. + /// + /// Crate private, to be used by the loader. + pub(crate) fn new( + file_io: Arc, + snapshot_history_cache_size: usize, + snapshot_history: SnapshotHistory, + ) -> Result { + if snapshot_history_cache_size == 0usize { + return Err(Error::ZeroCacheSize) + } + + Ok(StateSnapshotRepository { file_io, snapshot_history_cache_size, snapshot_history }) + } + + fn get_snapshot_history_mut( + &mut self, + shard_identifier: &ShardIdentifier, + ) -> Result<&mut VecDeque>> { + self.snapshot_history + .get_mut(shard_identifier) + .ok_or_else(|| Error::InvalidShard(*shard_identifier)) + } + + fn get_snapshot_history( + &self, + shard_identifier: &ShardIdentifier, + ) -> Result<&VecDeque>> { + self.snapshot_history + .get(shard_identifier) + .ok_or_else(|| Error::InvalidShard(*shard_identifier)) + } + + fn get_latest_snapshot_metadata( + &self, + shard_identifier: &ShardIdentifier, + ) -> Result<&StateSnapshotMetaData> { + let snapshot_history = self.get_snapshot_history(shard_identifier)?; + snapshot_history.front().ok_or(Error::EmptyRepository) + } + + fn prune_snapshot_history_by_range>( + &mut self, + shard_identifier: &ShardIdentifier, + range: R, + ) -> Result<()> { + let state_snapshots_to_remove = self + .get_snapshot_history_mut(shard_identifier)? + .drain(range) + .collect::>(); + + self.remove_snapshots(shard_identifier, state_snapshots_to_remove.as_slice()); + Ok(()) + } + + /// Remove snapshots referenced by metadata. + /// Does not stop on error, it's guaranteed to call `remove` on all elements. + /// Logs any errors that occur. + fn remove_snapshots( + &self, + shard_identifier: &ShardIdentifier, + snapshots_metadata: &[StateSnapshotMetaData], + ) { + for snapshot_metadata in snapshots_metadata { + if let Err(e) = self.file_io.remove(shard_identifier, snapshot_metadata.state_id) { + // We just log an error, don't want to return the error here, because the operation + // in general was successful, just a side-effect that failed. + error!("Failed to remove state, with id '{}': {:?}", snapshot_metadata.state_id, e); + } + } + } + + fn write_new_state( + &self, + shard_identifier: &ShardIdentifier, + state: &FileIo::StateType, + ) -> Result<(FileIo::HashType, StateId)> { + let state_id = generate_current_timestamp_state_id(); + let state_hash = self.file_io.write(shard_identifier, state_id, state)?; + Ok((state_hash, state_id)) + } + + fn initialize_shard_with_snapshot( + &mut self, + shard_identifier: &ShardIdentifier, + state: &FileIo::StateType, + ) -> Result { + let snapshot_metadata = + initialize_shard_with_snapshot(shard_identifier, self.file_io.as_ref(), state)?; + + let state_hash = snapshot_metadata.state_hash; + self.snapshot_history + .insert(*shard_identifier, VecDeque::from([snapshot_metadata])); + Ok(state_hash) + } + + fn load_state( + &self, + shard_identifier: &ShardIdentifier, + snapshot_metadata: &StateSnapshotMetaData, + ) -> Result { + self.file_io.load(shard_identifier, snapshot_metadata.state_id) + } +} + +impl VersionedStateAccess for StateSnapshotRepository +where + FileIo: StateFileIo, + ::HashType: Copy + Eq + Debug, + ::StateType: Clone, +{ + type StateType = FileIo::StateType; + type HashType = FileIo::HashType; + + fn load_latest(&self, shard_identifier: &ShardIdentifier) -> Result { + let latest_snapshot_metadata = self.get_latest_snapshot_metadata(shard_identifier)?; + self.file_io.load(shard_identifier, latest_snapshot_metadata.state_id) + } + + fn update( + &mut self, + shard_identifier: &ShardIdentifier, + state: &Self::StateType, + state_hash: Self::HashType, + ) -> Result<()> { + if !self.shard_exists(shard_identifier) { + self.initialize_shard_with_snapshot(shard_identifier, state)?; + return Ok(()) + } + + let (_state_hash, state_id) = self.write_new_state(shard_identifier, state)?; + let cache_size = self.snapshot_history_cache_size; + + let snapshot_history = self.get_snapshot_history_mut(shard_identifier)?; + snapshot_history.push_front(StateSnapshotMetaData::new(state_hash, state_id)); + + // In case we're above max queue size we remove the oldest entries and corresponding files + if snapshot_history.len() > cache_size { + self.prune_snapshot_history_by_range(shard_identifier, cache_size..)?; + } + + Ok(()) + } + + fn revert_to( + &mut self, + shard_identifier: &ShardIdentifier, + state_hash: &Self::HashType, + ) -> Result { + let snapshot_history = self.get_snapshot_history(shard_identifier)?; + + // We use `position()` instead of `find()`, because it then allows us to easily drain + // all the newer states. + let snapshot_metadata_index = snapshot_history + .iter() + .position(|fmd| fmd.state_hash == *state_hash) + .ok_or_else(|| Error::StateNotFoundInRepository(format!("{:?}", state_hash)))?; + + // Should never fail, since we got the index from above, with `position()`. + let snapshot_metadata = snapshot_history + .get(snapshot_metadata_index) + .ok_or_else(|| Error::StateNotFoundInRepository(format!("{:?}", state_hash)))?; + + let state = self.load_state(shard_identifier, snapshot_metadata)?; + + // Remove any state versions newer than the one we're resetting to + // (do this irreversible operation last, to ensure the loading has succeeded) + self.prune_snapshot_history_by_range(shard_identifier, ..snapshot_metadata_index)?; + + Ok(state) + } + + fn initialize_new_shard( + &mut self, + shard_identifier: ShardIdentifier, + state: &Self::StateType, + ) -> Result { + self.initialize_shard_with_snapshot(&shard_identifier, state) + } + + fn shard_exists(&self, shard_identifier: &ShardIdentifier) -> bool { + self.snapshot_history.get(shard_identifier).is_some() + } + + fn list_shards(&self) -> Result> { + Ok(self.snapshot_history.keys().cloned().collect()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::{ + in_memory_state_file_io::InMemoryStateFileIo, + state_snapshot_repository_loader::StateSnapshotRepositoryLoader, + test::mocks::initialize_state_mock::InitializeStateMock, + }; + use codec::Encode; + use itp_hashing::Hash; + use sp_core::{blake2_256, H256}; + use std::vec; + + #[derive(Encode, Clone, Default, Copy, Eq, PartialEq, Debug)] + struct TestState(pub u64); + + impl Hash for TestState { + fn hash(&self) -> H256 { + blake2_256(&self.encode()).into() + } + } + + type TestFileIo = InMemoryStateFileIo; + type TestStateInitializer = InitializeStateMock; + type TestSnapshotRepository = StateSnapshotRepository; + + const TEST_SNAPSHOT_REPOSITORY_CACHE_SIZE: usize = 3; + + #[test] + fn new_with_zero_cache_size_returns_error() { + let shards = + vec![ShardIdentifier::random(), ShardIdentifier::random(), ShardIdentifier::random()]; + let file_io = create_test_file_io(shards.as_slice()); + + assert!(TestSnapshotRepository::empty(file_io.clone(), 0usize).is_err()); + } + + #[test] + fn upon_new_all_shards_are_initialized() { + let shards = + vec![ShardIdentifier::random(), ShardIdentifier::random(), ShardIdentifier::random()]; + let (file_io, state_snapshot_repository) = create_state_snapshot_repository( + shards.as_slice(), + TEST_SNAPSHOT_REPOSITORY_CACHE_SIZE, + ); + + assert_eq!(shards.len(), file_io.list_shards().unwrap().len()); + assert_eq!(shards.len(), state_snapshot_repository.snapshot_history.len()); + assert_eq!(shards.len(), state_snapshot_repository.list_shards().unwrap().len()); + for states_per_shard in state_snapshot_repository.snapshot_history.values() { + assert_eq!(1, states_per_shard.len()); + } + for shard in shards { + assert!(state_snapshot_repository.load_latest(&shard).is_ok()); + assert!(state_snapshot_repository.shard_exists(&shard)); + } + } + + #[test] + fn update_latest_creates_new_state_file() { + let shards = + vec![ShardIdentifier::random(), ShardIdentifier::random(), ShardIdentifier::random()]; + let (file_io, mut state_snapshot_repository) = create_state_snapshot_repository( + shards.as_slice(), + TEST_SNAPSHOT_REPOSITORY_CACHE_SIZE, + ); + + let shard_to_update = shards.get(1).unwrap(); + assert_eq!(1, file_io.get_states_for_shard(shard_to_update).unwrap().len()); + + let new_state = TestState(1234u64); + + let _ = state_snapshot_repository + .update(shard_to_update, &new_state, Default::default()) + .unwrap(); + + let snapshot_history = + state_snapshot_repository.snapshot_history.get(shard_to_update).unwrap(); + assert_eq!(2, snapshot_history.len()); + assert_eq!(new_state, state_snapshot_repository.load_latest(shard_to_update).unwrap()); + assert_eq!(2, file_io.get_states_for_shard(shard_to_update).unwrap().len()); + } + + #[test] + fn update_latest_prunes_states_when_above_cache_size() { + let shard_id = ShardIdentifier::random(); + let (file_io, mut state_snapshot_repository) = + create_state_snapshot_repository(&[shard_id], TEST_SNAPSHOT_REPOSITORY_CACHE_SIZE); + + let states: Vec = + [1u64, 2u64, 3u64, 4u64, 5u64, 6u64].into_iter().map(|i| TestState(i)).collect(); + assert!(states.len() > TEST_SNAPSHOT_REPOSITORY_CACHE_SIZE); // ensures we have pruning + + states.iter().for_each(|state| { + let _ = state_snapshot_repository.update(&shard_id, state, Default::default()).unwrap(); + }); + + let snapshot_history = state_snapshot_repository.snapshot_history.get(&shard_id).unwrap(); + assert_eq!(TEST_SNAPSHOT_REPOSITORY_CACHE_SIZE, snapshot_history.len()); + assert_eq!( + *states.last().unwrap(), + state_snapshot_repository.load_latest(&shard_id).unwrap() + ); + assert_eq!( + TEST_SNAPSHOT_REPOSITORY_CACHE_SIZE, + file_io.get_states_for_shard(&shard_id).unwrap().len() + ); + } + + #[test] + fn update_latest_with_new_shard_creates_entry_and_does_not_modify_original_shard_entry() { + let shard_id = ShardIdentifier::random(); + let (file_io, mut state_snapshot_repository) = + create_state_snapshot_repository(&[shard_id], TEST_SNAPSHOT_REPOSITORY_CACHE_SIZE); + + assert!(state_snapshot_repository + .update(&ShardIdentifier::from_low_u64_be(1u64), &TestState(45), Default::default()) + .is_ok()); + + assert_eq!(2, state_snapshot_repository.snapshot_history.len()); + let snapshot_history = state_snapshot_repository.snapshot_history.get(&shard_id).unwrap(); + assert_eq!(1, snapshot_history.len()); + assert_eq!(TestState(0u64), state_snapshot_repository.load_latest(&shard_id).unwrap()); + assert_eq!(1, file_io.get_states_for_shard(&shard_id).unwrap().len()); + } + + #[test] + fn revert_to_removes_version_newer_than_target_hash() { + let shard_id = ShardIdentifier::random(); + let (file_io, mut state_snapshot_repository) = + create_state_snapshot_repository(&[shard_id], 6); + + let states: Vec = + [1u64, 2u64, 3u64, 4u64, 5u64].into_iter().map(|i| TestState(i)).collect(); + + let state_hashes = states + .iter() + .map(|state| { + let state_hash = state.hash(); + state_snapshot_repository.update(&shard_id, state, state_hash).unwrap(); + state_hash + }) + .collect::>(); + let revert_target_hash = state_hashes.get(1).unwrap(); + + let reverted_state = + state_snapshot_repository.revert_to(&shard_id, revert_target_hash).unwrap(); + + assert_eq!(TestState(2u64), reverted_state); + assert_eq!(3, state_snapshot_repository.snapshot_history.get(&shard_id).unwrap().len()); // because we have initialized version '0' as well + assert_eq!(TestState(2u64), state_snapshot_repository.load_latest(&shard_id).unwrap()); + assert_eq!(3, file_io.get_states_for_shard(&shard_id).unwrap().len()); + } + + #[test] + fn initializing_new_shard_works() { + let (_, mut state_snapshot_repository) = create_state_snapshot_repository(&[], 2); + + let shard_id = ShardIdentifier::random(); + + assert!(state_snapshot_repository.load_latest(&shard_id).is_err()); + assert!(state_snapshot_repository.list_shards().unwrap().is_empty()); + + let _hash = state_snapshot_repository + .initialize_new_shard(shard_id, &Default::default()) + .unwrap(); + + assert!(state_snapshot_repository.load_latest(&shard_id).is_ok()); + assert_eq!(1, state_snapshot_repository.list_shards().unwrap().len()); + } + + #[test] + fn initialize_new_state_when_shard_already_exists_returns_ok() { + let shard_id = ShardIdentifier::random(); + let (_, mut state_snapshot_repository) = create_state_snapshot_repository(&[shard_id], 2); + + let _hash = state_snapshot_repository + .initialize_new_shard(shard_id, &Default::default()) + .unwrap(); + + assert!(state_snapshot_repository.load_latest(&shard_id).is_ok()); + assert_eq!(1, state_snapshot_repository.list_shards().unwrap().len()); + } + + fn create_state_snapshot_repository( + shards: &[ShardIdentifier], + snapshot_history_size: usize, + ) -> (Arc, TestSnapshotRepository) { + let file_io = create_test_file_io(shards); + let state_initializer = Arc::new(TestStateInitializer::new(Default::default())); + let repository_loader = + StateSnapshotRepositoryLoader::new(file_io.clone(), state_initializer); + (file_io, repository_loader.load_snapshot_repository(snapshot_history_size).unwrap()) + } + + fn create_test_file_io(shards: &[ShardIdentifier]) -> Arc { + Arc::new(TestFileIo::new(shards, Box::new(|x| *x), Box::new(|x| x))) + } +} diff --git a/bitacross-worker/core-primitives/stf-state-handler/src/state_snapshot_repository_loader.rs b/bitacross-worker/core-primitives/stf-state-handler/src/state_snapshot_repository_loader.rs new file mode 100644 index 0000000000..88682efd74 --- /dev/null +++ b/bitacross-worker/core-primitives/stf-state-handler/src/state_snapshot_repository_loader.rs @@ -0,0 +1,221 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{ + error::Result, + file_io::StateFileIo, + state_initializer::InitializeState, + state_snapshot_primitives::{ + initialize_shard_with_snapshot, SnapshotHistory, StateId, StateSnapshotMetaData, + }, + state_snapshot_repository::StateSnapshotRepository, +}; +use itp_hashing::Hash; +use itp_types::ShardIdentifier; +use log::*; +use std::{collections::VecDeque, fmt::Debug, iter::FromIterator, sync::Arc, vec::Vec}; + +/// Loads a state snapshot repository from existing shards directory with state files. +pub struct StateSnapshotRepositoryLoader { + file_io: Arc, + state_initializer: Arc, +} + +impl StateSnapshotRepositoryLoader +where + FileIo: StateFileIo, + ::HashType: Copy + Eq + Debug, + ::StateType: Clone + Hash, + StateInitializer: InitializeState, +{ + pub fn new(file_io: Arc, state_initializer: Arc) -> Self { + Self { file_io, state_initializer } + } + + /// Load a state snapshot repository from an existing set of files and directories. + pub fn load_snapshot_repository( + &self, + snapshot_history_cache_size: usize, + ) -> Result> { + let snapshot_history = self.load_and_initialize_state_snapshot_history()?; + + StateSnapshotRepository::new( + self.file_io.clone(), + snapshot_history_cache_size, + snapshot_history, + ) + } + + fn load_and_initialize_state_snapshot_history( + &self, + ) -> Result> { + let mut repository = SnapshotHistory::new(); + + let shards = self.file_io.list_shards()?; + debug!("Found {} shard(s) to load state from", shards.len()); + + for shard in shards { + let mut state_ids = self.file_io.list_state_ids_for_shard(&shard)?; + // Sort by id (which are timestamp), highest, i.e. newest, first + state_ids.sort_unstable(); + state_ids.reverse(); + + let mut snapshot_metadata: Vec<_> = self.map_to_snapshot_metadata(&shard, state_ids); + + if snapshot_metadata.is_empty() { + warn!( + "No (valid) states found for shard {:?}, initializing empty shard state", + shard + ); + let initial_state = self.state_initializer.initialize()?; + let initial_snapshot_metadata = + initialize_shard_with_snapshot(&shard, self.file_io.as_ref(), &initial_state)?; + snapshot_metadata.push(initial_snapshot_metadata); + } else { + debug!( + "Found {} state snapshot(s) for shard {}, latest snapshot is {}", + snapshot_metadata.len(), + &shard, + snapshot_metadata.first().map(|f| f.state_id).unwrap_or_default() + ); + } + + let snapshot_history = VecDeque::from_iter(snapshot_metadata); + + repository.insert(shard, snapshot_history); + } + Ok(repository) + } + + fn map_to_snapshot_metadata( + &self, + shard: &ShardIdentifier, + state_ids: Vec, + ) -> Vec> { + state_ids + .into_iter() + .flat_map(|state_id| match self.file_io.compute_hash(shard, state_id) { + Ok(hash) => Some(StateSnapshotMetaData::new(hash, state_id)), + Err(e) => { + warn!( + "Failed to compute hash for state snapshot with id {}: {:?}, ignoring snapshot as a result", + state_id, e + ); + None + }, + }) + .collect() + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::{ + in_memory_state_file_io::InMemoryStateFileIo, + test::mocks::initialize_state_mock::InitializeStateMock, + }; + use codec::Encode; + use itp_types::H256; + use sp_core::blake2_256; + + #[derive(Encode, Clone, Default, Copy)] + struct TestState(pub u64); + + type TestStateHash = H256; + type TestFileIo = InMemoryStateFileIo; + type TestStateInitializer = InitializeStateMock; + type TestLoader = StateSnapshotRepositoryLoader; + + impl Hash for TestState { + fn hash(&self) -> TestStateHash { + blake2_256(&self.encode()).into() + } + } + + #[test] + fn loading_from_empty_shard_directories_initializes_files() { + let shards = + vec![ShardIdentifier::random(), ShardIdentifier::random(), ShardIdentifier::random()]; + let (_, loader) = create_test_fixtures(shards.as_slice()); + + let snapshot_history = loader.load_and_initialize_state_snapshot_history().unwrap(); + assert_eq!(shards.len(), snapshot_history.len()); + for snapshots in snapshot_history.values() { + assert_eq!(1, snapshots.len()); + } + } + + #[test] + fn loading_without_shards_returns_empty_directory() { + let (_, loader) = create_test_fixtures(&[]); + + let snapshot_history = loader.load_and_initialize_state_snapshot_history().unwrap(); + assert!(snapshot_history.is_empty()); + } + + #[test] + fn loading_from_files_orders_by_timestamp() { + let shards = + vec![ShardIdentifier::random(), ShardIdentifier::random(), ShardIdentifier::random()]; + let (file_io, loader) = create_test_fixtures(shards.as_slice()); + + add_state_snapshots( + file_io.as_ref(), + &shards[0], + &[1_000_000, 2_000_000, 3_000_000, 4_000_000], + ); + add_state_snapshots(file_io.as_ref(), &shards[1], &[10_000_000, 9_000_000]); + add_state_snapshots(file_io.as_ref(), &shards[2], &[14_000_000, 11_000_000, 12_000_000]); + + let snapshot_history = loader.load_and_initialize_state_snapshot_history().unwrap(); + + assert_eq!(shards.len(), snapshot_history.len()); + assert_latest_state_id(&snapshot_history, &shards[0], 4_000_000); + assert_latest_state_id(&snapshot_history, &shards[1], 10_000_000); + assert_latest_state_id(&snapshot_history, &shards[2], 14_000_000); + } + + fn add_state_snapshots(file_io: &TestFileIo, shard: &ShardIdentifier, state_ids: &[StateId]) { + for state_id in state_ids { + add_snapshot_with_state_ids(file_io, shard, *state_id); + } + } + + fn add_snapshot_with_state_ids( + file_io: &TestFileIo, + shard: &ShardIdentifier, + state_id: StateId, + ) { + file_io.initialize_shard(shard, state_id, &Default::default()).unwrap(); + } + + fn assert_latest_state_id( + snapshot_history: &SnapshotHistory, + shard: &ShardIdentifier, + state_id: StateId, + ) { + assert_eq!(snapshot_history.get(shard).unwrap().front().unwrap().state_id, state_id) + } + + fn create_test_fixtures(shards: &[ShardIdentifier]) -> (Arc, TestLoader) { + let file_io = Arc::new(TestFileIo::new(shards, Box::new(|x| *x), Box::new(|x| x))); + let state_initializer = Arc::new(TestStateInitializer::new(Default::default())); + let loader = StateSnapshotRepositoryLoader::new(file_io.clone(), state_initializer); + (file_io, loader) + } +} diff --git a/bitacross-worker/core-primitives/stf-state-handler/src/test/mocks/initialize_state_mock.rs b/bitacross-worker/core-primitives/stf-state-handler/src/test/mocks/initialize_state_mock.rs new file mode 100644 index 0000000000..32ed41e671 --- /dev/null +++ b/bitacross-worker/core-primitives/stf-state-handler/src/test/mocks/initialize_state_mock.rs @@ -0,0 +1,42 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{error::Result, state_initializer::InitializeState}; +use std::marker::PhantomData; + +/// Initialize state mock. +pub struct InitializeStateMock { + init_state: State, + _phantom: PhantomData, +} + +impl InitializeStateMock { + pub fn new(init_state: State) -> Self { + Self { init_state, _phantom: Default::default() } + } +} + +impl InitializeState for InitializeStateMock +where + State: Clone, +{ + type StateType = State; + + fn initialize(&self) -> Result { + Ok(self.init_state.clone()) + } +} diff --git a/bitacross-worker/core-primitives/stf-state-handler/src/test/mocks/mod.rs b/bitacross-worker/core-primitives/stf-state-handler/src/test/mocks/mod.rs new file mode 100644 index 0000000000..4a6fcfae26 --- /dev/null +++ b/bitacross-worker/core-primitives/stf-state-handler/src/test/mocks/mod.rs @@ -0,0 +1,20 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 initialize_state_mock; +pub mod state_key_repository_mock; +pub mod versioned_state_access_mock; diff --git a/bitacross-worker/core-primitives/stf-state-handler/src/test/mocks/state_key_repository_mock.rs b/bitacross-worker/core-primitives/stf-state-handler/src/test/mocks/state_key_repository_mock.rs new file mode 100644 index 0000000000..443877083d --- /dev/null +++ b/bitacross-worker/core-primitives/stf-state-handler/src/test/mocks/state_key_repository_mock.rs @@ -0,0 +1,68 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 = "sgx")] +use std::sync::SgxRwLock as RwLock; + +#[cfg(feature = "std")] +use std::sync::RwLock; + +use itp_sgx_crypto::{ + error::Result, + key_repository::{AccessKey, MutateKey}, + StateCrypto, +}; + +#[derive(Default)] +pub struct StateKeyRepositoryMock +where + KeyType: StateCrypto + Clone + Default, +{ + key: RwLock, +} + +impl StateKeyRepositoryMock +where + KeyType: StateCrypto + Clone + Default, +{ + #[cfg(all(feature = "test", feature = "sgx"))] + pub fn new(key: KeyType) -> Self { + StateKeyRepositoryMock { key: RwLock::new(key) } + } +} + +impl AccessKey for StateKeyRepositoryMock +where + KeyType: StateCrypto + Clone + Default, +{ + type KeyType = KeyType; + + fn retrieve_key(&self) -> Result { + Ok(self.key.read().unwrap().clone()) + } +} + +impl MutateKey for StateKeyRepositoryMock +where + KeyType: StateCrypto + Clone + Default, +{ + fn update_key(&self, key: KeyType) -> Result<()> { + let mut lock = self.key.write().unwrap(); + *lock = key; + Ok(()) + } +} diff --git a/bitacross-worker/core-primitives/stf-state-handler/src/test/mocks/versioned_state_access_mock.rs b/bitacross-worker/core-primitives/stf-state-handler/src/test/mocks/versioned_state_access_mock.rs new file mode 100644 index 0000000000..f6dee1730b --- /dev/null +++ b/bitacross-worker/core-primitives/stf-state-handler/src/test/mocks/versioned_state_access_mock.rs @@ -0,0 +1,102 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{ + error::{Error, Result}, + state_snapshot_repository::VersionedStateAccess, +}; +use itp_types::ShardIdentifier; +use std::{ + collections::{HashMap, VecDeque}, + marker::PhantomData, + string::ToString, + vec::Vec, +}; + +#[derive(Default, Clone)] +pub struct VersionedStateAccessMock { + state_history: HashMap>, + phantom_data: PhantomData, +} + +impl VersionedStateAccessMock { + #[cfg(test)] + pub fn new(state_history: HashMap>) -> Self { + VersionedStateAccessMock { state_history, phantom_data: Default::default() } + } +} + +impl VersionedStateAccess for VersionedStateAccessMock +where + State: Default + Clone, + Hash: Default, +{ + type StateType = State; + type HashType = Hash; + + fn load_latest(&self, shard_identifier: &ShardIdentifier) -> Result { + self.state_history + .get(shard_identifier) + .ok_or(Error::InvalidShard(*shard_identifier))? + .front() + .cloned() + .ok_or(Error::StateNotFoundInRepository("".to_string())) + } + + fn update( + &mut self, + shard_identifier: &ShardIdentifier, + state: &Self::StateType, + _state_hash: Self::HashType, + ) -> Result<()> { + let state_history = self + .state_history + .entry(*shard_identifier) + .or_insert_with(|| VecDeque::default()); + state_history.push_front(state.clone()); + Ok(()) + } + + fn revert_to( + &mut self, + shard_identifier: &ShardIdentifier, + _state_hash: &Self::HashType, + ) -> Result { + let state_history = self + .state_history + .get_mut(shard_identifier) + .ok_or_else(|| Error::InvalidShard(*shard_identifier))?; + state_history.drain(..).last().ok_or(Error::EmptyRepository) + } + + fn initialize_new_shard( + &mut self, + shard_identifier: ShardIdentifier, + state: &Self::StateType, + ) -> Result { + self.state_history.insert(shard_identifier, VecDeque::from([state.clone()])); + Ok(Hash::default()) + } + + fn shard_exists(&self, shard_identifier: &ShardIdentifier) -> bool { + self.state_history.get(shard_identifier).is_some() + } + + fn list_shards(&self) -> Result> { + Ok(self.state_history.keys().copied().collect()) + } +} diff --git a/bitacross-worker/core-primitives/stf-state-handler/src/test/mod.rs b/bitacross-worker/core-primitives/stf-state-handler/src/test/mod.rs new file mode 100644 index 0000000000..e3552cd37f --- /dev/null +++ b/bitacross-worker/core-primitives/stf-state-handler/src/test/mod.rs @@ -0,0 +1,25 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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)] +pub(crate) mod mocks; + +#[cfg(all(feature = "test", feature = "sgx"))] +pub mod mocks; + +#[cfg(all(feature = "test", feature = "sgx"))] +pub mod sgx_tests; diff --git a/bitacross-worker/core-primitives/stf-state-handler/src/test/sgx_tests.rs b/bitacross-worker/core-primitives/stf-state-handler/src/test/sgx_tests.rs new file mode 100644 index 0000000000..eef2da2b28 --- /dev/null +++ b/bitacross-worker/core-primitives/stf-state-handler/src/test/sgx_tests.rs @@ -0,0 +1,360 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{ + file_io::{sgx::SgxStateFileIo, StateDir, StateFileIo}, + handle_state::HandleState, + in_memory_state_file_io::sgx::create_in_memory_state_io_from_shards_directories, + query_shard_state::QueryShardState, + state_handler::StateHandler, + state_snapshot_repository::{StateSnapshotRepository, VersionedStateAccess}, + state_snapshot_repository_loader::StateSnapshotRepositoryLoader, + test::mocks::initialize_state_mock::InitializeStateMock, +}; +use codec::{Decode, Encode}; +use itp_hashing::Hash; +use itp_sgx_crypto::{ + get_aes_repository, + key_repository::{AccessKey, KeyRepository}, + Aes, AesSeal, StateCrypto, +}; +use itp_sgx_externalities::{SgxExternalities, SgxExternalitiesTrait, SgxExternalitiesType}; +use itp_sgx_io::write; +use itp_sgx_temp_dir::TempDir; +use itp_stf_state_observer::state_observer::StateObserver; +use itp_types::{ShardIdentifier, H256}; +use std::{sync::Arc, thread, vec::Vec}; + +const STATE_SNAPSHOTS_CACHE_SIZE: usize = 3; + +type StateKeyRepository = KeyRepository; +type TestStateInitializer = InitializeStateMock; +type TestStateFileIo = SgxStateFileIo; +type TestStateRepository = StateSnapshotRepository; +type TestStateRepositoryLoader = + StateSnapshotRepositoryLoader; +type TestStateObserver = StateObserver; +type TestStateHandler = StateHandler; + +// Fixme: Move this test to sgx-runtime: +// +// https://github.com/integritee-network/sgx-runtime/issues/23 +pub fn test_sgx_state_decode_encode_works() { + // given + let state = given_hello_world_state(); + + // when + let encoded_state = state.state.encode(); + let state2 = SgxExternalitiesType::decode(&mut encoded_state.as_slice()).unwrap(); + + // then + assert_eq!(state.state, state2); +} + +pub fn test_encrypt_decrypt_state_type_works() { + // given + let state = given_hello_world_state(); + let temp_dir = TempDir::with_prefix("test_encrypt_decrypt_state_type_works").unwrap(); + let state_key = get_aes_repository(temp_dir.path().to_path_buf()) + .unwrap() + .retrieve_key() + .unwrap(); + + // when + let mut state_buffer = state.state.encode(); + state_key.encrypt(&mut state_buffer).unwrap(); + + state_key.decrypt(&mut state_buffer).unwrap(); + let decoded = SgxExternalitiesType::decode(&mut state_buffer.as_slice()).unwrap(); + + // then + assert_eq!(state.state, decoded); +} + +pub fn test_write_and_load_state_works() { + // given + let shard: ShardIdentifier = [94u8; 32].into(); + let (_temp_dir, state_key_access, state_dir) = + test_setup("test_write_and_load_state_works", &shard); + + let state_handler = initialize_state_handler(state_key_access, state_dir); + + let state = given_hello_world_state(); + + // when + let (lock, _s) = state_handler.load_for_mutation(&shard).unwrap(); + let _hash = state_handler.write_after_mutation(state.clone(), lock, &shard).unwrap(); + + let (result_state, _) = state_handler.load_cloned(&shard).unwrap(); + + // then + assert_eq!(state.state, result_state.state); +} + +pub fn test_ensure_subsequent_state_loads_have_same_hash() { + // given + let shard: ShardIdentifier = [49u8; 32].into(); + let (_temp_dir, state_key_access, state_dir) = + test_setup("test_ensure_subsequent_state_loads_have_same_hash", &shard); + + let state_handler = initialize_state_handler(state_key_access, state_dir); + + let (lock, initial_state) = state_handler.load_for_mutation(&shard).unwrap(); + state_handler.write_after_mutation(initial_state.clone(), lock, &shard).unwrap(); + + let (_, loaded_state_hash) = state_handler.load_cloned(&shard).unwrap(); + + assert_eq!(initial_state.hash(), loaded_state_hash); +} + +pub fn test_write_access_locks_read_until_finished() { + // here we want to test that a lock we obtain for + // mutating state locks out any read attempt that happens during that time + + // given + let shard: ShardIdentifier = [47u8; 32].into(); + let (_temp_dir, state_key_access, state_dir) = + test_setup("test_write_access_locks_read_until_finished", &shard); + + let state_handler = initialize_state_handler(state_key_access, state_dir); + + let new_state_key = "my_new_state".encode(); + let (lock, mut state_to_mutate) = state_handler.load_for_mutation(&shard).unwrap(); + + // spawn a new thread that reads state + // this thread should be blocked until the write lock is released, i.e. until + // the new state is written. We can verify this, by trying to read that state variable + // that will be inserted further down below + let new_state_key_for_read = new_state_key.clone(); + let state_handler_clone = state_handler.clone(); + let shard_for_read = shard.clone(); + let join_handle = thread::spawn(move || { + let (state_to_read, _) = state_handler_clone.load_cloned(&shard_for_read).unwrap(); + assert!(state_to_read.get(new_state_key_for_read.as_slice()).is_some()); + }); + + assert!(state_to_mutate.get(new_state_key.clone().as_slice()).is_none()); + state_to_mutate.insert(new_state_key, "mega_secret_value".encode()); + + let _hash = state_handler.write_after_mutation(state_to_mutate, lock, &shard).unwrap(); + + join_handle.join().unwrap(); +} + +pub fn test_state_handler_file_backend_is_initialized() { + let shard: ShardIdentifier = [11u8; 32].into(); + let (_temp_dir, state_key_access, state_dir) = + test_setup("test_state_handler_file_backend_is_initialized", &shard); + + let state_handler = initialize_state_handler(state_key_access, state_dir.clone()); + + assert!(state_handler.shard_exists(&shard).unwrap()); + assert!(1 <= state_handler.list_shards().unwrap().len()); // only greater equal, because there might be other (non-test) shards present + assert_eq!(1, state_dir.list_state_ids_for_shard(&shard).unwrap().len()); // creates a first initialized file + + let _state = state_handler.load_cloned(&shard).unwrap(); + + assert_eq!(1, state_dir.list_state_ids_for_shard(&shard).unwrap().len()); +} + +pub fn test_multiple_state_updates_create_snapshots_up_to_cache_size() { + let shard: ShardIdentifier = [17u8; 32].into(); + let (_temp_dir, state_key_access, state_dir) = + test_setup("test_state_handler_file_backend_is_initialized", &shard); + + let state_handler = initialize_state_handler(state_key_access, state_dir.clone()); + + assert_eq!(1, state_dir.list_state_ids_for_shard(&shard).unwrap().len()); + + let hash_1 = update_state( + state_handler.as_ref(), + &shard, + ("my_key_1".encode(), "mega_secret_value".encode()), + ); + assert_eq!(2, state_dir.list_state_ids_for_shard(&shard).unwrap().len()); + + let hash_2 = update_state( + state_handler.as_ref(), + &shard, + ("my_key_2".encode(), "mega_secret_value222".encode()), + ); + assert_eq!(3, state_dir.list_state_ids_for_shard(&shard).unwrap().len()); + + let hash_3 = update_state( + state_handler.as_ref(), + &shard, + ("my_key_3".encode(), "mega_secret_value3".encode()), + ); + assert_eq!(3, state_dir.list_state_ids_for_shard(&shard).unwrap().len()); + + let hash_4 = update_state( + state_handler.as_ref(), + &shard, + ("my_key_3".encode(), "mega_secret_valuenot3".encode()), + ); + assert_eq!(3, state_dir.list_state_ids_for_shard(&shard).unwrap().len()); + + assert_ne!(hash_1, hash_2); + assert_ne!(hash_1, hash_3); + assert_ne!(hash_1, hash_4); + assert_ne!(hash_2, hash_3); + assert_ne!(hash_2, hash_4); + assert_ne!(hash_3, hash_4); + + assert_eq!( + STATE_SNAPSHOTS_CACHE_SIZE, + state_dir.list_state_ids_for_shard(&shard).unwrap().len() + ); +} + +pub fn test_file_io_get_state_hash_works() { + let shard: ShardIdentifier = [21u8; 32].into(); + let (_temp_dir, state_key_access, state_dir) = + test_setup("test_file_io_get_state_hash_works", &shard); + + let file_io = TestStateFileIo::new(state_key_access, state_dir); + + let state_id = 1234u128; + let state_hash = file_io + .initialize_shard(&shard, state_id, &SgxExternalities::new(Default::default())) + .unwrap(); + assert_eq!(state_hash, file_io.compute_hash(&shard, state_id).unwrap()); + + let state_hash = file_io.write(&shard, state_id, &given_hello_world_state()).unwrap(); + assert_eq!(state_hash, file_io.compute_hash(&shard, state_id).unwrap()); +} + +pub fn test_state_files_from_handler_can_be_loaded_again() { + let shard: ShardIdentifier = [15u8; 32].into(); + let (_temp_dir, state_key_access, state_dir) = + test_setup("test_state_files_from_handler_can_be_loaded_again", &shard); + + let state_handler = initialize_state_handler(state_key_access.clone(), state_dir.clone()); + + update_state(state_handler.as_ref(), &shard, ("test_key_1".encode(), "value1".encode())); + update_state(state_handler.as_ref(), &shard, ("test_key_2".encode(), "value2".encode())); + update_state( + state_handler.as_ref(), + &shard, + ("test_key_2".encode(), "value2_updated".encode()), + ); + update_state(state_handler.as_ref(), &shard, ("test_key_3".encode(), "value3".encode())); + + // We initialize another state handler to load the state from the changes we just made. + let updated_state_handler = initialize_state_handler(state_key_access, state_dir.clone()); + + assert_eq!( + STATE_SNAPSHOTS_CACHE_SIZE, + state_dir.list_state_ids_for_shard(&shard).unwrap().len() + ); + assert_eq!( + &"value3".encode(), + updated_state_handler + .load_cloned(&shard) + .unwrap() + .0 + .state() + .get("test_key_3".encode().as_slice()) + .unwrap() + ); +} + +pub fn test_list_state_ids_ignores_files_not_matching_the_pattern() { + let shard: ShardIdentifier = [21u8; 32].into(); + let (_temp_dir, state_key_access, state_dir) = + test_setup("test_list_state_ids_ignores_files_not_matching_the_pattern", &shard); + + let file_io = TestStateFileIo::new(state_key_access, state_dir.clone()); + + let invalid_state_file_path = state_dir.shard_path(&shard).join("invalid-state.bin"); + write(&[0, 1, 2, 3, 4, 5], invalid_state_file_path).unwrap(); + + file_io + .initialize_shard(&shard, 1234, &SgxExternalities::new(Default::default())) + .unwrap(); + + assert_eq!(1, file_io.list_state_ids_for_shard(&shard).unwrap().len()); +} + +pub fn test_in_memory_state_initializes_from_shard_directory() { + let shard: ShardIdentifier = [45u8; 32].into(); + let (_temp_dir, _, state_dir) = + test_setup("test_list_state_ids_ignores_files_not_matching_the_pattern", &shard); + + let file_io = + create_in_memory_state_io_from_shards_directories(&state_dir.shards_directory()).unwrap(); + let state_initializer = + Arc::new(TestStateInitializer::new(SgxExternalities::new(Default::default()))); + let state_repository_loader = + StateSnapshotRepositoryLoader::new(file_io.clone(), state_initializer); + let state_snapshot_repository = state_repository_loader + .load_snapshot_repository(STATE_SNAPSHOTS_CACHE_SIZE) + .unwrap(); + + assert_eq!(1, file_io.get_states_for_shard(&shard).unwrap().len()); + assert!(state_snapshot_repository.shard_exists(&shard)); +} + +fn initialize_state_handler( + state_key_access: Arc, + state_dir: StateDir, +) -> Arc { + let file_io = Arc::new(TestStateFileIo::new(state_key_access, state_dir)); + let state_initializer = + Arc::new(TestStateInitializer::new(SgxExternalities::new(Default::default()))); + let state_repository_loader = + TestStateRepositoryLoader::new(file_io, state_initializer.clone()); + let state_observer = Arc::new(TestStateObserver::default()); + let state_snapshot_repository = state_repository_loader + .load_snapshot_repository(STATE_SNAPSHOTS_CACHE_SIZE) + .unwrap(); + Arc::new( + TestStateHandler::load_from_repository( + state_snapshot_repository, + state_observer, + state_initializer, + ) + .unwrap(), + ) +} + +fn update_state( + state_handler: &TestStateHandler, + shard: &ShardIdentifier, + kv_pair: (Vec, Vec), +) -> H256 { + let (lock, mut state_to_mutate) = state_handler.load_for_mutation(shard).unwrap(); + state_to_mutate.insert(kv_pair.0, kv_pair.1); + state_handler.write_after_mutation(state_to_mutate, lock, shard).unwrap() +} + +fn given_hello_world_state() -> SgxExternalities { + let key: Vec = "hello".encode(); + let value: Vec = "world".encode(); + let mut state = SgxExternalities::new(Default::default()); + state.insert(key, value); + state +} + +fn test_setup(id: &str, shard: &ShardIdentifier) -> (TempDir, Arc, StateDir) { + let temp_dir = TempDir::with_prefix(id).unwrap(); + let state_key_access = Arc::new(get_aes_repository(temp_dir.path().to_path_buf()).unwrap()); + let state_dir = StateDir::new(temp_dir.path().to_path_buf()); + state_dir.given_initialized_shard(shard); + + (temp_dir, state_key_access, state_dir) +} diff --git a/bitacross-worker/core-primitives/stf-state-observer/Cargo.toml b/bitacross-worker/core-primitives/stf-state-observer/Cargo.toml new file mode 100644 index 0000000000..d2c0016793 --- /dev/null +++ b/bitacross-worker/core-primitives/stf-state-observer/Cargo.toml @@ -0,0 +1,31 @@ +[package] +name = "itp-stf-state-observer" +version = "0.9.0" +authors = ['Trust Computing GmbH ', 'Integritee AG '] +edition = "2021" + +[dependencies] +sgx_tstd = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git", optional = true } + +# local deps +itp-types = { default-features = false, path = "../types" } + +# sgx enabled external libraries +thiserror_sgx = { package = "thiserror", git = "https://github.com/mesalock-linux/thiserror-sgx", tag = "sgx_1.1.3", optional = true } + +# std compatible external libraries (make sure these versions match with the sgx-enabled ones above) +log = { version = "0.4", default-features = false } +thiserror = { version = "1.0", optional = true } + +[features] +default = ["std"] +std = [ + "itp-types/std", + "log/std", + "thiserror", +] +sgx = [ + "sgx_tstd", + "thiserror_sgx", +] +mocks = [] diff --git a/bitacross-worker/core-primitives/stf-state-observer/src/error.rs b/bitacross-worker/core-primitives/stf-state-observer/src/error.rs new file mode 100644 index 0000000000..914552fb86 --- /dev/null +++ b/bitacross-worker/core-primitives/stf-state-observer/src/error.rs @@ -0,0 +1,34 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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(all(not(feature = "std"), feature = "sgx"))] +use crate::sgx_reexport_prelude::*; + +pub type Result = core::result::Result; + +use std::boxed::Box; + +/// State Observer Error. +#[derive(Debug, thiserror::Error)] +pub enum Error { + #[error("Current state is empty (not set)")] + CurrentStateEmpty, + #[error("Could not acquire lock, lock is poisoned")] + LockPoisoning, + #[error(transparent)] + Other(#[from] Box), +} diff --git a/bitacross-worker/core-primitives/stf-state-observer/src/lib.rs b/bitacross-worker/core-primitives/stf-state-observer/src/lib.rs new file mode 100644 index 0000000000..5da2bbbed9 --- /dev/null +++ b/bitacross-worker/core-primitives/stf-state-observer/src/lib.rs @@ -0,0 +1,38 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +#![cfg_attr(not(feature = "std"), no_std)] +#![cfg_attr(test, feature(assert_matches))] + +#[cfg(all(feature = "std", feature = "sgx"))] +compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the same time"); + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +extern crate sgx_tstd as std; + +// Re-export module to properly feature gate sgx and regular std environment. +#[cfg(all(not(feature = "std"), feature = "sgx"))] +pub mod sgx_reexport_prelude { + pub use thiserror_sgx as thiserror; +} + +pub mod error; +pub mod state_observer; +pub mod traits; + +#[cfg(feature = "mocks")] +pub mod mock; diff --git a/bitacross-worker/core-primitives/stf-state-observer/src/mock.rs b/bitacross-worker/core-primitives/stf-state-observer/src/mock.rs new file mode 100644 index 0000000000..335adf7b91 --- /dev/null +++ b/bitacross-worker/core-primitives/stf-state-observer/src/mock.rs @@ -0,0 +1,79 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 = "sgx")] +use std::sync::SgxRwLock as RwLock; + +#[cfg(feature = "std")] +use std::sync::RwLock; + +use crate::{ + error::{Error, Result}, + traits::{ObserveState, UpdateState}, +}; +use core::fmt::Debug; +use itp_types::ShardIdentifier; +use log::*; +use std::vec::Vec; + +/// Observe state mock. +#[derive(Default)] +pub struct ObserveStateMock { + state: RwLock>, +} + +impl ObserveStateMock { + pub fn new(state: StateType) -> Self { + Self { state: RwLock::new(Some(state)) } + } +} + +impl ObserveState for ObserveStateMock +where + StateType: Debug, +{ + type StateType = StateType; + + fn observe_state(&self, _shard: &ShardIdentifier, observation_func: F) -> Result + where + F: FnOnce(&mut Self::StateType) -> R, + { + let mut maybe_state_lock = self.state.write().unwrap(); + + match &mut *maybe_state_lock { + Some(state) => { + debug!("State value: {:?}", state); + Ok(observation_func(state)) + }, + None => Err(Error::CurrentStateEmpty), + } + } +} + +/// Update state mock. +#[derive(Default)] +pub struct UpdateStateMock { + pub queued_updates: RwLock>, +} + +impl UpdateState for UpdateStateMock { + fn queue_state_update(&self, shard: ShardIdentifier, state: StateType) -> Result<()> { + let mut updates_lock = self.queued_updates.write().unwrap(); + updates_lock.push((shard, state)); + Ok(()) + } +} diff --git a/bitacross-worker/core-primitives/stf-state-observer/src/state_observer.rs b/bitacross-worker/core-primitives/stf-state-observer/src/state_observer.rs new file mode 100644 index 0000000000..21c8042ac0 --- /dev/null +++ b/bitacross-worker/core-primitives/stf-state-observer/src/state_observer.rs @@ -0,0 +1,148 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 = "sgx")] +use std::sync::SgxRwLock as RwLock; + +#[cfg(feature = "std")] +use std::sync::RwLock; + +use crate::{ + error::{Error, Result}, + traits::{ObserveState, UpdateState}, +}; +use itp_types::ShardIdentifier; +use std::{collections::HashMap, vec::Vec}; + +/// State observer implementation. Receives updates in a dedicated queue. +/// These updates are applied every time an observation function is executed. +/// +#[derive(Default)] +pub struct StateObserver { + queued_state_updates: RwLock>, + current_state: RwLock>, +} + +impl StateObserver { + pub fn new(shard: ShardIdentifier, state: StateType) -> Self { + Self { + queued_state_updates: Default::default(), + current_state: RwLock::new(HashMap::from([(shard, state)])), + } + } + + pub fn from_map(states_map: HashMap) -> Self { + Self { queued_state_updates: Default::default(), current_state: RwLock::new(states_map) } + } + + fn apply_pending_update(&self) -> Result<()> { + let mut update_queue_lock = + self.queued_state_updates.write().map_err(|_| Error::LockPoisoning)?; + + let state_updates: Vec<_> = update_queue_lock.drain().collect(); + drop(update_queue_lock); + + if !state_updates.is_empty() { + let mut current_state_lock = + self.current_state.write().map_err(|_| Error::LockPoisoning)?; + for state_update in state_updates.into_iter() { + current_state_lock.insert(state_update.0, state_update.1); + } + drop(current_state_lock); + } + + Ok(()) + } +} + +impl ObserveState for StateObserver { + type StateType = StateType; + + fn observe_state(&self, shard: &ShardIdentifier, observation_func: F) -> Result + where + F: FnOnce(&mut Self::StateType) -> R, + { + // Check if there is a pending update and apply it. + self.apply_pending_update()?; + + // Execute the observation function. + let mut current_state_map_lock = + self.current_state.write().map_err(|_| Error::LockPoisoning)?; + + match current_state_map_lock.get_mut(shard) { + Some(s) => Ok(observation_func(s)), + None => Err(Error::CurrentStateEmpty), + } + } +} + +impl UpdateState for StateObserver { + fn queue_state_update(&self, shard: ShardIdentifier, state: StateType) -> Result<()> { + let mut update_queue_lock = + self.queued_state_updates.write().map_err(|_| Error::LockPoisoning)?; + update_queue_lock.insert(shard, state); + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use core::assert_matches::assert_matches; + + type TestState = u64; + + #[test] + fn default_constructs_empty_state() { + let state_observer = StateObserver::::default(); + + assert_matches!( + state_observer.observe_state(&shard(), |_| { () }), + Err(Error::CurrentStateEmpty) + ); + } + + #[test] + fn initializing_state_with_some_works() { + let state_observer = StateObserver::::new(shard(), 31u64); + assert_eq!(state_observer.observe_state(&shard(), |s| *s).unwrap(), 31u64); + } + + #[test] + fn observing_multiple_times_after_update_works() { + let state_observer = StateObserver::::default(); + + state_observer.queue_state_update(shard(), 42u64).unwrap(); + + assert_eq!(state_observer.observe_state(&shard(), |s| *s).unwrap(), 42u64); + assert_eq!(state_observer.observe_state(&shard(), |s| *s).unwrap(), 42u64); + assert_eq!(state_observer.observe_state(&shard(), |s| *s).unwrap(), 42u64); + } + + #[test] + fn updating_multiple_times_before_observation_just_keeps_last_value() { + let state_observer = StateObserver::::new(shard(), 31); + state_observer.queue_state_update(shard(), 42u64).unwrap(); + state_observer.queue_state_update(shard(), 57u64).unwrap(); + assert_eq!(1, state_observer.queued_state_updates.read().unwrap().len()); + assert_eq!(state_observer.observe_state(&shard(), |s| *s).unwrap(), 57u64); + } + + fn shard() -> ShardIdentifier { + ShardIdentifier::default() + } +} diff --git a/bitacross-worker/core-primitives/stf-state-observer/src/traits.rs b/bitacross-worker/core-primitives/stf-state-observer/src/traits.rs new file mode 100644 index 0000000000..617e50dab4 --- /dev/null +++ b/bitacross-worker/core-primitives/stf-state-observer/src/traits.rs @@ -0,0 +1,37 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::error::Result; +use itp_types::ShardIdentifier; + +/// Observe state trait. +pub trait ObserveState { + type StateType; + + /// Requires a &mut StateType because the externalities are always executed with a mutable reference. + /// Underneath it all, the environmental!() macro only knows mutable access unfortunately. + /// And since the sp-io interface is fixed and relies on the global instance created by environmental!(), + /// it forces &mut access upon us here, even though read-only access would be enough. + fn observe_state(&self, shard: &ShardIdentifier, observation_func: F) -> Result + where + F: FnOnce(&mut Self::StateType) -> R; +} + +/// Trait to queue a state update for an observer. +pub trait UpdateState { + fn queue_state_update(&self, shard: ShardIdentifier, state: StateType) -> Result<()>; +} diff --git a/bitacross-worker/core-primitives/storage/Cargo.toml b/bitacross-worker/core-primitives/storage/Cargo.toml new file mode 100644 index 0000000000..fb60cd1fa1 --- /dev/null +++ b/bitacross-worker/core-primitives/storage/Cargo.toml @@ -0,0 +1,49 @@ +[package] +name = "itp-storage" +version = "0.9.0" +authors = ['Trust Computing GmbH ', 'Integritee AG '] +edition = "2021" + +[dependencies] +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["chain-error"] } +derive_more = { version = "0.99.5" } +frame-metadata = { version = "15.1.0", features = ["v14"], default-features = false } +hash-db = { version = "0.15.2", default-features = false } +thiserror = { version = "1.0.26", optional = true } + +# sgx deps +sgx_tstd = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git", optional = true } +thiserror-sgx = { package = "thiserror", git = "https://github.com/mesalock-linux/thiserror-sgx", tag = "sgx_1.1.3", optional = true } + +# substrate deps +frame-support = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } +sp-core = { default-features = false, features = ["full_crypto"], git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } +sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } +sp-std = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } +sp-trie = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } + +# integritee +itp-types = { default-features = false, path = "../types" } + +[dev-dependencies] +sp-state-machine = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } + +[features] +default = ["std"] +std = [ + "codec/std", + "frame-metadata/std", + "frame-support/std", + "hash-db/std", + "itp-types/std", + "sp-core/std", + "sp-runtime/std", + "sp-std/std", + "sp-trie/std", + "thiserror", +] +sgx = [ + "sgx_tstd", + "thiserror-sgx", +] +test = [] diff --git a/bitacross-worker/core-primitives/storage/src/error.rs b/bitacross-worker/core-primitives/storage/src/error.rs new file mode 100644 index 0000000000..9b859bfb8f --- /dev/null +++ b/bitacross-worker/core-primitives/storage/src/error.rs @@ -0,0 +1,43 @@ +#[cfg(all(not(feature = "std"), feature = "sgx"))] +use thiserror_sgx as thiserror; + +// error with std::error::Error implemented for std and sgx +#[derive(Debug, PartialEq, Eq, thiserror::Error)] +#[cfg(any(feature = "std", feature = "sgx"))] +pub enum Error { + #[error("No storage proof supplied")] + NoProofSupplied, + #[error("Supplied storage value does not match the value from the proof")] + WrongValue, + #[error("Invalid storage proof: StorageRootMismatch")] + StorageRootMismatch, + #[error("Storage value unavailable")] + StorageValueUnavailable, + #[error(transparent)] + #[cfg(feature = "std")] + Codec(#[from] codec::Error), + + // as `codec::Error` does not implement `std::error::Error` in `no-std`, + // we can't use the `#[from]` attribute. + #[error("Codec: {0}")] + #[cfg(not(feature = "std"))] + Codec(codec::Error), +} + +// error for bare `no_std`, which does not implement `std::error::Error` + +#[cfg(all(not(feature = "std"), not(feature = "sgx")))] +use derive_more::{Display, From}; + +// Simple error enum for no_std without std::error::Error implemented +#[derive(Debug, Display, PartialEq, Eq, From)] +#[cfg(all(not(feature = "std"), not(feature = "sgx")))] +pub enum Error { + NoProofSupplied, + /// Supplied storage value does not match the value from the proof + WrongValue, + /// InvalidStorageProof, + StorageRootMismatch, + StorageValueUnavailable, + Codec(codec::Error), +} diff --git a/bitacross-worker/core-primitives/storage/src/keys.rs b/bitacross-worker/core-primitives/storage/src/keys.rs new file mode 100644 index 0000000000..43de4f667e --- /dev/null +++ b/bitacross-worker/core-primitives/storage/src/keys.rs @@ -0,0 +1,71 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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; +use frame_metadata::v14::StorageHasher; +use sp_std::vec::Vec; + +pub fn storage_value_key(module_prefix: &str, storage_prefix: &str) -> Vec { + let mut bytes = sp_core::twox_128(module_prefix.as_bytes()).to_vec(); + bytes.extend(&sp_core::twox_128(storage_prefix.as_bytes())[..]); + bytes +} + +pub fn storage_map_key( + module_prefix: &str, + storage_prefix: &str, + mapkey1: &K, + hasher1: &StorageHasher, +) -> Vec { + let mut bytes = sp_core::twox_128(module_prefix.as_bytes()).to_vec(); + bytes.extend(&sp_core::twox_128(storage_prefix.as_bytes())[..]); + bytes.extend(key_hash(mapkey1, hasher1)); + bytes +} + +pub fn storage_double_map_key( + module_prefix: &str, + storage_prefix: &str, + mapkey1: &K, + hasher1: &StorageHasher, + mapkey2: &Q, + hasher2: &StorageHasher, +) -> Vec { + let mut bytes = sp_core::twox_128(module_prefix.as_bytes()).to_vec(); + bytes.extend(&sp_core::twox_128(storage_prefix.as_bytes())[..]); + bytes.extend(key_hash(mapkey1, hasher1)); + bytes.extend(key_hash(mapkey2, hasher2)); + bytes +} + +/// generates the key's hash depending on the StorageHasher selected +fn key_hash(key: &K, hasher: &StorageHasher) -> Vec { + let encoded_key = key.encode(); + match hasher { + StorageHasher::Identity => encoded_key.to_vec(), + StorageHasher::Blake2_128 => sp_core::blake2_128(&encoded_key).to_vec(), + StorageHasher::Blake2_128Concat => { + // copied from substrate Blake2_128Concat::hash since StorageHasher is not public + let x: &[u8] = encoded_key.as_slice(); + sp_core::blake2_128(x).iter().chain(x.iter()).cloned().collect::>() + }, + StorageHasher::Blake2_256 => sp_core::blake2_256(&encoded_key).to_vec(), + StorageHasher::Twox128 => sp_core::twox_128(&encoded_key).to_vec(), + StorageHasher::Twox256 => sp_core::twox_256(&encoded_key).to_vec(), + StorageHasher::Twox64Concat => sp_core::twox_64(&encoded_key).to_vec(), + } +} diff --git a/bitacross-worker/core-primitives/storage/src/lib.rs b/bitacross-worker/core-primitives/storage/src/lib.rs new file mode 100644 index 0000000000..3a3b6f2a6d --- /dev/null +++ b/bitacross-worker/core-primitives/storage/src/lib.rs @@ -0,0 +1,35 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg(all(feature = "std", feature = "sgx"))] +compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the same time"); + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +extern crate sgx_tstd as std; + +pub use error::Error; +pub use frame_metadata::v14::StorageHasher; +pub use keys::*; +pub use proof::*; +pub use verify_storage_proof::*; + +pub mod error; +pub mod keys; +pub mod proof; +pub mod verify_storage_proof; diff --git a/bitacross-worker/core-primitives/storage/src/proof.rs b/bitacross-worker/core-primitives/storage/src/proof.rs new file mode 100644 index 0000000000..6b2c02c49f --- /dev/null +++ b/bitacross-worker/core-primitives/storage/src/proof.rs @@ -0,0 +1,121 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +//! Logic for checking Substrate storage proofs. + +use crate::error::Error; +use hash_db::EMPTY_PREFIX; +use sp_core::Hasher; +use sp_std::vec::Vec; +use sp_trie::{trie_types::TrieDB, HashDBT, MemoryDB, Trie, TrieDBBuilder}; + +pub type StorageProof = Vec>; + +/// This struct is used to read storage values from a subset of a Merklized database. The "proof" +/// is a subset of the nodes in the Merkle structure of the database, so that it provides +/// authentication against a known Merkle root as well as the values in the database themselves. +pub struct StorageProofChecker { + root: H::Out, + db: MemoryDB, +} + +impl StorageProofChecker { + /// Constructs a new storage proof checker. + /// + /// This returns an error if the given proof is invalid with respect to the given root. + pub fn new(root: H::Out, proof: StorageProof) -> Result { + let mut db = MemoryDB::default(); + for item in proof { + db.insert(EMPTY_PREFIX, &item); + } + let checker = StorageProofChecker { root, db }; + // Return error if trie would be invalid. + let _ = checker.trie()?; + Ok(checker) + } + + /// Reads a value from the available subset of storage. If the value cannot be read due to an + /// incomplete or otherwise invalid proof, this returns an error. + pub fn read_value(&self, key: &[u8]) -> Result>, Error> { + self.trie()? + .get(key) + .map(|value| value.map(|value| value.to_vec())) + .map_err(|_| Error::StorageValueUnavailable) + } + + fn trie(&self) -> Result, Error> { + if !self.db.contains(&self.root, EMPTY_PREFIX) { + Err(Error::StorageRootMismatch) + } else { + Ok(TrieDBBuilder::new(&self.db, &self.root).build()) + } + } + + pub fn check_proof( + root: H::Out, + storage_key: &[u8], + proof: StorageProof, + ) -> Result>, Error> { + let storage_checker = StorageProofChecker::::new(root, proof)?; + + storage_checker.read_value(storage_key) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + use sp_core::{Blake2Hasher, H256}; + use sp_state_machine::{backend::Backend, new_in_mem, prove_read}; + use sp_trie::HashKey; + + #[test] + fn storage_proof_check() { + // construct storage proof + let mut backend = new_in_mem::>(); + backend.insert( + vec![ + (None, vec![(b"key1".to_vec(), Some(b"value1".to_vec()))]), + (None, vec![(b"key2".to_vec(), Some(b"value2".to_vec()))]), + (None, vec![(b"key3".to_vec(), Some(b"value3".to_vec()))]), + // Value is too big to fit in a branch node + (None, vec![(b"key11".to_vec(), Some(vec![0u8; 32]))]), + ], + Default::default(), + ); + let root = backend.storage_root(std::iter::empty(), Default::default()).0; + let proof: StorageProof = prove_read(backend, &[&b"key1"[..], &b"key2"[..], &b"key22"[..]]) + .unwrap() + .iter_nodes() + .cloned() + .collect(); + + // check proof in runtime + let checker = >::new(root, proof.clone()).unwrap(); + assert_eq!(checker.read_value(b"key1"), Ok(Some(b"value1".to_vec()))); + assert_eq!(checker.read_value(b"key2"), Ok(Some(b"value2".to_vec()))); + assert_eq!(checker.read_value(b"key11111"), Err(Error::StorageValueUnavailable)); + assert_eq!(checker.read_value(b"key22"), Ok(None)); + + // checking proof against invalid commitment fails + assert_eq!( + >::new(H256::random(), proof).err(), + Some(Error::StorageRootMismatch) + ); + } +} diff --git a/bitacross-worker/core-primitives/storage/src/verify_storage_proof.rs b/bitacross-worker/core-primitives/storage/src/verify_storage_proof.rs new file mode 100644 index 0000000000..fab9fda455 --- /dev/null +++ b/bitacross-worker/core-primitives/storage/src/verify_storage_proof.rs @@ -0,0 +1,67 @@ +use crate::{error::Error, StorageProofChecker}; +use codec::Decode; +use frame_support::ensure; +use itp_types::storage::{StorageEntry, StorageEntryVerified}; +use sp_runtime::traits::Header as HeaderT; +use sp_std::prelude::Vec; + +pub trait VerifyStorageProof { + fn verify_storage_proof( + self, + header: &Header, + ) -> Result, Error>; +} + +impl VerifyStorageProof for StorageEntry> { + fn verify_storage_proof( + self, + header: &Header, + ) -> Result, Error> { + let proof = self.proof.as_ref().ok_or(Error::NoProofSupplied)?; + let actual = StorageProofChecker::<
::Hashing>::check_proof( + *header.state_root(), + &self.key, + proof.to_vec(), + )?; + + // Todo: Why do they do it like that, we could supply the proof only and get the value from the proof directly?? + ensure!(actual == self.value, Error::WrongValue); + + Ok(StorageEntryVerified { + key: self.key, + value: self + .value + .map(|v| Decode::decode(&mut v.as_slice())) + .transpose() + .map_err(Error::Codec)?, + }) + } +} + +/// Verify a set of storage entries +pub fn verify_storage_entries( + entries: impl IntoIterator, + header: &Header, +) -> Result>, Error> +where + S: Into>>, + Header: HeaderT, + V: Decode, +{ + let iter = into_storage_entry_iter(entries); + let mut verified_entries = Vec::with_capacity(iter.size_hint().0); + + for e in iter { + verified_entries.push(e.verify_storage_proof(header)?); + } + Ok(verified_entries) +} + +pub fn into_storage_entry_iter<'a, S>( + source: impl IntoIterator + 'a, +) -> impl Iterator>> + 'a +where + S: Into>>, +{ + source.into_iter().map(|s| s.into()) +} diff --git a/bitacross-worker/core-primitives/substrate-sgx/environmental/Cargo.toml b/bitacross-worker/core-primitives/substrate-sgx/environmental/Cargo.toml new file mode 100644 index 0000000000..354aa878a6 --- /dev/null +++ b/bitacross-worker/core-primitives/substrate-sgx/environmental/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "environmental" +description = "Set scope-limited values can can be accessed statically" +version = "1.1.3" +authors = ["Parity Technologies "] +license = "Apache-2.0" +edition = "2021" + +[dependencies] +sgx_tstd = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git", optional = true, features = ["thread"] } + +[features] +default = ["std"] +std = [] +sgx = ["sgx_tstd"] diff --git a/bitacross-worker/core-primitives/substrate-sgx/environmental/src/lib.rs b/bitacross-worker/core-primitives/substrate-sgx/environmental/src/lib.rs new file mode 100644 index 0000000000..7671299615 --- /dev/null +++ b/bitacross-worker/core-primitives/substrate-sgx/environmental/src/lib.rs @@ -0,0 +1,479 @@ +// Copyright 2017-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. + +//! Safe global references to stack variables. +//! +//! Set up a global reference with environmental! macro giving it a name and type. +//! Use the `using` function scoped under its name to name a reference and call a function that +//! takes no parameters yet can access said reference through the similarly placed `with` function. +//! +//! # Examples +//! +//! ``` +//! #[macro_use] extern crate environmental; +//! // create a place for the global reference to exist. +//! environmental!(counter: u32); +//! fn stuff() { +//! // do some stuff, accessing the named reference as desired. +//! counter::with(|i| *i += 1); +//! } +//! fn main() { +//! // declare a stack variable of the same type as our global declaration. +//! let mut counter_value = 41u32; +//! // call stuff, setting up our `counter` environment as a reference to our counter_value var. +//! counter::using(&mut counter_value, stuff); +//! println!("The answer is {:?}", counter_value); // will print 42! +//! stuff(); // safe! doesn't do anything. +//! } +//! ``` +//! +//! Original crate: https://github.com/paritytech/environmental/blob/master/src/lib.rs +//! The original crate does not support multithreading in `no_std` mode, see https://github.com/integritee-network/worker/issues/803. +//! Therefore, this crate introduces the sgx feature, which allows multithreading within an sgx enabled environment. +//! It should be ensured that all uses of the environmental crate within the enclave are making use of this crate, not the original one. +//! +//! Attention: The `sp-runtime-interface` still points to the original environmental crate. It can't be easily patched due +//! to this crate not being `no_std` compatible. (See https://github.com/integritee-network/worker/pull/938#discussion_r952412587). +//! However, because `sp-runtime-interface` only uses environmental in `std` mode, it should be safe to leave as is. +//! Nonetheless, it should be kept in mind that this may cause a problem in the future. + +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg(all(feature = "std", feature = "sgx"))] +compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the same time"); + +#[cfg(all(not(feature = "std"), not(feature = "sgx")))] +compile_error!("Either feature \"std\" or feature \"sgx\" must be enabled"); + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +extern crate sgx_tstd as std; + +extern crate alloc; + +#[doc(hidden)] +pub use core::{ + cell::RefCell, + marker::PhantomData, + mem::{replace, transmute}, +}; + +#[doc(hidden)] +pub use alloc::{rc::Rc, vec::Vec}; + +#[doc(hidden)] +pub use std::thread::LocalKey; + +#[doc(hidden)] +#[macro_export] +macro_rules! thread_local_impl { + ($(#[$attr:meta])* static $name:ident: $t:ty = $init:expr) => ( + use std::thread_local; + thread_local!($(#[$attr])* static $name: $t = $init); + ); +} + +/// The global inner that stores the stack of globals. +#[doc(hidden)] +pub type GlobalInner = RefCell>>>; + +/// The global type. +type Global = LocalKey>; + +#[doc(hidden)] +pub fn using R>( + global: &'static Global, + protected: &mut T, + f: F, +) -> R { + // store the `protected` reference as a pointer so we can provide it to logic running within + // `f`. + // while we record this pointer (while it's non-zero) we guarantee: + // - it will only be used once at any time (no reentrancy); + // - that no other thread will use it; and + // - that we do not use the original mutating reference while the pointer. + // exists. + global.with(|r| { + // Push the new global to the end of the stack. + r.borrow_mut().push(Rc::new(RefCell::new(protected as _))); + + // Even if `f` panics the added global will be popped. + struct PopGlobal<'a, T: 'a + ?Sized> { + global_stack: &'a GlobalInner, + } + + impl<'a, T: 'a + ?Sized> Drop for PopGlobal<'a, T> { + fn drop(&mut self) { + self.global_stack.borrow_mut().pop(); + } + } + + let _guard = PopGlobal { global_stack: r }; + + f() + }) +} + +#[doc(hidden)] +pub fn with R>( + global: &'static Global, + mutator: F, +) -> Option { + global.with(|r| { + // We always use the `last` element when we want to access the + // currently set global. + let last = r.borrow().last().cloned(); + last.map(|ptr| + // safe because it's only non-zero when it's being called from using, which + // is holding on to the underlying reference (and not using it itself) safely. + unsafe { + mutator(&mut **ptr.borrow_mut()) + }) + }) +} + +/// Declare a new global reference module whose underlying value does not contain references. +/// +/// Will create a module of a given name that contains two functions: +/// +/// * `pub fn using R>(protected: &mut $t, f: F) -> R` +/// This executes `f`, returning its value. During the call, the module's reference is set to +/// be equal to `protected`. +/// * `pub fn with R>(f: F) -> Option` +/// This executes `f`, returning `Some` of its value if called from code that is being executed +/// as part of a `using` call. If not, it returns `None`. `f` is provided with one argument: the +/// same reference as provided to the most recent `using` call. +/// +/// # Examples +/// +/// Initializing the global context with a given value. +/// +/// ```rust +/// #[macro_use] extern crate environmental; +/// environmental!(counter: u32); +/// fn main() { +/// let mut counter_value = 41u32; +/// counter::using(&mut counter_value, || { +/// let odd = counter::with(|value| +/// if *value % 2 == 1 { +/// *value += 1; true +/// } else { +/// *value -= 3; false +/// }).unwrap(); // safe because we're inside a counter::using +/// println!("counter was {}", match odd { true => "odd", _ => "even" }); +/// }); +/// +/// println!("The answer is {:?}", counter_value); // 42 +/// } +/// ``` +/// +/// Roughly the same, but with a trait object: +/// +/// ```rust +/// #[macro_use] extern crate environmental; +/// +/// trait Increment { fn increment(&mut self); } +/// +/// impl Increment for i32 { +/// fn increment(&mut self) { *self += 1 } +/// } +/// +/// environmental!(val: dyn Increment + 'static); +/// +/// fn main() { +/// let mut local = 0i32; +/// val::using(&mut local, || { +/// val::with(|v| for _ in 0..5 { v.increment() }); +/// }); +/// +/// assert_eq!(local, 5); +/// } +/// ``` +#[macro_export] +macro_rules! environmental { + ($name:ident : $t:ty) => { + #[allow(non_camel_case_types)] + struct $name { __private_field: () } + + $crate::thread_local_impl! { + static GLOBAL: $crate::GlobalInner<$t> = Default::default() + } + + impl $name { + #[allow(unused_imports)] + + pub fn using R>( + protected: &mut $t, + f: F + ) -> R { + $crate::using(&GLOBAL, protected, f) + } + + pub fn with R>( + f: F + ) -> Option { + $crate::with(&GLOBAL, |x| f(x)) + } + } + }; + ($name:ident : trait @$t:ident [$($args:ty,)*]) => { + #[allow(non_camel_case_types, dead_code)] + struct $name { __private_field: () } + + $crate::thread_local_impl! { + static GLOBAL: $crate::GlobalInner<(dyn $t<$($args),*> + 'static)> + = Default::default() + } + + impl $name { + #[allow(unused_imports)] + + pub fn using R>( + protected: &mut dyn $t<$($args),*>, + f: F + ) -> R { + let lifetime_extended = unsafe { + $crate::transmute::<&mut dyn $t<$($args),*>, &mut (dyn $t<$($args),*> + 'static)>(protected) + }; + $crate::using(&GLOBAL, lifetime_extended, f) + } + + pub fn with FnOnce(&'a mut (dyn $t<$($args),*> + 'a)) -> R>( + f: F + ) -> Option { + $crate::with(&GLOBAL, |x| f(x)) + } + } + }; + ($name:ident<$traittype:ident> : trait $t:ident <$concretetype:ty>) => { + #[allow(non_camel_case_types, dead_code)] + struct $name { _private_field: $crate::PhantomData } + + $crate::thread_local_impl! { + static GLOBAL: $crate::GlobalInner<(dyn $t<$concretetype> + 'static)> + = Default::default() + } + + impl $name { + #[allow(unused_imports)] + pub fn using R>( + protected: &mut dyn $t, + f: F + ) -> R { + let lifetime_extended = unsafe { + $crate::transmute::<&mut dyn $t, &mut (dyn $t<$concretetype> + 'static)>(protected) + }; + $crate::using(&GLOBAL, lifetime_extended, f) + } + + pub fn with FnOnce(&'a mut (dyn $t<$concretetype> + 'a)) -> R>( + f: F + ) -> Option { + $crate::with(&GLOBAL, |x| f(x)) + } + } + }; + ($name:ident : trait $t:ident <>) => { $crate::environmental! { $name : trait @$t [] } }; + ($name:ident : trait $t:ident < $($args:ty),* $(,)* >) => { + $crate::environmental! { $name : trait @$t [$($args,)*] } + }; + ($name:ident : trait $t:ident) => { $crate::environmental! { $name : trait @$t [] } }; +} + +#[cfg(test)] +mod tests { + // Test trait in item position + #[allow(dead_code)] + mod trait_test { + trait Test {} + + environmental!(item_positon_trait: trait Test); + } + + // Test type in item position + #[allow(dead_code)] + mod type_test { + environmental!(item_position_type: u32); + } + + #[test] + fn simple_works() { + environmental!(counter: u32); + + fn stuff() { + counter::with(|value| *value += 1); + } + + // declare a stack variable of the same type as our global declaration. + let mut local = 41u32; + + // call stuff, setting up our `counter` environment as a reference to our local counter var. + counter::using(&mut local, stuff); + assert_eq!(local, 42); + stuff(); // safe! doesn't do anything. + assert_eq!(local, 42); + } + + #[test] + fn overwrite_with_lesser_lifetime() { + environmental!(items: Vec); + + let mut local_items = vec![1, 2, 3]; + items::using(&mut local_items, || { + let dies_at_end = vec![4, 5, 6]; + items::with(|items| *items = dies_at_end); + }); + + assert_eq!(local_items, vec![4, 5, 6]); + } + + #[test] + fn declare_with_trait_object() { + trait Foo { + fn get(&self) -> i32; + fn set(&mut self, x: i32); + } + + impl Foo for i32 { + fn get(&self) -> i32 { + *self + } + fn set(&mut self, x: i32) { + *self = x + } + } + + environmental!(foo: dyn Foo + 'static); + + fn stuff() { + foo::with(|value| { + let new_val = value.get() + 1; + value.set(new_val); + }); + } + + let mut local = 41i32; + foo::using(&mut local, stuff); + + assert_eq!(local, 42); + + stuff(); // doesn't do anything. + + assert_eq!(local, 42); + } + + #[test] + fn unwind_recursive() { + use std::panic; + + environmental!(items: Vec); + + let panicked = panic::catch_unwind(|| { + let mut local_outer = vec![1, 2, 3]; + + items::using(&mut local_outer, || { + let mut local_inner = vec![4, 5, 6]; + items::using(&mut local_inner, || { + panic!("are you unsafe?"); + }) + }); + }) + .is_err(); + + assert!(panicked); + + let mut was_cleared = true; + items::with(|_items| was_cleared = false); + + assert!(was_cleared); + } + + #[test] + fn use_non_static_trait() { + trait Sum { + fn sum(&self) -> usize; + } + impl Sum for &[usize] { + fn sum(&self) -> usize { + self.iter().fold(0, |a, c| a + c) + } + } + + environmental!(sum: trait Sum); + let numbers = vec![1, 2, 3, 4, 5]; + let mut numbers = &numbers[..]; + let got_sum = sum::using(&mut numbers, || sum::with(|x| x.sum())).unwrap(); + + assert_eq!(got_sum, 15); + } + + #[test] + fn stacking_globals() { + trait Sum { + fn sum(&self) -> usize; + } + impl Sum for &[usize] { + fn sum(&self) -> usize { + self.iter().fold(0, |a, c| a + c) + } + } + + environmental!(sum: trait Sum); + let numbers = vec![1, 2, 3, 4, 5]; + let mut numbers = &numbers[..]; + let got_sum = sum::using(&mut numbers, || { + sum::with(|_| { + let numbers2 = vec![1, 2, 3, 4, 5, 6]; + let mut numbers2 = &numbers2[..]; + sum::using(&mut numbers2, || sum::with(|x| x.sum())) + }) + }) + .unwrap() + .unwrap(); + + assert_eq!(got_sum, 21); + + assert!(sum::with(|_| ()).is_none()); + } + + #[test] + fn use_generic_trait() { + trait Plus { + fn plus42() -> usize; + } + struct ConcretePlus; + impl Plus for ConcretePlus { + fn plus42() -> usize { + 42 + } + } + trait Multiplier { + fn mul_and_add(&self) -> usize; + } + impl<'a, P: Plus> Multiplier

for &'a [usize] { + fn mul_and_add(&self) -> usize { + self.iter().fold(1, |a, c| a * c) + P::plus42() + } + } + + let numbers = vec![1, 2, 3]; + let mut numbers = &numbers[..]; + let out = foo::::using(&mut numbers, || { + foo::::with(|x| x.mul_and_add()) + }) + .unwrap(); + + assert_eq!(out, 6 + 42); + environmental!(foo: trait Multiplier); + } +} diff --git a/bitacross-worker/core-primitives/substrate-sgx/externalities/Cargo.toml b/bitacross-worker/core-primitives/substrate-sgx/externalities/Cargo.toml new file mode 100644 index 0000000000..7edac9aa58 --- /dev/null +++ b/bitacross-worker/core-primitives/substrate-sgx/externalities/Cargo.toml @@ -0,0 +1,44 @@ +[package] +name = "itp-sgx-externalities" +version = "0.9.0" +authors = ['Trust Computing GmbH ', 'Integritee AG and Parity Technologies '] +edition = "2021" + +[dependencies] +# no_std +codec = { version = "3.0.0", package = "parity-scale-codec", default-features = false, features = ["derive", "chain-error"] } +derive_more = "0.99.16" +log = { version = "0.4", default-features = false } +postcard = { version = "0.7.2", default-features = false, features = ["alloc"] } +serde = { version = "1.0", default-features = false, features = ["derive", "alloc"] } + +# sgx dependencies +sgx_tstd = { optional = true, features = ["untrusted_fs", "net", "backtrace"], git = "https://github.com/apache/teaclave-sgx-sdk.git", branch = "master" } + +# substrate +sp-core = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } + +# local +environmental = { default-features = false, path = "../environmental" } +itp-hashing = { default-features = false, path = "../../hashing" } + +[dev-dependencies] +itp-storage = { default-features = false, path = "../../storage" } + +[features] +default = ["std"] +std = [ + "codec/std", + "environmental/std", + "itp-hashing/std", + "log/std", + "postcard/use-std", + "serde/std", + "itp-storage/std", + # substrate + "sp-core/std", +] +sgx = [ + "sgx_tstd", + "environmental/sgx", +] diff --git a/bitacross-worker/core-primitives/substrate-sgx/externalities/src/bypass.rs b/bitacross-worker/core-primitives/substrate-sgx/externalities/src/bypass.rs new file mode 100644 index 0000000000..dcd5bd9f9c --- /dev/null +++ b/bitacross-worker/core-primitives/substrate-sgx/externalities/src/bypass.rs @@ -0,0 +1,60 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +//! Converts maps to vecs for serialization. +//! from https://github.com/DenisKolodin/vectorize +//! +//! `bypass` is necessary to force deriving serialization of complex type specs. + +use serde::{Deserialize, Deserializer, Serialize, Serializer}; + +#[allow(unused)] +pub fn serialize<'a, T, S>(target: T, ser: S) -> Result +where + S: Serializer, + T: Serialize + 'a, +{ + serde::Serialize::serialize(&target, ser) +} + +#[allow(unused)] +pub fn deserialize<'de, T, D>(des: D) -> Result +where + D: Deserializer<'de>, + T: Deserialize<'de>, +{ + serde::Deserialize::deserialize(des) +} + +#[cfg(test)] +mod tests { + use serde::{de::DeserializeOwned, Deserialize, Serialize}; + use std::fmt; + + trait Requirement: + DeserializeOwned + Serialize + Clone + fmt::Debug + Sync + Send + 'static + { + } + + trait ComplexSpec: Requirement {} + + #[derive(Debug, Serialize, Deserialize)] + struct MyComplexType { + #[serde(with = "super")] // = "vectorize::bypass" + inner: Option, + } +} diff --git a/bitacross-worker/core-primitives/substrate-sgx/externalities/src/codec_impl.rs b/bitacross-worker/core-primitives/substrate-sgx/externalities/src/codec_impl.rs new file mode 100644 index 0000000000..b65f9003f1 --- /dev/null +++ b/bitacross-worker/core-primitives/substrate-sgx/externalities/src/codec_impl.rs @@ -0,0 +1,149 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +//! Implement `parity-scale-codec` for the externalities. +//! +//! This is necessary workaround, as `Encode` and `Decode` can't directly be implemented on `HashMap` or `BTreeMap`. + +use codec::{Decode, Encode, Input}; +use serde::{de::DeserializeOwned, Serialize}; +use std::{vec, vec::Vec}; + +use crate::{SgxExternalitiesDiffType, SgxExternalitiesType}; + +impl Encode for SgxExternalitiesType { + fn encode(&self) -> Vec { + encode_with_serialize(&self) + } +} + +impl Decode for SgxExternalitiesType { + fn decode(input: &mut I) -> Result { + decode_with_deserialize(input) + } +} + +impl Encode for SgxExternalitiesDiffType { + fn encode(&self) -> Vec { + encode_with_serialize(&self) + } +} + +impl Decode for SgxExternalitiesDiffType { + fn decode(input: &mut I) -> Result { + decode_with_deserialize(input) + } +} + +fn encode_with_serialize(source: &T) -> Vec { + // We unwrap on purpose here in order to make sure we notice when something goes wrong. + // Before we returned an empty vec and logged the error. But this could go unnoticed in the + // caller and cause problems (in case the empty vec is also something valid) + postcard::to_allocvec(source).unwrap() +} + +fn decode_with_deserialize( + input: &mut I, +) -> Result { + let input_length = input + .remaining_len()? + .ok_or_else(|| codec::Error::from("Could not read length from input data"))?; + + let mut buff = vec![0u8; input_length]; + + input.read(&mut buff)?; + + postcard::from_bytes::<'_, T>(buff.as_slice()).map_err(|e| { + log::error!("deserialization failed: {:?}", e); + codec::Error::from("Could not decode with deserialize") + }) +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::{InternalMap, SgxExternalities}; + use std::{ + collections::hash_map::DefaultHasher, + hash::{Hash, Hasher}, + }; + + #[test] + fn serializing_externalities_type_works() { + ensure_serialize_roundtrip_succeeds(create_default_state()); + } + + #[test] + fn serializing_externalities_diff_type_works() { + ensure_serialize_roundtrip_succeeds(create_default_state_diff()); + } + + #[test] + fn serializing_externalities_works() { + let externalities = SgxExternalities { + state: create_default_state(), + state_diff: create_default_state_diff(), + }; + + ensure_serialize_roundtrip_succeeds(externalities); + } + + #[test] + fn encoding_decoding_preserves_order() { + let externalities = create_default_state(); + let encoded_externalities = externalities.encode(); + let decoded_externalities: SgxExternalitiesType = + Decode::decode(&mut encoded_externalities.as_slice()).unwrap(); + let encoded_second_time_externalities = decoded_externalities.encode(); + + assert_eq!( + calculate_hash(&encoded_externalities), + calculate_hash(&encoded_second_time_externalities) + ); + } + + fn create_default_state_diff() -> SgxExternalitiesDiffType { + let mut map = InternalMap::>>::new(); + map.insert(Encode::encode("dings"), Some(Encode::encode("other"))); + map.insert(Encode::encode("item"), Some(Encode::encode("crate"))); + map.insert(Encode::encode("key"), None); + SgxExternalitiesDiffType(map) + } + + fn create_default_state() -> SgxExternalitiesType { + let mut map = InternalMap::>::new(); + map.insert(Encode::encode("dings"), Encode::encode("other")); + map.insert(Encode::encode("item"), Encode::encode("crate")); + SgxExternalitiesType(map) + } + + fn ensure_serialize_roundtrip_succeeds< + T: Serialize + DeserializeOwned + std::cmp::PartialEq + std::fmt::Debug, + >( + item: T, + ) { + let serialized_item = postcard::to_allocvec(&item).unwrap(); + let deserialized_item = postcard::from_bytes::<'_, T>(serialized_item.as_slice()).unwrap(); + assert_eq!(item, deserialized_item); + } + + fn calculate_hash(t: &T) -> u64 { + let mut s = DefaultHasher::new(); + t.hash(&mut s); + s.finish() + } +} diff --git a/bitacross-worker/core-primitives/substrate-sgx/externalities/src/lib.rs b/bitacross-worker/core-primitives/substrate-sgx/externalities/src/lib.rs new file mode 100644 index 0000000000..f417c88286 --- /dev/null +++ b/bitacross-worker/core-primitives/substrate-sgx/externalities/src/lib.rs @@ -0,0 +1,470 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg(all(feature = "std", feature = "sgx"))] +compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the same time"); + +#[cfg(feature = "sgx")] +extern crate sgx_tstd as std; + +use codec::{Decode, Encode, EncodeAppend}; +use core::ops::Bound; +use derive_more::{Deref, DerefMut, From, IntoIterator}; +use itp_hashing::Hash; +use serde::{Deserialize, Serialize}; +use sp_core::{hashing::blake2_256, H256}; +use std::{collections::BTreeMap, fmt::Debug, vec, vec::Vec}; + +pub use scope_limited::{set_and_run_with_externalities, with_externalities}; + +// Unfortunately we cannot use `serde_with::serde_as` to serialize our map (which would be very convenient) +// because it has pulls in the serde and serde_json dependency with `std`, not `default-features=no`. +// Instead we use https://github.com/DenisKolodin/vectorize which is very little code, copy-pasted +// directly into this code base. +//use serde_with::serde_as; + +mod codec_impl; +mod scope_limited; +// These are used to serialize a map with keys that are not string. +mod bypass; +mod vectorize; + +type InternalMap = BTreeMap, V>; + +#[derive(From, Deref, DerefMut, Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)] +pub struct SgxExternalitiesType(#[serde(with = "vectorize")] InternalMap>); + +#[derive( + From, + Deref, + DerefMut, + Clone, + Debug, + Default, + PartialEq, + Eq, + Serialize, + Deserialize, + IntoIterator, +)] +pub struct SgxExternalitiesDiffType(#[serde(with = "vectorize")] InternalMap>>); + +#[derive(Clone, Debug, Default, PartialEq, Eq, Encode, Decode, Serialize, Deserialize)] +pub struct SgxExternalities { + pub state: SgxExternalitiesType, + pub state_diff: SgxExternalitiesDiffType, +} + +pub trait StateHash { + fn hash(&self) -> H256; +} + +impl StateHash for SgxExternalities { + fn hash(&self) -> H256 { + self.state.using_encoded(blake2_256).into() + } +} + +impl Hash for SgxExternalities { + fn hash(&self) -> H256 { + ::hash(self) + } +} + +pub trait SgxExternalitiesTrait { + type SgxExternalitiesType; + type SgxExternalitiesDiffType; + + // Create new Externaltiies with empty diff. + fn new(state: Self::SgxExternalitiesType) -> Self; + + fn state(&self) -> &Self::SgxExternalitiesType; + + fn state_diff(&self) -> &Self::SgxExternalitiesDiffType; + + fn insert(&mut self, k: Vec, v: Vec) -> Option>; + + /// Append a value to an existing key. + fn append(&mut self, k: Vec, v: Vec); + + fn remove(&mut self, k: &[u8]) -> Option>; + + fn get(&self, k: &[u8]) -> Option<&Vec>; + + fn contains_key(&self, k: &[u8]) -> bool; + + /// Get the next key in state after the given one (excluded) in lexicographic order. + fn next_storage_key(&self, key: &[u8]) -> Option>; + + /// Reads all keys and values under given prefix + fn iter_prefix( + &self, + key_prefix: &[u8], + ) -> Option>; + + /// Clears all values that match the given key prefix. + fn clear_prefix(&mut self, key_prefix: &[u8], maybe_limit: Option) -> u32; + + /// Prunes the state diff. + fn prune_state_diff(&mut self); + + /// Execute the given closure while `self` is set as externalities. + /// + /// Returns the result of the given closure. + fn execute_with(&mut self, f: impl FnOnce() -> R) -> R; +} + +impl SgxExternalitiesTrait for SgxExternalities +where + SgxExternalitiesType: Encode + Decode, + SgxExternalitiesDiffType: Encode + Decode, +{ + type SgxExternalitiesType = SgxExternalitiesType; + type SgxExternalitiesDiffType = SgxExternalitiesDiffType; + + fn new(state: Self::SgxExternalitiesType) -> Self { + Self { state, state_diff: Default::default() } + } + + fn state(&self) -> &Self::SgxExternalitiesType { + &self.state + } + + fn state_diff(&self) -> &Self::SgxExternalitiesDiffType { + &self.state_diff + } + + fn insert(&mut self, key: Vec, value: Vec) -> Option> { + self.state_diff.insert(key.clone(), Some(value.clone())); + self.state.insert(key, value) + } + + fn append(&mut self, key: Vec, value: Vec) { + let current = self.state.entry(key.clone()).or_default(); + let updated_value = StorageAppend::new(current).append(value); + self.state_diff.insert(key, Some(updated_value)); + } + + fn remove(&mut self, key: &[u8]) -> Option> { + self.state_diff.insert(key.to_vec(), None); + self.state.remove(key) + } + + fn get(&self, key: &[u8]) -> Option<&Vec> { + self.state.get(key) + } + + fn contains_key(&self, key: &[u8]) -> bool { + self.state.contains_key(key) + } + + fn next_storage_key(&self, key: &[u8]) -> Option> { + let range = (Bound::Excluded(key), Bound::Unbounded); + self.state.range::<[u8], _>(range).next().map(|(k, _v)| k.to_vec()) // directly return k as _v is never None in our case + } + + fn prune_state_diff(&mut self) { + self.state_diff.clear(); + } + + // Note: This implementation only works for keys encoded with Blake2_128Concat + fn iter_prefix( + &self, + key_prefix: &[u8], + ) -> Option> { + // The size of the hash part in Blake2_128Concat (16 bytes for blake2_128) + const HASH_PART_SIZE: usize = 16; + + let key_values = self + .state + .range::<[u8], _>((Bound::Included(key_prefix), Bound::Unbounded)) + .take_while(|(k, _)| k.starts_with(key_prefix)) + .filter_map(|(encoded_key, encoded_value)| { + let suffix_start = key_prefix.len() + HASH_PART_SIZE; + if encoded_key.len() > suffix_start { + let suffix = &encoded_key[suffix_start..]; + let decoded_key = K::decode(&mut &suffix[..]).ok(); + let decoded_value = V::decode(&mut &encoded_value[..]).ok(); + match (decoded_key, decoded_value) { + (Some(key), Some(value)) => Some((key, value)), + _ => None, + } + } else { + None + } + }) + .collect::>(); + + if key_values.is_empty() { + None + } else { + Some(key_values) + } + } + + fn clear_prefix(&mut self, key_prefix: &[u8], _maybe_limit: Option) -> u32 { + // Inspired by Substrate https://github.com/paritytech/substrate/blob/c8653447fc8ef8d95a92fe164c96dffb37919e85/primitives/state-machine/src/basic.rs#L242-L254 + let to_remove = self + .state + .range::<[u8], _>((Bound::Included(key_prefix), Bound::Unbounded)) + .map(|(k, _)| k) + .take_while(|k| k.starts_with(key_prefix)) + .cloned() + .collect::>(); + + let count = to_remove.len() as u32; + for key in to_remove { + self.remove(&key); + } + count + } + + fn execute_with(&mut self, f: impl FnOnce() -> R) -> R { + set_and_run_with_externalities(self, f) + } +} + +/// Results concerning an operation to remove many keys. +#[derive(codec::Encode, codec::Decode)] +#[must_use] +pub struct MultiRemovalResults { + /// A continuation cursor which, if `Some` must be provided to the subsequent removal call. + /// If `None` then all removals are complete and no further calls are needed. + pub maybe_cursor: Option>, + /// The number of items removed from the backend database. + pub backend: u32, + /// The number of unique keys removed, taking into account both the backend and the overlay. + pub unique: u32, + /// The number of iterations (each requiring a storage seek/read) which were done. + pub loops: u32, +} + +impl MultiRemovalResults { + /// Deconstruct into the internal components. + /// + /// Returns `(maybe_cursor, backend, unique, loops)`. + pub fn deconstruct(self) -> (Option>, u32, u32, u32) { + (self.maybe_cursor, self.backend, self.unique, self.loops) + } +} + +/// Auxialiary structure for appending a value to a storage item. +/// Taken from https://github.com/paritytech/substrate/blob/master/primitives/state-machine/src/ext.rs +pub(crate) struct StorageAppend<'a>(&'a mut Vec); + +impl<'a> StorageAppend<'a> { + /// Create a new instance using the given `storage` reference. + pub fn new(storage: &'a mut Vec) -> Self { + Self(storage) + } + + /// Append the given `value` to the storage item. + /// + /// If appending fails, `[value]` is stored in the storage item. + pub fn append(&mut self, value: Vec) -> Vec { + let value = vec![EncodeOpaqueValue(value)]; + + let item = core::mem::take(self.0); + + *self.0 = match Vec::::append_or_new(item, &value) { + Ok(item) => item, + Err(_) => { + log::error!("Failed to append value, resetting storage item to input value."); + value.encode() + }, + }; + (*self.0).to_vec() + } +} + +/// Implement `Encode` by forwarding the stored raw vec. +struct EncodeOpaqueValue(Vec); + +impl Encode for EncodeOpaqueValue { + fn using_encoded R>(&self, f: F) -> R { + f(&self.0) + } +} + +#[cfg(test)] +pub mod tests { + + use super::*; + use itp_storage::{storage_double_map_key, storage_map_key, StorageHasher}; + + #[test] + fn mutating_externalities_through_environmental_variable_works() { + let mut externalities = SgxExternalities::default(); + + externalities.execute_with(|| { + with_externalities(|e| { + e.insert("building".encode(), "empire_state".encode()); + e.insert("house".encode(), "ginger_bread".encode()); + }) + .unwrap() + }); + + let state_len = + externalities.execute_with(|| with_externalities(|e| e.state.0.len()).unwrap()); + + assert_eq!(2, state_len); + } + + #[test] + fn basic_externalities_is_empty() { + let ext = SgxExternalities::default(); + assert!(ext.state.0.is_empty()); + } + + #[test] + fn storage_append_works() { + let mut data = Vec::new(); + let mut append = StorageAppend::new(&mut data); + append.append(1u32.encode()); + let updated_data = append.append(2u32.encode()); + drop(append); + + assert_eq!(Vec::::decode(&mut &data[..]).unwrap(), vec![1, 2]); + assert_eq!(updated_data, data); + + // Initialize with some invalid data + let mut data = vec![1]; + let mut append = StorageAppend::new(&mut data); + append.append(1u32.encode()); + append.append(2u32.encode()); + drop(append); + + assert_eq!(Vec::::decode(&mut &data[..]).unwrap(), vec![1, 2]); + } + + #[test] + #[should_panic(expected = "already borrowed: BorrowMutError")] + fn nested_with_externalities_panics() { + let mut ext = SgxExternalities::default(); + + ext.execute_with(|| { + with_externalities(|_| with_externalities(|_| unreachable!("panics before")).unwrap()) + .unwrap(); + }); + } + + #[test] + fn nesting_execute_with_uses_the_latest_externalities() { + let mut ext = SgxExternalities::default(); + let mut ext2 = ext.clone(); + + let hello = b"hello".to_vec(); + let world = b"world".to_vec(); + + ext.execute_with(|| { + with_externalities(|e| { + e.insert(hello.clone(), hello.clone()); + }) + .unwrap(); + + ext2.execute_with(|| { + // `with_externalities` uses the latest set externalities defined by the last + // `set_and_run_with_externalities` call. + with_externalities(|e| { + e.insert(world.clone(), world.clone()); + }) + .unwrap(); + }); + }); + + assert_eq!(ext.get(&hello), Some(&hello)); + assert_eq!(ext2.get(&world), Some(&world)); + + // ext1 and ext2 are unrelated. + assert_eq!(ext.get(&world), None); + } + + #[test] + fn clear_prefix_works() { + let mut externalities = SgxExternalities::default(); + let non_house_key = b"window house".to_vec(); + let non_house_value = b"test_string".to_vec(); + // Fill state. + externalities.execute_with(|| { + with_externalities(|e| { + e.insert(b"house_building".to_vec(), b"empire_state".to_vec()); + e.insert(b"house".to_vec(), b"ginger_bread".to_vec()); + e.insert(b"house door".to_vec(), b"right".to_vec()); + e.insert(non_house_key.clone(), non_house_value.clone()); + }) + .unwrap() + }); + let state_len = + externalities.execute_with(|| with_externalities(|e| e.state.0.len()).unwrap()); + assert_eq!(state_len, 4); + + let number_of_removed_items = externalities + .execute_with(|| with_externalities(|e| e.clear_prefix(b"house", None)).unwrap()); + assert_eq!(number_of_removed_items, 3); + + let state_len = + externalities.execute_with(|| with_externalities(|e| e.state.0.len()).unwrap()); + assert_eq!(state_len, 1); + let stored_value = externalities.execute_with(|| { + with_externalities(|e| { + assert_eq!(e.get(&non_house_key).unwrap().clone(), non_house_value) + }) + }); + assert!(stored_value.is_some()); + } + + #[test] + fn iter_prefix_works() { + let mut externalities = SgxExternalities::default(); + + let key_1 = storage_double_map_key( + "Pallet", + "Storage", + &1_u32, + &StorageHasher::Blake2_128Concat, + &2_u32, + &StorageHasher::Blake2_128Concat, + ); + let key_2 = storage_double_map_key( + "Pallet", + "Storage", + &1_u32, + &StorageHasher::Blake2_128Concat, + &3_u32, + &StorageHasher::Blake2_128Concat, + ); + let prefix_key = + storage_map_key("Pallet", "Storage", &1_u32, &StorageHasher::Blake2_128Concat); + + // Fill state. + externalities.execute_with(|| { + with_externalities(|e| { + e.insert(key_1, 10_u32.encode()); + e.insert(key_2, 20_u32.encode()); + }) + .unwrap() + }); + // Perform iter prefix + externalities.execute_with(|| { + with_externalities(|e| { + let values = e.iter_prefix::(&prefix_key).unwrap(); + assert_eq!(values, [(2, 10), (3, 20)]); + }) + .unwrap() + }); + } +} diff --git a/bitacross-worker/core-primitives/substrate-sgx/externalities/src/scope_limited.rs b/bitacross-worker/core-primitives/substrate-sgx/externalities/src/scope_limited.rs new file mode 100644 index 0000000000..55c9a9e4d7 --- /dev/null +++ b/bitacross-worker/core-primitives/substrate-sgx/externalities/src/scope_limited.rs @@ -0,0 +1,38 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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. + +use crate::SgxExternalities; + +environmental::environmental!(ext: SgxExternalities); + +/// Set the given externalities while executing the given closure. To get access to the +/// externalities while executing the given closure [`with_externalities`] grants access to them. +/// The externalities are only set for the same thread this function was called from. +pub fn set_and_run_with_externalities R, R>(ext: &mut SgxExternalities, f: F) -> R { + ext::using(ext, f) +} + +/// Execute the given closure with the currently set externalities. +/// +/// Returns `None` if no externalities are set or `Some(_)` with the result of the closure. +/// +/// Panics with `already borrowed: BorrowMutError` if calls to `with_externalities` are nested. +pub fn with_externalities R, R>(f: F) -> Option { + ext::with(f) +} diff --git a/bitacross-worker/core-primitives/substrate-sgx/externalities/src/vectorize.rs b/bitacross-worker/core-primitives/substrate-sgx/externalities/src/vectorize.rs new file mode 100644 index 0000000000..d2203902ae --- /dev/null +++ b/bitacross-worker/core-primitives/substrate-sgx/externalities/src/vectorize.rs @@ -0,0 +1,76 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +//! Converts maps to vecs for serialization. +//! from https://github.com/DenisKolodin/vectorize + +use serde::{Deserialize, Deserializer, Serialize, Serializer}; +use std::{iter::FromIterator, vec::Vec}; + +pub fn serialize<'a, T, K, V, S>(target: T, ser: S) -> Result +where + S: Serializer, + T: IntoIterator, + K: Serialize + 'a, + V: Serialize + 'a, +{ + let container: Vec<_> = target.into_iter().collect(); + serde::Serialize::serialize(&container, ser) +} + +pub fn deserialize<'de, T, K, V, D>(des: D) -> Result +where + D: Deserializer<'de>, + T: FromIterator<(K, V)>, + K: Deserialize<'de>, + V: Deserialize<'de>, +{ + let container: Vec<_> = serde::Deserialize::deserialize(des)?; + Ok(container.into_iter().collect()) +} + +#[cfg(test)] +mod tests { + use crate::vectorize; + use serde::{Deserialize, Serialize}; + use std::collections::HashMap; + + #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash)] + struct MyKey { + one: String, + two: u16, + more: Vec, + } + + #[derive(Debug, Serialize, Deserialize)] + struct MyComplexType { + #[serde(with = "vectorize")] + map: HashMap, + } + + #[test] + fn it_works() -> Result<(), Box> { + let key = MyKey { one: "1".into(), two: 2, more: vec![1, 2, 3] }; + let mut map = HashMap::new(); + map.insert(key.clone(), "value".into()); + let instance = MyComplexType { map }; + let serialized = postcard::to_allocvec(&instance)?; + let deserialized: MyComplexType = postcard::from_bytes(&serialized)?; + let expected_value = "value".to_string(); + assert_eq!(deserialized.map.get(&key), Some(&expected_value)); + Ok(()) + } +} diff --git a/bitacross-worker/core-primitives/substrate-sgx/sp-io/Cargo.toml b/bitacross-worker/core-primitives/substrate-sgx/sp-io/Cargo.toml new file mode 100644 index 0000000000..0600c8a4b6 --- /dev/null +++ b/bitacross-worker/core-primitives/substrate-sgx/sp-io/Cargo.toml @@ -0,0 +1,39 @@ +[package] +name = "sp-io" +version = "7.0.0" +authors = ['Trust Computing GmbH ', 'Integritee AG and Parity Technologies '] +edition = "2021" +license = "Apache-2.0" + +[dependencies] +codec = { version = "3.0.0", package = "parity-scale-codec", default-features = false } +libsecp256k1 = { version = "0.7.0", default-features = false, features = ["static-context"] } +log = { version = "0.4", default-features = false } + +itp-sgx-externalities = { default-features = false, path = "../externalities" } +sgx_tstd = { optional = true, features = ["untrusted_fs", "net", "backtrace"], git = "https://github.com/apache/teaclave-sgx-sdk.git", branch = "master" } + +# Substrate dependencies +sp-core = { default-features = false, features = ["full_crypto"], git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } + +[features] +default = ["std"] +std = [ + "log/std", + "sp-core/std", + "codec/std", + "libsecp256k1/std", + "itp-sgx-externalities/std", +] +sgx = [ + "sgx_tstd", + "itp-sgx-externalities/sgx", +] + +# These two features are used for `no_std` builds for the environments which already provides +# `#[panic_handler]`, `#[alloc_error_handler]` and `#[global_allocator]`. +# +# For the regular wasm sgx-runtime builds those are not used. +disable_panic_handler = [] +disable_oom = [] +disable_allocator = [] diff --git a/bitacross-worker/core-primitives/substrate-sgx/sp-io/src/lib.rs b/bitacross-worker/core-primitives/substrate-sgx/sp-io/src/lib.rs new file mode 100644 index 0000000000..6962f6c164 --- /dev/null +++ b/bitacross-worker/core-primitives/substrate-sgx/sp-io/src/lib.rs @@ -0,0 +1,1012 @@ +// Copyright 2017-2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//#![warn(missing_docs)] + +// Added by Integritee. Prevents warnings during compilation with sgx features at all those +// unimplemented method stubs. +#![allow(unused_variables)] +#![cfg_attr(not(feature = "std"), no_std)] +#![cfg_attr(not(feature = "std"), feature(lang_items))] +#![cfg_attr(not(feature = "std"), feature(alloc_error_handler))] +#![cfg_attr(not(feature = "std"), feature(core_intrinsics))] +#![cfg_attr( + feature = "std", + doc = "Substrate sgx-runtime standard library as compiled when linked with Rust's standard library." +)] +#![cfg_attr( + not(feature = "std"), + doc = "Substrate's sgx-runtime standard library as compiled without Rust's standard library." +)] + +#[cfg(all(feature = "std", feature = "sgx"))] +compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the same time"); + +#[cfg(feature = "sgx")] +extern crate sgx_tstd as std; + +use codec::{Decode, Encode}; +use log::*; +use sp_core::{ + crypto::{KeyTypeId, Pair}, + ecdsa, ed25519, + hash::H256, + offchain::{ + HttpError, HttpRequestId, HttpRequestStatus, OpaqueNetworkState, StorageKind, Timestamp, + }, + sr25519, + storage::StateVersion, +}; +use std::{char, prelude::v1::String, println, vec, vec::Vec}; + +#[allow(unused)] +fn encode_hex_digit(digit: u8) -> char { + match char::from_digit(u32::from(digit), 16) { + Some(c) => c, + _ => panic!(), + } +} + +#[allow(unused)] +fn encode_hex_byte(byte: u8) -> [char; 2] { + [encode_hex_digit(byte >> 4), encode_hex_digit(byte & 0x0Fu8)] +} + +#[allow(unused)] +pub fn encode_hex(bytes: &[u8]) -> String { + let strs: Vec = bytes + .iter() + .map(|byte| encode_hex_byte(*byte).iter().copied().collect()) + .collect(); + strs.join("") +} + +// Reexport here, such that the worker does not need to import other crate. +// Not sure if this is a good Idea though. +pub use itp_sgx_externalities::{ + with_externalities, SgxExternalities, SgxExternalitiesTrait, SgxExternalitiesType, +}; + +pub struct MultiRemovalResults { + /// A continuation cursor which, if `Some` must be provided to the subsequent removal call. + /// If `None` then all removals are complete and no further calls are needed. + pub maybe_cursor: Option>, + /// The number of items removed from the backend database. + pub backend: u32, + /// The number of unique keys removed, taking into account both the backend and the overlay. + pub unique: u32, + /// The number of iterations (each requiring a storage seek/read) which were done. + pub loops: u32, +} + +/// Error verifying ECDSA signature +#[derive(Encode, Decode)] +pub enum EcdsaVerifyError { + /// Incorrect value of R or S + BadRS, + /// Incorrect value of V + BadV, + /// Invalid signature + BadSignature, +} + +/// The outcome of calling `storage_kill`. Returned value is the number of storage items +/// removed from the trie from making the `storage_kill` call. +#[derive(Encode, Decode)] +pub enum KillStorageResult { + /// No key remains in the child trie. + AllRemoved(u32), + /// At least one key still resides in the child trie due to the supplied limit. + SomeRemaining(u32), +} + +impl From for KillStorageResult { + fn from(r: MultiRemovalResults) -> Self { + match r { + MultiRemovalResults { maybe_cursor: None, backend, .. } => Self::AllRemoved(backend), + MultiRemovalResults { maybe_cursor: Some(..), backend, .. } => + Self::SomeRemaining(backend), + } + } +} + +pub mod storage { + use super::*; + + pub fn get(key: &[u8]) -> Option> { + debug!("storage('{}')", encode_hex(key)); + with_externalities(|ext| { + ext.get(key).map(|s| { + debug!(" returning {}", encode_hex(s)); + s.to_vec() + }) + }) + .expect("storage cannot be called outside of an Externalities-provided environment.") + } + + pub fn read(key: &[u8], value_out: &mut [u8], value_offset: u32) -> Option { + debug!( + "read_storage('{}' with offset = {:?}. value_out.len() is {})", + encode_hex(key), + value_offset, + value_out.len() + ); + with_externalities(|ext| { + ext.get(key).map(|value| { + debug!(" entire stored value: {:?}", value); + let value_offset = value_offset as usize; + let value = &value[value_offset..]; + debug!(" stored value at offset: {:?}", value); + let written = std::cmp::min(value.len(), value_out.len()); + value_out[..written].copy_from_slice(&value[..written]); + debug!(" write back {:?}, return len {}", value_out, value.len()); + // Just return u32::Max if we read more than u32::Max bytes. + value.len().try_into().unwrap_or(u32::MAX) + }) + }) + .expect("read_storage cannot be called outside of an Externalities-provided environment.") + } + + pub fn set(key: &[u8], value: &[u8]) { + debug!("set_storage('{}', {:x?})", encode_hex(key), value); + with_externalities(|ext| ext.insert(key.to_vec(), value.to_vec())) + .expect("`set` cannot be called outside of an Externalities-provided environment."); + } + + pub fn clear(key: &[u8]) { + with_externalities(|ext| { + if ext.remove(key).is_none() { + info!("Tried to clear storage that was not existing"); + } + }); + } + + pub fn exists(key: &[u8]) -> bool { + with_externalities(|ext| ext.contains_key(key)) + .expect("exists cannot be called outside of an Externalities-provided environment.") + } + + /// Clear the storage of each key-value pair where the key starts with the given `prefix`. + pub fn clear_prefix_version_1(prefix: &[u8]) { + clear_prefix(prefix, None); + } + + /// Clear the storage of each key-value pair where the key starts with the given `prefix`. + /// + /// # Limit + /// + /// Deletes all keys from the overlay and up to `limit` keys from the backend if + /// it is set to `Some`. No limit is applied when `limit` is set to `None`. + /// + /// The limit can be used to partially delete a prefix storage in case it is too large + /// to delete in one go (block). + /// + /// It returns a boolean false iff some keys are remaining in + /// the prefix after the functions returns. Also returns a `u32` with + /// the number of keys removed from the process. + /// + /// # Note + /// + /// Please note that keys that are residing in the overlay for that prefix when + /// issuing this call are all deleted without counting towards the `limit`. Only keys + /// written during the current block are part of the overlay. Deleting with a `limit` + /// mostly makes sense with an empty overlay for that prefix. + /// + /// Calling this function multiple times per block for the same `prefix` does + /// not make much sense because it is not cumulative when called inside the same block. + /// Use this function to distribute the deletion of a single child trie across multiple + /// blocks. + pub fn clear_prefix(prefix: &[u8], maybe_limit: Option) -> KillStorageResult { + let number_of_removed_values = + with_externalities(|ext| ext.clear_prefix(prefix, maybe_limit)).unwrap_or_default(); + KillStorageResult::AllRemoved(number_of_removed_values) + } + + /// 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]`. + pub fn append(key: &[u8], value: Vec) { + with_externalities(|ext| ext.append(key.to_vec(), value.to_vec())); + } + + /// "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. + pub fn root_version_1() -> [u8; 32] { + warn!("storage::root() unimplemented"); + [0u8; 32] + } + + /// "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. + pub fn root(version: StateVersion) -> [u8; 32] { + warn!("storage::root() unimplemented"); + [0u8; 32] + } + + pub fn changes_root(parent_hash: &[u8]) -> Option<[u8; 32]> { + warn!("storage::changes_root() unimplemented"); + Some([0u8; 32]) + } + + /// Get the next key in storage after the given one in lexicographic order. + pub fn next_key(key: &[u8]) -> Option> { + debug!("next_key('{}')", encode_hex(key)); + with_externalities(|ext| ext.next_storage_key(key)) + .expect("`next_key` cannot be called outside of an Externalities-provided environment.") + } + + /// 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. + pub fn start_transaction() { + warn!("storage::start_transaction unimplemented"); + } + + /// 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. + pub fn rollback_transaction() { + warn!("storage::rollback_transaction unimplemented"); + } + + /// 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. + pub fn commit_transaction() { + warn!("storage::commit_transaction unimplemented"); + } +} + +pub mod default_child_storage { + use super::*; + + pub fn read( + storage_key: &[u8], + key: &[u8], + value_out: &mut [u8], + value_offset: u32, + ) -> Option { + // TODO unimplemented + warn!("default_child_storage::read() unimplemented"); + Some(0) + } + + pub fn get(storage_key: &[u8], key: &[u8]) -> Option> { + // TODO: unimplemented + warn!("default_child_storage::get() unimplemented"); + Some(vec![0, 1, 2, 3]) + } + + pub fn set(storage_key: &[u8], key: &[u8], value: &[u8]) { + warn!("default_child_storage::set() unimplemented"); + } + + pub fn clear(storage_key: &[u8], key: &[u8]) { + warn!("child storage::clear() unimplemented"); + } + + pub fn storage_kill_version_1(storage_key: &[u8]) { + warn!("child storage::storage_kill() unimplemented"); + } + + pub fn storage_kill_version_2(storage_key: &[u8], limit: Option) -> bool { + warn!("child storage::storage_kill() unimplemented"); + false + } + + /// Clear a child storage key. + /// + /// See `Storage` module `clear_prefix` documentation for `limit` usage. + pub fn storage_kill(storage_key: &[u8], limit: Option) -> KillStorageResult { + warn!("child storage::storage_kill() unimplemented"); + KillStorageResult::AllRemoved(0) + } + + pub fn exists(storage_key: &[u8], key: &[u8]) -> bool { + warn!("child storage::exists() unimplemented"); + false + } + + /// Clear child default key by prefix. + /// + /// Clear the child storage of each key-value pair where the key starts with the given `prefix`. + pub fn clear_prefix_version_1(storage_key: &[u8], prefix: &[u8]) { + warn!("child storage::clear_prefix() unimplemented"); + } + + /// Clear the child storage of each key-value pair where the key starts with the given `prefix`. + /// + /// See `Storage` module `clear_prefix` documentation for `limit` usage. + pub fn clear_prefix( + storage_key: &[u8], + prefix: &[u8], + limit: Option, + ) -> KillStorageResult { + warn!("child storage::clear_prefix() unimplemented"); + KillStorageResult::AllRemoved(0) + } + + pub fn root_version_1(storage_key: &[u8]) -> Vec { + warn!("child storage::root() unimplemented"); + vec![0, 1, 2, 3] + } + + pub fn root(storage_key: &[u8], version: StateVersion) -> Vec { + warn!("child storage::root() unimplemented"); + vec![0, 1, 2, 3] + } + + pub fn next_key(storage_key: &[u8], key: &[u8]) -> Option> { + warn!("child storage::next_key() unimplemented"); + Some(Vec::new()) + } +} + +pub mod trie { + use super::*; + + /// A trie root formed from the iterated items. + pub fn blake2_256_root_version_1(input: Vec<(Vec, Vec)>) -> H256 { + warn!("trie::blake2_256_root() unimplemented"); + H256::default() + } + + /// A trie root formed from the iterated items. + pub fn blake2_256_root(input: Vec<(Vec, Vec)>, version: StateVersion) -> H256 { + warn!("trie::blake2_256_root() unimplemented"); + H256::default() + } + + /// A trie root formed from the enumerated items. + pub fn blake2_256_ordered_root_version_1(input: Vec>) -> H256 { + warn!("trie::blake2_256_ordered_root() unimplemented"); + H256::default() + } + + /// A trie root formed from the enumerated items. + pub fn blake2_256_ordered_root(input: Vec>, version: StateVersion) -> H256 { + warn!("trie::blake2_256_ordered_root() unimplemented"); + H256::default() + } + + pub fn keccak_256_root_version_1(input: Vec<(Vec, Vec)>) -> H256 { + warn!("trie::keccak_256_root_version_1() unimplemented"); + H256::default() + } + + pub fn keccak_256_root(input: Vec<(Vec, Vec)>, version: StateVersion) -> H256 { + warn!("trie::keccak_256_root() unimplemented"); + H256::default() + } + + /// A trie root formed from the enumerated items. + pub fn keccak_256_ordered_root_version_1(input: Vec>) -> H256 { + warn!("trie::keccak_256_ordered_root() unimplemented"); + H256::default() + } + + /// A trie root formed from the enumerated items. + pub fn keccak_256_ordered_root(input: Vec>, version: StateVersion) -> H256 { + warn!("trie::keccak_256_ordered_root() unimplemented"); + H256::default() + } + + /// Verify trie proof + #[allow(unused)] + fn blake2_256_verify_proof_version_1( + root: H256, + proof: &[Vec], + key: &[u8], + value: &[u8], + ) -> bool { + warn!("trie::blake2_256_verify_proof() unimplemented"); + false + } + + /// Verify trie proof + #[allow(unused)] + fn blake2_256_verify_proof( + root: H256, + proof: &[Vec], + key: &[u8], + value: &[u8], + version: StateVersion, + ) -> bool { + warn!("trie::blake2_256_verify_proof() unimplemented"); + false + } + + /// Verify trie proof + #[allow(unused)] + fn keccak_256_verify_proof_version_1( + root: H256, + proof: &[Vec], + key: &[u8], + value: &[u8], + ) -> bool { + warn!("trie::keccak_256_verify_proof() unimplemented"); + false + } + + /// Verify trie proof + #[allow(unused)] + fn keccak_256_verify_proof( + root: H256, + proof: &[Vec], + key: &[u8], + value: &[u8], + version: StateVersion, + ) -> bool { + warn!("trie::keccak_256_verify_proof() unimplemented"); + false + } +} + +pub mod misc { + use super::*; + /// Print a number. + pub fn print_num(val: u64) { + debug!(target: "sgx-runtime", "{}", val); + } + + /// Print any valid `utf8` buffer. + pub fn print_utf8(utf8: &[u8]) { + if let Ok(data) = std::str::from_utf8(utf8) { + debug!(target: "sgx-runtime", "{}", data) + } + } + + /// Print any `u8` slice as hex. + pub fn print_hex(data: &[u8]) { + debug!(target: "sgx-runtime", "{:?}", data); + } + + pub fn runtime_version(wasm: &[u8]) -> Option> { + warn!("misc::runtime_version unimplemented!"); + Some([2u8; 32].to_vec()) + } +} + +/// Interfaces for working with crypto related types from within the sgx-runtime. +pub mod crypto { + use super::*; + use sp_core::H512; + pub fn ed25519_public_keys(id: KeyTypeId) -> Vec { + warn!("crypto::ed25519_public_keys unimplemented"); + vec![ed25519::Public::from_h256(H256::default())] + } + + pub fn ed25519_generate(id: KeyTypeId, seed: Option>) -> ed25519::Public { + warn!("crypto::ed25519_generate unimplemented"); + ed25519::Public::from_h256(H256::default()) + } + + pub fn ed25519_sign( + id: KeyTypeId, + pub_key: &ed25519::Public, + msg: &[u8], + ) -> Option { + warn!("crypto::ed25519_sign unimplemented"); + + Some(ed25519::Signature::from_raw(H512::default().into())) + } + + pub fn ed25519_verify(sig: &ed25519::Signature, msg: &[u8], pub_key: &ed25519::Public) -> bool { + ed25519::Pair::verify(sig, msg, pub_key) + } + + pub fn ed25519_batch_verify( + sig: &ed25519::Signature, + msg: &[u8], + pub_key: &ed25519::Public, + ) -> bool { + warn!("crypto::ed25519_batch_verify unimplemented"); + false + } + + /// 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. + pub fn sr25519_batch_verify( + sig: &sr25519::Signature, + msg: &[u8], + pub_key: &sr25519::Public, + ) -> bool { + warn!("crypto::sr25519_batch_verify unimplemented"); + false + } + /// Start verification extension. + pub fn start_batch_verify() { + warn!("crypto::start_batch_verify unimplemented"); + } + + pub fn finish_batch_verify() -> bool { + warn!("crypto::finish_batch_verify unimplemented"); + true + } + + pub fn sr25519_public_keys(id: KeyTypeId) -> Vec { + warn!("crypto::sr25519_public_key unimplemented"); + vec![sr25519::Public::from_h256(H256::default())] + } + + pub fn sr25519_generate(id: KeyTypeId, seed: Option>) -> sr25519::Public { + warn!("crypto::sr25519_generate unimplemented"); + sr25519::Public::from_h256(H256::default()) + } + + pub fn sr25519_sign( + id: KeyTypeId, + pubkey: &sr25519::Public, + msg: &[u8], + ) -> Option { + warn!("crypto::sr25519_sign unimplemented"); + Some(sr25519::Signature::from_raw(H512::default().into())) + } + + /// Verify `sr25519` signature. + /// + /// Returns `true` when the verification was successful. + pub fn sr25519_verify(sig: &sr25519::Signature, msg: &[u8], pub_key: &sr25519::Public) -> bool { + sr25519::Pair::verify(sig, msg, pub_key) + } + + /// Returns all `ecdsa` public keys for the given key id from the keystore. + pub fn ecdsa_public_keys(id: KeyTypeId) -> Vec { + warn!("crypto::ecdsa_public_keys unimplemented"); + Vec::new() + } + + /// Generate an `ecdsa` key for the given key type using an optional `seed` and + /// store it in the keystore. + /// + /// The `seed` needs to be a valid utf8. + /// + /// Returns the public key. + pub fn ecdsa_generate(id: KeyTypeId, seed: Option>) -> ecdsa::Public { + warn!("crypto::ecdsa_generate unimplemented"); + let raw: [u8; 33] = [0; 33]; + ecdsa::Public::from_raw(raw) + } + + /// Sign the given `msg` with the `ecdsa` key that corresponds to the given public key and + /// key type in the keystore. + /// + /// Returns the signature. + pub fn ecdsa_sign( + id: KeyTypeId, + pub_key: &ecdsa::Public, + msg: &[u8], + ) -> Option { + warn!("crypto::ecdsa_sign unimplemented"); + None + } + + /// Verify `ecdsa` signature. + /// + /// Returns `true` when the verification was successful. + pub 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. + pub fn ecdsa_batch_verify(sig: &ecdsa::Signature, msg: &[u8], pub_key: &ecdsa::Public) -> bool { + warn!("crypto::ecdsa_batch_verify unimplemented"); + false + } + + pub fn secp256k1_ecdsa_recover( + sig: &[u8; 65], + msg: &[u8; 32], + ) -> Result<[u8; 64], EcdsaVerifyError> { + let rs = libsecp256k1::Signature::parse_standard_slice(&sig[0..64]) + .map_err(|_| EcdsaVerifyError::BadRS)?; + let v = libsecp256k1::RecoveryId::parse(if sig[64] > 26 { sig[64] - 27 } else { sig[64] }) + .map_err(|_| EcdsaVerifyError::BadV)?; + let pubkey = libsecp256k1::recover(&libsecp256k1::Message::parse(msg), &rs, &v) + .map_err(|_| EcdsaVerifyError::BadSignature)?; + let mut res = [0u8; 64]; + res.copy_from_slice(&pubkey.serialize()[1..65]); + + Ok(res) + } + + pub fn secp256k1_ecdsa_recover_compressed( + sig: &[u8; 65], + msg: &[u8; 32], + ) -> Result<[u8; 33], EcdsaVerifyError> { + let rs = libsecp256k1::Signature::parse_standard_slice(&sig[0..64]) + .map_err(|_| EcdsaVerifyError::BadRS)?; + let v = libsecp256k1::RecoveryId::parse(if sig[64] > 26 { sig[64] - 27 } else { sig[64] }) + .map_err(|_| EcdsaVerifyError::BadV)?; + let pubkey = libsecp256k1::recover(&libsecp256k1::Message::parse(msg), &rs, &v) + .map_err(|_| EcdsaVerifyError::BadSignature)?; + Ok(pubkey.serialize_compressed()) + } +} + +/// Interface that provides functions for hashing with different algorithms. +pub mod hashing { + use super::*; + /// Conduct a 256-bit Keccak hash. + pub fn keccak_256(data: &[u8]) -> [u8; 32] { + debug!("keccak_256 of {}", encode_hex(data)); + let hash = sp_core::hashing::keccak_256(data); + debug!(" returning hash {}", encode_hex(&hash)); + hash + } + + /// Conduct a 512-bit Keccak hash. + pub fn keccak_512(data: &[u8]) -> [u8; 64] { + debug!("keccak_512 of {}", encode_hex(data)); + let hash = sp_core::hashing::keccak_512(data); + debug!(" returning hash {}", encode_hex(&hash)); + hash + } + + /// Conduct a 256-bit Sha2 hash. + pub fn sha2_256(data: &[u8]) -> [u8; 32] { + debug!("sha2_256 of {}", encode_hex(data)); + let hash = sp_core::hashing::sha2_256(data); + debug!(" returning hash {}", encode_hex(&hash)); + hash + } + + /// Conduct a 128-bit Blake2 hash. + pub fn blake2_128(data: &[u8]) -> [u8; 16] { + debug!("blake2_128 of {}", encode_hex(data)); + let hash = sp_core::hashing::blake2_128(data); + debug!(" returning hash {}", encode_hex(&hash)); + hash + } + + /// Conduct a 256-bit Blake2 hash. + pub fn blake2_256(data: &[u8]) -> [u8; 32] { + debug!("blake2_256 of {}", encode_hex(data)); + let hash = sp_core::hashing::blake2_256(data); + debug!(" returning hash {}", encode_hex(&hash)); + hash + } + + /// Conduct four XX hashes to give a 256-bit result. + pub fn twox_256(data: &[u8]) -> [u8; 32] { + debug!("twox_256 of {}", encode_hex(data)); + let hash = sp_core::hashing::twox_256(data); + debug!(" returning {}", encode_hex(&hash)); + hash + } + + /// Conduct two XX hashes to give a 128-bit result. + pub fn twox_128(data: &[u8]) -> [u8; 16] { + debug!("twox_128 of {}", encode_hex(data)); + let hash = sp_core::hashing::twox_128(data); + debug!(" returning {}", encode_hex(&hash)); + hash + } + + /// Conduct two XX hashes to give a 64-bit result. + pub fn twox_64(data: &[u8]) -> [u8; 8] { + debug!("twox_64 of {}", encode_hex(data)); + let hash = sp_core::hashing::twox_64(data); + debug!(" returning {}", encode_hex(&hash)); + hash + } +} + +/// Interface that provides transaction indexing API. +pub mod transaction_index { + use super::*; + /// Add transaction index. Returns indexed content hash. + #[allow(unused)] + fn index(extrinsic: u32, size: u32, context_hash: [u8; 32]) { + warn!("transaction_index::index unimplemented"); + } + + /// Conduct a 512-bit Keccak hash. + #[allow(unused)] + fn renew(extrinsic: u32, context_hash: [u8; 32]) { + warn!("transaction_index::renew unimplemented"); + } +} + +pub mod offchain_index { + use super::*; + /// Write a key value pair to the Offchain DB database in a buffered fashion. + pub fn set(key: &[u8], value: &[u8]) { + warn!("offchain_index::set unimplemented"); + } + + /// Remove a key and its associated value from the Offchain DB. + pub fn clear(key: &[u8]) { + warn!("offchain_index::clear unimplemented"); + } +} + +/// Interface that provides functions to access the offchain functionality. +/// +/// These functions are being made available to the sgx-runtime and are called by the sgx-runtime. +pub mod offchain { + use super::*; + + pub fn is_validator() -> bool { + warn!("offchain::is_validator unimplemented"); + false + } + + #[allow(clippy::result_unit_err)] + pub fn submit_transaction(data: Vec) -> Result<(), ()> { + warn!("offchain::submit_transaction unimplemented"); + Err(()) + } + + #[allow(clippy::result_unit_err)] + pub fn network_state() -> Result { + warn!("offchain::network_state unimplemented"); + Err(()) + } + + pub fn timestamp() -> offchain::Timestamp { + warn!("offchain::timestamp unimplemented"); + offchain::Timestamp::default() + } + + pub fn sleep_until(deadline: offchain::Timestamp) { + warn!("offchain::sleep_until unimplemented"); + } + + pub fn random_seed() -> [u8; 32] { + warn!("offchain::random_seed unimplemented"); + [0; 32] + } + + pub fn local_storage_set(kind: offchain::StorageKind, key: &[u8], value: &[u8]) { + warn!("offchain::local_storage_set unimplemented"); + } + pub fn local_storage_clear(kind: StorageKind, key: &[u8]) { + warn!("offchain::local_storage_clear unimplemented"); + } + + pub fn local_storage_compare_and_set( + kind: offchain::StorageKind, + key: &[u8], + old_value: Option>, + new_value: &[u8], + ) -> bool { + warn!("offchain::local_storage_compare_and_set unimplemented"); + false + } + + pub fn local_storage_get(kind: offchain::StorageKind, key: &[u8]) -> Option> { + warn!("offchain::local_storage_get unimplemented"); + None + } + + #[allow(clippy::result_unit_err)] + pub fn http_request_start( + method: &str, + uri: &str, + meta: &[u8], + ) -> Result { + warn!("offchain::http_request_start unimplemented"); + Err(()) + } + + #[allow(clippy::result_unit_err)] + pub fn http_request_add_header( + request_id: offchain::HttpRequestId, + name: &str, + value: &str, + ) -> Result<(), ()> { + warn!("offchain::http_request_add_header unimplemented"); + Err(()) + } + + pub fn http_request_write_body( + request_id: offchain::HttpRequestId, + chunk: &[u8], + deadline: Option, + ) -> Result<(), offchain::HttpError> { + warn!("offchain::http_request_write_body unimplemented"); + Err(offchain::HttpError::IoError) + } + + pub fn http_response_wait( + ids: &[offchain::HttpRequestId], + deadline: Option, + ) -> Vec { + warn!("offchain::http_response_wait unimplemented"); + Vec::new() + } + + pub fn http_response_headers(request_id: offchain::HttpRequestId) -> Vec<(Vec, Vec)> { + warn!("offchain::http_response_wait unimplemented"); + Vec::new() + } + + pub fn http_response_read_body( + request_id: offchain::HttpRequestId, + buffer: &mut [u8], + deadline: Option, + ) -> Result { + warn!("offchain::http_response_read_body unimplemented"); + Err(offchain::HttpError::IoError) + } +} + +/// Interface that provides functions for logging from within the sgx-runtime. +pub mod logging { + use super::*; + use sp_core::{LogLevel, LogLevelFilter}; + /// Request to print a log message on the host. + /// + /// Note that this will be only displayed if the host is enabled to display log messages with + /// given level and target. + /// + /// Instead of using directly, prefer setting up `RuntimeLogger` and using `log` macros. + pub fn log(level: LogLevel, target: &str, message: &[u8]) { + if let Ok(message) = std::str::from_utf8(message) { + // TODO remove this attention boost + println!("\x1b[0;36m[{}]\x1b[0m {}", target, message); + let level = match level { + LogLevel::Error => log::Level::Error, + LogLevel::Warn => log::Level::Warn, + LogLevel::Info => log::Level::Info, + LogLevel::Debug => log::Level::Debug, + LogLevel::Trace => log::Level::Trace, + }; + // FIXME: this logs with target sp_io::logging instead of the provided target! + log::log!(target: target, level, "{}", message,); + } + } + + /// Returns the max log level used by the host. + pub fn max_level() -> LogLevelFilter { + log::max_level().into() + } +} + +mod tracing_setup { + /// Initialize tracing of sp_tracing not necessary – noop. To enable build + /// without std and with the `with-tracing`-feature. + pub fn init_tracing() {} +} + +pub use tracing_setup::init_tracing; + +#[cfg(test)] +mod tests { + use super::*; + use sp_core::storage::well_known_keys::CODE; + + #[test] + fn storage_set_and_retrieve_works() { + let mut ext = SgxExternalities::default(); + + ext.execute_with(|| { + storage::set(b"doe".to_vec().as_slice(), b"reindeer".to_vec().as_slice()); + storage::set(b"dog".to_vec().as_slice(), b"puppy".to_vec().as_slice()); + storage::set(b"dogglesworth".to_vec().as_slice(), b"cat".to_vec().as_slice()); + }); + + ext.execute_with(|| { + assert!(storage::get(b"doe".to_vec().as_slice()).is_some()); + assert!(storage::get(b"dog".to_vec().as_slice()).is_some()); + assert!(storage::get(b"dogglesworth".to_vec().as_slice()).is_some()); + assert!(storage::get(b"boat".to_vec().as_slice()).is_none()); + }); + } + + #[test] + fn externalities_set_and_retrieve_code() { + let mut ext = SgxExternalities::default(); + + let code = vec![1, 2, 3]; + ext.insert(CODE.to_vec(), code.clone()); + + assert_eq!(ext.get(CODE).unwrap(), &code); + } + + #[test] + #[should_panic( + expected = "`set` cannot be called outside of an Externalities-provided environment." + )] + fn storage_set_without_externalities_panics() { + storage::set(b"hello", b"world"); + } + + #[test] + fn storage_set_and_next_key_works() { + let mut ext = SgxExternalities::default(); + + ext.execute_with(|| { + storage::set(b"doe".to_vec().as_slice(), b"reindeer".to_vec().as_slice()); + storage::set(b"dog".to_vec().as_slice(), b"puppy".to_vec().as_slice()); + storage::set(b"dogglesworth".to_vec().as_slice(), b"cat".to_vec().as_slice()); + }); + + ext.execute_with(|| { + assert_eq!(storage::next_key(&[]), Some(b"doe".to_vec())); + assert_eq!(storage::next_key(b"d".to_vec().as_slice()), Some(b"doe".to_vec())); + assert_eq!( + storage::next_key(b"dog".to_vec().as_slice()), + Some(b"dogglesworth".to_vec()) + ); + assert_eq!( + storage::next_key(b"doga".to_vec().as_slice()), + Some(b"dogglesworth".to_vec()) + ); + assert_eq!(storage::next_key(b"dogglesworth".to_vec().as_slice()), None); + assert_eq!(storage::next_key(b"e".to_vec().as_slice()), None); + }); + } + + #[test] + fn storage_next_key_in_empty_externatility_works() { + let mut ext = SgxExternalities::default(); + ext.execute_with(|| { + assert_eq!(storage::next_key(&[]), None); + assert_eq!(storage::next_key(b"dog".to_vec().as_slice()), None); + }); + } + + #[test] + #[should_panic( + expected = "`next_key` cannot be called outside of an Externalities-provided environment." + )] + fn storage_next_key_without_externalities_panics() { + storage::next_key(b"d".to_vec().as_slice()); + } +} diff --git a/bitacross-worker/core-primitives/teerex-storage/Cargo.toml b/bitacross-worker/core-primitives/teerex-storage/Cargo.toml new file mode 100644 index 0000000000..ca9bafb791 --- /dev/null +++ b/bitacross-worker/core-primitives/teerex-storage/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "itp-teerex-storage" +version = "0.9.0" +authors = ['Trust Computing GmbH ', 'Integritee AG '] +edition = "2021" + +[dependencies] +sp-std = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } + +#local deps +itp-storage = { path = "../storage", default-features = false } + +[features] +default = ["std"] +std = [ + "sp-std/std", + "itp-storage/std", +] diff --git a/bitacross-worker/core-primitives/teerex-storage/src/lib.rs b/bitacross-worker/core-primitives/teerex-storage/src/lib.rs new file mode 100644 index 0000000000..706d92fcb1 --- /dev/null +++ b/bitacross-worker/core-primitives/teerex-storage/src/lib.rs @@ -0,0 +1,35 @@ +#![cfg_attr(not(feature = "std"), no_std)] + +use itp_storage::{storage_map_key, storage_value_key, StorageHasher}; +use sp_std::prelude::Vec; + +pub struct TeeRexStorage; + +// Separate the prefix from the rest because in our case we changed the storage prefix due to +// the rebranding. With the below implementation of the `TeerexStorageKeys`, we could simply +// define another struct `OtherStorage`, implement `StoragePrefix` for it, and get the +// `TeerexStorageKeys` implementation for free. +pub trait StoragePrefix { + fn prefix() -> &'static str; +} + +impl StoragePrefix for TeeRexStorage { + fn prefix() -> &'static str { + "Teerex" + } +} + +pub trait TeerexStorageKeys { + fn enclave_count() -> Vec; + fn enclave(index: u64) -> Vec; +} + +impl TeerexStorageKeys for S { + fn enclave_count() -> Vec { + storage_value_key(Self::prefix(), "EnclaveCount") + } + + fn enclave(index: u64) -> Vec { + storage_map_key(Self::prefix(), "EnclaveRegistry", &index, &StorageHasher::Blake2_128Concat) + } +} diff --git a/bitacross-worker/core-primitives/test/Cargo.toml b/bitacross-worker/core-primitives/test/Cargo.toml new file mode 100644 index 0000000000..ff82183e77 --- /dev/null +++ b/bitacross-worker/core-primitives/test/Cargo.toml @@ -0,0 +1,73 @@ +[package] +name = "itp-test" +version = "0.9.0" +edition = "2021" + +[dependencies] +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +log = { version = "0.4", default-features = false } +sgx-crypto-helper = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git", package = "sgx_crypto_helper", default-features = false } + +# sgx deps +jsonrpc-core_sgx = { package = "jsonrpc-core", git = "https://github.com/scs/jsonrpc", branch = "no_std_v18", default-features = false, optional = true } +sgx_tstd = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git", optional = true } +sgx_types = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git" } + +# substrate deps +sp-core = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } +sp-io = { default-features = false, features = ["disable_oom", "disable_panic_handler", "disable_allocator"], path = "../../core-primitives/substrate-sgx/sp-io" } +sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } +sp-std = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } + +# local deps +itp-node-api = { path = "../node-api", default-features = false } +itp-node-api-metadata-provider = { path = "../node-api/metadata-provider", default-features = false } +itp-ocall-api = { path = "../ocall-api", default-features = false } +itp-sgx-crypto = { path = "../sgx/crypto", default-features = false } +itp-sgx-externalities = { default-features = false, path = "../substrate-sgx/externalities" } +itp-stf-interface = { path = "../stf-interface", default-features = false } +itp-stf-primitives = { path = "../stf-primitives", default-features = false } +itp-stf-state-handler = { path = "../stf-state-handler", default-features = false } +itp-storage = { path = "../storage", default-features = false } +itp-teerex-storage = { path = "../teerex-storage", default-features = false } +itp-time-utils = { path = "../time-utils", default-features = false } +itp-types = { path = "../types", default-features = false, features = ["test"] } + +# litentry +hex = { version = "0.4.3", default-features = false } +litentry-primitives = { path = "../../litentry/primitives", default-features = false } + +[features] +default = ["std"] +std = [ + "codec/std", + "itp-node-api-metadata-provider/std", + "itp-node-api/std", + "itp-ocall-api/std", + "itp-sgx-crypto/std", + "itp-sgx-externalities/std", + "itp-stf-interface/std", + "itp-stf-primitives/std", + "itp-stf-state-handler/std", + "itp-storage/std", + "itp-teerex-storage/std", + "itp-time-utils/std", + "itp-types/std", + "log/std", + "sp-core/std", + "sp-io/std", + "sp-runtime/std", + "sp-std/std", + "litentry-primitives/std", +] +sgx = [ + "itp-node-api/sgx", + "itp-node-api-metadata-provider/sgx", + "itp-sgx-crypto/sgx", + "itp-sgx-externalities/sgx", + "itp-stf-state-handler/sgx", + "itp-time-utils/sgx", + "jsonrpc-core_sgx", + "sgx_tstd", + "litentry-primitives/sgx", +] diff --git a/bitacross-worker/core-primitives/test/src/builders/enclave_gen_builder.rs b/bitacross-worker/core-primitives/test/src/builders/enclave_gen_builder.rs new file mode 100644 index 0000000000..85e807c628 --- /dev/null +++ b/bitacross-worker/core-primitives/test/src/builders/enclave_gen_builder.rs @@ -0,0 +1,63 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 itp_time_utils::now_as_millis; +use itp_types::{Enclave, PalletString}; + +/// Builder for a generic enclave (`EnclaveGen`) struct. +pub struct EnclaveGenBuilder { + pubkey: AccountId, + mr_enclave: [u8; 32], + timestamp: u64, + url: PalletString, // utf8 encoded url +} + +impl Default for EnclaveGenBuilder +where + AccountId: Default, +{ + fn default() -> Self { + EnclaveGenBuilder { + pubkey: AccountId::default(), + mr_enclave: [0u8; 32], + timestamp: now_as_millis(), + url: PalletString::default(), + } + } +} + +impl EnclaveGenBuilder { + pub fn with_account(mut self, account: AccountId) -> Self { + self.pubkey = account; + self + } + + pub fn with_url(mut self, url: PalletString) -> Self { + self.url = url; + self + } + + pub fn build(self) -> EnclaveGen { + EnclaveGen { + pubkey: self.pubkey, + mr_enclave: self.mr_enclave, + timestamp: self.timestamp, + url: self.url, + } + } +} diff --git a/bitacross-worker/core-primitives/test/src/builders/mod.rs b/bitacross-worker/core-primitives/test/src/builders/mod.rs new file mode 100644 index 0000000000..610066f015 --- /dev/null +++ b/bitacross-worker/core-primitives/test/src/builders/mod.rs @@ -0,0 +1,21 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 patterns for common structs used in tests. + +pub mod enclave_gen_builder; diff --git a/bitacross-worker/core-primitives/test/src/lib.rs b/bitacross-worker/core-primitives/test/src/lib.rs new file mode 100644 index 0000000000..87759a147b --- /dev/null +++ b/bitacross-worker/core-primitives/test/src/lib.rs @@ -0,0 +1,37 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +#![cfg_attr(not(feature = "std"), no_std)] + +//! Itp-test crate which contains mocks and soon some fixtures. + +#[cfg(all(feature = "std", feature = "sgx"))] +compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the same time"); + +extern crate alloc; + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +extern crate sgx_tstd as std; + +// re-export module to properly feature gate sgx and regular std environment +#[cfg(all(not(feature = "std"), feature = "sgx"))] +pub mod sgx_reexport_prelude { + pub use jsonrpc_core_sgx as jsonrpc_core; +} + +pub mod mock; diff --git a/bitacross-worker/core-primitives/test/src/mock/handle_state_mock.rs b/bitacross-worker/core-primitives/test/src/mock/handle_state_mock.rs new file mode 100644 index 0000000000..3776a0d9a9 --- /dev/null +++ b/bitacross-worker/core-primitives/test/src/mock/handle_state_mock.rs @@ -0,0 +1,241 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 = "sgx")] +use std::sync::{SgxRwLock as RwLock, SgxRwLockWriteGuard as RwLockWriteGuard}; + +#[cfg(feature = "std")] +use std::sync::{RwLock, RwLockWriteGuard}; + +use itp_sgx_externalities::{SgxExternalities as StfState, StateHash}; + +use itp_stf_state_handler::{ + error::{Error, Result}, + handle_state::HandleState, + query_shard_state::QueryShardState, +}; +use itp_types::{ShardIdentifier, H256}; +use std::{collections::HashMap, format, vec::Vec}; + +/// Mock implementation for the `HandleState` trait. +/// +/// Uses an in-memory state, in a `HashMap`. To be used in unit tests. +#[derive(Default)] +pub struct HandleStateMock { + state_map: RwLock>, +} + +impl HandleStateMock { + pub fn from_shard(shard: ShardIdentifier) -> Result { + let state_handler = HandleStateMock { state_map: Default::default() }; + state_handler.initialize_shard(shard)?; + Ok(state_handler) + } +} + +impl HandleState for HandleStateMock { + type WriteLockPayload = HashMap; + type StateT = StfState; + type HashType = H256; + + fn initialize_shard(&self, shard: ShardIdentifier) -> Result { + self.reset(StfState::default(), &shard) + } + + fn migrate_shard( + &self, + old_shard: ShardIdentifier, + new_shard: ShardIdentifier, + ) -> Result { + let (state, _) = self.load_cloned(&old_shard)?; + self.reset(state, &new_shard) + } + + fn execute_on_current(&self, shard: &ShardIdentifier, executing_function: E) -> Result + where + E: FnOnce(&Self::StateT, Self::HashType) -> R, + { + self.state_map + .read() + .unwrap() + .get(shard) + .map(|state| executing_function(state, state.hash())) + .ok_or_else(|| Error::Other(format!("shard is not initialized {:?}", shard).into())) + } + + fn load_cloned(&self, shard: &ShardIdentifier) -> Result<(Self::StateT, Self::HashType)> { + self.state_map + .read() + .unwrap() + .get(shard) + .cloned() + .map(|s| { + let state_hash = s.hash(); + (s, state_hash) + }) + .ok_or_else(|| Error::Other(format!("shard is not initialized {:?}", shard).into())) + } + + fn load_for_mutation( + &self, + shard: &ShardIdentifier, + ) -> Result<(RwLockWriteGuard<'_, Self::WriteLockPayload>, StfState)> { + let (initialized_state, _) = self.load_cloned(shard)?; + let write_lock = self.state_map.write().unwrap(); + Ok((write_lock, initialized_state)) + } + + fn write_after_mutation( + &self, + state: StfState, + mut state_lock: RwLockWriteGuard<'_, Self::WriteLockPayload>, + shard: &ShardIdentifier, + ) -> Result { + state_lock.insert(*shard, state.clone()); + Ok(state.hash()) + } + + fn reset(&self, state: Self::StateT, shard: &ShardIdentifier) -> Result { + let write_lock = self.state_map.write().unwrap(); + self.write_after_mutation(state, write_lock, shard) + } +} + +impl QueryShardState for HandleStateMock { + fn shard_exists(&self, shard: &ShardIdentifier) -> Result { + let state_map_lock = self.state_map.read().map_err(|_| Error::LockPoisoning)?; + Ok(state_map_lock.get(shard).is_some()) + } + + fn list_shards(&self) -> Result> { + Ok(self.state_map.read().unwrap().iter().map(|(k, _)| *k).collect()) + } +} + +// Since the mock itself has quite a bit of complexity, we also have tests for the mock. +#[cfg(feature = "sgx")] +pub mod tests { + + use super::*; + use crate::mock::stf_mock::StfMock; + use codec::{Decode, Encode}; + use itp_sgx_externalities::{SgxExternalities, SgxExternalitiesTrait, SgxExternalitiesType}; + use itp_stf_interface::InitState; + use itp_types::ShardIdentifier; + use sp_core::crypto::AccountId32; + + pub fn initialized_shards_list_is_empty() { + let state_handler = HandleStateMock::default(); + assert!(state_handler.list_shards().unwrap().is_empty()); + } + + pub fn shard_exists_after_inserting() { + let state_handler = HandleStateMock::default(); + let shard = ShardIdentifier::default(); + state_handler.initialize_shard(shard).unwrap(); + + assert!(state_handler.load_cloned(&shard).is_ok()); + assert!(state_handler.shard_exists(&shard).unwrap()); + } + + pub fn from_shard_works() { + let shard = ShardIdentifier::default(); + let state_handler = HandleStateMock::from_shard(shard).unwrap(); + + assert!(state_handler.load_cloned(&shard).is_ok()); + assert!(state_handler.shard_exists(&shard).unwrap()); + } + + pub fn initialize_creates_default_state() { + let state_handler = HandleStateMock::default(); + let shard = ShardIdentifier::default(); + state_handler.initialize_shard(shard).unwrap(); + + let loaded_state_result = state_handler.load_cloned(&shard); + + assert!(loaded_state_result.is_ok()); + } + + pub fn load_mutate_and_write_works() { + let state_handler = HandleStateMock::default(); + let shard = ShardIdentifier::default(); + state_handler.initialize_shard(shard).unwrap(); + + let (lock, mut state) = state_handler.load_for_mutation(&shard).unwrap(); + + let (key, value) = ("my_key", "my_value"); + state.insert(key.encode(), value.encode()); + + state_handler.write_after_mutation(state, lock, &shard).unwrap(); + + let (updated_state, _) = state_handler.load_cloned(&shard).unwrap(); + + let inserted_value = + updated_state.get(key.encode().as_slice()).expect("value for key should exist"); + assert_eq!(*inserted_value, value.encode()); + } + + pub fn ensure_subsequent_state_loads_have_same_hash() { + let state_handler = HandleStateMock::default(); + let shard = ShardIdentifier::default(); + state_handler.initialize_shard(shard).unwrap(); + + let (lock, _) = state_handler.load_for_mutation(&shard).unwrap(); + let initial_state = StfMock::init_state(AccountId32::new([0u8; 32])); + let state_hash_before_execution = initial_state.hash(); + state_handler.write_after_mutation(initial_state, lock, &shard).unwrap(); + + let (_, loaded_state_hash) = state_handler.load_cloned(&shard).unwrap(); + + assert_eq!(state_hash_before_execution, loaded_state_hash); + } + + pub fn ensure_encode_and_encrypt_does_not_affect_state_hash() { + let state = StfMock::init_state(AccountId32::new([0u8; 32])); + let state_hash_before_execution = state.hash(); + + let encoded_state = state.state.encode(); + let decoded_state: SgxExternalitiesType = decode(encoded_state); + let decoded_state_hash = SgxExternalities::new(decoded_state).hash(); + + assert_eq!(state_hash_before_execution, decoded_state_hash); + } + + pub fn migrate_shard_works() { + let state_handler = HandleStateMock::default(); + let old_shard = ShardIdentifier::default(); + let bytes = hex::decode("91de6f606be264f089b155256385470f5395969386894ffba38775442f508ee2") + .unwrap(); + let new_shard = ShardIdentifier::from_slice(&bytes); + state_handler.initialize_shard(old_shard).unwrap(); + + let (lock, mut state) = state_handler.load_for_mutation(&old_shard).unwrap(); + let (key, value) = ("my_key", "my_value"); + state.insert(key.encode(), value.encode()); + state_handler.write_after_mutation(state, lock, &old_shard).unwrap(); + + state_handler.migrate_shard(old_shard, new_shard).unwrap(); + let (new_state, _) = state_handler.load_cloned(&new_shard).unwrap(); + let inserted_value = + new_state.get(key.encode().as_slice()).expect("value for key should exist"); + assert_eq!(*inserted_value, value.encode()); + } + + fn decode(encoded: Vec) -> T { + T::decode(&mut encoded.as_slice()).unwrap() + } +} diff --git a/bitacross-worker/core-primitives/test/src/mock/metrics_ocall_mock.rs b/bitacross-worker/core-primitives/test/src/mock/metrics_ocall_mock.rs new file mode 100644 index 0000000000..14cd8e67c5 --- /dev/null +++ b/bitacross-worker/core-primitives/test/src/mock/metrics_ocall_mock.rs @@ -0,0 +1,54 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 = "sgx")] +use std::sync::SgxRwLock as RwLock; + +#[cfg(feature = "std")] +use std::sync::RwLock; + +use codec::Encode; +use itp_ocall_api::EnclaveMetricsOCallApi; +use sgx_types::SgxResult; +use std::vec::Vec; + +/// Metrics o-call mock. +#[derive(Default)] +pub struct MetricsOCallMock { + metric_updates: RwLock>>, +} + +impl Clone for MetricsOCallMock { + fn clone(&self) -> Self { + MetricsOCallMock { + metric_updates: RwLock::new(self.metric_updates.read().unwrap().clone()), + } + } +} + +impl MetricsOCallMock { + pub fn get_metrics_updates(&self) -> Vec> { + self.metric_updates.read().unwrap().clone() + } +} + +impl EnclaveMetricsOCallApi for MetricsOCallMock { + fn update_metric(&self, metric: Metric) -> SgxResult<()> { + self.metric_updates.write().unwrap().push(metric.encode()); + Ok(()) + } +} diff --git a/bitacross-worker/core-primitives/test/src/mock/mod.rs b/bitacross-worker/core-primitives/test/src/mock/mod.rs new file mode 100644 index 0000000000..a59c988a59 --- /dev/null +++ b/bitacross-worker/core-primitives/test/src/mock/mod.rs @@ -0,0 +1,23 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 handle_state_mock; +pub mod metrics_ocall_mock; +pub mod onchain_mock; +pub mod shielding_crypto_mock; +pub mod sidechain_ocall_api_mock; +pub mod stf_mock; diff --git a/bitacross-worker/core-primitives/test/src/mock/onchain_mock.rs b/bitacross-worker/core-primitives/test/src/mock/onchain_mock.rs new file mode 100644 index 0000000000..22744289b5 --- /dev/null +++ b/bitacross-worker/core-primitives/test/src/mock/onchain_mock.rs @@ -0,0 +1,243 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 core::fmt::Debug; +use itp_ocall_api::{ + EnclaveAttestationOCallApi, EnclaveMetricsOCallApi, EnclaveOnChainOCallApi, + EnclaveSidechainOCallApi, +}; +use itp_storage::Error::StorageValueUnavailable; +use itp_teerex_storage::{TeeRexStorage, TeerexStorageKeys}; +use itp_types::{ + parentchain::ParentchainId, storage::StorageEntryVerified, BlockHash, Enclave, ShardIdentifier, + WorkerRequest, WorkerResponse, +}; +use sgx_types::*; +use sp_core::H256; +use sp_runtime::{traits::Header as HeaderTrait, AccountId32, OpaqueExtrinsic}; +use sp_std::prelude::*; +use std::{collections::HashMap, string::String}; + +#[derive(Default, Clone, Debug)] +pub struct OnchainMock { + inner: HashMap, Vec>, + mr_enclave: [u8; SGX_HASH_SIZE], +} + +impl OnchainMock { + pub fn with_storage_entries_at_header, V: Encode>( + mut self, + header: &Header, + entries: Vec<(Vec, V)>, + ) -> Self { + for (key, value) in entries.into_iter() { + self.insert_at_header(header, key, value.encode()); + } + self + } + + pub fn add_validateer_set>( + mut self, + header: &Header, + set: Option>, + ) -> Self { + let set = set.unwrap_or_else(validateer_set); + self.insert_at_header(header, TeeRexStorage::enclave_count(), (set.len() as u64).encode()); + self.with_storage_entries_at_header(header, into_key_value_storage(set)) + } + + pub fn with_mr_enclave(mut self, mr_enclave: [u8; SGX_HASH_SIZE]) -> Self { + self.mr_enclave = mr_enclave; + self + } + + pub fn insert_at_header>( + &mut self, + header: &Header, + key: Vec, + value: Vec, + ) { + let key_with_header = (header, key).encode(); + self.inner.insert(key_with_header, value); + } + + pub fn get_at_header>( + &self, + header: &Header, + key: &[u8], + ) -> Option<&Vec> { + let key_with_header = (header, key).encode(); + self.inner.get(&key_with_header) + } +} + +impl EnclaveAttestationOCallApi for OnchainMock { + fn sgx_init_quote(&self) -> SgxResult<(sgx_target_info_t, sgx_epid_group_id_t)> { + todo!() + } + + fn get_ias_socket(&self) -> SgxResult { + Ok(42) + } + + fn get_quote( + &self, + _sig_rl: Vec, + _report: sgx_report_t, + _sign_type: sgx_quote_sign_type_t, + _spid: sgx_spid_t, + _quote_nonce: sgx_quote_nonce_t, + ) -> SgxResult<(sgx_report_t, Vec)> { + todo!() + } + + fn get_dcap_quote(&self, _report: sgx_report_t, _quote_size: u32) -> SgxResult> { + todo!() + } + + fn get_qve_report_on_quote( + &self, + _quote: Vec, + _current_time: i64, + _quote_collateral: sgx_ql_qve_collateral_t, + _qve_report_info: sgx_ql_qe_report_info_t, + _supplemental_data_size: u32, + ) -> SgxResult<(u32, sgx_ql_qv_result_t, sgx_ql_qe_report_info_t, Vec)> { + todo!() + } + + fn get_update_info( + &self, + _platform_info: sgx_platform_info_t, + _enclave_trusted: i32, + ) -> SgxResult { + todo!() + } + + fn get_mrenclave_of_self(&self) -> SgxResult { + Ok(sgx_measurement_t { m: self.mr_enclave }) + } +} + +impl EnclaveSidechainOCallApi for OnchainMock { + fn propose_sidechain_blocks( + &self, + _signed_blocks: Vec, + ) -> SgxResult<()> { + Ok(()) + } + + fn store_sidechain_blocks( + &self, + _signed_blocks: Vec, + ) -> SgxResult<()> { + Ok(()) + } + + fn fetch_sidechain_blocks_from_peer( + &self, + _last_imported_block_hash: BlockHash, + _maybe_until_block_hash: Option, + _shard_identifier: ShardIdentifier, + ) -> SgxResult> { + Ok(Vec::new()) + } + + fn get_trusted_peers_urls(&self) -> SgxResult> { + Ok(Vec::default()) + } +} + +impl EnclaveMetricsOCallApi for OnchainMock { + fn update_metric(&self, _metric: Metric) -> SgxResult<()> { + Ok(()) + } +} + +impl EnclaveOnChainOCallApi for OnchainMock { + fn send_to_parentchain( + &self, + _extrinsics: Vec, + _: &ParentchainId, + _: bool, + ) -> SgxResult<()> { + Ok(()) + } + + fn worker_request( + &self, + _req: Vec, + _: &ParentchainId, + ) -> SgxResult>> { + Ok(Vec::new()) + } + + fn get_storage_verified, V: Decode>( + &self, + storage_hash: Vec, + header: &Header, + parentchain_id: &ParentchainId, + ) -> Result, itp_ocall_api::Error> { + self.get_multiple_storages_verified(vec![storage_hash], header, parentchain_id)? + .into_iter() + .next() + .ok_or_else(|| itp_ocall_api::Error::Storage(StorageValueUnavailable)) + } + + fn get_multiple_storages_verified, V: Decode>( + &self, + storage_hashes: Vec>, + header: &Header, + _: &ParentchainId, + ) -> Result>, itp_ocall_api::Error> { + let mut entries = Vec::with_capacity(storage_hashes.len()); + for hash in storage_hashes.into_iter() { + let value = self + .get_at_header(header, &hash) + .map(|val| Decode::decode(&mut val.as_slice())) + .transpose() + .map_err(itp_ocall_api::Error::Codec)?; + + entries.push(StorageEntryVerified::new(hash, value)) + } + Ok(entries) + } + + fn get_storage_keys(&self, _key_prefix: Vec) -> Result>, itp_ocall_api::Error> { + Ok(Default::default()) + } +} + +pub fn validateer_set() -> Vec { + let default_enclave = Enclave::new( + AccountId32::from([0; 32]), + Default::default(), + Default::default(), + Default::default(), + ); + vec![default_enclave.clone(), default_enclave.clone(), default_enclave.clone(), default_enclave] +} + +fn into_key_value_storage(validateers: Vec) -> Vec<(Vec, Enclave)> { + validateers + .into_iter() + .enumerate() + .map(|(i, e)| (TeeRexStorage::enclave(i as u64 + 1), e)) + .collect() +} diff --git a/bitacross-worker/core-primitives/test/src/mock/shielding_crypto_mock.rs b/bitacross-worker/core-primitives/test/src/mock/shielding_crypto_mock.rs new file mode 100644 index 0000000000..0006ba1245 --- /dev/null +++ b/bitacross-worker/core-primitives/test/src/mock/shielding_crypto_mock.rs @@ -0,0 +1,58 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 itp_sgx_crypto::{ + ed25519_derivation::DeriveEd25519, ShieldingCryptoDecrypt, ShieldingCryptoEncrypt, +}; +use sgx_crypto_helper::{rsa3072::Rsa3072KeyPair, RsaKeyPair}; +use sp_core::ed25519::Pair as Ed25519Pair; +use std::vec::Vec; + +#[derive(Clone)] +pub struct ShieldingCryptoMock { + key: Rsa3072KeyPair, +} + +impl Default for ShieldingCryptoMock { + fn default() -> Self { + ShieldingCryptoMock { + key: Rsa3072KeyPair::new().expect("default RSA3072 key for shielding key mock"), + } + } +} + +impl ShieldingCryptoEncrypt for ShieldingCryptoMock { + type Error = itp_sgx_crypto::Error; + + fn encrypt(&self, data: &[u8]) -> Result, Self::Error> { + self.key.encrypt(data) + } +} + +impl ShieldingCryptoDecrypt for ShieldingCryptoMock { + type Error = itp_sgx_crypto::Error; + + fn decrypt(&self, data: &[u8]) -> Result, Self::Error> { + self.key.decrypt(data) + } +} + +impl DeriveEd25519 for ShieldingCryptoMock { + fn derive_ed25519(&self) -> Result { + self.key.derive_ed25519() + } +} diff --git a/bitacross-worker/core-primitives/test/src/mock/sidechain_ocall_api_mock.rs b/bitacross-worker/core-primitives/test/src/mock/sidechain_ocall_api_mock.rs new file mode 100644 index 0000000000..0210e3bd85 --- /dev/null +++ b/bitacross-worker/core-primitives/test/src/mock/sidechain_ocall_api_mock.rs @@ -0,0 +1,124 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 = "sgx")] +use std::sync::SgxRwLock as RwLock; + +#[cfg(feature = "std")] +use std::sync::RwLock; + +use codec::{Decode, Encode}; +use core::marker::PhantomData; +use itp_ocall_api::{EnclaveMetricsOCallApi, EnclaveSidechainOCallApi}; +use itp_types::{BlockHash, ShardIdentifier}; +use sgx_types::{sgx_status_t, SgxResult}; +use std::{string::String, vec::Vec}; + +pub struct SidechainOCallApiMock { + fetch_from_peer_blocks: Option>, + number_of_fetch_calls: RwLock, + _phantom: PhantomData, +} + +impl SidechainOCallApiMock +where + SignedSidechainBlockType: Clone + Encode + Decode + Send + Sync, +{ + pub fn with_peer_fetch_blocks(mut self, blocks: Vec) -> Self { + self.fetch_from_peer_blocks = Some(blocks); + self + } + + pub fn number_of_fetch_calls(&self) -> usize { + *self.number_of_fetch_calls.read().unwrap() + } +} + +impl Default for SidechainOCallApiMock { + fn default() -> Self { + SidechainOCallApiMock { + fetch_from_peer_blocks: None, + number_of_fetch_calls: RwLock::new(0), + _phantom: Default::default(), + } + } +} + +impl Clone for SidechainOCallApiMock +where + SignedSidechainBlockType: Clone + Encode + Decode + Send + Sync, +{ + fn clone(&self) -> Self { + SidechainOCallApiMock { + fetch_from_peer_blocks: self.fetch_from_peer_blocks.clone(), + number_of_fetch_calls: RwLock::new(*self.number_of_fetch_calls.read().unwrap()), + _phantom: self._phantom, + } + } +} + +impl EnclaveMetricsOCallApi + for SidechainOCallApiMock +where + SignedSidechainBlockType: Clone + Encode + Decode + Send + Sync, +{ + fn update_metric(&self, _metric: Metric) -> SgxResult<()> { + Ok(()) + } +} + +impl EnclaveSidechainOCallApi + for SidechainOCallApiMock +where + SignedSidechainBlockType: Clone + Encode + Decode + Send + Sync, +{ + fn propose_sidechain_blocks( + &self, + _signed_blocks: Vec, + ) -> SgxResult<()> { + Ok(()) + } + + fn store_sidechain_blocks( + &self, + _signed_blocks: Vec, + ) -> SgxResult<()> { + Ok(()) + } + + fn fetch_sidechain_blocks_from_peer( + &self, + _last_imported_block_hash: BlockHash, + _maybe_until_block_hash: Option, + _shard_identifier: ShardIdentifier, + ) -> SgxResult> { + let mut number_of_fetch_calls_lock = self.number_of_fetch_calls.write().unwrap(); + *number_of_fetch_calls_lock += 1; + + match &self.fetch_from_peer_blocks { + Some(blocks) => Ok(blocks + .iter() + .map(|b| SignedSidechainBlock::decode(&mut b.encode().as_slice()).unwrap()) + .collect()), + None => Err(sgx_status_t::SGX_ERROR_UNEXPECTED), + } + } + + fn get_trusted_peers_urls(&self) -> SgxResult> { + Ok(Vec::default()) + } +} diff --git a/bitacross-worker/core-primitives/test/src/mock/stf_mock.rs b/bitacross-worker/core-primitives/test/src/mock/stf_mock.rs new file mode 100644 index 0000000000..d5e9ec9b72 --- /dev/null +++ b/bitacross-worker/core-primitives/test/src/mock/stf_mock.rs @@ -0,0 +1,297 @@ +/* + Copyright 2021 Integritee AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 alloc::{boxed::Box, sync::Arc}; +use codec::{Decode, Encode}; +use core::fmt::Debug; +use itp_node_api::metadata::metadata_mocks::NodeMetadataMock; +use itp_node_api_metadata_provider::NodeMetadataRepository; +use itp_sgx_externalities::{SgxExternalities, SgxExternalitiesDiffType, SgxExternalitiesTrait}; +use itp_stf_interface::{ + runtime_upgrade::RuntimeUpgradeInterface, ExecuteCall, InitState, StateCallInterface, + StateGetterInterface, UpdateState, +}; +use itp_stf_primitives::{ + traits::{ + GetterAuthorization, PoolTransactionValidation, TrustedCallSigning, TrustedCallVerification, + }, + types::{KeyPair, Nonce, TrustedOperation}, +}; +use itp_types::{ + parentchain::{ParentchainCall, ParentchainId}, + AccountId, Balance, Index, ShardIdentifier, H256, +}; +use litentry_primitives::{Identity, LitentryMultiSignature}; +use log::*; +use sp_core::{sr25519, Pair}; +use sp_runtime::transaction_validity::{ + TransactionValidityError, UnknownTransaction, ValidTransaction, +}; +use sp_std::{vec, vec::Vec}; +use std::{thread::sleep, time::Duration}; + +// a few dummy types +type NodeMetadataRepositoryMock = NodeMetadataRepository; + +#[derive(Debug, PartialEq, Eq, Encode)] +pub enum StfMockError { + Dummy, +} +#[derive(Encode, Decode, Clone, Debug, PartialEq, Eq)] +pub struct StfMock { + state: SgxExternalities, +} + +impl UpdateState for StfMock { + fn apply_state_diff(_state: &mut SgxExternalities, _map_update: SgxExternalitiesDiffType) {} + + fn storage_hashes_to_update_on_block(_parentchain_id: &ParentchainId) -> Vec> { + vec![] + } +} + +impl StateCallInterface + for StfMock +{ + type Error = StfMockError; + type Result = (); + + fn execute_call( + state: &mut SgxExternalities, + shard: &ShardIdentifier, + call: TrustedCallSignedMock, + top_hash: H256, + calls: &mut Vec, + node_metadata_repo: Arc, + ) -> Result<(), Self::Error> { + state.execute_with(|| call.execute(shard, top_hash, calls, node_metadata_repo)) + } +} + +impl InitState for StfMock { + fn init_state(_enclave_account: AccountId) -> SgxExternalities { + SgxExternalities::new(Default::default()) + } +} + +impl StateGetterInterface for StfMock { + fn execute_getter(_state: &mut SgxExternalities, _getter: GetterMock) -> Option> { + Some(vec![42]) + } +} + +impl RuntimeUpgradeInterface for StfMock { + type Error = StfMockError; + fn on_runtime_upgrade(_state: &mut SgxExternalities) -> Result<(), Self::Error> { + Ok(()) + } +} + +pub type TrustedOperationMock = TrustedOperation; + +#[derive(Encode, Decode, Clone, Debug, PartialEq, Eq)] +#[allow(non_camel_case_types)] +pub enum TrustedCallMock { + noop(Identity), + balance_transfer(Identity, AccountId, Balance), + waste_time_ms(Identity, u64), +} + +impl TrustedCallMock { + pub fn sender_identity(&self) -> &Identity { + match self { + Self::noop(sender_identity) => sender_identity, + Self::balance_transfer(sender_identity, ..) => sender_identity, + Self::waste_time_ms(sender_identity, ..) => sender_identity, + } + } +} + +impl TrustedCallSigning for TrustedCallMock { + fn sign( + &self, + pair: &KeyPair, + nonce: Index, + mrenclave: &[u8; 32], + shard: &ShardIdentifier, + ) -> TrustedCallSignedMock { + let mut payload = self.encode(); + payload.append(&mut nonce.encode()); + payload.append(&mut mrenclave.encode()); + payload.append(&mut shard.encode()); + + TrustedCallSignedMock { + call: self.clone(), + nonce, + signature: pair.sign(payload.as_slice()), + } + } +} + +#[derive(Encode, Decode, Clone, Debug, PartialEq, Eq)] +pub struct TrustedCallSignedMock { + pub call: TrustedCallMock, + pub nonce: Index, + pub signature: LitentryMultiSignature, +} + +impl TrustedCallSignedMock { + pub fn new(call: TrustedCallMock, nonce: Index, signature: LitentryMultiSignature) -> Self { + TrustedCallSignedMock { call, nonce, signature } + } + + pub fn into_trusted_operation( + self, + direct: bool, + ) -> TrustedOperation { + match direct { + true => TrustedOperation::direct_call(self), + false => TrustedOperation::indirect_call(self), + } + } +} + +impl Default for TrustedCallSignedMock { + fn default() -> Self { + mock_trusted_call_signed(0) + } +} + +impl ExecuteCall for TrustedCallSignedMock { + type Error = StfMockError; + type Result = (); + + fn execute( + self, + _shard: &ShardIdentifier, + _top_hash: H256, + _calls: &mut Vec, + _node_metadata_repo: Arc, + ) -> Result<(), Self::Error> { + match self.call { + TrustedCallMock::noop(_) => Ok(()), + TrustedCallMock::balance_transfer(_, _, balance) => { + info!("touching state"); + sp_io::storage::set(b"dummy_key", &balance.encode()); + Ok(()) + }, + TrustedCallMock::waste_time_ms(_, ms) => { + sp_io::storage::set(b"dummy_key_waste_time", &42u8.encode()); + info!("executing stf call waste_time_ms. sleeping for {}ms", ms); + sleep(Duration::from_millis(ms)); + Ok(()) + }, + } + } + + fn get_storage_hashes_to_update(self) -> Vec> { + Vec::new() + } +} + +impl TrustedCallVerification for TrustedCallSignedMock { + fn sender_identity(&self) -> &Identity { + self.call.sender_identity() + } + + fn nonce(&self) -> Index { + self.nonce + } + + fn verify_signature(&self, _mrenclave: &[u8; 32], _shard: &ShardIdentifier) -> bool { + true + } +} + +#[derive(Encode, Decode, Clone, Debug, PartialEq, Eq)] +#[allow(non_camel_case_types)] +pub enum GetterMock { + public(PublicGetterMock), + trusted(TrustedGetterSignedMock), +} + +impl Default for GetterMock { + fn default() -> Self { + GetterMock::public(PublicGetterMock::some_value) + } +} + +impl PoolTransactionValidation for GetterMock { + fn validate(&self) -> Result { + Err(TransactionValidityError::Unknown(UnknownTransaction::CannotLookup)) + } +} + +impl GetterAuthorization for GetterMock { + fn is_authorized(&self) -> bool { + match self { + Self::trusted(tgs) => tgs.signature, + Self::public(_) => true, + } + } +} + +#[derive(Encode, Decode, Clone, Debug, PartialEq, Eq)] +#[allow(non_camel_case_types)] +pub enum PublicGetterMock { + some_value, +} + +#[derive(Encode, Decode, Clone, Debug, PartialEq, Eq)] +#[allow(non_camel_case_types)] +pub enum TrustedGetterMock { + some_value, +} + +#[derive(Encode, Decode, Clone, Debug, PartialEq, Eq)] +pub struct TrustedGetterSignedMock { + pub getter: TrustedGetterMock, + pub signature: bool, +} + +const MOCK_SEED: [u8; 32] = *b"34567890123456789012345678901234"; + +pub fn mock_key_pair() -> KeyPair { + KeyPair::Sr25519(Box::new(sr25519::Pair::from_seed(&MOCK_SEED))) +} + +pub fn mock_trusted_call_signed(nonce: Nonce) -> TrustedCallSignedMock { + TrustedCallMock::balance_transfer( + mock_key_pair().account_id().into(), + mock_key_pair().account_id(), + 42, + ) + .sign(&mock_key_pair(), nonce, &[0u8; 32], &ShardIdentifier::default()) +} + +pub fn mock_top_direct_trusted_call_signed() -> TrustedOperationMock { + TrustedOperationMock::direct_call(mock_trusted_call_signed(0)) +} + +pub fn mock_top_indirect_trusted_call_signed() -> TrustedOperationMock { + TrustedOperationMock::indirect_call(mock_trusted_call_signed(0)) +} + +pub fn mock_top_trusted_getter_signed() -> TrustedOperationMock { + TrustedOperationMock::get(GetterMock::trusted(TrustedGetterSignedMock { + getter: TrustedGetterMock::some_value, + signature: true, + })) +} + +pub fn mock_top_public_getter() -> TrustedOperationMock { + TrustedOperationMock::get(GetterMock::public(PublicGetterMock::some_value)) +} diff --git a/bitacross-worker/core-primitives/time-utils/Cargo.toml b/bitacross-worker/core-primitives/time-utils/Cargo.toml new file mode 100644 index 0000000000..7052ee18d7 --- /dev/null +++ b/bitacross-worker/core-primitives/time-utils/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "itp-time-utils" +version = "0.9.0" +authors = ['Trust Computing GmbH ', 'Integritee AG '] +edition = "2021" + +[dependencies] +chrono = { version = "0.4.19", features = ["alloc"], optional = true } + +chrono_sgx = { package = "chrono", git = "https://github.com/mesalock-linux/chrono-sgx", optional = true } +sgx_tstd = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git", optional = true } + +[features] +default = ["std"] +std = [ + "chrono", +] +sgx = [ + "sgx_tstd", + "chrono_sgx", +] diff --git a/bitacross-worker/core-primitives/time-utils/src/lib.rs b/bitacross-worker/core-primitives/time-utils/src/lib.rs new file mode 100644 index 0000000000..51ac211d72 --- /dev/null +++ b/bitacross-worker/core-primitives/time-utils/src/lib.rs @@ -0,0 +1,79 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 time utility functions. +#![feature(trait_alias)] +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg(all(feature = "std", feature = "sgx"))] +compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the same time"); + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +extern crate sgx_tstd as std; + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +extern crate chrono_sgx as chrono; + +use chrono::{offset::FixedOffset, DateTime, Utc}; +use std::{ + string::String, + time::{Duration, SystemTime}, +}; + +/// Returns the current timestamp based on the unix epoch in seconds. +pub fn now_as_secs() -> u64 { + duration_now().as_secs() +} + +/// Returns current duration since unix epoch in millis as u64. +pub fn now_as_millis() -> u64 { + duration_now().as_millis() as u64 +} + +pub fn now_as_iso8601() -> String { + let date_time: DateTime = SystemTime::now().into(); + date_time.to_rfc3339() +} + +pub fn from_iso8601(datetime_str: &str) -> Option> { + DateTime::parse_from_rfc3339(datetime_str).ok() +} + +/// Returns the current timestamp based on the unix epoch in nanoseconds. +pub fn now_as_nanos() -> u128 { + duration_now().as_nanos() +} + +/// Calculates the remaining time from now to `until`. +pub fn remaining_time(until: Duration) -> Option { + duration_difference(duration_now(), until) +} + +/// Calculate the difference in duration between `from` and `to`. +/// Returns `None` if `to` < `from`. +pub fn duration_difference(from: Duration, to: Duration) -> Option { + to.checked_sub(from) +} + +/// Returns current duration since unix epoch with SystemTime::now(). +/// Note: subsequent calls are not guaranteed to be monotonic. +/// (https://doc.rust-lang.org/std/time/struct.SystemTime.html) +pub fn duration_now() -> Duration { + let now = SystemTime::now(); + now.duration_since(SystemTime::UNIX_EPOCH).unwrap_or_else(|e| { + panic!("Current time {:?} is before unix epoch. Something is wrong: {:?}", now, e) + }) +} diff --git a/bitacross-worker/core-primitives/top-pool-author/Cargo.toml b/bitacross-worker/core-primitives/top-pool-author/Cargo.toml new file mode 100644 index 0000000000..191ae19ea0 --- /dev/null +++ b/bitacross-worker/core-primitives/top-pool-author/Cargo.toml @@ -0,0 +1,78 @@ +[package] +name = "itp-top-pool-author" +version = "0.9.0" +authors = ['Trust Computing GmbH ', 'Integritee AG '] +edition = "2021" + +[dependencies] +# sgx dependencies +sgx_tstd = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git", optional = true } + +# local dependencies +itp-enclave-metrics = { path = "../enclave-metrics", default-features = false } +itp-ocall-api = { path = "../ocall-api", default-features = false } +itp-sgx-crypto = { path = "../sgx/crypto", default-features = false } +itp-stf-primitives = { path = "../stf-primitives", default-features = false } +itp-stf-state-handler = { path = "../stf-state-handler", default-features = false } +itp-test = { path = "../test", default-features = false, optional = true } +itp-top-pool = { path = "../top-pool", default-features = false } +itp-types = { path = "../types", default-features = false } + +# sgx enabled external libraries +jsonrpc-core_sgx = { package = "jsonrpc-core", git = "https://github.com/scs/jsonrpc", branch = "no_std_v18", default-features = false, optional = true } + +# std compatible external libraries (make sure these versions match with the sgx-enabled ones above) +jsonrpc-core = { version = "18", optional = true } + +# no-std compatible libraries +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +derive_more = { version = "0.99.5" } +log = { version = "0.4", default-features = false } +sp-core = { default-features = false, features = ["full_crypto"], git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } +sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } + +lazy_static = { version = "1.1.0", optional = true } + +# litentry +itp-utils = { path = "../utils", default-features = false } +litentry-primitives = { path = "../../litentry/primitives", default-features = false } + +[dev-dependencies] +futures = { version = "0.3" } +itp-sgx-crypto = { path = "../sgx/crypto", features = ["mocks"] } +itp-test = { path = "../test" } +itp-top-pool = { path = "../top-pool", features = ["mocks"] } +sgx-crypto-helper = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git", package = "sgx_crypto_helper", default-features = false } +sp-keyring = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } + + +[features] +default = ["std"] +std = [ + "itp-sgx-crypto/std", + "itp-enclave-metrics/std", + "itp-ocall-api/std", + "itp-stf-state-handler/std", + "itp-top-pool/std", + "itp-types/std", + "jsonrpc-core", + "log/std", + # litentry + "litentry-primitives/std", + "itp-utils/std", +] +sgx = [ + "sgx_tstd", + "jsonrpc-core_sgx", + "itp-enclave-metrics/sgx", + "itp-sgx-crypto/sgx", + "itp-stf-state-handler/sgx", + "itp-top-pool/sgx", + # litentry + "litentry-primitives/sgx", +] +test = ["itp-test/sgx", "itp-top-pool/mocks"] +mocks = ["lazy_static"] +sidechain = [] +offchain-worker = [] +teeracle = [] diff --git a/bitacross-worker/core-primitives/top-pool-author/src/api.rs b/bitacross-worker/core-primitives/top-pool-author/src/api.rs new file mode 100644 index 0000000000..7214e184e3 --- /dev/null +++ b/bitacross-worker/core-primitives/top-pool-author/src/api.rs @@ -0,0 +1,174 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +//! Chain api required for the operation pool. + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +use crate::sgx_reexport_prelude::*; +use core::fmt::Debug; + +use crate::error; +use codec::Encode; +use itp_stf_primitives::{ + traits::{PoolTransactionValidation, TrustedCallVerification}, + types::ShardIdentifier, +}; +use itp_top_pool::{ + pool::{ChainApi, NumberFor}, + primitives::{TrustedOperationSource, TxHash}, +}; +use itp_types::BlockHash as SidechainBlockHash; +use jsonrpc_core::futures::future::{ready, Future, Ready}; +use log::*; +use sp_runtime::{ + generic::BlockId, + traits::{BlakeTwo256, Block as BlockT, Hash as HashT}, + transaction_validity::TransactionValidity, +}; +use std::{boxed::Box, marker::PhantomData, pin::Pin}; + +/// Future that resolves to account nonce. +pub type Result = core::result::Result; + +/// The operation pool logic for full client. +pub struct SidechainApi { + _marker: PhantomData<(Block, TCS)>, +} + +impl SidechainApi +where + TCS: PartialEq + TrustedCallVerification + Debug, +{ + /// Create new operation pool logic. + pub fn new() -> Self { + SidechainApi { _marker: Default::default() } + } +} + +impl Default for SidechainApi +where + TCS: PartialEq + TrustedCallVerification + Debug + Sync + Send, +{ + fn default() -> Self { + Self::new() + } +} + +impl ChainApi for SidechainApi +where + Block: BlockT, + TCS: PartialEq + TrustedCallVerification + Sync + Send + Debug, +{ + type Block = Block; + type Error = error::Error; + type ValidationFuture = + Pin> + Send>>; + type BodyFuture = Ready>>; + + fn validate_transaction( + &self, + _source: TrustedOperationSource, + uxt: TOP, + _shard: ShardIdentifier, + ) -> Self::ValidationFuture { + let operation = uxt.validate(); + Box::pin(ready(Ok(operation))) + } + + fn block_id_to_number( + &self, + at: &BlockId, + ) -> error::Result>> { + Ok(match at { + BlockId::Number(num) => Some(*num), + BlockId::Hash(_) => None, + }) + } + + fn block_id_to_hash( + &self, + at: &BlockId, + ) -> error::Result> { + Ok(match at { + //BlockId::Hash(x) => Some(x.clone()), + BlockId::Hash(_x) => None, + // dummy + BlockId::Number(_num) => None, + }) + } + + fn hash_and_length(&self, ex: &TOP) -> (TxHash, usize) { + debug!("[Pool] creating hash of {:?}", ex); + ex.using_encoded(|x| (BlakeTwo256::hash(x), x.len())) + } + + fn block_body(&self, _id: &BlockId) -> Self::BodyFuture { + ready(Ok(None)) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use futures::executor; + use itp_stf_primitives::types::ShardIdentifier; + use itp_test::mock::stf_mock::{ + mock_top_indirect_trusted_call_signed, mock_top_public_getter, TrustedCallSignedMock, + }; + use itp_types::{AccountId, Block as ParentchainBlock}; + use sp_core::{ed25519, Pair}; + + type TestChainApi = SidechainApi; + + type Seed = [u8; 32]; + const TEST_SEED: Seed = *b"12345678901234567890123456789012"; + + pub fn endowed_account() -> ed25519::Pair { + ed25519::Pair::from_seed(&[42u8; 32].into()) + } + + #[test] + fn indirect_calls_are_valid() { + let chain_api = TestChainApi::default(); + let _account: AccountId = endowed_account().public().into(); + let operation = mock_top_indirect_trusted_call_signed(); + + let validation = executor::block_on(chain_api.validate_transaction( + TrustedOperationSource::Local, + operation, + ShardIdentifier::default(), + )) + .unwrap(); + + assert!(validation.is_ok()); + } + + #[test] + fn public_getters_are_not_valid() { + let chain_api = TestChainApi::default(); + let public_getter = mock_top_public_getter(); + + let validation = executor::block_on(chain_api.validate_transaction( + TrustedOperationSource::Local, + public_getter, + ShardIdentifier::default(), + )) + .unwrap(); + + assert!(validation.is_err()); + } +} diff --git a/bitacross-worker/core-primitives/top-pool-author/src/author.rs b/bitacross-worker/core-primitives/top-pool-author/src/author.rs new file mode 100644 index 0000000000..08cbd61ff7 --- /dev/null +++ b/bitacross-worker/core-primitives/top-pool-author/src/author.rs @@ -0,0 +1,582 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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(all(not(feature = "std"), feature = "sgx"))] +use crate::sgx_reexport_prelude::*; +use core::fmt::Debug; + +use crate::{ + client_error::Error as ClientError, + error::{Error as StateRpcError, Result}, + top_filter::Filter, + traits::{AuthorApi, OnBlockImported}, +}; +use codec::{Decode, Encode}; +use itp_enclave_metrics::EnclaveMetric; +use itp_ocall_api::EnclaveMetricsOCallApi; +use itp_sgx_crypto::{key_repository::AccessKey, ShieldingCryptoDecrypt}; +use itp_stf_primitives::{ + traits::{PoolTransactionValidation, TrustedCallVerification}, + types::{AccountId, Hash, TrustedOperation as StfTrustedOperation, TrustedOperationOrHash}, +}; +use itp_stf_state_handler::query_shard_state::QueryShardState; +use itp_top_pool::{ + error::{Error as PoolError, IntoPoolError}, + primitives::{ + BlockHash, InPoolOperation, PoolFuture, PoolStatus, TrustedOperationPool, + TrustedOperationSource, TxHash, + }, +}; +use itp_types::{BlockHash as SidechainBlockHash, DecryptableRequest, ShardIdentifier}; +use itp_utils::hex::ToHexPrefixed; +use jsonrpc_core::{ + futures::future::{ready, TryFutureExt}, + Error as RpcError, +}; +use litentry_primitives::BroadcastedRequest; +use log::*; +use sp_runtime::generic; +use std::{ + boxed::Box, + string::String, + sync::{mpsc::SyncSender, Arc}, + vec::Vec, +}; + +/// Define type of TOP filter that is used in the Author +#[cfg(feature = "sidechain")] +pub type AuthorTopFilter = crate::top_filter::CallsOnlyFilter; +#[cfg(feature = "sidechain")] +pub type BroadcastedTopFilter = crate::top_filter::DirectCallsOnlyFilter; + +#[cfg(feature = "offchain-worker")] +pub type AuthorTopFilter = crate::top_filter::IndirectCallsOnlyFilter; +#[cfg(feature = "offchain-worker")] +pub type BroadcastedTopFilter = crate::top_filter::DenyAllFilter; + +#[cfg(feature = "teeracle")] // Teeracle currently does not process any trusted operations +pub type AuthorTopFilter = crate::top_filter::DenyAllFilter; +#[cfg(feature = "teeracle")] +pub type BroadcastedTopFilter = crate::top_filter::DenyAllFilter; + +#[cfg(not(any(feature = "sidechain", feature = "offchain-worker", feature = "teeracle")))] +pub type AuthorTopFilter = crate::top_filter::CallsOnlyFilter; + +#[cfg(not(any(feature = "sidechain", feature = "offchain-worker", feature = "teeracle")))] +pub type BroadcastedTopFilter = crate::top_filter::DenyAllFilter; + +/// Currently we treat all RPC operations as externals. +/// +/// Possibly in the future we could allow opt-in for special treatment +/// of such operations, so that the block authors can inject +/// some unique operations via RPC and have them included in the pool. +const TX_SOURCE: TrustedOperationSource = TrustedOperationSource::External; + +// remove duplication of this type definiton ? +pub type RequestIdWithParamsAndMethod = Option<(Hash, Vec)>; + +/// Authoring API for RPC calls +/// +/// +pub struct Author< + TopPool, + TopFilter, + BroadcastedTopFilter, + StateFacade, + ShieldingKeyRepository, + OCallApi, + TCS, + G, +> where + TopPool: TrustedOperationPool> + Sync + Send + 'static, + TopFilter: Filter>, + BroadcastedTopFilter: Filter>, + StateFacade: QueryShardState, + ShieldingKeyRepository: AccessKey, + ::KeyType: ShieldingCryptoDecrypt + 'static, + TCS: PartialEq + Encode + Clone + Debug + Send + Sync, + G: PartialEq + Encode + Clone + PoolTransactionValidation + Debug + Send + Sync, +{ + top_pool: Arc, + top_filter: TopFilter, + broadcasted_top_filter: BroadcastedTopFilter, + state_facade: Arc, + shielding_key_repo: Arc, + ocall_api: Arc, + request_sink: Arc>, +} + +impl< + TopPool, + TopFilter, + BroadcastedTopFilter, + StateFacade, + ShieldingKeyRepository, + OCallApi, + TCS, + G, + > + Author< + TopPool, + TopFilter, + BroadcastedTopFilter, + StateFacade, + ShieldingKeyRepository, + OCallApi, + TCS, + G, + > where + TopPool: TrustedOperationPool> + Sync + Send + 'static, + TopFilter: Filter>, + BroadcastedTopFilter: Filter>, + StateFacade: QueryShardState, + ShieldingKeyRepository: AccessKey, + ::KeyType: ShieldingCryptoDecrypt + 'static, + OCallApi: EnclaveMetricsOCallApi + Send + Sync + 'static, + TCS: PartialEq + Encode + Clone + Debug + Send + Sync, + G: PartialEq + Encode + Clone + PoolTransactionValidation + Debug + Send + Sync, +{ + /// Create new instance of Authoring API. + pub fn new( + top_pool: Arc, + top_filter: TopFilter, + broadcasted_top_filter: BroadcastedTopFilter, + state_facade: Arc, + encryption_key: Arc, + ocall_api: Arc, + request_sink: Arc>, + ) -> Self { + Author { + top_pool, + top_filter, + broadcasted_top_filter, + state_facade, + shielding_key_repo: encryption_key, + ocall_api, + request_sink, + } + } +} + +enum TopSubmissionMode { + Submit, + SubmitWatch, + SubmitWatchAndBroadcast(String), +} + +impl< + TopPool, + TopFilter, + BroadcastedTopFilter, + StateFacade, + ShieldingKeyRepository, + OCallApi, + TCS, + G, + > + Author< + TopPool, + TopFilter, + BroadcastedTopFilter, + StateFacade, + ShieldingKeyRepository, + OCallApi, + TCS, + G, + > where + TopPool: TrustedOperationPool> + Sync + Send + 'static, + TopFilter: Filter>, + BroadcastedTopFilter: Filter>, + StateFacade: QueryShardState, + ShieldingKeyRepository: AccessKey, + ::KeyType: ShieldingCryptoDecrypt + 'static, + OCallApi: EnclaveMetricsOCallApi + Send + Sync + 'static, + TCS: PartialEq + + Encode + + Decode + + Clone + + Debug + + Send + + Sync + + TrustedCallVerification + + 'static, + G: PartialEq + + Encode + + Decode + + Clone + + PoolTransactionValidation + + Debug + + Send + + Sync + + 'static, +{ + fn process_top( + &self, + mut request: R, + submission_mode: TopSubmissionMode, + ) -> PoolFuture { + let shard = request.shard(); + + //we need to save it here as other function may eventually mutate it + let request_to_broadcast = request.to_hex(); + // check if shard exists + match self.state_facade.shard_exists(&shard) { + Err(_) => return Box::pin(ready(Err(ClientError::InvalidShard.into()))), + Ok(shard_exists) => + if !shard_exists { + return Box::pin(ready(Err(ClientError::InvalidShard.into()))) + }, + }; + + // decrypt call + let shielding_key = match self.shielding_key_repo.retrieve_key() { + Ok(k) => k, + Err(_) => return Box::pin(ready(Err(ClientError::BadFormatDecipher.into()))), + }; + let request_vec = match request.decrypt(Box::new(shielding_key)) { + Ok(req) => req, + Err(_) => return Box::pin(ready(Err(ClientError::BadFormatDecipher.into()))), + }; + // decode call + let trusted_operation = + match StfTrustedOperation::::decode(&mut request_vec.as_slice()) { + Ok(op) => op, + Err(_) => return Box::pin(ready(Err(ClientError::BadFormat.into()))), + }; + + trace!("decrypted indirect invocation: {:?}", trusted_operation); + + // apply top filter - return error if this specific type of trusted operation + // is not allowed by the filter + if !self.top_filter.filter(&trusted_operation) { + warn!("unsupported operation"); + return Box::pin(ready(Err(ClientError::UnsupportedOperation.into()))) + } + + //let best_block_hash = self.client.info().best_hash; + // dummy block hash + let best_block_hash = Default::default(); + + // Update metric + if let Err(e) = self.ocall_api.update_metric(EnclaveMetric::TopPoolSizeIncrement) { + warn!("Failed to update metric for top pool size: {:?}", e); + } + + if let Some(trusted_call_signed) = trusted_operation.to_call() { + debug!( + "Submitting trusted call to TOP pool: {:?}, TOP hash: {:?}", + trusted_call_signed, + self.hash_of(&trusted_operation) + ); + } else if let StfTrustedOperation::::get(ref getter) = trusted_operation { + debug!( + "Submitting trusted or public getter to TOP pool: {:?}, TOP hash: {:?}", + getter, + self.hash_of(&trusted_operation) + ); + } + + match submission_mode { + TopSubmissionMode::Submit => Box::pin( + self.top_pool + .submit_one( + &generic::BlockId::hash(best_block_hash), + TX_SOURCE, + trusted_operation, + shard, + ) + .map_err(map_top_error::), + ), + + TopSubmissionMode::SubmitWatch => Box::pin( + self.top_pool + .submit_and_watch( + &generic::BlockId::hash(best_block_hash), + TX_SOURCE, + trusted_operation, + shard, + ) + .map_err(map_top_error::), + ), + + TopSubmissionMode::SubmitWatchAndBroadcast(s) => { + let id = self.hash_of(&trusted_operation).to_hex(); + let can_be_broadcasted = self.broadcasted_top_filter.filter(&trusted_operation); + let result = Box::pin( + self.top_pool + .submit_and_watch( + &generic::BlockId::hash(best_block_hash), + TX_SOURCE, + trusted_operation, + shard, + ) + .map_err(map_top_error::), + ); + // broadcast only if filter allowed + if can_be_broadcasted { + if let Err(e) = self.request_sink.send(BroadcastedRequest { + id, + payload: request_to_broadcast, + rpc_method: s, + }) { + error!("Could not send broadcasted request, reason: {:?}", e); + } + } + result + }, + } + } + + fn remove_top( + &self, + bytes_or_hash: TrustedOperationOrHash, + shard: ShardIdentifier, + inblock: bool, + ) -> Result { + let hash = match bytes_or_hash { + TrustedOperationOrHash::Hash(h) => Ok(h), + TrustedOperationOrHash::OperationEncoded(bytes) => { + match Decode::decode(&mut bytes.as_slice()) { + Ok(op) => Ok(self.top_pool.hash_of(&op)), + Err(e) => { + error!("Failed to decode trusted operation: {:?}, operation will not be removed from pool", e); + Err(StateRpcError::CodecError(e)) + }, + } + }, + TrustedOperationOrHash::Operation(op) => Ok(self.top_pool.hash_of(&op)), + }?; + + debug!("removing {:?} from top pool", hash); + + // Update metric + if let Err(e) = self.ocall_api.update_metric(EnclaveMetric::TopPoolSizeDecrement) { + warn!("Failed to update metric for top pool size: {:?}", e); + } + + let removed_op_hash = self + .top_pool + .remove_invalid(&[hash], shard, inblock) + // Only remove a single element, so first should return Ok(). + .first() + .map(|o| o.hash()) + .ok_or(PoolError::InvalidTrustedOperation)?; + + Ok(removed_op_hash) + } +} + +fn map_top_error>, TCS, G>( + error: P::Error, +) -> RpcError +where + TCS: PartialEq + Encode + Debug, + G: PartialEq + Encode + Debug, +{ + StateRpcError::PoolError( + error + .into_pool_error() + .map(Into::into) + .unwrap_or_else(|_error| PoolError::Verification), + ) + .into() +} + +impl< + TopPool, + TopFilter, + BroadcastedTopFilter, + StateFacade, + ShieldingKeyRepository, + OCallApi, + TCS, + G, + > AuthorApi + for Author< + TopPool, + TopFilter, + BroadcastedTopFilter, + StateFacade, + ShieldingKeyRepository, + OCallApi, + TCS, + G, + > where + TopPool: TrustedOperationPool> + Sync + Send + 'static, + TopFilter: Filter>, + BroadcastedTopFilter: Filter>, + StateFacade: QueryShardState, + ShieldingKeyRepository: AccessKey, + ::KeyType: ShieldingCryptoDecrypt + 'static, + OCallApi: EnclaveMetricsOCallApi + Send + Sync + 'static, + G: PartialEq + + Encode + + Decode + + Clone + + PoolTransactionValidation + + Debug + + Send + + Sync + + 'static, + TCS: PartialEq + + Encode + + Decode + + Clone + + Debug + + Send + + Sync + + TrustedCallVerification + + 'static, +{ + fn submit_top(&self, req: R) -> PoolFuture { + self.process_top(req, TopSubmissionMode::Submit) + } + + /// Get hash of TrustedOperation + fn hash_of(&self, xt: &StfTrustedOperation) -> TxHash { + self.top_pool.hash_of(xt) + } + + fn pending_tops(&self, shard: ShardIdentifier) -> Result>> { + Ok(self.top_pool.ready(shard).map(|top| top.data().encode()).collect()) + } + + fn get_pending_getters(&self, shard: ShardIdentifier) -> Vec> { + self.top_pool + .ready(shard) + .filter_map(|o| match o.data() { + StfTrustedOperation::::get(_) => Some(o.data().clone()), + StfTrustedOperation::::direct_call(_) + | StfTrustedOperation::::indirect_call(_) => None, + }) + .collect() + } + + fn get_pending_trusted_calls( + &self, + shard: ShardIdentifier, + ) -> Vec> { + self.top_pool + .ready(shard) + .filter_map(|o| match o.data() { + StfTrustedOperation::::direct_call(_) + | StfTrustedOperation::::indirect_call(_) => Some(o.data().clone()), + StfTrustedOperation::::get(_) => None, + }) + .collect() + } + + fn get_status(&self, shard: ShardIdentifier) -> PoolStatus { + self.top_pool.status(shard) + } + + fn get_pending_trusted_calls_for( + &self, + shard: ShardIdentifier, + account: &AccountId, + ) -> Vec> { + self.get_pending_trusted_calls(shard) + .into_iter() + .filter(|o| o.signed_caller_account().as_ref() == Some(account)) + .collect() + } + + fn get_shards(&self) -> Vec { + self.top_pool.shards() + } + + fn list_handled_shards(&self) -> Vec { + self.state_facade.list_shards().unwrap_or_default() + } + + fn remove_calls_from_pool( + &self, + shard: ShardIdentifier, + executed_calls: Vec<(TrustedOperationOrHash, bool)>, + ) -> Vec> { + let mut failed_to_remove = Vec::new(); + for (executed_call, inblock) in executed_calls { + if let Err(e) = self.remove_top(executed_call.clone(), shard, inblock) { + // We don't want to return here before all calls have been iterated through, + // hence log message and collect failed calls in vec. + debug!("Error removing trusted call from top pool: {:?}", e); + failed_to_remove.push(executed_call); + } + } + failed_to_remove + } + + fn watch_top( + &self, + request: R, + ) -> PoolFuture { + self.process_top(request, TopSubmissionMode::SubmitWatch) + } + + fn watch_and_broadcast_top( + &self, + request: R, + json_rpc_method: String, + ) -> PoolFuture { + self.process_top(request, TopSubmissionMode::SubmitWatchAndBroadcast(json_rpc_method)) + } + + fn update_connection_state(&self, updates: Vec<(TxHash, (Vec, bool))>) { + self.top_pool.update_connection_state(updates) + } + + fn swap_rpc_connection_hash(&self, old_hash: TxHash, new_hash: TxHash) { + self.top_pool.swap_rpc_connection_hash(old_hash, new_hash) + } +} + +impl< + TopPool, + TopFilter, + BroadcastedTopFilter, + StateFacade, + ShieldingKeyRepository, + OCallApi, + TCS, + G, + > OnBlockImported + for Author< + TopPool, + TopFilter, + BroadcastedTopFilter, + StateFacade, + ShieldingKeyRepository, + OCallApi, + TCS, + G, + > where + TopPool: TrustedOperationPool> + Sync + Send + 'static, + TopFilter: Filter>, + BroadcastedTopFilter: Filter>, + StateFacade: QueryShardState, + ShieldingKeyRepository: AccessKey, + ::KeyType: ShieldingCryptoDecrypt + 'static, + OCallApi: EnclaveMetricsOCallApi + Send + Sync + 'static, + G: PartialEq + Encode + Clone + PoolTransactionValidation + Debug + Send + Sync, + TCS: PartialEq + Encode + Clone + Debug + Send + Sync, +{ + type Hash = TxHash; + + fn on_block_imported(&self, hashes: &[Self::Hash], block_hash: SidechainBlockHash) { + self.top_pool.on_block_imported(hashes, block_hash) + } +} diff --git a/bitacross-worker/core-primitives/top-pool-author/src/author_tests.rs b/bitacross-worker/core-primitives/top-pool-author/src/author_tests.rs new file mode 100644 index 0000000000..3fb0370970 --- /dev/null +++ b/bitacross-worker/core-primitives/top-pool-author/src/author_tests.rs @@ -0,0 +1,203 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{ + author::Author, + test_fixtures::shard_id, + test_utils::submit_operation_to_top_pool, + top_filter::{AllowAllTopsFilter, DirectCallsOnlyFilter, Filter, GettersOnlyFilter}, + traits::AuthorApi, +}; +use codec::{Decode, Encode}; +use itp_sgx_crypto::{mocks::KeyRepositoryMock, ShieldingCryptoDecrypt, ShieldingCryptoEncrypt}; + +use itp_stf_state_handler::handle_state::HandleState; +use itp_test::mock::{ + handle_state_mock::HandleStateMock, + metrics_ocall_mock::MetricsOCallMock, + shielding_crypto_mock::ShieldingCryptoMock, + stf_mock::{ + mock_top_direct_trusted_call_signed, mock_top_indirect_trusted_call_signed, + mock_top_trusted_getter_signed, GetterMock, TrustedCallSignedMock, TrustedOperationMock, + }, +}; +use itp_top_pool::mocks::trusted_operation_pool_mock::TrustedOperationPoolMock; +use itp_utils::ToHexPrefixed; +use litentry_primitives::BroadcastedRequest; +use sgx_crypto_helper::{rsa3072::Rsa3072KeyPair, RsaKeyPair}; +use sp_core::H256; +use std::sync::Arc; + +type TestAuthor = Author< + TrustedOperationPoolMock, + Filter, + BroadcastedFilter, + HandleStateMock, + KeyRepositoryMock, + MetricsOCallMock, + TrustedCallSignedMock, + GetterMock, +>; + +#[test] +fn top_encryption_works() { + let top_call = mock_top_direct_trusted_call_signed(); + let top_getter = mock_top_trusted_getter_signed(); + assert_eq!(top_call, encrypt_and_decrypt_top(&top_call)); + assert_eq!(top_getter, encrypt_and_decrypt_top(&top_getter)); +} + +fn encrypt_and_decrypt_top(top: &TrustedOperationMock) -> TrustedOperationMock { + let encryption_key = Rsa3072KeyPair::new().unwrap(); + let encrypted_top = encryption_key.encrypt(top.encode().as_slice()).unwrap(); + let decrypted_top = encryption_key.decrypt(encrypted_top.as_slice()).unwrap(); + + TrustedOperationMock::decode(&mut decrypted_top.as_slice()).unwrap() +} + +#[test] +fn submitting_to_author_inserts_in_pool() { + let (author, top_pool, shielding_key, _) = + create_author_with_filter(AllowAllTopsFilter::new(), DirectCallsOnlyFilter::new()); + let top_getter = mock_top_trusted_getter_signed(); + + let submit_response = + submit_operation_to_top_pool(&author, &top_getter, &shielding_key, shard_id(), false) + .unwrap(); + + assert!(!submit_response.0.is_zero()); + + let submitted_transactions = top_pool.get_last_submitted_transactions(); + assert_eq!(1, submitted_transactions.len()); +} + +#[test] +fn submitting_call_to_author_when_top_is_filtered_returns_error() { + let (author, top_pool, shielding_key, _) = + create_author_with_filter(GettersOnlyFilter::new(), DirectCallsOnlyFilter::new()); + let top_call = mock_top_direct_trusted_call_signed(); + let submit_response = + submit_operation_to_top_pool(&author, &top_call, &shielding_key, shard_id(), false); + + assert!(submit_response.is_err()); + assert!(top_pool.get_last_submitted_transactions().is_empty()); +} + +#[test] +fn submitting_getter_to_author_when_top_is_filtered_inserts_in_pool() { + let (author, top_pool, shielding_key, _) = + create_author_with_filter(GettersOnlyFilter::new(), DirectCallsOnlyFilter::new()); + let top_getter = mock_top_trusted_getter_signed(); + let submit_response = + submit_operation_to_top_pool(&author, &top_getter, &shielding_key, shard_id(), false) + .unwrap(); + + assert!(!submit_response.0.is_zero()); + assert_eq!(1, top_pool.get_last_submitted_transactions().len()); +} + +#[test] +fn submitting_direct_call_works() { + let (author, top_pool, shielding_key, _) = + create_author_with_filter(AllowAllTopsFilter::new(), DirectCallsOnlyFilter::new()); + let top_call = mock_top_direct_trusted_call_signed(); + let _ = submit_operation_to_top_pool(&author, &top_call, &shielding_key, shard_id(), false) + .unwrap(); + + assert_eq!(1, top_pool.get_last_submitted_transactions().len()); + assert_eq!(1, author.get_pending_trusted_calls(shard_id()).len()); +} + +#[test] +fn broadcasting_direct_call_works() { + let (author, _top_pool, shielding_key, broadcasted_requests_rx) = + create_author_with_filter(AllowAllTopsFilter::new(), DirectCallsOnlyFilter::new()); + let top_call = mock_top_direct_trusted_call_signed(); + + let (hash, request) = + submit_operation_to_top_pool(&author, &top_call, &shielding_key, shard_id(), true).unwrap(); + + let broadcasted_request = broadcasted_requests_rx.try_recv().unwrap(); + assert_eq!(broadcasted_request.rpc_method, "submit_and_watch".to_owned()); + assert_eq!(broadcasted_request.id, hash.to_hex()); + assert_eq!(broadcasted_request.payload, request.to_hex()); +} + +#[test] +fn not_broadcasting_indirect_call_works() { + let (author, _top_pool, shielding_key, broadcasted_requests_rx) = + create_author_with_filter(AllowAllTopsFilter::new(), DirectCallsOnlyFilter::new()); + let top_call = mock_top_indirect_trusted_call_signed(); + + let _ = + submit_operation_to_top_pool(&author, &top_call, &shielding_key, shard_id(), true).unwrap(); + + assert!(broadcasted_requests_rx.try_recv().is_err()) +} + +#[test] +fn submitting_indirect_call_works() { + let (author, top_pool, shielding_key, _) = + create_author_with_filter(AllowAllTopsFilter::new(), DirectCallsOnlyFilter::new()); + let top_call = mock_top_indirect_trusted_call_signed(); + let _ = submit_operation_to_top_pool(&author, &top_call, &shielding_key, shard_id(), false) + .unwrap(); + + assert_eq!(1, top_pool.get_last_submitted_transactions().len()); + assert_eq!(1, author.get_pending_trusted_calls(shard_id()).len()); +} + +fn create_author_with_filter< + F: Filter, + BF: Filter, +>( + filter: F, + broadcasted_filter: BF, +) -> ( + TestAuthor, + Arc>, + ShieldingCryptoMock, + std::sync::mpsc::Receiver, +) { + let top_pool = Arc::new(TrustedOperationPoolMock::default()); + + let shard_id = shard_id(); + let state_facade = HandleStateMock::from_shard(shard_id).unwrap(); + state_facade.load_cloned(&shard_id).unwrap(); + + let encryption_key = ShieldingCryptoMock::default(); + let shielding_key_repo = + Arc::new(KeyRepositoryMock::::new(encryption_key.clone())); + let ocall_mock = Arc::new(MetricsOCallMock::default()); + + let (sender, receiver) = std::sync::mpsc::sync_channel::(1000); + + ( + Author::new( + top_pool.clone(), + filter, + broadcasted_filter, + Arc::new(state_facade), + shielding_key_repo, + ocall_mock, + Arc::new(sender), + ), + top_pool, + encryption_key, + receiver, + ) +} diff --git a/bitacross-worker/core-primitives/top-pool-author/src/client_error.rs b/bitacross-worker/core-primitives/top-pool-author/src/client_error.rs new file mode 100644 index 0000000000..badd278008 --- /dev/null +++ b/bitacross-worker/core-primitives/top-pool-author/src/client_error.rs @@ -0,0 +1,183 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +//! Authoring RPC module client errors. + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +use crate::sgx_reexport_prelude::*; + +use derive_more::{Display, From}; +use jsonrpc_core as rpc_core; +use std::{boxed::Box, format}; + +/// Author RPC Result type. +pub type Result = core::result::Result; + +/// Author RPC errors. +#[derive(Debug, Display, From)] +pub enum Error { + /// Client error. + #[display(fmt = "Client error: {}", _0)] + #[from(ignore)] + Client(Box), + /// TrustedOperation pool error, + #[display(fmt = "TrustedOperation pool error: {}", _0)] + Pool(itp_top_pool::error::Error), + /// Verification error + #[display(fmt = "Extrinsic verification error")] + #[from(ignore)] + Verification, + /// Incorrect extrinsic format. + #[display(fmt = "Invalid trusted call format")] + BadFormat, + // Incorrect enciphered trusted call format. + #[display(fmt = "Invalid enciphered trusted call format")] + BadFormatDecipher, + /// Incorrect seed phrase. + #[display(fmt = "Invalid seed phrase/SURI")] + BadSeedPhrase, + /// Key type ID has an unknown format. + #[display(fmt = "Invalid key type ID format (should be of length four)")] + BadKeyType, + /// Key type ID has some unsupported crypto. + #[display(fmt = "The crypto of key type ID is unknown")] + UnsupportedKeyType, + /// Some random issue with the key store. Shouldn't happen. + #[display(fmt = "The key store is unavailable")] + KeyStoreUnavailable, + /// Invalid session keys encoding. + #[display(fmt = "Session keys are not encoded correctly")] + InvalidSessionKeys, + /// Shard does not exist. + #[display(fmt = "Shard does not exist")] + InvalidShard, + /// Unsupported trusted operation (in case we allow only certain types of operations, using filters) + #[display(fmt = "Unsupported operation type")] + UnsupportedOperation, +} + +impl std::error::Error for Error { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + Error::Client(ref err) => Some(&**err), + //Error::Pool(ref err) => Some(err), + //Error::Verification(ref err) => Some(&**err), + _ => None, + } + } +} + +/// Base code for all authorship errors. +const BASE_ERROR: i64 = 1000; +/// Extrinsic has an invalid format. +const BAD_FORMAT: i64 = BASE_ERROR + 1; +/// Error during operation verification in runtime. +const VERIFICATION_ERROR: i64 = BASE_ERROR + 2; + +/// Pool rejected the operation as invalid +const POOL_INVALID_TX: i64 = BASE_ERROR + 10; +/// Cannot determine operation validity. +const POOL_UNKNOWN_VALIDITY: i64 = POOL_INVALID_TX + 1; +/// The operation is temporarily banned. +const POOL_TEMPORARILY_BANNED: i64 = POOL_INVALID_TX + 2; +/// The operation is already in the pool +const POOL_ALREADY_IMPORTED: i64 = POOL_INVALID_TX + 3; +/// TrustedOperation has too low priority to replace existing one in the pool. +const POOL_TOO_LOW_PRIORITY: i64 = POOL_INVALID_TX + 4; +/// Including this operation would cause a dependency cycle. +const POOL_CYCLE_DETECTED: i64 = POOL_INVALID_TX + 5; +/// The operation was not included to the pool because of the limits. +const POOL_IMMEDIATELY_DROPPED: i64 = POOL_INVALID_TX + 6; +/// The key type crypto is not known. +const UNSUPPORTED_KEY_TYPE: i64 = POOL_INVALID_TX + 7; + +impl From for rpc_core::Error { + fn from(e: Error) -> Self { + use itp_top_pool::error::Error as PoolError; + + match e { + Error::BadFormat => rpc_core::Error { + code: rpc_core::ErrorCode::ServerError(BAD_FORMAT), + message: "Trusted operation has invalid format".into(), + data: None, + }, + Error::BadFormatDecipher => rpc_core::Error { + code: rpc_core::ErrorCode::ServerError(BAD_FORMAT), + message: "Trusted operation could not be deciphered".into(), + data: None, + }, + Error::Verification => rpc_core::Error { + code: rpc_core::ErrorCode::ServerError(VERIFICATION_ERROR), + message: "Verification Error".into(), + data: Some(format!("{:?}", e).into()), + }, + Error::InvalidShard => rpc_core::Error { + code: rpc_core::ErrorCode::ServerError(VERIFICATION_ERROR), + message: "Shard does not exist".into(), + data: Some(format!("{:?}", e).into()), + }, + Error::Pool(PoolError::InvalidTrustedOperation) => rpc_core::Error { + code: rpc_core::ErrorCode::ServerError(POOL_INVALID_TX), + message: "Invalid Trusted Operation".into(), + data: None, + }, + Error::Pool(PoolError::UnknownTrustedOperation) => rpc_core::Error { + code: rpc_core::ErrorCode::ServerError(POOL_UNKNOWN_VALIDITY), + message: "Unknown Trusted Operation Validity".into(), + data: None, + }, + Error::Pool(PoolError::TemporarilyBanned) => rpc_core::Error { + code: rpc_core::ErrorCode::ServerError(POOL_TEMPORARILY_BANNED), + message: "Trusted Operation is temporarily banned".into(), + data: None, + }, + Error::Pool(PoolError::AlreadyImported) => rpc_core::Error { + code: rpc_core::ErrorCode::ServerError(POOL_ALREADY_IMPORTED), + message: "Trusted Operation Already Imported".into(), + data: None, + }, + Error::Pool(PoolError::TooLowPriority(new)) => rpc_core::Error { + code: rpc_core::ErrorCode::ServerError(POOL_TOO_LOW_PRIORITY), + message: format!("Priority is too low: {}", new), + data: Some("The Trusted Operation has too low priority to replace another Trusted Operation already in the pool.".into()), + }, + Error::Pool(PoolError::CycleDetected) => rpc_core::Error { + code: rpc_core::ErrorCode::ServerError(POOL_CYCLE_DETECTED), + message: "Cycle Detected".into(), + data: None, + }, + Error::Pool(PoolError::ImmediatelyDropped) => rpc_core::Error { + code: rpc_core::ErrorCode::ServerError(POOL_IMMEDIATELY_DROPPED), + message: "Immediately Dropped".into(), + data: Some("The Trusted Operation couldn't enter the pool because of the limit".into()), + }, + Error::UnsupportedKeyType => rpc_core::Error { + code: rpc_core::ErrorCode::ServerError(UNSUPPORTED_KEY_TYPE), + message: "Unknown key type crypto" .into(), + data: Some( + "The crypto for the given key type is unknown, please add the public key to the \ + request to insert the key successfully.".into() + ), + }, + e => rpc_core::Error { + code: rpc_core::ErrorCode::InternalError, + message: "Unknown error occurred".into(), + data: Some(format!("{:?}", e).into()), + }, + } + } +} diff --git a/bitacross-worker/core-primitives/top-pool-author/src/error.rs b/bitacross-worker/core-primitives/top-pool-author/src/error.rs new file mode 100644 index 0000000000..1c967a1b82 --- /dev/null +++ b/bitacross-worker/core-primitives/top-pool-author/src/error.rs @@ -0,0 +1,111 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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(all(not(feature = "std"), feature = "sgx"))] +use crate::sgx_reexport_prelude::*; + +use crate::client_error::Error as ClientError; +use core::pin::Pin; +use derive_more::{Display, From}; +use itp_top_pool::error::{Error as PoolError, IntoPoolError}; +use jsonrpc_core as rpc; +use std::{boxed::Box, error, format, string::String}; + +/// State RPC Result type. +pub type Result = core::result::Result; + +/// State RPC future Result type. +pub type FutureResult = + Pin> + Send>>; + +/// State RPC errors. +#[derive(Debug, Display, From)] +pub enum Error { + /// Client error. + #[display(fmt = "Client error: {}", _0)] + Client(Box), + /// Provided block range couldn't be resolved to a list of blocks. + #[display(fmt = "Cannot resolve a block range ['{:?}' ... '{:?}]. {}", from, to, details)] + InvalidBlockRange { + /// Beginning of the block range. + from: String, + /// End of the block range. + to: String, + /// Details of the error message. + details: String, + }, + /// Provided count exceeds maximum value. + #[display(fmt = "count exceeds maximum value. value: {}, max: {}", value, max)] + InvalidCount { + /// Provided value + value: u32, + /// Maximum allowed value + max: u32, + }, + + /// Wrapping of PoolError to RPC Error + PoolError(PoolError), + + /// Wrapping of ClientError to RPC Error + ClientError(ClientError), + + #[display(fmt = "Codec error: {}", _0)] + CodecError(codec::Error), +} + +impl error::Error for Error { + fn source(&self) -> Option<&(dyn error::Error + 'static)> { + match self { + Error::Client(ref err) => Some(&**err), + _ => None, + } + } +} + +impl IntoPoolError for Error { + fn into_pool_error(self) -> std::result::Result { + match self { + Error::PoolError(e) => Ok(e), + e => Err(e), + } + } +} + +/// Base code for all state errors. +const BASE_ERROR: i64 = 4000; + +impl From for rpc::Error { + fn from(e: Error) -> Self { + match e { + Error::InvalidBlockRange { .. } => rpc::Error { + code: rpc::ErrorCode::ServerError(BASE_ERROR + 1), + message: format!("{}", e), + data: None, + }, + Error::InvalidCount { .. } => rpc::Error { + code: rpc::ErrorCode::ServerError(BASE_ERROR + 2), + message: format!("{}", e), + data: None, + }, + e => rpc::Error { + code: rpc::ErrorCode::ServerError(BASE_ERROR + 4), + message: format!("{}", e), + data: None, + }, + } + } +} diff --git a/bitacross-worker/core-primitives/top-pool-author/src/lib.rs b/bitacross-worker/core-primitives/top-pool-author/src/lib.rs new file mode 100644 index 0000000000..b0b84b992c --- /dev/null +++ b/bitacross-worker/core-primitives/top-pool-author/src/lib.rs @@ -0,0 +1,51 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +#![feature(trait_alias)] +#![cfg_attr(feature = "mocks", feature(drain_filter))] +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg(all(feature = "std", feature = "sgx"))] +compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the same time"); + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +extern crate sgx_tstd as std; + +// re-export module to properly feature gate sgx and regular std environment +#[cfg(all(not(feature = "std"), feature = "sgx"))] +pub mod sgx_reexport_prelude { + pub use jsonrpc_core_sgx as jsonrpc_core; +} + +pub mod api; +pub mod author; +pub mod client_error; +pub mod error; +pub mod top_filter; +pub mod traits; + +#[cfg(test)] +mod author_tests; + +#[cfg(test)] +mod test_fixtures; + +#[cfg(any(test, feature = "test"))] +pub mod test_utils; + +#[cfg(feature = "mocks")] +pub mod mocks; diff --git a/bitacross-worker/core-primitives/top-pool-author/src/mocks.rs b/bitacross-worker/core-primitives/top-pool-author/src/mocks.rs new file mode 100644 index 0000000000..d97bb1008c --- /dev/null +++ b/bitacross-worker/core-primitives/top-pool-author/src/mocks.rs @@ -0,0 +1,315 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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(all(not(feature = "std"), feature = "sgx"))] +use crate::sgx_reexport_prelude::*; +use core::fmt::Debug; + +#[cfg(feature = "sgx")] +use std::sync::SgxRwLock as RwLock; + +#[cfg(feature = "std")] +use std::sync::RwLock; + +use crate::{ + error::Result, + traits::{AuthorApi, OnBlockImported}, +}; +use codec::{Decode, Encode}; +use itp_stf_primitives::{ + traits::TrustedCallVerification, + types::{AccountId, TrustedOperation as StfTrustedOperation, TrustedOperationOrHash}, +}; +use itp_top_pool::primitives::{PoolFuture, PoolStatus}; +use itp_types::{DecryptableRequest, ShardIdentifier}; +use jsonrpc_core::{futures::future::ready, Error as RpcError}; +use lazy_static::lazy_static; +use sp_core::{blake2_256, H256}; +#[cfg(feature = "sgx")] +use std::sync::SgxMutex as Mutex; +use std::{ + boxed::Box, + collections::HashMap, + marker::PhantomData, + string::String, + sync::{mpsc::Sender, Arc}, + vec, + vec::Vec, +}; + +#[cfg(all(feature = "std", feature = "sgx"))] +compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the same time"); + +#[cfg(feature = "std")] +use std::sync::Mutex; + +lazy_static! { + pub static ref GLOBAL_MOCK_AUTHOR_API: Arc>>>> = + Arc::new(Mutex::new(None)); +} + +#[derive(Default)] +pub struct AuthorApiMock +where + TCS: PartialEq + Encode + Decode + Debug + Send + Sync + TrustedCallVerification, + G: PartialEq + Encode + Decode + Debug + Send + Sync, +{ + tops: RwLock>>>, + _phantom: PhantomData<(Hash, BlockHash, TCS, G)>, + pub remove_attempts: RwLock, +} + +impl AuthorApiMock +where + TCS: PartialEq + Encode + Decode + Debug + Send + Sync + TrustedCallVerification, + G: PartialEq + Encode + Decode + Debug + Send + Sync, +{ + fn remove_top( + &self, + bytes_or_hash: Vec>, + shard: ShardIdentifier, + _inblock: bool, + ) -> Result> { + let hashes = bytes_or_hash + .into_iter() + .map(|x| match x { + TrustedOperationOrHash::Hash(h) => h, + TrustedOperationOrHash::OperationEncoded(bytes) => { + let top: StfTrustedOperation = + StfTrustedOperation::::decode(&mut bytes.as_slice()).unwrap(); + top.hash() + }, + TrustedOperationOrHash::Operation(op) => op.hash(), + }) + .collect::>(); + + let mut tops_lock = self.tops.write().unwrap(); + + match tops_lock.get_mut(&shard) { + Some(tops_encoded) => { + let removed_tops = tops_encoded + .drain_filter(|t| hashes.contains(&blake2_256(t).into())) + .map(|t| blake2_256(&t).into()) + .collect::>(); + Ok(removed_tops) + }, + None => Ok(Vec::new()), + } + } +} + +impl AuthorApi for AuthorApiMock +where + TCS: PartialEq + Encode + Decode + Debug + Clone + TrustedCallVerification + Send + Sync, + G: PartialEq + Encode + Decode + Debug + Clone + Send + Sync, +{ + fn submit_top(&self, req: R) -> PoolFuture { + let mut write_lock = self.tops.write().unwrap(); + let extrinsics = write_lock.entry(req.shard()).or_default(); + extrinsics.push(req.payload().to_vec()); + Box::pin(ready(Ok(H256::default()))) + } + + fn hash_of(&self, xt: &StfTrustedOperation) -> H256 { + xt.hash() + } + + fn pending_tops(&self, shard: ShardIdentifier) -> Result>> { + let extrinsics = self.tops.read().unwrap().get(&shard).cloned(); + Ok(extrinsics.unwrap_or_default()) + } + + fn get_pending_getters(&self, shard: ShardIdentifier) -> Vec> { + self.tops + .read() + .unwrap() + .get(&shard) + .map(|encoded_operations| { + let mut trusted_getters: Vec> = Vec::new(); + for encoded_operation in encoded_operations { + if let Ok(g) = G::decode(&mut encoded_operation.as_slice()) { + trusted_getters.push(StfTrustedOperation::::get(g)); + } + } + trusted_getters + }) + .unwrap_or_default() + } + + fn get_pending_trusted_calls( + &self, + shard: ShardIdentifier, + ) -> Vec> { + self.tops + .read() + .unwrap() + .get(&shard) + .map(|encoded_operations| { + let mut trusted_operations: Vec> = Vec::new(); + for encoded_operation in encoded_operations { + if let Ok(o) = StfTrustedOperation::decode(&mut encoded_operation.as_slice()) { + trusted_operations.push(o); + } + } + trusted_operations + }) + .unwrap_or_default() + } + + fn get_status(&self, shard: ShardIdentifier) -> PoolStatus { + self.tops + .read() + .unwrap() + .get(&shard) + .map(|encoded_operations| { + let mut trusted_operations: Vec> = Vec::new(); + for encoded_operation in encoded_operations { + if let Ok(o) = StfTrustedOperation::decode(&mut encoded_operation.as_slice()) { + trusted_operations.push(o); + } + } + PoolStatus { + ready: trusted_operations.len(), + ready_bytes: trusted_operations.encode().len(), + future: 0, + future_bytes: 0, + } + }) + .unwrap_or_default() + } + + fn get_pending_trusted_calls_for( + &self, + shard: ShardIdentifier, + account: &AccountId, + ) -> Vec> { + self.tops + .read() + .unwrap() + .get(&shard) + .map(|encoded_operations| { + let mut trusted_operations: Vec> = Vec::new(); + for encoded_operation in encoded_operations { + if let Ok(top) = StfTrustedOperation::decode(&mut encoded_operation.as_slice()) + { + if top.signed_caller_account().as_ref() == Some(account) { + trusted_operations.push(top); + } + } + } + trusted_operations + }) + .unwrap_or_default() + } + + fn get_shards(&self) -> Vec { + self.tops.read().unwrap().keys().cloned().collect() + } + + fn list_handled_shards(&self) -> Vec { + //dummy + self.tops.read().unwrap().keys().cloned().collect() + } + + fn remove_calls_from_pool( + &self, + shard: ShardIdentifier, + executed_calls: Vec<(TrustedOperationOrHash, bool)>, + ) -> Vec> { + let mut remove_attempts_lock = self.remove_attempts.write().unwrap(); + *remove_attempts_lock += 1; + + let mut failed_to_remove = Vec::new(); + for (executed_call, inblock) in executed_calls { + if self.remove_top(vec![executed_call.clone()], shard, inblock).is_err() { + failed_to_remove.push(executed_call); + } + } + failed_to_remove + } + + fn watch_top(&self, request: R) -> PoolFuture { + // Note: The below implementation is specific for litentry/core/stf-task/receiver/test.rs + let sender_guard = GLOBAL_MOCK_AUTHOR_API.lock().unwrap(); + let sender = &*sender_guard; + sender + .as_ref() + .expect("Not yet initialized") + .send(request.payload().to_vec()) + .unwrap(); + Box::pin(ready(Ok([0u8; 32].into()))) + } + + fn watch_and_broadcast_top( + &self, + request: R, + _json_rpc_method: String, + ) -> PoolFuture { + self.watch_top(request) + } + + fn update_connection_state(&self, _updates: Vec<(H256, (Vec, bool))>) {} + + fn swap_rpc_connection_hash(&self, _old_hash: H256, _new_hash: H256) {} +} + +impl OnBlockImported for AuthorApiMock +where + TCS: PartialEq + Encode + Decode + Debug + Send + Sync + TrustedCallVerification, + G: PartialEq + Encode + Decode + Debug + Send + Sync, +{ + type Hash = H256; + + fn on_block_imported(&self, _hashes: &[Self::Hash], _block_hash: H256) {} +} + +#[cfg(test)] +mod tests { + + use super::*; + use crate::test_fixtures::shard_id; + use codec::Encode; + use futures::executor::block_on; + use itp_test::mock::stf_mock::{ + mock_top_indirect_trusted_call_signed, GetterMock, TrustedCallSignedMock, + }; + use itp_types::RsaRequest; + use std::vec; + + #[test] + fn submitted_tops_can_be_removed_again() { + let author = AuthorApiMock::::default(); + let shard = shard_id(); + let trusted_operation = mock_top_indirect_trusted_call_signed(); + + let _ = block_on(author.submit_top(RsaRequest::new(shard, trusted_operation.encode()))) + .unwrap(); + + assert_eq!(1, author.pending_tops(shard).unwrap().len()); + assert_eq!(1, author.get_pending_trusted_calls(shard).len()); + assert_eq!(0, author.get_pending_getters(shard).len()); + + let trusted_operation_or_hash = + TrustedOperationOrHash::::from_top( + trusted_operation.clone(), + ); + let removed_tops = author.remove_top(vec![trusted_operation_or_hash], shard, true).unwrap(); + + assert_eq!(1, removed_tops.len()); + assert!(author.tops.read().unwrap().get(&shard).unwrap().is_empty()); + } +} diff --git a/bitacross-worker/core-primitives/top-pool-author/src/test_fixtures.rs b/bitacross-worker/core-primitives/top-pool-author/src/test_fixtures.rs new file mode 100644 index 0000000000..b46f1d3e7c --- /dev/null +++ b/bitacross-worker/core-primitives/top-pool-author/src/test_fixtures.rs @@ -0,0 +1,42 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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; +use itp_stf_primitives::types::ShardIdentifier; + +use sp_core::{ed25519, Pair}; +use sp_runtime::traits::{BlakeTwo256, Hash}; +use std::vec; + +type Seed = [u8; 32]; +const TEST_SEED: Seed = *b"12345678901234567890123456789012"; + +pub(crate) fn mr_enclave() -> [u8; 32] { + [1u8; 32] +} + +pub(crate) fn shard_id() -> ShardIdentifier { + BlakeTwo256::hash(vec![1u8, 2u8, 3u8].as_slice().encode().as_slice()) +} + +fn alice_pair() -> ed25519::Pair { + ed25519::Pair::from_seed(b"22222678901234567890123456789012") +} + +fn bob_pair() -> ed25519::Pair { + ed25519::Pair::from_seed(b"33333378901234567890123456789012") +} diff --git a/bitacross-worker/core-primitives/top-pool-author/src/test_utils.rs b/bitacross-worker/core-primitives/top-pool-author/src/test_utils.rs new file mode 100644 index 0000000000..4c356e3428 --- /dev/null +++ b/bitacross-worker/core-primitives/top-pool-author/src/test_utils.rs @@ -0,0 +1,63 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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(all(not(feature = "std"), feature = "sgx"))] +use crate::sgx_reexport_prelude::*; + +use crate::traits::AuthorApi; +use codec::Encode; +use itp_sgx_crypto::ShieldingCryptoEncrypt; +use itp_stf_primitives::types::{ShardIdentifier, TrustedOperation as StfTrustedOperation}; +use itp_types::RsaRequest; +use jsonrpc_core::futures::executor; +use sp_core::H256; +use std::{fmt::Debug, string::ToString}; + +/// Test utility function to submit a trusted operation on an RPC author +pub fn submit_operation_to_top_pool( + author: &R, + top: &StfTrustedOperation, + shielding_key: &S, + shard: ShardIdentifier, + with_broadcast: bool, +) -> Result<(H256, RsaRequest), jsonrpc_core::Error> +where + R: AuthorApi, + S: ShieldingCryptoEncrypt, + S::Error: Debug, + TCS: PartialEq + Encode + Debug + Send + Sync, + G: PartialEq + Encode + Debug + Send + Sync, +{ + let top_encrypted = shielding_key.encrypt(&top.encode()).unwrap(); + if with_broadcast { + let submit_future = async { + author + .watch_and_broadcast_top( + RsaRequest::new(shard, top_encrypted.clone()), + "submit_and_watch".to_string(), + ) + .await + }; + let hash = executor::block_on(submit_future)?; + Ok((hash, RsaRequest::new(shard, top_encrypted))) + } else { + let submit_future = + async { author.watch_top(RsaRequest::new(shard, top_encrypted.clone())).await }; + let hash = executor::block_on(submit_future)?; + Ok((hash, RsaRequest::new(shard, top_encrypted))) + } +} diff --git a/bitacross-worker/core-primitives/top-pool-author/src/top_filter.rs b/bitacross-worker/core-primitives/top-pool-author/src/top_filter.rs new file mode 100644 index 0000000000..25b3574870 --- /dev/null +++ b/bitacross-worker/core-primitives/top-pool-author/src/top_filter.rs @@ -0,0 +1,320 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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; +use core::{fmt::Debug, marker::PhantomData}; +use itp_stf_primitives::types::TrustedOperation as StfTrustedOperation; + +/// Trait for filtering values +/// +/// Returns `Some` if a value should be included and `None` if discarded +pub trait Filter { + type Value; + + fn filter(&self, value: &Self::Value) -> bool; +} + +/// Filter for calls only (no getters). +pub struct CallsOnlyFilter { + _phantom: PhantomData<(TCS, G)>, +} + +impl CallsOnlyFilter { + pub fn new() -> Self { + Self { _phantom: Default::default() } + } +} + +impl Default for CallsOnlyFilter { + fn default() -> Self { + Self::new() + } +} + +impl Filter for CallsOnlyFilter +where + TCS: PartialEq + Encode + Debug, + G: PartialEq + Encode + Debug, +{ + type Value = StfTrustedOperation; + + fn filter(&self, value: &Self::Value) -> bool { + matches!(value, Self::Value::direct_call(_)) + || matches!(value, Self::Value::indirect_call(_)) + } +} + +/// Filter for direct calls only. +pub struct DirectCallsOnlyFilter { + _phantom: PhantomData<(TCS, G)>, +} + +impl DirectCallsOnlyFilter { + pub fn new() -> Self { + Self { _phantom: Default::default() } + } +} + +impl Default for DirectCallsOnlyFilter { + fn default() -> Self { + Self::new() + } +} + +impl Filter for DirectCallsOnlyFilter +where + TCS: PartialEq + Encode + Debug, + G: PartialEq + Encode + Debug, +{ + type Value = StfTrustedOperation; + + fn filter(&self, value: &Self::Value) -> bool { + matches!(value, Self::Value::direct_call(_)) + } +} + +/// Filter that allows all TOPs (i.e. not filter at all) +pub struct AllowAllTopsFilter { + _phantom: PhantomData<(TCS, G)>, +} + +impl AllowAllTopsFilter { + pub fn new() -> Self { + Self { _phantom: Default::default() } + } +} + +impl Default for AllowAllTopsFilter { + fn default() -> Self { + Self::new() + } +} + +impl Filter for AllowAllTopsFilter +where + TCS: PartialEq + Encode + Debug, + G: PartialEq + Encode + Debug, +{ + type Value = StfTrustedOperation; + + fn filter(&self, _value: &Self::Value) -> bool { + true + } +} + +/// Filter that allows only trusted getters +pub struct GettersOnlyFilter { + _phantom: PhantomData<(TCS, G)>, +} + +impl GettersOnlyFilter { + pub fn new() -> Self { + Self { _phantom: Default::default() } + } +} + +impl Default for GettersOnlyFilter { + fn default() -> Self { + Self::new() + } +} + +impl Filter for GettersOnlyFilter +where + TCS: PartialEq + Encode + Debug, + G: PartialEq + Encode + Debug, +{ + type Value = StfTrustedOperation; + + fn filter(&self, value: &Self::Value) -> bool { + matches!(value, Self::Value::get(_)) + } +} + +/// Filter for indirect calls only (no getters, no direct calls). +pub struct IndirectCallsOnlyFilter { + _phantom: PhantomData<(TCS, G)>, +} + +impl IndirectCallsOnlyFilter { + pub fn new() -> Self { + Self { _phantom: Default::default() } + } +} + +impl Default for IndirectCallsOnlyFilter { + fn default() -> Self { + Self::new() + } +} + +impl Filter for IndirectCallsOnlyFilter +where + TCS: PartialEq + Encode + Debug, + G: PartialEq + Encode + Debug, +{ + type Value = StfTrustedOperation; + + fn filter(&self, value: &Self::Value) -> bool { + matches!(value, Self::Value::indirect_call(_)) + } +} + +/// Filter that allows no direct calls, only indirect and getters. +pub struct NoDirectCallsFilter { + _phantom: PhantomData<(TCS, G)>, +} + +impl NoDirectCallsFilter { + pub fn new() -> Self { + Self { _phantom: Default::default() } + } +} + +impl Default for NoDirectCallsFilter { + fn default() -> Self { + Self::new() + } +} + +impl Filter for NoDirectCallsFilter +where + TCS: PartialEq + Encode + Debug, + G: PartialEq + Encode + Debug, +{ + type Value = StfTrustedOperation; + + fn filter(&self, value: &Self::Value) -> bool { + !matches!(value, Self::Value::direct_call(_)) + } +} + +/// Filter to deny all trusted operations. +pub struct DenyAllFilter { + _phantom: PhantomData<(TCS, G)>, +} + +impl DenyAllFilter { + pub fn new() -> Self { + Self { _phantom: Default::default() } + } +} + +impl Default for DenyAllFilter { + fn default() -> Self { + Self::new() + } +} + +impl Filter for DenyAllFilter +where + TCS: PartialEq + Encode + Debug, + G: PartialEq + Encode + Debug, +{ + type Value = StfTrustedOperation; + + fn filter(&self, _value: &Self::Value) -> bool { + false + } +} + +#[cfg(test)] +mod tests { + + use super::*; + + use itp_test::mock::stf_mock::{ + mock_top_direct_trusted_call_signed, mock_top_indirect_trusted_call_signed, + mock_top_trusted_getter_signed, + }; + + use std::string::{String, ToString}; + + #[test] + fn filter_returns_none_if_values_is_filtered_out() { + struct WorldFilter; + impl Filter for WorldFilter { + type Value = String; + + fn filter(&self, value: &Self::Value) -> bool { + if value.eq(&String::from("world")) { + return true + } + false + } + } + + let filter = WorldFilter; + + assert!(!filter.filter(&"hello".to_string())); + assert!(filter.filter(&"world".to_string())); + } + + #[test] + fn allow_all_tops_filter_works() { + let filter = AllowAllTopsFilter::new(); + + assert!(filter.filter(&mock_top_trusted_getter_signed())); + assert!(filter.filter(&mock_top_indirect_trusted_call_signed())); + assert!(filter.filter(&mock_top_direct_trusted_call_signed())); + } + + #[test] + fn getters_only_filter_works() { + let filter = GettersOnlyFilter::new(); + + assert!(filter.filter(&mock_top_trusted_getter_signed())); + assert!(!filter.filter(&mock_top_indirect_trusted_call_signed())); + assert!(!filter.filter(&mock_top_direct_trusted_call_signed())); + } + + #[test] + fn no_direct_calls_filter_works() { + let filter = NoDirectCallsFilter::new(); + + assert!(!filter.filter(&mock_top_direct_trusted_call_signed())); + assert!(filter.filter(&mock_top_indirect_trusted_call_signed())); + assert!(filter.filter(&mock_top_trusted_getter_signed())); + } + + #[test] + fn indirect_calls_only_filter_works() { + let filter = IndirectCallsOnlyFilter::new(); + + assert!(!filter.filter(&mock_top_direct_trusted_call_signed())); + assert!(filter.filter(&mock_top_indirect_trusted_call_signed())); + assert!(!filter.filter(&mock_top_trusted_getter_signed())); + } + + #[test] + fn calls_only_filter_works() { + let filter = CallsOnlyFilter::new(); + + assert!(filter.filter(&mock_top_direct_trusted_call_signed())); + assert!(filter.filter(&mock_top_indirect_trusted_call_signed())); + assert!(!filter.filter(&mock_top_trusted_getter_signed())); + } + + #[test] + fn direct_calls_only_filter_works() { + let filter = DirectCallsOnlyFilter::new(); + + assert!(filter.filter(&mock_top_direct_trusted_call_signed())); + assert!(!filter.filter(&mock_top_indirect_trusted_call_signed())); + assert!(!filter.filter(&mock_top_trusted_getter_signed())); + } +} diff --git a/bitacross-worker/core-primitives/top-pool-author/src/traits.rs b/bitacross-worker/core-primitives/top-pool-author/src/traits.rs new file mode 100644 index 0000000000..b468432636 --- /dev/null +++ b/bitacross-worker/core-primitives/top-pool-author/src/traits.rs @@ -0,0 +1,109 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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(all(not(feature = "std"), feature = "sgx"))] +use crate::sgx_reexport_prelude::*; +use codec::Encode; +use core::fmt::Debug; + +use crate::error::Result; +use itp_stf_primitives::types::{ + AccountId, TrustedOperation as StfTrustedOperation, TrustedOperationOrHash, +}; +use itp_top_pool::primitives::{PoolFuture, PoolStatus}; +use itp_types::{BlockHash as SidechainBlockHash, DecryptableRequest, ShardIdentifier, H256}; +use jsonrpc_core::Error as RpcError; +use std::{string::String, vec::Vec}; + +/// Trait alias for a full STF author API +pub trait FullAuthor< + TCS: PartialEq + Encode + Debug + Send + Sync + 'static, + G: PartialEq + Encode + Debug + Send + Sync + 'static, +> = AuthorApi + OnBlockImported + Send + Sync + 'static; + +/// Authoring RPC API +pub trait AuthorApi +where + TCS: PartialEq + Encode + Debug + Send + Sync, + G: PartialEq + Encode + Debug + Send + Sync, +{ + /// Submit encoded extrinsic for inclusion in block. + fn submit_top(&self, req: R) -> PoolFuture; + + /// Return hash of Trusted Operation + fn hash_of(&self, xt: &StfTrustedOperation) -> Hash; + + /// Returns all pending operations, potentially grouped by sender. + fn pending_tops(&self, shard: ShardIdentifier) -> Result>>; + + /// Returns all pending trusted getters. + fn get_pending_getters(&self, shard: ShardIdentifier) -> Vec>; + + /// Returns all pending trusted calls (in ready state). + fn get_pending_trusted_calls(&self, shard: ShardIdentifier) + -> Vec>; + + /// Returns pool status + fn get_status(&self, shard: ShardIdentifier) -> PoolStatus; + + /// Returns all pending trusted calls for a given `account` + fn get_pending_trusted_calls_for( + &self, + shard: ShardIdentifier, + account: &AccountId, + ) -> Vec>; + + /// returns all shards which are currently present in the tops in the pool + fn get_shards(&self) -> Vec; + + /// returns all shards which are handled by our worker + fn list_handled_shards(&self) -> Vec; + + /// Remove a collection of trusted operations from the pool. + /// Return operations that were not successfully removed. + fn remove_calls_from_pool( + &self, + shard: ShardIdentifier, + executed_calls: Vec<(TrustedOperationOrHash, bool)>, + ) -> Vec>; + + /// Submit a request to watch. + /// + /// See [`TrustedOperationStatus`](sp_transaction_pool::TrustedOperationStatus) for details on transaction + /// life cycle. + fn watch_top(&self, request: R) -> PoolFuture; + + /// Submit a request to watch and broadcasts it to known peers. + fn watch_and_broadcast_top( + &self, + request: R, + json_rpc_method: String, + ) -> PoolFuture; + + /// Litentry: set the rpc response value + fn update_connection_state(&self, updates: Vec<(Hash, (Vec, bool))>); + + /// Litentry: swap the old hash with the new one in rpc connection registry + fn swap_rpc_connection_hash(&self, old_hash: Hash, new_hash: Hash); +} + +/// Trait to notify listeners/observer of a newly created block +pub trait OnBlockImported { + type Hash; + + fn on_block_imported(&self, hashes: &[Self::Hash], block_hash: SidechainBlockHash); +} diff --git a/bitacross-worker/core-primitives/top-pool/Cargo.toml b/bitacross-worker/core-primitives/top-pool/Cargo.toml new file mode 100644 index 0000000000..21f6f89ea7 --- /dev/null +++ b/bitacross-worker/core-primitives/top-pool/Cargo.toml @@ -0,0 +1,66 @@ +[package] +name = "itp-top-pool" +version = "0.9.0" +authors = ['Trust Computing GmbH ', 'Integritee AG '] +edition = "2021" + +[dependencies] +# sgx dependencies +sgx_tstd = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git", optional = true, features = ["net", "thread", "untrusted_time"] } + +# local dependencies +itc-direct-rpc-server = { path = "../../core/direct-rpc-server", default-features = false } +itp-stf-primitives = { path = "../stf-primitives", default-features = false } +itp-types = { path = "../types", default-features = false } +its-primitives = { path = "../../sidechain/primitives", default-features = false } + +# sgx enabled external libraries +jsonrpc-core_sgx = { package = "jsonrpc-core", git = "https://github.com/scs/jsonrpc", branch = "no_std_v18", default-features = false, optional = true } +linked-hash-map_sgx = { package = "linked-hash-map", git = "https://github.com/mesalock-linux/linked-hash-map-sgx", optional = true } + +# std compatible external libraries (make sure these versions match with the sgx-enabled ones above) +jsonrpc-core = { version = "18", optional = true } +linked-hash-map = { version = "0.5.2", optional = true } + +# no-std compatible libraries +byteorder = { version = "1.4.2", default-features = false } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +derive_more = { version = "0.99.5" } +log = { version = "0.4", default-features = false } +sp-core = { default-features = false, features = ["full_crypto"], git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } +sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } + +# dev dependencies (for tests) +[dev-dependencies] +parity-util-mem = { version = "0.12.0", default-features = false, features = ["primitive-types"] } +itp-test = { path = "../test", default-features = false } +serde = { version = "1.0", default-features = false, features = ["alloc", "derive"] } +sp-application-crypto = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } +# litentry +litentry-primitives = { path = "../../litentry/primitives", default-features = false } + +[features] +default = ["std"] +sgx = [ + "sgx_tstd", + "itc-direct-rpc-server/sgx", + "jsonrpc-core_sgx", + "linked-hash-map_sgx", + # litentry + "litentry-primitives/sgx", +] +std = [ + "itc-direct-rpc-server/std", + "itp-types/std", + "its-primitives/std", + "jsonrpc-core", + "linked-hash-map", + "log/std", + "serde/std", + "sp-core/std", + "sp-runtime/std", + "sp-application-crypto/std", + # litentry + "litentry-primitives/std", +] +mocks = [] diff --git a/bitacross-worker/core-primitives/top-pool/src/base_pool.rs b/bitacross-worker/core-primitives/top-pool/src/base_pool.rs new file mode 100644 index 0000000000..a6cb0628a0 --- /dev/null +++ b/bitacross-worker/core-primitives/top-pool/src/base_pool.rs @@ -0,0 +1,1379 @@ +// This file is part of Substrate. + +// Copyright (C) 2018-2021 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 basic version of the dependency graph. +//! +//! For a more full-featured pool, have a look at the `pool` module. + +pub extern crate alloc; +use crate::{ + error, + future::{FutureTrustedOperations, WaitingTrustedOperations}, + primitives::{InPoolOperation, PoolStatus, TrustedOperationSource as Source, TxHash}, + ready::ReadyOperations, +}; +use alloc::{fmt, sync::Arc, vec, vec::Vec}; +use core::iter; +use itp_stf_primitives::types::ShardIdentifier; +use log::{debug, trace, warn}; +use sp_core::hexdisplay::HexDisplay; +use sp_runtime::transaction_validity::{ + TransactionLongevity as Longevity, TransactionPriority as Priority, TransactionTag as Tag, +}; +use std::collections::HashSet; + +/// Successful import result. +#[derive(Debug, PartialEq, Eq)] +pub enum Imported { + /// TrustedOperation was successfully imported to Ready queue. + Ready { + /// Hash of operation that was successfully imported. + hash: TxHash, + /// operations that got promoted from the Future queue. + promoted: Vec, + /// operations that failed to be promoted from the Future queue and are now discarded. + failed: Vec, + /// operations removed from the Ready pool (replaced). + removed: Vec>>, + }, + /// TrustedOperation was successfully imported to Future queue. + Future { + /// Hash of operation that was successfully imported. + hash: TxHash, + }, +} + +impl Imported { + /// Returns the hash of imported operation. + pub fn hash(&self) -> &TxHash { + use self::Imported::*; + match *self { + Ready { ref hash, .. } => hash, + Future { ref hash, .. } => hash, + } + } +} + +/// Status of pruning the queue. +#[derive(Debug)] +pub struct PruneStatus { + /// A list of imports that satisfying the tag triggered. + pub promoted: Vec>, + /// A list of operations that failed to be promoted and now are discarded. + pub failed: Vec, + /// A list of operations that got pruned from the ready queue. + pub pruned: Vec>>, +} + +/// Immutable operation +#[derive(PartialEq, Eq, Clone)] +pub struct TrustedOperation { + /// Raw extrinsic representing that operation. + pub data: Extrinsic, + /// Number of bytes encoding of the operation requires. + pub bytes: usize, + /// TrustedOperation hash (unique) + pub hash: TxHash, + /// TrustedOperation priority (higher = better) + pub priority: Priority, + /// At which block the operation becomes invalid? + pub valid_till: Longevity, + /// Tags required by the operation. + pub requires: Vec, + /// Tags that this operation provides. + pub provides: Vec, + /// Should that operation be propagated. + pub propagate: bool, + /// Source of that operation. + pub source: Source, +} + +impl AsRef for TrustedOperation { + fn as_ref(&self) -> &Extrinsic { + &self.data + } +} + +impl InPoolOperation for TrustedOperation { + type TrustedOperation = Extrinsic; + + fn data(&self) -> &Extrinsic { + &self.data + } + + fn hash(&self) -> TxHash { + self.hash + } + + fn priority(&self) -> &Priority { + &self.priority + } + + fn longevity(&self) -> &Longevity { + &self.valid_till + } + + fn requires(&self) -> &[Tag] { + &self.requires + } + + fn provides(&self) -> &[Tag] { + &self.provides + } + + fn is_propagable(&self) -> bool { + self.propagate + } +} + +impl TrustedOperation { + /// Explicit operation clone. + /// + /// TrustedOperation should be cloned only if absolutely necessary && we want + /// every reason to be commented. That's why we `TrustedOperation` is not `Clone`, + /// but there's explicit `duplicate` method. + pub fn duplicate(&self) -> Self { + TrustedOperation { + data: self.data.clone(), + bytes: self.bytes, + hash: self.hash, + priority: self.priority, + source: self.source, + valid_till: self.valid_till, + requires: self.requires.clone(), + provides: self.provides.clone(), + propagate: self.propagate, + } + } +} + +impl fmt::Debug for TrustedOperation +where + Extrinsic: fmt::Debug, +{ + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fn print_tags(fmt: &mut fmt::Formatter, tags: &[Tag]) -> fmt::Result { + let mut it = tags.iter(); + if let Some(t) = it.next() { + write!(fmt, "{}", HexDisplay::from(t))?; + } + for t in it { + write!(fmt, ",{}", HexDisplay::from(t))?; + } + Ok(()) + } + + write!(fmt, "TrustedOperation {{ ")?; + write!(fmt, "hash: {:?}, ", &self.hash)?; + write!(fmt, "priority: {:?}, ", &self.priority)?; + write!(fmt, "valid_till: {:?}, ", &self.valid_till)?; + write!(fmt, "bytes: {:?}, ", &self.bytes)?; + write!(fmt, "propagate: {:?}, ", &self.propagate)?; + write!(fmt, "source: {:?}, ", &self.source)?; + write!(fmt, "requires: [")?; + print_tags(fmt, &self.requires)?; + write!(fmt, "], provides: [")?; + print_tags(fmt, &self.provides)?; + write!(fmt, "], ")?; + write!(fmt, "data: {:?}", &self.data)?; + write!(fmt, "}}")?; + Ok(()) + } +} + +/// Store last pruned tags for given number of invocations. +const RECENTLY_PRUNED_TAGS: usize = 2; + +/// TrustedOperation pool. +/// +/// Builds a dependency graph for all operations in the pool and returns +/// the ones that are currently ready to be executed. +/// +/// General note: +/// If function returns some operations it usually means that importing them +/// as-is for the second time will fail or produce unwanted results. +/// Most likely it is required to revalidate them and recompute set of +/// required tags. +#[derive(Debug)] +pub struct BasePool { + reject_future_operations: bool, + future: FutureTrustedOperations, + ready: ReadyOperations, + /// Store recently pruned tags (for last two invocations). + /// + /// This is used to make sure we don't accidentally put + /// operations to future in case they were just stuck in verification. + recently_pruned: [HashSet; RECENTLY_PRUNED_TAGS], + recently_pruned_index: usize, +} + +impl Default for BasePool { + fn default() -> Self { + Self::new(false) + } +} + +impl BasePool { + /// Create new pool given reject_future_operations flag. + pub fn new(reject_future_operations: bool) -> Self { + BasePool { + reject_future_operations, + future: Default::default(), + ready: Default::default(), + recently_pruned: Default::default(), + recently_pruned_index: 0, + } + } + + /// Temporary enables future operations, runs closure and then restores + /// `reject_future_operations` flag back to previous value. + /// + /// The closure accepts the mutable reference to the pool and original value + /// of the `reject_future_operations` flag. + pub(crate) fn with_futures_enabled( + &mut self, + closure: impl FnOnce(&mut Self, bool) -> T, + ) -> T { + let previous = self.reject_future_operations; + self.reject_future_operations = false; + let return_value = closure(self, previous); + self.reject_future_operations = previous; + return_value + } + + /// Returns if the operation for the given hash is already imported. + pub fn is_imported(&self, tx_hash: &TxHash, shard: ShardIdentifier) -> bool { + self.future.contains(tx_hash, shard) || self.ready.contains(tx_hash, shard) + } + + /// Imports operations to the pool. + /// + /// The pool consists of two parts: Future and Ready. + /// The former contains operations that require some tags that are not yet provided by + /// other operations in the pool. + /// The latter contains operations that have all the requirements satisfied and are + /// ready to be included in the block. + pub fn import( + &mut self, + tx: TrustedOperation, + shard: ShardIdentifier, + ) -> error::Result> { + if self.is_imported(&tx.hash, shard) { + return Err(error::Error::AlreadyImported) + } + + let tx = WaitingTrustedOperations::new( + tx, + self.ready.provided_tags(shard), + &self.recently_pruned, + ); + trace!(target: "txpool", "[{:?}] {:?}", tx.operation.hash, tx); + debug!( + target: "txpool", + "[{:?}] Importing to {}", + tx.operation.hash, + if tx.is_ready() { "ready" } else { "future" } + ); + + // If all tags are not satisfied import to future. + if !tx.is_ready() { + if self.reject_future_operations { + return Err(error::Error::RejectedFutureTrustedOperation) + } + + let hash = tx.operation.hash; + self.future.import(tx, shard); + return Ok(Imported::Future { hash }) + } + + self.import_to_ready(tx, shard) + } + + /// Imports operations to ready queue. + /// + /// NOTE the operation has to have all requirements satisfied. + fn import_to_ready( + &mut self, + tx: WaitingTrustedOperations, + shard: ShardIdentifier, + ) -> error::Result> { + let hash = tx.operation.hash; + let mut promoted = vec![]; + let mut failed = vec![]; + let mut removed = vec![]; + + let mut first = true; + let mut to_import = vec![tx]; + + while let Some(tx) = to_import.pop() { + // find operation in Future that it unlocks + to_import.append(&mut self.future.satisfy_tags(&tx.operation.provides, shard)); + + // import this operation + let current_hash = tx.operation.hash; + match self.ready.import(tx, shard) { + Ok(mut replaced) => { + if !first { + promoted.push(current_hash); + } + // The operations were removed from the ready pool. We might attempt to re-import them. + removed.append(&mut replaced); + }, + // operation failed to be imported. + Err(e) => + if first { + debug!(target: "txpool", "[{:?}] Error importing", current_hash,); + return Err(e) + } else { + failed.push(current_hash); + }, + } + first = false; + } + + // An edge case when importing operation caused + // some future operations to be imported and that + // future operations pushed out current operation. + // This means that there is a cycle and the operations should + // be moved back to future, since we can't resolve it. + if removed.iter().any(|tx| tx.hash == hash) { + // We still need to remove all operations that we promoted + // since they depend on each other and will never get to the best iterator. + self.ready.remove_subtree(&promoted, shard); + + debug!(target: "txpool", "[{:?}] Cycle detected, bailing.", hash); + return Err(error::Error::CycleDetected) + } + + Ok(Imported::Ready { hash, promoted, failed, removed }) + } + + /// Returns an iterator over ready operations in the pool. + pub fn ready(&self, shard: ShardIdentifier) -> impl Iterator>> { + self.ready.get(shard) + } + + /// Returns an iterator over all shards in the pool. + pub fn get_shards(&self) -> impl Iterator { + self.ready.get_shards() + } + + /// Returns an iterator over future operations in the pool. + pub fn futures(&self, shard: ShardIdentifier) -> impl Iterator> { + self.future.all(shard) + } + + /// Returns pool operations given list of hashes. + /// + /// Includes both ready and future pool. For every hash in the `hashes` + /// iterator an `Option` is produced (so the resulting `Vec` always have the same length). + pub fn by_hashes( + &self, + hashes: &[TxHash], + shard: ShardIdentifier, + ) -> Vec>>> { + let ready = self.ready.by_hashes(hashes, shard); + let future = self.future.by_hashes(hashes, shard); + + ready.into_iter().zip(future).map(|(a, b)| a.or(b)).collect() + } + + /// Returns pool operation by hash. + pub fn ready_by_hash( + &self, + hash: &TxHash, + shard: ShardIdentifier, + ) -> Option>> { + self.ready.by_hash(hash, shard) + } + + /// Makes sure that the operations in the queues stay within provided limits. + /// + /// Removes and returns worst operations from the queues and all operations that depend on them. + /// Technically the worst operation should be evaluated by computing the entire pending set. + /// We use a simplified approach to remove the operation that occupies the pool for the longest time. + pub fn enforce_limits( + &mut self, + ready: &Limit, + future: &Limit, + shard: ShardIdentifier, + ) -> Vec>> { + let mut removed = vec![]; + + while ready.is_exceeded(self.ready.len(shard), self.ready.bytes(shard)) { + // find the worst operation + let minimal = self.ready.fold( + |minimal, current| { + let operation = ¤t.operation; + match minimal { + None => Some(operation.clone()), + Some(ref tx) if tx.insertion_id > operation.insertion_id => + Some(operation.clone()), + other => other, + } + }, + shard, + ); + + if let Some(minimal) = minimal { + removed.append(&mut self.remove_subtree(&[minimal.operation.hash], shard)) + } else { + break + } + } + + while future.is_exceeded(self.future.len(shard), self.future.bytes(shard)) { + // find the worst operation + let minimal = self.future.fold( + |minimal, current| { + match minimal { + None => Some(current.clone()), + /*Some(ref tx) if tx.imported_at > current.imported_at => { + Some(current.clone()) + },*/ + other => other, + } + }, + shard, + ); + + if let Some(minimal) = minimal { + removed.append(&mut self.remove_subtree(&[minimal.operation.hash], shard)) + } else { + break + } + } + + removed + } + + /// Removes all operations represented by the hashes and all other operations + /// that depend on them. + /// + /// Returns a list of actually removed operations. + /// NOTE some operations might still be valid, but were just removed because + /// they were part of a chain, you may attempt to re-import them later. + /// NOTE If you want to remove ready operations that were already used + /// and you don't want them to be stored in the pool use `prune_tags` method. + pub fn remove_subtree( + &mut self, + hashes: &[TxHash], + shard: ShardIdentifier, + ) -> Vec>> { + let mut removed = self.ready.remove_subtree(hashes, shard); + removed.extend(self.future.remove(hashes, shard)); + removed + } + + /// Removes and returns all operations from the future queue. + pub fn clear_future(&mut self, shard: ShardIdentifier) -> Vec>> { + self.future.clear(shard) + } + + /// Prunes operations that provide given list of tags. + /// + /// This will cause all operations that provide these tags to be removed from the pool, + /// but unlike `remove_subtree`, dependent operations are not touched. + /// Additional operations from future queue might be promoted to ready if you satisfy tags + /// that the pool didn't previously know about. + pub fn prune_tags( + &mut self, + tags: impl IntoIterator, + shard: ShardIdentifier, + ) -> PruneStatus { + let mut to_import = vec![]; + let mut pruned = vec![]; + let recently_pruned = &mut self.recently_pruned[self.recently_pruned_index]; + self.recently_pruned_index = (self.recently_pruned_index + 1) % RECENTLY_PRUNED_TAGS; + recently_pruned.clear(); + + for tag in tags { + // make sure to promote any future operations that could be unlocked + to_import.append(&mut self.future.satisfy_tags(iter::once(&tag), shard)); + // and actually prune operations in ready queue + pruned.append(&mut self.ready.prune_tags(tag.clone(), shard)); + // store the tags for next submission + recently_pruned.insert(tag); + } + + let mut promoted = vec![]; + let mut failed = vec![]; + for tx in to_import { + let hash = tx.operation.hash; + match self.import_to_ready(tx, shard) { + Ok(res) => promoted.push(res), + Err(_e) => { + warn!(target: "txpool", "[{:?}] Failed to promote during pruning", hash); + failed.push(hash) + }, + } + } + + PruneStatus { promoted, failed, pruned } + } + + /// Get pool status. + pub fn status(&self, shard: ShardIdentifier) -> PoolStatus { + PoolStatus { + ready: self.ready.len(shard), + ready_bytes: self.ready.bytes(shard), + future: self.future.len(shard), + future_bytes: self.future.bytes(shard), + } + } +} + +/// Queue limits +#[derive(Debug, Clone)] +pub struct Limit { + /// Maximal number of operations in the queue. + pub count: usize, + /// Maximal size of encodings of all operations in the queue. + pub total_bytes: usize, +} + +impl Limit { + /// Returns true if any of the provided values exceeds the limit. + pub fn is_exceeded(&self, count: usize, bytes: usize) -> bool { + self.count < count || self.total_bytes < bytes + } +} + +#[cfg(test)] +pub mod tests { + + use super::*; + use alloc::borrow::ToOwned; + use itp_types::H256; + + fn hash(index: u8) -> H256 { + [index; 32].into() + } + + fn test_pool() -> BasePool> { + BasePool::default() + } + + #[test] + pub fn test_should_import_transaction_to_ready() { + // given + let mut pool = test_pool(); + let shard = ShardIdentifier::default(); + + // when + pool.import( + TrustedOperation { + data: vec![1u8], + bytes: 1, + hash: hash(1), + priority: 5u64, + valid_till: 64u64, + requires: vec![], + provides: vec![vec![1]], + propagate: true, + source: Source::External, + }, + shard, + ) + .unwrap(); + + // then + assert_eq!(pool.ready(shard).count(), 1); + assert_eq!(pool.ready.len(shard), 1); + } + + #[test] + pub fn test_should_not_import_same_transaction_twice() { + // given + let mut pool = test_pool(); + let shard = ShardIdentifier::default(); + + // when + pool.import( + TrustedOperation { + data: vec![1u8], + bytes: 1, + hash: hash(1), + priority: 5u64, + valid_till: 64u64, + requires: vec![], + provides: vec![vec![1]], + propagate: true, + source: Source::External, + }, + shard, + ) + .unwrap(); + pool.import( + TrustedOperation { + data: vec![1u8], + bytes: 1, + hash: hash(1), + priority: 5u64, + valid_till: 64u64, + requires: vec![], + provides: vec![vec![1]], + propagate: true, + source: Source::External, + }, + shard, + ) + .unwrap_err(); + + // then + assert_eq!(pool.ready(shard).count(), 1); + assert_eq!(pool.ready.len(shard), 1); + } + + #[test] + pub fn test_should_import_transaction_to_future_and_promote_it_later() { + // given + let mut pool = test_pool(); + let shard = ShardIdentifier::default(); + + // when + pool.import( + TrustedOperation { + data: vec![1u8], + bytes: 1, + hash: hash(1), + priority: 5u64, + valid_till: 64u64, + requires: vec![vec![0]], + provides: vec![vec![1]], + propagate: true, + source: Source::External, + }, + shard, + ) + .unwrap(); + assert_eq!(pool.ready(shard).count(), 0); + assert_eq!(pool.ready.len(shard), 0); + pool.import( + TrustedOperation { + data: vec![2u8], + bytes: 1, + hash: hash(2), + priority: 5u64, + valid_till: 64u64, + requires: vec![], + provides: vec![vec![0]], + propagate: true, + source: Source::External, + }, + shard, + ) + .unwrap(); + + // then + assert_eq!(pool.ready(shard).count(), 2); + assert_eq!(pool.ready.len(shard), 2); + } + + #[test] + pub fn test_should_promote_a_subgraph() { + // given + let mut pool = test_pool(); + let shard = ShardIdentifier::default(); + + // when + pool.import( + TrustedOperation { + data: vec![1u8], + bytes: 1, + hash: hash(1), + priority: 5u64, + valid_till: 64u64, + requires: vec![vec![0]], + provides: vec![vec![1]], + propagate: true, + source: Source::External, + }, + shard, + ) + .unwrap(); + pool.import( + TrustedOperation { + data: vec![3u8], + bytes: 1, + hash: hash(3), + priority: 5u64, + valid_till: 64u64, + requires: vec![vec![2]], + provides: vec![], + propagate: true, + source: Source::External, + }, + shard, + ) + .unwrap(); + pool.import( + TrustedOperation { + data: vec![2u8], + bytes: 1, + hash: hash(2), + priority: 5u64, + valid_till: 64u64, + requires: vec![vec![1]], + provides: vec![vec![3], vec![2]], + propagate: true, + source: Source::External, + }, + shard, + ) + .unwrap(); + pool.import( + TrustedOperation { + data: vec![4u8], + bytes: 1, + hash: hash(4), + priority: 1_000u64, + valid_till: 64u64, + requires: vec![vec![3], vec![4]], + provides: vec![], + propagate: true, + source: Source::External, + }, + shard, + ) + .unwrap(); + assert_eq!(pool.ready(shard).count(), 0); + assert_eq!(pool.ready.len(shard), 0); + + let res = pool + .import( + TrustedOperation { + data: vec![5u8], + bytes: 1, + hash: hash(5), + priority: 5u64, + valid_till: 64u64, + requires: vec![], + provides: vec![vec![0], vec![4]], + propagate: true, + source: Source::External, + }, + shard, + ) + .unwrap(); + + // then + let mut it = pool.ready(shard).into_iter().map(|tx| tx.data[0]); + + assert_eq!(it.next(), Some(5)); + assert_eq!(it.next(), Some(1)); + assert_eq!(it.next(), Some(2)); + assert_eq!(it.next(), Some(4)); + assert_eq!(it.next(), Some(3)); + assert_eq!(it.next(), None); + assert_eq!( + res, + Imported::Ready { + hash: hash(5), + promoted: vec![hash(1), hash(2), hash(3), hash(4)], + failed: vec![], + removed: vec![] + } + ); + } + + #[test] + pub fn test_should_handle_a_cycle() { + // given + let shard = ShardIdentifier::default(); + let mut pool = test_pool(); + pool.import( + TrustedOperation { + data: vec![1u8], + bytes: 1, + hash: hash(1), + priority: 5u64, + valid_till: 64u64, + requires: vec![vec![0]], + provides: vec![vec![1]], + propagate: true, + source: Source::External, + }, + shard, + ) + .unwrap(); + pool.import( + TrustedOperation { + data: vec![3u8], + bytes: 1, + hash: hash(3), + priority: 5u64, + valid_till: 64u64, + requires: vec![vec![1]], + provides: vec![vec![2]], + propagate: true, + source: Source::External, + }, + shard, + ) + .unwrap(); + assert_eq!(pool.ready(shard).count(), 0); + assert_eq!(pool.ready.len(shard), 0); + + // when + pool.import( + TrustedOperation { + data: vec![2u8], + bytes: 1, + hash: hash(2), + priority: 5u64, + valid_till: 64u64, + requires: vec![vec![2]], + provides: vec![vec![0]], + propagate: true, + source: Source::External, + }, + shard, + ) + .unwrap(); + + // then + { + let mut it = pool.ready(shard).into_iter().map(|tx| tx.data[0]); + assert_eq!(it.next(), None); + } + // all operations occupy the Future queue - it's fine + assert_eq!(pool.future.len(shard), 3); + + // let's close the cycle with one additional operation + let res = pool + .import( + TrustedOperation { + data: vec![4u8], + bytes: 1, + hash: hash(4), + priority: 50u64, + valid_till: 64u64, + requires: vec![], + provides: vec![vec![0]], + propagate: true, + source: Source::External, + }, + shard, + ) + .unwrap(); + let mut it = pool.ready(shard).into_iter().map(|tx| tx.data[0]); + assert_eq!(it.next(), Some(4)); + assert_eq!(it.next(), Some(1)); + assert_eq!(it.next(), Some(3)); + assert_eq!(it.next(), None); + assert_eq!( + res, + Imported::Ready { + hash: hash(4), + promoted: vec![hash(1), hash(3)], + failed: vec![hash(2)], + removed: vec![] + } + ); + assert_eq!(pool.future.len(shard), 0); + } + + #[test] + pub fn test_should_handle_a_cycle_with_low_priority() { + // given + let mut pool = test_pool(); + let shard = ShardIdentifier::default(); + pool.import( + TrustedOperation { + data: vec![1u8], + bytes: 1, + hash: hash(1), + priority: 5u64, + valid_till: 64u64, + requires: vec![vec![0]], + provides: vec![vec![1]], + propagate: true, + source: Source::External, + }, + shard, + ) + .unwrap(); + pool.import( + TrustedOperation { + data: vec![3u8], + bytes: 1, + hash: hash(3), + priority: 5u64, + valid_till: 64u64, + requires: vec![vec![1]], + provides: vec![vec![2]], + propagate: true, + source: Source::External, + }, + shard, + ) + .unwrap(); + assert_eq!(pool.ready(shard).count(), 0); + assert_eq!(pool.ready.len(shard), 0); + + // when + pool.import( + TrustedOperation { + data: vec![2u8], + bytes: 1, + hash: hash(2), + priority: 5u64, + valid_till: 64u64, + requires: vec![vec![2]], + provides: vec![vec![0]], + propagate: true, + source: Source::External, + }, + shard, + ) + .unwrap(); + + // then + { + let mut it = pool.ready(shard).into_iter().map(|tx| tx.data[0]); + assert_eq!(it.next(), None); + } + // all operations occupy the Future queue - it's fine + assert_eq!(pool.future.len(shard), 3); + + // let's close the cycle with one additional operation + let err = pool + .import( + TrustedOperation { + data: vec![4u8], + bytes: 1, + hash: hash(4), + priority: 1u64, // lower priority than Tx(2) + valid_till: 64u64, + requires: vec![], + provides: vec![vec![0]], + propagate: true, + source: Source::External, + }, + shard, + ) + .unwrap_err(); + let mut it = pool.ready(shard).into_iter().map(|tx| tx.data[0]); + assert_eq!(it.next(), None); + assert_eq!(pool.ready.len(shard), 0); + assert_eq!(pool.future.len(shard), 0); + if let error::Error::CycleDetected = err { + } else { + assert!(false, "Invalid error kind: {:?}", err); + } + } + + #[test] + pub fn test_can_track_heap_size() { + let mut pool = test_pool(); + let shard = ShardIdentifier::default(); + pool.import( + TrustedOperation { + data: vec![5u8; 1024], + bytes: 1, + hash: hash(5), + priority: 5u64, + valid_till: 64u64, + requires: vec![], + provides: vec![vec![0], vec![4]], + propagate: true, + source: Source::External, + }, + shard, + ) + .expect("import 1 should be ok"); + pool.import( + TrustedOperation { + data: vec![3u8; 1024], + bytes: 1, + hash: hash(7), + priority: 5u64, + valid_till: 64u64, + requires: vec![], + provides: vec![vec![2], vec![7]], + propagate: true, + source: Source::External, + }, + shard, + ) + .expect("import 2 should be ok"); + + //assert!(parity_util_mem::malloc_size(&pool) > 5000); + } + + #[test] + pub fn test_should_remove_invalid_transactions() { + // given + let shard = ShardIdentifier::default(); + let mut pool = test_pool(); + pool.import( + TrustedOperation { + data: vec![5u8], + bytes: 1, + hash: hash(5), + priority: 5u64, + valid_till: 64u64, + requires: vec![], + provides: vec![vec![0], vec![4]], + propagate: true, + source: Source::External, + }, + shard, + ) + .unwrap(); + pool.import( + TrustedOperation { + data: vec![1u8], + bytes: 1, + hash: hash(1), + priority: 5u64, + valid_till: 64u64, + requires: vec![vec![0]], + provides: vec![vec![1]], + propagate: true, + source: Source::External, + }, + shard, + ) + .unwrap(); + pool.import( + TrustedOperation { + data: vec![3u8], + bytes: 1, + hash: hash(3), + priority: 5u64, + valid_till: 64u64, + requires: vec![vec![2]], + provides: vec![], + propagate: true, + source: Source::External, + }, + shard, + ) + .unwrap(); + pool.import( + TrustedOperation { + data: vec![2u8], + bytes: 1, + hash: hash(2), + priority: 5u64, + valid_till: 64u64, + requires: vec![vec![1]], + provides: vec![vec![3], vec![2]], + propagate: true, + source: Source::External, + }, + shard, + ) + .unwrap(); + pool.import( + TrustedOperation { + data: vec![4u8], + bytes: 1, + hash: hash(4), + priority: 1_000u64, + valid_till: 64u64, + requires: vec![vec![3], vec![4]], + provides: vec![], + propagate: true, + source: Source::External, + }, + shard, + ) + .unwrap(); + // future + pool.import( + TrustedOperation { + data: vec![6u8], + bytes: 1, + hash: hash(6), + priority: 1_000u64, + valid_till: 64u64, + requires: vec![vec![11]], + provides: vec![], + propagate: true, + source: Source::External, + }, + shard, + ) + .unwrap(); + assert_eq!(pool.ready(shard).count(), 5); + assert_eq!(pool.future.len(shard), 1); + + // when + pool.remove_subtree(&[hash(6), hash(1)], shard); + + // then + assert_eq!(pool.ready(shard).count(), 1); + assert_eq!(pool.future.len(shard), 0); + } + + #[test] + pub fn test_should_prune_ready_transactions() { + // given + let mut pool = test_pool(); + let shard = ShardIdentifier::default(); + // future (waiting for 0) + pool.import( + TrustedOperation { + data: vec![5u8], + bytes: 1, + hash: hash(5), + priority: 5u64, + valid_till: 64u64, + requires: vec![vec![0]], + provides: vec![vec![100]], + propagate: true, + source: Source::External, + }, + shard, + ) + .unwrap(); + // ready + pool.import( + TrustedOperation { + data: vec![1u8], + bytes: 1, + hash: hash(1), + priority: 5u64, + valid_till: 64u64, + requires: vec![], + provides: vec![vec![1]], + propagate: true, + source: Source::External, + }, + shard, + ) + .unwrap(); + pool.import( + TrustedOperation { + data: vec![2u8], + bytes: 1, + hash: hash(2), + priority: 5u64, + valid_till: 64u64, + requires: vec![vec![2]], + provides: vec![vec![3]], + propagate: true, + source: Source::External, + }, + shard, + ) + .unwrap(); + pool.import( + TrustedOperation { + data: vec![3u8], + bytes: 1, + hash: hash(3), + priority: 5u64, + valid_till: 64u64, + requires: vec![vec![1]], + provides: vec![vec![2]], + propagate: true, + source: Source::External, + }, + shard, + ) + .unwrap(); + pool.import( + TrustedOperation { + data: vec![4u8], + bytes: 1, + hash: hash(4), + priority: 1_000u64, + valid_till: 64u64, + requires: vec![vec![3], vec![2]], + provides: vec![vec![4]], + propagate: true, + source: Source::External, + }, + shard, + ) + .unwrap(); + + assert_eq!(pool.ready(shard).count(), 4); + assert_eq!(pool.future.len(shard), 1); + + // when + let result = pool.prune_tags(vec![vec![0], vec![2]], shard); + + // then + assert_eq!(result.pruned.len(), 2); + assert_eq!(result.failed.len(), 0); + assert_eq!( + result.promoted[0], + Imported::Ready { hash: hash(5), promoted: vec![], failed: vec![], removed: vec![] } + ); + assert_eq!(result.promoted.len(), 1); + assert_eq!(pool.future.len(shard), 0); + assert_eq!(pool.ready.len(shard), 3); + assert_eq!(pool.ready(shard).count(), 3); + } + + #[test] + pub fn test_transaction_debug() { + assert_eq!( + format!( + "{:?}", + TrustedOperation { + data: vec![4u8], + bytes: 1, + hash: hash(4), + priority: 1_000u64, + valid_till: 64u64, + requires: vec![vec![3], vec![2]], + provides: vec![vec![4]], + propagate: true, + source: Source::External, + } + ), + "TrustedOperation { \ +hash: 0x0404040404040404040404040404040404040404040404040404040404040404, priority: 1000, valid_till: 64, bytes: 1, propagate: true, \ +source: External, requires: [03,02], provides: [04], data: [4]}" + .to_owned() + ); + } + + #[test] + pub fn test_transaction_propagation() { + assert!(TrustedOperation { + data: vec![4u8], + bytes: 1, + hash: hash(4), + priority: 1_000u64, + valid_till: 64u64, + requires: vec![vec![3], vec![2]], + provides: vec![vec![4]], + propagate: true, + source: Source::External, + } + .is_propagable()); + + assert!(!TrustedOperation { + data: vec![4u8], + bytes: 1, + hash: hash(4), + priority: 1_000u64, + valid_till: 64u64, + requires: vec![vec![3], vec![2]], + provides: vec![vec![4]], + propagate: false, + source: Source::External, + } + .is_propagable()); + } + + #[test] + pub fn test_should_reject_future_transactions() { + // given + let mut pool = test_pool(); + let shard = ShardIdentifier::default(); + + // when + pool.reject_future_operations = true; + + // then + let err = pool.import( + TrustedOperation { + data: vec![5u8], + bytes: 1, + hash: hash(5), + priority: 5u64, + valid_till: 64u64, + requires: vec![vec![0]], + provides: vec![], + propagate: true, + source: Source::External, + }, + shard, + ); + + if let Err(error::Error::RejectedFutureTrustedOperation) = err { + } else { + assert!(false, "Invalid error kind: {:?}", err); + } + } + + #[test] + pub fn test_should_clear_future_queue() { + // given + let mut pool = test_pool(); + let shard = ShardIdentifier::default(); + + // when + pool.import( + TrustedOperation { + data: vec![5u8], + bytes: 1, + hash: hash(5), + priority: 5u64, + valid_till: 64u64, + requires: vec![vec![0]], + provides: vec![], + propagate: true, + source: Source::External, + }, + shard, + ) + .unwrap(); + + // then + assert_eq!(pool.future.len(shard), 1); + + // and then when + assert_eq!(pool.clear_future(shard).len(), 1); + + // then + assert_eq!(pool.future.len(shard), 0); + } + + #[test] + pub fn test_should_accept_future_transactions_when_explicitly_asked_to() { + // given + let mut pool = test_pool(); + pool.reject_future_operations = true; + let shard = ShardIdentifier::default(); + + // when + let flag_value = pool.with_futures_enabled(|pool, flag| { + pool.import( + TrustedOperation { + data: vec![5u8], + bytes: 1, + hash: hash(5), + priority: 5u64, + valid_till: 64u64, + requires: vec![vec![0]], + provides: vec![], + propagate: true, + source: Source::External, + }, + shard, + ) + .unwrap(); + + flag + }); + + // then + assert!(flag_value); + assert!(pool.reject_future_operations); + assert_eq!(pool.future.len(shard), 1); + } +} diff --git a/bitacross-worker/core-primitives/top-pool/src/basic_pool.rs b/bitacross-worker/core-primitives/top-pool/src/basic_pool.rs new file mode 100644 index 0000000000..577898f4f0 --- /dev/null +++ b/bitacross-worker/core-primitives/top-pool/src/basic_pool.rs @@ -0,0 +1,258 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 extern crate alloc; + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +use crate::sgx_reexport_prelude::*; + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +use std::sync::SgxMutex as Mutex; + +#[cfg(feature = "std")] +use std::sync::Mutex; + +use crate::{ + base_pool::TrustedOperation, + error::IntoPoolError, + pool::{ChainApi, Options as PoolOptions, Pool}, + primitives::{ + ImportNotificationStream, PoolFuture, PoolStatus, TrustedOperationPool, + TrustedOperationSource, TxHash, + }, +}; +use alloc::{boxed::Box, string::String, sync::Arc}; +use codec::Encode; +use core::{marker::PhantomData, pin::Pin}; +use itc_direct_rpc_server::SendRpcResponse; +use itp_stf_primitives::{traits::PoolTransactionValidation, types::ShardIdentifier}; +use its_primitives::types::BlockHash as SidechainBlockHash; +use jsonrpc_core::futures::{ + channel::oneshot, + future::{ready, Future, FutureExt}, +}; +use sp_runtime::{ + generic::BlockId, + traits::{Block as BlockT, NumberFor, Zero}, +}; +use std::{collections::HashMap, vec, vec::Vec}; + +type BoxedReadyIterator = Box>> + Send>; + +type ReadyIteratorFor = BoxedReadyIterator; + +type PolledIterator = Pin> + Send>>; + +struct ReadyPoll { + updated_at: NumberFor, + pollers: Vec<(NumberFor, oneshot::Sender)>, +} + +impl Default for ReadyPoll { + fn default() -> Self { + Self { updated_at: NumberFor::::zero(), pollers: Default::default() } + } +} + +impl ReadyPoll { + #[allow(unused)] + fn trigger(&mut self, number: NumberFor, iterator_factory: impl Fn() -> T) { + self.updated_at = number; + + let mut idx = 0; + while idx < self.pollers.len() { + if self.pollers[idx].0 <= number { + let poller_sender = self.pollers.swap_remove(idx); + let _ = poller_sender.1.send(iterator_factory()); + } else { + idx += 1; + } + } + } + + fn add(&mut self, number: NumberFor) -> oneshot::Receiver { + let (sender, receiver) = oneshot::channel(); + self.pollers.push((number, sender)); + receiver + } + + fn updated_at(&self) -> NumberFor { + self.updated_at + } +} + +/// Basic implementation of operation pool that can be customized by providing PoolApi. +pub struct BasicPool +where + Block: BlockT, + PoolApi: ChainApi + 'static, + RpcResponse: SendRpcResponse, +{ + pool: Arc>, + _api: Arc, + ready_poll: Arc, Block>>>, + _phantom: PhantomData, +} + +impl BasicPool +where + Block: BlockT, + PoolApi: ChainApi + 'static, + RpcResponse: SendRpcResponse, + TOP: Clone + Encode + PoolTransactionValidation + core::fmt::Debug + Sync + Send, +{ + /// Create new basic operation pool with provided api and custom + /// revalidation type. + pub fn create( + options: PoolOptions, + pool_api: Arc, + rpc_response_sender: Arc, + //prometheus: Option<&PrometheusRegistry>, + //revalidation_type: RevalidationType, + //spawner: impl SpawnNamed, + ) -> Self + where + ::Error: IntoPoolError, + { + let pool = Arc::new(Pool::new(options, pool_api.clone(), rpc_response_sender)); + BasicPool { + _api: pool_api, + pool, + ready_poll: Default::default(), + _phantom: Default::default(), + } + } +} + +// FIXME: obey clippy +#[allow(clippy::type_complexity)] +impl TrustedOperationPool + for BasicPool +where + Block: BlockT, + PoolApi: ChainApi + 'static, + ::Error: IntoPoolError, + RpcResponse: SendRpcResponse + 'static, + TOP: Send + Sync + PoolTransactionValidation + core::fmt::Debug + Encode + Clone + 'static, +{ + type Block = PoolApi::Block; + type InPoolOperation = TrustedOperation; + type Error = PoolApi::Error; + + fn submit_at( + &self, + at: &BlockId, + source: TrustedOperationSource, + ops: Vec, + shard: ShardIdentifier, + ) -> PoolFuture>, Self::Error> { + let pool = self.pool.clone(); + let at = *at; + async move { pool.submit_at(&at, source, ops, shard).await }.boxed() + } + + fn submit_one( + &self, + at: &BlockId, + source: TrustedOperationSource, + op: TOP, + shard: ShardIdentifier, + ) -> PoolFuture { + let pool = self.pool.clone(); + let at = *at; + async move { pool.submit_one(&at, source, op, shard).await }.boxed() + } + + fn submit_and_watch( + &self, + at: &BlockId, + source: TrustedOperationSource, + xt: TOP, + shard: ShardIdentifier, + ) -> PoolFuture { + let at = *at; + let pool = self.pool.clone(); + async move { pool.submit_and_watch(&at, source, xt, shard).await }.boxed() + } + + fn ready_at(&self, at: NumberFor, shard: ShardIdentifier) -> PolledIterator { + if self.ready_poll.lock().unwrap().updated_at() >= at { + let iterator: ReadyIteratorFor = Box::new(self.pool.validated_pool().ready(shard)); + return Box::pin(ready(iterator)) + } + + Box::pin(self.ready_poll.lock().unwrap().add(at).map(|received| { + received.unwrap_or_else(|e| { + log::warn!("Error receiving pending set: {:?}", e); + Box::new(vec![].into_iter()) + }) + })) + } + + fn ready(&self, shard: ShardIdentifier) -> ReadyIteratorFor { + Box::new(self.pool.validated_pool().ready(shard)) + } + + fn shards(&self) -> Vec { + self.pool.validated_pool().shards() + } + + fn remove_invalid( + &self, + hashes: &[TxHash], + shard: ShardIdentifier, + inblock: bool, + ) -> Vec> { + self.pool.validated_pool().remove_invalid(hashes, shard, inblock) + } + + fn status(&self, shard: ShardIdentifier) -> PoolStatus { + self.pool.validated_pool().status(shard) + } + + fn import_notification_stream(&self) -> ImportNotificationStream { + self.pool.validated_pool().import_notification_stream() + } + + fn on_broadcasted(&self, propagations: HashMap>) { + self.pool.validated_pool().on_broadcasted(propagations) + } + + fn hash_of(&self, xt: &TOP) -> TxHash { + self.pool.hash_of(xt) + } + + fn ready_transaction( + &self, + hash: &TxHash, + shard: ShardIdentifier, + ) -> Option> { + self.pool.validated_pool().ready_by_hash(hash, shard) + } + + fn on_block_imported(&self, hashes: &[TxHash], block_hash: SidechainBlockHash) { + self.pool.validated_pool().on_block_imported(hashes, block_hash); + } + + fn update_connection_state(&self, updates: Vec<(TxHash, (Vec, bool))>) { + self.pool.validated_pool().update_connection_state(updates); + } + + fn swap_rpc_connection_hash(&self, old_hash: TxHash, new_hash: TxHash) { + self.pool.validated_pool().swap_rpc_connection_hash(old_hash, new_hash); + } +} diff --git a/bitacross-worker/core-primitives/top-pool/src/error.rs b/bitacross-worker/core-primitives/top-pool/src/error.rs new file mode 100644 index 0000000000..47029b30e1 --- /dev/null +++ b/bitacross-worker/core-primitives/top-pool/src/error.rs @@ -0,0 +1,95 @@ +// This file is part of Substrate. + +// 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. + +//! TrustedOperation pool errors. + +use derive_more::{Display, From}; +use sp_runtime::transaction_validity::TransactionPriority as Priority; +use std::string::String; + +/// TrustedOperation pool result. +pub type Result = std::result::Result; + +/// TrustedOperation pool error type. +#[derive(Debug, From, Display)] +#[allow(missing_docs)] +pub enum Error { + #[display(fmt = "Unknown trusted operation")] + UnknownTrustedOperation, + + #[display(fmt = "Invalid trusted operation")] + InvalidTrustedOperation, + + /// Incorrect extrinsic format. + + /// The operation validity returned no "provides" tag. + /// + /// Such operations are not accepted to the pool, since we use those tags + /// to define identity of operations (occupance of the same "slot"). + #[display(fmt = "Trusted Operation does not provide any tags, so the pool can't identify it")] + NoTagsProvided, + + #[display(fmt = "Trusted Operation temporarily Banned")] + TemporarilyBanned, + + #[display(fmt = "Already imported")] + AlreadyImported, + + #[display(fmt = "Too low priority")] + TooLowPriority(Priority), + + #[display(fmt = "TrustedOperation with cyclic dependency")] + CycleDetected, + + #[display(fmt = "TrustedOperation couldn't enter the pool because of the limit")] + ImmediatelyDropped, + + #[from(ignore)] + #[display(fmt = "Invalid Block")] + InvalidBlockId(String), + + #[display(fmt = "The pool is not accepting future trusted operations")] + RejectedFutureTrustedOperation, + + #[display(fmt = "Extrinsic verification error")] + #[from(ignore)] + Verification, + + #[display(fmt = "Failed to send result of trusted operation to RPC client")] + FailedToSendUpdateToRpcClient(String), + + #[display(fmt = "Failed to unlock pool (mutex)")] + UnlockError, +} + +/// TrustedOperation pool error conversion. +pub trait IntoPoolError: Send + Sized { + /// Try to extract original `Error` + /// + /// This implementation is optional and used only to + /// provide more descriptive error messages for end users + /// of RPC API. + fn into_pool_error(self) -> std::result::Result { + Err(self) + } +} + +impl IntoPoolError for Error { + fn into_pool_error(self) -> std::result::Result { + Ok(self) + } +} diff --git a/bitacross-worker/core-primitives/top-pool/src/future.rs b/bitacross-worker/core-primitives/top-pool/src/future.rs new file mode 100644 index 0000000000..2ceb34827e --- /dev/null +++ b/bitacross-worker/core-primitives/top-pool/src/future.rs @@ -0,0 +1,316 @@ +// This file is part of Substrate. + +// Copyright (C) 2018-2021 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 . + +pub extern crate alloc; + +use crate::{base_pool::TrustedOperation, primitives::TxHash}; +use alloc::{boxed::Box, fmt, sync::Arc, vec, vec::Vec}; + +use itp_stf_primitives::types::ShardIdentifier; +use sp_core::hexdisplay::HexDisplay; +use sp_runtime::transaction_validity::TransactionTag as Tag; +use std::{ + collections::{HashMap, HashSet}, + time::Instant, +}; + +/// TrustedOperation with partially satisfied dependencies. +pub struct WaitingTrustedOperations { + /// TrustedOperation details. + pub operation: Arc>, + /// Tags that are required and have not been satisfied yet by other operations in the pool. + pub missing_tags: HashSet, + /// Time of import to the Future Queue. + pub imported_at: Instant, +} + +impl fmt::Debug for WaitingTrustedOperations { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + write!(fmt, "WaitingTrustedOperations {{ ")?; + //write!(fmt, "imported_at: {:?}, ", self.imported_at)?; + write!(fmt, "operation: {:?}, ", self.operation)?; + write!(fmt, "missing_tags: {{")?; + let mut it = self.missing_tags.iter().map(HexDisplay::from); + if let Some(tag) = it.next() { + write!(fmt, "{}", tag)?; + } + for tag in it { + write!(fmt, ", {}", tag)?; + } + write!(fmt, " }}}}") + } +} + +impl Clone for WaitingTrustedOperations { + fn clone(&self) -> Self { + WaitingTrustedOperations { + operation: self.operation.clone(), + missing_tags: self.missing_tags.clone(), + imported_at: self.imported_at, + } + } +} + +impl WaitingTrustedOperations { + /// Creates a new `WaitingTrustedOperations`. + /// + /// Computes the set of missing tags based on the requirements and tags that + /// are provided by all operations in the ready queue. + pub fn new( + operation: TrustedOperation, + provided: Option<&HashMap>, + recently_pruned: &[HashSet], + ) -> Self { + let missing_tags = operation + .requires + .iter() + .filter(|tag| { + // is true if the tag is already satisfied either via operation in the pool + // or one that was recently included. + + let is_provided = recently_pruned.iter().any(|x| x.contains(&**tag)) + || match provided { + Some(tags) => tags.contains_key(&**tag), + None => false, + }; + + !is_provided + }) + .cloned() + .collect(); + + WaitingTrustedOperations { + operation: Arc::new(operation), + missing_tags, + imported_at: Instant::now(), + } + } + + /// Marks the tag as satisfied. + // FIXME: obey clippy + #[allow(clippy::ptr_arg)] + pub fn satisfy_tag(&mut self, tag: &Tag) { + self.missing_tags.remove(tag); + } + + /// Returns true if operation has all requirements satisfied. + pub fn is_ready(&self) -> bool { + self.missing_tags.is_empty() + } +} + +/// A pool of operations that are not yet ready to be included in the block. +/// +/// Contains operations that are still awaiting for some other operations that +/// could provide a tag that they require. +#[derive(Debug)] +pub struct FutureTrustedOperations { + /// tags that are not yet provided by any operation and we await for them + wanted_tags: HashMap>>, + /// Transactions waiting for a particular other operation + waiting: HashMap>>, +} + +impl Default for FutureTrustedOperations { + fn default() -> Self { + FutureTrustedOperations { wanted_tags: Default::default(), waiting: Default::default() } + } +} + +const WAITING_PROOF: &str = r"# +In import we always insert to `waiting` if we push to `wanted_tags`; +when removing from `waiting` we always clear `wanted_tags`; +every hash from `wanted_tags` is always present in `waiting`; +qed +#"; + +#[allow(clippy::len_without_is_empty)] +impl FutureTrustedOperations { + /// Import operation to Future queue. + /// + /// Only operations that don't have all their tags satisfied should occupy + /// the Future queue. + /// As soon as required tags are provided by some other operations that are ready + /// we should remove the operations from here and move them to the Ready queue. + pub fn import(&mut self, tx: WaitingTrustedOperations, shard: ShardIdentifier) { + assert!(!tx.is_ready(), "TrustedOperation is ready."); + if let Some(tx_pool_waiting) = self.waiting.get(&shard) { + assert!( + !tx_pool_waiting.contains_key(&tx.operation.hash), + "TrustedOperation is already imported." + ); + } + + let tx_pool_waiting_map = self.waiting.entry(shard).or_insert_with(HashMap::new); + let tx_pool_wanted_map = self.wanted_tags.entry(shard).or_insert_with(HashMap::new); + // Add all tags that are missing + for tag in &tx.missing_tags { + let entry = tx_pool_wanted_map.entry(tag.clone()).or_insert_with(HashSet::new); + entry.insert(tx.operation.hash); + } + + // Add the operation to a by-hash waiting map + tx_pool_waiting_map.insert(tx.operation.hash, tx); + } + + /// Returns true if given hash is part of the queue. + pub fn contains(&self, hash: &TxHash, shard: ShardIdentifier) -> bool { + if let Some(tx_pool_waiting) = self.waiting.get(&shard) { + return tx_pool_waiting.contains_key(hash) + } + false + } + + /// Returns a list of known operations + pub fn by_hashes( + &self, + hashes: &[TxHash], + shard: ShardIdentifier, + ) -> Vec>>> { + if let Some(tx_pool_waiting) = self.waiting.get(&shard) { + return hashes + .iter() + .map(|h| tx_pool_waiting.get(h).map(|x| x.operation.clone())) + .collect() + } + vec![] + } + + /// Satisfies provided tags in operations that are waiting for them. + /// + /// Returns (and removes) operations that became ready after their last tag got + /// satisfied and now we can remove them from Future and move to Ready queue. + pub fn satisfy_tags>( + &mut self, + tags: impl IntoIterator, + shard: ShardIdentifier, + ) -> Vec> { + let mut became_ready = vec![]; + + for tag in tags { + if let Some(tx_pool_wanted) = self.wanted_tags.get_mut(&shard) { + if let Some(hashes) = tx_pool_wanted.remove(tag.as_ref()) { + if let Some(tx_pool_waiting) = self.waiting.get_mut(&shard) { + for hash in hashes { + let is_ready = { + let tx = tx_pool_waiting.get_mut(&hash).expect(WAITING_PROOF); + tx.satisfy_tag(tag.as_ref()); + tx.is_ready() + }; + + if is_ready { + let tx = tx_pool_waiting.remove(&hash).expect(WAITING_PROOF); + became_ready.push(tx); + } + } + } + } + } + } + + became_ready + } + + /// Removes operations for given list of hashes. + /// + /// Returns a list of actually removed operations. + pub fn remove( + &mut self, + hashes: &[TxHash], + shard: ShardIdentifier, + ) -> Vec>> { + let mut removed = vec![]; + if let Some(tx_pool_waiting) = self.waiting.get_mut(&shard) { + if let Some(tx_pool_wanted) = self.wanted_tags.get_mut(&shard) { + for hash in hashes { + if let Some(waiting_tx) = tx_pool_waiting.remove(hash) { + // remove from wanted_tags as well + for tag in waiting_tx.missing_tags { + let remove = if let Some(wanted) = tx_pool_wanted.get_mut(&tag) { + wanted.remove(hash); + wanted.is_empty() + } else { + false + }; + if remove { + tx_pool_wanted.remove(&tag); + } + } + // add to result + removed.push(waiting_tx.operation) + } + } + } + } + removed + } + + /// Fold a list of future operations to compute a single value. + pub fn fold, &WaitingTrustedOperations) -> Option>( + &mut self, + f: F, + shard: ShardIdentifier, + ) -> Option { + if let Some(tx_pool) = self.waiting.get(&shard) { + return tx_pool.values().fold(None, f) + } + None + } + + /// Returns iterator over all future operations + pub fn all( + &self, + shard: ShardIdentifier, + ) -> Box> + '_> { + if let Some(tx_pool) = self.waiting.get(&shard) { + return Box::new(tx_pool.values().map(|waiting| &*waiting.operation)) + } + Box::new(core::iter::empty()) + } + + /// Removes and returns all future operations. + pub fn clear(&mut self, shard: ShardIdentifier) -> Vec>> { + if let Some(wanted_tx_pool) = self.wanted_tags.get_mut(&shard) { + wanted_tx_pool.clear(); + return self + .waiting + .get_mut(&shard) + .unwrap() + .drain() + .map(|(_, tx)| tx.operation) + .collect() + } + vec![] + } + + /// Returns number of operations in the Future queue. + pub fn len(&self, shard: ShardIdentifier) -> usize { + if let Some(tx_pool) = self.waiting.get(&shard) { + return tx_pool.len() + } + 0 + } + + /// Returns sum of encoding lengths of all operations in this queue. + pub fn bytes(&self, shard: ShardIdentifier) -> usize { + if let Some(tx_pool) = self.waiting.get(&shard) { + return tx_pool.values().fold(0, |acc, tx| acc + tx.operation.bytes) + } + 0 + } +} diff --git a/bitacross-worker/core-primitives/top-pool/src/lib.rs b/bitacross-worker/core-primitives/top-pool/src/lib.rs new file mode 100644 index 0000000000..fdd46ff9fe --- /dev/null +++ b/bitacross-worker/core-primitives/top-pool/src/lib.rs @@ -0,0 +1,47 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg(all(feature = "std", feature = "sgx"))] +compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the same time"); + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +extern crate sgx_tstd as std; + +// re-export module to properly feature gate sgx and regular std environment +#[cfg(all(not(feature = "std"), feature = "sgx"))] +pub mod sgx_reexport_prelude { + pub use jsonrpc_core_sgx as jsonrpc_core; + pub use linked_hash_map_sgx as linked_hash_map; +} + +pub mod base_pool; +pub mod basic_pool; +pub mod error; +pub mod future; +pub mod listener; +pub mod pool; +pub mod primitives; +pub mod ready; +pub mod rotator; +pub mod tracked_map; +pub mod validated_pool; +pub mod watcher; + +#[cfg(any(test, feature = "mocks"))] +pub mod mocks; diff --git a/bitacross-worker/core-primitives/top-pool/src/listener.rs b/bitacross-worker/core-primitives/top-pool/src/listener.rs new file mode 100644 index 0000000000..0e069597cb --- /dev/null +++ b/bitacross-worker/core-primitives/top-pool/src/listener.rs @@ -0,0 +1,185 @@ +// 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 . + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +use crate::sgx_reexport_prelude::*; + +use crate::{primitives::TxHash, watcher::Watcher}; + +use itc_direct_rpc_server::SendRpcResponse; +use itp_types::BlockHash as SidechainBlockHash; +use linked_hash_map::LinkedHashMap; +use log::{debug, trace}; + +use std::{collections::HashMap, string::String, sync::Arc, vec, vec::Vec}; + +/// Extrinsic pool default listener. +#[derive(Default)] +pub struct Listener +where + R: SendRpcResponse, +{ + watchers: HashMap>, + finality_watchers: LinkedHashMap>, + rpc_response_sender: Arc, +} + +/// Maximum number of blocks awaiting finality at any time. +const MAX_FINALITY_WATCHERS: usize = 512; + +impl Listener +where + R: SendRpcResponse, +{ + pub fn new(rpc_response_sender: Arc) -> Self { + Listener { + watchers: Default::default(), + finality_watchers: Default::default(), + rpc_response_sender, + } + } + + fn fire(&mut self, hash: &TxHash, fun: F) + where + F: FnOnce(&mut Watcher), + { + let clean = if let Some(h) = self.watchers.get_mut(hash) { + fun(h); + h.is_done() + } else { + false + }; + + if clean { + self.watchers.remove(hash); + } + } + + /// 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: TxHash) { + let new_watcher = Watcher::new_watcher(hash, self.rpc_response_sender.clone()); + self.watchers.insert(hash, new_watcher); + } + + /// Notify the listeners about extrinsic broadcast. + pub fn broadcasted(&mut self, hash: &TxHash, peers: Vec) { + trace!(target: "txpool", "[{:?}] Broadcasted", hash); + self.fire(hash, |watcher| watcher.broadcast(peers)); + } + + /// Notify listeners about top execution. + pub fn top_executed(&mut self, hash: &TxHash, response: &[u8], force_wait: bool) { + trace!(target: "txpool", "[{:?}] Top Executed", hash); + self.fire(hash, |watcher| watcher.top_executed(response, force_wait)); + } + + /// New operation was added to the ready pool or promoted from the future pool. + pub fn ready(&mut self, tx: &TxHash, old: Option<&TxHash>) { + 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()); + } + } + + /// New operation was added to the future pool. + pub fn future(&mut self, tx: &TxHash) { + trace!(target: "txpool", "[{:?}] Future", tx); + self.fire(tx, |watcher| watcher.future()); + } + + /// TrustedOperation was dropped from the pool because of the limit. + pub fn dropped(&mut self, tx: &TxHash, by: Option<&TxHash>) { + trace!(target: "txpool", "[{:?}] Dropped (replaced with {:?})", tx, by); + self.fire(tx, |watcher| match by { + Some(_) => watcher.usurped(), + None => watcher.dropped(), + }) + } + + /// TrustedOperation was removed as invalid. + pub fn invalid(&mut self, tx: &TxHash) { + self.fire(tx, |watcher| watcher.invalid()); + } + + /// TrustedOperation was pruned from the pool. + #[allow(clippy::or_fun_call)] + pub fn pruned(&mut self, block_hash: SidechainBlockHash, tx: &TxHash) { + debug!(target: "txpool", "[{:?}] Pruned at {:?}", tx, block_hash); + self.fire(tx, |s| s.in_block(block_hash)); + self.finality_watchers.entry(block_hash).or_insert(vec![]).push(*tx); + + while self.finality_watchers.len() > MAX_FINALITY_WATCHERS { + if let Some((_hash, txs)) = self.finality_watchers.pop_front() { + for tx in txs { + self.fire(&tx, |s| s.finality_timeout()); + } + } + } + } + + /// TrustedOperation in block. + pub fn in_block(&mut self, tx: &TxHash, block_hash: SidechainBlockHash) { + self.fire(tx, |s| s.in_block(block_hash)); + } + + /// The block this operation was included in has been retracted. + pub fn retracted(&mut self, block_hash: SidechainBlockHash) { + if let Some(hashes) = self.finality_watchers.remove(&block_hash) { + for hash in hashes { + self.fire(&hash, |s| s.retracted()) + } + } + } + + /// Notify all watchers that operations have been finalized + pub fn finalized(&mut self, block_hash: SidechainBlockHash) { + 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()) + } + } + } + + /// Litentry: set the rpc response value and force_wait flag for a given TrustedOperation `tx`. + pub fn update_connection_state( + &mut self, + tx: &TxHash, + encoded_value: Vec, + force_wait: bool, + ) { + self.fire(tx, |s| s.update_connection_state(encoded_value, force_wait)); + } + + /// Litentry: swap the old hash with the new one in rpc connection registry + pub fn swap_rpc_connection_hash(&mut self, old_hash: TxHash, new_hash: TxHash) { + log::debug!("Swapping connection {:?} to {:?}", &old_hash, &new_hash); + // It's possible that the old top (hash) is already removed from the pool when we + // request to swap hashes, in this case we just create one to facilitate the swap + if let Some(w) = self.watchers.get(&old_hash) { + w.swap_rpc_connection_hash(new_hash); + } else { + // do not insert it to `watchers`, will be deallocated if it goes out of scope + Watcher::new_watcher(old_hash, self.rpc_response_sender.clone()) + .swap_rpc_connection_hash(new_hash); + } + } +} diff --git a/bitacross-worker/core-primitives/top-pool/src/mocks/mod.rs b/bitacross-worker/core-primitives/top-pool/src/mocks/mod.rs new file mode 100644 index 0000000000..81b1c65ebe --- /dev/null +++ b/bitacross-worker/core-primitives/top-pool/src/mocks/mod.rs @@ -0,0 +1,22 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +#[cfg(any(test, feature = "mocks"))] +pub mod rpc_responder_mock; + +#[cfg(feature = "mocks")] +pub mod trusted_operation_pool_mock; diff --git a/bitacross-worker/core-primitives/top-pool/src/mocks/rpc_responder_mock.rs b/bitacross-worker/core-primitives/top-pool/src/mocks/rpc_responder_mock.rs new file mode 100644 index 0000000000..766b92def8 --- /dev/null +++ b/bitacross-worker/core-primitives/top-pool/src/mocks/rpc_responder_mock.rs @@ -0,0 +1,76 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 itc_direct_rpc_server::{DirectRpcResult, RpcHash, SendRpcResponse}; +use itp_types::TrustedOperationStatus; +use std::{marker::PhantomData, vec::Vec}; + +pub struct RpcResponderMock { + _hash: PhantomData, +} + +impl RpcResponderMock { + pub fn new() -> Self { + RpcResponderMock { _hash: PhantomData } + } +} + +impl Default for RpcResponderMock { + fn default() -> Self { + Self::new() + } +} + +impl SendRpcResponse for RpcResponderMock +where + Hash: RpcHash, +{ + type Hash = Hash; + + fn update_status_event( + &self, + _hash: Self::Hash, + _status_update: TrustedOperationStatus, + ) -> DirectRpcResult<()> { + Ok(()) + } + + fn send_state(&self, _hash: Self::Hash, _state_encoded: Vec) -> DirectRpcResult<()> { + Ok(()) + } + + fn update_force_wait(&self, _hash: Self::Hash, _force_wait: bool) -> DirectRpcResult<()> { + Ok(()) + } + + fn update_connection_state( + &self, + _hash: Self::Hash, + _encoded_value: Vec, + _force_wait: bool, + ) -> DirectRpcResult<()> { + Ok(()) + } + + fn swap_hash(&self, _old_hash: Self::Hash, _new_hash: Self::Hash) -> DirectRpcResult<()> { + Ok(()) + } + + fn is_force_wait(&self, _hash: Self::Hash) -> bool { + false + } +} diff --git a/bitacross-worker/core-primitives/top-pool/src/mocks/trusted_operation_pool_mock.rs b/bitacross-worker/core-primitives/top-pool/src/mocks/trusted_operation_pool_mock.rs new file mode 100644 index 0000000000..72f5514da6 --- /dev/null +++ b/bitacross-worker/core-primitives/top-pool/src/mocks/trusted_operation_pool_mock.rs @@ -0,0 +1,227 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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(all(not(feature = "std"), feature = "sgx"))] +use crate::sgx_reexport_prelude::*; + +#[cfg(feature = "sgx")] +use std::sync::SgxRwLock as RwLock; + +#[cfg(feature = "std")] +use std::sync::RwLock; + +use crate::{ + base_pool::TrustedOperation, + error::Error, + primitives::{ + ImportNotificationStream, PoolFuture, PoolStatus, TrustedOperationPool, + TrustedOperationSource, TxHash, + }, +}; +use codec::Encode; +use core::{future::Future, pin::Pin}; + +use itp_types::{Block, BlockHash as SidechainBlockHash, ShardIdentifier, H256}; +use jsonrpc_core::futures::future::ready; +use sp_runtime::{ + generic::BlockId, + traits::{BlakeTwo256, Hash, NumberFor}, +}; +use std::{boxed::Box, collections::HashMap, string::String, sync::Arc, vec, vec::Vec}; + +/// Mock for the trusted operation pool +/// +/// To be used in unit tests +pub struct TrustedOperationPoolMock { + submitted_transactions: RwLock>>, +} + +/// Transaction payload +#[derive(Clone, PartialEq)] +pub struct TxPayload { + pub block_id: BlockId< as TrustedOperationPool>::Block>, + pub source: TrustedOperationSource, + pub xts: Vec, + pub shard: ShardIdentifier, +} + +impl Default for TrustedOperationPoolMock { + fn default() -> Self { + TrustedOperationPoolMock:: { submitted_transactions: RwLock::new(HashMap::new()) } + } +} + +impl TrustedOperationPoolMock { + pub fn get_last_submitted_transactions(&self) -> HashMap> { + let transactions = self.submitted_transactions.read().unwrap(); + transactions.clone() + } + + fn map_stf_top_to_tx(stf_top: &TOP) -> Arc> { + Arc::new(TrustedOperation:: { + data: stf_top.clone(), + bytes: 0, + hash: hash_of_top(stf_top), + priority: 0u64, + valid_till: 0u64, + requires: vec![], + provides: vec![], + propagate: false, + source: TrustedOperationSource::External, + }) + } +} + +impl TrustedOperationPool for TrustedOperationPoolMock +where + TOP: Encode + Clone + Sync + Send + 'static, +{ + type Block = Block; + type InPoolOperation = TrustedOperation; + type Error = Error; + + #[allow(clippy::type_complexity)] + fn submit_at( + &self, + at: &BlockId, + source: TrustedOperationSource, + xts: Vec, + shard: ShardIdentifier, + ) -> PoolFuture>, Self::Error> { + let mut transactions = self.submitted_transactions.write().unwrap(); + transactions.insert(shard, TxPayload { block_id: *at, source, xts: xts.clone(), shard }); + + let top_hashes: Vec> = + xts.iter().map(|top| Ok(hash_of_top(top))).collect(); + + Box::pin(ready(Ok(top_hashes))) + } + + fn submit_one( + &self, + at: &BlockId, + source: TrustedOperationSource, + xt: TOP, + shard: ShardIdentifier, + ) -> PoolFuture { + let mut transactions = self.submitted_transactions.write().unwrap(); + transactions + .insert(shard, TxPayload { block_id: *at, source, xts: vec![xt.clone()], shard }); + + let top_hash = hash_of_top(&xt); + + Box::pin(ready(Ok(top_hash))) + } + + fn submit_and_watch( + &self, + at: &BlockId, + source: TrustedOperationSource, + xt: TOP, + shard: ShardIdentifier, + ) -> PoolFuture { + self.submit_one(at, source, xt, shard) + } + + #[allow(clippy::type_complexity)] + fn ready_at( + &self, + _at: NumberFor, + _shard: ShardIdentifier, + ) -> Pin< + Box< + dyn Future> + Send>> + Send, + >, + > { + unimplemented!() + } + + #[allow(clippy::type_complexity)] + fn ready( + &self, + shard: ShardIdentifier, + ) -> Box> + Send> { + let transactions = self.submitted_transactions.read().unwrap(); + let ready_transactions = transactions + .get(&shard) + .map(|payload| payload.xts.iter().map(Self::map_stf_top_to_tx).collect()) + .unwrap_or_else(Vec::new); + Box::new(ready_transactions.into_iter()) + } + + fn shards(&self) -> Vec { + let transactions = self.submitted_transactions.read().unwrap(); + transactions.iter().map(|(shard, _)| *shard).collect() + } + + fn remove_invalid( + &self, + _hashes: &[TxHash], + _shard: ShardIdentifier, + _inblock: bool, + ) -> Vec> { + Vec::new() + } + + fn status(&self, shard: ShardIdentifier) -> PoolStatus { + let transactions = self.submitted_transactions.read().unwrap(); + transactions + .get(&shard) + .map(|payload| PoolStatus { + ready: payload.xts.len(), + ready_bytes: 0, + future: 0, + future_bytes: 0, + }) + .unwrap_or_else(default_pool_status) + } + + fn import_notification_stream(&self) -> ImportNotificationStream { + unimplemented!() + } + + fn on_broadcasted(&self, _propagations: HashMap>) { + unimplemented!() + } + + fn hash_of(&self, xt: &TOP) -> TxHash { + hash_of_top(xt) + } + + fn ready_transaction( + &self, + _hash: &TxHash, + _shard: ShardIdentifier, + ) -> Option> { + unimplemented!() + } + + fn on_block_imported(&self, _hashes: &[TxHash], _block_hash: SidechainBlockHash) {} + + fn update_connection_state(&self, _updates: Vec<(TxHash, (Vec, bool))>) {} + + fn swap_rpc_connection_hash(&self, _old_hash: TxHash, _new_hash: TxHash) {} +} + +fn default_pool_status() -> PoolStatus { + PoolStatus { ready: 0, ready_bytes: 0, future: 0, future_bytes: 0 } +} + +fn hash_of_top(top: &TOP) -> H256 { + top.using_encoded(|x| BlakeTwo256::hash(x)) +} diff --git a/bitacross-worker/core-primitives/top-pool/src/pool.rs b/bitacross-worker/core-primitives/top-pool/src/pool.rs new file mode 100644 index 0000000000..17a8fcbd5b --- /dev/null +++ b/bitacross-worker/core-primitives/top-pool/src/pool.rs @@ -0,0 +1,818 @@ +// 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 . + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +use crate::sgx_reexport_prelude::*; +use core::{fmt::Debug, marker::PhantomData}; + +use crate::{ + base_pool as base, error, + primitives::{TrustedOperationSource, TxHash}, + validated_pool::{ValidatedOperation, ValidatedPool}, +}; +use codec::Encode; +use core::matches; +use itc_direct_rpc_server::SendRpcResponse; +use itp_stf_primitives::{traits::PoolTransactionValidation, types::ShardIdentifier}; +use itp_types::BlockHash as SidechainBlockHash; +use jsonrpc_core::futures::{channel::mpsc::Receiver, future, Future}; +use sp_runtime::{ + generic::BlockId, + traits::{self, Block as BlockT, SaturatedConversion}, + transaction_validity::{TransactionTag as Tag, TransactionValidity, TransactionValidityError}, +}; +use std::{collections::HashMap, format, sync::Arc, time::Instant, vec::Vec}; + +/// Modification notification event stream type; +pub type EventStream = Receiver; + +/// 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 operation stored in the pool +pub type TransactionFor = Arc>; +/// A type of validated operation stored in the pool. +pub type ValidatedOperationFor = ValidatedOperation::Error>; + +/// Concrete extrinsic validation and query logic. +pub trait ChainApi: Send + Sync { + /// Block type. + type Block: BlockT; + /// Error type. + type Error: From; + /// Validate operation future. + type ValidationFuture: Future> + Send + Unpin; + /// Body future (since block body might be remote) + type BodyFuture: Future, Self::Error>> + Unpin + Send + 'static; + + /// Verify extrinsic at given block. + fn validate_transaction( + &self, + source: TrustedOperationSource, + uxt: TOP, + shard: ShardIdentifier, + ) -> Self::ValidationFuture; + + /// Returns a block number given the block id. + 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>; + + /// Returns hash and encoding length of the extrinsic. + fn hash_and_length(&self, uxt: &TOP) -> (TxHash, usize); + + /// Returns a block body given the block id. + fn block_body(&self, at: &BlockId) -> Self::BodyFuture; +} + +/// Pool configuration options. +#[derive(Debug, Clone)] +pub struct Options { + /// Ready queue limits. + pub ready: base::Limit, + /// Future queue limits. + pub future: base::Limit, + /// Reject future operations. + pub reject_future_operations: bool, +} + +impl Default for Options { + fn default() -> Self { + Options { + ready: base::Limit { count: 8192, total_bytes: 20 * 1024 * 1024 }, + future: base::Limit { count: 512, total_bytes: 1024 * 1024 }, + reject_future_operations: false, + } + } +} + +/// Should we check that the operation is banned +/// in the pool, before we verify it? +#[derive(Copy, Clone)] +enum CheckBannedBeforeVerify { + Yes, + No, +} + +/// Extrinsics pool that performs validation. +pub struct Pool +where + R: SendRpcResponse, +{ + validated_pool: Arc>, + _phantom: PhantomData, +} + +impl Pool +where + ::Error: error::IntoPoolError, + R: SendRpcResponse, + TOP: Encode + Clone + PoolTransactionValidation + core::fmt::Debug + Send + Sync, +{ + /// Create a new operation pool. + pub fn new(options: Options, api: Arc, rpc_response_sender: Arc) -> Self { + Pool { + validated_pool: Arc::new(ValidatedPool::new(options, api, rpc_response_sender)), + _phantom: Default::default(), + } + } + + /// Imports a bunch of unverified extrinsics to the pool + pub async fn submit_at( + &self, + at: &BlockId, + source: TrustedOperationSource, + xts: impl IntoIterator, + shard: ShardIdentifier, + ) -> Result>, B::Error> { + let xts = xts.into_iter().map(|xt| (source, xt)); + let validated_transactions = + self.verify(at, xts, CheckBannedBeforeVerify::Yes, shard).await?; + Ok(self.validated_pool.submit(validated_transactions.into_values(), shard)) + } + + /// Resubmit the given extrinsics to the pool. + /// + /// This does not check if a operation is banned, before we verify it again. + pub async fn resubmit_at( + &self, + at: &BlockId, + source: TrustedOperationSource, + xts: impl IntoIterator, + shard: ShardIdentifier, + ) -> Result>, B::Error> { + let xts = xts.into_iter().map(|xt| (source, xt)); + let validated_transactions = + self.verify(at, xts, CheckBannedBeforeVerify::No, shard).await?; + Ok(self.validated_pool.submit(validated_transactions.into_values(), shard)) + } + + /// Imports one unverified extrinsic to the pool + pub async fn submit_one( + &self, + at: &BlockId, + source: TrustedOperationSource, + xt: TOP, + shard: ShardIdentifier, + ) -> Result { + let res = self.submit_at(at, source, std::iter::once(xt), shard).await?.pop(); + res.expect("One extrinsic passed; one result returned; qed") + } + + /// Import a single extrinsic and starts to watch their progress in the pool. + pub async fn submit_and_watch( + &self, + at: &BlockId, + source: TrustedOperationSource, + xt: TOP, + shard: ShardIdentifier, + ) -> Result { + //TODO + //let block_number = self.resolve_block_number(at)?; + // dummy value: + let block_number = 0; + let (_, tx) = self + .verify_one(at, block_number, source, xt, CheckBannedBeforeVerify::Yes, shard) + .await; + self.validated_pool.submit_and_watch(tx, shard) + } + + /// Resubmit some operation that were validated elsewhere. + pub fn resubmit( + &self, + revalidated_transactions: HashMap>, + shard: ShardIdentifier, + ) { + let now = Instant::now(); + self.validated_pool.resubmit(revalidated_transactions, shard); + log::debug!(target: "txpool", + "Resubmitted. Took {} ms. Status: {:?}", + now.elapsed().as_millis(), + self.validated_pool.status(shard) + ); + } + + /// Prunes known ready operations. + /// + /// Used to clear the pool from operations that were part of recently imported block. + /// The main difference from the `prune` is that we do not revalidate any operations + /// and ignore unknown passed hashes. + pub fn prune_known( + &self, + at: &BlockId, + hashes: &[TxHash], + shard: ShardIdentifier, + ) -> Result<(), B::Error> { + // Get details of all extrinsics that are already in the pool + #[allow(clippy::filter_map_identity)] + // false positive. Filter map does filter because x is an option + let in_pool_tags = self + .validated_pool + .extrinsics_tags(hashes, shard) + .into_iter() + .filter_map(|x| x) + .flatten(); + + // Prune all operations that provide given tags + let prune_status = self.validated_pool.prune_tags(in_pool_tags, shard)?; + let pruned_transactions = + hashes.iter().cloned().chain(prune_status.pruned.iter().map(|tx| tx.hash)); + self.validated_pool.fire_pruned(at, pruned_transactions) + } + + /// Prunes ready operations. + /// + /// Used to clear the pool from operations that were part of recently imported block. + /// To perform pruning we need the tags that each extrinsic provides and to avoid calling + /// into runtime too often we first lookup all extrinsics that are in the pool and get + /// their provided tags from there. Otherwise we query the runtime at the `parent` block. + pub async fn prune( + &self, + at: &BlockId, + _parent: &BlockId, + extrinsics: &[TOP], + shard: ShardIdentifier, + ) -> Result<(), B::Error> { + log::debug!( + target: "txpool", + "Starting pruning of block {:?} (extrinsics: {})", + at, + extrinsics.len() + ); + // Get details of all extrinsics that are already in the pool + let in_pool_hashes = + extrinsics.iter().map(|extrinsic| self.hash_of(extrinsic)).collect::>(); + let in_pool_tags = self.validated_pool.extrinsics_tags(&in_pool_hashes, shard); + + // Zip the ones from the pool with the full list (we get pairs `(Extrinsic, Option>)`) + let all = extrinsics.iter().zip(in_pool_tags.into_iter()); + + let mut future_tags = Vec::new(); + for (extrinsic, in_pool_tags) in all { + match in_pool_tags { + // reuse the tags for extrinsics that were found in the pool + Some(tags) => future_tags.extend(tags), + // if it's not found in the pool query the runtime at parent block + // to get validity info and tags that the extrinsic provides. + None => { + let validity = self + .validated_pool + .api() + .validate_transaction( + TrustedOperationSource::InBlock, + extrinsic.clone(), + shard, + ) + .await; + + if let Ok(Ok(validity)) = validity { + future_tags.extend(validity.provides); + } + }, + } + } + + self.prune_tags(at, future_tags, in_pool_hashes, shard).await + } + + /// Prunes ready operations that provide given list of tags. + /// + /// Given tags are assumed to be always provided now, so all operations + /// in the Future Queue that require that particular tag (and have other + /// requirements satisfied) are promoted to Ready Queue. + /// + /// Moreover for each provided tag we remove operations in the pool that: + /// 1. Provide that tag directly + /// 2. Are a dependency of pruned operation. + /// + /// Returns operations that have been removed from the pool and must be reverified + /// before reinserting to the pool. + /// + /// By removing predecessor operations as well we might actually end up + /// pruning too much, so all removed operations are reverified against + /// the runtime (`validate_transaction`) to make sure they are invalid. + /// + /// However we avoid revalidating operations that are contained within + /// the second parameter of `known_imported_hashes`. These operations + /// (if pruned) are not revalidated and become temporarily banned to + /// prevent importing them in the (near) future. + pub async fn prune_tags( + &self, + at: &BlockId, + tags: impl IntoIterator, + known_imported_hashes: impl IntoIterator + Clone, + shard: ShardIdentifier, + ) -> Result<(), B::Error> { + log::debug!(target: "txpool", "Pruning at {:?}", at); + // Prune all operations that provide given tags + let prune_status = match self.validated_pool.prune_tags(tags, shard) { + Ok(prune_status) => prune_status, + Err(e) => return Err(e), + }; + + // Make sure that we don't revalidate extrinsics that were part of the recently + // imported block. This is especially important for UTXO-like chains cause the + // inputs are pruned so such operation would go to future again. + self.validated_pool + .ban(&Instant::now(), known_imported_hashes.clone().into_iter()); + + // Try to re-validate pruned operations since some of them might be still valid. + // note that `known_imported_hashes` will be rejected here due to temporary ban. + let pruned_hashes = prune_status.pruned.iter().map(|tx| tx.hash).collect::>(); + let pruned_transactions = + prune_status.pruned.into_iter().map(|tx| (tx.source, tx.data.clone())); + + let reverified_transactions = self + .verify(at, pruned_transactions, CheckBannedBeforeVerify::Yes, shard) + .await?; + + log::trace!(target: "txpool", "Pruning at {:?}. Resubmitting operations.", at); + // And finally - submit reverified operations back to the pool + + self.validated_pool.resubmit_pruned( + at, + known_imported_hashes, + pruned_hashes, + reverified_transactions.into_values().collect(), + shard, + ) + } + + /// Returns operation hash + pub fn hash_of(&self, xt: &TOP) -> TxHash { + self.validated_pool.api().hash_and_length(xt).0 + } + + /// Resolves block number by id. + fn _resolve_block_number(&self, at: &BlockId) -> Result, B::Error> { + self.validated_pool.api().block_id_to_number(at).and_then(|number| { + number.ok_or_else(|| error::Error::InvalidBlockId(format!("{:?}", at)).into()) + }) + } + + /// Returns future that validates a bunch of operations at given block. + async fn verify( + &self, + at: &BlockId, + xts: impl IntoIterator, + check: CheckBannedBeforeVerify, + shard: ShardIdentifier, + ) -> Result>, B::Error> { + //FIXME: Nicer verify + // we need a block number to compute tx validity + //let block_number = self.resolve_block_number(at)?; + // dummy blocknumber + //pub type NumberFor = traits::NumberFor<::Block>; + let block_number = 0; + + let res = future::join_all( + xts.into_iter() + .map(|(source, xt)| self.verify_one(at, block_number, source, xt, check, shard)), + ) + .await + .into_iter() + .collect::>(); + + Ok(res) + } + + /// Returns future that validates single operation at given block. + async fn verify_one( + &self, + _block_id: &BlockId, + //block_number: NumberFor, + block_number: i8, + source: TrustedOperationSource, + xt: TOP, + check: CheckBannedBeforeVerify, + shard: ShardIdentifier, + ) -> (TxHash, ValidatedOperationFor) { + let (hash, bytes) = self.validated_pool.api().hash_and_length(&xt); + + let ignore_banned = matches!(check, CheckBannedBeforeVerify::No); + if let Err(err) = self.validated_pool.check_is_known(&hash, ignore_banned, shard) { + return (hash, ValidatedOperation::Invalid(hash, err)) + } + + //FIXME: + // no runtime validation check for now. + let validation_result = + self.validated_pool.api().validate_transaction(source, xt.clone(), shard).await; + + let status = match validation_result { + Ok(status) => status, + Err(e) => return (hash, ValidatedOperation::Invalid(hash, e)), + }; + + let validity = match status { + Ok(validity) => + if validity.provides.is_empty() { + ValidatedOperation::Invalid(hash, error::Error::NoTagsProvided.into()) + } else { + ValidatedOperation::valid_at( + block_number.saturated_into::(), + hash, + source, + xt, + bytes, + validity, + ) + }, + Err(TransactionValidityError::Invalid(_e)) => + ValidatedOperation::Invalid(hash, error::Error::InvalidTrustedOperation.into()), + Err(TransactionValidityError::Unknown(_e)) => + ValidatedOperation::Unknown(hash, error::Error::UnknownTrustedOperation.into()), + }; + + (hash, validity) + } + + /// get a reference to the underlying validated pool. + pub fn validated_pool(&self) -> &ValidatedPool { + &self.validated_pool + } +} + +impl Clone for Pool +where + ::Error: error::IntoPoolError, + R: SendRpcResponse, +{ + fn clone(&self) -> Self { + Self { validated_pool: self.validated_pool.clone(), _phantom: Default::default() } + } +} + +#[cfg(test)] +pub mod tests { + use super::*; + use crate::{ + base_pool::Limit, mocks::rpc_responder_mock::RpcResponderMock, + primitives::from_low_u64_to_be_h256, + }; + use codec::{Decode, Encode}; + use itp_stf_primitives::types::Nonce; + use itp_test::mock::stf_mock::{ + mock_top_direct_trusted_call_signed, mock_trusted_call_signed, TrustedOperationMock, + }; + use itp_types::Header; + use jsonrpc_core::{ + futures, + futures::{executor::block_on, future::ready}, + }; + use parity_util_mem::MallocSizeOf; + use serde::Serialize; + use sp_application_crypto::ed25519; + use sp_core::hash::H256; + use sp_runtime::traits::{BlakeTwo256, Extrinsic as ExtrinsicT, Hash, Verify}; + use std::{collections::HashSet, sync::Mutex}; + + #[derive(Clone, PartialEq, Eq, Encode, Decode, core::fmt::Debug, Serialize, MallocSizeOf)] + pub enum Extrinsic { + #[codec(index = 0)] + IncludeData(Vec), + #[codec(index = 1)] + StorageChange(Vec, Option>), + #[codec(index = 2)] + OffchainIndexSet(Vec, Vec), + #[codec(index = 3)] + OffchainIndexClear(Vec), + } + + impl ExtrinsicT for Extrinsic { + type Call = Extrinsic; + type SignaturePayload = (); + + fn is_signed(&self) -> Option { + if let Extrinsic::IncludeData(_) = *self { + Some(false) + } else { + Some(true) + } + } + + fn new( + call: Self::Call, + _signature_payload: Option, + ) -> Option { + Some(call) + } + } + + /// The signature type used by accounts/transactions. + pub type AccountSignature = ed25519::Signature; + /// An identifier for an account on this system. + pub type AccountId = ::Signer; + /// The hashing algorithm used. + pub type Hashing = BlakeTwo256; + /// The item of a block digest. + pub type DigestItem = sp_runtime::generic::DigestItem; + /// The digest of a block. + pub type Digest = sp_runtime::generic::Digest; + /// A test block. + pub type Block = sp_runtime::generic::Block; + /// Test RPC responder + pub type TestRpcResponder = RpcResponderMock; + + const INVALID_NONCE: Nonce = 254; + const SOURCE: TrustedOperationSource = TrustedOperationSource::External; + + #[derive(Clone, Debug, Default)] + struct TestApi { + delay: Arc>>>, + invalidate: Arc>>, + clear_requirements: Arc>>, + add_requirements: Arc>>, + } + + impl ChainApi for TestApi { + type Block = tests::Block; + type Error = error::Error; + type ValidationFuture = futures::future::Ready>; + type BodyFuture = futures::future::Ready>>; + + /// Verify extrinsic at given block. + fn validate_transaction( + &self, + _source: TrustedOperationSource, + uxt: TOP, + _shard: ShardIdentifier, + ) -> Self::ValidationFuture { + let operation = uxt.validate(); + ready(Ok(operation)) + } + + /// Returns a block number given the block id. + fn block_id_to_number( + &self, + at: &BlockId, + ) -> Result>, Self::Error> { + Ok(match at { + BlockId::Number(num) => Some(*num), + BlockId::Hash(_) => None, + }) + } + + /// Returns a block hash given the block id. + fn block_id_to_hash( + &self, + at: &BlockId, + ) -> Result, Self::Error> { + Ok(match at { + BlockId::Number(num) => Some(from_low_u64_to_be_h256((*num).into())), + BlockId::Hash(_) => None, + }) + } + + /// Hash the extrinsic. + fn hash_and_length(&self, uxt: &TOP) -> (SidechainBlockHash, usize) { + let encoded = uxt.encode(); + let len = encoded.len(); + (tests::Hashing::hash_of(&encoded), len) + } + + fn block_body(&self, _id: &BlockId) -> Self::BodyFuture { + futures::future::ready(Ok(None)) + } + } + + fn test_pool() -> Pool, TrustedOperationMock> { + Pool::new( + Default::default(), + TestApi::default().into(), + Arc::new(RpcResponderMock::::new()), + ) + } + + #[test] + pub fn test_should_validate_and_import_transaction() { + // given + let pool = test_pool(); + let shard = ShardIdentifier::default(); + + // when + let hash = block_on(pool.submit_one( + &BlockId::Number(0), + SOURCE, + mock_top_direct_trusted_call_signed(), + shard, + )) + .unwrap(); + + // then + assert_eq!( + pool.validated_pool().ready(shard).map(|v| v.hash).collect::>(), + vec![hash] + ); + } + + #[test] + pub fn test_should_reject_if_temporarily_banned() { + // given + let pool = test_pool(); + let shard = ShardIdentifier::default(); + let top = mock_top_direct_trusted_call_signed(); + + // when + pool.validated_pool.rotator().ban(&Instant::now(), vec![pool.hash_of(&top)]); + let res = block_on(pool.submit_one(&BlockId::Number(0), SOURCE, top, shard)); + assert_eq!(pool.validated_pool().status(shard).ready, 0); + assert_eq!(pool.validated_pool().status(shard).future, 0); + + // then + assert!(matches!(res.unwrap_err(), error::Error::TemporarilyBanned)); + } + + #[test] + pub fn test_should_notify_about_pool_events() { + let (stream, hash0, hash1) = { + // given + let pool = test_pool(); + let shard = ShardIdentifier::default(); + let stream = pool.validated_pool().import_notification_stream(); + + // when + let hash0 = block_on(pool.submit_one( + &BlockId::Number(0), + SOURCE, + TrustedOperationMock::direct_call(mock_trusted_call_signed(0)), + shard, + )) + .unwrap(); + let hash1 = block_on(pool.submit_one( + &BlockId::Number(0), + SOURCE, + TrustedOperationMock::direct_call(mock_trusted_call_signed(1)), + shard, + )) + .unwrap(); + /* this fails because of #1488 + // future doesn't count + let _hash = block_on(pool.submit_one( + &BlockId::Number(0), + SOURCE, + TrustedOperationMock::direct_call(mock_trusted_call_signed(3)), + shard, + )) + .unwrap(); + assert_eq!(pool.validated_pool().status(shard).future, 1); + */ + assert_eq!(pool.validated_pool().status(shard).ready, 2); + + (stream, hash0, hash1) + }; + + // then + let mut it = futures::executor::block_on_stream(stream); + assert_eq!(it.next(), Some(hash0)); + assert_eq!(it.next(), Some(hash1)); + assert_eq!(it.next(), None); + } + + #[test] + pub fn test_should_clear_stale_transactions() { + // given + let pool = test_pool(); + let shard = ShardIdentifier::default(); + let hash1 = block_on(pool.submit_one( + &BlockId::Number(0), + SOURCE, + TrustedOperationMock::direct_call(mock_trusted_call_signed(0)), + shard, + )) + .unwrap(); + let hash2 = block_on(pool.submit_one( + &BlockId::Number(0), + SOURCE, + TrustedOperationMock::direct_call(mock_trusted_call_signed(1)), + shard, + )) + .unwrap(); + let hash3 = block_on(pool.submit_one( + &BlockId::Number(0), + SOURCE, + TrustedOperationMock::direct_call(mock_trusted_call_signed(3)), + shard, + )) + .unwrap(); + // when + pool.validated_pool.clear_stale(&BlockId::Number(65), shard).unwrap(); + + // then + assert_eq!(pool.validated_pool().ready(shard).count(), 0); + assert_eq!(pool.validated_pool().status(shard).future, 0); + assert_eq!(pool.validated_pool().status(shard).ready, 0); + // make sure they are temporarily banned as well + assert!(pool.validated_pool.rotator().is_banned(&hash1)); + assert!(pool.validated_pool.rotator().is_banned(&hash2)); + assert!(pool.validated_pool.rotator().is_banned(&hash3)); + } + + #[test] + pub fn test_should_ban_mined_transactions() { + // given + let pool = test_pool(); + let shard = ShardIdentifier::default(); + let hash1 = block_on(pool.submit_one( + &BlockId::Number(0), + SOURCE, + TrustedOperationMock::direct_call(mock_trusted_call_signed(0)), + shard, + )) + .unwrap(); + + // when + block_on(pool.prune_tags(&BlockId::Number(1), vec![vec![0]], vec![hash1], shard)).unwrap(); + + // then + assert!(pool.validated_pool.rotator().is_banned(&hash1)); + } + + #[test] + #[ignore] // flaky, fails sometimes + pub fn test_should_limit_futures() { + // given + let shard = ShardIdentifier::default(); + let limit = Limit { count: 100, total_bytes: 300 }; + let pool = Pool::new( + Options { ready: limit.clone(), future: limit, ..Default::default() }, + TestApi::default().into(), + Arc::new(TestRpcResponder::new()), + ); + + let hash1 = block_on(pool.submit_one( + &BlockId::Number(0), + SOURCE, + TrustedOperationMock::direct_call(mock_trusted_call_signed(1)), + shard, + )) + .unwrap(); + assert_eq!(pool.validated_pool().status(shard).future, 1); + + // when + let hash2 = block_on(pool.submit_one( + &BlockId::Number(0), + SOURCE, + TrustedOperationMock::direct_call(mock_trusted_call_signed(10)), + shard, + )) + .unwrap(); + + // then + assert_eq!(pool.validated_pool().status(shard).future, 1); + assert!(pool.validated_pool.rotator().is_banned(&hash1)); + assert!(!pool.validated_pool.rotator().is_banned(&hash2)); + } + + #[test] + pub fn test_should_error_if_reject_immediately() { + // given + let shard = ShardIdentifier::default(); + let limit = Limit { count: 100, total_bytes: 10 }; + let pool = Pool::new( + Options { ready: limit.clone(), future: limit, ..Default::default() }, + TestApi::default().into(), + Arc::new(TestRpcResponder::new()), + ); + + // when + block_on(pool.submit_one( + &BlockId::Number(0), + SOURCE, + TrustedOperationMock::direct_call(mock_trusted_call_signed(1)), + shard, + )) + .unwrap_err(); + + // then + assert_eq!(pool.validated_pool().status(shard).ready, 0); + assert_eq!(pool.validated_pool().status(shard).future, 0); + } +} diff --git a/bitacross-worker/core-primitives/top-pool/src/primitives.rs b/bitacross-worker/core-primitives/top-pool/src/primitives.rs new file mode 100644 index 0000000000..d40fbabd93 --- /dev/null +++ b/bitacross-worker/core-primitives/top-pool/src/primitives.rs @@ -0,0 +1,350 @@ +// File replacing substrate crate sp_transaction_pool::{error, PoolStatus}; + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +use crate::sgx_reexport_prelude::*; + +extern crate alloc; +use crate::error; +use alloc::{boxed::Box, string::String, sync::Arc, vec::Vec}; +use byteorder::{BigEndian, ByteOrder}; +use codec::{Decode, Encode}; +use core::pin::Pin; +use itp_stf_primitives::types::ShardIdentifier; +use itp_types::BlockHash as SidechainBlockHash; +use jsonrpc_core::futures::{channel::mpsc::Receiver, Future, Stream}; +use sp_core::H256; +use sp_runtime::{ + generic::BlockId, + traits::{Block as BlockT, NumberFor}, + transaction_validity::{TransactionLongevity, TransactionPriority, TransactionTag}, +}; +use std::collections::HashMap; + +/// TrustedOperation pool status. +#[derive(Debug, Default)] +pub struct PoolStatus { + /// Number of operations in the ready queue. + pub ready: usize, + /// Sum of bytes of ready operation encodings. + pub ready_bytes: usize, + /// Number of operations in the future queue. + pub future: usize, + /// Sum of bytes of ready operation encodings. + pub future_bytes: usize, +} + +impl PoolStatus { + /// Returns true if the are no operations in the pool. + pub fn is_empty(&self) -> bool { + self.ready == 0 && self.future == 0 + } +} + +/// Possible operation status events. +/// +/// This events are being emitted by `TrustedOperationPool` watchers, +/// which are also exposed over RPC. +/// +/// The status events can be grouped based on their kinds as: +/// 1. Entering/Moving within the pool: +/// - `Future` +/// - `Ready` +/// 2. Inside `Ready` queue: +/// - `Broadcast` +/// 3. Leaving the pool: +/// - `InBlock` +/// - `Invalid` +/// - `Usurped` +/// - `Dropped` +/// 4. Re-entering the pool: +/// - `Retracted` +/// 5. Block finalized: +/// - `Finalized` +/// - `FinalityTimeout` +/// +/// The events will always be received in the order described above, however +/// there might be cases where operations alternate between `Future` and `Ready` +/// pool, and are `Broadcast` in the meantime. +/// +/// There is also only single event causing the operation to leave the pool. +/// I.e. only one of the listed ones should be triggered. +/// +/// Note that there are conditions that may cause operations to reappear in the pool. +/// 1. Due to possible forks, the operation that ends up being in included +/// in one block, may later re-enter the pool or be marked as invalid. +/// 2. TrustedOperation `Dropped` at one point, may later re-enter the pool if some other +/// operations are removed. +/// 3. `Invalid` operation may become valid at some point in the future. +/// (Note that runtimes are encouraged to use `UnknownValidity` to inform the pool about +/// such case). +/// 4. `Retracted` operations might be included in some next block. +/// +/// The stream is considered finished only when either `Finalized` or `FinalityTimeout` +/// event is triggered. You are however free to unsubscribe from notifications at any point. +/// The first one will be emitted when the block, in which operation was included gets +/// finalized. The `FinalityTimeout` event will be emitted when the block did not reach finality +/// within 512 blocks. This either indicates that finality is not available for your chain, +/// or that finality gadget is lagging behind. If you choose to wait for finality longer, you can +/// re-subscribe for a particular operation hash manually again. +#[derive(Debug, Clone, PartialEq)] +pub enum TrustedOperationStatus { + /// TrustedOperation is part of the future queue. + Future, + /// TrustedOperation is part of the ready queue. + Ready, + /// The operation has been broadcast to the given peers. + Broadcast(Vec), + /// TrustedOperation has been included in block with given hash. + InBlock(BlockHash), + /// The block this operation was included in has been retracted. + Retracted(BlockHash), + /// Maximum number of finality watchers has been reached, + /// old watchers are being removed. + FinalityTimeout(BlockHash), + /// TrustedOperation has been finalized by a finality-gadget, e.g GRANDPA + Finalized(BlockHash), + /// TrustedOperation has been replaced in the pool, by another operation + /// that provides the same tags. (e.g. same (sender, nonce)). + Usurped(Hash), + /// TrustedOperation has been dropped from the pool because of the limit. + Dropped, + /// TrustedOperation is no longer valid in the current state. + Invalid, +} + +/// The stream of operation events. +pub type TrustedOperationStatusStream = + dyn Stream> + Send + Unpin; + +/// The import notification event stream. +pub type ImportNotificationStream = Receiver; + +/// TrustedOperation hash type for a pool. +pub type TxHash = H256; +/// Block hash type for a pool. +pub type BlockHash = H256; +/// Type of operations event stream for a pool. +pub type TrustedOperationStatusStreamFor = TrustedOperationStatusStream; + +/// Typical future type used in operation pool api. +pub type PoolFuture = Pin> + Send>>; + +/// In-pool operation interface. +/// +/// The pool is container of operations that are implementing this trait. +/// See `sp_runtime::ValidTransaction` for details about every field. +pub trait InPoolOperation { + /// TrustedOperation type. + type TrustedOperation; + + /// Get the reference to the operation data. + fn data(&self) -> &Self::TrustedOperation; + /// Get hash of the operation. + fn hash(&self) -> TxHash; + /// Get priority of the operation. + fn priority(&self) -> &TransactionPriority; + /// Get longevity of the operation. + fn longevity(&self) -> &TransactionLongevity; + /// Get operation dependencies. + fn requires(&self) -> &[TransactionTag]; + /// Get tags that operation provides. + fn provides(&self) -> &[TransactionTag]; + /// Return a flag indicating if the operation should be propagated to other peers. + fn is_propagable(&self) -> bool; +} + +/// TrustedOperation pool interface. +pub trait TrustedOperationPool: Send + Sync { + /// Block type. + type Block: BlockT; + /// In-pool operation type. + type InPoolOperation: InPoolOperation; + /// Error type. + type Error: From + error::IntoPoolError; + + // *** RPC + + /// Returns a future that imports a bunch of unverified operations to the pool. + // FIXME: obey clippy + #[allow(clippy::type_complexity)] + fn submit_at( + &self, + at: &BlockId, + source: TrustedOperationSource, + xts: Vec, + shard: ShardIdentifier, + ) -> PoolFuture>, Self::Error>; + + /// Returns a future that imports one unverified operation to the pool. + fn submit_one( + &self, + at: &BlockId, + source: TrustedOperationSource, + xt: TOP, + shard: ShardIdentifier, + ) -> PoolFuture; + + /// Returns a future that import a single operation and starts to watch their progress in the pool. + fn submit_and_watch( + &self, + at: &BlockId, + source: TrustedOperationSource, + xt: TOP, + shard: ShardIdentifier, + ) -> PoolFuture; + + // *** Block production / Networking + /// Get an iterator for ready operations ordered by priority. + /// + /// Guarantees to return only when operation pool got updated at `at` block. + /// Guarantees to return immediately when `None` is passed. + // FIXME: obey clippy + #[allow(clippy::type_complexity)] + fn ready_at( + &self, + at: NumberFor, + shard: ShardIdentifier, + ) -> Pin< + Box< + dyn Future> + Send>> + Send, + >, + >; + + /// Get an iterator for ready operations ordered by priority. + fn ready( + &self, + shard: ShardIdentifier, + ) -> Box> + Send>; + + /// Get an iterator over all shards. + fn shards(&self) -> Vec; + + // *** Block production + /// Remove operations identified by given hashes (and dependent operations) from the pool. + fn remove_invalid( + &self, + hashes: &[TxHash], + shard: ShardIdentifier, + inblock: bool, + ) -> Vec>; + + // *** logging + /// Returns pool status. + fn status(&self, shard: ShardIdentifier) -> PoolStatus; + + // *** logging / RPC / networking + /// Return an event stream of operations imported to the pool. + fn import_notification_stream(&self) -> ImportNotificationStream; + + // *** networking + /// Notify the pool about operations broadcast. + fn on_broadcasted(&self, propagations: HashMap>); + + /// Returns operation hash + fn hash_of(&self, xt: &TOP) -> TxHash; + + /// Return specific ready operation by hash, if there is one. + fn ready_transaction( + &self, + hash: &TxHash, + shard: ShardIdentifier, + ) -> Option>; + + /// Notify the listener of top inclusion in sidechain block + fn on_block_imported(&self, hashes: &[TxHash], block_hash: SidechainBlockHash); + + /// Litentry: set the rpc response value + #[allow(clippy::type_complexity)] + fn update_connection_state(&self, updates: Vec<(TxHash, (Vec, bool))>); + + /// Litentry: swap the old hash with the new one in rpc connection registry + fn swap_rpc_connection_hash(&self, old_hash: TxHash, new_hash: TxHash); +} + +/// The source of the transaction. +/// +/// Depending on the source we might apply different validation schemes. +/// For instance we can disallow specific kinds of transactions if they were not produced +/// by our local node (for instance off-chain workers). +#[derive(Copy, Clone, PartialEq, Eq, Encode, Decode, Debug)] +pub enum TrustedOperationSource { + /// Transaction is already included in block. + /// + /// This means that we can't really tell where the transaction is coming from, + /// since it's already in the received block. Note that the custom validation logic + /// using either `Local` or `External` should most likely just allow `InBlock` + /// transactions as well. + #[codec(index = 0)] + InBlock, + + /// Transaction is coming from a local source. + /// + /// This means that the transaction was produced internally by the node + /// (for instance an Off-Chain Worker, or an Off-Chain Call), as opposed + /// to being received over the network. + #[codec(index = 1)] + Local, + + /// Transaction has been received externally. + /// + /// This means the transaction has been received from (usually) "untrusted" source, + /// for instance received over the network or RPC. + #[codec(index = 2)] + External, +} + +// Replacement of primitive function from_low_u64_be +pub fn from_low_u64_to_be_h256(val: u64) -> H256 { + let mut buf = [0x0; 8]; + BigEndian::write_u64(&mut buf, val); + let capped = core::cmp::min(H256::len_bytes(), 8); + let mut bytes = [0x0; core::mem::size_of::()]; + bytes[(H256::len_bytes() - capped)..].copy_from_slice(&buf[..capped]); + H256::from_slice(&bytes) +} + +#[cfg(test)] +pub mod tests { + + use super::*; + use alloc::string::ToString; + + #[test] + pub fn test_h256() { + let tests = vec![ + ( + from_low_u64_to_be_h256(0), + "0x0000000000000000000000000000000000000000000000000000000000000000", + ), + ( + from_low_u64_to_be_h256(2), + "0x0000000000000000000000000000000000000000000000000000000000000002", + ), + ( + from_low_u64_to_be_h256(15), + "0x000000000000000000000000000000000000000000000000000000000000000f", + ), + ( + from_low_u64_to_be_h256(16), + "0x0000000000000000000000000000000000000000000000000000000000000010", + ), + ( + from_low_u64_to_be_h256(1_000), + "0x00000000000000000000000000000000000000000000000000000000000003e8", + ), + ( + from_low_u64_to_be_h256(100_000), + "0x00000000000000000000000000000000000000000000000000000000000186a0", + ), + ( + from_low_u64_to_be_h256(u64::max_value()), + "0x000000000000000000000000000000000000000000000000ffffffffffffffff", + ), + ]; + + for (number, expected) in tests { + // workaround, as H256 in no_std does not implement (de)serialize + assert_eq!(expected.to_string(), format!("{:?}", number)); + } + } +} diff --git a/bitacross-worker/core-primitives/top-pool/src/ready.rs b/bitacross-worker/core-primitives/top-pool/src/ready.rs new file mode 100644 index 0000000000..c3dbf5afbb --- /dev/null +++ b/bitacross-worker/core-primitives/top-pool/src/ready.rs @@ -0,0 +1,800 @@ +// This file is part of Substrate. + +// Copyright (C) 2018-2021 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 . + +pub extern crate alloc; +use crate::{ + base_pool::TrustedOperation, + error, + future::WaitingTrustedOperations, + primitives::TxHash, + tracked_map::{self, ReadOnlyTrackedMap, TrackedMap}, +}; +use alloc::{boxed::Box, collections::BTreeSet, sync::Arc, vec, vec::Vec}; +use core::{cmp, cmp::Ord, default::Default}; +use itp_stf_primitives::types::ShardIdentifier; +use log::trace; +use sp_runtime::transaction_validity::TransactionTag as Tag; +use std::collections::{HashMap, HashSet}; + +type TopErrorResult = error::Result<(Vec>>, Vec)>; + +/// An in-pool operation reference. +/// +/// Should be cheap to clone. +#[derive(Debug)] +pub struct OperationRef { + /// The actual operation data. + pub operation: Arc>, + /// Unique id when operation was inserted into the pool. + pub insertion_id: u64, +} + +impl Clone for OperationRef { + fn clone(&self) -> Self { + OperationRef { operation: self.operation.clone(), insertion_id: self.insertion_id } + } +} + +impl Ord for OperationRef { + fn cmp(&self, other: &Self) -> cmp::Ordering { + self.operation + .priority + .cmp(&other.operation.priority) + .then_with(|| other.operation.valid_till.cmp(&self.operation.valid_till)) + .then_with(|| other.insertion_id.cmp(&self.insertion_id)) + } +} + +impl PartialOrd for OperationRef { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl PartialEq for OperationRef { + fn eq(&self, other: &Self) -> bool { + self.cmp(other) == cmp::Ordering::Equal + } +} +impl Eq for OperationRef {} + +#[derive(Debug)] +pub struct ReadyTx { + /// A reference to a operation + pub operation: OperationRef, + /// A list of operations that get unlocked by this one + pub unlocks: Vec, + /// How many required tags are provided inherently + /// + /// Some operations might be already pruned from the queue, + /// so when we compute ready set we may consider this operations ready earlier. + pub requires_offset: usize, +} + +impl Clone for ReadyTx { + fn clone(&self) -> Self { + ReadyTx { + operation: self.operation.clone(), + unlocks: self.unlocks.clone(), + requires_offset: self.requires_offset, + } + } +} + +const HASH_READY: &str = r#" +Every time operation is imported its hash is placed in `ready` map and tags in `provided_tags`; +Every time operation is removed from the queue we remove the hash from `ready` map and from `provided_tags`; +Hence every hash retrieved from `provided_tags` is always present in `ready`; +qed +"#; + +#[derive(Debug)] +pub struct ReadyOperations { + /// Insertion id + insertion_id: HashMap, + /// tags that are provided by Ready operations + provided_tags: HashMap>, + /// Trusted Operations that are ready (i.e. don't have any requirements external to the pool) + ready: HashMap>>, + /// Best operations that are ready to be included to the block without any other previous operation. + best: HashMap>>, +} + +impl tracked_map::Size for ReadyTx { + fn size(&self) -> usize { + self.operation.operation.bytes + } +} + +impl Default for ReadyOperations { + fn default() -> Self { + ReadyOperations { + insertion_id: Default::default(), + provided_tags: Default::default(), + ready: Default::default(), + best: Default::default(), + } + } +} + +impl ReadyOperations { + /// Borrows a map of tags that are provided by operations in this queue. + pub fn provided_tags(&self, shard: ShardIdentifier) -> Option<&HashMap> { + if let Some(tag_pool) = &self.provided_tags.get(&shard) { + return Some(tag_pool) + } + None + } + + /// Returns an iterator of ready operations. + /// + /// Trusted Operations are returned in order: + /// 1. First by the dependencies: + /// - never return operation that requires a tag, which was not provided by one of the previously returned operations + /// 2. Then by priority: + /// - If there are two operations with all requirements satisfied the one with higher priority goes first. + /// 3. Then by the ttl that's left + /// - operations that are valid for a shorter time go first + /// 4. Lastly we sort by the time in the queue + /// - operations that are longer in the queue go first + pub fn get(&self, shard: ShardIdentifier) -> impl Iterator>> { + // check if shard tx pool exists + if let Some(ready_map) = self.ready.get(&shard) { + return BestIterator { + all: ready_map.get_read_only_clone(), + best: self.best.get(&shard).unwrap().clone(), + awaiting: Default::default(), + } + } + let tracked_map: TrackedMap> = Default::default(); + BestIterator { + all: tracked_map.get_read_only_clone(), + best: Default::default(), + awaiting: Default::default(), + } + } + /// Returns an iterator over all shards + pub fn get_shards(&self) -> Box + '_> { + // check if shard tx pool exists + Box::new(self.ready.keys()) + } + + /// Imports operations to the pool of ready operations. + /// + /// The operation needs to have all tags satisfied (be ready) by operations + /// that are in this queue. + /// Returns operations that were replaced by the one imported. + pub fn import( + &mut self, + tx: WaitingTrustedOperations, + shard: ShardIdentifier, + ) -> error::Result>>> { + assert!( + tx.is_ready(), + "Only ready operations can be imported. Missing: {:?}", + tx.missing_tags + ); + if let Some(ready_map) = &self.ready.get(&shard) { + assert!( + !ready_map.read().contains_key(&tx.operation.hash), + "TrustedOperation is already imported." + ); + } + // Get shard pool or create if not yet existing + let current_insertion_id = self.insertion_id.entry(shard).or_insert_with(|| { + let x: u64 = Default::default(); + x + }); + + *current_insertion_id += 1; + let insertion_id = *current_insertion_id; + let hash = tx.operation.hash; + let operation = tx.operation; + + let (replaced, unlocks) = self.replace_previous(&operation, shard)?; + + let mut goes_to_best = true; + let tracked_ready = self.ready.entry(shard).or_insert_with(|| { + let x: TrackedMap> = Default::default(); + x + }); + let mut ready = tracked_ready.write(); + let mut requires_offset = 0; + // Add links to operations that unlock the current one + let tag_map = self.provided_tags.entry(shard).or_insert_with(|| { + let x: HashMap = Default::default(); + x + }); + for tag in &operation.requires { + // Check if the operation that satisfies the tag is still in the queue. + if let Some(other) = tag_map.get(tag) { + let tx = ready.get_mut(other).expect(HASH_READY); + tx.unlocks.push(hash); + // this operation depends on some other, so it doesn't go to best directly. + goes_to_best = false; + } else { + requires_offset += 1; + } + } + + // update provided_tags + // call to replace_previous guarantees that we will be overwriting + // only entries that have been removed. + + for tag in &operation.provides { + tag_map.insert(tag.clone(), hash); + } + + let operation = OperationRef { operation, insertion_id }; + + // insert to best if it doesn't require any other operation to be included before it + let best_set = self.best.entry(shard).or_insert_with(|| { + let x: BTreeSet> = Default::default(); + x + }); + if goes_to_best { + best_set.insert(operation.clone()); + } + + // insert to Ready + ready.insert(hash, ReadyTx { operation, unlocks, requires_offset }); + + Ok(replaced) + } + + /// Fold a list of ready operations to compute a single value. + pub fn fold, &ReadyTx) -> Option>( + &mut self, + f: F, + shard: ShardIdentifier, + ) -> Option { + if let Some(ready_map) = self.ready.get(&shard) { + return ready_map.read().values().fold(None, f) + } + None + } + + /// Returns true if given hash is part of the queue. + pub fn contains(&self, hash: &TxHash, shard: ShardIdentifier) -> bool { + if let Some(ready_map) = self.ready.get(&shard) { + return ready_map.read().contains_key(hash) + } + false + } + + /// Retrive operation by hash + pub fn by_hash( + &self, + hash: &TxHash, + shard: ShardIdentifier, + ) -> Option>> { + self.by_hashes(&[*hash], shard).into_iter().next().unwrap_or(None) + } + + /// Retrieve operations by hash + pub fn by_hashes( + &self, + hashes: &[TxHash], + shard: ShardIdentifier, + ) -> Vec>>> { + if let Some(ready_map) = self.ready.get(&shard) { + let ready = ready_map.read(); + return hashes + .iter() + .map(|hash| ready.get(hash).map(|x| x.operation.operation.clone())) + .collect() + } + vec![] + } + + /// Removes a subtree of operations from the ready pool. + /// + /// NOTE removing a operation will also cause a removal of all operations that depend on that one + /// (i.e. the entire subgraph that this operation is a start of will be removed). + /// All removed operations are returned. + pub fn remove_subtree( + &mut self, + hashes: &[TxHash], + shard: ShardIdentifier, + ) -> Vec>> { + let to_remove = hashes.to_vec(); + self.remove_subtree_with_tag_filter(to_remove, None, shard) + } + + /// Removes a subtrees of operations trees starting from roots given in `to_remove`. + /// + /// We proceed with a particular branch only if there is at least one provided tag + /// that is not part of `provides_tag_filter`. I.e. the filter contains tags + /// that will stay in the pool, so that we can early exit and avoid descending. + fn remove_subtree_with_tag_filter( + &mut self, + mut to_remove: Vec, + provides_tag_filter: Option>, + shard: ShardIdentifier, + ) -> Vec>> { + let mut removed = vec![]; + if let Some(ready_map) = self.ready.get_mut(&shard) { + let mut ready = ready_map.write(); + while let Some(hash) = to_remove.pop() { + if let Some(mut tx) = ready.remove(&hash) { + let invalidated = tx.operation.operation.provides.iter().filter(|tag| { + provides_tag_filter + .as_ref() + .map(|filter| !filter.contains(&**tag)) + .unwrap_or(true) + }); + + let mut removed_some_tags = false; + // remove entries from provided_tags + for tag in invalidated { + removed_some_tags = true; + self.provided_tags.get_mut(&shard).unwrap().remove(tag); + } + + // remove from unlocks + for tag in &tx.operation.operation.requires { + if let Some(hash) = self.provided_tags.get(&shard).unwrap().get(tag) { + if let Some(tx) = ready.get_mut(hash) { + remove_item(&mut tx.unlocks, hash); + } + } + } + + // remove from best + self.best.get_mut(&shard).unwrap().remove(&tx.operation); + + if removed_some_tags { + // remove all operations that the current one unlocks + to_remove.append(&mut tx.unlocks); + } + + // add to removed + trace!(target: "txpool", "[{:?}] Removed as part of the subtree.", hash); + removed.push(tx.operation.operation); + } + } + } + + removed + } + + /// Removes operations that provide given tag. + /// + /// All operations that lead to a operation, which provides this tag + /// are going to be removed from the queue, but no other operations are touched - + /// i.e. all other subgraphs starting from given tag are still considered valid & ready. + pub fn prune_tags( + &mut self, + tag: Tag, + shard: ShardIdentifier, + ) -> Vec>> { + let mut removed = vec![]; + let mut to_remove = vec![tag]; + + if self.provided_tags.contains_key(&shard) { + while let Some(tag) = to_remove.pop() { + let res = self + .provided_tags + .get_mut(&shard) + .unwrap() + .remove(&tag) + .and_then(|hash| self.ready.get_mut(&shard).unwrap().write().remove(&hash)); + + if let Some(tx) = res { + let unlocks = tx.unlocks; + + // Make sure we remove it from best txs + self.best.get_mut(&shard).unwrap().remove(&tx.operation); + + let tx = tx.operation.operation; + + // prune previous operations as well + { + let hash = &tx.hash; + let mut find_previous = |tag| -> Option> { + let prev_hash = self.provided_tags.get(&shard).unwrap().get(tag)?; + let mut ready = self.ready.get_mut(&shard).unwrap().write(); + let tx2 = ready.get_mut(prev_hash)?; + remove_item(&mut tx2.unlocks, hash); + // We eagerly prune previous operations as well. + // But it might not always be good. + // Possible edge case: + // - tx provides two tags + // - the second tag enables some subgraph we don't know of yet + // - we will prune the operation + // - when we learn about the subgraph it will go to future + // - we will have to wait for re-propagation of that operation + // Alternatively the caller may attempt to re-import these operations. + if tx2.unlocks.is_empty() { + Some(tx2.operation.operation.provides.clone()) + } else { + None + } + }; + + // find previous operations + for tag in &tx.requires { + if let Some(mut tags_to_remove) = find_previous(tag) { + to_remove.append(&mut tags_to_remove); + } + } + } + + // add the operations that just got unlocked to `best` + for hash in unlocks { + if let Some(tx) = self.ready.get_mut(&shard).unwrap().write().get_mut(&hash) + { + tx.requires_offset += 1; + // this operation is ready + if tx.requires_offset == tx.operation.operation.requires.len() { + self.best.get_mut(&shard).unwrap().insert(tx.operation.clone()); + } + } + } + + // we also need to remove all other tags that this operation provides, + // but since all the hard work is done, we only clear the provided_tag -> hash + // mapping. + let current_tag = &tag; + for tag in &tx.provides { + let removed = self.provided_tags.get_mut(&shard).unwrap().remove(tag); + assert_eq!( + removed.as_ref(), + if current_tag == tag { None } else { Some(&tx.hash) }, + "The pool contains exactly one operation providing given tag; the removed operation + claims to provide that tag, so it has to be mapped to it's hash; qed" + ); + } + + removed.push(tx); + } + } + } + + removed + } + + /// Checks if the operation is providing the same tags as other operations. + /// + /// In case that's true it determines if the priority of operations that + /// we are about to replace is lower than the priority of the replacement operation. + /// We remove/replace old operations in case they have lower priority. + /// + /// In case replacement is successful returns a list of removed operations + /// and a list of hashes that are still in pool and gets unlocked by the new operation. + fn replace_previous( + &mut self, + tx: &TrustedOperation, + shard: ShardIdentifier, + ) -> TopErrorResult { + if let Some(provided_tag_map) = self.provided_tags.get(&shard) { + let (to_remove, unlocks) = { + // check if we are replacing a operation + let replace_hashes = tx + .provides + .iter() + .filter_map(|tag| provided_tag_map.get(tag)) + .collect::>(); + + // early exit if we are not replacing anything. + if replace_hashes.is_empty() { + return Ok((vec![], vec![])) + } + + // now check if collective priority is lower than the replacement operation. + let old_priority = { + let ready = self.ready.get(&shard).unwrap().read(); + replace_hashes + .iter() + .filter_map(|hash| ready.get(hash)) + .fold(0u64, |total, tx| { + total.saturating_add(tx.operation.operation.priority) + }) + }; + + // bail - the operation has too low priority to replace the old ones + if old_priority >= tx.priority { + return Err(error::Error::TooLowPriority(tx.priority)) + } + + // construct a list of unlocked operations + let unlocks = { + let ready = self.ready.get(&shard).unwrap().read(); + replace_hashes.iter().filter_map(|hash| ready.get(hash)).fold( + vec![], + |mut list, tx| { + list.extend(tx.unlocks.iter().cloned()); + list + }, + ) + }; + + (replace_hashes.into_iter().cloned().collect::>(), unlocks) + }; + + let new_provides = tx.provides.iter().cloned().collect::>(); + let removed = self.remove_subtree_with_tag_filter(to_remove, Some(new_provides), shard); + + return Ok((removed, unlocks)) + } + Ok((vec![], vec![])) + } + + /// Returns number of operations in this queue. + #[allow(clippy::len_without_is_empty)] + pub fn len(&self, shard: ShardIdentifier) -> usize { + self.ready.get(&shard).map_or(0, |ready_map| ready_map.len()) + } + + /// Returns sum of encoding lengths of all operations in this queue. + pub fn bytes(&self, shard: ShardIdentifier) -> usize { + self.ready.get(&shard).map_or(0, |ready_map| ready_map.bytes()) + } +} + +/// Iterator of ready operations ordered by priority. +pub struct BestIterator { + all: ReadOnlyTrackedMap>, + awaiting: HashMap)>, + best: BTreeSet>, +} + +/*impl Default for BestIterator { + let insertion_id = 0; + let operation = Arc::new(with_priority(3, 3)) + let tx_default = OperationRef { + insertion_id, + operation + }; + fn default() -> self.awaiting.insert("NA", (0, tx_default)) +}*/ + +impl BestIterator { + /// Depending on number of satisfied requirements insert given ref + /// either to awaiting set or to best set. + fn best_or_awaiting(&mut self, satisfied: usize, tx_ref: OperationRef) { + if satisfied >= tx_ref.operation.requires.len() { + // If we have satisfied all deps insert to best + self.best.insert(tx_ref); + } else { + // otherwise we're still awaiting for some deps + self.awaiting.insert(tx_ref.operation.hash, (satisfied, tx_ref)); + } + } +} + +impl Iterator for BestIterator { + type Item = Arc>; + + fn next(&mut self) -> Option { + loop { + let best = self.best.iter().next_back()?.clone(); + let best = self.best.take(&best)?; + + let next = self.all.read().get(&best.operation.hash).cloned(); + let ready = match next { + Some(ready) => ready, + // The operation is not in all, maybe it was removed in the meantime? + None => continue, + }; + + // Insert operations that just got unlocked. + for hash in &ready.unlocks { + // first check local awaiting operations + let res = if let Some((mut satisfied, tx_ref)) = self.awaiting.remove(hash) { + satisfied += 1; + Some((satisfied, tx_ref)) + // then get from the pool + } else { + self.all + .read() + .get(hash) + .map(|next| (next.requires_offset + 1, next.operation.clone())) + }; + + if let Some((satisfied, tx_ref)) = res { + self.best_or_awaiting(satisfied, tx_ref) + } + } + + return Some(best.operation) + } + } +} + +// See: https://github.com/rust-lang/rust/issues/40062 +fn remove_item(vec: &mut Vec, item: &T) { + if let Some(idx) = vec.iter().position(|i| i == item) { + vec.swap_remove(idx); + } +} + +#[cfg(test)] +pub mod tests { + use super::*; + use crate::primitives::TrustedOperationSource as Source; + use codec::Encode; + use sp_core::blake2_256; + + fn hash(index: u64) -> TxHash { + blake2_256(index.encode().as_slice()).into() + } + + fn tx(id: u8) -> TrustedOperation> { + TrustedOperation { + data: vec![id], + bytes: 1, + hash: hash(id as u64), + priority: 1, + valid_till: 2, + requires: vec![vec![1], vec![2]], + provides: vec![vec![3], vec![4]], + propagate: true, + source: Source::External, + } + } + + fn import( + ready: &mut ReadyOperations, + tx: TrustedOperation, + shard: ShardIdentifier, + ) -> error::Result>>> { + let x = WaitingTrustedOperations::new(tx, ready.provided_tags(shard), &[]); + ready.import(x, shard) + } + + #[test] + pub fn test_should_replace_transaction_that_provides_the_same_tag() { + // given + let shard = ShardIdentifier::default(); + let mut ready = ReadyOperations::default(); + let mut tx1 = tx(1); + tx1.requires.clear(); + let mut tx2 = tx(2); + tx2.requires.clear(); + tx2.provides = vec![vec![3]]; + let mut tx3 = tx(3); + tx3.requires.clear(); + tx3.provides = vec![vec![4]]; + + // when + import(&mut ready, tx2, shard).unwrap(); + import(&mut ready, tx3, shard).unwrap(); + assert_eq!(ready.get(shard).count(), 2); + + // too low priority + import(&mut ready, tx1.clone(), shard).unwrap_err(); + + tx1.priority = 10; + import(&mut ready, tx1, shard).unwrap(); + + // then + assert_eq!(ready.get(shard).count(), 1); + } + + #[test] + pub fn test_should_replace_multiple_transactions_correctly() { + // given + let shard = ShardIdentifier::default(); + let mut ready = ReadyOperations::default(); + let mut tx0 = tx(0); + tx0.requires = vec![]; + tx0.provides = vec![vec![0]]; + let mut tx1 = tx(1); + tx1.requires = vec![]; + tx1.provides = vec![vec![1]]; + let mut tx2 = tx(2); + tx2.requires = vec![vec![0], vec![1]]; + tx2.provides = vec![vec![2], vec![3]]; + let mut tx3 = tx(3); + tx3.requires = vec![vec![2]]; + tx3.provides = vec![vec![4]]; + let mut tx4 = tx(4); + tx4.requires = vec![vec![3]]; + tx4.provides = vec![vec![5]]; + // replacement + let mut tx2_2 = tx(5); + tx2_2.requires = vec![vec![0], vec![1]]; + tx2_2.provides = vec![vec![2]]; + tx2_2.priority = 10; + + for tx in vec![tx0, tx1, tx2, tx3, tx4] { + import(&mut ready, tx, shard).unwrap(); + } + assert_eq!(ready.get(shard).count(), 5); + + // when + import(&mut ready, tx2_2, shard).unwrap(); + + // then + assert_eq!(ready.get(shard).count(), 3); + } + + #[test] + pub fn test_should_return_best_transactions_in_correct_order() { + // given + let shard = ShardIdentifier::default(); + let mut ready = ReadyOperations::default(); + let mut tx1 = tx(1); + tx1.requires.clear(); + let mut tx2 = tx(2); + tx2.requires = tx1.provides.clone(); + tx2.provides = vec![vec![106]]; + let mut tx3 = tx(3); + tx3.requires = vec![tx1.provides[0].clone(), vec![106]]; + tx3.provides = vec![]; + let mut tx4 = tx(4); + tx4.requires = vec![tx1.provides[0].clone()]; + tx4.provides = vec![]; + let tx5 = TrustedOperation { + data: vec![5], + bytes: 1, + hash: hash(5), + priority: 1, + valid_till: u64::max_value(), // use the max_value() here for testing. + requires: vec![tx1.provides[0].clone()], + provides: vec![], + propagate: true, + source: Source::External, + }; + + // when + for tx in vec![tx1, tx2, tx3, tx4, tx5] { + import(&mut ready, tx, shard).unwrap(); + } + + // then + assert_eq!(ready.best.len(), 1); + + let mut it = ready.get(shard).map(|tx| tx.data[0]); + + assert_eq!(it.next(), Some(1)); + assert_eq!(it.next(), Some(2)); + assert_eq!(it.next(), Some(3)); + assert_eq!(it.next(), Some(4)); + assert_eq!(it.next(), Some(5)); + assert_eq!(it.next(), None); + } + + #[test] + pub fn test_should_order_refs() { + let mut id = 1; + let mut with_priority = |priority, longevity| { + id += 1; + let mut tx = tx(id); + tx.priority = priority; + tx.valid_till = longevity; + tx + }; + // higher priority = better + assert!( + OperationRef { operation: Arc::new(with_priority(3, 3)), insertion_id: 1 } + > OperationRef { operation: Arc::new(with_priority(2, 3)), insertion_id: 2 } + ); + // lower validity = better + assert!( + OperationRef { operation: Arc::new(with_priority(3, 2)), insertion_id: 1 } + > OperationRef { operation: Arc::new(with_priority(3, 3)), insertion_id: 2 } + ); + // lower insertion_id = better + assert!( + OperationRef { operation: Arc::new(with_priority(3, 3)), insertion_id: 1 } + > OperationRef { operation: Arc::new(with_priority(3, 3)), insertion_id: 2 } + ); + } +} diff --git a/bitacross-worker/core-primitives/top-pool/src/rotator.rs b/bitacross-worker/core-primitives/top-pool/src/rotator.rs new file mode 100644 index 0000000000..6cfec05fa7 --- /dev/null +++ b/bitacross-worker/core-primitives/top-pool/src/rotator.rs @@ -0,0 +1,221 @@ +// 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 . + +//! Rotate extrinsic inside the pool. +//! +//! Keeps only recent extrinsic and discard the ones kept for a significant amount of time. +//! Discarded extrinsics are banned so that they don't get re-imported again. + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +use std::sync::SgxRwLock as RwLock; + +#[cfg(feature = "std")] +use std::sync::RwLock; + +use crate::{base_pool::TrustedOperation, primitives::TxHash}; +use std::{ + collections::HashMap, + iter, + time::{Duration, Instant}, +}; + +/// Expected size of the banned extrinsics cache. +const EXPECTED_SIZE: usize = 2048; + +/// Pool rotator is responsible to only keep fresh extrinsics in the pool. +/// +/// Extrinsics that occupy the pool for too long are culled and temporarily banned from entering +/// the pool again. +pub struct PoolRotator { + /// How long the extrinsic is banned for. + ban_time: Duration, + /// Currently banned extrinsics. + banned_until: RwLock>, +} + +impl Default for PoolRotator { + fn default() -> Self { + PoolRotator { ban_time: Duration::from_secs(60 * 30), banned_until: Default::default() } + } +} + +impl PoolRotator { + /// Returns `true` if extrinsic hash is currently banned. + pub fn is_banned(&self, hash: &TxHash) -> bool { + self.banned_until.read().unwrap().contains_key(hash) + } + + /// Bans given set of hashes. + pub fn ban(&self, now: &Instant, hashes: impl IntoIterator) { + let mut banned = self.banned_until.write().unwrap(); + + for hash in hashes { + banned.insert(hash, *now + self.ban_time); + } + + if banned.len() > 2 * EXPECTED_SIZE { + while banned.len() > EXPECTED_SIZE { + if let Some(key) = banned.keys().next().cloned() { + banned.remove(&key); + } + } + } + } + + /// Bans extrinsic if it's stale. + /// + /// Returns `true` if extrinsic is stale and got banned. + pub fn ban_if_stale( + &self, + now: &Instant, + current_block: u64, + xt: &TrustedOperation, + ) -> bool { + if xt.valid_till > current_block { + return false + } + + self.ban(now, iter::once(xt.hash)); + true + } + + /// Removes timed bans. + pub fn clear_timeouts(&self, now: &Instant) { + let mut banned = self.banned_until.write().unwrap(); + + banned.retain(|_, &mut v| v >= *now); + } +} + +#[cfg(test)] +pub mod tests { + use super::*; + use crate::primitives::TrustedOperationSource; + use codec::Encode; + use sp_core::blake2_256; + + type Ex = (); + + fn rotator() -> PoolRotator { + PoolRotator { ban_time: Duration::from_millis(1000), ..Default::default() } + } + + fn hash(index: u64) -> TxHash { + blake2_256(index.encode().as_slice()).into() + } + + fn tx() -> (TxHash, TrustedOperation) { + let hash = hash(5); + let tx = TrustedOperation { + data: (), + bytes: 1, + hash, + priority: 5, + valid_till: 1, + requires: vec![], + provides: vec![], + propagate: true, + source: TrustedOperationSource::External, + }; + + (hash, tx) + } + + #[test] + pub fn test_should_not_ban_if_not_stale() { + // given + let (hash, tx) = tx(); + let rotator = rotator(); + assert!(!rotator.is_banned(&hash)); + let now = Instant::now(); + let past_block = 0; + + // when + assert!(!rotator.ban_if_stale(&now, past_block, &tx)); + + // then + assert!(!rotator.is_banned(&hash)); + } + + #[test] + pub fn test_should_ban_stale_extrinsic() { + // given + let (hash, tx) = tx(); + let rotator = rotator(); + assert!(!rotator.is_banned(&hash)); + + // when + assert!(rotator.ban_if_stale(&Instant::now(), 1, &tx)); + + // then + assert!(rotator.is_banned(&hash)); + } + + #[test] + pub fn test_should_clear_banned() { + // given + let (hash, tx) = tx(); + let rotator = rotator(); + assert!(rotator.ban_if_stale(&Instant::now(), 1, &tx)); + assert!(rotator.is_banned(&hash)); + + // when + let future = Instant::now() + rotator.ban_time + rotator.ban_time; + rotator.clear_timeouts(&future); + + // then + assert!(!rotator.is_banned(&hash)); + } + + #[test] + pub fn test_should_garbage_collect() { + // given + fn tx_with(i: u64, valid_till: u64) -> TrustedOperation { + let hash = hash(i); + TrustedOperation { + data: (), + bytes: 2, + hash, + priority: 5, + valid_till, + requires: vec![], + provides: vec![], + propagate: true, + source: TrustedOperationSource::External, + } + } + + let rotator = rotator(); + + let now = Instant::now(); + let past_block = 0; + + // when + for i in 0..2 * EXPECTED_SIZE { + let tx = tx_with(i as u64, past_block); + assert!(rotator.ban_if_stale(&now, past_block, &tx)); + } + assert_eq!(rotator.banned_until.read().unwrap().len(), 2 * EXPECTED_SIZE); + + // then + let tx = tx_with(2 * EXPECTED_SIZE as u64, past_block); + // trigger a garbage collection + assert!(rotator.ban_if_stale(&now, past_block, &tx)); + assert_eq!(rotator.banned_until.read().unwrap().len(), EXPECTED_SIZE); + } +} diff --git a/bitacross-worker/core-primitives/top-pool/src/tracked_map.rs b/bitacross-worker/core-primitives/top-pool/src/tracked_map.rs new file mode 100644 index 0000000000..dacbe841dd --- /dev/null +++ b/bitacross-worker/core-primitives/top-pool/src/tracked_map.rs @@ -0,0 +1,198 @@ +// 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 . + +pub extern crate alloc; +use alloc::sync::Arc; +use core::{ + clone::Clone, + cmp, hash, + sync::atomic::{AtomicIsize, Ordering as AtomicOrdering}, +}; +use std::collections::{hash_map::Values, HashMap}; + +//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)] +pub struct TrackedMap { + index: Arc>, + bytes: AtomicIsize, + length: AtomicIsize, +} + +impl Default for TrackedMap { + fn default() -> Self { + Self { index: Arc::new(HashMap::new()), bytes: 0.into(), length: 0.into() } + } +} + +impl TrackedMap { + /// Current tracked length of the content. + pub fn len(&self) -> usize { + cmp::max(self.length.load(AtomicOrdering::Relaxed), 0) as usize + } + + /// Returns true if Map is empty + pub fn is_empty(&self) -> bool { + self.length.load(AtomicOrdering::Relaxed) == 0 + } + + /// Current sum of content length. + pub fn bytes(&self) -> usize { + cmp::max(self.bytes.load(AtomicOrdering::Relaxed), 0) as usize + } + + /// Read-only clone of the interior. + pub fn get_read_only_clone(&self) -> ReadOnlyTrackedMap { + ReadOnlyTrackedMap(self.index.clone()) + } + + /// Read Access - no data race safety + pub fn read(&self) -> TrackedMapReadAccess { + TrackedMapReadAccess { inner_guard: self.index.clone() } + } + + /// Write Access - no data race safety + pub fn write(&mut self) -> TrackedMapWriteAccess { + TrackedMapWriteAccess { + //inner_guard: self.index.make_mut(&self), + inner_guard: Arc::make_mut(&mut self.index), + 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 + hash::Hash, +{ + /// Lock map for read. + pub fn read(&self) -> TrackedMapReadAccess { + TrackedMapReadAccess { inner_guard: self.0.clone() } + } +} + +pub struct TrackedMapReadAccess { + inner_guard: Arc>, +} + +impl TrackedMapReadAccess +where + K: Eq + 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) -> Values { + self.inner_guard.values() + } +} + +pub struct TrackedMapWriteAccess<'a, K, V> { + bytes: &'a AtomicIsize, + length: &'a AtomicIsize, + inner_guard: &'a mut HashMap, +} + +impl<'a, K, V> TrackedMapWriteAccess<'a, K, V> +where + K: Eq + 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).map(|old_val| { + self.bytes.fetch_sub(old_val.size() as isize, AtomicOrdering::Relaxed); + self.length.fetch_sub(1, AtomicOrdering::Relaxed); + 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)] +pub mod tests { + + use super::*; + + impl Size for i32 { + fn size(&self) -> usize { + *self as usize / 10 + } + } + + #[test] + pub fn test_basic() { + let mut map = TrackedMap::default(); + + assert!(map.is_empty()); + + 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); + } +} diff --git a/bitacross-worker/core-primitives/top-pool/src/validated_pool.rs b/bitacross-worker/core-primitives/top-pool/src/validated_pool.rs new file mode 100644 index 0000000000..0d66fca8b8 --- /dev/null +++ b/bitacross-worker/core-primitives/top-pool/src/validated_pool.rs @@ -0,0 +1,738 @@ +// 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 . + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +use crate::sgx_reexport_prelude::*; + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +use std::sync::SgxMutex as Mutex; +#[cfg(all(not(feature = "std"), feature = "sgx"))] +use std::sync::SgxRwLock as RwLock; + +#[cfg(feature = "std")] +use std::sync::Mutex; +#[cfg(feature = "std")] +use std::sync::RwLock; + +use crate::{ + base_pool as base, + base_pool::PruneStatus, + error, + listener::Listener, + pool::{ChainApi, EventStream, Options, TransactionFor}, + primitives::{PoolStatus, TrustedOperationSource, TxHash}, + rotator::PoolRotator, +}; +use core::{marker::PhantomData, result::Result}; +use itc_direct_rpc_server::SendRpcResponse; +use itp_stf_primitives::types::ShardIdentifier; +use itp_types::BlockHash as SidechainBlockHash; +use jsonrpc_core::futures::channel::mpsc::{channel, Sender}; +use sp_runtime::{ + generic::BlockId, + traits::SaturatedConversion, + transaction_validity::{TransactionTag as Tag, ValidTransaction}, +}; +use std::{ + collections::{HashMap, HashSet}, + format, + string::String, + sync::Arc, + time::Instant, + vec, + vec::Vec, +}; + +/// Pre-validated operation. Validated pool only accepts operations wrapped in this enum. +#[derive(Debug)] +pub enum ValidatedOperation { + /// TrustedOperation that has been validated successfully. + Valid(base::TrustedOperation), + /// TrustedOperation that is invalid. + Invalid(TxHash, Error), + /// TrustedOperation which validity can't be determined. + /// + /// We're notifying watchers about failure, if 'unknown' operation is submitted. + Unknown(TxHash, Error), +} + +impl ValidatedOperation { + /// Consume validity result, operation data and produce ValidTransaction. + pub fn valid_at( + at: u64, + hash: TxHash, + source: TrustedOperationSource, + data: Ex, + bytes: usize, + validity: ValidTransaction, + ) -> Self { + Self::Valid(base::TrustedOperation { + data, + bytes, + hash, + source, + priority: validity.priority, + requires: validity.requires, + provides: validity.provides, + propagate: validity.propagate, + valid_till: at.saturated_into::().saturating_add(validity.longevity), + }) + } +} + +/// A type of validated operation stored in the pool. +pub type ValidatedOperationFor = ValidatedOperation::Error>; + +/// Pool that deals with validated operations. +pub struct ValidatedPool +where + R: SendRpcResponse, +{ + api: Arc, + options: Options, + listener: RwLock>, + pool: RwLock>, + import_notification_sinks: Mutex>>, + rotator: PoolRotator, + _phantom: PhantomData, +} + +impl ValidatedPool +where + R: SendRpcResponse, + TOP: core::fmt::Debug + Send + Sync + Clone, +{ + /// Create a new operation pool. + pub fn new(options: Options, api: Arc, rpc_response_sender: Arc) -> Self { + let base_pool = base::BasePool::new(options.reject_future_operations); + ValidatedPool { + options, + listener: RwLock::new(Listener::new(rpc_response_sender)), + api, + pool: RwLock::new(base_pool), + import_notification_sinks: Default::default(), + rotator: Default::default(), + _phantom: Default::default(), + } + } + + /// Bans given set of hashes. + pub fn ban(&self, now: &Instant, hashes: impl IntoIterator) { + self.rotator.ban(now, hashes) + } + + /// Returns true if operation with given hash is currently banned from the pool. + pub fn is_banned(&self, hash: &TxHash) -> bool { + self.rotator.is_banned(hash) + } + + /// A fast check before doing any further processing of a operation, like validation. + /// + /// If `ingore_banned` is `true`, it will not check if the operation is banned. + /// + /// It checks if the operation is already imported or banned. If so, it returns an error. + pub fn check_is_known( + &self, + tx_hash: &TxHash, + ignore_banned: bool, + shard: ShardIdentifier, + ) -> Result<(), B::Error> { + if !ignore_banned && self.is_banned(tx_hash) { + Err(error::Error::TemporarilyBanned.into()) + } else if self.pool.read().unwrap().is_imported(tx_hash, shard) { + Err(error::Error::AlreadyImported.into()) + } else { + Ok(()) + } + } + + /// Imports a bunch of pre-validated operations to the pool. + pub fn submit( + &self, + txs: impl IntoIterator>, + shard: ShardIdentifier, + ) -> Vec> { + let results = txs + .into_iter() + .map(|validated_tx| self.submit_one(validated_tx, shard)) + .collect::>(); + + // only enforce limits if there is at least one imported operation + let removed = if results.iter().any(|res| res.is_ok()) { + self.enforce_limits(shard) + } else { + Default::default() + }; + + results + .into_iter() + .map(|res| match res { + Ok(ref hash) if removed.contains(hash) => + Err(error::Error::ImmediatelyDropped.into()), + other => other, + }) + .collect() + } + + /// Submit single pre-validated operation to the pool. + fn submit_one( + &self, + tx: ValidatedOperationFor, + shard: ShardIdentifier, + ) -> Result { + match tx { + ValidatedOperation::Valid(tx) => { + let imported = + self.pool.write().map_err(|_| error::Error::UnlockError)?.import(tx, shard)?; + + if let base::Imported::Ready { ref hash, .. } = imported { + self.import_notification_sinks + .lock() + .map_err(|_| error::Error::UnlockError)? + .retain_mut(|sink| match sink.try_send(*hash) { + Ok(()) => true, + Err(e) => + if e.is_full() { + log::warn!(target: "txpool", "[{:?}] Trying to notify an import but the channel is full", hash); + true + } else { + false + }, + }); + } + + let mut listener = self.listener.write().map_err(|_| error::Error::UnlockError)?; + fire_events(&mut listener, &imported); + Ok(*imported.hash()) + }, + ValidatedOperation::Invalid(hash, err) => { + self.rotator.ban(&Instant::now(), core::iter::once(hash)); + Err(err) + }, + ValidatedOperation::Unknown(hash, err) => { + self.listener.write().unwrap().invalid(&hash); + Err(err) + }, + } + } + + fn enforce_limits(&self, shard: ShardIdentifier) -> HashSet { + let status = self.pool.read().unwrap().status(shard); + let ready_limit = &self.options.ready; + let future_limit = &self.options.future; + + 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) + { + log::debug!( + target: "txpool", + "Enforcing limits ({}/{}kB ready, {}/{}kB future", + ready_limit.count, ready_limit.total_bytes / 1024, + future_limit.count, future_limit.total_bytes / 1024, + ); + + // clean up the pool + let removed = { + let mut pool = self.pool.write().unwrap(); + let removed = pool + .enforce_limits(ready_limit, future_limit, shard) + .into_iter() + .map(|x| x.hash) + .collect::>(); + // ban all removed operations + self.rotator.ban(&Instant::now(), removed.iter().copied()); + removed + }; + if !removed.is_empty() { + log::debug!(target: "txpool", "Enforcing limits: {} dropped", removed.len()); + } + + // run notifications + let mut listener = self.listener.write().unwrap(); + for h in &removed { + listener.dropped(h, None); + } + + removed + } else { + Default::default() + } + } + + /// Import a single extrinsic and starts to watch their progress in the pool. + pub fn submit_and_watch( + &self, + tx: ValidatedOperationFor, + shard: ShardIdentifier, + ) -> Result { + match tx { + ValidatedOperation::Valid(tx) => { + let hash_result = self + .submit(core::iter::once(ValidatedOperation::Valid(tx)), shard) + .pop() + .expect("One extrinsic passed; one result returned; qed"); + // TODO: How to return / notice if Future or Ready queue? + if let Ok(hash) = hash_result { + self.listener.write().unwrap().create_watcher(hash); + } + hash_result + }, + ValidatedOperation::Invalid(hash, err) => { + self.rotator.ban(&Instant::now(), core::iter::once(hash)); + Err(err) + }, + ValidatedOperation::Unknown(_, err) => Err(err), + } + } + + /// Resubmits revalidated operations back to the pool. + /// + /// Removes and then submits passed operations and all dependent operations. + /// Transactions that are missing from the pool are not submitted. + pub fn resubmit( + &self, + mut updated_transactions: HashMap>, + shard: ShardIdentifier, + ) { + #[derive(Debug, Clone, Copy, PartialEq)] + enum Status { + Future, + Ready, + Failed, + Dropped, + } + + let (mut initial_statuses, final_statuses) = { + let mut pool = self.pool.write().unwrap(); + + // remove all passed operations from the ready/future queues + // (this may remove additional operations as well) + // + // for every operation that has an entry in the `updated_transactions`, + // we store updated validation result in txs_to_resubmit + // for every operation that has no entry in the `updated_transactions`, + // we store last validation result (i.e. the pool entry) in txs_to_resubmit + let mut initial_statuses = HashMap::new(); + let mut txs_to_resubmit = Vec::with_capacity(updated_transactions.len()); + while !updated_transactions.is_empty() { + let hash = updated_transactions + .keys() + .next() + .cloned() + .expect("operations is not empty; qed"); + + // note we are not considering tx with hash invalid here - we just want + // to remove it along with dependent operations and `remove_subtree()` + // does exactly what we need + let removed = pool.remove_subtree(&[hash], shard); + for removed_tx in removed { + let removed_hash = removed_tx.hash; + let updated_transaction = updated_transactions.remove(&removed_hash); + let tx_to_resubmit = if let Some(updated_tx) = updated_transaction { + updated_tx + } else { + // in most cases we'll end up in successful `try_unwrap`, but if not + // we still need to reinsert operation back to the pool => duplicate call + let operation = match Arc::try_unwrap(removed_tx) { + Ok(operation) => operation, + Err(operation) => operation.duplicate(), + }; + ValidatedOperation::Valid(operation) + }; + + initial_statuses.insert(removed_hash, Status::Ready); + txs_to_resubmit.push((removed_hash, tx_to_resubmit)); + } + // make sure to remove the hash even if it's not present in the pool any more. + updated_transactions.remove(&hash); + } + + // if we're rejecting future operations, then insertion order matters here: + // if tx1 depends on tx2, then if tx1 is inserted before tx2, then it goes + // to the future queue and gets rejected immediately + // => let's temporary stop rejection and clear future queue before return + pool.with_futures_enabled(|pool, reject_future_operations| { + // now resubmit all removed operations back to the pool + let mut final_statuses = HashMap::new(); + for (hash, tx_to_resubmit) in txs_to_resubmit { + match tx_to_resubmit { + ValidatedOperation::Valid(tx) => match pool.import(tx, shard) { + Ok(imported) => match imported { + base::Imported::Ready { promoted, failed, removed, .. } => { + final_statuses.insert(hash, Status::Ready); + for hash in promoted { + final_statuses.insert(hash, Status::Ready); + } + for hash in failed { + final_statuses.insert(hash, Status::Failed); + } + for tx in removed { + final_statuses.insert(tx.hash, Status::Dropped); + } + }, + base::Imported::Future { .. } => { + final_statuses.insert(hash, Status::Future); + }, + }, + Err(err) => { + // we do not want to fail if single operation 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) + log::warn!( + target: "txpool", + "[{:?}] Removing invalid operation from update: {:?}", + hash, + err, + ); + final_statuses.insert(hash, Status::Failed); + }, + }, + ValidatedOperation::Invalid(_, _) | ValidatedOperation::Unknown(_, _) => { + final_statuses.insert(hash, Status::Failed); + }, + } + } + + // if the pool is configured to reject future operations, let's clear the future + // queue, updating final statuses as required + if reject_future_operations { + for future_tx in pool.clear_future(shard) { + final_statuses.insert(future_tx.hash, Status::Dropped); + } + } + + (initial_statuses, final_statuses) + }) + }; + + // and now let's notify listeners about status changes + let mut listener = self.listener.write().unwrap(); + for (hash, final_status) in final_statuses { + let initial_status = initial_statuses.remove(&hash); + if initial_status.is_none() || Some(final_status) != initial_status { + match final_status { + Status::Future => listener.future(&hash), + Status::Ready => listener.ready(&hash, None), + Status::Dropped => listener.dropped(&hash, None), + Status::Failed => listener.invalid(&hash), + } + } + } + } + + /// For each extrinsic, returns tags that it provides (if known), or None (if it is unknown). + pub fn extrinsics_tags( + &self, + hashes: &[TxHash], + shard: ShardIdentifier, + ) -> Vec>> { + self.pool + .read() + .unwrap() + .by_hashes(hashes, shard) + .into_iter() + .map(|existing_in_pool| existing_in_pool.map(|operation| operation.provides.to_vec())) + .collect() + } + + /// Get ready operation by hash + pub fn ready_by_hash( + &self, + hash: &TxHash, + shard: ShardIdentifier, + ) -> Option> { + self.pool.read().unwrap().ready_by_hash(hash, shard) + } + + /// Prunes ready operations that provide given list of tags. + pub fn prune_tags( + &self, + tags: impl IntoIterator, + shard: ShardIdentifier, + ) -> Result, B::Error> { + // Perform tag-based pruning in the base pool + let status = self.pool.write().unwrap().prune_tags(tags, shard); + // Notify event listeners of all operations + // that were promoted to `Ready` or were dropped. + { + let mut listener = self.listener.write().unwrap(); + for promoted in &status.promoted { + fire_events(&mut *listener, promoted); + } + for f in &status.failed { + listener.dropped(f, None); + } + } + + Ok(status) + } + + /// Resubmit operations that have been revalidated after prune_tags call. + pub fn resubmit_pruned( + &self, + at: &BlockId, + known_imported_hashes: impl IntoIterator + Clone, + pruned_hashes: Vec, + pruned_xts: Vec>, + shard: ShardIdentifier, + ) -> Result<(), B::Error> + where + ::Error: error::IntoPoolError, + { + debug_assert_eq!(pruned_hashes.len(), pruned_xts.len()); + + // Resubmit pruned operations + let results = self.submit(pruned_xts, shard); + + // Collect the hashes of operations that now became invalid (meaning that they are successfully pruned). + let hashes = results.into_iter().enumerate().filter_map(|(idx, r)| { + match r.map_err(error::IntoPoolError::into_pool_error) { + Err(Ok(error::Error::InvalidTrustedOperation)) => Some(pruned_hashes[idx]), + _ => None, + } + }); + // Fire `pruned` notifications for collected hashes and make sure to include + // `known_imported_hashes` since they were just imported as part of the block. + let hashes = hashes.chain(known_imported_hashes.into_iter()); + self.fire_pruned(at, hashes)?; + + // perform regular cleanup of old operations in the pool + // and update temporary bans. + self.clear_stale(at, shard)?; + Ok(()) + } + + /// Fire notifications for pruned operations. + pub fn fire_pruned( + &self, + at: &BlockId, + hashes: impl Iterator, + ) -> Result<(), B::Error> { + let header_hash = self + .api + .block_id_to_hash(at)? + .ok_or_else(|| error::Error::InvalidBlockId(format!("{:?}", at)))?; + let mut listener = self.listener.write().unwrap(); + let mut set = HashSet::with_capacity(hashes.size_hint().0); + for h in hashes { + // `hashes` has possibly duplicate hashes. + // we'd like to send out the `InBlock` notification only once. + if !set.contains(&h) { + listener.pruned(header_hash, &h); + set.insert(h); + } + } + Ok(()) + } + + /// Removes stale operations from the pool. + /// + /// Stale operations are operation beyond their longevity period. + /// Note this function does not remove operations that are already included in the chain. + /// See `prune_tags` if you want this. + pub fn clear_stale( + &self, + at: &BlockId, + shard: ShardIdentifier, + ) -> Result<(), B::Error> { + let block_number = self + .api + .block_id_to_number(at)? + .ok_or_else(|| error::Error::InvalidBlockId(format!("{:?}", at)))? + .saturated_into::(); + let now = Instant::now(); + let to_remove = { + self.ready(shard) + .filter(|tx| self.rotator.ban_if_stale(&now, block_number, tx)) + .map(|tx| tx.hash) + .collect::>() + }; + let futures_to_remove: Vec = { + let p = self.pool.read().unwrap(); + let mut hashes = Vec::new(); + for tx in p.futures(shard) { + if self.rotator.ban_if_stale(&now, block_number, tx) { + hashes.push(tx.hash); + } + } + hashes + }; + // removing old operations + self.remove_invalid(&to_remove, shard, false); + self.remove_invalid(&futures_to_remove, shard, false); + // clear banned operations timeouts + self.rotator.clear_timeouts(&now); + + Ok(()) + } + + /// Get rotator reference. + /// only used for test + pub fn rotator(&self) -> &PoolRotator { + &self.rotator + } + + /// Get api reference. + pub fn api(&self) -> &B { + &self.api + } + + /// Return an event stream of notifications for when operations are imported to the pool. + /// + /// Consumers of this stream should use the `ready` method to actually get the + /// pending operations in the right order. + pub fn import_notification_stream(&self) -> EventStream { + const CHANNEL_BUFFER_SIZE: usize = 1024; + + let (sink, stream) = channel(CHANNEL_BUFFER_SIZE); + self.import_notification_sinks.lock().unwrap().push(sink); + stream + } + + /// Invoked when extrinsics are broadcasted. + pub fn on_broadcasted(&self, propagated: HashMap>) { + let mut listener = self.listener.write().unwrap(); + for (hash, peers) in propagated.into_iter() { + listener.broadcasted(&hash, peers); + } + } + + /// Remove a subtree of operations from the pool and mark them invalid. + /// + /// The operations passed as an argument will be additionally banned + /// to prevent them from entering the pool right away. + /// Note this is not the case for the dependent operations - those may + /// still be valid so we want to be able to re-import them. + pub fn remove_invalid( + &self, + hashes: &[TxHash], + shard: ShardIdentifier, + inblock: bool, + ) -> Vec> { + // early exit in case there is no invalid operations. + if hashes.is_empty() { + return vec![] + } + + let invalid = self.pool.write().unwrap().remove_subtree(hashes, shard); + + log::debug!(target: "txpool", "Removed invalid operations: {:?}", invalid); + + let mut listener = self.listener.write().unwrap(); + if inblock { + for _tx in &invalid { + //listener.in_block(&tx.hash); + } + } else { + // temporarily ban invalid operations + self.rotator.ban(&Instant::now(), hashes.iter().cloned()); + for tx in &invalid { + listener.invalid(&tx.hash); + } + } + + invalid + } + + /// Get an iterator for ready operations ordered by priority + pub fn ready( + &self, + shard: ShardIdentifier, + ) -> impl Iterator> + Send { + self.pool.read().unwrap().ready(shard) + } + + /// Get an iterator for all shards + pub fn shards(&self) -> Vec { + let mut shards = vec![]; + let base_pool = self.pool.read().unwrap(); + let shard_iterator = base_pool.get_shards(); + for shard in shard_iterator { + shards.push(*shard); + } + shards + } + + /// Returns pool status. + pub fn status(&self, shard: ShardIdentifier) -> PoolStatus { + self.pool.read().unwrap().status(shard) + } + + /// Notify all watchers that operations in the block with hash have been finalized + pub async fn on_block_finalized(&self, block_hash: SidechainBlockHash) -> Result<(), B::Error> + where + <::Block as sp_runtime::traits::Block>::Hash: core::fmt::Display, + { + log::trace!(target: "txpool", "Attempting to notify watchers of finalization for {}", block_hash); + self.listener.write().unwrap().finalized(block_hash); + Ok(()) + } + + /// Notify the listener of retracted blocks + pub fn on_block_retracted(&self, block_hash: SidechainBlockHash) { + self.listener.write().unwrap().retracted(block_hash) + } + + /// Notify the listener of top inclusion in sidechain block + pub fn on_block_imported(&self, hashes: &[TxHash], block_hash: SidechainBlockHash) { + for top_hash in hashes.iter() { + self.listener.write().unwrap().in_block(top_hash, block_hash); + } + } + + #[allow(clippy::type_complexity)] + pub fn update_connection_state(&self, updates: Vec<(TxHash, (Vec, bool))>) { + for (top_hash, (encoded_value, force_wait)) in updates { + self.listener.write().unwrap().update_connection_state( + &top_hash, + encoded_value.clone(), + force_wait, + ); + self.listener + .write() + .unwrap() + .top_executed(&top_hash, &encoded_value, force_wait); + } + } + + pub fn swap_rpc_connection_hash(&self, old_hash: TxHash, new_hash: TxHash) { + self.listener.write().unwrap().swap_rpc_connection_hash(old_hash, new_hash); + } +} + +fn fire_events(listener: &mut Listener, imported: &base::Imported) +where + R: SendRpcResponse, +{ + match *imported { + base::Imported::Ready { ref promoted, ref failed, ref removed, ref hash } => { + listener.ready(hash, None); + for f in failed { + listener.invalid(f); + } + for r in removed { + listener.dropped(&r.hash, Some(hash)); + } + for p in promoted { + listener.ready(p, None); + } + }, + base::Imported::Future { ref hash } => listener.future(hash), + } +} diff --git a/bitacross-worker/core-primitives/top-pool/src/watcher.rs b/bitacross-worker/core-primitives/top-pool/src/watcher.rs new file mode 100644 index 0000000000..dd6626c6d5 --- /dev/null +++ b/bitacross-worker/core-primitives/top-pool/src/watcher.rs @@ -0,0 +1,171 @@ +// 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 . + +//! Extrinsics status updates. + +extern crate alloc; +use crate::primitives::TxHash; +use alloc::{string::String, sync::Arc, vec::Vec}; + +use itc_direct_rpc_server::SendRpcResponse; +use itp_types::{BlockHash as SidechainBlockHash, TrustedOperationStatus}; +use log::*; + +/// Extrinsic watcher. +/// +/// Represents a stream of status updates for particular extrinsic. +#[derive(Debug)] +pub struct Watcher { + //receiver: TracingUnboundedReceiver>, + hash: TxHash, + is_in_block: bool, + rpc_response_sender: Arc, +} + +impl Watcher +where + S: SendRpcResponse, +{ + /// Returns the operation hash. + pub fn hash(&self) -> &TxHash { + &self.hash + } + + pub fn new_watcher(hash: TxHash, rpc_response_sender: Arc) -> Self { + Watcher { hash, is_in_block: false, rpc_response_sender } + } + + /// TrustedOperation became ready. + pub fn ready(&mut self) { + self.send(TrustedOperationStatus::Ready) + } + + /// TrustedOperation was moved to future. + pub fn future(&mut self) { + self.send(TrustedOperationStatus::Future) + } + + /// Some state change (perhaps another extrinsic was included) rendered this extrinsic invalid. + pub fn usurped(&mut self) { + //self.send(TrustedOperationStatus::Usurped(hash)); + self.send(TrustedOperationStatus::Usurped); + self.is_in_block = true; + } + + /// Extrinsic has been included in block with given hash. + pub fn in_block(&mut self, block_hash: SidechainBlockHash) { + self.send(TrustedOperationStatus::InSidechainBlock(block_hash)); + self.is_in_block = true; + } + + /// Extrinsic has been finalized by a finality gadget. + pub fn finalized(&mut self) { + //self.send(TrustedOperationStatus::Finalized(hash)); + self.send(TrustedOperationStatus::Finalized); + self.is_in_block = true; + } + + /// The block this extrinsic was included in has been retracted + pub fn finality_timeout(&mut self) { + //self.send(TrustedOperationStatus::FinalityTimeout(hash)); + self.send(TrustedOperationStatus::FinalityTimeout); + self.is_in_block = true; + } + + /// The block this extrinsic was included in has been retracted + pub fn retracted(&mut self) { + //self.send(TrustedOperationStatus::Retracted(hash)); + self.send(TrustedOperationStatus::Retracted); + } + + /// Extrinsic has been marked as invalid by the block builder. + pub fn invalid(&mut self) { + self.send(TrustedOperationStatus::Invalid); + // we mark as finalized as there are no more notifications + self.is_in_block = true; + } + + /// TrustedOperation has been dropped from the pool because of the limit. + pub fn dropped(&mut self) { + self.send(TrustedOperationStatus::Dropped); + self.is_in_block = true; + } + + /// The extrinsic has been broadcast to the given peers. + pub fn broadcast(&mut self, _peers: Vec) { + //self.send(TrustedOperationStatus::Broadcast(peers)) + self.send(TrustedOperationStatus::Broadcast) + } + + /// The extrinsic has been executed. + pub fn top_executed(&mut self, response: &[u8], force_wait: bool) { + self.send(TrustedOperationStatus::TopExecuted(response.to_vec(), force_wait)) + } + + /// Returns true if the are no more listeners for this extrinsic or it was finalized. + pub fn is_done(&self) -> bool { + self.is_in_block // || self.receivers.is_empty() + } + + fn send(&mut self, status: TrustedOperationStatus) { + if let Err(e) = self.rpc_response_sender.update_status_event(*self.hash(), status) { + error!("failed to send status update to rpc client: {:?}", e); + } + } + + // Litentry: set the new rpc response value and force_wait flag + pub fn update_connection_state(&mut self, encoded_value: Vec, force_wait: bool) { + if let Err(e) = self.rpc_response_sender.update_connection_state( + *self.hash(), + encoded_value, + force_wait, + ) { + warn!("failed to update connection state: {:?}", e); + } + } + + // Litentry: swap the old hash with the new one in rpc connection registry + pub fn swap_rpc_connection_hash(&self, new_hash: TxHash) { + if let Err(e) = self.rpc_response_sender.swap_hash(*self.hash(), new_hash) { + warn!("failed to swap rpc connection hash: {:?}", e); + } + } +} + +/* /// Sender part of the watcher. Exposed only for testing purposes. +#[derive(Debug)] +pub struct Sender { + //receivers: Vec>>, + //receivers: Vec, + is_in_block: bool, +} + */ +/* impl Default for Watcher { + fn default() -> Self { + Watcher { + //receivers: Default::default(), + hash: , + is_in_block: false, + } + } +} */ + +/* impl Sender { + /// Add a new watcher to this sender object. + +} */ diff --git a/bitacross-worker/core-primitives/types/Cargo.toml b/bitacross-worker/core-primitives/types/Cargo.toml new file mode 100644 index 0000000000..86013c7c08 --- /dev/null +++ b/bitacross-worker/core-primitives/types/Cargo.toml @@ -0,0 +1,50 @@ +[package] +name = "itp-types" +version = "0.9.0" +authors = ['Trust Computing GmbH ', 'Integritee AG '] +homepage = 'https://litentry.com/' +repository = 'https://github.com/litentry/litentry-parachain' +license = "Apache-2.0" +edition = "2021" + +[dependencies] +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } + +# local dependencies +itp-sgx-crypto = { path = "../sgx/crypto", default-features = false } +itp-sgx-runtime-primitives = { path = "../../core-primitives/sgx-runtime-primitives", default-features = false } +itp-stf-primitives = { path = "../../core-primitives/stf-primitives", default-features = false } +itp-utils = { path = "../../core-primitives/utils", default-features = false } + +# scs +substrate-api-client = { default-features = false, features = ["sync-api"], git = "https://github.com/scs/substrate-api-client.git", branch = "polkadot-v0.9.42-tag-v0.14.0" } + +# substrate-deps +frame-system = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } +pallet-balances = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } +sp-core = { default-features = false, features = ["full_crypto"], git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } +sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } +sp-std = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } + +# litentry +litentry-primitives = { path = "../../litentry/primitives", default-features = false } + +[features] +default = ["std"] +std = [ + "codec/std", + "itp-sgx-crypto/std", + "itp-sgx-runtime-primitives/std", + "itp-stf-primitives/std", + "itp-utils/std", + "substrate-api-client/std", + # substrate + "frame-system/std", + "pallet-balances/std", + "sp-std/std", + "sp-core/std", + "sp-runtime/std", + # litentry + "litentry-primitives/std", +] +test = [] diff --git a/bitacross-worker/core-primitives/types/src/lib.rs b/bitacross-worker/core-primitives/types/src/lib.rs new file mode 100644 index 0000000000..911282e427 --- /dev/null +++ b/bitacross-worker/core-primitives/types/src/lib.rs @@ -0,0 +1,218 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +#![cfg_attr(all(not(target_env = "sgx"), not(feature = "std")), no_std)] +#![cfg_attr(target_env = "sgx", feature(rustc_private))] + +use crate::storage::StorageEntry; +use codec::{Decode, Encode}; +use itp_sgx_crypto::ShieldingCryptoDecrypt; +use litentry_primitives::{decl_rsa_request, RequestAesKeyNonce}; +use sp_std::{boxed::Box, fmt::Debug, vec::Vec}; + +pub mod parentchain; +pub mod storage; + +/// Substrate runtimes provide no string type. Hence, for arbitrary data of varying length the +/// `Vec` is used. In the polkadot-js the typedef `Text` is used to automatically +/// utf8 decode bytes into a string. +#[cfg(not(feature = "std"))] +pub type PalletString = Vec; + +#[cfg(feature = "std")] +pub type PalletString = String; + +pub use itp_sgx_runtime_primitives::types::*; +pub use litentry_primitives::{Assertion, DecryptableRequest}; +pub use sp_core::{crypto::AccountId32 as AccountId, H256}; + +pub type IpfsHash = [u8; 46]; +pub type MrEnclave = [u8; 32]; + +pub type CallIndex = [u8; 2]; + +// pallet teerex +pub type ConfirmCallFn = (CallIndex, ShardIdentifier, H256, Vec); +pub type ShieldFundsFn = (CallIndex, Vec, Balance, ShardIdentifier); +pub type CallWorkerFn = (CallIndex, RsaRequest); + +pub type UpdateScheduledEnclaveFn = (CallIndex, SidechainBlockNumber, MrEnclave); +pub type RemoveScheduledEnclaveFn = (CallIndex, SidechainBlockNumber); + +// pallet IMP +pub type LinkIdentityParams = (ShardIdentifier, AccountId, Vec, Vec, RequestAesKeyNonce); +pub type LinkIdentityFn = (CallIndex, LinkIdentityParams); + +pub type DeactivateIdentityParams = (ShardIdentifier, Vec); +pub type DeactivateIdentityFn = (CallIndex, DeactivateIdentityParams); + +pub type ActivateIdentityParams = (ShardIdentifier, Vec); +pub type ActivateIdentityFn = (CallIndex, DeactivateIdentityParams); + +// pallet VCMP +pub type RequestVCParams = (ShardIdentifier, Assertion); +pub type RequestVCFn = (CallIndex, RequestVCParams); + +pub type Enclave = EnclaveGen; + +/// Simple blob to hold an encoded call +#[derive(Debug, PartialEq, Eq, Clone, Default)] +pub struct OpaqueCall(pub Vec); + +impl OpaqueCall { + /// Convert call tuple to an `OpaqueCall`. + pub fn from_tuple(call: &C) -> Self { + OpaqueCall(call.encode()) + } +} + +impl Encode for OpaqueCall { + fn encode(&self) -> Vec { + self.0.clone() + } +} + +// Litentry: re-declared due to orphan rule (that's why macro is used) +decl_rsa_request!(Debug); + +impl DecryptableRequest for RsaRequest { + type Error = (); + + fn shard(&self) -> ShardIdentifier { + self.shard + } + + fn payload(&self) -> &[u8] { + self.payload.as_slice() + } + + fn decrypt( + &mut self, + enclave_shielding_key: Box>, + ) -> core::result::Result, ()> { + enclave_shielding_key.decrypt(self.payload.as_slice()).map_err(|_| ()) + } +} + +// Todo: move this improved enclave definition into a primitives crate in the pallet_teerex repo. +#[derive(Encode, Decode, Clone, PartialEq, sp_core::RuntimeDebug)] +pub struct EnclaveGen { + pub pubkey: AccountId, + // FIXME: this is redundant information + pub mr_enclave: [u8; 32], + pub timestamp: u64, + // unix epoch in milliseconds + pub url: PalletString, // utf8 encoded url +} + +impl EnclaveGen { + pub fn new(pubkey: AccountId, mr_enclave: [u8; 32], timestamp: u64, url: PalletString) -> Self { + Self { pubkey, mr_enclave, timestamp, url } + } +} + +#[derive(Debug, Clone, PartialEq, Encode, Decode, Eq)] +pub enum DirectRequestStatus { + /// Direct request was successfully executed + #[codec(index = 0)] + Ok, + /// Trusted Call Status + /// Litentry: embed the top hash here - TODO - use generic type? + #[codec(index = 1)] + TrustedOperationStatus(TrustedOperationStatus, H256), + /// Direct request could not be executed + #[codec(index = 2)] + Error, +} + +#[derive(Debug, Clone, PartialEq, Encode, Decode, Eq)] +pub enum TrustedOperationStatus { + /// TrustedOperation is submitted to the top pool. + #[codec(index = 0)] + Submitted, + /// TrustedOperation is part of the future queue. + #[codec(index = 1)] + Future, + /// TrustedOperation is part of the ready queue. + #[codec(index = 2)] + Ready, + /// The operation has been broadcast to the given peers. + #[codec(index = 3)] + Broadcast, + /// TrustedOperation has been included in block with given hash. + #[codec(index = 4)] + InSidechainBlock(BlockHash), + /// The block this operation was included in has been retracted. + #[codec(index = 5)] + Retracted, + /// Maximum number of finality watchers has been reached, + /// old watchers are being removed. + #[codec(index = 6)] + FinalityTimeout, + /// TrustedOperation has been finalized by a finality-gadget, e.g GRANDPA + #[codec(index = 7)] + Finalized, + /// TrustedOperation has been replaced in the pool, by another operation + /// that provides the same tags. (e.g. same (sender, nonce)). + #[codec(index = 8)] + Usurped, + /// TrustedOperation has been dropped from the pool because of the limit. + #[codec(index = 9)] + Dropped, + /// TrustedOperation is no longer valid in the current state. + #[codec(index = 10)] + Invalid, + /// TrustedOperation has been executed. + TopExecuted(Vec, bool), +} + +#[derive(Encode, Decode, Clone, Debug, PartialEq)] +pub enum WorkerRequest { + #[codec(index = 0)] + ChainStorage(Vec, Option), // (storage_key, at_block) + #[codec(index = 1)] + ChainStorageKeys(Vec, Option), // (storage_key_prefix, at_block) +} + +#[derive(Encode, Decode, Clone, Debug, PartialEq)] +pub enum WorkerResponse { + #[codec(index = 0)] + ChainStorage(Vec, Option, Option>>), // (storage_key, storage_value, storage_proof) + #[codec(index = 1)] + ChainStorageKeys(Vec>), // (storage_keys) +} + +impl From>> for StorageEntry> { + fn from(response: WorkerResponse>) -> Self { + match response { + WorkerResponse::ChainStorage(key, value, proof) => StorageEntry { key, value, proof }, + _ => StorageEntry::default(), + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn opaque_call_encodes_correctly() { + let call_tuple = ([1u8, 2u8], 5u8); + let call = OpaqueCall::from_tuple(&call_tuple); + assert_eq!(call.encode(), call_tuple.encode()) + } +} diff --git a/bitacross-worker/core-primitives/types/src/parentchain.rs b/bitacross-worker/core-primitives/types/src/parentchain.rs new file mode 100644 index 0000000000..05085ffc06 --- /dev/null +++ b/bitacross-worker/core-primitives/types/src/parentchain.rs @@ -0,0 +1,224 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::OpaqueCall; +use alloc::{format, vec::Vec}; +use codec::{Decode, Encode}; +use core::fmt::Debug; +use itp_stf_primitives::traits::{IndirectExecutor, TrustedCallVerification}; +use itp_utils::stringify::account_id_to_string; +use sp_core::bounded::alloc; +use sp_runtime::{generic::Header as HeaderG, traits::BlakeTwo256, MultiAddress, MultiSignature}; +use substrate_api_client::ac_node_api::StaticEvent; + +pub type StorageProof = Vec>; + +// Basic Types. +pub type Index = u32; +pub type Balance = u128; +pub type Hash = sp_core::H256; + +// Account Types. +pub type AccountId = sp_core::crypto::AccountId32; +pub type AccountData = pallet_balances::AccountData; +pub type AccountInfo = frame_system::AccountInfo; +pub type Address = MultiAddress; +// todo! make generic +/// The type used to represent the kinds of proxying allowed. +#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, Debug)] +pub enum ProxyType { + Any, + NonTransfer, + Governance, + Staking, +} + +// Block Types +pub type BlockNumber = u32; +pub type Header = HeaderG; +pub type BlockHash = sp_core::H256; + +/// Alias to 512-bit hash when used in the context of a transaction signature on the chain. +pub type Signature = MultiSignature; + +#[derive(Encode, Decode, Copy, Clone, Debug, PartialEq, Eq)] +pub enum ParentchainId { + /// The Litentry Parentchain, the trust root of the enclave and serving finality to sidechains. + #[codec(index = 0)] + Litentry, + /// A target chain containing custom business logic. + #[codec(index = 1)] + TargetA, + /// Another target chain containing custom business logic. + #[codec(index = 2)] + TargetB, +} + +#[cfg(feature = "std")] +impl std::fmt::Display for ParentchainId { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + let message = match self { + ParentchainId::Litentry => "L1:Litentry", + ParentchainId::TargetA => "L1:AssetHub", + ParentchainId::TargetB => "L1:UNDEFINED", + }; + write!(f, "{}", message) + } +} + +pub trait IdentifyParentchain { + fn parentchain_id(&self) -> ParentchainId; +} + +pub trait FilterEvents { + type Error: From + core::fmt::Debug; + fn get_extrinsic_statuses(&self) -> core::result::Result, Self::Error>; + + fn get_transfer_events(&self) -> core::result::Result, Self::Error>; +} + +#[derive(Encode, Decode, Debug)] +pub struct ExtrinsicSuccess; + +impl StaticEvent for ExtrinsicSuccess { + const PALLET: &'static str = "System"; + const EVENT: &'static str = "ExtrinsicSuccess"; +} + +#[derive(Encode, Decode)] +pub struct ExtrinsicFailed; + +impl StaticEvent for ExtrinsicFailed { + const PALLET: &'static str = "System"; + const EVENT: &'static str = "ExtrinsicFailed"; +} + +#[derive(Debug)] +pub enum ExtrinsicStatus { + Success, + Failed, +} + +#[derive(Encode, Decode, Debug)] +pub struct BalanceTransfer { + pub from: AccountId, + pub to: AccountId, + pub amount: Balance, +} + +impl core::fmt::Display for BalanceTransfer { + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + let message = format!( + "BalanceTransfer :: from: {}, to: {}, amount: {}", + account_id_to_string::(&self.from), + account_id_to_string::(&self.to), + self.amount + ); + write!(f, "{}", message) + } +} + +impl StaticEvent for BalanceTransfer { + const PALLET: &'static str = "Balances"; + const EVENT: &'static str = "Transfer"; +} + +pub trait HandleParentchainEvents +where + Executor: IndirectExecutor, + TCS: PartialEq + Encode + Decode + Debug + Clone + Send + Sync + TrustedCallVerification, +{ + fn handle_events( + executor: &Executor, + events: impl FilterEvents, + vault_account: &AccountId, + ) -> core::result::Result<(), Error>; +} + +#[derive(Debug)] +pub enum ParentchainError { + ShieldFundsFailure, + FunctionalityDisabled, +} + +impl core::fmt::Display for ParentchainError { + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + let message = match &self { + ParentchainError::ShieldFundsFailure => "Parentchain Error: ShieldFundsFailure", + ParentchainError::FunctionalityDisabled => "Parentchain Error: FunctionalityDisabled", + }; + write!(f, "{}", message) + } +} + +impl From for () { + fn from(_: ParentchainError) -> Self {} +} + +/// a wrapper to target calls to specific parentchains +#[derive(Encode, Debug, Clone, PartialEq, Eq)] +pub enum ParentchainCall { + Litentry(OpaqueCall), + TargetA(OpaqueCall), + TargetB(OpaqueCall), +} + +impl ParentchainCall { + pub fn as_litentry(&self) -> Option { + if let Self::Litentry(call) = self { + Some(call.clone()) + } else { + None + } + } + pub fn as_target_a(&self) -> Option { + if let Self::TargetA(call) = self { + Some(call.clone()) + } else { + None + } + } + pub fn as_target_b(&self) -> Option { + if let Self::TargetB(call) = self { + Some(call.clone()) + } else { + None + } + } + pub fn as_opaque_call_for(&self, parentchain_id: ParentchainId) -> Option { + match parentchain_id { + ParentchainId::Litentry => + if let Self::Litentry(call) = self { + Some(call.clone()) + } else { + None + }, + ParentchainId::TargetA => + if let Self::TargetA(call) = self { + Some(call.clone()) + } else { + None + }, + ParentchainId::TargetB => + if let Self::TargetB(call) = self { + Some(call.clone()) + } else { + None + }, + } + } +} diff --git a/bitacross-worker/core-primitives/types/src/storage.rs b/bitacross-worker/core-primitives/types/src/storage.rs new file mode 100644 index 0000000000..ea362dff8d --- /dev/null +++ b/bitacross-worker/core-primitives/types/src/storage.rs @@ -0,0 +1,59 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 sp_std::prelude::Vec; + +#[derive(Default, Clone, Encode, Decode)] +pub struct StorageEntry { + pub key: Vec, + pub value: Option, + pub proof: Option>>, +} + +/// Contains private fields. We don't expose a public constructor. Hence, the only way +/// to get a `StorageEntryVerified` is via the `VerifyStorageProof` trait. +#[derive(Default, Clone, Encode, Decode)] +pub struct StorageEntryVerified { + pub key: Vec, + pub value: Option, +} + +#[cfg(feature = "test")] +impl StorageEntryVerified { + pub fn new(key: Vec, value: Option) -> Self { + Self { key, value } + } +} + +impl StorageEntryVerified { + pub fn key(&self) -> &[u8] { + &self.key + } + + pub fn value(&self) -> &Option { + &self.value + } + + /// Without accessing the the field directly but with getters only, we cannot partially + /// own the struct. So we can't do: `hashmap.insert(self.key(), self.value())` if the getters + /// consumed the `self`, which is needed to return owned values. Hence, we supply this method, + /// to consume `self` and be able to use the values individually. + pub fn into_tuple(self) -> (Vec, Option) { + (self.key, self.value) + } +} diff --git a/bitacross-worker/core-primitives/utils/Cargo.toml b/bitacross-worker/core-primitives/utils/Cargo.toml new file mode 100644 index 0000000000..7c293aa011 --- /dev/null +++ b/bitacross-worker/core-primitives/utils/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "itp-utils" +version = "0.9.0" +authors = ['Trust Computing GmbH ', 'Integritee AG '] +homepage = "https://litentry.com/" +repository = "https://github.com/litentry/litentry-parachain" +license = "Apache-2.0" +edition = "2021" + +[dependencies] +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +hex = { version = "0.4.3", default-features = false, features = ["alloc"] } + +[features] +default = ["std"] +std = [ + "codec/std", + "hex/std", +] diff --git a/bitacross-worker/core-primitives/utils/src/buffer.rs b/bitacross-worker/core-primitives/utils/src/buffer.rs new file mode 100644 index 0000000000..89d02ccc0f --- /dev/null +++ b/bitacross-worker/core-primitives/utils/src/buffer.rs @@ -0,0 +1,67 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +//! Buffer utility functions. + +use alloc::vec::Vec; + +/// Fills a given buffer with data and the left over buffer space with white spaces. +/// Throw an error if the buffer size is not enough to hold `data`, +/// return the length of `data` otherwise. +pub fn write_slice_and_whitespace_pad( + writable: &mut [u8], + data: Vec, +) -> Result { + if data.len() > writable.len() { + return Err(BufferError::InsufficientBufferSize { + actual: writable.len(), + required: data.len(), + }) + } + let (left, right) = writable.split_at_mut(data.len()); + left.clone_from_slice(&data); + // fill the right side with whitespace + right.iter_mut().for_each(|x| *x = 0x20); + Ok(data.len()) +} + +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)] +pub enum BufferError { + InsufficientBufferSize { actual: usize, required: usize }, +} + +#[cfg(test)] +mod tests { + use super::*; + use alloc::vec; + + #[test] + fn write_slice_and_whitespace_pad_works() { + let mut writable = vec![0; 32]; + let data = vec![1; 30]; + assert_eq!(write_slice_and_whitespace_pad(&mut writable, data), Ok(30)); + assert_eq!(&writable[..30], vec![1; 30]); + assert_eq!(&writable[30..], vec![0x20; 2]); + } + + #[test] + fn write_slice_and_whitespace_pad_returns_error_if_buffer_too_small() { + let mut writable = vec![0; 32]; + let data = vec![1; 33]; + assert!(write_slice_and_whitespace_pad(&mut writable, data).is_err()); + } +} diff --git a/bitacross-worker/core-primitives/utils/src/error.rs b/bitacross-worker/core-primitives/utils/src/error.rs new file mode 100644 index 0000000000..5ca7508d26 --- /dev/null +++ b/bitacross-worker/core-primitives/utils/src/error.rs @@ -0,0 +1,27 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 alloc::string::String; + +pub type Result = core::result::Result; + +#[derive(Debug)] +pub enum Error { + Hex(hex::FromHexError), + Codec(codec::Error), + Other(String), +} diff --git a/bitacross-worker/core-primitives/utils/src/hex.rs b/bitacross-worker/core-primitives/utils/src/hex.rs new file mode 100644 index 0000000000..4c167af6f3 --- /dev/null +++ b/bitacross-worker/core-primitives/utils/src/hex.rs @@ -0,0 +1,117 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +//! Hex encoding utility functions. + +// Todo: merge with hex_display + +use crate::error::{Error, Result}; +use alloc::{string::String, vec::Vec}; +use codec::{Decode, Encode}; + +/// Trait to encode a given value to a hex string, prefixed with "0x". +pub trait ToHexPrefixed { + fn to_hex(&self) -> String; +} + +impl ToHexPrefixed for T { + fn to_hex(&self) -> String { + hex_encode(&self.encode()) + } +} + +/// Trait to decode a hex string to a given output. +pub trait FromHexPrefixed { + type Output; + + fn from_hex(msg: &str) -> Result; +} + +impl FromHexPrefixed for T { + type Output = T; + + fn from_hex(msg: &str) -> Result { + let byte_array = decode_hex(msg)?; + Decode::decode(&mut byte_array.as_slice()).map_err(Error::Codec) + } +} + +/// Hex encodes given data and preappends a "0x". +pub fn hex_encode(data: &[u8]) -> String { + let mut hex_str = hex::encode(data); + hex_str.insert_str(0, "0x"); + hex_str +} + +/// Helper method for decoding hex. +pub fn decode_hex>(message: T) -> Result> { + let message = message.as_ref(); + let message = match message { + [b'0', b'x', hex_value @ ..] => hex_value, + _ => message, + }; + + let decoded_message = hex::decode(message).map_err(Error::Hex)?; + Ok(decoded_message) +} + +#[cfg(test)] +mod tests { + use super::*; + use alloc::string::ToString; + + #[test] + fn hex_encode_decode_works() { + let data = "Hello World!".to_string(); + + let hex_encoded_data = hex_encode(&data.encode()); + let decoded_data = + String::decode(&mut decode_hex(hex_encoded_data).unwrap().as_slice()).unwrap(); + + assert_eq!(data, decoded_data); + } + + #[test] + fn hex_encode_decode_works_empty_input() { + let data = String::new(); + + let hex_encoded_data = hex_encode(&data.encode()); + let decoded_data = + String::decode(&mut decode_hex(hex_encoded_data).unwrap().as_slice()).unwrap(); + + assert_eq!(data, decoded_data); + } + + #[test] + fn hex_encode_decode_works_empty_input_for_decode() { + let data = String::new(); + + let decoded_data = decode_hex(data).unwrap(); + + assert!(decoded_data.is_empty()); + } + + #[test] + fn to_hex_from_hex_works() { + let data = "Hello World!".to_string(); + + let hex_encoded_data = data.to_hex(); + let decoded_data = String::from_hex(&hex_encoded_data).unwrap(); + + assert_eq!(data, decoded_data); + } +} diff --git a/bitacross-worker/core-primitives/utils/src/hex_display.rs b/bitacross-worker/core-primitives/utils/src/hex_display.rs new file mode 100644 index 0000000000..f0525b4e2f --- /dev/null +++ b/bitacross-worker/core-primitives/utils/src/hex_display.rs @@ -0,0 +1,96 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Wrapper type for byte collections that outputs hex. +//! +//! Copied from sp-core and made purely no-std. + +/// Simple wrapper to display hex representation of bytes. +pub struct HexDisplay<'a>(&'a [u8]); + +impl<'a> HexDisplay<'a> { + /// Create new instance that will display `d` as a hex string when displayed. + pub fn from(d: &'a R) -> Self { + HexDisplay(d.as_bytes_ref()) + } +} + +impl<'a> core::fmt::Display for HexDisplay<'a> { + fn fmt(&self, f: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error> { + if self.0.len() < 1027 { + for byte in self.0 { + f.write_fmt(format_args!("{:02x}", byte))?; + } + } else { + for byte in &self.0[0..512] { + f.write_fmt(format_args!("{:02x}", byte))?; + } + f.write_str("...")?; + for byte in &self.0[self.0.len() - 512..] { + f.write_fmt(format_args!("{:02x}", byte))?; + } + } + Ok(()) + } +} + +impl<'a> core::fmt::Debug for HexDisplay<'a> { + fn fmt(&self, f: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error> { + for byte in self.0 { + f.write_fmt(format_args!("{:02x}", byte))?; + } + Ok(()) + } +} + +/// Simple trait to transform various types to `&[u8]` +pub trait AsBytesRef { + /// Transform `self` into `&[u8]`. + fn as_bytes_ref(&self) -> &[u8]; +} + +impl AsBytesRef for &[u8] { + fn as_bytes_ref(&self) -> &[u8] { + self + } +} + +impl AsBytesRef for [u8] { + fn as_bytes_ref(&self) -> &[u8] { + self + } +} + +impl AsBytesRef for alloc::vec::Vec { + fn as_bytes_ref(&self) -> &[u8] { + self + } +} + +macro_rules! impl_non_endians { + ( $( $t:ty ),* ) => { $( + impl AsBytesRef for $t { + fn as_bytes_ref(&self) -> &[u8] { &self[..] } + } + )* } +} + +impl_non_endians!( + [u8; 1], [u8; 2], [u8; 3], [u8; 4], [u8; 5], [u8; 6], [u8; 7], [u8; 8], [u8; 10], [u8; 12], + [u8; 14], [u8; 16], [u8; 20], [u8; 24], [u8; 28], [u8; 32], [u8; 40], [u8; 48], [u8; 56], + [u8; 64], [u8; 65], [u8; 80], [u8; 96], [u8; 112], [u8; 128] +); diff --git a/bitacross-worker/core-primitives/utils/src/lib.rs b/bitacross-worker/core-primitives/utils/src/lib.rs new file mode 100644 index 0000000000..d03767e6c6 --- /dev/null +++ b/bitacross-worker/core-primitives/utils/src/lib.rs @@ -0,0 +1,35 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 utility functions. + +#![no_std] + +extern crate alloc; + +pub mod buffer; +pub mod error; +pub mod hex; +pub mod hex_display; +pub mod macros; +pub mod stringify; + +// Public re-exports. +pub use self::{ + buffer::write_slice_and_whitespace_pad, + hex::{FromHexPrefixed, ToHexPrefixed}, +}; diff --git a/bitacross-worker/core-primitives/utils/src/macros.rs b/bitacross-worker/core-primitives/utils/src/macros.rs new file mode 100644 index 0000000000..69783ff727 --- /dev/null +++ b/bitacross-worker/core-primitives/utils/src/macros.rs @@ -0,0 +1,35 @@ +// Copyright 2020-2023 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . + +#[macro_export] +macro_rules! if_production_or { + ($prod_variant:expr, $non_prod_variant:expr) => { + if cfg!(feature = "production") { + $prod_variant + } else { + $non_prod_variant + } + }; +} + +#[macro_export] +macro_rules! if_not_production { + ($expression:expr) => { + if cfg!(not(feature = "production")) { + $expression + } + }; +} diff --git a/bitacross-worker/core-primitives/utils/src/stringify.rs b/bitacross-worker/core-primitives/utils/src/stringify.rs new file mode 100644 index 0000000000..e514fdbecb --- /dev/null +++ b/bitacross-worker/core-primitives/utils/src/stringify.rs @@ -0,0 +1,36 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 methods to stringify certain types that don't have a working +//! `Debug` implementation on `sgx`. + +use crate::hex_display::{AsBytesRef, HexDisplay}; +use alloc::{format, string::String}; +use codec::Encode; + +/// Convert a sp_core public type to string. +pub fn public_to_string(t: &T) -> String { + format!("{}", HexDisplay::from(t)) +} + +pub fn account_id_to_string(account: &AccountId) -> String { + format!("0x{}", HexDisplay::from(&account.encode())) +} + +pub fn account_id_to_string_without_prefix(account: &AccountId) -> String { + format!("{}", HexDisplay::from(&account.encode())) +} diff --git a/bitacross-worker/core/direct-rpc-client/Cargo.toml b/bitacross-worker/core/direct-rpc-client/Cargo.toml new file mode 100644 index 0000000000..69631b5e40 --- /dev/null +++ b/bitacross-worker/core/direct-rpc-client/Cargo.toml @@ -0,0 +1,53 @@ +[package] +name = "itc-direct-rpc-client" +version = "0.1.0" +authors = ['Trust Computing GmbH '] +edition = "2021" + +[dependencies] +# sgx dependencies +rustls_sgx = { package = "rustls", optional = true, git = "https://github.com/mesalock-linux/rustls", tag = "sgx_1.1.3", features = ["dangerous_configuration"] } +sgx_tstd = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git", optional = true } +tungstenite_sgx = { package = "tungstenite", optional = true, git = "https://github.com/integritee-network/tungstenite-rs-sgx", branch = "sgx-experimental", features = ["rustls-tls-webpki-roots"] } +url_sgx = { package = "url", optional = true, git = "https://github.com/mesalock-linux/rust-url-sgx", tag = "sgx_1.1.3" } +webpki_sgx = { package = "webpki", optional = true, git = "https://github.com/mesalock-linux/webpki", branch = "mesalock_sgx" } + +# no-std dependencies +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } +log = { version = "0.4", default-features = false } +serde_json = { version = "1.0", default-features = false } + +# std dependencies +rustls = { version = "0.19", optional = true, features = ["dangerous_configuration"] } +tungstenite = { version = "0.15.0", optional = true, features = ["rustls-tls-webpki-roots"] } +url = { version = "2.0.0", optional = true } +webpki = { version = "0.21", optional = true } + +# local dependencies +itp-rpc = { path = "../../core-primitives/rpc", default-features = false } +itp-types = { path = "../../core-primitives/types", default-features = false } +itp-utils = { path = "../../core-primitives/utils", default-features = false } +litentry-primitives = { path = "../../litentry/primitives", default-features = false } + +[features] +default = ["std"] +sgx = [ + "webpki_sgx", + "url_sgx", + "tungstenite_sgx", + "rustls_sgx", + "sgx_tstd", + "itp-rpc/sgx", + "litentry-primitives/sgx", +] +std = [ + "rustls", + "webpki", + "tungstenite", + "url", + "itp-rpc/std", + "itp-types/std", + "itp-utils/std", + "log/std", + "litentry-primitives/std", +] diff --git a/bitacross-worker/core/direct-rpc-client/src/lib.rs b/bitacross-worker/core/direct-rpc-client/src/lib.rs new file mode 100644 index 0000000000..6de127f7df --- /dev/null +++ b/bitacross-worker/core/direct-rpc-client/src/lib.rs @@ -0,0 +1,262 @@ +// Copyright 2020-2023 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . + +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg(all(feature = "std", feature = "sgx"))] +compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the same time"); + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +extern crate sgx_tstd as std; + +// re-export module to properly feature gate sgx and regular std environment +#[cfg(all(not(feature = "std"), feature = "sgx"))] +pub mod sgx_reexport_prelude { + pub use rustls_sgx as rustls; + pub use tungstenite_sgx as tungstenite; + pub use url_sgx as url; + pub use webpki_sgx as webpki; +} + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +use crate::sgx_reexport_prelude::*; + +extern crate alloc; + +use alloc::format; + +use core::str::FromStr; + +use log::debug; + +use serde_json::from_str; + +use itp_rpc::{Id, RpcRequest, RpcResponse, RpcReturnValue}; + +use itp_utils::FromHexPrefixed; + +use std::{ + boxed::Box, + error::Error, + net::TcpStream, + string::String, + sync::{ + mpsc::{channel, Sender, SyncSender}, + Arc, + }, + time::Duration, + vec::Vec, +}; +use tungstenite::{client_tls_with_config, stream::MaybeTlsStream, Connector, Message, WebSocket}; +use url::Url; +use webpki::{DNSName, DNSNameRef}; + +pub type Response = (Id, RpcReturnValue); + +pub struct IgnoreCertVerifier {} + +impl rustls::ServerCertVerifier for IgnoreCertVerifier { + fn verify_server_cert( + &self, + _: &rustls::RootCertStore, + _: &[rustls::Certificate], + _: DNSNameRef<'_>, + _: &[u8], + ) -> Result { + log::warn!("Using NoCertVerifier"); + Ok(rustls::ServerCertVerified::assertion()) + } +} + +impl rustls::ClientCertVerifier for IgnoreCertVerifier { + fn client_auth_root_subjects( + &self, + _sni: Option<&DNSName>, + ) -> Option { + None + } + + fn verify_client_cert( + &self, + _presented_certs: &[rustls::Certificate], + _sni: Option<&DNSName>, + ) -> Result { + Ok(rustls::ClientCertVerified::assertion()) + } +} + +pub trait RpcClientFactory { + type Client: RpcClient; + fn create( + &self, + url: &str, + response_sink: SyncSender, + ) -> Result>; +} + +pub struct DirectRpcClientFactory {} + +impl RpcClientFactory for DirectRpcClientFactory { + type Client = DirectRpcClient; + + fn create( + &self, + url: &str, + response_sink: SyncSender, + ) -> Result> { + DirectRpcClient::new(url, response_sink) + } +} + +pub trait RpcClient { + fn send(&mut self, request: &RpcRequest) -> Result<(), Box>; +} + +pub struct DirectRpcClient { + request_sink: Sender, +} + +impl DirectRpcClient { + pub fn new(url: &str, response_sink: SyncSender) -> Result> { + let ws_server_url = + Url::from_str(url).map_err(|e| format!("Could not connect, reason: {:?}", e))?; + let mut config = rustls::ClientConfig::new(); + // we need to set this cert verifier or client will fail to connect with following error + // HandshakeError::Failure(Io(Custom { kind: InvalidData, error: WebPKIError(UnknownIssuer) })) + config.dangerous().set_certificate_verifier(Arc::new(IgnoreCertVerifier {})); + let connector = Connector::Rustls(Arc::new(config)); + let addrs = ws_server_url.socket_addrs(|| None).unwrap(); + let stream = TcpStream::connect(&*addrs) + .map_err(|e| format!("Could not connect to {:?}, reason: {:?}", &addrs, e))?; + + let (mut socket, _response) = + client_tls_with_config(ws_server_url, stream, None, Some(connector)) + .map_err(|e| format!("Could not open websocket connection: {:?}", e))?; + + let (request_sender, request_receiver) = channel(); + + //it fails to perform handshake in non_blocking mode so we are setting it up after the handshake is performed + Self::switch_to_non_blocking(&mut socket); + + std::thread::spawn(move || loop { + // let's flush all pending requests first + while let Ok(request) = request_receiver.try_recv() { + socket.write_message(Message::Text(request)).unwrap() + } + + if let Ok(message) = socket.read_message() { + if let Ok(Some(response)) = Self::handle_ws_message(message) { + if let Err(e) = response_sink.send(response) { + log::error!("Could not forward response, reason: {:?}", e) + }; + } + } + std::thread::sleep(Duration::from_millis(10)) + }); + + debug!("Connected to peer: {}", url); + + Ok(Self { request_sink: request_sender }) + } + + fn switch_to_non_blocking(socket: &mut WebSocket>) { + match socket.get_ref() { + MaybeTlsStream::Plain(stream) => { + stream.set_nonblocking(true).expect("set_nonblocking call failed"); + stream + .set_read_timeout(Some(Duration::from_millis(5))) + .expect("set_read_timeout call failed"); + }, + MaybeTlsStream::Rustls(stream) => { + stream.get_ref().set_nonblocking(true).expect("set_nonblocking call failed"); + stream + .get_ref() + .set_read_timeout(Some(Duration::from_millis(1))) + .expect("set_read_timeout call failed"); + }, + _ => {}, + } + } + + fn handle_ws_message(message: Message) -> Result, Box> { + match message { + Message::Text(text) => { + let rpc_response: RpcResponse = from_str(&text) + .map_err(|e| format!("Could not deserialize RpcResponse, reason: {:?}", e))?; + let return_value: RpcReturnValue = + RpcReturnValue::from_hex(&rpc_response.result) + .map_err(|e| format!("Could not deserialize value , reason: {:?}", e))?; + Ok(Some((rpc_response.id, return_value))) + }, + _ => { + log::warn!("Only text messages are supported"); + Ok(None) + }, + } + } +} + +#[derive(Clone)] +pub enum RequestParams { + Rsa(Vec), + Aes(Vec), +} + +impl RpcClient for DirectRpcClient { + fn send(&mut self, request: &RpcRequest) -> Result<(), Box> { + let request = serde_json::to_string(request) + .map_err(|e| format!("Could not parse RpcRequest {:?}", e))?; + self.request_sink + .send(request) + .map_err(|e| format!("Could not write message, reason: {:?}", e).into()) + } +} + +#[cfg(test)] +mod tests { + use crate::DirectRpcClient; + use itp_rpc::{Id, RpcResponse, RpcReturnValue}; + use itp_types::{DirectRequestStatus, TrustedOperationStatus, H256}; + use itp_utils::ToHexPrefixed; + use tungstenite::Message; + + #[test] + fn test_response_handling() { + let id = Id::Text( + "0x0000000000000000000000000000000000000000000000000000000000000000".to_owned(), + ); + let return_value: RpcReturnValue = RpcReturnValue::new( + vec![], + false, + DirectRequestStatus::TrustedOperationStatus( + TrustedOperationStatus::TopExecuted(vec![], true), + H256::random(), + ), + ); + let rpc_response: RpcResponse = RpcResponse { + jsonrpc: "2.0".to_owned(), + result: return_value.to_hex(), + id: id.clone(), + }; + let serialized_rpc_response = serde_json::to_string(&rpc_response).unwrap(); + let message = Message::text(serialized_rpc_response); + + let (result_id, result) = DirectRpcClient::handle_ws_message(message).unwrap().unwrap(); + + assert_eq!(id, result_id); + assert_eq!(return_value, result); + } +} diff --git a/bitacross-worker/core/direct-rpc-server/Cargo.toml b/bitacross-worker/core/direct-rpc-server/Cargo.toml new file mode 100644 index 0000000000..8b88b1f3d5 --- /dev/null +++ b/bitacross-worker/core/direct-rpc-server/Cargo.toml @@ -0,0 +1,55 @@ +[package] +name = "itc-direct-rpc-server" +version = "0.9.0" +authors = ['Trust Computing GmbH ', 'Integritee AG '] +edition = "2021" + +[dependencies] +# sgx dependencies +sgx_tstd = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git", optional = true, features = ["net", "thread"] } + +# no-std dependencies +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +log = { version = "0.4", default-features = false } +serde_json = { version = "1.0", default-features = false, features = ["alloc"] } +sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } + +# local +itc-tls-websocket-server = { path = "../tls-websocket-server", default-features = false } +itp-rpc = { path = "../../core-primitives/rpc", default-features = false } +itp-types = { default-features = false, path = "../../core-primitives/types" } +itp-utils = { default-features = false, path = "../../core-primitives/utils" } + +# sgx enabled external libraries +jsonrpc-core_sgx = { package = "jsonrpc-core", git = "https://github.com/scs/jsonrpc", branch = "no_std_v18", default-features = false, optional = true } +thiserror_sgx = { package = "thiserror", git = "https://github.com/mesalock-linux/thiserror-sgx", tag = "sgx_1.1.3", optional = true } + +# std compatible external libraries (make sure these versions match with the sgx-enabled ones above) +jsonrpc-core = { version = "18", optional = true } +thiserror = { version = "1.0", optional = true } + +[features] +default = ["std"] +std = [ + # no-std dependencies + "codec/std", + "log/std", + "serde_json/std", + "sp-runtime/std", + # integritee dependencies + "itp-types/std", + # local + "itc-tls-websocket-server/std", + "itp-rpc/std", + # optional ones + "jsonrpc-core", + "thiserror", +] +sgx = [ + "itc-tls-websocket-server/sgx", + "itp-rpc/sgx", + "jsonrpc-core_sgx", + "sgx_tstd", + "thiserror_sgx", +] +mocks = [] diff --git a/bitacross-worker/core/direct-rpc-server/src/builders/mod.rs b/bitacross-worker/core/direct-rpc-server/src/builders/mod.rs new file mode 100644 index 0000000000..ea028434c4 --- /dev/null +++ b/bitacross-worker/core/direct-rpc-server/src/builders/mod.rs @@ -0,0 +1,19 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 rpc_response_builder; +pub mod rpc_return_value_builder; diff --git a/bitacross-worker/core/direct-rpc-server/src/builders/rpc_response_builder.rs b/bitacross-worker/core/direct-rpc-server/src/builders/rpc_response_builder.rs new file mode 100644 index 0000000000..9cc85cf369 --- /dev/null +++ b/bitacross-worker/core/direct-rpc-server/src/builders/rpc_response_builder.rs @@ -0,0 +1,64 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::builders::rpc_return_value_builder::RpcReturnValueBuilder; +use itp_rpc::{Id, RpcResponse, RpcReturnValue}; +use itp_utils::ToHexPrefixed; + +/// builder pattern for RpcResponse +pub struct RpcResponseBuilder { + maybe_id: Option, + maybe_json_rpc: Option, + maybe_result: Option, +} + +impl RpcResponseBuilder { + #[allow(unused)] + pub fn new() -> Self { + RpcResponseBuilder { maybe_id: None, maybe_json_rpc: None, maybe_result: None } + } + + #[allow(unused)] + pub fn with_id(mut self, id: u32) -> Self { + self.maybe_id = Some(id); + self + } + + #[allow(unused)] + pub fn with_json_rpc(mut self, json_rpc: String) -> Self { + self.maybe_json_rpc = Some(json_rpc); + self + } + + #[allow(unused)] + pub fn with_result(mut self, result: RpcReturnValue) -> Self { + self.maybe_result = Some(result); + self + } + + #[allow(unused)] + pub fn build(self) -> RpcResponse { + let id = Id::Number(self.maybe_id.unwrap_or(1u32)); + let json_rpc = self.maybe_json_rpc.unwrap_or(String::from("json_rpc")); + let result = self + .maybe_result + .unwrap_or_else(|| RpcReturnValueBuilder::new().build()) + .to_hex(); + + RpcResponse { result, jsonrpc: json_rpc, id } + } +} diff --git a/bitacross-worker/core/direct-rpc-server/src/builders/rpc_return_value_builder.rs b/bitacross-worker/core/direct-rpc-server/src/builders/rpc_return_value_builder.rs new file mode 100644 index 0000000000..126d58e985 --- /dev/null +++ b/bitacross-worker/core/direct-rpc-server/src/builders/rpc_return_value_builder.rs @@ -0,0 +1,62 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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; +use itp_rpc::RpcReturnValue; +use itp_types::DirectRequestStatus; +use std::{string::String, vec::Vec}; + +/// Builder pattern for a RpcReturnValue +pub struct RpcReturnValueBuilder { + maybe_do_watch: Option, + maybe_status: Option, + maybe_value: Option>, +} + +impl RpcReturnValueBuilder { + #[allow(unused)] + pub fn new() -> Self { + RpcReturnValueBuilder { maybe_do_watch: None, maybe_status: None, maybe_value: None } + } + + #[allow(unused)] + pub fn with_do_watch(mut self, do_watch: bool) -> Self { + self.maybe_do_watch = Some(do_watch); + self + } + + #[allow(unused)] + pub fn with_status(mut self, status: DirectRequestStatus) -> Self { + self.maybe_status = Some(status); + self + } + + #[allow(unused)] + pub fn with_value(mut self, value: Vec) -> Self { + self.maybe_value = Some(value); + self + } + + #[allow(unused)] + pub fn build(self) -> RpcReturnValue { + let do_watch = self.maybe_do_watch.unwrap_or(false); + let status = self.maybe_status.unwrap_or(DirectRequestStatus::Ok); + let value = self.maybe_value.unwrap_or(String::from("value").encode()); + + RpcReturnValue { value, do_watch, status } + } +} diff --git a/bitacross-worker/core/direct-rpc-server/src/lib.rs b/bitacross-worker/core/direct-rpc-server/src/lib.rs new file mode 100644 index 0000000000..b05a30e67f --- /dev/null +++ b/bitacross-worker/core/direct-rpc-server/src/lib.rs @@ -0,0 +1,158 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ +#![cfg_attr(not(feature = "std"), no_std)] +#![cfg_attr(test, feature(assert_matches))] + +#[cfg(all(feature = "std", feature = "sgx"))] +compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the same time"); + +extern crate alloc; + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +extern crate sgx_tstd as std; + +// re-export module to properly feature gate sgx and regular std environment +#[cfg(all(not(feature = "std"), feature = "sgx"))] +pub mod sgx_reexport_prelude { + pub use jsonrpc_core_sgx as jsonrpc_core; + pub use thiserror_sgx as thiserror; +} + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +use crate::sgx_reexport_prelude::*; + +use crate::rpc_watch_extractor::RpcWatchExtractor; +use codec::{Encode, Error as CodecError}; +use itc_tls_websocket_server::error::WebSocketError; +use itp_rpc::RpcResponse; +use itp_types::{TrustedOperationStatus, H256}; +use serde_json::error::Error as SerdeJsonError; +use sp_runtime::traits; +use std::{boxed::Box, fmt::Debug, vec::Vec}; + +#[cfg(any(test, feature = "mocks"))] +pub mod mocks; + +#[cfg(test)] +mod builders; + +pub mod response_channel; +pub mod rpc_connection_registry; +pub mod rpc_responder; +pub mod rpc_watch_extractor; +pub mod rpc_ws_handler; + +/// General web-socket error type +#[derive(Debug, thiserror::Error)] +pub enum DirectRpcError { + #[error("Invalid connection hash")] + InvalidConnectionHash, + #[error("RPC serialization error: {0}")] + SerializationError(SerdeJsonError), + #[error("Web socket error: {0}")] + WebSocketError(#[from] WebSocketError), + #[error("Encoding error: {0}")] + EncodingError(CodecError), + #[error("Other error: {0}")] + Other(Box), + // Litentry + #[error("Hash conversion error")] + HashConversionError, +} + +pub type DirectRpcResult = Result; + +/// trait helper to mix-in all necessary traits for a hash +pub trait RpcHash: std::hash::Hash + traits::Member + Encode { + fn maybe_h256(&self) -> Option; +} +impl RpcHash for T { + fn maybe_h256(&self) -> Option { + let enc = self.encode(); + if enc.len() == 32 { + let mut inner = [0u8; 32]; + inner.copy_from_slice(&enc); + Some(inner.into()) + } else { + None + } + } +} + +pub type ForceWait = bool; + +/// Registry for RPC connections (i.e. connections that are kept alive to send updates). +pub trait RpcConnectionRegistry: Send + Sync { + type Hash: RpcHash; + type Connection: Copy + Debug; + + fn store( + &self, + hash: Self::Hash, + connection: Self::Connection, + rpc_response: RpcResponse, + force_wait: ForceWait, + ); + + fn withdraw(&self, hash: &Self::Hash) -> Option<(Self::Connection, RpcResponse, ForceWait)>; + + fn is_force_wait(&self, hash: &Self::Hash) -> bool; +} + +/// Sends an RPC response back to the client. +pub trait SendRpcResponse: Send + Sync { + type Hash: RpcHash; + + fn update_status_event( + &self, + hash: Self::Hash, + status_update: TrustedOperationStatus, + ) -> DirectRpcResult<()>; + + fn send_state(&self, hash: Self::Hash, state_encoded: Vec) -> DirectRpcResult<()>; + + fn update_force_wait(&self, hash: Self::Hash, force_wait: bool) -> DirectRpcResult<()>; + + // Litentry: update the `value` field in the returning structure and connection force_wait flag + fn update_connection_state( + &self, + hash: Self::Hash, + encoded_value: Vec, + force_wait: bool, + ) -> DirectRpcResult<()>; + + // Litentry: swap the old hash with the new one in rpc connection registry + fn swap_hash(&self, old_hash: Self::Hash, new_hash: Self::Hash) -> DirectRpcResult<()>; + + fn is_force_wait(&self, hash: Self::Hash) -> bool; +} + +/// Determines if a given connection must be watched (i.e. kept alive), +/// based on the information in the RpcResponse. +pub trait DetermineWatch: Send + Sync { + type Hash: RpcHash; + + fn must_be_watched(&self, rpc_response: &RpcResponse) -> DirectRpcResult>; +} + +/// Convenience method to create a do_watch extractor. +pub fn create_determine_watch() -> RpcWatchExtractor +where + Hash: RpcHash, +{ + RpcWatchExtractor::::new() +} diff --git a/bitacross-worker/core/direct-rpc-server/src/mocks/determine_watch_mock.rs b/bitacross-worker/core/direct-rpc-server/src/mocks/determine_watch_mock.rs new file mode 100644 index 0000000000..c01730390d --- /dev/null +++ b/bitacross-worker/core/direct-rpc-server/src/mocks/determine_watch_mock.rs @@ -0,0 +1,52 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{DetermineWatch, DirectRpcResult, RpcHash}; +use itp_rpc::RpcResponse; + +pub struct DetermineWatchMock +where + Hash: RpcHash, +{ + watch_next: Option, +} + +impl DetermineWatchMock +where + Hash: RpcHash, +{ + #[allow(unused)] + pub fn do_watch(hash: Hash) -> Self { + DetermineWatchMock { watch_next: Some(hash) } + } + + #[allow(unused)] + pub fn no_watch() -> Self { + DetermineWatchMock { watch_next: None } + } +} + +impl DetermineWatch for DetermineWatchMock +where + Hash: RpcHash, +{ + type Hash = Hash; + + fn must_be_watched(&self, _rpc_response: &RpcResponse) -> DirectRpcResult> { + Ok(self.watch_next.clone()) + } +} diff --git a/bitacross-worker/core/direct-rpc-server/src/mocks/mod.rs b/bitacross-worker/core/direct-rpc-server/src/mocks/mod.rs new file mode 100644 index 0000000000..011b4d9905 --- /dev/null +++ b/bitacross-worker/core/direct-rpc-server/src/mocks/mod.rs @@ -0,0 +1,20 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 determine_watch_mock; +pub mod response_channel_mock; +pub mod send_rpc_response_mock; diff --git a/bitacross-worker/core/direct-rpc-server/src/mocks/response_channel_mock.rs b/bitacross-worker/core/direct-rpc-server/src/mocks/response_channel_mock.rs new file mode 100644 index 0000000000..6a612d6766 --- /dev/null +++ b/bitacross-worker/core/direct-rpc-server/src/mocks/response_channel_mock.rs @@ -0,0 +1,55 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 = "sgx")] +use std::sync::SgxRwLock as RwLock; + +#[cfg(feature = "std")] +use std::sync::RwLock; + +use crate::{response_channel::ResponseChannel, DirectRpcError}; +use std::vec::Vec; + +#[derive(Default)] +pub struct ResponseChannelMock +where + Token: Copy + Send + Sync, +{ + sent_messages: RwLock>, +} + +impl ResponseChannelMock +where + Token: Copy + Send + Sync, +{ + pub fn number_of_updates(&self) -> usize { + self.sent_messages.read().unwrap().len() + } +} + +impl ResponseChannel for ResponseChannelMock +where + Token: Copy + Send + Sync, +{ + type Error = DirectRpcError; + + fn respond(&self, token: Token, message: String) -> Result<(), Self::Error> { + let mut messages_lock = self.sent_messages.write().unwrap(); + messages_lock.push((token, message)); + Ok(()) + } +} diff --git a/bitacross-worker/core/direct-rpc-server/src/mocks/send_rpc_response_mock.rs b/bitacross-worker/core/direct-rpc-server/src/mocks/send_rpc_response_mock.rs new file mode 100644 index 0000000000..bad5021bec --- /dev/null +++ b/bitacross-worker/core/direct-rpc-server/src/mocks/send_rpc_response_mock.rs @@ -0,0 +1,74 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 = "sgx")] +use std::sync::SgxRwLock as RwLock; + +#[cfg(feature = "std")] +use std::sync::RwLock; + +use crate::{DirectRpcResult, RpcHash, SendRpcResponse}; +use itp_types::TrustedOperationStatus; +use std::vec::Vec; + +/// Send RPC response mock. +#[derive(Default)] +pub struct SendRpcResponseMock { + pub sent_states: RwLock)>>, +} + +impl SendRpcResponse for SendRpcResponseMock +where + HashType: RpcHash, +{ + type Hash = HashType; + + fn update_status_event( + &self, + _hash: Self::Hash, + _status_update: TrustedOperationStatus, + ) -> DirectRpcResult<()> { + unimplemented!() + } + + fn send_state(&self, hash: Self::Hash, state_encoded: Vec) -> DirectRpcResult<()> { + let mut states_lock = self.sent_states.write().unwrap(); + states_lock.push((hash, state_encoded)); + Ok(()) + } + + fn update_force_wait(&self, _hash: Self::Hash, _force_wait: bool) -> DirectRpcResult<()> { + Ok(()) + } + + fn update_connection_state( + &self, + _hash: Self::Hash, + _encoded_value: Vec, + _force_wait: bool, + ) -> DirectRpcResult<()> { + Ok(()) + } + + fn swap_hash(&self, _old_hash: Self::Hash, _new_hash: Self::Hash) -> DirectRpcResult<()> { + Ok(()) + } + + fn is_force_wait(&self, _hash: Self::Hash) -> bool { + false + } +} diff --git a/bitacross-worker/core/direct-rpc-server/src/response_channel.rs b/bitacross-worker/core/direct-rpc-server/src/response_channel.rs new file mode 100644 index 0000000000..b1fe6a3fea --- /dev/null +++ b/bitacross-worker/core/direct-rpc-server/src/response_channel.rs @@ -0,0 +1,26 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::DirectRpcError; +use std::string::String; + +/// Response / status update channel for an RPC call. +pub trait ResponseChannel: Send + Sync { + type Error: Into; + + fn respond(&self, token: Token, message: String) -> Result<(), Self::Error>; +} diff --git a/bitacross-worker/core/direct-rpc-server/src/rpc_connection_registry.rs b/bitacross-worker/core/direct-rpc-server/src/rpc_connection_registry.rs new file mode 100644 index 0000000000..2c83986fe5 --- /dev/null +++ b/bitacross-worker/core/direct-rpc-server/src/rpc_connection_registry.rs @@ -0,0 +1,140 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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(all(not(feature = "std"), feature = "sgx"))] +use std::sync::SgxRwLock as RwLock; + +#[cfg(feature = "std")] +use std::sync::RwLock; + +use crate::{ForceWait, RpcConnectionRegistry, RpcHash}; +use itp_rpc::RpcResponse; +use std::{collections::HashMap, fmt::Debug}; + +type HashMapLock = RwLock>; + +pub struct ConnectionRegistry +where + Hash: RpcHash, + Token: Copy + Send + Sync + Debug, +{ + connection_map: + HashMapLock<::Hash, (Token, RpcResponse, ForceWait)>, +} + +impl ConnectionRegistry +where + Hash: RpcHash, + Token: Copy + Send + Sync + Debug, +{ + pub fn new() -> Self { + Self::default() + } + + #[cfg(test)] + pub fn is_empty(&self) -> bool { + self.connection_map.read().unwrap().is_empty() + } +} + +impl Default for ConnectionRegistry +where + Hash: RpcHash, + Token: Copy + Send + Sync + Debug, +{ + fn default() -> Self { + ConnectionRegistry { connection_map: RwLock::new(HashMap::default()) } + } +} + +impl RpcConnectionRegistry for ConnectionRegistry +where + Hash: RpcHash, + Token: Copy + Send + Sync + Debug, +{ + type Hash = Hash; + type Connection = Token; + + fn store( + &self, + hash: Self::Hash, + connection: Self::Connection, + rpc_response: RpcResponse, + force_wait: ForceWait, + ) { + let mut map = self.connection_map.write().expect("Lock poisoning"); + map.insert(hash, (connection, rpc_response, force_wait)); + } + + fn withdraw(&self, hash: &Self::Hash) -> Option<(Self::Connection, RpcResponse, ForceWait)> { + let mut map = self.connection_map.write().expect("Lock poisoning"); + map.remove(hash) + } + + fn is_force_wait(&self, hash: &Self::Hash) -> bool { + if let Some(v) = self.connection_map.read().unwrap().get(hash) { + v.2 + } else { + false + } + } +} + +#[cfg(test)] +pub mod tests { + use super::*; + use itp_rpc::Id; + + type TestRegistry = ConnectionRegistry; + + #[test] + pub fn adding_element_with_same_hash_overwrite() { + let registry = TestRegistry::new(); + + let hash = "first".to_string(); + + registry.store(hash.clone(), 1, dummy_rpc_response(), false); + registry.store(hash.clone(), 2, dummy_rpc_response(), false); + + let connection_token = registry.withdraw(&hash).unwrap().0; + assert_eq!(2, connection_token); + } + + #[test] + pub fn withdrawing_from_empty_registry_returns_none() { + let registry = TestRegistry::new(); + + assert!(registry.withdraw(&"hash".to_string()).is_none()); + } + + #[test] + pub fn withdrawing_only_element_clears_registry() { + let registry = TestRegistry::new(); + let hash = "first".to_string(); + + registry.store(hash.clone(), 1, dummy_rpc_response(), false); + + let connection = registry.withdraw(&hash); + + assert!(connection.is_some()); + assert!(registry.is_empty()); + } + + fn dummy_rpc_response() -> RpcResponse { + RpcResponse { jsonrpc: String::new(), result: Default::default(), id: Id::Number(1u32) } + } +} diff --git a/bitacross-worker/core/direct-rpc-server/src/rpc_responder.rs b/bitacross-worker/core/direct-rpc-server/src/rpc_responder.rs new file mode 100644 index 0000000000..2b2e41c5ef --- /dev/null +++ b/bitacross-worker/core/direct-rpc-server/src/rpc_responder.rs @@ -0,0 +1,363 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{ + response_channel::ResponseChannel, DirectRpcError, DirectRpcResult, RpcConnectionRegistry, + RpcHash, SendRpcResponse, +}; +use alloc::format; +use itp_rpc::{RpcResponse, RpcReturnValue}; +use itp_types::{DirectRequestStatus, TrustedOperationStatus}; +use itp_utils::{FromHexPrefixed, ToHexPrefixed}; +use log::*; +use std::{sync::Arc, vec::Vec}; + +pub struct RpcResponder +where + Registry: RpcConnectionRegistry, + Hash: RpcHash, + ResponseChannelType: ResponseChannel, +{ + connection_registry: Arc, + response_channel: Arc, +} + +impl RpcResponder +where + Registry: RpcConnectionRegistry, + Hash: RpcHash, + ResponseChannelType: ResponseChannel, +{ + pub fn new( + connection_registry: Arc, + web_socket_responder: Arc, + ) -> Self { + RpcResponder { connection_registry, response_channel: web_socket_responder } + } + + fn encode_and_send_response( + &self, + connection: Registry::Connection, + rpc_response: &RpcResponse, + ) -> DirectRpcResult<()> { + let string_response = + serde_json::to_string(&rpc_response).map_err(DirectRpcError::SerializationError)?; + + self.response_channel.respond(connection, string_response).map_err(|e| e.into()) + } +} + +impl SendRpcResponse + for RpcResponder +where + Registry: RpcConnectionRegistry, + Hash: RpcHash, + ResponseChannelType: ResponseChannel, +{ + type Hash = Hash; + + fn update_status_event( + &self, + hash: Hash, + status_update: TrustedOperationStatus, + ) -> DirectRpcResult<()> { + debug!("updating status event, hash: {}, status: {:?}", hash.to_hex(), status_update); + + // withdraw removes it from the registry + let (connection_token, rpc_response, force_wait) = self + .connection_registry + .withdraw(&hash) + .ok_or(DirectRpcError::InvalidConnectionHash)?; + + let mut new_response = rpc_response.clone(); + + let mut result = RpcReturnValue::from_hex(&rpc_response.result) + .map_err(|e| DirectRpcError::Other(format!("{:?}", e).into()))?; + + // Litentry: + // connections are per trusted call, but if we expect trusted call to have a side effect of creating another trusted call (callback) + // we force connection to wait for potential TOP execution + let do_watch = continue_watching(&status_update) || force_wait; + + // update response + result.do_watch = do_watch; + result.status = DirectRequestStatus::TrustedOperationStatus( + status_update, + hash.maybe_h256().ok_or(DirectRpcError::HashConversionError)?, + ); + new_response.result = result.to_hex(); + + self.encode_and_send_response(connection_token, &new_response)?; + + if do_watch { + self.connection_registry.store(hash, connection_token, new_response, force_wait); + } + + debug!("updating status event successful"); + Ok(()) + } + + // TODO(Litentry): it seems that this fn is only used in tests? + fn send_state(&self, hash: Hash, state_encoded: Vec) -> DirectRpcResult<()> { + debug!("sending state"); + + // withdraw removes it from the registry + let (connection_token, mut response, _force_wait) = self + .connection_registry + .withdraw(&hash) + .ok_or(DirectRpcError::InvalidConnectionHash)?; + + // create return value + // TODO: Signature? + let submitted = DirectRequestStatus::TrustedOperationStatus( + TrustedOperationStatus::Submitted, + hash.maybe_h256().ok_or(DirectRpcError::HashConversionError)?, + ); + let result = RpcReturnValue::new(state_encoded, false, submitted); + + // update response + response.result = result.to_hex(); + + self.encode_and_send_response(connection_token, &response)?; + + debug!("sending state successful"); + Ok(()) + } + + fn update_force_wait(&self, hash: Self::Hash, force_wait: bool) -> DirectRpcResult<()> { + let (connection_token, rpc_response, _) = self + .connection_registry + .withdraw(&hash) + .ok_or(DirectRpcError::InvalidConnectionHash)?; + self.connection_registry.store(hash, connection_token, rpc_response, force_wait); + + Ok(()) + } + + fn is_force_wait(&self, hash: Self::Hash) -> bool { + self.connection_registry.is_force_wait(&hash) + } + + fn update_connection_state( + &self, + hash: Self::Hash, + encoded_value: Vec, + force_wait: bool, + ) -> DirectRpcResult<()> { + info!( + "updating connection state for hash {:?}: encoded_value {:?}, force_wait: {:?}", + hash, encoded_value, force_wait + ); + + // withdraw removes it from the registry + let (connection_token, rpc_response, _) = self + .connection_registry + .withdraw(&hash) + .ok_or(DirectRpcError::InvalidConnectionHash)?; + + let mut new_response = rpc_response.clone(); + + let mut result = RpcReturnValue::from_hex(&rpc_response.result) + .map_err(|e| DirectRpcError::Other(format!("{:?}", e).into()))?; + + result.value = encoded_value; + new_response.result = result.to_hex(); + self.connection_registry.store(hash, connection_token, new_response, force_wait); + + debug!("set response value OK"); + Ok(()) + } + + fn swap_hash(&self, old_hash: Self::Hash, new_hash: Self::Hash) -> DirectRpcResult<()> { + debug!("swap hash, old: {:?}, new: {:?}", old_hash, new_hash); + + let (connection_token, rpc_response, force_wait) = self + .connection_registry + .withdraw(&old_hash) + .ok_or(DirectRpcError::InvalidConnectionHash)?; + + // leave `rpc_response` untouched - it should be overwritten later anyway and keep on force waiting + self.connection_registry + .store(new_hash, connection_token, rpc_response, force_wait); + debug!("swap hash OK"); + Ok(()) + } +} + +fn continue_watching(status: &TrustedOperationStatus) -> bool { + !matches!( + status, + TrustedOperationStatus::Invalid + | TrustedOperationStatus::InSidechainBlock(_) + | TrustedOperationStatus::Finalized + | TrustedOperationStatus::Usurped + ) +} + +#[cfg(test)] +pub mod tests { + + use super::*; + use crate::{ + builders::rpc_response_builder::RpcResponseBuilder, + mocks::response_channel_mock::ResponseChannelMock, + rpc_connection_registry::ConnectionRegistry, + }; + use codec::Encode; + use itp_types::H256; + use std::assert_matches::assert_matches; + + type TestConnectionToken = u64; + type TestResponseChannel = ResponseChannelMock; + type TestConnectionRegistry = ConnectionRegistry; + + #[test] + fn given_empty_registry_when_updating_status_event_then_return_error() { + let connection_registry = Arc::new(TestConnectionRegistry::new()); + let websocket_responder = Arc::new(TestResponseChannel::default()); + let rpc_responder = RpcResponder::new(connection_registry, websocket_responder); + + assert_matches!( + rpc_responder.update_status_event([1u8; 32].into(), TrustedOperationStatus::Broadcast), + Err(DirectRpcError::InvalidConnectionHash) + ); + } + + #[test] + fn given_empty_registry_when_sending_state_then_return_error() { + let connection_registry = Arc::new(TestConnectionRegistry::new()); + let websocket_responder = Arc::new(TestResponseChannel::default()); + let rpc_responder = RpcResponder::new(connection_registry, websocket_responder); + + assert_matches!( + rpc_responder.send_state([1u8; 32].into(), vec![1u8, 2u8]), + Err(DirectRpcError::InvalidConnectionHash) + ); + } + + #[test] + fn updating_status_event_with_finalized_state_removes_connection() { + let connection_hash = H256::random(); + let connection_registry = create_registry_with_single_connection(connection_hash.clone()); + + let websocket_responder = Arc::new(TestResponseChannel::default()); + let rpc_responder = + RpcResponder::new(connection_registry.clone(), websocket_responder.clone()); + + let result = rpc_responder + .update_status_event(connection_hash.clone(), TrustedOperationStatus::Finalized); + + assert!(result.is_ok()); + + verify_closed_connection(&connection_hash, connection_registry); + assert_eq!(1, websocket_responder.number_of_updates()); + } + + #[test] + fn updating_status_event_with_finalized_state_doesnt_remove_connection_if_force_watch_set() { + let connection_hash = H256::random(); + let connection_registry = create_registry_with_single_connection(connection_hash.clone()); + + let websocket_responder = Arc::new(TestResponseChannel::default()); + let rpc_responder = + RpcResponder::new(connection_registry.clone(), websocket_responder.clone()); + rpc_responder + .update_connection_state(connection_hash.clone(), vec![], true) + .unwrap(); + + let result = rpc_responder + .update_status_event(connection_hash.clone(), TrustedOperationStatus::Finalized); + + assert!(result.is_ok()); + + verify_open_connection(&connection_hash, connection_registry); + assert_eq!(1, websocket_responder.number_of_updates()); + } + + #[test] + fn updating_status_event_with_ready_state_keeps_connection_and_sends_update() { + let connection_hash = H256::random(); + let connection_registry: Arc> = + create_registry_with_single_connection(connection_hash.clone()); + + let websocket_responder = Arc::new(TestResponseChannel::default()); + let rpc_responder = + RpcResponder::new(connection_registry.clone(), websocket_responder.clone()); + + let first_result = rpc_responder + .update_status_event(connection_hash.clone(), TrustedOperationStatus::Ready); + + let second_result = rpc_responder + .update_status_event(connection_hash.clone(), TrustedOperationStatus::Submitted); + + assert!(first_result.is_ok()); + assert!(second_result.is_ok()); + + verify_open_connection(&connection_hash, connection_registry); + assert_eq!(2, websocket_responder.number_of_updates()); + } + + #[test] + fn sending_state_successfully_sends_update_and_removes_connection_token() { + let connection_hash = H256::random(); + let connection_registry = create_registry_with_single_connection(connection_hash.clone()); + + let websocket_responder = Arc::new(TestResponseChannel::default()); + let rpc_responder = + RpcResponder::new(connection_registry.clone(), websocket_responder.clone()); + + let result = rpc_responder.send_state(connection_hash.clone(), "new_state".encode()); + assert!(result.is_ok()); + + verify_closed_connection(&connection_hash, connection_registry); + assert_eq!(1, websocket_responder.number_of_updates()); + } + + #[test] + fn test_continue_watching() { + assert!(!continue_watching(&TrustedOperationStatus::Invalid)); + assert!(!continue_watching(&TrustedOperationStatus::Usurped)); + assert!(continue_watching(&TrustedOperationStatus::Future)); + assert!(continue_watching(&TrustedOperationStatus::Broadcast)); + assert!(continue_watching(&TrustedOperationStatus::Dropped)); + } + + fn verify_open_connection( + connection_hash: &H256, + connection_registry: Arc, + ) { + let maybe_connection = connection_registry.withdraw(&connection_hash); + assert!(maybe_connection.is_some()); + } + + fn verify_closed_connection( + connection_hash: &H256, + connection_registry: Arc, + ) { + assert!(connection_registry.withdraw(&connection_hash).is_none()); + } + + fn create_registry_with_single_connection( + connection_hash: H256, + ) -> Arc { + let connection_registry = TestConnectionRegistry::new(); + let rpc_response = RpcResponseBuilder::new().with_id(2).build(); + + connection_registry.store(connection_hash.clone(), 1, rpc_response, false); + Arc::new(connection_registry) + } +} diff --git a/bitacross-worker/core/direct-rpc-server/src/rpc_watch_extractor.rs b/bitacross-worker/core/direct-rpc-server/src/rpc_watch_extractor.rs new file mode 100644 index 0000000000..141ff21b54 --- /dev/null +++ b/bitacross-worker/core/direct-rpc-server/src/rpc_watch_extractor.rs @@ -0,0 +1,131 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{DetermineWatch, DirectRpcError, DirectRpcResult, RpcHash}; +use alloc::format; +use codec::Decode; +use itp_rpc::{RpcResponse, RpcReturnValue}; +use itp_types::DirectRequestStatus; +use itp_utils::FromHexPrefixed; +use std::marker::PhantomData; + +pub struct RpcWatchExtractor +where + Hash: RpcHash, +{ + phantom_data: PhantomData, +} + +impl RpcWatchExtractor +where + Hash: RpcHash, +{ + pub fn new() -> Self { + Self::default() + } +} + +impl Default for RpcWatchExtractor +where + Hash: RpcHash, +{ + fn default() -> Self { + RpcWatchExtractor { phantom_data: PhantomData } + } +} + +impl DetermineWatch for RpcWatchExtractor +where + Hash: RpcHash + Decode, +{ + type Hash = Hash; + + fn must_be_watched(&self, rpc_response: &RpcResponse) -> DirectRpcResult> { + let rpc_return_value = RpcReturnValue::from_hex(&rpc_response.result) + .map_err(|e| DirectRpcError::Other(format!("{:?}", e).into()))?; + + if !rpc_return_value.do_watch { + return Ok(None) + } + + match rpc_return_value.status { + DirectRequestStatus::TrustedOperationStatus(_, top_hash) => + Self::Hash::decode::<_>(&mut top_hash.as_ref()) + .map(Some) + .map_err(DirectRpcError::EncodingError), + _ => Ok(None), + } + } +} + +#[cfg(test)] +pub mod tests { + use super::*; + use crate::builders::{ + rpc_response_builder::RpcResponseBuilder, rpc_return_value_builder::RpcReturnValueBuilder, + }; + use codec::Encode; + use itp_rpc::Id; + use itp_types::{TrustedOperationStatus, H256}; + + #[test] + fn invalid_rpc_response_returns_error() { + let watch_extractor = RpcWatchExtractor::::new(); + let rpc_response = RpcResponse { + id: Id::Number(1u32), + jsonrpc: String::from("json"), + result: "hello".to_string(), + }; + + assert!(watch_extractor.must_be_watched(&rpc_response).is_err()); + } + + #[test] + fn rpc_response_without_watch_flag_must_not_be_watched() { + let watch_extractor = RpcWatchExtractor::::new(); + let rpc_result = RpcReturnValueBuilder::new() + .with_do_watch(false) + .with_status(DirectRequestStatus::TrustedOperationStatus( + TrustedOperationStatus::Ready, + Default::default(), + )) + .build(); + let rpc_response = RpcResponseBuilder::new().with_result(rpc_result).build(); + + let do_watch = watch_extractor.must_be_watched(&rpc_response).unwrap(); + + assert_eq!(None, do_watch); + } + + #[test] + fn rpc_response_with_watch_flag_must_be_watched() { + let hash = H256::random(); + let watch_extractor = RpcWatchExtractor::::new(); + let rpc_return_value = RpcReturnValueBuilder::new() + .with_do_watch(true) + .with_status(DirectRequestStatus::TrustedOperationStatus( + TrustedOperationStatus::Ready, + hash, + )) + .build(); + let rpc_response = RpcResponseBuilder::new().with_result(rpc_return_value).build(); + + let do_watch = watch_extractor.must_be_watched(&rpc_response).unwrap(); + + assert_eq!(Some(hash), do_watch); + } +} diff --git a/bitacross-worker/core/direct-rpc-server/src/rpc_ws_handler.rs b/bitacross-worker/core/direct-rpc-server/src/rpc_ws_handler.rs new file mode 100644 index 0000000000..fce836591e --- /dev/null +++ b/bitacross-worker/core/direct-rpc-server/src/rpc_ws_handler.rs @@ -0,0 +1,226 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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(all(not(feature = "std"), feature = "sgx"))] +use crate::sgx_reexport_prelude::*; + +use crate::{DetermineWatch, RpcConnectionRegistry, RpcHash}; +use itc_tls_websocket_server::{error::WebSocketResult, ConnectionToken, WebSocketMessageHandler}; +use jsonrpc_core::IoHandler; +use log::*; +use std::{string::String, sync::Arc}; + +pub struct RpcWsHandler +where + Watcher: DetermineWatch, + Registry: RpcConnectionRegistry, + Hash: RpcHash, +{ + rpc_io_handler: IoHandler, + connection_watcher: Arc, + connection_registry: Arc, +} + +impl RpcWsHandler +where + Watcher: DetermineWatch, + Registry: RpcConnectionRegistry, + Hash: RpcHash, +{ + pub fn new( + rpc_io_handler: IoHandler, + connection_watcher: Arc, + connection_registry: Arc, + ) -> Self { + RpcWsHandler { rpc_io_handler, connection_watcher, connection_registry } + } +} + +impl WebSocketMessageHandler for RpcWsHandler +where + Watcher: DetermineWatch, + Registry: RpcConnectionRegistry, + Registry::Connection: From, + Hash: RpcHash, +{ + fn handle_message( + &self, + connection_token: ConnectionToken, + message: String, + ) -> WebSocketResult> { + let maybe_rpc_response = self.rpc_io_handler.handle_request_sync(message.as_str()); + + debug!("RPC response string: {:?}", maybe_rpc_response); + + if let Ok(rpc_response) = + serde_json::from_str(maybe_rpc_response.clone().unwrap_or_default().as_str()) + { + if let Ok(Some(connection_hash)) = + self.connection_watcher.must_be_watched(&rpc_response) + { + self.connection_registry.store( + connection_hash, + connection_token.into(), + rpc_response, + false, + ); + } + } + + Ok(maybe_rpc_response) + } +} + +#[cfg(test)] +pub mod tests { + + use super::*; + use crate::{ + mocks::determine_watch_mock::DetermineWatchMock, + rpc_connection_registry::ConnectionRegistry, + }; + use codec::Encode; + use itc_tls_websocket_server::ConnectionToken; + use itp_rpc::RpcReturnValue; + use itp_types::DirectRequestStatus; + use itp_utils::ToHexPrefixed; + use jsonrpc_core::Params; + use serde_json::json; + + type TestConnectionRegistry = ConnectionRegistry; + type TestConnectionWatcher = DetermineWatchMock; + type TestWsHandler = RpcWsHandler; + + const RPC_METHOD_NAME: &str = "test_call"; + + #[test] + fn valid_rpc_call_without_watch_runs_successfully() { + let io_handler = create_io_handler_with_method(RPC_METHOD_NAME); + + let (connection_token, message) = create_message_to_handle(RPC_METHOD_NAME); + + let (ws_handler, connection_registry) = create_ws_handler(io_handler, None); + + let handle_result = ws_handler.handle_message(connection_token, message); + + assert!(handle_result.is_ok()); + assert!(connection_registry.is_empty()); + } + + #[test] + fn valid_rpc_call_with_watch_runs_successfully_and_stores_connection() { + let io_handler = create_io_handler_with_method(RPC_METHOD_NAME); + + let connection_hash = String::from("connection_hash"); + let (connection_token, message) = create_message_to_handle(RPC_METHOD_NAME); + + let (ws_handler, connection_registry) = + create_ws_handler(io_handler, Some(connection_hash.clone())); + + let handle_result = ws_handler.handle_message(connection_token, message); + + assert!(handle_result.is_ok()); + assert!(connection_registry.withdraw(&connection_hash).is_some()); + } + + #[test] + fn when_rpc_returns_error_then_return_ok_but_status_is_set_to_error() { + let io_handler = create_io_handler_with_error(RPC_METHOD_NAME); + + let connection_hash = String::from("connection_hash"); + let (connection_token, message) = create_message_to_handle(RPC_METHOD_NAME); + + let (ws_handler, connection_registry) = + create_ws_handler(io_handler, Some(connection_hash.clone())); + + let handle_result = ws_handler.handle_message(connection_token, message); + + assert!(handle_result.is_ok()); + assert!(connection_registry.withdraw(&connection_hash).is_some()); + } + + #[test] + fn when_rpc_method_does_not_match_anything_return_json_error_message() { + let io_handler = create_io_handler_with_error(RPC_METHOD_NAME); + let (connection_token, message) = create_message_to_handle("not_a_valid_method"); + + let (ws_handler, connection_registry) = create_ws_handler(io_handler, None); + + let handle_result = ws_handler.handle_message(connection_token, message).unwrap().unwrap(); + + assert_eq!(handle_result, "{\"jsonrpc\":\"2.0\",\"error\":{\"code\":-32601,\"message\":\"Method not found\"},\"id\":1}"); + assert!(connection_registry.is_empty()); + } + + fn create_message_to_handle(method_name: &str) -> (ConnectionToken, String) { + let json_rpc_pre_method = r#"{"jsonrpc": "2.0", "method": ""#; + let json_rpc_post_method = r#"", "params": {}, "id": 1}"#; + + let json_string = format!("{}{}{}", json_rpc_pre_method, method_name, json_rpc_post_method); + debug!("JSON input: {}", json_string); + + (ConnectionToken(23), json_string) + } + + fn create_ws_handler( + io_handler: IoHandler, + watch_connection: Option, + ) -> (TestWsHandler, Arc) { + let watcher = match watch_connection { + Some(hash) => TestConnectionWatcher::do_watch(hash), + None => TestConnectionWatcher::no_watch(), + }; + + let connection_registry = Arc::new(TestConnectionRegistry::new()); + + ( + TestWsHandler::new(io_handler, Arc::new(watcher), connection_registry.clone()), + connection_registry, + ) + } + + fn create_io_handler_with_method(method_name: &str) -> IoHandler { + create_io_handler( + method_name, + RpcReturnValue { + do_watch: false, + value: String::from("value").encode(), + status: DirectRequestStatus::Ok, + }, + ) + } + + fn create_io_handler_with_error(method_name: &str) -> IoHandler { + create_io_handler( + method_name, + RpcReturnValue { + value: "error!".encode(), + do_watch: false, + status: DirectRequestStatus::Error, + }, + ) + } + + fn create_io_handler(method_name: &str, return_value: ReturnValue) -> IoHandler + where + ReturnValue: Encode + Send + Sync + 'static, + { + let mut io_handler = IoHandler::new(); + io_handler.add_sync_method(method_name, move |_: Params| Ok(json!(return_value.to_hex()))); + io_handler + } +} diff --git a/bitacross-worker/core/offchain-worker-executor/Cargo.toml b/bitacross-worker/core/offchain-worker-executor/Cargo.toml new file mode 100644 index 0000000000..24d1fd896a --- /dev/null +++ b/bitacross-worker/core/offchain-worker-executor/Cargo.toml @@ -0,0 +1,70 @@ +[package] +name = "itc-offchain-worker-executor" +version = "0.9.0" +authors = ['Trust Computing GmbH ', 'Integritee AG '] +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +# sgx dependencies +sgx_tstd = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git", optional = true } + +# sgx enabled external libraries +thiserror_sgx = { package = "thiserror", git = "https://github.com/mesalock-linux/thiserror-sgx", tag = "sgx_1.1.3", optional = true } + +# std compatible external libraries (make sure these versions match with the sgx-enabled ones above) +thiserror = { version = "1.0", optional = true } + +# local dependencies +itc-parentchain-light-client = { path = "../../core/parentchain/light-client", default-features = false } +itp-extrinsics-factory = { path = "../../core-primitives/extrinsics-factory", default-features = false } +itp-stf-executor = { path = "../../core-primitives/stf-executor", default-features = false } +itp-stf-interface = { path = "../../core-primitives/stf-interface", default-features = false } +itp-stf-primitives = { path = "../../core-primitives/stf-primitives", default-features = false } +itp-stf-state-handler = { path = "../../core-primitives/stf-state-handler", default-features = false } +itp-top-pool-author = { path = "../../core-primitives/top-pool-author", default-features = false } +itp-types = { path = "../../core-primitives/types", default-features = false } + +# Substrate dependencies +sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } + +# no-std compatible libraries +log = { version = "0.4", default-features = false } + +[dev-dependencies] +itp-stf-primitives = { path = "../../core-primitives/stf-primitives", default-features = false } +codec = { package = "parity-scale-codec", version = "3.0.0", features = ["derive"] } +itc-parentchain-light-client = { path = "../../core/parentchain/light-client", features = ["mocks"] } +itp-extrinsics-factory = { path = "../../core-primitives/extrinsics-factory", features = ["mocks"] } +itp-stf-executor = { path = "../../core-primitives/stf-executor", features = ["mocks"] } +itp-test = { path = "../../core-primitives/test" } +itp-top-pool-author = { path = "../../core-primitives/top-pool-author", features = ["mocks"] } +itp-stf-interface = { path = "../../core-primitives/stf-interface", features = ["mocks"] } +itp-sgx-externalities = { path = "../../core-primitives/substrate-sgx/externalities" } +sp-core = { default-features = false, features = ["full_crypto"], git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } + +[features] +default = ["std"] +std = [ + "itc-parentchain-light-client/std", + "itp-extrinsics-factory/std", + "itp-stf-executor/std", + "itp-stf-interface/std", + "itp-stf-primitives/std", + "itp-stf-state-handler/std", + "itp-top-pool-author/std", + "itp-types/std", + "sp-runtime/std", + "thiserror", +] +sgx = [ + "itc-parentchain-light-client/sgx", + "itp-extrinsics-factory/sgx", + "itp-stf-executor/sgx", + "itp-stf-state-handler/sgx", + "itp-top-pool-author/sgx", + "sgx_tstd", + "thiserror_sgx", +] diff --git a/bitacross-worker/core/offchain-worker-executor/src/error.rs b/bitacross-worker/core/offchain-worker-executor/src/error.rs new file mode 100644 index 0000000000..2c955d3e00 --- /dev/null +++ b/bitacross-worker/core/offchain-worker-executor/src/error.rs @@ -0,0 +1,40 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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(all(not(feature = "std"), feature = "sgx"))] +use crate::sgx_reexport_prelude::*; + +use std::boxed::Box; + +pub type Result = core::result::Result; + +/// General offchain-worker error type +#[derive(Debug, thiserror::Error)] +pub enum Error { + #[error("STF state handler error: {0}")] + StfStateHandler(#[from] itp_stf_state_handler::error::Error), + #[error("STF executor error: {0}")] + StfExecutor(#[from] itp_stf_executor::error::Error), + #[error("TOP pool author error: {0}")] + TopPoolAuthor(#[from] itp_top_pool_author::error::Error), + #[error("Light-client error: {0}")] + LightClient(#[from] itc_parentchain_light_client::error::Error), + #[error("Extrinsics factory error: {0}")] + ExtrinsicsFactory(#[from] itp_extrinsics_factory::error::Error), + #[error("{0}")] + Other(Box), +} diff --git a/bitacross-worker/core/offchain-worker-executor/src/executor.rs b/bitacross-worker/core/offchain-worker-executor/src/executor.rs new file mode 100644 index 0000000000..5cf3e778b8 --- /dev/null +++ b/bitacross-worker/core/offchain-worker-executor/src/executor.rs @@ -0,0 +1,373 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::error::Result; +use codec::{Decode, Encode}; +use core::fmt::Debug; +use itc_parentchain_light_client::{ + concurrent_access::ValidatorAccess, BlockNumberOps, ExtrinsicSender, LightClientState, + NumberFor, +}; +use itp_extrinsics_factory::CreateExtrinsics; +use itp_stf_executor::{traits::StateUpdateProposer, ExecutedOperation}; +use itp_stf_interface::system_pallet::SystemPalletEventInterface; +use itp_stf_primitives::{traits::TrustedCallVerification, types::TrustedOperationOrHash}; +use itp_stf_state_handler::{handle_state::HandleState, query_shard_state::QueryShardState}; +use itp_top_pool_author::traits::AuthorApi; +use itp_types::{parentchain::ParentchainCall, OpaqueCall, ShardIdentifier, H256}; +use log::*; +use sp_runtime::traits::Block; +use std::{marker::PhantomData, sync::Arc, time::Duration, vec::Vec}; + +/// Off-chain worker executor implementation. +/// +/// Executes calls found in the top-pool and immediately applies the corresponding state diffs. +/// - Sends confirmations for all executed calls (TODO) +/// - Sends extrinsics for any parentchain effects (such as unshield calls). +/// +/// The trigger to start executing calls is given when the parentchain block imported event is +/// signaled (event listener). +pub struct Executor< + ParentchainBlock, + TopPoolAuthor, + StfExecutor, + StateHandler, + ValidatorAccessor, + ExtrinsicsFactory, + Stf, + TCS, + G, +> { + top_pool_author: Arc, + stf_executor: Arc, + state_handler: Arc, + validator_accessor: Arc, + extrinsics_factory: Arc, + _phantom: PhantomData<(ParentchainBlock, Stf, TCS, G)>, +} + +impl< + ParentchainBlock, + TopPoolAuthor, + StfExecutor, + StateHandler, + ValidatorAccessor, + ExtrinsicsFactory, + Stf, + TCS, + G, + > + Executor< + ParentchainBlock, + TopPoolAuthor, + StfExecutor, + StateHandler, + ValidatorAccessor, + ExtrinsicsFactory, + Stf, + TCS, + G, + > where + ParentchainBlock: Block, + StfExecutor: StateUpdateProposer, + TopPoolAuthor: AuthorApi, + StateHandler: QueryShardState + HandleState, + ValidatorAccessor: ValidatorAccess + Send + Sync + 'static, + ExtrinsicsFactory: CreateExtrinsics, + NumberFor: BlockNumberOps, + Stf: SystemPalletEventInterface, + TCS: PartialEq + Encode + Decode + Debug + Clone + Send + Sync + TrustedCallVerification, + G: PartialEq + Encode + Decode + Debug + Clone + Send + Sync, +{ + pub fn new( + top_pool_author: Arc, + stf_executor: Arc, + state_handler: Arc, + validator_accessor: Arc, + extrinsics_factory: Arc, + ) -> Self { + Self { + top_pool_author, + stf_executor, + state_handler, + validator_accessor, + extrinsics_factory, + _phantom: Default::default(), + } + } + + pub fn execute(&self) -> Result<()> { + let max_duration = Duration::from_secs(5); + let latest_parentchain_header = self.get_latest_parentchain_header()?; + + let mut parentchain_effects: Vec = Vec::new(); + + let shards = self.state_handler.list_shards()?; + trace!("Executing calls on {} shard(s)", shards.len()); + + for shard in shards { + debug!( + "executing pending tops in top pool with status: {:?}", + self.top_pool_author.get_status(shard) + ); + let trusted_calls = self.top_pool_author.get_pending_trusted_calls(shard); + trace!("Executing {} trusted calls on shard {:?}", trusted_calls.len(), shard); + + let batch_execution_result = self.stf_executor.propose_state_update( + &trusted_calls, + &latest_parentchain_header, + &shard, + max_duration, + |mut state| { + Stf::reset_events(&mut state); + state + }, + )?; + + parentchain_effects + .append(&mut batch_execution_result.get_extrinsic_callbacks().clone()); + + let failed_operations = batch_execution_result.get_failed_operations(); + let successful_operations: Vec> = batch_execution_result + .get_executed_operation_hashes() + .into_iter() + .map(|h| { + ExecutedOperation::success( + h, + TrustedOperationOrHash::Hash(h), + Vec::new(), + Vec::new(), + false, + ) + }) + .collect(); + + // Remove all not successfully executed operations from the top pool. + self.remove_calls_from_pool(&shard, failed_operations); + + // Apply the state update + self.apply_state_update(&shard, batch_execution_result.state_after_execution)?; + + // Remove successful operations from pool + self.remove_calls_from_pool(&shard, successful_operations); + + // TODO: notify parentchain about executed operations? -> add to parentchain effects + } + + if !parentchain_effects.is_empty() { + self.send_parentchain_effects(parentchain_effects)?; + } + + Ok(()) + } + + fn get_latest_parentchain_header(&self) -> Result { + let header = self.validator_accessor.execute_on_validator(|v| { + let latest_parentchain_header = v.latest_finalized_header()?; + Ok(latest_parentchain_header) + })?; + Ok(header) + } + + fn apply_state_update( + &self, + shard: &ShardIdentifier, + updated_state: >::Externalities, + ) -> Result<()> { + self.state_handler.reset(updated_state, shard)?; + Ok(()) + } + + fn send_parentchain_effects(&self, parentchain_effects: Vec) -> Result<()> { + let integritee_calls: Vec = parentchain_effects + .iter() + .filter_map(|parentchain_call| parentchain_call.as_litentry()) + .collect(); + let target_a_calls: Vec = parentchain_effects + .iter() + .filter_map(|parentchain_call| parentchain_call.as_target_a()) + .collect(); + let target_b_calls: Vec = parentchain_effects + .iter() + .filter_map(|parentchain_call| parentchain_call.as_target_b()) + .collect(); + debug!( + "stf wants to send calls to parentchains: Integritee: {} TargetA: {} TargetB: {}", + integritee_calls.len(), + target_a_calls.len(), + target_b_calls.len() + ); + if !target_a_calls.is_empty() { + warn!("sending extrinsics to target A unimplemented") + }; + if !target_b_calls.is_empty() { + warn!("sending extrinsics to target B unimplemented") + }; + + let extrinsics = + self.extrinsics_factory.create_extrinsics(integritee_calls.as_slice(), None)?; + self.validator_accessor + .execute_mut_on_validator(|v| v.send_extrinsics(extrinsics))?; + Ok(()) + } + + fn remove_calls_from_pool( + &self, + shard: &ShardIdentifier, + executed_calls: Vec>, + ) -> Vec> { + let executed_calls_tuple: Vec<_> = executed_calls + .iter() + .map(|e| (e.trusted_operation_or_hash.clone(), e.is_success())) + .collect(); + let failed_to_remove_hashes = + self.top_pool_author.remove_calls_from_pool(*shard, executed_calls_tuple); + + let failed_executed_calls: Vec<_> = executed_calls + .into_iter() + .filter(|e| failed_to_remove_hashes.contains(&e.trusted_operation_or_hash)) + .collect(); + + failed_executed_calls + } +} + +#[cfg(test)] +mod tests { + + use super::*; + use codec::{Decode, Encode}; + use itc_parentchain_light_client::mocks::validator_access_mock::ValidatorAccessMock; + use itp_extrinsics_factory::mock::ExtrinsicsFactoryMock; + use itp_sgx_externalities::SgxExternalitiesTrait; + use itp_stf_executor::mocks::StfExecutorMock; + + use itp_test::mock::{ + handle_state_mock::HandleStateMock, + stf_mock::{GetterMock, TrustedCallSignedMock}, + }; + use itp_top_pool_author::mocks::AuthorApiMock; + use itp_types::{Block as ParentchainBlock, RsaRequest}; + + use itp_test::mock::stf_mock::mock_top_indirect_trusted_call_signed; + use std::boxed::Box; + + type TestStateHandler = HandleStateMock; + type TestStfInterface = SystemPalletEventInterfaceMock; + type State = ::StateT; + type TestTopPoolAuthor = AuthorApiMock; + type TestStfExecutor = StfExecutorMock; + type TestValidatorAccess = ValidatorAccessMock; + type TestExtrinsicsFactory = ExtrinsicsFactoryMock; + type TestExecutor = Executor< + ParentchainBlock, + TestTopPoolAuthor, + TestStfExecutor, + TestStateHandler, + TestValidatorAccess, + TestExtrinsicsFactory, + TestStfInterface, + TrustedCallSignedMock, + GetterMock, + >; + + const EVENT_COUNT_KEY: &[u8] = b"event_count"; + + struct SystemPalletEventInterfaceMock; + + impl SystemPalletEventInterface for SystemPalletEventInterfaceMock { + type EventRecord = String; + type EventIndex = u32; + type BlockNumber = u32; + type Hash = String; + + fn get_events(_state: &mut State) -> Vec> { + unimplemented!(); + } + + fn get_event_count(state: &mut State) -> Self::EventIndex { + let encoded_value = state.get(EVENT_COUNT_KEY).unwrap(); + Self::EventIndex::decode(&mut encoded_value.as_slice()).unwrap() + } + + fn get_event_topics( + _state: &mut State, + _topic: &Self::Hash, + ) -> Vec<(Self::BlockNumber, Self::EventIndex)> { + unimplemented!() + } + + fn reset_events(state: &mut State) { + state.insert(EVENT_COUNT_KEY.to_vec(), 0u32.encode()); + } + } + + #[test] + fn executing_tops_from_pool_works_and_empties_pool() { + let stf_executor = Arc::new(TestStfExecutor::new(State::default())); + let top_pool_author = Arc::new(TestTopPoolAuthor::default()); + top_pool_author + .submit_top(RsaRequest::new(shard(), mock_top_indirect_trusted_call_signed().encode())); + + assert_eq!(1, top_pool_author.pending_tops(shard()).unwrap().len()); + + let executor = create_executor(top_pool_author.clone(), stf_executor); + + assert!(executor.execute().is_ok()); + + assert_eq!(0, top_pool_author.pending_tops(shard()).unwrap().len()); + } + + #[test] + fn reset_events_is_called() { + let mut state = State::default(); + let event_count = 5; + state.insert(EVENT_COUNT_KEY.to_vec(), event_count.encode()); + + let stf_executor = Arc::new(TestStfExecutor::new(state)); + assert_eq!(TestStfInterface::get_event_count(&mut stf_executor.get_state()), event_count); + + let top_pool_author = Arc::new(TestTopPoolAuthor::default()); + + let executor = create_executor(top_pool_author, stf_executor.clone()); + + executor.execute().unwrap(); + + assert_eq!(TestStfInterface::get_event_count(&mut stf_executor.get_state()), 0); + } + + fn create_executor( + top_pool_author: Arc, + stf_executor: Arc, + ) -> TestExecutor { + let state_handler = Arc::new(TestStateHandler::from_shard(shard()).unwrap()); + let validator_access = Arc::new(TestValidatorAccess::default()); + let extrinsics_factory = Arc::new(TestExtrinsicsFactory::default()); + + TestExecutor::new( + top_pool_author, + stf_executor, + state_handler, + validator_access, + extrinsics_factory, + ) + } + + fn shard() -> ShardIdentifier { + ShardIdentifier::default() + } +} diff --git a/bitacross-worker/core/offchain-worker-executor/src/lib.rs b/bitacross-worker/core/offchain-worker-executor/src/lib.rs new file mode 100644 index 0000000000..d30a11ba0b --- /dev/null +++ b/bitacross-worker/core/offchain-worker-executor/src/lib.rs @@ -0,0 +1,33 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg(all(feature = "std", feature = "sgx"))] +compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the same time"); + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +extern crate sgx_tstd as std; + +// re-export module to properly feature gate sgx and regular std environment +#[cfg(all(not(feature = "std"), feature = "sgx"))] +pub mod sgx_reexport_prelude { + pub use thiserror_sgx as thiserror; +} + +pub mod error; +pub mod executor; diff --git a/bitacross-worker/core/parentchain/block-import-dispatcher/Cargo.toml b/bitacross-worker/core/parentchain/block-import-dispatcher/Cargo.toml new file mode 100644 index 0000000000..1625bd31b5 --- /dev/null +++ b/bitacross-worker/core/parentchain/block-import-dispatcher/Cargo.toml @@ -0,0 +1,50 @@ +[package] +name = "itc-parentchain-block-import-dispatcher" +version = "0.9.0" +authors = ['Trust Computing GmbH ', 'Integritee AG '] +edition = "2021" + +[dependencies] +# sgx dependencies +sgx_tstd = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git", optional = true } +sgx_types = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git" } + +# local dependencies +itc-parentchain-block-importer = { path = "../block-importer", default-features = false } +itp-import-queue = { path = "../../../core-primitives/import-queue", default-features = false } + +# sgx enabled external libraries +thiserror_sgx = { package = "thiserror", git = "https://github.com/mesalock-linux/thiserror-sgx", tag = "sgx_1.1.3", optional = true } + +# crates.io std-only compatible libraries (make sure these versions match with the sgx-enabled ones above) +thiserror = { version = "1.0", optional = true } + +# crates.io no-std compatible libraries +log = { version = "0.4", default-features = false } + +[dev-dependencies] +itc-parentchain-block-importer = { path = "../block-importer", features = ["mocks"] } + +[features] +default = ["std"] +std = [ + # local + "itc-parentchain-block-importer/std", + "itp-import-queue/std", + # no-std compatible libraries + "log/std", + # std-only compatible libraries + "thiserror", +] +sgx = [ + # sgx + "sgx_tstd", + # local + "itc-parentchain-block-importer/sgx", + "itp-import-queue/sgx", + # sgx enabled external libraries + "thiserror_sgx", +] + +# feature to export mock implementations, only to be used for dev-dependencies! +mocks = [] diff --git a/bitacross-worker/core/parentchain/block-import-dispatcher/src/error.rs b/bitacross-worker/core/parentchain/block-import-dispatcher/src/error.rs new file mode 100644 index 0000000000..b5d73ffe54 --- /dev/null +++ b/bitacross-worker/core/parentchain/block-import-dispatcher/src/error.rs @@ -0,0 +1,47 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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(all(not(feature = "std"), feature = "sgx"))] +use crate::sgx_reexport_prelude::*; + +use sgx_types::sgx_status_t; +use std::boxed::Box; + +pub type Result = core::result::Result; + +/// Parentchain block importer error. +#[derive(Debug, thiserror::Error)] +pub enum Error { + #[error("SGX error, status: {0}")] + Sgx(sgx_status_t), + #[error("Two Dispatcher types assigned. Please double check the initialization process.")] + CanNotAssignTwoDispatcher, + #[error("Even though there is no dispatcher assigned, the dispatch function is called.")] + NoDispatcherAssigned, + #[error("Block import queue error: {0}")] + ImportQueue(#[from] itp_import_queue::error::Error), + #[error("Block import error: {0}")] + BlockImport(#[from] itc_parentchain_block_importer::error::Error), + #[error(transparent)] + Other(#[from] Box), +} + +impl From for Error { + fn from(sgx_status: sgx_status_t) -> Self { + Self::Sgx(sgx_status) + } +} diff --git a/bitacross-worker/core/parentchain/block-import-dispatcher/src/immediate_dispatcher.rs b/bitacross-worker/core/parentchain/block-import-dispatcher/src/immediate_dispatcher.rs new file mode 100644 index 0000000000..a58383bf05 --- /dev/null +++ b/bitacross-worker/core/parentchain/block-import-dispatcher/src/immediate_dispatcher.rs @@ -0,0 +1,107 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{error::Result, DispatchBlockImport}; +use itc_parentchain_block_importer::ImportParentchainBlocks; +use log::*; +use std::{boxed::Box, vec::Vec}; + +/// Block import dispatcher that immediately imports the blocks, without any processing or queueing. +pub struct ImmediateDispatcher { + pub block_importer: BlockImporter, + import_event_observers: Vec>, +} + +impl ImmediateDispatcher { + pub fn new(block_importer: BlockImporter) -> Self { + ImmediateDispatcher { block_importer, import_event_observers: Vec::new() } + } + + pub fn with_observer(self, callback: F) -> Self + where + F: Fn() + Send + Sync + 'static, + { + let mut updated_observers = self.import_event_observers; + updated_observers.push(Box::new(callback)); + + Self { block_importer: self.block_importer, import_event_observers: updated_observers } + } +} + +impl DispatchBlockImport + for ImmediateDispatcher +where + BlockImporter: ImportParentchainBlocks, +{ + fn dispatch_import( + &self, + blocks: Vec, + events: Vec>, + _is_syncing: bool, + ) -> Result<()> { + // _is_syncing does not matter for the immediate dispatcher, behavoiur is the same. Immediate block import. + + debug!("Importing {} parentchain blocks", blocks.len()); + self.block_importer.import_parentchain_blocks(blocks, events)?; + debug!("Notifying {} observers of import", self.import_event_observers.len()); + self.import_event_observers.iter().for_each(|callback| callback()); + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use itc_parentchain_block_importer::block_importer_mock::ParentchainBlockImporterMock; + use std::{ + sync::{Arc, RwLock}, + vec, + }; + + type SignedBlockType = u32; + type TestBlockImporter = ParentchainBlockImporterMock; + type TestDispatcher = ImmediateDispatcher; + + #[derive(Default)] + struct NotificationCounter { + counter: RwLock, + } + + impl NotificationCounter { + fn increment(&self) { + *self.counter.write().unwrap() += 1; + } + + pub fn get_counter(&self) -> usize { + *self.counter.read().unwrap() + } + } + + #[test] + fn listeners_get_notified_upon_import() { + let block_importer = TestBlockImporter::default(); + let notification_counter = Arc::new(NotificationCounter::default()); + let counter_clone = notification_counter.clone(); + let dispatcher = TestDispatcher::new(block_importer).with_observer(move || { + counter_clone.increment(); + }); + + dispatcher.dispatch_import(vec![1u32, 2u32], vec![], false).unwrap(); + + assert_eq!(1, notification_counter.get_counter()); + } +} diff --git a/bitacross-worker/core/parentchain/block-import-dispatcher/src/lib.rs b/bitacross-worker/core/parentchain/block-import-dispatcher/src/lib.rs new file mode 100644 index 0000000000..2385075644 --- /dev/null +++ b/bitacross-worker/core/parentchain/block-import-dispatcher/src/lib.rs @@ -0,0 +1,125 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ +//! Dispatching of block imports. + +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg(all(feature = "std", feature = "sgx"))] +compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the same time"); + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +extern crate sgx_tstd as std; + +// re-export module to properly feature gate sgx and regular std environment +#[cfg(all(not(feature = "std"), feature = "sgx"))] +pub mod sgx_reexport_prelude { + pub use thiserror_sgx as thiserror; +} + +pub mod error; +pub mod immediate_dispatcher; +pub mod triggered_dispatcher; + +#[cfg(feature = "mocks")] +pub mod trigger_parentchain_block_import_mock; + +use error::{Error, Result}; +use std::{sync::Arc, vec::Vec}; + +/// Trait to dispatch blocks for import into the local light-client. +pub trait DispatchBlockImport { + /// Dispatch blocks to be imported. + /// + /// The blocks may be imported immediately, get queued, delayed or grouped. + fn dispatch_import( + &self, + blocks: Vec, + events: Vec>, + is_syncing: bool, + ) -> Result<()>; +} + +/// Wrapper for the actual dispatchers. Allows to define one global type for +/// both dispatchers without changing the global variable when switching +/// the dispatcher type. It also allows for empty dispatchers, for use cases that +/// do not need block syncing for a specific parentchain type. +pub enum BlockImportDispatcher { + TriggeredDispatcher(Arc), + ImmediateDispatcher(Arc), + EmptyDispatcher, +} + +impl + BlockImportDispatcher +{ + pub fn new_triggered_dispatcher(triggered_dispatcher: Arc) -> Self { + BlockImportDispatcher::TriggeredDispatcher(triggered_dispatcher) + } + + pub fn new_immediate_dispatcher(immediate_dispatcher: Arc) -> Self { + BlockImportDispatcher::ImmediateDispatcher(immediate_dispatcher) + } + + pub fn new_empty_dispatcher() -> Self { + BlockImportDispatcher::EmptyDispatcher + } + + pub fn triggered_dispatcher(&self) -> Option> { + match self { + BlockImportDispatcher::TriggeredDispatcher(triggered_dispatcher) => + Some(triggered_dispatcher.clone()), + _ => None, + } + } + + pub fn immediate_dispatcher(&self) -> Option> { + match self { + BlockImportDispatcher::ImmediateDispatcher(immediate_dispatcher) => + Some(immediate_dispatcher.clone()), + _ => None, + } + } +} + +impl DispatchBlockImport + for BlockImportDispatcher +where + TriggeredDispatcher: DispatchBlockImport, + ImmediateDispatcher: DispatchBlockImport, +{ + fn dispatch_import( + &self, + blocks: Vec, + events: Vec>, + is_syncing: bool, + ) -> Result<()> { + match self { + BlockImportDispatcher::TriggeredDispatcher(dispatcher) => { + log::trace!("TRIGGERED DISPATCHER MATCH"); + dispatcher.dispatch_import(blocks, events, is_syncing) + }, + BlockImportDispatcher::ImmediateDispatcher(dispatcher) => { + log::trace!("IMMEDIATE DISPATCHER MATCH"); + dispatcher.dispatch_import(blocks, events, is_syncing) + }, + BlockImportDispatcher::EmptyDispatcher => { + log::trace!("EMPTY DISPATCHER DISPATCHER MATCH"); + Err(Error::NoDispatcherAssigned) + }, + } + } +} diff --git a/bitacross-worker/core/parentchain/block-import-dispatcher/src/trigger_parentchain_block_import_mock.rs b/bitacross-worker/core/parentchain/block-import-dispatcher/src/trigger_parentchain_block_import_mock.rs new file mode 100644 index 0000000000..a4953a4fbb --- /dev/null +++ b/bitacross-worker/core/parentchain/block-import-dispatcher/src/trigger_parentchain_block_import_mock.rs @@ -0,0 +1,102 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 = "sgx")] +use std::sync::SgxRwLock as RwLock; + +#[cfg(feature = "std")] +use std::sync::RwLock; + +use crate::{error::Result, triggered_dispatcher::TriggerParentchainBlockImport}; + +/// Mock for `TriggerParentchainBlockImport`, to be used in unit tests. +/// +/// Allows setting the latest imported block, which is returned upon calling +/// the import methods. +pub struct TriggerParentchainBlockImportMock { + latest_imported: Option, + import_has_been_called: RwLock, +} + +impl TriggerParentchainBlockImportMock { + pub fn with_latest_imported(mut self, maybe_block: Option) -> Self { + self.latest_imported = maybe_block; + self + } + + pub fn has_import_been_called(&self) -> bool { + let import_flag = self.import_has_been_called.read().unwrap(); + *import_flag + } +} + +impl Default for TriggerParentchainBlockImportMock { + fn default() -> Self { + TriggerParentchainBlockImportMock { + latest_imported: None, + import_has_been_called: RwLock::new(false), + } + } +} + +impl TriggerParentchainBlockImport + for TriggerParentchainBlockImportMock +where + SignedBlockType: Clone, +{ + type SignedBlockType = SignedBlockType; + + fn import_all(&self) -> Result> { + let mut import_flag = self.import_has_been_called.write().unwrap(); + *import_flag = true; + Ok(self.latest_imported.clone()) + } + + fn import_all_but_latest(&self) -> Result<()> { + let mut import_flag = self.import_has_been_called.write().unwrap(); + *import_flag = true; + Ok(()) + } + + fn import_until( + &self, + _predicate: impl Fn(&SignedBlockType) -> bool, + ) -> Result> { + let mut import_flag = self.import_has_been_called.write().unwrap(); + *import_flag = true; + Ok(self.latest_imported.clone()) + } + + fn peek( + &self, + predicate: impl Fn(&SignedBlockType) -> bool, + ) -> Result> { + match &self.latest_imported { + None => Ok(None), + Some(block) => { + if predicate(block) { + return Ok(Some(block.clone())) + } + Ok(None) + }, + } + } + + fn peek_latest(&self) -> Result> { + Ok(self.latest_imported.clone()) + } +} diff --git a/bitacross-worker/core/parentchain/block-import-dispatcher/src/triggered_dispatcher.rs b/bitacross-worker/core/parentchain/block-import-dispatcher/src/triggered_dispatcher.rs new file mode 100644 index 0000000000..77812331b8 --- /dev/null +++ b/bitacross-worker/core/parentchain/block-import-dispatcher/src/triggered_dispatcher.rs @@ -0,0 +1,374 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 block import dispatcher that retains all blocks in a queue until import is triggered. + +use crate::{ + error::{Error, Result}, + DispatchBlockImport, +}; +use itc_parentchain_block_importer::ImportParentchainBlocks; +use itp_import_queue::{PeekQueue, PopFromQueue, PushToQueue}; +use log::trace; +use std::vec::Vec; + +pub type RawEventsPerBlock = Vec; + +/// Trait to specifically trigger the import of parentchain blocks. +pub trait TriggerParentchainBlockImport { + type SignedBlockType; + /// Trigger the import of all queued block, **including** the latest one. + /// + /// Returns the latest imported block (if any). + fn import_all(&self) -> Result>; + + /// Trigger import of all queued blocks, **except** the latest one. + fn import_all_but_latest(&self) -> Result<()>; + + /// Trigger import of all blocks up to **and including** a specific block. + /// + /// If no block in the queue matches, then no blocks will be imported. + /// Returns the latest imported block (if any). + fn import_until( + &self, + predicate: impl Fn(&Self::SignedBlockType) -> bool, + ) -> Result>; + + /// Search the import queue with a given predicate and return a reference + /// to the first element that matches the predicate. + fn peek( + &self, + predicate: impl Fn(&Self::SignedBlockType) -> bool, + ) -> Result>; + + /// Peek the latest block in the import queue. Returns None if queue is empty. + fn peek_latest(&self) -> Result>; +} + +/// Dispatcher for block imports that retains blocks until the import is triggered, using the +/// `TriggerParentchainBlockImport` trait implementation. +pub struct TriggeredDispatcher { + pub block_importer: BlockImporter, + import_queue: BlockImportQueue, + events_queue: EventsImportQueue, +} + +impl + TriggeredDispatcher +where + BlockImporter: ImportParentchainBlocks, + BlockImportQueue: PushToQueue + + PopFromQueue, + EventsImportQueue: PushToQueue + PopFromQueue, +{ + pub fn new( + block_importer: BlockImporter, + block_import_queue: BlockImportQueue, + events_import_queue: EventsImportQueue, + ) -> Self { + TriggeredDispatcher { + block_importer, + import_queue: block_import_queue, + events_queue: events_import_queue, + } + } +} + +impl + DispatchBlockImport + for TriggeredDispatcher +where + BlockImporter: ImportParentchainBlocks, + BlockImportQueue: PushToQueue + PopFromQueue, + EventsImportQueue: PushToQueue + PopFromQueue, +{ + fn dispatch_import( + &self, + blocks: Vec, + events: Vec, + is_syncing: bool, + ) -> Result<()> { + let parentchain_id = self.block_importer.parentchain_id(); + trace!( + "[{:?}] Triggered dispatcher received block(s) and event(s) ({}) ({})", + parentchain_id, + blocks.len(), + events.len() + ); + if is_syncing { + trace!( + "[{:?}] Triggered is in sync mode, immediately importing blocks and events", + parentchain_id + ); + self.block_importer + .import_parentchain_blocks(blocks, events) + .map_err(Error::BlockImport) + } else { + trace!("[{:?}] pushing blocks and events to import queues", parentchain_id); + self.events_queue.push_multiple(events).map_err(Error::ImportQueue)?; + self.import_queue.push_multiple(blocks).map_err(Error::ImportQueue) + } + } +} + +impl TriggerParentchainBlockImport + for TriggeredDispatcher +where + BlockImporter: ImportParentchainBlocks, + BlockImportQueue: PushToQueue + + PopFromQueue + + PeekQueue, + EventsImportQueue: PushToQueue + + PopFromQueue + + PeekQueue, +{ + type SignedBlockType = BlockImporter::SignedBlockType; + + fn import_all(&self) -> Result> { + let blocks_to_import = self.import_queue.pop_all().map_err(Error::ImportQueue)?; + let events_to_import = self.events_queue.pop_all().map_err(Error::ImportQueue)?; + + let latest_imported_block = blocks_to_import.last().map(|b| (*b).clone()); + let parentchain_id = self.block_importer.parentchain_id(); + trace!( + "[{:?}] Trigger import of all parentchain blocks and events in queue ({}) ({})", + parentchain_id, + blocks_to_import.len(), + events_to_import.len() + ); + + self.block_importer + .import_parentchain_blocks(blocks_to_import, events_to_import) + .map_err(Error::BlockImport)?; + + Ok(latest_imported_block) + } + + fn import_all_but_latest(&self) -> Result<()> { + let blocks_to_import = self.import_queue.pop_all_but_last().map_err(Error::ImportQueue)?; + let events_to_import = self.events_queue.pop_all_but_last().map_err(Error::ImportQueue)?; + let parentchain_id = self.block_importer.parentchain_id(); + trace!( + "[{:?}] Trigger import of all parentchain blocks and events, except the latest, from queue ({}) ({})", + parentchain_id, + blocks_to_import.len(), + events_to_import.len() + ); + + self.block_importer + .import_parentchain_blocks(blocks_to_import, events_to_import) + .map_err(Error::BlockImport) + } + + fn import_until( + &self, + predicate: impl Fn(&BlockImporter::SignedBlockType) -> bool, + ) -> Result> { + trace!("Import of parentchain blocks and events has been triggered"); + let blocks_to_import = + self.import_queue.pop_until(predicate).map_err(Error::ImportQueue)?; + + let events_to_import = self + .events_queue + .pop_from_front_until(blocks_to_import.len()) + .map_err(Error::ImportQueue)?; + + let latest_imported_block = blocks_to_import.last().map(|b| (*b).clone()); + let parentchain_id = self.block_importer.parentchain_id(); + trace!( + "[{:?}] Import of parentchain blocks and events has been triggered, importing {} blocks and {} events from queue", + parentchain_id, + blocks_to_import.len(), + events_to_import.len(), + ); + + self.block_importer + .import_parentchain_blocks(blocks_to_import, events_to_import) + .map_err(Error::BlockImport)?; + + Ok(latest_imported_block) + } + + fn peek( + &self, + predicate: impl Fn(&BlockImporter::SignedBlockType) -> bool, + ) -> Result> { + let parentchain_id = self.block_importer.parentchain_id(); + trace!( + "[{:?}] Peek find parentchain import queue (currently has {} elements)", + parentchain_id, + self.import_queue.peek_queue_size().unwrap_or(0) + ); + self.import_queue.peek_find(predicate).map_err(Error::ImportQueue) + } + + fn peek_latest(&self) -> Result> { + let parentchain_id = self.block_importer.parentchain_id(); + trace!( + "[{:?}] Peek latest parentchain import queue (currently has {} elements)", + parentchain_id, + self.import_queue.peek_queue_size().unwrap_or(0) + ); + self.import_queue.peek_last().map_err(Error::ImportQueue) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use itc_parentchain_block_importer::block_importer_mock::ParentchainBlockImporterMock; + use itp_import_queue::{ImportQueue, PopFromQueue}; + + type SignedBlockType = u32; + type TestBlockImporter = ParentchainBlockImporterMock; + type TestQueue = ImportQueue; + type TestEventsQueue = ImportQueue; + type TestDispatcher = TriggeredDispatcher; + + #[test] + fn dispatching_blocks_imports_none_if_not_triggered() { + let dispatcher = test_fixtures(); + + dispatcher + .dispatch_import( + vec![1, 2, 3, 4, 5], + vec![vec![1], vec![2], vec![3], vec![4], vec![5]], + false, + ) + .unwrap(); + + assert!(dispatcher.block_importer.get_all_imported_blocks().is_empty()); + assert_eq!(dispatcher.import_queue.pop_all().unwrap(), vec![1, 2, 3, 4, 5]); + assert_eq!( + dispatcher.events_queue.pop_all().unwrap(), + vec![vec![1], vec![2], vec![3], vec![4], vec![5]] + ); + } + + #[test] + fn dispatching_blocks_multiple_times_add_all_to_queue() { + let dispatcher = test_fixtures(); + + dispatcher + .dispatch_import( + vec![1, 2, 3, 4, 5], + vec![vec![1], vec![2], vec![3], vec![4], vec![5]], + false, + ) + .unwrap(); + dispatcher + .dispatch_import(vec![6, 7, 8], vec![vec![6], vec![7], vec![8]], false) + .unwrap(); + + assert!(dispatcher.block_importer.get_all_imported_blocks().is_empty()); + assert_eq!(dispatcher.import_queue.pop_all().unwrap(), vec![1, 2, 3, 4, 5, 6, 7, 8]); + assert_eq!( + dispatcher.events_queue.pop_all().unwrap(), + vec![vec![1], vec![2], vec![3], vec![4], vec![5], vec![6], vec![7], vec![8]] + ); + } + + #[test] + fn triggering_import_all_empties_queue() { + let dispatcher = test_fixtures(); + + dispatcher.dispatch_import(vec![1, 2, 3, 4, 5], vec![], false).unwrap(); + let latest_imported = dispatcher.import_all().unwrap().unwrap(); + + assert_eq!(latest_imported, 5); + assert_eq!(dispatcher.block_importer.get_all_imported_blocks(), vec![1, 2, 3, 4, 5]); + assert!(dispatcher.import_queue.is_empty().unwrap()); + } + + #[test] + fn triggering_import_all_on_empty_queue_imports_none() { + let dispatcher = test_fixtures(); + + dispatcher.dispatch_import(vec![], vec![], false).unwrap(); + let maybe_latest_imported = dispatcher.import_all().unwrap(); + + assert!(maybe_latest_imported.is_none()); + assert_eq!( + dispatcher.block_importer.get_all_imported_blocks(), + Vec::::default() + ); + assert!(dispatcher.import_queue.is_empty().unwrap()); + assert!(dispatcher.events_queue.is_empty().unwrap()); + } + + #[test] + fn triggering_import_until_leaves_remaining_in_queue() { + let dispatcher = test_fixtures(); + + dispatcher + .dispatch_import( + vec![1, 2, 3, 4, 5], + vec![vec![1], vec![2], vec![3], vec![4], vec![5]], + false, + ) + .unwrap(); + let latest_imported = + dispatcher.import_until(|i: &SignedBlockType| i == &4).unwrap().unwrap(); + + assert_eq!(latest_imported, 4); + assert_eq!(dispatcher.block_importer.get_all_imported_blocks(), vec![1, 2, 3, 4]); + assert_eq!(dispatcher.import_queue.pop_all().unwrap(), vec![5]); + assert_eq!(dispatcher.events_queue.pop_all().unwrap(), vec![vec![5]]); + } + + #[test] + fn triggering_import_until_with_no_match_imports_nothing() { + let dispatcher = test_fixtures(); + + dispatcher + .dispatch_import( + vec![1, 2, 3, 4, 5], + vec![vec![1], vec![2], vec![3], vec![4], vec![5]], + false, + ) + .unwrap(); + let maybe_latest_imported = dispatcher.import_until(|i: &SignedBlockType| i == &8).unwrap(); + + assert!(maybe_latest_imported.is_none()); + assert!(dispatcher.block_importer.get_all_imported_blocks().is_empty()); + assert_eq!(dispatcher.import_queue.pop_all().unwrap(), vec![1, 2, 3, 4, 5]); + assert_eq!( + dispatcher.events_queue.pop_all().unwrap(), + vec![vec![1], vec![2], vec![3], vec![4], vec![5]] + ); + } + + #[test] + fn trigger_import_all_but_latest_works() { + let dispatcher = test_fixtures(); + + dispatcher.dispatch_import(vec![1, 2, 3, 4, 5], vec![], false).unwrap(); + dispatcher.import_all_but_latest().unwrap(); + + assert_eq!(dispatcher.block_importer.get_all_imported_blocks(), vec![1, 2, 3, 4]); + assert_eq!(dispatcher.import_queue.pop_all().unwrap(), vec![5]); + } + + fn test_fixtures() -> TestDispatcher { + let events_import_queue = ImportQueue::::default(); + let import_queue = ImportQueue::::default(); + let block_importer = ParentchainBlockImporterMock::::default(); + let dispatcher = + TriggeredDispatcher::new(block_importer, import_queue, events_import_queue); + dispatcher + } +} diff --git a/bitacross-worker/core/parentchain/block-importer/Cargo.toml b/bitacross-worker/core/parentchain/block-importer/Cargo.toml new file mode 100644 index 0000000000..96f85eb7a6 --- /dev/null +++ b/bitacross-worker/core/parentchain/block-importer/Cargo.toml @@ -0,0 +1,69 @@ +[package] +name = "itc-parentchain-block-importer" +version = "0.9.0" +authors = ['Trust Computing GmbH ', 'Integritee AG '] +edition = "2021" + +[dependencies] +# sgx dependencies +sgx_tstd = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git", optional = true } +sgx_types = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git" } + +# local dependencies +ita-stf = { path = "../../../app-libs/stf", default-features = false } +itc-parentchain-indirect-calls-executor = { path = "../indirect-calls-executor", default-features = false } +itc-parentchain-light-client = { path = "../light-client", default-features = false } +itp-enclave-metrics = { path = "../../../core-primitives/enclave-metrics", default-features = false } +itp-extrinsics-factory = { path = "../../../core-primitives/extrinsics-factory", default-features = false } +itp-stf-executor = { path = "../../../core-primitives/stf-executor", default-features = false } +itp-types = { path = "../../../core-primitives/types", default-features = false } + +# sgx enabled external libraries +thiserror_sgx = { package = "thiserror", git = "https://github.com/mesalock-linux/thiserror-sgx", tag = "sgx_1.1.3", optional = true } + +# crates.io std-only compatible external libraries (make sure these versions match with the sgx-enabled ones above) +thiserror = { version = "1.0", optional = true } + +# crates.io no-std compatible libraries +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +log = { version = "0.4", default-features = false } +sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } + +# litentry +itp-ocall-api = { path = "../../../core-primitives/ocall-api", default-features = false } + +[features] +default = ["std"] +std = [ + # local + "ita-stf/std", + "itc-parentchain-indirect-calls-executor/std", + "itc-parentchain-light-client/std", + "itp-enclave-metrics/std", + "itp-extrinsics-factory/std", + "itp-stf-executor/std", + "itp-types/std", + # no-std compatible libraries + "codec/std", + "log/std", + "sp-runtime/std", + # std compatible external + "thiserror", + "itp-ocall-api/std", +] +sgx = [ + # sgx + "sgx_tstd", + # local + "ita-stf/sgx", + "itc-parentchain-indirect-calls-executor/sgx", + "itc-parentchain-light-client/sgx", + "itp-enclave-metrics/sgx", + "itp-extrinsics-factory/sgx", + "itp-stf-executor/sgx", + # sgx enabled external libraries + "thiserror_sgx", +] + +# feature to export mock implementations, only to be used for dev-dependencies! +mocks = [] diff --git a/bitacross-worker/core/parentchain/block-importer/src/block_importer.rs b/bitacross-worker/core/parentchain/block-importer/src/block_importer.rs new file mode 100644 index 0000000000..6ffa524d49 --- /dev/null +++ b/bitacross-worker/core/parentchain/block-importer/src/block_importer.rs @@ -0,0 +1,190 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +//! Imports parentchain blocks and executes any indirect calls found in the extrinsics. + +use crate::{error::Result, ImportParentchainBlocks}; +use ita_stf::ParentchainHeader; +use itc_parentchain_indirect_calls_executor::ExecuteIndirectCalls; +use itc_parentchain_light_client::{ + concurrent_access::ValidatorAccess, BlockNumberOps, ExtrinsicSender, Validator, +}; +use itp_enclave_metrics::EnclaveMetric; +use itp_extrinsics_factory::CreateExtrinsics; +use itp_ocall_api::EnclaveMetricsOCallApi; +use itp_stf_executor::traits::StfUpdateState; +use itp_types::{ + parentchain::{IdentifyParentchain, ParentchainId}, + OpaqueCall, H256, +}; +use log::*; +use sp_runtime::{ + generic::SignedBlock as SignedBlockG, + traits::{Block as ParentchainBlockTrait, NumberFor}, +}; +use std::{marker::PhantomData, sync::Arc, vec::Vec}; + +/// Parentchain block import implementation. +pub struct ParentchainBlockImporter< + ParentchainBlock, + ValidatorAccessor, + StfExecutor, + ExtrinsicsFactory, + IndirectCallsExecutor, + OCallApi, +> { + pub validator_accessor: Arc, + stf_executor: Arc, + extrinsics_factory: Arc, + pub indirect_calls_executor: Arc, + ocall_api: Arc, + _phantom: PhantomData, +} + +impl< + ParentchainBlock, + ValidatorAccessor, + StfExecutor, + ExtrinsicsFactory, + IndirectCallsExecutor, + OCallApi, + > + ParentchainBlockImporter< + ParentchainBlock, + ValidatorAccessor, + StfExecutor, + ExtrinsicsFactory, + IndirectCallsExecutor, + OCallApi, + > +{ + pub fn new( + validator_accessor: Arc, + stf_executor: Arc, + extrinsics_factory: Arc, + indirect_calls_executor: Arc, + ocall_api: Arc, + ) -> Self { + ParentchainBlockImporter { + validator_accessor, + stf_executor, + extrinsics_factory, + indirect_calls_executor, + ocall_api, + _phantom: Default::default(), + } + } +} + +impl< + ParentchainBlock, + ValidatorAccessor, + StfExecutor, + ExtrinsicsFactory, + IndirectCallsExecutor, + OcallApi, + > ImportParentchainBlocks + for ParentchainBlockImporter< + ParentchainBlock, + ValidatorAccessor, + StfExecutor, + ExtrinsicsFactory, + IndirectCallsExecutor, + OcallApi, + > where + ParentchainBlock: ParentchainBlockTrait, + NumberFor: BlockNumberOps, + ValidatorAccessor: ValidatorAccess + IdentifyParentchain, + StfExecutor: StfUpdateState, + ExtrinsicsFactory: CreateExtrinsics, + IndirectCallsExecutor: ExecuteIndirectCalls, + OcallApi: EnclaveMetricsOCallApi, +{ + type SignedBlockType = SignedBlockG; + + fn import_parentchain_blocks( + &self, + blocks_to_import: Vec, + events_to_import: Vec>, + ) -> Result<()> { + let mut calls = Vec::::new(); + let id = self.validator_accessor.parentchain_id(); + + debug!("[{:?}] Import blocks to light-client!", id); + for (signed_block, raw_events) in + blocks_to_import.into_iter().zip(events_to_import.into_iter()) + { + let started = std::time::Instant::now(); + if let Err(e) = self + .validator_accessor + .execute_mut_on_validator(|v| v.submit_block(&signed_block)) + { + error!("[{:?}] Header submission to light client failed: {:?}", id, e); + return Err(e.into()) + } + + let block = signed_block.block; + // Perform state updates. + if let Err(e) = self + .stf_executor + .update_states(block.header(), &self.validator_accessor.parentchain_id()) + { + error!("[{:?}] Error performing state updates upon block import", id); + return Err(e.into()) + } + + // Execute indirect calls that were found in the extrinsics of the block, + // incl. shielding and unshielding. + match self + .indirect_calls_executor + .execute_indirect_calls_in_extrinsics(&block, &raw_events) + { + Ok(executed_shielding_calls) => { + calls.push(executed_shielding_calls); + }, + Err(e) => error!("[{:?}] Error executing relevant extrinsics: {:?}", id, e), + }; + if let Err(e) = self + .ocall_api + .update_metric(EnclaveMetric::ParentchainBlockImportTime(started.elapsed())) + { + warn!("Failed to update metric for parentchain block import: {:?}", e); + }; + + info!( + "[{:?}] Successfully imported parentchain block (number: {}, hash: {})", + id, + block.header().number, + block.header().hash() + ); + } + + // Create extrinsics for all `unshielding` and `block processed` calls we've gathered. + let parentchain_extrinsics = + self.extrinsics_factory.create_extrinsics(calls.as_slice(), None)?; + + // Sending the extrinsic requires mut access because the validator caches the sent extrinsics internally. + self.validator_accessor + .execute_mut_on_validator(|v| v.send_extrinsics(parentchain_extrinsics))?; + + Ok(()) + } + + fn parentchain_id(&self) -> ParentchainId { + self.validator_accessor.parentchain_id() + } +} diff --git a/bitacross-worker/core/parentchain/block-importer/src/block_importer_mock.rs b/bitacross-worker/core/parentchain/block-importer/src/block_importer_mock.rs new file mode 100644 index 0000000000..aae92293e7 --- /dev/null +++ b/bitacross-worker/core/parentchain/block-importer/src/block_importer_mock.rs @@ -0,0 +1,65 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 importer mock. + +use crate::{ + error::{Error, Result}, + ImportParentchainBlocks, +}; +use itp_types::parentchain::ParentchainId; +use std::{sync::RwLock, vec::Vec}; + +/// Mock implementation for the block importer. +/// +/// Just stores all the blocks that were sent to import internally. +#[derive(Default)] +pub struct ParentchainBlockImporterMock { + imported_blocks: RwLock>, +} + +impl ParentchainBlockImporterMock +where + SignedBlockT: Clone, +{ + pub fn get_all_imported_blocks(&self) -> Vec { + let imported_blocks_lock = self.imported_blocks.read().unwrap(); + (*imported_blocks_lock).clone() + } +} + +impl ImportParentchainBlocks for ParentchainBlockImporterMock +where + SignedBlockT: Clone, +{ + type SignedBlockType = SignedBlockT; + + fn import_parentchain_blocks( + &self, + blocks_to_import: Vec, + _events: Vec>, + ) -> Result<()> { + let mut imported_blocks_lock = self.imported_blocks.write().map_err(|e| { + Error::Other(format!("failed to acquire lock for imported blocks vec: {:?}", e).into()) + })?; + imported_blocks_lock.extend(blocks_to_import); + Ok(()) + } + fn parentchain_id(&self) -> ParentchainId { + ParentchainId::Litentry + } +} diff --git a/bitacross-worker/core/parentchain/block-importer/src/error.rs b/bitacross-worker/core/parentchain/block-importer/src/error.rs new file mode 100644 index 0000000000..856aa84ef2 --- /dev/null +++ b/bitacross-worker/core/parentchain/block-importer/src/error.rs @@ -0,0 +1,51 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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(all(not(feature = "std"), feature = "sgx"))] +use crate::sgx_reexport_prelude::*; + +use sgx_types::sgx_status_t; +use std::{boxed::Box, format}; + +pub type Result = core::result::Result; + +/// Parentchain block importer error. +#[derive(Debug, thiserror::Error)] +pub enum Error { + #[error("SGX error, status: {0}")] + Sgx(sgx_status_t), + #[error("Extrinsics factory error: {0}")] + ExtrinsicsFactory(#[from] itp_extrinsics_factory::error::Error), + #[error("STF execution error: {0}")] + StfExecution(#[from] itp_stf_executor::error::Error), + #[error("Light-client error: {0}")] + LightClient(#[from] itc_parentchain_light_client::error::Error), + #[error(transparent)] + Other(#[from] Box), +} + +impl From for Error { + fn from(sgx_status: sgx_status_t) -> Self { + Self::Sgx(sgx_status) + } +} + +impl From for Error { + fn from(e: codec::Error) -> Self { + Self::Other(format!("{:?}", e).into()) + } +} diff --git a/bitacross-worker/core/parentchain/block-importer/src/lib.rs b/bitacross-worker/core/parentchain/block-importer/src/lib.rs new file mode 100644 index 0000000000..3f2fd695bc --- /dev/null +++ b/bitacross-worker/core/parentchain/block-importer/src/lib.rs @@ -0,0 +1,61 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ +//! Parentchain block importing logic. +#![feature(trait_alias)] +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg(all(feature = "std", feature = "sgx"))] +compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the same time"); + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +extern crate sgx_tstd as std; + +// re-export module to properly feature gate sgx and regular std environment +#[cfg(all(not(feature = "std"), feature = "sgx"))] +pub mod sgx_reexport_prelude { + pub use thiserror_sgx as thiserror; +} + +pub mod block_importer; +pub mod error; + +#[cfg(feature = "mocks")] +pub mod block_importer_mock; + +pub use block_importer::*; + +use error::Result; +use itp_types::parentchain::ParentchainId; +use std::vec::Vec; + +/// Block import from the parentchain. +pub trait ImportParentchainBlocks { + type SignedBlockType: Clone; + + /// Import parentchain blocks to the light-client (validator): + /// * Scans the blocks for relevant extrinsics + /// * Validates and execute those extrinsics, mutating state + /// * Includes block headers into the light client + /// * Sends `PROCESSED_PARENTCHAIN_BLOCK` extrinsics that include the merkle root of all processed calls + fn import_parentchain_blocks( + &self, + blocks_to_import: Vec, + events_to_import: Vec>, + ) -> Result<()>; + + fn parentchain_id(&self) -> ParentchainId; +} diff --git a/bitacross-worker/core/parentchain/indirect-calls-executor/Cargo.toml b/bitacross-worker/core/parentchain/indirect-calls-executor/Cargo.toml new file mode 100644 index 0000000000..e8e018d334 --- /dev/null +++ b/bitacross-worker/core/parentchain/indirect-calls-executor/Cargo.toml @@ -0,0 +1,94 @@ +[package] +name = "itc-parentchain-indirect-calls-executor" +version = "0.9.0" +authors = ['Trust Computing GmbH ', 'Integritee AG '] +edition = "2021" + +[dependencies] +# sgx dependencies +sgx_tstd = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git", optional = true } +sgx_types = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git" } + +# local dependencies +itp-api-client-types = { path = "../../../core-primitives/node-api/api-client-types", default-features = false } +itp-node-api = { path = "../../../core-primitives/node-api", default-features = false } +itp-sgx-crypto = { path = "../../../core-primitives/sgx/crypto", default-features = false } +itp-sgx-runtime-primitives = { path = "../../../core-primitives/sgx-runtime-primitives", default-features = false } +itp-stf-executor = { path = "../../../core-primitives/stf-executor", default-features = false } +itp-stf-primitives = { path = "../../../core-primitives/stf-primitives", default-features = false } +itp-test = { path = "../../../core-primitives/test", default-features = false } +itp-top-pool-author = { path = "../../../core-primitives/top-pool-author", default-features = false } +itp-types = { path = "../../../core-primitives/types", default-features = false } + +# sgx enabled external libraries +futures_sgx = { package = "futures", git = "https://github.com/mesalock-linux/futures-rs-sgx", optional = true } +thiserror_sgx = { package = "thiserror", git = "https://github.com/mesalock-linux/thiserror-sgx", tag = "sgx_1.1.3", optional = true } + +# std compatible external libraries (make sure these versions match with the sgx-enabled ones above) +futures = { version = "0.3.8", optional = true } +thiserror = { version = "1.0", optional = true } + +# no-std compatible libraries +bs58 = { version = "0.4.0", default-features = false, features = ["alloc"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +log = { version = "0.4", default-features = false } + +# substrate dep +binary-merkle-tree = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } +sp-core = { default-features = false, features = ["full_crypto"], git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } +sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } + +# litentry +itp-utils = { path = "../../../core-primitives/utils", default-features = false } +lc-scheduled-enclave = { path = "../../../litentry/core/scheduled-enclave", default-features = false, optional = true } +litentry-primitives = { path = "../../../litentry/primitives", default-features = false } +parachain-core-primitives = { package = "core-primitives", path = "../../../../primitives/core", default-features = false } +sp-std = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } + +[dev-dependencies] +env_logger = "0.9.0" +itp-node-api = { path = "../../../core-primitives/node-api", features = ["mocks"] } +itp-sgx-crypto = { path = "../../../core-primitives/sgx/crypto", features = ["mocks"] } +itp-stf-executor = { path = "../../../core-primitives/stf-executor", features = ["mocks"] } +itp-test = { path = "../../../core-primitives/test" } +itp-top-pool-author = { path = "../../../core-primitives/top-pool-author", features = ["mocks"] } +itc-parentchain-test = { path = "../../../core/parentchain/test" } + +[features] +default = ["std"] +std = [ + "bs58/std", + "codec/std", + "futures", + "itp-node-api/std", + "itp-sgx-crypto/std", + "itp-stf-executor/std", + "itp-top-pool-author/std", + "itp-api-client-types/std", + "itp-test/std", + "itp-types/std", + "itp-sgx-runtime-primitives/std", + "log/std", + #substrate + "binary-merkle-tree/std", + "sp-core/std", + "sp-runtime/std", + "thiserror", + # litentry + "litentry-primitives/std", + "itp-utils/std", + "lc-scheduled-enclave/std", +] +sgx = [ + "sgx_tstd", + "futures_sgx", + "itp-node-api/sgx", + "itp-sgx-crypto/sgx", + "itp-stf-executor/sgx", + "itp-top-pool-author/sgx", + "itp-test/sgx", + "thiserror_sgx", + # litentry + "litentry-primitives/sgx", + "lc-scheduled-enclave/sgx", +] diff --git a/bitacross-worker/core/parentchain/indirect-calls-executor/src/error.rs b/bitacross-worker/core/parentchain/indirect-calls-executor/src/error.rs new file mode 100644 index 0000000000..2973f984f8 --- /dev/null +++ b/bitacross-worker/core/parentchain/indirect-calls-executor/src/error.rs @@ -0,0 +1,111 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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(all(not(feature = "std"), feature = "sgx"))] +use crate::sgx_reexport_prelude::*; +pub use litentry_primitives::{ErrorDetail, IMPError, VCMPError}; + +use itp_types::parentchain::ParentchainError; +use lc_scheduled_enclave::error::Error as ScheduledEnclaveError; +use sgx_types::sgx_status_t; +use sp_runtime::traits::LookupError; +use std::{boxed::Box, format}; + +pub type Result = core::result::Result; + +/// Indirect calls execution error. +#[derive(Debug, thiserror::Error)] +pub enum Error { + #[error("SGX error, status: {0}")] + Sgx(sgx_status_t), + #[error("STF execution error: {0}")] + StfExecution(#[from] itp_stf_executor::error::Error), + #[error("Node Metadata error: {0:?}")] + NodeMetadata(itp_node_api::metadata::Error), + #[error("Node metadata provider error: {0:?}")] + NodeMetadataProvider(#[from] itp_node_api::metadata::provider::Error), + #[error("Crypto error: {0}")] + Crypto(itp_sgx_crypto::Error), + #[error(transparent)] + Other(#[from] Box), + #[error("AccountId lookup error")] + AccountIdLookup, + #[error("convert parent chain block number error")] + ConvertParentchainBlockNumber, + #[error("IMP handling error: {0:?}")] + IMPHandlingError(IMPError), + #[error("VCMP handling error: {0:?}")] + VCMPHandlingError(VCMPError), + #[error("BatchAll handling error")] + BatchAllHandlingError, + #[error("ScheduledEnclave Error: {0:?}")] + ImportScheduledEnclave(ScheduledEnclaveError), +} + +impl From for Error { + fn from(e: ParentchainError) -> Self { + Self::Other(format!("{:?}", e).into()) + } +} + +impl From for Error { + fn from(sgx_status: sgx_status_t) -> Self { + Self::Sgx(sgx_status) + } +} + +impl From for Error { + fn from(e: itp_sgx_crypto::Error) -> Self { + Self::Crypto(e) + } +} + +impl From for Error { + fn from(e: codec::Error) -> Self { + Self::Other(format!("{:?}", e).into()) + } +} + +impl From for Error { + fn from(e: itp_node_api::metadata::Error) -> Self { + Self::NodeMetadata(e) + } +} + +impl From for Error { + fn from(_: LookupError) -> Self { + Self::AccountIdLookup + } +} + +impl From for Error { + fn from(e: IMPError) -> Self { + Self::IMPHandlingError(e) + } +} + +impl From for Error { + fn from(e: VCMPError) -> Self { + Self::VCMPHandlingError(e) + } +} + +impl From for Error { + fn from(e: ScheduledEnclaveError) -> Self { + Self::ImportScheduledEnclave(e) + } +} diff --git a/bitacross-worker/core/parentchain/indirect-calls-executor/src/event_filter.rs b/bitacross-worker/core/parentchain/indirect-calls-executor/src/event_filter.rs new file mode 100644 index 0000000000..ffb9882f58 --- /dev/null +++ b/bitacross-worker/core/parentchain/indirect-calls-executor/src/event_filter.rs @@ -0,0 +1,33 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 way to filter Parentchain events + +use crate::error::Error; + +use itp_stf_primitives::error::StfError; + +use std::format; + +impl From for Error { + fn from(a: StfError) -> Self { + Error::Other(format!("Error when shielding for privacy sidechain {:?}", a).into()) + } +} + +pub trait ToEvents { + fn to_events(&self) -> &E; +} diff --git a/bitacross-worker/core/parentchain/indirect-calls-executor/src/executor.rs b/bitacross-worker/core/parentchain/indirect-calls-executor/src/executor.rs new file mode 100644 index 0000000000..0c2dbcf74c --- /dev/null +++ b/bitacross-worker/core/parentchain/indirect-calls-executor/src/executor.rs @@ -0,0 +1,519 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ +//! Execute indirect calls, i.e. extrinsics extracted from parentchain blocks + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +use crate::sgx_reexport_prelude::*; + +use crate::{ + error::{Error, Result}, + filter_metadata::{EventsFromMetadata, FilterIntoDataFrom}, + traits::{ExecuteIndirectCalls, IndirectDispatch}, +}; +use alloc::format; +use binary_merkle_tree::merkle_root; +use codec::{Decode, Encode}; +use core::marker::PhantomData; +use itp_node_api::metadata::{ + pallet_teerex::TeerexCallIndexes, provider::AccessNodeMetadata, NodeMetadataTrait, +}; +use itp_sgx_crypto::{key_repository::AccessKey, ShieldingCryptoDecrypt, ShieldingCryptoEncrypt}; +use itp_stf_executor::traits::{StfEnclaveSigning, StfShardVaultQuery}; +use itp_stf_primitives::{ + traits::{IndirectExecutor, TrustedCallSigning, TrustedCallVerification}, + types::AccountId, +}; +use itp_top_pool_author::traits::AuthorApi; +use itp_types::{ + parentchain::{ExtrinsicStatus, FilterEvents, HandleParentchainEvents}, + OpaqueCall, RsaRequest, ShardIdentifier, H256, +}; +use log::*; +use sp_core::blake2_256; +use sp_runtime::traits::{Block as ParentchainBlockTrait, Header, Keccak256}; +use std::{fmt::Debug, sync::Arc, vec::Vec}; + +pub struct IndirectCallsExecutor< + ShieldingKeyRepository, + StfEnclaveSigner, + TopPoolAuthor, + NodeMetadataProvider, + IndirectCallsFilter, + EventCreator, + ParentchainEventHandler, + TCS, + G, +> { + pub(crate) shielding_key_repo: Arc, + pub stf_enclave_signer: Arc, + pub(crate) top_pool_author: Arc, + pub(crate) node_meta_data_provider: Arc, + _phantom: PhantomData<(IndirectCallsFilter, EventCreator, ParentchainEventHandler, TCS, G)>, +} +impl< + ShieldingKeyRepository, + StfEnclaveSigner, + TopPoolAuthor, + NodeMetadataProvider, + IndirectCallsFilter, + EventCreator, + ParentchainEventHandler, + TCS, + G, + > + IndirectCallsExecutor< + ShieldingKeyRepository, + StfEnclaveSigner, + TopPoolAuthor, + NodeMetadataProvider, + IndirectCallsFilter, + EventCreator, + ParentchainEventHandler, + TCS, + G, + > +{ + pub fn new( + shielding_key_repo: Arc, + stf_enclave_signer: Arc, + top_pool_author: Arc, + node_meta_data_provider: Arc, + ) -> Self { + IndirectCallsExecutor { + shielding_key_repo, + stf_enclave_signer, + top_pool_author, + node_meta_data_provider, + _phantom: Default::default(), + } + } +} + +impl< + ShieldingKeyRepository, + StfEnclaveSigner, + TopPoolAuthor, + NodeMetadataProvider, + FilterIndirectCalls, + EventCreator, + ParentchainEventHandler, + TCS, + G, + > ExecuteIndirectCalls + for IndirectCallsExecutor< + ShieldingKeyRepository, + StfEnclaveSigner, + TopPoolAuthor, + NodeMetadataProvider, + FilterIndirectCalls, + EventCreator, + ParentchainEventHandler, + TCS, + G, + > where + ShieldingKeyRepository: AccessKey, + ::KeyType: ShieldingCryptoDecrypt + + ShieldingCryptoEncrypt, + StfEnclaveSigner: StfEnclaveSigning + StfShardVaultQuery, + TopPoolAuthor: AuthorApi + Send + Sync + 'static, + NodeMetadataProvider: AccessNodeMetadata, + FilterIndirectCalls: FilterIntoDataFrom, + NodeMetadataProvider::MetadataType: NodeMetadataTrait + Clone, + FilterIndirectCalls::Output: IndirectDispatch + Encode + Debug, + EventCreator: EventsFromMetadata, + ParentchainEventHandler: HandleParentchainEvents, + TCS: PartialEq + Encode + Decode + Debug + Clone + Send + Sync + TrustedCallVerification, + G: PartialEq + Encode + Decode + Debug + Clone + Send + Sync, +{ + fn execute_indirect_calls_in_extrinsics( + &self, + block: &ParentchainBlock, + events: &[u8], + ) -> Result + where + ParentchainBlock: ParentchainBlockTrait, + { + let block_number = *block.header().number(); + let block_hash = block.hash(); + + trace!("Scanning block {:?} for relevant xt", block_number); + let mut executed_calls = Vec::::new(); + + let events = self + .node_meta_data_provider + .get_from_metadata(|metadata| { + EventCreator::create_from_metadata(metadata.clone(), block_hash, events) + })? + .ok_or_else(|| Error::Other("Could not create events from metadata".into()))?; + + let xt_statuses = events.get_extrinsic_statuses().map_err(|e| { + Error::Other(format!("Error when shielding for privacy sidechain {:?}", e).into()) + })?; + trace!("xt_statuses:: {:?}", xt_statuses); + + let shard = self.get_default_shard(); + if let Ok(vault) = self.stf_enclave_signer.get_shard_vault(&shard) { + ParentchainEventHandler::handle_events(self, events, &vault)?; + } + + // This would be catastrophic but should never happen + if xt_statuses.len() != block.extrinsics().len() { + return Err(Error::Other("Extrinsic Status and Extrinsic count not equal".into())) + } + + for (xt_opaque, xt_status) in block.extrinsics().iter().zip(xt_statuses.iter()) { + let encoded_xt_opaque = xt_opaque.encode(); + + let maybe_call = self.node_meta_data_provider.get_from_metadata(|metadata| { + FilterIndirectCalls::filter_into_from_metadata(&encoded_xt_opaque, metadata) + })?; + + let call = match maybe_call { + Some(c) => c, + None => continue, + }; + + if let ExtrinsicStatus::Failed = xt_status { + warn!("Parentchain Extrinsic Failed, {:?} wont be dispatched", call); + continue + } + + if let Err(e) = call.dispatch(self, ()) { + warn!("Error executing the indirect call: {:?}. Error {:?}", call, e); + } else { + executed_calls.push(hash_of(&call)); + } + } + debug!("successfully processed {} indirect invocations", executed_calls.len()); + // Include a processed parentchain block confirmation for each block. + self.create_processed_parentchain_block_call::( + block_hash, + executed_calls, + block_number, + ) + } + + fn create_processed_parentchain_block_call( + &self, + block_hash: H256, + extrinsics: Vec, + block_number: <::Header as Header>::Number, + ) -> Result + where + ParentchainBlock: ParentchainBlockTrait, + { + let call = self.node_meta_data_provider.get_from_metadata(|meta_data| { + meta_data.confirm_processed_parentchain_block_call_indexes() + })??; + let root: H256 = merkle_root::(extrinsics); + trace!("prepared confirm_processed_parentchain_block() call for block {:?} with index {:?} and merkle root {}", block_number, call, root); + // Litentry: we don't include `shard` in the extrinsic parameter to be backwards compatible, + // however, we should not forget it in case we need it later + Ok(OpaqueCall::from_tuple(&(call, block_hash, block_number, root))) + } +} + +impl< + ShieldingKeyRepository, + StfEnclaveSigner, + TopPoolAuthor, + NodeMetadataProvider, + FilterIndirectCalls, + EventFilter, + PrivacySidechain, + TCS, + G, + > IndirectExecutor + for IndirectCallsExecutor< + ShieldingKeyRepository, + StfEnclaveSigner, + TopPoolAuthor, + NodeMetadataProvider, + FilterIndirectCalls, + EventFilter, + PrivacySidechain, + TCS, + G, + > where + ShieldingKeyRepository: AccessKey, + ::KeyType: ShieldingCryptoDecrypt + + ShieldingCryptoEncrypt, + StfEnclaveSigner: StfEnclaveSigning + StfShardVaultQuery, + TopPoolAuthor: AuthorApi + Send + Sync + 'static, + TCS: PartialEq + Encode + Decode + Debug + Clone + Send + Sync + TrustedCallVerification, + G: PartialEq + Encode + Decode + Debug + Clone + Send + Sync, +{ + fn submit_trusted_call(&self, shard: ShardIdentifier, encrypted_trusted_call: Vec) { + if let Err(e) = futures::executor::block_on( + self.top_pool_author.submit_top(RsaRequest::new(shard, encrypted_trusted_call)), + ) { + error!("Error adding indirect trusted call to TOP pool: {:?}", e); + } + } + + fn decrypt(&self, encrypted: &[u8]) -> Result> { + let key = self.shielding_key_repo.retrieve_key()?; + Ok(key.decrypt(encrypted)?) + } + + fn encrypt(&self, value: &[u8]) -> Result> { + let key = self.shielding_key_repo.retrieve_key()?; + Ok(key.encrypt(value)?) + } + + fn get_enclave_account(&self) -> Result { + Ok(self.stf_enclave_signer.get_enclave_account()?) + } + + fn get_default_shard(&self) -> ShardIdentifier { + self.top_pool_author.list_handled_shards().first().copied().unwrap_or_default() + } + + fn sign_call_with_self>( + &self, + trusted_call: &TC, + shard: &ShardIdentifier, + ) -> Result { + Ok(self.stf_enclave_signer.sign_call_with_self(trusted_call, shard)?) + } +} + +pub fn hash_of(xt: &T) -> H256 { + blake2_256(&xt.encode()).into() +} + +#[cfg(test)] +mod test { + use super::*; + use crate::mock::*; + use codec::{Decode, Encode}; + use itc_parentchain_test::ParentchainBlockBuilder; + use itp_node_api::{ + api_client::{ + ExtrinsicParams, ParentchainAdditionalParams, ParentchainExtrinsicParams, + ParentchainUncheckedExtrinsic, + }, + metadata::{metadata_mocks::NodeMetadataMock, provider::NodeMetadataRepository}, + }; + use itp_sgx_crypto::mocks::KeyRepositoryMock; + use itp_stf_executor::mocks::StfEnclaveSignerMock; + use itp_stf_primitives::{ + traits::TrustedCallVerification, + types::{AccountId, TrustedOperation}, + }; + use itp_test::mock::{ + shielding_crypto_mock::ShieldingCryptoMock, + stf_mock::{GetterMock, TrustedCallSignedMock}, + }; + use itp_top_pool_author::mocks::AuthorApiMock; + use itp_types::{Block, CallWorkerFn, RsaRequest, ShardIdentifier, ShieldFundsFn}; + use sp_core::{ed25519, Pair}; + use sp_runtime::{MultiAddress, MultiSignature, OpaqueExtrinsic}; + use std::assert_matches::assert_matches; + + type TestShieldingKeyRepo = KeyRepositoryMock; + type TestStfEnclaveSigner = StfEnclaveSignerMock; + type TestTopPoolAuthor = AuthorApiMock; + type TestNodeMetadataRepository = NodeMetadataRepository; + type TestIndirectCallExecutor = IndirectCallsExecutor< + TestShieldingKeyRepo, + TestStfEnclaveSigner, + TestTopPoolAuthor, + TestNodeMetadataRepository, + MockExtrinsicFilter, + TestEventCreator, + MockParentchainEventHandler, + TrustedCallSignedMock, + GetterMock, + >; + + type Seed = [u8; 32]; + + const TEST_SEED: Seed = *b"12345678901234567890123456789012"; + + #[test] + fn indirect_call_can_be_added_to_pool_successfully() { + let _ = env_logger::builder().is_test(true).try_init(); + + let (indirect_calls_executor, top_pool_author, _) = + test_fixtures([0u8; 32], NodeMetadataMock::new()); + + let opaque_extrinsic = + OpaqueExtrinsic::from_bytes(invoke_unchecked_extrinsic().encode().as_slice()).unwrap(); + + let parentchain_block = ParentchainBlockBuilder::default() + .with_extrinsics(vec![opaque_extrinsic]) + .build(); + + indirect_calls_executor + .execute_indirect_calls_in_extrinsics(&parentchain_block, &Vec::new()) + .unwrap(); + + assert_eq!(1, top_pool_author.pending_tops(shard_id()).unwrap().len()); + } + + #[test] + fn shielding_call_can_be_added_to_pool_successfully() { + let _ = env_logger::builder().is_test(true).try_init(); + + let mr_enclave = [33u8; 32]; + let (indirect_calls_executor, top_pool_author, shielding_key_repo) = + test_fixtures(mr_enclave.clone(), NodeMetadataMock::new()); + let shielding_key = shielding_key_repo.retrieve_key().unwrap(); + + let opaque_extrinsic = OpaqueExtrinsic::from_bytes( + shield_funds_unchecked_extrinsic(&shielding_key).encode().as_slice(), + ) + .unwrap(); + + let parentchain_block = ParentchainBlockBuilder::default() + .with_extrinsics(vec![opaque_extrinsic]) + .build(); + + indirect_calls_executor + .execute_indirect_calls_in_extrinsics(&parentchain_block, &Vec::new()) + .unwrap(); + + assert_eq!(1, top_pool_author.pending_tops(shard_id()).unwrap().len()); + let submitted_extrinsic = + top_pool_author.pending_tops(shard_id()).unwrap().first().cloned().unwrap(); + let decrypted_extrinsic = shielding_key.decrypt(&submitted_extrinsic).unwrap(); + let decoded_operation = TrustedOperation::::decode( + &mut decrypted_extrinsic.as_slice(), + ) + .unwrap(); + assert_matches!(decoded_operation, TrustedOperation::indirect_call(_)); + let trusted_call_signed = decoded_operation.to_call().unwrap(); + assert!(trusted_call_signed.verify_signature(&mr_enclave, &shard_id())); + } + + #[test] + fn ensure_empty_extrinsic_vec_triggers_zero_filled_merkle_root() { + // given + let dummy_metadata = NodeMetadataMock::new(); + let (indirect_calls_executor, _, _) = test_fixtures([38u8; 32], dummy_metadata.clone()); + + let block_hash = H256::from([1; 32]); + let extrinsics = Vec::new(); + let confirm_processed_parentchain_block_indexes = + dummy_metadata.confirm_processed_parentchain_block_call_indexes().unwrap(); + let expected_call = + (confirm_processed_parentchain_block_indexes, block_hash, 1u32, H256::default()) + .encode(); + + // when + let call = indirect_calls_executor + .create_processed_parentchain_block_call::(block_hash, extrinsics, 1u32) + .unwrap(); + + // then + assert_eq!(call.0, expected_call); + } + + #[test] + fn ensure_non_empty_extrinsic_vec_triggers_non_zero_merkle_root() { + // given + let dummy_metadata = NodeMetadataMock::new(); + let (indirect_calls_executor, _, _) = test_fixtures([39u8; 32], dummy_metadata.clone()); + + let block_hash = H256::from([1; 32]); + let extrinsics = vec![H256::from([4; 32]), H256::from([9; 32])]; + let confirm_processed_parentchain_block_indexes = + dummy_metadata.confirm_processed_parentchain_block_call_indexes().unwrap(); + + let zero_root_call = + (confirm_processed_parentchain_block_indexes, block_hash, 1u32, H256::default()) + .encode(); + + // when + let call = indirect_calls_executor + .create_processed_parentchain_block_call::(block_hash, extrinsics, 1u32) + .unwrap(); + + // then + assert_ne!(call.0, zero_root_call); + } + + fn shield_funds_unchecked_extrinsic( + shielding_key: &ShieldingCryptoMock, + ) -> ParentchainUncheckedExtrinsic { + let target_account = shielding_key.encrypt(&AccountId::new([2u8; 32]).encode()).unwrap(); + let dummy_metadata = NodeMetadataMock::new(); + + let shield_funds_indexes = dummy_metadata.shield_funds_call_indexes().unwrap(); + ParentchainUncheckedExtrinsic::::new_signed( + (shield_funds_indexes, target_account, 1000u128, shard_id()), + MultiAddress::Address32([1u8; 32]), + MultiSignature::Ed25519(default_signature()), + default_extrinsic_params().signed_extra(), + ) + } + + fn invoke_unchecked_extrinsic() -> ParentchainUncheckedExtrinsic { + let request = RsaRequest::new(shard_id(), vec![1u8, 2u8]); + let dummy_metadata = NodeMetadataMock::new(); + let call_worker_indexes = dummy_metadata.invoke_call_indexes().unwrap(); + + ParentchainUncheckedExtrinsic::::new_signed( + (call_worker_indexes, request), + MultiAddress::Address32([1u8; 32]), + MultiSignature::Ed25519(default_signature()), + default_extrinsic_params().signed_extra(), + ) + } + + fn default_signature() -> ed25519::Signature { + signer().sign(&[0u8]) + } + + fn signer() -> ed25519::Pair { + ed25519::Pair::from_seed(&TEST_SEED) + } + + fn shard_id() -> ShardIdentifier { + ShardIdentifier::default() + } + + fn default_extrinsic_params() -> ParentchainExtrinsicParams { + ParentchainExtrinsicParams::new( + 0, + 0, + 0, + H256::default(), + ParentchainAdditionalParams::default(), + ) + } + + fn test_fixtures( + mr_enclave: [u8; 32], + metadata: NodeMetadataMock, + ) -> (TestIndirectCallExecutor, Arc, Arc) { + let shielding_key_repo = Arc::new(TestShieldingKeyRepo::default()); + let stf_enclave_signer = Arc::new(TestStfEnclaveSigner::new(mr_enclave)); + let top_pool_author = Arc::new(TestTopPoolAuthor::default()); + let node_metadata_repo = Arc::new(NodeMetadataRepository::new(metadata)); + + let executor = IndirectCallsExecutor::new( + shielding_key_repo.clone(), + stf_enclave_signer, + top_pool_author.clone(), + node_metadata_repo, + ); + + (executor, top_pool_author, shielding_key_repo) + } +} diff --git a/bitacross-worker/core/parentchain/indirect-calls-executor/src/filter_metadata.rs b/bitacross-worker/core/parentchain/indirect-calls-executor/src/filter_metadata.rs new file mode 100644 index 0000000000..22abc50bb3 --- /dev/null +++ b/bitacross-worker/core/parentchain/indirect-calls-executor/src/filter_metadata.rs @@ -0,0 +1,112 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{error::Result, IndirectDispatch}; +use codec::{Decode, Encode}; +use core::marker::PhantomData; +use itp_api_client_types::{Events, Metadata}; +use itp_node_api::metadata::NodeMetadata; +use itp_stf_primitives::traits::IndirectExecutor; +use itp_types::{parentchain::FilterEvents, H256}; + +pub trait EventsFromMetadata { + type Output: FilterEvents; + + fn create_from_metadata( + metadata: NodeMetadata, + block_hash: H256, + events: &[u8], + ) -> Option; +} + +pub struct EventCreator { + _phantom: PhantomData, +} + +impl + Clone, FilterableEvents> EventsFromMetadata + for EventCreator +where + FilterableEvents: From> + FilterEvents, +{ + type Output = FilterableEvents; + + fn create_from_metadata( + metadata: NodeMetadata, + block_hash: H256, + events: &[u8], + ) -> Option { + let raw_metadata: Metadata = metadata.try_into().ok()?; + Some(Events::::new(raw_metadata, block_hash, events.to_vec()).into()) + } +} + +/// Trait to filter an indirect call and decode into it, where the decoding +/// is based on the metadata provided. +pub trait FilterIntoDataFrom { + /// Type to decode into. + type Output; + + /// Knows how to parse the parentchain metadata. + type ParseParentchainMetadata; + + /// Filters some bytes and returns `Some(Self::Output)` if the filter matches some criteria. + fn filter_into_from_metadata( + encoded_data: &[u8], + metadata: &NodeMetadata, + ) -> Option; +} + +/// Indirect calls filter denying all indirect calls. +pub struct DenyAll; + +mod seal { + use super::*; + use crate::Error; + use core::fmt::Debug; + use itp_stf_primitives::traits::TrustedCallVerification; + + /// Stub struct for the `DenyAll` filter that never executes anything. + #[derive(Debug, Encode)] + pub struct CantExecute; + + impl FilterIntoDataFrom for DenyAll { + type Output = CantExecute; + type ParseParentchainMetadata = (); + + fn filter_into_from_metadata(_: &[u8], _: &NodeMetadata) -> Option { + None + } + } + + impl, TCS> IndirectDispatch for CantExecute + where + TCS: PartialEq + Encode + Decode + Debug + Clone + Send + Sync + TrustedCallVerification, + { + type Args = (); + fn dispatch(&self, _: &Executor, _args: Self::Args) -> Result<()> { + // We should never get here because `CantExecute` is in a private module and the trait + // implementation is sealed and always returns `None` instead of a `CantExecute` instance. + // Regardless, we never want the enclave to panic, this is why we take this extra safety + // measure. + log::warn!( + "Executed indirect dispatch for 'CantExecute'\ + this means there is some logic error." + ); + Ok(()) + } + } +} diff --git a/bitacross-worker/core/parentchain/indirect-calls-executor/src/lib.rs b/bitacross-worker/core/parentchain/indirect-calls-executor/src/lib.rs new file mode 100644 index 0000000000..199ee448d6 --- /dev/null +++ b/bitacross-worker/core/parentchain/indirect-calls-executor/src/lib.rs @@ -0,0 +1,52 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ +//! Execute indirect calls, i.e. extrinsics extracted from parentchain blocks. +//! +//! The core struct of this crate is the [IndirectCallsExecutor] executor. It scans parentchain +//! blocks for relevant extrinsics, derives an indirect call for those and dispatches the +//! indirect call. + +#![feature(trait_alias)] +#![cfg_attr(not(feature = "std"), no_std)] +#![cfg_attr(test, feature(assert_matches))] + +#[cfg(all(feature = "std", feature = "sgx"))] +compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the same time"); + +extern crate alloc; + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +extern crate sgx_tstd as std; + +// re-export module to properly feature gate sgx and regular std environment +#[cfg(all(not(feature = "std"), feature = "sgx"))] +pub mod sgx_reexport_prelude { + pub use futures_sgx as futures; + pub use thiserror_sgx as thiserror; +} + +mod executor; +pub mod mock; +pub mod traits; + +pub mod error; +pub mod event_filter; +pub mod filter_metadata; + +pub use error::{Error, Result}; +pub use executor::{hash_of, IndirectCallsExecutor}; +pub use traits::{ExecuteIndirectCalls, IndirectDispatch}; diff --git a/bitacross-worker/core/parentchain/indirect-calls-executor/src/mock.rs b/bitacross-worker/core/parentchain/indirect-calls-executor/src/mock.rs new file mode 100644 index 0000000000..38189f44d8 --- /dev/null +++ b/bitacross-worker/core/parentchain/indirect-calls-executor/src/mock.rs @@ -0,0 +1,247 @@ +use crate::{ + error::{Error, Result as ICResult}, + filter_metadata::{EventsFromMetadata, FilterIntoDataFrom}, + IndirectDispatch, +}; +use codec::{Decode, Encode}; +use core::marker::PhantomData; +use litentry_primitives::DecryptableRequest; + +use itp_node_api::{ + api_client::{CallIndex, PairSignature, UncheckedExtrinsicV4}, + metadata::NodeMetadataTrait, +}; +use itp_sgx_runtime_primitives::types::{AccountId, Balance}; +use itp_stf_primitives::{traits::IndirectExecutor, types::Signature}; +use itp_test::mock::stf_mock::{GetterMock, TrustedCallMock, TrustedCallSignedMock}; +use itp_types::{ + parentchain::{BalanceTransfer, ExtrinsicStatus, FilterEvents, HandleParentchainEvents}, + Address, RsaRequest, ShardIdentifier, H256, +}; +use log::*; +use std::vec::Vec; + +/// Default filter we use for the Integritee-Parachain. +pub struct MockExtrinsicFilter { + _phantom: PhantomData, +} + +impl FilterIntoDataFrom + for MockExtrinsicFilter +where + ExtrinsicParser: ParseExtrinsic, +{ + type Output = IndirectCall; + type ParseParentchainMetadata = ExtrinsicParser; + + fn filter_into_from_metadata( + encoded_data: &[u8], + metadata: &NodeMetadata, + ) -> Option { + let call_mut = &mut &encoded_data[..]; + + // Todo: the filter should not need to parse, only filter. This should directly be configured + // in the indirect executor. + let xt = match Self::ParseParentchainMetadata::parse(call_mut) { + Ok(xt) => xt, + Err(e) => { + log::error!( + "[ShieldFundsAndInvokeFilter] Could not parse parentchain extrinsic: {:?}", + e + ); + return None + }, + }; + let index = xt.call_index; + let call_args = &mut &xt.call_args[..]; + log::trace!( + "[ShieldFundsAndInvokeFilter] attempting to execute indirect call with index {:?}", + index + ); + if index == metadata.shield_funds_call_indexes().ok()? { + log::debug!("executing shield funds call"); + let args = ShieldFundsArgs::decode(call_args).unwrap(); + Some(IndirectCall::ShieldFunds(args)) + } else if index == metadata.invoke_call_indexes().ok()? { + log::debug!("executing invoke call"); + let args = InvokeArgs::decode(call_args).unwrap(); + Some(IndirectCall::Invoke(args)) + } else { + None + } + } +} +pub struct ExtrinsicParser { + _phantom: PhantomData, +} +use itp_api_client_types::ParentchainSignedExtra; +use itp_stf_primitives::types::TrustedOperation; + +/// Parses the extrinsics corresponding to the parentchain. +pub type MockParentchainExtrinsicParser = ExtrinsicParser; + +/// Partially interpreted extrinsic containing the `signature` and the `call_index` whereas +/// the `call_args` remain in encoded form. +/// +/// Intended for usage, where the actual `call_args` form is unknown. +pub struct SemiOpaqueExtrinsic<'a> { + /// Signature of the Extrinsic. + pub signature: Signature, + /// Call index of the dispatchable. + pub call_index: CallIndex, + /// Encoded arguments of the dispatchable corresponding to the `call_index`. + pub call_args: &'a [u8], +} + +/// Trait to extract signature and call indexes of an encoded [UncheckedExtrinsicV4]. +pub trait ParseExtrinsic { + /// Signed extra of the extrinsic. + type SignedExtra; + + fn parse(encoded_call: &[u8]) -> Result; +} + +impl ParseExtrinsic for ExtrinsicParser +where + SignedExtra: Decode + Encode, +{ + type SignedExtra = SignedExtra; + + /// Extract a call index of an encoded call. + fn parse(encoded_call: &[u8]) -> Result { + let call_mut = &mut &encoded_call[..]; + + // `()` is a trick to stop decoding after the call index. So the remaining bytes + // of `call` after decoding only contain the parentchain's dispatchable's arguments. + let xt = UncheckedExtrinsicV4::< + Address, + (CallIndex, ()), + PairSignature, + Self::SignedExtra, + >::decode(call_mut)?; + + Ok(SemiOpaqueExtrinsic { + signature: xt.signature.unwrap().1, + call_index: xt.function.0, + call_args: call_mut, + }) + } +} +/// The default indirect call (extrinsic-triggered) of the Integritee-Parachain. +#[derive(Debug, Clone, Encode, Decode, Eq, PartialEq)] +pub enum IndirectCall { + ShieldFunds(ShieldFundsArgs), + Invoke(InvokeArgs), +} + +impl> + IndirectDispatch for IndirectCall +{ + type Args = (); + fn dispatch(&self, executor: &Executor, args: Self::Args) -> ICResult<()> { + trace!("dispatching indirect call {:?}", self); + match self { + IndirectCall::ShieldFunds(shieldfunds_args) => + shieldfunds_args.dispatch(executor, args), + IndirectCall::Invoke(invoke_args) => invoke_args.dispatch(executor, args), + } + } +} + +pub struct TestEventCreator; + +impl EventsFromMetadata for TestEventCreator { + type Output = MockEvents; + + fn create_from_metadata( + _metadata: NodeMetadata, + _block_hash: H256, + _events: &[u8], + ) -> Option { + Some(MockEvents) + } +} + +pub struct MockEvents; + +impl FilterEvents for MockEvents { + type Error = (); + fn get_extrinsic_statuses(&self) -> core::result::Result, Self::Error> { + Ok(Vec::from([ExtrinsicStatus::Success])) + } + + fn get_transfer_events(&self) -> core::result::Result, Self::Error> { + let transfer = BalanceTransfer { + to: [0u8; 32].into(), + from: [0u8; 32].into(), + amount: Balance::default(), + }; + Ok(Vec::from([transfer])) + } +} + +pub struct MockParentchainEventHandler {} + +impl HandleParentchainEvents + for MockParentchainEventHandler +where + Executor: IndirectExecutor, +{ + fn handle_events( + _: &Executor, + _: impl itp_types::parentchain::FilterEvents, + _: &AccountId, + ) -> core::result::Result<(), Error> { + Ok(()) + } +} + +/// Arguments of the Integritee-Parachain's shield fund dispatchable. +#[derive(Debug, Clone, Encode, Decode, Eq, PartialEq)] +pub struct ShieldFundsArgs { + account_encrypted: Vec, + amount: Balance, + shard: ShardIdentifier, +} + +impl> + IndirectDispatch for ShieldFundsArgs +{ + type Args = (); + fn dispatch(&self, executor: &Executor, _args: Self::Args) -> ICResult<()> { + info!("Found ShieldFunds extrinsic in block: \nAccount Encrypted {:?} \nAmount: {} \nShard: {}", + self.account_encrypted, self.amount, bs58::encode(self.shard.encode()).into_string()); + + debug!("decrypt the account id"); + let account_vec = executor.decrypt(&self.account_encrypted)?; + let _account = AccountId::decode(&mut account_vec.as_slice())?; + + let enclave_account_id = executor.get_enclave_account()?; + let trusted_call = TrustedCallMock::noop(enclave_account_id.into()); + let signed_trusted_call = executor.sign_call_with_self(&trusted_call, &self.shard)?; + let trusted_operation = + TrustedOperation::::indirect_call( + signed_trusted_call, + ); + + let encrypted_trusted_call = executor.encrypt(&trusted_operation.encode())?; + executor.submit_trusted_call(self.shard, encrypted_trusted_call); + Ok(()) + } +} + +#[derive(Debug, Clone, Encode, Decode, Eq, PartialEq)] +pub struct InvokeArgs { + request: RsaRequest, +} + +impl> + IndirectDispatch for InvokeArgs +{ + type Args = (); + fn dispatch(&self, executor: &Executor, _args: Self::Args) -> ICResult<()> { + log::debug!("Found trusted call extrinsic, submitting it to the top pool"); + executor.submit_trusted_call(self.request.shard(), self.request.payload().to_vec()); + Ok(()) + } +} diff --git a/bitacross-worker/core/parentchain/indirect-calls-executor/src/traits.rs b/bitacross-worker/core/parentchain/indirect-calls-executor/src/traits.rs new file mode 100644 index 0000000000..ed1850b0c9 --- /dev/null +++ b/bitacross-worker/core/parentchain/indirect-calls-executor/src/traits.rs @@ -0,0 +1,59 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{error::Result, Error}; +use codec::{Decode, Encode}; +use core::fmt::Debug; +use itp_stf_primitives::traits::{IndirectExecutor, TrustedCallVerification}; +use itp_types::{OpaqueCall, H256}; +use sp_runtime::traits::{Block as ParentchainBlockTrait, Header}; +use std::vec::Vec; + +/// Trait to execute the indirect calls found in the extrinsics of a block. +pub trait ExecuteIndirectCalls { + /// Scans blocks for extrinsics that ask the enclave to execute some actions. + /// Executes indirect invocation calls, including shielding and unshielding calls. + /// Returns all unshielding call confirmations as opaque calls and the hashes of executed shielding calls. + fn execute_indirect_calls_in_extrinsics( + &self, + block: &ParentchainBlock, + events: &[u8], + ) -> Result + where + ParentchainBlock: ParentchainBlockTrait; + + /// Creates a processed_parentchain_block extrinsic for a given parentchain block hash and the merkle executed extrinsics. + /// + /// Calculates the merkle root of the extrinsics. In case no extrinsics are supplied, the root will be a hash filled with zeros. + fn create_processed_parentchain_block_call( + &self, + block_hash: H256, + extrinsics: Vec, + block_number: <::Header as Header>::Number, + ) -> Result + where + ParentchainBlock: ParentchainBlockTrait; +} + +/// Trait that should be implemented on indirect calls to be executed. +pub trait IndirectDispatch, TCS> +where + TCS: PartialEq + Encode + Decode + Debug + Clone + Send + Sync + TrustedCallVerification, +{ + type Args; + fn dispatch(&self, executor: &E, args: Self::Args) -> Result<()>; +} diff --git a/bitacross-worker/core/parentchain/light-client/Cargo.toml b/bitacross-worker/core/parentchain/light-client/Cargo.toml new file mode 100644 index 0000000000..4573a60065 --- /dev/null +++ b/bitacross-worker/core/parentchain/light-client/Cargo.toml @@ -0,0 +1,71 @@ +[package] +name = "itc-parentchain-light-client" +version = "0.9.0" +authors = ['Trust Computing GmbH ', 'Integritee AG '] +edition = "2021" + +[dependencies] +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive", "chain-error"] } +finality-grandpa = { version = "0.16.0", default-features = false, features = ["derive-codec"] } +log = { version = "0.4", default-features = false } +thiserror = { version = "1.0.26", optional = true } + +# sgx-deps +sgx_tstd = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git", features = ["untrusted_fs"], optional = true } +sgx_types = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git" } +thiserror-sgx = { package = "thiserror", git = "https://github.com/mesalock-linux/thiserror-sgx", tag = "sgx_1.1.3", optional = true } + +# local deps +itp-ocall-api = { path = "../../../core-primitives/ocall-api", default-features = false } +itp-sgx-io = { path = "../../../core-primitives/sgx/io", default-features = false } +itp-storage = { path = "../../../core-primitives/storage", default-features = false } +itp-types = { path = "../../../core-primitives/types", default-features = false } + +# substrate deps +sp-consensus-grandpa = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } +sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } + +# test & mock dependencies +itc-parentchain-test = { optional = true, default-features = false, path = "../../../core/parentchain/test" } +# We can't really make this optional due to feature flag complexities. +itp-sgx-temp-dir = { version = "0.1", default-features = false, path = "../../../core-primitives/sgx/temp-dir" } +itp-test = { optional = true, default-features = false, features = ["sgx"], path = "../../../core-primitives/test" } + +[dev-dependencies] +itc-parentchain-test = { path = "../../../core/parentchain/test" } +itp-test = { path = "../../../core-primitives/test" } +itp-sgx-temp-dir = { version = "0.1", path = "../../../core-primitives/sgx/temp-dir" } + + +[features] +default = ["std"] +std = [ + "codec/std", + "log/std", + "finality-grandpa/std", + "thiserror", + + # substrate deps + "sp-consensus-grandpa/std", + "sp-runtime/std", + + # local deps + "itp-ocall-api/std", + "itp-storage/std", + "itp-sgx-io/std", + "itp-types/std", + # mock deps + "itp-sgx-temp-dir/std", +] +sgx = [ + "sgx_tstd", + "thiserror-sgx", + "itp-sgx-io/sgx", + "itp-storage/sgx", + "itp-sgx-temp-dir/sgx", +] +mocks = [ + "itc-parentchain-test", +] + +test = ["mocks", "itp-test"] diff --git a/bitacross-worker/core/parentchain/light-client/src/concurrent_access.rs b/bitacross-worker/core/parentchain/light-client/src/concurrent_access.rs new file mode 100644 index 0000000000..fda60d74b0 --- /dev/null +++ b/bitacross-worker/core/parentchain/light-client/src/concurrent_access.rs @@ -0,0 +1,143 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +//! Concurrent access mechanisms that ensure mutually exclusive read/write access +//! to the light-client (validator) by employing RwLocks under the hood. + +#[cfg(feature = "sgx")] +use std::sync::SgxRwLock as RwLock; + +#[cfg(feature = "std")] +use std::sync::RwLock; + +use crate::{ + error::{Error, Result}, + ExtrinsicSender as ExtrinsicSenderTrait, LightClientSealing, LightClientState, + LightValidationState, Validator as ValidatorTrait, +}; +use finality_grandpa::BlockNumberOps; +use itp_types::parentchain::{IdentifyParentchain, ParentchainId}; +use sp_runtime::traits::{Block as ParentchainBlockTrait, NumberFor}; +use std::{marker::PhantomData, sync::Arc}; + +/// Retrieve an exclusive lock on a validator for either read or write access. +/// +/// In order to hide the whole locks mechanics, we provide an interface that allows executing +/// either a mutating, or a non-mutating function on the validator. +/// The reason we have this additional wrapper around `SealedIO`, is that we need +/// to guard against concurrent access by using RWLocks (which `SealedIO` does not do). +pub trait ValidatorAccess +where + ParentchainBlock: ParentchainBlockTrait, + NumberFor: BlockNumberOps, +{ + type ValidatorType: ValidatorTrait + + LightClientState + + ExtrinsicSenderTrait; + + /// Execute a non-mutating function on the validator. + fn execute_on_validator(&self, getter_function: F) -> Result + where + F: FnOnce(&Self::ValidatorType) -> Result; + + /// Execute a mutating function on the validator. + fn execute_mut_on_validator(&self, mutating_function: F) -> Result + where + F: FnOnce(&mut Self::ValidatorType) -> Result; +} + +/// Implementation of a validator access based on a global lock and corresponding file. +#[derive(Debug)] +pub struct ValidatorAccessor { + seal: Arc, + light_validation: RwLock, + _phantom: PhantomData<(LightClientSeal, Validator, ParentchainBlock)>, +} + +impl + ValidatorAccessor +{ + pub fn new(validator: Validator, seal: Arc) -> Self { + ValidatorAccessor { + light_validation: RwLock::new(validator), + seal, + _phantom: Default::default(), + } + } +} + +impl IdentifyParentchain + for ValidatorAccessor +{ + fn parentchain_id(&self) -> ParentchainId { + (*self.seal).parentchain_id() + } +} + +impl ValidatorAccess + for ValidatorAccessor +where + Validator: ValidatorTrait + + LightClientState + + ExtrinsicSenderTrait, + Seal: LightClientSealing>, + ParentchainBlock: ParentchainBlockTrait, + NumberFor: BlockNumberOps, +{ + type ValidatorType = Validator; + + fn execute_on_validator(&self, getter_function: F) -> Result + where + F: FnOnce(&Self::ValidatorType) -> Result, + { + let light_validation_lock = + self.light_validation.write().map_err(|_| Error::PoisonedLock)?; + getter_function(&light_validation_lock) + } + + fn execute_mut_on_validator(&self, mutating_function: F) -> Result + where + F: FnOnce(&mut Self::ValidatorType) -> Result, + { + let mut light_validation_lock = + self.light_validation.write().map_err(|_| Error::PoisonedLock)?; + let result = mutating_function(&mut light_validation_lock); + self.seal.seal(light_validation_lock.get_state())?; + result + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::mocks::{ + validator_mock::ValidatorMock, validator_mock_seal::LightValidationStateSealMock, + }; + use itp_types::Block; + + type TestAccessor = ValidatorAccessor; + + #[test] + fn execute_with_and_without_mut_in_single_thread_works() { + let validator_mock = ValidatorMock::default(); + let seal = LightValidationStateSealMock::new(); + let accessor = TestAccessor::new(validator_mock, seal.into()); + + let _read_result = accessor.execute_on_validator(|_v| Ok(())).unwrap(); + let _write_result = accessor.execute_mut_on_validator(|_v| Ok(())).unwrap(); + } +} diff --git a/bitacross-worker/core/parentchain/light-client/src/error.rs b/bitacross-worker/core/parentchain/light-client/src/error.rs new file mode 100644 index 0000000000..8f0276d133 --- /dev/null +++ b/bitacross-worker/core/parentchain/light-client/src/error.rs @@ -0,0 +1,84 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{boxed::Box, string::String}; + +use sgx_types::sgx_status_t; +#[cfg(all(not(feature = "std"), feature = "sgx"))] +use thiserror_sgx as thiserror; + +pub type Result = core::result::Result; + +/// Substrate Client error +#[derive(Debug, PartialEq, Eq, thiserror::Error)] +pub enum JustificationError { + #[error("Error decoding justification")] + JustificationDecode, + /// Justification for header is correctly encoded, but invalid. + #[error("bad justification for header: {0}")] + BadJustification(String), + #[error("Invalid authorities set")] + InvalidAuthoritiesSet, +} + +#[derive(Debug, thiserror::Error)] +pub enum Error { + #[error("Genesis not found")] + NoGenesis, + #[error(transparent)] + Storage(#[from] itp_storage::Error), + #[error("Validator set mismatch")] + ValidatorSetMismatch, + #[error("Invalid ancestry proof")] + InvalidAncestryProof, + #[error("Invalid Finality Proof: {0}")] + InvalidFinalityProof(#[from] JustificationError), + #[error("Header ancestry mismatch")] + HeaderAncestryMismatch, + #[error("Poisoned validator lock")] + PoisonedLock, + #[error("No Justification found")] + NoJustificationFound, + #[error(transparent)] + Other(#[from] Box), +} + +impl From for Error { + fn from(e: std::io::Error) -> Self { + Self::Other(e.into()) + } +} + +impl From for Error { + #[cfg(feature = "std")] + fn from(e: codec::Error) -> Self { + Self::Other(e.into()) + } + + #[cfg(not(feature = "std"))] + fn from(e: codec::Error) -> Self { + Self::Other(format!("{:?}", e).into()) + } +} + +impl From for sgx_status_t { + /// return sgx_status for top level enclave functions + fn from(error: Error) -> sgx_status_t { + log::warn!("LightClientError into sgx_status_t: {:?}", error); + sgx_status_t::SGX_ERROR_UNEXPECTED + } +} diff --git a/bitacross-worker/core/parentchain/light-client/src/finality.rs b/bitacross-worker/core/parentchain/light-client/src/finality.rs new file mode 100644 index 0000000000..95371a8863 --- /dev/null +++ b/bitacross-worker/core/parentchain/light-client/src/finality.rs @@ -0,0 +1,187 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +//! Finality for determination of the light client validation. + +use crate::{ + error::Result, + grandpa_log, + justification::GrandpaJustification, + state::{RelayState, ScheduledChangeAtBlock}, + AuthorityList, Error, NumberFor, +}; +use finality_grandpa::voter_set::VoterSet; +use log::*; +pub use sp_consensus_grandpa::SetId; +use sp_consensus_grandpa::{AuthorityId, ScheduledChange, GRANDPA_ENGINE_ID}; +use sp_runtime::{ + generic::Digest, + traits::{Block as ParentchainBlockTrait, Header as HeaderTrait}, + EncodedJustification, Justifications, +}; + +#[derive(Default)] +pub struct GrandpaFinality; + +#[derive(Default)] +pub struct ParachainFinality; + +pub trait Finality { + fn validate( + &self, + header: Block::Header, + validator_set: &AuthorityList, + validator_set_id: SetId, + justifications: Option, + relay: &mut RelayState, + ) -> Result<()>; +} + +impl Finality for ParachainFinality +where + Block: ParentchainBlockTrait, +{ + fn validate( + &self, + _header: Block::Header, + _validator_set: &AuthorityList, + _validator_set_id: SetId, + _justifications: Option, + _relay: &mut RelayState, + ) -> Result<()> { + Ok(()) + } +} + +impl Finality for GrandpaFinality +where + Block: ParentchainBlockTrait, + NumberFor: finality_grandpa::BlockNumberOps, +{ + fn validate( + &self, + header: Block::Header, + validator_set: &AuthorityList, + validator_set_id: SetId, + justifications: Option, + relay: &mut RelayState, + ) -> Result<()> { + Self::apply_validator_set_change(relay, &header); + + // Check that the header has been finalized + let voter_set = + VoterSet::new(validator_set.clone().into_iter()).expect("VoterSet may not be empty"); + + // ensure justifications is a grandpa justification + let grandpa_justification = + justifications.and_then(|just| just.into_justification(GRANDPA_ENGINE_ID)); + + let block_hash = header.hash(); + let block_num = *header.number(); + + match grandpa_justification { + Some(justification) => { + if let Err(err) = Self::verify_grandpa_proof::( + justification, + block_hash, + block_num, + validator_set_id, + &voter_set, + ) { + // FIXME: Printing error upon invalid justification, but this will need a better fix + // see issue #353 + error!("Block {:?} contained invalid justification: {:?}", block_num, err); + relay.unjustified_headers.push(block_hash); + relay.set_last_finalized_block_header(header); + return Err(err) + } + Self::schedule_validator_set_change(relay, &header); + + Ok(()) + }, + None => { + relay.unjustified_headers.push(block_hash); + relay.set_last_finalized_block_header(header); + + debug!( + "Syncing finalized block without grandpa proof. Amount of unjustified headers: {}", + relay.unjustified_headers.len() + ); + Err(Error::NoJustificationFound) + }, + } + } +} + +impl GrandpaFinality { + fn apply_validator_set_change( + relay: &mut RelayState, + header: &Block::Header, + ) { + if let Some(change) = relay.scheduled_change.take() { + if &change.at_block == header.number() { + relay.current_validator_set = change.next_authority_list; + relay.current_validator_set_id += 1; + } + } + } + + fn schedule_validator_set_change( + relay: &mut RelayState, + header: &Block::Header, + ) { + if let Some(log) = pending_change::(header.digest()) { + if relay.scheduled_change.is_some() { + error!( + "Tried to scheduled authorities change even though one is already scheduled!!" + ); // should not happen if blockchain is configured properly + } else { + relay.scheduled_change = Some(ScheduledChangeAtBlock { + at_block: log.delay + *header.number(), + next_authority_list: log.next_authorities, + }) + } + } + } + + fn verify_grandpa_proof( + encoded_justification: EncodedJustification, + hash: Block::Hash, + number: NumberFor, + set_id: u64, + voters: &VoterSet, + ) -> Result<()> + where + NumberFor: finality_grandpa::BlockNumberOps, + { + // We don't really care about the justification, as long as it's valid + let _ = GrandpaJustification::::decode_and_verify_finalizes( + &encoded_justification, + (hash, number), + set_id, + voters, + )?; + + Ok(()) + } +} + +fn pending_change( + digest: &Digest, +) -> Option>> { + grandpa_log::(digest).and_then(|log| log.try_into_change()) +} diff --git a/bitacross-worker/core/parentchain/light-client/src/io.rs b/bitacross-worker/core/parentchain/light-client/src/io.rs new file mode 100644 index 0000000000..df3ca294a6 --- /dev/null +++ b/bitacross-worker/core/parentchain/light-client/src/io.rs @@ -0,0 +1,386 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{ + error::{Error, Result}, + finality::{Finality, GrandpaFinality, ParachainFinality}, + light_client_init_params::{GrandpaParams, SimpleParams}, + light_validation::{check_validator_set_proof, LightValidation}, + state::RelayState, + LightClientSealing, LightClientState, LightValidationState, NumberFor, Validator, +}; +use codec::{Decode, Encode}; +use core::{fmt::Debug, marker::PhantomData}; +use itp_ocall_api::EnclaveOnChainOCallApi; +use itp_sgx_io::{seal, unseal}; +use itp_types::parentchain::{IdentifyParentchain, ParentchainId}; +use log::*; +use sp_runtime::traits::{Block, Header}; +use std::{ + boxed::Box, + fs, + path::{Path, PathBuf}, + sgxfs::SgxFile, + sync::Arc, +}; + +#[cfg(feature = "sgx")] +use std::sync::SgxRwLock as RwLock; + +#[cfg(feature = "std")] +use std::sync::RwLock; + +pub const DB_FILE: &str = "db.bin"; +pub const BACKUP_FILE: &str = "db.bin.backup"; + +#[derive(Clone, Debug)] +pub struct LightClientStateSeal { + base_path: PathBuf, + db_path: PathBuf, + backup_path: PathBuf, + parentchain_id: ParentchainId, + _phantom: PhantomData<(B, LightClientState)>, +} + +impl LightClientStateSeal { + pub fn new(base_path: PathBuf, parentchain_id: ParentchainId) -> Result { + std::fs::create_dir_all(&base_path)?; + Ok(Self { + base_path: base_path.clone(), + db_path: base_path.clone().join(DB_FILE), + backup_path: base_path.join(BACKUP_FILE), + parentchain_id, + _phantom: Default::default(), + }) + } + + pub fn base_path(&self) -> &Path { + &self.base_path + } + + pub fn db_path(&self) -> &Path { + &self.db_path + } + + pub fn backup_path(&self) -> &Path { + &self.backup_path + } + + pub fn backup(&self) -> Result<()> { + if self.db_path().exists() { + let _bytes = fs::copy(self.db_path(), self.backup_path())?; + } else { + info!("{} does not exist yet, skipping backup...", self.db_path().display()) + } + Ok(()) + } +} + +impl IdentifyParentchain for LightClientStateSeal { + fn parentchain_id(&self) -> ParentchainId { + self.parentchain_id + } +} + +impl LightClientSealing + for LightClientStateSeal +{ + type LightClientState = LightClientState; + + fn seal(&self, unsealed: &LightClientState) -> Result<()> { + trace!( + "[{:?}] Backup light client state to {}", + self.parentchain_id, + self.backup_path().display() + ); + + if let Err(e) = self.backup() { + warn!( + "[{:?}] Could not backup previous light client state: Error: {}", + self.parentchain_id, e + ); + }; + + trace!( + "[{:?}] Seal light client State. Current state: {:?}", + self.parentchain_id, + unsealed + ); + Ok(unsealed.using_encoded(|bytes| seal(bytes, self.db_path()))?) + } + + fn unseal(&self) -> Result { + Ok(unseal(self.db_path()).map(|b| Decode::decode(&mut b.as_slice()))??) + } + + fn exists(&self) -> bool { + SgxFile::open(self.db_path()).is_ok() + } + + fn path(&self) -> &Path { + self.db_path() + } +} + +/// Same as [LightClientStateSeal], but it ensures that no concurrent write operations are done +/// accross different threads. +#[derive(Debug)] +pub struct LightClientStateSealSync { + seal: LightClientStateSeal, + _rw_lock: RwLock<()>, +} + +impl LightClientStateSealSync { + pub fn new(base_path: PathBuf, parentchain_id: ParentchainId) -> Result { + Ok(Self { + seal: LightClientStateSeal::new(base_path, parentchain_id)?, + _rw_lock: RwLock::new(()), + }) + } +} + +impl IdentifyParentchain for LightClientStateSealSync { + fn parentchain_id(&self) -> ParentchainId { + self.seal.parentchain_id + } +} + +impl LightClientSealing + for LightClientStateSealSync +{ + type LightClientState = LightClientState; + + fn seal(&self, unsealed: &LightClientState) -> Result<()> { + let _lock = self._rw_lock.write().map_err(|_| Error::PoisonedLock)?; + self.seal.seal(unsealed) + } + + fn unseal(&self) -> Result { + let _lock = self._rw_lock.read().map_err(|_| Error::PoisonedLock)?; + self.seal.unseal() + } + + fn exists(&self) -> bool { + self.seal.exists() + } + + fn path(&self) -> &Path { + self.seal.path() + } +} + +// FIXME: This is a lot of duplicate code for the initialization of two +// different but sameish light clients. Should be tackled with #1081 +pub fn read_or_init_grandpa_validator( + params: GrandpaParams, + ocall_api: Arc, + seal: &LightClientSeal, + parentchain_id: ParentchainId, +) -> Result> +where + B: Block, + NumberFor: finality_grandpa::BlockNumberOps, + OCallApi: EnclaveOnChainOCallApi, + LightClientSeal: + LightClientSealing> + IdentifyParentchain, +{ + check_validator_set_proof::( + params.genesis_header.state_root(), + params.authority_proof, + ¶ms.authorities, + )?; + + if !seal.exists() { + info!( + "[{:?}] ChainRelay DB not found, creating new! {}", + seal.parentchain_id(), + seal.path().display() + ); + let validator = init_grandpa_validator::( + ocall_api, + RelayState::new(params.genesis_header, params.authorities).into(), + parentchain_id, + )?; + seal.seal(validator.get_state())?; + return Ok(validator) + } + + let validation_state = seal.unseal()?; + let genesis_hash = validation_state.genesis_hash()?; + + let init_state = if genesis_hash == params.genesis_header.hash() { + info!( + "[{:?}] Found already initialized light client with Genesis Hash: {:?}", + seal.parentchain_id(), + genesis_hash + ); + validation_state + } else { + info!( + "Previous light client db belongs to another parentchain genesis. Creating new: {:?}", + genesis_hash + ); + RelayState::new(params.genesis_header, params.authorities).into() + }; + + let validator = init_grandpa_validator::(ocall_api, init_state, parentchain_id)?; + + info!("[{:?}] light client state: {:?}", seal.parentchain_id(), validator); + + seal.seal(validator.get_state())?; + Ok(validator) +} + +pub fn read_or_init_parachain_validator( + params: SimpleParams, + ocall_api: Arc, + seal: &LightClientSeal, + parentchain_id: ParentchainId, +) -> Result> +where + B: Block, + NumberFor: finality_grandpa::BlockNumberOps, + OCallApi: EnclaveOnChainOCallApi, + LightClientSeal: LightClientSealing>, +{ + if !seal.exists() { + info!("[Enclave] ChainRelay DB not found, creating new! {}", seal.path().display()); + let validator = init_parachain_validator::( + ocall_api, + RelayState::new(params.genesis_header, Default::default()).into(), + parentchain_id, + )?; + seal.seal(validator.get_state())?; + return Ok(validator) + } + + let validation_state = seal.unseal()?; + let genesis_hash = validation_state.genesis_hash()?; + + let init_state = if genesis_hash == params.genesis_header.hash() { + info!("Found already initialized light client with Genesis Hash: {:?}", genesis_hash); + validation_state + } else { + info!( + "Previous light client db belongs to another parentchain genesis. Creating new: {:?}", + genesis_hash + ); + RelayState::new(params.genesis_header, vec![]).into() + }; + + let validator = init_parachain_validator::(ocall_api, init_state, parentchain_id)?; + info!("light client state: {:?}", validator); + + seal.seal(validator.get_state())?; + Ok(validator) +} + +fn init_grandpa_validator( + ocall_api: Arc, + state: LightValidationState, + parentchain_id: ParentchainId, +) -> Result> +where + B: Block, + NumberFor: finality_grandpa::BlockNumberOps, + OCallApi: EnclaveOnChainOCallApi, +{ + let finality: Arc + Sync + Send + 'static>> = + Arc::new(Box::new(GrandpaFinality)); + + let validator = LightValidation::::new(ocall_api, finality, state, parentchain_id); + + Ok(validator) +} + +fn init_parachain_validator( + ocall_api: Arc, + state: LightValidationState, + parentchain_id: ParentchainId, +) -> Result> +where + B: Block, + NumberFor: finality_grandpa::BlockNumberOps, + OCallApi: EnclaveOnChainOCallApi, +{ + let finality: Arc + Sync + Send + 'static>> = + Arc::new(Box::new(ParachainFinality)); + + let validator = LightValidation::::new(ocall_api, finality, state, parentchain_id); + Ok(validator) +} + +#[cfg(feature = "test")] +pub mod sgx_tests { + use super::{read_or_init_parachain_validator, Arc, LightClientStateSeal, RelayState}; + use crate::{ + light_client_init_params::SimpleParams, LightClientSealing, LightClientState, + LightValidationState, + }; + use itc_parentchain_test::{Block, Header, ParentchainHeaderBuilder}; + use itp_sgx_temp_dir::TempDir; + use itp_test::mock::onchain_mock::OnchainMock; + use itp_types::parentchain::ParentchainId; + use sp_runtime::OpaqueExtrinsic; + + type TestBlock = Block; + type TestSeal = LightClientStateSeal>; + + fn default_simple_params() -> SimpleParams

{ + SimpleParams { genesis_header: ParentchainHeaderBuilder::default().build() } + } + + pub fn init_parachain_light_client_works() { + let parachain_params = default_simple_params(); + let temp_dir = TempDir::with_prefix("init_parachain_light_client_works").unwrap(); + let seal = TestSeal::new(temp_dir.path().to_path_buf(), ParentchainId::Litentry).unwrap(); + + let validator = read_or_init_parachain_validator::( + parachain_params.clone(), + Arc::new(OnchainMock::default()), + &seal, + ParentchainId::Litentry, + ) + .unwrap(); + + assert_eq!(validator.genesis_hash().unwrap(), parachain_params.genesis_header.hash()); + assert_eq!(validator.latest_finalized_header().unwrap(), parachain_params.genesis_header); + assert_eq!( + validator.penultimate_finalized_block_header().unwrap(), + parachain_params.genesis_header + ); + } + + pub fn sealing_creates_backup() { + let params = default_simple_params(); + let temp_dir = TempDir::with_prefix("sealing_creates_backup").unwrap(); + let seal = TestSeal::new(temp_dir.path().to_path_buf(), ParentchainId::Litentry).unwrap(); + let state = RelayState::new(params.genesis_header, Default::default()).into(); + + seal.seal(&state).unwrap(); + let unsealed = seal.unseal().unwrap(); + + assert_eq!(state, unsealed); + + // The first seal operation doesn't create a backup, as there is nothing to backup. + seal.seal(&unsealed).unwrap(); + assert!(seal.backup_path().exists()) + } + + // Todo #1293: add a unit test for the grandpa validator, but this needs a little effort for + // setting up correct finality params. +} diff --git a/bitacross-worker/core/parentchain/light-client/src/justification.rs b/bitacross-worker/core/parentchain/light-client/src/justification.rs new file mode 100644 index 0000000000..5e6f21f78c --- /dev/null +++ b/bitacross-worker/core/parentchain/light-client/src/justification.rs @@ -0,0 +1,229 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{ + collections::{HashMap, HashSet}, + string::ToString, + vec::Vec, +}; + +use super::error::JustificationError as ClientError; +use codec::{Decode, Encode}; +use finality_grandpa::{voter_set::VoterSet, Error as GrandpaError}; +use log::*; +use sp_consensus_grandpa::{AuthorityId, AuthorityList, AuthoritySignature}; +use sp_runtime::traits::{Block as BlockT, Header as HeaderT, NumberFor}; + +/// A commit message for this chain's block type. +pub type Commit = finality_grandpa::Commit< + ::Hash, + NumberFor, + AuthoritySignature, + AuthorityId, +>; + +/// A GRANDPA justification for block finality, it includes a commit message and +/// an ancestry proof including all headers routing all precommit target blocks +/// to the commit target block. Due to the current voting strategy the precommit +/// targets should be the same as the commit target, since honest voters don't +/// vote past authority set change blocks. +/// +/// This is meant to be stored in the db and passed around the network to other +/// nodes, and are used by syncing nodes to prove authority set handoffs. +#[derive(Clone, Encode, Decode, PartialEq, Eq)] +pub struct GrandpaJustification { + round: u64, + pub(crate) commit: Commit, + votes_ancestries: Vec, +} + +impl GrandpaJustification { + /// Decode a GRANDPA justification and validate the commit and the votes' + /// ancestry proofs finalize the given block. + pub fn decode_and_verify_finalizes( + encoded: &[u8], + finalized_target: (Block::Hash, NumberFor), + set_id: u64, + voters: &VoterSet, + ) -> Result, ClientError> + where + NumberFor: finality_grandpa::BlockNumberOps, + { + let justification = GrandpaJustification::::decode(&mut &*encoded) + .map_err(|_| ClientError::JustificationDecode)?; + + let justificated_commit = + (justification.commit.target_hash, justification.commit.target_number); + + if justificated_commit != finalized_target { + Err(ClientError::BadJustification( + "invalid commit target in grandpa justification".to_string(), + )) + } else { + justification.verify_with_voter_set(set_id, voters).map(|_| justification) + } + } + + /// Validate the commit and the votes' ancestry proofs. + pub fn verify(&self, set_id: u64, authorities: AuthorityList) -> Result<(), ClientError> + where + NumberFor: finality_grandpa::BlockNumberOps, + { + let voters = + VoterSet::new(authorities.into_iter()).ok_or(ClientError::InvalidAuthoritiesSet)?; + + self.verify_with_voter_set(set_id, &voters) + } + + fn validate_commit( + &self, + voters: &VoterSet, + ancestry_chain: &AncestryChain, + ) -> Result<(), ClientError> + where + NumberFor: finality_grandpa::BlockNumberOps, + { + match finality_grandpa::validate_commit(&self.commit, voters, ancestry_chain) { + Ok(ref result) if result.is_valid() => Ok(()), + _ => Err(ClientError::BadJustification( + "invalid commit in grandpa justification".to_string(), + )), + } + } + + fn fill_visited_hashes( + &self, + ancestry_chain: &AncestryChain, + precommit_target_hash: Block::Hash, + visited_hashes: &mut HashSet, + ) -> Result<(), ClientError> + where + NumberFor: finality_grandpa::BlockNumberOps, + { + use finality_grandpa::Chain; + if let Ok(route) = ancestry_chain.ancestry(self.commit.target_hash, precommit_target_hash) { + // ancestry starts from parent hash but the precommit target hash has been visited + visited_hashes.insert(precommit_target_hash); + visited_hashes.extend(route.iter()); + Ok(()) + } else { + Err(ClientError::BadJustification( + "invalid precommit ancestry proof in grandpa justification".to_string(), + )) + } + } + + /// Validate the commit and the votes' ancestry proofs. + pub(crate) fn verify_with_voter_set( + &self, + set_id: u64, + voters: &VoterSet, + ) -> Result<(), ClientError> + where + NumberFor: finality_grandpa::BlockNumberOps, + { + let ancestry_chain = AncestryChain::::new(&self.votes_ancestries); + + self.validate_commit(voters, &ancestry_chain)?; + + let mut buf = Vec::new(); + let mut visited_hashes = HashSet::new(); + for signed in self.commit.precommits.iter() { + if !sp_consensus_grandpa::check_message_signature_with_buffer( + &finality_grandpa::Message::Precommit(signed.precommit.clone()), + &signed.id, + &signed.signature, + self.round, + set_id, + &mut buf, + ) { + debug!("Bad signature on message from {:?}", &signed.id); + return Err(ClientError::BadJustification( + "invalid signature for precommit in grandpa justification".to_string(), + )) + } + + if self.commit.target_hash == signed.precommit.target_hash { + continue + } + + self.fill_visited_hashes( + &ancestry_chain, + signed.precommit.target_hash, + &mut visited_hashes, + )?; + } + + let ancestry_hashes = + self.votes_ancestries.iter().map(|h: &Block::Header| h.hash()).collect(); + + if visited_hashes != ancestry_hashes { + return Err(ClientError::BadJustification( + "invalid precommit ancestries in grandpa justification with unused headers" + .to_string(), + )) + } + + Ok(()) + } + + /// The target block number and hash that this justifications proves finality for. + pub fn target(&self) -> (NumberFor, Block::Hash) { + (self.commit.target_number, self.commit.target_hash) + } +} + +/// A utility trait implementing `finality_grandpa::Chain` using a given set of headers. +/// This is useful when validating commits, using the given set of headers to +/// verify a valid ancestry route to the target commit block. +struct AncestryChain { + ancestry: HashMap, +} + +impl AncestryChain { + fn new(ancestry: &[Block::Header]) -> AncestryChain { + let ancestry: HashMap<_, _> = + ancestry.iter().cloned().map(|h: Block::Header| (h.hash(), h)).collect(); + + AncestryChain { ancestry } + } +} + +impl finality_grandpa::Chain> for AncestryChain +where + NumberFor: finality_grandpa::BlockNumberOps, +{ + fn ancestry( + &self, + base: Block::Hash, + block: Block::Hash, + ) -> Result, GrandpaError> { + let mut ancestors = Vec::new(); + let mut current_hash = block; + while current_hash != base { + if let Some(current_header) = self.ancestry.get(¤t_hash) { + current_hash = *current_header.parent_hash(); + ancestors.push(current_hash); + } else { + return Err(GrandpaError::NotDescendent) + } + } + ancestors.pop(); // remove the base + + Ok(ancestors) + } +} diff --git a/bitacross-worker/core/parentchain/light-client/src/lib.rs b/bitacross-worker/core/parentchain/light-client/src/lib.rs new file mode 100644 index 0000000000..64b46c480f --- /dev/null +++ b/bitacross-worker/core/parentchain/light-client/src/lib.rs @@ -0,0 +1,111 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +//! Light-client crate that imports and verifies parentchain blocks. + +#![allow(unused)] +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg(all(feature = "std", feature = "sgx"))] +compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the same time"); + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +#[macro_use] +extern crate sgx_tstd as std; + +// Re-export useful types. +pub use finality_grandpa::BlockNumberOps; +pub use sp_consensus_grandpa::{AuthorityList, SetId}; + +use crate::light_validation_state::LightValidationState; +use error::Error; +use sp_consensus_grandpa::{AuthorityId, AuthorityWeight, ConsensusLog, GRANDPA_ENGINE_ID}; +use sp_runtime::{ + generic::{Digest, OpaqueDigestItemId, SignedBlock}, + traits::{Block as ParentchainBlockTrait, Header as HeaderTrait}, + OpaqueExtrinsic, +}; +use std::{path::Path, vec::Vec}; + +pub mod concurrent_access; +pub mod error; +pub mod finality; +pub mod justification; +pub mod light_client_init_params; +pub mod light_validation; +pub mod light_validation_state; +pub mod state; + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +pub mod io; + +#[cfg(any(test, feature = "mocks"))] +pub mod mocks; + +pub type RelayId = u64; + +pub type AuthorityListRef<'a> = &'a [(AuthorityId, AuthorityWeight)]; + +// disambiguate associated types +/// Block number type +pub type NumberFor = <::Header as HeaderTrait>::Number; +/// Hash type of Block +pub type HashFor = <::Header as HeaderTrait>::Hash; +/// Hashing function used to produce `HashOf` +pub type HashingFor = <::Header as HeaderTrait>::Hashing; + +/// Validator trait +pub trait Validator +where + NumberFor: finality_grandpa::BlockNumberOps, +{ + fn submit_block(&mut self, signed_block: &SignedBlock) -> Result<(), Error>; + + fn get_state(&self) -> &LightValidationState; + + fn set_ignore_validation_until(&mut self, until: u32) -> Result<(), Error>; +} + +pub trait ExtrinsicSender { + /// Sends encoded extrinsics to the parentchain and cache them internally for later confirmation. + fn send_extrinsics(&mut self, extrinsics: Vec) -> Result<(), Error>; +} + +pub trait LightClientState { + fn genesis_hash(&self) -> Result, Error>; + + fn latest_finalized_header(&self) -> Result; + + // Todo: Check if we still need this after #423 + fn penultimate_finalized_block_header(&self) -> Result; +} + +pub trait LightClientSealing { + type LightClientState; + + fn seal(&self, state: &Self::LightClientState) -> Result<(), Error>; + fn unseal(&self) -> Result; + fn exists(&self) -> bool; + fn path(&self) -> &Path; +} + +pub fn grandpa_log( + digest: &Digest, +) -> Option>> { + let id = OpaqueDigestItemId::Consensus(&GRANDPA_ENGINE_ID); + digest.convert_first(|l| l.try_to::>>(id)) +} diff --git a/bitacross-worker/core/parentchain/light-client/src/light_client_init_params.rs b/bitacross-worker/core/parentchain/light-client/src/light_client_init_params.rs new file mode 100644 index 0000000000..114d684382 --- /dev/null +++ b/bitacross-worker/core/parentchain/light-client/src/light_client_init_params.rs @@ -0,0 +1,49 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 sp_consensus_grandpa::AuthorityList; +use std::vec::Vec; + +#[derive(Encode, Decode, Clone)] +pub struct GrandpaParams
{ + pub genesis_header: Header, + pub authorities: AuthorityList, + pub authority_proof: Vec>, +} + +impl
GrandpaParams
{ + pub fn new( + genesis_header: Header, + authorities: AuthorityList, + authority_proof: Vec>, + ) -> Self { + Self { genesis_header, authorities, authority_proof } + } +} + +#[derive(Encode, Decode, Clone)] +pub struct SimpleParams
{ + pub genesis_header: Header, +} + +impl
SimpleParams
{ + pub fn new(genesis_header: Header) -> Self { + Self { genesis_header } + } +} diff --git a/bitacross-worker/core/parentchain/light-client/src/light_validation.rs b/bitacross-worker/core/parentchain/light-client/src/light_validation.rs new file mode 100644 index 0000000000..9fe56eccf6 --- /dev/null +++ b/bitacross-worker/core/parentchain/light-client/src/light_validation.rs @@ -0,0 +1,266 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +//! Light-client validation crate that verifies parentchain blocks. + +use crate::{ + error::Error, finality::Finality, light_validation_state::LightValidationState, + state::RelayState, AuthorityList, AuthorityListRef, ExtrinsicSender, HashFor, HashingFor, + LightClientState, NumberFor, RelayId, Validator, +}; +use codec::Encode; +use core::iter::Iterator; +use itp_ocall_api::EnclaveOnChainOCallApi; +use itp_storage::{Error as StorageError, StorageProof, StorageProofChecker}; +use itp_types::parentchain::{IdentifyParentchain, ParentchainId}; +use log::*; +use sp_runtime::{ + generic::SignedBlock, + traits::{Block as ParentchainBlockTrait, Header as HeaderTrait}, + Justifications, OpaqueExtrinsic, +}; +use std::{boxed::Box, fmt, sync::Arc, vec::Vec}; + +#[derive(Clone)] +pub struct LightValidation { + light_validation_state: LightValidationState, + ocall_api: Arc, + parentchain_id: ParentchainId, + finality: Arc + Sync + Send + 'static>>, + ignore_validation_until: NumberFor, +} + +impl IdentifyParentchain + for LightValidation +{ + fn parentchain_id(&self) -> ParentchainId { + self.parentchain_id + } +} + +impl + LightValidation +{ + pub fn new( + ocall_api: Arc, + finality: Arc + Sync + Send + 'static>>, + light_validation_state: LightValidationState, + parentchain_id: ParentchainId, + ) -> Self { + Self { + light_validation_state, + ocall_api, + parentchain_id, + finality, + ignore_validation_until: 0u32.into(), + } + } + + fn check_validator_set_proof( + state_root: &HashFor, + proof: StorageProof, + validator_set: AuthorityListRef, + ) -> Result<(), Error> { + let checker = StorageProofChecker::>::new(*state_root, proof)?; + + // By encoding the given set we should have an easy way to compare + // with the stuff we get out of storage via `read_value` + let mut encoded_validator_set = validator_set.encode(); + encoded_validator_set.insert(0, 1); // Add AUTHORITIES_VERISON == 1 + let actual_validator_set = checker + .read_value(b":grandpa_authorities")? + .ok_or(StorageError::StorageValueUnavailable)?; + + if encoded_validator_set == actual_validator_set { + Ok(()) + } else { + Err(Error::ValidatorSetMismatch) + } + } + + // A naive way to check whether a `child` header is a descendant + // of an `ancestor` header. For this it requires a proof which + // is a chain of headers between (but not including) the `child` + // and `ancestor`. This could be updated to use something like + // Log2 Ancestors (#2053) in the future. + fn verify_ancestry( + proof: Vec, + ancestor_hash: HashFor, + child: &Block::Header, + ) -> Result<(), Error> { + let parent_hash = child.parent_hash(); + if *parent_hash == ancestor_hash { + return Ok(()) + } + + // Find the header's parent hash that matches our ancestor's hash + match proof + .iter() + .find(|header| header.hash() == *parent_hash && *header.parent_hash() == ancestor_hash) + { + Some(_) => Ok(()), + None => Err(Error::InvalidAncestryProof), + } + } + + fn submit_finalized_headers( + &mut self, + header: Block::Header, + ancestry_proof: Vec, + justifications: Option, + ) -> Result<(), Error> { + let relay = self.light_validation_state.get_relay_mut(); + + let validator_set = relay.current_validator_set.clone(); + let validator_set_id = relay.current_validator_set_id; + + if *header.number() > self.ignore_validation_until { + // Check that the new header is a descendant of the old header + let last_header = &relay.last_finalized_block_header; + Self::verify_ancestry(ancestry_proof, last_header.hash(), &header)?; + } + + if let Err(e) = self.finality.validate( + header.clone(), + &validator_set, + validator_set_id, + justifications, + relay, + ) { + match e { + Error::NoJustificationFound => return Ok(()), + _ => return Err(e), + } + } + + // Todo: Justifying the headers here is actually wrong, but it prevents an ever-growing + // `unjustified_headers` queue because in the parachain case we won't have justifications, + // and in solo chain setups we only get a justification upon an Grandpa authority change. + // Hence, we justify the headers here until we properly solve this in #1404. + relay.justify_headers(); + relay.push_header_hash(header.hash()); + + relay.set_last_finalized_block_header(header); + + if validator_set_id > relay.current_validator_set_id { + relay.current_validator_set = validator_set; + relay.current_validator_set_id = validator_set_id; + } + + Ok(()) + } +} + +impl Validator for LightValidation +where + NumberFor: finality_grandpa::BlockNumberOps, + Block: ParentchainBlockTrait, + OCallApi: EnclaveOnChainOCallApi, +{ + fn submit_block(&mut self, signed_block: &SignedBlock) -> Result<(), Error> { + let header = signed_block.block.header(); + let justifications = signed_block.justifications.clone(); + + let relay = self.light_validation_state.get_relay_mut(); + + if *header.number() > self.ignore_validation_until + && relay.last_finalized_block_header.hash() != *header.parent_hash() + { + return Err(Error::HeaderAncestryMismatch) + } + + self.submit_finalized_headers(header.clone(), vec![], justifications) + } + + fn get_state(&self) -> &LightValidationState { + &self.light_validation_state + } + + fn set_ignore_validation_until(&mut self, until: u32) -> Result<(), Error> { + info!("set ignore parentchain block import validation until: {}", until); + self.ignore_validation_until = until.into(); + Ok(()) + } +} + +impl ExtrinsicSender for LightValidation +where + NumberFor: finality_grandpa::BlockNumberOps, + Block: ParentchainBlockTrait, + OCallApi: EnclaveOnChainOCallApi, +{ + fn send_extrinsics(&mut self, extrinsics: Vec) -> Result<(), Error> { + self.ocall_api + .send_to_parentchain(extrinsics, &self.parentchain_id, false) + .map_err(|e| { + Error::Other( + format!("[{:?}] Failed to send extrinsics: {}", self.parentchain_id, e).into(), + ) + }) + } +} + +impl LightClientState for LightValidation +where + NumberFor: finality_grandpa::BlockNumberOps, + Block: ParentchainBlockTrait, + OCallApi: EnclaveOnChainOCallApi, +{ + fn genesis_hash(&self) -> Result, Error> { + self.light_validation_state.genesis_hash() + } + + fn latest_finalized_header(&self) -> Result { + self.light_validation_state.latest_finalized_header() + } + + fn penultimate_finalized_block_header(&self) -> Result { + self.light_validation_state.penultimate_finalized_block_header() + } +} + +impl fmt::Debug for LightValidation { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "LightValidation {{ parentchain_id: {:?}, relay_state: {:?} }}", + self.parentchain_id, self.light_validation_state.relay_state + ) + } +} + +pub fn check_validator_set_proof( + state_root: &HashFor, + proof: StorageProof, + validator_set: AuthorityListRef, +) -> Result<(), Error> { + let checker = StorageProofChecker::>::new(*state_root, proof)?; + + // By encoding the given set we should have an easy way to compare + // with the stuff we get out of storage via `read_value` + let mut encoded_validator_set = validator_set.encode(); + encoded_validator_set.insert(0, 1); // Add AUTHORITIES_VERISON == 1 + let actual_validator_set = checker + .read_value(b":grandpa_authorities")? + .ok_or(StorageError::StorageValueUnavailable)?; + + if encoded_validator_set == actual_validator_set { + Ok(()) + } else { + Err(Error::ValidatorSetMismatch) + } +} diff --git a/bitacross-worker/core/parentchain/light-client/src/light_validation_state.rs b/bitacross-worker/core/parentchain/light-client/src/light_validation_state.rs new file mode 100644 index 0000000000..b86a242677 --- /dev/null +++ b/bitacross-worker/core/parentchain/light-client/src/light_validation_state.rs @@ -0,0 +1,68 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +//! State of the light-client validation. + +use crate::{state::RelayState, Error, HashFor, LightClientState}; +use codec::{Decode, Encode}; +use sp_runtime::traits::Block as ParentchainBlockTrait; + +pub use sp_consensus_grandpa::SetId; + +#[derive(Encode, Decode, Clone, Debug, Eq, PartialEq)] +pub struct LightValidationState { + pub(crate) relay_state: RelayState, +} + +impl From> for LightValidationState { + fn from(value: RelayState) -> Self { + Self::new(value) + } +} + +impl LightValidationState { + pub fn new(relay_state: RelayState) -> Self { + Self { relay_state } + } + + pub(crate) fn get_relay(&self) -> &RelayState { + &self.relay_state + } + + pub(crate) fn get_relay_mut(&mut self) -> &mut RelayState { + &mut self.relay_state + } +} + +impl LightClientState for LightValidationState +where + Block: ParentchainBlockTrait, +{ + fn genesis_hash(&self) -> Result, Error> { + Ok(self.get_relay().genesis_hash) + } + + fn latest_finalized_header(&self) -> Result { + let relay = self.get_relay(); + Ok(relay.last_finalized_block_header.clone()) + } + + fn penultimate_finalized_block_header(&self) -> Result { + let relay = self.get_relay(); + Ok(relay.penultimate_finalized_block_header.clone()) + } +} diff --git a/bitacross-worker/core/parentchain/light-client/src/mocks/mod.rs b/bitacross-worker/core/parentchain/light-client/src/mocks/mod.rs new file mode 100644 index 0000000000..4dedae8c6d --- /dev/null +++ b/bitacross-worker/core/parentchain/light-client/src/mocks/mod.rs @@ -0,0 +1,20 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 validator_access_mock; +pub mod validator_mock; +pub mod validator_mock_seal; diff --git a/bitacross-worker/core/parentchain/light-client/src/mocks/validator_access_mock.rs b/bitacross-worker/core/parentchain/light-client/src/mocks/validator_access_mock.rs new file mode 100644 index 0000000000..c8c775e5a8 --- /dev/null +++ b/bitacross-worker/core/parentchain/light-client/src/mocks/validator_access_mock.rs @@ -0,0 +1,66 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 = "sgx")] +use std::sync::SgxRwLock as RwLock; + +#[cfg(feature = "std")] +use std::sync::RwLock; + +use crate::{ + concurrent_access::ValidatorAccess, + error::{Error, Result}, + mocks::validator_mock::ValidatorMock, +}; +use itp_types::{ + parentchain::{IdentifyParentchain, ParentchainId}, + Block, +}; + +/// Mock for the validator access. +/// +/// Does not execute anything, just a stub. +#[derive(Default)] +pub struct ValidatorAccessMock { + validator: RwLock, +} + +impl ValidatorAccess for ValidatorAccessMock { + type ValidatorType = ValidatorMock; + + fn execute_on_validator(&self, getter_function: F) -> Result + where + F: FnOnce(&Self::ValidatorType) -> Result, + { + let validator_lock = self.validator.read().map_err(|_| Error::PoisonedLock)?; + getter_function(&validator_lock) + } + + fn execute_mut_on_validator(&self, mutating_function: F) -> Result + where + F: FnOnce(&mut Self::ValidatorType) -> Result, + { + let mut validator_lock = self.validator.write().map_err(|_| Error::PoisonedLock)?; + mutating_function(&mut validator_lock) + } +} + +impl IdentifyParentchain for ValidatorAccessMock { + fn parentchain_id(&self) -> ParentchainId { + ParentchainId::Litentry + } +} diff --git a/bitacross-worker/core/parentchain/light-client/src/mocks/validator_mock.rs b/bitacross-worker/core/parentchain/light-client/src/mocks/validator_mock.rs new file mode 100644 index 0000000000..ed33d59225 --- /dev/null +++ b/bitacross-worker/core/parentchain/light-client/src/mocks/validator_mock.rs @@ -0,0 +1,79 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{ + error::Result, state::RelayState, ExtrinsicSender, HashFor, LightClientState, + LightValidationState, Validator, +}; +use itc_parentchain_test::ParentchainHeaderBuilder; +use itp_types::Block; +use sp_runtime::{generic::SignedBlock, traits::Block as BlockT, OpaqueExtrinsic}; +use std::vec::Vec; + +type Header = ::Header; + +/// Validator mock to be used in tests. +#[derive(Clone, Debug)] +pub struct ValidatorMock { + light_validation_state: LightValidationState, +} + +impl Default for ValidatorMock { + fn default() -> Self { + Self { + light_validation_state: RelayState::new( + ParentchainHeaderBuilder::default().build(), + Default::default(), + ) + .into(), + } + } +} + +impl Validator for ValidatorMock { + fn submit_block(&mut self, _signed_block: &SignedBlock) -> Result<()> { + Ok(()) + } + + fn get_state(&self) -> &LightValidationState { + &self.light_validation_state + } + + fn set_ignore_validation_until(&mut self, until: u32) -> Result<()> { + Ok(()) + } +} + +impl ExtrinsicSender for ValidatorMock { + fn send_extrinsics(&mut self, _extrinsics: Vec) -> Result<()> { + Ok(()) + } +} + +impl LightClientState for ValidatorMock { + fn genesis_hash(&self) -> Result> { + todo!() + } + + fn latest_finalized_header(&self) -> Result
{ + Ok(ParentchainHeaderBuilder::default().build()) + } + + fn penultimate_finalized_block_header(&self) -> Result
{ + Ok(ParentchainHeaderBuilder::default().build()) + } +} diff --git a/bitacross-worker/core/parentchain/light-client/src/mocks/validator_mock_seal.rs b/bitacross-worker/core/parentchain/light-client/src/mocks/validator_mock_seal.rs new file mode 100644 index 0000000000..4c7e4f25d3 --- /dev/null +++ b/bitacross-worker/core/parentchain/light-client/src/mocks/validator_mock_seal.rs @@ -0,0 +1,64 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{error::Error, state::RelayState, LightClientSealing, LightValidationState}; +use itc_parentchain_test::ParentchainHeaderBuilder; +use itp_sgx_temp_dir::TempDir; +use itp_types::Block; +use std::path::Path; + +/// A seal that returns a mock validator. +#[derive(Clone)] +pub struct LightValidationStateSealMock { + // The directory is deleted when the seal is dropped. + temp_dir: TempDir, +} + +impl LightValidationStateSealMock { + pub fn new() -> Self { + Self { temp_dir: TempDir::new().unwrap() } + } +} + +impl Default for LightValidationStateSealMock { + fn default() -> Self { + Self::new() + } +} + +impl LightClientSealing for LightValidationStateSealMock { + type LightClientState = LightValidationState; + + fn unseal(&self) -> Result, Error> { + Ok(LightValidationState::new(RelayState::new( + ParentchainHeaderBuilder::default().build(), + Default::default(), + ))) + } + + fn seal(&self, _: &LightValidationState) -> Result<(), Error> { + Ok(()) + } + + fn exists(&self) -> bool { + false + } + + fn path(&self) -> &Path { + self.temp_dir.path() + } +} diff --git a/bitacross-worker/core/parentchain/light-client/src/state.rs b/bitacross-worker/core/parentchain/light-client/src/state.rs new file mode 100644 index 0000000000..e21f86e2e4 --- /dev/null +++ b/bitacross-worker/core/parentchain/light-client/src/state.rs @@ -0,0 +1,100 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 sp_consensus_grandpa::{AuthorityList, SetId}; +use sp_runtime::traits::{Block as BlockT, Header as HeaderT}; +use std::{collections::VecDeque, fmt, vec::Vec}; + +/// Defines the amount of parentchain headers to keep. +pub const PARENTCHAIN_HEADER_PRUNING: u64 = 1000; + +#[derive(Encode, Decode, Clone, Eq, PartialEq)] +pub struct RelayState { + pub genesis_hash: Block::Hash, + pub last_finalized_block_header: Block::Header, + pub penultimate_finalized_block_header: Block::Header, + pub current_validator_set: AuthorityList, + pub current_validator_set_id: SetId, + header_hashes: VecDeque, + pub unjustified_headers: Vec, // Finalized headers without grandpa proof + pub scheduled_change: Option>, // Scheduled Authorities change as indicated in the header's digest. +} + +impl RelayState { + pub fn push_header_hash(&mut self, header: Block::Hash) { + self.header_hashes.push_back(header); + + if self.header_hashes.len() > PARENTCHAIN_HEADER_PRUNING as usize { + self.header_hashes.pop_front().expect("Tested above that is not empty; qed"); + } + } + + pub fn justify_headers(&mut self) { + self.header_hashes.extend(&mut self.unjustified_headers.iter()); + self.unjustified_headers.clear(); + + while self.header_hashes.len() > PARENTCHAIN_HEADER_PRUNING as usize { + self.header_hashes.pop_front().expect("Tested above that is not empty; qed"); + } + } + + pub fn header_hashes(&self) -> &VecDeque { + &self.header_hashes + } +} + +#[derive(Encode, Decode, Clone, Eq, PartialEq)] +pub struct ScheduledChangeAtBlock { + pub at_block: Header::Number, + pub next_authority_list: AuthorityList, +} + +impl RelayState { + pub fn new(genesis: Block::Header, validator_set: AuthorityList) -> Self { + RelayState { + genesis_hash: genesis.hash(), + header_hashes: vec![genesis.hash()].into(), + last_finalized_block_header: genesis.clone(), + // is it bad to initialize with the same? Header trait does no implement default... + penultimate_finalized_block_header: genesis, + current_validator_set: validator_set, + current_validator_set_id: 0, + unjustified_headers: Vec::new(), + scheduled_change: None, + } + } + + pub fn set_last_finalized_block_header(&mut self, header: Block::Header) { + self.penultimate_finalized_block_header = + std::mem::replace(&mut self.last_finalized_block_header, header); + } +} + +impl fmt::Debug for RelayState { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "RelayInfo {{ last_finalized_block_header_number: {:?}, current_validator_set: {:?}, \ + current_validator_set_id: {}, number of unjustified headers: {} }}", + self.last_finalized_block_header.number(), + self.current_validator_set, + self.current_validator_set_id, + self.unjustified_headers.len() + ) + } +} diff --git a/bitacross-worker/core/parentchain/parentchain-crate/Cargo.toml b/bitacross-worker/core/parentchain/parentchain-crate/Cargo.toml new file mode 100644 index 0000000000..760544b667 --- /dev/null +++ b/bitacross-worker/core/parentchain/parentchain-crate/Cargo.toml @@ -0,0 +1,44 @@ +[package] +name = "itc-parentchain" +version = "0.9.0" +authors = ['Trust Computing GmbH ', 'Integritee AG '] +edition = "2021" + +[dependencies] +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive", "chain-error"] } + +# Parity +sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } + +# local +itc-parentchain-block-import-dispatcher = { path = "../block-import-dispatcher", default-features = false } +itc-parentchain-block-importer = { path = "../block-importer", default-features = false } +itc-parentchain-indirect-calls-executor = { path = "../indirect-calls-executor", default-features = false } +itc-parentchain-light-client = { path = "../light-client", default-features = false } +itp-types = { default-features = false, path = "../../../core-primitives/types" } + +[features] +default = ["std"] +std = [ + "codec/std", + "sp-runtime/std", + "itc-parentchain-block-import-dispatcher/std", + "itc-parentchain-block-importer/std", + "itc-parentchain-indirect-calls-executor/std", + "itc-parentchain-light-client/std", + "itp-types/std", +] +sgx = [ + "itc-parentchain-block-import-dispatcher/sgx", + "itc-parentchain-block-importer/sgx", + "itc-parentchain-indirect-calls-executor/sgx", + "itc-parentchain-light-client/sgx", +] +mocks = [ + "itc-parentchain-block-import-dispatcher/mocks", + "itc-parentchain-light-client/mocks", +] +test = [ + "mocks", + "itc-parentchain-light-client/test", +] diff --git a/bitacross-worker/core/parentchain/parentchain-crate/src/lib.rs b/bitacross-worker/core/parentchain/parentchain-crate/src/lib.rs new file mode 100644 index 0000000000..368ee69967 --- /dev/null +++ b/bitacross-worker/core/parentchain/parentchain-crate/src/lib.rs @@ -0,0 +1,33 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +//! Reexport all the parentchain components in one crate + +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg(all(feature = "std", feature = "sgx"))] +compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the same time"); + +pub use itc_parentchain_block_import_dispatcher as block_import_dispatcher; + +pub use itc_parentchain_block_importer as block_importer; + +pub use itc_parentchain_indirect_calls_executor as indirect_calls_executor; + +pub use itc_parentchain_light_client as light_client; + +pub mod primitives; diff --git a/bitacross-worker/core/parentchain/parentchain-crate/src/primitives.rs b/bitacross-worker/core/parentchain/parentchain-crate/src/primitives.rs new file mode 100644 index 0000000000..97aff7f724 --- /dev/null +++ b/bitacross-worker/core/parentchain/parentchain-crate/src/primitives.rs @@ -0,0 +1,61 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +extern crate alloc; + +use crate::light_client::light_client_init_params::{GrandpaParams, SimpleParams}; +use codec::{Decode, Encode}; + +use sp_runtime::traits::Block; + +pub use itp_types::{parentchain::ParentchainId, Block as ParachainBlock, Block as SolochainBlock}; +pub type HeaderFor = ::Header; +pub type SolochainHeader = HeaderFor; +pub type ParachainHeader = HeaderFor; +pub type SolochainParams = GrandpaParams; +pub type ParachainParams = SimpleParams; + +/// Initialization primitives, used by both service and enclave. +/// Allows to use a single E-call for the initialization of different parentchain types. +#[derive(Encode, Decode, Clone)] +pub enum ParentchainInitParams { + #[codec(index = 0)] + Solochain { id: ParentchainId, params: SolochainParams }, + #[codec(index = 1)] + Parachain { id: ParentchainId, params: ParachainParams }, +} + +impl ParentchainInitParams { + pub fn id(&self) -> &ParentchainId { + match self { + Self::Solochain { id, .. } => id, + Self::Parachain { id, .. } => id, + } + } +} + +impl From<(ParentchainId, SolochainParams)> for ParentchainInitParams { + fn from(value: (ParentchainId, SolochainParams)) -> Self { + Self::Solochain { id: value.0, params: value.1 } + } +} + +impl From<(ParentchainId, ParachainParams)> for ParentchainInitParams { + fn from(value: (ParentchainId, ParachainParams)) -> Self { + Self::Parachain { id: value.0, params: value.1 } + } +} diff --git a/bitacross-worker/core/parentchain/test/Cargo.toml b/bitacross-worker/core/parentchain/test/Cargo.toml new file mode 100644 index 0000000000..dd9cbb8535 --- /dev/null +++ b/bitacross-worker/core/parentchain/test/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "itc-parentchain-test" +version = "0.9.0" +authors = ['Trust Computing GmbH ', 'Integritee AG '] +homepage = 'https://litentry.com/' +repository = 'https://github.com/litentry/litentry-parachain' +license = "Apache-2.0" +edition = "2021" + +[dependencies] +itp-types = { path = "../../../core-primitives/types", default-features = false } +sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } + +[features] +default = ["std"] +std = [ + "itp-types/std", + "sp-runtime/std", +] diff --git a/bitacross-worker/core/parentchain/test/src/lib.rs b/bitacross-worker/core/parentchain/test/src/lib.rs new file mode 100644 index 0000000000..b0ecad2d23 --- /dev/null +++ b/bitacross-worker/core/parentchain/test/src/lib.rs @@ -0,0 +1,27 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 patterns for common structs used in tests. + +#![cfg_attr(not(feature = "std"), no_std)] + +pub mod parentchain_block_builder; +pub mod parentchain_header_builder; + +pub use parentchain_block_builder::{Block, ParentchainBlockBuilder, SignedBlock}; +pub use parentchain_header_builder::{BlockNumber, Header, ParentchainHeaderBuilder, H256}; diff --git a/bitacross-worker/core/parentchain/test/src/parentchain_block_builder.rs b/bitacross-worker/core/parentchain/test/src/parentchain_block_builder.rs new file mode 100644 index 0000000000..5b7ea5e081 --- /dev/null +++ b/bitacross-worker/core/parentchain/test/src/parentchain_block_builder.rs @@ -0,0 +1,62 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 pattern for a parentchain block. + +extern crate alloc; + +use crate::ParentchainHeaderBuilder; +use alloc::vec::Vec; +use sp_runtime::traits::MaybeSerialize; + +pub use itp_types::Header; +pub use sp_runtime::generic::{Block, SignedBlock}; + +pub struct ParentchainBlockBuilder { + header: Header, + extrinsics: Vec, +} + +impl Default for ParentchainBlockBuilder { + fn default() -> Self { + ParentchainBlockBuilder { + header: ParentchainHeaderBuilder::default().build(), + extrinsics: Default::default(), + } + } +} + +impl ParentchainBlockBuilder { + pub fn with_header(mut self, header: Header) -> Self { + self.header = header; + self + } + + pub fn with_extrinsics(mut self, extrinsics: Vec) -> Self { + self.extrinsics = extrinsics; + self + } + + pub fn build(self) -> Block { + Block { header: self.header, extrinsics: self.extrinsics } + } + + pub fn build_signed(self) -> SignedBlock> { + SignedBlock { block: self.build(), justifications: None } + } +} diff --git a/bitacross-worker/core/parentchain/test/src/parentchain_header_builder.rs b/bitacross-worker/core/parentchain/test/src/parentchain_header_builder.rs new file mode 100644 index 0000000000..926f15ce7d --- /dev/null +++ b/bitacross-worker/core/parentchain/test/src/parentchain_header_builder.rs @@ -0,0 +1,53 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 pattern for a parentchain header. + +pub use itp_types::{BlockNumber, Header, H256}; +pub use sp_runtime::generic::Digest; + +#[derive(Default)] +pub struct ParentchainHeaderBuilder { + number: BlockNumber, + parent_hash: H256, + state_root: H256, + extrinsic_root: H256, + digest: Digest, +} + +impl ParentchainHeaderBuilder { + pub fn with_number(mut self, number: BlockNumber) -> Self { + self.number = number; + self + } + + pub fn with_parent_hash(mut self, parent_hash: H256) -> Self { + self.parent_hash = parent_hash; + self + } + + pub fn build(self) -> Header { + Header { + number: self.number, + parent_hash: self.parent_hash, + state_root: self.state_root, + extrinsics_root: self.extrinsic_root, + digest: self.digest, + } + } +} diff --git a/bitacross-worker/core/peer-top-broadcaster/Cargo.toml b/bitacross-worker/core/peer-top-broadcaster/Cargo.toml new file mode 100644 index 0000000000..f2c870e4b2 --- /dev/null +++ b/bitacross-worker/core/peer-top-broadcaster/Cargo.toml @@ -0,0 +1,47 @@ +[package] +name = "itc-peer-top-broadcaster" +version = "0.1.0" +authors = ['Trust Computing GmbH '] +edition = "2021" + +[dependencies] +# sgx dependencies +sgx_tstd = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git", optional = true } + +# no-std dependencies +log = { version = "0.4", default-features = false } + +# local dependencies +itc-direct-rpc-client = { path = "../direct-rpc-client", default-features = false } +itc-direct-rpc-server = { path = "../direct-rpc-server", default-features = false } +itp-rpc = { path = "../../core-primitives/rpc", default-features = false } +itp-stf-primitives = { path = "../../core-primitives/stf-primitives", default-features = false } +itp-types = { path = "../../core-primitives/types", default-features = false } +itp-utils = { path = "../../core-primitives/utils", default-features = false } + +# litentry +litentry-primitives = { path = "../../litentry/primitives", default-features = false } + +[dev-dependencies] +itc-direct-rpc-server = { path = "../direct-rpc-server", default-features = false, features = ["mocks"] } + + +[features] +default = ["std"] +sgx = [ + "sgx_tstd", + "itc-direct-rpc-server/sgx", + "itc-direct-rpc-client/sgx", + "itp-rpc/sgx", + "litentry-primitives/sgx", +] +std = [ + "itp-stf-primitives/std", + "itp-types/std", + "itp-utils/std", + "log/std", + "itc-direct-rpc-server/std", + "itc-direct-rpc-client/std", + "itp-rpc/std", + "litentry-primitives/std", +] diff --git a/bitacross-worker/core/peer-top-broadcaster/src/lib.rs b/bitacross-worker/core/peer-top-broadcaster/src/lib.rs new file mode 100644 index 0000000000..eef091de21 --- /dev/null +++ b/bitacross-worker/core/peer-top-broadcaster/src/lib.rs @@ -0,0 +1,374 @@ +// Copyright 2020-2023 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . + +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg(all(feature = "std", feature = "sgx"))] +compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the same time"); + +extern crate alloc; +extern crate core; +#[cfg(all(not(feature = "std"), feature = "sgx"))] +extern crate sgx_tstd as std; + +use alloc::vec; +use log::error; +#[cfg(feature = "sgx")] +use std::sync::SgxMutex as Mutex; + +#[cfg(feature = "std")] +use std::sync::Mutex; + +use itc_direct_rpc_client::{DirectRpcClientFactory, Response, RpcClient, RpcClientFactory}; +use itc_direct_rpc_server::{ + response_channel::ResponseChannel, rpc_responder::RpcResponder, RpcConnectionRegistry, + SendRpcResponse, +}; +use itp_rpc::{Id, RpcRequest}; +use itp_stf_primitives::types::Hash; +use itp_types::{DirectRequestStatus, TrustedOperationStatus, H256}; +use itp_utils::FromHexPrefixed; +use litentry_primitives::BroadcastedRequest; +use std::{ + collections::HashMap, + string::{String, ToString}, + sync::{ + mpsc::{sync_channel, SyncSender}, + Arc, + }, + vec::Vec, +}; + +pub type MaybeRequestIdWithParams = Option<(Hash, Vec)>; + +pub trait PeerUpdater { + fn update(&self, peers: Vec); +} + +pub struct DirectRpcBroadcaster +where + ClientFactory: RpcClientFactory, +{ + peers: Mutex>, + responses_sender: SyncSender, + factory: ClientFactory, +} + +impl DirectRpcBroadcaster +where + ClientFactory: RpcClientFactory, +{ + pub fn new( + peers: &[&str], + client_factory: ClientFactory, + rpc_responder: Arc>, + ) -> Self + where + Registry: RpcConnectionRegistry + 'static, + ResponseChannelType: ResponseChannel + 'static, + { + let (responses_sender, responses_receiver) = sync_channel(1000); + let mut peers_map = HashMap::new(); + for peer in peers { + match client_factory.create(peer, responses_sender.clone()) { + Ok(client) => { + peers_map.insert(peer.to_string(), client); + }, + Err(e) => log::error!("Could not connect to peer {}, reason: {:?}", peer, e), + } + } + + std::thread::spawn(move || { + while let Ok((id, rpc_return_value)) = responses_receiver.recv() { + match rpc_return_value.status { + DirectRequestStatus::TrustedOperationStatus(status, _) => { + //we need to map Id to hash in order to correlate it with connection + let hash = match id_to_hash(&id) { + Some(hash) => hash, + None => continue, + }; + match status { + // this will come from every peer so do not flood the client + TrustedOperationStatus::Submitted => {}, + // this needs to come before block is imported, otherwise it's going to be ignored because TOP will be removed from the pool after block import + TrustedOperationStatus::TopExecuted(ref value, force_wait) => { + match rpc_responder.update_connection_state( + hash, + value.clone(), + force_wait, + ) { + Ok(_) => {}, + Err(e) => log::error!( + "Could not set connection {}, reason: {:?}", + hash, + e + ), + }; + if let Err(_e) = rpc_responder.update_status_event(hash, status) { + error!("Could not update status for {}", &hash) + }; + }, + _ => { + //as long as we are waiting let's ignore all status events. + if !rpc_responder.is_force_wait(hash) { + if let Err(_e) = rpc_responder.update_status_event(hash, status) + { + }; + } + }, + } + }, + + DirectRequestStatus::Ok | DirectRequestStatus::Error => { + log::warn!( + "Got unexpected direct request status: {:?}", + rpc_return_value.status + ); + }, + } + } + }); + + DirectRpcBroadcaster { + peers: Mutex::new(peers_map), + responses_sender, + factory: client_factory, + } + } + + fn new_clear_peer_map(&self) -> HashMap { + HashMap::new() + } + + pub fn broadcast(&self, request: BroadcastedRequest) { + if let Ok(mut peers) = self.peers.lock() { + let request = RpcRequest { + jsonrpc: "2.0".to_string(), + method: request.rpc_method.clone(), + params: vec![request.payload.clone()], + id: Id::Text(request.id), + }; + peers.values_mut().for_each(|peer| { + if let Err(e) = peer.send(&request) { + log::warn!("Could not send top to peer reason: {:?}", e); + } + }); + } + } + + fn connect_to(&self, url: &str, peer_list: &mut HashMap) { + match self.factory.create(url, self.responses_sender.clone()) { + Ok(client) => { + peer_list.insert(url.to_string(), client); + }, + Err(e) => log::error!("Could not connect to peer {}, reason: {:?}", url, e), + } + } +} + +pub fn id_to_hash(id: &Id) -> Option { + match id { + Id::Text(id) => H256::from_hex(id).ok(), + Id::Number(id) => { + log::error!("Got response with id {}", id); + None + }, + } +} + +#[allow(clippy::type_complexity)] +pub fn init( + rpc_responder: Arc>, +) -> ( + Arc>, + Arc>, +) +where + Registry: RpcConnectionRegistry + 'static, + ResponseChannelType: ResponseChannel + 'static, +{ + let (sender, receiver) = std::sync::mpsc::sync_channel::(1000); + + let peers = vec![]; + + let client_factory = DirectRpcClientFactory {}; + + let rpc_broadcaster = + Arc::new(DirectRpcBroadcaster::new(&peers, client_factory, rpc_responder)); + let return_rpc_broadcaster = rpc_broadcaster.clone(); + + std::thread::spawn(move || { + for received in receiver { + rpc_broadcaster.broadcast(received); + } + }); + + (Arc::new(sender), return_rpc_broadcaster) +} + +impl PeerUpdater for DirectRpcBroadcaster +where + ClientFactory: RpcClientFactory, +{ + // created new map filled with rpc clients connected to peer from the provided list. Reuses existing + // connections. The list will not containt peers that are unreachable, so following logic will automatically + // remove all dead connections + fn update(&self, peers: Vec) { + log::debug!("Updating peers: {:?}", &peers); + let mut new_peers_list = self.new_clear_peer_map(); + for peer in peers { + if let Ok(mut peers) = self.peers.lock() { + if !peers.contains_key(&peer) { + log::info!("Adding a peer: {}", peer.clone()); + self.connect_to(&peer, &mut new_peers_list) + } else { + log::info!("Reusing existing peer: {}", peer.clone()); + //this is safe as we previously ensured that map contains such key + let peer_to_move = peers.remove(&peer).unwrap(); + new_peers_list.insert(peer, peer_to_move); + } + } + } + if let Ok(mut peers) = self.peers.lock() { + *peers = new_peers_list; + } + } +} + +#[cfg(test)] +pub mod tests { + use crate::{DirectRpcBroadcaster, PeerUpdater}; + use alloc::sync::Arc; + use itc_direct_rpc_client::{Response, RpcClient, RpcClientFactory}; + use itc_direct_rpc_server::{ + mocks::response_channel_mock::ResponseChannelMock, + rpc_connection_registry::ConnectionRegistry, rpc_responder::RpcResponder, + }; + use itp_rpc::{Id, RpcRequest, RpcReturnValue}; + use itp_stf_primitives::types::Hash; + use itp_types::H256; + use itp_utils::ToHexPrefixed; + use litentry_primitives::BroadcastedRequest; + use std::{error::Error, sync::mpsc::SyncSender}; + + type TestConnectionToken = u64; + type TestResponseChannel = ResponseChannelMock; + type TestConnectionRegistry = ConnectionRegistry; + + #[derive(Default)] + pub struct MockedRpcClient { + pub sent_requests: u64, + pub response: Option<(Id, RpcReturnValue)>, + } + + impl RpcClient for MockedRpcClient { + fn send(&mut self, _request: &RpcRequest) -> Result<(), Box> { + self.sent_requests = self.sent_requests + 1; + Ok(()) + } + } + + impl MockedRpcClient { + pub fn set_response(&mut self, response: (Id, RpcReturnValue)) { + self.response = Some(response) + } + } + + pub struct MockedRpcClientFactory {} + + impl RpcClientFactory for MockedRpcClientFactory { + type Client = MockedRpcClient; + + fn create( + &self, + _url: &str, + _response_sink: SyncSender, + ) -> Result> { + Ok(MockedRpcClient::default()) + } + } + + #[test] + pub fn creates_initial_peers() { + //given + let factory = MockedRpcClientFactory {}; + let connection_registry = Arc::new(TestConnectionRegistry::new()); + let websocket_responder = Arc::new(TestResponseChannel::default()); + let rpc_responder = Arc::new(RpcResponder::new(connection_registry, websocket_responder)); + + //when + let broadcaster: DirectRpcBroadcaster = + DirectRpcBroadcaster::new(&vec!["localhost"], factory, rpc_responder); + + //then + assert_eq!(broadcaster.peers.lock().unwrap().len(), 1); + } + + #[test] + pub fn broadcast_sends_to_all_peers() { + //given + let factory = MockedRpcClientFactory {}; + let connection_registry = Arc::new(TestConnectionRegistry::new()); + let websocket_responder = Arc::new(TestResponseChannel::default()); + let rpc_responder = Arc::new(RpcResponder::new(connection_registry, websocket_responder)); + + let broadcaster: DirectRpcBroadcaster = + DirectRpcBroadcaster::new(&vec!["localhost", "localhost2"], factory, rpc_responder); + + //when + broadcaster.broadcast(BroadcastedRequest { + id: Hash::random().to_hex(), + payload: Hash::random().to_hex(), + rpc_method: "submit_and_broadcast".to_string(), + }); + broadcaster.broadcast(BroadcastedRequest { + id: Hash::random().to_hex(), + payload: Hash::random().to_hex(), + rpc_method: "submit_and_broadcast".to_string(), + }); + + //then + let peers = broadcaster.peers.lock().unwrap(); + for peer in peers.iter() { + assert_eq!(peer.1.sent_requests, 2u64) + } + } + + #[test] + pub fn updates_list_correctly() { + //given + let retained_peer = "localhost"; + let added_peer = "localhost3"; + let removed_peer = "localhost2"; + + let factory = MockedRpcClientFactory {}; + let connection_registry = Arc::new(TestConnectionRegistry::new()); + let websocket_responder = Arc::new(TestResponseChannel::default()); + let rpc_responder = Arc::new(RpcResponder::new(connection_registry, websocket_responder)); + + let broadcaster: DirectRpcBroadcaster = + DirectRpcBroadcaster::new(&vec![retained_peer, removed_peer], factory, rpc_responder); + + //when + broadcaster.update(vec![retained_peer.to_string(), added_peer.to_string()]); + + //then + let peers = broadcaster.peers.lock().unwrap(); + assert!(peers.get(retained_peer).is_some()); + assert!(peers.get(added_peer).is_some()); + assert!(peers.get(removed_peer).is_none()); + } +} diff --git a/bitacross-worker/core/rest-client/Cargo.toml b/bitacross-worker/core/rest-client/Cargo.toml new file mode 100644 index 0000000000..668ecc4b04 --- /dev/null +++ b/bitacross-worker/core/rest-client/Cargo.toml @@ -0,0 +1,47 @@ +[package] +name = "itc-rest-client" +version = "0.9.0" +authors = ['Trust Computing GmbH ', 'Integritee AG '] +edition = "2021" + +[dependencies] +# std dependencies +http = { version = "0.2", optional = true } +http_req = { optional = true, features = ["rust-tls"], branch = "master", git = "https://github.com/integritee-network/http_req" } +thiserror = { version = "1.0.26", optional = true } +url = { version = "2.0.0", optional = true } + +# sgx dependencies +http-sgx = { package = "http", git = "https://github.com/integritee-network/http-sgx.git", branch = "sgx-experimental", optional = true } +http_req-sgx = { optional = true, default-features = false, features = ["rust-tls", "sgx"], package = "http_req", git = "https://github.com/integritee-network/http_req" } +sgx_tstd = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git", optional = true, features = ["net", "thread"] } +thiserror_sgx = { package = "thiserror", git = "https://github.com/mesalock-linux/thiserror-sgx", tag = "sgx_1.1.3", optional = true } +url_sgx = { package = "url", git = "https://github.com/mesalock-linux/rust-url-sgx", tag = "sgx_1.1.3", optional = true } + +# no_std dependencies +base64 = { version = "0.13", default-features = false, features = ["alloc"] } +log = { version = "0.4", default-features = false } +serde = { version = "1.0", default-features = false, features = ["derive", "alloc"] } +serde_json = { version = "1.0", default-features = false, features = ["alloc"] } + +[features] +default = ["std"] +std = [ + # std only + "http", + "http_req", + "thiserror", + "url", + # no_std + "base64/std", + "serde/std", + "serde_json/std", + "log/std", +] +sgx = [ + "http-sgx", + "http_req-sgx", + "sgx_tstd", + "thiserror_sgx", + "url_sgx", +] diff --git a/bitacross-worker/core/rest-client/src/error.rs b/bitacross-worker/core/rest-client/src/error.rs new file mode 100644 index 0000000000..8dea50ccfc --- /dev/null +++ b/bitacross-worker/core/rest-client/src/error.rs @@ -0,0 +1,58 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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(all(not(feature = "std"), feature = "sgx"))] +use crate::sgx_reexport_prelude::*; + +use std::string::String; + +/// REST client error +#[derive(Debug, thiserror::Error)] +pub enum Error { + #[error("HTTP client creation failed")] + HttpClientError, + + #[error("Failed to parse final URL.")] + UrlError, + + #[error("Failed to serialize struct to JSON (in POST): {0}")] + SerializeParseError(serde_json::Error), + + #[error("Failed to deserialize data to struct (in GET or POST response: {0} {1}")] + DeserializeParseError(serde_json::Error, String), + + #[error("Failed to make the outgoing request")] + RequestError, + + #[error("HTTP header error: {0}")] + HttpHeaderError(http::header::ToStrError), + + #[error(transparent)] + HttpReqError(#[from] http_req::error::Error), + + #[error("Failed to perform IO operation: {0}")] + IoError(std::io::Error), + + #[error("Server returned non-success status: {0}, details: {1}")] + HttpError(u16, String), + + #[error("Request has timed out")] + TimeoutError, + + #[error("Invalid parameter value")] + InvalidValue, +} diff --git a/bitacross-worker/core/rest-client/src/fixtures/amazon_root_ca_1_v3.pem b/bitacross-worker/core/rest-client/src/fixtures/amazon_root_ca_1_v3.pem new file mode 100644 index 0000000000..a6f3e92af5 --- /dev/null +++ b/bitacross-worker/core/rest-client/src/fixtures/amazon_root_ca_1_v3.pem @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsF +ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6 +b24gUm9vdCBDQSAxMB4XDTE1MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTEL +MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv +b3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ4gHHKeNXj +ca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgHFzZM +9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qw +IFAGbHrQgLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6 +VOujw5H5SNz/0egwLX0tdHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L +93FcXmn/6pUCyziKrlA4b9v7LWIbxcceVOF34GfID5yHI9Y/QCB/IIDEgEw+OyQm +jgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC +AYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3DQEBCwUA +A4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDI +U5PMCCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUs +N+gDS63pYaACbvXy8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vv +o/ufQJVtMVT8QtPHRh8jrdkPSHCa2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU +5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2xJNDd2ZhwLnoQdeXeGADbkpy +rqXRfboQnoZsG4q5WTP468SQvvG5 +-----END CERTIFICATE----- diff --git a/bitacross-worker/core/rest-client/src/fixtures/baltimore_cyber_trust_root_v3.pem b/bitacross-worker/core/rest-client/src/fixtures/baltimore_cyber_trust_root_v3.pem new file mode 100644 index 0000000000..519028c63b --- /dev/null +++ b/bitacross-worker/core/rest-client/src/fixtures/baltimore_cyber_trust_root_v3.pem @@ -0,0 +1,21 @@ +-----BEGIN CERTIFICATE----- +MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJ +RTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYD +VQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoX +DTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMCSUUxEjAQBgNVBAoTCUJhbHRpbW9y +ZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFsdGltb3JlIEN5YmVy +VHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKMEuyKr +mD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjr +IZ3AQSsBUnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeK +mpYcqWe4PwzV9/lSEy/CG9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSu +XmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9XbIGevOF6uvUA65ehD5f/xXtabz5OTZy +dc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjprl3RjM71oGDHweI12v/ye +jl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoIVDaGezq1 +BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3 +DQEBBQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT92 +9hkTI7gQCvlYpNRhcL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3Wgx +jkzSswF07r51XgdIGn9w/xZchMB5hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0 +Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsaY71k5h+3zvDyny67G7fyUIhz +ksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9HRCwBXbsdtTLS +R9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp +-----END CERTIFICATE----- diff --git a/bitacross-worker/core/rest-client/src/fixtures/lets_encrypt_root_cert.pem b/bitacross-worker/core/rest-client/src/fixtures/lets_encrypt_root_cert.pem new file mode 100644 index 0000000000..57d4a3766c --- /dev/null +++ b/bitacross-worker/core/rest-client/src/fixtures/lets_encrypt_root_cert.pem @@ -0,0 +1,31 @@ +-----BEGIN CERTIFICATE----- +MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw +TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh +cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4 +WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu +ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY +MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc +h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+ +0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U +A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW +T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH +B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC +B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv +KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn +OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn +jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw +qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI +rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV +HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq +hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL +ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ +3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK +NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5 +ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur +TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC +jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc +oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq +4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA +mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d +emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc= +-----END CERTIFICATE----- \ No newline at end of file diff --git a/bitacross-worker/core/rest-client/src/http_client.rs b/bitacross-worker/core/rest-client/src/http_client.rs new file mode 100644 index 0000000000..e45f6a3c88 --- /dev/null +++ b/bitacross-worker/core/rest-client/src/http_client.rs @@ -0,0 +1,584 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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(all(not(feature = "std"), feature = "sgx"))] +use crate::sgx_reexport_prelude::*; + +use crate::{error::Error, Query, RestPath}; +use http::{ + header::{HeaderName, AUTHORIZATION, CONTENT_LENGTH, CONTENT_TYPE, USER_AGENT}, + HeaderValue, +}; +use http_req::{ + request::{Method, Request}, + response::{Headers, Response}, + tls::Config, + uri::Uri, +}; +use log::*; +use std::{ + collections::HashMap, + convert::TryFrom, + str::FromStr, + string::{String, ToString}, + time::Duration, + vec::Vec, +}; +use url::Url; + +pub type EncodedBody = Vec; + +/// Simple trait to send HTTP request +pub trait SendHttpRequest { + fn send_request( + &self, + base_url: Url, + method: Method, + params: U, + query: Option<&Query<'_>>, + maybe_body: Option, + ) -> Result<(Response, EncodedBody), Error> + where + T: RestPath; +} + +/// Send trait used by the http client to send HTTP request, based on `http_req`. +pub trait Send { + fn execute_send_request( + &self, + request: &mut Request, + writer: &mut Vec, + ) -> Result; +} + +/// HTTP client implementation +/// +/// wrapper for the `http_req` library that adds the necessary headers and body to a request +pub struct HttpClient { + send: SendType, + send_null_body: bool, + timeout: Option, + headers: Headers, + authorization: Option, +} + +/// Default send method. +/// Automatically upgrades to TLS in case the base URL contains 'https' +/// For https requests, the default trusted server's certificates +/// are provided by the default tls configuration of the http_req lib +pub struct DefaultSend; + +impl Send for DefaultSend { + fn execute_send_request( + &self, + request: &mut Request, + writer: &mut Vec, + ) -> Result { + request.send(writer).map_err(Error::HttpReqError) + } +} + +/// Sends a HTTPs request with the server's root certificate(s). +/// The connection will only be established if one of the supplied certificates +/// matches the server's root certificate. +pub struct SendWithCertificateVerification { + root_certificates: Vec, +} + +impl SendWithCertificateVerification { + pub fn new(root_certificates: Vec) -> Self { + SendWithCertificateVerification { root_certificates } + } +} + +impl Send for SendWithCertificateVerification { + fn execute_send_request( + &self, + request: &mut Request, + writer: &mut Vec, + ) -> Result { + let mut cnf = Config::default(); + for cert in self.root_certificates.iter() { + cnf.add_root_cert_content_pem_file(cert)?; + } + + match request.send_with_config(writer, Some(&cnf)) { + Ok(response) => Ok(response), + Err(e) => { + error!( + "SendWithCertificateVerification::execute_send_request received error: {:?}", + &e + ); + Err(Error::HttpReqError(e)) + }, + } + } +} + +impl HttpClient +where + SendType: Send, +{ + pub fn new( + send: SendType, + send_null_body: bool, + timeout: Option, + headers: Option, + authorization: Option, + ) -> Self { + HttpClient { + send, + send_null_body, + timeout, + headers: headers.unwrap_or_else(Headers::new), + authorization, + } + } + + /// Set credentials for HTTP Basic authentication. + pub fn set_auth(&mut self, user: &str, pass: &str) { + let mut s: String = user.to_string(); + s.push(':'); + s.push_str(pass); + self.authorization = Some(format!("Basic {}", base64::encode(&s))); + } + + /// Set HTTP header from string name and value. + /// + /// The header is added to all subsequent GET and POST requests + /// unless the headers are cleared with `clear_headers()` call. + pub fn set_header(&mut self, name: &'static str, value: &str) -> Result<(), Error> { + let header_name = HeaderName::from_str(name).map_err(|_| Error::InvalidValue)?; + let value = HeaderValue::from_str(value).map_err(|_| Error::InvalidValue)?; + + add_to_headers(&mut self.headers, header_name, value); + Ok(()) + } + + /// Clear all previously set headers + pub fn clear_headers(&mut self) { + self.headers = Headers::new(); + } +} + +impl SendHttpRequest for HttpClient +where + SendType: Send, +{ + fn send_request( + &self, + base_url: Url, + method: Method, + params: U, + query: Option<&Query<'_>>, + maybe_body: Option, + ) -> Result<(Response, EncodedBody), Error> + where + T: RestPath, + { + let url = join_url(base_url, T::get_path(params)?.as_str(), query)?; + let uri = Uri::try_from(url.as_str()).map_err(Error::HttpReqError)?; + + trace!("uri: {:?}", uri); + + let mut request = Request::new(&uri); + request.method(method); + + let mut request_headers = Headers::default_http(&uri); + + if let Some(body) = maybe_body.as_ref() { + if self.send_null_body || body != "null" { + let len = HeaderValue::from_str(&body.len().to_string()) + .map_err(|_| Error::RequestError)?; + + add_to_headers(&mut request_headers, CONTENT_LENGTH, len); + add_to_headers( + &mut request_headers, + CONTENT_TYPE, + HeaderValue::from_str("application/json") + .expect("Request Header: invalid characters"), + ); + + trace!("set request body: {}", body); + request.body(body.as_bytes()); // takes body non-owned (!) + } + } else { + debug!("no body to send"); + } + + if let Some(ref auth) = self.authorization { + add_to_headers( + &mut request_headers, + AUTHORIZATION, + HeaderValue::from_str(auth).map_err(|_| Error::RequestError)?, + ); + } + + // add pre-set headers + for (key, value) in self.headers.iter() { + request_headers.insert(key, &value.clone()); + } + + // add user agent header + let pkg_version = env!("CARGO_PKG_VERSION"); + add_to_headers( + &mut request_headers, + USER_AGENT, + HeaderValue::from_str(format!("integritee/{}", pkg_version).as_str()) + .map_err(|_| Error::RequestError)?, + ); + + request.headers(HashMap::from(request_headers)); + + request + .timeout(self.timeout) + .connect_timeout(self.timeout) + .read_timeout(self.timeout) + .write_timeout(self.timeout); + + trace!("request is: {:?}", request); + + let mut writer = Vec::new(); + + let response = self.send.execute_send_request(&mut request, &mut writer)?; + + Ok((response, writer)) + } +} + +fn join_url(base_url: Url, path: &str, params: Option<&Query>) -> Result { + let mut url = base_url.join(path).map_err(|_| Error::UrlError)?; + + if let Some(params) = params { + for &(key, item) in params.iter() { + url.query_pairs_mut().append_pair(key, item); + } + } + + Ok(url) +} + +fn add_to_headers(headers: &mut Headers, key: HeaderName, value: HeaderValue) { + let header_value_str = value.to_str(); + + match header_value_str { + Ok(v) => { + headers.insert(key.as_str(), v); + }, + Err(e) => { + error!("Failed to add header to request: {:?}", e); + }, + } +} + +#[cfg(test)] +mod tests { + + use super::*; + use core::assert_matches::assert_matches; + use http::header::CONNECTION; + use serde::{Deserialize, Serialize}; + use std::vec::Vec; + + const HTTPBIN_ROOT_CERT: &str = include_str!("fixtures/amazon_root_ca_1_v3.pem"); + const COINGECKO_ROOT_CERTIFICATE_BALTIMORE: &str = + include_str!("fixtures/baltimore_cyber_trust_root_v3.pem"); + const COINGECKO_ROOT_CERTIFICATE_LETSENCRYPT: &str = + include_str!("fixtures/lets_encrypt_root_cert.pem"); + + #[test] + fn join_url_adds_query_parameters() { + let base_url = Url::parse("https://example.com").unwrap(); + let path = "api/v2/example_list"; + let query = [("filter", "all"), ("order", ("desc"))]; + + let complete_url = join_url(base_url, path, Some(&query)).unwrap(); + + assert_eq!( + complete_url.as_str(), + "https://example.com/api/v2/example_list?filter=all&order=desc" + ); + } + + #[test] + fn join_url_has_no_query_parameters() { + let base_url = Url::parse("https://example.com").unwrap(); + let path = "api/v2/endpoint"; + let complete_url = join_url(base_url, path, None).unwrap(); + assert_eq!(complete_url.as_str(), "https://example.com/api/v2/endpoint"); + } + + #[test] + fn join_url_with_too_many_slashes() { + let base_url = Url::parse("https://api.mydomain.com").unwrap(); + let path = "/api/v1/post"; + let complete_url = join_url(base_url, path, None).unwrap(); + assert_eq!(complete_url.as_str(), "https://api.mydomain.com/api/v1/post"); + } + + #[test] + #[ignore = "depends on external web-service that proved to be unreliable for CI"] + fn get_with_parameters() { + #[derive(Serialize, Deserialize, Debug)] + struct RequestArgs { + pub order: String, + pub filter: String, + } + + // Data structure that matches with REST API JSON + #[derive(Serialize, Deserialize, Debug)] + struct HttpBinAnything { + pub args: RequestArgs, + pub origin: String, + pub url: String, + } + + impl RestPath<()> for HttpBinAnything { + fn get_path(_: ()) -> Result { + Ok(format!("anything")) + } + } + + let http_client = HttpClient::new( + DefaultSend {}, + true, + Some(Duration::from_secs(3u64)), + Some(headers_connection_close()), + None, + ); + let base_url = Url::parse("https://httpbin.org").unwrap(); + let query_parameters = [("order", "desc"), ("filter", "all")]; + + let (response, encoded_body) = http_client + .send_request::<(), HttpBinAnything>( + base_url, + Method::GET, + (), + Some(&query_parameters), + None, + ) + .unwrap(); + + let response_body: HttpBinAnything = + deserialize_response_body(encoded_body.as_slice()).unwrap(); + + assert!(response.status_code().is_success()); + assert_eq!(response_body.args.order.as_str(), "desc"); + assert_eq!(response_body.args.filter.as_str(), "all"); + } + + #[test] + #[ignore = "depends on external web-service that proved to be unreliable for CI"] + fn get_without_parameters() { + // Data structure that matches with REST API JSON + #[derive(Serialize, Deserialize, Debug)] + struct HttpBinAnything { + pub method: String, + pub url: String, + } + + impl RestPath<()> for HttpBinAnything { + fn get_path(_: ()) -> Result { + Ok(format!("anything")) + } + } + + let http_client = HttpClient::new( + DefaultSend {}, + true, + Some(Duration::from_secs(3u64)), + Some(headers_connection_close()), + None, + ); + let base_url = Url::parse("https://httpbin.org").unwrap(); + + let (response, encoded_body) = http_client + .send_request::<(), HttpBinAnything>(base_url, Method::GET, (), None, None) + .unwrap(); + + let response_body: HttpBinAnything = + deserialize_response_body(encoded_body.as_slice()).unwrap(); + + assert!(response.status_code().is_success()); + assert!(!response_body.url.is_empty()); + assert_eq!(response_body.method.as_str(), "GET"); + } + + #[test] + #[ignore = "depends on external web-service that proved to be unreliable for CI"] + fn post_with_body() { + #[derive(Serialize, Deserialize, Debug)] + struct HttpBinAnything { + pub data: String, + pub method: String, + } + + impl RestPath<()> for HttpBinAnything { + fn get_path(_: ()) -> Result { + Ok(format!("anything")) + } + } + + let http_client = HttpClient::new( + DefaultSend {}, + false, + Some(Duration::from_secs(3u64)), + Some(headers_connection_close()), + None, + ); + + let body_test = "this is a test body with special characters {::}/-".to_string(); + let base_url = Url::parse("https://httpbin.org").unwrap(); + + let (response, encoded_body) = http_client + .send_request::<(), HttpBinAnything>( + base_url, + Method::POST, + (), + None, + Some(body_test.clone()), + ) + .unwrap(); + + let response_body: HttpBinAnything = + deserialize_response_body(encoded_body.as_slice()).unwrap(); + + assert!(response.status_code().is_success()); + assert_eq!(response_body.method.as_str(), "POST"); + assert_eq!(response_body.data, body_test); + } + + #[test] + #[ignore = "depends on external web-service that proved to be unreliable for CI"] + fn get_coins_list_from_coin_gecko_works() { + // Data structure that matches with REST API JSON + #[derive(Serialize, Deserialize, Debug)] + struct CoinGeckoCoinsList { + id: String, + symbol: String, + name: String, + } + + impl RestPath<()> for Vec { + fn get_path(_: ()) -> Result { + Ok(format!("api/v3/coins/list")) + } + } + + let http_client = + HttpClient::new(DefaultSend {}, true, Some(Duration::from_secs(3u64)), None, None); + let base_url = Url::parse("https://api.coingecko.com").unwrap(); + + let (response, encoded_body) = http_client + .send_request::<(), Vec>(base_url, Method::GET, (), None, None) + .unwrap(); + + let coins_list: Vec = + deserialize_response_body(encoded_body.as_slice()).unwrap(); + + assert!(response.status_code().is_success()); + assert!(!coins_list.is_empty()); + } + + #[test] + #[ignore = "depends on external web-service that proved to be unreliable for CI"] + fn authenticated_get_works() { + #[derive(Serialize, Deserialize, Debug)] + struct HttpBinAnything { + pub method: String, + pub url: String, + } + + impl RestPath<()> for HttpBinAnything { + fn get_path(_: ()) -> Result { + Ok(format!("anything")) + } + } + let base_url = Url::parse("https://httpbin.org").unwrap(); + let root_certificate = HTTPBIN_ROOT_CERT.to_string(); + + let http_client = HttpClient::new( + SendWithCertificateVerification::new(vec![root_certificate]), + true, + Some(Duration::from_secs(3u64)), + Some(headers_connection_close()), + None, + ); + + let (response, encoded_body) = http_client + .send_request::<(), HttpBinAnything>(base_url, Method::GET, (), None, None) + .unwrap(); + + let response_body: HttpBinAnything = + deserialize_response_body(encoded_body.as_slice()).unwrap(); + + assert!(response.status_code().is_success()); + assert!(!response_body.url.is_empty()); + assert_eq!(response_body.method.as_str(), "GET"); + } + + #[test] + #[ignore = "depends on external web-service that proved to be unreliable for CI"] + fn authenticated_get_with_wrong_root_certificate_fails() { + #[derive(Serialize, Deserialize, Debug)] + struct HttpBinAnything { + pub method: String, + pub url: String, + } + + impl RestPath<()> for HttpBinAnything { + fn get_path(_: ()) -> Result { + Ok(format!("anything")) + } + } + + let base_url = Url::parse("https://httpbin.org").unwrap(); + let root_certificates = vec![ + COINGECKO_ROOT_CERTIFICATE_LETSENCRYPT.to_string(), + COINGECKO_ROOT_CERTIFICATE_BALTIMORE.to_string(), + ]; + + let http_client = HttpClient::new( + SendWithCertificateVerification::new(root_certificates), + true, + Some(Duration::from_secs(3u64)), + Some(headers_connection_close()), + None, + ); + + let result = + http_client.send_request::<(), HttpBinAnything>(base_url, Method::GET, (), None, None); + assert_matches!(result, Err(Error::HttpReqError(_))); + let msg = format!("error {:?}", result.err()); + assert!(msg.contains("UnknownIssuer")); + } + + fn headers_connection_close() -> Headers { + let mut headers = Headers::new(); + add_to_headers(&mut headers, CONNECTION, HeaderValue::from_str("close").unwrap()); + headers + } + + fn deserialize_response_body<'a, T>(encoded_body: &'a [u8]) -> Result + where + T: Deserialize<'a>, + { + serde_json::from_slice::<'a, T>(encoded_body).map_err(|err| { + Error::DeserializeParseError(err, String::from_utf8_lossy(encoded_body).to_string()) + }) + } +} diff --git a/bitacross-worker/core/rest-client/src/http_client_builder.rs b/bitacross-worker/core/rest-client/src/http_client_builder.rs new file mode 100644 index 0000000000..1b51fc51a8 --- /dev/null +++ b/bitacross-worker/core/rest-client/src/http_client_builder.rs @@ -0,0 +1,112 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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(all(not(feature = "std"), feature = "sgx"))] +use crate::sgx_reexport_prelude::*; + +use crate::{http_client, http_client::HttpClient}; +use http_req::response::Headers; +use std::{string::String, time::Duration}; + +/// Builder for `HttpClient` +pub struct HttpClientBuilder { + send: SendType, + + /// Request timeout + timeout: Duration, + + /// Send null body + send_null_body: bool, + + /// pre-set headers + headers: Option, + + /// authorization + authorization: Option, +} + +impl Default for HttpClientBuilder +where + SendType: Default, +{ + fn default() -> Self { + Self { + send: SendType::default(), + timeout: Duration::from_secs(u64::MAX), + send_null_body: true, + headers: None, + authorization: None, + } + } +} + +impl HttpClientBuilder +where + SendType: http_client::Send, +{ + /// Set send method. + /// + /// Default is calling the default send of http-req lib: all Mozilla's root certificates + /// are trusted. + pub fn send(mut self, send: SendType) -> Self { + self.send = send; + self + } + + /// Set request timeout + /// + /// Default is no timeout + pub fn timeout(mut self, timeout: Duration) -> Self { + self.timeout = timeout; + self + } + + /// Send null body in POST/PUT + /// + /// Default is yes + pub fn send_null_body(mut self, value: bool) -> Self { + self.send_null_body = value; + self + } + + /// Pre-set headers to attach to each request + /// + /// default is none + pub fn headers(mut self, headers: Headers) -> Self { + self.headers = Some(headers); + self + } + + /// Basic HTTP authorization (format: `username:password`) + /// + /// default is none + pub fn authorization(mut self, authorization: String) -> Self { + self.authorization = Some(authorization); + self + } + + /// Create `HttpClient` with the configuration in this builder + pub fn build(self) -> HttpClient { + HttpClient::::new( + self.send, + self.send_null_body, + Some(self.timeout), + self.headers, + self.authorization, + ) + } +} diff --git a/bitacross-worker/core/rest-client/src/lib.rs b/bitacross-worker/core/rest-client/src/lib.rs new file mode 100644 index 0000000000..8a397cefb8 --- /dev/null +++ b/bitacross-worker/core/rest-client/src/lib.rs @@ -0,0 +1,182 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +//! REST API Client, supporting SSL/TLS + +#![cfg_attr(not(feature = "std"), no_std)] +#![cfg_attr(test, feature(assert_matches))] + +#[cfg(all(feature = "std", feature = "sgx"))] +compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the same time"); + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +#[macro_use] +extern crate sgx_tstd as std; + +// re-export module to properly feature gate sgx and regular std environment +#[cfg(all(not(feature = "std"), feature = "sgx"))] +pub mod sgx_reexport_prelude { + pub use http_req_sgx as http_req; + pub use http_sgx as http; + pub use thiserror_sgx as thiserror; + pub use url_sgx as url; +} + +pub mod error; +pub mod http_client; +pub mod http_client_builder; +pub mod rest_client; + +#[cfg(test)] +pub mod mocks; + +use crate::error::Error; +use std::string::String; + +/// Type for URL query parameters. +/// +/// Slice of tuples in which the first field is parameter name and second is value. +/// These parameters are used with `get_with` and `post_with` functions. +/// +/// # Examples +/// The vector +/// ```ignore +/// vec![("param1", "1234"), ("param2", "abcd")] +/// ``` +/// would be parsed to **param1=1234¶m2=abcd** in the request URL. +pub type Query<'a> = [(&'a str, &'a str)]; + +/// Rest path builder trait for type. +/// +/// Provides implementation for `rest_path` function that builds +/// type (and REST endpoint) specific API path from given parameter(s). +/// The built REST path is appended to the base URL given to `RestClient`. +/// If `Err` is returned, it is propagated directly to API caller. +pub trait RestPath { + /// Construct type specific REST API path from given parameters + /// (e.g. "api/devices/1234"). + fn get_path(par: T) -> Result; +} + +/// REST HTTP GET trait +/// +/// Provides the GET verb for a REST API +pub trait RestGet { + /// Plain GET request + fn get(&mut self, params: U) -> Result + where + T: serde::de::DeserializeOwned + RestPath; + + /// GET request with query parameters. + fn get_with(&mut self, params: U, query: &Query<'_>) -> Result + where + T: serde::de::DeserializeOwned + RestPath; +} + +/// REST HTTP POST trait +/// +/// Provides the POST verb for a REST API +pub trait RestPost { + /// Plain POST request. + fn post(&mut self, params: U, data: &T) -> Result<(), Error> + where + T: serde::Serialize + RestPath; + + /// Make POST request with query parameters. + fn post_with(&mut self, params: U, data: &T, query: &Query<'_>) -> Result<(), Error> + where + T: serde::Serialize + RestPath; + + /// Make a POST request and capture returned body. + fn post_capture(&mut self, params: U, data: &T) -> Result + where + T: serde::Serialize + RestPath, + K: serde::de::DeserializeOwned; + + /// Make a POST request with query parameters and capture returned body. + fn post_capture_with( + &mut self, + params: U, + data: &T, + query: &Query<'_>, + ) -> Result + where + T: serde::Serialize + RestPath, + K: serde::de::DeserializeOwned; +} + +/// REST HTTP PUT trait +/// +/// Provides the PUT verb for a REST API +pub trait RestPut { + /// PUT request. + fn put(&mut self, params: U, data: &T) -> Result<(), Error> + where + T: serde::Serialize + RestPath; + + /// Make PUT request with query parameters. + fn put_with(&mut self, params: U, data: &T, query: &Query<'_>) -> Result<(), Error> + where + T: serde::Serialize + RestPath; + + /// Make a PUT request and capture returned body. + fn put_capture(&mut self, params: U, data: &T) -> Result + where + T: serde::Serialize + RestPath, + K: serde::de::DeserializeOwned; + + /// Make a PUT request with query parameters and capture returned body. + fn put_capture_with( + &mut self, + params: U, + data: &T, + query: &Query<'_>, + ) -> Result + where + T: serde::Serialize + RestPath, + K: serde::de::DeserializeOwned; +} + +/// REST HTTP PATCH trait +/// +/// Provides the PATCH verb for a REST API +pub trait RestPatch { + /// Make a PATCH request. + fn patch(&mut self, params: U, data: &T) -> Result<(), Error> + where + T: serde::Serialize + RestPath; + + /// Make PATCH request with query parameters. + fn patch_with(&mut self, params: U, data: &T, query: &Query<'_>) -> Result<(), Error> + where + T: serde::Serialize + RestPath; +} + +/// REST HTTP DELETE trait +/// +/// Provides the DELETE verb for a REST API +pub trait RestDelete { + /// Make a DELETE request. + fn delete(&mut self, params: U) -> Result<(), Error> + where + T: RestPath; + + /// Make a DELETE request with query and body. + fn delete_with(&mut self, params: U, data: &T, query: &Query<'_>) -> Result<(), Error> + where + T: serde::Serialize + RestPath; +} diff --git a/bitacross-worker/core/rest-client/src/mocks/http_client_mock.rs b/bitacross-worker/core/rest-client/src/mocks/http_client_mock.rs new file mode 100644 index 0000000000..454165ac39 --- /dev/null +++ b/bitacross-worker/core/rest-client/src/mocks/http_client_mock.rs @@ -0,0 +1,144 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{ + error::Error, + http_client::{EncodedBody, SendHttpRequest}, + Query, RestPath, +}; +use http_req::{request::Method, response::Response}; +use serde::{Deserialize, Serialize}; +use url::Url; + +const DEFAULT_HEAD: &[u8; 102] = b"HTTP/1.1 200 OK\r\n\ + Date: Sat, 11 Jan 2003 02:44:04 GMT\r\n\ + Content-Type: text/html\r\n\ + Content-Length: 100\r\n\r\n"; + +/// Response body returned by the HTTP client mock, contains information passed in by caller +#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)] +pub struct ResponseBodyMock { + pub base_url: String, + pub method: String, + pub path: String, + pub request_body: Option, + pub query_parameters: Vec<(String, String)>, +} + +impl RestPath for ResponseBodyMock { + fn get_path(path: String) -> Result { + Ok(format!("{}", path)) + } +} + +/// HTTP client mock - to be used in unit tests +pub struct HttpClientMock { + response: Option, +} + +impl HttpClientMock { + pub fn new(response: Option) -> Self { + HttpClientMock { response } + } +} + +impl SendHttpRequest for HttpClientMock { + fn send_request( + &self, + base_url: Url, + method: Method, + params: U, + query: Option<&Query<'_>>, + maybe_body: Option, + ) -> Result<(Response, EncodedBody), Error> + where + T: RestPath, + { + let path = T::get_path(params)?; + let response = self + .response + .clone() + .unwrap_or_else(|| Response::from_head(DEFAULT_HEAD).unwrap()); + let base_url_str = String::from(base_url.as_str()); + + let query_parameters = query + .map(|q| q.iter().map(|(key, value)| (key.to_string(), value.to_string())).collect()) + .unwrap_or_else(|| Vec::<(String, String)>::new()); + + let response_body = ResponseBodyMock { + base_url: base_url_str, + method: format!("{:?}", method), + path, + request_body: maybe_body, + query_parameters, + }; + + let encoded_response_body = serde_json::to_vec(&response_body).unwrap(); + + Ok((response, encoded_response_body)) + } +} + +#[cfg(test)] +mod tests { + + use super::*; + + #[test] + pub fn response_body_mock_serialization_works() { + let response_body_mock = ResponseBodyMock { + base_url: "https://mydomain.com".to_string(), + method: "GET".to_string(), + path: "/api/v1".to_string(), + request_body: None, + query_parameters: vec![("order".to_string(), "desc".to_string())], + }; + + let serialized_body = serde_json::to_string(&response_body_mock).unwrap(); + let deserialized_body: ResponseBodyMock = + serde_json::from_str(serialized_body.as_str()).unwrap(); + + assert_eq!(deserialized_body, response_body_mock); + } + + #[test] + pub fn default_head_is_valid() { + assert!(Response::from_head(DEFAULT_HEAD).is_ok()); + } + + #[test] + pub fn client_mock_returns_parameters_in_result() { + let client_mock = HttpClientMock::new(None); + let base_url = Url::parse("https://integritee.network").unwrap(); + + let (response, encoded_response_body) = client_mock + .send_request::( + base_url, + Method::GET, + "/api/v1/get".to_string(), + None, + None, + ) + .unwrap(); + + let response_body: ResponseBodyMock = + serde_json::from_slice(encoded_response_body.as_slice()).unwrap(); + + assert_eq!(response, Response::from_head(DEFAULT_HEAD).unwrap()); + assert_eq!(response_body.method.as_str(), "GET"); + } +} diff --git a/bitacross-worker/core/rest-client/src/mocks/mod.rs b/bitacross-worker/core/rest-client/src/mocks/mod.rs new file mode 100644 index 0000000000..404a1b35d3 --- /dev/null +++ b/bitacross-worker/core/rest-client/src/mocks/mod.rs @@ -0,0 +1,18 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 http_client_mock; diff --git a/bitacross-worker/core/rest-client/src/rest_client.rs b/bitacross-worker/core/rest-client/src/rest_client.rs new file mode 100644 index 0000000000..187553abc6 --- /dev/null +++ b/bitacross-worker/core/rest-client/src/rest_client.rs @@ -0,0 +1,354 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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(all(not(feature = "std"), feature = "sgx"))] +use crate::sgx_reexport_prelude::*; + +pub use http_req::{request::Method, response::Headers}; +pub use url::Url; + +use crate::{ + error::Error, http_client::SendHttpRequest, Query, RestDelete, RestGet, RestPatch, RestPath, + RestPost, RestPut, +}; + +use log::*; +use std::string::{String, ToString}; + +/// REST client to make HTTP GET and POST requests. +pub struct RestClient { + http_client: H, + baseurl: Url, + response_headers: Headers, + body_wash_fn: fn(String) -> String, +} + +impl RestClient +where + H: SendHttpRequest, +{ + /// Construct new client with default configuration to make HTTP requests. + /// + /// Use `Builder` to configure the client. + pub fn new(http_client: H, baseurl: Url) -> Self { + RestClient { + http_client, + baseurl, + response_headers: Headers::new(), + body_wash_fn: std::convert::identity, + } + } + + /// Set a function that cleans the response body up before deserializing it. + pub fn set_body_wash_fn(&mut self, func: fn(String) -> String) { + self.body_wash_fn = func; + } + + /// Response headers captured from previous request + pub fn response_headers(&mut self) -> &Headers { + &self.response_headers + } + + fn post_or_put(&mut self, method: Method, params: U, data: &T) -> Result<(), Error> + where + T: serde::Serialize + RestPath, + { + let data = serde_json::to_string(data).map_err(Error::SerializeParseError)?; + + let _body = self.make_request::(method, params, None, Some(data))?; + Ok(()) + } + + fn post_or_put_with( + &mut self, + method: Method, + params: U, + data: &T, + query: &Query<'_>, + ) -> Result<(), Error> + where + T: serde::Serialize + RestPath, + { + let data = serde_json::to_string(data).map_err(Error::SerializeParseError)?; + + let _body = self.make_request::(method, params, Some(query), Some(data))?; + Ok(()) + } + + fn post_or_put_capture( + &mut self, + method: Method, + params: U, + data: &T, + ) -> Result + where + T: serde::Serialize + RestPath, + K: serde::de::DeserializeOwned, + { + let data = serde_json::to_string(data).map_err(Error::SerializeParseError)?; + + let body = self.make_request::(method, params, None, Some(data))?; + serde_json::from_str(body.as_str()).map_err(|err| Error::DeserializeParseError(err, body)) + } + + fn post_or_put_capture_with( + &mut self, + method: Method, + params: U, + data: &T, + query: &Query<'_>, + ) -> Result + where + T: serde::Serialize + RestPath, + K: serde::de::DeserializeOwned, + { + let data = serde_json::to_string(data).map_err(Error::SerializeParseError)?; + + let body = self.make_request::(method, params, Some(query), Some(data))?; + serde_json::from_str(body.as_str()).map_err(|err| Error::DeserializeParseError(err, body)) + } + + fn make_request( + &mut self, + method: Method, + params: U, + query: Option<&Query<'_>>, + maybe_body: Option, + ) -> Result + where + T: RestPath, + { + let (response, encoded_body) = self.http_client.send_request::( + self.baseurl.clone(), + method, + params, + query, + maybe_body, + )?; + + self.response_headers = response.headers().clone(); + let status_code = response.status_code(); + + if !status_code.is_success() { + let status_code_num = u16::from(status_code); + let reason = String::from(status_code.reason().unwrap_or("none")); + return Err(Error::HttpError(status_code_num, reason)) + } + + let body = String::from_utf8_lossy(&encoded_body).to_string(); + + trace!("response headers: {:?}", self.response_headers); + trace!("response body: {}", body); + Ok((self.body_wash_fn)(body)) + } +} + +impl RestGet for RestClient +where + H: SendHttpRequest, +{ + /// Make a GET request. + fn get(&mut self, params: U) -> Result + where + T: serde::de::DeserializeOwned + RestPath, + { + let body = self.make_request::(Method::GET, params, None, None)?; + + serde_json::from_str(body.as_str()).map_err(|err| Error::DeserializeParseError(err, body)) + } + + /// Make a GET request with query parameters. + fn get_with(&mut self, params: U, query: &Query<'_>) -> Result + where + T: serde::de::DeserializeOwned + RestPath, + { + let body = self.make_request::(Method::GET, params, Some(query), None)?; + + serde_json::from_str(body.as_str()).map_err(|err| Error::DeserializeParseError(err, body)) + } +} + +impl RestPost for RestClient +where + H: SendHttpRequest, +{ + /// Make a POST request. + fn post(&mut self, params: U, data: &T) -> Result<(), Error> + where + T: serde::Serialize + RestPath, + { + self.post_or_put(Method::POST, params, data) + } + + /// Make POST request with query parameters. + fn post_with(&mut self, params: U, data: &T, query: &Query<'_>) -> Result<(), Error> + where + T: serde::Serialize + RestPath, + { + self.post_or_put_with(Method::POST, params, data, query) + } + + /// Make a POST request and capture returned body. + fn post_capture(&mut self, params: U, data: &T) -> Result + where + T: serde::Serialize + RestPath, + K: serde::de::DeserializeOwned, + { + self.post_or_put_capture(Method::POST, params, data) + } + + /// Make a POST request with query parameters and capture returned body. + fn post_capture_with( + &mut self, + params: U, + data: &T, + query: &Query<'_>, + ) -> Result + where + T: serde::Serialize + RestPath, + K: serde::de::DeserializeOwned, + { + self.post_or_put_capture_with(Method::POST, params, data, query) + } +} + +impl RestPut for RestClient +where + H: SendHttpRequest, +{ + /// Make a PUT request. + fn put(&mut self, params: U, data: &T) -> Result<(), Error> + where + T: serde::Serialize + RestPath, + { + self.post_or_put(Method::PUT, params, data) + } + + /// Make PUT request with query parameters. + fn put_with(&mut self, params: U, data: &T, query: &Query<'_>) -> Result<(), Error> + where + T: serde::Serialize + RestPath, + { + self.post_or_put_with(Method::PUT, params, data, query) + } + + /// Make a PUT request and capture returned body. + fn put_capture(&mut self, params: U, data: &T) -> Result + where + T: serde::Serialize + RestPath, + K: serde::de::DeserializeOwned, + { + self.post_or_put_capture(Method::PUT, params, data) + } + + /// Make a PUT request with query parameters and capture returned body. + fn put_capture_with( + &mut self, + params: U, + data: &T, + query: &Query<'_>, + ) -> Result + where + T: serde::Serialize + RestPath, + K: serde::de::DeserializeOwned, + { + self.post_or_put_capture_with(Method::PUT, params, data, query) + } +} + +impl RestPatch for RestClient +where + H: SendHttpRequest, +{ + /// Make a PATCH request. + fn patch(&mut self, params: U, data: &T) -> Result<(), Error> + where + T: serde::Serialize + RestPath, + { + self.post_or_put(Method::PATCH, params, data) + } + + /// Make PATCH request with query parameters. + fn patch_with(&mut self, params: U, data: &T, query: &Query<'_>) -> Result<(), Error> + where + T: serde::Serialize + RestPath, + { + self.post_or_put_with(Method::PATCH, params, data, query) + } +} + +impl RestDelete for RestClient +where + H: SendHttpRequest, +{ + /// Make a DELETE request. + fn delete(&mut self, params: U) -> Result<(), Error> + where + T: RestPath, + { + self.make_request::(Method::DELETE, params, None, None)?; + Ok(()) + } + + /// Make a DELETE request with query and body. + fn delete_with(&mut self, params: U, data: &T, query: &Query<'_>) -> Result<(), Error> + where + T: serde::Serialize + RestPath, + { + let data = serde_json::to_string(data).map_err(Error::SerializeParseError)?; + self.make_request::(Method::DELETE, params, Some(query), Some(data))?; + Ok(()) + } +} + +#[cfg(test)] +mod tests { + + use super::*; + use crate::mocks::http_client_mock::{HttpClientMock, ResponseBodyMock}; + + #[test] + pub fn get_sends_proper_request() { + let mut rest_client = create_default_rest_client(); + + let get_response = + rest_client.get::("/api/v2/get".to_string()).unwrap(); + + assert_eq!(get_response.method.as_str(), "GET"); + assert_eq!(get_response.path.as_str(), "/api/v2/get"); + } + + #[test] + pub fn get_with_query_parameters_works() { + let mut rest_client = create_default_rest_client(); + + let get_response = rest_client + .get_with::( + "/api/v1/get".to_string(), + &[("order", "desc"), ("user", "spongebob")], + ) + .unwrap(); + + assert_eq!(2, get_response.query_parameters.len()); + } + + fn create_default_rest_client() -> RestClient { + let base_url = Url::parse("https://example.com").unwrap(); + let http_client = HttpClientMock::new(None); + RestClient::new(http_client, base_url) + } +} diff --git a/bitacross-worker/core/rpc-client/Cargo.toml b/bitacross-worker/core/rpc-client/Cargo.toml new file mode 100644 index 0000000000..fc06593ed3 --- /dev/null +++ b/bitacross-worker/core/rpc-client/Cargo.toml @@ -0,0 +1,40 @@ +[package] +name = "itc-rpc-client" +version = "0.9.0" +authors = ['Trust Computing GmbH ', 'Integritee AG '] +edition = "2021" + +[dependencies] +# crates.io +base58 = "0.2" +codec = { package = "parity-scale-codec", version = "3.0.0", features = ["derive"] } +log = "0.4" +openssl = { version = "0.10" } +parking_lot = "0.12.1" +serde_json = "1.0" +sgx_crypto_helper = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git" } +thiserror = { version = "1.0" } +url = { version = "2.0.0" } +ws = { version = "0.9.1", features = ["ssl"] } + +# parity +frame-metadata = { version = "15.1.0", features = ["v14"] } +sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42", default-features = false } + +# local +itp-api-client-types = { path = "../../core-primitives/node-api/api-client-types" } +itp-rpc = { path = "../../core-primitives/rpc" } +itp-types = { path = "../../core-primitives/types" } +itp-utils = { path = "../../core-primitives/utils" } + +# litentry +ita-stf = { path = "../../app-libs/stf" } +itp-stf-primitives = { path = "../../core-primitives/stf-primitives" } +litentry-primitives = { path = "../../litentry/primitives", default-features = false } +teerex-primitives = { path = "../../../primitives/teerex", default-features = false } + +[dev-dependencies] +env_logger = "0.9.0" +itc-tls-websocket-server = { path = "../tls-websocket-server", features = ["mocks"] } +itp-networking-utils = { path = "../../core-primitives/networking-utils" } +rustls = { version = "0.19", features = ["dangerous_configuration"] } diff --git a/bitacross-worker/core/rpc-client/src/direct_client.rs b/bitacross-worker/core/rpc-client/src/direct_client.rs new file mode 100644 index 0000000000..5f7acab959 --- /dev/null +++ b/bitacross-worker/core/rpc-client/src/direct_client.rs @@ -0,0 +1,369 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +//! Interface for direct access to a workers rpc. + +use crate::ws_client::{WsClient, WsClientControl}; +use base58::ToBase58; +use codec::{Decode, Encode}; +use frame_metadata::RuntimeMetadataPrefixed; +use ita_stf::Getter; +use itp_api_client_types::Metadata; +use itp_rpc::{Id, RpcRequest, RpcResponse, RpcReturnValue}; +use itp_stf_primitives::types::{AccountId, ShardIdentifier}; +use itp_types::{DirectRequestStatus, RsaRequest}; +use itp_utils::{FromHexPrefixed, ToHexPrefixed}; +use log::*; +use sgx_crypto_helper::rsa3072::Rsa3072PubKey; +use std::{ + sync::{ + mpsc::{channel, Sender as MpscSender}, + Arc, + }, + thread, + thread::JoinHandle, +}; +use teerex_primitives::MrEnclave; + +pub use crate::error::{Error, Result}; + +#[derive(Clone)] +pub struct DirectClient { + url: String, + web_socket_control: Arc, +} +pub trait DirectApi { + /// Server connection with only one response. + fn get(&self, request: &str) -> Result; + /// Server connection with more than one response. + fn watch(&self, request: String, sender: MpscSender) -> JoinHandle<()>; + fn get_rsa_pubkey(&self) -> Result; + fn get_mu_ra_url(&self) -> Result; + fn get_untrusted_worker_url(&self) -> Result; + fn get_state_metadata(&self) -> Result; + fn send(&self, request: &str) -> Result<()>; + /// Close any open websocket connection. + fn close(&self) -> Result<()>; + + // litentry + fn get_state_metadata_raw(&self) -> Result; + fn get_next_nonce(&self, shard: &ShardIdentifier, account: &AccountId) -> Result; + fn get_state_mrenclave(&self) -> Result; +} + +impl DirectClient { + pub fn new(url: String) -> Self { + Self { url, web_socket_control: Default::default() } + } + + // litentry: moved from `cli/src/trusted_operation.rs` as it's more widely used + pub fn get_state(&self, shard: ShardIdentifier, getter: &Getter) -> Option> { + // Compose jsonrpc call. + let data = RsaRequest::new(shard, getter.encode()); + let rpc_method = "state_executeGetter".to_owned(); + let jsonrpc_call: String = RpcRequest::compose_jsonrpc_call( + Id::Text("1".to_string()), + rpc_method, + vec![data.to_hex()], + ) + .unwrap(); + + let rpc_response_str = self.get(&jsonrpc_call).unwrap(); + + // Decode RPC response. + let rpc_response: RpcResponse = serde_json::from_str(&rpc_response_str).ok()?; + let rpc_return_value = RpcReturnValue::from_hex(&rpc_response.result) + // Replace with `inspect_err` once it's stable. + .map_err(|e| { + error!("Failed to decode RpcReturnValue: {:?}", e); + e + }) + .ok()?; + + if rpc_return_value.status == DirectRequestStatus::Error { + println!("[Error] {}", String::decode(&mut rpc_return_value.value.as_slice()).unwrap()); + return None + } + + let maybe_state = Option::decode(&mut rpc_return_value.value.as_slice()) + // Replace with `inspect_err` once it's stable. + .map_err(|e| { + error!("Failed to decode return value: {:?}", e); + e + }) + .ok()?; + + maybe_state + } + + // common helper function for `get_state_metadata` and `get_state_metadata_raw` + fn get_metadata_internal(&self) -> Result { + let jsonrpc_call: String = RpcRequest::compose_jsonrpc_call( + Id::Text("1".to_string()), + "state_getMetadata".to_string(), + Default::default(), + )?; + + // Send json rpc call to ws server. + let response_str = self.get(&jsonrpc_call)?; + + // Decode rpc response. + let rpc_response: RpcResponse = serde_json::from_str(&response_str)?; + let rpc_return_value = RpcReturnValue::from_hex(&rpc_response.result) + .map_err(|e| Error::Custom(format!("{:?}", e).into()))?; + + // Decode Metadata. + RuntimeMetadataPrefixed::decode(&mut rpc_return_value.value.as_slice()) + .map_err(|e| e.into()) + } +} + +impl Drop for DirectClient { + fn drop(&mut self) { + if let Err(e) = self.close() { + error!("Failed to close web-socket connection: {:?}", e); + } + } +} + +impl DirectApi for DirectClient { + fn get(&self, request: &str) -> Result { + let (port_in, port_out) = channel(); + + info!("[WorkerApi Direct]: (get) Sending request: {:?}", request); + WsClient::connect_one_shot(&self.url, request, port_in)?; + debug!("Waiting for web-socket result.."); + port_out.recv().map_err(Error::MspcReceiver) + } + + fn watch(&self, request: String, sender: MpscSender) -> JoinHandle<()> { + info!("[WorkerApi Direct]: (watch) Sending request: {:?}", request); + let url = self.url.clone(); + + let web_socket_control = self.web_socket_control.clone(); + // Unwrap is fine here, because JoinHandle can be used to handle a Thread panic. + thread::spawn(move || { + WsClient::connect_watch_with_control(&url, &request, &sender, web_socket_control) + .expect("Connection failed") + }) + } + + fn get_rsa_pubkey(&self) -> Result { + let jsonrpc_call: String = RpcRequest::compose_jsonrpc_call( + Id::Text("1".to_string()), + "author_getShieldingKey".to_string(), + Default::default(), + )?; + + // Send json rpc call to ws server. + let response_str = self.get(&jsonrpc_call)?; + + let shielding_pubkey_string = decode_from_rpc_response::(&response_str)?; + let shielding_pubkey: Rsa3072PubKey = serde_json::from_str(&shielding_pubkey_string)?; + + info!("[+] Got RSA public key of enclave"); + Ok(shielding_pubkey) + } + + fn get_mu_ra_url(&self) -> Result { + let jsonrpc_call: String = RpcRequest::compose_jsonrpc_call( + Id::Text("1".to_string()), + "author_getMuRaUrl".to_string(), + Default::default(), + )?; + + // Send json rpc call to ws server. + let response_str = self.get(&jsonrpc_call)?; + + let mu_ra_url: String = decode_from_rpc_response::(&response_str)?; + + info!("[+] Got mutual remote attestation url of enclave: {}", mu_ra_url); + Ok(mu_ra_url) + } + + fn get_untrusted_worker_url(&self) -> Result { + let jsonrpc_call: String = RpcRequest::compose_jsonrpc_call( + Id::Text("1".to_string()), + "author_getUntrustedUrl".to_string(), + Default::default(), + )?; + + // Send json rpc call to ws server. + let response_str = self.get(&jsonrpc_call)?; + + let untrusted_url: String = decode_from_rpc_response::(&response_str)?; + + info!("[+] Got untrusted websocket url of worker: {}", untrusted_url); + Ok(untrusted_url) + } + + fn get_state_metadata(&self) -> Result { + let metadata = self.get_metadata_internal()?; + Metadata::try_from(metadata).map_err(|e| e.into()) + } + + fn send(&self, request: &str) -> Result<()> { + self.web_socket_control.send(request) + } + + fn close(&self) -> Result<()> { + self.web_socket_control.close_connection() + } + + fn get_state_metadata_raw(&self) -> Result { + let metadata = self.get_metadata_internal()?.to_hex(); + let rpc_response = + RpcResponse { jsonrpc: "2.0".to_owned(), result: metadata, id: Id::Number(1) }; + serde_json::to_string(&rpc_response).map_err(|e| Error::Custom(Box::new(e))) + } + + fn get_next_nonce(&self, shard: &ShardIdentifier, account: &AccountId) -> Result { + let jsonrpc_call: String = RpcRequest::compose_jsonrpc_call( + Id::Text("1".to_string()), + "author_getNextNonce".to_owned(), + vec![shard.encode().to_base58(), account.to_hex()], + ) + .unwrap(); + debug!("[+] get_next_nonce jsonrpc_call: {}", jsonrpc_call); + // Send json rpc call to ws server. + let response_str = self.get(&jsonrpc_call)?; + debug!("[+] get_next_nonce response_str: {}", response_str); + decode_from_rpc_response::(&response_str) + } + + fn get_state_mrenclave(&self) -> Result { + let jsonrpc_call: String = RpcRequest::compose_jsonrpc_call( + Id::Text("1".to_string()), + "state_getMrenclave".to_string(), + Default::default(), + )?; + + // Send json rpc call to ws server. + let response_str = self.get(&jsonrpc_call)?; + + let mrenclave: MrEnclave = decode_from_rpc_response::(&response_str)?; + + info!("[+] Got enclave: {:?}", mrenclave); + Ok(mrenclave) + } +} + +fn decode_from_rpc_response(json_rpc_response: &str) -> Result { + let rpc_response: RpcResponse = serde_json::from_str(json_rpc_response)?; + let rpc_return_value = RpcReturnValue::from_hex(&rpc_response.result) + .map_err(|e| Error::Custom(format!("{:?}", e).into()))?; + + let response_message = T::decode(&mut rpc_return_value.value.as_slice())?; + match rpc_return_value.status { + DirectRequestStatus::Ok => Ok(response_message), + _ => Err(Error::Status(format!("decode_response failed to decode {:?}", response_message))), + } +} + +#[cfg(test)] +mod tests { + use super::*; + use itc_tls_websocket_server::{test::fixtures::test_server::create_server, WebSocketServer}; + use itp_networking_utils::ports::get_available_port_in_range; + use std::vec; + + #[test] + fn watch_works_and_closes_connection_on_demand() { + let _ = env_logger::builder().is_test(true).try_init(); + + const END_MESSAGE: &str = "End of service."; + let responses = vec![END_MESSAGE.to_string()]; + + let port = get_available_port_in_range(21000..21500).unwrap(); + let (server, handler) = create_server(responses, port); + + let server_clone = server.clone(); + let server_join_handle = thread::spawn(move || { + if let Err(e) = server_clone.run() { + error!("Web-socket server failed: {:?}", e); + } + }); + + // Wait until server is up. + while !server.is_running().unwrap() { + thread::sleep(std::time::Duration::from_millis(50)); + } + + let client = DirectClient::new(format!("wss://localhost:{}", port)); + let (message_sender, message_receiver) = channel::(); + + let client_join_handle = client.watch("Request".to_string(), message_sender); + + let mut messages = Vec::::new(); + loop { + info!("Client waiting to receive answer.. "); + let message = message_receiver.recv().unwrap(); + info!("Received answer: {}", message); + let do_close = message.as_str() == END_MESSAGE; + messages.push(message); + + if do_close { + info!("Client closing connection"); + break + } + } + + info!("Joining client thread"); + client.close().unwrap(); + client_join_handle.join().unwrap(); + + info!("Joining server thread"); + server.shut_down().unwrap(); + server_join_handle.join().unwrap(); + + assert_eq!(1, messages.len()); + assert_eq!(1, handler.messages_handled.read().unwrap().len()); + } + + #[test] + fn get_works_and_closes_connection() { + let _ = env_logger::builder().is_test(true).try_init(); + + let server_response = "response 1".to_string(); + let responses = vec![server_response.clone()]; + + let port = get_available_port_in_range(21501..22000).unwrap(); + let (server, handler) = create_server(responses, port); + + let server_clone = server.clone(); + let server_join_handle = thread::spawn(move || { + if let Err(e) = server_clone.run() { + error!("Web-socket server failed: {:?}", e); + } + }); + + // Wait until server is up. + while !server.is_running().unwrap() { + thread::sleep(std::time::Duration::from_millis(50)); + } + + let client = DirectClient::new(format!("wss://localhost:{}", port)); + let received_response = client.get("Request").unwrap(); + + info!("Joining server thread"); + server.shut_down().unwrap(); + server_join_handle.join().unwrap(); + + assert_eq!(server_response, received_response); + assert_eq!(1, handler.messages_handled.read().unwrap().len()); + } +} diff --git a/bitacross-worker/core/rpc-client/src/error.rs b/bitacross-worker/core/rpc-client/src/error.rs new file mode 100644 index 0000000000..f5ef6541c8 --- /dev/null +++ b/bitacross-worker/core/rpc-client/src/error.rs @@ -0,0 +1,48 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::Error as CodecError; +use itp_api_client_types::InvalidMetadataError; +use serde_json::Error as JsonError; +use std::{boxed::Box, sync::mpsc::RecvError}; +use thiserror; +use ws::Error as WsClientError; + +pub type Result = core::result::Result; + +#[derive(Debug, thiserror::Error)] +pub enum Error { + #[error("{0}")] + Codec(#[from] CodecError), + #[error("{0}")] + SerdeJson(#[from] JsonError), + #[error("Validateer returned the following error message: {0}")] + Status(String), + #[error("Websocket error: {0}")] + WsClientError(#[from] WsClientError), + #[error("Faulty channel: {0}")] + MspcReceiver(#[from] RecvError), + #[error("InvalidMetadata: {0:?}")] + InvalidMetadata(InvalidMetadataError), + #[error("Custom Error: {0}")] + Custom(Box), +} + +impl From for Error { + fn from(error: InvalidMetadataError) -> Self { + Error::InvalidMetadata(error) + } +} diff --git a/bitacross-worker/core/rpc-client/src/lib.rs b/bitacross-worker/core/rpc-client/src/lib.rs new file mode 100644 index 0000000000..59c9949911 --- /dev/null +++ b/bitacross-worker/core/rpc-client/src/lib.rs @@ -0,0 +1,22 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 direct_client; +pub mod error; +#[cfg(test)] +pub mod mock; +pub mod ws_client; diff --git a/bitacross-worker/core/rpc-client/src/mock.rs b/bitacross-worker/core/rpc-client/src/mock.rs new file mode 100644 index 0000000000..d61290c035 --- /dev/null +++ b/bitacross-worker/core/rpc-client/src/mock.rs @@ -0,0 +1,122 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +//! Interface for direct access to a workers rpc. + +use crate::{direct_client::DirectApi, error::Result}; +use codec::Decode; +use frame_metadata::RuntimeMetadataPrefixed; +use ita_stf::H256; +use itp_api_client_types::Metadata; +use itp_stf_primitives::types::{AccountId, ShardIdentifier}; +use litentry_primitives::Identity; +use sgx_crypto_helper::rsa3072::Rsa3072PubKey; +use std::{sync::mpsc::Sender as MpscSender, thread::JoinHandle}; +use teerex_primitives::MrEnclave; + +#[derive(Clone, Default)] +pub struct DirectClientMock { + rsa_pubkey: Rsa3072PubKey, + mu_ra_url: String, + untrusted_worker_url: String, + metadata: String, + nonce: u32, +} + +impl DirectClientMock { + pub fn new( + rsa_pubkey: Rsa3072PubKey, + mu_ra_url: String, + untrusted_worker_url: String, + metadata: String, + nonce: u32, + ) -> Self { + Self { rsa_pubkey, mu_ra_url, untrusted_worker_url, metadata, nonce } + } + + pub fn with_rsa_pubkey(mut self, key: Rsa3072PubKey) -> Self { + self.rsa_pubkey = key; + self + } + + pub fn with_mu_ra_url(mut self, url: &str) -> Self { + self.mu_ra_url = url.to_string(); + self + } + + pub fn with_untrusted_worker_url(mut self, url: &str) -> Self { + self.untrusted_worker_url = url.to_string(); + self + } + + pub fn with_metadata(mut self, metadata: String) -> Self { + self.metadata = metadata; + self + } + + pub fn with_nonce(mut self, nonce: u32) -> Self { + self.nonce = nonce; + self + } +} + +impl DirectApi for DirectClientMock { + fn get(&self, _request: &str) -> Result { + Ok("Hello_world".to_string()) + } + + fn watch(&self, _request: String, _sender: MpscSender) -> JoinHandle<()> { + unimplemented!() + } + + fn get_rsa_pubkey(&self) -> Result { + Ok(self.rsa_pubkey) + } + + fn get_mu_ra_url(&self) -> Result { + Ok(self.mu_ra_url.clone()) + } + + fn get_untrusted_worker_url(&self) -> Result { + Ok(self.untrusted_worker_url.clone()) + } + + fn get_state_metadata(&self) -> Result { + let metadata = RuntimeMetadataPrefixed::decode(&mut self.metadata.as_bytes())?; + Metadata::try_from(metadata).map_err(|e| e.into()) + } + + fn send(&self, _request: &str) -> Result<()> { + unimplemented!() + } + + fn close(&self) -> Result<()> { + unimplemented!() + } + + fn get_state_metadata_raw(&self) -> Result { + unimplemented!() + } + + fn get_next_nonce(&self, _shard: &ShardIdentifier, _account: &AccountId) -> Result { + Ok(self.nonce) + } + + fn get_state_mrenclave(&self) -> Result { + unimplemented!() + } +} diff --git a/bitacross-worker/core/rpc-client/src/ws_client.rs b/bitacross-worker/core/rpc-client/src/ws_client.rs new file mode 100644 index 0000000000..690adc1686 --- /dev/null +++ b/bitacross-worker/core/rpc-client/src/ws_client.rs @@ -0,0 +1,168 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +///! Websocket client implementation to access the direct-rpc-server running inside an enclave. +/// +/// This should be replaced with the `jsonrpsee::WsClient`as soon as available in no-std: +/// https://github.com/paritytech/jsonrpsee/issues/1 +use crate::error::{Error, Result as RpcClientResult}; +use log::*; +use openssl::ssl::{SslConnector, SslMethod, SslStream, SslVerifyMode}; +use parking_lot::Mutex; +use std::sync::{mpsc::Sender as MpscSender, Arc}; +use url::{self}; +use ws::{connect, util::TcpStream, CloseCode, Handler, Handshake, Message, Result, Sender}; + +/// Control a registered web-socket client. +#[derive(Default)] +pub struct WsClientControl { + subscriber: Mutex>, +} + +impl Clone for WsClientControl { + fn clone(&self) -> Self { + WsClientControl { subscriber: Mutex::new(self.subscriber.lock().clone()) } + } +} + +impl WsClientControl { + pub fn close_connection(&self) -> RpcClientResult<()> { + if let Some(s) = self.subscriber.lock().as_ref() { + debug!("Closing connection"); + s.close(CloseCode::Normal)?; + debug!("Connection is closed"); + } + Ok(()) + } + + fn subscribe_sender(&self, sender: Sender) -> RpcClientResult<()> { + let mut subscriber_lock = self.subscriber.lock(); + *subscriber_lock = Some(sender); + Ok(()) + } + + pub fn send(&self, request: &str) -> RpcClientResult<()> { + if let Some(s) = self.subscriber.lock().as_ref() { + s.send(request)?; + Ok(()) + } else { + Err(Error::Custom("Sender not initialized".into())) + } + } +} + +#[derive(Clone)] +pub struct WsClient { + web_socket: Sender, + request: String, + result: MpscSender, + do_watch: bool, +} + +impl WsClient { + /// Connect a web-socket client for multiple request/responses. + /// + /// Control over the connection is done using the provided client control. + /// (e.g. shutdown has to be initiated explicitly). + #[allow(clippy::result_large_err)] + pub fn connect_watch_with_control( + url: &str, + request: &str, + result: &MpscSender, + control: Arc, + ) -> Result<()> { + debug!("Connecting web-socket connection with watch"); + connect(url.to_string(), |out| { + control.subscribe_sender(out.clone()).expect("Failed sender subscription"); + WsClient::new(out, request.to_string(), result.clone(), true) + }) + } + + /// Connects a web-socket client for a one-shot request. + #[allow(clippy::result_large_err)] + pub fn connect_one_shot(url: &str, request: &str, result: MpscSender) -> Result<()> { + debug!("Connecting one-shot web-socket connection"); + connect(url.to_string(), |out| { + debug!("Create new web-socket client"); + WsClient::new(out, request.to_string(), result.clone(), false) + }) + } + + fn new( + web_socket: Sender, + request: String, + result: MpscSender, + do_watch: bool, + ) -> WsClient { + WsClient { web_socket, request, result, do_watch } + } +} + +impl Handler for WsClient { + fn on_open(&mut self, _: Handshake) -> Result<()> { + debug!("sending request: {:?}", self.request.clone()); + match self.web_socket.send(self.request.clone()) { + Ok(_) => Ok(()), + Err(e) => Err(e), + } + } + + fn on_message(&mut self, msg: Message) -> Result<()> { + trace!("got message"); + trace!("{}", msg); + trace!("sending result to MpscSender.."); + self.result.send(msg.to_string()).expect("Failed to send"); + if !self.do_watch { + debug!("do_watch is false, closing connection"); + self.web_socket.close(CloseCode::Normal).expect("Failed to close connection"); + debug!("Connection close requested"); + } + debug!("on_message successful, returning"); + Ok(()) + } + + fn on_close(&mut self, _code: CloseCode, _reason: &str) { + debug!("Web-socket close"); + self.web_socket.shutdown().expect("Failed to shutdown") + } + + /// we are overriding the `upgrade_ssl_client` method in order to disable hostname verification + /// this is taken from https://github.com/housleyjk/ws-rs/blob/master/examples/unsafe-ssl-client.rs + /// TODO: hostname verification should probably be enabled again for production? + fn upgrade_ssl_client( + &mut self, + sock: TcpStream, + _: &url::Url, + ) -> Result> { + let mut builder = SslConnector::builder(SslMethod::tls_client()).map_err(|e| { + ws::Error::new( + ws::ErrorKind::Internal, + format!("Failed to upgrade client to SSL: {}", e), + ) + })?; + builder.set_verify(SslVerifyMode::empty()); + + let connector = builder.build(); + connector + .configure() + .expect("Invalid connection config") + .use_server_name_indication(false) + .verify_hostname(false) + .connect("", sock) + .map_err(From::from) + } +} diff --git a/bitacross-worker/core/rpc-server/Cargo.toml b/bitacross-worker/core/rpc-server/Cargo.toml new file mode 100644 index 0000000000..d7f22c184e --- /dev/null +++ b/bitacross-worker/core/rpc-server/Cargo.toml @@ -0,0 +1,30 @@ +[package] +name = "itc-rpc-server" +version = "0.9.0" +authors = ['Trust Computing GmbH ', 'Integritee AG '] +edition = "2021" + +[dependencies] +anyhow = "1.0.40" +jsonrpsee = { version = "0.2.0-alpha.7", features = ["full"] } +log = "0.4" +tokio = { version = "1.6.1", features = ["full"] } + +# local +itp-enclave-api = { path = "../../core-primitives/enclave-api" } +itp-rpc = { path = "../../core-primitives/rpc" } +itp-utils = { path = "../../core-primitives/utils" } +its-peer-fetch = { path = "../../sidechain/peer-fetch" } +its-primitives = { path = "../../sidechain/primitives" } +its-rpc-handler = { path = "../../sidechain/rpc-handler" } +its-storage = { path = "../../sidechain/storage" } + +[features] +default = ["std"] +std = [] + +[dev-dependencies] +env_logger = { version = "*" } +sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } +its-test = { path = "../../sidechain/test" } +parity-scale-codec = "3.0.0" diff --git a/bitacross-worker/core/rpc-server/src/lib.rs b/bitacross-worker/core/rpc-server/src/lib.rs new file mode 100644 index 0000000000..1386f0de4d --- /dev/null +++ b/bitacross-worker/core/rpc-server/src/lib.rs @@ -0,0 +1,81 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 itp_enclave_api::direct_request::DirectRequest; +use itp_rpc::{Id, RpcRequest}; +use itp_utils::ToHexPrefixed; +use its_peer_fetch::block_fetch_server::BlockFetchServerModuleBuilder; +use its_primitives::types::block::SignedBlock; +use its_rpc_handler::constants::RPC_METHOD_NAME_IMPORT_BLOCKS; +use its_storage::interface::FetchBlocks; +use jsonrpsee::{ + types::error::CallError, + ws_server::{RpcModule, WsServerBuilder}, +}; +use log::debug; +use std::{net::SocketAddr, sync::Arc}; +use tokio::net::ToSocketAddrs; + +#[cfg(test)] +mod mock; +#[cfg(test)] +mod tests; + +pub async fn run_server( + addr: impl ToSocketAddrs, + enclave: Arc, + sidechain_block_fetcher: Arc, +) -> anyhow::Result +where + Enclave: DirectRequest, + FetchSidechainBlocks: FetchBlocks + Send + Sync + 'static, +{ + let mut server = WsServerBuilder::default().build(addr).await?; + + // FIXME: import block should be moved to trusted side. + let mut import_sidechain_block_module = RpcModule::new(enclave); + import_sidechain_block_module.register_method( + RPC_METHOD_NAME_IMPORT_BLOCKS, + |params, enclave| { + debug!("{} params: {:?}", RPC_METHOD_NAME_IMPORT_BLOCKS, params); + + let enclave_req = RpcRequest::compose_jsonrpc_call( + Id::Text("1".to_string()), + RPC_METHOD_NAME_IMPORT_BLOCKS.into(), + vec![params.one::>()?.to_hex()], + ) + .unwrap(); + + enclave + .rpc(enclave_req.as_bytes().to_vec()) + .map_err(|e| CallError::Failed(e.into())) + }, + )?; + server.register_module(import_sidechain_block_module).unwrap(); + + let fetch_sidechain_blocks_module = BlockFetchServerModuleBuilder::new(sidechain_block_fetcher) + .build() + .map_err(|e| CallError::Failed(e.to_string().into()))?; // `to_string` necessary due to no all errors implementing Send + Sync. + server.register_module(fetch_sidechain_blocks_module).unwrap(); + + let socket_addr = server.local_addr()?; + tokio::spawn(async move { server.start().await }); + + println!("[+] Untrusted RPC server is spawned on: {}", socket_addr); + + Ok(socket_addr) +} diff --git a/bitacross-worker/core/rpc-server/src/mock.rs b/bitacross-worker/core/rpc-server/src/mock.rs new file mode 100644 index 0000000000..172c1a7528 --- /dev/null +++ b/bitacross-worker/core/rpc-server/src/mock.rs @@ -0,0 +1,75 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 itp_enclave_api::{direct_request::DirectRequest, EnclaveResult}; +use itp_rpc::{Id, RpcResponse}; +use itp_utils::ToHexPrefixed; +use its_primitives::{ + traits::ShardIdentifierFor, + types::{BlockHash, BlockNumber, SignedBlock, SignedBlock as SignedSidechainBlock}, +}; +use its_storage::{interface::FetchBlocks, LastSidechainBlock}; +use parity_scale_codec::Encode; + +pub struct TestEnclave; + +impl DirectRequest for TestEnclave { + fn rpc(&self, _request: Vec) -> EnclaveResult> { + Ok(RpcResponse { + jsonrpc: "mock_response".into(), + result: "null".to_hex(), + id: Id::Number(1), + } + .encode()) + } +} + +pub struct MockSidechainBlockFetcher; + +impl FetchBlocks for MockSidechainBlockFetcher { + fn fetch_all_blocks_after( + &self, + _block_hash: &BlockHash, + _shard_identifier: &ShardIdentifierFor, + ) -> its_storage::Result> { + Ok(Vec::new()) + } + + fn fetch_blocks_in_range( + &self, + _block_hash_from: &BlockHash, + _block_hash_until: &BlockHash, + _shard_identifier: &ShardIdentifierFor, + ) -> its_storage::Result> { + Ok(Vec::new()) + } + + fn latest_block( + &self, + _shard_identifier: &ShardIdentifierFor, + ) -> Option { + Some(LastSidechainBlock::default()) + } + + fn block_hash( + &self, + _block_number: BlockNumber, + _shard_identifier: &ShardIdentifierFor, + ) -> Option { + Some(LastSidechainBlock::default()) + } +} diff --git a/bitacross-worker/core/rpc-server/src/tests.rs b/bitacross-worker/core/rpc-server/src/tests.rs new file mode 100644 index 0000000000..4c99081804 --- /dev/null +++ b/bitacross-worker/core/rpc-server/src/tests.rs @@ -0,0 +1,56 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +use super::*; +use crate::mock::MockSidechainBlockFetcher; +use itp_rpc::RpcResponse; +use its_rpc_handler::constants::RPC_METHOD_NAME_IMPORT_BLOCKS; +use its_test::sidechain_block_builder::{SidechainBlockBuilder, SidechainBlockBuilderTrait}; +use jsonrpsee::{ + types::{to_json_value, traits::Client}, + ws_client::WsClientBuilder, +}; +use log::info; +use mock::TestEnclave; +use parity_scale_codec::Decode; + +fn init() { + let _ = env_logger::builder().is_test(true).try_init(); +} + +#[tokio::test] +async fn test_client_calls() { + init(); + let addr = + run_server("127.0.0.1:0", Arc::new(TestEnclave), Arc::new(MockSidechainBlockFetcher)) + .await + .unwrap(); + info!("ServerAddress: {:?}", addr); + + let url = format!("ws://{}", addr); + let client = WsClientBuilder::default().build(&url).await.unwrap(); + let response: Vec = client + .request( + RPC_METHOD_NAME_IMPORT_BLOCKS, + vec![to_json_value(vec![SidechainBlockBuilder::default().build_signed()]).unwrap()] + .into(), + ) + .await + .unwrap(); + + assert!(RpcResponse::decode(&mut response.as_slice()).is_ok()); +} diff --git a/bitacross-worker/core/tls-websocket-server/Cargo.toml b/bitacross-worker/core/tls-websocket-server/Cargo.toml new file mode 100644 index 0000000000..8e4ca66442 --- /dev/null +++ b/bitacross-worker/core/tls-websocket-server/Cargo.toml @@ -0,0 +1,70 @@ +[package] +name = "itc-tls-websocket-server" +version = "0.9.0" +authors = ['Trust Computing GmbH ', 'Integritee AG '] +edition = "2021" + +[dependencies] +bit-vec = { version = "0.6", default-features = false } +chrono = { version = "0.4.19", default-features = false, features = ["alloc"] } +rcgen = { package = "rcgen", default-features = false, git = "https://github.com/integritee-network/rcgen" } + +# sgx dependencies +sgx_tstd = { optional = true, features = ["net", "thread"], git = "https://github.com/apache/teaclave-sgx-sdk.git", branch = "master" } + +# sgx enabled external libraries +mio-extras = { optional = true, default-features = false, git = "https://github.com/integritee-network/mio-extras-sgx", rev = "963234b" } +mio_sgx = { package = "mio", optional = true, git = "https://github.com/mesalock-linux/mio-sgx", tag = "sgx_1.1.3" } +rustls_sgx = { package = "rustls", optional = true, git = "https://github.com/mesalock-linux/rustls", branch = "mesalock_sgx" } +thiserror_sgx = { package = "thiserror", optional = true, git = "https://github.com/mesalock-linux/thiserror-sgx", tag = "sgx_1.1.3" } +tungstenite_sgx = { package = "tungstenite", optional = true, features = ["rustls-tls-webpki-roots"], git = "https://github.com/integritee-network/tungstenite-rs-sgx", branch = "sgx-experimental" } +webpki_sgx = { package = "webpki", optional = true, git = "https://github.com/mesalock-linux/webpki", branch = "mesalock_sgx" } +yasna_sgx = { package = "yasna", optional = true, default-features = false, features = ["bit-vec", "num-bigint", "chrono", "mesalock_sgx"], git = "https://github.com/mesalock-linux/yasna.rs-sgx", rev = "sgx_1.1.3" } + +# std compatible external libraries (make sure these versions match with the sgx-enabled ones above) +mio = { version = "0.6.14", optional = true } +rustls = { version = "0.19", optional = true } +thiserror = { version = "1.0", optional = true } +tungstenite = { version = "0.15.0", optional = true, features = ["rustls-tls-webpki-roots"] } +webpki = { version = "0.21", optional = true } +yasna = { version = "0.4", optional = true, features = ["bit-vec", "num-bigint", "chrono", "std"] } + +# Substrate dependencies +sp-core = { default-features = false, features = ["full_crypto"], git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } + +# no-std compatible libraries +log = { version = "0.4", default-features = false } + +[dev-dependencies] +env_logger = "0.9.0" +rustls = { version = "0.19", features = ["dangerous_configuration"] } +url = { version = "2.0.0" } + + +[features] +default = ["std"] +sgx = [ + "mio-extras/sgx", + "mio_sgx", + "rcgen/sgx", + "rcgen/pem_sgx", + "rustls_sgx", + "sgx_tstd", + "thiserror_sgx", + "tungstenite_sgx", + "webpki_sgx", + "yasna_sgx", +] +std = [ + "mio", + "mio-extras/std", + "rcgen/std", + "rcgen/pem", + "rustls", + "thiserror", + "tungstenite", + "webpki", + "yasna", + "log/std", +] +mocks = [] diff --git a/bitacross-worker/core/tls-websocket-server/src/certificate_generation.rs b/bitacross-worker/core/tls-websocket-server/src/certificate_generation.rs new file mode 100644 index 0000000000..0a1afaaf0a --- /dev/null +++ b/bitacross-worker/core/tls-websocket-server/src/certificate_generation.rs @@ -0,0 +1,172 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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(all(not(feature = "std"), feature = "sgx"))] +use crate::sgx_reexport_prelude::*; + +use crate::{error::WebSocketError, WebSocketResult}; +use bit_vec::BitVec; +use chrono::{prelude::*, TimeZone, Utc as TzUtc}; +use core::convert::TryFrom; +use rcgen::{date_time_ymd, Certificate, CertificateParams, DistinguishedName, DnType}; +use sp_core::{crypto::Pair, ed25519}; +use std::{ + string::ToString, + time::{SystemTime, UNIX_EPOCH}, + vec, + vec::Vec, +}; +use yasna::models::ObjectIdentifier; + +const ED25519: &[u64] = &[1, 3, 101, 112]; + +/// Create a sel-signed certificate, signed with the Ed25519 private key +/// Certificate Params are : +/// - alg: &PKCS_ED25519 -> ED25519 curve signing as per [RFC 8410](https://tools.ietf.org/html/rfc8410) +/// - common_name : the “subject”of the certificate, which is the identity of the certificate/website owner. +/// - not_before : now +/// - not_after : 4096-01-01 -> Certificate valid from initialisation time until 4096-01-01 +/// - serial_number : None, +/// - subject_alt_names : common_name. Required parameter. See below, subject +/// - DistinguishedName : +/// - issuer : Integritee, (The issuer field identifies the entity that has signed and issued the certificate. +/// The issuer field MUST contain a non-empty distinguished name (DN) ) +/// - subject: empty. (The subject field identifies the entity associated with the public key stored in the subject +/// public key field. If subject naming information is present only in the subjectAltName extension +/// (e.g., a key bound only to an email address or URI), then the subject name MUST be an empty sequence +/// and the subjectAltName extension MUST be critical. +/// - is_ca : SelfSignedOnly -> The certificate can only sign itself +/// - key_usages: empty (The key usage extension defines the purpose (e.g., encipherment, signature, certificate signing) of +/// the key contained in the certificate. The usage restriction might be employed when a key that could +/// be used for more than one operation is to be restricted.) +/// - extended_key_usages: empty ( This extension indicates one or more purposes for which the certified public key may be used, +/// in addition to or in place of the basic purposes indicated in the key usage extension.) +/// - name_constraints : None (only relevant for CA certificates) +/// - custom_extensions: None (The extensions defined for X.509 v3 certificates provide methods for associating additional +/// attributes with users or public keys and for managing relationships between CAs.) +/// - key_pair : rcgen::KeyPair from enclave private key. (A key pair used to sign certificates and CSRs) +/// - use_authority_key_identifier_extension: false (If `true` (and not self-signed), the 'Authority Key Identifier' extension will be added to the generated cert) +/// - key_identifier_method : KeyIdMethod::Sha256 (Method to generate key identifiers from public keys) + +pub fn ed25519_self_signed_certificate( + key_pair: ed25519::Pair, + common_name: &str, +) -> WebSocketResult { + let mut params = CertificateParams::new(vec![common_name.to_string()]); + let now = SystemTime::now().duration_since(UNIX_EPOCH).expect("Error: UNIX_EPOCH"); + let issue_ts = TzUtc + .timestamp_opt(now.as_secs() as i64, 0) + .single() + .expect("Error: this should not fail as long as secs fit into i64"); + let year = issue_ts.year(); + let month = issue_ts.month(); + let day = issue_ts.day(); + params.not_before = date_time_ymd(year, month, day); + params.not_after = date_time_ymd(4096, 1, 1); + let mut dn = DistinguishedName::new(); + dn.push(DnType::OrganizationName, "Integritee"); + //dn.push(DnType::CommonName, common_name); + params.distinguished_name = dn; + + params.alg = &rcgen::PKCS_ED25519; //Signature Algorithm: + + let private_key_der = ed25519_private_key_pkcs8_der(key_pair)?; + + let key_pair = rcgen::KeyPair::try_from(private_key_der.as_ref()).expect("Invalid pkcs8 der"); + params.key_pair = Some(key_pair); + + Certificate::from_params(params).map_err(|e| WebSocketError::Other(e.into())) +} + +/// Generate the private key in a PKCS#8 format. To be compatible with rcgen lib. +/// PKCS#8 is specified in [RFC 5958]. +/// +/// [RFC 5958]: https://tools.ietf.org/html/rfc5958. +fn ed25519_private_key_pkcs8_der(key_pair: ed25519::Pair) -> WebSocketResult> { + let seed = key_pair.seed(); + let private_key = seed.as_slice(); + let pk = key_pair.public().0; + let public_key = pk.as_slice(); + let key_der = yasna::construct_der(|writer| { + writer.write_sequence(|writer| { + writer.next().write_u8(1); + // write OID + writer.next().write_sequence(|writer| { + writer.next().write_oid(&ObjectIdentifier::from_slice(ED25519)); + }); + let pk = yasna::construct_der(|writer| writer.write_bytes(private_key)); + writer.next().write_bytes(&pk); + writer.next().write_tagged(yasna::Tag::context(1), |writer| { + writer.write_bitvec(&BitVec::from_bytes(public_key)) + }) + }); + }); + Ok(key_der) +} + +#[cfg(test)] +mod tests { + use crate::certificate_generation::ed25519_self_signed_certificate; + use sp_core::{crypto::Pair, ed25519}; + use std::time::SystemTime; + use webpki::TLSServerTrustAnchors; + + type Seed = [u8; 32]; + const TEST_SEED: Seed = *b"12345678901234567890123456789012"; + + #[test] + pub fn test_verify_signature_self_signed_certificate() { + let signing = signer(); + let pk = signing.public().0; + let public_key = pk.as_slice(); + let cert = ed25519_self_signed_certificate(signing, "Test").unwrap(); + let sign_pub_key = cert.get_key_pair().public_key_raw(); + assert_eq!(public_key, sign_pub_key); + } + + #[test] + pub fn test_verify_is_valid_tls_server_certificate() { + let common_name = "Test"; + let signing = signer(); + let cert = ed25519_self_signed_certificate(signing, common_name).unwrap(); + + //write certificate and private key pem file + //let cert_der = cert.serialize_der().unwrap(); + //fs::write("test_cert.der", &cert_der).unwrap(); + + let cert_der = cert.serialize_der().unwrap(); + let end_entity_cert = webpki::EndEntityCert::from(&cert_der).unwrap(); + + let time = webpki::Time::try_from(SystemTime::now()); + + let trust_anchor = webpki::trust_anchor_util::cert_der_as_trust_anchor(&cert_der).unwrap(); + let trust_anchor_list = &[trust_anchor]; + let trust_anchors = TLSServerTrustAnchors(trust_anchor_list); + + assert!(end_entity_cert + .verify_is_valid_tls_server_cert( + &[&webpki::ED25519], + &trust_anchors, + &[], + time.unwrap(), + ) + .is_ok()); + } + + fn signer() -> ed25519::Pair { + ed25519::Pair::from_seed(&TEST_SEED) + } +} diff --git a/bitacross-worker/core/tls-websocket-server/src/config_provider.rs b/bitacross-worker/core/tls-websocket-server/src/config_provider.rs new file mode 100644 index 0000000000..04d561bc20 --- /dev/null +++ b/bitacross-worker/core/tls-websocket-server/src/config_provider.rs @@ -0,0 +1,45 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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(all(not(feature = "std"), feature = "sgx"))] +use crate::sgx_reexport_prelude::*; + +use crate::{error::WebSocketResult, tls_common::make_config}; +use rustls::ServerConfig; +use std::{string::String, sync::Arc}; + +/// Trait to provide a Rustls server config. +pub trait ProvideServerConfig: Send + Sync { + fn get_config(&self) -> WebSocketResult>; +} + +pub struct FromFileConfigProvider { + private_key: String, + certificate: String, +} + +impl FromFileConfigProvider { + pub fn new(private_key: String, certificate: String) -> Self { + Self { private_key, certificate } + } +} + +impl ProvideServerConfig for FromFileConfigProvider { + fn get_config(&self) -> WebSocketResult> { + make_config(&self.certificate, &self.private_key) + } +} diff --git a/bitacross-worker/core/tls-websocket-server/src/connection.rs b/bitacross-worker/core/tls-websocket-server/src/connection.rs new file mode 100644 index 0000000000..ab456236b0 --- /dev/null +++ b/bitacross-worker/core/tls-websocket-server/src/connection.rs @@ -0,0 +1,344 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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(all(not(feature = "std"), feature = "sgx"))] +use crate::sgx_reexport_prelude::*; + +use crate::{ + error::WebSocketError, stream_state::StreamState, WebSocketConnection, WebSocketMessageHandler, + WebSocketResult, +}; +use log::*; +use mio::{event::Event, net::TcpStream, Poll, Ready, Token}; +use rustls::{ServerSession, Session}; +use std::{ + format, + string::{String, ToString}, + sync::Arc, + time::Instant, +}; +use tungstenite::Message; + +/// A web-socket connection object. +pub struct TungsteniteWsConnection { + stream_state: StreamState, + connection_token: Token, + connection_handler: Arc, + is_closed: bool, +} + +impl TungsteniteWsConnection +where + Handler: WebSocketMessageHandler, +{ + pub fn new( + tcp_stream: TcpStream, + server_session: ServerSession, + connection_token: Token, + handler: Arc, + ) -> WebSocketResult { + Ok(TungsteniteWsConnection { + stream_state: StreamState::from_stream(rustls::StreamOwned::new( + server_session, + tcp_stream, + )), + connection_token, + connection_handler: handler, + is_closed: false, + }) + } + + fn do_tls_read(&mut self) -> ConnectionState { + let tls_stream = match self.stream_state.internal_stream_mut() { + None => return ConnectionState::Closing, + Some(s) => s, + }; + + let tls_session = &mut tls_stream.sess; + + match tls_session.read_tls(&mut tls_stream.sock) { + Ok(r) => + if r == 0 { + return ConnectionState::Closing + }, + Err(err) => { + if let std::io::ErrorKind::WouldBlock = err.kind() { + debug!("TLS session is blocked (connection {})", self.connection_token.0); + return ConnectionState::Blocked + } + warn!( + "I/O error after reading TLS data (connection {}): {:?}", + self.connection_token.0, err + ); + return ConnectionState::Closing + }, + } + + match tls_session.process_new_packets() { + Ok(_) => { + if tls_session.is_handshaking() { + return ConnectionState::TlsHandshake + } + ConnectionState::Alive + }, + Err(e) => { + error!("cannot process TLS packet(s), closing connection: {:?}", e); + ConnectionState::Closing + }, + } + } + + fn do_tls_write(&mut self) -> ConnectionState { + let tls_stream = match self.stream_state.internal_stream_mut() { + None => return ConnectionState::Closing, + Some(s) => s, + }; + + match tls_stream.sess.write_tls(&mut tls_stream.sock) { + Ok(_) => { + trace!("TLS write successful, connection {} is alive", self.connection_token.0); + if tls_stream.sess.is_handshaking() { + return ConnectionState::TlsHandshake + } + ConnectionState::Alive + }, + Err(e) => { + error!("TLS write error (connection {}): {:?}", self.connection_token.0, e); + ConnectionState::Closing + }, + } + } + + /// Read from a web-socket, or initiate handshake if websocket is not initialized yet. + /// + /// Returns a boolean 'connection should be closed'. + fn read_or_initialize_websocket(&mut self) -> WebSocketResult { + if let StreamState::EstablishedWebsocket(web_socket) = &mut self.stream_state { + trace!( + "Read is possible for connection {}: {}", + self.connection_token.0, + web_socket.can_read() + ); + match web_socket.read_message() { + Ok(m) => + if let Err(e) = self.handle_message(m) { + error!( + "Failed to handle web-socket message (connection {}): {:?}", + self.connection_token.0, e + ); + }, + Err(e) => match e { + tungstenite::Error::ConnectionClosed => return Ok(true), + tungstenite::Error::AlreadyClosed => return Ok(true), + _ => error!( + "Failed to read message from web-socket (connection {}): {:?}", + self.connection_token.0, e + ), + }, + } + trace!("Read successful for connection {}", self.connection_token.0); + } else { + trace!("Initialize connection {}", self.connection_token.0); + self.stream_state = std::mem::take(&mut self.stream_state).attempt_handshake(); + if self.stream_state.is_invalid() { + warn!("Web-socket connection ({:?}) failed, closing", self.connection_token); + return Ok(true) + } + debug!("Initialized connection {} successfully", self.connection_token.0); + } + + Ok(false) + } + + fn handle_message(&mut self, message: Message) -> WebSocketResult<()> { + match message { + Message::Text(string_message) => { + trace!( + "Got Message::Text on web-socket (connection {}), calling handler..", + self.connection_token.0 + ); + let message_handled_timer = Instant::now(); + if let Some(reply) = self + .connection_handler + .handle_message(self.connection_token.into(), string_message)? + { + trace!( + "Handling message yielded a reply, sending it now to connection {}..", + self.connection_token.0 + ); + self.write_message(reply)?; + trace!("Reply sent successfully to connection {}", self.connection_token.0); + } + debug!( + "Handled web-socket message in {} ms", + message_handled_timer.elapsed().as_millis() + ); + }, + Message::Binary(_) => { + warn!("received binary message, don't have a handler for this format"); + }, + Message::Close(_) => { + debug!( + "Received close frame, driving web-socket connection {} to close", + self.connection_token.0 + ); + if let StreamState::EstablishedWebsocket(web_socket) = &mut self.stream_state { + // Send a close frame back and then flush the send queue. + if let Err(e) = web_socket.close(None) { + match e { + tungstenite::Error::ConnectionClosed + | tungstenite::Error::AlreadyClosed => {}, + _ => warn!( + "Failed to send close frame (connection {}): {:?}", + self.connection_token.0, e + ), + } + } + match web_socket.write_pending() { + Ok(_) => {}, + Err(e) => match e { + tungstenite::Error::ConnectionClosed + | tungstenite::Error::AlreadyClosed => {}, + _ => warn!("Failed to write pending frames after closing (connection {}): {:?}", self.connection_token.0, e), + }, + } + } + debug!("Successfully closed connection {}", self.connection_token.0); + }, + _ => {}, + } + Ok(()) + } + + pub(crate) fn write_message(&mut self, message: String) -> WebSocketResult<()> { + match &mut self.stream_state { + StreamState::EstablishedWebsocket(web_socket) => { + if !web_socket.can_write() { + return Err(WebSocketError::ConnectionClosed) + } + debug!("Write message to connection {}: {}", self.connection_token.0, message); + web_socket + .write_message(Message::Text(message)) + .map_err(|e| WebSocketError::SocketWriteError(format!("{:?}", e))) + }, + _ => + Err(WebSocketError::SocketWriteError("No active web-socket available".to_string())), + } + } +} + +impl WebSocketConnection for TungsteniteWsConnection +where + Handler: WebSocketMessageHandler, +{ + type Socket = TcpStream; + + fn socket(&self) -> Option<&Self::Socket> { + self.stream_state.internal_stream().map(|s| &s.sock) + } + + fn get_session_readiness(&self) -> Ready { + match self.stream_state.internal_stream() { + None => mio::Ready::empty(), + Some(s) => { + let wants_read = s.sess.wants_read(); + let wants_write = s.sess.wants_write(); + + if wants_read && wants_write { + mio::Ready::readable() | mio::Ready::writable() + } else if wants_write { + mio::Ready::writable() + } else { + mio::Ready::readable() + } + }, + } + } + + fn on_ready(&mut self, poll: &mut Poll, event: &Event) -> WebSocketResult<()> { + let mut is_closing = false; + + if event.readiness().is_readable() { + trace!("Connection ({:?}) is readable", self.token()); + + let connection_state = self.do_tls_read(); + + if connection_state.is_alive() { + is_closing = self.read_or_initialize_websocket()?; + } else { + is_closing = connection_state.is_closing(); + } + } + + if event.readiness().is_writable() { + trace!("Connection ({:?}) is writable", self.token()); + + let connection_state = self.do_tls_write(); + + if connection_state.is_alive() { + if let StreamState::EstablishedWebsocket(web_socket) = &mut self.stream_state { + trace!("Web-socket, write pending messages"); + if let Err(e) = web_socket.write_pending() { + match e { + tungstenite::Error::ConnectionClosed + | tungstenite::Error::AlreadyClosed => is_closing = true, + _ => error!("Failed to write pending web-socket messages: {:?}", e), + } + } + } + } else { + is_closing = connection_state.is_closing(); + } + } + + if is_closing { + debug!("Connection ({:?}) is closed", self.token()); + self.is_closed = true; + } else { + // Re-register with the poll. + self.reregister(poll)?; + } + Ok(()) + } + + fn is_closed(&self) -> bool { + self.is_closed + } + + fn token(&self) -> Token { + self.connection_token + } +} + +/// Internal connection state. +#[derive(Debug, Clone)] +enum ConnectionState { + Closing, + Blocked, + Alive, + TlsHandshake, +} + +impl ConnectionState { + pub(crate) fn is_alive(&self) -> bool { + matches!(self, ConnectionState::Alive) + } + + pub(crate) fn is_closing(&self) -> bool { + matches!(self, ConnectionState::Closing) + } +} diff --git a/bitacross-worker/core/tls-websocket-server/src/connection_id_generator.rs b/bitacross-worker/core/tls-websocket-server/src/connection_id_generator.rs new file mode 100644 index 0000000000..dac5431cb6 --- /dev/null +++ b/bitacross-worker/core/tls-websocket-server/src/connection_id_generator.rs @@ -0,0 +1,76 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 = "sgx")] +use std::sync::SgxRwLock as RwLock; + +#[cfg(feature = "std")] +use std::sync::RwLock; + +use crate::{error::WebSocketError, WebSocketResult}; + +pub type ConnectionId = usize; + +/// Trait to generate IDs (nonce) for websocket connections. +pub trait GenerateConnectionId { + fn next_id(&self) -> WebSocketResult; +} + +pub struct ConnectionIdGenerator { + current_id: RwLock, +} + +const MIN_ID: usize = 10; + +impl Default for ConnectionIdGenerator { + fn default() -> Self { + Self { current_id: RwLock::new(MIN_ID) } + } +} + +impl GenerateConnectionId for ConnectionIdGenerator { + fn next_id(&self) -> WebSocketResult { + let mut id_lock = self.current_id.write().map_err(|_| WebSocketError::LockPoisoning)?; + *id_lock = id_lock.checked_add(1).unwrap_or(MIN_ID); + Ok(*id_lock) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::ws_server::{NEW_CONNECTIONS_LISTENER, SERVER_SIGNAL_TOKEN}; + + #[test] + fn next_id_works() { + let id_generator = ConnectionIdGenerator::default(); + + assert_eq!(11, id_generator.next_id().unwrap()); + assert_eq!(12, id_generator.next_id().unwrap()); + assert_eq!(13, id_generator.next_id().unwrap()); + } + + #[test] + fn next_id_is_greater_than_default_tokens() { + let id_generator = ConnectionIdGenerator::default(); + + let first_id = id_generator.next_id().unwrap(); + + assert!(NEW_CONNECTIONS_LISTENER < mio::Token(first_id)); + assert!(SERVER_SIGNAL_TOKEN < mio::Token(first_id)); + } +} diff --git a/bitacross-worker/core/tls-websocket-server/src/error.rs b/bitacross-worker/core/tls-websocket-server/src/error.rs new file mode 100644 index 0000000000..3d86b509dc --- /dev/null +++ b/bitacross-worker/core/tls-websocket-server/src/error.rs @@ -0,0 +1,55 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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(all(not(feature = "std"), feature = "sgx"))] +use crate::sgx_reexport_prelude::*; + +use crate::ConnectionId; +use std::{boxed::Box, io::Error as IoError, net::AddrParseError, string::String}; + +pub type WebSocketResult = Result; + +/// General web-socket error type +#[derive(Debug, thiserror::Error)] +pub enum WebSocketError { + #[error("Invalid certificate: {0}")] + InvalidCertificate(String), + #[error("Invalid private key: {0}")] + InvalidPrivateKey(String), + #[error("Invalid web-socket address: {0}")] + InvalidWsAddress(AddrParseError), + #[error("TCP bind: {0}")] + TcpBindError(IoError), + #[error("Web-socket hand shake: {0}")] + HandShakeError(String), + #[error("{0} is not a valid and active web-socket connection id")] + InvalidConnection(ConnectionId), + #[error("Web-socket connection already closed error")] + ConnectionClosed, + #[error("Web-socket connection has not yet been established")] + ConnectionNotYetEstablished, + #[error("Web-socket write: {0}")] + SocketWriteError(String), + #[error("Lock poisoning")] + LockPoisoning, + #[error("Failed to receive server signal message: {0}")] + MioReceiveError(#[from] std::sync::mpsc::TryRecvError), + #[error("{0}")] + IoError(#[from] std::io::Error), + #[error("{0}")] + Other(Box), +} diff --git a/bitacross-worker/core/tls-websocket-server/src/lib.rs b/bitacross-worker/core/tls-websocket-server/src/lib.rs new file mode 100644 index 0000000000..919e0526dc --- /dev/null +++ b/bitacross-worker/core/tls-websocket-server/src/lib.rs @@ -0,0 +1,177 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg(all(feature = "std", feature = "sgx"))] +compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the same time"); + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +extern crate sgx_tstd as std; + +// re-export module to properly feature gate sgx and regular std environment +#[cfg(all(not(feature = "std"), feature = "sgx"))] +pub mod sgx_reexport_prelude { + pub use mio_sgx as mio; + pub use rustls_sgx as rustls; + pub use thiserror_sgx as thiserror; + pub use tungstenite_sgx as tungstenite; + pub use webpki_sgx as webpki; + pub use yasna_sgx as yasna; +} + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +use crate::sgx_reexport_prelude::*; + +use crate::{ + config_provider::FromFileConfigProvider, + connection_id_generator::{ConnectionId, ConnectionIdGenerator}, + error::{WebSocketError, WebSocketResult}, + ws_server::TungsteniteWsServer, +}; +use mio::{event::Evented, Token}; +use std::{ + fmt::Debug, + string::{String, ToString}, + sync::Arc, +}; + +pub mod certificate_generation; +pub mod config_provider; +mod connection; +pub mod connection_id_generator; +pub mod error; +mod stream_state; +mod tls_common; +pub mod ws_server; + +#[cfg(any(test, feature = "mocks"))] +pub mod test; + +/// Connection token alias. +#[derive(Eq, PartialEq, Clone, Copy, Debug, Hash)] +pub struct ConnectionToken(pub usize); + +impl From for Token { + fn from(c: ConnectionToken) -> Self { + Token(c.0) + } +} + +impl From for ConnectionToken { + fn from(t: Token) -> Self { + ConnectionToken(t.0) + } +} + +/// Handles a web-socket connection message. +pub trait WebSocketMessageHandler: Send + Sync { + fn handle_message( + &self, + connection_token: ConnectionToken, + message: String, + ) -> WebSocketResult>; +} + +/// Allows to send response messages to a specific connection. +pub trait WebSocketResponder: Send + Sync { + fn send_message( + &self, + connection_token: ConnectionToken, + message: String, + ) -> WebSocketResult<()>; +} + +/// Run a web-socket server with a given handler. +pub trait WebSocketServer { + type Connection; + + fn run(&self) -> WebSocketResult<()>; + + fn is_running(&self) -> WebSocketResult; + + fn shut_down(&self) -> WebSocketResult<()>; +} + +/// Abstraction of a web socket connection using mio. +pub(crate) trait WebSocketConnection: Send + Sync { + /// Socket type, typically a TCP stream. + type Socket: Evented; + + /// Get the underlying socket (TCP stream) + fn socket(&self) -> Option<&Self::Socket>; + + /// Query the underlying session for readiness (read/write). + fn get_session_readiness(&self) -> mio::Ready; + + /// Handles the ready event, the connection has work to do. + fn on_ready(&mut self, poll: &mut mio::Poll, ev: &mio::event::Event) -> WebSocketResult<()>; + + /// True if connection was closed. + fn is_closed(&self) -> bool; + + /// Return the connection token (= ID) + fn token(&self) -> mio::Token; + + /// Register the connection with the mio poll. + fn register(&mut self, poll: &mio::Poll) -> WebSocketResult<()> { + match self.socket() { + Some(s) => { + poll.register( + s, + self.token(), + self.get_session_readiness(), + mio::PollOpt::level() | mio::PollOpt::oneshot(), + )?; + Ok(()) + }, + None => Err(WebSocketError::ConnectionClosed), + } + } + + /// Re-register the connection with the mio poll, after handling an event. + fn reregister(&mut self, poll: &mio::Poll) -> WebSocketResult<()> { + match self.socket() { + Some(s) => { + poll.reregister( + s, + self.token(), + self.get_session_readiness(), + mio::PollOpt::level() | mio::PollOpt::oneshot(), + )?; + + Ok(()) + }, + None => Err(WebSocketError::ConnectionClosed), + } + } +} + +pub fn create_ws_server( + addr_plain: &str, + private_key: &str, + certificate: &str, + handler: Arc, +) -> Arc> +where + Handler: WebSocketMessageHandler, +{ + let config_provider = + Arc::new(FromFileConfigProvider::new(private_key.to_string(), certificate.to_string())); + + Arc::new(TungsteniteWsServer::new(addr_plain.to_string(), config_provider, handler)) +} diff --git a/bitacross-worker/core/tls-websocket-server/src/stream_state.rs b/bitacross-worker/core/tls-websocket-server/src/stream_state.rs new file mode 100644 index 0000000000..ef53a14b61 --- /dev/null +++ b/bitacross-worker/core/tls-websocket-server/src/stream_state.rs @@ -0,0 +1,105 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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(all(not(feature = "std"), feature = "sgx"))] +use crate::sgx_reexport_prelude::*; + +use log::*; +use mio::net::TcpStream; +use rustls::ServerSession; +use std::boxed::Box; +use tungstenite::{ + accept, + handshake::{server::NoCallback, MidHandshake}, + HandshakeError, ServerHandshake, WebSocket, +}; + +pub(crate) type RustlsStream = rustls::StreamOwned; +pub(crate) type RustlsServerHandshake = ServerHandshake; +pub(crate) type RustlsMidHandshake = MidHandshake; +pub(crate) type RustlsWebSocket = WebSocket; + +/// Internal TLS stream state. From pure TLS stream, to web-socket handshake and established WS. +pub(crate) enum StreamState { + Invalid, + TlsStream(Box), + WebSocketHandshake(RustlsMidHandshake), + EstablishedWebsocket(Box), +} + +impl Default for StreamState { + fn default() -> Self { + Self::Invalid + } +} + +impl StreamState { + pub(crate) fn from_stream(stream: RustlsStream) -> Self { + StreamState::TlsStream(Box::new(stream)) + } + + pub(crate) fn is_invalid(&self) -> bool { + matches!(self, StreamState::Invalid) + } + + pub(crate) fn internal_stream(&self) -> Option<&RustlsStream> { + match self { + StreamState::TlsStream(s) => Some(s), + StreamState::WebSocketHandshake(h) => Some(h.get_ref().get_ref()), + StreamState::EstablishedWebsocket(ws) => Some(ws.get_ref()), + StreamState::Invalid => None, + } + } + + pub(crate) fn internal_stream_mut(&mut self) -> Option<&mut RustlsStream> { + match self { + StreamState::TlsStream(s) => Some(s), + StreamState::WebSocketHandshake(h) => Some(h.get_mut().get_mut()), + StreamState::EstablishedWebsocket(ws) => Some(ws.get_mut()), + StreamState::Invalid => None, + } + } + + pub(crate) fn attempt_handshake(self) -> Self { + match self { + // We have the bare TLS stream only, attempt to do a web-socket handshake. + StreamState::TlsStream(tls_stream) => Self::from_handshake_result(accept(*tls_stream)), + // We already have an on-going handshake, attempt another try. + StreamState::WebSocketHandshake(hs) => Self::from_handshake_result(hs.handshake()), + _ => self, + } + } + + fn from_handshake_result( + handshake_result: Result>, + ) -> Self { + match handshake_result { + Ok(ws) => Self::EstablishedWebsocket(Box::new(ws)), + Err(e) => match e { + // I/O would block our handshake attempt. Need to re-try. + HandshakeError::Interrupted(mhs) => { + info!("Web-socket handshake interrupted"); + Self::WebSocketHandshake(mhs) + }, + HandshakeError::Failure(e) => { + error!("Web-socket handshake failed: {:?}", e); + Self::Invalid + }, + }, + } + } +} diff --git a/bitacross-worker/core/tls-websocket-server/src/test/fixtures/mod.rs b/bitacross-worker/core/tls-websocket-server/src/test/fixtures/mod.rs new file mode 100644 index 0000000000..6790e464c8 --- /dev/null +++ b/bitacross-worker/core/tls-websocket-server/src/test/fixtures/mod.rs @@ -0,0 +1,22 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 no_cert_verifier; +pub mod test_cert; +pub mod test_private_key; +pub mod test_server; +pub mod test_server_config_provider; diff --git a/bitacross-worker/core/tls-websocket-server/src/test/fixtures/no_cert_verifier.rs b/bitacross-worker/core/tls-websocket-server/src/test/fixtures/no_cert_verifier.rs new file mode 100644 index 0000000000..50e05527ab --- /dev/null +++ b/bitacross-worker/core/tls-websocket-server/src/test/fixtures/no_cert_verifier.rs @@ -0,0 +1,51 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 log::debug; +use rustls::{Certificate, ClientCertVerified, DistinguishedNames, TLSError}; +use webpki::DNSName; + +/// Test Rustls verifier, disables ALL verification (do NOT use in production!) +pub struct NoCertVerifier {} + +impl rustls::ServerCertVerifier for NoCertVerifier { + fn verify_server_cert( + &self, + _: &rustls::RootCertStore, + _: &[rustls::Certificate], + _: webpki::DNSNameRef<'_>, + _: &[u8], + ) -> Result { + debug!("Certificate verification bypassed"); + Ok(rustls::ServerCertVerified::assertion()) + } +} + +impl rustls::ClientCertVerifier for NoCertVerifier { + fn client_auth_root_subjects(&self, _sni: Option<&DNSName>) -> Option { + None + } + + fn verify_client_cert( + &self, + _presented_certs: &[Certificate], + _sni: Option<&DNSName>, + ) -> Result { + debug!("Certificate verification bypassed"); + Ok(rustls::ClientCertVerified::assertion()) + } +} diff --git a/bitacross-worker/core/tls-websocket-server/src/test/fixtures/test_cert.rs b/bitacross-worker/core/tls-websocket-server/src/test/fixtures/test_cert.rs new file mode 100644 index 0000000000..1b94e7a24a --- /dev/null +++ b/bitacross-worker/core/tls-websocket-server/src/test/fixtures/test_cert.rs @@ -0,0 +1,139 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 rustls::{internal::pemfile::certs, Certificate}; +use std::{io::BufReader, vec::Vec}; + +pub fn get_test_certificate_chain() -> Vec { + let mut buf_reader = BufReader::new(CERT_STR.as_bytes()); + certs(&mut buf_reader).unwrap() +} + +const CERT_STR: &str = "\ +-----BEGIN CERTIFICATE----- +MIIEADCCAmigAwIBAgICAcgwDQYJKoZIhvcNAQELBQAwLDEqMCgGA1UEAwwhcG9u +eXRvd24gUlNBIGxldmVsIDIgaW50ZXJtZWRpYXRlMB4XDTE3MDQxMDIwNTYyN1oX +DTIyMTAwMTIwNTYyN1owGTEXMBUGA1UEAwwOdGVzdHNlcnZlci5jb20wggEiMA0G +CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCa4nonCxArES+kBBf9mZoaQ2GBMg74 +Pj2ve4RKJSIBt9A7EgJ4hFznFQ11O11Xvb3dVQGOK+pFRxh2xg0DJvV3lJytpvKe +mviyT5KSGvp6Hybqmx66B2V3iDfrXhhySqG5tKEeczFBIq+62dAp0+r0oSdpZKGT +1YDtXonjcbnDb93K7g8arEadFKYN3MAjBGQ3m5fsWJJuq4hLU1+dpmAfxmYH1dlc +n89LyPhYh0I7R5v17VrGlNCWIWD1emLtM8vTS94eMtp8R6MuMIZTOKgBTrIpU4G5 +GPcR3flDzzLsCxEttjjMa41zStKXzieUIwirRAzPv48V4JlkCCUPv97pAgMBAAGj +gb4wgbswDAYDVR0TAQH/BAIwADALBgNVHQ8EBAMCBsAwHQYDVR0OBBYEFNn77YZg +4AGguHBKVggK00dtRvhCMEIGA1UdIwQ7MDmAFGuwcG2Zfyr92yAiXU9HP9rBYC6/ +oR6kHDAaMRgwFgYDVQQDDA9wb255dG93biBSU0EgQ0GCAXswOwYDVR0RBDQwMoIO +dGVzdHNlcnZlci5jb22CFXNlY29uZC50ZXN0c2VydmVyLmNvbYIJbG9jYWxob3N0 +MA0GCSqGSIb3DQEBCwUAA4IBgQB4xB9IPNxkJIA8QtngQZCCSPH5SjfAibcLfwi2 +NLHe4hO4HvoIVv0ru7CODfq45qNfH7sUj8a/JBU8BwcJ3xPewWFdavtCP8+dapmd +pr831+Xx6p9tNIdW16WrCXEV8i9bHy43Y4pWbNdXQy5meI0qvSM/ExedZqqVeJJT +oXL/aCtMsBixlwlKvrsG9ZvIAl1ics0wA5kqQWVufe95loI+HUcPc9s9689H+/ON +lH8rTLPwyufk9h2dTb9Wzw3qewlDIqgoyX7k9cOwrJqA4D6typCvb5dWfQlK9c72 +4rGbqHSx7mrlaZ4typfAMdEbynRlDSgIIZGXb7RaoV3NT2XuVFd8+lcXgBiJMvPk +STejz77EPR2+uKvQ1gMJXpEHCBUvMMyDqhpcNzb0DaXgf4eYI9RqfxU1pkgYnfxe +DGDGI2SdmO43NwSDyEQVSlRpCIBj4ZDay3IP7mbdi8MLxR9H1BCHnN7D04UrTnuA +c/cl0RMWL+iHtKU2cCxltEQQ9qQ= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIGnzCCAoegAwIBAgIBezANBgkqhkiG9w0BAQsFADAaMRgwFgYDVQQDDA9wb255 +dG93biBSU0EgQ0EwHhcNMTcwNDEwMjA1NjI3WhcNMjcwNDA4MjA1NjI3WjAsMSow +KAYDVQQDDCFwb255dG93biBSU0EgbGV2ZWwgMiBpbnRlcm1lZGlhdGUwggGiMA0G +CSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQDCX7V0gKGQBS64QKntjDlBslbQJaxq +EL8Yyq+qjF6nkOoqENKWSzeNyQ76kPVlzeV03UCaIgTF4+FeQrUr7wauEz0FGmDh +yx/B4xy9ZXdBIftPB8iz8Q/KrKO6YM6tkj7ijvL8hP3MfssBkA+VoAxamPSIikfM +9kyttemjYizgM0ywebzKmQGJbEINZ80Kp63ayR/Uo/cORjlH3xbmtTsL3pd+k6Ro +xOMZKm1RIwOwGgxDW4ea294A4lXHwfwHGMsP0/xmqTZ0R/EpxLKeqJAQffTiVsBK +YEFzANn3nol1IYrdcZcgcs16KTnc5+XyL87KSdIgDgG3wmQvRCdLX5G6GChyP03Z +qQSYMkwGSNgCD1v4m14Z5XT2su7iilHfjsucvT4OukCe63nqeXIZ+w63YqbjTp/a +HMgrXVg1wMlSncl0OIKcjLOgJ5vbPOGk9DvF93JbRFp/9sAZmK89Ur4gBmgpq2Zn +bknK0LVt+aerP7rf8CPYE89olPVUW0owwrkCAwEAAaNeMFwwHQYDVR0OBBYEFGuw +cG2Zfyr92yAiXU9HP9rBYC6/MCAGA1UdJQEB/wQWMBQGCCsGAQUFBwMBBggrBgEF +BQcDAjAMBgNVHRMEBTADAQH/MAsGA1UdDwQEAwIB/jANBgkqhkiG9w0BAQsFAAOC +BAEARD9wwIHsAFWlzrRLw3JcAUDB906Ks7KZzdqe3n6FkbyHHP1N5JG25wXwgADS +qux6sZU7h6+q209IEqXWbw+nbxJs/3D1hLN6X2tVgsfkSflGsd3DfNPZI8qKUyOD +VYlql/EPEMBixXOeVpwxXc48rX/yVjxqCvhY/A7eIiAc+bzQtwozLppChyVitQGI +MViXRdGdFiybwTKoJMYXl6ztamk9TWhdvJ9znirol12b06Z3J0Kz0c/kqY7VVZqL +ba76+IAJjvWQE7PYEOqpFHOLpilv9j5d/0kBR4AgJaooFwcYnr6aJKfNUgGWEmdn +ELYmfa0qORllAM/yGoewRfWGLZBNgT0QFYg2IFjnp0W0wIXFRd7xVqldN+cTmMqk +szpVV7bqGvuk6SQNFjIZ8VIVc/mXua4WlwBODDRzKqU3bIgBTODgVq1edwqp6UjN +ECLAOe1p03GGMr4WSPDoFjlQlHy+NLUwZg3RI+HsAkow9WfP7KqGN4vFDC4ru9Pg +2uD28oTrOgYQpzKjQJSH3kC5feOUdrsET7zic75XO1J33CAlgbIZ2TSQDqnH2cY5 +bQsWSNA2Lle3wBbeHlCy7ACiaoeJS23TJV9n8PcsRwSmHA9NgT4WSavXwtZ0lBhI +60GY80VXo9ziQjvVTMZNymZ4FEqCvULHGhFI08Jqd1jOXjnPLY4WEARqkicBJvI1 +3t4sBLDU+PEqH7m8k3lCZd6D7XVDcc8bJock+DjXZIMbZY79UMuzyHocXNJpRfRT +cqS0qneltFe6Pea7y0PN2IDttGBLb1CVQpXhRkpFU8jtyXh3ulSZSJEeqLVRFgdv +PVwHWAhLPewVGDkgTrlWVNfiXxp1LWVTFzQFas9xWiY4byQk/DNQaaFwHpGoZgVc +qAzUVk20Msm2u9xvSbPcBGk0dL4fdlnOkyeq/k/fnNrGdRHJWuJe7QR73/N0u6fy +7H76xUXvcwwrxL8ma8nV9K+A7oM7YUiR1wagD9cnoDDBgQmH9Izvfw0PxJgqnLOe +lQGPVGRhmXNtLLG57dqgjrvERGy9u5NMxBlkH0giZTFyQXPQ+N75ouM4S3RL75PM +UaTOBtnyCj++5ysnDFlGqEXgy08rrtkCbbNfd9dnO568juXS6ExC6TEL/pUMhy+Z +ooIJ69Tt7R5dOLaKRrkX/nKHfCfLfXXnjyDmdRHRYrXvTWusF038OsqY89tb0F0u +S4Szv4/Bl1bhzx/XYMZv/y7XL0va8FQLiRTuvqJ9hTsE/Xkd4ZFrP1LaP6HzVR1g +tsFs2Gc8j7H299U3WLjNon0TL2uPXa77Vu+9h7QCi1W9Uzsv0xMvZ/KMEnXyaEBd +W1lqo85ih1nnfxcW+lmAz8QNGQ== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIJCjCCBPKgAwIBAgIJAI+QZnVEkxq/MA0GCSqGSIb3DQEBCwUAMBoxGDAWBgNV +BAMMD3Bvbnl0b3duIFJTQSBDQTAeFw0xNzA0MTAyMDU2MjdaFw0yNzA0MDgyMDU2 +MjdaMBoxGDAWBgNVBAMMD3Bvbnl0b3duIFJTQSBDQTCCBCIwDQYJKoZIhvcNAQEB +BQADggQPADCCBAoCggQBAMD0iyFqRCNhvD5T9WXO8caNGb5ecrlnqSUvfcc+6Xh9 +sShtK6DX2DZ+6YT2WWOZTk0I9T+XG2kujjyfdCbEDMWcT9so7/gPeIG/qFlhONCu +HC+zntuZrGgMEYpF3Xc41CyF3saredTJEo1J64TPEke8mohezIGZYM1vTtRnqW+1 +RstSNTu8a/B0VaG0iA5P5RuSGVmxczi4EWJtuXFhcbgqICaUt0vJdrU0Fmrmq0Iq +ZEIpgZKYirx5QW8b6Q5tv0YsnXNasXvHZQve4GgF449ewk9wWfYevD8UttHUEe2a +QeEKb2l7NxqyY6trGyVtTRlm4SnoOH/9VodTKUEmS6pds6XFtjRflxgom0TL7CXb +uJ9b6fkXQlnf01FqAbv5HC1sjgGlSZc7Yk8k09nWOR8mZMoHC+U4KEq+oM+m87q4 +U/GsEk8UsPslGIIHHK6W/sdU6zA9bR3QYmkD40Z7FbVfKVvDmKPlwI7NONqysD8V +UTPoB8aE7FeulZhlTxdK2EcW14AsjbFiPQ4zAVxj4bRj39RLgJYL+BvAF6PfRHb1 +Xb7ykbuTvT7VhNYXLlQagR9EyixT3Wu9WCWUc0xJKSATn1s2YBLNM7LO4MkYO9WG +YrejhNHG+54a7rtnnlG04Gs7OhM32baMH/DxT+EEAX4j0Dfww4RaCZcfq1gDPsVe ++RzqsjjqF8+IzE25SK38xgwT/o3n9r5Ele3/zadwy695KCfbkhVFSDAPvhiv8um5 +6NNP+dDymFRXGzV85xSK75ue3Dpj+MoSScmIdGLEcU5EqYcBFLCXGLYPDIW8Lb89 +mG1z7TkZOLIs+6v7kp4rrvyijsyLFZ+EKUmabAK42qdzASZ1o6ETDDfFBETMxjWA +oMmGmRkhsyfBTuCr1ESlTBQHj4vvxBrgXgHtHwUinBw/sofLbkFRZ4wz/cBOtwqW +HIu88/o33l6ywMowcjaoToIbK2a4rD/KFJiwLliGKZG2veiESRhnNUQyjxT/PIef +0gqx3i1eBGWvfQs/wUC8qI5UadTRhjMFCwMCDVycevZE8lcQ+7zi9tVu6mXife5J +yP/jxRNDLzpdM6C6puqk0XieZey782XZ7sPpDpS2tphwakINF/5X3t1qZsssZPqq +F1S2VIsL8qm6Z7HDHXex3o2tDUhc226YSp/T7D+IWP3UCs0NjJrldakhnAd7ykxT +b2cDh09GDYSbji4Y6WmgIbSAurqk6kt4MWrfx4yfEAlp8ujH6788lRDAiXN1RgzC +k8r21IOJONDG7Qk1rS0YUV4XyGz4SEpBdPTI7RM1fl5bDn4e+OslBcfWh5XplZrz +4D4Z9YWVZ8X6d7CiPYZIg35oo/45KGel3Z8algziVkMCAwEAAaNTMFEwHQYDVR0O +BBYEFOWXlO0crUtBejJo87v9lwg8PlE6MB8GA1UdIwQYMBaAFOWXlO0crUtBejJo +87v9lwg8PlE6MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggQBADUQ +YqVmS9o3/5Qp7Tr+JL5ZNRP1fRmV5kAqaKDC5I9ONKRYahHvoI0ojE/j+pmwI4gf +mp5mW8EgsNfooovrzVSHxJgBO9r1ogMlL9AvwlvVxLbexvLXpM/1QjD/7FID/TaK +1q5mhSBKaEYXqQ+8DN25aVsI/bwHx4eP11Ft6YjhPqaX/WutE/IIAMbgASRFtBlO +foTm++fpdn8rCg5LiLLpWrRLC3zUSUtFd7if3wQ4vcDdck09v9PjD5Lk34aYkowJ +oARbVmBMpAxwkMXaThP1fT7xlYPDhAA26UXksT5xUNzFPbmOVReuFT0drhJlF6e6 +SLTjy2BcrYuz5ieBmmY6QboBYH3SzUFKuamvnHLSic3i3u9Ly68XUjOtDKgYB7Y5 +oZtfZT+YFmz/R6eLUcGRRfcmLJ+i/OXjgyKVkYBMDafW3RI9fRp46Yr/lvOv5gFW +Vrn3Tfc9cSbYQgE4vuKXcs4aVVeX8uAyjcucMV3eLdxaBLUAezTpJseRfqtH2kCk +3JIV6m2y6Tm5EhhaSiHKbe6FtPFKhpu7m9AlquUzhBU9Aq59mbKp6jtV0mWhYwKB +K6REmWQqqAOtHIs7UIXDeN1ZByJ7q+et57RvMgMHc5My0d6a+gQAUssH4i73sVTz +Uej57DW9L7hK0GQpzGzGIO/9lYTzWMVa8EZG1Fa5nUgMh3N3Oy6qUQIqr8E8xT2O +IbKKV6Acx6lBiwii4JkruEMgVVEdsDWDVdP8Ov5lJvvIPLWLqnXsZ2sKCyZrVkgc +PTXVtYBLmn7Tuwody2MSaBONSqleJ1oPQJ9lsAKyqX4xpX05ZJu2kNhST2oq2127 +378GS85DqKDM3P187mjU2G8moqWaGKr6byiIr7ea5TkqIzpC3tKW5QRHvX9aanz0 +akQx6F+l3l4L8J0cXaKasUJTaCk3cWPbbVzo8tQwwdxd0/MdJWrmitK85o+4gLqG +Cvn9VA4mnhjRR0XccxEtzmhSxBRWXoCF1+FnfDmXhPji+AmAhVqRwPkqX9T9H+54 +YG2ZA9Trxssme+QFSFCPZrHuw66ZI6GmKo6h+Hr2qew7LytASN+x2QyvRf7tSNmf +oUgmiD+CFpaH6exjrCC0/hcJ53Kv3E5GBvQskvOqgsUkW+nmsrm95YOosn+9MoQc +PIM6zQCmZ0N/6jHrEHnOnSnz03tGHsvPs6tMB6DKhQz9FNqlrLG7UHhlqhFWj9nv +H+Zh0oOwbcgcoxkk+W6LHLDpA3UpC1tlOzTlD2ektACvQQr/2A/fecpJN/7iWlX9 +BimWwRTS24bO5dX92Kb8V1TNO6ARd9TqOkPXRatysyh7it/MXpc5I2+t49hqlXoV +9Xpi4ds6s2cT8zZGDKI= +-----END CERTIFICATE-----"; diff --git a/bitacross-worker/core/tls-websocket-server/src/test/fixtures/test_private_key.rs b/bitacross-worker/core/tls-websocket-server/src/test/fixtures/test_private_key.rs new file mode 100644 index 0000000000..0e3ad60d01 --- /dev/null +++ b/bitacross-worker/core/tls-websocket-server/src/test/fixtures/test_private_key.rs @@ -0,0 +1,53 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 rustls::{internal::pemfile::rsa_private_keys, PrivateKey}; +use std::io::BufReader; + +pub fn get_test_private_key() -> PrivateKey { + let mut buf_reader = BufReader::new(PRIVATE_KEY_STR.as_bytes()); + rsa_private_keys(&mut buf_reader).unwrap().first().unwrap().clone() +} + +const PRIVATE_KEY_STR: &str = "\ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEAmuJ6JwsQKxEvpAQX/ZmaGkNhgTIO+D49r3uESiUiAbfQOxIC +eIRc5xUNdTtdV7293VUBjivqRUcYdsYNAyb1d5Scrabynpr4sk+Skhr6eh8m6pse +ugdld4g3614YckqhubShHnMxQSKvutnQKdPq9KEnaWShk9WA7V6J43G5w2/dyu4P +GqxGnRSmDdzAIwRkN5uX7FiSbquIS1NfnaZgH8ZmB9XZXJ/PS8j4WIdCO0eb9e1a +xpTQliFg9Xpi7TPL00veHjLafEejLjCGUzioAU6yKVOBuRj3Ed35Q88y7AsRLbY4 +zGuNc0rSl84nlCMIq0QMz7+PFeCZZAglD7/e6QIDAQABAoIBAQCEe5i08Nehnw+7 +Ie1LdSnFsUEj+6emW8bz5ZlguqZ+BbbN8DfA0qeM2gsq7d6IALr5KY8tBw9atteM +MRhMS/THloz2VMlPNYvpKftbkkwSTbdCEfGUemMmfZQnddM/X+s6J/FxVGMbLgpW +r51JSgW9vmMx2WwEQioH4EfeDxcwvZi3LF7SAo89eMSiSDqHZaIfMRmS0cSpoXav +u7gKDt7H+zSeYdLC4FhD4f8zRUpZEa4x5GIIm2JHsvIWuy9XKyepakaObJkWWqR1 +ATO94LtM2+RRVUev+yOVDDOfJtDzEqZrbokCHaVBYXgliAV/XkvFox1ZINyeGFq4 +kAvqfiQJAoGBAMhO/tAz2TpWeETMcujBekx1JmtDEUITJroDT0DvFDV5QRKVopxY +ZY5pPbwtk60KknBbsXrswR3Vh1q3xfKLT3Ln4x121ufltIwN7eopY9dXVqh830CU +QymtUz5VcvG3foWCeABcyklpZIdhHyDDDDP46URfFr3NnQiRnx7qb6yPAoGBAMXy +bSGgnBPUOWHtNW4hI5vxiOiCGWvCq7jERixybGMU8+kP6eRWUEAnOdCibq84A6gv +GLO5EW+bmL8l7L797w6ZN9DhbuR7W7hQVwdkyQS8PUgmTfsaba7+9hTC0chl+L38 +A7NlYRju+JS99SqarGA6WMvo30ykiMGwxw8tHOkHAoGAPT6Z/oK72nBx2WdBgxUV +FaeEFaut7Sv53UoBw3LWFPt7//isfW0xr/dRnuW4j2H6IEyI2XLmIP8WoZAq/9vE +cPeho3KghsrfByuDIOOC2Wak4mM7x30NhAKwvxBVUr6t+phHpKS6XPPSfuodIGFC +q+lhOTxxsZradrI/mq5HctUCgYEAqo4bYeIVGTC+0JWmd+Gt4OvYXx3Z8XOmqmjT +XfCpWyXuk13W1ZtZQi2KLy4F2IuW+w65ZgGL+HJExk5TEq2RkS6LXTsgZVW0zbbL +hd9dJOtckhIPFtDKuQGN3o2OW/EgxfGi7qvnYahmHyMdXzwuUitz3x4jaNJL0zgS +DA1+33kCgYA1iAZ58XXJPh6YObvw+kg21dCLLelxp+mCoRBSbY6wq+R6PmKg4a1N +oOc6Rh/1teyBVWJ/KnkXBeh9//XLfhg0r6zHDSCsDKabeM0eoB1AKWlc5f6bWYHV +60JHDgby+V1AElKT2yQT8KVv1hWJH4XQ1/fTQpQDDoo6O+nj1r4q6w== +-----END RSA PRIVATE KEY-----"; diff --git a/bitacross-worker/core/tls-websocket-server/src/test/fixtures/test_server.rs b/bitacross-worker/core/tls-websocket-server/src/test/fixtures/test_server.rs new file mode 100644 index 0000000000..6992b27e71 --- /dev/null +++ b/bitacross-worker/core/tls-websocket-server/src/test/fixtures/test_server.rs @@ -0,0 +1,41 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{ + test::{ + fixtures::test_server_config_provider::TestServerConfigProvider, + mocks::web_socket_handler_mock::WebSocketHandlerMock, + }, + TungsteniteWsServer, +}; +use std::{string::String, sync::Arc}; + +pub type TestServer = TungsteniteWsServer; + +pub fn create_server( + handler_responses: Vec, + port: u16, +) -> (Arc, Arc) { + let config_provider = Arc::new(TestServerConfigProvider {}); + let handler = Arc::new(WebSocketHandlerMock::from_response_sequence(handler_responses)); + + let server_addr_string = format!("127.0.0.1:{}", port); + + let server = + Arc::new(TungsteniteWsServer::new(server_addr_string, config_provider, handler.clone())); + (server, handler) +} diff --git a/bitacross-worker/core/tls-websocket-server/src/test/fixtures/test_server_config_provider.rs b/bitacross-worker/core/tls-websocket-server/src/test/fixtures/test_server_config_provider.rs new file mode 100644 index 0000000000..7f267aadf5 --- /dev/null +++ b/bitacross-worker/core/tls-websocket-server/src/test/fixtures/test_server_config_provider.rs @@ -0,0 +1,43 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{ + config_provider::ProvideServerConfig, + test::fixtures::{ + test_cert::get_test_certificate_chain, test_private_key::get_test_private_key, + }, + WebSocketResult, +}; +use rustls::{NoClientAuth, ServerConfig}; +use std::sync::Arc; + +pub struct TestServerConfigProvider; + +impl ProvideServerConfig for TestServerConfigProvider { + fn get_config(&self) -> WebSocketResult> { + let mut config = rustls::ServerConfig::new(NoClientAuth::new()); + + let certs = get_test_certificate_chain(); + let privkey = get_test_private_key(); + + config + .set_single_cert_with_ocsp_and_sct(certs, privkey, vec![], vec![]) + .unwrap(); + + Ok(Arc::new(config)) + } +} diff --git a/bitacross-worker/core/tls-websocket-server/src/test/mocks/mod.rs b/bitacross-worker/core/tls-websocket-server/src/test/mocks/mod.rs new file mode 100644 index 0000000000..fd5dff2b6c --- /dev/null +++ b/bitacross-worker/core/tls-websocket-server/src/test/mocks/mod.rs @@ -0,0 +1,19 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 web_socket_connection_mock; +pub mod web_socket_handler_mock; diff --git a/bitacross-worker/core/tls-websocket-server/src/test/mocks/web_socket_connection_mock.rs b/bitacross-worker/core/tls-websocket-server/src/test/mocks/web_socket_connection_mock.rs new file mode 100644 index 0000000000..24620c9af2 --- /dev/null +++ b/bitacross-worker/core/tls-websocket-server/src/test/mocks/web_socket_connection_mock.rs @@ -0,0 +1,103 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{error::WebSocketResult, WebSocketConnection}; +use mio::{Event, Evented, Poll, PollOpt, Ready, Token}; +use std::vec::Vec; +use tungstenite::Message; + +/// Mock implementation of a web socket connection. +#[derive(PartialEq, Eq, Clone)] +pub(crate) struct WebSocketConnectionMock { + pub id: Token, + pub messages_to_read: Vec, + pub messages_written: Vec, + pub is_closed: bool, + socket: SocketMock, +} + +impl WebSocketConnectionMock { + #[allow(unused)] + pub fn new(id: Token) -> Self { + WebSocketConnectionMock { + id, + messages_to_read: Default::default(), + messages_written: Default::default(), + is_closed: false, + socket: SocketMock {}, + } + } + + #[allow(unused)] + pub fn with_messages_to_read(mut self, messages: Vec) -> Self { + self.messages_to_read = messages; + self + } +} + +impl WebSocketConnection for WebSocketConnectionMock { + type Socket = SocketMock; + + fn socket(&self) -> Option<&Self::Socket> { + Some(&self.socket) + } + + fn get_session_readiness(&self) -> Ready { + Ready::readable() + } + + fn on_ready(&mut self, _poll: &mut Poll, _ev: &Event) -> WebSocketResult<()> { + Ok(()) + } + + fn is_closed(&self) -> bool { + self.is_closed + } + + fn token(&self) -> Token { + self.id + } +} + +#[derive(PartialEq, Eq, Clone)] +pub(crate) struct SocketMock; + +impl Evented for SocketMock { + fn register( + &self, + _poll: &Poll, + _token: Token, + _interest: Ready, + _opts: PollOpt, + ) -> std::io::Result<()> { + Ok(()) + } + + fn reregister( + &self, + _poll: &Poll, + _token: Token, + _interest: Ready, + _opts: PollOpt, + ) -> std::io::Result<()> { + Ok(()) + } + + fn deregister(&self, _poll: &Poll) -> std::io::Result<()> { + Ok(()) + } +} diff --git a/bitacross-worker/core/tls-websocket-server/src/test/mocks/web_socket_handler_mock.rs b/bitacross-worker/core/tls-websocket-server/src/test/mocks/web_socket_handler_mock.rs new file mode 100644 index 0000000000..26d9b3d61c --- /dev/null +++ b/bitacross-worker/core/tls-websocket-server/src/test/mocks/web_socket_handler_mock.rs @@ -0,0 +1,68 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 = "sgx")] +use std::sync::SgxRwLock as RwLock; + +#[cfg(feature = "std")] +use std::sync::RwLock; + +use crate::{ConnectionToken, WebSocketMessageHandler, WebSocketResult}; +use log::debug; +use std::{collections::HashMap, string::String, vec::Vec}; + +pub struct WebSocketHandlerMock { + pub responses: Vec, + pub connection_message_indices: RwLock>, + pub messages_handled: RwLock>, +} + +impl WebSocketHandlerMock { + pub fn from_response_sequence(responses: Vec) -> Self { + WebSocketHandlerMock { + responses, + connection_message_indices: RwLock::default(), + messages_handled: Default::default(), + } + } + + pub fn get_handled_messages(&self) -> Vec<(ConnectionToken, String)> { + self.messages_handled.read().unwrap().clone() + } +} + +impl WebSocketMessageHandler for WebSocketHandlerMock { + fn handle_message( + &self, + connection_token: ConnectionToken, + message: String, + ) -> WebSocketResult> { + let mut handled_messages_lock = self.messages_handled.write().unwrap(); + + debug!("Handling message: {}", message); + handled_messages_lock.push((connection_token, message)); + + let mut connection_indices_lock = self.connection_message_indices.write().unwrap(); + + let message_index = connection_indices_lock.entry(connection_token).or_insert(0usize); + + let response = self.responses.get(*message_index).cloned(); + + *message_index += 1; + Ok(response) + } +} diff --git a/bitacross-worker/core/tls-websocket-server/src/test/mod.rs b/bitacross-worker/core/tls-websocket-server/src/test/mod.rs new file mode 100644 index 0000000000..0d2c1da1d4 --- /dev/null +++ b/bitacross-worker/core/tls-websocket-server/src/test/mod.rs @@ -0,0 +1,19 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 fixtures; +pub mod mocks; diff --git a/bitacross-worker/core/tls-websocket-server/src/tls_common.rs b/bitacross-worker/core/tls-websocket-server/src/tls_common.rs new file mode 100644 index 0000000000..c2061abf87 --- /dev/null +++ b/bitacross-worker/core/tls-websocket-server/src/tls_common.rs @@ -0,0 +1,70 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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(all(not(feature = "std"), feature = "sgx"))] +use crate::sgx_reexport_prelude::*; + +use crate::{error::WebSocketError, WebSocketResult}; +use rustls::NoClientAuth; +use std::{io::BufReader, string::ToString, sync::Arc, vec, vec::Vec}; + +pub fn make_config(cert: &str, key: &str) -> WebSocketResult> { + let mut config = rustls::ServerConfig::new(NoClientAuth::new()); + + let certs = load_certs(cert)?; + let privkey = load_private_key(key)?; + + config + .set_single_cert_with_ocsp_and_sct(certs, privkey, vec![], vec![]) + .expect("Invalid key der"); + + Ok(Arc::new(config)) +} + +fn load_certs(pem_content: &str) -> WebSocketResult> { + let mut reader = BufReader::new(pem_content.as_bytes()); + rustls::internal::pemfile::certs(&mut reader) + .map_err(|_| WebSocketError::InvalidCertificate("Failed to parse certificate".to_string())) +} + +fn load_private_key(pem_content: &str) -> WebSocketResult { + let rsa_keys = { + let mut reader = BufReader::new(pem_content.as_bytes()); + + rustls::internal::pemfile::rsa_private_keys(&mut reader).map_err(|_| { + WebSocketError::InvalidPrivateKey("Failed to parse RSA private key".to_string()) + })? + }; + + let pkcs8_keys = { + let mut reader = BufReader::new(pem_content.as_bytes()); + rustls::internal::pemfile::pkcs8_private_keys(&mut reader).map_err(|_| { + WebSocketError::InvalidPrivateKey( + "Invalid PKCS8 private key (encrypted keys are not supported)".to_string(), + ) + })? + }; + + // prefer to load pkcs8 keys + if !pkcs8_keys.is_empty() { + Ok(pkcs8_keys[0].clone()) + } else if !rsa_keys.is_empty() { + Ok(rsa_keys[0].clone()) + } else { + Err(WebSocketError::InvalidPrivateKey("No viable private keys were given".to_string())) + } +} diff --git a/bitacross-worker/core/tls-websocket-server/src/ws_server.rs b/bitacross-worker/core/tls-websocket-server/src/ws_server.rs new file mode 100644 index 0000000000..cacac43b33 --- /dev/null +++ b/bitacross-worker/core/tls-websocket-server/src/ws_server.rs @@ -0,0 +1,518 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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(all(not(feature = "std"), feature = "sgx"))] +use crate::sgx_reexport_prelude::*; + +#[cfg(feature = "sgx")] +use std::sync::{SgxMutex as Mutex, SgxRwLock as RwLock}; + +#[cfg(feature = "std")] +use std::sync::{Mutex, RwLock}; + +use crate::{ + config_provider::ProvideServerConfig, + connection::TungsteniteWsConnection, + connection_id_generator::GenerateConnectionId, + error::{WebSocketError, WebSocketResult}, + ConnectionIdGenerator, ConnectionToken, WebSocketConnection, WebSocketMessageHandler, + WebSocketResponder, WebSocketServer, +}; +use log::*; +use mio::{ + event::{Event, Evented}, + net::TcpListener, + Poll, +}; +use mio_extras::channel::{channel, Receiver, Sender}; +use net::SocketAddr; +use rustls::ServerConfig; +use std::{collections::HashMap, format, net, string::String, sync::Arc}; + +// Default tokens for the server. +pub(crate) const NEW_CONNECTIONS_LISTENER: mio::Token = mio::Token(0); +pub(crate) const SERVER_SIGNAL_TOKEN: mio::Token = mio::Token(1); + +/// Secure web-socket server implementation using the Tungstenite library. +pub struct TungsteniteWsServer { + ws_address: String, + config_provider: Arc, + connection_handler: Arc, + id_generator: ConnectionIdGenerator, + connections: RwLock>>, + is_running: RwLock, + signal_sender: Mutex>>, +} + +impl TungsteniteWsServer +where + ConfigProvider: ProvideServerConfig, + Handler: WebSocketMessageHandler, +{ + pub fn new( + ws_address: String, + config_provider: Arc, + connection_handler: Arc, + ) -> Self { + TungsteniteWsServer { + ws_address, + config_provider, + connection_handler, + id_generator: ConnectionIdGenerator::default(), + connections: Default::default(), + is_running: Default::default(), + signal_sender: Default::default(), + } + } + + fn accept_connection( + &self, + poll: &mut Poll, + tcp_listener: &TcpListener, + tls_config: Arc, + ) -> WebSocketResult<()> { + let (socket, addr) = tcp_listener.accept()?; + + debug!("Accepting new connection from {:?}", addr); + + let tls_session = rustls::ServerSession::new(&tls_config); + let connection_id = self.id_generator.next_id()?; + let token = mio::Token(connection_id); + trace!("New connection has token {:?}", token); + + let mut web_socket_connection = TungsteniteWsConnection::new( + socket, + tls_session, + token, + self.connection_handler.clone(), + )?; + + trace!("Web-socket connection created"); + web_socket_connection.register(poll)?; + + let mut connections_lock = + self.connections.write().map_err(|_| WebSocketError::LockPoisoning)?; + connections_lock.insert(token, web_socket_connection); + + debug!("Accepted connection, {} active connections", connections_lock.len()); + Ok(()) + } + + fn connection_event(&self, poll: &mut mio::Poll, event: &Event) -> WebSocketResult<()> { + let token = event.token(); + + let mut connections_lock = + self.connections.write().map_err(|_| WebSocketError::LockPoisoning)?; + + if let Some(connection) = connections_lock.get_mut(&token) { + connection.on_ready(poll, event)?; + + if connection.is_closed() { + trace!("Connection {:?} is closed, removing", token); + connections_lock.remove(&token); + trace!( + "Closed {:?}, {} active connections remaining", + token, + connections_lock.len() + ); + } + } + + Ok(()) + } + + /// Send a message response to a connection. + /// Make sure this is called inside the event loop, otherwise dead-locks are possible. + fn write_message_to_connection( + &self, + message: String, + connection_token: ConnectionToken, + ) -> WebSocketResult<()> { + let mut connections_lock = + self.connections.write().map_err(|_| WebSocketError::LockPoisoning)?; + let connection = connections_lock + .get_mut(&connection_token.into()) + .ok_or_else(|| WebSocketError::InvalidConnection(connection_token.0))?; + connection.write_message(message) + } + + fn handle_server_signal( + &self, + poll: &mut mio::Poll, + event: &Event, + signal_receiver: &mut Receiver, + ) -> WebSocketResult { + let signal = signal_receiver.try_recv()?; + let mut do_shutdown = false; + + match signal { + ServerSignal::ShutDown => { + do_shutdown = true; + }, + ServerSignal::SendResponse(message, connection_token) => { + if let Err(e) = self.write_message_to_connection(message, connection_token) { + error!("Failed to send web-socket response: {:?}", e); + } + }, + } + + signal_receiver.reregister( + poll, + event.token(), + mio::Ready::readable(), + mio::PollOpt::level(), + )?; + + Ok(do_shutdown) + } + + fn register_server_signal_sender(&self, sender: Sender) -> WebSocketResult<()> { + let mut sender_lock = + self.signal_sender.lock().map_err(|_| WebSocketError::LockPoisoning)?; + *sender_lock = Some(sender); + Ok(()) + } + + fn send_server_signal(&self, server_signal: ServerSignal) -> WebSocketResult<()> { + match self.signal_sender.lock().map_err(|_| WebSocketError::LockPoisoning)?.as_ref() { + None => { + warn!( + "Signal sender has not been initialized, cannot send web-socket server signal" + ); + }, + Some(signal_sender) => { + signal_sender + .send(server_signal) + .map_err(|e| WebSocketError::Other(format!("{:?}", e).into()))?; + }, + } + + Ok(()) + } +} + +impl WebSocketServer for TungsteniteWsServer +where + ConfigProvider: ProvideServerConfig, + Handler: WebSocketMessageHandler, +{ + type Connection = TungsteniteWsConnection; + + fn run(&self) -> WebSocketResult<()> { + debug!("Running tungstenite web socket server on {}", self.ws_address); + + let socket_addr: SocketAddr = + self.ws_address.parse().map_err(WebSocketError::InvalidWsAddress)?; + + let config = self.config_provider.get_config()?; + + let (server_signal_sender, mut signal_receiver) = channel::(); + self.register_server_signal_sender(server_signal_sender)?; + + let tcp_listener = net::TcpListener::bind(socket_addr).expect("Could not listen on port"); + let tcp_listener = + mio::net::TcpListener::from_std(tcp_listener).map_err(WebSocketError::TcpBindError)?; + let mut poll = Poll::new()?; + poll.register( + &tcp_listener, + NEW_CONNECTIONS_LISTENER, + mio::Ready::readable(), + mio::PollOpt::level(), + )?; + + poll.register( + &signal_receiver, + SERVER_SIGNAL_TOKEN, + mio::Ready::readable(), + mio::PollOpt::level(), + )?; + + let mut events = mio::Events::with_capacity(2048); + + *self.is_running.write().map_err(|_| WebSocketError::LockPoisoning)? = true; + + // Run the event loop. + 'outer_event_loop: loop { + let num_events = poll.poll(&mut events, None)?; + debug!("Number of readiness events: {}", num_events); + + for event in events.iter() { + match event.token() { + NEW_CONNECTIONS_LISTENER => { + trace!("Received new connection event"); + if let Err(e) = + self.accept_connection(&mut poll, &tcp_listener, config.clone()) + { + error!("Failed to accept new web-socket connection: {:?}", e); + } + }, + SERVER_SIGNAL_TOKEN => { + trace!("Received server signal event"); + if self.handle_server_signal(&mut poll, &event, &mut signal_receiver)? { + break 'outer_event_loop + } + }, + _ => { + trace!("Connection (token {:?}) activity event", event.token()); + if let Err(e) = self.connection_event(&mut poll, &event) { + error!("Failed to process connection event: {:?}", e); + } + }, + } + } + } + + info!("Web-socket server has shut down"); + Ok(()) + } + + fn is_running(&self) -> WebSocketResult { + Ok(*self.is_running.read().map_err(|_| WebSocketError::LockPoisoning)?) + } + + fn shut_down(&self) -> WebSocketResult<()> { + info!("Shutdown request of web-socket server detected, shutting down.."); + self.send_server_signal(ServerSignal::ShutDown) + } +} + +impl WebSocketResponder for TungsteniteWsServer +where + ConfigProvider: ProvideServerConfig, + Handler: WebSocketMessageHandler, +{ + fn send_message( + &self, + connection_token: ConnectionToken, + message: String, + ) -> WebSocketResult<()> { + self.send_server_signal(ServerSignal::SendResponse(message, connection_token)) + } +} + +/// Internal server signal enum. +enum ServerSignal { + ShutDown, + SendResponse(String, ConnectionToken), +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::test::{ + fixtures::{no_cert_verifier::NoCertVerifier, test_server::create_server}, + mocks::web_socket_handler_mock::WebSocketHandlerMock, + }; + use rustls::ClientConfig; + use std::{net::TcpStream, thread, time::Duration}; + use tungstenite::{ + client_tls_with_config, stream::MaybeTlsStream, Connector, Message, WebSocket, + }; + use url::Url; + + #[test] + fn server_handles_multiple_connections() { + let _ = env_logger::builder().is_test(true).try_init(); + + let expected_answer = "websocket server response bidibibup".to_string(); + let port: u16 = 21777; + const NUMBER_OF_CONNECTIONS: usize = 100; + + let (server, handler) = create_server(vec![expected_answer.clone()], port); + + let server_clone = server.clone(); + let server_join_handle = thread::spawn(move || server_clone.run()); + + // Wait until server is up. + while !server.is_running().unwrap() { + thread::sleep(std::time::Duration::from_millis(50)); + } + + // Spawn multiple clients that connect to the server simultaneously and send a message. + let client_handles: Vec<_> = (0..NUMBER_OF_CONNECTIONS) + .map(|_| { + let expected_answer_clone = expected_answer.clone(); + + thread::sleep(Duration::from_millis(5)); + + thread::spawn(move || { + let mut socket = connect_tls_client(get_server_addr(port).as_str()); + + socket + .write_message(Message::Text("Hello WebSocket".into())) + .expect("client write message to be successful"); + + assert_eq!( + Message::Text(expected_answer_clone), + socket.read_message().unwrap() + ); + + thread::sleep(Duration::from_millis(2)); + + socket + .write_message(Message::Text("Second message".into())) + .expect("client write message to be successful"); + + thread::sleep(Duration::from_millis(2)); + + socket.close(None).unwrap(); + socket.write_pending().unwrap(); + }) + }) + .collect(); + + for handle in client_handles.into_iter() { + handle.join().expect("client handle to be joined"); + } + + server.shut_down().unwrap(); + + let server_shutdown_result = + server_join_handle.join().expect("Couldn't join on the associated thread"); + if let Err(e) = server_shutdown_result { + panic!("Test failed, web-socket returned error: {:?}", e); + } + + assert_eq!(2 * NUMBER_OF_CONNECTIONS, handler.get_handled_messages().len()); + } + + #[test] + fn server_closes_connection_if_client_does_not_wait_for_reply() { + let _ = env_logger::builder().is_test(true).try_init(); + + let expected_answer = "websocket server response".to_string(); + let port: u16 = 21778; + + let (server, handler) = create_server(vec![expected_answer.clone()], port); + + let server_clone = server.clone(); + let server_join_handle = thread::spawn(move || server_clone.run()); + + // Wait until server is up. + while !server.is_running().unwrap() { + thread::sleep(std::time::Duration::from_millis(50)); + } + + let client_join_handle = thread::spawn(move || { + let mut socket = connect_tls_client(get_server_addr(port).as_str()); + socket + .write_message(Message::Text("First request".into())) + .expect("client write message to be successful"); + + // We never read, just send a message and close the connection, despite the server + // trying to send a reply (which will fail). + socket.close(None).unwrap(); + socket.write_pending().unwrap(); + }); + + client_join_handle.join().unwrap(); + server.shut_down().unwrap(); + server_join_handle.join().unwrap().unwrap(); + + assert_eq!(1, handler.get_handled_messages().len()); + } + + #[test] + fn server_sends_update_message_to_client() { + let _ = env_logger::builder().is_test(true).try_init(); + + let expected_answer = "first response".to_string(); + let port: u16 = 21779; + let (server, handler) = create_server(vec![expected_answer.clone()], port); + + let server_clone = server.clone(); + let server_join_handle = thread::spawn(move || server_clone.run()); + + // Wait until server is up. + while !server.is_running().unwrap() { + thread::sleep(std::time::Duration::from_millis(50)); + } + + let update_message = "Message update".to_string(); + let update_message_clone = update_message.clone(); + + let client_join_handle = thread::spawn(move || { + let mut socket = connect_tls_client(get_server_addr(port).as_str()); + socket + .write_message(Message::Text("First request".into())) + .expect("client write message to be successful"); + + assert_eq!(Message::Text(expected_answer), socket.read_message().unwrap()); + assert_eq!(Message::Text(update_message_clone), socket.read_message().unwrap()); + }); + + let connection_token = poll_handler_for_first_connection(handler.as_ref()); + + // Send reply to a wrong connection token. Succeeds, because error is caught in the event loop + // and not the `send_message` method itself. + assert!(server + .send_message( + ConnectionToken(connection_token.0 + 1), + "wont get to the client".to_string() + ) + .is_ok()); + + // Send reply to the correct connection token. + server.send_message(connection_token, update_message).unwrap(); + + client_join_handle.join().unwrap(); + server.shut_down().unwrap(); + server_join_handle.join().unwrap().unwrap(); + + assert_eq!(1, handler.get_handled_messages().len()); + } + + // Ignored because it does not directly test any of our own components. + // It was used to test the behavior of the tungstenite client configuration with certificates. + #[test] + #[ignore] + fn client_test() { + let mut socket = connect_tls_client("ws.ifelse.io:443"); + + socket + .write_message(Message::Text("Hello WebSocket".into())) + .expect("client write message to be successful"); + } + + fn poll_handler_for_first_connection(handler: &WebSocketHandlerMock) -> ConnectionToken { + loop { + match handler.get_handled_messages().first() { + None => thread::sleep(Duration::from_millis(5)), + Some(m) => return m.0, + } + } + } + + fn get_server_addr(port: u16) -> String { + format!("localhost:{}", port) + } + + fn connect_tls_client(server_addr: &str) -> WebSocket> { + let ws_server_url = Url::parse(format!("wss://{}", server_addr).as_str()).unwrap(); + + let mut config = ClientConfig::new(); + config.dangerous().set_certificate_verifier(Arc::new(NoCertVerifier {})); + let connector = Connector::Rustls(Arc::new(config)); + let stream = TcpStream::connect(server_addr).unwrap(); + + let (socket, _response) = + client_tls_with_config(ws_server_url, stream, None, Some(connector)) + .expect("Can't connect"); + + socket + } +} diff --git a/bitacross-worker/docker/README.md b/bitacross-worker/docker/README.md new file mode 100644 index 0000000000..7f9ddb7a86 --- /dev/null +++ b/bitacross-worker/docker/README.md @@ -0,0 +1,116 @@ +# How to run the multi-validateer docker setup + +## Prerequisite + +* Make sure you have installed Docker (version >= `2.0.0`) with [Docker Compose](https://docs.docker.com/compose/install/). On Windows, this can be Docker Desktop with WSL 2 integration. +* In case you also build the worker directly, without docker (e.g. on a dev machine, running `make`), you should run `make clean` before running the docker build. Otherwise, it can occasionally lead to build errors. +* The node image version that is loaded in the `docker-compose.yml`, (e.g. `image: "integritee/integritee-node:1.1.3"`) needs to be compatible with the worker you're trying to build. +* Set export VERSION=dev +* `envsubst` should be installed, it is needed to replace the $VERSION in yaml files as docker compose doesn't support variables on service names. + +## Building the Docker containers + +Run +``` +COMPOSE_DOCKER_CLI_BUILD=1 DOCKER_BUILDKIT=1 docker compose -f <(envsubst < docker-compose.yml) build +``` +in this folder to build the worker image. This will build the worker from source and tag it in an image called `integritee-worker:dev`. + +## Running the docker setup + +``` +docker compose -f <(envsubst < docker-compose.yml) up +``` +Starts all services (node and workers), using the `integritee-worker:dev` images you've built in the previous step. + +## Run the demos + +### Demo indirect invocation (M6) +Build +``` +COMPOSE_DOCKER_CLI_BUILD=1 DOCKER_BUILDKIT=1 docker compose -f <(envsubst < docker-compose.yml) -f <(envsubst < demo-shielding-unshielding-multiworker.yml) build --build-arg WORKER_MODE_ARG=offchain-worker +``` +Run +``` +FLAVOR_ID=offchain-worker docker compose -f <(envsubst < docker-compose.yml) -f <(envsubst < demo-shielding-unshielding-multiworker.yml) up demo-shielding-unshielding-multiworker --exit-code-from demo-shielding-unshielding-multiworker +``` +### Demo direct call (M8) + +Build +``` +COMPOSE_DOCKER_CLI_BUILD=1 DOCKER_BUILDKIT=1 docker compose -f <(envsubst < docker-compose.yml) -f <(envsubst < demo-direct-call.yml) build --build-arg WORKER_MODE_ARG=sidechain +``` +Run +``` +docker compose -f <(envsubst < docker-compose.yml) -f <(envsubst < demo-direct-call.yml) up demo-direct-call --exit-code-from demo-direct-call +``` + +### Demo sidechain +Build +``` +COMPOSE_DOCKER_CLI_BUILD=1 DOCKER_BUILDKIT=1 docker compose -f <(envsubst < docker-compose.yml) -f <(envsubst < demo-sidechain.yml) build --build-arg WORKER_MODE_ARG=sidechain +``` +Run +``` +docker compose -f <(envsubst < docker-compose.yml) -f <(envsubst < demo-sidechain.yml) up demo-sidechain --exit-code-from demo-sidechain +``` + +### Demo Teeracle +Build +``` +COMPOSE_DOCKER_CLI_BUILD=1 DOCKER_BUILDKIT=1 docker compose -f <(envsubst < docker-compose.yml) -f <(envsubst < demo-teeracle.yml) build --build-arg WORKER_MODE_ARG=teeracle +``` +Run +``` +docker compose -f <(envsubst < docker-compose.yml) -f <(envsubst < demo-teeracle.yml) up demo-teeracle --exit-code-from demo-teeracle +``` + + +## Run the benchmarks +Build with +``` +COMPOSE_DOCKER_CLI_BUILD=1 DOCKER_BUILDKIT=1 docker compose -f <(envsubst < docker-compose.yml) -f <(envsubst < sidechain-benchmark.yml) build +``` +and then run with +``` +docker compose -f <(envsubst < docker-compose.yml) -f <(envsubst < sidechain-benchmark.yml) up sidechain-benchmark --exit-code-from sidechain-benchmark +``` + +## Run the fork simulator +The fork simulation uses `pumba` which in turn uses the Linux traffic control (TC). This is only available on Linux hosts, not on Windows with WSL unfortunately. +Build the docker compose setup with +``` +COMPOSE_DOCKER_CLI_BUILD=1 DOCKER_BUILDKIT=1 docker compose -f <(envsubst < docker-compose.yml) -f <(envsubst < fork-inducer.yml) -f <(envsubst < demo-sidechain.yml) build --build-arg WORKER_MODE_ARG=sidechain +``` + +This requires the docker BuildKit (docker version >= 18.09) and support for it in docker compose (version >= 1.25.0) + +Run the 2-worker setup with a fork inducer (pumba) that delays the traffic on worker 2 +``` +docker compose -f <(envsubst < docker-compose.yml) -f <(envsubst < fork-inducer.yml) -f <(envsubst < integration-test.yml) up --exit-code-from demo-sidechain +``` + +This should show that the integration test fails, because we had an unhandled fork in the sidechain. Clean up the containers after each run with: +``` +docker compose -f <(envsubst < docker-compose.yml) -f <(envsubst < fork-inducer.yml) -f <(envsubst < demo-sidechain.yml) down +``` + +We need these different compose files to separate the services that we're using. E.g. we want the integration test and fork simulator to be optional. The same could be solved using `profiles` - but that requires a more up-to-date version of `docker compose`. + +## FAQ +### What do I have to do to stop everything properly? +With `Ctrl-C` you stop the containers and with `docker compose down` you clean up/remove the containers. Note that `docker compose down` will also remove any logs docker has saved, since it will remove all the container context. + +### What do I have to do if I make changes to the code? +You need to re-build the worker image, using `docker compose build`. + +### How can I change the log level? +You can change the environment variable `RUST_LOG=` in the `docker-compose.yml` for each worker individually. + +### The log from the node are quite a nuisance. Why are they all together. +You can suppress the log output for a container by setting the logging driver. This can be set to either `none` (completely disables all logs), or `local` (docker will record the logs, depending on your docker compose version, it will also log to `stdout`) in the `docker-compose.yml`: +``` +logging: + driver: local +``` +Mind the indent. Explanations for all the logging drivers in `docker compose` can be found [here](https://docs.docker.com/config/containers/logging/local/). diff --git a/bitacross-worker/docker/demo-direct-call.yml b/bitacross-worker/docker/demo-direct-call.yml new file mode 100644 index 0000000000..504b53fdea --- /dev/null +++ b/bitacross-worker/docker/demo-direct-call.yml @@ -0,0 +1,27 @@ +services: + demo-direct-call: + image: litentry/bitacross-cli:latest + devices: + - "${SGX_PROVISION:-/dev/null}:/dev/sgx/provision" + - "${SGX_ENCLAVE:-/dev/null}:/dev/sgx/enclave" + volumes: + - "${AESMD:-/dev/null}:/var/run/aesmd" + - "${SGX_QCNL:-/dev/null}:/etc/sgx_default_qcnl.conf" + build: + context: ${PWD}/.. + dockerfile: build.Dockerfile + target: deployed-client + depends_on: + litentry-node: + condition: service_healthy + bitacross-worker-1: + condition: service_healthy + networks: + - litentry-test-network + entrypoint: + "/usr/local/worker-cli/demo_direct_call.sh -p 9912 -u ws://litentry-node + -V wss://bitacross-worker-1 -P 2011 -C /usr/local/bin/bitacross-cli 2>&1" + restart: "no" +networks: + litentry-test-network: + driver: bridge \ No newline at end of file diff --git a/bitacross-worker/docker/demo-shielding-unshielding-multiworker.yml b/bitacross-worker/docker/demo-shielding-unshielding-multiworker.yml new file mode 100644 index 0000000000..8581311a41 --- /dev/null +++ b/bitacross-worker/docker/demo-shielding-unshielding-multiworker.yml @@ -0,0 +1,29 @@ +services: + demo-shielding-unshielding-multiworker: + image: litentry/bitacross-cli:latest + devices: + - "${SGX_PROVISION:-/dev/null}:/dev/sgx/provision" + - "${SGX_ENCLAVE:-/dev/null}:/dev/sgx/enclave" + volumes: + - "${AESMD:-/dev/null}:/var/run/aesmd" + - "${SGX_QCNL:-/dev/null}:/etc/sgx_default_qcnl.conf" + build: + context: ${PWD}/.. + dockerfile: build.Dockerfile + target: deployed-client + depends_on: + litentry-node: + condition: service_healthy + bitacross-worker-1: + condition: service_healthy + environment: + - RUST_LOG=warn,ws=warn,itc_rpc_client=debug,litentry_cli=debug + networks: + - litentry-test-network + entrypoint: + "/usr/local/worker-cli/demo_shielding_unshielding.sh -t first -p 9912 -u ws://litentry-node + -V wss://bitacross-worker-1 -P 2011 -C /usr/local/bin/bitacross-cli 2>&1" + restart: "no" +networks: + litentry-test-network: + driver: bridge \ No newline at end of file diff --git a/bitacross-worker/docker/demo-sidechain.yml b/bitacross-worker/docker/demo-sidechain.yml new file mode 100644 index 0000000000..449d882707 --- /dev/null +++ b/bitacross-worker/docker/demo-sidechain.yml @@ -0,0 +1,32 @@ +services: + demo-sidechain: + image: litentry/bitacross-cli:latest + devices: + - "${SGX_PROVISION:-/dev/null}:/dev/sgx/provision" + - "${SGX_ENCLAVE:-/dev/null}:/dev/sgx/enclave" + volumes: + - "${AESMD:-/dev/null}:/var/run/aesmd" + - "${SGX_QCNL:-/dev/null}:/etc/sgx_default_qcnl.conf" + + build: + context: ${PWD}/.. + dockerfile: build.Dockerfile + target: deployed-client + depends_on: + litentry-node: + condition: service_healthy + bitacross-worker-1: + condition: service_healthy + bitacross-worker-2: + condition: service_healthy + environment: + - RUST_LOG=warn,ws=warn,sp_io=warn,substrate_api_client=warn,jsonrpsee_ws_client=warn,jsonrpsee_ws_server=warn,enclave_runtime=warn,integritee_service=info,integritee_service::sidechain=debug,ita_stf=warn + networks: + - litentry-test-network + entrypoint: + "/usr/local/worker-cli/demo_sidechain.sh -p 9912 -A 2011 -B 2012 -u ws://litentry-node + -V wss://bitacross-worker-1 -W wss://bitacross-worker-2 -C /usr/local/bin/bitacross-cli 2>&1" + restart: "no" +networks: + litentry-test-network: + driver: bridge diff --git a/bitacross-worker/docker/demo-smart-contract.yml b/bitacross-worker/docker/demo-smart-contract.yml new file mode 100644 index 0000000000..c6541b6d09 --- /dev/null +++ b/bitacross-worker/docker/demo-smart-contract.yml @@ -0,0 +1,31 @@ +services: + demo-smart-contract: + image: bitacross-cli:${VERSION:-dev} + devices: + - "${SGX_PROVISION:-/dev/null}:/dev/sgx/provision" + - "${SGX_ENCLAVE:-/dev/null}:/dev/sgx/enclave" + volumes: + - "${AESMD:-/dev/null}:/var/run/aesmd" + - "${SGX_QCNL:-/dev/null}:/etc/sgx_default_qcnl.conf" + build: + context: ${PWD}/.. + dockerfile: build.Dockerfile + target: deployed-client + depends_on: + litentry-node-${VERSION}: + condition: service_healthy + bitacross-worker-1-${VERSION}: + condition: service_healthy + bitacross-worker-2-${VERSION}: + condition: service_healthy + environment: + - RUST_LOG=warn,ws=warn,itc_rpc_client=warn + networks: + - litentry-test-network + entrypoint: + "/usr/local/worker-cli/demo_smart_contract.sh -p 9912 -u ws://litentry-node + -V wss://bitacross-worker-1 -A 2011 -C /usr/local/bin/bitacross-cli 2>&1" + restart: "no" +networks: + litentry-test-network: + driver: bridge diff --git a/bitacross-worker/docker/demo-teeracle-generic.yml b/bitacross-worker/docker/demo-teeracle-generic.yml new file mode 100644 index 0000000000..4ff30dafdf --- /dev/null +++ b/bitacross-worker/docker/demo-teeracle-generic.yml @@ -0,0 +1,68 @@ +# Teeracle Demo Setup +# +# The demo is parameterized with the interval that the teeracle uses to query its sources. +# Set the `TEERACLE_INTERVAL_SECONDS` variable when invoking, e.g. `TEERACLE_INTERVAL_SECONDS=4 docker compose -f docker-compose.yml -f demo-teeracle-generic.yml up --exit-code-from demo-teeracle-generic` +# Set the `ADDITIONAL_RUNTIME_FLAGS` variable to for additional flags. +# To skip remote attestation: `export ADDITIONAL_RUNTIME_FLAG="--skip-ra"` +services: + integritee-teeracle-worker-${VERSION}: + image: integritee-worker:${VERSION:-dev} + hostname: integritee-teeracle-worker + devices: + - "${SGX_PROVISION:-/dev/null}:/dev/sgx/provision" + - "${SGX_ENCLAVE:-/dev/null}:/dev/sgx/enclave" + volumes: + - "${AESMD:-/dev/null}:/var/run/aesmd" + - "${SGX_QCNL:-/dev/null}:/etc/sgx_default_qcnl.conf" + build: + context: ${PWD}/.. + dockerfile: build.Dockerfile + target: deployed-worker + depends_on: + integritee-node-${VERSION}: + condition: service_healthy + environment: + - RUST_LOG=warn,ws=warn,sp_io=warn,substrate_api_client=warn,jsonrpsee_ws_client=warn,jsonrpsee_ws_server=warn,enclave_runtime=warn,integritee_service=info,integritee_service::teeracle=debug,ita_stf=warn,ita_oracle=debug + networks: + - integritee-test-network + healthcheck: + test: curl -s -f http://integritee-teeracle-worker:4645/is_initialized || exit 1 + interval: 10s + timeout: 10s + retries: 25 + command: + "--clean-reset --ws-external -M integritee-teeracle-worker -T wss://integritee-teeracle-worker + -u ws://integritee-node -U ws://integritee-teeracle-worker -P 2011 -w 2101 -p 9912 -h 4645 + run --dev ${ADDITIONAL_RUNTIME_FLAGS} --teeracle-interval ${TEERACLE_INTERVAL_SECONDS}s" + restart: always + demo-teeracle-generic: + image: bitacross-cli:${VERSION:-dev} + devices: + - "${SGX_PROVISION:-/dev/null}:/dev/sgx/provision" + - "${SGX_ENCLAVE:-/dev/null}:/dev/sgx/enclave" + volumes: + - "${AESMD:-/dev/null}:/var/run/aesmd" + - "${SGX_QCNL:-/dev/null}:/etc/sgx_default_qcnl.conf" + build: + context: ${PWD}/.. + dockerfile: build.Dockerfile + target: deployed-client + depends_on: + integritee-node-${VERSION}: + condition: service_healthy + integritee-teeracle-worker-${VERSION}: + condition: service_healthy + environment: + - RUST_LOG=warn,sp_io=warn,integritee_cli::exchange_oracle=debug + networks: + - integritee-test-network + entrypoint: + "/usr/local/worker-cli/demo_teeracle_generic.sh + -u ws://integritee-node -p 9912 + -V wss://integritee-teeracle-worker -P 2011 + -d 21 -i ${TEERACLE_INTERVAL_SECONDS} + -C /usr/local/bin/bitacross-cli 2>&1" + restart: "no" +networks: + integritee-test-network: + driver: bridge diff --git a/bitacross-worker/docker/demo-teeracle.yml b/bitacross-worker/docker/demo-teeracle.yml new file mode 100644 index 0000000000..d71b36df6b --- /dev/null +++ b/bitacross-worker/docker/demo-teeracle.yml @@ -0,0 +1,71 @@ +# Teeracle Demo Setup +# +# The demo is parameterized with the interval that the teeracle uses to query its sources. +# Set the `TEERACLE_INTERVAL_SECONDS` variable when invoking, e.g. `TEERACLE_INTERVAL_SECONDS=4 docker compose -f docker-compose.yml -f demo-teeracle.yml up --exit-code-from demo-teeracle` +# This setup requires an API key for CoinMarketCap +# Add the API key to the environment variable `COINMARKETCAP_KEY`, with `export COINMARKETCAP_KEY=` +# Set the `ADDITIONAL_RUNTIME_FLAGS` variable to for additional flags. +# To skip remote attestation: `export ADDITIONAL_RUNTIME_FLAG="--skip-ra"` +services: + integritee-teeracle-worker-${VERSION}: + image: integritee-worker:${VERSION:-dev} + hostname: integritee-teeracle-worker + devices: + - "${SGX_PROVISION:-/dev/null}:/dev/sgx/provision" + - "${SGX_ENCLAVE:-/dev/null}:/dev/sgx/enclave" + volumes: + - "${AESMD:-/dev/null}:/var/run/aesmd" + - "${SGX_QCNL:-/dev/null}:/etc/sgx_default_qcnl.conf" + build: + context: ${PWD}/.. + dockerfile: build.Dockerfile + target: deployed-worker + depends_on: + integritee-node-${VERSION}: + condition: service_healthy + environment: + - RUST_LOG=warn,ws=warn,sp_io=warn,substrate_api_client=warn,jsonrpsee_ws_client=warn,jsonrpsee_ws_server=warn,enclave_runtime=warn,integritee_service=info,integritee_service::teeracle=debug,ita_stf=warn,ita_exchange_oracle=debug + - COINMARKETCAP_KEY + networks: + - integritee-test-network + healthcheck: + test: curl -s -f http://integritee-teeracle-worker:4645/is_initialized || exit 1 + interval: 10s + timeout: 10s + retries: 25 + command: + "--clean-reset --ws-external -M integritee-teeracle-worker -T wss://integritee-teeracle-worker + -u ws://integritee-node -U ws://integritee-teeracle-worker -P 2011 -w 2101 -p 9912 -h 4645 + run --dev ${ADDITIONAL_RUNTIME_FLAGS} --teeracle-interval ${TEERACLE_INTERVAL_SECONDS}s" + restart: always + demo-teeracle: + image: bitacross-cli:${VERSION:-dev} + devices: + - "${SGX_PROVISION:-/dev/null}:/dev/sgx/provision" + - "${SGX_ENCLAVE:-/dev/null}:/dev/sgx/enclave" + volumes: + - "${AESMD:-/dev/null}:/var/run/aesmd" + - "${SGX_QCNL:-/dev/null}:/etc/sgx_default_qcnl.conf" + build: + context: ${PWD}/.. + dockerfile: build.Dockerfile + target: deployed-client + depends_on: + integritee-node-${VERSION}: + condition: service_healthy + integritee-teeracle-worker-${VERSION}: + condition: service_healthy + environment: + - RUST_LOG=warn,sp_io=warn,integritee_cli::exchange_oracle=debug + networks: + - integritee-test-network + entrypoint: + "/usr/local/worker-cli/demo_teeracle_whitelist.sh + -u ws://integritee-node -p 9912 + -V wss://integritee-teeracle-worker -P 2011 + -d 7 -i ${TEERACLE_INTERVAL_SECONDS} + -C /usr/local/bin/bitacross-cli 2>&1" + restart: "no" +networks: + integritee-test-network: + driver: bridge diff --git a/bitacross-worker/docker/docker-compose.yml b/bitacross-worker/docker/docker-compose.yml new file mode 100644 index 0000000000..fedb1e549f --- /dev/null +++ b/bitacross-worker/docker/docker-compose.yml @@ -0,0 +1,156 @@ +services: + relaychain-alice: + image: docker_relaychain-alice:latest + networks: + - litentry-test-network + ports: + - 9946:9944 + - 9936:9933 + - 30336:30333 + volumes: + - relaychain-alice:/data + build: + context: litentry + dockerfile: relaychain.Dockerfile + command: + - --base-path=/data + - --chain=/app/rococo-local.json + - --validator + - --ws-external + - --rpc-external + - --rpc-cors=all + - --name=alice + - --alice + - --rpc-methods=unsafe + - --execution=wasm + environment: + RUST_LOG: parachain::candidate-backing=trace,parachain::candidate-selection=trace,parachain::pvf=trace,parachain::collator-protocol=trace,parachain::provisioner=trace + ulimits: + &a1 + nofile: + soft: 65536 + hard: 65536 + relaychain-bob: + image: docker_relaychain-bob:latest + networks: + - litentry-test-network + ports: + - 9947:9944 + - 9937:9933 + - 30337:30333 + volumes: + - relaychain-bob:/data + build: + context: litentry + dockerfile: relaychain.Dockerfile + command: + - --base-path=/data + - --chain=/app/rococo-local.json + - --validator + - --ws-external + - --rpc-external + - --rpc-cors=all + - --name=bob + - --bob + - --rpc-methods=unsafe + - --execution=wasm + environment: + RUST_LOG: parachain::candidate-backing=trace,parachain::candidate-selection=trace,parachain::pvf=trace,parachain::collator-protocol=trace,parachain::provisioner=trace + ulimits: *a1 + litentry-node: + image: docker_litentry-node:latest + container_name: litentry-node + networks: + - litentry-test-network + ports: + # TODO: maybe not use 9912 as port + - 9944:9912 + - 9933:9933 + - 30333:30333 + volumes: + - parachain-2106-0:/data + build: + context: litentry + dockerfile: parachain-2106.Dockerfile + depends_on: ['relaychain-alice', 'relaychain-bob'] + healthcheck: + test: ["CMD", "nc", "-z", "litentry-node", "9912"] + interval: 30s + timeout: 10s + retries: 20 + command: + - --base-path=/data + - --chain=/app/rococo-dev-2106.json + - --ws-external + - --rpc-external + - --rpc-cors=all + - --name=parachain-2106-0 + - --ws-port=9912 + - --collator + - --rpc-methods=unsafe + - --force-authoring + - --execution=wasm + - --alice + - --node-key=e998e728d8bf5bff6670c5e2b20455f6de1742b7ca564057680c9781cf037dd1 + - --listen-addr=/ip4/0.0.0.0/tcp/30333 + - -- + - --chain=/app/rococo-local.json + - --execution=wasm + environment: + RUST_LOG: sc_basic_authorship=trace,cumulus-consensus=trace,cumulus-collator=trace,collator_protocol=trace,collation_generation=trace,aura=debug + ulimits: *a1 + bitacross-worker-1: + image: litentry/bitacross-worker:latest + container_name: bitacross-worker-1 + build: + context: ${PWD}/.. + dockerfile: build.Dockerfile + target: deployed-worker + depends_on: + litentry-node: + condition: service_healthy + devices: + - "${SGX_PROVISION:-/dev/null}:/dev/sgx/provision" + - "${SGX_ENCLAVE:-/dev/null}:/dev/sgx/enclave" + volumes: + - "${AESMD:-/dev/null}:/var/run/aesmd" + - "${SGX_QCNL:-/dev/null}:/etc/sgx_default_qcnl.conf" + environment: + - RUST_LOG=info,litentry_worker=debug,ws=warn,sp_io=error,substrate_api_client=warn,itc_parentchain_light_client=info,jsonrpsee_ws_client=warn,jsonrpsee_ws_server=warn,enclave_runtime=debug,ita_stf=debug,its_rpc_handler=warn,itc_rpc_client=warn,its_consensus_common=debug,its_state=warn,its_consensus_aura=warn,aura*=warn,its_consensus_slots=warn,itp_attestation_handler=debug,http_req=debug,lc_mock_server=warn,itc_rest_client=debug,lc_credentials=debug,lc_identity_verification=debug,lc_stf_task_receiver=debug,lc_stf_task_sender=debug,lc_data_providers=debug,itp_top_pool=debug,itc_parentchain_indirect_calls_executor=debug, + - TWITTER_OFFICIAL_URL=http://localhost:19527 + - TWITTER_LITENTRY_URL=http://localhost:19527 + - TWITTER_AUTH_TOKEN_V2= + - DISCORD_OFFICIAL_URL=http://localhost:19527 + - DISCORD_LITENTRY_URL=http://localhost:19527 + - DISCORD_AUTH_TOKEN= + - ACHAINABLE_URL=http://localhost:19527 + - ACHAINABLE_AUTH_KEY= + - CREDENTIAL_ENDPOINT=http://localhost:9933 + - ONEBLOCK_NOTION_KEY=ABCDEFGHIJKLMNOPQRSTUVWXYZ + - ONEBLOCK_NOTION_URL=https://abc.com + - SORA_QUIZ_MASTER_ID=SORA_QUIZ_MASTER_ID + - SORA_QUIZ_ATTENDEE_ID=SORA_QUIZ_ATTENDEE_ID + - NODEREAL_API_KEY=NODEREAL_API_KEY + - NODEREAL_API_URL=https://open-platform.nodereal.io/ + - CONTEST_LEGEND_DISCORD_ROLE_ID=CONTEST_LEGEND_DISCORD_ROLE_ID + - CONTEST_POPULARITY_DISCORD_ROLE_ID=CONTEST_POPULARITY_DISCORD_ROLE_ID + - CONTEST_PARTICIPANT_DISCORD_ROLE_ID=CONTEST_PARTICIPANT_DISCORD_ROLE_ID + networks: + - litentry-test-network + healthcheck: + test: curl -s -f http://bitacross-worker-1:4645/is_initialized || exit 1 + interval: 30s + timeout: 10s + retries: 20 + entrypoint: + "/usr/local/bin/bitacross-worker --clean-reset --ws-external -M bitacross-worker-1 -T wss://bitacross-worker-1 + -u ws://litentry-node -U ws://bitacross-worker-1 -P 2011 -w 2101 -p 9912 -h 4645 + run --dev --skip-ra" + restart: "no" +volumes: + ? relaychain-alice + ? relaychain-bob + ? parachain-2106-0 +networks: + litentry-test-network: + driver: bridge diff --git a/bitacross-worker/docker/entrypoint.sh b/bitacross-worker/docker/entrypoint.sh new file mode 100755 index 0000000000..cfbefaf9c4 --- /dev/null +++ b/bitacross-worker/docker/entrypoint.sh @@ -0,0 +1,19 @@ +#!/bin/bash +set -e + +# Check if the first argument is "mrenclave" +if [ "$1" = "mrenclave" ]; then + # If "mrenclave" is provided, execute the corresponding command + $SGX_ENCLAVE_SIGNER dump \ + -enclave /usr/local/bin/enclave.signed.so \ + -dumpfile df.out && \ + /usr/local/bin/extract_identity < df.out && rm df.out | grep -oP ':\s*\K[a-fA-F0-9]+' + +else + # If no specific command is provided, execute the default unnamed command + + # run aesmd in the background + /opt/intel/sgx-aesm-service/aesm/aesm_service + + exec /usr/local/bin/bitacross-worker "${@}" +fi diff --git a/bitacross-worker/docker/fork-inducer.yml b/bitacross-worker/docker/fork-inducer.yml new file mode 100644 index 0000000000..6326b92815 --- /dev/null +++ b/bitacross-worker/docker/fork-inducer.yml @@ -0,0 +1,43 @@ +services: + worker-ping: + image: worker-ping:${VERSION:-dev} + devices: + - "${SGX_PROVISION:-/dev/null}:/dev/sgx/provision" + - "${SGX_ENCLAVE:-/dev/null}:/dev/sgx/enclave" + volumes: + - "${AESMD:-/dev/null}:/var/run/aesmd" + - "${SGX_QCNL:-/dev/null}:/etc/sgx_default_qcnl.conf" + build: + context: . + dockerfile: ping.Dockerfile + depends_on: [ 'litentry-node-${VERSION}', 'bitacross-worker-1-${VERSION}', 'bitacross-worker-2-${VERSION}' ] + networks: + - litentry-test-network + entrypoint: "ping litentry-worker-2" + pumba-network-delay: + image: litentry-fork-producer:${VERSION:-dev} + devices: + - "${SGX_PROVISION:-/dev/null}:/dev/sgx/provision" + - "${SGX_ENCLAVE:-/dev/null}:/dev/sgx/enclave" + volumes: + - "${AESMD:-/dev/null}:/var/run/aesmd" + - "${SGX_QCNL:-/dev/null}:/etc/sgx_default_qcnl.conf" + build: + context: . + dockerfile: fork.Dockerfile + depends_on: + litentry-node-${VERSION}: + condition: service_healthy + litentry-worker-1-${VERSION}: + condition: service_healthy + litentry-worker-2-${VERSION}: + condition: service_healthy + networks: + - litentry-test-network + volumes: + - /var/run/docker.sock:/var/run/docker.sock + entrypoint: + "pumba --interval 3m netem --interface eth0 --duration 30s delay --time 1000 litentry-worker-2" +networks: + litentry-test-network: + driver: bridge \ No newline at end of file diff --git a/bitacross-worker/docker/fork.Dockerfile b/bitacross-worker/docker/fork.Dockerfile new file mode 100644 index 0000000000..3a2df5bb85 --- /dev/null +++ b/bitacross-worker/docker/fork.Dockerfile @@ -0,0 +1,26 @@ +# Copyright 2021 Integritee AG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +### Build Pumba image with dockerize +################################################## +FROM scratch AS fork-simulator-deployed +LABEL maintainer="zoltan@integritee.network" + +COPY --from=gaiaadm/pumba /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt +COPY --from=gaiaadm/pumba /pumba /usr/local/bin/pumba +COPY --from=powerman/dockerize /usr/local/bin/dockerize /usr/local/bin/dockerize + +ENV PATH "$PATH:/usr/local/bin" + +ENTRYPOINT ["/usr/local/bin/dockerize"] \ No newline at end of file diff --git a/bitacross-worker/docker/lit-ii-batch-test.yml b/bitacross-worker/docker/lit-ii-batch-test.yml new file mode 100644 index 0000000000..b11860e3b1 --- /dev/null +++ b/bitacross-worker/docker/lit-ii-batch-test.yml @@ -0,0 +1,24 @@ +services: + lit-ii-batch-test: + image: litentry/bitacross-cli:latest + container_name: litentry-ii-batch-test + volumes: + - ../ts-tests:/ts-tests + - ../client-api:/client-api + - ../cli:/usr/local/worker-cli + build: + context: .. + dockerfile: build.Dockerfile + target: deployed-client + depends_on: + litentry-node: + condition: service_healthy + bitacross-worker-1: + condition: service_healthy + networks: + - litentry-test-network + entrypoint: "bash -c '/usr/local/worker-cli/lit_ts_integration_test.sh test-ii-batch 2>&1' " + restart: "no" +networks: + litentry-test-network: + driver: bridge diff --git a/bitacross-worker/docker/lit-parentchain-nonce.yml b/bitacross-worker/docker/lit-parentchain-nonce.yml new file mode 100644 index 0000000000..44e967776d --- /dev/null +++ b/bitacross-worker/docker/lit-parentchain-nonce.yml @@ -0,0 +1,24 @@ +services: + lit-parentchain-nonce: + image: litentry/bitacross-cli:latest + container_name: litentry-parentchain-nonce + volumes: + - ../cli:/usr/local/worker-cli + build: + context: .. + dockerfile: build.Dockerfile + target: deployed-client + depends_on: + litentry-node: + condition: service_healthy + bitacross-worker-1: + condition: service_healthy + networks: + - litentry-test-network + entrypoint: + "/usr/local/worker-cli/lit_parentchain_nonce.sh -p 9912 -u ws://litentry-node + -V wss://bitacross-worker-1 -A 2011 -C /usr/local/bin/bitacross-cli 2>&1" + restart: "no" +networks: + litentry-test-network: + driver: bridge \ No newline at end of file diff --git a/bitacross-worker/docker/lit-set-heartbeat-timeout.yml b/bitacross-worker/docker/lit-set-heartbeat-timeout.yml new file mode 100644 index 0000000000..b4e271ce4c --- /dev/null +++ b/bitacross-worker/docker/lit-set-heartbeat-timeout.yml @@ -0,0 +1,24 @@ +services: + lit-set-heartbeat-timeout: + image: litentry/bitacross-cli:latest + container_name: litentry-set-heartbeat-timeout + volumes: + - ../cli:/usr/local/worker-cli + build: + context: .. + dockerfile: build.Dockerfile + target: deployed-client + depends_on: + litentry-node: + condition: service_healthy + bitacross-worker-1: + condition: service_healthy + networks: + - litentry-test-network + entrypoint: + "/usr/local/worker-cli/lit_set_heartbeat_timeout.sh -p 9912 -u ws://litentry-node + -V wss://bitacross-worker-1 -A 2011 -W wss://bitacross-worker-2 -B 2012 -C /usr/local/bin/bitacross-cli 2>&1" + restart: "no" +networks: + litentry-test-network: + driver: bridge \ No newline at end of file diff --git a/bitacross-worker/docker/litentry-parachain.build.yml b/bitacross-worker/docker/litentry-parachain.build.yml new file mode 100644 index 0000000000..9a1df4908b --- /dev/null +++ b/bitacross-worker/docker/litentry-parachain.build.yml @@ -0,0 +1,104 @@ +version: "3.7" +services: + relaychain-alice: + image: docker_relaychain-alice:latest + networks: + - litentry-test-network + ports: + - 9946:9944 + - 9936:9933 + - 30336:30333 + volumes: + - relaychain-alice:/data + build: + context: litentry + dockerfile: relaychain.Dockerfile + command: + - --base-path=/data + - --chain=/app/rococo-local.json + - --validator + - --ws-external + - --rpc-external + - --rpc-cors=all + - --name=alice + - --alice + - --rpc-methods=unsafe + - --execution=wasm + environment: + RUST_LOG: parachain::candidate-backing=trace,parachain::candidate-selection=trace,parachain::pvf=trace,parachain::collator-protocol=trace,parachain::provisioner=trace + ulimits: + &a1 + nofile: + soft: 65536 + hard: 65536 + relaychain-bob: + image: docker_relaychain-bob:latest + networks: + - litentry-test-network + ports: + - 9947:9944 + - 9937:9933 + - 30337:30333 + volumes: + - relaychain-bob:/data + build: + context: litentry + dockerfile: relaychain.Dockerfile + command: + - --base-path=/data + - --chain=/app/rococo-local.json + - --validator + - --ws-external + - --rpc-external + - --rpc-cors=all + - --name=bob + - --bob + - --rpc-methods=unsafe + - --execution=wasm + environment: + RUST_LOG: parachain::candidate-backing=trace,parachain::candidate-selection=trace,parachain::pvf=trace,parachain::collator-protocol=trace,parachain::provisioner=trace + ulimits: *a1 + litentry-node: + image: docker_litentry-node:latest + networks: + - litentry-test-network + ports: + # TODO: maybe not use 9912 as port + - 9944:9912 + - 9933:9933 + - 30333:30333 + volumes: + - parachain-2106-0:/data + build: + context: litentry + dockerfile: parachain-2106.Dockerfile + depends_on: ['relaychain-alice', 'relaychain-bob'] + command: + - --base-path=/data + - --chain=/app/rococo-dev-2106.json + - --ws-external + - --rpc-external + - --rpc-cors=all + - --name=parachain-2106-0 + - --ws-port=9912 + - --collator + - --rpc-methods=unsafe + - --force-authoring + - --execution=wasm + - --alice + - --node-key=e998e728d8bf5bff6670c5e2b20455f6de1742b7ca564057680c9781cf037dd1 + - --listen-addr=/ip4/0.0.0.0/tcp/30333 + - -- + - --chain=/app/rococo-local.json + - --execution=wasm + environment: + RUST_LOG: sc_basic_authorship=trace,cumulus-consensus=trace,cumulus-collator=trace,collator_protocol=trace,collation_generation=trace,aura=debug + ulimits: *a1 +volumes: + ? relaychain-alice + ? relaychain-bob + ? parachain-2106-0 +networks: + # to be aligned with other yml files => same network + litentry-test-network: + driver: bridge \ No newline at end of file diff --git a/bitacross-worker/docker/litentry/docker-compose.yml b/bitacross-worker/docker/litentry/docker-compose.yml new file mode 100644 index 0000000000..5d7059c16e --- /dev/null +++ b/bitacross-worker/docker/litentry/docker-compose.yml @@ -0,0 +1,87 @@ +version: "3.7" +services: + relaychain-alice: + ports: + - ${AliceWSPort:-9946}:9944 + - ${AliceRPCPort:-9936}:9933 + - ${AlicePort:-30336}:30333 + volumes: + - relaychain-alice:/data + build: + context: . + dockerfile: relaychain.Dockerfile + command: + - --base-path=/data + - --chain=/app/rococo-local.json + - --validator + - --rpc-external + - --rpc-cors=all + - --name=alice + - --alice + - --rpc-methods=unsafe + - --execution=wasm + environment: + RUST_LOG: parachain::candidate-backing=trace,parachain::candidate-selection=trace,parachain::pvf=trace,parachain::collator-protocol=trace,parachain::provisioner=trace + ulimits: &a1 + nofile: + soft: 65536 + hard: 65536 + relaychain-bob: + ports: + - ${BobWSPort:-9947}:9944 + - ${BobRPCPort:-9937}:9933 + - ${BobPort:-30337}:30333 + volumes: + - relaychain-bob:/data + build: + context: . + dockerfile: relaychain.Dockerfile + command: + - --base-path=/data + - --chain=/app/rococo-local.json + - --validator + - --rpc-external + - --rpc-cors=all + - --name=bob + - --bob + - --rpc-methods=unsafe + - --execution=wasm + environment: + RUST_LOG: parachain::candidate-backing=trace,parachain::candidate-selection=trace,parachain::pvf=trace,parachain::collator-protocol=trace,parachain::provisioner=trace + ulimits: *a1 + parachain-2106-0: + ports: + - ${CollatorWSPort:-9944}:9944 + - ${CollatorRPCPort:-9933}:9933 + - ${CollatorPort:-30333}:30333 + volumes: + - parachain-2106-0:/data + build: + context: . + dockerfile: parachain-2106.Dockerfile + command: + - --base-path=/data + - --chain=/app/rococo-dev-2106.json + - --ws-external + - --rpc-external + - --rpc-cors=all + - --name=parachain-2106-0 + - --collator + - --rpc-methods=unsafe + - --force-authoring + - --execution=wasm + - --state-pruning=archive + - --blocks-pruning=archive + - --alice + - --node-key=9e7aac1fe73c65be5c937fc95fbb9e24cd31f605696a6b4cbc34aff6a7b43968 + - --listen-addr=/ip4/0.0.0.0/tcp/30333 + - -- + - --chain=/app/rococo-local.json + - --execution=wasm + environment: + RUST_LOG: sc_basic_authorship=trace,cumulus-consensus=trace,cumulus-collator=trace,collator_protocol=trace,collation_generation=trace,aura=debug + ulimits: *a1 +volumes: + relaychain-alice: null + relaychain-bob: null + parachain-2106-0: null diff --git a/bitacross-worker/docker/litentry/parachain-2106.Dockerfile b/bitacross-worker/docker/litentry/parachain-2106.Dockerfile new file mode 100644 index 0000000000..eab9c2a4fe --- /dev/null +++ b/bitacross-worker/docker/litentry/parachain-2106.Dockerfile @@ -0,0 +1,2 @@ +FROM litentry/litentry-parachain:latest +COPY . /app \ No newline at end of file diff --git a/bitacross-worker/docker/litentry/relaychain.Dockerfile b/bitacross-worker/docker/litentry/relaychain.Dockerfile new file mode 100644 index 0000000000..704c6daf3a --- /dev/null +++ b/bitacross-worker/docker/litentry/relaychain.Dockerfile @@ -0,0 +1,2 @@ +FROM parity/polkadot:v0.9.42 +COPY . /app diff --git a/bitacross-worker/docker/litentry/rococo-dev-2106.json b/bitacross-worker/docker/litentry/rococo-dev-2106.json new file mode 100644 index 0000000000..3f7995675c --- /dev/null +++ b/bitacross-worker/docker/litentry/rococo-dev-2106.json @@ -0,0 +1,138 @@ +{ + "name": "Litentry-rococo-dev", + "id": "litentry-rococo-dev", + "chainType": "Development", + "bootNodes": [], + "telemetryEndpoints": null, + "protocolId": "litentry-rococo", + "properties": { + "ss58Format": 131, + "tokenDecimals": 12, + "tokenSymbol": "LIT" + }, + "relayChain": "rococo-local", + "paraId": 2106, + "codeSubstitutes": {}, + "genesis": { + "runtime": { + "system": { + "code": "0x52bc537646db8e0528b52ffd00587c8a053e4507031753105809291df0e50a2dbd8dbab06e5e90557b3cc06cafa2aa2f596e8cf0e5d212e561567462b405fa9965fb7751da6eff21e53c0ff4a602b3945e925bbaba6e7aebe55a5855b97ec36e42f696644bb9a59449a6d91958153716de04fd551d87bf9a721cde97f4a612ee4b3a095eef0b7a09aebaafa6eada7d4157798edba4398edb04fd5582ab6ed36b73785f2a7f35e9dc1774eb39f7557dfa0b7ad30bf6d157fe92f7a5baaf1c6f6ac7f197ca5f38fe6a6faa7ee3bea45b2fe1366df7b5f9abc93acb9da2afee6be5d349b8afedbe726e530d9fde94b98dfb9af755e3bea443df1ce7be56aef9aba9bbafbeafe9d059f7d56eefabfaeabe72bac56e9dbbafaaf96bbb2f7b75bac55e5d759ba86bf735bdded7d62d767a5fd97dcd5bbbc52e6f775f7de5e581ed406902fb245f3abb7c92b5875ed43a7b279ffaabc7fb92fed45b0fbd54fe249fe5ec39d953ff2af3a77ecdd9752cbd2fea15720e9d6e6e6575eaf1be9ee04f97ceced343afe8acdbc46f9c20810f2b8e5bd0fb32b7da55f7a5f2cd5ea9ba52bb4d1104538481c4bf2abd955bd0b35bb9d51eef2bfabc4d93882c88c8e25f53e0cbbb710b7abc1bb7dad9611c8c42588628e8582aa6e6f9cd7f3a9fb965453468ce9c2143464aaa5bcc6576811042870e85c8b22cf3ccb324babbbdbd9d3d8a79c5e853fae37d4d911f3d7a74f6e9452e5bb658b1126331f6e68d1b376bd6a8518306cd993364c8484989119344124208d1a50b172e5bb658b1d2b18ebd79e3c6cd9a356ad4a04173e60c1932525262c4249184104274e9c285cb962d56acc0188cd960c3d39313274b96c000c30b2f18c0004444458a78514cb7d8db8b49748b3df3a210dd62875eecd22df6e88413451401064cfc12bf0c19e2e3e3dedec752df2ebd8fc9bcf4e809e9b28fce6f827493ae79c8538c51dd7c9c268d87ce999a876ed9f206bde899071f42785f10424e83e68c9929ca64fdd97d656a9cb812fb57e653e46797bb95494e097bf1d9912243827e5aeff3d0797874747272ba6edb6a95727e53e4120ba3bfaf8e135c60fb12ce37f19b180962ff6a9f22bf2f77abbdefe70feff7d49f39bbcd3ce8d1fb32872eb9a2ec2261360fddc22d7a934bc2627ce69343b2e39be0671e338f1f7af5993b8ab16f276a21ddea3f1b3e3ac758ec7ed279faac5eefc767a8d3fb3199a117ecb95b99671ea4cbfca167f763a95699a087feb19987ce4d84dbc757e4a1cffb319a87f76b67278a2cf5d1d3f9fb750ffdf3670feaa043e73ba48c2eaa797ef6f6f8611496a0c6f2c4d9ba25bb057d3e4bc562cfdd82ce382cfb7cfed12d13a0b33c808e1d3a7345ec9033b221168bddf07cb95b5ffde8b63766678ebb159da8a127bb15fda7fbba8fd1ad4e0ff147b770eb7a88bbf5c9678f9ed343d0a3ebf410fce8cc15496fca8e7fc1eab7d7efbb93a45d7abbbc4ff0e1e56eb13387047adfaf1d3a511335fbc4abe4cf3c600da119cb3d049fddc28d7ba8a1b35b16f7103f3bf710f4af3ebbeca1e8ec167245d16df42cdca2d7ce1c74a2b6bd31e3bcb004986ef14fcf31e48c4efaf4e8912b8a9721ce0b4b24d12d7ee8d3e36e45b7bd458f21ce0b4b24d12d7ee8966edc43fc5f7d762bb7e8b5430e7a73f2ca6e458f5c51ed5674e656e0874ed4444dd4444dd4444dd4cc15b5133551c31ac2205806f240079d9d5543a8e8326fae500d911ac266081743901892c490160c514228cd100d0885211404a13384c0104243c80821371072239403211f084123a402a130423410f2426805425308b14048034237082121d4859014426820f401a11d843c215445088b900f42a6848c11da80d0152169848e10ea41080842b8103243e88d902e84e040480e84b2086911ca4188072155089942c81921658458218483504cc88a1033423a08b942e807212f10020321461042042133426d84d0086d31840721690895112246e807425c203486102d84643124cb900c0871420813428e20d401a11e085942480b214a0cc1228403a11a0851215486101941b2a03fa06604a92288144164106406419a08e2441016040113244b901d828420080882f010844b900d04d1d2b12023040121c84dd00f82741094260807413708e222c88a20334136081a1384445016203800b206c817406800640740ce00d102081840c2004206102980a001b205102e806401e40a2066805801a40a2035005206c8143f64001903c80c7e7c0084073f39009206089b1f2a80b400f900d403100f4059807600d200500680b000e90074052807a02480900002011017202b4055807000ba0128f633f573841f230001013402a013009900a8cb4f1a3f45f821c2cf107edefc08e1270840470019015404100b8056001406080c900a808800fac04f9b1f337e80f0f3839f327ed6fc7cf103c64f183f63fc40f123f55344c4e247cc4f077eb2fcfcf0e3819f2d3f4bfcecf0e3c34f0f3f5a7e78f831f523881f46f891c60f22fc78f3e3083f86f0a3083f47fc68e007891f237e5af093c48f123fccfc50e2470a7e88f9c1c48f257e9ce0870a7e0cf1e3cb0f227e78f921043c030a017af1c3871fb11f39fcb8e1042f4ee8c109629cd0c40963823011c40527c4e0043227441144cc09506c6ab82e72248143033d46f081c40d1ce0d8e107063d45e0c10437031c3aacdaf4686295825ba60b73a38b550e5b9a1e3282fc90e3881d53ac2adb0e70f4d0730637c59603136a90a30537b8f010dc507343073e8e983cacd8683dc831020e8bee051d0c723c714308378260c3f4402268054161585598400416153d623bacd85185094530210d138c10c4811b6104e940100e006008004813c403386eb08a81093ed8a10208041e39645b340b7a055b17ab3358587494d8bcc8c004d9d2034bcb052730e1679c200647143c6778b2c031c6cd7021ac8e30a18c1512269c8143ca87c02201ab4b0f12f4c8400f1f7af4d063043d3ad003053d84e811448f12f430418f13f4e8d263033d7ee891a507084c60a2c7077a68a007971e40f4e0408f10f4d062821326b8c084264c10d383871e5b7aecd0c3033d44c0e3081e48f030c2d358156135d56c5a8c0ea3c1e835fd45efa0bd6835ad83ce4177d1691a077d83e6a2d1f416ad4567d167da068dc5b56235c68f0e80f4c03be06387a00eec30b3830a138c30a1881d48f0088387183cc0e0c186c71a1e3de0c1831d36d8716607163bb2d871c50e2e76a0d9b1821d4cec10b3c3053ba2d891047cb3638821620861b3e30b8f2d38d0b8117678f1aa04e5a0670d4d226eb971c6a522c70a70e0e04160656015c60932e0c6f0b0e11123c70c72c8a0470b4f173c697870c073031e2ebc1d3c0df07821a4062c2b78bef8398367075c0db2333c28d0daf084e0060f70f0b042e3870b1c3900f162670c1c59785e6002105853e090c2841ff850e29ed94ee01b3041091d5a5c29b62e5d11565978b6e840b1238cbfd90186070b13c630a18d09649880060e19b0622b216420f8916225062b87150f56445805619506ab079606583eb0acacdeb0b4b076581d21084d1018d28b24421a218f606501d266070b74ba98e066f5831b39b8916645c68d1bac8cb071f1d303ef071e207496e081c1f6c58d3539c2ac8670d9781ff044307fc8b4e89912f2e6061a377c20648b1e1e0871316dc0999924e82e2c1d84d8e0061baf032b205c1e4c20fc071e2e38aaf40441c89a36c1ca8c959b480321489cd0438f226e7c214402aa84c7656ec1f1c48d363d6c846e2034041e1004f98007026f0beb8a10334ee82294c50d2f76b4e1aa10c2e246193958b0d3c6a9886184b6482e4376105204ce0a213bb801841b3db841067745c5a2a70cd772030cd9831702cf03377670c38d10318488e8107840cc11e07881902386f4e055080143c80a1c2f3829c0a1020705385ffc08f4890e0c79841e1f6459e0c880176107193dc0f48091034ce744f784c7014e2a870a56604417dc40b3e3073d58d083881e2ad851464f1837b4b8b1458f157051781bb891458e2f3dc258303d86c8314464c2aa20071133cb8d33ee86070d0e28582570344c3063e5825512ab25564aacaa5831b16ac14accea898c8b6c082133103a83c30a10317a1c914309160f37cc085a230408b2063f5ef48851af8835e0a09858e0e0c289c063031e2d78b6e04cb0a3080e055c0ab82e267cc149d13306a781d8044703d60d9c0c566b563e302108ab1e641a30414d86e5c61859067ea6c011ebb10407031c583832eec3aa0caecc7645cf0f565fdc10a387113d3da84bf848011703160e386e10cac08d1ffcd4408a00c7951e3fe8d1c66e61b3b057582b2c1178b4408680a3e287063f6a2a9afa82da447da24ad52c2a0c2a14754c25137fa851686c38363a70d091438f1b6e07ee072e0b4f06722cc1a3816e0ae70a4eecaae0b6e082e921828e2a3a6ee811420f10703280e3011c0d9cb0c3092038210bce07704480c3c5843326e4c0842cfc06c7e238f0149103091e237cfce063081f1ec8b1450e3139d07860bc25bc305707578caba6e7083a623d43e888e88ae854b04d713870317fc2a5f017ec58916dd9317365d06346cf9b1e34b821acac7044e021058f333c68b0a32647113b5ee8a4d109634b621ba383031d3174bad85ab041b129d1d34687959e34b62d5b09b61f7070b92eb831b84d74657444e87eb06960e3c0b6436745a7456766e708398cd899e27a9009c1f940a78c0e1a1d297848a023840e181d14fc9ca94ad416d02a6a1195057408d5088a05bd829aa91fa823a821a8602810ea11940c1a05254357404b40b7d01fa807680ef4065a25eb41e6838c8d1037999490263225b228322832277ef490a100880fb21db22c01a05682da4c23cc3333077307f38c19c624638231dbcc32a617d38cc9c5cc62f6606a317d30d1983f9862cc34738ca966ba9937986b269a0984c96676317930bf985b4c1c4c1dfce0616a6066405af133468221bb9069e41a69464621a19063a40ca4147206b28c9c42d2402e2195902d904900b1810c420e21bf4821e40a2412328ce4800481f4416e204323b5c80ec82c92879826f2209a8938883b88398863441dc42ea218118cc8266611bd8041885f4435710b084484412c13c704551163106510a5e20c6810918a38c50f0dfcc012c54424e21234055189f64147114dd02f8827a04dc41da810314bf3207a80be205a895522968843cca161009588b196010a439a06310411043d03b84497a12da028e8277acc8f2c415d349826a281e81334085a043f32d041fcd8a151d0256821e011601a9008d008300b7806da0016016201af80328053b00530086806440282018f80646014f005d009d8043c012c01ec0245004300498044c392d237c39318a030253969224305982ca180042600c3806e607040035660c00b0b50800b0868818524478d031c821122290cc127341f58f80c6d24a1c5188549d20c4848b6a313a6242424158f22184a0c4c4f909a2041898109c9d21294023c35495a5a8252801f3c5830c3930c4c494b2be0a4a41890a03c213dcd20c393a41a7cf008c3afa5274c9e929c202525c5d08307188612839426a42751fe892989060b3071c179a880098909d293289fd484090a029e98a44069d2e47b7810c1afa4274f4f9ca0ccf02485890d1e43301394274f4c9ca438417a82b2f4427a12e59938497912787cf17878e197059294905e48494ea034497282f4b240521226284f5eafa405ece09102aee14994774a527282e200251e0f143052929424290978c149920c323079e1070f21f8a5d42469862641f0eb8929c9296906a627cee3044c4f62d8e161026ef2e4c5f4c4e9c98624240b2c4589c204c929c9c9d213292ea52650965c3c3cba300d484c9e983861f294d4020e8f125ce0c91293274f4f989e90c08304529a24d9905483c708d8094a01b61e2538e9898993274b4ca6acaa0af8a5d404ca52058408393d35f12a119c5387600b2429213125213d25bd906a98010a13d22b89095214a3231e185d408ac2a4891021264f90a2181d7115085e7ac22406a427a7a4d78b0912125745c0484c4c9e38614a424a5a7a7a7ab2b4a37a80a902b66ee125293470809d386152a36e604811a10b3cbd9e3091507dc8a93db00c494c3c6461214816a800d294274e6ad41db802525e4834242d25210d29221485ab5133c04e9c307945313a2aa16261a7195e48b5eac02485a75ee1a7274b515e4828d400c509d3931a72d41c58881092902028203d35495a4ab251ad2ccd50a502525ef5064e6ac2040509a7c672e814333199e109e9f54a5a62d1233053d294242370056878b284d4d13478898994a6244b8bc0509c922e8094e4b4a244e028494e484e4d2f9dfa03273561b2140589e90992059c92688022c31313141a982ab043879043df70141aa2181da9a81038089cf4c4c449142936281afcf484e909120a4142412cb00425ca193c64480a921392132834204d617a82244312131253052a0eec040a0d484e9c30415a80ab05242c70740c76e284c992141a909abc7cc0af1ab4074932f4a03c60284f6c588624261c2a063f3d3d212d49a181041a06274d79f2c4448624a6d713a4a418742818fce4943485e90952520c6b929e984c79e21405a9c993a50a48890244bf6027494a2f263420357982e4c464890900e80e38a9891427494e484d5e39d48ba725293438315962d2e4d5436fc049343c7972623205e995f464810ad000c52906241b90a2181deda0673889e9490c3130412281da8093962a20058a131c8a053b71c2e40aa7a697197e62824203d292141a386a0527bd985400c906ad8297a4d080f4c4f4044a14a421148444595119f053d28bc6802d10a5090d493420b1b0800520a0c805252b86494b1560f2c4242506a4a726494e4f9c303d4142c2d1009c2fb4cd9a3362ce3cc32c4bc5620f61d2cbb431b4316014482591a9634e223a74e89873ced994c62863730d4a29a5109031e2e0a64cbb7b366ddadd92768c9199635366ca94366b507236a68de6a1b93d802bd318e594d15aca54464b63431882581bad0deed84d993b4a9e1542c896ca8e55b28d4969ad95994acaea4869c75aa5acb5326dca916354d5aa499d5a2d4bcaa6dd4cbb086577263bd362a459edccc618553636654a99e31065664d8b51cb24a47452382765967252ca5b6f316a5a6cad5bd3ba1b328490ce0ae190e8799e37b5a8c509e1a4904e4a994e66d95d29953d2c6b8b29a5519395630fc7d833d29e1da5569935baeaa831cbb6a17100689cee6e71b703203733502b76039a3245817d74773ebae3d87577dceca37d745d77ef745dec60d7cad311a8290fa5b1070f4f07b4d3a3e389103684b01b521825845c9b6bb5927543cada32ceee1aa54ed348bbb94ac9b556ad366dda911976377338b45b3d3dabd8dddcb065c4e19899656400939031c3ac9933fe819d71c63f9c317396c1ceb8994b602e812309cc2434f30f84902384cdcdb035be415f60a6515b00670ae8c1f194b56353cadd3bb03bd688353a46d9355068c831b7ec986394b1ca39a5bcf75e1d9dd8daa431d6e88e71520a99524a690d1376708db19b736acf6e21b2b96db7ec1d5c7747ae4da916234338594ed9554a9ecc3ce34a93526a1a73ad52b25892c5d2b4186bd5345665455963a59436e3e8285946ca94b904c41a2c9bd2489bba4029c71f38384a7afc8831c61fcc9123c7dd10c6a8c5dab2e39c31d65a2b646ed8cd08e8d8cc8a3a5c0bb1b204c2196dce5431daa051b3d1dd556ba14a6976a39987c4e698258ee6703ae270370e8e85c825e138aecac8314a5637eb00d132737353243272c76e4a01402900b8352963cb4969ec1825a5ddcd9167434a3b76e45a2184915ba19bbb699750239552ceee49257394514a66ae3bba46c7aed1354cd8b1234a137698c0b58c12f24ecb8e313237c481a3d61a3520acb5d6187b87ab1c73c71aa34ad513d927468a838383c3e1c458bbb626355942e4c83146cdc691acb2e2a810767794ddb19b76536ee60819d2d92a66ee48bb3bda8835cec81ce39c2d6365293b56aae5c8183b464be9b4b2d638279d93c6383b76741a73727258b26c8e30b68c578bb1e39c94bb5946664a99d2d8b23bca8e9152cab5d62aa38cb2bbe7a494323777addcddb165b36ca6cc2c5b870ec93176942d5bcaee6696b15bc696dc31f64823ad638c453724ede689b152aeb2a38c31468e4c65e4ca4d999969339592327777777377f4ba3b364b2a9b29a5dc9472c7964d69edd832ca8edd926bad4c210500cf9e323253eeeeee5a9956ad8532eeee1b2ca78c94ca49a5843046dadcb24a96ad52d3a95996c558bb69949aec8edc916f307364dacc94d2c9dc33c6ee8e513237addcb125773333c7d82da90128a534a7368570d202b83e2787a8ce6983523a2915a24290201a14a70d392ba591d54d23a5274c4a5904a851c61aa99c3152a6cd9429a534fa34776c0a296d8f314629638d14faf8b48c9aac7293348b526a324ad99169ecce5a4e1a9b328431726c1a650fa1628815b1046e0b3841a12189862c694ad212920d4c68d8b1c3416480b2842403d313196480b284436869e98952d0007a1c69a5d0e2f1c3a30790138c0495e064e9c90c4d909e96a4308921c9890fb721c909d31324a6274c666812430c502ea481394892530c484e509e983481b2b4c48447004e929c929c3841411a424148d213a7a7137a94f0c271020b8102c5298752132615585a82e274421126494e393c4909e9c98624261dfe9424038e1cafa7d7131b9278b2a7264c5e4c4c9c9e909e9ed0400394160f16f2248624a7289749d252939d123808535294284c90926460e204e5e9c53364a8c70628353ce95062d2a44992d2100a423c87902048429294982c55004906a62733bc98cc80f46443924f614a8ace416878f2c424c5e91689e1494a0f093624cd80f4c4f4c4290a5293d7131a78b22727264faf1e42786c1c24e98989531253920c4e007092f47a253945a1014a13222b16e29434054a93242724262f274d929082280da120244a93a4d78f6a86264f4c2a8034c3eb09d393185a53989262003808121394272fa7a429481688e18953d214240104410105214e9290a03c45b1805313a4271b92784c614a8a3f2b203a4645492a6b9484d12c4a15151515b925300883aca8a8a8a8d84ba2202c2a2aca251c1545e3128eb251112a2a0a16392a0a962d898a6a5854146c4645c1a828986a09c3a2a260148c8a8a8a8a82c5b80406a320ac2e6198b684a3a27a0947410a8b8a82c1e6128e82f51286c1e892a8a8a82818e4250ccb6073090cc260bd8479090cc2607209c360b0b88461b05e028330b88461704904a6112033431a5e4c3833d3bc882434b7bdcde99a5bb6bd5587dec741d7bc5a449a38db1928c2e68aa8470e49116aa250fa72ca5b19c88a16fb190bb47ce6d4212b51cf1c7247ed1672d077a04baf6ea165ce881948e54872c060c05fbbe6d0fbda25e4e0356aa7d4a56b1e996fb74ddd887ae6cc25a19e395d419bdfda930c145d7a734ae895624199ef9b414ec9f6f3560692976385f108cb6c24aa81dc11a301466f516e91336237d38b97ce9c11a3f1f236c1291ec897dc119bb1a67f72470c46cce46af5c1b850ee88cbe0ae154aae35561f2c044c231056b291b80233df1ee343679754a2ccdec232ac6459571fac876f8253fd913b622fb8231683be95dbe48ed88cb965dc117f613fe38e188c8c33e220a89e7247fc03ba55ee88dd685fb923fee29be094c61d719bfa1a77c4604c954aa592d9ea8369516d963be21d1c3118bfd94d15571f6ccb4b6ffec61d311a2f5de38cd88b97d77291e33839358e638ee32097715cdb70f2e839f9370341b72cc94664125843d9011bdd6ad3a985aed43e61cfe9d12c83aa2c7315f4bef8ed2acfa94985a7ece1e704b30c76069b3a734775b6a7dd6f7aa59ed2f4b6b7461fd1897af36d7a4cc33b48b46fd7be9d3b804fd9e974b5566f39a534a848509665cf5c5146147d445f21fa88319b733e73459b737701ecda6e11ff6752ca186377bf949c911295f4e24b331a1561d28499228c1360c8d02a0519f8f5c3d80ea1337700ff209a602d6aea23567304146133734d32162bc13fd52437bede157c2e7cf5e951b7d2fba82b4dcfe44f9756d64a6ba573523abd7a4eb456e97456e9d4fb2ef34ffb9c1e7409a3b03f1095a277676e2357d4d456aa893de58c80624f9be00fe18ccfb8ea969b46b8b3fabeaf774a7d1a392430f6d42d4321abaf86a7d5edf4beea4a9947f9994fef93464c26167b7a9d9ab84d2cf64f357eba53930acf0ca4393d6d3f5d73e6944479fac5cf5cf39c9a54f866a0cc9fb2affef5674e3da7ea4fd94f672e09d25327eae935ed6852c1c28d7a4d70ea83f432ff64d389a2cfafbd3d5af125cdff7896fac282b70cc5742ce585cc03e0592a054fbc65b1a6a3f28fc73f47e5e564d42757d4753353a93caa793c3272453a3a1fbd464a33afce2cf3364e0965428b2fb19fde5c510d1dbff556b7a2b717c4bd60432c168bc56e704141c56245a28fe8904bc70f46093aff17f49947f7e921aedd6a8f9e79d093d736e48e2b796b4f2a2cf42e504c1381265a9162a60ad8380483e5fbdb79a0c79eecd6106dbef52cf5658cb74cb3296343ba6206629730b09f947ee89f94fe25db826757829786cffbd897a2966f8fde520d1ab0e2fb7ef099a296576a87cf1c02582a26858345f8291da07e8d314a2865c757ffa87f137a8cf27ef0a57b4a9a92eac6cc6732462dba8c9967d56ba597068fdc6b85e89ff46fa9c9787977a07f4a4b514b539cfa15f8e3f5d27d613388980baa3d4cd301f8a32f805ded449dd110b5bcbc52b80cc613c8283df8b11d426861df6f296af9af5dca8e8f1c20f351cb4324fd83e9d2e3b7d353ca7c3ae492543756bc0c81968f1b78d8dbdea6f73519afa4e5e1fd600f9564d7035d94969a8c8797a9c978e9f2eeacc05f45c3888f5769a9a261c4f7a5a1a261c437191336082c942dbda3bc4ed29f6419aff44d892f6fbb644d4dc1fa86879edd0ff60f3e5ea5cca343ae85ec2a4d892fbdcbf87895daef0e92f8ed7d9be84b8ff76b82531f7d89bed3906f823f45de7ae589ba6111c621a6e7f4c43d74a02dfe8bf27d9d98813e96ea8096df5981bfa8e59b6b61c7d4d47f5d2cf650a29687b1852ee31b03967d3ed8e533b75f8fa4cffb6d3fdd4ed830d39c3dab9b64b7b633cea8bec61b8ee62b876edbfba2d333fcd5a3b783447e75f9d5a943ee00d63ff8540b988fae795763933da43903a125cb574fe3a3bbf9eab6046b636befd33c25cda35b4df376abda2067a479f4a80d0942a779bbecd6746d7a74bb6dac8db3b15536c2cfaee33ad26e31c6ee868a52b956ae6aca19c1afbef2da2dce56d94854fdfd5cf81c9b6c2261a2afb8a2179595b38b01ec5ab96d6f73e6a2a714bdbacd2161831ce7cc25b14ed4f12d092cb7acce57176ae5dd4ad5dd1a7d64de451f997ff53367a99a72d7287a75a2087fe5b16bf3beead4edb4389b92fecab0e3ea63c0f76506a25dbd3fddca5add6afd78bbda34affacaa35c51dfa68e3a7ced0eb94141273cf5606fe1563d1f4f3ded6d6fd56bbd8d5bf57abc955bf54c783bb7ea01e06db655cfe7a917dfd2ad7a3c9e56ef3ef5e05b6dab9ef756b555cfdfdaad7a3bde6e5bf574bce5b6eaf5bc5d6dd5e379cbdaaab7f3b6dbaa97e36d8fadb30c08e8841f55b42ded6906f83100111706ca21003f82fc7803d1f2a339742ba4813823cd6bd52ee4c240991335bcd245ef9f2d7a9ab7f7693ccd3f6da33cf55075e856a8ab3f45b1277047f0ed8f0d72464c86578fdf0a013510ec561fac04efe49ae7e40f190868a30eddfe048033a20eb7548f9ea685fe047145f51639d2adcca9742aa7fe15f92ccc18af7a6d8c8f0e6dd0d69e0bde0bddca3ccaccd090d0102c1dbf046040a3c167c8058806a25bac81ce49b7325fd2ad4c0d9121518aa0b0b5a7b9e654d908dcc240291411400a47a2441f99db30002b52dc267e8c470460046e30acdc1e1940c358f49139c4127d644ed9b860ecb3cfb28f3e808d9b889530d5afb82b4c3462646bafc22d3d94c2d65e75c81db5c32dddd2e265e596005bb52a6c958d68db0b5df4a016eda3f7c7225bf4e0966e65de1ee4d2adcc2357a4412c1dfcea9a0036cdfbe06b6e63751f5a75a2662268ce5c51bd4bddca66e856e66c3e73cbb023cb95e656001b97001d5470ad2e51f491f90ad147e643d0e838faf8586a05b17f8aafb90e2ab856beba904bf491654e3925aad7ae92ea3a69f0033f3090ccab0b802ba2176ae956e69a07b73050e6f0864e7bf8d53ff8ed1fd4f299dbea51583dfe21ee280096c896c256d94816e5cc669665144208adddb8152b67d504a77e27497ccd6dfc07f5dab500b89eefd0d1c3b3930387ce8d1248c8b1e15383070072569081a66b1e8eaf9ece53afdff668c8357acc1533d0f4c89c91f4e9d955825d6a5f1f2cfbc0296d94ac448a0b6ef8ef025dc46606648c9ac3d7fca3df6ee9f472b668a19c51061d6ac99a1fe2d0494e23b9a3003c3350743bb7f6d862692c59c36e9bd39d79393ad187ec49b9a2e9d1db9939fd75532787040622bdbd1b0c24bb6e498f40c7523e4cf19a4fffeacbf890336237efe49feadbb53166a05a7dcd63e59fd698422d46a2cf97543e3d3a750b37cd539a1e9de7dde98f4e5b68cde3cf18a83d9b31bacaa3b792fe783fd8ab8cd8f22a87af729efcd34ed4cd21e957f9f4e44fee08e82503b5ca893ad619e3d5aa47a95c50d4a3542eabf294541e5daaee8efce8ad7a2dd6fbb9f0cd40edf47e2e3c6420ad9943223f3afbc82808a3bdf2e2ccfc3287b105b98304fa0692789e67292d4ebc7c2b37e68eb2fbc1cf5cbacdbe3a67deaeaa6ee906399a51f662dddacd55174ae59b4adb2e471fd36bf43155aef2e956abf7cb1c4a8e5ea34ce5b14b6e2a8f5dd2e755ea66c7272cfb7cdce6a55bc946e612066a98a5eb3bef9248d4304bd76a3e080497b9493602a343e7b2d4ad251fef0c70872e3acfe9f14ace28cb820562812c0118b68a66c2580f65d5ce2d7247197499795eac4fcf89bd33441fb273baf6e8195714bdbd9d0875e88c3c4fb7a4eb38517faaeff4d4fdf4ccdb3f9d970eb9a3fa4fba19a20fe9d069e6253110e9d39381819abafefee86ea3a679bc3e9a53fffca5db4e765eac75eb41b1ccb8acefbc20c4058500e65e10e2b2d6835a8de1b26e9b61afbea857d2dc52afbad53c7ecbdc11eca3dbb8699ed2b4d9063995339724fae49074e4879c97cdede68579c17f2d80737ba1ac73be0076d93b9d3905e8a0828bbbade8437a50f4219da887a0d1b14be5d241059775eb5feba56f1ebb984ba2ddcf852f7ae69cea1a45ebb14bf3f8ab57a45b527e8cdef748f4e95f919744ed396120c91d65ceddeaccfbe077d1acd24527da69971f3f5e03c0baf68fa55e529f818d44a7d02174ea79b11e3df867be3d83cc3f44bd0132bf651efcf63ed8370c94324fd2df9e793b48fadbfbdbad0715a57259875c122d5ec83fb3bd2a70ca152673e694a8b2fbb9f0cc40f3aed02de9d18bffccf565a15b52b291cc8da65396f2c189a76ee306bbb091e9d02177449f426fef834f6df420c70275e690743cfa7966207a9714f575d22de9449d7971de191848ba952ede17ba25bdaf0bdd92feb19a970eeba2b7746ef3cc232ac268b3a62e140c09ecc246da9be0d4b74723faf1c22e0c84a50a4fbd715d892ee83d265684162bb12b2ee620401b4ac0d6e74804bad86b24023d01d06bf4a100e8e2e8839da819688b962d5ab260c98205c660ec05abb4b4d928edb63923e947f0a3c0971ed3f6f14608b7b0db90860d5136eb8282c1c03ec31833ac79f6256b96a4797618d2c070e6d95d38e3c214cfbec2142b2880c93c3b1191028e3c7b912345863c7bd090a09f676ffdb47c9edd7d5c87470702cc2d80db6d7bf53bd68e11fcfa5d7b5ea033d700d6d4d4d4940baa42276a081d60b9873e28fd06df0edd42ee0030183ce41fc81d2559c14e679f8fcd783da081366229a2e5db7d7e8acc1bb348911efa7456e8a1af3b42d40310df6e001674a24f13f1582c1673b5ff3411198bc562585ced43d848fc58df253cebe05bf29333e2343fdd665be48abec88d2631b72a956d5a0f535899c139b9e79c91c76a3a8b8d402861125dd4f1347e7af05b3dc4523cbcf9f69f1e6236f3cc0336612603cb90888ea57860f3f3598a072dcf35dc40e9442d6fbd510a2bc20774cc1d00f652de7a194203882900929b353132b737c702ec95f836453dfbd7cedd1359dc3c4b6539f35f7de93f9ea5b27c79990d71c39eec16732cc05e66b0cf6e6d6fc819d3ade48a66cc7c27bb46f033cf6e7de83ef22a753fd804283584de103710b291e507748cf3c21260229433f31eda316a8f1e95a24bcf32af3dd49f49597e40675912deea96a5a48bdede14f5922b60b959b5875cc228a3042cf750b36779009dfced2d8b7ba8a56b79e839c16f6f8f9e6c96ca02c4b71739e944cd523c5879081f7a7345707be68ce46d0f26218c81659f2cb1ffbadf3ea887be23de435feb480f498ffed343f575daf87cdc6aeb23912efa60a576197d4489c3dddafcab10ba61174bed30c5b343cea85d3a51b7374bb1b3cf0763df0cc5e8588a0b370f63cf6e9b8807cd744ad1f93f18fbef59ea06561e3e74c82981373cdf0fc6a4b337453ebbf492b09e3d7a1fec3fe93b48542f6f13ebd9798b0ffa8fa7fe8bdefcec71b73c8846071d3e370aec906bf2a6eee3d5e91674186b2a2cf7d057db8b2dbfe9d917bd3a6436c22f37ee2169a517dd3264b6b2bd1da3e8177247b2ddca29e5a45e3dd8db6c9bdece74f8fdd5db99d748f5908132877dd43377c43d75e68ce0c7ab243d3a51538f1928bb3b48a447ffa4b7f34f0fbead9b8a2b6a290da079e8b287de56ee887b66a0af5d7af4326fef8bfae856839a06e5ea9bf24d70eaa7db3652fdbccc405f76dbe39f1e339074c9c52b6d47dbabe8904b22e36d8fbb056114ca20ae94b95244f41863bc12fb18638c54d2e44026072cde43ad1efaa44e0f7dee53ad9c81defff17cfc6ffb7618b34c80aeddb2a2db6f83446af461adfbecf6cc6d67ed5ffd78a7f7c35cd1a7f33a9108471fd1a3c76723f51255210203f17f9c02bd4455de3010ceeee675f1db93f42bb5d7ae87fa7ed0338fd2bfcca7dbcc9bded6adc8ffd5166a0ff5f4e85de6f1dbe68a667be45880fdf4e033d7166ef2a75bd1a1e7d3adc82f3d4e5eef56846574d13fff88c6b28f6518838ea5aa807996aa62e5bfd6b70b3d4be160e6992beab6aedb7aa887a6b3dbe9f1470fbee50174f0b3b84d2f73c815c5cc996301f699851c92e9d9fda64fb7cd15c96e49672e09eb277c1bb7cc9b0e39eed697f3d0ad652ebb1fec338fde57a7c7e87d3273a2b6d1fb0cc0d1fbd9f0d463f4e97ddc2d1ba2ccb0e4a37fd1bfe8df74ea35c5a9a9a9373f3d7adf9197d2a7c7cf9c12fa31f39ae8cffbc18fb7094e4d4d4dfd07fbe8d2abdd82db430f7ae601cba0d4c1f20f08838ea57090aa3a589ea57010f3ec3c39cfce3e7c00cb2a74d0d959ebbe317a7b73451d21079d3979a59d9b8d5b7bf09b830e39f885e5ef76d87d611022b1d0a10793e8a46e68f39ffcf60abd568e44b87d74ffd56f973dc40ea19323547424eae8c96eb51fe9beeebbbba3774708bd3ebc3b49a04b87f17ef03b425803cbcf3e5ff7ed36c790333ae8dff62d800e7a84ae142f515be8f54bfd948c8bcf6d6cc409aaf929dbcaf6063df95b9b6fa23fa506b7ada6642c36e20463dfa4c2436f670e898cc51e22e9625b0ff1371b81fe4597ddfae047af48179d9db9239e7acfa7af52d73ab0dcf6630849b02c754311cf747a1f8cfd8440e870d19cde1a74a01615cce2af0c5aa130b66d9cb3e5fbbea46bfeb2b7069d575dedd6a0f3f2e6402cfea2b7069da757d6a093c61b9a8db1460de7b851a96e4ed78693950dcdb2ac861c2f6ba8c19366e5d175d0a89c669d99cd5fd93645e62fea759364347f715e5f2b99790ddd739c7346a5f2d766bb9c57996f7fd5d03dbd2fe9d45f5a96f1bc74cb621e9292eb94f755bbe321b9a9ea7dadfc093e747a5fd69fe06fd49fe0576fc8dcf997a3bd3896f7a7f3eccc43aff68ec5dd17e770755f51aa5bd0b9fb8a64ba055d762bbe62996e41afaf38c5f68a66ba053dbbaf7826a75f114db7a0f77dc534dd82fef13c7b906eb5f229f2572a954f91af62b17c8a7c96a6f914f95ae753e477383894fa14f9d4a3943e45bef4e8d3899aa787e41129fd9539478b7c67d45fd569965d9d6e45ed47d3fc457d53f96499bf542bfff697f4d7ca55aafb5271b722ce107f555fa95437a75bb10bfaaef5beaaabfc25399e6e457f69dbd6ade8aa5a6fd7adc86a7ddf6f3af497530d394fbd86ede97db5537f65525e7a9d6ad0f1ed4d7108691c01065f4309d1a307e9a213c5e9f1f3f4d08b473a8e479de99bc71cead623b73fc9ae875e5de635bbafac6afe247fd3ee4b7315cbdbb5cde77d4daf99e6d567e6d3a354ad3aa7f745551eb76e417f597f928fd3b156b7e396756ebbd2e6a8b47a2bd5f976795fd2b3292f73ebe3f9f6e82c98c3080ba1bf2094c0cf589be73730051d4bdd107bdbdc11fde8d0fb280c59f6c29c2e48c9c2cf1857f8793ff6a77e28a53377d41f9da8a5f7b57c49698097137ad3993b821fef4e127ef3d1e35582ce6f9e9fa8a7f7c1874d5057aadc20f54fd9477f35c17488c28b36ff243ffa2b7a930c670c218d7fe26e7d4fdda493e54a95b7a19dbb255d4225fc86b9242c848ff78bf2b008b31dd8ad875e2438ac0ea7bf9a6eb8e611de17f597f5570e6fe25ccefb6ad271e838feaafecabca97d55efab693acbabd3fb6aa2be79bcafa6cea5d7f01d9cfbaaf765efabc97af51c6fb281e32b7fa93cdea6e825f84e769b6a38cb9b32c7715facfbd21cfaeabee47d69be79f55713cbab93b0f212ee0b7abdaf1202936b017adfc9b5d02e3b59e6277b4aedd2334e89f4f6cc8b9f050dfeeb7e7e3c3faf529c5e7b28faf44d07dee80c53e87ed9437005f85406894a58ee21e90cc49fc9f2edd106697cfb0755ae79732c48e93ee855d1552a2fc8f6c1575279dc7cdbee173d3a515425698f5906812bd0559dca15e8ca32a7923985a13a950a4375ea442d610cc1181fdd42659c0dd27cf4e8c47bcf525880791b80799f67291b60c1e2cd749567380e2f8e673ebd28956b3ab311ead98d52b932eb96e50216cde7f4a04bf3c234a9c08245742abf423d8cf598ca355d3acbf9a30da6f098546f7df390a8de76e58ca0d7d8fcf39496ac6fce39dd3c26eb5c0def833dcee62c967755ea8582b9542c6c97a5b4f9caaf50872e6bbd1dcb712bce2dc7714ed43b76e5ed588ee3b8eb050b85d73ad1cf0b954da75a76a3e6adc2ca1c2aaa7a76b1b82b732ceed26e549dd3a7d3cc378f21102cda4edfb132aa427536b0d48ef5e957dc351dfa8e9db02e1fb9a2e8703a732ecc1a9575adc2321cd3b1d40bbefc57596a0b36b5bdfed72d49b7b28760479647c1e0ea9c73e61ac079548e8e6f4e85731d87dc0b3abe5d281cce39733070aec3795b561d062828178e77cedc0bedea1c025472f8e6543acfe1907b21876f9739183acf71451a1f1d7ad6420e022bdfe12c8fcaca596ec3835ab90def3c129ca87778502cafe19b07b5f24d05bff36c38e7502cd7c1e1245ca8ceb91a1e152828ce3bdff176e97854a0a03676b13ca81e87f21cca5d87dbf0a8784ec59d8a0e878aa2c2e3359c0487d271a8121c2ac73bc8bdb0721b0e39183ac771a1602e96e7f0a0a08b75a10781d5741b974ae738ce66b8f860e68b193166ca98416386cd0bb87ccfafa0932fcd6079bee2a15ff1c5cc9b2bc43c8e67a92bccbc9d1e930a89ea2716407c748845968f9e5d31868d8d3908e0701cdf3cce571e151cbe721b1c046ce05ca89593e0cc466c6c1904a036dfe1502bafe1ccbd60c3b90b85c3b795c7ae1a1e95cd6df80e8f8a0dc7e1247854a036c7e11a0e07c3e6362e15ce6d380ef7020e5fb98e07c5b98d1b45e586ef70ce330f02387c75a96ccef2e69444d7ae650e86ed56b1e19bb36e94ca85e39c17a5727546e6fd82de0b96956f374ae5dafc83de9e398ec7f2cee3a02bf3769244a7de710de8aeac3c4c769596a66b9e398e331bb1f70b7acd55f783de1e9922ac62c3712e147451d9b950391c6ac7a1709ce53bbc7ad437af8a0ddfe1373c281dbfe1760056a4e40ec2c43e73fad95b98f1d0e5b90a2d190f5d3ef3f9f26d6fd44ba27da6facc550f9fb2795e43d97ce6f1fb9943c26b3ea3ae7dfde69000d9028ad8670e392403b022f559155a56bee3424117947777740ee53b7474378ac739efb9513c585470e5007375de39098ec5c31d0f8bbb366779512c27c173dca8cd49c0b9512c6739e7363c28980bc7bdb2ba619a5478a58f21908fa56260e6a14bc7c3e25055a0b0b82b6a73ce6df80d0faa841bb56d4e824345d570122e1677ad3ce76271978d1b55e36271d776afe0dc2a2ab8707c73ee5661c5a0ccc3fb24f98a879786ae8affa697227e89cdbcc3ba7c6f9baf5c3a47220d5839cbbb48a40acb57170bce0d9339cc25b3e94507155c5dbb562ea3ba0a0563b1ce06968ac5eecef4955f71d7ca33ffa27c7677e6caa17f4b2211d6a5c2f9e6d22b4c015e1d0804366007129c8fdc0bdbb6ba1de7c25602ac360e0f96610f7cbecccc4f9518e65a88ae8ac1978faee2f2d1a1dca2ab5c722cd02ba5fb4fc662ffd43d75ab6ace08063db3912041dece0ff6b0850fbe127495abaaaa1d7e2a6f8f763250bc932bb26e33c8bd6a82539073cd396f33136ab3ced99b47ce36eb4195e3f0e82a301d4b9179f3aa1d2e06583e5a6ddb7cd354398cb8156b83b067478723e97674f470b0088eebe138af27e37a5ceb61753676767a1acdce4e8db9e325f84e87b34198b343c676ecec781c8edce1fc86736e396fe74b0fedf8748bc3156d6e739472b8ca833e8733cae12acfb824d1553e3924395ce5d6c6d6bdf5f0709c13924d876f9d236179f54dc7e65bb77965715ecf6d8afa9dcd83cfb3b3e344dde3f16f453b1e793cfefad3eef8dce15cc739b72c71781ffc1cce393c1c383c7e9d1bdeecd2ade92578f14db738cffba01ec7fba06a781fd4cafba0e0ecd24350c67e3a8c6f1a8d4a7577904457caa453676e854cfa971ee27cbae538ce9b73e8ad50c039193664d0902943460c992f6c2d1677f9e6aef20be576fbc9b9dd368ee3dc7254f3956bbe5af974bb5aad562a15abdb3627242a95f5ea2a95caebfdece6b16e53d4af1c7a99a7f2f8bbd5ca89fa59abd5eaee24e11c3a77e1976e4d77bfaaeb518972f7fc7accfddeebb10b56d5ceb3141074f0b6b70bc364ee44ade29448bd40cdfb7878b332dd9ade5c0bdaabee57c3abdc7213c0bf5ab445d9f0d0ddbbe22e28f728d725c0bd31bf56b85170aff793d6b3237cd0ab7ff34b849ee62a2fbaf53e1b5e73e65a68bda68a9e95e921cde737bffc74cd6b33dd9a73886e7a9be9a122262ce2e7e6ce3f1d7ef1e9b509e03e25f782e7ee917bc11deaba5fcf33333bdd22d31e7574789e40f331e7a302604ffd697a94504e53aa67f7697ae61fa7a4f55fd44b1b9a767c853da55eeac11c76e1e66ddaf1d07ba0809c510b881e5c4cd802002d3e597860b91f1d5af1fca343edf8e836e8f8e84f3d1f3d0acf475fdaf9e833e4f8e84e707cf4253a1f5d02373e3a0c257cf41748f8e82ee47c74166c7cf4156a7c7403e07c74a2eea31f617df422ab8f3e84fbe841db47ffb11fbd15dd47fbe85e3f3a0ffde83ad947cf991fbd931f7dab0dbf1d26957048fc21d4674431fbdaa3f794f970ea615d0111399ea580f0a505b7ae43870e1d51870e1d6ee5a643870e1e1e1e1e1e1e1e1e1e6b6d4686cb47cfa1927a99c3d92b4c817a4f146f3e7a0e68a360d34306cb47cfe17dfd3b4e3d3612f42ccf31a48c6ec783fe833b4ed4cc46827cbbddb61c43cae8320ffaafbffac621f9fa39df81cff7e304006bd8436fc7330ff62cefcbe1ed1aa724fa8edb8d53d29f79f5a3ecd60b7be87d500f9de59cb3e21b2d9b5c10309d43c0f46cb5b26e599bb54ed4d56a1a97d9e33d3d3d3db36787efe8f19e9e1d3d3d2a2e494b875bd761ada6c12f39bc0ffe8e471eb7ce73bb4cd0f3f8b7e3ed1967147d073e8f5b9e1e4db3f18db55a4f734a7cdcf01ebfe13d5ff7f4e8b0a1f5cc2e5a4f4f4f8fa7ad7abce7ee24d171cd755c73cbe339c9e7711d3b72b232d6371c6e1d875bd79cc7abaf22a1e7057b7b9ba2681bf83d5e137ccd999f2bd2208fc7afd27cc7cbe1443187c78fc3a36cbc4caa5bd26fa8bc0fea3fdae6835a791f54ebb5bb93a404b75ec2d5b45cd88584f81f6df3d2352db44d8e0787e8fa299b1e8259191b1e1ca2839f49f510cba5e7f86697363da452a95444adb2728b6d7a48a5f22ed3435dd7755dd6c5ed835fbe732bb7ae53e2e3bbdb65bad8a7fe243d5e73f6a06735144047f340cf52517c8982cb135163e6879ea5a0e0020596e71923cdf73c4b8d71620c98313ebcb5b151ef8376db98abf783faead0f33c2ceef236e85d28cfa3542e6e146a75bb6d9ec72ee849afd0729be6b1c629f1f19a33b7c2ccbc1de8fcb04f523df3a31adf64f07e500f1df6902b824e149f5a890feb2cb7ceba934bb7a475e9d63ef55bff342e497abce5a057879cc3fb39bc4ffddbca2d73acfb453dcb33efab9ce78484f3ea486a38773f2724d5711c49e7d5b91a97bbc539773f398473bf26f89cd7fb752c6fbb4d516f1d7a99c779fc2baf09be75cee3df3c7e7e8d4bd27a7b7792a85c73d58d6dba255d7395981ed25c7a8e4fe3f2d2350f76c90185e832174208213a78a9f3cb213aa5eadc6672c0213ae8b25e28a5fba7eeb3eb058bbba03a892e549820e68a926cc684000a17150b40c15c3eae4390eb4a902b0cf4c9a587e29b1e820fc4f33bc9ffe29b6f332fbdcff0886d78b49926008f2f2f1d82b95de6c22f4d80ebd2730c29a3835c9e5ff6d04ee639ef64f785cef37e4800cfa5434f0702813ebd1cfc037d7248705eb8ee79e45ef0dce742f170cf9b7381c7eda20fe89073e15ee65cf0ae4aaaa783c0d8e8ecf3c12e3da479bc43cee8609797ce16bae6f0aa1c7a566594457e95b7aa9b8aa56aafaace32b7d6552aabf2693de899475d95f9acdefaea56e5adaeca37ef835fdd7a9f34e25ce5d1b35ebdcd89a2ddf839ef7b6a96f7c1a7feb60c513039d7bc9d24f7b31e5dfbaabf600fa347a174bedf74eb05c7a337dd32b7dd0fea3795432fe27858dc85e3dc04c0b950519d73a3a072286e14a2e378f495ca63dfbcc7f1d8d57961365f791f0cbf83a4f5d65b6fdd3257b439f4b8bb5957799f8c9ecaad573fe944f1a97f4ecfbcefa95f898f216574b0cbf3378cebec892dac340fbade58ec3b6e7ae5048cd12e2c25b5f843e8a5eb6729186079ee687b9f842968bd651ba987c55d74a3f442518f02b2051431178d1472454db54b0f3597a4c7472f75de0ff6b33d2070f9d647793fa897de5ef5b0b8ab6e158bbb32cfee270910459d1b85965e139d9a9a4ae3257bf5d8d5f165dfa6483d6e143e967a81987f6a1fdde2a886cdce8060b9ade50d16737096b144e962b1d80d307aeb9bba0bda7c8f27b83c3fbfcd9e33a844ba149d7fd279a7269efaf627fa995bca2561fd94cc21a1fec5c91555242da0ffa4479f5c91bcb2760b32b53e12812ee8b2bd3da6d6c70bb9a2d6c75b51609fa59a1013c5b399e726b490113a734db4c99ea59a60d3040e60a4cf524ec49eb567292774f08ef89be09414172f78ee67292e60f0dc245f8781e0e51821c740bd79b04cc7524e74f94fb2941321f8afb2a77a967242cbf310578986e57ea2ccb3d413629e7b967ae2cb7b24f25324fd6b51679f228af4102b890e1d7a3bdc7a2fd20aea21966a42886f1fd243f079aaf7fde0d7ea0575abef4fb75ab6ba65824e5e27f9ed39f6c7fb60cb04ddd7fa867d57a562180b47d041df981bb60d2211c8ac04de10e392b03832dbe6205b98f9c8c4c3f63ed0715f588681a2bf3a966282cbb3940b80f80fbe9492fef38cbcb0886e25e1c567b9fa30f0f042310c14fb5f1d4b2d71e6594acc972fe2a3d748845dd1619719a2d810c3a2858b8eb7828a10ade0020c4b7ae80b1ba1662216dbce33880b741173b55fa08b18e45a982798fad91e150bfb09b9163e2f5061a257ffa0efc4db7400fe8c4a75305916d3f8608b177b6f9841c45cedd395f8d282229eb917fa42d51ba6e900fc71092925c44085810ed50eef0162c6aee87d5eea6b01edf542556f5f00bbea05b30315c49631621f1df6e5e8437a8d3ea40f41a363574ce3832ded7da1dac3645746f7b293b9caa968ee624e01edd65e2af586a1ae830a2ed5a5a2dd30ec6a0f0a8c941d9f3995eaedd1db5981bf04b457678e85e8d9555a62407bbd61e865caae1274e823254cf67c42cdb7dbdefedb8eb48f860d39ae8a740b03ddc769be9d47023de40980811aa6206fe0b85bed44d1473b1530d1d9f5e97ceb4422ada8f391c8f4f6562432ef91f6d1def07ef5bf5611066a875bba788b14b19ad8b104967d6a27a10609346f216743c74f653abb74dc67de16cc05bd63970d99b0dc44a27f3c86f48fdd4cff388dcc3f688556ffe016126c383b472239aef9c7694a70957f39d63f9ecd3f1fcebf9f957f4358fe1de9fc633238fe7113a901bbb0112fc1eb3c1b5e0d8fdb078ed779dc3e58471efa8adb2ccf435779dc3eb4340f9d04afd26c4a3763bc0f5847d9e8e884659f0fb6d924119de823c214e0334ca16fe01200055d2be79c39249a13757309585da8282e511cf183980b0a4ce654c0b48799ceb5053a793fff793fbb74e4ab76bfcd35cfe956f4ba3d3bbbf43ea8e63b00d7742bba170c14d530500fdd57e4a37f508d18279c1073e433b7b08824922822caf6050c982f99c7748489470b535f21f5f0b62017ee48c6a638f57605a319a114ce0bf24037b96994c24fa91e22d343746bce687ae6d083471e5e28d5ade864a21cf9e9f0870efa57645e2f3b0b6017cb590e358388b9581e3d684a37b9157e98d1c4cbeb85f3e62ed4ca7550c1c5ba54a2661031d78a73ce21f75ac0cab90bc5f9ead6e803fa02d8c55d30cc46701888361941d954342f0e03c5e944cd29802b9a1b4c00f4ac097e07399566376b5d6e9bbd3baa14bec2987d6ac326e1671fa55bd0610f1d74d846d52a225866231a8bfab7c4a3e5bfa5eddba32f1d79597d66ae79fdcd2589697cd081a99f578b697cb025f6d44be1217774e4a992234fef4e762196232fa11518db3ea66143b7be2f74c8463a0aacc29ec252b7d433ca3c865ee6ccde0e99a74bee884a66eaf173463da3f436a93095b57793b1ec533a27a3e945d27b85e8bd647e4cf49be2d4d47fd94bb7ed61e0a5f75de0a343bdf43e0c7c742a2fbd0fea63d44befa3f2d183bdec408c0367de665b335d45a1ff35d1871e3db677818749d85cac931175e846f461930a9fc1d02de8d5a7c359a44875c91d499fed2b70107734bdd52d68ab272f0db3a91785fe175dfaf4a4a8beaf9313f42755e6cdd9f7bbf2dff479914c789b580fbd5ef97999e84f24f2ee2089f4e36da22f85fb78026623d53abbed8e70f6909d415379f5ae9e4fb7a073eea97c7247d3abcfea4de7d1e18eaae774ebb34e5df3a668ff45a7378af1f136a930f596dfaa66f5aac96e49e9aa6fde1e230c5c916523aca9201be19f5cd6b4e3a7c88f53b4e7becd9f6217353f25fee69672472ca74ea91735cda9c7721557e464b472e9452a577190634ec51d653e9db922ea659e15d52a79745aa005fa48aec87d8a87ce81cefaf77394f9d690870ecc6781ff9268f34ffd2f69fd5ba21f3de3940c7d74ebc10d744d2a4cbd7673b8a2ae5bed4f103ae58ca80b47da5639a8a5b31a57047de8a07f3fdf4a4d2abcf9a7c85221e8f253e2438742530f9d9eb4aff0e14db27dbd08e0b79e7952b8b77773c9290142b359b7d625972473eb924bd265fc76977077866e41276acbf9763f96736eb9ae736b39d6ca372fe23a5f6d5eb472bbb965b9e536ef63b1582c975c11e776e5ccd9ce83cef29c5637a85bd0b95bc46b79dc6b05ebd9fda2db23293bde5e2f38ee058bbb706e14af718191dedc0afcb2fb99d3b6e69c8ca22b2df19ab73ebd48f3cc9b1eb923f84e46d2ed65e2353fbd4815b915f8a7572e097fc1ff45df41c232f8e8ab319e65e62587005e23b922ea4e2aed7ab720bdddbcdc2dc9d3ad1f5677392051e6773c4b21f105092e4708f196d541c077900237390881153f7041754674c0052ce0c18b105ccc97a38f1944cca5830a2e761f6801db5b5e3a74e993a5bf60df1fece59532b6bebae6c1879a073923e8c1b772835ebf9d1bf4e07375d8ab0f86af1e19c655e6edd3330f3a516c8f1fd66e6d14b60c2c1f61e5a3b3ac4d448623e0e7a69994984ddac033d6b49967ac21439e61149fd7f01775ab4da4e94dd61dcfa86de5ca4df71a06a3c6951b342c850d61952b37dd6440cec8bfa3924739162067d41ec9b0b61eda911e5d294e5f3a529d1f3e06669644d3b6eaf1773c3e3f73483249e5bb63e59268954ba2c17921ffc456b14a327714ef079f4302c380a1e09ba00ea01345160fd634c4d271842cbb69e0469c59f3c9872e3ff3fe8c72144d4867be09eae0619cd497542f7de948967d17f8f69a591684d59b0c04955dc93fd0332a4746beca1bf9073ae490c4a7d26336659c1b6f32fe8426ac3e980a5e5e996561d9077a125fbdbfba10d2db95fa7e4b3c5a345f523d75e8fccc9ef4968e44f96f4905631222b12a19ddda8d5392241e0049c60cc440dd5c513bf476faf6ddba251daa9bfec58754bebde39c4854da6d06829f0b4febfd60dfdef4da8c1bc6d5c780f899c755b0220c7634e228219e3a07ade85ff77d7728bd467d3f388554996fd7a05499d7da3017aff626478be93eb946b2e9a14f7b23d1f4d007a53e4d0fa979a3736489952f53c0365bc4749a981065e2185a64126ca43f888dc4296bed3a1d1df7d67f2d2d8d6eb59bd129f375ffb1541118a8fd1322a28ac5209c82360406d2cededa1b066a6f26ba6f7b58672c1261974ef44f8775eac7db750bfa156a9278be420768fe9368befdc7f3153a00f3d0396eaeb669e9d4d4141a5b1021ba9d26f8b189f5947ae69ff6e6dbb3297027c9cfab147d7a76eb7d82aa2e76b5c9363dd471b593a43f2a1f2f9ca25bd0576ab22e8199e910602c778c2c255fd9ad18e38a81b0cc73cb731b9662f310ca35cfb28b04228d3768ce245144d412b38cc1a60c1921ba4bc7d24883464c12700bd4d26689a758c1055d0b32641f0662177492f946ae288881584da6832eb923f87cd9ccb3db56b7786b32dde48e649471053dc26b61c6b1e95ced2481b24db7d871929840bce4da10f9e696ccbf9985fa37ad3cacfe49374da4a289b24d0f45879f66e51b88af6822910aa67db4cb34eafdaa1a2b6cb2b4995bfecdf71862342b1032b7be3883ef28f5ed9fe69303994814c33eda61134ca4728d22defaa55bedd28b62a0e8be28e61b4dc3331d83ae5b0ea324c22ee8b677f88d8f44987d7cac8f4428fb88916174f6210fb9211fbd21677432e38ae0953ea564ae4d7686cd3cbaadedb689ee93b0b922c90d63942b66a0ccad75e959cfbccfe733eefcd361ad9c39fffa37674e610902b1001117a28fe8198edb1ade2ee8b85b35ee07f563b038f15dc38eab1a4df16b5c66209cfbd9f0d45d8844ea124cc1070289ddfd7458f7eb9e5797bb5f1bc59f6e45cd230351798c9af69f4fbf852c7bf5457d8b81a237135d647bbfeda5b313fcaff5d56fc9672749f7d4bba7f376701e81009dec568cfcd4adda826e7a746e65ced9952deba4f7a993c02cbb3b48e69dd22fe398228a78ea8ec562b1a7eea288228e7cf423316e3986940139e84472d1f99b39e9908b2e71b09009e2e1d291c7c142e6040dbf0ce14a43022eba8c20cc1822d0028c0e0d96972eaaf53245192cac17ee798c0e2e1863458831559c18229b73d22c036952b0011064b1e24b9b2cac24f1ab9f63ac40f173cee905c674749ec7e870021db8fcd7391b1e73e5cbe7e0c4b70a3a1ea303961f7345cc181d62df9e33260732dfcef342c75cd43912c96864672ff44aefb3e1e59c9ed294f8ec369eaf170bc821193b4e4d750aafe4049fa57fecb25b554de7557a4ffd5e3267ae012ab8b2cbd14774494618d2bfca63aa80a9d16bed24fbcc2796fb4b0a825210c425073ef8c18a178c81860eb0b8c2f200bafa416f59459a9dd6eae9785db7b8643add82d0ab10f15f0b4eaf734c95217e7ace0cfa2e47c79fc754c9c0ab9ec7e030f55fe752d42ccb68067050250756baf83c06072fea9aceb22cbb12860f6cba1ef4dcc018ff79c78132b0b4e1a1ebe7313898f18e839bf6710f4285590b6806eadcc0941ec822103e3fe0204486031135c7f3181cc63ceb790c0e47502d26a514478ceea16301417b1e8343acc304e9743e3d34fda787e69535f3584b872386cff986088f4bfab43e7f6fedb0e5bfce75f8f29da5cb791e738313df3974389ec7dc60e6a55a3dc4eed3aacf636ee0c17f1e64061cc1b7e4b3c48dd511aad0e18e10868ecd4a0deb011c55c75e34eeaa12acfa3e3f74ad810ee7596a2a060ffdeb3a2d54999acf5c3e3f484dbd21c1e5f3030f39ae2ccbb2ee40579fc7c44cf091c810355c3e3f6c3c26d60411ebf2f981a54a781e13bbe2edf398980c82a055a6204d45835e35b97455a5d5cb14f434fbae3986b8e93297cce4f34ad16bb7ba6a3073e9df92cf6bae72ab79aa0f74d4f9dbe5b3a684c9e7b3ab247ddeee10e8f8c01763c83041143800c1150ee808c34f10bba4ab25211b01cbe33c4ba5518226410721749d6f29e8a9670e6f4eb7a08ed7758b49134caca1020931c078c0cc1943f3b3379f5d57966510769ccd3631cb2084b566af20c00882891b9a6041cc8acfbcd3c1673ca010c2ae5b393fae7439cf524708e2b567a9238460e660b9cc17e4fa8a441813479ca0082ede9c7106181757f1dbb31349c5628c043d06c518638cd023ec6e973107411febc74742021159a820a8b7745ff7dd2d7fc9e7a33ff523e1110384350f5d7a4b3ef2a14b98a6210c424bd928270d6a60332948c04a81cf39b339e79c73ce39e79c73ce39c970d1428b307e004110ae49c5cfa9c54fcd35e78c2c805290809502186950034b593085460faa4882881bac9142ca46d9a08c3158a459b3c5144f441438a5f783936694524a29a594d2ae5bd2678e4ec753665e348f44b4db451fd2ef579f524a29a5598ef48eafcb304d831a589ae3081da61083031d8600a206613a1430ac4a1a665cd1c5064170c10e34a881d5b2ba7d96f17ce699cbea99e7341196cadcd988eab3fb2df97ce699577fe8328750ca1e4881c5164c5c8185085ab832293ecbdc0824f8cc799a08cb95b94f0fc9cfbc1589b02bbbdf52d0cf5b3dd0f143e9153661a7208d2d69582982118a3084229c61069b2ede0c219edd3e4b9981458c6648d1411e102112dd62a9aecca7f742c75c99b3f7453def20815d7eca78bfa8173a57f6cd799b582faf978c9da86319f3d5e1e883bb15d104412db6c47e8f73be6730f27d05f0dfc6c542345da479e8bcb231c618a333072f47c8451920e4b394195d9ebb152ff70962e4c855e0942b0c03556121129d1964a20f06c05ced54a2e7106f5443b7524aeff19fd41368266c5e265e13f5fcc54f67affaf4a437a3116d5cf5c6b80a2d9f26bd1e6f217310e8f1ec1367b70d2cf3082ca4a2e31a7439b1e3f883bdbd26f8501006fb2d23b1fd58c8cc8c83813a879d75a4e858ca8c2cdfe16023fcac67292010e1b95b3db04df01b0c32bff9f4f65ef05bbb4ad0b5767aaadfc453469bab54ce77aabecca76b1ea340fa064612bfb9e656e3a2e69248df9c39241a75eb9b472e4975083fcdadf7b536a57e533c42ec097e7b19d0332ca878e999af49e333a72d1760f83224c6560fed64ee3ead2533ac115384c81873feb498b9165853cf1c57d86058d24393cbb0f02cf5c59a205966c87fbce667b33f65df3e3d34dda961a5defcc3f7cb9cb922abdae007a9b757ef07fb3ed8674a1f75f62f43422f95acdd2dec2431497693406f9d1ea23e9dc77e11fbcc9b37fc579d59ea09345d8e8ddc51f58fcad443877d43ac52efcbb21b1e7ac7361a175ba392f4e950c6ea444f9dbaac53c6ec7efdb2ba928a00a2afae7149a8675e3de61fe97ddc118c7d13947a66a01d24525a5cf1dfa4d98d517eb1df9167222ce754cefceceed3eaa1cc61aff238af1ecc5aeb44bd793bd535147479e91c98cc6d112f3ddb81d44bb7d2ad8541ad09aa29be7596c7aeaab49384fa94744593d015b55edd6a2ae7d754d7a8bae65a9b97ae72352f5d69ba76b7cc48a552a9aed2f44fbab6b952269dde2ff3ed6a4e14b53ab7ccfb64ec2bcc415c56587e853948e6d04514b7cc8bcef2d8e535c524da55e25c0e0942c779cc38b777c73af5c9dd1d7bab672aa74ab5d2249556d7ee97b9756bbd6ff31dcd7947bb46d3addbfbc11d9879e9d66d6f4aaa2ff3cd379f46d6ad7538a559b7fe19fc23cf2ef6baadd80817898230556f3fd81538fa578d68fe69aff2607cee1859c8b22c5aba7107d834af5fe5c19fedf4aa1040f4d6551eb46e559bca88e99ba2b61d5f3904c0babce58e605dbe69c95b3f00cc87b76eeda6714882b8cd5bb7dcc6b5d01febabc3b9faa2b43cf51cbadd3655c3d5ea8beaf2d4adc7fcf35987be714adaedcd3824edf4aebea887af35874436c557e2327aa311ece75582de04f55fdc49f25920db009ba8032e39589303326c280e3b44d3b17f1b7bf0b9957c9e52e39999d9a85760db2d0bb247ee76dee2833ea314477a8f8f4e9dbde9cd19679c41e70ca679e8b5532f9b6fe79a0e7a731966ccad3de8137ed141b79333e234196dade00dfae6db75abc747f8b00c462b2c6cd3350b9ea5d844f15d8267a9308400e30c92a72a6dfe8339f149d9800c9e1dc2365d84e2598a8c1e1e927996f2010dfee759aa076640ee4845859a6f5af26d48f04d51abff9e7690039d12fcf7f4a5047607ff3dedb083f9df8b8b16fc708199ff5e62cc7c8dc59e79ead99f7fb04df0a5196fde7befe59d6760f9b9c5c316a2f7fddc00f1d2e507db4932b778e9738bdf81ce45df0bf692a7a6a6b63c9c403cecb9c54b6f0a09f03eb5db3e82532f91408f7e043dde27fb6770f9a7fe79bff629f0a3c39ea889dafbe879df4ff6d96113b619533c64dd8f0e616c95b792135fbd1d36f5aa7975dbde577dc7bafc38adca6bb72b6f67e5fc1fec57be799f4a759b583fa5396f67e5f0595c12d654ffb4dedcd1ca398fe59bb7729517376edb3c46e3b9cde3223ce7f55bd990279519ab7df3d808cf4dd872b59384a3989afa604ec462df695ee5b5a772d67ccb82cf4aedd5bfea7c04bdd6dade8da4bdba5d792b8fcb6033dec66de5b11beb2bef457f4abf0c4ef0adcf1bdebacd38b8a6b3ce1cfca2b39c66460865673c56d6575ed0ab3c2613c3e1ade6cd1959ce72bea934dfb48d6a6e3da78d533951735ed38e57f9e6694e35d565fed12e7d768a732f07290d2c44d3451168baf92cd54512cf4000e0388ee3388ee39c7d3837d65a6badb5ce3e960c4dd3b4ead4354dd3bcb211f6d1ae5207c3f0b4e8c0739379ee160351a7dc04a7a05719887a7b508a4e8a4ebac6468adaa9cbca4674601942d17db2b3ac237e9f2cc62cc61833ea99b73110955d74f9e92dea4491a869e6947a467b04f6889fe5969999991b3a7bf021b3360662797bb04cb772ce37b70ecb742ad7bc3a7558a6cb58ac7616cbdb63a1b10c7fd0498fd327f5ec7e1baba4d157df9bd6a3a8de5e2655f7d7be0483f0f332a9545e554df055698af8f92a25d99c9153a9e6bc0d81649ff16bde5e432099db086517b16fe7b7334aa59152e1db89baa893b0d4f7fd88beddd66d3a4b3d4ba5917a1ef37d65a6799ffcafd28f4ebd6f69fbe9d99d5783130636ba8d1e0b49e659a679578f9a57d76c36057eadf1eb556aa16af783bd066d8d31c626a8efda5ad7aeedb07de39de8d08920f5e871757adafe29fb285f9d39244bbe56a3e9f1c86974eab66a2a8f51e5b5c6e89a4aa56997f9c76816d5eac1c95d8554caf2c489d3ed6c77590aa12833b3537ee835413d6c8af0b2f7c95a217b312a819c51efa33ea5fb2519bbe1bff6269ac60d533fa57e9a671e3d25c9b7bdad7d0a6d729a42ff05e3ccdb55b709a6f172074973459d4d3f80d1fd9aa05e3a7fb0a7d0da6e87dddd0e2bf4a6de2eaf524c2293408f5789bd19a6c1ca0127f00816caa0eb150ed270269d0c3a3602bd231482856e59996fcece41afb16af33224d6aa58e5ec9005dfaa5c7376c81545cde351596f0a7ce84d81afc91857f036c5df31baf0ada75da5ead625d7543f737b79e26c2e5d73c8c12dbae857bbf5abaea9ee077b1554d9fb41bd8ddf7700e89a13c526a88f9ac74df123d4a28bde7dec2609f43ca9b7036f13fcec4709b440339dd2f41effcd0bb3748b3fba855992d88853d07b618771180e9d6f76ad5c0172658ec5860bba7498a587725efad2c32cdd921ec46024805d5632874ed4b08aee8359c078e950ec5df48106104b94608922d4c462ae2e2655d04310389ce00997952b402ee8586cb8d8ad5c6917752c047041cf3c2c0470418579013a940bd187f49139549817a867178a28fa904e2f549817328717caa30fe9d90de2e8434a0afac76638083a48e1858c1b10e10516feb01fa6788204241883e688335cec62ff825ef058cc05b3f4500fa8a55b066159ded2a794fec5fb457d9c5fbcbc934aa79729f3a568449b9f37f32fc6245c850f9f5d2fd54effa27e0906c4674c03b022753f1b3e3271155a7efa778197d935f3e50540b68042e2600c1c54f15ea0d8a35853535340b8b458093930a20a0f62d2a197580f0f28d8d2c509005d585026f61485d7bc9718902da0884d198015291b625c851617fb77819fce9c0233908fa56e70e59fe07bc181d7b8b41be3352ebe50ec514c2430011737a4118bb9ea8d5989c55cec1f94c72f0abbf4a237d700205b8c9972b133d7001c2f7290822354999a72b1e77c7c819d6cc6851ea22efd0518a4db964f8b0a087d5a3f30057e19e430857eae9e74182010e92f744bba0b2e4422ce66beb0190fd3e1fcc77a59db834f9bd20b2c99218a0d309659b173f2381bb148a44bc845e6167611539cee83de14f81f9c026d33e496ab799be2abe055821e3dfad34bdf7e0709af799bed589f2fd9bcbd0c817cfd1336c7154320d3a5b7b4bdcc3cbbfc2c839e5df382de5519e4a283aef2a8432f73ada9be0e03b1578fc7730662e73b6fbddfc637a491c599b7acdae6a54f0f4ed17d55aa4af550bbf44aa68732975ecbf4d07459a778e9f60a58458c910a08bfba457ae5d243fdd22b103005ae5d5e562d3085eea7de664427ffab5aaa5732522c4cafb7968101a8529148d5127d4897522f55d04daf52554bb7200bba797790742cf6d1a362b157ba1f093f459a79e95fd5f2d22597848d00839f7769face0afcb3fafca7b7916147097f7afc2fea67e6c1cf620a2f58547069dedece02d8a5b954163578e67a7a0fd8c874e9d54c24625d7a4513894097f4aa261259b9f4ca06a6505dbaadde97f94ef51aa6f81a6af02b6fa73a74b5cb7a3bf526a0c6fc0a745977e89ade0bbe97cdabf7d540c5c7861ce5ea83fd8e0b2adfa12e3ffe4e0238dfa1d705ee56e1a9379acbef874fd49b5705baecddc96e136beabd6019e2d2bc0aeb08ae2bd0a5b9951a8ba96e15aa31810efd09e83583cda667d828a743486b36a747af5e376733a1d3ade9919b3178eed67409b979e1cbee33967d4618ab47cd23f59879742df39a458f99c7187dea742b73fe39e699e238f41db923a398f4ea742b93b23210b71896a74f36029fa75bd397789df8551974edd0753c1251f9f45624627d7a500f693cddaa3ebd081b7106aa5dfba8aef26afba8376a9ccec3e5a7df6023f0a7673addaa5c24f194294eb5f2d577e80ebd525c34f12cc50513dad5e9569d0cc4ce9c6420f68f4458ee219a83d847979c91bc9f077f4a6fe9344974e95552875c930d5670b821f64d5f0d4530c2d467fe827d765ff47ed27ba95ac1e10699a45e69943933d037e994d2a3cbdb04f55f94c2520bb9229e38dbc639b39195676e579e11ecbfcdeb4aa93afbe67df5598a8b227e3250d69c51b7735e759507bf5df334e718f2fd34d7bcf636b71ef3dddcf6668f54ef7673a2e6eacda0dbdcba0a49fded2a69de9f96a45d73a2c89f79d3634f768b37183d20fdd3f9598bf4d00c1a325d67ba7381e567d0cf9f9f3a3fbdcbf1e91b4bf960992133ac80658ab3752ba70b2dff55339270a1873e97ca19fa8fcf489f4eebf4a79e79113af4d5197ae82bf2d4a91fe9a1214fa92f59f33447329aad8750f82fe7bf22dd6a8fbe815b4c3d6d34373c75ea393d249d52a7ce3ef42a719b4803cb10069d0e0fd72db67cc306dad26d68bebdcbd161233ead8285683a1ccb2b0bd174b2842a838d5d628c43beab773e5bb7841400cb800d7070850656a8694119179f8023b908baecb628d3df7e6413f2ed5b6578e5b3d416625efa60194a75ed7533c1326462158516625e3dcc600b363400638917b878b3d0a107dfc20dca6e41e9b55bada4ad7fe695298eec16bcdf537c769d1eb2d4524dbb9fe62ad7a8a4903b0af2dbfd3657397d8aafb985cd30aee8ab348fbb158930037d3c0fef97d908a10a4ff3a10d9f3933531cee16b775ab15bdda2df84d30f39e62d7adbebd751e89c8e82d36125f05e707e227b52842674a88848418b0f2b987a6fb88f9fb2c95c596cfc2ca19357fc64cdc785c7245d2b98794bc3da53ca8f469140a74b1204641c7109aa19126012463146030382c148d4743224d96950f14800ca2b4525aa08af324c7611432c6184388310000006400606466d80058c7b76f9ae5f43fa19457415263f4dff7fff0c9a67e95f940dcb9dea60be3793610c043ce09f8d7f96980740824f1b4f43028af632f295f0eab3120eb62c747040d92a07caccb380d0053a366dca3f9dcca550c938fb2b84ca6fe81dd317f29869bed948ec1533f097507e3d02e087e292db7195103ebd7f588cb12e77baa04d1b9e8c8a039b0f04558081855fc5e12480a5703de2c6d89808870aabf28d698c9c0f61f503b3f415d3058d02364743b54d17e4b493ba8873fbe8ff884cea76101688b349355ec4e02b66ce3f55955a14f492e57292559de082cd2c15319497255eaea7526d256eddff971d8a92483b2f45354b66b454e5da0c064b5079a0fda4321c59ba1a0d5dbe93cd0ff0033a6ad5ce03009720e85d06d855454c18804e3ddc6c12aa4bcace55d5815be307d40a8af2ef3afde024036b45dffe4ff7ee99af40315eefa20d0948bb7814e09bde64a0ec3a38c026ddcbe9beccb198286f40fff3fe77b96d188ff474f7ab77cd2280885fcf23a926f13a08242a5745415f081a64c421f6e400b77430f77a03fc81468710f34e3163423b3d10fee43076e439371877f7dc496d9d0b5cc77f58d02b72bbc92d51ca67481f6ff608cae9e43dacf23199e8888ff3e95fa184235a298ce3087a2385e88915bd233ac2b198caae4bfe5a916041533a45fdef02ba9c7bb36cb23847cb74b0b14e644d09d15e288f0cbe1839fce496bb149504f471c8f0f7451a86cbaa7bd29889e5976bc404890d47c3a8576e04d01084bd893ecf9d6543f58f22906ed02466b0d6bbe5b5204ccae9def650f7ccca7ce89b6e194b2a8072ec568c26cc56aa6fa768ec5a13230cd99b15471170746a92a3b7f81ef09401798325d59dbe6afafb00c444ccbcf8753ab2b5c64371ffebac8f1fdf9d54e69ed66e04993f72e8b038a435a09e0111f00b9a9373ba1a9270c493da663b40ac08f969d40f08d3246cb256af1f239bcac4af872d7a105c466269c32a386d09ebc66f5d3a8a28ea311573fc7421768c9681006e6c63990aa58a216e0599702192e6800d739c28ae610dcfc15483a379988dc69cb43e5636e74c6a407e8ca8bbe69b1db12309a26edc1dd43e19f2cf80dedd303c8e65ae81ae08fb304d05b6e3b1333fbe5c2bee7d2dbe79ac766bb0d535747a472604a04c00450a617489c1292c1818ee29c6a98308aa6f64ada19630f911b3e695eebc7eb57da3574fecc9a8acd468b8a8a4a0920eea90b9d5499e0491587879095a14450720b9d0fc1283300841bbf810f31e4f4bca1f5e48ea6341ed8a31a90b40c6a910e00760f297a55c4bbd38517da97b42e893bf4607740be9af2d59fc43d19f87e532c0d1149a51702738d0f6847849b77c481cc4582f3451b2e9bf69e189de77799aae9c3b128c0d92f08d4e315b3cd29a3a56343c31265763e21a56bccaa28171e2dee41dea6b6d6666cbbf3a0201881eaca8f0428ee1c55efd335d3ec7cf2c88125a064625d64f90fb738a48d77b486c8c3fca9a2ed2387771e7b769e69a2f6394b053c7782167842834622d1e08ca1f24cb16d5a5c0912de2cf7752d6bceb60d180b324e370b8e56efaedb2fdcafed825536bfa2e763d796dea2a3f1d3e984824cfdb0d1a48c2e6c18a3cff6d0efc777ceb3edc71f099640628bdda7b6f32c0a199d694801465b473ab7e74bdda9a77610d3fbe610ab9020e670309a951322e87b3eb99b0f84a9395804c23e14facc5f2d2c595fe1489f4b4ea0d3e98526fb00bcaec8ef452aea9891a38ab95db264e8e718f974e6d6be38f63753be2b7370fb1e97c88b96598409dc9fed876f08ed2c4966504ac38c0cf52ce2a852f3101a11f63964fce7dd20221c880ef434ccf4b947b567afd12f4ccd69a34479bbd69885ce4205c56d5007b6b8298fbb94f6b7d9602b6d733426c96eddb838fb4404580a355388d219e3c88bfb31a71d3301b080127c1707bc4b360c11d121a8c5d48440a01f771bf8d2e8f04810bd0affcd62dbe0bb7ef7e1055b7f4416629b09472cbe6a0e1134afba5a80068396123065da8b651cfbf62e1ca3371d9293af12de6d8c9d4f3769d39b23d174326aaef54af01f319af9f6d2821fc0e738c0071726209d26fea1af31d7afc611628b9017a020b32d7e6d9484cac80f89369c70f48d2218dc08bb12d3b16c93242d72af5991dfe8e486c92d2b8f36f698a941bd9bea7975f474e643263287eff51f9d438c25029dd1d9bc6b9395ae8bde79ec86b169d41d591d73456302f65822418c703e290f32984c4c654c4fabf839daed13edd7b12277ee3eb73a8d5f1db36527063a2bdb9417caa50bfd93a9682698967b0666085b5c8dee0503e1dc418805865c47845fb6de15ef40cb2a5671152e9c70ccea1c60afcf7683daf49c9a3dac1e60401a30ec566c00a82a2284a968366b8c5d83ad1af9854f00868c0ef3aeefd114853d191db38963e1843d26a8d08edf6b884367b10dce2bf249e34ccb6ea010d1eedf34fe86ee2ba442defe6a1b745eadeba38b44fef1a3aa57824d8dc1b10620c07a8d4c0f63c376febbffb527c91605f83b315a650afa999cbbecd553a79540b3998f28d2cb84d4f553b0addae8877dc112bc927081ae1becf37caee8beb34578cc4509c89434b8bca9660f8b9f58e8b028eb6c6cbe0a58209b879b98b72331d7cf603ef84108bf316574928ff16a2fe498fe67e30e998a881a37727bfd666fba2c03610fe7c71ec2cb4ddea726551f388cddc530c3341bde649aff3f57baeeed81fa754a1ccd68c4d850b86ea669628d02e883fe761336a1da41d98f4a5ba0dec5330070fd219a3f48cb767f1506b7fea2f2be6b1324cffc8ce800de4f68f8ccb24d030f10b1ac43abdbd37c151e4a96a86bf7fb1c294505c6f0e749282adaab4b0152b994b49ae3b0f42f7149f138e7ebd23fab4c3015ff55653029bf6231328c276f5493b5e98ba50d9c8784502365e7009fe7d58f62cbe6da64c51a784ffefc804cdf7173a5cdc877b904c68d374cd07e8828d9f0a77df9012e5781a91bf0bad69aa1112c69b805e3034ceb7bafe296c76a33397cbb835e9cc273b73be7593980cf6a99a5a403e870d7ba141c4c015db92b428c894f48954dbeb8e6a5050c7b1f96c3cc90cde317672f6f2800c2d9b5a303c544893fdb3869b197a9bbdc014000fd6aa7610dbd1bc788c4f93fe60a605c1db73af926a593358501dc9ec9497fc639ac322280ec98ba09a3ca4dd37cac9b2eecec9a261978c634c5b8638f81754d7be83504467c50705ad74bf8cd0cabd08522bb2e10fb1d1530fccaa93024d2439f6722c930de0c454a5e773867de85a8a8f6d12e34bbbb727aeb05e2420be209ea6ad293a914dc6cb4a6f41f52d95811c9c411cffbc8d78ad145d23d001a1cad073560babc9278c3ca8e738f8e984cbd2ccdbacb2cac6786ed5e4b9b59ac37bb9711d51ca40f974209c7d5ca379e77ccb36b95c9e8403e734e0ce63c589da736bdd2ab163286c98446df35feb53b5b61161df4ab6e5aabd47a735b22e47d5567ca725c4782e7e36d7a723783cbbc0a2b09cc3a2889f88427bd0ab6cb41758fc2988167f5cea05c91e00d91f80f5b173b6f2ab509891b8d5ebb1907e36e3d8cf477f562dcb8abd7275f539ef7faa7baade056a61b8ddbae7372922a0f8727852e081689f0a03f388fb100e5cf3062afb5339e0bc810706f3aeef0571c7e3c3dc672a206094c8dfc8b55929e63f24ac40ab7cbe24311ab84fe6b2f926eb2d4f69d219884812437e4375aaf105e84307b1d06e2ca6f04b1da4f935fb42a6cd0424d60cf9107aed09b7c1905257b852514ed7ece022fe4e805c09bf5a43022ed7a5dc401acbabbde7a1da1341173cd669e6669288e65f11a8119b4eb5a36d4ff75429a4b4ea78e5641905140adb5171360337292dd605234392193b4a3bd30f5ba48b0f1b98e25a36f910561aa8f1dd5e3b5221de219924eba84b24f50cba53ef3328d5f3237d33c76de97a425265275097d95fed23b900856574d8e648bff82e2d84068f32f7d2b5673fe43499453506ef57307ec02ba2406abc6d004733328c22cbca945ccaa49040eb5adf7b2948e4d86f9354b2f80c1feed4c91c0dcdcba427b7b6e047a54959dad9e29b104624fa47a652da9828e4fa754405295da4872a84e6e1db7ed2387f8a92bbc626be51a8f75b36f043ad78f202b6f0525f77f99951f83d580cb4c1f47a9f4c4918d040b059b7068b9f931aba13bcdfe8b6362f18e5b26157f39b92ba59c1a05be30d43e1be261e5db6c6cfc127f9fa79415b9238e0f3021d5801347f5041a29f1913eeeff1a99b2b38233f73b14cbfc8b9ae968a2ca6d1d97694b1264e5a37ac19cb0aa661470fdc7e3ef1ced59a9baacb1939fe4dce6291b30d4f07d3c3af91567a7c15cc2724a3731d6f21e8a03fe00ea47b1c208390d9a518abbc97d65b92cf1fff96e600f8a943745255a8b2fcbff8651e5141795b04294ef063f9dd76bd37dac085973a49d37c1603927b612cb5d9456de9c653ca04ce5e6486c61d3345b4b817421057aebb366b17783ba57d7d2b0e6f377f459bcce8d420e12a6532abfae995308f7feb17d9ddc7faa67ea59b64690bb7555fcfb6bc5112ecdfd55f5a3c357714541a0b66af9926e13ba169b8a57a5e1a59aa67cf192f2089a7261262a3c4f62723ccbc579fafd978af3ae674337a79a345ca07f20e6b128f04717e246b99544e16495c1c3bfd15c8ec092f73fb4ee9b0263b97295f09109d56b27e80b261b6090a6e908e5375c06bb69eb980dd2df21d1397fdb0e300b5e9f121b85ba42c8cd1bcad0f470f352349a5249a5ce7be5891f611c8148406b1c3d7350922dd83ee4613030043a5f8b2711982a9646957fbe3fd31ff6c07ba460c6d1a087fa1b375b6d49c115f4d316c98899eb5a3ce7897ed0a7d7c2f394782f4d4dadefad54123b8e5462d17a7ae7c01f51961e4acc93aa013975c3210be430afb67b00591e815a878827428e8015f4e1427e35f7b48e92205855d80aaaeb8ed3a54e9c97ec02301693a30859726b2908bbac7412bc67f84977c7b2a822cc86ef258582a5764a398741514a9e8c9342167d90336198297e699a0c07ba4385b0c23e78cc878c00e760821bf2b207ca15f53c73316861e40ef4ffe055b96214d64a10621cae6047738ec4f1b71d3256d69b38121badbc1e2e0c350989f861324b2cdc26e6a1930326c73f82efd570b41a8918113ead45125107677eccf8239c3fe5d8562b7f9d2448660bad6392575964798af483f546a6aa87a2f0e3bec5a42f0f862a3ecc9428782386442133046cd1f2353106f2b541c000b5e2050ca87a5ba5528cd3e0da025d3cf9b49bd078b6fc477ca9a74f976c246bbe219e5d9b00866c2ba8be0f14ea5c38a2b307f1729ba3aa14b1a7f142b4a8c74d03dc914fbdcb9a7d196468c7a50ef0b594a5ef2eba74bde87009b0134c3b0c7b8c329cb46b9e483777e71375ebed7260572240ca3cefd2328abd7842863c2c27902c0f407c8c647e4764f3d8d344060787d5ff63d42a97c3298f667e8fadc4c6bdaf9d74f458cf88283393a7e709fd2182f61e536a90a5f645f3b3ca00c358cd4924265e8d5b53db5cc5ba32d4138d939572b5292580f595e582cca6ea7daac17dcd5772abe9e522cfdc02c9d8adec3cd8029b050e0c0afba63e523739a24774be19013ee633fdb6c2220dc03ae5264287246190064ca44983d7b060038785fa70c52758b23b387c44f1868ce5008155ab22a911a03ffca11dc7260a8032533e9b7a4df88b17e88f8e5f13efecaa56017c9c11dc88c1cbff167b18a5fc20fefbf013a26c18ec3937f6071b78dea532ba3107e49341ca58d3621b372afd98ce883bea8a4427547e9d6a2328b4a26bd88c528608c80ba40223c2764913add97e01e847c2171c61f4167cdbfe696ce3c4eab6c43314e77d7407216296d0751ff51f283a7cd166c9c65ea9b4c822a5c85992809dc8f6a263b48b9744a1e7ae23d051de42964087590bcd3dc715c9f544ab32d92a898fad51a0fe08dfe881dee21425866eb53ba262c6c969e72c112194c708c300004b2a5ad0bdb8bdf7e8650c49bf2a1df9bcb24bf701d2445c1e650243c5cda4c380afc756e207fb31bb9067ef28818e2c8c2ee73c436cc6cb8f665dd1a528653e1977883a963842607a1c398aff58441bd2239b1c20ac25ffd56cc03740b5595943222b51853d639f03cb1251596f41d919cfc65c0d8a539ac659fa9aae48ee976db1a68ac7b18e9f88a3a431de54a4a1abe4993fab128213ab90fbd12e0219d50cea25b7dc0b08d9bcf06d3ac36c9c2e671188e21be3c844645b09a1a55a5101bea1fb9d8752ffbda71b4cb6b9d01392be33e7df43ba4168191bac3b3a4b6ec2264f5b9b2daf709ddfe698f0e70b1039463138fcdd3f1c98a0ab7f6fdb1703dbd7d3ff7f43d1071af2090d323d03615b7d25d000811b8791be1f83447f0b9bdca761b8810e96787008f5780d94438211df3ea19740052aa51ce2180fd186843495b11de24d9010306a485dd8fa90315dd686437ceef8a05f282d2e89f69026711462b032c411b51f89cdc8ccf5b28fb3a25f1282b8582a027aa9fd9d9976ce265a92be4e0f91d4c930dc95e845aa6645d252dfb616494742732dff45402fd9419a791fb37e8c1dd4531c5e3ed068856a81c6eb013c96f4670aeb08bc0c93606e8527811617d6b53a9857331a2edc238f9e7e5e34c470ae2a69719b5b1aadbb8c78d6ecd3bba14d8f3f06a0382420138123bda7f97217e1fd9cbb6cb785af0832c9c9c1741d8ff3b633dce14cb69e9a54a07c7b9e6a02bc4730ccbc02b877f9af468854354ae719a31345481d9ae5af425e8030ea4edc4d768ffd039c7753d465095a688cb949723bf53f423a8d2521c0232473fd44a86dfa8873ad471f840021b306a0931404976623d2ddcc18aba76fed80425d5f0360b84f01a6c55335380d36f8266dbb075a5e7ca748aef8b464536fee9740a76273b3a7c59f310e46f2bf0bab0c26eb70bc8d4393f3e84c05f09a870efd18ed70e96976aa65872f14378d1c01ada302e4b3f093a51df6db75b283af3b05e5cb48192cec5d5b053882548c837079ef2d078c4be4d92ff6a9c7193fae763425e698891169c2073b37545b001db85047105861e02c0c477808c7c2596ac8954aaf47ce5d7f36d58ddb5247346db00aeda72f1d1a50c26150a86fbf115210444eca6f21916887182a559248e76f9920e1c2fa51346170e766e66b682d78318a5639a0c908fef089bf9bdcd3e69e2e039bd694a896ff1b74f3d0630cdcc55059e3b01f2a034eb753202441564ed363cdfa621e8c5dc4c83f9623adf8b4dd0a314b712167016d61e69b1d5edec8559360673d467dc5859c106dfd6f989607d962bfd110e1523c8d6b400a32a6c5d1b49d96e5e06a0c47feb80224d753441370c0db8b7f31f840b21259374baef3bd3834b4f99f5e6ea4f511fd00ca840dba44842f3fa83f0ad37a46dc4a5988722c8ea1f340e860274506906a2627cf2444123b107dcadbc3a748323f278028509b5f224bdfe3c2027a11e9bb1af73a2023e45bfd6ab7bb7d5caeb260df67fb8530b8ec8d36299e97ea50e3f0acd73fa5899b9a406cc28df7798f2b401bf5d39e086a58646953f4f64c398c52e3f9c18137c6ac3b8996e7da111ccf83ad467a02f3a01944bed52a808e84c1972d743923296253fe72893b536f394015b4f58a159581744d06638c104699b3d991332d159c302d1b5928e39eee10ccac50980c490c85e4153d118a7211777f482d77012aca14c72022ccf5c26af7cefbf50499e632eb4e8ab2d76b1d29c3ddacd0b5bc1409ead1467f1615dac21d27fdfdd1a150caffbb2ae2ace49754ecd08eb1721f03ed448895c1f4486fe8539da9f188e11d4b11acb3b46beac833616b4038dde18c95075c0041c73a079a2e30aff410a94552ad828e79c590e4b1cb54a201e2dda91fc328a8017163ab7687fe29d0ba5cd98efafcc15da16985683f8ffba42d782c6398997e77d4a09bb419cfc8352ca9721dce40689c7707c8c52347f18044813085ea552131657cc90b66111cff864318af67f4261a4a335ce204e6ee2251f812a80b70faecab4d0c0adccdc1dfaf370c411b0e6d8b6843287e5ae3d84dd99670d90bb2f2b1e9e327bc2e626b52e4d751ef2c52811de5d2e79e3e4683bb327c090b684dec8cf2065d474a27397cfa1a7c019888854f8c306654540f0f06bb7722ccd7c4065b015af83ab27474708ab368ce4c5ecf3eaa91ac9a58cf07f7fede2342eed11a37b0d12691e5a628cb602b94d7def6acb76b01dc2becd6b07c7c3fa731b6747cadfd449f8dc1661d05c6926afda8756698fcfc0136a65a04d9d20350719fa449fccc8cca2162eb02fb0f15187eacde4ebfc7d8e7cf79249eaf65d8a5b0a3d1ee1af4485b44d5540e41c41eaa86c3ccd0d035b939db3317df54791e2e91962c3a18e4310992a147d61cd670eaeddc3f2532c45779082ff25f6081bdab80cf15bc4bad84d776a5b4cfb1ee1fca09941a81c4736deee8562a77c695c5195d713988c55c3878b2865945ad5abd482da30caed992c202095c15b1190e778d786ff3598781e53fe6c14bd82b431ea7de4c7521d07cae6c2902f5fab83793a441b0295d41c77d0bba91a8ec6952bf0f8f13ea276006710fa9f3589b2a2028e1d2be58b501d517dbfbaeba8e106a61bde22d77aecfac16bc0af87cd2d9c6f3d8419f513d336d427337aeed32fe86e0747f9e78bdddae1ee8279bb09884b495e8595084be80c416fe822d40922f688d372f3e383cb39f6ea9d976a04cf5ebb32156c0177d387d0c8093068a6f9336c3d40825c12fe549b8f6cb6624f9566bed6abc94dcfe207af48ab13488c902f6f4692bd78dd83a0d332ff243bf7e3a6c3682f987be31acec29f3626c80cef1fedd4d79ce9fd16394700a6cd7a4824ba1fb53d4e00baf2373aa351d89d046145843019406ce9570cada115cdfd49172452fdf15e0bb70b06212b8345a2f5dabdd8f8a45a7b0dc762f7ff55ee203fd0c196cd4486bb60e8c4467af85d5f867d5a111fa3a543ada650fbb0130132df7ab81447341c96fae088bcbb4f27cdeac1c84b72282249459e70426ed39c6c765bca5b0175514f21897a2b2cae759bd9e7e1bbb14da2e0849d1c9bee2ca63d97d3a41a12bea422427e5f6b9a497d5c97e83e180131d6919a11eeef640216eeb56c0d3f601e4f38aa519bdfd54483e85edacdfb35d388512e92d03aa44c7a58138cbb7614f763d7c2ed112112c6b3517774858548346cfbee6eede6363c41c25401b3098971a6c750889d0b21b5895bcbb74c52f82342f6969f03350073d045721753d3f040f4b04a73e8a16562a8db0044f3486336b6354d659a6bdcf31925e12e2d1c3c01610c11a41c7cbf4ca153eb50de497fec4deb4d7c581fb7ca2367ed79ab1bf2b8a6b09cc758121a7267aff483eb6bb3f2a98670b98d585466967de1a699db56020cd7e693e118b6889a02631b5f6fc0a9926189176a11017154abd4fa6f442769680ad026e488d218ece50e015eb5a16a783cc36775cdb638b8135b194fa60282bf9c5a936416b9e82ce02029cec195aaebf967ac4cee09d41f10cca3344cf542dc057d9939d78347724ab437f5b1d9b3328cd80b7d1547b6e632b712217485638d324b31260760a3f9fa86432eca51890c77136b325660eae778cd47e4ba62e670d7634e6e287ca98875c86fa66009e636df04bcf142249a91498e3f2e5121d0c8655b1abb00ec0753c1e399801c375ff03f4e74cc82aa7280b35520d18aa2b4226d2c0d01565a3f16d765c781f3482031b6830160bbd73763bb91b27ef899846ee13e8f40cf3e4d1c23de8c43c7ad078f43f397364db8c0fbb46686268c6c0dc0c1846f3bfd0628b3b26aa45382b19d48c6b597e77854601b814fd51e8d4f152b318a3b7e5a083896f57d9d207a9b19050120e0e0cbaec18e85d131c5b23afefd82248292dd4084b384282f2c055c5be1b0fe557dd209d9a35c8be676db9b428d2ac9d1fab51206f79c95b711de4c8d0c5bde06373b43d1537b80a29178559df4c79c98a69666b81b06a0a2cc7a196190260bb9c81c14e41eb665581e85fa7fff749a5449b953d55c50e110d211bc69efa43a08f9305d98cbdb609c159779a12a63d627d0427bb493dede741366ae411a3c1b502c81d6f085525f958ef2835ef26511b2c2237079bf848fd002b94a24f890538b11ac3775701c73a51397c4f56ea3b3e5a7c54b71d8734f8619ce709008ced47e2112195dbb90758fbd7341f7ed4d71665564ff5b4cfa9780ab2da340be803c1945e9c321145661137f14980b261e415ed418308ad76f9c268cec61132ced09e8640acac29397fbe5dfe95fb98f8a878afa835308fb66c4d126ae075e00f027da9e7ead9d98249d514b852f4974a382e82d1f1534d4446a6b25a3f3b145774e089cbf19c805dbf7ee66a2ab43d1270a732abdea9b66e51a96c685a93ca28b170837c9128f42dca863cd6e74745c8ecf561d78a3133edb4c4cc0ca7cc68823e90cdbab636b7b8c80369380f881979db35b5822e4f50c404bb40219cbbb04778d88d2570ae023bfc647a5cba86db5746eeda98fe8a2ce28ad8935a7241f9ce05a577f2168d76da9c1937f3d540a1e0d182de40550c4749d4076917f2a3706b52e251ec9dcf6a6a311049bdcbd22f7a96c4ccba510ef3dc78c56399858f0bd6450dea515a4bfa6e21dd492aab6554ec2e40aea2a3381cfa799ef08f175d75289ac6170fd7d26d4aedefbbc0458efed590c0d13d96031d05eb87a67e99d16e64e7a68ad65732aa62c5a582ff9aec8b0bff965946d85784f2030eb2db858ed8b59d7d41cb8709b5e7288fb1ecaaa4315b8c1d05499ae6b6b4161bbe90a6fc36ef3feb1408cf8ecd8ed0c35c8e83518147aa7c3de09328f4f0a4df6a07cadf3ac35fff6874a0ed4a389d0254cb63721a194ec2956c5dfa42dc051f4debbe70372f0fa3910463da35f38e506aac8013aa349db71368c8fb0375076b23f5640390bb6fc869d1ca292dd5bc954f9fbb1c3c1d79c3406a87935fb09bc842eab9bc6e09b23c207e51ec15a418afb3e779c6c2d31a8db137a93579d315e7d61afae5841f7498832205b450664e63abb34240f227064a3dc902db280610f692ddd44ef9bb3b4c85748fb736c646c2b8621794ec95998df4f2f495f3e3d8db1f2c2f13a99e0171eefd8b8af38a33274631874fac24d5f3c62827a7ce78f9925b37d850ca146097fef33a94f366899729fc2e362516e809c40ab4ce43279ce7ae891cb1771a563e3f45817302c595554bb8b614277f5212ac81783d1fac7a93600825656618fd9a88c6e5073c794f55f91f3fa1be24dbe753f83d837b96d2cd3c07fcc7fadbb538f0c1ddee7b71e2a3dd91b221cee6709343a36b3e25a0891607df40d390a14b36932de04ecbe102e7e71fe2f1bd1a45aa27a16a4e304b5d991df0194ee51167032fd48125798089dc10ade81e1c1de1061ce2b9656b6ce73ce00a09b702423565ec0c03ef7f96ee06fc3ba54c242afbecd73e263df497c22ee1b0268d80a4d046d214727d11d94e34c125e758a647776208915a9e0ca29125b4414b046983863021d9520dd1b6a713127c3aa92c9607d31125948f60d6f1686aa8669d7c85bba8f530382508d2826e96dc5de43e997956d175ee52471cbcb33476b17e8f56e2f25207e5c4831505f0cd6e5edeab5a547d95af92f4d829f45720598d1a77fd754cc05c226bc784f28805166add562479a1ca56270b200645f1e4bda3b8d3e960bf8a85232270b4c9869b2b5c19530b00e14290b316a902ae80f2b22cbbb5420ae4f3ebceb503ac06adec7a3e2a73577cc8ce7c9e254abcd1abcdf8f1f1bb113316a7ebf651ac06c9ff21ad77cc353fbfa1c2c14ce3549ec562af5e3fffab56e73a8dafaf150469275e9d6abeb8ad06f0f3b2bec6935115e49c577e005422009ed03f47d02c6c89ae16fe88080fdae121dc88304014017a96e2ccdb8bd396bb544115a54a451176a7a597af826791aa94339f1946f5a6f80605e15835c70ebf3a78df2307cbf2a086ddc5202b03f82299eadae60e741428a576eea6b17d9201af0ef62c42fc21ccb89a1846ca6624dd275cc76600276e15c0be28710fc4986ab8b8bdcebde1de8e8bee7c86843b64dee718896c3d300f4b773d7645f09aa8e2e841baef3822c752ad4ecccee8e8f8fd6f88bbb6e1c1bef6f2bd94fdab1feba105d7be7b1ccfe1124aa4ccedab17f6c23500fee0cbcbd510a5e2d18c384d850bcae28e6a9cfb43c4271abda68283f1a2b4b605197cf06ad8404cf1f3229cb50165e7ca6a7db6fcd031c0a5fc312175a55e974b9f7905a709e57e78b96bc11e8246b6b9a70f5befc45492ddd2780fcb8a4c0255e7782235e72e29cf941be1f65a5a2c8f9a846c3a18e41f06d01819a89358ef68bcc801443d764e0d8c4e846d5bb898a00a4450a12f3468ff660a50f2998a463c8858326b79ed554506d748ca0d627072f2464e92ed1e8b5c7b4f41e27fe499a8c60d2f1543ac4c2e2118ea2da45d896ea746e5c28c24665a28602276660147fff1ce4b33031f2df7213dc49d6cce221a9feb63cdbd8015c7522275f667b500e48231399aedb69e5c1a7308470ce98a94c96aac059cf9bfff14b9e0ea8e2646256a573a9172db0eacd28aa88d912625a3c8de69adcf058442dc79632a9f6809598f6ad8ee97f3fa25bc0f1191bdeb3ca7a4043f2228de5547e27bba57ca14aede788d2b0d7ee5b2afe3948e99083609ce3c1063835850c1d3131b74be3d8cf46f262c9727332928a4ef5021bef079b62828062c87b54a8917ec1b2ad9464f4b7a670abef85d9507903bdf30310023c48e0cfc181903a50598b984188ab2593057ce177033302d248dc69b75107b0c13bc8eea356b53f451d91c020b83d8a323205a073195f0d38daf0d0def1f5e0f4e6c41e35c908304888fd2a84a4e3612828692a5cde7dcefa01cc6f76fe562160701721b72584549f642d9082e63bcca902bdb6bcb86f8a48d4702f6a153366f61948077a3c7d310c73cb190947b41efb7d98c6a0025d34ab7072089df75001cacfd586ad6451b0bc25c3e901ed8bfb97d175204167424145a208c721dedb57872fb0497c76a29595ae849a5278c0a13d8b8cc814f16fac4aae40669c08a4271c02779c794d86a44a26bc232179466d8549210870b4f05d71497876b8ffbe0261f8c9cb4d85f71701f684dd1195e8593b64b3da5ac55521cd41990ad174edf62ce113a443583431f138ee0654866807af8e1db3aaf6ce65c6b0a09a03816e26709967ef71385409280a904a7c4acea95af78685e053ea2383ee3230e4a6e8fc4fe07f803a56e12d676671461a81b794561394a22b198bea625963ba81a9799ead8cd0888feb65821662faa446d7c6fc3011f4e89fb4f30028a3aae8a5a552a5c5249ecae88a09faa5587848a7c5a5062c7534da8c213479811061702e80b24606e3bb920ada8174a5611f3174009401f75a130a7f42b867e95cd1223a39b00b21335accc1d56ac5db1af400e2270757d0dec4f999168e5ee1a9c1576b1aaf1bc726f2eecc2932cd07fdccb3dfef78df23586a52e2eb41017f03d9149da950172d101091899840ec95e2e6ccb37d55c933b90f2ebe7ba3fd21049b9e98a7d26c413b9192ad4edf40d1aedabcb896fbecafdf9e56ebbfa030cae8e3fdf2c96a2887a377649b173cae3bc4737f46e312b17f2fc5ac90ebb1410cf091a81f24f0eb33e27f921d453efb4a35a559eedecfbb499abf223cd2f126ffd4bb5fcc65266b1e41b2e70321447252be72ade795b4a1935fc263c880b36310d47f537bb72aa36cf0ee78f547a68505c9a8b3b0008310f041078b36bc6d684dbd59fa6b1a092cdf2a700118724503908b564f33da4ba94bbac2943a06b5489c309acd3d66c3c67506e643d9f3dce7271470513585e1d80ef6eb0830d6c8a58f8811f6c92aae2ee9eab4a506e266aa1f370341f57125e41091a2b041e9dd5c341bbd7d9cd952a0328e9e25a0fb280ebbbbc5bbbfd19b5a4ec50242635516e410dcebe7707f63dde80d15b16bf0778c64c16edb6fdbb1a5acb61f096fced497830f83d2f96882d1d6c806634399aeb8753e5b66d933e9c27bb7ed732e859c9c328511023442b651dbc91ed0a165c194bb312e78b1c25a32c8f1cd6f606927498ce65aaf35199eb9c335b46695c6dd868596f865428da2a018327d2609048e7ae78a45ea9941b07a0bb22b7f67f55ddc64b746ecf7add7a4ceab36b398a957d855024fb6fc339221adf2e6d8c465c22d8672584aae994b900a91b85be0c41a172860c428b91e9084b06c77cf2b74fee71c51b9e3be370dffce082573c74c6e1bef9c105af58d0fb96938c81946d6c0ecb41cb72c1d54d6cec2d52e54c7a3f85f5db65d7fabb68368f0712d28685ea4ef805b83d636dc1ff020e6131c0672054a931601c1412afb3e16761eb11cd5f65242b96c2789d83d95c7022fb96e00c6fa61e6c9256474f9fcad2133ee31c60e227643bac1bba275806290034ccc76fb8806e9e210fdd3260568cd91ebec672fb498f302ab94b6c4a00d1b57198b7f4d70574a97412acb9e34f6480079e6c106ccc1cfcf98ee8aaae5c886947e7d7aaf7f9f6ab0b5ba1a965face16cb68610c8426049030ef6cf13ef33a6b136d00d0d90c95b480041510e48d99db0b150bf2fd38977a5a7ba3da4a5a7ced344f18382a9df44eb91199dda3a28bd9008b612e2ee9982f9a36fb1ffe2ec5448b6a6b30f433ea0ea67beb45bd22888704a33da3989c6deed665b0a2b6ded7cb6ba95bfb519e3362682c60bf2584fb234309275a8b89be852c53f05ebca3685be7529924a0699529a2d2772d880f1249dcd61e9a785e14a1377704d97fb238bfb7d4613120c81a282d215ce3e6ab3c100e44ba1fa504826b651839c6eda181366d653e630e0c968bc897541daf4c1c520953bf0ea7b5aa86f6ca53fba0f592dad7919296be935e7dcc9c3a8ce3b917af48a0a142c3f0e7513a9fdd805a2808196d33c7765654b6b12b739d699755cca6935b7e81a88d9ad786c2b08eb442e00cd83f948763b05bad5e8f2d79e9126f7481077cac81fc5f92905208cf58ea4824118eb0e93723f05b7cf00431f59c2a3f22cc49b1468a336da9beaa8ba544336182292c510483e178d5f8f9437f7a01485f4941552fe360addde0447fb23008785679125c88826e898dc892a43cbcb8bf8b14879203e32e6854df586c45263d1fe800c25cbda04558100775276d6765e100f38b451be375b7bdc4247988ebc3b68251649ac90dc35105c83914d31d0e22b5484279c3df3f2e56f2431400074b633ea17e17a4ec5c84543271ed310ea0d518d355395b36f5015368a588ba2510939d02bbb15153370caec64ec32de9890db1d0644ec7a0eb8019df840958b1f8b95a6debf9c989ba1282d791a1c47cde6cd2e991ae77ebb6fb7c4bc3eda6dcc3b4753af854b2f30cdff1fe125184992e31e6a4715231220af6ec13568bc9dc6704fa84434141263018f889dc2a13d0d65b99419261f4585a800a47d81b4e92ad32d2fa0505f4ba9f76d21e31b4bd01515c24a593e7c50758c9f7b48db8d70724fb9f455f6864b2859322a54c68e158a1c6c79e047ff63a1c00a2a5ee346f4aecf13b50426c98e71d09831b146ff063dd6c89e3d5a88498ce1bab5b11b7065abc26d7362208a3a46f2accd46117c77e698b61a990bffa0c9820e14381955139c20174ac48f220d3f54dea53d3309c500eb126e9fd056d52a946415b96abab3d86e22a45e66cad1b9922687ced0a759f95e60fcc4fcdb03df6855cce9870bc0705531fe6fab1840b99ac7428261e00516f9ec3582dcc6c47a027b2c2f2a2d20c8800f75e3eaa02a45548188db969a100f8ff40d7af80972301efaac95425f18619334f6449a05ff3afaa2485e5f0eb059c62f9616d6ecc5803c2e487bbf892313d47fa1f325e926800d7cdba827d4c24ca87f258b348755957caea008099cbd5970ee32495b6cc25408eaab75a994093009e30ad6b2d5489ca445b9b2d2aadf46012569d42d10c43e961cf6a8525e164e40cbc5e7593eb5d3f85f63e7d5c9f119582f5c2379314166a6d6a98adbac1b648aec9000b0abb286cc2561dbdb4338c91c13d2d431ee614f58b78ab2382c8983eb6cb9a7dcc1a4f82624b23cab1f984beb65318854a9318093d4f087be47375d330ae38cf923fa6674db98e58de480f0904093c805d7e36720cb04dec4ce38fbe82ef69fe73556c61456b10d372120f4b90f567a9e1c8da2fb363c8a21fc0a8da1b49a87736e714d63e9c393eac7c4a1ee085baede061ba85cbf92224c304be24ee53becfdcde35117d316ec6b7138ba87351a1b7a043565e432809adf6f471a3182ade2fc0f8fc2a731f9d2dd0a269769da611089c21746a00760a176d2c9f0168b1611a817393dcaefdbba4f283b20c0d02d7aba9fa3952818600bb55cd11b3457f7cbed77eeea13de04137a0024da2adfb41b57a9ed40d05c90128a2d313b23e72212cad6fbfc1f62e591a0385981428dfe4e06b4c21181fd6c07ca44244357bfc104558629156bc8db522d373a18f84705306ab40aed49d649798de33391a01c9379e3b1e38913f510665f2a8d387858342d3890454b0b664c4b6e3406d4f021923c3fca9d9e96543c31322170a00d663b668dd33547c7b0811c0c87c7776f71e0abbc4820984618a7b4bfe30a4ac28112bb1dab4fd43fbc28f1fe779fc8006091765d43115d4db204bf90432d5963bfbf569260b9a02915ae022b8728b92132f01fc5ac80e338d36ad8c29e0409b9bbda781b7a86247630a1c7c35180e903d1a29a865864ec5373a8bda333abc70090feda7479a0d842e2d5d36411a200b5340b3ae3b46132cd3a0d7af1b2d07c31cd99855d186b0aa5e0315fa6504c2efeae0aaf81b5cfc0a25d20374d545cc947d55c4a702add29641bdc97a64acc8d441a00babffcd1f663ff6cb84451098987ee862fc9c7d746711d414e301ac4771e62d7b251c04f73d655248dab1c67b45ff2618b9f108ac4e8fb2f65807c9e7aadf3ec81c8214f24e44f5a531df963b2a9e0cc71c39f981f4d2a29497ca58b8172d1a4fa80b419f71a9e3588dd5bcc3a35643e3b221a2ae8b4f639235bea2863c98183ae73d1044d92e89e6dc60e4e008129ee0e91133a8c482861751d6efc18c39f41ae2b385a1e53dafc4f9e041826cdd89e36e3c0adcad0ef66bc6ebaed219c7eeb80b24213d4a6f6ab23073da0b81239489073251ede98a317738d48725ade6635758a7450579b4fdce6b8c7dac295b00dbc2a5a520cdffc3b5568e7d66112ecd18570e2904b285b339c6cbe2e685fca122158f90b0bb09b3c3c2c47e04f3119aa646ccf82619c6dbb162d0b2dfc89f35447dda833afded033df963856f82351fff19a8fcf138fd75a536a20cd5a08d4a3feff8e7109272d04ec9ca59a5028360c7a8dd32c50a3b5c04f9568176b29219bd1b8421f87f5151385368f5c43b4c8cdb4befb25eb1222b04d85c2046bd25e815df3ca89b88c8c6088287cf07112bff491103354bcca2a00c87154dd6bea9a5632e9307e26b804807454cbbb87eba173b185addf07c7038fcb884c175e42dfb527e12ac1991165e17876602622861a98275119bccb60a296dd9ed2758c924def83d68e2285f307cf4079cbb6e2c258492dce437a532838ffdd4824070f8fed8a14092bb70f1ada0ff5e4b8dc10c7e36a4c2b3e95c29b4178c7bbb065d3e6818acf4d85d6d29a80bfc28469052203d88a6ce7a39f99bc023620437a6aaf586635037220d7849370838386c8b2c69003dd05304a6199d3c1681ab4e73ccc5c5aef21d4d7da407357b6d24c0c6abf3193d115f65ca32e96708dcedda4aa3f924bf6b5b2f004af4b8d597ba3de3858053d394de9722a3bff2afa46f941868409ed08ee31d1cd58d8903f28307738824c84908a035f04b0136ff0fbd8aceef4ac645a665729802947bc87de6b6428a4ca98b0d370c6ec1a923c0da534d790e96a3f144cee13d9a598bc1cab7371102e663a1daf73d7904a787e8144d18e1f089758404e1fa956e2ad5e11c3f36ae7d22ebf6b43f3c824308494ebec9134feaea8d21408347c90fc7920150ffc34421ed926e309a6899071b2ab40d3d9ffacc4118c85829f86f27caee0cf430895f8fa3326b1ca572a612f74786b684e21adedd1c0110e30ed8d86dee260b09885177a304c7b663a1e920b480c7328d225e58d7d170ad551ac53ecdf9929562c4587c9a23ab068e69d2f5b738578a510d5d82452552953e59f44e73659f7feffcd91c7a9f670b06eae68950ff831e6fd197e27c241a2b029383143adbd76ab82524ecac10d107f6031a5727bea6c40be56b3959037ad25403f4cb1161133f3dc8514d3a1a46d08d3ec1eb0da79bfdfdef20152c8222f2e57488c937014fc15a1eac565709366026687aadbbd55958b9953265305de202dfc9483eb456e40551b1852045b70a3067ebdf5445a12dad6a63beeaeab4bc79dd1857263595ef440fafe8137175557824a95ba84ad71c285cf2c79d683fde26578f556b1e05b3034ce7d15e9bdaf4044724d2d986028ce52c9396d4e28ed0481bf86d47cb2fec0faa870d08f259dc23f5202048d6f1a700284447ae18404bb024678309de40bd202d26a7322eb9670770069db861bfe33b13955be23d53b81695a0327a1d79573d1b8764a9b0490a0c2787eea3037b29d6e2ac83477839f6b0a280225e8d341ccb708c18a161a22cd6cfa1db2814d0835df1d0545e9f92974fa564cf1f9662d7771cc592a24186b1198273fda943475a0da2439e2d20d256374fa7515c5328ff3614cea17f76cdf92d9c15f239698b87f7873ff1d29ab168a5e424d8b7f6471a99b3e5711db5bae93ed6afae6d231b18e089677164e1d9b1d2089c8ed0f4687f2bec0683481bb2b7c0540719983449a81b628a3fbdbc1152602299995388309ab4c1b97683f51910d1a0562aa5b204be0cfebbeacbdfefda7ac4673719bd2717f2768559d492e4e9983c5b9340a44a6bf5287420eae82502cd11a85b1590201f1264c82bbf9c1031342bb6190e2ec91429b704af37ff68f9eb647a4881833ba0fa1884be8633c8f8091d958ba0ffc2c65063d30175888e28c236e8a0a65a5d6f5e5adbec0271dbffdce13b3d56ad71000b5324cfc4db548c16ed469632b712e28002a9ce83e5921ecab02e4dee2f8734bf48947c7a0a3494e43a42681433d63df377811e87c5b81709b980c51a7811ce1523096a1f26d8be9b275bb4d9780390197751007b33cfaf194b36d4296bd8e50b08f7fe88b1ddeb7dd66c856024706d12bf2d707cd5390d163a7331ac1b5426c73e39d971ba998aa84e52fea08ea64b4401963d5506f8df04dd511747a454915a24b0dccec7d977304f28a5fc730876ce3b9489dc7829769fa129b100e89dfb01bd42ac1d2c798a3df5b936515e07b549a7ba8441b6f183d04af062da256db779fa49a8c04963a7a760887bca84bb9f1a961d334cfd11f3a012cdd2a0b4781f22778b7694f89ceef325eeb4226424da54cf993f7c05af4632afb459b3141c0a9a1e4cdc44a3b63a3cd7cc7a89e50838498c47b777cfc5e390d1600dafb08f853cd6969846a6fdd355ed82d982aa5450c81845ac1fc93a262e5f88880e8287f6f64783cbc440612c8522b54c062b01e44752a41d2a2c7ea301997d531bd4f40b9b31d7009ecd33778d62e9fe1ed2deeb4d9f8746c8384db26782087a20940d9299429d5efcfd07724bf9cd28eb6b4d2cdcec68424e24a54e7f86bb6c9efad5cea0421215300e7d0d536e9a5d068913800ea4060176bb5457c7df878e570a822a3e645f9c8b14d25476c6a930c12fdf6d2c0b814f90b6670de90f969a02f0ced8b22a59c515f9ddb22ec12b2b223c5c8151074411280ba800fea92b421230760e915d391034e583ac2a6e6654d989108116382fab60704e24aed63a47ad7f243442d2b71f6278850b0830ce777b0cb3ea91badd4c0c53a8d1ada3f6e44128e454443280676e4840d38f770d40b3a138840dc332c1412845ca12d9793105aa1247354d93a9b007b761df15f2dc65e74c0b32253a83d29f2e9888d3b45cc2521d1f84f681bd758ea6b38ad8e0e69fcd5fbaffc7deebf3257bb901b214d9c21397d0ab0c5566287d4f0452a59e5f98c263813aa8957faca0c2c0e1f619ec6b60dd3a8993d5db2b0803248b3f8fc02a7f5f7ccd55a17b8bd7a950a6369f59c9d5106d8b4c6c12eb71ab1ce58c1c8476c14ffb008f986dc44b54024526ac74d88325ccd78469159340bc7f77def16f1e78fc494e5162b7977ac7ec08d868bf6b1f1eee045801c5333bf714336daead98e76ff9a0e1c135c566dac2943afd26f4f1f93aa5715e4b1c234b31e85791fd008b99a0145d8ca267d5fb937df14fdf422b13f200aee39c14f5bc0d836c7acf6fa66e5547bd6152ac514629b75dafe107c73a260e2873870bb733bc5b57d829229a1107873b7b2cc2e02874fe374ef711c4296e0ad5c036b0f233da94392991cec6f397bf373ae0409d644f6319296b734f770251a58653fd7a30d62862e50cfb6a985f652cb0791b9b5327994f661206d11d3aa1e9f407a9fc928d2a527061dee4639c1bd5764843174ae440d50b43cebef441a5b9dd26a79ca171210ff28f2957d5c723073e73783413871b8328f71772608c82c49b6516ad8e38a1c986d6a554cdc501d72aa6249ad49f1a75fbed5ad259d7b5cf0553d4ae0f24f073d3f13249c5edfaaee6715149de0117732606e53be0e224269463e986e0f863169959bfe124b54824d870ca44434a67396c3c388186560df3a8af37da818afebc4012fdf6f36c5eb935c54b42de4c087800331cf20824649c5934cdc942133f624c104227870ebf3af5f6aacc1a02520e258b73212766adf33826f32cd6e654560ccd6ee7ca359c37606626e1f8ef818ff43f14f7ad6578e05cc167df9514530be33598c49d21b19e09bc952c4f650dbf7b2339f8040cab5cd5e2df925b94cea48b33e582495149d40ae030052b94522c6b0d96964f5952a2847d38701b3f63d1dade9e696043d6abd88a3650c634294b18102476ab5064937a8f136ba2c0b2366cd9b0904f3677b74209460ddc8fb8e611cd6e850c43702f3333642a443fc962d66a2ad51d36a19c0c9c2f14ebd33162fdd8c2a9a2fec932869e3840498ca4e80b9a1f9f05bd9359977bdbe27135c926e4db65f462395e090ab206506862c69a9919b1b6d13450e8ebba5aec76ea8187601064c27256ffc4782e17b06b482ff28c96e51affdbcc88bbbe0377856b20514f2a7b8e0292a1ab054c98b730fe9f820eb9bad61c4dad53b4a089e4bd62d70db9da1bcd0cbf6a067670dc3436596b1ff2014e98e1af13562d53a6f7620fc762f011602ffa7838873ff534c8c22ed68d920e68e11194136e97fe8670c1f2ae958b1cdca028e28a9e691bee291a12f82f992e8023aaa7a14d405a5e400ac71063441471c61c0157dea39fdcd51c73dc1ee67279aa902569b55329367d9bb6ae737aab4031693ae67831c83d62aeeb489c8fc0c4172b14a1038f79f56144ea8a47b97ed69f4127854e6cbcc8583700540913a402fc3881e78c7ef8dd73b09bf698ef1d9635022cf6a08c6d93b807b3f6eec9ad21225161c695ea7dfa5fee89d273ffffe5beff67f7634ab51c88c78c991ec866a68012b5be46027d1636ccd01dbb338e2c09d06bcfb6cf2dbff52e583bac1552c9a518cb2f059918c7515d1544584d338eeabd8965a7182ba559f99b0fc0a7ae7888ca09fe14b648956bcf1e75b903a2d0231b59c4d5f3383d0c2010a4f54ce53188a509a37877aa3a284c425336d0a6234bb6669d0b0ef3f681aa5dc33e8d6489d35f878e8a383a93e5e664a84d5f4af37aa27dd99f9c673590c038d625538114e74548020fa9521c95184b5dc9bbeafeff92c0636e927a5a361d3280b7ade82cd12add5a190c4f01ec627805e46423e03861f20bd6c92a9a481bd8a74a2a0987456118e2809ec8e02e9815dea57cb78198ba21b46d0e54f45fae73548c948d9f0f6b620c24b2e6cadd9f71dd6b9dcc7a281b791e9f7df97c44e73592a49ca049bd072a7df91987c77ba92b101d4aecc43641d29c55334b02ea864b926182981558ca4195e9221efdc15c0cea5222b37d38dde0b4e57008259896b636300f242e1886919d5e4ea1c96715d456362dfb522c6e6065ef9ea6d2a3b6ebc4e73d235f8c3721c174f2a5f37517611595b0a0817bd40b0af7371436a4f2d65437d1fdf421b5a50470b24af3b4e5243b7b305bf260badcfed6694e43180b1690f4deb230c6f6a6f0ccb6ec640f7eef46220661f1cedb66667cb794081c60edb4d873221c833b04e7c967cd7e417903c54a4138759a5e0b588e7baebe08b20f2c2408b932d12ef494803fe64bacab673664cfb998ec3f6a370478903e3d745a4e50194a80a7e39000a3cafc7d18c7aa1206e4b2824212fa569097b7104a409c076801ffb5c6b2b7963c3cddb7821c172698036887d99f4088419de8a547b8ed25dac2fa656a9397eb85e9af9352f358d69cb6546b9b79662812e3ac9845f561d8acdfba6e0786ddf6fdadd73d01cf16b806ebca182afbdc9230ebc9f47045149356b3ad97971c1f4dda0703523b2b59cab960b8db4b30299a796667a57d306749242d8231cdc2e9b743e9500648f3b2ae22d32888799775b38028526241c996999bc979a36844045b40ea4167a123df2c1eca9810092d449c24d91f935c570562018388e7a1af1fa75cc1f75accf39836b7a8e074369baacb4980eac022dcf3fec24bdd3cf666b73086827e6750b7daf69cd895b2aa95fe2c33b05e894aa01c06de1dce52bec46ffc814c5310c12f7e9c5b4d24080727940fae20b3496c3ea682af356f53c721a6f179d5cbdd7261d25eaaf4305e0c0f3eb18969617f95598ac8276a794baab7040ac8b2f9e74766cf0b6383a03f7a6fab12d5638de53ff03f57acd6037ed7f8b6609f65384a5fb21d178ec08871e37c68887f919b18de7842c5d604460fbf4a9c7a517fcaf075fa47a01f1f9d750105d448047a1d10da597a1a4f088f30497c97648b92c3016dae7e4941f9932b589de7b25637e460016815b14cb01bce4d7f10b1ca96b5a685e88bc21682bdd588104592a81a7260dab10117f562555713d6de414f18a72d3c4536044ac2081992b100c952df5d9102207a059a519024ae1558160ef7ea4036bc0dce31fff2cca804dd6857e52cf9a6cae10e110ce4ac317c0ef57f61707ba1ef4c0e9b078838784a27c3fbc7646329b6692bbd0bd8b76385cb9743ad54793856543f4ee4b9f77446cc6a186d021bdb434255cfea03c5520c1b74201d9fc30c524a5ec001b4b4a8827db3112fb8ff47e32c81ad15f55688219adc9c1bb333f8a99c60bf52ee08603c498b6c899736683993cbcbad890ba95c02c4942c721979195dacf9af81f6348d9bc814b71ec15ca05e734538b7839c449b88051a61170fcc1bf6a772089fc9131274cd6fb98c121b42fb3f767899829c1b5859896fdf764db7fd4308d6a7c7105c063eed4b72b1087c51cf05059667f07601d5720695c8f440d4b3cfaa5684995bfc6bf2d462a33604abf3a3031656745aee41f369d0aa63cb3ef6785e40e6aa4ea5a9bb915963a59eabf6715ffba6254282e1803d6827db8236ed262d8b2897ba944e381fbef0d1a9aa3e139a7d23ac24fe004911a00106e6277d441065043813d061ca72276434281caa9120d5c0ff34f253b778d92bb69d6b002f3d4bc5ba8863a3d1bf7b542249f9968b7508f11bb88b9f2d83f162d2e5122379a419c0e1920a11b260efc4d483acb1bdfba4453c455613c6a74213e14a27f041aaaff3da9d8215929f0496b7c19280664fedae217d1e8772d521a67cbeef0923f319416d6b2df43af0b8f264827fcc97c9aa350e592c409dc9a502b614633b1e77c5ccb84f0c01ee9680ca8ce9afe474215d9bfcd687a49f089454786faef617307e2e90f3872ebc4001482269b2ca5a00f2123a77cc85e050cafbb37579a61c776152897f641fc27901846fa464679ee75d9d8a61ac3748c07e126d81ad83adb8410dbd611d06c4cd45d4a5396e6a3e3dc1a42e814adae94aa531b39d83ee032ad6cfcb9256f4cd507f510209603c413685a28783d3624d9043825f7666731049a0ab2c74e1adfcb489aff305c55886d2f00c4dbd24e64b7cd0f134e0b10148bedfa1e4c5326e1178c5165ad8e79e2a0fb8394b4a4b43cc5b02e8d3f80777972b3f2b74abd8c74c1af8e41141ed2a0161b5fdccf99196d7abd015f1ad4b6b0a619b64bbc93d8ed17270c5a1d8979e4cefe30157d3cd51270df1208a7bd9d9a06f9ab863433118787e44d1e98f901b986a4507fda2ae7487251c0134fedb8a9ae98add3e7739aba3b01cd106dcb03bc28cbaa2c87b4ebc65c903c53f247826de7e1e19fdeae0f22c276fe8421d00e37185d517756d056335b14f141e0494c14767ffbbfd331be1cda519cfe9136ea6047cec64caf3e75ca644f8801b535b0ef17b6c79bd81d618607357190ccaa1362e24ea442945449396503cd11738f01a58202a900fe39e85ef66eb50a2f38aedda8f12ee3de8d6e882da84417bd0fbb0353faa7db1e91808d288d1453c89c94fd935b351147dd884f0d36808dd0ac532949c03852c50b44071ac51ce0dac2c734a439fb06170a1d27b2c338532ba651104c6ef1be80219d152845b9b81a0ab63ea464f6b8b446f84d25ca88523828446271fb5d03ca43870baffc4a6fd8cd807b783c9b0a2811a39bf972d78e8bfdc622f6d06c65921d1acc664ae5610cb9c891a1136c1394d0c9fbe0e7bce064f1c1ba636a65a5f8069ce17fb915befc9208573df2c0f637979239e4306290248f7047a7d7c081bc2aed2f2d7a34b8d30e835b3bfbf3e35dbc00248af11a12f56d1a911d8d1239d4f27668f816a59c5d876fbf3fe3a84f80390c80867dd40efd397e2a588c013be990abe2a378a86e22c37f23bc1b000f039997c4a777e800deb2c2029ee66c7ef439467b2dbcb903e1475fcace99ff87243d55be078b5c5fdb9faf4065b8515084a6c8b6d70183519380a5b8b4529e8ec2905c5b1f38c68412aa7cb84efda5400226125a52e97ab5021f045db8ae9b0a5b7ea83e6b6e55cc5fce3083f9bb001cba8100f544e9c8c3182e0fd9dec1bdae7863e14ba9a4591bc0aa0ba6fc72d9453f6e3ea30b55917c310b7ab4a71f764ba1f472d5c34ea277d9babf991bab50749ca1a097c58cf4430610a4d689a04346432fe3e1c5fbd3fd8bb5826d2dcc020d2b04c0a89349ce1c83931399f7c1ac3d131ca91ac3398cb82854f0147ba34b112db2a1974aaa4273c6acd212d6db234433a75c60f8842d8a0b70758f9b14d2836a31162914d0adc466f3080b91a646c4045e4e55acbb180443e580eb4c3844bea261d55169806ef88f8e42710e04c5dd1fd2c1accd00ef1617b8e36588e221e75ddd13e7c4056425a3920d4cd21006ed386affc302163d14712950389cb7b10bf850be17b4edbc37e702a4e3e3297778de5967ec3f4a23c2c38cfde54206fc11c2fb9f5302acb0aa43f893e85329191304645a5c227cf79517e5f18c7413950ff33e3035b9d905267bf50ae08cd34d732455e6650a1f7dfadd7d4f58059d29250fa20f50a1412b306229974d4686e0173b53a3fbfddd8c887c00fd65004a88795280d0ae6c8331651c1b531b4c2f191f997a9b7ac8d33153d84addfbd2f89f88ea3ead4c00c3fe7e594d0a906e5ed651caf29dc71a2f76f60397d637ac630eeb789c3a5d6396a0505c40eedb8d55c6a7d78a3fd0d868a4445cc163b22370e14b4ab0e1303c58531ef69cf01882deca26b8762324a1d4310b993a6e5a094de9072df41c7fbcf7bda8f6d8a0a0269450ea933f5d5d935a4ae28c9eecded770a06223743271154435141c88077162a02370d78d92df8b1f8f03b06173a05be2f44dac0d42bd5cc7510430f04e518b0a6a4073e18220223d2178a1ee63ca20c70959bd319bc1fa84160121b7dc359216a28285f5967083f0a8426a6f251b617b790e1494a92cc7e306dfb68762127c56ad3e2bfd691038e0c0597b1226f778518a9e00715fa70e8ae620aac20df852dd15a9eb3ad68a3c9d30c810b13b58127cd942b1fc7ae24c4011e0b2b3dc3f8a72c97920ae3a991052afb8b41ad892d4e8b8b6fd13a20cf0007fd421d0faeea81768001a395e22ea2575491183f02464a18540a02392872370a67b1a4b6cd9d31e21400423d23288071bdf7504c1629b63c97e29b431caee722429d56ffc14db85ae0729045dfe8cb02a71774d2e98c5d90e3716e177168a3c0cfd014d30a601b95e0c5232e9e32866cd98012483fa4c1fab942e90362f1eb4aaabfa6eed09910e529d92b200d5397e72c8c6f89b594c8cb5ebf7e05646a425f4fb5949dc11fe8effd37b3e176e64338710ac576116fb2ebddd538d5c1b10e11dd128d258c2e49826e1d8d96619f011592b68c32b32bad30fadd5cba1149bbcdf4563e1c49fec0a7cf51f8a4f08208943a9b189c7947b5b37f032aabe50244b539d6a8909231734d38d3975392292ab00fb6560a59f3481250fcd98f56a71a06138df6520712633231a8239ec2403bc997aa86b82a59ba40db468e620077dd9f1ebb3f470104903391f34761b695807290fd2c9b941080910dcd51e9a9ce7e23aa2e9aa5c40fc8b64cc649bee895256f0ab5453b01e5b695d9c59ccbbc364499bd4973cab43d94313d3fb40753501d7456e74341c924e151f3cf97c19e22166ba8a33c4f7329c547c42fdad7c57eb529a686c95ad71946737dcb48139d3c382615a77248736e4dd864ed2bc7fe3ce273563b190e60df2f8bf8a26d3f60c1a1d7a291974822e6a33dd78e6f7014b52b42ddd809559c587e102f577203c311832fafcb15774e369cae5eb0af2a829aa259d518835ff3ec63ef04f5d81ca2a9a4ea9b679f2db08aef6d38b6c561b4b252f600ac631afd3c1833b99327ec3fc569bacebc94554952aec39e12c3c660684239867ea866778626abb2825cb34e4a49138516fccfffca7798111172d01a2ed8544ca36de2f17bfbc194db7b356b3d3e77d1e720a8e5355d9e87aa26543d72ba99992c3240eb2261055ab82e911d73df1f49e3f19ad71e61162c028cc2f5ac8df655612052d6381bdac1f90d3987ddf6a85af830551ad47729941b58b2b027a7442886132ae15229d31da01c6da4fc1a13988ba1317018b8ba64976b24985598c0151f6a19ef53b07e8fd11b3d5c86a7d7d2b57724c41f9ae5c1d5504f8344879b7dbd16c581b1c8975350e64689a8dbb99ac7ae88a6d9397a3666be1cefe5b6aaff98d6f20f13af9e1d01bebc3db832cc6cf86b20c6aec23c5bf23f175f0b9cf5a761d3e753cfb84f4ed248b22dadb35f17ca8ce7fbc8965e465632573b2573b59167a92fddad7b2a70e056e0b80cc8c19469c9c4437cc16550175493ac93708d42c19c21e8b70a4c60882acc9dd9c9448b7d5f6aa5c43c62035f758008d8623d2b3280ff20e7920b52d7cca9c121613dff9a1002a32fd00e27318c9d1876f828d9700f153483b8398b1c87b1072114b81b913641e3d061ae4551742596474ea41ea2b82274b46434594c340d4fbad4090ae9a8153a1469060ac2c076fadc76b72467aff2dea34996aa73a2de2c240c2cf8c54cc04a4d1aa9e451da3164155c044a9bcb931f885a57c97b239299810616e626d68ae1c57462cdc45e47619d7037650ca0fb951850df3209ae5f1362224f6426cec189e457e80c49ca5c4240490874c24027408484c01528b2a2154a5a7c23662ac4a3de2f258bb1bf63b75c344615adb35ce730de6879b6f435eb64b8ee779288deddf40e8f24419f6a924b370669fdbb8cb4a135051ff8fc7f7d93a99799f4dbe7bc39bc24cce0878da267c24ff6b41a84d89fdbcdfffcd813aaa9db6a17155083c004da0b76462462027a87309f12a151f87947ee4e8fee7591473760663044428686409a1adec542583479d7a19838e0d9234628abcb499a84f3100ba3038b1da33e55600f78c2f5e3e6449653d3148a0034b75e2ba344c6896c0f314f29d565f91786df562387dadb47cd81794c803992c7a521f28f32e0c2a907589e2ea6790707eef02b0c1225ebbc5399a4247db6e4131aae0a38f5d044a327c73f3f84d8a9204945b583166bcd8f8fede80c970a54129d814a5584903aa23e23ddf4f1c18d153b6880faf391dbe42fcf2461ac5f9958cf5b6534768fade0588564deea072ad6a0cb68ce19188918a43f1ca4b6ca6eb754f2e6a68e6e8279c4aa0cf5ff547b846f87e0189748263bef4ae09b8a7cf3d4851f81dbc32ab25b2c49c209036088a16fab6d79430d4569638e0008adf5f07b65d0a291dee5f36c0aefc85848597a236185e3b97bfbe19f6199b5366f236772bf684f63ef472557b22f86e661792333c6dddc5060c4f885ba39783b87360be2bfc0cdb508b011431d01ce0c2586381745f90a2ccdedf1267bea0785055a72e38247366e715e7fcd2c8c8b117a87e2c477fbd431eac43277e5f476c3bbc08aa5a1e29c1440ff358fc542903aec700ce3a0bde0e25e08d2c5f2fd0f8e4bc3ac953e100095ec03bb0444f6b094a55db893ab70c149bbf1bf76fc50e10a952a713c42baa347686ba41614e9d49fdfcf8ec4d5496833490de1aaca848fb3c7e91c98d39f3ab26b343336f70184be163500ead74221e8567b92c80066e301124b1b1abcbf3aada61659d8fe301a3604e7a7fc906399c77787e82a94570f2e6804bf4aef2fe8091143cb7bcae8d5ff7d83a6c6edd990be25fda39dea205ff49b19f37b4a77f0e5388159cbfcba7497db4f250b7fb38d7d78c8ec6d75d6359e4723d4f12516b58df037a6b3065ae05db1bc0ed7d4d850e3f616e091d15e04cfbbb8a73654cdfb86f95b1fb32d73fe38330e9a94807f25ba2d2bf0ac3c313702f2a838fee0865d82a1206cef1f7122ff5183d40cc86dcb4ad1f07d7bef5b4baa278c9a03cc600818b8a28e5417df4c49b03934ddb98a649a83fb390e045eed4826bb148a2086d6567cb975416a24b5986c0118eff4b9300664082e520dc09aea1ed2c0941e42324a64ce07130f91281a79ab7a5fe1a9970cf5f00549460d0cb6fe0bca520bc6ec4d5f8c267bab9c0f205c998203f856259d622113e36f5209917867227be7ece89805ec26ae4b82886d904fbd7ca74b8658131296acf85c83c8ca5ad1db8aaa4efb5375e74aaaf1986ebb8c3eb75d28202090c87f0e1950398f420899a0ff3a8d6218c0f55862bb27197db3c603bc48bfacdc20e704b3e3eb2e15dd25ba154b7e55b9876cf63a6fe621cb50e2e6b90d64ea261dd14f41c4a4d1d36a74dccc7e9c10aced4023880831822ec63c263560ecca8d92f2a62b50d8df5f9ce4ad8e73816aac2ebd079ce96b4e225979064ce0d102a4b7d2b2b74faf98a254ba712ab68c4f3c23140449a8c0a2af8b8199cdcc704e3f03e6aad5237e6f5f66c44881c4f2ef92030e47b3d29ca21f65be8ab02b2ca7c98b09e47306bfb43b4cd04aea68524f3c67580a9d5442caeefb2aa4571abd2c95b4f6aae14ef5dc9e17a9f6984ed286ffdc40d27f28c68ce9205f84cb30ffc92761e2d42961eb3bd94859e3ba7c0a712924fc2b4c65527b84e6f2ab15799f946ec4ee37b558890c0cc1c448e7a91be3ac773c58551c5dc06c91248ef3fb84c55e2d741ff089d8c2a3287572f500961371427c6445f1a9b710c1e2135e64716fbde2967b5fe8d132d33cf868340a50276ab6445461fd230decdb3ab0362452c2dbff97b17267aaa2c7f8fb0a6c3fdd8a824d860a850171c8c98d5fee81119098f76a2fe2582e078d8dbcc55a8a7705294aa9a5bdc2ad180de97891620e62e2e14de8d59c6152631cd095398d69117060facd8c614d73d926480dd53f90cc9824274c2885a31d096f7c37b5da63b3611cd3b817608260115a579f94bdf8f49e47fb4ecd1021d8a62bb9ee7bff21b09d417e575e62c5b256678598734c7e1a560cf67277d91e3e2f14b34b68aa0d3e1d29efd9a7ec583878ccfb21cc1b60b3a1a71a765404e4501bf335980939fe550319be5d4d71391cdd904b3d7604cf841db469f47b8fa02d89ef4bcd3f1125b33326127abfcd05077505c7678bf77438879631b9503b2ae1456c1a27aa16feaed7fba66470547a039cc6d7321b0e103918e39f8c396cba094104dc2abf8893951427465c8ae6967e8acfbca762142e8755534bc15ce537cac80fb7167854f072fb3c93517d8e59a47ad19fb0f36b2e4b66c86937cd334d8c803f2cbd6e6fd195312139c02646036ea685dbe1a00c9b01eac20edceab2d1be2fb862a4ed033ebb44ae858185ca028600f5913dd005494da36f88b5d0a7c79ab33e05859b102f8f2fab4bee2e2b0453c1bd027c0a044a89ebb25720d23a4a07468e7f1fdedfdf73aba3d7f3580c2dfd1d383dcc3141b3504ebb092bdaa1a7ad7debe75d9107bd634d4e8418dd5961eae779d69a7b68e16a284616245d8b36276f3598b0686c966c42f6de64cb2da59449a68d0a1b0b590b1fe633689a06873ad730cc34bd9ce498a3d309769d5d02e110f519302ba5cc47af71ad566dabf16097fea8eb44173c8a39d4a198a7141a51a31dbaced96b7cbabcadd465ba059d7ae7355227b5986ed538f53eea56e7d4db4bb7524ebd95a20bc70d1e3e5a8ca7de649e46978ddfaac2e1198939d46b3cccc63025ba6ed89bd54a656dec956a3ce653381780bef39437e5b16e4a790cf53709ceb37ce0a7dc07f5b1c665a8b14be0a7ec85423a5be631ef817686fea86ba03fcaa1604477e5d1637e5949e3a843a79d36599d36d1d393363946ccbb4a57692bddc29c3af3adcc9c47cfc680f22e87795b4d9d9c5f52d0fc85464ffd76152331ba2c1d75eb7292972188d4ad0ba57495e8a221e6504ef3dba19cbaaaab3c753844437431477bbb485d865b3f86cc939e91d813886b56161adc569d79906ef56bce42b75c8841734dd3344d839ad72a25e8b9ccf3eb04525e831cb45af5ae1cf3d0fbf387f2a8bf3ba5f054bf8c491831c668adb2a654af1304fdd579cd2f1f69aed3ad5b7d74eb763fbad5ae7910e723bfabefa06ff6d68ad9db755ced5d69cd47af7907e94f83ab87b562ced659e816b5b0555d73cc35dfba556110c5228820c03c97f132c1d0f38673e3d2f7120d943ef3028ca0cf9c7360d90fe19fce97078e8e87656e1c238e611495d80595c8547b3bcaf160de5774502962e9afbd764ad37b8541a568951e2a916120d0072ec11efc0b9947cc9b0c03e12299c72c7a4bb8bf0db35547f6e7e3635cc2428b4eba6c95e3213344c105ddca9983d1a7bbad2ead4e0f4cb0f4267793a6b9099a20520e3efacc6fcaa5137332e85427724e3793df9549e34e6dfd55c73e731f2ab89079966559a6f9edb2f6bcbfcca1f7f597394e7f990769e8994fd769cf32aa79a66df6769f696eb27735c4df6472cd21347984cc495e42d2b8e5988931f788544e29e594610cf5dc62eca6981725a5534e294b10c1f0e42823476666e6c892291674ce49e99c53ca3921857042090642082184104208218410420895e4849027ced05f56a5b74b8bd14919cb61484e9363be654e25a50de39c3a62a4a458ad55f62755a82f98579f93d24923532c71464a79a6daa59473ca29a58c33ca18a38c3068d9734eed28c628659431c6ee1865c7eee6c8bd0dd5eab56b11f394c0a7948f7850e3631ff9e0e459626d7963999a5382a9b44eec48caa654469f53d249e99c52ce296593c77cd2fa43e59452c2096598325262b18403ccc6f589a1896118a65aa5be4aaeddd22237ebea231838e1aa899842a269dbb66d1ed42066656852ef28652a86feaae69857e9edd3e4db363d73ce39e7e1e6e44c5e8c2e63b7228d118c339c53a34051c68e5816888a0ea5f4e881007e046a986a18e34ff7d7da0c613764c8ccfcc391614386cccccccd700baedf954f069026877a039293fb03021a92c2909b4dfe76e51eede5f935a4e5e39095070339066c4012933f25d0f2fc0202cb475f3dbf8090f25a94fd0131730abeec4f5a9e6068d2a527e625f78811c6a0e3d70e48df9181301030a83cdb2dfc832215645145e889228ad0416bdc68a4c4e934dd45bdf4ebbf8a31461d8c629807698a751addf5c7b08e87e374aa159d54878d35bef454f5375d0a1942b792524a380694928dee762f57dd922ebd53c92ae79c6e05a45b7fd4993a1add5d3dfdba75eb4a87744abd3aa5ce9e0f3398bb00f450a762ccf104690cb33d9865f9acb5d65aabd75a6bad5996d596a2b5a9ea9cc9d3fda0bbfe13a75bd2a1e7c34cd714521d1d00e1e40920e68c1f909ec7f3eb07221e329be95ad0d4e84ad036c941808108ddad1fbb950534c691b2bf2981d0ddee67a79a38dda9ca7417f5dd3d6c0300da107e08fb4c079d51506d9d139da3106e950073bdd4c920cddd62972e5f8822c6e3bc86a223f830d3b188c869efc428ed227460a030a24da42a125fbc24d1f1cb07f6e88350b4d2f1eb8728cf3f3879e9aa95d14b1e76e8b3dbbb696dec0468af745aa5538fdc0b4de42452c3f468affce8851656223704a815235631d72a56abf589d432330083b1078da14f4c83e63b08728f86fc4d127c63de9226229550e61e904f98f336f98e1fa34bb9a43f724462c378c21eb33ef1e994dd8a96c2b642eb7835fd7e3a9ef9edae97735150dd1cd339dbe3a3f9adbe24fe15e9fca61ca23701da892ebd1144bf9b578f1c8f111de00ee658f41c9ad890c60a32d05883084548b313fd09d04eb44fa863d666db35f299bd329d7a36c09d1c38cd8e508e9d69a1449731baec38a7fd49b44d4c2b30028a215060850caaec487f12fd897cc29c635731073a10b561f64ca2cad7501c5d50a43f99727acca95fa7f370155d50307f42313a394a0b65b5f344fab450eace131b580c51119e801913a68d2c3b4fb2b44beb5cf497c7c354d75f7498dafa8b56cafe3ac5478c90bac582dece2f89f8f6fa370cf11c3142ea8f5f02c59663b0e8f4c8401a8329406d8b5b7f2d830e7af55b99814853a34a1852c257eb53c2571fb8f4d5072a7ddd6273749ea69b3c66a6159eb922d36f7f1cb2c257ebb3c2c60ca4db9881cc9f51ca1308fa97f0546c4e4b6fa08596a7ce2a427d3a7dc9001a2f4c83bd401d4eaf1eeaa995f0dbe310d44b0c422e1a3799170f679e5f3c047df7fc82b2f430486b451ebacb4b9ffda0a15bd133ffe996f4cc99fc68cf1c49b738cf5c866e4dcf7cb5ea3afef159c66332d7a6b779b23fce6472a6dee698378771ae71b780bacf34678ec7c4c2bc764bf3ccb7cc335f75cbe49967aed3adf6cc5e1d9f79b7a66ff6fa67389ff520f497c767fc30483ea1716b3d576cd0d9c9721df372c0bcbabd34f42c897f650498f3cf26403b98b711cc4a7b2bc71c1af4d38344fa00dec13c3ae6e5001474546548c8090e3704ed3c01da899e65da9d440dfeae1ef677912b47dc4007658c204ac10e0ca301521c71c5111a5ab680b203dd9f39ff2334c6b97269e3b293b3c32fddc29eb50d052730253ff5a5fbc0341f0f1da8d42d93478763ba45a65b9a478765bad57974b8145d351eaf0a298ffea35b28cc93af49ae887494bdfe9ca7e06f5347ca4622fec9ad56317ae48a48ae1e7d7b9db5524e08f6986f5e75e92da95fadfc8d5fd0442d5e2cf2a251172f1ef5173de5452ffd45477911a9bfd83d67a577b797d910ff93cb97942b12addc93659dbcdacd371b894eb62ef1413de7288f455d90c0289589679c0c1141a4e5e8cb986ef547d76a3c27594e527ae45cda6b9f7ae7c1f6d30b8ad29fdcc4158956fa3bd9cee337715d527344940ce1cfbcf3fa4d1c0fca329f70e9c9992b520351b74e1efd646f3ff5c915e16cb47297c0374149fa66eeb179ed261e2d1279d105dc2366d6074622c990a19c27291df3e2d31a84cc973616718ff8a5bbb14ad1478f55a2956e11758be55256a469577bb6520a113281aefb4bc0e985a22b3b1373da9d6855a59bf243b5769d47ed47b7a6b70a3f023667dce4d1fce8d24bd217316094a4181fc98cf9688f32a4e85ac59c5e654819525c6548da8f55ad314ef767e8838e5f425f3ebaff911329cf47399039caa1cb7b01468c978eb9966d623822393f83fa8b5e86c6949dc1389ef611ba4b7757ab69b333441c99c6086149d2d498d265537242f4855b3a496120bdf5517757dfdbe6c34c27979e4f4631a7bd4a349d936c4abb32a498d35eab7444aba2ef0cc9e83b5b3afa3e19c55abbee64744f46dfae4931f28c1423c598ce4457f5768ea9235144e9cfeb624e3b0a5aba38adecf084e8170a411ee009d0a7f7af153879139e5f54cebcd64c88601f5d8be283c5fe1c7a7f6c020d87ba3685d45a6bad59e63ea625391ee5577a96993289927ec39fe0f0272a88c34d0e39ef1a798d6e9da3bc6be4512ebd4ea66abcd6ae5badfc6bbeafe1ba349f724d7e56dde4c5affd955a530f93adce0c44bac9bb99a39218c93c23693ee3a4330331d92539324f12a9ef331d043d9977de93494e561be76c6a75cea5f49ab9b4c99ccbac8fc95e8192c39fd8d8e4c8e13636396edc66b5f98dcd716caef227b3c6bb49741e0440df39e79bd739ffc9b9b3d2397e94c7f9cac3e1ddf09edca84ede35f21c754e831be7973ae7d435de5c4d9c701b69766c3c07216ce709d08e8de598539dcba413a12e6f7d813a56b76e795b7f9bb34f8efae6f5446711a96ff224d89b32cfc7199dc9619abf996b0e391e8d48e6d55e93cdec151b8fdc159d9d2cd235595f3e0cd020a181c194251cb840ef01ecab037d73444e5fed4ffcea53bf4aaff6c2c718c022527f7a12ec97c4a7d2060c28d5352fad3a77add56b9598bbcff4cbe4ab5d92e3a9df18638cd1fad011e20a3a1ff858b5f256eb33fd6223804666f56efd5abdfa9039e762d687da2bd0659046bd1ca863cc14a3545aca4ce95667432168ecde02f8d92f84411a5a1f76c81e3333841032744984a36f8f4a743016d145bf70080ec5222dddaade5dba055fcb3c7a30a8bff6cd6312739a7978c3f968af913769f1878786373520b3b7c99bac0cfd358f11235c74170ec1a1e8d28939edd5646f97c1a16f1ea6dc1093b347be3acfa3b9e6f91042c79eb9893d1f662ab78d55ba5babfd81cfc3deecfc355ab6120c47e1570ac63c7b6f118f9e0140d7e03845015a9ca2691d3509bf3d08a7c0a70fb776ed932dc0b7d7c83bedf1817e3b737e9943f526403bd5336f04f562b63dd36aadfe0468a7da2726d72c73ce6deb03bd9d0619796abd2bd54dd542a99ed5ea19998f39d19f54a5879ef993ea4fb2a587fec49e118a31fa6c9a4614e2cb9796b49ab65357a3daa0076ff09ae2e49f5f42acf110420861c71b56a49493e2e082611856b31b5e689bc96432699b8907a78de338ee84a240486d5dd775a99a9ae7d79435549b8d8d8d8deae60405c776e3c68d1b3856528811b61c3972e418819552c18e4d07c7a343870e6e085471246cd16367ee3545ca6b082c256cf035041459dd4e6dc303bf5200e635441933a82881b23a5ab8084360bc40082c4230d07206116a507162b57091c5156bcce00447547ee0450e334c5a80b2544181182b7030030538942142cb46c4514a8b019e5f425cf1379e5f4260a142cc38849fb9c7ed2084104268821344045981e2076ba4c16698f1a28284105848b1414cc340648cbe719325a4e14f4f487f74cd8725044eef87fdd453f5d743bc7ec84d1b859873ce39adea88856e5d1f467e04f1d1c2d539d22d1f3e3a76c53032006306415974b0c54efb8a5d4052926e8064822d4f70f962a7ddd905a4822286d006181d706041113bed1fbb20c0431758a2dcc0065cd88055584972e9c89c535feec41622ca4387f3d965cba86a57a7a35d2bce89ce5f4c61497de8ab877eb167e78dbf5899993f085fe8fe26e9b687d6a709b431c618a53fbf828854147ddff8d65b733c4aa4a973761e5f7fad011952383678d2e426391e253c3e201acad91ba670d2e6e6a35d32c49c7615ae0e176f9edbaf0ed717a537ce64574d39733c38ae9c61860d2a9d3430830c336c50092ac5266a2cdd3a594f712befa7bfc699e3a9f1208dc373259dffd457b90cd1c53374cb051d7f8d37b7d92b7f731caea3d39f0ebf3f587e5118c16fcec71c7ebd12fcce935f4a426b87dfcde59e835d3f620e4b0682f2e82b0672e3d15e1efde93cd145bf1f37e4d3893e4ae009ed24783ffdb5eff098f4d7ee5e93ce69e93aec2d8165ef6a841f396cdf58e8847bb4a33c1a7c40c12e28af87fa8bd282ee42a215a23822a9056cb8e0b5050141666680254b0a8cc0d8699741032be73c48dc9e7c3b0eefa76f784a7eba3fb912947f3cb61b676ef39be86db7f9ec90470bd5a8b2a9f1664875db26b150234a1842f04112184070a51e7e88f2c5071ea0d869971203dca3fde465009ed01e3d0dc8c03ddae30fdd854452a95b3dd451faa341a70b9432b484d941500acc60342ee8f24510133f2419311082c0b20508a231675061242c5e04a161a28ba0279b6b264ff3246f568910f93e4d7e7322f2373b3d8885076281443dd45120d14fb7ee0783a050b72e2bd1f03169029d744be9fb7448638d21965480e61504a01398400637f02028a94ad111208250a68823c840828d0400018619a2216c60e6a531248a39edd22f8edbd589e32f24c2d19428ba78071ab5f82fb4e2db6b563dcc8b927b488744d1355b8715372f9b7b29437fd8b3f390f3057f29513a4a7fed42ed3c437fedd813dd6da16fef28dd9ad2ad0b89aa74eb7e42ddba43dd82ddba10a989e8d6ad56fe36d1b73751b788d805347406104db0c0cb1367e860a71d16b16bfbc1146ba031c410ac98d9698746ec02a29203335e51ae50d1c6163bedf0885d1b280289305a0c31e185153bedb1ca7711094d8210a0632c4abd7a90e3914aaa63ae514f55bd8e7b4cc73c1bee313dc5274cef283ad9dfec2eba5bb7950a674a281ae35c56f958f5b801d8b1a4a3eeec37136b712b334529a54b8f1ee413a4e41ce93e4ae8b10ac04bbfdd0e16a2bb52c540fa2547d757c22de167f49654239cfdbe9f9c74f3d09388f8df9e8f6d55dc037ac71b5796dc6ddff2dbb29d47fa9b10428ed01ee96f1ae90f06ddf48f104b81c6ad8179f6d7104acff6a7bf00a8e91a733c3a5c93540af1530a71ce74288b640fec62728297958e20b7f6d249cba4bf291d3a730d4d9bd436b8492b559c090369283d485759248b20b442a057d75c33b9ba09adc9eba24b1ac9a4d54a16c9a21dba1cd1c94f8f41fd4ddf9cba9822ced9c1d9efd8b1c327136c63d22dcde4d0733894a2f2d9aacb43056f27e5a01c8f4f117f93dde198b3e669cc991c7ad24dde10e8d26d75aaa9bcbbfd8e1d1ea4b58c61164fcc3d767810932650bacda9df4eaa72f9cc0e4b67aabb8de6670ecf61ab58119a9d546bd7755227d54ed2494209f539d43687be6990e590e3d1e148600ad4a74f8081489f4e016e693e49f05b5d25f8ed80d83843b771cd8bfc9d00bd7ad04bf0a093e0c1cdf361a6abdf74cdab4e74fcd54d74487578b322935191960ba7fc74264d56199cd22dc967e0d084b08a11235a0ff7b7434b912cb245dc098591809d1a56aff6a739852e9c84faeb3639f4530ac59ce9f186eec66f380e5f79f492d46ed4ad954f9747d28b4cc2e177fb2b8b7ea2fc4aa49ff28bab04bf12cc4f8aea64912cea96166914357b936c39fcf299ead22e810f6d8fb4d5bad0df0edb7345c87748f01ff85748706851a0d25d59e5a76f0e9d40a1284c76b8b4d22e127cbaac5282d7483167bac65147814a771949e87b8cf437fd07be0bfd4da7b64746118aae7826e64c29f4d3b5d3c6dd6a1225a54d82d75d3a6712fde6b793601428e4e44c74318939738766cf8c406d7bc9a283cef21bbfe14ca20bee4c8741d0498ddf9af2dbbd4ae5cc2a678ee7862cf2a4517f93724ca20b49cc995e590ccb4a2dfd4dc7e12bbfb2e80626dd3ac117500e3d724550cea45b279fde04063110ae08caa15c025fdacbb9c983c42b24f8cac3e14dbfe1717f99df78d355de8551cefc741b4f098664d6d85b4d9eb2b763ea9d989fde4274916027d24f479d36db69263a3db3f7fbdb557b75e4528e1e400d34c6b9bdf4d4654dd7df4c39e7d2bb0a03895043a1a8f320dd5968143dd939f4a0518c5648f4ce3b1b318fd0a85b1816ea2b2ddee5a997a7ce180631e73c4e75d1a51373a8d71a314ff6474374ddf8a6e5b8f120e74457a53eba8dc79c73336cf28d4dad36f6eaac3293e9880e0e45cba303104278bf8f5e129d20d121741578a2c3662f3ffaebe8ed0156fa9eb6b6856797de5da3839ee4c733b31531081df41887441edde5a5c7e851081df49884bdbc9431a68941a2941ebbaf4840e71a4a850fc24090700fe8dc55e17ce6fa24fcae5e71e86ef7d164b58afa78e8442d094e9111845922ccd027d171e1d4c51c68821e7cce33a188eefef8e8ea3c7a90cee3980337134797aa73babbdf47fecda3ebfc50218898e82c74ab7af416569cbd3a36cdc61f6ff2c815690203135829fa242ce64d12622a484ee29a4691c1a28ec75f9c6f21e64cd78f9833dd042a9dc49298404467c2105db7fd81cfd37588886e557b25fa7458a5d1549f2e437475acc44a56c98422bae92d206120d4a7cb1c32ac4217ec65303f31fb23bf75700fcf8422ba76f9a4bbac24f4d365d0404d42a348572148cd1c26612f454890c41764943e092b3de6c9a7d375f48c3e1d16512ee49d734e8e94995d87aa63cc6f8c3162acc303c7376d4e1957d007f7e0098420dc835dc72a069c3349707eaaa0eacee8a494778b68a05b0a84c8f676778b677885143af5a6b672128f870e75a4d1b1bdab879d998eeddd60778c52ce492956399ecbe4833aa845a7e5864dd5e49a6593e3f68357aa4b55fdf953cb3e2b745b4b09799e24f768ef5efdc8e0fc42f3d15fb3978fa1090d57c7b39704e7d9fbc7376b3f787c98ca67921facc3c3fbeb24ec45d6688221744ee6e9dc73a58e9594524e7b65884b1d74f9337f4ecbfd49e9b2674a26d2a2651f61fa65a72fb0f750343c7a908e6874d0af0ebe6774d0ef0d1d4e4332e4738c3136374bd12217518f923e7b68fcf837abf9ab7d8c4d047b6989c038973b833133c9d4263d3331900a04f36d53a974e8c0c179299d3d451d73ce07a6f181697c609abaa453a264497de84a7c7eea43ff593d9c36456d4c750db4435010f4092dc31bfe480d0da318e6177b56a974e8c0c1e1c1833a7cad37d92d1f98a637acd65a55aac66a90133441417f9b04e5f0cc11896d04fdb5210887a0f7010afa086f78a884b907e63f750837a4bfdaba79d3f38120000a7ab9550692013df9a0970bd8faeb2985c66da446991f2c4108bbb744d92244b71c6d21da4204e42d65b694f1cc263160642b5148f90b9fa1fc163459b784e9c445a348269349d3a200130517518c89e28c571442e88c868c7a30dd5065c362c3509c812208cc4690e7867bb4cafbf277fb06b3a5c808e9553746553cb78c6e6034c6c609ad95feca6f28c43c44eaf80505d2dffa82e2f582a24b8ff9e8b0a17f3c1c875fa0d598710a2cc0133a7ef4f859802930f7e820f084de313d7b94f4d959802948210c04da130f1e031840095fc2ad386e453d3bc62e14bb5ce81cd711a48a54912a920b9105988203f8847635be323e86c5689ec10bb287d608f768c18cae19084c217afb0e0391f6c43d600ad16ef0845a838eb9870bfdf547db427f0d860a515b8b956f57c11f9e0341389eb94707b19627d06850cbd03317417b70a3ba737ef44bfb0664d433d70290157085200f7dfca129b3a94975a813b76915a353c686cf319012543637353737a99b9b9b9b9b9beca6623737289c2ed0fbc034257ccf2034ca9c42fbcdb467679802f4bb3d9f4e2c040ef1816984f048d764928f984b6c495dd2bdb43e30cdc3341d45834e2098970bd05c0cfaf0cd2f17147d148c81c44c8ae4a84cd412149302cb8eea09061907c6cb89312f27cc6c3188ab399c7a409950d0c915a45248d4482d369b91cae4e5868be71baf27c2dcb851d9e0e8aa8416c5b0338e96ee329919ba9584866ef1eb8931f1fbf3a1020b2d44973398010c8081c81efeea50125dc992faec3efe4bb4e7a30fdaf123ac1ec76bd826bd1bafd54d7a37af659bf454af9936e9d9bca66dd2ab796ddba487c26bdc263d9dd74e9bf4b6d7509bf44caf759bf4b2d7529bf4e86b359bf4e66b369a6abbb9a1b2b9a94975a813b7ddc0614f60e7a3dfa40e5aa40103611691f648376fc8bd4044fab45dadcf2ac269d2f4d787dc0bb569a0499628c8406aac3cd1b2ecb807742e45418faaaf49af3210e83c243aad906380ec2f8b2e6dddb8077408466bc82b5ef1eaaa5c38cd40ea0e5641e823815510d2d9c1bc5d87c72964dfa7761c98c2f40640c7cd75a473da63e89c761e3c707074e8b8ab6deb7e7aac22b34736c700e9d36e1df75881e9e4d6a9da5752da3bb9176010fd298974509cf60ae6415a7afd921b923d668f1819d35d28f43d8581446997ec9cf696028439da2ab406dd14521ef21002ed26d9defb6bd7d15fdbc8457755f7fbfe62ed1cbe31b4948e44464f75c3192c5db290799de75796281e0b16265690f4dbdf38ed570ba6bc019e5f4dbc9a28faeff9d584d0bf9a387a0d8e790d559dbf6a1a657b577ea3bdf0c415313de5b8213534f2479710723cb03de678a8d5a857e39a46ed95d1bbdd4788a47f7af37a546ec353efc68f367ee543dfa26f3648a4b06d36486f7cb3b75fe537f6f67370ccc30e452d54514b3957f9dc2eb4577ef714036a62038db7867f7ae1d25fccbd9ecd6d78189fa348a85f48e6af4ffc0b83b4e45eb8fd9b0dd63ffd9c47b7178e79cc7ffa6174cea3c7c8d91e78598ccd9b3240059d73ea41cb5279a7a8437b895088a45b0d5380bef90f1c33e6db6bbc0bbfc651dc901b87b607fae6a71befc26ff779e31da4d16f348d9873dc10ea3ddc0bdb53d789376e2c85de1ac7a349798d9bf4551e3f07a143f99cf750c50da15e937294438fe10918e6369ee638bcd5d778351e92fe301c3e53f6d6c7613de64c3f75f6d64759d8d0333fc1b63d9953873980295c8845e731bf592cc9f69adf24db4df2135fb33dd4db370e6ece05e99f88b970383cfdc4cffc6459d537c7dca34bc7a9633e820f335d92eda1739bf561a6fb890ffdfec4f7d54f7c6e08f49eb69b4fee85ede1b41ce6b7427b37d71c09cc014c815f73c9f16863de34e957117cd6a74b82cfe66744b46f0b73004fc0707874d6f44d09b8442a504c40594108a1101d21899450110d61444268da5fd5cf2f4bb4f1ab25caf89ae7d71260a416655e4b04cdb9041637b8420736c217466362d00316a05185100bbcd880915301316972d8c14a12521401eec082292916b0804585075ab0450c2ca84883832ea00e4469b02087a7373b94524aa973f7c2d245176198e9811636e013a22f28221be0a02200cfaf258a58020a0a648cf1932e638fb4b53f2f5d94b2611990dead311a041350518510be2869814ebcd6178491459bb083125414017308e30056f4d08330c278628b2d1d10e2c116635471e58627200eaf2b452f25b48857601856896ed8887c881956064c8e1fa856b7fb8e2976643303a88339c4320c6239226a82888a1043ec60f086c7ae9cf1187665088fd51d0cc368a4822ad1a58c1253acac3c8ee797123e6025d0e46bccadf61b218cdf8aada43f36a720bb3bcd77bbf46efde9b88377d70a6175d95fad257c4fb517e7bbda2b5bd56f74d9d13bdada5fdf55b54a9d3f737de9a50a561a934451115bcc103981415398f9a20d3286e0c5132e69b840d2a50b1923d018dcd03056b47456bc502b5d0ce214bf58c12165e504118583fa441b674c41881dcf40454bd00e720026684c1b4898a12111843884126cb411c40faca8828a2284c1952179f8208b52115bb4bc784083c4170e092cb224647044d402b4841017a3233344455f8880041424862000a38104191faabcc00a218cc1c61167e61145d85a704499a7f4e911693ca594c616dc6c993b24c182d71162bc8c3013a148a24ab6539444111d8b9278f2dbf3cbca10a21843709dc1c3183ca8628330bc704174c28433889862881e7850c2ca199d269a884de8602f23885e558e221395478d58baeef965840ede881b4c23bc3c7d7e195145f40146a2305e4618d1c882b844bc8213afe040af1d724b59c5dba3de0ea33cecf2415a935008b2c7f26f128e87d220dd4d69d39eecf20241a7cc4c1dba0f842f271364c420215131bac28b956f6701b6fa9d701a44558a5620e535d495cf30462cc6786d7849afd63e2d07fef5275d7ed15d4e4272c36f9c7a97c9d32337a89bfcc64e266f72ea79d3a7c993ceba9c844dcb829e794c52f6d6cede8ab227695b6ef64ca53e9d078bda16be4f6a0ee098633279d4bbd3a1f74f64f22cef3219a2b9669d9abcfa1196c9d2d01fd6535eba91e8824b31477a9564742656754ae7527fb287bee8ea2992e865d14b87b28daebf24420797e41098a143f759e794a67ac3afdc38666f58b8b41497e292457a291d22c12f37ec480a97a606391ff8cc3da6b3661fa5fa46d094cff1fc02531486cc1767be7a18a2cfc218bd34b2d96e239b65b54bcb6a8f56c8e49b9c6874d3bb9283e65be69bc731273ee6f027b2aaf70468470793cde2b3c2b703ed3047847a6659b54e8f596dcf3c00f4daf47aae888063ce750fb4f3d153cb8a724c18a1330e21f4b85b96e5034dd1e4d92b29d6bc82726872cddb39e6547e81491252a577eb65f25890886147509ed21cf3219a631e312328cda75f96740889683e2d4bda93c934e7c9f3813f894cd79c359db39bd5d488d3a577eff46c5298b24dea9cd08499784c26320e2bd7b3b9d33c59969d96d53618f3af1a78f96803313e4214cae39823797a32ff89dc04509ef2f66e7d269fb2dcf3136f6604e51aca7393a76c13944b7bdb6a5bff74aef3765861a7db61851d546751b6862c476a3ce529effc646ba8b129db04d5692e3d934fae761eef4c8f1f55592c99793ff1ab651161496b59d36e4da390d1850c2230a43c009ecc4f37bdc088a9b5ebd8ef4f7cac4eaffd297513e827c733ed854358d3dbab65d6644d97df5edb5f36ecc1fc274e00e59c7374a1ecc56c11193922269fb68caec7e4d22f6bb28ac8c7dce4d2b226e7657900ef689ac9b4e300a01dae3269027738cb3d3ff14d2e35232714e7d98679c7794db21ce1bcf32c4750ce3541d926598ea0bcf326598e54dbd92628db847329bdcca7471de39df67c6cf81dcce3e78640c8a3b126ab3ae612b35e443ee344536739d09899dd640a528ff868c579ed5d26cde49bf374586187ebb657066e0621b8c3e9b0c2cec9357b69e05c08ee9cb420918b5ae63bd5f3899fd986928caefdf6653233981c660e9d86e84a02e175c811996ffaa1631575ac567c14a4856a7293b77311a73ff66aaf777475aa7eea6ab5b70689fd39948185fefab2fca5e696d56eb2574e96d5b688bdc2396659709dec0c3107fa6ad5759c657b7db503db9281435b6f3208236606565a0c96bf52cc1531559ec5246dd1ddeffd8bae08708e743274ee0f5ee3e599252f928cc8205f5e2049311e06c51ce9be060c0a8241324c1723248a44b123c0ae4a46c783151a2f2faf013feec111993f5d6ed13d3b748ae4d9cbf2811246c7ec15132bda22f24ae6d4422c9028ba4c76b5ea3a7f180483a24bee487f5611f9d3a77530bae8ff718f98a5f982cc43cf5c43d5da75ecf163205f7fd1a1f420cb07fe0398c9dfea3fd1649905ed08aceab7b2a46b12075d4fd69001d2b2a4539f9625ad65555bc4d6fe5c079dce91cb238b5544ba4c427a815cb65023890a2e92ba24119164826e523aa5e8828dbffe5374d186e4d265cfafa41b1ce74be2c18b0d280e303258176864d1c50b621530303dbfbaf0228b28279982d845955a451744b48a2e9aa85574b185061f1082073118c38a298490420a2e70e822872dc67c41e38507083f042d7126a98c2e465bb051a9d8f1fce2a20c2ec638b2a223125775c1e9a2d3a50b9c67b8a8820b325c84b112c51428a421841a446c2104251b6c7181e90a9e09184388881f68d08315404194d9d0835218389041121a222d25e85e3ee7a473ce39a7aca29bf30923ba3859c14490953476e0831d88009de082879f2f2ebccc29a9f0f2a5cc73984fa9fa637574565b21fd18adabe8ea3a877d3ebfc9ef8f9f9dd3de5ebd9587d198047df02c356ed861a158c623934674d2078e61483c788c716698327ee5381f7d7e2129fd759d08e60347689860638834889660962c8ec8b26022870e152ee306439851010e3818830ac492c596051036483188448058e69c589753ab56b3d38154f47307ca23bad3f30be988edf98514c4cfe71752096ed0ee1519ad0d59d8b3f42449c2de3634106c215aed5657e80c215043c805a6812f7c18e3873464600609c8c40a42c90456c1c894342c92281634801069e8575a0ce1bbe797163df86205b2caa494ce9c1f7210c40f9c74a1020c221a90e16d9195806261d2628c296aa54e64272a402e2802134510530061460dae781182f362e544258c971c4e5e4a40b9a053342daa60717445182604708426cb135dc648410fa01258f8206271c68da4f2d2828b162de081c63857267dbb4ca2bb4df4ad145d940c5ca23029e6d02031f48c92101c624224a4135d984bbf3fa6867970477a1e7330c76c0d34697a2c18a44f9fb686ea72877734b861461c0077309fd2316b0375e935c902033c038a1804ed5497dec406ea98576b03f51a6cc0a4cbe9d2db0041678858304ca73e93583048a72e9db64bafedad2f93ba312174a2ab77d83514d1c31ae69034c1bca329ae861ae79c77a886b9e6bc93aac19452641e3a5dbac1e13c576ea4688d73986b9c6b9c6659d34f1d94049dcbce3cf4da425da5877a8a92e89c86798dd7d81a528e39ef708e8405438ddbb88dad817a8df38ee643f8a5ca6d52aeb211d2861e3a07a73c7495c792ae52d20e02f83e4a7c90a0bc3a12939f9ce74ae63e3034d17c7394c360720d7248528e39e49050af71234e30afd91cf31acb9a8e0312318939d0535e106b5a2337b648e571ccb1f158d21a317ae8f0c8ebbc55cc813e2080efe3f300dea9711f242c184c8e7294ad417393f30ee6485830a06ae01ce5bc53e34338e5d4b514f5aff9c16ac71c68478bbce3c4e4288f30686ef2e690708ef288647393455956f45392c71ce89b57630e74cd63456b24b362308fd5d608d08e0d3540b26b178d9bf217fe9245509445482a4610a143040e1144d039274de28328c84093c68715c00022c145098c7b7e5d7174c516635c5174c5115dc552ada28c04c0f3ab0a1854d105ab020b0a660ea164c9cf168bd12ff51a1f0440423277ea57c6db8fc187d05e76e99a07894cbdb25f6a721000bd74593dd95f0f44a83b73b147baa9277ae62dd9f3b8621815495d96ba90c1eca5b6a70773c845c7a4531c481e24148df993cea2ceaf2f527eba11557f2c6a85bc6440f4d28f2089ae7814a4852988bedd85d71447df9e84c9d0cee531ef440625fde52527db52505050d04e167e4db1f497d11c31fae23d008b92f7002c63bad550c847b7e011df46fc55e18851527ffc6c71ae60b6d3a1467f7ebbda2d761f8a42e38627c00284314550e412fb021205178935b458b94248872360115c5250b91c2177f07245182788c07c01c41448858b10171fb81dc24881860b0e72072e6af8206b25ad0694cb16528c1465a4702283e092a5b9b4204a212e5b5e3ebfb838e1058ed44147eaa05384eed6e9c34cc75efeae9e8daefa6525196243313e30fe65a582cb47e74cc76aedbad5ea7b9d2a85da2b59e5ced182611886615812cc032ce67b30af987759ccb3981fcf3f4c6ebde1d0de199efdbaf07c8dfc11242abf31b0069edd634e9bb49b1a8fae1b9ad778affac3bcfdc6bbe179e760ae795f7f588d7bb7a04d8d266b7f98db785b7f98d778294fa73fcc3bcf477f98a33c16fac3fce4b5d01fe69ce7427f986f9e11eef1a37330c7dca459ee0ff391e487aaa7180db3f7fbdbfd7c9337a1888eab27ef8b3927efc67c73c61c730df39307391eced6b8417bb7bb6ddd5370f6ea88f9622fe7cc25d1790fe87ccfe6a6ab13ef66311bbf4c1cd638db9be453333cf4ce53a1bf761bcf4774d5d8b6dcdfad2614d1659ef23ce67038ab13c779175d2994b7a73c8e39287bb79377b7bfabeb7f93e0bcecc1bafed856896ad984d498199a818a44e8d84f5cdca4364d346366c810c2facccc32faadfdf173674a819451c32085dc63ca26d23729e3dce2191a16030e1092e0bc740ab5bac9e04b537aa5e1651b3f325e0cc3b018b52ad0abcd83c612bad05f1bb93a1fa345a8842cf5a551cc3ae6cc8800400000006314002030140c898563d1703853173f14000a98b050604493479324486114840c318018428c210000638c1918aaa90ac6ac4cea287ae0f8abe449dc757ccf8d31e4de0d0000431c0d8c198c4a027c2710a563423b08e5542885e638286f334dd83ed7a2e3b7a6c614174c6bf81299b3a01ddbd4c071d477dd45608ff78d50861fc1021970a4571f26446d555946c806fd7d054f33dd14aa2538a5284fa6e8242a208489afc4480165c0e8e04e01a89ca802b1da3d1eac0f8edf856c3b5b29508c6a74a711a21fee161c2c82186c4a0e9a1707573581927d90aeaf424031c8064f6f6fc8800016ca4083dd839d663d82286f1d4912e16c2731b185c8a99a00e8353d06b24adad97cbbe63a26645e8a92a83443b3f5b9713896bc76a5cb9f85cccedf120356342973bafacd34cf12626c65374e4bc8261acad615669f95a71c70f678f62732126960e2016753ac5ab835ea0c7c53ec88ca8c0ec42d9bc755ff3508d754d4544d028bb20154b46039adb69e801bd6d9d4b6244719c6bb58131c7675d43cb00747a64583b1324ae7c8df5326bd6b8c5394267de84bcaa7598941848d14a8cafe542db200a37f7d09a5e2f7f5855fd1829dad66ccaea9b814e1179e59886a6371dc061f5487c5af6f69b6ae1fb858dd9c53c3ff54640a90103c89e0980d035524f9050697d5b3e0c8ae25ef96f80728171c3d77a84715c4050cce93101824332717d2a1d388e54971a0f9f4c3b633bf5fa286a29d0760b931bfc9f7fefef758e233708ebee76046f895e826702c5c00ce807040a26b503c7dd1ee63ca824c75a2e3ec9f9662321ec966a30b8845cb6c09f153c66873570d2011d2098d236791887a362ea2175b122f645c071c474bf83de35580fdc5c9235265160ce7f268c665eb84dc004034a3f58ccfba6b40cb2d6ad83c8082de066d49dc8b5c490587c82495a3bbad96a1c7482defbe32c12cfd578288e5ed63d6f0b0f0ef43b77a1e3c3f2225c402d4d5c90d322163d11d3e9304728ef0b7b8122add16916c39bfcf68a7af5071e2c8b08ae33605503d176ddb42ca86bac7577af2f1b762f27a6fe40200cf1aa204e3e15bf1940435124b4590842163abee93227a90aadd9f00082d5ac1b47ce62790e5e44e9965de73399110c16b9d379957c4e2899fc70050c702d08c94bc5b76b81037a873710f37a40e4d9e516e6893fe672c58c21a0e1fb8c9eae318a07fe89cbf370978a675c3807d70ee1e8df5bd5f7462f642fd7224a22f23a24609359e1870c8c96994308cb1608e0d58c359e51b925ef2679de39e3ecc3eb606d10d24f910ddf7d2e344891690fbb4ac1b0e89a382da6afe36b192c469603ef09bb0011ce485164e981ee8a54faf0017e8839c343747325e4b374010012349a5e0f128f797227031b0215897e3071a0c8189fc9e66b80ec1ac6d1f56cd313aebe387506d673de11c994ac23760ef800e3270bf383c0990b245f114ca19f966d1ca87635e35ca1c0a7c68686d480ae99b400901b94d6e356c9a451148cdfd3c404655f79f21606587260f8c76839527b0844aa713c0885a5480b887e1580090df5c1d3a8833124a9688ca5a0abfe0b7f144883eac4b8d450956c7c01d3060be49ecc8180370415f1a1fe34337ad0d2e4edde0877ef02880c634c147b0cb47ded6123a2ad3ecfdcdcd9ba2271db77652c241197d5e39af48d62ee36f4fa546e42a38608077a6e095223f118b526be2f4bf6a45d1b1edc5f54c1ecd1478335728a95fa6500608aa31f4a7b87a5a07f127b975f671750200784b12f46ecf76c1735fb9e620f0073213b40e7502058d79fd01a3d1f641f91e1093d52e43f4406ccd664d6890ae6f6d2cce848156fa88976c0e9b54f83f08411f2eb8a6d65812ddfb4b5261676603a16f091fb552804aeda63e963359eb952e1dd4d1b91366132177b40cb8a43c1e00a679d88d4b0b66ba042202e7b8e5253812e82b19660106ac848a657d7f6fcecfe1410639949a730a2b9c9d3a92e40073addde5f1d1bc9f9534edf15d8d470e90577612f56922581b72c5517d16c6a22f2c8feaa97a241200ccb9d5d1ffa8894103ca9a5e20aa668e5723ba1bb066a08fc0720532624c9afef2c90c2235f6ea17b89fcc380efb5303621e2e6646c49e443f14657ebe25336806f9af5517f4424550d64dd5c426ea8facd16ddd9460d42691955e2771c450f89a3ccb71c740c2d6ebd6e9e2119bc1fa476a2110b70500e6db406835f8e5b0937a088a61b49bf996d870666b6d276dbffd7c732d363ef0b7d0c74ab4f2af40581e8f5efa3689e73ed5f987386560732bc16f66fba5ca7d7823d64b6377c464fb8f2e1a9dd9ce736b8e77eac574642a0e073c73a82a67fb902da23de55687a1b6ffa40a24fd0dcd434718b55321c6dd04e5058a1766cbd3d8fce80c0407f8c7603e852286dd9a2c3956b22256f4ce99ae9e67ecf642738e96c1423c3a5b217134f25a5e24fc71d7e472d2e1bdf1f51f8ac814153a60c10291b04e8fcc91c6d278ac6cd3e5307f5cfbf54a4086db5c0040ba73747f4804397b0304a06400f560c10a611d08554417f4f06af06c283db05a5dc783207156b137e2b6039f06cb8a8b2c060939c47c6a6f1f7b78b909d9434115b3d4ad2602b9883a8d3631684476d26e86c782a11c1e87a8893fc21f015b92b796b019e0508b98470d0b1bb528c55cf0af9679f4269f91d06b043f970967df1ff947d024c659af24ac51efb31fe603bca5a84ffee92c72365781c9a4039b0b1a7c99665275fa756284aec80f6db95208d327bae380884007cd58c6e040eabe6780d82f4dfd012dc59f151e2512c78ad056f07123e8b4d51adbd768889e31d76da06a36878d64c9848f6f7c76eda4dd2ab6b118148082722bb1a10182f563e13d2a20bb821c40c809fcaf54200a529d2e0e8d6445d9e77ee3727384880f583d24d252e703f5d687d8335a2d1eaa5e1532ee7f370aeead89a9f7c2c461d80172422fd8b595a9c7971a620d676fe7ab3d4a8eb87bea77045aaf41827ab4300c8e86c4e6610bfadd329b4f5f7e88236d5a024e90cd9e9aac349fbc62faf06dee4f198de1883c48120af87edd7b7a12f1ee56f78582827ab63960d48add1c1730d7bba2e0ae3e9c3f16470c468b9b49533cbad92435bfad8627a0d3d73ba72d420b604f7d3ba75b6432fb6f73468257a6dbcc726fbf418ab568fd63f1dd17007d812241c290a5bd3065209f25ce45fd4de1c7bfbd9304fd7a9a3b6bb6f263c7a3699e766633a6cb381be826b0411b2a905f0acbe5a811fc82fd7cecd973bb206a2e2dd8c119036958d92e580cacfdfed483a0249a4fe8015da0c5a4ce6e7eae660aeaad9ec706f84eb7dd6601ee90c16e210fd457b13c0abc656e87f4fa6bfad81185e464a9a57e92702bf3578cd4f16c01197e18616dc3ddf7adce6c426cabb9a9a62f28809b7461c5d6952b43c7d9e490cafbe0316b4ad46503fcbffeaf29e534f1ef7de835dffee7093ec31ac25e7d0a6b2ac4e627947e8bc3a2186b0ddba7f4fbf83a5e2ccd46bb8b914ba271f25440c7e9ecb1e67f8486604541d34b5173167903c6f6c8524d2b13539fc1066cd7bfba5cffa8d158d7c3c47aaf467fee7260aa6b78437feb72522f151adfd41a3d812eabde72571e13636a8f4445c1bbe8509f4524780064b132c7362636d48b431f5c78da0e0002c80b08c303802423acdd4437505f31e9378c7914b540506cc30d7b6bde5e2e9425840985a9f46e87455f1386949299896fe787b3ae87f18576368656010e8871c22282cb0645781fb599c2f04fb3fe8ec53d4890fb9a26e0ae9c05e566d6574262f05a07c56cebbc967c2821ee190cb93ff04217ed95a8898ef32980d0659dba022f4312ce98bd71bf7de990d4ad61718c7a396e57160288038af1bca213d49a39ce6d50b5726cdf31b8b2b252015e1665ded85dae321c959f49fc9ceee0c2e48ac3cd9880422bbf57df04e770c16e8fc49c520594580340aea4e89a940ff4a08d075892bd6744f6e085ce029febb4d308323e98bec0c81379f4a984d21132db6a50e935285023069cad5185b1b32156d5b01d010d7d970c2317fe89cc5fb3a31a1b83d2a07925d0d94ad9ee47ca6ad0ffdbde3357dcc0fefae142ac8c5c95b31d8640288aaaec39553fdb52ac22f03f5e4ad94693783c818525851269309b47f61a126dda8b5b7a74da9b9a6f775d0f658071cc23bf50fba0d3b1156e595bdb2f8dca195805b6d097551d33168648c232564cd0a655d6b623c9cdb1e961f01b3d7a0e7f27a8b80eae266cd8a3ea352d1db3260cf184445d192c2da03287a4b459a17119874505077211c4b7467034cc79071ea7bcad7de41dc85d8e5c0f747c788f5da27c49c3babfdedab934c30f45a027c19fb9ffd03721d0a7278c584decfb3248aef90d3251801345713b03fefc616ae57ce472084f070776b4d4abd98a09ee9b8e9dfc9e1ad5c4477640597a8f71dffcd1921668ff6b3ce9c1fbad58c43f257f45f1fb9112b7a974f14502cf42fe38ede8ec5fc484ebc2a228f14c941f222584109ef242655ac00588f68ee0e8da085373267c69fa4f05f5e12bdfad851652d0e58ea997fc9f7fe6551371aaa04c7764c841d3c529e422b008442ad9024f795cc87348b5ab011a0bb2c527536da4d65f94cb286ec1a0977e0eca0cd6c0daa33ebbbf3548ee82d8c975785092a79b6c6f99202b0c422f770d56af47cf46729d7fbd74bf678272b8d7c1264aac1e01b4d4d9a8f0d06d0473738ff0edb51c9d77c6b609c83a6361b124ceb2d4e2761e312c67d102e0bb063e7e11d50b2214923cff1d68a60eb9387043be5e7a29382db134b84327c03454b8f7d1cea92cdad64ebd1702d04c59fdc01fdaee9cced8a7ad10823e2d0a9053e7f244e557c4912f42fb729d2024ca0cf56bea500fc6ac11bf03e318d0559beab199c72af2b08545498ed21886fdac021a8b59d1cdd8896cb9e04dc5e0986c280b2172d718c5c71ae75d7acc4caacfe77b23621ffebb71e69e07b0dccf5f8467a87426715f02b642a02b2ac7bd59fe6ca8e85e9646276e7eeed71eec5d2606688440283be3d8abacf39fa0d400e430816a5eb375f64d83bdee7a900020c154dbb7586fc666c3a056608cdcb662242b7955047dcb13da37dc6ed6153b9f76c9bad43e0f4a99f144dd750d5287d86f8e28b8deb6d2e79a8e5e171e28afdd9a7d5033d5bd91316b96207615feb394eac3b36ad39bd7310125b978cb2ca19bd4ec9c15073b81eb2929452f93b343a61777f930fe5a6ee0d4bafc9455a1e16deda137d06bf736ac7b905ed902ad3e8524dd58f6dac1c7571894d0d7a38750a03ecb7a208d332c5d83703229156e65a0746c429847df001ce47a440b4cd6a92f21c27008a05332fafdd929b10bf3f684159e442f21db24cff3845bcd75ba3f83583f7ed027946c1cac173ace3d9b73dc842eb6536145e8767d0f57f133d0ac30ec9350e0398e4dd4314036df855887cedc27977b28b2a33cd7f3b8b12df974ba89ae33618a87daf6f24ec99017069297f4506e994fe043b815eb581bb9cce6e85afe95a6e015d1e3edcbd84963d16db18b09df60858f7b33395dba3f8d8345776593cbe2238a7a4dbb09b85e96031d0430717119d992efe029166d74ed08e416ed8a0ebbe49f2ff4f8edfc6419f286210fef43946f34e0c782f9daf8b2aee36f2186ab1b2f8b86cfb78bb651285a6ecf45a086846e263fe82004a52476bf2d13aebd4d4840d435cebacab184a0376c5e4a307b7dffc15e42d39bc1104d160dee41e4a1f4168268625a352e9953a61f95fc020f47df08c7985c79f3fb538453045aab263cc3b9a8d6d9b670a173be7954b34bb84a2f79eec84e14f160b4d6d43aea8713eca1da8a84ed82ba23302c2a3454642dc6247dc4657aaa6f22e9d28095fc9dc0114cc253d6211232b250fc2eaf1171328776cd2ddd84429730d216a1b01f0c71436c7a3265a09cdc1c4d49450ad942354733bd46b0cb0e8b688ad4cd1c8d868a0e9635c1c081464a113a4ce7df1a299356cb6cac88af7a177b988f184061f63cc021f85a40e699e3ea82183c5ba4549c8f112020779f36213619f9eef84d67a68d2a18da72c2bee33c66d1ddedbd9e2dd25cba5c2c6aaaac678b10d85d105b2be6261285e8ff34f1067c753fb815a3476cf0c4199f4002e9ecbbac0f129e7ccaf2889e75baf89a2456c31d7c1c2fcfc65a9f96a59524febfbe8e7205bfd5b95364e956aa4797dffa672c7dd0014e711c14fd4c525fc8ea8982c76e7234fe70d6674f9fb418c8bccfc2024e4c331a203726d6fc190def65e3beb10a5753bb5635dba90a5b7a3ce84f1aaeec17f42256b175773caf74f5e80ae89872361e4f66c06c479299e39b2c6ea855a0df0ec76238cf651ccd1321f470dddc99f67ac794eebbdea43de271b94a2b08d6f8626539a4058aea5dc6ac1450b1964cb9b1ad0806bab3565706baed62290c7c54c6d00d145e0371e8d6ce66df5f0731cf0ce0b96dfb44ea63b1c6fb592d5b45538392b76ca267ceee14b0460574df94c1cc673bc3c42e63ba923c9114d31a0a92f41c2cf4e0c82dbcb3d67fa2d1768e0afefce74cf49667274e90f8179fef486700ad346a1ec2280fb4ec322f58870183d2a3c8c603a20ffa5b0a832a961402836558d0b78e58d83052478aafbe280d5913f9ff309ea2f74388c787e9962eda0be02524697854a86d21a3410682b5672e330ef97cfbab276c72cc3c244c98841f7e9a301f56681b326913d4752434c1ca0b2e147ba58695cd91c90851bf1f8001a26247d8540b20bec78633204b028b5c6d3805e6494059b091502ef6eac665192443ccf078f3a23125ae6ce6e849cecd262b206f63e5cad787170f8f91e6dc71ef49e577956a74587651af1a8aaf92f1f0d855144e0f429a1d2934fda1ef9948e4de61413f56b03b2bb09963fe88f05970bee8afa0061b5e491fb87169c4f858a9cee560b05f76a36f4e76d0752f098425024de47044d421d6e4d08c2c75b28f070ef7d4f749a6ba552a50501b41be97c62f51a1b9e349f3d8f7a51e07094e2a496319260a8186616572204662195a58d336e5c722c35a0653ec5b004639da8b4f0fe0e8c2c62235cd972c987751e944b911aeff4dde1078605377c1bddee08122504e37f9f18f0a24c36db305f018879464266ed6213427c4c19da2038e197de0ced111ee041de09c183d1182e08ac2231dde2e102c51dbc4ffba4f45f2746e5054681eae8857c5019c40401ec37be21b5a58963e53b3f9fd10c1c689a10a44a32e36cf21835b831f45d02a6fd0f2eb245eec399d5d02c04c4052e6c775fba6fda18d72016ffc0a709c80cd13604b0f703fc9a8d66555b3f01abf6640840cea590f286de619e2ac7452b8f9cf90948f09ac139905f665fe77c124c83b8a7d79403f83a91c71a8d67488555c8d8ba020213e0e74365074971a1953e03319ac636840f6832903832a58673182484e944662241456f011b0778ea876c81f6dea69134687b37f8d6186e3ac832e713242a9912079eba75097e656eaf1be7837d781e952b7892ccc2e67701a687b34c63857b529c661517ca263778f3f1367c4c771150613444e6af0821bdd26111a685f3a07a20ca2bbc6e8ed12a3f4f95dce1b6f5a3fffecdab13783e88fa571e0ea5aab1a7286b3ffe0287754c45a93f4b815d7b4cc2b1be14e05b008a8d8c33831baf842d2dc1e01e9fbe8df46a3083bb5b275e965f13932e0c49ac0e0b556b586760569cd0de99d09c57e7b01bd30a52e57eafe4e3d087fea2a5f2ef410ffa7ba76441323bbe84556b4c3924f3ac20c26c88f7fb20d4d5c74703921c815d9a3461f1610ba3441fcfa74e992676f48a6e7726ec14ee40f18470ac5193a1c1a88e8190c7033a5c30a74e8bb81d38bad32c4bf24c02aee2326ab4e2b56a23fa12c0bd808676e239ac2a0f0f638d23c77ce262675cecda3f36c2518066c5558f17fe3f7e37727a1d0e96caef18f17bd3ecd5f9fc8bbdf7aa6d03e3e5df4a72e8350a257a92ed4a7950f805651d08a3f6a9554007dc2f9db6683bae2f454fb2a1a2bb38a7313edd41114d913b1ec0516ebe66e7475a8f4550871a8fef25a19f6bbfea7bad511a73ce962eb6d36469bfc36df2e170034be9d344d013a3f4f9395226c64f08fcaf7e3d98fa060ba7f32ae0ca8cb0f260e560c2b9e9165ef2895efd6ea145843fc38364445c5820b627d83154fcb8339a437a5d0cfb0c21958d07c6f92561e84dea778cc7b47f5047c06e9ee30078088843372bc0b7f4b650cd6995225e1760d7ea18a519482ba5c96919e00be75cf64c26cee9d2862b2d33a4027484f11a971785214d3dd316d388d560e61c064ec26e8be19a1e3af94a7a3fc4e059093f3150e2bc0fb1e3ef71abc4f75808af9db47c40671f45c908445797b43c85d341e5479a98d3efd26aecfcc513fa8976bc9d38b6da25556ff9ab51b5fdeaed0d33382bf3f1fb42511ec33a50fa4ec6f74e87c100ecb4fa5f0e4fa081a849667f586d3a556a9dde9938f1147d8aa8f65997d210d36f4a08324367cc52f17f5c19b98013c8f5a308feeb4faa3495d308de70aefad3be10458a099de9bcf34209d0ee74e5915a64d14e8e6fafd1fac5e448b7766a98b51c4a1ed139188955f78000d24f25e0f590d5c94ac2f1132359e3afc2471543ddbdd8f91ba64b26d9e9b54742fc6a1d4f70b48c47104f9a5514dfbaf4e71f9ec6173cc340fa3418356e37f7a5ffeca4b69d96c9dd0f17f40abaeb087255836c1e72fa6e2eeb56a17c0d4aa834bd8e06da5ab8bf6f8933ac01f9dad53f248898830ddc9b77be29231f288a4b0580009908b89c91e64be0cbf4550a3894302ff155ce3c28873952685433647cad812762beec69356e619798cba70ccafae1ffc3fd650fa71440e713106839f6e1d882ee0d293f848d7ca3f82d0ddc9089849c4c25a202e110829c657f4b205fd82241e88ff7f0cdf8cdd3f6af507559f50d021e67104bdc0d2d99224b23e252e15fab251bd05aa3e98445f00e9c839f21397daea53561da8f985e4afb54186573657c45ce039e853a643ab3f34285a54540bd52ff4cec259dae0aa58978d0532addf7165287e6388c27339e5580eeb42754e2c94e856ca08c366814ad255d383a9ca5b77fb5b9e47390fb9d2034a244f52852bc89e1181e0732e822d7f9aac4e5ef683b0c4df4fa3ebdaa8ffce283f660a565a5dc3263ea1d33756d9fd41f9242b7ac65948b4c432a04c133543882569643863b9ec852b6b7fe448aff28103c2253b0042b7814a3f746c7b1098977058eeaf6bbdd89c7ab82d3a1d739fbf14fd88911bcad82c1b58c88158403b305e9d7c8e28eef262270d7c09b851ace69cc2bc9760ed40f7abb650025086669f66577175343bba7481480f996cbb9e6d9949f025bd48abb79d345fb519b8f3fe1ea69c7df5d31cb98f1107d9ed8abc9b14118ea20be952c10e914fc87f7db1d33cd219977053b5655f8e1a9b6cd8afaef4b7ce3568da4d940810a2cb407819fa611014f06e9d5ffce04a0ec9599d553f478d777c3e8f4361585a2a5cfce682d2a5bdf8d8feac5db5f3560dfe8504cd5b6c062853d159da9862d0cc79c5e9028d3078452f49d6d5a556992a4e92ac395bd7fe955e63ef7f190a028ed72d438bafa9f7e4c4c496d28d4e32fac643d0b480c1451b6f5092e04d66a8b3a374fae523da9092f3ea5c3905d35d11a29eb88ec352392dd51246f837c654046ef582ee0b458db9689aee0b10261329845bed7980207ef30a02bff02c6de47781ad2acdc004c0cc9b20f6f4d2d983b3b772678cdc3e2b254bd4adb7d6619392d6ccbccfedcb53c1af9cc5c828fc69148eb241ef8bf4f80667be75d445ce305247116ea5d86f956195de7811171d5c3260bbea6e117fc81cf258bc8064e5d72630cb6f525f885ebdea74427d09042565c74e4d462f53e0be855427a4f7a98b4f4051816e1c6c616fb66d8542d2734c8252910fbd8f12713ac160c02b620683085c1d6b31a7a6803347e3cd2cd3f5db86e7bc74e436181874eb3aafeaac6de862a0f38780012bfdfa3f4b490f246080488a4b168b41f432d86da29cc134bb407e6562a270045491bbda757f09b51ec67126dd9741ba3ee0438cede40dca9cad94a6200475f107149dd3c1fe16fdaa6018cb959640d66ec3a9be52a0d44f075aef29b8780ac62d9b9315de691694312acf6648c3adc165a531ba47499e1897577ca8246fcea5c457791cdd44b362636af819e09a33472e588c7b80312885c1e82ee6ae684798932e62a0a4c3953516c724ae74dbd9eca44bf40a28367eaba7e0854553cfd0ab77dde809b0b85a2359b144d209e7a90daed2aad86ba68fefb2a3268572229772fb5aa73cc921ee98489c9d2e4f4ffc7884912a7981a21ad6b1c1d21980b94b6178882b21db72619071c224aa861465e9ec94b09412859fff39a3afee56f3d52bd9b29034587735b5b1c4b0817b9ac25f8e950a7334a3b47d941cf4606308d69daff36a387c0dae43c3c8e951d7ec2212539398c01fd47e4934608fa8d4f1f2dd9c4df7fec8a7f5bf7931229ade6cb6a4ab03884637371323f90e97908208ca120245ed623740937611fe52418b8ec720c8406507530211d23566db7d80cefbeff4c93123664b400ad4dce80c8009016c11ec77334d7db1d7cb3468969f6778890aba03d477b1e875186ce7e8b5e9580a52d29075a1a116cdd74f65c3db7042212c998f14fe8cd8187b184e30609b13bc30e2bbd9884b3a9c0d45be10d5c439e98daa062a90c6c08030c82855a0e86eb082025f99c4266b4bb830cca9a308ca5f5d75fcbc538b0990fc229abb1d858dea943fbc9470512bb98a33eaeb6cce6ce1a0653a175e520765ff7e89f0030b3a50052757b06228eb666036c5b9a1342842174c8a8073deab1dfb6427824e3354d3c5fe4ad8f05d28ee80d2f1e014330ad062cd0c98dfa0e03aa59c726a1f56b899e2624613c4838f9257dc3352395049b18c422085205bef0afef065ef008ddc1494fa5b59173b9f436e03869e51fb4fe6eb8903db7a60e6a03b20a13103a30418c995d4060b3863872e2af22a0312b99ec4cc787981b606f9b35f3ee4866a0e205eee27e281209d2b3e49bb2724236112a124f2f5e2e66231d148f544c17c172d29371e1f885d9001ebc643cd991ff1bf32407195033ed565a5863df97c0f84f2f0e17a3830b9e028deef1f1907e48cbbcf01cf4e5a67321b61453a044c2d93e9f822363b4999b6f547264f8b4a2e12b1b5561ca6073361634ebd637b017a4ffa5a969c5975f986bddb602b4f9fec35952911a38acb18a3e4b002772cd783635ddd344de8b34b503cd4b406e49d8478a75c8dccce7b6d3af4ab3ed9b4a21e758c403cf36cd60c7f55acb8af1d8f4389c30441e176f751ad30dc0fb6b178a74925c798b2a4713dbd9880bb8896353ac403e26a5aebe88805283823a16823b8dd2a50f00f60d21efde02ff81d1feae3de49e66ac02d7906ba53faf5c72ef29dfc817794ebf95b82ac309879c458363622432d5ac02fb756324aa0e13f281ab2d9ec0b60fee3660121125a3800404ef1e1400854e3a25a3acdac7765c24c29ae909ef0b8e1cb2a7834bd80ab3c4fffe0858a20b92a8aa5dfdbc486ef6382adb9dad77086bc3b831ce87f25c2cf356eac0c10b66b9656007f2347d9dcfa1a41f98f02e85f8868793ffbd61adb8c8470a0fb75c298d0ce73b76563fa6e8c2b1503d426f14d5efd49d38ae05188dd501836149f0ea89bcce3604070e9e619d694e5b1c7b2b1f92c6660f8bd1d14981decb0fe768c917d297ee8d887a3fd5a82d100e5700cf8aa5b352d5c38ab3d10e96aebca1a03f0b5c3d2bf12e7510eb584f5ae6d05a3c9d12e8c6041610c356090b90ecaf79956e4c1ddd4e6accbe52ad38757694bc08cbedba4987f9d01bce0b1442a4484a43cc5cfc17ac468404f5d14e066e130b3e2448ba8fb3544582eea2f080383ad38ed3f1011723cd472e2999f39328370ed987955ef64e7207e1d4cf50238ec42c03aad7dd6ab6eb68d6698f8701b9f9c96073e40d456b360ab936fa6df5427fda751c00f3f05457e5bc6af6235903914d870271e69be18c03202dcfbaa439a81799bb1e011501b735237310689ebc8eb8a5a7032080b06ee68e0667b5c32e4f0d46c4e86f22fc2626b7fc3b2f0fad0522c2886c58f8ee7cda7cf433a03017d77f440f2da24b14fc5a6048e432a99c2eb64c7f80830ee970a3d48171e064f7f7042cbd5f90dea6957ad83c7691cf70945931185c5f3a9c43e4ce110ceefb6cf09ea75d1575ebb186e00291934c2d1feca11a4ed573a647a581caf6aee832c821d63154cebb45824deece0c56b1ef2418c6c92027407ae37d0f5c0840af00b23430476619e9e903f02ea51f34679dbcfe5fe970c8f20513f1e884fd80d048dcde1aa6084e5aa51c9148e64e1fd13884156621b3b89b2a2cf246c2662fdeae770f69e5bbbec0ef1170242fbed327a1493de792f31f9c750780bde1579be9d75255de2c1ab0c694aae9823ec74e7dcc514f53ad81a58f691c695455d5f65d0528cd3a641a162e3a61751225a0f27644d93ad52c722bc0a6397ec920d9c814bd43cd96ca882a9a081da5ca79ac7e9a04ba05db0f70545a55215626730a2092bf7ab1d3051e62ba99479a8ff10b23ddcfb1f23758298018a43aae512fa378625317a834e8727cf992618346cbc67742d6bf878b0f0a7d8d8aadcad504e3106b080317cfb9f187645b3c333fee57201fd890ccb5328138e52b62585a7457c0e43d1d4e1b567685b7fec6517d7f98f709056c9f8a6899d591a1ad0f35405996537e19dccc24c1d72032dfd1846b7b413ea0cd8cf3a34bfc2e0e466bc3e44dee01a18249976c1793cd7bb93b6f689236e6cb0431e950db3a0169d7f9c4547b7620e4b867d452fb31f70d4e4f0a812c2c6385a9aa7f6e84c9c8a19037530e08dd5f7cf37a276d84a91c41d2d23af303556121053af4ad5a49f3ac7bf47df318daaaef0151711114dcadd9b86c21c00ce0f8001b96e335bfae36c7e055666ae1d6172d2ae68abcb12d1cff08490ff9d6ca5e74317f66a3b6202456ae1b77006fd8a5aff0ac5a7aadca17398359ffdb0b6743b32b566beacf911f9f2aa79dcf72ed8f136f140a9b0e1ae0993d2c93f867c0a5dcca506f0cd656f1167518da4e3a0f5853961539fa7895dd75137b788989166c3300f42db16c5a2e57e6cc97c5bba6f5ee85edd1a5a770221efbf723b00c6c849acc33d1294ba87d6f8d2d42cb02026f5f969182b0c5cff49cfa0f9bf0ddf1ca9a6ed41fbea3c2f1f205b2838e0ad93cf8f61d41a24681b224a1869632868ec81010a3e92ea89c7dad43986db8f1b0026a45d8ed90a97fe52a1def3b7874dd3be21572b93122f819e6753ebbc68612d18c12f796aae1ad7a8000cabd90d02043a377ac7aa04de160ecdade8f512671e8207dc8ae232023b39f96f34e55df5afe3f0ad87181341b0b527c8a704284614e1eb5fe53626fa5fd25cfaf34d47f9a66e4b3a37a0141174a444fc9529b318f7e0fa958afac347c619300e67a4b3892afb46b85d23dab1b4576dd99dc7523284f5e8291c76dad8ad5956418c0209d4f3fc034a82b7bd9a6644ca16aa4118220bc9ef04304ec89e5b721b5c8bf05dc35115f849a414aa2db132b780818ccf1fc285a68153b6dc4707ed2ad181d2d07542524fd35b4df353577adcdcc9683a0a7796479459a88e542299a9129fef4acde5403cbe50050827180e9a19ce442c4b045ca203da904c8153d911c432d8f12d9c1bb46f962ee43240bfbe1c1c9e0d50f147adda756b28336e0d9c4ee47d209b8b7ccafe246d9114b2367b48ae4591d4c9f0cfdef878d92191ee733641bc9df84c92b2ce755f14bd32ec028dd60f2ae5a68ff45a0bc9c27e23775ea6fe5386a170f4e559259305183168b421aa23d5829acb0115bd45f594051bdc3fbd96a4832b1ae08fc486bfa684173e7cffc9c4d61ce3c83523f766efb1afdcd64d3669c2302b302ece62ded708e20792198aff31ee82a1b0cb6e6e15c5ad33a236ea96db30e64151891bbf6093167b742332bc7715dfed13db796990fa6efc43e07445ce3ea4760f68e0efdc12567bff462f4bfc030f196eceac6f4ad691dae0f97f381545cb22df1557f9858dcb87cfbee24bb30a554cd935aa902fc7985ed915ef71e068ec3a7118ab975d009f521f619edf7e545e1b728378c05ec97c5b8412c2d60c0f0d95f3645217b90ec8e95bfcb99758f7b4d79fc48e7bfad6fd9636a8cae2b1f47a6ddc07e09ed85cd59faaf5fc1ba45ee8baed463deb5ff61832d74be40a9be7db3f8524726d1fa0b12a3222747cad9d376e5e4506942eec0366f9da85445d570d2615444c84c510ff3c1fdf969bec6c4eea49a2a60f277ac0695a14e6a49b5f199f6be7df7e4719946dbb3aaa865dd969d598b3b2c337f50236fea468ad4ecb5bae6b0e76a4b669436dd14a38720450338665065c783f4b6c34342ed0deedca146878750cca2e47361b1310ccca0045d659cbdeb863e7d133f7f428ca52524242f5727858ea980f1be414d71b28a314105dce3239f2f265394035810a725cd543725ab842ddcb8758b970c7f849fc881e13d5b58ba553021bb5c433cb16ad75de85425880490a467059a6ebfada32ae06d2d9d5a43deb5c011c3437b8ecb0ab614f4b15a53013846c593e6b7a832021d0b6143275f505a6b65105f3aa2cc05e307f16f4a698662e98f7c98fc21f534605f8f72261881b2e3bc674d0dbc2fdcc3a04409df507b2d364624d6b43daaca0d420d427bf66c2603ed4e96097f0bd2ea15baabee21e75c523d93729478e75c7201433226afd36db5d0a8710ce24946aa6502aca022016b5844e98e302aa70baa3d7acd843ed04dc7646e5197a6d270fcab14b471f91f240fddec4b8bc6bb5bbd1140797afcace155b9a862c88ec367d893f283af9c05c53ac563c50cda54bd423d72833ff48c2359f4c8b05fa868f0f0293ab7b69b8777a0f7113f48a9a88b85c60f2dede33ef1789afe113bda7f11e669a65b518120f44f89a886e67fe9aa62fcdd491d1dae8b3cad6d8e1644c4cf9e9a6c7584daa12408e01c8dcfbf462b18cc334196953625f6b81a1be8aeddd05f12cfff5f1fc78af892050a86eeabf27499cc41a6ef4694dee70162d20cc1c20e6302a848c8e80ff40ddfec28fbccc52a3050dea98d3441033f2d8901f09b3e1d9340a1d4c57bd55bcb7a457b4ce404f05ff6230b12e1f6ecedea9bae6523abe331a4220146cc87edff7e116b6caf0050111094ee6e07a322680614c80084b8a106f53df2f9a73a704430e7619d2610fd1a4a801896409ee6e6672264d1a29b614833f11b9cddefc611f854a9783325905820a923f6740d78ff7d18c8cb9917e28e010e3f8c9aeb91669abdf873b7184f4dde0e6d64574a2b767312a3165d2b60f51328b8aeb65f11adba09d33ba5d0579ddc923a7c1781be897991c0429472ac953a05182be0456a9d3aba3da14d967fda605f5de21dd3e6025734fe3b79cc5ed7bf323e4bd38670b1e458c80016be287e7224bcff622a0dd963686f525108ded8fa7a4b7896e338fd66190b4f1fe0725a71ee1e7c1b2274c8c581fed573c8d9b58e6402e2710fd752df5a03126c3a1b7d20db8961069206758e23344f761ff631d804a7e0b962c60db0d3c7bebedab43743075c84f84cd320c94bdc22a3c805c2d70e2238054dfdcc0c225953e1149f6003f3fd5dd86526a5c90d65594eb9e621e9c2fa87d427a0d742902147b010aa6c2c3dd627eb1bbd8be6b103cbb3a049c67ec12ee614aa5337a128df61d94a3fb8848924434051b6c44d3644d33b9272711a2a3663055e3c3a9de5ca16fb215224a83de055106c34b1cfb8c6a1ef7d177c6697c405996c9a2cc1490fbb623c2944980bf503ffac2169f7c73e51bdfba71e11061746646a6cc8f8864f1764a87db2b09ec9c29cbfd389aa858ce227da2c38e630a5119d363e3d06f1ff784a047fbff6f93e75e48a386d11b790b843f6286e28edd73ac1e4b1bca6f861e1244bb96ec160c2b520590456077fd3c6e5b2b9b861284e6936c6d65cacb948bef228cdc053ba773d60cbc7ae7ea332fee5d701bb7ba5ec6ce6ecc3684226ac4951c40d65353f01d12765a81bf35110232bd0e17916838d8e808928f7051509227664275cb4908ede32f34acdd1c890fe25e632a3c96d6033ff9f12f0d9eb2e8371dc058d1e9337fe5019329bd543022dd770c025fe3621c37313574dcabbb16375dfabc89e17ca63ccd799e5098cd633d2bacdec62872e179b5e2f932f13ad082ee9c56639fc207a6dfcd4fc8836b2b14182fc7c9d29c9ada20a937b4c93d7daaac8448b2f7a70143593c576d6ff5e2cbb65db63219ec69faafcd28faa3385ef3b593dd5424acc15e39c9f31be3afbd0fe5463e1e8cf42a646050944360e6dd4571d3b6c3d9bda5ee6be7010317feae0db6d6a55baf0302df1bf78f52c2e9536accdf40d42c936eefb30d77708f38bf740766757b184d172d7b3a64d12bf52b06a14cb2db8f9a1727051e3595e54d724da525bb8b47eee837fae93b928aef8e4d2e417b1565dbaaa7caebc313d8a2e8230eee23e1c11e97b900badf8c62e29306bac4c3912c73ca5806ee0dbb607327d0a3cccfaf771b6b46b3244723372b8d3acfd481fdb4f00d59f4cef54412de461281d6ea74dc083e5c91e53f9aa69d33d3aee03eaacfa1a5506818bde4beded321080384cf132fcfc89f96e506ad39ec757f97241ec966add97d4ad6fc20c1777c736e3f33708ed0caa24880e9e965ce4d43c0648c6290fc1f26a11bda6b2dbaae8fe7d6a455836d05a2f118a22797f53bc50af2812f65b0be77242e60bc53936221f524e1b51acf421c416baf285e2a6ab4ecbcd7d93d410d5db13c575fd5814a321a615cac6c39fe40723195047d2dbf5aab1a054b1454f091bc315b7eaa5887d1985f9ccc0fc2507be2cb695fe7f706de95cde511e9cb97ae9b929b99f28bc1615556c02dc79714c7954908eb895b199326a3ff625047dfcaafc3153d9265d41353caafaef12d2ba268b7b9bc32f2425673bb763b3a4dc3d7be62bb340327ab8c6b8b3799d68b38d07295e0d430e684021ee427cb08684b209b7122e0888c4b4e1487a21efc85a1095c966e46382d13eac483a6a3dad1f4754be4147264daa79b4414a37dd0174b984453cee5a2d50e2c92bbdc3c04adfd3c5348bc6a37190e54a9fbcaa458537c102235e1705a6cf2e337752ff0fae964d8bbcfee8a5ed909c45cf99613d2288acbd975f1a971cb158630b3f24091da9a7f5d7eb346f88e048a750d7f9155b0203e83a724550f1d5d583ea22b1b1fa1a32a886249ccf7f78c5eb8dfd575015fe3ff4e087320096761e1a0921b372c0ccee792bdd992faac2fda1d1147f5cbe6ca6c60bb90b39d9c90323d4bc4541b3ea8246a0e4c3267e377d98628eadb8b8d43fa20aaad6a46ba3990f39e9d16e6db561f6a3a9bbd873cfaf6c5754b547039610964ad0b1b03491f6259f9b0b088b218c2128c7f49d38dc341d95e098a670345ffc6dff31a44ee07ed72a9a5ebb3b3b3730520d7c3524fc1ca53348c755c55e0351bdcbbc8d6128621203426b883c9aadf47665888b72fcc360ce8fab3d1d06d05d07f7bfb15930ae2f114a1e81b15bfbeb012b1ef5daf63cf889e3a80cb3176f107350d7961652df2225ecaaa7133cb1b75f45c5e58075cdfb84686d8b7f9ea3360a918c7b637acb06452b602bceed1d4227d91fc0c615fff6151b8703057a27c52e5e44371aaa9e7926ac4b212c9599712d7a1e594d4ce40565a2ec4ff60f03e12365527301d72030c45bfdc6bc8e517b9bb6fd6da037585d3c26af40706a0c4b3f310a799dfb392509111b8803b70893b70352e39ee1671fdcfb16c34bca0811c5800bdb9cf6a6e7b52b8791edc78af860e15ad5aebb71fcb674e1430a93f512ab57dfbbd7ce646137e6ea966757b971fcbc3dc478472bd16173fcb7fee4174ad9a762ebff7c75c8f689a2a2dee3f73f9b08bac83258a1c77e17e6215a10527ba246ee7f5141445033f823eeec6b1a791671150fe9339148a50c11801f14b3df6c1d6d08a74d442c9e76087699f7ef4e31839eb2fc987a8181011be6b9d576f6b885610ca93fd0fcebcf639909b1156a195aa14cc09cb71a9a1aea83726a4896fd29f1e80032a154973d05bb98431087f2b4e86d1bbd8b6aa939342cd41813c90c4aaccc43900dc0af6d4728ad27f0ba8d1b52dfbbbb41340fff30445ee1b4929c1da3c6ff602bb6691079193809e64b0d8836ca4023c3faa20f3106308c64807877ec4b881b8cc8f4dc21a075f3325ebd5d288b65582ce5bf3489bc6a9645989ae91edfc51f5f24a758e225144b7e7adeb3fb7513a456798e2c87b46f5e72e63d8be6f626ab82a8834a3e7deee48346d014d6b67a419869b67258c6223c83266489e7ff69088bec1ec185bc1d387de4f84504a39e715a6a6a7af1a0ce1883c35adda840d117d580954982bb444135d1482796461c7f43632e9c02384d69399d7c8bc79ac30f1ea855fa1eaa42e1e4aab0e752d07abb13f84f11e3347a98bc489e46ac4296c3fe20929135ac0542c20febe6a21935d264caf8190dbe0a74effebac8a962011a88a38ef3ece089cdfb9cc334d91e8e3e9c5b0bb35cb322a60f5101a103355304930458049f1263c2c09551b6e869a5077a2de4134156d6e4e7d38505e20fa2e96ec40074d58e1e84611e295062853fea19da939d301a4e81d740b9deebd4df5a223eebe1f8668d9e1bc6b063335e956755076baa614c489c8e7a228aae3306093e7b1fcf5d9e24169c066efed83dedcbd54bf2e0959c70c6342f0613a9cdeddc066c6c49e2772b1b8bc48c2b1c8b9185ef383a6c47f86f9165161aaeab4f442ae89b7cd038d0490439badc9df916a7ad12309ebf63fa431fdca25c14cd2042c607a57c938d8840210d6abb472943f8ca27911cf01d6116e27a8b6841f41d1c557eaf213413953909363339989082875a8391932aaad10b25a2d9784a4ad9a5de528c30641dea5651c8757e2411e1fabce55d52687fc69f4ffdfd6d3a1bfb32e8dfcb85469cde495235a0ceaefc672c423c9c1a5ae12a8451e01b5dc3e6d1f5c8ec6ea21962cb95b58e28dc711df0770a16966a69fc5b355bd82bb190ec9ac93676ab4597d69ef37e6aebccc0c90418414eb4e012cb140803a6b78459e2f5bd0db1f1fa039e975988b4e37f58faae41413d93f09b06226c2706a33a43e9c89c2795fcecb52f382ca1b708287de8ba1d2096d84e6767d8062d0b205a4c61b53021aa342060a7fec97b145bb18a01b2039c99e897534fe38ca49828f71ba8d0d269ffad4da6641aa806ac5bf5afe5fe82dcf5e494e76c7e33e4f34ca66faab311ae07fc08d39ba14119eb15774ae5261e257cad5b330b7ad25b8b7ba8e23544977b0efc74f9568146248cca35fdb13146a6b250ff2f308f6dae31a7c007534eef0ef96d4ed9e4ffa86d5a27fe0775d44cc470a142766ed34165def6b1858ca8a93a001f203d0158c81286196e411f723f9e18d816b94e693b155d507ffb128ac6ddc0cdb1bb7ac7dc76d95c7984156bc8e84c88a1c41e021b3528d306ec6b862bc46bfbf746ecea2374ba54cab11e941afddeaeb6acdc1f48bc374d70827118a84644193ef9bc01844dc51bc3d757eb708dfff3adc97940b91592de5bda811f6fc0f27272144d52f7c854f92374293642cb90e918e8fbbe080e43b9c06a3cf0c3f1ee2ed17a6c0a8d5d166d4f0767af962167cad7d8b666e8fc1c46c5c1fee75702ea475fbee07f10228c094838ed2f0f8e42c92dde475f02dda5c7ee7143ce3372d7b3379784632fb04872fdf2110f7cc9df76c0be0bd0f18ac4214b4d88702ec77d94c9694c4ff7f0019e6ef9b194d9c3799d2c13171a37b5dfa5293a19ff0b304c6d63dfe7ad729efaac0414cacbbac2c141bc96692cebffaa3704eeecfe0d9a182dd3f589fb9c6bc4fe7ff41ac6d641f96230c260e54828dc666fd3426a8f7870a015d7cb0a0b7c89e80caca698cf10c130140a90e1d6b279d8ea0cbc1ca106ebd7efac3114a9fddad5e6165cb93a1f56ec9fb1a4dce395eecf7b31968cfb6ac2fb70666187ddcfd625ad918ceeb9085e9eba41b55a0ede85139dab7aa7dbd9ae0d353a84448d0896a5881b7d1b0b160401a7eb7a903c23d44e827f322915f846895fd4c17189810c7336a9662a48fdadc6269247b7c10e3744e01868a014a24b06db37a5b24c7e3fc345c231650ea8e6194946ab177853b4b8b8780aa53d5644e7158fa659626b1e3d6bf99c742a50d58c9ed87d01fb8c8463e4e2f046c1ad721229f9f3a7f1c391da8c207a10f355a1e01c998fdfc7ba9718e620d1b62ce28879c4812eb7f4351a99e529c151e995fa0f9a26c482383f777ba78fda3ac607adb58ac33878ea282e9ca8d5e69cd13c43036c503d09d36bbc9ad84e485ae1865070f892674a0432796dc3f720628207e7923657190601c7ad2f39a1bcf2e725dbd73fd81e04fb774412d3b22c172223763fc147e8f0711df1613e0df05932e68612177cba9b8a41bfc4ac6fce14a69399ac08257b083644ca549ba47928b938fc6343422db359e57b917cb25dcdd28f0a430fc99687d2bb09727740905acbbe0e4c4a7812948baf2cc8781e0a0755864a3aac514f38f844e2038213ab0d8e18447a0722a0b56b42abf576eac355413668ef0c705a1dbe6a7e378d064471ffab116311871244d3f775c67be1640c71a8343c58be30bc6d331a2ae178dee03a7a319eb979b354c5187f77ba30c206df233d06c42d80276036ee108cfbbec3615b708166f05c3cfa0be487a5e53c22a865937e53b733c590b872a7abe45acbd921f9ae55ea9754928a661ac11e2a489a26b2a80d6c63e126159df6785f534a0b3186ccbc93e997bd0559bffd3bb161c27cdc513cd202fc2bd8aa8e170c6a25dc8bab8438162893af906492eec5696e9a1f22a9a569d84da88dabc6800b8cea7b929c28a701c713966d0e067a751e5a58a9b259f7d702cad33cdb6e1236f9ebf3aa8f96c05603e7cad3fbe4869f492b87c0c279c6d8b4f0ae2c8f800991827bd59c2d9c90aa1bb5303c23b9eb8f76a7a6033103092dc97074c8e329036a639a62d603bcb03d56928ee8e112532558175a48b77a9fa281e28d39103eafcf6f92b2d57fb604b4e6e28e0208a3473747e020b0377982e512f961ea26647ded5d551923be3d2b862787d35a9f06b7d3e8a691d7b3a7be7b34ae07e9e8c6dfbfd4fccfaf40eb5a38061391845971ec007fd9d3a76c4af60fb72ffd40de8ad2f81e9b1a2a7deeb94d82b32659acbd452672a5fd688e7e7705223ff18e625750707bee1875f97b5cb78e3a9c313f6e1796b6419beea4538fda6d0f71a8e9215091f2c1c611e0314881b22314760445439035cd51be87082a94a0851a631f0935453afba640ee034c6243b0156f65dc7d0fe393544ac9e59e75f74e39abc904c36af0594bab6d000da24717c0581bb2da3048cdcdbcfa1cb9b13321a96b9f5a91b27520562801d4de84d68510b616867ac08012773ff73e62544875992e40229cff80919d9f440489d37f03c4149d5baacb4c3c56400490d2fd56ac0f82fd4901a2cc25d5ca3c00f77dda0f34a2e08d0397a9cdbff8cbb362670ddfb1e00d4b5390dc8e45060bb00fe035b11052ce9126fa205d997b4664d3bfcd9b557357bc991abd73e7f66418a18dd8b141bf9db2950aec399eb61f9e32862ee86b711d4c4a7bb6f1fb03861c2f2ea05f9a5b19200dc060505859e8635e7076984572305c524a0d9766dcbb46853655d8333458eb6e3ec41f91570255e7df45ad7c55a845b7927f5c417b46851b619360ce0efd9d6b8275e8c54eb14e4b68ed75db089ee87dd06edb91f056d8a79fc9925c3b7170a20854b0dfaa9966c5b5948840caae835003f22b1ca43420d9e10c706ff3393b21b9dc9a88fd483b95d6c7ec13adaff7e91c9a37b86791909f93b623e2a13255ce5027cae106457a0aeb6568749c72053a1188e295c381e88415a9ef4aa097508b7f52058b6db9b06140c2875d42adba1e4db427293659a87c8eef31ea7b09a60ed483e6dce821864ca327ff769be32bea4212a200f52d0c359b17d4b597b88a19298e6399441440c73e4844b1d26a3bbd1aaa44cc5404eaa12fd45c95a9467afeee34fa7d8ab3a2a68324757f4929cbbfecaf44e1f6ea14c6943dcd95e489b51a35b728b61a52e824a83b84073b1ab77138cd82a3f3c40e52a98236612669f54fc797ee69302e0b94841e205977097c061eefb42389260b638b50e976e083a5c6b835d527a5ab8eb3ae6328958c37c803fd666ddbcbebb81b2b275b5ebc1c0c8c6395df02d5bc58ac5d2b1ecabb495cdf87171dccc01c36d40c90d6e53fb0618c7625d7e247af58c55ff63ca0455f681736a639a4fba21cfa537f49a42c00f49278631df0f0e9f4e83c03e662846bdaca07911c38885a384820157f33262e0fffa2d90ea836064ae3f616f34a4c496b1bfdc4f4687ffe859be0d9fabf3ba6b2a757d12cb905e8abe5a8fa7fc9934e5545a7e42337fa043a2d93fd480ca6b077d985e4e7913c510f4a5bda920419cee4091f427e1fc76c80017d2b4ecc955f24f0297f3cbd267e999cbe5a0dc7767fa42e45eff861b120d6ef5bb6223897cfc32423ece5d421d57a9bc0d0fa25448b750cfc7aaeeabf917051e6b19dd30e152f4e44dc0444a72ac3eaf5f15c4c75639af54cc2939b95e5b6edd3bcbbc73d7f262c78c3956c32d7e318dd1ec9255a21ad97c500c0cdeac755c3204d9aced61814c3e3f8ea564e5fa4afd6af3528e8e9689317cb01116e5d830facdc39099d147316241b8f8cf25b954a67f81b32593e73dabce9d24511f98ae144a51eb2234a30381028f70ca759dcdce9a0e61655a76277caba0feeef0a76055f99d11c03ca126c34d66f7aeb417ac0aa76ca7b7b6541c7fbc4fa7c48f2e1b3b000643cadf2137cd33e8ad3d8e645c3cc6c603fbe3c32630204acfcb5d8f69c2eac6370a3e57dcdb5ac9029d48dd4e4f52104e58936050ed38c3c57dbd27392a34dd941ba0549a14ab0e5144e8737cef0c75755d9ab704d01dbbc0380a4733ed0b5771b29b14403cfe9ea194a4a6d885504d475aee656c976439cca9c3ee665c6af37003f4d62b206df05be7400341e82d10cde6823843d11bbbf2debb355224ebf5e7349255274fc80c3985a8f4df940610102e84e4dfc94fa5ef71142d2b1b5dbf68f9f10d2225d9ac9139276d17765847c13d00528a6329271a396e6e465d7c88803453e89300b4318d0fdc0fc6409e6fe41b0ca316fd10e950a72f8811e50181190e0cd0201af26d8f04026f6c52575267f889891bca8474e6660a08f0fa92f8ee7049fc6f9c600d83f209364b585e22a336f9705300c05656beb626014f8e492ae31d40fb3182f94f02ec086db7ee972d355c21951640ac82c43741e369ed510b8ee195cf53ef16487941501e27d0fc1beb2694172e1d30f0f1ca8b23b0050b02148621f766e57255c3b23859506a6499c1bdad3001d2fa916e4e9b75290ec3808e9227c4317fa13d3d5195407c2a9e746f8ed0f5413c952944b00b0e480017b89307e94728bbcecfc623324a127029ef91183baa07189dd3bb69600e881b5372d4703e024918892e46602de09d2c463cc788a70b7df7f161c6f29f9dcc32c0f42ed58971996e2ca19a24e4f6f4b4992d4e8cc70edd12a42eba26d78b1fb8b3cf073b03695006014232e6865bf2c619857276c6caf5148129ca0a15adc1d262b956993fd653945a40172e1905fb80e60db103372641858538c1dd6e576ea12abb6dff273d4c6f27efcfc2a5cae361dbfe12a00b11dd4c65fadab48e4c708fd4f4f1c1539f5fb578a94114eb1f6dcaf834fe3154ad37597358f554ce8ac5c01ee178405d3d27852f6147d306a401b45774663de43f055fcc6afab216cde1e458f5f435c5896169bf373917b87dc9b2209036be7616f44b3e6e0c88a5fc7514ab5f27ad770b84878765a9e12df044a382d30ed091c3bb4d4bac259f988f6ddd081d8e51837e7bae58f3c08f6f64099233b78083e702877653205324cb66acbe2e24f831d8409a3424209c70efde7dfcab41032e19aa88fd0af13840158f92cef5a1dc8a9b9b877382cb26336289e33a694fd2dbc905698c791b9d96e9cd605f69718eb082c41adfc6cbfa6f8a788dde7b7e9d5d9c1b5980dd090b7ebb0faaf99677789c6997129a1a5a6f6d4548bc98b1a65d1d360ebc8dedd14202821d28ce3e3980554c725975b5ef818901ca23625cfa6aa7ce5d636ea7bb95e370b1c58bad634453544bc82ede5c547b2c513122c81d5982877b3b2d82f2b49db7977d3502c452774cc1a066ddc5bea498b4ee69b61c19483ae317824a8c25e86a2318bb883a64ee1a8b5caab2aea9400f54a90dc34cb063e24e8357fbfd6a067d7a23d05c80a780d5cd58bd59479f6292d5d8bfc029d1b2e311a6e6b6b0a3c7f94d0d0ee735a2edd06824dcd136a0b4064be632809bac9db256ff58bc2d792c23d11c8c4b26e385af1a408b8b4db6625e68970bd7fe972d349997fbcef63e02f2544a7e701c95000aa5870494813d2ae911cb86d4708ab823c84c8991815b217d80973b8554078a3657774134c023558c47cedeaf583e4f331b9940df664a1ebbc1dcf40c49c8cf5b6bfe8f17fe9698f39cf098199de2404666201052c64554a9a4631a75f46e49286105402f258c5a89b99b48c5da32416f97ee6915a9bb49ec2398fafce2ea24f911beae4c303bce868da5dcd539cc478d26510a237a6b218b4724ff3ae408a926ab035112a63681c2b5b8e83a002475222fdad754b4e58ecfea1dde316010fd657fa174148f2bbcce4f5d51ff3483114349d502a6d560373b52c7b522946b3aab73ba484de49ee24f847f7fb09678991464acc3636cceb4dbdf38e7ffaaa197383007a54b13cfd81890ea1b1109f36e0b27df19150bcc3e4548b962666fafe81ea0905f5358e6b1e77cdf876ae559102deebceccb196c1b33a2dd6fcd4252d1dea20cc6e5abafdd1e1154efca02e92856aa200a64e5092ba9168479bfc05a0059725c14b74d2b44b4d63ddb1b23e29b9c486ae3ae088c453073f3364ffe4f61abacfe64c96eab1b6bc19cf97c353010212f450c07987d46ef1db9ce3a01755bc0fbc3a225c590b990e736152630a0109edde38b5bfe0b1d31977141c713328f53d9bebb1def9d0dde115a77382bedc9a4736f3c4c5b2dad6c49b5564589ddee2649a8666e7c6738a9277a02bb8707f2efdfc05f370ec1644c00984b9455ab9e94cecebaf13a8f2386d3cd4a5f7674ed350d6aa335a7e22485e289372b78b69441fe6877d6509a4a2e761712076e0fc9839cec7b2934a78dc339fe74185c7c5ca1302e1dd6d2f59f8daaaee00a3598e543a89b5a215adf1ee521a660ed4027f794c1fd62efae801de0eef4658fd192e57ae4d63bb37ba44ddea5a16d7c44850901c961c28287192809858faf5c86b11f7ca604c83164eb80cc10a9d02010f01684329e9ccb916aaf1b01962589c9920e09a85ba3c666fe4a0a3065d3661d61677719885fe1782d7ea1bf9df1e32efb4547aabd78b0c389e421dbbd5143f91977b9e73e731a6eb46a623d80300235df9ebc1ae60fb4b47a07a5b7228ca03e57e34d069c069916035166aa6b104db4bf7516bb328ea10ed0fe097d0794a67c9b21564d84b53891e028044f453e072aafa94e0e999ad231dd8eb6a819172824834ff66f8bf44d9d30b81f8ca09b6c58ffa4352da4f5cc00f923f9f7fad0a0b6050104d1a1527f031f3b4f2493a7c374b351d01ef97b6e37db22b553afe19f8294cf9e06f7e11970f06e398635803635c11684fd4e7b84c16a1913f7613d1cd9691504616fcae36af02bf1bb740da0cb623ec692309f9d18bf33ea8415d71c49f5034501236ab6b71d1d2d7fd1a9ea8df45f0472cb736a989cacb0df8726b6a7adb6564ac435f698f798514a81c9cb3e5dc8cc370f2ee321bd8a714af01b8534faf406e8faa5f27eea5be93cb48a0abe621a157292620a07c8c61c91a729a4b43a481dd23ba4f82d4630035472c4f83651d881dec8c0449a27c1c7b0f242708cfb51dcf6f6b100c48ce25b2513f6180e51edaeaa91c98a2f26cf7e79cee3d2a2c80bbedb34616a02633bc29900ca36231b4b1a91ab2657d52c4c2e0d6528d68a5fdc6b82cdebd46ccccc528d6f1f5cd4f59eb8f5531fb16e1d8b6b7f8d36a21b9deb325b0b2c061196ecf0e12897c8de5abc369bcf862550ab64e4a9b8485b763fd9cc9bd2df044cc2a3fc697b4a67e29d8353fca43deb7b433eec8cf15d26bdc92df3f71c3fbab99ef514d19dae024a801bc2ab1a7abfe904b5dc9a2616c84dbcd46493351f11f25a8c29e0056c0557a1724b5f3e418455bb05b9d8efd7275634ed4d9a0abcabc5bf2a3692b1aa8507f4a5ca72db1dbeda500a3ef028d8093aa713e209e5fd7c695675454a68ab0d5b1e5869d500db412562922f1c8474fd3428eaffbe179fb66b78b886f3e6590c914b13860b5ebe1016827007271bc6cae5bcdd729736af01edbb3fb0aa8ca4dd63a3acce03c05d367b0137e774f47320ed4853e4731137f00d9b387f11ab60a68c76627bf348ef3adcb21e4550dfe276c143a7a89706d9e4a06dc94b9e0ca7af62cb4ba9711b01b7a4149c43fcf30db18339e024466ca0af5e89150da5afa32c06c61835285e0fb0173092e02fc23c9b603ff4e0c29cf0f1eeac929e6ac7d8689e2ec80df3de9d83693b31163148f7c3f951699ef7a60899d5e0241fe67d43950ab4010c1cc8aab0df8e802a8f5a3e9ffd1a4965272b3d3a34f90cef57f00a813283e75934b77304e3963ae79e59aabc09b06ebdcfc26df12c125db093854583d27dc44c5a6e65efaca7c99e0ab384e4b193b5530caf50cbed0bab51c72ac8eaa7ed09365d860673b31610441ae999e088dcef8d69bf1932c3982fc8d52b056df5717df080e5cac7799f37c2680bab493b327d151afc5d43fa4e0ca3444fedbb11b2acb2218aa35c2275a710c4ca8319930a1b896ccac0862d918a6dedbc1cd39179fc4d6b5bd0d3c8054e1c422d19ccce50c947069c1a0d3f9569fc4452e9a18e899b568f8a0bac6cb2d118d8b8fd75363ffdd243aa72898eebbed1b5872ed3d4170d469f533542dbc5f5dd7882421951e8a802bc0bf9e4437d1292127205ae1c53e327ccf06efb5207c7fafed9273b01b13e1006e05cf629396b8129d0ec2e522110cda6c515d2df3a14ad33aad535fb1723bcd56d3cfeaa3d94581258321f48c9e1a081ff3716c55007fd56438c4c7e1912ea8150a08b78234833d9571e644462834cce9f10341f5563affa38511ac6ab10c481600a07b7ab2af29be3b30902e4a0966ae0b24e2c1ced9f4ef9cf40119909798293d73c80d9d850d5ea7a8943a88abb94470324013e06064cf31bfe44e816e86a987ca298b922a921e78c487c46d26367cb6e565b2c1cd77382e58b6af690e5ba7d8925eff6fea4e73ce92cbb1d11b82eab96b732bb19bb95bc61029f4c95a8c82b97373a328cdc3ba661407c22668fefd8830e862b666b4f0f3cd63933504985914b03f55bbfc143036f62797a79ce738a93dfffc34c83412d5041cfb739acb8c883bdf01cb6348d4e37f033bf8d82559f3eaf9189740536f01a4fa3c0205aaf19e893cd0eb45c7cb69b6793539592663a22371c9baf26ed0c36e8ad8766e67cbb0c64263c41a3aaeceb47d5d7b916e241c8930be4d2740ef51b450a44b5611a2afe304440dd61f6d44c0f9193bf0aaa437351ae0d8092117676a7083fb78a938094c0074bcf90f07b1d24550c3593b5f2e3646ff1c0e67277aadbe9975a0338792ed93573321bc7aee4cb7d0a60f05cfc770caa580b5f4817cbcd1df0bebc53dbf2303f9ce4160ac7891c1e97385b8fce8e9da57be1dfcab0be677682ff5f0c0e7b966eae835f6b22a9888b745bdede0c6c7c97c2915273cf305ed3584d948a0fa0380d78f0c90be144ba234979a73e53b2307a9c2a645181e4a5404c991be02d7cd6e8ff80bd8d2673d4276c6933d0f531c3305c5d8946ec18b14456390880b8892f1ef9d2343b8dbbf50284b75584a3fb087b853ba09f572958b680ffb849e19c744ae7e7772f85303a4c4310f3da60d5d1ccf3feec964762edd34f4bfcac776aa6da3e219c3e826331c3a8eeca0e82f31cf3de5b44a4a771eff91f4f636a145187af76738be4438cd4713be370e65e3f95b2a168159c5062d510537efebaec25f10f0b1c71205a59f03dca48f0f44b87cd3cab898075de0d99039a7972e158c5449d0cbbf71eb248da2bcf9e2b45155bf71950c882f8abb9fd504ecfb789c7108526089c3b6911d9199d19f7cdd16d5aa6a6b8bd5be8cf2bed03c6f0b2d038184a41372df8732b584ba623a3e4864bc1ddb7e3cca1ab20541de411f9612787b8bbda70963c1251f7a1a874f0684aacf56fbe2bd467891676098cff20eb46d043e00346861280a542b3df38b986979eb19906ce44bb2ba27ac141be0484f2f114066c03aeef3e4ed01f32f0753b231d43134659c743c164e10fb781513326226f4102dea169f6bc972730f502357b2ed038b437d6b997469aada906d8861b7548d5828d17c2e2dde106d8fd41d6fb339c90ec8c2d92b2d25485b58eb53227d7021cbe53c938b212abe0ceb4b0386d576dde95fc9b029fb2edbe78c2bb47eb41f4a03aa9ee45fb95f746ecc2e25d4990ffb72b53058be40d65c31616cf9d960dfeb90e33ec5fb7e7dbd85ceaebd26e5fdb2102d084bb6d06b41615f10e243f02cc351cbf122071bef8ef74566a093d67591848175af8fdf4a923b3342431733cb9f8c78a72d011c61c852d738de3b05043701024b48e9b7a3e19d31a3b57d142a76888a26d7b08ad61b9bb4488ca37ef4e908483c5a961326f769ef368539d5fbf154d89c38618ad798f06e2d578fbf021400539aa3c0a14c8c99ed51862220728d110922012655580f9437ad229f40b8137be5e223d04dd6340dc89fe53b856298f7bf1a0d55e34a03770aa65142731095f1b2763011c0b99f134640dac608b27eeb4ceea0ce2188167132323a75054df653cb992a596f6f1381a79f9f727b525efa4911c9f11d20d3373ebd760aa7dd9d78fdffec5e5f4d20e928fe16e109afd5a9435d8f814ab3c5367a3143178e079b14429194a7f528d8bda4e7100e7b469c03de74fe3d62fc4266a0a7261328941468aae162176ce5f891032d83c3af573eda3ad66f962e908012eba3a795d0ce9491a179c52073e414cd0432083c5a9359ac9c5057813cc32d3ed0ace714ea0498c7213ea95643278db2173a38083ef19725ab409287da76da06563ee049179ecf995f85cbc262a9a47daaf2129baccf8c2a3c2d8a36a24e1cf50bc7beea10e0e9192857807674677885b3acc29d822da40920f7cb26d31124b03980b66871f5dd4f7b0e886d22d0743f6c0a957ae2096028e0376d24545728ae06e141d047836405ef4341798cf9fc137c10c18edcdc63b0c392225d4f619e713a582a1644b932960982c57711ec93a305302908e02514a8a239cda8e01613455e9dfbcf7ef98c25f067aa8dcdc20c6e0b4bfbd2a2c47ba9754a223ce1e0dcee3fe8c2e26c911f0e41ef46adefe5d1d0303592402bbbd8f0502e4ff95a49865ee3413cc9f911ba72141ac6a134b8ff3ae27086e98634d6906146758c9f8c044e6dc16d53c40851298e02a5e2bf2b9be35a75232887923003bf7e63a5b424b208c9d06260e06793e11656e5b3dcb82c852ad13331e88f4b499e0bea169435860fc64e2d72910ae4089db869d74c141ff9190d700ca02ee653972bd047f5c34e7115af3543cae9dd78fce1460968902687a62187a98f6cf91d0a418d3cbd441cb384a97c6c427fb9669a3fca13966cf6896b4f46517a8fc9e426c29a0e04bebb2767e274b7175c8f935ba05757e601f880405a4bfd27e57741ff770ebce24ef77f38466d1f089692432bc0cd58ede15e62feaadf9c70060e42f295eae6c7897930e791eb4f892087ecb28791b753d200760f286c6e3125690fc100e1d2adabe88e271c261fc733f1a66fdfe629c8382ba7c03c7ec54aa560e0a03defce019f0f4fa650c4acfe7e4a5d769c3f9ff60c234e3347b78a732397061ca62c18f3250e6bcd49e626e4439a9112263e84b52c83024f8bcf7adf932701f264c90fe4356f10a9f31098efc035ea4df333c5f17431d7e0180c2f65f543667c1c733e2933ba8e30cfd15020cc3030a26eb9d57309c15a5c5b7d5ed106530e131e6bccce2b6f273338ddfafee955966e3684c1176ce552b6ab54ec4f377129eabe0bcb7c7194352513419cdefa2d4981867a3dc2707cf1fb782432372e381ff6d3742082112b9b4b27b0754095909bf0a95930a68d6a8e8fa5301554015500554067b7a8aa23fdbfea35036ac80ea4f0584dd6bb51b15ec2936ee2b2cfb570d5dd8b3ba830566b5fa7aaca2b39a1b0fb96dfeea0ceec598621189b6b576f40aa8d5de5b7baf1622fe409bf8e8736f3c65da6a9f2994881967ffc5d3e95e8c492458eb4976987665c76e662f6b2f7b4df7ac642492141448ca90f1b2d75a6b2d0a756fafcd326b7ffe5dfc7d3f5e3b76e52a549bc07eb96f8a65f54773576bfafabdaf4dc88ebe27e53d2baf3fb366458ff4d473e529377f3f6e56444fd1dfa608cbf850c3a11d739ba637ed1a76a74092051e9af9dc6fa250f79ba89dfd6aee72770631213b4a4d50ae6355662f7b3f9998413e3ef5046d86664dfd9933f4f7620efb95690ebbaefeaef9b0034bf5a70ac9cec7c7c7c7c7c76706d15b9ba8424c5c33c8c787deeb3763114e7be9295406284356015654fdd96107992449fda93f523e99a87b312691fe899a286a42e1affe7c55f4429e6447a94976f4ab3f9b6eec9a706ef75ca5552d7976a00d570fb710b4e1aadc90f3f1913388091feedff499414cd4b89cbb3e51b2cbd7a1ec2efd71d7bf6914386e977f137551d38422bb298e6cb8a18d1c2d67c92f276596af64d261b45c25a7dc25af9ccb2c6fc94082a4bce52a27651c180fb2f296bf641cd283b0bc45e7a45ce5a40c61e4e8ad64e86132e332f45c72f46c8e5b25af3ce52a79e529b9042b3ae52aaf31a79623e59a8ae570d05dadc66ace9bd3341c110a29a048e18518a048b1643bd9f597895d7f29b1e3be6240b2e1be8edd8c42c15c0f73d7efaaf530b77c024b5af2c012fd858255fef2967332c80c78fe9b281fd3a63fbd1cc322cb61ee92554eca2d4fc9a4afe494c36420a4a71c46c6e11ea4e5300eb51b168df3f2202a877192061224e530744eca57bed2236e7bab49007a29e732e92d19c65fb2cb5532cb6b4c961c3d970c3d1b3d181248f98ad6617911951c2945547e6bf505a202514ffa39d1bf08f49180d07ce044d85972b705ceb48e9e94c39fbde9ec2a79080d2f458b6045eb4c731990ec826c7b692ebb21b7d51cca09ca679a64d0a6f7020a26a67082551b2b311cb13756f666328968d3b2d1636ad6c82458b469594ccd197aecbab59b35d510a66d22fc8a46a0941c4f7386aa5cfd91aaa1965bacbfaea53bcb492b24ac82339d92af785d4040a79305514e825079ca6bfe71a3728f69362c87d1c7d3f50b746938ae5f9ac37c907037a29cc088c1b9d9d7aab91bf5f63e546d75fc81257a217b0896e865928b6f4d520ddd5b0da5be6a285563cac6d4a6a75bc0f109b4997b0808080868d39edd039ad386883fd0063b7d3cc5533cc513167dbb02b0e6449b0e624625042cd10f01511a44f5f01997feeec5557f2492d5df5f0ded199b9eda29a0487b6fd645d3e91630ac66e4fc988076367d3ded6a68ced01ea480220c48ea0996e8691970fd570d6dfaa8dd43cd9ecace6a0eca8a09d964105a601db49118d2d9c93fce7c4aa5d53d56cf7d15239d5508c391289440e10fc3cad25a29ad6865754fcae3e855af9048f330c68a524aa925a9bcee2545c71b66619a156cf54a2557aad17b528e674d8a9e1a6bd2a5b37f9995f2d14d8af6d1d46cd8ef47865d9ab3af9abbac5bb6a230bd0296558cd51570fcac2a57c9aa3a46ab48a58c1db4a1bf17cfd813c66a46a53b5892ef6049089f3e0e07ddf295aef40765dfb021133038b9d59cb594528a0406253627a53f76bc502401299d5c885a477ddc2e66e5eb178b5af6ebde5bf697961dcb6ebd925b867286026db8a13c00ddb5aad66ffd77a69bb3b5d65a6bbdf76a4d77b5d5fc07e6e3c57507ab5a87e8d5b23276ab4149e3167f5dd3dbad8c719be6a216a1901751ec6c4dcbd7f5ed35eb10bd7e4276b438eb40c843d41f0e90203a10f2506474fc1a13e786e83564ccd57186de280fa1e1417980799b79cc2d12bd861469ee868d2d73f15acc3217ef31fdd1cc4519638c52bb616fe9b034673d9eea787d805b8707e8e3eba3fe003dad6e8637794d9690685dcbbaf75a362c21f1d6a53db86e6130fe52467581e1b421133098b6003664f20528f6154202062f3636b3177aa8d1bba746ab86e37abd6c6a7453042580b051a244e1625b1be30aec66560f52cadb5b59bb51d94c5fbd20f5bf7acc66eb424a2776fd62b7d9aab799c3ae6bce7bac667bcc4220ec2bb4b4cd9c8491833b6a372a10571731b70e79ae7e434b5227dcd73933843c62ac87b7740f56afcfaaaaae6a0bcee22c8d83de6336d743fa9b635481eda10dcbfa98fb46ccc989f534f75cbfb9073b9c3598eeae97185560b8e90fe40b363d13287430119491d69c37c6b905a157077fd861d6fa757b870edeee76d569aa2ac6aeb66db1fb98d8e3766b375d7dcc0fcbb11ddb32ce76abbfaa7dcc2d6d6896b5dbb669204a6e46171d47c94d1d6991c6d95e6bcea445b7fbeb77fe9b8fffacb58af731f7e4748f88ab3ddba5a6dd9ca94eaa2aaa6b5555d583e8341f228f08b30feb5c3d1870fc175fc12dfa36b51b913dfd66abd570c0d79038e8ad69511cda0f21dbced72c94b2028c524a29d57ee5efeeeb5acedf0f1df53ee6572fb58b8e651c21970e1f19629717691ced97fe300dedc51bbbbe652334bccd080d4fdbb40813691c0dfecaf237c37d33dc9ad5dc8d69c939051796c04435574a6bf7c3fc3aaebaf4c17e6aaed2300aac63daeb4e76520664b28527b6fc8dfce1b45a2b69855353ab93f2dda69eb4babb1ddc90b3ffba6d350efac30eb293b65a4bef63ee6ae3ae66cfd540ee0ff14a5c46e665fca951487634343443324a947422812450cf269dc80e68d66c5a02d1d0dc48a5c03cb3867a53c620a08d4c62cb3d4f336b24cf49140bf85e8cab80e1fe2ca03d63c86ec62ad6fb98f16a1ad9cd68750c2ee07af818b29be7a8eed1deb39d66d66cfa6292b55dbbd9b4bda65f59ebf5305737fb989bd21b567396aee7e0fcbd189348ffba38244fd0660650c6957247be2062216bf08c43524675644fa903a10c0c2291f2270ac9aea2b30bda899a0f735fee4621d9cd47142ccdefc86efaec2903c28901d8cd1c373208589aaf32cdac89e18434a702f6fcac1162cecca3ee109ef3940a1cf7471f77049a35347366fe624c7afcd9d3669a86d2c426a41cba648acf4f1676f61787648e94411f535930491dfa0c8b16fdadf5d7abae4054bb51ed0e7655657da40c025135a7f294575cbc32a7a271d09d825579478e1fc7df2eb31a927e0163213bfa1e969e96b7e81f73863e3b366bb4dfbb4377b326f2e0ee07a0888a3cb366455ffabb2afac3dba6e88fb4adae78e817b00edd48bbd7bdee6874698aa63c107fecb55d5be6c15537f7c08c3ef24276f5a94e0beca36eeddf7d722fc6b0d11d613c225701c9ae621845cd1a9b4a9166f5a92a95b5eb68958215959a4f48ccce1136e9a842919d95158a4976f57502c98aaa2aa96fcaa6bedb1d58aaffee93542a954ad1cc1834bb5ecaeddab6eb7afdfde898fd4dc269acb2ae532f64b75527d9d514ce150f2cdd2416e83eb9494649aeadf44db2dd78ab3bc2acc4ec29654f2999c9cfa62cca3ab140a99b64df24b3867af577497691a85e4fab4f129b52209b82f9cb0dcc8b9695957256d87d427648eccde669965cec7aab45223b49ed0f2c559fea537daacf2b9f5d6f29d02948ce2ae8ab28496765e5317cd26e543675929dca312a68c76b28a0d3bebebd0ca67d5d43a536f60d9564e7b02113540ecae7c915aabf41778a5da1d8f5e5658a6e065e0e23446ed6251ba1e1b91cc6080d0f888b86d1384094dc70877139104ebbe09798b96c364623cdddb8aef24be5f65a6b7d6457b50dc7b961b729ccbae82cffee93598f2f09e840f5f74917b0b6f2d108e31ba3510d89c1cb4a093f33766a4729fa13b247bf328f3c351ba3c33829a518768f240abc1d7a181d8db01136ca5f8523bec2b0975779ead0e163e294e39691cbb42e76e2cf9c7239f2420a8a21d99279e00c9f92b50eedf11a8e782d5a1f8b644e7b9a23eb6391c8aedad316587416fdade8afd2e72427b7d3bcdd9ea48c89c4fa4819394615b83ab4412b6bb3487a5e3e730fcced69d6c0e8fb045770d3a11dbbe886a68b881bc370166448f45e0e7353f45e8ad0f05e6e8a1e4c8db9637f221e731e1b652fa2d3acb240a389adedba4155923baa3e179330adaffd0164c67c8c2c5ef40f73a6c6400386def45e0ea3e19ca9d302592716283567eaefc5d6962f16f8ab92dc27a97a31e9b69a767d35592774565535a7ee799174565900a5eeacae8a92fabb17e3a93f12a9a282b834506f59236c34c2b0db5f417784d98b9e6e8645244c4f348b21ae85286a054eb995795e08cdc6ac1f14b231af666392e6615c6a52e6e6bffba4cadcbc7d45d2dc3cdd302e61dc27445098efc2cc976c03e986bfdc44c3b3e19c0bc65172c3fde538d033d1f05c7e832e123d1b34cecb395d247a2e1ac264e8510993a1f7422f690f0c8cb6402dfabb2cda5a15fd7d03018db00b3567eaef7731c9daaa208a84fac8ee243bfa0945a2e80f2cd11d0b64514fee9015f8b3a9af4a629d5894ec2c90eceaef134f64b7316c0896eacb6b487bbad6daa92d904c722d9e95cfb5f046ba7e7d681af0674fbbfe3ea9bf92ea6edbd4ac99d7d2dfc5bf36354d5fb73f9bdaf53425a1902919e4844e1d5140553673761c82252b70f5429e52afee81194db21b42767594e51e8d606450f361fb1de52feed1310cc2689c97db5b5a0fd531d1a196e3e51897a1f7925d8ec3b9681ca8bf0ad25b9755fef04bc65172f3a2e406e62f9f33f52f1a0746e328b981b90dc7c15172f3729843cf068d03a3715e5eb94cafb2b80c3d320ced984d33dc2f197a51f321eeeb3a46cfe1a26bc8aae1881fbdc6b4197e94e1c69a28e72db7c848e5dc240f2cd55de9b8034b32890f3d5d81bf789a26940cdab5d6d3215c3f736450268364900cba32c8fa259fc42d936417c3eee8f7d23efa75c9934a5923edd72d0d88ebd9e3101010101086ddf8134ff75691e8c6a6bfedf8d8e30eb4e1b8fa2166cd7d7271ad8f995239d2f789ec6a7587f47d4276f537b4ebd88e8936cdddd08e65fa03b7fe0e55796357c5d91b95b454643ce20bd8bd1893483ffcec9833f2f752716467d766961dcbf28eec437652a39a0d4dd3ae69dad47c70da3f3884658ed34e37fe8677e450b94a36b17c45537991966b2a197a2d59c97696ac84078dfc69e7f077e8d0b4286722e8fee0907643bb8e3e6c6c1adb214fa7d3b6690ebffe07d949edd0db8e65b76d7a45086fdf32cde12dfa6c190258cc76dc3b147fa871af99e90fa2b6ca658a95fd98fe4818c37852c970ce3c66526a9ba6e10d6b4ebb48f7ac603a2239cd9a155d434aa987b6dcf1e36724b7175ceb5a5146a9a3badcd2decab2aaca56f656d60cec6abd1159af341bf5566b69bdf66af49895458d56dfcc969b12ae8023ddb40cdb327d5994ab959cf33aaa6301cb8ee65b2b3f65ede69c73ce39ab7b3becd7ed0d76557a6bb5b6b2d2b24194f69bb66971661db4d171289a35233d03d348ef2591b07f336650ed66cbae5999b5aaec63e2b899b3acd78a6a5575c9ac0913de0afcb84376f337dfc86e524b297c62e9e9f6ab45fac79c992791b6ae4b492a638c514a29a515f8ebf68f27f007534feec538ea1c73ce099f88ac6fd7b296b59fd984d10afc759dd4328c5e017ff049eac725f56ce76467e9ef5e4ce9b108699c5ba5238fa686317821062fac106da22dc62a4a2be8135846d16605d60515ced0b93819c3129d087b8c31c618a3fc84104248c980e92b2ca59452caecca7e6597bcae4bce39e79c7366bfb22bcbe6e5a7756ea329a3143d92d6a594f6dc684be1467a9b96d394524a29a534464ab36b5a1633ddc15285dd7d3776e70cf60ac3b6675bb63d3bb755d831ad8bbb833658cb5dbd833622cd5d97bbe69edb24a594721b166d58d35dd56f9aca0e0a898a20b4ad6318bc2085198410c24bd34c57fae8132316af48638cb15e19fcbd97e6aee883699abb4658b4dd4aef28eba0971b422cdaae8e3e97cc22d528a5f4906a2669920253cf925492e46396496467bde6ec57765d5aa669eeba9626d959bfb6577d4476d67b56dec372699a352c7a8445f85ff461f9cad46e58b6af5c36b69b2f91e8dca5dcbdae28046d745c972bdaa7d64aa310b4f1b9a64cb48934b7fdd210962ea86bedae2f602c73d885fdbab00ed3164e6b0fadad21a5e9624c6bd9b1532eab34173f2f7b989df68c84e10b5eddaee085e1f8e8336b562eca22bc54748a1ee98f84f5a6e1ac28b5feedb0e967acd37778ce58a7940e3167acdfef624d7f38d3d6b1eb169cd1753f8984311d72ff18df2b97c09205846d7d8859234d73c6fabd185b264bfa5014ee6009fe93a66d5dfacc9a28147de68c752be729d21046499f7b312691be5ba76ac0f1d0929894a99d152b382308d951934c3265904c9992c8a8ae801dad864cb0e1859835f4a2f01009a6363ced68eaba9f44c23875ef0cfc43023ac17812921dad86a40c3a24bb2ba00c7a05ec68dda9864eb386a6e815f5f4743ae9a8a8fd934818df8b8225fa9abf5a864d4f53a9542ab5e90e10cf2e5540b3a69e2a1e9f2f2125c13c154fc553f15457d0612ff7477f9ec05f3c65d590dc8915aa72520155403d2a980e461c91441cc3175a7c51450f3028236945d305923dda9009174b6ca851013be0874340ca985aa693dd6b38e0872f82be7862fb40617f344ac0d68f10be38c21230b621932f7e80ab26f0002f910320f028518321c4e0072c38c2111e7c6164075f9420076b60426ac9154ea842076578c2143d000312b8d0040b3e7882832818c10944c015932470c544133e415822c99222289184244c24a1848709929ed3ae7ed6f082fd7d3470ceb9869d3de79c0e80f089858435e4cc3fc14e4420e90423f697f78d09804d18314fafe198afaa4f1d1fe3c660dd202cc5cbd4bdf7de7ba961092f76ba78a20b2773ca39b718751505ed06bd0d0b966a7583d2dbfb6a891468689cd000c90055404040342a48c001155f3481841d308881658a7c55810b23e0200c4260f8c213522001230726bc30221405118c208430e01baa607204164888c1132aa2980f6802062a6431841b6cc1074271093338f92491451315f08041cb60a17e200c32e04292296e40862f7c81a782c111575081123c39e0818f179018dd3861e40c4610c30e7e10032878381de480480c524a2083145ae882c6851cb0c063e1138828d1f3852730a18228b690054106378822083a3c98422a08091b8e78826405413b489e98420b487c0728bcd00523b6f8c1132fc8420c16ac2770e840144cc4c008330445b9c1155a60b68084284e40848b256ab0020f4c0d967082d38e125cc8c112aa8084a80535d002111748d104912c3c41826e4c8c50049e9e2a6cc1870a37e0d04511d0a08525967003294c2105fefc20b18209162831540429bc2ce00a63f0b1424808573471e272052bac4085263840411986100524ee01b830d540075218b1c1129c90354988e0831f90210a1f04416185460ba84051f18411ca8003201e9290223f47fc4028e7082ba878021258b58012281081c7065c28018913a0c053abad55adb5d6ea04ae15a276bc7802055468f1059326400109242a1b543690490da54c37e022874a1e2e7468e4e1c2542b1e2e8ee04205f5d2005f1b32d9e28b196ca1c516555c99ff32dd165ad8c209244e37a834a8b668c1dde204778b125c2dbab85a6841613664a20517b478f2846422d2c2c7aa56c00212c905a4aa05352a19e00fef386b62ac6250d9aaaa5690050fb2d001165a24c9e2e794c569dbc9426765676865078b275b6302290058e0411648342a50810a68b040820e1642b83a58f0c0d2c12b242c90c42b8ea421890a05151629a84c5865432657745119b9820a960d995c81852b9c604224328109d6e600e2152630c10281c510aa60841954c0459326964077606da583ad8d4c60828d4d8670656107d914ae40b2adb5b61a52f5542590a94a4013854691b1020b2b8eac210d48cc341c4173d2408359e58836649206146cbb219334e854465ca8d9a821a95529ad5476908487bcd8d5e9c528a593524a6f5ff5ca29476ffdd2d36d5f6d8eeda6eca2bbbd8876d1a6a43ecbf2f49c3dd64135ee81de62d7be5ecdd91a05a687de3763cf5aa58caa8a247cdce159732fc6959db2883a2f233028f3cd9f3d9fe3743a9de4cfa9b2eabdb556b5b2eabd17eb32cddf0f1ddee52231ef84e8741862d398eb7093cc3bdddd24731d74bd325949fdede663f2101a1e901c0ebd4e4e1f24b29b3c684c93ece634cd2372684e1f12dd4176d8d5c4cf4f133f5597e922eac658beb2ab2779a2a77a4d124aada8aa56a87ab584829a35323a888bbad08042c3112ff6f50bc596a740680842039221d3de3664828614bcf52cd35fb7a1ec89f9cd367f3bc43c26cf9d6b21ed02c339334f9666e3da4a33cc341bd7a222949cd9b242ba5d762d2b5372c80b89454c4c8673467b968198cbc8681c2192bb216f5d6ad98b4b978dd0f0bacb18a1e101e9b44c8c06a2e44687cb7407a283eeb2c764e8b99cbba13fecd73be892b9c8498dded257c4b018296334aca49523e6584cd641bb8cc6d15bb631b9bb921b99c7c4681c199977319739f46aa77164344e4c8c761d74f008b2adef4c8718eb2e9947e4e8bf08241f84f52dd38892ddbc8efbebda8dfb4bcf6b4076b30a285bfe5efb2f0ec99e18193d4f325697a3362d02cd733036dc80ba246ad6c893fe968fc3afcf1b6c70913e525a526afdddac3f7c793a0efab4ddc8e8188e47dc56661d51fba08f5ac7bd3c17bb799ab9287764372f654fcc7b6422d0bd417fd706fde1ece274ec0203e091e78af088f4e2f271f56a37e8e5f78f94d144246916189aa545b3e4c89979162de4e32e4b2682ee954c049dc7b20e9a65f1be86fc8123c4d480ca4cd1a7592387e6cc9c3c3367cfa3a0cc23b29b7f89510596b7b7caf75093f7f76a3820862dec5e6b22b97494414d04694656d59c8cd5add6d65ad5ea563bdab4ebe7475a53bb5b077dd41c00f2254f2363c88e46522f30d63d396811c44091325031d9d26c58328fb9918999d66b45abdbdb6cc68650a43f12d49a9652fecc9a1a254aa3e804a2571d88047ff08c9f79fa993e13c93ccdd344324ff3344f529e24cf9542b28918e54f8d55fec89cc6bcd2b209f9336b64b44491244afec4e89f3de769cfcfd3aca19edc53a22c9c3f970da002833219247d9fa771875a3b5b6dd7a351f9a87790ddd43496ba8a24b6cb864caaf8d93f8068d56364a1497346d2d71a33ab34877c0d595992a2a0cad93b6738c3926d5f67cea6bf1d4d8e207ee4c88ee60a76bbfa84cf5f574d1d75a2508eece8ac73d699ab7b49742477e449f22481e7ae945bf5a6fca668eeba9ab3b880b16bbf9eb1a47ce531257f3fb666e57a5d5ccd32770f6f6b54b9d77a8d592bc4c7a266c945a8c702b5ecb2a65c62ad2b45df1a81aa7b4c0af0586e75341d678bbebd86c4d92c587f42f6a6f1a5e8524a11e47050953a5251812a106a186b14e2a28e532c59b26489f594c7a768bbc4ca3763514769127d1ee8b01c3520a2ca8d425128a2b2dc9b96f988b4cdc72788091f1f26644747d867f38931eacf03ddae8f3ab2a3a62a70a539d1b464d6c49d14aebef2f98f66c725f1057127eec417ec9076e20e95578e9481377dd491324c2b39084ef456bef22038d15b79109c20deca71a2c7a283b09c45e308f156aa9c0d83368de77e680006c1200d04b104062d81414b826050c511758cd3cc1a1a1a5392282484420dc5548e3461d2477654066db944765426a1d6d26baf491e119a33f4f70a0909090951fa6bfffd1eca4e2e914bc88e7e1405ae879eb59a0a617baa3f22e2aeba88baaf279132201342b3e65e8c492421edc3ee6a098de88afa93419b3ee6a0d6d2144bc7a099352d5a2e21d14bd3912bc65787de77f5ebab33e44081028a930d37dc59ee6131994c264a973c911d954173865ee8a2f0d0a634b5e9e5920854e77a58e89239437faf5c72a9a5e5921c43a2c7cd2904cb032051ab431c74437b688653b78310317eb8a99fc1848ad4aeb4cec898ec6fa5ea00b56d0e82367611d0c6ae99c167636648b2b18ba030512b144bec0a056ad75a4fb7f6df1f3f443bb6fd356f6b4c8d07cec6da8da9cdcb860f249a2684251ba1e1e90c69b9ca87e8b4682242bc96ab9c0587e540545af4eded2fcdc6559d85c3aeebfaa0f631b7d59c3dfc2fcd59284a9821b5a3064475abb92b6a36a76425561371c37218bf51794bca55cec261578b80e85673184bcb615c96afe0c06861b9251d7a157aa41cc4e62f3b84f873b254a263af5a047256c938384a6e58de7292ca611cce1a181aa745e3b0a8dcae5c765be1f095b9d1a30aa6b91bd8ab9116017c43a4bfeada31cd6d974e813b0aacc34229e38ac065690ebbb48f28bb7b592bcf1983a6db010e6552e30283329f95b3eb291045c9510669c15aa19a02fd698204d504494e2d528d60bb6193238cb0f11068c46f72c40fea2fd3e1b061932376f6b66193234ab0bfd31ca925688224755523ea10970d9bd06068d74068e30d9bd4606857c7d0467e9e88d4573d11219ecc337355e7d0a980108f089d5947bbe832eb5819478817354ebcd41c119c04f0e53390f2794e02dbe56fb6cbed55df609f1a671e3bd43809e06fcf00d69b06825334c4e23fa395ddcad18a315a8fbfb11ead1835901a34f11f8da573fc5807b2e15b17651c211e8e929bd1487355f491b5dd7a06f04796657da471e62da87112d89e3d03dbe819c05a883953892ed2393167ce548f8186eb4044cf3ed240b65f59c651829f69aee25ce73c2de368e7aa26829380e8d733b01d9f9340f6eb37d92f8da3a41e473e7bd537d7b1c699bf1ec4132201d1b3df8874a6810491d79efd66d37167ce549ace91cf0ebdf92feee490c7b21c9fe42894238f50d6893f57d6f9e1c1fec52556f5185b60ab79c0285b473dfce2935d3d461a6625a7e6eae781cc434f041480b386cc80442242bc7b2b47cfca40e42376a17601219e111a9e9cf202aaaea4bee62270d89f90ddc34d007af138f0c713011121de7611444d448897b7478d02d093d89661dea896430703d09bdecfa61a05a0378408fda6712e4dc289b76e455df1a85e896025554463bce2f6789a1a5b8c3922147a22b5633f521ba1e1c5c77ff04976e85d15f62b67a7f93a90ebd0ab596e2be3440fbb968dd0f02800bdf9f9ebf3d0135284a1277272b2f4e6aff94b87887523343c7922963642c39b971a6708173d219e111ade1022f2d68908f188d05b9f1a27ee54374243fed238910787ea5bddd2384a6eac4b8db363ce54b7f43cfdb533b5111a9e67fd8b3c70681e7a968e4b620ef42a111c3d68050f8ef85912af4b2e913b9247eec81db944f200c151621d7a5706821d7a58c4b48e92fa2251c744c3bb2f123deb32673745ef7acc5cd51588de75f9ecd238113567aacbf822d1ab303d2416895ed41168ce005df1d08bff62d0ae6a6ca8e5d021123dd98406506c016c0c484fea2a3567a40996aa4a247ad0fb626a5716889ed4384a6eb0478da3538486276f8a5e3ca687442fde143df92bdf5b1947c9cdf5ab71a277dd82de6565407af55cd539e473c4d79044a207bd18e9e7af1775e4e3e51532e576a4e6c8d49c5b23e00f6fd9e398d65aeb57aeb5f63e48db9e243b79efbd0fd2be1ac20e1e064a29040cca7c7767c393640d6e328326366c328325f6774d4d74b8d850a34864a705fea869d3d324b3461ae151934e09f6773735491947a48c797aba2365c026337882be60d3575be08f26d9940049ee0e11a13d3f0425766943264b28b131296395c558a3b5b5a2536ea83f2979fcd8f635240f6bc37e1e6eb821dcd006c21fd0865e7c6bacebe6cc9979edde0c638c44ba7fcefd62ce0f68236f83fd412e20171bc2d48c29580a0016669259b3a33c913370d70791848eea8668f6374f3b4aea8997932367e0fe66d04c624b1974c3ff788d960116032e0698ee5d98e6d7b639ead44f4d6a8abf152843b43f12fc0f6843a768d34326517e36d47c10edaa66bbe7bee6a8638a2f9033f35636ddbb3a1e913313899c995762cf272175cc893ab233cd99f9b8137364373f852aa9f960a2672b30327b0751f6a04e66c6078302a005fc20660dfe0cd1f6ee8241586b605ece64a4231f69cf8f4493c2f415a60962ce4cb942a2f4da510353cc9822ee96455c1b9e8350c6558130a00c1feae611a3649ff7320ba1010e0ce1811db2f381451d3c6dc40caf10e1daf2904914226c9aaf59054c33698820a060791e2b2d25363d60dc1e3e429b1ea46f8797d0a687cbaf1e2fb70eb9633d609e1dbe429b1e365c3bbc85363d6eb8e81087639b1effe8f017b4e9919f62d3435fe530e62b87d7a04d0f99b31ce6f09643112cc513407ff0d573c81b2cc5cb640d96e26372064bf13a63b0149ff3054bf1c7215f588abf215b588ab72157588a87c9152cc5732f79c252bc4b26651859fba0fb8b169615959411166919665d9b8dfa87cb5fcfc29c45187df8f6995fff62008efd930278f66fee70ed1f2d5df4af1ac0f1bf4a808ffe599aa7fcbb3c5ce59f5580affcbb0c70967f588cb7fccb0e7018ff341927fddb6aeef24f34e32fff3002cefd1bd91ce65f4a026ec33f1505fc867f2b0b380eff5818f0ff6ba1f1fc0f468deb7fa4fd987f2ede65febd34e039fce31c7000fc83b1711d7af4f0eedf0d1bd2c061c3fb907bb861c7dbb061c73b20bf01dc8ef75e76fcae4183012d3b7e012c3b5e010950d9f136293b1e01336a443b5ec6b6e30fa0edf81806c0767c01ae1dcf83b5e36932842502e41d3f80bce34b19c2d20e19c292007200663284a52e330096e475c80b802579006405c0927c0e3901b0242f936d60493e46e719b0249f730d2cc93fcb8025791cf2016049fe861c0396e46dc806c8058025792ef3004bf22f9926130096e4497900b0240f2397f20eb024cf9205004bf22b3900790696e453f228eb9001004bf2a29c032cc96b592626eb9c0f4bf20680d9f0acf9e1fe90b79cd12b6568dbb6dd07696ffabb2eafe54b6527657c725f1a578fb9deca45643c620f52d322058564cde78cbc8c33b5a38e71059e42fbf60898884e110478d9758a30c0cb3e44484e8e8e8986a7bd48f474748a5caf5ea708f6ec758a90bc7b9d22f7aceb14e9bceb3a982e32c3db5e84c6c35e5d66da64bd4d1ff2205f247a9ad6d1d131cdf0b20f995fe478a6cecbae33c47a9193e399485ef621a2d4f5b25f2f237959e7652f32c3cb743767e4e5b19c210ff257d69007792bc7401ee46f96813cc8db9c03e441be6600401ee4abac03e441de00125f42a69c44c0228ccfcf2aa57ccbe7abaaf2790babaa7acae7adf9eb98a5419b1e45dc7d6dd0a64711788ba04d8f2248fbd2441071afeb3e48f310daf4a8ba08d29677e9017511a45d9de5f317daf4b07411a4f90cdaf4b8ba0852862f2d61bce7754c8d8f4453d4a94e1fc4acd1d1d11982c310e6bd7c080d21ce7bb9ce1018a58800bc97174980f7f221337272723c53e5bd6825f37446c11f1ce2b16357af978768472982ee98355348cec4a74c433b4ed4d015f8eef0f1fb1cf2e3b143e6aa0bfcc1211c29e323fd90328aa03b7c5cbc7fbf1d76641eb0440f2313014bf42db9072cd1b3641fb044bf9241004bf42ab90858a24fc9218025fa51fe014bf4388b0096e8457904b044bf6512c012bd9671600996e8b11c0496e86d16024bf42498cbc81abc8301f0079fe4b809420352c6bd1014a22ea4b093bf19c2ce3ac539e302cfc31d7b1e5f7c5b240684c3666117f84ac4025323e9b6481b545628a7a5d81baef9328231e506324805fb831c1efc20d91e45061576228a0be87522cacea44e444141259d88a263e30afe620b2b0ba418ab29d4da85125a85428e0e9a40a16428a2eca8140dd655414b99522300000000000315000030140e07c6c3e1709ea7a2f60114800b80a650745c9708c32089511432c610638801000000c010100021aaaa00001fd0e53dba07f6d3f22eb2502636eefd13fd6939ba98f8def398e8a77d4549a2088fc86281c639610bf21630642883034ccc1cba1622daebb741766f1a6e253feadafd0c0ea4ac8292fff36bc232071840b4148d2d0e3870012d8d0b33ef549142311c28e95cb89df50d922531164f72734dbfb70a7d1dc29b483f63836698da9f172e4ca96122ad9cb830fdc2fd1cc34f4d8e23525180c632c7ce7a0763e78e8a9ed08f2a32503888bf092f47761d893fdefd34b4a0e166b05778e9f724e4ffd0f9b9ba67af4843b149da9a4629cb36abaeac27b961b86b2a9aa59e5196616af0645b85af598fe476c9a7ec0436d3da3c30a69cbf567b04d6f60a4377fe3acb48dc6b9a9edde6e80d3d25773d116be8d2ff0ce4ae282055993411d8a8caf0c2fd0f92ae308c16f74cc08c598275b3b6be30a62656ed2b8e70736235fba9b66324c3537e41d842d7eb80c4cbe972b9e8f84f78e86060003d3b209bb3309cb57f3f9e7f46f8da7c10690bf7fa7f071766aab433e8a7a1a5c42b4b8f0cdc4bcb84c0793bef88a86a2fbcd0f238863afed021a351b8933c7b91bc8281d572cb9d88518b137400872647dcf3edd6ac94c59e0b4443c9fac1aa486d1dd6439404e0439abed91f53793ea81a0c6f4c5a3a338ba224a4186be5a2b98ff6c164a8d2e7d6098b9d5e3df6890974c8eb01d0dbe7822e1bf6c244d9d6d2d64e8efe443fde1f245c4d0e92f142875336d693c487763595367b3ac7458c0821c8c878e299897aeec9f4b08810e4cd5509fd385920579c0b9ecbc73360484d3382883fce768b90ff022dcada0dc5ebf782cad4bca7d017d270d3093393bdebe9baaf7eab9419ffd5efb0cb8a76fca60fcd2d213cb8a564fae2340a41e215c9c4569800b302036bbce61e1c0003378ff86f7aa13958a5b45300117092e2366cdb728a98aac53f38785ff10d847c62d58d5c3a5283101b64c198ccf5af280c16dcc4b241454a730b2b803e429bf8cc1d41f2ba28baf9e666a9a8a9254ba9919900bb09b2ca11554220761893e88f69974cd195a744dc7010ff8de4fe00bdbf4a0259136ae22893cc4b9d1353da41eed5e142fb3bb5157d9984fd7521d474557ada2726544820a18f326cab86d94c7b29d2e3f646b14633db0cee8aff8fc08e04b95f0195d85a8ec87f5f20c12976a8d862be3c4f61f269ad363d7b12a6c1d7ed1e6e75cc20a7db92bde3a0ae3d2249dff951366d5035dac1d8ddb04f33a66c73b0ac48f41a6651bdc1f06c9aa8eefebe4d780514871f3e51d6f412a812d421ec9f465a64b26470c913a118ede82584711d1dbeac2aa1e8b0e8681a4581dff25f56227105db0c52037abe36cd41a57338a53a95037845aed01dccbdfc611c77e9604c1e978f3ee16894b13e0f7b68c43e4fd51169a250b67040dca9503563fd56c7a9c028fffff5d2f4950648d38354d5ef25f02d2af9d99b22902c1cc0f142fef3e17dfe9de70ad341551143196383b680ec129c641a834d31fa36e531ca40ec14472a39b0b87fe8977462f46a242d7b2f23edb810975ca06c04d54bdb5511c14746d996e7ef9f00971f5cd28b859de33b65a90cc49631ea1735dbc193fca2755b4eb94286d1792eea443725474ab25018637c57a9651fec893308114bf543b11d1925f729990a8560aee469cacaca5b3703ddd4b0488c0dbea09aec8b5a310419c89795323bcc174160312706128bab60e4c6649a5e66a3ac8674aec7d49187471ddba2face0595f58a22501a07f5b6ca6c9f11143465f62caab4566e2e417cc25d2b8dcde56ec8076d9985b143ac31eb5e493362bf6b4ebe778c40554b04e2fab08ef46684823fd60dae036970e00d980807adebf25b8adde46c6ee9b28060a95a79f6d92ed526add08f4a21e2a5ed8c5f3ad9fb6613b00718b460a767055de0a28f5e50891a1a56980e67df6af38f28e1525bd097c4b6b24b81932eefb8be799642098aa21b303dc38cd1fc9f1d8c4adddb9d4d1528cb61d8e87518e41e1840237ff185b2bc383e9f89d25a9465e5e40d8342f92e5b13977fe4977e96997973f4a74b3d7f3a7a337fba90f2a73984e14cada4fb030da5bf024ad49f50456187fcc8932d59eb59b7795c40a14b3e862d5967bfc680088697a287323ef35b1bddefb088651e687e942f205ade8d1c8f0f37c197d58d2e3e3628faff7194618aba2f650a824fcb85614f552cbc9a771695e9ee8faacd88ff2c1a133be5d20fcfd9bbbecc36f368d19f2a8b8bce2c5fcb4d0b327122d9cf359c86767e00d7adb1d5e09276802323850b76e94e7b76d39ee08cc15ac35605376dd934077701e099e46f8e41f58af2a65545e23b488c0ce3d85e43c2924896b69a9ca22e384c307c4a389764dc394a5f71af4c4321ed90e1a592b670d2737ffcc4f48877a4595011ec1d1c4a969ab0dc766816301f7fc66b51a486ac9566008b21b1fb8a7544a9524e78e8c7ea5831807e595c3df7388f7f1f55dfb6017dcf50081c4d98abb0f2a7d9d84f0011a8a825e366b7e76f872b76d735df5aa2b1f80d870598d5e599226793ea94186e33113239d1465d36b16068f7597e27e82d4d1a548345632e42385a93488dfabfb1d0fbe8743ce68463f45cb29d6b2fdca4c50c372b4c5aa52dc326fd1c212ed49c906ca216bee3994fbc59cff76a968105371289a6997e5c4a96fdb922da08b0a85b854cf4d51123ed3b8d71bafc46cb96930c4869328370848e4f002f4bafaa17d235ceb866d012ebbe1a0061288e0d1cfa7b9857b0a3154b7a3a21e00e9fbc7fbea9a4bd2927a614794b417ee2cd0e6b76c820edbae64e1ae08ed5e5a180debb9a1e1864bbacd1a903b7a3753c2c20f74605dd5e7d9e76ca4b3022ed88c827144e45452d5d7cd239932c2d3b6267d47af2946c0a710dd2e6acf54555f096970b089b36ab37a29507c408c8a20a2e931d4c18a07a62fc8c88b1fdc4a42297ce778b88488423b843c834be3b4a8da3db685fdf8ff2b4f5ad78acfb7575c4f67be418ed833732e88b868434af11bf866510eba4d27e2d51c15297f60d289a6b1b7ef743ba990a632a2d0863329ce0154475a2c54698f001c046d6c61975e456235ad1605acafcd30287987ce6555a962bb004870a04193d26244c8a08782c8220a3c4996846e70288261ef1d447dd44319c7949090e937e206d2be242bbd0f858159530c4952d3b19fa480d3acb429176516494cfa634ad2903a55e6bd99c7333ad8e49e5d32e777287188e657efbd191907ebebc41c69921ce2344c820c1d960ef5a91fb1de0a82ac22dc66cbdbc8c296e47e5aaa69659c2ea68c12a864646cc0f922e1b9f065b4492689db95c29cff39b7db05d4c2009893710895d80f722be205bc499cdf34a4623d58722815673bffe1e51aef9a5b7a9ecdc549b8aa0ddf6a7b2b585db3224151a1c953de7abccd1cb08527463b529aff0b1ca106633977efd3a12f7fcdffb3390eecadd1ff04c688ad8d436a1e45f91179d151bfaa7404370474b79f2d54abd69a08c2e6a1db5a360fb47797f5491b7f868eadae870711568de6bad35cfc40bf7ba440b80155a4755a29fef549490db1d65fb6591876138a4a630a949ccfbd06ce422f0a9733de6d8ad0703903e8fd3f8ca0902ce0b07791986287f5fa73e5e091bf79b8a4239cf7d4c2bb81403c6110be46f5eb52bec593f2ba3cd66603ce0cb1047e394eac90d14dc181d30939e86ac0a974a712cf112a324c151dc643e14f4eab68d0e5ee333a1a3a01bbf6e3660ebce88c529be0b41720565a38ca6aa942d98603a64bad36e46b8635adca738f402d71656ee38be89d7d22d0f9dfddbb111c5632533fcabd5856e1c3db01341bc8d8c2bcbc571e5dc2c178e8b7361b938ee9c8be5c671e75c2c778e9b7361b9386e9c9be5ca7171ae2c37c7857367b9386e9c9be5c6819b31ff889167907ac29a162ef5dffb8186a279f8896f8c9fbed00785d70e7611c79f90de46798107103bb97d8cf0ffbb6bdff367dcce67e70dd6439a25a26205bc86ab037cd82f923935602ba297f53ba037cca67e27d0eae6903892257f1fb4a3b7f9370e7a3c82f7895f89e5c307dc97d69d76f923552a618bba7564b11a3ef8806a9076ccc00d403ca06eb986a4eb6b4af455fedb905ca560561051e94de4b151e33e4335f0dddee3e94435e31a017afaa7aa0a7f72f2009edd9f5288a628877c50565ec74550cd18e05e8ff9a404865f4c228738a023fd1cf48ac8c6f55ba506e0eef40421ab5992e69637d7002470bf96b4347f1f067d51fa7b54146690964d03384660824b3123ebf0b061cb285d48ab6edba41643ef7d867031af3a950fdff306a3a25eb5981dbbf41b1c93e9e7b66d756976e8de37088b76aae36c389c760f769cea8d6dcc45cdcd9b55501e029807c7e822289d3b93d9df65059e1c700b4d93d5c2591c75eb3436cfc2f1a2d239c518fd7b0956209bf5dcf661f965765e09e02a6764b98130d5117d4160341779b5894931d257398491598f8a0b710d9b31daa93224a8a8182d79e848d1284e2262544e7a252dbfc120125ed6753daf2081e43a4b5daf47f53d108819716f47fa5623bfed1030ddd78b24d4a46a9c2f8885a727e38a1c9e305145e4e05b89f0d5a7e772e24ab2b0834ebb8513b434efb2b0c3b7c3984330a9c3fae68f5a2307d4bd850ad055bad484db691b500ef8c2213c08e158c939a05dc1b58f9aa3e1a660b17cc6609d03542b48549da3a219fff42644e1d410730ede30be92c958d05d5a160e2ed55721fb88022d3e0972bed3812a38ddc1d511dc99c48b90d3610f50f97deee04d34dd14ba05b7284d22ee12b803bde081fb59812d2d16149f48ec6c00fd8586514fadd6bcf109dcdd24adeb2d2ae663eb9338488e9c4c73b3572a45322112d200113a6774104531b6ca09a737f4a8dea2c156198b7297948ca488e98cee2085d88c5b2a2d8956ac139d5bb4621357494907cd49b12a5a7c35a78aa5b1e4e319172f63c558693f9e22314956642cf17cc6c4482bcf727a76d20b3e8d870f24c139f4055be80f4c9cb4d244bee74ed2a3d684fb2916937e4556683d9e7131f2ca939f9e9df5fe10ddf080319ce991ca327bd4269c6f4bde35e99c1b97257626d10f92b99f35d938897e96ee361647b613f10f995bc69d93ce6e5cee9c7476e3e6d649673714774e3ae3c66db4774ca20f12f79336279ddf3eac3fe91cb72a4bf44e629f24b9d968427f32fe90de4d255ea70634ed92277493eb88ef99bdfb049afe5597b45d1ab650b0a8170c83415f327ffcef7b1b1c154eb4657274579078c2433f968e73c059f0efb18f286ee5edcfc4df63201b2b6def065036a9a34112959dc8782b7a483a40e407c04a82f04bf8e00f414f4bf9fbed590839f567a0ab31f3087fb31f3440df1524ce8acfc5e346452008a8a67b0534b65941aadf6b4212a8acfff282a11e2c6e360e95aee33f8f8ab32998e304402a6093f9b8ebae70f0ff8f3482d0e85713d699811107f8a734568c49a3015a89b89c8ba4dd264cb3595ac68c9a5060a28841b7bc0b5d18b6f38eb6d2476115e1d3204bd41394f86c5fa58754d2d2906b2a26c359d975058af0377bfa4577d6a7a86e12039ad08815b1bf9e81980f0e2cef36e7406562a983445cda838ea74d408882b12bccca156efbc3e819f3521ded08def13c63d1e46e8e10a4e335bcc28188761faf4f66bbf6abc86704d7b66ce614d108f33c0cdf670adb4eef0ab630c7e532d06cf325d24c286783cb618119accd16c8f036c707de77af38f7cfeab1dfedea86645ce618277685c8ff8c7f42818a9464d3a19bcc555f5b7a15a1ec9b15aa5ed2c5fd7d500b0c2e1047dd4c035b596e4ea7c887ff8f86813f81c45e51844a3a65c6f57f0ef5111d9c987fb743d79215c1cf2c8720089732cfc83c2d02e3f0254c9c1a2c878b8aee4dde4f27c09692e893b132ab36bdffabac3a870967a7713d72a9d3c281cb36249ea8adea8125cf1a1ccff1d44f252bec5579a5442f356c57d7676346b068cd6ee6150252447c96f46be39e0165f2c1e37d4f4a0b9f81d26f8023b93f2a02373b8368f32efb2ac043edbf7a15b340513d495ddcec66b60abdc06091136e3bfbd83e7d56063e9c7950775077523dfcb0c965452fc3a17fdcbe9d88a2222b93cb1e67288bf3c2b1e9b312426ee6833e2814de994cfeb11ed23c54ce96ceb1e4febacf7af34907e7acb54eccd8fd514449c93a3509ad5e8982395616f55ba43e6d57dd089ba9eff105d989dee49f83fc481405bb1e55403888a2b83346831a358f446dbbc15f3fa646d403480919da511f4035a32733f07f546a9eb2fb60eb7ed92eaf2076bfc218d281a8bed008d89f1685c64e1d010ae6ab772dd0bb569c7bc549143640c55f1d2308f6e8860286c628c61c4ba1e4b160cc80a48892013568ab618e7586b4c1f0e339320481b8fed1cc8632e8fd32fab71d150ea4909edf41ae79835e2bb941d4a05b151017e2b6c210b79d05e1ba0554c69d015ed35c24a12d77ab46efa8f78d020d25da3503d1ad1d42b1091032316cb59d868accd021ae3fdc1a1e25bc9e438efb4d24cc6acb62381e52ef8bb1b4a19e9b24b1bdd2adfd73de5ef140bd6ec59e185558acf62ec679b051416934c2ad87eeb4d5e98ed3e41242324c10dd90f43abc069f5576725cd3ab405e24f75af52ad94b4f5a384a2bbc44c4ad16236c31bd940b97f6ace2df621fef6596a18d8d6cb369a22eb353917e56365e4f8f0be85e9e9223702ffde2d6abef1cbd3ab29997c0229645acc294a49c722d34055ead17ba45b0eeb4901e9847ed35b3fda5d3e1fb9b5a6bb702613400e0c7737d216cde2e996085fba101801609bce6c81fe835123f95ae18e6ac30da7145a8f00aae36a74d97f16dd04266272eb2ed5c1d6f38663a8b48add9c1b5fffbce5b08a34f34bb70f77d994fe309d29e3fe241b58b57d3550b1d95665ec2d67fdd8a2aaec8be74b5210fa10726ef279288f50528706a45c87123497bc5ecf65fdbdbf13388649bb011438e1d10666fa362a6ebaaeb164a9a3c64da4d950359cda45b2495dbb1f2d3f171ec439773f70df218377f9e248103259dd50d6763ce2339f938df5d864aeb00700f8a992c000fcc7533b1134bb7e04ab26073712dd86ae335f2f8b394a78f1ff9344b9ba14eb835b2d42ca16104cd34221327ac3313facffbbd5aae710620520371c4e163e2135f7d9e71a36bd1afdba37a85a874c0baaa56c983221e94329206b3e6bf578a08cc07f156dca0b8886a223b9e1bdbbd189acb0bcac57c98ec20079374bd20a527724a9cc0f383a01b384e132644b386175f6a67d48d4672e85d2bcc62a7464a5aa8fe398f3e27e89207ba02e7562fedf7853e0d993dcb310d30fc429702561759694a89a31846d45315e0d9589315c7ec0d78d48c81ccb047de40c21228ab976c22267fb4b40b9efdd572ce05cf63a9a7fab18c79a26087eae0a40c402c2aeee3e474d1747d3954fd83af1de9eaa343e0175eb8de87e14647f341f8622d160e36e8053a7349289847898b6ea28ab634221132229597d300771149c4d6d0b87446daba3897d848d284b5a1b691f13057be2d3551aee871144c3b1d60a034edf9d80aa43122e420da3fb994d8e7cf1505368e5134849c2380c3deecf7b6d28d1d95b09d2077c39c15e8e89a58484cf519f4124d3470dfc2e8ff99d5b6e18273d34414c284fad3bde0b853db0f137ef931d1ed1041c784e592ec3e08ce48606119a95f2e51801b75be9972d6a3af3308488dae2385f7df0e0cf4b1934ab512f1112a15c65ce55a111ceac8d2a817ff8420655b6af47802a29236b21d2e999c138487038b365e3666d61a4b467651c60392d91d7ce5ff87041eded92427e5f8dff5c2be12bbad6dffb5ca45d92d9b185c5c4fb8a6a5b23628f878a06ab562664d9a31c71edc6d1d4dc9fd9d34a386d71367d18886fea452a7df281cf9ef41b4635462f18b86b83193ebced0618ab0c892dac294be7c94ab342b882d1a761056d2aeba5d9429395767152601e54c24ca2413c28d3407b17b16cffb12a281110d6274b95a75d67c8790ee8258b59581fa24ee267e05ff328e4ddb5451c01da390e878a11758b2857ee93d1326a0cfef01a2b88c2ebea894158cb812e51bc86bddb250bde7835f1c468d9b9ddcdf986db9f828c17da4a0f16c908695f27d1cc5769c926257e0566ff41dd3bc740dee3aecd3698134b74086578459613f1dc9ca5f186c7a79a21fc0538633a4642652a27a184466164480de55552c18f8cb8d0ccf50d0150754461a08701f724a874d97c11bc0840cd54b183ff233752a3fe1237aa38dcef5e396436cdf9d6cd5a9e580107b923853269a420a06c9a4a624119dc7e4d9eb9c0a6885279d01639e34b4faf2da559d3c0c085741411cc7b9cedc1314318d4b84665fc95d07b828509d395656251166a8a2a84a2227308afb1a898a94955b452d9d6a38b74f9456a2b8471a8b8b7b1adb57e967b7d23336f4ddb6ba753ae4dd200cf48bef46db6bf22f5be6705cef521463186835ae212d3481e902e6e60b65829c208e65213f4d6222e053af20c2beaa63a10dec04a4e0070b676f5111e71a0ef9f20b1f2c8f62d92a6beba3a49d332db0d9f3889a5f3b4bab4143d0b7e526d51372131292804192aa736a10adf148b9f48bf441dbeb7aeb44b2f01c72519b851c26ca2598bc2ddd91b6e0b7612ac0c8788e8c012eec849547e614a6a89414fed2a95bf6bc13264cc5cad3f0c9a5874197f4b859d83e07fdefd7b44e04efffb89d33637c201d3a9ffaf6927a7a73613260dea5f809c71cfd6cd4c969e10a29c31568c8eded2535368a2f897fe4a399938214d0e4060b86205936979f4e0b0262cabcd1893a9029e39a0bb6ba4654a09174bd93a131461b78c41da9ec6fc389f39d4b8116846603647428816d6b1b7421b615e01850e007e29215189ca3303c8a3e78374bcfca7da5851694a13e94c60ae82235c469dd7f3c77224cccadce182bf6157d7db8f7a02e85551c44a50b0eda6108eb2add6e8eff6cd7c4bb51098b182aa2f639dc9f781456c8757ad716bd45fd3b7f324ca5cb1455b3e831ff582a21132106e06d71daa98e56dcdc7b381ed643f91be77c0699456e651190b0f3e1049f2475623debc6ebbf035566aa9d025c6b57dbd417645270ed7713030cc4436d60b3904867d8449ae1c537c0066faf0fae951052ed2a7315057ca88d79881ff6185fc090c70ae3f068c0a9b20fda3e6de4e17b39d58d1b3269393ae604f4a3be05a7268d34b0a1da57e12daf42c63abb310aa2fd90268065479c98d92e0f5b60b73b805e0e5538d4395ea2e9ad308403219a4e0792080b5281157d9b05a93b950358d243b01932e0c25be8a80ec70550e32fd0eaa0868a8c1d42d7dca8f26695b0a6ba4cd7c05fa460e6a3167e4611db468d5a3f1a822c3bcab76848f667848de900fbf95a1840f5531779604e46fb51cae3b9db5a50a993941881d508649b8917845f379c857f47f182c5d945ce38cb8b71c074459222e31758e2c2ab5f5c2399e2ecd09e5ae44e7d9af682e1b8d83d07c04297d87a3c215ca0bb274cb8f5324d07c0ee76a579638340308ca9829811c379f5b0d404300201247be056d7828b161c40d68d7c7743fbdae91b27f1cd90e985dd37d48bed6b4e1423b5513c3b46ec6af869b7013526d4057901252bcb5419c1674507eddaff2bca410d8d095018c45ef169c671f24c53b95e88b6e6a22c44063cfa2762529d77139b05d75adb0dc5fd8eff58b0deec2261b56235d368f7fddc1208796f91d72b953cb0e234b234b53a094a33d80db9e3c11b0c71ca81c4be3ec13b0c37ddfded9702ebd627f44a7a783db645c349c85bb9dcac6d50625b60489619ae22424137a16027c528710f9a10bc99ab4bd0d5e401eecc3f22d5cf953ccd04efd20ef59feb3401074d7e87847b909ebf8c13baf2177326efd70dfbe556fe8b858d40adc26ed4eb4ab49a6b57c338cd42792ce760388ab5afc12d10dc05d80f8e6eae92b0bcc82305abffb0ea7837d0d3605dc5b3ea334772061ee40cdea66b04836ee9d1c06c380f028ed46aba4d5089dd25244cc8de2ff8cc120835e54ac1f28c6f4d80aed0bcb2d862584d44c55d65feb15f8830f9be6950f6f6cc69108a42f51890a787b961f4623b90b04cdba18063f560c6e407fce6b8895a1852240a2bc8a7c6816640b8dcbb7b7ba04a4ccd9fb674bf9619a89561f6bae0e402602f5b36f1833f65609e74ab45950994c71dd2b8e86efe9fdce68ad908fdf691bbf0dc06142899838e0504772f59ca1a4df6f94f72983d2781581e18130fe28a5af71905a114444707c2c580a50efb3c6823e83af5364abd67a16e7a992e8837688b6ddc29dfc77306225f089d9d0f6157d341df28984860fe89f031768b8116a0e2910bd92352ed8b846a9fb2da935887c437256507749f95662d553a337c5764422eba1919b69242fa84572b50880aa57a85a834a2d925b0a950419d3b56245c7e118f3327047ade0120b0d1cc095354ba547809d4471ceaf78ffffda8ce4148cf100651832a4c74704466d180dd16316f02b8602379e8a7a69b214b444e9903fc5d97d73e0254f8219c0a526653566ab008f9dbb1765dc30333f8dcfb8c84e281ce78050212d9709f8816d060238e5d4771c395134b2915bd85504b85f7c97d6c39b87d22c21bbcf85de7450c6c0cb07c1455386dd08c6088744afb560310a613fea83cf158e3be88c2b91afb5abd6a3a580101a6f65c62cbd920cf69bc27122d305c37c53b3eae8b6f9fd83e14471f6c6edc33bda4557c4dfa22e34804193d2fb3f313270602fdd1a452f46c7f2335138791c32996c486e60e96b4c03d196f19b09fd8670e79354ee1f09491a4d13110853cb40f64d4bde9b11037fa49c41f5cccded3be0d09b72e90f749b7f7715541c7cc458dd0cca353b1400467cf056891400ced36071e904f6ef7fe9e4c044e6ec04b80b19e2fadedba2f8a120d347ad42c26d9cb0458f278f9d01705ebe1c4d8d3ae7bffabfd90ef88f55523a87df8c1dfd70736c39051879aa7f446d05c8e97611c09419f205ffc469a8f47738da3bc2ffe7279facddbec95a7cbd2af2090754df3b3b1c23bead465dbbee257baf75b21b13c56057ef305714a7ff9402a87744c0872984683989175242ce94819a156d4ee4161a0b995564354a8095b0ec50257edd9952ab146a77ed136b7d9387d1f5c4c6061efa6c2fe3f4739cc15c086bfe3e916d2c3ab34ae643650bac1d68b104b9e3cbc302325cd7cd098617835f1754fd1de68042f4b80840f30a76c674296183401ff33d1c01882119fb4c22bb3b0eb366ef89aba48c7ce82426a6e421f3f3900b2059cc560bd7389e2cc1aa8b7eeb3a8e15f754289dd7b656b3719dade0eaba004e846c390baaca1ed7c2fdd70d2ff9f0320b16269b32a47a9c99719f2ce41fe31666a780f123dc0d42056550c292374b1e86a37ff3220c4dc69d9d3d9f9aca9f8004e0f88ba5df8ee163ca5be9a88ddd25a7154ec253b0c91eee3810fac25331433d518007f652370538c423500e17d22f3679af0a9577a692e45df71fb80a903d213ea030fd94c9a3a9a976a5076130b5d3687e3e70689ad4297094ea26cdc2ba17aaf84abc6da9dcd4864bd84ec9eced08eec4116534bcf59b646ea8f7a57dd656ab6269644f3973957bc6d1c8b508a85cfcf97168c1c6ecdc56d497fd79fc79f800dc17bd5363974aaee507d980a2167fda963ba4b047d7bd93792cc99b0902d69692c2ce931c2f8e07e938303db248b6d92aa801072afc71d40e53d7fde68486a9b54f4831c2a3d1fb7623a684242ef5d16f56c11922e2f1e89750afc2028065fc49f7dbfd71d59ca4c718a94bbe512e09cd12a0f7cf01ff81f80095ab5cf7ecd3ce842060ea975c14d57f28b1101ed98a9c70d53a599189b58ddab1dde2313b7f66ed7f1d903bc8c29284cdf027dded4e21f9a3d601122a988ff8a0291b07ffb6e4d49affddd6040211817f860948558007f3db9654b1144152fd614b9d7c05e5d2d5f03320cb8fcd7b3803304c2c082520d71ecd711c318b55c27e92e6a1c03bb3a4b0190f14e663a383d139a58b52f80b324ff0d98d39dfe0f2ebd198cea26b27107eabe7631b8802022bd196deb347091c1456e561c952c0886b89d6140991a1d034798985349cd6f4d57bfceaea5bc8823106b7425afb66cc145c305843c5a530bdfdb0cb7135746c5ff00c927a9c4a224edf6d83dc2c7255ef21d52b5351aeff5da96fbcac58ccbaf8b9f9f1e36afe27c6d6013800257839a6fd8d90eba94544a76462f32a035a44ffb69ab4b6c056c8197be6b54d3a6d5af1d5e48c12802afe644554012d8bacedb2006e7ddb625e08e6413aefc41b6cb71e7e0340446e8786833ec8c174557fa6d0f7d26a34cdf48299f43e1de392e5dfdab20a6b4a96216f98d0ae8ced2297de9c6990297568e7a0aa4d5bf0496527e8d86e8cf014ba353a2a33340fda89b4b2d7fc9a59408712927a21094ce4d7112c512a5e02f2c3949789c8be24abd7547bf0888488bff029f8a1709e5fc87431b053a6edc2bbb7c0b5c8094c9996b3d1b569fccfa0e192d85ac001fd84d80180ba5a30b1cf6363abe4a99ed6ef3bc3de7b6343613947e79c2e67c7f48d41f004582cfeb8d07f1f7fb1e7dd0b4b7b708a32f25362d87c4cfc97fb7bad7bbd0c8581d072a98e84710508973c872f914fa7a75a9a2621403d99c1e66da09e7d27e90c37f133e6319120f3cf0645445308a082da7e6a00e40ea2ceae39172b9626c3fbe41654e141321a446b151999d23ae9a422f6777c4e388b6a4cc5333416cc490669934917746323d1de651a4e866088a14e2029b8988a454041fec967b129e4a474c0674da10665125e11bb7301904fee8ca8eaf5c3c6dd84dd536aa34cea2a7769246c5f523bfff7cc9c9e56c6d5229176f5d054b47aa43c192ffb7680684aff45ba93a50e6b2c5d600088b6eba8653d33fccc45008085311ca1d30524105a3fbc976f49fa01a39997bab6edb649e4f2f57099ad20b1f7fff7bad710b43dc9d77e1f7efe055b71df9fcd25207ffb6f0100d141b862e6f2024274842db8c4c41084015e56143bf1def9d6bb373b32aa60cac3c9bbdaf6e3c20da3c7f961f6f0cdb3b744920b94febad441335fdfe7fd44fd9a1f77d354915796b4e2a0eab33616f8bbe2b356932c88acd4e564c4fa151ece53b4a9f027b881f2553dc87be7ed4fad522901098bd2e495057ad7fd6110e45af3d7cd51488461a5925b76a5bc26336a58d4381d4ecd55c008ebbbccc737f4c387fa1d1de1ed54ac0029e4c1b74b1ac3d022efb4e2bcd20d3a973e81e3a956a7c35a79f8607dc523d7dd67203303d1f9d800d648a5d7497c6f04996b25cc991fdd76ecef885f13815ea34ed8b310a5a455ab7ff91208ac6c2127811dc51484eec33d05f51e18a1ede806d2815cbe6b4d6963117f0200f184a36b30cefa02f980ecddfe1fbe93f0e834d7a405242370000d19086a2938b161f44d382fc9d4e3764c3de842ffeb7a64e28725fcf9042144176987cf1eaaeaf3edacd9b063e2e92e5bdbf9f5ab1126f4e05455134bcd6c32eb70cf4c952f0ea12a0822a40ce1fec3bc608359fa394f647efcc9c715f3dfc26a6e2beca75e0638688aacb381b2fb59ab56e57d12b675f0bf22a5690287d1781a027fa69f97ad65a77d0042328f08cc3dade9453203bb8333da0240e57d5d4fc7bad114b822c0090130cec914983adaad640bee1225548e0a41580622023eeb9e425a5756826e2b8c4257a5500d5d14379d6b00eac76c251f498639dafdc52b04d0731d86f3b96b0c068c366e63c4c39edc01847b90bc0c58b6e333a3832b08b27b06164f938f0930c8f6d74759fd8af0bc3338979559fc018bfc11e24cb2973ac941075e700f66c818a764d2c381a4ce96a67d48e7d400f3281515f6a19014823a8c5b5e9c70f2f686db4ed4308cc76fee9f73bf91b0c701090cc3e095072de76d4d92d939004638cd4133bdb7b3e2a242d39e174b80f0545cd2259447125f9f93a0ff392844224217681be5b10f0587677fcf716a3c470b9e51ff729f82ead9456db2398700e6cdaa8b607954e422f678a899c8282d4b40daeeb2ac16239503d2a2545cbace629c2d0ada00d3136ceb6c6d8b099fa3223781aba6d9da32d897fc987f1fdf04f5224c28bff0797f096496de154a2a31ab3f56628dcd02710330a1e958857a552eaf04abb8e8a3c86194c9ff959a6f337b9863de39b1200fcfb990d7c2a9e1e78266eaf45483805f37c5f664f46bc5e5524dc549c894b5f7b32072b8884c4a65b7bed75045a80616018ab940bac565f5df35eb03c57cf6cb0db763191efc972697627e06710fd558289fd70d997067860c7b4232d3b6f3fe8677d3bd4feb7d9c58ddade3a8b7ec8cacbc6c1acfb1e03367230ebb93a124ddaf83296919c0bd8a10e68629618fe45e43fcf2ec03a2abcfb497b36edbca8703a7803374f10f5f56a8078fbf224985018ac19bf34668077d09164e1402ee2171ba96152688a255cf15e86a4d0203229ecda2d5a28e0e00baf8fb7e7c290ea23a9f539865605cbcd39e1c9bd70c5f2ec2b1f7509c149a361ef2b156fde56a75595426367ad2697afc06a5f8779dab06352ee1170a792db30f8835ce347ade0cfeef6af083dc865672aff496b273984d06e5b91ce007a8dcb0a2b2b5e2c4a1f9a7521921cab34923e50555c2306247d977293e282cd58a3fd54f14fc46d3ecb51175dca963fa356fe1206345b4fe1e31a263d61330e10d6fb2ec47cb6f63008fdb4c70f22a79a9a03a34dd7743427590ba6a91b5a079aa34b984eebca7bca1ef0e7b4d24832947e6f07931fd77eec241227479488be371a4029470560cffa882841290f41db2c0626a2a96f1245f2e39dab7d8acb6b263aab46da4c1922890a8cadad8916fffbab2b95e7a82c2bbab1aa6b59ca5934c14fb3c4f36030de1e5e967c8e93427c41f0ed51e564fa38c9810a2792c3c6302a21eed88ed7a2955d9cc0df485f92745910f4c8b26a0ec6a30d65dd9c634730112bbe664407fe615ca77be86da8d8d46771a41311ccc98a2693a940e05a7993c716192316a83f8634768f30bf3f6dc60e2ef4931f898e577ec29b9d24fb08cbe8a0f700fb28431cc0ec6e064356a6b637216123bf480c3eab2c4dcf3b3fb7a3889d1177110df79b8c264867d3a0bf78e301fd654e8e108ad845070b792644431626e22d0323dd57a975854d72038404a00a5df33e478a24527ee955e514983448eb01e746d4d33ea1c40246a43b79ce49ad334eaac8f3a4421a27f52c79642772f1f0516d1954f446e44b91b35b087a832f17341399ee0daa29c5ca2967be973d2cf82b053b0057c612e9b4c047b7bb0d7df103651c02a225017e3f4e2fc491d36a9069c9b6d3513bcab75f21b58719ab75b285ae95c14112cf68c973c40f9f447bd05a00226267216bde84ead8907ed6f06efc46410eeb41808fbb67e9a3499cb91da78482dc7782b7a0c1833a18055d7611be34174e438351172aad13b845881224943e0034d260f1ba14363140975e239c20b25c35154bc413e8da1058df327503d55297685d91edf337df77b6022f093b9d19b2046ce082ae03560c5339dd4ed6a4f9ec5609486904b433341b47d957fc4ff725b01b6eb0a353f6a2cc42dc91a6029711d225b80c7029e516cb49658925337df29c1fa0fd7f2d49daaa1c79ea5e3537e85e20b7a91dc4bd1da498415406c5004bff4bc74c88b368369968f1e1abf9ae8bb8e1f6f36dbcc582ddc8bd44fd984a3d9da52376a8fc9cdc20e1c078249a7dae98c03256da4cb0cb873a318fe0b30b382e6dce4bc33b8d0f430189410471a1f12dbbc5860fa2ba5a63e7e8859e53b973bb4a50f618646b924ce6a4b2a4267847807d2ed09d4298b5866469d3b346f3b5b5e05f750e8f2f841fca881ea2a3e8a072eedb7cc3b0348f9b5ab6b213f547d3e56709f6ad2abc960767f8bb35350f4bda51be8bba9a8718a839c19d63a4e190d3b2e6463141a80481f5818a2d48d13c2f0447072068cff158ac333be36c2999f2920be63096373afed0e1ba144da10a96829e63ee38fc8db5ff821712bda2850f642974d2b604a76acdc9ad49467763db1c9bfbc08a3be064548a40bd9f144b15a3b8c49bcb62e9faf90f0a18cac264d5f744814689ba6ba41a4a1904ba21ffb53f5915084f882c55860834f4e827e222b897c04a20a4c45cd43005d9e10c2f1f0878363d95d83404962070a892da0431b0227dc02d8ae6bb89f1e1a8408472569963d5cf85244c267a14723c47242bf24a215ddbc3af4d813dca31808cdf4dbd593f93e9dfa436d88a3508ced791d59654d2d02fcfb6cc960d7e2558b24bac7b1eb388b380a88b2e838fa49af4281052b9c6829062f1166245a818686ad190cdaddca19e09d713a58ced5eddc71c67a5e2ec43268851234e07a94dff2cb6f6330a7a68cc4806bd516b7d8f3298746aad99788ee868c3ee1d392b9475649651e7c81a58dd5e26a460f54a0403941fdb7bf1a1a37a54683ea16123370c1b47ae46eda1e1720a1287c9dfc53eb7229620f79e40672d0dd9cf16cb515b678a677ee6d82319f72950cdcaa23c63650831784a9634c1ae7c5929ab0de74570f79abfc7b951f119f881227f96a1e26edd4806b6e621279073723bda0cfb75dc37196c725b5498a304d37a318ec3ee49df6fdb215291e842c507ca80ba18edb7c39da46e0f59f41514494d2ea19c8ed96cf38d9bd62215d4fe9adf73f08dda04b8759ec4ddb771e426e71f8653980883a48a0cdbdf68da6b3729784911273e6762f4fe5e464ae08dbcb1c9420fe36f75d5372e196803e8a877d0b87a029b77c35b8698a28344510cd998889823573b93f082c3941ca9ced0a2d58811c1741345054d0aa18b50bf4adb2929d8fc5c6cab2b33c5327b9b3a129413c52a2c41e2020f7d1cd465c017c73cf96167a05e1634ef210f00e84e0fd8dfee5ec15079c27741625fa7dc93f7f3d23f1baa709290c63b017e600406812bb03400041fca8725a13b51768040ef8141baa65138f354e664367af3421cf849f1107803b07da0eb8f772c13f9874999e8b2ff3e8ec76a5d06329cc5a98e594a709ca4d494e8529c4402d44d2558fca41ed413ec1bd169cba43ed706e243f2fd00baff90fda4a1601a0c5ce1d979a1f6c0607ddc231e572dc9ab8dd0c9cddb38b522db93c5af6c611a3592f6e27dc0ab1d4035953047d5bea9026117edf8efb4e167b1165f10056afc2de307aa08c289d632c5c4a3aa84a4ca3830025cb69f2ccaf2c7ed9d98ad3636828444eed78910923f682af01c9574cfeda3b0c20dfcee81b2dab28a7408ba57f52be12b93c42919158ead446ff9b9d1690689d73a4d328a2b2ee182329a6df86dec8b6cac517d5367f36a421ab4fba7369088865aee90394b6460c16b091cd8e1e66a5732991feb3b8a93932e2d622b7ce1738d5244404b5b2508d6311ef3f232c00b018f7126428c93a4314e8ac9002ba23a2dbd3701d10b0e74dfca2aa162412ccee33e3aeb544a60eeb694381254751031e73a79eb78c40a46129a87d26369bc38c358baa291c18dc4d000e8ee826d517080149263f83d15fc9244ec9cf81c6b853338155cb316d609fad0f0f253e738c8c01ddb122fc1005a1731f327b2b3d5baa78b21536fe6bf6353f6e6ad910d8103247187356f18d8573d36b30fbed761801d455aa41fdc3c4c20d0630152de7b616bfc1dcfd1d009f36ddfa2c4fb249c3e75865af7e2d78f38b362a6dab25d522b9315fd65c16485abef7a3179ba88a3f099060d76e27c8fc316862f6349aca1f67b86f2ed5b228cfa22062f74ee58c5aef3582b72a2b678245055be5376505c587ce0928cf54a132316798bf3cb68bdc2a4bfdd06c74212adfb6f27cf3627b878c7e566fea8034be45bb3710744798933ad3b55739a77a82edb89c774bfc4b3de819c7bb7ea84cc2dd0e88c1d0d85408e520b650df7ef0c793d52a180613bb8138ee5e517ffc57da0b90e2fcfa2bc2c83aec7c90370490b974136e1eb080055cd24348813146c41fd991525cde4763ada96e979bd648f0795db5c13e61edd9f558fcb573ad7c93321bc69038a4a5679d51572a0109d804fddaa50230559e8d5d97064d95990a62c7cc7ecc186aabd6bc6d42db8a4240d9624151918c2d1cfdc32e0937734f677609c6ec8e959368a9cc46c8d6ba3d1548f9002eb0228c427bab740752f1e23f6b59704f9d4c32f0e3afdbf58852a0cf6f5ba80b268ff1a62495b78e5960c8724427fbd3213c0692c5436c66f0ce345de625e21891fff033772d9388a1405bc26127fa5f8ac583900ad6ebc312210b06454bc82a487d8f77f292ae332e3cef83ad34d725c663f7f176bb17f8bbbbd0a7ee574f3cac5960fa0a38e8008832deb35d95aa83ef283f04dfac61e78ce9286a404ca2fa0a08fdfdcb35478807b3c9341bea8133fc142a4908d519afe88fd5cbce581e04de5d588d5ac4ca0ce3c16fa22a224615bd9c4e2819b0a6e5b1c8a9dc95a74f232508d92ea385995c5e2e319e1775df48c57acd47940bd930560050c8ec2631a0badee3524595b0d3c111e47f0cd3cb852eacc6f3c7b95a40aa9bd987c855da64e4989c777e84e537c3821fa318f452066eecaff3126201f11f8153d76032eae111e163348febda9537cac59b2ffb3a65c36967edb0637466e916da61e53b22bd676584f1f48bd23dba4032c72be855292fc03bbc5f67e4a59a388d786a4c224c81a0306b5d561babe984e2b77f2953db4b6383a5d5eab7e94062f08abd3541822269400980c2f0f7e280072afbfa372d5426049af49d29e7360cce6af6f29784821ad985d6888e942a9c0388f3bab3551298c9d3f6ac452abda7a3788bf3213306f0b91ed91b905d06b52ae32ab1e2643696c0363e301be7f1ea0f178509fb19ce592c970f52c861001cace3c230d451f29f7b7a16ea0d65279299491624f05a1a7210badd8983b02ce3d748e6f11fa49e6f547f6fea9d35d53e58cb282ea0b9c3bf248b971167ed6d3d80bd96843890f308fa168a2236f9225dc744f3253dc5dc606060d3ef8f302a6df3edd822e426d70ba0ffb7568323cf4d1841d68582698c698b388ac25e765c2082df63d5dfeac1fcf26928e2fa89c39cffdacdd772d3ff6258f1d6cee65cf20dec6847f49d44d76a43b392397b2ab19a65781273a2d7f9d314f3c63dd48b0676a16d7a5b80bd98ce1462f691e97081190e7044385332622cbdbb72cb475b1b92485967a3f4ba752876073e636f7b374573e1be4fadbf3a001229188c1729b831161e476eee231d7952919ea9bda00e6f03755a17b4288c8ca553f366b9bf0f410140eb42e68a0c82813169059265c3fa6325349435fd597333cb819e209c4f0503d749978098bfade7417f0702ce4a6ed96a6513a8de6a6999ff3757aca30489e904587896dba01a9ee4f21136717b4c8e1d47a4e931b34898e305023c9d6249f2f7c59955d3769a7e78cf5c46c9853b7b6e3bdd06ae407343dc228251e885fd0d0ac70d55b2e49fd9bd5144f85716fa17c9c711deea17fa11bca8a8011744ea57c1601a1fb160f00a62ade91183a4ade0b164307febad02d30801229cd5b8f242c37954d6b6108c36c5da1705bf85f57cf00f3b232d24a209c4ab7697b02f8ca870018c743251d51a4bb4a6deda4e2954d7805ff5c5a96884511424ff437380dd95f237f620b1c0f8a36f3cf158eae145f4cd883f6caa71a249835c9dea581bf953aa097b8d54d00d72048844592f61c191607647d5889324d10311ee3395d6bfa94df959c9038711e7ca3a10a936e5767546da0af6ae8e9df531508f78efb22aa2bee089281d473124374450401f0fa1da29f85063579ea84b4bbf3fb4de3d7b7780b37e5652357697e370365cc6ab1447ea0d21e2292351c9ffb262638708c7c7a6a75ec6af77a7aba978843ec8a640a6d74b9573cc90fcd18d7c2bbb650df1e75d3a78e3f054b96915482dd5f254bdb3f8d76d096eb9ebd409706e533005e0b316c05a872d54d1813bb58f1a8920592fa0d7fdfeccea3dd039e2dc1e07ea6a43b47ea40d90e70e7a17796ae40dd1ccfe554a0fe7faafde579f9e8a1d99e2f3d588cab0b172f02eae7b9e2cad7b08b86795507bab777abe420fe4820a9470c6384cba891af81fe6e0336c056d1bf2970b70ebf4fe5b3029e3e3b3356752f6eb0537cdd0922300baf2929b343b19f9e65b5a38a07e399b1e5e3e41c7f66994a83ed39d002e225980454686effdc506a85ad3e4ff4a8a81332d0df491feaa7c06f9c06b67cd350e3cd73258e83105576ac3776fe911a6febc551c4da3ac2e175c712abb0e83793b4e8ba23d79e16536dd29e0e4e04be7eb6423fbc7f7d93e7d3b06d8e2fb1e7a07d331bedffe2ec2c32f94dd683351407aa4a27b9fa64c394bafe3c94f22c3a41ad13b8c424754064bf1c5a3929af24c343994a5f23c962ad8a33b8293c29db54cbbf17bd6de2df094a27c0bd4093957d7e9cc60fef798ee8f3300b90449eecaaa321d632e20841075d900238b86bab22175ab1fd917a7b3c060e70b925cc6fd6c68b3bef7f44481a098144b06663d07a1b5451c83d8205df0f4019bcf6837095a89f5b4f3b05ad0eb73dc1d35918aedfe694e87cc1b1fefe88401097265789e0100bc1fbb125664d51b4e50950368be071022866f4cdae2e0be925ffe74a412bcc60f936d30e043688ca82f2caafbaaa139878e22a4435cdcb7c4141b6baf9b9073394c028f646bfe2c487b0fdce424ef1ffa2c920cd06f1b217b3024239e5f0e2cae89bce47b87d7d02d1ae52caecd923bce0a238f448b8d38ec91e1e24c8323607cf530e235f576a1343cb484aacd2347b3ce14c4b15d435e27a2fd4fe3b30b7e88d655711c623aa1ed408e76a92c7e9863a96a5f86afb1dfcebb40b85a384c7e59a9601e2e2e462e61487f8c7ca91339d6f01160262187f2b72c681fd6c70efb676543a17444706fabe4e5c5f97f65075fbbcbae9e0c29f62f7006c0cf50c505a7f1098f633610921af0793f8d588401f861f85f919ac73cc99e181142005185992d6d4bd43e16f4e4ab94cf467c87ce3e325f656c21deff45731752a4646d75b2f191cecfef874191c70c5a0812d7cfe60b4ba153e417c117434100543f2fe3df55421fb8c4ee80073c1241396ccaf3247f096ae99b89428fb7efca22e32f7a1064354f194cf4afea9118c1af490b90626d51318c0ecc9d277756f341d0b269e0c38a7121321f1783429095a9e00339001f26bf46f3f6c953fa7b8ddbe1fd645e4a6839ea9e194f91459583e46c4383eb878767fb18903b8ceb27930630cf3fab1b02725eb42ea1a828d404d76380b553a5b907b3d93dc268d9a198398fb3b978987121ba5631a382671f0d07eb9a94bd56e8da74e1c216f94bc0fcef7043865278df6956cec6b85394df7cb9c7956cf1ee408452e9757b82b261058df3b54e40d54d8750b5bcfb9b910b6a1b7e76c0b20303022636acf156a2cf215022e8dc4af9e6e08b4bc3378ee7ba04da1decfd99ae0146ee617eaaa4ae4505fff8466fe369e9e3a22162d98635365aa590f8a224365b740516b167ef4a1fec3059310473a2316f7a54506cf47593e8c56a3ab97506945a67be488098600a6fb4ba6514773ea954104c4458cf623adb1ed72fbf7480e2b768d80daa993579f513ba61ca45558530d5a90067d46312eb80b272b92d82f928d225d7f1e82fd8063ad849de4486e884b7e41c46291005ac9191a5a2cd381f63cc13623f2bd9cf070ea2bb934134414f0909341953f3f748ca8f0eb33916f4ff5e32aa83a866519c7d5fdd83e060cb9731d3e1a8647f3814e44dc84b2787ba963a1a6cd8e160e35b4b42e551dccbcc10090d785fb8adcbf807774267ba6a9a71341db2aca392a5b1bcdde4e3d2d078dcc6381b8b4c8f7af4a07f62d7fb433a5ad6fff4726bc5dfca5c70feed5cb6c03e6e91d6691cb5c8270c8721b141171c32d18922a61fa45efdf4effad96cfd0f2117fb8e11b5ec406bbb5b485a01dffc4af7c9f997e9c451c07215ec121e29c2a57f7079ec217f9421be6b67c2b7ee0f484b34077ead5538951e8cb4f2d4fd37292fdb108be9d2fc1eb728e9d54ddcba7731b5cd77d2d442a6621aca448e20d76bb09eec23a3adbeca648938d86e759c54fbe312cdf2c5f809e9b98472481f400f2e93e533d94d9768f0fd7f200c543b4c9023ad9a93976047812c995b13561d507860c6569d1c49ffc4ce24825f5c27eb0460d2b880721216cc760dbaa9506c28b84671be511c59d8c3c14ac5c37f64ad8bbce117ce312f253f1fa356b8a99ff8e0f2d66b0129b32cc998e42aa79e8ab3c007aea6bc8e6a1b2c6a68cecf0d33655cc28c06d99f6891d5e127dfe25e8649fe7e15f077c95a7e0160250176162e6c28209e4eef916a80875182fe963a432c7531f6e2e0ef8949bf55e9123549ae067c335518bf72b1fd91ee6c67519a457e66e131fb9a155bc76d24304731d0de790d1b6274a68cda662da540a349ebe584671bf763195f7f1355a33cd92cf7c815c8786cde852236776ef5c523e9a24e97eaffb073a411b68c1fd6467bdd50eb8632291326c18517361bbad855404b8c9d10323a49a7c09b7c172a0cf3f9644c16ff4602f9ecc1922d6469079842eaa8bdbec94e6394a661a8fccf222f082e882e3d17ad26f886ee19dda8db58ac3bb61110b436964489c1e2dcb9d4426ab00d34c0fdad4f3e2d90a30493f10683a75d98319d6411ae0e9451d297fd981f72249d4b67393c18904b747fb4b1299f579e8e2ae908a1e7760231f797c2f1f04242d3421464d1d8d78451e9c1f229e9ecd280ff9032936794dbf114f07ec72132ddfa540e0c47e55c1b603c9af082d7e6f6c912bf3ac112b646e280e894930c028a5264a6b003bdd1ffc6170187aafdd786d603cbcd412291da4f0c09247ef2674913d041246d42205a45968abaf6e4e5e675fc75a61d81bf27d58fbdbeddb76cf42aecbc033d232ea5253b5af17a18c1711ce69eebd739b542cc094218e46f0262d0cac4c7da81e5a1d2b8c0fda737e4b1ff58cf90ecff8c7a2bdb4c16c0b71879244bc0274bb7251be46a3bfd2d29426ec1e15c904ec359af22fe864ed2fe542e042a520a7e15f08d067cc2e93972caf3f0d9fabf4f2e14d9867008dc6694db8864c119bc5caad545c4bb21d9c0fa78da81efdc3f9a6115ab6dcc9d7a62943c39e1dcbda242fadd953f0d762a29c38588e858daec53ff6d40721e4d13665d7005f5a5ef044179eff415a622fd4a1a53afb0e0dc37be7259ccd3494df6172d4a5491ee84f5f7d848a737e1c35f656054d6312d507f8622ac9bf1a205ca8a721f3ca60e55506c87f096830be9509f2401c85b3f4c1f0d1fae71cfaba276121487e691e87f58ec884548c20d66cba0a1924060b28358512239776f40b32778261098bceeea65f529aae74d0459e9198fe49bb113ff5a7822194172d66d64a58c2f7863f502955f7d48e3cb36623c1aec3d483d0db14f0fc38c2bcb781625d69dcba2dbc5beb98708c034b5431e6f8154af7adae20c3059b6787935dff169c7c624d88678b63e0310c9cceaadecd2492b9f48284735badafb0067ecda02df8e3c4d62f4e83f95840945a9454fb03f0a657bdb7436e733bd840d71409482b5b79d67f92ab5ab9c6093d056f6c81639f974be378c78df45dc1f923a16db01a7e9fdbcbd0461429268a28de7347974818a39c6602ca81069f4a9bb5e9783fbfb01afe63a64010d26c3999a6c033303e7e1cc2bd3c60d9fb607a6204f09b8e04392148554cc836ed21ff4a2cc0af8fb0b0e4c242d0f5c29071b8c2c447e4cea0f11ec7b1810061f403a01adc4c70505ccdce6702a79182d9cd874358ad9cfc1e22d1c3642c3e598ba2b2ff6f52e39ce948542ac0724864daefa7fbaf412014c1634ae86cfdd72059f1df2931057f5f284821bb797c0451a16ec39e863cbef984543b266f99e84871e1776bc3332343bb7146f1a7aba794b8f06e671042e5e4ffc26b1837c3e07ac479fd6cfc00ed221675542aa0fa2ad3a67e5c8049dff89357d5e5895d754f1d0fc8f2d87210a2a6389a69b0d595a213e8db46a4b050b240fce94e7574f66134d407bc44f436d7c01fec82aad42168840b731cb03cb8bc9ec8e3b41946d38751feee4f70b061e986398c4206bdbc030bba21965393119ec77a8f39064f0e2caa36b07d69588694bebe32eec3f2ef7cca67629e7d32328c8eba357840acd9901fb20aa0c0c8962e5c9a0b44479dd70e07a342583103f75bd25af75ebe2ebd42b2bbb6ace7dc40e0d96a7d85ec9632a51ef27141d15afdd27805cf679afd23f8275f8139cc50c9af703d05263364484ff4127409b7b02e01ee76c9ab481d1efdba8738021df1f3983edce8f551601dc18086006228a7c064db8c91ad4b3a4330f627e36360d06c6657c0af430dfb72dbd1393fa630bb64a9f7e087958b234ee4bd6b32f552fe379eebc926df040a9643f5df404a5ee1da08336e60e73d7cf77473ca15af66a4aa49cda99d718f1bf65af493f2fe2d8708b82295d863e8847f8f9ee30c3eef0a50c73f93a7f6cb9c36053fa05de8096d451f1e7b8d017a5a976a77dd311b4a0be48f0153aab108261d48b323f50cd56d886af34143973e70c1cc2f02a0fc42f59f7cb6224fe9588698a44ade8ae735ce0d96509ad30983d4d078cd352b30bba2ceb1a3016ae3066fc2d87e19a153683af92503951e7da566b86230b5df726a95ed9ea9d833fe90a4a7e9d29a3732985e8b427c7a9a94375a0204e58eb578e5686c20a56f0a609daa8732f5374502fc04ec57250f64fba7419cb488a128883a914b7333496e258a1beb57646a05466d4247e837d7e51caf72044ac55da0f2f2366cde278219c6ef7a5e73c77be1d272969c7fa9d6925a535ba040ef235b10cfb7a24185ac42cd350022dac4256be154b16af319b186b6a2c9b558d01dc26a9e5eecb3d64070101313e91a51af79f72a3e223706f6cabb9b40dc88aaa542ef0017d024a2e72880ef6e1b827894205e45c375a0aed832e1dcb091ea20a91ba0fd2cff4c44d75f609506649b52876d7ea6bbe1b7c1439176ef3ce7f5deca68c724065c503b5fdc67eeac0e3a920315fb72d422800122741cb2773bddde0742a313440810891e678d366a5f41c1c2bcba51a0b6f5c06a45d875f6c1b5a0866de03141ceb29b1072ed7ebb1e84d22f332cc7061eefaa1e3c26e65e160116b2223a4a1aa127f0faef07174ce1505590d3573b629e667938eca523ce34980acd65041e549436fcc00933a2502eb06f6a7836722a1f4b7d8e2fcf83b1801a40f7f9bd011d7286005577c4cd23502a7049075ace07f427687c4c48a408aa2b433b6d62615b9af7480da306e49dd5f3dbafa2d44c8fd41e323a85b511407829aac141694d4a5332ccbc75819cbae1157b304a90b29b9e65a28132612df19772c8717d04a0fb09f73d4c4b0211b6402b0c964344343e68fc00a03928075eea591e7ff14347a62212dc9f41f41fc83680e41220453ff4765d870a80b06014c05509285f100a4a005aa85cbc88568ab07050f56bfe1d3b10b3d30bef485a8ab6b4d8da6110f0ee9046d9dc1a058409313ff3144720f502576e96b983b107369cf20c9f4dc975188ea64a995211483c558bf0c4d540798b2a6eb232a776af9b883a9d04608163f5e286eefb82f370e5bff3dc36c8775b9ab689e16ec88d1a245ac1af30d145e8181e529b64eb06e568dc552e0ee3ed0aeddb16b846f6e49b7f66ee31355ec3e1c826d804d4d8e8d2c083551592eda359631e004ecf55609a974f2bc32ae8589ade47757bfba05311d16cd793bfe7aa84d166595f64a80c99e9492371ae522b987c0a25e16a55a2c6cd8658d9d99cd13563a8c9a02d4aa5d7a5f10aac8d9e29e87c45631227bd10ba4c60ab2da956dd01e6819e018195301a83192dc360a89d466ee73dbb929eeb359c741e295a9e52baf740675fb60c4d5f5fbaeb3d932c865c1c12391000012c8ed83e18c05644c3b4611c89ad6911c985560c117d931c6e9649771de9a780213898e5c7d864c28909fd5e402bfc490816874cc1d492b29b7fb92b761257fef20531761ef025f0d6b74fd4b5e2307f8a4f5473421435c245134be4004b56808e1f399a29f2394113f3904968cd328698d19591fd14738a9a89b38c18c64dfa2e5672e8a560a5e2db07f82ff59c6c6cc20c622b490c87cff9101eddf3f825ae2840b306a440a74c34010dd5941ebb1252b82181d5215a8635cc8d1eb466a0ca4fde1c9c51c8484a2cec1b40a3fd5c963805ec153f743e6a2e09286e9566449b0109280133f08ec3dab2188191db055430952d28db868b424ea7b2ec68b9edb848a0944c1f748d238c5a13d138685c4ecdb7352ee1e7a340133509388e89ec8efaa31a07d06d4279e3327a733d2932f4853d0360d2a140535cd395b92272af16e5b0763ca3c52d38d939fdbef8185ee1a230678c1ebde71201705e6d57ebf864d282a6045dfdf03519a3355940d0accdc4b131229090e9d649e41c3ac4f16aee9a4e87a36be57a08beaefc253c69c3eec8f8fb3cd06687de23dcf4f7e04e2a19813287843b8abadf8824ddda673caa57c5b0d3764f988a9fb882d147e63029611c672c06cf77d0068d44ca15bd80e4a19753b5e88b748445f8f9ca0e6852313f35a7c2f16826a78f6522f1bcee690c88f5b733b4f1ab9b323d0c1d6333d69b01242f843f0b052034983f2226629e2b6e18ec59f6c76d84717392867b7103af648152663fe63566a1cbccf1042806752b91d7e373b366941656b17282ccf7b1b0e9f1c9bc78acd7d8b3602f698d4e00c5411f180f88c431608042b6ea230c6dd94eb80630e66d4dd62189768cca6f4d3a83634168abe353c5af3fb6b094cee4e7574041ca0cabe84daa23f728a840a26ad9478818d34ae8c27c407bed290b55eb5d108b95c913bd5c03a78845fff71c50e4798daa9d319ee588bcb80883434220bb460b474161f03444dfd73662f7d6f154568e78f77115764edd1d1d4e682941166d05b09d43d91967df7f2841793c1f176277ccc80ba040dfe6d1d94837b2a4d879d1c6e4204608f65c17887338a49c97eb4ed78b36eeffc274bcabc6ee26ffe462bfd2c78744fbf4632c2979baa72b3336bb6f67d5a8ccdef2e33d197041ae89b55a26e70a2f37cb1ecf6ef67f1e9de4468b78a0296f0dcb95077cfb6c7c77f27bc42bed09d508c144e57c664bc81acdd485e32b870516b045c2fd8c0808c59b6ba70a12b2a03e4bd35878f27e96fe948faa2a9334aa89d169bc222ce718ef9df4634a0cd82a9b38312f67023793e8a84a84e2f17c038ab6b25a776a7b13fdcc2aa8dd2a256f00d458729ff65341aa326927506da81a44d40a4172697bceaa0fdd4addde54213d51ff043a697372597745e8b77095dc7f68474ae6fbedf6385471003182a04e295558ec656bd5b3500fd67675c684c172cf878cd1f7e3839476bb2080cc35714b001245168109578657a22f79ffaf3c61c063121072891417f2f2e855ab6cb1c0a6a249056a82bc4d7d37b59ebbdc009c699834403fb7f88ea309f399fa7431cd7d774996a5d06132690fa4fe48fb49ac35d9bfef0832bb05a3100059e80ca218c75363e33346c93b37813751448eefae89e426b7b3f7c24e5a3f1e4fe4a94b5afb854ce07495f4a663d558ad8f62e8409e96837a9b3246a0b366feb4f88e6cb2862f9729c8c6fab20c97c6736333987351ff4e7a64f2496111f8a4b4e16f6f18d9b0ef3cb5de6c0d19686149a5f34d065b0fa416ee347da33ae428e6fe9f5c30dc63179a441daa3a373c59c4b3fc2f4a3470961402bcef3526273f713f14ed1ee2fafc57fa451f4ecbbb33a2979c5d459abf736dc595791fac27fbfac852517a86c7214e3245d6b0a2a177514a9c017bbbb5e5646f690389ce90b84bfbfd5b6948fb064b3f93074f85efa7f3876e1379b20c0c193388812dc0724839302e66e0cbf235f181424e69e050baf9740d43579c69c03a83289b7a2bad651439ec38111e6f007e393c828c6d894a3a2b7d99754a9c1b374ef0197d9891fcd9083673d643c73f741172f0d2dfef42371f13680fdb38b3e62b1485544b9b58a33700ce0f6ba9997717212e01cf3958acc7fdb2e925ed2b428eb69fc9f3a48fb781b763c2c68f45bf798fd6c868972ba63c09ab617f81813af39f215b1ca1b200e1eb2fe318c9fb23a6757ca68e04111d73b061fb44003a22c42023a1f7312ad8278768c94f55b5571fab412f358ca2310c3ef37adcf1af462d19c1b6837aec761cedeff827584a0addc157b7b569eaeb4eba2f11210171bd05fca2f782e4fa50ca1bdc430154bb7e350fda63fc65b043cad0c201f86f3f564e7bf805a1f5dd051bda62312146a540dde60d8b1a6e578014212c6f76696e8b3ef9dfbdf992e606ac78ed3fc72540e997ae7f3300eb032d0046eb62a9b054f7ebe9f8d84050cd036eb6add8208c03b10c1b86c0e881dd24dcd6860024c6681447b03f1ad471a336dbf017bf50f7903973b1863c5a99a2467c688eb809e7488fe6a96ee28d221d9ac642587777a7327d82f48fe164ff42f4d5d7e397fa57b75092ca3ac748f648c729ae8b4d24d1e12670ce205d4674837055ace193dacb53e81de960b25acb7fcef01f26dee7d2ff816f4f7b8262c9bf31233e8a4e4894b92d11d4c258ea42ec90eb77640273ae7cde2ffabc7bf6b2594bc3ddf8aad076e921645a05dbb892c1a5e75fb81c795d671499d1d55937e42ca5c8986fac60a3e0877cf66228b8ae39f1d8e4a95468eec3010415c484e176f3470cd13363af1cd27281f9293802bffd39bde5ed0badb3860ba3e432c3fe2d33a9464687faf3815ac9c372f32fdf20b4c2030a627bab5a3098554d3ae536bfdf39bfede6b73bc7ce9ff66187950203763775178845576ffbb78de8fcefe263ffed236c873dcc5afa17607f08d053d0df6125eb56de1f2b357b70412562dd0c98db88c96e6f8d6c238410b2c9267bcbbd03ab0a870a890a75f647ba57c5d2ac22e952be6c2471dc6e2a6d78f42abe5eaf579d39dea57cc9f1f0b8dd74121e37572c93b64c2a6d9f24acf2e11efe9a65c2970a612d7df44e4d2f892a132edd3573a9f412c6f1308e115475e38e0dd6934455c53e6cef93ee9a99847136ec8a65d58d7efdab5d74c992fcf2fedafeaa27fdd5c3ccf6e0787292922f9a76142945be688735caa6225fb47b2af9a25d13c1073a9045d646f7c431c758f3769238d24c3a28bec0bb6686ddfc0aff2afd556fea5cb7c36a36bd6613ac73e9e3cca44b59f3d2b1b9b47d7449a1b96486431e5d3a64d8cdae512e3192eb71ea6dc8a30b96431e7bc8f5a36bd49183a13ceaf840ae778d35723d066e76e1d44ba18aa57ce94cfa0481e8eccd9344fa9188a3d379bbcc20e8619c0e1b51b12b96fb060e9a370cebdc16bbe847733482fca5ba85436f3f7da0b7d847aedeb5df729c6b7a1e3ee15315e6185a30088dbbf7d16efffe611cee5b876f70df388c63a737411eb89013c32a2009691ebfed63c8dd879a37095e59430550f6ce7d823c58fcb21f6116d1b5c39347f76c152c92f076073f726f8c83e62f739fa0c52a1f54372c4e5681f8c6bdfd78b1ca87ed02347bf8625887a761b7ee276635cb7ebe593d84f334ad40b3bd67ef477b4540246f406c41d46c39acf2613bf70de3dcd37318c77ebbfd46bf1259720fab66cdbf6ab366f5a89051d193efabf8c9979e4258314efd7de3b1bee7bd5acb9ad95c08edeb1b67bb3d4eadb5e2142eca35cb709024b7573fee32b27ccf2359fe246f380ccb3e70d7f0c8d22c1c34c33a6b8775c641b38b660de368e3178496b96b9cf7f1bbf16da26b6616f9523fc15721a459fb88a39d7bf7f179246b643838926bb6130c82e278b7991ec4f1bc7fb2e6e397ebabc538de6bbe51b38771b86b0782bbcb9c21731d5d3256b9ec7779f87d77efd27222ab59da377166efb234ab7aa2a649f0ac6f135916b3f410ce9eb5562bc44241d374644f0381984bf2acfdcd19dea67db60961cd33b7266bee35fb8dded840b63ed48c63afc13a5f1f6abed7c499bd49af0da9149e942dadd66bb8af6c55297b464bd952ca2683f65aebbd2acaecd52a3f2bade00dedf514f4819ebe41aa6109ce2c56f9d22af0e4a401bd95dd8028db57296fd05beb43d82c793acaa4e8824c8a2a849ab5da90f0662993e2093f90a209364b9914480862a9b042855aeb83f094a54c8a1f2978a04411c51850a238c9521605922b5821ab20cc680f2c0c1443d00009103ef063095c10210c4e683640c14031c4063e4c546ba13065298bc20859254b5914427a789265d466b96fb308e525ed41815020ea83f6a03fa80fe5b10517444a920c6da124c9912155ab416bd5346bb75befa53def1dd5902f7dcdda6dbb973b42bef4b77b39aeebbcaf7e1fedf9715de779df07168dea68447b8eee6826e93eeffb4070f46344ead7f8b600b9c8fd11d188d40fb70895e47e2989a99a4cb4a7e98efa887ce9f78f2b843450ffe8293a48fb28e91dcdd3451191922e8a92cc298a10192254a7a843725f13ca334817b3c7e43179ba9849cc9e23fa48534944ac216737a5b56ab65a4b7bda3bbab329ad55d3ec56b78df6dcaa66edb6ddcb75b5eb68cf6ebb1cd7759ef78120ed0976def781e068440a6b18d29e21382291c2b0543299541313dad3c464723a9d9ca05028a99a4ad19ea9d247c557357d5434b9c9e9f451f1e43bf9a888026dccec49948a82427ba2dcd1952ffd934b29a63ce44bbf12d91d84e3ad44b2a6cb7d8d88acd1662f3ed070344a69a548d449ad16554aabc5ac5a2d01376f6fb4a5a4b2524a395b03af6a76bbdce5ee6667b4a76a76bb1b8d249a4043ed635635bb591a49348186da47d5ac46238926d050d52a8d249a4095d28c92a8df238d1553de0ce4c6b447bec85321f9728d70d7026193524a29a594524a29e5d6f7ced4df4c3f330ebdb4459e52cac9eeed0c9e6419c3cccdda947e570badd22a422ecf2a425b45b8e52a426bab08b52ac29a671521cd538bf164ab083b4f22e1fc58caf2b68a70665b4528f30ce58b3ca5944a293bcbaad9f06432a90542383f7ed9a395d6fa5a6b78bf32042d4bf9522fc7751d2a0102989e14eb2e2c5884521605501e5351f8c8e3952a21ec651ea2796eb8877466b3bfe20e24686eec7bee0dc7e15b8352230490a5c43faa6aaf81adb62aed2f802e59d233a47cbd942a8985d85eb102e4cd06f30319143d8200591d84520645910c0a20191444b2204164012417520099681e326c01480b27aa48620b60380289892ff84491021cfc30b204211f2eb4607221b38114400b85943333555e652f77f4dc9b7bee1b1234379b66b110db651e22bcb9d66af8e7f2e42b6ea2388940b1b8c13c4e0ec2befc38e51592d98087ac063f960adb03590d66508318d828e61764358081ac063e8ee0d91c5cd484e4cbc41ec912219437e59635897cc181ac063db2a0225b84d99552ca7a5a44e22b3f1b04ed66f991524aa77ca9a7303c99d099b29f0582945286db776f18ca53ecd1498d10ced75396f7b35a4829ebe5b81eaf6a76bbdc9547c619a47b86a890ca238966b7bb8df2c80cd23d3d4485541e9addec16a47b86a810ab8df24890ee19aa5ad582744fa535488ba33c628510cecbee6e929452decd72dc08cb8d6b9279659e9435b30960a79002264890203041412c4149809ce109205dd4000819ba06a32c654094004162032020469ec0821338983f4f6061ed8fec092064269860e979b725422a854fd8504821961682684fd80046f644134234d8e247176a98b98c2167eb863cab9dc1c6c520fcb2943df1020b83275080c33f8104484fa9304c0109a1219df9c32da49a85f5b392f4e7267362286f5b98fa09425b64b656066198a5cc8999134434ad092d9a18b241f182a905cd6aad699aa6316184892d424dd3344dd3b4ae439235eda92b644dd334ba44ea8841cf0a66c0052514010a21e082065480996c095a20021021255b6822886d0207a32dee9c5589267a38ae0531f821410f27dc800754985a604289c64417401738a105b60530b21f53c86600049b022ef40a643faac0d915c87e14c9374bd98f21560556052c3e64c0e3e3239360469b2c4fa486f604f7decda220ecb294cd40680642688bbcb2257090b52c654b40d14508b3474ab5b5d6f208adede91699b9cb9eb9598247b77061f6b1040dbe1264c104242001097c7ab294c560481eab8f4c2fb3c85216039e0c831710f9545953b7bbb14a08fb1f6b6f718c014452daed47d68db1f2c874629510db7f36ac12c203319e1bfa188e4d1aeea33cb2d51edd4a12d371e35ddedc8fb2280bfd4c21d3870f21403eba0e074d7c816691d7e0cf249ab34c3f6793680ecdd93d12f8e6e2a00e427f1a684768f18e1b9b373b822ed03d405ca08fe942286f2e700320f0f0f0c0b8b14702df581cd4d85ec331edd6bbbd03c06f1fa2bbc531fbce7b7707783847cf8400710bf5500ff5cc7b0eeedd1563f7aaf6b87b7740f7ed4368f770cc36118f77213adc44355a23d22ea63c78badfe7e07274bf1f298f1c0bf2ae5deef70ee8ee5d9500edf74368bfda1b0f71efe1d8f67beb009f1c34086da1ffee800e539fbb9dbb66354c8582d8e7081ac2bbf61c5d0eefdabffea65dd5ddb53bc0fba77d08ee1a8e05f5637608ed1f8e6db2c3b31c3b437898ce680bbdd6611e7b6ea43321ec39910ed116fa4da44462b522114fe5c9f43162085d7289bc9937315e08fb9428d3c3000644f98af3666bfca39a3c371ab038e8a6723aba4943f064cb5ea005ab699ad5344dfba9355296b2173c2152c6830bc5160592942784854a68099e9012b888250a28454e7080a24dfc30d12676b00270073de8d6848c0753f02008de12644478f0231f268b24b9cfca62282677df236d42c2510ad5d8c100ff0624ac97da65a14276d528bd1b15e17cd3296c4f6c414e6c4dd04d8a509ec6a55b309f315fb3beb0de1c86423bd881050b3628b62058a4000b136c4e60c143868508805880608080369f255b1214d915b3d4d6822b760002da3a905dd123d301914c07486c32681e19163cdbc6021859caae88c1152ba0354f29bf178452d3c65a6bfd266a17c797e7646d30a8524a2965e39e092525c3a6c4e6821fa250b31f354dd3b69fb0e9bc1fe7c7eeb0c26c3e58361f3061b06288cc0a215618915961054a69ad561459f185253cd91e0cd1bdb9efc5d0645abbb55d7ea719f224ed5a6316967c49358b5e31c6a6c60eddf2c3bdf7621cdd426774ba85dec565b5a2912ff473460ef48d614610fedc8f291899d63d7d0ccd00606ce68cfe8c4cbf5d8c83022f5656b266febf978b3314d149f39c93369dd32ea13306a02dfd7bc330952202c384f0876b00318426d87824911578b4a701cc206dc89796f207b96fa3035aa594523a2ba5f454d6d42c65be9dabacb1b02dbb260f7863b607b2d75f4bf0003ab2a59fd57a345ba33db5a694524a29a594522089b682a96db359bc9eb3dad98d4755cf877466074abf7b72016fcc37eb6a2c96d5364dcb82e7a7d46b3ca55667f938d6479bf93125b7ccd03eca8442c8177a7108063c8088222880c3089dc962fdb0b047b9d9b3767505316f8f475c79a8e120c843df64bbc965dec23ca656e1e883dd90e5ccc9474904d9846c52436fb7644d21e9f22cdd1a813031b2a6bb3c8d4dcfb0502e6f806ebdb8fc0fb266a5bafc10dd122fcf0059f3cb3fa05b2b322e5f84aca181a545cac819dae58190334e52ae72f906c819a7d4615c5e027286097ee984193f0635c172f3be164bdf44d3af08bbf7dac951af263f99ee7d5fcfcc430df7ba6f6e58880ffc1250a790e92320b990e92d2073a03f348b82fd99b51c1e1adb9079be866e0b0619348852beb0d4c7c0a2942f53fc4a85910ac38b9528e58b4a2525b5b14414cdb60d83d79d439d88da0f52be7c2731013287170e8ff20899be7628924493f843fd014b233636105831255fe843717516112646bed073224b9cf429f5864cdf2273a0d76632bd8ccc81fea2c817fa139903ed1fe85d5c585856324f7c922ff49b68ca332441c83a8a9c0942ce193fcc1ce8e951b20601f285dec5a5861a56565050249131ec812e219cf9a7e7372cfc43b7d0373640b3e8684e3cd64f03411fb437dec49bad28adc5c13c3434ca13886c7321e9f22959f379adee29aa2c7f1b732cda3c90a4b6088d14c9b2f10edda7cac2323195cebd90b01513cc1a6f18e29195bae2cc616e5175a3cf9d03c2bef110cda20cb02f9db07dcc21a9b0c835126e8184070b640ef4a138799ab563f64c1eb3c7f4215f7c9af583083a3381688b1d12827bf4f4993fc63088f829fef4b06e4a9f3cba753f795cae609953ac5c5ac8906ea11f5793878fe9821cc6c9824c671249843fa5cf14489b1e960a4aa79f3eaa38ca930513062ee82bba8572b985348bf20847494448a60742ce80dd20640dec075933dfb7625f13470d86600b01cb6c6a6badb5fecc786f7dcd126bb7348bf5a7ba69adb5e22a4e2c9108a7f7da5f952708e7ed0feec3d453620c8d4d0d3a14debca3031ec872c6cc2397afc671f738f5e3c5b02d8f9da78d39ce5bee9e8af357b421e5cbb89d204f100152bad84bdb23edbd235b3106df0c0313d3333892c024814902930426090c052afef13ee3e2c2c2b24aa2d32d7d79cd4a49cfc919334b0fe3a080cf95303d718d3612f66fb3ba7ea74c7b28034d17617f629ac6443f3c5a05590e9498737603e56006390742344dd3ac95e560882c0758a86ed031566de0c926eaee9ed9a15bfa344dd334928bf0a77e5eabe7e40c2ef728f7ef472bb6a9d134269834accdcc81868686864607d9d297cd651bf94243698e10de6649220d0a6f5b81ed6ddbb6ed72b709f3ce39ef762fc7ed9ec295cb90b0de7befadf7823666de4eed66cbc0aad2e5521a532435241c2fab0c236be81261f2507b4a856118ae4ea966751886a1b5d65a92b59b952452ee53cffcf09dc6300c3319c299491b162ca5dd6aadbbbbe99535dcdc91a7e8832ce2e1e1c9e3113c3c3cdad4e6265fdae29c3ae7040fa0a3e24dbef4a6d5a0ba20055e257de1ec371efb8d7168bd316dd87a1b5a9532d87eefe9cc56ecec6d5fadb5d6d36a43f3b459e766ebedb479b3ecd69535579c6f0bfa70cf7d7e629ceddca5a4a774dae0b0bc8eecddcf87ed9748c886b6dea3dff6cf8e219c79dc72ff5ad58d2ddbf969af8d0dcbebc8d66a376f423ab02ca7afb6265f5c9ad52e303134cdb2e916232f9292590134c11e66d66ecd9a586fc59b7d50ddb0afb79fd774e41a0d041840e00a629eaae86158ac77dfdc5b07c2f9054fb28cf3ebd63ccc0c2d820238423ae3ddc3ac700e115144cf78a740ee14e115a921f7477bf4dbc4ce9aa5b1016fd49686b78ffef66d9a554304617fa4a1c1353aae1a80d24984882f843fdea90426e09dbe0859d3a7af809cc1653aa280ac19657a1c73469f6621d36b3d70f8a7e737de6b349d3ec4ad0421a5524998330dadd1ad7a6db578b4b66edb666fa36fb1adf9a6a0aa6e609cdc33bc2197a7e8323b37a7cddccbaf66b6cb1427c2d0161a9b6ed9c100daad5dabe8c27205d19f9759087ae46bd6c4acad27a41308593f8190746a3dd8b851af5dc3383af2506deb03590e92c831b29455b1237bfd75cbbe7e44e1b8816c3f6ab4d29e365ef28dda3f854ac27af0869cddf0f27db96c3cdbdbe0660f2fd9e22264d75cf2e53b4220db2b205b2ce50b85c165a56fd006d81cf064b768ef548dcec9812dd0ed6a5f17c2e6f2d878cc809409294396201037f7fcd818e7b3f1b8813cafc572bce8c0aa9e798a3352e86ef245035bd4f2dd7ae29526a6422f84fdd193522684284f0c7c8ada5b54f5651e756872520f8c0943e8e57929abe2e71a0fb4eda3bd9ff6bae75ed6b5c3b389b0306b38a65930b4a5c6348b368b6ab626d73af303ac148e84342f2b00f9420f0099037d4c58a7ac81dd3c67c0c25c4fe94ff4230c65692bda90d96e9806260aa114ca36cda2a76916bd26c66821d47abc298570be4a94a792276530ab2416120115320e54ca9313955161848a2064294db294512184a620a9a92c65549841bb29b0f6059b36830b241322a42b6529134284e338aef33e2aca2913322413b2842c5b0b8227dbca1a15cc66927cd17e4f806c3f2f1ec917f054d61020dbeef32338721fc1ac5de25430881cd9a323f07ea3be60df8f7a6257c50ee370db862f40b34e8f80f366155ff539f2e572e2786f2a6d1dd7711dd7e1f17278bc77e32e773f56ce0a5d77cfebba779d77cf89aa8bb9bb26c6a95ef7d7e53670c471f776df94a477e2982377e36bbbdce5c2b181e8dccd73223d89e3a1c33820368266ef7a783c0e9a390ceb7c715cddb97bf55e3cdee3d864d7cc1da6b2cc1d87dbc917dbe46e129066ff81b03a7ab96c3afb71a4eeeea7e4c6de77f023b7853087e6ef328fdf476ec3630e9aa74d86d93cfad82f174cd6a9f91e563369ce111e691e65167974511a5d20401e5df30602c8a3cb66d8cd38f629d96258bfcc4a5f451c572c7397791b378cf361236827ba68e62ef3bd00cd1bd6e9dcd41ed1023393c4b9248fc4f1a0384aa10f24924244b95e650479e4fa52f72885461c72a848387e423e5b37bfa10cf2803e99e25167284f399447985964ce8c18e7111d3b799c4956cd9a494d2242750649754bd7da2dfd0d657969adb24a794733529f8c78789443249122331d4676b2d6b8468d6609658a47297416960b4c0c8d8d8d4d4c0c0c8c8b0b8bc5c27270bb5cf7fe29b5eafedaebaeb9be2dca7af9b1e6ae315b08e55096b97578b33ec1932c63dd82106aafefee9f52a66fb75aad45dfbdbb01ba35dffd07218660c003ba65c2e32ac424ee233c9e40ee1ff6b84bc97dc3f7c57d9442a35feff327f013f579fa57ba47ba04bd5f91b664eb6b8d5a61cbd43a79771b141e5779fcc9099bee4b783c857774bf2bdf99bc746ffbc0f0d224e528279d7c643a18febb9bc9bf16d822b54aadd3bbd4bbaf54db53f0b84aa160d4e994bb9f4c780c73f7d2f7e5eea411fef0abe6ee2afbed9ed8c557b880f142c92a0692211b9a18181716cbbbf0b8f894804858582e303134362dd3a9de32dd41fa518f0ed9d078312b30305c9a86ea05ab69a858de34301ed1212dd3c91b5aa465ba96f9a811ba45cb7423bc85e8ddc8ca07a3c80b70356424d432ddaa5b238c334a8d4ee1d7346e95a32bc4295680bc0869bd5f784aada84fcb749f14a41fa5d427d5d1e6a13c9487f2509edcddebe2d55cbc5ac9ab91f450b3babf4efe3afd85facbf417ca5fa5bf529eba047930d122ec2ebaf5bdb95801df4a9a86ea851cbd91340d8ce7152dd34d212dd3cd295aa69b415aa69b405aa69b402dd3cd1f2dd30d092f6fba88bc6923bdc5f4e91e0a87eee54d88c7abbd7de88cbcb93edd53f08feadd7b47b752f827460b05ffacdebd7b740b857f5ebc3bc138de7f6262f3e01f182f6241de53f0cf0b1c8ba52ebb55c23fab185e1018340a2205854125251f175e17b12053d029e8e4730849cbb40cea28293ca9e641c13c72689c1385c7dbbdbc7ff7a6103a930a426742203a73a78f3695e8168857239cc2a710874974ab843f13be275c4fb0ec7eea6e12674fb3ba97c49944b3ba87e2e4d1acee2471f66856f791387d34ab3b284e259a553f4e1f4e54a95457ada8543054aa17315631700c4cbb00291723aaa465ba1509e788512472256fe48dbc91374116e7a0432dd3bdfbdca25b3f31fc9edffcdde791a6f158907df769a469ace0ee73d63460e09e17691a2f70f749a469a81e53bdfb1cd234563816539d460c1c536195c538472c962376448e98ce0ace113322470cc70b9c23468196e972c48a68994e358448919991232db345cb743807112dd37d0a755a84dcb56f3f08cf9d0ed1197943c2e31d610ae2a1dc7da59b1e9e7413f1957295a78e72d44f7eba49d7755dd7755dd7751d11dd5077959494789bc51d45fc9ac571dc4f62aa59dc4dc455b3b89bc49228deaf59da4762781253ab66695dd7755dd775975dd775972c1dc6a9a56e49c1939fe7c72944440221fc4624ec6f5a84dac703211ca78f1c1af2199a43524868484e1e211f9e4d8bd09e3ed62d9ced3fb1532c687b771d53c93b0e7bd934401c8b81ff5e44d318e118787b229ac6098e8158b59d708ed8ca643bce113b95ee635fcbd8c764cb70230b524a29a514e7902d636fbffd20ac1f1f6ab79f43434343424242423e3e3e3c93e7c3e3f56a58a19b1b7278bc17a778b6be55f0563fb12e150beaff7429a614d38a6331eae118c5aac60a90371e5821ca115be588a572c44e3962618ed897237673d4fb85a7d4ea2687e426e5c0683b292c5ddef4fca67b7753890b499f47abdc38add6969952defb7d61783aa5562dd3e1a442d47adf46ef4aff489737a887240dfcbacd5279236f64a3e8c8eb3aadc278b14a39a1a8a870787169a12165c30d3503a09189a9a13583a2230f85bac935a8e7116064c3a231d2a184a25db22394e78db812a7695a7753dac3a6f1607b0754693412bdd0abb80028aa69dd4795b8d1ada352b775b86add303407146a2b9146e0a84d6e8c92a5a8d2664b288e725cdd6cacd48f99cec900c0fd6aa3fa1a3de14efa1abe00f8385a7a8c7ec4dd3b6bc66b10c05338c63a0a8ea57ed218857750473d76b2b2f569e9a8c63ba59700f058005e1f93f17ecc0493034b0c136e7454e9a3d147a731f0393c06f3188fb1dce4b11e78d8a10031efa8d2bdd13defdef65877f131fcf0b1ef3dbfb9c9357498718f2afd9ec3201efd7abff7f62b8ffde063dc7b7e5333009a1900600160eda8c70280774ad79e038ec1e0d1b56fb8f3aed97bcdc6b6778fd958c52c8c7a4c06de29bd3e068eb1e09dd1eb451cc378c77bfd0a5eb91bd65e6f861bfa58fdf658e314eea3622778a784ab098e99f0ce08df96c1240f7f20fef0cec561cb4c0eef68f8d432d3e29edf687d0fecf45b7e8787c942054fd67aaff6711fd108699468a8e6ed69a82616c2e4f2e63d3731edd8e1b989e9b8e9f94d09dc7278602eb9c961040f0f0f07ead5b86e04765d373a81262612380a4b28d48b952a8542495181018306961887b1226219325e5c6e60c9a8a185b3c1eb4ebc8dfb380d070f87da75323102f0340d2607003c1600aeb394fb4eb45bbfd6d6c2d55602dce633b68fa6354307706bb4cf8bd1dbc762f5b17bfbfa187dcce28a29ae9f57e33ad07c6fb4027c87f3e071b1eff43eb6c5eae9b7c7bec7680f8fc562b1582c56dff39b135a2da5d6528dda4bf14eb57807f7fca607bc233f1e7628c04dae4183860e3468d0a041a312c06646cd00685aad9956abd56a5d9918010400003038e090030e38e080030edf8bcb0d36b4b064c8a841860c1932648434b0c4c0e261c058810103060c18a793f7fce6c54aa59292c23194cfeb38d4b6a14eb6d4f69edf9c4c4ca5908463e0e8c3f2033d5cbdafc3b7f338fc719d86c39dfa8b4f2dd3dff04ebdc5ab96e9ef54bc6a99798a532dd397dfd961d690852725ca93ddf535a8a7d9b69d1b8fb5c672bbe8b4c2939779943edfb2d801cc0e7ae0334488ac3dd08320574836e404b966291b32050d9e279e3ddd01700890213cea674e78db157d65cb3ccb3887f28a6644d3344df30edbb27d4e8e3d6ce61c8b736a35526bad15e7e49c5efac973727272c2d1bbd6ebace4fa1c6badb53627c7e4a6a360336b46344dd3b49c1cd2bf73da737260336bcfb938a73b78ed1236b3919cb9050acf2327781ab138e78473ec4df014da70ce9c358bde84734a780e9944745256b2f61c1d1859c33961bdf6099b791a9973ce89e715233ca70071ce87a70f9e3f343c73605bae7f4e3d6ce68aa78f4e9c40824c22b9e297d5fa38b6dfbfaed58e637bff958363be9f83a3fb7d0e0eeef638b66bcfc131e7b50ebbea1226e81992b5e7e0e0b0ab4dd0336409d71143963041cfbcaed933640913640d5795982d84924896b947b772ea7974129c1138ba55714ea540b7349ca37d3e873ba2569d948e96b3fd9e7ef2d0c7b40710515b39ff61b3d9b66ddbe8bdf7de8b398ee3388ec31cc75d2795b953fcd299b90f9b9dfb2eca8222559022c33a377ee9d4dccdea564e77cfc33938e7fe0befaa5b398d6fbde2779a274bd47a6fdb344dbbe3f6bb6d9be679976e74dbf078dfef1ad465ef689fa323f7b8ddbe7ebbdad5b4eddb66bfddbbddfab1d6b0539a13a42b08fad6ea274e5f0c423bd55a0b42e5033dfd973dfa519c8953e7d551678f618342d364434290354dd39c306529e381188e4828d8a0074338c3073c8083263407b2a8e26691c597850dba2c98e0b250419845cf48a88bcf2407a26cd6fd26dadae2c4305eac6851116bf51777818949b15ce52a1aae7a0d385c060de257a953f8ddca92aaabfc292914d4c989061935b05a6cb8c1e5058717971b6c6861d5208306961858fc0a8c172b954a4a0a0575723ac2a4c854542a0a8598cd662c164bbaccb003189632ca235d58ec22c1541ed0ac2334dcad442ac6858f945112f550d151c283054c42c3d12c1d7a56b4d1dcc1616dc3234c25379eb88866d15a3285f6db0d777978557f7e7569fa8bcb6ec1b83cfd1215c3e5068c8f22fe70721257a28d788af9ee6645396d105b44d92c19220d22cb5442b41d99df8eb0524fb9cac3abf0e8a27ae92b3cc2ac6efa0b3cc6bcb8c961e09106868d148ff218d88663f12b305e88a1f8ddca922847fde4a79bdcf492188a97af38c6c959504e43ca65a85ec38bb35a64b36cc02ccd62d520830616f1bb55b260bc58a9e0141e6d50f884c7980cc300981b9ec7864942829c1fefe8c9cbf99dab5a173b62ce15d78809a9e330c947ac90f0612a241a0e53c995e545871558ca8a4afe379056483015529571984a8f2cbf72f9ecd1acd661a51e96b27257f229152e7491c01a0e53c927a794cf249ac5ddb5f2e2210e87a564f0f212a6926129f9c3234c85759d996d384c258fb0cecc2d1fe78e2cffb948e2612ad9c3e30f4bc95dea2b9f3bf0278dd8796b82b5a19fe8f00d75144a94718cb3a456f008fe3bbeecd6572ebb25e2d1e4a3ffb25b38e091bb76f1b25b29783cf949c5058f28475dc5e5b25b2f7864c13fc4c0371c45dc6165738af95caa77356dca4b93633cba8c7efa0a1e61567ef2e331e6475dc4234d96c74f3d05c778ca5530cb55ee826fc036884334abdf220ad1ac3e4bac419421e2a081458c21aeb09812c5d3c57045fc6e95305e882bef2aa26c568a984241d1c86699cc69c2e32de1bebdbdccd00742f2288b8ab8e0828848899224499020191a9a42346bbebbf7effdd1053cfd08337afd18430a6f3fdae850faf6510aad98fc7e94437438673a999442d208fce67fc54d13ab2847fad3a8fde4f21fea921bc1a78ca4ab5c96ae1a4dbeba6435eb2b91a5596f9698124fcd9a471151e28978eb7c098fa614b2a18981d1a19ad6c7b3972c63fb6c971f65110bcbbf5aa5522b2795f086f7bb29b9e2e0e8b06409137a806d7945beccbb669e459b128aaee091a576b2d6c45a9555c2defae0ba733d3cf0e3778f0788c7d1c12448b8f4313ca9844f3e9a5e3a3999603ca65ce523ca531f4f8efa68f2130f735604231cc1081292a084b9042634610b273c010a5190c2149050a10a56902ff4f30a58c882122d6c810bf2a59510c252baa8b388aa94b0bf3eb8773dbc7f3cc04e42a53a0ee9e1fbdda3521da7d43b545aa54cc8382af8a6e0c993c21f0a9e3b50389c3d277cc23309933879a4668fa984c79a3f2c0f8f3c22910004349b4d21cf8a6640b359d1ac0868cec639e7049a33a0a2a2a2a2a2d96c369b0101010149987ce4c81198dc87e169d68e247afcf0a359fdc154b26b05874986a564174a1f63d17ac952eb755eb5cb95a61d47b3b4eea78ec3a30e29f9e27165c99233e411a6922d1e7558b264099901cdea3fa059fd229ad59746b022491ee5119eed42746b1ad902c9cd2895e46f4908e7373c79ba19d0f7c891f6c932860e95d902039f2372369bcd66b3d96c369bcd66b3d96c369bcd66b3d96c369bcd66b3d96c369bcd66b323720a1909b3a2a2a2a2a2a222393b12f637241c515454d417a267ac66b146d64f8eacba290aad94c6f889c9f538fa1dd331bd8978418f53f98e6a3512b79b944827d0e3beef8c52e752606829934a25e53bdfe9050c4f4399c2d177bfd39dbe78f1d88e868356c0549b542a5f4aea3bf7f4c50aa5e2d88e89ca4ba49bd25058beb33a3d3179eceb0e7a8fed682b1abe6322a9585462fc043eb69322dec3f8f6d88e3d4a7f670785831a7f5fcb340df8e2da3293055712bea3189805c4e187f13d7cea44bc4adde3145e59ccd232f3da0adea930f0095fc7dd51f56581b73ae5791dbb226b5c72498699f28beff230be2e85946127b9af5355640dacaa640dec6b0e8592e775284ac3c0afe6e59a1996cade75669eb02dcf1a18c9db4ab206764db20616ca1a9849aef1ec3f5897670dcc04be5c2b197692e775b4dc309a1be6bd5c5b86a1724f1898271e6129b93fba5640acf296bc5c34c35279c246b9f10853c9f3a3cabbcc128fae95ab3c0ca4e48ebb9bd52ac5231129b9f168040f0f07328e6b2ec9381850c9138f44f0f0a020cb7abff0945a9d25af2c59a2852cafe39b36882769bd2bc5c3c393fbf57ae98cf276d708952fd7ddb5f28269d9fbeba5e365f02ed2100f4fd631c9305e2f9d9b497fe98439bceba672293573e92f9d2d9bfed2216593bb5628f9f482d17cfa4b47cb277fe98019751789878727eb9c649417ac6694bf746a4efda5f3e594bb56847878b2ce29ab5cc26c56f94ba7b3eac5754cab978e299374bafc82d90c03eb74065f8830565eac542a29f2651e259e8828f265fe24a2e4cbbc8978225fe64d624934912ff3a1682289a59118829fd77177b35aa562eb7831ab12ae1595c3525ca49f1e951b93bb4829ae150facec98dcf4a4dc985c9ec564e68df41def61974ca9c77682b687df219dd47291543ecd7bc984f29defa9cba7bc7a9392e9f4d80e0a0eea77df39394acb455201e9773ab9f79df0e05d2b23d5633b9f0dd2e93c5f323db6f39de020eda3ef80f75ca4254b96e41f9514951b148eed98a0782741386464fa1dd2518feda48437e120eeb19dd477144662dea0be333ae9b11dd34d1edb293d0507c5765238681e0523316fc2c77648f71edb018faadff97e82919837a3c7764e137f58b68c0907e9cccce15bc24117d770c3241c64716c67848370c8c81a067150c53b1f0ea2f8849198371d0ec261921bbf59261db7b52c6c45c29619e54b5d47a63fa55ce53253ade2d7eb757294e9a517f8d1bf7b77275b9514f124a2a04e4429de2f0c49e2aa59dd07c5b3441711861363686c9a95a2a9d965f0b620842bde56440acdf112076f23b2fd60f6744bf711ddd246e0685617d12d72878e699866f5b38e712706791e4892fc72dd9d212274f8d09e9e9949ba65660e75cb113d338f74cbcc9ce1e8d62cd2ac9e99431ed033f38a39c50f3d338174cfcc1eddd293c7cc4208a511a600ca2fd78e10a783e7c5b96ad6e90ce3b06bcb77ac0143777c3671bc85e121855a76b79c486641b297a58c084746b35c931c199a1de996fa197056c46648cc15dd52c129baa502e9960afee8963a032ad18347b348f74251663049cf8c880cf5cc48a85b8ef4cc4848b718e9d6688a66cdba350ad2ac0ad433a39e20e014a010f00a50081c0212018b748bfaf4cc88c747cf8045ddc2a36740a26ea9afdebf8f20d10848b72856d19b8e33ff934365c32afaed3f2638160b9ab736a569281dfe3131e1b08a9efb8fc9e93193fb9f93c9eb4714bb662ebdffa3c23113ac9a5801f24605c7824c78042465c323a094c5a31f281a1ef9a03a3c5222472c88c3231fcdaa41178f7a34ab1ee7086a3c9237f51bca8d4741a6107285d0102245bab5c516478e6c468cd8d94c2b52a42342841b32c4fba87ed463e463a4c4c867f4a35b40dd32bd7e04c4c6c64443b3c5c4581818cdc5a563b138963c3fb2e41124fa0e72516bd1bd6017dfc713863b4ea79e546a94c4b8ca2011fd1cc1d13533c52fd7a8c355c23814c3b41c1df2c4aff93b45d7924cc22f57671d12e945afd3d935e71932e97349a6a2a437ebd01bd30cfd9a778559a72ec9d3c6ec2293a6e87ad6d132ccb5650aa399ce3264d249e2a883072334d283108e3e823cc2500ca2a0a8e48a5a6a7b983a45230020002000e315003030181009c482d1284ce238d90714800d8ea64660521888c324865118658c210a0002880100c0108099995255a1ddb2039b943e0405eea5f44434f1fd11e015228979692bab40c017a25ae0cb7fa0c8001a1ee234f8f26a20c735409aae0df3d557432e32b92793ca73058aa72c21ae36fcc20edcfcb732c4412d2a9b6b1d60f9e2a60fa0bafd4a6c4a4bda9082407a0a224f29d0965230dfd67cb2fff5995c732b1b5c62f0b2c199b156ebc40223e8ecdfc58e4e4d30c5362a700cf0ac216760680eba60cbca93f70087fc6c58e4fc4e457f16ea077cbd75da136e233fad461aa7f819971f8ebf642479e18020d1e298116ef473305438a228af2e75cae48b017c57019159fa77c2de9063047128a04fc88718738e2a8a7e0b46d3d6972f8a403808f8f1bdfb4f6440ee3a6ad2eb8c28041478fb8d369b771bc6e67dcb3a578852ef3bc5d1b33ad2fd12456f3c5853c7dfcd470effa8c175882b5d3c1509fdcb4685f50c55a277dd1f1dbe060fa6884139f66d7952e8da0716e177b52a527a81c00a8a84a32dfc0f8077acd4ab15c1c2497bf46aae55731e0bac191b2804700aea303088e2940ad5219efffd77c6ccd310c75d3bae952a6676a55c87bd64d426c8ebfabe078fbdf2a7884bbd18d62746b0eaca3be9a74eeda269e18488aa992121ad1deca8883fea51b3e7c72c6b1b3a2c1e97383e7ddaa05e6788093725f2d132383a081c4b66fb6bae338e8d80b2a3fcb03e99f8b4aaec3e191167dedf1071ce5b88c4fefec057e41b49bb49838c88f252c022f870a637c74aa77ed949e8ab89f88cee53eccf67604508fa35c48cc29d20e1f5bb0d20ff0980ccbf6253662b6afe83bd7cea5047b693d8cac3d94ed08a683b79bff86eee59a289a82deeb98c20c9122359e4f5291cf3c3c4bef2b74fd03e79e500109e325b28b6605620c659562871847d695be70c256d47698384fbc459b1a49e201222396545d510b63ab0b68f97668c37d0c66b2a42ab1f678384e01f391f344a43ef6503d8f87f8fc9db203d9b88355d26ba155a1846347911ca5f41268d46cb2ea2d7a128fb7aef9b4bc0d59f66f5fb626f6041bc54cf340ebe05170fca87a414a23ababd0466b0fe01737b037a6c2d36c425bf62652e433995bdc57226e5856b3331be8fab0890070bb019c99a4ca13113c3c8cdc394a860651092e6d4e9d517f3a5ca147532fe9db2621f5faa58f0ed117527f83dacb03417c4095039016690679fbeb66cc0def1c3855b9ee12f94e8236f0a2e7ba1efd19c59ed99508359c8d9a1b2c46f53c6e27e47e9732cdf914f8b3fbac5f13db1548ee825d8047dc13cb51660709306ac566aac2e3232de161355a737d96561951d38c4c9ec7d1b4d7d99e03da086c43c4364700bc19b461766e76309c49efc4acba9472228927a085df0eb8aa822d63a2fe4b1f43f26948c76d73f4f640c10ba0ab6ea98bee58c20a510a16a5dbc050d03615afc934c01a817d331374f3d9a746668c33b7238b7990b545970f0b029e392931c099eb1d078297320b375aad63967efe11267a9c06aae63a80f0d72b79c5ed63c95f0dcb36860d8f022c2eab847106d685f946b308e361effb9e9ef2a42f9d4c4dcfb1560dcf7fd9b8223b9e31d7afcece764a27a44086aca13113ea580e9a02b695997c3d9d0496862b154945c6b8adcc44dfc8ae1782883b15da1aa902b3c4f8750792b8e8a41b5224174561c4a35a18a15d3374e5ce7559c310d44a18c542b136b33f8a50a05ead5775e1789dac369eea5bade939312ca0d3ec56c09672121be24564245b8442788ea0ef08588d823877cb339a6f443c33dba743bcb161f8ab4d0852401ac3a3131da16b79d01495a189b25328283c3ac8ead6b00ad729f402d86a353d3db4f0519259ac9410bee464f5d0e9cc70ba19d857d9e03e44daa7528dedb3ef04034a979465cc66f718020e0d7db32660dae91d5444b0117158cfdcda16d4761dad6851992eeae4f498b6c56586d04703f0c289788211c843586de53623e78457a3d9fcfa661839fddd6a60be1986915dc5e6f50df9165bd9e2ecd64ee05ea1ab1881b218c10156ea7064e8cd8c04266ca614506584ae9b3e7fcb44105267b4fd0c6e0dea02a88d4b0ff941954d5aecae6b0820f73fbfd919f926a920eaf6ee96e8e208693ace00abcaee4830043a8c6409dad9122628fca9f4d0dd0d82ddc5343cd508cff4e175e6c759a2d325a0b9d878c6d026dd88194945eb9022b0acccc9b823c492d30c4842f1ebd33233735f683525a67b2faca46424e4bc51e41eb93201c0228637dd23032e0797993d6a999fe6a31e370c82fcca833915b68adc5a6df3b424d67b5cc38d0bd631dc36205b89ffc4739fa1226b4d562ac628de21f1ed6d11f3dcf74f3d5bc8329d146a9f93522264a232bbdeb7f46679025a0891faf876a113d1d9c029e0e2f76bd6a59574d6e61b5c105428bea17ae9b365bd5be6c4b811557ecc552d574a93a2016e719a7134bc55173c816b3e9b2a2806f8ab918c54c646338a81373828d30c74fe97d8a12f3b82198eee6fa56ac05fb89e1d95595abc4781d5669f723a5d8b2154452475c6eac369410a4cac788773c48915f73f9ccd06f600e9b0dc287377d77f7e0bb450182311b08ce990237a1c8a6022e2f87506a1a350979497e7a48f87ac2e622edc9800396fb45932416ece75531d868e5ee939482482d64d2a30aa8893f206c6ad81c2eb533997c0d6a6681d2c1cd8e313be08ade140cca85fdc96a7cb0e62fa324f410e0fcbca975ea54adc758f7691e8aa21db6556d588d6592bc0e460e86c35a23f9d747242258b1f0b5d1dd7f45bdb8262d5c9ff48f3e3660ce4a7ec6965694bba36bdf583a62c9e071dd6513468c9ff63dd6345e70fa79a5fa465391e23b9be833fbca49e7cfd6db3714da28e06da650767317879075b5926e26bd7bc6248f7197b124f0647d8ca93a91a217e0824645be6e09f5ec65b49943b119f2e1845a4bbc248322208b7e86b8c70b1c75f80995b31cf8712f053576f8b4760256bdb99f7e6424eb83e28957e71164948ac0f591c41d5daed2ecb92c7103816a094a8e835a5b7c57a0ce3fef839cb3b2ed976987334f22a8440a91db19b4918067e6d0a6a80bacdbb333e861b1fccc037e898dad56dfb6f021dc5019efe8655259cb86b630d5ac25086ca239d2189506a2d39f7dcb0a914ffe65be7c95f8e661d8da159ac595b4b8cda5becdc8efffc76f4719dfdf6de90ecbc4eb29ba015b8e4fb3c3f0ba8533c85340d328882eecb984927d467a98c358a586331d1f8293b066550ecdf53f9b58b2226f41f8c446306db6d8a5c0f93194d1c8a456491e1c8025af2a74782bc84fc42b5be20bfa411dda260ee8bdc4db5bc8f710cd43a86837da9c17cdc7625e4b8ea3e46f1cd030689358a82b1c7844d8f5e104cb60cf7c1a5230f486a650040655e5d28b0e0c2239432c1a8e3c0efc5b9f183ebed8eecb6c18deac16cb70250b7d480c96197cefa183258f70243c96396082812047775057d17de457c1f764f88dc1697cdf7637530618f95ff2e403703e3a5318b382f8c907db2f0c6cab8aff1c324b7ca39280b44d822b56765ec878f619322ee653bc656cab8bbcc93000c09c726de57ceaef44315a2a25264bdc8a861d76248b9bce9c6a73e37978265cdcfd4cd55d2f3a31034c6c6285f44ea6f9116692f1e8390233f4ef53ed42cfa3bd0ff5cf1c8440d7301a02d7b64b625974800ef5707266bf369f3ceffcaa58c214bf1d7ec95f70f2b6dd37da2be7479cd16422701a4c8578f0038260f92f9f75790e50eb8daa60db50956161a9361f08ee1a8aeedaa393a6d54405398de0ef7e975b00535ecb593fc3732c88c0459926f38ce07cfb8299ad5224f60267c84f6df8d2a043dc85b10611a9fb4af6aafba9da1629f8bac6e87e72ba0e75cf68b92a4dcb2fd4f26dc90dd647c96ff90c7aa833c8273b0951d3468d701defe41a2fb094dbb2fb65fc951f2575030aab606f2b8a451286bed9bafa1b322d6410b171d2355d3122d4d058e7e0664bd1cf474b790b8e38346cbc032eef8913b765716bccb38808071596891a006230056ca014ebd8bde8842b70605d93903b35ea5378a69d9d928f9036e74e7fa96971c996895ee857844a168eff8ea53c4a436f66709efb118ede59e0cf6a6d287e03274f6379134433330e3be4fe72092674c986c20b13124651faaf15e911cd331de82a9bb313bbabbea4f9e1dcf03a968da126651f0f40ddd9fa9ccf392ffdde0068deaa7725ec785a4159d586a8535dba730fd0674fcfab444b8d5e1f029cd72f0067affb4d2a0f11d2802e054418e1f1b0ac012a56745aa4de57bb52f3003ce6f1745ffa2b8f2006daa64bf301b505e525ef952dc29599e4ff75d603718b3e41239cbfd93cd05348cc2eeb7178f3fff7069c77811f3cbe93f28db4a6ae12acc71294878a14ff4d91db8a6ba05f4bff9fc7c61e3970c6ebe14bcc6d60f8ac9754627c85b34a41ca04406c56d1d304e98f3fd2df21ce939b482105e16635428b8c8c859415293b7ad9e517cd3f913682129e4b42d3167b4a11b3a5e9a8a559c4917d58094d34c0e6940bea0d502643078258ff0d1067b407f6c42673915bfeef4193dd487a587b47a9c253f7841fc3718ebe5f96a8c0ce79300f1056fbb94d810a148537b1259703bef33f7faa9d6ae9119e2864f875ba0a080b7cf3c9d630290ced3361cdd2447035281aba146987709259c7e194f0d502f8239acde675f8b9e691ec081b74913d701fc1d2f6a4148b2677f6e23ed7e3f5a865c095ab11f152dd67f614aa1ec39211119f6a515816811570f6568d587aeb794f3ea649baf4c73ac4ae5e11d996d1a392f357c30c50634559e7477168e775038fccfebeb2532e878dd742cf304d2b6c1029ab85f6b090c7106eb45550b1c9403da07eff03c0c094b1ab55c8a356673c04cef8d4b5a74ca51235a366159c0b56a6c933c015a691b32438b5c41c7a7e06654bd6417dd71a22bc9bd4ffc067d97ce8e30031942d571bf153676cf1fb7c8ff67b0b687c4a0b504f4c6575d8744a4d8f83a689dc11bd646dd2fb5dbc22507db39bb95504d8ead3f97e867d6b821355a9743188eceb5b6af75c22f3c6b6caf5aebc0d1def30f59cf9cd1a2e8c306e047435fce4fb9bd7b2856b7bc524b4d7c5eb4a6d286e4a6bc12c542b5c0eeffe4d0411f08dd8edd0b91f6667f14f5cada14d944067e923d2da84bc06f71dbc9cfc9f1e727f4691d28becbe8821d0bb2534f31c2d8c4773e200340b77f4745ec19a1c5779ef009d8b3de3941f8f38db5a081bc3d65516cb5758f70334f29bf4432816406295c249094a5e387da5fe38172028aefffea4fd4f5b8af0bf09e3499413d60a0f3cee9ddf9e4bc4a60244dbeff17f25961105071027330d942db92887d0011eaa6887c03240402c29790a4c62a0b9dfda4f2f194fe9341a5ca673061cee50b6c6cb2559f01189087fe8959fe1d8310ccb1b126163818d64386500828b63d48302fadc9341eca6d4b1e26b69a802985c99dd5c6cbc76f7c5122eba243acecfe865c7e076ea50ff0bb409886ee6d3294f4301dd1718c354c622e9d7af20550baf7b0794a433e562e079e48018354031b9b54322c5c3119a8af9886ffc3ba92c688a58e07aee3884d9e13157225a73282de714e1a0383c0983b8727686d5c997228d4a37230232c728a2aec94026808cb842fff9e3ec306973ebe70fec47bd23b8f4e8f8482481f900bd3cfb40460a42a46d9fd10a9d3587ab038764c37a9aabfa0542ce6493d30670290ac74173adaedec52236860ea75b04f19ff7de9fdbf67b6c40d3fcee5fc506009e45bbd16ea59bf02bb240c77c4dc5926900187901626a2e9b825579e02a6b20040b1d7cd67606d3a12f64c6ae90b4cb32d1918032133e83bc79da1fe0c910afb950ceef42c4a44d3ad0da166059282cb743ac5e9dde6c2e3bf3ae8f187e526b3559752c2f59506b6584dbd24051867464289034c6d464ac2f696fc35607cd1277386e3b926e859ce91b43a07c210c66f887db2900e2c2023d70b25601b91b1a4272592475dcb8dadeddea4c0e7bf30641e8ab4180efe7d1e6abbab62c571ce1a760c9e7d1298b60f340c107f008b0e6f0b50bb9d4e4c2d0362eb56376ed7d618435718a28340d87baec7337144884c103aa1689780d0c0b05ba74e93082db8aeaaee2ff652bda99c166c7401b69d0c6077565cf405a14cd1368673dd2a23bceac6ef19c4eaec694965e2f4d7a05adb95f41fa329c8b23b4e69832e9ddf7810c3511444cdd5a049d531c82cd50e17fa63d501a5e500610a5696fa7e6310733929be91bb80047f45a540f055baf6be907485d85d9a5d989862cab4b201cb4d8463a66ab44839501e663b0a5097c3513bc0b83f28a035be4bf288a22ea34d2deefff5d10ee42c0bd5f1fa5de5e75abd547847b54e771f1d994e5b2426c9aff11ef32352580db5af90d7df80983bcad2acba8865ab22af8dd04e6f610657a88370febc796f465aae4bbb726af98943e49693bb8fef1012ca20963987a45c024b8fa042af8ad82835addd184ad51624c4142e8a7948b326dbe170e09c523ccfd412e8f4e80318c5fb1258328c520a20eae99a51001a6bf889811e9a19c105756cd49d491be4ed304fa4ce4a64fc4e61a45f84c08c2e0954329788983344c950777b90e67f5a36ecd36d03575151408882e0294144b77c8aac843d5f1987b1ebd12ccf7b8f00bef76c50340de801a50757ae630356d142a04644361244a85ea830dedf697990aa74b8cd977059b3e56dfc0b39746f3a220cd8870a30a033a8b688eba0b33bd419f4fcc7f6316fa7842c61e8f2ed185b90247d7620b31549fef29bb28c2d41c924d4488331ae8f1cb4f82c660330d62f0776566fd155c554e01dda60e091a6558ce84f4661a46f7ce19e0a394d0a3b8949aad7062c5dede26c5c2c1e454085463fc978ab80ac17c54be43440b8d5b0736a426ef78342d535da4110504c6bc64c5dfa7486c6fa4cf5a548650335a3a0e4a3a2f21baf4ae42185b14cd0c8016b29ce63b9d2a2b5b2b6a21778c1625639e22f83cec65b324ac9c8251d0399c690d8d8f121562ca35494087aefc0366d12c59faa470904bb10cacd198db8e5d0c590949e5a602b136e3fe3a2db7959dec40181f63fed4231c151c8eefd2d81fb87db84d413d4b7e405ef79de1c716f311ae0dcfa33c3094fa037aa2be200a96791632b579e0e828e19f9f232604755ab8e88e9f07e81c9b3a663ba70a572295d026f6ad27603a2347f404d420994a63dd4cf20c7e97bb210453b3c0f5b4569a5150e0fa891c306c8c5aff31226121bb0b3e0c28b3eaabe5f5d8801465f9eed30d12292f9889e34d96b3f4cd6ead425322ea55f728eabbeae7495bfbfb2efcb8cafb648544b82eaae2bf8b4d7551fc773fed5c74a320638630bb39d4e30ee3010a270b3795572cc534a195a9ed4bb04b012d0fd87945ab41064c8af45b4b5b133a7cfb95d1338d0176b897355a5de286ec19b2113612bb1c0c673b1fd43aa345a573f906ce6a33bc804dc84e2afa241a14b8bd451443ec03f148a87021b32daf5a692c55e0164889e0351e0c8539245733a3dbf312654ad59fffc6eca78eb97dca327c2df7cc4cf4bb906e92b246af7a937b1d8094896c8b1313a5789884410605c3c52daf571d52c1e3116f25de1ddc6b8f3dc75c2ed502ab24628f7192952801ea0617be8e9548b6dd7327a624c77c106e59a19bdf6186a0770cea25d26d4d03be3f6229e919221823ec61a76ecb86b3c1ec608ce0b9c32cb609046b8597991101aff0f36c6c820587a89820f122cdf989a9d42f12d62ba25f3ba03ac833f3bafee1bac40ea9648fcab5d7c727d26ad1f6c67c9ebd46d99c77ddacdc9715391506afbc5025561d56bf483c7f8bad2d030b77f27204f2c5b9b244269e03ac97cfb3704374c548feb4bf4aeb9b52262442b282139bc55c30fe39874104f11b2b902aba74eb4430088b1c2ece2ad0bcd751a3849ac0f4ac0f7a9b26a7503e5e0069152e36590c401d18a70c7b330b90536eda54a17a769e1e8100c5efd00cabdf536b122e499e248d1d5a8f3464cc1431aa8c9fb455a7d3cdfdea5633cabaec16faa23fdcf5c13423cd3f0861210bc5ce038a321200e41f187a10c80c1547b2f089444485a5da02fea7d2a1224383fb63afe5cfbb9c90f4dba1a71586922e4ecbe1ec4ecbec850d648c6f94c9efbe10ea9b1844d23e1aec43ce4ddae84fa32392aac9f49eb5bbdc55922f93b3e3341453797f8cc0a60ed553932fd048324f4434006e1233f2a7ea76607b74f0702acd6fb93f238ce461b2f92b4850e3023b8b07cefc374c37f1de1315ad72cabbd99489ef3babd02a6732a7f4389dced7711969d270e4c13c278a0c033218879e9e1a2448ea40cd107f3c2178c913bce12d109b2c3742a05140feb4b19490ab74af5669284437e0639b92837fb946e4676ff0bc75f8a181a258dc513aa411a073ce5260bc9089cbf36879fdde426f69c7c6d923c570d9691065928be54d6996415facf95e11504db83d514f423bb56bad173268af40999e2b213406401c17ebae42f868dece78d0d76052b08c6323e23ddb9a169cc8b0e1596f15a4f1894e74ba5da3320feb60a2d10161cdf0bc5db3ec439eb2d75b538a6d578dc725b1a8611dde73a8c40fdf9a3e663d2356c2262a3eaa343a2a125420e868443dbcd6d78ae633bf38426567148fd1b375177ba0594b3cf4742c1078ddaef167fade811be000b2ffaea72589f11c9434db71aba03a80b97bf884d7837addae7c46a9594c8c40b94b1ca6bcfdb8d1623403c2c2acf7009554091477e9f4c19c4c8df594e0c9307e90d49f4c1943363891f1003957ab2fe02443d25bd6b8330e793840ba1a2ecab5c43dab100b295510c7960e91400225ac73a0d4e003474a64d4b58ccd1493e9657931d7e1fbaf10ae3e9354de89782523d0355fd7c2732b46bcfb887a2724bd43ccf31193c3974089a9fd7723aae4c8b43f226f59cc907274c636ab83453ac90206d08e041a8d09de408769883384541fbe3e527a5f098fb0cb6bf9e0d5fa9d01afd34153f51fa1333d745d004d15f8fda88a23450a7a1db38d0956704bcb76a2398e26600aa3637088504e752aa8f7544118c2528292e89b90bc2f9960b1660294cba4f2ff8c0caa3398f7ddf1a09f3f0d7c90a64a554ad55da8c76c9e8596dcfd212996c9f61f13776b0ec71b90514a1b37cef78c8eb33d87835b64ac4a8c3dae7d8fc66f9193c36d6494928f1bfffda3e369a227c5d1a243b0f0437b2978a1c3293560fcd6989ca9cff565514e40bbc0c5ce4173476c6fbd71fcec522211626bc99b197b7d014b0805fa638b9181e64956f438a708c4c7e6dda82d00b79ed1d2d1e1ce37d2e274267f95de4777ab4197da17531147af23d22469a446f1f481c1077dff8598ed898f073a4e693de65abade292a6a06ea8134e3bba0f3b9c2798473dcde034724488df3c6fd95be783f08241f6884d9af62132eaaf528b5a49a840612ab21cc2c3605c13d9dfd9a69b406049b846ba4a1c3c65067914909c5d299bb28046ec7154d2195051182a5593164b0497537c2a8ea13337e15fec568ce36fe2a08e94684067213ba414bcee102aeb13fcb6d61e862368717073379e4b01761c6acabc0f2ad41dab9d5719e4bf2bba01d7a7a4b1f6d04a1901a58dabf99603474d09b24e23d52804bcbbb0bef9602fb4847b8772af0b4f126c11cdec0070984eea50696d6df26384919f22789f89e34e0d20a5f449ed113b0e5d67e3b63b00044b4fc0a302ef8e91c0e483237ff1d6b490d70316b06968ba69584c4cfcd1c8d3946d6d09423612bfb703cd05b8b62a415c0f18d551a8dff84b5e8e22949626561997a10072de339dee505dd2135c40af20cd2b871b3486ded1422b1ac1d43f3fa3142d21e951ad98d942165ffc99b173d0a2ee78dc5f2e793678b0e080611bdc385e48d50882027e7cf7f7a0559ff5204bf422002ddb98d42d5307f9f3bdb20355764a2cfc1729ab80328ef0cf9cd042ab11f9624eebbcaa82c2514f43445ac5d7d30f066e931391bbea14c4bf85e6d4efae53d03a5ee81e0656abc5ebe9000846b0e70550052cf0fe717767d625a43f2428a285db48a2c7eaebe00a93f160af6c792bfdf3e87555c7f54156220897f611740784109dee83297fc0b09082824604630ff00cefa837e15d6f0775d59986007fab8483373b052f71fef7ef9153c1fdda0ee4c1fa9160f9e204477ae8401a55b92c3f5e15f7c0328df4560859dc4b34c651d939825ae8d9c6d5da291aef894f5f12b553466d40d488339a1147d9ae3a2e13d9718d2a5fbf1f23daa56e280b10fd9bae4087ce2dba3bca84e320ceabc5b8a27342f1b1eb04507d0465ecf56162dc77b112be9bf660fda9e80fee2e4f49beb176db89914a5a6f3224ac05505f319c97a955ac599076965a84d1d13e6031b02bbb45a8ade1d034844ec65c0c3e31bece89452b397de41dd02e3f85e092a70967a65c8abcaf5ec438f36c13ea73bb7b6e92c32a07584580a65e72f117379a9aa46abf80976c1f610b79236c129132df1c1449159230f188a64a6890151fb788e61da6d689e83e54f808bba51150a981e6de492525502ade0d23d2e0ede7562dd26dacce3a96446ffec923ab04595f6b3b14112ff1f489511eec9e840d582c861b9d0b3d728c3d9079220e512639cbadb862eec4acbb4855c619425e159745dca95a3bac11bd70cf0f97ace54a1d52467bf3b7aeaa160ed59ac46f66d35c85999598f321421f2a1a26814ce6956103574ea08e79b2f1df0fa996e1742b7af5fd6235ea305864c0fbde462073d37b809a1c84cd2ad065866f1176919f925c8bc6293eb241917f8abde1f2a0fc57a3fa275a874dc3ff88f1618205e6657e45f927d3a5060e7476c927cfa13c6b85d60f2509285385f01e2b88c19071ac719bdffd6ff507ea507f4a9355a34a066a7fd2f02e34433ed498000235217c825a7ab43ec37461e62c47509375bfcf251d8675d6cdac845dc2c242a1b46cb0ad223b5fc13e9aac2509449ee50f685868a61fe2b961c2352a3a3510449488b9226ca6ea4f978114b0cca80c24341d1f775e4614fb9446e194bd0df26b5d1b5cdc7edd733c68b87919c5190e545b1651bf49a5120de1c8a2586facc38305c3c856ab74ed5b6e4650ef8587d74a599c897d1cfc22b084069822996c0156f26f2bbe2fca273cc5e8aa86af9347bd6e976331bb209ba0d9d7fa43488ceec0aa65e14b4451844614d5193523a7401b0474b870d9dba51a34891dec7b2a8f595bb03301f87edb23c67a1a7f0aa6d27fe0fa70db89f8fe4f81e5fd9cd5c30240118b42682aedb824f061efbe8080f1a7cde0ef6f4390d3057d2fb9f01e0912a7b17f521c8be51eff5219dac1eff391cfd87acbd440e82197cb82564a061e72ff3ffd836043a14ac16cb418554c87cd65eef432a0e35f8a210299cea52f98704dcfbcbbd7f53e28fde851ea284c6a4de222dc978aef3f79bec5356c040c69cdd5f7250dafbde6388213ab73cc40a205f760069fc50e85ed4ab324023a48c8146e0902f926962b3c88e300dc441b2648a88edd5687f660b65357e8f5b678b51c6bcc0d604d37985add60d6a95311c34756a66994ae69c6079573357a5a417c3a4cb18f67fc0c8fc6df62a5c31f1bc5fe822dcd735fe6e3ae60ee1557b4d2537d904e4672517c94104c7524bb6a50ed724d473703d707a9309f660558d9226d5f25b11b1d2315efa3a14e99a7d2cd3859ac605a33ac6a124ee1894b7fd28c3804f1900986e10a8832ffb71993ff22896d9f185d6db17d63b9b039c9bb100dc0f8e1eef71afc1cd4cc86bca40479083d1b6f680b6f17cb4a176fa1ed49d4cc48807d598b15e77548b708de16e0ade450d6a79264db5e69b35b17d549f240906a192000566ffe361b5c0f9b3fedeae4a116961d75e60be0014f6e638d9b1bf90f2d333008819008318e66160ee10f37af19ecbd33ab1670660d8f8dc8c7ee534bc66d500719dc38dd8d509a3610ee744c0c62ef2e6e8fa5944c33aa6241333f1ad29ee65fac670caac5820416ba8470b6f181819dfabe1ea754fa1dcb3ce692f8289f6f109e2eae3b31ed89f9b00233d5f51e2f4cabe50cdcdfec9561f7895b9bdbc4e7737f51ba01cfa8ccae0998fa2cd0600827d9d4642f96ea48ac9eed2f51c544208c607f49d11de0ab59dde0a2ebdd94b688c734bbb64c4719f22afa3483b8d5f42d7365a6ec2a94d1cb015e71cb83a102428358fa36b3e908e6cb8913ae3803b061d9498787fa86598e3a6df4083ff6c78e9cf3af715e86cfbec256af0bc47d83b343b2fee7e067459c0bf6d20cd646fd7f036a88418b0e424dd27d98a2c4383d942425ae00b16cff087217aed227a9983edd26bedaed96750388e7a8f6fdd2a08b8e650b1b72f0be3f5f9da6f825e52fa64bcaebb8d08e8ade1eb1c550298e216a78cabe3816a673818eda94a94c6117c8634c7ffb131d9315309100c8be617423f7e5dbddb6bb5a5fa64a0ba967c41c29827d5da21f5824edd398861b132fed212b2a158ba873a363ec74fd22c16e8ea46d98fd5065246d2359efc30b1cd8a1b3db9c3e27599a70f8daf7103576e42562bebb1fb39a5ed24ad1eccf7d1e01deb62b3c685c02fa3c5dda77097f0f996efcf181b961b9cba14a57e29e78ee58e78491cc5ffa13b518409eabae12861559e912ba7602376660048abe714e57d0527cc9d1eb2513ed342ad0f16f6dae26f129e8820a514304222e7dfbd2fb9dc51802568308b927efe79cf359d611644a0cb2c215f268d2d6b21e3c116bdf941343c95c6f60156fb6e8bafaa47fc14bc7f135329ade6af1387752aa4d16056d24729873143ea9400bdaa8e65601d3ebffdf7dac7ab6d541c89858d32c0a674d9c8275070d738087825672023552606d0bdd50a542b2bb6d30e4e3c00642223a7f4cea15a202b954c2ae9acef88fad81c909b188f53ab000649a5bfff50373ba5c5f27cd8b4049237ad401a5b20303181d130901d0375e4b53fd13610e337c9588c4ed51feac7f4130c27c2eb5c0f7a034b17119e10c56847dc274ac61e5e33fd7aed41ef16f9bdba29874f4bcb197eff62ba2f85cb57de781df5ecd3caa67647e4b39f99173a2bd4ce2b00e95b569e66ef619d560b12bbcb72489b6042f785b014e89e08f85428399f640c38c00482c91cd399fb344c3db6030fda3b1af1a95579675b7c90791ff1ca23d5d7dfbf990664e8a669d61f7a6b7dd7c5d9a80a9d024abbbb5e60f84976544faccb12eb132d625cd253ebdd366edbd8c184f4f65b2c875abc8e20feb3fc73523b000e32f2d04ccd19bb23e281eeab49e1893b209d812897c6ecd8bf903c88e72a1385a90b4730d2093dac58d4ddea832d4c423c655c4c68f976e9802d8f93860f81287d378de9c40986a8500729a44b9e018455101314a82566802eb1af828da56e01bd81abc5a0ecf91f0204840a1d091c097702ef7a9a7479f0ee0f13cb919b784992628ceb15324110b1e90165eac48b75997a0dcccc4f09a948213af1597d932d059e8601131dbe76bd7489d289ef8a43a41f10d16db7e640fef1fd298a468c978170f8a203a74614f9554383337f2a64434314951c736fb6062df0aa4a5678f64045cfc12cd12a84632733ca8d3822f4f69cc4c5adfb2337c37c287afcb30bd099310101a473a875d67705270a98cf8b901571b91ad6a15f0a0ed4a51660cd4cd29e8fade19e74ad1717610e173be9051dbe6498c488f9fd54ca7453de839d6c486030f0c5a619553a3ab9eef77e998296500962c8537e6c6d259b53a8386f2e3871c9ddffc1757d0e03fbf761509bb119e14c61d2f5243204badaf6cec3212156114353a0905f1f3e6a64b78f83d339bcc720f30e65dd836c0ff6a524949fac3b76cf22b00634149af808677122468fb7b9d497156605a2a9c1007c3cecbe91c59f4ecd957305e3113bf0466788530addc62b1ed15deb97046f13de46c28f385025a62247723f5881e81f9890f67bde7942c0562829cfc8a925f662755cc20efc8db2d6cd13085ba0a01d8389decdbd949fde871ee9afb75762deb978fd533044820c2295fb8359323ff4257ab47a07f601d3b5af43a1c844389c84e01e8f660f02c8694b40c72d149ddd9efb25e9d20d7c03559c4bbab374d0112753737586ddb03c0561b0b7b738763822d57a70aeecf8aa5e29acfb3fd972690f5a9070ca830880f43d7ed61d6e1a4a62024d8249685a294c7b138a936b5025c66fdff0219d07e9dfeb152cc690d0343b72933d3650fec43fb322f8015f437db5f1b7a3c1ef7825abaff22cfc288ea3e744220c7373679c79a2d28c4f63e0f1fe384e305266b87a0e41b7b2f3cad0b0a4063aca6450a391939f8368894a2024f6181e9c0833135abf1bdffb0da540f979e40a817a2fbbb83dc26f7f5bec5153b500437d33dfffcd42e895fd508233b3c07896ee85f1d8ce810afcf7cba7e7545ea59433f3c94fa840a9a0507450e334ce4ef12f6dc7b67d4f76bed26919242207e360c7e1e267bd01bf89f55d1e3384e2b00323523bb6342d6a940e03fcf16e8ed6aa0669578d31e3c7102efa713c365a6c1d120a823213342d8d98f5e96c2d33df87b653850977e16f6c3617ec0c73a440e05123c5f643a38b0d66ea88865c1fb5cbb2833d825df63d756ef51b3c7f111191e15a33aabcc0d5b7f625b0f8e6fcb444b3dc01c17f3e2f0244f02e3b14a4f12f7af6f68cdb5382241bb2ee118995d0c9c4d575e389726f6fe44c65b01cb6683b22fc034b09ef3163de2a163f6eaf181a744a3d8d2797ac02ae07e2bd3cf74d4e7f9225155b0ac009846bdbb1ba3383fbbba05804abfa352c7ac1ce947f481b79feadf4bf5b95f124c6f3f1e40d549eaa6449597c1bdb35678c54fc62f270a86b780af93a443c675d5bac1fb2be9cd178522dd3abb094aaa085453f50e5b94f5f9cc49249f6629670f25fa5ee30add19d7a20013f9b9b9b9f3cec0061170d0cc19c007306572ec782d414f9f81b96485f48d6dbe44f25140c70d677e12e4133f23b7686b8e66e697ccfabe62cff54c966cff614006b08e38f122f45f7b81687510106b7517c1d5b5425d071314eb510aec451f484f559d95023db5d67e25a04415509e4b5e7a7f9bc29af1ada16d024c115e7d3244adeb7731912f38edcf81c28d2dc6d0277d4196fdcfe1f5b7457c167eb6b15b175b0539b773a4b0bf10aa62e7c3404a280f1064b04c55b375de6689e08053d307110a2ca3cb6a300db3d77d5a69cc3e9b739e84a1df83e6bcfccc1bba5195d96debeb0f347f0c308418704e0f5b92db9e576e26b7448d72964da81d22230ace63af4073795e462e49faeaf24053be4e8e85bb67cf3d042fdb3b3b916b586ae3731db9f4fc2d891d2f763cc83bd40af678371271a4b9013273a14f748462d6c91dd8fcffa1efefc6976663748e3fd90e90db59ea39d7d00d7ce4a70138d313e4bad4495f5fe58f95dd47890757fcc5f5ba84709d25e501287730a8820ce096c4dd5ae46c27a314b2aa2ac911d5688f09070fd0f1115c872d67929b906fd962ee7b42fcde05d6929975b367e7ba0c235cb62a1c0d53313a1cc8267be5ee36796307deb05b51ca205780eff767436dc10add0c3b0fe81e5d42002e83fefd818a215fe1a77acc9f0015a37c9a902df88959976ebb16d645982cd3f68dee4bd819288c92190d5ec7feb76499ea4286ef9cb5d5e09719f329f4c2315969518807fae28f90315b751c0ddc43f149476e68e3d65ed4a7f643a2b956f203aa06030bdaa9d821cbd423c829c8beca1424f5e986c6c98c9ef9bbe4eac9609fd75325997b3760a85a65ea7b3e747672a413b707f18f423eae5099fc6319b1bdb57bb7b7c7679730d0d6b86dd494b481120598fd729aad5391f31b5d566a9ca0d7643e169bed5a450adea21ec132a1a936e56074f5286906d4806f2a99081d4b24a6629b2d71ee4d839a6c7d196e190341e6bc640b6d073b82e314d88a7490e64c28527aacaa4750fd6de473feb89a067c54044ca31764d9060dca33ea8c785a5e5311472c026bfd26c0de636bf8ad31fc2e8577c0fbae40990216d89d1409cbf1bf5ed71f8d9e55566e723dfe8d448051c11b796d09003e4c3e093a033417314bb9529dc80b1a14ea17ac9b28196106b19c43d1a4ede94bed2e41c24262a3f1ef1d03a53504c5198600aeadb3b19b4409b27d3374ed708047a0047b02f15ef8aba7563036674fc8a43fca68dfe24bcdedfcda13738c3c330890142d2591913e6aea009d8b80483c33ea3b2be8bfeb8f93b9135ab9a9453229a9451eeb544f407c0c1d9d1f003787a36b240a3b5740777f5715f6959c401726184f63f571998e17a7de22ab0b30b93080a6b74ceef0e7fc7ab542ded09ab46e29b95d8c214cea5bb960cbb788c7a036f75bfd5035887560e1904f9ff28557ad61ae8b11236c4a888ba20b13979e1221702ad271674422ce6e9d9268be13a226880ba78215dd64f6801b355ad1442f8353017609d18846214c9574f7294372fb360606df435521ca37ffbfa490e176f2c394f9615260c6515147689c217797205db50921cf97186d6c4c2afd2ab594cc739893d84f193abda372700c1db3901d56f8a1e155e2b13a3a8adb16ce8a81c8c81dbcc62bbf1d69f0c46dbc7004b8caf06964b32ecfaef43f80c51a7dfc12b8057ace9f7e4ed53ef081a662e70bb8906434c41970dc370764c8e1191cf8d9899f50dfa4436efbf8fe22ef3d82881fca87098d721c7b46d720ee74102dcdc744a2428d74e8469f0639e8f2a41cb2d658ff99c75863422ee98a7f6ed1fd583d7a8414e72825bb3b2105cfa4713ce6788e017e0589ca8c5f9b7cb79ee200ab747296171ed7e3d4200cfb9aec0e70332ec7bf52838f27a55003c5e828db8e937b8f1ebaa67517da9fd8637f58184777dbf5f494e56c01722348ec90a25ffa84366284c3729e2e0460e55e48d26f11fdd2818c18d09f5c15a8524ef718468d080f1d0bbbe3634587e94173dd16501fb08e5446b62166196cb20777ee482884349301f6e88087a99825d0bc1c8aeaa5ea4ccda962371b329dc163921ea9e2f61aafe02f2def2d7170c0d991010a9a30fba6d558f790e2ebe6ecae251d22ff2bef9b874523354bf3d5fe4545a804d80305618b9c878adada9b71ebf248f2fbf1a8ccc6aa1a631c77f4538d6ab9ac35215af699f1fcc25caec58241fdd408b3446029069e54963b728c1811393e5468ed1db295e5556eb0d9ecad293582e21e3b88f8b0f8eb08e5ad7ddff6f2c8fa66c50c73276a759d8b82082f813530e1f3f50209644a09bb5a148c95c51b37a0b7b942e243bfab82131270674e7a34a5b3ff59758f8d6fca9473d0fd3950189d4841ddf063234f0453d9ab2ec9245409a3e98197da141ed89cf91bd3d17f9492f1e96ae414f28fe42c1b289ce09b6808031ea50fc18b655296f5cf6b1625cf538438c62df101aa73aebc5b32ad790a5dc972b8f0da39e717179e89dd737dd5be02d2bda8d18edeb29b2d14a64b9e922f09ab070ade31d8ebeab39cc8f5c2624c12500d518033acddf976ceb080d8a0a745c4be989e2c6e53b163a18d628e22685f8d1059292387a6255f35e7817ceac0a3a5e4cce9fc1ecc49aa8d24f4269339fc5476a61c1b6a55d97bc6d9612dfd034c1daf5696e8b19cade192be23328255d8208d5942d6774966289622cbc1401cf4e41fae02c94472c03ee1421bc0bdc19426e00596f1e257144c0a45a73cc51826fcd9d56aa26653ee4de92136e2c0ff96e37b003f5b4d437fa61e3b4ebef3a400aebea19f4224059875d4207758a1446f71c45c56183ce19c17aa8321c2dd44b6ea961aba91698ddbcb06968be795815b6783b4a432e57e815da1651a982fe11ed19fbb0127a38cb83aa959f843acc798f80a98ea6aebfb78cb0907f1058ea2d371ff6485f525885bf6afe15b52029ef736b69721d33cf6f000539529901ed216d6f2350ef866352d53ad424a89f4774a8054e174c99a7973f232f19cf317da68f46fa3a83ff9cf1f0efbcdb5edaeca29776de189f6eb107dfcfe5355ff21da34bce5ed80a90b20cf6cb3112f8962150e1e614778337430da7f88dee0d7225e36fe0d5568fc482a9a6bbdd14a208c189fa930465770175acfaf14d5b9fcacd3cd281a7536266130cca97b262bdf5af482297d360c9b48b6df9cb50bd70fc03f83210f3a099190d2696558b9f2ef7fd1e8b01e18104b0bbc30f5c3a868d0e063d05a88dc15cc22f4f48071da97c9206eb20e2f8dab05ba823a92ba5e2af3df6542dd167a32c45688925bf6cccb850f29f04e1847eb1a8efa08754be6144fee91a70cc428f9c174f4445abe6ecbacfcc7d96309268f7c6f9a269c3c30c983cd6338c435961d01382d982242c419e5aedb33a543268b1737249a09409c130cf60072fbaa18dd6d1dc4b5cf3b44a0b3da5f19fcd6c61a733c80cc70bbe10041b40486d9066a3a9d1d669d5f836253db13b33d6527497efdaad277b65adf02edc91fe82b26135409a5fe4869310a5b4a2bb4a712dca3a2f0e0f2adeba4cd8b493b08dcafc1663d2b6d436162acd2c6a8529a0bb8eacb86a18ebe3a5c9abc07bee907cf3dd35ae88823be9234e8681aec7f0fbb942a9cdb9aed61c74fb330ecc35b1e631d65d6fc187983cc8a36042b3411e4e0734062b1849d31e630c90e95f0650ad3b83a8806e42fe05aa236ee8b0f83963a5c729a3efd3f40cea935aa67fa5c0f618d3dd18a54e835a3b4107e5493eb6d1da30fcb4d427cfbe9e013bcb80953d75991aa0fb6e2ef3ad3b4fb0dcb1245021b4f39e7a79d898363f2f604fd141045f86581e19d21f469d755757344460068c0c7a312e827fd6de5597a2b11c78d58d1f36e9a643609d12db63472202e6dd39c7618be173d6b3d37f4f624173eab3d7d0b26c1c118b315379a20701be81a8543a55493365a126845d395b2e15c76457d04d1d8d56cd99a5e8976dd1d091977f1ac6f995a48a64ca2ed07d495df2bd1468a7c0034dc42d1ecf4994f4e8d1f4266353ff67b17aec2eb9ffee1f09f2f50d6a1e290990fc1383369605634791d7642d7841ac186ed0745cc127899176c36e01c4f1e39c132115f36d0a976ffaf2e0873a9df18046e7b2b3437b91b9412c0272e8bb33633d57c2e52536e9e1e3a21483324c2db07b47eb67c6751c3e883a340ab644e8a34fbc44f870a7a93dda29e229d84a8f9ebc0a6aaf4f37051ec2b17aeb03cf901c92e82e171884944019d7a10e998da45b4e2fa78a0674243e36b68064eb85021c3f3c62ef0d0c4b55e71f1eb34b5abd67c38ce892825e2d96468ae398fb2042002615cb0cffbbded05c89f0c11f597639e499590e3e326d9115c8459b0e45ef6e10b2f7fbc7b4e34599a0b5fac8e31b81fef328e8bfb46e5480ffa6a0e55ad65b2348d5b23ef6ce881e7966bda0a0cc8582b06b250f90d87444a052c1a7c354ba522ccba749956116695368cec657428a56cacd918c5e5f9f86ffd6cb6bfdb83e23bc7d3bd54538ca8af9bc6771f948224c25177082ff2cd39f852528c24c0e4c84344503139407601895c71e2fecf96944499f53a76113ca7ca064e01f7942ec04048d39a1e028905ff47c79848f63acb34e6be1fe79f953108d1ad0dedb334fd4fbb5be046e2a57f4f7965b85403e8aee4811d5609e8a2af2c2c8b00c2c7d168caa29a4eb25d72958b87d96d8ce504bd580609876166806bca63be5fe01de4d3822a32ce00b561bff8e86fe006c479618eb7875ec46a3ddb1a49ec8b4e1b3575639c80d108003b5bb6a58b892c467405c464b3df14b4c65668177623e513b8d25a2ce42b3b1ca3256c55069eaff13c15bc1f3ea260563ac777495b350c5c915282336c2334f5fd622abc863791bea822ea650919bad84781d7cb8e58dc95ddc8210aa5520d133b954694be13d7794c58a95dad678f4bb3a242219657ffffdb8ca2108ecfd0888f4e5443731b5f8d4c5d7d7afd6185faea9ef29b6c66429d3f2285c1d9bc354f1c600fa9a341f76db499bf4d28a0fddd0bfee5528530ff0b8634000afcd624491320e223f4ae7644cfcc7cc1aa17d4cfdea10c01595bb6ab1a3bbe8b98c394a8552a495cfbaf93f8a57bae770423ecc78ed9cd94abb6361459405abfe2a2791109e877bc6c0488b2820969aed61100e65d098507d71d954e87f128f9193b406907340492277b6213a23b25e2885508610338684e3b3fab9c82edcf2fa4409c2ef55021e92ec05769fb4283c5707eed2b2379c3b731d475e748c35f572fc545e58c925324dca3c48015c00dffd6082c906b636775ed412b9e2def08dd469f084365d489dcd96c7e59fee60e85b99a0ac65a851d91ac30e0f661f65537754369dff1ff060857ddacee0e1e5f2972b916699017b60ad89b14d85be7d97a2116c09ceefa9aac731c92b1ac71ccc4803682d2d57785e494c71e9229531c4c37cf68971dca30cb857a02bf1f691b89006c8ab24310535dcca5549d935d20edceca53d95b81cf8852014d5c67eb06c6e48bfd82a0ea67edea9b898189d3171c187fe6124173044cce59fdcd9ef3ca2d821295df527967c0ce97b23d79c0541e4ed9bba72e45bc5faf9c01eb072b0221c872286b2e92403c412d2c4b6e013ac5971d6f5cbced6de491ed59162964f0e75bfec366795e53cae6f47bc5452d87487d8f2f5d372d6d54523f47a55e3de96f38ec5acd1a2b3813050a19962d9ea51da828d767fcf6379d8cab295ef8605daca564cdd28a50f879f80f666cbc25002bb7e8b4bccc287979e3d7c1f3a6ba63d1a5531ea063c297e4554d76e40aaf82589e2883d685e43200307ff249d317a6f5bd0d448263a7c99a288dfa8c43ae7e7736d62fc201ed37cb2360515eaada352aca7beaf2127d11d8a3dd709ee080ccf8696feaaa2071047e4d8350192f9b7b1404e42b0ca35837d13abe8343ccb74e12ed08eddc0606ba17578faf3d517df222f47a223eb7586e47a075cf9dc4646b809f992842bd50e6dfc919f3c827e6d3451c99ee07ed770842ba76473c758878f25b75a1a2907ac297045ab5979f7557fa05f9ce71acc4fa5e525e3e3fd64b6ef1b73ea8c68ded6401ec0bf1de4c8494aee76f85548957d4e9894dc0e8247d2232ae337b6fcacf6e67d23232c8a125958071e00fdc0048835775f7a26ec80aff0207c1a992734088f999dd1d98d5f7964efa091122fe727e41a1bff689af27fc61cbd3bf478f10fe2c6b359af0c9bc368a08f1aefa491cf843ea5cca87eb95691ceaff6782df4118dd668b858a0df0c25223bece8c3d8bc0b9066b5614d1ced33c24289c6f2002cec88967eaf84829deffef87bced87801a31925f6883744404dd59722869779f01a9ca1792e4f3f5e1d9b23b657aec7d22d41524efb17cf9a353aca3772f7f899d6b7efb4523109bd684ead4b55e65ac656f3fc9f8be09f2beaa8b7d4bd3667a6d045cad2c30cd2dc8d3a1efa053660cd78c5363a13f936123e0f0be5514b451365e54f2890d9e22cb269292a3fa91e84e34487019aab49e16dec1995c4afcfbd4124a529449d319264f350313056f31b3ed5067c0e787b7ac0417f5a83b8308b285dfe9ea388e63f38ae03438f8f3e0721cbdfbc48d96951af4dc0f66d733de7ae79a6b59c7f9e20ccae060a49c060693980f54d223d93881e6f98c8533070dc7faca84678bb9fa3fa578f59a65fe039c27a9c0741683c11adb2048106744c3e1f16ca1d5fb31c9fe852ac4094b82f4a2f242fbbf845e72410306c86152b92ed581a4aa299bef093fa9d6d301c0cdce06c803f8e80ca19d55f3d86152410d88cc0394345ac7e9afc8aa49181b5c1baed5ca91e11cc90341683624edea960980e08b669c387cb865c81fcb063916ba4a4a508068257648bff0ea3ea103022c3363e88eabddd007528bca6053272748983151086796aa052cbea2e5b05cac80a8d6b12db213b7cc44505ae67d95891dca3d406ad36321d20b47e0d56e1c952f7124641059c35a01401617929b952da2c3320336d101c2fe88a0f44d45be824a62961d8261e853b7092206a098d0170640c15857e17b9deb20115a6568b1495b27fac3598a8dad8782407f2f71454bb6cb94ad0198747cced315230395a89ff2f5bd0b4b4c5a783e70e7817673ec6061e14becc18db6adc64e2ed5e2a47e859b68521fcbfd0b1fbd7c15487060f1728df74ed5fdef9a26f82130a25052ced68ae968d6a4277f9277efb7aa66ae1be1cfc161abc21ec4cff69c078afac9b4ee1a226512479ec8333f4a003d9a50d01351d14335de61a559339179c43a3af625a769c99d03a4aaa633a3d8c69a13fbdd6e5794f8bc50bf82955c039989ebedd3de0008cc470e2da3368401945903efecafa867c72ed0c1c7bcb07920db3e0682c7cc961385eeb7776cca7cc925f6ef85edd42e5c71c4d372f60c0f26a23eef78d4811183a38239bc0d6b747b57fa5d9240dbc6bbe4a171b7b87d8636e42dd0b1fad91748ce5f1df85c7b26b2076ce3ec462d26119409916682c8ad8d61cfcc028919d00f7c52a218247c7e8e919e959cbff1d46e73b8786e516037ce3d426e081b9398e10070fb7446fe0d96854df3bcb260aa9a06435ba3a87f875c300398b14dd1ea0a0ee09e41baf1ae4042a0b2a6c78f375e8147444121342eed444bc2bd6ee284f9a78a1b123c3d85d521ccda09eb13fdaf464103a7790a6a3cb2b5127d9e4918e0ad43014c26d378e2c9aab428e3f0b61c13de79b5d1595ec708015c8e5aaa92a6a2cab28c56705d25dad990bd70229687ba9115d7f956e15351b6ac4ad8d05fc5d8eebff1dfa7c7cd9a298eb0058fd9fbf4fbaae8b93adafed9d693c85c95cc7e66fa080496c84aef42927c3dab99f5e73d592a591e9a0b129c530dc98d50b27b4c7b591b3b4d381499a926e80878c960917b35604fb3e9deb48f92fc2c84015b617903035bb1108fc55bd942669a9dac7c65254529d5ad0589f92518ed39056ab2b71d3b147132323c0ddd023908d3d44f98f698603526e360f98ca25223973b41e60d326e59f9bfb434f7ece8e7ced446c1769cb84a14c4b3bcadd530568d8872356192b7462862862c5620b8845d2968ee1659398714105ed831f94fb74e37c9e98db8354909e61f3ac918939916a58829b4e21c2c1f0d9c8b83771441c18f926eb76d8b229b9c239e79402ed337c243b4e41f8c4fe31deea147088085281f09e2ef620bb486359ec7be0580dd280253783f8538f1600d80e2f5f285dbd3c974b9276ec20a42d5391982bd86d8d2739ba802afb13fa8a8b600eea203cf61fa96c2047a4e0c95d01c83f2d0338a80efcae7f5bb17174cdf722281feff71c3c07c6ee1cd9ed8cb8a266971339e5f69caa6de7534a09b169207e794846bf3ba5c25f189de1a846c1f61c0dbffef6c70a20f7d30752a3bbf059d8a0f7ec64c2918200284260cd3c1c2bc316b72e67cf14a11dea109368b099e6e252b05719abfcda9de63a011f8f269730e461aa8fc92f3641b707fc93262bb1a5f504d824c18882a1cc799457d5d1ec1f82a950f52946516d4e908ad38efc436e5ad0b4aa31187ec58a273ded43998414604d24d0e2d274bc50800f2385e27c364c6b0cc052561944b170cd10e698b4ad4bf4f1fe43d21bbe51d73dc472708c06a42035c6f3c9dbf5610e1a9692539b7ffd06ec43837305a5e284a59a31004942ca49f8de79fef059b01f0d4ed3d4673e2e07fb20c304f95474f7a8fb9cee9530d13bdab95aacc7a8d4dc8cf0fe16ac1622da2f34c43115e4968cea0efd3dbaea912f602a509252caaef00f96b67f261f58ccbc80ed3bb437e490a429e6fcd7102b5a3265cb28b19f796d52545f3b8c075d1d15ba2193528761dafc95fb1445eeefd20665b05e949c31b104b592c1482a1e0127cc3b5f396e554b01d72bb9d042418bec61f6078ca6b4cd0ac957dee05dd0d2bdc1a64836effecd5fd200400c3d49be9e9406d53381491cd79b4344bd2252eaf107a25ee8eab5cd265f7fde6ff6de9dcad71e059756292dd8991226967f0bed319f4aabff7d2bff3d040f590171408804cf8478784a4a7ecc7439a2964d26581fb084966c299458b1138bc78dd5c41b06f69c54ceb5867fbd61ce1679acd7f1b80aaf1e95052055be977c1acc4662ac7d22986890aa52cdfc2c917d043ce39726bc03e3ee56db549eb223b59fe8df4d130b4da0a70a5590794d0bf80747d7266d16525689c83f1c97d118d62e1455bb2b27ae6a1bf29ebf7c5635455f1f93a9701c5761e2959e34353134d68bc90710238f29ff1c210d8b61e954228a0436701018c55f3261e5ebff80171b15592db634df01e77cb9b54c40882489bbbad05cf09bfb8af58a4b5d9f78e9b08d3bde8eef3e8bcda9677b1614a0158c41138a369f494efc51544eb45893403bce022ab80429e93823e0f9ef1f3c735e1334a28356dfa20eecbe71d3b75410765f553f48a9b0a986d9c1cb50d966684d06cc2ee612c3ab1104812c379eb4ae58eb4e5170276c546d9a69cdc45bbd6fa5a27843dba32d310c30f4d23499aa04093b7db51c1570fa464757816ec383e9fd226ef767dbe491581c9d05881fa565d3a41886e95f50ae77ef1de847c9062b4dba3ab660a3d1192545072e43c7324c05b71886128e59989396d7ab2534b84721aa6b332b3c4d4861aaa6dad2f0c94e727d831f7f5c4c83d25449c1f5ec8117b46a6ba5207198fc0f80f92d432a74d95a47518f67c78b0007c24a8bbf566aebfda76e75d52fd681d20cfaf576c0569ad0758684ca16ef719e004515c3ee992af5442bd3b5200d7ea67b46dec1ca2cd12b92f1e2451e8a715048c1703672b375f474532535400afaac18515d5d80acc3e2a6e300dd48a0ec1320cacee170fe7a0cc9ff61879a46f1dca9820caebd024ea23d719790cdd26ea901847364cc95df42c245b20aa279df897f0c37d2a3682080e8cc2812cc824bf4e98ceda3e39be702b1397ec396a40bf1bcc7f6c15e5536152c59718b3d767197abea3e1f6cfa4c09d459bb18cf6aa9b1acaec91363c70a66c5aae4e62d56489b8c8d9a2a20b79ab028d99b159d6e27bfacdbf09dfd1f81a7d295aca26f08379806efab0fc3edf81d8efe1143c97f5880c15e0b283ee7d8a0b392a433249af899e112a7f03797eebdf1ca6ccfa2ac882ddbaf980f707a58e9828e19a967f9dbc363ed78b278966ed1bdc3d97af2a51a2b70ef2cad2b827b2c22dc7f79f50c5048f5465fece720902fbbd7e69679676ef9e576000e7596668f48367f48d1de288a0a59e9263879836e721e65a4632aca2120239585a14829af43d760573965eb77f51364eecd0183c328f91fac12d9d929366a4ba0a362204fcf151b7c5ab93649387da878c242a3c49e41b4bb54c6ef8fd5ddbf42c57043d220da62e80dd1e7fea06bb395a49e9a3b32d12a9c02e81707a106154fe0a4256b0efe3b831e311d35d04439061fbfaae2cbdd24a326185a05b05ea9433c4448a4c565ff8760213547ca91cd5ae469129090659fc220c6c1f8708d0d388e5f9c10e0b83a66a6a4bb1bb710a4b1d4d8fd90659cf99c7339e9a02effee6b015a2415b9eeb5f3c25c03d61dd0811ad48206d126f7520ddf35ade2d9211cf5330c75cbf95e1c9ec3ff56437609a853f40132fc9ee3da49e07498298cf910cf8351f93c8b0946d7abb9cbc0de13e700c714ff8cb6524fb0a77675155081c60012d17082232eac90aff11e040aa1f03ad36a1a8a6c8ae8acd2309ee3fdff03f138551c0ff723c0932631623e71c4d444743bf1b8061d89fa74fd4cfb8065be93791c4d569f22a5616c50c06090d7a47a937bed66092c66038a484b322892c9c7c367a8a3b70de23a57c4320120b7b9822a2d0f2675459aecf8f201a7d2bee83daa69707785b67691a0ed56b2105f902ac6769e680b1ad5df5924720b1a6ccc0c211140b7b1e38d9f804057e59d87387b90497b53081e87780b02ba920962dc98835bf538a4c1aadcf30ec642a937371888ddbda2729333df1f01b66d2efd5b0b776f36ae951f73b154868efe8584fada38d91aabee831bbd36ea2f46ae754a99b1dde3b9b9406fb582760a3c3516b033a5da216331059f0b7bf5d03ad12072b7e7077711a39f28bb82548ff2a6065cd5cade7b6c19695f759fcbbbd09d451d8ca9008c6a3ed1615f8c5958d547cf05372ed31570415c0e322c617a17a7b3393ed382eeadd63f5c53b2ca914c51148ecc8139c20c4eb20121bc77e0d6349ce1088cc78f849397e3c61f50b2eee957dfe5188bb62b5275fa89c6ec2dbd7caefdf9a5d3dda1509f081460d04534a776f8fb8613d105e2d8d3e1c062a12ebab4c0e91d4f917141af4c3e93bb0cd39476d7c9a025d1680688031c58a7fa79d63c4c9b6489648bb516cde27cdc6dcab390e7d3c75d245a176be04df26484390cb14f1fc53d04b8a4ea6626744d094ab2a30c9a56a0808cdd042714335a6274402a59e327bc5d370ed90c8ede2e8cc0661f22afc43fdf478847ff9e59a84fc0824a3afd5febf74c034171eebaf20ab293392b827a73098a2da38b04568cdf3c9727d592aec18bfca147087b900ac85776b40110042983c4bee49c77c3efc1d870e1333a0161c7c8acdf63901d567336798d8037bc8dc0f0abf51df3e262505e3fcf2053f28f75a529c2b4db856d49c71513b11d5613abe3e3fa02d007df28318cdb9caa7f74e81233981ea509d24197f95b5de80167bb34071bd79f46bbb971ac85fc1c501fc74f0b7bb6e93e2cb7b2485f75b8c59e2a73c91e46974c65687fa2fe8aa323eed25d168ec9822b82920430074b589034ef62bef53760ea22970ea991f6a5cc23ee296afaf3bbb032ba4def1cfdcffe5d840c1aced52f38890903d9710158938deb082eb82f7618fc6acda6e5a7bc6890dfacd22824dd831096e0d0fa06daecb296f110f9b95e5f7d38c62832a3c3152f746856a4ac86bb123aa8f9570824d9700e165166badc95013fc81b0eeefb4a7391428488e4c68a4dc640c598f0d224df21768b7c91d237fde6189f89eb8636d31368fd72af07df66a8842804930f5b282e87ab8aee21c09ab22a60d56350614302281e3963fe510a701f7ac8d88d5889f6b103ded52b8cac73c835fb8ece569992f832ec26d46f3b1ad949b78b0fe8e23c43ed56be17a480f53e8055ce05857c1dd1201dd423528299ed953dbe7599b37c22c45a6f4719c5fc534f48d500e45c8480a14286d1fb5f71aeb9a1e147e50909341168eed76c761e5b68f713e39eb84531a9213c0694d7e0e53d48c88b8a5292356db3dc09fa0573c85cf0e7252493c5dafc33d9dc61860f70b48336169bfa917f9cd9fea172c332f6a9bf20d77684037b4c6abd07eaf6c011c8a7b87acfda672a632ae0aefd489fab3ff6bd5958cd1d55571809cc1fa4899ee42e14349bdd177fbaac6c808d70c1f0ae2995b6bf2844447cc2772d29810d28ce9b39b2e32c881d21eeeebf66404a3fe61f01113cb5a7ab85d3a977425db11cd3271081bbfd02c48aee925f819a0fee7b446dab7081535c62e5a5faa991faa1ff51b98c2183823c6bf6ab159eb58c7e9754f35f68868f2dd7dd59e5bb9b82be81cb60e34aea84c56505bc47d50012d0d8bac73f562bd670e7feff0f2bb2cb29cd9c834d067261e1b6425509045712b916c279d46b440dbbab2b29f41bc376c6cdc2e8a04045919680dc58924ee999ed434544bea7412e6e2ca7df7805c43104fafb53cb5c4016956d3a3971aa07a75cef40ad77a0d663d987eaa7346c9d42d921d6d15e3683b8d6a1009bc0201114f1fb111fd0e820fb12f017ec2ea633fdc2c41a6fd52121e267add671b198dada1d4ff9480f9afd7fbf75935113217bcbbd03c40c120ce40cf84472dd2d919cbc26f5d66d2a6cc875b74472f29ad35bb7a9584181dd86b16d85b5c7c1760615d8864b280b7b1b8bb6b0a690eb6e89e4e435a40b9fd216f5a329e4ba5b2239719dd2166d5b51f195e7b06627b0159fe128d8063bca7358b31533a858c1b61ad2ab016f52a14caf013fa648a1428da6db6ac09f94d876729202dbe8cd5662156a3485dd6bc07327f1225833142ae6097c8c23073d72a4fc5f29266225b0adc68433b918b7458da690eb6ea9c5b5ae0bb72d29398e09e63ad4680ab9ee9784e4382dcc75a5db5a246e7b611b8e1cf6c8ebaee7b066e56128787c0d78540d78d5c909099cc39abd5cb8e6bbea27d896d3c2b61a96c7024bb0f7a14e37855c57f24a2009f6bed58a55eb55ad4a1d6755eb5158855f28d7e974540a9f288b5a3fa2f089c9d8a75a6f1a710965d167d1162d9e455bd48738c7ce56a1cac39e58eb391ce21465d128ae619445fdea2fbea5eed780f8abc7f16a7d87eb89b2e8e3dceed3d7c0d412300861d4c50cbd65da0d196624c74e5550be03a099bb38b6aef2424981fd4489cd1231142b295094a722a7a49391d311e40d89f392cc8195a40e9492d47995a4112693158ba44414eaf1a1423d3959c435a89114295034813ca9d08fa25c831a094d43a79b76394b58252a848e689793a484c4284834d22ee70a979414b5798bf0285338493b5e28908cc0471ce9a0a430d2d12ea7c96a7511a38ab4797360b0db30c9abaffcde4474c26997d304af62242598a6661317310aa9cddb77e18039e24b74dcc032819d6eb06693104b24ab93e934b1ea0456a986a878a85446a87e543a543f54382a1ed54d4a993251a686dabc8f9529a3142e5345dabc2fcbd4116ddedb949b4c4e7c55c23c4949db8ca95c34f19787a1c0fe0a3a534327e24f549178d4454ce3de98784a4ef283f5958fc94d4d22d5bd66f88a1296897585e7eba773053ecd804f435ee5e9549e6e27a3539036ef53e5a9a83c0139119d4894a7a1f2e47312ead38ff264529e784e44dabc6795a71e6dde9394a792f2b4d3e63daa48053ebf157c9229f0d942812ae251c1e767e2933c81cf560a4fbe57dd98c0e717c32759029f2dacbac9f7a921fb4267253ebfe39384e1b385921acad723452790678dba936dd44cab65c8e2cf2b725884d11e11497f9a2cd5a12673f8aca9c9e239129b2c965c1c63909470652d4316cb7a24b782563eb2f502c154aa54e28af20d4395eac4233d2790e745a180e47b6f8844fd746f88ac3f4d3744641124242323222221a1ee144ebfc48ee89757917e5921f58b68d42f1755d42e312d2da8a27cef3181ec9ff7c6c464626ab5c2b0e23831b0ee1d0389b5ad56ab656a91b8a9d56ab5acc945029f2e530b9fa3099f5c49593349d99955dabc2a6f3629b95ccbd36424dfb36f6c798a4527b9637cab2c29cf9a4b4e529e3593b0be3a11458e1345eeab7a82cfca619a0e9f67170616c78981e4de3194587b84adf5b7d567678e0cd485eb2602a847b2886bc5a77893588a37798f326859c434c49f9c8e32c8ecc2e709a674c5e422a6a9591431a52b159fe3ef6b194c7a2cc7c3b0632e293b939436b3ca9b57259755e5c9ede4fb54799676f23daa3c4df2b4739aa69bcce1b3cf7ad62c9e52175de63e62eef5e2d9dd4ef0e60c6f270deac81b79db39ede46bbac9b77493e9fdc9c52d5a20fb26ab826ab042e825c1d6dab5d67befbdf7de7befbdd7761d42e80dd16aa64f02596bdde1cb1d6bb3be5aa5ae56fd22b65813d0bda37700794a206b92eaa922f6f576371f4e98239ac8c3fa1548f57e2512d42ee7156a97b30eb5cbf955a2707c9fa67ad42e275991dae564e1fe0af767dc30f5c7b2a423f7c1afc3a937bda3777850a83be68d03f2c9f65e12c893255b4f09e4797372ae8e76b937e2ee6897d3ed2f8fbb737b5c9efba35daaf81b6188694a2f09018258885b9b1eae11248820800001c4cf0f3fb469da5b5fbbd887364d7bdc038f8c4c8f19337676d881870c193b70c0c108183074626274c0c0e4b474ad4fab98c6779a6b8def0dd99b681ac9dbd34ba9385652b6252f2c97954cd5926a81c2341800484c3bb110310d366216fb3afa58711b2759f431c36ba8b28f1c93d98bf89c9399cbf81c9399ccf49c93590bf91c93590bd4734e6600483dc764c642f59c93190bb6ad9e63325b310366bdc68b8190594fc9452c8e7834618ec44230540a7b4fa9b06a55fa8a85c3b34a30ae4247186933a86f861aa712754e51eb306a9da33602a97724350fa00beb3c21f0a5f022cc74c3aa913aa98bb4cbe9f511ed7296ec4dbb9c224ebb9ca69c53a5d32e27cb8876394b702562639515e8461d42536f4204a901e40788b2fafc50d61f3e549e23d85b0de239b97d1379ddbe83dae52c1de5f62dd42e67f8dfbe87b0cb493e76fb2e6a9733f594dbb751bb9cab9b47ed72921cc5d97a8adbdb3d5c3fbbfed12ee7a97ddae514fba7c4ed1b8889db779013b727ab87d49b891dd22e278cbbbd05ea88c06c90783b84223a7155918a350a6277b4cb3df0e70da59007db1fa44f8afd31bf4271129714b896e22a6e716de52a56b0ad12016a1714b886e22954704de52954f00d14b8020d691713d7ccab9cc0b51357c1b4fada094c93826b293f6102d74cfc84092c440aaeb718aec56ea204ae95b88912b8460cd72018d7f04b94b856be448983c0b802f96997e3da5fc2700df612868138ae3f3eed82826b2887ddfe877621816b240e23817f40c12e2f5c7b9d840bd75c27e1c23ee0fae304d74eee32c13593bb4c700f27b8f2f4689716aeb56e52826b253729c132b8f668d392e01ac94b58b8c67a090bcf20c17567856babb354b8a63a4b8577c095874de15aea2a14aea1ae42611924ae91479970cd749409e380ab1176c4b5f12611d7c49b440c63c421ae999e237ebc0571adf4f0846ba793271cd3e15af7b1c33035a725c4b4fa1a875b2a0e0b886915d3a8d53eba98a5dec0b0b50cb9ee584b5f3cedf2a3f2549eca5379a80e1cdb43cd74668786c4958704d21e7d1f49daa3dbed76bbd91d7687dd91949494946481be96bdb5d65afb5d9f148d8b10be3c122836260735b3dc49bb1adb72d0225825362627a445b04862707252b31c3489083beb984e8cc9e1661d9333ce3a7c11acd369968396a19bd9989c9ed9989cd2cc760c4ece6a9683c6e478b3eec0126a96831ab9b32e26e7ce684c8e38ebbac6e0e4986639e81122bc59c7e4d459c7e480b3ee2e4763707254b31cb4e8e666d627a267dd6937ebfa8bc1c9019be590b3ee4470b38ec9b1b38ec90967dd793139dfac8be9b02d07ed4c23b68921b6e1c86153046b56c245b08a60b577fbfb7916db70286d2172b7ed7731bced3b8e87b98eb2a0174b9e077ed8fbeef7c645b0665cd7bd5f046b867a05ebc5367a13c312f82b7ab8148a6109bc0ddbba3edd76ff795d7b230a47c292c7a97834d593b05226d1e46258022bc95961eaa617c19a99601bbd615b11f7bbd7ddb084fd7ab78dc709312ed195c0da7ac971e4b0096f2b611c396cae025f8f238777e4c8919b9b9b99d82ac1b6be2d87352361e1d251243e919405bd5d95704a4559d0db87b781d846bef42258b3950adb8a60cd52266cbbdf6d4f1971cc84776fcbb13315109f30bfdbaae9230adbe80dc4b68aeb0c2a280bfa22583312db7040bc4259d0a3a02de86b1040821cb38b73ec0d2fc013f1cd6ca02ce871cc4ea5db8a60cd4c23b6e5b06622b6d1dbcdcd2cc45ddbe3b0680bfa1cf4889b9b1911e42cbcd7f56ddc350971498bb2a0b72f615b8d39a481d9d78138a686cfc56b093b665efd300d1ecc892f5461d65d0fbfb874b29a00e830c2acbd190e11ad59875b280bdaa24fc437030065416fe3f0ebe2131765415ff3ad8008338b73d023478ecc727a864304396bcc82b2a0c7a9780565414fc43763798d4965f9a84797f388c8d30e212119191111c9fc204264c8ed668fe89758917e7921f5cbcaa85f44a27eb9ad3244a91d3a5bf26987562e4eee16c08b5cbd21f2fbf7f0de10d9fda4404d20cf2e2a22295d392bf81c9625233b6ace8c1b3a5017a77d2319110911c994d221312d2b6f9194de90417c960c78d5da0c78955ec23468352933a0952d089634dbdbd9b966ea8276ca257c5a8f0219c9270532f3598fce7a64a48b8c64da3f392910d9ba99cf0f26f72dbfc07b02d943bb987ec3103e69271b2730a12245c6242424f108667443110d7cda30c9267c564af456a16fb50ab5e7671ffbcc36e9a7031e4f884f970320dced767100646f10d4d9f49316c106434f206b359b300d9a9a695d842045b9e21ade2dd7d3245a448728113a24a665455cbdc819f485ceea0b9d513284b45d6a94be48525246423a3a3232ca4545444443433366b4494f840810d09021313130302d2d2ca669c662b1ffafd7abd56aad562b92244551fcbeefbe466b5cb3d8cbb1c3a9eebdb6aeab3c4af028b2e345938c8819e1791d890ea5a3abb8eaf0bc0ea54b795e6772f8a2a8b8e29cb8ef20eca7a697a7f72d9313d7099a1d525e52d6c00188181fda6c91599961a25029a9682256be625f3bd85e326eb470a059c110828ca921c204d16f0122864be01f4c379d9e9e9e9e9e72a7f73fa05ca8d47bbaf7a8deb37a0feb3d24ef29794feb3d27ef31790f89a3a04e4d4c7e22f1c2b4cd1376996ec267d57162d232611197882126115925bc2a61d54791baee34357f3885c23fb4494f5373872906efbdf7de7befbdf7de7befbdf7deef45b9f6ca8a69c662ffebd56aad56248945f17e17e5b7f3bc8b9905e56441c13555c74a8e892b4eacdedcf6bad1a2590941e21a62eecec14a8c6b82f8381bae01a265f528e7dec1700d0aa62debf0693d96932517754556cc24338614fbd15f46af56516b45b42287485148fc823e1494e3e8a1752818470f6d00363e8a24211d1915110d09e5a83394f770eff9dee3bda7f41ef03de27bc2f798de33bee7f41ef228b887e6f6743a79c23435d62ee3681a8342d18640e06986785eb5ef7717962f66a9d9e21f8a8a8a8a58ec0b9d7d640b65f3ea21c210b6c0c4d01bc95ddd075e1c4da7170914d84b5c2266e2f4e68953fa1f52373ad99e2c5d6d9e347f4fa27499277154e96af3a873a5ab6f9e3b4ae96af3284f95ae365d7df3dd61a5abcdc3ae2a5d7df3aa7ba5ab6fdefb4b57dffcbf2a5d6d7ef5af74b5f9ef65e9325f9e55bada3ceb60e96af3e0712b9bc727295d6d9ee42523d97ce9254a57df7c899794ae365ff2b074990f1f331f7bcb7ceba279f126cc9bb88979938fe6c7a798d97cca4f4a57dffcc94da5ab6fdef413a5ab57b2f9137795aebe79d74fa5abcd9ffe2a5d263e2d0c7ba2a439a5a4d94449732ce392e6b2a4f925cdb092669492661234bb686ed14c52d2cc2a695e9534ab32cd27315b9b94fad1c0c7c8ca8a69c662ffebd56aad5624298a345bce5115bb66666666c4872fd9a04a999f222da3992c575a566f9a49b118d27ff47a19b55a45ab1511490e89a2d0f7b5acca683e615b119f9d8ee3b6acca28f671c2387a46197dcc5c296f7d599bb16f118a3818f0641128b73277916565255fd3cc3716cbf7b774efbdf7de6bcfdda2ec6d20fc26b0d22e679136a94d326348b11ffd65f46a15b556442b72881485c42fe8bb97f921d226cdb6db326aeba135f621f303d426cd5f5959314d33168bfd7fbd5ead566bb55a9124298ae2f7c9eaecb6acda9aae5c0ac295d33b7ddc159333635decde5fdf69fd57cb9ed620787af2543aad45efc8912347c2d3fae129added6239ed6f7e369f53e4ed8d6339ed2dad498567d9cb0edeb3151d3a909df71c49f188a582c85982c9d96f00a3c885bdfeb5d8c0696ed4a9bf5d5666cee47e883bbcdc3366cc335b7a71f9e68cdad37422fa4c1b28d7a7a5a0a676cf4e969b04c43a3af0aefc392ebacf1fa8b3d30c467e7f0dfe947978873b0ff2dfd96306ca9acef162d905dd34e36a55ab51062908ee371f4d0be876009470f0dfc875d03b0c9f736792cbd4ba55229865f18bee72b896159fa404c69cb28b501cbde670396c5d3d47cde3ce39da66611970ec3d27bf6b73c6d4db5019beb000dc4a5e77d14c57fa2ad8706621adf430fc461f7f55411044be0e5aa8d57d37d251086b45fd0f6baee387a6827533579387a68fd11cfd0f0d18d6f71f46eeb43cf84cfcea69f46517ccf28a3f9249663638a3d0c8ae2c3eef465d3fb4587fb379bf0884f4f0ccf9a7c69357ff7399f71d8d6604d37778512675fdbda5289b3a5d271f4d0387cda72dbce7609e3e8a1dd972ca6690b72b760f7cf7a1d7731ed4aabf7ce71ef6e77ef69936d6e572b9c68dcd31cde7eb56dad7dcf3d6d190ccbd5f4ad36c616c2d326d3282d095d39645797e7bdddb97f23b72df72967c3bd6b72dbd3263c310096695008b987fdda98a673e6ec975d39d0ecca81b6d9302cbd4dee4a5a4d6e5a6d7ac25a6b6dcbd55b6d321deb0bc2f0e2aeabf5d55a91d67ab7f5f4235b3759ba1a7e80de7278fa364052a19f5bfe3215fad9c964beff32fd0beffcebd56aad5624198a62e9eb6cdf6bbc1720b6e11a0fd396d1d37e64eb26cbbdb79c6b389bdb9c9090568fe4b6b6b3b7bdceeb3c7cdeee7e954228d217a72f8fb791caf6a32f4ea429dbdb10eb2f7d41a26eeb99a159e57b1b5de64ebe4061db0e2da3ef99e9d3c84e256d996928533c43f3de1dcfd0c0f769a57717cfd0eefbb4f0dd2d9ea171ef463c436bdc9dd617f169936dc072e373e6879b9b9bdcd98b69b0123e417c923f7c72d9c3270d5683cb2d2c6daec46811b24fc5b62a084319dd694f5f3d5b43bba001e6d6eb9276ca7daf0849314d88dcaf476432d73194e11521c97cc26492860ceef4dcebf129c3621af464a658469bd6f60829dd81be9054a5d6b035b8c634d89132e4c833345d6e8b69b0230f3892676cac729f8606bb1d3992676c98b23d4d2adf1a5cee8e69371c39926d7c2d2b1deb173a93816930f279c3b56dc3d59a8552e922c029f763ed42be06573a7d4b892ca158442c9e502b394e474e662b6a0a5f73325724b6d5a0beaa29a91ebe66bc785b8d0af7744fe18bc23ddf49dc6a19edf16ec2af9651ee21ae29e11ef0227ecb68b7ccb6ccb669e3cb8d5bda745133527737659acfeef7bb05025126339943dab64d27cd445d984c63fe4a531ea98b7114f3578e59a42e4431cc5f29e690ba08c352feca3097a88b5229f7579632485d80fd9560fea88beff3f2e779b9efe58ebae8badcef32475d70dccd5fc9e54b5ddc6bf357de6ca90b6b73fe4a9b9bba68aaa2fe5de74a5d7c2ca6194ee9447cd6e39dcc707ac236e969b09cd50c27c49796f04765d5c697bd96f2a4c162e52944eed3f100332e0548810757d8020598f033646602a9800a219801145240831925bd0653107689839383de727ad6bf2dbb8ec3b61cf6dc73ea2c02f61cce417f318e1c756661585bd65baee16c6ad708f90152a654050b09c8f36be9c09249aac2aedab43f64fbf0a3c70feb5033592a6d20bcf76a0e92c54ccf238b46d8915532155204a45c041d59ccb781886431d71edc3215d2039f1e40201b01288bf9e3414ea6b77c870094eb4d38c6f8be0f02247d733b204c8ccf04a4fdc9ed88e35702f2f4782c152204247b3c1e8fc75364e76672412d6dda7ab32adebf8f245bad7a3badcf37f230668a6b52d24dba4937e926dda4ec9ddeec8bf7a3553c8fe70b420e6911c99ee7095dfa5bea4033c52c204feb63a2ea116dd28b55a7e84627d3c6306707d91bcfb337f6c6a26e077941de6ff9a16e9ba3776fccc1265b7b1bb4d7bb2d6d3258d26cf9be4b9aed461ec6a45c93be8f249392fae1b9b69fc7f391640b7ba6e95d1cbd24b29ee6918731575c937c80dc8082c0d2fbe1f9b4e9bd547a3fa30e9cd0500c8bb9202ea85db87be784da65a85de8e9f17843f6c5fa783cf685dbb12adecda107dd7c60be8f245b2d1e8fe7eb21cf7abbd8fad897ee86dbb12f4366d0815af4e663be2516e5999b4ba3c733829b746f37e916f958da543df5f36bdde382ac8af714fe3e14c6277cde334d4f0be4f70f7ccd2e01dc12a6691e1ec6fc9d1b2a3a4ae28cd4a436413cf24073902f86d1a677d42605ca272dc27407f919b9f780fcfdc6fb57ca6873289f5c104ff6fe79c0dbf174b2077493693eb9a0ecbd0bfa86c8a2d6d1937e7646f2e9dd7cf8f472b2771af3bc7eb520fc3e119054880f82649a494f874bdb04cb93e682e557ba66666632474b5a154b9b4c9634dbfffac5874b1f58c40d33226033d471f4d0c8d336f169cba5ee050ae3e8a1954e62d4b9873ec05bf03e043ff0b39ccf7a4e5b060fc396b49a5cffd55cd270f49430a52de30e9635d73146f7fb51882777ff4e3795a77fe5cd632980d24fe2bff2acd964d34b77cc01c427cb19f0f4345f26c1323c792acf9a4d6d2a691e05d0dd05fe96f0a903cd20a6d95c6fa36bfe07819036d8755d17821d08a6badb751deade0ebc240882a60eecbaee045e10bc6307de7b41b1bb20085eaf03ef05b9ee822078bfee5e8c8b60cdc2308572711a6e3a891e077697bbe04f77bcf74efce861db1d6d8deb276fcac29e9ab4cee18fa8db3e5c046b560a6bf877d54a55fec4752427af3179eb1e0a90c3de572239794dc95b57b9dc77dbfd0a0ce52400701bcb6d38c54bd28423870d886f4bf1f236f3275e046b1672dfc596840a359a42aefb2d919cbc067c0b86f2c76e2b81f2db5e29246ee2e5b61638c54b98b7bc06179714afa106d96d3560db0afc5ae1428d26aebba593d7786fddb6024379fd45b0662e687071394c4bcb4b0b6c2b82c56d2a00c0825550d85b2239790debaddb588ea3824753774b2427af59bdd5e23600c0566e9be1368ce22a295edee622c32d33b4000066a1e22896209ef9f07d85b75f956e696aee7c88efdbf0d55dcffa18cf811ef621fe76631a079b1302cd2957bb35cf46e9c322f78ec32b8b6b17b76c9025f1251b9fe89d23c50c9ea6954b33b47a2473a7d932dc90b9846ba58ba5db107309d76aa58ba592982bae7d0fbfdba87d2f7d9f2dc34d06bbeeeb6ea33369d5c3340b85243173b856e3de615ae7f30022b9c6dd46f7912d9b52e57e00c9227dd34a29a51ce52103618c962f90345dcf93c5dc660b0540d8f672a794aedc73f7fb216bd7dc22a98afe21b9da3ec25a761d0f4da98a2ad2b1bb622d3bef97ae78b81bb95beb143aa22ce6a6f9a47692bd11b1545475385c753c5c753edce18a39aee34c65cd34be7702e8b81f8a8a8a8a4ec5b0d4a7f5966f23bef54ccd5e876fa654450781271042841d9a0aadb5f7d485b679da31c69da9f92e20a4f4deef1345925cad5a2dfc6a2320b9dee43b049e2000e5143c74102122929477e47bee0443c8c935a85f83da8e04a837553c4d772c812fbddee374e877bf35b897f002b837a6f112882b5029c47d7f1c63dc7734ba9b7d1165c28bd8d6033ec4b74c3f4e87fbd22faec11dc40bf8c6181c96d1e6872b509bf5de48807a937f6970b80661faafb91184b4fe001a3a329253642a24083cecbb73f4fb48b2d5fa4df39769d3cac80d82200882e089809981f81c0be065fb6bc70380cf01eb51e63b886d3df71ffeacca0cd2aaf4d8d3190cab52bbeede3b21088127db5f21ecc833642a2408474118cae73327a266b4d979f76eefddb10037b23d8d1d5e09607f5fed62ef61196dc6b8b6b1dd3da0a4a511bef0e4db0079de2c3e7c782a718de91f58d610b76881a4c9de4be1771a03fc3c8ee6eb3e42e83dac1577dc572ae1f366fa9ddeee5c49abe96a36f9c334ecc18725add65aeb38dab1f48dbfefb12fe1b3528fb3b5ac99f68b8b4f9ae66805a8ef3ea303cdf6e069f1e9633c5831f7d2fb647bb5348f3d35bcdbbe475375c81c9190c6ced42ddf1799a6e61355714f73d50049bb6105183206487a6ac3e6fa1754c53d3dc9a47cd2db1916ed74b7f82c05557c9e744c372778f376b89b24fbc6e7e7a35393f2fd9701f2c4c08e7d315bc55e7b7b5bc5fe04a9432a91b3f208715fa35d5680e89758abc8ec80038cfb5ab66881249332cd2fa80b1b2d1ba80b1b640c7561a306eaa2057d89a5a02faf12f465e5a22fa28abedc3e51971ba80b9aba9920a4b12f036410a23bf42394b9a01f9d3d8b4e07d4a34d3b84567fab3c624eab87c9d6b4a7554cc39f05c89325cfea8e5c772acfa7439eb49aef6915d3a8bf21d32eee5b7cbb13f83040d6d3a336ed2d6a93e88821234245829288b4692f509bf677489bb736ed2f9036edfd69d35e9f36edfdd1a6bd3c6ddadba34d7b77dae411b303c68836af4e9b48edb2fabdafc34eff5d2cbd23c7b38e4fbf329da4757ac963a77f916fddc4e98fbac9534e1f4bfde4274e6faaeebae912ef0aef9dc457da2ccdd85fad15297eb7cdfe3d02c0cf9a63c4e267c52962f9596f8856fca4470ccdf0931a1152f19316095af9499388a4f849918050fca4474354aa18c4fc4989809cf849877e527e52211f133f69d00f223c257e52a01ef8271db253fea4371eff19b3035651aa58911a9f2b3a8e00804f33c788053e6338452cf83cd10a7cbe8e189a019f2d23422af0b92a12b4824f3289480a7c8a484028f0f91d0d51c133f7762b0a62e2738508c8097c9a433f29f88c09f998c0e7837ec4f0f922c253029f2da01e189fab213b253e491ec7a718b30386cf0fc608143c733bfc7975ec49b84ab38cb5ca576b458aaff296b4458b162d5ab468d1a2458bab13c48720407a00f223f3e333c3e7c70e3f7864f0f4c0a1c70e8c1d1e313c76c0dc1d2d2c3a46745787e3388ee3388ee3388ee3388ee3388ee3ae4e8762e97c7e8004f1d1e2aad2870d4f953e628e2a7dd470b2f4e1e2a7d2070d37953e603e963e5e5e2a7db81c2c7dc8fe953e5a4ede2037489b164812901fa41f9f239f1f463f788a787a10f5d819dae121c46347d08e17f7c58bdffe06e9172ff0e9c3f6c286152036a46c88317f62503135c47c6a206b70f11f2e4e2e6878f1d060a201a6d50366847959edbc945e5c481e2ea08b4cdc71182f60601c6fc1385abcc0386c5747cbeccdb938f7c6c511341881b12f492e48b2a316a31bde73fab0c1bca4b0cc4fd28b0b0acbfc20b9c8482cf373246b3961991fa3161b4c58e6a7c8869811cbfc10c5d450c2323f4335b800b1cc8f900b1a3eece117a7fd14c1386c51cbec61605e5e5c5c641807c661b361478c1135e8b8d081c366736c16e70748905bcbacccca6432993d87c3e705cccb71f4bc7871390e9e1efdc245761c32fb42b6c383c78e1d4618a1a3a343474ecb71c8ec8b9616c761715a665fb4b8dc5fbcc57b506f79cfe9b2f798eef29ef12fef291de63de06978cf7717eff15ec37bbac7bc27751bdea33af717a44a6583e56997145661b394f9496a19cdb6470ac76a90d1eca294f9396a19cd3494323f462da319a694f9296a19cd2f329a5d6434cb6434b7942d4aa095365124a639ed72baa66f144be48e7601575feb7ae7388ee3388ee3388ee3388ee3388ee3b8ee072082a82104cd0d5bbda93835a7eae84e5d57c4711cc7711cc7711cc7711cc7711cc7719dbdb13836c7eab03ad608bbc3f2b03bb687e5b13f3a93e7755dd7755dd7755dd7755dd7755dd7751de7dddb1d72812e911b7485eed025ba45d7e81e5d246ff4bc9baeebbaaeebbaaeebbaaeebbaaeebbaaef3c47beb9deed13cfda37dfaa7817490bef590066a22a1f5e9a016eaa1262a323a424a2a62e455d25c0a5b64d169310266470c0f183b38f490c1b3c38f193e323f3df830ce8417e90f17882f08b10629c48aa6d5a6fd0ddb6f626d5a4b840810d09021b75b90204080fcfcf8f8fcf8c1c3d3a3c70e111d2b2db37fd162b6ccbe6889ddfa45cb83d85e406eb47e68563e42903f6a883c417c2db33d80b0bfdddddddddd6dbd9515d38cc5fed7abd55aad48f245143f590bdaf511b78f68d31a49325204a948d251129211d251d191119151d150119110d150d0508bdb422db3b72d6ecb11417c3002a487223f32493e33907eec70c423c3a8070e453b308878c40ced8069997dd18271d86a8e3ac3515b4a2c2d3031307090b1c30c991e7ce0401d2376f0d8e9c1f3c3e7074890cbd2dd860011a94155a80e55a25a548dea51456a99bdd56901b34283e92256c3635e36b45eac6e205f60882d9e652d3e0b4000ca9ad432fb59598bb4cc3e97d548cbec6194f58896d9df50f64dcbec5f948dd3327b1bcace69997d4cd93a5a665f43d93a2db37751b6112db3a7a1ec1d2db387299b47cbecfb566badb5d65a6bedeaebbbf8c2e7cdafd37ed1e26469816baa8e951cf3a5e2c4eacd6daf1b2d9a9510e44b0dd17379c135415c99d7226b71c13540b4b87765b705d7b478c9fadf61d88f4411c7126365f293bb3e3333431ef5540cf0df4b37dd73ef4ec2a46c9590fca04aa1c89369144b3f7835e776bbdd6eb7ab7375aeced5b93a4545454545d6c7fa581f7b7b63adb5d65adb3b494949494949b7dbed76bbe9e8e8e8e8586badb51f8b6dd95b6b9358bad6e00534491491c2f0a84441f0f4fb4e3def94e34eef3db5f6b43bcbb832e293128974288c85f8a442a597f04983c0d74781bce6e8edc6588b595a467bc58cfdd55a91e277695da92b6dc6fe6aad48f143a92815065b8199b018ecb017ac055bc1489808a3b7c2601506ab305885c12a0c5661b00a835518acc2601506ab282815f69519564c15666c25f6147fa178b5545aab132bd224c514f1fb7d772f66da75d5da6a6db5b65a5badadd6566babb5d5da6a6db5b6d6ee274b77d7672855aca440a172c24c31112b51afc2fd8477137c4a7813e363a797401dab5eb2fe971c761c3db47a6252c252fdffffabfc44bd69bfa77ca59b28898f89a6973091c764ea656af5af4e5333c96124a7a92647c13d333660b9f56e8ce13a3129657e8a94664952c6647e90caa7ca97a95cc9fc1095a4cccf5029cafc0895df2d6dc7f9e0430f3dc8c8cc98b1c30e3264e080030c18313130302d2d2c274e6557b957c127b0cd8796f5c99f78ce67a6896d3d9c6e3ee7b394146c93313dc504b6cd186fe2399fc562d8b683f8d8fb3264842ff13e0e38948e61c050015fc6c4a87c57818169597b4701bbed29501800cbdd492cf353e484657e924c58e60769c4323f472296f9310ab1cc4f5109cbfc10c9fc0cc9fc08c9fc04992bf84f8182a24505a68cc1304ae010936162879419a64ccbfab0639c1cd80c867b68594f877dc0394e2898e564f161a507532636a365bd43cb5a46cb1a8796358c96754ccb1aa665ddd2b2bedf0448f2e4495b75742839493938483847f5c666bb7183864608216ad408c21644cb1aa503a265fd430fadc33eae0e1d2b3939260e4eac65b5dedc667bddb8d1a2a15909210459a3861844105fcbea0b18c66103a2c463f7c1871e7a9091993163871d64c8c001071830626260605ab8a7bccf3243c30735719896f5635ad6c7a1657d192debdf443fa56c69599f2b7de81718dbaa8e7e0f35c76c597d5fa6e2c45a56fb33eacd035f252949b56811b235a1b79724b354b74ce5f0c476a5d7a5445431414b3c293211cb1d9c882739fe945c223983973816f19110cf031411665f1fda946c22df94c814afe07ccb1326c234702f9a6e4ab14410165d55f84a882da31b13c5209fd14d11c5202744142a98a2c84345c43940219260f85288e205564472095785f8c299411c93be15624b88ac95451c7fc86ef9903585052ea85dea6d775b5b2b4eaeb46cf102c905f53f214fe091bbb91086d4eaa83d327defb4b53a5687e591e98e4c7384908e8c8a86848c8a82ae1097eb3cda79a0105405fd0786a5708cb91c0ca5221d4f30a2d08894e94d47a653d16928d393426d946951a64154057df3e81f9fde691efda3797a87d111468e8c8a2415d51f7548a6ef5b5b20d627d3df1f3748a6e780e4ca438b541d39b748c5b91122a6dbc2d46e6befe5686d6befe5b8ae76de077a1f08964a6128d62a8ea6533d551295a2b43cef8b96e78a92d092f3d65255cb73a543cde4f9d59284b2be5a5782f0f180340969edfba240e407966288f5a4474056fc52ad158bc51ac718b4b66ddb223915d9c2b2d271accbb22c56b328ab8e279292e418034551a831c6b70352f5dd6f07e40a25212121a161492d292929a9b11d90b58584c492909034090949154da996eab482c1e247d2f50ac086e620d377fec09248cb1898d829a5e5c9f2a2afd7eb45495412244890a8288d828282d2300b83c160b6339d35ff6f673a6b322dcdd7ab541a59638c8a2949b762b0461dbcfc917c548549bb5c2e97abba4091962dd204759272d1f27551244bab462bdb775c58cb8e66b3edb06da9c4d48a5c89aa950db24472ed32cdcb8d2d1055519f4355542f734054056bcc8124114b28263992144d50c55309ee15499224494b730b6f3ec2dbbd11e4f99cc0f3e97b2f29b6be3ac6b8d70ae479335e952410597f4455d412a0cb35c6a8e6eb0433228764daa40fbbac34f7bb2425222104b29ea2c0ba5a122450505631aa08437fb12c498c4b6881ac18e9c80868c8ad47ae3b9547bd39e2860c4c0bcb8aaa385581ac78956253525252ba52138ad8828926630e21f9faf004e63a2d4f919628614b94e812f5fbcb129728118b993091522286718912319615b15352c4181d9aa74dbeb618291769191b7568b23431ead038a5c66aad5d0a2e458a9b22450adb35458a1494c4a289947ae204bdb11413274c95afcd30e5c409d31469a9a282028548cb1429445a9ea418c3a42a545450a04891a215638554a1628619605a5858b0b05d4114638cd8ab159e5a0850737d0a152b6a7c6a50ae3fa580ac35b8ba825a9666a99ce9b4c997aaa02ac61864abcb1b96a79831cdae1863d0299015b3b000408b31464bf54ca74dfe4eab1833f4803cc5dca22a4e32536b3a6d70b962c58ad58a15aa152baa0a0f44b5765bcb75b43cbf22e9077a1dc85db071424ae98d9076d80f4f9656896e728f3c984eaf37373bb21d7920c915df0684dda803984d270e4a6f9bd68e33d9c3e853cddd68dfa237c6f02a679f833dad7663570eaa4c5599e24b55506b6fb51d08e9adb562b6b6fc84b8b854057ddfd6143415abcb8c0e367f7545bd0ea8bc6ab3561f61cdf4a6f080a49f91a3ce7272d423b39e7a7acbb9d109d2c08c8e3ca0c8b43a0bbf20643df56abdf5a8efd671923d68889289019136e90cfbf27d24d96ad13246cb17c8ef94f9867d310055b157c20d14b2b5d40a65a62a646210a44ddaf6bbe525425a7a951b9096fe9b81bd79442828a847460f18bd30406445140e13b00b96801203b2de0e4189810e3c119501b29e0ac9a7b5d6a2d8400ef24929a516b543d6db5b0a136eb8a1781d2f44f125031b4651a5478c493c79c2cb492c75e0428a780a32944802693112010095f81da8f856a2eb082858222c03289744343de05522962082ab25ba8e4e3e13b12505937b228a36687d2eb1258592fb12451b90901051aac0421145108c30110b092f925f287da528ea74582499c0dd12e22b0237268e5cb026c49611c87a9b228e30b8f484d87201596f290dab7922c544ac042d2161ada82a854231667b9ccf996cb18918c27a1a0bab8b0779212cc103f93c8f3669ae14d36071801142780d8140081b80810584fc98a03580041a2a7401081a18c208862a40bd7c7ee57cae740723f0d9810876703282480a3e54189002065859908204564290c28d2a89ecc440020492c488e406246b0847d001c913483153215190814f144e60822870005585286060a58128e44809214323aa1f64d785940c480f0b2916909f1492c892127600052194c4000a3b28f1011460b07a01144cc01222c74c854041074b0ce4890c2c219028a42a141da56e45452e205f990a291a821a0399ca5448d10b542c2051990a2922c190a20fa8b4508481214512200922bda41bf23bd251c40a223926ac50407e4650e1901e11161009ea8024022498a99027d0405502b2cb54c8137e62a610268cc10a3df93ccb97145e1a54005cdbeb9d87199a2f37a62afab3b95fbdd778afe30e1cf7cb5d1d609906cb67e5e1b31570e590effd217d58028f6cc275d66bcb81dd95405bb97b39aee3bab9ae032f67ebb51ce6c07bf1596f5c0e03d9e1b383ba243190f496cf9bc4eddc6bbadd6eb7dbed067e644b47270ca4edeeee1e2a3a4a32e263717777dfa406cadd407237cf4d3aed4d52e7b44eeff0babbfba6de806a501d2a0a43d5a93a7547dda93c3e40c01f928cd49cbe6581a14034c8130359737ffd6e716120a9102520e5fa93e33ef266bf83565c08bd2190f5a806f282480f88a4f526534a29ed9ddef9ba5bdd49f5d6fd35d9b7eeeeae3ab4a8bbbb4f96eeee66c9dddddd9d1754df414db65616087f64eed63ea4f50791cc3d4816c54ccf5507f58ed73ba6e7b53ccfab4949499ee7798db2b81af1cc16d79df33ccff33c4cd36d3dcff3bc3be660933baeb334b6ecacb59df7aeb4c9dfb5b957b678813c69dad2d41a36df53db5530094908ca627ea9834de9caa186b4529aab4dbeb98300593f08588aea5e398ee3385487ab913629e5388eeb6a7f60c312e8b95cf1f50cdf7aa93c4b27f8d34dbe7affe42ef225a5e924e5e9acd2e4aab29f2a4f8e2a5d5f95adf25ce1f3f6a750914cfeac0de19de4fe10acdc3f692e9cfa893aed04abde78f5738666f2d369a6cf9860929f70c96b4394b2e9b52150b2e943a8b209b70ec3b64a2729c1b3caefabd2bbaaec9e2ab9a3ca7bcb267c2acf9a0d9bfbb5214c727f08536e7c9e7ed2366b364a997c6d8853263fc4789a626260605a5a585856564c3316fb5faf566bb52249f1a366fda53f196f1acbb39660f97da55892abb2f56ad3a48248b8652e559e9d5334ba93f82473288ae2f77da6679052d384cff0f42188cf902cbbef04dd3f1ef25f0fb23b6dd1ddb12f74b6b3b393bddb23dae5ac16a95d52a9d4695a39756f66c6462b87e1695a39c41629c9beaceead30a52af7deef0d35c37fa4179e9ff775a99f5f267f92390c55a914189247d54c624acf550ecf570e437c76f768066bd2ad8b414863df09c8d316fde321bf1e642dcadced51e6ac91b100dd3d7c4fe4c17f37fd64325d71146fc35ce5dab4f6cfebd5247b9369099bb1b616c27b1a3b6f7a89d2d728c5b51279b27c5fea6c19c795ea278c68a39567681ccfcdcd4dd0cdcdcd4a9542911c582be8d5ea75b57661adb76c0241d479af3dd519ebb8fa5ac771acd54f33e4382e5471c2a7e97dd64a954291254a4b1fa5df48e928522ade1e863509113a6a5197918e2fea2252f2743c5d1c4de75c4a5474f9c8ef7b51938aa752a965fabed5485293beebbeca8595e3c0ae725e377a9ee7dd86983dec1df4bc12c7791c573f53eeb1e338ee350ed76896fbbed249536bed2a8ae3790304c1d7c0d37c19c4359acd366e0e5f036f329d4e9b876b34adecbd464366ef35ef3433364eb2775abd651ba9ece19996038ea08223a820d3d45cf36ea3cb211622d485dc9dfe5492ab4f4401696fb5e0aa15dededac8b43c5f2ed4c5c39486b84623ced868d1888d69780f74a998e21aa5b721668a6b35fa4a2916c3d2474dfa19f0bbd4a4b5fa4ecc15d76af55cbd8d2e574ca949dfa5dcafa30e7d9355958584d05a6badb5270d97ebe9b30543db8ab6d9e36d27c4a98617448d0322dbb778d3c5eef4daa933dd917b4d144baf953a8f0c3defb5eea56fd526cdfd5efb5e35ee1d4d97b9569b3ec8fe8702b26d5e7bbd5aadd58a14c5af769bb17e1e085faf566bb5224951fcbe3b049969f601b7229f5c3f33c497693622723ce0d6d241448e5c3f442bd36891cf0e1dd912095be0aa46ab2779e35a786bf6a70fd71ad74e5ea3a16a3493f74dafd14ace9d3c4dbd468e5fdd554bbd66c23510d76860edc3b4efdceb275cf330adf53eed542be1dac534d559af9930cdf4970bd74e702dc4b4f0de53b8464bbd74167e9f04d7566f5c2b9de6e15aa946f293d768dec59398467e856bdc09a63557a399bc755feb12ae71b572f7de3e5771ad7fab09d7c27f97fc5ed7e6556f0dc2eefb5aff36eefe3e1bad4c5d40f07b0dfc17a7a2a8d4a95b697335ab189a0100000000d31600203020100985a22049a23c917b0714801184a65c62489649e41888518810a3082100000000008c00489d0800210ee800a2b8be23a083d82da9808de0459848441bf284c38d49a73b9fc282d4698245050e8708c73a98e3ee157c357d99e877f6aa5af80e7262066836b99995059957a1e185bd1e7550c5e568b084d251f93ede1e878b432b959db8d637445d3d2dc2846d01369fe39304aef28a833d5b25d4af1b7762e69c6606b4a77996eaee5cbb908ff5a1bee58bc06ec28f80eeeffd08d7509f971efa1e699812c97447fd268086eb73a0f12c7ab061d59ca5791983f42937c6acdce6d41531c2a2fc7ab6654dc5d132d9d0a500bb429837bd309803c9721bc27d01c0303a5e88e30b97b86e8ec313feccd3aa95ef16901c831a451c415640f7f535c7f17429691d3db4727f538d5361cc1f1d1243ad4f99999bcc9f086917471e546554a18c4351c80fb2a036b4097d5de4932b7c0bd49075378df0eac12554811040939f0ec2afc7da57f0c08653d87433b776751760d9c5546d2d58bd289e16b953c40637361debdb55d8e03bb5705b56b99bbc37d66367c1b8b4464ccc48164d9ad0c8577c34c3e9c9be39732b2a4efd6edb7716bd8ff86e96f711c5699e049142ee9e635d73d56bb33397592bbb916e5f06a12bdc95a1bfd86d08dee12d83f5800d56f7e6e55e86a97a67ea9ff105a8500f3d91a8271578549f9e973150fbf0ae8591f203de0e8a7fe22a28f7800faa5d73e8f836c8e2672eef4059f3a0b5e34748175e8544767d33330bd060ef145b55de47b63c57d9c8abf0a34257c47c650f1151025d90e2e13455b2e949e557024b5bff496596f44470bb3273183c5b59b68882e7866a7216cfddb5cb36eabe5363214f3ecff8fe4073075cda2d214531db1e34f7f55b64881cf58a046df5e8c90aa0824aa02bbc9a136193e03b98cf2301411446e3291dcdb5c3f6110b795195aa854da6cfc61d5210b51636f9785dae34371e98e49b2efb603e939eaf57d034375d0f8b42ec22b62cdad58b5c8437e432852c94dad1a41b6d8350b79882649b0e451726d35119cb61c499f0bba7e6fa3ab6e047a01b8adac23b1863332e8e7074f3b19a1ba8e2f4503ab52189ca14b8ab726eb28f9aa81ef1d8be925d9920d73feeab2cbc7cbb56759f8246cc9a5b83fe20456498d46f7ecfefd62ef79361969fc27ff2e22ab5025698a34d26b3df53a0c52e469d6c3ca6cc288e5ba48d9ea7bc2a6dffe370a59ddad6ec9d06078b200fc7b5b1f5690ff106718d9a5f99a738979d998294cd6e7828d866f2960d8232fbcfb1b9996116958ccea5e29c1254c674f05fee1c3a62e32832b13904c4e3844bf841421022011672801e1b9aa61e0d3d1f8b7f7ab6a04db6fe8f175ed93aa79e3966179dc2d851b8e87b00e7b111d7d54a7fb9b09e98f03706678220aff8aa89e7366c0a167254dbece461ca43bec54c98caa051eb964e4d8f61057f808df2174b68ec35e18a17e2f2d2bea7317cc31a0b1069db9923f3e3320c9d46238aa7606cbacbe3634e9dff1e7c2685a65bc824ed0eaa5217fc99f576dc68a06f2b78bfe31b011917795d4751b9f941d53f0c9344a05a7f34ce51043dfd5aa0a588a59dfa6922fed8131b5eec2e7f5bb2f99664610c84fbbab8da2f8a36ae81988598e088125294ef1bf2a2344d6d605f9b275e3f570010ed02c4520aec0c75bbcceec8a4acea93ebfe1c9dcb7e30651d2fdb566496750018c5cd30432f0de1b66f9c8aeb408e5e01c7245b3b8afb0ff1b19d3c8fed59f71a174c9a3dacd17f58a16369d6bafa4be467dbdd936ca0ecabe3c4b18ad18289a28c13540941a3cab9433deab7e5765ca5c9e97cf003b833d13ac7a892086c22db583fbf21dad8e49a9f00e5ba72ebe6021639e73b1fd4792f99827536518e65689a982b85d29c65d9d9d943ce6ee9f5bb3bbfdc1392803721c465a61a257d3546ebe56b85894a53c6e6d3193ea70842b0e240b8fb4c3d51154b6519b94baf4c3e9d065b104917c18e237048690e54f22fce712ae0ef5b710b0d0838580e1c7710a7e7eec0ad56679879021d7e3583185c4f1fce2cb61090e217c8b946bb0d7ce5f70d070fa5a8b0d2f59442d7336d4f0396b70b272f97c211829e5c35a39815e70365a7d6fc58f2502dcd8cbc1c78d5b83cbed89328328a7a08865ef2173c76f1999b641eab77a6a7b6fb86784703264fff2d2272e1af5ac31bd1716b7cec5800266f0b988833a3eb60c95e2c909f94a54b66857f4ff9a6302b97b46dd9ae7e38feccf9d747620854cbbd2e2242a17fdcdfdd4ff6ea1b6b9cee1dd453eef62981fecc64566f7a3f06cb3680132924d0d512baafbd88943ad44443828ffe63cdc7c437baca202e4241d745fc297dcb0fb6b80940e372cf5b0367f4ae3bd0c075aec9499aa7ed36cdbdff38c2a74333423080718dafcfdd93c168e0600789c5ab0d4819554c4754efa23765fb15f66b1c6432414c3fd04b8e769fca0f421435e8bc51abe6b5df290ba5b909382a02b331a95c3a0469f8f94fd5ed009b5e7ae3e41445712c5af24de00c5a30775703e8344d00301395fbd20de098c976502965cb6ec04183d04a98140148ac23b580e2c43c8f7a986fc5a5913cc2c878ba98978550dd60a05d999801f6d3bb1534b053953c60e08caa5ec44f025f83110f880bf625f968769599b4b018f73470e56e63c5a65bc161984b45662fbf8485ded3428701e9d6bde0aec9d0dfd4f99f74cff6762091e5703894047ac939d5a69a6ee9eeef3320bf02f7302b0b037407df73729f037f7ce74c27263927152b8df98d495ab06f32b261dd1cd5e19f8b22461c18da87b07440748a9ced5442ec2e66a84ba2e318aa1bcc9b0cc9007b8e3739e720c05a315c22746d02948f0f0255f473c1d648f375bffa4d3c6f36f2cb43439c0581f527578dbc26f1dc1f530710c305714532095755a479230a9e2988e294161c716fca16f3e0dfca708c2f399435602b8df9947a73e938bd88351a874f14fb2b42c745156757bf5de5e524bcb0a21e83695ed08f91e08172fe45026060f4c1a7d8e11e16cacb4414afa5cd90fd6f54907ffd04861139f8b24546e2a8abb9c94af59db610c1be641f879ac3b8ce1e7b464b559e408a332135506457c8b3610a9fd523717a470ec5627ffb82aec65190b54ad67f78573243ae10408b2487635a1092e1617352d714bee330e9d3e8276e7c39e81bed6d7662a7e058452b6a6b2c752f03b276d615948350eaeab5fa2e8e0545b44c6503876416408412db6d22ca60164f2c8246a2df907e91fc36f7ce52f17faf6290f91cb0e49633ec9165c04cafa2c9fe600187347c9fe5f42389e4dc790608fd17a5a62872935d3b94e3e8c39e6d9b2b5a09a533c242563458aa1c4017dadadf96e5bf6a78c987ba539f3f2e5038cd53440350cad335f140f653bbf8a7c1451c8a5e44deb2d94f7d0f89ae154518cab914cce4228ec38c8992774905313a6140f97612d79d1bd2a805db348cf720bfabbaf5fe09137dccb035f55ad36f4a03a81b6eed26ae893441f5065a68b05de3574b9e5d5e2655c993be0bb505a1ce35977d508294b8db14543ac1026434d53c9513a176231c13bd8bf2743f7ad22d96c9db2745dd2342eaf72b8d5ac1a63230b430c4d407193b4fd7738d294dc0f188c65c03722437b76daaf52f7a212260ec9f218c1cfa6ce0db8a8fb7f367794634c270000959051dbfa65723d9ca8f26213898f6025d48ef2cabaeeeeedfe2ddcf2f93a1adbfcea277bf7d8ab46121c15df5764162e22a354e03d35631c5818a580757b015363722ddcc23497dfa979ae6588af56356fc4546a5af5620909eeaa7b07af1482215507855fa826e33f34c5bd5f4544d2428368a9a8b0425390772e54170e97eb32610202425401396b9fd3205279bd98dcee7345bf730515fa2fcea22afce56d55c8ef5f9f40b7a70c987cde64103528b02583fef13cd934374e0de476fca914be6446805ebfc928e2aa030d8c8dcb11a6e88a4eab91a6931c5900ab1d61bc76e20714d4abdd1e37cae8798fcb7b5b4bab6445c1bbcb689e1791c5c4c1005c482e44ffaf16c6351def7cf331c483c83ba805a4321e3adf80a4c3463400b244b31216d8ac26572c8afbd3845250c4e9df37b4b60f2c7976a8f0a62a3994bab78ce486a64b3915d72a265ba92e995d6c40bc6cb99a8b62af72dfc2b31914a18b4d6ec5e3978142587e0615841c01749356618b6231aeeb4ead9592977db7b1af51425619af71dc8c576336dee9f0bb446d40c2b7379b601edc77d8cc7fc86eca34ee86211dd5d0070077a74714308c5eb14869b3f0f94c0904f429a532d85b916e34a074a82526ad31a7d91bdeb3cc7b7daea36708c26daab1bbc2896e9e3325f06e03699a35b641cdd900574ab8cd06d32003765c50853770f27ebe81699378979b2846e947943cc9561e0b6ec829b32edd0e6c9b439cd23d3e7305fa69dd33c1980db650edc9671705316a0db326d16f36504dc2ed3c69ae3650108372fe3a2c5bbc91b3d5182235ffa5ba8df759330e9ce229f3ad0a20c88fb1aa6450c26a8432fcf66cb4dcaa06940a2d0a773bf6be4b6139e95e59a06cbff5d5b23b7a2205ffd1b1fc09c031cf063212a45d1ec54947fb266862c63c63f21535917c0759a286e8a047342854b8b2c5362e546a58b7814dddba2104ff04ba52657d9fac5f4f2f1204ee7a25ab433ab217f1bc6dfb14ba485c1eb99b1b3587c47e76f7b87e66c2dea6bcecefec9ff8068d1785a57269cbab9a6a725a245892695a4b6c1781887e64ccbe96f9cdcbf49ffd67bee0cf9e18fa6a17be051ed2bdd1fd1f6e5cfe83a22e8fc25b872166e93627727d7b4950bdaf473e97129e7e95f78829e832f9d43b828f463d2b96eeb6cfe2e267df6950fc0972a8d2c9818ab42cf867462c417d483e306ef58165e12627383e030e0174305865c0b9474e01bab0aa4967bea90837fa35678a6c51f385cd7d5463df9cdb39a7b22b468364a7926c4a062d1d0ed4a1568f191185ffc6843ad7880cb5c16c7758d5524fdc7a71ad781ba6ca517bfe92711cefe7de9aaedce17316eed61ae5e41ba36726484c81d45b94f6004ad1050796e93e6fa89051c2001b0ef275da63fce4b29ca03fb3ca335bc304d2370682f29b4d89d28ddabb165fd4fb6ac0dd14f5cfc1db710161e5226bbf2ecc3061ea0518029f7327739d081deaad20b9fb07666d68cd73a52b1d5527961201ec528681bb7d8a92df98d6855d89274c7378dff2f5ef8ebe4d9db1156f8ebd94af835af750ff95701ab7a5c6e4f76b4f05092b2b2059ff0b2d685df17ae62641ff1508cc63fca62ada99fdd06a04db0a7d22e01f69ca884c2309115c389d393745554784639f9c0221377b71a112c66d407516ea45d21e11ecf4775592b127e60ce9eab03d379b5b794204fee4b5f3d4a3e1e7ea787b024e5b49831f4005d676a05ba58b6e80178ddcb972e9ca7120df8ecbd58907daf457364569236782990ff0e6eb1684e14834cc3764457913c30057a9bb927fa1192f3c4d738c777d6282c5d246a10c0048711db906049e366bded454efc3da48efbf2b0ade07b87120e29803cc18860620488742e1a8e9e7cd1818594d82fc9af076b3c896504e23a7e8ee2d04d5c5b7a9d41f5056835f00f72b000eac3df81950b236b12642a6bbe624425460431e9b4cdd694626c1de368972e534085bb7b39886ec75dd15f352ba49b6f3864bc8efbb082fc99a350633d2009e9b61389285a00b14de145a2eaa3d878563819d1e97a18c5f0ed5fe18cf48b4a1a6c622061b646ce842418cf41f3a15373e152f2df8a687546a74bab6cc91153f08cc20c42ee2e968e29b29984b26069e6da268824d828647c09dee4ed70b9529d44427b11af0789f18cbeb6f7f6b5af42e02a777a4104ad897e66b302b68868b5e91bef392c4380c9df32d11e4371e9a93e83727c563b48fbb130caf208d075cd0a11e39c3d5487137f7b8a76cb0c62a2bc5132f9d7a44b6a85561451ee8ab2937c761a369d83cc5b0877ac10ed3ea55484d11665e7789048444da25ef3ffacb943b03682a44c4476eef7647da50d3c868243a6f5fb61df2a4a37aae021de09c2b339c787364aefb9b1baf36306b50e54cf23371a6669405eecf7e4de1cf73b38d50a470660e785d4d616e7e70095c954fce5c71bd36edd944faf0049ef8eb144cc9f0cb7732e0646ac71c2cbd4b97e47bec79f3f0866c6eb481a005f9a2badca7f0a751c4a7c9c07569b720133f4b6178d2b2cf8fb555c4bd13ca9b572081473e056513671d1ad1efe40cc8bdecc7658b6f61589d510452716c08c2d0d75308bb7d19dd5460cbee44edd63b54ed543c1b9b9c69b1f395f0501b38ab3994ac567452c7fbe62f9ccd985aa5c4b2527a644d0ee93009748ebecc9f1c412954802b3626359361329aec9f561d3d1143644643cb14347452e6db6763188f15eb16c1855ed8bef2874ce5beaaebcaab4568bbf1d91c869bed4093727d00d1006cf1b9badc69701917a7d93a11fc0c59b1134cb44c4d508773677abcc12de2c7917ef5cef85d01664c10bb025c51f1cc6c0d3981f8058dd5cb3b3f26559a7445f3871093d17afd4c45f0bcb0f8a773297fbdb3a88c25b04e2f14a60368ff7a363ce6fd4094ba25d499e3eee788043644a900b5896cc70830b7cdb08187884b6672a4b841302d19b88b3f8a5d043a3ef3e3fc4131e6b2e91480c25a6f126c800d0ea6bab8cc03be7923ee482ff8706e32d88b32dc7e8232f249772a330154e22fb39d39f1a798e6e133aaeaaa2f4667ece5e150ccf130a48b50d53c0110dea1468b6a859adce1129770525db4dc4a5dd72ed6fb52a08561ab2de8ca581ce4f434decab0ffe9856091717702fc01cd7ab27b127d04bab570abf82d375946a5aa0ff72035e3daea8ab7c5ca9b7f2f8507ff1d1a13ef9715a5df2b176a8efa5010d84e5d7dcc95d4cd0979e9f26ca2f3790bfab7b6cc60dd04f3b262d90cc878a63c629218010f43f9e421f54debee9d043075203b680ba0677bb9549d60057e11e951faa282bb151dd91aeb8c956859626e145d111047404d8d93b70433c161cfe44c4f4fc55b0903c49f9f54bf9cd3e0147ca694bf386050646c5f64006be1aae7e64cca0cca709ad44346a2e4b2898ff4b31592fe1d782c19f17f7618525c92d3a6cf8f47a9baca2c672f918211586320198637265c4f906470c22bb06b1e4a2040c2b256385a10866d6a2c439da9cf3c34f7e7772ec8893596001388d3f5f838845813f2a60403db0928b72b2708d09b2a3b3757148875a1e1bf8cb5248c4e85c738a337c407a49fbaab1d329f7f288b8732ba6fab970bba2565b920ab61e82531408e23814db262cb289911beff6a23bee88d6e87f86c97157259171ef71885f318e63664120e8cdb19d8fe57c11065a3513acd22b76b3865bf0086ae72c439c48fed85358c8ed533f8d396977594a417dfc54a2e49cc8c72ff5f4472d8ea8ebef65ff8a1028fd21d701661af2b32bdf67046560f1809b7e776b4dee45b0d28c5519943c78d117f7758e8189395931a61d9dfe92bc6c4077899f258d1492e5f9c6cfec348826afe95eff0310db2d65ee90bb180a2d71c9543c9266e3ca4775f2b8bf1ff6dda5323757055307c1ba053f9b35e4052845abd20bad138bf25db1732e2133156b02bbc4110fb9db3aa7ea6c348f7b7201f34d4dd37e5d27c773e283d3b5caf4b75a29e4ac2f992aeaf1dabf2373d8f75481b82fc765027a98b7e39931bc51ff4cce6d7dbce14f063beaf1724fdace5fbf72822d45efa7d8f59283efe5e8e7ce24737eed36a5b93989cc22bad4872b44556e9eadbea5737691b1af85f7a278760a5a71876c789673d7fd9f11db6c506c8dc2fe1fc819f81c91b15870df45cf283b4d4634f6314db245dd1edc347948434d0210a911c3776841894c407314628729fdc8649a0286e60dceead45e8a31772f2781d8215885cde12624c05178ee3660a99f3cb3508318392022e86892bb81fbccea5081c1d939b8cb1c6ac423c515223dfb31699b50cadb7fd8a6b0c24aa9085b0090aac55fe057f2b883606ffd7a3e7365931e79f551d4c08cd3d66b65a99aab92d40c468ef5d950d525f30a64d9b169375c5a717bfd2324652be4b8aa905ff60531150c45003627c9fcede2c0918942cf6276dfe74c107c7aaba7490bebeab7300b0a8c4098d50f95c5feaa27f2de312e1ff637ed7c35c5cc4af59e984cbb51523b76cafed1f27d1fefdde1a8a0e303c1d67a47487c8c61eff77aee305383bcb20851e080a693f0e21464ec244e3e47168b9340f1a0e1e17ff1c8448cecb05fcdd24970b70973cafec58832dda58e926903a5c7e9ab92d15862f28f58c6c98459c6facb7be0b68c085b991eb73e0b8c5598acc784166e4085b3bceb0ca59c4961803cd1ad7d570fbb81de690715753a5fc488ae2f2654e185ea78e85f084c5549ed6b47ae842b61c5e3ed6ecbd22cc75b9906eb5ad1860ddf794ec6bd315d19246b60cea4912edfd50914ac3fd45f23af88ae45036ad7ad051f0a466d90a7f5d064d9e0a4c9b2e168930537c05192676a40a946fc6376fa867f4807503961286b7d043488b4de9a871e77929cf29573f41a0ad2dfb95165d1d2bf035e33dd340ea3e4fadff152045d12243afd8f3fefbfc95dbe8f8646ae3ce8fd7aefd00f77069638d4673f55a42b431c0bcf33820f92a01d5eedb7c34fb80ab8674b6ebcba7fd89dd181a4e33333b55d2967756018321a364367ad912791dd9a1bcbe2e02b8428aba9f7a26967d7b8838be125162d182d6edbc7a5e82da4c88d1b0f6446755368ed0b150556bf5b18954a15a3654e57d596e32e06b1508bf4cc918abdd386c64ef438b8229cccac435e36558cf3c814b52b2ce1d92924ec7fe34d50796f64b982904864b7c5aa505f8c183e79ffd20b974d3379cc968cce25490b9d350e287036384a4ce173d938097e799c4d51a38649f0074b299b30ed1c4b4e7fb010a1b5b4faf7a1f1819b890d57525073b1572ba8eb2fc2f437d04dad46fd6d9f7891dc725c569c788ca5953a7299e829becc007ca6e0c206931df025fc016d448810263b7bfe1e2d3c8efee009b12730c71d310e0e302efab6b07ecd306f99db72faec1428da0be0fc25760d844f911b25dcfd0e521a1030712fea49726a1086bb54ce33748be9fc25eeea2c44d80f9e66ac9bc0f9a9bcdb161cd096b858d02ba093fff14ea006eaca3be8fe77b089e86864569c628fb793980c01aa354d90f0ff17a388c6fd1c929f184554974a641c24d668c9ac39a0f9395e161d020c9ba447a5d751108423526e82480ce306d9a108dcd3772c08fa0b1ca361876a15571135dd0197d88f30a9d67417a8b76bec46391b37b6340528933569523f253bff81bddb44c22a239c0d2770728d8d81e90be187dedb57b8c6e03d0f3f467135aa9f0939d87c8da00273f2333ed4f4286554aab029fcf71fc95c7432143ef0dc5d9ba1b588500a8cea1bce887be1de50a8a192a6d515e796d5ff67389e716f3dc9b21c15bc0ac6b50c1e48891e42f12344940f67014311b10a8620f9703a21ca76c7c45dd160994842972d3eeeb724ef6abeb9212b12179032be6368dfc4503df8c65209e314c01743bdefd1d6ff4f6e160ba1bb4acd0a761c2d007d99d0c844bc9f0842066908834d056fc07cd74f2847ff71c205220c35653b2840c16b311131a986d329eac1a4fb2a87825510d145774f6379b4bac46955d589ba427a1c75e399189dc5476ea10e68c1252226ce04b03e69350c9b141951f74010f07bb5580f846aac8e6cb0d28c2d99ec55d18fc424fb2144832366816d7a1a398f90fd2c92336220fcb419ec0d90cc2d4925c6025699c60623e654766cb81b8bcac3f2d01bb269ee91b681e01605ce6897f597c4c5b7c445327f3a8d8a298d5493bf0cb4a3eb5289760b452f0e424c326b9d028927f6cc8df6cbf806d4d1fa1cf639652844d5d9265f219d19b6b3421f3adccb9bdd763d50cfd57859c0d3d3c32f333c49626f18557840bf5e88dfb3416bd719d67cdfabf67f4df7e028225f2d988f6f1c2a86699b93d1baf8aa5569eb22f12507656feaedada993203477af6b18b254559e198af621b1341aba440fed15c5a8339229937afadffa74378c68c86d0a91944ce6c569329330194392151280846f550df251de1c90471b3341a555ca5148a6b550be2fa55eeaf141fdc5a3a3fa257cfc611f221549207fc09075a5f878c25c9f82114e6266c198c30efb7248e0419b4cd5ef2075438c89780103403d01d79c025387bb63ad5621cb8302253198a9f05804a036ad66b09385c837ddbc54996811df791441377bb857c06a17579004f3a4c6e263151c08939e91d04d93f45d308b8c606d64d617fb92081e76eb1c3ee156937319ea983a2f8724100a2735bbc251f009813d45c52622a7e67a4624ad18b2b2d3905d764c46c9104b43d87649411eb3e5816d8973fa0df6dac1ad41695342ab5c61746ec3afeed438018657059e99d54c459a2bb309526342ea7359aca3edca85ef7d078a66c662eca81b34d694718478825a8ba3dbc30e512b38ad92f9804701927a6794befb80016f1de3674243a31c34fa2a7c64b431cf7627351c690d582493d3f590530fcff6f1cec51d5b224c38510ea1fd9b424a7b77b93640769aa5d40ba8f2e1df2ca5aa192eb50d6cfe503821435c126e8da7736045e5476c420a940cfd70ab8f59b03949365f0cd1b94765fea401570643ab2382931fc62a1c111322c856254cf3a76d26b8463b42d356e15eba8dce7662602bc3e5d698cd6d70800aa5c93b924222527c0cb7542fd8383f11d43bc7154d955b05eea062357ed218581b1ebb43f36dbff234f6e98cd9c856838919c5360785fa0acec9c4c9299ed00e659d88ef0c38e536e51dc104b50726e99c1a5830d1ce285768c7485ee3cbc98e637688e87a52bfe1f66f27ccc4b485f0d89e0ee84eb5792a15a0de2e6b51526b22fdd97018b6cdf35030aad2d9263eb4ccf8037da12ba2ec5d517063c11f7c3cc120d929b1ca539085231e9cf4f82b3423879bb8b232ee31e5874ac10476837c2f4b1d295db2ac75f2a7a5dd9ae6a3a6c1975f18b99478e0850f557b1346cadeadf3c0392745b5e45c0436d4de083cf9148ae5b541058cf448e69c3c3f7acf95d576b3a5c7746513ca06b040ad9d4d0b90cadf2f8607de8415e314b643c2e6159db1eb74e4d7842438f3272e3fceeed52b632596896d3e8dd64fb9fecc8bfddefcb7906586c0af727c5f4ee2db0f1ce21f46a735903bc11991ede29cbe04921544275365d13995517936cb3524b9d4298011e1014504ef95b44b82a2eb26d9f49c20a252a3d03e6406cd259e95b45d9bd4ad5f6068daf0cab91ffd2b8930e884d255ec4154ba09ac26407aa92e8d0751c724db72654b66739142b99742df34a5850b5da1ceedc9a0eae50ed35061d018406c34ca0b983cec552be21d4388fc1790e935399d106c0b35f572eae870233d54002990e5a05c01f47954127dc2b713f79e067752780166834c76c58e428f21760b29820641d4237a4de9d9660a170aa3daf92569f9f2fd35ec046cd829b0619b60c3fe60c3563c07a344cdeccf75d6e96aa9442cbb8081e404d887971fcdb44ba46f4d0f66ec77934b95ccc91c43f6557b29d54ae3ea95915639a2803d935c7ea918b89a6e0cbacb6730b90c1386cfcb16e9642d052f3e4054e46a1bae0bb2fc737af05cd42d1aa37fee9bb19035c6ef2d5a383dc8a2ed8b2566628854e2e7492989b66274f44e4ac8c67508b316b58abdcfa29c4d2a97aa4afa2b55498ba04e8c39c1a912c151ccc9e6a2ee6a4c90bb0dac6318c3a04387a8d49b12af27d7fbab5a56ef83ebc659e739774a548b5bf4cc793f2b019db0bc00c37828ee44e28c263814db9f1bd80ba427ffc810aaba4422fc389f36a37e8f17155e9331e661ca8af1359298f6071e46f4f5c284a5441888a482a9905716517ccc10a566c747b3b906115b52d34d3b8ae9d0a130c879cc1189b043c56f294e8ab1c1895856706cfb1344c7883bafac1bea4a5307f0a9cc514c50b0e417455f7839d269a2e1ee592b998260de2d57677957f71e54fa83785574a9e104cc6b3d434c11fe2913fda364b05a0eefe90c3235bd0525651dd727ce5d3e93babe699b56972025d48f02a624ae550da707d51ad9093338bf3c6480cdc285bc087186a15767237561a473be2a92e0fbd0d4038c36855e215eb40d8e42c2c79ce4d08b9f94cd711e3ec203490f3ea6f4224b5762591e95acc13f4a3b1663d4662610f7257cc3dca99297a77bb985ae4f3c1d4af6bc583cc1de3d656b3c41b65c896fc27102fd34c25be0f7d52e14935a31f8a458f81d832f9592d339ba29adb92ed12365c176197f98e2518ad168c4b6186a5eac66e67120bb4d5052a67f2fe5ca123a4327aaaa56b001b243c84adc2d613326f6be7e588893fc61b4d4f09d510cfcf6b86431db56666c316b4b676d3523cb59623d2bcb59b5382bab5937527ae71d3f16747e515af1e863686f46e64806fb40a58b56b2d2eb6ef997179633f31fa1cf082d6786d829e1bd80c637fedc2846d4867c24a6d6464e16215b636e0e31724179dd82380280e2ac98762b2a093686efa5299e4792235a3c66cf77ba76856f04176df51bb1b5511fc370edaad7006e7de537827da33cc6e8de15d708dedaea199e33266b98e62f10c69a1c84e8d006789c4e42199ce9580ae4696a878defa54624efdafb3bb697270227c5dcca43decc9e3e886c1141b215ac7680e94de110642bd5c3cec218b8bc02a37318dbb6991a33ab7b554e2582e92c9ea942b0f91b646accacee5841ce7d57bc90ad52720a42a8cacffeacaaf1bcadb1d4deb4c0b92cb5aaa3b4eab900893069763c2e4d6385d5f97e70a833170e2890109ea91a60a4cb4e2bc03f768fe7d09f9953b3eb3cbd65d177620267a145872481338fc0798ce0fb2302370f85d85b3abcc03c204220e5104559f92c2e463524c464a84926128ea5332b1636c03c7280e6d11f827e489b1b7228182efa9127a74779833df8605644fb3198d6020a56dc4a8abccd0a72ac099641ee77c1522942a28e3430a9832637969c03b6672007ba61e4f8c6c38d0117314b80af8e3f348edcacb053d4635f98aef66402499709586b264026d781b631185733d359db800b6ceb7b7c6ac04b58190dcca1c79c817186088129d77f706b751f0bdaf840a846df500b42087a74f01d7a19caa4953ff9fccd2f5ff9f5cda7dff9f4c1e72f7cfdc5ef8f7c8ec630adc695b624a619a0e483b69c6fcb596e39a85b763937fa6735d2fda3c3c76d6b676c352bcb99623923cb196a3d23ab195b336bab195b9dedc618901be83de245e909461f881cd4d6ff0676892c666dc9acad666c7196ad6665392b1667653da316676435fbc6e8b552cdfd8b6514469fe8ac79ad44c2ff21ecb9653dabd6b36431632bb3b6326bab33b63623cb19b19e29ebd97da31a9f42f699a7131bff3cf48ef798b93eef06368ee0f4b4c517514021687d4b17a847dfb9869ef0e11c66e9536b2521a15126e0013e284a689fc97c4e47bbcbface8aef8bce53bd586d1df28b33e0822659c63ebc43f47f2c9381ae6f56565d2d7d8b4339df8db21f22d8180220d9b5fb54994cb4af37fc27184c933c0d73e952b22a86d103209ecc3e05bf9261c671015d37e3308c07e82a2387e37820ae1a701e55bceaec3695b156a4068253d018ec16a05659a867f51f1070a0aa6db74810316ec1077d99b3f981f4caebff26f876f06073c1b2dc11c37deffedc2cf68ae73463f8aad8f7c079e34dec09f5c6dbd02be88db7414fd44fe546c7ccddcdcb1bfd1e79135a24181096f6665746c4c45768576e3827fe3b9647f6dff9d8372ead015c1200b948990db70725b670cc5d644f1520fcc71251567401216cb1f71e10abf60782a02093022945d07cf7e6c922b26ccc0521a16e644341aab43372d7911bed5977ac0691880872d3029ebaed9e88f9441f18036b71708b87142ca4e3c02d1656b0808e05b758a0090c6c6b77a9adb02b3d771773e8a971ed8d55174ad157c9f9661fc307af9bc7dd05bc4bf42ee8bbfc7759c00b042f115e787839f1a28a3f74c5479cd80cc36be21eed988aaac88a01165bbc580cc12be21dbf15530f604c7a97715e284c6e8c1a68543f4f46d2d941399b046793e26c529d4d0a9d9543d29ca939e049d69b0cf48bd22b9b1b7baa62155d96ddc65602dd3f8a19fa8179f2b6ec957ae24dd01bf50cb7b137d46337b084ea78ba6925e85c24418d5f3cc2cae46681a9b9a5f8f77460fa62d0a96a6fa7244bd4301ea833a551e04806841d00398628b77362b7b43e02f7dee85b8c2061921630d780c42d48f3007561cf77ccb47272ff555e5436c78c52a1810abbe5a4dfef57eaa420c620452c50a75efab36647b28976b4315101a8c7946bf3322ef626bd646f0792634cd1b428ad0ff1d8d4f64149f31c5b8250dcdf9e168036cf00dd11f7a52bef43d5ef3bd6c0056af2ebf165f8bdb8f8b95fe4d764cb4fc3a91503c299b97a6bbfea8272be50fd81ccc5e5a33beab82384323a807a3ea30fc356df69cfe456c16cd03219455e956881be8ae881921bf31988154c38f10f72caded39fcc20121c87ea1abd7124cba754c3ab6ec016025cc301191f151fb6eb6e53a0fa20118f40fe2cdfed66fa07ce5de3148f4474d4da11a6d17738456d0031cd576552fff8a109b3369ab287c37b00855eec3bf682810056e9e760dca57be7216561675cee2b2d6ec0027160ce6e436be691fddf9cde2209372f1a1131c09260ac37620ec6bb4cade59945131a013b4aa94ea180f68270687f1f28d4dc0a0ad85e080d9daf0385a65ba5800d606d31e9aff623fe208d06d979a629959cb7109fd2502e499abc7e8f14943f9eec914168f247fc90898d157744324b1f3cb860c660588d8cd4951b60c64f746a48ae4bb81313f099d1228b222db368ffcac792f951ed3a17bd701b7a877ae36de8097ae3ada037ea933bfd334044fa8ba175e1aa58db5cf9e84c1ca33fa28cecb2acd15df91ecf1e007ca419b3c34aa5703a27c4ceabb1c31bcc04e515585e0603db33e2906fd9e7d01facd193dba1f4169c05a3fd000826ee84ebc93d5a1643e9a6f23757a6835be0b2e777cd7015a27b892338a853520b710da74929e4b09de042f8d776c25461bee59c29853cdb58d30194c0916728bcaa35d38b88dc07bb4a961b5fbdd60286749576be0aae92f840ee093b0ca3ccc67343c8f0d4b38d54a5d110ae3f6637f88dad2f00210f209ff4d2c4925c5b54b96aabe3de528bb5419d5bab3aee0df5581b54b935abe3de50c5b645450db5237909346e020dcb8a58ccbadcc23e9259d9ba20485f439093846e76d53b4f11dcd478e216b3a320554878e418023673135c5a751808b4e6e05ff33cfd9f6a63688718252c8e1e2447c23d4e6315e6285506b16ae46961053e0bae90268125ce85aaa89e8f8fda6846ee9e6844f0b5eafb8137d9c6f4c4a6818795d758d1dd3c5e3fbf820d768b42f9d34188b16b7c090e21a9bac607d40d0bc7e7d66d036902627ad8d18d79edf94c8a482643460074d13140fc1e01b012877d66f9844637ce190e04b40b7422557f4555eb8e28b29e194debbba349fd45762429005db048082485f4386b35f9c29fe0b4c83c1f74998e5d8ab63f00379c8a5e1e318a54b0a268c3444b6a6d9d46dd7bea9005686508de71a3c9be8fe2f269e13c1a9611ac9c5de435f9c84ea2f296dd1ccff2ed0e7d03963b39eedb9d6b59f11a1bc4c1c681276f161cdb64f1de4e5e851f6f7ff718531e152d2fedb286716129fa56c0bb1f986cd06f005d53c34cbb9999f1140967461c26211982549a9c8c15a648c2b1bb9eccdfa6d5f0d5766dbbb5d9edecf666bb3bdab84d1c5c23284f9a915a8e499f102f1f48b686bfa35ae7f528d600ed6f2f429ef802fd646fb4cb1537d2e995d31346af1cbdecf4d8e89c8e9e6b6836004f061df88d7569d01f25f08706f74ad6cca3f7f44e8cc1a6be61b92b701af9005c8816fc2944c854d9e3c89ee293813914fc8f408e2d9b53c2a820078ecc480861851abc22dd2f327c51c46330c80885f3f3094b127c1fb93499d26311d822db2202d6b937573b710b4bf86d64f8c90006608d49dbd3c9bd9e1145d43ba348dd4354a9738d6a588bcce3fcec1e47f463311dc71e4dd13902f7cdcd243e9ccef8f016f2e160813d4a5a55b9b048d2d17fe1c4d3291c0e0efd934d78c7c63384a907ef47f711e6cd5add8e299048d8916e8f3f71af4132b56dc3eeac0a6efa99b057e79541af6de8ee7e44f7f9826ce6e547fe11c381648349acd079e097d5cdce495400aac632ba761bb37e6867be62d45ab60cd69365667afbf037db75ea2036c7280924517e6b459dffe2d260b7272d7165312ef3d09dba9d0c53d4d0a91af0ca5681a45a71dafa92d0831075a6b856bcc4f22df0fd89390287bef60c90004afc2f77c4d10b705c46cc54b02961fcd9e010d78eb64f354103e21c38c93c7969d7a262ccb6c952b12ddd8e814ea6940aaa0b738dd5d215e1d26d1eb1dbc32a5cb8cf62ccad5881dbb01f150f0ff57299f6318c8f59ddb57e58ca14a46442c507bf0b70bd1fffadf5e07be78fdd352c6fc0f70a241280b72280afa863deb8d5f2c95756f5e939dedc91a1f7abe9910cdfc30ad4fa659e2fb219818c0102bcd03a3fd4c15d3b78232c5adb5a3c92d254a3409014885702790c632ee7c4ef6a7d58ecbdd19918418025d72e00804952c6109e800c095fe6c9ce0dba111d35e5b51e7728aca4293c549df9c11376a81c8fab4cff22fc71f22abc2121a729d1b17a40b211f516bde41d80a5a89472273a0032511d2e9137e3511ba3fe0cb7324aba330ed118f266de6a63445c50330e49be061ef024030d7fbb172e5a83c06f8371af48b683c4ebd06a91790f61157202e2c9da590ccff3527b004292ff126185337187d8602bbc8db55c914a91ac3c9bdf093908294bb89f301d627f9f15cd9205995f8f1440a2be2cb7829b70b5732a3ec9cc5d33c8e0b415dbe8c11b3f4049e04d5177c341ab3bccf2006744f27e54731d16f00c678d559c1d75378b024eaac2d6b05ca78ceb287c9de04b2a7edb37409ac9f23b7723aec34878a43986296f344cc8bfc3d47fd13031e68549356f8d3d05a198a18845f92c8cc70f00e229f0e76d4cea72fe79c9247868ede01d2021635a124f282a5e3cf9e281cb708aa0f1fb054320f91370260995aa0186f681ea02e114235f4a38f5145a6cf323f70529ce61c521fef6d55f87020ea9c97d76a8719043cdfd618101c526473d6fce2364f8928db4a56f3039f2b98317157a73d0de27737f4bec63c67c275709308e2b352cc40c235e90d7f069e8f9959c97b2db87b757225f1fa56952eba766246a8d455f470f434fe3e4a28ad78297c690e4be8bb47e32505212e0c13315c9c0235cb0b9196e9f70e292e899f728dd570302027adc7dbaee0ff7d82632b737b787c7d24fecb9d1c2a3e7b247ffa9ff40cfd0d9c37a04fbf91b83fbc2f871ff7a8e088df716375946ed0df5f7433f0182391b28a4a776c9f50bec42b7942d36b743ae19c95b4831ac626fddc364709fdba8d2d2dfd1b886f599fc16e75efea42be5d0bd6f4d4b9b73b99292af583f33366180ad4fe5510ed3baf1f5523c08caf1090ec25497b33fe6f88316d05006af6e295363bfa5d21d2a73416b73a7506f995af90ef1b0b95218d7e0a29a577dccd32e2aff30be1ca54a6457634cd15bd0483fb8ffc5e265b6e7e234dfbaaa4395e08ded05c61add67937e075d0b5f155b3dea8db7624fd41bdc78adc2e8654f9bd3371f90f177f2d5b1c47dd74ed2d106001ffb07465d57d3cf72e65703c0baf0272eae278074e05fdc5d0e0475829f4ab9f0e92981f67752d73976cd96824d7851168ddaf988dc107a2002c96a9f843768d99e721dc304f6341bb1a04862a39a88cdb111cbb8c1a0b5389b38d483092e1802cbd168236a7c202a1e1691784402f0c1e58a08d5d3b81cdf10f324e8ba3307500ec90519b820d26d9652875772de4793b319e6f483190b1de00b3c89eb50f1e73ce43a5374fef24ef5749773bf51e513adb64bbd460519d1d076d425e340a70ddab125bd6d7d3cdb0f7a397a92525eb0e014da9c54ce9960acda1c6e4aca7344f3501add7d925c397c1ec02e418501bd6a0a6bea4fca58d06a68248b98892bc1fb2ad9480890e4269e611d8ad21fb757ebe9679c26df7d7698749bdd2af14e60b3eb0da28acaf947d977052bc4c274a7f29b33591b21e6fcbcb3aca827483d83b0698d58f39cf29d33768de812cb6cf318f6aa4aed4ef4d8677afc1893bbfbec17d91e21f307b30e67234f453abcb8e26d744e31a3afa86ba95d88dbddd49269f185bdfe47af9259a78c84af908636d989f79a9efa0a2b63a1609b8f840f909497d54a6e3a5bbb09929b188aab86a2140a1ace4a51209a40ab8f1b5ad6cf951a97cb27d187824cefd4089f5d6a87b53489154c2b4305b6d0b3078bb3b86977cc035ff009810ee38d71f9b0972ac13a9b1388ce75961cec1490b6ba4f2a9c3ce55ce794c8bb13e9491704cd856888f2636e7cb54fd7db2e1d27352b66f1d699bbd48e5281baa90c80270d6db5f4f13a353a4906782ddcccb39c0b1f57edce1b276ee2d55b5dfe1aef98f6507de8c04fc240148a5c2621e0ade209c27b1602bfffb88060e5877b56137820a6f5e6b503c3596816c7210d55441786af5ca2dd838927cb4c3206b3de0d7ad343c0c76ea61fb813207e5d7c6d5f0777192a2043974a30c339108de8bb2bef7638a409d27c02d64dc6d77d1085fed63ebe20067d1c3485c82102e55340938601379c433e05aae875cfc431dd4a98471be91dfe80e2d6aabcb5b5be568b2745672945257f78134d76e4d4ed0a14f4b71ae5c4be05dbf1fb98f0d2e2fef5859ca8129145711ab5853e76a3c1ce8a494061b91ab8991d15d464846c30bc36897c0da08be3aeb417dfae82f6ee64bd7345bcebec002fa6168bf14cb853128324998dd8dff878f943bdb6f4d903376ba6775ae239f5324e00d2c760068a92467efffe348652dc27b457a48536f7f28b817f05ffdcb4b89c03204d0a97ba2cf42086cacf8970e4c07aaf0fa529dfca5a6944acb594daa344d508b4d082322bf9161a127d5d9f33732db314d580ed8e7ed03a59ce9cad380d5fea341cca42b8e0148840c92b926fadb08d4ba358e7dc45454a0c06df3cc0c3b738409e84d5eee501639076d750a1d543a63d716a863ef24881d7d78e978561269cf8795b9bdb35dc95bf01716476206a643813f0e267496672aeb54d0b74df5dda2056ef5d6a8b831bb0913cbd726f52be6871665ad03655d151487e6a6b3756430b17198a94c8c84f1f5780054ca2a2e3643aa45c3be2d7906d84f453bfd8ad4807d7084f50bfa9c5a9245fe5c2d233c04d3dbfdc6d454c6181db84858f982014e3810d09f9046e47a6dfe80fd7f0e4fd7e2fcd8e4b4a21d8dbf37a51f232b46ec18d264f048e89e9eb3164e33880d35c65a6886f598a2d32dc384811c3d0ac4d28af0e6aec7686e88de8934d4244ca119985832e08a484d5d8942c1b7141d4736a6f7605414e60355b067f1c592fa884ce5878a692ef31b71dfb95171c79e45481ca6e26a8e34c760153ea87ba82213c1f0c799219af52b440926b96a98051c41fe9425cd8e46d2e02d1b89927503ef800e5034fa037fa04ca6340d4f3319b37b57c42a921f7748b18c5e8b0d5cf5e3b987504cb62c5e8e84b4012ccd6278fb957f2d9176745ee43bded38d0a1e06bc9c48c63ebd7abce4717a0eb6a3fa4409f0a05fbad5d952307b7e69ff13722d5d029a05ff686373a6220ec120076058cc486d746b2bd196f106788ded2bf3fd5645f1843bfffe6654ae3c89779d6a9d7d3b7e8ee4cfe41b330e9e1e17da49f3c2963344a56d1eede3b3a1779a346d66d075722ed3bb399d80ec5ab0fa1bbd442676318100aaf320504d95103afd24311570d5d678fd087ca4e290d9b7d775e40baa0fb47c79535618de101d2236d8fd6d4f0c9057fcba02135d1a8ea051dffe0bfe5e774fa1357c17ac4182d9bfd805bce340bd2494558279341a3e32c8de3f34034436cd91c5c7929906de83d8160eff12fadb45240676fcb1a0676e52e49e590faa60d4549c0902ade1ec8d57739721dbe71fbf8cde5b6e3947930ccffd6fd2776dcf4fb2b7eea808ab9e6fe440e3c86286a299ee45a13a019a6783a43ec6ca0821d06618dd92ece297880ac8f44fd18b3565f04ea2b6f5f8d86fd1a458edfb4aa7e538e7b5a257c7334c25490d397312d7658837eb3e3974391379742fdba3b26bfe3ce94c5d43d44d0249e4f0afbc07a7ccdffd82159c4b13ed91acf4b1198de5cb70e45918b1653923775e3b1de2d8a9fc1f2b2c0dfd2dde758e9cf136f0a705ed92396cd7a0f8ccc53402fe28c90ac22870525648e204d2de20dfabe330370030830a0674b7edabf32ec318485a255d7d9d63216a4d9531d2fcd89162bb294755fa69eee0a0f588f2ec823a55a85c0b145677663b0770305474d20a136641bee4c8eb0fcef7513075675ee01970c7a9aafdf0a7092976ad6e934171457d14b9ad530105fe26e9531699b32cb4487f8590089adea3283ac1f33bde494f3855e02b73267f65160fce8a0bfdf28399b66ad6bec6651782004ed5b70d73454b0433a4a69bdb90d10e7ba40c3797c8b269fd5b30bce3c9ef144ac5b72ab72201b06c9ee34bed4f96719199a55ed172b7c942cc7d889ce7f64d1b7a5fb38fcd5d8de3808e24c6e7671d675abe596675b7adbbf6dfb2cee7141d5ddcc5243765151008c698c4d69b268eccd95d3ec48ab9f37452f83e4aa636def10d096af51fb53d4a689fce04283237c7b6c26b9c09dce40f9d1ac5c96e1d6656a8885ce4df1354477405ca83103cba5c6277ac7052152c511b46bb02ee2e3df082f384d860412d13bfe6333185fb71b345bcaa3a2d70d6cf24afa3be31eb4e9f0cdfa5742db7795671d420a2d5f6c81db2a6ad3d2f853b4b847dc0d703e9db2f173b0d13b5c0af2d5fe95cc1723b062e8307d291bf1a873e1cc29a96b9c5c66e41fab77905977914bd711966e1e85fa63e7f7b58b92f6d0a576d16328cea88bda02494fb5b8ee39442c693e1f94390fcc8194404ba185602dfcff7aa487735af8e09c63760022c1b2bae2956001bf7adfce6c745a5056ac5b0e443f49258c6d08562d999aae164e3cbe3b657e8092840a59eaa8cf2aa2f546ddea2af3466761c28b799dba6f7b776e2db79f3d0898ef8bc1e5e708c00bf733e71c7417d5af1f7581a790b74150905a00e40345fe5041fc035e73a13a3e97c6f9b868dd5dbdf1bb96be0103352638e06716a91687d0a3ea773d8ef18f433afec08027a4a219784e245279b14c0069dda89b6f5f551939e90b50567653e493a7846ed7df3b1282b45a6ef35654b15fa7956878b290ff71779628038f22fff4d5aa7541458528205271e867e217c1b1a31bc39ef40b1fd565cf4afc76d2244925f66cf77bf814d31a73c7380e1895a844d64acfdeebe0840bcfa86b89dbc04bdf1a209ac970538855d1ecb012a058c5e855cc337b636c93286feee689cbc91a0497c8f4bff408bf8386505f4f8509c667050ed805b700c0eebb73a3f5ca10100c17b3cdfdcc164c6838f1bf0468954683a4cb69f54f67bc0c9ee859627d697a837dd9f9a0861b729054c717ede7e9e7a88be838a64d2c853486147b5915869564a9a0aef094695772f058d06382a58c7b04434e669cace186131b9788f9d77a6b262fecdf0e4437ce44a6f1a879feea57ba1d06d6fa05af4293f455cb7f5d66cdf8a21eca3c47dcdf167e7e41d2672c889eaf3e261bae4db4e1c3fa8a64ec97d15e4b13757204419d47442f1c0d70f33aa1d116177f3b8708512295afa5e48b8fde19592aeef9adb886e061a4d7ea57d0014cad5c6f46ec1a07869b85059f0bc96c8ae558374198ccc30e52518242ddbbf07d94ed5bb8b23aedfcc8d548e4331c6c247ae4a18521fecfbdfd55016f4aac554dc39f2e9b19eea4ce600e198444a14dcdedad3c91d72d15a2121051ea88483e3f64522773a82c6462445cd2685774cc6c2a1061bbc12b1015f480e5b33d7e13ddd6e8a5d23a5b6f403f6f05d4da2ce4865db4c2413d2dc2f6df1e8782695a267a1243e04e668d460bcfb9c720c680bfd5208dbf47631d3ed262279acbc2c76f3631ac9861ec5a906990ee386fe29465053e1acba8bbd4e15bc7a2985ccac3bc906c29c4e2721f06c1bee8d3efac6b17e0b8b71223a65c908adb5e8f5bf9318fb9a04327826e767f93e4bb1c6d09dcead1c44b9aaddde1dfdde0d111796fcb808384a9819660fb724aa3a089f2963a52b6e59e1538d2d818d12ac01b651039a91510b0ab036dcc1571e8fbb3c1a410a41f40b6d736efa69cd7894ce640478de6f62fa32e86aa20cc956a999bb21a93a23605c3ad67ac82943ea87b2862e921fad3bde85c9eed541256696963acd05f42e2645b368595e67d2671a13c3cd5079b5cd3ecf406bb1f0aa3e1b4184be06d665e146669564b586a02c83ded478e44ac0064b804377cf590e83aa118d44f25cda3a2273b35a33ae0c452d4ddc071c496c225abb2949348c91af1b947299fe4128cf2923343a3845b89d862a1cbfda3c5ba2cf2b9e4b1d1672d2389ae224b3c57766486cd8d5decbcf6f53f8b0798e4e0ea21009e3b33b4dca11c1ec39818aab0e37cef5501f4da316a07e00c4d1a1775938d216c782065519105aba05f64e78637a40734da7b4fda86cd5ed2bb15b86205ef6a8d9495f06e252aad9a2588d34b7d8366fa223038a1b16120383ae66549bb6addfeb062faf5b070891a17be457cee4550aa8c769206e5236557109c65d8b6eb46c392ce424b53184140993a2db9497f143de3469c39a7cb8ce4be09e1369128121b9a6e1d94d25b0c6d238ea8490e72d4e2899f2526e2031ebea73800fdca0dbd8f9bf8a5e659e560e2c3c990e51ab209208b045955c0f1748047cb044416c2afe3a70f983a2c10ef6571447e13adee40a82c340c5e66b842ca8e39e41b20ca203e89c1091303e503ee067e388466146935b735218852f630beb870cdda2a35b86ca7cc81b88182eff008bcb3874727b3cc46545a3f6275d8bd8bb88fc27e8c848f1b379df18037240ac38361cc85561661abe8a138079a32a2039e2e603fe81c12fcf85924f61e826bb81e937f5b5f7a54d4348f4a8b2af067abd1b4e1f2ecbe13823b796c4212295b60507ff863634515acbae04e10cddd9fe0235a26856ad3b6c64ef1ea1ee194d49ee1c37b2b09459ca60da303e692220fd364b8b4375f331bf1585336d79e25919b38119d8a4293086184b4d25bf1423b223c74bff2dd0ae81e57a0780c909345594bc5807699efe6f854427bcc509743f4b00f40717457e438b0ccbac3093ebbc503368e5e7d134d163f20fb4ec0ed0e7391bb5b0f50ceafcb4d04c4b22a193143133a900ef8eaa99a0dac7dc43aec4700933b9296f4b816573d08f9cc35088e6b6890e534d85f710a323c66224e3498ea8b82b865d0d1cda0857bac5f0a2a4bfcfaefc48c2e8f86d6a56157069299f3a5e2f98602e0267a2ff363e7fcb746ed500e350a9aa95217ecf579cc4fc8100dcda343668f2799ecabca5db9338d60c2184082e3bc55538f1fda0bc0d0039a3c27233ae681766e042ce0aeb3c3852da9ba0a30981d38053921e60bcb6e9140dbf02f10f506cd6a18f10bbf67c7c5a23a02951a88a8e62aee01768ae3aecf5d9bf2f66057822bfd3aa7ee65ae681e734d18bb9f7c08500be4df8b5808ca60111e676d352a28741b1117e7d1777a40c2b9184170644ed465af40f127ced809866e0a8974a260744d45d25fe2ae72f64354caef4ad6f8d176a4f511fa30b03099a9ce1f4d9cd8ce69dfc928add2a92fd0e854ba91f6ff7f6f573eb70bee6ead546a35bdd86b0dc79038d7e310f333a58e59a1c7b1903a7dd39749ea3849cb2caee368da081cbc8e0dfcd377dc680730018af2d75c3658afe632c3fd15c7d9f56e1a199e674431c5221dcc93c95914e6f7019ac98a7b57f02f66bc7fcc01a3897d27be901fca7268974539c22e0b7268f1ac420b4ae8a7e5a1d364602839afaa0e4abd58e135138694b803e420cfc70cf968dd6920375c3ab30cb9bb6d074cda631a283c4faed39075c6433da97a248b0c2683295f941176061b929ca97e039f154ec8ea9e99877596fd6a5399fe91ac7f98a0fda9d9b0ea21ccc0bfa5083275ba0d4530b63ba2edd9757430b16e44299938795530c53f2df333cc75460a8d6788aeb21796d2d4e1a2e886eacba88a87054bf8adf01a2c607fff19b30bdd82b51fc040b78406fb953679472a1a82d1fbab6816f93c19fab7eaabcc600d6983d25dc0f1aec9a01ab073fc0d32f1e12ce1de83b6219660eba2daa22dddead924ff0380647c04868fcec76bd0712d967c5e0fdf36600344bd0dbc0a30ec17f0eac9586818a7cfbbf546dc6affb7312936f7091401abbb8604868dbe8007309a7eebe27b90468dcc62438028b77b030d2f2267d9af7da1c9f10e7d3bbf832deaafa616c1568c2e7c2ed38aa6d886a0699247752d691ee6563719c9c9145427df1f29a8d7f3bf2250c12287f9c05cedf83d3e9efcc05c1b3e2e43fb1e92096350ba47581a31d8b5073c1ddc21f6f0b14f43051461b744054f11890607f48a043890bf2df2de3d388f374e36134eef87f7eba1da7eb0548e3aec87242002a09a4698171a201a576fb0188c0c919e17588714bb000574ee3c5156da6067f3e0043dd8cda007805e9f64e08b543b8dccdfff0615d639268cfc33b9ff7fdd65e902119694622d0e7efee20cb5f1004c5fc671cfea1b2cae8d0ca2058f521a00f6c06f1f08c768830b8c561520c660a213aa086dfe44eb545459e66083a776974b80bf266e9cbb76dc38bd6ec89ceaba2da3aac45dbb3f01370fd74f42e60938f3b8788dfe1cc9f286a1e7321831729030acb1552001287d6d8da3f54dc268ebf768a3fda48e0b3419239e72aadab22bcfa2d62314ed064e28554f146bdf4d4357dd06351e7296ca5a9e289a2e2456add644423d2a999b263a49749119bd69d014d3a5c953fc377c10cef533ba4b7c3bd60793395973a34473cbeb36e161ea91b802b9832451b23a181f73b816ecc491fa084dc0680d19dd48eb94ac8d87f6fda97a001905c3e144ca2fae9ccd88d6e2185599633dbf1883e92fd2b730abcab6dddfc2c332b3ed4cefa0bdb685f51ad4ebb4f05e827ab98fc7c15f6fe2667f88c050a61a7d8a22af2aea0eee236ab50647c599c450f01062ee0d3ed58d3aee191c16185ae91700b7100968170815ee6c806e5efaed29d6231efb5632a37347bfd911dd56234d8ea8bf3d51e47fcc60d88230ce1f1147a347799cfdc0676905fad2f6ef0d0fb38231cd33ba71685733901b8676378bde7828973047495db2fd9f2d14666c83d243cc1f90430c9c500501ab0104be3a93f930d6a965951e9a1dd0e515313f40126cbf32042ca6fe44f5370cd7e37f7df4c52e0c93ac5148e69eb62fe759528c9addfcc30a624e8c4c9ac143e79b7815644e7fd51c480b6f94fb19b8be67e031ceee69eca74bc31f7c2d7f8819017011474d668926fe41e6030b08756fee7202931911ba31b9d5813128a14fa036bab39afb1313707e85b5af451c78985d871c48278dd3492872b46022cae26a5637a2e80586549610316ddef98fd6d4bcb3752941d98c844dbcd15f75bb25404d9382d299e38b4f49297d2a8bd8b9e5bf09390bf4a71a8afcd390c55c894ce546049e603e36b47a1fe28fbe033fcd044b2473217d5d9aa2294d0fea0192ac6fa30d17f437cce5deac5d0586804ddc59b2d7dc69008b4828264835425f1185161a8ff013d78d923803119962e989a43947df87c049df425946dc355131075d8609952553d313653a13d8b988a825609330e09b2861a64d97e51d9560045406208a3d51bd0bfab2dfe3660591c63dc8c195569357e7e39286a92cb24a9ab36a303fdb9bf402d27d8c114b2ca09e73c5430e0e4f5252d6bb2044c693275f25355d4facc3a8a07089365f61d6eeb0266faca3788356fb379fb1bec6bbac41dd9101daf782b54d825a1517334c4d8ebefba2670ea59ac0bc017f4a4412c4e481fb6d9e62bc28faefc3cbe575f5b5bb6e1f1f67a78ba94dd56d398981f101a5855387b9535329ee1baee7a9f6d413317673b3e42c925c36dce24eed12d53ba1bc14e2f32beb0a716de11beff8bdf0c562581f0fed78521a9524df8e5e5446678c025750bcea8ac2a35ef2130e3e63894b8ee8f964775b8d25e82ac79e8d49b47bc6eb91f5657ee69f63b84d644dc2567e47e5c818359dd250837299244b0fb8d4901936d76500787623ddd2a04320666c2076331a7f0d132f8160370a03641565e6889c34f9052d2c84e3b497d2e577c4fd15542cf758903dbac7825eec1e0501e9bb8be60ae6d185cb5cc01bda8ae6a33b804c878677f36b0236017a1ade22b3b9acee34705296f571568971f24d958e707ccf2347998de92aa95e066b68a7c698cae288e320094788b557c36d8b834243a58365ce86084b041796e8bf1c976eda3f5fec15b3d29499eee8dfa1752293aaaa0ca8f17263cf594c3fdeb92a54bf61b1fdec07828aaaeb02dea021b6d56785125fd905918faa296f24ddfc2adcceee8e48d2036e309d130df8c1b9ac7a27e4dcfe4c6f0985a35ea0fceede13af8abf6ee879238d6ed94b435b6e2f9f86a838d53f5ae1494a952d0f03d8d6784d5c85be4eda29990847eb897fb75c6fcea1662f2fe53021a068f4e07a449d4d7674835fb3d3d70ce867a2cbd78c5bb4689a155b2f5a742b3ef460b4e8712c76857f574ac5672495de460c6e5378d016a09b361732d8236cef8482c735efac0266d0b65269485b8a088bfc5dc51b411c008f7c8d205f934bd2aebb64887c1c7fcf30c6f7a8605f7cac63ee05568a680bb4a16954562a581edeb8f864b9b87f6aedbf635821f318e1e3db208e929d9e7daaa19d178a4d53533cb96c92cfa486ed87e81f81aa6737949117400458fcdb789ffeefc3a4c8bd53953024e524a404f457efd5292786152d20b2cf581580c38c0c645b434a364316ae8914f7299696a4f8b2159205236eb8a40d465ad4597c756d0cd5b7d51c29b4c287afdf4f978bf9b466fcca13a816e8c8f2404d3c24df4077b49e20b9487d980bcb6a09709e48ebcb3d046cc96ab3633cd9afca7b6f1157100d1ed7438ee5e7d6faaa49b69f41669c50396dda9707118ecce0e43468eae137ad0560b581eed7b6e2ffe438bf046f5606a06c0d613eb9c555208803e8d95f51ab905d1b3215e15efe84fbb37983387a98ed1c1382287e36fa132a453e1fc396e2db2fa17eb72acd3a9e106b1ecd00378594cb458b9747b1bf08aad173bb32ebd25a8190f13b4da404c00bb48205773b9fd91198e333d3bf08047d10163452a65a031333f605e85a82f6ac65df9c0b0d1425444e892ad4bd4063827d187b9539c576d8170550b6d489cb03ea5283d27cc3c6b3d740ef1a085b83527293dd8c17e46765850589f7a9dbe2cc3de415b4b0f8598bd280ca7d3d15eb33e5466fefd7f4d1a9a44d9b00d19becb0f9a2f230f18229ce5736067accb484f131a9a93c55e50eaa2313241c59861f8814dc8788881d002e20308f8c4704eccb1515ba82e9f5010f1f02d1578b0001830b2202f7af11f09c1ff10f08ba4240763efa924190cb67f240404adc557d7c509cb62c80390b1839a05854ad25a374ed81cf1b1652a57fd2f1e0c353d59fc4f8949cda0af9ff0a05176c495af1e6d4a2696e62a927ac41ab6d443678459a6893c3ece6e3ac403b2c60da1d3894f82e2e1d70b9ff2ef68bb1651375144169d1d24ecbbceddcf898c511b16b8140450bf81279567dbcf683a4393dd30a890d0a2eac3dec57a200a6f14002024088a4df03180e341b8a6e6aadbee8557e885a7d94b9fc63ca9ccbfc66eb199508d8b1faec49d7ea7b041f1e35c1e90fadfa67420b082bf718f59970ca94bcc298309eca64d0fa706a3b2f3206083dc2b3ceed5fc20a6e67d07fed538887a8a1b30108305a2bd29985114410a5ea01462fb7422476663031a4124185470fa2f4484df4c4b555106eddb6d229aff949e59781937faaddcbbe7592b140ca42ab11d88912fb664829646bb62909a9a922762160ed5cedd679024dddd6bf5e246146878ae2fa8da0de45f6f847be57d1eb1f814eb48781010c1eea404f8ad52ef6784087458a642e988e010d8419135bb8b9528ac79bcc8cd6f81967f8dfc399259c9cab7349e7920ada5595c5b82000f7d7599e93231559416d6f2951c6840c5a4d5bce227c142c33a91ba413cab000082b23e7b3c192d1f50c98beefff3816bf58c8dd0755cd28642c0ffece6ba5809a895451e2b1d1c8681a4f4adeeab79885f95c01260add501233a16a9893b70836a518092c0e019c4e515abca3821906d45cb5fa760202c23aad08d9117495d96dba502f39c5a9361c43f65a21b4dc81c2d2523f0dab86979eab57416bdf8cc9e131b91cb8b6557e10a29cb5f3e0274097d3827e0e8ba02196876b64ae553627cb81e82a526780a9e28a37f9f6460087022bd281b629f8e88f315b224a05fbe922a7404b0f8ba5d078aa2007a930ff408b059f6df63d15d8094c4c68ee89d9ae13fd28bdb8f2c453701ca23073eda08bd31fcde3903b02bd4260c2ee6effd0adcf61965b5c2b31f46668bd58fdb8d70a3eb3dabce0b0d71e77e5bc1f2c7dbd7e8b754710748a9c759a70156b185fd7af91fbecd744e3ff8163b23d6cf7ecf2fab89cdd202715c81e3816ecbb247bd2933bf8c6fcb7fc23ba19cba06b487ff48cdfc1eb58d09c8a845c43d17525dcbb8517b2de7ac585f74e2404c06202a591c3d8a6d15c6c3b05a84b36013a562221ef3b668a3a861c3bed98f3a0581abb73cfebeaa764f7e8638a85976a935dfb4fd3bef216eb5d06ca95fe2956da4e1f8a2b6eadff140f77e812825acb70e655f240e6c16a8119dc92df3469f12ba9fc9bc8b3a7160d209c0041cea85de8a06700cdcd031a389150aa9d8c8bf06dc11484b9b7774d20e7aeee1e5d7a161a3405b8068ff2a6c0b10a398a36a38b1f11088b281fc7d4e40df9b2234820268ba77f089b9af95993befc0b1399e761f70ce8035679a8b89428ce69f8421da45fb9545debc1d31699af8bb6038ae4ad2b23290cbdb12e3739af8c46d8d936efb19f01a06f11c6ccd241f7fba01922bdd8a70c3855e229649f22db9f82bd26f089b1901406afce1858206dea11265d78c6cb4db49aaa6b97d5df3001068e61359837224071badbaf8697ac273abc6585728ec8590833b771c28096d99ecbcca78cae26433c2ccc869363a38614389dadc6193b54fae5bf2eb160a6fea4b49198ffd7d6ff136a0b31efd1e663da1ed534e6b744266ad56f8e90e8d8aad8e63fdaf62f565b25c0d121418e4c166914121464511838f2f1d16fdaa770a74701deba3be0a5534441bc52db0ef2b47ffb61a23cf1933ba9456312b72bd0552a8c1b4396233962bc57f422202a175b515a591d647f9b16d32e543ebae33d40d5c2ed269ed950c713fa23a7e1e92ea6870590a67f9cfdf779fe0cba0004f37d3c6f02f6cd1a64a0adccf80b324cdd358fcee310000ff40f52c02509676e8589e88b43589bcd8c4f94983f1cae803306509940e757823be800987fff032ecfc7ae18d1cc180ee0f15e010956228090f6a046348084352bc420d67ccdefcb5b89fa92ab6eafdde9c2a0b7fc4e03baf472a05d30d0514e07f4bcf45964ac440730fcb0af8e88d090920c0cbd3f8f34d34d91e32c933d5c20cd2007898e9a18a8520158e6a8612b73d4a83017e46056a995c05deaa288a4a9f2556767ba57c0df107c43ff437edb7befbdb794524a2903010a6e0a030ab8d43bdc4e864b9e12973b3ba3343bef89d15f5c8e695c68a07289cb9c25354921971d68666884e41297198d0c2fb9c465aae90c945ce2523c7314954b5cea285c14132ebd28a4a8a3fdd465082733de96392fe28cb9c4a518c594f38319991919b9c4e566c24619d55310a0cb29d30b619e32bd60e66d0974c3ff5edc197389cb9b32327451b9c4258e2e894d2e7189c97821c3b4c291919191914b5c06e5129739b9c425ce18a83136a0ef32789b4b5c7a63666374a0b8b1440d2a97b8fca072504db9c4a507458342c273503ac4b0f9e88a5ce2f283d2924b5c663148627289cb4f8c4bd76bf0f6c514632e71e9352d891c3c5142881236fe9a27e41297fa2f5418a6bfe609d6830e28cf8e4a87b2b4c625f8b7a44c3158795bde7f91eb9e894359c4d9ee18c5920aa50b6c2725850d7aecfe25ed8e1f85d2eef885ed4191ddbf4d731266f627dcd2c6cf101541a0c06103d805cc19284006edbce67752fed9c4234362802aa766603f6c6785e1849419508f0ba70a266808fbb6142083765b5ece3e1529ae37292dbb7f1e10f911d223e6c945e98b4650e820ca76ff36f0b1fbb775904576c738555020ed54969b1e22f66dd12c6372303a85603829df1501f667d8d6da17d57a3d5a50e5d4885ea2dc80c1fd7c3902078c0be2979b2e3a6c2f32a4a88449d0e8f9c2464cc229a70b101b0c0f631239f8e48c18fa3226e5c5859b2464588129c2e3e50b4e97a8118c0f32b7c3061363ec822505668d2a09312b1a373bc42f3f6e90fc7871dd74a161fc321bf272658391d2939b72f3854aca0b1a1c20632e09f9d4e5e37223e37ee03c01b7e4bea7241e172a3b381fde162b1f9721395bb2645c0e7751e1dbc2e4717932e26e804f36482e6b34ee869ca79d8873e2660b927eea11eabc2d4cc0a723780beeebe20263a4b8e8308af19e8610bb14c13815be272674971b3c41bc27a7100785c365c7cdd30f200e4ad09634395cbcf0e0709f65b19f72aa33bbb4192e35d232adc66e4cc7bed835e2e437ab1f4da4519ca6e9992b55679bb455b0d2ae2bdb2e2ebbb4cd5edd67e4e98a489bc5cdc4d890d6518f466db7e5e128a7a97aefbdd75a5e6f4b9ffcde3598da4b53741d7bcb454a2bd3d32ce5e9496999a794521bbd750ac4d314ef0c787a00109e6e8d0225d2599e327b96e171bce59fa97b50bdc27f5fd7479553cababc8298d75014390995a8f3f0bcc6972ccb9edc4fbd2e91e5a3ec12594ed23e6eb935c2d9fc24bf6ecbf22cbb291e9ef135bede92a43db3ecb672ed12d12c8b8ccb4f288bdc85b22ccf3599e596d65a2bd5a9221b03f9bce11dec389d282cf359ca571c4ad485b2a034e32c0b90b22a2f77ad5da26f934057e8b2169970d6476d0ea255007e91da5aebad506f293982997dada5e35b7cf93736e19a6d758d58b70e6d51202456083112287cf78834a2152994e8e4883037858802a5814f9d1c81d3ba9b1c436ac861e48588da19fb020d780acc0610c2305974288ab095be032c0b6b21400173dce068637e39106de14b65f7167fbfffdef219084077d64000ba13739b05f7d44916243f80a74e8cd8fdeab62050497b01cb827e51122c0910302c2122eabc97e8ded8b6da3b43ac3f81f07b0bfea32bbe8b2fbe17df8a2fc5f85edc41aad3e05f88b7ac35c8c6c2ce6c67b693b433db99edcc7666620fdbaa623f3fe8e874743a3b1d9d8e4e47a7a3bbe60e8e835d8d0977bbe16e6bbc5fd247892abffd0379df3cb0cfd499e9cc7466586756c6729292feeac831ca31ca81e5c464b3bf2fe0e47072383a9c5d8e2be7b581d8d6b661dfe8410e37b79bdb0deee67673bbb9dddc6e6e37e0b8a56c8b6bbf0196942c254bcd52497f798a268e4365c81c992375648ecc91393247e6c8dcdf2fe48d347a0f9046dc881b73236ec48db81e743adddf19449928fbbebd39cd5da2be837b9ed725caddd6cee6c9f1e49ec7f5a2b983eb80062c080aecb6443ef2cb796877c3c25db8135de12edc85bb70272e85b7f016e2c25b78d319879e088d6aa1916afc7902e2401c980375e0ce15be84a46cab0574fde522cf486ad916f6b78967fb6c7fa578469e9107f38c3c23cfc833f28c3ca3bf33744dd77e465149bff44b1be9977ee9977ee9d75f199816348a4cb22bbbf22bbbb22bbbb22bbbb2eb6f0e1aad46a3d168349ad0282661fc5a6dbe62f122567d0d8de58f6bb48bb2edf7a368c3b6dcbeea6db2adb8c1f80365db9b655b0ad09b6bdf91ab58414529fed6dac158044227c08e8eaeb89c07561180cd9d32f483cbaf99bfbcf3f8f89ddcefe03cb027e5e4efe0e88acb45b01cc476dfc1fde54134cba2f324fde59727f797f324ddd677450fc61e36dbf2afe220db063191a6e8de2ccaae1663fc62b581115b7fe74f85d8bddef2edede5d5cc36cbb274853dbd99b521d214bda752dee3ea71f5b87a5c3dae1e97d08f6a6fcd41777453aad18e8ee47131e5aa996aa69aa966aa996a16d402ce2a5c01747060de6e1d1c8cac099093cbc99936686f00341a8d46f33eca7360daf3726039b01c580e4c08870fb47d8daec071010c3f78caf7abcd07df776dbff66bbff66bbff66bbfdeeef450712314ab0b02789ada4da936523b9c2371cb8af2d42d8b157dcbb75b07584632004f790a9682a56029580a9682a56029185f814c6d01c053927623694148a91bca49922449d2882876b3d3103d1d63baf147cbc6a1c212a988b7928693a302e3c1532ed26e4b9bdb76892c57a52143abd1def25dbb44a6971c1d5511074fb968a4bd0f0445a34f34f244232d1a65d168e3a0e23ac5531eea6e4b67ed79a14e87ba1cea62ecf06c10ca421987c2d3b34383e5a3c2a97094a88bf99483bbcd64776afc4e0c55132a332a315fd3e769d9dacb5b9ea1c05d14b8db35cb02b2b26b3db58a2b9f2dfc29089ba205840d19f9fc90197afacda8e466e4133f405484bc1c152fb70115a020144fb927f3649ecc9379320fc84b108a208dd338144294eb988ee9988ee9988ee9988e29090d4da1f936a5966f6f7764acb80c71ca332cc3322cc3322cc3322cc394780904e5f88643a34d1a3260b688e22dbc81b7ef76bbb5c037a12e2515ca71ecb6729b3464c0f47cdf352c2106710cc7700cc7461fe6066de895edaeccf461831460a8ade16c6d9b490186ab9e665385bb4496b3b85db258f1f46a6c81830eace8d8a66c2c1d783062c979caa9bce5b69d23cb0a82e1010be7292f81ced50fc8312ca2dda64511082c225eae7ca6d056e6b609331eef5bccc7fbee02f2beb37cc8fbb6127e1fb8f7b75a79bc88555444570841f4dd56268b8860837ea858d5706a6f7907776d53a1add56d695385cbbcef2d6f39a52dcdfbc6a2bf6caa70ab24bbf2aec2bde522000040c4f2a0030e526c60967c4808850a152a54a850a142058f0a153b2a543a2a54842ac04f850a15d695524152ccef357b66d736608cc5fd84fc987b7f79380a0d217d5423cc8b5ae0efa3975a16ddbc61d71b1c7114499d9b7d83b3c3b379cdb1383b4745f55faee2a12258ccd3a3716eecca7346153b74469c1f5535766004de0981c7477fbe3d2b9f9ffb37abdb6dc5745b35e55649b9152d577bcb57aedbf27ee4c8520546114a2c9d60beaf5e37a617647cf14125ccd95746497c5fc102f084114c5f8c680922e9ecabd897ef2b595fcd5648e08f1e35e00f36df7b763228591498d47303937a706052ee2def89dd167d42040e1c526e38bc7cf1f2bdc76b33c416031730325e67efe9f2bd27294997254ffc8014040d67efa171f9de53eb3d36fdbda7e953d3d3e353d373c4e27b0f0c74f5d870e9008d78d880463d32de721eda6dd12e2d3c79e2098c935dece93b4f4d8905178a8861c2c30c67e7b1e1bef3dc569025178bc185232f0471761edc96ef3cb9cea3e38972e25172e259e241c283f49d2709c703c3f1c478646ff90eeeb6fee50447132750392c7122f17d27c7040828b5d80f2ba4a0e4ec3bba23beefec844cc9b1c49822602073761e9796ef3cafce63c4a3a3c98e53931d2d3b4c3b4d6ffbceedab59a2cafbced257db81f296efb86eeb0061665052228d10251bb27cdf118ae164c398282b3d9c39fb8e11df777050a2c86d08162e5f9ccebe1373fabe2373b267df41faa1e6071ba8a8b75db593a96e32d52753a962b7f5828853ce09236a924459e1f65d15654b122f37a2986101c9d955332cdf554906c881863132dad0c8b2c2d955b422beab6a5d6513bfab9a3e18aa1e1f0cd591cac65b1ddf55b0efa5f3bd54df4ba543bb2d13072d548e581265061bae7cd7b951732591516107133d9c5da7e9bb8e935ad40cb819b9990a67d7c159f9ae93eb3a3a9da82a3a4a5596beeb24dd90dc90723ab09c4eccf21cdc6dbd3882658b10516a80899a7112f13d870332a526970b3e5ca1e1ec3955bee7ec2c00cbf2041133440d5172761ddb779dd75bde758cf6771d1d4a729c94e468c9616afa9e93748992726849b5172c47f696f79c590e9277438d77830d54d4db8eb3f36038375c4e96547bcb3b8e0da7a90c4e8f323847383670747cc781ed763b1cd7eef5966fda6d51a71a538eb020f1c30c5c4e2adf776d09269488c19059516ae2ecdb36c4f77d6381181c465cc0d2a3093167df3821beef5cdfba1d55652b55d94b1b09d2dbbe936e97287693e576bbeff0fbd64a375ae9e686a9e96dbfa1ddd034cd755b2f84d05a80e1c40a3bbc50e364fa7ef382ddc866486f79bf4922bfdf2ce91e2935ba478a4d0a2a15f5b6a776b1d42d868be5def254ecb65c689105519271048b12e794ef29998b261c3a7c7002a3870e674fcd82f89e4acac095a520617e08a384cdd9533429df53b59eb2dd7c4f358549f50873f4b6a760ba940d5d4a8776edb42be5d2aed75b4ed26e2b03438c722884c1e2c3e9ac7d276b3bcecc8ca6b499bdb0c4d94920be934dc060ab22040c57d2bc70761217e53b99eba48e8c5222959496be93493412098d44b291301b19b391630c371441e4c66397e6851fbe8f2c8658c271e4e5864ecbd94728df470ac68a13311f5cb1265dce4e3ef94ebe3a69d4491d5985d129aba0e56d1f6fd96864326a8a8d49b131c7c6d1755b3a41c06a54e19105470d27dfc710c49c62500304983340ce3e36f93ec2722c0183ab0c0cd90e671f63b4efa3ac8fb311298ca8268cc8468412a37cbe8b3b9d78d389389d28d2f094e589325dca0cb1840fdf4522ba15686c96d8f868727671d6c37731a90422b4293a583862063467176962ad8bb6a0ef629314b18714f148b421eaf82ec26ce1ce65135f6f7948bbad19087123470e331c35118687ef610d474a8c21499270b11275f6d0b6f43dbc7126197078a1c6cdcc8db387b830d7435d1865245432122e854842a4ef61d22c84cdc21888bbad174b5a58a384d6c4030e1dce1dbe83b9118c0fa3305b864839727650c7e43bb803c08c068ea82b4f517e9c3d74297d0f5f3d34c2f91eeac02a804e5805500bc80436bdede00d1b81494620cd755b3f43c990a43040880192f41d4ce1346627a5851f51709c1dd4e13b0803818c1a1bc6cc2084114dce0ee6f01d04412427354e6cdef66f8783c245e9be9b0ea7fb726ff917bb2d0a041246ec30723283cdd392ef1f16345556c8c2a346aec9d9bf19d2f72fa9842a29242942e3468685b37f341cbe7fb5fed9bea66be4eb718d7c47e4f70f36fb6ccc3e1db41ded73d168b7f582c98ca62c2ec418b3a371c3778f0440741082cd111a477c39bba7e4bb4744ed082f29c89e78a2cad9bdd977af7b5e941a4f498db7347ef792ae0b890be92dbf445eec1abdce01404853921966a0e1717476adb3e1bbde79afb7bc7b4639df3d1d52b493142d6ff5cda6996cba09a793709a8673dd161d0326491351d2c4d0440f49beebd70260455c01220683471067d7465fc3773d440f67c2c43852c30d4a9c5dc7907cd7b2ae67de778dd4434d0f366ff3cec632948de5283bcb375ceeed8b1b708822c40a3d7c90d274d2302605588da81d5c64ce9e8f7ccf2c307214a60928356650397b36f23dd77ab6e5260b23f7b0308e7ab69175bc7d65d7078c78b2c68923686028917dc7092042081a475a620822cdd97191ef388514147ce8d0c40c5b82383b26f21de774511def309b2a58a9cad25b9c74bb44486e4835876131fb020720416829824c0c060d43bedfdc073b578ec78e898e2767bf3a21dfefce65a486518d314b6db49c1dbb827cc7af8e8df277acc3c87532a2e56d9d31cd9adef24b73dd96016ab627646c2411720390eff7a50026ae300112a3855c0c67bf463fbe5fd88b241c5e4e6c5051220a9bb3dfd8c7be5fd90cc94abf4b6f6fa8f91b6ca0deeaecaec22c51b55edebec8e1048b528ed998570ce70cdf2d14354bb0ec589022e489b3dbd9cbf0dd26c1008976238249861c3bce6e6931746bf3ce6e9b4240599577db833e1dbde51656026be36d4ec7cebe6c0561e941a04a6f55e0c487991cb21a3cac398fbed7da015c388ad57648521b72f66a83e17bbd3d093b54d9c530e508c7ecec15e7e37bcdf5aa8b7a8bd402c9f75af906288bfabdea78d1ddf7f84e732f963c31b5a981089026949cf6dbd6720dd010e85b27579a82f8383a63e3b4b0b7695e5470c81802852688d3f278b143131258d0a4a1b1c6c66939cbb2b03b58e8b75c4886dd49da3fe96108156b15b4e331ff3c72844cb2b0836cec3eeabef2a01abb93aeaf7cbce5f1f6841336b386dd47a11b761f8594ec2ed6d85dbc7de52a58d85d4cfaca717cec2ebebe729c1ebb8bb0afbc8322760f735f399fb17b98f4957319bb87b5af3c0887ddc3d7571e74c3ee21ec2b278a6177f0f69513c17607735ff98f11bb83b2affcc7697730e92b2f95ec0eba9e76ff90ecfec9be7212c6eedfeb2be7b4dd3deec3ee9ed2ee5ed257fed365770ff6950355d95defbe729cd7eefaf6956bda6d91b44ac3e7e7f474082e287ce605a871664e01cbd2341a9bbe97c75c57d7508ddd75ec2b27d9ec9e755f39d9c4eedaf5956fc0b47ba67de51b4cd93ddbbe72a02ebb67a3af1c884be52b2476c73aec8e6d5ff96acbee3869776cf4950b71a95ce8698f3c76bfb3af7cdc51b90f8fddafeb2bf7d9b1fb35faca4d1e2a37972adf4c54be75bb5bfbaa9c080d5923faf2e40694149f79de4454beabec20d7ee75f6958c91b19188ddc9d8d7ca491a0985ac310d918683cf1c933232765b751ff1f7e6382f0fba4f8ac0e1557ca62ce89523951ce1ae9876a7b9af7c15c40e8aeda019f64ab622b2fbeaab35694fe2469005e312af89ad31c2258f1a2fd87651235303bb257dc206f6b6e4012017cb4fe4ab3540e60ac8e497e8f2f0e321074d4b5a809e9f49d4a4af562aae1cb9b27a137611dee91172ce36abca15d0bd572bac5a91d95706983dcf14753647fcd1400d9071ce5bb5b227e016e0c79655f30b6366dde42d5228228cbde2ac14b58d666f2196225056e614f8a80d4afdbebd694b734b699fbfefa3506e683c79a2501e9b3555f50bbbb3b16409f971e62f72ce3a7845d6f21434046d5db0962829eb9b014957e4cc2bae9c3fe6225c5b5db03ef34a96e0c394040e1805acc726a6a17b8cfe7291de04d91863ddc6a20faf7917ab34a0e8b3c9cb887075c982fa7d6bd3854896409d66d4320a44da9bd0637461225dc0f6b878f37d3ae791755b24cffcb6449e39cd66c7a2577e5eb64702e58012653eaef8cc770e4d9a0d30de09d053b463251fb01f73b1ac670aba2273f079bfe6949582d73c050effbc430d7075d94b78cc29bffcb32c287d8f5bfd376ddab4d159176132224d61599506b0c7fcc6c8b69c96dde6def2dbdb26cbb2496f4dca5d58bb138165553368456bad58f594e214a52b544f79e6a2ee9fbea32e3ba6d55e9c52d9129b34b7824b29148a2276fffef2cb59a21d4bdeb9e545f889203b5c4061868464e4c20c4e2a2cf971040f66971c2135bb72ef03c310fc3c9d83f63ced7d9fa76738d1ba6aef03c1cfd315a8a9c70462577ea3cd105a6bef0343711cc510fc3cfde5496bed7d60288ea318829fa7993c69adbd0f0cc5711443f0f33413adb5f781a1388e62087e9efe52bd0f0c4531043f4fc36867b4aedafb3e4f571bb718daf3b4e76928adb5f781a12886e0e7e92a5a03d19ea73d4fd770af00565c1313e17d6018829fa785c0bc0f0c43f0f3340b3192685db5f77d9eae4bb4aedafb3e4fd72536b4d6de0786e2388a21f8793a870c5a57ed79badeb4d6de0786e2388a21f879ba460ede078621f8791a081249daf3b4e769934b8e8eaac8fbc030043f4feba03d4f7bdfe769194fb4aedafb40f0f37425c2052784d05a7b1f188ae32886e0e7e924705a6bef0343711cc510fc3cbd034e6bed7d60288ea318829fa777d05a7b1f188ae32886e0e7692f55ebea7d60288a21f879ba470f515a57ed7d9fa72b0b4e2868cfd39ea7c968adbd0f0c4531043f4f53d13a88f63ced79da868c6d03aaf4d4367eea248c91cf317224486df7f0081384c78d89558b65a52c8cf9bd59e35a9564fc558c535b7ba3b76f6ba444285e3556cc6f05bb0b1e73caaa9e0c1ef39bbfcadaded5bc6fbdcbc7fc7ee02bbf19bff85abf1ada449aa28baeb75cb435c09c621d034cab4d79a6ce351a42e615ebe82dac352ce9191ac97dce573394d1159677f065d31597067f79bd95da54a52b32c619a7b0411e458006ea076099292b735c82949579a6dd164935f071fbf399f72c44e61fbd69caca610bfe5acaca587f8e81e6e205bf5b6903692bd32e91c5b4d58a664d0ffce5afeb4d61b3d215998b60b5d96bf097d72cba461bf08b8c7bcbc59d4f2cc4e6bb3f7d7f05ecb92fd1be01679c476bad5094f6464a37b5ad4d57ac98883a637db5f5b4d6ba1a20a5f90e4172846cf69a717a8628e4440172b9f621d07bef5d099de159edb02bbfb406d5622222d0f7b98330fb691d090803f5b445ac492f51ad3d54e13bb0277e3841040a45a6b0510a13444f902dee76725b33d1c3647b627a58d85f971e1976e8a4bab1c521787c6cf0071d1c7b2f51c5b617a4099d18393da890725cd89121678a2a49a58667090f3b274d4e10dbd3f5d490d3e9b23f1c9b9db33cedcf4a0cdb63da49e1498db1861651a808098397201c5a66ecca290e4640012d8ef5b1d59add5a7bef139c1c4e54f0d895531c20bb72da811606701a0b084a5200d19004fc3cb5ca252ccc240c20b4a6009b0901c8d70038102b287f15433a845228046d40c4ae1c0828cc8fcf8ad39eb1071ea1dcce1803e9d363349f887b178e37f4b6928352c064d4bd625747a88ab2de729eef19786b6e175d41399012358c8c2bdff726ed49dcd7246a5409628993f2ab665f17fe850e2ad08a30d103111d9438e98b22383464c6cc78e264775bf8ca492d34045b5f69ae01d67fd796d974c1facb3359b3ac6c925048dad22663a410cbc2f2ca4999652180afa492a9442a994b261213a9b6f96e26d14c18cd8c99b2b7bcc4dd167572a68997126c7e784a7359f85ee6663491f1220416c6c6d94b1bdfcb9d0c98c8acfc808b814494b39baeaff1dd7c75d3c8d441f6289dc81e5a984a5bd9f4b6bcc5caa45849c6cad2755b1e70097245499a1e8c90ee0adf4b1f3a5e58b244951d4ece5e5e15be974238e1848d1a3ba0a0f972f6f2bebe97bd2c91c2703561d8bce5bbb73aa8511745ba2e11e9cabde53c765b115833660b142d449c8c5c1adf39151a94546842039a1b33cece679fc2779e64822640a4fc8852e668c6d939ed677ce7b5b7bc731b6faac27b54e147dc06d7f196c36edcf57acb8768b7a58232b4353ec468e28aba32be0f6569c24a0d2686a032c40c671fb27d8cef43b7324ac784871dd6ec40e4ec43b847e1fb504e17d58776436c940c2929195a1a423284f476681c1a87c621d95b2e84bb2d0e188901c99230b720455c18df857238603043e4a8890697b30b5dd777a15d949a1a1b696239a439fb90abcdf7a1571f321ad231de10721a6f08691162126a7a2b741b6142234c68840909b96eeb0434663f045143120c294f7c17da81e99543932c46aec438bb909113df8560d40832493416cef478ed7076a19890ac0bcd78be0b21955153860d54d45b14bb1d8adb0eb7cbbde52862b74501da0fb42c3bbca8d972b2f98e421681303ba20441dbc143767614b326bea3484212454a2d49172e282c9d1d056dcd7714352adf51d876bea368aa82a247151447286ca0d0f116054cbc05893714e20d4510edb634c086071b45c090715341cdf7a025272cc8d0830a6896cc387b906df73de8d6429329638478ddc21c9d3d0897e67b50ae07e9a24425414aa292a0a520246f91de06252505c19282623d48f69603e16e0bc770d8d4dce0c21926d07c07caada9a103861cb4cc705a3a3b90eecf7c07da356961a67404486ecdd9835c51df835e3dc868fc1ea4438401e424c2d0f216e826be80985e4d220c28498401d1441850ed2d0772dd16e5724649131b98c81dd960e63bd0cb8c131f28e8f8e1880d9ab30331f11d08089b2734209e7690393b50accc7720199721df81664048e1d38f9af0e987cd0fd44fd4db9f5d98fb09733f61eee7a7c9134e40c19c9eece0a1fbfe83a2489a2168a6204133e4ec3f64beffe4bc2c2d19b30346161f67ff19f3fda7fffc3429f9e9a1e4e8ed0f2c4cfab11126fde8086b3ebbb0f6e30a6b3fafb7dc87765b2f8c6a483e1c1184c9191996f8ee535b80982f4f357081d1c375761f1bd4779fdbcc8a1424498eacf083d2d97d7062befbe4ba8fce272a84e1a314c2587aeb9314be7c90842f1fa410e6030b613eb1ee237bcb57b8db7a113bc20c911c56f84206e954e2fb2a27812b379ea0863853a3c8d957ba0ff37db51342e409277e5022052150ceeee3ca7df779751fa3d4771f1d55564e55b4bc0d7dffbdf7de6a39c615ddca55219714f7de7befadf6e2e84dacc2047643a2a8e8ea5e3f665c1d13b96483a24c5a5240b9a1f1840b14246cce42d550f29553abe556d73da2da309a1c4e365a4b1d2531416b48ac5c942ecaa1183a1f9cb22e09911b59f7f29e3c957921916d3587194ed986c4f8975f198f689123444a8e162a02f46002a33a216b2791469d664811694df82fa5e12302d00324ca860068b12c6fb602140fdeacea30901b2a541d12f62fb74714b9d0b20a0486325a86848b958a2b478a58e59ab9cbe57262855c4ed07fb9dd2e97eb042d024f674a4489aa99827deab29e79bf09d75e5b8554a0faf4eb6f5af9dde6bfb8d505b795352572c1d33397f5a4e404beba024b0618db1b5a1150e907fd726b390dfe727c2760df846b5fa69a7b2fa739f39bc71b75b382fa960fd11594bf781441403f3eab1e9e1d954e0ecebe4991a318829fa733be74055d4157505ee47211ecf7ed6bd6a0beb0d67a11294580b5b57e40f98bd6f779b5922052cac2564a02ee9bb330e6322ccb7213f0bd97f36b7d548c712e9074645914538c31c678c43ae7aea516f3d89dbfe594a7b0d6567395dbd5de6b93b0b6d2106cb50d68011229feab1c344dd03ce32afb332fe55f36ebb5409010298b4e29a5566b6e35b9859a2fc0e509f86b9632f51ad5dac5596badb5ce69f467130469b41eb747c35ed110b4e779deca8712e5d56715e49d5ff065ed69cfcb3709a6813d1ecc36f72211bfacb5d6596bad2d40a21937b62c1e78d65a6b8d4b33df8284d04b62d65a638d31d638e77c75fe9cbae96aad96b17a92672652a58c90c750814b14c552e753b4a358e253bca358de53c4a358daf324cbb114e9831f17c17e1cf39fcafb2ec0980d54c28d0999efa726d003f67f9cd6cf4bd117eb5702a621d0ca7109d80413e8019f39fe4ec8d5f596e7d7676dc61863d385cd8dfbfbb0ad5d974dbaad9063f3da9cebbaeebd36e9fb4a56817b86a6b5a5b1379bb35035669fcd655c86712dbe62ced98428d5f57d4d948932e5caf475cc9e873d0a250105e829c83100ac1621287a176092d1e2021a679b7ddf98a9164f8e6253dd9635011e5e0dfc90f9f40d33914b36314cae9bfad1a041430931c8a7066bb16a953d2fe7ac69c023378207d8376e9c4b128399782364e35cb6f929cc638e73ba667b8cd16c8cf5ade97c36f18eaeb89cc8071c26db729871cb3671767fa0ed1a5435aed65461fc599b7a537c5566f86d15dd02c0b03f9b98aec038633c03ba55ab5a6bd82b8faa566bf65e79e5c616638c31c658634c79a6a68ae672b42ca2d9ae5bb5fab0cd30985230c2845a9025707ca28ee65c7e7a9c9d7295c73c4ba12dedba443553e770a773d659679d2fcfb5ef5bf6579b39283be5acab49881865dd8b3aec12f593fda65429a2fbf626796f41f4b8fc7c686bb5a22178ba254202c418df5e0d8da29941da67575c6e1ab1290bd325128013f046788c4875ce6403827c8a641d45c6dcca6f599544fae99c8378e43b06e39b9ab3ce3af337015badb3d639e77cc6d4bc7a5af33701e30c05055163ad39c510c0a2dab6d65a6badd5e65aadcd55ebfdad3e50b5c25a8f25dc3cce44365cac5a7d7c0713679c71c6d8666eb5277ad6b39ef56c57bdb51ee8426586c5baf99befac9c72c25945801e4c49a83e3ba1b5fae4a012440ceddbad228ac1ac2c4b7b18638cf1ca1cf70bbb7ee35ed1b0914b693d4381ced4524749656abaaccf684e35a544fa7bc1e7e5acb5a7b76e367e18a7c0189be3a6501e27e071011e0760ab1ef7117f29de2faf14011da81f5c5a6ba2031ebfaf7d6fae96afbefa2a34313902a8ebcbccae5f598206e8d72608e88acb81ccecca3bc58d98d65abce52d6653b2c733c73404cdb3999fd839db155ab3b49e01d61ef5b2a6f7cb606c61b83830c53c9738e79c4fb0d6c4142cbf2f7bf8a31f50e620d7a60f8e5d29fe6cad3a624f389d33bfb174b0d95a9e2db797c7b7c99b54f839670ed2107451985286c863a8c025de943b29149f39e00059e691dc3b26e8540bbc0f79fa635e3d8ec907ec0739264bd0af4333d31531c895dad46762ba22f3aa359e012efa6c6ea1cb6b8f8f2dc2a2a28df7fdbebec2406d7392260894281f808492e8f307c204f6eb0f3c7e00a7d59ed4b2f8f4e7d98cf4dd7b8b6e8ba822104628e220e02d728448c1d1a20806cfcb5cbbd025a63ae79cf3f7dabcb77287eb8433119b35d725c6ef005adb94b0826be50b79ce7c73cb42b3bee8149b82e5576e15ec6fdfa594ee06c8bebc7b4dbc19946783d724c8078837ab2b402d79b394ce82c198e6b2b7e033af5ae49a7f34848f6b0ed21042fc691929149d941200e432449e023fc79a7925806769f0d93e186230ff470d80b9251bf0e23396c1e38ac7c726c647b56e4f6badf5e779fade6bab976faa0b9d73ae59d78a73ce799539ff3cf201996b911ce1d39f35219bdbc456c6822856ad371e41f3cfec2ec6d75c6559ab337baf4c28bd7102985b96c69c8ee0618cc907e04f23f93259c256adb28bf1f19523578e8c3688ba62aa29f53cb36b2d86746b7d4d5b02c61ff63ccb750bf2d7bf49dc19c6bd3e559b1395ca6bdeebd3834c689cab0da3c971fbaaedce76785ece1f0d415317a59a10fc4aa05ecacf31743d7cd61905a51122ad433af7c08febb283e0b538921e07c12456d9343db2045cc2073e73fb811ee8791f68b620bf364dc8f8324171187f2bae72006e711d70bfafa601d6637cc263153ceb710acbe24eacac3566e11dd671dd3eda46dbd75ab50c06b7af3068fa0a03db9fe0fad1f599dbb2e6dbd7dcf435dbc80a7867d9b5eccdd162d17edff6b4ec733bf69af75505bcd333c7db25ba3c2886dbdf14f54aefac79844f636cbad0b2cf15080cbacf3a6bd9ebb8b0cd42686df613f267ee25b1b3d6fae320e0f9f590f674465237ab88a461191dce2a2a6ad162f3d1cca1c06de9983926f881df87416cb3b556fc82b4798b971a79e637654996f41689380c33969c12652e96452ad88f8b768e5c39f2153d36717ef1d9ab46d49977b14a11bbe90a323937d558d00c5ef062e945d293505f203d362994c731c798d315148a87710ef9011e83f098a8a4ad7d390d01e4b80586b15bdc96063cb3af5226698a430f9a2f004ab32bd7c0c51e3633dd3d806b8c29946f86ae7e54a4e32547b84fd7e95679ccaf14dac2ae4b54bbbcbbb83a7186ebea95e61e76fdbdb5ef5be68d9424416b9e31ae617c2364e3fb7a6c76cdab8b4bc2f7d9bcb7d249bf4e237cfaeaeceb878cab7b6c599e2e578431c62e56abc755048bcb6ae21554cdc3329e3ba864cad7f3929c9911812900021400131700002014080744426198e66916cb0714800e6b9a444e48481488037218464210062114cb20600800c00000409129a2ea00261719f6457f11ff845c882bf8177b9ca0540df7fdf14db0731bf8ad33c5663b7bc7989b18a81aa0a67c0394638f116ea2579b3aba4224e3922142491d4f7be39998ed2bf76538e4c324e7fe8f64840fefc06629cf8453cef69a847239fa09063d1465f1d02b7b45c9f98c287b5fecf9c2a3b5ea2f21fecdf78af5e2e18466fc25375ca521138338b7f8c0f20ae63bae0ab5f1b702d28c497a3ee0aa520f287a32ed239d010abb393fa46312199c77812b980b2d488cf0e8411f15a1644ad5982958281197125ef99374a98c2179bac98dd59e253cdfb0c2769a0b1743f3105a6ec3f8abc80f6e9b1d7bc47fef8979c8550a3fb5f2d059b6685232945c627fa79bc6452a9567308bb5f41d482272cdd45754de11770763414b7787aea8c26f40d3e8aff74536fda1b6a218bfe1d0062643b0833c68d32eebcf1e658337ad04ba75bc15ffb09f5732c8b6a52a642f1e0d54f69f8a4131410d0d3b8c435df9f4fa77e6bd5f9134b1f9ab6adf010ee85dac1d50552388bd98869ee318393c989ae697c8d149d8da64401af1071b146981f9e430961864e7041116f32e1c83606352793d4d9c341a7de86bef7c0a408610481e496154bbf789579ef789636660251f0eeb257bf5d9810237b14538ab92143b0f1f8125ef3f47940881fe3ace1f79136b8a41130961ce6f5e8317328c1d44efbd4ff4b227b2a88dcb074c519c14b2630ca00636538523fe619de599d0cedaa8d606ef31e8c04a8dbb0396eb475651a278c348c25b5828f096e58c186f0612c9934e317448999d91ccac6f559c49a962577364cb9040367374c02404d49141ed72437455e452f39c9aa701af9635002a7dde4791eb6489e6fe071985ab04c940e142c14d6f04116fa068dd6421d64281a0b21c54264f7f23fbe37d3e9ac0eda39fa2f0f502f38ba2e1642e82215e9ca56d8b12c369d5a50d27dc819d093a6c229b7c0a1bcda078b4a8504d550ad0860ac1f79bc655272cebc037e4da345625377458ec5cca5d87d0ff68ec58ce5c874168e4274af35f143bb041de8c9a172f0841483420aff203a3a4180ef2d320d8364c728e6b1b40399fd1ecbb40477af03f329e3d2feb9fb9414a360cf9a69b60e44cb4d9ae2c74c12328660637cf48d13ada2187234e5a932c4c5097213a251bac2d3ecd4d0ced5ff550b6f880e2a114bb1d42ceece5d35f5dc990f1f1e02b9b767c3e5eb0810c1960ae5c5d0d07603373fc5633f8d2da430189faf7190185745dd5e9133c1881fe3fbd2fec02675667da79cb7b964bfcaabbe3c89fb2058a3b208afc8ac9b6d656cd6e24d92fb421dd9c3df745931d39abcc640e78ecdd76773c460a14de2093e453ef81d66b8d220ee5584911bcce017e6f9caa00c3ce26f7c5d83f9ab9b799c5eb086c34e083e36496d182129c6592a6503de9a08ccae0ace54e90c0a1c2a30b05c56915878a59029f60daf9fa190b1da7ce171217ddb1be1d1ed83727b06d134a9525ba07d006cbb0e9e280e10d51260609e28068c90548a953a17ef9f7a1af1328b57dd2c4ab7d7b3a5e9b65dac031f3cd1b23e253145703c7e69bdfa800ece04a5e2fe545b68cbcff1f747daf93cbe5bcf78d4244563a98075a27bbcbbe54b0b809bd31d84ee45f850e11b983259529d2e4ad7ccb8995c13d01e0288ba8ab0c27caa186bd257421fca6525189992e94602f11caa30f24a4cc7663625dc70195a215a6831e35450abca8a9f581029ee8254856e32620bc02bc9db2856fdd99e425f714a21574605ef4f34675fbae3a5f0693f7a4d2d7928c5068c0da6ed68f68f03dbbb903f22745e8e29b8483cc877adf5286f5a23c6919a01239966f8110739678bd0e041f5da5d16d7d587bca7c97fff7a2dfe08ce611f46229ffdf7b494ee7a83ef527ffec63e8fd643b6a8ff79bee40b72383d9e4c3d9cddaf747a88f85c57ae7d89b9f99f4ee9ff8481673033834cde911c6d3d0e34c2366d26377040c6a74ff07628d4b4deb4a530dbbcdf95457c3a4e1a0717f007984db8fb269ce08f9340b1feefa7a9d5afe8bc963243b2c2b28091c61a8c6e1aaad139a562fe71799195f35ad3651fc57ea4f7af265cd6cd1e244533720678b95916a083676902596fea31210e8c0c746769804678f260cf8443c92dcf7ddcc1e1672e629d2c7e011a44dfcf8478f456c26fc9dcd9c1762c634e03e60919c809cb445b5777df2d5843b425f6f3db1466e8ab7b5ca7bf8349f7a6affb46e94615728dc011ec723eef348f35411113fdaa962c781e2e201b189af082b31ccafa49ba47c16d27fe216493c92776eaa6c0c9217fd76c2b247035c64accc811aba50bef57767ae0dec03342da617762f687d82772b651b7deae36cbfa1cdc3a9be3f5c4a849a33f02dbe0a1297450b07ae07b748533dea5059071a96c28449558c7014b7a483d757568788d23a8409c2a4f61b392bad889ecaf89e54d80023c5a2ffe730dad1a5e23033e08be0ce2616ba9ec04e8533dd6124a0c2953a569a4b878e321f1a75796a899f30bb935cea2b520356c19e5d3a111f2750620c3f36529b60ff3c0e88c9679c7f0061c4b885617aa573e1d83e3d57c2f1110acc15c148e2ca45d5e1a45468f0f17a2f1a74b1cd91e18bc0577af868d9af2b67ec0fdf081216bdaef6aa70bbedc5680058549c595ae8ee55d714e957b131295e43e7c1d270b6ca010f6a2abc2e1ee18911264c470a998f51421eca53ac282a3c26f0c9fe013f9d95c00ba957a121d276c7f8b2668672ee7603f8f8c881d26387d9b14e85b86ebf8b02b06fc728e10fe3bfe33a4d48919abe33179bfbccf627407754b99926d6b7dc1ae8ff961b0993cd8cf8c08fa1d315a13e4e5e0cd4d582e4d5b2f9af7680cd7587180d29d48d4092aa5bebe0cda609a2df842e49729f35831301623575cb30629d53d35e36331aad9d099b2e50d08fc9c20c82a465d0cbf0646dd4fe62d4ab4bfdc145b94cc4d3ff634a897fccac470e8dc71c7e2a1800ffd2c1e570d8e97f9ba0b7ea41ddb8a07176908c6e7970f9bad740e93341e5d99be0a8732bd0e391edc942ca2b597043208d469520c8acf565aa243484a57cdf2ac3e6a51c875f36c4b251600bfb3191353269f603f32a105c4366294afb61cd82204e5612223df0ad59fd4de1df64f37bdc198f6bff326fbed62f0c82e92047190d097d88beb7aa838fa9346136876cb248ce9d228d12e3c59bf348a928b253cf937e4b94461573c040d4fb7ede8e7a002c4331d9c6dcb6373ae651a6a1835a7aeede040de973f6897b6375274000be1d800aa3db73df3f60b1705dca8e42a96cecdce833a3d3f4d70e105afb49722407f607a9c7824dfc3176e74f956a735372ee44a02b5a4fa8adb7f53a55b47117b97574b51abdff11ee8dfd20fb391741a320290d7b58b42a54e3741a43a0718a0514e83d8ddd9b73ee0c67b8df92eb0890debc3387fd3696b0af05e4906b9f85b0c3194564b1413a407f17b4de60396223a3606e71bc5752391812b146dcdd29f7f9a8cac391d6b1f3bafb89f6ad9ba3b078ebb13eec7b2056ebc8a94ccfcdab19ad9230043fc529031d1d47f3ad0cdc8786886f10056538d6833f6ecc81bc98fb4284774a0402d4b3441a8e08be6371933f320aa787c9c3978f1bcbe3ac144f2bf12a5eb623069323c8042ac0b228cbe37192a3c9e114c1ad128257ee64942e8e3c56c3b9aaf98a2a9e00a305744739d3b74e250525732b810ca7ff6700daa22dfc9474a931c3524fdfcc6f9e5a188347fb00da07f6403dc4a5a00ab8f22195a20b053a278fad923aff462a04e6e379e7f1f23b56aedd3d5cd31d93d3f74af6284561477ff0742b11367c072f0cb6311f0685568f8fcb84bb4b750b836f511a401176ee4dd90250b037d732cfdb572ad981253fb36560df36b74da03becc6de0e2ca0ab67843aad05e9483c7f80218a06e8c05faf10cbdbdedf4224702b7aa0abbadc6c8ba08a2e61c8bd684d1aa0acce059ad000ace9fce670bc4fd590526007f7ad9602958415fc93e2735e3dd16d528a6b3a2c76c092f58f42cda4f28237b6a95587285bc6670a1542872d2bbf40519a1061f11d7206cf504c527487056c457990a356dd21267f710d46998d3bc71f0df15f660dfcfbb6e6b451a7be56952e51f71483ffd001fca55cb978454194f2e22f0fa8dce2377fc4807982bc07404661499fe8eba5c9777db8f76c5552b337087ddd59e51b874dd072ef03563abc39797328299cbf815582f8dff8b287aa6257890556c140d778d57070d3e4689cfa84288d0898dc74521a3baeb6da76698dae12286b04cfea59b3d716e35611db31530238344b2b19d3f9aa0a54810aabdc835c758511e12766703ec14e5faa199962304a69574ddf6b4c3da72c5052c24c9d70bc7c21f08a02df41a8c41a35cb6ba19c35252d685a51e185447605e40047dd7f6e706760632a157943766681eae57999064c4f15ca72e9749055e2df87260c3647b2e4b8c12ba4250b995cb2bbd47a17f5cfed92513f0255639b3a0129ee8756babb55898efd66fc05adf7da19302406f3d80cae69c67a8664f8c5b6139997cb8ab92cc3237c3ae9a98c2a3cf0d4674afe8fff6d9e59f99d03ae8f5df5398e4c4cb22df500c0c1f71ebde26bca5285282b35e516dc0c00efc28545eccdb88429ae4b81f1b22a13972a31f7b1eb8931469831f681048fc5729eac0892c83a66a0a7e759f6a750e6f68179c94fe800c6997d6e2ea5aa6829593f431c2148b29188ef49578991f8bafacf1c6551a313ca562a0d007b5cab88eb72928e1b0b137338b3df26a3ffc45392e892934594bdf1c6be9ecf8e4bab1c8f07e569f3242e7961caec9d88c86e691da4d30bccb7e5e52ead52380676c2ae9fe61c5ef58adc12f7e49eeba571e53fa27d0b750c2bde7df847b86df30db11de36d49b8cb64eecbd0c11a578bc8860fd37033fbea24d5329a5406f75a0b2f555dbd356ee5d2e1c8789f63d5f4fe6ea5aff611b4156ec7b4bacf67be90f775da3c82f3d9456746ee3ce1ae474d6032d766e6c50db858e1a9882306c626abc5ac32b56fa540166dfb670cfdfc66e89bdc7ac3bff6f6de1c13310e2a109b40b36d20872ee58147e7947f8adb9291b26a6d45267f22863e9a08f5da14e026d0fcace79d66a3afc2388a5262a87c084d9795a0ff178bd7e4b30a5e38bc4051bcc37c6bb7b2603230a99ccbd549b7481238e1327cee34a991f988300f07a0d0a1e21c431647c245131a4c68d78a6b0928f4dda6b16ee67f0051d12a7ea18b09154b32691d9a191449b25d68167346c81ea243b96f588c181f396e2010e4c3b7fb14db3e5e7c1808c9318b343d809cf0577182031ad2be5a2a380ebf91e13b3788c4b475412dac035dc9da7c93bdd6881dbc3f2edff53569e497bea0788d5f311b5914a4e89dd6df42eeb2d1a4435740a1d76820948ac9c6d2f074883278bba7cdb34e19b961d9bcf6517332f4a470a7ce370c82d6bb4de1a8a1c10934766b90c74f1d91c76e76ed8fafc81e3109653248987eac6b95c28cef61506053b2921ac8c4238780879c9e853eec68733e15a481da270e7493ee53e0f4ca50a15b1f500b738346dc49d7d81061e4b38a0a4baceda651c2d02138d522cc8c97512240a4ed4eb5bf0dcf73d6d981a652313142223373369774338e9809cf89a20b16181f138798fda90a3765303282d88655962bae0737d892b9323b1411d13b85fe4d2f0585143545dea69150dbaec4863f43880a9bf25fe67da4b7c8b9eadf92595ff23b178da44710a843f92f09ee81ed484144f5ec3dfe11992e5c9fde6f609665bd6fe4a65a369b6530ac45b217aaaa4c24547bcbf359ee5d96dccce87ada3842aca1a30fb5019697d239c08db79fc2102cd014eb5715c972c5a2dd23a8fd65b37e0bba0f99fddaca81bbd6d8d454e75b59cfa737f98fb29f70a3d5157533104ace001c5b2a797ee08460453f0d1a8bb5bf02a8c606910ee440588ac2f945038542b74775d83393d39e4b6cad6ab002d4c8f6932eed55e57e20145eafbc5293e3ed147122c6036e484aa7644a0014ecc029771d9fa35e3c75c3e68de5b2beea2227e7be352ead373cddf59c59fe4d98088420bfbfbf76610d0c77e91aa34123ffc26b5d537c01ea36bbb8d9c393769ec2050d771be9f0ad95409ad87559abfccb7abc82d67625f9ddf96214199b1b24cc9d35c703dbc58fe607be860a746f67b127381169cd3f8c4b8007c5cb40084d06498864c002ed4884aedb228911fe0481406026a8754ea8e07abbc3026919f51ca820234471b463c737190a21979ba1364f8c69748f9ee9486be7472bddcaa102018527167c1438f4514f0c91f78e672a92118bf42a784a1152a58a7016d3a8b9512ae147cddb8abc6ef1103b38e254dbbd806ae9ba22340244fbabb6dd6e8c00e1f95a5c5884f92e711701bb280799eb1609c0201910738d874ec7336903cd2dbc2257964ae3fe0c69b0f1a4d3ddec167d5fd4c42bae496920bc7a1ee81d16ffd5a4b886b77246f84cc45b24785f27c4f06c4eebdee60de106b696db540e89683e53574b4434f313d00e21ba2a334fdefcca4271a4ac5ec6e9cf8e9479f3f20e4483be6f5008141808645e6d1ddba05babb2b98e3824ae72369a6299c715c17b036c120993835bac686b4afb9947f9c2c53193746f47f21c0d1d8ecfedadf5d4261dee0c91ba1c67ff2a52d444f4a967714110bd15e578c3a27f0a65a816d3cc9a964ccbdc981d72e56f6db0376a691cf83d3f4e382d3dc95bc63902ec406788b7e177a849008e750091a816fe56386fe55d7caa61ab91b943bf643e7ec40be4ded40f522aead6929ddee2765c91b0782acdb72cc737f85e627a1fa29651343db72d540e722783f82b2f5d637e23bcce292c464741278583f9a9a62d25c75d852174a4b5841515c3409ce2532b6ab992742ccbabb127a694d9e63899e1977565ffeb164104194188f4a29da9ed924a29e354d361787cd2714afd8c84d3481e6141fa98fd836060b8dbd07604a065e7f0a2bdb46cb4638da2492400777c8348b152307b77dba68d90e22d558d42d910d5d7f4d23d2867edae3e5547ca6eb610cdc3f804c998dccf7de5eedc304206e754a7cc393d6d881cd33586a8c41818c816adfecaeac46f6a51e825c1c57eb65ab05dd87c45b15f7e10ec7216795cab43758dd711cc43d8260821af2d9c599b87da3b3d4428638acc17091e550d296a8d36fb0453a38e5aae03a7425b883f33f599849658bccc2a0a1701de09f6f5da5b8a246a87bc2271312bc791d7230cadc9ee9c239aa232c49021c4de6c7aba563d7e0c3fae8cc5dff2736612fcb455aecd8901f84de196ab9f654eba0d43b1e937b754259c14c2181ebadb98b8ba669a5a678acc4c007bda276cf7911919dcdb44e46918ffd364cd8193fbdecadad9132d195029d9418aa6d807675c093557e6f2b12df2458554ce74fb99cb304aa7cbd43d11ee7e6a0e22bdd448a39ae72a03d1a49f8824ea51b7101664544e2989c6837aef3dbf0ba4a70e49afd36c26d5a992b1383ab4aa04a768545a1dbff5284bfa4c0b9954b781d60476b11c4d1604959b81b4bfa3919b754bcb1caf7b4adbd13b24c5dec30465384ee4e46fabb936f3404f083c09e3871c39dcc12100842cbe2c0a35e91c0ed9c81f820ba04544276e1f2f5b4443260b59f20fff5b09e60c7ed2a40e786815088dc02fdaa21ab54d2ca5ea2150ca661e2f20450cf38332c8b3143147ee9ed65e97788ce5ca1e86f256ee6133eae45876ae34f110a8472afb375256030793b1a05c1712958c6fb7e9309024756c385152f308724b970d11b42a043a584d5647471e033c408c7b92d1a288cb4feec5d20edee573b31916635c536501fb08e1e3b08fb143bce488fa55c39d0594a5f9f2a02386dc17a4207874b173baf4d173040c8f938eb0bcfb7da3487cf75e290eed654350e70981c70a3ad04722330a9bced19117740b2ea68c6bb6ef3c2c3d8c3ccf4e368009fe1ba8e065cc806260e62483865b21e462fac6ba91d32a50be78ba981f2357ee0a68f4377b448459d00a262b4648fd350ed4fe958bef2dc17e7a90e34ebfbad2d45dbced03d0b24e67d756c8f403dde5b780d5f426121db00dd4f9ad5f230515d39a9ab40ba24f2817323633e064c22a8c393dddbb5072e7e3179701da5e0d7d01004704b780b033d3cdf36e20240bb39d83b20152f4a84b3304f421e57d503ce87c09d90847511af204879d7d8d26d313c42644c9afdf1180d63694a5d8030a1271ac16bb81c766e400d900d075e556e2f9b2665c5f4b772d3a3e0ea415d9402c0cbf7987c0e67e30fe06e48e8469a0efd3bbc39c64e1199a21d7f873a8f2ee05cc3dce46ae14bb7bdd59670b6334c689cd2334fd3b9b1e1c72b66b2204e95df12503ef32b1d9db05241debe495517319d08f0b48c83a3ecaf6c457b3cbb087f0c322cf48c6c5cbb203514896726492888a934b42083180f727ada7179d061ddf38c6826c2d8411fe8d6ddb4c7647253d0a590c02e6dee4666edbf249249e74c41ad98f5cc7aef7de94015b1370f6f554508af2660e9285f0beb2d848c82fa802e1d786483694b3c3c4f97960087bd4fd60c09f43eacea5a50c313668ce0322ffdf4384ec64bf2f9838982ffb459b0f82363cc8cc04f403d02a06cf847de2351e9059a2c3ef5f38f5e639b366d043dffa24030d136ff6cd794f1673e3e81a50e732090da12c83959d224cabb0da0d1e78029ff00a48b032319cb09af87fecc5894baf4be7cb5d80909ba3ea24811f5601ed024a44d51a9587aec5858228588aead7abf6bfdd78fdbdbcb20337de95850b18507dc7eab96b93b2669f41bcfbbe0c77873a341a4fa73780047042c1c6d0690d3e2bd34575391345df3dc2f03bd6491372a6045ca9ec8cb66c6fe05721b2b842c65ee6196c6dc4b4a099689f4d1979e51ce994243b39af85d60210697c6503c351651f35aac673dabe5dbca5917162301703a5419a827ff58e4f3dc578ab2fc9436a6a7818e73811ca399865cdc04c20270a8bbb59ab27211c82f07ff04bbf955ac88f53c63db77d69ce84470bdc53abe7f82edfa7552a8c934218406a6093e70c2a29c18c22abf395329630c4a493d68bf0721e8b7d84d515bfcf38af1f750b46539f24b5d9508b29fdf9b4b4b459ce7d1689d2bba66896b0cfc22cf5aeeaf373ab67c9c0912f23e652253d7532efe5f36b4645a36bbc5dab59343ab48bd7628c27286f089ab7e8454d4f3d43ded1104b2116430d3b957c05884bbe7a48ce491cd0be762e6374e9db94a14325edf1fdb73519aa7c78bec02b1f349ebff65ccdc0ff95aaa4af2447fbbed8adfa535490a193c15f79206ce71a43f7cce120160fc88048d7f2b043e9d791dd1e731644dbe505ef87363e19177d54e8f9779d1cd2ea1d69cbdd5df3c5da9064c893d3d7c44109cbe93eef9f7d1088ec88f8731ddb51a01fd7e869c89bcb504d493771a2f89062d46a0249467871b61fb0ad26b8d3dee8ba89323fa5f8dae318ef7f962f982a89f5d7a8f65328f500138dfde51f60dae372fd2ad4ba8df48601fe903c2ed1ef73989c4469f3fad168962f9d38de521012d33d007c975eecbaa875290f9ea4b047a8abbcba7a5a43f88bd7c39a733c124cde5a5c887bd120c20ada1f44ca6f5c272fd8e41c92d4bb202f5941fbcffb2c3537cc55312d8c50c9a13c71a068a5ab982b157d41c48f7154bc5ce3eedaeeb4462936cab82e0ba8f2b45a6497db3829778100ad96029ef533fdd24b5f60249169e84cdf5b0bb09580b1d72f423a528213b2cf2890814818f8bb1ddc97aa13800df76037b0f1d0cfa7080726a5e35fbc1a9da22f6d2de81feb55bc16394ebbba03bf5ddaeb188d7f4671f2b40f7b460928963147d6bf6fe93a8b1480be87a874a831d9d1e730436572c00d0299e06fef18050a72074233652c5f7d737ecf4f84d1c7da080cad84bd321ae64e000e51f06a34306b98be6b007559d9b334ef68c94df4d5fef74b0ce8b2ce35d155253778f47d24291d0e5c25650a52e65aa70b15fcbb66f54536f7e693d23532c6ebd0e735a53ce22dc74ee67594f2adb694f0e27c50e5ff27aa537083f4524c11a4c2d43a9f3efc905b6f9817f6db069e9556402402ebf77228ecba62a09b0e1671100e688147434b8800dcbc7bb6dc50d84197be85cc5853784c7b8f0c5f762ddf7c89ac24df37254241e00533f23b28804a8081cd45a63baa74475ace8c94a900bf03dadf688148a52d55804b56558dbf790411c5c8d8051cf76cdb4ec6736e7322c10b1fe46943e43879a2326a3d45a55186cb2a9c3cb3e014e21f5b1a3fafcb1bd5715e86d48eaf4e18d918487916f1ff631a80ae8e70efff402c2bebcb6541937a5ab5ffafebbb35804a97b06d54b99c907e1152b96fe882f3621f1ceea1cf626383ae0be0e87115b3dca041924df254642ba6055357280b6fbedcb29f5e3c0e02674a5e5c3fa2fefec4d1f15c6917c2e380b91085813a60bccd53be100dc071a2696025105acf87631276d7d2dd60a5b7fd97da8958948a6d86707bd8bed03119a1ab0ee5bc4ea726c773348e9a1613230052cf0a4c31115145d76019ebb9c8257ec99f8f6a4c1df74abd5c17b9e42824eca0342b4c9996cd670a4431041acacf373287829d713c81cb64455bff2dd1d1a156b5b2cadd136e506d9e855b0d7dcd123412a9ced812808db8d84a2f0413a7d58d387c9eb47bfd03f622edc43ce6ce2a5cf7146601b1e5c4595e6ea6d1709de1b3217c486fadc8d458f4d019ae2b7a27e24f94945c5b90172b3b75cf8723c18cf2a9bbc1697b3e314d3ba40a25e247459eff379f52850deab0e1490ddf2064eb086c5cf48573431519ec2892fb6f900688902489fe740c6c610ee6656f0633c4bfdf5018683b3a6e565f0c42a5abce79b1be96816ad5205c3dc43b33e233268b9fb0c00538b3620f4f4702c7038d876a8f206c3ad5a11550dc9da9a74fde596d8eb379fd935e923aea4a33bdb3dc6afe5d2ca7b391a58a561d17859917f9c14018682f3847e1b28e33d452814c7d01497cd1ebe22981c9938407a8eee2f9eefa27ae3ee57186105e33a51e5cc4c37ca7d48e53c23aa5385224650b47ddab000e611e485271684e38dd49161edadc9a54e7fb231105a3d437801b8c9c9baaf9fe64eb3900509a277807f30ac2d981096fb06d4baead40d408683e53a198b34fd0d3540c7232cf2c5cc0763e1071279ad858004cd704baa60b1e1e080a5aa1831e0959e6c8449124a7a81712e36ae0fa8f5733623039fb97a70826d9555c0e2a53c99d311608c5536d58f11371fdaf91623a6f481884d48b2847f4c4bd4b455d6813d1e39ceacc7f9be6e38fd2750b25fb0ec6aa8b894b3b718a6065987d2726b816230db81840f528fc7d640769a6b1a2803fe45e49515371356a951053a64475460f5a193838aa5f068648cee246126e12a04a44cfd39d91fe37d09b2c3adaa8cfae4eb0ff0d1539b2f31238cefe7c9218437dc38ae72be98f978a1a0ebde22ba7c69ab1497c9181dc903d811755687006130d9264e5ae05fea219e0ebb643918f886103662ddf7a4748ca8a894be7886adce8127d080fc15421e2b3582f7a34dcde574d37f082ae7f9b5000d443586b0ab3de891406381fd1383768055acfcb88089f61a5263299ecdb8fdadc8e9ec4ec0d9116c520089f764143e2fc9273541015a72ffa0b92fface613491e26433febb71e6837176d7880ca52e2baa0ccd5ec35fee3c38b358f2ab14c4d11c7579287aed87c5719f1a6d6eb1393e1f6202be6e80588751fa3ec8da257de67b5d7c9f8163baa9eeec3dcde3e93834f409df1f2c66f20a637516372aae40fcb89efde2799b4ace86fd9ac0edc9c8bc4b72b1ce594d67d1cbc0b810e284fcfb4316f3680d7bc5b6e472afb9d44cdec7f765c9533320784f5bbd30496cabf968b7f9106102f8eb50e118694fd3e41b458f0bf5c24acc0ca6258ea88682699cf13a4c5a5df8b45c01ab9113f2618fe974e5ea4f073a9fcebb4f92f727489cf8421687c6f5aea076179f1cfb2585ce6eef32d463919df9b2a84cf5e69dd0758d6410ec11efefd7769abe8384375e1f24e205b6cd55a4b2de22d16c159ab1cc1dfce955a34fe2914bca999e7f265e3a227f022cf6e24b0235ae463358881eebff855e61f1aefba80102e96fc2a0d118fe95fd6479808fbef974db050febb1c2bd00af7e929233da6df492bc8b1bff447a8bf14681c07d77c3eb16a7b9131322742dcb4679d39e5e0d80ae5b37dbd8fc501b64bbeab9f65b256668c1b91c6ef4b252d2efe5856fa555aff19db2766eb2d3d197dd50342b250fe6b5aeec3e3282ee7e1ec94b3e58bbabc6a6031078f57d80536ccaa1a041a039a2d2c73b0522267b48eb344e69cb75f4b4abf4c9de5202d62303f3293032c2ed3609c95149066b2296fdbe08d4dcf8ca9b3ad160854fc5c473e3b2e9729ef2b229898f70cdffd6f71f99785a2b300abc565a3849299b478ce1196167f2c2b9a25b05a4c162a2a4c6993ef8864b1f0cf82a259236fe41988c6fb66122d16fc2f17f92dadff141829d5793606777aba6210a5e79ce571d99b86ff74dcaf25137b24d85eb684f9cce23280d00485983c526de08b75d5d9d74618fe9f4aeca413279e3e1d6f52511c5be809eee55ddd427e308c96ea74c3708dfc8950758aeee2bd1819a827c8ad4727f057c43a728da560398ac51a31f50c28cf9bff9a3a5d41fc6ed1fb3c9d0ba8e4b3e5907ba4666be22a5ab126d9ff1dd8c3e30e829112861f4be95ec1c3e33bff736677a36957d2081b854948785830fb5f14c69341f0c38c850f23b93dabfac81f8d35d1f575838fa42c0d1823d96073c9cb316d3ccb53d787344a962093908cc10bd3939550e76b7985670b93345ab2303750d00cdb5999af7b38976cad95bbabd7b8d3b6d39899c7ef1bc8765ff33ada86c547c94bdb86e28f22811cd0f0be4be5769b140f08322ebd11b25b6aab6b0d2917dd7cd99bb383c85637e529d73417929fc47bd6a6d90ca447d6bbed2819d26c36c6549bc17c903b71c02944933289f0b86a7736f5f35f4406121d08d15366a17dff7ecd38c53cedf71c20c83f69e3413ac684ce36e9341093179dddaecce0f91288dffa79ee5ac4469bc0c4dedc399ad8f246174405d923a5fef7341b620f79ceaa6c2feaac89a230847ce635af0e04c945a1013d9db84fe9cd53c4f3cd678c40f34c5bb3081a97e554f43142e2bb8b97a634cd4f6ad41384213ccb6868eb92beba603a05dc2feb916d35fa111597d6ec0020df2037062c2099144238e0c1f0b0bd36323032759b09ea476e3b931322009c5ecc564b6f908c085386441d28d5860a53c7c20780d7ab3f421ee54088a63e89b33959c21374f951a6cc2c3ea89daf7751afc9441fd75a30af9578b9345c435cf6fdc6448b751f7af2d8ab70d54cf636128d9e236e83ab5e780415ae320cd4d5f5ca8e383c6090d8d0e90278604c92e4e6fcb56c49980a2666fb0a8ddacb9596097dd194a28ff954b1f50ecc12aee91e10fe5604a348a7d5f0390ac49bd0a3b1c63e67abafe0830ad5b63d41b408402029004034ea1f5594cc62e1c5ea0154ec04ccd601025413b9ba87e1bb4975f4ac2dbe933b0daf607fd134abdaf848de03ed62d1ea660d528b8275a28df3d42b1a3f038d712d5012ba2ce7ff14b6fbf8fe9583d6d973445453f21ec4ce3718b53207463d3d15b4ef0a559b31d9d97bf2fc3705ddeb81763cd03189475bd7604cb107b432afe17f0241ba720c1c60f687e1967d79067e692cadfee3b3e6d04092df5af9307de4ba8df0620cd3c3e06df8fe5a834b8b9ed20988e4185d7c291340b2f0b11e3280075535fb131a6a18468c30613371bbd2a1d0ac25e12d80ff757a8559013df2352fd98629902c0949d7a629999ca8a57dfa4a4b46d8c74c341a89a646a807f85c5b6181523e7b5c3504783aff870ac345a0699501ca2ea57cb9a529516a79e557cf2c5775003d592923f8473f469b80e0b1610c7383f7a0628625e974501936d38a0f91428adf549954e974f75226e281c43bc7d111cd29d3124f9de6be6ca532158d40a863b0cf53d5733bb120bd3b360a9322f36e1e746b81aacc7f73745866265dfb90de935e329872eda37a97148ddc18d196714b2516a3c5db328e52490630f1486ac92a318d9d3256d29903910d0f911dac74c819cfc851c8bc74c3322c2fbf2385a1448a86b67561e0a1c0bf2d239336a5c2788f5474a675c7f25f02ffdcc0f67c74d29fbba5df934e323351cd877e87d492c984ea1ff03b524936b3aaf9c86f919aec8e4908ee8669a0e9d2817601078f213495fb337d9c1fe7bb3b8c00c3a03c92776d87547faa1bbb6cf3948d22c18e5c3875a9c880d2be98f27a343657a0767487e099fb21e26349465c854d6b9c04611c7c7f4b19c3d78e10b5a4a37cccfafdb00981583fd14fb556194e4431c6893a50a8712ac71717017b1fe49edcb8e50b88a2a72e9dcd7acd3131d647dc838c27fb2457c452b629121e6850936909d1beced7d118615b80d927a781751f334d8039f25807ef75b64288fefefb7b3e182ebed008533e8a9941c9ef905c8031855e39ddb4e4e27372b209770c518b51e016b1e6c2a52f30f6934f73e8a82351b0f20b88abcbb72b5304a18c6f5538aed6fda185e788bb383cbd40733e7a443abdc74337e535f8a03cf8d13e8c2efe2755c1fe274eb7e505a90b40dffeef5f4b3cafff21fe6f391e2460405704f8e23e36e67e940fba4bbfca10095eb263f88a037993914c13d68cf2efc31a7e1e2472051dc53c7b19561424f8f17dc53bb74891a8338a7816f055ff34a0263f3201e1f4240b25634a0a1881e0ea3f5d0f7c3768cb6e740e3f5f6107e87bd7b0026394a468f13e3ab74df66332c175789077b0927274bd84314bca0f06ebb790281acf853a6a2218dc54a8cef0808fbc87829058cbf6b070b2fb8dde1babc86d14e7fa5e0aed07d10602e6e7c964f50a320bc257eea376c4f531ed5b45f239e0eecfc4533e6bde838edc3fbcdaa1a7dccf87bbaa9b6e26b38bbeda0a28b95ef48eb64c9ae368eb3b594cf47e65b3bbc7b9297e93f28a2985e2837606fc2c52a9eab05af313a6651d3cd54630a6a4d816babf9bfc1d662fe4687055d4f5c9820e1dd45d504249d363b6021e6b09de9d7cf015f71a99f34d503cd6e28340a03d4358ee233cf870a5afc9673c5e214157c85287d9d4012621c51add3e6d8494305521049a81b9ab66ef9db20c6196256f113f0b3c3c6d03e3ace173f737e42b7513dd00f60303c129ec014c02f8f271121bdd353e7507ab11e3f4359d7ce9ad09e82f9b7f30daaff1804bc2387cc39a37cbb160b4de4ca74c1cc79a7710d307f217aecff2a35e96643449f7c7724924b640c03a7683861f07ed2a64054b9f76b01ad3c197d294bc705ea67f801cc6a5ca9ec61287b1ca62411178769eabd6251f71d0c5458377377bd5ebc5f99644d1a6c2260690f6b4473b044a1fde8792b313c0e88d40d07ef19afc2d8034372205a708fe98d67d290d953ca992a13f21729aec007678cb81b980457ec91d60b42a00825de54a0ee0114931734e9e192bdc1c8ec16b5807aba21fb2933e103671296a0191cdc5010dbe8eedf6fe3fb0d26fbbb88731fe17e3034f025d8d6e578d645a20d267478c88314e02633a1884f7b31f76db2f8dd6e2b80656223cdc40d76eb7e08ef22eef13176011f210569d2b5664180d78ec47da36abbd35c46066c8ac18781feeef1d4d095b586e75ded396eeb2a04f91a5deba1ed00d8054f9645216446d3c65d3c0a8132d7ba365b4954428ab3cf50fe7d224474eb719fb5973f19b7e5af81712734a4500edb27fab693b1dacb9e6e2b347c5023128f598e119c54f904af683f4f71b92ed75ac72a694d0d887d50b79ecbfa56a9dfc08e00598b269a61396091e9d84b7c323b9cc4f3d9d1327392f41aa90d9925b4d7d926b4aa698cca009f81d8091edcb32c205164e00fea45f08b0b11cd01135d29180395240bbd5c166fe6e728ea7e62030de8e3c5a36df766411e0da6e0001a2cdc5499f7b33db9f20907632755256d5bed0b723c9e1c6a10b3f173b3a4bf353e1c619ca668f3bef6ac7af2add7e28b3860478dcdf36a2f9c9a4567404d7215e010c21b3f2924ffc5e64bd257c9a50020dcd2d7fc1c64095bc2761abfb3ee9a8382d9a823acb9a4e0e20c38fc8a0ca503103bca21c3ae7a87a5a5bbb8a3b103830e8837500263ceca1b4c718f1cdec152c4e9ba71a313d33ec63c8d8ae1378a622f5fa4acc841dc1674dd805662f8f1da4100f7305818febbbe2dd012ee0dd69d4dfc17b2a190946e21565b93500577572904f262608b29b6e8d8f3cbdc182b48314c391d91c5ee6d36c463e161c60644e1087204853e985ac6030bac461c5992f7491f71ba22b9fde183e03af810d454140d28de6e4eec288fc93e16b8c792bd4c25d71409e70bab45e12c86a4b76b8f84dc574a9e605e146066e2501532985574f067475440b15f51b8060cea038e0fff133ca1f9860dc971d405c467aac64909176e1f131098cbee436e2f4bbe5db61772cfca58da77c982f5db212d11c0d658480e7171621528702de34f45350896b7dac40bb93ec117f7dff3a4330ba8992505d0871c1599254da6103ad6eab7621bec079ccf08897738a00552a1f3956a4c9a11094ee4ce9275edee57de26c430050c9e74d2277650212fc3945727213470ba6897a758fb0535c05dc10ff44022d93e916259f5cc3d288ba377d81487bd799c9038052bebf8ffb0e1d868d6096c365ea03efb385101a4fa58f01f5df0d731dc7828a0626e1bd3776f487e7c68eac0b009ac2c253417dafb51ba839c6b4fcd36a3da7c5de8a391edbbe610e8ed8a6cc3ca8df7e6ed4bc4523ecdfa864f847375f28075d87de475fbc022ffde2f86bdc9102de5e62da075dcafe421aa500fa17af4a829f74866f8d3604a1d1bf9a6d87775577436bcda06111313900e64807bee8bcb432e97496826e9f925bc8941f874b5dabad7202b6ef4211c72246cd69ed310d58184ac3b1da8b46775642578e90ec356b599b4b5364db21ab2aaefbe87839b65289f52a5cacb37a9389097efd74b103409558706bd511d479e32563b50fc7f15277e74cc0acbfd8e6b30a29721668ead318ccf3031ac0fd86077a487b45abb2b733bfa2acf9413097909d83ab536a053402886c4aff9f9b6592b8cb5a35886e85f5e13fafb4a87062e099c405f276944aabaa264891461b50765e8c78451071bbb673b53b1e0aded059e07e0f1f82a19afa2f1e321d2c0176a79be9ac23534f669600b461a9c37c44cca2a95f7575d80b27698b23ee7b1d28b9453c01149ee716e1f50e0cc951029b7b1f3563f747628a92fc63a1d503987627acc1b67f6cae85bb5fbda57b5f4e0382140903e07b9601c333f02ff649a30d6ed7877f2502fff50d9934f1d70674b44ce1daab342e622f9a907235c18d74c51e8495e7392e8082d6135dd9a50f7b971996a4ad7d223321c819af8a36ec6015bd817ba152acf476ca181fd880c726d0ec8f289fe7d09f2732d045bd4b820e5a1d7ec41048f960335298e6e1460a7b1563393e3366e8fe9ba9ee84284bcc3853f417b7348be081ee5cfdf246146d16815897356068e1da44b7b7e61137f115cf0780177e044c8323af325772b9c388e02db701c180d13fa95aef910776130242301472a42d8d41a6e79e231ac7d9ab6406383be0337ee53e8a920c66361801edf272334116aecb73e13d8db86039139841ef27ca60a1ce0c0f4447f0ed0ba03b680cd029e805f3180c7b29894fc6f3cf777f2a74497ebf61d8f38c560013c9bbbcfe8300316476007a62984e28ac2765b4a013f60689f7c2c7a8f56c024d69f8f61904dfc474bf29b5d83b15c4db09ee3ae5927d77e5f83c834bb08e65969d12a7416c87382e4f78b9c2e833d31ceff3bd7fff360643ad41533a7235fe4ece64f606b71ae4ff5aaea2c98de2e2356112c1ea4bf0e00ef28c8b2e61527bd73e90f7fbfb43e892c95a6020b5d5c4cc7cc31030ddd1c520e44b976ef97f6c38230c3025d6069100a3f3ab24feef332d147f114489ff0cdef79f8f67c784ae895004fb07b84604c809f0e0290a76887515c168be1a6d338930121a7ab850f05bcf841a4247c44562f732a847f7601c19119821308194dae28990578445419e68e4e9e029934a1f1e1985996c6ff141055922602803732681a9ca74dbc63aabc6da5a7e60a143811038148466efa5b277eeaa3f59db2c0bf51e489fbe8e3c762a229b325f2285bc783913417206d205a9cc62be0c2b06d01617ed0cb7bc24e16c0cb1704b87e2725a8423aa5088d64a2fc788aa242a81c5ff6550cfa071e45fb81338869fa3dacfb4292c487c0034607be2968cc70944d0dab796dadc836d21cf252de8c9a12cf4597ab69c5ee8f605af314c12182aae5a3471f1b0ae56af744503b591c343a555f9db9b1d6409f16d3bfa60d46b04d32a34ef3978cb7863e08fffeb0f0a64e108f66a8d8735c5e7068f6eee410e2dbe808de67b050d5d28f86008016ca608dac0020307e610c4660d600d26107861850146b6f1f41ce476d10e8191bf69ae62298716df4a806f44ec34ae377c7484203a7db3a88674df21946510833b932a94351b41194335d433144279b311983192a11d2364a5727e614b37080de935db7da85a7a5692ef09353afcfb18a9f289e18e7911c81baec0dcb09d4d2fd85c6d9b0a0e810dd4093eee447e703f5b6577be6e7f28253c8eed3973800fd813a60438fe56339af8139c259fffed399e7c421487f23d370c2ed6339efd03ca5dce50110e2b055ecedd705e8ddce237e796674bd08f51301748c143693692db52481db50d1a938a546411e8b4e9b410fef7d92f5d81c6651c1d65ef8f9111ee387963bf6f78a74f175eca81e8f0b1669a37e32bb44f59c0148bc5fc8e67b8274db33ba21142dbbc7d9cb1e4471ac8f1d6b89a659466f1296698d08230ebf9bb5c7e7933bc22e1e5305876e9be06d2c96b241804990cf4a1dfab1d3d3d93519583b1f485b229ac8ff986d9ebe259d066fa673f7884bdf68e117a43d87be659e03eaec1f40a650bbce05e305af28bb140e5df72c4d46ad1b5c70b1ed97a919013a99509599528d5c85a0a5a121b918d21f14ecae23578a89878f5ce48f2daccbf6eb803a4531dc5d0ecc466e129e4486c3544309370c296a68cf918ae92e1dcba0b7baf2858590cf4073b460cc63b5040576124b7208411113a87d0958200838bdc9ca66d1baed92b99c84ca8ac30c461d64b1041107a65494098f53c77cfb9af8d7d16733159adf68568764ed38fd239187a6877caf773dfa31d53326cc8b81f77a564b5f5cb801b16910fcdeeb908be1a9e206ed29bacad15d0e5642d3a1eade810ec661fb57b42816262890c10e211e3044172097683db61c273adb6ec46921dafa4d3d6252dd07bf808018624935d5869d57ae30ab66b9325792192aa2f6b10841e8caaf3ce0e2b7f87b334ae12e9e18f85b5e1eb88c16e59c1e2021bfcd788c7e5cc061e2789f9c659660336e57c93a395dd8cb696d778019fb04cbf50bd253e90f985c6ede2c77ea0db609f72a8436a0a880166200d2124ee58e5d2527c9b82570165143834ee865c519b913153ca3a304a67e3bab44b148f02520621f48850d911af1885c823e80c6de688ef26a1e6e9ba1dd130e502f28cb3d8f1f810ed65c3d88ed07b23315c4fd8fd4b1041564b0e72d2b0b57c9bfd73e73a3b68d57fdc166b0fd0ced85713a538a8ed861e68ea8768d17c50d9f426be3ac001026e06fa318818c803b613b0ebbe7168fc036c12d6a8bfe076868abc8ddc26b4722579c8522a3782b3cfdc7a23e1464eb425fa2d6ded34ee2dc8d1d06c07957656bbf7877511beba3d2baf482ea2aa9703b0ccc5461717f0d41d12c03e445ea415d2b0de21d827c7df49934ee8b49eba707ead10265501e2a57306abe7c20951fcd096a67112fded2a5bf20b968413ee3d357fc15ba0ce517ec50c37898b0a5af1e79c8283e94411a4358e634411a1ea8c7a2961e2d1f6258e1b403f62571dfe19da9edb8599fe04741e1879ac5b6de497ddd14d4d516491850e7dfda21b102c0ed3f3b7076b47ae5b370eaab339f43ecb41d0e294f3fd1b24ffc47a63a84b0403c9e218995aa35ab22880a397113beb2088c86ebbccc17cca86f8dd0997c6c2f91f680d48089d8ed3d9d4ce240be15540b802ea8040b481fba09452cf80d1d91e562d397e2cb3432ef57fe1beb4815f82b00bc6638b7d614ec78039368c1b63c9ba51b3c309e93565b9efc38b9ef3ba90157a6b29a4d43a2533b440e8fb4e518c28768c5b24ba57195b6f35580fb9f5d4810a9d15e7b9138062cb59bdf2d64a2e462c88cf877151b16682f4257d7e34617e55ae92327f1466330b26adce6165019195a64455c2589aac9039126c95a813438e5234c9890f43edf37a0233cd6edc2843b98e15863204453e03a6f5617643ae9b600fabf8199edc060ccebf8995046b38d31952a0e42827691d9d34c819045afea27bd17b374bf4b2ae42e96fb8082de730028219dc35e30994676ddc74af68a74b502cb6c2c9752446d3307f0f7cc2f67b0a58de038f445c9d13feec8d8fdd5ec0bfa2d8d8cb72209aa42a43ccf77820cc4b1b5b4cb1c407f11872f2c41533bda98f8acd5efe4cee63b3112629e6008bd004e0cc1b880c55057469a68b46a62d3b19e39ce412fe72af17a1fc52e625ae2ae8d302f45d3cfd0929b523d4bff75c24420903eeb8ec89d2b023ad60380887399ae3814e1e244b15a4eae6ec05c588286d8fd6d533ef3d528629a4eb7dd599b714f0c091d70c019507abc1da7772c3a0db8c02a34f668e49aa521b10ceca7aab674a332e9cb3c8fabc8e949f490b5f762e7e11a4e5b4a9eb0a65f1416566fd55b352d2998d5e903d7c9501bd60d47ff8de12b3a1ad956e6a162224624da5a994d694312c06a0763933f21c1d7677f0c4598c3811ea74a0c3429169eba5a1e16a1075cfb8ee822beebbeb515eeb0d5aabe0589c6da895e8a79d064724eb80a97c28af9a069316e14cc2e90dae878e3d77cd52c5285e5cf14f3ca2fa810ca21c5a4874de4537dc415175a2da9d45ada13d8d6502ae375887430d745654095214aaca9f28bb873a586b8d8998f8573bb56f90575114c41f56a086b3df2f007c6212f909b13426364f7cc73db2e045b3f110bac5dad69dde1056f2e578ec362e1fe8e430c982a93e5be43c2953f6869a483c7307ed8bcb2d86568d58acf963a0f279bf9d8445c050fc6f6b0f40e0ec8a5114d158d2594cc1835358788433831b7e76f3bebb7f1c42cf97ef8428570946160792c2784873a47cfc42aea1cc63758af78cee1132c5ec4f7a59c90c0f207bb22318763489570bc81047fd490fbc18a179845ef291bf28d87f0e58ce39fb2eefc8993ecdfc6f2c34258b520bae71bbd72973b415fab27f6a8237e6a69abfddb8b56ddc7d1a3fc076c8cd51b1db95dfd4d7d81dfb909009770be290d89a678e262e1728bf0d4d99a32496154118cb2c00094eea96f353cfc97159b5b0c6bcbaff00d33ee1246c9c6eb5529dd8b9e7939628d4b600f3444c2ee2da1b81e72bc4f577b9ac06b5d5045473b6ea157953d30ebdea71f84e0183586acfb57bf90030e3b94372b8a29e7a406d9890a2cf1675090898ba878a8da63455952978445f9da569f1ddf9d74840f816bff79218f1812708178b37bb9fe5537cd9572ae8606b9d8e66c0389c63ca317750a93f2c09f507420ffeb0951cfe06b331124e1d3f9f8f805e28e153d8f839affbeb900f26ee31e1f51880b008f5894f769227cde9bfa22b7a3935dcc668b015e918a710ca56e23b8b87f1a414369a40d7a8a28392543c170f62c734912017e540df4149dedd15ef87ec0ea7c24816168e301d7df7346d513af5d5a57e754f3d3c517732390b0b3783182a8170a3839a1ef83590d9a1770ed03f2f5f6de80c9293f54d746a979e3d482c718626a232e5af96d9894300f689801a0464072d37765fde3e43ee8043161ab2538985049f78e54169c80b7b12ecf81447b3fd852570bc043f40867632ac4598ae7dd5b4a4ee5cf2b6ca01017618142ab4e54e1f9a0a8f1d0b40f822fbd1e4cda4b673ddd488eb6a65467ff2712d58236839060b846f4b813e7588584ef46c2a57082b0bb41c18a03c55be8a49ec14c8842762a9875fb97e08bd358dc59c6298ed1baec17d62707459e6f185139dc50304a03e1a32fbcc73d2c5e8cded3af0f185d48edb1236c23b5f46a99a3b690b8afe08b12cae8d9129ba7c4f122372a3fad161a4cbea014ec7acba6ceb2a17821dd5dcb9816135ce5a367ca6ae25a9af5ab3d4d02abb0d0c1d426d5dd7f76f4f88a241eccf0064f68104c91de6e6d655e01c5e70801fde0af382992c9e93984647994e4d106352becc0a271f0af3447182587f72d3654570830fbce0eef0b006f83c1a6411f885e4b796a0fd081e9f9458867073b7df2dd955815c6bcd85469826b4346840a7513156596987bc16a067e133e27ff2c2260ffe6c12a4c08915f0abd8dc0cc6c245cb336506d3c73c69fc09df0420c18b4b45d552433c413cb3d4f0ad34f466a9b5b72c850ca3b05188be7245e17657ca5e330fdb3f8be85e38961814e7935102c466b41629bb0efa1ba371c6924d9ccb835d352e3b204ef74e8fb37295640c0f0c857558ea0fb3a5def73a2cd447de7bf989f9e4fec061e10308c69a05250c7c28185e768ecaf6898325e28626aef09f814de5cb974a188ec2303bcee87a8cd8d164f912820d92668f1c48889d741e84a8d6b0955475a1c904aa1b40d84875a9255eef74e103d7f438ae6da3775d62a8155ed200d4b24b181b279f08a29c911c53e43466d1d4aec37e142bb549c7ed0e0b6798bdcab1d29a4cc22af48cdb938b4651b1f68775e48cb51e1cb38f549d22c2dc5211e8532e0e630289c6f1783b3029b7f0b343d4d3ed6dd659cec02a9a7b179edb78e3a16443009b5ba851173707205050c6b3a55b7125a231535310df3da186e35336039c222ba7e0a6f01e30a37f9c50eb987ff6f3c670dc882311f47c7ed093689e4f6fc2ac64b5189706ec06d5390fcd213507cb2855d1ff19fd1ff32a59832261f9abe868de61e4d6a0f01e8290a6e5f43e16f0d664fd8cb2e999a0a4285602fe245cb6a2d57485307c0dfae22ba77875cb11aa1fbb8725b28e5a6150200a91560c2fe537e0e3afcc1178d1911f811741ce17a54409ccaf3366d48e492c9c62f1658b74069c31659b9eecbca9773a23e980091937f19417a70475a8c9773287bd0a27c7e4b7428b64bf7a52e219e4927bf6ea9811e3b7f56db5e8e2c2b8f6c8e43763bf4a77aab605c939327632250331e81eaeed5b1b3b12260e82f02dc5a066ca20c9e2e1c91436dcfc724557a5ded87ecd58ec192c647bcd657c1ec3f408e90c1fb46199ca90944ca603baf5f2925a40d815a703e6fa6af3d476d48acd493696812b04074a7133f589c833481cc09c8853bce21398a374769823f701da456305866128322ed4becc43538352ef0e1a70921e8918d1a1292f535596fc447665db7befbde59652a69464830880092a0994daaf7bf9dc4348af508ce7d40f3fc9a021bb62ad8a9d41e3ebab3cf634bcfa33ea8beacba81666b1a72fbbae721e8e2bd4ee3f900a273fdececa54dbc9fa335a21fd655648dfea44b332f5bbcec264a49c1a65d0c334f385179671af71b4aea8f6ec59cfa9af65be964acd1a380de4412f52ad368999dffddd889c50ab4099993f2dc8b2a66531f7fcdc755d1777434b7123bd6a29edc2a0bf3c50afba0be69662f56ad55db4143772b95796d55dcc97bf65dc5d58bde214b4e19e6d97b48935eea9fe82afb4532efd5eb513db529a445b8ac4aca4d77ff0abd07e5cf7fef2b54f7b197a68bfbaf218f62b74e5e187203c85a0fd4417c33ee4ad782a1e7ceb411ee83b0fc212663ff920eb31ce0a91b7675b990d3266bf7ec2b2bb98df5db00e6865b2a76f599afd68b2d952aea4b6bbe01b525e212b731afaee3faaf25fbd34e4ad782a5ee759f3fa41996dd88652b6d1bc3bfffac922dadedede24a6973eb52da5bbd0e17a6506322726e1385d84d9c6329126c9f9f16b1b25fb53fa306a7f7df4b4eb312cbee65dda430fc7152ab541b44b5f83d6c74bad4c6661bcac4c3f8500c5ec47d356c6aa9a8cd647cd7aedca58da1225121982c8104486b868e47c6bda1b3e1af9d092d27a1877efe20c5a6c13257bd03a6d314afb2d34a2d8c943f08df871cac83991c10cb6cb333bc06f88e6a3914ee45bf6868f864e27ed421fc67ddb117acb0bf9602664705e78e50e59e4d2e8dd8c31e50e697d3449feb4d4931f06913b800bab00c349183b61247133d7e49428c57f1a0a5f6ae7fb68979565274d9adb7fecc47afa6df3eb573fc5787f57a1d47eda3775d17f18cbd317791096a85d79150f366925f4b04f322c6c1695b760c85b51f995d76c10ed6aa05fc171858a59217e351b342b03b2f3baa4dc5e5ea96265b69f6f7d6f109856673f9aedbab54e2e6526f00dfa304d6b96411be8cf97defc1a520609dd6d07fdac3edc76c8a7bed5505ffbe9b17831543e6b8dc58bf170eb1ea6e59603cbc778b9eda8a5fa98479b547ff3bed0ad5feb6f9e566193543a0ffb181ecb8354bceb3366d8dcfc6c6a4ddabef36893b68fe155ef0bdded411e6f35eca89066a12ed5f826b548cf5ad26302df902f7fda48a3d2752734b59b6c753350a5945d898ccdbf6d366cdc30e3225bb54b3bdc3ecb387797d120c89de39ccbb8601d0e9adce4b2d56d7766cb6e65a4462d9a99b6786650a6ff0f972737e716ac633ecd9c705bf42d6e66ab6b7d7f5b9eddfc41b48c351b4b42805a2b7ce325a9f54febb9edcfb6f88474b6853c44bba8c3b35fc68c417fdb6c98a1294347c660b17286b61d54bbb919c7719cc7acf9fc4de53b27dbe2f65bd6833cfa303eb357f13eed761ebcb473b8392df6754ececa60cfcf56c6c5a67d37b771da6f9f31c76973623feb633fbd2fde6a47d7d3b76c5a7324d291700fa2dc6fff45f9c5fd82c02fee7c4b3ee7702f8368191719177cc37afa907ec605a5d92ae342c60b3a9e8248e4aceeeef99627b365dd96353339ad9f1f6522775a19ced8e6632232dab61f8336086057f2739b0ded22b9e5c321886cdb0ede3cd824097ad86534333fb0cd668530cecd3c194dd6cf24641bd6213fbbc9beb76a65b2d7567808d6b15529432bf6ebdb9dfde88d5bf61abfd69fb51d696ffdab48c936bd6d4498c8b6d9d03d5b19feedb5cefbf85a2b2cfb57b2cd0689c9b862257f776d3b2c9ee26699a679f06659d69b03b2bbd1cd06f9a09f1e7f7bf3ab673d8c4b6c08d631b72d88b6651be8e3b3d8f7527cee9b3399ebe567d733c7d9d16f51fea49bfdd8326d1f7fd37808f9d910ac03eeb0885ccc93974a78afebba2e6a591e826fccae5598b0245e2f2241d8c3cf34ed61bb68efd225f70971ca13dec93e7738e5c9ed3433d4a9573867affce68577da5ee7a8eb8f362f72fd3fbed57db47d756bf9cf393de77ed60b6999fe1fae6bd6537e6afdb3a65683d2f8affe7cfb79916bfde6d2e5d4988695f9aaa5747e6f561b55ffedd9fb5eb042fa6e4fdd8eea7baffc8675f84fdbeedfbff59f17b974be5b19ff9e74bea5749b5406c002c04e7feb5fb0fe345b72dd937373cfbddd6ffca7677d0d4ffb91c765bd6ad20cfb5191fd2a0b0c88ed8a9592d952ec4120a656c67e46d06ff7acfef6d657ab55ed37fbf1ad0dc29e822cf9524a49df7a8de96fffb593ab3de74d27d7fa49ed26a9a4d27e42e447af1bb1bdf6bd6a1778b577235807bcdac76d8756e4669e9c188661d845ad1bc137ac1a2c6ac20bcf843fe24cad660f3fdbb8dfac57ab4864f1b6d940e3b987ed62c16b7d8c3738dab6a3399bd1f82cbb9a9fb3387ece7a18b784f4e5c9d4f81f2e7b9f5f6bd47f597f3537b2300db71baefe84f427a4ef0b375cf6eb5be35fb05f5f50c4b9cd6c9ffbb8bb394a33f383f5f970fb2dfb4523f7a3cf7932d7ff709b41f1d2e7f8b924ee474137f053cb7e11e752cbfacff2e9d327c8ca345bd1a7cf79712bff89ee7b6993408d7ecb7efc0991a31acf3dcc0c918c7ee6defa588475f45b57e3b842151271aca7dcd3f03ebe341eb4d9f0c25fcf6d37681f5f2e4648a5ad7fcee2def3a0ff66d98fb519000b006b3ffa2fd88cc9cd40f2d698a06e90d720af6f3f3f8d19a25f91f12cffc522fdeed98f9e3762ad6dbc69126df93943248097613f514b15b1d84fe4167a296457ac8aed66bd32ae5e56267bfe84c8acb57804ebf8b8ff7af5f61312331a38a46cfda06f295588bc9b95e1fe7a0bc40fb21f5fced2ac354aadec6bb523ec414f4f3fbc345f2452594f9f468c97fb0b24e5e5ac07bd047acf03d94f48ecd5a52fc35d3fb81789b8e728db8f0334d7fadf3edeb40bbcdbc7235807bc1bced53c9965d9671976d97804dfa0d69a568653a3a6e1a40b4aee5f5805179e18b9a60babf842cae582cf2dc085556ca149156010a9020c2daa0023892aba00a58a2e2ca9a20b5f384b2e9c2f238cf8e0f6cf8ae45cb8bbbb732b21b6bbbbbbbb7323c1dddd9d1b09eeeeeecebd12b9bbbbf33b3717eeeeeefccead047777f70eb74d5507e640c0ed7ff98e40d478647e08189564243f66326a14df076b14ed485a1cf8e7c7c0b7de07fef93e24711b6359ea03d72daa49003aa8a60bbd902289284794c081157e509688fa996af8e1c3e7ef6e7a0a9a9324c75a725989ce4204b4f02270fc14014b4a9f485de287b243916841734cd6172f35d7fdad1e1ebac46ffddc1ad6136b752d9f3b25c536d1c7c7877d72487e6226ec139b7394f8d8c747ce1d7ec0b044cfceaa468b0c3fba675a34c06841b2280e531853b4cb57554b2c1d6be7d68025fe161970d42ecd004bfca625b4c9e54a71784062888d0aac6003a75c36d0466ce9a25a3aedf2718e9276611f7a615260d6641d68c37f08eb68cb5058967378065bb89e6393714e12f5631ff6f1f1c1ae8caa60d821414a082708418f1f4158f111b861a841bfc0e450f90c6a4f0f1f1e5bbe88120624e4bca91f5c7d2f2fd38aa1a6c2743de04a1514c6a07e704557abd58f1fabd5eac76ab5826108b547fe7c7f1f555eaa4e492aa5c5cd0544164c70050c47c000440c4bb4206921c28a01053b53a89658ef6fa59e647ab126c3a003beba1623a6504959b292d22ef1fd34db45f42493979cc6a08445e4ba4504e65041c8d0468c2d36a81f5c7d73ca14734abb444d5a31c54ebbc49fabd56afe989ef526ba22ad4c3f2aad8d82a18bfac1d55cd22e1f5431993b7e227989ffc95cf9dc1e93ea465405130c02b8c7c40dc312da5b82e0d48499620c49fc9bc42458a2a20288a4a806f583aa89d32e9f2989ee69a4e7133d95dc9629deffc55f7a242fa9309f2f78769adc1917f2ecacb08072736b5c8885145e7033d0ec3bea4183825fa35b487414ffb19fa1af7d0e10259a4f837a9397feced7fefa1c20eab2339ae9aba0ff4c120551da4fcc1bc5efe1a5d9430e10c5c3cec078697e46837aec6950d48e62b29495240372d476a4037dec63aedf6692b48da18fd9194651d9c3b2a31ed68f62b2b73e7beb19e5db8ef8bde10051d967d1cb1842764ea7b62a95baed849e18a46ee611c00af5631b22e603f193f6f379f013a3e6fff013e8e70ff113dfe0b04d93e6f554fbd8a6474d4df6dbd760cffd283ee869509aa77d4ca681ec0c67d9c64bf3b19fd932cccb3cd528bef6342826a3684738648f7d4cb431d86b7666ce4cc6f1d2645ba18df8978d6f59e93adc74061977a97ef63a40ef06ac30c048894a502fbca249915b73608e035cf9dfc34fd7941b16aaf6db5b991db91db9ff8c3f6767febdbe59e68de0733e23f8dcea423bc201fbec63b0cf6692401b933d676566f292e4b701de1e447f3db6799a07330f7aa318edb3d76c66316f149361965512be97e0530f7a7d2d6bf212ec52dd120699f559aa3fa8a2ef278c519857bd64fde559d6d7245478473d6afaf9bbcb77247f467bece9f53428df76f4a8a9c15eb335d767967ac9facbc33ceb2f3b929f3d0d6a6624ed5f2fffb2d76776c69ab11eb3d04b34281ad4d543d4a81927a8d586f492fc16cba3b8a00a42a4b080a20b224cf8a94b2f8625541ec58754342972bd63bc7478f00831e5f2e5af40bbf8659e9a944bca944aa58e407d104a4dbcc1c97a92409e21a4b835b08ebefcd1bd1c9e5879393ce1a449df9bdae563c883cb9e73f969601dfd382eb7e07e33d090529f592ebc22ca17f7833e5d4c0d92e07afb7ebb8cfa214f1057dc1eb515dd1a37f51341b1d959020abab04517a6a082a30981f41386810aee1cb4e900773e8cde0beb687b0178c3a7ede1a51cd7553d5aba50fd6189ffeaae8b1c429740bce4f34d9044219c167aa9513120513ff864aab4d9d37de940c4130223171ae1421e10f8e06620d812b56a85a6a7d12aea47efc582da5ba89f88a5889817e0a4e709502c9102155001359d0577f2000547b459798a80c253032baee8421e10c8200516c57902940f7cd1832941f80a7c408322361f4051247421cf9111cc0f98ba41265812c6dc410e082c8b074418913b6801938b9704713f19aefc2680800644ac5050021b78122e58e2ca2b5f241fc2344c07e0429e267470e3853c2e6041c442651d7c19708510520ce049e207d55edc02358ae9f7f7b6d54bd01d5edc8d225491faa19981e80ac391275081fa810508549208af8842e3600aa8e9cd349126523440fd008311a8247de37cebe77c4bcab7e6cbc93a5980c20e4a7a90083940496f4401f9d64b3be3508c80fa41a2e45b76c689d802158246c9e79f764401ebe75b7686b500052f8240fd40c140c99f7686a17044118e40fd000019a0a4a54165519bde2866529f9171051336a81f3a2da0e6d3a0a4378a910f0014a0a4ad5eeaa7415d4e2a6dd20c0e1c2b5452503fc415f84009d47ce9cd4055103740fd30830c50d3b67402784a8610dad8220445c841498f85f841b5b477ac4106797e2ecf12bf1c024725a9a91a2052281e937bd2cfa81dd9002fb538b25029cdb5e8b4c1a2b9d132139c46326b6155eadcfb4f96651977c34f4e663f9a9b3d895060fc6917af9f79358a7bfcb13c3e8950e2931825fec89cebf18965c5287eeae80aed9f4be94b1e5e9a1fa358f189e4e12720263f857e6a136427953551a6fc8b9ec297ad942b3f3e6917286ce34ffce1ece7a27e6279b61ffc4a41937f86877de8077b168b81ec27ba73cb3219d9f6343c084b99c8db3ec66641f6ab37b3fc218f7a29fb191ef4cc7e41443588e842ee41366bfbd653ff78a195e1ace80b22bada67f46314fa310aebd8ac8cf6525a9a9571a73646e11bcc57e7cd98f1fc8d9af17e8ac1a2eb697833bcf792976478d04b313ce8a5d82ef4278b257989feb434e435eac64f2bf6d9c64fddcf07325f54ddf28643a33aea31f37fa4eb1f5fae7b4ef6de759ec94b4d7af272e7b3177f6214c668b85ee102a55f102d0ace7e33977be9ed44d12b3b51701cb783935da712afe9aae0b82af60ba27551ecf093ae834a60143b2bdf792bdcc3287638a80446b1c34f20c74531a19226773e54321f2a990f952899e2ce874a58079cf53fdeb9df56776488850b71fca97c4729e8a9f69cf77262b1ddf6335dcd7e4134f6561e7a38ae502f1b44bbd78afd4cd7faec3b0fc715aaca7f1b779795e1aecc7ea6fb55dbd92f7214ac43bb2c47016a2e0ade8942621953a6944ac9492a25e76d006a94f3f83abca2e01bf2ab7784e541de914cf3b2bf382f8657bd147a7f6843f6dac7f042cf7d1653593cfad99c730aa196f5d4db00b4e148e88fb03c6dd2fc90c7692c5ee82def0a794c699334ad86ec35edd9ab306a355cbef2ef44b11345d72a3ce83a8ed175b4ebaaca579597af626f58a2f2d5ab95d2fa942e89f12a5e0cfbd1dcaed6e76d47ed2aa595769d1b7182590939b9f2dd08dabd9f64d890fdeaaf88ec57af0cfb7d0e9548a211cfe924a4f422d9e745522a34b693d2a96e7ea4112430c70f3f855e3e101efc04eafee577c6e28d78c51b717f4cdb99246c6342cfd1a04425a86cb392ff03e6a0573e103f712b904a4e710ce56f9707b4215f003da8920446bda6c57dfd9a7e508c5ff99818bf6247d8af3c0d2a46c6b358ff958ff15fb13349b09fa9ef8fd998d0affc8a9d017de86950429a24e58c7c19de0f2fc98fe1491602da909d8a4616b56382d96e095cf167216f847d08b3231cb8f7a7407fc85a5406bbc37ea47da7c2bc505f0dfb217e12fd685244912b3f8890764925418471a408501fd7b80e13f7e31b2da7891139b81f2771e56b19d6a9da053631a2c895df2d6917778d07cc91bd7c07c0d305ae2c6a21cf87900f2cbff270db31c2c19f7b1d422c5e929890ed5ff17c709bd91fd0867c22542f5d96963490477af1eaa13a0fa2aa0751dbc3340ab579955695146dd00a8a9f1bad385f9a14e9fc4f662f233ff999cda426e56b518b5ad464165fb35ff6da6799261fbba4a67d26b14bdae8c9305f82d4db1fbf879ffc51507768971ff181b4cbf741e44b29a5a4604419653ca2feccbeb9f24b3da8d64f39ab3f7c13cc111ffe01e00cdac3ca8198401b92d62a12f5443f45cbaa264914f7f889d25a45224ef5f45c0a737cdcadae6420c0124471bff635d96fef1ea3781be1d03de8755079eedd8328274d92bc6228f255e47712e505b421396f149f7b1a54a79a34c2a11ff431fda019edfbe3f6d9d3c8a2b68ded9a26499215eac73a57ca672670067ff9ac5a92d91eacf34f226db54ade09899ad4036d481a5ad48f53cf5cd32e9289f04d9330cc46a83529663d442229457e82289fd5939f2ba75ce922f768fca05ab63649fedca2faf7cd6c8c093494a8d08a423e9ad0c0489326aae8eeeeeeeed8dedd111b42dd2ee4318273bfd7e213f5a3371221832d9fa92b8944a29714ff23f995af44652354e726b44b435294e2078a274eac94f0a1355a3461e40a2480a81c9fc01c2b1732f1137d4aef0fccd12fad972f8310ab309db0e2caf722e0c9eaf1121398835fbedf84a19a22c50f144f9cb8d25a2961f53812202f8270e591fb7140b8f2bfe904d7036dc89f1e6412061553a4f881e289132b57c2a70695db163425062758dc568f9f38246049be123e4eaca07822c58f5331e54a8e491857dadc2fbbb1e9eeb41c0eb4213f00d9cd95cf5e076db0ca757658a10dfe3470b3fac3bd03d4e34d85a861c4e3dbdd40bcc0c924c928afeeeeeea69436ed8eeddd1d4d32947850fbdddd71f03411024aa314a265ecf93d5fa6bbbbbbbb637b774f1957fcdddc42a89f36d3f3c127463cb6d7788430c6c8d3e31b396b287081081318155a32e92f1b7e2f17da8f5e7e1869e0e127ecaa9d00f9596b34b40bbcf179bba15eb7523e7653fb25e06184d14192fb4b991b5fde1053a90edef087fe32c88d2f67bf6f0ee8d4dd80f7a0f265e0c6971de80a35e0f5c6f80db9dd859a34f21eb9ada1afc77f3f7137f2891a9defe54a2aa85072a50c57ea5041450fe47b6c9e2df8c116bef881155eb0048f912646e04b9e28b24488235c26aec4855f03e6809787656526a8fc96c5a35d2cdbb45ad2e3e1d100d3a4fe71f9dbb708d0c0b48ba36450d1e0f2e1b83cf899d8c2fd44b73f24aa0c620a8783bfb181e9cb8bddfc317e16e163188659f8d01fb3d404f52f8440006efc884514b43c5e9a444393fcdf7fc88cf511d3243b848e28a842da85877a87ccc48f3c466870e3092a17196c9194fe29c2484393a2298b3a5ffe679a2ffb047374a02600eab03e3e0e9843fbf82fed927dfc19da65fbf83034f0f013e8e3e661cff1a25edf962154fa9fa81ff3b6cf3cbe2d43a820be229863bb91468ba3499ffd670a03e4d5803e8ba6207e10314a41f511d3a462361e7165b8df9e7ad8859b0338db83b65d376bad650875de4f742377798b8fe3c59b0186068f8797620f42ea3d411bf113006fc41f9da04e5bafa834eb094416655b625b625b625b228b9245096d4c6c4cc0964f259543a3b4875085c6852f2a41ed72600e035c7f56029e2a8cf62349f150b0257151f9ad8ef97e4e04b547115e99bcc4d785662f62e23e8c32f9a94767ecc4f5ffb6132b216f7bfc9ad728938b44d4d61f54ccce24997981044d14c949a1b49c24fcdef78b3bbc37f9a9474fed113544f9d65fe4d8dc91ed7ba300a3363bf3034ab38cc44b2bee611d2ff933e9e9a18cc3459a448241fde00f0f94d6ea3f9d8a6fd991a52aa90c046c45e5cfe07f327460ffb15839e87fa12bab0982c340651f028ad26c4428ed5f58076679d0c03aa48d814bdc3e00dae8170f43691d03b4d1ffa95cd10a94015d2cdac237fa631603cc215ffb18bed1af591efe9ef7657babc1b211a1b2d73c1e7e02c225d6c129be4129104490f36d9035b8669100dae8cfae08f9baaebe2ec738eca325026df427711b4703f2f10aee656d3c005da26522dc8228dc189454be362bb8fd161227b80d05a481409c5970fb9b858090491fbb808bb8cd3a6c9331a9d047bbf0bd15e81389244397fae391eca17f66a9bbad52d48fdeeb04aec33dac45c6b06fdc764c6d66717b60d8376e6eaf2a788e1b6997691d4993fa9d7ba0a8ecc35a74cee5772d7a246cee884501465976e60714fb78a99fdd91b89126b9751dd9a4e7f206befec01c06b8fc3cc01c2c12823f00bd80cc384cf7257a3b006912333feb0cf1937cfe18c965d28bd89abcc4cf6c599e42786812d35c12bf48c4577a6c624a9945fc4c62a9d324bef24a3b845f7034899fc44485ff99ba9e9945a7b35df8196c543f0f300730c0ed375971fba9b8fd0a70130e24353eefe86e3a24469ac489a07e5d4e87a4cbe967af2be275383cb4cb17e793fa0547934cfed084a3493128a9b3ff0989f426474dfbd2e58c92d40e4993fadd76469ad44f62a2f27f5dced5a1465ce0022eb88007874909a65c88850b79487073797856f3b3f9b08ba981bc108b2d88b856a4f3392b2cfbc11e2d52518dd6485aa89fe9c29e7a42e4b5469a27f246daf3d56c8d2154d785581c8109f79a158a0a037fec5f2c91c87aebb18fdb0eeb337f4b88bc8ea35db09fdf98471f6eee26dffcbbb37e745191755dd6c7b44bdff93efc04b9f0331f86870550eefc08b48bdff93fda05f2b4a0e6ce0f32c404a8be69010a261051ee77514bf4d3053a71e13b5f86989d9e4d02d0c90dad82460ae99c735ea31aacbffe7a28332a6ac89b5e9552cade26002fcf97dea88617b54b4f2de49ea88bea3146da764acc06e88df8e1a88aa0caea6e6e7f660aee5e658cd1a7b47c69bb44cbeeee30423a44d6cf573783e3128eeeccccf0074be98ee4892825e3e83ee7f42c70fdf98817441b408eee178da219f4a2d606010b7837ca77d8c1103c59df967dafd112a537c739e9e600f9fe961646d47ae617d5b0d124117aac22572c42ce5c01f5223c91b489edbaae2af259c52a03edbaaeebe165290f9f1c2fc193057370afebfab75f9016ca4398e2252832410d898c506535a2970f7017b1aeeba256088caa72214f8ac94a166abd9027758415302ae8429e54147e50b70b79525e34c0881d2fc13be7b790786a8e28e2891372ba37e619a72b8bd12dcb7abac5eb611a0e8007d2a75dacef0fc7f51742effcfe1a7dca6cbc14126532b44d536b654f6fb0c66dcc9ba8243940d4f5d3eb003572a5139b88798eca6cfc94cdec066defb6741b2d8536aecbe660d992cacd3128a97e21fb10f83384bd1d80f490bd107a7bb850974d77c338f1035d0ae63000ccd1d71989eb5cc4f517a26d6a13a8c29185fa9cea4ff5a7fa5ff5aa57c5a0a4466e77ee88f6bd51a051da478f5598c779acf3017823889ca79a2531a1ea56b40752ca28230ea0b86fda472fdb764c7a65da74e95a865dd49a5182a165d845ad1965bb0e645721e3a8dd4dbe7bdab6c3a2cc9031ae8644970cf029adf196d7429261ab41bbd1d21c54adb6cbe6dc327ac724b20fbaf76d0f829c884caba9fc5fe4231c6fad791631794d4afd6393e8bc2416a1b66931c6d8eef123df1823e70eba82c864f4660d88cadf5ff422383b1ff10267e7235e00722268299782dba39c16bdfc890bcbb48d63674752dd9fe04015d48e840c0c30c000038cf61c7020a8651646af8b6299a5d18f6a1a6c972d720e0a5551e3471b372455eb60bb80b84dcb402adddbb0e4e851b69c3c2ded04411736e98b79e167d39ad81585ece5fac6be5ffaf869652189d4243923656812a5db11510cea47224999336502219530821754c0134d4d51d118fc502450a0394ba03846a03740a0292b765eaa131308d0078c004a319912832a2059028e6aa722f94c5765c241537ee2ac8025f9403002bd5902c58102cda902453285c640b5130016d4cf7455261ca697faf30243038f08ecc0838f2da45cf91e49325c503c2142df0f128102acc308126e7c7e4cb5d6fa82c3c781681113c407884f8d8f8f950b799a38023e810826373378f1328317476eb018c20d1657c0e066207ed8f2b7422c8cb0733fa8b2d74e853518be04800bf5ab17bae0feed87a9542a9583822f03cc01bffaf76bb9f0a36c62684db0047b3e2082cb76a77e14c62338fc61827187eefe3f1c4208e13bacb0c20a2b74a7f2c70edd51556bdcddd4d313c4ddbdbdbd2d9c0cb6f003b861ace7a7168659561661e699679e31866517e52cc3f8a2cc568471772458064be033a9e52d4bfaef7bac7ff49e5aa791d218194266869099b904f7333d71e4b328b8d584139cd0f6524de8016a11eb6751607a88288d3624a20ebf8ae2bb156b7c18af8f1fe347514854433e2ccb8386989eea4d9ac0a777a58232c6478f5b9fd107a594fa88e9d124f7e117ed1103ad081d428c0a13080308a2c26778858cd2c626511958795cf9f0b52eaa3f0cf272a53b3c414beb9d1eadad6248a9d7a4f2c3239a6647321a4ad4eee1165b1bebdb7a997eb699cccffeff90fe6553c3a97669b73e78d010d3a4940d901d7e6a5c4e71cd0f910f4e619b1f1ffafad5fe1bab67172bd20b33333fc6cdcccccc922333c3740cb31126cccc3d311560d2e3c50713263ce2085613062968b2a2595c219585156c322baa3f0c3cf580a5f89449a5a61713c7faf0648acf2b8e429a14e1cf90214d8adfcfcf43bbd01b7f88901d7c7bf030818518656ca246164419148931c618638c33ca1863af6a4d77f76a8776e90112df638c31461e234f5c9dfad196510c2a6d42ede71d70e4cd54eba2c2171ecd76070f48937a2503ff07101a38aef031bb0c036917b64d6915c192056407e8fd80ef42dffab103ec013343049ad4ff3bf8fc85f02184107633b91ff4f9d12eddb08644752621d571ed2b211d242a954ac52a24acf213a5b58a4452b2aaa7078853f9d0ebc0f22bcf69d1c35bf08a555e8242e78180515c28c43fa18ff10fd5ff151a59549ec2525825bf913cd12e11e638c2d9e080fe26a74693629402e8419daca36d7a7ac01cdb95f4e1caeb10fa153be267791a940e2bcff231fe2c762609b38de96779163b0382e91e360001befc394014cbf7b0837e0f16202e69f45c03d8a2f6c0019e30f0a40703026dc8ffcc593e26f42c76443fc6d3a062567e44ed0807968ff149b49f61d13e067d9a4d9b19a2795cb3ad78407e421e44ad14016dc8d758c54c78097c72d1a77f65231c563ef4312b1f0afd8abd6c0ccbc7b0332bcf426df47c584942df87d07be8fd6342d69fda98957eef4d304e7a61e29c88a3577348600d6d2096e67c07a4d3d3d3d3d303ead10179cc03ad5d0ffce97ae00f48c6d7b07c8cdf40efaf437dee37272b283fd5eb7a403e9b17d086dcdc7fb8cb6079cecec47896a7914505b243a773c11c4736968ef12a2ffd25e3d426c51f24d90f0f30c7bcf287b0bc54652e653c5bce730ffad0e0130feca2df5cd40faeba1e6f03d0867c1e7eea814bac03f28d8f81805bb8f22fb53c401bf207e0a47e5dcf950fbd848d70e0429ff106fad057ee63405c65f1a027c30b7990c58328191e44753d7e02d9117f773e7ee22c08549ffb994e42144a877e7f1d583ea4d5a488dcb0783cf41424a00d497b7c3a2d9a84fdd7f5b8d6241cfafd63fabd6d8c7fc8ce447a33aeaa80ba158e2ad12a1c26f831c2780987a765d8949f2675aa53a94efd74ca4f94d62a12fdebe0300ee3f0f6351a63af437d2c2bd2379d44e774f5ba9d8036e4633afed8c7f863dbbbf6999d01bdb6a3a453f2f9a75da44c81398eac407688f622f6619b1e91fc18c2c91807e6d846fcda882de869f8ad4ef19cfccc847576788a253d5b3cd16205e5ca9f1677aa6b463864ef9f841f6467409f3d6fbf79206ff28e9fb49f367bcdc33e631cd6d13657fe16e33320b723fa30463bb23d44690fd33a9be63d0d2c2aefb0920128a10aa00775de8f7104d0836a5dd65e077f4d07ed9734899b34a98775bc8d006dc8a7b453910ef9b9e1e12529f9a66130989726c9c7a132a964572ae44b5869e57a0b39cb0a922da75375aa4ed5a9b64e95b3798cea547ea2b45691e8bf534114f4af5f137ad0f70887ed575e87ee59be3b2dba9e6e8b2675aa8ec9951d14a00df92060d4f6f1674a0ca18aa8540c5895490c15a211080000003315002030100c088542d16834cef34cf30114000f87a250684e15c8c324c85118658c318400000000000018003344844d001c06bdb14274db1c07489a5bb307b00ce9fb24a2392b2aa3f1477e452030c00ca57288e3982ace1cf6306b9c76f03e3f7c19403418d6074372274b96f820e7943066cb51e3c72022b287638a4e76564984baed0527e47408e779ea9bfcb020849342da3c3392bd745dcee565382a2acf9e29d92668d863abcf6260cc48d1bae6214da402b9abac80c83584aae540c9eae7448d00bae5cb8d12bbdec245e0ad3cb44e6c9742012667e05aad89052074075481b0c12ac6a44be1d6e16b7714bb34868e11fd53a7e9a64e5a4fe767b819c20383c00c1170edc0a913356e11c0dacd32fe015cf301b3a73beb4317fe0eb47a90d060586de4eda2bb53906b1c8ea5efee03ceba9d2a8046666a659d26642c2616497e3fbf7e2bf9d0dba96d46b4d0f8cfd51cfc0a10a6ca795ec31270acd59f4fe322ec42c0537fc67089dc30ae83d33a81c9f4f518aabf368084172d9c5e2a770b6f81d4f3e3eff02f381146e907d3870ae004514429de22ad5bdceb65451d5d91beb9b50375ea7082866d5edd2334f45c5fa2e2d428fe5f1e3eb90686739440d212a39fc5d91ad6da67d55d008a6d075377a2818a56e7ea9ad222d5d216a960955892b585ab798bfff6fde969e6663886e90b2d927d44587dd0ecce8003c59c247705cb55fecaadcec022d8be52dc8c92759adb128f37a3986ade2340b7fd44f0bcc4ffe7c0335ebf83c419d5e5e740cfcc69121caa6b2dc1bb914a5c723a3355916b71847c628b7758a4150b69f192c4f33e9475a5f741ca99cfbbca88fdf5445a675a9c6192a311905b16cb374a5695b0af5cbaae752dab170bf56203bb2d7768cc958eadddf8544552acfd6cbc4f6b555b0369dd0f89cf8a6da4b2f083ca133d03cfcb1ad112a61410361086096eece32eb1c2edd214c5343ebdf6d5851c40c976e2d933dbae0bba772fd96b8c2ffd2efdc0d5d0e3d768f93081ce944e8f1a8c98bed6d0466505fc73325c6bb6e8d85deadbc417557ca2aa80180da6b88a96471dbaac777ae0beb3c82134b0a829ed4e81e61a61548231e068a8d3889bba94cd7a824a8fd89f2f4e91777a0243c83137c6755c4e35ab24e4e35de28c432a74c18564fa7bf22215427a040a02dba9881e7c19cae0c511a9be65485526f70bd5953b995931876a7269b4e8d50d5e8ac32d0bf15478538c011b85abdcbcd7a5a6c084598a4800d4c0182d38a93ce1190b140966d37907d76e56ca2d620fab846156c827ee0868e0bba3f1e29bfbf481ac4bf78c55aa56370fe1ef266ba0b79f86d73875fcb68df18e5c3eb3f295762b582363850c0c8bf26e044b90536184a10df3aca7d272e876770ca319f4c9e09d52c9ec3710916d7447d7e9a8471ffce734a7563f5b9b3d375a5c839683929ed7ea5f6cb6cee97a33adae543c29c705674df4b8e2aac96b2ffbc9e3e9e65f5041364b7f0a9a0cfa6ca5ab9e1b49d8e62f272f384108765807384ad9ef113cbdfdce191bf74a8d64cc907bbe13850ac79678cb54d72571c449dab78a2719ff8c1e609291dbd420cf10f4a6c554528f207ed084d3eddc918de42a4a17b982cc48c2944b021bb78d1ecab2499e5347ab26f10b67b761f5d45cd8f7ae21edf651e30cf6dd624baa70b65f02523d1d2df596176de69457d32ec4f0b50b92b6ab1906e0cff9a19b58281f558a1ae34640bd1e261722e219a7c744ae036bf822cd6c5c15e3696a40309e3497e3daad7f2d7d4f86f4a45cb7956b8c3f8922bcaf6711dd8e8705a2b16f9213419bd7d80bf728a64cfde6b9a98fe1dafbdac1760a875b9f0cf1558813aa242fcbfc613a1a23fe8a55fac08c94b1eddf7d5fcb1c73d7f17b1f373fb0d2f6ede5b7fadf287079b82161eea238ea829785cb0d73ff69fb619f920ecbf5c68c6ff45b3fe83cd83bacb1acb5a214f6535658890715f1121045133054196151521bce40de21de56d2d309f57c4ca1ae813e0231cb1a15c405cf93de769e08037c2f18d88162c3449146e1e877602c9e8d822bf5511555c89eca61d5564bfed2c250cc4cf3613d3801d003042944462f938c0b1905896ed12ea3432182b465f15a076514b9e04fbb41f2b561798e87d8d9a39435f749d4359726e756ba7bc9611ddb241ecb94d2f40e6ec209ec7c5a5cf504f422908e247d29d01b24587a0f68ff55254906ae29796607b5ddf1915c6a1dc456c535287bc2ba9621693ef22868897f4705d25c8e276f991bffd8dc2680c32f01fcf4708d196abb1f5b0d604221301a134141b01b0679b8d0348432712e397bde5f183d808666d254be06280583d500ce4688bbb10f2957da02cfb3c75d27e8ec935284f291ba386f5ff5cede3a7e4a89cdb284ae07a228659be44166050e4a5ec5bc28fb74f11b885048da76594347c12527c3c144cfd9760ebf8d77ae0d59fadaf7fbfa109340bd2fb8a604cbcf8925782b0234de40b13bc22b7980369c4939495027fd8f1da20bad1cd8ac32e4431f1892227c4b6cc9143feda425c0f6067e5886c2193479a3258212d3a366d6d7db17ac464a0f4a2e1394041920543ac9873643fb5bbc05d308308ff3a80582470274d13d1110ccbf46a38e133d359a1be5a9c0174aaf1b18359cd0b686740cc41f10c5f1cd91f7d5db8dee68e34ac29834b18679edb34ad68aadde2ca44228ce805c1f3de1f0d7a957dcf55963e70f8205146d335752484dede162b7e492302afae4779c0c4a5b0e94a428eb474ca9b02d2d78fbfceef7fdbf2b19ad8321d38c7f234f942a7c3c0d3f27f62e29baebe11582b77102c3cdafb4f21ef22884b023538c39b2f9f50a6898803aa83208d8de00f3fff7c741de0a429b8062b0608ce38d863a800d4439b2cadd8f26680de940d75c01f6e7688009dd1f99e4b273413ec964b6623302aec71aa1ee790ef3fda50a3c35cc95cab59f873974bb3a70642f813ab47e7d9201d54087c52003820aeba9b1a7aed13d3bbf20a2ad02acec93b2685c5fa73d7cb1291e19d4bc826443219a2f6e412377f8d5aafa5476860499c28a6fadf13372587381d9542b360590ec5847451c3a766af300293ecc1f40e3dc6206a6e6989947aa5612f327a1200780dd807a814d03b2981ae522a6f561100ab6e028a6b8040a00b13e2802e32d8213f827b02340228f9788a74081c858c3f4c42ad665793f81492844b9ebf28a6962556d7fc58c44a573ac5d46b8f3441bbc5a3b309f00d294798160028e32d2c9266ed3cbb84bb98467aac6fc5a1efef8b083e6d41c702fcf5c37d13f050eef77f10e2941e09b60e15004f1ce744ea83180db39ce59bb472df3e0c1ffc55a5e3010f48d001875250ccc097bc4ac72096795d98e091ae48d30e819807e99c7b2cd7dfe37842c9e250bf2a0684148a74c4cddfb078695c6e8e50bc45256d959da52e9f4b17be1471837abbc2b71d124ae2036f26fe31f5575fc48af7763b0302a310009bfeb9c47adfb7f51f55787a9e98bfca4786707ee4d20df6d2901dfa1890fc634693f02da87cc08aa9d7c534b0f0decfee0c024fcb1cec2ed146c0dcc294292dea21baab8388aee03e9f46caed2039483cb3740620a6351e0e10045cf8d517214cb5fa2a5097e3f6799f214416aa5139bbe22bcd96c4f676d07140837bb57b6cac41598ed46e33c12fddf1f942668f5199e0913ec4de8d36e9bc517512c9f5532ec621fa50c21fea2ed23c5f4375287d5600c4c10366c60c26444f7e172e3c1d3bfca828325687bf670dec46ddc5d5bd72e06262ab3139cf9074a3ec2159fd8ddb4a5046295ce34cb300cebbd92352cdd792a4976d359403bfb66146337fe66dd814c833836e12545e3841e2800582249384347d223f4cbdc5bdcb59b11178ffc6b97aa6deffa5b48e9c9ba398daebcdf725bfe602b358fb9bfe8f3b7f5c85f7f8c9e08650bcffc80264fcac5ec3471c550476e40f3b41f94233d4f99e3b99843b5705373e76e868d3b4d03f2c8437b103200d34dc3b716ceca98c2317d17a8642132a0d2f233c94d8bedc874381b7f3ce2ed5dad6cc3ea59f8912cb8a9e6ecc9810e0080331651b58a7b0112de8794146fc1d9d28761cc7f52b3ba7f856e49839b832945a3816634f62440d9faf80872bb144b746970384bdd6d25a30f7e9c8a64933a0c93339b585d4ef2d517f08593b90d840ec4c7cec5ce8db4525571e0bb77c1022de6a398dc99ce7fc46500c626b683deab277f0a98e40f0e3aa92205a4cd01a5adea897d8128602cf0288ea576dd5b7f11d781fddfe9e552e4c5496d72f2d343d741548fba06aa96106370be2b1f8f6cbf1957a20745be51fc753a4c35bcd2cefb451fe730329fe37fcb0f67bd8ec97e5e777121b1c1ae17e3a1593232cf89078689c7486dcce1f2849d29e6884e6ab1ec750961c41815dc64491b14200ffba3a1f75f7e3705c60f90ce78a41a443acac847faf8f342a68860ff5c3f8a5e614656a987aa46278b136d847d3554bd72bc1ef364a12f63a067e8a7c77be10fd3f410ad54844ef077171427baad00c44274cae66fb4fcb27688246eafcca62244f4ef832bbf94769a10b372e7a4009257cc27917729f5d7a742cb28fb6d4272c15346f57a0b657e23a08bbca6c451f3ab09f23629fd6a8e71b3c6c4cabe4f028dc948f31fdec4834147b35fe965961cc79969b939a570fcc1e34868d30dbf2ad37503ddd5df1f967ea50a7ec574f918aff6997911a4fe40fd5f9d0a2fc62bb1eade61b2aaa84bd96bf5835e11977d5e5300feee0f79d2b22ea12b476e34e15a97687ededcc8a3fca578b3a8d4eb8f304a41586a9d5cffa95b2d9b54a7fc4e1bb2bf710853914c3e311d05d79871933945781da62c70525e83e32ad233b48ae7aba30a6526896b89471333c47b05826d3a143b380d7ca6e36826cb94d4f933a7e2be28e39c29df73188bb14b079e147496335d03ae47c1c700f76a60fc8647f49e0672a19282d14edfb6f0e921f9e2de7f148ef032bfb70aa0621a6aa637fddb3d9c04c24a75a3943e2e01ef08b544fd1a672466538162336dd17f2c54694017654d9b9d3e6912692311b48e4d2de93ec2202a049e49df637dd296d59057fd6c36533d3e648917cb1db15210066c668dd45123c87daf4d3251595bf72b010873c7a7183cf725f8d311650e075a8ed099fa4f938497c383d71179973c9edff816891758c874eb782887556f874884b4f6ece3f85e28aababff650911653e9dde3a8ff59011905b44848b2366ca294e28d96ff3d58f7ad9495262f7ede2aa28d13d8fae0695eee2c197e838be0762b796db77717f3d9f8971a95e02ef36c40201bc36797d3540e5ef1219b233ddac14adae5475355e81fb4d0dcdbbfb2ef1061b8994dfdd05404a89941461c1836d4f57b016329a55e8d5717d1987c0d24ccc52abdeec04761b5e2d190ccd811ca40f6ec56b87060d13cb8942db856fbfe71527b9a050cacec34ccfb20304502f867997c049e24e6c042d48d6a7251dc96252a02bf160e2a9ebdfed8517f4fa8822656c04bb9dc1dee9f8e0fb0a396f6a58847ff6f05216f779b04e487b6fd3eaf2337cc4fb3700fe728571317491d158cf992bab9a58b0862f23859a803c8b341a3f11b11bb7f849f232908b35a3fb493a8cff721f04451a6c025a71f917780006ea0e39a79ab45a268382c0b687a0e674dd946e05cf6616e628215fb3e590d5883c1d5003d378fddaa8f4cef6b5aeba4fb7648c335fb4541c01065d3b4101ca68429cfe19cf7c7c89eac4ae7296b0ba6c5bf6aad4a5a36ccb06de74525a90bd3a7c91a45bcf11fba84ab1fd1690b08fd997e492481d016f0542f4f219c79545775a07e715041f0461d3171d3dca274a2f03f38cb95670d8a5214f02f058805f2e9a52a3556d8524381b6235877861ea0b7d1545130445de6fd4895920ad92550603f29a1da80680136c79398d5809e12b256b4185482564c4106f82070bc22709368a375475bb963f95f85020f1ed41020759f87902c5c472ab19d1754c6ca72b0bcb35eac37736f1599f3fecf8dcc7c63390f9f46254834ab376883016ea382debf93aaa2f7c521bdffb583db9250fab6a9bd1838c608bba271008066172b67b474b5d70d7ef82a28edcb58e55055654772ea64d00c75f1e38856a70c23ba094b8eb41ec2a1552aa888b44555e9f5be033a3b2891e83782ab1d246bcc0b89377f78a4c561f22aa51180a3d6d682dfc289812dafaa5363c0198588703dc460b1e1be552904573c88a80736ef33cf9a868e2d3b962b202ee220b6b080f1b363fbf4a3a6f3831321e7dfda18892ade529578f16aae54048761200c42fb21476859e322e7cae0b811545bf6db9005021285f083421622cccee6abfc7570475544c3c24eb84f594cbe8e24c4049b3382198cf15eefc638beb0469ae1d379043313c591d3fcbc944ec543925d3c5c7bb8f3ce08b011667c211ccdf3b6575808847c487cb02c9ee9871792cbcf1641647d2f5eee3554576dec717cadf70b66afb0b5e0a1d870029f0559f33b2e2ca73f8843e13f6e0c0a335abfd28d52c3c096874aefb050eae55de739e1b7b23f3d32e3b51a1f2cf508a4392a66a7053ab1c97c90c1e29fdf132c1249a1f39ea1151e0a529514aa91333710a6a4f9b1bc47fa12029123d68d061ea1cb43139230946ce05982f61c039b9c502cd01c24abc31e677cfaa9aa0168aeb05fb1df7171e7d868960dc8d7f77f80625dba6dd705686b32b68dbc672972d7adbfd61f3d3228d4fffd45b19591ef085f18868025a6cd0b85d72794cd8c594bfcacd951c603ed4ecd4d5cd3c271299dde688b91cd97979b9e87119a08d297254c060450a7d0541ef7f40342e3a500581a172ef34077f39cb6e1d5952b5e7d65fa22c4ff8b20c06dcfc52b8d8ebf9cf31818325d8948628cb6d33e5ad64a30e563eba27d0ab0060dc0c40c5da48a8b85c47f22df807d55415ba67fdfdfaf738b35a1e51dda888468f3992054742d3fe28aa8ed7e7f9c7d4c8bd088d24f90d5c5ad9392a8d144a7734d41fe421d9717c6dc6f6e93f393b9838956322f1478fd73756d959582bac298973366f44afcc3876ccb3a258b82fbc88cf777e05eb37129368936a97fb2c46b0bdc3f48441953ae93beacb982c1165ed93619e7c4761b104a645816e700621fdf62e9d44ad0ef8346784caf23b650cf3f7e2bf3f22a6c3dc6e1b5b9b94cf08b688ab8b70d5711c574fd643fa01b360cf6995701469179fd06a50e8c06a5b713680a79aa98e1b200b2c274842a0f763b13f3ea4e7ba92a79466ea98ae43614e7e4d3bbd97e8ce84dae87aecede898c08af30c1d45d36c2974ef2883205707b091d6ac52a6f236500e55d8aa0df51a36a4a867912e78ab190a5dc72d337d3641724c45c00cf9fc34d296d9a232570aa2d8263d08b8e9605d4dbd1104551008d65169894f2453d1a0a7c0a3eabbe46a0134af1663e1595cd9acf0ada4159f7de89eb59c16818827f4c767b0f7d5431499747a0d3bc94bff7f18111687a723bd6ff72a682f94fd5653e562ceb948129a1e1d911208f917e5bb29ec4f334356a7d0464a59fdb31abcd80a19418dfda0e0134364474826fca2848045030005f77b79a7276494675a32c7120d3a0552383883d0d8d8ce4c39c725d9ab9622f69ba462e857e3a8c609ebb7fbc07684313168d0cdb133188394c232aa1ce3a526f2fbf4bcc070931ce146e40e23a85017036b50de73a7fb7c3ef131c67459475b3d6e911549ee8379c6c93fc0d9b3ac544dbd59195d3170e230727fff5f8c16f3616e79b28dbf39764e0128c2abbdefcb153f3c11b83adcfed51170ef8adddaf6ecc3bc03f62f2f593b55a86cf862185f019761fba9dea3a63cb517faf5c0c90099435da8e420d545c556169f89d692013a072c0742e986a989e7126187c70739b5c1a721bc24324647cc21093f98fd77011e063b24c78d5c89dcde5c385b4b874b89c9aee175a1c12f3223c7abb1d9ec2840fac7bad49e235c7830d18fb485e3df4d22038e81ebc3fb60747c7448a3001555425467dfcf614793c3b7a79de6439a9796740016e4bb1bb34e7e988432fc0cb5259976bce29e48cb420b72d47e93c8e9fabafd1269d03cdbe650de7577cb2445e59dfb28624a1ff031b4bdadb2afd55b00ac2d7c50f56dd23e7ec30e365c28b3146a8688d5866b0a4042e1f129857d401792f34f01c10a5d443502cf9d017963c060e1bfc5cb24bce7276c9e337ff8736154f27938fa3ae409813bf0b0ad4582a2a545908889c6bba04358fd1b2e1dadd992697082de90ac52428428d71c22ff63eab776ddf9505e0429dc46c0fd1b0a04d17f4ab1605049e5f5324fca343b591d36e0f6c244eaea5ac7a0c87d2fb4e1f0baf67008fda44378d6994eeb9ca0fec647cec686788ef82a83694afc3705db4a5963f63a1519fc5d765e4613f7666dfe5dbe08188efc034f641a6c99c2781bceeadaf459d1047c4dcf2518d4ef7b0f1398a9ca7b31d13dce7e7957d71f578d2a3339712986a36ff990ec2f84ea6c811bf4e7f8ec2bfc0808358506a1454bf9c6c392541f3a40c2ed04b00c9a6c0788454219c6dae8171afceccf7084d47b18c716df335fe84bf6a7b850c83e043b57562cbd902c6ec34557fc0c56633718b015646026b4a85116f37e77c9955cc12b2180429e8f0d18e75a80761466ffee1e49c01b7f6b2793abd2d4536c8f18ff2786fd967bbfc26db7c595e9d9819bdca7d18dafd6251b010596d59ec7fc36e02979e30856897371a69c0e0c9eb0fee77490f679f8d9e6733d46807d895441eaea253b006dcd8fcaacc911f6be0ec71045b14b11567c0a8bca65b3637dc751d6e680f17baee8254a5a200a3010f1ec5520866736cae95c0df3c880c3241617b99d8527036c0d2b091932088927674824d73283b37b4a3f3c208b49f922cc46c1f1ba4a1e494735d6fa749cc6821ea86272e154eb23b17948f8902a6ac6ce360f7f8952ed431199f4399b51293d3c4ab2be71c5edc031ae777b8727f15434d1eec8a15a6e72113945f10490625ce285733cc0bc71346cad7cb3ba411c4b0a82c8a237901f1d22d1cd1026de502f7d8553486c9fbcf9927951f74818575bb9afe73b6ff7a1c6c900ab553fde760d6150e5ff4192d380d85f143f8b064696b63df6abbc515a4858dd91ea968575780f78f03620f8e818dbb7380cf38fca2c35342ec7a12a30a4abd8b9b7f70033ec7f8c9bf66ca8cd04289a228014e7a1a08400ff3a395532faf8cd53685e804aae6eb7b3deae1b535c9153f4984aec4c8d5d92501bfaa72fc414fdd26260fdbe0c8154870e704a629c5403f49abce92c23ee703c690c38085f0874d2f219f0a8b3aa0533b6cd5ee888f7c1da123349b2e9c32751415c649005c7d5e61678bd72d9fb834837a9dd9df71004c37967a558c9303f4210211ab438e7a22e3d36ca20d2c1770c491140192caf766aa75e19bf9d1ee6f4d0f3c9340bdf06b2d0c34f10503a9f31e39883f8455955bcfb4633e967711bee1a945602f67b975dc69ed34f4e9cbf569223964994cc201a41846b478062924516514f91ca634d20506a192bbf6a3ce1a9e9be9a40aad8ed74f22418bed46b5acfb332d93355a0829a6aa633b0b3813512558e9549df85609b2764a1216ad65c1b00683b81c476d917aa24c729ee8e129b1998b9174ba661d5a51f24eda4a22035af00a8057e30e3ed82fa77a0674aa00760a5825ccafec1fde22e71f96721e79f39ffbbd0c8466b13511b2c0b8c5877f883d6674a75c395ee8cd2ecb0c964e5ba194ef8eb8f491abe2dc96eb16e412a0324c42de2cbb24e2073603e3ed21e8ca709cb94c8c00966b42cda0941a85bd3949c1993e8e04f3f448feae548c89ed852c6167ac93f31950a4d17f0e8f25669ee439e1c2c08c7387ed06a00e2bcca2f39a1cbe084dfd97d548acb42aacf5295a78a490263ffc4304bd8205c8bc3aabcdf6f123db00c26b54ed48f7425d1cb867748a1ea42329e0e123fd1b2b1a974dd22bbb016e35017ced5cd1d024e3954004cc7ff5464c2add8be056f6e2609856cf936a0e2cb9e55728a009ef086a39a3fff735e135a3df630c9ac825502c1af9ca703a0a191472990e3ece87c14071c1fecba6f9e9cebad10c2e48bcbb8190e9f1050f73bea5cc870df87204843471aa658d8e13e91399641221bdf1737b3c6cfc444b271a800354d01e87fa620fed0120ecb8d1530459032aa21407be7a57c373d2db711c2f7449db87bf25ab7445bc3d9b0c83b09bda91f3d1a0116902776fc6afbf2fa49f080c51bd33c2602a3d8c31801269c64ccfd67ddf93b03f1cba067bed0734252146c169a0fcef1aeca8528f100f996cec1f9a51d1a31a5121b14f77fb545e639713cb9cfadcb042519c1df3b523a61cebd2762ff073369d881f886c76c89a4da245494586e92c89e79d5fc20ea2d021e1457d8f049accc99d70390a0942c7004b8183b8bfe4a417409196fdd95252bd8124dc7dab617c97883e02a794059f8650dc5ee194c9243397314a31586b55fb093c486773978af0c8499bc89b2b132c5e8d15b515847fbe9ba4d3188d63c728fc194b998347e98d406e4af89dcad20b4244c9aa718aa82018aa6d54fc1c19449675ca97c727a8d8f0a1356ffba611f46c223561c51a6e7029ff8e20aeea50c22ce9ea32e5f793e61b160e2c7caf7c0d4bc5afccf6ad61773b983b8201f304144d1c7928d778ab7e12e2d93d41c10463da697424a676e1c7a09bd13a10e21bea67f403f922dc4f5d77d9b0662fb2eb338dbfceff42479d066d915ac79ca08817cc2debd327c7234a27c24847309fe4038ec1580f27f01e36c72efab3214b3b4cfa5ed21e6e409f9b36b58360857cb0e034a4ba3d08ef0d3d696fed217d2fda89834de0b355ceb554423e1d177f7125aef54f7a67ce450e507d83443c5e8f35246a09d193ba83c85bb0a5569712828d51b42aab47ac34a613c729d525cb35f8154d198a95b36ee8e6810dd023f851012255ad43443334b52887c331c3286815cb240ae9329d290c61255f98ccb8b372aecb5b3834369bfcaada9de2f75cf83176e6e32e5c84982ba8aac4c2249bba8615c5c83f46cdb0fc5c803a3957258477e3923bb30a979ff2c8376747fd3bd309eb8ec8b56675e19cf34a48a90d49bce4de0d9fb9078914b7a216b9f8a5b8d3efdb7de0295617610222600ad7a1a5d674b1853ca7a30855b4245ffb50b0c1db90d38bc7fe2c9179fc941f6d16e7038652fc073a3f4c68e4d30ec452736b6adb281c85104dd15d5f79502eb12f9d56a87f6803c3c9ca7eda7ca3a92bd8ee638b633a868fe908178f8ab4ec30868d572a086d1f93c29777e5f6fb03f222488e65e14ff955600fceb5230c616bd0e171179cf41cc7782dd37605a645c7057bb3a1f8b25612ac4cf7ff150b6e8c3a2e0878544dcc17906a9d8e307361711670915cc5c51e98801776ee932081754fdee8122d9caf6360053565678b3b14f9904cc56fe03f04b00181a7a4d020e2a5d39fbcf28a51636d11598ddffc25f8ea952a45c8f2ee7b70ce9caaf0a83e4ae2dc3cb87e26be62002a13b9670b6d1f9cb319cfd6adf21af9dd8449a701224719808fc58dd1257f74644027037640d690e86a32ee51ba054f75df579791ae726bd0358a6ad57fff4d3b360954ec45813588694b7e084a2dcac5795c882eef1eeaeea73abcb0994b28adc126d3e3cf7fd9c9a3bc665609e1744d99ecf80f6770d3a36bc9e769bfc7c78bb8a738667a54d2582d066105987c3c6df88e9abf9a4617c26d92d0d08e611b8ca9fcfcec9977e26562fc50cb9f928fa5fb917b22cfe6f7ea1576c3855cbdea485f92811e5a2306251514bffe1eb0beda3e2779187f9476de1142d32f07a534b8f54072fa277a63c3ef2d54d1836bc165dc15b4ca89182c6e5aa889e365bdadc37298afcb169c8b9718982fb99c2cc8ba0d853bc4f139a278de0dc01d4e908cbc939a188c929f1e698afd56662266e8be8b5c9a316d8a754a6a76f789abc29ed30380eac27a63d743645b16ba3701df9580d926d9e337d5463d875ca508c20111a6222f80be45289af51be735b0164bf7d5f52d8c6c5329df355c96240a0da64dd8562743d3147e5dbb84d9baa7d64bfce2a55f0ee7f77c1e2fdb31c879f5b91d172fef6f7ce65639772ab5a54ce6c3a8e99dec45fbc2932c285d2743fea9dbe76c421021b5b0de57ce10f6b6d299a39f06065088f4603f995b65fe61974231e44388f3a7eb0d2eb1454d6f16f4366062fbfe1902dac49ffcff203280a8376939b66d9f37288daa7adc5d1718cb3d8eb03c1b1958c63b4c7d808701b4bcd3970c1d613e0f7ab7ccf692b556c5b7277d072f4b51f2d25c8a45776eed8da914fd9ae6c1009a322d1cf4c7c918d0c5bc40ef12f0d8826300b57a8cf2b19d08b3b09b15ba782288b1ddfb0b8352d10d140897c704b21aa2600d2fbd266091f40d6e314683cba3b4126ba0a76089cf925d7f81dff423c0fe0825e9dbe4232b5fd1e83c9da70b3a5efbd4f871961e9105f128244858dd13286215c598a63d7574ca7cca3a9e472d495d0b2e76ba6066f3a9173d204a34135464daf35ab4a679fc945053f33b402ecac3c093dc7196841d88a51e6ac83000c67b0ec2d073e003b54416a9476a5644e4182ac1accd89d05501b16cafa0fa7c0dbff1361e411a9d79c7e6a1d8fbc217303343e8de9e1323c3a2c6da9d390620438fade3fd2743fa75c80409aae4f06e2f05a0d4f9035f09c041be02b2aa2e830adf80feb95dec8efa2448316a75c73f0f96d48203b9cdedbc4967b179d52e7abe96ed866f0787a7aa9ecab23275e740c17f79a0236807235968105f75747a23d92799fb754d52c81f2015dc7b29d7329f6528cce3cac8d1ce92a909168e587edbc2c9211412d1b75c733f5bac6c29284cddc50fd6c95de53d9b6b383a8ae85eff4cb692fc08d5a20fb005440bb4e5db8ec42950352413997a260989d3798f27a2b51b26688a49ffb684af5bd128b11ba74f6f8adbe6c665ce9635c23126c9146b2d48ec42bf2fa3197ddc63be6cad20fa370cb77b8749e0bad47ac5224061af8c8b6fc2c0beb775ee910e1b153a338e15082472e1b66b7a69cecec0da303a2c8ce5acc05f2d9969ede9c0285b0ba3a9e81c9034630e7276f4ee8ae2690254b9fa1cd86bad340516e9878108e93dbddaf8c0a963b9a7b9a191de2875230aff6f148b600cb9c04a96e4c5f41b2c73631f90e1e306c5edf32a11c16130a9bead71a1b17fa85e8caedec28c6d35626b962de39bdd0d20926fb084c0fe349102dbd14306358070fa94235c49f37d81c61148dcfe65f895862d5a11e506d5f64c98fb48a7cb6a84148cd48d8ba69d2a1ea272f5b875dda5f8ce743bc01ce3fd8acca917cd69d391bcaca8eaa3785ec51a49c34bd5941125c2cb3aaa67d9c18f3676dea4a04cd79833fff69b5fe85fe49293ce1d71186efd29b1114bb995289824dc6c33fa110e503474f690652cbed85ca04401bf1793b56b8a6d0d4767931b01d71d4f8f165693cdc39cf48ae34b2a6b390a532242dea12ed934f92055e42a8d95ee8cae282aeb17c107985435dc578768ed4fcdc5bde2f4623705589207ba0cecc7f1845b75f60df7ff4ab825e885aae0e7a2b32ad3c84140aa54d08bbe1285f8835672571f20993e3c7d53cdecee927027e54932890de0490effda166d9577ea81a6a6a16562063a28041b63534e44f80d434537777f848b2e94ed6b42bcfb7e0e3c7224ee084948752a307866b101310de2d7c4d1e7d1d34cf8b624cdd2a0cc1607bb9daeab2b81fad993489473b94da8302c73d9075d83995c33a0e7e0987a3344e6a3fa9f55d5379a02f36b4feee8de6254fa2257e9fc1c8ea639cf9622a8f605d6ae9840379ea33b0e46cc20a0183b9fc998ed673be86cd698df3ef86184049be703ee4dfa2fd1492a7f4b8f6f44bb801fea4eadc80a5cbaddbd482b914a278c5bd9388eb477d20f630bbc04cdd3eadeff340874016ec99cb9d639d9866d3694032a97c15dcbfc7789cfcae87139ddc0f44dfaa736f16fba8d7878bc71c7881abd03a2684ed00ac8883f08e57f2e213b21f2245856e2c0402c4447d86b9f78c70a9cf1ec1038d4443adccef1362e7eda28eac61193ed7653d6d8ee4f78fac5968ef904d017614488f4c003da381cb5dc51e317a1642a0202eaff513532a8fa10f74394b4f472f09e123f11c4310df6d0a5d90d553a6d842c5463216e3523e01f591edceb49952824f8a03434ad6414bac2047dd17764a6d7a5d52e8e42cfe0c5b47e89e81ad3c7b2a352bc075a85afee09d1f0769dfbdee58099019da5518c196fabe103cbbec97814cafcd90dc466137df00010f95ea4e5e3e2007a72743140ff9c480277c0cb131591a8c606d9c624889205f941b998f40ae51efd02f1932c3c504cfcecc1284b0f55d341001fa336394dbb78248e686041e45f80918d40d06a59af386eac2bdc0a941b7795f2c181bfb89deccab4eebd1c0ddb98f63edb79f222c66d41ec518ffd4e4524c2e66f63f9813687546b7d57dadb938b1586f25d52673860dc81e3e43a7ec215d1fcfc4bb469c5be5f8715dbe1a7e2e9fcc07931f7a95f31edb596bb1516c4922d0702162698ed02f510138898223c84ae76ec0adbf163387a13227a168216585f128023c76311cf71cde8d7a6d49a2bf1e0d326137b36c89c5c218baaff794e42147029ecd95abc0acb7089eee48056120f3460ccb91a65cd457340e01b498e8f9827b51e563ec4cdf16c305110b81def99d247a252c98bc0442e57a90031c0fa5bcdbb4811fd7a29ae7569ec6b2f5a34d37f672249deefd0b0ca0c248593d21b2ec5c655a6eea38c6c0c470b2753156490757838a95112c3c1ff2a8327951f180dad55664928194c4d1698f62fcb484fb53e0111b73f4dbf48602a37e89e0610a1ebf1529882e7e2d892606d0e0fc189280fef58b62f77f6459f789a50b215b9609a100d8ad4460433f9957eb350833824a3803cb8b49600fc9ad4866cc53b5a832772d7206e4b2bbfdc3121ef8a9107de51a7b4353eb539db238b50df4fe156bd3a92360fc3e0664dd44821740f5b613855f4dca7e7fdd658fd4916a610874496a8bf08af14ebe564294ad8bc41c0002d2fe323c22d11d4f3cb964841a76ab7b3847720aa70318228e6c18aeb5e5b5875680c7487085c71f2912fca95b3d402d85b982eaf95664fa099a99031873632705fb4535f880310eeac2967f742364c138c8f85762ddb06b2313791b5092af3cb35e2f596e1f83f26cab57cd61fd9c0154e0ce70f56d66ba4e5fd0769ce2c3e172623d608455b8370fd4e5713a92cad44212579045cc65127412b95ba096d0b0a29aba4b76f21b2f6352a5c25acf51bc0526d798902a2a14e143520ca68aa34e89fe95bed8849f60c8c4e528dbe2a2c9e19e9b65fa1f2e5ae35f4f1928e4ab05fc24b64def4a4712e799b34ba7459960f132544694289c5273b2fbac2f466b77883843f822aae0beb2af3295e70300232ff7350bc34de7f3e8fdaf857009a0d0b6952ea79ab757aea7f62c1413334ae4deaba1179b646e0a3b6be5941442953259ffa7e896fe1d7572c6d2dd61bac5b2c238b45460e46caa0dea5362538cff6bf99562240514b10cc7649c2d15dd0425ec4883c4baea4381789d8166350de32aa58067064730897b11808c9bd9c69d55bde7939a56ef56f832d985cc7edf9d243519d386ab864248f29a4ec4d2ebfe398047671e917bd0f8ee27d894d7c436c25d85ec128371c3e6248f0fb138f902ba9853b0f26c6bbd13c6117f544b174ff3c9fd16b226a80e012ddba351ea816172befb25bc78292e5318b29e94a6dfb3031baa9e93a18280a161f25130dea9f8604faf7980b767240fd05a2b015433d06417279b615e4768556ed3ba3caf721a779b12a9f9d87a41b1d28d8075cc5edf75e7ae4771e59cd589a6b48a8f75ac81096ae8e6630c1c3d4fd63ca690a0846d50e7093399e1b083d58f5d36c511a64aa507374fc46d98164e04ae29224529b2478b1557cb3f1e9b03043b5ad9d6392c757cd6945effa9f9102a3f1865c7deaf12c861a817219adbf055710d0ac5311c4c422132b0607680e0151cd54ab164d9708cddb0a886e8e7fb92045876d16f7a2b9547e24693bf7da63d153edb010e1d5669924793be29900f93888872a65df9c3dd38b0f645f6cdef0520c0bd6e3141aff374bf5c455cc413d5611555eace896915431909354b5f387c012652bbbb912bb93218f39824535f508de380eae71c237821d386c63c2dd4c55c979643957eb0f12a1b009de00388009ac3594719515d0c6db498035fa274d482049c226883f536e64747bd31416c69bbceeda4b1c101dd75e3b6e027525d71b1f355ea8b6f3bc23023c26f697d1d2899981a97ad709c72c269efe8c3386bee4d8d2a461158ea2f7864eec83ed8da02f31fa80e2e7805e4743affaf7fa27bd1cde5ef0ac170fef756cdc2b6a473359a0e2514a60de90346e5d5ede0135d492141948053f518c9a3b02d3ee56d7e840c327238fc03c2d673a1c63663217fa6c402ba3f23997dbe042090b095e8b9db8a471b898223b94c1dc5762c95cf0b77b8d1ba533ebf56abf2a52430593975401e7b585b9dc2d1be7d4868efd26b5c235915e778c82499b6b6e72aebd611cef6c59c94c13039ea4c0f216e9361662a2a6cc6bff7b7dd35f1177c543050dde1bddc7c62a8fbe5fc17d33769f55747030b8e49c3f4082ffbca840ddbca0f976c52e2a2d5d58b8d6508ffb830183ddabafbc6cf8c26cb01b45f7b9e2fbaf04763c99de15b740585a7213f9ac10cacfd486324ecd1c8bb21048f59fd5da0cbc223e1cf485f38a340466af848927935b038f6d130d9b1d3cf4ab986be5bef6515097db693591f090cab936079c4066b4b2e6bb4ce179c621aa37ede9c46316a5c385429405b800f3388d6a20c3f740f9bb6df02aacd71871c7c0370add2c0eaca18c6241038b0778d581e254d1901bf038454dae90fec65c2563c26209cfdd380792ec7af365f10cb29f2cfe64e8c802612df717d3ff2403363e19f6bb6954204dea01ff924a223cc89c86ecbe1b8dbdb00c85a2cc02499954f816ea0c62420c31dcba6c0ba34e7ee5c7cc21d42ff667084e73297ea81a6d910ccc9c3fb45aa84f6260360988b25a890acd354429d67c5b1b128b5970bfc530f0f28abca046968352d907733172b8fbe3d24cef739341a012c0ae4569cf038f88d5be4a472d594fe389ecf729ec39608e7293ba377a057737b8c92e88188f24b5ebf530525932baf8bc87842724796218a0c9a94b5a3cebdb9b8b4b51c5b25a28eec36d1ed4b4e88e11ddeda62a40fbb64d48b39ffe4d020da3fd5e1ab6f7e7c98aefd3c2af7b8b82bf70295871081ec5b47566b30b0ca09cc85fbb530e11d35fa7bf57bd70fe5b196a19d5cf0e14148b28ec173eab41d260767d060ff12f6ab05defb9f448b94259c359c18a799409a6ccaa776d7bb1f987fb6889a673a634796646432a30022012e99fe456518cf58f9ebb57a2bf175081f8d62c54900d8f81846dd72a971852b0b70abae78d45da3cc93d688251b85e3f27fed9b93c3431c42f148c7788335378715cdc160da821bcee6ba7413b52079076303d6f00d79dc3b00c16c2e4e63f772728e104f02d4a2ffb73904abce429db60223a3650860436ff43d983584e5657433faab93b83794d0f0b98c5cc11657e45225b0e75d95bc061e2df66487467829242315a461b8e8d6bda7aea248b25d81c9cc958342a3b2f637c8828d7102e1a8a7c11dff60761420ead0b75635a3ea88e39d523bd13a530cee315eb0e1d4aad79d8819f74cfd51fae1850a3e9b36e72713cab388a14e5a8c0f9c551094aaca4b1c97fa79bf0a328b0d255e5ac21f35462e3912fdd475fc0bca7fa4beb6789178437edd0dddf7b3a3cf6edb7e85bf0eb6c8131beba5f413a701ac5152072eec7271056e1543fe396feb10ac5df6d07f672941da0f11280e6213f609fec13ed74334397ee71899d89f0e6a7065ff9adf7bd2f6fecb7acfa7a568c5e3eb6fbce393607fe2d939f2ebf2c1bdefcba13b9cca40080145339c5f10b6c097109ab0200d217bb083918955631872f5b9cf159fb54afb3f3d0ec98a18e5efbe3316d4a5c383d68d646080b0100c45365c7a871eaba2334ff1ff45813af1a836f4ed91c2e718bfb3fa2d4c9995564675b5a775f38f7328b19b76b74947ae5eab93c27b2a0416022699d8afde7b16758605be33ff4edd640fd8c7e16faaa630eb069bee8391595d41929a7b38afe9e15a7173ec63ed6f5937b87314118cf4b0823ae980a6725913b92fd7f906c2286cd8750ef410cb43027e606cc31d8bded83c0b41b70aed4ba7573f5ef220cccd266d482752e0797748081c424a6deeb719cb349cdd38b0f8fc2840602265799428e01f4e632656d885b849357e5c690fd7981d7b687493054aae8593dc303302a9d6b856badc59f244663da817d29264fdbaebd91ede60acaa262d7acabd88ab2c656242d871a700bef61950a6aa033a5085f993328973889b6629471a4e80ba18696b1cb24e2c877334b0e0d18b9005d36aed8629ebb7804d47f8f269fec70b15b29a9f33c5196bc249e7e89d509eb6044235dd87ac950dc630bb813932e94d0f63ad26c80f57d1edaa90c481d57512bfc1f2adf794725fa29034a5709b3eb4cd3bf2ea113256cb20fc50e053046a615c980a2618ad21b3c4beddf4c788c6398d774cf652a801e8a7bc1b8ea3e552ef4d2982ad2c7cb5f9ce45fd52cbb8630287a370c8dcda903c5111b2b4eff90fe57e73a2a63308609edf9a528ad7c723eb1be48ac7140480ceb2e8c918423a17a490f9b0789a8de0ea5b35184eb0faafd2ce934a180ac8d78c0642981fff80d53aa3d3262e210aa91a570a177c39414b10b60e8f9dcafbebb95dca6e01684e9a0da1bbf79c5800ab69845bed6b94a919cf1132e643b6c8772ec4aad3a11e27859b7e862a3758bf62d15611f8484364f4c6795714d46681bdc58169d4bdacfd3803e08255ec6c9648b48e84a6ab1a08669aab9d3ecc09ab2aa0a2997c76353bc04580c35d869e05b1b521d2dd95ccd841f6db41a292807c22e8102bc17ea03f07fc0bed6e810434255f15fbdee6e10686042b805a57ed476f69f07aff6358e53537e2fdab69ad290273049bb511d208309d87a17e20a9f51eb39c22d6b99b884e0f0a8c118e4b8183d547c8bbd562e67c65d69bcef0aa70acf039cfcbf7277fd73a96176034fdf2931f96dc724190ff422cd8c96ffc43d494ff711e7280f685a93c54e4b6980d004b1bffc51686c4527e2417b300e74b20d9b1f7f63cd72cebd085bdebe4d26428a3297b0461a7d5e439172dbb2b325560195ca471f3197355b292277d63c87997125a8e252b9f857b7c95a17c630b39eb0efe9f13e4637dd92a05be945d0ca030b80998fca9615d9a897afee815c9b43b27557dd591a070101a90d6622e88a01bba5891114bb67560f85f1ceac570913281733d6d816eda46b17da2542308031cbccc2bd3739fe3816b54aec917002f72563adb040b8a46724e70a0707cab975ea06d8944c5f15d6e3d1cc4ef5dcb293933f0c96b1a81eec665328e4067a340efbb4384d676af5ae28eee2e644419b67161698eafbcf3b7861ff445e46ed208c86ba04c4318a1d6923611239f2324b0fa7b2541728985616c30b441fe7e780b9ab3a2456a17ec961029e1b6c0f6ea3a837153620cb8aa5e39c671945119f57220f41cc3090819ce991b9d616060c15620d0a1e0d7faf8704aac11d374ea77ef442a038502383d00135a05965e408de227c8769e1af62e5b8091ccbd4b4fb20fbc1692c94142e593e26269178c178a872b6900f33aa67919e877ffdc1a8ca8c107d61d4f5bfa12b42837cc3c49e81daf340191622895f37f168e1a5c59839868bfc2fad58b96ca4c8f5c83ec5c81439c35f5cb55520928caace7ab4651f1e1106f5524c330effd10e58cbc213ca6f4ce5442bd5e78916124a720578f576253ac0d744e49fb90ebe5d383323cdea8260965df13b425869ab63eccb150725047b16108a714c38727f665cf209d7df0ce22ec24cbbce342cfab8bf26eb7f9c03e96f64aaa6ed3d074887b99a052e5369e5e4eead605d5098589172f12ac1977b0b7ba89fb9cde5c07f17f75695a930b46d76456846060a312e42790f445280f853c8899662d833530207e62bccc497a89706d07b2873c02d308f2a18e311c8c073a2b9f4ee9c649f3c193d81bdccc9b65522e1fe4b98eb6a80b24d6c0ef6124b57c3fbf3aee284492284b4d7110ad46d50f23c6d26350e02b5c58e3c7ef57b23c33a49bd2a76e4006c748551cf96f11219b13c9b55ac82b5be1a362f8fc174bba5132332dc3abec321752829bb678f4a52b2bedd2b386cab6b4bcb83dec907e88413a6488e0bd8b3693d6ce2b6ae386d3dbe09f0db59e744c3aa19bec7479159ddaba75be255a5e8e38da1fcbd8be65fbb393627877d7e382a54be6266f11adbe93bd06a68a8ef33577a3ccac0f2a6a45aced9614b684ed955c2d2188cde2d851905af9e9126dfbd026e5e8925f2480cf36a528f940f42297fe4416368fbe09ca8f83473dd5f724b1d804074cf17a2bce96edc0acc4de717d81cd45a2b7f2de5e65101c32d8f66b13193319e6e90567e4122248da0f1a41f16c16494f63f3d9437a14b2700749b6371d0f31b4eec4200fe6b72caf198ee396fde0e1cd5ca5ea220a2c9a1ac9d77a52402c60bec5601d4ccb1b7a2cb4046f29a7c4876ff5c21cf48443389971d4de74df949f50bf871d2080609d61761966024c99b31c38cdba31d51943180e80fe64ec151dd9174108053716285617a1a090bb3cb1049c4752ecf319072e805b18ae2a44986d36d0de5329808f4e187e25f2715b7fe6165866ca5000480057ba51863c02003d10d58b564c6e1158b68228b225eed16fc15173ea94a250af41c5e11c26848d8d63068775c08ba15d5161e10f4bc2801294e57100b90300dc913d5ff7ecbe6754b606925dfa0bfffe901efe0b771dde3968a54a73931a0ea1ad2203aa6c23d20cf5a2e7cec2d971b7a9fa815ddb220194f4d80240032d676605c00aa68656b09760742c1d0d5ee07dba50c68798955beb4f823e69586503ff9e865af03e536e28605509f006eb0c5d0c820ba204614a113ffdc6da2b41488a1ada1b266c4728ea6c917b3861f7cd6c795a6a2efbd0e607ba2a648d437205d116a48fed9c75ff9c140150aa9530c9860f54493d40f83a809d4a9a124822029408be1e0349992905ee4064b2dbbfbd534aa4c3b1620ebf73f0449fd0d725d8a1450afcc11912f100af89b826c039cef7df1d0b8798f9858b16fa78a91902442898985b69928b05b209424fb7b391113ea9473b72ced6cec5f6ba12375730f11cefb9220b654f4b303e48d07e6b38894d8264fceff5a0c70fb6cfa83e2e00e341a1dda23f86a5f117ab85e7c417bfc111ee4a69b93250dde0075195a4876519f18ec815940e5048a9f16e11cfba918b41326c5ab1172924a41bfe6c4889ff4c549be8bf83945ec5e003724483d05e0ea4bd7921c0a5213a5d1add62c9bd2135bd695aaf191b1c19bc7179be29e6ab4939845a9d8203a4890c42c97d1131c2b182ee775cfbcbf5b3ecb9f842d4e816ff1b938511e74e8e00295c5368484270c32963bed8e9b63198c83bf750fc30129c4ec7454afb809021dd9da6567e41c78c383d3bc1b249813d997658a51760e6a7c84cfbee03e948c87367bb2664320ab3fb265159a03d66041f68f6835d016f2d86a255022763b79b8c97a0008984ce7c52049c8d1ff10aebe950716350d1f68f62e458c0f7dc7b2429db947c27b34f0dbab599ba2d8d5254e131a060041589f01fabcbf0f81686fd178a7c652fa2af9ef661648d588bea0ad17fe9a6a89eddd9d92fc4c673841b0be6979920d9f3e5d2af4ac83be2a1001f3737eeb0b6999454ef1be4e9ff7a4e1cc3828fccff79d6a212967352773ae69a98e17f25d6ff2850a6c49835f41ee732bca501b5327b47a9f7d8ef555f15ab9773ac5904181c26050f7e5eab9505292be22e99fc048503179d22a0d8e839ac79898847d244f777c4cf8ab87a35bdd37ee0e93a4425a94e713a84efdffac8ba721ca98ae7c0d6388a3cc6dd4e4aeae6f098006ea774bf09e407aab68822bcb76ea003d7a2fb72a4070c69ad99af33d115839b00ad7ded0be78d60271bd1420f00b875ce9112da9f676a9a794e31125f14ebd469b0e306c3c4301ce2a16e9a4406cabd71104eae05a2d4db34e1016f91261a441c10f0213aa75a65bc00ece6e00715af7dc097f05c5ca074f128db73ee101bfc657beddddfaa3714c8dc114ed59838a33a479507b044dc5bb7b1f0b41e30de7fd2988cf4fa15a7b3a8c5957cfe9bfbb3f62c298766a215b14b1f9ab4a0d6b835e7ca6b51ef0bc176b0ddcd93ca652ea4676a6c3cd47c2a187dc1469dd32952c2ce3d9850049e8325536a9665d6943fc5c1df21f8f898e37f6ca15e8276c74fa401bda0c8f2201560ce0be7804a129d9f2b463de42565aecaf4b03df9bf6f46627869f405422ed5e1323e4e0b07ae24012fdebd28962ccdbbfdf9c80a9c12360a03be5703b2fca7c5a3a14e6a17adeb3eef0f51a8826ea2199d100678f1124fbd44e18e4276a4db13963f207620609cd73bb42b80809f083d912104770c1ad99ab33f0dfd0488bb2acd0c3a88d940df9e6d067d1d2335ee9ffed5065fb2f1a2de17f8bd1c85bc4b75a4afe6ef13cc8d73d399ab26dfb66a2c56f961bee17044b1703ecb1ac0cbbc6b695dec02dee084d4e92c87ccc1fd04efb52c0e3644afc23fff1d797ee6d0ef978c7db42ff72feca0288a521479e6da98ea6cc6790fcf2744627457bf5bf530b4b46705713590e24d65def1fb514c1e9d76f7c24c430da8ed52882749d2292607b0109756fd4767da7a7f19f1a285ed1b53d386f0bf643d8c2569644c79daa6562426bee82d121412665e6337f823920870de81f0df8812d5133fa4e043931fb1715ada49e672ce6a505837e735c16ce44add7a937075cf87b9c2c28732b915eb27396083e30b979d106c56464ae9a833c384d6c1f8b1dcf9e27d67ed66a2f62ff17c7badbcff6803cdbda11632cb6f5cacc5a5bce322e2b822a0fbc168fb78a3c7936d5efc0e2e719979e01d9556b683bdfc9bcd978e2bf72c0305ef39c3d155d8bfe26a27558e3fb47113dd50b016f00ca3fa2c78f6d9257f7c145310baa3d42681cb694815c19b851ed0e648380697a29614e8dd90b49ae7b2511474c92734f57e59538f6520666abcd702a4fa6ca059f0f835ab7daaf2d76f92e8d8663a69c91bb73ea45d54b88d975095a0d2e4d591033c46e3ef8625b8065c4671dfac5a3c205e0f7da6688614c5c475b3947f1de12cddfac9f67199c1d26d85ebc454323235de11700b9415a77155aea90ef27cb78822922982c35ba6fa1a12a9df704bd7caf0f782d3623bcd333e4cae6c1b3618a2d60790ec81ccb24704ccdc021f05b55dd4ad2fe6c84fa9b95b6dacb59e05066384a20d909f68295033bbbd1269295c7e5777080d4b625d0d107489fdce25870e4eba09b46a2f0064787007f6980d8aef001153ea59f5f6bcfe71914849e5566abcc2bdab499525d886f14a97c4a2cf7bc88353dde20b63fea0835e1812a9f8fbbf842d2a0270797e0d03c37fc199844611c4c28fc85349bdc56d5dfaa006bc4243f1719c4d7af630b08a4a8f66a13190b45e044c1ccd3202c9146c259973c8c8acaca5d6d1992cd3386f6ab5cba673c48d6b2184c156958df2033b5997adca95079c9bd5c736320f8975aad4232f4c092c0068d7987a2e5ec92c48307a1f1b8b48634b7dbd84729b7f728a1da9cc802a72d2458bc944668f2088c3e8929894becbbf34307f30077671d1abbc516f581f93c8c09fa46b4f63477959c24fd3246e39513a2882984fe5655783a80694415a5c0d99e5e9d3bb58fb680921623ad97f442d3bc3c6958075b11d93e4c6a05d7da35a135c32048b8343e807c7a9f97c164f44ed251d0f639355345c2ca1b48028522a9237ecc371a4d927de6bf249d395b7671e277f86612766600c8d0b18ea2d095f7b63a685fad81bac8eadd95508e3bc804088a79dd4ada2aa40e20d2986703f1982be9b2b74d0bce93080e3580d553a3b21a943e0bcf6e105a687eeb39e7494a15eb8617444847754693c863124f82fad47be96305995f46b6b17629fe80330c01e339fc4613dd44dcb5541a517f1503dc68888d84b5daf0d37c4625337c1391f8405476588254ee705e00162570ea3e7839bbc271bb6e6eab828a84cc26ad7e7932d5954462458bc6a65e3819546b14e8a87282907b5be0d33508e00d1071cc25e96f800189d06b52a43e192dd5277061fd1958ebe138d98c3cb13e52c5e025593cd432d1acb8cb89088acf04ef604e2245676feab6f21a1612c73fb7edebc8d6333fed6a2fd2b7d28a84b61413022c36e49378b335d32e310f8e4aa8414165fe2a5aa945785a4b642adf61a3759a6fac6cc5575285a0851cc14bea24eb98cf2e75ba3692084a82fe496aa97aceb258510c0c7f1538768521751226a340086ce5de751f8751976626741238192a6867ff010267225ac1e9c482255fb5d640c1c3afb197965a3d4ffb5d45e3da00cab44a0c65435ff5f63482ba9805ad12e348ac0ad8942d3262e08da0a30100fb96d8660021b7bc4b62d357926c7fe4843de48959192405db05f02e1f61d31b0b1a51b5a984cbd6cdcf1b827c6957b722ec496aa0cc02e047bcb4061c678f2893ba331c8d514ee89359afb21c88d95b245b0b1201e7273fed83a11f4eb2bce54c3496e1523931f359c88340fe1e9ad5956b071e3b9bd0295cbcd8ffbcf6367cfe85397a97253ddc789d77cb05c2143954620cd74f38e95067fe624c4c155e37381b68169ef9603264a287613b4e93f8f29e4e5068ebf5c6980d9a849e53c6290b8fa789e0e5664a8ac3bf505781a0a8584ef9c54520def2564accaa72ad91666463497add7b3b61a7db531df0bc990b8011b0474032eb0efa6cda8589dda28c366d57cc450b6607ff468aa6ba5b4eb40c9c54ee210cfab83a0536720b609537d9a4e0b158b395975af327cfa6991f5dc13972a67d7a53595aed8a12753ebd3fd906f79c782ca802009ec87a754c7a6469907ee496fa96489c2d0ad40c01231e63ead6d3647db0a66aa988c167b3704af18a31a78f27b4f0fff62fcc9ffaf39c77a2c46555f8ec7b048b9bacd0b3fe4c63481c8dac386613b8ccffa084c4214a588d2235fecaeb7fcd904b23794cf7448b600a08913c39809da376898b8e75d2aea81a8be55b1fc9c8cbbd577a9d43ce31680b58574279ac052a98e8fd381a8792c6541d44d14cb4047c2ee79434e1aef64ed72fe238bebf91e5ecac3e2236f6e12b417d0574c64cdd4edb44451ab34bebefa2b13451d86d414f291f0218c983fed7194728f013387f25578684eeb08515aba92131955d615547ca29b2f78e0ca8b0c8c591be1f4d6c11092a57bf5c1cc98512a4266181cb6ccc6407a94f82700b54da2bf49ba19ebd71f886010a097790fc162dfc4897120c7589d4d81c72ada2bfe879a1659f8389ca3a8e9c18957e688ea3b1e4888402ce51741cd70cb34769be989a20119975379d4d1a983a29159ae987a498793502a822ea08e18b0a90729a71f9567001643d10ed3afd5f76f3c69af51f06f0c96b4a744cf46330f291484bb9205e90c0f78b778b5cc0b32ffc6a541d2381d95ba64c8f6adbd80449d851c42607fdfe8e0b37a38c64dfa5f74a759898ded7e141472a80b1e7089e9eb00a2225876dff2274e5a1465cd0967e184c5e56039f533299b4d1509fba96e1f2d939473e761cfca7e1630761fae09b83135843c49dbbef84ba679cf06150fe6e0ca4e853b2bb75ec5f51503d9eee46ed0e8d8cf6b472dbb9034b5e80c627dcaea2b40f404a6db7b8859e170c7856dcb972548c4f74fe8da13e0f6ce30be557aea1ce210788ea6d465f56d6d15bc79dcb4b6231cf8b05de9a6b9e21bbbb4128137ca3317efd92e3403b8988a92940b38eec3116e8d5b0865beeeebbe45709451c4b103b3d2414e17d1c50b3937521a1c871b38b805a7b1d43d95b67001d91127534ece3da48138a8853cae25188d6c08bfb70184bccdc9c44deb9917dc85b7834c431facaff1dad14124e23afc7e6bb4ca81182ad935ff3e926b69aed8dfc9a0fcecf551b6836e1cd7d1cc8eb4e35b28083d390b79364ddc8109da21cf44656120fba81dcaa54a8f7d4494b77856661ca33cd684f2669ac8cd5d7349271e1a88c552e4d589f53a6530035be24a27393433ac4b552be9bc9fc0d6f129d9c6d83317b76247fbd22d7a386dac8662c0d42383572c0210a82e70f659a2e5870a10881a5ac40fc7c6b017738609feaa1ca242aa418e3924b9a2874b5cc94144568bed8281fc1d3e876002679cc5dae2ba923b30ee5ac0925d380c1cfb071a7f642a60915ef3a65410362740265995ec35b563f86b94cb7fcdaca63124542f71a7ea77708fdab08cb1ea1c2691e65f95e2c1807ecdaa6337ebab204ee01da1b340e3807149b987f5edb441e4f8137b98c706fe7436c2bf2ce384e36cdf8f8c7927fc1e9b3693f6723b532cd309832f95faaae99f3f86bba1ee044411ff21f59f39e896911293d18915acbac0d6e90e4dc39970759c42049e1ec97ccb27ff3981a74a5332632ca2af3b6c3340c8d4902be5252292aa5e5c54bd3d4477e7ce64c3dac1b9621c6bea5fb449ff8f4ce39c8176b8f83e0472422c8abae10afba4969821e339ec085faea29c91a8cc591959ac11151ed8ec248ddc018d1e0ad5a2daea4b61308a7982bd8d0b4ac0116c382ea599f0ad9b145ec64fd0f0cd5c9166057539dc176b48d1446a3ea725e990d5440aec4426c0f8d994c7dbff3f40dc9795a201fc2c576f1b07073a56367e5baa1b02f07d962a8188aafbe10e170f67f281752245cb9b545b1123a1b9418028936109d6711901a2848d91e6e6735067ddebb2a961822ea2c84a97e84778b76425aa509f2459c5672b030458ebdc5f6ce3a58436c5721d37722744b05cf2f088eaa581dbe35508101089e03a0589f91dcf1d4c055f3d81e6987bc01cf2406773acc0c0c429b0b1a1d678e896512c360a9119126defcbc3f9a8b91873258197d298904be4f76ad4357d0d0f9dd6ac115b4cdf620da192740286d90e96f7ce808f172277d1393a374131b7c57b239dd3e31c9baf4abc79970eb4c351711adedaf3f54a0d883dc704560fefaed97c27dc567bef8066c5fe22ff26d96658f2e53619c59e3798b2a1ae7f961104a394a2731fd0e7da7d413abd99c1be17b9b85fe17047b1636e6d8eabdf094cba95d903298b369abafa870bc4e8859eff712cea9933299bbb8bc85103108983bf8f0b12e881eb3f527f4f55f81751c2bb380c1642be1164f72b31fada3a95cb6cd06cc488cb41ca3889b5974a39c7e8c245609ebd1b32b04c682b839e2aea4bb7ff44b9c8de3d6dab8582b45004cec9dc174977e21c1da676bc594aa2ef6978e342c4969e197710464bd1e889752a6afec281325a7d1ca557779577c7bc10f1374269cb720bc5325d93f9c758f56f7174d3ed24a824fe87783bd58d868e7ffa59e5f0797f12feb8eb0ac4f352a08575924f920a5ea4994cacb72107a9f5e18e1067d78336538aaf138c0329c0684f44ed25af8bbae7db712829441b4c8c86c69bade07b1e9f229d941b7cb6d01f7a218775ed8cc67cb1064f03cb630976c9c5a155a60f09b1af3f9cd519bda7022e2a9eaad60591c020c165d0e99b82948737ca2bb58c65b06e52687db002aacf2fed9f3b26b7b0510dd13e43f948c37a62b1145e84a687c20bf1f029693eac704fd42dda7c2e3ce3dbb4d6f7494020cd99b20cb63ff21137db20f89a228245b388fd3f7eb8ddfb57ee46d566fad8f2678056e924d767290189c56f1b03305a2053a2b51652fc35830d98df9e1195db348654bebac0f2ae72782a8b1f351be2d7b66115954a0ba12a1bcba75fca0879d58b70a912e56057a10503dcd792279fc3b75ddc04c796f429cb4f3a6183edf7ca3caf44542465c55667c4086231aa04c52b8373c0315146dc4c0af57bc4ab28579bcc81b19e7632a163825cbdbd98bce9fff4fd5f4c7819c2fc5e41c1768ba40f026321a4516305b0efb0672016b0791bb270aa69a0734d2af54ab2fa034d7a368dc3cc101b1fee36bb56d4f4f2f7c876ca45b4df5638b7decc6b70a22ade82180d00e9d104a6b516b2b2c5c02481ec23c04e4fdb691a28025d596475d20d6a0e3d6e16f0510c945feff330891927ad521c4d38c8ff0a5e78cc1d5331f526ec7ed5593a5f928e788d2cf8a44b06f02edb73e5e781d2df8b01e6491abf38f1bfc729741ba5144c9676144055ecf3f7c3eca699c76661a166483c6604acb692c99c09ecc1b2f71915e2941adde1e0fb44e08dc6ff6fdaa20bbd3364617b805ace61c8ba9d2c770d0f313d1d45807e6764a23a2554f2b11ff2d4c4aa6dc96982bceed283d321d5718aafe5be69bebf225561e3e7c691dad9ac830f6fc4433efe059056e45b20d6f1573e48e476823b05ca87a0e0958b0d5d23b0352e4d4c758ee10435eedc67ee576cfe8602d946f240c08f455040ac7efc3592052a34a63dae9ca47060d8ca811785eb526cefe0ce51311c185fe91f289564eac413aef36511d7140143308f06c800154aa4bb491a8ba9e55f8ee7cb42a1aac4450bb70f143f9a5a6050bf5372209d97b932db794524a2903870c110c120c39b4ec0fe1b05d7bc6f5e4b0b7d75ab7161ceeb71f326c99ddb5bae2a05d0ec10445298c1fb01186d2d0de620b4eb6760d73b18361c71b72225e0ddfa20b391e399963934080cc8fda1e649c17ac0632bffa1a2e3b06c80fb9dc39ecc51521cbbdc59aae0b72ba3d0d5e8c86c32e831793e13bdf389bbaed725edf24d7c26397e392e3e6aa7054b6793a2373b7431c9559657e77e83ab9cd115110dbdee62ea801950db3a30bce08da6c3899b22dc7f94c57ea673b7533683b75cebb4f795a97b3c1de03ee782cd8ce6ff80d3ab6f31e70931cd724d3146f0eb06b1e405f37d05704361fd4c868f595d21cf3a355eed0fc8ec8b7e83a99df0725734c94462b916377821c39e4983826fa8ac0371fb7b1397d043c8d24db3cf515be6d5dce0a309d027a1620b38227b7d605b1b7d1ac20f636b7d138c868ee2748c683dd323f0af35830d823f008e8d8f6469311087b0f18b3831819dce5d8e8d55459964dea1d93b5b1b13f34281e3589b2e93b20fa8a4a46311e1189b1e596db0890be4362a873426f93b21cd374857768b3315dd4c9a69f7788beb8a11b6ea81b62c36f78ec7688fc0197dd4e037ec365b7c3803f407337781c144a43bf492ae50d9b1be2e8c83c3bb7e13cb013391ddaf4dc12fae280e865f7c2dc1c0a4be490e38036e7b3e94bfaa43ccee79eb53364c8236883c7daa9a18647703b6db1b39afb999fb59aa35244b6d65ed2cd5dc6146a6c05fba98154ac9947b6fd0a41681d327edc391f0e86ba57487da39cf53a30772a5294cd6d7406e84ee9186bb8e3cc9fe95a41873d9ccf7471db89e37ce8b99f8ee30ef322b8c999bacf74b1707aeec7c6c5bb431e2b5fee7cce63657d9d6cab6f911c99b3d11c95f96d55b20f1d535e8d3556c7f9bde8b0eed7b715ae7aa1dcf12208f32268e7d7820eb9ddfde5857577df86ccc7745e838e1139ec43bc9dc76e473e36c377746ce73e1038cfce25ccf381c079887cde7642220881c76e06ed75939d9079221fe2c9d7e07de75d063620b7bd2ac57129eee31ebbd4e374ad18cd8f0ac940aec949def19bdf21fa829dc2b40e2a499e3be49ab8a67813374765ba3a1de6d0b251cf66d05c981fadef66386ddcc166386b47d270f908e20ea673d6ce3cec30cd23030eddf12248e4c60bf1de2b2fec86363d04bc9804857cd34e1c0d5e0465f022383bab81d4af783562407b3dcbef2d07a6ed5ed0be725453cbe96bcb3b24884c1982840c5394cc8f2ab1a12ba30625d31596315d55a782981f0db26109912ea9866ec8eba9100d4ba62b14922169ba42a19d5f9d0242294d5728047bd5a920ae0986d37354809c9eabf2e3f4dc1c2ff8b4f0c302908f206e4edf3199ae9084ab70fa8e89e90a4738014ec3d6534c9c4c5798c2534ccc8f16e53c71014a02a280a7ef8c56387d27c5e6f41dd2ebf49d18ddd27485351fc0e93b35a62b14c0799cbe6342e1f41d1b34a7ef9af6e93b2a38a7efaa20e0f4dd1c07f049fda080ba20b8d313fe9d02e001189a7162c2e98ed3a39e4c57e872fa727a5494e90a57a7ae6fa706b83dedf17b5a00d4d274851e4a8de90a4b40314d57c842b11113aba0034e8f6a6a69b90faf050afce5ad2081775e2a02bfdee619c91e701626408485a7406485ab40c4070c44801049b1a04320f74144052229bc2640e4379e916c0b5180051b5638016c68b57ee8d0c75978e1a665830dadff10f9d0210132203a7ce12d6d04aba0c31626a20201ee83880f1f3a6ce137447cdcfc87e8051d0a11b90a36b4883c051b5a29fc8788003af4f11f2de8f0e62f9c8509acf0970d36bc5ab081051b5a60e13f442be850c886bf2660c3045420400b87818503b94d912134a1cd07a08de0213f4439435c18925a61888d0e73fe1a42e342aac8906709d8d4a07f88c2019c873682c3d45140e1751b30f3380ada48ce35fc87e8a5c3013c6b23d92b27e028682338478728e021e000fe1af27ae97085e721affc1fa204e85068c8c11a5018721a6d24a340f37a0256d0613e789b223c743880bb5043ea9d36826be0d1ad50834d0d2bd8fc8768003a14aae13c8aa46a785764003c56788ecd5d38cabb32e81fa23086d0847fda089621f51fa2cde1e8f0a2ba4f06137418e4296d24cb60020e0a029d0ce72280a241ff10853b0c00fe10a0c3ee286d843b00f7692339003afc3e1380ff10753a3c4016c367b4111c4487335806041ce09d0c5da7c3d439193aee3f4431e850488623808619196e823692674cf80fd10174d81d01291d723fc05110d8c7a1e1c334e06c4fd180a22185fa0fd1d6a1100dc781c047c30300812f00ff21da7498fad621ea38b737c062b4118c63d0f6c2b6ab00ad8d64d80262d8b491ecc25e3d23d9167a80ddd13f446190f097d146b096b1ab5af575a82fa38de49d5f1dbe640af80a16f305682318b67af985dd5b61b7fe8748013a14825d662706f6d58e4ccc7f885e7478ff52bfbad546b22d74834b10bc857634de8961c75d76361dbadc6a23dcd6487e88b61fa2203a14da790c37681d0a011ddcf9b591bc85800edea091fc10e9ff8768870eb7ef70d1a1bdcb71280c407ebc90e34202c08d838003b4e0b9ce826780fbf07afcc62bc057f05cb7f10cf097d7e3d92bc0539eeb28cf00efbc1ee7bc027cf35c1a55c5001a35c7fc74caa7003a6583b773221eec35783b1fe2c14e83b7a3533278309d52c123e104f04678cb633d050fe603f06a78780290a0038e82c73a8d07f3cf3b21001e0026e880cf78ac9be0c15c7bdebd1262147480fe212241a796cc8f8ea05348cc8f5ec6636921d8633c182d047410a6532dde69afbc6bc60e6050d92f5e1606500da6d82e1e3562072420ec1dde4dc245930e5a34aa89c573216e202a2f03ddb77acffd98bb7bd521c680e4800e9bc6eeaedff538b4eab0b56c6bc771a18e7b207157da059175a09aa60b55e59e6ea74ffd4c1777fa14502a8854d074a54e9f52925a425f114c31d95c1b917b237e71c422c46e87d82189dd0ff1a3cf5e0782f8d126a6316ea03473b525f20c1e5785d2d0eb789d10af036280d72da134f40df03a265dd1fc1ae0551f1f90015e04c3288d201f508837411d2f82337817044cb82696cf1de29ab61dc79832c70e2f141e5f500ebf4d6fd11d9a1fbd4e64f02218f3461c038da65d7bbcc55241fe0eb9a64d3f061a4f76d561e7c302d76433824b4f90f942161ba5dc1206d8a27d2cea00098cb57610471168354bbe7ec0a8088c4924557ca1041ec92800c1184d13a0d54452c6b045fa8ab9e5d26402a095237247841d4c7246459503365c56902d0f56964883064928bd5091e41247c63b1e2581d4032b69bdf4d24deb2fbef44e2ece8499ad3e64640ab3b5e56a87b86e7aea72ac662fe564ec969f91c9f6acd1a2eab7457b7ab26d71bac2f9bce79c7335a79e13cb6c5e6a6bb574cee97d639c73a439c6d58ed4beeaa596f411539af8ea6539e7ac73a26ee04d5a25a6f5d5ee3a6b2837bbc3cbd4b3a80e4af865d58dad4a3a677745940e8b2c1f723b464a07a54eaed5e25a2a287542a9936bb5b8960a5beba04d68b5b662612b9dc2de26376b92615bb1b0d54e816d9563b3d6059cacb684be2fc374e633caacbe5612a7b4c43403c46e203159642feb843a294ef6e2acc93eb1aab8aaf64cda5b2a4e5796edf888e5331a5bbe455e66bae8eb726ef9968d115aec301af94849da724a0f2062b083219440630b16d0263b8c4c4c76101522c050fa84124806c9252590c17652a43d9450a26c19bbd8810c1bbc21842796d0823eb143897404133b94493f524ed9524a2679d9445f2c5fe040a9088d2b7a70833ab14359e50820489f9f2d653883b69c4bb64462cb4f26f2319c434908118300c3f964cb28f447ca87538c2d393276d8b25370ec54173bb503d04e21a1c54e1dd5e5a450efba1c546dc1ee8e18daddb92ea7e3be75395cdd96f6f65397b3695dce4997808aad1d77399a0a3533628c50dbf751c6576dc10f3c18818f0f7855bb4e578cc19235b67d7dd5e348bb9c1aa5ec4a8f9618b12909a46ceaa23d24ed3965d24ec94d4926c193d6bdda85e99236f4d58384174b548e7e40c6133b002f1ddad70629d81a8f2dcfe35108fb00bb0649294b55a68f8f8f4f121c6d66a1882b76a50142fecc7754c4927d2f0bfb3edefb7cd318c2be2000af920faeb86d9d2e9a5d83b0eb2a538fc324c821ce54905b9936022158ea1a48778ee0042e93561cf19249137776269326ee10e7115c91d7681a81173f7e50340232647ef88069ae92303af120001e66a6f15819226a31e3270a951f2e569afcc000889fa5244ab079b47a785249b0b1e6efe3d4ac9d49e5e88c17d401d2efd8d7efd05f1de349128589221f90be6a1e22d8a4727446920f48356b5acd9a5ac73ecaafe5c5246509244f9822bf6f4e99064b939ced78a4648b1d3e4ad6763c224249cb0fb2ddf1480914254522302a23524a29b691c618a33743395f40e5035f39114c45c412823acb61a8b3a0a0c0504b3485a2d243948929a44b38cd4304ebce0df1749a05cba9739ab5939f7ad63122960e77064490d33bb74a113e482209241f1f9022511afa18d004bb1fe19ed2aced28cdd2491df5088614caa6efd146a6345489d250fa1e6fe408d22849aa18630c353acd73c467fba6593adcb777470108f98280c9a63ba44c7788d2d0a3bc5b4469e859442cdda11a64b1c3dbb4299de32ed12ada1239a455367de755ce434adaf428b8917d6a100fa41c41b06b229a41165a04f9f880118c60587db2969e3a5d88e69c53ca39e79c72ce2f64cd1e75d8d272ea38f3a4618c57ab5af1950ae8d9566ba0ee25b6cd815a6b95b156b963144196e78935b1585384494709a7356daa9552ea30bff8fca29fafb54eefc89c19508cb1d66a6b7d0844bc3db5d1fbfc6296d57a6f5edde3f8d2bc3855b0c548638c3ab416676a5e2bd26cb3365545ac345315b0e0849625f9ee78b484156864d4908b144c82586204494b80e02703ad24b120458212d215d429c961dd335e460439c43922a952cf5be4224ae5a534b6e96c5a9cdebe63bdaa05b02aac56bbd2d41935567babdd191713af529271cb068525aa2572580380067dc98739d3ad7557323e3899c27ca8fddb31cf6c5f8fd3bcbb92a295ca5c5b338f66ded46e3d214d6f199709594f08eb150138e923446154d813e38d005a4a5fd2915636f4d3b8dc72bad7ab736ba72f2bb592bebcd2628d4b97535b3a05f4ecebc97dd230cd108aa629e68cd4e75991b9137214dc6966db3639abbd274fd3b4a8a1c29e5d594c403a129d2bca43531daeba9cfa22a596a7b5ca6dc7a79410440eab4b094ca80fbc9060021939c42b560f60646258ac18a4950e725865b8158cb0fabfafd5b2b18924ac4102ce79b5fabf2f9e3341092e55b494ef58c271e4107b5c955465b3fc0e6fcf11b67c48b373bc917b3e55460e2b4b2e2387d5042ec69b952de3c34ce746e566cb27d39ab1e161d423cf208735001c9698be726c92e79d3545f393fb624e78264f9ae7963fd19598f97dad968dcd33aba960e4fde52ad2448931e52a5735a38ce7b765b7936748b9748bd828a5b4de4929cd42d639e78cb5524aafad73ce796dcd26a514c79a38e79c73ca39e99c73ce39796473d239e7d4e19c7386dc9cf345c976d2b693f67b6b566dbdb6ab029fb478d2a2adb7765784f9de7b354c2dbd9452ca5d31717705c622534aa9ad2e7b4a676282b8b65a7b0e5839a3a434d52464c9ed6d9aadba27f86bd91c739a0a466ad4564a5fa9b7edbfd6ea9eb85389ebbdaf77db8d9b188ccc7539f576d36f14756d364f49e8a528da714d3aee0474c31025264c9830c937ab28d7843b4541b52658b5622d6e72ef856185d2dc84a585b6719bb050da429be036585a5caeb6e113c59b76ab772f8d8c8ca43c5549519035d9915340ab76da50a9959755dd4e43dba905881b58ba214a4c983061a2ca2b312baa18c3aaa7a1532eaaa9a18e43b164d2c8f2dcd049db3699982e67b58d4082fc22d7b764adcba9d2c80d122e7f617654b56a17d1c8f2131bc5f81849242d04da5009272d17a12eed295dd5de0c6b432d2836996402d3e93c89e4e5e890f0c30d4394983061c2244529a59716017ad09e3baf628f560b87d2cce3ce060a05cc0f88cfcd513ebe8ad0532a6ff77db3d24db55ad13967e6f7ce49963468b3c8a42d3b9ab48dc2c8f2f393a767d9e10a63669c37dbe33f1ead93a441f338cb20a3d3e7c948bb78d3f34a23294ab2ae73d282afcdea924a490a895150c52231650824a0bd8eb5d65e69060a90b0d65a0b0024bab8a20a1b2c514114501891553bc6ae635c6badb5d65a6badb5f6deba7282284a2718a226c7fa404ed905d8d65a6badb5918e2648daf8400c88c00515d0126d5b031c6c6badb59609945d53701a0137c4a2c9c1b469c182e7083a8d913322246936c0b7084cb0123b580952a24a07431c4c4c909c60906388c91029188800c4c4042a284ca2d0609843e9598d1d497ea02223b3ec78f4e3460990209123d71d8f908c800a238640c2640588bced7884440866c72320137491fa316b3cd5146766def558f572d7b3aa6e6121913f1f62231c38e184500f28903003a8470f29847a40e104126600f5e82185192d49fb7e8b5bb6c45e7b56cf82d1af7c45c7a8514cf6e00a140c01c68ea842a00370e547301d207d0f583d16ac561d8b31e8028c1d9148e08a8e1db120254abd07e48672289b26877a54592fcebc751c956d44d9146fec65934a37713159c60c42f005183bc2c9810270e54726157580f4d58bf5f8016347e4137045131d995d805413a526672d376746717606eeacf9b83b2fdcce9a3a03f39dc621e4be4def47dc59f5e9793de0e8bcb04897bdf338603747e340da5dfd4169cf1dc364d4d4e99026d5eeacfb981ddc967b1f5ff431d2a3f8a29a529934f757c74913d239c2d857ff9051ab8ec91a1401083d80b1232b239002d21f21610ab07ee53d20ab45c7a2176280b1239209481feb61829528759a340d70cfe251244a73bfe251a3a11c7e734f3da4464d4dcf9d359a06b8f7e2eff785b2b3a66d449afbab19d117eca658738f3339a25cff2de3ea0ebf237dc5640ba688a3098c1de9886803a43f328fce006b4c004e80b1233208a49a48fec8fc01ab264a3d5c5d2bc9216da2b234bfcba4e9f7435ebacf4d4d6d441ac3fac3be75877defa911cd3ac41645e7b867698a37ae7d4f9be2cdddf794ca745599aeed281dae94581de620c2fa3303eaac20a9eda9c72dbb1950e73e531e459ab469df9bca997a85f22895f9dd771ead527fbc1a34bf7bda34bf4be7a8d8ab41ccef569ff9ddec52a4fb8f4a4b123761923861468f96136648b14550c564dbac65468b6c59989fbd2c41b6e80be39cbf574264fb1be62b46165a04883775bbfd8a4a6423aa11cb88625cbd5dbd61bce999e95ac03dbe8c0cc6186b322bed61cbb65c0433fde9dbcc0ff3beab7defbdca93992eaa17703ae5fe7ddbe67d333bc8dbb167b9eb61dca1eca643ecd91d1609bf25f5b20c20a08e3aeae0b6ca454dcbfca0c775afa62bbbbdcc7cb930b5f82240a4b1ad58636f6570ae2ae80359b544a5647ef3a12a88c9696e5138e184134e0001cd843469dbfb45d624ddd9bf77ea65956e875e3685bf176fe6185b03736b60eef0b28d58636553acb1d488f544a64854cafca85190f94c53c1a0fccc2faee667edf7034d0a5242e507579346229b11f3d2fc6466d2598df9c97f404b91d2951059fac49b1e5bc36ca9da52cb277061294a4129d0420b179c30c70d9c40a1f73828def4d8516cbc89bb7e55c6b6624c19b47a622313db7eabc0fc2c8c96f0812c81be2ea8ce74b1f0d0d20ee5d0d2e6804c57d52cd8c477c7316e60c4a64be48f8c4c2dc62273c0d3a1ea23b2e6ad64e6671fb383fc31d218c2aefad7a4c8d98c1379ce38914f5204b1c63ea45b461f928898827d7cb5f75e90c3af3e9399963f3e648c73fe96cccf5a8c85bd5acaa0a6931a4aa8fce0aa816b265c196d7b16d561d173efcea25ac804b99346c20c7a8396e8ab647ef61f9096539e6db24c7689d254a13a88afaec69b1a0474e5c38ccab6d90fb6fd0da2af4e674b335bdaa91dde205b6589be6c1c172808dbeec069ab4469ec0ddaf6d88c1cb77da6c674cddb674cd325b3259a31a991ebb3a56db31bd8bf2cc59b1edb3e5b8a37338e6d7598dbd856676bac8c92f430430a279cf87c6009daf434ec81c39995cc2c9a34f4f5519ad8eaf1f1f88ccc5e0991578ae28d0b6956115fa7d3cfa2785337fd7c126fe65bf8b361cbdc62d317a1af939e45995eb23a4c7940620d0c9166ae00069bd28fd2745bdb41c635984629c8f49b3ced30e3192df2dc61deb148cc54b02bd838618e1cc6258c8b9ecc2f8827180b28d355f4aa671118399c45bb882508c7d1b4e7b16542e354c1aca002c68e474aa4ec6d729a874cbfcd4833cda2f530ed208b9ee774aa59550bc9ae1d965d3b3d0f113d4f76ed3c4452c3a60e73a7c3dc998e94066b2094663e467de8c1174f10c009987dab7a882c97d4ccd811b9821cf0d004b43f22c330020c25c0fbcc8b1d69610ad06a22edc311167e005e4d44bd2a2d254872c97445f047bc89123f82f33632bbfdce3d96996649693db9846a890115c0218026b7122207a982e28d0a72e87b087ddddb53cd611264fd93431974af7bc8a10ca23268822c1009d6acaa33b8d22c7abf639fb1c09dab5954eb64bf3163e4ef201e3268caa0e9139bdffc0953721895649052139d5b1b5b9c094748a24186c74b4e6639ecdb82430e2d7b7be0081e8ecc6a63e156381597398b7a76fbec282f6e9754f6d89d5028ee855b71305c0c979d1503b37a4175f728ef749a718f9de54ef6845b2e5f8f166ff3c0995be5897db0c599707bc2c98993f166c3b8dee26a7fab6669afef01bbbfb034987dd53122ed31ab61d6de0dc88d3a6d3fe1edf4f9e17f52f2c478dbb64d6e72db30ce7bdb62a7618e8d1c62b9c41eaf74271de88bb51de611c4aae34db384dc0ba375a8bf0f5b7b7b954b5629bd697caa85ec75c0cfba4a14d95d814738c618638c639350cca9be1cebb0b557eef2ed14e6efd349f0581e8ca7f224f8e2b1b4eab1b4d5ea3b2fb79ac7fee52bfb97f3ac46f058da598fa08cb73acc77568761c168b9b4023ffac2196f32ca749d8e776c2d1bcb96dae2cabb6fdd71b752372f8756776c6bc5bbe3acc812ca746110db5babc69406e32ec51de31fe30bb4f2379df258dae54e7df5c7fa97efd8af34cfbdfd8b3d4ff6964db5727ab52cbdd22414fac238eb70b57d07de70e8e675b9cb5ef7d4b6fd7482b1f565b59dde1dc65b6d7fd95eeda65af1b89fbcb8555cf7ad3b3d76dac96a96e3668cc835e39da21d4a67e087dccf400e4bc8cbed612fb79ad5c15667759a25c4be7ec7d6c31c46f35cce1382798c17411c6f249458838ff14f5f305a26512dbe241691061f67bcb114637ef8db92f9612618e39fbcd8ea4536a566cc11dcb9d4b329436a5cee334664e943ca7cebf7362c4cd7e9abbffca652de4a04a38eadfa8a3777ca8bbb087dc15c3e05e3e948ed8766450eafdd6e6b6d95c6413b0af54c872d56ea727797790461ee923a4ba5594262cefa0ecc65344f3dcc599a8708560f731efb984730e62dcff20a0b095acbe8486956c2550f38f2c53967dfd92f8b0ebf1d5e7ba769cfbcb0b5b3abbcb0b547782acc3bf570b5530fbf9d7a4ce95075ed2378321ecb8b9426c68b14c65bb9ec5e503de3af78dc555edcd9a35a967aecb2149771dc37c9a13cbc3b4edb782d16e677bff2fee2693918d71b9354132b6df81bc6da65e6873fbb1f9ac6dfb8fbc1cd8fe658838f7fc0c41a5cadb5d3da1fa76b5dce067260620ddeb458831fbb0dbcd06d4daf620dfe0bdd3ee9186bf071266ecad9392e08ad168e38e2d8e91c676e48509a6609b1efbe539f9a31225b94a74369e43b25ac718849756c51245747e8e4316df1b215f9f9d8885cc28ec79ba5c343049bcfceb3615b144bb8a062e403f2cc67c7dfa1c77a673ed3172241a32a30ce79b5aa95525ae99c73ceef8bc1a1be95807c5f7fffecdb96e43e6e47c2bd6be1486b1893c20ec86c760ba0d78e3d5ac7ae27cd6209e9be1d863af70e094a9f3a207bb6e65dea619cf36af5e7d0baa735f2bdfd762434d339b4f68db4a20eeb8eda346c8b71faba07d4a666a43a1296af7c38c8186356107b7cac75989ffca3e41d6739102424a41d7f391296bbecd02cfb1d2f9885e53b0e63f90e1616cce2a2691eb69aa6c9586c2fd4e4b3f58e474262bc316567cfb4a05db3e39190127bbb9cf5ce460e231290eaf21a9be666b5dfef783dbefc86bd93f693372313ce0eed73686d7ca9733a7539d9678cc85609d4919df61d2c1ecb57dfd9f116cde3f21d5f691e2298cb779ce7c57a3da8e41c5a5bb377f1fe61fc0db95e0576b0785817995fbde2d4bd20374fac61697f790459eef29d1d7fd13c31df719798efd018e62c3aebb4d4cb4cd7b597f12ed0da38dc638c31fe36feca7bf15cbc486950dd498231301e520f38ac02a60b5fd3e16a656f5b382f87d67dec328b35966f6bbf5f79f1c525df2e67bbec5ec03f1d87e2cc2d87d6cebe5d4fd370fd9c19ceb410cb414c5f40f046c22c48f886f9d57f2d1e482baa6ee61434c59b1636bd5c42a9dd743b459d461b269b8a41b9192332093b3e4ae51e05034d74c688fcdde56080729d4d4bc3bfa659423a4ef3f09cdee96fcb779a673ba70f4aab8ba42c405fdc51dfe9baed9d66559ed3855011b4280fe79831d2d062d7a69a24870fbfcd2a52012b9a6e80831d4aab25c9d55bcd4f665552b68320766bc723276af00412dbb5e391134cec2df549c9b3b5c413a5174572686daa435fd16a17e6579574221029bbd6ab2ad3526592c41d65a9544692cf4a881ce34d0bfba543e552bc61d9f59289beb24f265f52cc3c0c509a7a9928f95072287d92383742bcc4c4fceaa120ca614c1223e367118c01c874492f76bd6609d138cd93fd94fda45bf81ad36a69db83a194354530aa6caba554b1efd9364aa42d94c9252a3e12e8bb22cf87d2c78a8dfb5890b94d87e9d2011f676e8f92b59f5e04e3a91d7524a76f2c8bb239694dc74efaf25b2cded8673c9818d8610ead4d23d22b82f2e3d820cab1e7d6e029426924132b9b70f060d74cb3849cbe7d473bd63c3c44307c4d674a53cfa3fda4c1cbb45ada160ea56d8f9bb69d7054d956d7a3a1327601763c1a62b2b7c9e11732a62d849fe9ab08a5a9c7b5e6645610f94b224b9f6c28c3dae5d6885bce1923f2cc0ef18ed9f177322d8fbfb3e92254f324b84dce8652dce29872d8dab54531ce996a393cb146e26787591d7eb0abdfc596e6b43d6c78baeeb5624da59f3aac74ce1974174e5f276da339ae705c00325df7b10663fb4883bfe122274ff35c9818037b7eb38746c76a45dfd8363931c0011d62f1863e9e27ded89fbae3d057ea3af145628c2bee8c2c1fe299854cb04569e661a864f6762fd04d750db23c8be74274a2f27a641b25e5cd44fbda43019bb6d0991b36fd677338e59d84a78d6325a51447a44e77b5ca811715479bc53c14c50b7a9086102fe062082dd8bc18a1b529c1b192b2e2f8c428ebe20d22322d6c59b17481448417488ab0c47434c6145ddc271f483d09c129ba01041c3c247942e40229a4203113b36663b6a298406e4aa58e04c24a663c7a58e3881f274bd288821e6dc1841aa81e12341182cf162150430a272c68c110906454f04043450a55040d2690fc6007212884a05c34e1a6b80235451725e4e0988a2c642a8e598341c50c3a3732ad1f5035e9ac5849398511570a106040a748819502031b6cd9144a644f9cb62886085200440c56529600067514914419674801c2480a34589aa418424b06c614495059b66a020e4bc646f7dcd793f193d6a37b9b9c95915294a572f6b0b160d851c7b027457db04216a4c87bef8db78935f6bd6f99f7de7bafcb947cdaf1a889346c1336d8ab26a4c881093d940106164c00c1861b2b68c2091c65064df490adb5d65a6baddde10422f0c1a20e2abe58022d55c1b674b8f0b67aa6b239e7c4d16a3cf389e2e0b10a183e289002b40514556c31843a9a14418409b070324494386cca8a3c310f5bd42aebbf5a817099808a2806136104d524a21941ec1084358278d04393163d4ca2a4800a23aee0428930b260c2c90f41960e2e9ae8411319654ca1582001616903e3891a355ec0600635cb3b1ea580083e47f2430f2728aa420935a09830458e347c08420b4a80744513d95be6b7aa7a95c32c335d71cfaf665e5128b12c5ca0060e887882043bb06249b7f1fc6617b3da50da53c41155dcb0819212440455717b00c5142558430a326a409fd43da38fcac3a67416f5ece0032150e9e28a376c3044c5ae6520595a2282133f208132851c4a2a1213f4109186cf075870832448554891ca01164080220437ea78428bde403277987b4bc55a755ca869ccc1831b4cf1220643b000ac51ecfad77ff52d1eec2a04586badf566c7e8e3846453399348614c639c31c618a31230c6c7a8b100f65c22ca9e938629cb17618b72053926c121c674c598f406129bfe164d574c8263e846b94f361090c87c3615823a7756fdf6ae3b77d4d67573ca773a16ebd10169880594802031452518f74e75ee56c3622cefded3758ff3dc77e43bcdd35d5eb32a0fab82369905c78860a9ab746c4569282c3fa5635fb6c11a7ff311e438eedd77b8779a8708c6f2ee3caa73dfe958de3d82a10d91fc148bc7b22aef761e3ee7652b12ca09480e2d813204745a72872e94bbe25da3958772c9cbea31ef01611ec1eca184a25d3e4604ebae7a8c084604c3e71e290d8ce59a8e492298ea2c3a2695381d93489a43e2943ac9f25056b950bcc9aa7a07a559f53de089b5b35deafc64c7ef01b52f9de1840a1c4c7c7c40d45b4e045bf9f66d3beab0eda821d8f6161d9b407a0e2dd91e4ea06d88023155a1404cf430de85426968bd1cd3acd23d82dd430ae4f2b9f218116cc7372004802d30d45d74cce5a8afe818116ce5281d73d17345293677e81e24d8a291548fa0eae184a2d22cfb1e70355934cb6a9d9f1ef0425162ed4870bb04b7b3042f160e220228272d92b4644142b0a469a1c40817096b1125db204300655a88f1128488242d7290a0202d8420130404485186c8740c4551424547d26a0545979963f5e24392225a90554ca490c22509172b51248101193c602923091c4b0481442584ecb2e351104a76fc04f1c41a416471c28e474128b5b1cd4cd79430cc3d5da747ceca8774f79029d8c7c7160b93c69e02a0460e31ce5cd11ed2c70a31057b4d87323bb4d161cbbe3adef8883536ecb1eda7b6d166e44bef9557d28839e963832450e62187b926fad08929cccf31f63c8f7fc660cf8729ec19cebcb0d68933c968b35d4e46b33a84d22c26654372ce79c8fc7492e88758099315365d6134da436ef83192524a5cc55da2d6e3d7c5d9c6817e94c6f6a8ad4a29b5b8041eb27c95f79115e4844d2f773864c77f404e2c69b5f6669c7c327db06199654a69b578ba22a594564ae9945d1555509b29d572d1c665181765455c87ca302eca8a50a90ce3a2ac28956f0a955516d5a9563cb0edae2b2c2d3b328c81f8e5b62e88110d06bc71d8a1715bd6c4cdb2286e1437cba2b851dc2c8be24671efcd6cfcece365ad37cb8068acbd34b2e9e51653d301526448acb8f57d383636178a09c5bd37b3b16e59773c712b0c501a0b501a127e608a1506bc4f9a8f9d63b5c30757b8e08a26427045112c43c8da8e475780e08c2b3eb082841575b0c08a2a4c488c333e6eed6905d30eb2c78814c84147113f58810ab6884540e389105215ad20c1aecf5d4ec54033ce40c91060cadbb51ec3510512bb1e9595745dceadf51c0dea182e3b94d9968a216ccbc5b6f6f909946dbfaaa2876dbffd45945c9044173bf8f1620a174c99637b1417044c40094e50be0895b74004c38f8a2976ad3fbdd1ea61430510dfb6d7b00a8e88e0d8828b25592c118389335a72ee9ce28c14767d7677b5f5d65a6b6dc114444bd041833ae87002ac61ec5a5776adb5d65ac60eb9996d371ddbd2601f4521832227b63d2aaa63c7232964b0ed14466cdbba3d5414418e39866882031f4c0163dbff8b268a60494d91c3968dbc13caaeafa732495690851b499688d2066891c640a349d56a1d0a11002036ed7882573b48a23252439228072b32e21c20519a8889deb831a8014444841870b004850f5c0c39685a8960a5c960b58374f1e9210c97255966c7a31ed858d1417e0142810f4ad4610592bcdaf1c8873058a2c82d3b1ef990839716e41d3b1ef93084972af2ca8e474041b4acbc1d8f8058f245d0be66c4d75545f1e600fbca36f6956bec7b6ff79b9dfe6ebf9749f475fabd54fafd2a67bd6511c639cfede4690bd8dae9254e4b1f4a73e9fdf66deb59c0fb368d34f7276f8b34f7d8638935f7d23361671e0a9b7a1a907bca145a26cd95292a32bffb1298c8f6f5614c7a325d4118df7bef755c98df3d4ee68120cb227ab3383f7a5914c6a538868f2c8a474eca8832e55e23eee37cdd6b389341452a305dd40b4af345a62b411a10523d8151fccc27470e4bd8f3466e99e1446bbd6f863ebc2bee9d699e78af970337a36de6d7b2ff7ab462122d21dec8cfd7232c5e22d753d5b35f2f5b7dfb8639b4ececa96fa9f9a57e5359eaaa94cc2af36c5a3d5a90a73e23679740db050f48958ce2beddbe89d2be5ff926395de7b7f22de5453a72ea757eaaa734b7e28575ab74c862739c79bf7145c87167ef7272ac69794b264497b35def90c36814351929ea5ecdba1767729b773d7a3aae39dec496cf4608d9d678d35d75d56797a3da36d5531e0ef7aa6f77e535a5f256529a1524f5ec3f523aceaf45872c3a8796bda2c39b7a7ea6f252bf3de697d236f393ddf64d8b525254a763acc9e8c9f358f7b18d3dd6d53a73cfdfcfcfb67ad8c82062deb03129ced82c3726a298b24dd8710c28d8a83f8156e3fc093b641ce8a546350edba5c661fb45853970606fbf35d4b0c6999c8703fe955e38391c650a51a6107a400331d6d09e4db5adfd4c97dcb76f5baa63a5f40b73a7f2755c404d7fb2e779b4e2ebf30a68f97c2a773054e9e34a1fd247dc39bf4e17cb737ef64e41c8f9f1dd33f55859bf107758b7ac2b18cfb0a273fecc7a667e1167e6af49463d7ced72582e3b18f2bbaf78ac95cbbd72168fb5f2b85958bcecb156e4c89f9ec9f4f419a075d49153b9841f322acc1af66287638dec5ec81ee7a7bdc5e32cb77971ab8af2a69fae99b124c599cc6090bfb7ba65afeaae5ee621c699b93253b669bae68e74670f39a12b5f59b44c9e55637ef4d22ecd8f3e6b91439b14daa54d6f93a6ab8cf9ca244b6652eb648fdb00f326f9f8f8f000c67af963dbf511a9aeb14653bca953367eddd3955d3f69e4ca96af5e133da20922ecc845136f6c6ddf1d5f2d2f1e60cfcb26e2abc563cf4b26b6a8624f1b2239918acc8ffe27c8af38287b45a457010bcc6f4a195446964b661c39fb913e75028960e2200f030202fab99977650a18389dca3869f993ca22dbc3421b634dd029c847498c1c59d33a649a035b1c790155a6209fe92b5390414e90d82aec78d484696f93931598dfb480f42195c8fa4df32c707a23e31f384849c8811d66f2f5a7ad48052c305d9a964045a8fc61f190bfb2e318669060b7047df39b1c30da8c8436a399f9cd2ccb212b9a210f984eb780ab65f490f9950094e969c2c8e169a4d44983aa428c942665db69449bd8f898cc22f9efb3b149c520df87d328a39402d1170bd7c35e75ad9a856315f78015631ded511ece1c9e99cef499b816e490fa50a0e98a940dda343f261ff9951d4aa61549139ea67cc91e481afb287902914a9dce0f924ea78e84d372c9354fae2199628d65a22fca4469ac3d1365caa80fdd21d2d857592d2d838df9d9dbee47a6a952f78352f9b1146becab6cfb8d7259e570ed72369043d7883596c220d6d8d36e032f30c51a4b39cabd91bf5d32514ca78fce55ef8e64e5a8c72ed32c21214d92435442a134b668fbf8509f6d9fa7a63eb1c63e9c3ed127fa74cf6eaf65de048a359d9e3e94c63ea33e4932a53ff3fb8432f541b1b2ae3beaa82ec3f8b17a0e6b4ec7e837dd039ebec54e3bf64e3a6ce1675ea843332f87d6960762918e718ce1577d5adc88d2b2e3593a18e45979b7cc6fced9a253b26013438baf1d69ec2d40b351bc6961dbe300a12f7afb21d6e6dab45819d6993ee918bdf6ddda6cb4d3b39f748c28d3f427cdca1e35cdcab4d0d6039ee2bcfad5f7dbf66a9c5863ebe9ebb5c3eab5471046cfba5a67c3a134363d8ce6c3d63dc2a8132705232121e52c333f9c354d2221d1971cfaea2f18e74c578f399297c31c67b2b4afde03e6c7e417cdd25e563af60293b38c92372d8d9050b807dc7498376623cba1632de63b307fd13c2f8779390c3e0fcc573a82db59ab55ce55347ef849a3e9d2347e828dfced1be6aea6855e2412a5c10ff190ed729220e12f31abc3ac34b67f19e1d4e508c9e46ff925e71c93f3595e4cf717194f8224783de0081e6b5b1df6f2558c6883d1b289d2e01ef0ebc4d8b1692d9bc6b269dbca51d72e91a60b758c92f122a821a19e554a252a82dbc6e1ae3ba134cdbb40eb9aee3cd676b9bbd55d1e5939e7fbd563d95f5ab495fc97d5107d598d35143304933724244d43d290b286a42169489a877a17a250ef4e9a97f3cbb6da60b6984dd3613eeaac18cde6d3f386daf263b7e55a4fdf50789f4e3beee53b2bcdda76585b8c687b2c83d5bffc45c7eeabd0cb91b463b9f40512929c323fac0d15cd0f5fd3d2c9fc30c6d307c604f7de7befbddacdeecdeebdf75eed6a17e36757cbb49be955acb97fa1db58c7eb837bef6d2387ad7defbdf7f4d8b1b2efd86fdfa9efce80089ef40f924c0bb1df3ea4bebbef384f2776ba6e3c21c60401cc6fccafcc5918cbdc1e09eb231c67b25297790fa8ba55b134eb3287b1528fc19c95d230d6652ea36331678d30e1c85658a9c7a4344bc8cb610e7b39cc5387d131a29486ad1ea363f5abc7ec5fde03a674d8daa9b364aa72d911e3c17872c778ac96b3de03c278ac16cd1202f398c3601ef396c7e818518b86c59ca563f5313a660fa37bc0889fe93075ed2d5dc8a29338e500753a187f7aec344b3b7da7fb49f39c679b27eea76c7a27add3b49c3d94770a75b6a6c33bb3b0e73853152587ad6fe6337b12c4d9877c9a436bcfd7e9615a6b93d34fdcad134a6a765a7d3c5a3d56f4b57a39f7ed1bc7136fb84bd4376f6e8ee3329b65dbca63812f1e8bd32c212d2d3b46f88e11bee33c326fb98b86d23864dfbeb5b66ddb369617e3c1acf25f3a174f06a54da8d4ab974a8b9a658ccd08000000002315002028140e87c5629158248b945def0114800e87a6446e561789b3204861983286106300000010204000608686680338914762be71e50111a9bec614e215b2e050e215145f71e0f8563e05ca7e350352bebc9f878f2e0934f015785c4798211137aed4bbee53e77cc7f2f968dc597d22414b3e78546daf014ef2cf63c5b3460c50b623a95df5243d18f29fd56d542a71b65de142d6a37a8fb226e71d54f577050837f51ace927d9f9b7c025d1b512b69bbd2c2312a6705bc82c4aeec404676094a07cc5c757405b224e343334e242609d71b084b6523adc9c18b212296a101edbd4805841ff35963c2855e11234c2c9d146d3f76e245350e76efb57844a002e6f5d174fe14f0410b80df2e2405cdc0450cbb9478b16237c627735000a0ee22dbef5ead9632541e9bceef65b775379025d833333516e97b87a35e3afe32b669dd629c4a0aa479ba8e1993d82a48d33f18425960f41581f08907c34815dcec9cc507c360e00b9b843f9975d80243bb718e707c6f4a65f4d90e6e2c1866ac8647ae72ff7add759874a35c5da48ba9015d397eaa0fe3559289ab4cb3d63a768e1e5835c7d81d32e38cf60d1dde6fe2bc1bd76148fe738112614437cd9ce7836799c799db06e30b0fff9f6afcd58e3c381362eae2ffe415edc679fde5f945e481999b4759d8f826c4dce08e91ce05c0220113621abe5dd48da17bbb2b498489a44dc11290418597b542d571c1e091997d581d480e66f2586196e56984c7fe8f5d43cd7015aa058cd098789b92ad61686b47848aa432b9b951c47bb763ec8fc08608d47e09c10a480c54ce1d164f560f28e2ce8062795bc367d19043c08ccea326d360225f7f184ae33dccff9a8220e98dacba0d71acc09dba68429001a8038203ab277acfa0dff3164692c6077b6211a2867ba7efadaebcaefd11f515c5d5babe8809a919ee1ce93637d680193bf8df9f83401c9988127388aceb658b14a21d0b5d90036efeab33bfbb831559dcc304fe6e32454a6ac22cccadf332ecf06de460ec0d4520dbd3eec79455a88cba6886fe5feb86423e945858830983acc8bd97e90be5bc991ced8d11cc985778286b381291e6409912c6f0121523ea458108d5318ec72c3cb7f349ec1b1253177ce380f4b247843dfbef20fa77ef0bca02771bc1b21405ec6b8a04c128f8ea0d03d477a3ff7b77ac1dc7fa7849b80b7e17669d569788dd2c923e32abc56b3443a97d50394da3d92b7f290d698e23fb5fe609edb58674ee02243ee882b0ad700d5e560accb636e898852f6437c17a5726efc2ae3e8e6a32e744d6fcd4c7e2fe174c6e915f77c0b5f7f6ecf9863040fc88b2aec22dfca44f69990896cb25af3ce4215a707f7fcdcb7f7741d3b1e1ef1abfebcee4df83c749d6bfa8226819e4bed5c1097ceb8682598b607904e01558e263a0b3f79fb00004928f7fa59c79ac83b3d8b91139ac9080801f17d0984dccbce4212fc6ef30093e292ca6275dc6033df9db1fff62f59ca50f558f56b8c605c0770bc818ef722813fce952f30f452a891b44d5dda848093cead08d6a2ae13d00472246888651f14d46462d7c84721327e5909250872d271a96dd7aa4dc275f40673d0606b44047c4de11da0eb62f8dfbffbb833c0dad2d012d1099e0a8e746410febbb2daf8711178add2bc322a78b3cccd9f260848de8acb0938e68e40f1de62ad2514d2b2b8a4b91a41f07879978e122b18d625978cae76829f13dd1565bf815d3870e7c18f2ce384fed63e09d08d8c1adff70c0cabc69c1a5bd8ccf9cad669296031fbd26890531fd329189901f69e68a80cc8157fcf4dd0e0dbe58f2a752e6716079d6c19b8739b7463b31b2c703d649b7c3a27a3c15b6c07d87b76f6ebf83a66ea74a0252fac18b741aa28ec42a9efe921d89c0b423d911e526f6cb9039ac22172d3990c360db298a5ac0775a329eb2cd478165d63ab431963d50f028d060b7aa90b7055b8550f71d05e5cad9dca2759e3ba73882e9e546f4e46e468aad32771a1d7a34682689ac843f2f8aeb44887e3ff2d03219df495b0b97ccfa204ecef0f811d716b84ad5f28e063fe1cdfe4f98f89ac82ba2ead8258d93dee0e99bf2f0a1c4173d0e1646ea4e4b40b161f1a6722c58a6bf29299b7a34c2c470d8b8ae7105c3e98884d5dc70f788d0a4dbf3c8b07a55a059154d098dce3abc2304157e92d90709d69897e80857d3f478cf62e9a97c9988b0082ac33f1c761c8a8c0de1e5d2b6c2c879caf4d3e1fc667c33a5243ce389edbde0065da1486ccd2b92b0ec24064b0b69c22448203e91898764613434c533219f8f8ae818e7996c16b4e68d33f25865faeb27679dd8181535147649ea8639d8203048f0b128c608799d5554685003957ece2d3ded4a448e58c367cfc595d63b3022d28b5e5087c4909611d54da1128253bfec71158942a2e1edbaa762b86aa67cb0191558f6dbc80469a48b749a0a1f788f438f3ea48e355d2dd4a37741d76df938c5c606085ead12b54185f0e7c36b858d12a3a037e3cc8e8a95815c85b0d0d88130ef244a8f7b7c7759f12b032ddf41aab695c06a21f229ee819a2227104322b4d2fc17f42f440ead117a5cbdd62b8ae3c956ae32240ce78d7898c75919127bc8e8d99c15b7679e4577b56df09a8307b052e79c8933bb255e03c110934ce1af8d1186cc89d829c498bf4f8b60494acc24f7e481cc47924e66784a7e13cf870f9d6ad4c4983371cd36a97473eafe00796bd10cf3af6ed01d0fe687fcc6bda275d98a3c0ee15f6608a8651d9c96f497745a9a66cd7d57f222ab0ec1600d382aefdbb6a522269f55a361356f2c3a0fa042b547620a0face689402be4fa212e1aa7cc952637a845eef32b0f77edf226aea9618d88590e76f5a62c0eeabdf0857543fff9be72dd9f6069b0cfbaea7cbfbb3330ad5261d483e7258c578f47b67212851cc8737af22f5115e7413a9144d2d450d9ae73c7ad68973b31fdef517b898300ce08eea1ff1dde9aba8c827871719a3ade003e977c5327af2979300575734c7412d4da900073c0c093805b95846b7adb757ae254c879fdb25d89677c2d6619596aaa258931f489369e2a5e339a7b7c5dc9b67253334e035b22fa09f7cb73b42bc85b83915a5f720be4a8b8cd28e51adc3fbc1ee1e51da5eca36d99c256528ea4a0a47d43dd7292c7e0045b7cacfa85709a2a4e0d51ef5d1bbbcc02f89445108fabca36652a8bfa379b8cde91e59836a0a7a6f0f6ea0ab3fceba39526b6a999b909c6fd1f9e9a12e4529da99b68c0d687e9e52fd5ba0719e84dcb77c9b0f5565af01030afd863fcfe3d0a1f69fa3ec86a70477b1fa3fbea13fa9748285b09b80a62d195e252b4598eb5dd2a0681241e0dfb064017954007a2a25e0236343128858376ab70440a97e93c4bc2142018c5291b761daaec49696f06d0c8e0d06eeb5f46151263c35c92b36fea83d0ad256c6abfef93084ea051b417e5945a181521c160f6ddd79bf697f1934f2659b886e0eb3973463a36e334648306ba3409a91de44a5daabb66711c379e15eaa3875e1f3bd689f95b45df1d3472f30413e709bc04e0308652a348e2a58281e13539d447ab9a57bd7d360fb295b1237725f0fbd6b882b576ad939a8fc86abe8bac74b890bb8b4cbb2f3b850e7650cc189aad19f7e004534a824dee89a2284913594d3a0e5a283a149382c4c4a0f851ab8eca64ca3f6e1846222d01ef7e6c6d76a7085089f832eda8bee86b68b83459e6cbf2a84d034f045fe8e2a081c2afee5de62f73c3289f0a8dea20dce94b4e8978dfc6f642a9adfce3381dbd7d40591696dbd49c41a2c9878c7ab5b00c5a1d32de3a9ddd15aff9c2d5491868749f6b688688aeb7e3ee940b10fef1ab2441d5b4950f92e56214f35997a638eb22222de47925a75abd512d25ce33f2e9612e7e1097c7c6eee7cabde2b93532177704564ac0aa2096edb45a59761668d96d33adb6568a67dd44a1b23cfd2525db2287f5c24039260715c0bccaa30334e5fc5705fc71212098537956cc3af8b41bf6ba93dd51c13eab7975f5760afb016deff36a2aaf0bd97dd46d51d615b56ac1283823c9cd0015fff68d5198c7b423f9a48bb414f76f3db94e2e882c736c4f0722653f961fb88126e2370963a900d18972fd7bf09bcb74b57c2a0494e9e3e9ba8262b16eed3d524f7d6e3bd8d30dbf0009a51b3f25e5d2c5644b091ab23430d0ade0902d175c2a2866a30e4f8de4dc74d3bfe62827b12b4800c9e37d551e749f592ecec4627b26312e7c24a04b8fe0785f37c015970ff4ff54f1ba61b716d74ceb26ec885e5a74923964dadeaf2ee60f2f7b210cdff4121853854c4eaa641ec19c757a100db719da08ac0b7dc02a74269ceef884de7ed3081b6a1430e3e245766f04bbb1ba98427c4af0311eb8750388638ab723ba8992051cc7322d60f304654e9d32e0a3d262efa7f9a98ae8af8d6020256e78f7ea2f5c392cbb43827ba7291cdadf591a8f8bfd8eddbef93da4813bebeff97ec0c7f80fda49c14ca278cd4c4d44fe0bae651b7bc1d36551c03e02b2e33cf050b0c9f54b237227ac2143149bb73df875eff949862cac31b30d3aad7aa4b4e80cd1c42b87bf14f58d294de8c67336ff17475b7156764b05df16c02eebbf7ba489622aafd2896b5bec5887945e3e92edaefc9be39486e26e7406a58ac4ea749135fe61af229541ff1dd87aa1d7b663c39ae81adabda4470d905a0683725c9bfed0d4742bcb30eb1eb06a52a509ac1f8cfc9f42d61f0ae6676fa8c28746ee276f2e4e3df9c24b3b9ea87955ab8918f67deed05c903fe7fcfd4c8f36c786bd16109fec0dd3bb02b6545373107978c2ed0f1604557b83d970daa50d9bea03addb2568441e80ee3ebd4f81583ee7170cd402c555845e2296bd796d8960761b603ff38ddff14917bf169837afb46085180a25ab6c04e2af873fc2d2ba463eb83be7c328ebb21d4ae4b609942795b98f2ce5d10b3a6f6aed227af6e732b48b1847ab55907caea75f63bdd29f7882a4d30834fa354fe70033e706e5314aa09ca81e8d4e3732a56504747a1f13da2bd94e451dc0dd23f052e636014130619a81733304a8804296627a04fbd8831e807f341d363d7a9410a2877e07477dfabf88caaec7890b0f4eba94b967338077e9f027bb43e9d76c1f9c9d5ba8a9e6840d001e4e68cd04651123b17e95e98d2ef2076005c2a6a245a4dd05fa6f5db6aaa528c412870eccc2e625463246c3b05a92c73492d468395dfbe632ff4498cbc4e122a79d13ec829531b0d0459159161700a13f5d684f93f2606727ddc093c3476332917230739f6ea308db5e432e5fb74c508c9e303852368076d538ae2697e89ae31768aeb746a1cfe9210a998dd3987448d25811865e2592a677e9fa67c69b9cb4bfd51a4bd0069ed149a959669ea93d747f82d1838de3f972853bb70fe05ec1121b5ff97c99b93b32a056ad9e3bb7c785370b3ac5874aa9a2bb5e6b96e282a34bccdbdfb2a6335ed0afe23dd05a3475c41b36b60dd69521f13600e91010e81772b1c1034e866c2108a7041dfb5ebde5e90fa465ccadc693c1576ce03564f66cc1466b3f8447531eebb5526847abfed3f2994d6c1342e8654d131913be0b43a80e795f3c41b673f0b3f4d0e5c3070d64ffc56e469f13d13bd9693f33188fa502c64264d4b9aa91428e0db587bfe1ae3df25daeb42422642238a9fbedee8f923565642a24af5a6d827ec7721983be88b2622eec4d78123855150aba7e2fd84986bcafe0194031872236f6180545c824c63c5b596d7d1ceabf5ae0e13bcabd70b4d21e6b49fab85a11d27607d82742b72a02a8bf7c13e1cafe5022575cc7aad774c1adef4b02a6fdca85a8b73ea23f9b6ff426181b66d4d970bef455fcde6ce04fca48b50818e1e4d2cb8ebd7b27764a808815b9bc32021808e7ab80305a97ccf6cf2f6e409c882e48101412968e913c6efd25aa2d3bb9468736b1426cd98b3de80603ed0b8a651a5184966f5024472ee55a7c5b8d64537c7c30007bc7872cd971250e9e629c563dbecba59a21d54805f80d61227cd2cb4458b328fca29736d40ae880128bc802b1517e7e6bd0d270bb2a21da9ecc45a9e34e7eac929ff266c4d75d3b278ded98e5fcd43192d58fde5ace0e79120517de5f40508c8c70ad6e70654d4be8ce4bd1e4b845fee57d3deb32e28ba19dbcc5bcf0f6060a5017dc7ed97897bd5278bf3659994b321e663126a3a3f6fe4aa6f2af32357a452fb731d26b707f8694e0efbd45eba0bc80548d09ea26f909d7bf2eef4421b40905988601babdc7a99419384ed9cd69833534e6695baac384396c4a4b26eae158e09b235d2e6715050bd39c9932885b276144d3a6be9b371f3532d49d381a0a4ab60b764d8e7f238cf81b3b5a38a1dfb0fa0beabfe3718a6a24fda7435dcd309686c2f1739e186c1d3e9493484667e01588020de35e5f456bc074603f500a7b7248be629ab2ca9322b35f085ec6db65b47f16a728992f7bc95181c4fc4a730396823e91029653feeba9ccfca96a390bf8d89cb5bd08a20f8911b43a464ab2db1dbb1031ef6100bed8f60d596aa7236290a379d3e20d5d6fd14ade9e876a36f2a886c92bdb928aacaa29531c936dc9232b8ba5c1b24f763a1b571d0d75a551f80be5554476b626551e96b5a0f202a38ac5b74d13b71d916f11a629ab4d0c405543708a91a0be84b283e6f5f27987659a4f6390618715775ea885771a5762d2a374d90d5b352e48b5dc1721f86bc22317cdc943527a8939c530814118abb39091505181278986d05b81aa03eac5f55be2599671de1b54cce4e79c0083425e21e908c2e89d8df12345e77d9c7e0d073d36a121bad23306010cc39bd13ee35be0df3522835c8c68f08376ac5be10817d806d7bf0267aedaa146694d5e83955d040e36e5dc8a4a42a587a64349d4607bb044104b15f63d0d1a387eb0a95809df81a506b1c7a2446c916e2f087dc6be2b64c8292b85c915c8ccfcc08aff124c5bb38922baf779b3dc264369f47cb0f827509a3e8d87586c7625847917b180775792ba975fdbfc007adbfdfd461803a87752162826c29dcaa2de92c1765ee2cbd15325d16be206a858348e09d6b165f4f4e661b0aba09f98a8fd73ae65fe4347fa6d8d424de4aa721373f44b4be781242bedfb609bb17909917baaba433892a483379243e19590f48276d07dd6dc7293a8b3daa414374648bff90e53eb39d70615e20034adf484f9dcab6adbd015aa84c8a38d44dc5638d84f70b6d2b0fdaf68c09c8cd2e58f492765b21a8fc4dc984bdde9dd462cb0db4acbe246b0d6c97ad4020163ccc2f035833bb1eab22619a883f986356a21a25f2f8b8d1bd02a8b881b650001966fa4d614c040a862d2334c79fb6d78a7613f8bea17cc752548cf622da60f8496ebb85cebf2cef65673aac541f1ab3a197940679de54dcbdb29a29f475568e572db7be66189698bd95323b2284f2cd89397e538c5852a675649bcfb6400061ea4ac92031937638ab6b15c3add49d19eea232adf6805122fc65a6b17b5e36463deb256c5a9fd9eab32d75ca2c5ac255fde7e934bcae44e98985868bbc6418acd1ea24ae322fdecdc7cbff3c119dbb165ef69085327b1f35ce366787fd48cf5fa7e405f692c91eb16b62485719c975d60f5fe05d677a0a57285750c6c3c10e7f4fe8b5f06eab5b4a17c64808dec7723d0962948257c62c8715bc97238596e92d5b919ef82468635801a8d16aba2dfe75af63daec166f9783dc2a989d7625f0a704a13c69872504908c65ec74821480491d7c878978dc3cf569ebb84b6f07524a39be180d45c0a535d54f6e5fbd1c08a4c2dfbf2d748a10389f33e460a4c73eac43d67dfaf8fc0ea410874c4be1d1268f0911316fb53f9e3758c3762c6480092f3db57800c7d5b2de844f37ef73c5ab213131f30bb5fadc00623e8f461f8e417cd6fe61adff9decb2fa96bb138c16e8c0772a4b40121e0b40ead1051dbdcb32f03429874b9837f041c096ca817604c1126f0021407acadf739d21ccf03b001f13ce07a8500db8288cc482040520aa751afc90b81c09f3d8a2515bb5553de9e300fa1dd68874070a66786c45dc96ef042e901d666fa442fe4b1ec47426bf02da5207ef460f7975ee4f4ef50165f6dbee7f174489b7d7c38e55940c91fbeec0aa6004e987e83a39d6201f1d5ab2575a45a02df2f715f912bcc6fe4d9423811c369546186a190fd9a2c4c8993d86514df2ca8e084b3699730240b46ba7ea1b892dfd377af95f69fc4718c20490d6b1623c6e5fb1a46c788a97dc74ce7a9d5541d869a711e8d36ce800be169fe5fa78a626c60c3a9c8133ff775e0a4ec867733f09fc240e8e3a528aa7dd358ba2e710bec6cba710770b0d62950cd8477e9eda1b98e1497b5f496d4f567e1de5c9ecc8549609492caadb8b252951810cefd643275346984aac4a2e3eea3eea0f21474e0128340ef422badb12fb361747ecb853d3406f4e386debf0b3d8b908d8a4d139d164a191f3d4728002c4e7a8a2d29b2acf774085cf661230ffdce37b177cbe49d3693ba2faa60c76e9356d221219fb90bddbe05000b77a4e412555dbecc0e198516ff13e6be4a539b234900a6f0869cbcf62f65eae3d322cb972679a04271a4158b8d9c52972be8af7862435ee9b39393fb46d6a4ccd1170655b054001a83704628c650bf0393e512c107fa20b4f1b41d4845207ad9a1de36e6c398f51d29e497165d70cc800815de9d2cd6043136c837f4f884643a890149322542d6d978de65a38454abf4e65694568307793fd211d284412f12648e39e9bf84c60747a844ab88712f3d09ce347fd3589388d057f3c21853a1446d935d04fa548556654cfc41a01a5e940825280fa9ce7b6823f3ae7f629470058aac3ac68a2244fe4c6a1c49af822d2aec53f54b9488dfd138883a283d250068573efeaede4c85bfa24ca7c8c913fac23726fde0f23926c31d6ff7ae4ee3ef4a53bbccee1e7756115976e6562496d34f51c4b7c342617f19a291c3f4a9e27ae0bb08df1da93ce3c1f0b7e6826768b0261652f46554a2a769ea1921f8ee6cf488eb2a1c131b05a54fe4c7faa7478965e5c45df35c65205d716c9fd67ba77c6b78b4c9ea306d85bb8e8c88619b5692586edfa1e3aa534b43ce834c22beaf16241e559435bb536e1b498d7e2724a38009582a8ee2b5be6757b03e8e10e426c7e9f7a78e220af060a73f1f5259700918a9b1de109b5c338908a3dd78abfe995c5dc967ceca279c0005151dc4340ff66ef4eaff0700319c960e94240e028877a41ed287ebd54748473696dc5e94f2ef9673aae81fd7d990993c3e0b7c2833a01026ae8ae42895e4dfb0fbc2439355c227148bfa1a91319d470fa86e0c305d7256b51eb594a60b20d0529adc34d7ac4d34c772d8baf98bc3e69c75ccb1734fbfbe2cfe61894c3b90efa26663d8cf72df01b22bf7f310297dc194d07d1bd06ec206d8c63b5714ec434ff9732b3096631d6a00be36f324063468912a91b5b45adc8f2c3ea26ba42255f10213d4fca4a28b7724e980826f81655334778ba950aa4b3cb29798286aedc1f33ce125ce42e37f540669519f89aeb6872ac2b6660d4eafe153a7f4c13e647e3444ac6cee7c724f4fd50f5e5dd52404ef77f35a767148191b9a54163e69963ecc432c69899eaeed38428d61263aa7dd0dd402dd3e76624c232f1a0e262e7f358cf5f27e405f29990815128d203e775ca6e0a55a7a3fad19b9a291602d00631c3163a7d9579ac5e4111e30d6f2d4e06023730830882ab691e06c3406675191dcbcf43a7a4a4905437ffab2fc00c8afe6daa861e498f77a72ac8ce7ede7b0cd6e54be1b4a5f7a4a191e895bc4499ec8027bbd8b53ca39fdf144e3358e03a8ed81c9cd266bfa89a985936283a1257b05d3ac7cd101ad60ec57b192f92e7f81c557c99840768698d7dacf61a6d4c469b5424135b77aa5bf88ac5d3164464a10e2061c28a404ca04e462892f14e1feb29f336f5c9242a8aa960ca8878a23a9baf8f0856453042f5a4e26c67fb737552e0082ba47d91f825b51b9e67e6aa6c4b19e164780ae4c730035140d3d746fbbe2ff1e6556cb2589faf356ac26324545e07bfe528d0bb475fc98eab6871a29d1a64e6e7aad425d2082564ee805b34d99a82fb0507e83891f0c249d90d67a162aee7d4d9ee4b103915ac3f78c65ed70f8450cf6f1d93771f83598d8f7b8f50ac0e1a3497c92ccfb8f4eef0a2c07ee449fafa8fc56ef0fda4a49ced06aae1c82ce3043080a8d06ab10399ec3592207327d6877b271dbf9f49b287d360a26acad2f720e1444815111a7f9b285a91ca7e8108773de367b395d616508e00fb0fea2a2af73ab1615c8435833e2d980d5b282568e62c1ea026678a3168741afde56dd65952979b0b57495754c2174a5494e3c44e1559c411b5325e948fb85a50658d4b2eec36d49a4b152fc5861b777e7c63c689f5aef0313f6e2df084af6e0186a23f27a8b4a9ca59ae0855808b72aaaef0ffe12e76b1af24102e0a2a6c1224a2d77831169214a0d98506ee797d2cff475b119c714726cb85dea9b58e770b6697ed27c9566a07db8fffc34587f2ca1adc5e308793cb32d11efaec825e8663951478fcb03242344d74671d630a593a09d5af4cc86fe0e4e3c472c3d457f496bd76f8de8b0a8fe89b60fb9d77de18fe9838eb13e9fbb4b13f534fa56430ba10d35fe1d4e19f2cc7b51f3e64f7f516f95707bb4f93a1c6efa7f84e7dbdbcbd74323fd16da13607bb60975e6de24ea03e525f50edf6188c9f96e541e7a2de62680d18c1a86885c1d16d61ea53dcf3959b1f183378d6c54535ae80262bb1e8a0c9cac95feef179d3bab984aa6507daf99f272cc3994e363396054b92efede45aeacb023ecca15f17be01c710a154047e54a037bb47079deeb0ee8a9ee36f51118e423a074f76558b917837f792f579c0da446715ddcb4331b3e8fbd0204f6029f3902d514f73134fdbf9f78c3503a3025afe683f20af9df710a8a78dcdbe32d896113339219a182b2cee82f434934914d81e2237e38ad0d5f78af2aa786f785964bf709d4ad859434b8ab9240bce11ff0b56ab451b4bdc92ccb6af82db6f44937560d7b57a7d77aee2cc0482355935056a51407f76bb3e7bee1542768ea657a66506eed30a39421a5f9d7b27e2a9bb68dcf5170b805a641276db5b25ebf3376d71a36e865af7d846858d0c98b01b2be594446f9e75c282538a317e17be334b2512d1a7ac327fe77f4121ee0cc4d2e2974d71ace5a44665bfa328153727bff3a285e50d35faec6d43e04d9fc9bc1c6addbdc2f8191615aab0ae6947dfbd06379587cc725f755f3871e50228cd7696c9de6592653cb63bdcb706bede5a14d2cd58b4b149a486c45c03e05d997a31de668312f8e2cfe741e17c76688cde6c8c4bbec1e07e41192ab319d68d62eb43939f24ade57da3365d44ff4b1031a02d47623381e3bec59b79c1cea747cb4d14ffe72ed7a4dc700490821098e5fb0989b8ef3fec1e9a822e00887ea726647003f248a797dd0820aacbf525897c10a6bf2df4394300aa208fbb251c0bd7817fb7b010daca79da20cfd52bf9100386cf06b03d79e34b3a533083bd51f9c6202618029c43476b875184b34931d07e004ed51ea65bdcd23bdcadaba9c4b9be503dacdb4dcc91c0751d0cc8840e49175789178e1bd75e9aaaa40fa9d80c29a61c48f2a609e86be912d4e7ea89a67e422c043973147f71be0eed4b0e945c5b3c97e44d3109aff81a0176afe6047e85221dc007c35c95dc868c2b3c74e3f789fa24ac1b29f50b7efaf2c490b86579b08fc58e0d3ee3565348c3348e075d5921d02940c67d7c154ed64ef2366d0f36999579282b4c7acd6c41136860b7843037c02751f55a81f071e901d0f84f808bd9242bde82109c324d6f31888d93129c2fcd6e4165576d1f5c067fe5ca88354f18805716709731aecd02b36c28de621ffa9f6146abe99c66781abd5e59120342a6a9ff38610d37e78a9fe9ceddb3bef06b25a0edb5d79546c57f53f3050650ff66e4ea993eae34675ce4d152358f8c6aac6df6b44c95cd028dff78ce485f9e0f9f85c2a9a9fc431b253bdd2f92eb28d8d040aa414ff29f53d800d1320b4da8520d46363598c38a17b0447c75ead05f98dc85b3b965708a9506580b0628a6e4b5ea135ae1ad2575d8f90f9b5a6bef5ec9a63c80fa169feeaee01c9f4616ac50abf0363a93422f279390d2c078aee8c70f9ad69bde578f0a565e3ab267e0fbf1a9029a91addf755d0235b1948997c59582c3c4d2fd0b818b2f76cd8fceb4e7a33209e79cd4fcaab222f554a798d4813ac353b63c905a67a1499e9030ae73e9ae94faadd68721a5c10410a4ae6146c48f0ba8fbab4b3ef138a6d0239aa0ea5a6793843e5ffebf66371cc6b2b8a97bb10829851c87a8bc23b6cdfa72551541531cb9177a571af68375e54640b3c6a6d46bc9267c7c009ecc2d2e5f7e7f4899655eb752d5deaca5f80367f59c35d213d49f403b0ab2db2ce207695aab53c4df7bc3c281bdd2253d4e83628bf95958b2b2fdb2300a81dd18fcd142e6932fdfb2b21378d786e2a2ec452317112a04018a3b46779af628198999b97ad3d1b61f867b368fc096073eb38b1a0195cfc2fae4f3020c52ec81d886e217d9ab47da0639f0caa2831027fa806e46afe2c0f6e36405d4ab927e8db8e5ed93f3e2c6afa871e10af854fb18123ba9e4d0aeef452c9996b8e545132686cd000a43dabf2fb9a1304dcf5b4834aaca47e6897c01364037e058206bfb14daaf4edd93821c9b199684e5405c9c31a6970a75116ad544067b9508c7c4c4ab7d8b37c413a2f836f65869a0f92095b8e19761d505f31bd2708500741424e1e95601c260ebf7827b962f5ebe43429fa27914db61474ff08cd98326f79fbafca230c274c4b149a82aa3d5df429a28a5a7f9c6611f6a1d3e0fbfab1a74ccee5c4aa98c8ccc0e1aad093f693d728b5576ed54f43373f031bcbf97eb5b114d0d3241b0df62efabb91c469c89a0b8d756cacc5ce0c51566d6cfc8b0bad303195d4595d7275c11c16061a81d46b68f948d84ca8202f27f848ec8380589652cee0a3220f9c8db4af44cd4f8c77a119a9c563ecb30435d9dbcda3e28b1e1c3f5c40cb676b62b15ea20e8e27ab8cb3f3c7f97c67260a8c18b0eb271e93de9a3f5313e51099160cd7c1bc5acfe434da460ef974eec7868d87994b591a97d42d56211556aedc1b509822a934f9af052d7f9649fbff348c7f81ff6fc7a07b5c316c6946873743d20aa26a3ef475e5b03c0884ab612d91f6cc7c4855dc2721d29aa28ac7f8bcf3d7833611e323131dd5e3c284ecf9d4d46178ca7c97a0693ece9da077a1dece2781929f57197003ca95e744ac3c2ebea3536e1097615f0c4e9f0c02d0a058075bfd796d3e0cf4eafce271b4d57aaf8fd3f067c2daf6cd0e98a965770f136255e75bca99a2e791ef761e4d392797fecaed63f0e34f574f0229a6c43351f3844825ed03b8e27a6fb2ee21b1497dc3d8ae11dfb3b6ae98c33acf9ae6b016963af20f20b58aa40581a64e3c8b181f4bb0010f246f1fc06643fd7bebb0e0f20539028c07108391a86e1ff00ee01a7dc7428f0d79e5bbe4ea55f788fdab0aad2e5e0edd2f734bf13649a26479dc42d9accd2087efdacd7a8ddd67a4fff2a1b1d6a59a3003148fe0c2b29fc99181ae46a47e39b2832b5fe635fae62c4a46d48945a9d40f8ed002ce70d611e9e3461eb7a2419c5bc0bc20388b940c29a2a09887fb326e1bb9ba880e626d1dd7f70421144db37729623fe195550c5da006ed3c00346cf8c7d2362c0d0806e444420e6447100e984b0f78559b0ae8edfb1dc39c9524554d35c4cc62b52d12570653da665dda6ee4159e5f1b0dbf63d7d064ebe851a409ce202858d45d3a0be97334183e1d9268630de5a24126f780bb4cfd926feacc378c6886de0b37bdcec33cb5c57e2dfda840ec2ef29f7d85dbb2a324a3a7b834b35f761432c36469b8fdbb773e4e87f06f7cf2e262799938cb1828ab11357202cc83ceaaa2a5e42b9b4b0601dc0db060fa1ca4c2988393ec1d6b67b8af48bf7510a4c200a7b14850b8152c77e8a1c2a087a1e64122862e464d4f13b1d6fd59c5866da29fae99defcaed0d1e65dc77fdc4a3bfabf1f7c54624057f9b820b6c499be1756abc02162b92eec24109a58f79b495dab5272ff1dd69433f99ebe44eb4aed6f8c4015a9c0431e0499066eb2239aaf6c338eca122aca35bacdb7bedbb008f182291adde0992269dba11e0d011a4700984a3354df803eab4276bdad2e3fd4b14009def788a230a8d8c1f0aba40b2c6611e5b6b4a52064dac91480fe0bf4bf2d9cf6ade3a87b97a1210860b87a1771ebc1422c5a5ca9cf01142713c5d1e30a057facd00ab78d499f8fa78da43dd3cc5078d8d93788a6eae4a914c3661be3f700a574fb76fc23d01bc8183cb41c07d3a6facc3a25493699f6df216e7ba0c600da9b43b5c0dcd652be763b8c8e40a00b7b6c54050d1ef4791e569e028f2009e5c3948631d77ca5b847a2b290d80806af4a92af7a83b9f85e3ba6aaf73aad62bd6e63264fff1fcf9be71770399de25fa5d3ba3291e4d49f68e7e2e495cdc3eec55b848c2a49c4c321a0d01122b17da0e49711ee75a2247a8c5ae6c06a4683584032df972af5631db2acf7c02d7c39e8562e928feca524bc7e2dc83eb6cee630d7be96e7e2b3ffffc2c08d321387ec4117f0dd82e5131bd73b96ef557a81f68bc3d211e96c6232515a7dbce1e56b06c959d26e6547145d15599370c55db085d5bb30075b3a8424ef9b19c9501500f46cb8e2a402c51081f0a014b2c6bb945ac4f3d78c8bf798dbecd0680216c398f8dc2516fb528cc31cbb59216281cd357a077f6407e2d55b1ab5ceff7443046ef38fae4f87ad897e8fb8f590de64414ffaf32b38ad9584e2ca710bc5f0656e2a8eaaa55a5364240b1145abad2ad3bfefd775bb068db531b62b2c1859385160a2a4ca7de8341a0fda0bab3646d602be20057828e62821ee25b6898dd38808915e1d2473591feddf05c2e5994006b854bb152cf022ef1ad5b98413490eaf30477c5a82755d778f5bfe2e00ce5ef4c1cf241f323bc4205730dc63bacd0f655019f0998d0c349c0eaabe708ded31811e6bc90f0cc739416109792dd9ddc47561aabc41e050b5f6a2d02d39273e72d602193a4ad552722444d414ca7ed72fa2fb8fc5f69489295c0bb9b12c2eee4a03ec2355747bb68c3f971a8235d10440ceee2dffbe2ddcdfcb576f08e9eb43f0c8f8c2e0b015014453d323e6d0ca28ab71b50019039f03bf393b10e1849e5123d51f9ace41cbcbee0aee047cfdbf94795d3418949854ba53369042f468f77a46d17caec59e368b7d1b0c064a2694c4039af2e308ba8487056b7a984b401a33bbc56176a89c0eda1c2617816abe46ab5e75efbe915fd2bf8be408879de4af6a4ac275b1b6832982aa7244e0c105b03e3758889b46b9507b45cc9f9459dc4549dc3abffed0e26a06b15de47ad8a8aae2e5949eb950a60a511194a389cbd6881bbcd1f6c5e59cb7a7f35c2aef30f2ba80714ace5484ed2823c96580645ebede1d9a191cdddf21f4e83374c5b46a3cffcc039fd3e5359866a33905031556ea815bc89ecb8ce556c90a4fad015b9848c51dc93d7584e394a4fc18adfb2da1c829169744e1f746a9e98ea939f6f8f4608f09c65b57a3a038f26ed3eb79ce12f6c6f9fedad83d8549333a727dc07ae4ed68080eae38a4a773ee8fb4885de48c2114a70f5a4b2f39b8d271a04dd3bef83f0b065bed2321855122517dcba99a43acf53354441144709fbc3f5c0a114f1b0e45a5be2e2115c5b790c36bf9c753b28b8e6bc2aea36f3ee57bec480eb033ee85ff36e0a74ff5cc829a85fae9a8661378baf236b55a723b38ac54301fb3bd76147e624e0ed05495cab637f1c730ba1fc0e864e09a41e7804de371a20002d8974eb12b02e46139b7ed415796d6645acdedad58a8141d7d42208daf7aab00ac187237de3f268203cb388b9ca203d7151eb6f20eb23a78b84055f842829bba831b3c58e56325bac0018a17ee87fa428320fc322eb2ac58a845deaee786299461a5196ce3ecd4fe8a3c9748dc5e7e2d2b6aba826268025c18326fc9f344dc435cc0bf64ca798f7a5ff340e5fbc19cc739fecd1156e2d9059d83b6c18de544f4af6b3df5bee705e0a9cdc04c5f502fde150023e81c68a63c69aa9a1e69e0aa5056776bafaafc1281fbd57213a1d651499b70bf50619eca6e3b979391a5e33265ec8c497fef48a99be97bf84b1e51ebcf4ac2d675cd83f7da3bff4c9f9e877e7a46e08f386bfc156c02f6a0e6166832a5409c8b36d4b1e7dfb431ac2d2fbf90a691962989713c00f934d247ee76a85b3a9427ba4c4762816259442f0afa9f14136694889b640bbba4cc520ff7b321192e41c399c128620464f0ff0746a8783d6483d7b1a1e19b6b4cfb17b71d89e88ac41111d34fd9038bf8d1d1a5c011997e56199da02c86adac1c7e40640983cbf25452e4b786be2d8377b21f1453603960fbdb0937c5bdb367bd3e9b8f637e10203d49b1b982d1a794924961936bcca0be7cfa744b155b3d268b52e59f45a0f04699be4810ee5a346b4f12c695aa4ea7dcc47e9f82b16efbb99b14959ebdef1a28133e24692cdb5b1dc1070c490d88fb6e962729cfe105a6614f313dc92c09bc210b3dc789f88bfa3c629402821374ae71f0d88967a60948906662e5cfce4ce0b79588de59be046ee2228f736b290200e09ccca9d546264ee22b529ce315a8c6f1ca501ac3c70cc5a94cf29d945fa1b650fa087c03a44bf8b56c30fdd12be225472f2215711286c762af8b4195c15c8af2db3bc74f345a58fb1d218e4dfedf03737867c15b9a20870e04a9880c986e3ba4164e616593b83f684454cbd40c8b980414c36ca7b056332917531c6de2e6a46382c579dc7c35bcd7d60540c18c145a069265f096fa4e6b0cae304c1d9062ae0661e7d0359f28aab45a8a707726065e56006c0cbfef8ff280418616f6a3ccd60a599e671dfbf2fe90f4eba0811f0e87de0d3b4f3360b51204df5ba063363997f14c3bdc5692fd3e4b93f74fb6943e76ccbdc577069e7f9dfd9643ca63e094ad2acee0397067befa0e88db334d89ce28c27ae6809c69eefeee5d6b701b1b8242db213eb63deb5aed4a5d39f92e991350b7194c2fdc99aaf43f3a67218238436f70c6530d3da86f2af5fcee1a7a275649de25faf24c68bdc416c84f4efab28ce1915ca1679880825dfb3bb8154a7828f94456f0a137d16080954efb6cef148c81333b7cc7aa0515c658297b303dcfc633a2027e18a20b260299cf149dc44ada823a094dfbed7b8f62f71c5e89c71a354b6ef9f86d58e2070a39819efb353aad6a430f1c73cbf05f2cf8b5e9e34db574ae0dac04616c8d4951ed25841c79bee84f5acc93c6dfb168fc56103ae73b269e94d7b8b21beec0441193055f1a54b81c7555dfa1ef9c28beecd11a568472e454549ebdb2db84f1600ceeaa4fb0e520cde9e7f7fdb2287c93d01282f68e3ff861871842d3f901e6419f4a60d8b097ad377b36173c2ecae56c46b3d7356c645bc3787c72190a8ac75b7978bb657224c38c9b382cf60c1feae279b207bd51ed2e54d72ad4e2483ae4ba5eb1f421fa579089e76b322d60f15f831e5799804573f8c55471ff83594d99a2dab47c3db8c91740a9209ae4143fe781a3072105c4718afee3f2b05f4c6b9f95d55ffad9cc0f19de52a6b280aae9036eeb7ad16ee175e7358a1ebf6817a2c3f454688087fd0dd34208b0553ba1203b36c8f62943046dc958f57a92a7346453afe17df4508ab34c7945842755a0343cd6d6f4c0ae567e568597d0e68d830b24bc7022a802097b7a296627440c73c0ca2985575ad99dacec753afaf4ac2346648237cf9fa2f979701fc91a1de973482eeb82cb6da3b0490583775df4e5c285e6dda381fdaa0c2e40bad957004e5d9c5e470b87373124b0229d5410a8a4d1fb3f3dc82655d0941cd8b1be361078e52088d7660b72f7432c272cdc64a21be385e64798f9d08c05e1d0e30713525623ca18336eda6cf2de1c7a45000d3ed2c106e8ae752c202e2fb02d01ea72b2a2719fc4fcdfb0adf871d34dbc20962c65f004e7a988de62bbd95e36c3a1aa8bf48afefd9d9a4316c9d58bbf591d9e3ee402f8ca541762e57d63e81cdb2e058441ef358082d893f8605ea27565c6624f290fa176ba6a6e44fa2718ea8afbfc4a36e2eaf5d0945d7956cb6fdd0b505b92960b719d1b86f5c17bbd8a875f5a1e62843267c063e722646888332c316c1e4bfcb1fa9071cb63070bdc8c7c89dfaa719772c520a98cd5669682b04d12c76b44f4ab94c62c2c513ccc67f545e89b29421361d72a73afa5d0459c532dad2d3b82bb993b281b2e982d9a75e2d1289454970e98bc5246b279f7cafe46493c08c0a856a69eb731a41da6d271035f115f51b6d294fd4ff0c3e6d54cc5a9cfae8cc390614bc1afd135a288f637759af7a488682b36077a21cf261fcc60b2b3d753f20cb41a7ebb9536903bfeef5a68b405df05092306ab605c70a3500e2cd75dfb5bc85674b23cb2a97ae16ba899416c5aba24aa69956f9a2e7d83a02792e7605e330a71cba5c6b6d18891a243a9ba3e3dac5b56aef839884d295a1f637685a50d5215768eb2a693ab015e5dc94fe86bc51068dcf68f331b4536e8135656cfff71f02c32d497a91981514ec23a11c30a5929fae1a5301a91e632f05c024d4120ef6c0890d41e6810099cc330e9072ef28cbe14580575163f9ba850a2b3e30d1a2b805dba5e5f9045ba96a38d54efef866e1306e78b3c7aa4c7f45c70bbe7cd06d6a3bf99ba6a340303c05d3142f92ba0c0e7128cd41d93fe81a3ccbe6ce36a40b1fe705ac63330db5ed8cc276b92d5aa33cefd28a6288256d419e57ba91f9b263caf2166fe0b2f429cfc26d3e20278bc1aa7cc1e0c0a8c1d270157b6f4df2a1de2dd7a67611761d100393f83885181106732302880fb00dac5fa94ae872703f227c9cece287956bdd1ec785e2c61128369b4511af82a356b4127c7c17b9cfc4c9cd66ffd771df3cb86e83e9086ef0309734cb2dee1d58633a3cff734375b6620e544c53d9825d6267437ef16ea4eeacc2b5ae50459abcfd05f286a43d8859ce8a3afe3fb88f150755372a297f34dbf9ab06ee3b4e0eff6eb5d96cdf9d5c23faa57272bef3a55464db02d17da484a13d9fb4994071d6b0a829c879c245ef971ebdd9194b5648ce036d25871c8d885490b682dc3b1f61f30135839c475766dccc3ac4fc9cf95edccd508a9329a73ac2498a4cf0bb4925845e1bf69abadccd821bb34f70fcd5162656506756d251d86b9fa909cbad72b0267b737fff7ec371215dc6fba69462a22b0d72853a5000bcaa793f1e378c879dcd57084df873b14b187bdb4f04e5ffa338072dc7b746bbe3ed6506e82eebbe2af53ca91e9a3e161351255ccdc9639709baf604b4be293a3d5b33ab12768190b07aef069d204074dd7a96e5d2bab958863e2a522ea809a7d09f7bc84068ad36b7c2a7d7b5b28e4532b5e9ba832482521467079caacc7a03915d3c420b0d5821def9f5791668f403f662ada6aaf09727613ece2108b3a3cef543f1ce802a282d137064751ca974d9c72c37c50235cfe7e67bdf3fe5597fad9f388ce63fa4b618f09b64b8da54781aee65a6fc9dbe3950e030ebaad5a420b2183c3790af5f4a0c2f6a478c20f6ea110f9e1f15fa3f83e335fa5a2f016f432e65da806c2fef6a3d58ad4de617838d259c96d0cc41fb0d699376540cac2e193ea51c65252eba3c0a9206d05b291f5b3253c1ea7e32cca03908a504c67c36808325fa5e9c28fab332f3109bb383cfba34b39a0b61ffdafc5cab9ac33b3f0d8bbb64c347f2a0b884ea07c1d789d8e1cf756b54ed17217b8f358c5b36aaa48f0ad3645e094d98f266b7f22f9681e6fd4093fdeb28d8a6006629390ac817d1290a08a7bb55445a3996a890c7c24118387daabe94855ab95cdfe34952c5d9b8c9254116e2c7a60277555d5e265b34ff5fc8831c27bfea7a7eb6f7ef41623f86ded6dfadf5ec237fc206c0c56a042605d0feece8bec4d29e1ff2c5d2221d6cf5012a755d820e142cd6c5c44e0766476e3d8ec5b68082bbe1da038eaaacd8ff40b0f9d42e6e0eaafd2ad373303be948e8b18e9edbdb299f99ab2079688fda08df9d1fdc3953717fd694d425e827565a18a7fbf8b37c3330c3ee92d057af7c90e4e850c4b2b74f90c51745e86e035670f70198a5633fe1b9f2687084da778e3438234d02136cd212dab191239c0196ab0b45308fc7de272bbdc237dbed3b82d31502f85642f17b7f3a349521f9a52e66911e459fe65d7b05a93b483549d4e949d5a53567f6bf5c5bad35be54c588c1fc98a45541f2382f00ccd82c2e5c88e055c0ab56d915df42363b148f6b08929e7a85391742ec00b9533e4d4eaf637c7db6a993ae912ce3faa190d46f5496e358b5deda07d96baf6622b597bdc5aaa3da74645cfaca779e55b2758005894c6d0b0c14f2cfa3ef81881721da6923d4f90f006324ede7c85bef5c3571061f79d396c3f1e1bf44f09061996e213d58c0fcbe8b69e71395cad8041e9a5abda2fb01ea09b3ba8719ba85c6008c5a964100299ac9b6b965b3cedb01b40f7a1909430225f8e61689b7ce050c51d5e2abb10364c802e4e0c9d5600d6758db62fb8116cf64ad414c1846e76c8480dfc413f1e1e30c1de91f1c6b760d60c914e9ebe4a9edfea64c05dae081c92c189e0ab27e5f6a20bf1153d3245cd0136f8ef1a8018ffb0113b6263d63a836b782ca4d0424df16a6c7e384d2199e90f17c6b0566866e25264ae80ece9332883e4ac5045ef30a0e7015609a5a73330a9c87c5ae155eb285d86187ed992e8eefff799bb6105115c61b915447c583943b1045026d287a4516971c5f3fdef651f553b0e6608d74360383cd0bcf78ed33057000b572e63a62a78b18cc7b8f54500af32694b5e1768c79e94a951ff4e58af1c7fa5eeac8aad1487febf1b61d94fe97e271125843b23a854a731d406602d78003e85dc870c486b3211509d18771700cc43004a6e0470081b7f173125e066e00b78d260a7ac0a2485ddeca399487382868db28fe042f846d4fb002595b862ce2eb8aa2bfc08adda708a392cc2f95840c32726d5469b111ccb546905db5f88b08e95f89e475bc1e9838b16201a88ede2ad2b730e41cc2128bd0ab5ea803c2d128ab5ae6af69086da0d86629120182411b0c0ed53b652a3ad626e9f9c0811ee82ae82c4a0af2aa4ef664a0527d692d96287558c815aefa04c85a253348b21e1b3c1e2cdbd8f8be4e720a34bfcfffa2cd18d4ac808f6dc4e66860ddebf66d5a9a3f77a18f194df5022e7bba58c48e0eda42c08d3fef4482ed84857bef56bd2592f4b4f387198c6eb4fa645be7b2f11ff4f1e1e48b16524a5cd5886034cc74212b178a84e59f87538823802769a886ce18c4f00ad1b3c55c6ed5aae05b6a1e89f8c7356e46dc5445f0bcb5b8c9f0b88887bcb1905744261688923e2d81757672231c815a0431935d85e773959821e3dcb40d2f2e89a1d8144f930636996abd4131caef539f24438664a9ae22dfd9f0faa29ac222cd36b7bd83fd84088dc9f25e86f7f035cf1c934d85749a82be2954acfd61bcbb2c5e0382df1b804bacfb3f7d51babb43879e5fea9dc7a264f1fcefe79b751dc25420a00e84f1338415a01e8ed8761b68a2fa901c47023da4b03ad1436367a699d1b43e0d6d1289f0f428253c919da4313b19b05cb19f148674533e19f330e1b0c6b15eb8e14dee556eca438a51cb195a0146f8613f0173c03e2d5c105943ee559e2f986dea6d10ee70f000aad7fa0023c860cef59972eac15c10d8415bbf848d512c40f15c841dfa40c69f5caf42840392f1b023ca52ddaa158fa2db951676463ea8721cab526aa4757ecc725edd4bc35f22c6796451ff8ef0a293e06f9718680585f0d1799d65eeeec02d4e6f10de24b00a12fcca0e21a4e32bd82cad6e57cf5377365073b3904d5459128288785ed72b5f2e19a1c35cec195a3f230506788b3640553ba0984783921f41fe194feb2d2d82dbf00a987d4da2bf7537f8fcb5a43fef5af649fdf4b45dd004211619581bd923db446c36d15a2e103c60bb9fa80cbc2665a80493e4912d0cd1a5346a197fbffe1d2102f6f584dc57f629e4660067aa0677e1b68b2907582162842f6b0749f3403b13dd9b16640e8fbed82e38ea0e2385040d82e44a8706d82175e81543b9bd033eaac83a2cc16f8942122b082c5a3d95304cff260e043240a0e11b6a84e05334398005b08a48474791157248e3b604725709fe4639ab3f2d5038fd61f2f8f632e2073cc0d7b4a88683768321d166ef00b90154a52804bfaa901f1cbf89178507423848dc0e33f3b15b2e363cc0fbd190f80a5bb2cf19f4a130328b14a8a31d0fa07a8822ee0834177be1cd428c4fc23df024ac4f8cff6a733408bd8a40a87d59fa28545bfcba46bfd80deb8c229e581aa6bfd122fd082505cd9cd830d4691c1ec86cc4b5a6428e6071658053f0614d63af65dbd1fdec51db14f9cedaeeea7cef44ee62f1a3aec77939e586fcda1f33e0efaa3af2d12995cd6d891085d224a967eb0b0120bbcf9819b72138dce8d66eea915aecfa4582a62336b78216cfaddf0201ec871706d71218242f967ca936ab86b06bc2b344e9133d04de9db20af1a01e81dfb6d74540e7311f352548a4c86e221b07eb7556ecd0063659a0a50287270e24d0cfe50f288253b2066065a5f7665b8cb8df35eebf11b53e8487594b994171ef96862dba0fe495f9ddeeaa37db03e206fa8e8d5cbfa53ad27a02faf570283e8d7ccc31df26665af32bd556a2f4886259a25fdf9bd2b8b079578ed90192b948c4950442388f70fcbd9d6f93b0309ba038e71705b6575094f1358fa2436302b1db1fba0cac3355063a416e737e0b5b0ae5b972b00c17df26294b79486a047de14b8d778b048209108e6acc6b782b308a682672a2b1c74d028e300713add0d36ee7af906c1bcc5e6d3b91d081f27185bb9d61d905a97e7d28b336a2fd17430f4b025395e03d10a39e47b34a5ec96bd19b95914b042ad64b08aca5bd17f66d77e7fa312b812386a4174f460bf87e4ae49842e75db50363053f01fa5f10371e99171a83e0a47d31b9c569b7717da75f25c494fd6c11a3f339a04b6024ab74a1a784592873aa9ce6564307f22b30547ef74ad4051144b12cb930e448d7392850c8c59a58d4a6f2647f5cfdfa34af70c668172bc0efb2cfff13e38fda90a926190c4daeb42dbfe3f5bc5b8da2f28fb03dcb96396ef43f084146be64482eed9409dd088105b237af1ca1d7ea21f50ad4a5def20a3d2c361b6e1927cc0f7ca02be4107e9d1c55949211adeeb2159ebcd12890541defaca02950989f3d4cf1924ea6c19d9f1f2b02f606c8fced0eb1485fcccdf71abf9b47841f2c554b68df1a75c9c75da597035790c5d8674668293a6e58b3c3e9be22a49858d004294ebb444d838077db510989d73f0c97e303ee72176798d9da0d088af90fbd8ef9c8b56d508cfb333f103904204e747dc446307d2770e0a7e8f4f099b19f40a26a7999fa593c5f3c6db1939fe97a8034119322db2ec845f33d2ee4aa7fcb8434bcc331efd060a718e6d06e03081c45185562565d9d8173edf84e510b6c486395203b915b176e35a5ca9bba2f9ea2563bb2a94b617421a7f1cd468c3dd3765f58f6764b07dfb63f724ba871a5444efd353fb0dd99646d4674dab0fff52fa3cd603b419619d58fcb5e6331cac53744eee84a2796846639d5a79b0c60437f8c737646976096092a37c46d88b35a48d887109729346923419203b87754c6e3eff8439f0710bb40bd2af3a6e42dbfcfd5682be86a093e9c35ad3bff630fe9ab0faf6b80c02c51289a8390336665f037b01b4d6ab58e41ed9bab23028db2d272a50b4d303451a488f4549c0f311493df91ccf0d7a84d482d85ba54971920386a458511adcf6140c61e252c38d5e8bf8be4edf4ffab80af8ce31a0aeaec513016d96951360b4c494eabd94ec8ca98060f58ca05140e5cb7a1660fd894234581179276596f75f89758ba9136321ebf2905c4d09a276a41392fd93383446d4ad04c33225c21c5caad818dc3611c0fd02c98dde04f535fdc738592d53199c3c5ef7ca80f9d46c5e5c31506fa2229048528ec4a9a0e9418322777e9b1f027581318c93b26600d3694f84a658718c72f915de3821aae0b633d1326fa9316283876a5f00508b8490f7375459e009f055a0c78615d3fe38296c90971d635485b2a95dab85c5366ef9e21717eb57722a60a4a6fb2b947bf51f9689d83ba9185bd53733eab25d4a6a87d10b824eea291d172009fca1034d3941bf85b60d5969932c111a321c8f03ea8872f128344491029479f55c462f95e083f393224dc52631e0786cacf26324e96506ff38cdd88acc220a98fc1a4bac3c4ac4e128dd21a5b80f9861fc7aac20bd2f220d576ba02915277b5d40a43932304f0958bdde2cd009e019a21be7816991d9702a2e74d0093cf139cb894b148326344003d96d082ccbb28d392f29fe8456237b4970b34102f02a59a22c7265860349d6dec468f76e425c3529da34800404b0dcbbfb805183e61c662b51d1a963417f0b243a97bfc1656c018a875aa14f6ecd35f75c38527f2317b3c95d3717920bd3b1c6bd57cec94fb05c088905ea37e0d1a68bdd24b36ef07c62d7652ffc6cffe980b87557edc6b66efdf9804e8b461ea532fa859fe5e643dbb18ca5eac7b72d81c8334fc7c2ed24f43fb0981b2ac8b0fdc418b1084c06efe918e5c3b0a5f8762f67c1a96afebad23e4dbaeef8251779887886cf964f5a82dcbd531a216810a66a1960bd828803ccf5bdc9ebf6bd4806c2e47dca6745d080e01a3c0cc4ea533c39f2495ccf172947b6c7060ca3381e621d99aa5dc4fffcac8ffa123958287d26f4216238667b3677e2d33b93cbdb9c6477a1d96afdf3a2226b8848042944448f3c79f7702d72d5816d409e3a4576213d565109ceccd81ed9725b868095cf088c5efcd589c410dac3fcd3229bc2153169fa8e8ec1979ac23db48623d9c5d7b9148b0b1f89d8f16a27c9956f11b78729fb92c275c1ab0fe407d1a714a3e2ec53990e680584a096d141ddf46413a1362160e0bf6f01f25f2c5271570906678549873e8106632fc605f4560419019969b67ed92b59f9095edea50e5c363c23d90b34834c37965737bfe019cfbd45c1e402d8c3c0c58aa8130f3dc44359bb0e79445c46c2172e51928c958867ea2e9fb86ee6cb1d778312eba3b90104d1ae6355fe1aaf2cfd96c37cf428b58b17a3c0d5a5c1fcdc0b119ab6495a52a93c42ef3fd7052bbfaeab2305f1751e3a1ea30c839b215de1c296b263968f215d3f07b96a281611470e95b713c23ca2cf5821beb12ad3108c65c9fb39116f2bad605cae740b57da82fd648ae7bd4f4c2ff2c28b37589028013320fa7b1e9123fddea01059251b10e6707cfc6374dec8f29eb17cfa1ae32347899fda3cdcf6020269fa51ad8dc7dcf0ca93b3c3d125dc898ae419cb1ca291d3e79b22b5052fe5f7651dbfe861f9b34db28699740a811c86faa8cc851c02d1af3c5a9fcbf58dd0a7f1324be326edc7dadbdf41a893a7c7b2a9efb536c4320ce1f8d2a68382a1017b415db80c3017d465f8fea996390061f4a93282eb53b61c0587db114816b4e729aa2452568e53e337ee261ad683ee846de25957890673aee6507926273987be2f33e34ca224eacc348419c66cff2dcfbb3578ca79d201a4a7437141a7cf8c5ee05b38cf18964c03ef35f635d844f1cebbaffefe6f4602aebd7322171bd9c29873b47eca821d319ec9200f8c0a4c6642e6600e6548a1c4711bbc8a7c5cfd41db9107b6340177beca69191dd8fadc60bc67002884309fcb94466c29d5c4478f0f615f481c0e25b70a9ba419cb48e648a74f5a6544dddb7484cce7d8e1a91ef052e74787f159722a6ce5a9bb29a340275012ade2e48c44734df3c521e6cad38d21eecef99165caafeb8ca9c5bcd4cd29540b69338bd3368a7245ac8260e72fff2e1fdb2a0972739bda006c2ded49b29e1005e75c4b0e4d56cda12638c9fcb1d756b039b3484b51175aecaca0a3c14014fa3b3000f8187a15de52a37321e2f51f7f9f43c1fdd4de2d48bb3891e83c6ee242f58581f5b68d613dc00ae52320cecf3819ac5d130a073e1504e333624f983c1b313e9993c6671befc4288950407bd9030063c629337b1566ebec50c8d2ed6adc35924f44baebcfd8b31a01be8af4d999fc8051e3951e1436d684a8d72ccd14400c183d11c1773bd4b2e48f3514db84f201aacd2bf09b053ab06180007f0f48694064053cecbab09132034870a8a81af914bc4f5ed94d6b7dd6d86af62dbd81e617d0185bfe642923dd80f4672a97cd68e32a3c8dcf6dbcb8032e85f4ef868b840f61e355c002299d1a20ddfd4c0f6dd7d944455fcc14d287026bae859a09f42eacbdafe2ed683468526748a7c248a93f7d53768a949fbb4017e665a490566aa19ad99a4eadc711d7842a8dd0b8924245571805cb5459d30535c6719f73377609de49b48b4e4909e06fc38876cba60ca7582911c603f52379e076499337808700007c9eb6044946f72d5759265584e2ab04350cc15802348e56e9059f40db812873e03604e50b22ba87b6e3d1b6dc9cfe3b2378a33c11f991eb106a06a552ed9112d93780adff31dc82547a43fd20f24a1b4183c803d1048e11fea05492592ad26418445933e890a2161aa06140dbc7a9e86fc645ac579d338f5c2afc07af410fd5c9af2774d2a754079657e270f2122b442afbc6db4f37cf06e80246dadf40c258d0161d5e2e9f8c639d991bcbea3ccfb736c6fe8dcd652a864359d19d220d9968b48005163daf92b4b4df7c72751b78f367e0544ea4dde521e7160881ccb9052315681909265f83557cae4796c618f8a711eb4347c1c966cae38e134b4377b0d77cd7f6e233b99cbb179697da0ace294737258107467eebc0f46de20d1b39bb4f067250a08fcb28ae49e776931cbb28facd72b83006797973d7e7c641546c0a87a03e8c09de9d3a95f67231a1533020638994bfd137ad9d39f31b4d314b4f5121a7db997886c30b7c709b511cd3673e7298de712dc1ab3d34782ce4cca622e19a4a2130db6040537ce5670cc104958c8eb5318848b11a1a6959617ec35ab4be574f60a816955547081e5c1d1a0f95c69f32f9134d1e65465073328e0218b9e12f6075fef1a8f219132c8acd71da1dc32fa85c53a76e22b6377be326bdcfdc9e46a9f494d64d58a9b08ea84ac243e1c7c942a84afb5ec752dcebfbd00f9227e5ae9d6421e045b35867975f88889a3e8005c01ced967896d44f9088f863f34811311825b15946190a1f60a0ac2c2170b44edc4b536eec5cb4a751e21fe3f2d9f2b482bde30a7e1fe79d8466e7455f4bfa53f57b83d258f0ddf422a669167b1122b9d8936327545f4a607421304a45fc4eccaa43f8130081f548e9be1e95e69fb25be533f5d1581ca6f08e7284b4d8181208f9d9af416c58b953dfcbbc70238c6ea0e0f4ca082da9bcb6d05fb83921dcf3b73f546522a8d6232e6bbac0c901150cb305c348c334f35451ca7fb733351cc7d78b5308b650fd89b2e8ee74c9b28cb427ceba8287bfad080ec0efc922222fae7c7648eb2302d6d1125deb4c12fcd1651cac791cab2658e2b6bf3c1504aef737478efd380d8b26fb4b476a465ad03984165a15b152d81b5d37d629fa8857ba5750e3664f621f65a812221c9589148c05b3a7fe27cfe7c0bd75cf77b104694f0196658ab5b98e3d9b211d5115fc9a11c0ca355685f3efe8c0fe516afeb1bdfcac77b0f37c23733254d08dc8bde35058b2025a632eb6095cc20ff7e994e378317749c405b88f19834f6282435a36e91f8f03fdd6739b4a43833b8c7dbc947d471e88442923116b88845c4dd6b77cee7bb87745a5a63f5b7e78af8639416bdf99803fb50c5723f03d812d52d70a848d2d3de71bce417ac08d3edc26a4308e32b83d73c60f8283b746f73e3173bf64dc254df0f7eb6855ec4480cd7e86e2ff7f19819faea01cb1cded087d74852b45c101bc1f04f40c71fe015a63f6f365a46a00d8072a7cef5310f48aaee7e181ba3fa0d1eb5c543b15d9c7c6055a4f4129a78ec94b8e384d339ebb7a9e0c06230d197ff9aafc860cef967ee34b25f6b9107de6343f95c282dd17b8a57f9bd6574a2c540a1cfd53cc8512eb7a24c9ba5a490cfd436d4b847bbd3c84ca481ed63df19020c7bfc9998d076821542aa1c9bb66bdcabe993ccffa9d53e5f9061ae5efa97b28986503722e322c2fb88c6df3a7965a2de8cc96540c347a3d4c9f25db50c7440dcb60dcf6f5a7fc69613c15b3ec69fdaadd80b0447ab76d260dbbe83d17a9630c006cbb6d13876d6e42b989bb4b0474b14245bae4b6fcea0f045e937724aa4a0b7c021d722ac25035c3691bca08b3ff548149fbfc10e362186723ae570fe0034cb67ded2f400dbccff13495e1c734657ce76c821f7b9a5a6ae84abb2e8bd84c0a3883d2b259f49c0c09c9f64668541350854877dc63e88972af7f220c48a8deb604fbf5da26144104ce73988872e0848547b14f0924b0c4580cfd46f640768c4a00077d5def5d18e8d3216244302fdd459d465703dc3bc3214034e0aae87ff9d43651211fd6dbe682371a3cf0c2e243ae1d9d9f46a31067e4e685bd4129edb4345c42b1b90ad531da3f8b51f66a4eb65a9a51b01855e8cbb3fb33751459ec30aa28e1d0bdc8b7eaeaef92c3fca017c298384944933a93b4e4e5fd0711b36db499540a49af3bf840774f82c6298faf65e4eb112d60418836f72098a1b06b6640bbd0e7cbe43f4017ca4066d589de6eaa990d21bc9d74a5a3f84b714dd99e7602e10dc468c8de2613c4c9f9a10aed170e37a6860b19daa046083a84d62589b58541e67a2accf439e11ff92a521b3451e20928498978f3d9962ecc157064c2c8270128c1172b16cbee1f080b4bc6391b18959aae73a44a6c4bd358e983982a71e7e5e9baf529ea1901f4a269a274269b74e741a64332287c3db941aff66f7ac809ffba95b244a5f4fcd686fde985246933ae2bce4473e85bb88cb7da3f6f13a6a272800ec3ff98551cb03c730fdb1f85e666fb15bc4f20fdfe3f5bccdedd168ebbc3852f94e7c270f517729326054b689e3f94714f7dc285f08a20a7250697fcf2746e1dea25645e8c6a98f5983d0e83c3dc92e9f747bb1ce8c6e7b986b1e00ebc2494c4f97c70b4af630fa6cb87bd9acba550bf2041d6c6c4288c5826a42a5b560b49ac78ee96322ac269abe2018b0d0ba327ad30f9f300951c5c1c54fc35b55e7528315d318f9215ce93569b3a5608e2ed6272392b77639df5d1ad13b6cd5bcd0e6de1fe1d61e73d0b0a2bf6daa7d3338c24818a08e78651fea6acb037548f7e77498d9e91573126331d4ea1d218be752ca162378a02e71d56f1f4b37711ea5445bed5964e2590b1f4ddfa8064cce21e0decbe450e7cbed4941e022114acfa9109ac6a29b64e658f7c9f8b5e5e844f854e1216ee2d5cfa446251f26437f8daf384791674a3edf71cf05af75e52d5a70f203c12831af002db671e63c24a43a4c4975866efbb82eb512adf9e578996169e8f8039512cc9d935400fee012c6282d5c61755c592482304acc0a525ffe66ecf8f30b434a72691171a6eb1855d9960cb9ab4dec8a7394b19f42d28bd81e6f4329e257df6a9a36a8f994340c6d174405f8c660f75bb3f11df4ac2dd0d7fcff016682c3e8d0d0e2b4a4f967164905193aac840bfacc7f512f8397fd21d9d8ec1ad59f8926c096ca93e10d468380031718ff5d127deea3884da0a8871b24b2ab5dc35a2b49464fdf266643a405b2fd5b563a0506b6509c8d8b5f4455ced5c8f6db238c0d0371b122541a4c839729a492792aa694cdb324788ce8f385bf852a60a63c146ab8e2fa391e363efe1cdbd32b0d5ec0da306115c1c4891ad135615275463cfa19dee1039e87bdb7ad502806a0573f03da0f24a58c043bdcb32d092244a268c92227af9c36461e5238512d2a51bdda54338f157a0a8a59f261f15b6405b2d752c74c784e95e0ca7aad5d740fd79287f58e1024cc665a268bd81cfaafea19caf3f667f7a08765bac125621d660d0def046e58f68d3bb92f16a7162b73385c6b7b57c5c0c6e116489a7e08f2e08fb6470f005c0956b52ba2cf0fec240a91b119d5abffe3bbd81537c1b21f67c697d72f351604f7a76a5c7487f7f5c7c832e41dfc9e4fb03cef495953a148b08452dd4beddc68fe0045cfbd5708b504286af33f8dd40a85c9a40d14eae2200a1dba6ed7770de49cdaa077e651058a3883a9241a8bc378b49bb443f303e890b6498d09e93afab3c550f36447724454ee4ff7168c5e3a1e781495753b57cdf806c20979c04062bc1f6b7106ab29f1feda090a7ad0976430594efc17f1eacda36d84db69ddcc205fb8d49aff501b7dbe0ea3f890663869367c0070d08d3066638c18a28e9233439286e5490b705370e1d976a9e432b8c9e2a23ac165375b946d83c4e42075bb8f60dfb899df850237f10e33d4b3f143731a47166d60e316f71b6ef04a739ad2a0e344b3ccb246709bb3427df747103dd87f9c98672491b6a9657ecd6ae2fbc68c795728c9e28939930a3cdb9c38d623281cfe88d0d27e2690fc36ba0e199303e782e689c32f1beaea4062f346549914ff96e3b745819af00766245cb9278e346a028f235d178d0241cc594d11df41ad40cad9f4386b7f5a39f3980dfd839c36a67e12e25e2001ae1785ac2cd9a525a6a9223aad27eb20a006a2128e0a5832a64cabde278301a338c547e283712d2dcfd0c274d4a8f4496fe16f17dcc9516b8d4da48142b8043d2648d4421af41357da657f242b16c50628427a51f943e4b8e5935ef99a937f017d5e1715395487aa0e03efdc4f3b87d3f250ee148e1131f6db716c359153b24c2d1dceb204463021322fcb020e625a751aa57379218fc12adcbcde1e2f6cd0bae10dbce5bd768ca2be75b3ccb383d2b64e9348d5fd8243270f2827e92b45e8b95977c91fe691a44ba88475afa76e800d0bceb1ee90e205da3012f3d8525a37631c5cf76997d455fc4d9f084c135cfd1424ca86e685f6442cfb068acd75693a749db49154c9b94362447317a51bbb01606c238ee26adba430c2e224f2bbc5ee8d761c2f259521102cf8a4dd5a6a85d9bc271e5668cf56eefd4af68ecc494cfa51c3f0613bfc5f89ceca91c540b2306464da4ecf01a0b3517302634014dc99d42902318c77f60208b1b9747d716a139aac91012cb8f9f8aefe7eecade24c3f80fee9a26b550a7d9bbcc6e1b1cd91540fecee65cf70e9d2e5ee260c8d06cecabc6884387942b79174024df26572398cd0e4e6969e813991c1307fecc2c72e714812659b422725375b9928fc7fc3fcac0f0c0809b31da5321d35bdc4521aca9422b74e98e9e38e84881ef755c4c71da91eef51a73633ad9889ab5497059a8193fade6d6c1ab3ef9fb87a693b75c421310b00d022cf25f6e3b01fc1593bbb47042530015e6684981a332e199a2f2cce32f1b28bab3505edd9dfd841d47e733aad6af91418cdc4f7948af32e96fea0a599cd747c9974acd447d52d7590e0a8377be57cdade2b889b5e2cc06deea9d49c2e3667ce57ae48c187eaa07f255533aa3ebc57d7688704ec74a74ad8ee87183042ca6e32e831823e1e0cc506e60530109a1f912c6c4044d311f100ee9420539d8f83d49deebb758f823dc16da1cbeefef50fc6d89354a54010571f2ef41b48fb0cb10e9b38a3b0f3938a600ed4e3137e3d63953b6a6039cfe13a98eb7f1736663c28e5d5dfa50fcf8c35206461c9bacc719035df36ca5eec94750a69e74fc35a0aac6308e0908bad470eef70aa05d40ea31ed28dc5cba646410ef88412341c3cd07c0e2edd7964fce05adbcb65c5e605d19874b864e81e1aec16adefd42d100a56a4fc50edf0542fe1bb7aec822fa58bec35531587d651adaa250319f3baa0d7aa83e28a06b9128192b7d4d13c1b211c604a46b8160cdfdd991b62de9bd4e57c15387e51a7f5e080fc1a2fcc787c6a92cb75f221fc45a67c2aafb99ad00e1d97430251744920346c06583bfd66b1ffc8001dd1439030a35d6725a3090ba4a074b998cabb74e54b1b2c2fd3a0d157492f973f605f292cd6712e1be36a3ad8499cc465dbdc8e14b89f9f78627c6702bc3b9a228cbe2cba41c43ce6fb05ba9bb045022b10fed3143ed6f2911d97b932db794292599021907160705074129ef9bdc862468cf64599665d950d1d190d0d013a22029464eb0d09c594b941d41b7c9e44c508534bce8078782a0d030f48488861b6651aab3acf948ba07320b498d5f0291aed8c3a1e63c5ecdd389006bca0ec22166e5ac888048282860136bc73bf26047986707f7c0ffb1da41353d05bc8570fec2f9db2dd99905fd6010f3c05a999815e1eb89970e936d130ac120e8a408f8ea800afac117dc3205855b2abf10dcb2408e98c5cf9321121e98a0a622f76e4f75438e37eaee51f3e88ef241ddbdfb831c28fc49a3d7eec3dd7db35077c7b029b3c8b9c6f5c631075334386634cd636f1ca57ffebcbb657c9b9c7763c9cc2beff66367665473d5b627ea3a91c44de8ecf09133b7db384ad3f45a6f3e51308b3e757cd1f145c7170a5fbedc25971ddb27263dcaee5e9d59757bed4e42dd9cac67dc89c989499a710651db641e6f17954d8d7168712965098890252062e3522897d2e7e4382c4555b267f40ceb8275f129bb383939d1504c4a33524a554d64125d25258e32a41926b060524a196d6e54bdeae82a33d2637653836bd8b051d5c8773263a3b48e455262177174dbb814ca27768aa6b1383389f29c9c9c9c9ce37cb6a7aac6e294286de3529ce2364d3eca4b36a3d75e9c9c9c9c682846a9aa2319b1c928ca6a6822cd993335353637353af2102c03cd804e3982a013b39e601932e8d00e719b1b9a484306afda5b653735b8860d1a4a696c689d16768eaa9bff4e23da74e8e0a8e77da083d2d181071f703e1d7540c83828a8c86accdca13f9058589683d3c1071bcd7fa0130200787c737e759667a2987ffbcd7e5334f4956c0f7ba147958b509a14b77190c75ca4a30a3e62248c580ab3a0308b79887f8b98a5a30a272727a71c3870400801cb81238410381f7f5f9ec8d3fc3a433d3cc44f5645454545366adc00002b328143d06988c99933373635581b8bf3f117006c82586c8b1fccf624e977824e5387ee78c2b3723c94238621266216f39333b8876df103318770e21654864e3cb43cf84521ff10ae51d9fcc043cb27d81ed5f36a7f748fca834e4270199a33285c35afda6bf7288d2a0002604a23801d5b8fead7a6a349ed40655a8a631d11d464c1c4145e50aa848d0c688da21a1c30d1438d2b9890010a4a33831b28f4a68b1a5b509b2d45d0d50b8e904e200609884a1859b058a14a03cb13366268aa6e1296a3c804842e63bb8ced194ac676bfb1adbcd0a56fc72a92b039dbdc1a0e6dd5373a07ea86dbf01a7ee338cf6265af9342a1e64d9ca9944d4c61353153452f60c0ec17d99e22db820fe44796ba4a4c0b264b653d45a0f7ed92e7d45447f3a9d7549c4f2acb20877aeeb3d728e793a150a82658b947d1703e28c91549713e92a394ab336716be92ed51d241e4389f58c4bb7a95ddfae8c9d99607319b9cf47a43411278b5713eeec1a71e7fa0a5608e922654e1f3bbbfbc0faad09d97ba4cfb54a404892a16d4bd331cc4ac757787ecdd2d811e0b35f14f0098e87e13877106d7f942fdf7f7a9f600a56e133dec3027a5abd5ef34214399ba4dc800a509a01ad4d93dbcc4ad7e2f14cc6acc97a9cd66d4fe11d0c92aa8fb71833014d8a37f9fbb86028370dba39f6679f47f5c3f8632039005e5a2a2be527b0a2630f5e32cb57fce3973f81083ae96baf5fba16e2dd12cead62a800ba36eed5395d91c425a1efd110d6ac343dd266440a37eacc42f568adeb7e31d2bc51b503753b7899fa0fab1529317232cfbe89bce17aad525ce070ae6c3bf0c3be5dcd217aa62ce4788bb737375db855c7927f30bb581ce9ddabae676793077423c00152c58004514415b5c71cd2ae50ab5c2be0ed45869f5bff962595bbfe649c0125d2c6b7d30f8a8224d68ea7c5851de95c02cad046e7545b895802a248906b6e52f24a42e0f7f0dac96ea824346db1240fcafaafe70ddc381de56559dbd3c42b86588b38b0f7fb9bbf9423f5a57317b5f65dea4d517a375878a57f52c2909a86e521345b5a76e12134f55eb4de70b8535558b9bce174aebfa9801bda91f73756781c01d44d81e48826df9bba360c80281352c0f1496892a3530c2cc0ac0a8fe4154ff6fb9a8fe265075aabaab43f55572c1c7d5de9647efc0ac2dc22cc7b09f18e6526a0bd03e05f9507a5f8ebabd5f9959b6b5f5a3095862697b6c4dc012486c6babf4b4cda19311d01c753922382afc8d5bdb73d40f7bcd33c22c2f720685750ae69bc40493d01051f7382c1a6284793ae88459bec3174ab36d0ff7d009736ec3f27058c3f6f0df879c095c851e8703f50ff2056ccbb1a0e551c3f2f05f400ed56108208e099628ff2be3cc06ccbe0414f7e8eeeefba2a2072e6ea8e206199e70819284bb3b5cd1807e3b8f29b1a34689b9476f72022b50e4604490103f20f1ea2d5094a02b0228e14418a88409aa3f37b173bd51bfed8a51172562a01899b9fa400d2735424e3728b8a1ca41c806091515c1508d13353442462a2a57d448e1f044a9945971379ca1015a6d23084a3dc9d144f0e28e74a07430daaa589123fbd1aa3c717352962e3da8fdd14ba1ffbff67050a8d063cfebf73accd3d28b1aaa28a37633d30a422f36d4d58eba495dc4bcae2c35f921880721c6b8828b981ae018481ce0c5182078517942e9861eb3330b0458ddbfb373c58bfab1ba2b106609a533ac7491c6103b3b5772d0c505622044860b0aa0c8206697b434518153125586e852060d225c908b0a9feed293a6263124484a62488c27a0c450436f510419242f65c4a0882e4f44682153c51632a6742185abc320693013281282881184808a2028828000a042e13784bed01dfecf962390f0855c15ea5a3712b7d134c448ff910824e9ee06aaed3f98e7dbf1d1596ac377187f347f6dc59a91618c10870aa26e2a8e82880c735e478bfaed9839a1d04238d49f8fea38eaf7a3ba5015b49f55dd91ba9baa82aac1ad4ab581a26abd412e4f84ea72394116953b1ce8f5a83c55f38d3b3a821b42544dc2959d5ad2b5571576fba24195aac58d8992ca40aa4bb0ba01afddd56451356ce36e2b536b7c3853b56c831d4efce5f2430870e2df6cdca17ca89ab6c12efeb65c8a045c85dd72f9a1a8462116f36cd54225d3026125dd7a8a61c154ff6196bb4ba70a8534066caffd91ed35cf3bc2793e8c906098670cf3ace062aafc2fd6a0fac7330b04be33550cf53e94bdcd3bc157d2312c0fb46159fe3e7da0ba6daaf0b5401be25285efd1a9c2ffe090c69e37c4c38132e91ec8d130bf7d0e0cd81ea88393d0f2f0d751042d2234bbe54320d12b8750d2184f9e4031baa28404d2921125244b47c00c29a293f3d80fc6aa1a92c0c83046b8429ae2688a5764c8dab1b34942e042fbf97d70cbbf07201c35abacea8180b692eea16032f0c10f34d960b15832b824d151042dc169d52d771affa3b113123119312cae8cccc06444cac284c50b296187b503aba22177f36b89a97be909082b4d495288f1b1f3c37fbff59245fd164c167f7e56cdea7e942b372a95755a1e516979f05b801b723777f0b4c508a42d46412568f241688bd19586dc44010bb0ea72552809acea67d23588922879557f165c601eae9e2446d10e0e9d547fdde03f5c5650e3b763aaff474211e6692caa33f95b8004ff9d2792429525abe213ec26d64e154695df070943aa38aafc4748e0fa7609690aaea90a33d51bea30cff74f66304f5f51d98575f1d52df84b66647972058d2eaad63ed169c798fa8105127f3667d6f27b37e3277fe2132da21f35417226d4d425d03b77e29a28526b81b457fe28b440b4ca1f9d7298c540f45b55f6a2d2f29042318da96528cfe6a3e6074d9716a3681eea6797bd904665d8bacb38bf03198f7bf3bf7f96498e50e098826e9296a3242d45384632d463b303c23e68ba50aa3a3feb827eb8e6a33aa019a66b7ed00f57f61a93fa58b72e6cc9aab696a15fc6ea0668760956db4b81f6bbb048ae0ec8ef80ff033a8d34f8fba56704fbf61ab02ecc7b00025c929dbb0cded5767797bd9e41c31106f50a1f4e4e7a41d3956158e751326fbe909e9d27a5b4a93ceecd417a02e9dd28734af63070444137494b925292968d296c925211144e2a27291155661ccf0457f4827ef04eb3bc6ed0ca155fe3d86d1075c5f55ae86417345df1e30b61ef34d2e0f842986799b5ddc59b483f376d6e70d3166318a04a03716eddba6677c4e18e103dd021e1366dc907b115019ad0645da8ee5b558e30d47e9772d3b018637fc3ea3fb5961dbbdb398e6f6567e3b26d833df827c320af03c2d64d698115b0831b827afd76bc0e08dcc61df111b86e5ddbb6dbd234a04281424e0193a63905501c06a49e7b2429ef91ecfba0015db267d6a936713571f1d6016d4f3b20ee7d904197ec19578aa3dbb75271440a503787cccd6c07d3415b9d297ec447f0406feece0118b736a973f20683649ab6c1b84030cfb4d7b40e4813e18b2f2547a47f466ddb1acb382236157b4ddba6641042544c655e0b5c31c73cb8f125a46df74cc1b2233e421f81705b1907666b5937c5fd9d1f4e895c0fe747123465c98f9a020b5de7b36a1357f6da722878d601653fc394253f2a0b2d4293139a5497c3509d884d95af611be416d0b51fcbba292d30d6dd33a6a6d702fb7b4e026f394bc7d89ec32be62d300afef3537d564cfa28a32bf65db1972bc0ba409a1500d3a8d193b0077f5c5380ff55e87d11c2e89db002ac9fac552e10d8b5c0ddc1dad38bf23d05ef84f5d2e086e086e81ebef900131922970637eef605e5072397c61b772e2c0ed2287a72c19023846b79846fabb0d737042b98a2c805038418d0b6ce6eaf360a8d30dab2cb778e487c7fee5290ece10cd9ca7fc256f67ccce08bdf026c52f9b73abf09b4501ccbda7ad081180a5f8b8f755fbfd6599d727ef439dfa7e7c528a4b3f62cab737632f3badfbf58e3fb482298170f9498f3b7fb623f23a036471ab4d5e9800a7e08218c72215602a5468e5076818de88bbee88bbea811a00eb4a010fe306116bb0004f5950291908c9a2061d942bf3d03b154177eb02c106c9b5266111193d799d79e794109435f404829c85a7c9931093c389fec7770459ad45dcf864a6124f80aed6a689013a11d869aa85baa0e1ad11c1a3a154706fd26d53a252c708b593f42dcc127dce24f75100a8f00c42da6a95c37bbd5a52ad645d99eeb9430f1cd5b114151dc134644aa2f6bec9fbda3fa91cfd913dd7f638edb95aece66ec58d49d75deb1db158bba67bbb9bf63c78ecd952b83fa33ec0161a5e9827e5e2152160495ee76864ea54c7bf333843d1652f95e12687346c11c452603e81e0585adc96db9f53e188ceabe6aff8c82c2ed54802fce67ffc34101b6114514c1663c4a299788908df53423c5c0a6944b444ccfd6ccf6c8504b98cc8a6277bbc4301648778f521a49892ddd9d8978cb6c0c4c4a2329180cb2ebcffe3d3369447d379495149614520a298594424a614961b949319162627b6161d00983c85f61eee37266a858f79130dd50180406f1b9b1128af3f1579d49ba150685dad6757fc856f71906f1ffa03c4ab23d5e681623096cc11e0cf3e4115c32e491bc32432a9bdb0fd0ea0373ce6cce6945943ae79c273c1962ba42c9730001520d24a408238b153e64e1428b2c646eced05837290b0dae408a42072b6470a19abafb71851d8be13f8b7924941e4ba7e97b5afb9f796a6af70fdbda9a002b78d8d656afd96130eeb2b5582183371856d490b593153a449a251814d9604608271e62f02507180e2f61ca48f1b34505462a2c3571118229ae9061c4aa9bf4c58a5a5337e94b96fa51953655da10d49e683da09850a190960713aa6a44f44c9205b2f145cd98d40ced414587342327ada85baa9f2806f3381365b18aa85f8bb220c700cc35bb25836450f7c4497b5fd3918162f56361d2089347120966f103e00c85de0ab07e511a55fe8d329bba67c626189b3a3655ee6e89e46505137c7cc226fa4df8f2e337b309cbac139ac62773e74e98de5c1eeb7f0216bd2898b79e6c2f8af4ba05365e3c9da5c28f4c2ccf462477f250d5dd495beab43ce20b615a8682b12c9a03155a1e5a9146d42dd8f48959eceeee6e4389fb824e2be8b74d145820ab1155ee76797c3690aa8d2cd5061335c0a8fc5fa6fa69c0bc827e342a55a667bac5df9a426dbc240ab83915052a59c8ddb6f85b225436000d94fe3febe70b528daffdbe680799b6385fc7150c43318a7558a1fbc4fcd2e4c731dc7f37395eb815ffdb366655e8c117b3ae50ffeea0978d6f2a7cbd98159f5382faf3c3d99550040cd665157a8160f863d538a683a72d41ee5b88d88945ccf39100a5d4f811f330e9c157085da87f0b9137754e9b3a678783c90e07d36447ebbc51a7b6aa53ca9f527b4dca6eab53763575ce0e07857ad9e1a0fea666b343bdecb2d7541bd60dc1861608f6113b324a5a568c48580f35c6a8bd5e98a44ff34728f62ed03cf58ea89e3ef55ca0aff2567a289aa73c50a2f69fa452e3cba305223f66a98fa89fcf7d94d85307a39396074ab1acf8112a31ab7aa93e37662949213fca974f837951697948cf0243e2beb82dc55c0a7bad4375d04b3721273baed22ea810cc010a412115b82cd91e58056cc5c7513ff85a61de07bb90de07b3e06012664d2aff83afd92434a7cc11625a02f3141fa21114a11935b2931a7f62f28bb14c8d1f9920941adf02497e908021ddf06177d75bf739b78dd29b9bd52a6773842c90feecbbbb593baaeca84261dd9eece12f67c28fbae407eab3b801045457b9b0ce8505f1806668d7f4a6f8cf90b9306f852c0ff850088d5fe32e3505f5f1a0a0c8f9d03839a5a6a09f0bd53eeaa3a6260e4a4d41e1afc466aa6a345b9733a13d29856d00b9bd7f53c23c18d002910f9f09bb307be08ae9c70f6bce154b29a592432498a50c6c59f10c1b5c09f330644e616670a84d8127214a44b44d4d88562b4a5bc86af52feca8c97d71f08346864f199ecc88019310443ca80006490e058eec898a2d9ea8a208a0a5fe62054636643027ccc8ec081c3adb324e34492760e02f1afc78e5a04cfdf6c5a586fa2dd3827989b1137fc8cb8b17182d05daea7c98902660083f90c170e2767ad2ab24382619249f20b440a291f3048439a9bd483bd4c69eb84e0d2216639ac69431030d0ca862dfafc469c8b6e0bfba690729041fb0a96302a49ec9740cafcaf09bc142a3ce18b22784a040f88279c0241132c43522bae98cb135712024f133e1cfcffc59b17e660827a01ffc914cdd4dedd44f8d1131f398c1a8f66b2f1803e82188000ada35bc2b7ee0afd7cb8891d7eb65e4f57a7941bf7d1509814118f680debbc30449771b81cc1c41488376c31ef0a5116d5a5a5acaa24356c34bca962e5a8870a2df0a9a9102ef08a5b4b7e47c3c092f3ecb1199406da4667fec972750fd5b7a11fd26d24426f031d09250c0024998a71f42cf88119311d34ef740253f564fd58b13f0058da011141212125a254f4f4fdba4850aa920e87eab7053e142fe76a528047686cd772fcb7eb329e3cfdedd3a9d67b3df6c998364bfd976963db6db14f82c9bdedc19bdedf9824905eee328517e28015adbb703ee3e99f987bb632be6e89399997b325ce8de7bd0cdcc3578a0e2be3df3e7ce39dd71a0a0f0e5e7b84251565014d0ae30b5cb69dab6bdbdae71bb2d2386b9bb7777f46ca76e866277389d6a39ae601c0d8df48edd282b5660158a89c2156065611b6edfeca2b67062b81b4709ded8558adb3454467383b4ddb73cfbfcbd0a9ba56e7b94d8cce272a1fed980fc5fc7aaf5e7d5c8f299a1b4ed61776b4d9505aeededc01a31c60f6ed277175543bbe1b6ed628cdc51a4e17c9626a5d1885383fe76976a37356c2c8f6d8fd2b09ca1344df38de3dacfe86d732eb5b59fd15e854b694c3afdea1e5e40546698c3b6180a250171c6e836c2bd2a712ba271da022fa22aafe25c91ca6b5ae0453536a9b5f19b1678d14d0d1b2a28b271a35dd56ec68d5595558daa5f0037b612dd230da25b89ee9106d1ad58f118c388561c936284142b53ca1152e011523234a4b4eca07e15e7d3d2bd1e9a81159a1a56b4d581de3225a5c42687c5c7e666988f1d2d96918eac5088068f50c8931e959969a8baf343695ba995bac56d44b641da08f6e0df9ed473bb2dec398a61dc095cfb9723e241c5324f49b7c4781ada41a9db08068139f02b41a9cccced4d0e06691a926ef17760445548b27352ba5afd3c6264c37eec703b3b4586ecaeba2894ee60168b6668833b68a1dbdc1c2a7cae617bdae839a89568daa87b3a87fa41a13eaa3c543f28d4582a07b5527b3d8463c666888d84a0500e2ad486d2dc3c51a72b3a2951d5689679ea42315cf08f106c3a72d245520e42ed050f22b88234c6052378fee20a9007f5db2a37464be5deb99f5fa0e0a6fea8aefdcc811729a09ed4859731f3db2a56bf9b8a3df633898b19346559e9a8224c52961f97a4528809039e310651d108b5c548a93a5424a183d28f8b99f38144351bc3a22b314fbc38298179fccb7021930408b2bc804c11648670776705a07edb4d14f5cb09e3a5cb1651b6e052636b4b8c154251bf9bea393a60c40c20cc0dd57ff5cdaa2d323aacf5a2c5114c606c6875a11fed0a5fc777ea77938595e95ac4b0d2817e734752b9c972946ca87c08b261daa2030ac4991aa61b4c9a209a5431c8149110ad21c5fde044c3836a03e22855c469444c5c121cca07a7ad892dfb2148a382ce1f90505ba430a10c8b32347288103f138b1ba08230ca4206d40f59e080227acaa2874964940510d387a22c86a819e283124e1436454e84b971822f6e44e1c418589ca8818d2328f76303aabaa1061345f9604387a29a2e28e6821a55d278428a1a219aaa9bf404989a304f9039a25bdda427c820e2891c7ce12405086296f87dbd8065205f7c293529e574aa3cee0d617c975bb73f420e056cce2897b1eef3fee0e3a00021a4a2b596f8c08c0a3fc715caf02150f35185cc4e554e895896faee54945f0a3ea7e744a98e06a56ddca49486db345486c5b98209d9b5d1c320e44e289a462f26861e52f73633f596a04bdd875c3608dc413ee44ee00a5fe3c2a0cd99101f87889782336b32abf26b8160cfbf028444740e0d41247ef2c11dba14137d70885f4f60105e823df8f909644e45a1791acf05185c292f063151f744a32f5a0d556697f2f22287c22ca22518c4817021bc8ff97388a0f03f27c2f8a87bdad5ec62ee04af4b368ddaddc6ac278db11b682bf00faa7a2098fd28ce0b0d0bf59fefe1405f3082a47bfc852947a687a3bdfcec718ec8cf5e7a38fbac6ea19e6583272e677021840c9a70659f69de91fef9ede1acb7c2917e7fd4331457c880030b42e00318d7fc897a1f63d075ed18977b2e4c6f35fb5f881ecebefcf993e55a57e6bd8079380c903f1f67bd23f227ce91f8edea6e5d5a6f1e0ea86fae01d085e1ecb3002bcec63dacb3c3d97f618af62f648ffd0b5338ef88fffc173a9cf57036ef48f69887b3efd2bc23f3fd5f700f673d23cc423d926ea128171447c3d1b07f40f698f7c29423fdd93f60bed08bc2fe47f7608f7ad48f7d72260dee72f32e33333b179186b907680af67585efcba33d84d9c3dfb1f3a37b520f5f48f7d43cfc2146ba677bf848ba873e840f37880ab007c3d7b6ebd1f1030f1a23f878ac8b42bd5501980022285920ddbd82d725cb35b88358b56dc3ba2836df3ec1a07e41a4a31a9a27433b0801318b49c742a76479f0ab00832cd90d2c0f7ed50eb4470086e8370760b364e3855bfc667c99ca2a21e8e71d8f10c2d0cf7754ae03523dd0f6da546daa8f8fb9505b7fb75637118b392b961ddd63ab3a76a93ae86a158da2f23c6786b92bc2a715e0cb30197d0ac0e635cda6f37671ecd299a99b6e6dd4a6832e541765fb19a62b5b11f673e4e0b8f12e00ada2560e2d589d0be83701107d5361ab0e848d165163db4ea7625d14d5a3ba28db7b17a55bd3a0eca26cde2a4adacdf0aee511e2cb2e8a6adbf6ba0f5e6976fddb799aa683f3c972ba31ef6fb270ebc683540c3ab60fbad06f6ed7010e19facd1c9c2ec7d6e1d8b0ac361d60d06f7637b6cd87ce069397857e5367dbae860dd24d07956c6e9eeb80a6eccff0ae29d96bdd0ad86b308ba8dd0d9ef4a8844db825b5543433000008024315400028100c87c402814824cf945dd50114800b6e9c426e5a301588434110a330086218638c318418020842862052a6ca3800f8bde78943c4442b92bb5bebf424cba8accf0b91da796eaf98062e6cabb340647b0be7f24cdca6489faa30f9eeaab8af9fb01443e1164ab0e0e5053c2c638c0a273c5afa36d7c5a13e09ecb3386396e9f69cc98bb7a84ace6e629024686c302b19dc205e47da530e24825d1cf183643821f53d25d4d4a8878f413045fb70d95fad7e7fed1707645295426efe037d3bafdf009bf1632bc5730df215e6b071706a80c511c5b663f4adc1d97625cc42ffd1c3858faf06b4c2d1461031162cd39501c440f6db593189d7de9b653614bcffaa5261e29f739eaadf2484695e80ea2b451e3adac1b35a3fd1c641f37b8607eeef6526e6fa71fff630b6227f23e385af80528747543e6ccc5ac57404a5db02c072dc36f55fc957aefd7df1fb16da19b49b2518d9b596c121310c0918b7d5f1e12c48a4d3cfba441c00631ef0d06fd70e0817ada5a99c3c01317b1bc4c500b05265fc55c329c31954eabc32b9bc8022f66f749622a4a2184d86f231d06ffc0e46e163d060e6bf01e3170e4bc6f399b87a0ed28dca82910922155cd250f5314272cea61a9c7dcda9b41a4a62c940773378cde7540da7ea5b7ca60e11fa1f395f8e1c40ea8bb10c356831a70987b2b00569486c416be472d38f89b5e162058c206375ff2d64c0f29db0745488044e603a2c8cc10df7ec4b7201ef2fffe275fb54509b61649b9bc05621c4b3a0ac603d3f83c470491f6af2d67f1c614a8aacf73a493f069d87e9fd0bd825354afced7283b1782184e8f0af8fa813c15699e976f9db20f25a84241a01add101738317633cc27bc5576a132d9b99546665ae581906e7d610749bbcaffd643d1fbf7a1e92f9c54fb31d1170a4e6b10ce1eefacfe8046e515db2c9a15090db3d89546720b485eeeeb88f0ad46dab0c25f8bd90b5c5c705d76a10bf62a37771dcc241f919ba422a00ff0c4fe9ab2a287a61fb7bfed3a062d2f7f81b9152ec254279ac14a10fb122ef9b9fcbf92e8592360f8b4686c67822944868f23abd1ced068c616b1d1db9a06ab5185e3b9947b1d514c8f88b0395768d9d78002a8c3bdc1ddbc7f9dfc3dcc5b72ec7f3624da3cd36abda4e1cd0246f8a66c5eaf17cca87da62c8f21ae525e52d05ce0155922793283c02102995144227d928f60183ef321d644619e12a7a685f50b2764b5e1a21fd6f3ee458908f786bf32deb7e25e815fb71d5f92386ddbd70cc771ca2f556c6f96a3e2cba30db1f2d75bb31c5b2723a1002d894753c7c9157a6fd52c87a9b9e38e79e6d69e9301e9fc1a6f858b5a99c462b353e57b745514881e37743590885012e0d562bc0f85b00f5ac2e979215052534d32e9215afb5916ae491f786d311af95afe33fd48feb3c49fea9a049735cb2e5c7bfb2e8799279712cb1e9f7ed3d9e5fd8d0bd24be0594e31772a886e3e122f8e2d40b232ce1b48ddd2c7fc2b5b8d301a1bcead33dd0706d883ccefa3c550d0b380934b34f35c9cc297dae72e8448e20dea44ef6e05e4e309a87abcc2ab0e843058332b187a9f9a9474f3c7f1d80e8feb824744dd67de8a409468e097d2438dc608f65351d757f08cf0b5d6ba3a92ce927382212f48e6b3f300b41a8ba914a66d53a6509583b14d90bcb06d9de585f0e8a64fa722c1b1461c1a66defbefce4709d4aab97394a2242eb5e5455b9b0c8faaafc44ab7c5d18aa4886b80283ea121d3b98b96e893918da223a798723a3cb3215aaa821dddf349d0a6aa621f52237177c20e6ff798a2f937f27506425256fe0101934a152c907c1ac2511826f5b3ef4a25753b39eee0881d5a9488b96b356260b8a05c359ea8702a07de596d8e39ce76e2800bd476e8bbf9656f96fec81d8be7a184889c9d711555b752f065a39be0b99e901f928d0063888dcddacb3b2dff6c943b0ec455652b36835765668a21b22540cf765c4166718508af50ab430cb8b96980b6e69464a19018995a794041aee3269e8e44df47b0a5e041fa3b9b0e79767a34eb31c8dedbbaa9c5e032de0ba1a1f31806126f73a4d49aa5f325e707917a2e56fd060e845278f1dc9bd8b0dd5e059e004002f1157a32d96153e20e7002bd6ff0e865a473ccf26bb859972c5f2c000fefab55ad9f1b771b368738abf2665c37f2c3dcbeb8f7e112ad7effac71e6410a6efde59d4a2a985700638a13ca12e310cdbb30a2ab0a714f9ab85b58a0c246b7137735d8707ed25c4fe6eaf1316e993ca0c2aec10585c27614397c663a260f23070367711d54493182c5cf110481af5bd3e85e4b7f4ff7e2f5c37d62814622b4efb86e618d160d37f8ff849738172d3d0cc0803848aaabb0ab094f045f6a33a76920da5972e9a0a3a1194d0e8fd090744c07cbff665e3a3f5cb020aa464f3339f22a4baa248441fedf403753ab9f66e8e1707c8ab7e1f1d71989af4f595e737db018d5ab2a1134052050960412781d4859357731144cae6e826fc82668c916d8c5c47c282e41037c86d2c70a64afecb9eec50bda8f740b4728ebed4e821a6027dcf6dd4dab570d0aa6600aac82a7010d81470a28cc19617fd5f2f96e0fbe305c7e2de2f86273f1181c7c2f2ca44ae3db2ca5d6a4c215c301eb6bee8f42036c12a13b5e5d9f0d31485a6b06fa5f537d4c2bc89350e2949eeb4d1cafd0bf08347a4d1363a1f9a893a4a88315ec508b80b047a81e43ce778990e7ee482cbc342898e885c7cec01235e10ef4e3b917fcb09072301279b4261dc88202f8b2c48b282c903add9801ad176fc5a5221d40e97322a0bfa00e493f69b9d66bc3d6893a0bb4c921d63cb3ac71bfa5df662213e8eef14066c590632cabddcf0f0b9eb6f9f77f249740e80b2de56c8dd7b30c6dae420a33c3859624aee4ce1f6724064e3fcec0de1b53290001ff59ceb88c948d6053dc87aa276cabc87d3e59af05a7dddf67155bb438095a0ae71df9385fd95d2b9e9c929e135d34fd7df74ab4d23a77e60c25ae1751d47648188320ea026cc890c39ccce0f5678cd4ffd3dfb7543a4b6dcc90a5fc2bc43c5afcbfc12ddf9f5caf6c370c108055f60bd7e6dd17d6d5daa0f96fb3af48b665e8609f77543fbbd0e15c1eca128ecf89a3d28977498ad21c2b57f55b2a7bfb0c6d74889443508a7d181150bb7305ff3a528d9ff172b2f920f1c1847ae417a2631df5fb52fc5d76a20c2ed84959d44d4045e5ac7c9b3b2cc8cd3b3611e09cf3dd4b357df06a73795f7c6af13e99ddbbdaf5ceeb17ed5e2a6c7ab3c85eb0c2e53b71eb15d102e18ca5936d4f3f640a31bf3f99f903cfdb0059b4387af289a3a9861f5477986bad36e16847ab740bd23d69564fa00ba460b7c9af6494e43d2b406caa174ac10d673c85d9d65aeb44737abe9ab7a92784bbfd186dce8e7c5fb0f7cfb7dfbda2888d3dd20d1cb6ddad728f8b9b485a0acbe87d0f7e2fd2b85aaf43445f360be5a9fe8e680e5bcb33224c01daa92e83a033121ef590f29f8a12a16ad2b8884bc773dc460875459b4ce2092e5fdf521821d5015f175829894f7d6860cf6501589d60d42d2f1005480830065fc97b8e0f7f3ac3222536f23fe95e000147886404dcc53c0084379a404ad44081af0a1c095be62b2053b180ac7b16ecba86597c4b364a912d0786a8282a6fd0b207e9372d07808e0c966f9de7f491972d2a29d12cf1667058ccc21ff9252d865bcb9c6e5cc04dfba67b4d0e07903c55391994a628741860d7fb51c7a0bf6dec24b76d8e958d86f6cb921c6cdf3d60b8905bfce811d6642acb88ef3a5019f4eee8a2b58b0d80ce1dd48fb40324bedfa6de35c2b783bfae47ef27e5c7859ad5e5a177df81161ea0aae5163e07170d233d14f0c14bf17a47f2eb10e9f17e8038eccc705c3928a73baf8a160bb3a59d757ff4837e7bff2e2d55705e47a4ebb136bdbe54f74e862bef5836387405d3926bcfa7ff0703bab37569c5a6d8b22dedf26ddb5d39e5eb13378d4e82c2e6cc65abe02c3f8656550bf62f66021c94b382e7cc47abf957d9d3670abeec689333bce3188ddb70240d3a56f357e2be4f09ff98d53c00c66f9526c6ac50e9b13aecb77be15fef2c7023e4ff18ef1a25238533901dbcd0c081bde62e5457a0d1a697bbbcecdf3836f8a0b124a7a39797d8100772075796caeb99378d6be0bf61495ce53b06617e82c28920f1cae219b5792b1e2423bdc1ca8373b30f81fb0c62256bc0766cfdcf180bbb511a6cbfd0db00437c612dc8bcfda7d5c5c7372837454d678cbf973c50d38184804331d1da0f223ad0800b2374b1cf2db0b0b5f0453b58f0b88f415961d4cfa8e69c77e77956e104d6d85c0964a776ab8d33e3cbfaa9aabd27d95860d7388b7565320decd494cdf0eaa90d5c879c5d2371b0fe78aef3c7589b55253b790feccf48feda8e7c40f363c37281cb9e42bda0b141b00591a9a3a95162e625cb7ed385d2e5b03683b5a01cf1f176d48c75b7860ae3902a6e01880b90df9135b7e6c0fcb810384bc3899b5fceb1f038ba059fb960dcb0ea8bb8a94208303733cbab26c2a843852b2c92e5008174a65aa1bc5259ccb26a8fe7af8d04dca143c45d4d4ca9d2c8474231b98e0fc9ede412d0c9b52885aec908ab03660ad212819b496b6fb6adc1eb796abfd34639cfa3a5225465c7e35b2f5d2aeda91a04ffa980401a7e3d5657ac7bdcdcc4e9ef50f23112c6d1fbe86008e8e8c1aeffaa6e0746edce9c2d5a5604bdcf03b8790e27c8ccb05e810924003bcdd3981037509b7c5eb3dad734520d043cb4581185286140ab987980ff2622d64739c4766fa07fb019ac718d9f773cbe11fb6d3d5561411c2fe5a6d60650672b7244578b09ef0d406f0396b24ed3384f045b0a11b5f266fe8da8b4230c4f8fa554bbd53de01a8ba240e714d73835bd17def54b46c2943675843c41f91dbfb224b07f470c233d2116cbabfec4b7a988d475af891040684c7370705c1d34cdb1c3dc3f635306204cabdeba0fa4b92c292985c9d3501ec0bc15363d5f3a4967ef236631b62c510ef8b8f0c43f1fd8402a34e277328e08a9c17e9271f7a9443b795481d793432c6a88e81f796f8d0a4323514c850584ee70724d9c6d962ff9a2ef34b7c0f9b422be336fc325970c9b9031d982f976d2b96a6ad622f43782129228d2d7951f36336b1b970d6e25120bb972092b2c29aeb55f6eeae9e9bdfea1c2d5bdc68c53635653fe248bdfeaf185c624ef2c9a0d1b8802af3d990302faa8e933606fb48a0f4b6c32404f4ae88ed90c4533afc733712d3861f205d7047788e3237eff164216f73171d87214cadb0cfd0be7085a5f40379c42e2d13424cc4a25954aad86ce58b849254d2cf4ac655c93758359c22a9528bfd5227a0784b418b695099b76c6bbbad66cc0c4e7c13b098741a50646eae4fdaff07c7f9a12e001553bc9038d36e0a1d78d99425564c5d18a4fcc15b02e30ede8a2045ad819bd2baf366712412d70849c6756d16b5017a129b7bb7bb7255d1a99d066f6b4c98a8070f7dc1e3680797374016cba1d36a92283b594e3fb8273cdca458546ba143de7c613629f8d2ee6d2458faf130800e33cce7a5d3ff3245e499f038b6867e55459366ab195a4ed5a9a6ca85a0901360c59076ea81ff14ff0ce2670f37df24bdad620798a9f94ea2fec7796146926c9983ed232f621047850d8e3b44386651d2dab3c28e19217a43a6a771fef2ff568acff0e6396a92bce5f6bd3bd02f80ba1da007bebf80c34976d6509374881403d488c1a6d6cb2c3c4cdb26ccd6b377ccbea93f924eacef38c6aa9b508fc48afda0c8a638cf5a4ec9256edf164104755e4eee989762e17f15e472ab135a21341e14386b1ed865a08be3989dc8b5cb5757e6e3455921d651144c2895e344c4482550553531a93eaab515214c222b9f1b1d88689b5a0fceb62c5e66d5d1250d0c010f644571d51b866389a162da7a0a19ea155ef6f81c5ab6bb3b0e209d03d163302acd881c46b9b1e78871cb1df566f28c24ad1492ed1091927da349c5c85455f4447c47ebbd3caf59389c12dfce60d13db8a82226a942475c9b961774b435ec632303f60c328cf26e2436cb48726d5de0ada743fb74008cb194d1f86b4c2f21324a56f8cbb9e7688266892dd6dc5ba675c9b7ce0e7705a4eb43f20318062c128d1f8cc2006d2eaf525d8a030a468f39394ad84649fd53d68b0131f2bd0506d0d5ead66250ccf85c72362370a18935e20dc077cefcd668e3c083d1fc5cd2b6d9fbec17a4c3ee31fabd9182be7139cf46c5a429064e1cda12e26cc3527dff82580d39fdc4fbf0f9d5713536384462c42550cd1b0044e8ab80bf7d870979d7c5147c64088cff00f4cfe656000eed0e8648f8788df38c36d756346226c11bccea5969c33c3802ffd26ea928ef03e456f3c389fd8076bb788b2d53f28800bafcbe55fc62439b4f105b79eb22ccce296d0be3bbe0e67794993c56d677a6456b615873e6fd858f5da925cd0a5929b02ac1e20c25c6d129ca27bf86e04cf0b0293bcab382ba6d28f5c6470962053c9d149d921d1109caae9ed72d247d2c8e9379699bc3f19f5954e9e547a9a0e176da59ad806e1648bbcbc01024bcc25a86a9afcf80b740590fbb084ed3a92ee8e29a3dcf03cef94543267fd46a3cbdd35a4a89aea3f52da4a5a893c097579688672ea4b69d6a0e3961aed4792903e6cacd5031e1e7932d0368bd13e0131f288ba5748df4d3b7757f22235b68e22269dfe6c0fa0ee3f32f948dbbaa2f5a4244fafa1c75bfacf0e425e14648440cff16bd9c035856cd774eca1220af4f12b79feb34db39e84c52eea8cc00758829c6e715e1bce864d046636d9600d82fe3f7d20a6a1e2330cc2268a3cf3e174c6d9d5e490e1e22b0f1a62cb075bf9e3134e6456f67e2949177a84eab8a99d32627460503d09b84a9f73a7c9093f20a009df25b4894a22eb3209004a8119b238ada758c9aa2247361ded8b724c39db2f59741b2cf209f50d7e0ff77fbcd7b63cc55f7e44e59ed5e03b350735cea318971b5c2ad87987bc8278fe365c6c0a0bc5c64a4d292046b1aa14bf6e12c2d2e0e940eb397b79bddaa51cc72403edce26eb62a0f9632d8a02c4bf8f44a3965ce9e7572833cc5184e54a9025fff3ea45cc23ba1d73c0633a20ad91eaf68ec4d7864a989bbbbc67e79aac2ccf65bfe26c751416190b9c340a05856aeebc30aeb82af3f7efdeb254f64cf1fddcac40dee9c85bda1aeb9745898af10de2ab328ab234de5128134446f979cf050dd839d8222e3011dd094ce49cbceab9bc8729b464ed1f17799691e53c8f1404830a23064e7aac253ff3ce015503fe07099fea75ec827fd7468a5ac20bf1a03e22fb42f7bd46ab6478e93500a40aed2075e717caf4ebf4e5bb4c87fc6300382aadd0702e6085f220ac098d2e24160a6dfd51f52885cf7c71301e4574c9a7182e5b2c770841ae7973e15d8aeecd5549d700b28fe142479c69e428fa9c40986c5b1ebf683733824842740d17834d5643f18a2acd0aaccf905d479722adb1c5403aa462280a4ebe48160b4c59262b21de6102c678837045e1238f8f58a0c82aaea6382e10c646943ea29ecc49623ee405374b78f5a75626b29c04973e986724ab4563b9a04a2a0e5085619159168731f3a43beeae325973df8349b76598b90b6fdc9e1e4b3ccda57aafbb59d173b5bd9da28ee5af8e906d27a7478e962a48a469d95e74766ed69361297401b40a6edf866b38c897dbc332796661f7d8abaa08a6bb6660223ff1b50a369a4b48a02e1c6ef4a25329f1777e66f6ed4caa320564542467da232c4821fae8b40b28463b772b4da623f8879a369cc20211b3d0436436eb83e8c07514c7f849809333eb8bb474537cb621b702b1bdae1dde6bf0cdc83b000e35dd252eca776b94ba3fac6bd73e13d436024e46065e0d8ff3091d81c12e29c7bde435d8632dcc93c5c7b1f371bb2a3573ded81d1c1d95f2f898cef6e74d748fe46a5d0b6648684f8f64600901c973170e73caf5ed7f7c6f70c125c02650eba01c58ec53b2219498dfb7adf59d8d44565e54813b382199af6269761a9049388922bfad4ee47add819b521bccd658ae01214e393009adf572ad1aa44ecb640d3bd35ba98bd9fd2c0616239f59a46926509381350dcf62fe969b52c17eea9c3b4cce4d938055f5c689817658345da7cdbece5238e3433f45518bbcfcc56bccfa44f9725524f9d0c17561217c77fa8a195612ac6763393d0601efa2f51b56664d9aacb36ec815c988770996142d8b8401fa19f48e3bdd63e1fcc18b47d987b81d2003bc96c1b8a845b02e4faa69155707fac0cdc3a2698373fee8c874aa5d9ccb790b68d65493f2f0c8d17ba4288c2bac7e48e394d3adce858888614ab46708a2a45d9186ef529c0a2b6e4564fbdd1e116a20bb46ad8bd4c217dd3aaae43a700707b702f2bb8f0edc0d53bdbb3d5ab815fd5d42e547dd79004ebac82420208a5038752efa29baa719ff5ba9c2a28dce746d7547e618423cd9e772f8cdd0a82aa0d9d6f3f84904df71cf8e6e61a64e8fc2d249af8d0cb525e6073096965e1ac4bdc9f6ce9d60ccadd079a801f96edab2f71547d957c5f316b99574f8e8d64d9fe0977b3886baeda3cef2050323c3aed2d1da724fcacc5f93806f271635def59498ade023731bad642c142d0a565c4ababd708d74a4c0230bc6b8643a2d47434b2cad32151f1c661cbb774b6ff6eb92533c372a7b5ae704189d14a902cad4b4a43d2afdcec188cbcc9f305e4a922503832c4be341919005bf34c4e9a4037bf482d04463ac893cd58f6c54c8694fb12ceb3b1a1514830adc51b4daa208f6fa955aac037fd8d005207389603ecf0ad12e0ca204f028610fe69eb17d3864e2fcf71c99b90a6ed9359018f572f1273ed3f6287bcc0c7c9215e75594a5c9b197208e1ee339c13265836790193f91fe719f2867fe82b60ba165901bb5abcebad586ecd8fa7daea27035c32c01e643bcdf6806fc4c87bfadf623a8e51c64bdebfc36c8be356f96bb38accc08fc15b7a91044e8f7dbbadd009dde9a1c5d11b8792d24486a32f885385dcef1e09fc541c64f6407ae2bf33dc7f5b63c4c4616e062ed630362654024b72505f5054d4483c02fe0a50d57a60e1154deaebdae23c93e3b98d8f8c190a3ea67c54be8dbe1eddce3f8b8d0e7b0fb95d475793203db9ab0c2ba13eb00dba1ad62407e1291340bb6283cbe99dd45eb013d8dd6f1771c50924c0550d2f73c33e1197244b208ba008691b5b39b3320976fbb38a71e45d6b1b777d3668635b3ec8b39ce0fcab7099bd8ae68790a0afb235c652f3b7ec897c037047e965938238d6d7cfceed8d8b35398c778834f194dcd3c107d53c5831d8f6802e4b60a047923b8f0e37daefb879a888f365069f413450c7eeeb47b658c858a8415767655aad3a089ad1eb7789ad53aeaee4be528a61dae67dd64aee3232c3c199b9d2c4e3a1bf33ced1bd1e31bf49c9426b7272ad9f2add612dfba9f843d4eab7211c5331d8dd4723388d204fa1d7eab28f11d2ca5197a1c94045b186edff6d6ba9e3c232c00ff0f5764ee0893ee95f6e0a70149cb91227aced19f1b8d9ddd3e594bb16f6b82fffed7aaa6acb14f44b7596764a60f2d4a76de97ecc36afddb92c11f207f043d0ba4a464d04d74b8e667fecd99a56894494be2b9d14d2d810f5e121954b052c2c15be0d3b9f7f5c38b1c048970ac60cfd51b24a265e2a5e676450d8801762304155032632b92225872b488cc3c1f17bc25d203215b53421a125af19289861c1a362c29de2a0b0a29ace647ce8f8ad0fff15ccb93e8103080c99b70f9716d836ceb4fe9d497a3560a654ed27e70c7f52d4249ef3fa89feaa7a67d685dd434cd8e393cf35c62742a6435211d093b932a763a49b27382b70b9cf6226ea3bdac49fa63d5385dd12d366e3dce280b006332e1e8c88366060baf0100f1f504c1290a074fb767bccb2cf190e8d9384a60bd5ad1fa23872ca806048377a53114fbb70fcb4c2096f1473efb78da1de6a00d43cb665847b4f119743e93772cd75c8fcda7c23e39d5d60c90d5de3b9ee0a1c8069f7bba70d73f030b8307f4c4804743a6683f835e02cc2e4c0655d916f627d5872385b845c7bd70c56458ee94c9b9dd7cf93679adb522dbc4732db0632bb8c5221f898bc6ed476a6c16727ec981d51729c0af1fe02083c833462e9b8418c26ebbf75dcd3cbfd98d5d9c516376464adaa3825c28787f242eb02296c9f3e56803e86dacae0a8ff5869f9e94aadd2f2bef0e2691555d21f2b2198aa94e8159d925a2878c1af525ef294081173e40b2975cc40f30a593abf1a3717a55ffd0715c3b85fcd07665eb95ce35728e738363433af94d2720faf1acfede763c1facce0de37796ff1165144ff9d31ede6d5008419e64f3cd316aa9857c80fce82eca3323e52f1bec84cf9e8570fea51c29f8a243470adf24a78e7963274aba381457e358d285a6e151630a4efc3723fcb12416e4edd4aa41ccdd57b6d5d44a4849f718d1e842d52ec34ba0dad7a7b563a2e1dbba34f573927f02fd94244402ecd6bb9699e07bd205878d5da7deecd45887c8dc4aae2604f9c0dcbb068eb64902c4afde504a7b148045cbce00eacd4e19cce2bbb610dbc63124b836dc87873ad0e120b56c156f52574683d301800c073f14e936d4de20ebcc70f082a4f198ac49cdf2e65a056294e9dd39abd72ec2155de68f3e8f24f242e8e75ef7ef7663c5bd1cc6b0c3c96d7dd9ddbec094b5836f4d0629ed9d71943653226e989d9fc8bd5f9ebb903efea38b1d712d809655aa456a38be64b41b4020859cf0c558117f77398e6e5793bf6ea2683dda630b60def79082f376e434d66f48fb1ceda7823425e6069c0a06f108602d03d2ab17fcc158f3f164e4857cb49b4fc121956e3a29d103415e364d583534a2c5e567160e29c12a25278759708c6b87f0b1128058d7fb40841d19d3c18e763fc5db189857eeeabcd3aea561a00ebe4a3ea22d0e9cfeff1a1ed74fcabbe655a5386656efcd9b215f84091b333889ff87e9ed5fc84b37bb4a2a0d8ec7be4d30fd42a9f68f26e1afc2be5ff3d98418dbd6666f6f35b62524a040c1aeb94ea11414d09f39644fdab56f9d27defac2d1b25654709ba9618230c368e1f440dd5353eca3b72a8cf2b907e7c0008900361ecc7a05301d6c99079e7e9bb5eaab08ac44a409d2665f6765d0dc5d6762d78aac361cbf3a8d5caafbe2a07d3d22fe14bb380747d9f290621c8c179919484793138d326f2435d9949054139fac2f8de68d85b511822dc86aab7e26df3a911c6bd1cca897a6ef36251004a26d4de0f9425f15c3bd3e1bf922b2953104aa74b7826a4d5a61c5553bbaba624d7fe121a20f1496dc3c52ef981cbd31ae1d4bdaeaf31d8bcc68f91abe2584cd9fe98004f0aeeccda04cf23948619bd54a3a524a1c5379f343a661efdc269ebde74398ab620b3a1d0e06d99164ca5d4590357abd8dc9b315305b79f73542226438a4a38202f4cf2d55c4d4eda144665f71338a0eab07e8adca6fc4f351eac75c0bc5a723ad5214a7a0b142779b2a2cc3435bb13f4177e59b82f9cdc7ebd8ab79d480df72be7219798704c98fd101264f95c423320483c1502493598ffca5ea0e96d7767f058cbb4aa7b6538c695a044131899bb958ccb1cdb85f134fef5047faf9613f43014e8d7290d88d37714df0694092795ee54f54e8dbb5a068bbffe3645b11269e1c5b23ac6f2819670ab85fb6624258140a3b84a5c6431f7a3fa9da3bf7f710cb8c20b5d5ff197cbd28aa78fdbe42fcd5a25196b6a750b89727e1d818e54fc32086c99e9ab5de8ca8e5118776a9275ca40f8e5c1a39646a484ac0f9a89769bfe5f158e8e78a01e2ba18b8e307b81c7db61c326952d96f9b62cb8500b561d455422b7120a288f0303d2a10684c6ef1cea76484d43601c2667bf7033c812a908aed05018ed21fd131448ee892b6c7e3c2d474dc4392940e49d66d6a5bdaa6a8835ba80908ca59509057b0336536307d6a83c6654c44323cc3edbb2adc1ee437aec509ed6471f5c0c1368175f6c8442a396d65bce07d66733f735fb5ff2f3ee638b53daeb0a9cff1744f071cd9d708da10926727021b7352a09ab56f494390858c90783c9e1ed8a5e42366d975b1eac6f26fd9d5a2949b26eba5e306441c1388cb688c1b4c46f8adf2db23ea285826b99bd22c63c2890a11ffe9a50554ba9dbcfeb5357cad7f195eb2fa10056f6cd9ca043410e641923a902f87659bd814f19deabe9c2f568043cdd2aeb8200e12daa077152d93a2e62fd848c7b7ed0eaaab0523c70011fba6c70b5bccc7003942d57c7ec57b64ba1d3fe1def16de0babee2d2a01667f0126f2d25f39ee0e2f53983c62ee5aa4ea17063844fc7a21ddf7d6d6ec25e9345f3182f415f8863541e823b10f69d83a87ee84c13b11019129c4a882b9be912cc7a569e45d08aa1e0d75916196e054a1345f49aa83f503a31f450cba3fcb5c2b038bb9dada7e68ad781adc61f7640ab851a133b63c20f56b2c51c5ace6450541af207d9ab74c69e0fe15efd06a4a1696f5cfd75d1a584250f55e9189b47a5d685c730da4ad030d37ab066d20846887e606a8545fcdcd1c1042e8af437bef5f7c53e72739543eb0bf24c3ef0040658e608f641067c5b559cf48b7110e184b514bac753ea36cef8ae84c2d84df0697a080508a6e70ffe6fcb42e1f275bdab71ec66b4896a73c56afef56ada7f352ab5215898456380bce36cba40618aca7fb0c14d040493cf2b629510c99f7c277a3727da85707efb859ad5d4b26c4a270a2620a39e577fe09205a2ffe82932b5c483533384267526f3ef469e4d82a2d82642f7b90c3fad74feb0bddd1b162a1f9696af939308501f13a89282a8c52e610c28a71e2d8287fe0c7c6605cab52287c08ccc026af5e0c1574e48dab382cc777aa6670c7f8750bd3b7fddc1437116d558c80811043c8dee31909d85bb2131022b5e6249a858d01286e7d44ae7d2dd24fa0e09eff7521df51578cf15057826cb4c05264a694934d5ffc1df0ebb9de7cd68296c14d824c6752135d43c255f10123b6c18fdf248572a66b3f85afbd168e85a2749647c15f11c16e1af864771406a0571b128865b84411b84048b154d8acc5bd90c0860ee57035640835f26372d2c0ba3d3a1443d5070cabdfd8b5129fff1a7e73732f6912d947ca1c1b1ddab096fa1f26d90f58c9fa3b1f159c72762a142b6a8f0edd694020c33eb04c1e158aff1303367816739741a8b506ce79d215fc254bde2a06785a3945512f4021c7ba44508e18602f7bf64761695477bc4bc40cdf0db2cca700327e3f8e2fcda1102e4b10cce7280466b44f399560da8b44355f26cb212dc175d1dde05cb25af653658c0e3864ee45751f788eedef03f183028edb53a862bfe527a928922d9ce65d529eb3dc9fce28f75d2292fb13d21a099119260107b686bd1d4457c8eb08ba26d0f7f3c710769f901a3f6c5c20e4ec97a7343a328d7d9602277a3c3683d978bdbe6397c8a648f9cbd29302a4da63a85fb58e65c724fa23ff144358cee24a24f98e84cc66f9a32ef9d5a873bb2583261df099ce4d3db3a1f8806840924ebd0352c879b38cab96522122f9ab07d3a638f732640c5c763a8484194d772af524bd7b46c4cdb530a0012e0d57e96c7cf270c3e6aeab3171b31358e32599af6e02da741f4aa76be19f0bcb920d2a5f01811751ba0778fae509870dc774f4d2ce22dcec2a1cb43706624303b1ee1106a74bb7d53483a9eb13149497b0057163a2610522ca123c99f2d519677c64e2b08367545c9f712eb28b03ffa0aaf05a19d0c9d8c352d571bc5a95f7a05b40f95ba0947636cf89d515adc947cefcdd64b06c5e0671a03a1cd3aa485acff5a65c9d01622c25bf65133e98aada16e5aa8eac9dfcbae17936835e2b2d48bcc1a018cb0d3fcf771d5b0a5ce535c07f3f30b8a491df450c49f186cfd342b7c1098293c003d2d67ff3fcfed71c5dbd97f4b439891525e40302e4e0986027819213e828106659bea58212df3387fdb7793899260a854ee88fdc47e8fcbdb1ec87eba504ca6de3f29239da68b937941e3f7063957b0f4fcd34e8bd623a7cf4493fea060e1432b19450e6668d2a36a0c349fa4672f0f6ce879c383cea2b85ac2ffe89121c8fe86baa62f1a2513b0ca236bb73c31ec7266b9f20f374c059d9a55cb57b2af2fe68639b141721fe93517b52d578fd3fe053b0e6fc9e39492902c2dad10e31c42c38f9d3c9aa6f27080c3c2896f0a5a7cc2602c8fab95160f2efa92ba6590a34269bd3b3947a764b550031f9bb3e77167052a6034a0d50663d5dd36b3034968ffeb24843c050203620b15e3936f7561bf88b88c0f3050eb1202222d883590652c44454b21bf8ddfc285b2b2909f20d42366a9dd548500857002b8590c93580f3fe40626f2bafa667122ca372a7efd387210e2695249aeda02890906ec7af9a85bec28676abd189178214ff9d1ce62e3d57aac95ea7a6b7cb8c1a5319fb2fdee98fb6dc6cdb59160b22595f204dc2a135b2f72ba64b77213b4fc004f7852384aa6382086acaac242e6c5078adba803c9eb4b3bf9716b71272f8ae69228fab09f6c41e28990b564b83645f6770ff348494e977d30788edc36fc76f03cfe6d9ca41e7ed4f68315741e1cdd07396393501ec31aefc2d3309759ce95a8129c17bfb1d165a530d8ac948bdbe1b59f6cbd55ccdcfea502a104c69d902610abc3b76f8481c77d1110d1ef66c2f49c169af7adad94cb28dd27087431532bda4a4cc0f77cfef83aedcec62ee8d7fc238342ae9eb5ac6982802161c1c4513a60f8eb692598c4f090db692dd8f5916196c0e0cadeadeef4fc1a3b275deb6296dbcdc26f34229cf20461c88be6dcea1feb58ce6f54c61a3abcb52e0a9b65a72003a725f38a380b1fa36bb28ada0b59ea62d464345874c25b6d6933784baaaa9db9a98884019690d04335f9dd340f97c121e4933e32b314b078413ab9f00f310e4f58bc3a710d3f0355c9c088870ab1f2b361227fdcb516c21895c71d8b77c33f12849bf531b19fd30648b7cf67fd70dfa9362a2aed39baf792467c1346bb6d4f8148a882abf88e9335720be5945d6957fa1b5fa4be33ec5a35325f1c4db973eb8873f9e14cea1229b3cef36d97d6b1fadbad350462ede4258aed93730810f46d8e08e8f9e6e0f4986219fc0a9c9273e590265dfcf99b1ca8975ac1241c35c973cd2d4a5d65d2ff2f5c5d9f5be248150c03f59bc3b4f8c964ac1f0368fde5ec391cdc43a8346d7d870db3259800d618956180912a043bf9e846f205fd2b468c66c046598af4836cdf99c05ce758083f5cd50db3a3a15afcee24447b6d488e31b8585c4e38e6ab8cface1e21738d96911e45df5575368e15acab03fcda7f080a8893a7bf19232729d5e01bcb3b3e258c168dd0052283140811afe388c6c0ecd5698b3cebdad3646a713484e541e35c12281ff1ab5daa0177b1814292f9c608232bb439a383144a2e5f0798d42d68e2caec1016d91ecd3a2c93a18ae8ed64bdd1b859b02af14a376eb217b2746530881398d56ff90bc9d0e35891310442fb1ba9a0f7abe54b717542b02c34ea90327f95a9e619936459ba82a3af1b8fa014091471d3f0c91e60129346b22864ba2ccd29f33fc922fb1defb786cfb7915c3b967da43ae6dd9b767aaa7de2475c2aa108c69c739449c3f70d0efbf66ff64045b96f0b058be18ad8d94a7895512f3e24b4e8e652d51159c5a1774a192f0d63af95dedbb86202a0ef4ae4880bd3a5539f167c5bf9c9407d1d29a4c406c7f71b937d12b8273ac1bd6bc9cb67f039ec459defeeec97084d139b7b127b97a32104fab8e8ddd083c67000d56a3a8180997cfa23601a1bae53b9916ab25dba2e275fb3736b407a24e826897f45566bef8df969aa66fd1a3c4a062727b7f9117d8611e9573ed1e65bc5705b13f1c8718ac7ebe22098be6017f8d6563fb23c82693c0c04a2a6d41c44c64d0315a101775bc4c1cd75b6c1a780de77c22a8b2906282b72cbdd68cdf4a01ab2d52aab240e13b64e37ec3eb6860792e63778189aab2e935dcd7497f7af2d8d26254684411122bfa1c103a758810d28f8f0853f4c700270d2098909e360e6363a9806855107fcbd09e08d1fd08e5e64d084532fe04adaea91d675c94e07ea6a34046477f97bc165a009fe1999e62dbf0f146254d459286fc4c5462c85e2a43ceb6382c3ae83e223222e567e246400d29baefe43d3bf3c31b5e335d1d445a781b7e459833752006808803a4ef766fca755567b52e73af1cb57fb05440838f123156a638d2d35baecb4bee18aa1608d1290ab52d4173da13742f221e39f68bec66e3b50e523676cbdce0b5008aca494a205ff5cb5fa8069d8dfdf80bfd2a71eb7da9bf00be7da8fff9ac5b7ee9600036258ca94cbd90268dda552898c6b438f8388d327e481c8072f6fd0571721f2f26e66d352e9a41ffccc1984239363ff5a6e783594038ab674b3a3058f66f389814df0de7d7af491f4aa4334351a4b7f3cbf61bc4b7ad76c7c577eefb92f92d02f12a95682d99085754e28599c4424e6358ec05df1b6821817b870cf004035e5c510b057935acc4ff2f91bc8a59490c8190cd551a7f30314504a71cbfb942669ec674987671e1b8c97039c8bd2f0271eb481cc880a4e86bd70016d5b447f2abc62e00f525ba6f7258937787946839c857620e90e64b846b483d232d0f4b6beda67d24f830859b69532aa509aa12b909d3e8c36613f7b797ef5bd4495dd40430bd574df6dacc3300b8d21e0ede88ad048fc2a4c8c25e7ee16b7b9c57a20b79ecc2051bdf74daaa6a457e416444a9122c1e2c005c8cfc79c7991f6b61b81849fe2a5eb8067993c4e89f78062ba49aa4d57af86d4fcaec164394f3ddffdf2e20483326b9441b709b6d2c93c0622bbce6599a627f7ed9bfebcf49d2050a6ff36164dc25f3133600a6046369bf21652a188cd23bcb0d2e59a01606ee6c736c84e12b1c657949a84866ea9e63f883445626991611bf8949fbb072d0c9fbff9d0653153494f924bdcb8bb5aa54040679c764eda5f4b4c84750452373ba6e89cb55297eb928e71f933c2a5d28c770c67fd8bf6721660b2f7b8e19b0b3e73bc2756e7fd9d1099052e81d3c9deb456c461c6d71a5d222af4877340aeb6e79692c1bb72f40e4f94b8ddb97e641f07217fb12ffb7312849b6f8785ecaf7a63c0286a548fc5c72f13219b03e0a50e1157f9ba891aa80e7427baa80eb80d51030fc98e49b8095639b9508416f983f817607e45c10fc3cf87cf56843f00369912d714ad126762d064dd8120d97663bf2fbfb34ec48a0893a043012245ca4ce280af67cc6587aac1643c6329a5fbef225bdd7ad28fcf6b1835256c87c758d97be3d7ee8fde70fc9e6f5775983fdd85b0ae62d8b17d47a531a91eecf5b2bc0d376d622d2cc1ba4abcab5aa6504b6bddf79eae2abc925158b9c07be023c5b7dccd3b3db773f69313bd45a631ca38b03ede2f3bea46c4f9c10fecbc808579ad9ba8b73024fbb0adedb4121fc6f32fa11122f2d347c8e2c015931b6a1f13d612d1d2bf6fe4869b16294d84d840eb6057508b4d5c4dc5ba80c5f6f21c7fc3f2e4009e11e9c70ebf5511376105ed8fa22055fe29d40570528f3492e5f1147b0507e045bf2483ed8593239fb64014f7f7e6c98c372189e8ea09aa79631d0a379fdf959bdd30923aa85379f9fbc6b8a4509a8d4aa5d248e272ad0798cdc2bccfaeaaccbd3d0cebefaf3dd43dc64463815152574cf3f3bdb98c4eb33f22ce4129e59f8fcdc6c417719a309374633b55ae73d6ff10bb03d3a065dbb48d14d466bcdb465ac22c98549c67d59811a6b1c4976bba62fbfc7ab24e622112548bea6e2b9a54941614408c2cbd694c6b01c08fefa47d690527290b94f08c34261f2fbfbd7fdb7328592038ff191c4f7a6302ff5c76f30830a61556cc052394e1b42e033412d8946b7dc16a9722c22288344eb4cface6f99948ccf38309e2f089741d475e7ca5aea098dd2982ebc8f677e15c0ebf01c8b78fc7c6f6f1dbeba91b5cbc6671c318ebd3f895a86668ee24c236094554460fb9fae386fb32f17512f5385f3056da14a2f49e45c53d0215c4f3e9d03baca0d0d96864f9fc127ca5aa9df0577aab04fbc2e55e6f61dbc2ebaec7b63355f75026f9f8b16aa4b689abd3f4e8b6423b78c88c414c12e6fe1d1d26d48a4e9e26c8d5431e5ffa4b366d9bd11060dcc009f4ccea14bd0609b0af406d13b59320213bbff99a0ce09a9129f1f43f0be8f28dae95326c32a7b62d29576abb68f05d201a3b9855a5885d45103c9ed6d5ecb0ce4fae2b329aed04fb54597bbb2700c20c0bb5c1cb67226083cfd3790d6ab8fd8b501848dfdee9bc2356d5601391eff4b10b85890350039c38e6f3a9942a7518084528951f78bcf4c1df1e561f86bf6b04e0c7c6948c8b8bda01df79a6fddb25b12a813823e6bbe7e5eb7070f22c11c672c2f820da7b564b1e22468ea56bd17f75cfbad18d40d036ab2aa21b15e247153f784b2cfa3c20670a143409333f4523ec3e40e06b2214d3762a17d8fea50a427333d77cd0e33536c83c437ce081c19a0c7d0fe4e7432ba72ae7d4fc8ec74178378ed1e8769305255983cf4eff87962e62282c4377a125c73aa959c4122eed79fa4e887dbf43f22ef36cf23876ab9c2bf87c2d2af816f52c2fb40b88abd570701072df03491813187452477e5c161b56756dd4ef3eb33cde464389f270bb55a838b89eb297e128c8e6952237d4b2e938b1aa975dffb515a8d192e48280ab90195c8de6fc4a4b80d8eb7c61c970b216d2fcecf429d389f5759e08a934ea65fe62b955a3802029c821ab0be0aecff12624c8ba8d4d38a75468fa1eab7f7c001ad301f74e81ea2e4a633d544161580133d9310a0d5a7f381ea040a4ed152819f51eed7e9bf0bfc9f63063dd80a6383b27769c04fd4be9cbca4252551fa7749b4afe832c4f0a6cfd34e2ca68618c47558f06d3814c2d5c846b94e98a7938356c0b393595db9e5da5753d935cf93d4dca98fd12f38bc7a2387b92c64080f1e84100da2318f8c08bf1a96b27d9866b086998ad9d8118ff93b62ea868d1eeb261726fc92c851fc8820d18afd4a5fa2c2bde9db7929bd998aa5379c265352c7a418e77a7c0e79fb119ea195a84af8192258da3e6287c19bfdcf39c8b3bff1851b7259a15b31a0d7a0529e3164d754ea68ddf97355cf68783f265ace58766bfff9a5e91958ec4680d28ec6abccc8249a6b0515c3bb5c6212198ae2164692172daf0ec10da80560908a127524c885f801087b8bb94a91b937098ca5933a738f2b60d56a0e27cb13f19ebc2e169bd89ad80c1d5d5fdf93d31e25835649e538aab51a4282f5e257161502ef2fae2762e4b4d94c744fd29830599e58d3aa7ac85a4ac7f28c5a1ca74630a858430a7465cb8a21c6ced2460096b27aa4f8720c55013cc3d1e4f7e44af58c3cc569e1adb88d6340351410cc074879ad7b3ba56d05e11ffd80569e888fa1c662cf7ee7a3c62d48f40fdf9900e0978970d3ad9238c72767430e1d420273dd71840447f2291052aeb99c2d75482e8ece1b0732969551d0c9cb9d85658bbec9900b8df636181f2fe6dc1a0da33ad76b3550b8dacfd40e10d693d3a2695eed3e5f2dad76cdb1bb969632a95dd2918ceb131c07858ce7d4d707ec50ac63707f56e9a92088b435faab5836112c33588b32a8651cc10d00e971dc29f6a5d931142cef4ce73ba6cb9c385ed785f53cfd189e3824d048b8d9e50299d8291b7170c51df3d8030da3d63d9c44ac26d724a3ca770aaa754c21872cab63984275ca97c1f87ca812dec17e3dd5c75da7f123112723cae5474cb28a362716b7a8680c184f56adbc7f5dd348c67acd50ce496b98b216076c5001d1f8cd23c51fe36b5d9802ee2722af35f7a7a4e5e255d13fa537c08e1716ef0342823066f9de935fd69605584c01e4f1eed4ca01775de6c4c72ed3d521364714fb009b5955c1be42387bc7da12e9cfde62c98f07b58d6f9e834da1c4ee19388c9bd21574efaf199e75b4b1ec1a2dee00de0bc27ee82f053bb046d2f98ac037b46d5053fd96497d0bdfaba12cfc00420c0985d23a41bd493377209b52d648711745c6aa505d9d3687c46e437c0ad9bd64f826bbb91c1003fd46da111f7a5cdfa519cb883f96589bc366d3844c02890f0b69b4df02c40ea474fe7ba5bb56943f737923fed760dd7bb499171150686fc051c9a8bd41074106ecab4ffbe5eb4e1f44a3b5a4afbfbbeaccf70e87c2d552f2bb50c48e5aa43fc23b227b6cde2627b477eee5708ffe4286a1e5b8e4b4ee4bb3444841e93124986cd2330c1914ff876b3c926c65bc0987222a300b75ad8cfbd73f0243728df0ea68c0d6d0c0e7538748cddc7690a60098e7c35ec2c26865e73794b8892a938aa6452b0a3fc88e49017f22714915303e3acbeeb8b887555c8853ea528e92de8f28321dcc4fdf514646d6070f424161548218a1d4f010c0ef0afef78ba4a23951544fcae40960372a5cb8499995ea31ae1bc525188717a96aa933682d84bd2b75ae9b6d36b840292b4ca73ce42eaadd0bfbc40a4c623f2f75ee1f5cb9b7942c2b08d2c9bd6dab2eaef30201061d4304553b6b07c7001a546f387eca82c4f928e3d107bb408272338ed92dadacfc108ea653a8304fdc3f06e5f75e9cf0c695875efa9856af8789a336d21b5f23206ee5f1af7e8b7a4d26624598bb6f0388d96b2ca911d882435cf36f5489bd527b673f68e1e50c058e44e987a13296ba1c72cd7f952f002f530e6c87580aadc421959f5cf583fed492be506b309055b33d4a289dc6b160e0764be60b5ae94f017261d8c34f11304f14eb95aef90064fd9f67675e1a04456c07c1da83b70784e0a1262fa5313c0fc192d8266f0cc78550bb586278348f6ba9add7147b895260128ffd1dc7c333879001835ea8e9df61761ef5eca866ab34f083dffc132fd73fa48c92900f019ed0a9668a51fcd4bd4117afa9f8a0df78b504292cf61c833003e4d30d8d94bfe4be5b3f53b76c6804a421f02516a4e692753eb80a23c64cc487ac36b3cc8a08309937978f0e1a0db6987b8dfe7f1763efc0b192340348c8885d4512b073c94ed660a25b01b400a1a62dd7ce54f300751070b3564fb318a9ffc6727f2b3f160fb8fa6a2f9d86114eeb2a32fb80914020d2d40435012f9baece51b5356b44da2ce4700e3e1c3d66a4f76cb61d5d4e5389034a804b7699ab127cc2613a92cbdd45b3560f870a46967046bb3a6385d5828d81b755fdf8fa3f265184a8f1026435c036974802b4dc8ce7a0de0d2bcb170cfe0317d276ef1e9d41dd8e01011574a1dc03a1245fe4109a8f0bd7a04f3c3bdec6b72206ed6f66a8ec0fd112827dde2619625b39bfc37597278ee2892dd075ce49c3d806309642a128f94ffaf86199a50c38a7f2b21940ced401f4161f9c0087e90c5b3dc1fd160051583ea8300b038014d238cc6be12b6d3c02421ca038e579497e0356c29634762adbc3cd46576bdc59938b60b210652ecd6ea44951100fcfa7ef4d11e2b918439cf8d198049ec7e9693ccaaf9a1aae55e259d428c1bc03f5aa8366804e86fff10934d364cf8d95e7f699349cd3f9d4c5761735af8c9e7471e78f2ec9662d8677da0f9377760fa600f382789dfd15ed710249330e8ec373efe05f4baf1fd3501ef7e083849b1a58fd9ca5208c0679ae1e75d0205066eb43c150b1f82a6c874d9b941a01e1d9ded979940e246c22fbcf04f9a6b96238ca8db7cdf9ec0951081f02a4020bceef404eaa55337c1d10b5bd3877e477481551dc3e809cc6c43373b694bb3cfcb50fa99fbb2d451434353fc17d26cd0fa3c5ccc396903783b600a4e3f9d3427b0aead88714c0e3e54d8d3d5171fa211a00b2b401e4cbc69ec406da3b135ee2cb69b5bf8cfea0ccdbd440ff21811b0c62a276806d932fc7014ca916cd46d3fff438382290ffbc92271c0f5307cbf36fdf25fa2f31958c3b66ff3ed5a25437c3e13e44505a4eb5e85e1d43f6345c322ef95976a0c22340e8278258a2d6c094e9593bf4d4b1127e7168cbdf7744f413e1c6901f4f167c42c4ea0d5de8f49e4b1a088646134402f3662ad3606431e34049266ae816c12fe4f82927a1333fbad92a390e1697a13dc5382dd8c8d757b6fd706783f115a0f4e9bab74735aac14131d769f52f7de0d79ae8e0f694335434ce3e1aaba5ae0b80ebf95b3d9e8d24af5c84f48078ca64c1ea21f36775edf0ed882d19f939b49d2f332a45a265d9043e61784e24381876b82f26c001abb3034b1252c98608f39310e281f3d95f8408612434a20657c7c85f06a0c06eaeb404e4a80dc3e63d12c55dcd2c85a61bcacf3b253044b1b2793d2904faa55d6abb99842db30c5e92af944485f4918f0c3b6ae87da801440f315a94fc7132d90d4f05b66e1bd8afd67dae57fc611bfcd176531509e229a385f24f0e1456f43c1be38b29054b512680de9ec8dab59291ef8d21843a61ef497a34859a55d3a9ea8ea47debb8b6b8f3da73aee78e25c53182ae274090562050f469b7d880116d465b173d40e1c4c34308700b5782d6de6c2f725c27145c4b9e46f1aba14d3c73f8fb879d957783b0ebe0ff0e6cc71749dd920456e5c7160ef9a8f0970eb650ff35c4f796c3def371b80d290c03a7e977a6f90f7b2874acfa6bdc92c1a89ee1eadd42e7d4d67d8776686bbae91e5801dd88a822d1b78dc52d37b15a1bace7b67a8249cbb69fd03f5b290bdbabb43616d46be563a4dc36bedd5f23f115637ccbdf102544d53d202eaa0c358ea3eda8d2e558862b3d9ed11caf72a6bf2f6c31cdb0c22b1b0687e63fee5a50b0f9c41020913422ccea27f0e85665a0c4cd51196cf688d034c416613ec22702f37bf1222d230515e3f1baaaee1190cbfeae93d6956db1812729f23a75b8bb5b602bb5e289a8215d0b38a7088a4d12bc6e7bdabdc4e1da06774c1cc28a12bc108413847a5b64a4b768d0a35455e4005169f117b4e8d058b67f27f66877c6acab2846eac36a553495728808d83490bc9100c8f4c137b5b184e7798b18b04b004fad25a992ea1873189f395257c5b5b1b7c52f312c90c938a28566824a294670165ed28235e3d68a99b00e09bacf5e46e8f749d88d1dfaa75abe47bc200887526b68578069500299ff1e6c6aa01b7b7413870e9d01475f72707a5a2c9b841ff488b4edb26087bf8667cf9ee601aa04d436b2ccb1e313cfe313bc09ce285a3d630a5bd861494a9f5e68bd819bb983f688242b481cbd52f0eebf22b001a665ca0dac4e7e915298e524b9e92c27c94d673949eee6c66745a1ff43c18c88632b5617bb1a451e10af3addebafba138a8b7e1ecdc44cf04001e2f73b2cf59342a6f00a2583f28fb1494647793dad804b2474e3c4c3868ace76e60c346be9d7b2480531351d2904f1e5db85e4c36fa6a8ac23922b04b0cca0c2e2151685305b155598e258a34d85ec0f960cce2abd6bb51bac134cab210f67aac2de30a33947eec294290523b83f83b1583d09e4e56f0a314bda11c19495552f55457a4f268fd07fce422e87920a450218a2caab63e0759c5d7e19f68bcff394fc3a345732031d781059067cc3271817f93f353111fd6f46943b1ba2bba32baac821e4c56dde46d9d6a90867c5ae1fec81e4d4433ad3498aa28a2538ae443afd054ed07b6e2a91542b1c0d930b5a3d0d83b2dfcf4b6508cc6d09127025fb91e38cb157124d98673de63de54f453cabe5ab73b495cef49af532d9668e7b4a8fd8ee2cc36cbf53b2b11e7b00d81dce57dcd4fa0c87b5a0946d192b112bd6447e3d3edf2035b7a361ba3c8c923770e7a2dd3116d834708b06bd33ca379d1212af446b79ddffdd25b1477b29b036b4a5ca60afb531335a921d111b0d4320a26561d464ecec3988f89f68318892d19cd812c6f531d1d70e0476701436d1c845adcc0ec265bd72827444856861c62ca051e03bb353eed058696666d9745f36b5a8dcc58263b172279379d17582e39dcfd88b63a78c4f28fee7cd4c2e3accb0982e19953b189f21d6e310bdd55656a75aa87b3f9f6be63a38cb67e3007c8ac80f0018c0687b8171b6f235a9354fb2f234c6af76a56c1dc47775f6d0aec2e771d5d9ae8e5aff7e885aed57e719d1610c5dd10d969372972a943859edd664fc83ce475e8d00fbe0c91aacebf1933959ee173fc66de3b182b53216a22d9cf45779bd49ec791a9e080a751494994cd31be0f235ce71758d33c20386cb5d19d73e7d4f68926ac35bd727dc2f464ab1010603c8d874a07aebbeb9750f757310d81101806d14dc93db9532544c134b57041fa25b16afb4ea6ccbaf45c78ebebb246300f67110c239b51519431e8c8605f3f9a0e94e50912e980d4ee35a4480f7b029dcd7827cc65d50de6adecb73feffd7ba9a97f5e7d8768d04e9cf6ebe1371e94cb5e9a1e1c1dc570830ff6a0c777aa31497b7cd6df36e0889acce209f3ea68c861be9d2654de1acb255c87bd0b4b401f661d5844399f68a9daac6963f661bded80dc0fda2d87e6aaa47900faa85fdfe8e01b5ffe1ff614ef0268b69d21f19695d97f9479c5fbae4c04a232c65020ddf95914b4cffa8a82dc20f0ef2a251360e8b70d10da3187f6734daef515375de1eae3ca87b5d278cc579dd626ebcf88225797c53dfd959a10383d680a12bc4d425c675e0d04ed7c989d01ac08ebbf7fb958c3b521b231d5f6f1770a25534ea41d189def92d9f87fff182d196d8f7010c7334da22ae56c7da80af11becb1985d408cd5749f95af385872c9ca318743a08cb83d8a1158fe4771acc7523830e99d91194864d68c6237d828db1a6cfa31c764bf3543acc60905f2eb71fa32b13469ea6aeadcd0b3d5b594608e727f56c8b41181c8ff887fab8e9197e0d682af8a65d47b42d1480a344a45750f2e16070d0343fb5a184795ea23119b1f413a18b80d2ddf7b838eebecd9ce0eb1ec3df96419f31391c9e464e5acffa4d59dd66389b8d5375af1c7e066a8c49be6b947dc6dcf93ee895500a178284daf1ee6a9f401b97c66af6f21e7bdf2f9f452ac41dc795cd2433446766f464c6931c6aab36c661d1ef5ee687941e4da6b18cecb5fa9cd4b95af9d0875cb97b3abefb65a8301a74df93e5a77810bea847a87d75b2460f181c30a1d6253567708330b922b13ae33128b8847c4042a0d8e4bf322e5abb6731d6eb0bbeda0f1a179dccc2c56926eee02fe995dcc72f6ccde00f89c010e92a3d7b9e0f90405f782f301221480184914042740955791586d40ae5a3ad29e1185ea12f6ac6c95ad31df6a0e7bf15d2da2bfc30fc169763eb9d6561bc0af93088e6c35877fd0ad3a44a0a5901cca7dad89a768a44c6ca81f420c5a31339d243d0fcd0b72e130fef0948a775a47520a10f7e0b450869821a7533006efb2da9795fc64001be28a794796eeac6a1ecb26051016336e80d451ea166a265aee987493417e1d79739dbbd563f3d6d85fc8899159ad21f1ab8001ee7c1cb9301c1cf36938e033169274250347c475fd1930157e0d104cbc441d29b02a9387ee521bea40da7acc98a8264477b593471f9d69aeaeda50c313c9d7217e573fe4e778f84650fe1521d46e46d1e922bb5ffa2519774d6c699c597f144a667709238d1fdf2e98989aebbc0adfa0bd4afc2aa37880089dbd0423c452fba12aa515ea02d31002d2ff237035bc3a407173e4f9671e39f7fa97b04ba6b744dc7f4ffef1cdce9f68055fe01277b6d2823b9a118879d58006bdffefe0235867d6abc1e3dcbbcc1c3a5d68e3af91bcf853f0a0e84fcfdd7750cb19d162326b698aed6168112438656f1111aeb4c985d8116f9809d5ec3a02c97c68ac212c84b39fec809ecc78fec18cdc5b5166df8d928d59ca8dfeb5592d5bd902e4216595a8e79a730de3e1a7cb022a4f6e2b9af9a20ee89039a6f9f82daf2b6c76a9fe3cdae5c68e97fea6d0b8981b9a984008fb352aae6cbbf035ee0e8d20f499ef3e20a98d6507b48a9244b023cfe7c844872455fd1f36a5ea5ac4d582ea5a99886be790e4b07b37b65f1a013d122f2c87cea5521e5dd7a37ad7777f416d636eed9228ad9e4e3714a4c167787d0baa68e3b936403931f06e0f1c7d9fcb407e51e3b487c018a215d68df69cfb5e13f9c6e95077c2a8f882eaac90500e3054b332a6db5b752a51bd0d74d0e5dd31dbe280a987982d3b237b7c3e22b42047d5ecd8788d5dc3d92c62e07f356c4ed9285ed4effb808bf47da6ab470f7a1baa5b5345d48fa0413b97b5b42b16534b7181c2941d98e48808ab1c1917097cacdec81ac54dcfcaa725a1f27418051f7f1e05d6bad2751a0c6a809eeca8ec1dace01c1e0411144d157b37aba75951a4026a76b7ab96dcd596cd884850f347b42e59d9863a1a4a43172148c6ffafbeecbb7f1ca611010c7ca286362cef83a8c67c4ecfdeb002b4b1054225d1f876e93ce767f53a19c33786c274f16334746ef2bb81e62d0b6bbe0170eb601261fdf7ef6b574d2dd999729392807a92dc9aebf5d8afb7cebdff7e3315675767919caba464f14f62cf393b422a9166a8045a5265858fd499be8dc89b953ec9d67d53a06d53e13bf4bc265601b0b5021b105427c86ab2245779c10f2f63690c163b04ad2e8064788bc7b0b443c0cab4a9a8e3821f3c62d10e2335c1529ba830372e101543c478003006f3efc1f035a006a66593092b24a07179b065b930eb8c2d118e12680ae8d711ae52601b8380e8ff7cd1520e6078a99c979c55a551534e737e601c3dc1104b139fe574f1b73d6f7af0a0a1e5c90299708fb30e0c1f58f404d12b2f7de5b6e29654a290569062b06c906a81c32339e0cd743958a991386d2178f7a1c14bbeb2fa869d2bd1d337d3e15fe4e16bd5f1cf7ec9983828238e8e47d35d4ecf94d9d914efd643d4570e8d4914e01f1108ea3d49dc8d4f20ac73caf10e124e98a15423c81866c815c1ac6126ca203b85a30e9e1c2824909aea51e16481c41063f5a9534d048638bcc81bb400a16278a2a0b75b1386154a18030ea6840f49ec8e7be9f2b0d931fe8006e12eadd08a2f80e2038185ceaa752827e736d66dd4e4921ae981146e587df1d8429e04ec6ef97447a89f2fbecd4eec26622642bde8d712e43132a11387703832e4312a420840cd5dc5cafda0871a7077f17fec2da83eae2823bd7bba4fc6b462bc6e8ddbbcdb651dca27f13386e4e23d2888431d851d9fd238a53e0efffdc632f0e85b1396e4ee979906a3baa43873baa1f015eef4782a8e684f4a475d735af2bf30c5ed373ce0dea7ffd5c1ded2feff27dad83d9fb9c59d765d9cff73ccb20840ba15b5bb4a0710a5cc34af7ee9e60d06e4ba642cf48acee351116dc8f9e7b0ba743f9d3e34f2b2e8f9360dd872cce3e5c08dd7d7bc48f91ab82fa16d9b72f2374e750dfbf3391967f4b29a565414b4aef06c81f0318bf87d0a3737612894e1caaff800d55534a2925959223b337b78727ed2eb99df42a49f5a4efe9957ce7c2695fc475a6159d1eb407986e98ae2f3e30850ce9c7af6148357d7c1ad4e3f4f163904148af4efcf129d02b1afe5595806e1d037197c58a16fc0c851f080606c67b519180d293f7ed15a6b5c2450caee0e5428a2c5cc4804a8d1b230cd1854e452d84f46ab3d41eda1aa05ee6b12b7e8cf1a21b326a7c8e32389447cf80525ba85ba50c372a1353119437f8bcc4931cc51ab2184c44d08fa1575e0c9df28f571344d58a5b468c5fc30a5d28f6977cade341fb2d46edb7320e3e9f0c9aa77dec620e3f95b3df2d02cba35daf7559f7cd7a59c18ab0583fbb330d0aa34412d4ab25bd924c7a25d4aba15ed164bf157bebaf8ff25aea6e07eb886214560bdf5f7d9c6fc8685eb0bcb9b345236e017a338853c8c1fa606f9a60711ca8fafca953091efdfc731ca5412a078a01fd3a49081eb9cefccf813e079a4146d57f1209651a91eb6453dcc69f4823d288be0b29c84abd01568de842e216b230a609d6471684c5f10cc9660afa654444ee0ea1f77dcaff324307b5cbeab096b5616e81b9d814ced8551abb8a5f4612ffd76f544783f2b352b656d48fd7b03a365a9c2caa6e9e4d68f240004b02105a1f59f5258c285b41551b9243eb8389d5913fac8dff105028a9ee5289eaffc92a6ae4ec06cb8b468bc3d2fb2eff083b7a14955c47c7cf11d2d0162e71e9485084032889249250a414a3285edbfb221758eabe0695a01b6a54a4bafd5fd6c26e0aedddc05a687c964bd168714e31292ef5ea8b470d614c504c8a4a6868a9fe718d0887049249a4904422974827f1a857fe9da296b8e514850e51f5d9aed1c01ca59c25d7e1947290729292b054ff1c2e396ba8f093a4a5faab8044852545f07c2a1c813f4969d44f8520a13286a89f0a4caa3fe4eea6f4aaa3d2d124d12445c0e2f1818cd09409821e1d557f1310b43f0bba09ca2260f1dc0069a1fe5bbf1ba068e52608888ed0e278ddad866e4a67a5571f8f9fcec875648aba295dd11947d5bfbba2c3d21d755b3aa54e4b97d4adc1e3870750afbe45e2718407929595f5c12f876a8857aa0b200502e8a618b98e0586cb9ca357a37e3740aaa5c5b901aadd0d90db780e520e524e18ab73bde79451bf1c35aa7f8e1bd57f0049ae73793993e37206902473900690c4e36775a5fac76365a50422fadd0005e93a2916e706a8fad3c49b25bdfa7290aabfc77823e43a51e80628282809939ba15e6d953392aaff8d949ba21b2848671ca17e375382b830a9dfcd15d53f42ce419a92d4abaf9322674baf9c4bf533ea97c3a53a77eddf49b13efa5d87c8fb5444c6b941b97704e1eebdd3293a3d57c51e4eebfa1859dcd9c568675c5d32c3e841114067aef3ce5b9bf8180a35fe7f2a38c0abc0f21575c8a1bb0580a1faf354c5f8390fb0c089c816c917a8ba93c839a7942425505f242551fd09a9a41ec858aadfabb290e142c6185950982c3128a0f48a99a128b0f4e00739dc2043053b9011740419239059638c2e4863248d81248612129be0c2defc04ae86a2549aaa612a326cbfe2adda91840ab2c03e6fe6bc96bf7358a82295493af7c805a84a515506d9b5eba5fb540cf9e4c5b64217da42f553d19c61da7e780d6457ad8f56a9d607e72c0b5b451b951045965d34eecf92e3a44b7777e8f5951d1889269440420dcd0e1ddc8c4c0e540ccc0b3d99362dc32e2b2873b76484de8c05dd2a4a54ea14c8cc6850f81a7c38beaff11f0e618c525ad68cde61d8160466de6d28ba6d30ae96cabf478bc3de9d608d468be31ddd7e709da21bed14c7d8931575cb30305b5ca3531ce3c608475caadea1221c4b6bc8c8b04c34d1c090aaf0bb7e34d4a854390685ca2133936366660615033333f3426766664e33a66d66668647569415654564d4a133776b9ea5f23b7c37d234186394cb32c6694dba250949cb16a423cdaa71210e55c3d1c599db8f49392e4a495bb824215d12c98f388b6bf123f83b6d8357c8996840356d630821b466f7261ad0ec74da7e9c7073da82d4544a5f5e208c65bd9cd3729898171a738a898989d161b2882a7bfbf55844957f7d2ceeb0d8d0b0a92b7c326c61a4cad0bbeb51f151b6ad85142cf5632b104b972c15be1652aea8504b857cd2ac1a54d3a2b17eabccb2eb6334d22968a46ab59f041cd0fe1df7ae47bb01764c248569da83216afd4853f00e0b752f2cf3a46c4ef7de6d7875a6b70fad97756dfcaf17b8b338ce3b92fc39f504ed0e3a916d2b05d5fd21eba31f09e9e86853efbbf94ec3ae3b1dd8a7bb8980f0ba2e081fc5d5b83b841d9c1a45719d2af20314d4ddddedadd085128d201be2fd1ca5bd0ec8da0f8b6cd8a96d43026a7fb6ccf36eb3f134647d7cfd10bef7478f08dca29af4cd6f4006ff874c0e62fc359aa6bd11aea653fb578775a86b3b6deefe296e9fba23f44f96b4b6ed647a7a3a9d4e262f4a6fedede26c90affd49dc8d7070572b4d4af94638baab5dedaa6657bb7190db6cc53eeb6a3a0ec86d16353d0574f9719bd52c050c61c96db6fe90eeeeeebe8981e9f42693a699b63f994c26d3a6f126612d9dc8be2ecc54b8a2421696f50484d0870d0d1976492965747f63eeee46096384bbd277678c10c2382d2bc618239c1e34e1a517bd0dd8ee0e638cd0b29cd961b37b847257eeceb676b73abcb453137ad553133aeba909b5eaa90995f5d484c67a6a4261c576008f6e60786a428d7485de873a3509e3d484723d3599d6ae84d02184106e53c4dd6708210a15c3ce652622deddddf56d082185d04444f923338410dbc10ddd0b21dc192f58f6bc306d43c1c49665f99c13c6ab2f5e798c715e168661bcb0535695d0aa5f0edb940cf59c6f52326e87515a3e0750e103a0c2e7183dba38ec0ea31c40f5ee030006bdf8b5e90619b7c3189d80515ab3afd4d3986158b62b108a8e6199b6994c9b966151a29c47b0df2a916437830c46141072b4809d22170cd0034a0f8815d92d80cf18ad091f32c4ba14f6ff82e7df4cf3972d6221c7a6aba81e141f1d691b8c18758246c8431b8450f552bb29f79847a1cc8dd50b9b2db3027959539beb36448e3d945ed0af1ff5c03529f662da5ee2126b0596f53e358312836aa0066aa0b5196275aeef56729dcb93a29fe827b5bf95a8fdb5926d4e8dd28ce3b0ff54aa8b8a7248879e6328c790cb0cc90cf9ccd0cc90e48674480d2c4e3f6ab381eb901c18d98a5cfd329bf482c2fa35f4962706062533c3ccd6cb88c3e5d85eb01e7a9f67bd6f2f58ef1f63713aa0d0b143e3f51103b383c687f5571cb5975850621dabc34735a80d062228543d3ae2233ee2a318189a9cba3675bbba3a5ed64717f5100ff1a0f005ab407c1a488d152554364b3d3e50420368ecf722b7e99f93528efb7840d840ac4d3f11568e304a01111940b06a790db438fda62628bfb43aac9e4c24943054c2a609e9e0c2b91d6a18b73a5b2f719dcdd3382ef396bcb1a9fe4f5bf552a7fa03bc3d29a2848204aaf762f3eaae375e7653567c775ecc04a39c0e7f6614107294811a90e00c3218a0478f05ecaca05245937b0e7de078a2f40ce92d40cc66f3366692de8fa9713b38bba4d4de0514e3f5c19b69da130728004e0048a8fb399887d5e9269640a20821503da8b6d25634b75c3adc1e954efeb19264124c8a499ec43f9b4953a56cbee374d017fef96175b6c7134f6ab312ab8487e0299372fff1142059ed256f9cb4c532ecc7ea1c44197028374884a85801839fca54883e1e82d26d851426b59f8384503f4dc78a535e6cb14f4e25dff297d929239dea1ff20dd860b0c00d0c22a810562243969108f9f102f5f7a7d12302238aca2fe8c4810b31c83083100ad49081213a330ff34203a8df60094850ffbe38d4db50a4ceb72e8bd6cbfb8ad4e911b12c9969b353f22dfeac270b908c80220d2b4eb478920495681a927e80040a78d89244139884cb4048130c80b1841115416812842b9848c186111b4cc470620d248400f1c30f49c8c0082455f400a280034656506182a48a173e1cb15c8424c087329a0042182be0d2c592951453b4e0063e98a20d1228a1a14f20e488244c1c218927547c88021a21640fe06408255c840832011727a0810a254a48280902154a92d0e08382259450e1811247803184225640858a234164e1228d2513085931983882951ec0a0c8054840228c28811069bc200b29b49c20484808beb8a2882094a44811c7103db898f1060cc4f8228917c012d0e030f021e288113801c3065a6c300409d68c234b5c2cfd18610b25480410051180a08549105b8821040deb861855780843491a4baa04e1038510823072620848984802e2075ab43cf94113406d4020217ea58ba0000c88a83082941f24e9e2071a14a0e58a22aaf841891668f8e0248c2cc61072038b10b0e841488e13252e58a208662019e3080c80e08511526c4982063be04188290926ac6cd10650145b4670811ed810838d2e9ab0d205dc81060ba4b1c6135ff8c0881fa8c01fa22e461881134320e9e2893884c098e10334803801104578720447a2a1afac68fcb3eee0185f79b71e6224b2f93dbdf90be713b11ec95f907de0e7e767874ae4890e6bb46d3f80c4cf3edbb2bf280a4533ce7ecba2f6946a262de63f1fa26ad2b22ccb36ea43547703c271d40bbec9a499506f4299502614b05098e798cff43d3e44557b98eeeb59a393e6c137bde94fdde743544d2693c98442994c7183db8f6c7e6f2f5c3fbd0ff3bef904f5bde9b0465920c102091643ff036a5d98c090de137ef893e910c2223103274b78320e628ae5c1cf1b423c996bddb11449d418e2c9a0d65d6a8b2d929278b2a875c72d40c114209e4c5291258927b364f00489279b5a775b032a4b4a3cd97584058987a734e1c50f0f0f366ef013c493695a7738f070838b1308f1e8908038cc38ea8e9f8881258927339d4c8b832f7820e2d181b977c0e84bc72d4effd545ab0747538cb24081511ed103a46959db46510fb8f8a08d6869584783802e2650e2b9bc09e795ede27095a507c4610996887870c05e07df020a1b3c51e0fbf064578775bbfd981f75a8564733c375611de6d1641e0eeb36d28767c76517df068e238e388e703d80abd2860d70557adf90ca9fe940c44696656da16ce4793d5c85cfb19bdaac38b8b04cdbb80cdb8d5e934dd08a69f909422b862855c2d1188d9829777636a209307c406e87bb351cb7cd284a77e510b2369d53cf27c0ddb9d07b77f952c521329afdadad4d33e807b50dc2fc24cae80e61949635e71251c66b892ccaa8699b69fb01a38c27ea5c92eacbf6831a71ff1d97f23dca0823e5bbbbbbbb7b8cd11d85ca914346ebfe1d87595125d21efb48ded4c8dca736f36c33582f3d1d98477a401a8ff5409007ce00792ccf071e4e3cf29ba781f8349093f43eb60ab28c8fae1d3fcb651f8ebafbbc6575a67553539deaa8b6c42955f68bafd18eb4ed7074c3772eb0692cda2923b79157d4cfd7a852ebdca8bd6f4a47a2eed15897e7be05cb3c47ea94fc1bb8d6b441e75faba3fa3ae9c9cf38e95272d771596ee4479d7224b791cf21a9dce1d4326b33de7eccedd4e579964ec95ff8e27ffde746973b12b770bd7c07c2fa08c23a19ab737a799aa926d4f99f09f573246b6de6639d6f2a85f9a66efed6cdf7aece6e4a78796f3ebb15ba508f5b0c40be5e97273d22716b92ed0973fef535de151a80427a75d0a7f267d923de7ed04c3a9b799957a8bb454f8bff71ce7da7187a962ba46cb12744b80ba1e57dbb5d5bf1ad8825763206be5eba862d6281851c1b165a25af5b1dae62bf7fdc3b6807a7606d3c28aa7f7b1f074d51fdd963a11a36be1eadca70e48fc215fa7d0bc9295da9bf05bef771e6284986e0a46e1535a0545ab78a1a4c5eb2f89d05b8003fa5eab112ae842b6f4cffad50a1013ad8a9f8a96eb34eeba096cd2abbef84785ddfd74551f583db298b467abb463bc8e0132d84736a1aa52814c7d5d460dd58ef1fc91ec3e6c4aecf300cc32e2fcace8d0efd33ef80c04e6d3d7ab45f17e4384a23a573660e5f5ee23fc7498ea3b4b720fd832bffc741b0ca3a3a05010f622d841042ee69f2f5b8c5e11c08dc8240198ef4d0c3dc82c4da417871f883481396b905497d2f7535de80f4e753e9acdd11b8de21b005b1b8a769ce2dc855fb3153ff4e7b7b971240b881b833936c4ff8a651f5cf948e3ac51c7fa7a7b84e521759b1626474c44895bd29de53b20d0d7a94051a2d8e3bacb0973ad549f58b493fd19b425f2b55579a464e036d42e6f8cdb8fbd1db6e7e3d1a0d4df4b679083bbdd33b3dd9602a4545281723d088a6a547bb01c36124dee0a75bf5964fbf3c73cd373779cd4d12ca35723a3d549af7a532effb79d32b203e72c3477ae5365faab9fe9fd863588f8afd54d82b20d6a67b4ca18222750411537ba6827e6cd4937246ee71b3d2d6170e58a866a7fe4ef592fe66357557e765b33b6108ca157ea7da85cdd3bc3dc23c2ee297f4d88345d5bb1b6095b280e9dfd3b9d62932856a118f6e117b42a4542a134a370935a035563e6eadad2facc88208566441844ca36e23ff8240e651b7e9a30da4a4f7a5eaf452bdc2e2cb6b9b677a1c68b68ff9e54169da9bbc1972d06c312f01fa315e0e5166403dcce710f3f42500f3322fe3e5807a985f9e1c9e0f8fe66da7ae98a72f04e5c1fc6e37cc80fa180f87f5d66964383d4d0496e7442301e679798e89f1a2d0c040247b6e794eb353dac34e693f517f42a7e44b47bb1adaa9fdad6114394459568484b32be8062ca22ae897196546eba3c622caa9fc1691aab25742d110e88742094515859fda99914594199550944384d3241455f959e6610f49d0506bb696eb4542cc0efbb30afdaca2a28f24549effc5ec10634d656f0711e703fd3a24a2da21d5b68a16a78b8aea0ea2da6f7953c3118a6f64b3571d8858ec7657594d8d3f75ec6a3e751dd3c7e7d6c7f571b5ab6353f2bba3914f5ffbaba36908d0d79e467a12a0dee9b73f79df1b10afd973eba3e31667ae0df53aac5e3c3bd565647bc2e715d57e5315ba81aca8ee9baad0f9d6cf494215da9fcd4e5567fcb2a2c742bf999f3ae7eff8667e80a8ea2ecef456e8421b7a9a57f403637352ca71524a2271c220fe2e6ccdb2ae571563c056f95f8f6aae7b1699940f218c0f25b718d9ecafc7874a85d8f33376b9e60e5fa08181c85a709df7e20e8292656957e6990cc228864dba3d3637aa8566270ec32e6cce180f9b260cbb4c461a5719c3b08c2b01eda10eea24319fa452a53ea69bd18b8f03443dcac321c687878862a1eb36fde3360d610e51e2e780fa98b760fee5ade7186f3d7a33c078ace4366dcd77c16d3a8b83f6924ed2a9140f34ebdf71ece32518a553634c4e314e38b909a184ded7d353e34b965f0fca22c24f1738d660d27d2c54668bd9b22ccbdac5014195bf559a208bb0fb8818e91a7f43f50589c0f7d8f1f4a0cd0ef4a31caaa657f1afddda5d407f865008cad579069902605a9096f5d49a939e60eabe331cebdefc62dded07dc3ee2bebbbbebbeebeebebbbb50b0771f27b793fb3fada2a7695996e57dfe2678fef5f87acbee28608c31c61d87be11c208b94f10638c31c228658c321ae90a1907bbbcbb93fdca843ce82ed1619cd082bfd1dd6165235b239f56a3437777778f38cc1e6ddfddb5bade164f365f814564c5ddb2dcdd1d721c990e441f1bb1d1044e4c9c9c9c864e43a7a1d3109448e9290514456914fa510d0a3d39a10068666666f61ac2ee7e6fc80c2184104208e1f880963d9aa1c70a2a4835666666786a41134db4a00902687035ef144e2d80210e5ededde55dde5ddee55ddedde5dddddddddde5dddd75dedde5dde5ddee6ee7dde50ea6bbbbbbbb97777977bb973b14773218972c3b31337b4b64d98932378cf0c402fad10a4fa7937682b0c722aa10fec909d5e80b84ef317a8f738c0e4ed9699fa0683b8cd29a4bd01f4160c5b25d6d777d77f74d272e49dc7af612b3eecfcccccc3da9ca71a9bb98de47eda336470ecec11c833ae590c9212323838a81919179a13232322719d3262323c3437323a3ccbbbbcc5d8cdaa44756c7219d9cd0130be8e7461857d709d5769999ffe4049ee052faf2b27099999919c2dd5e6f724c9685ee4b787b77bd440d24468a2aff62d9cebdedd416d9ae8f3e80648efc51c697525a9617bd49dc76fecf1dbe3ba451a331b22bf175f7ce3b0b08219cf3087a84705acfb1658430423884eb7a0b7e8414fa67fdfeb5c120fffab9bd505f700f5adb5a2b74a16b117123193b2f468eccf303b399888dead5cf777ef85da815df627e668bd9832e57c2e8459101e1654298aad0adf02792e81181449a83d07ab5b4535aa7acd59a356d6a9dd2fe8a103a84fe9de2b73a6a592f3d78059e93a8340eb814356468480000020a0315000020140a8744229138241c14a6513e14000e7492407e589b4a434910e4300a828c4186186400000018620cc94c4105008ad182d181edee2e2dd3951f3bf4454cc271643f3c40972cd965ea66b66760fcbc988141e1b781f113e2c03cac2c4921ce1ba18de22e60c78801539405e2b57d6b16230c9d9b65743ca926824d1adaecc05c5c3b984b26bf4e8017efbc865b3a42f5ce5cdf3ddb4260e34cbd638b4679d91ef77a42473a652aff32d44b1f952fadc455ee896a6a9f5fbbb6504bcb58374c8e4de4a1b4bc08f825b51f4056cec801d86f316c7effdc06cbcc03199d28a3cbc865a5450d11bc3742ff4a88521528b710b05c90281f3ea2941179d2c8421f7c070547a0da5a0dc11ab52a08a1ed118c01f5f23a16d763ed0ff460191d0d59b84897f5530a5022bd7290e4819f5a9ea18288463d31b813b62e94d84a4a7727cd449b94dd5f8a49003afb565f0cf83bc49d90abf94b2fe19bc11bda17bb636c88b80f70add6ed67a875dbde373ef42c9d419ae635b4b42dc963756b40864e38fdf4885b94adb326d2fe4aee04139c2a9a64e98472d292e381200d96c1c8359ff68a0e2b3da6da1c47dca39471b677061b122e7b06666cfaa2bf5a06801e3a47118d57e68c5da6b4a17e93348335cb3cf14488efc96d66d6e26f8eacc4217ca4398731fced0c9a564d4000dccee85bb9647833b382e3b10d2a6ce789c5a6b59abc478e482da6a963f877ed654398b0c57c9352e401093a3858fb35febdef3fa1364bd6458ca569e7342183b237e2904f263a0928fc1639bb4ac2a60726fa2e8dbd9dd2fe07d520218cc39d270f44886d02000804c3a306cd1a9603de69709af9c97b873babb868303c0afec4792975cc93fe91fbccb08ca8b5d837e4961d90613d92f2e260e840e489e956f0aef035c2a877306b631bdf2d8942ddf4cf14e63446f44832519108ba15574555738c36057be2155d604e7dc4390f4b034557f9b2509446037f1f4da53c6beec3a6d064ebf142bf44677b442048d77a7d0c280819271091e699781ec65c19d68436aad2bfc2852a0a5558ad78781a9953cc8a03c4aef758d5f4ac50e0e5aa232f4ab53c789ab2174aac53b1ab360452ddc00be5678de7965e3af453731bf871b21e602cfcf3eb790e41b87b87f632fe478e2d4b2af66fc63ea6472fe2da9eb6ba328b36a44f837bd8ba6911a9d6698672ddb8b9b0c4b1df8fd9deaa132081a6077f3d57387a03b0905c70c45150f9ccef30fe93becfc241f9ae279544ecaf467051846614e9ae51c90af5c46079fc5d08e39af54ae5f7c608aef7a7ccbf0f422246ed44bf17382bc984919fc9c21cb4ffe130d5c3c3938df47a3c6b13822061c1ce4e1e2add91719d587315301a7ce879d1daa8c5642871d1e2d2e17ed70acf62eab3543fc659950d697b4d3fb79e817848e28db61037e32e2dda1df5047421d56a0393fac786d4921e3af3e272016c991f922832b9587bbc3d790201b06962ecbbbce08b1c89155ecb2a9ff94c2159ef6925b914cd49d87a6a6892004c85c0cd2c7e054111a16133fa5b005b42bf811a314701d4b2f9d5116e68bf74ab9e788955e42370d1f2e8830092f75bb83c60e56c18f80f5e6e978526387ab96330cf53021f01570a4bc83967cf42998049eb7667281e1f5f04c6603b4eb04545bd6e8162791d9f13a0d87b19c2fba25b54b0946b55b4fca6581b0eccca530a7ae7c2a504514e4185b721ca2d7730ff087b1f9c9968c93c7e6f6e5627a0e1eb62607632eda69bfb14a4232a8a1cc29d753194adab8b8592c0a7c21d2504bd3bcb47c579adf1350d66a80a4faf84664e73c918e42b84a6ff50d01e50916acd3cd2c687d8f7e025b3c44d8defcfe667836e43768c564cb2cf6f19ac07aea6bb146895bac9937047f2620e516c66ed3b57ee903944e746f04cb8248c29fd98cc6a7ad2954cfbb3da2ff632a57850c807f3a24f19981cb0b8bb394fd5a3fa007c20886c8f966c57a50845dbe8e82257b704db32e00fd6bfe6ffee49755b472042c6dd1b9a0208996e78b556e8852b29763f13df539d6c3cb2025568bef09d958b3182aa0eaa2d94bc7bcbdd6def42d57b7ac4a1aa71dc012f799ad1e9c4e10a957b52f6593a5d09e4c430d32a76c42c9d89f21909ea47ac69b5c1259d7e6639c0831f5e11115a8623f81044be3d9fc895b998792a3d68e7d18d6ab6d14f022804a0cce90c07cc3c8687d184ae1e450df34b36df279f6ced6d20e8b7c10f13081963e02e643a19ee53730025018fc14101865057df44eb9d9fb6b00005fde24869bb31a61cd6bafee89919ad5ef6d65d6af1daaecc85a440a6145fd344dd2bb24fa6e60a9dc0e2f06c40a384d68264c6434be977f3644ad5b0efcb373a93f4a4fd5de22747cc3e06dc87515735c55bfce1d1d2ec6376f01abea914235bd250437dac42465399d42e68e4643a171388b83c56d0b308b09b3f8b2b555ca12b3a25671ff725677068d66d9d2c65ffc71ef5d0939b4f6beb87479c3acc047859f425897206989b907881729b3d011491a1991523b96f4cf322e1a43ba3394e4ee7ee54cfa523f20c9b1d61d8dd787eace2e974a1850b76486084ea60f1471e89da360f1823254f33624627762807a2be605695c5013a06572b94cf02193e25020d9c17a7a916b8b6755a661908829d4389a5f7e4aa8d63c6ed3a457de8331306ba749e899c130235e1025adb5a1e12f598aa0b0946842836d7c0609d96ebf308b6be3378335497cbfc4658e34151f1bb42219de5ef413f29d71b5ecc385ac5ce267af787eeef056dd3d8c3dae933f9f83986f6588a911aae490b645a2e64602e8708487e0828c7117505d80ff00e960fee27acbda12a241c437310e33ce88b0c681b6cdd460cb5933941a57da008580ff53b1e28ccee5dc38186c0f07028a9601310658fd5f9f87f1ed271d5d14764a3da3acbd296a2648d43df24f2b5bc20362e364324d329ce8893fefab210a698b35aefc77bc015349618578f8623bb95bb63d11be4c1a01c4d80f517546d5c523715ae0ae94f176ef2f4747a0a78ff244fa2f6bbce0c322ef0d806641b441b73f40f00859cfeb986daaad4215c09b4cec45110bf1e035e956209462c5e6392fc65af0d82ca0fb65d2b8cabddb2c6837cbb51e6299f42cab1239b1a0dabc46deed8eee90d2a5481c7006ba80732a2ca245b7ba3c93dfc826ddc3353100e4e6e238721d5c65e947902075778b78fdad8f37e4587af97306f107a2a2567a045aa3e7bc32656b04d37e93f081953c485d738fc2a38d96d64a95ba04a5b6ac3dbbf0a57848237374787e7abceced1ecee958b1457b8fdc1c66905c232d4670565108b96616086d948f2c70cdf7e8a56f5fe9275b077290bd64e653591f822cbefc7f733cc630ed637579a5a79494f97249bb99ac55134a4cc1ec378a2237b9b4ddfc0851c361827c0c8c563aea85cc3140a6bdae02f7d0e7538127b4720488ca3cb5ad21bf92791c9c074c4096dcafefa4e205d29a1644e98f89f2b8216e19ffa4cf2de71bbdcc69100ee38ebfd406143a4d12c00ec7a9cb40329cca9dd0cef9ba1afa9d83c68ea458e32c0dcfce6cd30ff49ccf6864adfa06868313d4f328a06d6544b4aa617e13464bc4ca0f9e0c1183c7373df31026552fb9a64dc9fd4990750e0e3da49e75835c55337e0a56444c6a77f7fddd3256a92498b14416550cd10a83c6ee169b97fc8f02354986280957434d079369ec04810b99be4a1323421c9dee16dc89a7b202a93343c023dcbfe438fa9862dc5485d4ff096a6bd5a3705afc806b9a704ec7136620282165598a355a050252985bfec1c107644fa247cfe5fe54043f3c06777666de446147ce1990b178f85c2260c564d6528a12cbe0906ac2217fb3876a547e9de672a0015ed970f210df2b3fdef192aa3e5082793982353862bc98531dbc9e5000c56a0f3bc21afb1a2aa04288904b7c055f8a3f38388e1ea4d57eff53e60ec60990d0a80ae5a79ccb5c971274334c2c43958994eb1bc505a2e558ea2957e006904124ec5abd3fa699978ccf1fab77e0e12fb48a4abaee46c58f570badbed7b5253341b3bc3ad8fc28489910cd06e913bcf2130d3418858612756b06053bad323946cced513642476512be3b79ac675c5f2fa894de9502b881ff85d0968a133013893436a34a37412f7ccdfd6b57d186229878af94b78537d8aab4ba1ea61c19ce850f3cfc4a378844ebeb0d44113470469a4cb4855f13617e0dff9a97c017ec6b0fc5f2d8ea67caa3142ef5745a85427bf53525e12e1d0e4c9d2ef1884f7414b15fcbdea7af906a706fde4a14c074191dbb4363fa5ea6d4903cb882485aeceba4ac0b468fea67fcd66b34d5e89a075c8f64df5142641dff3cebe2e4084c3f2fc9eb94b89f22075cbbc5787acebe34043f51b10cc2eb84dee01c0bddc1d5590cb45db47e5083e02fb62fe8226d97dbeea9d4cc7219cddde2876dac4de1f93f151d2f262b6898c0ec494fb60914fa7094823f35581488d5fd2f127682c777306342167aca46cb2ee96b9d35a03510ae43334887f8585187127dcd7050a015c3508acae0808dde29654afde864afa1e2700f7dfa7a0003e2ff0d969909739bb5b1466225be1ae0f3e9509f9c09a4d1ef081c86e7272faf13d023628f069b3040918773a38c9612f29216dec0b3ec95368ec2c8de5630bd71bca7d8b81eee32637d280ccd26e9def9645316ec8243928067e08495f4ee0833b06d97400461dedd5e189ba35ef906f44502982c3d4aabdacab63d1faf5de24c72f68ca9c9f7b4916decb2306e78571144e736a0cf3fd247775212310d51461e1213c8b0fda06b1f3162c4037b9237b1b2affa3e9d75dd384636584a1892ac9635dca371bab13491e8e4bb063194338494271241b0cef24c1df3eca04fa1582cccf8c2e1289958e78840a5d1701bc205db47888178984b152781053e83913645d6f66c4706ec398d655f366d117a5ec3a1ed745397ea1cfb531f093101e13c19cbece5aa16ef66343c1196844a78a389394b98b34df0fb852c4dd1339e605f0327e5ac7bd31d14d132230be76b44a9c4fc439880bfe95ae8c73ea251c62f01be6c5c23bd7529bf7e19b99984f796f8c104abe06d5983cb02d81ee865863198f6923e14400835b76170b1a798b86abef687e466f59bf4d405d1393b9590e8e3fcd823cbe0f163c11cd9440e02e68fa283f839253a7fc3b1c4152fd5669e0ba9921693c1636d48414268ce49105176a25442310ee47b94c8eb6082101cfe0ae5e5505a0edb62da237019ac1730af0c0b08f832b6ff516c6b781c36970b11f6f0f87069b481d31b7591c43cf653d8f5ebe5c0717d58902b2651d9292da7c9cdf625179604a3eb095598ff6d5e5c452d96f5bab8b4ded9fe8a26be766bd59a48455750d8e5d869d86e484ce283a9af54c5e786aea81093b7738d85e2f31bf7c1bf8e120980644f147d299b7cc44663da5b7589338c747f6f14ba736b08b96cc7a0417f8f86031d958060cb15f25d1c76f9bcc7a0d49d0885e3d2ca46422d4490cb2337569dab28c14412db02f0225fa8524fd611bfd35cbd350125580d8191899375f4767750b17403b8e591ea4d471ddb99291c1a0808564a4d495027ff435fd4ec91c14bf4c594e2875383201c6c9e0ea93c1a4fa8432554499da28dfb53ee50aa2a9453c71e6b3206c267ee9f9c1795c808611062bed8bd54e2f4b36acf1fc90f58199c8399fb5a18c33e1bb82c6ad194099ba990aa833e10d9f48e9604baa77ef903179d27d2cad3b73eab6a88e04c80d4b66feb8a242176e49e20cefb6c36350f438860f4c6647f43532009a16661b152b4dc20f54d644cb5a56b09e51d41844703165437884ccb1ac253eca6d3699726e63184f065673a5e2a2768494ac9a503d0984466f4feacd5ce0dd3396677ce03e88b16d41c0299a10c1505a2b791afcb2dab1b0c881b8b12138e587a275b25d5e3eaf4407b57d53f2696b2ba72154372feeb696d87b88dd9a554e2d45b6a0a8cd9263115dbefaa3244e0405a9abd68b7bd2aeecb04a0e1ef29b3ece76067de36082c784b518e72088b27e6bd599b0d23d02d71e1f6c0d1bd8f9becd8fa1b307467c043f08df085ca173b276c34d9a6f793cb814b2bc911789275a39011b917373b9e37ed3772e10516a8a722010710f51a7caf368d02664cb77bfe815adc9f83ba989a5c10c893a158b65663c26fe6ace34158b06d0efe391906fc283a7064f06bfebe5ae7e65181051620b02b2bff646068a016a0255407da004c89e9a5714d1ce0942c655132fad6b6058af31caa592dedb2f5ed53083ed68846b0a0a2973027ed3fd5d1955c24e7a03cca92dbe66f1b42c24c97b1b8e5a31bd92df3f5857671a8a7302435d456c29e8d23be26ab450c7a54e05982353406efabadc3891600bdfd5a40520ae66c4793c51b463038d1a20682d0fcc219df1a9a51f31ddd983e7f3670398137634a88039573f93caef8b3ba05b8d405b8e62d4da6c7cab57d426cc6b797df62bd1f003451e7bde4fb6b25b2dc3110f64a245c678a643f46b37895dc6c7b3a04007ae1357ac65e8444558ed73cd94f804aebf3cd5ece330813882f0a0136daf34549b94a336b2f0011fb4b735a82032382674c3d8632b447668c771279fe811636ed22193eb086b7c4a4d15e5872cb227e0b1352a9e088f0e5f3079952dc55cbf364cf58f57b79314c1a8b783e821938b64fddf0ac5c431d011d79715f8e58fea817bf6321b3a786b422e141dd1380b9550a5e63706518274641dd8a8fc40162260810926b4be265953467a4188fcbb85bc39e460cd4c8ccca607b3c1648217f287a3719c92eaafbf8b7cbfce126246f8f3535e8fe078ac99d590a6fe3a81221ae66943622c69c4c2cb2dad7dc936a405b71a963df02166c960567f7a0e426bb0c4571c681bfdd6d454bfa75153f8ad0aa523b1ae86603476dcb1e8983cced6715d059893170edaa0a99142c186266f32b7306b9701e381c6224615249ff23192e0273ba6d1645c387c5063c32a238913ea1ee0d048208641d69b902d0dc64a122f5630c8e0d6bc3d5f6a30fa28cc82f1d60fdb2889c1dfb696246937049e23a9eae52ad10a4c66a9b5f5cad7a05a1ed8135c5bda9af056d1c2f1cc900d04e21c7f3b8b62d4a4d56798c558663a2a3f469cd14cdbb667d33b0ece602a13edf10e045f5c8f8095cc9a3e5a849903b4c1e6c874c5496e7cbde8ac1cc138b76f78e9d0b5a0f28c5100e36b94006fa8a664d9324640ad1da77b8816eed475f2ab7196af676fa9f12a64980485c5957b943259feb53e41a429b44b88877f72ab4e77c4521f8adb3109fb012a3c6371b47cce50db6907920ea5e5c3fb189fb768dc5fadf3847c65f7e6fbc463573909971250547ec6d016f2889b6bba47ee1d96c9baa8e575f53a3c5f4d9b99d424fde5a257325858893873920cf732792dd4e926064ee467c6f509ba666a573cdd4acf720fd0eb99ea6be9bce9e2e1c965a2e05c0e5a53fcfdd7110ced3b1284882eefb30879ae0f346762a8f07dd428473ee065460fa5a074277a7b496f57501090d35a02ffb336a0dab849faa26f2d5fbc983cb3ca57015dbd26d4d1db2568f424f287e6e39efb878342f28674fb7e3406613f0b257fcb7f86a96e05ab6ab5ec936339d99fbf604045063f437a0f46dfd54d14b38bf51a789bab4bedef1b185ded9bdfe1377c1696f3ce71a21a13bb6c3110d38a159fafaf2d1def2a8ba050caef9011a4ad75c5cd8e6ee6cd907784ae6618e19a2b8e3d2ae64ce806517a1355738688eada081691e9e5902791a63bb37a14444db2909d5e852d23dbc6526e6ca2fd2eff651b131562d45eb878dd6078ac8b62cd9db95dc7e082d1376003d5ccb68b5ea29b6c5bcd74f916db2d9f072c65a2e438f91553de895ff6266ef7a34235442fca257c5b7fd1c68a759a968ff95c54438faf558f893e77ae9ef325cc6e21339d479e6e0668a829a9ca60704e9ff7bed2b9d61f1a2cf2a6cecbcb530e379ed840628e185f6c12f17debadab6d19c8d510fb41bf7dc4ad54c35e8ca9ba80345c27eeef8a83e3498beb738d09583871858dd099f7ef32428e4d78f4b65025e3da4d36ab717d5f623fd09bf2235d6875bf7cf49df7f7d814d36da7edbdcfc1da5a27311fa2524bc6ca4316542db07a5f028c1356c1471bd44995d68ea57433795f5a3dbaa4556bf3296bfbdc5441ae3288934cfba4065d2a6d8e6cfebe07f1a3b0f042ea5ef4d690267d489352835efa69eda77749933bf4812b652082f308eb004dd307b3f5f84152a47880eacb479a859a34ad3d9a76eb4563d507d68ddfa4a917d9ae34d236aa47b74eb3a69af8fe8888b2a7d1fa1bd8464d60ddf84d346eadbb854d93a7d3884e785aecbb5667a01b026805ffcd9582a5fa463157a77e337c02ef6b5d4dc0eb985555bde621a987a1e88e30d156fe619b2e7efcf79a0544bfd24a97318897af11d0d541d04ee362420f451a88fd93e1d3c6fd1fc2a918d1b88dfefa3930762f1efe7bd0dcce067d4fa6ee079803b38e864825a0e7ed7d46721abbebff742c31c63867d06319947cb84e81988c1f155d0168ed264cbda11d1d595692f1e83e3c83aeb8c203a7cea0d716aed1322c828e7db8d0e06e16c1e8b1c7386aef8aa30d266639601eb1ee7e4683abe91c401e94b51cde885278cb190d4a0fd2b78ab14f3c45b92ebf633ddee6ac4e92067d72cce9634b7ca07a4721283fb39059ad70aedf1f7dda2269d0e68a93768ffeffe7bd72446a3e0d5eeb336cced95b22e63ce78c88abb4673bc19cc6ac286a70f637ee1b1792ce74363f712a3fa5e7d6b17b3dcf524cd147e21d5183a7ab0694b4d12e2681d09f6cb89fd8bd96c19443f06cd64f103b843818dc8878b035eb0a0697202633f1f97ae5ee123586ce8b6591a4469b457aa9849812b348660f985bfbeb3ead2fba2c99dba9301a7b483ba00ba7c4fea84e244ef4e1bc01e03e15bc9552d3e891b2a5d8033a240f6d43417f1a61c9feceb39efb10f23030ed4848e372e92d1b19b04cae3df78840959fa2f5a8f6db77d6238b28d4c85fa843e381b1e19512aa1025cfc073b433c9f5b4d597ae7d00a2651bdccc2238847a29b5c4588e3bbf4b4be0a261f0137e3e2d1912162e80789fa969b856b43623f98d9bae13f0045e66e9cdbeb5693e4108c52dd21fdda6b032a39c46173f9f55d4076d4a0ebba2d70b1fed21bd37de07d223daf7a6738e6dac09ccda400ce04caae2e454bc37355fc4f2a98129ce418289c1dba4556eaf9445d8cb16d602f2e6fb4f174eaa2a0162af9955607521a95e557bbcd98d4804f7787dd5979714b132132934a42ffb6fa0dc8e30ab14441a4cd43e64a8ee7aec34e4a996488769301a7e24482690fa5aee429aac08c9d5c844a14b6ea1c5fed789bf8dd947e58c7c040991a3f16252ba0cd80ffd1cc4377c59ae544ca3e4f090e96621a01be4b41cf608490ccf39ae33ffad6d81b316a3e00cfce7604c41ae166da6f95cb56bec1b457ea79653508eb25960241d003f4fa058e6ff9444438ad100ae1b0a0ad332d0f591824d00881ff19049b35a8389cfe3212d8f3f93ea38c60879580188efe8513b00cbef33c79597fee92cd08ede6ec75172ac1a5fa22b0cf8b23b448aae5527ec3523e9475c3ba0264bf619065366130c7b9d5660d7271146cd600dca426453a2560a6ac80a132794fac1f1d3bcccb695dccf5308b3af7e817a3c312a9cfb29db03d8dc125b3b3ce1bced9eaf461fe5108adc3c4d6e3b5a11bec6c39a1bf9378f18c0d5cf9e41d3da0808094d92868270de04fedd8a3672d90377a7e79477753b082e7f37d22b0043aa09e03b991d4ed5dd3138dc240642b07268c00bbc75074064db595f3c58c2420c26e9f46edaec6e928d459d5f076d33a7d0101ec115300f39d058365d7e9aecf3a7c5c93e2dd31d21bfa1eda57016af26e7701df302509563447cb5151e116fe528b5f95d4b7cc87eb0847321fb40d03ad1ddd5c4ab904125229e1580e4bac44505800037676df85957f0518724c8b0a60d4d717d241378ecb0bec0b52d97d13ac2d4d186e9924e0272e44570df3cefced5f430e5e3f4bdc77ff450e638810816ef26b400aa17bf6db1893862f040cfabca950d2c958385956a4eb893844f2d82fddaf97fbdf623a3d90874e2363090c1546071f1daf971fcc7ab8ea9f42dea4db44a14800f8ee6d6f5c083d2878c8abfb4675ab450b7419370d10190e75912ac44d095465d692abcb5f626cf7513fece33f8ba51a7b5d113c1ac804d5b847ed6c01ea9bbab1b5685048ae9cce350ead3457ae18e6f2d92d689a8f48ddddc7e581a1dc75d6578343bb3a0a8f6379e5cd63ce74088d075860b11648d278edc131ca9c1408d5dacd1a0e310387a49e923a085461e6e95c0b3f51f47dd668f4ff639bd392ead3a02a12a32624bb9593a56b34569d00f70a49484a509894d52e44767e3498053309e379c50b4493cd9d282746184479d24ed716d773d1d54c9366bbd83a037c6d2a50678da522e63b7898722f2b15f6f3aa4464b652ebae08354b41e1ba45aaf66c78624b15d89d5506d4d009cbefae30219c0f9f7d78cfe90d53558d2fc700f94204673e0078712fa1dd65babcfc68ee93558a6dc896fe824eb99fa60d7b6b39d6b3017ef26c34f4984b34244d1349867d0d00d4f6029181342e19e64dc97027628f0be5fc1e425e69280a3fd06af328285b806d0fa054eabfb120184bf4df457c8ff87b77e3a8702f20c7801e3444fdc28db40d8366f54862141193add828a752ee29177107bc302fb8dcfd90d54ec36a0c75f6acbc4df56a306f51cdcd971becbdb69bd1efcb065648ebfe033dac5e1939c1ea25b3fc7bebdfed9fb7d1170e9b4d68c6c9325413690f20e9b93c9971c80ec59fe2004b5de19890e5ea59682cfbf5346f80f3340833d7754c672bf45dfed19f0dd4adbcd982aa33fa8103f4f0a5f4f74b9d3e619ccedd61dc75be68e81040cbbbd452d0284717c08579e8969e1655197282f400c7a5fecb20a0242353d88bc420d80992cfa8f9c127f4b5d20f806274f66931270eca82b2af51b57c71d155776d0c0fdee0a5cd266b675e30d0d6e4ec3ca5927499e68db4a4ad6614e032d483f4dbfee532befdc41f3a1bd4643347990e8dd2b4a16ee03a3b69ef1a47310b3e8429084cff33058c7aaf930e5985a721bc8af69b4e7cabace4e0a8f54f9e94193471f35e294a7b8c7dbe32ae74055a09a7304d9596bda4a02563f7852b10c540361b1f69a9ab45f62e7bbc834502d501e142e63ab8cd4d7d7a8f641b515092ddc5133b2a4eb5489f7ec79e3131d9552afc8c872a82fe915662de0c55cbe41c9df8bbc6838a3d7898949f1c507dda57a056686f3460ff265267b8e4f13b1606f66f6876e47cd4987fd695fd868ef7a28ac0eeaac1fb5cd1f7ab62817763ddab9680a9ca8eba04a71fde2d43a1d2f137b61cb5a82e8e0e3ce6b12c0440378ec9fc72a9a9c831e76ec8428230099149b61f9305b636db67a759c3b08566ac55c1a6c6913c015c963384925351c92f9ec97045e7f6c892a4bc15b2dd692a512d82e377c2ab594366f1728ec51c8a35cde9adc713b397c0ca3a76f70303162231f5d5faa482e25d1b8479c0ef9b07851dabf5e6d0c5a86b1df891c149a32926a12077f9efc0d4ddf2974ea77433d5562a28f78c8b422e62b7b49c841f036c570903077a404c3a3e70ca75530952255fca0af5ddfc35e1045cddab901bbd22647a8095e0ad63365b71a756bbbff11c6e1ee92137fa5456b0512e23eefa2d61936ce82f09cdbbae7c979067196b92baa6e6ba0b2342e9498ff19cba01f45d332552d926aa28a282b8a886186451f283aa4c8a0a20115095374838f8b8e480eb04341a92d70f9c221c82ff0041c44b0f53b0f028e51fb7cdeb029579323aa22b2557a4ec0edd05abe1a2c5cd2fa9bd763d57f89be99905171713d13b15f479a2e3d7892628a7309c69940dee6490b515e43553301dc13b3c76772cc48eef89069b85725415dd327bfdb99257196dcad0cc4b1ee341031200565d75bab200043300c343ab533d8f961e52d4cea035751fe4f2f071de894749cf89a6e7dc0c7f31475c0c918a0024b55a223389d9de66210673b89edb95c119d5c0323549294c50303ee42f368aecc6b729ea1b0a927c97c40ff7138d70388455aa0321624dd51fe19c23c006e15efb669b89f8c3887c7ad988797e09d6661b61018a1bf9c08cd8d84febad149e7e5cf8592fb9ca3d599a0ac13b278612371b0e451c1fd24f38823072e335159d65abf38a0d91d633a08201a3907ce0936f39662832ee2c0d7fff15f81c3e61fb814933f0f99216487368258829b1a9ccaadb6628a87bdd31bfd0016cf509c3bc701afc6fd858d8b5340ed4a547e81013b283ab93891a658499c1d3cdf66619afe730ee5948df8afeae8047fa48259ad5549df73439f080d6b8730e2de2c94598e351c55e4396d567bc1c8c2c1d38c245e8bd37300db2798bb2d7619f1296a46ab253ddc22829abcda146fba95800a0eb57af92b5fd8ec747e252e89de17b1959e698851c7e19fa195fbac3c8cfd8720e7ac2aed52dc613a9dc19e22bc0a172cb3a10aa900a34f61e1ff42ac907d230cd015001c5442898a59160b3c650ef5c0bb039c30a86833a0eb04c66131440919a44a1fd8c800ac25baaeebf12c8bdd29639e8ae2b09942707c69a57b2eb825ed5bc87ba302ebdce37046c900ad9dbfa44716ae6ff664792b5ebf298b419ca7ec9e855b8a46119aa7389cc4287c6209902d8739c3905a4f7138f3f1415935dc91845b2d233053a83df486b6e9a917e4a417decd2b72f2a9250cade6068c8d385d5a665526e3d3537a2d0aaf4bb1eb297a3d8ad74ad1b529bc16857cb244b4360a945c8352bbc65e2cc0874277801e99947cec315cd3ae49e0ecb293d562f2a38ae2352984d719989e018a8108d435b764bee7826df841270cd8bc2d749f85f151f700b046aa6d94e192edf9b9a5df94e223f9c879013436e7ab718223cf7a1394a0eb2f5248d0c8cc5ccc3879145dab8ad8fb4a5d63e9db52e0d750814ac5002daa489004705ed3689480c9867ea20ca9d66410f0e8ab4f7d82b1ca43cd6a4d71d3d2d33c92ed6de1e03206a02b757291674df38a37ab5750532fb1315bc4258991c37a328b2a4936f0b2f352805eaeee8abac767dfb601e30c1188b7470e0f552d68dd6edaa570153066d55b543d3d0a1639686c33c057738e8702009c7bdf9be3d22cd4eec2945dcbec8cd1b5b590d82372850089430238bcf6252d34f2610abbaf471b9ed29525ee27244424319606b2d4cdcd0d5437fde7d5fcbfd097fbd16b2048d700c0b281218c44790d0cd1d4219afc0c8cf3865f104672ba41d4a4afcb436a6fb73eb2eb8fa6f650caa0539d3213cf8ffb4a34af37338352d126898b57dd62d0de14b229b8c264f09f0800dc04422e5acffd4413b8719f544055b5b57c975bd3ad519e6eed4846ebb83fd24f5342461c0e027e48a947ab59cdd224b9c00ad4d81d442bf07efa6eaaa03edda115d11931194a4c94498aa916d3b430e6d3cc6a936870b1791bfc8227fcb4245e742971e944950db041c00d01e6260c0474ebd836ee89ed4d6f6cfd34b2f3abc754348d9dce14561905e56d9f258d1105cc3106e326e56702027b7bdc425c2d938c821409232b7a2e015812476e4d2c207670dffa238784e487a273f9b70a035b8412fdc1defad5d0b09df7cb08c64a3a0f9178eed485c2f52eae25b1e3c6ab0aaa406b10cc20d79a7ac305d3ec9a971f76e8a96e54e4d09d9a0f0a5260954e161c0fa6d975f7a523337c7cc5c7fd2e21aa1bbcb479deea0025d637252fe508fd8854de5e3ed76b08c85a96fbeebdb73e3329871812adb417e80b8d3120bf26730289eac6a50a97d3d619a1b423d3392c5781bf0754ac9d7f8855422bb4d20153a730499a01c466f67d174a622f2431a211fa2b4e3ad2e536d60dc4937ebce93a1ba2665b092502d79cef20faafa2e73211759589fe4511157989a4fe5098d0bc717c637e1e3bef49a900a6593b5163fc89efd04aedc57d9e22a48d8a2e3e1c0fdf978a3b216acf74ee23989f8e0e110d60faa913d5bbf310b3be4e09d5b4593d5b348289f0c06d654b4ccf907a119f0a175d7bc989d304669bc604e9299ccc1fb7f51292717156174a688b7b05aafcae0f66caf5233b4b0cab0809159cb68fab39ecb0cd8d3ee2bf73639fc8c2d3beb9dfc89c7691e73b64faaf53c2cc19374d31d8b61fa4f69e13d9495dae9efab5c196e6da1cddf226c70808b36258b900d5f582b0adeb294b0b265031cb16d3300d994d9c3c6b703ebcda1368dfc1696928eac8bc5359c7d870bdbc9db435527249e83d7f3b4a517da7547cf9025ccd7c6bcd4d30ccf0474428b8f787171efece3173b597d0a7cca4e6ed2a30f4c0438e4e64d8ebd9231a9c044b9a61626912cb38dae0ba3a0958047326ff2912bfddb5cb668b05af4a615cd7232abed9d44830a27dbdcba6cb006a6b65531b22921178b3c921fd425571a8d97b06c7c4f078c4ff096ddda38bf07aa45d5f89ba1c4c745f9f4781a0791dd072723264d99cc391271770f57e8cbbe53afbe870d20e6ee908ec27a799521cf188f644601abf0c354f3142fa082c1788782c64cf0da0e5d41e1c81fd4b895c31e50fe404fa2186b07d9b95dbeae32b2dec559d5497d9a9dd9752f896c296f4a41f54eeae925992b095f9fa3df0e834eea023c97c9e5f0e4db1b1e0713fb3c173e2b403393be8064b4d99abc122cb0cc283143e0d0ae2dceece0cbd8faabc95b3125b03238d20d39c55155d4a07957876e1c989431313bd5c902ceb9bf25625a1c96c9fc4c789470812a96368e705f8e5396267df3e584c83894b4fe1d05ab4cde675848c10f78eac7d25345860b029ad32570ab868e74804262ed83b2edacb6cee95c83562d373d84866c86a6ebf01e60515178c1426c991ba86b947267585363b3f4268bb4de418c979e50d6928c00774c60d449eac9c502bdd5d85cf84308a8399cf265ecd88a17342b2bee61b2039cad99a0cf9dacc18c423f5cbc14be024e079235e486ee4720b0811a79fd38207b5b48e06542b3e809442a3dc19e618e0541de1ab9a2b42e1eaf8c86a5885ca02742c5a355ac4fbbc3acca2848d22497920ca524caab274e25de10d2054b12b05931160017dd35b63d56d2b4a287af698df5e9c48b6e1c2377d9ef0c38e7ff1192a9624941db93d3ae733fc219276897c36fb04289f6162cc01389bb3fc6aeb76f5d81cd99ad476c56578ae9ee2e0197297e227bec505606f56cba9ae75cc2462dea125ffc2f13db1e86402ddcbe6ef91c92538f23a7a0d78715a8c5d879e35f812a232e38273d144e111e492046e521c145d9c6488ef582c331981d48e92c0112319ccecdd3212e77f762167e4fc1dd387ec20407267f24b26bc7c7f77b2043bf6fde4b972006b41dab6394326c746fc04727b147b525ec1206cb858f2ae94be85636d8a8320457ea012d6a613cded57e5311cc1be9aa0bfd9ecaa85245380ee8fa10347da0caa7271c0fe02b6629b35875769c1acd47e58cb80ba1221770688cea10f9d47e0b8b3eab87e80d1ca95147180208f54e8e7d33349720b994e0c97f6f51730cf7c4da61310adff11d26a2859e96ae32b1cdbd3e42a03f21aa296fa5e944c3d0a6a5db78fefd3c135efe3b40f851645e299e994231f256f98b51161da353e71b5c1fca222bebdfa7a796bd0b8c35d509b12e764d125ee3ef20ddbc36bcf2373ba9c3ce596d783c464e23cf67445217cffa4d3c87cae0a09d68f8962a1b0e79a6b7f70f3bdaec7a850aa1da51ed65a4ab81945d45de509bc045803586f3e576eb6f97771fc29d4fce9e14d5ac3fe7c7a7fb20128fd46d124c05d0808fa75d0ca9d867ac6ede4ed2c5a08e6795208d5c4a0d4a563d02994f219638466b41087dc8757f45c88438b48df0f35e37068a9eff866d1a1d5c43e322ecdc5e91177ee82f7d4966e30eb51f1ab92d14ce25061fa0f1ab5e770faafb421e091c5ee6b1b5e995c41d6b5f98e3cb48c957240307f3c034648410ad6496c15fc4ea547b94d166a87173b85c5727af04cea79040617a385eba39c2085aa92a623845483002b7f441918e40db6ce4165143001e8a6db8c680cf257315de0ffcd630184f4b2cef1379dbdede7e2d017ba0960542b64ee8dbb0845ed2a91445ce76e74952be58b73271787b4c84f70b5678f067fe33ea8669b9097fcabab60acf929e1bffa08fa69c77b2ad76b2f071b1cc46344f841cb80d238860465d502518b5d22557422d196875c05c6e70c765c1ab4cfebe21ccd1ae939df45a6af7402467ac2aa78672b15cd0b727c8410cece2a0268eed955f5aa547975a43bcf0b2f52782a9a70d5354be98328e16771358426bec41cbcb45a31d5c14b9ab87dae02c01129aaa815d796264f451cf24966a7724e9f05dbb2a5feaed51a3aaf3238bc7637115a4a6993ff04c54a9ef7dd8eeb636e2669ad19e867056905e17988100cf30811aac0ca5d1a33dd11cf088ab83b8610721f9a20505607ee77f736d255335445c40dca8997212533fe047b465c47b10bb33b18ebae47bd4cf6731f8d0ac88cdcd689001dcf39ab1842cc27f955a7ce0ade539e962bb3068f4c832d264c2cb925b94ff6adf5fc1faa1da5c0a8598116d80ac0f3a39d237108acd5394758c0be0522149533bdd14538131120d348cbcfa7a6e50608a32f40cd6e67d825cda34ee9387a13e1638f5d0a1c94244cedc9e484b933d206aef878386c96dfc5e16ffd7c4b1ceede9a83e7c78b111867da2ffbb600b5d9a7c2bc9620d1dc83762a24fcbd3ee3d57a05299019a183c311d3db81289087f4374ad0449b0ec3896587459a2266439aa8044e4dbcf502c69d25a677f549818c9936756ca8c669a8b11a07bcdc8851055a7e58760c4a7ebc812dd9a9dbc6af3e5c1e5c6b8bdfaed7ee3513af240db09319562fd7d06dc7333eb761f1004b253b88bb687b86db16f0c1f14bc5b4674767dba5821543db3e16bb2cc670b4b44a60b5bb23d38145ecfedd3834abbe508bdf055bcdb51bcff66556163e6ca7a7ef745637572076b79a43900db6e6d2d82ac73c918adac9185b5a96285379898aa750e3d06df60562d129e67c41ea30fc66cb66199a00c37b8d444ce0a1e6dccc7cc781b8c30272b13dcd64ebe0c09bc63e6979f08843fb6bd0bb831ef6e7a19b73750f175c3f07ad3b477e36c99a65b9ef3c65b225f19bb4f78ee63bf5be3a2b21c72c09272f0630a82ac740136a6bca21e1895eb5bb1b94411a86ca8b298d83f8b4cc4e2b630b4bb99d8816fac4e9899603a73ca5acba4669589a5c49ff49305bf8c067f9d61ae3d4f5b8b16034cb8bb6977dcf669342e734f83ce9c039441fc714c4e89a716418a833cf6a0800b149bca83a7a6140d19100ed72a06d06c747b9945d59894a08e24d8bfbc2dbde5c017735969b64bc6f521c700bc669665f95221766d81b7dd4425a1b27e55bcd5a01b1aa872f3b4688f609f1aa9cb3491c1adcdf9dea3ec416ab23f5422a7c903eb2f4f6863602f5164523a39dd1278ba7cd48ab7d0ac848a4ce3d2f15559c7350c0730e7f01cd2d0c9636628ba79a2c5d4648eab01053aadeb6fac84c2080ee96fbe3b177a9f3becff2d43584b9145b53453f7d37d30b998bbcd6e63ce0b1fa64976e6f2a954ef64b209f707b57b3c868b08d5f134029ffc8f475c2ba05b322693502badb856602f6192ceae9f5d7391a2042a2f156da08a05d3ccc18ae9e807667ae1b7df5416a3ca5bf9476a3764157911536c3d1454b5c8df5c787a6028a50a8e09a640f86a766fcc41319d2ce5cf663edd74155eb65c5c27efb26c72ccb9546285f8c9c8a70690962416e013859525bc6c2647c238772fdbc00f282a8d62001b32e7d9ee7abb28f6b68de4ec6dea82b084c3b9de111b9dcbf77d0c148b25786c77b1ad91f09bc669ea66a2282eecf7ae645ee98aab7145fa24604e9fc1538f807b63eb9d1b598acd4cd1adf7ab8c7397d283cf124b82ac1232a2e58c8513f86c80ad1394bfc0a4c3946f00ecdc0027df8a6eae86e4b7bb09a74a5a400911e2d8458be57d19b85a8745bb512a570849a2106c4e056d2daf808aa2573b0821de97a5912890506c2152a9a1ccb13745b0b29b796ebd6da7bbfb10c1c855de4bc63508af19d90456432978e15e2b5834d92dc8d282a24073cf5cb8673cc30215d8125f2af9213dc454076463dc6638466e5a36a81edf9a022e2202a6c61148bc6ea0b2ba944b3ea86b6bff0a3cae8f3f03ae4bb7d62ee5fa843cc001e76ce6c8a476e927f619fbdf6479edd70467867442f00842d32bd6a1b4958adae5d63ce298e84f22b9f032dc219b9e250dca5d0e64ac607b94d30a0fcbd8c44434ad171723adc01766e2cd99899ac4b47f99a6903029b420a069147942873df33faeafc50da8ec411d843e94f10eaca4ea6ca653cb82f0df6dab48ab3311f418c3ff02d3b78efa4279584767bbec2355e81ef2f318d0b35a47642320934ff9654adf4b1b828684c0aaefaa0d939e6d865f7a6c3f5ae656bcd946421b72d2c4832dac116cfd9362f83d76fd1c63df75485891786a8f1ea564035d666712f5b2463f5198a62337c3c0899ddfb828491f6f0d9ad2c95dd24a73b76ed08aa05da7cb058711bbb6c7a56a5b8db75b11e160759dba1b5213288ab8ae7372936cc6a9a268ac474877c944e880f1c74af37643be85e4a6ba836ee38a15df682e282bfbe03ee1c3ee8c85eb08d3c0fd38682d23d42b33dc688fc161f6e16f9728748fe19de4fc3a0be1f4a535cbfc72dc3780951ccb2cdb65633361781e9954102f03b42b8a86eb99c7b7cab8963b4a757b3dc8ede50f5afa4666c9272da34422b257cbedcf1307531a1142ad5e06dfdd757f655be405dce58401bc3eac8567b72710e1622d91b88b1c8e3252b9997ca62a4c79aff613e24fd2f2515c26bdc37f7fa78aee26bba19c0aaa0d8e25118566ced9126ebccbc24f541fc015a022d0400dea8a4f107fb81534b219f9c24d0753667106a64b9a84a4862d818875d57240757c04835e7916515125b54f87291f411eef73da17645817f45ed521dd95a6c89b9016aee3e194953cded56a7de7ea876833188f26116a6700fd1fc94658d4be5b1d12f492d00940966496a110a64497b6745028f12f95aa0fc8e9800bd953a390d48849aff826db51cf0c8a550dfa8c6a5704f80d86c24c0b9c8cb1e98b7e249f99ce6b2ecd7b76c68aaad1abe5ff74137a89bd2dc2a0bece4de43e454d9c84d9190690fddc10b3f5b7a4dfde21b2dfa2840ef418c08c153589509fdae339a61e4d6eada4b4518a7abe0a50e0e5c209a3f00e06b6833b020e14b0ee1909a8108f7d5c491b2bfcb8ccbd9514c3a41de40e35762a92e8ed2c992db9db4f6e24fd68862b79a0f252386cd458491c4683ec68c9c6d1e60dcf0e2ffca4f8e63fd70e0f98a26b660c3d1c2ca563cea0fb1adb3e56b2c087e4dc9be6f4e64ae805a821de95d2b891abf601ae52e80759397891412565263d81e3d0d09c4d8a62d7bd0ffeeaaf1ebfb3cd904d7bb80b461f6b796d2d16bf8ecd082348a9c951c952aec592cd0cb8858c38e8408c808f185da066f846ec351a90f18c8d9903cb1d6671baafbf80f79d6988e22bea664538fc4928909e7c55c1a88c734d35d43800d195b020fbe5a6b03530a7c5e7a40681d974a019a1bd2e1b5951fcbfda65502c772808923bcffd59f487b3bed8b1c8dcc6dd8ef2bec9c61dd21db6711a5d5001e199124b7073e4ccff57ed02191fed05d9f71edd0170c6157124ca15695a72a8dcbf1e0db5117cd69e0a6ae3714cba01c3447b3ad44169dfbdf43a4e0896c9fc313c8275be0577ecc3d634f5fe403ab3ba9e5dff9a057505d6219397ed084743936bfb056abf9609eb070c54481c0f495019602a084f69d6cf4b0655e634097e9b00d5faab2f95f3814b136733cc18b0d07901c1fa39fe562152a84f397f40849474b88dd752279c75a968ffceba79755822fba81c4b2b3fa557f19e9c6e801533661789d81e7722e5800a554d04b3197609c102e57d2ba110e163c35674292723145ea2201cebd5d99433fe4107ae96116c3c6aaa67f104383a7a66ae0c94e37e19aff0d01157e4b3c120c0e8f21417ef911940d14832fa52b862c158b09f3c0d91907d27fc5e81d9d750cb4292c95ac95110f0c72034ad71aea1bb96624b934107ecc4ee8c15294a00d9710b8e9bc118150fadf6cb94d913344c68e86e8ab2b42f55ca8889291d6996e99ea72f0b34e086844e2d8d48be56bbd2da9846316ebbddc8b26b65be040894cef9391fb4ba3a6901480b621b6ddd71f45e5535868c01a8e4aaf94231d4244915c0f9b22e0a6fb8bae3bfe12291849e08fa891925eeb9b1672520d4931dc89f43044df0240508cf5bd7e03c62cd847d9d2c9839caadaf02f3ea52db535b11057a89875f2f44db775165e358796786e646957cbcc133a47db777d9f5c37c18f52a8838bd84f4670b80321cea3948c5ff967c667ed899076484be64c64b2386d6a09b1bf02168933d6c014733886f250955046d52586eed53b0a9b05b04131405c1d513ea2a1651588b8b79ed3936b41b060d728227592a496fa0d2d5cdf28619adb69905e888996e1e30dc710ab201110ed35b7d0a06ba6ef27bb83c8f902a981a05cb552616ec8886aa4c18d074eb8dc13428eabd0dd33033f55c92df9f37f4679c093e3bc87ce46169172c8cdb3204dd4a445be613a6142155324e56c3fcdb7444b846bda146be77e3aa94dcaff9693cea22e8e72b36a6e102db8a9d9c56301b6997d31fc3372da20c60d887d2c78996ce02843065f0a95a392e609384ecc20f7e65e1213650cd43bb992d55cea151ea11a22ce849213013ea286c6fd0e4063361970c2e4a58c4d6f2c0ee7d3e15d942f496faa9dc3762ed302e984e56526cee4d4db2482c629cdf85db89311e9ef96747553a2d6a023f9de6c5c33d04f5d5103c3d18a3edee6398818496ba7a094dfcda7de3f1b19a93f90bcb7ea36791a076f683f77acf46eaf7f4edfeca70c04449f27fc55749151672788177d5294b0af77a4a1c10ec3e3ac83c5c4cd454d2f5be1a99ff47ccb5d91440b2370ac2edb81170ae946d2f43506b410aaa57f2c50acdadacfb21fe949c84d6643ed0c35b4fb1a0b090b8a7f2a226975ae233ac8552a5f5a8d559fca9f2f40770600cc27bb614efd19240d57cc1c805de6b52a769f9809112b2f29339b25d793ee6f21623dee3a95bb8b9e1e9dd87d07e640b66d3db683722c3fa4924d52cb09e15a14e518f339ed202a0f405e33c251c69147d9e296c605ff121b47922b838c807de58223210803cacf4f63ed6bc250c160ca8b0c829ac44f8ec3d46f7b49dbe7c3549954eabbcaf1bd09ea327b194231b3bb86e786d9252c2266cba36e0f3c9603fb26424f20a92606af85afd91807df12e5638460c0e32d7a14cbd803ee508c4bd8bacd98cbbacb1782b9746da1928e2beb1be9924682d97364b924198554107f416e51056ce0aaf68587d5e3299406c95943622b45838f6dbd83ee8ca2c5ff4e1590f6004df4894de68f4d925b586716bd0a883bc84fc5023766835a971719ac5f01332dc70b996df2b7452cc8bc005b5e7120ecdb3fad4b00c1011c62fbb8130b49b4d62b536826668eb0027f964ab0494062297bfa24c7416d8dff27ddac834973395df5c83e869b9d854d329c6b95c5e182fee2c0aa0160f99ba9462181342489a3002dc329bff9cb93dcdb52e8200638ef182284e52a27f8badab838f672f86406f3d570270924d30dad28950a5cc820a9f69d9d7358c8530e9641a847a9e24e1af304c5dba78e934707533497a290185c62cdd590488cec9f5b738095464f5280b78479dd9f700a35786f5f947c206ab38040060d3f5e32ce7aae9979ccc7103cda4ae7427a9290a93f924036df7237414619dba30fda24158b7d9eaf6c9d80bf5cc227de00f2b6f33a954ff662d2fcabe5a280c79393a84590ee517ce6cb8c71480d6b661303eeb7a3fc8cd8d535804ac104fcb278af55bc16a78a68a249df1dfbdbeae72f2f64ed89d3084d57f1d2314a8fbd882c4767e46793db05846b1062b4b6cad34602bd3684b80c95adc90e03403c6107c9da5800ba7755b669f6df84582a5d1d0e3eeb6b3939b800e6e7dc13183da185c1b6bbcbbf1b7540f8c287aa6218e3da4a02472cb4c753fa47422124ab067afc0c4c97af92f306d26cd1935bf01913b45c4ef8c811537283b0f6fdf46e6683419d194723a013f4bb8812342627ec84e6bf2d8bde46cdc598b3645d3b39f20be70b6d980ee0243265ee46e45cd7507396647fa8f4f4b078bb3ad098c409d9f844ea54dd3feac9a4c08132231894b94d84eb0f50988946998be46b0c1df81e0c711aeaa6d5f8e18ee153375928d1d61af449d5cde51c7eb4ba9a4da3b432fc4c9970cb81b6759f09f2c510fd18e766744bd2ee2201a24cc8752305f6e6f8dd81f0c4bcd06aa0933f98f1d3c7bc74049f07389d2c0ea9d4ec6a00e1f3eb85997862409b67682deaf6be268afed76d45e65e039b46a9e55a6e499889589a98c1d54fabda8cccd309e9b8c618ac454553714d2f6314a3e4e1f98cda1c52bd8e86ad9626a5146d0c99df4e93af485b106d808cc0419a27c3884c88dcde1271a10fb25a539357f12fb8b358eeb36ce11149192c2f27e5210f6c2da48dc66c0517ecc6d88be01a83913652af7808d9032748ae3f39336d382deafecd369867fef9d12914cc515d6f19d8c9fc2d985a9c49790a0415f3991da90ef4f6a59bde8825f9a86fbd85169f8f63b813673802b9b682347d5c441230b05990c2805c4be808fbe44574149f528433f9c765b72a11b522addfe8601f06bb31052d7a426950975026b90339bf1712876d35addd9d9a757f36368844bf6d30a287640e52bc299b8e12ee80c8fb7e0ad443298715534ee2368da5cd300dd0c91557d9fbd80e9ee90265d6f0ff3f18a7e18beaa49c06c8419f09f84848246a40a304554a8ef57cf455a06b8ef27035d811114f408d7d23083e0d5cf201416d809910ec02b909ec4dcaa2e36fb242980a0d66cc883a8c290da16fde8492797bf2e3d5859fde0ee264bcaae1a5f660455ab2dafb897f63069f240500db4b0f3641dcb19e4be9e16abf66e8d40c272d90707605cb647f8c8f9cb367b9ce5bfc451fc152f304ceb59dbbfac029009493460bb529ddd64312abf0e80b62a9c02657add86e53a10bc28faba79d465a52f95bcf2c84c1986134efe4c8def989c4cddcd3331cd517a9ac7daebfba26446d2ad7404b520db43f495e6d1e2bb134087b26501a735111eddac6eda5e311a37b1176a3000f2316f20f1bcdb466c285ff9d802c88452b260cc202d1c302822dc1c3018b5e61a0b542a15d6bc80f88c34f44e4af2e69471a571aa8a188393bbec2adaa01fca82959acf4a7bc79d77b4f2a70f12e85098c81020d4a4f7292d4afb9637b1a186d50a321747c5e43c2ca86fc5a354d7937df44ab6c7c5b311f2f9d325836be2698dc2c61b4448f3630221221cc150669fb1336e498e19bc75481b48bf1c010e59028aa7f18bda6503092ca8900aecd9f33416f24673289240abc068a93b41622798902212e14f347e7aab016379fed817ee6ec47836dc77b966299769668a93081901b678ac7c752655643780988eb9bbeb58ea5b2a9f57a44eb3e782c5f47387eadc1b305f8649c001310a068cda5b85e3d42a3b3a2057d732b6ec6f70201288909fdb904b7a6cd26cf7d3f19662a725adac0b6a885d31a4d07c4f04c3e21fc37de6a0f025cd7d67dd35e992fc45d8de9c39b647478bbbd2ccce5ac1f2f3eea89cbc0abc156d1980dd13e9b3a4bfd63375470b2c06586d4e83f3bb6c915c71a7e2b135c523c0ea1b199b0273b7a68f64638db81fe0f4fdad49410212d9946ba1ed13d188702d96dec41157055273c86cf7a638d8f3652d1fcb3a8bbcf468eac8460ee2e02a96d8af81ea07b39e4abd12e7541ab94ada3d6038f51c8c5a02378e9b02cc81093d2811f215534f60cc001009c7029017cbdf644802ffb18514ba7fde37650bb9c2867d9784815290626aed4fb3da6309eae9c9f05389a6d77c951e2f2afa90f437e7432d87a4c547a84f44bbb6d6e41f4e4021cca122023577930c5720be83334b8cef5106c98d05ca5048ff82a00a179686208a019e3c09715cafb3efa06880a218ec528ba999a3c987783b647fd49c24e3f92de33512821c844f653fea0e41f05666159d8d1c6e6be8c62b0af1759f2d59b3d051b4e331ba638e59ed81e84140d4e54c758ce24b6f8f9c4c043b891f9d53c0630742bd7b16d0d1d4b28849f92c193df6158b6c20f05d0b6f7f916785b33311988c8b13bd841a8ae47ed96f7381a97d4c115592407cbebe8718b2f1fd10eb5199e4a9f2b29f3630f85553b87c5cd9403b35bd556be29eb15eee596308995dbac1c700eed3b9019ba57278580d2ac0cd7d4d933712ae57f9f50fdf7cc9acff55338a4f9d7e692bbeb5b31fc5a3f4ff14af7f4a76581a5a4d81a6089b9321508b3c11d0c68815b5ef9a550049ea0eb5764b8eb5a18f19a20bd01d0df3c3cf31995e00b607e6f3f0c781f4c5c347cba5b1aa218df8f63704c0d78ae927e6ce25c0fcabd71c372e671c15010650780f15fa6165caeb4298882229365f21461d4a12042492688d2aa513435c124556d228bf380cb38cdefdf2cd76eca2fd7ea88b4eb7b83f066dc219340900103049486cb629fa6fc4b52aac615cdeab43dea128e287d83d79676471cef2dabca57e6d8c54f4fff3a40cb5d71ee87ee75311641d5658ae6401bcfba809ada21a947fac6d741bcd67ababce379503bbded614b4e5829d95cfaae7a667dddf4e840bb23abda50c529af1c507a21e031e14f1338a7fe29da19762042b0d383d8187bde1b7830db3abefd0413cfc7105152f848e7d9795b12a0dc9074ea9c4f76d0204938fd56d9f6eb3361579e962a8c5712e35d85c906a40e5200a5e44c705bebe694d82e2bc623af5b9287b3b9ccf9d8f99440a4a1a92b34fb13678790747ca82d95c1f1e7228fbc5b74c32a03fb143935fe538ed5064a0a790ec1ac95713a27098c1b33bb36b15f8cca3d398f7737d83e261bf2e81e52e2a99e8548ec5789b39f93780fe4f82dc916fd21bd285fc96005bf8cc1c0c6e262862354c7a7a2bea157cc1f20e0a83780dc172b7a43ba4683add0627004f9bafceec7d844b899af437dc0d9a390bed3c1653f42f4e38d029ad174c00214aeb79e9af18d64ea10afd03bddee1246115d4a16f6a84845d5ae8bdfee89640bc9eb988d09f751c1071d4fcd7a888257311159a56ad06f2378b1af325be2d8e28ea9e56c331d269a923eed55431ffca5eb4ea55b0be8ad4dbf63971a929ce5c0197dd3ec52f99c08d168b3f6aa03d300d8ec4943221ed80ca04cd3350d9314c08e95af9cc4c537b88e6257d8bbb4bf51cd622b6ee3a7c94bf1fbe84d2ccc306903b06eb510e80dc00209d161694384b5f8b0edea2374b880c6b9c62e8e0bc0cd182edc0184d6d717c81700b40258f88d5d3ba9ec7709652e570158758af6b47e1d3d4508b30afac98916495a94f64219dff302e8bc6bd40003ec7683d4200698f9608c482b678907209863959d80ffd8a5bba9521eeeb1c47dfa2ef0122533445f2a515333b8c005cc7227c34a9d6eb4c56518ff37688287b2dcbe2870c830fa37249080668f8efdc11dec255e61477b70c59c7c5e7d47595cf797a881033473d81e7b2d20d260b92042b2b9be066c7425a7b1a008c1b47e402153f52148ee5d9ad8ef3f2e4a11ee98622ca140e05c11ebe21004305fddeb78896bc8268169d9df760d38316a25f9ce36d408bfd02faed17e689020490e624516f7b032f812844833ceaa89104501f038cd0a9dd287d8aa85c3bdd1aae170bb0a4f6f160388a8418384d0557555079048f320ec7f353c0c08432a3c0fcabc3e794c5f16212a3e0882ddd63248335918ca4d22909408494436861c838005f9c857f3c75126abdb189cb89a0c7610335a6df99158b123870c26b65fb80604fd2429c17eb6821a755012d488c6cc2178fa62f065de993efcf229ddc47bf325267cb7e1e74c2e9c610e72f72c2c2634c760c89822b671b7263208db68840b180f82b975644ba5c01da7568566b21cfdc5d6f3a673109330608cf1eebcf638281af273dfdd82d81c60627d9d4eeaef9159259b21bd9b8f272f5aa3015d601068743bf5e186f7204be06194126093278d30a70b42cf7e6fe64c8056bfc64f0d9b78e906e5d9a8b9464adcbbab5ab015e3c03816969f13c9e495b1fac23390348f5c5e60a296b497f6a9a061e27bae8d1b4e884236a500d400817e40531e04a0420744a6ed5d7ead77e08e78813b4d1205c667cda20f5663db40e94abfefd9818d5e01f4e57dfd6429100a505ff7603e28c0e7194a92f1705a40407021298d3dc629a5c0296d59d5463ff5904075b15b5a94e2b1133fa8d63b896aaa56e08ebf6d3f14a047f3bb7b5abcf3cf600e861a27d10c3abcecb8a285a2524c952dcf831ee1f3731a5fa91ff5505cac795d34046291f39a4755b779f25cd19c99e442926d80147e248cc000d0f9173d5880ecb7039aadda8a5d3054aa9a0e39eae8db1c58faedb4c9a2944dd88bba7c339cec2a0bdd39357adab535cd3475c50858c67fe121be8ceefa67f4c101200cc1a030931f8f94673f85ad65e2ccf4fc99d55fb7522e8d26a3264256f626bbdb965b4a29a594016c085e089f0849808ef8501e2a0e41633407295494302845435cd49ad082924c2586c861caa484c185d0bcd921c3f22cad441e076ac8b4f46ede4dab9c42d4ab326fbdda49bf9b1a327dbd6aaf864c5b0fefa4dff551b9b0f60b6d2c04dd9c2ea5945206117fc2204339a594724a94adb6da6a2b6ada8c826e4e29ad95524a198e732221a79c524a29a594524a2967cca1105151ce2ae26dcb991b8d8868b36d86dd9d379b0a9434caf0d96aeb4d2965ce92e3388e931c2747a3914b131de9799e27f137d2f005a0a2cb7b251f6d2bfdbeeffbe6f749ef1ba1b4e7e27492a4fd5a56987efd860078dc755d87bdcdf33c6f2365128944ca1ff77ddfc79546a552a934f2485f5792a88c1a2fc079df94f493927ee3055eb29ea4e594f51b67f8ce4927a4350882a0c9743aa198dc202a968e68932daabd741549e732515121e9b85051666bb7bc8da20ac9bb378888d276afd83da2585a5a66cbca0a49a7935151ce39a7ed783a222fbd636161b12c2c95b24c16a9027f3af8a30b3f1d1c7160064190821304a5e91b479586c9960c6718e9ba4e863248100d809f873ba48d2833837a41d918f9e8f29392a6cc0cbbd1beb6be2ed9a06cfcf4e92f76d48d66e697645ceedba7f5bbea7d5b4a525ec9ac56ab6a3b6f7f9f7b4e228dbecf2379d94af932c87e43007d4152c2e51226978a8f96c6c70c6a550a2553f3f251ce5c3a7c94351c1fa5d00340ca702c6d1c6eda328eda307eda339eda25b86a93e0369b00aec27e790abbc6bf2df3347b87c67736e0394bb47c0339c7866dca9429394bc47887c34fbe79df7e7ddbf56d1da056a550279b528e6fdbbc6aa736ea6473f3ed9a24dfa62179dfce91526990a694436ffcb66ad27ce9c97dbffb3cd34692a373ea390080a3c3f5aab139a1522a0dd2a87c9e530f24a2bf5d02a85529d4c9a6e655caf16d1294501a6532f2714547df6ed1809a66671b981902dcc8e060e98dc35f5b05afd92938cdde726066760571b87619191cae82430607cdc697665b9a5d6936cdd1342a1ecd9e39ba047023b10949d84868c296cc9652c411d3c1883099667fb863030db09cf71c8eb3731c85adc37d6c97a3b6e8a7fde2a96dc355fb86dbec01b8ceaef113f6cbbf8de34d1b098d973a1d1b05776d1f5eb375fcb54ff02ec7b639a0a6c9b16b0ecdb961437c19400da8695e2e1d393bc79e393736121bb7b17fefecd8509a22a5862939cfbd3439e81d8aa403b234a84d343663fe6fc7a4bc6fc36c51c5fbf6cbeb1e0e6e243d425991e45879dfb6016a550a75b229e5a0d9020877960805e0e0aee17abbf8b75ddeb49104c0551b090f2f6d4f6d245d00022000010880c66b6c243401e0b16de1b76b805a95429d6c6a5eae168f66ef7095bd1ddcee7ad370d59ee1df0e4d30c13b193b159e9cb54f27d78ef24e85a4833ab99f50a770efd892c2f8de266c4961a40c3f6d96a3b4c8f2beed34a056a550279b9a974b074e29c7b769805a95429d6c6a5e2e1d380028e5f8f60c50ab52a8934dcdcb55caf16d19a056a550279b9a5729c7b759deb75b42efdb2c3b3389ebdb2ba056a550279b9a5729c7b757a056a550279b9a5729c7b75540ad4aa14e3635a51cdf56d16fa740ad4aa14e36352f970e1c009472885e6aaf5cef16576d16ff36ea4d1bc98d976e9c66ef2c2155360c268f21ff8a7713dc528a2d5bca9bcdb2a51457561b0609d000fb15d8dd20e9e8190d9a42295b30deb74f47a81234898ebd3395e870dde4db2650ab52a8934dcdcba50387f76d10d4a51c32deb7b5caa6d931d019b42a45c466cf214a396af64e4dcbfb76e969764782f7edef4d1b490ea7017529c7f785b93a0906a1d9e4a97341668ddeed56c7b7b20829819a1086dde30e705cf9481eeae77cd7aeddf38fabbf9de638aeba5d09b283da5a6d155ad46dff6e9eb3cd167b9306b49bed9d6ed6cd24161a08ea66d939aee8ed1d3a49515391ce5bb30943dfa0e77ce452a4a274e19022f5156925e220fa481d97f7f55b748b4620025947ad1137e8572b087c75ec5bd0df95c5944ae1de80af9b84913286ab82c770694c993245534b29120f8e428e73172df3b3066b7f3ebafef6b5f5c12da5a8b794a24c0d16fdce7aa50d3ae825d7da3952018480a12eed70e41c7f2e5b965a3df2edfa6857e7c6199246296985d20d506ca1679ec10fa62e43eda7af64a1afd3ea7307d97ee8ac3f7403230f35ea261539efb85dbf93ae917bde71241d2f8fbc119727e568a62e52371aedf9a4f99d97391f8d4252018478e17c4eca96fd4cd2c9d52d6a56bfd756bf75e6cd8b45cba3bc933cb69add6325fa39b4e2630daa351fab5000a2e011f39cd077c4667242077dacb49f3bd589958f15a865d623583e562364f8588dccf0b1f2f0b30ef994cf13cac78c698463ce33c2316b19e1a859e1e82da30cc7127ed47b6709165fb5b885d597856dfce1dec02a6789161b30748baf9c85a5c5b7169696705f2ba3442bdbca1cb53ecb0ef7ce069c8a9f558a9fbea21f6e29758c358a953dbf6537596d09d0007b16bc7dab9595bdfddeb2c2f816fab952d928576d10e52a3f9d508e512794caa65073ce5ec2671f4ba05276ac6c5bd4b63caabdf1c816f5524d9f7ce4da55bbf4a59af65cb5bf21d5264d1fd5f64aaedadd976a5abb6a8fbe54d31c0ae5dca7f60c7c542865eb1492744c0fee71de30de8cb268fa0cfd686523e5f9d1ca68ed472b1b6bec472bab437eb4b23a670d52eb569b41c124e6ccd58eecc8ea6cd46b0c76ba24d51983ed424afafa48d5abeef22498e95dd7715cf5387bbb3d7fb451a2b8c2a40b13d41f549f42e87461b3dca8d6d1b601438fae25e9546b7325e9e4cd574fafb5732564346b13d4e9f53a33f33fb2e67c64a9d71d64e6299db55297d433a5e10ab1945a5185c81e8f6f6e6626b76f66c4eb9b5b15340c06fbea37065c22615a5170efbd9925933d94c554a3561b49c7decb5ab95ce67799a463f1bd2e33cf6bb94c65cc408f284df2465c584b9e8f39b5e7750130894303665940d4f539901d20b12ef4085e8ce44716900fbe884091c431c928627a5106f62508888a99355342c5ac8700ca6ef70b93971a155f82a609b40609cc294fea661bcb0f6a5a083d5b31d9cad7c8671f6598f8ec323f12a7e4b97ef1d9471c433e3b8e9720120aa7b71e1793fd823e9f1d8ce5ac3518fbfc2371ac676fe5273fbe047df61a0122d9ca5ee301cd02fa5cba3c9fddd6a2cf4e825975405b002671509fe593d8670702ab2f2f94808ff9a35094adec3e64be0b91685fad3210580b120d240664878ad9b9503481a63eca27b0cf62f8fef93969edd2d0bb57caef748dba7413eac2ae8542c985269aab0e68af491c196f35ec4719a46b2b14155360f2ae9958f758bad039fc1116808a560c41aed5a868bd078d61811e75ed0691909016a2a2686b7756d3422950d7885ad528d130d8b7a9811e75ed758dba681321ea1ae282481751574b76a9c3d051b414eada8981398044a8ab858619861ba2f6cf36844eba8c3885062c199a6104a530a90bf428879c00d5d775eb154f5a6dfc54166c6061306d8f27ee172c7417bbf870f510be21004ae147f641e678605948c10623171df4d050ea88230c21c508b21614e8080c660323394a942980a8e8a14921449b22f6338ca1e6a8398aae3edaa774e6da4393a1e2a4da872972d0c57b5018617ae090184463c468cf1845f48cf1e3639a309f7246a240312265dbb65a5d8e76b312e38ab79c3d7b994b42898c849579f1001e97b79e33cd73c88caca3ecf23cdc4d78b3baf11b1716d0173af0424fdfd1037d23e56fea0d911fe5d0037886acec0575f630bc69cac712506ef269adb556c8cfce23a950f8198ed86d107afe7516aaa71c159a1c0c479db32679dde8ce23beee7146c1954adff77d9f4be944b87d2eeb27fe37f39f0340befc46e254ffbe70f65e5f330a2923a2620b2c461f8dd3891fa72c0b49212934655268a6863348b6642cd14e61283ab281f43cc6808b481996b33cfbbdf7e6ed426166643cc8ab11b39c4519dede8d47868a332ea27d7c2bbe5ba6529af66e4030f29efee87276fad09edbebd60b65877177bdb3ded5ce8679f331a33eefea522349113ae9327a3f4ff7a82720451b8e407eda10023f9d65bc40cfcf70bc1e0f99013eea4d8b8ffa9bafa8b8838a79344389e626f0027555ce473cdbd1ade8b8aa9eacf6dc1e777843deeb797a6b7dad1c50fd46215d0da0e20df23cdc36be2eeb75795b54a8d2a757172f267bead5e9cc93f13c750748570e4f9df65418eade10cfc7865eac03babacc192bd01385d3773e41e8e9fdf4208ff2cadd3956400a9a6c216a4f96313691057ab43e730bd427ce2eebd66ed800b36505ea5269189848936618d124a7422c781cc0618b0a9be32d9c91b1a102a8483db3f0420c32cc707d445d3988a2906ecbb0e70ea506e04299192ad217a888fa18a8489d148e36eea2383343579ef7824f5cdd862de3fc1670b8fa4aa46b8c0af4663da7eed239e7f9396fbbcc360a572e5b6419d1351c5939079bcbe86877e1a83f7fd9bd1e744b76219fa77b0f8a2190b59e1175fe1b11e6c2b9712a38ddb0531cb6ac601fbb7d210f012ad650afc857100a537b5498ea7327871419c6571ff7575fad665a82f2a5ab8336f46446ccd94ca6250d4e70eb5d9a2187839ecf717a055acfd5b1cb9ce7d7dfe6266eeef5f5f9b6cdfedbbabee8a8d63993bdee1c664c49928a75b31dbd5b0c75a1002032b5b6ce79b37a206ad7d61bdeeab476c1841e678c02a187c2a89446167ad4f9a6ded470bc32bd235759ce5acf9b5178c3d53c476fbb995144d76b6b18561b6445230b3d5154a47a643da5395018ea44b2124f3ba7e18f4ce90e0394e891c25ed6a0501814d99a5184164db913e622cecc69a79d734e3b67486f72a66e67c0328a65818a52ca0d15690bab65868a54868aa897249de9a3c698e27b696d0015a594dae251b1453e05ecb7c0b2b5d65af1756d7138bef0d78632f464d88045455ae2c17b817705e8814456981b9b1f6666f2df51ce7adcd8af7723a101454f1fbd6a217361ad347539cb586353d27eb5aa95cabe9b1e03688ca169bd4263cf9c5b89d3013d3f67ec37fba87be7abe7892d252560cb919788e7a33dbafcc833ad7586afe13892baab7872158bef6556ce39cb5e57e9717a0b4706702bd0f83cdae76e92eb5d49c6165a5b9bb714c6958f151569dddb66593fb79747515cb13c7bf7da6b9ddab0c5ba90b7e138df3b3a49d85a0fb27aec780bcc8191bfba4d72f32ba5dba90e6ca58f7c039ee339e7d9e366ef6da73aa8e72d52d2a60129a58e6ddb36dbc3b9f5550c3f6598e1e7a88a266a2fa57c87514574cb74213fc33a5da6e0c2ea5b18f9ecb69d5d4439a707597dc676b6e07085fbd8712843683991f54e27751f8d46239d11e79264395b6bd8b2c2d7b0a5ba90afbbbab0fa165cc84f928e6871d5a910f8b17aae2bdcbf5e656ca16b580303b6b926756e7bd0f32729d4ee7d4eb5cb3a371fd7b1b51686692dec57a4cc01d3003dafe3ddfd788c85e0961f9f2740e67ce1023a12f03811860ba604f9f1d5ed0ba1f428a6a244bd950c8f6778cca1787c68ec1dced8cacd51ef69cb71d9b7916fde71dce4726873761ac85aeebc6e3df30c6f5d661b8ed5e3809e3f6da8088476f96eb750dd664f7b3eaa3db76fa898431b20f4669f747663a75b5a5cfa89c2e6a30f7abea5347b78d21d89e34350f22b2fa11842edbb5257bdce07ddb2b9105761f39c47a10bd93939a704e8b7f8a0bff9f46da3203fe750029bf7a0dce69c67e7421736cfb3fe863d061bf4f3a5d002e8e5cbff36dcc216b6a890e557922771240ebd3985861a1efb06db300e7d8cf11666d9c2610bf6eb38f441bfe57bd02a849bb8882092b84189277c72f039228969b30a73ce39a712407829549084b6231bb447451f2aa5a4924a29670f6aed62bfdbbdb549257ae9ddd04b973f498ef8549e1aab39449102a5c8c950adc98c169356c3163f82b5b73f3f824ede3abe43d4356a276f475006ca6ccf8f1acadbda5d617dec8c7c916cd9aee8c149bb59978306916821b4a4d550647a3b3d84714574d2659453fc98bca3b45a15d89300fbae7ad776b7bb1dce495a3f54dcbc95a405c4b58e5071738ea4d3eaa1e2e65206913580b43540ad55cb578f56d35da411029d7295a75ce5636ba612e337cf019238d955846af5a58524cce659cfeaabf5536136f7d96fee22d0928a33fcf9cd5baad4e6d1fa69fdb492b480a86b3e178ffd6e215d1d913b2471a6e33be4b1df18dee2b1d7218c316ef5d0c7d85723c7ad1e10044150eb52a98be22f86dd172b9e48d74b8d8a5dd05fbf4412e7e457e5f75ecff2a5e2d7b57cadf8f5957cadfcba4b1c945fbf2ab0ef56f6aaebbc1a407ac32a7be6745aa804027dbd47c53b887642c5cdf5d0cae621b4e231f48347adc26c5e030b3d6a212da49d50d7f5cdfe06a640cc014c220ef9eba328fb2b12017d14637f9530f1d7c7979fbf261f7ef3f1c690bf37627f4f2a88e2af8cd8df564d060ccadfd68cf5e4af8733894322f91806fdf5914534b28afeb2a2fc1d5fb0300207e5a34acf4ce28cfeba0a4ce29c66cea8127b15d95f1e57fce6f2c5a3266136bfcec30af90a613c6ef05bab8704d8b76af5c5a316c2a8b88536f0a8d5d7cbacc2c0a8eba516da205d2f569c12407354c21a253dd465f2cd7934a12ece37e721445d9f6faeda353d15667b99d557cd4f85a951578d11f962c5cb2c063fbe60f19ba34e610d4f137af6236b36001e8973f22d843d5108ab303f3790e22624a130f29b84a2e7b7148f1026a46f707dbb3e86b1df54d753a71bb6ac70fd73f9e3f52f07dab455626cde715ef53c8fa403c3c96400fa5fd83aed96a9d5aa4296c085ad16c7b578d4b891470d4c02a6005462f2e1a482dfbcd3fbabb556b082fb734daa25926f3e4bbb72bb1b225d1d9198c499be1591e2e6e3a57542d827a31f89d379170427b898c4f11c86b98d8850576b46bb22d2d582428a9b6f4242b0ba208424239be4de9ede9a51d775428ad4376f41417bea1b756246a24f3421f49b133cfce6236bf632d9826186b0df7cb47974610e508b478d6bd57ef3564de28cba70d7d99ebff1a8fd9603245b3c6a728a1fa775d2655481bdf43ce79c73727189a848ef50e945dc13e223d7478c3b2228d455d423716e3c75bb710cc3a848f10e9611a12e9e39573daff34a05164a7b99ccf8ae7a757b4ffaeed23be5b577fb4adf594f9481b63708ec895d26a20934f6f18e37c862f008e8a3225241e99138369efa2dba44170a15e98dd213450a75c16ced41c31fb4246d6f3b2b34f5fa6108bb2de8a4cbc8c97ef38efaacd3bbce5a29dd1b8dba20b5a823d500d2a31a407a540388a3f7e691d700d2f5e515a2e2e63d68b7f968c31083fe6b856c6d7eab90256cb7091537ef6e6dab5981cedbacf5d624cee6c3f4351ed02ef8713ebdb5df9cdbf36f4de2c8d016c9d6e63da8177a7232166c339ef45df5b6fdbda42e4ba79576fb64e9bba96486bab69d5fd5b1a7f0a3bea8636781baea638c633807ea925117e7d8e5b18bee420389199b9b6d731b45e2987ef32b7487eacbfa567ff35b445d323fcbdb77299c40450cf6542374d265ce404faf08d8d3a3544a4aadddf38180248ec8427d65f1e666f6d8417dee21defa103b7a5071862d6e6d8f1d54b49eb3a651d1ea1915ad9e6dd4b1a6bdd54aa8781363023ddedc20d2e34d8f1e3da8687dc78df41bea926ebd9b5ee8ab84bae4df5498a0b75e43a4af8f3748b2e7f086ded0104167a0b71aa8be727e4a42e1024d49bf52169afa0d7b2cf5b028759a0859d2444ca0972496b59675efbc5ead9df3de39e7b41205d657180f741ea5b53ed14468e95d2973a30e44a1509e09852fcaa22a0a455112f59534a803a88309d4019592a9542aa59a2a954a05ea904ad5542a4553a914683aa15029d309a5e3e22a920ecacb2a2b928ece0a11baa58543a550a8546af5a994567a056431b578dae48126944a1311b2b0b4c898c162c9903163060d1aee7b872e2e366c541b366cd85099e1ad684c1a2b335868b4b0c2b086210d69d070df6158a3868b8b8db0c6de6158c3c5c5868d1b375e50da85a463a386f6668d39278eb93131362626a6d219131323b5e762e3c6bc71a3860d971b365e441b376ebcbc88220c4c4c0c8e97175184818989c1814346a6d59a9981918991a1b447a53bc8ac1d51022d4146a64542093339686a5a2df00812482001450209271248985a7475c5921b8599e2574cc2e33af17c9ca9abf5d24b34d0a3f778f33c54cc4b2f65a147ef615ede29710e3506093d9d5249a9b593526adfe210938279ca3129d0d3e7cbf1d6ec147009b8045c022e0197804bc025e0127009b8045c022e7119a518439fbb4e13a1e56868c6334273dec92a27b51daa1b57282ae691f579a583b276daaef31169ce21e6688fe0109f9d823c20112ae66d9b1b28a36257bdd89095e94214d2d592b910d4f2e1074c5a41b4be8012c5670f1224713a6fa19bbade2d3344725d3bf6c9499cd2c85d3fdb055461720c66ab4761864290c4e1748fb6ae3da081c0ea4b839e1d880c084f7d61cf0ea407880f9023244ec9553ebb7ea88eec738faec7aed967770db988240e97009a7343974f17a3cbe7330bc84628df40b38066ce02b0832e490bb8ae4320b00a93379018177ab41182d9d1b426a653e320d0238dd0a869846886240ee7d969b6a021a2117a4d13e573ac0646c525406012877e76203b4062f53573563e9f9ff47c06651f5be1a0877e94423d2ccc20d02371529f5d17a1473026d4f3d99bb3256bf9d00aa2f545093c9fbdeb76553d91a20a8a8a07d41315916ce5eaa14a862292ad4c841e411f950c0be952155940480586149da8c610a386b7ae520511b0f8ec15105a450983677a1ec3211a520f07b5561fc3211cfcc802226921f49db586c8916797632b87b736429dab8aa8cbe5e32a30a4cb9584146b62aa3146952a3e5c45d99f777be42e1ffa852b09e992327b36120e15491f3cf9ec634dec2514273efb6823f4d9bb1d64265be1d067a79d8faa0b411608975eaac46c369bcd463660dd0d2078a86b3639d09bcd66b3991f33b45eb1881ee76c3667e39cd55be78c48c6660729d3bc00f663cb406de2a0fab6511cf094af2c5a123c65a7ded0c0fc615d82f4286b3e4afcd40a546735a8767ddb3715e6ced46ab51f3f6ab5da8f5aad6623067a94b57183299164836d318965a8278808430748d43004255524d991c970f0811fc05c644044de41b762814568162145e2c85098e94ca2485ad10ebd7271522d68b531449430798583aeb25ddd206235f3b2d453425134ca62e2d244bc2e5acce06b500d0be1a14780c449c034410117dbb8218975055cbc31d16dd9c60f9973b9a2ba9593cb5b8ffc399c81e2ab8fa3afdbcc6846073dce24a1af4c61a60b499c4bb512baa25167223699b2254730961d6ab1da10ad8826efbda40991440f312f694514e1bf9734218858cd59f2016fdba684154f7801a5053b28b047922cb1c52049124c8bf848e004de36ea811f8024b020a02d5104a8512bda123b2cb123842488604aa9ecb408228a10302256312dd02d2ad4bf5efffa4b5297d94e7e10f2e8d159733ed193e4abcbd8d06a50f295851a821ce9e4abe33b89a86b643d1416754dec54ec428b3674e9ba58612250159da94a51b69eaead99587ab8526aa15aed05b1aed56ba591814f4a5949416e5d415494d6f33237adb56eb3b5b57a9d1c9138961ef4749c377c65b994e5a6b3c4a413e413c0887e6be5642bbf1fd1d3e5a8a2f26b94b77b3b95177e83a88bbddfa09776ce28829eae4aa154be5a71ec30a77857d65a6bb7cd5a6badb5d6da6db3d65a6b375aadb5379e24f1deda1d74b389adb5d65a5b023dbd5a6cadb5a1ddb69ced0564d5594b6ed1a433c8360c6a11d55e1e49ef62e47532d456926c3f241de9d3e58d277a7a35424f0f298a051de75ae498146cb55abc12434faf6f6f10e9e9d686d9621d536bdd6ab5f55bb026d0d3b537637c6252a0a71c8d70d0d5eebdf7deadd67aef95b5eed3dcc8fb54463737371955024f2bd807cb5cb0ac5e4c64fae0237888eae3444fc73f2ea752c9db6e42aff0055658eebdb3daf4e9aec0322c1b45f15864ad850424f8516bf78115cb8caa93681934ae0dadac0607f4bca34e46ad7546b5d3e7d22082e90db10c89de4dc8ae6602e3c75a5b6bb5d6d65aadb5b5d6206b6dad15ab489f6619c566ac002904e995d2ca744ab1e68e8422a104b1f505fada7c0b27eca3d4664f1627f4d882522d2c2d9935e56479e1cdca1732fc5e0c56c7b5ee16e819443448ab199128e813410b6b5794d632b64ea26984b67ab947073d3dac413896645b6bc3a01a33a8bee691da53a7b3270444417af610cd9e201c8b49a2a7d71f96111e6aadb549b40995f248a595110ba3142aad3e15d084a2e38e71077ee52c6b412fdc40dcf0e441b1cc3b4b2b2cd95a1d595b3cd6ddec66a9abce3bbbe2e62b8a36ee0a71dc09f488817e46b65992468081bc7ab305416669f1caf25975123d83628c5fa881839e343c4ab2f34ef7a4f796be369e0a134e124f7dd151166d3d4f638ee8224bb4f16c3c4f6d7885648b7a0c0af448c23611a529f1b5dbf542cf6ba7b51b90ccb1453788685aa21b5d4c496b2f32aa2882f8a921081f140e7af59216844cf501ad1a43a5862e4e33fdbda419114ad960040a941346904049a1512f694680d842ab4cc141a778a032a24959a828a14935930e3c4d20e139e2084f911df4e9258d67277584d62f6945c230d9a0f34b5a1128a92134e925ad080e4e5068d34b5a11295241d0f625ad48142a30cdbda4159915010222086f917fde04ea5975895a3b279e78de694bb84a6bb5c0a244d2b1762b7da47c6d8d173a3bf51a229d7ddbb6c69b639cf3e69174b0776f474b5c68ec5b69486387e162eb94c887c607dafa68899efa6671688946249d5bc3fca3da81aa5e2754a4524a2efe0ed5cac55b5aabb5d75dfc550d22a93073562578154ff40cc7eb040516e9001d4f8509a2abaee7a9d7201adff50ca1a78f34fc942d6a492898fefa9d628aa73e6b9d5a48e260a7ae876a78ea1a2671ae834d60f1d43f23e4cb3424f4f5481c7bdaa1168be20473224a13454c3c35117d479c783a6ab704dac18828a71b5a22d39b86eaab0ea93c98aa115335c2548f3855264e15e874b2618dd99b5d3a952670528ab512a1af63120aa6af1dcf5f0d93adeba415eac310437e2a5bd8b98a81b78e69e8e89743bcf1f840fdf51523cc24cee64dfcbdf7c4f3f77a1d225f7aa8c2dc98c4c17e77008a3101c28e88624411d1df1b7ac744134fb9213c5c6c8727516a38faa1b2657a3d545fb90a09431d0ba22d74d1932f60358b117bcac176789a6b348ab05556d9ba6eebbc2e554f0a05336fd84485be2f693ef0fc30e4071f32c0a40722fcaa7b49eb01ca0856da730f4e62767a3872f3d83f960f0f44243dbb19174a8ca10329b0c0c17e20075dc85e7870e2ed09a364f2980256c8a005444a04f520075b231e67f1c4e3d4638c317652e347d40e4fb0903df1968722defa88a4633d2928b5f1a3f798e8b193c73bd074b07705ad03481e7b56e8d083c78e7dab81623c85931f3c96d425a9f8d1a3e930440eb4b77e8160b1cde247d4631c36c0f2128a28441ebbee798c83111ec6075fa462f80630784d4cd2b9d972808a0f07adb58a75c316f74494baa10bcf24460d7543104620cfe90629273d849929b683572202181362f48151a443403a418c588909d03b41cacff7c4d70d9168ada323bd2a825011863c7d831117c6acdb410e026c140b02691b43c6c5a67c589675b89708b3ad8795fd42084f244cb3ca1c46940a335d49a62744b1b48e4e0e8c1cc020a2296d08151d1da230f23721105118f963d640cc346a755fd27e88c10ca1958c0a133ffcbcaba6d0345ed27ee00145d3fe9246e40b0fe8192f6944ac503142afbca4115141101a7c49237284ca0bf4f69246e403261d689597342238a8683e4881424739c187229a0f468c51c4db97341f88b0eed2445e4c0ce611d0e7fa084889ad2f3da4da42baba1ea468ddbebc75d51051d1dbee072ede8eaa216f5d159338d46d5774a4a794851ef510066354d4445b874145ebdcd651a8683d6f2d6583b00dee58d7439a0b2a5a900815ad9d13e40189c404e91194813250f67604c11fea1a3508545f930445600f75491fda5b0795a02e4abba109135008a4bd0da2faa8540d9755390a99a11100000014004315000020100c080543c15096258aaed90314800b76904c745a9c4ac3518ce3308aa21431c6106208210018446466868825013824cd887d3a488ce1d8aa9a05ef48260268019a05632603e8cbfe1872aba73e1d9457ec2903174da4f1dfea75ddd595e045f47008ba639b2870b30d4bcb179572e2cbeacad3695cf6219b58c5061caf25e8a5a4f2753568b455e45a9751d2ceaa224a12205747a39bc435735e0ac7793aa065d1c91fe7cd6da324da72a824943ee5dc0229071346821a4c483e1acbb91073d738313a28b72fbab0afa0852f8a392238448097a346b85d994db43526d4468f891bd698449668265141cdab1226752f5edca1cb9454de0f77323c902d3cd2a8906e180746e306e3bc96bc5f974857185e89bb45d10ca0fd03585c552f9d51efbf2722dce6c8cec469e83678ffc13a649bb537da0ff0a0a76d65f61369ee0da8c4fe04c216ae60a74db00e2637bdafec4247925eb4c8e585505c51734c7332a62132f5e434c9b87b578936976f23aaaecafc0d2c642943de99a5068f799e73e5bceecc1ce1a7616e886c1981a1f15b74483cb575e3ffd72986e5bc2ba8f850c2543237ac2f025df979055d98c5f45f08f6874f498b5ce8bd8eb40dfdd27caa2cf84cb461f64e1945854a8e0e60e389c13d8cf766e35507e2d2ac772dd4844fed77194ca6ce27942e1ea7aa9bd36e2c034ce0fc812853f546817736108f0de26042c196bdc6b574a5ab34588f6512c1cdfbb0dc762c0f25b4eb9f0520faaeaa579543fd749204d3ba2fe8db9f239bf0a032b83b95cd1b16ed5913944c577a20ea66c3aeaaeaae5d69bada6a5c884e5703eef3352c82a258e8c67b33f414dc9adb63a991cefbc05ccfb10af63ce9bc8521a4b2a734a039e8209f4d5cfa884473f694e14c3296e36e5c46d4f6fca3eeebcfe8d0cf1ec65459b00f49d85b3c2d50990bde83a70ddf86f601dcea1932db7e78b81a86902c47ca70a045e45ccb6ba2264c7a413b6af9218fa2b0b96ad0e98765aefab1904134201ab2fb0cdc0a7618dfb12de5affc2666889dd32f432f93e1b81b17583c4a5b70506843b7c27e505c73c323c35b602f412fc337012be82d98f0c8296f9f13e4a56c8fcf4081604571ee54bd23b3110034b65193ff6be0c9068c4ff75e495bd18eb9712f801acc9895eb780dfb67bb42f1d3490ed677791cd66298f3ed0f0ff1bf7f6e900c55f4f66a6798a3554f6b6694c7c173205720f0026fabafb279efb93cee194bc9f30165377c18964fa50d7bf709aa289a5a579c297ce3c0831e461bf240fdc04f0a1f755aac80d7506fccd7312bc549a18a0ea53059a81d70ef8a0c58ce3b7a3e80c854bf1afbc62847e3ea2220e5f6b08d7f8bff597c38c567e99c390d9cf74795d1d42803324d3c0261fd512e68a0ed0f399c60b7f09a6836aa6dd64be274a494ac0e7dfcbabb74685987997ab1056460d0ad6b49237f9c2ff21566e83e955f8e2aa0a4f4d956dc87187c5380e2652ba3c71388aa33fc3c304cd525fa958f13256bf8c7e8f1adef37004b2861b401be602f5c884027913655c42c09239c12273026366c03bc6f282e836ed4df60eb7d0145fac3bf8cc7940d4b9af4ad679bbdf703c9c770b36ef0aa84d1ce7d73684874f127af9c36e41b82320a8ac0669625c726ad42bb630124482211b5b951bc7af1607f5c876a78fb81316933fc60c384fa6cd708287911ea8d4e1541d209d954837868289a2208e6fb4970bcc13a5912d16fa34e1e3de292e175f30f2483c7ed0eeeca24dbf758e9c42f134030697a203ecadc552c2603f91b8d87eb40e9df15164024989164b6b409e125ecdf15e544523f7d4e044b15b252fb69254172b4957cbe9edf298ce9b66c0ce74a58923a7745adf951a08b1192ccd0c2be97cafc56ea0b91e84196423b209be0e716659b901b086175455b8ec4adfbbe2e8471d5e602cf5280d4fb2c67af5a9d6f22ead438830f7873d13503d9b58997e39a383ef6f524452dde549a97016947f5269fd29a8a563b3700850a3f5d8cd9987a0ebee3c94a21a4ef25a7655b601a1b951af45ffd6cffdec4f9571e28e04b5966ae1602cc448452e4fd7fea82f72f29ae42ccc03fff2a71a51c2f1183a9ec4f8ed3d5c6d36dc26c95ef3af884dea22ae758f6beed0b0593a8a05c97ef3ca19600047b71795e88a81d59e8ef52e4306e9acc04d5cbb8024bc1eab3c677ee20b0202b9e4e1bd6c73ae4639535ea72e6ceb7a947a348f2aeb36ab0d52382744d19198d4cdba874785c478463f5ac403e05d995a974f9844de0e4ffc9dfe13157d2add2442696d5c0d04a1375b966d951f1f7031fa783acbbd840773e843a0ff778401a0055d52af60e24511fd3b0af8bf478d2bdd82862595e2a83c3bc95e3233b814a9dfb5855150f4e24a8ddb60b5282134ff82ed4119c3c253a33ebeae42de8c30313319572a77afd58c346175461c48a417ffb6e09e3ca8571a7aa234317e2eaf7bdd972413ad2c76b64ca5bd8cf91e5a6b16f2291526bbfb211d2d870a00b888d7d17ba3102c0f4981b920e7021b408b3a6b290cc8a9cd468f885efa604c3a9050fc8cd8c5126dc5f11034ddb121492a19f8bb88ae2dc2d96571de348082a9604ac3cc76e1019f6b9d43c588bc7b01dd1cd15819ffe000bcf1631f9df3a7676f325ed2ac8fe85ee410b4c946f861faacda34828640adce391e6136d81d06f88f8b08064bd062c54552ccd7c6fde6ea1902c81150bf21c89d6e222a145fbe3f468a66f4c4e94d343ca609aae4519780221f1ce493953a8fd862a89f10b1bccac2ddfbecdffe1969a7652fe508285fb522637a49bef198ebf8eb66d2b211321c6620ecff184d54dd29fdb2131e14e66a2e4828fa59cab6ab95c7be80a0e28336d51e91f102168c0a27ba52e13c27c21ab7ec4ba75abee8d0e20ca6f481bb9a6c95ae0db66578653686a1d0183891b691aa4f3a36ede69278fdd596c11ce9d8cd494e01e47e198e789c689bd669f6016ff65d651098ce07693e1a7cd7e833cb6b09f91d6a68f2e6dc0f5be80211efcb6a2f645b2536d8c6cb7064410a980536796ba9cdf97f06ed8b28b2cdb8bf7db2a7e9a11112e7f3eb5e457a5b40a6ce66b634e38c1a46e35cb28409679cfe5a380186b9aa0b5869b28ee1c0b875d791366d3a3fa69512ae328c772f85293da41a41e393458287b5c68bc3f4a9aa929fa8334e19f3bc185567fed911491eeea0f0cfe663f55d58e5c52758ccfcff69959ac896589923114b87bda7dc6135b185edc87e46493d80cd0118be0f0038a0fe9934e047199ee5ab548c0e6159c882579281e33d9d10dd6452b166aaaee693a9eec4a527b69348dd1de1ef11c2e80679a07cfa722486a7a1f5e73a88a769c3107caebc1fc1087e16be94ffe5861ab8a9778cf3e1fab8f24dda207b6ab0f81fe1d1a79715355268b8ad79d32578a29a56b66c407b0f69985ccf6eef1d882a88759201673ce0af2023b33d45ef3f6131fa20bf18ce671082015752f82c4904980f8b36127067c4a7cffafd93cceb1a73a49632ca4bf11530da43f439a3162f9b079a90e0ce4839728a02bc85c80b3f1b70391ad44e9ac9484cef129480e0f7188d9dc9c233e1e72f7d2b6b739f23a2bfdb8345aa380177555d1268592f4dc6c3c267962eaaf219525503a0d53b70f155ed7c9068b5abff8a69ac66e8b45efb24135aa81e00416bda4abbf2342b7b7deaff147f4c702705c3ef0b96a5637eebb34fcc19da2e2335f99fbc8e92fb76c146b3bde7f51bae9bf19d0e222f8f13f6afbd65dee2790d94eee76f84ef9aee94fc59d955709c07d05b177f9eb412c5d3b99c83d2866efac02a277a3f8091377d5a13f25eefc6493b02710e69725bba1863f449a58969e31eda7dfac34a11481676f1825bc0470870849a67ac3f18bc45fc937c7e29f18023c82baed6401408f0f1588300ebd82fbdc15c94f18bd937425070ba7c0a3328281d2f020bfeb33015e7f414ff516e2a757202cc86a8a621602696c721774dedfdc945ebc0138918bc6b9fd5e5b8bfef1ca44fdc2d6420e1520aa2b9133cf340c9b9fe8a9d023961ead4666a662fd9f118ba81d5d7214bcf4c2224b7b32bd5941da1f46405efc84db0ebdf95af20b67be6cf5d448351375a5f6e30791b9b7e0317ca1e8fa11f2ac3040d399be5920a13b6e4f4c21d836d78f236921e8a2f4d8696c9f9f4099cf310fa694704f1ad78bb8abd31c01126490f10e7022f50c32e53e104931644f83582e33e4ac94c83ad3b2ad9862b4886526224838c80b906013818a2592c1c00735d62cb7a37b4c9630831b4b17274d64962bd1250a61fd0cb44eba6125c925cf5d6e79cb3b8915b47f14b91c73c576fbb38b626f147e58e7bf90500c9f5b5cab1c31ade839363c0596f603b32318d55ae88e31c3d4ea7c10796552a26b2fcb47e482012bb33575e3149fe7fe7082e2eec46cd338181b6f5ec557c705ddbaa65ca535d974ea8751f4e3a9fd3527a1f4e67172de2f9a2fc242c39698fe6a71e8f8d575c65a88bfbd0bdba39a48a978204dc496442dfc8910bbe3c2c39452a6b25a35eb1247ab1e9e2b94f1fee746c31df94ab0d6d2117986a2b833ab710855e55557735816b205ac77e5491fcd7ea6c02d75f56331f0b508c0af534df0ad542a9731e79d61efd1abece0ef8acae47669ba8b69a7faf684c3d737814a54219f1b44403001778d08877549b2b8028baf18f7878cf1fdec056b88049c6765c15b8d5418dc6ba600970358b4063a30dfbcd07c63591720af58f0a3b726c5ee3a0664cda590e7d2840d769e2b5372c97f7bee4a037947ee17e798aa3c72e04725464a6ff3ac8022e780cb08a20bef830babd669c94ef8f299e1e07019256366bf6b06413902ba0c0a25800538bbb1027687e9e3413a7ec347d30dd4ef207e82c3b7b593578312248beaabb99078f39ce14b07dcbe04f607533d4bf1bf807644e4a16ce1920873a67f71952af7f849c072e43092c3bf175d6192f19f1d5a2748e6c70e62e6b265a167f2272890a9476c0d194d0cfa4e809848b870164d9f2df0a7ae974d74b57f2b55a087eac569df4e81429345f9a299d92fb0d3b6968af57039d94ff2d3f8f1730abda0433c88f084accc56e739ac44c69f189f27160e653827546902279574540d831c8bd02873d20a950d20a1475bd06bf4c7fb802b88f573265047a9644f22a34c70dc52cc271fee2f5b30afabea8e025b48f7e01241c69be698871c2402b0186f8fe3f5cd733876efd9df7428bc4d0639f642063412c8a627ba37e61f8d3413b1ba233a04cb67b36db5f4e40813a18610e05bc7d4f03bdbd1cc100369e8a92a3a37dc93189bea806d46b5512c8291d41dd0ab6aaf5838e5509bae0a72e410f424de15a5febd4ecdfad4c2c7467a7adb8167d42cd0bfca47dbb75b47fe284f8e98d530f1509185fb49cae76a29640936242ddb1fc770bf2f264ebf475e75013b27555ed29c5193e5aa9f289394e9336a93e5be456f5c63289e1af4ca063a5de4be0a6dd91118a717ac1b8b4761d2170d600d3911d3619c8216729e503564d2d7ea17791896f46cd222576a379e0ec42aee2bddadc0ff9952e63867b60935567f4570d935fd84507e2e0825cde7e8dff4bf7df6c94097fe6a65f6ac3592357173520f05ea279f4509f62aeee64b008bbccdb30a7c47bafd2f95807e92de8799f8873d592fa664df8069c60e5d60e5712a8901f10db4d8cd9e63a6fa333af4deb15abde018f2fc21c6f33acdf8833c81bcef20839a1273bde82205fab7a3e4dca6ddf031824d73f7f01585fb891ecad443b7aa1b77f90e1d70a0ae365cfab4945e1171000005dcd78ad768de5539d3cb455625347828db0e6dc1f98614400e1196f3ec7cdae044687e80eb86b2a675c57563bcb3ac55dd6582648cbaa977015d3a078fa75546b9c2d92fbc04ae63cb0652d4dd8dc9b8245e12fa3cfdba31f475682e7e38c6a4c415e7cc9d3740649dc3de0ee63ce0511644f29da36cfb7031c852dd051f584283cf6f8b049612743bbac202cdc6d4c9e5000fb732ab8016f914a1154c1f4aaed248db69c5fc3e9404070bb4e32417879cc12a03e75558ac29ffbe2177f4d0bdb4b08b293a7f6c6ed962943178db2417975599bce10ac8cf442a2a9b7b3ed7265072f5402fcbd6a6de2dfc2337a0139f6ca761baaf57a8a94be9cb75c9dd89513fd9cf546f43f6109130ab928d29c048e5c16839e8351398f1bd86d12c31618947ae1cd9a40b939b05308d72de7d118a37e5d2791a92679b6d9081d825015ee4bf8cba0799c007f68444fcd11e744c2fa161442edaa49c59f4b8c2933332a99fd38c9660d309e04a276f238c9493dcd6770277633a900ad15d2042c13dcc42c7320b6556c6b30e88b7f7ee8cca84386de85413c88be640f94775f21d56027b36177b5b6169df0100235f790c8ee810d618137d2aea7fc6179a6a725d7ca12d3db01ba34bb29e177b50e8567a50f61af3ebca23ca87b95d2f285a18fa3c02515a2c30336a4149d07a7b8de84989f100751d3155f360601b1c25109cf38bf5b6a4a021abb0034f6af08043019865d82c0ef7cf56a5db4f9cf74a6b77cf1a7dfe76b70f162b082e491d820e5425d2141a222a20ed60e9aece2c2d3584547e71d186cb1bf21cff50af8ba5f3dd8b42fe7226cb0276b801125f25ce999ae3a38491228f5b99f79540bb011052ffee982ba792652eb482bc4dd9f0d80e857de39620da56d1d54234819e0cb3e3f6bea4f4c10daecf9d12e4740566859e5555173d20f2fdbb19988ac6413f129856b41200628bd67cca02a469c0c900a1035be2372644918b5999afaea6910aa6229990c96a91e6a856d5c53d6a3f3120373fe215aacb6414a6ef40227860cf1fddb0ae3896892aea3ed1a79480f64116e3b7b25645bf68dba8f41592d08c95db78b7a426f0b0f2cf7f3402a810d5130f5ba1310b9dfb0afd8a7ac86535670377718ccc367b82c8d580915c89e0a0772983df00dc6c804eecfcbebdd9e39640a617a108c49c2902f4fad0f29d0846d871ae98d594f600b2b7d2469ea36625e4968aa87022752134b52e7460b302c03d827af869a5036615c435262585442956a56615a410650c2e99332f9c5cec248961cacf4a37127894080ccb723fa138194130325512db5e1600139abda768568a5bd0a65a3b008e12c80435010484fe97b39c84da686105d1107b664d81dc50a3a03e2abd09f68eb4d8a4a77dc723c527fdb9f647c3d57e51e279597e1b306e3967a19464cfbb6a1b01bac404a2590614d7879a184f26c60a95f471a7c6f7f2fea9bfce08f93396b2f13585fb0502b235d257bdd95cbf3ed281013eb51e220d5f5a4743b6a953c422dcfce8682d39f9622355f47131be1acf51c634f4c1e25c750c5213317392fc0e71ed6538a9fd49af8d414a4d26f21a10750f42bddd1e74f0df8c4504adf7b883ba79ade285240db0d4026f3aa880b15a226acc08b7d109af1e81e73caf4d15fe8bea7abdce4bd5439233d34f69d1dc60245acf4031ec8aece4e00482e5083a860b90b01c81c6e02204cb09744c172471390685d9c5d5bf024094b45eee3546f0f50150fa2233de38753ac0aa211d99f260b48a08c53e9323f4dc93b7a0c42ff580aaf4f173d96c6417d0a9aaf5726e565e0972fc86131f9886b35c896d041029afa5699d06177fb30796236ca62f32aa5d8829d702318d9162fab34a25a865281b573008926ac145b257b20e76aa8c67c1f1d50d50ab952a356480d51662c5d80bc394dbc010f24f110cc43a7f3eaac94109bc42fa0695e5853d14e45e6260bc2f5d09f5d1a81a984167a9b3ed1a226894c9aa4c3124bfb0041e5527a8c662526580ea3cb38b9541ff0469b53bf25bc79f508e163114268f63e146067d27cfbb42efe65d69e259778fa1337cf40724039d57c9e8f13f8bb84ea3b49394d5f1849a549be894737df6fa8a9663b6812c13920cb7415e2974c72ae3ff81502a37c3c184d078e629cf8c001bb0e788c60365403713b8fd6bc98e71203e6e7ab2bb89e1a4286c5508eae757922482f1fa170b58a90fcf564b87e85b51ee1467ccfea595404280ff3d1e4e51869803d914164caa2fd66ecb29087257df7d1ea4c4d75d07d2a337338bfeb333e835c91f5a242179e12206bffc0dfe701a48fbe77568f4e7e36d94ae96db5011ccef54a130609d764ac501438d4bfc2bd1c62ed953764c6c0ce14bd3b7fc4e896b88b25ecdb3d5585edfc1c8eaef6395daf31c092292fcc306daf577ec9a5b2ee6ce1d1fa7462fbb7ee73b5a953eeb2e1775600c1112cb8c6d3e234e43c211e3bbac275979feb28cb6791e7136a694e0c697a2deecb1ec7301e26d222d3fa9c531a60539e61671d5b7f6838cfae22ec16a1b077bc207e0acecfab9212ba2a20bc435a0afe470a735ffcb24419cea202d904e0ff2a93f64eab59bdfca8f25ee1ac12761bbb525f500d0fbb2ad80c5f7f92b8f797dbd33ba7cd924c9de54dca174d389e80e0599492d82e968547ba7ee636d7c58a9a90f147ddda211dacd11033489ff0e0187f035816ea4f5f9c0a0bae4f8438195d395841e2183e5e667b6960d65543c221becd1c714a1dc8462b2e20b32569a9a2dcd57197d024c7187692ba606786008573c91fbb136bc318727599552990c83d187e91747820790bdae2a45987de783f9a16c800171fe8d7745989230efe4a0ceaebf30d7e38e285c8e1a4e305721be263af3d4e73ca7bcd498136fe5c8b8c75c99f07fa72c5c9bbb81ec8ef0ce6e2937e1856f1002b5a6594bf35fc3a693ccb560c51b696269433e1b117343143723f0258a55e4770b57541aa38ad2dba622804e0636518201e24776847d234163178da6eedc3763c66e67120915fba95e94f1655dec3744a2174bae3723b9ab7522c5ac64fe4a763770c92c273bcddd2f9dfd8acfc1286a70f798233ebc7f9b1554bdc1a7aeb41e78802576a81f41766f149896224e4d2209d404a5d07a568691e38dffcd2790e48798df488dee417a912438856eaacc2d448909365bb95084ba78a3264bf69056686427c490b67be0ffef9d7a4410b6bb8546da872a54ec3db823563886ad2870b1121c480c0b7850667dae4baa10ea88cbe5564958757104fb846bb1d1e9eaf77ab36fcaa4c522693882a9b0e73833932d3fc427b81cca021d4364e453604cd8f57e1dc5e98e8f95eb3795e67773ac77e23cc5d8e8f370aa46a490b0621861b2ffe940ed29000934b4c67366edba908448904d29c6b2db2d61e9d8f88d142d0cf40862146884fc0dc086187e3197104c89b0d6e2c6935d085c14566575d752dec1c1355231be0158388a97163d2a197b9c360b07a408d3722abbb9b5c44ccdf045f7892b5544ad93595d3321b5b6ef025bff16748968a676f5fbea0d57f125435d2d46689262e9d9b0e98ae1f34f97ca587145c5a4bf55dc0a8dfaa59d7d4262deaa45e15e9e3ed12140f1cc80db3f2ecd978bce982bebd3284ef52de150fce0136a0c9e393e4b9740502fe92703a32435451bfd9dfb75864742505ac9712656b94289df8d9651fff83bd2bf04332276b71905e0a6fd09ae1042767cd0a37ea8cadc915de814ce7dcbfa7a4ddf122be65bb212f3820f264d5d7d40b3125ccae2c551e21d5c8e28c55bd5db8b9d1a0ca206640bf03e5360c10998e02d20a1d2cfb26975faf78856381d029043199041ef3ce0c852557639300e0e3c764580f9d9d2495423e3975c7c0b0b42a006a511c7336176cc9d5ad00664075d8abd068474a19733e88daf8f2f1c96786e93028354c610bb5d06be669b48bdfac400c6b04272cf4705b765b8b7ef93957aa4702f418a412c93a06c39b15e0270f606a49332449f3391ac72e6628b84ae404d1ca6caa1c1dc70a1763c2195be47071217891263f6d19edcf8b5051e667817d493a92b9ca297cb23e6fb2184d3314129d430bfa9d86b09a567bf348656d0ecfd86bae211a7327626d3f6702a60828f7c0971b83d8e10ea2b310113a21ed19990ee8e3e2a624c302af2fd6f7cc56cf44efc8bcf0ad0c8d790bd2504b94616cc16ea06ad1e3efcee426a5d25274f8e6e81f06bbfc0d2a63673e18925d7fa81ac12222c340286e283f9ba3fa86065ce2b0500bf64cefbaf1f9baabe0b08215f7742525ff0a4d402634ea5f2b1dd8e2cc5124c96eb7056e9841279e298b0314c2fd638b7a52f274c88792f1ddc5331863c98701dc2841c388c8352128d45b90fcbcd67d6032a9f4faaf9a9ab1a094bcc8b74f20c5f7b21d922721c4519d56a1f895a89dd924f036ba810c20cba4c236d085bbf5f6d4bb844f4a8534b5db8f8ce4afaae03a4c9706e43c6245caf1b1e3d4701d6142bcd76ba2042ded8632e8f9afaaa2f413669b57629759e9260705dbaa0bf46627793de21a8af31812816fc3f7328adfc31f09d36635e786bf38f7f4bbf0f66d1b2e6710479f8572c8a323c57169da333ba2466f69b5df214abe46785fd1231390f978a4e2c87440dedb1862cf6eebe2814598a24061175cc13abb68795720d251f0f6be94d8e5cd833627bb524a97d60fd75a1408c5145773293c351437a8a5d6df59670301dfcce1a40c2c59f4c26d205e7622398ef0714d7522ae2489383d08298856348291b4bc949e27543907847ad1ba219364626990e919f57110f03bba99aa228376e288858d29a6724c0940540446b6605d940030681ffc31db2737f28d477abe0ba6628711815c4692187270ca2eaa994144652b578c914f18f673deeb76c97596739be7ff0ab65e96af0fb93500d6eb0a1271adaffb62b69c454e131c8e2875bea876745734d0b752734c78920ed15f2751103d167f18a59f4d5714718c7924d90338a290488a9b001a45e2c1cdd24ea01aa3db15f7209617ffc8103aa91b49db7005c96b179259c13f5f8ec629f7457fcecddd4ae40c715f11dc077f4d800e207aa2da01ff1a99725862bcf7880bc8f0c9c8e08a2a69b50dd58cbe400aecd63ae1ea4248cf88fd3b8c8864cc13552c2b555e02611eebcbc289efcbc1e57e7e11ef4b6dc22696531e6ac755416aafc049df63b35b0eea02ed133a1e099b6088251551f11b6c600527345ab5ca63e172e709de81e3c8ec4638b610fde84caa71973d540ebb492d120c31a991946d5ae02593cc996a6bf8a83b490bfb22453b9cedb0e14e4765b4ab7ab72b7bbceda82ee3ca7100c4b4779c079590992a22260bcb0f9e92e545915fb75594b7240a3bdfee17db6555f52a78a7cf3b895e3bb8d91135c6b29f58a86c90688ea78b95a065645dc6cc0ea80aebf4ea962b1967fde245d0e64e1f7172b80aa0a64aff09293dbe751205af7b477bad891ac02c27747b40a4ac35953249ff5de9747203536c2be1d032dbbcef7b993231bffd208e9e2a10b355fafc01c94772659d60bc9589445d8dcfb0cc0f2941a0b00434c2d59cdd3681f4cfca9201f30b4252e8fd296468541a7442bfc922ddeb9908b87d408b6d3ce2cead6430ea9d7178ac973c577d55a5376d11eab396e82854821e68b6600bb990686ecc0738fd53c57e1668e8bdc890ae981763d08ac47713ce158d67d8d0cf149a3c5f4031c9e134affdc0f2beb4645931bc5970000071ab8f13f8bd1ce75b6ce14451e408b31d381b382b5611d565c78f781089affcb6db60877e96d98b15e0878e25b106ad3c92aea498c8cc1c701dc3f94107e5ec5ccadc02d9dcc897d851e87e82d0aec2323d4451d467ddba793e0873dd08151783a1a54b5c64bca1cfc74e6e85e9fecb33ff039af99ffa3dabb7dc1e835e067d48146f481f204d3e3cbedd78f995c7ca41f96ca9250620ad4eb4149b3ec8e72525be81697f48f4aecbf4d83104a757c07377ad2dd9bbc6692cd0b34b40e0fb4c9fd376879bba779c594b8001a13b4ba3760e9899f88aa308d87940f1208e4b7494b7a6e4bac0a8dea3ddd420b8cc887476d260e1a07ba7acc6a0b7df3bbda6b8e92faf35d317305bb6439254f56e6e081463d9e8c35da51d34a39c7c9c90018f1d7a190a176e05f23ec66bdc2f1c4d8a053598d7fbc753a820187d9ea7412c2e1f389b140ab7a35f679cb7470011e773d99c507d0d64ee1f0d0a4de167144664fc9631b348e9d5811fefbc026af335c19cdb281c6fd9970427669ba88e891d31ee21e731e117f4d0c7ce4706aa97da03004b4f8138187c15fdc8cbbc1288296fbc08d03224de71a058bd59787b1c195547ec9714a8e59f2b98a6eb6f7bf4835a206f4dca676c072e125adcb9df871574d2bdbf35375af01f522730cee385eb9b8091d3452fa9c4ec443ddbd1297cc3a8bc1ea4aa14868026a0224663717a6c48d7f7c3a03cd280f196b9824f722ee4cb80998d5ad173c3d595bbb69e181e6bc4431a67805eb614c7e58182d90f50910fd56dc503a07429fdaced088a45aa3bbf9826e5bad7ab2ee9d5aa9c830c46b5f5621a8fb4c8ead9b1151da8d5530e23338e95c5c0fbecddad42a81a37287a53365a042cfbe52450adc09c44d5716c50dc2c40990af7f90818829e392042ec2b1a3f5328e27d4ffeeb71c47acc272d5a25fbd646354ecec45ee0f069525e0722967e2ae655820bf5615333e0812969a4c1ff2a98e572232395745efe73ba488108c336f328b1888c38cb430d30a11bfac5b451e8b4d12593a8fa240b5ac378be3c11c47a31af0c99ee3c4f22c63ed95d072a90b1a4d3e780774049dda26ccaf23557d962c5e44cbbfca849b55d48022879dab12c0b97916b2b4f548f9091ce4dc8f4cd4b0594409e14a26b1dcc2370a2f39c141f558a76d0ff2a8e7972707075cfd723383bb899cc072dcbf2b1da5f3ff9bb89441d05bb97407791220510a887d32264601a9ca9271b927080f4f7f2aa7b52a9355e0b5ec494e7472fe91d51c9e7656e15c4ba978b0e6e1bd0efe77e6fa2f8ad992a2c0e0d6852b99ddb40684117a24bc9b8485ecc39759a655ab7a5e81fd63daf29735fb23829205d76f45816ebc0fd7bf8929f44d9c1ca7b17b73c088d965564fb5f73839ce109d3f65a6d2c7f0fdcb4995223f8cbf64fe4fd23c0140a7d5163046cb83b2cf1edfbfddfc51a4a70d1beab44c107366f7eb0700daa2c5a1170de4339e31ee1a07d5c72e02ec80ff58e325a3ea7dc6d2bb743546e5f4a6171db79409908bc8fb8a8fd12d0e59798b563790ae1afa0b4ca7ea604d6b4b8b8ea1642641f0e06b8193bffc9bea1c2f0086a886e185e50dec8f9b1046b8940884570e4eb4f2cf00d03ac4049650882daa7a45de3e57acf0aa02808593335807db56180c3d484069d6b5ce027cbb75fc3588f80262543702ae4611587e12b05d435638dcac0dbf0d85848cc45081f8770e982e51d73a07d7b5308e3aaad86b2164f4f54e76784769eeb4acbcf136563bfcd3ffbd8decf0980d11ef083a1ce393d56a1c81703b819062c1284368c063d8d7378532f5ada88e00e2873010ec8d9fbdcd2ad37b215f79dbe005b57b78d60463b6279a0f66e283d5941808c1508bb3e078b24c314084ff59f086248dbf60ba1a3938a95574e69fdaad07a6535d0afde7b44dd5bf1abb4c81797f5189b1540f44b2e6957b968c7f5c55e25edb4a1eff1fef5995035196e786a99e720ac3a710bc3aab2ae444d08999006c89e9c466703ef7fde75cb981b7ca899660bebad881bb4eb3cbdedb7b4e1607e3675b234157751843298b93f3d7a52066f845633b89000c0d281dba52773427bbd10e0049625403d01310759919c6a9e57dc4d7244e932849155ed8642fc7c3f2f02c235708ad1d1824c32508910822826297bea11a64a932b24b75e64c91ad9560e252b2f7ccb86b46171a29dab05af0a8e2c534aa564018dae6b8742d96fb6d04b9fdf09dc42b90ff4beb09136df17345f373f3e954b2f1a636e46dd7fcc462d60e46f643eae9424a96d3b5acf57089f001ab580a8e64f4851ce6a990d4806f453231ce32b9e2be12edcb8a907118ff3a530e544a0e0d51454d20361618a8d2ffbeebb90d35406f797b86be02cdf966e8c210abdab1f7ec61771643ff31c2a6c392721fd8cf9a4caedea889a7ac0f88152d1b0d8ac955a6554513ac537d268370058f237ee58b2aa83e82133ac04356398dc64ed0548e239f2c8a28538ad93f30446651a20302eeae162ec2cc89931132f7619d6a577443e9f7ffbd248fbcaa041584dfdc877e1bf7ff2b6d64305c4f050b49eea2fe66c0c92e8ee3bdd1fe70f07afa9d91a39bf844b44d53c4f57fcb7800e144f88eebfc13fd230d4cf255822e0fee4338cfd6592164a4ff5ea4a706e7e0866e5a013130e30841fc705ee28334d6628f5e1768612b0b66e546dd5a1ea6da6852ecd17272d88de3483b5746dd292ac28796bfc0b3cbe39d86bae95daa47edb75a499e8930cf1b646b4968a2ecc298539568d581ad45aff5656d47096b750020a6498d2c401b933e0059ade4165a1ae18439c475958b714acdbe4c7b989ae5e179c2a62f2e3d42948cc35359e4bc5c3feaace86b5a2bce523c7e57b77e1b8a047c863e5bec00561c9e6cfa12e449e16aa51077a3e16e0122af82f9e62f095636768e168fe2f15e8092d1dab66befa31d0374864b474c4b6fa1ec64cba5e526f5e6222ea0fa68bf532da85f106bf6947d609c985991976c2837d2f031689fc47898eacbba86eab6fe8ccf84e98d664016fca696a81e7e5d5f46ffb30145ba30117b82a0b0aff4ca53cc0bd936fafd99a28ea1ffab005472881b852aee6475cfbaa69a9e0c5eaab80e94a1e380849d3993c12c39403d6ed63bb452c577b826fc562674307227d7376babdefde6cbc25eec37402990e5810edcdefd7040e01e17403775e1fe5d665d193665f9b3fb188bf0e0821b61f05eb7198615eeb21cf2b642b6f97cefbc1fc731a5bcbce91e2258f2d815f5d3a4ddc0971eadac28451c0247f5af320b0fac0de05b53c0484f135cc18683b729cf77b887bd86bb7d3accde0615c70204e5d37797b40187763340cc4c2f65afdac640fa6cb5faeb3da0069f19d955fd42cf5b991f030e1ad9bfd446ad543e905a08a1e543e81abe4c60ebc326b1a4ff6cb8ff9cbe3c78d0e2c9a78a6d9a9ee58571f69fc79a2b638104a9c379f7092a01fe785f970163029edfd2b01d549367ffff0371c79b648818c445941edc7c8ce26e87ce870f418ee4873e24cd48e638c6c6ade0649c2733ec480b201f0e4a25cbe846a99c62477b76f568e0d41771ae7870cfa3049cfe8e2695273a12344e2432296bcab77553110fae3a3baa1ef865d428afca18cbab3d9077423a5a504d80ff3d6add1053817aeb4ca455763aaa292b8f829f4abaa31dfdf46b418177fea2ba5b1bcd598d67b9026aa51f57e0f24e450ca7c615cc6ad2bd3caec0e5ddcc1af534850da76674495f053c1d8e547c4c3c3dc06acc68f19d5fb9c9cbbc4c9de245a9a9225b3bb0acd8751c1b34deb03f76d1daa31651e5c0da69d3d9688426174de54f0dad156066c58eb6666a3b95adf8dcc39648569b2745232634b434ceaba8514e2de9614bebd9b6869ccd05eb47ba425900dc4f207699159367904830bb2519e213d2d39e7d7b711d8d2ca0261dbbacda182f3c26982b94f17329da4ec4d777135fc058b17178a62e6247b79a0292987bcfc344307cc90dee5015557499874042b77525d31ee7540dcb7af895836d1e9ce6274f61b170713e4a5ef02658df9da0888654299a8f0d98b8f309b1635d11937eda385f61c5c4d33f3bb03e7379fbd285f2cdfdccff48b3266d59cd44674566bb70fa3730759f431e47849acfdb10bce5bc9bc6bc69604fefc2259a5914276830ededed172a0ef8cd5aae536842f46050fc43109efdf3f53c0798d98e21e4ac54d9ba36bcf48ca5a5c52ca255685c81c5f74b914a5a1a2ce1b129dd670a6f08d31edf3d52ca97a31ed58ed8e538a7af305f240fa7133fb48d9f721d69fdcd92f7f61ea424ca916f86fff172e68651fbad8fe59e47eac6750673b3351dd8010eca5bfa1541a5a5bd178e063d9229b553a164a840380fa35aa473cce71fa1e13047a91adab6ae43a48851b550235835efd01ea69e5ace4cf950b8cfbf0aa41fbcb28def5051a24c7049a86568c52d48cb4cf9464c259b691cc091f0ad01dc7e7463899f74c092ac2be50586223ca0dc77863d59b0e6dada709ca4573ce1e4d9de6a3dad427c7bbe7e59fbfa17937371e89b2b0c6c1213799f880eb95207cba6d61a07a9022e29fedf635b2992ab7e505a105e80dc27a0fec13747005be44aa2d161141f59ba4b68dce3c7da9555afe4e64d5b255a05ed375c46b68ae5dfe8c85e24a53e87a684e675a8b85019e8238be0a8ba2511efad911d47f512feadb36c5759a2edec55ec8f49a8e73a38d1e26a73716360d57fa44d8a8c8db7126ed53e6a8a95bacbc0d71650039af6f3aaecf0294f836d53d311d50387814dd2be81faf7652eabeaa04e4286084548e47fe5b1eab9ffa0ba66fe32a26649c5dbae48570a0642b6038410b60f66cc867b72484c32869228a6544aa21049b0d18596c2c3e2357e1aa5de944a137405b0f25765451cdf72c98495846884a3e1a4d8888078bb94daf333c6e9600210aaae5ba6f45eb9076ce7f4c93b8ba5188b7c368f230885be71ec95813a34b0fc6e1f79c5cacc0aeada2fb65e031709941e1b3df90bbe34dea1a2890cf0a760dbc7d92b361a70d2bfbd342f116fdb62c3f1fbd1c7071a393778c45d75ea92b278514c0b8c30af3c1399d7ab2c991b7f067b1a4b2d8ab57ad77a13820c8a59493ac877ff1bce95d5a9e7d49bf0b4e10ec61c67b4d0ab4acfa0ff347e9101de907cb23ba8c18bc8565cb1c914f9c44e35e8da2534226dd00b74a183326850403348132f88dde019b6253a623dc93b609222e6a4035aac9588f94f7a426acda425841266a94eeccc3cc58f3f9b3d438a2967adf4717020ce9b2c44608a530d0aa43e223d6683396a2cee54818b247c5e6c6c6080d131291654962a09b1e7d1f344deee4e3d16269e741dc80890bc0db3cee47f793cf85a87a7a8ea3c9832921547d60e5aac08a9de25880834fef62d0b854b2a23d6608a784bf4687ff10dc4fe281496519344b622538a19b8b1cfe48aec935f2604c1a0f057b284c16570f6753b19dae040e6bf34fc7fa7578cccee94107c09b3c22a9a083e9e670466b4d75f1c1644b6a31f7a7adbdec6a5528ce4f2ece89bb40c6d5a1692f058162b26311ecb73a2429c4ace72497c32a70eb5aee62034270fb2f47427b98ce925dc145c4a03271f29723d63d7f16c91bde029af86a4e9245d0488dc1b35f019b54d72d9998133967398fce682d333395dde680cc03b7f0026ef0d2b70eb3d30240f249b6a953b62931e80f56272a4a260865b1e1d8716ed4a2edc2256e7e906f777bd1c47a46cbd5a9bf973fb599c6c138747a4ae9d83d300d55d86cccc17a626aa45a4840591a0f589c249a8ff7ff459207c60c8e2ff67b26878f0a3f119e58e3979b305cf58e03880a4e0a427412713008b883a0b70ad4e1c07c15a65880b470f36feb57270db751cabc3545baeb7cb0a0b2dab24a22837f142ec12765a6ef8dc0cce062e6fd6b60eee612b368b25fecea071dc312716db327372702ebc73caea2a4e5bfa40a7123544539b23a2c41bbbcfd2059eada5f11221a0b01a5ab0390a205c08eea6f660bd05722604762ca20405470df0bc38ff43f206657a6d4265c249e7adbcf7caa0876fea413e40caece753f56ee67f7815b2afc1e2bb428c977b1bdd7361b30b032f0c4cdbcec2f63b001af6fd392cf464302f3efbc5f723579b1cbb86ca8b35a0129e876c08fee68ef03a6ea5666eb8993748610f4896ae3b73126ac7e7c293af490bf3341df880504da1b7cfe92810551c40e4bcc452d092c294ad01e4479379357a634344087a7824ad180803ecfefa57ee4ccf8b531cac7aa4c41de71cda659051b3cfca1e1a2acac9625521b09e2fe26c93d1cf3c48a48cfa8eb8e510b7675ae51d48d69b77265e396c2bfc2f97b4a98af578e6c17636892a3230222175aa9d483cfd6882a8a6e638fdbd4b480c9e78d6324fed0d268c1b785fe935788bd1b37669db2577e072ac13e5cc30fad9da3e7d690847ff6e48c1a18c0344d692dfc7d8df76c859ee63851e3c3d97ed861767dc16e89808b615e3d13760af29d1970b51e500ba9602d88a0938eb8e0ddca8ff6bb8d3456855a414badb80aa9564fac52be7f8379af419989423f6a9e4e948017507e1c0f5fdfe97ea7c5642d3e03a5c8745d4863c1ee00ed18d297a09f5ebe341b4264c6494aedea0b2c5349fcc6b61059df61b7f36b88c143c058f8baed19f648d64ea461b044a993b274913b7082445c1a6da2faef7c289600efc6c4d4ee7d2c2670d47c89a7b1362d94a1308b4c8403e28f902843f490ba547b3bbc376cf952193e231d120ad92cdded04161719b3aa1869bd22c4c3755e97c856911632d009d9c61ca0f04bc72982c31e5f6285dbc10e5971b43cef069b946190a8044fafbfe944044e01caae2ee7a4a2f8478e183d20f738d4929eccc22145b802e47f8e4b2ef866db64fc53feb05341fed9c18d666609bb5be730b8a72c28bc9d4ac91a58f2b55829b92819b7659b624a69d8ef4da16623220f5e695a64df258c413356a7f4c8c12563d4cfbf78946274001bd7c2444b6870fd7c3d3caecbd6305d83157eb43d7ae6328aba63ec4b9cf839e222144819b05710859997b37351370a813ef61025bb55f2b1799f8c7bb9753fa0161621f81e4ed4544ae0ccf3b52201728ee9961049adfc32d0296d8cc4d47af29ea9311a005a0ed9e5d39292811034a6172570eaf49d24a635d34032b38809e36096227eb60043676b50e08bfe2d342a7083613685582401cd57aa659f91f35ed7b524d262d548612552659ad8c38d6ca9c1481066e42cf8297261686553fcfce9ac7e1191719d618b23412cbd7b2755a58cdd74411e2649a1b64c39eccd649e23738b7ad5dc3908d2de96aa8264303c83549b58096b80f12ae595d0a89503267d15366d13a1b6474d2d7d26b0aeeb713c5aa1e2992c563e0789f385a3c3d7832be7b9035bd670f6f105c8c259ae6eafb27cccb760c3b512241b09072f50f02de56aeaca1d6e1efd4cac2292af17fcc2c7dffc0afc3fdfb57a98cd5384bd1e0eb60a60236db2729a8fc37ad3044e150cc1277a87327a4ea66a1810ff5a1db52505913fdae08a9026cec84b889b19a937995d33c4a167b77b8eda3a36f4150396d2cb65e5803b47b194a0bb2ffddcef220046f84a2a707c0d6e7a81d8b62c232d8a22b15e8ad1981a98ebd11fbcca3c3144fc90d66280814cc3c4e71093697035429cff647ee956c2a612890bff09edf64b92d93c713e8ec935031f1f7c3e4a31767bd70f25fcae41d5c5ee6638fb858ca88f59a23bb9f7fab04c14cb8933b8d8424e14013facd35d86632a7cc6494193d1e73657f4c3dd1c45236b33ca885c03b8071bc65ea6bff8faca0c358544f56f449cd02b3dc1de0b3505b5a3ac93adc898edea06b3b74918bd2aa9fbf045e836f4b286882c0aa135c6ab8384611b937531bc2a181289a873151cecbd4f36b5cff86126e79c008077f07138af9a28608e3dc44afaeabcf5e582145f5ea03a75a871368ae6e38611ca5749ca7c56efa0e9b323c013e0386c8588512a368b36797c67aa4d1543cac5d6dff9a85958eb14dc10852ab63896ed3b76ceba9bddb43f6b14feeb633a77f3f48aff1a99efc6c4bc50e6cc5d96e1adb76c4e087bcc1354593478760212fff688555085b07431d1d98ed6ccb994827c3a3bf7a11ccc0c7916df7a01c644437b339d0446b85defa82ab354356f4a49b52ce8df30ce223783244cc70950ce14150d6257b1002503c82078a71f9ec2bfb2f57025e82693e1c02460bd52b63239ae2baf156d92c23d601e9577c3da82a98f35b8c9c13a0264084b99f98914eb72d730c5be384809bbc8276674fde5552b04f948cd40ba0e1156dcdde0920596e96f9584188f5b2d0fda9f7dd8481dedacd72698e6196d76852895d16f54619af684c58f0ca7a3bf013d2689f8c332510c3e2dc7d19c4b40c671d7964d2061c67c6f96bc1a2527e3938623b181ac90c64a34a2bc3e116868b3e68cdb6e9ec7cfda1ad4f636c102a17ed25fc2825efd4394260b8231ac7a61d3750d784420c9ab889c269c4593f6a446294b6089d4d412dd830e5abb3d959047a04e9c88f3583e4b14696ab4c1597360c4ce590cc4f3b0404c5017a7574c32495053f02615aea866044a6203477af087d48878fca325ddf181154f53b526433fe7364e290fa5ad50941b358c7b769a49e6cd8f8bf6fe201fc75f62c198e45cfa239e187351cf4e5e1c64b079da78115c70c9cf77761ddcbc91c25c811f7727bec2dd3b31f2445dd28a25bbf69165fb20ab9af0269e639680b770d5fb997dc0ad7a34e3240271d12ede4790124f01858450dfd1128fb931fd6c4057f15f8b4e852677276689fd05ac2de8dc1e65e1aafa770e8a1898ac3aefd3a481130007cd7b732c761a88da87b62bf4ab69cdc390c323ad0c96e605e65c73159f8f3176ca96db233a06a70ac5a23e6e14021ae15b36ecbe17ac25b0cef019c655d87575dcf45ef6e00720b24840dd51876cd885771f827b01a303e2c543e71a08a727c7ff53fec4a51d0df6a45ac8e8117a800d57e6f3a47a380236ff4d02cc4a70db2b2170833c93ce0f35a00c9e2bacc3405b1c3fe4a03bfae6952285982ed61b0447740e305bf9b1a37cf4ae57d186b21857708d80e9350aa1b13952d6ce62bf52106462c9b9348ad254671c8d4d2ab419de0242b7d15360c1f9dcb2e4b61f603320876c74097def958c5167d03a524e01283588ebe799250123df9becbf0b106a7cd4bb89bd1012143efe50b32630eff173c0a1bdbc5456493358e7a17b66e6c45cb2ee14a2c91cce2f0d9681209f4cbc1aabab0bfb16a1277f52ea3c11043199fc5cf10e58c83335db9f8ff8ab198920f4c3a163e764bf3792b8a456386b1c260c8d5cd0cbfc1c5f599321cc4f4145ef1dda05f736dd5c73f082aa9ac03cd94f92ca47c12a438b64df5b80064d0c30e0524e00b63570ea4d32ad5d731305f287850268982f32af1f1d580b76a70b7ca1bc304aac52b63fd5b115e0f332a4bbc4c72b836f835474d9d3ee62c6e75b57cd8ce409b6819f6aa1d8aa72653b3062295d732a8d12ff7d5eeb234d8926e8dbb773f44f2b4906890507f9714ccbd31249401d30a6a1d5fbb33af8a66f92c7ad0ef71a247eac854bad05020578a7f109d5db38205c7b5e139c01fc5b7062462e520b5870ac4c5476dd59e31eb6a21484c513fc7be35c2f40dd220da1c1addbda0412c985828bcab2ce72ae8d03294b49f7ea4315f771d61769110b52761b8961b8905dd77919f61a7048aad67d7dcbaf7b51c68c706e501fd47c277827d35650b796138401d717b1787f4226f3c8092a5173baa1f0db353168ae08f894b64d12b6b23be567c3aeca06512f4389d3e08a8db662b6bb4c4a2cc407a81bea19e1bd37e44be156f23fe64d7d0101750cda517eeb15053588a8fcfadad8faff65570b2192dada52019280afd2c3693f814700d5393670b98ee980302f506ea9c660e6b5e675636c89bda6ca7dff3326f522b72e408416c5541ebb13021a641dbefe9616f33ec7a9870ff33060c64f38453ba470cb70181e49a0d75ad8a71db3f160903f410668f9e019c18541ee47c20002f6b7187e3f852075f1b65ceab9ab020cd27b275b997c140aee9330bc750b1aa48a4c166475b80adf109f547802e98384f32719f79c30a88ebeec27ab0a12cb549fa8a7731570d756692e97f665d8483e2e587cc102def0fe4e910e19c85885d26f3049b4b4d0f8646bfeca4b6487c922af310387cf0358601d863a5cb782272d864932dcd552768c64894a229975fa3b0af0ec655ef0b5ae65fdc5f7f84482e2ffede79e3078c23db30cc442da9548231fecf051c7a0659a3cea83dfbb0d8d7bf858b6e35187f2a74032e241b883adb1a3c04e6e5c67ab79caaa5d94f0a3948098458db087dc68eb950285ed08f2f4e54bc71c5ea74015449b19591d62d71665539281aba8e1a84bbd289c5477408d1122a9bb84cb36363d091512efa5956e35bc63bc5df43cf22404958d90aa2c2fea36f1e6ef0cdc82128eaf07ca79029dc0585719319cf77b8ac31fb823d233a4e07a9fd0521053ab78181ad4b786ae4c59f062c10497b28e5d83a3bf45bc8cf3c63dee70f1679bf88d543fd24ba8b015cb12532f146b488d93958b66b327740924aaaecf18eeed13b14853e0eabcf347dc8b4c07e43e3413c0ad7b7fefb484a69c195964933865fd6f485be71f209734f35b4d237ba2049aef2291a3b1f73e2a3956a77b6570abdbf1a85371dcac455086b35fe3062a5a0aa7a0a0fe36495462650455853f3b4afae57673e308f80ac82d60bc9aa84fd25145cedc1bf49d8c1d1e96a6496777d590380b3f1c1b24a3d7ccd21a02538d87014cb0c15acd5960bb69f5fb4289da56ab04d2e68107427511f73ff66e646acbe4f083291c75a4c1021aabc4fe0b9ee0decf2c24e26a227b5e96fe948a358c79137debe4072277d12f184afe48a0b73970a37fff79bb156a9c42082261d84154dfff41f6b00bccb7d9f70f0b90c8d30d5c91fa30021d8646d5b435fa40b150905424e50181b3caf1f94f7f0fd7e05a3329c2ed5ed093502ada249fc220f32d202f7d4a8daa0b75658c6a2ab42a591b984e3ea24fd4f52e5e2dc3ffece347d39c1e90e842f4f96951c922e9bec7aa719eb926a21738a007e6b00fa2d68df93bf6320fc2a92b5487a679e34bcf2cd8c46deaad6064c1022f1b451a56b9924c8c68cfa7f9057ae530892254169cc8e384a866c4ea3de60e4a4538c3e0cd6eaca0c66f145eb51b45099e1f50b38ed2273f20867e18dd075eff22f9d95c15f82434dcb0f01f6887a26ba816b1398fd7dc24f980bfb7318f7e73da2400fbf86270d6de08b1d7767878ff9284e3cab50b8859c423006feee1fc18c1eb7f0ba7f22c58d41601cbf2b86db2c9dd6cb0651ae8e2ca1dd98661a9986a347c38360d3e900a9977fda4835cd6b39839ff69a9c60a57e254f3028f765250a1ca3129c4598fa0961b4110145f56a5ec153be969f82912885862ada136f257b346b6a1e26561f46569384bb6ae6d022d5e90dc0b0e56011cdf05bf968c3301c7a7e11126c6ba20dfbe42526e441b4348fcb1076f101707554f63648fb240b7bcafa2cc7c38a40fb552a195be7da2c84a303af81d9b397f1b2b3f79257eeeb5b5db030c364b75fc01fad08beb08ad17eb0580b125f3c6c18ed40d2ca2c9e8b53a935ced0a357317543837f3012c24a85ae8185c112ac2902f79c906ecb83c4f21a8849c73e0cb7ab2351832191451f350b183bb4ebd3b9498d8afadda402a5450d6fd85546580be8a026874d8fb9757ecfd677a2ab11de0a9427221d08b5822951b8b2061d03a2525789d4ccbc55b9239924b70b0546527f583193b1462c5297e921713db5a2bf2624a02fd556de6b1a9814431a803f9e0221138207bb80f8607d6cdfb08de419803cff01a7461f3cc4b18c4891a1cc486d03e8a7d430c14560e70c794175a377b3410b61f40953207236ef353f09f730a5d60485dc55bf1efa94e9adc81682dacd954561f10c3d5d4608f535f9eec10a20b826051da22bf24dc231c9f877d9eb194d474937151622889352e332ea5b8707ab930ac9f2964515a1283a53662580ec30145deb735c246c719268b3e7ce2770de71da617b36fee062433d8f2acc106917f01516f55f1d5d039ffcd6a16722b2caf55a36f64edd01a1c656af7dd7bdfa596dd0d226083fc0da5b164a5f52c46b4c90237142104fef6497fe86acfab8338626d26ab18a2e17561760fd5723451d0b025005cee148025f863d9a6e717c7bbad4a81f4b3515f3fe14023070b139cfdb9be783d85074063e80492567fa8ad91b102140fa089986fdbf01739421ff6dbc83dc69e4501dbcbee780822c793b63a532172f7308306a6672c5f962c3743239e67a2ff740695b429c2ea09655252353118aca60ddbcf3abb7d5324fa495350a89e1fb4780fb7c67534cf18bc04c0d100c8059138d6434b7a61e138fed792264b65f2c1d617129a1ea577f6dc3533147d11ba6c7873279854c6824153537a9ce552a43c647a052c1f566d9fe03c601133bf387a15b960c1e4c964c1c2c55c4ba08bcb14d91a79b13652a590f04efe30b9fd2319166561d894437d13121316fdcd866bf5b4e0b84c22d975b5359aeeef1e5e52b788b7145502cbd68c65f7ca7dfc008706f056a213cdd88627803477bd9ca65d3a2ec500ba2ce346dff1b447a01de6efaa2bf58b27d86ce48bc197198850c2e8af6ed2eca56f70807b2a8bfa9ea94d8d6c0f4bb5c26f4611a785ac600fed436ba7ac9d4a12b3f338890e6e7a4f1d2425e44488118246b33bfa5edcc0f07b76e744fb672c03892ed9ec3c0a0715264c493dce20c972c6f5992faa3a2cf07dcea885aec3e2c12e6588a7fd2b551294a39e27a9a56f81bf4fb496e62228ba33a4ab3d9fd455ae65cc7000e30db1e363a60200db430fc5eb6cb0bc035315bce034f4b135dc94bf51140cf65ba995b9bde215227b5d27015f59be4fdf81cf9b86302c389e819eebbdbeedf4d0c7c42144b9659336c2400b111dbd80cb7ba1145d21206d9cb807696f49b1504014babdd46bee6508a8826b1f7494f92fd77f4c288698c23d26e5fb78d9cd9a6dd9790bb11aed3cd3eb3c7f444216eb0845b8a40408708080d45bfbffa9153074b06dc2bc26d658cd63971e28b4f690603f373c7340e681751f0a06f4667ac0a186250bc735b2ca013a19f13b3caa30b6c18a0f22e816f89d135087116e2a272986029c6fc3af8e2e22672c526b9d67ba2b9ea53b405ca8646965f8d755c31bfeba29d7663d59020cc22ab8bae9a93b20ac5f825a3b352e428f6eeee48ef46993ff1f76f08a20ca928132db2f6fcef00140478b5adafbee0f536484e4151545154fa94d829e1a285a0449e1a4b1724c321f9aa8c9c94bb7e0bef1463ba4f6ca615aaf8dc23a9fa4489a2ed319db3e07967f68aa93c1bfc0a5af3a984c0703fb53f0a3e01eb930d7d784db81b921e80f8e06d84ae364a9733ab9799c32e955abc1413ea0872239c314669f2a84b282742962f15030dd9068b6526921119abf60b5bc397ea8c2ead4a4dabf681ee16114dd8fd656c9100183df9c134d643ddf1cd62d1e387174a3a58e114ca405d38bdd8b681135ea3049bd23a0e46f405eaa831d5b1fa1cc6b1c7f4327ecc735a18469bcb54cd2f39a011aaf74c5589a44b2cb11e51215dd8054d75e0d125199a4ad122d97d4f93ba4442d3fa8ef8fc1aa55f7e0e29bbea7d20592aef01118e4c5391796a48b9658346702060ae917904accab3efcdfa586c920753be10c94053852bbac6dde80531cfb2764c8ca199ef7bfd6d5e5f4322ea62814283e2b56061c9e5342aa5a9f8c622d4bec3af760e2e2a4df5fb27bc08fb62f34d23a32dd9668873a1102b9a15c7f5a181bde932fa4741a1af5a277d4415e3b47c6c28ac3a68b4cf660a68ce3c4078afa9a2910dc2f52b22f189bc892f04c25bdf86aaa77b6ba8ad7d96df593a235fa6d5a91047530d462d2f90866a401ea1a4d707bf29f7ab57e7a71914e4549cce8cd66faa0fe4be2bf3beb33c2d28bf7e4e6cb60355612a389fbc4160e987d86746844f2080ebd3c1d2c454b1db8ab7557b277b39cf6c3fbd7e6bab1ac135de4fbec4e2f9c3e5d3e9d46a70f0a5ea0d42e7bc79af7ff10a8956f8acc5b9974ab98b199e9475e700b66725f9be549d64f28ae28bc98325e7be544247a34e9dacbc70df4671cf65ee74f1f1ce6d1883dda3682330eab8d04b454a4cb1ca2fb30446ef35839d4b08d6832c1c2f1e571c54096ac7bc02a3dd2f0e90fc17f72abf0e6a4cd37153904b75c66958e5ee8b22c13b7743514d475ea86f81b04cef782ed5d1b0817d9b0a43b9fb3f9e61dd3b7ceb6d687c1165c10ab25495b75bde17caa0490480f2338fffdd601dcb92e1fa851d5371177f54dd44a69aaee082d2f0915e884f847821884af5c90064a8d9475c514e414422ff051028f927e2f7a85451eb902a92011b727c88aaac3b4cac057854aa2e5add55c90beec8cd1528f32eb0a01e45a5e2ac2fa9721a40fd7d300ac741755932aca8a1d14a2ba9e42b3aec49b5b32855dd0f373ac0b981476afb82d51a42758684ab5206ded33667b68dc008db3adf934a1554a35093bc7c31c64d509e06f281b827d5e06966e50b5de128823083d0bbde4a49bc6381b85f3200944a493bc9ead2bf756dde4662c6151ad2796ed820054ad59a75d4a0bb1825263751f7201e14b7203d36acf1de8ea7702ce77d51816537a86994d15694ed74a251cdbc875457f9dde6ae6f52a90678b58f5473dfb23668253c28ae2fdd53c91c8e494984e426a9722ce2a7f69f611387d7aca563c7245269d20edc0595d1de462c914acf43d0e1097778965231ccd465a29df3261c98e22941dbd0394d55bac7586827750fa4ca85800e6f8454bec50bdf1efa7eb725cc171605a994a03c5d09e96c7be2b85ea7ed375112bfbfc2df47db0ee9746fc9f0750edfde1dcb9b85f4f3d573a3b0ec3c3be54439fa0841fdddab26f8f0500a3ab4ea36a10848597d9aa0bd8daf013d5c648c49da05f4618dad04d387fb75a3f25e750415efe29910e46775fd3207c10b67a950e320d48e93d6a49f7590f393ce3cc48692ac539df25bcbc77d9e3e2dfedfb0d3e47bb0c829472c85f34fb9f3979237a89c5c68f3e5a172697f82204cf9a6f10882f09d829f6b01d2f0433bcf03e6b2bf574a5dba1cbb2495681908610d82c4c6e34e47f9b79219641b5d355c8c124eccda6ba6379f3aa0f68b26d686aaf9d7a119a37ac57c10c6eaa1cb49864512ed63f1e18888390af7727c2efd1c716ef1e1e0133c11962e6511cb1761def06bcf2b9099d18d4392c10db0ee2964f40f93cf3eab70cb2eca0cf850fb4c632c7f44bd6a6f62ebfea06dd0aeab52c6acf348ed4fbb4ed480a061ac1304ceddbcf8a1583d9ebce8695ba44e2286e5dd310b6facd97b78c5f7ea4e44b210c60830e91ce06c7d7f02cf7a50b7fc211aaab2c0f94798073c08fa49664edfb817192bd7a1050de2d112403e950b4ff5d461ba2f6798f9ca7633704d6de214a664de1831d270b7efcd618703d41734f68aea253d7fea825316559ac3f16b511db7e9cf7d98c9d8241d8dd026b7fda9e41e60f180f32793bae38a9bd4284732b56291960c76b102b066dc9201c6d8abe4f6d4e0685d4523589ef1b4c3161b361db043d65d9124e9d6c2b6ef78b7688f0148c2ebd297f478aa7e74f04fe09c3e7ec14f43a3540dd8c1d2a506be43801d2703a12820535dccbc8e3b2f27d431ab2b6be5329767ad3c3531390e2cc044c63fc6a98ae037e0c884383d1110515ef7f2d252721194e49622d1dc8716398b8802b5219c84d91500ef8a90ed71084facdb025faca14d3b1b78f1f2a17a27425def4be7a08766a3d39c502e763ea4aef56e39faeadad1ed689e39a28266c3b893dfa5bef751fa81ce8be1dfd18d83dbb73bd947597d7b1aa266926ed80511f994db2f0431d54e21f772536da2810678175c6e8a4dae284230493a0ceaaaf81252830a95646b36e63e65b9b99f9ddaf8bf45303f630f9eb22aa375fa4084ef81dd9ca03a0fc4d8596aff3072e7ef23a116f0aa06033607451fd441ebb65b74dd7d14969522c520f4cd9836200a50c43d733c61437132ee674f06a429f8d68bf160ba680e4c40ed55216987f10832157ca427ffbbeb185e931b761ba45026e7e90bd94242cc7e79ddc6a8dac1bc7aac23c7ee2fe5243b76e555c14c5aeb85e48c2c50f02efa3c1890bc799030d9f055b83760507686033e713c48e2b7792345161798306d33675a584fa48ddb27b98fc030a280e6f8d416f10eb650da69d1129d1c88045cebd37c1baddeda554309d2780186814550aba76f4bb6e88532ef7c1ae677cae1da9b11536fb87dd33f02ed7002dbdb2542c53e72c45631eecea58e0f171dd125b5ebc5af392f26dcefea5bfe451ce57847e25e1e81d0398266e8c1c3a139fa22a2717e810519250a184024312ba77e2f0d15451b6ca7128be04011a19203cf3e7cacdb86058e3c523f71f7f00f07c866c260580eee6fae79f774a596b9e1073e48bc33d6db0922d3c2091e729a111f47e677994bd93c3ad80334ae03c99e51c16c61fbcae5c8b37fb71e229a974caebce3c04ca2d8bead6639f6af8e21607165dd813a9efc6c8b5c8f82e7cb5e41a72d0f735d5412e269ece67fbae62f44c677fcc7b9a8840ac5c47abaf34bd347fe409ab4ffae8a165b9a376258469c3411794c26d40d258f8cbc93acd116c7019bb90260a0f4d297b352cfd00f2cd8f19a1bdef5d0932248ba44a6906bcbfe355f2fa35f0947b3626ac4081f09999c4ca359ff1ac45334e24e7d31687ee3760c68ec21fec98d01d9603e0ed54f3d74b4856fd07218ff4b1fb4d8074485eb139181c9423f14c5e1b1bb3853a2eab2f82f41f797764fa9b0bff17c461d291e288a00aa94b1de77ee5830c08e65046cda67e96a9064aeb96e5416d6ea3c2719923dfbfb7bd2c345acefe77be2ea2120ea5a8b697cf93bb66277e67591d52a538a5a38342e269ca81a70869a8895d62a5c68e07bcb45cb5c5b95ba610f3f746ced01525cf6e632bdb78a492b3acec7aaadbd991aa370c51f8b329e8b6451fed908683d60fd24b2334f3ea14ee9fa68a379ebace8beff862fb4d0e9d05402741f1a55fff7d405e6fd57395bbe8f71912a69e18a7735e91ccf2a25242bf48d4745f75ba9e65156bf79814fe019eb9010e8303f465d242d8fc51611ac0e362608deaf579b621519e5e9ae21c54bb604b8ef04e06b8d095c47a192d6d3c3f512cff0822eae18172ae0fa7049ac5479c562f7aadc8a74f168bb99c29a38fd595999379bb79a6e9ae3d35fb459e93cf311abf6fd78256c841868bfa43e849ccca3eb31e8ee691ff9971a5c74e9894ce3c6446c2639703fec01a72a47c52dd3d4e4b9773ff191393ede27a12a9512d3f58399cb0ea92aa3c5f59308930a949f7014ed3fbd447ae8977c9f7ff68b185a5444ea1ee50969a3b5095cbd60a26743853bc5e6e7b45c6e4a9e663d4836b47282bcc6448263b04028f340fd175a08fe8df226bf6a30e816c866b646a256a2cc904e661d228747cb2fe7f79ea5cf0d243e57a86d32f14a5fbc48ef4e2f6a6799fee6dbf5d86c60c91115e28881d772490a8e5dc15e47d5e8d130f25e6cb45e26dc434fdefbab81d4c1f17b796362a3841fdb97103b9e50e04ef20ad3b159ef08fd458e8d05804f3a3c9124cdc6ee6143e467b30dd1eea7a016fe9ab2e31613034037ceb94f9a854e24003f6fbd22a208a02252f829b43a728632169614d1c51c5d2117b2e222b52b7c868b2e19db6d9171943fc6132dc1e48732de7d0c33408ba5eb3db651f813c77e96394ff624bfbe5e42d42085b807528fb3998b3f12940f32f74eafdb3cc0adf2b706b4677a071250a4c8a19f72270ab34e450b8cdea3d77d6087132a08674b9cf5b6813e48301587e86576e7b13d9c03d0b8209903d9203a6c0e86a1169451e61532df2342e73348e9993c408b4553c90ce7fba5923c4060ff215e6736e1e5ff411471f32af11c4b1a24cc3e30643a733250dc3f8784119ad96e39423340690f7e82986d87d28942d3acd12679d5de301f0e1a57de70cc14aef330bae114d83dd91c7feb682ee324b9e427005b24bc274d82fa00c7627892d545df3e3a1ded3d02a87347184564008c74b7304856a68c84dde73e31ff6607233241d36ca6ac623a3acc07c8f670a29dfb587a52823e45afacda8574d78c3bdb05736fd8d186d61c80cd4b6b851aa6f688db7c1be71844439a190dbe97f7e6f864d3e64abc28f24ea68021b710ae7c31136d8e2129d5c59989f4d83de4e41fea20c8774303af1901e5034472d5e2d0c83dc1bc06650426804c9cefdf272d77fca564bfa7d385361aebebf435fd72522f4a36b1a1b2c8f60a0087aaa35fab1c4395cea33308945d6dbc9075be4ff8ef5398656178f8d0355c8f9751580d8422ca59cf6f2735049f76f62703ec742b8a2d09a7dddbc4903a3e3182f15a80e17bfd96187699c65c247281f19f2aa893f5ae9b2eebe293c6e7c5df51c863c8322e929d24fe046fd41433bc2b2a094860fbeb06df79e8300cac82031aff96a0561040cba83a55b3f60885c93f0c0eed7728144479357d5ea524c76b1f189cfc7767c80656640a67c85c2ffc016ffc507cc7788dc335b63e91a590743ed40d799bc7babebfed448728d650603a16617dfb7bef2d659232cb09b7093a0aa6d35c32bf54475760deccea9634d121b33aca533e6bd2f469594d4fe957485695a5a3545398b80ac447be4e56206630df989fb9ddd88d89398fa03293bb31133883fa2b4c1b69d623a42fe2ad38f071c9d76b54f588014955d8a5a305508142430750dcd248e7da33a16802c31b358cc2e4eb3a6a68a992affbccaef3c03e2330b2ed275f35b45c916d2631348366904bbe36f9baf9a5d3bbcb5d1a1121b7cd532655ed11ba4d55df24451fad93df2e4a0973bb0d7118ce9accb56cef956ed4d005267627a488bd9e38e07762031337399da061888393464397393295529b94308b454e501216c14ee61007270430939c270c9936acadf0b66180d3a843edb220c79d159889f101295075776d72b42740919dd6daf3e3a869ca542a1689ee4e014a74d475314c4735d076beb70ee6b6d6c6b88ccf5ae65a995b7b3165636fde95e16b6dcdbbe16923bb5cc1d24c171dffac67c645773106e7232e8942b258b9a8d034f3b4c1cef50d298b569a278a9e124547159126d4cc5b5af32a2d893985d94857e634bce6b591288a33d6f733e711546816e9c644a51b133d7c7bd4a8e8326f813726baabb2306dcdeb2c9d1a756ac3d9d2a9cd1e35af53dbee8303ecd72b4e0512e2c8918d3a0393a89338628b4312638c313ea14ea63bb6f8c3c2b455a5264e7068e16ecc81d151af32cc2e7ba582e8d79784bef2fe950ad751d751ab25ed296f4fa1bc3fb51a62573de4ce35cffa64ddb4b2a85fd19a9cfa939037368ea393e3382ef50350b5559e2b15488ff125e3e831d6cb292b7b7acc39e588052c29cf29a3c778ccb9b253488ff1d295c478e9d6cbd24de711282ffd8894c738155aa5551ae94226f74148f4242697f14a237f6543f1f1753bfa92181f4b9fb2b27e7272247d65cf252727574b4ca3971e3669f49a8f4a994ee3451ac91c9fe904075817d32ee1c6bef1f4c2b491d97432994ce1189e629c42710ceb8be1189ec2303499c8314452c22449f813519556bda29c88166772515cb22651144511259e7cd6a9476f4c3c893f3ae42719555288e26a874e6d39513a15dd89288a4eae722a10ec3d918a6d5c83aeb49b1ac5167d1c451b8ea2b5d65a1339bbb124e26f0bd356954827b687a5c06fe391ab75b2c750c4573cf10dc3300c2120866118866118de300cc35b6b1886e10dc3300cafb592b3250cc3b09a35b0b1f8a7aded431e7def45f18dedb75d8cb1d96feb7edbd97eaf779871631c862a8c71ca92b5d62ae3ab2161ee6cb3ed6edcb8a63bb4d97c92c9917814c910e39014a71895204552d4824352f4c138144d61188a238947528b88b138aa522754883a85618847524b2862d28728866e7d14458c7b31682143d18ad5c76d8c2f2a954a6941f5687f42516549129bbc9ab498ee9dc274dada83f4daa9b5236922ad965f795b3181aa2d6bc971249d8a7932351371042385f41f2533a1cf9444da9bc4a65194d23f4bde8688b062c40c0d0d0d0e530d0e1c386a489b9a9a52e87a8dcd08e4e7748641ba2d51189d749af2480d367f6246d0261c49a0121026f707bb933842b03eda5137b614eab199316d6e526d8358af9e637db4db94a72ea6b58d31e511234423d8a63c82c53235044775c39a1c393939a669cae4e810d8fab9222a67b52a85aeaf72788ee4e8a4c79442e4352398235aa0121026f747a7140a5d07f713620e1a98b7a11f1b8488ae928df819c28ce04a2c533bb277d640d5963d9d7c7ca87c94581f3c2a1013f641dd945f549bbcb4a71c27ccf147c98f9b4e26b5477b4e04b0caa782c9adf2c138144d61188a2329a65cc4a4d731570fd12a2b3de5a9b73fa39b50579935e50d4d8e732d8fd86cc2e388c9f0da11859bc3f17451a9540ad5d8ea84aa712ccbf222a93d30bea7564ea8b23eda636262eec9aa625a47d91249984fa735dd30d74ec7fb4d7eae0c07950df242f5d10ee64b0cb547ab9894f5a6c33391a31a662ad7a3041449c03ce57a94802f9a480016383060a2723d4a00145e20c08d1b868b906caa54686e6c2fda83a2b11ee80f104818c1023cb0bdb5da4a9a9abc2d9d9a5a55280e4b9bb0b4d921c35a8e40011e3f3a35a912b5016167848b9a285a5610765ca9b6412eeaed8da226084e31144563288aa2288ac65014454f3b4328149338456ff7bdf7767fdb0ed2b6ad0f20b7bbfbec768c316e615b6bad75076eba4962d4c3c8e130d2b0c2175a39000da0e81581a1054680972d72b896a54e2ebd3e20975e966ec62097ae42000572e9a952a84c991ec8b69a8c729b4e463946a1c4b04046156991513938991d383ac017a3d7df987a163d2c8544ac864d87846c6be5300c0de0258757c8c8e151184f1c19c001686d830d9f955c2b068ef2bd0520cab7005df2fdf98e02a290410f55844d0220c55a607a0b3d224017310f605b6aa704b9fb80c900d34676196e9e74c070006a343281d143894824181a488543d4c08d6088c0848d4430945077080772211831207b08971c06630dd2f66eac92160c1d8c76c806743756c91218015326573470f0021c0fc041f0868b89238a9b304cf28b1a2f0e60330336c648820d33da6003a90b3692682c6086b9a2c18609c20cf12a901ef9bae8802ac3b502b15ec533ae0c9f22eff2b24cb6893af1567b884988b97cdd264e205ff109a51b233f60b66a0f914746ad402ca945a440be5eab88019c5cb38171d70a842369245a0ab1c9e40a240e29730f62981c656ffbf5244c8e6859cd102e62b755251caba8f55baa5069a2fb9c585f1226378b6bc7887163a3685f67d62a2e4c5bf5615e9882de9dd25316a0a41d35ba0db3b5b836b932945fc76eabb4ac06e764882b2375ac645c97c8216e05e223636fe217ad6d329d4750a1f98de19f1bc31ebececffe22a972a64d2763a70d0d997cf4a13209aa89931bc34b35e833d116ac8b697be8f69de9dd16bf9089f9c2b4b9f7f5108c3072b822532b31a705a699ab069220906da459d368e86648147aa852e510d71e1315480b96b12d8798eb75d520d8fa78a1c63026bdc54281796d1057f5611d33a93db093de33561e95dbccd3c99347efd3c6936d3d19db3bbe0f368b222e87843e3afe8d67abf630b9f83ba0590ccf95d73cf68ca70c3537d9c20cb1c34660dec61d8c37108357777317776f9987cf4f0fc9675b5abad5e54a00498676cc3a962ce3513e21c90beee9e9e96112e2766119afa0e36ed4e5ee0fae8773e2237f4ae34b099d160f9f9b298ee2cbca28ae61f200fad4245c35794f0fae07e7c331f9e9c1f5e04ce7ac692e1a38a9c1d07472c900672249d38904a2586f98368bc3e1aed5e150be1d2ef8a248690c920dd2b501df98d4325b5b0f26c797192ff99abaf0e0d23d4119bc7cb1ae25b28a97117849dc256ff95625f426b13d9267b4ebed90725677b3bb5bd12d4a50c9de942c4ee9f5c475e57018032f4a27e8d8608faa4b12b9438d590f3374bbdd5a1b10d5185117981b91e8a6ca5131a56a140a9268dcf57c54974c996a4fb3f2c2d3744c9ee6c2d3963cad85a729791a0b4f5be1692a3c2dc9d3903c2d85a7a1f0b4139e76e469263ccdc8d38a3c8dc8d3863c4de869c0129ef6a5f6b425dad3c0e4a705674f0b13f4b51bd0d78648f81a4ec8d7aa04f95a0ec8d7ac8cf035a29fafed645fbb927eade8c7d77cbe26c2d7b2d440f85acfd77c7ced83aff5f81a8faf79f0b5a4affd6a5dd0af297dcdcbd7805ffb82f2da16d5074d669d355dedd13e3a1fdd9501e1ed3ebb2b0bc2db7d8aae4c086ff7e15dd910deee6374654478bb4fefca8af0761fa42b33c2db7d7c577684b7fbfcae6c8ab7fb285d1912deee03bc322adeeeb37465f6e6ed3ec12bb34978fb8fdb955925bcfd07eecaec12defe23776576c8db7fe8aecc32e1ed3f7657669bf0f61f4557669df0f61fbc2bb3386fff617465f6096fffd1bb320b85b7ff40ba321b85b7fff05d99ade2ed3f7e5766a5f0f61f4a5766a7f0f61fc02bb35478fb8fa52bb3396fff11bc325b85b7a7b72bb356787b8abb327b85b7a7b92bb356bc3dd55d99c5c2dbd3dd95d92cbc3d2dba32ab85b7a7bc2bb33a6f4f8daecc6ee1ed69efca2c17de9e225d99edc2db53df9559226f4f7f5706c5db53a52be3c1db5360ba74653d787b1abc32eb85b7cb6eb22119aed3186f975591e53a35bd5d66a5d3196f97e93aa5f1761951a738bc5db6ebb4c6db65573ab5f1765951a737de2ec3d2298eb7cb789daabc5d96a5d31cde2e33ea34c7db655b3a5d79bbacd7a98eb7cb8e3addf1761952a73abc5dc6a5531e6f97f93a756f972575fa7eb24e18ef4fa4d377fe4ea513782e9d41d68d8563e5583ad68e55c4e2b18c583d1612cbc7fab1945840d6122bd8bab570ad5c4bd7dab58a5abc9651abd7426af95abf96520bd85a6a055d3717ce9573e95cbb1b7315bd8be7cae232726d71f55c472e24171797cf95e4fab9bab8945c5e5c40d717d7920b8c2be80af3bafdbfce7fe11aedcf5f1a6df7cfc0cf5e3e2b35dabef359e7f3ef7352f67de6f219e9f351eee52dd908c7e72c349f79194b2eca57f22e13659d179f7bf81ce5330f3f83f2b325a29f01bbf89912173ffb6df1339fee67485afcac97c5cf8cb0f819cfcacf8aaef8d9ce8a9fe9aaf8592ef7331c153fbb4df14141293e68a9ca0701a3f82025283ee8f7c407f9701f84e4c407f59af82023263e8837f441454b7cd04e890fd225f141b9db0751f9a0db8db523f140c11b6b9ff2404b473c90110f54c403fd6eac9d88071ae28184f8201ec8e8c6da817820de8dd94ea417aef6689894d7f9e1757c789d251d9c132937ea6d158d2e6cf5a84a6e5ddd0019b91d974370649d1b1ba60dc5d1a1583a15d12cb97919c592516a9837dbd0275f69b60cadbd3df927a8696c31c9b4644271dbcc0d6504e56bc11b43198563925971df1ea2f000a5872824699a3696cb1dab121b2a8562371876f027e74ac91387e250ce239e38151a0a2503f3ba2dcc3ebaa5dc23dc4258c3bcba5ab0d17ea2e4441b408d2768c66e5716c579701b0925768bdd723b8eeecaa29c403c902494b3de188eeec9891302b3661b10ef64eb8db9fee42b6d005f6f6c87bf9d6840bd1b6bdf6103d306c4d3f17208cef7547da5e5b0617ab60101f18078b9bd7220972b0b091f2a02688b85892d2280c32202b71b1398630e6a5e60d2b800278b0968b4004102ccd0c00e8d0c9811019c2cccc8f2060e53a11d5362dfd478917aa8caa3c7e601497a2b469a44277d7e5a3121f9761efd3a2a1586e7e96f88b66248b97b3c7889a493385f2c8aa4188aa493e469b30e797fac9bd0d345491425d1134aa2e809754249143d89cf45f7ed6edbb7bb7beceebef7e2bedd1de2ee16bbbb556278efbde7bdf7dedbdd8d31c67def256d775b7bd67b2f3633c656d58d529181326bad350c7dc2100dc3300cc330bcf8e2b36badd5bc169746b66bad8d313e4d6da046b1d61bab2e62aff5dedb395b6aad18bd5db5e0f0a7d452c530c27a5d1cc791c4a16872d3353d11c3dd0d9b419a4237e1130a87a2bde478c5d04f1895c2373c99c8513c99c8082f398ad88cf144a2ca187cc393491cc993898c511c45d28cf08e223623856f7832a5502994c760324e2632c28bcd2885ae97384606dff0642247f1642223bce42862336edbb16bac8c178ba38f6288b58c23b6a3967114435cc62886584b88c511876219210eb1a8650cb196712ca38c51cb388a212e631443ac8586ecbe58aca66a8a924d6edd92d6a656091b8661188a23dedda23801de420f49d34d527f3252887944e4c12d5ba2d16f3a266224a9e18e68b76bb7e34d779e36cbe5a61bfb87573e7a499390183efb2149d274b2e895a1ea58df7c31c8de9646fba8636d83582d36a93d02a1bd19895509c71226266dee5e2b4cabc504386f338ab2ad2e5589420b0bf218828c841c6a3980d10bb2898f8cb2602514d96918f6fcd45aabd7dbb5d65a2f5965a16991e86ea0ed994657d6b06dc4762c21a620b044fe00026464d114552574aa324d222a0550430104288095161c608886c3c8d8b7441b198f19638cb159834a23cdd0d6e8b478d826b2cd4748168faaad2675c9a2ad7a11c56cab6176b2cd0ed92a59244aca367ba504a2cdb2858c34b2e8a293a6cad11e0d64d17f66459234e0974567d20497457712c58a2cfa10658071cbe205ae0359749bebb41e3520298b6e75bb2c66144dd1693d72c00b8e1ed000133891ab00194319fb3dc11652982fde09b29408e851a2c7e822031c2306420d18030738483c2984b2f87859d00839e0c72bc24144034bbc08d810e1c2e3f96288a8d113d3448f125da3c50d2e380a3053b9a2e14609b0b8e10218b8d1460cdec0d96c79e30ad2cd68008f9e2e5cc0008c8a29af4c244fe3e9644f23ca628c718953e5a7ce23a8d0d0540ff949c4d08a946d6c74cba257201a8f898ebaaa5c356a57e3363e6b9b1a2e2db33aa44e431b1ab7755216ddd63c1c8e4275893dc6975cbf1e737d4accaa8db298a47737263a2dc727ba151d26fe8a16f3ab3e572a602f975ca739a7c4f8f5f29cb20025312739c5e4b29371d37b7765a6cbb8e8d674d124b31b5da765a58bbfdb04e8225bef804aa813a97772f289d41e459c5c9befdc8d895ef33afbbb16c76981b74645a779bb7463e250c7c4de89bb5def76bbdd99a4f49dd16e577465342e8ae24e9cf9de95464537df22dd984a0bb3a691b1f0aeecaec4f4fc0c21721bbb1c03555b49c2eadd4bb6edd0124a7765abd04fd694f192f1744e69d2a75c6b79289b1b9dbc32d26772a55bd28d2caf3c4fd569734515880fabc3b8c88de1176ded9e3111d2248abd8d2a9d69ad589d904e6d9a04f5b499cddd988e57a4845ea5f55d226380b4d4c668bac07c62721185aaf57c2225cca67285d3f904bb58b30a28af3586cd4c9a4227737857e189c946f38a00a60a1df2c6c175940e6e632489a1036126304d1e5e9fd9d2e9c9af8f7e3283b67eed82cffacbe219ac391f73d7ef7099cfc15feff2d3e6b37b1fa246db47d768db14103fb814b7440f848f1fe3f759445d70b185ce6d165858b9e2ad952bdc5691a3620a29aa4401c51338279a606268092592b8bd4dc2a9bcbd39124fc5a73c127ec44f7123fe082fe28d7022be081fe28970217e080fe28570ebc50711e57b407d0e3e3c147ffdcde70fbf80d1cf979f2e42516c2886934173507888d283f52208218620a208238e988204955b124a2c31c444134ee09e80228a2a524c4145ae0a2baeb08245165ae8ec16960bdb85250282157383a3ca91b3d2d9d1c1e36fced0e0a8b139e1d02a5337d8d0a4061a66902106185e60e2c2921694b0b0820a4990a480c209474c305284c810a1126ab43c0b02d281042141808cf0234b7ff8881002083d3e3ee8c1c3831d31179a43ada03a191919191919195c0eb937055e05f2b0eba31bfdba2d76eb9468e701d3762249f9c107202eb62472f3e9305ea73a9c3e4821b30ede8ee23a75a14ea4d377fe4ea513782e9d41d68d8563e5583ad68e55c4e2b18c583d1612cbc7fab1945840d6122bd8bab570ad5c4bd7dab58a5abc9651abd7426af95abf96520bd85a6a055d3717ce9573e95c3b57918be7cae232726d71f55c472e24171797cf95e4fab9bab8945c5e5c40d717d7920b8c2be80af3babd865eb8579557aed396b7bfacbc742fa2d7ee75e555f4c2f2e2bdb2bc8c5e5b5ebdd7d10be9c5e5e57b25bd7eaf2e2fa5979717f0f5e5b5f402f30abec2c06eb021180e560596835981e96044b01dec0aac08860596056604db02ebc18e6048302e301f2c09f683758129c1bcc080b02fb025181858101606bd75ba03add2690ede8e3abdcb73f8f3e8dc721a9d594ede89e52c3aaf9cbb93e8d49d56cedc59e5c49d43e7edc37cf0c1fcd27f792faff45dfef749ef7b2e8ff447dffb2d6ff4599ef758bee8affcee895ef7563ef7551ef7437ff3301e7430bee45f1ce85e5cc9bbf8cf93dce75c1cc98f1a6dd479f68220b38ccba13c100fc808a80784c48ab9c151e5c859e9ece8e0f137676870d4d89c706895a91b6c6852030d33c810030c2f307161490b4a5858418524485240e184232618294264885009355a9e05019120240890117e64e90f1f114200a1c7c7073d7878b023a60329038587283d582f82106208228a30e288294850b925a1c412434c34e104ee0928a2a822c51454e4aab0e20a2b5864a185ce6e61b9b05d58222058313738aa1c392b9d1d1d3cfebd23242ebe2494ccf9507ee7b683dbc9ede876763b453bbc1da39dde0ed28e6fe7b7a3b403dc59da09eab8e9c0e9c8e9d0e9d8e928d2c1d361a4a3a70349874fc74f87920ea08e251d419e1b0f8e27c7a3e3d9f114f1f0788c787a3c483c3e9e1f8f120f90e70bcf120f189e204f18bff990e3bc8ae7dc8aeb9cc877eeeeeebea5519b1a1c3433e63b8f8e1d9d554e0e15ce4d0c2be7322edf824b40a59f0fa967c42bdacd74b3dc0c37bb0597804a3f1f52cf8857b40bd205e5827041b7e01250e9e7450f517880b27373bdf71e78be4e50270c1ba6ed26884392a679f3bb01a38689baede6877ecd24ec9d08200022afd12b8d36bac317cd929b883f79d51426e929f02a9096df04637cf8010a0f517ab832ebc51d75c8e10647952367a5b3a383c7ffbcc1862635d030830c31c0f002131796b4a08485155448822405144e38628291224486089550a3e559101009428200495d29c2c2cb62b4a57784c4c597f4eba2e405f865094cb016a6d3d2db4bb85d99fdc2db4bc075eac445d8b9e5d6655bec7613bcb29b5fcc4df071f0201e0817e283f0215e0827e287f0229e0837e28bf023de089ff24738123fc5a93c126e6f4fc56d126f6f6e95789b84db25de2ae176e8ed126e99783be4b689b74cb875e26d136e716f9d70fbc45b9c5b28de3ee1368ab750b8adf2360ab752bcade2768ab752b8a5e2ed146e736fa9705bc5db9c5b2bde56e1f68ab756b8b5f2f60ab758bcb5e2368bb758b8d5e26d166e756fb570bbc55b9dcfbc8c9b1fe3968bb75b388e9f719a37dd76f1960bb7791c5ef3346e89de76e13a7c8de7f036fec35b226fbd67fbc50ffd100047fdf03a68289bfae1533454a77ef89286ba29279f8307e075f01f3e8656fa0f2f436beddc7670ad736768e7a6c3fb10f9ec7c78209cf537bf9ee5aec7c1d17f39ec5dbee3518f3dcc79fc0ef7e063fec1f3f01eef81f7fc07eee37b7808dfe320bc0ff7f9105c8407c1d3f7f11f2f82ff7ceab2ffe1a9fff1115ee6413ee5407e0427e183b89007e2414f8203bd10cf1fe4b307f2da67a7fdcc85bee6253ccd89bc900ff912dcc813f1223fc48fbc1137e18b380a7fc44f78131cc9a3e029fc09aec223f1249f82b3f02af80a9fc45b78165cc9afe02e7c0bbee495f80bef8233f9251ec3bfe0303c139fe16370191e06afe167701a5e06b7e16bf0264f839f6f83dff04ddcfff4ff1b5cc7bbf3fcbbf5c20797e23aafc3779ec77b78eb858f2fe3f7633ce7757cf53b1ee57b70d5e7788e5f390f1fc56f5ee5389fc3a13c0faec3df780e8fe33f3c146fbd8e2ce51770dd875fc0e82dafa5d04db0d1cec15b6ef3c1e5761f5ca7b69d5beb6f72789cdb1aa60d8867bb09e6f69ddb9549f1f61ddc95fde0ed3bb92bf3c1db77749ddeec63f4c5fb6ce998cf961b201e9011500f0809c807f403520202022d0105836e41b8a05c902e68175414c40b320aea052105f9827e414a41c0a0a5a0e0ec36c3cd7233dd6c372b9af16646b3de0c69e69bfd664a33e06c6916ccb78ccbb9accb447997afe4a28c25f372966c94b7e45e3eca48994bf6e5a4fccb5db252f69281f94ba7efed79a9d3d3db33984e6ff0f61cecd4066fcf613a6de2edb45ba735783b6da8531abc9d86eb74066fa755e954066fa7e53a8dc1db69563a85c1db69ba4e5ff0761a51a74cbc9db6ebd4056fa75de97489b7d38a3a6dc1db69583a55e2ed345ea72c783b2d4ba72b783bcda85315bc9db6a5d324de4eeb758ac4db69479da6e0ed34a44e51f0761a974e4ff0769aafd323de4e4bead4046fa7fd3a35e2edb42e9d16f1769a52a744bc9de6a5d321de4e03762ae4edb42f9d96e0edb4a54e6bde4e03d329cddb69c14eb3b7d3c2743af3f6daadd3206faf0d750ae4ed355ca724787bad4aa742bcbd96eb3488b7d7ac740ac4db6bba4e53a70f299742e696b7d7883a1dc1db6bbb4e7fbcbd76a55399b7d78a3a4dbdbd86a5d31fde5ee375eae3edb52c9d8ae0ed35a34e43f0f6da964e41f0f65aafd31e6faf1d75eac3db6b489d7ee0ed352e9df6f0f69aaf531ede5e4bead4036faffd3adde1edb52e9dc6bcbda6d429eaed352f9dc2bcbd06ecf4e5edb52f9dbabcbdb6d429ebf4410a9901e0ed35309de28074c3a55396b7dff89ae583b358529cf583b3582cc7a510eb3a14a74243995e2879429353a7a71c85c3a355d021f4060b030bc2c0c096605f604098179812ac0bec074b82f9605c6048b023580fb6056604cb02c3022b825d81ed6044301dcc0a2c07ab02c3c18660b7579857f005e6b5f4faf202bebcbc945e5d5ebf57d2cbf7e2f2427a1dbd7aaf2d2fa3579617ef85e555f4baf2dabd885eba979557ee55250832b31c008f02f140bcfc252fddf0198c0d9f834d3e87a9e169371a9e3634c3d370323cad4a0c4fcbc1102d1e3e3a29d38c9551f54ceb3eb51ef1284ba1dbe50caf8793fa970f76774020100804026160491b98dd864a09bf5000c75be4e58b0c8ede9e9e32635d8a095cd1e92cdc0d062b856e88d1d80e1e6314e190bca2490155d6bfdb00232323a3d6e97011c6dd58bbcff7f329555f0d8c3a07b993c8ddc0beb83bd4e8adc38069b41bd8bf0e7ac0c8c8c8a881fd821a6bef1a90f8b4750e4edb4da2752f07605c3b49e25a0d3c9f15dbe1c189757a909a91c204028140d3f589ad83256e14454545a48f29247864023353c3ec5031eee5009f78efc537bcff448db557416e6112a0dd4becb3c16030a8638787470ff287baff7ebf9fce6aa7c707a391ca34323232cac9b1fac0474a774fa713985667752a9c1c3e7c9442b807877788601008fc02042ee17c0906833635373d20609b1a1042b835384210a14f3868aa083e40201008bc54c4a0ca92ac91757097b851f4e07b8471388cc3388cc3380998d66d1897db7b4c193c83f23165706fc7ef34cae0e54b05834f6313781cc751748c4913198a360cad8874c5d026e57276290cc3dd6eb74385384e1af8400986ac69aa5413488561e80bc3b0c686e4f1783c5e2eac28390469471165f1bd38b4c10db10deebd27550e9c23e7e6acda5a7bb1782770c55bde1d5550a86aafbdf75e8c719d91c23e218569bbbfbe384ccd4c617690043d1e4033e0b5022a206608e48e5cfdb4b2eed9587bad80955df264d2a8725a053b6c08599563d25c19bc7c31dd325f60ca89f3f73b69489d8e92b9333435d7897b134d783c79ad7e97a8b2e6dd28aaac7339abdb755d0a2edddfaeee9478d6c8f690c2300cc3367d277597fe71e1f57c9deb5ce77ab31cbab54bf7daa5fabbb22649d34ce5eedd1d0ac7a9063c238589f67abd9ee9ee461caabc985d6e49f7e613e2ab32ebdba182a96186503b72b7bbbbbbcbede5bd5d95ca346f149840cafaac38d6d8903c1e8fc7b3b9196dcee66c0e554541c55c20a3884be292b884c249e19442a12a4c4359925eefa81b09550addb38f6a90e4ca54aaea3ba972e01c39b744a5ca142a67d5252a55a650b6caba5763eda4c99c51e56817a05165686b20777f207797600532b2d6a34b9af7a7ba682adf5fa36798d649922c756252a5c7e01c6c07a404ba842a306da6ab321986e10aa6c8e1151687a7901c3ad2081a10866118e2d8926933ddde1260dac8059c748c624cd5349d910629c6c94d7e3acf18c1cd08c692e90c1ad88838724826541aaf48e1215f2c8960ccdc5b2801de4cd7a84c60fcb0042870da49400332267cd1936181caf22093b0a6f1e4e3783221e00d187c79038c698e6fb8219ba18d37da09a5044d1426ce14384060d68481630db3d432930253260d1b9c190302dc0abcc840b7031cdc8c81c60e767081db133ab91e11ed4e5684e28ca22c2a7d69c2e638a30ad9822a090063add8a8ee711447711447517cb1cee4daee99244fa7cd34d954e4e983cdd8c684b1434d1ecf55e8351769d4b1c53f6bd4fa2a0b0986b20dcdf6de528834e5a831eb1568ba55ea15c0b4994a638fc70dd2961bcc600b0acec018638cdba95c7bb5705be4c6663756fdde7b6fa501699a8991314fa85439d3a649923f3d68358d782431eedd2494b7aff7839a33671153a59231cdb2534908a0c6da6d1e8ea5d0cb01b1af3566339d501002848c918447848865fc64f46b22c79a1375285b91aacf732d63647e2a5a512a552f1c23df588d85150424f97e8d856e4b23b15bc5afa13ea94a616306380ed6d962c583e09609b8910ff0c20adc58208c4e952b1a6f604100aab670ae1bc8d86da8b23aab406cc6b8be6004b503185891d5ad752657868337ab47110093b19fa06487216e5b863276acf4c61176b25a6fe103641b8f5cc7f04c32afcf3c453aea3367575651e7793a499e6a20e5f207b91e5d4029440ab9746a72f174f26757fc4cbae83632e48284147d3cc3598736294ad9567d87d097dbd76080e1408ee5b5147a39aa08de6539caa6be04a60d88c703cad229eb098ed78c82f2950d2e5870b319e7b4d98ce3e3a3d9477700d306c4ab2d552039bc97a868fbcecd76def8caf35205725de533b7a6c0cc128da3cbf1bd7c5539aba5dae3c64777e3b32e87e0c837e73d6da3b366bdf3b69b754e5bb87adba540cedbf00b681ce79fd0b8cd285bd2b861da4ce32c1ac772250d2f376543e33117f0e5181fca1ee47a9486d1116bb3ed072a3632e378af7972e3a3df388ea36edec6697c4ca3288ffebaa33470d906c403eab50319755a8fbee0027404b4c5888edf1c24a3df20c9e12abf719c9cd3488e53755ebff1eb382ad761392e4fd8f11cc7e3db6e5c75faac61de388edb382a4ce1fc7514aa9647747cf49c1cb7250a387ecf550eff550e57f9e839bfca71deb8ca55a7ad085e1efde6b415e1b39bf3b61c2ea3f25a16b179c767ad73faac618ee70ea1cfc66b8964c755e7931dcf399fbcef7077cedaa8e938e73bcb6bde86b3fb2d8fd0f8e85d1af913376a9ecee3e369c371e246fda2a0c3575e4b1474f8cadf86445e5d5b1ab979551eb1ddf8e8b5515b938c73b12d51b05dbf719b949b759cb629646af5bdf259df9c38a78dc7a5dcbc72db3da5dcd539e33c3eeb2e8d749ef1d5cf78ed74f4ebf7b4a178fe3a8fdf5f398f5f3f5f8acd2b2938afbc96444e5f996e98ab23396ecf95111a1f9dc6c7d376ca2a3fba402ff3c8f5e802569ea83cc6515d1a3921a1a92a8ff159d378cc91058239c65538a78d4ac61947bfb101f16e3ec7c7b7ed10fa703e085b1e31723de6b4a9fcda12499df58d799bcaafa3eee3380ac7c7cfe13737dea591d1739cb5d19bce376fbb71174e974690728e8f3938e71395d3bced4675c638cb6777f535c798d9f5361398592ef3b6227899e56429c4534b219b1d425f0ec2661ab7c934a7cfeef535b39ecc5082a85146af96acd38768a5b3c936a0dee83620de2fedec0c752aee54e914e38c421d7d9bcda8e3e070866ec234da289bbab53eb0f6689b0ac029001f9c1396dbc8ecc407283c44e9c17a1184104310518411474c4182ca2d0925961862a20927704f4011451529a6a0225785155758c1220b2d745b70d1852502e20647952367a5b3a383c7df9ca1c1516373c2a155a66eb0a1490d34cc20430c30bcc0c485252d28616105159220490185138e9860a40891214225d468791604a4030942820019e14796fef0112104107a7c7cd08387073b622ed44bc684ee4428ba3211884420caed2c1fdcc7f8cdb33cc7e3b8ea6f7cf5393ce755bef32bd7f91ce7f91dd7f13afecfe3fe3a7ce6dfcd771cdec64f5fe3e5e3e0ad3ff90d2d6ff237b80d9f721abe89d7f036b80c4f83cff035380c2f83c7f033389387c15ff8187cc9337117fe0557f24bbc8577c1577825cec2b7e0497e0557e159f0143e89237915fc844fc15178246ec29fe0471e052ff226b8913fe243be881379235ec20f71a127e2b42fc16b2fe4b3a779fe9a03fdcc833e3b090fe43a7c900779125cc8ebe0237c1007f2425cf623f8cf03f11f2ff3f47f5c84ffe13e9f3a082f8287f03eeee341f09e0fc17bbc0fffe07bdc83efe13cfe038fbd07bee379382aa0eba884cbd9ef814ea1190100020004200000e3160020200c0c068462591604719aa8f614800c59ae766c5898caa34910c4280c42c610638c010410008831608664883a0af8c533dda34588252028f4701dfd7f46fe33cd62e46fbb006eb15648ed2320748ebad76665ca8e0032e64b58e4d1e776e2af84324622a6f6a95c3a508c9c7831c4fa27f6d35e19abbdcfbfa6bf44611df52618109bb8691e3a5eb726d997b2acfadf19dfdc890f5a4556ceadeb45a878a858924d4aa530146828d394d96002b329a69c80bd66b467a6b6b0f26455ca4a40415f2d1f0551854e558e3b1df9eae8aa6699c8878e7fe6867770a9b90a5671031082bfba0fce3404cd68bf27f63f82ed055b46b74d6aa68615416c227e88b4e78673952548dcdd375d2e3389f1815d2e6b40b4b977f94369578121146652226ed52ab008d74ee334c71d96fe08f75820b43bfc20c209d6350e4376733b623e30e86bc49dfb61bc3d9f17f76ce21ed234008ab9376c8f889ab3c26749b377f625307a9fdd759100dfb0e058c7f4101ca30eab2247a534508b7d96a87dac465eeb270fd19e5b7c8a152ab61755307ed82338f1b8f41d69476025951b89315dcd0f1bd9b45f36f9ea50fc6f98dc2c114da1ba328bc62c52f34ed841a2e29e091f440687c2da04a64f50e51872330c0b853cf9e6674f279cac165f7b3a15dc0d2bcbac6cb4d27e8b129320611d411bf8efeaeba9e83353ab0b318e0e878d93fa9cd3ec603f59f81dee810a7a23daf565b6aec5b090da4e57dbb64b2c1144ff3ea1467bc8ac83f2e437df87b105d39b8edeed524461f680d3702a6265037ed6e8787d5abd761136eb6e16c0a93682a1921151be19e6189840c4eaf9d3e1e2b3cd9ac56b1435b72e414055dfe4d883c50e0325e7014cb12d738cfca779a61a007aba22dc6394d2b38c79c3e1fc6eb139203a2358e6f97a51c8fd90b7268a5d4b98e14f012a01a72cd700cedfcfce1bbe47fc420e7777df814d057737939ec8a5eb056603971d8f565830d0f8d08e5c03efe4df40e41bd34f349bcabbe7fcb2824506bb7510152d776de7fa0cdfb28f8d854bc1507121def452e3b83793878d08585ffbcfd7f40c6be01e966c08295e31e953da5d864e6d6c4d8100444caee3ccda26c4fbfda2fdba8c138bd16eb79c26939b9c725bcc7c7bc74c33c0b8300420b812e8162c581553484c71713d5b5d9bbdc47d5fb44571385cabb44798eff6d17b8ca9d916a68f0897e7d5a48c48b3a908a1ff8fac9f57301584bed1a01943c7f58f5eeb6c27f82ea6da12332052031324a6f1ff4e5dd9e1d535115658dc60ef6a22fe2cb56d6f73f8c79eb2cc57a2ff638718a75fafa92f73c1045e20c25447350c00a23a5b0079ecc8cc6032400a99d8b662f0bd87ba35d45e272d16b59dc79fb47bd00d51d50b3a1395c99588121b2bcaacb017a92df865639d12c5a34edb7fe248da6e785d56394ee11c47b90d47fb03a318fd11bafa3f624127b8b6534347a33baeffd7fa9f481ed5d1e219402adb697a114bb443359a013c239dfd1de14658476377cc34982ac8234f6750f408316073421b62358eccac67cc67701bfa24e5961df2ec69a6227bac59af9a5b29480c84bc7be682cb58442bc6c37a7999aad99e2077493015c2aacc5c79ae54563146550ea3df4fb9066539cc6cba3bb4a520fc6d0b375fd94b1f33e652e6196e041ef62f740f868c68512357a734c3aa35e24de245b6aee5af0d240d01faffcd7ac0bb490146e872d3550e914ffd6206dcd5c32ac4227b643def5af84d5bf277e3c118256ecb0d26c32f26c05d05ac429c62a55c2742fa44d9e7bf984452fdcfa7994a9a9d848f92e7d5401e7c57b241f3ccd7ebb0cd1bbf255c0e30e712c9ad00720189578b8779edc66a0f8bbda9dc26c21eec39530155862f11c504eecf42b5f58b5462d89934cb5322a52f82b3f4f1d4a391bf6041a5ffd6729375a200629508e81ca75aac78c6152b552dc41ed065b79084f5b4e768cae762b39c180f35a65b4ae23b76993e76a91e9d392535a99525d35c3ebbf8590cd84cbf69f56bf10235019cdcd7a40fce6bab58687e6b79b890cfd6016bfec9f575f0c0b616f93381c70cdb138d5a5e604f8390c27c318780eb4546b9d5c5a6c9f5d57db3d6bab7827257efa2e3debfbe692453e7485b0a83da8ccbd42d44c6836a7b09cabac88497fffefded47e04c7464812d61fac55412f6a8e394c3c51131a4fc29ece4b33a4a473ec809893a955ca655dbc8cfe48353717b251892a2e918048762261a318f86064b588e47e13ab936a535826a8b406a5e22075db72a87fb8f581f454c7723f75a5ea160f30f430416b67c7edece8208d4a1116a25c0c2442bf40b81399e60416e4e400273b4d716fe5e269168a0dbf5072c7a0718037b721c49f4942c82334e9381630f1e90b0153aa2cffcae445511c5bd098ec6f32556bbfcfe7ef5073874103b7ad325fc7406fc219d62cbb754383fdca4e74662ac06b90d2ce1333c093ed09cba08f77e42d474ae164f7734631e44ddd78c5229e25aaf870931553b78b2d52a6f788f73bba3973803af307c1d5068200c942d5ad65831b25a80b115657f4647a214f2d64b490f818824a2451c562493885b1bf03a96aac9a386fd0fba3a8fea1afd8d7fab265134f9417464ed2e1ec59ad1cfd276458371305bc3fe5c691366d0495724e03db7f61daf4c68731074cb6850bff7e2bd0b3bc1390e1ed66aae5043903f7962323c452f1ce63c0a4d8026878ab16d056f282a955bd578be9de434773f166276925b662a7d62daf0bc6134a63049382b074adeab0059bba20ae1348bac0a5753f0a436148be6e1c63d205a07111636e72bc5df53816d86803f6588306a514cffe14e095d7352e32681b161c2c0b6c6c462dab253bdd1f3f77c0be2946672fa5ac431f674e6922383ebb6a69c9c833584830cf12c88bec88112edee8a0624762590312655cc0fc3435117ac76e27d51123904779639be9b8f568821803d6cbba173dd3a249751add3fdb1d92d5668eb3eaf15b707e1022d4050f288698232136c85144bffbc9eb1004a83a0918449731b8a90fd60e4127c10a40f5de5904f0dfe88fede855fd74d63f39456392f87dd6cbbfddce843cdda6aed4095bd7545310107b2a78a4deea38f721ec3efc5fe8d03d20412e7a4fa8976d02082f6d97f5c608374ecf79b413cf39f6cc64a737b417ecc49e7b19bb1ee45ab5cbacdc877ed172d4890af276eb68ebb52bbd5167def5e6bb30164e6c030dfc9a29c157b373f8802205518d043e919938e01e9892493117d87b4b9f770091c7771ba365c29a3196bb535a2628f363de9b369126b07b5c2a96a9305103eb1633fc4ac73c5836df6920d51c725ce917e56a5f4d2a5cd43b4255fc2766d4ba335cbfba4f05cb2e29f6a09ff6bf3dac357c5830f058c8942ea382479ea1bb63a670b0e1eb950f59fdd60f609985cbb3557515ea8125ed1c8f95c91b6de42f80e55a2257bb2de4ce55ab267ce966c127cfb0af1b7703b605df1ad8b50f5f6c62f7e64846aa2af068a6eeeabd30a3cfd86ce86ddf0815125a6a42b429521846241fbe354135a6182746334b1a25b314f9396bba245d79f3a97e5a8afa2172f1a03d425e9d4badcdaa28c6cdf9c1d8ad790336064addac17c8426c5b5edf882daa71d32e10be9254560b6c9c5cde2d76a82fe15339b4bab4204291861b8c62dcc503ea93dd4dc2a4bf6a0841e8c776715eba5acc5369bf3f5e9f8775095419df8f0e2992036e5ed3f1eec49733038547319f52600d9b213e31e270115e1335079e4a01911ac1d2bfe0137b5a30f01c0379623eb44a08fb4143f80ada097fad928cfc28eac51802a4cb75e5dfab4902645d1a431597372ac38a7697ab2fbb1160f254945a27f3daaeecbf0b9d031204b314929a4bfa5ab7b44664f4286e81e5d7423ff27b106ae9e8c0092a93e22d71fd12826bac083deee4841bc7f455907757c47e7fc9b1a642d18a7bba4897c99df0995b7f600db4ed0c3aac3fe903d46a7981e81a19e8d089e4084cde9cc1db45d81af63e84f5acb32f9157448501338bd18b32cfe13208813ecb50563cebdc35e9822990d54ce2f4699961267df8566e8d0c239dc8e1ba61a67be68eb6689387f2de93d762aa0774750cee1db790657d56986af8c11a755c316bae44491949b72c2e7d4cce589b3aa91460f7b8285fe982bf103fa7d36eeb40c4c24cba8e1e147965b8678f0a34ff1d9b983f8e9d4d52f5775611e3bc301b7243d65884fff54a780d18e2c6f6e0f34519bfa064fac98322f276ceb62e7ac2d468044ef947faeeb92acecc3a4032813eac183c89a391b2c5e15361b347ec7b21dabb61444c215dd48a3a0ffa4967bc3ec03c68d834950e39ffb254dac3dcfbd2663e241c0706777211e8e986fcbd50f19070a1188c6aba52aa4b7f54224a2c5ecf7df8d6bd222bc82a332fb8a4878b91f9c285860a8a6c88a876a36884a70b32c89fe8ec45faa6a480ac005166fd5bfaa929cf88f36e2581ed4458452a2a440f2ace19488ae4868f1487be91cd7068c05d82915a81198cfd9860e0183025a06674f45f9d303d6fbe455095bd039df1bd2746583d5500023cd4cad00da0528af7ccc57ecf89892fc4e8e5ebea8d39c17403e049d9f3ea05f4c9d5202a09e96117ee17bc9418765dc1d1ff3c56042edd20bcfbf90486ad78423a3a0bfbc36eb3256d0226d4eeb7e5fa5b498c35f84836273555cf2cb588523fb744b25e7235858f39c9769b1cee5a055c1aeff6f1b77c6e83aca3c9ab835658736577a0ee264dea3c14d445e38474d9e146a4f4af0448238d996cf762d0e491e39b857fef315a728a1517b9916ecd0df03560e11f25fcfd84d65fa8e621802d46492809367105ed6ec90380c8cda4ad7f616c9d923d911639456feb551a213d4d45417410a023a4790fb7cca23fdefe574583168742d33fa975be095b7161deea2acd2abcc5119beb5282b07998c85e961216868126ed6dc2e94f4e7dd2a8ded6c7cc3a5db833a5ac447b611581c6d77eff5c39d54cbfee8190209a72c5c3419594719262f156b164588b0d7c7651202a69768b09b34588a32a9eccbe40d20dffc7c209b586b78619b536063146dc61239b69dc39e19b8a83d8e3c1f82b13fabf78210803ffd1a23592a1b6fabc5bb5411f2fbc6227985113c653ece97c93a8b6970f2a2d18b68478f8a46731439a79b5e2ba0a380090295fb8deda593056a554f2915bc32e2c5ca7b2fa88ea3f90ef1fd05b78c1ee5476ef677f632f7c2c48cc50b1b81190343afbc040aab88057fd79dfc58138f1a99909542f7699da788f858716880a996aae432a685f4c3857f78503051330b25f2b767601031e6d677eff8ab8aef271c2862fa92115979c5c02efdf4f9653dff4c7d9961e0e308bcbccae9758ea3ebcdaf09b76b05a3475579cb0600d2e3fc859f3ee9ba3c576af3f6822e812abdb012583b7629bf77f5128be2e03192f8ea6e680523865c11f634544269168fcd1cc39e09e003ec9001609335656a84e1b5633efb7532a766d6a73649f14f20fb1e6b7cf482cd759bde412fde50335add4623fd1629de45005ffa7e3a7b27d919faa8db39060b2c3d90bebdbfa2e29944311a0cfc36e34fbab17712575d5c7812b6f0869074fed006e53d149d12e57e77174d4ce9f66a712ec3171eb4854451417a4c98cfb9f7e2ee4d9c7798392cdc3416042f403a528ead350cd6b80d54aa152264591eb49cb697e3e64ca379d900f43feea10a97dfc7c1c9ecde08421b410b390407323ecb68a61f87be787e1b96ae45a1eedc5622d79c7e1277f449bf42abb9bb6d0e1472849d9ceb2b1bbf17d0669fd30d16dcc8a2a30ce090b00e11f9628798dcd7d398a6e7d77d5b49a6ad58076319eaa6507e3e1b9a02ea6a1b58a652373ca30748bedd8597acf7f198895b68e22a4b6a793258487a32fa1b019d51ca0f834e73343cbf472dda36b366d812c3e27647ccfa75b28c82901431c70951d0edab67bc817c1e44d660331ddb8544c8ef4b7c63cc8c2ff753b87748f8de1f430c00e5627babe7dac254a72c779cb6a85f089adbd4467da7ac861d099e10a4d9b7790a718d64bf7534dc71a6eadb217450492d4ee431ad099d0428ea6106e84c8476ff04031f47aef1113487f675896edfbf4f89a00173ef8aea1858c3782b5a9b96955a89dd9715a4c9a2f883ffcb16dad875d6cfb68d1f66930541e599c41b1eea1c0459074e7abede80a08158b984086e458c82849892f3f18f4c0db8cbe2934e3a75c24db8270451edace1ce538123167c86cf1c3fa078d07e226e0046fcff60f363f8b09a6379fb64ee2fc0e42d12c0e896dc9a124fa97fc28a1cf0e304bd8e60e2d6f179094aeb3169879ee39e849468501ccb15a64dcabe8ee1948bb63afa73560e57084640e6aa334db11e82fb404c67878fd0acb96c859c7a9e2a696d1b3fb845cc9888f0516094874f704346cd64800aae6710d91517389fd8327aaf24e8ed537bfb67eaedb9b0245a0265668e7f41ac73e8d5e13fb483a97b956e0ab5e4134459a41ab892e9050ceb7ee31e9f8a2eba32f24238701403ce7930a3a7400f5560ed9c9d0d8f7c6e811ba94d8f68d3b1711381b15da8852bd8cd57815b37f7e5f73ed072f2dba8d8b38e42a66134017a72e8ac1e4abb7b74ffa6a21d60c22cfea2cc703bd2fa848f3a6c42fdffc2f8666ee1950f16d45a5f8649f61b7c9cf402f792eb5d3c3350e29b055829264f347272f110b8ff1022b91a9704f0a35432aeab3f11daf8b814c23d63c58bac0fe28e818005a95b72198222eff7f3a5acd1b8440fe9a84745299925076c747fbaad71e3bd0ad8efa88138368f68453c5466145f658fce07afa737c0e704049a8f5cfc50fbfb2537e638a345ae0e6434e0ed1a06f3fba06ac47a2ab5934629459ecba22be07bf70dbdf43bbabf189c30bfd9546f7329a829b3ceed4851012e842b15ef4ed5d1efa65ca12dfe04bf76efff71083e179c04789fd930d332746ff4e224fff882dcb9be65e6887de3ef1928585811fe76e63a81063d5db02a1f2ce07e4b4ddafe5dfc31a71084921331b8fcc185e99061ea5f9b46a69db48124fa8712ad7c0b10541402f4458c424fea2c0641a3e0f66b211ad1d6e428fad92de1641705702530c285e096fdc16fcb6c59292a07769530a807bb0591d417b88a0cb583eca20ad4c7ba4ae4e2c15c290deac06e2504fd44ae2053e5015f29827651ab50a1fa30578b9938c06f3c9290fa7ae5963ed33f04aab3a0efa03605115e4385be7f5fc4446fb3431a0ee395229a51ad650ec719080d6106e5223a06e410e1881f344707d3b941a4d9a1c1113168f0b8a058f694001a111ce4032de1c06c3210020b40cb04ce8140231a300f0584cd01a04280e304a021fe9bd93f19f833970bf51bd442a259b4c4f4ac9708758b0950f152e2040eeaabcb65b3032436f65f6dabae37ebfb2e6f169bebbd3ac3555f7d1ae7d489b2fe90cb1fa7132deac4547622bc3b01bd3cab227d10fca6bdcd206ee252102e224b48f2c4ca788e4b3c1d0b4fece0394ad7093982815b50497f91a9c9507bc02eaa407dd42854aa3ec0d4ca241e6a165ad057e00a3ad51eb2b522681fb48a687612aa8719a54ad407985a99c443cd42cbe8137d7cc9299828a61bb362a73058f972a268b7f4bd89258a86b39ba4fe07c37c95a01397ce4abfc3f41e5071384df8f44600614666755dae902cb1000f1e2f43a2d3bb240d6dc75d908cfd64367b96e959edea281c56fc517a77bf150f40bdcb04e04819163d620f23ec836c39d51df765634a157d614e569e21c9077969e088081f710f1f5317236cc32cae85f1afb308a54ce54c9316b415ab96c5628b8c34eb76072c0d43a5842890fcc32e07d480b46f95e3b630d275b4c29450ce69d2202b01c6322ce21a1c53ff1f9b05f0059c7f99f5a81a9465caaafdc1dd24022d717fbe4b237c24aa9042ae04da8cbe2cc99b1675bd11070b6d2a228d1f6576212c27ba26405637544144942268e24392dd29ca85a089d3d335391050a3686278d062675272a764a284744d07e46428960ade44d891865c9130410aba250032fa81242f1775b211e748db43a471475912c284a2cb83ac5fa8e2445402344943923945cf10c49f9e5cc8914e8d6162bea08531294950229b10ef747c053218adadbdec0783189129d6588ba95dd48ad9b0e8cecac5a8e29914a583f29d535463a2704ace871475461411911b84e2e01f6aecf1483bb12387a26d7c204d34c9501930ee6e89305728578a3b9c446d12ea29e25220d1c083026f38c38c68baa01a2adc2d112521a89183033044de09d479e0ba0aa2f54d6cc5d32465e394d394b2d3b4c14c93e7eae04881779b69e4a431ddb846c199edb4a56c7a65d8d360993eb85232cd365939685c338f2931b63bac28bac69750badb7114eb1a0e9edbed863513626d30d609c9da6b211a2d901d605301111ab531056bc980719dcada21b2c6c0580f47acbd8635021eaec6e840bd98aba466b1a690fe34e30e81360fb34ea6230789f10729841662063194f1ef592fb585574aa90db1240604f1569404145740479d22aff88319ca0563ba175c7d4ff3ed15581ff96b956504a08da19a0c67914e836bb247ccbc4aabab8cd1665bc4e45e9688302cdb6d8d96d2267c19b3291b75c3c73324fda1d7f082fca2630597599b50a7fd1339b22ee9a05305111ad7d132d0dad74dfa4a1601533d11e2658fc1451eb6095cf69b59a02968294664b3c65bfeb59e577ba86afff4f6d128d835edfe430ad6a948722842d26f5d0d0545ff8522d22775f39bff8af70a3dfa9a535acd6c379fd069516629c283ae58b5c210cf3a3b6444b6de0a155e59e8e59fa0d9f36a7ff2c64368691ba1948dd541a69b85469bff506dd8049f7c97ef75722f0301751ae98434ee8174f973ce2151525d4326fbf143165326c3495314d826a3147a2bd96ca1243526a798ce4a6d54c425aa8609bc5399048b5600889c4a07c5437c5125e2624d2545f540aeae26f141b3a6827c22a3d2a970905b5541e413bfa353600718014d4d64e94146ad66ea416f41b944ecf25d1063a5b961ef74156a6f84b99512fc50f7cc69ce203007374b56058bfd1aac50a27c66d7646c572b3aae803af11a95ca562084dbe527a0326ca0096edd3ba0a12114a0fc0bf929c7f4897deab524c6630775e80b69d91de273a5bcf627916517a4130ff21ab86f30237097e2f29154f3a6d78df4e1cc4bedb92b2db44a548501413d8b2419e525c051224cd43d70cebab280ec08eb6bd57c5658a462a676a4097b4a71162860012990bc0777f1c2dba2f8cb8a0602ea19a1f7ea777ad0b787b759945510037ffb318caeb5e9bc5eabac2224aaf0887d2042b75df8f094b20886f11c104504e1e400ec021f9cc053033a4e80b309b61c80361bc8fa030613b854078b63a8ac002adb30cd01a4ce10c11c2075e1e1191cdba1c92830b386a521289005899a80f00a876d6064108a5901d10c064882a01604bc01600bfc07810f05744980130a360fd07e818c3b6089c0253d5826503d0f146f9872004932440600fa1a1ee6e0240b8d6c60bcc3f215148621c91210a1e03009c65f41422c0d7917cc753426ec9a7c6996ae966c5d902c5d72d534557733a5a14435e7e96e34e968a526887441469a00519b83eec41fedeae9889ddb1847036d7a16cd75c868d92fed6cb9905634474a7b9b5c4d126d24d20220d7b843036e34a78cebb8d0da146d28718520b48743c32fdcfe049d3f68dc0b2e7a40e706f4f76f43fbf9753f4bf33dbdc3d4baf29d73376e45dff9da9e7dd7bd4d43ddb3ba2d33ebd86ec359f73b61bb4dba85d22cc07455e500130580b79fdb005efbc97b8f7ba1200cf9aa2efb98d416eeeab2895a405f5c30470bc45f7aa15331c1777f7bc06b3f79ef712f7ae649effde2058fd2e26085201a9e150747c9c9ba302e5e1144db956009133d3b30ecc12fa2390e7e19fe1a654aea3c3b09fba611a914b25c380b896d216fd57ee54f10163dcf930bf83427f572a0704f6f19d878a0151d61ebb19f7527462b524024841a64e02282c525c88d0093cb27b4781ed2fd1c1c335ecbb833d117f39bd7c367f15f55ba43093b26871fbdaa213ef749341df9aeb159ccb366e12c94141f91ab0f636bfc93055b4724a3064946b014c13bfe07d29efeedeb241b3cee505013c7bcb488c6b91b7a7ee3f3ad0c94d1186d1235b99d85210dc664a79919cf008741c537449c2d5a4c0b595cc010155b402657583f3144bcb51cf3b83d5ca7abd18d4ee2ee9fa2ab5be42053afcf78870988b05c9a235c3fb2e0d57f6f323ad26c00abc85c1aa6849365ed0f8fb96778fdaae4256511afff1272876bc3bd9ff8873c683b081a8f2c2c0906dddfbfbff1f6ceedad5b6d6ed8dcbd75c3d6d69dadb7376eefdd6a73cb60f3dc0bdbe4a83a59ab79dab2ffcf5a057f165cb92ee798a76416c1676d2b1b1018f501e555b51dac505e6b03532a77d9905878e8f84f7fb090904c62d85799963527ae3f07ad82b92b2a674ad8c3cdf54fcd5725f21637564631e3664bf8db383141fc017f75c5a794fe72cb48fa0f6c13bea241c727cb2666b834d1052e39b64c755e1495f46cd116ca172167ed03f166e40fda9eb12303643ae527de33dd54967724660019541e1f0e9a04248970aadc60fdc672d1d4b8d0f562d8af10e3bbeb481d2164f38d28d57630d237069f3174375c0fb3f1378a3b6cdf722676b7c6a1712499d9bbc8fc5f9b567d9088dc75ff7a941553302e1add2898e1da6430285a1a3138187cc79e0b3c9b28082d096e48e3f9eb17d2a55e812d88e90365232dd35100f22ca008b303dc67e448602d839e86d4b34155c06fc5a90a853426626e46e7b64e51f34b14a937a61fe198a40b6ba364fb1dbb2563c47d14a190dab318a252071c1aeee6733113ef879911ba26529c87aff14490db6542b3dd1b4a5432812b47c8af978395ac92122a40057afe2757d67f857183ce91dc10cce4239249600116e10ffa5e60890b9a630342d03f065f0195128b22137b597aef57d8b6a293d6569c3f75477fb18ef9466f77f43552f8fc6fef020baa7ff1b4b61a32356076dd495ae48ca46114d1fe7e043cd2b716bd4ebc7b1ddbb98ddf9ee8dd340309cfc4c5cda78b773bc8c68d04f78052bc8827a88b73d36db32eaf409f92f1c2bea30d16e2331a31a9ed85b1eeaca3f5351bd69433e444602f1b5e4398ce7e68a520f0492dc4a7f51acec0de2bb7fdd57c5b0c8ab08542c0af5cbd63f63965487710fed9c16736b345a9f49f3476c7f40c519d73414b13333cd03b66600d031e3f813556ba45dde6a09f8d7eb785d0957c0bf08b21f9a9c8b80db4218e2eeeb6a27f62425117ad6574b971e4948ee63c623c29f1f7e367be0d9d4718aea324831dcfbe7a3494b1e3829cdb07bef22d1d44d8873234d5da2c80b5132b3a01aa3772d3f19ed4178f5eaca2c202575fd34c7ce472eb99e1721495ae80be874a454a2482504284e040ac81c490e1eef640f7fa855c93389023a2a3145e60d4eca128068025ea315d4feebdce80b6d933a6bdb8e28e23c9c965931d0831c8ce165846b05f57f1e72b448753c25fa08baa6b518a9fec91eca62277ee405c07631f750397ae499f822e5fb7627d11e0ae56ed5e15406b488440a20388092e13beb05b5d4823f79a86f1865b44a3879c023ad1ee845445f02657a509353ccd888e44894ab7062fc87f3276f4a3fa3c3787fe9fd0088411414b131f5c8f085ac8a9a5c8c76274158164f55f1b68b48a7bf9bfbeb7ece620f5d9351c3ae52fb5c4dfae3db33409210df62e52611b2a68d48b2845c2759183ca8fdf9c8044a0112f2329ee8501770fdf8e9cb9680e501924a9941bc7e0d647d2434c39c5219659b58a73f5dd722364349b937d8fa09682e4d492daea4011b63642f6f25091b38b94ab99b6de0ae22cdbbe245d4668b32795cea3b8ce60dd878da283281af52917773414d057d7f3bcd159c7d3fe7af0a5bde2119000c0e6cf62f65af7d7c095ed596da37b93b22b396429ccc0871b5f82fc6991490225dc74532fb874cba102e4528cd22b600756ad9625efab3a600f23073d5355e3dc1a1cd39d183d47d8cf22e1ff387622a976cb6f38ebdfacd5525e229c932742d6e0a36463c8418108e7619c1837d9644251627a6e24e7c68b704adab6f395dbecb5d25aff3dcec20d94a40518bda6c701ca10ba3c8060ce27409fc68cfbde211de594b954f09b33a1f56f61d5007161c516e6701d96178939e86bd0155e2b98e9cdf7d4dddad166ad7fcceb86120630ee9c01d056bb7d4fc19f134a2918d339503a38105acd75225a1d5f98d4085cc0370c2114a5274a5da886873ea8682af507fda575d92d7bba6a6349f191c702ad0a3af4faff1513acb150d8eaa91e82048f63b44f3608415f56b4d3c781babd71f811c2ea3dd0d61d5fb5e53d9be1b12c806c231d20f8a461c9f374e10036a036093ba816d3c4a19a55526ccbcb25adb06332f368ef3e9dbc6cc65b126cffc2f29bc6a68416680b30bb6145c8a09cc1e157bb78347e74be5a713f876941b1f818e2fd8931dfdc48ab2a62a23ababb0d6345b735d16fec688ce9a90a222731ca3e3df051a1de0c57958ef96a52e67a14524da8bc40ec1f35dc55ecd99477b7ae66c72183c0e05ba2469b694b0f80d436311e9372db0180a73774b26125e4772529d6a214af658cb6b531174a70069306547e575aa818d9a02802137eb78c0213b306ea395e21e3d0eddf24f8da0b86973e042d16951773d4a0ca6147905da023a6090ee5c26cc53282a26a9be8c5168099bc8026347d2a3aed78d605953abfc479f478343c93953e77d8204abf8b7cdc5724e2a027844004de6d9caa06928720239934c33693c8dc7db3c4786412b08df4cf24b66bc04d7b5c091405a65f64a441a3013e16d50d4d0e26764eba99be204cb354fb897c2cf248ed88d148e6425898975b4f8e3b347748b0e077b3f3571b78aaefe615c0ee566b92136aa44668e1f8c7b18aeb96492b4370ec625b2dd6ebdfd485ba9879a509f1a6d14058b090e1a026ce21cac340599bfd90fc74ef376b201ae61d87af4004618c48f893aa40508f25776429161607bad40ed683430c70251f0bb69f98e4c8016c446416dcfd3c32b71ee91ca2c69f95b43fe4fa43a4ca17b05e90f1cf0e53246d00bd4a55892470397cc506b835c1d61b5c6b8b1abd5ea467d6fe2dfdd4b5169408cf0244df55fbcbf430a17c6a3a52bd998298dc029e1dce645848284a7e80815f07b4915acd043efa201e1c681c0dbb0b72f59523ec7cebcbc3c061a9e5b6c43cf38cf4866a64a22fc26027c696e49aaba230768439abfd8443348a75919c6d0f8bd3d5cb058d2c2a9276a017dbe4647b4eb07ac8b95f0946de6bebaf9376f4e325b164bd84ba4c89fe2c95eeb9ecb14c51502a934f3e512e56090b7f8cc6a0f16b28715c74ab274c73c415e508c32e5fc0cff7042a03c91a233a59d7159cb062ad05f22fa918d8720c2a847d0a535eb950fbf21004b986f264db021def6d3046644f08954e649a336ea465928e2437b333b4c8ce9c11f750c8e5f99519006dfe6a8bcc0924fa60b24c91fe6fe3b87c5a08870cc713c3493407cab483516de188da2900be01e672da2f058c1d11abe0e3f8cad7d44e3000976d38a6140c4bbaf33520c3c0e393be06783392b20fb6d7e7d94e5579aeddd216f26f4b0c4811a9c339b8977cc21f3e928bb74841b40638153a7acccc48c2a8ec5100564ec3f6ac83a8faa113230bac6c31066b1ca1bc9cfd99482857607acbdbbfec5c93615ea33bd64fed3ff4abf31892019a7bff79d30f2c451afa94fadc2d7f4e3e8671f498188f0d4821c50cf466ea686bfd1dad111741c4e7d8455b24ab8061a6c9ab86a269ae8d920f8124b8dd8d89106eb7478d3abec16e2443a9dc6f4a8bf0ce7771973bc2462f1e0aad72268141947054036691dc284bd206e1e4b9a9259f3c31d1d81bb96b079ebd21735b49953b99307d552fa5d42262c4615d825f54190aa37a68d281fe5586c75ae492419b496584e0e330f0aef1a3c8d57e856ae88e64f1576cd9d8db7f60e25e4ec24bfbd7e2acd89aaaabb06d20b19176bc2d92cd2e18691a57628e4a5f209550a9571a140bbe37c1260ea944197b77bf27288468938aac0cb7cb9be43525af2b4e8f99573fbc91700b5d4e4244f453b4f4b730cd49a5f4e8ae07bc361a72e0db0edc7783c49b3e3e2e64b28793ecabeaf9b9a650b2ec21710cb6b859cadd782a495cdb6212415e4f848122788e819129820a5d390e13719cfdb62c921abcf9f731e3c13d7b58ee18bdfda984cb360bf51a3fc46233856ec4d5165f090f7736d65cae44a2133c33b2dc04ee39f2d304c38c30d5a829327d4087b4a6a2bdcd88dda2c63f556afe3a71f112a2acbc20cbf748f6da826cc50f59f77fc7635dc1d99a3232d105737c13531c9d728119ac4ee9d7cd683a89d5e428d1c89e1e19bd8e9aeb321c74c033aac247807834b7b4a40e27fe5f4c1c12febe03914e22b9984ff17edb236cec6aaa5f4e549fa4ee2b0737168d89e9587f3c00ad5de7108142c017b6abf058ee95958da3b7e36721c1e355b40e2fe9b2e8596d41d67dcaa53790ebbf78de66288328b2f3159f70a280c279a79ca573e15c129cd353b210bff2b0e141bccd94d5fb741183ccd461f4946a6ea74ff7ef38d5b36dacb3d6b93bc0ecd21889fdfec90ff4986df7e4a6d5b77cac0d391994657a857e99b7270fce3d2c25273a46a1d9d756b2b959aad0dcf0ed9868f29b9ec9d30a8c6808bb846cf9413d1600c41506b935aedde0bcb6cb1871463f4369d978fca18585a3a72a3a90e2ab60674e2dd353e05057babb6e9933f1ad625c6408eacdff554ded35e579dbde9a5e0b495ca70d344c46913a644eebd6d383d4ceb50c98e1c2be7e13319217961496b50a726353a7186d7b7dbfcaa9e526af1de878b99f41029c89b80d43b7f0d679d142a3ff39b7100810636d288cb750a425a7d64b1f2db8fa0728dfbb05b21e74514c636a4f6173eb436f645d004c578295abba4f60611d6b8ccd9305b4fe11e791c65562646f3896f35c9d4a1c055bcc24a25e297f1f7b514fb6b4936639cf376e2974a9e58a02e17392739ad97beed76289bf3767f8d9d3f333a46b090f8f941e0ae9543e1355e4d93edcb64fb802609c3789f24c198492dae7bc436d14d048175717cf98f21c320a0d39de6de6b87ed160113ca05d1e7f1ca9d0228a5ecfe3fc02166fcc8aa4e2fbd36758379631019410cfa581cf68e327b756099551bfeca6d9c4ce4843f2800448c3aec58873a573437cc89ba1269c534af995ac0186da331bb0581ae498a91f59c565c85299fd40a5a2b7c213e9307a320a51fe192455d5376a4c90c579ea62b849e68f688430b41af712cce30852fb7d060f3122cd83c38d04d9ce27ca8603474a86c7774928d2a96d22c8a6849339e7df0328fa12212ae2ec27dbb49bfdf3cd7aac0173a1ef3c250837da39a53de66aa5c6fb6ad00f5f612caf37b8a195452e67fd03fa37a76eefbb4599e2d77331668d0e35540890b2be78302de16068e5241e07d1e33fbfe39965e4f53e72e863d848e31dce7ceaf7a26853475ad13a170f1417090ecbc4152b912720bf5d32a823186dd618f5303074e2f40e7ac59c5832337afe20b2ef46d8633420624ae7b363d741d8870011905051093fa68614a2464c7098cf4a8111cc7d8330c7a1b423ca539861fd389fb9dcd4adb57b800f090b0c592eb085552a69a22f9465437c06ff6ef7c0f9266d4993aa5f38d9de8a2cbe2513f8d51400d501fa19532901e8ab082e2cc4c99b57884dc40007b2e7e6ab2b8a18ad2307e70bae09d8240412be8af4b4dcab72302338247d915c8e00f4a5762a0a06a63057a50f5d8558b01aa55fbb76115679b71061133c6a35e101d22554e0c0d444e434dd6375e84536b13cba52fb972f91bc6c8bca5a443fcd378154fee325351f429827c584923fb58e19e24c9bdb5e23f11913a627d7f8dd0dd745fa821487f2aaee861bff3d53f4b31a3de2b4d3996c4de98611cf6cf34c7943e3068192e4546090b365ad2e2b725f4b8ac05216410d180d0eedcb5a1218d424c4d92b04a6b15c842df4494976874c89dfd2db4cdc7a22942e70a9f8b9713893b23904ced07bc240b8b873521f6eb26ce3e1e210627dba353f2000beb976c180678771a6609395478da7ed6313eaf8e8360dbd823ddc5186e3f690399d0610fe4b6055faa0cba1e2018c5b8833e2812c17120069eada3827f903f1eebc08e4c763c439a63cf4fd800a654bfb4cd5fe40318687ee738b44d3955493282e8149dd80eafc7277f020026020b4d231f87e8567001a71663d2f23ce2d8b5e15ff96ef73c4c2fa8788ef0b940751411aaa43662cb94f27fefa9c6b602d7732211a8d9d4eb416a413d640328d5777cd241dad2e9996e204529546164510b1207f22b23534652e489ff6facbb10fac92f840c44bb7284be98652fb0a2a5fd9a109e9bd18d900f58c68eda36dae645c9f0be0be4bf3859ef64550ac6d072c3fa0ff35dcc33250e85b74e5526eaa7741f386a0354e9f2b94139fdbfe1ae7533849761f3baf263c52d802de1eb44059a4c7cf5f69fd8c524aabe1622f5b5042b22544ea14dc36f8528bd9253610c87bdefef3d99338d44a3cf68cb5fc5aa06c01ffd60b4e75dc06d3293c2a6dd8158d4da31542d90ca683139dad1a0dbbbb736d3947633dfe93c0930ccbcd800ded024854f04b0a782d1d755fe133c79951771b0c7052acfe1b8b90971c0b0bc1ac6cda3011bd4f72cf80ac575b7c6028408763735a201918611143204286380742791345ad19b6c078905acc90615587024dad1939c1e0da905a115b09ed841868980585aefb096688fd47afb3424a125afd0c3b1c2b769b358fcd4a7ae6b4e43893572f557a67e290ca09116cbade1a04a0f52105477cf5e53b3921050aabc7aaa79a84c1762d55072ede7ed51114684d9555e2d649a062f7408b4ba978482f32892effc24921100fd2aff3d7c0707221552e8ba0ab72e6451945c39ee467952e5dd8bffbe0df33d70774bfb94691304adb8b1d91d149a3d867482311e88f7639103362467cdffdc277a7c55d5c1376c6f515687ab552463c37de7290f36f246dbc7b77689fd2860088eb83e8cab4fece7d878b693470240c79ff45473214ed3590929a9931f104836215b47a3f8d1959254d13a78cf72abcb0428b141d0deed4004b3cc71859604dc0ee7b3a56817c23860e7126bfc71d1a1bd3f1c33793b62993283e0aba47b44cc8579388a4866d20200665ce9b60026935d150a8b287ea975df276a19621739e8c4f03053c59d8991743642ecae272eab2a5310b8a52ff7700695e34875727e0e495dad3ca5a2a7e93afd3ca70b00f5bbf3f87083c1eb03c878b677f4debd421fb0e83cf76b48ddc910e70c5519745ca6cc6accc6b89ecf0d9c6ca83f566b6a112b0c66a2d5f72ffa1b43375b7ad0f263b88edfadc848f84f2db505259784ca4cde6735dc03fc88b0359608cda697ab4072b52111b20018bd94a62ab1b490a1419bbdf42a6e099d8977f6fe9ed98ec98a464a00e547d9c6a371319a41b538051fd1875175d598f4154bb9560c6d99249926fdfd4f23c80c11fbc1ee8dd1f36a4784d33386a405b1ff43dadb54efb5400b32615819284e4aad6097cdcc4086f981b5e7449b25ba055faf00b8aeb8d3b03391b273f1c18a7c6fd689ab9417c8698ada61389e5f2d3ba8e67e6236ac5899d10bd02e6393594e21ea8995699b06ed6956745a2103e03f407b1c65acfe17b468ac9b071bdc007a3bfb0e6a11b439a45adacc1f5206d642fe57d8900912c40fc9063ab1834bc32bb3960e0c59d21c303764d44e3e2fefde563e4c9e90833d725d795313cb434aee3988a7f261b430b43626db807eea8fbde06b74cc9b1a28c71e6d7351ca8d1df888dbcead0f30d12599edfc32a88fc9617f63c3af436605a83822c224e8f1617b6a59388a9cd216504103f69f293ba3a8e4158625189596fa573b0f0db8a2e924340b0d49ab21df196197ab462d3ace340355fc73fd661af5f7341019a13f22ee91212399d9a16249971c323e9f2f4a0e9836706b1850ba467cbba1eebdfd654564482cbb875b8cc4929f6d77747ce9be48371047c34aa5c134dbaa0d3779159de43c876eaa3ab7018081deeea8ec02fbd56fc453fd1e2b707aa1f53f9d6cf6de17c4857abb25249eec4a0e788d0bb6e845b8871e3e8c70d6c6d1b20b11547273af0b36f14c7fc071da6576e35a5369e1e47404897fc4dd2cb502f0c11309d94d07c99613cf5b7a4e45310907018c4d65b342a1e1257453231f21a388b82381329d0034abcce6f1e61ae06252f3b90e3916eda6fa5a85b4885026a5010cf7316a961ef404fb988620467a1424670f84b624206018403ac6cdf62e3817595205ba6cc55662be65b0dfe32e851e439a49564ab8d44c4c8cdba16187aa15b1b69be120114c65c7bc1762be265df548988a9071747544df3186cb541bc6e1688e88b2a1141d20bee962f3e907879e4d7b401b9d20d6260035422167ffe50bab7ae126aad83fe8fa5083075844ce187d51c25e232d15f4dde7d04bed9714a8057ef2ef4859aa569843754f812b45137e17e0f8656857a28b45648157911a43e08aeb8437c01fb04b587883d25407f0b37f8375549bbbf5849660352962acd01dd345448a00fc4b44b8a1d68d76560e932f84ee3c17d19acb445d9010490a8454c81570785f735031d80ee1b0fac54079d8f4e73d0e880fa5307f1f34233d1b083887640e690c3797dd9df24bea8e72325622bb75be381f95f4eed8bcc969ec610e671205432a9704d003c5f03771713bd71d9d1cd5d4e10d8857450232bd4749a1cdd3432368a61a8ab9dcc03f8a6279fd00532c667e0a490616840937789e83ab6bfbbee43aeca11e991495491e17abb572375b8e98d2092e3c41340b6f44432a816d42e1f7303ede4817f042d3dcfd05382f4a8e75f060466c3f96ad7d77543fe71a774f9354439f1d5ee100cc9a98dda7867e028eed614d687b5489662ea7773e0247e2e556f15b501e1a38c2c8b419bccc358aa541393c29f2c2edf42a5a40488dc0c64c227509e2667ae1028a5193f30d3ec0833ab45e43ce7412e926b6584a005d1d21dedeaf1c3d413b75e9a7137185be258362e55ca5048881c9f3a7683e11b924133cf468925cdc0c28e7a7c4f4d090e46f7a4e3e256acd689f959c146cb99ef5831f72fc4ae8e25c5e1aa4db12f7b2130450552eac44a9e0c0093fdde2182d6445f380dd3ac1a7231da04d4b1816c987a9ab820277703476348da53dd08e0887319f711dc552caff8b8f3f060c055a402e407607ed03606e7bf461c6b570a60bf40948ba4bb7a44449d955b041f9340c3717e5d7d5d7ea2b12af16268e11b5e6a5ad51db6cc5f2a61acfd9065ea1f0264b6935d30c6b69722f8fb93109737f83242524f725c05b0513ed3eb4b4d1efe3081e426d274b62e5cea37cc164e2ec46fa62cd9b2f84e64c5ff1fef4dbb5dc35a27c35a39bb87c186a89ec0c42e47350e9dbdcde049cf3db8fae93289cbb56200c847d0e791cd5908a2d06d9fafe7d7ae1cefd3d54c3ffd17ea91371b67f378591df6d1b8abcf54cceb92f7b41df59266f4f919bf2143f876bdefc34fc78e66b39c934fe00ccc7ab1ae9404713f7aba840ece240eed159fa64cedb76213e3ef5edf65e35de512f61c746d05a8005b3eb61d333c196686d26c82337fd63033f4dcde2d0c710ed6e4a625829f295749d35e3c23d8dcb0c77b35ba6dd0ffa202f5317ab97f0a1b5df0a2226fbc399aa9a0bf46b95f9dc06403f511ab176f9ce4889de3461aa702a2d19f2489798fadc4ebaef01a6d488b4986bdc74bd7fda124d2bb0963fea47a460fd0dd4a58b772768fb2dcec032ebf8ef93dbed160e9b35834efaedb0f9a6aa4d1bea58cc5ef659087b33a68d223056c0e84f9a17fd56e996c7e87889c936020c80239ab86ae9447cae6aa9688ace516325e84dead915b98a8f15b357a8cad20e72279eb005af26562b8a027535d97d1bf013b5d4af552f667586e4344d355f76380a028acd08f51fad1995c71e7882c71ac01df744fc4b702428119dcd09db906caa3d9adf02a324bb6b0b63e99d4271ec5980bfba68867065eba32ae06241323afd217811a774ada887b9b822700916e1530df53626bfe84a8ad41b7e6c3ff40eb16b2bf8fb4ceca00fee9deb35343643bc21fe71fe8fe7dc8431284cad82dba817665b6d35c2c33bde8247609b0322dcdaae8e6b1d804c7b12b6a8f841e65dfc1d9ab046073c9953a6b97ed32ec1db415ad86797207e9b93c979c02aaacba2a3bbab249dbc1800e355a1e99dafcc439d38e235ee95b5aba3035aae5aa56b7b065f8821fb2c870379378e2914580ba60a28b84c7570d036c682643d32d0c92e1550e40a54529bbc55f6b04dc468cee2f20d9b40c40e02fccdd90328eade4dee64de4a99e0ea2deb8d6294ce0d490423fa0af32ed7ed7f4a2f68b7bb2962783e30ec67ff73e334160b812e65a1a7e4d611150b690b8b08ecd14f3ccb602d73c0156f2bcf619f0fed018df011215d416b202f838da6687b74445a8371d3b4d287b98f0b00a7a2a728d0294d2d2510b06d37bdce879963b4131e0f393721a72438d7b9cf0708d016944c35a5ecfc5482ef51100e3c14f000aea92a4f2c181d4e97f0ae9924054bafbbce4f0a350cead08e36348619126a6cc2b1247a4fdf84c9acd0f281bf38133607667f9dddc10327d62d898719c2731212ff53f93200d8a936b5fc3a2820088b7cef8471e99bd00e0e006a51217d04652cf25961c31f1915968ae88aef44ce160b9313bd990f11009904e9efe1b1d48893e46b6766e1b1b4980fa0e80cd40c5fc01dad9f7b0a215c94078464f69a23e0f39a493cb62156767d79bb55aaf38488ce49358a2f518465756cd700ea3039481cf4053bbb762cbab09b2a202e9efd3ae8039c759a33b726df5363d63f760c39b856ccb70171d439393e177f400b0c9afe1110e6e263bdfdf36e0285ebd63d5d16d38afa0e527fb425b5d36d38915a9ce0aed1f6376229b3830cdc1bd5bb07e43ca5af82b4b32bd46ba79066cbb022ad6a4d17cc3d51f16eb75a25daed55f0154d4d037a4fa0aa748d95d31343bfce71318a933fd8cd6834c48ca3a9527130ac205093ffdc3e86b04562e743f0f8b2f1d24a823f8913602f1393620baf51aeb2de3134fecc46a8ecd3ee067ac4fe6e04c4f9396e5c72ccb162cd45978d04fb7344462bab4d70da2e1e6b224d94f65bfc0b2ad403c6994738c43112da60c9ee15c16012bd4c10891cc05325381d7accf3f001a4425d79afd298907af24b005ead6f994f7ebc2b57409c5e15dba2ae58537239896f31710f0ca62ee2974a20fbc82e6c42d98fa92dc318b0558a4079487d3df067ac7625289c12455a7aa97f35e4c1e8b7c5721b3edd4548b2af079e1f1b50680aa322de550203ee4087fda5159e829108080aff8cb065928e97de2c13a00aaddf75812046aec819e3a2c7f2844c723e9544c88498ce2556ca6c4f0ec279f986ec4bb05e8715ef6b43d3f4058a5a26b09f811f2ed2f6004b4b98cf3c43e4a9c1d15ab27b5841aa6cf4e8def68a36210903b91a887a8d8b78c1b8b94475cdcf46acdcbc94f7cd7dc54cceed44e5d9a3d45a62b7ee983db16baa8ad2c4b4f1711d282c7848da815874bd08082ef849ebe17763f468b166147695d162bd05287a9e33a44b8cc29222125349c05fc57a2d326e0476bbba250315e655b08f0011d0c383614d1dbac4cb7be9350550c2462c1dbdb0ba6aaf0135655203dab8aa3fa8da93171028f84266d23a5697abd5005a09f19bc07839a0745c5b42e1b0bc1f0dbaddf49e37f6febefb4440ba2bdd69f7d4c0d45ac64c4647fcb04f6e7bd85d7bde2ca00a8ac1446da25087534224514f489d71485f98b2950a894c1c6bae7362e6904c8ea286bbdc853f5b75ce244bbad7cd417063bc7ed9fc4a8c80dda188aa27c4d695a473f287ef0fa9b4efaae486abb087eff2c2e257fbaa7afb16bfd401377e8f9523563e33d1d5caac071ce0157bd661b8422a3b7dad4d9040c299d1703d5e92ff0c3baffef04c03fc2b757181baa73bd3981681d00d4a4bf350c2e35ea275ab348b53c8175f8ce769c26e0b537f64539411ea47f79338abbacd386fc2a492d8644053dfae08e3af8aa0dad7cb211ac31f578d7c6b095d5b9f2a43513ab57321f1174f2bd2154d41004b58e8027ec23d0ab0a6b8d9f371d4d62c014e412957094c70dda95dfb3fcac82819da86530c177b8c93e420f7d636b13fe417b5dc1ee4ef72a8b2db2acbb5a429127240988041cb2e7b3870cf6d390308a74f2358901df4a70cd23b6a27c8a7b4a98882700cb330d12069d6b1be75ff598c3ec1bad30307e721c6486bb41e3dab09fbd43257b7564b4c1b1900ef992403bc409c42660cc6138fcef090109a00dd4896468265c5cd7f210770064dc4302c1e219cfafe3dca232d12630284c8854870bc316b45962348b5496b122aa0d865ff31148cde174e15c27e6b962ab090c1ce7a24d3e2ff81fcee6a42c7402fc0f1b7a040245938b64c1641d8114d26671334721ffc694c8d1a120725c4f14c8bc6daa4590d91dc67440d60de6bbb2f793ab570c0c807bb332e10d7429ccc080a8592b0dc5024972e679590b885fd0e7515b40f046f81ba9e076e5ac5ccb288158f3d96c17e6c42fb0a5d13fc8dc226e2d5cd3a754c14890bc372bd4b46593b6c6c0c0519579559401a4b3e040042123e804b52ee179a0803b5ebf01270223ec0284017380aa31b56657a62c4e955a6725e5feae7b6dd8c6698561f295b3e6325b13a477508e9b6db84b25528bf5fc6fbf9b4aee1280ed9137198c28f1ec6e97b1bf9495e15a1ef0377003cfe767c99ee512a5c9396d45b522e11b3782e7a1208f0155cc4f88420858597c200f85780cea623f210442c8caf022a22d8152969ffe66adac5a40f5e5d1cd775f1a237d6aa107bc7769e859513803d59a350ed6d85e5b3a2c0cadfe82c495a972084403e5a3dbfa80878cc0eadf650c44ebfd03d2a4c0a18308a78cac874a2893b04c42d2e47c9cef9b08c1a9b6f6ea44305886062ac220415f07a287e1491962d3b11049513acd83346d67717f6418e3fbadbc32b6d58c199a19e9b2ae170a38e73514a525ea0354a726050182481f1a8c7d2b35c411c0af4fbcdc74c8bc362480136cfed73a097ae86c356bff56428ca888ea9cdc1064792e7ea78201efa60a6543c8775ba1c80e27885c5e9074030e0575e10f83c985146315f79b55873a8ba05fdba78c08ea624331fbf9d296ae24aa1ff97f5f47093dd011014233ddf5c8fe8452c141311d2817648584cde558e67198247abb3686bcc0d1195e6a95377969833f4008003b07ab7dd67b06a3d27b0c22af38f7bd5184276227a396f910fff87e8bf2511638d381dc47119111441380800ecc54b1b8b293e1c0e98302c1f76ec752b378417c2576b8c1005615c87a8469fe5ad6ccc589ccb37656c4cf3b3fe6d6416b1ed466ab6283e9a12679c57ac8fdfce0c2c80d91b3c03a9d8f67723ed8e3958096d987081999d11a8001a973efed348ed914801048096e74d119c393fa280229de1ca35e6081eb8bc8c24b5b83e09728c58cad80251b4fb3b29ec3be16d8749d4a52980f637029432c9783e74dc976256523b039f6705116b388247cfb40eb07569ef48553c83df51f37ccf9b84f540b87d28880b77156970a19a490ac9adf38165d25f488d218f14c02d77a3bc3cb2910ddbb4dce317de04a0fd8270404202ce4d2820f8058cb2a7f427b230406499fef63285e84a4167d9bcbcf41f9d418cf453377c862dc0dfb90e8305635bd366c7a5de9c41f6b69c6f0128fdaf2f9c472c38c404928d90bdfde9e4ed7b4a522af57976f1862ceec8500c78a936b374e237b9e1ebb63b3bb5ef78459ce5b01b6c7a9af6b6f8b08a0aa4cf38dc18c4db137722d03ac9846c673e91e724203baf80aa3a8088d209f63e79ad2005c9e2d207958059e26d2406ac7324d0d31f245136fb583227c051e8394f0fe4885c974b47fd2779a5f5d6532a2d3c37a890d0e2e9b5cc425e75823e006a4245cc0f45b7fd1fa2fe69b605df52657c70d5f878c4cb8e0ba98e5fb37a85b03e80673867b7d0a9d748a43dc3b8f53bad7b212a0882ed925fd1ec5d18f4b71149e7438de403d8f2ca515c8056f31b3cd249eafd99ab3d1dac343e8d02ae4bf307588a7427b9c7320582b6d065735d07ab71288d2927d7645a8e0a7f1fe64da35be3af262e46fab4d28a5b9a5eb019fd3f087eed55a8a2826f25a9cb53229a6727c45d635dd72ca3ce24436ba80e4f0e054a864b92c8ca894750f327dbbd9c4aef741d65b01afae26caa6278447d452a705f334533fa6260857f71f5d676413e9ba7ea9cea27760426cd89aa2e28cea6cbaa6a41304413565fb506ae0d84dac030a25a0d70b2c5183113ae1059d1b89ff11708a801d18e3ebc6e1e1b6e04bf958ef853b397b8582d49334749e2208d7d44e27d01b46af09424f8025f4ee50d8b9dece83a166f72fb9f32dca7bba3a3180302dd16442253290ea56f8f9fb0aad48fbb8fa96f5bb8fe51131f3372450b812bbbbb1ca60b23c8d5161573485322b267129bb24717da221a4970707780a98709fbd81d42d6962f7924d641948f2e8b3b88d18589f6262f6f567b37fabe252f571a7f1d044f4005f64b413e1a86c31682ca7a462cc0586291c7abd47cc897753787b6737a95f397b645e7ee949288044cb90e8c90b08f43a4644357f528bc0dd7f4db4204347f410138181a30f93b1a18f47b3c714e7927e760c17f1032ee0782d716f5d17ffcbf8de92431208542ed503d25d7d6d9bcbb6142f055778f33e42dc3496306b460354f2f7248c6c517f9be48f349103dd44b0282655d9f1f5cd4926129710274fe72466492a0a6e60b1d5838b0530aa183f826e7a7b4bc6374e423865f6c489f83a284de3289aafb6761421973e74eaf5ef09975b8251a1b3c3b5516a213426efa949273d5e3c75a6b7c70a4dc40e620fc97016327f9cd823b18927daf0c3306abaf8a2272ede746128967ca2a134daa7bb326b92e192d5024897728af28a682bbd8f564ce62a31a67a35bba698323045af03c47f0cc979b452d60b9396bc35da4e21673bb2bb66095b9088adff676d2b052f58fcb5c81eb01c288f213a72e4049964a0d62ca4480e16da8d8362189b03fe4722791ad08b268516d013237590b747302163369a042ab48486423099dc0b74f01b44a61dce422316b7c3fa6caf9438c0c6dcba4a26bf4a6500b4a9296eb01bac46356ae2904e79e580448715a0ae024b328d21de5ed7caaad632c897f0d75118f40d0b5f15eb0f92e65486f9b76c34529de4a72d62a748a682aa426f82d506b6248e608fcee061c6722607b5eaac444483567b351f67e1dd9023c35f961e7f6afa1dc283a9fcc1e843c9206d1dab20d59e159f1cb1d16394b1c64f227928d866eba26d109e5350ba4df88e9891e135b7393ddd0706ae72fdd6e464d5051f68e3f842eb180f65bc97fbedbfde3564194361c9329fb6982807f9cd319152075fe7639fe1a88ea0b076eaaba0e23ff33353cfa1db34a8e7600cdceb7a69a59fd2b811fe26069920242761b234f853f6005c5231e8b2e1ef262fadc6f5379102493e89a34e89839108c0b6ddf734cbb0164f0a94f9bfabb9771365b2cf8a04d9d42c3ad1b268ccad26aef2e1faaed74ac4ff508bcf66a1850237b6f0a40a40570e4c0e7cf1023a64127859405c11b5c5099e61cbdb628ca874ee3b2f9d0021804e75ab41e7188dbfa44e74e25ab48a5959d1b07185f9cef80834ceb84ae09e802629e09fa816481bfb6354a122b1703a664bf0bfb5d65a6bd64d22dd44c8a8496477f70ead07ec06f906dbdc4a27398e928693a4e3debdd3df8d8dcfe9efc6d6be7ddced86f377efd12faeb857dbf87cd32d9f77ba45f4cd25656fd7f277b54bca1e1d131d3ecb1fdda1cf2c877891a6d234d2afdff4779d4a53087bb540b74016666dd7ae6561dfae81ac57cbc2be5dfd552b6ac73492a549afa45b99a4bfb82dec9aa63fed9af57aed1d4bb32ccc834bca21eeed716fc774f6a84935e2b1c76317965bae575b155f5dafe2abead7b58ce5efc6c630d1431fefdd39d2e15c21f9e86eec21ec1f8f34d25fb5b58b421aa4bfbba736bfb577fafb9e264d3b8ca9f510f7f6ed31cb21d6d85ee9effab665ed51071d608683dcb2dcdf964972c94bd9e458fe52367699912240f292e3207989c68ea374130d270a2637963fec94f68d148192931c4789ce4ea2e1cc8e23cb34dd727d987649d997ae0eefb6be78ba5169caee21ee78cf14c9cbc49d019416072e213365208a8c35660601ae449b24aa13a670da168e54a936bc68c719ad3d03eefa3a455cb82faeb8d166dfe0886fca2021572acc942a9694a1d99fb7bf1a53616a4ced316f2055a8ea43a2c8d71b0cd9d4b6748d296171a39e3fa449c64c991a53636acc4462cad4212a0db67cf5516362aa8f3a84cc72b02c15860b134103448a4ea4d589556ba2ad93da3a6977cd29278c89222f95c9415823e42c34ca3957e00c84f3a29d6ad98aa2208410da0025ad539f4813cb4d292c9f8e877ab4a31c05595cc535541d718991d2caea50d475ea17ce6450f6ea74aeed5876b3b6d2ac14521021420da968444a315bb54c46d5d49c9632419448222931b90490036cd320cc3039a594534a2925b5a494726a5a99e89c734e59e79c524a29a59496ce59e98c998c525e4ab95d0d00479861812816086e7cac4564add5ce7f544a29ad7862c38b92452184d7e29260abad2c96076e7cd531cbd359c44e9b3f6aaa15d658b4d65a6bada65a2b8410c239af33c1ce1aa94e763dd0a8c549cc0103188ac415598491235b3e5a788899385313675866ea67ae34cc9ca2cc7090bbc589004c1d9392072000998c590560b266e20c49a9240001c8646454250094015801863a6d94a9286c9379802462e488dcb40cab7414d2b148a392c994c99895a20c000c60a0959ab6aac20457644a0f204e9822ce54d6468a20333351c81344a111ca007af418a2c74c9c89343d7af4e8310002f070e261c890210420800d2e0a600518aa802b37ca703ac9534a4a4a0a4d0c2224ce8080c632c8d394075239618a539cd184a4a4a4a470b873a1849926e0cab53f4571e27137eca200f2628ec3f76e053040bc98e3f0dd346880165a460011504b2dcb4cc7619b85ada9a9e95c96966998eb4c8a5aab8a93a2156a5985598a555ba65de862e448c7e1bb6919564181da49516b2b4a591de63a0e5b15452d1460606060acb5c25a1163792e806f6eac155d61ada0585870a5f807986c856487b98ec32151ec30d771b885490d959471c239e794b3c25a6ba59585d65a0b2d6d028c120b713f294f29910c910c11453e1a89457c910c2a509a8af8221924cb4c8d1059c4773b356ad0353030b1c60250cb34cc75eec59cd5b9379381fd3a0c893b8fd6cb6ab2885944fc01e362e4088faaaaaaeaf19b26ab0cbb880c91429a6c3a5c2443a55445c9222ccc65d9900614026de69cf1860a2271881432da48984ed779313145c4c49a1824d6442131484c4c4c8ce7b94084b9c0cdcd8dc7f30185ce408632c0951c6a98b5a6a68685852547102318186992b1a6a6a686e5038a4d8835300ab8722f6735af9630110a5b6a18f943559d878342923bfc676dcce11b67145d2d34a8c9019ce153058d1328286957b81e1a8074617fbf02cd13441bd2d014e143a303cf0c0d0c3c40a031c11a9ac8a169820a277c40d3840b689a18014d12ce70d34f4c4f50bac9cdc4901d53c023095fd81f9ce1d183092b76cd99093151b3271cb2a709e865e247ca02688c189052210c9bfe05a59452ba51869c986698c0040d7e70bf0a08da831925543c4320e2238810acf0e9818f2a3e23f0a10614aca0065e16688400028d103334424841882ee80d6964c0c30a595114655534333ea86c531445519e11cc8ce023733b235d918bb7e099e26e5208b999123c47dcedc7678aabed00dbc8600417db90660915705358a204f7074b78a0082460f1e102128adc5014a28d945e934e1b63b596c22aeca4945927d65a4a279d934e4a77bc3a95856952432b488d3336ff4f6436e5949d8a08dc01db34e64a8e9923470ea982cd8b76aa652b8aca9123478e1cd026478e1c73259e76902c5acc24362fdaa996ad28aab256edd0783a4995910cee678aa71366c1a5ffa0cdf70252b123e4e608c69a2813a3c5bc1035679ea121868881b1870eb8a2c3c6e6064489bf66c7051ae14184081554402968686a65a950c856d576acadf50135ee69d10e8659703fba5f2cc006881233cf0f2aa9f24108e185109bf37a413b2795ca4ae5e88739a7ac1565294a4a295368bda31f7eb89146dd639352421c29a594724e26200c423529a10d1aca6942789339b10f5c9109087f30d9271b4608a1561285d8e32694e26095524a2985705a55052184b06282524a6b654355293be7b47eebfca413a3b4d65a2bca96b04a2184b02329dd590c3171e32bbc1056940ed95073060390832803e53f29e5254f05c6e3caef85ac7993b5c61e30a73a45181d1005cb1616c56c1e16d9a19968034ae8a68b12bae9424929c54c01f5587f224da549c3affa8bfb0381cf3b9f0eee58590e9ff7bb75f0bddf8ffe38b03baf1d7c6febe01beae8100dbd93431d8c753a577e8932ee75bcc425c5dd1d6bed143f1e6338b760b73acbbae5d1df8eedf9963f6fbb6c2f4369ba17a4bfcfbd7327c9587fd937782fdb7ff2e7e2edeed93ddd61675d6635ba5b5a6636f025842161c8ceca1ff6ee5797b7eb2feece3b973dc7f9f336fe35b31adc8c7bef30a4274369baf76897bd7aa7e15f4f9ab4cbac06d6740bf6f84cbb781bd3d6e1dd9d0cb765fa6c70f19e8694ea866e82372cfc695dff53a20e94d0b45b79584a4a4a55dd1b0afd26d38daaba3714fa4da61b37b6a6699af64dd39428955252525252526ea488e4d68394ac410c1eda67ebca326de92a23c125a76072a22109eff89ee792354f7f2ef9e62fdf7b37ed9e6701ce73bc6d9bf7f1dc73ee16b0804b76c92ed92527912df0833cff785c72cefbde9cb305f2ee21928185bb14655934ac65b12675651ba6b87b37d6b1ec2b8ac6b667e9c172255d43114a249a7651e896bc8dfbc682e58fa5aaee0d857e93e94bd9d837ed9db669f9a3b1b56dd3344dd36e77eedabbfcd1d8f85cfe686c4dd33496ad7d636121d134fd958ac04283f411c9a8141a7d42de87d35fcac64a9aa4bfeade1d0a792a534a09cbc52ef6ab3f968d612c2c2c3458760f91246f1014457514555514455114754e07fc946a5e1645519cd501eb4a7f378850425282c384e4961c47a984eb38229494e85092494a8ec344974870542bd55751940fbbc2909444407d957b40593aa7151742e7891eca30fc0bcb2eb71db3a1fd3ac6e91a9ac6d73df9d3b8edf2f8b0b94cd27e91345d03bb0f9f0ffb9efbb4ebdb367d2fddf239a75bb26fd73bce324f140a81402010feb6813076b77befbd5708dbc58e5b5ee6ee9e7d3b962974b1e94cee7bb9b97bf850aa60fdbd6cfc6dd31fb6756c2c4d9e50487f3e7836b0b1feb443fd611c06a8ee5a7e99bbea740f71df6983e330ce32ab81e163194317d3f32167bf48cdc7b5d50a16f755ef85523b6fb15ebd63d17a5b790012040cdcdd0389fba6834a930e1d2ff485bed0205c1d2b25d7b4920c25ca0bbd974ad3c9486a39b817666de8d8f49d0a9357a61245c7b65407953240e83cd041a37fee095d7469f73e64ba0d27a46ffa7bb9cd6cdc6b36b8e36b58a66b701a4a93b61d9f34fa757af3a71d6b1be93ab6f648babe1dff66d275eef7abb6a64997ae214ddc39fde9d8f758e3d161c84b7aa11b7f1b1deb96d12fdd12fa7da1fb7ecb9fa65fe81e69284da063a1c38b3c3704f25e7ff5f7f178b6cdf3bcedd82fccbbc7b4edf798b7fd6ad837acebba5bb9db8e6118866140d8b6c76fdbddb1b52d7f3af6c61dca95d2374e7fd5def4576d6c3bf652861205cba876efbd31b371efbdf858feeec6b6e37b377da589eac0d92f5324312287946541485114f568bf5bd082d0da6b66148c973a8df80f30d1ad5fa1771f91b66fa4d02d79a15bf23cd7b84d7f18f8ee61b435b06373dff7f5ae77bd7fa17dbd6ff7e4cf0b9d3bddf4bd201ef6764d933ed7ee1d67d2e7dc7155ddebd1a48ff6ce9dbbf7ed9c973f1eb6e685f0413af44db784bcfc52b17ea93ba42f6944ba44dd682412894458842f8661b732f683cdcbdfb7779c3f1e36d634fd9978aefe4c4a4a48484a251269341289422110e8f3f1783cafeb380ee37bb74dd3b20cc3aeabd3b1b666ed0b0269cf3f1942171e6a6b271dc21b3cffeabe87f006d04324fdd9ad5df45186d085487f76df7ff20de98f8b8ffee8d6eed91e95eef8d774f587dd3b8ce965789ced3becdcbd19ffdebbbd30c3fdcefefda5f280012a8b2cb218b25fa8287a485c17fcb03db353d65f76a5e6abaa3e236198f54b4369eae8faaa3f178c5e00db7145e9841e789ed043a483fe1971c738ce08514cc8741b4ebadfedf736b3819debc1646b60c7dece5d9b26696fb9be5ddbee3df77bee5dfe36d2af534ee3539c2ff62b7f2ffb7acc20807fcf1dcb24eddbb1aed3244d676fe9ae3debaebde3ae696efb76eed7b7fcbd6cecdcb771a40fc334e99c6e21fdd22da2732ed8e67e49587f2ed8e8c3853cafe7f407fa7ceef5783cf7f817f670c798e79ec32ef63cef56f630c618e31edcfbf87b394c7f3bf6cddfcbbedda15c21d9b044b9c712051fc6c439fbcd9f0b86711cc7c5cc013b38ee1797354e7f71cbdd6fc68ef3876dfced2df7d8b77becf7d8f64ee3c3985c961b7334e02671e7f40b335c520d7c69ba1a4a53f6ed627fc1e6486a4afcc2b6aaee85d332edaaca5f0a353b94d5425d86dc75e8b46957e7349c28f63a60fd941d43ec0fde25851a317f611e485ae32bd22dd0add1479f5f0f899edde3eb661abf6d17c5a854de9ed3bbd65dbbcd6ce05f12771d4a27b90e262ff9ddb00ddbb66a63a44e93381d8152e9e230d1251a4e947bed98973fee019f77a7dbb1d3ace5e039bea649deb57bef8eefdd6636bb7e948a927f212aa48af77a187393644f9a4c5e926d58402c21dd695a4369a44a3dfda1e90f9b908dcdd6b0624c9a4c3e2f65c5579a8cd8953a11fa27196594b19e524c320e8644b9626db8d1af2b961e8a0ab0af1fc11be2eb4950a5e4f5def039842b1444a1ffbc244f68a2b754a66f41afe963de948ef28b2bb06a0b17eef8afdaf59e7b432c928754a176098b3bcadfe8f631ff44f6ff7d69b60ad054ebc962c1625163ec186a0feb850a636d2c15accd9cf11d273d3dd1933455cda4f2a8a77a32d1f424552ad7596b6dceb726269d8c31d3921293d3d33c12c5904d4fd1dc42ffc3fb44a582009aea89ae238028f5b5ce40480b17ec7a0d0454403d4503d4fa01e8a2fea3a79ceb29ff947f9af1fdf9e75bcf534ff554795498121206e28eef816eea18d83645f2cfdad053ba87b8a3fea8164a533d8f4893896e21e2256e22f4a33e801017744bc4de48155a8412912bfaf57488543179bdcef18844a9cf59c23ccb1f386de6b4d0d33c224df52f712f409aea690c1575d208ab46ca416e7bba3f0e6c7b931c73a4a916b143ff648f07d0c80d88992b2c25313850dbd29354a15e874c94ca79ef4e87785e2d1db22be92479e64853bd287f718bb4b539e9983465d7628c7a3b44aa9088e07fd521f44ab9c65c61a4a9de66d6a622e9ca439aeaafffab279b852196f56863a9b043aceaa38fe00ee52f04ca3619a07606e8676d76e57206e8feeaa9ded09e3933c76443ca0b698a99fdabb98344e270020c8466094758021273881f368c30c60a5cddae8ea954f15edd57d52fbce1da5e65adaa30d6247c0b5d74b71a4217f53bf0ed67e05b9b71973fbaad4c46f65b5ce798d5d15fe71077b48bb7b7c353df0e2c2aa0631d4303d85bddb65ea637631993a68bc4e1cfe8748e35842e766c4ecfe83467659c3febf79dfc59df7e516c66d9ad4dcb740debd82dcc5ed7c0a52f74616f551d4daa619dfa0c974fdb938b96082550d43bd43b5455955e3239e92392977870f6ee7d8e2986b37798d5f0787b46cc0286d43c4f93aec601eb743a59d699d1fdbacc0e338ec3ba46f7ebc2f81a96b5c3ec0126bf8730a44723f1dc6610f08e35493bfe754f2669cfeef97c3449d3387cf4e7b23fbf6e9e91ffc34cffe69885cc388eeb50195bd632a6758dfc3f5f7fb65d039be7da0636d6b6e73b360c0963da8c46ec4ceee9b0c935dd62f2ab5b48aefd93e171fe4c3494a6d23d92c3979094489a56892a4d545556a55555a5dd4adbaa2a87b6ceb76adbeab75bd55659af947049baa5433b5a6ee99cc21475eaa0fc791bb4afb669282dfee15a68fabb4019fe667b2e7fd73d8ca953faeb1c77b25f33c3c1623393715d3867d9f1b5ccfdaad90c4dd3b44c46770dd4e91af7da2fe8da76af81ab2f74b15dd317ba007d3b36be76ee33b40d1f93977135e99e54c373d0677834842e3c0769085d7cbee31ef419f7a0efd8386f199461fe644f5663eeec986639c89d1d77d8bdfcc5cd715a93348035f64d5fe802fb0e528dedda676c9af6a409fb8e9d5ddac5db1d4d1d5e17eff2d384cbdb15867d07ecbbb53694edb083cb09139c105db79e8d8e91b48bf340c79fe3dbcc8676ce8667cbdfc9deee76b7bbdded7a74b7dd83f2c77557c3df0efb624dfa685a5571dff7257d740d284d9d477f3becb0f1efd50ed257b784bcdf934fd32e273ba43f9793ed1d9e8479d935c2b0ebba2e8c2f8c4522d1ad2cc218638c9de8ba73f93bd9dcb5fcedb035cfb7adb443a1cfdb5b086f2f6dd2f4d19e8cbd6bf05ab6271d8731779cbf938d398c4fa4e904d6ec70a285e1d757e95069cad6c34c874afbb027cad431e50e2aa3144d78b8870eca8e7dcbb28f3c9c1dd381e42512d638f486ef71d74e33bc6ddd7dd8d8a66599a4691c242f1d9f440192974e52d29f0f3b3bf6795d86b16ee1aee996d1b3c3905ec64d50361281409f4ef62bfb743ad9f60ccb7e338fc7f34ef664b1892c661b3ef796ef65669986f527377ef72d67f9d3b1b3ecde4b79f3aa9dc189a265f97b991dc74d4b7fd8ef75d8b652267996bf0a4729cb361c255d4d949779753c2be24a4b559eb43405a91c2edeb160e29add2dd145a167a393f0b70b8f3c6f6b9ee669f857f338ea69daf5cd0502daaf2679b64cfa7cfedd8d499e0a63ef1086bc3c6fc46d5844ca46a22e94655dd7751d0804ba95414c78f2dd9af67b3f1ffd55dbe3d15fb5bdcaabbc7d6fe5799e8bf7cc08f2f4aaa475482f0bd35fece4cf65776e595696edb0b35777d9d96dfe72ec4c7f9d4ea6c7ea61c88eb56ead199d8e86d2f4b964e94d21be84651db38eddfa05af1a7ae7f30e76d1b552f75f5da6bfbc7c6ff799d9d8deddcb9fb7bd636fc5fb85f1bef75dfebcec1e66333cef6ef700ec9e477cef189f846dd9732fdf5f57cc72c8eef9e6b2f1c5ddbfdb65ee9ebcfd66ee57cc6c74d9f34b625dc601f4ee73a901daf7ddbfeef6b56634e2c69ed9c03cbacb2edee6910e5fd230e9f3f59e54b19410832f7892a8b5561caa3899613ee10222b04ea70847d440668a9c2bae30023261880fea892136c8acb516aa010b3c0032040b42a018a2082eb0f1aaadb5d65a0db06badb55a237c14c10458b8e00920e88f285ca00436050f03ae80c40984c0852c9250820862c8c1c6c0e3b232325666a603850c14d6450426625114f5841980a89c40d5586b6d1533530083a946234af0c11019bcd6072c9861c21245a400033a842744300510a78eadd65a6b251434c081a20627ef0757a560ae4130285028d4b003cbb256a0004411225042073ea4a042a811e20315152c8aaa4da834c220636baab0b959f8c2166ba870045c6ba60843c707b6d65a6bad750342553110814a82add65a6badb5b6b5d65a21331305cab02c144b10622971c2a8b8e00a9ca9b5d65a6b707cec7aafd65a2dab02a1835dab5d6badb589d75a6dadb1d65a6badd501a79b4a91d8f589278860d7ea04cd15bbd65a6badb5d65a270ee584185e30ab509493da3645511445f3435a15ad81f921d20a563545ece01104115080530513b620031a04206e0084084fd8d44b278841452f1492265a0348952a904a71738aa22a65a98ca2288aa2a01344e46c8abad95306360821e8743a4720711db144a733bd20062c50278e08d282a2e13671822a18010866e80210bc708414530648a060902be0800640d8c00b37580105821554912c8b2c7410862bd46c610c4a50199a310011451034974651a5f0441451108288cb0bdd0a8510339ba29ec82267535b0c8aa22cab0c29a028abbd4b4f817c40497c20081e8842103378c20f702ca9126368d3b9124ff4e403f107980479061a21a01544b4b86850441a6080051e4960e183285aa0068c036b6da863adb5d65a082427886dad053204246c9b852394d442c904333e54007345112250d01e38210320aeaa2b7aa2320795462aeca00a4a4029ac400a2105554c122401041431684e0010312e1a7d1051862b62d00ca5b082185705724418ae8871d920552c4182181755038511a0887155d8124a50022fc4b82aec095ea0a9418caaab89224978c4a8fa42d881416cd03082183493f088214f70b684592665a48c49caec2923553e9344c2a43571e1ae7696134f5d4e9226ee355353e6fc32914c862365a08b8bd25353bb5c335bd3707262b00f4ae14af5acca3687b6ed6632ae17ca70329cccc8bd3bc6dbc7d7990578433dcdfe44a50c8b0c07a2c88b90d8f2d9157005a661cb0b6355de11e382b0c3322332321c69929911699239d22445335b8a7e4c14290118432463e51d31aabc23468b285cf9288d90583443a9a866ae509cd3e9e4811812fe38c211684442a40a6c020968b6bc888a1b212229b694324dd89f68c896571348a085fd898a6c793aa15491446c19b31152e587901ca96224c369018350394ec18e78479a2bc8c6313b1ef7d891085b24035176bca908fbfed8316e29d85b8f1de51504284a424684190e1916639c5526e1a874754d382dc5e0753319f156de11e3aabcd74c99802de265fd679232dcbe2456f2822dad389570a08ba94b62321cd1a435673822995db379452f886468d59fe80715553a69bed264e51d31ac8cea78aa320aee2792d92299792a45322219918c549993be6e22992de3cc9534551a0a8542f044ea96139c173ef855515a6f2805015cd1515113ecea66a2d47f15566f28d5f58666fa82dd469a6ee00d1507e254958e97ea34ebb8aeeb78912a9d15593351ea85d42336bb5e0ed97576b2aca98f3d42b246eb087291a8aa1b60494949c9bf90acf586c22e935b1ef5724bfb43576fba7fd647bda947e8c9a4a4a42b2929a937b58834d563265cec56c84d09f67929619c1a35b989b6a1e206a594d2d336518a6ddb5675eacd858d48bf218109dccb5ee579553e46af0c3bb6d241ed1b1995fd75d1134661e889f2a84760769521cbc24895aaded893e5b17fa041439a6a89ced0d35c993854d2d82e36b9c9adea0d8d0648157ab10e797139bbea982815dfe0be38e8a18f0631040f0a437bd020542c3d7dd447fe476f80e9899e280f0a53aaaaaaaa375555691a0df8ab0d9cf1bc1aa147e6cac4a954c895bf9a7c662bc1191a0d9838b108ce0b692a49192424cae79fac893ce26903d2543f71e68a0e9c8973845a559bebaa369d4eb5199d24c3a874bd19bdf47a5371aa11a912cfdd7ba3ea1452a6f466ae5477d69b91a6a07ff526f48f562b70b6edf1a616912a71c3a034559ffc85b697334075eacd953340f78dbb3253555555551549a2a00107a181c2080d143034408cb4e8711d9e5cb6094ad90ac4aef50451aacc645410c0159669822d55a8153d3ec289cdc0cf86251b7e72ff9828f59a3fe6b4992b5a573f6e333d3837d88ed8a6260537bce8fc11aabf72761c86b439f68854197d45dbb0cc15ad674ebca5a89116b788d670a2d45f9262a1d46966a14e718f9965015265e4b139fba34e3367527ca5c9645a1b6b05b8327326ca1450c5f31e6580a962576ab9c03d9311694c28e6c65c1846a54acc9465ae9c1cf4d0e1ec7e925b649d674e282794734393523008ed71df913de64bf477dfe914688aa743e6f7a2447f304808d274a01457a706369a0ab9b0cb86bae757a7ea6c34357408b5a142367a4389cc6c1aa5280f758fee81a236d4469a8448958fde73ee9745290ba3317345f69828f5554547b164c6581247d6a6478cdc47aff7646a049ae243393bbe56fd8560763c554f3b9e3e60c7fe28ea2070a4e96e10ba88fa733919bd07ba3dc7c0b63ddc698d34551b9e73ba87b847faa3a78a6c2ac4a3691069aacf0e4083fbd1991d8f6beeb56191d268a2815623e510bf0e6caa298e3479367e55c9212c39cdd44473bd0a931cd22c21c8476964101ffdb1eb47039c1fa8542bdb297b1822a21100000083160000200c0a068422d16096a6699674071480106c94465e58281488235112833808c21808320619420001c618820c423765037c90fd8947b8433f93f13c16c914f061c6d59377aba9945632e809821fc9d762c3c08ae08fdbbb58184b299feccd4c525c35cb8db6e365b572c54ad22a1f1ef6eb5c4b2a2b88d84bbcb2be958c288d6ccd56e1de6f2d62324004f5093e97a9c0bb1d788f5845909a75faf864c8444c2e7d5620e154361dc499b96c532897456c6c921113633fe6ac153c6fa5069c33c16248ba7c41a10eafdf0fe8385aca7570c172b79061d1b9f76d8803dd5d474efb7002144aacdcb322f3e36f756c1239a5632c8fa1b03f6f7fa414fab6e4b92545738c6fa653c62fec35c994e805c286e566a92ee1d4b4a1d1a3faa3b97b56ce84484686e2298650a7b78d3e900b0b069385bd77843cd5105399dde70764e698eee20328a9b6c0cf1304fec897d8a7cee758d4e07e45499ab4b9e54a7e01c8da0c99c10a184bfa8e175b2f55e97bbb4fdb347528c9c7678bfd7eea48586679715ef545c12940718420cf90a3d3b52d3d374f8c9986a7689c8350488f3a736bb9e12e255e11ca2535e7d7963e196fd311545e321694d7e1df967ad2f2bc946a322a5bc6c5246d532042f6a4aca6e1ecd7c74b0330798614ed245010dd2388d846bd350806d7f502204db46e1d340502e1ab6b8c111a58410520ea3ac27c33ef4b00e2891b2bd946d3c8d2d878ff35d5b8bfa63d061324b9bf43a07848625f595facbe8bd6bef68932022f02645de15414fb19dee4116d2d42a895805301912dae3f7dd87e8d2bc0c09d513dde0dfe4e4a62a0f2c95121f53aedc828753c9987ec3417a8ed2949eb599682d97fb91a4ada83b1c1d79a23fc2edc2d95ad389cd269d3aa9ceb23eec3cfb0e8da8b4586b802a26f450c6c2060a7d21eb9d7b0af8bf4b38f759d8b1d976f58ea727666285265f2d50378086d6bf89ee9fa49de6f1acf4a12fdcdd5ccd411fa4c0a1b5c3b2987ef5d8d710562cadb639b58cd7a6a133906fbe6e87db0833aa414a04fdb1cd440519a21632ec7d47a1335256595a18858013386aa967f1beb845df74cb49b903e1b3b6753c627f7943605b94129ed2c975a0d88090319e8014a362c611cfc0ae671fc04db72954cdc0008eec11dd0cc4f18cd4d94106fd0040110accf4fbd0c7f7a2341ab6e495906e91e02883f794860b76e29a8e06cbc716e15b92fdd8c0ed05bb020c7d9b198a1b49354f05bab9081bbef44424bb23ebffcb92ca1d082773e727bdffffbc743f098cd112abe9b79dca11216f1629a773bbc3d80915b117d758542e907c4d40c69efc170d6eb8bdcd17d4460491e00b7b854578d6c9030a12323d2ec5856ed088edb80a6bdd55fd559af7d4dc9a2443d1c6f740ddda86cc55d4ba5468925783a22b09a9de57a749030b152dc74008858a14e30dd3fba6ab83b44d90a895fdb8dca549bb289b36c3107fb188d605674845a10232bb18499225c9bebd088b0ceb09b23ee247b397dac9228a5d7f22a096fb142b1a883146c92083328f7a651b8d214a8e4f3b4224a1b248490bc5c563a4be99d89a6271cf05b7a47dacfd4254680c2429c8adaab0956d21fe8907fdb6cb626461cdd2d17c23c5753f5aaf151c19bee056b22f371033dde2031685dc5ff23eaaf0fd5b9822f3aafb254ad542bbf83b6d1be3f29f42a55d1bb5b130a1049630ac8d837f4b5fb818f02c405d375f6e558990dd9700d044c8745dc89f5028d9cbf1aaf07c5484e154e849886b694f16c92c0a2e6eb0bc52c4de1db1547496b081c115dbc744400227cca950c83b65d638e245065c995b79da8f4f0d2d3e3bcb43c2b83b079441256d6d29b135e647892bb9b340faee72573521e6cc5ff35cc0f811e20aaf24b8ffd663a529ab1debc4acaf0a4669146218125ed6741f9404ba2ca6aa82f3b2f693e5133a796d6632d8d207c3e416efe038cab12b92c15e7c0a4c1c1180a4ceb2440a5a1a1dcb020aaeb422a825f9f6e5d8f84ba243b9e91e9e06d8c6fec02e07affcb117263c7b6f5f6fb5e98bb96d6ac69433502f54d1d5933e46b47a5f6a2da643a8ea24d136a06198aa5e83683903fe6b46e0629b5b387d4a5496f865b450e7a93c664836313106041c9eb0c28e9dd9d643412f1fc083c7d8a2d7eb620f167fdc95bf9ea5dadabf0a62ad3d8ff3811e7df8369276ae1f32d9f152f4a9cae402d301a7d5fab71f081eb7732132867e8d3295ce47dedaf4ca1bbb55a988114bef568497dd666090bfb156dc7fabd639c2f1002c8c055adc1e60640d4a743b1e33783de3acd9a3f207b91b78385a8ac4cc3031a98b9f73fd05103533d29684e40fee98fcfac9e0167a627618f34f2083ca8c0838429ee72fc516d11214f1d92f46e4c1ca3aa7ea8c2cdf0543b6c11dc4c07b49255df233e0a8a2e72ce4cf18f7096798c91e17b4112e3c7bec3782f5097e44255d35c45df7e1c6e9b569c12e3e177e9110cc422e09f732dc5c03d7d052c8d92ab14cf7cb4b8f62c33edf635e5aa8c91b2a9700f68828ba5be3dfe8e7e8dac08140209664a318a99aaa79cc9edc2504fe3aad41579540363cfb40ab030245b40e8e1d9756e934127202afdefe99a48d5ec95eb062c6b79f4a494c840a81ac284bb163571c582389112f0c44829ed8b5348bf68e1ce251e0c1f243b0f88f0085aaf502d91fac24a2c7e77de1841d2b3c548a22b2ea148c199401d20d57184d07b91283b063a88b973c92387793198402e8aa8721d8efa268ea09e2b100170df23916e10d0f1179077ea032308e6a14380328460231e0add915d227aa6507b745b9fbdf4016c553be1210712b35bf092433b30b2bf63b06e5487b396180b716c41426ebac639f662a7fce5943e4b133efed1c922817f0724161a4e21a2769e6c7538f2b70ec45da7cbf0fcf46ee0741bd69ab2bfc14d39ecafca5abeb0449893b2726c7c5722002860a689ef4afa27e2c303b2c844d1d5fc8fa02904738810b98670aefd3de7bcf741218e7f51dae42755ecdbdece71c9d91d724246c470f2de0bfd8dff83f8ab780b8a098e3b0d1c0ed4647742e5c9cd59058d5e860d02880ae5ceb5c63441d3d437c7449516979d4676d7cc6864c72ae92069c5d00227cb37017264fcd16de6449a11a8fa71560c0211207761aa821985bb8b40cabcf172acbf0d31a682a6eac4fde42dfbc7f594e3569cc124e7771953b5e16bb2684a7a7a4952c66b7191dd8ad055448527b3cb69bde7c3acc3cd9c5590caa03a97121a34a2215c71a430b628b31b52fc8f0e21fce90c12f0114c71dd2146614b7ff8c989525a7ca6442cffb9160504c875b24dae8ff9559807e7cecbe2e831ad7265f31c875b4652b122a96aaabfa569dece2e9ff2ad255c3431d5f57c824616b6d90ea0b4a37ed48a2d14008f80743cd1df0e1cca6e935852f9c444cd4ea56a17ade5f5bfb3f19286008c16858c80cc7dcfc1b60072f7782f243ed2c8efd0037eca0934f9ae2178255ad2003feab7e7de1455939d4226cba877cf6d41003a95ec4b4115e6367989d900bf9682a21fe6ccc70be9575bf53525ff903a0bfc7514dccf7f5440c51f1370669130b95fc0927f60828acbe51963cb504ed2c4c86bbae71020829bec29ed589c6b4a0623fa2360679f84a8f4801e0326665bd3afc5a094d49d831fa1041f3510b0254cd0406c33ec53c9b09edf804df4a2b61f061c65560689742f2273dba6da32db379741e6d0f0580494b2020acd987cd7d56af790e605417aef86d46258d5eb14655b0d2cab676a56537f54d6bfea62b7430f36037b1b002e726031ae727c1278495ca9cda701d2067710d83570cbae441d7ddcedc531080509f7c7419b01b79204511e9aa67f88a4c56d6a85e99336ded6c4a29b03827ec77b42223236455e465e6e3b36f08437894671375324bb71f43fc071123686d874531e3b29f5b945b70a498c02c84f37fd5c960ae3f6af149db2a258b6a7d80f5bb5ca2051b12f6a51124fcaf258e15c5bc777662666a8c085b170f38456195b9b8a2ac02a6eb229f67e985d79502c1112c8b58ac52a7489de1b909fb88af54c762a172ffce3bc2041b3e1baee377fd7b28be2073d2d0aa08718f649f1b07b17a2fa720b8bf74421e50aebbc7022846ae7d3ec203203f5399fb0bbbd6ba414aebcdb1964c2275536ca2a1f6a7f0e92b041af244fd8676ca1619d901069db09eb66f3764a82a51a77eb30b0ccdcc84677c9c6d3c1622b890642be6a491d59545d07f6afd78a3a524b31becc9ad472a13c73d128bb82e9c4f59926d304d6ed1586d43bbcd1267c640ed403f60a3535d49280880d88417cdac8356d8452fb80ad0f965668f25c210e7eb2dad898ac665482d1166137abfea1fb0d7c0ddfb6df425cd79ef7b86e6d87f3b5b72855d6577d40393624c745734f4e2772685ee45671decd21ae774e1033887421b8c4fa592a611abda522baf497ee1ebd0b4797c3ea66a1da6d21627e812c4c38ddafc6998fd8c63efa54bdc7f54597ad04b058042dfef22518c845f1adbf038a6a69a4785ab3c1dc07342ea331e92e91a340209d5c530e834973985146c880a702c9e67ca9deff172d663f31f28e0914873705ce7e08c28b6fcd4ebae793680d604eb66603babb4a8341b84a0f2e5525610656d62725ae172716213b5a873bd38d2ddbde04f4cdfd3a705da8b53821a78e8b4b04b2cab88144aa5fd5ea6bab02b841f174a37033d05fe43c6780e810416f631010d44f2d65696d6edab7cc32d2608e868369be1a26356b20abf8803ad91d54892b8184da32e87c211d2af3b3d8b22647e095e1515efc93a67edb5ec2a62d1ac8aaf1f3a46a796df16c9e480b8f2b33fc268711361a6b12fd615bf5da791592b4ca3bc47c8054bdefc104aebcb7b643e85ee846435bfd619948848077298e4bb6a5af9e2019b737cd556aab81b707e75b1ac45526bfb5854be327c20de4737ba3d13fd916e5154c442dd6a137b5ae505e30a52d524523fc15ab6f08f19819629c1bdd15872f47a295f8974fb1f720cba5eeb3f7f757c284ba7464381a9996214a20acbae805d267a986c7622a9a43132a674349beb1b2f527264d8681653f4c7aa907cd70201ad8b3afd17b68b66a525058a7e66367abd1afcefb0493db89ad98e62b7ce4d2b0da075573a126aebf6dbb93e0f2005fa274b688496b849b2dc980e7796bfd9c4af672152b2c29d7241d8de1573d38296e47ab5b2966bd7e6abd892b39cfd4146444989f85fa11f749968342a51fd7d83b03a5d4506defce55a507018993f92f6e43e36b12d5c7b50178b76a5f4956bec36b5b4af397b4408433cd8b7831529c6ef75ad14ff7bba7409288bed3901c29225c05c7d9216fb5184be3828944531f9afd8f3d247f7689eb14b6f24104e49871ee598bc921cae637b2cf3439a05eb63fc0b9c10ac5352086a65fc3f6febb5c6eba6c67cf74411fd58f3460ee180d6c98f0159435fb7040f401b23b700a98c5168767217d67c6a1c7b3a30265b8ee35d40c16eb55e3ed1344aea8fa30eb8e0f01aef66bafc3dd16c246e94baab885a8a5dd7710fdbe13293c181af05b8c6aacbf39eb224174f9d22571e9dff3b4ae57e8c2d58faa8415507e4943fd3bb41ed5cfb85e1ae8995a467176160161225d26dafc1cc61331ec3e797a5a01bc11b221407d9d4761bf4ddda1f3e26d40b3bea26270a032ff4e2cd86e1ab359cf91781c8216a0064747be610ffb8946de621d153883017588d5cf88cf06bd49abdee3b262bb8684482f44ac00141d59c991bda3322fe0177b02369272cc60805c4c2f2a1671f4df7554e68f4ab64fe16bef057a731d56624a067522c81f81703dd76da00369c497be56cb26a80e843c2d3f0e58c0bd38c062769b73c01cb47917ce4a0f9a54fe2efa8b8756070ca6ac19c1dfc17bbef2af7ab9b2a788497f92915ac1ddcf4bbac0ec254d21ef9226f5e6028f0538af4ca3624afb158d562813302d6708e9e71ba5447df9b6ec15c05e7502edf45612ee0976078824e14c5de474a5253a9c37fd81c4e4e8a371a1d60b518509454fc0f73e61c507c2e295f1a10c2657fb15051e00bdd7c4a329b06a68fb3ddb099d34cb6bc6e91c46cbde47e5b838251e150fb58bbc0cfeb380580cb5b965f3ef416dc033dc7453482a1fd3fadf0de0197d24a30beac24c18555e53e1e8070d7b7f2c1d419dc0050e550195310d956dd1002067515893e5c1b458217b46f4ef9f86c8918e67883f67b2491e2a8990d6673c4aae3463daf355f524e3711b48a5066c9db49a9264115ecdbbb886a7d83bb3c48232d10c6a24be4d2913caaa198d1feca7a056e9aeb277d1b959b70664a492abe39cdc6f9881028ed85ccfd54194bc25384c9e86817a54d0a454f17b8d3f5437fae819be146b2b26be1098ccbe643f22315dbccac8ee7472251f9b2bf54830ea82502417d064ce662a1104531a9ff27e2237425822e0bcfe0e28ddb7e1f0f3f9ed1eca0649daa523253b75d3374a4e636f9f18e1c24fccf47d4e11b04dd90aa5b40ff5b8ca409c729df4ddda6838910656c122e8e365dbe9cc72fa6abd6499356a6db7f28e148f67b3bf49184f8dc96da21341cb5efe501dece976c932e5b27e11855ec829bb342b45a656fd66b3081aeaa1ac1fe988765bc8c67dbc92b010b73daeb135efdfd52db61576d74018f3e880832c6d9a3fab045479ba0b00d379a2a3db461d4e0150d4a88e16376480cf244d090996acdda822a1611234c54425b2428552670b001020f2809fc25fa927292f0bc95795fb86d5c8d05fc4f1bad2e725167eb84d38ab7c0088cf7ad8e5a72b531b26ee27a7655844eb50edddb7d0bc58ab7abd3a809b6be33826a13914c4947d0fe692a8c61be5d8a51b15144f0274246abddb2edd2ea14bbbe32ee71098ba040647612d9cef97659d0de9c359e8aa93fc232af5efc4d7270a797bdc4c560dfb19a77485f153a0d062df46db1a88292cd3424a4a0f95257ea2566917aaa4d3baae0b673ef4b90a078a6467a7035d113b4669745e2d92604fb11410853d937bd0d8dab1439baa9f4d44da0508a19d48ea8020366e8cd458f6670cb6733d2c5565acbd09414c3e0a37a658b6b24c483c8502f69fe077d26f1dc48b88ed5d5273e33f1c4e0cd6b0e1ac36a07f344f222c42cdbf9e3eae647b4b7e71bf727da7cd2504abd0c6c0202814e5665e501d407939a95a2f0435e721dd7432f50709a38674bb5e319624e61d2eada984c8376cca42baa99070182d5171053dfccc8033e305f59cc1052d827de34a48200d7d40c53e23407dce6595d845c3661fa76ded90ca4c4a1934cf3cecf8283539d2e524bfe1783379ad8766655658ee35275591066bc7647a31e725f59f10a77d09624958d059271940005c3c7572106fe92672ebe034fda7f7aa99885e9ddadb358f251d9ba9453d9fd0a4e4ab1490aa8709a639e8edb67583cc3e664abd1d12992f4b22099b843fd658df75ccc8180dc8d04c9adf297e881b49defecbb0fe70c2a2ff3eb1ebe6a8bef68740f06a01b96671a7b588a79a9d7ae753492d3298ddd43f079026e967591e188922550b9a2d4f0ec5bbed936591533c6b2351579ce778846b9e806dedcc8b083abbefdc89bb5969f557dac47848c16a2d58413b0609990cea2a03d2efc633fdb44508735518a2a740fdbec8469d3644fffe935ff221e62cdba5bf76ff40c591a78915ce9a542bd732ff537ce5e81cb7e1e4eaa66196027ca311e756ad179e00f6271c2facddad2ce9880d5d97b33d978539ef9597df84c90bacad7184b12a66f00125354da5f2dc32f701401d3a41ad261d1f2b54f781c14091c67032b4409c5a5e5601854c4c560dd5f474849ee48bb8af5704226a960d6210f42bb822da1aa50f4a0f719a42182621f2983ef4135339f1fe20f81d7b22240a7f26297e17cf7eaba8214fd2e73dc21819ed0be142693a4bd52fdc481e17041da1424dad90865b5aadcf4211f80278440b27fde00c55c56516109aba3f2841f52f8d26a904f5cd987540cd8afdad2644bb1bff0a63392311bbfbe6301089088e04ef1218f389721b4561399e9440f1f6127f89fb6c8517883933318bfc7576e8ae327d182268e3b14477a1e50ce6da322d0f348191ee9a9cafcbde08666fc41284adfb8e721b0094b24d55830515bd112e7b65f23a31de994f5b180da9597e93daf941cb7c232c0877bfb7a35680d10c2f3ffbb8e8c8cbeb8310d64fe09716011d3a070458d0a3741d34e38407512350c1a0a6d5bbcdefa465bf55d612f98deca5c38a736f575f68c9396ea143745bd0ecb1b9ffcd1472b38fe58b98c7df067e7f64d6429e950a898c6514abf0899ad1a798cdd069d0e67dfe68d5a732abf388cc590abd9360089aa8f6c9df9d64c935d3a25752a59b88b5c3386f1e9a625a3d822a78ed9f265e5c2bc74b188f0996f8d0eb340e3266901da533e1fd382c5b544f06156be724b9988b8c8e08ac316054d811e1233536416bea3662990eeb9186bad20b3d5636207956ada5ea560b12ed4a682475ed671eee73a35cbdfd1ad06babd82f343c39d505d804d9750714e57060b01e0ca5c931148b7d3ddef52cd0f63da9ed3ecf61ee88ea729cb7eb3c40178d41a0fa2967a78ee1cac608e01c1e8b8df242abb67e746288821197ad33455760011a69d58b7407bc04c5849d3a0d66aa47ea5080260ab7783841c187da37b94ae331d120aef2e52022ce7298ebcf6165903a2e680143f6f596aa363a826aba6ab62b1c4e6f508d1e8f9732297f98a996fcaf092ae64fa505e0b8ff00587c2a8da38a5d0303c047ce864e359818defcecaf5349cb5cc7d70c68a763e742821e60bfa05f79e9468b88e72dcfc6807e9561792768e5007da221b827a2b2a8695c7d02a9aa6225f0bedd93b944f7d21292184b87dfc9bde3d02a284bb28cd92cfab3c4beac6840e7666480d2e1c1ee71ecb76536ea5a402eae2588209642d71a63df8519d87f9b244607594ff7dcafc4208a5347e1f926d3b20e8e59d062b1d9a9b38afda3f8b0c5dbc3c460505f2ac2c3cb7e07245afef1a32255ea48e789b32a521f8ebdc26fda3cfdb63500ee2bca2504c75d3499a02259c43c85c1e05dc21a5c8d2347c64a4f7521d0bd6a035f08583d9e62e4a69ec8630ca56f7dc4f67652e92a43ddfc7220b4ec95b913acba001314f9091cec097a951322f2aac2ba9768a78675ae6bca039a20cdb908dc4654f7e5333d15d0d1f3eb9c507ca8c7b6272c2740ffe181afc3343a8bf8193a61477de50174285571aa5fa9bb3fe941d18f10e47a33ad3711bcf33ea98f03dfe5e0c74471517e682699ccf94441404a1c4d0411ebaee0cbc65a02d4448ced9c23093bfbe8cde50552b41723df72e11e52b85445a9b40dac61462c6b062e338a8437119f00d3152e82a08c0043475056897608eeabceb98c983f2bd6850ef381951f06d15b024202ffed639de06a4ed5e6248d2193b39610a6601455a2705a950017b184129a759a52a6380181b19b1351ab7b15d400392ea0c50fd12545c010138b91a90f7f81ce6d15a79181b859ea51562b31c9ce25a6148cb4c529e26bd847ac00bfc125e03648c114527193f27a1f56280d844863cc377d1e1c34581573783c909695bf3b35a8820f64e6d721b44d1c2054411a3d93c6b9f4e7608ed0157de20cba086c2d1a3cf615e18cb5036545016dd2304f6e7c26bb3833cb8083cc9e7643bcf0f155d16eae4d5157549c1eea296d900782850fbe710a958363ad209ac4eed59425c5605438871b546d349394dfe69e2cc759fb0470c50655fa6e00bc2f6b8900f09780a8a00b0bb9524c76a92519e6f5a22c2a294f82afcb19d72e3893c1a40fe63ebeb121bbf8b161f37b1bb976d61002a526e60c460b2416ad198641ebca090107a100db594095a25854e8e2b16773bb811c4f5ad074188802d679c13c897b317049cc54711d32190e04c3cc615f89c94ce07015e5a1a86b4f670275a662c26f3528907c69b6e9895932461db5060fedd3010ca2cea2caf8079c0543fc47c252d49d899c27469dac54156361a86342e1321aec856b743500de5fff0559c2108533cf325fccd6ec664d8a9bd83a38f3c7c466c6d6de8b1f9401a439980e022f3a0e794dbfdb05d2a2836f3909e898ca6ed39cd08ab0a49d9761868774a7356e02ab00594d14305b91bdf83f3d1a19226da1b46a4d9e428cd2cfe45f1033254f48aeba10d7ae3f4655d4c9ce970a51fa063156874e5e6d0213b4dfaeb0a2e704e99e8534b5f950f3b0143d7bad1523f2b258916b27d46e4a3288f4e7dc44e7caf3da7a91d48000c4d151c836943bf6fd93ce93b8b404b51085bdd2e1affdab559b3020c660f9244217659c4f1065d15442c60b079f6d3ce4687866ba94993351a1b1ba978ed2f800e114e6e63e2668b8793177b998218a830ead987ae63b4684fe1cdf7cf66d7e1b72a9d2546c80670a6d71920098149c9ae8a9d97082cb40250f4df591c0a84aaec5f55931c1a8ce4b87eadfc515e68edf5cd8609d7a59d1281777ef214ca9555a449d0db98b3b312759ddcabb1f205f5b1f98003892d3415bd486562b76277d24893dc8d802173fcec3fff7658a7e7977a1710629c34268ec17690236bbfc80dbbc83add9483a711ec02d3c14ac3446d42ea55ae244686815735751cb9a5c577ef5364c9949e097ac2d92fc86ac60b5ba37b1fb0fd79388013e0cfdcda6cdcf38f5effa85d37f667871d874e36728fe399851c52e22dd2d378649b1955f663d0da161ad5039ea5fd344bc5d7ac113574d660190efd44b3584e41c26f36bb4070db8fbeede596f996ba735866d06190b617530d5c79e0137400e4841d7293b9261563dedbe0720f36626352f9082542556f4423674a09d7281b0e6ccba1684e9d71567dc34353f34d5fe32fe71c0705fb95d9e2c73e79adbd508444aab7c91d386259b3329e388293f46e8dae9cd17c55a2c7ac47ccf6ac12ecdd6706b5513235cd005b69cf61a2983b3e3c3d39639f229068c1993f0baf3a1b59d1c79dee954532d43efcd08992333781ac4a6e5bc52ad2b078a2b1231df4a79c90803342d57d18e9bf314afb507abff5376842690edc4aed190684c1e0f31f7d084e681eada4044007b4ad7cf29bf247c9c04c1981d9ffcd38c4cb8125286ae448f4fdb6e1f041d0ef49c5ccf2d9c55868b8e93aff4209486832624a2772629c1c44fe3e43e87802589afc700198672c011c4927338ad23e2a071fa31e99a7c2c64fba18f61510a8592eba4e02554de3fc15a3f5fcba8413ebd33e2025ae82458aa3556c87be12b517210d504fe194cf1c4c2eebd02ed7d77c0dac09886d08e993470dfd8406e392e28584e80ff849c582204f1c7a3f6fcc3105f08693bb32fff78d454fc7f52589fabbf9473259e14785f8d1b4b25ffe8c7a6a9cfdcabc126c45b80e8c59b1665463db00280aa82c2f1988a76b187b70d15bea98e52990ab010eb62736a4820a6c48aa10176968202b800a2d88e0c072d2b05f53bde30212afe459202f1537c789e620b94f1429bfbe24f0b0b503017f7ad36969cc414f48c40b4b0c8867a2a9317eab2fefd085bd97682e02d4bd5c41fad825b011237037edd0b00b41594d49d00341b4119e7fb526eaa41652950e3fc62be0055408503370b426d67d84f19fc80a28a3eccfb59b018399946185bca420abb02be58bea607c2eba5f0d86a5d41769ed1387ae640259607ca560ef02536c37b13f8fed30425881bd76660ee798fa23d068c2e81fa291dc4e64a20604a77d2ec280100367b7847434f441d1f8ab6f38c82ecfde69c889780837ba4d38017588d3bf76f1cd8be40f97d73c7cbc6ee4f507a3cbfad359a0c06cfe052792ec1058c781298fece7c20fb47d56e9abb008ce9ab670ed06190b564706571aa47f004b7b66a3036dc50fa9388deabeee68bc125a436f410f71bfc762788abb1c0e3195c3f884bf4a10b5cdf53ec9e7365fb23a4a51ec55c8ab50657da42b8f52979bd32b82486b85eed5b6c1d2e59f3d0a90783cb0a13290089efbee6e18038e08e6851ec1250d7815ccaba2937db27ee2451941042a92d6414e5821219065352a5640bd1f1fbdfe65ad08ea81bbdd0fbfc2c203b078acea13a41347413671b23ec4c3850d402411bc141f0342378928ab5e941c4001390e6c26725b904dda62095d507ed890639ee4880129c4a97cb0125c76f8a02bce6ac9de7c9958cf93126d03c41610de46616930e4aed5cdd1316d9e758c3d5c9ba878894259c64a06057171ec44b60a14257470a8e7c5ec38b03e95a8d0974fac6862731f8266b5aa117a2a49104d176256c1c5645f586943735a9ab630170beff80449970162e6f941010ee410f896009071e7f65569a2ea4fbecd2ba0458d01fdfe8cec1b29789b0feda6c9a1bedb3c6378e46718b56afb424885791415ed2577085fec5a09fbb84c7f5fbb8bc1e82c179272e245cc7dd5615c70c5056e8a131e453de11d612d3b381b445c4e480363420f91c478853b48a4213c802c0b9da20b457c706e5f4442f014935248ce2fd054820cb89739c640985140e6364a666e57727407c261bf19eb6364391d4bd2f75643d747ffd8591e9726c4fbf9bb9185264851b62b50bac7ccfa72ffbf6c092e0df8b144ea164f4d8ea661434a8f06f120515187557c0119f4a79ab11d5567fb52e4e4f819d26fa3b84ec5890a4f36dd71888c15a1577a50c98580bbe891a0c61af6bb3ba2b01421b7443f5db0be300f13f876246b8e0200d9e2e956760e73e703712f0dff28ddd5c92175ec5a2ef48b990de6a385ed02ebaeab1d617b8883268e3706231f2e598d2d61bd9664e2797733d67e253a412515c102366e09d6c223a9331ba71068e3b1655d011edf3698fffe306179867e725b2fabe78263ec417521ea71ac4d8bc65a517c3a08305dbe1f1e4026a0d6f748a2d2240d8f12d9fe9673ac02440850aad4e490293eb84a94302815caf5cf4b8bb13ecca747a432c6369078e692dcecbf2416d107d134d6885fc0ebaf569ba3b2b5f80f25fe3dabc627aa8ef46394932142436bf5bcd480243d3d2cea49938710179b119dc00199e646f5165c42aa3666ded4bda742fb11583ccbf91e1130b74efd2319306a5f7c12d77ee05556402bc53d74840e0fc739a20f721303dd11a0606289b4592a14ca1bbfcdefd2b3b6821b39830d7b53c7cb0655ffa8e21104dd3d0e7983c1a3449a6402a79702c4c3c4d9bf3110e8b0026e22d6150152e12c6edc478a39ca4aa48c6895db542131f080322dfbf25e4e1c9d96121fd7ba23932c698df6363fbc4780f08ebb33fad1183bdbcf2a8b8406924ed8a14c143e642181c15a3251df4632b6982c77f4325f0456c2b3ef52e6af9346447dd1c2eca3111600465651cf4214bfe6c299f9a5a9ec232f3a9b28881d6f536264754b3eebe63be6b334ef08560079ed2be661eabef6f7cdad54a149693b38d9111a462ee99728fe566d934d7c48c336ad67f6a5ae249762a32882cc30709bbabd95fecd4f2d8eda08f12c172bda397ce1ceeaacde6221524dc957d74ffb11a77b5a5098c3bfeb0d00537e1ae807e3f65c2dbdf2669255362a497c933d24b2173c59e77575f5b08007500331caf099428f81d31293da052a16cdea7bae839a255973cac7858f670e961cd8395c7951e171e163c5b7ab8f46ce1c9cad345cf2b8f563cad3dc3c58396189800b97f95701117cb33aaa63c5da4b653f5471e34cc5e8483b144b011a23b7214704a3511f25e24a4fb95ae7d08fcc79190f48032bb71b8d248c50ad48fa8e01aad67e9495ce8e33d74c85c4812826ad8ebf021cbe297501404e3122c77fd366241cd1a9194ec627d101236de47b6bac0e2b0c1b6d5f9c605c96d358a4d6c979006a8d4f7f3082d17518172383d2b9365e5bf6b9510856dd440187d08d683430f13a04f2578f0fc932398c95bd76c969488de17206ee0915ca865cf4fbc53706c474199282d25070da852c1417a10f6b2d8e42f82deb0d180025c60ee58095db854f347a500607902ddde4ae13e8d3e8ffaa3ad9609aeb5a1e7b81a0da496cdcae384de07827d25c03fbd5d53f122de668e3cea2d69a60be6e870a0cc661c853f1e943ace7fd58c488abf549b6d6a0a2554d250debc1f88fd0589a89d3fe22ea87fc81243466c96d25107eb0a492c49d53cf846a563e11fede4d9c762a0a91da78ee584ba280a9397355f3f77a5c897ca8eaa1e10d5d120411527fb3766f74a48c18ce188cb0cfd8e1223d7b51b4b4e918e3d75c3b621f06c9bc26912c9925ce74acaed9d38f6c27c10a2081f80a5916037058542fdd60809c227bb3c0767a3eaf620e94029260af8994bc809a1db0dcd6bb73f2c6fdd9f9a958461e172bfdd6952fc0ff9674e8e95895188ec71f9627312fcd21a7402b030a94c3c607c3452c747807eaf5977991427f4d75eeefd6fe8d480685e0fd4bc9b6cb37d9c73d2ddd1a3530625488ac66759665b9dfa3b3392e3021b66a20336a93410237764eb881ca8a570adf16841d2152a4aa88c8e306ba6921de2af040afff8b22168b2083cab958189e20bb821d2bb23c74a810a8fbd52ea34962e99b717bf8c45229a0c0e65d26a1b6d681c5099bf79e76bf3a4dd159d2e9b84787845cae0059bdbcd90a5e2dcc2358af035d7a8baea1a4d1e8c526e44980b9d6ba421a3b796f283a5c8712f6b6ee72a42d7a88584c8e342884d5b2b51126808d573178244945432d7e943d69474e4aa208f1d82dda5090aa34a8a48dde9c6e1945722aba4e947a9e9cd77d658637e50a284b781e226a9508807ca74a022819485cbe66e7522a951a4116c1f1bf7618a535103d30d1e8df0feebde3602c461dc9b89e3006231b00b3749f42a3923371e1760a0cd024d39386cb3599685048f21250ae5f0cc428c65cc72a46d59dc488da6cc816260ddc322d3bbc8233b8b6c27c313f2214d8bbf16c13944a8f9f10dfd51f3653f9604cf024fcffebeccd167337011eb9858c0d21a4c569b870a90c042014492b29740a91e8afa3b01a76a76222aeb193413a569f79815818048a24699818cf3013f502085bb13352525e74f06443acafc42ca17f95f6e43cc32340017352092e0ac2044a1f3cd8d0d88543b8968569a4532cc471388247651308fa9cb329465655e8d379852dc2aaa34143584953267d6aea0d64f888a2c0a1d2a65b629ab2c77f8de6eafd212cab0f591a3d3d53bb1ccb90915988e68ecc68a7bbd991f6e8ba56f08ea08bfbeac4372cb5a56caa831c1750ac9696dde6ca445134a4c6bc8d895133d26501721d70552a00d509ff5867d91e53d547b0225677b4721315106cb058a8ca869a38d4da0cbf293869a4183b226108ae874876cc62e2878ce387661f312220a5e0f6a5cec489fba5781ef7002cdd61748b4c4db0e6d8c191c55413d51583dceaf4554c84c5b860224601f4ccd25dcacb03710dc48db93531f4438c10066e51afb90cc2ad456830d9d763f56b3d67feb6e3e15339a830e68e333e347f1d819c9dff720783db1cfc82d5771b47176dae254d8c59a69e136c7f05222839c8bf0e9bebdfda5fc0808d5b06501fcf1d79130d2b2fd4cf71beb601e3e4d70f2419f830b23d67a7d898156b1a073473033d7f7e1c046e1fc5c914405f6c1f0813ba45710e8c2483e39d7b5857b97d630669a8305db0ad0552828c398dd0b7e9944acb4bd21b8e4f32d8c59179430f3e00188f649136f07d2eac6ee911298cc6d8432311f837a61d2ab330963b6cb34b34d228acba683d0d25cfd60328f42209d2529bf7793a277aeda892bbd50fb2660cdd3d5344096d2094895455f211f73b023399e66920412d528337843357d9f9e00ecd5a678e573602c4b021f16144c9040e227a18a6594ec600b12173cc9d8d68b933de3513155506a2c6f7bc43bdf2c3c89d616ec6da0b7c1d4b3dcb070430fd998a6e13e423f196003cbd1313c6e9969d89a86d16e58dd2c741abbc3e272846afd78b9b506ba0ee6881a5a80d0a6e9825589a182df8f99d8cec7eabc943b1e3876a3bc768ff9f683a0bac17e396225477007c5f4d742b85dd56d172c2a9756cf01e181bb12eaf25e25ed5e9c006829975938626d1df80d4f7b2b904021868ab9218dcce22088198d46d030b312d0a323c8ed4b39ca2fd7bfd48628c2e299909a8f71163076650cc8d5ecee7e65d8ce0410406a48bddea4f6ae046845ddbe364c0d9de9864f954a93b0f5beb8b558a8c9eb75f5d48201db0c3c130469be0a3b4c312d6fbd62072456a4672212b5114ed758cd7f88dbab802b67a5ac6498336b47e021dab971b7f7f31da629462f5179fe5611f1f07e97df6abe3281206d66d1ff2adf961db1dda6b00d51c2758900ad2b4356abad1c492f0bfaef8455d4012cb97af93ab06b59cdb08243389d884d52ff9b12157160fac7bebc0f3b5148911da29b97601a0c44d0206aa95c91e1d9d63e437f6644a6a9d49e3ac38b6b9356e823c38e48f9be4028c5442460692eae35bd392c52fc50a3ead1611a2c20c2052a5654eb090f8e53de741d23a320c0f6d6e8a743add5583213d69c3e81bd138c5e10ce091e0ddb21360be0f6381ac6e1a88c25975dba2c9987aca3caa13e4c8c35f3b1bd1e60ddcff3fd2c4044a8aab070a97935726ad0931a376911db5e0573fa894711e6d87f6ba4898aebfb255bd7f777053a04351836e3dded174194c2037d43acd996074174bf1380c0a454bb1d8af2155456c58cea4283357b530a3c7de7817f6b6003593b819bf209d7e0dbea5d0551a0f89a808d3fd6f71304bf9fb0773cce52108f87fb036d3d9fc980843b5892937c2d8e1583efbe72f55530bd84af02a8efed061e7062ed5520aa2cfcf94326ef6d19499d06e4c3c90f3bd49cc3cb5a241c86de51023e2c42ce80573543bf304c125282d80af57fdbab2c77b9ee9a45f79060999362556a4a194dbf9036c6f9bf0eaee765ef05bab27a3e39f2af712d7da883649550cc47629c2684f015e0e7accc4548e182c2cc6fc1a7c3c14edd6012c6f70ff8c7386b00048c9eef376e544035277c8a946ed749db6d27c8571c8df192ca90accc417fb74128bffaf970011b2f782bc51786dc99e766c739afdb2a8d6c27356c26d3454cd534724d74adbf5dfa9785d7a85e93fc994d67295ff9761a91f3231debc8a52bc2c73d4d8ee43bba0ba07e574d373211b46b63e48c84f8f318245aae4e2920e38e5a1e50eda587cf6e4848a76b917b527bc2b0e690522b9c7e93844202b212fea6234466a5d65c8fa777b26c63d4d43442cb8c9b8c3e3800d77d8071a463ec400e39424e97201635d98d80a92d3fa976344a83ce530dcdaa233c5082fcc88650e0ef0d5cdb31bd308ee4c144d409f7cd2efc48e1d8cfc6f8f1af62d7ab3de8092c31cd0ba84ee7a87826a8fe23bc6067817728fe6132c027a74380280dc9c638ad7bb342da3f455608149e1681fd8818935d4814761162eeade419c7bf4e535472bcadac5b34248e39a783b93f1c889131915bed8dea997b9825c91f28a678eddc6131808eee37d13d25e5da8a9d026769267e0e8147076de0540cd218eaa3083a299ab18a3f15814a341b1943c841a69aa0431a25c8443b9bea529695ec89a8cd43b3e1a1cfdc2f2a2ea9f845cd2b35ce8f21b051fcee03604a9d33190542f5247438fa7273852c46246bccce090b3ed9d9123898d734c2542dc7a6fdf6ed635a7ece7b9a08901568af0eee93a667516f06d0e1fa80509794006629be9fd3441038d86676553731ac9b066b9c6de9ae591baf9ac1392216cdc55663b2b6ba493fe945f65978926a1cd791633c718fc3e8d17cd392ae8b7e3ec193fed8caec5760deff158023608142d570a392581b8c9ba1164e490c1680ab01f6494fc7ac579b5a82e393865d68f2c267637b2c6513c1432455180ea88aa552b9617d6f4569255a25d6c850fe3b843caea8aa7e11c689ab5a033478ea1235c3a5932b99a9b73980e0d637459c95c6ee970e564ce14c55f796a52aa0fe49c5169dc1e2100ea66746023ddf01b14d28e86ba7b68a35952c13b8a2f7f11abc2f5daa9635c2e02fd7ce37867c9026b50580682ba2e3094ea2c34243bf1f5321fbe5d69d406598a787030d5cdded9b92a0cb695b036b1f015b27859c15ebb92703388c8c969f40024aa11caf6c23389dce45e52b69b4bca4b877135b3e128251ea1e869f6f3631d12256297aefc96cd26a53c38a66da5c2c175c6f42572e64bc6d510d3157b155e183b48a3944a57b455fab07af064275c2b765a4666e817e98b4554e4e44f1a1ae769f0a5e5fb72fe0416bb98c086b9121be075106ae9d3bd490ff4f91cc91c4ac2d7a4119c2d2a2e0f4d243a72779e956660836c000cfa87f48d22dd3384047c7f6d62e6e179fa0cdbed2d75a317e466c8df100a3b314358c0d4521e81b6699e5021cc406ac5c659668df006c3f9923ac5953e52b1253023ef7b80b4b1c6f8860ae0d9630a62a2c02f80521fd9c9a2b7ee50a75dc9af0dabb6026e187aa328d8e5ab22525c9b026509204d937a9d680c45f1a3ce28ad18681708f01efe0116b4f6578db617886f5988efc7f0eadac51e019a20348f67160c7b9c83a2010485ea1de9d18d3ca2837c40ac6d9273171ccc5a81089c68526d9f90507b267b1dc5755d995e36590ad07b57f1d57b829fe0e6d4ebed22dfb177142d8b13084442a8950d3086256c3040d346c6acee5b6d46b35479c83432f19745df1475ffe2394d73193f28f2097fdea0902d56498220c164e8500d142a5d9c2ca075ceb6bc638a76d29d14bf2119c383fc187bc40ff89ffdedb9534c87351c01c2ea544dae76a85a270d89dddc0b80643d30a920d86347f1853a1a7583b8d90d147f36d325a4057c2b43c90969caa3b17e49b09be88af6f0214c91609392c74b4e8f5274fe8f1e3c816142f9d4621d69a9e00c55c0f05fc08f3c97eec4f92981c84afa7e29e00d898dc9f17e5783e0a0ce64d289e30101a9c441a36535ff84c69d78a955fa8556cb6a068e71134973c2aa952f9aa16e8f3a8565ac530695519c4108cd2eed574feeec6fd2e20f674520c61ff3b8dc2436d0fe2763c8621b8f2575f06ac51f4480c599d7b4ffa2fe7fbfc32b34147d4781c3c178465168e9606eaeb10ca0427b2c50791c07077403e1239a0f3b039746f9c77384a0cd802ed1324fb1b587f7bba8bec47fdc0db8b41b5c403c65fb56a91abf6926814b7e03309eb650af4ca8a25c03673716a42ca2a4d6c6080831c11d3c61109a014508ec6074043422cb69f41a6dbbd35bd30bee0072482487f8e47be5c59792576e2def6a475a8d7530ef4da8b4e89ba8a1eec340eb32f000195b00ae4c01e1eba8961e05fe17403bf1224c223fe8de23261462393f202b2e7ea189c308a4cdb7c6960f3fe72c8e3f0e93049057642336171e9ed9f815e891114981b4f22fcf54e31b746a968501088aeca261ec16ee5dea80cde0486cc5a27e39315b64de4b5b866bda216898ede07020566bb2b2827aa44645f6e4d5ab387c0c33a1c453c96142c59641985562d88e2d35e8add8944e77180806a9cafedb35671c700681ac90366c155fee9c7dacd984090b17696bf97076de23c032685125d05036ea002ba31ec0e5d2a002440843390004dcb2a8367632f7555055d2edc0dba24f3c814451c24cd550688f5d64b1927047a12182da4fb6f2e0e8a0b7e288655455c410a7c1576fc1270800068adf8e5c5a7c66381e66963c0e50e56fa01dc07bb18c62c286c4705b19454208edb0e4304f889c87f48c906a53b6555a8013542ef1f6d5a039013540810060dbc8b7e9d217fdfb73bcd3f296d3eba0c3408fc876caed952b5f25e7d599936c19875c104c845033b3dbd22f544c5d28eace860586008795d90a81035ed66c671dd4ce5113595d914b9196d6ae2a3299c16c429c1fb4de0f8d2d08a50917ed3b4922face40552627813c47d1b2daf0bae1c9ccf948ac1132ad3d2c95fcc2cdc3223cc8a0d0a03e4196e5cdaca3545d50321af1e0a84d256cd699f0104a136a0036eee3f58625fdc0cf8ce03c256a7a493eb017357985aa94f00f2d1530d07451e5d5d94deaf500cc803c9b96c9dc697d17d1429dc4645353dd68d33a103ad22098817f66e47616f9cfaec83f388f61a857789dd14ba26ecb39479007afa647dcfa5fd28cf9bf6127766186b528c2bec9b79c7312d086183e82b6f9220dc2a9ebbe092e80740b9056aa937618d28fdf3f04ec0139d0f463c6b8646d73c0a9f1ee1e3dc0041a165b05fc3c5449eb7694471efaa8249e6dc87e25417f4ca58dcdfdd1f095b8e545c297e923184869c26748ab53e4f68067237ca9e787a7c3252d1a15f9dc0c773c9d5e84472c0e10ccf947ae416403c7a9b11729d7a487ea7ddc208f25914405f40a0c473841f5fab99e0f3952849cf054be2d097a01fe661ae11e34befc5100ca5c0d5288687f241f89cbd031942706bf5d7c638f1203c52bbbb21eb979488e685b8e56b15b575376ae755202f6a215e0704640c38006369ee86f201f72016a67a05c4f470c4e27679993dc7c65988340b13605ba0164e44dfd7632c25588bfa9b5b5f5fefb3ec244c9fe77cf9d59883845f389f6647422a82a6c46b1427c1b9e356724c1133091d1209f7382050d22121e4cc009ae0b4604471c5807d81410a0399a48de7f02043ec2f12a78a752e98c40f60d9a3d757edf60f32538c0d61329150c7ad78ff4ce5e5844286f27f40498038845a2eb5691bdba66be9fad7d6388bf731ef6fbd5ff7bee65b19cbfbd6f4135efc8b42dca7b6d190a985cc9ff7f8ea2b96e43e94abb84213b8cd8c740ede041b1978ea0825f3dc802514d50a0ec780d7d924aa50ce93b2606ce937cc3a02aad5122029a5e390554bab2932a53eaef6e4d2bb29d446a73ae8e86fb2146b4f36ac16bd9bda8cda191eafb0f69fcdd7ca44d896f3d3b3da131a33c0f6a17a613f8652e2fbf49f040dd388708eb0df2fb0730e64600ad787b30b88f1e067cb8c412b8a69e3fe6d77761c9998d6f313aad94462ded0056bab7f27b0d91abc6c6fa7590a1918f004e89f9982c4f0201cdc4214863fa47335c02682885bd040bf5fd3cb33e6f31650aece983a8f133aa10218aebeb1da459fe0801f9f060e3e44b9649f48d45783014bd700446b7a845e4c52a0b99c7110223c53d203e1ffd2795e88085e6e410c187013ae5037501a5a4241c9b9702b887d9da298b0cd41607e3c41b553945cfea4f5726e9ed4c4a09435ca9ae762b7cda757d829448a3c88a52d449f0cc21d01886850b5d21e0346279afee6fafa6570bcbc82e63b6bfd87c695d8a9367605cbc59b79f1bb01b6b71df3525b003c9861144773246c47c206de23f4e29e9e7032ace13dee71ca0b17d8ca1ba8505b004aaef36079dc9ac94db01c29be4813106d47a466b6fb98fda13020b09e831216d73716d3e42397f49be71e3484cbb9fe2f405915acff400980abdc84d07035ba04d0236d8ee290bfb4db65e60db2de85489d15ad4ba76e20469172b51dbd456367c32c382c7eaf3c0acdd5e0fb809d314b47a807b252d1dc5d82878526c5f9b6ffe441f9948944e4778274483ae54965dde15142af7cd7ef008095f2a10dab12033991b7a0b86b2783fae0e82a9a24f827c866e96a3f79bcc5fd752b2ff43004ac78630f1e44dd105657b891b0328b0dd6869dac7897e409d64cf115c5f4141f3dc3acdeee88a71a515ce9c637cee13af46d47ee1591530ebd244a15afb0866eaee5c59486f9611b88f8602ffc11e5e6246433caaa95c0ffacdeeb52ddefccdbcf77eb6a54c843a566ba1ca34ec4a0526b4365ff7cc06c12875a01b172ac470c110eacf199c6e5845ce566422937682e8b3a0c9c4b4062ccabb4808d7201a05a2e1acc8fb3523c3125cd5e8e85b32a065d39179f8b097a595c34dab3c1822baddc5b83c474efe0065e8893fbd34e95c868065b7fcb3e5b41f53cdc9655d511190ed720525a286345f09becab3d7894095b4252214cce11be29a7f7e17a18810275a752bb4a8dd5d883f4902a7d5fc9147d448c292c5ee0f0f318f78a3fdcf7ac099037ff8a0277a08ae078c4a7b286c04ba1fc47ca5d1750e58312c226d5cdaea2dbb69c2e357f279b73711d843c4da2d1a934f9580cdc15b6b39f6080ed4038aa135687e67513560a33327ea58594b4a4348bae73a460311f15cece232f7515624107171429aa529cca99ac9958bfec5604ed3cf0a603ae07a6e7c2482d63e77b42a5a5816ccd6ca53b50ad26a4f17a7ebf058a4ab066581b10e5118e244194619729570fb5e7cb585eac51a168ba978e86d827ddb89845da8e9b83590ebd0b0eeb9119e898e0a1272a0d84d4ea515cc6ece97905be6a99d226e6197203ac2d915c6865eef54fe9608d5e6b67aa7a561733291d0a0f84993c329a98ff5848ac583b03852aa3f71565be1cda33403c9c1011a2d76ebea21eb4be711f5e82dae1f703aafc334dc18942f3a99de833b22b2b34c389628c8adf6590ff3052a2c378aba895f50021544f9360c9640b8042348d615d4664705e7f00e29827f648e697ebba1c15011053be5f4ee352346cc5fcf5db80849914e4258e621e4241fe205d282a0302518e46d440176128f6c39104a7f4691cb98828e6eefacc704356056990118a64a87342c4b4fa71746c685d6700da712a5f34a87b7fccb97dafcc7b2d3e083064ba1a6884dfac20d7eda28508c89f199ab6288540f001f284f2940b3aa29a1fae9b91608dd566439a8b4bfd4098a2065d1bd6e3464af1a40f0c3679634823fc921491f7308877d9784818b603e188ec3a3010b20489ba4fb7576d7335625b822de4ced7933614565ea9e0ea4b4738b21b624a30e4c661aa3bf9f915a3c8b9c1c0811c2b451593880b43eb352818b250eb4ddc3a27325e5e7862ac49b3b6bc97cd9af209a12bde26f218895f4cd82d76c15517fa39b066050fd84b54b8c04a9e2c523c6624a2a35b1e1aa30961cd883fe5ff60c979c44237282e6083c4ef77e9d503846c015a07fd355c708aa4a374eb06c858190d9c5b0c9402757b7b85befca1ddd200ea9458a4e13b81134ca0617a80712ed4adb95bcaf7488ea80906cb7224476a749adcc8fe690a107431ba3a292bfee51bd52cd9f4ece27f5fff97fcbd899469935812630349033d0333489ca6850cddcd56146e415aa87e484581b5d49435cadc212f689b4021406e569f25de6777777777f7f1e8c874f4718c3a561dafcc59d350eda865958e1ac040502e608708ce122217234158ef656c23196c809e16970e26285c8daae4f314167477777777d726dddddd583aa68d3c773ed0ee19d6962cc6a46a5509b7aa4c3283991e9fae1e17477235894b4404ae9e0d1e7362fd52f2d025aa7fbeff8fd51521e2ffffffd1fa5305079110c0c05af27302ab229918224300b0b2d8e06c7276027bcbb6adb56dadb53378a58dd4f1fd8041d63083c8cccc5c0322350c893fbbbb2b209dc21c0f224811694184b303aaab1e09af644c342e747747c97a19ab0364e90628986410b70b4ab8b14b2201522b8b99192583f6ff1f4c49a49a5ffa07fff7ff1855ad2cbd5fad1f285fafa2df20b50f98924202535258c447da2a2405e5791c1676ef112ea3a20b1a4a645654a3e09190646a42ae1f587785f28ab1558b5eec202439e99abde071d0ff7fe3e1fde891fe475941e9ff3bf992d0962e68e9ee06d2f9ef0c11261abb972844cba0fc3f3168dac8f3ffffa0ce944cc9859f9999cb476923a3aaaeec8d4beb82a93bf92f17df6f2ebf9f562b2f044bd8bd0d4cbb85417a6977f7bdbde46254efedeeee6eb4752a3fb976777788a8d246565dad84d0625beab8e14abbccd0dd374c0d6354812326929680266c744a284316321ae082cfccccccccbc52e4c748465a080b8e4e06958357a33ce59bbbbbdb360b226b67a4dd4dd26a05c1b066884dd2649a1a96b64a2193ce9942d4537432410a9bfdecb6cdcc2cb455dac8165c4ec76b161b3a18520a4a1be3362764e7799ea7f5299263e76148949f0accf15d1c6a24c7a8c849ed3b68659962c4b337231dda928e9613495dc920440b8c2da2d550c5a1a2ea2c6f38b68ab44cd4263181527be944886092411c343aefa49c145605f0bcf7c91763547292f9e9a9378e68d8e0d10d09f79a3282465a0e92708874df4b76198976f8947677f30693058d83f216256bd833a6c0071c0670299e642e18ea21ac444b564ed025231c66310d4944a61a411cf6fcffffffaf848007062f48104b87476b486b2bc6a403cacccc2f2c263a19131719bc26e0536c54011c3b9bffff312fa58d9c396968bb945e69e3989dd246a61bb89032dbb3da90a94846222a7477dfb6512323ca0b144c564e1542614c03bc1e4d846496546cf1928aaeeeae65c9642933b355da2a7260c491c4d5d0081404e426a6de84904045728b63cd77fecbff10d2ffff0f676fbf1ccd76c1ceff7fd9fb1f82c8a57fa7982633f34b94d246bedc3accd894da93ff3fcb8a166bffffff519356abc5d25adbdddd6d518e62666666d304e299c2242c5256a9f5713e12740fbaefedeebe4e4c8aa45c236965d9dddd35d345438375ac5199b229aafc35f0c286881f40386ce839f140711ef168e1e0d57370fe655fdddd44a069234f2df47cbd1eec68316de4096566939a344003500a0d51644900077681053024a029014d5a6d86967210425ef07741bc6829c69f45a4f498a8890561ffffffbfe57ff6e6eeeeeeeefe80e26929a783898dcd8f4a04c1da1900606b1720e4e2088383c106403e86ba13301332772909e85861070c27a8e1111715207a0c57d07a6a39b59299997d67bf6d9724aa4a1b79a5750d24a2bccc5c43099aff3c9e90d1034734e2e7a1f210aa5012babbfb393bab430818b9a1953513c2fc0ea435bbf7af455034832821c4d18c135431844b7ab569427974c334e1b4d65a6b81f84a1bf90306894523b300393233194d25592e76feffff41faffb7c04dd1a846854f8e0c329c98feff7f6b65847090629ab5a1a8d24656fd36749562ded01811a36946efed464f73f2bbbbbb59466cfd43de9db27b7347efed69eb002aa2ab1cdd9b1b4277b72e25917a7669b72e55726bb5a042abd957111e356630071198b53a52dcfc000a259a27333b0d98ea0e240c3aa8c3854279fb213564419b0afa656666c66d9536b20597d3590d1f78d6c63081b5c18d0a164a3ab2549c40435a0e8cc92a44a451e4d904e1a83978e60d89c50ba3221a0b943095d8a0c6dd00a9211fd659a3c866cce4a118989999a97aa58ddcf9193ab2155031591bd3395f2ff367dac893678247a29a280324f0104c6265638510a33a1ce26045d0cccc1c9cda4a998f1c3cee6243b666ff7f32d8b593fe5be96b9cd0491f800cffffcae4ff95621ca5bf950924fd2cbda945005bf23089483104d7b352225af275f5526ea6ffdff2ffffb8e2ff4f2bbbbb3b08f7a01cad435117d4cd930e1d4455d8631831be33255aa3a2ddddb1b6f97f962b9fb546df6f4601cf9fcccc1c6357dac8dececfd011d34a0c1f13a4dd40aefbff0fcc0c7b40d58d0f397c66666666e60a82f85a88d2909023119725304122c47b8f449523127957a6c4848648ba38360ad4dca2596bc684624cbabb293063fcedd9c559df8b41edbeb7bbbbfb1a903a1743242f4beafcff65af9c9c6923cf9247fdad6518c9d2a46359d48c49ff3ea94aebee4e5a02a6ddcccc5c7b72bebb3b87f89f5d4b61d6e1d51d8e142d2b70816bf3558728597a10c1ed465690ffe8859ffc7777d3f84a1bf90306998586c86cd1b2bbbbbbfb3de7049a72ff7f8ffebf8622a3b567676068171484a2ca048c0caf54e96d56d13febee9e8012e2dfe8bd38eebeb7fbb004944d29962e5499314221943fd13ced9e7a4f3b4f3f484d55b5999999744c3cd38c40c33171cc4ddae88c14fe1fc9e927fd5fbb979b99d9c93a5927eb649d2eec8c297a0014e7eb12ef43edff7ff3e8559c3021656666268539c0e28caa9b605d6b9dc8b86daa7841828292910a4614258d29a964c4291dc1c1fe7b9586b9cf6aad4636835e4a1b3943b3eb5596a09d5acb102e66f040f239f66670688044d0a68996720a38159c224e15a78c53c7a9aca9adcbb551983d6d3700285071b5bc4061b5e3a91a6b70349cf2778003bcca5f4a06857a2905e599c5c3ddf73ea025466ec6d08c1ea1a90e339a019820c816dc42076566ce9918b29aea4005e545955a013bffffff7f0ba88913a7ac1f256084fcd65a2dde0fd1d41007981a5513a55e52028e50ae1c19f9e8288b7ad690a10c06ffbd4c925c4f1af0b078572d764005955c61800024374bdba22f2edad8ffff3fadbebcbcccbcd0bcec5e7a35074cd676acbb9b2641dadddd37b8d246e6cedb8d8e9682567b6fadf7d67b2d3333372ae375c1ebc662ebf684d7e793cf5823bb371edc09badbbcf1951b2b38781826f8ff0adddd6dfec2e633333333330b69145366e6aa522b33339260692389457b4362b496d98c290b004522490d8b1e5d2df5a9433b99e169a1d1ca96943c3a1a2928cf1bc9ac629eec8810eaa9da90a183a4cd4a6a24dc3be10238554b1d7a41b476d462d5995084c1b89892419897f42ffe26ca0fee86323e379fcccccccc42b25ac8564bb5b414aea5722da56b295e4be974dba82d14feff4cb5e83233b38e2123398c9caf17a9a3336de4b943a32a33f32c56394459d214a883f32ffbeaeecef1336de4994378369de8bd12eecd110425408b99696d089869e3d3d6b6b5a610955a3d449536b2eaeae6414b652986d70e3e948c565ed0be1a357370339949c260c10d43bfde15591906e6d70f5d6923793a3f7c293f7e2a3f801730f42b0238a0a04e0b51cfc7fce1a18bdddaee6e18066666e69e636923b3ac869ead169cd5e093b3f6b4ddddc223c6b49b56bba0eb63f776570df8f5e31f358b3395cacccc3d684a1bb9ebd90a7aeca8d4fe7f2517a6f4f7006c732a094f55f280d4efee6e24163ed2ee77dfd8bd95c982056ca1e5ffff1f66edacbc4f1f640e7cba7db4277383120724e7ffff3f21fdffdf8e8cfffffff7fe68041a3cb82439e65f1aa1d59ba6601536314db8a810171fba7ab462e46a6010b4600e394b00cfee6ed408446142992a23333305704426995fca32392298b62720fd101d39cc0ecc0fcc90c94202c8cc6ca34c9373ae70dee7ffffffff49eb29cacb0c0b14cdd9ddddff4e2d570c4ff45478f98c9036a43592511e18ac6bffff1e59ffffffff6f9637ab1c33f34cd6dd4da45d960db2fade5a8d4db7099425872e346492ae1f56504c414e43ea919d5a2442d923d2ee59eca54446ca2e4f623ce7abb5166d6205feffffffb31b126e5041b4c9185c4c2e46777677c3acedee9e41a8017461c0ee6e09ddb3e361594d48c47c0881871bdcf145d3469ebd996c879ebd1c4a5329ff7f3853dac821cd496ba295e56b57f6684dc69a69ce5434e6ff4b046d09a22d51b45600162ce16155d4940286111b9a7397febf07a0701d1d77258466ac967431966c804000c164ad317b8f1401f0e36972f5feffffff6d82a58d24168d2b3647bef0ffefeeeeffbfee81ee678a07494757070e4050b50810efc2f8ffbfc9718ae7bbbb5d8e4a1bc9e4236ac5a5ea6c2011fefff7de1b1b01eb000c902769c3918e4f9530828cac3faed6326a4b242daf62b5f0336de4f9b6166d618aa8cb6a7088c9ee8d55d37766e699cf3c9eff9fb4734c7fa21dd2fcff5f436935b3870f74104c5a2c46f350b9f9004e79a81180316842779b26cebc974a46752376ed0e4b6b052bcacb4a9299fe7002435044c3890ef1e5d5b1b49159f576b5d5526f58b80b1b04c0866f4893666666a5aa999403928aa8344cf807c70014231a58040004611c8af34066600314000815daacdcac401a8bc3615130180e030381501810008081c12000c3500c80d1204836491f709e65abdfdc288489dcbe7d003a896a4b760d92cd0b885298e5954d7083f682485a120483783d47c82044f95e0e11f6ab9517db7a5d786f22911a289c89044067cdce2d4334db0ffe6f5d06d177548eda6f918c6a046f2f921bc2a2543d42cb55b6c421ec3eb877b74513fc91d94724d4fe23b2bc02df7c67fec3ce250dc854646c6f589b06013b26820d727a13de591292ceb597ae8c42a92b735bcb6ed239a37c125d5e8b7c7f64750113b49399de5440f4ffd480ce20603e4e29712bc80f36702fcb965a5b30eb61225f1f3bed86740478ef85a4775b7581016eb308602e20c320219bae1edc5ff1eaa35c5b80438163bf0f6bb2430e2d554318103714bef6b3dce2298587bc9aecf109624ed4f0677db751935222498044b406d1583ad4c0b0b3ab45279d928375065229e1b88c6e8d3b4cd0d8be975792d25b10bb6fd75316a06b9805c8cec6f9b4d11d800da40614ff1e3012df4a4e81928ccb9371002cd14411c83d17e9d1b60697423608a9c3aa92ff0e76303f3aa411ee346b8d5533887a000b0389b76f428d292f7fab5337e657ac21a084f8654c4666eb9e4a6f895b50363a7fd7cf9608ecb81dfcdff5cb41a36ee136e4c43b482b208fc52507b1b8d556d5080ad0001ec3431923dc1d1e605eeb1db7cf66637d618d9660f8789e027738c414f64f6d233c572844a1ec0c5b010cea0771e40f44ae2312afc9ec028affda73c01f270fc84399ef8d9a0eebfb43ab1872c0dbb6ca0057390390f35bdcc0100c5c04eafc51b649030d539b1e31424b3361e6c08accd32804adbb60dc769f38f054efeba04fdfaa12cb8fa026d63a0c960ebe89878625de9906f4d4a4a71419aab0262f8ae92b70b01ddc62a1d25cc5f8399ace806d887c02c4469a8796ac278ae9456f8860056158224fd216866d0f2c048a6869f580a003b43c75b09c48fd73fccd0e21849b6509d09165073996efe2f6890a1d797358c7549d228eeaa04911eb5c1b20f74e7c6216ced37f8ecf2813af0069abd2411fe4c5978d1cadf695c2d39197d5279ed16616ac0096ec9f87b0160b606b004df429b4dd62d4b8dca7264cdb11ab391f026ec206e247b991114e852413a8c54827a956fb053a23b7c3c1b127527b09cdd42e02a1ee81a681ac3c9955fbc506af6f5fcc34ba2cd9f90c426e86550bad6fd2c66700c73f99166e66166fa22f3515dbea11ae62ed3d1cb601e8bb36ae4b0fd5087d3d32d8e83a9f98c42a922d5306c651a822733d86974a00fc1aa408f8dbf437f28058aaca73380bd039b80519afacb27b0dee9988ba873f298da7254da6687269c51a95ab6b43e35b1af6404a46fcb72acd758ed7d8cd93e6325d8bdb42aec9e281ee22de93eb5896a6772c0d7d11ff60c0ed68480f740a7ab2f345f2c13e95b414d703d98f647d10f4d35df96ac5ff74652dcc30715ee9ec747190ed0f5ec9941658c5d95179afb324ae86c4003813ba7c6d0230f6436640f1349d8ee0e435b51ff8d078a620296a6f9effbb85c19008ac96d93168a0ff395bb0d1df3a939921f237824a8583301c00cfaa018f7d5e1c284c1eb17cb9212b40c6c24acd8ec5746e0632198a9e71254132dc27f6858388f76c4c8603c0975c7b8e3cf0fa95131fe8ac1575b204d0c98084cfc986da314acc7f8f0f25d111fd9f782d783d0ae022a34e5ca058d29a834b8956c157ebf4c4d86a1ec4c02515807161b2f578ca6068542051fe8a1596188d3328c62557ef78e6ddc77cda202fd7b56aae17793db2d7415063a98184fd7299fd1e42d4421c6af4753e3b60c874d2cb503234228cd34db9e5c009c00ae49a2e358611082e7301b9df7feecf12f7daec17f2302eafb2958f08c30d084c09818142a948326751042ccd210e5dcfb5c595b1527e13939f2104fc2482a49f22bc629ca501d52c67ba7162a08503433ec603a032bbbbcd8ca9111bcb4d2de6d48c1c67143036fdb31d0d84fa5fcca8e82c08595d094a2acb16bbbda46c2689028dec572ac34c9f60070fc75b3e691a07c01dff2cac4499674c5b07f4c161651b4c3557d8c6c2723cf88f49b449586ec012d1224f346cfe82eda26ba6c20bc0920adede6006d020048d24c316ebc76395f7a1473e904f3936b5899ed735c01121c0b701dc4e769ad6c3f5051e0504fdf11f2b82c4812c3aa5618c0757fb2567516e38cf363bf658a6881d75df546e0e17d2be1c3d74cf6a0b9d7d68435be7665f6e4ade12e4541c32c24c8994543c00b2528f0da325dd7ae304497cf44d0b0065e625900ff39fd277334749fbbcf14359ead9bd4a2ad64824f1b7a3e93206003d22f233f0f68c395c454d380091515e3e219c2eae660de2254c7cfc3cdc68690d325889064f3d6086df728c889cf452adf2622a43847cbe169b7d4f11c50ae1b6dde0c6646a317f28dbf56602984dee72660aea99049cac28f2f061f67295624cef91ee65a244570ebf319a7ad7d26cfe9b9a410552ef552027dde3df731caa9cd7341f0d9e28b3778be05989fcacab2b3ffcb5962337d5d7d8336935965ae78db9af0d626cdf1b895c230013efa510653240e6d21b430e6618025b1ef0d0b09e8fe4ab91a979a357b29950b1ff84941d7b2190dfb88c3c6cf8a2f6fb823b05880494a9886df38c64c58135d822f3db06050998866ced55a527bada21e2ad2d088a0bc412a105b89c8d9368f3c78e3154c436e407710a70f7c2328a050ad06518be20c86d21a230ba5d5080a68360fa9b594c756814c4519b2de7aa42f79382e6e5000deccb6669cf1e4e1bf865e2dd1a181b238eabd55342ed02e2535c827d8746b0d7f19643731650008387b9b04d6a54296d13ac79459752d34e5a54c656b49ccb539bc22a0cf8055fc3de246f9fb3d1a65f6a03647237851f9cf357893fd450d1880b9c643d42a7b82b8d370a01922bc643e35e588110ba7fba29935c77ce3750f01c13c1b5c4e42885a5916f58e235d430254ad9d48df02aa214daa8dade837cba0853b826fa99934fa9791be222bb30aa71c8b5d78be5211fb085ccb3cb874778eb6a00fe60835b45fd6f12a60b3e1ab25d42419cc2c41eb15e31054dfd523547117aefc302e3fe41862ef70822f5d557207f068d643b22e9eaedb571ed58fd46cdd16cbd7693cd57da719c9104e8bdb301035e50745662eb3fb9f3bc5c334502abd12656f5f3bed4b51019718636f1d6c06a713251cae4e80da211902542cb546370b2038bf816fd2882f835ac2ae9bd205752905355be88e180bc49a9dd20f5e9e83a8147d5bec1930361bbeed50f0cd25b3981fb4e3ada36e3a4377cdc93004dc18ba2d621389a4476a956fd44508ce60c6d4aa97ca229055338e1db5ddbff6d2ed02fbb8e44f1c03e679908d78891fb22c96cecb1c3828ca43e053a934737145c2b758077043cf4c1859f8521edaafb847ee37de103f8740633a68f48c503aea1b2bc0fc24f2aa4ba1e91361bb33261ee98a4b03142ae9f6b1235e88e372c043b0a4e57e0caf3d87180ad4eb7947e0d20fa6a01a69b6b5cfea8e29f56481990dafe1b56dc4a4228ec314e54f30a6302ce15a186d1fc26abbc9ace436b5ccef42edde5fe5999a054eadaa1cb586ceb2e0168b46582228b85b0086662b461ae25bdce8f44161669f99038d924cd2cbed00889635e5c02fc18a8674409e9ad419539616bc9b411b92ebde20e22dde3a7312efc79428a00586ef0462f635a78b1beb7966479a0c6ca9b7cf8b79d3c1454e51730291aca67a9cd9357cb29c905f0e45afdf436ab7c6f11822f527a5fb7679c939a37a2155d45f30bdd5a3f563d6d06bb96693dc14f8e8930e6f680d28fc1e8ecbeed56bb1e42c9dd67c09db842b78c93cd148ec9265bd9421a2323804b42e8e3b817f4d0137e11f54a998ed9e3a4e2eaf5f0585ecebab5100a71c2489d819ff61b5a813fb03312f354435dd764f81fd055df049ed366733299010817241c37d20223723d2636d6ef86dd65699500fcd00714a7402051d353b938c462e89369e75ff714b1de606a074a06894e3e4bb141f876701a7c805d8c974294cb8450b08883d9046f5f655d57e95174713f6a20c0c9445c9b54f6b2cb72adb335b5472f72845c78bf87e73f4a3c23092856b5c8417a87549aeb794b6f85594504467f3d84fefe4eedaa0df199fad87aab0604fb2ea147a444edbf7a60070a9f2d07e0db0a129e9ecb96c287d38640dc7f32dd6afe1f8783f30636fa47792b3f32b9250aa4ce1c04c084c286498515b7e0f721a118f68ee8e0822fe58365d5ae0daa648631c5e0de0b60c55e053a0d480d4a690c2cf54aa1bede6bc97c9dd8ec40998a03ee8fd548d8cbfc5ab4c34903d29a7d9d654ca29b619290b5e4fe23f3db805341eaa4b5fdb8d39a8dcaf91248fdf7296e36ef45204742f52bd337bc107f24bacbcf8e1fa7d6055191c138fd32ac2540e9ee4f7567021e7b77cf43aa7980f9a01bf9a0ef44380b41899fb25f7b39d2ee3d4bb6fbf72028dc727a2386c38eb767a19b679de8f7e6d7b741e0bf27d4b4c692a11d28349ff0760e3ff5aca5bd335f210565a13d95d63d3ff9c7cf5032be24d83185a69030cf215e70cb700913fb01695f9e448f67b9e36a5545d760576686219be6a79467be9c70019127f842a9086b3c376ddac1c1ae720f4626a21c8faa937bb40753bc8154e406dcdb6ef58aa4b2ac975cf4644f9058853455e2103341fded1ca889da8c6d889656a1c44ca5c04ec99b2f343cd2947a178ba8a8cd736725a06fcbdf07e8d6bab1390a781390dfdf9a7fcd58997f92811ab1af2b50389f3a9fdd9b6898a5c58d3e7b59dded3ce2a6ed26736a2687feeac17b07b5bd8333c04adfb4b38fa9199658c4bd274291a4892210782cd37338099e3d15b4cff4eace78980582134b84ba4a054f59ad0cb617a0edaceb9ae90962ec403eb1cc50c5e5ff0d4a9b0f5b868a71d329e04b9da9e222c95875a28223f8efb33d708c07064de80cbe24a40f3beb2499955b6acea68f174d2ed067892f60ed132402389ddb5ea0a35683e2b9f7293a38190a65ce371d6ab8d69e9ed1fa8a0286058b1c9caaf9975b51255d85119b8e4e91d384f769a393a587a56f6868f0fe802c216c6536591544a22a232c5066cfc6854d6404a09f6a988def85dca18ec6516f490053c1c81e6ee925745f666cab0b11b3d6203e9aec699b0008498709132181e99dd8f4a85faf20503caf20823108eacd55e251d292e54d4a970d49e5fa455168eb9be00a00ed774594930dff33021c80e3b41ec0d9652d101a40d74fbf52f8ab226ed52c4f6a43245f15e96a09503afebfe293588cdadfec432892eaab7934a246d40aa3c0a095d1d387ae4dce567686364cd6cd06fd27537064f273fe6200a000a03364b240be04b2ce07d5f71a15197c1625b5615cd5ced3f4f21aada64d03a09ebec97f94771c950192d3c4906c04692454465da07528019eeade26bd689a1a7d3937b58c03c06135ccc9b883f7c08ddf8c68470a610b3a62a499eaad6067868e95433c08c3c2eb1123697f7b6a63d5a23cd8640bc3c1d82242fa81563a0d6fb8d489f0d8eef403fbe09995b782a224f853e131eb1a498184aca46e417aeb0832ee84d6e90d0885cf44f30661abb9026d14f95c933b334e0780e0d3f407463fdacc92529461a782af5cdf2cae11b05425eb9f283eed8dc2ced0991e40b196ced92885ee643305dcd3495d772a6640169323aff4dd1f4297ec2d97fc1f07d528539332886c5b0f5041b3f837c772debd0ea53fd8bf2b14166abb63f0b219372ad59cc54dfd921b29bd702c6ce50b316c362a2690427267428e988a5fbdfe4d318fcef35d90c44799c621b39dfcf888d2aec3e49a42c203ca4d831a478cf4e9782e4da5607da92c5c2901097a4c80145573180ee7f849082a2c8c3eaafc6583f50a0da3193f21e5f675fd70624d8d1ee415919ed84bc36b1e024baf800c9a94782c08d4eb3285415b2cc800513434162d8db6c7549cbbc8121dbe2e888f50d9896a471333df4c981c849b12c209784f5e078d795f8aace9e2ded0846bb5b3170c608d01d0650077134252a303b050a52c4a0d1a462682431eaef5594ad0f6a7e8f37d7efb8154cb24740b7e280487d0b7302e097b69f403b4fd17cb4371c2a404c688bda509476d8c1d12a0520b8d01e19209c6cc1caf08d258a9b97bcc4fec39c2622f7e03a34f3f457729dfd95bd6dee0c39efb99ce2c6b4ba7a0d4f30ef5756447db9d6efb5f8d8aac8ab2530de595946fba57f7202bb8352ba795ec260bc619714a53e9bfa0c7010643be03c5f5d7a569183522ca52ca1e323fb49f9ea7c8fffd286077a47424462382c422290bd7d27ce03cc389d527bc86aeb670af3a63c958225eb1165525f5465ee00d4c8ca68b747309b4ea0b977a29aa216a52287b917440163e7dbcb6c71073f11c53d90f30a00c83a64c5cb7c2454d283b9848823afd8b7aa8c35db1c871771d4c3cb7257f91a93798a494dd80ea333f676a5be1f44e38ba7c8a59fdc4eb99ac8c0e5c5ba1a8ae3c76edc640abea8928d7023788aa3a28db7f592cc4490a006c273347fe13ceea6faf10120c89825be7e23600f078d87760b4c051625324824954003413290283fc1c10f8505562db0d3adebf575c3ad8fbb8a15e2e614cdcab5de03462c3b77ef8299cc9d7f018b281b6b01d979a342326893045596b4253c70e7026e9cd8a0d0c6c354cc0903f2ee7ce0c653a38fcd9536752e32778618494ff9a89e5eba7cf1606fa68ac6d00bd691bbf5cd1c7fe9d63d326f1eaa0c5aef60ba51b0a1ea11627d46fbaf67c2f536e9f2a95aa90616e6ea453f704bd3350cb58baedc4e8524df28c24484af65a8525f753e3d268fefbf0dc30c0a989babfd346345e2360d5a40e1ec4063d6fe59459c48cf5f693ca0a219881e6cf9d82220619a2a70565ba0bdbcf36784bf3007eaedcca8004c1426501f332f8e500b8498d1829d28b31fbb500e3298149ba7d189129943399253d4d73c16989f97be05d3954789bd824b3095932d0d372d13b80c7bae077963ae3f410f04a26c200c7c2828b53d3b949e8e012b1f5c02f062aca83c02f39054005cf419901fca667a738320d8de5b40df0b256a94cafa4c8e70742c7691897403e8ee14ebeaf0d6e8ae3d85227c5f83bfeccf3bda76a08462351c9387acb726d352808ac65b13d8adc8ca2c8e122d20a893227e30570911a98c4e454fe6133faa5c2c631ce7e4bc64177b99721c445f972eaaf31a6594b1c22474cd8a5da649604b149352961396106f9c5ccc5a7d48c54698171030726909af58eb2078f42713143e3e212e80132e95810f54cb82f458ce61ef09fd7b2130a8978dac6ad62ca021d6723799d4154aab7105c3fbcc6977ab3d60e11910285be865dc4da8a52232aa5012b42b032f460fe35183d17ca6236521af3365229f1c0b1e8193841cfe2402848599163782352bcbc82da809b3d9dcbb8073c400c104d69c3500d9997ef8e0d6197a343b5b50851ab67bd0a644dd413698eb8624aa82a41445929488f0d59132dafa0d2d6d737fdfd48bcea934892e770f781087a8f6e521fa320093a429220801fc5559885bc0644cdd1ccda66c377ca3b054e2236d021ac6d32c06bf08b067ff89b8d880fbce7430137a3cfcb5074e7b537e0789c4203282b5b91246d6c6d8195ba8bcef25cafdab54c432bf7b1c4c62bab1403267797662d98a86f6d7f765c902a498dae8e3582391f9990130549ca4c800259d38b78214a5d1996d21a61b8b5ef45887b43ed39064dcf04944b1974aa356aea28403afee8affa5dc66966d8388c153ee972c9cd6a1e9b0b0f167d02e1ee48c445cdacd50148b38a6226a52493d30d77279aca904628396b70e04a5e0c8d8dcf30bea32e49f8926fc183c6b47d2d2c23188f1eb094df3f4ea38a63da04d8afdc6415a34647084d3676e13c06c9b863467d913d1245315ab326dad6a0efe2432bc44da5366faf10dd1f2deb025227b4a9aba3b88b7a2f4b99b9272e11ab312fdaa16025e1f5419d1f9adf9d0c18362a9e38531d2e83aff4bf9d3a29d5575e14cfe1fe07cae722606ef543bfab562648e52b6f3c577380f3627500ac9ee36568994513cf2ec37c6283964928be9a94ba1e08666d710fd374f66e8202864f42493bff8962978b44bda146b83fd9351447b69f311345dec285ceed5f37f1af1ea4956781a39992c151a02ad8924da32b8cb46390cbd0230801bface01583507f2c59a5ddb801a267187e62809ed387a0af9b193830c5283422c0209287ed46e2dacb6d13fd30f9720a5126c37c316a58bef9d0ddd9c04257d0d369f2180de9c81eb14814406dce6d660b1b413be90f1c11a90e88f54a2832a5b108850cf14bf8aaf24bd38fbe852692e50d26274f6d445d8a4e194e724d087100fe104ff02aa0886c88a200e89ed80966bc0f2183d6f36584a059ab714a76b723180d603df27569bed2fd90de7af205ad9dcdcbb9e7cc688329fc60163fe9b78b4a61a680d7b2a992072c0b28655fd8681ff6692ea8d5ab8009faec32da426160bb3952616ca181cc1d810b5693ff70a33a2d876faad90a06c93239e2cdfac39a18772e8d91a9daa8f884671da474a7fffe999ab6e00c5c1af7e3bb9d998574c5d623856e77babc47bdfad6013e9d28fc0ec91b07a6b65f6c4f76145060f36de70c0d7775a4211c3a4b59b94e8a6a13d0111d508e84b8d3dc0ca43fdc626cee847162e45df392dfc107b2d1cb1e3016b92c1422dd32726e4fea3866c224102e9a4a161a871350f14c9898a4656b457dbc3f2a39958510f00dacd144d2e918d9aa6adfe12bdc928c2568c6b0029aa92014b9a2637bc56a7a8fb33485181459d3c3ec21a599da9e5efd365113bae657e5ba4778aefa2afe9e3b301e6b3c8fd5013a632bfb6f13083d73afe9ca221ae0f8aecf7db464055352b4b21c8486af322956c047e87a5b3b11b23157e830c6554634d8501a4e2357adbfb0180cd9ffd49ffe5eedd9e8d743b4ac7c13bf0fdde51e0970e0265884529065a005010eea4271224d9dc319e6b84bf388addcff9a04d00c20298304e564cd14f28e2495920673d42583ecb13b1c388883166093023b3bb99eee48f62c8c92a8653d3726e062db453fad503d3733fea2f8b84301445923152afb5f242417fc24b9cb736c875bb9081d3a9d8d769a776ea4ef1a8a988dc327d673894ca836ca9e9661e04987b1bc8f626ba11a35bbcadcf357e1ca10240aa263740083e73126d16c249f52833cd631d7ada8e3a774367694c74c02406a8a075469dd76d5e72b5a0929f19ff7ec61fd851097221ca565d151fcf3bd47fe34c852890a88feb37835a84bb83d604301b4008970c523484193bfa7fc7c05af756698f25d8e6e1ce58c30609950bfca0809202b9a504389dd25b01fa964c467a7a45d2884258e33e394c0f4f141e35d61072e5751b4c51f271660a4ddbdc053204150a75c2f38d09d9aa25682a3b92284c11aadddc80af77c819c190f2be0cc72279f0c3fd12d5866a917c993348528d3e484400719f6b4c456d09ff8a2518e0c11250ae7b74831002b7f48d161ec8024f0eceed0e7013e15387d5eb67fcebf68523626996bb67964bf94d6a6b365bb8d07f3c4b8889291696523710b5e9467f4d936452cb3060b4626b0e5360a84055c6d7c12b74e27f31ea4174dc3a685720d0bd0d6b3df27c323cf5f407936e19a331393c808b45d9f05282e61a268cf49a8909619062980b2f431f383e511a78a4328e493443a4e1d0145715a00552a262374069b5c01a99ece20e05b05536965794a27d665e427512ad98d44dd731af796c22769e622bc44f580619b38ac090826a6521de339e5c5441594e0e7849b68b49429dff7d2f8c995da544cdce15fee56ddef83068c4cce1c7f2bbdba3b132748c5dc728fb88367ba3c48da3323c1e526cc627e9adebb0fff2e47670467119281b56ebf5fc6b369dc4c99d582e68f2c6611e3dc814c4c3f04b4aee03e48b5724955380652445e997a056414442cb2ca4ae14502daf36cb61acfe1d47597ce5b11227818cd2a11bd293e7f7b12dbda506e7c05f27102240522119c527967df8af65e4103647cf9704935f1b920ffa034ae91bf1b9f26a26dea3178809c382a5b2b532d34894eee37ceecef332116fc1062da5a555fa431031820a30926781406559a12ecffedcc2caa35525308ccb94cd11560c29fb1f72b3c00ba9943949a9725514bd360567162c60010ff061a5cf9d8e9a251840405364e0de6498dc30f6e85d000cc2ae10de02fb4309caa78379dc481a76392eefdb977c408c83be076c2feebc243d3549d3e105220c37422971c6223e93b062d8ccdafc390e01bf87426f3df26fc885b01a56806dfdfc76a57dbe818c2bd337c706fb7229b11d78b6b1e6d51f873d00468a2cf328d25454dc1855033b84d49cad59cfaee83fd507d97754f5e406406fae5483c509aead95632fca230ba8e8fc65884cbbaa3b226760372c782844c6454fbcf9b31fb04c214ca96581d89361249a1836faffebf0fb092609c0a0918c1d8ec7f5f264cfc692e3d38601a661c9d2c15ff49960c693b1f79eeeab2c5e49e721eb31fe6d1b3ee5323cd4a961e8be2f13d07b8fa6b62861bc36045cd405061999359516cdee1f37e008886f91d003dd6564342408b89203d3067d513feaccac14f808787f81b920f430274dd84f9c8c8f617d3d72891bb2ebd2b4b4785a4fa918484ba6508bcba7b14925304b8a41785556c03b0dcbbf73e083935ccc9cbe67f7553e467103233731d0ce04e15af7437c4993e6471835773ff3739135808245c761ee00bce0210b121158385c48e660811aaeb5298de41cbdf83273772e11950424649cac99821ec1db144aa8b7855a570bb7c66514f8f47689d66ae45780bf891975831a8a9b927ddec31e59ba5781ff95ce3f5a751a7fb458b0f5867c64b88f5a5ef5643eec473dc12c42c52f361c413ed610c6186280110ab756092de551697b94222c95ca4d7c8d7026a8a694f724c6352d57142276dc845cdd091aea4cf74d01b4719a2ab249f4060f9b131448feac08d5de3d08f776838580d9b72245f33e0186d011381184b50fd4f8ba3d41db5a99361d22da5d47d790c480bf0af0cd6d9f4bf22039a619764012128dae543916fcb5573b60300dd4ec59d1d25b96dfab0b01140af3a2debe98afebf82bb56c739f5d4ac51845946d578ee28276cd6848831cbf2ef30b1ae14149697f318366a1cf65b08fe51558b71308623cd531fc3c855c71fa04a5cfd01eeea4dfc0ee9526e5a916e238d2107ceabcd8b6a6e435a0a37adac802caae2a76b40545cb135e7e039ca92ef0c874a8c505b25e2d1cd8c132433a27e810f002d9424036318fde1177345cb643290b157eb948bb93e21e8970475551cb9c6f5afcd2a892472bc5a2e2b0d544a011ad0ec295580d4d9340631841485da51184ed31f8c63938c71702ed1bd31219a1bbb9e077e4185fdfbb6c37ad2836524bc0aa5da2ee7749fc330dde7304cf7062fcca999e2864a66e12d1a5fbf3723a9096db2e54e29ed6dbb0396026d028c021fffffff7f1d2730f6e93c8d3aba974e950b4cd2c82aa10c72d3ce9a504985d5b381949e240d7c397e84c8e2240992a2a12a5359685ee664ddccd051c21225840d71875bd5a6a26021f4d0592285051e4f9e50a10243a9006d6062022227454d7e1891e38938f5b384266328468691cb2f66ca4d68db4d3d32fb0810b310889d49816ddb4d7ac0d807244444fba049cd533d288e735b9e52860951931facb2c989b06412cf8e560b466c5b1a3d30f6e9d08c3a362f9d1c1798f6ffdf1291d584076d6b6c3b061018fb64624cdbe317b302afe34f923fa963e5129cfd7feb4459f34a42f4892d72ce92a3d05ddbb66dd7e811773ed850c2ffffffffe912866d4b439a34a549bbb91466c2c78e0d1cf8ff73468dc921bd6e3b49923f0895ac27061035f53b02c0a31a3a5e3e164ab5f1c8482b213042f4e20408848791161708b4eddfb66ddbba6d2faec212d964ffe7f49c22404de59480e40710241e5c4af6d1c68db16d574cd5562d492aadbe5a0c1a1bf6cf39e7cc1318fb74552d667a34362d5ce43805397dbc94e2083543cc906263679343e3c1459dec3ee69c87b5ed5f761c7188706838351c269c262525c6711c479678438624faffffbfb28d9fa8c09c3722bb18c57aa9c288d6fa003f663f7a202862a347287324c7840792840072947f0980cc10de2c91a39f21b270e65649b224c922b0155a1d2b243017c6beb10487829831be00c09c38724e1b1049b4e612ae254b2a4e82570357ab8b20a440149698737a8e73ce71ce39a17060eccbedbc028a37537333a3cd552d567203700a9027aa1f7ade5b002a79614766db5631e566ce20981c6152828548d40b0f2c46c92c4edd30b6ad0e48d6be2ddbf2762f95c17273e201fc24f9ff2eb02b03d1e0036ca662d6956d9b75a52d8e7a6cdb0540cd3567026d4b46093b087a318494941f5148c42296e60fb0396d4200e048f1301d2d8aff9f45098c7d37a70fb23cf5ff4f84841fd95f1fb5bf094511a10b49ce5ce07092d1a38690290f6e45f69ad0c4e5c598140453dbb66d68db56cad9a5efcfd8a53873b59db375d9b66d5f08dc99f560feffc64d18fbc69224ffcf169ad30b85260ac6db6e5b1572c0d8c7f31334b442052353f089adc9bfbc0a82ff4f0357191ab9974d0092fc92ff3f49b3ba6bdbb66d1e3710594a810610db8d86a0206d5bbb846168a4078c7d4093851121975f99816166407f6830e118db76b62dacf589ac398fa2c257892116606e0208e0bb917d4932985ea0f810351b02440a3e62d58ed1ced18b6bdbb66ddb361d3f32fbd53253b6e6dbd9b69d9524c953825f924d524e10193ca072f038923144b5c464498a00a00e022693df054b8a8ea87c312f10d93091a7dcf1d5d8776ddbb65d043525c8920e9e928e1f47dbe681098c7d4db8dc6e050fbc99153dd4fcffffffc581e19cad6823432b8c187de22c0093a4d8f232e73fc20e524940d924e98031850825f28739ff396790b7c8f8e474909d849124e8dab66ddbb60a5d8d4776b710b27319d09c6daf1ac2d4a2185ee181b16fa6e6c6306d5bb17479069136a7e738e71ce79c73071218fb946e4e4fbaaa163b7aae972433a5eddeb66ddb86d30d779075690ad61a0204aa8832bb2bfc6ddbff415c4e0bb0d7b6a19cc0d8f7a4ab2a0ba81e8d4d59e472da55fbff770501ee08914a0420a984f3818e6effdfca1018fb8c909462acdc7888fc93a4ad851bb0634223714fcaff490f6469a58a6c312427b6adce4d18fb461424e9030819e268a38d04655cf4d8f6417f4948933435d57f8984e506140c5ab2d8fcc020730cc53143d494702ca0d6238622fa54ebe803d46fdbae2b0aee51a0fedf36dc3361db1d59f189c234b482c9a835d9b665b90279807ee62cd2b6513d1d8dce4697334e2d85ffff181cd4f258d0a4c3911d8b470d3b39beb7486004871828b88004d14ebcd25486668d33c5f87e7e45b32b0b1ade4ccdcdac2c4ae849f189759235890a1631c499e1f4d85a4a04204ba404a64ffc5190e411e3092113263e21d99764741322616fdbb66ddb0e591a92b5b8d992e45b6301a8c50148c5c7050770b88461dbfeece60f6fe29871695798734e202730f63de9aa2c03d4a3b1b18c0c3976052e706c2df44861851d11091968a20c48aea404be21478848cd2ce158e2730496a9b1425673aee69c9f493ab7deffffffff6f636224fbffff24f9ff2f243957bdffffffffbf6bcef29f588a73d66ddbb6edac6dbbeaf8975580aa085521aa42ab52abc254a5e9297a0ea0904041d93949da89bca432c9ffbd44b14c0500012ac12157762fd8cab68d2234f9dfa6315334d155ba34a265dcf8e3c8db03edffd7f8a9115463a886510d243fd0b635f8dbb6ffdf8596234263931cac2449dcad24c9974140de8d141668e0733ef54acc990312308a9454b1e5808411bacfa09a2dbb030e005b76b2af3634d3b2234d921f5b80b022ebd8b62407bba3a3aa14ff9c73063102631f92d2cde94945105db884841e306631a5c975d7d3b66ddf82c0d8771b1a6f46af1b920b0c0a17d088670707a10d1a3c25429b9ccdce86076346941a3f731d7770c145923b14ad4892e429592e1484258a7ec0d8175434f472c1b56d7b6ac0d87733eb69d10314a20043d5046ddb9b323734afb60da35cdbb62390d9b6ed1f44a11db0d3784a5653dbe63081b1af49260737e545440a2706309f06e0ece9e54928d5538eba26b049ed77fd7f05e0cd06113197305ce52881b1ef96e3f472e98b1a576024a9638922ef544d5438aa1cd58e8ae730c9a766851a62186ba821063bac6d674c61ec1b89c81d2900c8ef1387f82a660388d2ce4e91214f5c1c29e2c50b0b14167233cca023a486ce0c098024e980e9e398c8b5feffff8fe281366c1a02639f1192524cd3ad08eb33744d615b2f10fcffa25a551431fd3f19b2441d9d4e9548bab66ddbf68d9ecc86ddb56ddb360f986bdbb66dcb2cd99f6ddf76db429901635fcdcdac870514a011f6ff6f756809a2c93e0338543aa89c14f5f0f1216699c124b34892f3258d1c38e4b86b3d1b8dcdc69613da760e3d7e89184f317431aa462bbb296385375333658ab89973bc1dd278a0b5ed5c0f8c7d34363953460acf9ca193093ec80cc6b8c03445d1b673c0d8c7f313340fe0c1860913f480038ff84373b5c2dacc58b75528f46aa9296144d1b6734e60ec7bd24d15b92a98cf39e7931118fb90946e4e4f2c9e74ac5795587efd3f0ca4c2502a8c5b3b47f12c92d4fd460c20e384937295361a84cab67db5bce815d95e30a248149a247cfaff2772834ef63724c91209a7f0849a9394c8bb3dc40e0a47acab6d8be0c2d8373ae151966ecd29ce29cec9530265006507054932f158e42f86a1d015182ae47a3de078580ef244d615db16a23485dce6b4cb2892acd3d36d056bdb95eb04714e1d47acc4d7ac019525962d2db64d14c6beb1fc77843cdb9e210c1e90a4a4989d9e9f737ece399ff4c0d8476393c3f3b34288207be5c36584f682b5489224e727ceb99a73ce79d891b64dea05c95a23498cd0e9b09225484feceda4927654ad1639864428c510711b894e90a493b29544fc7c6a7c6e5eff719420c9c35e947cdc1091a3324866368c659122a8b4cddea6a6000c00131a680400034118c9e238b70e0614000613ca94e4b83c301a8983c2703824048542813020000003434100100c0e83404090259b261f85118b88c4dc9b1a38f506443975d953c75687b874e860078b11c0d4c3e627e8bf1e101b2d236374e9fde983dafe2199fe8a352b09ca34fcbd5d9d96abd4b6bda5d8c178d9e19d900d408f01e7a67edc7dadc12145933f8507ff8a2bc4a4b9b52bda2a800a5d52d2716c8b27ecf9e5d010e22ac031991d8d11a56e6554ff0dad9f400145ae9302b7bc45651dc2722cdbd4904031e2b179e3709ab9bea2d144555b2567920088aec13c1b885e29529704b049e3c3e07e89e12c9990448e017f2fb24d0a82a1efd0c45731ef4d50d0e9a665ac83f7d03a0be9ccc4c561a9012786b10742d046d5df4f456261054ce709f9169badc6678266beb3018e513fc5837ca856ed51f64f7607c3edd1c989a76dfddbc145d381685d5ed13767623ea711c191391d14e6c945a7627e0a366d0b425289b9027c11e05605b8effe8a147e15b9f11771e8d093c8dd19eeab05c05db5825876d53b10eb8ead725c82953ae7737224d9e1b8a6757ed2f9aa93d053bf92b721489e5676f9ee3ccaae5d761d4074c3a8b584d41932919bd0c15f980104bddb026ade1474c4ca89274282a1edb98308aec3c34b41b30e587f080965d029fd1f26dd1822197d621a2ac331e1c682a16786a3d580e268f62921dc5a5fd1d154ddb4547ee631b5d8d0b3809e85c5255a80f521136ccc33490d2981b9f3662da62e9aeecac08516e0202c366a1666dd56fb995a24b397458209085220df7e5d766e67ef27775a0ee229be9f07496006a147e740ff1bd0eb1a65e5fd7753a45a996922f2215ed7d7f0fdbd07e250b493cca41b8e77fb3eec263b4f95d4eddd90e52acef76c9e3e983e6d2d3ed7f7131ddadf04f49830d52b3f9c9aae21b258ca0dd44bc5d44905d482bbe183b3a5c5d8ada047eae23df0504c5604ad6a674fbf1d714a102da93a1946b22d86b0dbdcbfec987dfa3f0bdd041a938e5a104cba23c79541d48e583665876d4fe511fbca508cd729ec59abffe15c1d4e56564af3afcc5462f9689b625df524c11ca56313f994bdd9f1a02f7ec7641f2a801bd3b424cfe9c4e4780f1079ecf917e8c59ee81769ee4b5211ecfd0e5083de72e78e9527232398c64fba64b021a9095f0903a459dc7fb2a788dd73523d710c134f1405768bc606a2b4124dcb08c59d9490296fc4cce892eb6f483e402345f37712801abee46b75bc837453b939a2e2b8fabc210d0274bac1890629938473ba01a74560d9316e1e5bf79a320db6927168704edf0fa651e433f98951998c333553129a6081c51bae6a8c30ca035c3929197186ae3a0bf81bb68712faa886ec5e221f4acbd71cc0acad5beb436fcd79a5eaf1afb0565c74d15103890bcf1280dc20e885690046abc0965f417d41518347ff31ee8490b785fc410e14441a875ba2aa65d4c4f51cc3a960ae0d82ba1d3266d916eb82098769a92a1a4092cc4eaf1ff3ed924288542b6b9a083e449595d09c69b3f1c8dd457a9a8cad2f25dadcb0d938c8e7a342ede5cf248d0e32c6d0fbfe5b5fe40ad515a0271b78d205318ed9d4632ffda47c3f8112cabb62624dbc4dc06d35e1f120701d17a21fb65d8fc461c24b292876176602e0692894f6d656c982ca41d77dbf346204945502860daaf69dbd33120a3d0bface3c243f01e67a6621c49881888dd17a13ac9916e3ab026c5dcf515d7df47569fbc8c51c01c2c7b4ff98ec772ba6d80b291a87f6f3289e49ef05559ef24a4af4648c3535d4c0d19a2fb7e045b758a7491183ea9ae78179fa3e7ab582141f5165150832a00b79b47741b751cbb732afa0703ff8c2141a214dd9e474caa86094df0b24468c52f8f5962f69400ba6850ce775635f527c50724d0a12f8f04a76d8330c10754a7160391b0603985cd185879bd966c23de9ff2b084ea91af00601f4f7cfa39b3c01635ca27352b6249e3f3ae0918e71ac5a351f67e9154a352ad4a799ef8cc1cc09808f936fec571f60a85184221982905a205a3582a0958410fdd72995bb7df1c5b1ccbd24efd1d243fb0079626430173d320eacfc39bc0c1d473823a7e71e5f5d60e8ba02d2185e042e6e65e1b545e63cd0f849a0ae1280c0e6c1552ce057dc79184e7cfcd16c7ce69abc9ad4051d17b064158d2a5b6aedcf6d9e273b807df1e79164fa53cfa68a6f72c8871907487146d4f8ef84cb2f799ae4f3226cdf5eae8670007273c44a82648875f7668c5f51efeb746cfe634db28a1c23b1cf2551f17e91f698fe0c95fa4d20078d350ab12b913440d2a16e2704614b0d5c347461a852798da1b4217a6cd48e910e5ecbaf289dcf553d42b7bea298f743b55ba40c28e8f54c206e60584a7180e6556d1c57568824911ed7d35de7275e0ac7ed7c09593ab7f9deb352aae248c2f3b86d5d835927277d4018ea114abf468d94ce78c5a52077ad15b541551867d0acdfb226c997364d2b0b6e75f0381537d728c5029c0b0dca69aa06a7d751d329d08e3e1774c91aea1f1ddd6506a3e579334a31dbddc73d592324f892cc327d6b10dde6a40082beee347a608555253b4f2cdfc25549a54f42084597f826e98792058b51f03d129a5449d4b75c00e4fa3fcf401a2f125efa218ad7c65dad23bf809a5727084f87f3af282e1be4733218a5b1c97851db378c162dfe7e40b5d0b1f38838cb3acb5a0248ee412b812002367e449b905c8e11e4a8a1765233c548d2d4a29fb0736b62d5a4384b0e62ed20832bd5c9aecdb30c173f413af92e90852d664d885f471a7c53488a608d67d403dc4f91740333af7cca2e005398256d0dd091bc88b26104c556911db5aa71aa0d42010908c5b0caa613d0533e2f61d2523c3c09dd14dcc31d3f24abb4cf2b1e5bee535026622a4f56a3b8559cdc210f159e707274182cd2be40955ebe02ad7960a3f505801273799929666015989290f041bda2305fdf33eaf96a029b1f2a595479d15966c434603c76e72dcc33f1a9a168121211f18fc25e0c5b18a4e47bdf95f345516b19274440d52fbf004772c73532ef6201e6e25b69508d918e9227c201ca5d327fe1a75bbfd0006be4f54892a2689cf79253bf2bd1ff8bd83e548dc6a77e313b59b9324a023364625a7e8dbe5759549b06010e06cebe15c3a1c569e2959a031fc4e6fa76c9c8fee9930bd00b23a782022c6eb0e4ea230ce2447a399fe840e2b996fee4cad6ca1cd8e398beb8b1bedc9e314e18eb1a30f9de91208665041ef9d31d658a0bc066c2ae1255f0e7d5f09fd66c8838b1fc5a31e68b7989626f61b570610bb2e6922b74e06bba52499696f4c8bd0dc96b556f3da080dfe2d2cf4741443abf523c566f8be33981b56038ac98c2a18a14f422a2f204bf82481597246db7f3de0d00912717e888c6ab6c087a7caa96ddb8e0d18d05955fd261f4e3f2687ccdae60a98c7458b6699f6458fb5522d0a672907d17af718320fa944d510800ce6a9beee1f59fc1ef59bb4caa9d187ac6c199c14369ac2654fc5bc6685f7d96f11d52141f2065d2a52b53faf3f85c210888e33fd1af52ce22ad42561eafc8fe58de2c4772af1e573f73ae6800d374347adb7baa450f070744754b3dcfdc26cee505a015e17b313171e6e168146066d409e9e53322f2aa1d849cd9566f0bf3165376b010d4c69d15929041271e115afc8be1ba69628a0898f88e043971d15331477927dada39c3ae8e26bfa8d9ae888617407fb8e6e657bccc0d0c07bfc975f15b27a889315de18f06f035f13e5c9f61d39d8a2c5ca49a4d52b49cfd2b5d17c9265580627fc05e61b3b05cf7d762e78e2dcab9e8f107d02fd78876d4328507a44f3396155ca40a4a25ceb27e31f21e4843688b58c603d65b2133005405d63819ff231ca496ba1c4946be17f8145c6c84a727d1cf62869be8856a0891382f61b5d52fabe45f5a882e49ee7cd24aa4e96c0996f06f196be263504547719d3fbb1a13291968a14eeab24ab36ed8786189afb6a80027af2e0390735bf1ee7a1795f1013ff0b4d14944d87775623c88cd63d5078c09244010d7f17ce8ec5b2e5f668ee96bd40ba5c90537812c90d9a88731dde94e30e99e58013b80b18bb718111a7b6c21b4a1dd2765e4ec7920f8be11272eca8689619779c2a6d114344ed97a17de02ea9dc00ff74ea4b7335527bd9001c6812e67981747629cb81ac68364703ab211829575986ca002c9ad669f8572cccc1d417da610582ec638df25454215fc4dde0aff56dcd5663b09fa06af6c959e90d0b4bbb1ab5d30cc45d94a0c2ebb9fc440d18034bcc3c66fff0c7fadc3011ad180f7c051a366019787959bc5c2746828cc2b3ba5d619881438f696dfed0258cea256b21c739c2df8412655b00cccf35b4a84dc8f776dd9b8a2fdd31f98db85f6ad4c644b914d2ec0ad20da14c9a6055b7e8ef803a2e3dd8b53646a579b63c45e18e01e99a5fb883ded3939ca983061ad6c1475bac6b6150773a5a80d78803d767a3275ed0aa814448e8f73cbda8896e50b82d86cf000fe5708d008eac932d9448688216607b6092b798db7b66289022edd65d3a395ec7c3083099d58f3fa3f88b8ca083039487e5c9ba5e4488a06cd09a829de5dc09838b57f7a40e384c0fbfd082d871cfda1524bf5f771e8e3e12ab181e16c34a46404a816626196370b00d8b0586fc8fe6140bf664008f36305e5241a77540d5ffa554b54d8d76f3d3a9ff16300fdc29222c1c43f5a606f34099316d0d29e4fe34bd27057e53101df0e21b36b2ca8ecc244ab616fa843b0c3831b83c0ff998d16579e4cee9f4aa414708b228d3efcd85617976847ba69c4aeff04e80cb0a427bf65c583c6740ad1737242172dcb4b7fe574ab4a2895a9919f37512f1ca4cb9984d4b3b582097b83aae6f17d0483831294d819f3e5b4c44594174cd049e85f908827afdb3955922173e1e8dc9ce95ccf1547901025a2a49b60a1949d6b9fe5495c6d90c32a280074dc2150a7893811f45bd2093215c84c17b1695760d9c55bf356a4a5a78ff771f39e704ff83473ea01a050365813e2b7e31780594959c203639b101eac90ba806ea18e5d05529572fd97b108bc5392491b0d50e08241eb8a7d749421555631f83730060ba58c4721a82429f73b95578db0725901d554bd299ac7e123e3f91860eef3a1b016b380a9251f197b75fa88870dd7843e58b2f1fd7400ed86246d2409098133902ac1de8f0934c26d33b81c9cec6490581082c2b4bb54fe1d4661d759105a2a4fea0a9c7685ef9f5b0d885c5c86651d348b53be3e64b83288d9d51e69b8bf1cefe219ea0b27d24dd46d1f385eaf1d0b15739742fd913d4de2aeee7a863a7baaad1d046ea0934d7c249b4a5d6f98eae206cf8c8cdf65d4624e8276d4667ebce5b4a817111f9535dd19b526cad0028a13637e412e7d977be3c841295103c0ada4f264fac6929e5cfa8d32a8d14dcf43436dea37a861d720b0e45533655a772533d7b849e85c37e0a50170efc64221dfd2861c8339216c2a3c01a0de31ab304565db5e5423642c6a46389d6694ee0b584d561650dbef022543359985950ecfc6d88b68ae5d76002cbbd9d47172837025a514cd6fa7f4e49c4c38fa043d689d0e56e4e899d9f058da29ad12aaa5e89aa7d9f49b0fedb5545fb59dba6041e5dd141eca7b9b8ab5880574dba1d086f4a0aa646709da2abca320d1349e8c8afe2027531f60b0b9d3d21199f306db8141823956d6ca2ef1e148ce414e1eaee19f7f3eee6080a41068f1c0f511be81408500d9846b6f8225a80a43d1308159a3c0df63793dc636afcf458b97f380b8b2b0cf38361d09880987c9c4716e4bee138279c9b23aead9eb6807f4c4b921485161c8498444bab4b07ef126315629a88f8c8f8cab8f2c89552905062bee151887d121dde85aefa529accc530fe8b838fee766530b12af8413c6f447e044b56476bbaac93b8c64dc7cdf63f6bbd22ae8b961f6a8c93e210dc8a145278438fc8f20c1a5c693d50080eef8293db2708558e5128f7ab09b4e2cccd3376616d73360af7a6495fcab9747886fd9019617cbd41c762e4c4e36a227290b2d263dcbfb2fb90ed7fe9b0385a020bcdeaaa6a34200a193704135aa4222c06011346a960ab303d0ea3952888ba904d4515c1f9ac7eabd2c66a8d2fb5444aea4b325d5c9394b40cde9add7379c435f839a4ce45e45356304baf107929f485d33cb08ac2fbc38ebdab089e292778da7b6d190120f441f50265642dae5f0cf179cbcf40901e7c151acf74be6a5cb64c531af18b6e99271b81ba290b6c809d9826140b75009aff034a4ff3c4e7364a13f869facbf372189d9c24893b6890668b93084669ef85443f40907c5ea0753cd888ae1bba7680fa73e9f3165db565e3b96a60557e71d2ebb2c838201cca958c12ba87e44246d325bca9a694b56e919100e7274039369865534c6f295ca84370f8c4ccc456c70573e0a06d415a6c7d384e8e46baef1df782aa780b8013e94e7e460a1bd0eae65bc41412564fb793108747a0c56b98077bcfc347844cd2c72d5b0aab5e99a4a367f99d61624367db91a076a3a9aa0cb5ab2d9e6bb243a742e9b1f29f7cd0745a85fcd4c3676c60280a30a9d524ba1d2699d5ad9702b3b5ec99495893b6e2c210f70836c3520aab0d8548353e1bb26cbfa16c320775912d0c1e75f05382508493390ea15eec1f8bb2100a94e3476ad3e11033d04b6502e01a6a0690939398e2cb005db3785c87854a24c89971714e034b38d7f7f35f1c92b374c3b3a6d59ac96c49709ffa956c377c11d5d7528e28c704d7b751809912b1915ec4c5be9494ddbe64338e750cb93de88a9da7ca0b7c699c0ad004d1b91794c74ac19dfcda5900a20bb54531a9086d844c23e0d819c115ef5f13c1a26532a38661ed45e0abfb838005d54582601b601f4a12f48ad9380832ad7d219244f9f0b979503d7010c5530c9678dd63c5f733094f80976f9f0d685e304777e41698f7487c4bd2ea674554d7de49845d77d954abb4255cbcc13932f817ab257beac802ff7f3e1f1a438a268598c08bcc200eac912c4f5100ed4ca3da1c9d91dfc7431709a6f81940f193400b622cb8fae2739f80906c4ac4124531ce2c9b8548072f3b78b8d68c1b194416e26bb8de67e3997056fac1050ec28a46c9f917ba7de2bceeb70959ba38c6f6fd7d44c90498462d63017c68b26085d8ffc1bb0c9cf03f725d7e375760cc23d6bc9e3120ca58c297b0b606d43de78a5078729d62e8a84b6cdb03094961ef078b98ad187b810c509faab8a70be177acd69b0114c67433b907e390007157c5b2d844ea7658a2055cabe801112f941ebcccec71ea3db81cfc27201ef531bc62b2a8f2c4b5492bc36b5bf6dd95d940168cfa6cbfc36e491341a374f126c4a6c35d33f4aa5ea18a7b5a19e476eeeed9d9c300dea2933ab08fee46242ad231dd8480febeb9563fd64fd5fc10e2dd0033202382e804e43fa8a3547d6420904143597049f83cffc33f0a40c3a549980cf140d1d3092cac94e10932741e5922689eb0a02dfee6eb05c938d7403c69eaad00ff55efa566722debc14379ec1e08f3710f562cd19525b4f929486cde2af7be74c194e39b297ce2389f6f6eb5b3c85d58f9e11555e8e4989024d130cf64a7dd80e7fd3240e20854e3a2d16daa20362a9a43e3d1106e79aba601245144fef203df0b9fa698d5f5cc107220830e2e5303d020904a59c59f2396c146e13c251927d05370adb1da3dfc932aaf13aed68a66746cab0b7d7aa20de01807667eb3d6f05fd96394fc6194232227822122e597b32197d129f96cce055703618335b22a0b102b49727a018fe686ba980c18ccff3f3eb477a910050ec1d72188c03ad777778b47417885419a903c08b569c63b778241a4f123f68e34eb815f9a0dcc9e5877106397830588d6e89aa96698af80a43d6b65ccd27a740c580150f25926575e8b8ca906dc171ee150b6c44ffca541ba04ef1aeebc7a9bd9c4251013343df906d85006243029b0e96bd624c441669f9cc63614d1826a8506f7628d440a59a4197680ba1ba0be41d32af7401d04d17733931e13b1ba82e3d36329fab3daac8b21077dea4ed68511c3ce1b033a817a7754f970e94bd7f83a31dbc6c1ab4558779f91aaca36a8972604d261971f0200a40b719b58a3f08133a4d1f46597324e5592259137307407b5c8133b1c5763a53b98b5a0f216ae1d7185da5dedce036a05354a3436ea36cb4a92c995075b0923c098b202ffac23f75a39b854c7571ce828128b71f05eadca04071101c40cb371248bf2f86dec897ef6a72fe17d001a408b5070e7cad0d6e7b87b4a6c1f23192d25a603d4762a340cc6f8f9ef2fad5a6865c66ad69dd272cfa2e61bff43d3cf04b96648f0d6dbe4e327906fc8d2f7d38fd55cd81935384d2b8476bccd5f6661c4c75420cc331538f2ca6cb201ca29eb1435500975475c0b1bc1ae5ae7d8d783fdfb378fe0a6650efca09b4088160488573b6e1835d3c52bae84a517272877d167c5d5d045eee284663bc13fb2a69b6000f322b90550f64def3bf8d21159787c47d1c4098485d715984160a850532a7b0243be54cbe1ca898a0a52ccb0d6de2bae2cf9983092dee93e0e7ba9f2dbace6c3c1092b1986d0ee34c9b50e103161ef6f212328e0844a6c36e9ebb7cddabaaafa2412770a0e4b1fe3af65c631805a57950fc610f5834eff145ba32e1f588179cacda024168d42ccd01692d485022a70488e6671db3bec605af6e37872f6069359937eb427eaedb2644a578c83dcce150295bf5db8fef14e32da33ed6dbd5b715dfa315b1a78c42bd00f1b1d1f31c66cf033b361eef055be2ee27991262f8a1aa6223bc9e9fbc32d5b2637d45f313eca413f1e0d898a0d0e7c5b7f9c0c3fa3115f7778d3f67679ee3037074589b1b49219f40d2892592f29970f9cdc18e489908ace1ba64e93982320396008abff829a4de7c722795a1f896a64cd2c09c8969226ad7d043c13915b85bfa8de544268a5a00d81568acace382300fa5e1d0dd087802f4c3b702e949988cef86df2c8d5877dc74ce3128a9d4965143195400a03d5bbef3fcbbe75a869915fb2a687e1ebc2fc5cee12800ee3f76995981306f14952b429012675e773a36d154e6c73b03e128a8f47510f2b03bf52c872ea8e4050f9fc8f1a7ccbb629a94824c04783fe31d2dade5150b81cc4543bff4c725b3f1a3cb1d0d6f970b9e2901d82ca7f49668c63ee71a10e42a0671003e4d056444b076554db115cdff7f3c36aaa42c437f6675a25695ff33bbc816900103ce65de18a900b054113de134ef5225a4645be2ef44c005ee0caaae2e128204a0d761ee81228a972fcc713ad261e936594d06a0a32e18466c3b5f664b16ef13cd2225f68c6c405200ccb95f645f8b05dfc0470e9b99f26b8b5a3416a88c230d1470ebe41c757f2b7db1777b2e93fa8e71bb14b28b55e2aa8423e5269d780ae5303d1b4486d003c9afd254c812449a9a4e940f6fec40ed89c43c2701aee338b8408fe5c56b4585ab2ad8767ea184636c52eb6492c772fb593a06165c4b0eaacc18c48f6fdd23fa3e25f810607ce06f8aabccf41458a0bf27f44ce39a04fb0e58677bb3ce464d337c3367ed23aea1d5816f915a6ec037687010db548078b301030f9e1fbb6e2d4e7a11dcae8f12cbab6b1d2b3de7e1b9aa8a3c0b793468840b6c36e2576c3464f5a682e3841893b9855a5b32316ede0acec335805a54470fae065bd88f5005832ca9e962eb1196107c88532a1c40e98ace8239d5a823feaad46e09412e69353cf48d1f6a6b414f271573c6f41d0518b1a21fa3394ee80e539802499459f1922a4b5478b9ff47314a66889f81c2ad0847ee1b2d9d7e495724275569758376d5698f55635c16b991dbe83a557ccb5bd4a2010a19754270a121ebf5c75a2c763c71031d2f723192a89fa4945e653f1c9d266b419d5c0d57acbc87aa9e47772e966d9386fdfffca72c7e5a256664213e49ad4820fd66a0d0536283511a67265cd1a40b28944f48fccea43611299b029815f32a6175f601cc058633151c52d832167a20e9b5fdd6d519386dbe08266627037007d8a08623294f31b0cbe501ae282dcfd2db9b31f63828f664e94514fa345bfe8085cd6d73a47917c15e7014fb16c01ece549d98da21bf5b91014dcf7e3551cab25549d20779422c16da11ce641da186d8cfb4404683750f8ce97ff6c1dd88efd8cbdaa7d2f7454aae294ba2ab92e29621716dbd5573aed1d676fdcbc88760aee929b65e507ad64ad4ec156aac0954897168417f890a888b204b00baa2c862935ecb5a0a582e869dd828c0909bb6545bc045312cf209fa792c7d5e1feab835416b44b75c422ebf011e6ea049e3c41bfcf0fd5d95a886bc2138cd3fa5007407bd9217ea9a53871401011c6da126fcaccec262932e1100d4129ae46ef0292041513d711dc30ab5f206410975eb6849632527609ea63a8eac64560e50444ce795ef3bfa5d072c05827237c768c4d518eb07a3f9e9fb04ca2031c8d53d46f970218500e475dc68b911f44bc657aff064a708e58ba4268cef0ccd8f8b47c4addbd671cac95a64e39b814880ef9cf20eaa5074f704a758eb6472d5c730be57185ed470f1f3054ad8339592f7a519fc08bf0a61c70a126fa72770c0cccd4100f761d394620c8e8509d2743f51a79bcd52274ec4410c29e0945d4f4a8dfdd2b02b146b4025b0290e409cb535afb22dc51956726981dad7c609fe979636b9e38dbfe08c2f0a6212b3147022fb89795e88fe6a4cc5f89e9736ae09e9083d614e074c34359582fee1edb2f2325bb53027a5db007e2509126b428fc46146d63b42597f99292849b7e66957978d2eac507db310f97288350ec0ad639bb61a678600158807c6692b366986cce45a8986aac9a88a5a46dec6cf9a5c3f40a618b42883eca5958e534afbbf971bc7e281bc855c268227ffd810485603802456b95c91ba00505197a508b3b837a9b4db108b03bc076ca242ae3e272a9c9b72de1189ff3cc3f83a9005a4a1010a3075415e408a59451d8ae46e75253793177a0fb0e60eaa0e3b61fd8fbf69ceafd3316b6d147a51d6c132060eb1c5b41fc3d609b21459e186fb67d8fa67c03c51532cbc1b0905d7a7158ca3e44f30038b0713d4ff8d2981244fb8db965ba6b4b79432e003fc032204f75ed5bdf7ffffefbdf7fa8efbfeffffffff3fe567dbff58e54cb99ece47dcbd185f8c6dca4bbedf7bef4f9451f2de7b57586c6edee14c4c10265a0d1d3e3486c985d1ddb12ccb7bffff9f36adbcc4c8fbeeeeee5b725646756452deb936d8c2d3b11a6e794b16706494913135833663c855ee3e9ae012ffff7f666465f408af9821b9aa1c69e580c95b870c89cc88d48e86a6bbbb0e2b3cd1e338f228d3018f295a07280cbd1621821c43a4210e23445e03851e42dc6ceef7de7bcb0fb59b1b5cdb94e7a3b6ef93d40c1fbe334d5fa4b8093f8afcd089b8f7de17faff8f1afeb35675ca0c201dba39e446f08690ac3b7737c727373a0677d0f0b3f1c4057845072fa103bb95bbbb0ee39c8d3b8fed6e43869211aaa0fc4699dfff7fb6c92d8c552d263c64c762084fccc5bdfeffcd243127ddefbd17ca131428285da0444129f331bfd74b92244972fc5602a27820f1655094d17befbde2cac94b62126ba159191d222a323a42ba1b687972af6f999120499224cd1b281e212537e523f9efee6e925961cc83b2b180ba9133b4caf2a6fcb2aaf1a4c6528d5e8d27a9f2de7bafbbbb97008c7246e9a8c8eaefc5f83136f1e5a009e7eeee6e5225593054ad27fc82eeeee27330e6e7aa771b7777cc5322daeeeeee13b8dfbc8c2e32a2649431a3dca2e0a2e456620b04435cab55e236e50d751958d2af598269f915ddff7f4d9451f2df54b5802449d4e8b473777777f71c72a94b2fb74cd5ffff8f7852e5dc7b6f8e1e47ea34b3325ab361164e37fd3c2dbc6b04cab744011a3a29559024c1a062d5c8502b42f19010369ecd67fbd5116333094dfaffc7efffffffffffff1d30011ef5d821861c40c0f4c20e41efb5fd4d35166d81854725cb6cdfd1171367b8970a96a10d799dc464149c95d19c2e69c7f3f98a283f77771a54feeeeeeeee2e7483e1c99a192cb810e44e63fb65020263cff99274dddddd6dea8a303ba22d42d129353cb288929a6163a7a4dce8c14cc21380956224fce556007a18b708734b08cb7c6c8500ad0de34419d621a21e195cd4184132450489cf9892038c718bece71fcad0cae8ac66bbe1153bdccfffff04452ec65ab4686192a4cb962a4e82dc656c1fa53c30ae94a4a0c304ac1780258f87ad453e297a62e4eebe8627caa8bbbbbbfbf5fbf7de7befbdf7de7baf59ef04185ff387bc8fdfdd9d89cfcae80f181472c06448de7bef7577529768e8b1463ca972722c7861c2982366bc0835d9418546038e6dd1c391f7de3b418c75efbde4bdf7aee179076b7cf9279a6b6828efbdf79a94478a2dfc6cfedaf0f8a79419babbb7441b222e8aa68c6f8c9a1c5572c8e242437cec3ee8d0e948d2b1ab5f6656466bb61b2ec7c117ddbfca1403d401678e9ace20e99ace5429854d66724d66d6d89a1d42924f5b13810bf2a4f35164231acaa7b5dd8a4ec8a7bd599c35b238d7393df99a72c81dbd904f9b0321da6a40acce2229c9a7d549603b733b83eba5a1ed7a3b3cf5cc243d31924f9b7433030987dd120af9b4bb1ddd88c33233815882f07a37f2697938c05913941ab009ca145c130c3d3479e0c9f7b4423ead6fc44cb8e403cc0fcafe4a25a1a1126da644e3a1538251b340db05483e2dd0c429a599529aa2cd94863668a35ac8a70d662bd4a12b5a6285b68c2e9f56886765a68039704a55723c3bb4532ce4d30e5b3e265f528f684663924f716633ebf510673ddc975d8f28d8bbd58670f9146b5bcced5ac59d88c2051473f604d515213da14c568c76d5e2933d41eb4eecedba73b24ff1b7ab8ac94ad33ec52ebb8a274ef1b6abae5a34aae38da92716d913391626da44221bab5ab489c2d182f043456f3d1dbc518a1a23524803b8421315a53437d741034629038d1ada4e4192e4ee2e1bc9ff6f85a0b7231e69a3c2e2ab21ca66c9361d69c601520dc9669a2172a28c921240728403529aa899790e1b4cc0b1a188848966655e1aeeee3423da110d89f6e4b5fbbdf7de968fc5922465c64380a1a1c3cf890b471f701c44682c11197de4bdf74e5096ac2a062726274677dddd7d690c6fbb97ee119885e1528313af27b45da81f9e0d532037de15821befbdf762104bf275c7eeee3e13659474d1dd9de541801817b9e9822f0af98ac0fa136594fc559698bffbbdf742d1ac8c0e1115fd065046ff66129641c9e8d76ab9fec9134015d60cc11863dbcfca2830286c611bce5ae0a8d934d9d9dd6b626c8656320680b90075a5062632a890440b07702042ab0885367e73b10283db260763b25cf20255ab2d00b1bfbbbbbbbbbbbbbb5f53c9adf0feff6f7924851a13fcff13d130d1102622c2f8ffaff0babbbbbbbbfb942949dbbd1cffff7f8aefdfa468cc601b8c6518da58d9605cde8bf13503f5feffffffff4f24f7cfbaeeeeeeeeeeb7a7c254ca9aa41b159731470565f54efebdf7aa39b2328af4644903353dcb83ed5d0cbee05ed04153a6033453b4a10e8644e2ff7f30c9cae88ee7d320f87be1d08df0074e0684940cb141a50329bc70c27dffffffff7f31c90516042a3081993308e9580ae1b8bb7bcddddddddd7d8531c642495646773cdf0fc84228f843de7ffceeeec0232ba348e493bce4ea690d804fb11f1c42b01d87c42dfb7f2908b818a4848637a6ece0378c3ca0a32bafbb7b1877fcbb10f66877a3a2a2ca444d8da1bd979b4d120c6226ca28499a6569416d8621a9315690ceb80d2ebe1b2e37505077d8b069561966653992ff5bdc55830a1f881189b9db126e56467125e472093a5709493a86446cb90945b67bcbc97befa50d591925a215659a918b76a4630118ebf275bef0d50adc00fc1a37a527aaeade8bafc518c348d86863972c5760db82d41576df015b025f0e01041b7b0aa0b2a53bef2da82e40eb6e7b7de52c80eaabed1637d575a1b5c8a220eb4dbb76e1fad1df8ffee893132033e9cada15d33fb193fe5cdb4997b85db19f14bb2017a2cc6b5245b231f7aadb41a92cd5a25845b83a7ba98f8d94bbad082aab772e5541c79f1d1506297a72a44851c2c6442dee20adc3483071b974ada2a63b3090794ce33b419367c6cf54b756abd58223883c921764a1e2192256f285124c8d63034417c705d0dd111a951d4777f1f5d5e3aa85b8e25f8499b9917c7f775d5d8fb031cfb60833abcee2aaf506e9e2d994294b9453131be5a26375f56ccaf48463ab3665723aaa614090f1d6d387232e156246ab033fc66471a90f358c09c22015a2059a8b1802e248d1981a8ea3c5a9e4561492540820881c6344c8c0e1c106a956935de591c20764d061061d30b8dc6684e0f243889811d074c0018520cec36eaa338889579c6c61c149044c3c2d427ef2db6bef63c00a13e091932d46ce778019f34cc33425465afda123a937651ad2b0cb4d99864e3d4c48e9a0cea0c043cd0d4e24e28a88183eccea99f3ff341a4e4e2b0465a0e471d39e909097cb4d7b425fa0caa0ff7f9ca9ac72b2916d62c8424c562d9ca11124a11f1f72c879d39e908d9b2d59c499a2bc0ad3ea61061068b2b9692f46152659b5692f06940f56622cd935f76214f9ffbf1941c6d9b4176307ce0cf9c3a6bd18313e10c92336edc10803024c2637edc1b861486e6dda836105c8ce0b0c17707ee4109bf660fcc82183d8b407a3e694579bf6666954e4cccb76cf2dd7ddb437b361ab36edcd84fbccb80b8e1277554aaf383669551c0226f666eb3c14d92e261e4ed81f36651a4e0119c0ae4bf54b88c0e5715326a79cd1be7aa43bd5dd49c8763139fd18a3a23ba7285461edb0abdd2cf5c3723c781248fdfa45d08ba0174194053cf382f00c15d2bce5932477a370e8f7355ede91cfec33dc91d1878be22271944fd791d677090c3c62258ae433f673818d7cfe88baa232ba14182cc9678add52110e979481067427eeae8491da8105037ce493f21e0784f6331f4d1ce041927c529f69e341ca7d3dd87011011cf9a43f73f685c788f3723401109ae4930245a09021df01f1852042513e6970b4f5ae8079f25d012366d45df9e2bb026685113030249f540802d8c389e9eb61450324f0c8271d621d102747335a0af9acb35dab365156f52b483e6b0de7a404a6b915e9c867bd6d5cd539473e2beebe6ad2927c565de9b3e26568e5cb6c9c5991b2e1402b6088ac7869da2dd5c867ddb9f088102a95577b2ee4b3f2ae70490a52aaaf3ea990cfeaf3d901814ce176a4a9bf0a4594cffa1b7d3a7c4bb3a30aac5d82e4b302adb086d50eca0e3558a372f9acc15df5bfaab00e4559d5004092cf6aea844c3174538666b41cf9b433162e2fa0998d593d82c4aa3be2bc17c0b4d92e1a598295c3748ac85c4c55f8f8a5b63d2c9868a1c708053271a4ca30a08e910e4ea7e8a802e9f4d0f1417dac89a36d35099ddb0532746ef566d7d1bfd456972fa01ad06cb5e26140341bb3da02345907674f9c22b870bff6b148c7a88465ea33fe8bc40730c5176bdbbc8a84d0225e3d3851c6d2f7d573a33e2cfde1253442082d2af514f5f4285f3c41eac3d2e48b07487d585af5e2f9511f9616792c2da6e9c273c328c403b5599ac5b385c6581450a0354f18de6601f7e962b17488170c28ca581abf60c1a088021665652ccd8295d92c1ddc2cd8053b6431b7cf1e1f88574febd5b313653d467a9434d9560360b581b84d584f8efa584d42a87333e102508c6d49134f4c28a14040b35a81a52aaed6f5e4562b4658cfd11a133a13482692788254c58aaa30b5d53c61280a99122ab31a078e1e3d5658c18811254a4e18b0b6add6596d70b35759af5a58f2625dbe469f8effa84f8da95e24d4161a7a7a562baeeed13b2b0e6e760993e9a88fd50650924f133db96d4de8b6d5aa9e558bd7b85d6760abebdcc6d77d550d34ab40945670bad3aedaea2cbb02cdb6d52a20537c610c4cf145aa10608aa38d91660626a52a48641b16ceca5495d845def7b1848f02445b6f0850c14f010c6001095690f82a3790ed5fdcd80acc7a8a7872f0d4f0c173a547051e22e44ff953975cd5f2b0e20e1171dc9142da46df31e1c8c2ce1d7f9ea17717795d0198cae74f4d4441c5bfe1b6f8b9fd771c613bd4a76a9f0d1695a8eb5b7336069d7ad3acb2ab0f3ea041d1e5634e8bd7565b588ee82a7a1f5f94fad89d18446537dd39339a5cf5033004aefe0d604d6abf186b52e3fbcaf1e0f5d54f49187d18b9e3d5d61aaa0b98b3fdda6a324fa36b88576de2285aad45d8c823c937ebca85fed50758ffce3636f24a5899d5549f64b6252c8af176616709879d3bfb8c9d310c60e705268c840a4645d9b9032bb14fea13b259b366cd1a0bb888b9702ec69f28b33a29675cc1c69b28b31958555d7d403f5069ba72c04a8bb21c0f4c96365f04a94c6dc24830350b46ae3c6069158c04951e93b61d73db8a7abcad2050834a4d570fa8412b98f9caf180a4e28b20d52bc703ac4b55a9a2aff36f8ff3ddb6bcf235d217299264ce2e97d6b7dc3eeb2e28a2187da2d0c5738dbca01583db064514344814e6a09127ca7064bd479bf7b85ac0a8aba8735ab8aeda6139aefd624bf025eb8d4396cddbd1e7b8c26a2159dcf4ad4d2dc5082a847527c62f933f1764b53d365c883b412abe19f14316206b0b4a9d47dd93824e11fc3d91f9855001172e2aabfac737661cdf911a35e9e465d18256206a310565fa14b57ca6e07dcff7644f8c215015ad6aa3349a26ad403fdb3688c6f2b61a5b8d2db62a8d4992c4bae2913ca894ecdaec418a440a00082800e318000086201086711c48a224a8c07c1480062ec49cdcac401a0fc62151301c0c83c280301010004120084000846220060661aaa765035dcaef41911cd866e3f7b65662434bd9da4a1c08a3eec9beb15b442d71d6d0279ad114dbf4e4714f4328aef2f27f838196fd7584598910a60b7664596f47266a320edf80d82dc6ea4eeb783f16a9dea06fa1237f27a412b3465b449b62cf65cb09e6b8ddc8d2f95b6c6381711bd83965a9d230bdfd322a5409d249a054cf38d6bd3ec73278b6747c229b3722084c202791166fd79c10d8f573901d1c00728248fc9d6484a3a0233c0207b1f115b7101553c57b42f395dee96baf115ea2eaa35305836c7c479df160bcfc7511b15ce363a28cb8f64b0982383173dc6311065c9e16d9768e6ccf496cefd179180308337d3897eddd56675322dfcf63b897fe7d1413db1e28374fc4e2c464f978b48d02e00cfe1b0063db250520be23ad83a89aadd1fcac762e2d65ad91e7220a50ac719823726bfa992ccaa07ed914dbea5931edfde2999c2b430c121982eb26deef0410688cae482c07dd5014eb0610dcb766930cdf58dba7bf2e46945168aaaa8b3f6a19a065282685612c076484dba95ace8426b896e5c2575a672837461d2bb43ea8092b7a59bf70d9f5f3abc8473fc763eac9b98eeec20525a3d7b78d72bfd7cbbfca49728d0e03ce46175c5150909f9171e8b3dd095a2b67ff8e5a90cdc88f06c35afdc85172565d85fa62bccb041fcd4cfe6602598d46448fe891a1eb490c1aefa205fa0e5ade4dec86a362678344a8156a2a773f3c8516bc78705bcaa9eb7e71702337fd419fbc8e3bcd1271fa9566dfc86ac5588bb4c4b84c73af62e955d733d1496cbe4175ff928d0a207a2c5ecc202b5c60a524e40657c405a55330bb422b8184c8ed8dc579e12174f1a22eb0396d0f6810da817ab1ab1dcbd2a9f18f2ec2cd27dfdb7fa38faecde79493c2d2449fe928af099569d413fb01ce805ee46ca5328dd3cb6b6a6f8e92bc3ae6322836e19293b390aa67339fa9f10dffdcb691e01e7c77bdb0ff109b8b70cc4fb606fc9267caa4235eee74b55ed2df4a315af228b0ee33a264bb9813a7b681e218ce2d56b4fa1020090bb8dac519e41416625d946e85ccebc0b6a2d06885840b3ea70c030f3c801004586f0a8a880476ba5db675252efc2664c2dd1884352593585f8089d4c45cf27f01254b1b9050ed4d5e11d1ed56ab3d9705b83e00505b8c018b86de542c45341d738a9e11422b3842227a708fdbe61e037eaaa6bdba1fbd679c264bb308f9b44b1a4d8ca786d21e24ffb7379c01eb1fe447eef7224311277cd3d052133f355356069cb53fa4ae0c5fbf5f3da7d765abbffd9e5d6d5c1e9f90a093c17145d66761038d1fba75a668606070d03df3c32365337bf258833e67c2f771a5a0c1873d3644c186c23ed25c91535146d9240925ceaaccc0ec5fcb9f486cd221553157026a8296edbf914a911c0d76c56a277bbd5dd9342f965a9f1282accc6e2e9c09f5dae0328bad453880d64da2febe60d953a6750a7de78c19214cb65ad690b4a27138ea28a512a2e66d7c2b748ee56939b2343951910230523cb2bc2be0ed3fa4294c59898cb1a73a61373b661212a9702fa73b5a9c448fa975fdb5c8500f9075968ce88f90352dda0ebb3ce1a4666335d8ac9ab3a65190c75a5e2c4128a9e5db03b10f3abfee704b9acceabf7468d08a7f601b83e4b4cdd11bb138a120e1470baf71cbc31cc025e9bd4e97a157e7b7649e51ea25501a95997b617650e7713324cdeed271cc242412a17cb0d92e541bf31d72c73378484a02c9711ca7a31d728b81ed17aaf278980e4279f3271603964be4f55ade1649e852315348edf19fd9e45035098643d9980583c8fa500b1dc24173b8f0c98fcee3a6dfdc229db3bd8f9680338ccdfac74406a4f052fe39db90dbfe3d3ce54e7fb1cc53949aa7db42a8fe864329ee8b3f5f1747dba6f535d0f4e5fa519710dac4122d4c5f810ac25607047c9970ca4f07a149b1e9c0371846f221d9adf7a5eafad68022379561b4faf505a2abed96c271599b819eccbb10a480945ce1e3c280c74f1cf321c43a3cd39415fc9d80a51fabee0f65301ad797d8a46c4aed15e983c281a5cb9dc825d99e05cc44ac88222b15db22437251b08ca40f326aab7bc46beaf1f919d610d0cec4ceb5135315c8a269f900842ac41a0edfa097720170628b7073a192b0ae58b7000092cb7b1d540737ebbc2b25a1ee21be805daf0f56470a5535437d222bf39b5adf61820b207303b19d79d8734ca11a6ec59b1a11080521878cf22f141a64ed3d965050456b1e42ba5bed21c65c2169e50676a067797ae570b075961f1785d3852fc911260a87acde46449d098af16a4c911ca0288e8b12b621c07f78442a4c80654762e860144b131f4df8ae167370616803508358816416d5769e239a1973d0348891d0e880867f2f8474cb70f050d2ea054733218c6cd7cc9e43b3f04dee51dd3521b221373c3cf248bcdd7c507e0b24cd067bf2d8062160db7c3a85001cc612ab69525221568a404f32b398bc1f7bb16c2a95e8bf15c6092c855c9aa2438235ca83758e664d8ea98814eb7fef6e64ae453202ea7b20863a6a9914f9436003ae067f9b77a8f2a8ab9885173c7366104d28e6c8c8fd831b251a3f72449ea6265d5fc3bfe15249cbd3a8d204bf6af6edcc0b1a09e92cddc0b093e92d43540ac84a49a9c9022ebab632df0d07de6cf2dc8ad720a63a2c0dc574fdc8b81a2421ebca585171c66102ce3bbd8b304b3cd576e69308c08f630b8701541464c68d3ba43676d84e19347883f85aa4713d065015c1832ddf14255a13221cd49f54e52379cf288fc46382a8aa0e39ca0c39ab07fbb8650cd3b98cf1dfd127ba414622c8e4ec446f2846e12797e15a7e41089cfe9ff038d4fc867cee8b17325d51ae7497af257941202d926c40fc50c5bdc470a0e82e8012450b2ece9f07b25640cb28f9c724283c1399120413873c7b933bd5b3da01000574fb65f8edb16a5125d91cd95063bcee6d2035934bef252161bdd7aa9d33522c88bb901ce4913357033019fa4763c196db5666210e9bd44ede9820c9df363832a317629cd823e21c52f13e2427b3f47d200d912c0965969853268ad84427012daf9865bde04c8374b38f834dabacd9fcc31f4414b41f0f3697c3ebb3fecd08cefa623253a973b95a1e92ccaec406c2a137463bc5ca01b2d5b861f3b1ad32953832f21b1f59a2d3dd7ef45e7fec01dd63e7667c7b067530a050ddb3b80ff95acd383060c8ebfb6a302b6c289ffd7f340766bcdcb6b37c0c816564123be407468e0e90254d0644203cf291ff8c7eaf2e44e4f863ad998bd7a10cfd6a1a23707b3f39ab73ae53c7607745be1f635643ac2b4361828e93a2d503682050c85b73a52540f28342e8439a450f0a4f6d500c7666556f47f24b54d92fd5169209bcfdec976a23ad1b60199c99c2f40c31d1071f6dc9d5d7b6aec491c8123574761c4dd0b75b536a9a7db40d85a46fcc360a9931eee6733a1205cb401357fa4204ddba11f3f34ac9f56b9daecf5026ba41ce16873d43dc516f8de67ce19082ec2cb4cb3ae057435a1e36441b3c385469d02ef31d2682d55bcd6882c972b3bafbe582b379cf85b5994d4bf8023e7f35bbbc4c3363fbf66a00abab904c41e04a2cc1aa164d811bb200023f72e49a579b876e0a1872e0ce2b8a5040c5dce73916322cc4748446e85526e5d18dff5da8faf6fc053d5e94fa22907eaa1734c032de85aa49f8b3da76e0aab630168a44c65f7ac79b1d4b1af420b39835acf8049a0ba9830b1c9114e18bcc1fcc905fce2348e6a359d02e0fd20db8cd78bbc62ed72906e14add5e660e81af97b9ebb6d3a0c0876a8886190bcf92a0237c798d83cc97ec929fc4e29f87d957a4477c60e4cc88ac7c108ca997468cd1c42edd1d4ef1b30317a9446aa1b4406fca5b022ed8187d9ae7d45c430fc649bde2c94a0739047693b0160e4e25437b0c0b074fb87b5911d006d24071e8590f5309c861cd5b2552b2e0cd44a2f904fb2afc0c3a6fdfe8cb256ec397f5613d07f5418966f69f561ade10c06694fb33ffa110164604f2be979fb8caa240a799bbffc8bb025d0ba8831b9c429ff9d0159a0e9c41e0579b3ef26bb2064e813698219ff988ae79d28540faaff6273410d8dfd0b87dbe34236f2698417f3e9747f3ed6692fb23ef3e690d9c0f5670f2830806d7b10267dc3e3fd45d719669b4ddf1f8b38084a59e2b062bc342873b4b30077963c6e0fd7dc4cf7c296e520e2883d517fa63d0c9cef59861281ff992ab5c890b6af9ce1f3ae121a277336eff99afd27125b7df82fcfcafc5475a65fd7c37308c67b16772572930fb24f995b0af000461a6b71a1132e1eba710d74fb1138754252c3143473e54fa0872e5b6875730e34ae386ef305113fd87e80017fe05afc40fded7972997cb7011db7d96afaaf85cb48c240d1c21216c5c0861e29f35ecd7f73704d2d4cd8efd17a17fb6510d1e4970837c0c73a6951aac982ea9738ca0a094490a085dee605e34b0734442087c302fc3d481caa4a80038d1301b0de0c1c1168f8cad175655e7090fa387166349dc9f3c3aba8fae2f773ac3273e3cb6abc9a09f77a8b2fe9aa1a9d3ddef039790bf9aeb21d27fe2d50b0da4d15f0442347dc8ef5106867dea37bd64ecf027efbaedcb13d72dcf73c9c79250eed8708459550496dcc356312092ab1eb140198d22842e4386cbf040f883d7c9ecc02ae29ce06a5602c75e173d4b08d6113e64d8fbfc436f026212c0998a2e64b0e13c554a61fe2854864abf82f5351a0050e2714d88d7bce94dcf7beabd1e89e64588f3e0d4593ef48a950582d88d14a26db1e187901bf946c1b5adbbc114e931ac708afa75e78801befdc31e05631e9ab032597aded3ebdff94d7e0814c50aeacb90c0045e19d972ef79e65695bb3a7c460dc08544ded09a82f05a2ba21059a3984c44f189dcaafa296374c1836e063656c3a58b83827724b9987b60e45ef958d24ce479adf051c2085e57390867af7e606e8987459ef422cbd70a0f7c24d42faf5410d4f65b1d6220d97afc9fce741ab969c2d9df67ec6cac5b7de9514ad8591e1d1adb0b3f46aba7cd92bbc777293fd5fbf798eef4ec39ee2c2d38d1891de39427e6c8ee4bbd539e1360f8c1d5130bced59ef9cf828548050386cccd24e03490151be3502bbf33842c49cd1bb2b2fbb1e1e5dfbd87b435b24be61f405f5965fb5931492f850b3664f10a2e4f346ae6ba5ae4c2be86a71150ba31374ede981d8f6205ac63cf3bf6b1b4d21ba465737159c2e7fde5fada3348af348e023b2e42f1b711f9e8342e01559b75880c60b6c4234cba9f5f6598a1008aac3b2614bdd751af0208c0ba9f5e402f912d46926f684e8a6cfaf6a0322ad9d9a49f3b90a7988d7b4b0205a619995957149f6f6797f4245e5e0df89ab53ca6a2cf62d3eac7c5c559228a9d05ad1902630fa60c1306f9e183c1285fadcedaad9d6a15978eeb56e1c11eb31d3b6147417b99a7abcba82c88eb98823549aa5192b9a78132c50571cf1d5d258cb147dc410e5b10d8547b5665117d4bcc15ad664c138c7b671988ca82a2713bdcb7f57c53651a4eaf527a717144a77831b62865a106c10dd0a35ce27a69ae015ddc9105f1e517b104856fc9887a8a9d888096b959929b7606d39b14974131a285d6bbf44bab7162384ad8008636532ff148ce1dd2f5d5969714c0c47199993b05d52e63f12f96d3aac69822fd24a7bb5473ace810f70998b579c51debd1f587679a86298fa84ad15ac22a630f12da4ed9c986a9b75fb27c5def2c0be592eecf35240168e268ffc6bceb0ade694de6e7f56f3ced94f3637d426fd65ef542693a4e4d886357ff92b75cbeffde2b55d069d34820f4e92dcb024cd53724a33050fa232ee7746b6a8d4694fbe1c1540a8a3a3adb3412a4667d15c2837657085dde29f614d451032a5ace750633701ca6cfb0a36fc16a5d3054a1234fa0d5c827ddb6bbd4b26c2da7ae29469e64c5eb404be57aaa55bf86d75c016ed8f72d07d2219cb584ad3983d851fb20bc75c1a012b9d27dc3cfbc25456a273d9ecee32aa5536e4002311f8614bf4aca250b9bac9398a59fea92947d405cdac42a2caefb243fa95fecca2ab84af150e42170139bafd17ca55c744ed421dfee09a9aa4c6900ede48a73a77d5ae6a509e715f7d5f13c76b7e40ee93cc23a87969846a1d7d901b98bd6ea2c9cca7e85fbb612ff881ca57d7af06c18efbad585d7cb915d21e35758a28484dc0552a9c1324c3a0905d9954c32fa3326cd49d0294060012e72ce8d0e16cdd425c3a4e77a855167a3429ee141ca30694b0a6e1e66141053340f264840aaa069ecc57ee3dc157a813bcf53886098e28c6b4b98f68d56986b090a34881b2453e77e1f0611a36da4b03bc6d7c0582d59606d98fde0cbb5fe1d5b268b43c830d5483f74581866b0bd1834aef89427e9a3a3ed909e31107840836e252077f6c34f9d08d09acac6059005b700850044b9171334a278aef02e13c18491299b31b92440ab2f063dfb86c71860f56e26a6959fac8d1f757009744716ab4264aba3061e2880a98c9f680eca3b3729f82e54ba15004a9c3be65b26002a11843482c07cfbae2c94f6119fc065108610b0a2c81031d4718a30c5a9ac9e12bb1e0ee019ee7f5450aa5b3e32dc0988d5b180e2811c87a66bf4ffcdf7acb4116b23e8d75131ac94b3cc297a3a31503a8b02a05b93cf5bbee87d85b953aa302dd74899c9678b016b46236999a4c5e216cc59ca8299d54a2418972329997ca53a783f7eb97670b734800fa9d0c311a9e55ca077ef057be69d755f0a51ffd0ef00e54d98be913609d9ae7e194f2110d884bf6946f4b80e8bb3abb033356f324b4a9f8e17bfbcb10b525368183ee35e8810431cfc9c139c39d4d53bfe98d829c82dbeeb99bd07d94a0730dfb438f602bee19b33f4db8088fdc1bb710310be3f208f99bcab20568e05342cb6e7210ae9a36a69895296c344e9d131818b03636677985b0af03042f81d3bac0b0ce89d9202fc626e8a24ca8d6e610e01d5b5bd987a60bfc3f70ab51802e044976de6b09808234e9a0c82685c7d673af1a2249c8a4b515528266bd5296675021c310a4ecf73a04b7c78ff01ff20403e42a1a631bf061589fde19a56b6fcf58f06747c8408ca85c7c94dbb589442b1c708d0cc73439286a11b7e7f9740412332b112a76f168399eb7919916cff84b89e71cf97fb94b0695980eb7cd03867205e3999f2f87f83dbb63cd8617e3b877180503262a06324c909982406cab9fc6e37536a7afcba7edcc5947a625ab3a43865ab2705ee0bc59cc18bcd94763c02329e0b0a286901ec17e6e3a708106dfecd885756043fdec4e1db5802b956000715f58161e6a123ef54bc668dfb15cc10ed4f76133f94f05698dd955d40c3a821169d64252aa032310c6eac00847890e9c1e84ebd0c3b22a1a34040cb4419db11717c1f296313bfd76490b17bdf8c5606fa900b5f0511105d37270916c004f00df41c82d6b99f837ccec71cf89494aba8c603a0b40747e83719eb8ceaef2e17b6ffc3af5cec38ac9241ebc9435e37d0761bf90b54b956542cd253d7081ab0b11f126dc885d0114db905337f57320b56f61d927a6858c72d5488fe2b110b8d37da07fc90dcf68f069ee7ebcc31a8e3b7ae0abb27adff6c9597c7e9b7f932106718f05357deb22a16d78270f37c73b38487843d509aeb0c8d8dde96e2d18bf615d2bcf1869dff3aa824faa621c33bad8260c1cf1fe5311cdc66304a945640037c098741580b6405805067afd27743a957f3cf3e9567348de97e7453ac79f9a68490cd6447e35600a5f838778fe286a08446ed62f36babae4d6617e2633cef833ad9fee7ee7b229adfd939ac29a2320d2ec0b0d3f054069ed9ce2b03b456d75838dff67112ec3b4fdd736eec4e4808125a32a1b4a0568ba353f58de455c5abadfeaa74ca0ea9980a349119627db4ac393120051c15f236f7bee14626aa7e7cde61d6b3b592b98ed287a1a378ab82ceb82afdc440ea25d57c17888cc7eeee9a22a2c6d35ccc5c2541d411e2a913591c208c0cc0bdcca8eab7b088cbcb5c3866d9e73f1e54e55fee21bed5cd0892cd9466bce47a6ac5841a93ea916c1cc9d5d81da9aa210becadd325775481326350e4a93117447578207a84b8d444fe676054019cc199281b03d44a35fa6958a80908c96adf5272c973d094309153333503ffdb4b08c0c42e4e3f0f7505b6a98f456c0c5e85e9ca965ab2b0ca00c8086552aab371530d787a7c5e09c1f053c44cf5f125dc0138c89c86e6dfa9bfc9b00c860a227869f2fbca3306de64098bed71dc15b6be18cf125fe41334423b2903ac26e5c31892cb64d32e7a88f474448e28236f74df2bacefbd585a06d41389abbc541ec54c1745fd9d4cd5fc6c4561f048377055de56340bd5af104ce331c126cb6a05e394faa4d91a3b26596f5739f406ae129e7e271b84bd74f30bf4fa74bd1d04f3d167960b47668142232cbb9569f30d60942b99cddc1b906c37c8bc883c0b37f0480589aa22ec4e381727360e819a36b5943804ecbd6d6648dd14ae908e10556ac4d5a7e71922f1bdac47753edaddf1c3aa9d0f66152a3ec60d89361fce0fce12ee94f59e6edae1b3b399b101d0eda0a4e5298f29cb94fa2cc665e2db8b5ed78251167e42a4ceeb27fedc22ec390f9c80c3fbf838d61bacbcff2bb03a06a9c17cad4bd87cd500f2e3013b450535f95e90e521ef174c7571bddb1ad2d47bc9adf2cc09da90b49d83620c1d6e4a3fa421f8fc9689527a503ded912de684f26001ba970f590f85e8f9c007224069bc2d6a692ee5ac6a162360ba818287ee85cbc4a7620dca72a288f8a883b81232a294deda21873bd210860b4a55c0ff168ae901ec24bc957bb97a091c56cbffe26d6bd02b9f56e99951a55f019739632ed6df467fc7e5d8ee34e253e383df569436983b05c148762d64713726202813a74a63a282b7474cc42b6bc9a3a5abe6874d38155115abb4fd7dca8215843f6e508e90a71a959ee308b6571dc47c36c1389023f56dd97fbb0700ddc1a3f3e5d3aff3a8a15e62e97c1016a060429d79304bbced7ba80542e652089f73d1e4d190244eba33c7800222013dc6348b4758b09220e6adb7fff3ac291a464dd5352118e3110e4ae3a294ac5b8b58e7f2cbfe1bcff865f95b421a63d764e1d4edf08e04bc24fc3a83478ce01628729307ebcedfc56fbece3d62fb9cbe952bcb5ebfcc08a3063865b601f047b18dbed042ba200505c1875639891b3145355b28fdcf93aa4ab71018486ffdcf6c4a967a780436b4d0f08ba907866bfcc44b1a618f131dbede4cf21bf023d437b72b88b3889b12784335628901f174117659a075b2bc04850a6dc8beac8910a02670d0a913e21313cd00164a249f3a676d7c9fa34678ea4f0bd0c175a8f6e8cd5d1e70004e8c27c56f7d26ced41160f8241b5881921734f5a9c3cf2f0115b37fdbfa38caf760080008e91ebd008db8009644f70eb5f59612487232ee621059801696cdbefb0126652794c02b640e2627de0b88c2c0a609ff3a23693567c4877b44b9dbb1f50c311802209569eb9a0ad236a6c2c49af8a8a91a04934f66609c4ab66271998888edf01b9621d78b176a068e70e1286925a2d0adaa9b9a7e125c209fb0c3c0117f2b0e8230e759608a50fb4a6fc7cc2ad5ec283a994234c1498ce4f62d180d4db116e27030f98580316191b29bd920baf42f2599f49df2213d462a63970a07a5196a5977bb204c4d6751f49e7c107c9728343b4085d6693ad470a35b2f529e0c6e67c0cfb263820d15ee50ea29364f3e1b0f700ae1c75bafae4440774e850ca5c7afadb38d652a48bbd9a6ba17bc8b01711be063ae1ee84469153e65ab149645e634ffe9711c0fe8bcecc80b556989de96ce04d1018a03060c1cddd06cbcac002c60d308d36c46dc5f2cc24bc1b29092ba283189c2b621c6d9bee715d33671a1bd61808a9eed32579725a08db5394cc8eb6a1580077a794c21cacb174bde2ab2b897c1854949d69b077f3c1b2ea265a51d4ccd3ad6833749014026fe92ae18189ffa48ed8e4d52ce983370c99e48069e86f3771d17d5d1223b70b93ef5b59c3277a8df58a79e442f5a9da5867580cdebd76bb6cc9e8e6fbca06d08f87a71c004449187a466055e254d89f1b4747d392883eee99f22319cc56229e22fc9814ff0be88f4a1a1eee88f57417869718189605e2b945735eb274e42ad15708403b0091e5bac93dfff545365f7c6fee56ac2d3587f9bd79c39e8726ffe6799e08541731d4c856bf08f62248806947cc4a4aa953db27c6572af45a854ef374fb1afffd630bd881b2a099d25177b682d9ca12ee62e847143c83dc467b75b1d5c3047db034a8f5970d79259ab05cf26edd8f394de89b6129c2ca2a5095756c3674991264df4d6bd0a20b046632f098691a2ae6ac39d74b958767e17bd853495aed6fec17f1327bf002730ff1bbb0da0160fa2f9cfde1ca068cc70dd9b9908f0d330667a8fb538c802d8ddec8bcd342ce11827c8d43723617764296fbee61353f77d5a9da5419a15710bf820a50856dfdda49d082743142ad9f8d881a0f76d42578cfcbd58752f2e8a327edf6ed16fac59024f14c37c3dc80427261447ae2850ab45121feb91ee8399d5835d9145a90ff081f1c2f07a5382e4399fd144ede122baf4c68650c74c21748c2352a22e2299a6458be912f3f1c10a81e4a20c913c6e4f5654f393afc026189004497436fcbeb66095a6118d003831e58e00f10d6b5842bd2ebc736224113d9bc6a494a6571be6a89a67d01bb3a5c478e4fd533913146690860ec2869a84ea29199a0d288558a9dc8867988445bad6da28386eba43662717e174b8e9575aabcbec8ec9dfe1acedb4f4b200de5559dba7be27ac5b1c5cd0ae014efe5d19526592c09fd3b2a3e8310339493a7ced27d494b2dc1633d36de6aeff35f32794f800bba3fd4b87a9612986d9837315330decff9ad169970be87aebb4d94352f626dffda9d936bb4d9fe7083e41dde0d5f9980b3930aeaee584475c3b90ad44e3bb5aa895b5f6ddf289ec8a3dc75cb405f03dbcff82f590635ead3c84fe00b63ba77165b1fa41b0259d0a0ba9c5f1e76c71fa5509b06b8bd5ccac04bd20cd2d3d5233513393da03cf253fc5ca3d510f5c51250fbaf29eb2ee9cf9bcd4584a45997fe4dc4ac791650b4ff49ef0a4163964a3d13a709665876fbf0422e0baa85e39c10b2a84b2109fba88cffa6bc07a125a6b52b04ac68596af2099e84f119a2e2ca0cd0dbcb52da455965b12e325ea50131e295617cefc671e152780c3a8cc96bdf607b2c6f5184eea003445d013fd2cd6886f7dbb552a36bd37e3e8d5dc0fdb13f0fd1eafaa6c0b37611cab8a9cc4eb1076fe8ee594243123266e6eec3709e81c6f07c245c09ba572d5072d16d98394addc09c85d09f18b4902c47c8728bed90f8c4c41772e7d13505f2102496c0c43166f0e8c90c87c044652b75e9ced6f558ec1662258090be57b18fa10c716ca4e6654d9d5c88e21a7a272b1481c2f6d64576d06a8a3297676845b89ea895a8e691e562fd22989e74c723972b0888ca1bbceffff7c19137f943a28f8241b68c99db2a723c494c00fd7b3fa6eb029c725a4918039e32a89235e2ee5ea5813293ebe98be91ee97dd8bfeef4c66041028b114e6578b9c058c9d1328ea4b4aaa16e0d3018e0da263cf348d8b0580a86910bc2d3289012108b6bfba3252d02d6dbf00f4b552d044a743054c2ba6113f835ca1b7fe149e1618a4894114c5bfb518a86d9f00859dfbaf685f88d10955d673572bdb824fa204b47cb31e0895ffc0dc5e42f892a5f49019378b941824d07f1099835cbf1da09daf4932aa3099fd5ca1d6aea52af7c5c09202322a81fa4bfc87611bed546bbfa67522ceeae5023f22af2a923149aa5ade0d5adbc365bb16e13b534d7151bd1c869241e5fab4c111df0a3a3fbbab8a8a7ad35cc35e53b4935f8a3292b43cd384c586d133b2ca7818c228ed04b433af5b0feaee785a5e5aadd540fb142e785518f9f5cd5cdd0ee3165aafccaed106f0fb187262d2a96c8e572dc45a790a45aeac3c9ecc876f6658986f9977d7f8a0856ef5d8fdcc2ce85a49eecb6032a21ba655edb0230681e7274e6bffdfd0a99bfc7b0e9b819959187c62a5c6bbad72386172e0d1a3c01ca024a19b9197bd045512ec297c343e505e3465a9445ce5c149469ea6097b5c5d23d19a7a94b19e561856244c05f61cedd2cf9c1642b0bef9d2a089039a6c54b2aa95e1c481e7057bfa114074b001bad110d90057ba64559f2e1395b69c902d7c932c0b6f07d33f7fb7399a9bc72cb89696e3311282c39c76796e3ac1cc42c92c22fcb8c8d8878829f400d0aaac36bf84bc614281f7cfd6616884d174eeae97c503d2d2bf8e4e5954bc962866b6896389c6632b5a4197e984f1dc82fd739f03267b10bbd5d756f7e084da5aa2e9076c93fb3525bd6ebd6178331f434238ccda3161f5677c3896591aeff45cf4d0712a485eceea53cc1401ad7b3127efa8890c3dbd58a487da74e816d606030300aa3138f8b349af15c273ce5358a343a86693cf91dfcf467a1c14ae25df7ab5b0888be7ae3ea82b72fa273edf5767f0b45e7ef5da6fa05b5e7da4de77e0485bf9ab7fb3efddb783c414dd22530854895495909f9b2f115bb4428015df85b1089e14711aa071cd16817d058e1391aeb06388d313b3fdf6887aea6acc9c993d1e358193bf30d349e55239e4dd94b5f080611ec07db1e388c81e547fff912a645e03ba9d26855b301a12a7037d80cc12b952f777b4f6005764d25bb7b8c90b4b32c30969fcecb471787784242c19008d92a243175d9f7b01101ef478e1201ed781820daa21fc03cffe2a22d1067fb16fb27b4a346a2224a4edbdf796524a9992940134080108980836ae0ac2c2c969b9563e602ee8d6c630d8e66f3a1a9c4ee4f9d289397f077f41f939e79c27f3ce6c9264ce86bdd25feeb3ee49a13779a23ac2a499f97366fee4396958c0cfa05c357fce393fd4e49c7eafa37cce594923d4e9b5bf29fdf6fda5ea37439a6fe34d0f6435e7b7f8cbe827e969b4277d3fe9ab49d2a5dfbee6f4da0359c178a9feadbf6f5b9fc7cbda9e73ce39e79c73bead1d95a860489e4f3349af3d0de9b5af26497ff6d5989e94fdf6d58cfede2433f84fde8f243f4c5faaff4bde8fd197ba81f4dba7faa349d1d16b9fa219bdf6a3d44afb6dce39e79c73dec913b4459550ce4819e3e1038c67c70e367d8ee1168a67ffc4bb7ff2b4377999c8dbbee4859ee47528272fae4ca41d3b3c403b8078f4a783fc68623a480c81bb9be9118bf9e8c123f6ffffee233549a31efda2d7d130dadbbfc9fe9246ef2f83bf8cbe54e327d91f3d8dfdd1777f34f77e8d16c69e9a2434a3bf5f8dfdd1d7dc277dd892dd5f6e92f403715749e6c7dc9ecdb24bcd984ca7af5fcde84ddffdd2d3dc2f697f9f7e34f64b5ffa6ab2b7f56b485f5ad194be66f4a5d575d5cd2c50813fbb1288641b1285c4cc0de99b718545dfcd4df6f67dc858383921e9e201aac45eceee50e0cafe50e0e27e154349e55031c0fd5bdc2e073e81c3916be43f4242be57060efa74b2ffa7d32ef567f4bf9dcc28270658e6be30577f239c764931c0b3ff286754241c1d19c5efdf6827d3bf75ed5ae54fd912066583b5450eed4e86fec8e5231efff9e1c895bda5416ff95c350723147640abfcdb93239e179280474ab2ff4849bb8477e52e1a5ce51fca568843d4a3c0649467fa93edb1a73d8ad73dc9e3bee489fea6e6ea04c58b2b921757a58d0677ff95fb0e57f937eaf94650e800d3ec63e6151d60cf3e66fe86c0f3b76f081cfeccc75820b2b0106117902a9f5ed8e29d0522cb0ce0102c9f05b00996f7628c42fd83608ef7461fa979b31efd3efae987435ce16f971e38c4d5cdcdf6a6bfd1fef4fda5e63773b3f707fb4f6054ee97ea2f7583e9519ec6f4281f82a6d3bbfbcdee2d20ac1d1063fafd1f105f2c1055fe1ec1e872631836fde96364a9f667838df238c415ca9fd4d464bf7dcc3417c5ab4942b53f7d3f487fbf667bd3f72309fd1fa5cfde7a377b9ad297c51f89bcb81a79127f3737a2bfe9fe66fbec6f427fc3eda0794136222fae7660aec117b818bd688b30f82877f724fca594536c29f93177cbcf31764048306e4c810a1255c21858b9ff37299b9e00fba49d0c366db3da9f6c5ff7de2ccb3a99ed374ddbb6ad9309fdc6715c37c3cc5c27d3fdd67534c45d91a89311fd8639adcb7e1bc58e3e2389567b338db4c92e24c2a31a9ecc5bddae27f3b679326feec9bc759eccdb860a02cbdf70d763fb01ac49ee21beccb1b301a544ac058617f1c55b41c0c28ae8e23c36fe72faf8fe135f503ebec3fc3546eef84fc4ff894518892fdee32aaf421122d1c5834810c1fed087e4f84e44749936393146fbf88e136358316683b5a0fce52689e84b2f55c6188cbd7872ca5d88c35c89db4edc14794850dfd5faa11354adb5d6aff56badb5d6596bfd5aeb11b87a32c7486bc7b92769e84e4fe6cc93f97a32c72ce2dcf32cf290a07ce72139a17c0770b9ea004e1c008a00e4ec3bc04e8345c035c8e5571b5650c7b20ccafd1ba5eecdfc84c5d13ef3e2cd4460e0f08335cd28debf5c65bdef892cfdde32a2bf5fc94bf138cffa204fe48978211fc4f378632318a7c8911557832b3ad76e1911445270b89f0fd62e7549bb50cdc30d5aee87736fcbaec8d23a42a78808f62481139e48e1a15e0a4e4eca91065d4838b15d13c7659187c4f4d6fb576469d363f15644b01f871559da4811224388e8796289238a40a5e0b82a2527e5488a8ef67dceb581e2c1b2e63273b2732128b2687f3d17629145fb4d73610a51a5bd5646d65e8b4204b5d77e9240bbda4a4ed6342259fbf0354dc35a0b41b2a6fd89f7c55ca57de67d410d6a1ff23e260d6adf693fbd6f4983da53ed4ba355da6b2ddc644dc3c9e10aece7e5aa959d15d7ca122b45ace844f09f5869d93bb56ca5853fd807b3bf698f845252ac41d7d9389ddc1365144f15530145963ea9986415183bae566469d5122a245447a8745445a8605af45891a5503db1d25a71b9aaa5d3e04e834e4091d3200ae58fb32f9192d2c9681ff2621679325311121c5f874715ce7aff13592c17af85fdeb7d4e64b1d6ab60df83ee17be91dc6feddb6bb115d911c95afb27d65a6b6d4e0e577e5e3d2bad1557645939225c69adb446797a1f5083b006bfaf93b1ff7533cc8a0a82c30f66a39b010a4edbd9b2ed53b90a70448ccac882b96c8be107fae39449b6b95ee0dc2b699e8ac753ed984c27aa27544ea896f05ceb17aa8ec8fd1dfa18b743fff195d70a142b4a4ebc959d159e15241a5cd14941f15272525288443008d125a548988293c2adb0602f66557d1118385c69ddb021f2909c5ef3bee53d4e64e9d3ff91dcdf6f2482fdfd45727f3f9108bec690e29ff05079899fdc47f49fbc941c2f05c74b6935d8293a2948e4ee97f7fb1c1c40b9dba5d2899352c40068581c402cd443727aec49d40c89bc0170eea5f28683738f85dc79484e4882fceaf4e116cebd1ad93d94bc595bb5149c06bb56510df0fceaf1605d29395927b3d2120981a75d260d69cc5d7370ee99f2e6b2a2d3c9acb45e38035061d47533dc6cbf149c34fc05078fabfa7bee0bffa070c0542ed511f1e58da4e0acb452708c182962fb565a292bad149c2572b8d2729e1caeb452705c3a069032fdde0055c0e1015c26efba4ac632fdc20fca1d1a9130ca4fc9e4a820987edf12fb3931867effffc498edfbdf487c71018c0f46848891d117ba9122445fe845f811394cc149c1f960a78e01a34c3f1780ee4e4a2bbb28a0ecd6ec06ef3de20b0c8f6f7581f34404911b6604b9633f0462e8228bdc601072b7f8e47e8f8710264a20bc78f8b024f7d7dc4856bb441f2cca90ad500ec9cd630412f44f8f9fc2a696a15da80b7213c9618422f70378d824a7801b45ee2a72d3910f54f5eb2a97cd93bb7164712fc6bc68bf7a299a3bc31e3cbb7f37f48a7e51a52710ef0c678bb33d7ab48aeccdb48d83c9f136a2080887332463f4281767f449b9e6388ee324c7452d1402b9c1a974608d287038a7b748241289a44814b95027133fd387bb50cbd0ed62d7755d160a8542a04824f270c418e30d638cb778ba27addb4222aec3200871d10b678ea4de7e46245249498e7f8a27289d0c55d2205843a24e80e36fa24e66633512a9a3b754766da5a9d44ca5bc53299296912e89446a9224915a9e9821860e175028725f46557c7947344a00c9f265430427ef953166342023cb2f6cb1f111157998d8a24a0b5b609752c618d365df9d8cb689b6c0f363143dd9fef41ae708042e569053fd72069c53fd22e9f9985fbf451eca06e7a9802d0dc22cc033f570b38f1e7046892cfea788a33fec0181c3f8731b741ea411617e0513213ab1a5a7edda747a393cf0071c02c9314629bbbdf8c993eb1b32626afc4d1b12856a5109017f0e5bc0f9a9b47ce73a05cfbdf7deeb82699dc04830130cc6c2c92179f74b788e304ccbc503c3b303762fc628d43f08ca7b3146a1fe41b0f14847db8a47a39208bfb55b4bebd1c0006fd2a76eb09fbd0ef5473fbb99fb239ad8e06cb0bb991bef07fefa76f436cbe6d78c68ee93be1afca91b466f9f668479b8299ca08c4a279c73ffc4b36ff2b41f79d99f36ec752858de3bbf1fc0b7000c760118ef29d32355e7df92e8fd55447844123dcd7dd1f78bece31a2d6cc9d77ee439bdf54c5fc292256d44f74f4f73ff24fafbf5a3b1d4e380ccf3b76b5333a298bf991b7b336de3ba101544a352a896e82dc947f588c57cf8e8667f539f34baef6fe3fe083dfed17d1afbf7fb6ffdd25743fa7e84fe7efd9aecbb3f92d0841eff8fd28f42a9fed0df4fd184be547fa4cf3e84b1a3547f8a26f43990bef4fd48723ff435f6b3cf21f4a42755dca39087a9d4526062c5a8efe04c1b1c0ff298c3fce7b6e7b88be6e484de5deef21de7f11e11ceb4f1ce01ea1d9c1c7705951193990d2ce8878707c68f7097bb5c07ef47b8cb5d2d030cc86d2f71ee45792e775bef47bbd0973b274b58b7fcc7b57d992757eef217978ba777bc7b7678329999ecdde53d2597bb7cc75fb0c3fc853bc8551d7395bf07e93c67b9e7c4c28e0dc1a1bbda89767128da256c26d97dc7795c9a9badea9730a098bf6c5d1096309bc3de79dff197ff38cc63ee0255dcf526d6254d21b9f60b265ffdd3b8258be5f4db3acff4cd62b16ee3e4e46e752f67f9eba759f3eb207dd3acee59fe127219720f23cc65638f8e26a259cd6a157413d1ac662520c360f6ce47aab91ef47dd02fd5fff317e0c2a3877e691b57f96b5fba614c83067fd9be739427fa1bed4d2c7f912eff66b82fd5cf3d9015f734d973a22ffbb4cf3e99e32a7fed932c57f90359b58dbf34ebf3eae148f24ced598bc46a568cc1f117ce5d9afcf18ff225815ce5dffe2114113d24a75dc216d2acc611d22efdc5eadd06b7b9922cedb7f7972ec9d3923b2bc9f297b8c2c969b97678b2ecc12ffad077dc6f1ad8389dd3ad7635abe546b3401207a436e907d23aa055f27452328d48a1fa274f54f2ae16f2381b6a29edf7039672b6fb7ffd9bfba2917d7f8b55da258a3e34aa6f9fe6ade8f157735ff435d9d7eaee363baa05837836e800194307b15f9fc67ec5f5455f4d68e3b4ec6ffd5bedcdb48debba1db0d166c6e661a061a20ee904ca6be6e434329170f628de3de97ee4718f3dd193bc908e3e99482dd70e1a16d0cda02c00835d0085fa07c1961618180bf4b7c3dddd1d266e5f6b45655ffa9bfbdab6997c7b9a6c337d35daf783f4a5ef47921fa5df3e73984c7ad3cf493d0cc8183a884cea869393d29f7c4d7a53ca7ee9b72779a9fa299b22d5ef86d26fafc3f6251db427452e763b264cf274566c2d3aaf191d787274e0bc462f9417f79241248bf428aff4289ee947dee94fbadf3cfc5a67231d38393d3a7a66ea0793e3d5326f78bd708891c5e73713593cd6bf2fbb1ef3ef8743d7a37ea9d6486ffa9bd29f7e7ea9fe66b46c8b9d3d0de9b3efcf4abf7d35a72f7d8de9493897bc548bbcee39fb45107960f097aabfbda67daa6acf7df69bac1ff252f7b70f7de7a56ed83ef4a9fbe5b07de839eebb1eb27eedc5e9f5884d9a34b9420f99ebd7a3e7899784fe69fbb8e2e8671f57242f45bf1bfc37a28f3ab8ca5f84232c76219b99972b1483538c491b96c421ddd08967ffe4656f1279da87bcee6f8aeae8fb7a548f58cc470f1e31169c86eacf39ede3bfc97ef4fda5e83713fa9881ac5afca5fe0d859ec67ee8fb43a4af66f4c51afc4d9128f43737f7ebdb9b719dabf2b8d3fb0ec1077f912bd4ab6786a7461029e824082568245d353ced515ef6271ef7246ffb91172a79f84f9e4847d7f0e20a85729ae1e9f999f9f141870c527e20b23808a4caefc51885fa07c10f4416f721b2380f0d0dde8b310af50f8227d3d7f7fa5d3f1ce26af4cfbde6af72b36f31bdff562ac90d66e6100646c6d0413c8499210c0e7175fa526dfa52ad75b6594e76a999d39bde763d6c90b93e0e7155b2dd4ce9e4994cdf6fca1ee5abd93efb1a6ea634a1c8dea3034ddca6ff8a0e70e71bb4377d0ed9973e7633a7df7638954c2cbc300f1e82ec871168a6664e6f7a9ad39ba2d39cbce94d5f0d7655bdfe72faaa79da5b943f3d0dca9fbe9a2416659a5e7b1a9356ca3eae48a3efe6066b2f032db4a0a2e2820b2b2da87c5f0b2da8b8e0c2caca0b2f80a617e40b2fa8acb8f0c20aa85a79e1051054a96080410002b801822a150c30084000376eb0b00c60000420000c2c0260c151a3a7468f9693e76ff25e8c51a87f20f9a97670d839332701d15561e3e4c9ca01bab873624c97a78c0105e12012c855f3bfc0a1c772ee117098056553d04610b520b246c4eb68e97596f36774682451357f0757cdaf2247f103d444b58cc13f02c918fcf398c411468ca19f931159266a07587e8c3174e0664a190000207038f3e790d7ab1ea81160ff6e24f145eee420cf5622cffe4114797e8c5504b96afe9dd89b2d57cd17793bf32738479f7d3b3b248c472814fe9f2fbf99e3aaf92a25b2a019b3207f91afa8920f82934effb95f88b3a03c652ccbd772b2e6b2d8a28a5b2ae5c493ab3de4f9218df172f929dd414404153ffa9c4e3bc617fbd24a4ae7f6826d8bedb243b6b36b9d3de4f81dbdd0c403ca7efd707eaa866963635383ac61a2b20eb75e48bf739d1fbd90b3f6a7fdbcde0097e9c7039763e5c210dbe9b472d7bd9066ff9a85598e1be71e17ef45c2de3ba91137f39ff3a9b5d66d0edb19a16d3e3062e39c78ae9b761ad1c5d0e47e9b775223f0a51f3711be5c0d6e04d68488d727757b39d734ad9dbaeb7455fa5baf5f75ae93a9b4e6d0e9424174422219bc88e3ac0d1d7c4df273f9cd06fdbb9bc7ae069dd2964575794f94ca401d26ce8f76d607d4b78fd2d91082706ac0fda4b3a13efd5357833ff55396c33fdce2b306816f8091ea584083fd1a12acd260ffd33a4da5926603b555eba4d16833e1e881ec5e3aa77d5167837ffd5057c3ecac06e887efcdece5b64e0801f8bd576be2038511c07097a30f933272f83a58cbd18749189995d7874917f9de7b3f150ffcfb8141ae1ac5b028471f262f921018e7e8c384e7c11d1f262c7a0339e59453727e31973b19ff9ef3eb4254844be7bc9dccac33bb54073fe79cd3dd7dce39dddddda7bbcb3967cf39e79c73ced931aac06f81093ae79c3572fca2ec24a2e6452cf2c81de99238b1514be025b094ddb2c5007bcaef066292fb652c94414ff821876d933bec1b2161b31aa791b81fca1d27a0d882093b20920407645481d22087b2078c17e450be2416b95fae922dbb6710cbc8dd5d6389110ca115860e84b033831c4a1c2032e4911ce5fbfb0b9022c408e2ea990117341062d54680503a021a3f000da1e70541abcec9ed0421b99b0a1b3672a802c60c60004349182e08e38b1860c85a460151c1c5cbd9d74e269301461a8143540442128ae410e52fa817902bdfbfffe17c1bd3fbf9edf2a18d8c72c214d95a2ba9c0739d800343ce010efb0543d9d8d8fcc033bdeb2f0d837df19373642f02870d6b01bb2470d8b07eb54b88026a17984de774ac3b43f6c401c3e1cc12c716389caea385b858c27cd1836f540284ce0ca02081094c000595c11639424416be2f8e64fa35eeb715b46082236be67cbe5041139ac8f4513a198aad00bb61813c29c212a04c2f6a01333126a200d0032904210518558861831874e143ba1165941e02514896ac20d39fa64e865e2dd349354a29c5f43113204760106362843544092d56f4c176a13078d9104129a55d17b4d4c9d018d3d58569235441400e6fe49021cf5884f95d782105ec064a86c0aaf082065e9491e7b7c02c21499eafc3c687094590992fd809a40b9e5dec20d3177d2f6b73e4d046a892c31b5901408079fec538c8330966e4f9df2ef3c1227c9450469e1f8201819860490c709e604209a610062d82e30a1c8259ce49844c9f3e77051738b091e76f375e100182c3f7e20a042430c9f4332af8200106795631554e406325cfb74c2802abc6d71648327dfaf96c51822fcf9fb8c69e3c9550818416d7a0bcd83b993a804cb3c85415051c5e99a58f163088c17702e19b6519125c8c47244386ab8a92cc1838be8414c7a8584eac2513c3289f2c9ab09065592685205260f96d9f1f226d7ac944e107a39804f17902d0c6d336bb61fa028f72f4f149721a820f72f82ccce5e8e323c54914f096a38f8f114e6660941c7d7c60251de09ba38f0f1a274ff8f83459819214d8f004d8ccd1e70942e68ec81f097d24b19f6b1da404da66153f9bf93107d964453f9bf9a57290abf97235bf9a2438c4d50f11c425abf9f2e7671397ace48c7c1d2dcff0c9e2488e3e590cc9e1f693e5dfc8d1e708401996e54cf5648242617cf1ebe38b167ba130d7115f6e8fab821a8cb916bb5f88e947b33324c83f119420cf0f3b48a69167125804e11338fda24bca5d2fe52f73dda6d3f03ae8076f5244957c2bb27cf941307f892ba058d0ed6101c8512adf2008b6f427034c83292883e336d696d32ea1ecd95afe226de0da5838ed127d8e6093e56f45daa5cbf2b723ede292bf39d12e3d9247656365f9d3658fcecbf583046c092026624dc820276cda256c34821ca15d08c9f2e58d2247116394c850f6482e96a8e450f6c832641a32e450f6081992e50b72d845b21422877d44d36e4f4cfe2c60d321a45d2eebe2b02eebb22eebb22ece65b55c7747f63840eb64faa3413eedc2dad8201406a3e9fe66e89176a12deaa22ddaa22dda5ab976787ae88b02ae43a311635034c0a9d82090d58cf61b0c64789ad75f486318b03bc2e6c9af1e540f2aa87964f764d93f59364f960d94e5ed7195e4a1ee00d4048f1e6a7c8841597e3311633610999037e044a6f02fb524b3206d84cc2041b2fc5e22c6f86fa087376992e9f7f02669641ee2923c95b0b0c851891058c0725432042cdf9e76894a583c59fe55d22ea32cff6649ae91a39212d864d93da07f03feb3b34136c9f4db807f5f5c92fdfbfddb40c74c9764eac92192d520ab484b1c1c24728ec8d6912dd972b99048c99d2c9d6850beec2fc45942d1a0ecc952bef40dd6c208c4e022fa94313e0a85845676cebd236e245bfca812a51370e4d1a28c2c6d5ee40b6bc0e50872fca2d781698328c7772f041213ce4fd5a0e5f9f510e5f8318bdc92c3d82487ee456906962f73ec037cc6d93f544fd1af12c2941246061eed22bfc6b118a3cafd32c75f02f4094d343144674e5b6913d356da44134d58269af34999a095896a55d0b2fe76de6c3abdb63241fdda3a99b8191399c684e6ee844d25c66ced5af499514e25c6dc7b6fc41a63cad755ade2f7460e15d972a3c11cad6a15883f01a880d55616960055688e7f3146bd806064e9075562ccb5a1979537091e483484b4c8a0848b215c750613f2fc7ef101164b204308364f4c81b6e08c2372016ecb6c023d2305a106a0e08c1764b0338e740d38410f2aa725bf5541cb0f9dc5eb0b9c21812406d696984af0120345c8ab0a5a5801841578053e6814f1b1020b208831c4106230f1a080232063f422463072c728e408349d07b87d06d924f7904dea47f933c42cbf1c67e01e68ae5fe8df0109244fcf871c45557f7bb93ff7c79f8c0738bcd2864a37e30a1f3382aa30238c1214b028471f339030c40c2b8030438a520ece72f43183c78c9dead4453e41903a2a0b6cff3668b9ae2fd836aa321f6c30be777bf7f53e7747396580e9eeee48626d9bb79207906b0ec92ab68dba7b0ebbbbbba7bb7bbb7b4bd9dbcc9893a5255ca7fbe7bcfdb43d1bda861064f5bbda10823cbfce6ffadd52526b6dca0697f336604b95393c6ab080aa612325c523c6420d1b29264a472878c789a97402400038ef03f02f773a9391eecce89b7ec9853c5f46faa4918d0f7a11475b837dff908d264983c0fd5c64b1aec8aef6d5ec4a176649b9d55aab37a25ab665dab671d9368a24af0293ba1054ca17965e04a90be1046aadd35a21aa945a04433e32af4ead0393d21054dafd6c914670ce7e294390fba5ec50bc41843d0fd85377b4743bb8adc5bb858af0886ad99669dbc669d9e8dbc5f41f29904c65665e9d67a8c0fecd193bda2b3f4af9ee734e539537d32ea519fd4b6bc86e8c209d757eb68a9a7875e7f83065c420bfc096021172f790ee2c328d22d3f70bfacb05a560932311b263144c0e528c248870df7e4dfdfbd988a0ade004ab7e36f5ebd72f4a4474afc778e79c73ce9f5faabf98b37cc69311fb269d14f5938a6a4251940f0e5b5a6614a64800192820c38b3c555a482a6354c8f4afa4942e6922d32122aa4113a03097040e6fa663dc7b6d663ddc2012946709528e0f0a15364bb853f4f8c4c2c05400a1ccc8b98112041548a2686294061552e4107f11541801e5092a9840041560bc7652b0459530e565abfdb820af5f875794c09d235324cfef6e0699b9185706176423166360c8f3dd430d01b7abc1f93b5f45a2c1f9e00a3017a322cf3f0217a4041bee8b3c3fec82e43945649950607f2e274f8e08871359e68736eacb5f2a4eedf197fa135571fca5bae61492431b39e4625cd0e562ae1beeaa7e5cec052638ac3d5cec85d32e292f3ac5e6eeeed4ddbf071b7f5a1d8c78e5bbc7d9e4b9a591e71694a706b6ffc04f762fdc1ea07de16fdef6851ff0a8170291a9af79e1077e72f685fd77a6728a098cfa4c2f4001ab484a44c7566badb5def55afb5bd7b6f6adb5d65aebf6abfdb6f6adfd6badb5ed5598b56dbf2631dfda6b6dfca5da6aabfd18d69cfbf27e3344b7d7deedd65baba9ad0df7fbbd543f90dcf75a6badb59dfd81f676151f250466c51818b2ff060e016b2f9f3af52fac40e47e100c2c1d75b7dfb6ede3d578989a77eb7bc4c1aeb8d73c2d6f99f694524a35fa012c32fdc02bd31e6c32e56cec476b3f7a616db9aa6b4bebee06bba25a2d40aedfa5d85f708cc365a498c028138602963fbd5a82c8d236360537c66364b9771471dc8fafd3dc8a12586a2fedcbf6d1b99038bccaa455f7371ad30901c3eedf5b61d9cfd065edabb0c872df7ad2ab4bb89031542f228efb970991e5be7f615542beff92e19434787b22cbb55e5dd2e0aa06b9eabe8e8602fbd7564d22c6c87ce9dfaa936f75e55b6d3e078573bb06b93ec043a022df8ff2c3ca837c81f4b041e6fe66885963c0ccbc78e3c5f9c64df3c29b6d28b3b5efdd0c5df61525b0e710dba0bdbff6aec974eade1acb97fbb0c2b4abbd8eaeb00681ea9206efbf10052cef4795fb69a0cbc1c2dd7d6a9df9ad5c8cd165e853b7d5ceeb998a3bf5d9da94eeee1e5ac256b37b83fe32c6183bc6d831c6ee6e4f66dadd928b5c2836186b185c6fd2a5b774a44b6fe94897aed54047baf4968e74e92d1de9d25b3a9352a1a533694b47baf4960e778472759b5eed9dad9bcd56a66d736a27c073b6366eb6b82e345b21d19cb3150a8946a4e9530042cbbd1de66ce1d19cad1149141263a31cf5a93980861e9af1d05badcdd030c2de9aa3a5856af34683a0b6f9cbdcdf381bfd9271f7e39bb26fc795c14015f08e2aeb8777701b28142777d881817bb96ed3b2cbc53415cc215e34cc7740bb8cf2fc4d443faad8f88b800448fcbd9349cd4457651adcdffd7e1ce2aabf1cfc43b9aafefd5233f55338c455fd6a92d0d4bf6f5faeeedf97ab7bf32309cdfdfe1f3feed72833ec07e3aaf939c6c071b5f26f7ff939f447e7e209436c7c07db165bca96b9bb5b4623883e3aa3286eed327ac87e9e8154d92cd86e8c313611b6a8b28afe42eb8dfdf71fa6857a34e8d061c6552d575d0eb06c19d4252363503106114c381be3892c479f3176e68f87aa3a994c629357d4a05e6184c43e6318c938479f3188a049bce56fed75a06b9836365b64f1cf220eb7c9f3f351bf879bb3c8323d99feb2083a951df564626eaf039deb6fb63b084cdad243f3ebe1b97e37b24c4f265503cdf3a994a139bcd9b9dc576c5165c331057e4924ba4490fe266d247d19440ac18931b67f071d19885f477ffbc21b37b22816a3aff96b9aa6b956230f5c9e3372b35b02c0042819c3fc78481cf4f311599ae3e19e1c12a4419690eb2e8b642211a44f631227b250151378aa7a503f56fa6940e65c1ba082d488a24614a820a820ff9ef7059f17a8848c785541eb18a21100000000c315002028100c870382d16014864980423f14800c6f944a6c5a4295c6a320876118c520630c328410400021c6101a1a1a0e089da9041ef4f0b11c378a2eba35e8a898251c3387f9a0d07894f8585cde44c5b1be07af24067f6ce8160385cc199e2b92f045a2eea1d788a571472de67038f2e244516cb0ca1a8c0075ef7fa121af0f4686461978883f334ec869c4ce40ba22f401891c11316f1de8cde3481d38b010a7410b1486fa2704cd6196445c3c911f8e4e8cff3067a33e2178360ee3450bb68c1b8727903c0f99262f9390a02ec42dbc327a6e55ec74264e9edbcc9db2c4a45d2d83534c59e3843076fb2b2d6f7720dc2d63fc8da0f4994afa1c4a7ba2d6d08f0212e5112e5c5240df66fec702e6ec603c27f04cd10218ee85fba7567f8e026880ddf55e21734ea8779e102f12d394177b66aa73293b9b9700dbf5882703f2f78155716fa40a776da20d5b1e964849e1ab198b1d4517c5ed7273b65f8e0baae20275d1505bf7af636e25c793c3852e2f42e2e54851a62a597860b3d72d0c7912f8a9f1beddb81d6516cb184d0afd8fe47fffc2c59a18bf153fd00b019b7dffc175e40e62f13767c48cab2330827a911eb8d31814a6409bf7813b7a3f139f31398cbdb7f30bdee053c6186f4200c11d55a86b9a0565b54190b8d2c5088deb1993a0a5b08692ff78cc854c999f996446c132b684cce061d43e59b5491389f1c7c78b476485eb0f4c0db619d238f406d1a3821c81fff40f207478738bf73fcad83554cb5bdd83d28ba4dec86e6939169c836ec0cd8e6036071e1e5eea37851724a68332441c7584579ca627da682eafe79088004eb68d5bec6502f5af0fd9555284ba8a449a00a45b4550197a56afbb0b7e6575c2f25cb1892b5a04bd0e593764b9c3e7909d63c2295f2c40d27a03699104fb1e4b14b3d7f7985f9d10e6c0912b98f3e4c1e670c35ae8980f9eb0a3871942d32cd0682a59c2100b174129d80229106ee91a07db508ac07a94159bb951eb0ae932a29c0b4cb0ba533a5bba363ab30cbddce518d56a3ef9e7e77eea491958fb6095f9380c118733687f4ffab536a2c37a8768aae265e74e8d5421a49d0dfee4a524cb8038cfc23b723e62f8b9a0329dcebed36743d48f81b8672b3254c3e504457327f199e3476fd3314dd6fcca7032262729704974998a82e84837621c8534a2a6fe8bc06f4bd8e206bbcddf8bdab6a3b1d3a3b1d7e70e42dae8c5175d732325e40d265469f242d1c8edf34472e70cc278f9882c8ed8c62c335d092f270abeb6d5355cbb7229b021e84f4b577f87eb7e67c8c85ed0fc938122ae1e0265929d077466ab9e04831ebf953fe3b744feb9f4808d298a65cc04fdc92fed08a0f1e1d2c28d75d6679bf361a9db44459a452982e49310010f890438049ae8ea17dafcf2c85371f8c38b1838fcd48b66832f3858cf24e51614caae0e3204bc0f407604e8bea90ba34a17728c062412b66384464dc43d094655764127228ff2f86995c6d3f269b066f129c688012092a366c4fa0892ab321291bc1d99322a648337fd80db081c2e30de314c9b89f58093d0f676f9034f2286e9832149aa91c053192be6625b650aed1e8934452787538114331b568184d6de30a7796b98fd9ee71293494210ddbb471030301197cae9ca59c91982b999f157705c125bfa66922bff9b85e8cf89bc0e66462a36941aceca474f3c131d86fcf8d855e315764c114264b65e135cef488ef16b8e4e014ebd024529c8577c55b1fa4db94be3d39291ea91140d65c34e817349a6c65d7bc70f247c9751a1f8c529db6d06b2df2b5fa0dbb0db69b013b7e135239336adaeee97d98e099c14767481b76f9bf5bfe5c21ab8359d6e6dfd73cf6a341e4030bda34d05e734d24965dd57e1fe0e17278f98e0d9feb2088364d15207d00d3d709a28fec0c60b105a347e9ceff83dfcc83466f14c617db964bb7889450abfb41742bf4d3b479aa7a08718676a05ea2fdd9a49aa0b6c866974aeb922c220121b3b20ff2bdae0ef6c512cc20bdae1c7f49dd488c1cd1b1acf4c3843550cc503f739df9bc7709ab3d017477c92543bb4743e262da49064b9f53fb069a373dde459428e5f92444f1859109e489fe2f7de61525272663aaf94e96fc21bcd094a25ea25c2a8b8e41ead722a1a1089d7519724821b2439fcb266c11bac063a2a4560c06e0bdcac83a78947cf1c7e3b4fc671f32d33ccd8a3f4e4608f9213bf6f55c642060512d2edb0859f40c29c8f74e202b18b52aa62099466005c339069d3a9b00ca7572471ef4f63b5e7f4593e091658b5d2306f07fd8183360d63b6e1aab7e4ddc1b06e25d950e0d3e0104b08cbdd2db6845c28d78751778c70f7844ab178f9141ba7fc8d3c1fd51feaa2c55bec2547f8d8171868fc4b60a03140974ffa38868ce2a380126a02f107108414fdeb81fcc562674260a9af9f0c11792f6688347132b0309e7a4418d59240d776630cd10b93a0c92e0d32c463ad63951ef6db0432397483e1c1278d46537c92129eb5cddf9ba1e1d23a278646eaa4e86a33564ed3c6d448e48ed5f8fb176e50fff872a7c2bbbbcf630c01a8c4ad209536ac957b7114b4eee78ba30f4b4c6efdfbf90142242c9d13d0c6bf8f468b93790766bdd38c99b37ad40e8dd74617fca4098dada6832d288f2509ba935f5aa809cd482461b6e673d40ad09c4463df96338193f2c68ff60eb0eaf8399db5be120674b5b4306f665fd0ac4c6cf023c5523e18a0125f1bbc36d195b8e298c0105f2fa61ef719091b3f2495ac6440350270c078568b8da7069a263a4d8df446dcf54dac9fc73328f9a2ed805d3bb7e8913cd6fb0a320b85d52c4526e8faeb940090f4c68856021eb113fbb3759c8312b35a770d771e447d9cf587ac27cbda1038ae5677e4618942294ffc80d5b4002aa08e9474787d8b4cbe05f3d76068f9276a3996d98d927c98af16117bc5be108102b4026022348787d7357b1e71989f2a781fe72b42590280b95e64ff95fe1083ae765698b1fd0a653708ee6b124f1d42f27faa1ed033ba9c6d949a6acbb93e280dc48e1841a07cc2eae74ff9eed0634e0fabd354f78e64b242f316b832625dedef8d0a0edd258c7596a3b3c3dbe91d2566008f02e11d0f085104526e793315b0e38d4fb1fa4aaf2369e66795b558ee3b37b67112361a502fa5a58dba178b2a25dd84c366b1ae51e73339986e21a0e6ec2d24c1e98c813745bc9c0e6bcd641d7f32003b2fed6693dce51205e0b003376c5b2b7d3e558bfeb2115c9be88cb08aa98df22baf49321cc1f8425611a662b811f609da247d37945c99e12c25850429575617dfc82fcba03e7e0639b95e5b7566cfb4ebb794b9323b537bcaabc80b693083a683f59f3f23f8d67a44d100c661513fceb43148d14922e180148366696049dd66a32d05523ee6511a07cb544143c33d5c2d2aecc7a14b21cc600af41d9e708e070011276ab4fb063a8a8628198760110269d52ca7a60f45482a59cffd7176816fee2a08c12fbb1ebba949d06dd3522fb3181a3c60947bd7f20748240bf3fe859183f931d71dbafb43b60316c9af05ccbcba94ee00a492d36c3991e8142d2818335bddb0c14349dd9cf47b2e7f7fd4458e0ffeee60c568febaef4f46fc374181473102d15f49462f81c85f39b558b74e945841a349c8188d7243e9d1d7a6a54391db6ff25e3dcd0be8a5b36889f91db4ec9d99622ca1a7b930f4a5d0bbeecc5450269e0672a5b0874fbab9e31cce7f9b2e9e1482acb20d42f6f447228f55e2f3357eeadf21a615d1741c5595109c393645411e6ce39473eb3c9aee4b01dfb09d2f31693d452ee7d1f84b65fb5751749026d29ab26316363c5d4a724c5ab399fbc25b6e4f1968a1481fdf5a0b7ff436b537d61aaec2dd8689a7163716b15e89b80c55a75aecec97aba070c31b5499f3ad802a559b1f4065953f91d5b5c34d19ca553c392ad5b1ad24ead5a7b817da86a48df6804145f1d4f4cee1248403528a62e13e097c0b5e46dc823770ba57b407dc8808af8e5f854b1de4d249e20b057f60d6152789f09abf239ae8f52c788725574e3de420d0f8397c7bbfdc7823f08c229897a9ab0f5af4e08a4ff4ebd3becbf08f2326bc55107e0181d427d65f73f4946700e8bc5addd54f5292eab1d1eb2b0040b2f94aede97855d4ca27e46aacad632baeb61edd52c3d96d1ea222c7890a0ead58554b3694a4cca8a08f6769a5011237b4260971e7a9ec8bcf287194db9834baa2899024d14167912e9538b164fb32029908026e400c418cdaae8d2e91bc5936c6c304604a5aaf24395145e1ffa49a2e1367dbf734347a2934ac6911ba8b4f13638ce130ce35b92b4d4ed34b80fee7d0326985d9ebf95e7ee52319e1c4216e1c73b8f6ca237108118ed764001976c3fba972f6592d2b5920603fbe93eba0ea9795304ccca5766ab1db4f829a9100b80fb23d8d9b37230ab66dd6b6bc2f05dc89f4b0ffc6854542d624c973e55a6a755a5ce73344969a0244c16d2eca67702017608f5e2671d7bf4b699fa6cd0aae9e4e9bb4b558f60a96f8f111b4f15a6b47a950f74b827abf3062fa544a3068b83092e07ef9fbd0a3a842cf9f18dc730b69cbd19060a9a965575554a988f997b2bc14a646510b200c70342cf6a7dca9e7fef81b2acb8e15e15c1f4fa0c783be3d88229a266530d78052bb1bf463c894cb75fb8e6c1e633e8d61924ac6a73d6521514595ba9a20a07714bad6c915ca5506740dd821fefc484e100d44d05d74b6aeb06f7ed7bd22c68d4cc3cf86b49f9b845d713c22e4e842b78d25645a0fb231c7cd8b5f7cd8127a7edfaa4f7c53049e4a4f5e50bff9dd57dcb62b809fd19945b0a59b26e04f4b6e126b1fd8e8f8b4261be4a503ddc47ff4cede3701225b687d4eb5c24bf34549d40c0d08d3cec7fb7ca80f1feeb2deffd0ad47404cddab88dc2b57d166fe091d9bee02be11a5e44155e94a269057ee844c1f2e5fe1cd2b809be16e0373839b6cbd9f040e11b2a5f8a3190b01cb1d55a08f2b0b01051ca7118310cfa249b7f8309fe566b8937f54768b392eb18479d00ad1dce146aa35862bc146fbeecf1945448df253102d7589c343f1cca74c9f553a41cc054aa6ad5d677d1782a84552e14cb383a9d17782f28dd31129d342e4ba60eebc88f8943364375fa2b2489a803608cf6f1fdda644cbd0bd88b979231e481c8680640e856b039de7b0ff2249caeed5ee0e676858568a4a9784ca5963b108d84680c83c433d6a42811aa6295bbaab2b930d2ba3a40cc8f7fb8a9bb0e69dd4f2abb3c4d21f1e83d4098338ddbab0ca37aba89dbfae3492956a10942b076d7c9f06c4ca834a330e41e1d1edb5887268b1646e256633b776edb009e974aaf663d60b33d5ad49695abaf24056192192cdb24396c41f6a4d9d44b9f5f8b3d60878c873e4abbe1f92d692067c348b8289ff44cc37614dd1ef362154bbc7ab3021042a1b519fb2a0304357baf02dc67aaa3acba45f0dc521dd743760f430e76e077f8c56c5ca3521357e06849ac58932c9cc598f593f5e63bbe59e459545abd004e804e1430c81902790f088709392a3204ac54b12a949debc04a50bc6767146466086559f41742fd9634719fdbda8b3cee71d2c1434e77864100a2a9e84778e37c01648031ace131d82893cd346c4791aa6a13a76e09c424d970ace2ad0212e7137996e85c5c53564268b1564929cd047a062179713f460a0c79a7d2eef958e23d0a6e0ed543c1e0232c70cc9ed39be036c334fc2288acc535a702bae717a8abec87f0112d23f4fb12d14a877b526be2150d49e4e09d73b4f1f03bc31902bb34600405d6db2c22c258033953d8381d2e4bc656002fae6d0cba800d9305b86266ac0ee419471d0d269e9744ef04bac18766b4b2d1781bfaac8e92ca4aff2a1e384de8485d10eb07916b5be409b034df714400b526fd27ff76eed7fcc66bd9039cfcac6a104e6bc2bf37023b1861f9944fe076b08551bb88e14eb63a9f2e5928ab8d250944743f2f322b97d15a9e849a63fc17b0e2f15ad175f97c5b746cdb39164c812ef6240a602edba2387afffb8c3009568d0375d6b2c68766f0c592b5682611b8c50eaee35e5a43a40a770ad6bee8d3508280bc948e886b8c9dac93e9656cd80dab46d0efc2d458a21dc5f9b966d68f4c362e273f91660209b54ee8a65003e32d2f3155e1268b8da5395bcb43b0bd17dba0c3cb3da1d36ccb70d3e125f2d462744c9cf12416506e4c676f99b4f3a06efef16498962b5f486350600a4cd2a062b95c072dac6b32120efe5e3638055dfbb5cd3e8f2e2f7fff39839a2bdd7b062d2cbe8f77e39ec14a2df892b9d8952bf6f7e6a36e83a77b3321344cdfb1485d403deed6e2035f5b9dc7345203050370bbc9e7126bdc66e38603edbc57fd1590d47633c11ab466e8d192af259a313839253b0f08500aaa965b8c46df54fbb81ce6164e5daacaedd3053716a5407cc8123770ba6e415ecc90f94268afedf6fd6b574ce58cc6196babf0d9d6d74aef7785e08d9605eb794ab15c143e8bdb2602b4dd9fbf4de450974148d6e378e4aafd0f64ecc0fcea23a3d13937687a17364777fae2e870e033302ebb2a5278898a74fc9e2e4e29598381acd98e57311a3aa56350394c2a881194d0d43cce2c376fbdfc046175dcca98a018c5bf62a19a5e80ff63f36854b649873a7464c3763da9fb860026b89bd0db5e16a60e30ce83819a4a5aab43ae53bdf4d0273d5f9f4e6cfcbaf9e722137b9ea9287f020b36c0f2563700c9f4b82bedec2238b2aea0681ecd4584170895f4c8cd67a05cfcbafaf7e50576bef2004e3ecaa08cf12397c611806b4b139fdde225c129de369cbc3e72228cdc89d3829004f0d06c7c9138b84df496c40e9f6d910c654c9ab464661b19cc807bff09b0ea2e5f986ab06d8924a075358ea9791d5897ef2045857f9234bd4ad5e36d35132e51ac61d4757bebd54d8263848b24eeb02efaecbfbff72cfcaf80c7c3f2852e5f1fb6acfa93526d39bf0c0310deeaafc49e50eb36db714ec1a1886e70a331417106b18a8405b8fb82b2a1fa0dbc369caca8934b41eefc3dfee01c2a827bde2a3e9120a21d38ce39af42fb38b1a331e01e29dfab3006d03100716a69cdfc3ef0afbeb70e5d94970aa8f0b876ab487dab83d22387e762aaa091f125bc4a2b89c7753553d41cc281559a447c3c4715397044c560035f277402eb425b748f2c85eee310aac9e604db7cea08bd4b3f73ee426bcb0608994bf069dcd83da7f8a3a2395eb11bfef7b6d138b1f8a798eae0cfb75ed43e01c6adde41f7a0be6bf135bc11b704f9a1ffa948e6ed4144ce8a66a4d843b1334f2fbab9af63dff7d855d2b2d7861602d9320259da865163ec675bde9202395961524dc1dd18fe90a53e2683bb74e07f5c3b557f1958ab2b4454e906446f4047fcad0fb80f0b8050ad312f4bad16b80698eb097f8a019d8f49337f89fc46b1337b4853bf668f1e36c8059b131c143c9ee6759040df5890c259e5a477a5c1b83e7f28f8cc8970757da6ebb1216b7a681793ce6e2d2fa6e760e428f8b27faed2895d427a9f162cea3dc0dfaff481ed7f323c250a06ecc861a33eb34000512c03c95b447269161995475ea9064149f25466d189ae0fe53d203dacec4ef5158f72c922ccc84a66af5127db30874dafc6d7f7a4b557aadace77808519db1a2f1520fc7f4499db4c5cc923ef3c6d9c0f5a7053fafeb074fa75f485b2160b49cf930515c7c00947b441ce1c8d32878f1d087b40748788cf32bd8221470eb9e4205c09285b18b49f223f10f7a8ac3a44c331fdd591c01d21aa28d1be1052698a84714b701f093d81e18744538b64c34dd335be27b520242e5e38bafbe4b7f62533c595adbd35fec3927386745a6b1788dca53f5ca64b206d77e252a3147bfaaa962cb349b1ac9c3d165613c656179216db8860c17d295f8731febe316ae58e71f4e4b5ee88396bb45dc8713b2560d4553ef917311c49726e13dafc2b2960a5624410d2911b7b7a597a58f5ad2774d771fec7f639c2c52634c920d61e01036f076739ddd8d078d548ed87a68ab741f9e53e517773f4de821516477369f32ae2876432fde88e2d7083dda3cb08462578c99a7f2a46b0e2d2970c063f9f7a334e9e106a43c406c0a8115afef6c51b5db3327ef756fdd54c7ea900e298a141e64cfeff24ccf6752d21f9ebc9dc619a3690e8f1494b05e40c3fd07b7d08af6319358695c14f62cf450328610c73eecf72860fe08b102757f70c73e75bd59a4b701bb31aa060cf964f2341c8c4f20ed4d5ac4feda2191a151ddcbad56a199fca0c8523da5a74b373bbb465451c49c61266d423309ae5ae78e60983ea3470b2f081b33cc843e3427e65a230382f94b7828fab481e4993bab2cd2cd6e0f3e921bfe56e27534623b38bcaee77e7b33e7c51b92670d6686663f11f749a64f727e82f34dc926ebefab5a7f189ba06b0eb227f549c953e643b1a7d25d6932bc032a8b4d69293afe12020017b2f6ee8401efe6dffbb7d4bdae39a9f7e95ee5756831bbcb037c58d2ff69af1325bd2ec0b0a99454ac243361e824bd92f7b36f090fc5a1ffa739bd418361194134f869585eef780b4e142d58b78b0c4186a0c57ad32d74fac9cba35adcabe0e3133d5f6fc640308e268c6264b091afae7220a51ff57139acec8964c105872855e6024f2fa36eaf41c19c853f2adcf2ceb9142c1967f21b7fc3f4316e42040029e27220569307c0633522cd372ceafd1cfd04f2014979e60183f81c4d0ab75c94952f4ba4b98215ae0864e1ba134db8f3daa074a788f6ce23fea4fc4b434e26f691622d48371937322ca9756ced6d746f7ef179f5a6030654e0d36f6c8f614e528edc68cc383645e513494361a798fe88f912b795490886670f9bc039ddadee0b231bd8069163d8a0ba810c948cde316277e80aa8c590d37f33bcb612795735e81cc66093110be62ac07643d37ed2b153b01bbfd59343867c58db253bb7dbf320b79d8eb333280752be3be0e8127d5c7bf34f61b9271d218a2095ff9aa6ad6bb135817a51acf69c0e352dae4f7271ddc974c90491b31a82d13ecf4ecf35b299898ed291f9af45e57ff25631398e8de5b8d38280fda25874b6cb55d0be224fd655694f40b6656378ae54b17668f10786c1ebb5e53c56f3731dabe9fbdbf297ac492c347316a764386e16e7e37ba2651c6cb93c810c2c3c1c3639ccc05f44dad9920297be32d686e0b346eef8ad1f858b891b1547ac5e69d3bf95f83f354f76886122551bee4d93e6de782ad190398e516a9daaf4bb52c4a7f95771f9fc05c72cea445588182970a5a5d0120c2e11a457cbe60f4235806a561575ed0084a0391d7a904274fb6f9b3d9de4456470a19a637d7ff47a2d221843544a538c395cf00628bf703504fef7096135ae0a22fcdb03c9496063fec5be03d5c3d885ec32af7f0825baf9cb2696b1005194ef1d786f51884fb03d7ab7078c36136045451d167246bdc406b35c1f29a14ae052e42c925a3083a2b1edc41d6bdb598ead0c2affbb16e61fbec844ecfe509d4e07cc313b434355479574e28660b432748146128d5dfa8fcd4500e4fc860e723d83d3efad806788c30d10a9229006b985d936920784806db2f89a03b0bde20782ed49257896a919629d8e9cca7570edbb3b01792f303035e124a6d5533b3d36ce925b33034b28b38a5ec373813c7ab2777d5f5c4ee39106ddbff221b69ada283625c029f9acea285c1d8696886941398805e34724e39032c813580763a921f64b51075b7a0e7cc8476b1fcc9d437e6baeaf5d213b57509fcc0882766318970f75174b99d26642ec2ec28b1c0e11fe9f3316bdde194ee12fbc72726325a1a76c70220730c9fc487c9b1b56df410ea5fa82647c24664dabc854ae69198f95f25c899f0826511251034b1ea4f886ccf317a8736553c4b8b0b0c4c5c069158f81e1739f6403d97ec029669c4119739b7e542407417ed6406140ea913684ba02922472c1645b3f08b82e380dbda77293a21e353aef67bfbf40b0298951eede4010314d31c5177151ae14a7c774c29dedc5ce41ab78ef91bb705aa1cf1380c05efdcd91752b599c5a3dc51e65984f649366f217d494d9a15d9e768245e7bc874aa7c3a184ae3a4caa11086c0a4e79bd41f96fa3bfb5e93b38314a3e6566157c17b0fd64208b02e32bbd0972d1aca2f2d334c163bb4b2f83a52b6950396ca9f27d36069d1e05c639b6aba73e7f2b155700af1cba73a7c400fb205c23690614d53fa818ffe435cda30489f64054a1835cc330699269d8b40182d1fe66de7e89476515a92b0ebe47bede836fd0e0013f4a9e709251fd141b33e2bb498e8f4792437d14b33b0272768f835eaf8c31488ea17b7b040dfcc483c72d28938c48597a7c393b2de90c070c1d871d08ef4c7b68438cb652550d4ed55a0949553943d8e0f8e0ae51559ed7b3f754d28729606812ed739da85e08ba3950fdc64d741f486703a5b06599e87023e5726b6ed80658b75a29665a103c4afcfe57b222637bb1f10f36a331f282b8dc9f3357828e45e3a3b4feb389a6e834ba487b348e5c2439198349a5fc1504c0aeabf4079d6ed2642be611dd1397aff84b6575fff2bb4584fab9e25549c6e3bc217fa2073a27ed342053bb84f36c02c776d501cd8d76d3e827260a547af6aeb4ddcecc03bfb7e16a6bf6252753447757ea44e08368ec90720dacf685ab335eb6875f64c8cffd392e0c2f7542e005ce50f40957fac43667f9bbe4fdc6368a68a86612a5473ab4bb1c78b586359fc297a40828681209c1c13a6ae8a18bda3a79f389066fbb5402ed027cb5336b937d6c4a174774ed4052b94254df859e42dfc9b1d7147533fd5c3a18245bcd539253458f48be05149ffe7a394d0ce6ea20cc9360427196f60b523e3cdd1f86fd50216c03a6c3511468558cd5375d089ab53191145a82584af0250cd643ea5a786c12581928ecc5191b1889210c75c82445b61644f549f9a82bc1c0a846390d62ecd31fd59cd1c9d6d7d74a4eec47c2e19168027c5d3740c80b9af648bd269770a24f33ae0b208cd8e32c054c42fb7d1efad27cc7804512a2054a3b56ea1763bf840bbfa1b1c6ee2f4a9adf1ce96228d9734ffce18fcca96fa62c229a9fff26b015fbcda589b437126d3ab324a6d023198b4a55fcd6546c6a3a7d0a56cfe8e79b7b1d2920a47947c0912e1c62665ffbe07856a9bb83b1fc057bf11ca8a4808300fb03c72406a2c72715dfe850e0d39b84f054b831a770b2f334a81aa3a308807f19b1497a819532d0ac1f2c01e28e3c959b4c2aa8c513e898bab069cccebcb51a631a45714c52a638eab5d894a52da290a784ed4d20943a7c1745d440ce42696a10f57e7664699d17e61c81ba4992531793638587b93ed58e8d3b3b0cad3bbc8c31feb2d0b3066e63547ed042e440007a10ae07144aa0e2460331941bd60ea6c06258e99030db27eec35caad4177950e761ceb062d9684869c9bc51a931ab0fdc0c5d4cef18a9ab58759bd31ab9e5a3f304f1ff3ea122c86920fb88660f6fd20fdc5d11ba986173f904b78acd7010703e80269dddc576347c4e25c6190512c84403cafb52518703ba2307a15d1230b5c9e9837cbb52f99944cb3a26ceab649813021a48d60b23b5fc4d7e18cee11e008fe3f485d9d3cc0d8e871541382829f7e6733b064ad07b5da4ff8f11f43b46f4f8d5ba895ef26127c05358a037060516f1e0124b99b3028bd8e40e0f066a62d9246850f0a74395dddaa9dad769848fb04e41c2ce94f759800156a34d29fe73f3e1013e18b1da3848f3c64c9710de305e6341b735e450a74b9ea8d840681fec408e83e1c43fec99a9b64cbd244929cdeefe1bd9f884fd76f2b6da8636e150207be0a86742f19b8a3daf198913052c7ad6365490495b990678951f3f269d68c7b4b152c43864748f118763706f578bc31e56548a31e69d31aa4c89975fce79bca05a79e3477a73898ae475dffc503852f0c19f9e1c83505ef900948290b343b27c0779ef11d608df20e3577c380fe9a865dc72e08389698655357df490509a8cc184f5caa493abe039afb57c35e82030838b417f56abf4932fe1250027800407184da5229d65cfe617a27544af41145491c288f8f15f437d0b5c6a16276640ba84b505c705a4599a915e2468a78eab760664e5986008c49a7954bc341f219d02de98ceaeb2710a1004e7b877b88d2a0d8d614a30696e8e8753498bf1aa763ca3478d9941d94b860a95a408a3f244481a70f526a89b0787891444ecf6dee0c5ea1392282008107f116b8aba8a4a8f5099f0649376b46349831a5ab9fd813c3ef8ca27d47302db4da6094ed7e1107f6f4afb2724e1c424347916b0e93a357359bfbf6411e8eec81295a47c21198e3d319b4e43a97ad5e6033cdf667d0558aa1772b0f57b915f38a531a8e59b010526103461b15f6e8826073a30dc3c8e1c9a3634188104bb40724645ac125d88fef091080a91dfd67c46a6efa6c10743d8ff22104da195f8b96a7a66c8c87f854592271c90a729c92dda5d07c70211346c329cf7293304f03b7ddb9ea9dd94025a33dc59a67298ef05a4eccbe73da2af544404788612efca1c8c78ac11d32e6212be4470b4b96e193ce90756c29108a8b739456c4a82f83640331ad4f9daacde31c884815cd0be88115fe5c5da25b2f2e4b01d36f351644f2038916654c4474651c025bfc4b7d4962098091bcd64cbd52e394cfd6e5c32c34879df39538808266aaf0de8559ec0362d47383c4003ceca68c9730f9773aabd7a5a7b365a273566689c441c92fd0757befb09e80be057132bd1af0884d1765c8a262aa603a158849a3d88546387733391a36a19cc892ad0f962dae290bf970e74f7a31dc3ec9ac0f8ccb5928e904ea86449f5b67d3e098f8b1bff741734937916a6252de992205cc3717896ba67362e604613a58a03c935e82f87b04f7ff07722a84ff29c8d8eb61e7f7443385940980e0d683bbe097880047cac981bc0619889a6a2d5add62112a4e739b02aad14477046e870b09ecafb7b7b96a9132408cf9741f7ad8b95aebab8199a37a33f1482d6bcf02bdd0841acbc79b3e9be5d04c5650ecb50276a8f3a34c787166a022b6327bc4f76c4a87a7c10d7ccdcd292cab63366262941e70fe719673c6a2e0499300b2c9c9f519c3aaa56966cab0c0e53b0491329cfb21a23d965a81ae20023e1394466cc5ec6c14ab38897068ca89b3d6027388dc57f216c2644dd1c14275c49b28a02e7482a8e9e14500ffb60cb7d4ba802a0f24b7b5e451444d4bc95ec332e8812daf699bae6d6c0f531d5a204c42aee95c66d5ed62445d370a9c9f4a704d2d410a2e487ca8afd345219408550018c60a3c0a9e2118bced5feeedbf958d7ff674ac479ecefffedaf2a63dcbf2194c480ddf8d73cabcb0b8175368bf26300e08ceb223927e70951868ef1cf2cf7b67be3d9aed6222d7302a89089d19153307c72340e9bec6649f01f7b655536a1448e834438d347d399b3bd63afc0ac184e556591612a1662b7f7026d15a92692d2d1ef2bcdd198de13a50450be52f9ae3131b3a44052457b35cac0778020e4bb6fbec0277930de5e3bdfbee1d1d16437734879e4bdf2f7ee0d63d67a5faec62049fa17daa6e1eb2f83ef410280eee61a8b4414b8df636347cd8b6a0d28b7a163ee1dd601d24d2aa5d1588532a876ecde0c9efc52610acb197e5786351ce14c3117d8ec3e04a6e24bc91ea47d7241a7ae4ba4fb7a520988944ef2b628372bd52550913d6c016e12896766c3216b991945dba0737e0e29e0b8ef0ad25804928e6dd0cb6baa97b4ee1c35a8ad620a236a50db6ecc1491e3f1b7b3ccbb7ad38de70fbb9a35549667e19d13e4053f27f352cdf562435a7f8122a27f0a398d0467288f092e04b991b645525ad3c9f4bce3c2d3098689fe657c7a03050c3d8d3a3ce913356437313e3c47a5804460665120e5ce7a737812af0b5228b55fdb09272feaa2672b3aecde0fa24dd2796781bb51787d8dc28b508a436c56365cde8f26479c6746e69d2ccae69210604660f70d4dc39ac375b91b0c43a5e9832ce5bec7c59eea51b75131a20ee26792b959017563586f5725f2b1fe9b032e15939c1db83852d7ef7d17e939b71251942fa620978a75746f310d263c24c7924514072550fab25237b0c250d86ffd0dc064329dbc09d3c09bb896a0a4b85119b7cb9fb93fedacff5c6c402627643a2ff36562a1569363a7953ea5d3fffefd5f9775c56904e2a6a2fa08be84e3a0f82c1e263c2ce5a7e29b6ad16b939f7208ffd3819d26a7db1b8c60e36c9d6ddcc43e920b1065f062646e07fd59587759cafc7d644b42ab69d6993a24d858a02801d07741ec5435108e9cd3eb0f3a6e2ac633fd7181cfc08d036482c2d5dc835e431aedf2555773972459ead947b2f245c2e138514e3f41d8aa6619c00214a04dc7c1726e8d919c265f12e7541b0eb5f83460931f71aa6f70f9b83c8db467cb409d5b8715ba658d6a7c11fa7005f7f23c10439ec18e394b792c4a3b0d150e1ddb0b2d44eea0c0d91fe97d2e410268c39aef7a7f31d4d4b41b4233105bdff45b6f97d2fade2f8033e5fe263d5651898d656cdc1f6f729dbf5b912787444acfe10b1d8d88049ad68382fb97da08daccea79a488be49f6ff95595fab8c248556fdf000d6c03fc732fd9a2ffc658b4937238370f56b36098d3723d3bd636d040ec31e6524f45524e0f020c2aef211f68305ac637febd04841961a60e0e035472ca522b963881b17db0faecb554673047eed31d668afd105333cded3f88a6a2af86eb7f8d7312a9992d923c72c2ff331cc9e4201ee4edf9222932c206819ead6811051a9a346ac10bf7bf04ef8072afb128d069e5c37d71f1e994e7fe59d83c4c7c420cc775f6f18bed1a299985d5cddf20a5e81ad59f3248e466aef4baae16909f60e1d2f958e2f10b7dfae187cd02bb0a2bfd5230b007c76a283a3500309889ee3df3150711083f7bcee501dfe291308224b3ceb1b1d8cd3313d0b66f1a4a01c98f2974318e680ae75b93ad6faeb16b0423d4b3604e145fb48ab9f1c01a7a210a54e758adb5ff2a5381aeeb16f9c238e8bcc92769861d2833532a3292161a4d99e008eab9d9dc2106e39c98ac27f80c341d5b293947f2edcca2bccf169c96f2e713812684874a16c32a21b84d9d7412f48d72c848ad66473e2d897e9d1a79a350f667193fc7f3127f63fc4d85750c6be3ba7b5b54535c1f765ad2603987436f66591f4e54089e59e35a2072ed44c4cd2bab8a3cba19a6df2d80f8a68e414c289a8e5fc9b9f4261d4983f9a8a5962e874cafead89d1f0478911c2baef1bd3ec6dc4e2e03387079537f2e382367733d9210b963abd50ffd27eab206b536f9300ecc4fb73c656b210cc4f0450e8d260baaa741d7e1e28dedde594431f5da8873919ead0c259d1f15d7c19652b7c9dc1e6eb2f1b015a38aee53ef3159518f94b240dc571a11bb36fe18a75201b1b4ea05cceab58b6d12c30709a14db6741c10b1ae003a33be1ec3da0e661c00901edf2706dd2c322bf42e821230e905a250c414e469d6f55ecc5f5783c3a18b3ca211ff421fd31162d8c60441eb3b0207a8a5e77031c55bcb0de79182f41d95d6b6400d400fc9dd60b3384ec8c12eda34c8c9398e77103547558bf41c416142371a71163331e2c3c3593503d17935e44580a1634da91e476d80c09195c021fa3113d773918ba0702239e146383967984dde4071d1af012639a8302e86f49c6722fd3b9aab4c6f990c867198d44ceffcdaaad3a49d7b4baaf6d2af02a7f8fec352ea7fe2cd31f2b2f732993983b26c69a7fd03d069231cbfee0eadc464fce983bc50a463c00770423bb15c5fbd8233fe9c26643376a788a111980f99f54b53e58c9df8b7ddd8c18c1e405511c0fe0d420c6b790bb6529fbcc081b4ee1468ca3568d9d8d18a5ffb71f9730365961ebfaa3914050e693b12f46b346cfac90df8c02115cb038c6dd789f47ece15a731d89cdfff20028065ae6647d90a5286ab9b7caa18d401ce39abf8f7f1991c1e84e05b2ee3b565be456ea0666b740a94d26835e35269a40f8cfcb902bdbf697283f3e6b22a37c3abd9e65ec8f3f6eb6d05acd050740eedfe225d0977cdea2946948cd0cb1cc70b34a615249184cb4b92a80e4b913180fa2bda189d0c5246700ef9e191eda54d5b5b314eb712f46c19e9e814631323f124b426b0c4de08a2d57a3b60cd8cf1b61366f2c7a16ea71f96f4390f3f6644882c25ddc6a9e118106ec21df209ec293824da6ad793ce6aee2c4cf4334d9a3f520dc406c72f98132e1d541dfb478dc0d9d604bf53573eba9b383c80d12f85a63059ed1798b022af919d2d8023826e71d912d963ba5cca42c22f870409f78372901298baca1a264bd88a768379edf3643379c8aea1a8390bff55a361ca88c17c2388916265e6f01f4df6b02556906f357a0e3ae0b4490b108f8389c9cf505022efb954d0da3e254f5950f1396b2f1aa5c89cdad36e7ca42d23cdede0c3ed1bbd19284cb6a33474b89a7278453c4f4f3a1b6073d26ade3ea08a00eae0939bb9ac04168bde1c1ee1e8010504b7cabfe8ae4fa77a70258c4343009010316d13da369b8e4b2b238439a8ad735558524b1eb0490593cf6bee68c8bdd9bb98e81feb0800f2048f5e513636b8a31ff4ebac889b20cf33a730d86473ec0cfb50f2dc3052396d206fc268a759d0d2597e52ef493fe26133872e8b6d5b00e8387d535ac46f5deb03224c7fd473c7cf13a9c7aa78b30410c0fa52d89155301afd1022eca4a321517a56e8c237b57b5c1af495f316dbce19e3a8a47780204774545459fca08a2e57ea0847b2e9791a16c9058afd2d3191f09cce2fb51ac5b766f0f61468393a6e5cb93cecc69734a8c189a6a58030d468760c1e5f1bea878006e22054bc03c82698790dc18257fe3c674246b3bf585e03f0d9e7e82768ce0c1268fad46e09b0b16aea4d3335d960aa813eb3b6e2b48906fa20f07fdd408c467d03ddd4debf838a4c5d06f7fd0fdbf755042fdcc5a31fa52a4acbd6feb99604a5e4201f3962a8dfeb6752e391f2d2ba8e462ad244dba0294a6c28aa06c3cd91a87ba43b20ee4c04a339fd257d2dbe00bea8c181cf69f478bf26ad702c3f6d3fca8a41711bda64eaefb902b563260a86579be435bc32e2ea535eab0f1c7a4a33d9c4f555a46f1d6f1c63dbc9d4f58995e5315b4b22678d03ba7ee0d1b2ddfd7a350e471662f9f8dd7a594733b22ec036fb45216194017f8f751ea551760d4fbd12d1caf37b76c0309e054aa94d035706e8e982248abfd70b56529f4babb08fa9249b1e3f132c635032ec2c1d7d9e24c7d574210d148c5ba32a4f48b8904c517b6cc0f8124e432771ef3c40860accddb796f10f97d468e18125dcbe7f3ecba9e76282ed1586d0982f4ede78cd0ab83e1338193df32aa9a333dfb54249b64c35b0b39afcc6ffdb505925100783729efa1dac0b5e903d4b7a59cca00bd55001c95a4afc36245f6e92d861b39def13d0030ca032ead10eec4bfaac815fcc94aeb44537ef50cd5f795009ac4fdd3cee521f666e936ee5168a781065efa9bea30e88d561ddbffeff1ee24d4571b2605f00d2ecb86a113602129f51a62a425ad7dfdc577d295bab27aa324bd105e16d0bc5d7558c2aae7dab2ab7a39c13857b78aa986ec9fe0c38894ec6c179ab844c135677f93d9b8b4b73105116168d74312ba0c3d1144c1bcdd44e00545bf1e3312a5ae6ad220d9a49f373c04e19e81bf3c0359442182c99319a9a787ec831e651a609a0238999b6460bd639588ae9f0e76f0d64a74e037a5b24d9f3485243055651897b09652eefd4ff19a16fc627022f5eac252cd8b572c153127df7637053e5f356d0a36419afb7775996b8a17f2fcc4993b755d07413aea42dae61dd0187794215e86d1957a63a174c93b6a4acf54207b0556e1d9579a3d1c409e1097664352500240a270de9445dad7cb34ba99a998400055844f1afbb113139cd96b2f0339a639a5576897ad564f92ca46b297b38d82f44d817ae884ab7124ecb1b80b3259416299907c4272cd80b2fde86ae41fe4456a8ed1748bc160dbc3efd4f61847d773b8d742417916e507b5f8ac4744b6f4b35dc1e9f1ac83dceffd0cf1c4ca350914690a2000c9ad370a2ed808b3dcae83b0391013f743004ea88439bdec91ce010e630a93b3d5a9a336e7da4981559c2bf413c3acaa66f2e27812e8ef4bfb8f10b2b83dccd6f37e1f92812cd8bd79c611d7bef41b9c2b9facb3dd58ef5218d46aae2e5ec73f453bd7792f43e686ca6e3291c5f9bf9d18f36c93ec40a449010079f84ec2e73768c12e326b1da0f5a6c351d2229b248c8a2cc8b562ab6dad8ce1cea8d8ba38381ff0c834c87a193fb0305cb260ba81c633e42a7d2c5fb2260071be43a8192c9ed3f4e10be73072c6367cc3fe885dfc320161af37fe1065862f2096f548b8b679c82865eec6abbb54a287d307acf6f503be36c31290bc3acb655687bcf0a8918623ca52b515d0a6467fc5063d739d6579155d3ae858c8947dd96ad78ce315b78c215b42deac2e732c4be07c56cc8cae7c00f370b8c7ceef83caec8ce6027440c905425bd1ab8a2d207e5719b484dce8c2b44c8677a0538a6004d0e908140cd7a47cdc8f8d9a91f5f75d6682c81b9adfb3469ca80e72720b3a1d6322dcdb51071d6752f2195de74ce06ce94827858081dce6be6c64e3ccc310f7e32f49a678c01d8d226b3e525a6d569ea90ca056645a1c8878fa52ce9b4c0122e2bdd6c8c38171a2c051b652f27b7c4d65963a25bcdb9234d068bef87d16ae7f68f6cc813826cdd44be891f033f216926db4ad5ceb3633c38dd9b4a57cb45b3635a5807fa352e698471f79650768bae049d4bdd3f8b1296d0bdbec2237c28f534157a586c864655e6248e1ce9cd8d060bb6317a7a3a1ded7f543532d3c457cf400e99ac0f3b5e5e166fc4069c2d5649f65ef9337e83b8f1591a8b036209bba92884513a84cc023af3c11eeda13c98435be8bf1857a7122e4bc8cb0ec1534f1e9816b2c0ef8e3711d04b9b085b283c4ac11780eb4ef6cfaca2cd391d9d9be45f83164391c1e6da6cfdef34dbdf945ac27dea4f10b687d87f097162b01ede586b3ff2bcbf93d68e620955ebac1a500e394492a62ddd96aa16e9a1d701de31dbf956c3a233cfb25c2380bae40e7e0d4704ac497cfe7225e7ef884958ac8a0d9ba609bdf341255c18f2b840b636c23afc3d2f19e6d0fcbd3e464b43590af6b5d6ee94bf41ff2edccdf69f22e692b4fc885e0fc0a254237000a8cb4f8d92b447ae4b8baf2f4b1b80fbc985698f581a6b6ae491f5d2d797cf273e5375330a1ce3477be79a7df3181f9392c1064350d72ba350a02bbd21a59d3d43f018a70eee7dd78703cc45d306367e3dc9425fef38d5abc025f147643879eac46331362a3b9e6a36297f1526949aa02495333f75423fde89407b60c17aed57088fdc29a875ba76c61887fc9791af39c4d18f4469bb002014b5d5180f41751bfd886a53a1977cb1b40a26f29c87928bf4cd8c988465e3a8e8a515ec4db7a5dd08a5b9bc6a3ead499e48341343ae28d42b9d7bf3cf5513f9da6695348913eff7d3516afc3661563a4a24fe8323d95ede896001b0dbdbfc2fa7112d099dab7b8549ca1c2450e05785a314c756537f312c655ec3f1d575bb69e9ba9844c2ee30ceb1b724265a6892c19e47c13899336a52456457f8d4dad69d7cdc5b5ada9906be07a3413dca0447fbb6493c136196d65dbdf30b19f5d40764504399d8f54bb347617bce72836905e58fa2981f730b550a211fa9ce1e3dd8eb47efcc73bd436454e381c6fa097f43101e39fcd92b91b39b49910d2d207652c3420142870a82c10d6ce5a127dac7261ae54027a441887a0075e96f82cfbace1163821df8e8b5eaa3e7266f5299b09821952e4570e4577c286269b38753d9244d95fd40e64c47a6172b0fb6511cee9116b51eb4aca7563160737f8563d56591c8c1f91629868d92c45dde476bb96e60d8add6c7c9cd15df670dc47558866dd46133855eba7bb99d90ff3f7776173e6280ffd8f88ffebc50715aa90730b3039c8a99c89ca3dee05dab8b48cf86e0bd89b30d18fe3dd6358396c5640088ae9128d0797ab8ccc7854725d46369c153d6bbcc146f8a0679a333335bb2e1cce19b4aeb0edebf711d3a9dbc05a09fb599b9562bece478de097eecd14e568b11c70b3f1a6595b724fc95ecb3d4b7005335ba2b067545601a24b81a6b7b541357f9387f4531a2238bd29f98c1614be86e86d1662624c6ee9f9c7673f3ceb4d87146dbdf91d4c5e2db31e98c0b20d57b0669904368adcaf62cebc2438741d89a1ecc9950fd99dd791d86bcbf28557f815b548a6ab8e7fc95820a5b554988b402e528a692aaaa2dd6f6049fe114731e1cadff0716295affccfe5bc8c18524bd515e53992781804b4ecd661d7304f4655af54d7930366526e5d30ea08d924c8100c1df40d911c04fc68b7b520772ba491169caa1f9609b1beabb3d98dc4126b616ed51007fcdfbe363177d96f756ec6b27a83539ca5d6049709365847d42629e72ee60b7a4ccae7b553e76725240c9d4a5d769b1ea727eaae94d96d83a7a3f9b77d465abc21d04b03325a65823aa2cc7856664517dd515cbd72853606a1649e56ce98e09ac648b91ad72e61acf10e5871090fa70f9021cb77724b30d3e8bc91e4c344973e1ef44ef1ae2a4fb65e9a5f19adb0add50eb4f9e254e759b1f578eb15a04a28cfda74b98c2593d49a7d1675a90d60e9bae756004b7687780509c2e63588d33eb3abcc25697c4a6a08399067a4039f2226a6df633543ca290b4bc202d10f7624ee5717c9a59f14f89075f421c8129576f545f85101de9aa524ce730c88750d4e54182b14dfd4d4394554208c60089d21b746f02b41378aa3f4933f2aadf5b9daf8b60ac10fae00942e686b9fce2bb00940ee7f169fa3901c5882e99bb1a7a62c5321606b22d06ba925f718c7ebae05c9c606c20a95fda4535ea0aa30a6f600445718ce10be9a1ee1d8889d2d864266398ed39d5c65cfb9e038bdb8923ef541c95694481af959d184d10d1483124b40fc9adab5a5288b8862aee63273222734134de05cb6905558dd9d74a394df74422be362c096d8250987ce374aaf177357f2f017d6ca5f3898f980a834a4d31bee386a1f9548fefec8ccbb19f0d704422a5bc9bd60381c640a151c34442ca6cc58a110147db112605a359b4319480e9df5110c5beb3bf4b138c53e1c6a120713fc689b453fbb0308a66d0afeb5b6b60b10cb1246990151e8ca0b6b96faae4eb41e70b198b0ba312277f45879ffd51c8ac6ef2d0c8b9fb032139c3b2b270444327969df16d78d7b24ccc5f650c9b1d2cdf42234a938d76295781a22e3ab768ea94e415cf27d798e3af991aa1e245f6185b94d4e80060fe354955ea5ff77bd77b1436b38f31a15f2c6272ddcefaf71f4bafe961c1c788bb7bbb34875c1775b9ae8e69cc2a19ff4662fae178a73465c273078e850b50f8e369c717088ab46a25117bb693944fa17128e1a5aed369350418bc93bb974e950ef1f014a77e0c3ff503a5886e27641004d27c542e377c9a7413dbaefc3aeec962f4f54800f511429babd13b31b22e6c1a2c83d2f910aefd5df179b7888350de9c58d226e237cc242f81e1aa3c11817fee35df6e19bb361169ae5ed7c49c806915afc21ac1a7172ef034569391f7016e636021614c3e9facb7b0c3f21726b2cb0b74a508d11787ddc722c425c5298a425859dbdbc23ab115466a3ac7a0afb42a0c446c35eed15614565b7229257f0155ead30ae131a47e5158e002eaaebfa0a029b0dda8d71deb0066902440fcbb6b2932660ff4da6287f912ad2904384fae22e49c445fbc6fd6655752a711a735be46062171c20be66dea5f994cd1b508d857a99f8dcc4d17e36bf790de6d8709f3c1e6f89286e827e2952ebc29b6222b007e82ef684de6023c94a21e23695f0286aeab7c4c01b670de896fe163c381a5b887558c8af2fe00ba400847867386130124000d882327eb76311a3e246231fd9a81b40fa8e5cd16eb888fb22a622bb904c5560c8c3efb1a9895a7969b2bebf9c3f9c6ee2b177408fff7141c860025b4862e8d3057d16092ad3a2e45fe03773bb36f5d1af5844619a5e4cc216ab37352923c922563d657527813698e485fe4437b206a4af7679bbf8683183a8457b46123cc422a92f8ca726200f501f91b272f24171eab29ca786f6389b012c2a97e1f76cabc566cfc93ce93543a73c2b964ff594aa879b948a21f1914cf130e68950be724475beb044c1d175445c437b6f4358e47fffb7aed7bb0fb4bbe8fcd009cff13bac21f04e4285d718fa96d025ac0ffda03eced6a6142ed9e8e3ebde0a5eb39046174348fcaff2abfa5c2e3baf5935a6bb246bce39d73d0e5ea60eff2a05c950e1dc0653cd443ed030c38842a70106448241881f3fdcb68cb8f66c1736acad101f3154075a768860bd3e80e16b8ecab0a1f3bf16f6ba305237833012123943f212f71061a6e21a4e4b64aaadbb2769f707f0d814cc148aeae2a675d3eeb0a770878761b678c6d84dfa3918458d42bae5600456b6286cc52ad3d6fda5c37318ed4c79c2a59958e01162195693eb11437993d1f68f40cbec0bfbdfd41c32109a98f4cc8f3f8c0b569e81004fba41f13f8c43a6edcd08279811994c20c6ccc2b225310983262303bd72bbd91b3325f67c99a836fd6b04d19b30812bdc460c81c8e4d09d4428e0f26deac4ed6dbc4608ee82fb54d8ae0300dcff5a0b2d17510c949e5635db2ac70678fb0d3e1cd9eeada85eac96107a8548c941a1328860ca17865dcba235be17e57325d379de6ab3ca8c7c7e1346cd2b2601a442f3624c056ed1cd0c9d546459ec10f1f7a77be18c57d4a3fee194d29d015b64a482ff30b3f46e63feae5f3b888e6e06e38072295ef4d78cfb143b170253a5cd3cb9b2dbcf5837a6bf9fe34eb5c122be5f475f3e7b1d6c1bf80869b1a8eef1ee8c668fd5bfc898755597da184cdb1500d4253b4a14bd9355f14db5109365cf72aaa0e4531bb1524fa3eaa5700b6b4d9c49aea640a9d036657b4e19f04e1e8278790ad0ad8e705052c6f67f6b79789d7206152ec1eabb05f26487ca211e0d7b86c94e43a82b25fee06a40796ddb27fd82b5964d1525dda5d781666bc9c4931f361707f72000089dbaf449317b718fe1ed007ae18d3fde70e095848c1d9d1577264a7a477de0a124a93a27ee1d1b87f50cf577f985e18482ccbb076d958517bd3a7d7e54419d41ec76b263751007d1195367d508dfd1ff938ab47d0d7c8d03bd598d992da41ae6bba5b3b8cfcd75338ee0b48fe1733739c32ec1acda35f27c60ef78eda46f0e7dad8642dad48bf382b644bdd5f9c16f4c7eaf79bfa43a8555e0ae9bbf4b8252bc25b011ded2fcf2c1c3a8042349675cbc4a39ca44653c72d2c1087a92ae6006d9a92699aca5249965b2f62dbc0220b24527fcfeeabdbb109d8be8540ce4cd18efba5cd895731ec2ed4ed382a29191150314005e74fb78960ac70beaebc11541ceee63fe1e51c4343216d9efc3bdd5a76a64867c78d6f6670e98c7ca951d81c7db4419cb6367eb9067a6180376e178ba107267ffb2b9a143ec27750ad1012d53d4a9a508bce113b26c0eb9ffba174359be1bddd7d6a6b64cd9a8326734530898766fcf7d68895a28acc43dff330664e5dd1d97d9949b728f23a1f25bcaf595bdd0e128c29becde7cfce32a71c5e9b52c5ad9fbdd300526533f4ed39ef3ebdad3ba0e1c5b72f59f9bed0888fe3ec56e859bb333e7dfd33169f8d2e9d5c75d1bf3608851966771fa1f51b6e5e4ed5377c66af00b792909720ddf6376e4ba020179997a2037edf6bbf653c3765baf861664b8e94d5384a8ee43ff79ab350f231ccba63d5b390795f79c64c5a949dc9b9037c7b86d8bc8763642efe8f05e12e5d0ab5f7d51c3e1087ccded00d5bd15feed1e02e403d686f4fe0cad64bfeda97808d112cf656c23c5f83dead09860fcd6fb8006fe3a463438aa730adbbf68f55f645d318f649bba8f1428ab5db26be321e399aa4c37f7cb5279ecd94083d07c899ac27161fbe4a2b7c4a87d9bc44747eedb185bcd9379140f6594a4b32f890cabdb536170096ef777aa95ab9f94ac203cc95940414dd74585bf91cac2bb2fd42d748434c59bd199ec20a7b8ebf7ff61c47d899dab68bf7a5175bf0576eba37dadec663c768c0b048ad133f454df0304ecf16d9330fc1d75a09d77636dd08f3efacaa09c9fc7185a789d034990273c16dc3084184be9a69eb811cc4c20ee7050715ff805f3c776577a0fec8414d37a753b916757b5f1ee407e41b5f05837402b2854d95e96e6fed7094ec6c4ee6f86b26683e95742c767de469cf8ede0e17d281b93916e6ed2aec540763726ddb01fde656a203789726bf8603be63845a2997ac54832a58af8a01fc44f43c21cc2b386db919aec78820498fb98db41de0f8b562dfd475fd95e68c6f0bbac9d2c12b4aadb77628b210d614e4b0597f753e5fdd8cca8af31fc001f0379a70d61c7c8fca60b80e63eb27a50fa2294a0632ccbcec42682361875c4583f4b65c7e5e22d7476b956dc5b044a041167b224d6b8ce002e9bf6cd1f24ba8b98af274d07cbf3ce493fab7716351e930687227e9a17dc5f33803d0025787567b6a3520a790ba90d0741912052e4400e30e3a1ac6855f3c01204f5fac95e0aba22ac50eb2954a0ad4248e5f5f159a89675d78891416302daffc05d54895365889d8e74124952c71002f8a77360fac6e21e0d21cf0bd618628a190f715e3d8d882bc068c8986165f84105f35e2a298649b564dc0c0ad269ba38c7430cbfb536d28a9b1811859071a05a22be344bd0d8ebc22791f0c350a264219bf2fa13c34858b2640ff016222de6bc17be88026de7f06fc9671f19f2fec9a393b10af110c14d2d10574170da6d3f418e8284e07a55ab20d0ac3f1cc750503bdb6cb35ba20c82826e9d9f59a42e54a8b74319c571d301b6f010e026d606c320bbd47d4fb3dcc760af0cee314451377d037f2c7c1eb798304fc441ad19b8e1524ed93578aa966ffb81801141b11fe9f6cabd3785b4669df936c7ec13cb5b360e848f3a06518aedd9d59c0e5ea4c7ab18f95b412bd17f6825750db904d7f2b4efce7341d2b7d01fd345bf486b5fa1a01fc9748198f8ecf81026c35dffc8a98489d7856a7ed326054e913d57bfaf07a91c0ec29c66d58898d6f338490c6307071c718f62ac26567853b41bd242a8a3a6134840d16548040064344e7ab4b7a3265fc74e6c7b00c36162f2620773e00d310ac87f0081cec714d0f40604a2e29f18a2ff8b75a8ad7816d738b2986d1344c93758fd8999e95c2137ae30ae2b7b667c3240d636aa48136a4cf76c00d5fe00eeb96ac19c7c0411bdcd64a3c2ede577069b5eb2070bbf330117cee305c9e422ec45e8e12f14c41bf7cd89cce91ac5c316b5c00769694cd96a352bfe37f858d7abe4b766a014770b665eac59c9df487075827b51df49a86acc269c847206edc63f3476704dc59831f94069382b0baed52f6e6440853a38db85fc0177ed438876054f7c553fac5c57b72e2f17043b5138635ece2fd9d1a901894719ef013afc8685d647665191462727081ea38d9e939d7348415bf1a3e59e8268f8bbd07d0bd92d4b2eb1390f7b2628f5007a07e3765948906620219ea24780743046b5b67673d3f608c55bceeac031c2cbe26722eada9662b63ccac2549534beac0ca33b9d35d0f57f45de70ec84f86fc88399395eab1d11b13959c6ed1c5fa5c59dcfeaf42cc35c5312b7266bf9aca76912edaa76aeafcfcb00a994ee50ad828a900cf13b43e0e3d60111a4586654256c9a87538fc761c53901c12850ae605b4ec7a7d42064fb1151279927b5d27325d87a2528ae6ea952fdf98232688c19f5b07d32479a0ca4807ac647337090384a7f16004007699183784ff61ea3e0bb5547b085ba382aa28c35c585de0959a4a020b083249edd8f311be06478e213ecb12a814415be8f8979337e06012019c800e720890cf91ac2c79ffe447d0909173e5e8f3de1e8ad8c4bb9416eaefb6b1eca381744e6beae23a92587e8d65aa8256bf1ff76838e73a32874f13e260eab3ef3d64d38779c01470a8218f977c44233fdf5ca3565a6f54abe3278eb634413dc77fcd7b10ff01acce0b7814f70733c721c7577c916449804a63f4d6a08a1ec87d93a3cd650f24da47bd5813d0b24c62852648b0efdf211abfa463c2ddc892affa9bfcb103e24217a180e317081d1afe2b9cc315a954abd7cc3316a55bb4fa00a08395078a80fb57c4d79b9542d766d9df3ffb45db61004184b5d3521f0290aacf87459256184fd42b8f411251a1cddeaeb40cba622723db394b63180f431673f4f361a7b166ffa20358fa980426801ba7bfbb84f8fddbf005170addceb364bcf5bc581d9631e001f7ff8926e8670fa34f16dc61e08a2f405336ba1cdbc4c330cf6ffb154145c9fa060851dc0d7db7bb44b4835668ab5a8b725c353ef40bdb1dd1baf820c933dca1ff3f3856255962aa9faa83258e4127972b0c1028dd9c831b9a7c6e56fb6009abfbff3d8dca4a317acb0d19de36ce50245d208b1f6bfd9dfff026b965c5319c06ac1ff5fa86e28027bedb41ccb08b97701c0c39d9b29443d844b7852e436f00351d6d9981f7e10abe7d9688029372108d4e6029a13e26a5f50d0596d0e569c311c39bbf2cedd40ce551ab32d77c5bf03bb73a7487194449621e55daf0fc471919049fe6ca41a1f1664f51912d4d1ef7610870000339180dcc6413341eae32f2fee011a6cf066b08085a7f79f6de9a525a3255bca94640ac906d1065206f672a48e86a5cb75dfe5ba8e86dee5bc8e86dde5be8e86dce54a1d0d49dbe54c1d0db5ec722b3a1a629763e968582f87ea68482fd7d2d1d02fe7d2819ceae5e5a322c631ea57095c6f06c0cbe55e39cce5ef2c0b4bafc69fd17aa592c140c0f10c896298760a02b1d846e23aef2b59d30966050c8ceaa57f52ede324e8a54b754ff3bcbca860c00eb2b3a3728969e91fcd8a618162920e76be9a73582ea78e58d26b611ec5253797d7ca3071ba523bccf292a622eda2c21180e2a9c869e6d0504b0be5259946d3e845d5c204033363a7d12d2710ebe9c06b314d7b4df0cd66e43d717b33f29bcdd59baba9f488830cc6f3e10befe876abceadecb137d746a585c2ee85a9889f4c274e8afc6e2ef105eebce8b270facc1e54909764fecc9f7105b3c807b76576e0c66dfe6005d971e14d1e9e1168af7a44e08500175e50008f1efb693c07605bb9551941871672809e0a7e5d0461782da24b6e2e8c8769fa5b546e3f7603df34111690bb14853515b118354aa87ba857a8211414134ac824c564b4c28d12ba12bc1af54b4e58195d12b79fd44c454cd32618f00d4a08254483a1dbc91811ea5515319e1ea1a0867a85f56042309eea9eabc7f65a4702f05a34647429239634155d981acd92e3351505612af29bcde534fddacb566eae544d8d4dc380a08d099305e60476e695e7f25ade0c192cb9b93cd746652b7b6532eab1bfa8c7965283a9e86adc091d4c0ccc872a9a9142c502fd4a5d54b1e05877adc9e860493bb313e4b2129789ac10b92a167af00a50c0038be41edcf90c98482c39d638cd7c2a4661c91a97279860e9b057e3a50a1247f4e0ca25d906485c1a482cc9423ee0445baa711ae65ec202f38765c4112f606942dc59c462b12c80baf359fabbeb0e037718d767a070bde42413b570e723b771eaec9ec425a790ebb3c8f5cfff08299e5c7feaaf59b1e1fa5bd08a91ebff56caeb3f4e01c4f5af615d7f1c1a4b5c3fe28a0fae7f0b2ed870fd1590e4fa114378e2fa47a0c88ecf752aaa5c3fa28a237ac5442c1eae371d82144002e06a429412e050430fac08a1884ead21b835886f1c6744cb47f440032cc880055c2538524150835b7f0607a6ddc00da590ea7335cefacdd4d1f1702e878564fb5c8d9c4357d34680c2762117aab0f7a1430a559898e387d63e745e40ccd71ec690651dd2bfd3680f040b4d127b58b1c57ecd0882659d6ed65161624d8fdae3388df62f48d89f52831b1bd05ed39e9bddd7ea633615e2a6d16d274ea36a4cec41fafa3d36f0b5b048d53dd869eab3a0d5dfc41e55ece143c7870e8fa921969a7458c7abd3e4588e318fac1b31b589cd39bbc3b0aa516cf6a0699ac69aa7829661b31379acf488ab3a4c8465079ca6e9e8a75fe9f7d3e76cb0f352cadb3cba140a97404f0f625832c59223288610c2a9d061a6a088e50a02941b7210d4811cbe882386308a12850c920882954313408a62c06148088810614237a003152e242e22a080c10f20a8067420e189097c50d0b2c10d2a00a23c3abc943c31030e76406589202cd981884c153fa8a1881834c182223f104141c90e0f21986283264f9414d1840a70706da086a09f1e420406296a30031139c400073824a141872ec9eb060b8cc0074536507da0472e1151b460062aa07243901e0eb0040f452368c24813508abcc8b2a7c8872952fc005291501bea1386520443a142e7a4623f4f9ea5d9820f07cb1f5aee776f85b9b538a390f656f74dcbb25a297d99ea2d61999aae0be14090b14969e52aaa5c9cb75e191a63e6ad6bff99b3e9ec9e33098e9999ce593a0cc700a5b0fcf3c197e56f7628649d14fbea74d65aa9b7426d1c685ad6cd23b4f95aff0b1496bfbb2790bda924b388d5165e94c0f23b539fec3d9de0381a2a2bb6bffe24b5dbddb49b07d6ded26e302d63a7e96c104add3dc35a785102eb357c61ec1c6cbb7059172edbef94369d1d03ed28ad9492a2f0d33aa90fdf3f318c39cbb2ccdd356650a32d036ea36269785dfe1728ec7c77c77e700cfe972017b8fc93b3596562581531ec5db859ad3d6a5e318f210809e7349217188c3614d6929e2fb73d8dd63edb5efbd2f527597bb7b777631628d6b2fc60e77710a9db054c299d31a899de24649b96a15eb65e3ee24544124f40a2252682ce6908aaf3f5f3cd99f1ef8f1a10a2f65f44bc39807ff170334f43f9e36ba7d26892135a4b4224acb7ac44033ba1a0305e127df1a08b507fcaa8992102ce0bfa99e7d520514aa2353d8383c20b1758d55edcb0aabda6897eeb6b615f0f6738c6c4b0ad56c7b47fd0b962240ce76bc019cea998c6b15cf7fa5cd7859d9d2ce341e7971370dc14b18a651aa92b96691b57a39f76b786d2b61a52c75e3f8deee87318d5364e64f176d78fb1ac63f06b3a60b35217dcdd9f597376779f71f7ce5d9c09a5163c763ef56ccc2bf2d882c7d6ffe63b3731f6ceea9c222d4d4d386691a43eb4c8959791942641cee341a8b886a020699f665d9962e4a4c9143279ca1798e8462a05967b9c49819d3cfd9b9f29615d7e22213c97451e2770a5cb443c47a92be3d57a34c2cde7995006375cee91aba98372b9478ed1a19d21388db04c74812997ec529cc39cf3c3df3b5070ce1a9028728265840f11200c01ced9243812c4142340011538d426496234bf4cc4a2413fe1b4bb2f57e2019ddecc4c359fb4d21a962c59b264c9923997f8f7f420ce811cc8811cc8811cc81d68083a63d6d4b4cff83f8cf187d63a35ad62d5378d096666666666666666666666f688d05aa3736366c698703c43d664d4b9a971a40e7bc658fcf04c72f7204d9a803170dcacb7332fd1ac96b04cdb485ce77d256b3aad6041b5b8801d92598764f38beaeba7dd4dbb9b8a80ab1bd7c4cea7a7d30a4e816085d784a4accbdf2af09a3033339d9599a9b85a55c6035d4bc7792ea5cfd2ccd57297bb7b3530bf9e611876d462f0645af13e30a04da1585a68ad152c5d2515173fe69462efdacdea6dcd8e323f3fa7eabc2653c60376ae260b19a694763d924e3577161dfd98a65e93b013bd1afc220d9962b5babb7badeed5eb57af492a0476bed7c4858b172fc65005763e1dddbf1b47198410828d701cb2bb978cd85483eed2724949d8f9252316c5b2e274a7c996ee3462bfae64c47a2523b62b19b1dc9dcfd9ae64c4924e2b58502d2e1dd8a5ba97d4e75fe79c3cbbbe5ca7945228cd32ddf9e5faf7251370b3273866e61766eb0d91a29d0692cccc586dc982c8829e1da5f58a99d91b62b28c58f6177577ea0d5133a321e60924bdc5914c1d57ddddadbbf7ecf4f3acbb3b35fa403a44844805f586606676238eb4794490cccc1e11cccc1d7dd2dde751c55c8468a1f5ab4b27f3013bdf9d7a49692ac8cea7ef0dc1ccac39f7926ad5cb8481f20cd3e248997ac1b24c158405a960302c080626860525423b10c34206c3e64422f31836279217d50c966541574022984b104c8c08732221e27285858c8b39911071b922828b393be07225145bd0502444e88fcb951633349408fd71b932d2605916e442046b09a219a1c80824381d7f7cfca1e30f8c1873fec4704ac28f93f04349f8294106c57668c102254a680009ad700368a89258fde3c811a08a55ac32611d19385a022021cc390f5317bc2ed4b3e9eeeeeeeeeeeeeeeeeea9ce290068bfdce9d3a74fdfa600ca66285b5cc08a6129269549eaa556262f2f2a183fe243625a5aad1816a82254510a8885cc570cab4b5ac2138029b16218132b2d472a8ac98baa85bb9223282b303133ee4a8ea0acb498711f82b222f3e10b5772c481505642f1851f71209415172f2a8631411da92c4c5e8c3e230d751740d40590bb001a8104772012a8d300511a20a7018211c36b919a6202fa0f3062c8a8517264480925c8a8f1233e44464dc5a8634ca8bffcd414931a9b5add87d89850abfb10134ea8d57dc809302d8660b35bc73d1bd3c99cf3faf0f98011fc9419c65a0644cdc2d14b023a0dc9067666d909c68663f4cf1a147070328cdea021006eb980805ead5ae830070b43b62bfad1b2324312d46307b55aad5609a65ea64b355b41b3355fb32c5530d3a8080626860518c342a645e651747b6d574a55b60f4bf155563124e48350eb47aca2f5d252cdb4ca1f9f209fd64bbc023a71f192cca01904132382c9e572b190710184b519b55eafe9bdaebc4468b988a2dc86a6680df9cdf67a852cb1058d57529657a5c5da5edb158c75bb484f4f8b191ada9a42787e785ee21570c7d2741170800b91d74e8b9764b282583423bc84aa6809b98ab446206133400b21025c68bd307a0a8011230717c3338a020e8e0068ac408277e367a80419747b6d2f2235e3482fedc1cee74af04a1936266c2f20aced8a0c7cd341411a68b58e90985ae56d1697a9155453e3953626e8a0d504df78a5e98997c722e2957eb3bdbcf24a076c5a26386d592d486bf9cdf6f2168561f160fb31950927b48fcf0933260fcf0c006c556caf6d0abec130d1d422c9704d2dd351075a0080916151241ab9f85e0d1d96d4cc18cab22ccb9717150cd83f483ca41d52909e8f45daa9c14959962faa16a6d7ebb5b98c5ce507e4637d327c1a2849413ed6f7a324f1dc26ed908294a49db22c493ba41aca57d9ba246907e792763e1669e7639182709b4ca62a290f94e5ab6cb98eca96a98ae9d58aa20402dfa05aad29483b1e4febc855fddbf958df8f8f5596a5df9076483b2569a724f19076ca2ae5b7f3b1be1fa49d8f75fb493ba420249e5e995e6595b21401098e63f621666e00adadc3cd4ec53aadd3fd31c7701daf00c735b30d983b93e0a64c67344c5df0ba5c2dcc4a3bb0968bba5a98314d2dedd058ee8acb651d0d4fa1e9725b47c33d9fb85d8b5c5a85dc5983dc597f5cb9f36995bec95893962417b919cb6f307ae5923363fdc878825c72b6b29e5b85643eb79fca7d00bded22d6c281edbaebe98af48d57763dbdf2daf5905dcf9d474dd3efe26cf5cf39e7537e9712df644ce3cc32fca7875e8d493f961604c7dff77ddf77fabed3f77da7ff4eff9dfe5bf1df77fabe53e9fbbeeffbbe2f6479f00be735994ca6effbbeeffbbed3f79dbeeff47d9ffd4ea7ef4f2751b5e2fbd34954ad389dbe5f21aa4ea73f9dec77fabeef7bceeb68c7629d9f25449d4e618ed2f77ddff77ddff79ca9337ddff77ddfe9fb4edff77d3adfe7a7ef4d7f12c9ef4fdf9b9efb4e9f29a47f0aabe9e9f72cd21ebf678bedd43001e78310c6186318e6363fb6fbfb27e738fdbaa374b1a759386f7d77fffa343aa358e5771b2476b6ba6bfdb01820e61011902977e632111027f7e7f2e59bc5d86049f03ac730b13a78cc146ad81cb1a4a6691ca91bafbbffd8ab98202c096a8fc1d4eab50ed2f398f785f166e3a671d9fb7359b8a374b7d7b22c7bec92886098d7bd7e2cd4918dbdf287d12b1da49a199cb3bd3f0038a7fe8e924780fad8479141d1c54861a8c1306f267a355ad53ce3d90f389eb9323df31bcddbc5d92251b16119fd0f368c19c52c2710f86646a330c5edef9a234bceb24aafe6a522cc6cf51892e36cb9c63dd997d4a39f4c19fda45238b349e562df937d7f3fd9bec5ed39f149cee8de28e0d62e499ce591255ba8dce62c2b393d154a978ab3d5e39c356405aefbfc6f6e2bc8d8f4a7d0f4dce9f9f434da743a997efe3c85a629b28c7e434a8ffe26530f413ef8f05cfb2725822ecb9f8880f45cadd398ddb19deb7c534f61ad524b8ee19f6a59dbeab1c854cb546972e7f19abe1a79053889758a49ac45363e581d94d5a33f8f79ddc607abc3f43ce63dbd29ac42f5498f363d749867a33e7df0f4a727ece90696fce94eeb773a89154a8fa44be9f124922fccf29e9ea55727310462abab477f2bd6a3ec8f3217e798fe664e984495b51e014e6f32892a9bb57aa532954ca637994ee20a4cd8d393b56c953707e798de9f3bcd1b02b12bfe6b955e9ddebfbe38c7ce5ba5e09c1db3bccc31dc8a2a96cf23c0e9ad15552c2b957df247c7717a1651654515c66bdf8a37deabf4e87f0a6198d78a2bf4e8d74f7f0aeb0f3846d9b24440762edfd3735d9732ddd39f4e3fd9abd1f77b2fc5fe4eb58aebcf3066eee9f42c936f6ac934fea7d373b4fb42d4d3b0f4d33bbd97154aaf4cef5f87fca6e5f976f6fd5349589fcba3afc9f464fd5ab68443d77b1ba24272deef0404bec9e134ce758aebd935895da4477f1b10905e7ad92b969bacb502d33ecb5ace22d6326b6d2bc4d6f58789c29a441da737bd15c9d3db37bd3d994a22d95dea71514856290f9877ab240bcb253d7c00bda497d7f90698952b1a2543abc50292302e20cb0726a9e41cd57c4981b4b62881a194c8fce537fe624a596ee4a5cbd563939ef0a1cc27fcb95990d3905cbdca7278825759111efb3b7382dd9214fb007a95f000134aae1342dc7625320f6439d02c872877663e7ed3ee95c732e14cd4fa53baea5115bde54224d30c2ebf1b293195f0b9dec2a61875489caebf69883a0559b40fc46e70f9bde54cd46f8a391318f653bab0238c0449cd1bf2219edfef454f7a945b7f4e0e894b663d3e94ed70a360459c63bafd251fa2df9f9a92f55cfa2c9837d9f417dc7629b5dbc0ac47339d30cb393c8f5c6cdff8d033975a96b43fbf9404e792f5908c52532c699d825e547ff3a1194f42fa8d94f5643d43604ffbbcb0b83584b9a5242c3933349b9d52f16aa1e634f3b954bfcccc874b495832eb21b90facc3245c8a0696f41d5b54fabc8e23715234b0bec3395bf77c6a84812244301084ca108d9cde255c8e351853863f7dd23592488297866f21a9699b48f6b89bcfec993c93f5ba52bae6aa0eb1100e59336180a24679559f9276478f3bdfef9c22e9a3bd1a949643d3e77569d18e086497acc08eec62e274188dd559b4bd88b890167af467a14711dcc192204f76f7a396db300330a790dba17bf6eeee2e64237d5cf76a90486fa33ee97ddc0e494af6084921f7bc33e4d15713dd8629a38fb869f89d7907ca4c293333a594524a29a53578f2a208ebcf0c85871b482492486e9b6fef9ba8815e8599293353caccd5293f531f9792c4882c8888e8c91320209e2620892e5044f3d666ea0238193004cc55c8e5e79f9385660d7a7459a847fe394b336a38468d9138975fd3b46d6a35ecf69aa6699567d4cca03fc31a6ed65ab5eb4fe6b8e4e370359cd12316d6d72a7dccbbc1778a3ab2d744b2e662f4d65083808fbbcdc7b82cace9117b2da4218e5723cbb41b35a81f62f0c39ddb7b4d8f367c78385c84808f3b7f7baefee4481ef3eaa83524ab8b4f7a2f85f9cdfe2471468fd877a86313716e468363609fda81ad338460fd79064eaf3631023d622f80a6c1beeb5858606066662e86f1e811fb1e31a1d905a9dff77da22ac725bbaedbb6edbb19a45c6ec165a2197e5c6e7a36e8e51eb7a73f9df6f5fb5adfabdfd5efbcefbeaff5bdfade0c47d7deba52f1cdb22c237d5c98540b8a85e5643275dea7be5aeac21da5efbdb0d4755dd795baaf863abcefabc7bd74dff7799ef779def542ad476f10c6eaf0c0947dcf6a9aa7f1f53cd1865aa8c3fb707862ad9ee751805251eb42be29607707d6b7af0a87dfee5538fc9213b89da85defc95e43bf34d4583c0c70e66ecf240ccbddbe23fdb6711bdd1edb8ebaee3faf4607f6e85fd4527a356f2bd17d7dafa2cafb4980ee6b17f58a3b0f47f7de78eb5771ac30cc5b4518507a457a5f7ad7e1bd50afbaf7e7489e0af3eb7721dfcdc3e1755fb9f6f1ed5177bbdb8b7059745ed8b7f354f86ef570946ed5de6b8de318dbdb20b13d58afabef792a9442b2bb5d065a979fb84c344395cbb1e86c7cb06451f79d4d0fdf3d8f7975743d390cebb76ddefd692249014dab21ed0cabb5725c4fe6e857eafeebde1335a7d15c48824797046f8e4b6a2246bb345958e17886d4ca5b27063439f630da63594cd449d73daa7bd40a14ed01fb0ca8e766dffd70312e8f4ab9b87c0bf65a14269c5cedb7204097a35c26ca40793917efa5707aeec5382386e18a4fa150dfc9782accae63e1e1407d978dd04dce992d0fb6bc80dff212ce2b534217feb3888979a137cb7e6659968529d04be1f4df732374b4c741d05ab055c4694eb840af00f4b377696947bd72b9ac78919c974cfd8ad7a4f48aec9ef4f535a35ee9e8b4a25ea154985198f841857c593c1c9d0bed11f59c16e437d315e437aca3d9cee4a5d0d705057e0bf864f62f5f1f0b72f9fad80fe7a8be3ea68473505f9f43a1fee5b3909c1765f208807a179747a19e69b40a25aa60a017fc1da50b3e0af520f83e39674e1b24b67449ecc766074b623da8e76a6c8c30d613a4c8a50f7e7b38e883220cf3eac868b44fafb217914ca54a9f872325a242be2d21eadb7b09f9bab763de9696a73ca93fa1be7a3674b43c8f795d3e25da18b124d673eb633ebd6a117b7a058a644b915eb9883a5adee53d0f478b8b4d373927051da7671b2396a4d84f0ab38acb8325e90e16947ddd1ea8573abccec3b189d96b22c7b988a4868599a8f588ba98082c221983ba99cbbbd967d9779cd37d567a2e0b390cd8cc468d48a3310cfbae57a4c7f89ec81917e74e52a301a33c748706e915ed9d0fb5201ca37eeff88d4603d3d4efe15623b70eb9b572e20fd0ad4f0a31a01eeb4f8f35c88956b52641f5a913bf611dcdc25065aa4c5461bce3a539aeb63dbd59d6f2c1588f5af842cdcd70aecb148d50b9acdb710e110c28b79f9c81b94e9bdc50a0a6e99a193853ae752a97753b51fba4d879c916ba4365d3f0bd43af1ef9f6df201e9ee6199b758ba0e078a686d9dd9dc3176a68ccd0346b41f071346fd21934a8a6590b82ff22066ce0f44873dc176aae7fd3b8417bd29eb427ed497b522a52f7afb5bbdb51e8b1e6523a03c7983b1c837e6a071ab69aac8e7ed7b1b0c0c0ccccc02061f4e8913e8d4e393179362a8a20ca810ebe5bd61dff1fd0c7f6f0689ab520f8cfe180de518752446424a535e5fae63aba2ecebb0df98da6590b825ce3809ae62ea6d0f5ff12ed04b9fe7f857e08b92c24834b48862757ca944b3b231c34b7b27a4c41b1e4f612c118232c09825504b7571121d2d10e501157a5e749d7faf1c339449cd39f10cee914146d06102c2d2f7f9afdb1bdb69ebed9341ffb0306f536e4e4f626f439714db3f673e2c488be7ac5d4881ad9f897df68df1fda34b14eebf3cdc414fa0a4da1ad64cfc5edd563cc092c3dea1509ba7a456eaf6bd4ab6e6d2f1005cee9fec139cd39449cd3429cf414169221a7c2439b704edf1acef1677a59d3ac058dc6ed4a8ffd45db6b9be284cb8fd33724960d0760938265b48ba9234b7697ea80cea0b78d8fd26a7239ca1246245c8eb204d0f52addd1e392dc751b84eb6e83c43ae62a156e1575f8578dc7bc241fbf611d5a3aedc9f35b2d527c3d7d707bf69c73ce96cf26029bf9a8a4ec596a620ad58c0040000000f315000020140807c442814814a5a922a13d14800d7388446c623695c7a21cc8811005310619420c00c018638c31cad4cc1001508209d9025c4c5698bc193121fba57cdd2c8c82d0a064948c33526d6e914b03a00d0c461b52b30fa9aa9efb6c0c76b92aa861d2d14744e35deb3e4e142a8abd14b9595eca9bf938e33313393c8d2e6ea22bfa5342fb14f5f14cca73a8a8260dcf366d3df30cf71ad4602ac46d5af8757b32c3912a0de47eaabd87a4c6f66ed34a1102999e835f4d11a91497311cc94ffbddb11ffc14e4d2e7c299e9c001bc049beb090736612e4e9307cf0d5d9b36025ae33160f572cadc4bdf85226f1381021e154b2aef5dd4cf6629abbb0a6fbb19e804de7fe73bc7ac7a00f68fc884cbb186a390e56b6c747ba2dea9b75f3bc0b3205133456f5d0cbc06aa6a3a2f7ca10922b9d32e91ace469d40bef612f316cb3d29982a5ea56bf210b77ae3a44ee47d368876dc371b262cb130d6fe61f644c9dbf5422fc850ba0860633542392192c58e56f97b51d1eadec7ea2105bb05abede55aca0e3b3b4c8666c4bd8093740b79f9765d956e827ebe8309afa8a1619c9757b793a52ac8466ea82cd9fe41354a6ebbd6f8a5725cf9a769ab08ed48dc75536eddbccc9d493b173fcbf2656361e00d410aebb00561eff334dc038c63191b40eeb214c4a241b2861193d8a2360d0e4f331ba42985e6ef7990f01e3d8e510ebbc9fd341131777005bc1f15ee4fcfbb7eb5923186a8ba5dd04020d7d86428d45c7743fbfd26857f5a012df7b1868b368826041e1ca55d5da18673e02c4f7ace32092afc7cc694b01529f1813af893342304ec6921c9f2025e595dfb56f767a2fab5e3183458df4e5b18c241714d3204aa1ca9bbc8a64a5b9befa229b6b6dcbdabd2cf73828aa668a1cef9804da0aeabe967ba7adf49153db5674808d16f413c1d9026d7652733388ecb021fed9d7ed12fb2b374bea5db2740404d4f21ed2139df3f039fb92a23112418b3968e6394200e6bc4f101b85d536843312dd4fab54d375e41956a342ee665ae11c0dd7241d3ef42b86482dbd508f6f240550991936fac5aa6381133caf0368b5c43dc8d6dbb9be0cae8bb7c952e3c5904cf18bece405ede463fcef77a34d145edfcf76d68849b85861de981d78d83a9b32e091e54fa527850d62a10129d1702b2387a40bfc882cdf142dd14fe964053822e2eed57fca503bcdff8d2112f9140e5e9b65811485b039aeb582819a21e002cc0f46ad826ca062ec45a0aa58fc3b527c02d4048061cdd85104ae83142b775c4fb72f729e4f1a5034ba5b20c83daafa3047523c6546c0ac5667d3054659e2377298b27d98f50d8e227fa446115cd6eff6eaf56845c541f9b27dc01a3ea64a9752c2ef4b7fd7055a04f06290a486aa66b14f3153f0467b8dd9c3b5de4cebe7f4396ec19e67e077eb74363201ada92c64b5313b972f20aef2d4408df13d05cb37768a2e5204a11cf7b58f42c9cf0470dc841cd29d462a5da291df5f4950eb042909985f0e63a2a6d7196abc5eb081530f595b31278239cc90bb375957734f70ba687ea04bd1387b07ccbae13bcfbd595f57b296f7d0731881abceeeffe67178604d2358ae0109d84803662093e3c4dbe34c420c3ca1c6aadcb928bde51afc18776b3b0269a68c79f021b3af2347f5d3ca8ebf8123a96752ed4374479ede6efd252270eb97a4ed57cf38fc82c859ae4adac0addf26dcfc58ee2cfc30d0c92d5cb3cb29f9b719e05899960b1343f0d5953f074364c5bcd936b29b7696266d83bdeb2446c4f82723ccc06256db1b3e1daac59c7085ddc406c9ca81cc17f4b5d7d1c3500d89fc872a8e235a7aaf296cbb304ada7fecacf481936f9ef7c734f0956460e353497e6d7dcd44c04507d46a3cfbd8d2155e92e4fdcf68c98698624938f2713e359349b0bc04cc387f3c133c12d082e8a56b193e61581a1d70c802d31db9ce5d5cd66a6ed27c5b217561b97e6bf68fc9ab5d64d3a265650d4caf719a69763838999fef033694e72048334c563ee01a8f0952f99ff3a7c7793827b03b59fa295c836e9dba6a19e4d6c3af946f180a31e960c8fcfbadd58d4444584afba3164a130458570d3f8008abff676f9506a62048aac68d06b2606b6ca7ae71d091cdf2f636255d9d41653ddb6c5f5690f44c530826738d319df2d5257c74dd1e953b72169e935546922cd142b355f1657e2c500daaa809b04aaf04133b2e6e12f6c59f58282dca0df89fd0859f0ad7bd5013a74df96e1049057e96f8e1fce2195cae95ccf94d8222369e8c5c7e8354184e86b120de6018e9de6a1507235aaba807a7c0190da540d7296eef982cf23ea018f18774ad7f88c4f266c43f44e6b385c61507464c22b01e28984e593201a70a0ed4a6dc5711be08fbdfcb8a504cff3055fcc116b5f8b67b01f04476879ffa3488ba2d007256117411f36762bf02aeaa3bff2e2dcf19a7fbd188dcc223680cae48ff04acb853de24f1bda9c1ff3e5bad4d34f62295916429942943dda452ed3e457daddb22d4b230a9232265f11cec758df2900cc70eddf9acd0e2fb336522e118298b053c22ea5e076cc8dd2881e1214706852dd78d40594b2f0a8c292953112238745b59e93c4cc4b527f6acb526c7909e0721efb8b194b30c8e13d8d5f02920a9eeb59c3f4a46a9562d36051f5db4aba3f6138e50048c7ba58618412d1ab725d529a76f49fd7edded3b5d89418f52c66a34751bd238479e2e6b941b04f7cf2bb68f3442d832559380ae00baf29f7f233417b8286e0522961dd76bb38041442ab877134ebd1687ce9d9159528925f1f519ff6dd654e9270782f00d8444af3a46f481aefc2c04b5df27464b41eee3596063407f823dfdc38e8b337a8983c08b43c8c9b94b1ceb1486f44776ccd30fb25e804adce7cf0464648ed8c6bf2c98059629c20bdcbee7ba74ee840dd980ffa4bd74ff3d88214cca1708733becaa5521b31368b6f266cda49b4b7d73687fbd652f724d45d3d8d448711e9c9f1ec486837cf61cf2cb514e71e47850ce3b153929bdc519e2753c894a1525a34ddb733662237636fa9e11a24fed1365f03fda89de0874a735858e653a286bf180e189b48323931f63e409e7a9dd8d71379a2d2477ac318df113fc2681b6c47d237b444663c311c9ec49a16d12fa54babb8405b343b3a74ba9c2e1e96b65c492197ae666b995d093370431c4f873f0946ec813c82104dea1d7a5c37d9fa394315e9f842fa7bcefd4af8331b0b2ab789e932d29bbe9e96da97e9918a174550f76b585471be759d6afdc42e05b2a9b6a7e6f86738d97c70dcdfac47c033d10ee82930b4376c5b9ac292511776c653871784545330aeb66e54ba3c3fc57e911178bbd931a18b18f2aaae27205938c16d33f6bf94fb4664305b068a9de1f1e482ecfc112dc5c089c28c5b3118034cef6ffde90944a72dd9d36d7788e0e11b670991a4eabcb512f8851a65f129c59b5603738a134f675a2761b2fbae599637fef991fbe4063fe2ed4805589987577f16cf81369ea8a88b0f669e7c70513e9f99b872da1c8e118786bfbda2051f29f16bfe4f620eac1c8422721664710e967345b336da01d667c3e825d2bbbec5af0e048a61e3ed9a5db5da43be9b5d1180c869853699ae5a286f69ca047a4f63bbe1b3caf291efb3f7747d282dc82df41244daf9ac417e601599bfd8bdf4f32fc8ff0f4bbf17a35c68c1dcaa596892a9c26e54dbf18c05980c67dd487d7441b5f3f23e43bd34dba7e015afbedc39ac7585fa1398805444a65ae6b14e8e882b899abc5e9314660ed1879adc3767ff7e38b511ec1ebe03a83ab97523daafae1185a3b6862114ad6ec0d8d9c0c414b68c91bcd40bb068e429447ed58ecb22ce0afc0de637c34ed454e9e7caf02456673be78aa820f386e7a92aeb4995268b57b2ec26524a38f4c1b9cc6e89cc8aeb6b8c21ffc865fde9ea58fac31f3eba98616da7d4dfc656b8a9fcc3b0187cd4b63470973719a97ac96239227ab6a7bd9ff4d1b9809d875639141619e1a9e1f527809b3af6a4661306c72ff836f004ddc290cc6311c3f1378e5f029beb1ff8ac7a24f7ca1617ffe36d6efb58df84f7a629506e32929cdef4e52da24a311dc68b38e817f287d3aa5c2b48eda2279619c87947dd3169416cf2a19b677be61d84249e1330f7e5565c61fb201b2b78882c5f916894be61604fc389c9a4dd7089aad466cf75c77d94a3a66ce74e3472da3198698c622ce3e88182ce30041a6c2728a4fe8247222f29b74a8075338804c6ad9c85410e3a1a460e22de7ee42fe4bc7f5f6de4a52b756f89111c538e6a81abaafe5cb7d96c99db5a5618a5ecfc1b84794eecb2ab879def07784f6ce8dc25e05adfa2a5051df167831ea2477d630ec931a1cf3cb286a9557cc9cd3b9a204f10059920ef58f7a48be58e3205d0ad41e06d4387ea176b5ecf770fa5e66c44d091e82fefeb104141e506028cf2698b17c7493482971834b94e84a137442006785c5b5bc97b219ea8f06412addf7fca972e891f1b25574778142c2f616763742e61df600a08a35285f66841c1edfc74c9fd0e19fb61ea2dbe59dfeff0127f40df742aba9278155f6260e83114df06397fca9cf0fac06d19978daa5cb38f09f3aa946727f125b22343f91162980aaee8bae90a6907f8cccca98276482717b5cf05128c8e0516966c135954832b821f78f614633204277e833db60bcd185632544c78f6cd1d71b1c3990628535122a4801a8f100a7412e1fd5a1725ec85921402908da368ca2f4d2e538879e4a6cd3f670afb77e26a3746c43d405dcc3564d22cc7f8ef4f02e41cbc61b6995853c800049a01916599d4b440a1cac0df2804848aafb676af76a4847f033c3dbb2604cb12cd40f78c151f6cab27d221fa59794e6441f1e945c0ca84d142206653f3da50a3b6dc70bb408ddbb43c265b73b68cb062b98c5621bd1a0b8f45b42c25c379f8f2a22fa1c44da9254c7ff1e55841dadd451c2206683ff15258b10e9180a64e4db9fb81a116af398d3aeddd95109908c9742c1dbabb0b9f692d40849adcca7218790ec9c5a380b708a5ba490bda5d1e0ca041c12afd4e607455c1095b7978742619fa3bba10c25b5272dbd9ae43f0872824ae97eaf44a68d21ecc63000fb19cde2e64ae4f5fb5336460553c359be2026b76e3e25620579fea81654419643eebbea2a2bd08f21ff2fb575795f931fcbde138a4e57a81874179a90a54f600a83946710fa745a092f319a7cc4c0f76570ab96e40d6886b3103c60863c9d8e10e8f8f674e65fb0bd41a2da2165cd120b595fa94e5a34174e8a39cade89cf01dedb8029e2bf0abe683c94561c46a8e2cda0096cee283d21456764d0483a1d5a3be4d3e360be005bddb020fde14ad02cab1a748361199c921440e951e7371ed66bbd0f4b1106c2bd9e3d66ff23e59ebf679ec29d6bd4f840dc2fa27e72d9ba8039cad2a4e5eddb1f4c7c44542d5605a56addf84ee65a04cd4015a3757829cba240517033051c3c4e662cd8b9e193c3ec176a8738ed2aa7c87e127826ae25ac69f2aff7a7ca8f5f50d0093ba4645425708e7e32e4ee9a7fd245d06ab58551802ad894a245c327197e619623d73872a79f58adadeebc7b5d5bcf78b617e6579ceeb5fbb75b67386362d15c6a5d721b37128d2050326d42bca078ae89a06b016428282acdec6f75705915715ebcf268fd2ab72e4a576f2c2076d9957768659522d61ab686d01d605045067dce7b7485456596eb7af39ff31fdbba03e000389ed27696e1a3bb2c77a824f8f7768901cbafa23958cf38cea71c87defb93a7d041cf152c5bb97890a72b0529d86bf1f95295a64ad0dcf7b42fab835442fda19c42445ed2a59e32a2d1233cf073ecff305b9ad13908d9cddf352d781a49366f2bf0be2970b2442598ae94783e6fe229e123b9e6e61f26f7b0319a2b2637c53b5bd4483b41420c9ab01e3c1e5171c967bbc6643a9a2a2eacf4ae2123160f979704cb7a1b1e7193ddd2d14780640ce1dce9ff229faa7d2ea07d845b4284165d539990395eb75525a4c5933bb410b0a7c751f0ccf18c132fdafcf5f6a37db9eff12038b6ea88a277b82b932ef6220646115ac8cc703dc08dd92d094d6fa478b162e8fbe67d07dc2a8be8b1073ebc6a2aac32011cf6d5192c402c7378f46bcab46d7708289218b80872bab1014c873f797112b448e775aac7d07c92272ffac9e237461e8eb5b9136bd73ff36d542eca654e9277c3186c90ebb81c1eeaa1b3d67a6086da77ba7ad174ec33899c5e76cd85bb42ccd787f60703ad576f88099e8895c76d81e244a4d69111ea5212d2aa17e8127904f8df8eb12441bebbe2989cc78bb5d16a6aa3a7366b54547ebbd1904c6114f89a4622cf7e845546d4cea91dee0b520664e8114e8e2f688f102d6e4532ef77e08727feae41d945714e43968437238b4318f270686f9debb00cdbbe7cde61841ca604a52b84c8bdc2d34dec367f0114db72f009bd398dd26de2489f7974dc3e1fe5aff269e050c4c326762439f0ab109bfecf53d1b3c3d2889eec3ff547058436248db994ff98f33eb1cbcdd92ad2d103143fac089ed104619ed3ba0bea80b87717dd1cf0057fc582e0d4341648f3c720ab8a1d92eed5a9657de3cf2656b76ff57d06d91558f38424d78ef7887dc6b20ec8f5b22c88e3e442bf643b745320f81930f853df9ba3a74d99555855c1ca182c6bfee7d82d6040f9e7453e7f444dcaf8f9d829b86e9ed09d48b7f87a9b4322373e2bee92c2f3a3282cd6c268dd3bd4d934bc17eec0c61f65f7a04ce21d4a0f90a68d3a603f47534a8beefae20c785b05f39bcc52e3fcf1ee3843bc92ae6e50336ab891f036082a274ea2a3b5ee2c3485df7d18591c00e5859b5cda238bf097309c42c25d758744800f6f02a7b109c56788514f99cbf4ab47db906925ff638a2525bbf5c72a3e861e2e0624e9f7b938c19c9a043e261d194b748c685c57bed28ca995b05524c3111a7bd8ce9ec6aadc36dad9041d3b54fbf4871aa2a6893281d62ab99158483b6e3d178c9c8f8917488f2595a5dcbd6152ae8aeaaacdc627e27e0fd9e0c16fc94cb6e089cf682e242d3c4625e31952995018253e416bcfe4245eb4297f2508a2ab14138a7bc980235c0c6f3fe9a53257d26771911223c362a9ba0db9eb923e9fc6382e971a5d9026c5b38b6ae3f40d7daab97fb5a99ca1feb275d0f594cdfc15b74a4c9a87ad81481d5af101e412aa356740faea982f96574d77141d17d4831c5651e30aaa7ee99addbe319251da8c55c44a941f7fdee151cb73025b6de97462216bfe6b610d272b3f36376a515b207b521d60f2f38fbe5676540e967f70719f326da19768897673a13723e39698717fe34f1d12525799e7d3333ba00f3f35e081fb209271f299ef985047dd4199bf369a929537e042d29daf3ef846e2d5efed50f7f31f61b6265d249b185a49103c2361ddafa0c0055f991d21870da6c9ee93ebcf6661f508eb519c207f4135ae3b7fd84322cdacf742b8ddf3368469eb7655ea61cb67eea9128793ce6ed51a734162665f6c2418a9f923424ef3eae3efdc6d3727515720f75a94a5e8d7f01ad6fd1e37702a0dfd7db5bd79dd9f07f6023989fa2fa82240f2861a1ff1afb5cc85540ede15973b9ffa3544e3ec019fd97962eee446293387d417952a109c5077025e08a1faa40366c926515a07503656eca611e2f7b63d82b3a82eb28a4c143857bf94611010e08da37b8156a1bc586735229c25725836f0652b7576559cf62a24aea7f84a4d65bd1a0942bb0759e69df030fb4ebdf72d58e7a240706512f578c5af38848f79122dee85dbcf20545c565c46d9778446dc15b23bae2f81d21eff886002b5c06ae0188bc8a2ac1e4ae6ec770a9ddac2861259107b16f24a39b9a42ac4c5e9b044535dabd0969dc80a675041bb2182083827054638645281a7b7c2904c63c17c5217c11938d819b26e18a2be85022563070d4964f4a7dbd6debc1d46a8d6a662a914f2f5b9de01502e61dfa59e1fcfdabdf55d472f14f14e2662a5a004209aae45e920f7aa475927f54586145e7b89883090068020a35826268755f7668b9008a34c9ec9d9e5dbce140bc82e36b8e873d837495f004f5bfef69c76bc35b97a9890f44d331dcadcbf4e57213f5366f6e9704c1f0f73d9182919afb801df882be97adf78f085d89208f3dc5e526adab2dac9279ebfeb3eb5c5260a93f2a22f537c828f67c12d190feaba0a8c157a1f105b89e607ea1c03b498cf6c92f97538e0ea1ad8f4d61906f6b924e67520d4c68da4fa8aa81765b56a1e35ea5c1805f7d077b38ebd23f3fad7890f72af959a09f64e6db28fd85f6ed8d95e0497c4108a071999d8566ce052af344ca3d5b252e23fe5bad38f3a4793bf6680ee4c70d1712682a374404cdbc240fc97516967f364a089f525636d8740774f2a3205399de3fe93488940f44f6c135a37a07d4b9db62c663361ba3b4a46a2496ba896a0b4b2fdeab94c56beff142d3aebe638dcd334d23f3b7f8a51594404ec5c38c29632eedbbfe942297edb2c89d8b8727e02472e2003ab89b542c5036165055f8576d4909eea09b8fe0c6a09b8be580a49d8a4e4c806f1e828a37a660e0a46d165d9b2812eae83d92f046e572d7034d38bef5955a1d6ec9d03bb117869801ccab2f54229ce952cfa289c5dc51454876c7c46012cd09ba7267bd7e75422612a035ba2430ab24cfb52c03f3266db072af440186a6edba896496b82e083c615ca8f13e3cf6898685e44db9238248f03c39f0ac93a732e59d5e92824194e357122b8b1e6ba3f4e2a38e5cb8a49a195541ce415efc1284a004506e8b47bcfe2549ffd0491133297d4c768d180be428eda78204559710fcfca2de482e534426033f82541b3269e05024434125fe901c684a2126d0bcb3a4a483865f374c556ad472bf0e0e6adb49f325f1d6dc8ccd428fa97f51caa171bf0d45bd36659304d0422c0e1d3fb4234f23c5f63198add59b93722fb6acc13fa5252e813a98b7546c41c4a260f69ab418436a42383765356e6515eb3d9e7afca5960b44392e07ab2fd112ad5daacf358225243196989d9b1ac0c443f21f8723f0839d33787707fd522c0785900df801d855a98d2d40105f9b3ccf12b327d2937b589d2c387dec7c8d67aa48e15f259f1b064f9e0fca48a0e2a89778e56d37ddf725c4c946e5dbb67771d931231f645aca0d46cfaeee9512b584f720811db193cfe294248f5c0828bf47b40fe272ef56cdb437ea59ff3768e958bd03a2cf90881d962348fa08d67b3e28f5c417efef628a169fb13c500fdd34fabc36fedf44d636f88c8745ce69a2b1acf54403f5c294de9ad1a63dd941b1e2fd68a7c51a8682561f2ca65c70d407a6c7cd596b5a9fa57db1de5803db3723982561b903b86b512ce628c2be29e0b4a7a8a593388ab28a4853d8aaf003650469053555c000c013b42704781444447c88953502708d5035a2cc6163a5bec15f8e5904caba380602694d53074a30e0818c69ac5075bca34289e26141064bf80561c4dc357cac3ab6eb33885609eae658becde2d96ab5780a6bf6466a57540235928e835280782dec1f8f2543f92784ef54ec009ca4e514a24b03799c964184df1230cac048ff969442e0aa77f44e025938a48b66d18d9fd224fa3a06c002bbc1bef1325033ee1a032d4e57fb108720a09680189d4453ed0f19221cc08e864d96065b03bfc38bf04e1b0deddae2e15695f8f4db2f10c6ef61a038addf55d5181d8fda97bd8ca81b178b6a91afdb2135cbe7c33362491728233a05350c2bacfea541005a4c55a71c3ad6b79a56660e53d4dc8e8f39581d5ad6f2919b8308e68c5a1e72a525b50afc818fcc1004a30502ef626d95193cbba12d0e0cbba8215cfc256e3951df9e2918c1d03d42e9911a4627a94563a47ecc33b2f135f09cefa3b1c39b162c344694ead9503c8d5a314637d31b30f9de991ac59974798a5997e5d356217e6127b12c83845e04aace6b8e8331bae661b7121872e44aab692d1ef942300c55777c3ba0ef5806eb1edaa5a6e6d94fd444d0275a2d09035b199d288f23a8b2b3a1602a117cc047787b47a205ecab058fe6d0801ac9d5282a93f3e7b785e14d78d77f2c2add082abb815dc6c4a5e54979d88263f4edb87e29b752106bb675501c3a2653a19918ee6a3d0fef167837dfba853376862e6f46b745b66faf10db849f0ee3dc02f54c3743ed8b337a0933789e390819c9646952828dc07164322ad70a355c786dfb3b55641cdf7b700c28e4d0c561f3bfa3f744a22b765db51474fce12c6f928717206440f04a89045862f3c9f26f390f6f2e925b3e9b6579cb8ecdd763623ba7706d744b0171bcd18436f248c411516c644ac872a585bc310653461841375298265faa5aae40d2f4e6a572578bf1e5888d3fa69dab4e00807d563a6a69be523904ff3f536fcb3cad9ed175e0541b65cadcf29ec478fc76976458cedbf646fbbf4d4a5ddf6ed1fecd61784801741a4b667c8ff7e739afc40b6e22788d0fbb7f6e1ac7eaf94c53c0420da13a462576e5c2901c13dc0586f4911977616212f5bf7a73bddcbba684e1fbc5055d0469368eb590830a9f8334d181a06275aa0300e05acb90ee30f0242908190df7f6596c5b04c44d60ccd99ef238bf4f6fb2b4ed6d7afe1446c6922837a0d3bcda454319904e1567fe2e4baa6e9912c36025da0a752d943e5018d82c2c0a720a224a8447918d5956c6296f27f6f9c954ebc2dd6a0ed20ec6f649f70368a0f61cb59b01f02a4d75952eab65e2e2878abc5912704f790775f3f34a7494c336498efbeb7114bb5b6f0784b75df659abca7b387b97309abb81892e721c0b47606c6637252294b35d50ef902927d56a8a1c910a77a97a3dcd16535411e7f3102fd5b1ad7acc79dfd71678dae69d1f8671dd7d9c6570bef7ad6c79dc5f8c0ac7ceab2d8968d87b4a4eb3a6df3317b15eadf455cb26ede4588756488c714036ef0e11207db5c0f82f496277d13aed9a12008e3eeebc023ca3fb786192182229b75f3be885da94798fa3f9f772fe183b711d5387547442ae6c0d34f813d0adc888992d797c2f09ab44ed8a6cb303c5451256dbdea20bf987564311121b28c6965276796e5d3eb973026fb847f00213611c08dddb887e6b27c9f6c5e162fc65cdcd83a0ec39755f70a2e5128355281444e25254844a5597a1d446499fdcfaddcdff295d347ce082efb7d0a73adbde756ee4bb0cbe399eed3c3aa504888f66fc786e96eec0ebd1b7d3bbb7d037bfee229e4985e1a03a11d1b34bb5e45049e6d9cae0986730f456314ee12b0d0bf3c36424d5977778aa52add53b2cb472a6af92548aa02377e828e159540ec42318b01db136ff89330324d0ebe67410b6c0599e4bf0accf2f5e3b91dd4f4ef1f07deca4c201c70ed752015f8033edf4acb85522e073fb0e43fae4ed95aa8cbe4a726a25f196b3625801a937f0e7bfdbb7d59e8f0c3ff295c4f62fdc9df495ed69bc0467638e4937c9380fbe1a3d5a46b30522fe628677e67c520135f42b0fdac9cbf77ab3b0784a667b8017d05742dc723396b2198e170faf36d535bbfa360068f1390e3e0171519cf7d3692d1cd47d868e3b688ef6bc52467ab151486a4ff9faa08051e2bd683477fdf4d0ee02cbfa788051c1b69a68be03e0296c871e6303c740f800a2138d17e5cbde2df58071b61c6f131df604543a41f8b37bf09cd13ad240ddac0c446613009010c069729839201c81dc7ace2917f91510c9385de3c1e9ce5a6fb671ec204169437f238f0b32b0a15a7c1c3bd7de706c2e1ac8c4a643d96cdc969d3aadc1f1e8bddd825f4539ed101eb2f4a1fcb5e7c8622df7d17aaa65729eb980a0666f8b3ed5c58a7fcd41621401573de1f1b810553017017bad57ebc88b045a5c207250281580fafc6348156677bdee47e42be213d7fece7572f00d94b1cc1bbd9a5582be2a6bdf8dbd983ff859a09f73cded1cc301c63266cf3782100d693beec511d19182497645abd85a804ee5feb2303352cc82277b74625b3d395a19e6786fc16163afe48d1e73db6d978d2ab35a603c7bab041733394aba536c0d0a86a9524e7553ede63e26c38a7cdab6fe30928a74b96e0daad3b635d9d6f4e3b89f086c4ace98d110240984e1de3bf10262b2e0c10eeaa586c7a13f85dfaa22bcfaeac7fb151ddafe28dd150c7ef6e4c8bf37776004ad50f68a5d68b6f7091451c0165197f537c9f8d6a4f2e990bad009b3219c59468831e1904888ba885fc23faa5e0b4be5df7b894ba3610d19b293971facfbeb6d2f942fc3cbb91e7d84127e5a54c334c350fb519c4e3c8d4755c428e7986cf04dcab25570bb20ce3c934a728dbd283ab8ad6dd739013c2d0b1ffc070beeba833d22a01e470bd55cb20cc7ef893cdce22ca60f303a260ff781b83a70750537ada57a1085da2f2dd5a3f059413022e05c65165c2626035cd54db691ed654c40c5e734ebeebda3ca7c889d24edc5341fd16ef86fccc682e43606a5f5367d44ff89bc5de23c7405128e588dbe7bacd6c97435b1b50fa372389f5aecd3a2904190ee4165bfcd74509def0f8e53a7c161f35242a96e4a262af031b78e866b643c88a2664d9b85a23eded4c17c5cd553eb03cb086da0b07406590263e0039092dc087d3045f9e535533d6c0230bdf413f0f100d0a8cb2bb03966c9163831e70168f9e9ebe359241b5d0ce0fdd9eac73f5c482595602e10e4915db45f63bc1d6137e71d74d03e86efc2ff1132419b5bb236339c79c0eb68a739459f4c288f55353709686bc21dfa91f11828c83beb169e5175787fe44d114e64d904dd364273005350feade79b1617b87625af7f60ac71eb03718301e66856659e65560e4ce60c4d981bb023b01ae260ded66e75ad1e4f3f6e59a0e43d57e9bec7407003e7b1d684c29b99cd2dff7629e84b0f993c2a648e18b1029942b3f567d75063d040dac96407c0aaeeff38098ac2fd3f5e66647f40f6b718c837c49d59c610c8eea404c56d652eeb29ef700a31eac782bbdf7ba10f9badbb0bcefc9d8ccce1132ec99aaf29da9b61f2a2cc1d597268b02584020a68574ee4dfb39373027b185dc87d0372acb63999f103f153b93a329b2b2b6074154a828946124cae892e14e0aa9e40ee5d87a50f05dce3034cf5bc0ad926eb5c387383042f116440bee4b782da895365c102b6ec3f71baa89c06f582a2e5350eb06760b951822ffd6cb160884702ba8d2720ba204dd027e1b0760f5cc0066dc6511ee239bb190a790b3ef33bb17b1f1218540c0fdb6169d06d2b992960d772c2c17b87084fc11b65765c3f41d47c84bf53947431a6d6e3a79ca0fb5b951d8c20f05529571d2b888fc9c6f8a35d28f0ec6c985f478879a2363434e5dee47ca075d791a753387df850e6944dd39858127a15c635004aa3645afc056f05f11350f31bb2534276bee9aaca2fb72d4c3f6518a260dc6b4524fba79a826df7758dc4685f0e1d36a8cb7b02b2c5fceaaa41da703879a18a9818064fb799e565d67dd07fc8e1ae55819a1e46b59e987d1a53bff77f4c31ed7fe72488655af39717854941dc4b56f01446b1a53fa180b4385ca79000108bb888b55a50ff7f8e77d11c49f7641baf862d3c4d85bf3f0f1c0cc041f5a8104d9d061337f48c9afb0acb4b224dadf1d7724700c406d071fd98df60a196717fedcd2f2dcde95e0d6873b74c22700ad9b40435e232a22d7022ec58d311f9f82c151055f28167180cc8c38821ddb33c1cfa459af750537ae48db7c9efecb2bde274635cb9881292edba2ce971392f8d9d0ffc20f01fba7f1d2f82a112e318eb2a32f297014e012635d28069e651bd21111c4c66c12696b362fbbbe037c0e3d41a9cfd746a016ded1455b9ac2f805869fc272a7ee4093080b343e143dc34c751af394cd6aa64d43508d1cb5b2725c2aafaee6ed11a7df28a3a099bad448e80ec6768247b2453241b3f98048d44503dc2529b7bc6c6acdf0e0f92d319097c18ecda824f06a2c0cdd8069a48ebfd5e14681cacd5a50d60eced8cba3c475344b8d70788f5685998f58ed1b5eb05298f7cd75f8a5167e8b168c9a7849a12a07fd9689e020d648502a68c64e28a6a96b959978316a106e09a8f192edd08bbff74f8cb0f49c798183343cbe27a6bfbd0ecb065fa53d36897413da0079bd7edc4bdf028e25e7c372b20fdb0d55b16a54e84b5ccfb672cadeebeeda191c481db73f669900c11e43c40ff5bcdc4e4a75e47a39e2b4022b999ce6d338684af995078bf8e97898aeff6023cfd3af3d6392397e5e8b2289f1baefb93ac6203c1369f1d8490ca79f2eafb09911e2b042fc7e371d93b1ca56b7b4df4887a911fc3f2b36e9845bf4773324e6368f8fddcceba7c9e664418642ec1fac797ed62d3872b6c1c55bb6d174fe4f747854fec37f6ec4dfeb6d0121a1f720db3a1b3144749ea28f748cf9e28e12c974f9c3fbfb751309faed0c1847a23ff974a2ae57cf0160cd68f973cb42499fcc9ab7f47524f6a64acfa935c3b79303237c6d804748d4890bd3dffa069e181b8d1dd34b44a8de2f7d17b5b66538ac9c34ef20f9bae2f8709b2f05dcbe8390adca0d015850b6d707ee0a1d0730ae5b1f69b20257283f0c9bea1978ffa317a18af1834552fc670d0a7074f77dffdb9e2563790277df62e04d8fd6dc3189f4b2286ccb91ffc6e153b4022498793a4eb0032b18543c7586c830b940cc50e6c79ec0a0289cb6b5b47da2716f02404025d6520040bce595e428f231c7ff54188afe498b875c9323aed566bd090e0d2738ce010c6d570a7cc411ec4d9cfebbd660613dc814ee633a7b9d3dfbaee1e6573371e2dff550a37935a89a786febdacba34d8263021187d5c47536e9d10a9b292d162b88e5f4d3329b566145cbbbedb4090581fef162179ea405773f4da3dcc4f0f04dbd4d3a6c4af6a428883ae1b2d36559a2237b7b8cb0a25ba9e0de54b74bcd27f8fb4abc8cdeb451026c03b7a9392a987e7b1d001e19643dcb28993d345e077726df4b1a4cfdc0d35a6cbd1a85d316c8981b4e927b694eba2b0b02f8d379985bcf305e66e7e1447dc34d566a1d760d231cb812d55a89a00a6b5b7f97d873687cbea538c081210d4a25a6160195d676f57c9f2d18646bf67d3dca577349a4156710c92039ed653d8b662bc147454fbfe005ec9e7796e1e0b9df9688c5b8713d29a122e20b38659bea54ab51005fca173b2c9893ff3e765f8576b8feb894efa7cae98ebb4ef3b693689a4dfdad176ef9cf9bda1013073a58d9a6a58c87eef9c1af76b202b7dfb4acb41d715563a4453c2680baad2b3ed0de2a966c1439f1b6b94f7075eabf607ee9b27bb400a6324023b7a105715adc0c142a9db2a085da3bea318a544e1a3e48bf6dea35d044ac269086a28f788777fa10a45010e8cb25da38e53ead8e13130ed8d73fe307ce244bfb6cd23bad6981b3dbc22925da5ee5db64d151c428adeaa234a11b2f8e387a620747f381119f0a48b993457125a6c2bfd1490a6c1f6443e9f92848087dca2637f32af6018677a7c15d7302548778941465966dd6653a4d73171046fb8187b621c47f1291e81cbb37d207b536cfe102200211f68ffbca31f4c2e9c0fca07a3a06b6b3302afe7055eabab53043ca47aa6bd5507ac559ded51c7d126bca9fb3a9a329d93424ddb5ec9a897fb81f922319c76a2a2d1b467c271f00f83763b0699079443c8fc0951a4799c35292862459533f65549a4e56fdf0e6c4ac9eac1b8b2b69e980aae7af4e3a39dfb24372f1aa1b0cda15f9dd716bb4a0bc3663b67a25295338e73c267943f2e53631846a92f4a30f9e35059dbd101a6095636317032188a43994344180304e4f2a09d2cd48bc5e9c0c3aeb70ea87221178fb367da1053a953b03d784425e23c7e0a3fed84cd9c95334295b092f91cfd6bbfeb409d554a8b055a86bfcdc5199d4016b8724c8861abd36754a0c88e507bf871cd8d06707222326098eb0b2875e895a5b382a10784898be57ccb53bb8cc0602e2f8981e7800574c1a07ae65c030839cccaeff259f0f6249f3defe312a6fa04e2901d75d5e1ad164465f6ab1856fd34d949bbe08830d17e461d96f512ba5c0a14a4666c460867708c6a3471c6538e217d9e1756442b4c44b53622b144d0a01b32d13e64b2f7834e4b9aeeda17a66fc334c0a5760c6bdb65220208630c2269c8608850d1ee953b91c7ec60e2d946da2d3f5060ef4e25534b877f1206d0082ab4e11f1e36b371e2cfe7200a2aaa311f6d5c8e5c597574d31bedc78412735c33fb6faa539e62faa3d085f6177949cef3074fadac5358716ed1c3f0710f5af177abed93cdffc136a5833c1f50b1bf74d3c53ebd81984ca4a172d2deb4a8378cfd18b2b8f7d13ebbbf4c19ef5b0c44d8b9520ad340924b12bf1563dd811d0828239ad6ba0cf2732c024a583fa5b79944f050ccd9b61c839b9e584d686539674cfe877b396f7746ac389790ea3484efbea64cda6a816bfa3853f3ee1573f0c08fd2848a4bee377129a2a3f296ccc2f408995fca8773e83472d3b61317694c5fb97892df9b6ec38704f08e349322da4350250f6db5cec58d372f3d0d5ea3eeb08778251e2a9f185dce7dd833f1788f14d2408a73f1d517761e2fe167aacc8c8613bb27dc53310e2527e2231ccb4344ac7fef1a41166bb6b895466db8c57d40a873d535dcaa0771d4564aa000d574b377a377bdeb926f5a59619f68215fa0bb6b1dce4072f43d559885677945dcc524f044db944a448d7fae81e29505997cec33edcd7642e65b9ba4162693fc856b83ecebf065f9863f432725e65bfdef58c40c0bd21dc2b88cb765978e5c04d1eda15ae0f96c543972bf15498212ae10a05f02a600eb2319c33cb7807a7015f8ac2e2cebea9641862024b4072a74b633fda39ae150abca13e8d0d9b75ebe70828994ac68a89ef1cc8f0828b67906d2039578a17726f4e5e0e66e842a8901efb4742649df65b1fe648ba09e2eda96323072c3fc662a85e8f2306f4ed13071bd0c6b17c75b7684e4929685c5220bd9b1ec9557f8a11421685200f0195d28bdc72d34f9e2d62dcfe86170f49833ee9fdb7d7461afe14e8462eda91f833c34ed7d5fd651dc5a6e54c80271dcac260193342d8452e031cd831a39cc80fecd804499b8e5221d9100ba2c331e179a21babc77b0b177584584d1d56fdfc2abbeaa97e186b36fe109677cf5faabe3e1269101118a8f31dbcef562c150d6af53608e8ed0db7c9b749170b4c11df94dc002430c0e6594fbd07743615cac42d1769ca51ed6b8a2dfd069c58240abdb106836fc56ff860fecf80139406d9260212e630564013ff73dc34fc77f4660a138f67d5e5d467e8b3a48afb21798283849b244b67ce814217dd3db093ec8c7afde582eac6e7c2d4826bac75659c9bed2369435bce314dbc9356f49633a26d36145cfcb1c96a9e885fc0b90cc5f9b73519fa1bff1afe85da2417c024039dd55a49f2bcc833fe2868a8af31db2a8188297df6e1d52a6b93896ea2e419d2db4c28ae68122c751bab947ffd6c042c0a9f64b897d180b77d4311280ddcceb7beb73f25489222bb29011fa06c2221a5ad944e53519c402ef0bc818ffe434196a37787d645e5a57428e468de33bf72f3a461b7b62d272a73190e741da4f3ca2cf963138e16e4116d24b477c0888bb74cc74bb2ea40b4046a7fc1c10677389f41726d6d755bc5fa9405dd438ce6909f14c3d8da7a7db14e09633b3804b422080f901e2560e43ddb6d70031f0e1f0e8261ccbd2d23ebf4bba10148e46a62ea26af66acc100788769586b016375fd27795234b4aba2e70aff8917c10f91546feb5c6741479dc49a6d5385945e5801f9f4ecdaf67f811b26eb4cc1c1a1fd04d958f4730ed0d1deaa05acaafaf6021d1b5b18db2bddcf0ecdb682f9b49e50c5938b08a89f2c954cf1ea3b2ce7a442e53308eb0c0d3b1a2a82fa24e4541bf8f9c45684f3d4fde638b214b69c3c840fd465189e2ad2ca1138eb78e2146225efc1d8b8c07b4b0021f82d70a2e09147301d66821089749417785e10575e780d04329680c4c5978ececec8a3e500ee47d89727fc27dc35f81d3edcad67954105640b86aea0310d18cd878efe0b3d5ad933a3b050e3519e40b482f06d6f07e9ca968a6049985c061e81c54bc9fbd6c08f7b7627a4eda6e6d03091b61c119420fbd99e0ec415bf223f4580073ad76413ede89f27d9054446c560fea1de4a4b924afbdf384df32270d0dedde8c5e7fc03666ccf5777a4937b1ed2072f51f39ae9384509b71f73f4a454551af5310b9d6c29a271ec25bf3a07ca374b0aca5ec9e89cdea154849b4cae77fe1687efd24ec8fbe5a9b2545ed74baf0b9b203fde32df4dbb65703acd297998b67a4dea9f2de1aeec6151dbbb80845441365803a14a008e9ec59ea75f10b4f9dba6fdc924c61b4e2be57872cd17e1336ba90461100ca1cdad0d429248a81af7c5d484110078a27bfa5148229cfd560e72435ffabab9aada1591e0fc59e9944870c5c9d34ab7fb292ae4d2a2eb72462bc140c1b96221f4d5494846451f07410573d1bad355f11a42a36a379c3ce17a28c720d13d8275f63ae438295fdcdcbdc863a879158b25f49418f2cbae986d8decaf8c6046cdba51a3c7527a3471ddd8065857b822d50df545537abaebc58296f554e4d180b6dc3bdf7327586ec580f65b6abace08f5a14308abd461d20dc6cd636a28d68e063d669c1fdca0d1ddd2cbbb4e2bec0feb405119de424b911e7e1abe12f5e0181a00479f16d8deb8c1cb0e419a1b428641f169c5840d477c97b40187538d132412a888ada2cdd8b0e12ca8961d0e946551afb0c61ff31b2ade835b083559d79762e30632769a3946077321bff867bdf7464ec72cd14dec2a0231876e686e1103eef2c01e2dde2e6a04f2815b2ea43bd6b558def3fd91fb1e11829b67dc371b72a32c0269b4343cc4c637ff6f6ac4da4ab68ad6a16fee515530631f0c682b669272e3227a5557b36c0ff5fe646c06e77235f1aff5d7d16ddc3c2203941c34164dbbdec0b49d19cdeb57ae8687b06599b2e722469b30b29d90f25f218b767a7b0887d146c65e57f24ec38ecd1acbf806e9d6e1d386e603ed37255c960a783dc745865e776d0c331aa551575d8e36a25b11e9923afc72b41194eaefcd4f7d75dea3d99edb82d37e13f6bfa8fcc9d272bed36ca89f68113a3b5864d39db8c00e5e50891e98ea40b2251e9cb688802b13ccdf32eeed201eb030d731ef9610c85c42e334f09bf54adb10fda05d6211f05755d3350ee2c334660963d294d3d947a8a623b6f64d07d4ec313141a170f527df04235405c6dc8243b555627e5f8877a2c4666c2d7374b9b2c3fc6619e6a9248ddf71c959a42135091796b29802d00587a83d5c35325973c16773cd53f3a0b45f1a5dfc95aaaada7068100c826aba8630755274355ee45ac31150b44cdfe036975eaa9458bee4722c01076215bce1ab3b54f98a8f4490c65d2f815bd33997e9c158a23c942a6623fe8c3fc1e27796c0eac5afde7fe990d392b306af98635e44c431fb689f417c0d40062bdc7b3e3bf25498105da50231b8c80b64e0c63173667625c44c0c2e02e717079258630de0e9f6a82e631ff6bec98eda69532bf09b170b52943554eb14fee6865daa75226d1a84a0987525ab09b5490db6e59b08f0c17c4528f55d35cfb4fb01abb9c45c57266972a907eca09e1e9a542b0829b6610ffbb6120ca83ff4b2aef68e6d547007570aac31396bdc00568113ac1b263623b9a8361122f9bc5f060047d5f99c30e2ed6df63d69dc0d748ec260ccf26acb74282528d12680b6c6690cd21f7f0b787e69c210258b0443eb850aad11cc29d4145856fb261dea94b3a394ccecb5cf46a26a8bff883ed0c37089aa557e7c4729f93ec182dc3ed54764f23f144313015c9861488fc0538445f66e345e4c09d9c8df8827400bb1746fb6325e2603a71df5259f07da82660afdebb3094f433b44a8c9d116a5b907f57643b8f4f654a32260307676e6f6047e178715943828ccf556fb8d273970e03cfb72e0f0366acc96ccb79af81b9fefcae8cc9ba67f9814078c31ec01fbdd270d2b2e7f0ee6530fe44bfbdde341fe89ffed5ae6c6db25e923f8087bcf282712e26363b1ba0b7f10b2bc772b152b379cc26d6a9388644126815c977fe4ff7067c39e70a92954eb5e46206f670b6267a39f811d20f54322037b1ac5495d04a2f361f8499bd7a09f893c9f694051440087ae64d38aa948e72b34e067d3af101e53b271c56a748d670d37b49d824b1c5dbcb2e701781448030826c1a045010e3996dd956bd19cdda501418d3ecf6f3d2137a26b8caef1d68043e7a8b7cec7866e2572a6014f89d3bb964f92805c62acdc66712466fb738e868f57cfd12408b777de3e1bdb57ae45efd6809f4d47b2f7cec7866e25722d149efac5ee0a129a758e0e237a697ce5b4a0b1e92b59d9b2e02adf24adacd22fb4e2b6c7d98b819bb4a89f237f82fe22fa131a8a2a6eb7da0be1b64c3bba5d2a111ae5e3216aa5f0676a4a458b4049dd6f0252c5567f79aed3118ca14407bb24c59f9d9035288efff570b35b48fdee074b334d2bb1e6cf74c42a7e407c340e4a84fd84d028142deb20bed0a558fb122abe8c4c41912407a8db2209ea1f385ed0055b818e02f8c68c72aa9ea2a424a14bf51b21acb373f6dd67255550a845077a8f5a8b174273e077f3ac43eba2c39d23ea3082f34d96f7d7e6701e1c1423f4894b12900f4ee57813ce3a30cbcd84bda3a0a8bd00bd0a4046659d8645de69ce33e7b3721a818ff491cd8b34ba0b1a99b43445447da7c092a37866ae75ec41166da19bb05d7312b6b72b02ce0ff935bdcca34656300615ad1c7580e3c987c0a5f052cb7a278bfe174622aafa236e3b8dd50c4ccfd8199247e19ba6558ae8dcab1b2fda41d6c95f8d27ffbee93a2381228b56855ee497bc50a6f19cecce8275d5582a0ef18857de1c3aa7d1d7568c900a6c805412905a2101e2c3e039e34383e62d0939e9208980b6847408278560a54c98943633688b94743f0d391a2b3db723f29a5464bb6edc4f33cc6fe2db240dc7ebff91ff75a7b11d88ff947164b84ed1806d27fb909ac2c2110d18d370f3dac1d12dfc1b21e26657d98e832d3bd6f82481c43c898636c680c0af6c98728d73e521d4d76ca72834e2f2d97cf209f13596e92736cd3b9bbe7edec0b844fb0237cd9d2346d986ec402081cc171e3aac678d16cee43b512a2963ec732a4c55769c3516c034f91b262f57b4ff11b21d9f042c39fa262c730074e879ed83cc3fe7380cdfeed3b730f4d9efc1cdb47f585b84065c9626726529276afd0e8be5810382e0a8d23ec8232e1c8f8a9c1283381d803aea5f850533530e2994fc3d69173a55e59bdf16c2218a8f1199f8b9c94d3e8e5992a04c4161ffaa80783ffd8e47a700a65586530d445864558e25f81c34eb303d25d21ca99aee91cbae21937bbbed72117ef8b9a612c6458fcc0603c28aa9da51a15eae11a158eca4b8ccef52208c4c2710caf54a9d64b3285299001376dd668f811766a6d669ed13a5c4f37c7e403a7684be8e8d0394df045c4e0f2c1be501911102b4180e097ec19c372dd2473b2b373cb52589fc6b5c1aeddd55c49413315333e493623840c90470984ec31ce9ce800c85c2f2c13d5588510360daad7c394876f11cafa245b51f76f998b7c92c91d1c1fe4e8567ce45efcf777cf294b82a5d841a9c53cc42e365d896c088c9ca56c0a681aa5c934fb2d48801847605a7d11d450545d29af49eed4bea9531ced2b1c9c4895d3229b3199f3321517bf2899eb4efdb12a61aacf8a27e1ff4341bca2fed094071fec450a2b526d27ea8ee3a291ab425024bb64019a3d19c4c90fd0a8598c7a977461d7a05b5ba508e1c9a18f6bf3a8aeb6e800238a0d3133d88855bed8763d9e035f34a0e6cf4fd7b80cc2b28c2a1aca7a31ea73f84c8e98350bff8487e52762d7313f510caf2f24481c1d9e2d2ce3232432c27b151b417a5b5221ae53b5cae4a1ccaac7c67aa34af97c495537368ebfb52d24427018701eaebaea355818d1f6506353d45689ba4a22d42d6371a739792b000e45a47f62837c2c848763131728673ca6db8b492573174ed3fa159c4b469acc203548d115a7886297362b6446c88207fda653430394cfdd31b3519ee5685c7d54bf7b392448f623a8babe3878bbea00100f463cc152d27284777a5adaf94d0813470af7f2963645f289742ad20ccc925f16e504e76ce61582546457f9115ab4e837d4ead8332ce6b199cb2f06e0ed17f2e910662266ae957716f795786056cfaee284f65250dee81b192f4e6e0642c9c91475bcd1871725bd4d136c92d191a38c9c811007c1372f770055da7c57179e488add301518f806f8c944e5f4df539fa345265ec29c29d52458066044d5add20003d88c8b3a9305c7c9460ccf6dc423c76bb9c588b1a269ba636894f5c565da2bcd50d88b218fa49c47cc2737746ac3326d2a95595ca3b7b08407b48bafd83f107519d06ea6dd472e5f591219abfaeceb23a4177c656cd1e21140cafb59b3cca9bba5435ba3a9f8241fb48cc9300f1b822909d41ba2c18f9e7a69e923ecdeae1789e49519f25b86499649243db84b888b1af2febc5e59a0eecc99a15009f7b74e05ea11567d3b9592be80534292e4ac1e0a928520f3cb2d77c9642b93b9467fb83a6156211adc7794a13cda3139f01299aca735a80d2154175c542d610ae96cabede82a159c151b1bfec0b044851241dd311389860fe338f1a82a948e49926f300699a259322bc02c40ffde72e1dd3763e6605041c0364fb36f60b004f1c98779a999bc07fe666b2d204f05711624f3d3d3741cda437e9b052265b71b3a48653cc3f53fa45319add308c0e00fd1a25a77526ecf2ca561be2314f72bdc7319759350ef7a066bce665660626a15c94ca202870ce8db66cddec8d30aed6319b08393eb7ccd76cc0ebc12f6d2c973b28407e5dd198840a14dfe414d20a8e78bd13188ea99e0d6c27872bcb58145d035150e33fdb287e686bebd7d46a47906141c4650b0f09c559c2b6f1815e0729cfdd3c583f9944fa3c98fc015f4b0073978fb92d5b06cc602a430249864ac2ed047b883ca0c47b4203972dd27cca9c89e237cbb07703a21bd64193384a398ba9d51e1b9b667c9b92448d45a68f986ace783ef6e8f1b7af34ed64b96ef55a4dacf21a257e5e4e8a8a8274e185a4321481fc7e1552ef25fca2be31de2ba80d989786cb13e418750017687ff963940474d6fdf5414eab240e50f11cbd1163fc67ab0d0384e90f9a1f87a5362e7fb4678b90a8101238628d07b54645149d6d362725294d835203f303cc8b3ffbca959b84fa49bcf2ab47377701902fa72bd0b50aecdf19209ae6b5e2f01d1846627a7fdcf15f044396797d06de1c2b5707e28e902972c0edf1179b589b8f74b47806a4d36df6af257fae79e77c42691126731a1df86ca112ab041607740163810b09032dec6ec1eeda687b2f45aac27d8ca5261010ac608861a957483e0aae52cb308b1b885ad183dd820b22c276f1171bdf95b971465932fb6712b9717e291b6092c159d018a0c47eebeedabc9280a68538a4cab5fa69c77bd38f2d7d113181959c52421cd53c447d59c15ddca3c00dd352cdebe190c4e687be9c920715e0246f848781a1b95bcc34dea884aca8cd753cd0471b22391cbe8b510b0601ef4906801e4b8d73ec2003ca4fee775a20d0ba4a07d56730c0295a541a78d2dffaf992f0f858021a96c9ccf1b1d563edefb7bfae26568582da180a85e400db8c030a14152c81ecc2f97eb2fd8bb21ad0ceb896c83216d2e656d6383f0c37fb9290bdf7de524a2965923258070f08150740fa860afa86d10c7278539453474bdb1f47913f70ba31f2570c3d5e06bc751ee8fd6fa2dc1cf90b85f79c6378051556f888807c37462a7c442ca1fd2abc0a1f51d077b33fd6108701b17ec8dde37b498594269874810e48b026309f0f6f8a7a1e059dc2eb68023c9076cfebd19382c6048871767103690be36807a4b1b81061fb75f40c78f7a8b2b7efa1ef1807fd734cd3d10378204d07d0e9e8131e484f588e4d9d9ba2d84d514c5f14348ef5d0729fc0fa5b46e4e17f53147adb6f8aa68c3db46fce566a67eaf6d071ef9f3b64b2adeceffa68568fdf3dbe1888c01ee889fcf8fd40ff73b43f2269e43d8d1173fc1fcc87d2a829e5fdf0dde37b27ee890c801e3d400823af78bec7bd31228f4ecd87fffa7025800ff35ef9f810efd547a92357ef3df9ab84f7f7b6f88b84f7f7983c59e4e931c2989c0f573b3ecc5b25c2475785f0d17fe64dd01ffc859a3a9b08ec55f8e8454fe8e755f8887e3e7a3e54f20fb94b78a0b87974de84dff9509aa049d071f77813f4009ec8f68e965ba7be6c9a3a3603b2554ff861d7afe161d77f7de14acaae2f802fcc36875ddfc75782ae24e8eac5c1fa3d746d8a39f55d3a3ac8e30babd3ae954cd1d4a960bc8a3ca172893cea085f88778ddaf573be702566d7dfd1c5ae2f42fd10aab4be1027dd0ec717ca8de3a7dedfe3716e1dff2fbd166e5ec7177fe4f8894323d1f172f74c10e741d052d664e7d038efa359f581dee77f34ab7e31a420851360c0887c9e49ec82c4171896f9fb7f7e264b0e6f1e27e4f1b4fdb3931cde14dd14f92b00dfcd43b931fa74dc5ab3e6e3f8e8fddc14bd66cdc77bfe8d66cd2f4fc9484749e41b1cdf0d0836c8f6c39b2222b0df3f3d223f1ee8a727f4f3fb237227b080fdfcf4847c1ee8238a617628e202f3f99e7943c76da39b6c960eef0eb67f8d0edf47ffe88903980d1dda1a563af4c8d8fe00d0a127dbfe1f5ca8f0860fa127e668fbcfd0a1ad614687954bbe50a1370b6f86a84e3bfcc0a972d9e1073745e10eed426d0f6f8aa41744fe94591cf41ba9a4dae1cd4dd176b9e4a0bfd0c4010ca602ecf7fffce8088bde0b03a0811549b01f1fd0fff879a0efc7cfcfff7c373e3ac2b65601f6c5f6ef2fce567883b4fda688476e92828fd00317716cac6431d1f30fe3c8418eafcb649b1f7274c9a2595942dc7befd14eb384baf7dea3de4c74103f8bc86411710fa96c470f083f27830719818b9de3afd203c263d7c79a0564845d7f845d916c2dd4d74219bcbef6f591dc67fd88331ca26650b4cca068d9568fb0ab1e1a21bb175ca0ba1471d9324553d2145550b139d58d309c12352a68421be130c2a1435e01084664a6003c71f3458d142024d5fca039a0ade0e84096924319e35270c3839a296aace450c66a9870228732a67918228732e6c12000b21a261a9df7835340e3a0fcb28379ffac62395c6551e1a43e0539fc1d0eca0f44814b4c0e5d5c113838c011c1a1e0a0fc769cc8e18e8f8352c6c24f1016238791498f206fe186c83be450c66a64399431ef4bd6b49083425e90c3d8b4805ac4881c462707e032f543182efd7b63f493454dc45beb17c2b0daf439237abfcb3038288fa82087f149866f88c8411c441f26c0b3e52ec17037344c707fe1be38049d2b3cdda5bb1bc1b9aeb2c8c56da53ee79cd6ab53970e8626d3d0903e271929e5087c62f71070bf315ead7cce29e58e313a148e46ed318756393dcf618294d2e952d2a0c9be9f5e22cb3293d259eb153a9bf83011a51336f5df2014d8f6ab0eb55d91d8874d1d6130987d6a6ba530f905a5955a5bb5d44042837b985768937dedcf79ef4dcafea22fe586e264cca1f4e38c545280ab818426040cd0ef361005c1c5a87d19bf48132c25118104c4919445f2e70d51c7a76c16459efaf2f3a50d88ed9a932f5a2ce630c51cff38c60461247981a4c5d117a3c9a5885a8f79d11737d2c28fc2f0243cc64d20ab1f66a2414313b34ac898536598fa3182af13a8f65add6ba9fdb8cdb0e9cbabc596fd1376f0bbded686a5b77e72dbf66dc86d1975c24d1c3d904d31dacc74f583d098f6d2d8f46942fab180d06cfb34db7631c7df77f4d78cfbeb7684c2518aa30c572328eb279d7c4bba770eee5896ef0fb65ad60bf2920c77026ee5af991a48b6bfa4339b4a60bb64229b4c9732ea2f3a299d744e9f5346ea2f4e16799ea8175eec38c39f6462b8bb47d083b86fffac945b20a941e3d2734069ddf16df6970ce23f9af89e76732abbb928bdee5c29b5bb4995b28b2c6adbff8db7c7dbe38dbb553b92273938bd4a1726c741da4f5ba3715652ca3d7d2a5ff829fd4ebef00fc5d4fbb938c9d0c6ba40f06f1febdebff2c3f57328de9a56bab7dd53a52c4b4a44b81fcd169d44441e7c97f6f6d7afbc5b15b2f86e784a2cebb828ad7aeed3fbf43efd41b6752b0f486bf73838a3a4f8bbe8fd580bc4359d64a800f42fab7eb802e7df1e07e7db38883f1fecfdf04d3fc95f48ec570de3d730c658f32287e2460e26e5d091bc8abfc28ae454220ffd591f2751ed3abd0250baaba6f40669168438e845a96ecace692a6ce251a283d4c75f3b1ca41f047e8d986c3f646df6636d5f1070e3a76f3f8c4cda074e1b35c8feae4404171f1196fb6d9f7a22ee553fac21f5f3bf503f7facfb1196ff05faacfb5999f1113623911cb4331acf96ada122cb2459e541c822fb0f89b027f5e91f993af2ed0f4d1d7ffbdc9194b5bfd9e7b4d7d4753ac2906a589087609060b2bf7cda3195972a5962b12f4568359051a54a1553a28e88f0242b0e0e687d7a9271f5d473647ec673a544119f39849834c7183ad80b185aa154ab63087b755809a3972d2b2770c7355bb7bb16c4adfbad44d8ecca09e7c8225e1bdd622d4c0ee3936c764c458cc81c351a50f840e609281a06fc3583dd487470d15ffe313a18e260e0c1a9f3120a0a6ac805656428cf1d27a81d27398c503b3638dd0aca678e134c5bb1ad1fe592c308b5d3b4736cc9df5941714f5cc429e1412331673e9627d0af0142b8c072074d384a06ba7ab0fed9f22179c8e7a48e2a39944550514d63c870794beecc204fa0d7c68982ec83240f10270a287f8571cc9efeca1eb5125344c9d479700cd63b240fd095718ea61ccaa230568cbf28a64d36fd524c7011875bf5d44499a4814cee641356e09e1fce7030c716d92ef5ccffa14c88018334860f5b94b8b2031fb25ca184c35089b5208a16f71a05dd0e48312c54d215f72caec5b7cca02cb6af693a68079c2d293d0c1dd05b524c94d92e2c983d5d4f4684303131050531313105313131e15c617464a1ac18374671b41845998d3c12aa090b557338c96164b248b12afe0aafd1926c33ede93756647474ddf3172b29afb557bcb832a50c2ec8e04204b50534903233cdaab5e34c690c1519ec30ff9c33c618e9a454ce38e76a85f1b437703430d0e0ea73d63a67d2956a639501455283a6fa9c1a6e22a9dacd0b426b144fad3ee7acd46da4c8baadadf4082d43a0a04ab64a3424c85c0966d8c0c30734f8800886c801cb1035cc38ca790c1a50e4ad06337cc833bee0004b152a80a246174ce880e5881c6051024112150a2956d8808b1557886145d38c125b5811441065b8dcc780a95145d6769c51e952459e3bcea8343591eb8e332a5348917dc7199528c0a0a24437a332858a110d737271426bd0f7de7ba30ebc2043839325ac7892d5a6307ed8a008432985293b7680d8714bb7e36c662485e9e79cc1e28b1438f8e204155f528077a22c6e997d5172d52f1bd8a91d675f7ca0b1195f84a161860eb2108363c71909a0d8a08abd4734903a60bb16bc8c29c24b0e88e80109d875242152ab19165b36de718685162f1ab621cfec38ebe2c5125f6a9091f38eb32e5114d165099a159207e6938b06874113345c4c91c5035668ae646fc7d91421c0618a22251d8091533bcea41003b280256926450d5c331fbcccae2c5126562f11ecbd345f1c418307447c0025db1d67450821dd034104b17a1c7056c406f6dd7156c4931dbe6b0a41b5a0549461730463ab33d0688e57685d361a1f66b315dc7c675380d9da8eb39916ec2504e794fff2a3275d5a26180dac64bd54de9757fbe4cfb668c19eb1e36c0b1993cb5d5a9a957462022eb04cd1728321bcd42a88c86293b0a1daa670e181c6a4e5d9ec86396546258b2b67c7191737ecbce38c8b2b365ec9644e3d681a889af1a0341bc10b8cb090b2450ec28012c368ea4c6fc20b17495ec3126520c15cc7261bc05c071c288112cc75944115586ce2a18c0ce61adc01c6512745642089060fb8400673ddb20116653928e104734d0306c6ddcef58a07d8d444520b324a14c198d0a5a89101824b12cc35eb0a18139712065cc491524e298fc2e0f95197184b59dd9d20529f7efd228dea220a2ee280619409a153168bc59cc0bcecf92cf86bee392b42cc9e0f83bf629eb322c8ec30427550b32c537618c9f86b52b127951da200c33ac6965bb9ff53e77ed7e688a8c904c7224224bf5082d5a72f83dc2fb0e48f0005231a010ab6230eaea1927fee4805164e88c8123d8994c3d5f6d60e5e36b8e36c872b7b87293bce768092b3e34cca15db5f471dd7d2d1105088c0881644c1fca517e4c62e366725c7991417380bea8c8e30ae6a224d160412302634669e04158331412188255200ab4f3551fc02c6243e01ab1f166e46e941128c898b0627bea03b3cb10463e28ac284122cba00c2aeea15910441164e3026948b1671ca0657684982513dc1804d2db7cb28a534a45acc89b24ccc899f0e4fb6c401c9284aa378db718a315c9c2776b1a74b200c481d647e5322c1a16966849759099ad84f78400931000b4082603eeff311fdf09950386004f3f9160a10640515f6fffccf4704f4fb6309fdfcfef91da9d8428ace7109720b3a9331802e80fe11e4a33ca5668bfcfbe668ba8ac82ce89d20bae7034074d06cf9afa08554f12287f968eadcdc105bfe3a208120e9868ad2f6205dc4c8189806d23870f0432bd13256254379f9413d99f66d342b88cdcfb7f9b8a707c4b7cd5bcdfa9e3e0b88a5af03f0fffff36fbeea24f2e67b7c4ed08b6cf5cdb31037f8d1fb40901e8ed6571d1a098e8f9be351ebd61776438772df784e7a2e4c015565dfbc0ecef5d1fb21a1c7a743b9bf2118b64df8ad2fd46c794c3fde161dcfe9d03a3ece764a0eda5c71506e1bba43709130e34d98e1d92475343efcc069c88565a52d9905447e8f97df647b5025bccb5b396e4beef1e14d519633e5c9628effcc4fefc673ab2272983abaa234b797d9253c473bef2988dc257c1e948362805639dcc86eb6f84bc7fbf3288a3c216cff9b2b91a7c7fbdf60893c25441ed7f930efd4ce8778a76c7c0836de65e349b0f1267c21de9c8de73e4a1dd5d36cf98fd426810416090fe483fccf03bdcfbb5c3f3f71eff7f91e07d22c123e2b401ff42bbcea6947f5b4755441b40a0fa483fc0a1ae87be81b25e81b5462cefbc7586305adc207d1378eb4b7837c376201485c13ea5b076ca26ca26ca26ca26ca26ca26ca26ca26ca26ca26ca26ca2ec1539bd9a2f68cd17957a40f567ad355b1aededaca7694c5c09777f2fb86860cab6b123170dc436dd623bea568fed6f23b6fc71a61fbd55cd530e72d05712a421536da57ef4eab78486faf6892e9125f7cb1f96f9114675933d350b774322ac7e58480469f62cf32118f7b5f75e6b05639bb899f80fcb2262467a76727c216373e6a8410e650c6a9389c58694ec4c9d9dd8922f6bdac1b6066520f6db996206a63b51399431277f8538ccd38338d20d06dab431e9fc6ee3987f4bf9411e676fae60a5f4e4aa656665346185073ce06207d58b1639a8b5d65aed4f4cf34a4e6cfa518904ab954480ac04318879c1841307ba642186dbb1e547a52216072ab595d24a6d0d7270f6f89c20d75a638ebb17c4e280b4eb3783effa5ebf18aa940fce197cd7f002d4a79c29fb49e6aee1a435061c9702bdd50ae3ff9b7777ef1e74e5158e8f2f37e7dc7634ecee776746197d4e4a69a574ce49a7fbea6ba5945297ee5fe82bfb34523ae7b51edd5529119e585acad65a6badb553d6903eaade95524a7d66ce39e79c732e654a29a594d29d2b96da2aad903ac31886d2ea4e69a49f9cf3a35422f11fa504672bfed571b6e20ea515ef5029addce675aa942a7502af3b81578a04b7799dbd5e77ed8ea6699af6d16b91881dcd093eadb5fe578ac4e5b69b638e953f786853fad18b04addce6755e57e966adfd68a54854ec3492a4e4de6ed453a5663e36cd644c842a450487b724b88e4e4f9552a5ee7778c7b3bf712f7f4b6dcf6dcfd9e7acfdf247b53be5224dc153f32698fa548a4a227212a92ef2c89752aa542aa09924549256db7932552a672a89e8e60c8e269127be9bd768b2b5765efe18b32e325bde34e43f4e919062d2e9a4dd1b79ba5aeca867ce4e736c656767dbb6cf6e6fb78f3a68efb5b8ded8d19c298f3af5d9c9ee2d102a672757fb7a1a634edf2f5e6a2b520c2956198646175a412e7e54a5bc8ee3aadc6989b053ef4a6923b325dfeb34c7596b6db5f8716c2ef539af946ff1b472b313c4e0066210dc408c6373e9ac9adff0a269cba28749198408a4a4526e404e499d367562533a690b5c190859e704c40e9bfe0bacdd3285f8c40e71765881412eda7416e569d35912149bce80c0a17381471183d7a656746865911f079cfd70040e9692437c82cf2ced6a3671cba578d3be2e180ba85995327296d80d357e8c30e2010045b31218f1930569754529d3ac8458f252802404161a5142f4a0450828335090bb1d6742c460e0c39420c6cc82f82106008a3c7794ee4fa47e4bb0e05f525f7b7f22737aac21f5b517aaaf3dfe0cd3340b7f4222ac8605323bdd97a494524a2929a5320b230ec058064abb56b96125b989fb95d1d4267d6a634e7dd76cd5971a48cca9cfd5d734aef5ddce6fc585c947fc551f865cdf7e334a6462944b47124a3ecd392b76bd9a2d8c37acb9660b1b8939f85d58fbc21436f662632c53ddd28c117e691479e2c65347f5aba68d31d65e7bed356ee33e591473f090bc21e6e0576923b3853fa595cc167e4fe3c7ef3a68b6f05bad0817034c71888ffc85795461dab2f1e3f9f8e5149f200ddbafdec6bfe21179eee3c7536706ea8ac155dd751c273fc238effd89a45e7e4be4a7debf255884b68fb0d42fd19e88bfb6691f6b2ee9de3fd6942f243f222cf31392af7d44dacb27dadebf092cc2aa0fbde3607d4fc376cca9b3a68a89690ca98fe107bf90d46bd67c6fde6af5136b883ff7449c7bf94bbaf72722e5d7345d5bbdd6ea3ac2e46ab6aa924f0607abfc1aa35e5db0c9ea165cc98b377ead67b6667c0a6315f356eede2b5593dedadd7be5e6f7effdab618de28edb54b74ac78200e10a4ce1caeac1a943dfda27400a740e51fdf62f74cf7da725d28f9e209f261f117d15fe0d7f422ad6557dacfb09e19ac038aafafc58b427aaafca4f443f7f2cfc5999f908cb7b26ab84789d44ea7258814c42feea22e89f7f67eaf404b120c45f3882fe11f40f87b6c49b7ea4dd0d70e8c71146c038e755186521c85728c1f93d1f0462cefc283904f7fcac5cff6c1cc478d58a3cbe6928d634cfd4a71531aea64e06679451cea4c2a19d6468cbcf748afdf9218dd559edfb31fefd86628efd957d1b03c1becc9b64428a3cd1896d677e15263b591b25cf9f60993c7fbe9431098298637f460fc9222b5464b6ec3d325b57e4d09524bbd202a52e599c96bcc82a4245ee173475543aa9b7efda71e1005c4ab3eefd88b020ddbb829ae910e54a16299b4927bb655b251258a40e2c615fc3b70351b67d18ecfde836ec8f08cbad7f3fa2ede9739b0ddb8b3657bbabf1e66c7735b6617397569cc2777358dfe7a4c71ae2bdea5ff05ef52dc1a2fd92faaa7fa1fb25f4537f75ddaa17aaaf7aed13a29f4ae24284e5e809c98fb5dd5822d9d7744d537e9b999ffb17667e7bacef965aa44c4b247b778c22e6d85fd55491df06142387f1c913aa9f1f2fa1bf3da79760c19f105db2bd90eab7bfbf05d391a217558a433f72281e4556e1fad1c2c8a1c73ce64f701c69064b20bd7df9b149337235ed6af8f6f8cc704b29873b56b69fdf0e07e7f6ad5620ce2ad374e1c2704c1c93bfb8267f859c1337e3bcecb063903b0f91434ec6c9b82d930b3365e0ee3f32e6f86c620738716cc99749946cbf9d15b4525a6912a2ed7e9dc8a169c85f4b4b32262d5b8664701d39c55bf3c98420d491831e16e090bfbc8946014209e78d441e07778e50e8015d3e82848ccc9cba38f21752d2942a461a105ff28608ce07bf10dc1fcba134028da218893c4e2550dc3656ba8f8016255f562a6b95954a772bd6dda70f5a195a29ad146b390a3290a8d4564a2bb5b5565bad0f73ce4a71b0716a2bb596da4ae9779d8e2e74b095da5a6da596fedc3c40c3644fefc7525db7d517d8b54e4701b5955a4b6da5b28923891a61a1825a5d413daba54c8f9094937a6e97eed25d1eb7874d248d33253f2bf7ce6d94c50e7087bfa2533d522b0c43458c3840c913a348a6a8621ac48297e7bc7b7f55eae375e78c0efec8982ef73d77ebeee5b8efb9dbbdf78ba1e37ebecfdd6ee7fdf6be2473771ff7f5f834d95788833e98052c99c9bf1579ec10dab215734220b2652b82fe39e101b604638eb712b0254e04bdc8961f415fc02c2257abef49bd4cedf057ec9038dfc0c892929496ae640163c720b72be6bc0872289190aac828ae14638a2bc558f750a97532486d9bc1a7e64d604e4a29fdb046818d956cff0976fe8a49e0a9033a8dad452de4bda347eb01289d5a1e9a9696644c5ab6c4fbb966abeb22875249290bcef5a6f99484d20e7027f2f893127f853b44fef22343334a28f2c8561c9d50d8b21379b4889f53fd912fdc91527e2eadc9d6461c9c3e1c9c4516e094635a00767d1d79e02c604fed65c05bc79cfaaefbdb0cb5cb112a60dfed2bf7f14b32b7f6bddebe9001fbfe3ce2aada93cbc1a1cfc71107270c525c4f34e6f2e1f2e1f2e1f2e1ea7ebe0f9c6e27f278a7f906452db596daa2683fd0ba9d63b2fddfd6a974a3a8d56bd36c6437ad6f3a2bad7bd334e2d845b03eaef6abb5d93446829fbed4be7a40f053ac6f945847ea7e4220e17c93117f852e071c11526401434445513226a1d4393fce383f6c99b0a38e6beaa83324da6d3f960d39045dbf7a8a9445471e1ae4638e7bf744b603ecf157b75d3d3e41ae1d14842c207a89616ca549526966a1df451760c07899edd0357397cb5dee7297bbdce5e33a32786bbeabdbf41b4a59c9a144429255706eb7652a88d4566a2db595baffe32023d3106c40c927cc50930c4a8c1c9150e4917c228d6ca54592842218acb167827ce70c2353100bfe02c11d1f8fa35406dcf15718c7a0d003ba7c0409199939d94a95f88b483e0141100441d74b91c308352403055304837347486c7d74d2d9d1bed085bf10bc5fb8f2d8fafd23366d1a0ad9f2e39764684b8eb323c821d7ea3e67a595d62c9e488ec65fb1da5aabbdd5e29e201f320d12bbf099983323022ea9ff4ce4e14f03c39cc1377dae76354224f52ba55f9e91c0d631c618e629df3f2b57de57b43dd86aadad34ae936d1cc75f1f41f932846153ea2e3b7a450ad5eecdbe92da4bada5f6520e83e08e9fdf0e9f5a03469e3576edbdd77a4026981a4471b2fd8b1194fb097bb1bdd75e6c2bbe73df19461ed602db7f5afbd4ce98436be7f69b11947f2bb0bd05baed0c3e3d4eec3147fe0eff195dc60dfacb9da6342d8c5686ad4bb97a059865cac808ca97bbcea90537a78ed1dddddddddddddd6710b9e387f37d98e3c647e4c8abc732c638271494524a3f5b6fc5b5627729719c734edb0395abcf4e3de79cf1bd54ba7cd0a4c900fd1e9018d09732ca29675294934bb63ea79c3b2e1f2e6336ac66350322a52e270838aa5dfbdabe0f32b27d0cc4d1f88b629b9d69fcb5bdf4f0471d94d4570e4a7cebdb2f49ae3f344d36e95d80605cd97106c6942dc28eb31b406ddc41c5f6ef380323cce6bcfafd8aefb7763540dcfed5fbe1405a9b6559407cfbcff080b049dc3dde824562c15dbfb904184d7b66c719185af687376aea60a42c7a358bbe7d16c534e6783fa4f61cd5f7dfe9e3a758b3f047af85fbdda71f7e70d31d59f8031f3ba824168b39d936c8486612273196aae75e68e6f3cb40cc079a366b48eabd2792fa88e4da71afe9d44fddfda6f3e3ed3d8d9f13b284fb7a5263709f9f0b336424f5ddfb7b8fbfd3dca774e74284cd788e939e0b4bb0d4df7e6a4eab3ccd3dd64b3c214f2f899e9019df93fc797409f63146de3e45dfc718f8b3ad017f35e46fe6fbd9dabc0f7f77cfbdf6f3b76ffbd487a3e6b87bcef512edfd37d5e30dbf6a9b7a091621edf35fc2aa2aed23c2dbfc9eb9e908c3b1a2e95f81199bef5cf458d7d3450ef33ea59f64800030ef8b1c96faab85786fb50b11e67dd544262cf59a5ea27aed3b4d8445283ff7113dc9400ab0ee8b248cfbfcb12a51918475cfaa7a091621d5c7aaaf5ac2aa1f6b48d68452af7aa2eebd9e298d668bbee7438c9c24f6604fa0c9b6c27221c236ed2bb049a3fd64fb649cbba8b40c19aa72d02945030000000401c3150000201008060422a150200e14558d3e14800d66963e72522e9807034114c3280a8220886118648c21c618640c420a95a01d51849649122bb982f0a6cbfbc2fed9fac3d3c417bfe4543cecda8b843639bd02352156ce20c40b70d27543d45da3c57d4d74f348c09af6f4259b3f8da7b636b1516555e5ab36ef2b614ef18ed637fa0fb374c1f03469d6d82af49436e6d64abc6fa2911a39c54a4742568d5158941d2d2d044323b0dc39bb7ba738277fa1a290b634eaf5fcd65fc0c2c0d61b12665d5866b55dc65af96553a0a9542338e8b201b117e1a0652bb22a6dbb501552d8fa93d84f075d8cd70d7cd85e1a373cdaf6224d64249bc5706444d4843a29374db7fbd5c28ad03dfda13bc425de76fcaebd68ea2fe9ce23f78757e74361c5bee656e603582aad03f2a5f419eb86957986b9804ce729aaa7ceb6665e878ca8a2aa596f5ffb7f1195be1e22e83cebf8fc0fba53d7cfd306e43a232ada03c37a40d353d5f0f23d82a431b5390767f055a2a9bbdcf39129c9195bc227b2f77d945f78f2db38b0f9ffaf1e230a685ab85bca963441cc37133fd65bc91faa438a95d3a2b0161aa5a2ca0df10e0a38da5ab7ec4c6148ba7bdd029840f85dcb35a5b288a7e5bdc89a9d25330ff04b284bb39006220b01346aeca82c45d01ae0e38e8db6bbca6edaacbb7b1c755aec1232ec5150841ecac2179bb35bdca266e66cd9401d47adc0edfc345fd14da1086ab2da244b67cad42de4d43f98fe95424473ffc19d8c0d832213b1e764d5eaf5d7ea54c2d75fc06d96f30b9ac4d7cb52fe391bb35ad095b860a3f384221d14016ecec61046228a3049dc39f179b79e47736ece043d8f25c6d55ba9d0fd0753c6eb219567e9943821ed78576a05f011ac743f35e935ca89de82daab38f4769fdea7af617657fcea6075f60ed56bc0c382b06dcb05d01428df9aa87e3be1021a07355067c43c64c6ab347cc1ed4f1c705af8f643816f2c535fe0d371a6de1ed5389b1790e3a7a9b7cf34e902af3b01d6fbeba3908660e2e9e5f136599c5eaf3e6a5799ee8409d0da1a32b596510fc5d586f7f5282841c1f1b790efc9f96c996fa70dca326a3ecdf1d29542e71ba5c2f5c8e23f29fcb5a8a15afc22bb83c94a7534429c38a750621f8a0a5613a291684379b871d59485e5def477160b3e3e595b68b25fa13106618df46875c83e3b3a346168410dbd8a8cb66f968d359027ebeb52a0b92786a5251c5c91982622fbae146d175f5cc75d76d88dd05814f9fedfcda65151ccef11dfdfb548ca25dcefdfdb6b9a5118fc0549b57ffbfc26c45103db3c5adb8aaef6e59ef2fb8675152ef31b7eccf52ebbc2aad3b31997ae0982b8245cbfba160a9c754172f8f5c81707da8ad5872e8d3b4c5ceb747783a2955e8f935741f42527e2baad5f7c5d273ad900ceddcc89479d8648309d28445c89842e05949bec09d4b314ec9adfd9ee0474ddd640cc1b3bf99311142bd35745497162884122f49852cd71d1bef39db70c938636b375644c1121c816944d7b7039c43eb13a4aaa1974ff4131769841674794da9c495f91b3b354191b18a3cbd6069a8640d1dca6fb0419ce1f84e5f83869ecd021af9ee5244a8bc50efa656fa6698d96d99c642261a114c1584cc2106351ee1412eca0b0a4301b63681b289b373eed33add7693fc6386fe8a92a7d6a37a318a1628c45ba3a3a0cff9e493038d600633b955000c19b4b503500f8aaae4e2279437c6e79c4a6a60bd9454635f16ea5a57d4614ecae8027354fc1fe6cf32ab128c2bea170362cd111b455a4ad0d329e087e7261cd4a65199330d8208cf2688e6cd5008c631e281652a34a12860a3576d679716a8a63b3c4ab3880a77bfd3e0a689291c131b89fcf35b13566cb14fbdab4933e1c216c23e5182a5d8bb846b6f53466a8fa09a1b5c57a2d4d03f6aa394c69aecc576948f69fa220c78837d1c2d760297738008c63648bbd56c81a20868119daa74f125caa7bf6364e2ddcc6bcb1950a0d71fbedd5f5a1ebb301c4c43501761fa3e0b879b6f8d351c83e138476672b8e16528bb426012984f16874045a2b164648460f3591b859d69903475d78a0ce635f6d6eca7285119f3feb2c6e21bea5114f8762f3cc36f51bd251293553d278167250c222b01709454e3214d4a3582ffe6e581a83deefedcd7102c38bcc5cea2506074244071472acd43b95125b9f10c7d115146808f0281515093ff71d1ef318c024ed2592bfb674184e4fad4bd751e0c9ed9c201e2dcbf76b77a49464d33af2c3dd6dcc066e75ec6cf610bc133ffd0fa295e0ca1fad4f67f65e12fbca1070c73d49ae65ce226aabf1c9d3fd3bd9a9469242dde0d40a77a4b4d4569e7902fa7366f7ba96e34edceb84df7a9894b274c9043be164a27d239739c499a57c93ae1838b1ba532046be863c4397b235a6be4e7f57c9620aba1eb288110e822ee0cb406616ab80136f701487126d211b472d66d26a2f22213821a010d7b4f917526a545a1f22e2bbac7087cae46970002ae4f7c3b636949a7b2c7033a519718e594b3d774f0958e8ff34f0c939c17297f7858000838dccf3f121891d94cd0d43750eb1f57eb7a4a8546331bebf28b30babbdaf24ff6660efd5f3af4e45a293dadac2ae2d4572b92e035716a3fc7b05f76fa407c32bff272e2c7b08fd74af6e3799634ca3e7fdfc3d6a968c49e8af2c07e6f708ebcfeab5c895acd475fc91614d25cf24c8f306c567e6e55cda5157901f3acd87c93be3bb28c80cf5f82e6d5ed5302991e101c013e5bec2f4ba5eda07659d3390f3d9dba259a9e218acc6458c2b616d3066827c85e8dc6093f673145dcd491d245405510bc5917643992ac6f57946a8e0877198366ebaa15518f8f80588f226ffa24e5edc00006fca955ae669b832c7ff5a419ad0a4321513fdc2d12214685045a40f918262f468128915749030b93ddc82a7119acb8444fc13fe9971f312d03f51ac15ca73b3a9204d175dd20aef0af215b82f4a9ced665937fc25a285ccc2cb128d52828e25e83d57155a86f77b96a5181abde4ea9d34b384018871faa794ecc3c2c7b88bc5f9ea07edbe8ce3ea86f85e2a33bf2f95c23dd2fb71e1592ad991357ed5067fa840c4f428e68e5669986297a2bd1ecb6f0452a8983d3d26958b232cec74eea2ca0b5522d1fea9d860208e19470b068fb8aedbb51d31a19d86fa7ce84367a440c4dd3f6c5829d1f188f3bd2ec8022dd138838ed0444340d226c6191579ed962e7beaf2a2959f960bea7ba6f03db3ac7410870f15a39375dde383331000d58c52a9d19af29a8bd128e5e8e4017bfb9b116c13d200fb32cb50abd929affc1868d2a815b6f4500cb7e80de0274300b28d6b122c591858f51c2704ec86ce08401a62b2c39efc897f6a471516bfdfa7666fdb5670c0ce7ec5d2f0869a4ccfa733929289adaf90922291b995e1e80bb7dfd47a1e8bda7315bd7c3f7c3ba31a90d5a6f28ca8e0ae1050222079852ceeeb9c8f3515b4cb8b0b4dcb439da602103ea7aa1d7ab029c286117b11ebfd3b9fa7af8c1d13a513af551d4342eefef84d03b54c632046dc17b2ac9773b454983f1fe14a758a1a95d30abb78796f206a497ae8430598b31b22c340a73d84766e28319f7456b9c04802f8e0ba0d65fd07e56e61e3baa8b88cc008ff6f28dc560c5f4c5734977b47dcd9f176a16e12d990816647c3940665ff4a526489ebb827772f99f57ef516290e1b502ca31a832b637c5260c101e10670b2ea21422645bc9a8700032fee6be9489e6ac0a8e90832ea02ef3f11673a7500a1778189ccb68d3237f70de7df210b024d87541a3321c63af6b5b7415da2a3c0851d2d81fce162ce43d01781ddca3eb1363d6c2bf25e60f1c0dac3c4815749a5655a71bd69bc220b90021b86bab4cf7a3fc946b29b5e8ac4aae036886865e67386af0947dd734e2b67bfac410b871dcdf94bf3b412d586f99d1979040eca0e87c135d0a88fc3f75112515209090731a2a1ec5c8a2c61381c1c803054a469eaf55803bee18801de6f9ad9f32149ce5890cd99cfc4d46e005ced8bb432232f5381ee33dddfff3c627caed6ab449fdf2a2a2b875b790928d6ee19a161846ee236324017adb89be34056a515033f6ef53784247bc68181032e66d06c4e1926a59900bc2d594a93e56d7b1aa5cac9e21e9477b9e622c82b113ab142212a5d4d224ddf5bb858823c240768f943ab3aa768dbf25ffbe51e1e8862c72b2f200c257cdef042ab790a3dd29aa01f61d69db524feea4e1fdfee0c019ec9959704ddbfd8b22ae1d3ab828d228c3a19c2cfb784edae74b2e695762d8a48535d815e8f924a372a72623e3d9192d8ebff6eb487e07fb24fa2ab21374b7c127ff3c737c4263de5405e2eddd117a8b17863bb35faab31a58b86ef2f00a44ff5720796a7cc2abfc4fc0f7c0d8775927dfac9eb59a8abb5abeb5dc5539f1cb88cc7a8af951832dca34116eb4879602d1d322b3227d563cdbe4d45562ddce6f9c9799a88b44c09df5a7a6fac4233893c1f5c89242fd61cc4242ed896b8c92509eb99ca4956df89bea55c4fca671b97a9e30f8cdb2154a1e1f75e5e12e45e5b76ef92d75fa40221fe716996f55efea9e047c9379404adfd96d731526c2ac6ee672f5db8fe6315280be87d2ffd2efaa626bf6bbbb0bc9d4b938ee2624118176f1ffbfb94cf7c87b538fa5f64a1e7afb48b12030a1411028efc73021654088a48dca2db914f1c126909fcd1abeae259a746cb9ad6086922a2e350533becb54846bf4739343af04cf6f6d11cecc11a3afd18f73e0b429457325c9017084537e04211764f2758513bd1f152eff6e2c308f52f9dcfed0fcfa26acb2b0d3b9e3f6cba6704cc83fb98db007c6e3951b34b956ad83c3d376bc603e8c406892e915166d82f9df428e2f035e10364665026c45fd8706c350c3866d53594d9bfcd2b1e5d9f3b08a4ded4b3c20ea024bbc03692d11c81d46f05ff0e3c7c7de162511b2e51a64ff6f0eeabf020d636d24b7463e58df79101dc25c978048c3640303211d01d4afe485847e269630de60dd9ffb90050b241d766339b9b9db996701d0d642d37c35a312119da20753154c1087d6b524a99676aecd0a909aaa386bf06d9ec7443918c72e53197c639c8e8b2c962a01d8a5080884f9abf8d44f5f10bfc2a5130bf10fb0ab9dc4446a82c4bc2f94ca9b2ace815f3ee83d97a8af9bcdae7b9922843b50727504f2f7bffdbc322657c94a06032544db5ac86682f0f71f36565d778b2183ef7be71990747df1a5c78ab33738aa137883f2afd22cb367e4323961ed68d34be8a58ea60f68ee2bcfad49561311eb8ddaaa0d9f1d7cc1d98cd112f4ddf7408ac04372a9ea956a4d3e701c20150beb4f18c6934d5478f2f35b0e7f71794f2ce9e460cd849c1edc4c41be0d28dd5e6bdf16d455cb42a6d624c5e1fa802aa59ee405c8a35993839b57945dfb148e5b32a6ea4ac1c8a1e1106d618b5e0dbf73c3dab299dffe558cf6aa2d1785490738b7a3a85b7fd2fd29bfa85d86d180c1116f1dc7d8d7df9382631a3444523db4aad781871fbe1ffb67edc88ff1f8e6bfd77bbc91f26a0286fd7188b041c9344f1ec1d63b504ce54e4f1e7f6bb0423f587ed66077f279a7ec7a5bb1b29c797871017bc74b53fd3095fd40f6976b3d8eaa4356aa2ddb7eafdc173fafe5c5616d45d2613d3c61288e4440bab52480d5a24e3a5d511b1710c74124e1ad6781297a972123b53b6e4c62527f423f24a494969b5ff4bb6a28853044a878422de62093005dbdd934211d0d24d869125d47ae1ab2b890016b87d7f0600cc9d59e34350125bf95d8b8951421de477299bdcb8c5a48b21066a9321bf5719dec3e61ee3924e51402520bbf1ae62a876b5f74264a9d52f1d1e74823858d99a2b69518b76f8b5b4e048a8eb094b77098b30402986dc3c62f913bbc2f3b4bc2fe0b5cc621a42e7585cde2b5b6fc2c41ba02c6fd23436984b17a966a35edf6a2e3ebe0298d68829c023f9f38e4b9d84ac1ce2ad2746b71242c49192a4f1e1f0b779632fa0b6c6948a91a3b34b256d08d73bb77443930988592d39ad1196fc71688f77e9ced8550ea32537877016ac9fd74ed1490ebbc8b617bcd8a2063ee04108b2b312759ae27db35df104bad97c0689b6cd55a923fcf07bb23df2357e399caf49468c7b4023ac0c918f18c6aa4d91e15298a8b0446ac3ee855d9e53f6300b149d94b0e09d944898679ee949cc7f3bbd731dee05e9c5a8fc970ece0dcbe23d4db1a747fe4d3105d702f6882bce88a9a921055464893a4ffd042f584da745ef374cb7a020933baac16bd1c410ae920021cd0d3f5f51bf7181703b6803b6b866dc0577ba21f11168699ef25a96df95e22d0e52adbb40cc1c94e3ccb3dd001c01a34e11327872db2069c130574cbb18b46689070228f57fa082a1408a348811e00753a6c931db643f35c4732e74fc2a1a329f93b5e64b74e70cdc9e68e69bcb55e2988436fa8889e0b7e8a0743e9940d3093649d979273143691600ca436d098cc968bafc1ccbdd7adffd46dbd27ff6147db6ab2a6d4d36c70ac6bc84648b77c7edddea48d022bddea2c4367718eac6e29a66c325423d4fe9ef7969447d4cad0131546b0c53cef29e50b0512c35d8d61ba35224cbd0346e7407938760d8f217c0b7577a86fe5c1f183cc00077016b6902effc18e633a447c51dda5300c59d95a9a685941d832c593e002c0cd31eb4241bc8b9b6232846482c4e8025f86a5fed3a444da5bf4dbe414ab502d833e1782a3b1e5f4e54decdaf47f023f171a45ae83952001f740eea71fb493c7c97039ec2250077ccf942d4853f940c23832218a3dc6cf9a3d2114009ad73b8be77ee0134925e63b8a300a5f0c95ba5ebc365442e5a1c5e051b23b232dba520f221531c696a3dbfb6f909dffe405e68f1a94a90360739bb109bee46419374349bceb24e6f7f3d52735fb19052ebe4139a2008a212e85b201ef120e28691c7e2f53739b6ccba46187b8d5d75aa247a16c2280ff0e129ac6f1dad14ba749d49f5e94c0a112bc245d88e4c0d738a87fb64055b645610ae3bcc22e35610686bfcc05a957251947439bc41142d39b1d843699b1412e0b473c36640e0b952684354a08414a50a49726db031366f249026ad9b9b61c7d729042cbe204430b00d5aeff3dffecb067175eaf54c712eac252eacfb861bbc60f574d77987005058fa6eeaa307c3c55cdd91f6fa3ecac4f0e031de8599a9ba7cf101d8170229075c67d02a60f559e8d0e7c6c020e4673e5b9787a6c6a35a5162d8c88a7901ded1844e3cdc73a630e6df1f0f1b30e6c7fcb323f081af316b3f7b809767177710df5a2130c02fe2eb10dae596a3324546b2ae4b952a0c77e6bd53390bc2c31e9bffcdc0a10409d008d9551f48dc9266b4680908c8e9bca79c0c20eaaa147f6711816121b333913abf67dbabe8294502a47ab825eafd12ee9b0ccdaf051c2ca7f3a2ef3c67208623a4ef675bc9feeb7cfb5b0c8dd4a45b93d7006780557961555f00cbff85f54f52c9bda863e8c5dc4e92dccc028b9c10b56207ecc3159e569e0a2dd5455e7e240947839b48f1459570e644173d55d55ebd0871d993a158c0939c54af8810abf0cad938e102faa09c8b9fc2e7a81ee9f8b4c532b8130723a113a4b563a743e8c220ef24733b87229b16b3f1c592d69d8a4b947f410ed8e24d951ea4d208e24c42c33db745284c20a4a7d31e733182d4e91cf2fa892b38de9695d6ba4a4b8082c95012e51c0eb37682c7c4e3c4f359e6e6f1fb71471ab9b2ddc1011ca053b10eb2a274ff97c0a08439250fac34e25ce7098965bc8ce8a3127d1d18db474d51944fb7f8a4b0a6a8a93b913628b66e7c9dc20f4f2460a92c0f9eb19587d3ec95f97a9e8c71a7d0dc138912fc86e2046b8365ccb38fdf1fb9770ccbafc1e972640953c3fcc0e2c7f8aa1458af68a1d03d58ff0760240c81be8631c5c96ae14e4e6b3f12c0e2c5caf56d2f14fd9c284c0395828a031dc5909437775b71468571999003e4a735367dfe2b33b0e1896fb360882b675c0893b93d56817188e5b7ad6ade2d1d3706ffbcae3e72da0231c902ac0c03c9b58c2001b5e6b1625346f7f2ddb5c5ccb402b84f10b2c20423ccb78385f9f6c1011ec74686ecf989bfe705857ff260f36e372139755d751169dad01d3f474d60bfe0d006bae3b232e919ad97877f1288534d96012032be306a82f814513f18fc81836129a42b7db8c9a3180fc2f7a032dc48df7bae000d308fffb6184a6aa11faad3a3e1340da3f4473294250729cfa69e43dd115e6851cfb07c607694e6c353783c9f67f59b916489624af380c928657f7c534382a17a214565fbac284af416c1c583e158084acde6453ef13e82766253276a4446688fe615618cc3b748471b6d3bd3bc8882cd5639e98e8b814ad748e162fefbf5b1b655ade304d89022d78e8532388bbb192f76c80a2022c575596894e98edd573d7a79001f783118b1460362a9cb32fee1a31b26d9f3a83d832ea1a6584bf05e0f1d82276a754821217ac5ba9c9d17b2e8615345ec7ba00e01f1025962d14576f2c5233c593965824fa9d64a2e752f39b7f9350037933b0046ddb0423aca1d666621b714d2678533f222cd19fa9a4158f10a24006ce667972ce9804d3421e289e9112c2c2c4517cad25070dd7ef17d64e01b55aba2020b6da66453b546408b3fc87db840beaa03d8124cbcef56fc74be183d24955fa3efbd0f51b2fd593d65ea89508ce1a6d29d3f7ea96e739d2c208b545ba7a45fc085d0380756c441399e232cfe047649bf9bb033e3bf41d2f6897017048348b3e510b04a747a932735aa9e94477f6a6c79bf83062fb53a08cc5581824b498847ae24d23e4a072c9b956af0f6171016671b52a58e61749ac3d499c0986970d9b3827982b8669c3dfb91b00298317bf172faf6a62248d5b71e8c18c6643e5f36643c9cf60f9fd01d19046274931cc21eb6af73c30c1318660dd46c30bf2c7cc0657530d136a0fb1b93640400047f67412a8e6add5899d61b10adf2436bd80976a80e66b9e5f018db1d4684b02ebf9808bf8855f28c43172206604f236c659a7cdcea9d9bac1f226e81e81e98acdf46b050846683f682872e6e3492e62cb39035627f0034793915409e5488636afaa6e58f88af8c48b9163261f08d60721565480f2ece7801474eb4cd252442080391659e965ee9e9936377d09d4814f05c8da756f7a401aba995892ae073b753caad43a6b4c26ea14db35e8e44701591ad1047e2b9b65fa1423d802d266e9833c4c6155258739721673668ba3d3675954dab56054a50ff147e7a045160a51eea7a34110557406923231f2625b83aa5a594abc8e72b0b381311f0d76a1919230343c11e3c2484dd56cf66c130555317d21dd14bbcc055d9e60f8a0015e1ca39293f47bc8ec6c0c0ba77b42c2ad6a4519a7e205be67c29478f322493c8d2074585982c9c6be4d036bd63593ad06701a7a3ef854cefb7b5ccfe98fbd4f6e6a62e4b7d9116db086fa188e44548b1c1fa2c7a65598fb0c022013801ea456d5ad44c33f24013594eece71b75505e489e90488cbd54cc9ddbc75f423699ee3fa442fb252c513dc1396e7394dec4402e9b5b49a7d4655184b0c11b1752c91608cefb8f97142aa82cd7a993452c4845492a7b0256e885e194e2db093929aa3fff8fc6bf6633c96821990f91b2857d9002d16b015199dbc1d0a0f21caade5ffd402a74081bfc80d14c0170fda471f9b710f74c743e22de594bd9e74dd4257770e63e07811dc930f48a05ce807cf60eaacbdecb1265d6e9a069961c943492b7e79e0782e1fb07037dfb358144ddf9ab3cee2d2e35c22ba6c1c6fdcd39999ffd35c6b92428d0b908afaadde4cc0bcd39fc2b7739bc13b335697fc2c3258856e86fca427255feb56dbeea933d240f42d10cf93794c4057c1898abeefdd413f516c20a81c1da423638b85eee8032784d5dcebb1f2780b0470582192b1c9502138621ac56ff04514e8a7411bb8314d063089f1186bcb2f8511b9c96ae483a80fea0284b705c76836d6d64083358594bab0cb22bd288473338bbef6737b84c92d57d3b89675d58d4675189f6d736f53576b58c0ad2837792012c11437ff513d86294ab2c1d847a2858f88c15ae08eebd2c185c6205435f6e984e7cc8d9ac8ae041df963b4bf8a12cf40d520b41dfa4ecfd7d4c14cfecfb7f9afa9a190c79b56cbe0667b1c1bcc513dc335c0642ee54f61f0e0d68f0563daa06e85a9a199951ed455e1c367e40f305c35c7f01670bc695d6c14b3913293ceb60e36d4b4db0f767431e859d208161d7616768af7b15ae050de66ed36cdbf3dab09fb9aa2c50c8e9b6b711c677d64f643ebc8d4362c5ce2e98f76db8e592259093ff194c950d75040e9095602ba633504f94172d70ca5d4bb189fbf5d09da5f85ef02ff82436eb7b2c935803caeae8d24e65ef215829fd522df7d7d06d7f11496fb87b3ce6856e01d6d9da0cf2011a1243b74c2d5e437d6334747d8ad3b8ba4ab656959cdd0387d06858e7732582204c2dd93dedbf0a6a13c0cc260cb94726265d8fa56e7869907aa391af98e4ce726ebbf26b5ce2d376bb53dc97e33ae722762c57e867bd5a929443dbdd681b39d8c632454e6689c05ce6e9967c2f192c30f75889c0ad9b51dcfd338695a71ead44e9110ba945ab0769cbf282ffbd6bab2e7a813b97ce7db68f08fb6bd1646c3021670539a72c37fb22d0d6ae701e452f9f133fc8336b8c6a501c6087bb66dc22391bc56ab1abb30000b2d47fe0b0a1a95ffcb6a14267e50b954192ca59dc5f96a504a24ae29ba3d2120ff6587ebad14c941ac74bc33430bc2e615da78e6b172b215ee0921c9a270c912c73e43b975fd5e6293806ab06a88b7d815af1a44bc30e825c3776264fc36e8a94d0de944b4a344c1635f0b08e0eed209758db07225a695b3d6f9405bf96c057d949dc131419f6913b8495d7e2438006d302f18fe5b39f1c6a2be0698ea65163a14928f3f53a10fa17f674d6bc434a7588f20e075923062a5c734596b70ac88ea4b798462dee5723da373ebc6efbdeda8782b9c15ce606db43745a2fad06a281925d9eea8114a23bb4b45a1565861b98d246731c54ea9f9dc505c16527c3655551196e6088450b325fc75971abf4a0cd645809b7e702e2bc4334de8ac9e1aa7f9204d01ee60366300024ce30872a6d33d0fdb8bd7e71d5d8e9a00cbdf408d47e1c765911d6e2f2391e6d92d443f4b81767b1662b758d0520a02d5ded5aa4007178741d7f4f958da72102ca1b8d9b8ed65d4057cb76f621083d5d56f090f1fa8cf67adb07b024dd27491bd8023080e698353b33100fd9c661831466db2d7e35d920094549554e0ab54da1244d834a2ddfb5cd876bd030b65cdc6d21c10247335f4a13c556140dee1fdad48bf21f55d0be3203bc03f78a09f0ebbddd4822f43f612d1035024ae5a001155a4625b7b16eac33545da1f49b40396ea50700c4465eb46b873f3fda0e02d79765b1625fa64c862b321c013752cd7c782c252b6f843d303d6e2ab2f99cea3b1f777f56505476c13c05f443eadc5aa976e70cce32c0bcb5e4436e1abbbd469a522e26864411f5c6a46aeb800f111693ae85c083db23d94da041ee3d7ecb05ca8f79a4c0b60f832346020d0cd706b453ed3c9751a12e0279f0f7cbe66a32ad606f9ae68f653ab97066f149e19b838433543925b54be09e10e0b4d282c2561825aa4871986a6ddea15a212a9cd6cbabdb1fcda2051bdf3d28c5aa29d96906993c49ef1c598df066e904fbe61e1394f03065787429698d5f8cd2a8983662dc984c735529620a517540e29e0ce0231f64e1888325e7dad545f83baf70bbe2a8443319feede9e9a23a3855c90be74839101d8053ff4f4c4fd854bbc3745b89d3aaeb074da4204423523b5f485114c1d0cd4d6af4f99c3b69406ee3c758a37456338a76562cd5a189ac8b42c1c86673f722101134619a9868847996176e33129da99da2e81c34cddf91a6530edb029c41b03a79d16e1d106bcbe5b75b3402060434255bd4712f378081ab0f918819e5d963f871621cb7f92d02a3628bf84f0471751bf1de4a0b1ed7f5834354008eb95b8d2098009d916a341a1ce459192104f2a957cefb8eba30573cf711e6342aa6ad8df09377e0676004615c90917513843552844d7209cc3a60f6e69fab31645f51765117f59814acd667587ba7d96ec75e8e378fab14053b54b72bf6357034d01c260b56f965caee5f366744163ff671ed791ef458b0f99490f8a0aa025156e549f4fcf5481bc6facdf0f0dcc1c3744b298d9b15c5aafe6114bfb04e6dfda461a70c18e6a51fd40c054d6f1a87a9ea5de23cc943b1da2e7aa66a484a22e6a6657a0065a101b30118e5606b34c2b74c47f3c8b75b5309af2e1b133f60e58b1171579c31f3a6fd48ec8b144d2d1bbcd1ffbde768bb7e1dba51a069a75856b596ece4c9eda407a8aadf0b4d06ea302ae1a9d4edab900a57050b8a51a6194611f702d61d3fef8701f18a8d5162ee9ce4114112cbe40eaa5a6107efd204d264de9ccd15c4f8d979cf1415f570371d59c7aea5757a441651338feb1a16ab3a0a460c06be9c3e8625b7c44f42754d9cf2c13221286793dd5ac40c12301ae7edb4ea89c3e475e43408a2e6f0afdb3c8061b2f7f30c13084d032070c29889490848c5e299bd7e9fe00d2cdc5cd26e4302d5233434093f5a6c5248c12f46ab92d8a899692432aae5f215142fac40368e2a6a31eaa277f122e0fa45b463136f66ce16c0ed8260ca3060682ebc1850160ca150b520209009bace91cc2730ef8428b5ec0a637a2b6ae5c77fab836850255a6b09512a35f0e7b6640d26fd22c03b3faa5a8a867a691527270e9ee8ed9a1602c28833531d3fa029cfa7e2f642ae4e2e12122c3fe79fef7b824f98dfc89f13aca3370e0bf3e62d3af066708e1652fea2eec13e78d7f1ef8809b2a7a956f3e5d2f7f093c815ba2077aaac5406fad390a7f82e65d2ca4e2665f3996a1b781bbbbdc71f023795fed97193abf6203f9643d3b6afd099bef22e448f8ad327532a0b211ebff9b02b7d5edbc1cf4e7c2f0a20fc44fdbc375b935290fc0592259ecf7feda369317371430c826c3d571698c163fa6c5bc35740e2030fef24a16cd8e4a83b11413f8869e862d7c9aa2f8919eb5b03cad4f811fef42327c7aad5cf8502229bf136100a61e300aabc2dd51bcd9b1a1be80605df1a1f45505aee97da95c2736ee358049ee475c21888873df29deb7bbe5672bd6ed979e09ef54525bd7bd037face6073329a28114cfb83fbc91bd74a3899606f70e09945fbfbf4eb18b770e17ee86954a6abff8246800f3a52010c133c1c475cbf7aaa040bc4b8bb76c985640bd577c8d5ef4269ee1d9e73c58b10b062cc743601bf0367bfa1676d01af92224907c6ce12290b8aa77871709ce1807c859b3e3cb1efc81620b22a7a40e1d581a07328e825300e16549e234d7c8baffa6e79849bca852988929f87884400330509e5e4e92682165359818cfe6d8992c70e7073bbde1ceefec5dd4a6fcc7347a0433248f469c08cf874773add1542ea21ba3e9e2902a9a0d8565d00d0a4235304d6b5d15d47ef6c0259aea556f280977cf453a24bda528c5c21a4652d1eebaf9d7b45c0277313d7a209f6dc82040edd77db0925a404cef493da27599ce5ca87f10a13b3851ca157c3fa6b040f5775dcbdc3a92f6b664c101922a5a85f99f5a58f56f0705e0b9fbbb27fd7c1c11cd977b00f3086701fd5a7140a413aa20f11cfcc04ee37ac9d3502ed5efc4bd11858c905650bc22a932f1a2890fb89a481d95044a8e6660ade2ed11dc51f600c18500e3b913ddd3a3bfa217c561ac7f97991424861caf976a694c3910a8a961227149b55541853edf22fb3ee0f0050f296bb406c8035830ec932786e052a63a22d88cbdbb85117900623a10b314d8f546e8fbc02d16069d053f44fb885019fbc1e05944ad55b22523a269105c51197077b07648b2d53cb8dc21ece92fe3904041659b7a73195da2f9ebaf2b1a876c54e35eacdfbd6b6dc69706391d00775fbd0f6b5b1ff87da95eb969241e5b4ebe18e8e08977af772c2baae10aa849f3ea224c4a7ffd05baab397cfc37e4c11474868fafb6d97bec99e083b7a81d258301df520ae2350bba78057697f2b6c8f09878aad2084c10a0c874bb0e38227f60b0077e3d9867a7c6718ea2f64dacf8dd564155efe736cff8036bf33596019d09d107d5cd7103de138190f00e95b10de95b0d024b4311ab98956c917e791aff49a0d704a3cd07f091e51c482116bb1c095f27ce78604fa71c74a2922138f320ee4a7b50fe4c698c973a01b42d8c44c68b7c1422be0252cdfe99ee38cc0b04ce3fa9b4b5730c3cc686ce20e86594407f14c8402048acc06418d14b474d4d00761df816fbcdca0bf25cafc1df5f4f9eaa61a5b0b69fbc2f3e648260639c8aeed59389fc425e390a394048555c72f9e5b2ef86c6479af5d0e388da6c4ce6717402980ea5f50ab835f0266f22ff7957a5674ae31ade2961573710b75278a5e792729e81be5ebd10570d305b770f6af19f31889b10fb95b15576c1282ff7c72759b8eb7d42c1967d3452878e93ba02851db93c271146bee10f5c3f743ab8d8b94f680b9a875ecb0c895839064db72b813b18aa3d06cbc49a707a51d17193d0bae71d5f3b382e8859c023863b7d1c5b4f387de68229bbba5594507d82cdbede66d0ec81350f9becd96f20b147c0138cfae2f366f621fd1e3f550572cb97ff7a1c055f91b25606038bcb94875c7dce46a5977859120d29075d48282ed3f20e6c2ceb3c7c0718dea1b7be1c90fabaa0ad3cbbec6fc093d2e386b522393631453b89f22106c45bdeab146c5af3fa8cfb44e20da29eae95d0494c32d66b881fb3d8d56fec8650601881dd9cd7462bc800ebd35957859c67d68a0e62507702d1bd8bc0b1eb6cee2693c5340a7dc10e3cf0ffb48a7402322a3da7e0238bebb1f29e98a608cd2a90e474baf1f164bf9b1a652146235fe2701f05ab03e4d6f9937104a1a8c7f9443ab2ff10e17cdcfe2235dbce7f29702fc33f82958e74ae651fcd9e815176edccbded0ae1042aefb1f84c26fccbbe384baf325198c18c2c9e9aa38b8ff77ef8ee717863f3f9987efce405c9849c3d27377f9330c3cb87361e0d67fa44a2b9b98019c1996d3400704952fc1ce0565320199e873d08382e91f022bbc56c75832b7a36f776496b6df692e608ebe7346a2b2c81851a86f1b4afeae66529c6767daaa1eb176a7938ef3aaa325c5525d0d8e40261f931160ac53add06c35b2d1413c3ee0fe60f66fce1cc5e48ba855fbaa076bd16ed82c5e6b9190d44b0aae81af47a13ff59ad34ce9af81c122e94fde5f62620c2aeac4b72a2bd609be7f2e993678d495685ada8ee79be24c1b2422d336f31517b59c9c18202df64146bda277aa421c70c201bbb0ecf506ffcccd13b0e53b49ecb03e1ef08508ea4dc00dd71243e48c7dff3a65df993f56acc53e6d42894ad1cf2182a8019db2b91e46117ba8a0d3604a0a2176e10024acdc0a8d09544464d5acbb15363910a9340e6dc56fde4247d8876623ae6e2f5ccedd1221a79de46f175972ddbcb4b0b07ea6938435d191e0b683e7548dd6b3ca21a165e680714800284458bd84b4562bc11398de06101a6610e06502e17561aef547e3c5ea15f2087fd1459d7e9523aa3ece8f1e6d5bb4312766bc4531d8a60956afe37b18e73a1d722d0730135ae6b16376f32aeaebbf0879d5b0983fac4692f1086dffcc83c13532d659eb527e904a565c5449bcf027bb892b49705d1868bb87ce6e31aa7b4a0812a0d202ca935c22dca9709667337c2e6113f9ba9de5ac3586d0d1d6213e2986d6e9f16ca95d884fc3f54b3f78c682141c45b79b416a3611ba0e6776103a9c6f4dcbcb1c313f1dfbc48554e604c490a1b695211368b7eb5a91c99506579e84fdb5e7d61811ad4c4be4703e9d64e3e3f5a6457fb6f0164c552359d710387f5fecc32288f5f9ae7f54357d52b363f5565ddc81650b2fb57aa0b07cd836c6806980942b08a8a846f8a88ccded450168f5a8a090095168bbc9b7901c7dea1e5863450a797b6b72d5fafe6fdf77cc7ca25c2744e4dabf7a66fd6009c8c15388181bdd48268260c3338c9fe802c8740657bc664a04f7687c40f8574dbcde1133bc05339655eeb910a15b5e2e60f966f2207a156ee4edf0d47f9187502c67292921a472cd7f73e4d5485a73081681fc4ae76e429e32d189e75c0bb48028e45290b3735173a9a56e04c603654cf2fce060b815cd7952330281c74f83ebd57e8211c4f91642a53bb8a0dd168e4e46f20fb60b29a598f9faa41117d0ec6d0a0f3e485e53477fa1151520fb4b748fa141e8f3b5a394d6e08e9c74635f44d0ba08553c9696855f43c32c8d09528cb7624d5b61a11173b3c51173fd4fd7988cf4f0903408d9dd929934f2885adf8db7cc18a3ff3192e126508de67420b7d513fa1c79fcea43cb6f405f48ee930dc0f80ba8670df6f4a8744e9e9587421d3c7d1003a68f1e39c74e3944e6e20b4d5a28d1876f9c309d8cb297783886520e34b4eaac1328451957bc6ca65ea0e5c8c9b733322cfe229c35633ed69156bc5102e0b3330e55128d8ea1e7a65fb6d761ed18aa4a7f55563c738d960f3c7a1f669e6da08e6708133506fb6a7b2cf66cb669571761be9af4b900d43f25ab6a173acb5aa6498d6a4e9ab0325073983eda9e3a15950ed82963f650c51a2374d12413e15bdc06837ff90261b677909a288264e17c26e524420eaa20f8ec3314a9f5aeef55a30c76ebe8a387919cae579beee42590702e58d9fbe2adea6d87f61cdb3fbc4ad160990e8567875744bd051eb28dea97840a5a692dd51c6a11a53bab7e9a4f0c12be2cfbde340baa818bbc5c3f4c311abe94ea43181424386c4cacc94ba78ac669715170917e797f293258cb5382eba6d442a3c2b1b6c5bb034679121ee7e6ec5ae82cce9055f58a46a753cf169f715542c93f744bb563e4255c165f6a66c12912227283abc50d0c36343fe249db20acce81ed99f58f81cc3f694c135ce3367b8b8098cc0de9b196c1e08b98c8848547991d3e0a8d1088e2430b919df65cdba4ea21ff09631a2a77bd886220a6f6e8959ea4df3d42ae511982464bbb2557ebd253298403151e66d66000ab88ddfe254d9980f99fe917b2061955cdae91345ff90caec5fe0a80a50d25aab11bf239512446088c2fb5f0138f49ec246b08ca349ad5e463d03e183e488ea621639ea260797a82130263f88f0e440a6a8d8ab576b7f18398292d7a9060f615c7047d27466f536e71f9a045321b23cfceb4eb00b58f82c6e4c13c514a263b68876461561a7101337821215d39f602a5c770ab408a2b64d01526d5b8e9f1cf7261b11ca3003d29eabd7c90809e14f622027b855afed059bc4b149e279b288591ff3270bc26de46d5e0733ff39f2ea9641c9c4687038c7f248bed577a0c0f56795868751de0fe64f7a43942e3536e769cc875e9a233621c4ee964987841b983f846079f73f1eaa9f3facfea74ebdeaa9cf8ea8040cab6254d5ede9272cdc01515ea3ebb7783e3ad13cbd4697cd01c6b8453e42c821f1f3f2d137d3bea0c0648cd686cb946f293069bac368d24c9c2931c2d6a32ddb82ae193e8bbe0bb361e69fad50c09ccab6619fe1acf9ea1fc356c64e9c273b50a0997820c5694383d60f9222377a32b95da09d95c4ce5976364e401fd7cbf39583d8d6a8f37c9c8ef6abb47ffeebe034ca287cd993577a52d91190044c0f931e488ebc433621d2fb99d04e55bc211ae41e5cca4d33fe80ebc64fff6503ee02b6a21b18f0f3439fd6e8fa8c4e329f5d74ed666bf99858c0d999dd48aabfa94a5a743ebca01f2047afd8bf575ff9f707aff7de2f557e1af5e47dc468edaf5c3c41ad0460315452dd6a4082f4ecdd9d0f73ad452a0fb8f08895e8082c114828138043bb538785998754d29c956b73fab6da6872fd67ddc7f157ceff009466f646b5b40fa8fbf9a60ab0e42ea918d5da9f77ebc5c38633e052c7024659e698f05cfe18376c06a1386a27422745345a8cfeb03247ac43af36e761b44136bfe17bc408e186c09dc0c54ae037d0996635a2532e9f9eb66eac85150330dc1e9f805333c946d4cb6800ebdc30540bc839059d28e40cd633e184474c5c13d805a93391c4971e4e19875548748d47a541264b65c1ba3c312349ed3725b6cd1440b4d6c9c8ade7f3ce01c2156d467691a41457b503ed2eff51e1276de5077f4acf11e5b2fb39820a1ff6e8069da65ddf82276d07784ae8386b468a1c4e04346aeb1f498444b48e64712baa16e6ec88c05f9ab6d3feca3f8b0f7341b2a1a3a65f85ef2680fb91de216a80a790c87e1a5a43bed7518410e2475619ce91a026a7a932f67b6dc82001fef64279cddf48e8830d449e626bc06de8abf6923d07ba1d71916873f260a6995aea0ff7413a136f3b105d1ab31455ea8f400275b514f7f82961dc56227fd8af4f967d7783c81122abb794a7767dea2858d25ee55f6ea4b91f124cfe5ecce270dfa0bdcc447121ebb4b8768683d153f569e1e81f773aaa3b24ed55f9fc124e3f6143c926fedb05eeb144f17a4465bdb8b9deed684b08e3c9f5a7572e5abc4fe98f30fe9e5c477872ca274eb4338a5178b791e8b61f80a921021ad1af1c2300c3aad98d10c5ce18cc0431e2129a66ddb8d6badb5d8dc053a40367c83da37e219a584dde9ae40e20fd687495dec48d82079fabddceafcfe130a7bfffb2b83b70db3da1ddd568b1e304e2e6a7f6185b5e7183783f5ef35d32fa04d0f40764f34082e2a1906a43fbee9e8c01c91bfa1d8884113eac463c1570a7454ffde1b8c26b92c4b125efa8eee32bb65fddfe8be7a4cd9cb8a4da1a287afbeed2034c9971cea43748db73d2bf41e85285f71cf79072dffa5e2a2301c09c0b987e37560c691115a947b1549a22eb27c41211567447a6ab62fbac4f74a747e9be8a924e628724dac1eaffe2f33634424f8866f428281b9d338fa15449d6b56da2b41f241ed8d186b55cfbe949a866fb9049ad244f6bc82e4822bc701d6292f4c4205e52779f1fd3ea8575f72f7857e63a1f9c1f62b2272b035cb136e6fbbfa8254e491cddd3327273b93d2ba94bdd8ca3617d546e4afff8156b7e84608c48a5b6940774768fd1c370164512d20cf00a810de139bf0251848d5418278ba5763e0100dba8a06f996e3f723f7c016180aa5e61376957b0fdd9315e92cd504e3bddc51911e9831a1a817e736e5ec87c1bf2b0afe8dfbaa4897f6160877cac631af59ea7b5e54b47607d11f5ae2a05d48e33edec68d76e2a572cecbe7a233379de56d6a1710bacbe6da4060e09d0a0b05050754588ba94fe69164f9163c2157df3f48604f71e4808be9eb6f74752d982def3061ec139b89fb16d7940a42a6f4199c14d96d362060b561c54281de8c7f8e5daa5297afa2ffd1c1b02c50d6b59588fb987831182cc7e26293397c77bb83bd930f32fc6d8bcea98d00e0255c1b09440404429dc165c844fd71ec460386996fe7f96654f3589b5b4389898ba79de0f452c4729fdf4cf246de6e405bc642fb4e05cfd34cd2feed393832a10bfaf618e2c1d5cb5d561cf265043c6724acf5676f160590fe4968c2b612d3dd7dfeb56d00babfea4f7ac5a7fc8b0a0c8c9e0f1db6cb1c1ced93afa1fa9d8a18043e38849ded45492112c530183f7822bd33b720d5de5042ef1ff2b22663dfe70e0188d132da84533dee0e2c7ead8fc60d921e8f30e40f82fff6b5a06728de8a09dfa3fb8441e0ffc8e5cae7877889fc69a09f716d62d42555cc0d6f5d9d1a5b656ed1821cf676c82da4c020bbc1d9768ba5dfe55b273f9da6ac394cb8cc3ebc84226e64fe1cfd8c10142ee80a41ac3f5465067e324b107d81c7a5152d79b1f4fddb09efb068ebe6046a2b303c7dd0e7924c8d2230d0d774a38e06dc650d0ca6a8721df40b1cee77e1564d750e6bdaec8f4aabf3ef00ecc8a457214cea33c4a1b7cee0812ce3b2a842b030b7ef83b562e19bdb226efc37bd126f9800b42340dd7be09f50b2061f68c271a304e6d1ff9d6b718f07e6a624a18d2053258a93a045a4d215a0db03c199fdaba9d7f4155fb47eb9f36a3bdec28ecb270e758cf5ace1b6c51dc7ae7886bcced1d30f0179a27734a93346ff325512211ff4177229b8acbbaf8380a6fe4faccd3c611bbc8c5e52edd3c092de978299f63b9b8ad3e4d9cce27c5ca1fa1391a200ee8f4b577bdf16312bd89f7ae915be6480ef4d9d56d07c8688e7f217676a93b6306744fb52164e8466c5b361622384e0eb5ff0ce7dcb89f1350b319f8836e3ee608d3f6a896efaa4491f2ed0c3659f14fb620a0ef2530e2e1c439000876d647106e8b441aa7728e6cdb2388172d4c1082b92f6b39695f904f53feb9df6e4f19e94c8edcce964a6e0f029ac6436d2aeff96d64d3c3ecfe673f378b1b154af04fa39832361c78740b04ae9ed945ed637a0f382763fe0e0d84007ace72fda58ccd29c2cc3fdea9fd46c06f0ac6e0f15134a3b042cc1474bc83262514b4111d837077bffb61ed4730fd933a6f670d211071998e3af12c57a177ca32f7d78d871aa786c1d9746a6e6f1980ffd62286c3bd07168a5fd1f76bd72e3bda71eec0f0c748b85fd6aa1be3713a0c40a4a867c60e8fff3f9d0e10bcd1951eb959e5ff9d9368cff13ef55d7babd7c39637b214e697f19fc2d58627852ca4d6a5caf7e45e0936749b57288f5a621a08cf83aca0c031212b3b0ddbee364090435dd97dad7ea587780566397491a1498915c5941dc0290d1b444ecbb02c80caf35e2b07713d3f5bedfcaf8f44ef24a086781aec81919b8d66bdb61e541ee9a0b81d608ec00fd0114be82c295c6d5df4402bd5d922e3179daf0f015f91a558056a888d255353ad2596c1c3d7a68a8ee9f49579f66159b700446832fb76c1c2a3b505c9002257697c479ce2cb85e1aa66008a67a49f9074ed496cc632d9f6ddde9bdedf45d4e9f5dadbc4a58eeaf492e22efccdd3fbdaddd4abfb8bca7b989bc3377fde0b27629f94eee397f06933d7fbc5a774d697228735878e2d7c42cc8f2f4a50b3793f364f25bcc4be666aea80e334ca8082cebb3e314f3b49cda85932478040211509191b28651b936ddfa607c33291ad09bbe95ffc42c3b15d6c652924d20e88969883c9978897dc9d890d5e03d37841b3f4a6efb3bf059dba911cb3e15fef73b34be985779ccb3d597f2eecc99bfa1b9c9efdd3f193a0557cf850681e73b05a8a8c8b8848661764eb5e1e2787c113c4d851c9be187e6365643508281260612d250000eafad78264d628e1ae0ccdafd8bea7a35da3caa9dacdebbfb3de3337d9494a4caba9d7eeeff59d4496585299027a88d6560ec24d659608b85a594f0656e2aa5ac308aeb7b426931f1cee6f00ecf0d1576b5eb83d500589a6720027909c0bf0094c30f2fef37e4f373c742f219e4659180305d2633ac67612b55846f155d98ccaa0aa89f08991d5f025d240f63989a8cf3d1fe6cc4d5b26d2dc9faebc1bafec14bf35e283e35f078968d98c5e69dba30522d4db602a898438146290995dd5b6b27ba179473b9e9d93025e425777919d9347a3a668522ec60565ff58d190fe67a46f17d9f6a5d07a1c566a8d13e07bdbd39fda63ea40d203b0480c943de305dc78246858c2873ca0fac5b8879bebcc2a3f389ac8a8767f9c8edff7385eeb664af256486a3cc96fb82c213ca75662e94defcaf7891ec3594187001677436bb36841950f3088c0c76b5581f753003dbd2d4442acdf217c7959a50dcd02488e2fa100a13e60b21f231c83ec1d204ff559405c7594d0061e5f8e3fc29ea8fa1a60cad0bfa7269226b91316cfca8e1f060159ceebbcaccd1181502fb504888f720ff8f2572cdda0fed33f5114ded705e2c81d00f59a9a7dd16385860220ea95870cf29f336641dffac553eeddd6ba6b69d20b97f1347692926cb165eaa592ba3aef6e92aa4296736af65a7418696265ab008e6abbfe0fbd8479735418191f05745dc4bfcae61ee75f2b01df091871dbf0f447180f768c22bafd8c460064de319627d8e13ced97e20f56753d2de2a4b354cd6673d9b645a04207cfd9f7efe7cd91fc0b1b48062904cc40ebd33d0de2d0ad2f4cd40c38cb14d765752dd9d8c76a768d59b40063a757d70a9eaf1f9657df2c7b3b0037f7dab525e7ecc6d608351bdad158de0ca248449bc09bba7c463ffb42b887afc71dc893dda0d3939b01cfe17be1331f9505075c687bbc954189bc4c9125b132572cd57c0dbf736c586951a2106234cf6e4a8f8ed092cc296db6bae5c3aa7759a3b62875de8f330f49b4e5544bd852a0807183a0615542f34830b58744a6ae5b1bb380bb925c7676346effd536571610008118955284bcb7ff38c45a1b95e4b5595e7ea15c7a728945f1ff2db8ad7f73d790d78a70a3b862a45fc4d3f8a051a9efac14023a257ddc0ea789a349f4c3b2c6e1dfb7ad2397029ea4fe28e6c76801086fbbef32792bcec723f92941fb12ab14f01efbde56ce42580cb7caf94c6f65e9625883ae30fd6e2200ddc008c2ecb61d0a95eb44b050f1ca95b4190495b8fc218d54400c869013ce905a1f2d759e3c84b192020d895f3005276d89499bf9643eb6a0fb03fd36b622ca6d098d3ab8bb81b217c499b2a315583618283df4474c2c81a82981dda9bb6f5e6e562d78829d90e9d69ec9f1b1a8aeb4f7f027a9617309850f42392a0f9e78469aa21ce173568bd1b63fbee8f3e2d4ea38ad507a3c633bf6fc9e40bb0df9797bc25b03f703041c8cb187301e7a4606597e53a0a701424bf9304bc6b53beea2a46d166ac6042f968704edb4a9a4016081fa03b5aee872aa0b8ba25fd1f8da4356d4bb3f68a1fed16cb335f8492033862a391913ad51a8dbf05accd33fdd2e52eb8a83b090eeb456d8c1f2787d35b4544e0b066fb9ca7ff8c73649f424c2a56aebc941dbb7dce98231b8c4637e2beaa7537ae6a7331c0a04fbe83371b8bb2a99616520233abd97f12adaab5a92a05a09f9eebeb094ee5c7915049546dec62c84041204ac9a148a911ed532c53369a7b4762d9708dbc3b0e14aa5f0fdeeaa095a9d16faed2e584670aefe05b5efa482d0ba1cd1b66062f7c04dd580dcdb0fdeeb958bd90cf7ff879d3b10b66de162cccedb591573c1c532c1e95a6c4b93965826b8989a4a17caf7cb7b68203b21add69fdd0578cf7f1aa5a3ea4a7049fd541a33418255d22f1d57911b4c710c4c29b7c5dc3b95a73bf0223c58355d42b782b0950c5ecc2d5b25f2119f834c196a74c023de3f512f5abe715bd622d5777a887b954cd43127de2caf428289b3ffb453f5cf57fadfeae263357f3b5b1c7986ec1364c1d6b457c76d0bab181d39465c70a0c15fdde4a3d64ca0bd1a426610d4f74b34883c8875dafd7d56d4b5d66be0a933c323e15ed9589fdc335653e59459350a152f32864573c1ab04ff011c7c5877e35ad9baf4df438d14f92be1c178fc0c107ac29870a15717c78eac9a7dec62ba7947f059b518fa0343ad29715ef5db95961765b5972e05ed6a9ea75e49f8d5eca17bb61a216d5da82294fc0d5f66bb6efa10caf387d894be538b42d9c06581943a9983d8803f50e71020a25c80d478b97de13f634e418f389c319d75674f5e5d3eb0021e8884ba950594a2eb9b51d690ce867a05b3c6c6055fe39ccf3481a2f311122f946c598fae0f71c534e07aa148408c4bd9df3b4444de7dfe8910d370c137401ee4a7a2920d1f67229f1ba8c872108a0cf520d314558945487a632164812043008c8d4bcc2e42872965c5f1d1e986d45278bee430e8986bfd61594c84e99fb6836bb58fb037ebc18ddea90c4fcea5aea5a7bfc3aceb02aa95ebb9a15649b9e87c418ad64634b59b965d85a32b0430babfe5dc603a0601c97af56772549707a909ff58549e742f75590f55c35d622d5fb1bfb1aa303a8aa48a362e3eda8e16b9ede20beb01783a63733406766d0a2cccf8e2aff8562d2002b3ed5b6c469cddb55fd000a48a79662519e96c08e11b0be44d79c65bc86c143b57eb8a7c5075b4a416778c4100355c959c81255a38c0e74190b6a42bf238058cd9a6c317c6ae0be172fc02c08073ce4997acfc8b023a6ab95633ee45168f768257a39585066911ea59a017e323c2a52979dec2b960eeb4bbfcfb97eb531244693799fd63d2216739810099de83f952eaf56844229e58bc7901ed6dc0fc6fc645aecdbce2cd69ad62a4dd62539cc5e981d18d9f54f04c370690e340050cb3782a801aa46d6ded4603215c616c6375cf86106d0f03964428393ddbb949ac08a1f3bee0938490bff07bd2fb4876d7ec0a84c9a22d3fd0f3f196d2d4b1f9324fc4bf0b45285f6f3525e583893768021c15bbd4f170e6e92eed52ee1a1c0690d92dfa6aaaf79ce29ae2ac35c4cd22bd406679f92f52da22766055d416d9ab93050dddbfac1dbf8cc494f39510bb8664bbfab02e17b467c27973fc12bd6789c6d40e5785bcfe081eafd573fe10f425c1af984ac12c23c83f3b6aad93e52fb58086eac902572d8d63408fce47bc06412b0acdec165dab2222b9488c5276282a6599dcb0fd402e2a8a3314ada0d4573ec0ca98d4c4a70023b8bf9b209537e2d4afc6d7f48a19efcf7cb69cc7656cb60bcb66a4c876500112d5bea0f2b5fd17972d9119317c28ae82222be376899604071efd5b55cdfb19cf57f6c76d3b75c95bdfdc465573d946300b1f69e0a2a714dd713a0966fe3ca38a66b4768176e126445165c4d9285cc6a742b52ad10f5b6a65b6a618aaaec7cabd4596424c001e8570f0208e40800bfb5fe111493551bbbeb922466f68864ac556b696ce82840ca8121a1f2e557bb1b87d51a99ab79bb9364c9427da2dc8462d42a9c622cfa6b6af18ba218cd041a05fa980ab10ced2a316f7082a0d3703e80e968ad6a95e88c9de0a260139b7117c4110aa15848ac379f818f37735307e3d8b78205cc09e0061c8d4390c1e0fd0292ecd120ea907be83502e9697f0fc06a409c1d584239a04b35cdb764e54ff0750569161405ab009865f9d5c5a8f8425593de84c0249259703aacf5d5b861c7a32511bc915447eab1c1538ece539bdbc749969543ecbb6f169dd7a9f4bc9d0a6423036a135a6b5a3054b24a0795b6ac745ada4e0696bee6fd9a7763755bc5fd0027d25dc080f49f08a1c7a29e94bfa4367570e91015fb727b00084bde0d88f1346dd3a677141bec5b9df89b6978f97d9fe6411311bf0fd9c8de7b6f29a59432a5148c06b40696063b58ce2e2e75c30a3b54c43da155920efea188e7f4c321cfb1b7994ad26d7f499fa55851c1854fdfbbb887025349ba10c8b5b8e74fee3511f663ee67bb1fe7079be2c166190b37e39cf954e6caeff1b969edecf8ec18c3d2a712b22073fd21c322ea580cfabd1e02837bede45ee7d1dda3cbdc983577ede45e3fed2c493825d1a4c4122592300c9028595097a910ea72ad125694a83274bf061a1262d516f6834e01208175e1057ba11965f04dff57952c2b21e1743fc8c549cbede78b4490e77411199230ba1fe412855a2989a258240631d36eaad1ae87b70308963e7d661bb689373db0b0fb58be8f4327cff1865a3c47a65ac0180c90285ad8ec533ed8187660fd6307a107dca9fbb0afee1403d18da80bb9b04dbf8ac94224a8a3b94b970064699d23c1953bf60c61278463c19d9e84b8c7ef5ce50903248a52cbcafd1aa81ba8853c87955a551a09e49241ee8b81e842a7eb34720cea6be132dbb804fc47861bb5b0e04e97dd835c66e0557f0da92339dcee679882706b2020d8c5bd964195451c92b9c21c63f4628c31c618bd8b49ab14a318e3ac325e935609af4a2794464edc21b3c3d7d1b974b09ace07d6ae4535e03cfd4a875c542fb6a581161abce0caff915ccce08c005cf9582a255ff603d1051031c6f84204fc686a8c30ba524a2392ae9c010bae9c410eae4ca55c061f68f0e10ad214579a98c82b6e2044ddb99f86e4c314482929a39452084d37b06125850cb8c0e0c6972929a39452ca2dccb8b248cc21832231b86205b6634746d9c1084836216ed02b4a0c88a2c860f6105a8a82c46614e5891a80a274a1f5a821297504516a86e6b28230686c59c1183d74a95901d97e1f3f5470cff9e9bee028fc8a751cd02b7fdfc27b5580eb41d828a18fd80de95e70f7cb85e05a09416c20003610f22a56ac5c38bbcf87bc13c282530eeb5c9d1749c27361c7befa1c4910d673b8f0a58f287f3a5cfd784fe924f78a5a4b8a8a5a469eb3815ad4b9d0976d6091917b4b260a9c10a38b0bbd95d453dcf382b05fbd492ea060effce84255983aa9a7b850edafdeafdea6ec0766a7ed943a6ddf81f088a594d249299d74d25aa78cf14865f8353edbe7f4d93e6b9d4376c250f93054ca48ab651bf9f203979c72c6c8e48a570d0d3d5dc745c4ea7f1886613d17fb88e1440cd6b8e717c33862d8cb8eb14e4e1abbda718c5132e15164ccecad9921dbdc49b870157f18a14452c58925cb9879a68cccd0995bf64bb5b28bde3133d3e8439285efef459c918a8a85954208a323391457ca20842e650fb9c336fe3b52a9393bc8524a873588dd33b38ecb2fa5f4991f587feeaf9ed3eeb1920f4d29699c5838a564cc39cc36de53be67e54359e305dc73f715d8867fe60731887bfc38386c239f5049b1f03d03d9ac5fe3d39f4fdfc79b63b6a9b5a652f3651763a4b0729f7ce6f8317e8d2c703742140c014b5f1f2a02361cf20bc0d68f2a300b970e723804893ce7c3814860123f621d9c77212f62af8175b07725435007eb7c077c755b2e7c2884a20b6110131f419a3c4b2a0cfbc122b048ec985017621ebf1a3c8a4ccc3963a4efe329789ade0e538f8f87b3c30790159498b030794e9393152c2b50b91f77d1c55c41b15f2f2d55994f70cb0c06e038699c334e1a29e723d906ca3a645e2098518aa0d67a021ae68173ce197f849608cc03037c03ff026cb36242290df3c01883c070e434c173ea5fd9d61ba7f5d599c09ecf94daf5b0d72ddaedf4cc6e077b1dbdde81632d865197376889fa60f0712c8e7098273ad521b1d65865acdc446710ce912b304ff6fc04fb20221e6b7b22cfa2a1cf603da9414229d6f6443c16ea9995722e8ce961e61cbaa36f6068c08b71ded36cd3c3e4e569700078f9180e7b1427e4b150bf714144522cd40b79ac97dfe9a93e7047f358a16b58112c80495e618fe234adfb3a806197086e7d883dbcd7fb160178b39d6ec7bddaf5086101eabce02b340f0ef00d2c12d4a503ecc5850f37c036f0677a60bf1df98920eef4ec6c0fbf67c3619e88397624e39431ca38e50f56629973ce89434b7ef38dd401a994b1367bf2258434d2eb7dfc6af664c3115c8f73ca0ec3a8192ce39431ca3865431c11986c0b899085f55430a185988779071c1c085a69414fa432521aa98c383b3d3e0f75b0f7987d76787f027a4ca830013c27540534a046fa7427013dae3fdcf187298e95e906ae97ba7df5780edf585bd026784ef7105111242fb8a77d61bf06c2010aaa31a108568883e379a91ddae1a08840568c5a34f55052d212935295a13ec2396d442369243d84544292fdbad59ad2439106086b7bfd2d08b10159ccf0f234647bc045c22046cb4530b2eda6938cd0ca0f547a208478830e438cb10409a9046260f1148327a41a0c8a1f40b1a4b140f536fe5197a4485a90ba349207e5f8af9d46f8afb3a8feeb27a52fc0b8fc8d8579707c512f795133799108fc5f27b5129425a03071f9bbc53c33cf42355cf61c2ebf0b318f8c10274f5098839a07fe4ec23c359e997a28863b88b39871f987308ff69ec5325b69ca02085f91f41da0a700971f08f36c9ffdb763e74a1c4b636552fc1af3441c9cc4c14530a4c0c1c19bd4a505861439b8113815d7485a94bef0a0a42e170c1c3938d5ab3ec78f30824aa57a1a81eb8b83eb9b230b16b6e9e7e40c1739783b8a081c8d8d2e5a82d24b1c31b55133e13f230267c3c6ab9ee6336dfba1b161a3fbce707d5549ad994c86ebdb4250a786dbed9ec315629be66484b7895ce7fa6fc07042fc3ba8ff88db50b8b412ff1a9c5f1898b7f1376efcdc5430ba5cdf1a5c5f1bdc924e5283e32bc3c9a871f03699c1831814178485329ac8a9879accc8e217158342757d1b68082723072f6361050b10bee2f66bc9e23657f17bfd4c766d3f2f136505c8d538191de7000bd8217bb8d55380dbcf4bd70f70fb3f97dff7dac1c92227bd26f532a9add171fbe5f6c7cad19f9194529a9a288d6dfaef0b0e3a47af8ee8186d751b61750a67563dffac53147e170e5cdd14cd4553b31cf16736a195b1598e2abda662c7b6da1659c69325849d4786eeeeee32d66861bbe7b0fb0dcc31c61861d33899e3cc113260668e51c2cd889923a4cb186334e2aa4ca29551327394daa4f5c2a494936accccb55da6b294325e1aac106e48f51a820f9a7437e96e624493ee26dd4d8630a24977131f0c71ed3069dc12a511ad57b7d185751b61599c41ac4699d6bda46d51051fdb16512fb0d229a310b2d21967003123d44bb7d18bdd920961b52d052832ae91d70b42f889561636e0442bd5c00a3c898888882e1084e9c224901f4b581655f07155c6c9ee10b8f28b793492bef1e770e0ca1fe3987817d7454b3a0722273b202122f269313f375127c9aeab28652b4c85f90a8fae6bca0d47a69441d4dddd8493bea1bb858a0cd5000c2278741ba98f6835a142c59126508e1c49eaa2e5494acee40414f7f3a61b589f63f12cfee45cbadc7e08d450e809a66e4124b73f98e4360e34ba7d3fe8e4f6d378994be3d90697c6d3a0f1d689332e8d8fd97e68a4b80574631e66fb898119e3c2bcdd7e60acfd97edc7be2435715f1eb5fdbca0be6edb0fca6e54bcb89bd6d9f319377b6cfbc9b0c7be59c7c615216808e3ba6adc785d3508ba570daa6822899c1c528a6e553571e4e5a8e9ce97dbcf642ca6fc70a5ec02e846c874746934ea0a2692a0d19d5e9c71e7cb9d73cec9040a78dcb8e2a20301cc20258a3b7f3eecf93be69c734e1c293c1499472aced61ac28621692890b98a322557ed118613e65cc550ea214695cb2e5104a683d6124a684b4081ea914568092d7600b44418da0f0e8096d8a2ede048ca0c343a70fa1817e090c06bd8a0e486272f58c11035bc509204174fdc388112a61e9438f9a0840c121495008c228a904d9e03d3c43c3b57bec7033b73ea129626f7a41396eff76cb05f7b50c7b693e77057e19aa9889defb55090213ea00e74ba5246cfebe6c7ec27eb98083b2f7fdf6ed2b60e06116c700192222096d6f5635cca3d297fc716cb2c663df196945fc47e7f651f9162c41745402cf8251061e7f5bd954004fd19ae7735fa37dfdc9816755a021a2068b0d060a1c142838506081a2002e0cd961180cd006c6ebea0f9e23abaf1a51f350fd9c5221f827960175be07ef96354576c0a8a85ffcdd65c629bf8f67a178a57378d6edcb858ff967b514a396badb5ca39c5bdf87326a576b0df8c3f5b916f5471fcb874e36cd5eb88ee9045666666e618619451461923c72e424f0ceb4576ba1deef58685e5ff70ba17260ba564fc2a2dac8abb533ed81ab2a4fa8b2e5a056672b0fc195786fdbc057520f310d9f8b18b215e31c8bfeac74e0524ce8fb0db8248fab053018157e7e39e4f951cb322c72ce84bdee40e8d5c0daf2798077643dceedc919a07eca2517711066ce3efb0998705ba9cc5d2f599b4b4742dbd6c37a5c47e33e9aaf53a4aba5a6c23019f593c275a714f0bd6b996e0ca5bcde34aea9b55fc0fe7098c8b496ce37f3d712d419de88433c13a9108be929a473cea1b7fc7b9c1f5d5fda2d1b5944ad1b81d8d86b0f0bfeb287561b15f2aca993497a692878455f97c479a40404242435fea1a7da9ebd168769308aedc063ba39193e5723dd526b4c0a2db3bb0830ebd9919d248238d94be8fd3aec7bdf669829922f74321ae0c1fd75ff5abf603ead44e05a47e565f06d6f632b0faa1002c5cf58c0e7605f702fd343ef40e401d7dc30f2134424a18e39c11c2cd0bcd3d5869dce3bfee0b72be0a3e7757556b08e7c78fdef8f369a4f4c29f55c66cfbc9324ce30dc2aec73d7e290429b6d5dae3393568c8d40827e5ab5e9f37e2e3238626664ba5ec0bcc0d1b37522ad4163f95b20ee535eb7602cdb2b4eeab5947bb18182b63376bb56c4b518a638606b5d108af5951db0948a8c1f6ad9c099c11ebdf7cfaf467c21b6e3ef93306e8b703f25511d2fcc0c278038cde99bfbc4046196bad15d3a217e49251ab1a6734a95476cd28378a097976cdcebeb3cfae7b6919cd361be79c51522cd384483062fb334cb2775df3d9bbbeaf8975cc36578cb20552c66e9fd88226db10d07b52a99a1d1fd9c33ebb2676711c7db847934a5d3deff9681ef02f88b363a7c7c7840ba32bfc9532d6464c7bd5151b3fd36874340ff82c6ba6fde6e3478e1a3a128ad8fe2c93ec61cfbda110bb0b7b9fb9dd78d426943d9f1fc9503e5058df52883e4ce01ecf99b04973549394c5e92108a9500205dc34ab7082561cdd8f9f8c54b1e5522c325528a1e2099dc89ec3b56a74fce0c2b7704905172e597121154a94a6488223c5b034512cd93627845ea210e2456b620815458b46e604574ca3b0027514451799511459aa5147a1a536d72696e08a6b145d68f87082498a14d4f041858b144b62928ea48802e3e3092729a8c0f8a80193144c2f3ea02892020ceb2389c986d0961dc8a8e182244462ccb0f5b252121c9892f4001f72d6d27cf71119d77ca9a25b9f256fdd83af658fdbcfcb67bc3446521640542ca8403965d3681659ed39c676288d698b72298379b047daa50251336e7d95106c8dd0a136a5c6cf66d5e05440e6d7f81a1d0cbc84136b762af8365e22c1557d1958945301a9a1a26fa393477055bf4607431bb9c117519e644d78c07a023518d8091964518505c308628cb09ec0fc082e2725603db96c9060bddcc73e7a6aa8d6cf7a60b1e85028a39aea8aa5dafd5e75c56e936356dc7e7ea868c894115b81601d6a74a3c53c3a6efd5ae439dad7af4b6aad48b756216e954cd408ead09677469348728175166553e8d6ff3ca64cd6a55bffa353dceac4ad343a590457f52b16f6934545d207206cf759216ecd3a236e5db24a161a41212d1546fa3409ae680baeeac325b8c43c978663c8d2f80fb6986462bacf56d595ec8bef318fe950791785ac6b019e0151546c7fec926efdcf9b726bcbbdfa00a0c266db09a823b40e89cb6e16b577e2d6ff5697e9d2ad74095ed5ffb86b83def9b88dc2d20e86271d0c235c61440c202016edfa3fda623274f8820678c6192760b737762fd62eeed5974cee55d9d4d5cf7080531ff5319c0b7d85fc803a7009aeea5754f7d50e8663b804759a57f22fa65b65ad7c9f79b61a2c3aa4155f552e78482df8a6fec74179bf8ff77bbe00a0c2f6a52dda621bc90457f553296b5f70afc27443dcabff827bd508fbf1537d2155c6edc776cc36b2c5abfa290d95c4b2521424b8f52593b422b1340ffffa2f9cb4e25e7d54dd3ac9c436f55566d80f2edd5a9fb630dabaf5e1525d4a8171702fbf2dc054d1e639baf4d6f3e7c7973102800adbcf27d48e5e1cd60d81be3b80302f6f2a34f7d5c738f9337eb1639c10ce54cad6cadd43efc185d886bf6f0d2efc8264fbbda111f3673172e652ceae26ca08f99faa84f40832c8980922830c32c820030a2775a31c7ca15c8481b938ca197b2fbceaee980b058a42fd0ec8872f32ed51d2fa0054265325a068d7dab2e569cb962d5bb6f460f49caa34dfedeeab7f4d7aa950982f7fc2cf3cca0807c0016012d8bbe195ff5f1d38021de17f7e9425a0ba6b698c31709431c618638c31461218f81057f88c5db3d2ccbe68a80d468646cccfe0a8f1ed71564c43390fcc63e34dc9cc28902017f01cfb30cf0f83e76ccfa88f79a6f12cf3fcddea299e83e3f93bc973669ebf95fc46aa97601e8da56ffc6dfcd74ce8f4111f0d21b182cbdf46ae33c403f368277de3ef24c8756a918be4f287807974912eb282eb38f153200b25771d2515fac6df4be9f0ba9d30ef0c8e242c4937ba4eb2d17d4e6bf411d46927a73e3ac1efcc0c4f34b8ce3204755a8b93e6d1610415790fc918aeb3b496224fef1f61eccb0f16505bf77517a8558aa3c2ebc0b37ee2b47887e141b78b0ed8c6bb9dd8c65f6502db4eee79969685efe44397499001475b271cf7d86507730c14a4f4fa747499a1cec951964f5636b5c9495646b5c9455656b5c9415676699373568669936b56a53005ff00cc857f45da1549c918ea4cca51d66449566441562635c939ab59946b5ec59fd151a0238032406f2aa96e2bf409073e66682ae28a185e3c3591014896958498b2044add5abbb4e6344d732242511048d73d88a4eb6ec3511057e8d0843614e3d7f680694391f65973d9fb1681ece1c7ed04d87dfddafb40be71fbc93e721dd45d0b7531425d4c509cacc4fa5b21cb4a3ca8d2466c5111f3f434f3c0d760add76380504aac908c7d1102756280600cd09310286c0f797f736fddf7c2bcd85721ccd3832fecdbef25a1f154eafa6b37d8cf63803c4776355fc41428432c290289d4e4f6d35d4cd00f5d00a1a3bdac6ba1bf87dfee5044f38a153b1a07e77afca6d61c1397a5a7242748f4fc909b1f5b60c0196774b9197c8d6b01deac6b6104ac7be1078b1172cf638054f4fbd22e26c83d57edd03d3b48ecb7a34aa23b137c62806eb3146e24e4a435a4c434a5294ad1f58fb063803cc73f26c873e416d77f082d295cc073543e5428dac20c20459fc4f6fb78cc908a862c4a1983802c175e26a5f3c8f6ec25f5498f6681a06261031eae5003f5d3746b321fcd165a2e845fb9a072e1db1e2e54b2b2e5421d023cb17cfb3952b7c0f2737631c59d35b44d1137c62b33d05073e3915ab9a8324d58785989072bae52510e6abe3974bde592ac22992417d9c573b4ef9f409eb37dff0c9a25601efaad4566b1e23a0bb0e2f64b2a98474fdf10619d6a0487dbb387dbdd8f7cb8f590709b0065f9f0a0e3b737c4a20f13dc53c1577eb1ec5861af010b809dcf64a8633938b59e40e02225fd4a5bf3069be538250b2a080090223e89314218a1c1e005f1486a713f5e62923089bc6493d216407105f974afcb4a5a80711d91f552ad955bdb346d7bda59faf3b1afd8d72e5e98c7f004c60ec8f559e7b0a670ba0e7e0cf569fdf940eacf0ec8f5b4b370c5f163988fbdfc873a31d0cf5412988f3d90f958e701a19f750f57d9c5a9fa1faebc3b1726c0ac148401eb18ae64607d8f754ffa9935ffb33b7a609985b1266fdd35db54dee413a9ee2928c582c6cab67bda226ae145151096000921e44043910c864881640a424241659452ba515a939e98544a332daaa8e20b4a25d502884ae6b1db996de0acf9940e6fd6ce10a2bc6b615cb6e5a995b106ffbaaeebaab5c2bfb816209313a624383eacc484e43a4fe9f9895c92f5e7ac58ec790bc25d6131ec7a11c3da1edb097d02fc7a75f063e1c2a732d73baf7b15948f5b9388ae4d5b529710c218a54be85d8c526a1c690c62437798926908a1162b841036cde060fbe73f84104aae910fa53b7c7b196ab142082f29aa1f0f57fcd7eddb1edd3dba7b8cd148538411465abd6c679380b3b20e87088e093e538589651b8cb4fe080244cad28f2040a42c19fda09ea66d8e9259b21baabb2be438887bd89642066e8c3f8048f1c69e1839317262e4a4e69d3cd4e1791896b991132389035e829059cae78a71cddab8e615cd3e83dcd76b593fc6f9ecc0c1813d3b3b15d6895dd7a7f040f7ea68b69a873a3c0fc3328f38646f658c38c8a56b8aaa1359590405ed64a1c3fdb8c5c449f17760b154b12a150b338620458ad7a6e8be02881bab131ac07a7dad971541b0f40437a60f2a79442a56c10163657b71adb2835bebcbb8cba4ba4990aab5562e86bcd62b74b8b5d64a6997ad2035431fe1c186ab030f3e2ce121063fe0810918786d6a23d9f7fff00175504322e7f077bbcee314e99b2ccb28a793f3eddc0d09026854b023ce944cd21020aa51ee00502867004ca35c017ac80720fa48e7e0031099363926f6eb27cbe484048fe06a89e41ac990237cb3a482365235cadd08808800ab259ec557fe9f7729677325295a42391d17e3825e3e287b22cf7a4287b2ca8299c6c1a72cca49ce6e3335b69fa9820c5dca2794314a9871cc7ae19cd52c9a2a4056071089e0fd1e6a22a873759211d4615a5a4afab8c5fcf5d011fbfe52c55a16c06a860b8f8b62bf1aa3512e0030664cae0e003608cad5d020e4e5b32c6bbf2e395f38220f25c7e4a5bbae6943a31c099fd46d5943e17a89b7135fc19a238da88b8caef7587ce52b5f591c1ae546c84139115462d0cc689453516e0601341ae570684a502e95230ccaddd07ae834cad9782e4f246894ab7127c7c47ee69b2dc37e9572328f71414fe61379ce059ab5cc3886f5e282883c8bb9005fcde5873a06306947c38a23c01fc52df129bef28f61824b70e5444986409d6ed198c07eb5048d72303fb05fb577724cb26747e2498ab6c83119e2393de5e5625c852bcaa1eee4985c8f713d045744ee258957d7453dd4443d012ed8e1793bbe2795b2b6b9b0cef9e81b48e3395e73bd4b33b97fe1c2c21ca711b2ee4e4696c1b93939843da7f49feeb15bc121849d4ad5faee7fa1b3bfdfcf85ebdd06d8861f6688ee6ed8e1e8801042088bd8d9d1e3a36fbc081a23369e02a8c44d1825b5646a48020004058315000018100e8604227138200d345d15fa14000d6c94406c6034960863418ca3288a6218630c00c61862883104208354d15100cf6d212c741c9762cd2af6710da9a047220ba34a2a266b870434a88864d82015e63d5ec866a7a81e0732b49520a06dd85b492f7dfc4fb81cada71f7910579e36ca0d019e26ae24cb596810517a1fcc1d32a2e72627a8f4274fe0a8604aee7b3e6da7a2104b78aa2079b4c9f15580e60f842085cb633d2d709ca0f017a8510b4ca65224f225d4d13f66b52a2b8df981fe78fc79ae399a8b2994e90345ed488f23c32f2980aaae9e73c554b74a4dbda8972df2d5a616c3c6cc0e9215081ee71a3d31728b3e365da296c39ffb25175a3d8cd54021a3f860cba248b30c95a9c569bd0004211643330639fb978de2847e41518d76c48624de52d7af9c64b9a21233f2a3ab15c6b87a8990086e4c525a7a3697640153766f1088416200401bb7bb1ed40c4f68e6e7360898a62571777013318dfd77fcb2db2856f2ee0db54c4fcdd5429acedc02096603c4ed45cfec9781077e8c5d1765495622c8b486f39e86c1f0a70fdc7d02d7d98314f1949c345f8eade16092b2d2e021d54ee44e9064e3df7120db8652f3a4d383a98fba6a3992d1729cd0beb8b2536774178f7eb8592a3564339105c1d400eae2e0652936ae717bd3f20ff6a3d7349c0955b40678e2c60e51343f5b7cfbc9a15d9405c805c91d5e1bdd94e546b5771b1e4715d3e3efacc6f5c8bcd070ae2e8a1666464a6db08d93a8d76b2abe5af07a744fe630058801d916d9237e3e4caa0bb0ec1c6cc671c27f7e67ece190a8f473c8213b507c52fdf84d27e95e961a0c47b3f3790b5a07519b1d25893cf322dc364ed60fe170fc70b0ecf4237a0ea2a7d4207d0dcec034f3ec8c6bc8eaf1444a6e4ea2daef13d4a4696048b12fde22a0c2ff1d6582eb294c888320841b59e21cc5c1c8af6e20ee2cea07ef1006e2171c2b00df10723a50c093da32de32c79f7cacfdc38b88ae90349540268994efce5e9acf7e0bfabfbbba652663dce0abed22b6226b168e284a68dc24a14962d41f9367e8563ee5154a9101abba1adfa32c19f4ab11d5f524fed4c11e9c6001153ed0c507d8c781f9616eb0e37d5eb9185589c17e64b3d3507289f8915060a2def8c51848f44ee421afbb49fc26c0ebeac682885a49da702fbd9597ed2b285d66c7e9e5cfeed3a97ff89921732aeca9a76ade3f85995b99cd30a456110154f9b137bf97053a0e40492140301a0138d2f396b2688d262591609aea69d489f794eb4fba46cb6df23eee4b2a0bd19a391cc1649de293329ea62ec6be0b5e79673727b7c6dccf3b70986fa36ecd11546d5dd6ee3555f6a80862c94155bda3a11e93e26c90eb1b21437588e7e1d9586948806ca9ac7965bf84576877bcb3758e28446813b0c442ee2d40be8012b978c2e8aeb05bb3438c01188d703831e6d160fcf9c954d48f0b5c4859b2a7643117003115cb3633dca25d556f7284d13247618d64994b321ca202b875426704d1c59ac573e6ef7b7f7860187cac070f457caa2f7debf79ed89fe5ab2ed1d2b4fa1c7d00a0429dfad5d459f607b3dc30964d91504cac406b86940bd2ae7215041dbade70e73225552836b298290a6074010ab4b68de6d7117c0923a0006405ed235b862064f4f5c91052ddcdac073e64768c2af66e41d882a04d98a15ade024fa77fa738c07ceb3eb63a958fb8822266756d5fdec53d59d3878b48895486926c9cf2e0f6e98f01f507ce994025221d61fc58a30bc45933e8268f3803658536fa649cc02975ead46412ba41824566f46b8bc9fc4fefb9d85b92812799ed68a37dd5f7a84b78fb4ba0f619084023bb93e17ab46ddc82b07373de6cdf69eb0661b2050e84d390f162c285b3cbfd87f19000748661bcfa12fb9c927f1118ec1e6b7be016e952b827cb563d6f9834a7e480b5e25928db1844b4f06fc60962ab56b1a9024c2943923f61d8d4a4da0d6b194c523d6f6d0e65c471dbba7578235d9bbc91861c76e5194fbd1c777e72909b633b76e133284e60c743df1dcac530f4b01dd9510cfa916b2b431bf32abe17eb420d09e6e40d3fda3faa7384e14299221bf07405bc385c9ee13b17ba673c4d07875fe0cc9246964edc0ff759240622ea97002d9e8230d42d280802161a9b64a4d3db0f925c7a4315a64cda588218484cbf9020933badc965545a4f38bf7d9b33c9db5dd0737530fdc722079b1a19ba51d815c965052c32a26ef606f327ba8a82d2a7b81b03deaf12a0f21f5937039a88f10a998af99eaae17d09bd483ffba9851eee0393ead4abddaf7ce3a4b42d6342fe4139633d07ec2dd6738881e29853904a4990b3b9d4cff659eba43f400fadabfa7085d8a7cb37edcad7bc4f15b34a2a1f4098a4fcc6d2d39838a5bc1b34c7e470d0a4b77629131770329859fef5ff461ccb0ea2523b851e3a69e5a824a629330595070dea89916f13505794619ab8d6f38f3e5655a8e0a09209ebb43f044209bc0ca30a983f9e185c23c852aa009ecf722b9fa7d6b544876504e2b36a17d369cafd91052df18dd6e7277ababe51c63941561bc7d826f33b8398422eeaebb93d95403181bf8a565bafc282c5f8c6e61c0674b5be4ce5711bbda28b6b6889b08e8d0db36abc5cbae371a6ffdee1abfc9ac61c35e9a73ccd54e61514baafb1a53e2586e2094d745672fe584c9ce040c6f081790b5b8a3284459e7a51b15ed971db254d56c71a262b69f0f3fcedbf93390546645ba76a4ea12757ff6ce43ceb313fb929d14807a83ff9e94b239dce37ff5398a17e5823ba0fb30f93b76c8aa103960750f9b8d7c0c22ec949f3542210b540e14af344dd25ae0e8e0385fda11fda5aa270c6a4dcbceb8fb99cec33a5ac765cee72462d7be468f3596ef22b2330c644242d410693d553c656325ec91b85c15e0bb875e457816e0300446b4cbcc55d00bbbd22ef6330350802ff090c130086c0e217f35706f2bae3ea816047d24ddb59e0f3c76237503afeb7fd599ad12668043de3d5b77692554fb1ab82374b913eeb1678691d7b2ab6b19209dfcbefec7c9e40644b8448f6219afe645377b10c6972f225e68c2f6e93e7b8aadbbe29f40eaef477fc7656caf9961cf0b2de61b24bbee42c9919c61433aa0a094fe7439a0546d68c45099d20842cd0d761a548bea3c545931b1060be5f7a5a13ae65f849036639a2c0478cb45ea4c04c0f80790c0a90be4a089110844a995bcd036abe1bea060ba339086da5e6e2067a62a8f8fccc81e6f6375cb0c69a838f532864ea2763dcd3a03651d7bf3ac84c55d60de16f0a6930aae7667285dfe4814b47e6c10a337deba6f99ff923f682d8265a324b841f7283631a376ed282df3c087bff6c4c7a84ff8bd5c7825fc85179b17f156af734ad67c97919417805cee242f205d0b270e2acd09929492e5359caeb1f5e8007cda7a82467e18fd719de6abf7661b92bf3239ea664d18d9e359b8be09b5b810f1ec53e49f645cfc1adc02450131fe257b792213902753a96a4661b34499cf032fbfa1d841e78b32c2f6ce9e5dabc189098e4499feeddd5d665a5f2c9c1a7a7500f6e546489a659e373e183bed1c9280c58195be8d5a677052b5f490fa9d4f18e510d7232be23995c71482e947e045a3ea3580659916c0aa7b2b1eb093903503fc3600f282684f7682c2cd80a91a971f51bc64bbdb3515ba870cc45794d24df967a80a1d9800b73b28b97cd62bcb94531f8cc2839e6e4d70082074c9ee9e044aa8f55523c95c8700a24542582f253e10638b1b95763d632307fcee006b377a0e0b2f3e4acdef43a8a97ff8907405de31b6f6e00a5d1cc14f6d37ed2048f22e76332395bf8554a1c84af09df5d4247b0f5af3a06fedca401134e86c6275f58c236aa28f49a9f7b329a6e7316746754421e54ac04e7631bef27a5bae0ba7c810b25e8b816c9bf0fd9dea3f0d6e20dc7719ccc35202a0a0a9fec8a541be38721b1e48543c2c5ea963ee48a377ed25ea5339d397814501e17339f3e7c09233426c7e8ab0c82d768e8c3d5b5cbd4d8b7a89ccdd39172df7aed44f2fbd9e7f99f549b25ffc17e905abf45301be893b7de0daa959536aad466b7abfb84a59e1589aef38593a9dbc2d5a6008fbc4f77566a439aba00960b7a45b2f29746a2d19a1e51042dedf488627cffe5eee11dd94b1cbca173f0ee70c72021ce4910fb754a1e220d58f696c406f18d7be1a28d9bbc4b8e81ba0a00930d2aef7d9043bb541fc3684a8edc3f5e909eb8045a70910cc9acf03139c6d46e7c54ddaf6700dbd06d5d1848d770e6c05e07ddcb7626bd89e46b2db180a37f8c3cf8b64120cd5088220b8ea147c73e1892f05ff622c86f05ba9a93fdf89902bda9b5c6ed485e3710fbc89293656c6ea2aadf22bf0b5dbdfdc8f05b65e2a1cf0c45b8b3a515c412b983a66a84b3ec7d6736fa676b22f66968be2273b9004b3134ae0ed2ac2a07229658dffff9115f6d27da1d8da6ab3197fd00a56c4ff4e0a98d492cebb7a68c90464ab51b73a9d168d999cb2106ae14abc9403348f699cb2554970a1eebbf5de525ca79fdcb0502504fd4e4cfb66916e95b73c140b8102a48abcb7b806fd8449bdbd911f9b4bd03bbca4797ae69b12a6dca17e8b50a386e4133fffe50979ea635eed5064d0e7bdd4c4899c25720d71be8536cdb128c9cf77b709c50510f6b9812c34254be0139bddf73af6bd7368722f845306b5937571925393f5b374fc39d23b8a7d2db1db2c29874cc1967c380741a0644b4d282f0ca19cc4ae0c9018367b2090b4f71f454f6dc1453dacceed45375d77f468c4acd72fc96831899356897838251464be7e5a1928f829e562c810e58321eda8d572cbf9b0c4f7478a370507293c6b828be83d9a74099d60d6ef5ff0cc6abc9c9e8d875c23da133fb06170f760df160be6f7fbe9de2ee4fb017b69b21ea1c2521ae88180ab6c036e21d4c86f04b9cf5db88062e674faa204132cbc60298650083a8308b5516975d0af48423ad9bc89e84528c6ccf6b131ea38d4a09f0b6177346e774258de6197be8c579c075e4e9b0c90cc68f4a263615b597e2a97d835dee306d725967886a0f760a8defa8580d9b509372b4b684bd66d7312e06748276e1c18ad3f19f1056323c743c2b3cd88edb92e541b4273cd805fe6cb03e6657d17bccc3223bcee7d929b8987873ac61051eac2ef5087bba5597612a0bb24b3bcd64e082bc2b785522434e5c90dccf227fdd883e05403c169024e0c9958dad6da792c88d30e7928dc61ca2e0a8e85ff8251f9c424b0026a984957510f35440d6f5580693df6a31501ea541e791496940dab62d7fecfc38f056d978a0b5f15cb4b36019622795996facb2d12b72e14324681a1c1718b5352d78187abbdd559d63a9ed7319e58004ff0d7927d1dc1e52a3012e2de768d9726a009eee2f1968fc611a4748935b5cd7848feaa1d2b6cdfe489a78a409f5e62db5856f1fc4dc14166179abefd2c3450927d5e18d380fd8a88d5d94041a5559a304736393b602ffac860d1d47cc96eff83e58c0800743d8b5f87274484e0849cef47b4092d46e8680e4a0123b80a5f7c19c15a673094c7f465c4ac0274a821b81094342b24ed3b44b4e2dd0d595c064b80c179a745edf1ece05e075599affb68af0fd883dfcb3c2d95252a06089eebf51f73b8ee99b485dea7e70b6dde3f47066131cf5d35da76c82b13ddd33938fc9ade782ccf0ee70cc4df54e3055dbf27049153bda9ac2daf912f2a2a208c779ee6783f35f3b3a051d39614ea7aa4f369572293677acfb12cec122df20d01821cd4e36f9d27bb8255811224afee4c4978f7e9c1e246fb26083c94985a3e000742b6d00e18319339d14b1e7ceb280c0ec0489edf2f9e58a6a1fbe644cfa208318ea6dacaac7cf6199416d1b5483a215b8d5e3b10de017e651ae779c30f095888d830c21c2a2320d8ac30444a8dcc8240b37fa05061ffd2935b43d5cee535b984d0466b9b629df22ac0fc9add865f74e6220d7f155be5e45cb1eda5fea6d523b14c5ce326049d38b1bfedeb104764f32bcbc320c67c030466a5f1ecd520133b1e7802ced36944d03b42ff18710f2ffcf50d0048314fe6473df804af84a510cbee83ed974a8668c9033a1bafb41c91db9060019be45b9c8c17bc42b04b49350369b6a1fa18f58ef2d9afdfbc4fe3d22795d90a53d70858012495ccffe27a809d90cb31882976251a1b5f831a65fcc89bd6f4aee938d0e7cf3fc6741438f7335bb2e343998e35f734eb0b0cbb2a9cf54965191e07083df7f8d2e6c42fec4429b6875b31ac0099b23978f249b979ed7327dc6cdf47258c55089ca8ee46e9d6167c5fc1aae281b4a06225fdeab50c1c216ec87033b3f6eb75abe540e32ab252ac1df4215c5a4752b58f1811818db17653da4f7c5d508b66bdd035b74706471303ab048b78437bcb91b8c2f8dceecb329c1f716ccea21539064c01f1a06d82b38b873b108fc031f1e2e76ecbc677ec617d270f1dfc8c6818745f7e77c7be229418151fb6aea6edc0025611968a44551cc114880c01f4c6fb9f342bf7879d03c8c8057ca661786b7288abf0ddc8eaacfb4810ff06cfc65ed847266ecb7942fb2fb2d56b638ea9087556b5df94426b1437eebaaea9948f616283429feb54f2137fd964e3f21a297a4b8327ac94c23d0420df3983ed523a42539baa50106146d86313876b6c92916b931bbbc6ed3e9f63d1a978304c776eb043049ba389bdd9f7551e3d8289e575d92a781b27ac3d2e52b557470629b11063fd1d172def6288d631933bc5eaaf9146470084ab1721fe14a75b6d0292412bb64204ded719f58e725449046a3cb2997bf4ce14ae4e20b8c52e50723c2aa5fe24e4b7e80be434136653d8e61333ab402893406292a64b1ac275641a4f97c920c3d071044e9dfefbf471bfec77d8e2b853817ddf5bb547755d450e881cf6a7c07aa60a26445fb072b4fee9b6f63328d1f59b5e0fe60c445b6133169b786d6e4b6fe545785d4b9108ed8b95a514c7338e41218efea00823d656c096b9003a40bfd746b588a31544063c0fa23df7d34b512f54c16c8cfbcd50f55060f404220439648cd2572e987c7980c200fc4f2a04a8766a605f635958d40cb331b15803acc0124d1c54a78d7f0e81489fb23454554a4f1dc81ed3e40097fc3138139392be645a7ff9dfe0a22fe30ab5f209a647464c53754f730200dfb304266416199428a346b7a248b26af5b27b0f82c23e1da3cdc93291b3f290010377038e078532fe6e8bf7067a14482bda3a519a726c5bb76771910fc5bc8bac4115525b42fc58001b393508977462ac7ed70fc0e912fe65d50a91bdf56de87e44be40f750903c25d0b756c10004b6a1f24d4eb32688e88c9546613e18cfd91c4b1c31efb47c93ac6eb6118f2d1f607c10dedbe8999a41b19341cfb2b7090d5bb02ebe4af23177483308a385cd9e12dbc63f12e56051c43a26936e01d6ec966470c06c839452485721c11287b94401ba3ad04d5ac128791143a7b145fc7ab9d28ff56b7816610364df2df509f1aa8bd3dcb0dcba5d1ef38983d88012ef8dcf5d560898e517a7c398966607874476ead4d0bcfd09b8b0ca4a121187aecc09f3138c520d57ebd66c1f595d99905624f4618b07aaee2256766946adade6989aedc0dceb4aea10ac93ccbfb89345db65f27f9495b18889040d653a0c1c0e0f4a65fc35539211c0f8fefd176fd03a829a07e455a713058b5c622d61229343265156a1ab1b8b088a310ef0a7be2a78a92bbe7f5f14d71698ecbc08b71f4ae1d3995ed95d17532b64074eb529e72094cb9039023219371c75035dc67eddcf0da246e41eeba8b21c26d6e560bb07e63073bc61f10544152d9ce28d4a20a9ed33ac952d68ffbdb610935ad065083cc5ea47dfab7c0d5114b1e4202d641e0d2fcd45bbe82abc02d7874b38172293e676ea2397eaebd64b310ca632fcfb8e2bf90cf19d2dd9e754396ccfb8cc690361b92fe37172ea23aaacb9737cdba4fb2b07880d0da410d342025a768df6053a2e5577c46c7a9177980e8028a682e30705c61572a91a1cebe09a1c8cc58a1118a0b9a88ed256a50b37e1d5f473424268d50ed1a587cb41240ffcd4fdaa7359b194b95271190863b96c10f7ffd7988d89c56ccf8ceec91f1afb51af4b4726d712b2605a545b109dd63dcd694e0e8355c3baf0c23c695a50cdca08e952bc22ed83db8cb57e541711ca3b5d9e8209ea08bb64b4c7ab378c53c5f1e4f571a9b0aa934f6fe49696c5b6b5d2130757bd5b611d960ada6e9132e8de03234dcbcb1a4039255cbe0a5f789b190bbe06d5c4a3246b6b23ebf40a2dfbbf396c12448dc882b31996abbe89fa2432ae604c0a4b6c2f4b4b22a9f5450acaa601a75d81227450b21a1573b6c01ca3bf0753f7c5708aafad5800a043245bfbcd565ec351d8cb028469a0235ef88eaf71a32c522ca9d532de7befa5422b3259be8bf657918042aa733e88b5298ab2001bd42926a26df3ba6e5f569d06a4bcca592340e6010d6f148383c0282c81c31f4ff281fdca00411863ea034226134ef5004bb978a5e4291305013b26e172cbfff24755397d88cff05021b5f82180da7214dbb4c523e444f22bf4558dc8cf3103fc4581d1688b94c877e9b10f0dc3e74211a1807a460f81fb8a477ea049c7d5959819c5ac5df48c730972929417104303ee5050b82adde3897a70bb4bb8119a00084288476227c746d73295047d561d8fc2d85a7791052b6e298670ea848bdb883e0e9e873b8b5fdaad4e030b35e0b47abb8f62634443dc6f67cad0fa33eea3bee20327a4a7b6b9470259b9808e4e0652e055951e06fd9ab662de9eb87555497d471638095c2721de0e603c6d5a8bc1aa8ac7ef778c6bb8a5628490869a0793a2589684a9e622e3d7d318ac77e5eb1780c57f264963cb99ea46b010b042ca16fa71c1b1b07f6566d1b78225b65472a49fa3a9a86bc44f42a78d897d377c2770c343e0b2b31bda94ab5961fbaa09e4544fdc7427f5a8d05efab2268071d6fb325d4f279cbc3bfe249be83b1a2a5852cc2a166c788d71bc57c94fa873634229a12f70a7ff52811cfe4090115d76bbc2068076074a459c675c1cccd4fb81f2f2005b9bd602bffb3c625493361b6c5a776bc0aed5bdc4828c45bf25d1c6f90261bf97b3466d2708258c7c1cff0d540ab4fdb64b67729132c2f0f12627519263ef2e02a02e70997364e3981c3ef461c9dec7d32921a04f4f32c789ce90ca62af7057cd3e37a3395e6e51ab0de94a0e567ce0bcd087a548d3943c5402d8c82e2841ab34be661066905a55129711cf3587ce0700d0d9448d3133ed5f9fb4039af6c7a20fedee9052ad081f676ccf2ce8b935101d32ac29293a46056d7c208427151a50791a4962590d90fd72482f83d99af01284d6bf708747307dd014727b8752fdd0036f57076b859774740723e496273f55d5a4716a2ff210e59d04c8c33aa68dd815abc3baa3255823b75f903e15c5da68110a76ecef9d027c7eae026efbdc5409ad3ea9ade720486ebddb639899b9d68eb76778372e5181660e908a22b1c9683ce27611fd8397165f2f1e3f8db1b9d6a203bd1b4cfe93cdc135a5ebeee48089f4ed0d2edc30d097b9c770b905954de742fcd7dfc7fa042f4404d6fdda0c6c13ff7aa47acdcac7b13a5b45e9e829a2506ffef0c3526295dd295c1f8d7db17bce1a450ec3116215e4b5b13b19cce8fd83382a82ca66f2cbcf89067a307b9e1520d3bfcf43f4d8fd62db5e567d57a2ea4f41330844536dd22371da9e7082e484a6de144da05d107e98d1fa14de75f4b8b192c4c1b12cd3902dd1cec97c30fb425dba506d7b0eca643d7b1995dfd7c58b5f0b68a10756e8d3056834722b607680c2d4a871a449701eef5db60366535fbaed88aba51a920ebccafff24fb4ddb03ecfad695b245f2eb61ac1a7b0f572f8301ece160f016e92928a6cdba1f200c9bcedcd7217f3157a39d1b9f81f7bc7f4d2e5593644d7c448b7d32ee71603f0f8cfec05c23d8a8f05b135d618fe6d388df83a6fbdd0d8e12f1a398c9c8d6e31e10a93dd7ee6b9e4bdf48ea16b9f43473ee9fc12148585ebbd641eedcc7940b59d7a57273c7615f5233ecf9bdde30c7e1fedc50467237971977b52d6d7eb47ceb62e033c3e018b91521f63a6232f07499ba4e24ec9dfa7cb3567b61b662d92c45774954916b84d794a60b8e3645c7e24b929541e88a0b7f5a1853755fcdbaf48b1dde695784974b6ed5217fb82cc605ee343e9b2b72ba84037ed25a48ff2b5a052a2500e83646766e49ddaca05f34ca15b3ddfc1d626e67cab0c7446069e6470ae4bd88958077c2ae27567eb89019ea0a0f243327ab3761ab2026d6c42d29d2d49802649738f11a558213db3038b459ee2e749e1f6b1d7ca80adb5b059e81e63dec17be2ada9f6d7ccfd8d1d4b3be7dfaced0e79f53fbe066c689efa178dd51757d4e3e4dcd30e8fde325e3fb01fa1b89d032df1384d11d5d456857a45b4337fc760d014dabcc4ee5cf8e82b36211f0f730d56fca141710bccebb8a2d41eb4fdebb67f231132ce2ea19027c5669582d406dc2ec65d6c8c02d939ef5f5466384ecc6b29c558297a16aa4f47446c96baf91da2e9f5f4d73bc9582de5aebde77e3494c4b814bf1e248b597e1937b1cdd48997392c73e994d46ef5e66ef415e04d2b69f352215d6894a516589675a6b1f12a6a159c233a5ae33d8b9421954ce3754e0d0d0660336f959ab75adc1cbfd2ad98f93fbdf05eaf2274cdf8dd79cf9885f783873ba845805ab4db2325d2e2e4259dc79b5a3629a318e9de32935b703edaf6e92f58ac429743d8616034e1e79cc438d4aa496e5b3dc584b12ad427c0ce692fb0f2bc03bfb2d08eb3739427c7ef3c5070d31b7b86927242a31930ab13a09a5bbd65a5bd7fac6af6a2f6d41ced85b1ea80c8d1cc0f86cebcceacddd4631d38847c4c0d2960a3ad2c607d8e95b9f578b7ebab70669e91f4d82ae4904444cae0114e9d822e84cff02dd1f7d2ba422a5c64867d089a93b14615bf4ed57f8080e46d7037b88dabc0be6bba631932bd36b4c30dfc220dae37c151d7a79624b095ea4be7d14d9e7e4481def907c2ecbdde4a4bcedd2d4e0bc4c88d167d515173a27b887d1b6752016731dad641b5adfaa0456ccdea9a62a516449d00edd6cc3bbd62ef8368b889a6508a01bfd033eb5d95a3e101cbf929fca475ff2979d939fa30780132e2043b0c0582a717062f86231d116a324f59f98c61219cfbbbbdf8d28071b1884f0f14cc92f63af2a4d8a8220774c83b503b6d9e379fb1950f76e97114b371a606d97cf2fec038b570785db494584431d85af6384be8ead4c55dbf4beb3106b64d5ea7d30e12f826ac87841f4dceffff414352f78bfc51c4c47ee36b56196ec9c47b213655628afeb8baf597b0da1ff9ed0dc3c914509ac458e93797672dc901a3901808310674ce12441d430c243b8af25c4bfdbed13385904fa0c362b7f4ce6777699cd867d20fe8ebfee60ffda60344958be6d5b4360f0a637e2c13ca5eb513417e3b35a729b10edc3c368879e86b5db5a7c72ca8e7f76321fe34d5c79709daf13659e518e315a4164ded3b1aa1874c4791e735e16a1af9fb755fb865c0fe5fbbb96343b8f3a4ac09b37e51098def7efd594a6f18ec81a58bfece9a1547bf199207fdec6cfc1255e82630f36b0df0573d7b874cbbc2951e79945426ed9d9c97dfcade279b765c4742855742ce9c29ed24161deeb95d8375531af325d2c5bbec7024875c04bdb280f56e4a5382e757ca72791c249c0a6231eea3bcc20de2a5d017e2411c7a9482eb24c8aa0c7cd526e91b3f8e9406b83c3c7d008158b6187f6ae3e93302ae485ddc0c4ec69ec4518e564b871470c76115858cd5c6dbd834baa54bcef0e7435ccc924a5d000a2163ba4c50f917bad39cd63a222f6791d1541708a92d682c9e49896ec20b8c408e179b4abcf57dbaa4c43aecd217685015b4248de217c735f548906959c7a07ac894480a1f15398f7bd527eb38a7996ebb1ccf23b16417a02fd347daaa333655f35247788b23229d1d6cee16a5eb1176bd871144326404c42193615dcf673c2588b3dc88ddeccc9f2f60fbb4b05b6b641aba330a23cceb15a9a0f4028b10d000552533736b80d8f94adc98e29546fda618fccce6ff34f1e550475ea367396a4112465e93d9e37469041ce179fcc9a4c438a646281a046664efde3b5ad7fb41ea45d47a0f695f86ba8bbe6b865777c0962bfeaaade1977460b7e69b05943ccdee0a92cbb5f4163f1df6ed690105a8baf48248c0a99503ee6fd9f06f0a8e14a1028f632443f3e871a2a68737a24f745cb42b97813a63d5e896d6315fb2ed76259e55b6c82f606b421937e1684db84fd8dab4deeaef7c6092c4fbad240dbb978460e23f3d014a73c79b8c31558e144d1eaceec96f861649ee3b511ef1c15a0631870d3077bb68f3f4540814ea3e10608f36058c3045f009f07198d5e61bc2e73de833fae0bc87113aefee46b1c1fc74494b9ca1bb285b859c8b3f8b69f27f4158445f354e33aaa794f918ec0542d0b7275afd38eb4b299abd9da95aa4e19ba5265f72160f7a57bc1b1534dac21c206555ab79d14ee5c3bce98e12a0938352b4468cb52d1ad5879c0c360238ad68e3ac4e4cb3ec996e1d1ee0bca6d703f61e49b86797da89d7bbec410f78bfb451ec4de2c1548c358764e0e8ea1d593577ec0213c6b97f247968f2c57218cc609ebab4416238848dfb666820ab980ae2cd7c1cadd07f05f1981c227897db51440f6099e1e8d2be958e1383a8dfbe69a7a0230f7a34fb5294ddcc6083e34e361582d55733dd50938906ae9dc91eeebdb6523e13c6f17c12c689d12bb5b69892ec10ef0044332f86e614e40e1e31d87896add1e4487228a601339131da32a092b036f0ca99ec18ed611d0f73b83479a1a3963a330ee29f15aaf78b42f97a39c0a2b1e17f35689be66bb7b404c59e6636eb764c6965d19dc924a3de913dcfb1a3f1b9f00ed2fdde5553613ef39889882d86eb361f76d5062906b667a002f9ca03c2682024a4b9685b6bbed4a2b2a9f570897a53b94499f6e6d21dd61eca6445f549a096761d3dacee2d67ed851762cbbb81a6ef82904da65b5da50033a329d62652eb4679e0f8dc18ea7c5a50404574319ef9f87a79a67f25f881302cf6c520e4c26f6e45292e3121c24e79b5b40176d3daf63e0a4c15c5ff49a4cbb22739e0ae86a9616d3cf851bc90ed928941a433215ca09fcd092367428e9e3b5c4daec9915a5185fd1f88578936f86d294772a7f5551fd3b39e3b9017f3571f6d2619b03261a77710591a3d0c77607533e66ba5d26b709aae481fbc92a05e4af1c841273f04def50377ac8a925f7f405595cd23d3ad2893fa6a2141b9fae0636447f2754a1be329b32ce607a758a0367564643e9c617fe453331e36abfba59fede9978e4a90f6e29c633f8854001101bce20083cc3807f3caeca63714db9541ee99ef1ff0c336909209acd2ed0f232dc29f78f7764bb491b84c53d3455a1da37a97cbdf7166fbcc73b829302be1f9bf234481339cf833cfc8e994c39510a637e626f1b72b8f8b5cf313e95be5d10300901e1feb09206e51faa94227bea497913e15a8fdd018fc2582f07e2878c4d24e29b9ecd72097dc4cd574328aca1bd5201ae4ceb25b972c10e3d6ad9714d5690c20c03c2ce204de3ab2b949f2ffbbf7e5811d21b597d4278e87c2f671ed3b15ecef9f63bf7b2c32c2eb4d129189b964afac06d557886406d364f9224f6252a3562b60b960b437af4a3fbdece3e9919d748a35890081d8f7c359e7985522790bc2e8fbd6081560d37c69e9dec93258e434de1c0262c7e4e41de2151cf2ba2b7af765b8065db15f5d6c0bd3ccbad46a9efb13d06a97334c5a7d262309e8096f1b0d882d5cc8cf64d3e1d0e84308c872a407f3c617e2e96c5f0e6cb8944f51fb8c3380ef6a1d2732a3f5c595f2f86e594ecab7f502479624f79b300f878a82e4de557713f53b69f8225aed45836b46cbbe410fec329910690eb5c3b75d8747281bac443c7dae474ac18bc25fd36c2591dc51f8c7d185555ce7dfa77757f96b9eed06c967669491784d11f4c710e5918433342d06acabf617fb861196947c0f3002d5d039d15910456b16752e388f258168b44c0331996a7ab9c7f737df9e3f250f3b7ea095fa827c606b0ba46ea1a6dfab96a10db8e00249b91ec76087d0319e738f0241816e053e98974111621cc785217fdb1d167c4a164fa3cd3b2d2d7fc81096bcfab24978b3ec6b9be8381a2fb8fb76c0ca860960157bcaa442208e4b9d8892e50d66e94dc18bb64ba1e20ac1256de5e8ce44f2f173997c60e96094df086030cb445a8e4b99eba757285548e42af772a930eaf6abd7111379a2c2846c451143072de2a14d1035400385c477f38ab6da8689adddf966de5a9409df7abc293845fac56f570819c043950691c97bbde06a1c6e95c15d8531276c20c5c795f2265623bd25a80e0e439c116294539d80669058fdf6a57843ee874624b5a461ce0cc77c2859e19a201b5c2e147ee496e7ae474f1186004881ad88d6914aed9b60052be310a1d0061d7a462872f7218f5c25c1296a93b60c35cfc09e2df6e02a30c81900456e8fb9672c2661e03422db14bcdb0ac182ccc9d28aa7a9003c5af4c61df340299b348745b3860d08e462215d29e24d5d219663184f58b64182e0512802e324c2c508eb14bd5735d3ca44fc542df8a08abe2ece29cb269142fc20ad33ebda3aefdba484357ba095650b30d28e8caa673a0b46256361d9aa922bd78e8ab2cd62fbdff9492c1e967b2a14810b6d44a24f76030bbb73ef327ed9478b243af939c091881d44ca283f892051ddda5ecf10ca0598f425efc068d0f1f330b8190368888aec5edc69970f824e7bcf24926cb309dddaa5dfdae70e607b41f5d4c21cd84e5d2b5d3a3e6ffb6ea1a41db07730170f810158e2a51ddfe8a43750433c48a7638ff1021ea825095afe23ddd368e86b51215830bedf1e0461b073bf18288df60a6b24605db162f434b9d9f92ded6f69d1443ee41bcc04df4fbb85e019221923aefa352420494481805f230b3a8d81630c5e9911d4a8cf270ea312bee388242bb822e5016f2debfd895d4a0bdba686e83ebc98232fb904f600404ac350d49c24396501dfbec5d16d4b91329ad0489d7635ee7f031aa8197629cac67ee5183e66bc2dbb0afc2ae46eceb5f695724168b91dfcdaddc9d72e4df13cffc444be3413c0048174635d68621b22924b1a7d4635a83dc874c070273607b8b81cedf72429a5aec84aec9f9a344209f1050daf71a89f96e3ad64ff8140705ea6c994b6e029263a999359e16b5647b0269be3e6540f9c9925ef05c3aee9f9511eb21727f19dc48298363e0fa93d6d8074c01c86b73d7f1318a1012c3ec25093305b6e1e69f01f0276d70bcb67eef9aaf73f98e6bfdf6f70fa0a9f0d59254c2bae83b21c7af2bedc7c936c779412efb2a3453a4bd4d7231cf5af93d58e84f22e5f1cde58ed8b3f6bdc730bc9e97cfda8bc348a5fffffad125063d25f946b6dd4a480fd34bee1bb6a6bd3fe1ffb8d4fda10e0a7e4073fda4d615f55bf336ae82600c2fd3be1d66ddd014f43f8ac7393d5aaf424fb743363d68b2985533254752eb836c2492b1840442dbccce87b7fd128eaac5c59c002d03032e5348257cf27a3a7505becb2f6398f5142fc0ee6a5582cb5533d31d4f06a46136688ddacdc387ab9c92cd75e0c824e00ae68683c60c8bb1e6e6a101bd34358fdf30bce5043995d08e3597c7554946ae3dc3245bafff848eb8a5c97762afb21c4c8b2f17f7551923c742e8cf45bb327f635f1dedf5a636355ec161bdd4391e57f1d3f10a84ea05bcc116a7e32b88993a1ada1234180e70557bbf953d592734e5882c3c6591feed67aa3b74ce78077901ab8d23b701f580afadff24a019e4b66af37f6a3e2d9c0520291f5d9c8736c191469c45321556ff788b6e4d3e9fe1815027a72c9bd54329c53cc12c1fb98abcecf6893690467d8269d9a33c06762f6d2d530898c1147972262b055904cac1477a6088b09dccd8674ecf64edaba1ebce01bc8e3c0f1d9bb54db42ed6cacfb29fe2f867716d85afbe39fd26be51f5f12e0b1e7f177947cf59d583a8742dd44c0ed099f42c84326868a18c2c2f4c457ad70ce2581f9b6707b88dea581a88cc8cf4736a665465ceb00beab21bbdd8e989f3ac3f11f9728ace30ed3ddc69fcfacf3a734ad735b43929cb686213fe0856d480cd496ac91a15d273d716a8135369b36e09fc4b12cc0d118fdb5e90e20f85a9a5f721966aaf98819a4cd1728e765e5f8f690e1ba4dfccec852525359ad8c9006fc2472a060a1b259155f448e4365682d7cfb1f715cc29b56d28d251a610576f5865f69a97b880b0fc58da3a6603dfc823cd70b68eafd2d5cf4c7ca675690387db2a5a54c1f928b432190a0f9fa6255d47bab9a0ea9fe188b7fea5d434e6bd913dfefd837341245b557353fc8b4aa6f5a38b46717c64088b84276f157217c26c63b4c104952ffa52d25830baebdcf77182de59b42831c7595baedb5511b760b7f08193f1a66b485c30a33e63c8bfc54f047025ebc0f116aded89f72d72c35857ce4188c0f1a5160e46f655679cad619d9d96275b14a77ab75df83dd92265c005e19ba1daf5edaa8eb788d6b4077cf70987b5b367ec44cc2d86b06c6d21412d8650c03e56e9d94ee9977295617d626ad2b54500d6f5d614d77190012bd2574951c9e57581ec0ce44d5492c9e4143c2863379bb37d891ff1ad81505015af1e75b7fe672e75b531a757b696b60e2185b5570835b0031e235650a5e4752f70013f63d453c83536e28aa2fa868f93604ed700457de85cf21c167a2b843491735b8488f26f37ea43e3390ef0655dabbe534567c79af9ed0d298080ea36d84d03f5616b6339b741e4d4ced952730b4b560843515f0d6161355341fda31f2509ccb65744cef6a60200128cd8f3ac3aeb9ed6b0ebfb0e4ef3ccabbf3087fccaa24ee19ff97550eace56b267164c56e131427457504827004c7d2d7282765d278d27c62f4aaf2735c1335f2c5f28db0a3dc101e04df874c9a503a1c12c20c66b169582ab4320a8ff996d300da75885128beedab12192e402cdbd73001d3c3578a056bfd913770815c6bc82ed58b815c4bc1e771a0c9e8a296ebc14e8ced4663e9473b51a891b91e0430bc866302d429834aa8793645a504d44c80cf601fc7c85ad55dcddc94555a7ac9fecc65e13a134df7284dc90e481cafc3a916682c67bef851ce722dd11098abd9c40e51abf4aa7f8d7f50db4fb94551fe0a4057e89715395b752843b5dd526473e9347469d8b7168946d422e3900973236db063323d97c8ae324cc8482302ee572ee8d9509c3d1c8571d1293230e7c5110128dacda0c09ec7f8f23dc1d21797244e78b332f5f203126aeaac911328b9085f640e43510d03dde52c9c886513100139cbafb92342c5a37124ab585a2c06694efccb9a2a6f1bde8243c94b17b1c97e2645bd62b76e1e9fcfb6d2d5d482ade7f74e3fc74e4be15d10dae18731f51cbb4af6865dfbc1e219db225edf05455223928dd8ab174b21b9914a9be14942b78d15777551d254e09f48f829515ff75c498d0866ad1ede5619125fe74bad8465aa1cbb7be9251fc21c52a5e2f60313af9c63a4aa472c0da4806891b8b63eb92999cfe2ac4c542231a2a01b8fae3e0e8f78694b0a1b1879bb0e2cda575d4e2c8369ac5d32d4307c6256e0dddcf658fcc471afd79026b68d773e8ee04805274b118c37114245668c91ae619ac9262b0475ad4369916d4fcacd2e8f77d4676f2415271190e54c548260e685d3c8331d828248dc537fd067abbeb5319b6ccdbad92e3d2d3146a5f590c937d5f2f84de2be76e31fde1cc56a4a19216b8d303a3d8bb4afb309841f1f947081f98a6c17545a8df6603ad01433f02597267faadda3bd81b60704f5aae3447ba776954b975235cd8c97b8809b5591938ec19a602075249ebba544d5c45df192a8ff046fb4bf21226bd335a9db9cf0dd02df302f60ed86c690e5ed5da4525adb1a890cec13e719ca499f76f1dc344f7d6075f33a9dc087239f218a1ccce7091fe75c9cdcfd820b5483e74c40050f3eb3d55604fdb5c252dfe921a0cd0283a9b0141781152faddd45ad8e2e3f1e8f9349f863f95e217a0a340a11e2d3d49f538fbce15a366df79b4fde42c98b248f6dccdc520e652c0fa0fa6f5b96c2053f79cfc2aa2d38cee04f8e6ccad801edd291dc8f29bef0998032cd1c07b027892ae41e486e422e250b34e02f5256c9483f8124a8b2e4953a398c7d202b3069457ae31ec635c81fcf024b666555679071ba79a4f5fcf42df24791ec26ff9aab06e7d5359873764d243048962c1e364f42691632492b740aac65337e87c1bdb9fe1fea05e4b7b8ac8439ebf15a39934f1f22f283777f8aca70f996c18c951cddfd51be2473eec4bd48fa4a732f2e8276018c31059aeebb2164dc3a9aec42d8154aea1fefaafbe7a583c258b95c8732394452fbc93b73ec7b59c63653863b15350a8fb049dd3aa68688ecfd5a7c27fc01c69611e5cb895adce0d375e26bd039d677b7aa054fe18f9e45185e93bbb4c0536999a4a21744d8fb13f316bded31696730afc55e5c98cff29b4cc68f3082d8e38cdefda347e07e2acf88726cbb436c6052d828340d3b7872b5b8102023750ba83413cb947c34b288c0a61f94117cc713d1cb2781a3933b4c5028deb200d8f0b0b605e4ae523c8d1c2ac3644e63ba0a68d2892b7dd2c4abb25ce38cc28d6b6a5fbadeef95b94235e324506d349bf5efac2150a979c9671f348420d861583a9ff31fa436dc3a2141a734827d1d64116a3ea42a3150f61aa89bbb58ee1f4cb6da250777d6bdd674d4f7e30ccf5d0299ab2cee7bb6db69c2c898849c420a9c009761681dff518ab32f6e2d64ad6f7d3c242cd7ff358f448d4cd3a1f8e6d254d46e58d3571d2314b2f0af97ae148609889ef8859976a9d12660af65ac550d520e97cceb166787c3e7b442a8b9825e339794ca06999fba317bee5314e263987ca42e312db1a28b4823f48f38b58e65b682274d4bdaabf6a85da15910959c8e86074c382b6e30f1b355553016a3adb77f05cfaf2cf9232bf16c56f31046e22cb6eb78029cd289a1cf9258bd75948f26d914adc574ea85b433775db4c62a4746ea8fc5e5c76e584bf39cc6c80d81c488f99a97c7c5f8aab21f1d2097c81290cc504d4a2f55f6189e8502920b7b2a2ab60c08c1531940e087495b0ef8aa02f8fd5206e5132401742355c8fb4f8487da320e89dc8568e6410c26bf0b1c0c595350edafb2c1836c9a63499aa2634509ef596b2f08aa625847809814cee05d6472493a14956cc1be03eac6a9ff553e18d4d6e53e662de2db05c869486a5ba74227c61bda889e8c1fb9e731af34dbc93edfc00ed4aeba9143fb703239f93ce117928fddcd755306a5853e944d3532d98d358bfd9a7f74ff751902047e126d4e4e8c7d2565d4509c14283d6ffe76577a1cb8a56c364ee0932af8d3617ed166a014bf77e417069a180d884f53871ce2b4ced4b8614f00745cea925cc7fb03117badbbfbdc4cc8f00519219bdabc12f5261bbef76fa3d56e486499b1f84b5be92fd0e3a2e32ea026ec387057402ceb0ad6193911cb6b785485db1c3f6b854877bab67fc15b1480b0f3d6e682ef20cab351c417d207aa6503047a576af542762a97009afd58fd1ba5389dbaf25e5e93df9a2f0d3b3527e5e634de03a42592905e92287a6306a4c8a15565a6ca6860cf6c62f58aedf5b575920d5aa3d79bfb4bc8f3e3bc02ca254ef2c25f2babaf09d44b7cfb4a320c102f4472c70612f0892430c3782d303b50cc12304632e324409143c543bbb6b764eef42bff5d7980d6950ba035441bd13d1798a4b4a1ce8c802667bb9bf3521a0ddfaed2f9f7a55ba912e21694dc0529dae3405c0883429d8e161e5a82507abb7d205ed2d4cf007ec47576ec9584add448cd30834d4f4c9dd5fc30fa503bde9234512d0764b840998c723101c4dc34a07071d4dc84542b97aff5935aa2c110f9116a8a9680d6ae53843f4cb109612159c02e335e60201fcca643f249f6d62e7fb03e8c621beb6264e38da93c1dd1606c428b6cd7d4ee03c49455fa0ddd1741c93b16ca1b8dfcf0e64495630156d84079bd07a27bfb1062cf04e99664960c374fd79371191edcc739adb38cc5b10ecc91c0f8c5fda056602c56aaa1ae4a6b8528e071ea8f164caa3ade3ec71f60f97bc05e2dcb00a2939cb89aa694869d51d0cb63c9936b80f20864ae14e5d6b84201c51ce805e9b67961254c3886c24bbb708fb8bd22f5f8dabe19035fc0712c8b92e72277116af69d621583e019ebab6ed405f5ba032c55ff1a1ef4d70f28e5b1c0806624e010a2201d33bad5e483a8e7568ad78a5af43a27f324bde78a46d099cb862260ef725a188083ed897b84fb2fe3841d3bf48548b028c5679fb2f0b02b56d281322c4ddb62557e3b00dc0977b5d1f0aa8891bd759b57a26bc0b1ba811e927fb632653761012117e35fbd91bf0498a214785df1e2b7bb008223b6f632f54e862c402dabb91634618f876f1e791fecec8407d369a687c7c77a5bb7c1ab7a48abe59e75bfb8dfade31e95a684b0c860705a5f088c6cbd0f86e57a7cf881c02195471e518f29b06b841631729d94c09994fd4f9fc1536c1ad1bd5bd3a95829642d9e6fe7702c4c66f0eeded75af7248b92e0841057242cd3be9f37eaa49a5259b78c8202598fdc66b88b778752a3f9c0b30d98fc602853fae349c1562221bef3cfa999926002cff9e522194ee57e625c25114d60f8ab25b51d46f8cfda39caafedad683d998f456b32a0e0237510b741554c8ae4ff5f096f5f5ca30f2028bbd48b310fae55485fa136c0636abb57a67ef8552c055421257e50487eaad5633490fdcefb5076535fe97c5ffe28a9edf409bbda3b90a50104e3ccfbafdb8fa4f4df37500d7422db75c1153ddf6a7e5a2d9e8bd00e112339eb768c61f8f024340fc43aea90f014b3bc8e599016215b8ea541ef859206b17d8520698eb0353ce827874b1821952efb0b6080538a944abaa8a8b3da3c0709a04ad0a6623699f32406a6977683cc9f22d278755d05d5dfd90d5b423088f362c6ffa88c37e9ed22c60dd154c430e4b14bbebd09007e051fa247aac7f1fbddc420134f86b78d8bd2b876028a2c8c6a74de9cec85c689588bb497a786aaccc73568a06c65b537c41458d243ae2b04a234f9d0a86164b784b0ac28b1ceec05ad6f67e5a568e9b07369507769bb30c1ef11e8a1d3ee2deca22c4d1acada9a6b059e37b6c435858bc20ca066693e388d71832312e2d6853109090be3a03e1d719f3e584e58b7c0d745538474ba761545d01f6f34ba08dda0a7d23aa7af9b97dafbee1dbd67da071b7f96cb510bd4797ab7b3130ca3646ecb1b1c91fb6c007b9c7550afa7f3f94bd36ab177a73b377f20102f1b93fa86a5aa59e75e7e5ecb7836d0d7f05bced9b0c366dc36aec2f6cb35802cf386c4bbfb191a614d8957409e98daa11db7c3a775fcc8e630c3bbe880c98cc78d54620f4e0fd9bacfd114f9b9076f0a1688efc3fac5bfcd647869fe9602ab7db18f95e9bf6614a6a58574f0d53aca826be59e60144ef46b53fcbdcc7d7bf7e3f12412b06506fbf5315a14abca76e1f87826eee07fc94efc7492052059ee3d662531d8af5a9a0cdc50e932e98b0c051859d79b1191125358d81202e3dcb1140db9bf0f1c303a6574c6f2e39094ff8c9468802a629243ff76a410482cd9940977c3c59f400f78c6fe5231a6466719156abe50c09fb01d4409a40c69b812b8d9a0aaf9c0fed499ab1b59929c1919a48856f7d682cea55528d824d22f4d8906048612478dce5a42eaee527a5d3896bc88d7558e58b74d2b47ac6113379ed910e6931c06855c0a3020ee8a0e2b566a58349cff32643128fc92647c8c5f0fb8878cf4d141d38492c494db9a51db82f2408650d7832b21f47718ffd60f8cd6d63ea094b35aeb904a7cfa8e2386849fe3afccff87d062dd8a4ab13a426dd232eda7a6d9438bd1575515f07654e58e0791e20773b8624c3f96c84c7b6b07fad10c84d767431ed667fb119d6c41aab4ef171753f16d115a84e49699bb767e98f6e95d9a32a4e1e7676c46ca64cb94bce994a19b54dd57d3e4e76a6631938f9a1c628731ad5b86cb076e99144b2470c19eddd8873444b20fd8c0d3310a702c2517b59de72014c8e4a15767aeea223e0617f672dd99cd91bee65651cb2978ac3eb6ac71cc327d599c1fa5511ad6d5121b2ed0478e5b8f50dd2b48721ef71821cb1f0728272803a07b04b8d479efa1e944d1112361a98944193c4137e879edea7d17739e591e3a7e9eca4c87542ac7e1cc67f9e8cc8c66486aaf3accbd3622ece5c3e4b377a76fdbc622f3d16d630ce356c1359ce488b151127df26e9708d700598adece7176e7625c271b8569e9b3b93caa7bb91382381ab0ca73e5bfd4914d76d1f22ed4fc43089fd26d1d630c32c82d5bedab185700d64c75a7c7547643e89087a148ffd27c889b279b2716b3d6a82ed48ac03e8a5056bab174b27d261b263b55f4016fe171de7460a6b43248b77c2b2a793a8f7542a1c076d93673c36ebe7638248dfcd69e7fb51166c0ca0894c9584b89ac63eb5d3bdea7e271a3bf5bfce0e9dc435c61e83aa3122c81d765795e1febb02a16717585f9f9cd61b8c96c09871e1a41ba9de29911bb1c4f4590f58af46fed6288bdc9cb919115916f7d5dfab91b481ae912d9fb8f4e257be884706809c9606a0caf85aad20e3584bad61f47761af30ac329ae468ec9482e65078be10fa4c024533b58c652f94fff73625755626dd2d20dcac14d665c9527b9f4cfa839727d9f61de3d740bb6a84191f8d31193b4ba53b2dbd922dc607e9e382051f5c08c58b5a10f626f3d6b675a1a7f25d3c358e1a0164384e127d288004e8e823f9b187fe551210a7da5af89ba12fe471774a82e211d58ca1eada6fc99b9dc6e81c446604a21dd5077ed811e6e8e07159cc5805c09c224fcf114a36485391bdaf20ac454fe40d591486c796d205ff8bcbe04bf758c6a5ec372c38fbe4220d64ccf497403088755eca3e2a393226dc58a6637638a81f19e3812101385d1fc294cab1c15e7ba508f8ff1aa76774ba0fd09d4b9dc9f8b116ab5247898d23c2cf508327c100a07e2e0f4fe57fdc0f3eb9f5ca2d8385597b322514e95d7f290936ce0f5b6f0bf8435a1cc87c7ca2048f8d304356fd41d2448ce52fd9d0142074492454cddca8ba20547b0722348edaaff46c04d0217083e235f4862df7b4043d1035c083b61ec044c372d81d352e7f88328640067a33a6028775211be46d620832cae8bf4ffb6aa91f0d044aa658291134cd5d4e3d78f0d9430074f408c0d1a419c8560cabae86b050735637fef79b86cda7587e467af8e4426d4bc25940f3d94297fa088af15b16f06a559bf074e3bc68d20ec7cfa6cc577ad35b90d2ac007d6c6fcf86aaf41ea8880f1da17c6a5a469fbbac3963809753c05b61a5078e7f54199e9cd38b5a744a6268007f3927d6080336b3696ec30299c54476b1876a3123d0c7e7f7cef7084898607ce1e4c1b75cc63b07ed904f1c50fec07a6280bdd30821ab16f8ffd72ec20eb04ed256b49a490965cbf64608aa65a6c5630e6821fce3d3ce5fac8f92e8c638550bf07a052e4a0e4d944a380d0e68da285380a08d1e97528cc7c77fa25169808c2d332105769c0d5963520f98d637d5f13e1fb90d3878ab5613d53abe6eebead158166044d61871603f9499f5bfbde7f71683098d0142df4f7fc8252f414d52c8b615775b7a092b76bed446f01a28ed0312d3df1550a278fb20da2f4e80c8665c007f63ff00647149528084465e22ee314ee2ac053d36ec21ddcb387a7259ca6158a92fe3cd342e7c7ce5006436649fe04023b1d3af5c735740b57f00acf5da354053a56d1088549897bfbd9a26b5decdc98e8fca2459ab7f4fc649ac59bd44191c22fcb547d0145d4f4246d7921fb31ae0a7ad15b803a342fd07d4b5f499f05465d6f9b5c2f352a9c935cc74e45e431bad8afac200b5310a63be3532a8566735f24546e8f7364501d053f77328a5b1f8c28e91017852b7fa7fb51e6b697970d10a4e5960d7f93bbb24acb894d2307a0473000ae658c2aa78caa5fd855e8db51a1e0dd9348713d42dadd394bcef5dbdf7f8257125134d17745a8bdd7760fc1b31563b166d7efe3fcd6d445fed59abda9c3c1fece7638682e62c96a1f65dd27613b11085afb4d472fa1fa46f6c95f036721e8d2897a47bb6c8114bc38c414ea110fa30546636084b1ea94b8d1d0a724b9c05533c034ab5f41d3cb05253b3d7738e43bf659ca32fbf678eeb769086c78a8ccfe505c600150e9febf0362249e783ce6ef5a1f1ea203528a5f351747728197df7130a3591ff4b2992d6f75a4a601d0325bd1d6fd07be04bcf59f0dd8943361c76a431696211de445fb1f5f2b2fdf7958e99662f422e06f7c7af628a5c8b6761181e6696c288b075fb21271cda0249dc901631702a71d22c99d16a786078df2fbc80298a6574bf7b6455f7258f198f24017b4bbfa7a447fe14cc401082ef04d88bdc0ea071bd979600c85ac5f8293c7061bd4c78583ee58dad82d6ebbdf5ef1b19d15ec11f25de95032ae4b0065a31aa88afc338c95b74858ff5848814616f0c5a5c8a6936f516702acd089444b743d05b48320e926eaa9254f4a2d92d49fdbd2bad72963575eaf83d01886d307327b350fb242a5d5cf026392d82fa485524dcba26727834be78d809d31f3f537b4ab676c06ecb4b96917825374e702456e1588fcfbf1ad70505314f99941da5eb24b179370948aba864d4bfe789d5ed25ed4510e4445a4744ac86672b30a82aa7b21028cdea8d461834ee2a160533144dbe6cc7b8c31f34a1801096e9f5e8ce741c434212c0fbc91a7f5b29df742c98e3f617e289563ccbdeeb37f96f3814cf6af82b97008e2725f64d28b12525765924568c8c3a5196513d574e55c635fa0956a6c9cad3104ecc9551c24fc6f22cf56515e2f31fa4092033542551b78d11cb7cef4f2a3370d6fe86b63999a0b4fd65f59d2259620b93a06f0f1f66d965848b4064bc5409e60ccf568e9d05497166647e46976a45dec829bf87625f794972e1b89fbd700eed5db584d09cc3f149749c81e3fc669f48f9e1940f643d7b770a88448824753238ced3edc866c665ae1d370deaf23cff4149526e9d100d39682e1e2c81125b4c8e819b65eabae35c433b98d22eca3e85426965b75a9c95626f37870370148895ad66d466c048fe0eb7c434b6e3a22f1112fa8c1ea06b774b8fb7a1cfac8d282b865f4fdf23525f544365f99acf496b7b16080649d702151675061dcdcc271edc20eef8ad67d18785eca0b95a61857b1b6e76c783d887e5f3f92bd7d7decac6cf8d180d4bde532594e1cb2446571f84adecb53d15a40ab6872f625e2fce2b84c3d42197f3240fb6872f28431e8289cfd2c04f1fdb62df276b8a6756c8ea2f3e3034e64dc76d6100dd7fba6193e6b6cb742cf39faa3d0d8210e96095b2179d785ea0fe60564d7d634c3edce2518b991efc865ae2426d4a95bbccc4618015c3090e5d150757c6386cdc453b38bbe666003db1ddfd13cb93693f354ddfe3dfaa52e3166107060550d77073458ffe84c0280565b312c106c78ddc64be7ad369b14c89dda05e121a35e422ddcf7be50d7dc4640147e4040ed5bd7a36a40c885808633a63c2b3e8ea0daa5e5337cd70ffe144456f8b9a3badb0fb631acb6080354f2311ad24f83790eea6b122d7cd232fd1a1af0d8351a3776da017703b1b0aa81514c9c9001c1b894082daf94d04863614a091a9beb4466b24cec750052889ecacae4ff83b11503ef1d1e86a18478a802efa724048f6767cea55f7c0688702d05024587c8daaa5cca0e6a1946875aad3b6c7a026af3deb956a8f58609ef478836a725490e83dd47aa6424d3e9b871da6d01e3e1869e7fb3f3ed3f21ec4e0c2878b3f49ed48a3d2170b8e7a43898d43e9e9f5245f7bfe92dd6121a0d4eeb90684c3116b7d65ab7d242b43707208e714232305a9df460edc4705cbcedaf8b5f90a4c6f32fc28a85fd3d75b3f798433b033d88f072760bafecd86933d0266c6d50d1754cdbf19928f5208bea9d22eb053b68cef6bace70aff58ec9745eda50271d638c8d0dca1d7cbb1aeb1f7ed1161b57019e910da92e9358eb5a665339bccc5515874a8395024355063cd8fc7a5ea2adcd19bc300b86a09f8dbcff355ca5868d158eec275307f9db2cd01b7c65b2d5b36ba481bab052c88f9df8f41fba68ea26f7d224e78c0585f8c28035a6b367a59305c554d074bc7280b4c942c30a37cb82611ecf8bd9e6aa2a9b4cee55f51ecf855aab947a7fdcb74120040601881a9eb1142c31003a03a056555934073d16a3a606d3ceab3fdb55c5d536349266c15edde7b6fb9b74c3249199e07a807bf0723164caa049ef379549cfd2bdeb0fc8ab39088fb2ec1b385d582ac7273e36c9298f2a64bf1ae25e574e95dbd6bed01a9cedbdc56e9cdf49f148aeca3cf51aa3af1324fabbfa55c3fdd17369b24bcf34237d4c17ee6a90bea827e82e6a947cc33dab74bda0afb322bd88af34c44c1da34d361775f8827ada3a2fb8ef81dbce7d767f6e1a0db8dd366286d0755461e726605d395cb121eedac083f9146eb1feaa260b83df1e96b9e3a162889d85e888ab211e251364258943c41a47143bfbc6902f477ac7992e958f3d431e104ee145c3fa7742d3a6fa60a076ee6a9230c876fdad431a4df0f0249c40a703fa7f1a06e55fb6ef8b0f132d4fc6287f465c0206f7e54b0bc9924d29c48b464d7ee78ed6ac4c5ae82ddcb7a66cfbcf407a461c993ae7b7e37a74bdc33465c626977f4e60fa49493462923a64a8830f16bd5e69c26aa8418c6f739e79cd415e90721c61823bdf4a79b73d200b32d1c3c40a81308b6dbdddda953f993aae03929757f971f2bdfe577237e744e882ccbb296a448a83b0ea44482e360ce9f1309d4a79c72ca297780039fa22391ac95ad098595fd44d7f249df12b9cc4b59962807098b822c96c7c25eb2603948582e698c0e5922225b946a53d7d361c7ea8e2081c5e39212e12bb41569a89665d40993854bd29719ddc0c8301cf58e47891a4f1c2bd82e612975cf529488de40049b473744b87f7433c219a9dad4fd74ad0ec90fba169eb259b868107c66d3a7ec02494aafd105477a02c94fd53296193ce183b35d6184277e80f35bd2bf845aa802e777e14c12e14c2e0123f566500f8258a17e18e2a915a05a7e88afa00b28a7419400f5c3109904d5f243e41228bf496c2358a43100ce91b048c302672f97449a988b8cf5719e5afce77d2806dbdb673cdcaf7cf69d334f2b3ef36e6e15ceba9b5b2885f30c0695d8d2bb7c0b28594d80ecbb500912d6bdcb102cfd2c6155fab4a9fbec46470455025bbef43cb47ce9bf2fdd1f92f82e0fa577b93f94eccf2f7deff21155bab5642f0e8953debff4954a2e3704a49f5f22b168b960146c676f9b205b5a6ee9fb96effa70f9d24794ec7129b5b4aef4913dd2d561f62e4049cabe050b304e98286c96b03cd303eb9b799a5fd795ba8fd87b14980766dfd20425f481e7dd679fc34c2cc664a32b6113a6ebb2b9712f2cb02d5e586059bcb0c07638bf0ae8bf02ce670123aac69e09937d36f2b159e507672fb1f651d3fee769bef6f4bba149d87761de856db08fb34924bc791ace2f5b3ee111b67f72601f6916d83c392b6049fb952782520147aff23c8c54545ee5f6cd0ffea31b124191e68944ca6870c2662f7b64add6baecc1190b673effc60fb00e3319934333389330ffd1f3e03fba25ed471f513ccc2f69d7c7caab7c44e5d0332b443968b70621db9f675c5daf98429765dbe49eabd98f6cd2928e88e9e78898de1a63b040402112635acaae37a6b77693d007367e03755d8c9af69ae6ee9a77bbf69996d51c59f6f389607feaefde4ef8a328a1e2c607352423c20950f687021c41fd30242241d99b04f743a216502319ec0e900390a7182d4b26d2c4c0fe3422cd7c9214560bd10a4bf08f92063b8a566ad9995b03c565b6ff8ff1b47df7833ef7db67106fdc53ee39fa28dfa9c04a4c3d20a0f6dc671077f1bbd1691e05b9ff1843efa370dfe74ac2ddf61af883fef61dd552b494cf1171caad3106fb19088835cc3de5eabfb0c052f9718f6267759ff4e42c2d4d421fd84ca9073af423ec8fc01a7b3f3061dc07f73009db9f2d87052db0fc522a85a14e086796267076c101e797570a6678f564a108f6ff2c8421ec4114ba396badd333d9ed630b53ca6e4a63b5b2561289524a29d53229a34f31dddddd1d06d3a759f6d65a3a279d54051186be068e3a60b325d460ba534a04771b4acae7c5143bfa3c3bf254ac4c66059979a936e2d1011ad8adb5b6e354be1bfe926befbba1dd2c714caf017660645736d6748f72769d89f14453ec8cd6ba8c34d1a5897a0692a665d9b16e3d60b519bc7482c78d7894fc506646099c634b05d1e5041346b84c71e109268e40851c8a9a45224cd4a946224cc4a82678224cecf984133a32124915809a8815492842892260d0ba401e13ac4e97a14537f1aab309984a3741869174a2042859144c6430c516667013c58a29ccc048b78cef53ec191de94df0e008840521ec5fc211080b45c013085c6b873d022a6577d38fdf0e1d7da0b87f76115d7cc9be826c5bc6bb6976b7c4b25bc6882ec653d5dcbd6a7e3bc6f8ec2b741ed580d77d1fdf031f9827cfa6e438830b0b96c13daeb1bf09a0bc778794202051de4b94776f3c14cadf38cac67b212a4a461ada7fa044f5c783a350ae10352928ef1b159dfbccbb31d2d034ee06a704e67e09224425647f3b624bc73c75739f653a72cd452e7271fb4cfbece7b7237a77b31bbe06eba494de5f8e260aa906e6e9262ef1e2c5382377b8ede577ea953d53a8408c21e0904387336390d184d9b1707fadad301801c54b05354968420f8a0a6122475400841096e00008503041d12b60fa3237c0d4aba494fb41c26652c746c91cc0344553916605f7cf6fcc12c30e9080527c9be6f793e63cd9cb22e3c5402e11c3d9e2974f826129250f945c22d8ed095150e17e949e9637a46ac49262a558f10814300c36cb95943288b21f850636aba4c0276c962a99d326794b3b3213acb07c942b5313a66555a7a6523555753c0d05c5f3501a6b2fada8d35e99f67a617ab5224c53b2ea36782a37d227ad3561e8879f9da775a4e513e3fdfd05d1862654c3678f01f6779d4843c3fb7baa4f9aeac6559e53d4a619aa8836341e8da70c4491e6df7f0af5298bc5a692d890ff0c6a138cf79f5388363426b0ff4c1269ee9f3297abe5fa71b98eb409dc41b4910d0df58015695cde7f16e953c6624d1d9611160ff6d2fb4f13441b1910d02402fb4f9c480380589f3215916aa6e6cd509b5e2c8936321e1e2ec0220d09a84f34164b12138a29c1dee2fdfb08d1468693e17412b07f2389342defdf3b7da22e96ab7bda489b5cbc7fcb20daa0434334c0cef2fe6dd327ca62350eab8bb074dab4d224daa040404f8a220d8b579fa84a0553c58884dab4a20ad106e5e1b94250a451f1e993c7624862406edf5ffa20daa03872060502f6974722cde8fd654e9fdce5922bd78e4c01f69745441b3e2467f4c95945405fc0fe1b88361c08e5fd3dd0a6fafe4022cd84b98f3eb96ac250ff1dd186f3c819f42392180e323aa5df730d1867ba260c7df721396386ef86b7700cada509b55a1fde1a2e0d2933682a8d4753bd68aa189a8afecba3c0886938b1988683e9c7b81f98b9b2a1ccf5990b46e6ca8630fdebe295325606c462b180307d1000dd8b4cc593a95c325529e3c1f49fc4b58865383152ac450c46cbe6c235e422b95ab886307d00b0d415ca02a22c16ca5aa12c204cff050b6d0555511ea72a16aa5aa12a1795cc7a8ce2782c4c63b118c5c1f44b232a5d432492bdae214cbf05c5abb31ce83acb59ce72204cdf0519ecc45963792a1ed23b4f8a8b9654a2a4c0c633e638247b638ef3ad4859566ffe98641f930e5df354577348daa83e72062591567408d3ef3cd02bb29a272fa7fa481b5e1171067dca22797585a9a7dac1d44b418ca1d50747e3ee7aaa1843dfa50adb9fd29aa7ef4b6979afeed5b83f98d6431b6b472648fa3e267d9aaaf90df509e68b30fd2e7cc1f3593e2af2079b131661e84b6d861485bb01a05f77b0766d87f461409686a12e9d2da6f4e3027d9abf29843aa44f83075e913e75afe9a9bcd7077b61fa0d350cfd8fc9f7c1708aeba533f092a163ca65deb2a7c4df0ef2b39bbf9ff6c7c385a32452d83eb8dd79bacf806242b833d96a93966dae3ea17cbc9dbc597ab8733caedf0e2f1d567fee861dd62484f49082e57b592662191c74f050810fd8a874768eb480821adb24d15cdf7c71d7edf092596e6893b0f346901c11d7cf21b1378e7146cee4c7a379840067b3bbb971f63cb8fbd2a11089b51810eed7b41de46b5b4823c64cedf62071e626ad674f4951fc33b04687133ba582cd325d6f3988d13cc2f133253828d061053aa4dbc8c586a2c377434787b46ffe2e0373cc06229afce9e8733dd98ff100292f5f0dd375f7eaeed52fcc7d37501cec234f7415b840e7d9cb11010ab468ebe6fe566e56ae41240706a1b8823ed0f8398a0e1dd28fc03cc50a78e01056760fa63fe79c73a210c1e2e8282b760f22f5bcef730f616b1f6da21d7dedea90813ea0b0d99743878fa628f7deb669dc391dd2edfba66fb83b67cbdcccdb365c916e558794b6c0f3e3b7a3056e9c0e69df7c6010cf9dc282f5cffdcd8bc24414ae10fb37f50a4003a66e14949f77601f6918fa3e983e7773df20c1f4b79b2d10a62f84e9673787b86f2be990fe045d2cb13906a522a0810f44e183f30b7d1d3ebc4f2a4f0f30fafc6227d847e649a58e9e6449f4bf667548df8513967ecf8e71bd4204ddc7979750c618196372f4fc1ba7ec28b84cf181143b4fa40923b3af1346d28f37c4cf88e01c3f1220e61f708ecfc3e2bed903b83f82dc6b5bfd1ca6060ed10215c4900fe207ed397777777f2166507e8704410495dd20b61ee1a637461afd3c24ee2fcd213168a7491049944cc14912a81ffc83181253842d20b1c417a030832014fd2ccbb22ccb5e881954768710398209119001072eb801105140d950fa36355a512a85ba21a1e8d7a410a55229d44d45d1af284a4251fa42cca0e80dc26f127d4bf3f218a211e9fe98d0752d35a6b03ec88f299589cd3ecc2b7798f7c7fdd12f7f871ff37acd496125112a654e6c3ac127909cb1b1eac6636402491b9b0c361a4c20dc2fe5dd56bded74b8eab0372354d83c5daea029d426e9452f0bdd94b181b0b449569c1b7c6cd798c2d2188de1f8c5700e6d01f91d677dfd038618c2c11168894dbbbb74c146a0252f1c819604e1fea45469c152469a2dc238f58f3f35c6f8bfb8b13211a8416fae3860a7ff5a752e52d8fe88e5e7d2b9bbc796b7a44f644ae9836e90caffe1024547f739a54ea909eba293b27b4e774a336de36cbaeb92dcf0d15946bb33d04390c274cef76e1970a0eb62a86c04f34b8e8981ae4b9133a6c824d3bf1ca1d710f22f87fc70c8c864a3c83bf39a3f5dad249286bf0510c1fe4d644a394414425208e1b8048e4052e4e0ce050aab9a27e9aa2cdccfd9344cbf1779918d0dcea52e50d8ecb27bcebe54d5219772b1059b670fb5a18e7b25815ca7c7e5d3a7b9d3d326a73daab9334fb4888a1669987e1ddc5f0e0dfba52aaae2582e56b0d9c31dbaaa58c10d4eb8c1093182513881111ca370821cfcb20bdd0d504882951f5326919e50d84c4fc56b4c61690b36a30e5ab0eb5bc0c11148c90ad3c011e8892ee0160e8f689022d6018183228d7c0ecbec7307c42827c6cc568ce96ec8b1f55904e530eb28d60505df0d226f78d785046406c7fb1dd20f7dec80c132f5c2c73e7d3984c4d19e667904d3c63298847d883dc4c03ec8fb12e7d0f208e8319b36f1d0210dff49a496215b3f976e69bb3c42dcfd9364644ec1b227cea04f036406cb77e9903e2175345836cb1e4c89c81ee9d3217dd9f3c98be33a0e225882b2e726082ccdaf2fbf7d74485f4687b48261877d131b463e0bb8024a0d49d47e6a607626b4880c4dd3344dd3ba6ccace3ccbb40ffda9bbcb2051d09b1f8196c42240e9a4112ccd8f38e23932411144782fbd9745accc3aebacb3ceb2cfe368564279f9db9750ee97655e165ee9b1ab3f9f93d13470764bdd3bc8f7babbfb1df2bd5bea2e8f1077df75dd95d1615f30bc4e03094bdf9ff21441c408ba9fddcfeea7f65d112b5f87d6536bada736356f44c306367bf92f4e60e97f9747d81fce937773ad7782a1cb3a7ae9b06abfc968d37ced6522cd7cee330dac7dd8a61de6775c89fbf9dd2d71dc7353060d245eb42168966519754a9f669452fa2f82b094524a334ab38cce4004353535353535353535353535353535353535353535353535353535353535353522883159672cd5457fe9c213e6c21108f683bbf664d46d89aee2609190805e25b4d5a0a20c2d2658fe7c4271e608c6f0e9407368915887d95b325c7287e3b3b88d2a67ccea49884c88a1742458fa13228c1412039ece842301cb6f014abcf582789a79c067af81033e7b120df8ec3ef0f1d9fb6715f154811e9f1d08067cf62176f8ec45e8f0d97370af4c219ee40d8fcf130b0bf83cb7b0e3f3ec828eb63b8827c9caf1790601c7e7a9c48dcf53090a187dff34413cc9a0047c9e46a03ecf17e0cfb3063934ca9278ea14023e37180ef0b9ab30c0e709040e9d728478ea1d1b9fbb09349f7b0a05f8dc5898e96f242d83786ad7e97323d13be820d4e8af493c35d10d9f3b88017c6e13d0f8dc46c8bc2c9255983fe3b3cc82003ecb25319f2518b08cefc2cf3209cc67d984007c9647903e982f9f254b2241c36729831a5e16114f3356bfb7189f25cefd2c83884da21870ff06e2c97326cc74f91c612f621560f4ef88276f01d11169b42fbd010810c3f2d10566f179847bc3fd33c493bf449ad83d334ff501375707dc06ccf898d95a3d6eae0cb8d9ee7075b81906de7278dc5c1770b3ddb1e5e0f93a6e86816b2cc7cd15c7cdf6062b86e72be06618b8fe24e0e68abad9cec7324806e1595708b8b91ee0666b80d47c1c521a918d9b2bcdcdb6003b4478fecccd30a6e63add5c4d375b02b86a10cd93b63361e6d71b6eae96c69d2fd344786aa919375701dc6c6356326e8681b3a08c3561e6db70730dc0cd16e666521684e787f3a7d67073b534dc6c67b82f37c3c86ebc354ff415e36618f7661298f339306eae00b8d9bef0968bb7f07cefd960f3444b37c320b5dc4cb23d783ec96b8b9bab6571b35d713355e1f92c9b4a0d4fb2aee33a3146b69c0872fd1011ad808d55c0c69ddd7280c0dad9564992c41819db88d86eb614118b156364630b36ee50ea4f8da2be6a50754d9c89535745e861edc06031a6318a4754575055f5a6a61a4923f95c5f80bd827ac5693b5a12b496d6a3b18a8a628c96d262a0a9b49ba020b0311744450cf63a7264633de1a795f5c418896b76931d91ad32d5109018a3bd9e10c560f147478c918db31e265c3fadfc825f628c0437588c99db920833b91b1d7040ec5481e77c30e039ff0510b6dfc1c6a70de6356e75776bdad85a72c66c529b48d9bbbb5b2ac17e7b7877ccb2dffd45caf6cf0db6b52697c2737e8ce1b9844c8ce9152f708c30f25bca4ec24ace85630c220d9014a04293a2264f9e3c79f2e4c993274f9e3c79f2a44993264e9c3871e2c48913274e9c3871e2a44993264451c0b09d15c774b9482499d94df0ef68c0ae7d75ffd95ec79f31a4f185bed39417afbd700437a94d2429a9b05266cf5d9ab0d971df0ca447dfd8616947fdbe35b609cf2884dde90d5d88b2ca9bf6d73dbf5ba519d1c5979ce2c294fb7ab26146883650e3305f4e73d5d369a6d58debbc0f25c57a0b772a2b2c2b58b420b96829b9bc00000cefbd6fa843fae0b70306a364e017fb603388f48a88333e263d4945b20aebd5d5ea5e2f03bd9e0ee9db007aaca92ad2303c3d4630d5d9e994f429004fbf7bf16c00bd0ef4541f6cce191c141b4c5f2b6aa181cdb305d39f8f80f9fe60f366942298fe6ccd16a6dfd140836703e865a077d3bd56f3d4296918eaa9264c57446262bba155add69248ff61d742039bebaaae8cf4c906af7b459a89557d809b4705e0e9d3b881dd3e1f1180df3e88fb60fa5243d76ab55a3474424260b75aad56dff9f8c4e852a9dbe9bce05eafd7cb852b2a82c1b55aad160038212117dc6ab55a91381f9f12974ab5703a2bb6d7ebf562d98a8a5a6cad56abc56213125ad956abd5b61a6d3e7206f551d952a9de74eaebf57a15d522dbc956ab555b13860a55a1542a5553d9e7bd5e455507457ba56845f5fd57bc68da87b72534710dd753b994c1a6d0d0126acdd07a690961fa2b20ca77abce67d5adbe5b753e98be4a8cef76a94ea74b815deabb54a783e98f5e782eafa2d7cbe55584e95b181d005a42ad172d979610a69fe28223712bce67b55af960fa28a5ad854b713a9c0b8ec471df8acab2bdb6a2d7eb5584e97b2d586cad4d686badd85a2c5b6b13c2f4bb95328cb6d5e6b3ad46db6aa55286de529b4e6fa9d196da529b0ea6bf59efeaab16f57dbdeaab1661fa5596c1ce56156aad5ab55585b2fab9a702d592388e7bcfe3c2240f44e21cc67de45e469f9c0b31f798fbd8957b8ef3607c3d388ff3fef36e0be5bff73efb90e7f2edf8ae1089512ee7ad18a3bd073a920e35ff91365c8938e34522e52c863523fcf06eab70babbbbbbbbbbdbc577a33bb06f5a481f8efadd77366c60c4b3bb7fceeed9f2f5e8d93dfba66a2eacbd83d990276ff8af80192c8b75a84d269a4cf8f2b3bea9a46f87bcad9ae12d23b25463ed339bedb5cf76daa47dad46483a59910ca7fbfa39e3c992f44d87da93be1d9d87e3476d150e78d3a5adb46dbf6d2a77d53c85ef4262b15eabceb47e5cd28f60ed3bfa910eb518afab68b80aa4a0e7386bc2f474e8298831da7b117186eb348cf6cee346b00b16353c094e7ca32a02dfb4695e128eaac5c783cb605a770e5de5aa064d9ee7f8ca77bc47c67309442006c5a0181483b0f62dc4717f0f29b8bfc1d883fb7aabca55dd0006f0ed80c1eee3f2b25cb33ad47e05ec9d567588d33760101f2cee12c418ed7b8838a38b744822699a466fc356be1df376ac87baeb4d9214900c5cab4ae82689960222ca62192c858ab5665f3fabb566302efb79b321ad08ce2a178470f7f53b0278b5fe0a18513db1671cb7e1bccd6d0b127225f9016a61ed250e27c96abb451b1177785bb16ddbc66a93f7f3f3f659b2b4e7c09f57e5dbe15d21127f377b2c5f8fedbb2b44e24c2bd2a1562b0d9ded7afc0946bcdd0ce405978438cebe87149c7dfd4e071d2acb0b901f1da8b0f3b98fdc0d5f1f4472d919ed678d97417ab12e323561b4f92e4d70a3af47fc9efbef721707eec60e5f7400511d0992452b240dc3612599448d33d07e3deaeda1dcdfb114cd69530fe13f892453a9ccfda4399922c1da4fedbf6f47bdd93379138cf8c50ab4cf5a914662eda3f7b995c0285f8feedb7bad1569787442e667b553ecab8023b063608ddee1f46019ac4d3d48dcbd1686ff24cbfd771be6ddac15d9d15788c4dd73df55d0450c36d31cac7ddfd01c1dedbbccf3b457614dd334ad15bfd270419ef148b3a118a3fd0433980a64165e91a6bef62e5c8c46dacffecabd10c7f57b48c1b5c35c6fbd4224e6be1df5fb47cd51ef8feeb60f1273b7871a86b58705712f526a1facbdf61d6b93ab1aa6df56927dd2f70dd65c85036e24168894e443edbb0178158cd841fa3309ff0cec41e2fa3ed430da33c1da67456f83350d076b9f65b0f6346e60f37c2e83614d2b82b5dfc088fddb31af1089fb3a2871a428d56b0d3c810437522cb991a24da529a50c7a7fb4cb36e59614c4ae295558f9f1613061e37b956694deb62ae8e24ba62cec35982fbf08cb7769c206719cc3149f0ebb0dbf28819dad4ed2a7ce69266d4a79ff266a13f7a421ab447b940eec56fb744853347565b6077239143aeb9f3695e837a593bed4efd0e3a97fa2cb3ecefdd3ad2e5a399974e845b07f17e9d063fdf2f2908de9165d3591e0f96d8356bfecae8201073f28a4e21ea69314ee6490eee76fa00f126f2fc1fc82b7597fd69ff3764fed01e2fa344572d16a71f119069e2df04cc1f36734d59f8d67123923b6b4802d2df7b17fcbf730f174210f8a31fece7a7f4fb2f2eebd8b9b49b7c55d79163749bfc42c1e345948449a565151f9c91acda19f0e3d0fc1f5238e5f37996160951b84f60a18447a60ab4df95b543e05767bd963fb1ff2bbe773627befa494ad5691eda4d76095ddeaee26d2f2f6e9d0a3fc70f4d7a760b73af448333189241b880a83099bbb47da903df3649fb01167c742642682bbff31df07b9f2b4f3cacd32f7fbaa43f76e0f12cf1722b1efb80a7844e93b90a6606213cf98af46d78db4a9de3b5b1f63526483432af23ad879709e31961f699309473963930bb68463e21ee4137c44a974676c28d3146eb589aa6eda148162469cd5a61ea72916cfbec23b91c626285b7f1a31b0d957be9abef32205d66152a66e549ccfa10e3d886369d36153231d3a4dc518ff1728b03ffa83e6c95941d87fc88fb589beff6c1269b6f7adbb59ce0a4aecdf0ef22998e54fd6b7437eff9cfe2e4336cf1decee9f9dd5a692fc205e92d27fb63ab4e9536c9a7a6a043bd5695a043bc5c1de30fe4e5453f686a4c2fe3307fb7bdd6a93c43d6df269939473a74df965f2b4c9a505e51130056c14b0c106ead0bf73fc3bc7bfe3660b499bf2f6ddbbf7fe53894823dfb7af9d047b48e97e03b394f2ebe3adb47d2e6df54acf217eb54b5687cea44ddc95d13ff3345be13f89d4b2fe2d43767e2e6ddf4f7fc6d90aefcbd7ddfdd9fd0ebf430fe2acf006cb1dfaa7fc1fa51d137714cca14330d85c03d778a1ac161d8385ceda5a47d0a5a8e853ab3d29d234cede25c6ab43877750072dd18be3bac41407114c7dea6893bf74cbe81aadb583efd795605a64cbd1253b8b5986b26deeeeee9e7d1db174b87d049242479bb2ec4974031d2c69d63fdbb6dfb6eaae4d2184ee6a472cf3abd7d1e8d26f048210a4b0790965dce677a3fbae931d6e22b83390193c9f0333f807f7de7753079e2f7d64231069b4a72a1f47366505968f1261e47fefcd9f20f72a60ae017f3f02f36352ae389c8aa8448d15564550aa19120000001000f314000030140e88442291502c8c5351d63d14000c78984a765e1f0ac33808829431c6200508000001000000010001510007131e162ebc46ecfd76ae778dc01a3fbf3751f47778dcaa5589f54100951aa95ef4fac7887dd8c4a2f2651a356b58d37f8119ebf3922c0cb2a555d1a406d42c07a050f707d4600d0726a1304041cd03e9b1d8881a8ff2d95d48af19513d2bd4352159c43825f683c86dcb88dd6cccb01f7e710ec638e609b8e01252e5e13d2dbd5203c4616527d6d9df59d87315a8578c4cff07133f13b6908a976ebda584c00ce3543ed2708b4ef08111bdf9c2a7b466f3a3e63337b32cc5b2ded0d8b0cc0d9b336ed6958ab33e1ab45e943f271ee1e9ae9f7b909494937a1110fd528a314082131d9a76bdf718486563c9ffa49eafdacfb2e9755074829c25f1d0e9c7b8ba563668bf46b6bf293460b9f90a8656d9494741f3942fb5c707a724efdd306303ac9b546d949c7879ad4d107ab378d0a962c9725e996825e7cc033a26263b1e4b25c6fde747bcd5e436474f1efdd5aad10531a8aaa880abadbd02a35e509b69c5887ec21d6ee7a8f652f100fd64eb3e791e14688f70b14c8106a2eac5469c85cfa2797742614e9c4b1f092904db215f26308cac62473357a18c32d07d4167d5985f79a93f575a671a62128487bbdcfcbc7b104d68ec2f0c17959e42b19bf705d7ddd94861a3bfd6fcab1c2807eb713b5c00e5dd5d903055f1af0cf1c7ac5f75b57b888d6ca83eae56e496ab715f68121b7feab1dfc07c153e1785df985f5fd9a9c9533b441d2b1148290df16bc1433105779bf215d62dc47b123f270175e51e89d1cbccaed7997d56eddbacde8f4a39298a49ce74929f86b0b48467e0dec11066b9c969bbb14c4b7605bfca0f8399e3e409d6e17e48ff0cc08aeb0d808d0974758b92e082ebc890eb09189b218699e9421472205450e591a3ffe91c745c78625bed1d6a683f0dab80a356e040e8521c0f379a8cbae94e752cb280945ae02df90ed39afe62620b421fc55d6023a26d0189f7325d39f23365ee6077d4dab3ce415c112a23c187b901bf5040d4f250b6d1b2b08f43b7225906aee00038f8adfc41930a1cd3ed2d1d0739b7b4e97744ee9f258dc00bda05bb6f7580dc0614420d661a2aee9747398f3ea2efc4e58a8077836aa93aee5371b81cd892c575586a617621578f2313eb4b64b8f57f2b734e4ba0f99280899373729140cf5f645c72adc1379ade1c923a283a5dbbe73ea0aa98f54aeb62b6bcf6cfddbb5c4ccd79a350d47badcc97062942c8a81c3c369735853a43525c3dfb6483bfd6ca85614674913166fc6b626299e9c7be68fd9a7133809bc1d1d6b812a2b9e266a20c1c31a53d4e1b085ec74e9da08f4b98d20dd07ba25bd1747c8ac30ac77c427c279cf5a84c063de77c12ce183cf353f7dea94b20a8af1d0e307d5e94c9162b250650f2fdd7e85ed72553c35c8dcb8821834c7234e0dd2c4650468282d04910d63a188e8e8db08dec06f1103b1b5df140640e0659f07cf87bc71d7c7e806497dc1c12f80a0b98437a71f2cc996950e3f86f316aefb5e0b537527a70a7f08027af1e8af54896f2bd69664d3328fbbe6d88de73694e1d4eaa97515d7104c87070fd2aa0d8a69c127c1f1018173b1876bafc88aaf9477f36af1edcea857762f5683bc83ecd69dfa0d0236841b4428faf9a3d4eecc37364c6c11db51a026a3a63f22411667fac2068de81cae1d86b21797d0e805624ee0fae0eac3511e24ee3228bfc4509f44d0f972888fda0f71b6c319761799a528c981240d91978c5d15547a7cbcdd0c59d2c88bb2d5bb2672d6d29c9815b6236d6acf560d19a4675fe69f94b9acc8b8a80eb348a9b9e143c8243d29d3f7666c72e75de053d9d136c4df712b0e463e27a97d6c3d22aa13cf3ca7d20ab8f59f85323e653fdee30e0d75eb84b22815ecb266186b6511446eb495a6c7c1b594ae8bf15fd4f69c507974fbc109d882aa5ddb3aa84ab0d96d2330da69944c2b1a869301e11db2a9f85e02664b9911f4e3fea185fe82f7be0a4524760939692613504973dd2cbd0a8ba0a0ff3892734c1e9dde991b140a9ef23791fafc10f33dd89c153d286e6019a1c85582f2506c41d65e6a8712894916c844cf08f3c8d911431ccc26420a44d029503c79664a071aa021e5a37537a1fd8ffde6f05a980cc5f5df7563349a4b69987d65cc8aa021a83b2a39b809f35ba4abed57dd018454f0af91a579b5799f66af8cd538aa6d3f8ebf8bc63302c2ce395c8b4f4e65e65ce89e9f1725f62df52fc3065bf03fcae2d2dfd7ebc031552caa22220d24da54871b8fc0669957899ca077b9cd282e755acf1a0fb31e66a78c6985a970c85bbee6f1fc551e230e056dc0fc4e59e026a7a3703b48e7c774f5d2f2eee9195c583311c2091e1712ed5db6eb85dfdf3b69f2ffe560a12642f4ac01a4f9686acbf498b5208ac16b6b4749b63d45222013a3fb45926815a293ef0aca2403f3ad82b69dca4b3bc595fff59306ff20ebfe71b1f1043ebcb7ae9a3e157a96e5188d347a2a82deffc79751b49ea2f81a446f7086998c4161c9c35fcd30e1c8ecc4b2b848b1b231c3bc4fc31e9402f414776c2de4b7388a286c9ca817d12061a0d12c06d0306eeb0cb70def72172cd7ee3d4365ddcb877af4a0986b66df88ee5aa171db95f07eea5b797287bcde6de37a34ef19d5c7623d21920bdef70fd2ed719f259703209972dce640265c3884fd4d8918932f1f3e872b7f19c67f2cf95c7cdf4cfc6b5f0392f6ed9131186640c4f2406cc8f10d5cf6d7d313c5a4ad9bbe9ff491a5d9d87fd86a64209c9fb781352123d53b581b13859fac2194d92e25b7878d980edbfb27d7e8b5f6469211e2801aae77bb7195884311b4bef4277bd816ae1d602c4b2d27408831af3a040c384fb3cfb4c679be2d962334cbf52561492c900816f0714452421dca08bc43fa38d0c261c1b12083f2cbab632873d532d3ffebeb3961ed6021472a15a2aecaa838f5ee82d741aec297998ddc11eaec3c750e93459505c002d2b04c45181a6630c32e8ce7cc4cbf15eff8f90620b1345660c156cce4cf88863d27b051f747afdeecfc7cd4c6ab667c74c41e87ed59ca73baa4e5f76570b334fbb11eb4d30932bdf2e62e646ed8be00907f98dbc40ffc484b82e62ea3491672cd3416e45fb666bd22953c48bc64e2c3e1829b020729309c39ccecb9c7969ba79a75eee4427e8755e0d32378d6a72b04f43028aa742f4404ab09f2b682fe8b31375abd6bc2082082d5398bdaaac9dd4684d40d1fb579c2801872657468c1b87268b45fc8f0624a1ae7c5ff098d7e9e96a3892df2d1104b1661f0be40dc31839700df8d6bfe12339094a81b43cd5cde838c03749465007e5bd0f44695c2308d985c9262be3b2733b1d60a05bb86bd634f13133eca82437a1081023da4282d36940d200402a22fb1593839fc8526f145b1873862b5cc52f0b5c5a30959029baa3c651403a56bf7bed6b2d67d17b1332e179960caf0f5b2c52ad205788065565cfdabaf6e4080090f8ce22c0879d8b35705d2a7a51d85435c7a82601699ef71ca826f4aa65a9bec42744990fed4956b2bb056c16f4282588ed93fff462db4b3caa7eca69088456562446925aa8b5e10320889ea955ce66a581928540419499fe019d540c6974b8587d865e654c0b965880893b510b0955be690a92a0a29cd20325361b81ba70d96fc379007d50f62fc9da6169da0dbcff601887c32b6c88726474c6fd76c752484cb7d2b3b882d221b17b2ec37639818930f124575cf264e19f1d7ced71d8566b8cb81a997bb8bcad4e615bc38c7c0ce9f9333c160979aa3cd07eb2b582032bc0f89b4dc06ccefaee0d13ea8d0f2a861584158b2b55d4be747308fb827af16780d3210460250a57fa78fa476892dcd1dccd05ae23d087b65cd83b21ca5a9ae70bc20fe6e3357084b25f28c7f76f3b0609bc34c726fffd49167a405a006a6b791c373e780c813810233202f41a357370739d790018338bfc6448fcd324314dcbe70477d05ff647f67c17b99e294e1448130fbb6596c0198102a9975f74ff3ef87c8127c379b4728f77277b05947aa5332b996f454c04278e6324002babbb2939f0a90a7f3c6152ccd2c30015eb00e8822308173586d90d9df08b8f36b90867fcd0f482cff29cac9b10e625581fcb89782550e20b2179baf39e4aa8e80de23de6df8ef8eab8708bd23917548cb78cd512935b1646b0cc2863a597cc488a036a419ffb71c914ae776c60229e1b867ce24ac52e71100f96a2f5255239e0a81a91e189ac359eec77991e660631a58028774606336009f1a66fb30bd4108b446804bc7a080be80aad446986dafcd91a60ffb9b26b9f0c46ce444d7520d2b4195f874b0dec6211531c8268509a99ca049b44429f47d0cc7a69b07a2b5a5acecfd5d35c85728e3f6484de11e52679468328b39f27da71e1f7bb9fec356a4e2499e7d288adc6a506a081f0231c7ca84ff62b618c46cb8622362151cc1c154bb6c8650db7359d04c4b50ccf0bf1daa9a41e7dd7fe0c10490b283a806264618dcf4fae3a491ad7350cb115f06b0a59c1f14a97d95d0440845b62ed9a6f604b7d9529676c6ee3741f407241f710f994cc87c341cfa0ac344120e80ead9f0a95fd52b294c0daec59bc24acd3c86a45cd07173d075e4747bfb54131eef9740ce5c39d39c389f64eb27a8afcb1dca3a4f19101cc2e08c19e3f106146553d5a37e9868165e0a0da6c6777d343039fa586a361e1d40817b58e49cb42da61d367127b6e086dc4077415a147ed8306282b6b5dd7a10987bc19292a8e4f42bac01747de553098c9526b8ccc055aa3907c0b2e3a93b226fb255443449c443bbb33a56e8a8ea8efbeaad15166747def67006188edf277c5d7d230706f882b92a8e660d1359e9432912197f33f8f1b9b73407f72ef776815c256ced8a30812c8a78d71e5aaa1ef22ec538b8c53061d6f43591b703312e7ffd05ca25796e436180d78371b730d89994a4ba407d0db6e816d1057f4f8bff090f0b52e18363cfe93b9d028ccc1e0357d2135a3ea09746520df6a8cc38b896f35960fd7d3b775427378588032efa1c47bbf624763d4478ec28cbec600b9bcc4afa0a5f3b78646ce8b5cb1e5edf4193b8c609d9931099de9c4276005ec820fa5dba4b0287dd1ab5de9f1ba2adc8b80ddef73ef20649aac23faaa17f355b689c943d466c2e1327d963308dc5cac734a6b5540b152ff3dea7b72d5dcd3782c24cd720cb33b6e4842cdca79e843e2f6952ede7b80ee523dfb581edc43b4ca727acd821de7d15ca7d262e812e33700e457af396fdb808af10692cef0c7c95a4c6d6b2b2fd6fc88c1c17b87b5e226d7159102eef4297051aa56b796e9aaca57488cb044d968846c78a166e2304b8cfe22cb05a506a1410caad4daeb866784676630351128246c012678c09a50a7105cfe22e6d27319f4bad41e1577c441afdf9712465bc9561a37e97a58fdc938088b4694f4026484dbce640dd934c155338c564b32f1c0966889512c10e3b6db9e9d01823bd2e43c7e766642ed9b51042417d149f9ff1b5913dafaaf8a8f15ba9a00d1c4a1babdda522b883d3c86ed5a293a1aee7a3386de37e5c17e139b8363410f2d4138719d530f9735bb14445de679688af75a377e6a441beff5c0d67ebc4f989be5023852d8f5d4ed477870b401d54c4af296b7cecd449a2769aa04dfc89939598d90bb280294c0bcc667878a2fcbf3923c0f2de0fae2a14fbf6b99fc53cc10b3ccb920288992dee330e22e4d12f344386716f0aedd58d79167e02155c66396f07d9607a0ca22f48ed8799dc8125d912db0b2beb4254cf6063c337568ce54fd2ed034e114293ccf562ea4cd0219905c9de74505fe0985e67f3ceaa260c84003509138d522985bdd11e43204c0d130a3221f9a0ad70c9339df585c0632816bc75e62d4ce0d5be6c152822602af4873750caeca0abfdc3d76058dba1686df11027295ea88073efc91d3e4ed9dcf805ccd6eaa6b8596129c09c99991b415d31f7afb298ac961dae38db948cbb2e723b79caca33de16d41ee7080058780533e1b514ac2aa753e261ba04bbc1da88b490e99a170698c9bc0004f66cb54135da05c28d3252c4633e040e3229209dc451cb79cb51c5c9f8f7d3462ce20193f15597a6826ebfe804900bb5a0b4564cc08381afff0ffd9be6111de6fd07641e299be12b9e5228caf2c1d67e07065d350568870e46dc8a9887be4818562db26ce74f1ed169f4a1d5a4bd9a8a892e8c79b2538ccf0b3284d70c83af316f75681aa580ebd1170ebae87884b457267675be453e442538f2056134693a74de8003745040afc0182ecc655237ac8159d0ff0eff5ac319bd8a69a9e63041d805bf4c9229729ba02d9a7200cde8fcd9f4900bea5ae26a4c5607d3584b8e73b805dcbac088c8986e00a630060ad06a66846d5de2c1b9406d0bc611905bbedafd2f931b7eb8e0709f3ba54588f2c3bba8db9191b87b0d6dc60d726af42c696954b445deb60f81354da53993943e5d00bf4b71b005585244c1ae4aff2da446fc18545903ce558466be1b9cd42d21de098050e08dc2b44a1e0d4e857b672532e99b66dee00010b060747cc5e1249acfc8d632158c4aafcd531e2c624d6df5a69ed6dcd567106e149e7ab27ac658e22f59044b095c952063422ee54f36e9d7c7b361773ef88a319cabb7701d11f7033e1ffe4bb2ec1f3587fb7adff26a085b7eef976a40cc39c51a887851ade541af6298b309bc78a417540a81b1d56ff7f9020a22c9bcaee885addf167e0c6b3b1e8e4dc2dc0dd5897069ec8bb690adde5b2bbeb0bb73a2e1932dbdb642b922ba0b073637ef885896bcb4ef7a4b648fc925ff5b0eaa378a3b1f5305c0679d8d4c6640306a13acd98f7462b2b2f72eb5ee65f95ebf3b3dce4a059d8b62bcbba53bedfc978a90d62dee9d91a1e19dd67f8261a19963e1274e6247950223f76f7f9eca3bdec15ce0425f55d59c6ef9e5626abc010d0bc554dd95392843586429412c572f65f27846cf0bc31f9f830895fa4785cd29825f729bdf89f9d472bbf24643c2a6fd4a5df13c8f08600b8da0cb0ee043ff35f6c18509640dd1230285f96df59eba61238df3e63ffba9a0df363dc61350b8954588f1486b638054ef53e00ff8d720b055150b3417f2ade2c9d7cfa7d8e8b7cc1439645fe5b94b5ecc121814b6fe50d2ec1697de87dffd315d4cec1125998b2b2b3b01607841920a08e174e3c0192fa0a7d015326de9b5a136ab3f066c086cdecc2a8f3b3fc2ce9678f5c18740db05d39e8174dc929536b8ecd4413266f8c4d9e1f2385034236704cfbb3a27b87a7ca6fefaa8cd09c698f1d0bb22eb7d5e323434ee546dfbbc1346aa3562abf24f9de22d5f860b8ffdbb37e11099027b65803bf22c4b3ee9f6dafdbd93e6ac866d9922b9cf5bc8fb8175dd3dee5eeb3f2eaee5f7175ff5d71bbfbae7475ff57baba7d57b6ddbc2b55dd74daedafeebe2b6ef7df155777ff4a57f7ef4ab7db77e5abdbbf92d59d7765eda67ed78b61f7cbbdcbace213704a08980cef696aa7183dfbb4d003d9e73fadf1b06cd7b87da1c2b82661b94232dd246633c11f081e7731854ccf71f08a7f7a75c532a777da20f174e2c26a27b41a4ea58e1aad66bc5beae445ad5ba7452c418b5da6a847a056df5578900356eaeb932be1bd081625bd7414aa3207a664cf4e86b54b0af93c227b2629868dff78069e95fd1f4c3fdd0105820e8b4f6a1d76d9b0f0837cc78b0267523e740713776e2639d1735164d162d6d3ed9343b983e04d1aab2cff955fe2e2bea54a2894831e82a468f27cb8d494af41e0902d989bda8325b12b97e1997d3bcd4b9b6e83c25f86d0475297b385046ab10c3e51a1d0681ca05f199d541b5ce36784f0c6724c2b2ac3f345c2ef89b85ca4268bd06d9b509a56c830a3b4238bedad563a4b388bcbc93e011236de7715d3e30fa399b214e8628de30f3e1a3d1a49af95dfe09d2b3b3cce66d3963a983ea8284180fca11999aec6d38d980977d166fc13199f5e0fa9816a68820e35201e2fa0d4604e6450a04ed197c59c45b9157392f120b0eae181753b3d0cdf2cd989c749af2494e5f7642611b8d07fbe9525c15036d38a3be775784d4b1ebf335cc3de3a78cb39756309388b1239595d46ed88e4603e9ae3e6290242a5ddc290cd7577d546da1acedf9087472a57c45c372c952e3e558e379530a4f76234d9b736fe9be6a0c1593095245db2c059308e5a674b2ab9146fba6aa5eacd3675be25420e5308f4b3ad650409b31ade7d9355e074ccd013f4334f288e2102772bdfee3d10c174abc3aaadbedbd9517fdaf17e6d4674babce9c0d5605408b2d4dae71ff7be0bde4ebbadd938421dd355c25a1f4281ecc31ba2aa6c8339ec6bbdbdcbd426931f64717e157fcae5032af1087e71157a1c1baeeccda469f78a0e5f74cd59730f40e4823bb70fba8217ed36108cfa2e9e288ad39e16c58555397285a6d1d2dac6dcc4c959c7a982376598348a99004202fa130d5cbf47e3ebee8d30362fec15e1720a161aceee6938db95a3721d0d63f52e8bdb766200dc13c72b950d5ee56e27de36796e97edf082fea537b52354b3cce15468736c5cb197491f98908a78d12e206f66c1a1ac87e1af09905e442e0392bc0c6c628923ce54850ba4e0833a20457ead1055effeface2c913cc12eb605eda9c070a0c4637324eaee356de4a47020b38168d1bf50b38244d536d0aefab3bea492d7cd988efb86180ac272829f94ec08089cd980fe398ba7aef9d51484be89b2b7d523e8f05f0f8666f5607463d920e8fbb8f5b87977027e45dc6b4eea7de42676bfe1b9758a9aa1b6d5268642df381154a764f5cb3ed9388f0bac365b0088f644fd06701a3b058c0d45b17eba705b885e0f99750b2b58af1654690ff4d618d078dab19851d8d0a3e04be486b126533d97485716cd455123a3277150c61a4b6ce816fec2b2ca41007eea52fcc520949a6bdbc140b012fa1866e8d63c09d386e3886b394be52f0a80b54c0b4065a8e16041566444877b4c9a1e5e5456ba17496aa4131f0aff9366618922337eeb11a6775e9b67d4a9ab30054db88444a5eed3e5173c5a701d7525b0e19da1f9ba15e5dbb33e22ee7aba9648c3e202be9d373778dea8170c2d54a05c09a099f97719ce4b6b11b62480819830bac3d71a376deb5047f77f6d6c06f1b16087ba876efec0e7fea1e51cdb6cfd506cb00e62187832150a7e8271f3a0d549778502706401025a2b1476c22dc0ee82000f6bc085a841a23c3b47d50779bbdabf2e55003dcb70de2dbc6a07f08affeeeb4623ca39c040882e7c3533a49e102e0205817a00ef691f8f0b3b11b46b950977617adaf49d0a6053d30c91fa0560e30dff3532bfc71633b84643a2897e35f20c9c0527181963589e8fc39b8577ba33a800275028225ddf716a7d025f034c0b07dace09fd6a30eb3bd86277aa3aa2fc96ed6b7e1cdbc3bcfc34b0b1a554911de819ea81c6fc3afa2bd3c5ee281cf5443ebd931203a00516d06ba95ec1fe9ef2b89fc0da8f7cab803e921e856f22e815d213f96601bd487a0bdf88a09ba437807bb9d3cbcd7ae593db47dc28441759af829b48740beb15715b884e643d05b722d14dd633ef4684f51ab97ae1aa99ffc9852129d62855975086c7210a926a1e8f5575d0c7a0e3537c5d379e4c8fa28d8c12628b819b5c937ae7ad501b591e3a2f54529334a86cf837e8593ad1064ec1688849bfc1f9fe1bcf5024209d6f2beab20e19539084e80a1fa95c443f05aef8939d761616f3d71865ab892dd93d6c8fe5d464195f379b7569a2b4f60293455284b3010b0d8c4c7fe4d509a97f947c53879d297d85194d9d67a47a2f615fc52a179a49b3fb4cc23f9d794cc059611d5411848a4350b538fd8da67f5a1e9ed4808d1838021ad88636850e8aa20355027be0c5c98ae86c2ee699b8cf6cae0354c3f5fa423590bea300918146361fd82442e00b93a758fb0ad69465733183228ea964ead9c4d8a13a283db1d3eba7929d103144997394fc0a721a2a6edeebc2b288e6aa1539a2d8f6429dac95bb38b77968e6834a286040d42e3f618c1bca98c3adb2d69e28dc4e9dc1badb4296f189f691d0be56c694979b22b3c230c9f897fb20e31377d85703a50ec85a9d9149ca822c73491cc10811e7358fbaf07eb6a154d490d38604dd1ba2eb2e7a1865646c512303b1f0305152fe4a41ab467fae0abc0aa1744cb29d1de03328f0e4751f9d47b26974a39cc1de5d4935adc7da1c459ab3ffbe61ebf518dbd8684efa41b9828b9c68d6e5e83af8cf85aaa086391305b03ace5891b8ee3cadca9b87c1b41deb485bb596f55658656d2bacb2b6352b592daba2def98b6e582632cc28e3993295714619cb3c13c984d5cc839086fb9c11463d9cb6375f9afd97ae3f7c71b540974ab5c117f125beacc4265a93bf7c02041253606336547a9a54b4cd70f50a4e2178d1251c510baba164f1418470b3971873a439c2f8a5867ead0baaea13bd05dc6d45989737c1e19852f3a9844e95ec1ffb6189c5022f36ced8ecd1abe4447ffaacfa0fe15458e032bdf057694631fe94910f9fa339f22861c893b040d0ff6bebf736c51ba4bda8b5c62e97f1caea34d604d6a4419bf037d9c1b2196e854ca28899a6e286c1b03e507026d256396c472497136d3c738702fb33f70b4d62dba134b6d95b75185da8ab25ec0f91e8c86aec966c7c17b870c2f583304dfae429b2403fb059bce4c3dfca47972bf231f1174cf5ced3b4895988b5ef42f75dabf62584017fe0747e76b67e9e27534241c04f73b8251470fffc94fd7af2fdaa13594241e6a73d33436c2f4e2a23029e818adf8f19b3f2ffeb22690905223f3e9f9f3ca39fe4214a2860fd734f5c0905999f3cc11f9eb4dfddd99750b0f2ebcf430905af5f9ecddf9d85dff3c8945020fe51777cf859b9cc934e1774807541775fde20972019564ac85bfdf622fc8d9dfde9b75042b5ebefb5d24bc80bfeaa02fcc1a6ffddeebe84eab5dfae3e4ac87bfd4669feddb15ce02c218c7336ecfe9d1c1bf5f5b8ac884c440fa5a2a451b4c2bd957d45ff49e18ef3e0e0c339306304675342efb2e567ab65a780c58a4ac8c3033edbd743879afcde21a881f5d920d8fd466876ae1a7edab57fb1f04290428d36175a50c554cdd4b55e554a2c21915c8596b74e9ac8e225ae5ce0dedc0ed271542f9cee7f42d869edab194ce196c4cac89e2211debb24f94169ddeeaba4731f92577e209cfd73b13e52892d40472c0d158b45066e461730f9d1e487b20a2c582163590684228fee87ac271823028a342e2a714d266242a0a60e3f22235ca0302c03b456433af4a1eb79b4809dc32674ef6f516faf4a917920bb931931adade54c096d3c086394a448fe095593eab6c37774e92544981fc70f6d4df82a5d1507c37c4bfc544608217409a80397ca1f2134c791a901731b6a39fcdd337a1054c83ad97be8b04a24bf983ff0fda93aec1d0aed35d8eb410cb2c7b6c211424c2910b99dc7b097b45c30017307c5b36901348c7ff15cceb14212c01d582b84f547fe4be28448664b9a63d14a5850a344bc0e39ecb5a190107a37945088ac11a510d1c664aeff0f8a929986fbd690f45d83eb0ffcb8a371e3fa14e449bde841a241dad3f5b70e59f30e46de40840179a3d6505d31c7ed5dd5db7f42f3a584c078f8e647ca285353fd5105593b48790dffb8fddb2eac1ccb47a9fa4f5d9958a7b8e4c15d896b2115cc60ba11e4739e43d90c019fdc642064c5af93fc2f9bdd4d2fe3bd366329d3379bb4a4089c783b641acfddfdd82e68342d891523ddf956c6af11c4c38aa824620cf21fcd0864326047a63183ede239354ffa8fe1bc56578ab8552adcd75619a325f1fe4c8eb37c04ff12e60071f40a6512f5c765ce68fd30520eab78949fb26adba11e92c0be70b39ce217f760a3e8de40d87f8e45c79fbe289190038ffc0c82ab30d71cf44431aabc8afa32a8c1dd6ea9241f5ac7a37d81dbd5a14713ad43e7d7311ce55a2ecf013db806c0928401344c5348a63a5edf5c767e009ff19e516d8c2b0ea3cdd3bdfe75b6e28a3d1528df817fe184c9185ddb7ddc6ceff64891f796ccc834a02eeb84197f3281e056257396e2e2fc6ddf7a49416ec0fc886f8af6fa5e501119deb9ac2172df70cde43eb1aec6b39bc587418567679c2068e24442b82078318542f74669d7b08a259539aa63d55be5424f13a5476a956b080d708350924764b5034ab70555e55d9b92fc53b6b35f92563624c8760ba9b2ab46d86066f991cf3b17fd9b05e7c68cccbfc2ee9dc238c510fe79d6f426cd9fc1674e3cd790ba0adfb1a439550b57f19f4bf0e43a561a33e4bc28bba6766939ec79b96e5d98e43f89ee3a5d26676782de95b6aa9056af8f00b55add6546d6e065f711847478577a475555cca5a1462527daf69dd86a116f4b3eb8fe9a18355870602502f25d194dcf063110b583edc081f4f3d1d9c175e4e537d7a210c6f93659fdb24a25368d33e476d985a740a55eff3e6505c30519fc861ff0697193436cdd7fa8fa8f0c18f2af2b608de141f65b01d4198f0da6d61439bbc6cea73a108746a2a6ac7685a16bd3c181db6bcac5579b98c808546dab4cc90fdfbb2c445d6d8bf182c8141401d098b02c47e62b53f97bd9fe541c571c06f22db58c0c68b5602b110d660d9810740289896c17bccf920df37e1fec3553a68a0c57d69c8ccf34461fc4bc91960a945e0e50ab29f5cc34392c3908668cf2949ad690b793610d41471a00be632c817c8900bf6aea7d6d57ad3d0333377b281d805f17cb9ebba1ccc93e48f00b12787bcad954599b14b5fe8b72fe54ec9d9614b4175e44d530673f972ca17b009db380b382bc26e25371ce7ad553b8943fddf1cda9613eee4ea92e45a7911b8df23b3afeb4a27755c0f76f409903ba1495bb14125394c4bbcde68fa29481e0d619ddf29aed6520869550841b0c596104aa809d0ed701a52baf14296a1420b1669ce01a571a1e4282c8f039c5d46ef9cab468d1fe9f4ab483cf73f1c7002c5ee5300b9d967c9623ec1e2233d79bc2fe17d0f73268f7b2efe8c39497b22c55c41a71ccdbcd87bb1fef1505d50781f95966ecbe5f9f26e895b6d952f0925a9ffa9c968e1d4edc8994388bd6a8f5731c339eb44e29d985e127764345952e985e23a6f374352a2fd7134faa96cd541a1a508fa6b023b78b9e056aedca5f46320a913112980471de7e0338d3148a0262ae7a7a29015c6b7fe947f4ab2a0a2476c2bd9310fe812de304af77a1f67b1be288bd0bba127288fa2bbcd3cc7536ebb290588000235f5e9ae61dd2da4836355c0980717c79a5bbebe188ca5e546f5c43f350499f5dab40f2681ea086a50de91240d2a29e9cb02b8be510057c8ef57fd42a97a7e56ac98f6e06fb1904ae32ee815b1551090f40658d6c432bed57546a19e38182fceb653a13aa7582a2730e287d94dea4f9288327a3a0a1c12ed4f4138054f51bbcdeb950d4d4d270f1477ea3d412b375c01c53f8616e88671476c363ea461c7cfb499a13766420c129e2a85ad5bc705f1be190b7b6f6b48cf74a2ca8bdd879cf4035fdb470835b4e70e1225dd9e879b7e399d51da32003ce81d0b00a2cc0d1602ef110eab711867eff73f41006d15534a037a5442232c87f5e11c8572c59b6f35fa5bb39b1d7148ce71f84677e4776c3b2106db591e951143ec2cad498282e8e74de54162aefccdf038a69c4fbd18dcbe38d58f15a0de06b84eb2da31cb7671c1c6034a4ecc7e04d4ac23f33b0910781531a9428cd44ef091f21e1fa72d3d4b62fd9ed9e6efaa09884fdf4e6a84721bb9b4ea33b6aa3693115659c33751decdbff545515ae67c05f4669fcaf25b920ad32bf3baca712e9d1906ddd41871e7092e040c54ccb6684e6f00b2b890b560eb4b9e3eda0e362e8bd8d8a87a88333f03b9f63c7d66190a38b6cc6508eae2c9fd8ef9d640762f8f24b3647eb1fac1f5a628feebcab59190767acbec9b34322ec37f325ee1279229a4584877d4704d967a8b897a210aa9a38cbe89993998aca7b31eab6929b361a8d3083686cd8267a89c8b5189250bd578b7d99a23f7a9f97551c19f175183bf349e42809999937a9a1bde3edc67fc88534b31dad837a1dd5d1f3265c21b3ef3366b8b68294f55db5462d64becc065caf4c385d1b9bc856f6789be68d7d2d40c7155620ed40d57629a8716ece260b08875c7fcb90f14038298f5e9a743eb69b730c6d1d648107293a6a32e43d5103ec040135a367b74a76287d284e439e4f17fc3924bb9f2f745bcfa1f27741c07de4e926905215966429eafb5b3de44aafd3917afd04e971697f16d3a6dc19cc0cf98d21ae00320c9139299287a37955afa7d060e273d8dedabffc04d83c2879fce0229d0a6a28bc809051da198118d26558d7821c2af465550429a1dbc75f899ea0e0cc9cd714a73fbc86c8d3527c7894e14ee1c34bf6bdb6be9b281aa8fee1a6adb29a8e002d97ac84fce063f90cdc084d99e3cebc18d3ec37705f9dc738d05c36b4074f8146ccafe48eb661a31d61079e32c9876fea271d93cc12bec6b2a9fd5f1172706cc66d24ba0f6ac9ad4484a1f3862eb91c2036edac8855f845348309a356dbd1d6e65ba77334c764dcef54ef2307ba6e1e7dcca1175865528c21813134cbfbf3e58b9608e7ed810fec92ed96075cef555defd07b3c199b900686df425d32614ee03aeb8bcd976c78f638f259024a3bdeb96026a33dec93c17a30efd78787d3dc62783010a4ac43f4eddfd3a7ee58fbcbe60b0c55344ac8298bf148ab5cd06ae82672902529ceb0b4e2c6997649331d92705c0be368c08396a54eb2b6e62b2c46aa9694964db751fd1a4fd2172624a7cc5e117f76c32fa1a62faa25a550b953a7e67df57a9b4f65809b21457012a6a8ed6eb89125ef47da878135f2a1b1f3ac6691665728e158dd94230b31b7f118250ae235f871ed7f8868188e37629c8a8f93034d91abf26d5788fc8a22c91dc0e2ab829d800b0915da43bfb512956bed8cb34191acfa4d68c2ef7543a6ab19beef1082fd606924a58f16a2a9f0106c39c903e1bf4c521f85aad9e6af7f0749514a7da18729a52694ffdf391da3594d61dd1979a25616bc3b24e9a64a95954ecc03ac8a66f00e1279cd29970061c66b99bbcc449b1694c32d45f7e32d1dceb8d7f520445a1c25e28ec577ff83ef0c99871cc18d948b1789bf534012fd1a27458ae0892b1c8cb2ae06abe28e94f74e133585947c57abc25072173e7990612151ca123d854fd42cd3e0719491371cb5255396805a83079dc41dbc280e1c3080ed8f886fcb323c0c3befa15227142a24c466e458085f5a97328fd89a3bf70b2f0795d57bde9cba34cc5ccbd4aa31181b862842627c6cf9eb3e22b8b6f99584517e1a0912de8b2013adc46aee57483f5b85cfdd5931aac32240378eca54fd29951031c46dc3fb84f4778d5f2e06c0fae481b2ebdf9e82d710cbf9f11c35153dfde31317aaa07af4b7a677d0c6f6508c01ad907612c8df81d21fc74989726a13acc24f0019bb412f81d15bf8dddf17d58f8371a2a32ec60fa10055b9f7f943b63398d08459da2070294770b328efbe2ff0035b0b36c84b176c54f7a7fa333a17349ddba2e28ba5be27d29569d9c3c22b599873939a193891f59ce45d632e820ed9be51c97af46d8b8134b7f3979b87f448abb981e56e3ea187d69556a4e58780bb30c435c01b2b2286f7a0d7008b7f3854fc587459a9ea3806b394e194bee3fc4223893cbd8a328d79845aeadedb4cfec415c6a682c1f6e07c7e94fed20f396414544e2c0a6aa9d41552d1d9b3920b9ab41ffae4e17a97a8010989a3149c67bd2cdf55428ae8d135efb49e7350d1381a4fe65a6998efd4f0af86e49e3b7fbf178582c1e8c8fc480ee630850944aee2c0021d12829d0830970b9a95a7f2c2aa616db962dc75f0ef0dbe8f8a8ff5bfb929d5f443f5624afdc0b945ebb1038c1a8c71f1ede7ec009f5cb54e3b7c52b4ed25530b436c71a95e86c3a5207ab3b0f2af3c1bcf8670ec29b6bae89dc5e4d6a97edca3e1dd8b06acaf0aece863cb426cffc41cbf02dcd16960ae97a6a50174aee4ecc5387b097cd739ee37062f3558d1433a9d3c4876096435c26e79f5ad1eb4b0c827a9c152956a80a3b0d1468ae63d503d069e5259ff799789dc285bef19c24d3e6ab0506584be0ac9846a87913acc21e023b3346a2419787f14fad1b400bc9c7742031000291f9a0d6dc8acbd0653bbdb6b16616466e88fe1de0070179dd852ffc9cf4a0e95837c3354a898148ac20a3d650ae9db1a0a59c2cdafdcb583c19e038abafd5308cb26fd58af42801b21bbba0862028aa2497a670a693eeaae5f3eb85e2ad81f5abe110fea073a255735ad4cf5fabc880e6c5ca8e99ab7730661ed0930cff057db39bee3b3579ad62ba72991010f07781b9c7c6a517e7426257b4caa2982a2ab9199ff5068fc48060d45eb27f40c3438d543c3ace01fa041287a18a619819d31a356b3d5d6195b5d01fe615902eb421d1bb1c71676e01712d8833aae320a0d8823c0d7d661c60297b64501e6a1275de9f2680fe77e223f5cbe609bdc019f826012da4bfd6b05bb2a131c63b883bfec81cbe23c6bbc853238bcdf77a6c4b018cc849cb4241c40aae2c439fa31e819834a7c56e733c087d279c9ce9c83baef9d518b32cea75e2f457efe81bf9fe02e372d45aab35e80f6f17e52d70577f7d35d749f74962110eb01cbfbbab444f0d7836524cc609fcc022f1a301e995e44031d4f195b84ebe6faef584cb9bad61a85cdfeb5253aa3930856bba5fc27eceb5658880a93cc35f81727e740aa128971771ccc64bd8071cfe65025a05121432b4c6060ad7034b61f1be3cc1acca3529b15275103eb33cb4dc99c8db3a86babd56a5e9ee0b9f4543dfc8e42b1207a2873e06d5d125154091aa595b6a0732cea38469c28d2423c73e8ad2c9c0b740aa0259009bb8387ba9417b0e5e49b29c4c6105596e1d2ddb2e37775686666d09cf630057eb1a8fd2ee80cd91c47d85c772915a86e0c6cb1969e3f2ce4455afc8a2ef8c2506916e8b888919bffbf9288d5b45e746134093098069663278622b1e42f17f98a063b5d0b8a1b5f205e4a7628666c07214937f0af9e0d9a86a98c113fe8583d9878b6247dd31f72c889f77a61a64393ae9f56398a667cb958e64ba59e190f901bf102fd79693367d8caceeb7238e4fe57e4f88508b67268750c856ae53c1202b0992e526b83423fb88a25707e729f604f8fda3cec651c4bbef4f6674b2754b6280913ee0d8ea26d4e79a331ec73d88912253fe7324bb77c59259ce7865b6d11c503291944b405d9233e9f6c57c2d7aeab6b4df9bf48d8628541120eff36c246894da0be3a3cd0ea00ff58910b49ca715c97e0cbbb131ba718bc6fc6e8149a1bd8886f048a41d61039b94526104d1e2bca32d0f2e4095b2de1695b4f9b4ea1a221ff80794f8f7c64e3ad420c44ad527a2bfc072bcc83168ac6416f2c5a7d4f3d11bb644bdde523e54feabee3688683c1be9c2333be8711e6136608a2f1e4c2e5c5b1c2cc80b3b0d111fc1921d828a196fd2df2d0b8c2c5a2e272e7b074f20c4a6015ab8000f8cf5e5e5285842dd001eb7c9132e4ae10f7b81fdc62eab2c731c3610e3ed29601531c58aaff8f85fd71df491970805b2723a36a966a047c27e1df10ec820700c48766eb4555408da69009bb946a98e44422024e8696f856e4d8aab374ea65f9ad3e82e00e3d5b549cc5993992f8788117abcf9a433f7601f97a0dac4b3440b90574b9c8de9365b77e7d3478c34edb81d6b4eb34b90907a31428415d932c5df717dc6905e3456680e8adcc1e8cb012320b210ce589692be72db18e24fb16dd7f4dc649352b2da79118392f5e2df25cb8a9046b803cc96c3145b38ccb784e4aa6f1a82805d0df2bf2af94447c12a6585e04c695efa21e2581d24e0d98bee684d314f2e06c3636e98fd90758e69bf852b550ca39d7bf8d4997238b6c022db6453507f00f0d92cae5059dcf301b4a8dbc8e4ce31b08bd63e0539010d2e5d1c55a34bfd252f9c83de6dfe823546b8be01be6e4ace2a8875da6107074e58e522c3e2f8d16c556aa1b6cf2b80757e44c1003dd6fea80eb13c98ebfe3c4f55ead7839ee8b1d0e683a133e8f52c70fe25b0be600f54a094a81601049f1b3b1f316cc42b5e9f6e82cdace0956e8ff9b08eac14d88e46e02e96cab0b2cb21fb8572d77748e9f35cab2c6b1151c797335090e9f56dc43a9827e148ad4c0d5b45bbdac023d027141fc10fafd864a9b62b424ea1cb7cc1b668759cee599b9b43ebdf48723cda1b55a85a3706a4f291313cf22b9c38f6488016e8eeaf7889f2caff51d86a029c7bb5287fe2306d2e02b4ac3b6169dd303d767720f658e93e72089db5c971d58fa2e27b661f5c091456cb90481bc8a3922734bf7eed769a8e1a25d916fb55c434cebf1a4c59924425b33c0bfa310bcdb987f9788473fec1c4b04aa865728b931b69222073824a14c100ed89c28364ca635941bc5a5bdd8a20d3387e631c4ae30d99d0c4c2715eb3510d03078572d6b9fc9d39249c83fa7ed4f3404997cddb4d3fc01b45d05d4ab88772dd0b5a2fc20b69838515fa09900f6f905a788c7f70c54d1fdebebcec163eb3ac9848150b003c340a2016a62c83375bd855bd6a234384db59480b07109a9e492219695400ed02fa319d98eee8e5944dfb438f25e1728f08b896a52276ba92d1ab897450db0bd342a65df5e936c434e19684246e64dd30a49bf503d90f895a53218dc99b66520637f32ca1e81741d864ffd837b55a0fc4b0081a43433be1f86edc676ad70844026130d766a5c41c94f7b5a763f3fed4440bec61a031eadc125fc44f19a728c6b246ddaa6812309183a54827f6619210229ef73ee8ec1e3e43a644ccbdc219ad4fce0e577830311b5d64e16ba2df96089f6e4f5b1957d829cd90432558b20ad538b03bf1232b426443da65da61f9e943e95f7719dfc674dc9529a8b4eda0a8d15a95f4e5929922084d8a64f0e76e790fbd85dfcc9d8c3276bb60ed9435b52f5be9334b060d23fcd55ccf111cee78868d6fc3327d891f13c34e69b408b9ee4489a1d11cfdbb709280277a12d5bddad8e7e1d744120c47d0b3dac9b20bb237e869ed35df5fade30beb61fba29dd43679d78eb79aa6832b10a9f0ff37ca76b62f862ad3f202cdcf61bd8aa9429af8aefb7f9b33f27a07cc0023b673e163e87ab894c81f9382cdbbb27d5504702e413531e526c6030260e13a45389fb083b8b3322a933beae339b28136ca6a818658b1c408175924706d5ad47ba3d72a9cd775fade5855af91063ce482d41bb5000a4df9f3805ab8b32bce9e96c237f9952851ce0139f46167925cd119bc9dac716c43e5d401c8ad8facbc5b896e11e0d2b27ec9c0c8832e211083bd8c359e574cb830430bfdf510ba0aadb3b88351a1a96f758103f019c432fc55beb883b44da7a80aa63fbbb95fd5959779707451ddba06852a14945469a86eca8dc82e00be451777a2128e0acbf19f087b93cfe68451ef041512562a35d0b2d0f9b4fb62d223d94272150689610039c320f64eff4b4c60d3376a5d6cf77e7e3d91553c198075893eb8133d44375077497363f14bf8cd1c09b98f1888ce654235bdcac830b03ddc57f560344eb3c802130fcc70a18b9da61b727ee31bfb379257fa1cfd51eb878e0d54e3aabed595f4261712ec460dffcc56238185a686f95062758b621c4085a923f7518f1e49d508de6113e5c37898230db1100a948b905253cb07706d0fb6ddd4061a40cc60b69ee01cddd2952f04d0b97dc24ee20d1467d32dd20b4863e3283a66c80c8a4ee0df07606429914801836d36daa145009519798ae5de4ea109886016a4b16f45cb997cbc306bda313752f66dfc4d3dd6ac8cd5b799a2ae8f87d4912cf02c3da68187f9752e5d3b3277e3c12a75ed65b34da5afcf8dba7e2a1b8c75f282568842a79bbd2ea410f977cf7e32a48c04a77755b2e1f0fab75d8aa8a20bc25e434b80dacabc4e141627083b02fa183b6c09061bce41ce95e6ec27d1628bf0c490b2cc3a50f2009b12a46531d0277d545b4fa8fb7183a6997d3b9867f040b2d20da3b7a5deb80e686119e203e39a5e2190bb9ceea9a7b53340994c93f9ed743785ed1d494efbc9744b9409cc02a3f1f5ed1f016046080b6d06d1a80641cea62609755140e00b23e18ea61b43cc30429d6ba80bf170c2e345f97824225846f51186fc785affc0e2f754a6c34d660e406e0171cedd786a9f070ac9832fe969b459f5e8c2f7b8f11c315a1a049e3cafd51a7ef19e6d96212b6048e59799ca900b29e204643eb185d9cfc5c86a085473dec63c7db524414656eec6f4445de78a032e6a28b6bca1ac3c7f563a4addf966c34d4602faacbd6167cb6fad1ead3c212801ba6c169c541b8eb05a8aee2631ab11c6aca5bc8729287b9367bf0b979feaf76e4824e3e268a19295765af9beda50b4a3f9cfac87c26a153788f64d0117c2b2120e4eddf567071438218485c4c968a40c31f740563ded7c86b6221f3463ff69a268ae5e8832d8537fd2279cf1676e9a79c1df8dea8a29a679795a9e18f7ce4467b52469b545d276c4555977fc7910cc3f96215c595ed27de3fb1ffb929124a5612b0150ffb911c2a2d59a87ecd7af4d5dbbd63fb0897b9c107b82847d23f7653ecb38b54717444344e874f752805803ed43016d3ac6c9505986f6d39fbd392e0009158b69b3ec0a1bf20b7611fb8a42b2efb53a8d6c04169e5846a082be4d8cbe2024ef24db998ee0c923df1f5e8b712970f0bd108ad5a7ebd1ea757c301f760d94ab83e99975f793d3b89e09c6e9024d36752520dff8a04ad0954a3e2929fabb52596d9a3cc6b837ce0859a1f67f43420dc22a99843288fffd7c20cb20e2df83e0e709cd9bf9338c0e703e8cd4a5f7a400f59d072a85b810bc8e161fa30b054e3d86ed18bddb0fb26e6248ffcf31b520627b56344557c81cb9fdd85ca19a85fe8da47623e30965d1ec61faf7968df8d9ed7ed1d2d5718d99cd52738c60a52f06f6b21d1018034ffe5d111f04266f08be1d1c3559e818edd76ae855fb5a516e28c95a23764df4456676cd45e2f00b041fadf1eb1257ef97f2bfc147908fb2ce1849e58fedb60877394301defa14b90e3c9f32ec47d2f718ac1ebaa3d1fe241eb4e6f29eb9b74fe9d0e95119580082906851e4fd085a957f42ba365a20e8ecc2c623fb614a2b51cc2efe6e15cf8afd6fedb396e8fc012e7c2e4102afdbfbeb6e737fec0c97ba5e38a9e5889d2f106a04f8e4db4d6a004df15f25410006c19665e0d004a9776373d39799799be3621eda1188d84cb0a64b96bda01578e89d27899d1278c273aeea961de0e0c954600ea4203509edb65843afbe8f2b44d501779942b7cfe92292b20875b9648e3d7f070435fa7687bc8fc12c3577bf5bd4b49d6fb6f1b7a5787aa136239f6d8e690b12f6cc7b5122bebd81778ef044b507ba1c4bafbe81dea8246dd378b831933477a3821ec32030239ec5b025203371777274d2fec9d1a874b1371be02975f2abe745ef43c183b958154a00fbd55ec25e0799c68aec1f2b0dbd10520594e45545cca10e78c49deb689e79aefcaaed2c0ef3fb7e20e465d79a481d516f721dce63828c49cfb7c6921231e60f4385d63bd826e05257d19470ad7ccb528ec34b40ea23a8cfaee9063cf3c17a366bdb4a0351ef6e0ae174411cb88f95cbd4b4fde120da60af6d925f4fe5c3d8579ba604834654c2030adc2c959a4ffce2bb75077845828982b13408ecbff8640c695dad50607f92f5a0ee437c1a350d1e7bf21319f03c1351c070dbc433fe4f1b125bc5299d0e11f9412e6654e16efced0a13e008d721cf8c179ae3584cad401bcf01bd31f622303d84f9d019ef17c0300108b645d7df9ceaf7b69eaef274a890e770f1e0f094d6efe8f6c701375b40e16946c1d9819d7fe8115aebeea28b2d3b6b92a5df216df6af713f0387c763ec5066344ecd2056ae13366b1c7cd5880473aa5465d1349eb511fb9311516af31f034f990d44d78749cd291fe30fd0a4d9c8defbfc90b89e5c02875073a08054dac1979412a8d81ddf87fa6b6ffe8a9bca206fe47c12d2bfef8240c81ffe18c79eec2b63be1d032b2e463891b0948052cf99dd2301548f43a844e363ea304442216d2a5755f5d44cf2f6c405aaede6402236f1849f864b02a5c34e34b5533910748ccb02c45b6df8a5e1b1df661f7ebd11a7b0e3976e5b0d1718364bab483095e09c7a75a39207920f8b731569bf3faa8edcf27c33f82d1f78d7f88ba01321301d7e4b9df6a020db483a927464efbd507167a1ca5c5b18a45f82082afef46a39b54dc303b84c5dae04388e29c987a5198a1380034b8b97b0c2c5ff61fa0d7422055799cf97bc86479a11530ded45de412e1501f586c79b66b4336c1fd9225f4654cc3f3e56f58827568c1a0a1a10537a167b1bfba15be1faa113da569f444d381bdb04d12a1ada1ebd9c4466f5e28670244062742b7da674e5851d42498e0a8b0d8ede709118ae3f51807ab4ce2e6331149144c8ade919234cffe9805b5ef2145fc2cf1eccfd4fc73a6517f2eca3cad8b9f5120d387c5ae1fe6b86fb4aab2153ab461e6f6fa8a0ed787b9433cc05b90e353ca737a31cd23cce1546b273606f3c49c00c503d81d91ea11d5e3a34fc8d7b1a4848b98f25091068f000dc2e2907fd5e77c06b6e6db715dc2498c72d77ad288a2412c458b97b37cbb3e3212177595f2ce0f2e40176e6a02b7b1dc830a940d136406cfdac8715d4be2d634a156e75df4d1bebb53983aca2144733ba57a427415c2570b38a0f8ae1d6fd7be4cb1b8345cbc5e6d215b229f169f66f17abde4820bd3ebc1e88dfcfe9dd84caf1ba010269d3f7b936e49387f6048e6374b371dd0f9c5182302e04097911e3190dc5a304196033a57cba231e2aba392a68fbf126d9f0810559d95c26cd40b11b290fa2357f94fa7121b58059349848cc8d52953ae33e3896f050fa061f6a3f6ac7a1e43b422d547695951326cf4cb86a78cc4d34d3f62dbeedce8dd7501a75fd15895c83b603abce832cad2860beb6d1e9d184fb131856c7fcc898a24d548136dc4de858a2b16ce3932978224f937dafa8fada5fb48e3d9aa31b0ca76979cfd9dfc406732e982adc412b5d359a7aecfa731ca676b00ced9545331ea112652062078a45a38b839ee0e853ded2cee97b5ee78d517375d6171c11c1906143dc952d20854acd50a9791269ac83ddd2dc635e00eeaaee7d141ffc825801be563c1dccc403a3acd89698650aaefc13c356a328a73462eefae96463515df5122e43eab1a996d668bcbccf6b1639991a50e4d9bbd6c73bf3bf08523b925cc0b0d25f7d066e627b0b621fcd3c62451d66403cebc5c6dbca1de056f8539b5811d95125cad9ca3449a910909cba5d48cd371fb479ea7fff3b93ea5bcd560c11537743f5bad597896f20c11bdab130755bf801badb3c382d4a2a8c3671ae4d855d12cd7bf6134a99eaef3e50dddb65ea8d37eed5028b1ec46f29c3200dd10e67ae8d3adedb841d8d4c740429c77dc92efc8e71d4ccd073de843e8be861d5d2fa147fef563a6765cfa385ca8bf3f3e1f2164a661b771c68e680d18bef4b6ef1e92f2d9bb91d0976e43ca9aedb2004ae7801139f5f152484edcae4523cf1c1c8ce92843ae7f96c4f70deaed26593463152e2d5ad12118d32a5b6a475456e352bc3c8b44e693e9bb253d2ccecf3d4cb1ce60483511119887149358a4a7bec9bb2de08a4ce652b63d820673ecc1cf98ef5d628b4edf8aafdb4fad7b9ba4b03a914ef1e9fd90645a4d3e890a96c2995d01da175d4a1da8b80842d2ca931e257d8392ecfe591615f3dde1968d3d01c3d06f2e0873a072d058fffe4494a88fd1f70a98c94edfe5122238645b574c594f2c1f8d88e85baf14a7f6a711010b5f685560e10a30005ebbf481903a1efe3f552558897478ef1354c9085d335070504b4e66d2c1a4bf38073be72d6fb2e428f4a8df60879d1bda5edd78b89c26fbdf08cf02d0fc35b0a5a236839e8e9527f123f992575ed364befdc76062493c1caa5c4e0fe1c280e00bd6e1fa799874463834b8c038896bab91250847c4d9ad36e70d442c7492a4181152ecf805f60259db84380602f71d03947b7f2c21ea272d9afdb3028d7b125b8a691488ca2540b5d45b7fbde5f03b570474f89d7b52fd460eae48abd451cb6f759c88ef457a5120e725e61fd6f3208ce4441ab680d1e47250ea4eb3bf210fa486e227598d7fe3be338a9423f47c55baa326b052c71ee21ae828b7f9f8baa1f01c6171bb0fc42504ac9c0dc23a0074d095a1ba2f18d50191acf9e77e1e1baa1cc641bfd3bccff8b3f449f83fd975e0843e9f24e23abe8bb2fbf1c6aa7eff6beab79c284e06ce0d53baeb30c6a1dcfd26a42f92d098f2aded751cd072b1023f5f9c9eb6e7ccfaba941098ee8acd48e991d1420508619297290f8c7576107e9b9093ace3ffa50a3bb4d292e3ac34722db535e0385a9ad462d680b35d42deb68ce1b869b3d982317f0292d4d4362759284a0d9a1c043e3142e2980784edbfa340e85bffe84850aa7cf2be0a60dc20398119fae38353e0a7c5eec67b49110a7e8b87c53d0c5bc82614409edfe4242ca2c870f7293f582d355b62505cb96199d6c7b1d77f84d912e415490e32261b7eb6e1a892ef717cb5fc4f289165ae56ffe9dee8f36d1214502e5c96bbb1658fd8f884f3d0d811a14857e2120ab39aa3b68390fd059bb0edcbf7a01b9f084291ba3e961d55cd20fb421bdec242316a9ec7c041c46e85c678731bb424a0efb514f4b764cc91e8fbc67296949df7d1a3957dedd352b0212a08d10cc6dd7a44abb8c5b089c87888a1da58b697c52c98175c68ce30687fbc7e7f9e9d91692e245e2ea8188cbaba8be43fefef561257dfd484c6dd9d24c7b9427cbbbb83ad1eefd922d8eaff057f6cef3e29a02be442fab43e85c6f1b0340284e0329a863606567de6931eb923cce907cc74b4bee190a9f1676d13c94d02d694cac3e6b4ea1a8f77e4a451a752c96e4e12c0ffc6a1159a5074f584945a9d16dddd4b6f2a826397452527860646bc6a81cce465625870db8ab111b3852b603502d76589e164036dffd306033df4ae64eed04de8c1aee4a79aa81c09fad769509f46447d1d002945001968cc64b073c8eacd0e2bc10f22b8275651f5d6359e1398f605a0ef1b1b897ce4020a0c4e665b409a19a5034d59dd6458527f4240037f4ed679117702530b59e1e8b635366b2bcb59b932ec3a046f0b0f14d099636ca57f00340a56056306e451d70528068cd838258e817330feabed18e8993154f2892464efbda5dc324999920cf4054906720695e7d4f3409ed3a8275ea451eee4fa3f0d17d40e82e082e0d920bdbff3748a4b429dc2debf9ff44cdcb4f7937be5ba19593c95a78b9e13052617759f4f1488dcecf57b1c479dcd2df190ebb003d7bf8358d0a5af8a4e44b587503b53497541cac747ddaca565d30173b187428d7222d74bffde49642696c52b246ae93b1872acc73041ed9a95e3acfafecdd339882190e296e0cd401e11bc54e9fd630edf805178867fd00b80925c8f2728954a3b4a25f9504a19ad4bfcea421f3e6d5dff242f1eb6a050cfbc788f444edfc5212e1c4e69f12f385e41c89dfe5d9c4e2d957b368090fec70e77e53b9667b1cc047edd704087d605ae227cd4353d8b89e3a00b24527f3191ebea5f41e2253d6c75eabd5a7f6e35f1eb8ef8f5fa4e87ed83f075a941c128f1dd6f84a49fdf62a301fe0b3067ce5a4fa717aefcee85d2475bbf64bbf8f379cb11856ee57cbcdc78499674391e7931f34997644745a34bb21b94ed92acb6ca201192c586b04bb2f409bd243b7b675e92bdaa5c97646590bc24eb4cfc926ce49c17334916fa7831f3695a01f09246dccb8b9924cbef3e18a60c1d0c371239cef5a2eb71da8ebe78128e3a21d7816a3320a8e8879b1b3febeeeedbb07bf4cc0ef1f9a608861415720d371eb061ef504f537b33c80ef2e1778f283e221ea29a448af091f8d446f7eff19112749f8f14d6edb8c8478a1217770e6a546c54648e7153bba4354afef53df8c778ba6c2e7cc85299a3c492c7df214ade9c7b57e9d4a8bfc1a0a0a363026fc928c426c339a94308b31688cdc813d3c12686611886d12ca39eb5406c46d6c9e8a418866118866118866134cbf846d7b1bee3a461aecffc3b17fee89c0b474a1d7a7ce8303eecb2c7300cc330182ddde86f19a57446ead4dd9dd277ff4c669aa6654c336ccee9590bc426ebcc39e79c93fec428a594523ae9a4934e4a297d4da394524a29a593524a29e528a594528a61d0764b36278c11ce19638c10e280df924df6f8943a16194e233a73ce39b1efe86318c5303ae79c139bdc92511c9c172d3814677bcddddd378d528a19c128c530b7af8527b35377d82ce83a104277994e3d1beefed3dd25cda8a4f0a785d78730e8eeeeeefffc9fbbbbbbbbbb3333b34ca77809eb65f07c6676eaee4ea5a5dc5bd99ef2f0971c0f7c15b1cd6a142f41fdd73a31ea5c9c4be6a4f4a19c2c2f52ce39e79c73ce39e73f29b597afc9292784104208218410420821a434dbb894c6d69b65fa956dd3b44d63693122d5d2b760d14cd64df062ae5fb16ee4cdb83eb3ced3629de55aa992469953d799b66f5b37e24e3ad5f98e63462846b50c8bd675e2b7bc2ae6740c574d8d291263171df6fa93ba0245703df9ebcfda7277bfc7652e14e0a7c6b7816f4c9ee11389eea94627135131c617a30fb24b3e84307e3f9473bea2c890878432c89f1c0c174a79737d07f54c174198eb6fba757d0ed1bd747ace5a7da8003fb58bb108cec4d3a95618f49df3e05ed7fb8f1d2e7ddf786035d84318a3e41e0fa69f28422de280b048e75e2c7bfce1b7b73a0581c41b2fad3f5e3d3bfae39d5c37617853a8f4a3bb00726a37efc5dc933dd2e788dac5a27b3d5fcf4573d6a29bf99d73e0c6a24e4db8f198efb18adfb8cf6bb555915d9fe5d0faa0ebaaa8372f1e6a8d9ea932de8c8906c25c3fbfe3cd5e4308b3cf1e914d07cc6d268dba7a9baf8de6a45946a11218a5975cd79487551a1587dcebe10a063deaf4f574fd9b8f5db153dd5af67c7a26e634ccf51135e5a59c846a947be540c1fefaa96dff8374b7ef9f73d639e79c1315e5a19c7c6a17cd229939e79c754e1e738e5efbd19cdaec22d2e8b5efe66b5d0491dcebb7ed35ae87361d238e07be24aee36b8b18cfe93a5546f2770e73ad7d13815bcc69cb43d4c9be8b46eec6637ee7742afb94ceb3f16a26f64d29a5947e67acf8d763d86b9b149d5b80fb7ca020e5469161d8a49fd1a7afc1c766867d470174636830b61c3db996827143f4350e482422a56b9cc66956b3582fcd9221d330fd3570b2026898bd7cae23579186b99ee9145924ab482af77a69856be7ba813d289e679d564a646c39fa8ec0755cc78ff8ce4f0a2ffdd933fc6eb80ecfb89e3ecdfe07e966df5a17269616ff665ab81e0f6652eec5be379fc5be37df64a137bb8f38e7b28ffe9c3fe9b6eda02fe7d3ebe5f5b386a59913861974c38b992e3eaecb03bcf32167713b665a92d1a8ecb908c5553a25a3511c783618f062f8f9fbe6d9c0508dca5eb319f7d22848c43358fbaeafdff06c60cf4c04795648c437501ad735fbe4c43759206cb8f45f0f977234cd621b7b9a3659204cef838dcaf4d1a2f8c68e37833e0b01b335d8ac6ee7e3015d1d78803749064cffae0d26cef4d4d237d9693b0ddcdc294d6d72dba917eddc411574ee7b4e548327092592484289249248428925963882895cd7724889af473de26354ebbda2ea435f79a9faefab7f56228de0bf775f96456dbe9b8d6caf1aa883e0cda4563fd68ff5e368347af8a487107e56aad0a704a7700f0365dff1102eb6f1a81f9ff674caa75340cfc6aba9a52f719d15cf060ff536e1dd80df43ddea94d0b331fad34d8bd5e22a8dbac9361e190b4b8b51513f1b0f12d59b13ce8aed555f120ff38ea240e10cc6481a71dc53b22d841f27ddab1c7c4b5c0e0de33d238e83d1aa55a664f6075f0bd8dcd11327d1050db1e8a4c9e0c5f8370cde0c7f1a9f2797931a4c9620e9d17a7ae06844da788c1e8e46d0057835cb51c2d1cccab331aa902b71ffa2041ffe0fd285dc23c11ead55166fec14c985665be8c5555cc199de0182458f3ad5d364d1328ba33e0a753aadde1d8d3e6ba1ad581eaa9689b251bc1c8417e3cf3f78337c9a85a254086368a4cf602ca15ed988d42d4863a77671d5f29fb3f6c4d588ebe6aae7c5c0d034cbb75a9843b22dd4432fc61f3614ae7f3b01166918afddea56b7bae539fc96b86e1da9cfb928de11acd2333d65a84f4e3e314a50219093be8343b824aeb4f1203dec89af86c445d2cca16785fa3f9d48248e7be6acf574facf2c5f2d87465514843d5e8c731178b3ab678f3a21b772d0e7c5f8471be304fdbdc358bc999567a37e577af8d9af587e30a379a3ff8bd1c8ebe8eb88877847ff8374475cbc71e39171d5a10e73c4e90081a00f0d24aaf70089cda4513e10a853bd6a540f9ce90161fceb3cd5560ff7709186f13fe2bf72b2615f4befabeee473d67a3a954ad5c29e2dc7f53490a82e9ffec5e9503f089c7fb94aa734ce45fbec5db4294022f4a91cec59b1249bc3838213aeff68e5ef9ce38f4df19daaa407f6f470c3d7e223ad2f3f7936302e07e582f075a11523cfd6395070a98028052da80222f997fceb1b42785d8df39119621b8f0b5e3fafebc2998139443a4a70e6ac15faf78b387db318479be5cb03e49d44e2fa0efee5f3fa6de3316be6ec29a7f63a65a3948657c311943cefcaa45f128e60248a5286762a8c92e52f0ed4a38bae366d3be475c938d4364a71a03874fd19c77182dc8f70813ac543fe0504a553d7252f79f525af4b5e3b2848e288248e2069da43ad519ce630a4a8fd1947fa9006d7674986273e5060805947618aa5c17538e9f32b8adc19f7f944e1c99df3c97881c1c2abae51cae954ca4536ab59dc6ae5399ed3ac2874fd631ca97c3be7098272f2b9ce4eae738b899e572eb4f39c8bcb2971bc1a7dc75ab8df71d1139d8650f5742a7d27bff4956312739e541f28ff357a3aa8864e7531c6af357a8f9e6956ec624e8cb1c61aebc3ca755c3fd63867adab6f168444a56a732711d18a6805677aac5e110ff7e4f01a55a5e69587556d3bf9d2bb8e916763f4fe1c03a601cbe0f18a85c03e6027aed7d48f75c6382f97d2cf2fbdb42ea5ac645d485f7a2844428dbe34fad2e84b2f638ebb4ba16115547af991d5a937b23f769072db51fa916f3a4a3f922f390e62229d8cba8967a3f42efdb352e9474f2da9f4b2b552e9dfa6a3442ac11ceb52a281a4f210ef0f26ba948692faee0c8219ed8d074b4e963e22b9ef8eae182265e89652d0caa656b2a7f7928b96162f4e25928b96162f4a3f4877f43f76b872351b87949c36a575912ef2495f928fbad963322b914af4bd9812d7456af98e46a552e9e35f5b4de963e9e3c71f8d1e48844572e407e11fd9cee646cec5ffdae24b3b2f1b214fbff3f44387fefcb716f7c518c08d1793e61b58e22ad7fd7de1767ca3c538529b05e3d9a8ef7f8a11396888573c74005d4c17c34bfd57573458c040fc4731c61823498b31c61829b5236a376a356a336a316a29b593da8b5a49ad53ea83ae68320670dfc768e1af4b5b8ecca4994cd98b574686273e50a2387922c3131f28ec45361d308f3a7dfb4cb36a04f5f9705b536e6d6e385a795ee17ab8f26df0c1375e2ad79d8032f89a95d128f8823da4fde28f1755681708532b7dbcb8d4d47b7dbd5784957d0b3054a1c22bf3713b7f1fa77ba19cd3040082ca4f03a9505404afc722d3e21fd7f9a8f1c23e080361b477615b6cc696f4d994db05e96a3b9b5bf9d9f499c9f434bc6be24cdfbd273d6f39deaf3c0d6c2bee0b5205cf203d0dc4b8d8282cebeecebefbeb6920666ba3de531969b3d211882c768a5fcc230095dacddb0f8483781513ef9fbd9e9d5cf7e23607e46aea855f85dcdc20b6f3f17261b4dd04ee6cd4cbf9a16228422142125aaad703233ea0040545c512842ae3250881c552bd298a30c2c34714a1e22364a08affa0b0019222d583d2841f0ca9daba448ea1509db050bd34154b3481a56acb5258a28a2f78e28996aa6dafa05065700452081189c06941410520f84cc1042b5499944214ab4b8396462bc80652a8da9688f8a8b2a9417b802738a10211a8da969280a37a58b07670546d4d2dd50fa028e951b57d3c40a2ca320dda4e41950fb0546d61f44095695944c1d934686954a9c233d2a07d403e54e051b5a5f14495552df280c91538aab632eca8b2aa41cb508298028eaaeda362a5ca4a1ab42f8a245000a46a2be307aacc6432f11344aad051b5e5265350d9b090ee68640a43f7f9fc1421c07d3e5338723392fcf7d2f12a7bdb1d24ce588b9e8f4631777777bff71e510d1068147f9146e9740cfcd712b56324fc1f84cacf05e1238deae722aca476fc7a8ae8c0cf726eb4409887c8916b1fcf10532eb48f87089ffb36fe9510d90bba4597b920f0d29036e6062ae8c30322ca41162a21b38505d5eb183a99981ba824f7b2a70a3920422584de14a172215081c5119510fa022454cebd8ec14695b5262f1c98c85a70850b0ed2ffe2e49c10460cdd09da53853037b8733e3c1e0c9962a5127205a1f2b751bdbc5b54c7d03f9ba8cc690d3bba207bab1b04dea722000e90e4b066abb9c08d2f754c9b28849b85c81e9c6102080e9c85aa3f421df3422e3e954d0be15e408c8fb18c0daec33690716e817810befdd95f4f2f19ccd579aad7757d76d1eb9a7c71965ffc4ecdd9f5cf397598d376fc5d3f7ff78c173f38baba311ab0a7e9b62fbbcccd819e7c83af9414ce4bc699b2a4c4538c31c61863fc1a32a90b5b0f3579b8043d746a32a5efff2edebce67abfe28e2b8b2cb2a872bbb5c0d7f7d029f93054a1fa90d73fbbb4882309ceabb06f9b04e3849c544ccc975b8ef9d7bf4d87bcd3a5c6afcbe9d7dfaf733d9800062de8c192ae385870f02fbc448918e343c93833bf26744f09447caa08badd1b8a30f80d8d8a50e6c5c47e9cc3044e5077f0a1030028f06ec0e8716a4ee65f1e8c08801b9d6511249040e295ffe4cb95cf921ff57f3abdf737dcf0626c6894fc1846aa7cff299fe533ce032600676420e08077a3069e215f7e0324cbd420f99f9437c439ff05cd6b5eee5e0511420811841042c8a772c6a7f1a9fc39ffc27e1524d4a817853b5f13ee7c4ab8f36f7851dcf92d2c8b8d3144ed9a4872d1bc6a3c3d0bf5d0a39c0d2f23f328d7443634ea79bec97597e47a086e351bc8a40cc2d77fda8c5aa7b487b0a7b435371e16cec4d669a8532bdf05e0521797be14d6f50d1fc233f8e95f6f26b6200c7f0bf51043ee07bc47628bdf87bce715ae3b95b82b37e4cae74b72c2b321038045769c112c824494cea773235920ee3a3a439d1241c57ef2c05e87f9ddda96c0e373cea12af5b25dbc7a8852fa367c5ddf428de2abf5344d27fdf897eda12da31f3f3b9d78b2e4160fdfe016bfd6e12f2e026d3be847fa114807cd38ea5a0c8262ff6a7ca3127c3120a0e993031a7191630967e24edc893b7167e7c812264ee24e2bae5a4271272ae1b81363488544494c4470c6c43537f7749eaba4535d04ba0ce43dfc114aa7523bec3871c771b63f7d3d1111350c3b0e914e25313dbfe7f40c2ccfc2c19c1d252b169ca203e6c6238d021219497c32e3ce8b611d2863cfef477ca7534fe4734fa77c9e8d9f67437b7ecd6df7b88eb71df365363fb6b26881308645248de2211b851a8501e9dbc51d2596e019e7f1c8821883cbff38d6e0f6cd0667dc8812977fae00069d07b9ce8be18fd1813afff13073175b77c89f3ce11e9fcbf3b76f75ca651249ce65c623979f29078976903033d46918fe9dcb4aeaeac4facb33d4ad9e74729c13743dd39f3490d429e5b6f1882f391ed8a5e652ceb9c8457e1751d445d2bf2c5ffeec09b32e33cf0d3f27a53ddee349ffc190a2528ebe89524a5bdec49cf366024310419313ea8bfb7ea0c02102117df91a22563218cb20c8fcd0a613d495fb7e866025a9f5be9f2194a086ac64c8f02441660b75def7d364ca4f932b6eea75df4f132b6ef795e97d3f4d9ef84c0e6032b882e8a14e94644d103913284a0c21767e6c80850b354000b50864d75307ae0eb4ba3a31c2523364e58409538d1044bf517131e9cf4debd4281c3b083aed00827559aed0046645185d4888538cb22044e13d4349b6eca789144d7e9a5439028588915abaefe7064911eae9be9f9b199882aae9be9f9b9f9f0eb4229d3f38442b3c3f9c72a82067c7103b3f1e58c272fdbe1f204a70bd65d241d5eef3a1b2c3022a4b9250b1c14a0ea83c310541258a95105069b530525beef3a152c513a8546981a2ce205c34514b1f58a9a26e2730d5a0624b58a8d45393962bea8b276260c5128aa8aceca046214c59c08208222c8cd8f1c3d0cf0f3a5918f2f34311598213b30c2264c1c10920d01942931538d981131941c53d5596d38f1150eebcefc7081f262cb2ce285010f2bf8ccc0d5e3f8124faa0dfd79780bcae4b8eb21dba02794991fde418e127c70637bbef27677583824bc8b48cc02a0b247870108509ace052384129b2d0441658d79fe524441656b7abffd3c5e62b46d93931eb77eef10cf86c9bc8e5eefe00cfe0f77f8f3ba7510c6d3a27c2eef7de0d41903803d00c706ee7e355b9f2639c314e8f9eb53c8bd252f08c8cf92767ad46b547661af860610a137426158d75f3bb49ef94f25949e94beadcf33bad5f1a8875d83f9b510c7b8a4d9f925e382f74f7c97537ab1f6cee32823de137a67cca97b92c5613264d5856d40fb056d50824446978b9b3fcf2bf6c3fb47e3db32e0f4926177e3ba469ffaefe78107ef775b1dc2fbfdcfd62f9e5b289bce405e1e53e9360a520486cc25a6de19be0d77258e4c22730e7be6e4977e93146180258c4611197ec1c80455a485e5a3004459e04d59b560d32d950da0640c8e3baded03694cf42b78b78ebc2bf1ad028d81b733e361cf0bb877bb564a1ebba5a08c2776602cf80ef300a11b35077c36f94cd643985507c5e1ba544ed60fc0b8a45860c8ccac24ce01b4237dac753536ce3c442edfe9b00b28951845a43019d8a7dfb9f0c9953a39a7f7311238a0a43bf8c8b67e3dd8e409097df81de0c36a57a4fe7c37beef5419815f987865aadeb3d70c67b200c73d7dff982f8f140a101a229024d104d50ec5e5ef8dddda5fb0c40b70bf2349df10c7fb633f85c9633f4ccf004cfe0bfdec61f25dc5c03dcf79304a19bb52667f8725d0f6e330350a368e08f8b2777fc18391708b91cd08166632bd677cfddb9c9753eb42bdfe7a473da4ec87dd73f8e2fb9c733e6bb8d3fede3217886672fbef7314e26f2fc5d1046e843ca0211b636f7f1eb7763dcc18d926b80fb7480051ffeb6f29f75e967229d45c6b9ef25ec2b371c4f4a1b1af8e3bab21372fb89dc2ec8103ce37dcc9a3febe1f6b32502dfa6e3baf26d2e9146d9fcb86e3f7fb4ce77b68089dc8cf46eeaf462612c51653ac52f43f08d47e4463b97d4eef57011b543a1ba575530773c1951e3d920fd93e1d14ce0a556fe7d0e3301f441d1bebb310323460468bf82a397ef76f4d9bf8d06865b8e15ae470214d0a8d830f16550a8ffd3a9d69eb3d62ccbfe75b6814b7a9aee61ce5a4fa77f92a57931f1b3a1195426e278fb17a0d4943f77d30289b79b2f075dec5e91941bfff29dfb046043e28b05fe5a9d99ff547c1a323f8857d58e21b218e1e92f1972b5756447872e1b0ec9b938e73136ecee281f76d3050839990d75dd857559f9d33f558b6df9178f838b3fb9f8171cb78116aed616fb542eec53b1fc83332e2b9ccb025adec5dfd0f22e381f9858791f5ab87943cbbb78179c0fdc9b5d0fb7bab03640181f452253677349cf1b0ed267b0458b164fc3bb2ddee6b2d8ce7613b82bf54db6e36bfa1696a5f46f5ba169163b7a93b58957f08cd1d7d1d340920c9c991a9771a8dbc9d096540189d2c89525abd83fdc74d0a891c1ac3fadc1e6cafbf852991bb3e7eb326e386810fb78461753fcbce1c076b894934f03697a72b5515c27e5e8247b2fda65c8c2b69e1a15e3cb28b9d928f9129334337377777737337337337377676db76d8bdaf320aded7b120df1d95ab7daa897e4b1b45d61666666eed7eff57b8ff9f57bfd5ebfe7e285113f735698628850c61d5d483e962d9f5a151a6ab5a2045d304e2cefb59314a2a121a1d67b0188419530882194fb8026009678af7e00625049a45a5a79c19c0b1ec4e089e1440c27e4bf972c8bc123a59452b3325acb3ece2ab7effa460d03d786520c27029b09a8c4adf68439ea14cd0000000000f314000028140a870342d168308e5359121f14800c83924a6c549c8ab3208951144719630c41c0104080012300032333540188e931ea869d68e4e4eb6a1e8035a90ff560a5bf1a2cde0231a78a85f6e8f8dc5e5a3df4906e97c6600278c9cf76eb4ea57d70c331f1fcbe08bdf6bf6f4e07084d97c2f6666e4302e64b740d1b42a5d15f8351373a0b0aeae718f1ec8f38cc8777a925ddc1e0f503583ba82c4f05bf40531a46f2eae6fe0a4078a99e1c15c163d8a28e2875a5811a686fd2e2b7c780350d85231bc66c8e9207098db025ed6d12f313e1ee839429709fc820a11ef4addc06055bb00e41989b64a350ed7b5183d5139427b66a3fd87508c564d87abf2099e40984a1cb761614c619e381f0b718b0b869939fafd9389664481a40d4be5361c779e604ad1f64ad6c5d2e3f48487e974e0c2c9835f61bb85f881aeada007dcc710413549b3ac7acd9579240e51704bc1341e460cad6715c5e461245d0d6ab78a86a5910650f45404272fbe6142d821f0b8754f69622c59a54606eea00878ab49a80717ac39de066a368f0523fdc2e7e963cc84a950388d43a01a36d1f0e308f063b451e8d37849adb8aed5a07df6cfd1d245aacc31f10e21c9ce531840a1eca1c84d753d44d6c62b57c7ee37304f82de7adcee473de08384a4fb8a4dcf5457ea941df7517613b6ed38a2a5b77e1d54dcbbff1dd1e8e02d69343aaec1ea5a14761620b93c89e6fda4804dc19360c26f0bb2b9331e7bc64c5de28a02c8a276593b84be673fd023ce1e7e9682d4916f76b3dd7efc04fea6efa5c7750d5db697e3fc4e22c7508e97247b18dbfdeee5da330e7bd9d39bb4f227186eff03b0593d2473a7906c919402b0b071f826f044576900ad254b632d67c1c71f0de3ba4a28e79458e87d4d8c1ded71a30d65c0743d038c8d44033a4c48df684d5ca69e7c8279d2def8a7d767302290a0609a334add61ae655d1b5ffc8a1f324c3c22c97192b966fb18de1f69d391b700b208c07a37044639df72a38f7f07e8e69e6ce6dfba1e0cf46caa1e573ce5e0a5bf1f2d1e13c6d81c0c19448375e82ea653f22d74a3ecb839fdf99d85b5509883fef65f7d8141becd71af1d0fe62146b628917cd16ba1672a413eb5877e766ea202e02dd9984e50050ba7af10147f683c323d4bae929bddcb3eefffbd7d4b89372eb7deed8df1df6afc072badf42bb574fbffecf8ca854faeb55cacc892da4efb22475fb4c18ee0fd8fec3b04349d4675dc0cc396ab0e23903ed829fd1d15ae8c11ac1226e789160063de7f5e45be7bd5bc8dc5044228344770073b1056dd27779de7a48e3c0facb979d5db45485584e41b60e743af1dce856bb113bb3ad01f12191cd9af0b5ba74fd7966cd83ed7d4526d75f4b57f65a8e07558682564260b7d9f01e5f306671b717e2a1248a9fa1c4798e36698c1b8aaeda2a261b50a3484b3dd7b894c170983bf7dfd8684250be4b1a76575cd660d8f280bbc01805fef0c4007565bd990e6255f84f489e281c709a83fd20950693d0ec216c182f6b93fc3d701b02bc6a6bd004021e88a280a62584596ade2d1ee8ee0c28d7caf9686eebe6b21ba83f7c71dcd779c941029a86b7970dd6529dc9b61545ed528f5a04b58e48cc039c328fc25f141adc218f2eb7431488d8b4da523978cfd4ee29a5c64bd7d7650aabb1c3711ced29dcd49ec7d21799c786d5efaee28e1de8ed8a53fdc7c3b610f2c0c06be7368199d3e9c6533be51e87676b910a4483d730dfbd5d9b4e4c7d83aa53c95232002eff4cba69dc176e75b04555b81da4e51cbe0a045d6a6dc8af4bae3967949cda374d4f1e370226a45a477835567ca55aac771bb1e2f3664769ed045cc58abd25d78977578435fbb61b5f359d75efbef1bf96b591884dd9b306ab8064801daa150c017b1dd6f82ceac12d3a2d138f6d178f76bb62c8b0d7b4e2a0388a720bcfbf42af9664b6358289a27c60fff7c229d6647fc3c4c34605d16ca82ab26ea2422b220438c1df43d4a42b48352e621890cb747f0968ab705a39b0044f2679569c64b69c84c47060f6b98f981cec6a5d55552c27ba4263c0cc7065313569eee3ffca89556eab6955dc59635ff48f80ab625fc0f696f2add54dd56fd604bba13971a3a0971ebceaf4e084524798139394f5acf53a4d9dff7d25ed57428a51674d86deb9b73be2b41a249b69e98eac28bd7b6abe875477296286401c62944190325455359b4452b44b6bf1de7f4b7f7183de4ccc02648c70c56a50443e3103032b72891d9539ad9c904f2c7aad35ea368e6d34115acd211ac3020ccd94132fb860f394ec4ecc120eb900654738d48f41e98641bd64e154e7bf393160c88c42cd33003a4ca49b1fc68abeff3cdc22237724f722e774cbf544921db8a7bbd5165529ce6fb4e8f9c122c277a1c130fc418ff7ffe4c992baf9b91322048cedf1b2b9b49b4914b0fd876226aa6625ce2ba1fd432e216c8eb3f8fed178bddad9f9dc96018b82fc291a1da48ea1ced451cc1adbef978b45948ec912ca2e9214d22750bae1963b8a721819c49ed72645fad23b2b41958c5dc080e31d1b436a202f030f2a140ea23d3016394db45faa4c21b03845a01a3d76719a9759383c42cf02a150dc1951f567d42f30fdfb53a9d73d5f6434458ebc1c6a2f0208a849581feb38840860b5458c61e1ac241f8a645c9e53f4c5446971be747099e669b737d38950233861ac61895142e7e84d8c3ac6d0e438713f4d75a1152936905de6d866da0bfa7ae94e21a28609e6525ef65121a48196e3b49bb628f1d01f14fbf7003469d0a060b7d9eda01315cd6e70c7080985c90c94fd7a7d8cf430141cb8daff3e6c9bbd9928760184c9d7191367ffdc9ff9a69fde7cfdbbd93510eeb7ccd7166f1ad217f13db6a6e6338b2c221e9426ad5b7b015ab3df931b0ab09582cc53bc6af35755e7a3f4bdd85c9b736988a95ec003b4abb692e6d8c601522c7e4ec755fccdc93afd1c81b95d60d47bb24da327cb316920a2c301a9325588c0d25ccf52f4324987c2fa2ea236ba6b148d3ad1c8383a0d5ba4e9ada51b4dab882b57af46ca8b314121acf23729441b3346491fa164971f2cf925962bb408165f1f64a13915d470e8b6ad5c2b26012f1a58f0c96b6ab6d7a8b27aff5c80eee490e47a747af3f27e2b0f9722a3dd177e35beee8255d26f256646145a036cb24056fe8c720e4f9d253d3f5eb6b6f8f08fd8473443692468708d77d5e4d58e52907b8144313e53a4599f6b39962db4e0e482fb375783114285979765b14f991eee4e13d975ad636334b7e6c8dd930ab97a29f750ea82a1d606643612a27a7fc831412c901237e89f1bbf2d5cedab721d631ac656f232262bf42c46563d03fd8067861ef9a9d1b0e7c4590e89e73d83cc37c86546ffd2c0530c2d7fa72294c45ca1a14a19fad137067aaf387b45211268a37e4fbfa0a88cb3a1e275b219ff45296d829d3cb95848c13b40cc5d9e843c6553edcd9cd1d2262b59d0c4757f08a75fbc662fb03f968e3e8233fefb704316f65f85c3c08a2eccd71ad34da0018f9f2d4b99d2aea11402d54be48b460d0465e2ab8820f035f2d15d6ebe0cb1d2d2c6285fd8f5d22f76b63a35ed154d58a0647d4c01124136f24ab8dc546886538260a75154455a0519d8a2812212411419881a02d57bd4acbff716180a8954d80c3c350953f08606cdc778d4d1bf978e1dae3a0155a708f8003eedb826d62dc9aacce9e5383739610ee6acedc39e3305e16e0d0d3bc87753780d5e9ae4e6256f19cd394d6c1bdff76c7e811ec17b65565ddb4bea954cfa774c764f3054388d0511fb49925ac1b86d5b9606ac6487d8955ed630e1eef5547ccd1144aaa4a0f83a1bcaa629a210b496cf859615349a70923d3484e8897b4c43fc316190e65daf29329ff5ab143a6be38435c02af7c5c4555872a1231688ee186040190781cc99eeebb218017a1efc71153774f7c483f0134c7f45a11cb1a0b9189fe1737bc40236e2271f1d270b35408db4c792edec99da5f0431ba9011f126322bd661c54600756c06f5cf2419c938a3f5443248c3a8debe6df0b04b3f249a0e3040f45237abc3d091904d049223f394eb8235cd7001779fa718fb558c14ca0e43b678895e6872f4b7a3db8b290ca4951787fbce1ec7966b29a170f1f6495e7812832c1fe4565ad759b951b35ec06a626fafb0035864bf647bb5262d33aa8b6beff6a9ea06edecb80b3051616c25e988bf5cb5d7e0f88602b34f8bd78f55e667282eda99aecb2a4269a13dbc58853d8fdbb0831b35f32972309e84d598ac1acb59a5cbbe88a54b8ea5e5b48f37331fd7a0524e125463729a317701effb71c07eb402ccf3c78dc2e81f647d491e1d13b686d751184a80801c84b757e31028100279485ac4de3e1cb2548e5739f5a527a5b11e0c09387e7be174a8366635d8079e588649bb23e22d65c2a10eef301ca73d7734a405be5732db480bc1f823fdafcebd4c47ef94793364240a994af808447ccfed0172f6b23a8b72b8bf59cd591092c2df2efe8deef2e243a4fab5e7e6f253a592c3597529f76d6a1b9e86eca2b754512bf60642ce5e1c4e20c28abd4795197e126e205cc6f42cb9377c8db4bee7ac86e701e712c2e46d441c3a354d473dae6485f37137d8004e4622408722cb3b11c0614da922f5adf3275e5f2f133e0d9a17cebc22ed1ad38ce229b71df733821db95677ca3d891be934f9c8e1bcaa2331edd54d0cced21086a39091b61904c447089245d56bee25e0de5e4825a9df35b1c2b55ad94034609d8818fc4b962891ce8ed5a0c8b472457d1b9470157c9f4dcf195147e9f3d6bdf914e4d33d77bea5d6645940cacc6c10a754becad4cc03ee8261b0db667b84fb0b07113f23b244460f25bfe3fe04ce5c464aaa887952b5ebe0c879e2c6f518f9fa7f2156f2c33c79cc525cc5087c83391a1631a47e967238bde541fe65b51b304f1ff682966c3de0919649adf7112d4522df576d596ea86b843cd89f59dd27e9f67202ab956014ff1fd51ff384f15f5496d3bb9a539ea408d915f1ecde80a35f0cba74a50725100ced8053da45615f727da082d480db65ac65ac2ceb092ac2e0520f4212bb147b98d96d39f3625ffd7ea9e94b99a52558f9da3b57c15a59b887d54b886d3c1a0ac6e6589c64ecdb6891495f12c2c315a3f11466bd844f79507ebda8904ac1edd3e90e5cffcc4da8b312673f03d07e2b3cfdd7223c4168848a36318dcfad86dd652495fd25825f958333ef3d1144b575613815bfbca316f2f2851df143406d096c63a2356761bae10a97087fe7e7609b42cd7b112a62f5b49870cdd24b2e5de277e61ad4614d3881dae3a3ca3883e9442740085990bbe3d1d5b313dfe5536d38617ffd24956938c91f2484b5a2d4f414683ddfaf1123333a073bbd724bb8332ab9b5fc17adf22d6bb59e1bfbb92dbd75f9ed9b6bcebf607c750725f153bfd68a3660d31dd8990fa4c4cf122cd76c228f1b59b3f47f22e6918c3f6c1ff2c78960f7c000d71025cc599a795cea9db2e9faacdcedf91f5bef6b23a3c6e76ee3e50184001483700cc39ab5433564aaf7df60979b88bac229ed1b147f1f44be3e44324e27b2744875d2b35c81814c74d9d780753bb97ffd34f42f53feaabfc76aab7c925e1c27dcc9acd5693ad72a727b04987f00f0ebd9a21bdc1fb50de085a67afd1002f3b98de38bf3c3611267afdcc69b5a6fc5155beb46b71e3335ed8962b7960e87d3f75bf64d7d45e76cd75ab116cfacdc5ba05ea1aff0e9ba4398411dd76977cdef3ee4a4a019b6903ebd106309ad3beb79647870f741ac5bfe973830c5575ec30dcd546ae2357070a82b5299e84db16c0e6962d2ebaab19fbae4a60bacaf445d9a0c2e01314f7f502b1ace2d322391671aaa4a1dd4242339df4c58f1e3642ab4e2aa5151f2fc0669ebf87d8991adf5ab2cce0980d5f3fd226b3f7b75013d111eb8f4a0c0554e6d5f5f2e7060bd4012052ed0b76e8cdb9864f28d0251ff99577f985dd0e2a0fb6b9673aef9d38e98f3012962dd91ffb640e2393d51d7f3f04a9abf2f731ed9bd0ec9ec1a1701a9d2c14a4ea5dd686275ca46c0011a8fa9954b94894db4e5b8a64348cd17c6e0cb675348944ca3f9b6501f06c7fdf37e940a7c84df8de3c85866c434cf55b7a2b74cb74d4db000d0a4183a13cc9aa5539771502d8eb411411bb0b1c41af4edf39c8d07bea1be5ba2efe7a3116849f43686eb36771b376d919d532fc491ab67a141fe3e40bf5d7b640768d266436eb6feef4b6b0f4a8a0506ef10dc94f19883a0240bdeded9b7cb60e80ca26e4544f3366cf9f6159762c46f8fa527b2f0c32b3a761efcc6540f9f1e4cd91bafd8d098be048aa8e2a7131dd24409ff0f9fdd2d197c4e53a058ed2b6d81cf8a6f690e1ceb7c4e2b50acec234d81674df8f2d31e7856defe7b56752bb82d0f01d3a5ca9326983f37b74c4b39abd5a9922c0ac97453004adccfaab9eba52c2bd00ea04df2d432c3028035ed037165f6e398c4d2bee5652edb517d64852eb711150ef108ae4bbeb40f10409425c6be2b8ba91bbb99c711f5ed96781bb4ee4248bcf897a811a71c580bc1e9d51d0da142cdfaad7c0b702f6d9e768d87c79adae98490e9e207b9f250b146ed354f3625f0bf48c9c3806710591729777d68aba49dc1d97f8bc906221ad535c0b62fc2427a8ffebfd550b27b8b5569c030a16c2ee5afeba61f62b924813165b8024c94c0b6c1ae7a561fd30c851099461f6404421efe6d2181b48b486ad54cedc0a7326d83cdfe6163bbb45ae1d9e43723d330209a840b9b640c1abb24d147806a9f6794cde2629c5f53fb1ed131209502c99e4ff77783e07e2acf6c043634e00de7ba89131ea1bba006350ca4f3144d33686bf740c3cff7e9d4a3bc016c1c47edb98a040b0cc11cd72552f6de1190e2ad529f17fb0363a7f8e65880aa45048a4586d8b600f0d68b8c418d14fc8b4257b457d26dfc6abaeb3960220838f2ce15d8bb4ef01b88b7b70a0b90961b918aafac21be85bbfa3b0c2f8632978cbef205e83d66f9ec6a431a212c986be9658457bb88e71396090a86dac67f0ec7ce7125403e82846572298bec8d079052f28939be0b3c6591cfe7e732578faa8cce673debc5012b29e1e7b40ddd94d3526893b3d8caf6f5271bb378c29a33f2aa95e0d0119297580bf8004a5ed7a2ee70d340993c34e4710ee9abfbc1def8b202147bc31b1b18f8f9750f6aab45faa7c6b6536613bdb767bb6ddc885b3b06f22ca126abea6f99ab27a9e8a1126f8129e0d089807bebe130050b9256dec545a1a87c3e2d869c6e749be4fda0d76a23af7bc531182558ff271d8ce7f18de3dc2017c487aeeac21dfc03bdf5d4d53bfa03b75d15d76199a8012d55249f02c55aa400bbea27e2444868f503d61c67ab0b80f44e8c9d542f6573a3a92006de0fbfca86abbaab4b57cbae1ebcff2a71045f9bb0c7f37259fada0b337cf6a2a7585ac88a3ec1227affb3cea0597fcf4225f60d446bf23784f24cfb5ba3b34891ea902a4d0b7c7b59ea5b0d3b3faff04267435a48f74632dca775a4ce4028238411a06cf3482c8b5b5a1292841692756407bb8419dc8e4d80b526f9cbab7b2b5cd9053d80de06434d9cf47c4c131e553dcfb476bc0a43e963711c5d6e0874aa64bdcd01d629d55318bf64bce3054a3290b384daca772e55bcd67a5a1e488ddd3ebee84cff76cf7e7b55bffdc2e51d60c6b58e4f83f6f922f8e2c38afc6e3a1282a6bf086a0ad570488bd51e8a5aeef112db582ca1e3dc96448d8a6830f45903f59943ec94ea0a605ba74e64343388e2192b39d9a29fd625047b9a1daea4ce4951516953cae1e1a15525485cdfb5d0877ab2f7e60c5f3282582549ac5a73a9b4debd0fcdae885073bdc90b88c624f2fc1fa8f60fa6f925f906bb7504780648a3a3a90dd2a82c660eaed5791a181ec14f21de52fcbb830cf91e01bdc347304db30353ce0e8c1f745e94ff23ed2069df8386b3a3427857f06a3a3010bb42b607891f5f02141df40d07abad9388e0a773831d6cbd6997d2c5db3b74b5c12e2bdb1ea10de65c5fae7e536477c75064afe6734da0fc4d2b8c72c661becbff162d00126a7b0bf2246dac89a7742c7a535ec9c06c0a86186fc1c21b2a99afe717a599169a04a703aeb499a05d0a5c0b9d21a7e77d9003da593764617e8f62d06cb7ede8270c537c7fcd8a412f15bcd2e0969a625b6799fb2f47602e194b5abfd06eea1e953c627a5612cfd9cf6690f49cd579ee0f68414d3ada59d86b170bca3ad128d0073b09fc17f1ddba6719823081cab3bb205056c619fa829e91bcaf6a0f2fd357ce87f54e49999a8f8b5d7f65b3e4ad6e8381afbe0101b9df8475a7b95624a7e517f5ebc5ca92a8d5d81c232ad1371720a3810b88a1a21995bccd0992c912a03e4b1acf1e667b6402456fdab1f29090c5b57700cd936618fd01cb82c488b5bc4112324762cda6bc2ef3113966b16f3024a0fdce6ebc5c7e8910dfa513b14cb02d87b8f3d29a6f2de60bf7a5391311365f72cef24e4dc7bb7cfe2d3767a9c7302feb4389c9bf7775d25703d322856a9f401424018e9cfe7a94808f49af2f88be1139c459ddedbb6a7ac795b176ef71923108afcd5bf1bc3592611fc8eac80135bb2b2521f55dc5b83122c8d9a95d44e1b033372d4b6b423b958b8c61fc4c5329334b3253ecb4251ca49bf56928a474dd048a8a911977dd13df2c09f6c952726e5ed716546e53159e5aef6f14e986d76806cdd180879e1e5797bcab4209da92da58b350554ad2f7c7baa28bdb47e8d09e580aecfdaa8aade747aa4ab06d9787049a07a1272eb76a62cec496f9335fe7424e494aa73be0e6f05eb11a25bf1cd8ddb1cc7c6f1b3b6e705d3dcea6ab7806f948d53c04808b6c3e96c099cefb539088e80d0e0710d36039b5405d1bec7f03e89cb07ed041b0bda7c0b2a2744d1c2b77437557e7d4ca2b2415ea0c32495665cf4d65f062087772f99070071dc2ecca4c40ba619914d37a8201c547a738b78b81e900c4e394f4c67716db908d8f935099599bf0d11b9c3f693b6af315d1e7cb80be13d3a1591ee3204887f3770320e2fc7bd59128fd586f0bb03fe16707da9e4311fac984f12eb347ce4163b5813deeffe83695a5234564735c433231ed67247229ab3dfe942831cabf72cd0a8bb50901d0fc141b9cc65396a88a8f234ee514a399b8dd14edac4c642a5278a3490795127d702cdaa4ea1e3cfaf2fc52534e8f098fac0e1c958e5871c738f562ba223cb009a3c9892831b614c0a652a93862a06cd8133c0184a534daa51c89e6bffa9c244a6a492053da8e987788434b752cf646f3ddb7c1679705c718b5902995d4e5340a0123be504a2980e2b245ca778780ea2c1a2354141b33861753e45ea325991ad08e58ac6ac16247f0169bfeff7ad87522ebe21dca8717b027379eafc34e6c16c7b23e003bf6579ea3588ec711f4ab02e47d06fc43bf420f2b473d20ba89cd3e895af57050a265b9998448c671eee7f554a54dee0f7151fe92336c706f648563527b34d1ae3453bb2af805fff38aae233fb17bd68f23b759afb2b4410476452318dd89418d51f30ed655f2221dac5a9eb1ae794be10ed4f9ad9dd1d035d2960d16a562634a9ca634762caad70fc39997dd2a2604e346f4d16036fe69babd2ab6085fd6e9b40a5306e83059709a72ca9a875eeadb119c20052214374634be1ada52396425bf30a2b27be5366027f596d47e11cd0933facade34b39eae1a74bb950cca5e80f17e44b97f4cf8ebb997cb8a1f678a38ac8690418239edab4fdbbcf6d7f6ec22f4520e979d27003b535cbd78a93041adbb1d3913f89ace4c31f4da9f7a5561d6c02b7275ae2c60256e436b4cea9f0dbd2db344d71bc1f97563862df02bd091e837572cc880edab337d4cc8e70cd6a0a0dafecb185ef4643267b0615d3eab273480f325b5937fc59b887ebc9d1d7f164b46e9c47e266e3fae5404d5e9ae5c614ec3bf0437aa098f0c930788c0f59f972ab60350afdc194d9c240af66abd494b0c142503918d803fd774d96862d891fc9d5885e6c3285264b1acc6107a9d5006fa110b84214eae437b8bd4f4892a5eabe1560a79465061116b89c36c0ceef46797935a32714407fd1be3bf417c2b46520a84ce59602e0ca9f3fb5e0b0f152d0da4e9860f3fa09a2fa62f352945692c851a07b2d055604b79d0dd2897464503e5cb9e5a527a97a72cfab06b1339d1fea5ecfd4300b756cdabff36b33698864a8a04aec80268beaf56e12b297d11300a7e456b4e4f2ecbb1106ee7e454e74e8ff9170bddaebc013acc370e11c48667fd0116dc4e2f4843a3a28d94c34a6b39be6d86a8dbfc74a879fe898a76518e1c150d4c5fcf38878ab67e5fcfa0a95f5d7cfa04b96ca506381c49c318c570eb234225ebd0aaf6bf5697c2c3518ad6fe611df96f38986820106da1e2600d5aa6bcd1eafa7a8aa61c742293730abef56621f73b9ac637c673ef6a3b754182c5856b8eb0b51113ed2b95534b8f334ff704e938b55775b90b5308f37c51dd1dbb0d342a22c52c662fc3e899d0cfed8aff3143841b87bc3cd208c532ee0fd3a2d089263044bbd7616d94ba398322dbfd807442814f947833322768a3ed96cf23292b47cee2d25211b788a36e10c6af25f4247f4d3636cddbd4fe828a15dd0bd7c82c128b3eb995fe5da6f9ec23910a92c7e668ee44fb2241f720599fb4872f8c4eb4780f212ef5f95b16923834ae5f15c2155326301764b225953e91a0499d6808c30b199e2fb94a0785cfcca0713422beda0a2d55c26b9b70bda209a56539be8552a4745f4d32b8698f3a0bad4dd1421233b73f6174aa8ce814bc760eae4af7187e06931a930f5a47f9fb06b644df044a13e53c921357eabc57d748c3694bdc222fb309283162f42c3e8e816d675af364fd8339b7d9f6d327229476dc9e40ec603fcc652a0605504b354b55de1c1c886a16fffe243cf7f821c72a372d6197d05036fc85160eb2a46b67561ff6547556bc836251f25faf141622e2af3c301ecfc05bea4c8ee2248b351b31fb462d084a785f5f4966f97864d7e580ca588874a8549be0292808a6cbf2fb601d3b30556792f9e874bf19e21ba254f8adcf13f73c695c4752ccc65a097820356349800fa9e64b01a6ea8ca3b30209a201b62acfd55abb087afb2679576dea89bb38b2f5cc416d466d5514c1edbbc3bd74460ffeab217b3754c3c015e9ebf37327ac3da4239fd8c453f23439ab17101cf2fa226bb7930d7f9ed87b20ef9102f6f3350a8b64f04ce5ad726d1885029c9edd7ed6f77a0bad75dbdb590447ff5fe88fec418e190658da7856570b5385ca93eef7594a96141ccaf385405cb26656e0e59b7146349878fd93974c32dbc7f4af60b94fef9d714d7f9b651af8d4a8e9a742f7f52c272159b9ee65d8aa95941acc4fdf67fd6c113cf4e9a58f4f8b8e8d897e7b0282439a800e5beee7daac01a5677e29082836bf0cfa93427ef54f54b7a4658c75e4aa909bca20634c78aacad22cf92671a6f109e05bd96f601eecab1f19975556b63a6426900275845f62fa556059c7d2cdbe376acbb5c896137c49a338a4d519c3a6c7ac66402f1139b08996b9409a3df85e8abea5dc8c7c2ff57adb1a3fdba7e1c563ad3b632d61e9c7313c58bb2e5792902cbbdba80d794fbbc17a221e2ded42e6892039da358627e295fe15ed2490b951a0cb6423226253f294f81706c7171b4e008f304da091ed322fb06c3b89c46cc275ed0cb5c3206c72d71843cc521cfe566c1cd0fe5301c3efa7cd3ab19db9b085d9f982cf948a9da7844908e5069633a97b416418f14f9a3f30288492686665ade51f2be45caf449c8f95b96fcef891a202707ff99920c941575802b6c99b6b6645623e96420bf6ee87af92d2c8b1b7f2b9b1a5ded0248f3c09dcca821f9e5b8f83cf7fcfc262cff49118393ade3c4bb5947552b10e7122c06b18069721a11cd92a6ed092cb4c4df33492206c55263a1eb33495afc1e8c0840570e5c7241fb79007c98aa156896ca365208bb2c63fb5a08d5b8a43b4fd10710b21bd52acc9b388903583ba40941e9406938bbacf13d728ba669ff7b418e2fe166ebc9805c9a4afec45ae400f72dcde954d8ebba85282ef4a571cfd001349f6b0d518db8500e943b7f9100dc78ef2ed71218032a34c0cece0f6f94680468a4ea0c23d4dd35f21612a6e8d8c1757597eee472d4bb0adb069d080f74e2dfde7d8a253068a4a2c4b7712d5c76389337adda6482316460a07c3e27b34e9f1bf8414f95ccb0d2f2778c8e5a611377dbc64ce53cb20f2f3b5050586ae2f41072bba48c42904c93f5851c021343e14b1b70f3fd9843242580a7ce4d88e7fda91152e9159d4a13138d51219ab2877de12590c28d774895c4a95125e7ff614fd4af02b193c9818857fb03d22a8de2293a0c8edadb6affdf26a4f9100f05c2d191508db2b8c25374b156a7132f5be5fb1a10cb3e3c7a78e0e59a8a0fde3bcc715e8eb2e23aada3f3d0f4968204f7fefda0c46078a447213108b95e17aea59c9b7c632603a75d49f040e1134d966d529f2072d005b632d21f5282af9afdd07d51a75bcb2ac82bf71f0896f485e373f3ef07abe0fcd4bd63ddaec0662b484ce82d2595da19745d91740d9f75db35705dc3749f897de4b99f0a7acfb0e1b7f8af00ba3ece7ddc8a2bdc636adac9cfb6a8f0579f90cb3bc08fb67ded1d1725f254aef1a346740dc368592b60f89401dae66bc04bd7a304ff7a637c827d5b69cbfdb36e6380a6d30d39ca15e1a6dc80bea695a3bfe66868c170a1a6b4311499d107b6cd90588a7a7f3989890ed3247f1a141897136f4ca0823c594a9c0686e777da4f06e20e559c5d22cd4f0866eb939e26579180dbea224b0e4bf30cbc9208b4c292702a7f98df102a3894e2c1354415165c2111076d8161d67355e36f7017261ff1f3282ddc8a89e2548b02c36862620bac24e920596b98fc6bcc5eb11da66817ed6c4b25d07699682fd5aa11afd25649b25b971b47943a2d70d893812e06cacffa0f55a2b60d229633426412dd53cef6aa40ebb2ff75f38ee88c82255a9452a8dc3c35fb5b3d1e095238b8b9779b21238fdfc01a5f84031f4b9073e67e4d0379f973015fd8611d0620ae5e396bb3f78bc36afab0eed303befeb9ffca86e992c4b8cc9b995d36c5769f4c0dae4510a299dcf7de345c3adf25aa13a526508c435abb62c613c945bd00996310d072c174bb6f611ad2b1c0f198bca788fd9d62a843210d503ecf5234983af47ad92e7547114cb4341d019004859265614af4cd798e5dfcaa948798964ab97bbbcc679ea6a792c97d7519bdd351c644478c4dd08d3501e9c4a47a133bdc6e20052afb0d3928df1dd4388d0f27a8df4ef1a62709e635259e845e618cf65d2a34c6672fc62003956c11e8d23cb5df4fb394b08e8cb3a1d6191e4518ae81901c507999ab1300e1587bf7bc83a78a8c828b388bf61444f0155235322637a0a9240740f10de6a5ff9a4906d84db0d18f3675ce93a50e996a36cef3431fedaa648f54cbfdc4ec1f8ebe1aa8db76c5de9988bc2a7799cf0549482234f5aa446c8902dcf5224f5986015753837c6aa44011b0d812779b7d569b3fa3681c5695394166b2f23b1735a969be85f74ba5a76aa799601d14d4c2f5866d26c1b6b82632f7b0cd977aa148f8c039a75cd69dd447259bf00422d5065ee3f04111327c9c318000bea99c17d27c229601b3ce110aa082e4221b962b4e9cfa3ce852a4272bb16706177bbb29a910c7824e1b6dd28fcb8903619606460afde95a4b27ee307ac05710ed077b4f5a45c5280655179fedc049a3532f419e516f9bbb79818a3939d7c0bcb1904aeb95247aff557e1edfb9b18ab0d1fc7400da64f874722442c15c8f42947e65f261dda6c47fed1d05bcd7cc09027bf1a41e373eb455dfe203d5289afcc8f3f6ff9da79774a9ac1ee19a2dbe6676f339b84463be5a113075ab5f722a3c3b07dddd26008aa8cff95b4bc6be5cdde4d2d1348b0c5a21d7021423f26210743a911a89ec70b82de727b83e0caf63b1c747d58dcbb381fa03930646ae9e2f481a48017ef93a9ce7a065e0dd4059e3e1666c011d84ae1e1b97c74003c4dd43397401ff8671204792d5ae517972ea6ec4b02b8239ca27f182bb53b764bd1b5db8c3c5a02a2f51377849493ccf324e37854f8ec6c63173ed831a8a8dcdce843f29cf38c98e0f4404c9f0aa3df058603a6697caefa10c7d04388b20e51c29c27cbe63df16b75316b82cce048238e5a0e292a0bb3cc98d0df7c458a3878b0596481000b563b8cb22f8ceb42c91bbaa0216a9b88cd89ec6baa2d36e9980be06e2a8592c581877ecaedaf249b174781e3977dbc60c2e5a8583747db501a9d4ee9434952a6a27f00a9426fe1c38fbbb694445ecdd63b37cb0679b06ea7f71550c82a5dc9ca1ae457a53b455303fd4337807802b2eba342493812f447f82d78abba97426509fdf8375646b9f8488261763826b19b57fc3859b726e0e60f08448c06c087f5f142fa6a45fc4c5c5e9ed8ccf90f6fb08c47fe8df0c0ec0d1704a2ef2561ce548b5750091697215422db8dbd6b9c276237dbab2248b92b07935493d3a2dfde9aabff942f30465583327e6018d78529212e646f9b0bedc183c1b33c9fa16286d104afe7bc8818f570cfb14af44a97e9de1b8a0c466024c6dd14ba390f50f834f9736b6308e1e35064a582831d9a5709f494d9599a093da5c8703ac20645feb3ee08c9a1145d5a42d9669081cf1d0f6056098f02d358839714752e625c1bc397b9440ecfb3e83ba59b4dd896f1b1d990d1efe819de0c8018269766aed6c9b6aadfe0fc32fba05995200e5f75241891ac5c2edfeddd17d2a7e3101fc64cb739e4e92e89187c9ee4cb23f0ba62bc2743c5ff8f032db6feed263d3af1b224f56f291064f9d27d28b17323f56dedef85e8f95a05f7845114977e758414161b24c2472a489edb09f365f75b0496c1ec64e54f21146141755e56256043b0fd52cc31da306f55be07418b323f3f81bcac7ffab05a1969a485ea544820f3871c879369b0790cd766a94ebaf09d6236ce215d5c5528c5549525819c862f4a4b7227a3e582c6dc8153febba01efcf59b8eaba04b440a548a03702078c046d68a4c5482ca150ab21a351846c2a3a4ee9786154a2f4969616219892b6f7e02160a5a2acfdb6ac5a7a21e31885e9e8753e99852355bafc85c37ef2ec2cf1942d96153f63a671899aff395b1b9197a7508bcb796bedf3224b669b2750f3ed9d80aaf41ea801a141c619d154ca19065f4d63282ac0230f4dc1a1b3aa488a64371a36af0173af037e815b2b8941256c8e8c6ec8879d9b4ed5fdfb6f1577303f3e47a876ce37a9acd885e88b29824db07b004c90f2be662e733caf5221877016d0b8a41dbec3cc5e819a5cc188dbaaa86f498f6af838598640d0e1abe29a68194511b17064e46c1bd8cb2ccd4101b3b818826ca629858e9f0ea1f1b0cb45fb38115f047cba8737aa84cc73d618aa4e8719368d21064e4fbc6ed4c2b55c615a506f015d077ba1c7e9a5fcf528720cbab5ec3ba4e7c9612073fd7244ad5cf71158a8d6daaf3623712f8d40a1b3c88107a1af9babc6822c4d330af910a005042980508002de5b57e3fc57aeb3b17b7e40701a4a4188927b97b288ce72cf158b20ccd2764d6a015a3166d27cda788a8d47bc84b425aeda3da8a0cd1328ac915e047efbd851d00fefde036cddfe146a0a06c48df7a2ba5ac251fda2e3f44373ca3580230e4703ac08292b034bcde614f6891772896d022d42b853dd02e4a27301a1024ee412bcd2c2ff5562045b1dfb8f6e81e8052eead4f2d2cf0dffcdfb46031059b222b851da30a011df208a11d99c47ae1915f97d021addd0c85fc758e9cc70c1506a4ff7d38e71cec42a7284db68ada6770c802ea4c7c0006116d228aa36fddeea050f30c1ec3cfd5ca7eeb94a4824ee0e09d165fd9fd9834a55182f5e9c2b33aa6ac98f4566386c7f5be62c0bea86c3fd8a97df3efadbc23d9d7a5fbebe757673d0f1dbe7df585f20a93a50cf897d8d7ee55264286c8be21eb413fa4b0044e63feb5a77f45ac102b30793c002dee86b7cd2dceccbb7806620e899aa0e7ca38ac66edb779eb6c876a067aeaf53cbc9a3f96adcdac313aa148ec2a0d0263dc73b7b5eab20ced3019fd9798fc1ec79ba63b486ba2dd527375e72be64117cd05a3f9103e548cc258c3d586d06a732cd16a139643c6601e1945a02c0de83c71a1831a1cdc1483ea3dabe2fbe80ca63d4edb3e3d9d24184e6b9839e3ad1ddfa58619c44722a00b1d03cfeb27b9d9c095dc0e5152646a54fa93c31bde53e4d7dc4c496e70ed35ebb6a2d5e40384d57abccffb9955ee25c3b5dc9c6596e7a8646caa6209396783caaaa547043ef5a73b59c1138869344b2c4bb1dcf253c78b3a573161eb024dd1b014152909a02b843e7ddaad17b1ebaa8a9ef19b372c6c25906098e10149dcce30b255f16b7a839793a694d86cd73c604b369e33c4a2cba63e80cec7d68ded68ac9da782572515e7f16049feb44741655de98e6f4d958f19bcfd84643b73060d825b2219c9aefa94d5680a3ac8dadd87d73c5fd6dd9d142ec2dd720a8d628853908066c0b87c575c657ae9abfb21220b0bd7b04c7ba5104f1005a50984451ff29333ebdf7a2b3dbef5a4d3af0c5989514626dc7c70850b41aa613cc2c4e54e467583cbf34b959454213886acdff891f36a16009d18e0f6a2fe38782960f7f8b0b770ecaee0a28093d1684d3a306aca01da703511a8b603d26f7c74881d58e65bd7daad7dd02420948f363b6335bda44cccb58f6993e46efdb8eb2b2d3501469cbdb04fcf055b8490f19ba1b576864d76c54d8edd1072572b4f1972bd58b765883fc21b38628482867a89742ed708641a4e130bb02e36a6695db1b7ab8a1b835108e6480cfe4037d5872e84fb9a5ed044d6eb91eaeb1412c93a02f65e27ce40ad556f47deda3c7ea1ce237ad039acc2b8122c9494980c7180a159f4cc5166ff55973763214875bb952309c67508c14120b301fca33c28ccd70f63711461c44bc14fddec17d13e23cb11860585e0ad5086b71c712cceaf6a9748c67a754283c5cde87941040a8fb919eff85dfd32b58d598dafd5cc09aed6a535299964bad4c75429d35a3eb03844893f6ebe1fbfe761ca53d96c890b818628cb6dcc6f66d02f28dd2313af9d4a606ca8ac8b338f096dc35cad4ae0678861a8ed3b3c682782b7cb1115d819e43df31d29ca7d3b8ea1f6c9a657676769840c15b9d12fb0063ff9100ff5f6657c39a264bd22a168f1a5f8a4424ec2c8a0ff3b43255a2628d11880ade64ad74eaed6d2c2277c02e9f00cfaac3ec7fc7a1acd62d3c2403e7a640fd44b6757649cf912d628200175e9de12dd448c6658f29410c6e15442f15f60d73a796171fc39cc0de84f10fb656bae30490d238b88a3057949d9113820f359da38f457b0cb22598519b13f1744cfa60a675a91b95c23e7a5684f16e6f613709ae10ecbc214edd2208f39359c1966b6af3e16e6a6f4f56ac9dce36f6a020138c1c23445b15a8ea7851071eaff936b4ec5e1b082f1fc9073e7203a70b89e0cf5c438e56f68c773e3c71097cf912b608bb933f376202668b6a2276430c436eac5659e66c823ce188d9f87636c92d4bdda638db373f9ec8b94daa672390caa915c6bc3e3d2d8f2af95b5ec8ab1ca3b666226d824e58345881ead41cf82e9161a5455897bcbbb67baa84375c36eb82249e914b50ddbc3fda30c3d204b010c86ae6a0406334405d1a12ddf3f966a203a2c270ae805f5fd3a3f41f63aadaf00b8782350d7b304035031206f9c83711768f201478fe301f630ac7d01fc975f5ae9375e45123619dd1a6fa9f743796341dd9d5e602e2bc8e06557cd2301e7519a7687553c4cce66f72d7f3d8eff8436ae255c066c5e0e64769adbfff546c0dd86ae423e900433daf42cb6deb8e0b12ec97027e0b9cf9c50cf485ea1145ee5a6e3b1645d2aee5372ec12a8e79102632157ddc6198a4ce24e56553ff84b7df0fa7d7e5bc369694468b2ff79aa3de3d7d23c548a111eba20726e9bc4ac80079c71c952afbf2d54e40ac19469020068e9f1311d7cf90e615837f914cc13ca383171dfb119d90e128d6078439615450729b1822b9f9637f98ba84fe68b3a2b7aafc5820e6f0d1d2794f0446deea48415a4753e669c51c29afcb4e1f59a267f53eefde249441e5b6c4d5e2972906160de45c4534cb327043d53db08e6ed625c2b05d0aa75f9e024c4e693760e989c0bdff68fa86a7a2e7c5b67a73353eb74a87ea77655ebbe175697d499ab1b9a03ac011cbdac1bda97d672eddcd6a7e61ed751c7d5f5e8b75d05affb37f475b853172bce6b616f48ece833eb314d33cd3dd046b9ab482eaef31563939e6c8c0cac2a43476c0c795c92b24729b4082e093a596854413dc59be4738ca611aecf3ae3c007ed380c3e24759b5ce1af675b7c0f26341d5994f5c83775c4fbc89c61558b4767a390302df00b5cb0c0052ea8374aa31474505df09e81526b3c0ecc6b23f916452da80c5362e5c19bb2e9e78345f2af3248f20cd67b4caccf47e7c6579eb306179c810c46f0f79ef250a5913ac7b065a61bc2d52a942ecbc69e14eea42ad229fbf3b66237dcd97d8cac6453169c3e2abf288e3bd95ae3ca17cdad1057c67a15105a0ebc1bb57a76f7f65032e64e856a25751d82c9c70848853190e76cb6ed01ecc2be86488d167d95ef7865330490ffb1d7db7f0b6b62116ae1932d3a54df5167b7a2f5d860c96caa02846e8cd6eb674aeae71985f40e6d02131a3dd289fe9e85ba6ccd96ac6b3818c91b9625a52a2720e41f223afde8e9fbe5b485208713ab43a866923d7e8d1523208774632a7a54587903fabba39888fbf905b5967df61cfa07b833ceb0e3b7b6c897a87812eab8d37c1364d0511feb9abc35c6cf44b86a694bcd17041111960e9f2e149d5017deabb070992f04d4f713b20958db8e90780757833f09db25b4222dda08dd9dd8d8579ed63eb960aa1a64d4dc70b10305ebbc0b1d47932a386f6bbbc9b4a7296bde916596f09bcc30cd3b42b493a16c762cbc8f952976861647c32ae95d0c6617b82eabcd4eb6564df7e915a89ca8db07638fcdcdf0f719307e9ec4358ed3d7a18e1984498b881ecd48b035cbc1aa46db03aba5c8908c3b1f820140caa6a570828fa9c6d05ee16324df2fc2df285cfa58859ac37c5841541be49fde694c162b612d7a213e336165b8aa2062cf40b99751e1c56157320a69f12716fb697ef3b576188872f3a23ed969ed86c1a890d18d6f5f275cc31d3b81fa9021fe26c38bac4686649975f2283ead3e99e0c81bf369d39862c37505e08859967a98b45087ea40d7c503777543226d59362ea83591ea95223588a75724a42b22fbd5593fdca555e8a3b48a64420f1d05affe4641791518a82d27c26d36054fe1e479555560d98c68b81ec7e9dc188a393714f5f895568cc54acb510a02108df81c64a1b0d00d662674a7f13d137617c98465c1252dd553eb6c9fdc1bcafcb06e7ce9478775fa9dd102d50df7e0e13334a8c01c91baa5ae8d4d734d9635b4d8175150cfcb80f0970b8e5c94bd80a93faad2e25fd8f47d01c95e78ba589853da8befab70556c62dc3a452361ed74b113ddfbd420184fa29f91a7371246dc31e8e6ec098aabba4342a57c1eb298f945dded189e91b3c75d8f481eecdc8718a36b80962281e20bf8a1d65e6ec1a5ed451309e74a7a164cf7b9042926d3ba75039cf2cacbf2303adbfd9cf474e99ac4dacc7f05c863ca84ab39d70b06e15847d69d74b12a381242b879e74fc3aa0c4e5783178693ee54a4cad10c5f4849c242ecb5873447790ac1508611844f68836d02a24404609942ce29d0f2cda87a867d6c7d781ca1f0370f615dec39399eab919cbd7c743eb55793e66e9b656537c36e735327252491fbebe8f7a2c8e532b8be583215ba4bc1549ad674ff56d27eae49ad3ab99b29efdfce743dd440b2ce31dacec72d96c1e9aaa57454c1431ddf97dd40dda43c7c56d3299232fdd8599021dacaccae87d168d463b4818445a17054f134baacd1b50bfa72be3ec67d64055aee3ec8c822e28762052b70ff41ac2a0cb8c4862bac675d562d80b45411c1d566936e1c749a9ae4cefa4f7804fddce9a50845d4feee357b1c9491664440f19f4ea5430631c55914a674ece593ef2b273d1ded14eae04318762a7fe7fda2c6d04b30b708a962d302975a0a8b1b2cc21b17fe925b47cc0bfe556cd4ea95e55e235ce75934b799f1eee7ce35c8f09f9d71e4ef47814aee0daa33c59723ec3570c0a2279eff46865ed23d5ea1d7f575a84a78db7cf09c15adb94cacb5b486f23ea002a2d323a1d22208e6b998453a9d060f195cd7dc37f4d1a643978a3a8db4b1a2d8455ef923cd83c89b3c02ad7b4816feaa4dff0ca506d6d2dc49216335e35f81248f12657fb65646d6a6cc04fd51accafdcd95d5e44e3ef7b75886bca08de66f9b0f6e1b5e3170c64f627750c68210810a6d15c8d8fb95a0af0f6132f423d9dc82a1d3ddf577548cb45864a58aa204a82f6ef8c5b69e73fd127ff00775eaba9ae00e6d569eb6889f22a490a3740d33b5e96e4cf5847404fa7d6d7fd5f9a1e93ea3b7cfc45fee3d2cffde987394a49c8005b5342fac1d7f8af286b2a0bdcf319f35113b3f49566e0ca8168b5c9c7bf53baf707636bdae01bfdf94ca42cb512fab01717f61b372701f6a01895e2665b13f7bff2388914e8813897bc41bdf8fbee1c47a4ea4da127bffa5845e19766ab758137397219ca434c77d899ff3313ab3f7f5aa072df7c0fc76fbcefa54d36d88b990ed03adac1225cea0b109748ae4aebad56acc83168a2365ef97aa36844bb8bbe2ec0ef0d6519604afab83b2f7e19a882e9dbefe93d30d2b231f4383f2990947c159b01cc16f36a955fdf0d2511aff0ba038f6ee9db8a5a83a137687c28348a0691bb2b4e8fbac450b8e025faeb03f2b5c4f7f6131cb01dd9ee4512ffe1585ef2628bf2b7b1911a5e30a8338add4f04602bce6949db257dc6efe7ba11887aa2b321b3c355b35b8dbc954322e25f3b87a2ea5ee8ee8a13077f662a14505ae6f707ea0bd08962fb8065f7003298ef5b3b0f0080d2bc515a6cf7ed47948c61cfda85fff4d3bf4f9baf3f04c8fcba03d6f01049481e81e049cf6816b97052165a90d42750e5a6ff2d8f3221963744e7f95b281acbbbcbcaf2db0ca1716c08e4a43f338d3d61248901574cfcd37dde0f8cb17d3daf638a8cf0419a0dae251d70af90eac2eca9b4eadba6bd58d5793129ff305bc491e41085be47aedcdc01623497e72b967fd3d35a9c7b5e267e4fc488fda1f986ee5ec29eff5d9c804594af82ff3cf900046c06fe099ce8ff1bf9fd48019154bd79c3c4cc88650475bb76c85b94733d2015e43e1b3e14898a7d7202d6f047d1d9ea3592b12044df3a160a2abb7a6a5336fc6ef4be79383e082095c11ce3f83983ebc846e738573d5cee53d1bc905647aded8ed4ec38384e70d71bf1950be84abb6378aff14ce38cb6baae4bd8770e494f71e829143cb879901173b0aaf18180093524c6e88b07153c2c72a72a56624754ba33d270f204a3b19c67c1395365931038fa8915f282529b671fb40942a5c3b66508222a89c48ade79e5052dcbcf72ba6cf5e68af6aa76725f7e007409c2a7fd0c766decff13db474cfd3743356fa67453f41510f9935eaba64d2727b7bb6f3c699c156ba45df4f1485d1153ac49f5d130df31ab82608e8b07af0a647924a36f88249010a35c921709c9cbdd9e8d992b96e8d161ebd1c9920a7b0832a00cf26578a6a8c926b6976f97a289dd9adbf05ee0d496e8b177984554c2b4b0115087d69227966587c086b5178bedbf9b055001429ab80fbd17b00d40a2044a9040416bb065b868cab16ea3929655a61a0c6669990cdbec401a88f35647813eb9b2ff7fa488680936008344f0b8cc2dc14bde9cd26c4e6fedb4741bb8e637ce28d679b19f232dbe35b757cfaaa4982d13a03b51947e19d7cce1da778cb71b759173f0f74fcd4a18a0b84549dcf6329d131bd7cf84fb8a559e6e203807eeb680058dc3c8ec600b19d122605168929cd63f59ecab7b90af3f78c42a2bbf965afe9eec6eab0f856149d9d756443552363a326832d97c05e6f5ee80188f5f8c64637f822ea0f19b4b977d62f22db6959b7f98dbfc16d9559adc67c4e2df1993ee2e031d17b6f05f2bfc1ea6c8ac1e184528112316ecce59508c4f2c61911df06162c76d64eb66182f500e91f2df3941c18b52a4d645578ad6356478ad41dd7594bbaab73d5a0e3e8719e29b8df2c5759abc6b18bfaa3f91646983ea4822f86640abb2ac22022943b2837f7135b6d4c0d6794c96547fbf52573f2497f0d6f6285f2510c46a9f47baff5875d092f51727e7722a07d06040921d813b28c791a336b65100442583a1a0cb4e57dcbc2c9ed2061a3aacc251c1e324df52c8e357a986400c736f871d91c335a03dd336c2b77ebb9782e96fe4ba5491ae81fbd3f698302844b179a1ff984f46c00c99caf3ae9aef84c7c1ec54159bae578c989cf9e7d5dc610f0a97bd6819bf3284981f21c378a81a27994690cc67fff019be1417d5fa451a7a3075a980c94d612930303b145c2be66466d6bed4d75f0480ef5e9a15c9165bd3b4ef1d9382d65f3563315c6b4d77984531398d276619d43a61d88f0a0839b0fbb90ea4bf72638d31665659e03e46ba765645a893f204f0632f421376e37b2403e2ab1777141ee832759326ebb7704d89581ebaff79759c45f8afee0215fb9a90942816225f04b54e056e1b98542872e79b2522e2362b06aae888128d8b796e2bf9017b7919dd3f4e2f6dbbd1632b601c6fff06d74db2ba99d687376904331908e61f7d4cf59b8a48d5e844913bdce6b6c0f64718c32df5e6d9411c005a0f010596e6754a1e1a83acb23f2c578a8130089d5684cb94cf0c2c01db7195ea1a3213528f9f15947f791b18ca999e5634a1c81324b63f1a0d3b26817a4278118e39e7a6b66875803ba2a564e1224b921cb0cda181f643117028d8f98ca6797b9a86786ab099baffd5d06479c6e9996eba125c6500b6f4693d8a0488518b586558448e4df067840d902a85467e963b8dee44e4f8a1654a845cb7c5464c996a2f9357f0911b3db4dbee59997f52637b2645467e7eb4e1169ec84623a9f1e53abb51116d763e68c37ec4a309362973185d19d7c1c7d89147713bbd6b0f767d284a499bacdc01ccc42c5d898241836d5489ac90273e12e99f1b658ee4898028d098d4561a3adce816352dd95b9e438ba2b58240079897f138b1c2abcbc48887df935e6dc51174f675fcac87068141bb80197b7b810125a8a8939c64bae0cd1d1360f54510c2413d0c2fa2805e6ee78d9e3b8cd0bf4756e70941de742111ff194618f0858ba5a7a3cdf1ce3f958d5ce848b8e6df7962d8b52d658b721b26527cb6d4b8f24eed8b34f072aee97d766e2e9f8e824dc86353108d9b480802e18d48ed9c0dc64c5a9af8d5c3245d184ed0e18991a110c1ed082fd817773d921a62cea898e91dbe54605bd96f819f960f74bd46b081edb9f61f8a371befbeaaa9488e0a1beef96b427e3066c449af573d1c149407b3957d57980d35c2da1e7222cae4df0d554d3781d6b9ed91e9d6e61e7974b149b0e37b2e51b61d099620d9f2c02bad8bfb442449186583ad1afc0505314699f50d678613d30459301ec058a270cc556eaae885b5b691555755546b51f089cc36f79fa3addb115b749109f45a046bb1a324298b6a00209583995028940d4c3077801607433958d654b1036f0c6902e1a62d6b9f85fe78f7515786f7a1837754b70b722f9eec283685a2856da9e42ba473b12d0625acde91595e039450141e9f1edbf4513998c8ed9fae32384a951bf276140b459219e9d02b2e2094991c4f7ed4b96c85dcb8d67cab33dd28430e93a60a49eae9a7a9e766fd1f84216cb0df544e49103ba7dbe825e3090325207a6a24652417fcd0bdca9bec93430bda6fcad498a95c43dcbbc0a0fd89e74733c9d5cb22f15c6c6982ac67a72d300a000142e1735488958b40211c06825e041a65262ebb63aa97ba91166e007d96682d0de25646f29a54c52064c081108d8077b5c99c63feda6b48ef4237d69244f10767d5c49b1f1c3a036f706d4c4306c7f10c7b0b5d4a0e2f01fb263b69fb67cb11d1fb9bd3097974482240f6a529b4a7b7e57b93c571a8b51653407db200483c0b158412860f5cfd3a63cf02ef5a03615046ad63f1de786dad4a736758cbc7128c9048e50e8f3c6f667a1def0d8183bdcf72975a9329ae3670dd7cea175872d4d28a20a35e92e4d28424771d4bce9e8e3eea88d75db2d080bae3238e8fae16c845af481dbaebb7e0322d082c7288c5eb9bca20fe8f6497b62e0b608758775b3d6bfa904a83bfc75ecaac33e79b0b4e08c5238fd445e5c79adaed8a0a4264442a9e5604267ab89ff05fb1b7f029ce0cfe3160de9f065ec419ed8fe29918470dff2ddf4d50c8fbe2bda45187aad6f7fa4945aafd4ab0d63c9b52c27babe0f31445d4285506b2db6d66f89abdb8bb383f7bec0debf165f9bb35cbb04e76fc9672d687fc80292ea679be50816f3fdaac520b697c907929890ee2d7d2068fb6ca55aeb83a34e25754114d25aedbd388b3380d0f4431024914aa53014c5eabb4d5f87b3179f5629d5b55e55aad2bd943c456b71a8f32ad43a60e6ebbc91b1eaaaac4ae52aaaaae38ba65a6b133551eb7276c0641a75660ca14f133563087d0386c2c0c0c0d030a6c6c4c4c4d4d710fac2c058181818878181a9a2cb0964fb6985d271c34cdda854ee30ee241a850725cf94088e2eab1479c266e8cccccc0c955165c89021a3badce572b97c869d3163c60cfbf7ffff6697b3037b66a6541aa96ad4a115c66fa85ae9a8461f1f8c18b3929161f9cb8a45b6c8197a4d335ee260f6cbf7cbab9446a9c494bbb5a5c5511b7f77ff36c6511bd52802f5188d67445194e11281309ea1f56b4d6aecff8202ed7e31d662b97293fa4dcd0042fb7b097e9906beadd6a8d33275648832a4d02b33f4bdf56a65ddc1ab2f91cb05d2195eaf0c19325c2ed78c193344d8a6ff224992ba2c4b1a33d05e9ee27677777777777777771f2f5a682fff9f24c9b2a44183c6ebf5a2a1a1a941966559d21069d000af9b26b5a1ef618d1a35461fce81e86e6e1a2f7dc3aca9a9b161c3067843dbd8d88036c4b083d7cc4a87eda0031b1b1c38ac55a1e66ed8cc2042530b7358c536a2cda81302407477778b2fc6e5b538448a85f61206f3c0830f3ec89163d4d1513f9713c8c601136710a14f7106113870e048e1c081c281a3d6b8d703e042fabaf9d20bfb1078e41e945a9c989ad93d7a7ca26b076d41cff7566bb38335901e842b509cbc57a038d8afb5575ce1650acd8205e80a14a76efab2c7d08648491791e756f29b19ec87e9c5d67e26596c2fb6a10bb4f65e4b7ad0da7b2d75d1b40de92dc1a0c610e471ce39e79cad2cb1b3077272ce3967725f18746016fb36d9fe05a843636cd954894d89c608628775ac3fc293ca43d5a1f793a54ad95e81e041099595deff8795795d4223a043969f2d665650d96eeb96318711fcde4a2291de07dda407b241f2044f1776fdc00d3e251a43c90ebddaff4820bb922dd89d4bd2d2107a0b56d4fd383ab272f4e3c84a787361dbc12a04115784186765d4967ecb1dc541854014022e84dc1e004f08b810725a84a7bbfbf8cc67db6f3ec3e23e2b10bce5a9c24ad4798f78245a118fc4a33d16f11ef1483cea85baa07d9f0a3580e238a906d24842241e484224a14daa02d2484224a12d5b2c5fae93d76d5865fbe77bedcd38b48e6dc5d65a7cafbbfd4bdaf71beab638db3dfcdeebd7babbf5fb5b803183decd06af28427d73baa934a8fe6e6b60efcbe8621a61e499987f6e3209f479737343733621c0154a26c855f2551dc829148b24d3d0ded708a65439bab22f7ef180b30cfaa43c5cee13f2f17c783cde0a2bf078bc15783ccaa38992898c743bde1e81e2dc374352a906084ae12b0495640a451a1d51eecaee416beaa766ec0b8b2394d1e50584cb0b182298e299e979fd8b7ead404740023f4c3f78d046b113b4a6117e50268c4e344dcedcdbf67b27f1cbb9f7e51a641087aa21a44fca03792bbc7ea6f6f07837b0d30d19c4187a010d6100218613274e98cc006ed9228444122d608f9f9081b60657bbd85efb5fce47b6ffc4b65fcb5353d9f63f2bb6f5c7b6acf78215db0fafadb5da1e4617d7ea98bc98de8c367dd2b373a18f3a18e7efe13d8cdcc4375faf0f03671a046b78e0c87d1bf4b706594bb3b53d73bbdd7af4b865ac833ee94d54c110438020d86c3ef8005ad95de9ea10f8a221bd221e2e76f8425f21b5a2bfcdc28d1de5e8d57516aafb5f6da2b21fa4dda9b7b5a2417d437114406decdb0781ca16506bacd12a06262bdbdefcd8e9b74de89ad81ba4a9b5d5bfd2f010210b94da501cf57d5ffcdd7bedfdcf664a29a5f4fb9efa83abfa325d21d0f4e9574102bd5842a74b9b160531028c20434f90c092141530619a42bf34a9a2439b298bd634220dfea09ad098062854d0a353410c4e74b869910d8c15cc000b2c5222d0a44d8b6c556488a288cd09120816d99e8020088260945dea0b5b939b2d88cf67a5c56c070fc81045ab362d8a414b119af72fd3c8100cb722b078a1c74d8b8ab0925ab1983c014448089cc0010a1323447cd1c5c5810950b36ad841c70cf1c8d400c40b4c13deaa86279f6ac92ca606dc4b6ac9104c0d2f784135c9a96ac8023cd15235ccc03484aa618c926692238189d149cb30be18b133d9607219c26924a393dccb902822f1e312050c91301a894a4e78a20d2f20dd76a10dbb11ecb125d0062f4a240ced6c18233412c1cd4809502434b119f1c144c2113dd508122f55af8ca0d91a0a1a69e28504247a46a800493062c89fc616983b131e488193a01e0d8844c9c938cbce5ac8200f4581d16c5a34a4c376d9b468688814580c8e7a4214c68f8f8eb1f184b144aa041a65c5a9091da3a50623805d25ab9b4d4f1e38d7ac4d896cc06475bb10e3a4050b235014edb4c94911142768d5342eb67515a18b68db9a76e3116f7ff461ee5bb2744db40c28763efca1101efb4a24316f7f67c863f8f54602f3f677a2784cc411796c8ad14e959d238fbd94ad5c2251bd69cbb6262da62ba69d86d27353205dc22807a567db3f9d4e32466474d8aa950c1214cac7ddd547476decb3743413cf6336b67d931697fd6cb64fd34e8f40e7ee2ea5c56322500f684b108f893d1e43f90415f158ebbabc7d14c9ba42b2766e6692a5c3892daebcfd1d4fbd7cfe4bb2aeb84b79a6b68e9cdea1edd8766eb40ada4ecd63635964db11f2187e9dda2dd4ad43ab70922acf479527ad22cab6b40a229d9b47be03aa0d519cf05f6e7eee86a9230b16b8312db29d7458494223090df3aa87a9ca560a2b0ec4c43c909c160aaa1760ca560a3039aa0792533face30fd5c33c1d538829612b185245a2523d46f09f9f23457ae07682dcb49f1a7576686edaaf752768a7564375c20f2b53fdbd2a84b7a05d51b55d1f45dbf57768e09f50beada928c4fcea57e50b314072bc3ccd5d8d807427b8401f99766eb2748eb15f9e1327648832029d157c751e3b4d3bd691dd77876669152a11f498b9ebc3a0626274453d6bd479793cbe0e2bdac5013d4a651fa5b2d4532a437d0f1b92e70c914c9127b83315dbb67f479b0a98a7e32f6405cae91daec7c4542b99ac8362fede181246755b5826b35aa206d2e737dbef7f8eb85d7b76f51608d1366d010f5b726cda02255cec96cb895777779ffcd547977d8e761728670434a526f9a93b41be43a338778badd6a85381726ec2ec2b3490d18c0c17a35422bc5dfd0e9161ba600e50457363fc7ad4d1f185c69f7ff481ff8e08b82302549f69beb9e69cb3cfb89c19d8f791f8f5814bd0e59a31ea549fa34a6be92efe30a2d7cac2dda68e2fb48f5b0aed0a642351fd2d479a9bf57a8def66cca8a26b059aa50382018bb869bf1c757ee6a67dcbdabdecd3b483c2f3b2edafc0b34290157a3c56b75de99e9599edac4c66666b8cac2ce6fdb1ceca60de63b0248ced7f7b56f5eee16db3745cfcd4da92182cd9b7acb521d79096f9f198cdb62f73c4653e576482f4fbf06c8daaac3e47acddf6f24909f4b665ab1779ac1dc9523d65e9dcdddd64ed606aec67152659476eda5b56a0dc0b133fdbf675fe6e569f231f9db93d86d4b666f5332bbbff32ab950ccda883eae12558a08eb131a0b7e9471f16b0638ce152471f2ee37f8fdf5317144da97d5fbb99ff561f9f23232239a3497124dde555c5d0ce6300d8f659575c5681722c2ddb7ee82c13e8730c725e298e636dd731688fb497e8b16fd7d187eba64fea05affa1c79ac05d3e126c5a1b00aa4dbf6665b4abd78d1d4802107438ea686b57687666531a5e6c0b54427f9a138f78774b6c6c6053db24dbb9ae4869a8496a4c685ffcecb33bc61fbdb325f9c0bc1cfb67fc99fb08612a23895daf89be208c3aea30cbb8e43760d43ecedfa1efb0e745c48e821385d8ec7c04d6d9ee65a9dc45fef0a8b3ee917b896082708f4501bfb4e923b4709f4597d74748b0c43a46cfb75088ee2a09e6ed9f58e5c566118b235f6fd537f561f2d5b7c172b300c09b1eb5b27bb7e856168db28bb7eaa3c2b0cb86d5fbc4186dc3e3fba65f7d9dcaca832ef4c6f5fe000e0291713fd73e4a99fed22151a55c962ca92025551953ebd231f9d9b51b4ea61fea43a05f0e814b0ab3e3a2a3cdb7a0c45a4a6e348d37d56a0dccc0cf449a19881b6068ad9a61e336531262c541653eed46c8d7d180d4659056d8cbd43731d51056ddbaf40398a53daf6593a2bb32cddc9d26d7b7eb65d7535d8a8036e0f461d5005f31468074356209dadb1af222b9091ad09758875f4714bd2ebb0a20d300eb9597f8ce272c273cf9efd753c8fa11e488722e97607ca798ca43b65e4b17ce4b1d42e4556a02915a84a053272b3021db909b4ab40392374287ecc9b5ebf3ca53bf2bb602cdb7ffc2c83ed8fb7d8fe2bd23f86f4579152b67feec9318af06d5c7a79defffe449a484dbe90e7bf6a6cb13cb1947dd21b797eb35dbf449ea34d05186edd5284d3cfae7f7eb60fe70f24956e28da132aa5828959c9b05a33325c3ee3c992c6abd2d4e0c0acb1d1c10d1b00e0a03097eaa3e379ecac40b9ead3b3329c1c0f0f0f0c393a8f519f1def8ac77cb478acf2788c16f9f47c66f8c9d519826c5b99d8679d61761b4114fbac331c01ca55a0291ec334d836c9adeed083db1e39cfb847ae87d12d9321e042c0b90bee1fc618e310723433095d4e1c6377d1ddd5449fe0adb55a960e2bf468dbf541f7b18416ea46cdca121cda758cb2ab639142eb3ff104152a565881719887b5948ca2e06f7b89711f2851caaf6714073fede5f2d443ea8cdad8c721c647251cc509c1a31d8643614df3c208e9ebec80f7a5be32ac798dfd1ad6852ecad8f69411d65ccf20659ffa4a6ddb9f8135748f54b92bdb3e26551f28a17d66877514e1b46970d4c6fe074968fc1dcc284efd2a6ed867abb76d07b31c3768fff375dbbeee8f8e6870a72ab7ed5f5ca35663a8466d9f76073c2342facae16404fa5cadcc5babfd99bf01bbe9418013506800dd3a9cd8429f58f7bd153f92cb7f9f49f19263a923a74facd3f1324f12fac4ba7de4b173b5f3d889ab605dfeb03c53fbc4f74be589b76c5beac0f2cc41b6bd4fb3cfaee2b1bc9aa147fbbe0db77d5616faad9518569754d3a7ded80aa694527aadb5368f3a3f56617f83e06a754b6a2d058f7c5fad3b28c1f6fb6add41c957bf9c960f2495beaf5622b552582285e2f7d54a44a463257fcc35067b7b14b9d8922f2ac325cc7564f15bc96890447172988619643842a44ffdb9e62a4042ced5ae2420f409427112f8f47b509cefe97300236548f84fbb71f9043f89026e6144a5ecd8f403fa6d4bfffdd2bb607affd6014e9ffa1450af7a973f6badd6ac4c55ba606bfc05f5e189a4392892e684d44dba65229d3ed326937ea70909e1fe1ec5df8982581b9091c7288dc811dbdf44d24ea4c8f6f7223a2dfd29fda8079243a2b9e93d5880d91aff5379636b9ee6b8cdd69c4aaf7900fc698e07f9ac65446b5304fa96a4b3e2ced53e6bed0422c476e114a24aa7d1d2850843e3a7a412ac3f2a50a29dcb96ad5585dcf4afb9e9df22a27fbb0e689f8e829f404aa24f9a43f168474511d2d7699aedfce1ab47bff46854fed37a4071e4a77f002aa3d403aa6d1427c7ce0fa338dfce5bec6c4596429fec0c820e180758e8aa4d8f9d2f2f8ff9b77250b8dfb2e50924d88dadc9ff91a69bf96df982ed5c29ceca34ab6ebf08a995511dd2d7295231fc7b2ffda1046b4235212374064171832dec1509e2b641890d4a7c28c424fda19d795def58c20536e94be4296ed204483a0545bb0945838e25a4b5572a8160f84273e8695eb7d8332ebdf657fa1cbe25bf27e5b7af4915d8df7f4fbf1c20b903d79d0a2c802001cf56adb5466efaea4d0a8651e821fa869d4f907bac0c2c29ada9df43734f8e9babdc137ea41697d0b5d481e0bfce02f65cf9675bf630f36cbfb55ef086a05b6b85f6796357938308f8724029f4898d76a5426bfcadd05be02c8e04bf91956110d47a6574710e0137079799c7e7f236486fbd29c8a59b8dbf9473d2dbdfdd0cea0eba2f6f9b86f4a94baf3d76a341ed02d32fa4cb0dcbb735a5c73aa5af2adc94a00122415278360645b86fa94862206f5c4e80de1ec2eb24d7421281f4296eb7a4ff4ccda2eea0bb6ad92626fad4f63589a400b9bf3fbf92247e6f2959cbf3fb48ba417b4378effdb1a31ad421e076efbd9706489fd4685b5dad43b3baa3967509c561df96b5d684c8b665fdf15aa321aab56a493bbf3563af3f75472d25406fc581a6cf7afb7eecedc24c2bab3ce2036ccd7d0daef4fd616b2e127dd69bf81db9ac005e73ff0a4db9b2effd6c56763fda0f9937186edf7b8df6fd74fbdef26e7a795084a16b075da76c9af320ac958ae605c2d0e5449fafdd44535ae3729212ddf4ead45a7a03d7cd7573dd5c37d7cd7573dd5c37d7cd7573dd5cb75a6badd5d64a29a594d22db0b5d65a6b79b8895ff6cdc620d01a7c436d30286abb9a7159e9f1bf3cf672932491da9ae48d9a73ced9b1cdb95cb98979dcc42d58ab4278cb3d41dcc49927f3f06c8ccbb3bb8290de5b5f98980185a443e88aa26de88f97b4802dbd14e1b4ef4e8490bece1dba9ddf52faf7de7befa5f75a6badb556948562898dc2325b71df7baf8cb6f39f62ecc80b89648add406b72ecc7c6121a3605666465e1e787e960472e133f3fec8ac76057dccc9f5f2461470e33b2301e4c8b9bd9ddddc28cdca4f77bf88b97309d9b39079b4213c5cd7b2f0d8e268a0d9c3e69686e345168701eab3b976ef75e7ac5bf7ffff64a7fef2892d4d6dc0fcfd26de79df3b3c2d83983ac25370c550e1b5959ebc76bf267ddfad91983276bc9ce5fa545fa73c60d6cd4a84da6b955a1b9b999ff0325f41780216a93ff8324740732ece0a138fef93bd8edfca5f2bc5bc8b0f3d9c1cecb1d3cdf9fb0dcce0fcbc1a61cedd2e70fc010c509dd468de2903e3fcd6de70773ceb1dacea53f633f3b3fa9a64f706752499ef647eed0b9d4245fca479d93b5a3cec9ea6c636d3a9260238b46bdb88ce127863d4f9de088fa10f51fea4554b699743da5dc7e58ddb5027d350e1ae6635a5bf5f8ed8ec446fe3b34f7ac22c19bf3a8137e7e9713adbbcfc318638ceff75fc7ffc8f39ba98079df726c42909b26d0dcb4e3f89574d1a7a70a6d89d51369e1cbe8f2e358ed98e3891669a8f2dcc06ca3dee544f34ecc73cf99971245318bd9e78acf4e4b6fac3e5674f8a748bb2a609e094126d45e483dbad0b67d138a6aae1d4c3b6a639d6c3bb4833e65662e9cfe175a29ac1ee6614a0eb4fc572fa38279a195828a032d2f91b05ef531af7a9a03132343561f5600ec48cb912d122a4fab84cab3ebf64d8389d620a857abbf30d712da59e44ecd03605f06019e0312d93ce642780cb37431774b2e05985795d567676b5250fd4a668689d8dc2422849b7687a6f397d3a3f18ce2d8f699b209c9cca2f85cb93243ac90294263d5e7889ad6b44b1b27d0a76977ff44e1b6adba7dae76aa4a714e3bdf6d6efa334d80bbf25c4ae893a533ed4c57bcc65691e6af446a14e712a1819a7686db35ad847e1a646617d50ac2d2b1742c1d4b7753e4897395c8d0d90ab22d912495c86ddbcf97b563f13c76595a58bd168ffd5690564fcba755c463a9d64feb482bc863ad0b34c528572357a3e745eba4300a65f2a026a630c6d5839a139d3d7b8c7bbe37ef644f619407b50e8cb67d2b1af515a84671dc666530f5e680cb419777ed3b9d469d70d314119bf8397b2944a7a2ecd03c669becd0eae803b5eb101c0e27ce199db48a28588aeec4ba7dd61c74dbfaad5e6f6da5b0a71c3b908eee29a870d433d38ec76ddc322e2bd07467fba8f70f51a4cc8f4c111f7ddf6566324e43cfe104ef78a9ef85413c36f6f814f1d828ce70a4ce10e4b116b62f923b42e10e6d0b21f1ad7e115d523f86a7173f45ee0851374deebb02f14e1eb76dab780cf5faa53c531be5529e15e8ca589e1f966705d2b22deac5f2ac405b76683a8fe1a73976a7e6260a45ea94ae55a01c2ebf7c79dc62bc1dc3736269c1c2c20223f5a851c725f595ece1ae24b4c8da91992d61e4b2edcbccec0b11975478dbe3a7bec8ec963e5a6c5bdaeea3a33e57509909342f0a2609f6d65a4b223d1541f08a9f982deee25ad15a2bfe0d631194d2b1883a2e6175a1eb5f4ae9856daa0a816f5adaf4b429fd7b161dd1760b5e37def553332f11db9b022fc662fe28a55483a452fe446b2dd5f7de7b29a525916492a9e24dcdbc4471d4b1a538d6b3e5dbb431c6263b0ec15834d028d4ad621436a1eb62124f17e78c743be76961c686132aa542046abb940a673b83c003dccc329b59933ea954aa0b133313f6ac4f1d7fe07030312f2753cc0aa7050e8763c1aec7c5155340d1dbf576bd5deded7a4c7a2b1956bed8f6f008d95e47b83d749904559c8705d68709ae35c3e3a6763323a3148a25ec908f33aae0bd6196a830758c302a1ce7b89309e59ae1eeee331e870587c3e15890693d2eae98028a1ead47ebd17ab45e96de93382c381c0ec702177a5c5c310514bd5eafd7ebf57abd2c3db2bcaad42d69dc1c0e87f3b7e16b4fe335e3e6eaf51a75f0bf2e4d8d8b2d09fc72cffa806455812672d3eb14eb537754291487ff51af8af3b0c00ac165c1d1a06054b61942c4009d9af87e16ebae5589c537e7312ece17831fbe994422914afc138a2fb52ec9f87edff75d9c67172fa95549ce39bf2a0d35714d02b625a9896918e09273ce58b060b93f4a6a557231be24f0cb405c4c02bf8cc51583e501bfa7914c43325e646c923e74ecb482d605dca41301dcecb19b796d93ced6b80c18aeb33a5bea74b92496461f4ef57612f62a206ef2138a2ff7852b8e45bc0f954251f4a1b0e4b8c9e822be8438f86b3561fa65e0aac260bbc93496f0b2337611e238afa24d251d3098e9f494b44d6248e280db67a85949b83f3fff807d7fa778b5d69a52adc0e3f178aa4a65f50709f3c995cc4f0946b0b25259714d6a105549051a419cf342181a53a9b5d6fa1bd1a6d15c89322f33eadc9761b5eabd31715ea5e2700d82e09120f72a7547bdc1c96ae76060cbfac363a54e28175bf2cc48023e785715d40f9ae00b15374522080e810f92273e478624a98190d9597b4aa8d842ac500a6ae881061f94e8b959a15ddfdaecd00f43f6696f3e39a725b239d59fd6c856b1bb1f8ef66979560bcc9f760bcfaeb7c767d7bfb3fb6343c13e2fed06ed7a6dbbfe7987ae931fb06c19995f8d3a32ab8f197556313fe4b0631e66d4898179d5a803a37adac4567d6ad451a502804a027563a3503d106d940f306c540f347a5424d4e4eee0c2dce21e537bfc3bf240c51e950c51c4434f2d2a4ad283a6425bf0da2412922c9b54630249d103a008090df9f1a893414841131b833665b36d5017db16a1e0886d534064dba743a60c10998a5202567fa56f502d9739e713740e62e7ff2bb918ac288981a5282915fbbcb18307f6dde1887d5f03fdecfb2b5a04c464dfa22023fbbe1e756e4d13b5169d60c9cef95f469d6c83c7459a92293b3f38c6ceef32ea647d7327dca4d061071bfca04382022fa4f0417c6ab3d2f2620d6b9f33263042071af62dd261b72f6dc8be3ffee78c23d65214260822072af6fdf0899b5338fb9cf162e7bff908d1ceaf8b7200ca363e40a194000436250822afdeabc430836cdf079dc00104fbfea7a5100125ba81c9be354536b6cfd4ce57ecfc9906538a6e08b273cd39d32e827a18e20a1229441ec8c95a76ce39e79c4fd03f3becfb64df209a0a233bbf8e1abb023082059844550be9ebb4bc7d29ed41da2fb2d4295596b4573b6b0de751fce6de13aad9845a506a96c74dbd7516da77cbfff42dfba60792d3f24f7dcb5a5ba2907a54a557d8aa10116183219838caf1717bc9810bf459bfd63c768a4236213c565b0748fde95348952d7cfa145ab83c41f5a8a739a9ff6a2ad267a489f4590b7fea5bf951f84fdfca65eb00a7d39b3ee712f5a97fc1f4a70792c3cae96aab42291245ae48176c0ff3655359a5425db0b25aa34fa49c7a97c25383a0d6ab1eee51b9350995599bfeb03ca9ae549e940aa93ce913607952295f79d227b93c41c0e56992a67dd69a267d466deefb136bb3321f4229d5bd94a74542c5a53ccd27a4ac2c08a5929aa4f2b42f205fc667a0977ed3592fed919bf73998a2dd2d6f7497293ed2a90225a2a34e09044190047e89f414a0447b02e067cb83c7a9e3f59a9949a5ec0d2abb215299486b6cac7eacf4f4edae64b616342905a969bf528b6db9ba7ff72d530fbbe16aadb5d65a6badd569a55ea97984aeef454cf19283299a7e85e930cd92a83dba4475944af8277d824aa14fc03f41d8d4b4260fa8ac46c0ca3ca0356e75d58819d25dc97720d4256876d7126654a7703025a713ebc5e1bfbc9a85e26831f1ae6d5fa17d6bd4e6f6dcbc5fb5f02a8fd6a35b73754a3562dd3fe17f95737feb5af9ea802598e4235397777179ea7b7f750a6236bb623bd9b687db3e31c563f67ba88ddfa6e4a0e89aab46358a9bb87a9381ca60b63a44717a288e13f4041476c3109e5fddea2d9f35f7e59acbb99c29477172d41faa4d9bb8e2886dcbb3eab6bfa88d3fcccaea13b4c6ff660beac4f69a0b43fbb06f98e6c90656e1dac6c35f64f7493a85126d37b9834768ff13f6a6997bdd622544a3e0af6f1427c7be4f00978132d267bdaf066d7d7f5ab250f7b9da970023b8a957d4e65af308ad539746c46c467368289eed5f7fb6a5449652fc97b4807df5e850f451b70e5d54b47ddfe1d75d77585b7555dcf47a6b6e9ade82a26911ff99a2ed5723d2fb579dc7783cd622a1fe07bb3e90edef413c26b3fdbde747a592e35bb4b8d1151ca6a8b95fd57ce631d1548260ca4d56165a0a116cfb33bf4aa257429c4671824e348a93633bca96a7dbb6dfab89f4e97ced42edb1b686f6c22dbd664b0fa2bdf0491880eff8fda3d9da4aeb4b89f6579e404012cdca44afb1f6dddaf0f16842f8b9f4211dc7f20422c41ec956a16aa8644df74539eb188900004010003315002028140c078482d1683049e33c997b14800c74923e7a5a361546931cc7711c0421638c21861843083088c80c0d1151100010d037a6ac0e00ce389c80d8af25de48408dd6d93cca2448dc2f1af12387edc5ef618981a2d6c2ae7dfeea3b32496cb4635c554306c80819734bc9114c4aadcc3a6c24c1008e25b40785d895674c135a1c721d41311a4623f008f6fc4155bf74663de7436d0a91e398501378dd30a857cebd422cb5631338cd198812e6326737afbbd611a9ea2266258209893be30815bb9b2569d87e03236a9508254824964f4092a4aa9bb83aaac4bace1fc8855338374392035617ad1c125d1be2fb6a62b956ab668b0285e43602dcd45e557030620fcdc0b7cc86402dee2d2fc7d92f0f92698929aedcd96cdaea79de14311d3a88e1d0db86160e560a6492882bda1bf0fb6e2880b8a14e754c84d4a3ba5bfcc83984c3e64224be8009c3b865d14b18c6a75c03c0e851f811597cf4e2f387d6cede61d3c97c656ed5c92dfb65da67b56ced785ae4f49ef60f9195ddbb09626bce2c44047f613c544c83f9227b9202e8ed3eef8d9b84464786aa458372b90c44a8749d7a70463f4f5918e04b839d6a7fca8f214315c001ab8c5d47928fe090049ab9e32977f11244b097da229e629f930342bfe6aab6b87c591205b8ecfa5b8b1954865a52a66c907ebc0430c3fa2fe4f21e9ac0428f0d66604f2bc6880162e3cdbff6d3de962db99ccf8af4de40ff5899a1d35f1ff0d022abfe780ff99b23bc748d46ffccfb99d27345debe6811cc2c65de1022ff995bb509233e5904692f1cf7863bdbb5bddd703c75196cd3c89e132b15938a90b1b2029b32b5315f8cf196c5547da0cd25671b860a220fe5e7e725a79c681b3fdfba832669f61b15f3b7a4f2d089f52d62dbc9bc78707727456e0393b71cca52620d77b5a8e4eabc7dec75481ce3afc88568f7c965dd6b1ad5496bfe3d5d06b93bc425a2cbb3a939bb965f38d0bca3d113f8c76bed7b5015fedd5e5f25955520a749e58a7c92410205f961f8c4e588fb32e530dbc3958533cee19d8440e77c6c0ae7cecb9a72618040ca0daa5b1aa0966066ec981b229a0ccefc1447e7a2be327abf7c1f3c06e0ae223be7162d2c4c9c00a27c2c5a41e73669c6df74a14be2c0e8f054a35b0ced6c8c7430db7524290ae7e6181d4b2544109219b8bac805bc91e180630f47744983b36c2e22b7af12a68802451675175cd30be47c11284c21fe8270e9e4682b9ebe373d30b872ec1777ee09e497fe4d11344e658444a33365b9a95cee3783fd6e39b7e80507192d6c975c7139b347a3a519c72ceb9a62da3edbe35843c0a0b96158b495b1e30e52b5457d5593a120d2fbee612a4606226b8dc7d4b511cc9894bdc51359a15bf5c55ab71d29b51bc90f2270d7722ccec8158797d4af5e267a00d08b894465caa8ce236d718b2c32dc6e65e78302bc7ac7e3302e5ad813ae34e55d7a816b95e2820942a9178e7d50d66f648c2c2ca34cdf259aa7067820b27f008812b2f2a90313da47c35cd576a77e52bcd52d6be80f0e8e59dfe4250d714f1e3c5b65333ef842b5884379d9c5837bced99a2db8e404436e11338cb6fa5edc1291b272cc38d7de4241461db4e3b8eb1365c5b404093de955ec78c064d25ab6f19d7dc061d3c8931cf7c08cc62ded67d2967bfdf9f3045cd49c7cdaaee063bd9d8e71b61de80077e11bb615a7bd7b5ed74ee9b43386b2aa739d73097e1f1a3e576358e962996fe3a0a6c8bba58ebd1f326b0a7a13b8fec19b4d9957e6557f082aa66ff1eca1b15e1dc2153f83650fced798a7909e4cc9facbea05e10abfebe400bec413ccc8c80e9e43825486472433f8ea263ed66cf4b2a75e7ab057cc3f0dcb5db360763b817acce92c7dd3426270872f04b0f3cf1b8ca5117dad0e4e1c4420aac73dee668574cd24acd7008f0b0a7087e6fa389ef5e190ebd2aea9c3a6de2669b35908f6266420cb215bb09e93c035e13b0306b63d796a9ab6d2f469760dee09eb369f75783ecca669b8470270f2f18101fa928905957abb426bd50eee187f7e09966b066d92ee144a2be71813ab5017b0e2040b97942cb9d92de224e71a862f320f5f4b3e65e882815b0588d58232ea226598bac54fc93938e3bb52cffb6250069e4b69adc1181a31125b6af522db12f94baeb3aee75cb20860b29d96bdf4d006931bc02a77312449230d8fdc4254fbfe9050e9aa4412d62b477f2e2fdadf79b821b90041c6250af362f82654e7c54f97475665e4a1aa6ff82fc314ea34ec9a10b814b125a445a0dc7645b16dbe36ba443c67b90637217ac5d488ae721b0c1a0e351a8c561ca701a97f936111614c5357e4cc0479e8d11f33fbf107666eec7ad63dfbc4ca611aa3c46e8be2f58bb2bef6fa63db3618225cd57a443c4225dc7b3b7dfe1eb494ed6d9bc892ff659174d8caa7ba42d9a649093bc1a76c4f6affffc2bd0c0f08664ceb057ce3331d5776b47d06f95682cfe3b8828510865d18ffefeff5766c19f0ef31808efef1d69a3bff0991f416aaadd8b8118a64b48038af5e5dd0550c6d493456b905091252d7dba3d350dcf8574a1fb068578e106f054690e92c127417162e50c9e554b1c9b55161c9afafd195d549b74b38ee72ad0bb46a72b43855d374ed4e5520492f20fa7234d44768429f2c94a8311accae148b8e9fd766d08745880a65265616dc41b14c341223aad687361f5f8fc17aaf86304e7807ac7d4c40bff94d3ef0685f77e9122b13bffbe5af2344c48c84e8cf4d668fb6c9c234343706be9754a407ecd9688b8d17d751a3a283e59b98cd5daf7f165546daa782c1e1d19641cbb95136833613431e33d0fc935814b5387c29efec15fe716da82736622efd9993cadfb0074333f28de6681adcdf557ed848a9b3d6546f4174f8df82ed90c1272211f589d3b95b4059ceb4e8b90184aa78bbb46b045f36db0300e676726959688ba66c05ea2b099b110ddf58590c4ab3c46e2324d91853ce4ec62d9b438f09470b0b6a502d40d6ae1b68346463daec9853ad54e3c2648374c4795af419db1c4ab2bd25a18eaa8464ad87f8a08443a21956caca5fe29e7122b308404802c9d1894a02adbd99baed4b9372ddcbe35c2da4fbf502b12602f6b8911476917a06de620af90970b9dbdfa38f374f100d64980c04dac4238e57bfeb0a270ee9565c15a09d5b2704b32c27b6cd3c1825669eda2f53c47a14d9344dee4e10ca2bb654089870d8159ad029f7964a428bbeba3d54fc423749864d3c977b884932e8f06f957b01018584ffdacab36f4e721073ef90b953dcad569ded1ee3d35ed856e8adb35b774c22b66d941c99ee80a46d4dc87f22aadceb7197079872efa3e9bd2d0b63ea575e5903a008186e41c8301ff79a11a7ce0d3f59871f8dfa832865d496b012bd56cb5aad80d88d82cf6aa848d1afc1e570cb2b7672a93dd5db0ec383f58d909ff6bb9622a6a2314a7130e24c57f825fff479f2fb688518a15a710d7d5b7a8174b0309c2f71eabdb5befc7301d6aece70fd2824f5c60b3a699e3e4bea2d1d37d3878442760a61ea1d560a2bf4d45b039b1804056cfa9bb4727424c79b669cf91ca4a8b7c00897a95c3c8320102455ea4504fccc9d7a634bebdd33f1e5a1a9775457baa8f9b5e3931fa6a12a364dbd07ab064472f85e9b7ad983ae23cd1e927b264adeea247f6e3618ed0d294cf8587266e5957eedcd66cc6b9de6d7957fa02aa2de90eb51f552706c211b2db861380986f12f5b07c9f7b1dc4aedfa22f5cc52db43e1765d2012301769286660d121565633830f859e46e9236b893ba33c38ed3757a9c0d133486e6db94fc569398825655b95e5357a014c6f31060c496a085631f25515c313f8749464478ed01f3d9910b5c6fde6659ddea8f802f77558f0346d12a43820cb03558dd240dde74bb542c14824b571206f58e93fc5ae32553e0eb13cb7fda62ebc54adecabbbc6ca76be5a387a4d109f250403056e615dd37a261d01af8c75b89e3c75f29bbcb84e720ea7676085a74fd893afe3debca9c8001d7ee7d298c64ccd1ab025fc5f090921d346e184f3cd94846412325a6adaa81767d305a81eb21448565a43ad97fd6021457db65f0e67d6016af7803c66cbd29a7bdc60db0bb2c87be0fe43f773a23debc5d2c920b3e9a2a2662f9c50c57acd48773ab6709582376cb29414cb2b8001164359d92d4ed28870bbeca4889046c95868763902b9dd4183f85833e67432e9e78ed044a995b52cc896d676c75244f24cf5cb06b4f92f271e8996f1db9b059017dd5d1ddda74da1864d67a17c400eee201b16e71bc6db76ac9ecbfaab5f9fa1356a35ee92710ebfd96aa51244435f002116a3860fc53a3beb339cb167fad2fdfb217fad647c54d3b5aac8d4b2bd3738e94852052d190046f3b5f094adcd61d32d2179e1049c1750f1427fd1787b9adeddfa94b9dfe1336be44788ac58b7a976c38b4ec0f5afd540acc55c84e51c77dc314f9e96809d6182ac7be7c0201696f0670e291c317d60df321b027e299591c7f590428887f85d7be7645a1116d480be7cb8edfa4aac5417c896cc54737e52d6d913574acc2a2359d1269e848fd298b639184e5ab319d6c67e7864e17acbb735ec15618e6a906d4195c00b477f51a1bc9229f8b59c36b454e29d84e76cae2dec6249710d00299b594b05b4d1677cbdb79164ffb9c3e24f888e465c4e7e62916b9d1efdd66ddd14c4f0ac5787e1bd7eeea8060693e39b716d2e6bc2812619acc763a94ed33d9a3107ffdf847e8ac58eab3a8343e460b2a54a6d5df95f6c4ca02e457e719829d238042d954b9d1d1247bcbf3e2beec99603521f73ca0aea7044bdd202722a7a65032830ad778c043aee467ddfe3b765eef871027994aea99b669d81211f0eadbea0c2400810d43d8fd57c4ad63360f7c62db28746c63b8288f091d18c76cd6ab85b0304f96e81171a6bdd6817977b3db48b2c810264c230dd8f30fb9d7ad0e731a7bbe7617a04f626656743a2b3d283c196a5df70f978521a1d72596fe2ee2e4143ade15e14967aef70a89e81cce482b1aee93ec6bca3c4cbb4fe8303a7191440f706a011c59042dd3072f34ab81b8a17ad9e40bb7d172c4a8478b87014c6efacafbef5cb19684381c689b60e8173222c0facd4ce259ae1cb416398360117c0e2f1449f86e0e30b60f64707ea35d580c7237d52bf79a0ea420f4240b75a3aa6843ad5eeec18f8fce043a6b253b1292094e208d9ebe6ec5889290aec4f284c360a1481afa25c38c58d02ffe191ade37c8aea6a83508506e92d9c043911cfdf898b63200348d9e34baae168a824e0fe9788f31236d2967e230e49b9a2218c98862e527291f70ffd1995aa1ae76661147c53864383eaab46385368c22a4469b81e304ec7155fb9c6f1c93f404d8eba3175c7885ef8832e81fe8ac27a8d2d791f72b3a8cf020d2d7e8198b1e0c77a5c6193aaf48fa68393b156f279f90289c5ae367bc350a0e936218fe5a90eb99646301e0d71afba7fe92dc6d1066e5054dcaaa48a79a6eacfd09d50c43154dddcd9d035374a06c91e7813f4b4da2deaa604c2d1170df6b8921206136bf6c16de81442beb668b0fd68625a97f37e24ab12a7f2a1af300e6c67a74620221020c95ba203efef5e68567e44bdcad23c4af504027c150033b9340bac1499346c9b847bbc61ee967b536c21701e239d296cc74dbede856d4e0f052d8bad18cdc2a83d1cffc326d1467bcb2d64c7b81e37b66c47d52f5261795f8aa9389279f514fde1ffaeb7f20fa06c72f293e5e1438ce088f9254fd104517eb448dbc22a4d73e1e2ab1405d386a941e82100f2a23ead060ec09dc44721df2ebd6c040818c65154e9c909197e00f6967b90a5f3f732990ba2d6952a4da27ba7c8a38bafcd0a914a721ea80dd33c07a128c2de5d4137633d4833ab927bd65fcaa9701eb420395f44b196886e5a9f4c408674c93854cc0fd2fa8ade5f27d501aaeb5c0e5a328dd30d199a820935e624a03a1fd38d72954a4c8573d7bd10818c54b9429b778bc1ee5ba634e26e04d7da1015cdc4e1da57e7eb7e06a3835d62df48359465f927c02083e6e422d369a29457ab2ae5fdf0efbfeb7e95024b18729f5e006c43c84d76a1710746fe8b75b28dc44c0793b288cb1b3e81e577801260b51f9edcd937ac073c85cbb87fa158791c038fa2f39720fd914f7e87414ed151272760f9e523c1171c0dfc50737dff0777369e3e4f77561f90ca97132cb7777c30198514fcd734018e8cf7442f012591803baad182770530ddd3bf1d0f9a2acd006323da393837524a5e02cf5ad952236cc825c5f458096ca8e6a6c2cf87990422dad39fa11fc1c76d205a293c8b064aa3e987668a3ac8c47069be50982741ce6f6a2683dba550c5e0b1886a11099f82c8cde1d3a4a17d080b401cb224334ae64f11bd0199c27806ab52d62d51de2f0cedac8863d1cd406c1a6f6a82fa10f64846dbec71117cc4513d0ce0c78c1a45bcd0b93b788355b030b9b56bbcb82b69041f73b9000151afa625f1902ffeb7e2e23274c1c4d2295c328d56e589536b54802e629026bb3b499df2e6fe958ab4e4ac012660c11225ef031b7f40befe3b13d5479aec02cf863d56182a182c7345e50803b05e840dcf03b8d135469f43c7b7014000083aa7de9ea236135fd9c46930953017cfcdc44efd1948ec1ea7741ca50cff6ac3384a16236a1af41527f26a3ae7631b44eab84b0191e14c8b49e8f34f15b8b828de7a097d567b98a602082cbacc22fd90a0619d46ddabbe33fc59da01a02eb12a0ae102e0a20ba993905c8444049e6ddd2d1e6c8d147e35d8f8e33ed87489b5b5ed280732a139b3cb7932bc32e07dcf8306383af8cf1747c55db0a90575d34b14325f8099220b2a9e43e11464230dc8fbb079730a35160b7b82e4199e158f6c09e27f82685e52788256c3e67bd2be185e56c60c83195dcd180620c5a7b7c94e521d2907e8fed840ccb695512dee894ce49f7bebaac2dece3e08ae80420205655bcc62fe5c68620c438b7225bba9b284b769180565a93c7389140257b5f7658338f17e85bfeb0805313c86a76c0023edfeb5874752834f04c022e188dfdc2604d76ca164b518eb4a09be17af9025a998190c37326b363c76d14902472515536b0d70b2bfa58832bb496dadb97b7f6c991d0e2ae049bfe52b37e3a4dc0ac8cd17b93eab5ddc65b1fcc092845bc8d41ccc59168aa03eaff56fa2e5e2b90cb488e9f8bed64b85225996242929c4d8b02fc515b69c776d2062049447d7c42cc9f0f3b28c46c6120d4c18a21945f2a7b21f9291802aa535a9b314715d0b189151a02353ee2bc78dd13a09a803d71bb2b6c1fbb0c422f4bdec3ace652709f4b52f6c2d804fe9934ec4caea0b88222ac1d1d9349a6ffa2b11a9c7ee92d5ed10a3f508317f335d58391a4827b13c475c87a91ff1004820d3b759d8f776de43c72e66899fd8919f9fdc0ac3e64fac13cf611b8c611d08051a74517b33649189af3bcb86884e0d20eee99e4fc78fa0b13c9e1db90e611cdf9dd99fa0281dc2a8a42cc248fe2a6c81c7b7830fb175c4ec004bd86b04719e3e28a7c651a870b975266c04156052aa78a8768d5d91dff5a3056f0eeb4e76a84e12bc729368c3793c924c99e7c422d59ae6f657a36671d41bb13a1e1c5dbb973e431afbd33a67932aa086b699f25ed4f3d2960586353e16dcde82caacb4ab2bb122dc1056c04ad9fa9afd6100b54a2a70799fd1ef5541679453115427d98e2e4151260c0d4f8f8b78e3971b61c8df8705c4a96ca57c329ed79878cfe21a8d2e78094d7c7e904b18dd6a0ec7dcec2972ff00b5117590c6d8fd1b6503e03208149397326fa0945127b7ed08412eb47926a75f40919650c1396464a0d833028ff4a73cc7b831a03dc6cf15b7872acde609284b88105b0f4ff732aa5b2997936e70fe37887139d9f94969a5afa865f12a26ddea14790f6c553cee62bcef16820dc0b08492b828c5f8d70db4a924a82922a4a902f0d3ecc6aa76634993d6bc900bb7081bd182d30250bdaec8314f5b489cc2c03372413d5ce9c1156299be30440795a25bd01873af6b72c2cb418ed29e2b9a62d2d1818dbaa2fb54346a074056d7b9aa3138f4acae5f199461e6bc2b1852168759fc408c206a99391aad25b4a0d1d89f0b884c9075a3ae44de0dee09cb5ef73755d67ba58b0e28564ee529cf2fcccae9ca84ea7ab5ba2d25d0f55c1e570f19b58ae2922e139713549a6f4b12091340905b69d603f515a3331855faf770e306ad31b456814bc4aa2fb7fc86f3fdc63590d334f3678cf45cd7dbff02ed842b38941f851525aa99713c4139b313850860cb96c29e60f5e253cf8080c019b0af96a16daaa8ccae962b566e1fb6506589c11edc4c440defb45d8c50a9506c46a61dbf3b000cbf9fe528d62d1fa2cb35d6845fc394406436066240afc735698fc1f27804ad041eae32a5f68e1ce7be0bac91d197b8179a87a354eb927ede33a8f1fb1ae93108cf203fd1d75e43e3983a96000a4e6d12cda967f14cf84138569f3fcdbdfb810d00e252054d368eb379afb51e670d3c0861c6fb53288384f0013da5156d1644ca3e4caf76e4d9fd27f44724128fd510dd771aed377b8cd24076d797d6977d7069f490c62a4fe283507dfe7e60ef47caa000fd9745af63f978490445353ac96ebbbad35e914d5c470ef61e1574730d5f0738808215ff48792735735527aee428ed9110bccdb9241831cd7180f7fa3d26cf3f58e4a3114e0e04ffc4ec8fac616e1582c99681795969f856a9605d632d2aceae08de95b446ad59acd1d0462968a1996c4849bc0244d9bd237f22792529d738cdb442c3d2bdc9033e7d397669225680d06a5c2e159358e7a3e5ac0dc10f6c3136d4af970fadb216bd620b9053a51365f9bc41fc1a96ca3ea37a67e36bd641c334c11c1384fbab00bbd0f120b8d64c629a203157922eb556ed753a4bc928d90c07579c1777b6ed1ff476fda84703d6151e64cb12e0908987376b29a6a36c59e9ee88d7dbf387ccf61c189929362c425a39663b9938044077648f8e8704e26e3ec3d82301dd964c3a072fbbee894108f97af6fb50c4aa923be449930bbc59aa044e5d6b8495ea36d8bca57a38197cf673b520559a5b55a1ae2fc6486c3105371c418a1311f092531b6a937f2ab26758a0359493c80642159e7e0576f64722d26d404ced0583e05939f026b15f5a32c5eab22078318b0af4695f46d6887994e31e340dd04beec9b3bacda4826135460e251aa2c3c49d592419a21f540e4922b273d3b0c4f803e6aec24a1fc3627cf6a8e286077bb5e8b4d6ed25b051009f4a21118796880f44c37ea364453a674473621bf9e4f6857ba044cf10c135a9da9e5b432983b791f7c43f6062ddc6e897c3d650f05028ccaa2a2107559e97317e55b4024f351e6ab555c3ece381ea3fcaef3f5637f77f90e54e6e8f6d93a17c3d79696a353a37d10bc4c4b0b9b08bc75ed142cceebbdd521ee1e9aea446fe27f6d62084f326aca89915727c40f931a91b5e49b54e070b50274f4e53725b69bd45486eaad11c93247642bf692bfc46ea164ecb3d23ecea38a529e5fbb7bfc8ad39b4111466a20304eb19c281e4be3e4bdc1bb7eb3f21e9d162cc1281954a48478d6ad61c5a20d3cdfa4f82f29de474eb07c82f446aee9c7ebe9bd9e5d2c57403d6228a0d5061e017202af5ff3f095e6d669d7bb875270426c2547a7369e70a20464eacb3749fdde8f06b8f079c4d64b23cff407d7f7dc3ff586f8bdd1dfd9922a1e400b297ef4ff607fb9f73a2ddf3e73714908add0c1dc4ee499776f95796aa374ccd5cdaaf070166510b9f958cb67b47fd20516ae95c23bd1e9fc52720094193abce9a663b3da97230d9f33289680e894fbc3d2751d4cac9f9a9cab52b4fd46f060d1fd248193c8c8e7f26ab96470370b7229b2d1b18ba765803dc19d765d86487a1c3003661cb17934d741bab1cef40832c8753b2547c4734c54ceed936060a6524a7c17e9202b4de48827b69c97c9a88901587853e725bd2392dcf4e2e8721e9e2e6d0df7199f4b829fe84ed0bdc0fc795c8b6dea5c98c9af43f774e5459218e7d8202e7f17bb83f5a3cfbdd01843c0a25756c3a3a5ab57d96c9812919f41ddda118a8d4beeed19142194bcaa87718b5582f4aed01dd00dc5c5c56c6f5fcca3cd27c7c1849d26e0279d975a8ddb2531ab8e315dec10543b3b8f8fa279ea545a45f38195ec399ef5d0530877279c917cc545411faad101641b8ce2bc391f6c0813122673a638b5684631c75f3f76daa12608f7dfb849df4a577ac1c6ea8d79f3aac83e9bb34c3b32273a3f7f8981fb773915b8288e2c448eab506f99299daa60054f3a9365e35ff0a37019021c7f57ed06a772671c1236b5cfae8ff4fe5338f24403a6ba844e6ec283ddb65d32eca7e9684d8d7aa522c7280c079380e6979b44272b3d28239795d07c07609fd0b03acc1e2a7d48903b8a19057de59957d3288ab8535646d72f7303c68f31da44ae6ed11a7bb348800a93e9dd72b34231a9df56059db0971bd44fa596709660e5b105f20c8bb5469cb48c6693319e4946bd9d3800bb585288b2da760fc6f913e8d36b22883c05ca5ac4988e089e56f2096e6fd5144905ee5802b3fdbeb45169052b93e95c01d30652f12fa0e2213c32bbde7cb96238e806dd8042e0d73a628389e807380ee4ae88d053341df2f5ee08bb13e23d5cf7311b7e254147dd0eec4200cf5e8d821d38b5100da8fabd0a2883f0f1ed69f9c54bbc358c93691b17f7828db86a47f9361bb10188f0a4b6688119b6f182e619d90dd608d3cc0656ae4911da7afff72d6c4f436d1e8445d839222efbfa99952e6ad2cab7c8a14a63f2e9b574f8795d103df16bfbf9ac979780c107ee956a075c7d700b143cb988916b53941a40b34c9a985876bc086cbdfaf2b14f670be0f0a53b01da7517b28831a86c4a844cca4cd5342dc1ad83399800bfeeb953c58d86f9b81e7f1ddd7b60b184176efc80dbff3f2202ee322db26032189238eead7c109a69793500768fb25d5d215e01800bed0a2e84b5f2bf4730452309b950464af5c039c77bf0f47e4ea01cb5c1f425acdb3e7df81b623bcd3ffd11425d85a9ab5ea6bd8ee16b3a046b9a2771bd01d730af7c567df57a4826493c84a20dd0f8c60f0a0d718e049bc066440095f5a20c4af7bb63d69b10d0299c382872254b5a9c600510850e0febc49c64336e8adbbbbca7fe845128ae8531cc911f19baf1e6bb23c762603a4bc2c4118e62d77c19cd03ce16de80d6c1883deb6340d6882db232f73b7bb2a9481487b8145f8709cecd0ae3ddffbdb4071a459b61b7dbe6f49f2d0805c583c11d696bff0758f0fe657dec7b09fd4e9a749e72f00826ce5dba309295e484bd99dc9442ba9a004f744f0bc321d3ca0901c917fa92e44f71e1ec1db3617920ec929aa49b716a8c951f43e3f1b6e2677eaec0927d702af1c898ec84b470921f0bc238dd5c61e88fd123a22355bec4afb3999314e8eba8ac5e21059f6ef3dd4d21ee87322b94d18be1a048302d59f9de5e490c0063b742b8f5e6e358fe106077efad85f07ff9dece0c8124f06e0086162f843a7b8e26a38acc6fb7f55477587355871174792b32c2101a5b83f441abb011eb0f5b6fd5156981123e91b979847e2396403b93186cddcc7f76fdade62c172ab9af09d38c1c4eb1487082a1e83234557a1a4433739efd3dc5fc2ac8648c8818435fcef26ffab9125e53305222f1216730aaf2dad5ffc16188ba6f0d418660f7ca24217ac6c45216d70fbe20aaab0ec64139d64afaaf1a0cbb629db610bc2e149bd57fb87ae2956ae737dcf1409b8c71e631cb6c8893f03a6403064c04f309b1436d75ae2932124d8c89b1496656acf03a9bcd7bd70c143c732adedcd87b1818e0f267cb04fe0c08d361b0bdf2a1f57c488fd21ee15394c2d76e9f08521b25600a32d69107fa579ec10476ad9e243c971a9325b23074bc9b5f2d5102c12563540458dfed40571c6d78d8b133f3ace04410bd2f641389c0942b890c616acf95f5336a96349e2a8e078e1dbe7be2bb6cba9c089abc044cb7d14b9e63748b3aa1ab6e91c834ce98d3b20c26fa557b4264cb046f0ffe76a1286f27c53ef5c664158cf02d0f2268487c224b250a6a4c58973dff16e64a404708dd6fe5cc06e21ae6495631cd4af389868c866e85cee848e04119011e9bbfd99ebe73554475d016368d3da67cef1bb1b5bb2cbaa9be4f8377d8cc236a1b5ea107eb990be70ea0d59c7def9ec84a8234a2a25cfcd90c4c36512bf8f748f5f3bd5dbbdb0a5a9945e087a133009fc0affa1233795773396866d0265dcb1606c7d4e42be3eb4e07df5d3a85b3ad6cb8efa68d8ed8ebbb31e105e5c428d0f342a719b080dee305a424b03b9cb9a244f371a2a0161ed1268b90dd24753a1095f70e9625c37737f4a3c03d02036633237e4ce3613cbf9d4797b5388a6e66f57323b6c0060bb963ae97264801d4cc35b411da9a7cb9a7a116b4ee2313c7386dc1c0d1e04f7bc14b3fe8522d7cdf797e678e5e5c97f72ab54b8c97a94d6f75c006e5eccc823ab6ccd2b8f4af211b2f586d56f6cac23ad47aa29b5e9b08f63b4535b1b377f568c612987fdea1a903ee4aba892a1b84aaa6b959401e56262a6b00bb3520404ab4a99f61337ba87744b5e4443ca76896c6180a7af9fede99101005d2017e420f341f11e61b462ef6c65fda1d1eecce3f0974ae57b3968ecd3cfe84b0857a8f84dae16af48b9057e506853fba7aa1fd98c66edae9ecf15fa6e5c88c13884374064b9e0e27ce68c0c35776cdf1382d43bceab37721fc846217910d6a2f4d1aa8f26171104590cfdd1c95d58c0ad652f73a02caf408ca33233156d9b49648a211167a55cba1f31d7374d551ce4ed56077fc0c51c5397ba89255741e2b143a618187989d47721ed99dd8178a9bb8faf1212260a706e3527029714824f451b42dd1625d3968e4794a7002808e3a67088f89a41980fcd7d7359724099cedfb2041fecdd45821083761c40db1a952dfbc92faba7287570e1e1c75df5641475054b15831df6e76eff74b509f74e04bb3a0a44fd61123047a275b34408c47ab8a977dbec524aa52a13d396ed5f6b2122f4ac5e592652b17883f543ea85b28deaa8b983ab5f77ce8b702c83226f8ff847653e00da4eddc03b935982b2c3690076c14f8e2dc086af2e6450080a80afbcb86b152bacd50702d2671684b45cdc442d5346105dde075558570efee1568a8ca6c39e72a62a8221e15ecf6257f357df51da5b83760b527b62db679968412b9902cf06830c697ce264c70e703a58bc34a08d8256b0808b90583b35c8d9e151b8a68169fb5f56de332117f2a8316e42d72aeb337d541294252c404ed039fe056eb904aff1260c01838c92e43ef5690012a0de8741d11973761809e8603f506b55d492abfa1071d4c0dea998d48e495841dc2bfa7854373053ece00a8fa780385cf69e07cba348dd835522206765fe2f8ea96c80367a0a27da7171990efb325b96984525f1d5ebc49aaccba347ebc5276d56b3955c780c3fe71a8d19a30c138d2f3de6f2be0db027d1a644af1d7952d4ee4ea270be3c20640300bc43154e303ba30df8fe60bc62f7f896ef69b5e364ad347346557cfced9dbae56c11d28edd67f49a557c99d8cf5ced7459e1c9bc805f07b1c722b3fd0284d30de49331120d9bd8ba857d4c5c6510476f672be32fd7e0198fdc2591041618e6220996924233bb54f9725eff8e4716ee8a3483829b9331e13ac6685c5587ed84e86c5107532a75693d0e1b60f3f1efbf1d88718722edc41039b09804512acc14aade699b874bad683e13d6dd9e8ffb9452020d3632d19742017bb6ba53c60144716ced0f487165ef1a2e97714f564f974e60c504ba8487d826be1caa2b853913b307bde83b31276a32bfa0438ad91b53bf6d89fc086c63ccc19599250f5bad9d65b838f71bc02725dc8b49c1331f87fe427e1321d96efe12ba28cc554da25c620cff19b48b712606847203433a141aeb15fe8ea1480481bbbe995ae81e3e6cf823f3b3190502b429902d5f8c619073a7c4e1cac71a0b3812984c6863175cdeac518e4c802b49939724cdd0e4b14c92d85571de24d76a35f1d49c54157589fb91c731d5125a8aa266aa5604464d363aff4bb3dcc03ada0eb38ed21ff60a15dadf01108d71469f51d987ce70a6667676724e20ebcafbc845a477b2c31b15dc102f615341d35d626b2f4d5a24d85f89f0df513c7492231939ed80a34264b335deb8a71997896395deb44d6d93feb9283e9260b2ec5d9ffedf76cac58d2633e9ee91bcfac793ca490ab129ab147ad244013f79f365daf410b096d35d5dac774a9b5aef832bd685c7e622b9d0251498c0366145cb692788d02615f7a01ab02492945dff2440451ad8385c08e33ec203b266677791b2317abfb4d2c4058f784d29d53a03c93a859b33809e453d888d907d10601432063a72d7c985f687518e8508cc2d55f67282db973d36c9f12082b3e0c80bfae1222768ed2a74f7e345e82e088400c917ad89a47322294e25de2f0066992a5e019954a55140ef6a622879a3916abe9b0746e5ed6a5c26e97fde25f5839b8063c0577990574d884718f3b214a03be692c147d748fe24831d509db26d41aeab244904d8da6a3ff8440df432e44bb2920465e0b5db645307e505005712ae492d5d76e8e7aeb7338684413e48df45449634970a0df47a081609f03385fa824a37e5b122db11bffa8ad08ed2faf42b566e8e356241dd24b7125236a435f893100e2fc066b3bb8da93511783b88c31a1437cc8c9f5e668f1c78b1eb1cf1d53889d15e450280a902c762626d8b4aa632f96d97d47bfe3e7929b346dc5cd5a3aac43a97be618b08c97801698bc9f018230a8dbd57a2211adedf465488c5116137551367b213ef3233a2eaca7bcc187aec439eb9448c9b3111f28a008769a6e722ea1773cc11e76c0f7e54550456a371d43a78768425a4459356ae4684c2be0441a99dc6ee30e0b9723ee68bf897d14d5eda2cc114b462ac9b8741aabd59ebcf0414fbcdedc94a5850328bf704854068f2cd9dba5b3329363e0bcb85ed2ad67677ea43d0a1c3bd241769595dbccf060a83f3b1f515d3d7c6e1e25459267537cac6b55cc775cba92e7aadac3f072593ae45edcbece9e0c63cf68b8ee150f96573c2af8ffffac8c5eb104aeabab64842d384fb95b38dae2b04e6c9a3107d19db06bc9220fbbff184eb657efc1eff379d43c4a3708d8260455e518e68fc9d0857454fecd162ed284460715ca9e590c9627ed23641497f63c82ae506500d4fd486000e28a507966f06f5d985da858e3863930d7ce8e73b0fb9e79789967f57b16917ee23da526c2e70dfefa69aee321b03c212586baa62130b849bb4ca38a81449859453390df5f92ecd6773524e26253862a0242262ace9243d4ada7449e7e1a1cf18a9f26cc5de3d8268a6cb58b559de77c9aa9e46311bbc6be679ce51d481051c6f0c0aa58e3b15815154c0cc3b49b93f68d5a6c0969af80e5c4479275228a97e1c5cc2faf3ec994d831ba99edbb071ad54ac39346f99dfc59b04cc97fe82eeb042ba744463a8db9e5d462a02dd61fe700384987bea0ea0922510094f7d2307c5a689dd876765279a572ab58273d25dc1a237c447142cbfb01551af5166d711b503509be46c46de6b94bea343507d338b35b39edeab7b8b6f21a055b1bf37c9b233cd44c76baf83c20b50168ce1011f784050413f64b34eb616d042ee217e40475f61605774565668d87f67fa105e92b0164c3e7085d9b4e48209ce3228f05f47910581bd9fa7b0f426f37afa8ad74df725ef6b4f87d89f36fe57c878394c0892c5eb2fa601996da653c4a008a9093180810af86f22cc10b827fa222041f139b510580a3156a1e9ab3c1b1b7271a0d8480ac9d4d0a65db9ee1fdf37661cdeb254fe2bbaf72d60ac65fe2f30370933c54352f7094ebb4cfb13ddea5ba152d6c37c411a4f730b9ef046211647cf17137ef9c1073a8f74d25581b18016497c3d6f1032be1b875b8f0524c0b098c004133d141958086799aa268a74582fb841bee43a0e5353975c885ded95bd88c7dfbc085c74264012a1b48f5ec0dd7490c2f5615f1a6f16ab229dce19da67132cdeec0c745a9e485a7cc35c1c8181e105875a818fc3c2329ea53099d09a2662b4bcb67f5f63e2951c5aa55d080652945f41f19fa51f3f588d0346bc0b89d782ff1c62eeec54cd4511cac8c2a2384db4d9d628ee1291d5b168e0820e239edd1f1a7dbe6001b318c380e497d1d1e2629922154cf9b250ded8386eb87622b0400d7a0fa08735fed450302bc7d8674790387b6e8b7dd00eca1809d92719dc1118256f7e80cf817e964989619ad55f0fc522861b07b4a3f23c28749e6b8bb892768a847991d401696170145a320a630d581ab72f941dee5cd48541a175411669eacfce6718c033269aa4e7eb16b2b4999864cfba1c0cd080f088cc1492841354308a8301254cc713d3b93e132be78f2037c451de7c81071a3f058eb8b02eeac4d632eb27348a7f08a3d37376172d6180c05fa0dc14e7be00ca844cc16bd92e25e722596fd21522aa2d2e86dab00ea875e48bddeba71b81619ef1dc2ba0c1b7cde2c852e77a13ae32422e632baba4f534af475dd5041994d76ec59fb44c82557678b546f0a3ad1f2ff462a9a34c6350b3fd7fc3e4a64aadfbb9478dd65c51b3c27e790db601c527ea28ec9d3bb8b9c7ba48bf1cb32e8eb08c5c5701855cd0edb5f65a68613b0a6b56bac8cce7018323ecedc9e98f33e69fa63c50a538659dfc975cb1cd69bdc9f8b6123501f1f3aa22cb1c600bac5383ed76f9b20cf8358a373e8c256607fd2c4ddb68d216792ecddae4285cfb5ca679918bddfeb6fa1493cfb66a8f82c231da0a30fc2ecb0c3fec5ac6df142545f4f55d9c6099df0516db6427791b4f5fdbbde60ab64c857a2e665707e976b3e8ccea5afcdafaf19ca524fa171dd4981904632cec4f4a934afe9c0429ebd43810031c69e18419158f82035d33b0b8b866df413a60750e36ecf351268948cb5369fe4a442553bb7f1c1ec162ea827272e824f25ffa9b1bdba4d4334030d0a78526b0275c9caa4daed40c2609700ce149b2f3b802e00a4aa63aae702702fe467be59fe0d8154cc6310d834de88157602cdaa051c245c59d401e583be6cf87c863c335a2abff43979cc88abfc3fc2ca5808157b623f502b4c5bc94f383001a7156458d560987625230350c158a1ff21470abef168a8e4918057723c1e8b87c563dd253032f5345ef2e614e9653cb849a66346952980dae17b152a42e62430c007cb34c5a5b06da66c0fcdd334806664f1bf08bbe910d7caf869a81ee4674d8e817062f6b89219968f9a00a5e070b8018bc163ca4d3a545ff203cf6cfda32c3f032b056a44c18a9424cc93c6946a581abde9066a5c4ded284b78bd564e13119867f996886714c8fe852240577066e76cd2718244b7187a98ca1d098fe2bcc66f0b9b53690716e58ac5f3172f41385f985d60ed868b597ef64edac924819d0e5c1251561965fe1c2fbfb241c8eda51043b310060f8ae2038affdbbbd63f78168d1f13a13041e8018c0a944b27bee5cbbdc29c617617adf8c5bf70846cd205f0b0f84bc10682c90d08f9ccb2db11535838377cea78ea0cfce3f75b22cbfe3ae490d584649c74f25a891c817b282be2e5cf567932415b982b2c37177bf7b3022869eb2e385d18a14293d5a4dc400d90560ac1be4b916aec2bde5077f0c60d04049e5bdf84c6b5a19b5034d23b66de0c5b2d5b66bddbd40548f3ea8659582f0288bfaa9e96cb91343188856ce29b2dba1682612a4cd198d5faeb8926c54d90b2ae84b78d86d520567aede7d0cda6b853b9a52abf2e7b21632952b1f669eaa8899bb0f2bce553710d8862d4d12132872fa15515b77c582826e4e80833dd38fef5ce4a1d6edee992ba973ac7da2ec57ed207eabe04e2c1fbcbc8d4620e522a97a829788fa7a3fb31f156fdd08e637915539d5e964c6f01d2701285701e84a2978a95979561f7cd8fc01262ff3a79dac992cd454d10a346827a72e5804fdb9a4f3c31abb961a4093f106ee6286e0ce88b0a30b9e5276af6b0d83e9a1e9f3d3f45e2f814b4e553730969f93867dcb14771acb32b5efcb0f71dc6083d215ebc2c5d1c8ac7d841a09d91b29d7592a075b05bbf3a0c851139209aa78ea8be2ee70135f95fc22bd13c11e19fe6f9d16cc3a7aa4c9e3ea48fda6e180c8f32ee065677639652a4914ccc31b7b33175121ac7a2ddd9b3315a40377f665b6737f91ed2dccb7325be3b6802c15dc6dc21fba49407068fee94c404dbc8d689dc697441d05627bc77d577787b4d9d0d8d8b9bd6eb47afdb12dd0b0696e1612d3080ee2b39fb66ac63bc7aa686805028ad9aaa158105175304b25167107958eaca96e31d6968ff2c89828e8639404d43fa49cf312c579299b984b2f859ec1cfa6bf40146b574d82034f830ba0933171bc48b18711315881288f7cd7715abdb352693c1216bdcc897055a8dc13152d4976c5de708d00c4960b348287aac807cc397711e9b8955206a90b5c3465885e18867c16e6dd629eca45f6ea13bdf6c667ccc823da54721e54a5d0b35fab9e354c0774f7b294f95873b5e22c0aec0a4bd328dfcacfa2801cdcccabcf6b9a9627d5085b6a81598ab0eb29ca94285f140f98bc8b51f0ad921021447d0616f90cd7e3a9d4a584b3e9408173bca5f987aa5b9c470e02709b5c462753f61d8ad7f76f20aa41660ff96a91681da68c22c77adf62d259160de286583a4ad5f12c3e53340ac96449091b356f5f33bffe8ebee028cd206cba365463d687be9b7255713845a9c190c842142a5da14634e2680359283029954b0abfbcb70e7aaf20a241cbb954ca4d9a0b389a5d36a9235405462e8956b56559a60ff4d38e98164dc0a9abdc3a0eb2937ce72275b810e99b289bde270e4374aee9946e8f3fd5d25f7237e46540e69e90fe9a2f6532f889d8f6bd2f416f3e05dfb86303f38c95013717aeee39a0bb54e37a4ead8e32e85a7bb5d14d4b2b893b9d6e15cfa6a7151beceeba0c6e0da8dccbb5ea8289f31cb1c33c712a2842d9ee64a6738d19c1f5607d23595d751e64873da754199d32f8a03276aeb00702b94a651c4766bfcfab73f9a8f56b3a21cf529ee4fc74c5d741ac856cd76cc8ee23b88385e1c2c3be4cc8fa9b10602b1f8f7d11cc0a4a498d2495bebb6d1cddb36ce2a3d90834481ca6542c9c888e74ded6550dd97aaf4db0c25b8f4f5ed80b701c5f777301239bc8aa1487eccf28392d8d5ea656d8b94d616bd0d87b6cd620cf03ea059504b1c3693c952a2fcb13339f73a69bf57fc8e6e67e9ed464831d7834c832e57390fafca28b336f46198c7233401753ebd7d147484e9255014e6e0b0d59df348926b67f1135d2190d482d8a6da0bf75b297c6602c1c2e18577b63226b4511298642a820b4a9aaeb0bd8af105ddd614358bfc36e0f78d66bc3ca28942052ae6608c9f4842df9deeb28b084cfb30670ee240bb99c56a9c8a4281d275ec5b3e636759c04f330db911ac15d43b8268d77fa396322396a6951064620bdb6774646f6c2d148b6e105c8c12fae432dfea290c31b5754a0371baef69d1fb0a1a179f801f232e67789e67965cd13aa590f44608d7c5b026d2cfe4fc2e33fb841060bf1de10432518c883343bdc256215e1ee02850a191621d8977bfbb57d5400f0d1de80d54330209e0b4cafbdd2da57c365ab2e98a7d1d97d39aa599b180f25e6010a131be53131f6fc706225f1a849e0fc3bd174615b94fbf0161d640be5ca351d0f2f94b44622075276d090c8fe7bd74764035d6f6d2cc9b480da52c2c4a5a5ebc34924619e59bb16530e3c28c0824fc7d740044c10dce255e0d9ac93b7a0fda1b4fd0730bc0ab04baca02af6db62eaefc7f858cb9ead4c018f3e45ba1cd11858795d676ce20544cc32f29b645cbe5bdc48b1561d7e22a6263a90ff94123dc6923ec2054d0846d934c8b15e5cf0524106647cd193dab797cfbabb8e2837f2b22198c6f73021e15bfa5b0ad0eae1c34aa6f33c2509ca5deaba5acbcb924a22dad7b893daf674b17fbb12ba9e595c412d5564e31ab8cd527a8ff893f082b48cca289ba53e606bed66382a4745a18fa1bc4b1118e2635344251179b10e9613264a8c19f45ecbad0d7d34203a2d5ee66a3b6801a97f22d01e253a8629960987e952f3669a666546cfa69a2822b82b2e6663705a90cc1fc0a1cb533724e90c6c388286410fb81c4a5e45e2d702f12c4f2342cb33fe3d9dea08403cde6d51da68044d9b0dda937287f611569d9012f4fca6218029a696ef1231bba668785f02ca00fd3885ff26338ffb8d0c2d99f5d362fba7652fea528a3c4ab91d4b873563cc68a37a034804fdca7fa44d8becae7e0d4c4625d9286ea561670e2043913a2b0f28cb1750bcab412e555a369bdd157c4503ba16ce2f5d009427c496e558c3a2d5e6e1d0fd489094518bc849055f4c295706efe1a84626eacba30adadaf30ddbb10178987ad742e7322a69e5acfa867bf8fef2aa7fbc6f71618e56558656413a6c93e771083279f0a9dda78c2110844833e3c8ed02d5d0ce3d93a4021f50f193857871512cd163540a12781114cced56ee3da179978a3365abf48013f3bf340e4e1b408c5c826dc1a4d359289931b47303499eae96062fa5a575e4129a37b0ff4aab43311b80d585b42e8d94d60800d226977322c51fd9a53da0314e726ce2068658c12d720ddd6892dec6c18ee7604973da54ecea4504572d72c105c7eb43204143253684aa831204bd1abc1d4cef47f0eb78279a4fde9e56d66e973febfd58b98e4c46a64a80646480e3552a0a21c5c1014fbed605620fc91a64f2ec8754ebdd82d4a093dc122d3a4a53ed9632efc467dff3ef32b264f26411f22b0909242eb352daf6a30cc630dde6573f42d4a991b7cf90a76ef0653590947e47fea4a2b04810cfcb07102e4a449326f4540b6e59643041ea5e7100130ad9aff8ca072a0e543a99c1ac08fb6e26681f6bc028c01161764519197172ce9a5e196bcb9e0af77401305c1fb55b6e5b74abe148801d020a8ab9958e6987d84612417fe655e61c4d9f6c04f24e063f1912d5c0230ee52a80df1038700239249deecdfbac879932038dbbd241a96a41217b4f202bbd2e700ebd77a840397ba91c7c573b1c10c6b0790c47e212c19ae3e0ecb17af9a075d2cd0590514b4c02bbd0629231ca50d45988407a8bd68a932158d749cf4c673c01093db5617dd2afced9ee58d81882adf4e513cf10336ca649e72bff5575d6f046895703113d984567c02e75185cca6e3bc503a16b6174668bdcfe3568ac4b0ae9397313a1920e6dc99e75cec9f20a491cc890c6404124efea49ba22744c6ccf4e51a7546ce54af33703411f4843be6045b2bcc2e64e7a86df96af5c8f7c994de24261d6222ac8539143d362257e28eedab6e08abef35ab1a263ced76a1adb876e9b06e0a7df9888e9aaf385e351c8a2c7823d8cd000ee65c618cfe12b2d59f8f06c3eac78f0091539e377e21d434594c258a562c1dd925824ef1de055f316d86a4bf3d8376a919809a9b401ff79479839e8fa8688dab95123c66f908fc892e6138ad8208ece36819c9902c7d85237cb67034e0486ff5612bb136514432b2c6d8a195a2c4df4c3a084936c05b88f126476dae7e903a4c6c08b5a09bac13fc6bc3757dda0b7e006d3b314a19a6b984389f04afc66d4b16889af5def11d921124b24a1a0efae012f138b5574ad9b6c705ddf497b4596fc8ad284080f8b300d1305cfd218c6f5611ceeee06324fc3fa65cc0762911c9912f340acaab8f8a5338f39fe1e50d618dc532ec2f668180b4905427c84eb942de4a5e6727ea313e2485d087c1c0e04c807cc0a7fe6abb25d8a6e4dee4997f313ba3603e42138c9d8ec06c934a419fd2cd86073b0c34b38afc166f94a6771e46813b5618faca44f51bafe00044b8232a1da2969eae191703518174078c06fb2044728834b8af887292e6eb2457b3df8c23ce5c677f511996cc429a464004801f243d0700094cb07e36c17222a33d1ee0d18978a65f1f95471fe94a3d9794e834b68af589109f87eaefe18352052453c0f80548a7154383a97b51a40977d584c1f62aaf4200d4d12425b7535e7c38dc05e434a38a083b5bcd93ac4e802c870f7c489aecee45dac98f02df5a00a1f13361aae376de32691a06720415431977943eca2d6874bf5a082f1b0d3e53d87f60ddfc3ad6d95345642c26d415ad3923001847135e855b28aa860d4b23ea0cae42e98769519b02a64a1d9a694fa1ac5aa7aa1eb87b8324182a0f2f582670e23d1fd8774473f42c577abd000f680e878195c1d53f84f1aeeaa608fb3529f6c675de30df2fda5c690b8288a4c2b44d98d10fd856bc82081dab489950364d4d63907b30f4af70f6058372f8ee272d4cc685bc989cec3f672c563d3d3cf6881c01cd4304972573bda15f835e5fb20d0f062994881e7b86da93ed45d5624ab9fbae09868642338a02281701323111c4a014769054286d0c1e2b314b11d1337968cee3ea247b1ec968897c970f9918efa491a9d2aa03f00d02ec471f8709f3ece0c8ff22bd2c9b84ea17806fd62404deee0243a30c506a1259da16d7c17c5af6199e20b23ecc316df39d8935c54167df1ef8efef66f163565e00c666a1ef774b5d77014e584127cd38b35617d0599d7732d3fcab41d062643ae35ebc7ac4a82dc774c22ba9c52e6e0690d7b60b7855a73970520818a24c1f66cd062c65fdeccd3e0320995518136e21147898bd9df4414581bf3ed39c78e2b8c8a5cdd7ded5f1fd42dc18079f6b95d9651d8a43aa56572a19508baf50327504f08f3f13fd3486c803010e3a67bc35aeed449025412a4d2f1e6f703d912c7ca4a4a3cfd9f56e58fc69b38cd4062d58f7f61f58de5fa4017848a9d174348a09f909ea07797eeb7bf6b2d36c1c148503cb1bbde01e381cbd3c4ca167da02f1f6704ba2c3d39a068161305dd10c8460ca703fdcb8b2412df484669025ecc79a1793b692f4e73d5355199cb595db9c6c4d23d5bff0ce5221af6e5674d26393292c378b9301a0dfa60fd5a6e7201eb74020be793cf308512a230c9e8af20c856beee1496190227a721ab7807e0e7960191cb20e929af9e991c96b59024eb502b1c255e571e91ab5c26e7a0460bfa2dae7862e510f9939f459566d6717cb8e42e92108ff802ffba91324283808112425b3f909ad27a4e7489a7fd054eb32f02379080588df8f8b20855054b820ab54ee8c1351ce104c137f159fab498a2942065b608350c6ede141e557d89481143b07b8387d5d04451783073ee667f217ad2dc4ef74a7b0301e48e80ce3374dad30e402f5169ffa301e604ed447ba0ab80de780bd441b294813a131c5284bd49087987bfb09a5c49a5ad415e3b53d337574f47a0216668d3672f3c94c045f66b3211f4a96ce94a4dbb6b9236274b2b2e7ceefc267c9ea8c9fa74e3ecc291a8bacd025a283a4554a22b0643d1a349a7f719bc1c4827c8c68beac99841353b621d3f32316ab2750fdfc245f61b194ce2869dd8025cee7a6e30525613ac6c74860e50eda16c29a707563c90c16ef9437d88e70c29c029e94244e5ce4f058a7ad36a4c8795bfb0b24177fac6fc8df09e81ec0438b379c45150493a9aa8e984c6433234026345edea322e492fb930ef026a5da2cab09d0271e2d6a42398a62509700cada3acd7a7c7c3a04272513fc04bef2023018e0f54ab8c0eb59c0608b224b56a4e95828b664aac458023f29a8f84593c09e78900d7ce0766c6d66704a0dbcc40a14a20c8134b0584d04ce47bc275cab8f0ba99bfec3ff1a188716162ac58d49233794387492166cacea258fec2d67842bff219bdebb86318ac3e14629db6912cf29a7e5d4a9678e53aa53b8fad206868c0cdaf25ad5d01a746258a004da63945a007054727ebd225229f391f43e445eec5203f5c58f850da432a9a57ccdd123d4905e71cd12b72e30b1e4edc246d50b937bd7bee33b93716ed5b2f648ae86ee64a1f7b93aef7ea1c77e8ac83627849f38dd7a87d6d8553c555e1c70c266b575aa06f457f2f23794ab688f720314e5d0de17a426941ce10b2fe3bb0d06bda90d0aa61a2cd08d8e6efcd1c2ac4f49cba6647189be3011c445db79607d8bab40c24baa4f505c84f15e684286e8b90ea72f18e7df8ae42bf96c4e2d29afa72e6e199a6a57eee5ebccb5d3762dc6bf82fab978e027be9948046f3e95b234fae02999f0cb296eb52682d143ad0c6257d09822a85c98ed0d087791123148afa1409c219e2119527033116240b6056817218aa74dfa085656459f2f9671d12afb845139b3d24eec5ad0e4d8a70cee6ed9c93cd81c9093a3d705713ef0e67941959c65e6d0c0e146fe814a3c2224cc69e4d3992f5da104b7210dcc833536f9f7e8381bdfeb318e1b4fd04a7c45cbcf160ac83c507b7791e8e4c7935644af6e20f83c9cc57237ac5c78ade58a93baff5faa7bc83cfc1930a75a78c930b6c1447cac203acebf1bbe6777fe67a07032ca0561a50995e21a9ae2373813d974b8f3cce4d8963b33f07153c0f0dd88edf14587e378d103a9179e9f961bf414590ee97c0b3d05db7df968a6ab5e34798b59049cfe32bfbbe7cc8320dc72c43aaeac93889b3ecb3ef4123cb48cbed96c9f89c05e94883f4d29762b2fe73b7054205641d64999fc9106120894d52481d8593aeb78f4d6b252920c8329e838df2e3f1166b6ce5482ad75ea7a131d8aa9af90ca55a58334c94ca0fddbc9db8e5179f8aad20042aad9917a5f203d72625f9a6318ded4d1cc074aff937ac3a065371e95e295817851b99de213e0ad356c4ab3863e6e1519f03a26c28dc8747d2b65c54acc6436b184cc23605777c6133c15790dad22e0d275c80a7730879278eae9d5164d8567599ae933a6c73636e37a04a0ca66f3f39566d8e90bafc9afcc5d48bea1d93016a0e08a03a7e84a8c7f43d26cec9385622e2db9288802f1688b4e1cab76713314a36d021ded9dba0fb83441cc07e1606a58c27bb107d172d7014bf1e092d47811bb4ecfbfe80523a97f8eafe4240c9ee9a9574768d4e5e88794ef24cb4690e16ff0cf6d5032be47b6c68bcbe24b542db7b7f25fbaae571ffcfc69824e8c5851439a7def005a047990459b7f990d3a73f8b5f63a308ee7f6e8e45b9da4d981382b935a51eb9c892a91708e5220776686b24089afdff1901d8e1241cf3cd42a97773fe7a5939287763e3a82666d93da59a99e7c0d029ccc6a4cb5d54dad99d8183b4faa60505ce956a8f51437f580e4d1d2d86e13785ee192104e1bd8c6214a7b462fd49b943ad6fa619e470d5033ff3402f801685921975605f290e3a97ae44ce0daaa3d1ea59deda43539c455a5620b444593b750d9676859e50a0c44f80a65fa8eef391b4f12bbec4b1cbcac57e6feb976694f64b299c2d131baea0745bbc8b3cb08ade2d595775d412cd2707b74498b02e25e23178c4f65c500507f384549a7e48098c8373c3113fcdc0dfbd92c79511a33b7cdae74766815e049a707f81d07719d82b99b949b110d8590c06cbc0dd80c2eb5117416fd20cb90b3c6219c58247bb5070ca906daa369f8a39f05083ed09174052787fa0d44b4621c449dc20af140f4a1115ecdc9c12fb093db15bb248c0828a661adda3c6d2c95ef15fe9cd3a470931bc2d6eb1ab03c7fc7de418e885e00ef307c4d9c76256770b21b69bf0a548156fec0a680ce83f2a5a1a23b7e781aa7fa0c9057bbf4c35b50fb92f5df0d0e14acae136cd2482b68e7c5cd8d7edfed09e73f762a5b71cdd6efcf74681be173d8a057ecbb32dde80b983fea34e4babdc9ea47f89fbe430bd2ea4c70c1f51fdead807005db848fe4de08b049091de44729484281b1e7d2e1cc0e761925aa6e6869d65e838b684b1299568204e6c5ddff626dddf4fe8aff234e50c637de6695c2bde20e29b75ececb6a38d379c0477bd740c0078f2da24729cddb0c9953e1b0b7a2547f4722ba366804b08b6faf76c8d54c627b006a69d605ea96b2e435eedc2957190cb3a2ccd867ab26c83741611ebda338c63430e35b535b196c5332c8b467e4679f2909ced1996a85ec43a8e9e016d00a8a8abd5fbc8ed11fdb17a27dcabd8f462e406de6da81b7ce9fe1b9ba7d67ba71176a1d1159607a2c7bb0de3827a5fbf9414be212363ee95be0ad0077f547f71da29a6d077d877434c4ba11472e39318ec5262b0b35c16cd217517279e9c8dc76c64a5624ffc05bfcc4eb4c00e38f5d00053e7fee404d62603c43cb9e322537c11d465175eafeef52832c9f5fb304dc13fc2a58d678a0fea8864fff1d0ec90dea9032b6908100bbd8ca9ab86b17a0ad7c8f5580d2a4ed1eae876d4df11f9c4fb69de9112b960f2f8c0e1db99ac143895baf0c87296298891cbcab66cd2533ed4035717fe5172f0b7ab630abda706df54155fe518b8fe940be99706fce1e8159eeb7a479f2749832d2ae9539bc6c5a5027db3d597992f5742a860c7c0889b9c474c1241d711be491e0ea86b7cfb16957fda1eba9561399a61898961f4051e1699688d98dab25d33f0d6a6001e1f8fc52f0c8c338ce8503e5dd534841ddc40c98c7c6c54a8b75af1289324daf2e125488876ecb82d9be2a100156e4749d524caed8323e1b38e9e6e6c09a329c73a06265aa46290ff274de865d133bc54db5ca87855a11011ef5ea7e692876e9211ea76480fd53b98d2dd21faede9faa204403fc301d53080a27c28c80c0ed2c377a0b16ad9726332cce43a067f546dbc872cee691a284dff404d8d57ac114d3685ddc686ef8ae6e59050787ed4e4b55aa8ad5d76818dd2d5007016e569c9bd63d13e2f8c26b0a51d8b81ac6300af1c923ed77d0a3c0b5386ac1e623adce4b7e76b89adf0fc5f6fdfc6dd160de4ae64f9aa2284e57f42dea1a4b2919da27f4ede2b29806f1a17f2917618b64e0c29c8c74022ca695c82dd55385df21d7f6fff9bec5a5972ddca4264e83586e3d50c8f89c4fdab7070f63c3672bcbeea8d1a96e6b539fb2faf6ecb27a130911b8f21b070d873255a61c26dbe40e32fe49a8105544c1379d8f80060d7e8b303bf8cb02122fa1e012edc8bdd284fa156424e11ded89980d2b0d1d2bc2c281db22c2fbeabd5b096f8692c8760536032e0531537008dbc7747d3abecbd0cd01c65f95cb49fb62cd9eac3bd7f58510e5b6abe4115336b6768617a7ae96dcc6f1e3673752f6b08c1e8e3f0fdcfa4bf00a1d6d1bf66c7036d24e92e33343d49a0cde8ced0949e526b0fef90483c22014b25b256014f0678fb914cdddc19a102c4f31c990bcdf5eb3233408b73dd267a3e3e5a4ea19999ede77f3b99ab9e0689051a26d7daa29c7ae97c47b99a6a32d0f756270778b242346539408e12351c13950fcf56b202ff4145a8e18e5c9e9c72ea2547cd147e9a124cd4d68f17010ce79714240da70f99ca15ebcddec894953380a401d5bc0f4fd9e90a57bdf89f1f1678f6306825ca1c6e3161d2736bf3e69efb821cf786061092468ff9419d477d5ac2f8b87be35f71fd7ca77f05e14b15876230d6ae02e344fe075987f34d76bd1ee5b51be370d7aa4b61a4a1cd6e5fdbf03097770c5b03b83af981e25b161533ef4d0cc4d49f3a04aa8cf226727d2c43f96d96f8742f13e3165149491d63eaa7ba301268c2010e2ab804373d546d8e2b74f4c563759922b5a0afd55b8de29afa1d72c04b55e6c665e86d36d1eb647db6b2928957fea192428908ad4ce5a47503a061b8a1b66ae70c02cbd85c97a8ba464f348b05f66489e4111c57c7e6fad1ded7a3499080951535c10389c1a3346282c1bb50e04cc636af09acea77efb0e9ee23c25d0d13d0ada90c6c258b8520c9ad4b689d9e86689de9435418e759971813aebfc4f56e16a3718a1002647a737d5f230095b58fa4e9e5e4485e03fc6c965a659a31cef392caaaebec1769777d2569e33b2adb4ce9b473af0881b1fd697c5584c0b0e8973fb0eda6ec793f29b656ba279e992e16d1d1d0217cf3de6da1434c809c7b5a3f304bf29e82dd4d1b2447415147df7647528023408943b8e1d960fd6b6265725265f6f02512fa1ad8cf0e01cbf5b06cdea7f1126a0507eaf27b2b1da4d3325ae3a1f71cdc537362cfff98d7ddac0f0ef001c309df45363759034632cdd43e895ae20819293e6ffd9abca5ea7492e59d792ff791bf8d63bd27d828cadb13eb1fcd688419b7981fb86683232c7dda84c1690fea5dbdb47bc58f975efb15c13b8c74bbbee2420214c3e61a8ebe8f8185604dac1b915b9b9359500f0442a74e39e67c9944746702b2f0415006e1684fabf7073855cb9eeb4515cd39e8cccc8ed559c5600bba447c44c34380d3ec80738f3941aea05bc871e4e2e88435bbeac66b1e84e81d1916e1afc6df7cb8fe5ed54875434d92c05e70240867c33210e6daa2ab012cf3820598cb34ff8dbd568740da6fa77bebc276609c2170763aa425994d4e5951602e8fede8ceef815bf8008ec5f3364074724418a948fb05d3a93945443d7f9b56a1ccf4d77799e33ec6d0e9e326a21648aebdbcf7e4918b86f4bfec62a4f5690808fb05a8a1b185a446dc7261d07345db22d097798b90927bc7597637ba681e59c14dceb9ca286312dae9cc53e5fcca52a02ed06aac527bbbc66949da0f503d81dd7f68dda3d3c6de0356842d28e23c60c09750f66e16eebefe22e09ac2e5df7f77370f6ebffe07b946b8b479835174c70012f10538fff5783dbec819e39332bd0bf9b439aefefe27e09ab8046f1d751fea8916a2c4bc10e725949bcdc392bd5baae303316ef6df6640ed6bff5c270b48d76b8cbcba5db2e4add8ba5326e0aa8922938de414571b5037ec807ce94dec34bf24b75e1c0a6c610b1b396180a8ebbc635c8295263eacf9fec0cdb2e62da81ad4426fefd5637c4ce4b3afb4e6bdc1791a6afa70ae991d5a8d7d6c2c683e4f33bb9fe867282a48b630c48a2ad330123b2d4861869cdcf9e0d9b9501ce86b4be5147814d4b8db5dbd584e96ed5dd4c2e56e262b0b332b7f01bf9bfa589ad8cca29196f141c54ba95e00dc7d3f67273a88e98062a8bcb13e35c4f1231d2ff46ea78087ffb425b44dbb247b3115a0626f532479eb2b60dac73a35e9fb8a78a7c6dff76ca69bdcd0a3d88089347ffd3df79887bab261e321c737a8f4ab98a9b413cd820c7aea22324ff5df314c2c4e032a6c3a7b5c40d6554d0711fcc346bdc4713b161159e7a6b8a5fa598445e4161dc45fd859e20ca8ca8ad371b66a0bcfc5c6b51924f3e17697cc9f70157f5db9f4210a9c53d880a8a843710286fcf55e4e8d6e7258c69290b6b7dc5bee2d654a52067207d007b4075877365885099279f508a3758d6daed678db34dece169e05c33a252e36e36df6bdadde5bcddf6e2b6fad8cb75c8cb79dcadb51ea2d09f5f69ede964e60bc758112448f1aeaf78b14176f619cbc3595de9eee5b546af456a57b1b837b2bc3be5dd9debaf6d6ab6fbfeced0cec2d0b7ddbc27c4ba3dfd6e0aa176b5a5a6099f179be2223864a0d101cf56743a70f55c9ca4d8c71e566ce39e70c829571852b7dd66a32757777c71863ec4e39806bd8f9c30bbc12fc79b7cc1bb0bdac621df2bbdf0274581f38a289ce8b08ff70030806ae9a16b453e7b29a850d0cb2cc998f5d227040859a4cce8407df2e4c10bc6204df9f8d7e79397d8c820912df38664c1c1a42c4ce6b32010a4358d56800013430c8ae0db9dd0e721a3162675543c3611c92acaa451142457a7472806680e4a3049ac19197472411381f20a2d32ae295f33c4318943b95996bd739eb17f698a6265cff6f16818956756b316f8f99bf90ef63618fd7811dab1ef6782cbc35ecefc7fccca7fc640f77859baac1ceefb2f7318a2b52907d383794ad50eaf8b0ca4812a9a4474baff55e93c941f0e545b6a4a78690291fa3586203c92231f7fe1c07d9c32dd28d5ce1fa5721f42e0cc94a0d980116554cf1a174d9787989628915cf383a26e625cac7288c3085e72f94ae97927396703df6e6198a49c5f44d1424ae8991e0f666ed417635501fba8d60f667c9d2d4dd3cb99b99b9ab2042a25a9dde3d23297609d022e68c912eab66ac613af7121b59421742323c8647ff42706378ee32bc159f5ef700240788102038dfb2f53c2211ed6ea29e40247a1dda8986106aaebd144ff9c248e4a249eda38eb3dc578e3b17edd33ddd8a2e2f220c829c7222528f93f02bce60ce2d9711067da20b53027c04d2217a49f4c40d99e739860fd9e387fc22629c17cfc9899ff889334ff7aa61b886dd0681e12607f229aee25c8aab788a7bf31b274cf10ee2d520dde436c56b1c0639c553bc570ce2b02ae50beb370e0c0e867398d2213fc5e5a7c0e09e711a26d6a4beb0a2be9ad3279958286e8adb140f25e5260fdc5ec599f9ec1dc4c52ace1400c584eb9ec23cd6acf8f555c3489cfac28479eea1a2e0172aa69e9bf26c6471613eac41e238e6a82faca7cfc430523e9c17de4aba422039cf2312bde6d3f3314f3c9c50d2e0d9af471ffb62b825cb9cf4852f59f7caec16a7f6c99cea491c21435c9c15ab82ec60551494104514353f744f68420819022d764417f630be64b87b31ba2a64102723e84a5ec9a8e24a0f7b85b1ac783e44209f1918a9f9a173021357d4acb87b3e6448a8f901258b9a95af053d08f03a3e1d280258d55f0ab4d1ab9797985e35f38a4176195ec7f0d8011085eb4228c52f8050244816ecf26ca2533a27952e0633a2181dc3b2f8ac0786cb2ba66e515e8a682f3e37e416ab324beb6c346db3611d06b31c065f64a079d5e6f74bcff590b58fbb0c623bc830437c0ec260e6d24b7d8cc399cf28724399b3da22ce48cf5c6241dea0ee99534f5a41be90b9123e9439b20a34a0b899470f658e4a9c89d46d56b3ea9ad65266f6c57a9a7d59966519ed1cef5a69dce04e6f2256853c4c8f79165d4489bc332f1b6d9efc1c588539b5d686f262d66d12aeb5425885b9f858080e83b4f3182d87f285a6b71ea365211ca457d94a931bca9d971c5c2bb4b3135da874f185f5e42be23e1a4fdce9493e73e93df02a88c46155a9e4617e3dcc2d4dc6651fe7596fde6d372ffce1edc88bdf1a91916799c7ceba676d3bf745f902e699d73c94c5605683b602f942e69cb59e659846c45aa761cb4d197bb47110ae82d49b7ec30e56c9288a143d7500ece0869eb13a2330f11de2a7cd98418c31c658a34bfbe0f2cb0e1b5610e4c398444a89850c923ce923508f928f273108224929a369123ddfc04c240dd285e3c5063fbb4945d2e7af072e7e2976e9b4bf503a05410c8a7a703e36f908f4022ba4902785393ce6a5d8f9a87e9d86bfeac99f0c92dc9ebcb4ee0c2732500f49fe83ffe43bf94292f330fd896324acb339f9522492934895fbc2ea9541ac7e5c0c225792bcd4f513275da75f9d8b453fdf665e09a569a552e9d3ee17190c7330015d21f411a80843fff211a8083eafb99d5fbf30870fabf330a5ee97baceddf5ea695eaa7aaa7ac94bd52f32f82f349ab82f6e3d32684b3d30687d32683d16bd759217ceb7d5eb4783096e187f5cb7d6174cbee6d2eb749257e56bb1e3b8b7118383559d634e9383062bf496b9b9ebc5cf2407e68f0f35e7c1a5342ae5119075b157631e7b7c3ce668581549384fe29ee493ed1279433e8924f4b253b9288eb98a631867b9ebdc77de9d4de7a552c967885ffaaa9f7c36b4b8a91abeead681bcf624bf5e28fffa8917ced7b491c78e743d204ff278703ffaec12f902c7394d77dcb7c9fa95a070548cdd125dd4ed9ea0e4274f98036f9ddae96595cd4dada49dea248d380eb453769ce19eda26a5e458b8acc3469c09857226eaa1b6d5e832bd2e9d8026eea5f9b96aa59327dd2424f2641466668e99b9995544c0cccccc551f418cf6a5bbb7a9628f71ce3999f9d36a77fb0a337b77f7e77577c6dd188d7132778c51d62cbbcccccdcc5c1ac928f2812b8213968fb264aac2954ebd62d987359d31a28c90e6a8c338cbd5ba7d32210f94bf4e7208581a1a8607c3c41c5230b8e1a55efda5d4c4bd4e7289c3aa50065d8f0647901b4a1cc9d36255c55c4758b5fdb00ae3161d1bb8853a2b88bff36292a28f493e022519f20a9045e40b9b635ef50d8b5d44be80611886d5ce26f32dbe0e4f87ea9bdb51167e64bf940eeb9dcf60475f589d07f9d6a5770e84dd7adc59dfba4e8e6aa5e91db2efc21f6cba8fe37cb39d5beb9bd7b9ddbcd66edbdcbaa675da56adc76d5836855018c612a5d7774c28571c3df5e046a0243a2f7b080999dc8e6eefa161366f97cdfa6e4abd7ea1c9b483622877f34cde2ded5e1237f55aad6a52f4db617df39622c914475635612492ab1eacfaf1236e1e4d0a888b7d2ed0eeee116726519cb9b179b146dbd1303b00f1edb4bba687152978fad9a02f5c7a691d88e1fcf881221a57dcfae1ec06c16e11d2125d220c00644b7b83a6996f027c8343de4e8404d2c8535df48bb2f97ccc7abbc0303b76340c4deda8b83207ca0ab354ba248f66e4e5405981d33a148df330be388b6d2915682c58a5d1e2155f2f365e3a26234189c615b73dbaceaa55856e883342d2b9a728d83604faa9d01cac9a3a70f8fae9c7ee0606d925145f2ceef2451017ba1de4cf9982eb1f46a22c12e1108a8971654b08893136edd9b47b369ddddd4d9b677737266b90e5ce04916f40ea396786d1994d6cd239e79c73f69c33c6922d8a2bbf18527c4bae9c734e4c04a42c93d2099e0c8b4ef01c4199c680d26e1e224d69370f91124c2ce46cb57e10358661584f9517d11461b2ecebf163c62a3e7c217b1824c1954ec5cb5056e4760b8f2ef4ac53807df991a8b85be95e6feb6a9122b548d7917cf3a694914fae5b9745e48dd2471deb746c7f3f5944be706511dad94867f140cc4954dc39fae1e737a7e92e7c09e74b288df8c8223d457c863c70a58f8fcf0bd6b291a509939ef78f4e5c61e89dd862c8bf7c74a249162f8d3c928db3dc8f3cfa6455e7dbb6792994bfd9dfbe6edbb65169e4d11ab8af7aa1fcb0faf5b98d4a23d7bc76de756e4b5f28bf73eab5d3b17df7490ec8173acfdc8e46596733ba0cb6293aa9f3d1486e4ec3cd79f169ced6d9480ec817d8abc4913738206f4837f2992785b85288ec223684f8b2d1352312134bb651b947b7b0e76c31df8e36e9304cac59f1c0cdfc32282529942693119434a7924d4c564d2b9d4e326bb922c4cd7c32485d3b4ca68f7a74c6c99bac2fd395f75693c9f42263e48b8c91720aa13abf39e79cd3f473ce39e754c5cf8114afa75318f1d43d938c424c94e28c14483c75af4c363082152a5e489eba8c49e7f43b953cf1d3883813430aa0be4ae0031d3c7595eb7c450a4e90c231a9571f74200a183c75d49572c9145e0021e174e9ece9ea3999f073ce39e7ec8914888900983a1bfa49d13780808898d3617436f38a110891022259c2537fd1d9d0976682446783c51b0440b2c416d434e79c32a0f859020ea2a8a20a426a26b5c2cf2ba8f8797fce39678ca0bb9201985843690f58f0748aa794523fe96ce817c59c53658b9f5e2f0f6af0d34d3d28e2a797bc8717fcf05c71032c24f143ab5085d007eef47a4d0eee20063f9df44294b1bc980429819120b0d084162db1410828a57484a2c2e2828d1d9ce0a75f93832f3f3f3fbd8b11c226b04411254fd8200b45f081cc001186885c153f08c0872e0c20074fd0010f7e48f0d3630e9af8e9f61221a9001036504412176cf18226a8b0c48a4b29a55b504aa58ad086154f34399204e8c813a0e801500e52f084097ec6cc698413fc1c41cdc4829e7a76e534c21474648c132c1b7aa76a461c10f1810f84200525f458a166522d7ece58e777b11e7cc8a1a86c3cf5faf3d4af13453cf5a8f3d44469ac4203251593162a32547eb2fcbc01133fa75717113ffd9a5cad9fee38d8c0cf792fc5c29863479c91341448e20849d00008269658ed20c80b120caec9231113220e8cb87e12e1a70d4cd0c4104d58e1c55f48a20822f618a32bcedc78f61a09e39146dee00c988670a7909507cf8e2161303e090637bc4ba6f091ddc42adb3ca3bc3181a81e8dabb2b0506a57e2a241c8b337c00676083410133a39e898a06666dd25406291412c01210f1c3f9d7a3af4e44102f9f9f25383e64fa4383c2df78e4d6f5abfd40cd2eb87e3e9174ee74102791aa63e3b26070270a486b851881b4244051b59427ef5949f8c52c628a394198d599665998cd1492ab8d23329a5945fc6838772c821071c72e0d1e3870f72655d7e42da06ee8c4292c91397913078844166c23f5dd095af206c84e18e742efb94524ad9dd7252395b474a29a5f464a473d2d943e8eeb6f173cec80db149113f6f2fcc7c6642318b3176e5c145983b85eb5efc11084266f2e10ffe41350d88b6452d522c3a0d5baa39e651d7bcb0731ef38835114e69eb304831ed33af6258584db531297f3e0f969f1f05c16c4a69467d524a9d524a290a8db3490d4923c6163e8c31469619f4c3bccceb8a26638b6155b854878a913b7131c678638c296177b70b1414172f4e524a30ae89741aa1ba14a762636c32b495ea99877d74c664e91698868cb106575915638c2f96486e539d14cbaab659ae1b912e2d9d742e505ea4c0309d502995183256dcfb66b0b44083d6a0b10638a2489a6259d54c179c9d12def2cd72dd88744b272e505ea4c03055179d12f1844aa9c490b1e2de3783a5051a3540fab60500017001a4e1028ee68779e6933ec59a5f329daacdad0516df96d09640a95e103d686ca1dd530a646e5fb4d06f69d4e03459a35946101c519701603de96c64580cd61f214989ab394d6f1e0feb9219c26075199ee802853bd936d7344dd334ffcde301be16831006abbbe8620882728bc2a5743631e09c3ca5b38921088315060c0943d3be18560cd6172f525260c8ec30581d466723a3637a613299505c9c984ca56b329948a6516732994632a7201f66d0e9d5309967df09480d119608b2aaa1a5540c1547e5a462c4480180e58120527a40480c9594cdca2608ab9ac857140e2aa75b2a6a06106ee7216a353d19db52762c8dc20afc96e3c52a205f3b1d39861a26c7ab5baa57ed3b322403f8339a7063121f22df82ab851f974d9c915f4f420c5697974c4e9cd9bcbafcb8fc30585f7efb6274d1dcc58875bdf6b15717d711171f979f9310ab402ed954db54cab6202404923985c0e2aba386304c7cb58c544fb53df1892ed55f787c9a851d56c13882c5aad210191e5699bcba0c1156d12b2480069417c680f3d54f5e188390af6ef2c2e882e1859ee2851851d89d5e3e642793139a3e94c9f1314f30161192382384b9fad4c3aac8028bf80836f4b5263cf9c47c88b14a5ff8e26267a8faa955dd858b55b1614cab868935b59a563e2d1ed64e4e673899ebabbb502b4ef2d58550e862e863c3d458d731edf4b9401a207afaa14b0f0a6708b5c3aa3042b142ad5041305604ca000f0a8bfb10b542ad5047c8d037bad48f32368f34ed73f1d9b46d4bad705e9ba68531e8ab46ddbaa961a6dbd900fa758bec18206b6ab758b732ca185dec170a60353fd7e76a18abe8b2853056bfc9b88d421edebaa2cbe69b735dad34f03fece69dd83b2561b00a0179c06539674fb317c03cf30b509f8e7d323bdd523dfb6a0eeac9e4748bddaca5443a7322d9a247081c702b245bd8cdc5e7f46a613e2f2160618b0f31235fb71567cfc527c76b3bbd4e49647264765c7a826c5639867260e1f26a9815afee12d43032bc721de79ad6302ba189e5a32380c1ea9ab783370d63f1b6f1690544444f3750075a466c1ac7209eea3506ab1891af58cf571a10e03b58a579f59886c1bc7a7553ada6e92b1e3b075097e1415a6037efbcc8a08d754ddb5c5342068d8f1e3bee9bb5ba0cacf5d56578950d80b1baa5fa0c205c8d89cb8b4b9a87a8d5574fd9cd5132399ab59aa3761a6612a156384274502c22289f8a1af215d5fa8a32f2d5eda6c9e4b02a7479c9e854cd637779b18aa57e3a4428725258c7ca4696d0ba1ef31514dc58e3ccea5aef8d96e5552e494f55cb92f273614e83581585769860c1aa7ecc6911ab2290105a8f3916845539b4c9632e6c7b0109c1071f623a8f79cd24cbb6588539e67608ab1a8bc7dcf2d0261f5a228f5de143db93807efa9a4571c63e26ab750d5936715f6c6258b3c4aad4b1558bcc1c134622c923c43bfc6a1c2cab59181389248f10eff06b522cc332c923c43b14a31891e4110a632291e4991d89983423882b993932616704b9d1a3478f1e7d46902b3d0eb9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b999455861754fac6edc68c57bae66af66af66af66af66af66af66af4e961bdd1314f756b357b357b357b357b357b357a5139414937b3d57b357b357b357b357b35729304e29f756b357b357b357b357a8540cf77aae66af66af66af62c8f0d5ecd5ecba5af19eabd975e5deca7b80925e2941b34b4959469ebd7d26e579764a87d09e67c7682b9b59d62cb33aa2acee3944833c3ba52bac6862319b3c7b9d45dad4b466a9d51186cd169267af3f9a6b9b3dd6c54d8e6b965c1dcdd6b6b17333a79bab671f3599429e9d3471eebcb759de3aea221247f25c4a9ebd14c427affe7976174718945ed8499e1de5155fcc172f9ae58b3a6a5717b5e6102b891bd2a09413c52ab771a3eba15cfce22016e221a2a21d168bc562b158ad56abd56ab5bac8d5382e97cbe5ea9cde6956f3742b6bb55aad56cbe572b95c2e17d68db81394941997c5d3629f17fe119aad2ee25751511107b1d0105111465bad56abd56a75511775511775910b142ec5842209c921a2225e310f8bc562b158ac39d4e29d56abd56ab598c53cdc621f76318bc562b158ad56abd56ab54c33463c2de9e3923ff2258beeca84e3392c168bc562b1e650b7f0d0d0d01051d18a71b8592c164bcea139343487e6d01c5259e1be195d8f9c1d1a1414c4ea167e7901417793e95ed9923e2fc92c168bc562ad7031ae9f57500e0deaf1f20282ee26d3bdb5de950907cbc1723c07fbc17e82328c06d19e346825896b430ab7719e736298ebcf86e5340cf6f385f53af8f2f25b2783f6d84f74619f01c495df666aede30c2066689ab6b24148374e9c2975af1cd15430e208ab9ada0a4a92c4b5ac587b5e3a7751a83012c3aac82c2fa910920f5f5e76395458e19b3f242e459d3cc66cb186e0d75a49a44bba298c56ea3182ee4a90faa1dc1ca8171902849e6ff90804041c182ebf10c7e3b4576b6a0ef4c50908378c4c9e0ed9cd4b194953361a8d3ccb3239e2348d1b657284034da778a13ce2a9c3f0421e389e5da23c53b7503f714d6eaafafdfaede8d12d94e4a51410a88f512879e24d9f0b201d2af90bef272eab36afb5f60e2e78e29b57bd131577b4d5140c6f4f71cc4bc170cce5dbcd73e1560a41f1eac99742341d6b25a7715e08e4b9ce6df7a56ae8dcfa0cdd1799c9776e3f205fbd70be6f9ec963374305f2f507bfe96b22e40b1ae7d9c0e00eab464e2180f22387e1f9b0c15c477bcaf782e498c4092511ace4055ec8dfae6d317cec74d01962f8faed10c357b7a43b99f69c230af0f3807ded1440bd75d0af2ed166881f37cd6a289e0b71dd59c096e81f15368b73d9679c71466666ae19465f5e90a1464bae74ed069a86a93d42904ed93e7c04400f6e185d327e93c1cceb57b35a6bf6cd38fb8729e769e04ef7a8c519cca975ce721c67bf19b5e842a5163ded547167015be20c8d53faf6d5c852f08e9f0b71db2f8ae91467a6b7f48804762fd292471a6abe7d9be6ccdcd96cccf2b50f036d9bb3d3650de2c8ceb76fded35d886b4da738437d7636b20b35cf3cdcdc7eb586cdbbb3b1d2862eedd48b2c5328892450a0c4e676f350db3c2cc5399934f2a87df1934a18dcae17c4f5d29cd7e35f67bedff5e961745ef7eb450f07831b8e6df31c70e06de33cc6d64d2c18dc987d73698455da27b1602b5370abbbc9d4981c8a2e9bc7e0b9da90f5f67c4892e76352cfe7070f83db907539c4aa9077e6b639290b77733944bdd66ba29bd3dcb065db6603ab56ac0aaf0cf2b279cce63836c7619320f84d0af19bc4c06f4b8a3e8c4a7edbc298c56fb1c96fb7b75aef8ddfb67964d93e1d98350222892450a044751bfb0bef77e6567ae6913e1e65252f88929f747f251a3ef17c0052532a7d256f4ffbc26a81d54fade4691c8395cbbe8a753634c6060d394858dccd630cb9d5889ccca32ccbbc7ed208833205d75deb64989f7d3206cf959ef9dcaf5aa79e0f49f2707cc81f7921cb871227fcd10383d54b30b8a1f491edc995e7c316378c455f5dfa745f9377f5fb422bcb4bafaf2186beba8d18a315bc83083f1fba8063ab6eb529893a2374d0f398a77474754d0bf9a57718b5af5300e6d2695a92b0af9224904cca1a7848a9531a63acb5b29452bae0959bb0914552aa03f5385907f66fbee1e307a5b19b61fef0213d1525a9e886fed2317721ce54c7dc06ab76f8c159c09638b339e62e7146e3c7dc6a9efcd11d3dfbe8d957de4a9af83ad494f6e980e1d97d0059c1f0ec303c3b901b2ce179ec629815461e731556a9a480e4314c36f7c81584658f2c45b8f2b321853b833ffb8c65b7ecc920b9e711ed721f58c5517189ace57f79c84c7eeb15e7d968b76ddb6c6224195af18b8318949c6432f86a23ddc3afa1f621eac1d5158103ab78f4f8c1fc6952323333cb1a63cc01476baf9e2c62b0331965267d62d8c42636b139e7f40cfb64163ab81dc622250c7613e1047541b8612c22eac10716aa43eccc91c71a1c24b8f386ee4ad3305ff8126bb8da1ede516c6f723e399f219037e473ed3bef0d3372ea37b6b05f1c31b161a673ce713ef236c7dcee605dd7f90cf1bbcf8616d7813cb779e1fdadf342ceb1cab9c601f9cde3d76bde0ffaf59b21902f604ed319b6faa994528af90f264cae10b2e10a269c0429520f63a4cf4c29cfa904d2343118e3fdf6d9320b31c638638c31c619638c33c6202cf3170f50270eb6882b25bfabfbce87147a1eb8d17c8ee877c89e87938e1bf180bd7476529cf12157bf430c5fc35dbde462f74b8f919958b122d1903ac75cbb999be3ecf8c5193d4e6f6fb207e40bb38799d3ec1debb7126420a1f312070543598c59943aabef26df1e89621673884990927e217179f374f423186c97395287c18ef1631c3b51e6979a9e654dbf30353f1df419a72807e5bb9916395015449e6b045ea4d84193e6e7d82f063e44f91799015b800db4c8e04af78fdd123fba2871f14697241faa005571e443930aab4a71463e73973f60a35771e3143c3d8f7d9c8287c8c729788e78ede3143c391fa7e059d18f53285185ef3e4ea104162f2510e38d08937d3cf89312866a1ed698760d0ab57ea69e9612984f0f837d03046c6857c9be986ee91af361cdc08f86560b73f5c8a0cb1f8186309282074bd0e9ed9252a64c9952dbdea418c528a594524a29a518a54e2da5946e4fed10a088b1051a18ac8e801d3578bed618f235580c0e610de171d971d1d9f91aba1cf1d58891777d95916955999c5ac38741191d5669ceae7d355a3243be7a28c3f3b546cfc73e05819aa6bd200489f60ad2444e2fd48ac1edd36e45e130586d34b7d3bb770437f472c2940c27bf79d6faeea73ecbe4ec6c1ecae4b47519d6d6bdb90c4fc3b808c9e4b02ae6fcfcea3243645a3246647e647a645c3248be7adbcd258855a19723c4aab0864b125661417cbdf9d045890b931aadf7e18015d48ac71aeaa51c2003c5d32dd56578aca9e1734399d7cf5797f16f089720978f03377479b9c49ae9d4e994e1a1d6c6153794c9a9d152c00ff92e393e5f6b1cf9ea05d8892ed5674071a7d3eaa816fd520ec02e9039e6b12643f9f830bf9403a6bbfb77811aea80ec43b5baa53af6a158dd828a6985a855113d383118104508a18d45932b681bffa41a907d98ab81d44c0f1bea964a3d4ce8d4a379dec987c17a32d227576fdec97584c1eaa71f065352dcf2e6d9530fc3c8d5c908abe2a9c73bf91861994ca3939313172ed83b15b95e2eece714d42dd5e987fdc860555c44243162d3f884ad4654dcd0c5e7abdb225659af7e7ac596a7578ea16ea9cc4a74ab3b1b192271d22328866559ad9ab66d49b06c648eb0323b1cd775a3910c8fcc1019567421ed903a1b199d9d23602082018b38145d2a0c433630dc6e86f93008953819485c142f7536323c334d668a389f63a8144d782541ea10cd8c000000a315002028100a87842281301246a226fa0e14000c78984a6c529f0a64491224290c33881844082180000000901291191900a02ab68c34f051546ae191d4ac74ca3ecd8520a365f6a62b7d137999282253049c7ee8ddfba6396d7e7016a4a76075b875cde1bcb431e4156674ae0c44c7455f25e1c284cc5b2545f96d2cf9894f0eedb95cefe7cb8c945b3181d0de9f1c9e2f1dd52ec8a1c2a39b4664ae2eb5a21255f37ee59daab9a9436a74a00a1bfbe9a6bde8abf62a6dbd6d8f88ff81cb00fe60dfb2a5502dac0d349c2d5238b82ed47dd775c55897ab15a78b0dadac3d2d11eb30832a497f31b55d6ff4896dca4b6958a28d92e732153d1b367471ad0e91c40a6987e0264acf61fe2fc56caff0b53b5141f7d3ecbd0696639696e22046a00f2b700017833a8e62a819600165ef05b961cd37c1aa1ac9394d44a3813b43a2461783871c990517e0a1ded749bc40810b736814cf37c1c0c05afa5e7174398304554ac5f20a51345afe8793018ec98ec1f13e9b6b276a56113c23ccd463117694805e52a0b36f6a47bc1e74494ed2135bb61d58bce607094a9c63b5ed9439c4c2a9120162cf554d5c3019aa27686a6f0fee4ec6bd897903e0b788a30b1555669cf49a23189f1ed987cb717bd429dd30d019112d9b80228b5f12b9eebd66e9ffaeeb36b40e2b29b5acc6d8cbc8c4adef042b9264955c9673720eba326ed54d57c137b0e846177733b2be5d2591cba7456fec94ddc24b71f31d6138e35d00f50fdfb9509ebac78053a769ae4891bdcfac21cfb300810b117b7fba34d1cac924e0794f3e345af73d3eb9140ad7306642330c8867f8041757d010b78c0bcfda81c622e7732cb223e2ad0d25783d307a9b1406494396795c7eaee29529374998ab76f40d44636730f3c4d67d68147460bfc053f835554ac209e006479593f82b6b5a0b5eb03ad2ef58c6975adfd5b2492c3f4db33d5d53802363e49a78425019840f93902ede148be7b2a495ebf02c88dbc3d0d061ca2ca5c8db11f0ff33d7a447d64ce9c43b63ff40c8320deb37e90114a5862087d79505c12f1d3ec21c81907f371f9daa0764081f1a5c572f20c86fcf033f4578b6e0a4ffa36885fe208842b741acc0c8a419217019742ee656fe9dbbbe619d1441560b4fd7ca78766ae8737ce446508118da11cca7dc23b5ab50f82e1232d9674fecd24f426d02ab01b2a50035ecdd0eeba70caf884e82dce01983a1eaa777aa3d743d93110cb46b4d0d71359b43d1dd5e12e7fbc4864b3b5ba86d7e7fb3cb2d05d9b3e0b36fd9b0de36c0302a8a79f6677974718de505ebedd49449a2cf4a1c31b0c14a023accc0867d96c507c5d4a153aacfd6c4300cf7562a9e95811f5917055029d3281f52b8b7af1677876885d83d5ada05e5a8d620858bf96ca1a328a6bada37fa39012a050bc1593212fdd94d5e89f8c9a875824534ce3aac620cde669307ba8ff023354c87909a702c4696a8c1c8b6252483ae586162208d90a8f693c498233576c46a5e82afb3459759661f6ba7b4268c27afda0be3fa5b46516d39dc7552755fb306012ae07e4af8c6ea4ca13ac68bc635e2231a7d458dcaeb03f0b35811d01499b9bddc4020686f88eb512c7646260788a95f66466d1111db53081a200008b1ef30f5836fe48b0d1cfa73c240d4e2af6b085bc4c5c1d3f59a0d098843b1baf70ea60309d2009436e088e224a088fbf38c7793c01558162216372b9e5dacb7db97a8a3875b75351c97808afbe3af78bae042ae1c9bc5f83707b6bdea65786fcd39e5838d128851ebfec72297c58e1c215716264ff29fa0879fdf2c78e4aa45e7955d67075882df348544534742410df717ce299d1bff487885d219fe8d3d3ecd63f1a059552c6479cd6f9b01760745514e03a4ae4e58044586355334a69164a71fc29c4fca5a4dcec168d2b56a3b2c48a0abc29d044b11c8702bde87ded7e722dbb09bdb344413f61635e0fbc8c7964ca67cf00396398383973123f3d2198c10ec12071488cb8b06a00cb62a20f07db3886ac3b2f81981c03d2705485ed3f17859b6bb22f305d56e72a3c22afdadc5105fa516b17fd0f749db599d10541628841cc6ce126b2b14d42ea19c9cd3007f0eae54e1c52669b1300c77041d52a7f15479a5f106cf21b132bbf424e7b86d8294d318beb44ad6f9008bbf1592df9ee6fd6c6da292b8a1bc2ed7d4a325b7eeb446313fc88e9abd42c81b093c27e73edc52d45caf0d758f578962544550bd7088e9a92e85ad43a02053822e8f19b392bb46305318c890100a78e996fbb89c0740302c4b40825bac576339f393f2ea2b85a070c89dd1f37c4804a4fd8b3641ddd59c3cc8abeaf7b39c832ac7b86185654bb848d2e875cd636a0149df08dd33091463df823db92e1eb5160e0455db54f0ca0dacdc182cbd79d2cd5e589ee609bf470b65c46a9ed0820d45d51773efc1bbb76bec52d8c4639ac5f96ed22f878833ad1ce8154c6d6fc234b4bd05a0bace7412ce27c511bd90439474963520a94b291149a89a5ea78099f8a7978b0126562ad5b14aea2362e05ae9c57eb480b7cc6cd3bda482efd45b4d52141008a1b2d0bbcf46a1ca36a8f4b0ec78191cc2ea5d10b85b99bbe91bb33d1025b5cf741f40ea1bc6fcbad87aa3e2954f61c8ac0c3acb56193443d37d0bc4a32688f42ea6d95fba2b040f2a902c7fc3919eec351d53c6ea4a7f55a3c61f50d4a59bc34433b8ab705eed2cbd8eabc68a52645ea88f23720506341c8416f76f59d83e67279b246b44c5562326569922d183da3f8d145639c34101b264ac5c475232037845a301a34ec14e128518f2926a29a741c1930f5adc6e3b7bd5c40b6b1ac92d69d3f2cc4ba57676c2976ec140f6bf45057272a771911fcf132f7aa7dadf67282a37820b592b76bb6f2f2bf42b58d296a908b0c5808665521a78a952b0dbfd9a6aedd162a0cf18a8d613353f944b8f4d8fe7f5cd70798d7d8a026b00bd559bf3c0b71681dc40b66bb499a4fc3e298cc673cc24dec01bf929985dae750d7feb9ae5cb733d69a6804dcf20b2cc79884201e9b4cff033d2db0173748df05e0b507724dd2a2029c4af7a349339a83bf4c62e5a546c995f888676f0f1fff5c223f666403e6fc60c5d5d43b3ca37ee0ba0888af01b3315542c890198a2d0194903fb98b95c37aa9e93001ce0f902f24466bbc494f285fcd52813b704a47b812665cf52964f422387146627c8ba3bf0aa26f630edeaf54065bb428f730277556f969c3b71795478d298e363c64e72066ed26f093e4f43dc967d2d1c38d075e975b71e5b1cdacf52c19e226cbe0448801ed1f5eac69cc5948ed482c4ecd48c8a045e66d640af3d967bdbd9762830b276321f510aa1842f507d09a6a1fbd81c4b5e1186e285c3f0b3c6bee7ff00c56667ce04a3eb545eef0054f481de27c475eed38ad1112f041cd08d658af266b19a04ceada1207813c81549c8c0d6dd32de2cf732a859ee55fee41fabc4418144686e054e5d3f1f805c1be1064a9f29bf42ad911e140b039539f9ba61bcd7c1980a6f528055a0717ef89b7b89edcd36566f5a44ca051ca02e7ee85a01ef9eebaf4ea8932ff5dbfe1342296820144278a2f660ab9072b89e535e0dab4a048f61a339c48bfd71bab9f462872fc48e8d3ce07557e52950f5e9c800ccf174ba06010bfc2b3e00fec0c7c7816c72725f1278e61d7adc09b11a64c300595383ba28574a5c548d77cfa5857c0c7ad9799966035e19c56fafc6960845000f24da4f43842a30957ae0902de087707a2ad0c6597944ae1f63f727386c6f58781bee83da8e3abb798f06863d0695f1ab8bd5235dbbe2b26eeb0952b35c5d53f4d3acee4fb3e8f67aa52d0b52e7091f192ef3266b5c7ed9e2ae689b1ba89d76ad29a7604151ccd0d15d3d5004c898d24dbcfa306de73b41c511cf1a9f142d58d68da0ea983819a8584d7d9d0d2f1904a50a4fc049bb289974717bb45056960f9b4bfcaeb4ba86017f382e9bbbbedaa6b26b256e66141533cdfedcedb4b6fbeb582b959595868524aebf593d9d24b7446cc327976ee720809e91321ca4244cd809c60a9962153cbd729f248e00999324c03007ee9b25332281636935e366fbe743cdadfa14c672ed7d6ce5a93ff131e30d20b9ea1c98b7478ba553c0e6d8c12bf308516cf98fd16415fcf80accd3b775467cffe0a413c1902ecaff809a97e509b48751fb8cf8835f8f58f1ecc5e0b212a81ff62f5f0eeb6b7b700ab3ec412879c75e890c1fe9517f7f8715b345c0dd57ed988ce3f99597890dab9ca188788246a1e2c846aaa7a99543a0270bf10ea391d82217a720af000e4daee166e077a2a9519e94fe96c0891d09b51388b782ed378a4227a1c1edcefc7666517e06513ccafc0c7d5bc1a8d12218d397fb31c420c968da717fec86e42490f4c7e346249ea3eb2276d33c293713fd361af50ff784ec4e271bc83899834db37056da7e193fb29da4a2c9810198966645a1470e4a2f8340cc12a8965514dea0b149730df3b61950a8d722220dc431b8af150e0d5270387b82c4121521e1d57523c62bf692e7849a2f0b70e438df0ec981bb5fdf7f249b0245fb80e4db5ddf2c0b816fadbca72b293cca5b03498e91046039e7c00e6bcd91baa27b17cf2e15d7ba247fbfec7f069d1184d223133f11b86d9e1258f0d38167fcf87a29ec46803c1b843f51276052c05ecb0cf8ec1253c31e8a662b3202b1f5a9fd74d237214f96294bedf7f0ffadc51349e3a1c58a0e1f7f3c90fa94f2262037ae329a00670a0bb5fd3cecb12c5ae37b96c9061697ae469c51329ae29d02a7e352c2198e009c6c8c0dbd4a891ffc17c4fd38bcd84072fcf684b3ee41582535e1e60c1ace5879dd47339844f98a300fe389f38c7912976c464f62f12757ee1036432e7c9b94a450b3cc0ff467cc6c7b49fccdc0584d2836564ec0ca5ee636c40f08b3e57e333ab319fa30732a8bce0366a8d6376b5761955b16b29b697803d976e32d9048b3d16abb52de7d694e2af773f3ea4d0db4db3afdd503ffe1cead5250be5229ae68f98f8d44fff31268bc72eace5cc970f0eb2d7312f6ad8817dd68f477334a35f104016f7b64550ecc77a05ea5bdf8de39177544c5265c8a5660b0f03182c7bb2285d7de42d5f240faf6a4b4b8ae95f23897030348d45d0c6eec3dc5a9f2dea2b0a7112a8a0991b0048f890b91d807c0a4cc0d6bf478904f55852534f98c7e5e46ce19e5490e89f033045f36b2b7efa4796ba624da3b3d0d9ea7748487c5e8aa19ef1ece077b616b54e8b023ac52c380c04284fdcc1a179abd5624371e43625dc229c9edb135f68e6a28ceab31e5ea334971b96502cf54c3eddfca26af813906e81aa65174979f45454d7552a11fe599984bb6c2db77d40d34c401e70969f264db7eda4a27e4cd276b1d6c65f0a4e09e653d34bea0dfe743c729690a4a4a02dcc94d18d9401951b9e78aface00aa3922c77b092e0e8c3476c07652120c5160a315410c4391686273afcd755421db70edb9392aa303eed8bcb25b1b64184ec8cc54c37a54b0f4b1a6bae109722b148fe54697b1acc47ca528fa7a84878824c1ce8e92a9b22e286b83ec670c117a662627369e424cabf484b009bc7087bc3b12ffb1d3c007130f3b99c0dc10fa04b94af287b2e92fec7cb63aca49e90baae29436c6d2462852ff47f2d0fc1445538e2d5c2970c9c5c34ed179508f5054460895752eec34ce3be86beaa3fe471b41018ad7204605f24b2e6a68d2e4d2cbc48ef4ed3bed4d39386ae45aaa79bdc019b458ff472ee4e0090e82840c5e90d44f00114667e6e8c21d405638c9ae88dbccc138465f0de479a12a47bc893ca1def00bf22300e52f28aaf1c271d35831090a0b2a07383316675856cdd5c9a1ac7460982d3f05a88a6fceb2cb5c671335e62c30eec0fedfa03a856c9564f1551c216a18cfaf0162af7425cd606b1931b61c540642bec39ab89de170434523d8bfbe914db2a212a95a9c515dc99a357c69f208e22a5583cfab1dd6a1f731369342f1f1ce0f35b59f6a2ba96bfeca4fba53e8b2723569f2f0a31810f4fb7ce071ec410281a7bb462fa3ec036a54e2580f39709cb7cd3c98d1f9adbcb5c2b3f7e31f4b37c34eb19fcfa17e3141c0355abbb6b2ea03f70721c4f9c8a41f7a46c8fccae640d7e598eb622f31d3affcaf40690949f684483187dca59c786c77b63105c6001eb2f5b6c6598c8e7af4a1b253b377c3dc2af29313aecb80d8eb9efeb8900f1331440c42259fef29991c177c2bd5b498915940e399df8555c7826368867c600b1c071ea1c8aedc9fa164c0f22ab404d66be7ebedcf8c9b1734dbb555e3400748afd29d2691788bca989f66b711b3e28a834e60dfdc3a60ff921a8fd7dae8516f19c1a09cced1438524a537a138843d5a5a9b536d9b05084c13693b55a0d9def9e62750b49645607fc2ce3c6333a881029dd65c68d423ce9d291411e03442aef2db6517c059a71efc452383e21e1c27d0b8ede31e50895dc927ffa9cfedafef1db758014250befc62c009b7cb26100e14777f45500673f73b27e09ad7d0ed4defba1c36e02b7a6cc29b527eea12f436cf7e7ad6b92d8374dec5e1c737e81e320f5dc429550695f5d37a0155fff2604fe0851abd0bea2a80bbe88e482e5576977c42653f588cd45b147fb40a8c6d8ee36419d1c868ab6137856e76c77b533cb2c2c26181872a2d206f5bef4ed9b94e582d91ba7789ec1265483e2d4ec9606e3027b085fea5984e159bf8977b965e026cfd1dc5a80b89854e6769c1680a568e1812c3df4eceb6a337d1b82a2dd30ab2c1f490280cde47fa0980d7fd211ecdd20fc894eb27224325e6f6068390163a21b7fce587e85d2624eb3c97495a9d12d465444dc1e2f8091f1bc682b6463529befe197750740142ac01f2e0ffc87d26578887ff9e7ca0608e43b7bf00b65285c7a72b842446f58214545aa94d5ab9e8554ee35e9bd449ed8980301fbcc2b608e02bd8063f2626242adda5582a06b7fc72944af3df4f50cd70c48919eb7417d32d228d02b50a5d8a44f65efa03a13337aab7eaf8879a7f57e3735718bdaf86b66edbbf73859cec474e0778f63202b0d5fe2b29da7077b1c90421d82713cbc1b76fa12562005fbd361669532cb57bbd5a4aea1963d99cdf92228ab71c496d2905d87be9a5eaa0de2c405b6acf982915c6fe2aa6f1c77247ec8c5f1bbc60ddfd45d00a2f6dd6d0eea939fdcdceeba9d1fdbf2a9171ab1a61366fe08599343ac2799c66442ceb4ac1161f3892e6f7f6af3d5020c07f896fbcae068acaafee5732b80db325160a2868b5bfa6822b9450d17353612bca3480197874b657da52565ec06852975a7edb43e63fa90ade386eb1cd154d416cc5b74a1ed62ef5d7cb198e7d7af79cad2828e30c15ac8c09cb6c08430b2e7110ff95e620d211ca7051dca54e1561984dd98998eee98a5e4bf79aee8d228d10ec2d6f6fba93662943c92729342121d60e8b1d00175837a9408292bf17c2c0519ae3f288d606880598277653655f1b666a5035654ca7b03a5e5c98ec5ab3b8fdf2b61ca7b0b2c114d51368d15b0179bed4b2196e60fcb67efe80c174d963bcdfbbbf08d1b0d8385b6d93a0000466925fe60f55b50fcb51b13410362326fceb163cced4c3792ba59ead0f436a4faf24acff650a3d3edefb391718253a7caf98ece0f3c659c4ad897264b69148b848cc34fefab6bd6a238c8ce1d623f018b911422e88477155457b8a629c111e07bba3019d0b10e507034d118a7d09d68d1796340a49afbc61569be1d5a889c1bae696b56b3092dda91121b5d126c4488518b344e3c4c83a63a77406de7869b3aa5326e71ffbdabea3722c389a449f7c045fa128f01c94ccefc8f9b4607351fdcc0506d623ec3dda6f2c9752a5767b6437c0af1b16ead053647964cabbfa5cfdc052125485bfeb9139c3e749f477fbd42b81ecea1261f13e6fa5bcd8be0a9e5e0a99726bb82c9463f38b080a7d1fecd3d157faedcda800f26f405a7277ad2a324a321d8209df5f58657c2945153a05e9f8535f610f14bbfe2723f9b8592c86809c46ec32b112f993e01b3f0e4c24f7e08ee2990dba846b5f9407b33ed4553d119860c042f2d9f947040bb9bf2164c88d901fc71358643eefddafa0d4aa4aceedfa2711f3b2fdf4efea48cd2dba0836b740bd6ff448812cfa4a79a5e952432049e84b7ab6e74fa0faa07861b6a94f2f31ae165010605b42f1b1036a2bdc8b145feb8d0075e8504d76c5763629f5e49e77f6aa301770bdcbbb15549dfc25a8d68face7e8094f928b5fe56682a1418ed3eef083ec0dbf809a35f009d4d02994a020d947fb379f9104017cfc781c109bc0243b45254bc19f2ea43e6959c38b35acc718458e3c509f84e004f618c329ae542029bb6085b143548e68bd6ea3583a1180a3bbdd47a2006785b95ce528bec3cae19f40b1380891e33b109395e3f719b425863ac0f68127a8fedd8c6080799e9de3e834db296e972788e0552e791a4a4c1fe0bfe1b9d0fe1d05b7a671bebea9e86eae05b849e36dccab19248534aa48fca4a06d1d7abc303b423d9c725d6f6c8b581f371b1e46e9cf83eaeca82eb311afaa9749e1d5e914f6c94b9cc51b6054b4d67efa007789ca93abadf387a5cdc99d20ab2ed02dce3f1279d351464b5a65229b10222c7bf47dedde058599efce02b5e7d9ee9c52a704ba8a7ebb3e52eca39efc45f4cc819d3f5637f7ec208c3798cb963724004b40b5577e81c20ceebb538b7cfd8c095c6875ab8bda08cb713aa79b6db61833161e1283954beef93b5e4a0ce08f1b3cc8da8a254bdc2e3ef7335428565b3630ca10b2c2adf99b46a7b95bcb48a798582b51d08d906964d3eaa3dca448627fe6e3c8e4282e55e5f2d0fe8ec7c2371deb168a54598b99f0e808b9749e9c08c7223f410e54777e56342594c96457d6988819792ba658d8efb751526e61df36acd9a805398eb1ac67a82290d7719c31738479d44dd825e91de36ba7dddc2cb5d53f74bd843ab6cf86b0a8cbc0e6a96114891963deb156514c5c14ee177e3e698702f5c6f4046e74f508f4d6bd13d057eec510d811d2d77127d4d7d183f08644ef4fdf1ba127bcd1a147d8dbc88d0edf13a0a37b23a09fb8d712dc1bd3217013d67b36f888f43a6ee6f58cf49ebc1bd918bf7bc158826fe5869fbe521ad34c79a454852a85674c6238f41f1cd520f5f03006df1c83ec227880e2919e46e237b73b036e3c7e8f60d28edba018f4cc1907bc894c0f32eb1f630aa8873a1fccac3f8a09502f75664639003e260e412fb7befe3e833613e380b791f981ccea63cc01f552c70798f5c73103ea499d2d8057de87dba764d38d7bb82b48a2ef0ea81c0de6e301dc962907f89ac79b01e8b90e6cc0d42fe7c5ddc3de67d066621cf036323f90597d8c39a05eeaa8623fcfefe24ee9261af80b9268bb019aa387f958003765467e16f470afe0e7e861f25e003765e1cf6446106848fae992862433f589727b4310fb18147581acecc7cb41adf279a733d9a38d4c0dcff38d643993487ddeca96a75e13fe3dcd3bf38a0394ef17b6269c40f0cb5b0f4e6c438f47caf2b24ad9ff059c6ed0ee868fe438679dd5748e0e20f16e103adcc992ba47732f4df339ae78ddf7a4551beec64dd9d1c147b6cc5d49a03cfbb2fc3121949b50ea75ab3a41e9969abcfe4602057f4324a8f43552de5bd4a743d86cf7c2190ddf7eebf00fa6205efd22f625c674629f5705f08412d3cd6dd66718c306b98341b7e2abad6b744600f1c76c8bc3cb4e2bcaf03149262027599c73588c59151c795143580e444e857caf278e2dcb5d78ba3f4012bd46254675aba42bf24667a352e8381226d411acad468f10e1eaabc2a540b59c444789a308cafa2bce07559cd159712e4e662be5808521a1b2143e4cf3ce5fd74f02089f193ff7071aa5fca48a290d04408a19714a0cd79e024519dcbe99712005eae5befaa33e19d425834b12866931cd4775fcac8b21f6078a88f51e78feacf0591e8391dd87ffd797c9ba32503d0beaa77f22a3cd606401cd8e6ac897a4efe5c9aeb4e176545712f99a49d0175dc2c984dc2c5248713dcc813d6af12a2a4445380de1a1ca465b739b9e4aa496a82918e7eefc1cafb5faa3c0b644dbda57c5ebc8082614122df3ce0e01f5f815f0d5a74f439c26b3a0331a0c805c3bc00a23bcb71e5abb643919d7c08d6c1b5e6c0dfe4427ce108c3b5b6408ce9463c6e51e6e4fb1dfdb1375fe6d3897382f85b68c4bd873eb660cd03ca19b6ad1d3bea43292892400c6d372ac5d721c33360a567ee83bf8beef8dde749509cb22aeaac9e800a7df2aa1fc0b7ea3d4aed5120b497ce3a06479dcbca1a22ebe0a7e356be924563d7a4a1da34031456aa3354be818f4357a151bb1acf1505165969ba7864088effeab407ef4dba4c20ac3b40e9ba2cdea650cd89b1f2134a97bc066e86d9ffc575706eaca809794a11a4bb322b67f0ae322feb323a642e3ec77fc63c277a4f6cdfff5cbb4ae0ca8d69ad2166c353599fa2968da65386253d948f2445725ce891878c70c19f80410fac046f939e1c809d61f8d42394c15aaad7bdd834682a0a4288c1d73ecf30cc355a45c431596283a119d28d9498ec6c59f97920811bb59bb5a4d06d1a8d1004cc52e585eb5e3d06109491828ece1b76874a5315edcc2bd7cbee72567919c40eb3d7f8b968019931e46d0a849a16e6b176e685fe9d5d888b8f5e46905b0cfd0e2d6f5c63241ed49921ed9ace540185945b1ea36034b54a62c09e43338808b7581366ba9e948c401274e14394cb5ffcb890b97b4fcd82ce6c49d5cc8585d24b35252422069f7a790e76b015ac794f0958f2c3e49eaeabed0fa6d16b68b553236111805e9a94c14f1e303c1fe3cef18298a73b8e89bf00f7df127f91cfd14513db5aed4f1c6f1d30de60c25c8b3c880784c41448306b4b7e987f072841e5b77724b0cbf30605eeb501d8d2e73d6fb569c2f0dff974cb5461dffaf2bc3ba4f86cc45fa6885f37488ad6175aa143f7eab8c2efc98c4e7c83e21db1618c67ba4b6076b367d525d9fceb351afc55ec565956f8090a9090d4d152c41ec3b6ed8321bd788e3b6ab075003740a043f124ff118527430cf0539aa229255e51cb8fb2fb68cc88f7ee7d99f7d92674c60d7219f39a87cc0c9b50612e0294a940c7b5054f78c70cfb4e426db918176010a006556d70d75677adc0b74cf0b9451285f5d66d7cd50c060e7073f66176e079e898380ab50782d6f6fa720bbf19137b01eb06ce4532985a06e20f9dc294bceaafe0c4fd9cb6e9553359444944b0926297d0c61c5ee9a28ec03ca6fd6f9240cfd82aa1f48004d0e583c4d6ea12c379124a01ef5d564d6743fe5c9e664379f2dbbc64a50aef67ba19f38ffa93d2b52153927ded45970fef7295c1c448e817645e60000c1c2084b11ff636d83e8fae08bd40da260448bb9ca6cbe5cb62d9045254330d4a082a811489220034b04a41545064e7182d31abfe2364da80e31c606304683b4853c3c5b860686e26e6df509e00e313092e78090efa12c73a0f95772bebb6099c4afe1aa4dbcce82c933a5c584a457b4bc5dd10cb98c4007a535b17e504ad6d724a68f171407bdc55848d0e8a1fe8e8a14a527e0b22ab091bee35d64e9e86931e70c585a5d238418f7a085387f2792d4c1519ac7192acf8f474b063d1e0d004835ac3f0f7e806dfc6855d263399246f52686100e93d00f155f851890a6d6b5e5a85a0ae11ba27e83f197717fed9a09d7073bdcfe006d1625d0b331125eac04d3a1cf9e1a250594e382834ede15cbb0ca3fb98e3f0bbe4ffce48ba10130437920e964054535b5d0c3d6230dc8b944854b887278b3e529a0510dd17842c65fde963060dd22095eb77d3f20c90098f7fe4340d5977fa11accd78105b9aea5945ba4549d135bd82b7b0c41d4909b465d0986697f05510a8428941bc1eb5795d78182d76e1f31d30eebeaba92e3c971830b055596a832713a84522bc2ae886ab62e2a3eed5a575876fdac3e7078d3115282037f35fd878202fbe6add0e2532eccb61a033e8b3db914524565cab5705ff1eda7ac2e23c4c3aa224ea1f9c4a47944d954c072011e41b41d58c823c5d6f0efb07cc0436444cd08da6865e5e1ce63a0bd22cfac8d81c603f5f8d22fc6b2a5411d6bd161f2c04410e42d7a3852f3f0bdd21fa63102cd3cd1ce22268a081a629fdc4cfab9392d675f4c19eb1b4e32b0e51035ed471548454374a06747c962dfa66a26d0fdad6708c72db3e500933b15f1d85badda750a3cbfb9f7e4d6b2ba8f6b2b6dd037de1e6cf1b23f00d3ff15c9d18c457684dec6a22dcbb18e91d278ba17723632779d87b68a98faf4d7adc5ab6abd6aa52960b8810dce184c6428c9fa7e6d5efac402c958c517c5466b33e8558b6f7978e5ec1bbc2040e19a3a61f25ba16d4e618293a8d8ea48cb3046fddec41cffbadf148614db1c96f50f24a62c5e1079c6848297d7c6dca1cb234475e40ed4627e6765004fdeca9f0ad487d792a03a15a6972f03eaedfbe7570cacda5d24a60749668a081efd65e4dc38157e2b5f3dc2c93b3d2727ea0c0df722fde204950451abe3d0c6df508d87fc62a124436f55590412d4754339015a95444001a9f6965fd2f51f43dd6308057abac751ae261e0b0d1ea60b7557b47bbab10f0e85d2a27485cc5bc19c93048268272c96d82ac177fb72be601ab5b67a914d9020e13d5e55f84c87c77a59ffe47c28324e155e319fdefa9e402c3de15a044468299e541564b70160332813212faf6778aa3afb7e96ab632272224991f70ea62f4106fd815052420a891967987a022e368c70f4bc478eb92ccf46f518489f5dfd5297cf62417048e9e42b99f85b4308cd7df446207ddd22501494d83c4590f6c422dd41a114dab53a382fcaf02a03a69893217e48ae612f9984a511b4bcf0987c6d36a54002c17e49782362ea71a731705b4d7054a1cfc89a21c2abb98eb26512a89d702a6c391a0f6700da08c9ef2b885b84b4d331c544f00654c86305284e2474a07e69b9dc5514aa98d66672cf9e3f9fed19c479cacd0e3c4516ec68a90ba496a5d612b09a0a1b3134e15654df49528cbb2030454949159a26ab6070b1eec627e7daf469ee262c072d0efa0128312890d2dad16b264b4a715c1485db2fcf41b676b072bf961a0b99f761050efcef75b9b8d4038ee31b411875b7ffe7e3c91b0a8d5453eff15f4e8a6daefb45ecaa1c2c645cd324c621827a343000c1709e0afe1d41036e5039421270994f18167bf2faae6c8bfbb4b2cf35fdb6a880451e467a4327f8858253c700dd69273b7b87948ba3d38838377e676db9248fb541535c3c8c892fa5746af716a4f1d294740b6078c25b26849e593a62c8de4ed32221096e566be0a77a1b8d0d679b458b3d0e2d1ad0d648794d5202c1f2480072f562910dc0aa81a25a0ac75c222172a941275826d0aa534a02e38efd52104572202f6cf760e1bafc102d13d53b2da1f2d98730381d955255d3fe1e33c9ea9d9d54d78c37d56703d5317beb1ba8010f4859e010d5395137eab349fe2ad63362ac8d3be3c4379d65c4960ef9662f6b499bfa38ef9db88c7a6e659c522ab41a28b814a4c32f4076929bde014090a93b7088237315add7567052c69a83372a24b19855431ed214a2f6e588b9e74b9610e8a2668e9781db29ca5a866d886b8f07a4ff9f84eac2730e67e5ca22b35ef237d37c891ca25d133c8d3ab828efdf921505e8eaad03dcda97e5003443135d960c4a8897eaaba8960d6036aa1393ba040b51a66ffbc0e915ce2c67117bd5c8589145345be93efc3a172c15c78e5b0cea83e76f61e246e29b2541b4a8d7a904f57e10f63d6a43f74e363540f3b45d8d1ddbd46307e3fdc4b2b1736c8d9468e34083d8156458a1578351279d472c25d834bc1e99a7b9a27de19a9e36e6a929e6e46d69faf147c23232f5ed47362fa6e12c54c3720b5fbfa32337a8575736fa04874d03a8fe28ddaf76bf85f9c5821fd19ac663beae487eeded11cea8a5887547c06b2abb5ffc79abd9c4e3e7cf80aee549bff034940f9c7ea6096954f24700bfffed9d1364befa7485a085c6c5c2cd3486dfc6fa652c2c7fa14d61aa0cfad64c73a32c9dbda72e8d775361f3b4682cc566c7e3d77187c3d11990530c3edcac28dd82d19b4ee3b765ece5c17c5422612ab8cc40c8e6c272e21488da3c9a497abf15b1e6eb26fa1df191b7dcd1dc9a2a92b8dfbd2ec935bedbcbaa2245ef5a09394842863cb3402c64540a856c0dcf444baf52850504884e02be5b075bf72dd586a017cf62196b1b6e40bcf037782e14f3327a6b5414ab48c61b54977169fa54ef82b244d3ca02ff93fe3818f9730234f6edcab36d8c87cbda2e3f620fd658bb8f8941067df6077ad9696c0b203300184f011be2388b5699f0ee8983011c95488b3af7ed85a521211713d2520b04acdc9c24e27a14109f16491831bf24b537f0dbafc56f90b220e725317dd4bed2046b3605025619a7152d524b082475877a002150cb88d73a7194ee7ccd8fd70ee3205e6ed9d5b12db943f2573a3ebde88d0f5f68a1c6b08a8f9941f3dd810f30bcffcd6c7b87911d4cacfc2907221e258e1cac079df6408f38e7f1f4c70d640dbba159d685bbed319a007581a74080f342e262629bc4d407c9b07f1ad9039f250e3b3a7caff7420d1ca365410d4474b53f282bcc957fe17df2c889dcc15f97e1877ccbcfc30a8ec656fd182b6a5bdab34dc2f6ad033a7e40894541c2ef1cb901f4498be03598b6dc4506660eb7a3468e5d1915c1c6051180bc1bbb988722b6c28364bc15a416eb0d7f315e4ff1482826dc5383d47cac656ad366c40b773ed5a7d1add6f2310830926c2ad6489927a8ac35085942eca4b5369d7400d72b6e8eab7652872643423a68ad466cad66566acf65a1da7052240d49577bc1c83501b8af838d26f43e01bd5be3876139fc030a4c7270715c6a89fe9e51b56a106c7e50a3b5a4faa2a707225399aab3b6638beef0921ca68232a80fe551e124eda5c394fbcfaf41050c2908d9b604dae9a5ffd24de1e9a6137ba9b07d7eae76df041ca0c01cbed2bf8e8331a540cca03d9e1d51bc9eb715be3f7de584b68c78549e16bd398420a68e20e1e7e3157eb7cc8a7a53952ba69d6dab9a28429709b272d77d1ff2b3a283f04d79456c8c554256daaf1d86c8d7dba4f791aedc4a521cdfd1461d7cef51a56d2c0ded5aa19f14c77ca248405fae9fdb4ea5e0e48b58df1997affdfd4ce0a14fdf055302bc60fdf9e6e93357174a90a4f9d5eb2a29743296d022381e597edff5b66f21ae117602f0a53a943212c89d7104d3a8bd97a8743fe7a6e76b259a18459b3f1cbcc7a1c71848c774a9a87c4c8e54af68435d84ba94465d021a61fd305b988a8e3c0091d7cf15f0bd1bdd0b6a91d2777ce22213f404de3183b0135121baa8265998d383762c54c57e4d24d2da96e9aa778bc41b648cf79e5ee8005569b7820e05362ca8976d531b8342f048e4a29913a94e8c711b9fcc8165b049c0627f2cc4945c0125f4ceb75693e3fdce0d56d1b4389851110978bd15edcf3611e6a09a9ef40d2579def28513f19cdbed1464d26b819c66b517404cc1956114be8989f19fb461b40bcf8034ab21bf6a743550f3d06b976dc177d42701178cf0fd49144150b747c297da677dddc3a34446280da3d904839f82cba2c7b014f25a63421afdcd86ac812932c10d36479f74bb3a01c3ad121d629d16386909e2c051279f0c14482ce7aaab6ae46683df64b547fecc026bd2643628aacfb5b758c479e39eba1d9a409ae8166100b4f53d13710296865b5bc6b11e34cc5c71daeff22bd9c07ecca20a744f6574103b7bb92392b2938f14299e330a16c3a1910bb52321160f96e1534954ab018b51807cd860c6b81d6f5303ecdd152550715e18788a40effe4e6e76610c96a1cfcb5c924ace0e8b1ce8ed7a3a06b0fa7ba07081c489758489b078e317cf1e7b95517fab6cfe5262bd3aca7636ae3b205739b7ee808ea71398f663dbda3e72b5262e93b6373e268984db9de77bfacac9700e31e093c0dc522c3b284f028004ff4f45ff63c5cbfb4cd4b2803a2f635f7fbd7fa5c0375c589683503a435eb3c585b4e4d69014e545a7876dbf900297e177f4a573b895c614fc02d7fd21fec683075fa7026a5fad333130351e077e59ab06a3b5553402babc1dacf00de5f0bf31161ec06fb496f5a5ccaf1496e62f3b06ea879a822285d16851cc8044306af9e21deeb663d3203d395329927e151d11d7b168e5d940f7a247b49c833810a57052ea5e81144f0e7d42b36092bf50ef154169e314ef5072fe4d33ae4da98dad290bd1e924596e4aa215e563663473c4240b70c209f776ed4348fe050f0f2b32f92213ab02fefc600401c0d881d8f1a4dd58a8ba79cc4a8395a8fb0a0cee3c2862e10f4398a18c577a79386d83cbfa221922f3d6c94d71f60ea6e1bf14ddc8a3b07d6b3a4cea92054ffa2c98b6dada072d020e3d0991f00a64437bbdd05a3f56b049a88da1f31bef1a4a1de18d8690efb053e247381c5cb50b76c5ddbe0f506ab5c0ac6910c61d222db47c60d63569e3a77bbdbef4ddebd4afd916ada6f85bf082400254a78454c97b05939a0db68ef0cdc2320552df468b4db3a98c1b805747b4405592f1212b0818ddd82d584c9566edf6b46dba602680bc18d07c14644c2bb274a00410f773635d16ca7e308042901a944aa9b3438fff707720d3f84b34cb2a239930c695368989b827814070b1c83e0a0d012e36fe0aea734f672719d7307866eb3cde91525aa8b89088a721b586d93a10baeeca2b503b4aa9afa753976e7c4a2d4a63c92c67d867eb25b461505b0c5e34ba7b9ce08646c0e3de5845e3207b8fb8f10b2253eb7687166afb8e24dc7725003d6518493f695d5ae553903e847ac8b3ed84cf09f5f764089a740e86db5b2c45dc1638c9022bb1d70e79a1b15486cc97d127a9a05af2c9cf9b938daa25237d56dd10945d9f8809dfca6f898ae086c34d130654c6e2fe4a2786dc79abc9c5cf2365cf6a3101b8cc07c2facee84af121af0842cafdbab316b35ee169a1641b39d79d084eb2989116741e0fc7c49607c76453be314de7f594cc38de136ccd293325098debc61c3ecdec93b6181267feff5eff1b22e150c3f2b75dcf8ed99099ac011ede4e135934c45ae73253a98aa4a109ec092e0e84574c92217f2d9e6d7593065f1a32b643f4df7310fb11e70006e008d4a16727701e718b99d82d3925e82997ac7bea4986d7f82718615818b0a171862ffb488d1e4cf3018c05ae7979eefd9031c3f23422958c0f902ffda4271010039978a5962f554b2807e0902b409af9ba7c0d1a997a19dd7a4176d8deec6f73f066253a87121c902f5d7dcb9177e42b3ea66fed0dc073a649eddc83cc6fe7aa9a83766ccdbaa35d79329f208d4455c80c4a74bf5be85f216386c5ec56c8c468c32708d45332a8e8d5124dbf73105c628b84b8403b07b994f49b682d0fea9005ad91147f9622aaf5f929ab2eb88028056aa1dd6f91f4f5547998b33cad5ea8d2c829d19b94c5edcd78cd76cdf2a733e833360be1d6d4d7f95824a492e49255d1209e679126633142048927287e3ede7f4d934df54f492a5cff0251e0cf9a8d0d3fb864c4b7d8e60149980adc89dc5ff2c86d6fec4c43435b8addefdd0824637b81c9e5693c9bbc95bf7aa160361fdbd9ed0166756e25d5d133cb0f629d11eb74b91d1d0362dfc8c74bd6d9962551032ed6c03e014d7a7e78a25cd048371b6950ec64ea94b966b63a0775c3fdecf04c5f199a5704b8cf855008e442818eafc2bb25698bd6f39a6bd34f74c195a5a2f7e9fcb712860d250a279393564de2be7e7ab48af5daed2d2ba7c4b27319994ced4be98a23101fabd10aaa0109cc0b85b2849ed09dac4c023856b4ea3f3dffed681dadd6898d3150fd6486f5f40726686c96309102d3d10b7c11b0120805960ecd72c71384c852c1b83b7f2c8f2763c4afc30fc6a741c070ec0ccc8ac4fcb29d09cd3389b005e7c2c4422d27f06876942c34beef9c71d78ee388ebac411d0d19ae27a47ea12b1901017ed9001bfa2c8c6d03658b10b22426f357f275386a7559911630f2c4324966987d3886da7c9873acfc6b7583d07749f387ccf23f579bd9259fd9b7626ea6975b6dc7d83271366b1e8d747c41af227384d62355f1b6ef19788a7b5ccf82a22db6314f148dedd43bf614030259d211221d34d619e4fe9283743a52cd0a1a3b34fd04aa01108ea3aff5c0da0757a7e293334163b32a212d0a68e4c85b132924f9a96794288d53a1aabe90ae44725b8061686f5c09e1aa2f1e5ede616db5fb614c900dcc701b4cca2a0e4456878c16f68831a465f01a676f08690806d1dc468ae446811d9a19ce802d307ff33fed9a91a88eb65c995497e56e783c8b4ea7f753348a8e06de4fec885861c4ef990a3b854ce07d2cb51fbcda373fac1363d56cee50f216627539adcae54b28b79f40d5bcf9d36518181ae135c3e0585e48e0737e7a2a20332414b85a31251231b972a127e827d7324033be7bdffd409246540f3609b9e34930cec9e3aa0a149a15554ce0fb0d012e882b14ebad95dffce7eaf6ab1762b5b5898c31b02dc701999eb4d35b69d5e7796517334baebbaf009426c929765f890def634799b5d82cf7b5c9e4995b84c1bbd396ad7b345c1054f355343d2629e1ddaa2790ac0a08bcbc40f24b449625f53e5855c1aa4b0ef0ce44a7ef7db02a19061e0f9014052d588536981f2e8c202e4798084225b0e0d35e2036776f90232cc446bde23f192e55b9fe469a8a989e854b22aace8f386dbf0938d533c681edd300a95cb17d21b966a43d539dac267a22bac4bfa536b2954791803c9335ce93a2eb84c1997ac1db82821aa2137911674b1f54c5ecaa94485160c4c9c4b9ec5aa78d6cdd6b19b812cd73538caece124c7d6e8ae4b8acbe81efa25982ce8c1ce8b20494c56b302befd2d27ba0e441bca040c3abfa6d5c7e1b6843bd094a9d5011960068b4c072e8d2fb357d6bd66def86e0c555ad0d6da4b9cd34db90469bd36c330d6da4b9cd34db9046dd03cafaa546a03262048ad59252a0adff77a08d7cc410a525f4beadc73220221a6cc5ce309c4dd49f9f946399d6e13b02432c55791f88474a1b8d4e3f7e1b9b28991b782d14af42e05508bc0bc14ba1782b14af42e05d28bc0bc14ba1782b14af42e05d28bc0bc14ba1782b14af42e05d28bc0ba13cc2c6b843e117e0389b12720808280f66a8cda021befdfdf2d5aed4926b27d89b2a54c22d055f434b02eede1b33bd564c323ae8ad43919af508a186575085843316a1d5d0d7d1d5d0ead1ebd06ae8ebe85ead0b8ddbfc6ebb7a01b9c06fcf17d97dd5676c30ddcead0a13270ecb8ece7dcc8accfeacf8e229f0400bd2ab07f0406e6a9983cc7713b7886720cd09445e4e879a63560846b097f35cce061d5fe9efc4831d54d4f5e02cb003ca9818733cc89f4bf58982212cb479b2b156d50dff8e6788b1327f5aa8371a48938f2bccabe0f45d756dd99a19faff0c9ce1317786941f81dd8243e0bc64e69b4fc6bc1ef44ac02ba12e9ae23e3b41b9bc3e88675864216b318d89685cc98ad39278d9aa9c28428b2fb70b57e29dadf580dbba22f48431f6283cb16708679cf09d024822cb309e38e51b8d1144d46cd5f834c2dbed0d3579142695fd9814553a8fa31aa2510bd003ee4f74a43f69f0ebc933c8049444c108c718ece809fbfb1fdee443a95f06fece22a5a07293e1930231410744b2d62315471eb1a6903ed440200424741f9deeded4abb5d7eea9a2f068ecfa5f211ac5e991001adfb9ce59e615a18feef4eb36b93974844b059447068a7de85c41ab7c4be0a7821d3a548a9a70efee927504951fc9cb163f1239f1b9eb8028f1a1f4b5eb3bd2d4c2faeaa8d7e5c5cd0bed8804cb13bd7acdea44aa9c6fbdfc33c0925da78260e88a1b7f529d2d2af9239b95e0e6432bdf556ae2e1391deb2c0aada7f85f49740a7b3c3b3f47b8a69f778c2c503a58e8e8326bd779b91bd2dcba0b44cb4844e5ce7941d6658ff6318456283881ed53c77abed86dcf7229b38dcbf373d804d351a5561a693bfc3b7b7aeb405eb5e1abe3049ddb12017bd4849d9c4fea297cb2e746470e1340ca0f2531179f15eb0b638679303acb65aca912b42e5cba87cf255650100b7a42adf92ad268c5fb2bd06e06d9b87919bc5466d9cae21b4278f4ddd667442357dbc7a9fe648ab222ee0f1dc05dd8d5670d5ba4d223880305ffa2e4322e29b4463c2f00c485f82ec06f50718866b3b27c36e1a56fdc4d902497bc5038993e2d6948e794109541f3664a43042af643abe100ce2d236b454a131beeba492c8f77052c26e71ca94b0e820c986ec5af9612548ab91b8fa488ae50e2e565c22c28967bd7d71d034990888d391fb139850989cf6c0812eaee9ede1f28a9ee655784ae7cab4a95e7f7bf86a3d778e96f649e25be68fed9a96cd299457b5e56664c8c6560a1651957282befcd751a307ca53a9b034d0aa65ccfcd56d08e6d040258e03ea25ca7cc95f0d84b203cbc6aac8d3508f94b9c3cf905cf602f75627efeb66c11c61e795a1f3c40116a71ba18d328188b1525f816af930100115942820dbe14e44d45114e6808518eeb9459cef6932b1adc3917ca85b533532668ee0073ce4a5e954012880053fd77bf062c6fb66c49cf30bbe76c1bcca4be23e967199a898db7fffd8f0667c3b73337d825a9993a42d9274d7df083f60a778d63e9d5996b2f4b429b6c6049af189b29dc1998bc515c9d968a57d7445d5e0fc32a9fa50561dcf8163cdfe839aceb3a85e185b2d69de7712f82e58b8c9472c2d92a932b7226096888bc6587d0df41f93986645f981d1f981c307c0cf3eaaeb2d738d6536a2abf5d2fef582a77ac1a60e635fc162031672c9942be78ea7ce519d3f4a46e3374d2773f809b582786ecf6fcf06cc12bd0ce048030c959b2f9830e4c8673f76a9f969feb9c649c9e83852ff064ffe63f6589baa6a28ff150b92727b3f387f3a96b3be7cce9beec68b05645598dc3451ea06201bd7ff9ef84286eacebcc577cff0a2c152f4375e7bc51d253bcab90f045435c9da3e80cc3b996fe82822ac959c623453e71ca3352f303485f2d1d3aa5f0574f3e882be8072eced7b3160662399555ab5f10544ee31c6a7fe3b30f5a0aeb8ddb7938bb5bdbc93776e1d8dfbe41a96008ea2268d6564f338484f19113b15d26810f21ffef21f305f75e61b36470089fd4c75a551668849245548de0cdc93f88af28e8b7e060b816dc5d44688dabf98ebd46fce2bc413b4b0564a0b846e8fadb635038e81f97255795830fbd643b1b18af927b96e6382117bbfdbb653d01b93d32e74586cefaffe9fbe635f35dd70e03e4558205115ec93ae1033724dfe2d7e5393c43c800cdc18e20ce0946aa3676d8a4a8938802cefca41bd4c2d5f5f4c9a3bc52c93419ef254b8c5cd09dbda75ac6dda2b28c9850d57f52a81efbcd111c95361a7304563e9ae92a0366cc2555818e6c9a3ed003f5eee3cec341f050e3923dd90739311df92a6f929585b4c7b3c43c2f57ae516aaf6e2ea09bfd20bce08a42487780274d6f37bb22aed59c77f9c91c59ea6829a0cac126c42c358a102137aae97ad09982d9b456476a20550131821e9345c784f03c9fa8b34d8fa1b60f6bae096279c9f3a308c26768b4ccf5cf6fb7e7876a37f7b90143283fcc869abe12fc8aecfeb3b414b699aca45947947b0c32330b661b0767e1d941bc82a421af08563c64e0412d65a9bd1c347a305ffb5244ea305f64e67af2e6cab886a4c09a5e8dccc769f47889cf3171a3a71eeff546f541e6296e468e14ea5214e1ada44092c046d1cb7b17c1ffbe1058147aba8239a6537c28dcb07b193d0b3ecca35be6886dda6d0222d4abfcb610e2b984aa9e6910897b49d33a23dfcc56fcdac3030ffa7f3635051ad7868f835c8814ab1517a7286425e15f6ba8e552b5d12528149333019cb0d4f4d08608b105eded8c0839597c77b6a7af4cb052d970ca4aefd02812340126f336e04fd5db44d233e47a79c5ca4528ad21649d6fa73066e0544c5ba14d79467cd5d24434c6fbfc706639ac847dc54413e6ac955f6284fd04494302f12cbbccb41cec829f220568847cb27b62fe342d7200e336a4c0edbfa9ea0e9738aefce37d6a26b923657433321a8b21fe84f9792a26111fa7424ae713ea5ad106e87a46441f58fec640abfbd18b7df0c1f5f10032a0531f89e1032a53052ea98455d0ea901bac35b23b0957d5bf1cf814af6cc3c076fb2430a4391d35223961784bf71d0f523c54452f3083eb29baaff8b89dbaa803e29abbe668e4643dd8fcb8c8f5d7bf00a2a7dad7a2814b3df0087b7d129e8da5bd07c19e4a6265e257785806604b1b3d67f1940d4b62108cb25e92eb16cd1455c636626a23942215d6d394d512a21fb34477a054111993f4bbe050f85db058077a0dea8b956d330e5968004b75ce527770a9cb0a137afd56bae7d9031a05e55616a41b08ff5fde29c2a5aa5d415fe6749964b8d5db7e9ee363730ebb3bd7d56d9ec5669043e1a9a0b80ee079320c8e69b2403cb152f808196281aff8179eaa9daed92910d82f826f5e629853af0b2075203aa8f0c1920cdad08c526716957a4c5c4805ee733b7c725138835bd28c6614e1187302ad7664f9811b3abd3d385b81159d692d695c7e439616dec04a39bf3809e9864718e3be0b650aae57c04cc113eea2757d4c910beae2c65ce4a6757fb731a568c6a0dc067287435acc5733ab5628e5b9da83731b7f35c814b2877f699a05fe51e1fcc2989979cb0a1364b3a491512a2d82f28918e035f80c7f2647259e247df5cc252e333570fd920559a3980743419cb841b91c6a815e01c5f82c91b8075b53267e39f273946894a38b468406ba2011821e4a2c41ee42e88b89e792d1970c3cacc9e5206885a3762ee3d0a643aaac675426464b08f2376f06d45cd07cf09e121115a9dd92176254cd1ba46042bf5b131630460a930774e292e5bd5cac7d2ca83590291fae32700f0367a5076ca3214ce328fa99059cf7d281a0ea86a124281092210eae7ddd416059c8770455fad9d70759ca7559cbbb9dcc21b84395075e06367ca3d0bccc9a5003297018eb394bf16aeb96f910ed68c1c2ec314f529c3916c67f0f7c2026595d327db4acc01bdc1fa63042353de807c0ba533f9bc67f72a92cf867a196085c97c17304d2a8f010d3243cc0c3e7dcefffb7bdba959015efb6ac52ff1383f907b5d4857170b6bc82a415b7460df1180c1c7ac21c224d8a84ab3f60cf1dd9ee982c1be0dbbb2f352c0c71e99879056550bd882409696d2430c45eb48a566d32d2dd80e25becbef5ed1e712f76e477371830cc4365174c7d9f1ce5d1894c9da3446cfaa3e34b3598e362fe845d91d17150a6004c21c1ccd136626097006d4f8c58632ee2707b8370df420f404136898b8bf3829d3a15590609a7a02dcc0312a06343eefc6cedca6df040b07c9d1ff14f59e27c84c3d6584ab2626cb40b86a0d8f573619beec9b9ecf926b39d830793b69b4aa2841e0c02ae75b7d6a9d77a36d9c6f7f1c2e35926839d46f6e7a58fd85058dc760d7faafbb541197146e1f8f44a8b42ef1fc6a5a96545f1d387c72776c5e53d1df7fc24829c543ab8070982c2cfb55201c2838dcf2a843031a2000a5629ba884da7289897037a77b20c0a60ad95a2e0562fc2916710da767411b1688ed2bd97fd40fa07fdf9dd7252228f316ab54ee606de5bcc0996932e8d540b58f7c8e824173032c853681e45b506ce6bdd47bdf46bbc303d5734895698f487ffd90faee54eb870ca551a7fbb665165350216c387eb8be38a1931c94de3bfb3a3af9d462dab19270ddf4f293f49ae239afaeccdfaf66bb392d454f74282965a63e027f2f09c006a50abdba135041a1478758a77bf93fab3b1d1715b2c88da512e7993de07e5ae5c8f52925906fc9c2a66a7527669951ec08728e914862a00acecb4a74462c1e26b46c3f7cc89b5d75dd287b91906fa9bab83615bf2967c67bc3326e0625253f0fad52672586b7460e0614f1969bafb875b02fc488b1a9a4af06821d0a7c4836569f7ebba8c84068f8545fd366bfaed659fc0c0618ebd73df14eb0256c86b9a07d615bbd4b0c3053a8e6adbdf3da4bd1115ed9d54fcbedfe179f82c3a9e49df11587c3cba4c4de8c5dea644b4de0b81573887ba626805e5f53a3bffe6989dc26b60403f3cae4aaa8eb89bb63358c5b492d8fe4cc4b802cc96338c3bd5d7b25a01498ff023743737a7e0aed96ff6454e05c71de29f632cc9b1e3bedc4522932ec3f065139d007dd303e3dc4f6b57ea1543da812f0d4fc70353e552268fd1f5d8168b30b2098580c54d0ecbd316cc192837918ecbcf8d5ca74ffbeeffb8002312d74b31d5510326d86ebf05613b67e196f66571616dac28701bc5a6595d34bc2988e0692d9f0302606c5250a0dbe41d81716f59fe15f1ef9c7e508f8827d2b78a48c02192983801123df532694bd15280a24bad11f125f916cf72c250f9de6b8a72180eab7d175d3b992e4c766df65c1d692067a199c1bad94e80b0cc047881ad250025477065016c2a029c4012b29418a61d2266c4db64a926c0cbfb7beb997f771d28c44a460c422356cc1be1caee45c75149c2de7e37afa9af75cad523f09eda555eefe306ba1bba3b5afd8639e13cb5785ca24c095300cb8d44ce86edf70a9d25654b5acd4862552cbb357f4b657b47d11fc1a69713220fe4e33f7922796d1da9035630198fff0f8b481f8c559d26c6b41dc05abaedd268dbfb48eecfcd5be8108d997c348ac0cee5ea01b3681853270987ffce9d63a22e8dc32a46e91a51a761215512dcfc2a66f6e61b1ca3a2b93152c42fc9420b1fb43bd3e22e17ce30caa2ef16e980cf586111332e9451db943c4e0b4ca6be331511d4bbed4424b849605ea40f6bd277d2fc2abe738c85a670956c8e06dd3260f7e6ac1a2104759c7406b4f7a005f7828279a531f691f1750fbb3439d5ae05cc3d685c3acd1e77483c5ac433d4c604624a126f8d14bbcd8c623458da7a8d06b44a3805e4ad8a4767318630f33b5fc8b7b1278e7457f3aac0e15a98de384a7bcac29ec080aa82f54b56c14f292995c1787c39571fe6f8136a1e3baf2cb95254eec0819d50e1f26aae24f18d7e56327a5767f32450e69f55e84c4918a47e829c2b4c241d5591d9e164ed94c5ad5df4a8cbd8e638c5db635adc489b63996e57d52a546eff848b60c4f2f209a5e00c004083cd63aee427fdaac72907e4adbbcd5553646e33a08a3981aecda72cca8ab09c242f84c0b0ac5407411b753352f592561d8fa66f3e90033ea05acbf9c96fd22126ccaa326da1a46260fef69846b12c3fb269f0bb1275f67ad95b9a4ee49ce560691225126f10b81e7c37cb10dcbdb38418480701370028cbf9d3f3539da51462d599641c197583a80a66492dbfd90a7ce88b0da4d99fc775a5d4aba304ec2a4506928ca2832822c8b66da4c7733746ee71be829746d040e7c447da48f5202ba8fe1e13f3c1525b6501d281fc1ff349dfc238f4a3b05557ce5a44fad74bfb508af5f8f621ca8694811227ef7ccfa96a041e88a509e41be55d224878f986daae1fcea8816c1236c3db2516e12c998a1a8a049717300390804b2664e554b3ff828fce8c0a55749065f7c7a9915952feb6679a8e43606fa45986b1bbe70f4b9594d0a7c94d16b04dda83cfeb352864653ed657f3039a63814fa2e34f2d61abd62f1a79708937baa453a5016831aaeb9106de1eeff673bb3ecf7988be82235d7a60ff7d40c3e32f5e16b7a806174a4bbd11b914520fbd71681838c9ddc0634171de08939306d6ce3e2dbef7e8aafc7db286d225d0f0d23ed830222125d981c7feb01706423729d06cc75bd839c0f1504c8fb20cf87d5854b260c45fb174222ca056d5782216a8a0f02b22b7aa32ab1195dcb353738d86415b46e6ed349c71cf27f1f9306c3d69cbe41b94e76bde659a55e6d1d18a980b5a10264b286cf1dfd02f0fa8ee7c4f72d89e761c7402c848f2f9b8bcbfe7835a97caa24ad5e53ef2c80f5499540f9e8abe89ed7b872ed53de87bd18fcbd86da992c11795fa74df6cf0e9a30648bb9b2f4b6dd5a12ca7aa9ca7c6a7f60e4373b6c8400376948508f2d11ca210f833bf912c7f2af027338e33c27f70e2dda11648d2aa1ca147d3598d57dd44cbc89ca2ae329e5176d356bd94970357cdd0ea5e9f88d3133d888e8921244a7b666a7fdd4327f23d0d1938a572fb52238e821b0a21bb5159ed28151218766888727094290af00ea8b509155e80639186776c58fce36da8c27354bdd2324bfaea27274c70890de349de0bcfdde41f795488cbe24e07c61eace6a434f72b002249469aa43a60affe18b522819fa2c5e3ce0782bbcf7b72af6035a7870c1b3fde2a9e27e2e26567454e1aa7b00a47cf4729dc8004e14a01749fb8de1b8a50edb2305bd3189f6ce5ac0a51142b7cbf7f657dba11a1cc607bcad9e67e256750a755f345d289124c78b1d2addccad99d24568a414c880d4dcbd5e1a495120f11b449803d6d9ed6ca1b9d077b331c4ec8be734a4359f53a98e82add50b5710854838083427614c74ac4d5674080b6f709a3e0d4b6082885fb991cf74212ec2d5d736d4aeffb365b59fec1a1e779cba30b6348afa3e7ec40933ec7ac20865494795e8d1a3386b38f0a2d94651a820aad2159b0c419cff855c9f4e2c906f2979e232c6495acba4d7a103295661dd8200743ece1e34323f9974b50911f0cdf48550e3699e03b175087107584e2adfd0f157d2462f7fffd69fb2d3f0f6e1e6a378d1e12fc903da48cf902149403dab65e915e3050b2a20e5664526d51adccade55c2b1319e7f0893857117715777d46c307fb75de6d7166cff9ba6119f7d3f0b8c51a62c8905ccceb0028481582d2625da9c35642ce826692bf041fed3cd62d619486fc4ab68590b45d42f696524a29654d099409b108ae1abb971a3b971abb568d1dabc66e5563471324fb579936d8e0273bf1945e76794b477120d83ff711427d0b6f3eec6542a5f711aa2aacb0bbe9af8d211b24b04164230c1bbf9c9f9c175c2f2e39b71347a7b3a10a52e56c69554c608e5262fe1d099ce061e26683e8d2788ed05918bf9c17a064c9f9b13939b0d052d7edbbc893d64f1b442f36886c10b56c109d368836f82ad206d1ceb9759c125ecbdd19175bbc61c34f3ca9af55cc248fed867daa72ad9e2a0713443b58a283240e2dda756bbaba12af29b165ce964c782d68c806eed26a3e40c13db181b3f9a5c46cf31b6557f6d9ea3dc7369b79b9aaa338d07fe62aa43ee66f54e121d19a9aedcea874fb96270a90f3e0680dcf0f8f8dd6f024a1b7cee3029df9741e22b4dc652009227e42ec76aee7b5a01a8ad792500eec8bbca6a496e33526e4d853640d5744ab478d20d2ed9f37aae8faf91f10f5da500d57b35d5a4d499193cda4dbafa44dd535c963bbb9c125e3fbceeae59538124c76ca240f27648c322ef64993d8d99c32d9b232338aa278c79103bdc4d3eb82a0aea268429d7878ecc4a21c320f241e4e9c52478043e0e8c148e90d1b5c2b9902388a9c76d4aa8f1c08f69903c5fe04fb17f779cd7c8c2779e86c99a3d01c1e5168997797a6cacd4069384bd0997d1cdd9de56c8e0d9c2d750e34c7060d349b77b9767997c46e86b7b2a01dd88fc15b31a037f649deb282dab0cfb9cb0f6ff9862ead75c5ceecdb566f08345f64ab473bb07ff3038da77767f62d2d7ad2ed9fb408876b34d8af25a11f84e05339a037f2db7fce23e33cbb3bb32fc379743c3ca218018587cee6f010414b9bc3974395bb341e2274b6c40f47776939b4a03668a050ac746b737258414b2388683d74fb28f2b469b2a47f12d7916d840bddaa72dd82248fed06887db67a1d17e3f77767f561d896394f8f4a083e97895edf5e715d2bbda648237add36d1eb112d7490123d48dda46c8c284e478e6db67eb9ee9903bd5ed46513fbdc45dd1675dea5a96e7786d4cf5d4444afdbdf452f994c260435eb433046cb4a8c134fab479e7854b9564f95d37a830d66d0a031ab1979d49c7878ec6c699fe6c4d3ba49da272dc225b1ebf66b4136e76cf53aaea6c4e6e46cce09e4fa3aae3169f5e88d172c26237b4e7e50c61ce5c41e977d40119b6d9ea10289ca5f1d57b8e3d2f4d71d5624fa89cd8152b5940e7e8e1d36c735b3c53d8267ec9067acd04eec93f2887af078bc1f3f7edc6c8bf649793f2ead96782d3ccba3a1e6b96ca83a0c41ddc2dbb9d329603001c40e3b9d02461260cee28a9e9f4e0183046004a9885832ac4050b5d657f0c00219a4a0c483ce54830115921d16b564d8e20fac2d78086221d9a84e8f78f840cb0b78e8c00f0f2db4422084c5e547e80a212856332d4e6c9611ab853d06c11a7212c366e15ab010da8017424458495bf4a22505bb14831094a26b95a9f5ab6badb516819328436cdce9911324946c53a7474e4eb04312985ea07012f47264a73a3d7292c48991136bb584139bca04fbc4450cf6a6a2c5c57e91d2aa32c46a053b385165b1c74e8f76c8fd6cb1d3a31d62580db1c3cf3ed2a10633e57f79a40316473a201de93084ea881d767aa44310ab2c9bd5e9910e39f02083900e2e5cd92e9d1e35e14285c56e757ad4a4055aec53a7474d9828f1142f847ea63c6a324493235252700a7238515314e9e9ed941e13d3ab64532af5b8341fcbebf12a11dbf776dd3e0d4e0efb052881019636befd52ce39698f5797e4f184fc34c3680d1d4b2f8a2f9ac8d267ccc1a08833ec63af390be9c3bd27345072ad08238a0f2630628a5503453e9f79f9cdcf14ad144a8088a03c618a378928769706a1dd8f7979ddc104a69855c0015d75a1071c7ecccb6f80302b100f5408e1c4bc9c42e1421366453274c39997df2062622233f0e0635edee2c1608aa611f35b832b547ce6e52c1e0c4c511c31a7489c00cacebcdc3502531c47cc2d0d4f7420c8bc9c364103533c8d985315cc00c6cfbc9ceb4cebc2079af099975323b030c5d48879cdc0932a38f372d28916949882c8bc3c0610a6d8d2d2c2020b54a698434c23e8d13832875017d0b89425e6220c3e493ee0cccb73ce033098e26ab5aa1e0022d28539a41482256e64c01c526198f967b158170344507c30879c6e22a833109943701043b0800a98cbd56ab584e80106e6908c448710b0f6767139f1d42398b001c91c92bf78c2c47f7910b088d9423631f9aa248ea9636dd87f29d95fe586fe72e2a9a517f6cb88793d32849420f3721823537441316241cebc1c048129c23041451343e6e52924a618f343aee835624e8d28e261c8bc1cac628ab011737a451630d899976f254c312663841760e8cccb4322a688812930f099f2021d5410040bbcf8e2c9163bd4f48b0779b2ba25bb26779039caa14d5fb4b27bbe96c52afbdc2f9b8e0344cd9d1e557141cf242dbdb0cf906e7b6ba034db1b58c4fed89feb638d6820ae316974c198246e80de7bf1d5faefbd1483af391057bf14882defeb1f3a0977fd3e76dcae05608363cb19178cde9308b96b92daf2a76b0c669167d242c604b115e01ef6f59cc35670cfe79301f6f9f00de33ad66124f88665c0388c8b3d4129fdb969239dbefe1981b83870cb48d82bfd32b149f68a7d81bd62af5cae2fd63cccdd8b43ad31c6d98728f2fd3bdce28b3aac467a7dd26907c1f075883558d2213e3de694625c2a954a295dd2214ad4e187a1118db5d618c573224371e42790b1638c492a7bc13ec3aeb54b7fc84b8fb9c62188bf34c2dea4c326f204824326fd86a10e35c518c40f6270c418c43804b5c6d85acc73c6d7d61513d9570a07604ba5c230fcbc7314b68439655323df39dad1ed1ced1c95f889b3ae8f799b9e5e9aea53a9d487a9177fe7a87eb0531fa6c89da3ca4198dad1ed1ca5322f27d9f2e61e15550ba777fcda3dd521cccf1d2776763d7cf0c4b37354e23bdcd1ed48d9d1d99ca3f077766138005b07793852d93bbb9dddce2efb50562b713f98328222f37e8f49f1bdb7c5757998b4b1c581881fb0d613026a4fa470c308a3d76a6b36ac3d218a63f67513aa0424fbfae951baf644aeed6a4f9cc43a9eb8b6e99f15689bcf3e155a84547b625773a2b6ab3d514322e26705bb86544f19890b6a73e8d39568eff70c71317fe557a1d6eff7f4572645d839e15e9997e9f6650680a9ac8b54a463ceb786d12d3f8710e9f6a9e5b1f4a2f2d3146a18affbbab4a8531287d1453cd257fe5b3fb044ea0755cc633d62876fb22999ac87640ab21ec2fe9e42e5f5f0da93cea8911a20bfe92f2fbd29f50b406fd06c6d5cfdde1d0670e896c4b43e3e25a0c7dc7756974801443f7710fb74f518b494b2c882427de0b735f0724af24b2d618d34a07e6889b8dc498916930d44a34f0a98d2078a44df15563803cff4c30271bc921295aea128e421dbf00312f1c2364d65df106ab0e5295ac46c084a76d805976a69212409ba331a6e71c3e8facde0e7a50444aa0c494e84d8ab205a599450c1b077a75392a4a862b7743a25098b1a2465e940151c6021b14b9d4ea962c90c6c36a7f6e09af20219bc102212e94cb5b54b3b7dc9243e7d1f2530e04703e88d9a7a940eb5b4920638ea77045d7fb5640168cd9d4282ce77d0528acea1232af11a2da1f43c69e1365b07d3a25a8a3fa774466f8faebfbe0defa51ff2f8ae5922ecdacbb949887148770d6200b7c051b492502ca2246a40839bde32c824977cf8e1449fb047748009ed433fdf099d2afda4452745a2d273165ae4fc6116473de79e077080620520302ada99f96d76fca0bfb1d3295914d14d9d4ec98228050ef5fb62135b67f54daa983a23066b332682e8d6b7997510803b53032e012fcb6842cf5401ce0841c8a434930422b139679de1870975067aa3d29ad09402f0e6baa20c3046a3f034530525a388d48c942d038a1619455451ac6680800584092d242e4db8c0858399f9c5d020be4a29f65971158783e966c0bc180e57713d70976653711557d6b0cf8a2b713b2c65c0a105f4b208dabde0eba1e22ca8bee551d0985352c5b556fd7d1505c57c023f06d582ad5ff53f4ee38b6f2d4f7502b101ffcf1994f8a9d7bf5f4c71d4264f143aea00b4a7481aa4a3481b5bda04509346946dbf64378bafb8fe919734b6d4333d544f59507d901e53f520a852bde65485f1d7aee62adef2f43402355b9e96427eca65d5d1e9b5da1251288ea2b85930cac2ef1e359d2f69707214a004066c16cdccef0ddbe51f199ab139d60194278e7467124593b525d89cb306f5f0c1001a53586fb60afc3001880f05e2801f26fca03c072411e90c8e4d17c73789a2c9dad1447f333425bb430fec9c33fcd163878d8e0072f8608009404aa61c8e024091212bd4b1b1c1a9361d86322ffb76375bfe655eee652bf98a8f119c12a4a09d135476bdcccbbc9c9479bc6c25f3f490de8dda76669f1ed2398dd336fda38d68249a8976a289f493fcb339a7d6655fbe12fab44da7fc70b3603438b51cdaa67d5863a86dda88b6edf034ea1d0e220e8be29813c5caa35ee46c361b912119243d81529da854ac58da68aabf9a63b24406437d04c1134fce75ebb2e59f60faf14f536ec95f876c9e5e19b2d96c44cc5cb73fb26668682753e60970929479e33dc1684dfd717cf04b7c2481506f32e54ce23a048e234986f464b168c39b941b197b5ef6e0d395a3b8611863b9a24591103d345992c4151363b6180bb19fd812315d0c2926458cf7c2440ed6d3b1d3a1134f327e3268b0faed20f6908e221d46e2c9030ff8ce6d478913263b38df9b7c3edfcf0b3728763c2a44b1675b6529217941fc116f2214e24ea442e4dd6eb7db11f1762322dec45ebf81ab9f083fab9f89b36c4b5e411b8a0d8a6de440a489fc1c2554dd40f23d54fa580a89bd93cbe6ef86a1958fd6209104b7d3953e68c807284f56bf17dd1e32994693698cb110b3c57e624bc474312962482fb11f97d84f2bf6c38afdac623faad84fec27c6db297a61c29583f5603d584f04dccdcdcd88f260e7e6c1ceedd26e70c464d040c6efb7faed2054ab9fb8faddd5efb4faad7eabdfea87514aac0d32e8e6860c1ac5d96ed6c40c89c60d3470348268ec00e37a7169b1563486664dcc7633241a37d0c0d1d8814610cc0c698634439a21cd90f66a86446348f6af1267d866d8c69103c93ce73e422397f9176f6e6e6e6e7070703cb8b9b9d9447b68fbb0734b9970e86e8ca4dc0cd91c1c49e0f8317d37449786c3851b23dbcdefd24c2c38455cc1f9b139a6164645374437443744374437443744dd8573eb37243bb83bdb59fd4c269369347f7b68f58bf11722230f70dc68cd8eae5bf116ed20b125ce964a76724137b84bdb71f2a4dbbfc1f970b37303c0cf0480d58f8f1c888f5c278a000c21e1d881f03372020713386e386ce60fc711a31f1c448ac8626231d21911612484510f463bb91d18768e500eec9bf80e921ddc8e125b06ddd9cead8822b04401eedc86ba7d92ef04ed80f0bbb41d243b4c40f8ed2801e167fe7ef5d3210509dd2acb7832a14ca0d6a249870e48c74e8794532a0913a77d3c712019d9a36464fcccc7d051a4c3680f79e0c1cdcd78da43434348e864f05518337c5583187c8585e42c1ccbc6f259fd56bfd58f86837767f6777cd8b9eddc3ade81c1f4f6778ed00f7064a91c708ee3390e1d8e221c443a8c8c9ee828b2393884307b266f0f5d9a89c583227c1ee82ecdb4e2a688a41b9ccd31ab180ded21a326ddfeb8878c9674fba73d6494e488cb856e7fc888c850d8776e7766fe563b37990c0e1e8e2c463c6a0486c9349a6264486e994cb8cab2faeda1d56f0fe93da437d860060d1a331d5274e856bf9d1b12ba6e7f276773ced56fe7b6836407b7a364f5937273590754218a2919173687231f3a7db1079a63a2e5504b149dbe09896a9f4eb3d0f2d09d45a1a5a59f93a0395967cb9f4be34f3fef284de6a9ece967dea5fdd3cfbd4b7b3dc52d4f75068a84f8f5f04d3aed2dd949fa914e3fbb40697947d333d099fd3363a1347dcbd139d0d2fe89af74fa580b9aa3739f297deca337f6531df4a88f795ac5f124d6310b161d1142f4d0c4d5317669e9d71847e12192058b8e08217ae82d49b253a10cb795c7ce9697a35e56929191f9c9869011c964349bf25db21d0c11313719241e48a329d5c718dec29baf0d7c1b70d1eaa98054391e3a1e5154a63b729c1d8eee7453bad4127255bffcf617afe1ee8c890f4e38e898ace53ce0edd3f433fd2ecd9a7ea6df29f572e249bd8b7813611071e2142292d813b1a0d9946fdaed441f8ab77cad5ecb4a49e38741bc8938710a1149c42227871544224ec489381127e28e88381127fa0c70a31dd84ff156afe5b325c86baf30624771a0d76b97041142f4d0e4b58ff839e2c7358e280ec4f9e74cd4439325207ff17d67b483d728e362c38c979f64dc47a824934921b185f06518ce96b1d88927f5b1ddeaa9722d1ead4162490e6957920d113d9102a5d583d96518aca48239da325cc8f8647eb2216444b22832dd8bcccf45e6d792f9b1647e2b999f4ae627f393edea2984221822626e3248324832484606c885e376c56cc44e3c36703670a74ce248f9a9e1c2cedb808b0d7c375baba70252b57aa656efb67a63ab576af55abd560f9f98581b33391b386b63cfe4646464546faaa1ab11a5c68e66069a1b4d8e260718d78b4b8bb5a209aa11a586aec68e66069a1b4d0e3439981abb4f3e96fda979fdfe6e167aa3f6cd93917b479242e1f397fd5991bae0a48cb48f9385ec637f569e6b8d68fbb3fa53f374ee16754b94806a6adc9dd97fedb071ab8e1fc6a9f9859420748b17a61c79813924e65f3c0875c28a2dcc2043681256cc185228f543f41353686b2b3627f5b47e0c16be7ecdbbb4578f9a31af44e76c89ffd4387be316676f5398a05f27da0619c1f361a8f4827d5cb3fcaaec13e3facb8beff22cee12f3addfbdd56addfa8c4e8f8ef4562ad5d7138feac51b7e4fd7fca2f45fcd5717cb5039583d6a8571fcfcce22b112dc0dc3bd47f27475d6e358bcf42dbe42eeb917ae9528b14f88c4f0ea174a13a1505a473484cb31b11a8ade692750a0c64598083fc150c0d7fcc5639f7e7f4f8fbdbec784c13ee67dc062c82042f7d5638a5a6cf0c7e69cdefabc7e5146e66bbdc6a16443ec987ffda97938bc32851c740206e5ac0dd0d6f2324eef8c359224c8c496fa66cb3f413ff8a77efd436a9b3662cbd2b684da77c3f047af803ea0111ca8c4d2ec87faaa3e276b24b4c66a2be0af3e048a797d498d5b6926e08f911f1f5bda0ba23e2435cf96200efce9b69cc5962bcdd33edd7e875d52276923dd3e50cc2f0c7f47fbcc484a6c8c53338b9447e1462aa8e8a7f651b14896f5ab8721e8c803523a4da7471ec8650901459edf516f7a590bb6ed380cc3184cf4d2dfd3f56ffe027ff53d3dc65ff7c9ef3163df633eb1a52502398ffdabbffcd57a97675db1f55f8dbb3d186c4ca4ffd264debe0ebab4d77d5d921422fbd7c34821423e64ff7a21fc74c54c20eaff3da12dbfdf85b7f808b08f91418458a48fd8936490d7c73e48ccc3f48b9aaf584f4fabaf591e3a06520051a5b35e3ceda07d4502d11141c7400a20789db5fa9a9551e207019bce224fb8bf7addc32095f2867d62a22ea3629f190923dd997dce91c2bee236e988adffea2b3647a549fdd3be2bb6cc3f235bdb72961ab6fe33ff30efca48d9a7e6d99c7305ddc1bf3a495bb139f755affb212fe96583aac9d62426b2258804deeeac8ce1f63482355f2f00ed4b54bb304ecd18a7e6e69477b3681c6f858c6d48f67991a06cccc3a7b661eb3fb1cde6bc6caf5b2bb6bcb498b7afed6bdfa5c15efff6f7132351e9a19fb867af6024ebb33e0cec33ffba7d187fdd187f5df235c2eb634fc2eb63a410d8c77c8c1422e403f6312f24a65d78f40608dde278f4064cb7b0b7f6d262248cc44831fe7a188ff95d650711f201fbd8c7c8202cd4304ca1f3be081e9010a049f72f090448c8fdf9fb30d2fe344612baa4267ad89ff6d7edf3dd3e35ae0b187971f7872699af8ff9f3e2b8e66531f2c51d633868e3daf7d2bf6e635ee67dbc3e3642ccc39e84d7cb9edc629f184933d14e90b8ee813fbc1b88cbe5609c9a324e4d194e4d8dbb346aeadcd5bc18a7e62b081c6f0a1cfa25714e7037e806757bc518fe0a3fe6a9f9e2afb08e1746dea117bf4477663f86d33b8b39da2179ed974fb67eded5d9528aee913ac996e5d0d6e439a4e3efe92f0e2e61c6f0141348884c7a4240265ff7595d9ff0ba5fbbced952e3ba56624bab79b86eb5efbe9c7a5c76041e4404bcecb3fafd135ef62b77c1f6eff1093dd9fd9bdeb045505a9f84540b8aec0b7afe800da5ed3b4b002df7133aa0b84967f94f5c099c021efaf580cef28b377ace3d28e8f7c90ec20e1050e2d1d27304364d0f71ce0274fc3374163e1533a5e3d39f6140e79bcec21739f8b4c4c110d434867dc12f300e41cdea6d53a753c0e02289ad3b9d02460c68d197345a886054115e01ea29301331b439344a29cdb69ef8335581d29a15c0ae83da4eeb0d828188b10b3f78f553d509816ebfd219be0ff6fb345f3da4db6aad68ddd35dd79236027c47a0637a63026007ffc60becb8da08a8fa7daabf6332051a4607c90cea53083df6569bb18db5a20d184f5491d2c2c32e5359f659761a9b5e576044bf23d8a2c33ecb977dfab21f76fbe55b0e1b62ff254f1d2ce88cfd241b18b9295538a1bbd253898463d9e7bf6051c5665a53079f5f31ae2ec8d500a9000eb0256ca05b9fcc43d24f7aa5dbc7b7becd3961274eb7337a493f69ba8eeef4a84a129d9baba8353371b5c82a858191e0619c652041e9490cbab1944a9b6e238cb802046bd01458174485cb15e02e0b17fda4483d9f948a142db224f5b0d32959a88056723ec3fa38ccb5aaa05e4b4ff544804a9e3dc013884dd7e409294ce07620d3d39e59287d901e0b94ce90ecd14235c71f4b2c041912c610536431031ad4200cb3f4457acc125944fc912453a8b57bf6e820072abdc887545b51eef6e3830122260b340cf307c62c912e94be88e94d25d2059759a4f426d285d02c52a448890c62ba61c90f496218224ace347d91d217319145481a5e6bffb3d5f7d63074b972cef973ce600eee37df4b69ced55eab6d98f1b5610529a873381ab9a62cf2199de5121806a0e7af3afafdaa7fcf14d06f2d55162d7535a1e3afa6f08a9b96fab106229a3089af0c3b801a0c7358c225d315f158c3d0c8a46393ef8b90ea15bb5c76e312a718ffb8592e5db5016e0f5dd66a5083610e4bb864ba6158813ad631bc4920587ad165a3ff815c369982af1f93b38e592b30b439f5f3d3310cf36b1dbaa84e2244a0e707b9cb89c7ee36b6b42c9717ddb25f5c79a75c3038858289b9a853684fe349040a94c217ac8e22ac249a443090b06cf162c46b1559a2c8a7040b5850c002272e25c0f281d56fa33a9d82c54816586cbfdfef278910e30a7eccbd976e7d33c6f9deabf5bdb7569c73c618638c31c694524a2b0a075fb72fba6250d9985a7a44dff7edd72394566d746675b74435033deecc3ac05a79a1dbafb88aa48462f7b8b32d65d7760a34a702b6b4f7eda3406fe49c0bd0242d2e5055a85d85dacf7da335f66bb6daaa8fd6e43626eb0f597d6cb94195edaba1d65b4317494688e878a1a49fb4880a85e2eb39ef5ed405931bac7a5d08bb4062c5d7b59e55b9d2442cd4fa9601ac499b1b05098ae8fac992e1e2ca0b5ce45c41642bbb0d6cfaf5bf30f2c5db529f46a077764dfdf6f3d70f648874fa7885dbefb714b12f5992332cecd3c6e67366fd9acdb9dfebefb0393ad703e46b04d6c33c09ac97777921ad673d092e1ff331a490176a9eb8a9d3d3ab8710211ff7615e08fe1821f761fec4c54e4faf11f0c77c09f863c812eec39028f4133775f104e62e7ecdba4e277eea1f5fc459417713a963cbfc3f6caecdd5c926f06ad09de51fb426ff0baf2ef95b9cd5003acb9f73cef96b3b72f08a5a8a461a8874e654d55a7945d55ac54ae61051dd5ab12d3c7a03845a7aebd36de9dbf8636fbf56a1b46d6f44be165994785bbe66c5bf5c3c81d074d48b2f3e15519f0a41fcfb280e019a7e82f8973c5d5ef5a2c84f9a7e45f2f4d1697845a8b7a7cbbb3c5e8abf2def8c2dafea45eef2f4c4a32273d480d0f44beeb0a5e98dbaa022fefd62bfaa7691771fb52f109a2e7e8e1ef3c55f5714f90e196cd1ee18e1f5b0f7f17a98ccbffe923e602f2383c81ef695776928b4b49c7829d2260cffefbfcebde45991d852f5a20bafb8a4edf23aea0da616ddd273d957db23c6cc53f345924f02ec674821ffb027ff612f84575c4f77797bff847ad4734eefec511f83d33b8341bd88fa9ab32ef20c519f3abd783ff5b57b5d3ec52bae1615dd6a2fc99627f5f162bc6d9167c8bfc7a5c520c93024557f67aa97e1b50b8edfc2cf31459e3d3d6563d3514f2f8d7c99ffd3c5ff2cc913f5e3939c3e97e1a83f7ded02b1e9a6f18e5c7c7aba624b0715ecb083f64b02b1e9a6afa6cf271e130914fb127ff108613d245fb5a8a757deee23af667f478c5bcd6d8ec7ed8ddb2a7466ed0fcd12792cddfe5956265757a432f5c0d89724f1626a41d863ea7da84e281218b5d5c707fe7dd5df4f81d2b6fe17a6e1ea11225830f91a617fcbfbd8dff218933e5a5a3e08ebf7f7983d7e5743a1964417def7b459e9d89cd4e315740f77e448dae1eba8bd788c0feb23f9c25ffbf83d1d85eb43912eeaf3d1c396d72792f8f165ad380abddae4dc4b5fb325d58b96935d14dff4a51cba87e40e5bde47c196b5dda555db0e1f2f1b760556b0a5af120da1406bee4d01473b523e961e25f8f0895ab4a4f002426f5522a7dbb2534f2fad75bff4ed9366d6df1f81d2e8ed416fe817ea619e9a97522dfaa556f44ba3e81745be4650bdeb49583d0c29c4e557ef228508f970f9d50b699d3abd644bddbe8fa3138621892befe77f0cce957dd6fa09f8c37fe1f4ce5cc2af27fce3d7ae89f6d3c85ff8c38e5f3485266ec35f98c4e93ab6bc3e6c79bf6cb22beece6e0f5a736d77767ffa0874767f1b68f156b8aaf41b45d6b1e5fdfb3643291b7a21863687525aebb539579a3319d2b7328894525abf874dc98a54beab524a29ad94524a2ba594528a84989f925be3a73595f2c4d0e6d02320b07409d89e5a0f40774a6beaca61eedd9b750f8aa90629c6a4c6187ffd5bd21f525af89a3cf5d35c0a7b7c6e531b5ceb0fc618e31aadc902b0657d94129bead812638c31c6c118638c6d6c5969ce5f59bdd28c290d290dc4efb57c97b53ab6a46fafb5381893a10d168c41f0c41dd30feb83245de176fa18ef5a2b10561316cb035bc6c8ae7f66a49a7777469f030a809a4ee9a5a93568684a29bd3add2cdc8194527a75ba32dc85ba0d4ca531440dedfa7906a622901103df7b0a22083a33ba5898bc176bdbdb18df7cefbdb6c374206cc17f6f4c0c324a2fa594ae5431d60ac67afdf0c3bdf7de7dfa01e605bb5c2f94c6c0b8bc80624e3cf469abdffb62512a632406d3ad1e8684d52038e45385329996976d929f78e8d37befc53bd446ba3024f2bd79f743d67a469441e98c52df20a4b41c4f4164308bb3f3de4bffefcdbac65317a6b426d7b83a3cde10d360fa36d7d77ffaa1e61e006a2c07f4e978439ba7e30da90d0700a8a1a94163566e30c306752303183fd0bef4c463efa5a40af86903684da5f407ade951005b564a29a53b6c699329a59f29a5f45e4a3b7dcd6b7756750bd7855936a494d2ebc22c3bda3253f22ce1a1283bfd8aefbdf7de9818767d9be9d39bc12ca6fe76c6648737dca32dede69d61587bfd4d6baa290691d20f6888f1dfcac107a4ed39db4ae2ca01c538ecc9d556c92bf44aff71d8f8e90319f18f58e7acf3ae4f6cbcfbb5bbf273df5ba235a64e33b63f854867ce3a9364d7ce33fe7ae41d975671396c4ef8465d85da55a83d684dae486aeec5c3ae41646562cb526857199dbe78e2e9f1a7f0ac75b0764de42bfc7005dd4baff92bccaf1ebe6cd825903eca26dbdebb6388de00a1dfbf36f486abdf4bd23babe4ae62bfe5568d443a73be14c5fceb5f6410d8c77c8ff98a91416274e89636d427bb23187cb483b7077d4025dd7ea82f0f1be3d48471b10b5f9129d29dcdc3a2268bd70ee341ea16474d6ea6ec633c48fd91c184b99e9e60be66657c083d22890c6830633c8c0f7975c08cf1e2dbb04fcd8b7d18de9167adea33af2ee9168fae17592fced05c45a41147448f8e48e9b548f3bace41e7d0350ef4e8880fdd3e4ea2b9e8d2725078ea3988d6d8ff1b76ec614839e8e5e9a59954d9e5138ba15e0745a11e4502792021ae3bb3e1fe191ffb339c5196b187bdcad5ad4af5337dced970f927dbaaecd8c3304886e42533d2b75ac814198b910ffb18a903837d4ce7529012c1f8e63a1d884e87f9b7617f6cc6c3c820423e663ef6f4ce2e8c0c0223492125c47e86dc41bef05cc81829e47ab2655ef6327ee6f9ff9f54f7a4097796053549f23ff624bc901924ece99d3d09b1279f2485c06030d8c3c82142c8873d272bf0339eff497f33487a3959717796c5937f565c87218162fcf320ff3366f0e742e0c7e0e08fb561dfc5c119ae793238bdb39f0c4ecd194e4d1917e8634b1b721fb28f91b618394448257ad8cbc81a1465631e89a99cf8c4483052e87e50d555dd9d759c2cfe6562706a8a9703d98420701fbf1004eeebaf2711f05f1202af3bc65ddac5b8f0225d1aa662ad74fba88b84af74fb20c63f181bc11823612a78c74a31126f8c7f7c4c7cb3d812fb74fb9c0711f2c19f2483089d40b18fbdec39596de41021b517a046a814cdd5273d29119140000000288315000020100a06c482c16824cd0261ef1d14800b7298406e4a369648433916042908828c31c818020c3004194368686aa84100c4d8acf42f9546577efab151c12dba7a9595314b88a3456add2127ddd3fedc814158a428819b68e59b39e4d8d283d9fa6dec0a6f5795e6b08bfa55fc3e524b1ba48e21aa5a6b0c501f13a3ec451054096ff22201ac994f17dcf854a5a0ff1543978d88f6315f8ce51edf1c4d045b251e351c36c0269d61c4e036e81f9bce6e16d961a373c91027ab34c6af1d6172631645d2f4632d72518298958cdbb345061a5060eb506bc8014dcbcfa17a1b95a1cf7774ed259a90ad4a62251daf4db6048993d29a92b46781300782a8e74cf3340ad33ab255d9350222174d20563cb74628c524abc9ea8051b4deaf67b1d3e2a2e4f10b1b8cf3d5b8bdf225243b2eb6e2989d218aa50b5ed2c40676198001d0229c2fe3ab99fac6238381a13863ae5a63115171bc85d6d93f6ae12c5dc360151fbcb318417d8e4b193ce4043097ca12c066bbe6156ea0404e580ee0b1ecb463b8c9e092a098612aec14b57b294aa9d3f63275ced834c8373e498e390f9052e8f99af19f98c533b93600d244d0ecfe9804bca3e08ad4ae0110b151c9cb06a8a3f9bcade3d4ed3e1c192e404a0745d785f3d2af90e6e860b88e08d485651c53229299e66ca8464c0029ed94e97d3831f95c481e6ad477f76a389c1563a5702aa6a6a79b32108ed127e3605a7921bdffe179afae7d93566656ddf04391f35f2e766e411258548dd90e98d38af942d1ec5902057bf4649aa9a6f7a8f74454a49791bd75adec28994477ae1079766a208f8362dcc41b972ab76b6745b42aa152872c00e3b923c630c4b51207d44a2933bf754c4a6c8c394a7b2d15ed54fe434e2c81dce39881baf28de5f01fd89bf394c12823d99baf8d770cf903b7c13fb061b7d61f52d2428913ddcde1b55b56a0f0d960c002ef0f34f924931f14f041c4147d454cfa4d73f465e9410cf928c3a0d0009ff3d326d7841792e17ee91ce5c5b51fb079888636f33f6e0e89a19e812e2f7045f00d7072c5c4e3edad87e94b65a61b2366718547c94f4a9e9175fea9287e6ad1ff31e7b197eb0419636c3e32798fec457298538a40e01f1b3fa245c5b2014cab0ffc86a8589722aa308f543d899bc80411ce57cfabf8b97b4013da89cbd2cfaa47208c7d1eea334542be9085f24fce97a70d8d400f4f72928fb97a15102cb5448444f9b8597a96b37feb76389b4c405422c879b7310c97de13b125f1c63db13c55b1f6d7c7c64013ad31687cf14be3787aab896a97293fc24d23c65e63382b721da13329d0a463ee483e4a5580524ff2a1f4b169b1f53f967479cc2f4583de8f8d5c420b2d9d481bade0066522dd11cdd907df6d33301a9b5ea5da521e2f5737ee64275baceef3ff997ddbfc021fd9a7f7e14528e029dbf1ea8a34bd6d3c1b590162255cf5ca312f13a4c4fbf7f1694bf9ef8c13c4228835e5064ac358197a0f492cfc03d02693391cc9bedc64c8ae5e8a5cf7bd2bc5ff21dcca1f0f1c2e3816c4aa479420569987d81095c32be595299a31bb47b2214eeb4de71ee569198e6324ee1d0a61263290a11ec09d53e95a01ba88e19b77c87ca4af9c7ab79b34129754a73f21d95bf27b49f9092f68e4006652a51bd17a70eb2e782616a4c7b68b21ca51b733cc83aba8c008e2e3e76a0a5930d3b06737f198f7e35c649cd3a808f6b5c46c221a972ff8bae73dff587e2e4c7bffd294fce7c7c7a1d393dbfac1208a2da43bac3b693929209adacb052130ed0571031a2daa7c49320c15cb2369a109b188b002bfbc685b28f23252f0c7c8e78772c64ae4f431a1744f260fe77143566a3b28b19d58229b88207e1cd6807c4b532e3afddc871604f4634d1aa8a34c56987facef8f0542b009e809d1cc3b1183ab7901901a2d243ad1a2e99ae3510be3e1f9e18ee350a71efd5d0188a27981935568dab49d8052bd9897f1250b3c00a06e5297e6110a8fa4ee4f5125cd984f89e88cbfc56596d4356f0dde74b53b47821867ffb2eb40f5c08ed3ea13a93c67c38a353593ad266b62fa30459e2af4bee5110a9c52513688429ba0311130d54146b896755768765f298d12527243b56e7b93f2892a14c3b7acefa08dcae079337bb942716afa804418bcecbd7da80e7df72827c21f80f5e12d1e7889ab58dce64a619b2b2fcc43316c28080766a9077a1c06679dba388d0f40bf6178a51383857884c345be6b76cae76d96695cec6271c4ba2eefb70cbb087b630776e1e6377bb7fce16eb74a725ce4dce4d345fcf6819a4d95877ba831e551e22655f06893c9cf3e6c70c4dd8503b752bf4b0d382c48957e012cdc4d4842b1b60e87f849bd343b81376506d09a428792b505e16a143f735dc1c41525d65d815517507021d177dab3d071dd606983ff5279a6c535d097bd5c9a04f3387341e1acface2eb8e14ec5e09484ccfc619114ef13aa34782a869868f26910a5409a8e4599c8d51eb95a9829c749cb0acbeffec372d96efb3fe6e9bcc4a3d1fe934c5bb1cc9ba29412b4c7d74212aadc7d22293ebd9d9a29bf436b29f4a0f909e827ab27dea4c2e96ac84c693d124c7ad2a06e7f1574146e03b25ebbcd16977414a0d6c9f776bffe9ef55388332c68ec52501cd8cbe43168681adab60271d8ff5dbb2143a9e9c3151310922cbadec2763a2d4ba728e036443d3e09d34ec25559c8222d62ad4c7953bcea2714541db0282dbe7a517f5b4448c819281cb349fa247f626d06325b1ba4968c6ef7e25cf728a7f0e8ccf3d7ce85a0b3905ca652b2d47d7bcb88a4708dc9e999861bb9105f2a21b7db7ae45be48a5d6a5ce2d529002f86ad4acf60b005a1edf19bdf3810344898bb0d2f778d0d28e1ad83c2a567482f8d34f449c3b1f7f77f9c7cece69d9d2835feb328c76b653e2dbf3591b7a345fe20d08939c44e35814c315c126589f4d9af5799224508f398b948471a28964759b21711304383250caa0599f6eded1306c9f796bbde4d2762113acfb509f6309d9a993066937aa40d454d3b50aa554fcf7d5f06eea7f3f38f3604e57a5af50391d70efc77d7820ed9a2daa32f784f5f1a042aef8ca3eec91978c71564527c0c476c7800eb37015e54c86e250c6067010ab900a807b4e53082120444c921a303f88fff58d81799d06806f70b8d701ad48f540a1a15b355114e445a9016eaa5f5f44aa4e72350976bacf73d9bad4dff0bb7eaee1d10f6048900dc170cafd3a6aa86113388dce252692de91e2ceb87f0bbcd89745faf8a841bafbc4bcf4d7e4fe6a9584b6e38c61eff3cdc7960bab9c76bf7f80c99ee7a01c4ed4a7a281b94ea4cd15de36bb5537c0bd95939e8312723ae140345afffb9a0010e3947724eed2b73de3d7387bbb9aa6c0242757b05c86a28907db40f6f248896caa189cdc9f8fca08b4838f62eccd42985b6f756d6a07036588ea2ac5f74351b62217d271a56b13223aa9dee9dd0aab65c13671581bfed8be412c01967ef430614f48d2bce5ab556e1fea9b791d4a00f181a883340c8d69c345bbfe2e5df739361d3ed19a5644b41192a26edc2bf414e39e3efef9f2f667cef7041c23b65c05be1036c65d540ed750afa63ef0e743edf1d8e5432f4cb3678dcf5e2ddf02031d740b11bb8d1ef840280c281966f73a07384f6bb040a214ce517063502f450cda6d23577a0579b36857521c6929c07adda577ee5b419cfbba5bd916b6fdcd9ab8cdc5bc20606570cd621ee0ddd5b6149e8e059b5d0122ef65af24b960059e6e33ef1e5a449748769f37520d35182526e7b27773839ee796db9ef18516a2f2f73fb83bced84a4eeadb8dec82644229c70ffcc36c8430f7aa03c0af5e7d15ebcc5f117f72c2475f5c7633f0a35e1c62d0001443a71d988569b736deb9586a651bdf5524c0a723ce82b390dd117d569605891e97a69fbb7adb411c39ef0587bdb4c7141f428a8c5b0903610fae8426d5519df1805d676882ecd6dc7d8f70108b52025d141085962cd2e3064535dbdb92021d0c806702e94d473bbb9f25f9a14ba68a8bfe0b29c58ed572905072274d4b4ac0b3cd6073ea655c23920d87aab321697cbc238996c14830262318050bf7cebbfe369ddc4ac5febe9c5b30103df4dda35e182469ced96ea05a8599f4bef21c82eefbc21e9038f9b31c45aff77b8a1c6df1d0a7c990e2b8f99fe4c626c8e87b98163a5df172ae906d6fa07547a07244fc837b0f5be861050cc0421bb7e24c192218621e8464d622a02aca5d3ca307524f938210c0e1d990408b100f4e7207c076db46f00c3f05c555f857d1c80be2d100d9152a7898cb0c60d171250312ce10c91fc6af1dea34b4f474d71157169470bcc13034d1e1905244acea926ae5c96df2cc97bb3712be994597480ba8715507afa9a595b7d4547f274bbae436ca13336cd99709fea3bfcb148e8e935cf7db6e2c9a2d4728c7c69b14fe8355ba57ba5a5b9122a59d7d6c248ddae10fab1a580ac75c94c23ec41cb17a2711d1ac328de7cebe6322664dc5b3e20355a4026aff461c0c93ca162bb42c16f85ca8d753fae9fb3f610e686f3b2ef9369a421bbd586ecdc1c6584a11b5ba026ef3d56a0b5442ba3e438b924e78c7b6c16fbad3143c4a036922d139ce5f7ea899f352049d7aaf61c290ddc6e922dbd6eeff8df24337a6c5cc25ea0f86d9615512e80aa2e9eeb0401bf5a6d5acdfb828b1ae6039315a829a3f255114ffa9f66445086b67cefca5171a90be4d5a36cbfac7d16a7cc77483064ab7a71e1b6c28505514561164e583c9ebb61e4fa9c34126269871f39216bf2a600296c57b4314a3eda5c5f73ce37c25a7aa78cad16ee1841b24a88bf7611358d41f72943e14ce4b27126cf0cd4fefdda530546b13da96066dfefe6b76d83555f586100abb7509a724813eb854283247f6e8be3b24636f201f22d54bf31697212f2ddefc36f598da8734840195158f455c7fdddc7b0a61d87373a61f9d919eb6ce4592a7fcc1e5221b5b0240eba510fb601a8c4447300564000a3589ae18118a4f4c8084e480df4b7bf036ef43c30ba88d3ca2806b332f480144fba241516d4c8bfbdd243d1c22e01f567815754041bd587037c5b3a307574836b751de4f43b030184bf340ba3a1099763b1a8e35721f5ba9756c12b1f4df66a1b275ee934b6729567ad008bd93123f05d9cc55c69779cc934e1e313831ba78b4ce01c4dbb8fd82f710900a1c98b66b1d8fa85c9d10a87f7d892ba683d2e6c94672c1eeed84d20143c2cd9fe434311c6774eb49869c75b93024989fbfb10148c5afb8cf24cdeca25e21ec33118e347608a38158a104e3261a32e4b70f724222f981dd38fd9f231f99537618d08d4fccaf8d0ad03f4b01fa9aa31c09446aced4b5d1be9ebae2171998d83accb3700ba8c3698c19966698087917abe5628a33e3357b5e07b9ea97f58980261b1efa36f62df257778bdde035fdbe8eee37f0fd4aa0e3c9d81037de8e56b49ddaee1427868a8bb5c849ed0bcf394839f0423508c60c5e0b0d0b2362be3bd06b65bfd3900d99bef5bdc6496d78d2ff072098ec66a664629420172669558ef4b075a680ba805a08e52ede9dda4d50d260e870eb1ac3433a26af158bc511f0a648f0e8e571180213d87266a5b70d820cec0267c937a7a3b3af515a575c4a1533b2985894a5e091e4b68024735dc820629cb40b4dba834bac47990de18b7a03d5a5d548e9abab3eadbfb0908802c0ce366b5b4a7b2a9a770192d29f64ba5f5a9cad9d8104b3353afa2144d17a2cc00ac6d657c866a675c3ec0e34d12a67fd9e360ce9ac91d75a73a90b79775271150c9717489664b1e5306943b311f2038bde865a7934c229f0d301b382d11e143f71141cb98b9ac71938a1a5bbd6c98e073d1f613674a41206bf49017a76183d980364140acd3e81d770b971782762707a0039c13ef8f2a5d8ac8e1c187db596c7981eab0a60c23ca4fcee9212c984ec09324d046eb9f5719749f48910887fc2a1c502afc38ad23a924d206f3f93067704d58349b67dca85ea3a0645b4b5c8644ddce37717fabb1b84af9b02e852b12326e92f4a668118248d874f04b373c648c577dd9c8176fb19c7ed7d32e26bc698d6ae04b488831ca01eeaddb880daa75d831d2f0925781bece3692a6cfa01d2ce3656364a131a3f17578a4c06ab5092e489162cc7c9d0c2b0e7affc917a5823a77b9250818367c21944a484269e90024143950dacb993dee27a12ad43c4ddc06824bbe56e833755743c7c0ce7a92139a1c16b02f38ca8c808f00bb10f8bc687ca465e3c6978176353d9c1dea2ff74b5e938a42c57055c8d8530c5fa25c865b505a215e7033c6267b86fc9d025254f94d88cecee6f8f242d15eb43a89f3325bf3ba5d20ee21b7bc1c14940bc6c5e82db2e526b98156ad5e05a6555d73b209fd80840add2a140a706927957818c23d2871d6e7ddb8067a8d2fdd8d01cd051f797a11343575a6e5932ac61a31a27698d94a46b45c435561f419e73f9d26786c880044493bb8f222b17fb2ad6780a910d6a1129ae5beb150491c55b6adab285d042155e1375263478ff0cec03812cf74833f873b9729a093bef595fff81a785166aa92656abee23ce186aba8452d1375651632d543d2e6e054a757a91d20ccd569e82c054a995ec1f9d309ece72e59a4187ca6ac3dcb6c47d989f28c659842215bc30018f261e6ed14716d18b94b74aebe507feed8f14c9a7994e9af02a2eca36420a5eecdfa4848bdbe36c06709182c9ff146ff326f645d33d196a5fa0fbfe2a140ad8e9c620337b66db9cb2e9b1abc1a59f5ec68b46e666a4a5745b831daccfafa7d9c4e5c0f7277e545b412c0e6915012c9ccada4da157cbc4e8826884f18a2b2eb3ff86652d32ab34ac399c11e365903d1dc734772fb6b18dc91d670b70c49fb3651f3e7eaab36280d4f086d9bb3ff2b717df002f2408d56c4d21291515ad3e314b255d536121c35a928af171273cbd5ff0a12d27b78b539a2f60c69321e19c2bb6d8bf7089be4bb39b758bfbf4702951337a2af1d45c929771996b1b9dcc621541fffbdf90033bfc86eceed4b46cd9a78d31a9c088303172008937aa8471021827081053f8656fff33b4a377c863a721b57c303b491e666288705532f7cbaed8dd644ba487bf45447f9a535f150ff78d5ccb0a45bbc2386ce70391d91cfb7f3e97288adf0ac404caf1ae627d880a9c624774326486457ab897b9ad6927c2c2961408ae9a30100687442f2d4cfaf09fe430599e556cb44aa3c0c771f5e968cba1ac4d553079941ebc11502d843bc06ac43e063718884dd8a9ce6f9d40ee087a822851227e0b857693497c433ae9d409b18a93e96808b8d6a8191e5293d1952cc37e0a9ecc40a093618a277c0a378b527f2762bb352a71504191bdea4f44bfa3b897d4956610c8bb59c83284400e851223ce60b68569b8ad1e83718f6d2cde0465282fcf346324ebe80796320f14b101c5cba79d8d73fb94f95d36b3da6a4a3cfa85e917422bb6c3173cf0ac9543f104ddc67d3a0326f1a90076de8102e4e658af89c550c4b8add691ecb04a732c0412908dec7cbfd848a101d1d229f0191831fa6d3edb330b4540e8ec60825ed43dabfd9c3bc2c9babb057b664e3a00ae306cc50aa4075995833331bfcc0d9160756345e1c62460dc59ec97c6544b4170c900e868c76186ba870048b360463a922f59e49cc3a7fd190732d365c8762076fc223c2892063720c14e0c6cdbec265ed05e08644a5e85a43c509a368aae733afb8aae68752b91985a291dd248557f1464146390215dab77ad21ee8089d117a6ba5e9e81922d9d2f81c65db12297373f43ebd7559b30e2d734363afc1442e301a87c838fa1d084ceeb471ba357c2b2e38346c3e9420ea18f68ff6470f66cb9c8345a02ac58ba34fc0aa09d548de014e4633bf77a9d9fcd81b1e2f0965a6882782aa35a2c5cc30bf85e3b6b39856b753071479ab86c5daaa60e6ea5aaa775ea35824deb9b6cd76c027b2ed89df9545b219cd79531577f77fe98007b2a2161419d805b431d7aa69e97807c495a9ffdf486e00082f1a99246c87255ee3149f26c4e2c81f1090646e328ee7035e211f34715814649a7405214ba5d92278aeda159cca751e228bea3d2c7759fffe19868c8ebdfb2a9ce91bf32ac19d1040cab1d8dbbfbad12deab7d87015919a31399f29516642b2de76a85450fc1d91242b0f6564bd691ca57988aa787ea7b8c78b7bebc561b40f91a129179979516315d9f8d6bcc1b4d5c709a9d37893ced037978e7bd39a663056ebdf941d78b63f040f57c3deaa2077bc15706abc967f9412af350607db02ea7dfc2262d5cb7f6a002dfff4b3a79180c81006238d5b391414e11621096884dd291e24d597f82b44f095a699dcf1825348278da04529516df60f9dbe1c1903d9b2f18cf764c57646419825302c17978fec68ab50c422302b870a7a411804b2bfb40109095ef0e78b6fd6a866004e3322f6d9a8807991284040ef1ed3104732bdd86ee34d45cabce1baca9622887c30d13f3e5894d9101e13cfca10bc2540997f1567c518e004987e64152dbcd3961ffd06690d22715b11358053dce38e32e622b5b913dcf3f6534388a19d18747f8ef006ec9aca2b754c59bbfec5042abdb607b6666f83793372df67d53ea2fb57898e41296c2eb4d4dc9de0a72bb1c06552e886a4fa5fba480bbe17cae6e9707ed52b6151ccbbc310bc5e8e80925121e32c4e13755b6260ba44c227b8a88cd8a207e3649f210533ba17357db55fbaa8c3b88e99c6c0098b77b6a52f0fe9558971969a50279e44bec34c7ad28ce6b81682243a62316796a10842a3ec054853b72ee04b1e9b0effcf960563e7539d0e29fb7ac5392abf51c4eaac56c46d5bdb70bf7151a93769dcb812434c686f4a5d4b6a64081ab5a6aa61094a08716f3dd6d4001766567415828b41b6afc46cb94c231136b263e03751ea43937881e56aa28d143cf8e0dc65a0dfc915843d0fa42b2eb6daabae8363bd70d7747deb008bcd56de107c105675dbf28ddb530499442c84ceac40826818bce3882463c39979b5bf01e65d31b0439b0d31be3d5b9d112b54ce30f880ad5fd288598e460e7b8fc62df876af8de7f06eac9defcaecbe681dd52369313267eb6ee1a987bbd2aaba9bbf9f399bb353d49deaf292c4df297616aa342ad78a26cee176b296ba4c5bab4c92edeac26cbf745b9586004c248f55e9999c0965146ae7fcae8ee3fc0163321d46212bc2b1bfd2c6f32731c86a4b3f5e34f762e4c0a37f00622e9b81af524be4dc672a0eaa0792386e50ab66e5a1aed4ef211c17bb0ebdd3988ea8ec8b05031df5d4c65d21206a0507b42165a0e147658ae17f5a7722525c020c621a6fb877de5579379e656b452284764530c446e032f35b905fb9f6fcd1856e2de2630ab8d968a1ec28be7492a2dae28cb724de4d0dac37228543deb570c78f4ac1aaec143ecee27ef85c74b394c97ac605ef8b24344853d4caa133b8e79c1214b3df5fa0361b654e74cfee4691ef4e74117c01448fed076ffaa1d5e45e269dc90853bb24724dce02b080b263187212126210c616844cd6ec5d794b435f43237c6049caaf915f5e6e8fe23c767aca733c2d78c79ed123601435c0b8c5f68fc78f85d24e78f483f111bcdca874523a096a03e88c1042389ce6d5b02351bd73781776393a708017533355b9447b5072e8154df16ad1266e2fa83a046c49f62af85c41a9fdc90b89e5bc89b71fdacd654ae46cf9cae8d58000b0edbbc723f7a8222bbce33478e3ef0da2e414e7baec45564df80921e2a85a9e045422df10aaa0c31d1950040bf6d85f15562559a1dee440e01e1f69c42142c966a44863ea0836a554a3daa541ee357e365ab0c29372cdc3041b0299edf003ba6ffb8118dd608ff157d36d7bb4634267cd7af6a74a677eded4cbaf26e8fc1ff80c54b20d39dd4c1faca6454c83e49d438a872062972892cf02f20b5f4512bd67a1d44b1a8895bc60442a0e61312a722c5790e4f89b4216390055091d1d116d7963869162c1d852c14338e3e19adf855107180eac2dbf24360f4747431c8116c0623f17f8790871ec71aa911e5e7f8352c8e193a76b34b686e7f3d5ea7aa6582040947b6fb84d7959a1fedc4590a60f0500d61581a4132e87e0837147d0d9187e39da23057730d9a41a1650116d7310e64b73d0ee878a210aafffed2bb9585b669a56cc5a44ece08caa4443f826e822d2c7dea38aef89ca8ee2b00b50b76f7917936e0b09fc908eab406a4fd69e4e93005e98de52f266f3d3a5329931aa3abb87035c4293e3dc4752b4c0b100c95f4654837a5d7debc2f2e42e96c85a3da9c77c8f6cc6f1b68a7afddd550b7c6cd80da8cabefe04dbc270d7eb6f6aa0a8d768e79fb1d73c04e33fb2d016881dbdc2fe60c1738e36cf28556e6741dd30de5fd474ea5753c80ace298467691e9de6f43dc4186d1cc3827fd90248aaa79804fa5c444c2869cc03ea7d4fa75fe5f774027ddbe0f0f8bbab5e29d24bf734c66ea6981609ec86fd467359176a021c0c65800152d3a092c77eb9a83c8ac2fc30ec3fc20ded9a1a9e6d2479a5f6efb1243bf7af510d702c0322cf7a59080fb85f4a7c015530963aa099275464a8728c295ad25252f9db9366334b4217114d67341ec9857b3cb4a73397ad4cc6ea3182c617b00071d439259bfd5d1788035aa645b8d13ae0d4be81dd42941b70a4c91d89660249342b4934e1749324214e38857d509ec2a232949cd853a87418094c6fe858d670e2b6230387f3c1feb8b51dcf06a47ec23256e8e6fda49c77096df3bfc85a8bfb0b6789ca65b85c04a7364eeb2d0fbb56bf02605e0c7562414890188bbfc3232e64253359b204a36d142d15af7a4a6cc3bb895620285a820afd11e0ac471012aba16ea670903e55510bd37b4c2909803909120f5b35bc53dbac584b0c7bec6ddcd21727f8f04a5583fc392f23c4a99d9ced8a746d5e0a6d5b98f91b74748eb1d59d0c3b978ffa7ac9a69e5a2677c4325c22fff18dd170ad5d84e6a70395d29d889c44c98d5a218cc303ac4b024f1ed659ddfb81b1d8a3d283a5a878bb45d82a5a5bd885345d961644147db21bbddd00d789d36aa6fafbf20609dbec76dbca458cd246a616bd4b12063f5422bcd10a0bf3bb4a4fbc0e0f6dc47846740a2c627b52afab408f2d5beeff3822ff793caf5110234d5561c47667e52936dc2bcec3400d33fb7cd20b3f6cb9ac37d17ff5cc8de5c94d17acbef488fa3752c24dcd778c05c9cc0310ad7c9157b741cc7e56038c5096c9e117e26b40a33b6849f8feb5a4daba80813c1507acacae7e264893fdd00bf6982f961adc38f700b47ad6564b8fe8ea8b633322dfffcbf6efd1f0608d8d588f079a9439a284a44aec1b36ff9346c95b7cab9a52da9a329fa19ad04cbb7b40387d9915317ba0d4613ac664d82f3917e369da0852505d70bab36c24771908fe6f0bdf9753fff5ba75852499558cc7448b0fa5073396553bca5a815654fb9086462676a40d886f642e3b2802f760e6e2c824d71941b6efa8c9c4df4ae8268c8996d04a84c8c8b4a5ab9ced081647f4e932c4bb80391ec0724b9ff74c5001213de7aa064bdca90700c5b4f1c149044f76aa95da84b36ff83a2988515e3409ebdb511c1e3380a72b23abb92b62176525ebf2b8878a63a18f332a4b7614cb87be4f188c2c3c6d3cf1ef793c7ed61508f759750a61c6c17e020f6f64705cadb71a7d00f1b6ccbaa5f6c7e8e3109d5ebbd04c0538734632d3ecace32a949d293b8fe36692428f3e837029292ec67c9917a6e0e6cbbcc9c9aa55361295797bdcc51c3b37d5bda704a51b4d300085d8ff3942777ca9c88d5776293eef4911acf5db72e084cdbcfdfc527026f37e635b2f9f7f222c8c8b24df4100c9f06ee103a2b67784f3dcc3abfc9d89e6abc7843c735002b668537907a298115c0f24bee9e056b89a1c295a823d8cd478cb625c78ffcbdc30a12889c8ac64b3712005b777260695d49536aef739576cca2a15ee577ad245c1d2ca1ac79e245bc37c17f537d4ff8162100915e53a3dd6cee8d92e016e362960dfc03fc7cd1366a3b53e51b10b568af5be3a4c4ed5096a1d56ada53d2b432aa93d0862faa4bfb61db3e14718cbffc21737530bb0c9fa3b3e699915ac92c42f0a3c1bcab0751b843bd2b4d5b8a93c24882860dfbcb05182d2d41b5191032096ac10b9b06fea905ef74f6a5238433a09e11749c34fdbe7055b47acf25d4bc0632f7ef6bdb454201ba17e900d8164d6bb41780eddf6e62c8459a3bd4184b93c6aa163996194398807cb9901a7666d483c8305d0e81056f1c0633a0a9c670373e33a800b4705bc0bf0d67f0e26bb29b188c020ce1e6555b58bc1e5e7ac9e4f9211607009df6f9c5d5f1e437c709c54e49321527c349edeaa6dcb782adf8e5dd92f9d6636bacef11e3c9cafa431e2bb6d694fd78e3e93dd7a1e0851b8539514510384bbee2da79986d2a1e22e28203120f65c11aee85fa8d1873bb19b593fcd0a027b7a457dde59092347550e44e2330b4b7ae5bd7c2d5b538ed7786df9dc0b32a982b55d2dd3c3a384af83b51025914c8c4233964ed4bbb8dd06333e5cb7530824e9571999223d6b13b8bd0811b5022d61c5cace6cf953a2cbc43115d61868b0c67d55698415796a016376e6347c596c7ef8e9bcca89b766c0229bedc5e1fd6821cdd78784902f3adbfbf82589bcda7bf2b5f7ace5685b1944c41a4d494a09a64fe469db2850175cc24aa01f326ccb8fe1ff19dac27df20838c95b1940c5baa309f0cc498b5f8580fb0273249e4af015897d38d591698e41888d3d6b2209060fb1979b2de3e05a9790f274e3c1f778fb7bf06a73875e86c9f1900d97795ef2b39a10ef1ea3c71aeb006885973b6d06acb83785494184bd04255707d7bf80b2bafe33e59d2139324f15cacec9994457b0d19da85f620c122da72fc4b692a7bb9a791f3a4522d4d8539be865d38985c5853d0bf8206b782b5401b72835ec13358ae5a7dc7c8ef76c08400662ac4f48bcdcc0fd3c50fb866b58754cd31d5c609cf49f0e9deee2887413f5882230ec11aced0e3b90a5ee99438f78222a53c7b5e548acd3183f25d6f16ce2470e13d3a78f8532645cfa5b09f4ff196d36e9fa0cadac0d4ba8e8447a023784cbbee9a09c395a70b66ac57a0938765509938e76c6f809ba607feb96592c1a686efb4837597f355c6d5af55997246a06976e013e6207b8ebf5dd8b49ccb1cbd6eee7df6606c524876a200538a0fe7e8a1c011e1f545f2f96ecb8e214fe57efdd46ee70c0ec1797d4428aa17fd0ec6a338a7e45115f49d9f4cb82a186e721bf0caa4cfadc53782400b6ef89062989aa9b1fbeba070af7e4f336b4c28ea209840d86d9ecf2e48f814d5f0262256abeacc626882c6111c6ac2d2736a224908a976c010b6ec11b895be086e216b8211dd73c42cc1510bbf863db08b2c6a7c7dea3efe9bb6bf78b42c9c25c421f4b2b2d530903a903f6badaee7cc7c8625e0b15332590067c7fb219b862af4f715e92b01f5157b096e2666c68078ef94090fdefe2e858cb7bd22674a8a408f1d63044513852057f17c66fe722fafc2c2055e5854b49b5b8120b1b15f38e175a6ec80063ad5a955df6560e8e92603d085bf4e795a57304ae993a367e1b6507d675d42b64233d6e1a7298ece807f1668bf32e6cd64e5ff396fd30232422ee16b36582119d6650d38db611042afbf8103f1f02e9ae04b503369ce16c578aa21513734359952005d5a483ef5353b6c0400d66443de006ea0eb3083212b3c29e49256a247dabc8b0d2189fbcdb8813ebec13ccfcbed01056541746537a55d42c5531342be268f549f760900f67338615d6f54a9e2e4debf32fa5e4bda44c6f2ef5feccf99d88abb2473fe8363732837f420b560f798f4279966fb4d7117f37f50e778a1185b6ca3dcc83e93cbcbfef400c6660005a1e7d370fa522256aaa88c9a23b3a6ffa95c674431c87027f97799d91b4f51d485ce18e343c1e7fb85a7ded7d129f5792b4489774ef8c59b8135cd1dc28c4a49687956bf8b5e628846e15a0d7f95c735c6c304cec2a5810c812f6cb42bf31413e4c7c030077f25da5614908969584e9737f4ea25d2a3db0fecb14531c76c06dab8f21b4c14d14ecaa3586432f1bf1ff167436c635883481a2ddfa1561640d37a3754808ae7fb3acec8508a05f4eeb7b79ceb6d1da4118913403abc1951b415ed8b66b6b2674649adf8441bc0aa4ecfab21f42480d0b26fa064187cad6758aba1172461dc7d374bf0f854d3fb6996a8a8166404304f47be74700cc9d116a330c5eec2295e9841121a26f8584a52912880674103122b6b833a453dcaecfb7696966069c2415a22d68ff4308393fe041b6f2ec31a50bb70c5b886234f810e19c803e70b68099046106b6a96332264027f832cbc23dca1afb104dd722cf07ffdb0f77535473aff06bbc35d7d84710511c16cdf5d118e4751186353cefa84328168d43fc42207c8eb2c63cda73e17ac2ba426b9ba854fc52293d6e3f76bdd5186b50824fa5dd4d8b081a66608f82277e7d4fecb0a2bed0f67b50b3d8ac99c6d45260660cf6dd20a2ef64c127f8f7434a30ad4fd3280a2b2f811676d28ed71bf0d6ce901cc3b1d18caf39b5ce74fa42266583df5e40af01d218b4f13db45cb993196ce8ace465c44258f41d2e9e7d6bfd5b03bf8412e7d32a06b9bfdf7bfa568b9ce6ed8fd0eff44fab30da2b457d7faf186979f4d5bcc33d32d5b5c0ae1ca61b787cb62d64223e981037c852f3c9c369e3421e81e00ac787fb3bd61aafbc660b4734c56dfccb02787779ee6d885abc639a5c206db8a3c11ae5764ba5a16d7476a91d5154898b9e88e8fd193a111493e0f7bee3518dd4e29b6ea48e6513570c1bba0ae92da1179bf8d7e5c4e90345701f315eb9a5f8c5cd21cf63ece55849b74c2b7857925d374ddf931e07abd2b45ed335e8da30b4213d2ef33074b3d3a663e0234cd7a2403e03a129fd79dec686595b8046ecfccdb6d8f09d83a5e7ae29bdd1c880a32019744a4137608e97c61aa2440a322b10edf02b49ee84812dddb9a4db20ea386b466d51fae5ef489a6a5eb85b052ae746d2d8b2f9191213d5646c59e153a3ca7a9112eeaa85b8907a1c560b957d66e1ac5a982ba9c765bd10b27d29386b16f65a6ac1b5beb0b2be18ae9585b8907a1cd60b23db7929a0ecfc17f843ee08d20e2a833223f108042ade7601eacbf9b22f7959165f3cc41051bd0e4b9beaa0d9f0362ebac29e9d35d3f574155cd08a490f85eac1bcd40a39a1d66c5eeafe088a6d11a553c4a2b2362f8020f4a08c791b65764f74f86d03e3db4d3adc9ed35fe4e146f9b1b4d4885f2a1d8733a8a3fa520931c66e0b9714628914a8365bf710a831b42d5817c4030b909ec31e6a8d6fc1cdce6d6f0fa441ddf9b12a95cc1d1635cc637b12e4f598205a9f7c17380203009622d2aaabf6c2e355182b6798b35033a78ba4dc313895e71da8684353eebb36b8fbb39d438f0d0544f4977a74bafcd6fad2cb5e119f62163cfa0b0ff68a1d2c009c87560fc9fc89d4dca8f6a8e032cbeb0e54dd06254a00eb0967ec1eba8cc5210095485e37d233f7af504d9124b09b5102e71ac42832a4def21e1e3c46fb57e986b222842c293aa085adad5048ba071c33c5edd6abb3ee4a0f69d18cf0d94eaa84979b326ee699c97f09f0a0b51a27e4a982d36dc6336149be246c7490e4fb8fff1339c34cb1efc42995b3e03f189c2c595017899358f45073cb6cfa02a65d25a7d7b470ca78afc11f564046d647f3ad940ad5cdbf21195091576cb33f2a57396d72b990aff4df2423ad688c1f12dc7c62a3940c985a81230b337d06294b1526c60f59892f8dab86cd0b85451e0936f548705d291eef230310071e70bd391444f037b0021be8491bb577da60d128f7205ce2f9e2928dc7a92c8c45518c59a80d68be9bffab20afb88908ee57a1de08d3d5bd6037d77d7431fd32a8e8747fac6526f30a13ea745158aa1e954805b24efed1a9270e3e73948a44f4643449387cd94429ba17a5ac3b83b39884d5d375ec74ff9a1a32274819b5c4b50e23c7ccfe7361e068c2f74e418962d5284a6e40e7f39430ffd41309604f64cffe9d10024a60af05b1ed59c23d2b09afcd234fc7802fc1f57b3aeb6ace0b9af421aa87438efd45a2f86357b75ca79de0ea1552fa8642e9e9634b937a7523692ab60c54a4588d2f811e496c5f86decf442961e9d71c3032dff9e6ee8e9a36dc6f0626251dc0849e3535aa09486f0d5ced83768b9d5bd812749975c4afe70874e376e42fb03acfd7cda47ed0a0aca1ff53c9c4886e6bc2137dcc714057745193b583cb194258e08cf745f48ed7e5e31e00442f03afc22604641de23e7e3f2bd3808f04feeed115da40854d6371a87444088efdc5ea853db9f582bda0034afff27b50718dfbe5f480d02ee85ea097673a54f01ee9881bab7a8d7483124c029fb0a5ad86ded146431fcb3e2d9ca4f6b00ec3f5fc7911ff6a5ad9d8211449c54985d723f9194b01f52c1a9f96b7030e436f3f0873af3bf84bef554dd63fa9e007b37b5f0eea43ad53aed56fa39fa44f0e4f7f099b0d7684ae3d0863ff33d6b78eced436707f0e38666ce8ca1559a6facd49110c385ffd70fa9600ba013a3a5ad9546a170bfacd087406112e33f00b218e7d456da6c9381948eb7ea14cdc2f3c555d8ff4a95969e6b53085b3e3aaa18a0a259e4155c0fdeb1814b17f0312964668bee5b52bf3049b8a073a8209d2414f5bd869500837ecb572fa98c9e731243b84269d491696ecb4ee8195e5a84453f6cccd494000b79c364e706962baecfe18c550c1297fbd0e8485679bb2a889c5fda3b39bcef2fe9102a731e6ac48203f59f3cfc71b24a75f5a3f7d6e2b40e809313f3c1dfe012d31de556b5014532e3e4f0d8a8e050bf618cf08d73fb2335d8af203530938538369f90b40d6e82d6868566dbc70098b0f5a4a219bb9a607813f71011842d1260a09a3585fc8666b84ace44d8c1f2528e8a84621924e0d4d90a7301eb942eb285326835b5d57a8f794c4b75cf705759bbd49fc8331c31a3f3c55494eb547a50264b6f0d1b9412d629a6283fe6f1bf3cb043f1e5c541f0b6d18f425d59c3bdb7edae877c99306c21971512a5331b9419951b2358cde25af6117b1647bc15525566b9e4941352ac9b8349d56821e01b77d506f94a8245ee70a21e805f6a0d03acbebf8fb4485e1f55b1fb08a411c67153e0a36ae43b5c780b0f280e77a5ce5b5b353c52bb5de85a70db836c85365deb155610cb917e7dbae97446ac59e04cfa396841771edeff76082b0d9d762b99687c0b6acaf2f0780ab7666d20d30a003c0c78a1d524dbaf1d8595cd84b34956f94588a3a9c72b048d18443164ae0096c45ff3083b148d2d76c2f0fdf4f67b8410f3000c11a6637da338d7cd0244fa6ddedf9c3112ae93c80d265666f993f118dbceebdfed4877952e520ca51d0334b263b4e5825a481f4647d40e83c2bc357ed564cbbcbf3b6017a0072ea601ba322f4daf41ba26a6d9541c2064e0deaf2eaf5e1a854d0a787374ad4c6cde2ffd7911a62a6ee5e2938c473dfb51e2cabd40e76ff60f8fb3bc693514e658cd562a9fe6ae01fe6ba94b80c5b87686df9f828fd0a670cad106894b533627a7c305c5b7394ba658f6b84655c892db0726419334c5708ccd718e3b10b5f2fa2eb7e1aa5185e6377f16c9f84c611e2cbab9e01b1fd22994c19ac0fee771df7c4fba8853d9491a2cbcab09c7e44cf4ccf217b066b20205aba01c53cc5e0103668e2228c3942166ca38f54e5e7532f038d96c880f28c8889701291f26de9e32a9d3eb56685e3051a3548a1e73a050e0c341a0cc23871bc949869b5afc16b887e5da59bbc1c781e0aeb20a6972b0016e4c0f8be96cb93df0d72ab5b4a8ec9b29d5d1d8b98f4911c0330df20144e7ad23c0523b11bfc51ba23f23a9cf92607425d01a1baca13ee7df606a229bb23ead2403c542d10890b6725176d7d5c582fdeb349aaab5b85046d51714d1fbfc1d12a2150303a78fa7a309ef0420fd767209a7fbd3402213c4dab3d767142ba465b5ce07ab98b7287b30664833e8585c3413af436fdfdc2bd41000333b1864205784a7d0668c49afd2da160c3cf733cfa1123dfafe21ba6fdf334fb25719e070865bb1e7733cee739dd9e474e91272e82c5b255454b08a571e98bc495d43cefe6e1533acf4f9c376e403878fd29e2b3180d546278cca8960867b5a1fdee0dce086107def211447479200da5de78f9faac793b41b94f1d0a746d4c68fb30451e952abf2a9ef041afa0b033385032e5391cdd3c71c24b1ba9317e8e4af3622b6a8e2400245eb5cfd1252b74840926c28ceeba386939e65fa99f8ad53e17301f25ef737efc9fbc1bbd64e03aeffaf01c2829b5e567d5b5450b204a5661448423e1187d26c6b077ece24cb91dd6e120544909d87d5d387dd930354bfd6f51b606e44670d425bbf75cce1cd1cb0b6886c6a309bfc7cbcb7b32e77c5c148eb10a116d509dba6bc369a3bd29019fa07ca867fc7c72de0951d1251fd16fba8df66c9a5696a2ebe4c11cda610ec46315e6f98d2fe850cd064100e30554eda64e76d64162c4d9439d2c457c4e60c4dc0eafc0008f2ebd58c05d8c2baa2ff7189881e23175025cfdcac0ea82463bb1d2cef9629a13ac9b011637bffa039996744e42221a46d282cac5c628578d6f2f005dd7f8c2739c13df3fc831efa2cb1e1eb140ba08789370c713c585b7cc8344b2067d3489caf9b8632ef4374979d75a256082e6088c8ead392c2bee3658a973da906bf3666c298b03e764a4968680b7e56a9fc56706e8e44d5e446ead3bd70fbbd18809178fbecbc31b90fb5ff13eb18e4ed842f095d1002b8030da6fb1c70b5f5550b54b01c095d484a5327097bf125622044da3cee761ac96c9e6da0582ee4c562ae984b85fb3219d6c607aa3d2891f39bb964e30d60bd0017b3bcd2f9d2cffcb03481b493c3acbc79eb5c23c42ad64320a9bd41433e5e34fe840a18be4c40a3c922cf26c5985be25d4fbcb8831399b7baa967ff7e77d760e140d2c9e24b6c227f8b9aec3c9964f37bab4469bbe773b9ca4dc3288be9f26ed13f1f795111e194ef86da4c7fae8b6d93093fb65155edee7a6191920dba9d3dfd9853fd06ca7cf2858d75c7c6ab99c002cbe4df00407663c39331338230cb24ecf292310ae5836d60c9d9c60ea34267774d8391f02481d76e12d366f13ff03360df59d3bebb5fdfce643242ad3be4ef637b049dfa8dccfd33586a3931649b14951969f847fb800926c22f3cb932cad2bbcb3925f2ae0569928699502784486246d922a94efa50a77a729b49055cbda24b0bf6a45c69b5a23456f6d12dac21837b053ab92f373117da7c21d717bc50f4fa12c4af78c026b09ab949681f891af89118b79d2b000001d288ac33437c015bfb4414cbf9b4dfcc53771387bc5144f86fe5aee7e30101a7ab6aa37419b20cedd566a130941770bdd77ce35440dbc6fb2c66a0ff1e5b66623be579f393b7d8c4a40a159e8ba88cfa6d9b43d6d84ad22b6c16cc61e1f089b349ae19ba0a2da0d2d0b293ddf4222f4500dbc484025c6efca20af84dd88e67704dc1b256c22ecf553e324f8de6b1bcdb50e72d3a7f2f140f33a752d2f685476825ba4b6dd2fdbb74e4efb7236eaf84d7bcc0e1b5d339f10f07a52ba34635479e8ba52fe071d6602aa3c8f78446e0b852ae1bd3721d73857d8f86b93e305dfa5996a6bdd4d8b31d8f47d4d98fd95ae8a0ab48de85c08c0d730b8aa8e7e889787e762411e1c3661557f69c22644197f4eb0c90e098d84b00979c44f006cb2cbf76d20854d7c8df6e688e8a4232c35ff73fd4f8990dd13bc65c854acd9b2d4441615b7f34ee691d23e81b36d2876493521836a75853f69758b5ee65a5d92e94fa418ad2664102827cdec579327c4440e09646c1e41fb2ce1d59af4dbea5d153448fed226849e1b46aa1dce3b53cf512b4b7d4bbf7ba9ca499954b7a9c2d175275c131cb25a93f3a84624d6ea9b6393e73690e7c0a2ade4262ba686269f249a80c88afad0e5beb8c726bfa6653d72e25201a3cb3da26513d2553c53a2b991ff29b57c568223668166c90e26c2cd486593f8496d9bd18bfed14d6d926eae82f5eb07b671854289e88a78f01525eb61f205ae9d7d7cb60935a3f056f573e29954a650b7a6db246e42c13fd5c80738b139300237510b5a3c743ffa2e9adfeb9b3d27584a6d79bf8df1b650fe1702bee978489f46b0879c3588bffcbf3c868c3f1a6c3fa3824f53cb4d30b50182d088958ff13cd86ec2b8e64de2af9dda0c81de043f5ed8db9b04427152c3630e2fbf893bb2fb42411ba935e92dd0e6bbccdb64fb73f9bcde84b725e76baec7dea6fcfb94c2cb00c92504ec1b20769d7b30a7d9844b643ff55a0b894021a0144a9bfc2d148ab0336e1f84e2de5ca96489b3b27dda84236e12daa5a8cd26293214b788145b3091bfcda3c63ef28fe527b0d61f0a5fd3d89db5131b30018449937e621adaea3132eedbe3be5022ebc91e5b9ad54798d7c3d045a7571d88f54eb596e94f94833aa0f95d9dd875e99f545ba61ef060b5f7cf2c5b6a73cf921e4d88537e3748cac49da708f419e087879bfbb73d8ef4426ca37ecfc11cbe984c8aff03fbe09ad6feb47b7dc07427b791a0bf28a6496c1e171c88829b4eea2a5c3c883c1f6529ecba9dbe8822b6b98d1f9abe982dc7650fd324649792b998dec355fffe356d4997ea898be81be3080150c263ce1ecf9a64f9473a1545d178de451bc572f60ecf400dce58e879b9972cedf8e852855e29f360ed73a5488349f4ab048f47ef8b3a61467c3d8ea66a4ecff06987134b9bd3328f923fd2068eb1856397a32f3e60385786bc59dbda42e13c12a3ed43a80e216d445924b4825f5cd4983ddee18c6225c9831fc004eb095a7000479608ff1e1d5cb62692015677c1ea21b7d05e5bda411d79e2026914677b00d0dbe5897d267fb17d3818a8c2052ee38e12bba64110f3310c45e0882362b872e522fb8646aee8038d381ad609486e8f916e497738d1096a54096926aeab72b315e97b8f170266733cadba871a01bd6de19f48f7412d79d175fbac70787b44bcc0cd8d43268f018ddabbd9caf017c10d43e8689e4772fb8a7e61326d97098629fe97c9f62f6979b0ed7f5305ff5a51af01444a2e800896416818a045710b64643df4ae37a27ddd1077f0d163bc914d36d52f4c2d2e5c33ebc490441cda9b4e18415a8d79738e656b3d64589d3c7f18f06c1674f9728e514bc510c14350940852ea65ba9600ba957e88cfee6512c7b09d6a3addfa2ef5a22c7b4481e4ac5c8edaaf9d67a0fa58ed7643f9a667454df6148f8c3a7f2e11314f3c19617934bd84fa5669a2a6bd8c29c5b94511e08829ea8152fa37b03a420974d4e272e67691aae7913dc05d1c6a364f1253cf937a49e749388884f03c6520688cefdd2497cd271afaae01b20c276412aca9ebdc02ba308d6d819c59625b837bc0eb67d6f035facc57b7ad668f6b19db6da294ddbc7a8bbf005da635d03db064061b39a74b6dff59dd91fd6cc056b940fb401f63292c3aad3b141521e4c9f6bf709a13a5210ed3f5323fa3abbfe853ad66368a0585c53b8b65d5d17510a83f7ed46aee4ea4629a0fff6b7b345dbe22cb633bbfec960e4ce1fcec2864615b98066f9035eed1520daab8032600b2e1afd821d15c0bbf323a31fc9840bc618e601274ba063b0aa49c4f78d031956a1c26747420395b73d99bca00a8f3a7fb4a55a712821f11c24e228b792a12fc74319d95a08b48c0d69c21aea155fa23f2680a302d55c1a1b835a4be9e93b7044b67a4c74313143eb38b779640fcf81b5c32ff271f1f47774f0ee607d7fc3e15cd741e5f2b70588d35ae721bafc4ef1f8757e47c2329331f2319cb1a6d8bcb99ab687742ec0cb5d57e1f0a24a23d6d11500b3072c89af622bf44daa902b024272abd5c3cf891cb5f2c7d293b7e85b379ad3320d4ec63481ccc449de642e961c40ba5f6fb72f6993202708f2889e9494740cb139bf00e4e9ba3b64f4bd7070e61cde0c2d03326aae0a100e3100a8d2bb82ce58195190c3af3957f1f7e9c6080da58aa750bb435fab3b230b77b9a05f53fff31761f01e3f76562539a4c41529350d59652f9dc50a91230271051ec449b2129fafc9f6527539f9424aad5f6db5959046b3d17f6db4a23a75606eff5576c3cd75e929a6b161a915d708629ab6575b7a08df687bf5059b20ec9a6618485068aeb16cc7b5562e06e1d9960116dbd1319559f1ef68c3670a4dedaa5c8c9da0d65339154b86e6d948e83503ed6349c689330561dcea7082de56d1a859660675ecdcfed0f65b0393db6a46943cccbc963104ce6cb001822014100909411a90a4f3f6ec6b2d80285cc1729334488ee740c7b5739494d312a40627a4e1c16825b42e0762e8f9ae1992e2d8382cbe5f5fa5b1ce988ebf0201f3cde0df8ecc5edc76606c6ad7a7b4b272ed4673be3f64f6a8a1948fbfd7d84a1be4ffb15068356dbad7aa8ea69cf8e3dd5598def36795749db05391d7ed4fd13efaa27c70054c201e3d332066e32f75861ab18da27ff4d8f7032b7fc80c6ca0af4c2320d0595e2d87255cd953f82453afb6326965fa20f7e0c5168d18d51d31f1590f98219509e33244db27cc32546b5796e6edae0292894acc39f8f44eff0c90965df14304668559b37e8f5859a994d04673e63611af205ce0d2534ce4bf7b64682865ce9bb271b87c54ed2f7f54dfb525e3292ba8677c0521ccc79e014f40b722b096b5f05204f045c2bdde5b7825cc0901bc60223b316c28d12cf179978d6650bb5486b9345a7ca6b38f28bae9847ecf45a310cbc414f845a8e0fbb338fb518da3afcc3d1d68e4376649c16aa64547b7d8927496560eb7cab24c40e1117114958732252b06ea106f4c2674988b0455e7d82b922b9f868227cd2a4602ac2cca332799ba1439d7fc7b4e12b310d3aef9bd9b11d25ef7adeb726dfc9db1855f70c1ccf0ba65734868019c05a5f357e412f87f006979e96eb6d54a77d607f73395b79857a21aae424c2a90ec200528fe75e278efbd0c1da0abcb04a45ef4e508a975d4025e32d8fe0070407d86539b694e052e3f98ff950506a5e6462dad15c633af7062443a720ec69f6812981ba486a2f457be5d594ad9b0e41f0f83d47c0ed9b8bf8737da07e4179f35e669624fb5be049834ed3e7deffa30a13b68e7962d79beeb87cf7dad27c2c4ef1e92d64ce8be418013587dada99d03c3fcb4590e9e65d790894fbad2bb9ab410071211ca2545c6658e87fdd6981b696acb1b0903186953af1f1e4c01f74988e53114ce4e27ae5e3949bd3d9d6ed63c25d90e3ae88cb3b504d77207aaba517c73be69e1af572eb6f3400eaeedc83a9dd24f62e90c24de3e4ea5b063d0923524b4f393cd71eb0c75e0b88ed49443e7d7f866cbb68afb2393fe90fc7b4b00a7bc5d48f8b26a68c864dd5a1b3f3936ded29078add292af578716200a294c59d98fc174b9860e9e7e283b9067aa6c9eac319ad211c80b3500efc4d4e3b83531160c7cb2a8e36cf10f594314d46e0153b8332f7442f76966c76502ba2c3c29bd02658ceddd418939774a51a8d173b83abe106d317abb3fe933e8f95b8915ff6072cf519892a2d4a82654b4bed432019a263f486f52f134f46f613b6a2ac14704d9c489144f86817ca8a0fe3aa5779f1458e09de5acd3139fd8baaffd077eb389ce9ea306f2e0a4465f54b3207ba21abe6661d3caa61b6b1b518ebb571af980fb447ba339065bbef73f82bc6853edc47580fb1e916dec4224ab64b866f26a787a0b157632b120a043d25e18348ad53810324ac47fdb554f42f9d6d947c15b4be95012f67d6006406d6fd2184adf581b90bb881469e8f6e52a3bec3a46ec7c791641cf44e43c3773f93269612263c4ab3a69576ba7580bbc3bf821921196f85770939a95e62dd84c61cb52be9f59b841e22a871ba5b95006328b49583f763442b984ef5611089486adc4bfd7206653e995e65f4f925949e2371fee12b105cf27d4c69a7825e5762653d53ba4a7a4c692aeb9d2931cb2a371fbbb553041f0c3226426a0d64ac884c78866c5011d907de8bed9c5d7e1eae9e5b3442599233c3a06a7f80b7cc85ca404654744a2fcb40365ad5622a634b0d544a61cb40d23fb8f21e8fd41f042405418eb8f5b63194cacfc0102d6afae8ffca838e9076624c541a53902468f58162db8247672fe151ac030955ea2ca8a39163131f384d0bf6d683d89536fb83d7ff2875bc8da15df6cafb0d620223a07bcdde3e3efa41c281a965f7272d95c8271aada0fb1f887e75dd218c948790c06c10927e72dd322ce4603f6884b76a3423f9701c22c2243fd1cd70a0107976efbf44a24439fd37315f945aaf48fe7f527fee6d1a0a4ab237bb7f1612e7085f95cbbb23217acebdd3dfb90ade699c9e5cb7509c7f709362569dada839f94c07c81bf21166cccdcc67ea219f6d1d89e70a405a4dd148831b2ee3b93b53e12ab965b8ce3ca6fbaa714dc2b19a7dddcef08506545cba8848210ea2f85b4cce486ebfa340b8bcbb2b3fbf746a3b614c6132b6f1f0cde3738bd3320631c1cd241bedae3f955499c39fbf234ea69695acc544a0135ef0290e2023e105e27a20dc7d21bc907c14b7095defbb087cf0e39d863b261ddb8220f804e18099906779d6a991c00bfa955dedada414a40dc82a7b30f8a44b1233ce338505a1a51edeb9e820ae2ffcb3cdb1a6a95ec408010f072722412684d6bb041047901e896576a30cd0a046538a7ceca1813fe1e0d911acc519a45d70ddd196a708bb059faeb757726faadca98b4dec44d73794f7b29b8bf8150f4ffafa0a83ed26566ab60906d45e226c9d210e82aa130dc2e668f4b16060a015d799a4b612246d4dacc568b51bc6734e1bffd176584b3c7b0f9c60168ac3b6e8b5aa80a386fecdaa2f3e10922eec657e3818b4dc0f6738f080f43aaaf642597fddea63bd0004f2fdcc05cf6176f4e28a7119fb93cf0f42bba540ceadf730166e6b62718e4626b9dd7b73aa731886e04c569f65bb811b479b85458d0462f460f24ef8266970340fec3b63fcbe0a71e50eb6e97b912dd903339ce77fa470eafe3dc1a5fd7768823bd31f21b842f75da531c67ff9fdb89516ba88a252edeadbc12257472c9e20248c754d85b07829bda15a10e8ea6d9e6f9c552273287d2952b6eb94ee6f7c8adc3593d479024b1ddc37a9a0ef645e71dfa695581084cc25a3cfe8c034a495bf449e69293e185c2ca5fc3d7ea1f65f7ba1dfb409b351aad879df61e678a2f5592546c59cbdbfca05bd3e6491b51166c7abf9b4f1e164b6dffdc30a63d3ed37053d0b19597bf3c3de32caaefca583cef4205ba96848626b444f54372b11d85b7d3722264a5f7e4b756a82134aa003035c055663e2479091be677f333db48103ed850e007be221c4dfdc2773f0b7818c7ecfacf76d12bd1e8a7fd68a069676f4ac413f4b334e2b0c5f806aeb44f1e6e61e7b01593dd9c35d3a30a2be53b795e88481c91d2db28f55a3a0be2f678df83e3a8f6a063430fa4a3bc6db11be7a3d7665ca6114225fbe6d327f94f4837460ef2e5e5f01226e94945054eb3ac2325c35606fe78797c40a96715d8b50b07792f55a2ee202ed6e67c8e1b4ba38532cdd03ac972e5c6344263bf22ade864cac784a910fef5f1be6ea3827be8146948b70474862db3b513704c0d5582d32815dddbcb6b47880b370e0d46ece38da3a8369f8c58d57265ae86165c9b75e36825b1760bb4488240792252ba56e5e97dd85503df374b0344f3b43dcefd84946c068dfae84ffd81493c77e94df775573cfc340d329bb430bd4423b2cba0f94047727e78d80d4721e048f14fa72366ba96219a886c7f34ab7bfc12e0397db83d6792f5888ff0217a634d137215a3a334af13425b631293027646cb81e8a16c5510302048a57bc3ba3186fc4e9743a8ca6647b40d1db8dcd43cd9d017e2ad8c1a61f2728feb516b160ee8cde3d3227884c6d6638fd31dfc29b88483ee74d3b13b59cfe4d5df445f1125be8323e145ce51588140a1a4dbaabcb3be492718c3d0bfeca0cd135e396d90a91c43dd96447216bd2ead4aaeb24de2c8ab7e84e5f67d9bb7232c18d63508777dc0a68aa9bfb0cabd03dfebf3c522c988b9cc13ebe6a1a6f73bf9734905d5a66ad2d4c81bdcf6346e69266b200219b15c654548210441b1d805a0277117226c2b820deaabca2f995cc17adb96a4b91a5f2136dbcf57810a74371cb224af2426293a54221df5bd5acc8a19d89dbc15b54854fe702fa19d7415ddf211368d4ac38ffc17463f5e789b301ac389cefbab170f1b5a3d74fb54723aecbd1508f65323f7a6ebe73ade7b3bcf486bb0c426aa60e15ee79c5591cc37b1732d0f256edd0fd7e66ea0c3ac154b28a2f2b1cefba7d0ba0dbc1b42f7d76aec00ba09a1bb67129b81208394433334444c5be959c55adc352d9429f5fc252f6514fc16082ccb94fac6a0bb335f52709c4c760d44bb54a0b96f4fe98eb40cc957e8b8fb1c7bf6481cfa85283c14329ebcba8dcd71929286fd8d6b09ddc19440d699ff4ad0aae0f6641ed81407a51da5877369896deb40d79c187223ec675325df222d3c7b775c9dbb658ccf41d9c02614e2bb770e4967c867d81ccb173ef1e7727443b126f73ec15ff7da3680aa853307aac76fd6b369021e4ac3351e1acad70652c80f37df61c765ea96b3c4b0c535cc18e57a7643627116f7ccf203db3fb5b04c24fa4fc22807c9342816c2efc476506a278578551d9298695e0002bf29a0a5d6f8de2be77f8e648fc1290c487d74f82fbc5643100cc481cbcd6fa04ab646087e449586551c64cac953ea75dc4070a08045bd3492e6f52f8e3bd517fa9f87fcb932c60aaf72c930171242a8c7779d8fcfd525aba4d7767872f922c4a0626dc8af7bb5d42e672cd22148468b8acf18f9a7fedaf2b798e0b6fa5ec6af6c6f2a56438c39b60c611694152b713e3989dbca233ed0f9d8ba484e23c06f9abca1070c670d774574a6a092bdd40fd6dec194e3b65858580208b9015823a0b670c3c64da483b5d8ef3e59941e19740291caa24ec8b8cd76e5a95e6038c9e94624396e6262e5cbe8446d4808745cc40a50f8a4c797066facbdef5891e5c8669a82b3882d0d778c7cb0fd78d9446169ffbcd967c4fc3792ac95ac448cb340dc415a5e662b82cf5be24be628fcc9b07519b504cb066a563ece2490d61bfbf7a9a262e95137bb365f0242e89300ea5a2e66831d7940c05a66a1840201dd06bed5fab80a8b4e4809c43934ab1441a5807a4ebcad2139aa7e118482f738e298c3c3ca8e042aa40cb613fc568543092b3b9e93b0ea39d5d2f1daa4590536c08302f427b408f600cbcec7031aaf2629d33963df4ab5c058ae6a119c5962d01ea32752a1dde3bb3ce1ce58da8d1c0dfd0dc2c7fcc4543dbe10449a160dc4996d5f32f7327f7a9b36298f4b50137c94884c550867fb71de61298e9a9cc9ec50cc5a3ff6f16736f87e2f3f8bd49f95f56358cd7a8940dc11aae327f8462baf8b61e848b71072e3648d998c5707ed86e18352b6204486e1a330ddd05367db3861933d6b5c6b756817a801d1b63b61cf487b8878f75c8a7ce87cb9146206fba0731c90d944140803a68df2d132b5aa5c11e2e7945ce6d99854d78e79158353671593a03add9e1a95d6e343a0936ecee4947661e8632eeef0445d81744bd0ca1a25937741c1e071fc1265916d3ac5195f81f099a4b9fdce199acd1c1b3c66bd1136b1df854ecb29dbb303b7708a559bf29c29ef4ff4f665343304931922a96fed792be1e1418c3b27e708065c0d4974d54201a051317c433de4306033577920e0a117e28931542ef7e7409b4efd3935c832617f116bb86948cfd53032fe8c00337c8c7652bd0e014254656a8276cde7452e9f077305ca2db601569e9d6bd499ff5709385e75db001922083eca87faf375c7c024ac745615f304ebaa20e85de0bc83478002d8e49d7269f3a0e12bc913e269f913ed7e1717bcdc7565ddc9a799ca2756a130d6010ea7c9fc690700890e1751eefc757faff1687a1bc5a6a00140e1ee307f27b793c09d8aa64ab58b27793bdb79452262903b105e705ef0541b07460082c493881658a1821b05021244bd08f2c457ac84244cc922c4ac092d0aa4da1647182892c52c44065f98284162018d0e2434c07f46c53285a9850d1428216b45411fb41c73685b2a5855706b6048961419b9b42d992a4b5023db329942d4e314f34b929942dbd146ce9f29b42a10203df9616dc5104373f519541db0f4b194cbb80a23e08ca64a20c05db3e23d0434542d9000f55e679c1c7dfdfef9fdaa736bfb5a60106e03522ae796a90f2ae20f2afd749f0cf8fcb06b87ff44f15f0feccd35f02f85de6b50a9b11a986785d3282346c151c1f40aee896a6174cf558a02e2144c5123d32154a0b3d16a05b96f48076c76477fefe607977f8b60c436b2d498e96fc91b44f5af3d40fdad0d45f63d2bb915ced76abd19a67f8e0f3589356a21063db12e422b573dbda07f0ecfc20251f409776689e3c3b9b0d003f04433287a64eb9a5d7d3983cb8d21f6bac3bf0695e7bf04f992c84eff54a85bccf08f4d8e087b0879900c2626060313130fce4941312da1172cae57cf0f1bdc005db3f060696abb948266242ad39ab73020cec049ae3b4a7f95af50aa6e660660856c7e65d349954a6b53a36a69bd4525ba3b16c230dd74b85bcedcb5a96f4115f7f2eb5f69ab3ec67c3b3b6676f4f1adbeeacc09d7d50979f59e62e34f5a6a4092a0b82e569c90755c87b7cf27579dac66795acbd2a67961473336b561f35a82aa1605395e0119907ebeeab3b7f3c559f62515c72413e76b9b0078cc79ad40550d87632547d4d4adf0550fc95b280a2805ea943e238aa5e2c55a24a14c5185bf56118be18aac227c557813fbe18c6d8aa07e9122f47087efb1e0445f3548d260dafa110638baa92eeefbfd187f5aadff19b93a0f885bf637c1a63b933baff68eeecd00e9aa44967a41896678f99fd98d7c75ec7eb63b08fc19e47ec5f4f7b666870d1630ccf1ecd93678f6fcbefc5936787cfe3e4839bfc1d4b33f20406f0a854da415f3dab3c57e21833c646d928338ee629feea676464b11895f8a1aafc5efc5e5c8de3f7f47bd600c6b72faa90b76d87a438b68c6831b596cc1c2d1ad2f03e581e817998b2ee58c08bedeefe14ac3c21e4a03ee8a796b7a644f0b32e22dffcb6d58baf63f5e2f82b5307c9437cd2b4f5781e4b117c31ccb3fce02ceb6ccae883eeb8a9e906076d235721680e7e976a7bd5a943541cb2b65c87631b7fed599d29ab133ec678f7343e515acaf884aa34cbf8eb12f8aad711be68f2b01fbeca0ccdd9f3b80faa9ef6804f7bde82d6299b2f83d64d38e3e7f1918bbe95e7d8318f2797b5c7b3381957265e3ba2e45a026f10e9cdf912daf645afd57d5810876dffc4b17f96ad4db2348e0bdadf7e8d4983d96f678fbd0a45976b5fbcc46399da0c9fea24d68a0c475c85684c462b2c0b2658750ff03261e60c1fa065ceb0396bb5fe65ea68fdeb5f2d738778c7a736c83fcbed44e80781615edfb976deb3cee440501badb7d6a59ce7511bfbee699f7409d4d785b675211088dff26759a3885765153d5bc13c0cf63c5e3a603c5a0f3365b26d9d069a63bffa4805ec61c2ebbbd7b73ec677424a34c7c698beb338f6791840cc1780f6c47cec797c87d58999b33bbb2e57ec5d3173470cbef869cf7df11b61a68ed6c3a81e97a1a92a0780bbd54790d76c0ab1a73db08f791d301f3379b41ee6634c1e3efcb41ec6e4f17a98d973cd934e6dfba95ecc63ab7cb95ab32aa4fa1992f6a56ded8b570c792c2ee9fe32e8bbd91daa42aee44b84a62cce7d6b1f02754773b854a13a04c4772fa195c75e58daf81b31c9a3363c98c0b87afc27bcad85c9af49e9a2efb1ecf12f80eea036c0c7313fcb22c62d13e663ff03f3b1cfd9fc89fd8c5901fbb1afc07d98efd1c3d3fa1a93b6b5ccfa3247316bf1b4edfc35ab633ff7ac3eab9055e54e49a38a56fd69db18bf6a2642fed5afcc93b6b339cb5ff7ea7bec1d2df304b5796aca324f590e1e24fda4993fe3fc6375884a869a7021e28a9e99d721f33393870f332f63ceb20e159eac804086a55ccf8c39cb013332b2180cccca284efd97aba5592b167d9105da10fc32be22a5a911778f5ac71088e28de9d65ad3dd4b9a1deddb50f79a8de6765de635987ba5d9a84e73aa0d9f596bed4cb5d6cac8ac75777777678ad57c84e26de8d3a6d67eaed9189bb596b604c30473f7d7bdd7f5656b6dcbda18f75e3db2dc57d6da7b2f2903f5bd7794895fb636747777771fab053f77cfee8eadbdd67ed9cabefce56bedb5eeeefee52fd79ab5eeee5e9dbab75821e087531293ad826f4ab3a949734491c65a4bbbf7de599db1b6ca582b73f7588cbbc3506aad09b316eb5b6b7dc9ac7551dad2ee2cf71549e948a9e86e434569d5eed8417777cf14bbfbb5eeee260a2aa56e4ae9fafe35373158a7f6d27cf9e26450e377601b3ccb74e6fb4099dff1a02c54c56c085e9d8209aaf0e62fdcc9f777fc6bc572fd8e67e9964e41eb96d6296898f177bc8dc942990cf83b5e66e6b37646c3b6c6aac05015821804adadc28260a812c751548560160c66b7f1526b54ae1d17814ab1ab59d21c9c00a7f6d2d05a9b9638f7de2644e04f15821f9ee53cf37da00c280b5531558c08b3a44f9b2a039aa34100b6fd9a33108009a408a36d672c4b9c9d8100c8fb3b3b3b3b2f96ab54c0b3744bb774cbf582c18ca21893853219907e33b36a565ac3f8d27035696a2cd93a6572ce20d51145130026169b0fc5f714aa79da6abf9df5a766697025d3e4cbc69a94b9e571e8349e15a2a1aa86ce6cfade44548daa52e04843bf862d994d7132d8b40c7bd994225733a6a5a525d58a3553775557752a9696d1b2962b1603d3ab30d4a0155985789a82ba4e402a05291d6a0f09107bca615e3131574cd6da116500999087459fa419b5ad667178361f7e0996e677f3268b3cc301194c5790e610e96ac3b0e543328e03cd593db9b00252a13a61683a91933ee4352d2f46aa436d359c2f6532ba5579b45aa13ae1fb87d53c7d86ed2f5cb1822a869e9e7ce869c8f4217ff221930a6d5353bed0e7341e7680dae2c856d035f3b6cbb59dd8f5611548901a72406ab8620393251b9ef65981d4a91b98ecd37344370c65d180921a70b02287204f8a8282dca5f33271606a9ff7e9bc5266febc5378b33f6fef6ad9f5afd479a7884640a4e7c43e687fe21fbb9e5888e64f3c8489767d5c84753920b14fbcc34b76c54c3053138e1212649f9887abfc9f580b962affc453f84b2e4888957d66a1330331ffcc44452cfeccbafa7997958628ed339fd9889b3f73536ef167ce538470d92d5afc0d896b7173f32c48dccd8dcd420892cde24d12c7c234bf2471669943d42eff495cf9ff3624ee6dba6c9baf2171363a35354f43e26a688868d8344f237134b49f9138da8c0344f6ec6748dc8cee99972171333253e8380599a13239e160c4d7d360bf5c50b7eb5b24ceb5e33414846ffd2c12a79370ba018a46da5065933f9238727c91c48da2ea4312a75ac2a90620e07f240e84da1f1025fba369c12c4055e6ed1675e608ed2434450ab4368a212a5a8c19b6bc7012227177943203122c76fe191c16cc70819dffe69721715926ebf1c3112710ecd0eb028407f20e50106195517a8606159a326dba3340c5be7f7198c8c0518d9d3f865325033be89d3f667c92626718129775ad16830a589061890f508030c2e9092a240c0345fb3ac15dadf152ced90590ba748c1f5cf6fd96d639e75ccbb59c3315172edf1f1fd0c129c18f0decfcf957242ec37841cb8b9d9f247159d76a16a7be25a226c02148882553485094816ce469051a6e33358b4afbde5791b86b850c2d70b0f387384bc4d0030823286a672576fe6f043014ed64138918362a1eec4c9b4ae0040317469010e0528f205057d8908314278c88c12e01b1f3d3a8a306417dbb578052325d1c0c69e1134c8b9c14b19bdc970d582829cd159e5a942b7499bdd0dbec6e6a589032a361a18a1934211bcc5a8072cdb4404503991a5a321e58b12399181f4e0fe3838a18cc8517d1cba5a4f524a65d7882e50297d7ea851829841c8d56a2102e55123021ef053a5d20053041ac1b583c90418c44cce82636083ecceb05a9767a2105e3d4d79c1cf554f0c39517aa287add7065882a579868b1e0ca151db0b4d084254832a35cda766854f3867c6b7118a9dffce36b7d0751a4aa3fc53fbf3fc13fc33feb9ff94fab12c7f1c5d154e17d9de27d7d7f785fcf75f3585c9e28e0eabd42556d13a2f8edbc4596fff84ce8fa15dbaca0df45eceed85a96bb4dba3a2bab57f7e5cf22e5d65b3fa0efd55155f8ddefdae46a3b046fbdf5d65b9174f9cbaab0085b6db5c1c8565b6d30b24f8750c2565b6f30c214c8f90a5b6db5d556208c84a8ae61dada2ad3309db69a3e1133646cfa4ccee3b5275ddde684c0938385255b63eceb3c16a7049fb2bd56f3825bdb3076b53b361ad57ea53d91e51997570259adb423acac20c48620a4200181acd61e4345400085032c6409a2973f60c3119d989efc377ebb5b66377542c2c472c05c9a819faa0ca61817c3c8385fed097c21155299ac058d1a59f068aecd9237bed6ff36ad1a26f1459bc964333232a6d892b8c42a429f3131c86f270ab9988f1f7eabd85e07884bbb01f757456807884b6f9fa608ed2fe6a7196371e99bf4cc19cb6dfb4efad836a539d6acefd89a30fd920279352d1bad75a9b579e3e2c5e83527f619cbc9a23c09b687b6ac3030665261dea6258e022996dab86773648ce38cd15c82096aba41465c2046d03675daa1862dd2ea4453271e7a9b3aedb0649fe1a64e3c48d9508660026588255da6ecdfb4898b121ee435c71663d1628b71b55f6fcd35d75c83b6f51f58e8de9bffeb8f1db49d4743d3a3d172b31992d0cc4c4f46e6484a26432a8ac58e783131433030484130d8d1d4eb95d473b9845a2d9dd64a3916eb69b54ae291a4d2d0384689a2944a953415864544fb472968ff28f9d8946ad127c8c4b4db2d5162224a9db42d9bd959fe7157134b3da0621b28a4e427156ca0d0f7792cc6d8cc4d56be1f9fd07e02f7bc86795ec3554411e7dcf62f2a6c4be3a4c72fdbad35f194d7fc53fa983e1dfe927cba6fe7b7acc464bb9b99c9f765fb94d76cbee6cb16fe4bf34ce19f96ff39bff98fcb6a7e69bf46cac6ec6dc7d5981f17af65d12728e54869834a7e3bc1a5ed4bfc767ad1ce1f5cf2db0932193165fb834c7e3b715193dfce9b039ffc767eba2da576c02588da28a236a86ea764979ea0e49eebd01e4abf2d8eabd0dc0473d99e996cff1fa4297ecb4c36dd34e50fd2141e0fa98adfb20736ddb4f207a94aaf77f4c56f79884df7acfc39fa92cb21fdf05b1662d33d53fe20fd40124212aae2b7acb4e996297f8eaaf47a475afc969336ddb2f2e748cb91d491141291df32d2a63b56fe2011211521151d4df15b3eda74c7943f47538e78473c207ecb4b36dd30e50f1290a121241f7ecb416cba61e50f920fa420a4a0232e7ecb1dd874bfca9f232e475347534955fc9681d874bbca9fa42a49bda4de0fbfe5dda6bb55fe28fd10125232e2b7ac64d3adcb1f25233add17bfe51f36ddacf227e98b524e29d7e4b7ecc3a67b55fe24353d3d254df15b4eb2e926cb9fa42949bc249e1210bf65a34df758fe2801511a521a92e2b7dcc3a65b2c7f92a4444569f15b46b2e956953f495aa4a492b8f82deb36dd61f993c425692a698ac86ff9c8a61b2c7f94888a8a7e947cf82df3b0e9feca1f251f4a41d406f9a3144473e8e6f19bb33a18bc39bbb43dca90d43e6fd135cdcf9ae3cdf9c10f084f0b94be6691433d2ea216cc391d01b2a9ce6fd4e9c80fbc647b1227244976cea64eba2f5b14790c6d7b499fba7f539a63edbb1df2e13592097dd6a2dcd4e9455e8138112e2a22a33edda7a3b745bd06fb74413b07dd1f3767f382ce591ddbcecd6dafbd7bf854e3db09b1babd58ccbf03804d6db8560b02414b1e2195685ac3d85e5ac3b9de25ecb6033125a71d64f080667dd9c108952c469a5e4118f100cc041a665327233c4c3162c3124658700d29a2020de89a4d9d8a44c1bae8d8a64e459abc94288204064b111d5050448658124556102262450a112897155a6fea44a489ab49b7367522b283c140a408ec039a66532722178029818e917a8140bf9e30810e48c472d0b34d9d74501283a203912974086a41a163ace8e99829311c215574340222311ed0af4d9d8a66800dd1339b3a0de912c4102b303a2ddbd4694894100c1101c802b166535aff746d3ae314a73e0dad460d997216385381cad849c6385fa88caf132c5260236c6454ab1136c24646419c4e70028b83e7daa76b8bc0c1d3e3d953ec9e6b6f24b93792d81b493ec8616d921cd7ee247727b13b09cec70eb1e25a7bedb5d75e9b8da6c65e7b614fd4d87c942f4d6c817856c7a45ea4bc4cb160711345a6e9a6451499a6162ea2c834b9781145a6e945add62864acc88c6a383de0c0c0e00a06f67e20a8d3815decd7654617230689b339f65eb13324ee76c9912145c60c15ccb0cdb860cba056241968502b120d36a011c3ef6870b0e3800312676ff646b1486e3a3bb546b153a3d6286ad8e8a0de5b9f68d1d401009ab4b84283831b38ec8d228abd4d6e3a3878ec8d228abd4d7676481c588367839f4b88bd3e600f89bd4d6c74b07bec8d228abd4d7878eeeeb1378abd4d76cf959e0fac7c90c35e1e9de5d15d1e1dcea7569dcf07d37df00108b61046f7d203d222c416c38cbb830f082390606f14512c121144207176047b71148b6d24ee2211618412665cb8315cdb0866ec48280149092620312100480260b31b68d004ce38e38c33c65ff014a81c1bdbc7804a022a09a824a092a8958a144020c192f1c5d7c8e8a200a3201b619cb1e08c0225a6bed46a54ab519012251867289c8d6aad526b956a6d9d9284132c385381cad809ce54a03276722fced7286327385381cad849c6385fa88caf132c5260236c6454ab1136c24646390411813315289c8d30ce50381b7d09825252ab51ad46b51ad98ca837ecb4687befc518e79cbf8f04010c55e248ae58bae57ac1606262329999196d060dbd4ac3ad34f42a0d4f2048034900eff129728236d6c8f811f423a8c6c6f63148712447f16d2506d584512fb054734ff5024bb92793054e97a12a745d86aad0b1b8a95de15191bac2a32275d3e28509744c26d06d978a52dafeb1162e9e1c018b501d03e88cb61740c9e2f8833225985e5633804eb781aa9c60892ad1dbfeb1022881a0d632d97f8d2aa1b4fd63481fd506e2f9e0e20585028a1705c5dbfe3eab243738569a72b91e8eeaca6a36dc09bd14ac00652a30812918303028793c19cb0a0c462f55e8d04748cc223e11f229f29a2db44275c6779c94d5194d9f229bed6505d44b1524083a712285b37d74325e72642ce996742404d11c192b64cca0199a61e3095a0ab2cd32b0693003d483a1dc51431e31006875c4720021306db0010d99e5e016333575d3c1d1c3d1834227f429f2394275703c99f449d213253578389e703c6d07e2599c7742aa06efdb35a78352c306095c348464ec6845f064ecb63f0b5e4f830d00e0414b46512d4a46918ca25a140d0e3cb8a16b4c2c7235a61a138b5c8d89db782371dfebd86ed870b06abd7df97411b568072ea23ac39d1480ef6a529a038220500f079a403cafb98bc82564a7c658c4454471fc5d43a88e2965a9ebc8761a9d1155a6f09870a2892853caea00f14ca9ed40556874376e90b8fb373e4a8cf7e4888b68caa68fa5e0a78fa1680735297586dbb01fe3512f5a88b694da01501474860351a139fed93c6b4c00f16845e0e0b1322af146a5a2eff1ec118b204f5959ca2ea6d8634f48c3b67383e4f9c09623462dc7a8354db69388389fb1f26440bcd18bd4f69701434e0edc28c2d844ab3b2f55f6139d4f918f9113b83609414f3e453e3a1f232090385b08f7da1e4c4f403ca09ed770d604aa42d3030821d84610c9f17d74524f945ebb0793156409d41b2d10af06069f22ab03c4d3da0b4f06e9336303f5a278c9114518c18b8a4620a10a099130526ac35602f56205884781a8501d918aa64f91a55eb26c1f233de8126c19d86e087df79428512285aee51017df0fcc16dc7dbb6c776ead381691de9c620ee7a2a80d9bc10a9bdea75fae599c573581a5aea9723185b8b3ee4458b1e2c214537c0c5835aea6606910ca1a195c5cf156758de56b74184c0c88849689aab1baccdddd1d464873e8db1f66344a478bcf7bef95619a255f3b4f5b738dcd78f58ff7daace053db2eaee87ada7dbf82704d93050b72890b1c1c18f4a580512383468276848eea798e59b2b81965b4b87151abbdc0a11d5131186d313070ede20aed084d2ed175c915ed1b8c2eaed0e0e0a6c3018ddb4d6a67ac5163c7868b2b16db185d5cc11d8c2eae5000b8a6365db224ea97d0f5c9251e7870e3060e1a1238706020c312d50f46a10b92a87a08bbe88a8e74bdf75a37227fdf2eef32ae545c8c955c25f503193bfd10e874ba10e842a0d325499244974497244986c1c0317cf052afb9dfe8a6385075c39defeb67d2bc1698dda8d46b9c4b52c76406000400f316000020100c084422599224692027f71400105a8a3e666c2c1dc802410e232906622886812084186388410619649462ec0c00e80a9d4c5d7393b66f9d243fa9ed11979069361d90e289cf09e1c16ddcd98491ba0a9b22aa9b2ef640aecb510853fc7dae7b909ed2e70b6c7aea3e38ee872b6f1c0025bf87c8cbc05770fa8eefba052a69eecd44d2d5c178d7e876ae59bbec2766926fc6d1cdab51cf60ba9b79286f14fd2a6f107d19153c383d7289dc5824e851c8734f48338241976be37a049eaa560664a91507225916b608c0660d1661f0a35b4a4a76f6b3c7499f68379d57cb621c4c27c226f4d5884432079a2c794c654dcd951b050642567eb1360c1fe615ec7140727304f191a21aab93a52bca493d59baaa1cd490a52bea492db332bd41a362b9b2a5ad1d201f477e6831bdd34d9545692d02eb11bc302688145de835b1fa38b77814063c3bb5a215b04cb0bc18a4f0057c2559f609e639e31fe49f17a76a956f5c119f9ee86c221df0bd2ad722c8ea42b0d5e06fca9303ca83679dc3fce2c529acf8cb4724e26a9b34674217d2d3430edca21cdae07685587567d651220a0e6917748b428c7707ab28881ae799150b23ed4286553329f483ac6e2970d2eea9b9099c29648430ba020243167cbb0faae409362a8b42ac770b5651108574de0a3c354262fdb628bd96709b3f3a0e40e9df21e64a702bb8aee077ed824992f94f8972f56854346abbb9b702bbe3e79244375bb6135c2068209ac35f871d29d4e5f5790a3d98034b4a4117d795a13b465f554bccbb969b6f5a39d16155d9f9d82b9339ca40df986b158ae3cf70d368230f0935c6290aa1860755d5d0be90e80b086e0d450502b7d3808f4c98960f86f95edc0669f99ec91a31281bc0e12d3e45dfe14da5003d7ec5b3a8165e081539728c2a197483e532aa05b64b01fd734bf0dfef75082cb844da701c08445830c1324d2d1d0e9b724c95290f22bd1499443f45f5b3d874f515ddadad48575b998e1e68424f3c4043e86674c82d150a69ff86e20e26db6ef1267bc8bb94128f3179f59a33e875f067b86208d0040247f4fc031da66181653189c49ea8a70b0282e0c0270a1f5be39977674a07a0979b281f9fa2077ad79ca5e7fd035579b89d1285e3a4b9cffba1905049878d90929bf47d7fa42a2eb750527798f417493f2d6d888b98a99b1b906284cf0934e06db9dbcc445525364555b4af14d746f5bdb0f5111a3ea1416f50eac15caa4ef328fdd19e8f094cdbed4f98ef012fc2416001d7a1eff06ba8f0945308e293f72d709f5dc2ad8e23716187d367b68e8a9d6e8a840539133f2d900052dc7d33432b2747f6143dc5ed397c2e5d69ab02df972c4ea5d15d44aecde9289a6e34ccd627bbb04f183760e2bb58b7c82a4a0ec1a1fee942b61deb4910c233be42d7c264eace640598f5ae65f06b0751e40c444f06e565f0fce868406e61df3c842fcb0775016f9cc6db8eff602d0dac70e68fdde09a3b758a777880c365d46457e8bf818a55bf4dfbe0cff3e23092ab07a8cad94076aca4daa03bd3a59601c26c43157218a92e1f6a3360ac76714879cd1036ab31843b2ec73c1a0dea497aba8c595eb0bb32c2c102318226a8e67c19a7804d43e3e30a347083816e4271850a1fcd628c0d44b12277071714a3b87927a19ab28dfece4e530050b1892603fab9f567dc1b60312ae12bc0d251bcd3e2bc441d0b7b68d68f1132420a7e618c95276cff57cfab6fc94424948948c89f9350d4b2a1245775005ae32ec7eee64d4a76b8536c7928649838e41209a2f7ce2d5669e830425790cc4523fa8d8e85b0e677b985599a44bd1d074fe4ccfd33320024d810e62761b170682c7b7b09b482ea7528db3cb0b2b0e164686e778cbeba80ffb3e658efe5329527b818daf2092fef595bf7c2063e3ee29fd0f3e62ae56275e77fb60a168cdb40427ca033fc0204e0376edd31974ea67484298764894243eb2f6ef0b2a520af5f4735f03211d6347b3a4b0f63fe0f56e7a422add7f398885c993061ed2cbe820983d2116bfbf9c5aeef2bf62c60e7603c038083ea8dd0dd62be34c44609456253e275ead6fc3cccf4ffe724b776de4b8d084e932c222062ff52d425107ec5cc90701f74c283c72c88e21b236c2cfc380962c3252e488938ac951d4a9e7986ef83a7e1ee381c5c7d6c823de980d5d9943a48f28e00380d4a7a96e834e7b0950be15b3a77d1b0a947aedc2b09657a600d25dbe4d79d951008a19d12593151a0eda43d463660eeb75f47a3ec5525c08b5d29475fcc013a601547878b26c1558711f9c2a6f18573594305b9b4deceb9367e6331abb7b615bfe8c80e105978e4c319235261ce42b133007b479df3760b4d56995980cb170a658745164ffc1203d2e2c37be579747cc77a53758a78cc05c1e8bc8060cf6deb489085ae85600108b6321051016406bab21163bee8a6ad0c910290a7f605b28155d1c096dea99979ca426d68958542cd0003da7d3df43a8196bcac305326dcbf990570eadce6f427bd3dace8d8ecd453fe3ced03a436f90eaa95a6651a64ad46f1b4f501711bbd839fad6c5e1e37c01c2b0038662301caedb322cb3e2180462a24b2df737bee0813a3db9ac2d03dd0231c949f149bbc3ed7dafc16f24eef32035a68e066b963bba979a670e6099d63f02a7b58fb11ad5705e03811a7c154730d55a4090e28502c73b88825ea71ce14e27e7d75846e6814a793254b08451ae96faf7a21b9aaa953dd39d626b7380d397c15749991a6c98e1fdb654e23c42a6d2f6cf66883bb8c258c0c6515ba009e652e9e6cc8fa04095be71749ef2040138611dbf7b4b3141d2867742e75856dca5f0634183b9c18a12c17e3bcde5214228e2746ff1808ed3f2615f2c29d9e30e3c70768c13c0366d3c4cdffd872eb01d742cd2c35b8c496b824626d5ccb4aec62c1c3275cc089ad7f0dc166874a1312af172578d5d60e720c46e098436c6e4263eaa619f339a2dbed55a0c741bb7d8c3920b868a9be798f426e70115d56e1fa61fba6a49117ab5dcee656fe7048d4f45781abc1e8dc3d9c3cb1895a9a997dea9d9d05ced46d55a52764ee41e8ca5ea06d759d8b2ed02b5f652466e7c24cab85d3bf0c0ffcbe6c632c94b6a885c8b9d3d5b3f7b9be0c34f0dac7d3253576301cbd2bbb10e73fea36a212f10c6c3ac3261613e375d483b615c7e4b21712b9059fd9494fe1520a6bad1b7c2b9cc9458b36a4a75f2ca3dfc4bb0309e4f8347dd435c1d3490ebd2a885e4eaf82fa8c03324379e235345673d81fdc92e31a3d2a0f891131735dfaa446a7c7099841d701f00444239fb0c99262a6ab946ac7344ee34f97dff388c7aa4b7d6f1ecd824e1843dcda6411ad051b651a6fda8448edac28c4e66dcf0c607edb6a433007ad4843e6e67b5666f8de4c838feb45e4cfa4ef4b90f1e27909659075c3496fdd375cf9310e5550aa67b0294410bcd5342bd3bd2f4076358d318fc94d2ffaad1e04314f146a1f8b23d322c37cf653adddcca16a576f3897b786912fe6b976601dd4f634f19939ab59e977fb0d084fe1007d776b20c0aa60225c9856af05157e5838a1b767c215a0b9d6c9e7305e1c0c364c1c233867f31423c233bba271aa890c44fcc9a1dd1a9835daa3d41501ab7d0c543b36bc06d821e7fe17d0ec2ebe2d171c0be4e2f593b499669d4ac5986c0a20aef2e24574a933d30d88e43950b32b8b88876bbf8505701de84a34f75f27c47a826a8f68bcb61cb3aed97afee882afdbb9d723129965ef35536940b06bf317143db7614b29fcd424d4d1ee0be682212f58af56ca2afa565f82796fd462b894fb7b4f7c044e4f8d8ff5fa430d64ed287914a965ce0f9820d5ad7e160081908e65b9a06e48e4dbcd381ccf8ed6a0dc2c1c7be701275eb2a4611f5403ea9a48db5828a35d786cf07ca958e099b0c9403e8d5259e924985056e2188e4d0b758b0975ed396a87a6086b5c8f276eb2ce6d25134d69ee8d6a6337ed3366941412b3b11c3dca4061707b413225523d4e5cd6c2b0a9626209d0356e2e341886214a0dbe36cb60cddf9164f1e338f662c367cf50684105c5159cbaca7ed8e80efd03cf29a49ade1438095bc3408ec0d5a6fc07f1a7d25935282ef4a7785236112d8c95ad288490b3c1f76b6eaa8acdccbc902eea5f041e94ae8a96f6e389770a00631c4bb09f410e7f2e6b8abda6532e93bae66cbc690aecbd1c2c70131fc4549eccaa3a021cfebc5adf4efb3e2d9dc6f73673c44e11f50e3a0dc336cd4b3fdacae6efe64c2d715a42b21d8b50051ca0360e2cf861bd4507d08bf060ced288d2ce70bdc838c228ab049c0597b51e790a5a610cc637d6e8cc6b9e6dc37761eae4ed45c6e7740d845135483aa1ab68dcf37fcb032a9bb7e46967db97030466531dd543110d82b1789e1f4ec474965b84375c6926f585bb8f69ef498ddad83d5153689d36e843d81986f4cdd502600e0a5341cbab30d1f2343ef61cbe1253c001a13868c265199fb1f361c0fcbdcc9a8cacd62b1b01ba158f7664eef600647c0bc711f2e9e18c972c33243e85f211652abba016da861aafc22ee1eb9169dca8326d33f6e3ee76733de0ceeeef27dbaf6527545841304cbc22aa2ce5e87a81935ba51e409dd222ec3365eec4c93387557dea9b45dabc2ab9d5b52062b91a9017a2c91753de685f23c17cb897069c455f2f15411807f7aae60597a6118d0f5d70d04504b438f71f072ceb619d8a79264d909dc4c301f41930b539b314ccdfeaec4d837baf7d0fa5fdb046d2e39af8c534aaeca6c18538bf8f72f0211d4f0e9aec0cce4c6badd07cc548306ed9dac3937ea83a2eb972654c8f493e195a4f9e2ce5e1570e3d8f9db03a2ed2c02b4042927ece35ddc861a5f1d09d7f1c6ae34e34c98e9eda26b8e411528d05018ef8b821e9d86ae19727d79935ba611ab49e704e20e5dd7e9e8288ca8c1a5798d56ef951050a079937acada4aeaf3b353a6369d7b5b3cdd92c64364373f35c77992d67664fa699f51cf93778e2c4037ce1bb78eb2d8d547469e62b0badb807399df26e6e646e0991d587489ca8299a0bdbf8ae009e34634b54b6709712a7cc766a84ad02e551e907ac9541adcd74d37fa41e95e6622205bc22d538293e53df7eb5282c37107c231058f6ae35095923ece458be1427079fa8b4fd3e28ae4dda78c9e8e88ce11432937d200bfe26a7688babc42c4d1b079cfe7b36338641525da40987dd0f232d69665e4e093d2e1aab418ede0ed2743054859f265d92a9d4eb44f0a9fb6ad4aa1d141c8fc528ae21449d4998a3bc74a04241b224dfa55463ebc0565287c0e59ceffa84fa2e3ab425b837055971249e86b82854d1c3518dce420b1f79676b40369005d15e47967401d131e09051019c9f5ab04307464848baa309422b3467b0f14cbaee2d69c6f141a79b434b412909c05f0969a747e7f35bad5342b51b15d89d1cef4bc006569364c81cf0dc9414ec61abe4868f76c3a830e3edde400a76fc3a4a74ebc8d83e2c7a27cf7423b10947c8deefc717bb00f45be567897c0574a39f201f2355b97bdabc19a697572b233cb7c45c596f8c65f06018c40d1d63228f8a6cbf6636d3dcbe3ca227d77e2a5316211566aeb4e1b1068331ea7395d647509763587b19503be1cd31a766e0a52e002a306bd6f970aa9c3165243f1f93941d0530d1d969052ba5ce8150c3c6d839125499dd2a124362087c63d75176d40f26b0569a632f1cd7e456d487180d1744c680f6473f3997c2d9926a33c3468373131af1f398dd6c71fa468683cdfa6b1bc209fb57da903c980d516eb8d48ab4f56ac149426225f485869be5fc5f91ed4d848110096869ae9a75c1c5fb5f430ef46b41aae28cdefac4cd78dd30143687f36e076f78b221c43071dccb8060dd34b266720e68bb51789bbc2c965818da85735e24a7af759322a35291c8bd0a109b9c6dbcb27a2692bf6fd5e9592110e7770f34fd3469c431b139ff98977b6bbe130991cad5c9ec463172aa1ee329d692f4d6d1763ecc912d4bcef5c840c75ca5c1eeccf20fd64008c70240b81a1d76b0a29826466ede93148b2793fae035903082bdbc3aa7d7b34e70a11d49f79e14b1f225ce36b9c12e9eb1a2a7b0e1ef9f9e348dfbd4412318dde7a32e941a06540e9564738d752a0f82e841fa851d3972234dd45ec86617b2194b4674a404735c3b857d00a4a36a013a87b156d97416ad9e1acef6cd0d3473c218ecf3451e0e3052e4b58b2e90bd0dae83a90690452987257a6421481965f147cfa1ba2b93908dfc0ef643d0bc9e059c207b2650af013db97cbc077b0d485bfe378dd91fd76c684fc3bb1ad01bb89aca5458cd443f2acf31989ad59602e890f45808822e0ef214228dd3a593cea34d1837097b43b091005c780f8ba66af182b18851d923e96f93f8f2f9cae31b0ae392c062b6ac2aaee6c429f678728676b1998f2ce62a18fca4e8dba39ee1abfb8da0d1a5729507cbe1edff76a7fd9bec06b1cdf85486728405c3208c211b06c12bddb0985c9f8e32e7303b1a28797a128fecc81cd60241279c8085968ed3845f9785aa7f8172ad545139c412f0e3a0f24709717d430014f705be38a27c8a0caad117a48a196d8e60ad4d66f62778c5afd6417945285869e600e0334c014505e4fc6f3500d363526d29310960751f1e3feade778ba7b771dbfa05051458ac993abb3a8d3bcef8f84cd7c528567c3fbc06a32fe168d86f4bcf4ecfe366313639118b1dd4c133908487c9a354da435d47b35e78ec3c0283a43c454c6ab390a9c2d6b335362db04a1df758ffbaa69bd22887753effb0282e008c3fd789ea2a8039c69e780409cba6f651c3bae383697d3b90663555248637ac1141a5235687a2dbb2a85ed49e36f2a5259221240a5f0d1c1b54d696600093a1fc84ee203e6e8b1fede3d73975ee4463f58d1f275f257a934f7c310dd97b405d21356da0021a9fd1e29cd00eceaf597c2312adc969fda52b9cd69419d801521ddd4155338d2367bca06fc89d24a23daa597236ab939e502c8d61ad6ebdc768b0cf7665a1ea9d0c1f13ca34b2bf798087a7560316b0a838a01adca626b7d7d442f091d2773b3cbc1ad17bdc356f96c600771f318f5f0a9525add56b321bf9c7b73f620e15409d7eafaaa762b811a554f3c6cd018f58d0e4a5cb03f29938634f49f85423efa4d0833fa70f74df29e466f5239a2d974fec261e1fd6f62e22cfed859b3380d27f2b0e686c7906a3d1342596a944983c3fe25e836c9c7e062845fc8a75308ce4187f30765641e6f77e05c4810e929790f1ffe4f011afb6cbfad7522cdda15196b2adcb006531e8ef19448ee0af5c665d95c879dded8d6b6b592f6894b43042aa571da6d345b8f3a1480160891cf1f340f1c47db0e41d37c5a6cd284ac205453ac2578f5d4239828fc26b17a9c75ff62e21dd3159e6d189e66a9de1fa39fa44ae9dad81e3020c053b18f948e6c059a244824ce8dd0f5d1a3aa5d16c81a5ecc13f65175edcfde882a4eabd63758c5f84cd39032ffc9512855bf634226680d4af30063efc5c1f7f9b840e930b65b45aa689a71f6806a8f8949d13a24c27a107144a24cd65f802b50d434d71f5d0960eaf0b7350af6c1ae7fe8c6d92fc8cb92f58a8e99dd1c4ba0227e11b0c9bccf94f3581a3e3d69f2be126d637aba8c2f107a287e1e78e75fe6346e9eb7de799fafe35445c3b7bd61e260a71bba6ae1394ec066cfcd6420a2ac1eb7daf585d1c67133373e5f9273ff4c906af0797b1ef69034ed8999a388562926ab3da12c250f0b859ab20c06d5eae74f563835fde0686cd47c22f0d12eb411285b1616d1d26022147d5a3544a84c868e5acffd40d9f0189d18f5eaac2de35012d053ffdb48df0421dd6123b7694a38465a55b02e34c98571da61800206b80213df7011000184e28794bcdab0b226d4aed6791babcc48ea3c4192ab2034da4634ad71c0727be91c9b4ebc2e67ada27eb697d8924ed78306aa21256cff99700559e1f5e6872a1d41f1a0689c82cf2cdaddab29fca015982bb982b1b77618bb1ebad5d75606a90ebd2a3cf75770a73475e5cbfcceb7758cc701625fb98f5b1e4fd38f9c2f9a4f7839a9618440b0a490fdd9aebfdb99f3b1890e0b895c9289a0dca1ff299449ebd41d7a46b4b40c6ec28f477ba82039078d5c573a07f805701e60751f51a59150b55a6afb601febb952f9add88c134099f04c49518a5e09c2458f91b754061cd6f1d9c0beea17f530a58edb9f57dfe2f4ea690c30a9934e5dfc2826062f2a701e74e0fc707cca27dfad07d11c17b44645beada2956f73d8da206aab868f5fea250a3a7286b3512754cd4a22eea2ceab5bd44417faf28e7022e9a2dd65d0699de13262fa2bdaea2d8d550d493f14503445cb47a7f518cedd02235dbe31d392915ca1f3e3c3361827f5582faa0232e563dadd926a87e0a8bc0773ef428a5c9a2d1949f3fe688baa0afac6763a71e311a237f25bfbef0135625f04e5dc9234fcb653cbfd0cc6b432d4e397a7205c614407068b077680b112d84ed390ffe01abcb8b8d56a92ba56f0f3850ff852702955e674b26f7a9fafe79189b84e26ae611785a82b60d6c588de54950191902c5ab94edc31cdfd1ca4683504ea7f1c06ad855460ed00c0049d0775102cb8da76a23cad14a3da899d1069e420af8f93337a0886cb69a9e93b7e0fe1b8c25c2809984b48ac4af8e138be917ea7f1b88330cb0ebb22d93165fb444f042b8ba666d86f7c850c68ccb23e9d02c54b6653762938795e8384519590513dc2775ae0f8817b64f0d5f846411cbd58e415ad054e75abd13d30b9d230fbc037da77332e19c2f893cfc374bbbabde73af1099cab26066dcdb3373d12d0134d4fba5a10b2656166ef9a93c9d5d1c72a039d1320276c3af85edf1ce14517b78327d97575d236409cacbbc259143bc5e6977934a801b96199a72f91fbf323d170f29b89a48c970252bc909a0b9d8a1945b1c346f38e6754a425efa0162cde7940f93e43251e9d4138e899aff6833abed2992fb5afcb30daba8892721c3920ba5bfac3dd7be430e5cf390435b77f6ff393a7cf531999c3da6867a364ec072719b5f5b0b3020db6cb1f0b2fb2471deb7cdc53e396e41f6ac55ecf9f4221ab04a668e50318c1fe3ac7bac53176c9d3228e63899162cfd12bdc7115e0dd946ba7c4422cd6858650ae30bdbb4c8c4e82bc06eddc47a28bf98a2e69dd5e49e3b9fe197760f6beafaa3cf446e4ce9650e25e3ebb6397113aafb2641a23abd7d01a42c8c3f6644a7ff1f4546941c60b9cc5f9d0e49e8e95bc61b7076d819cd7447a0ee3d761adc628bb44f9c001269339052a78fea3d8e59f24ce1cae6c46f6ca4b54f5c7d420cb889179534062024dbcfb2e6c32b392061641e92ab033199026162cfd152c469d6b3d3221156b6baff91da4080974398ccb49283fd642e19ac0174a47d47e6558b46ebf3dfc5f588b6aaaf34d773b8f998502802b452114cd4517ca1a1b58af7f96c879e8bbad42afca2d45320e7fa862702cb255c0b035c157959820388e4c3180dd4309d0bc8925a6616900841708d96ab958ddf7089eb1490ec11c84559e9916bcb75860809b8765eb20c33936c5f13711d6baa37d89096852559fa036f309d38ab659beec32472eb052d696d27928dcc852153002bb7d02c2dc561e303a2228dcba888a89a3fa3faaa3fa759484a0d7bf4291c11f697a54b22edfba63d63a240fb56c914617f14bf76f97c6c0d241ddef82c6f4609218fc3d2cf780b5af2b0fabda7c88bcab43250fac8fd68f8cce78b3e6973057137f9de2bf3cbdb7fe686bcdd309dc77d237fa74d95311ce23c206d3745fb271f17c32c8796669c1c30e1f4351de3502756bb0ee5eb7663fc27c77212b349d44b90f13d7b81ee088e093aef84c41f283c9a432ba5f38bf20fadfd72140a831fd098811c71c18de419e9a22d35e38a73aae52a9fd21ff7e052e9edb2e5985951ecb5a45de73b0a5fd3532a00254ac7e9e3798162b64b84837ef0e6be28cecc2825716158a1210c3f3675e81649e2fb7b9f6af39b42d3255bf0a14a17d4d439c6abaf662883da564c945cc5e058489fda17fa54d928f70907150b2e0cc31c542fe846042126185c81403acf4d938d83bdf955dcef179d157d4ccfe604e467e353f8ff3d49bc5ef4e350a7e8f41a166459336c117b9b896482a1f9074c64c936c21f1b16a226f6ad77f31ad40f1fce5920937b863571accf0b0331c70cc6f9c3edc9ea09e73a0bdb39ea7b17bbff6082dec17041c474fba2a82797d778090aeb4cdad8c12d45f3ef21f3f4a6b8d853c9fc50fc3c1c3540f22b877f19cf2b07e36fe4ce0e11b3d13c24180979a352653767b8f557ad6f8c753ccd4cfc392b87bb03385fddf169c1bf2c751d7f0bf8f9be1a1a1f896a10738238a8c1cde8f5893a28f1c71417b6eef0537cfa636b9980d71bbba7321bda6656fb57de4dd0f12415ef9826c50ad716eebfdbae49228fd00b5fe63fdbc80e1ffb2e0669763a0a31c5370975f926abf6580dc9ffe619a0a771ea8d3b7b5f64188b44fa7c1caceff8aa1349ea5f922a8df4eb43b8c5fc262cb04818f349ac212f50b4d3f2ce617e3854ce6af7135bf5c81cc623f80022f9a07a4228f433919d9616e1ef02012516d48496b33106dc0cb009e3e23f541ba9457a3352aacb81dddcf0aa8cad7d313ab6858f5d2fc5812e42781e5280fa07bb0664446bc3c76feb8d31e06680f5a9a0562852e2ab610bb40efc9edcc4ab017d3df7d2d66e164452d4141835f46811c576eb00eef90b053d1a213f64572d541e965751c314e9ab36d55425fea7327ca16c5241ee25e87d90fa625ef5c897b729cc2cc5c7ab480d747591c6d946e72661d1f67516afb816bb9bf351e27e7d070b62eeb0bed9454216864101a1b12e53277c17359be8c63dac04fc07301b657d9bba88bcc0be8d5f2adabbc45c2b41559ddd4b3502d9105114113a9930117ba890900afccca891dda1e7368799b95ac3dc77012394356d25ca2662ecc78f01c5a9d7911c70f10f4ce4bf77e752761b4d87f9ae7d60e0dca69c5d864b354e88fe3f6d9844f70b8d8d29dd766a703db69b09ec01c904b83e2c88b18ad238f51b66cd3ab29a5267016d49418562ad865c718ed0fbb9db3085613ec23451f250eb28db7674d78ab660527ab822ce092772048bc68ca5a86e3353fa0f74ccee949eb297c1cb2c7649eae827fe3470bec168130120fef1b84d82676160b411084ebab2fd6b1fe96a51f68c950ebe20fb421c5150ec24a0fd26b6798af33dc305f06c4b31a168224051f44fe1443397faf79cd44d1b6a1ac5e5d2c6e1bcd6297263fc0ba3ba07073d877cf2280f76b0d618fa41b287e80e83c94ff406bdfd8df3bcbbe157447004553018b6dc7d3c2ea02adcf2586961993d77d5304fb2844143fcfc8d010893a530008b672c3852a14399dd1e7c798e84cccda61a1147a062e50d3af918db1ac203160654646658741c07f3a175c42fae12bdf85ce3b95ba6bbd88ab12cdcb8da4ac0ca59745883235fb477d5b78c5c2672309aa8ac3274a54bdd75e15cb4b9d2e84fc78f2484ebf9e9a25e4b99dd459dee6b5171f45558c9ad5ba9c361c24f6b31ecfad04c6e9644e5340612f1a9f3fd6772ecbed23e97e4f0de99aba83fe8fbb75102a07dea708f36c49e67a5dc07e7543538cd5fce7da5d6d6fce95059c67216810df34bf06d9bb046afc581f171ecc83d7c5acd63d054c6f0c2020aeef8e0cd857042e03f1675480a126984244d8a8ad22997ae1d2181332fdb6f50044afea67add110c2865c004c56b4cf51d0c9938eebcfa2647c986846301f3f67595d41c574bb4e614daefcfca03cef4c729aad64f921d074a76b8c12002af65df1f4f1ca52f57da33f619558b0316e5ffd22d7247368537e4c05217150e0a5fcfc4596f3dd5ee879ce9e080cd5061819a04bc929e508658db256cff99c7a88032404b45d9cc849952830467c6d5a0f78e375ded639ace1847c61599bec927fa58aa0a953d00c7e817417f8323a7f7fa81b0f1a9e425b05960b1730fc0d85bcbbee80c8fa8e1f658ca63af4a46f8d066e62b73bcb8c036582af50805f6deb658816718ea22b0fa614daa0d59c2b3df01289b5d2af46c0a64345dc7d9fe9822a28ade4291c485b0804e660f0eea275282cfbb476de71b182fec6f85cda6c5a3aaca3b808cb3afd36d01cee5b540ad80f4f4088d3130d7582262cf352136df591669d5faadc1fd0208fc554bd553b4e9ea295b080a8121d8be18595c2aa13abd805cbb8a904d1af6a00dc717bc45a0a72f88980250895f70b4d9e60c5542c372b65376cecdd66b8301606edbd29bc959e606b13d860f760ada227b82f0b9c5ad7261c860c5f564e0559cd6c3229a88c1b96290165dec6e245c706c4cd216d7e62e0777f2b462b52f647a3beeee4980049f12d979003e85d6c4664df73feac5e89de8e7a4122ccff6e58d6d5fd0b2f62e73f8d3833db9914154ec16880431f06506121e126e7472f7f61521a356cd88b765c9b652cfe1e5910c1460cd62c48a12e889e2398021863383b081340d901d49159f77c6acd6a6cc05ba4516ba2f2a18544d5bbae4bc2e7e623350195199b594b185d8a43355e7df216fa48205d088f94125b65c2149be3df9978b1e768ebd6f80d1229893d5726e1f874423fb9ed184184d7c74615bdbb19a786454767a5d860fffb28278742578fce0de6a6f47085e5f8bd5986e81cd94c9ce9298bb58ff50cd22467b6575397fb042a25c5238acc4a4f883c0549152deda938c295de3957db3ae4abe44c778aa82d7aaf933b47417592badd298b9d4f0bdc971385ff08a44c597e85812c816d32c7ab00d44aa57b86eb307f2f2d8824aafcabf303ec62dbc922a146b61170a9bc0ae7263d7f21a6bb3d8f46b8f96d1710378840ae0fdc4450d3a1862834bdc32822ec51047d4e31108bc7aceecb758e151320454df8d044ea56dd8157cecea47e0bc797eec781079d1927ed2f2843c08fc2eab27fdbf23fd101952c4505fdde57067e4a94d0a58ffa02245841996313f8a1219c683b5b4f839c28805cd1443a00081052176788d182e3a581d865df3717e04c2eea583bedb28e29ba1bb617a59c27ee2f9de884f73ff6dfffd865ffb5ee04b3cb08da790e0840029fabbefb43f1acbe06001600b3a115263a4497fc20972f78a6f62c58e96fa8c8eae44b017d69a8761141ed63d91c45c93e37cf94c20c210efbb2ef467b7dec62d529c12141273ef746c8177c6fc00d4ddeb60eeb25a744d01b8070436413726bf266ffc34b1256a99ba1f6ad514adcf69ab3068e0f6c659a36b42d17562e55f9190dcfc01e88f06aea6e30785fbc0555bfa08268d94a545550bf49438cb6535f20c13023c9b324aa28ef7d50480b63a8771becc59abf7bf4c7d6b36914caf49192d245d9d5ed11b9283be7d0ec981be08496bf32151bddc2bdba9d1c40e410e5d42c47eb1d51a45dadb739d09b9c36fcd36a25e13b85d80a236a04d56a043147b3872efef9a4de468af49591a0938e6e1ea66cf20e6e3721e2f4493ba05b0b28a7885fbe1053cb3d24c5aa72c6528ba51e3a033382b702254637d83e02ca12d49d31f55e352adc409e666065135cbb7153b4f6ff5dadf29d75bdff36965c11618c10db1087801a0ce1cb452774c0f39d9c841357d9b868c4f28c7ac48d1a6885780faf98b37dc3499026141984707de8190935b4b4b05868174969c70a35a225d8edba5f4d66f2c68a696e07d7f0211ae42d97e9b5d6c393f6054a8e69e9d16bc20276f2818300f5764d9cf29724bcef62c7c0e88536e899c9ded6b4cc7616ec999dd7a37307289075ee8f0a472c0924b3e1b7687ff25263c482e2133d18bd3d6d11df9e5ccb1e818370508f7be35da2e2f9117c9cf1afa9590ff95932c4f8e12a144869ce34000acfb737abe7acf59adddb242ecc4800ebabb505231e52cfa255555750d14dbdfb62081b3392281871f5c14d572c47e696470033708887de8333e85b03df929e5a0484851cbc4bb84fc20202333a1d084f2599c6478d67073eabed0d4e21413c5aec246fd683218f403855ba5494f1d2305a4a9f508d0eea8a4277ffb590c64ec9b192976133478abccb3fd119e6a76d5b9e36e8b87434a973e14b705bcb3b4c13d267f51199f00b9309d23a410501f705c5c1b049a2521e8907d91f2d161a99b90a36f96863c0c9cb51165a862046031620f782cab6152559168d0d84092534e3e6e856a3d249a7c40584abed906e3a415381bb94e41962bc9451558ceae7ea20fe1af12399b17f180d430875151b85f37cc9b9d1b9670f02ce2fe18d3580a4c89a6581c26df960926166c9018559f9034082121beb07922c1fe5f08c90c7e44aa504535407b9cdb6257165262e748b4251c8ca2b222c6c020313a3716a4e8287d4f06ef9dd7f8f207748293c2b4d56546dac8897c1a894dfd4c1da31e025351f8a652590b873846502b88fd014e2ef4d73e8e066349d7d68f6e5ca981bc79c120b62ee2da1fe993d340afc0f53552a26e952c25f511019724af90ebcdcfc16383677309104609fd37b4f38188ef10058f24f9d6ef28781e7b7f700179c32f16ad141717a7502b12bbc25572d5008853c7bebe2aa7cca447ef9bfd28093906f5b86bd32c13388ae1fcc21457452ae2f112d39e08527dd88173d891f4e0d7008fd2200818d62f71378a548fc1cf8e2d5168f1df0fc9e147c9c703896d4f4c4a1d485c7b4248a90346aced107a40aa54d76e35cd702948971a9e13e9b00abe593d057a4dc1f3033ab9a6685657815c23c5a51eca25d56c7bafd468549e991434f20e9a5951bb0fd14d47ae8c68ada8d761174bd7eeb14d546ce93eaf84b24307de5ed29735101e9fe8e5965f3fbd17cc7f895f2114966ec4a9434da8ba93701050f483851ee05bf57423ebe9eb3e7790b2b87d9c73d9605b3f22c12033e1f7106de9c60dd3b406f04c31b25de06f54ed42fc8dca4632bf9e8a0bb0a19fcfee3b2e10c38b0c61c898a68f6eee892dceb94aca32df9dfc49011f99574e45780497d3c441fbcf612fcedd5dd2d36368c1339818088fab8089c3acef97bafc45c802b868e0cddc4d0280fe0ce216a77e81ea18803dcbf2b9e45fb23d9c8f7ac61c13b2faca5fb8c7dcc44080bd3f11f256988ea72e646fb187acaa835a96e9426ce3defa3ceff8e18bb0722a81c3d0bacaaff4d5f87eaf2c9a370ff5b70f626d49d7e69b6600fa4cbd0841a95ace8cbb734bb1e996245e9da4fad2cf2029e359a24147c8227b47e869cbe7ec0cf43ee2a8de8f3842751707f5c3679a100ba866e0aa5396a3ffc293d82bebc2c2826df7d88582b23503a62d4361f483f7d1abec09fe5031aa75e857b79c31a61cf27d3eec387cfa336c9dbc75498cc9ddab6797300110b89c7a31b8d0012fc0ee14d813491f0089bb9aefe96c816bc241f4e7dfb1138e8947c96e88d420bb984c273d1c9a559fef39fb36d96d93c81df867e0dc126f8a4318c9a293f1280c422fb18936a9e4ee0402226405ec895cffce8d2d0409b73e1edca7fd8e118128cf72318a2927de71a477f5343cec1834fe91f6920e3d45c8d238026b78c242c382e0d7ad914041d69d2d9c5eabe978eea3472a549d568b7ad994aafcef1b88d4cfdb31e78162ae2e123b817f60aeafd39b694a355865e0825d6d4b50c6cab954f24209dde3691d2ecba45988aadc1e3dce338fce751e968f2597f95f35e4daed6d8f98f601fe037cf14e618f153107165901afab610bfd76c6339779ab2c5eceb8618d192f18c62e60ddb73649cb181a46bd0eecd5cecfb5a5804bef79c311eda4f7e0bcbb5a5701d8299c40be21988f317f988858d42019716274d7a475a7700251c7da6c989ad63dac284d5f2543066a8daab87ae4e24196a2d8a63ecc4cb1d6cac748c7f9602bb88a867c862196c524999fa120b2b826b5884cba251dc4d1c4249d24647322c4a55d8a0154005db032b15d24d63005a1c45ae1f3ab226deff795fbcb7a10d91edbd7b5cc24bb138ab9951f8c1ab66845fa58e2ccef253a54ea8a748e188fac90417d6e66a248d38a5650ae6c1cd3c4d08184401c831190ce3f78f2127ad4babb86f747a17beb3619eb985c90898e32a802e35efbe9ebdc05710ba74be152d8da5689f2ee7274cfa4ab8c5aae812e4124706814b44820f6580ac825c1c3baebaa928753ae8802523e8820158e125a09b9932aa1521d98738f0f617d9d6c7d401cc619ca852cbfe8fb6d7fcf5824e6e67f2047289f139220898e282905b5ed263223979de7b3e46883674f4877318cc922b1e49a92c7e9cb09e05b4ba9fa38c4051c5b0f668224f982882f1bba102ffd4ba15cf0b6b8bc94b73d96724f0ae4a7cd9dd8e669a31462b1cde9a252390cd7a139c7f54599bd9fc36869d20449b9786f2ae4f34ed5bcdb012b0179f7974c7975141013ffc9312a6abc4cfadb777b43a9b365ffd130cd5884df16beef330e44b6d7f877b6ccf92c0989b8ca42521cc2e1aa8b82910706d99d1cb22f1b95e955cd73462ebc2a708d87b208786ba8469f179bd8be6a63536cf773220411138c32dd48e7f9e49e824db974459bdc909e688fe6a3044ca2462145394fc681e7417f1a9fa55bc1b0627b858969b54f21af424f8574b48142f28f7d1a08fe58da523854ce182c358215126dcbfa3ad639465ff66568c3a42c2393b07f74902949d5a392f82d965968acb5109660d04b8101846de7d2ec2666f1e6b259a59580d9d56a05de2af525f77303fc6079306a1a4e8c04869e0c47a3758ee9f2559c61ee703aa095f7862615303df19ac822303b64db11601b32933c47b16071b2bf2dc45e0d2de1f61c128ab7320fc462def4acc6283426f50cc8c6e4f6de145703d500289c625c206943714143f42bd8b0cf3494a478b9dec60f31e2ce937df8d06b363d4f8964ccb93fd959bc472c6a11786acd2e820c8f5610d66bced6668cc1aea3244871e277e564120e80a3530fc459d3dd4b57196c48ad0d4ab65e23bd99c27bbc410fbeb3f5fe3018543ba1be6ab138ac25ce38a81fa98392fa1340350ff6113f513221011ccd9587009d952b91c433f2d3ceeb5f03ddf30b879847c91231fa1b6d36df6eb224a641cf826c17419a355ed72bdfd658ed43151e7eb5137a72ad970f8f5eb6dd7b9c4bee6fa2c3b59098a047929eff3fb4ca3ecf3199eb1724ea501d870c6e6c70d3c61a1bdcf46d646960370ba142fea5abe2b94021ef48c4e47474d7d641647e5bbe6201d3a2dea692971d5c55224fc85f6ebfe7389e9fff21c13213fcd984f660ae113f6eeafc62396e33c45262e27c04873ed8fe1a814930573490ebe359ea9670752cbc0a7e0bcabad382286fcea65be03cede99665c8b203c34d854f20226ea5ffabc1a383b6ea90bc2bf7c0f18dd8dfcc7c0495521e4f6819c95c2aa70c26f5ce42192b10d70099c958230f2fc9a406f860ac3b823f629f360c506a112846597746adf8a4af269784d9807e08ab4046a34bbb71fa973c01ea0daf5c70b22a16412e56ee07f2231da6dd118150be21be1a7309bc00b2c97418e9389f5aa1ea0443350a0e32838308e1b0bf5855244c76401a2e8ddc8ac47fa7676dee5e2d0105e0e271c7b69b8ea406e4b21ec2971e0d8398d78e98579616c57cc6590a17243e67543e1cc4e61562c9440a0819b80382c8886351369551ba5b2833634c4c0ecf42ca3e02102f6be79ff4d12200c55028f4b447a085af6bc4cab5f1987f43fa150ea7a3516f05b95a4e718f048bea7c13668e88552fb9775e4237227cc55325e5cb9e4c5f6f1afd72f4e0e976008fad620907999501b4f4448f0a26efe19bbaf1781489019b0e89619622fd2b3aa543c687836f0a8f471315a38b4df176e99276e125672ee6df35933e08d49f8c2b55f61d14657d53a54f262467cf6cf7e7178cb71877b3f40be96464599575e8a8cf6d4d8e7adb038a7174c2f8eb25be115922f4bed3886fd349b2f0f9946f6dfd1f81607d7129972477001878e8d6c0fe5a469a6894f00607e344fea53aca44e61da7da27f24d58f89c40aa8487c80e5607d7323e5ba6b409f8074b7c86c1358707f08bd1413f3495519444eed89bdbafce794a43448cd8ae97f1acb6454dd4749b3ec1612058c86802271681af9169f73d01f7ae001efce11b99ac550db45d7b34ece0a17399ca2723833001b8950707511b0a7492c237b94544142588c1b2b2abcd5334bac46ebc2e70693ec7f8d58dd5fcdfcee96acb1348033f2698fb90eb71692d71c127d8bd788bc9417cf17aa7b1732f1a04a7c47829e36baaf79c907b2f90270d22074688fc271e8feac17c0fd00556ed4dcf683eb427845232e6470d9057852cc26cbaf32671785547d93961394dc5ab3d6c55eaa5301a061454d1d3fd40eeda9a2aea6765c44bdbc2f410b255e08887cd6ff519662906a6f5c382116bf989964364868c2498bae45718ca5f655fe8cf8f08990f8468b3b389cd4af28926f52dd8747e06f5f12a4e1a73eea871d634f0c607ca9e677ca7257dee1b5ecb46bf3af6cde1231f64abc223c6e6d5d86263fd280e1b79cd256e6c764ea686fb8f1dca2eaa2907726c7e71beb31b0482659af68e32b365c94ec022087ead0035e1eba95d50ac003637c7859da5ef370d9c3fc2c2a2a1fb7cfe372218047e0c7dc5fdf26d7e9accd2cfd334c44d2def8981e34e7536f927c6ec7e380e532d5f10a6cf5109348403064ddd00773946c805e6e87161fa0faa5d368942a165527321cc4f69c7ddb0ebb2b6a578147cb6896ff3b34ba94da6fe0e72110c0c7d56b6d9f84ba1e45623c37ed0782c3bec056daf7f67ae8146c6bb61156d5b9415f485abc676cb79540ea3a87360e1743a7d4dee7241da04376af536fb3164ce3e1dce9202b56cc3552d555ce9dcc9d5bc287a954f1ccc65b3d9e8dc951280ce95afb8bff120ffccc7e13f9f7ceb3f6e88a52f523ebc8cb13016156270f3361c3bbe8df617e9d8bf83b262c54d42770ff032cb3c55d6641207dd95a5e7c21539131f0a8a1fe89c890115794b561f56abca77f8de7b0fa751a742fa8afa9156c42c240f1e80884071497feac6e564281688e7437f6d9fd0094dce765529128a0b01dfc415fc757426b7bcb88328285ba689344ed9c22d9fbce078b21aff4182e3bef5dc2c58a0dc0cc37254b2f4fe8b18859ef4f2f1d5c4948a07c0e9fc0991cb242795233e5e907b57571d61521d2402d5034e8f2cf25cf51148e3c19991650673f0c69c797c8a1e022406c4a78a181caa3547338195553c9869a8a44fa612014aaf9a41e78042574f6aae96e675d433ee9962e767214e0ea89564218def113df2256f3c01e3682643b7a1af75ef176ef9b7a41f8ce8766a0820cf4dbbb76295e85bfaac3495c64cd905cb5a23c28ad9d2945605372a1f347a4b789ac80b5c0c9393ce21bbec3522c5f24cb470fb6c4f199db0af83fe4cd2bd028833320c49e116c6bf743492e48f7635b6ff3d84505eb5002c85b4f872de22d3d4c519a862fb3fedcd4d61d32f2fb26de423e914af0b922b45cd0d6fc72d1aa6169274cf4fb90b954268b7637987cc2e728ff425886969bd7918a00a1b0a5fc6754a0ff99ab6e1e411e85da2ea362ae5a571f45d5868e3b03b951dd8eb38e109db608d176841d4e9a72534dd824e1149ec5b766727d2af12f70f5b718b3676a4b2b16f997ddc32ea671bc5e1c8f709910a5e01bc356cf224a64b1670f9dea094e41db9cfc58b495b3af2a5d40c0a96cce12ddb6f8d17ef00f07196c24c3efd4955ac1ab750400afb07bce102fa262a705d30145a4d079a8c88e83637831b07f3672b657b24443126477cb9b98fa65ae68766230b77e56851166564904700066a7cba6e8ec1afefeeeb104dd3d87140481344141606b8a05665701eed55d061d370586b216d6fb9a5dc524a29650a4707b4061407f22b3884fd39e90b32152d38c35dc18c97a90732af5cd9f68911937c99e892dcac02444cb476ec21be5c41d148eb67871168472660f1e9d4896e65c78f3ec30b5267c61df952b64f418320f89114d2210ecf0a423acc113d22a81870220e8d2e70ae4e882a42491d0900218aecb4351f7346abc994ab2e2a0072a2dc8689c661226513f944429192f28833294e121d7a114e90102c262ba23c77e33813dc45551c22706a777ff6fc5cebab404a54fc62c66309344c308180aecfae312b56a3def6e092a91ab8567aeb62bba2cfc6245f492b007ceeebd22e11f9da7eda8fc155f167b4da666998ab1cae8a2f43c56834ec84c78eecc7420e148e4ec538947e49116556a44e28891c499d30d6680aa796a376dda3cc1dc86de64759dc916044e2377303e32b26b9c19e60ad8baf1045434887f2b5d5a40e9d39f6ec66ac4087f2e54929254e84c9d7fc1985647cc940bbba902b4de5ed41ae5257c89edbd19e97c88cd45e9739d2bd7124a728d20042eadc1973b0c08ac99f11a4432f7a4d532f85b64c1a4634ceab394d695021c56ef5ef96830596c7ea0c22dcc8315716fc1cfb4874e8452fd3f5a750110b3e2ab524188d469b006151542445105c94a2942c45d0733bd11239c0b440cbed444bb480b0c377726587291b414ce00a811059e420ca0e7688591039f9e267a4ec762227473bfc0dcb32552e1247385e502309aed55062050717354db4bf6f33cae4818ca848153edcc0071d8cc462b119ad5612435c232e889c0811c176e0e3840870078830c490104d781091506d47f08679237f3be8f839bf0f5abefc98fd09e0bbbeade00f20fe61c4eff7dbc07d1c82ecb88f3f0bdc70cbf7ded721c88e0beac07d064120fef1ad05b90bee705f078cef7dec3a5cbfaf834f950ed7b77b13f54d7a844c3fdf48bfcaa694d2b7d17a068816f45183063a74188fb6d47acd0aeaf7fafd5c9a0518f5ebe7fa180cef9db57e4f095c68fa52f666639d4bd8d294749b89bb6443e29420dd26477a71902ec89d71d8e1fd04041941900684008226888062073bdc55f9ef1776e17dce74b7e9aba1db1a4c7124d01d2967efa39eca9f27b507c815d8d73d95b9f78cc3cf00c1bf2956211819c59f331e08b22de90c3923e3ce80f606672d6e4d763157a353792952975ff92703dd2c948372916c647b95e5a05c241bd9f16505a78f9ef967cb4aa7e94473b7197abf7e66f17aea9728b5f6292d792f04d91beba327afa7ea39e9bd2468a1c5aded180335130343660645450c125e7420c34507ffb16a2e1f4965e72155e68d5f6547d7d1deb4d26295e94aab32dd6194cd3e994867c15b8b26576b34a6199a46e94db2c5f4a8ad45d38aa64c31b3bfc92953d066534ca1cdee1417ac45f6abe9aa945a94e58c7147d971fb4eaaaa940d5699dbc46dbff0ee57d508800d1b01588aa255a99f03e0f5d4af11e3d472957d7c505f65463ad412277623fb1461fba579519ded2ce387d92773df97830e2b6d479971c89c489dee1bd926716cd1c5cf89d277fa9c999d6ef9d8bd10246edbd295a0d05d890a1d76fbd2296b0fa9474d9f73fa9c734ea794bafff6f22375af9452bacd3969add3b70d0cfdedf449a9bbd30a527ac5cc7741e937a508f4e88476266a506acd0109b63fc92e35a6b1882a370241e3b8a216e50bdaf6285f146dff6e7b942fa06c8ff245936db747f90289cd6d8ff245921d2110e58b56142fac6c8fe285d1de1ec58b29b647f102ca0e511ec50b27dbb43d8a174148c8664ff27311e5a4d56e1773b9f348a5f8e16048369d4c272640272fc6786219ca376059416cbb4cb57894d21617292e2f2e2f46198917981718fbf280605030a8129044808a41c5582156f08118183130962059d2721918325296c41cb64468c912dd755d2733b3e4e846961c944aa51824b82e1324c82041861151fc641bdc99edcf8406fdd497cb78196f0413239e50972916161696ff8c38a22d2f171717970f3cc2957d8081818101696e4c4c4c0ccd8ccc858c8c8ccc0c1a2f8a81a0448a5d03801a1698a6810c193264d4a4822e9d414a9552fd405b231a3f25476c97291a1a1a9a1a01c8403468d0a011001bd369b454242ae9c146003602087a05f57097b88ea8bd006e0470e332828a27841b9c1b1c2a445b817303e7c6e682d94e9404ca0d1c377004d5b610d021947e40e3c8c19173684e093939d78acc65eae6e6e6a684128c70dd1b376edc18c0009648b9317bb1cab15a61216b04921316394cc891036f276222c4526402cb0413ba289d76728df86162448c12ac1d9607245e899fbf7bd56d3eea36481041e207294c8e98d0a8d8f2bbb86f0b764ed8d959429bdb8996185121df22c409289c70c2931d764ec4a4042f6b4441b03dc2a6c420caedb0294a6c8f28a0e0f554b7911f3fea36414cb6ed444834718414ae4911124a9038120bbadb898e00bad559aea3dbd9d9d9d1a1e3450828a080020a29a49082d7e39e827f0a29783d3ecac3f35db7213ae2b5b1b3aebf3094715881a38ad98cee1d93da6052277b07951d2af840851526e5019a3c409407a887478c403c26550168aa00445500eac1021d810dacb08226b155061feef5f0e0b6bd11e436d4468e115de381a739cb7efe9916a592675a7b3eb511b311dbb3c6037bfa6087b18a3dbfe6cd7d54d6c75fdc97dbb97a94247adab97ed25af9f4ab301c332e88ec33429bd9b65baec255f63dd3b65aaaa844d2315aa9a2b9ca339b96b37c896d4b60989ad1f86cfb34adb932c9402aae63828134b036572e6f695c4c5439a2cde62a1f1dc15814ca249bab18ada982d9b76f62c275b2159eb224b0757708f38ad1cab36c450cd706e699dbd8e7915f90f65dedc768996047dbda9f6939eb641f8cc1fc6cfb2148dbf63555b3271ccab63299b21f8243db82b26dc1a26d33cc4b2687f61350f6fc10e6c7656e608d95a8d0d2be9e9984a206b6fd7cc4d148a1e37629342e49a1596e8914a345fae2de481fb7b76dfb68db3ff54a60eb4ba24397f5207df44aa0f7e1663f6f5f85edec7d71e7166d7b1fb7ad11fb7296fbceade94dafa7f4a4e79173db487303c3d875b5966777da5f121dc690711fbd1e20cc6dec038957f6294710e6acc86dfbb9144388d4b11fa3f5d19c95b77d10567ae9f59474696b1e27ef3b6dfde58935f73e60903a2c6fbf0a398b7bfbd6c759a7b79f4f9fe9b92f6f968fca94feaca5d7a39ffbb87dfae2ced3a32499befb1c232679de3695bcd269e7e9f500e171da1308b2f5f715a14b3f3f7a3e8494beca76e963cc6d4aa08c0ba4dfbe44fa6d9e3697c1d3766f1372d669dbc781c5e22e49fad2cbd325fd491f4797a40b56d806dacc5a64506b3b9790689b8be03a15e85aceb27bfb7ce4aceeb7ef5c73359f52c93fdbe6e32cefb7df80d8f26f6f5f9084ef582656c859f7b7cf69a2ad90fccd752ee0a9edab93ede5d7589d94e62cfc1107516cefe533a01a4530b42cd8dbd3e83b9649bcd9ee4b59db3fef7dd213234db64fd9ce44173cd850acd4aed268a4d0272018d861901d83bb4d9512a434ebf188bb3ea9c2dca6fa10427f7e05a40e4aa6b6dffe02ae23e3a9ad03bab2b730e2606fbfb7ed2d93b87343bcd97edb2c93bd7d9e5f61fe64cbdf36a0bd3dfe288dfeb0438f62cbedbd2f0606b88dfc1be46f5cecaddb9d0ce684e8edf1b69d5a7bdb3609a44f3e780a3a032120f8f8ecf084ed2f3329c542da7f66bb4730b4b13d469739d8cf381e9b725bf9b67bfb11887b8bdf5e6db3f7e18f9ff7751fbffc99c61c8790ef7dbe237ebea3fb689812981588ade89a2a1e33360d32652538c354d9e7913252e033a7f681b3d9ff7ca03c1b8fa56ead76957debdb22d1416cab8b6cfb38b12444ad21c36aa041a6ec4bafa774024d3fd2cf063a83d4a96fdf0172158984dd0e7db6ad8f4cd9af21840e71b68d2d5a93123fc9d274fa7cb3f47a6cbf43dadbe1e73ecc71bf398ec31cae25ee2f7703ddd9c8ce8f89aee861cb8e87851572ec13a4ce0ffcf939fc3da5207d697d1efdf787fefcf5b395c0f6fef4e170fa8b83e9f554d5c73e3e1468ee6516204d320b88183855aa9f67f2481ec97df7f527e302f7a304badbd0e7f6be2173ef32dcd3cddd2ac361289a850baea084b6cf33bbda495b0383367dbfdbd75b6bddfe6e1b4a0b1a29cf54d1fc42ccd3bf34c618b7fa77bbf7e3ad5b84c9146d2253d4242b424730a5848e015f90292a34573e8436cd31c61823aedbf615a7e0aceee9f3e41fdbdb87a2a54367da6d5b8e2186fb2d1f76bbbabc7c8df9fa39e68b81cb42c7f4880163e87a5efefb70883bbe2fa29bbe6946f33ccf3315c914952253f467288940d3003a40a6e8a792d0a6d854a54043e1d34dafa7660b1d9a6273f599a4489d97a76f2a923af7e99b4c3253d15c91f0f44db3b99af134c6d33751148a448a9e0d2d6cb4dd73658ad2fcccc7007e8ce79130fcd3781a200eff4176c0b8628ad02eb57cedc87626d92773963bd954b7f68cfe7dd3fb903a3028fa303ee6eb17836a89e981f18537d00de363debd1e9998f7981818312f03038c41a6680c08038a05df15bc816e98ef3c1752b872e5ca8679f70ac0f2f87924eaa31be69371017ffd0afe60c95bf71f0eff5186838c8f455315631f0a74cbdfa73f039459c094410228b30089810f630c6f20f1caeefe6532a143930b38c4ccd337c968c9e7906e013b99aa7f5fd7bf3205b27cbe4ddf2c3459094d479bbef785349f4cfd99a7add60e90848ff1347e8a88b576548fc79782dbd0ff3e1ecf3e6088811e60bb72e58a16fbbe8541eaf80b32453f19f8a300dd17fcb181fb3ba2c314367d12be18dfcc178ba68abe8c064c331b3c731565be83c6d8545114e8df94075c6c93ac04936c531cfa2938cbc120948c0902870c1021dfbeece6bd990bdda2e56621eec41914a61945221728715a951d826843e87ea8bc64d1ac76d5eb9109903b5898aaf80e90a9e821a16f90d1b0c37e6cb57648503e0cf32b41083a3a68cf4705610626d8a63d67b42dd75cdde46089d68ef8f16dab892f5c0040d3616ac768e38498cae1ac1f67e51dbf1e599f697fea151f6a1b7bd9d61a2e6aacc41bfc55bc9e9a591242fbf3ccf9d55491295c53a39142571a29b44bf1218a612251d064a822573a5e53069ad491df85d4f1c27acb4f865aaed1eb24c9404381d66f7a3dd4026ca26a68cd550dad8626436daab00cb4a9c26f818c36fe3c3f1d2f699a2f876073d29a3369626352ec0c5b281bdba28dadd1c672b600933a3a7488166a0d4dea843534f929d0f4654d15a9231f7f4d4dead4d0b2fcea4bdad570d1914cbe430bf433de0697c2b9eb704ac039e1e6c841ea3e2637575b63e5c7518d15b9f511142f3505b45e687b3e1424500009a8b48145d103197a700511f40144507a29256dfa8413d1c9219329fca10988dd997c76d7799d09411b7728c08a76f7c48e0e22f1067f98a3ec2ecc5276d7752623bbc36208dd8f2174b2bbdcbd57c7eb96ee8fa33bef8f2eeebda4bfb7e648c7ebc751098ba38d9ff4a38b0962d1c5c6764617d0064657112d882e25b6f599e38a45367e3b6d9138735c76f2ac007be1c6369ea669b2c222434dea303d7e198ea40efdf865e842eac028940532e42a6cd28fdfc2e6ea743f4a91294154b1b116b48d6d8876a886168f6d5b10880dacc769c70ec4aab4a20f3eceb21f7d00c2bd38e2a20f3e36b01c663107a3d88198b3b20ffbc12081e812da3885dfc68077e8efcead52af470ae1400a3bf4bbe28ed38755e63cecb6ef3b5c7187feb016f90e20311deb5a80b5f044ae74e8435036e63a4eaef4fb53ff166073a541cfd9bd3002068ee20db6b9731dfa2618b1b19b50f30612aff4c8ab9adbe0c71668e7b468ce8a1b7332f984094128c0367e1d44e28e3d125d07918d3fc7508e580e282b2d36fe552d6796e3b3f1e7f490c343ce0e39ae9922fdb9bcf13b429b10f48020138298d8c1c091df3cd933c7f6fc3043d953ef09c2b2ec48681ac18e027efc067f682ab2a5e9b5e503826a8e6c62354799669ae3ca6196e3d22d3357069a0c55e4ca024d15f628ac6c6c03db605a36b0dc753534f9713fbd1edeb479225336b0cf2a69b2f1538e49d0c68f81a3b8337f8296082f8e360669a4d0dbb68166afaba1e59a2e640a1fc9148632b3658e2bc7e52a2c7de8c9c69fc383af6c60dac39c211b87261f13111b6427bb7abb6ebb7ef51d05fccc5d3fface0382e20d7efdf5b5af4c5f9f3a8bfb5ac19ff9a55a32851f684fd3a73f1b3455f815f013772c114558287eac12b7c1ff8020bf22685b24be02527315febb64639bc4c6130c5144d81ebf057216cbd5e2cac6e0161dd8f83b20e647293225882a906cdc056dfc7668e3e73258338e26e6abd0721bfc3864a075bcf253a008036530742ea6e430db1868e38f1428721bfc394574e85574bc367e1df87518913a2ab43e631857e8c7be456b63fcf4814a54e8d006b671866d204e5c67060904e62caad3004fe10f5d8b271b53a94980e62cef23ac4ad1c6555a1b7f0d42a44e7efc356cc0a6606bc077ec911a5aceaa8fbfe6a8e66863207377ff63c3b643f067638bdf1e893b406af1c8c66f4a62e30f615c1bc7c299a24c731bfc0df02a1b3ffe19a44ea6e219082ad9c76df0d6da180fc136ee409390dbe007721bfc1903a9c51d8bc46ff0639bc46df073ae456de3ff54a06b6881367e181e056de38f3ed414d0448c3b9778b8a77a9410e0ae1aea31f5ac4375a847ada430880f21453aa8e6db4de3f3c8d1bf24d29bc00483cc287b907f36bedf551830609c5a736585a60a3fc618bfcf55c52d2c27530e4c773bb84e053afc9dcb59a4c7dfbde66a3ec6ef02865d0f1bb78061f7833fcc4b36fe1ce4acfcf84f5fb89d60e3d2e3df827056f7f84d9f85626920877cc732b1316771d8466f5abb6ddbb66ddbe6f91062bfbe15fa0bb88e7d81a7f0638c31c68f31ce0f7b8115c2f833fe5287dfe3307ebaf3d76dd217b7f7c9e477a3ceeb11a23f2d5318639f8df1e3e7306a630cfe38fd64135cadb50b7ea284e5a4511e90b5dc274ac498622c4f8a340f47a727462e259789e849115e482efd01ce6b958a6c9d46c148f2476e9c37c618bfdf1d663bd03c0d038ee341c64351a76780c22b68519477d05d578cc3a2b4f1f021868964600492fdc1088f1f8e4895eff06ad7a98797084e2b583952f275e0a806d9033e452e3dc0889a0082c9f583728268e8270692eb02832484a22401c5e5073db39d28092317225cd082f941b36c27720110302970c111030cbd889428c1a6db89624f7ca0194233846608cd109a2134436886d00ca1194233846608cd101c19886dbfc6b8a0ece32cf9d686ed436ec9b61fd6a16dc1d8c94fe64ba243d48e3bcf48e5ce3ece9a9bf4de877793402e066a1a29f49cd6f706e270ddf837829c55bf036dc49c155690d2665a16ac45dffc192152e769932baaad2136e732654f2ee62273d6fc962367c99f1f94962270310e8acb59f8a70d3c4e5bfe4c0b8a8d98107b7e969f0d675a5b7ea79d73b05def174c3c2672529111848e4f63a561d7f7696d0da82fb494d63829a594d64a6d37e3c4e6d7091d7f36b1fdd7c446e7479a6f139f52ecbd28148db4ba748f7368fbbcab39e4aabb4d3a873ce51fa3f4928853e6f341f7396339ce39698d324ea0e34f986f915f07355aa0e37ba76b1ca12ba5d469d8f3e9a76242c739a7a6b37633b118a7533a736c4f299533b1f9bd7dafb5de946a09cd554c5b6dad758b8d368f361aa5c9a7b51e3141b96d5b653cc2759526a573d66081f68f4e7dce39e79cd3e99cee74565aaba74f94d2165b27a594548a95e230b99ae9123de77cd9269df7e79ca6d3ddb66dabf408a7e484a2937a3db52675e8dbed524a7be85dc186b91cf3bd945297171899198f72b8cb9e472279b3cb54da225e28a53030c598e370ac5c6581576aeba535a078092e72db44514a6360ccc4c894c339775d96c2898ecf614a29788ba001cb3e7548fe0481a27f7c9f13e4d68cfe138c2fe3760739201f68ffb0c2a6efdc727941db4629a594524ab78d524a29a5944e3a299d75d64a29a5342aa1b5ae45e665ce19834e1718940d994a7154e8bab95c73158d6c3e3228460ca554069d2d77935e01b6bfef7263fc89af888da065baafc947e90f507cd5eab22d266fe736ef9c26af67ce2e8b8f71674480a7181ff63c12c9d3dda7a70a45027832e93927e8460ec5a1bc205572855f4a0ac617feb0c58b627c51115f9dacba3caf67c657278b2f17f855d0b698544a6957b425ed64f369279b2b1ba593c557378baf8ed66531413b2342c7a019aff8922a295779a318dc5ae291ce85935d9beb5342470c825287e4b91001dde3755e1028257b8c52c618638c3f48a178b7c79c258b606c6f4f780aca5c6db039e43a9b4ca6e496c546842db7a2a97ac275362c3c25933a1bad286f59f8bcb2d1e66a1eb9ca67ae8ee0ab0bded654499f2d6f6b035b0a914573453fe034045b1679a944bd169eb66d1badd2ea4b8e0234a923ad05e89685afeecb8d08d71b0285371295bbde19e7d1d6721bb00847f7e707b6e3c7bac48e763ad9e6922da59c451c882d7feee0ab0d3661d3057afcb02ee1538aecf81b6caee4bd3ad428d46330fc3075b381e1cd0e3798148a9f4b54484ea690602e54c41220243f41bc8af84c205cb14403400fec69cbd65c917670557c205c457c827821f9994b80762409edf8a12c62c787214192cb6de2cb2881f60f73cb410ddba4649f119e3ccecf73ce18e79c9f0bf49c36ba47f7e81edde3a45fb72040e6a6dbf4362e56d39d9f6c4569ceeba99d476dadb5d2d7546dafb9ea6437c3358c98f376fa5125bda56647eb8c5aa06f92af89ce94bed04ddbb2ab7533cab22d688ad540a2bead5bbd15d708346b2c0285dd2c0285dd2c0aed2dcec0e57437054f40459c6a8b4b0c0cd2cc9c47c35c9148a5128d44a7f769575115f7c916282594508254c9152739b09b7957e957b076b317964d4153ac0612d7d65ed7d6e62adeab2d18a264ec30b66af284c455f297b8923839897533a06d57f054bf6d7733201e77ebef05b3e9931406d9d105bac2a0dc8fba99ec66dd4c7646b2825bf761cb0ebb99ecaaa05edbeb4b42c75a6badaa201dff24a3f941091abc360d7c889cf8994862b15a2d66bba7343be79d776eb3f37a2c8d3bc707bae6d074fd1035bd1e3abf2b6ddd365b67690a1d5e19bbcddebbf5d86ed62ae6324ee5e06098ca791fc71034a51fad291c4a0351790712c79cb5d10fad6bc2dc866e5e4fa5291893568b35925c65db69ad35d4daaea06f51f2214adfa2bb59ed26c41542f7f4a05ceebc1e3a49240ee8f8a5e82db3646269617169697171892e2c2d2517af87beb8bcbcbcb4b09c5e5e4cfae5e5a5f442f25e5e5e6a66ec8a907d46886a6deb20cebd28773c3f9c69a4d0fa43a2ebc3cc4e545cc7d264cac2788b859baac4d82cb6bdbf3591c376297d9692c459fe1d12dfe98ec41bdb01c1cce62a4778edbd30be3b55dcc77c3e559666b1b0596c4dd8ef8e7447e6bd2ea5161cda2bb6edb6cb4777cb27734bf6ea1698dab6335ba25097a67a3cf25f3007a63b2067a1de7ea744eab8bc7dafe52c98b7ef69c0592d6fdfe4e32cfcf64d3467bdbc7d53cd5976db371dcd55cc9fde5dc7054fd96731751ea9f4ee3b5648bcb15f7af77c08890179240b52c7baa40bae6379f0947d7b7ad960db0e2805db5a1f2671c71ac51bfbd6484885f1605df3ede90533bf654efb2e1ffdac51b4d808f5f98679f9e276319af1a9cf864c5918abe7cfe8e1d8be3f59be70ee13189aa884a756a8ed973e1ba24761515c784117e66f9f434a4aefa59352548b459e44f0f667c797383b6c7f227d0a144a0e71996d4d557c1d57eacc0f9a4fa8d4ec17363d0a11d160000048007315002028100c08c562a14816e560b4eb1d14000d7290466e503897489320076218c5186288510419020031041965680a9b00b0e30920ead46a4fc1bd10d979d7a81b6111e9aa6f9276cb4de45906adcee10aea430bfe8e784f774cdc9bb1c3b33019c09bea1f0f9f72f6ae6aeea51bba295f0e84ba10fb0c8bfb61d01d94a79369ce89b0a60637c7e911827e9086884670cbdc13ff1c808e5de11fd6bc8eacf2e303fe70559e7063526cc3194b300f58f238327a06919bf4732d6c4ce80e4e0fa0f24a216b65ece2b6eb01b34a56f8899f8ed4eb4902d29a63a065b99b4ecd7b2bb22c26ec11c95e18500157a418b4d0b9d112739041d55c0f7b5053440bd2d562e2664be9aeb3a899e9e26e1591c6fc8d1fadd43d65627d8e6d81b44566aac8d1ae620a48d1071ee4eba5964c4c6b57ec3dc3f027be5a70c79c720abf7b1c2c74582dcdf088c95d10d96358500b2ee4f5c06400794a9760a36577b266fe5d9aa9bfa59f2d287c9d6eda5f46f80c25d294dc49ba7044db838d5c28480f9505841126695df130b40b36fd363f7313b048261081946aa4e7852887fcbac057fbe319ff9bbf8ae038214cb1e0e235a46f3876e95b101a554c59f2b8d603cd30148f17a4ebe9166be0a804a8e61b0879ea1c0330f9be94df0cdae58a01dd24a4fe2e4dfeb80e8c03bdf640271a51f46d9ff2157e241a0fc663d1249d896db0b909b8c6175d9bf616d6cb0b47cb341134f85f0aa72054bb9511d07fcbb111f682b80bf16e67a840134889a5d63ac2f1de9349e20634eb710edf1fc8dc28079bed2254f42bb037ee8cde755d2bbb5c912752c7ae4fe30d151c555f1bd0492fbab901e2358691c1451c902a65f728bc48624169e4bc9a0a85aea5afedeecd0bbf44d0af24a5de460441e1880a494e38911aa762ee81873b7fd5a0ec980d2df235035192cbb04bcc7bd880b6f82cca22f466edc78eea42b287e0a93339f0998d6b17933965e32e2208189feda0d61b0f1d46c40a49a528cc9521ae57f7dea2925e45f4a440cf298a082ab966a18d602d432b2dbd4e95b9830947fb458d2b2d0ac09b7ef222a1c28dd24883050541036db1c6dd0e351413b1825c4d1e14ac50f4d91cc916929e43e74f09c34c79e1a7635cbe07e5da3124c0e6c8a19802f119c6c2d0db40d0a36dc2b90a3ebb9b2fffdf0c649e57670c3ddf6edbf9baa8139a67a96efde84c77c22ec3bc6fef8fa85ffd994ed65287cccac5c3f2eb37cef97ed99bd8582831619d262a9dfaaa9fbe956a8a767f6b7ef56a95ca708ab61d9b5c77aa4ed18d4ddfc1125ee60a2cee4bdceac4d1e4c2b60929294108cc5d2ba48eeaf0e4238c47342b740df21d8df7351772836369dbfdc28a4e44132cb56929edc79446147eed57819c1e0897d92cdadf70c0b17c42f60338d64a8f085f4538656918f1539be89a20a2126a94a4f4c4dca48dfc44183278e63e4b00860184edefa7b983c1efcc11c20c526b831524814cf9d90d4260b288ec9bbcf311b9a3725502bf0fa54a51a1118a91fe5880d71532c748b97823b35333004b3d226851ab6caf3f56f41e1f5803f7d6105b882341a58c8180eff351cdfc76f36f686e91bb94071f26e8087e62fde841eabb85a53492efd8c38b1b080ea9c6881f8904fcedf328348435c12c26ec6640026651e07435494ad7d106b6913d36000bf25c83a16a526a8afd622b0ef5a4946579bc122065bd936b7b69e708a76fded6b661ae9a490407b67493cb9afb921be40648d57f1f4c151ee9e8e26a8cd20ef80cbeccb549dea5919cb51d1b6aa02d1ba0345398241205d3abc2f079eddf5f4f416f70169c350693083c252d443ba9fa80fb62a3338531fbf3092f8020fe263460af7add2f94352381c855771205668f195736ba844aeaae95b7419e3043c65c44a7cbd56a0e90df059b0c8c834b0fc20db8f00e8b8f75f698379b5df1ec65a813a1ddd18788b4e88db55c8cab2b76c15ad828ec983d862470171eef6d2af999da5bbd210b721379b7014d78a8172ef806bee95a999233eb6baf021b7bce3ce5ac50880ea0e59054595f48eb56fe28f604eb0b1e4de8bea42e9ff9c64dae4b7a00024d79d1d6970ac550877117367330a1df1e6203affdbd87f077f7aa6a4c38fa309b77ec23d2010cabc17350165a3dd45c7b8d00f86184474e37d8397d015f390f8a15a161598fa9c79e5b6f902e60d57c0d8f60819cae1abef6b304aad6737285205755cfabc63ef3eab44e4829495d66b792e1dafc4438526a91819012198a8c08c18b1ca6b66f03c69d82084932c8082c13862740bbb1a0348b5f0ffab93b2355638944cd6297433fee66b08408fb9a342aad83a70b77520648c18d688b8a6482013fb00fb95a060c60abca70190106874b0801255d74ba84139834f5c03ae8a543d9905cfa2fd6f00980feeffd8a41809f28e7ad26ba0ff28bd8513ae7cf457b8f57d0a8331024e5e1f82f6ffa2f53fa75eb187a062ff3224a6dc294dcab181040e6ad62271e009e2f8180590ee113b184cc5b9097cedafb16a0d04e3bb8aba4b8268d7be7d2be6a4c2aedf9fb1191c56f4b7c558238f4bdf97f1511ad5f076bf908653c84a646b3dfb7dd55bf65f35100d64f3cd5535ab4c6b7e1e78501e94f33cc24c0bed2f521bc593fb48cc3a08a479521a2b9f594c71e1875ad02aec5d04ee0bedbf3da233a3fbddff0fc1ef78e51fa6fa6b81c1c5348e20fe8d83d26c3109f43211619ba836b3da19fe1753e27279e74734e5bf022de85f77fbf948a0833f195dbd73ed902814d4eef8b2dac1b9d727d969cf6d6688d96a58f171baf51de716569101645bff42e707f4886728b2b42103bf97668e1b9361246e4b2b48bf4044bdadab58eae408ef756cc9ae76140df054b0c0774aa457c4eb4397e3fb907775689eea47c8d875edf337ce6759005d77a05addf1b24334dcb619dee6c451dc0d513b39491e2fa66369e3ff9fa3cc0f034c5568d39fbe24b87253d696093a553dda91fa6559abbfc866319ebea494a23d60d90e3a4c3f04f8adf555adeffa486aed2757e9246cd3249850069f9dcb980c895f6e9e71f2d68b9f775a7e02dd42acea0577bd4537687d58e10d7b6ff1aad61caecea8369afcf908922d6ca9c28793db8983600c2b2258845cf9cc9c10dc80617ea328a530ff61ebabb03f236a0f30804c379b46c2a28aeda70a9973e24a87d327add42ca5215eb7998d41f74af81d646d01f28f88948ea9df08320a267155ae2058d4a0394e4436643ca8e96ceb7a03d1d20fd0ddc461f169fca26b05ea6ea158e042c7a479cc03e1ca83f0daaab74d86908465ee4492aad09e3a7329d6726c54083621862fba0903bc97ac5cd4d899d82727c7d3a0cc845f36fe9c06e182d94582b7956127c86c49ea4d3468da05feff6541921fbe033003324a4dedcb024876e2040dfcb0d6b23c71d743d4761a35c48762f158ceec283a8756a4e7a3799870c0a1127380067ea4521b14497469e58d5aecca547ad9163b29e12b18b33248b0113c03c31083040ae9104325f928574e976822b3928de659b46c640bb638596e9c24ef0d7a445a636231682c77711e745a64e8b3b1568d12f5b51c2e231774d9a683c07f702fdfe381ca7eb3cf3089d0861032b4e3920cade81fa8ea3884864ff93c24aa57a58df384296deafa96ad4d6cd0644d94d6df0d6343a97133cfe63b8600b231523534b659baa5ad8092f24b8d3793f1b5b4909c6ad54ab2c73f807e9ce6965cd9d5271328c8e7c0e3c89eb6a0ef3fcd23f5b699e8c07f250b522a501aebe0fb2ccaeaf416b5165f057fda5c7f0e87679e0e9318e4e750142f42ee7acfbafae5e645f00437246013effde999bcb9271819083a2635c9a64dc542246d85b69f73567c991275debd7a888bd5f005040f28a928947aad8aedbe6b523c9a8a4e4f957c5d1f734bf857795e9ab3a66a98d11d54d470578b0af8be296c9ce49e77d1491cc24c720950d34df3cda03444c4e9b7fcfd362722610198a2fbb882af3798ce5f02873d6355b6f126eb1460d19da781d22f0aee0a72a627466e46781c1b1b2dfa76d4900e8df54eb859e799f1508c88bd427860fc6e94a68071a9dea94b15367cf7908674ea02803470f3d112cf409beb9ad5097a488f1a2a3e8ca83745048401e81c3832f4c5d467c8911f1f60155ea83ccb3bb8932195f182be668c93c1ada6f6b6687bde739de7528e80b1efa5ecf5a6d44b63ce5358119384a003172d21aea235299696971526376ea9ea97941b320dc56a26e240b8aa2a138c228fc2c5ddbbbe174f05a589854681e9dc57f51cfef743b6ffae078df97c69c1fa9e7ffc2bcdda5acd009efc65afc63057a6a7d3e47966166880a8c78ff9dffb490100bdd5ae8402001868708db3d16990f7f350a349a5ac3a5e16ceedfbe5df11a24ca65d04803fe33a3f4078f93ba4ba7952c5b67577268ec626e6c44d6efac38881343d6f78050f7e5c8ec4cc90f87fc9eb72083e04fcc8f75bf826df32c36cdec618a4e47e70ff781907e880437681132793e92cf3a56b45039e8f7ef15fff0f80a9591f7bd44b12e4dd6571a6f401b85576ad2ddfa492b8939b42d7051e61299a6bf0060210f44937a958d24644c6ebb4fc648abbca85b1d124a6f103a557597733b202fb2e4798e02ab97603d74540756bf2c820b0354afdba3a45a6a2b751c292bf7efd94972de934d5683778aeddd632313458ba9fdbdafe155fe8a7748c2b49052411fc95f2c8ce7919c48bcd2b2ae1d7538047bb912b45cbef2fc3988b976da5f20406ea912e1ed4c04ad5b470bae4c15707ed067dea1da92a18cb5c3511f4fd8b1c8ab434165e0cf102cc60fe696dcea4f7ce188328608fab61c23b71a7a3adcd62f75e89b3c0ae38abc469ba03310e71de8c5a96d4bf7fca5eca177b620d25089fce433c54460086b1e00985f95570976868ac44122524dde8212a29274d766a7cc78c2b82b1957dc15b4978c68865dfba9ee9c421ed8599046b06568ce25a25129cbcfe3cb4657793d4ec9f847778c3359011939e43dc8c44abf973f77aa0c9fb61abd2652246a2b5927873bb81dc96750bb526886080c6fe8799bb7c0d59a6db92fe5eb01066bd041b5dff1fcbb7a8e95c56f1cf3c6274091a30dac9d18e18fbf1bb619df6a6e886d4ae923875dd9206d39904cc82b8454380f2f372173b1c8b53ea3847a0712505fb46de88500d639aac0dea8150ad3839e351ee36f49678890fb41f0002f642e4d3262304699fc52710000211f09686b40397a620aa12f53938a4e27041eeec5f60ade6416c1d64bd1c1cf70e3a1e9541c680386fb30fd735e874e03d7e4615a9feeca5eed20f0f419c8c242e78b4eecb3cd872ffa4313a9e48878ef473604ec30a930ee4403cf4495100b573d3b115efe3dcbaf5d07e54cdbe5417547931969348c606a3a4811f8a59a3d1e44b938752af022f0910ce4e4347db32223f9d06675eb723a07b73dba905e3b16dee9f0acd83622a0d0539bae5e012413c2b08788302d58b6c0aaa32f1b1681da1cf629c38ed23346feca9e7e706dd50068792822777edb094c19c131ed621bf54620e16e4836e1cd7e7507228edc5e66c28ced37d186edcef1ea2657fcdc51f0761a21e053f8c9d37a9645ad2563d9bc3a62e47285f3de95dd6930827574d35e70f2e086668e212ad5b7f85b63387ea62cb79c73d47d2e8558ff7affdebc2831fd8d6cc69f30f214f7c662776401ba46f32379ca16ec550287998ae490e57f262618363b6479237f6d67462d361e87c04d17f66182fa8a09cc5d2661f4dda2c8b2c18e2c4f3315c5edc1ad029cd1dc46fe4a9d5c34ef3ef9a472ed27bd8e6f9d753c73a8e426cd6bbc71184ae12ff9f2150249ad443572dfc85031c35fa49794fbbc9ef518eb5f4ced129254bd051f605bc0e72c5cb204d5d2f3c55b88dac16c36fb588fb070585dd233b463de36ddf8265c0034aac653412b53fbca4aef8d433e106bb211e2ae19dd599a976f968c3681cd3fd58a00ce345d5a3c1a7fdb8b332eb816a44ff99ea47da0910c4cd10ac471fca6f2c2ff0f04db013e15815738d193142f6353b60489ef1c08711c4d4f46926337cca5bd27942d68159efc55eed31e93819ada225e8bc0bdcb28b6f9325359a0becfa1d56bdbf7bc48db9cc054a0efd03ed40945b8134a2af0eb6319c12bb39a83da3e666363e6e6ff3f5434c39bfa7087d3328881d7673ee988bc558289fe36392351d0ff702c94f3d705798f5a1ff5317691a5269a4c6ab40b3eec7d519da6e725f74f6c4d7d2d9ff189d6c7b21660c932f66e14a543de11b3830423583af10ec5ed0b1e0b79cb7df5b59df9a3b0571b5df49926a7603d86cafcf26b8834c86c513d1a369b6ce32ecc47046636c5507cef0f99789ebd36bdad72bda98a4508b91bd5f709558d57c0669a2e43082f4b2435f4b99de7f473a31678adfd1e813ff14cf80b07707ef5db97579b388cd60f9a58dec891d8a33bf1532938b3cb54d1fc24a35d33cb17725db11fa78de04020a379e76bbaf110b8e58c3032738a5c057ef71883b8ddb0ec82a1dda826ea762e61574ce53d8e157fa90d7ade4a60de1cce188309cedd550cfa84fa74aab3ee10c14b6f3eb7d50a6315e16ce339b0f2aa5644801c48a9564758438ad67942ab1a255685f4f340799d42690abc5451b8c387a6ca833b89844157c15e85d508a5c80a8cb200d7a9d830f48fb3dded7edb33400736eb9107e7e1cc690b3ee1e871d1b32e4cc69e6de71103ad6738855ff07b69c0145407f628186a51c3ccf9938afe6bd56efc93a9d3e0c7445f6ac1a78143cc7ed58c9a33f716e34bbe803918be3b5c0c952408cb0db7e5eb7e1f9c0ea80cf4eafa22139cd7cc3a1c260bec2b4a72ff3c165cca7847944abc5b0965eb903b41ebfc687f9003ff792965a18e02d79e07e040b30ff402bd24bf7286af767600c57e928bb379cc14a09d4f6624e5b96efa093996e2b6038b09bf3c8d7ee6c10d32c75226ea014049dd53da8bceacc8f30e94d28ca6035de9d2c1cacd36bd423e58f95c27cf3bead7e3d1ab1129ff2ccc2dc7f67e9620ee6251172b6f76cfb86e8dab5656fc1169b0a19c9bda8a3c53aada03d05cda8f4b0546bad1607de6e85ffe07bbfc11086c515f0e36e724d15fc6f4ed6b9c222458c538e3f9996009e4bbd9dfeb299067d846c2f62f66020c91595e06e180b6da1990e30721fc7de1c227ca9e649cb7a17b3fb2a49e7f4228a118623a71c9cde7342fad7e689604cbb83138903ac0a4e65454de2d9d41151cc08144f71ee96da3c4338f14c74765070057cb5672559ecc6c24033365d6a899b531ba22140952a97b74dfc35fdd0022bc8094277898d502cf56264d7088bea391afd293c587b14c4e356bfcf78485ce3494ad246355e07995549aff49b47d6ce9cd5a3986f60429550e927a79a31d15bf1b52512cbd477eca7621bc9a71e9246710a9557ca8c4fd79a545d79819fbdcf9ef6a66633eae02c0b2af4aa0653de00064ecee1883cc27aaaa0286ddc2e780870216ccc6c8ff40d1f28f9d3700d94966e779fe88722971811ce4ade4da2edfac898a486b0874ef7347d7e331e89a4123988cff4d323ade34455aa905803cb0ee6b2df05cda4dfcce2be317422e80dd819d6e9b0a8e94ac434d639f7b49078216945f6df8b28f2540e008e4ee68b12ea15f26f54f5a60e32c93b6c1a237991670f1b4fcd492760727642ca8daae0b31db1ece190140296b2c0c2cfa77cbdae9a1ac3a02f4503b1999b799ae9a1707877049d6291fda3f848593c67ad10b53863940d2aaaffcd4a1bba450c1e7eaae5b0ab0d94a5514dc11681758dadba9c10ef5a1f3c62ade31707d01606e7ff64bde50b80499db1fcdff5f29ab81e5361e6262f6c098d93335987d3727fc4b307347499392395214e9cfd4a0d27b568a17db43dba67a59c952942ef66386af0d10a8430f7823c84f8c34008d3669cb8540071e85711ae4b21a735719d1654b9788b0b7c81d353340c4bf06bd550a3c85d3951b01642afe4482554fb1b8d11264df68277a1fa5e26dfec175858c0839188f2b0d7458a866b6d2f4b4a2012e458d9570772d75d5085695c9ca76a2fc1bd5d84dd1ab600fd7f531c8412b5581504064a8292c6f2dbb95934faee0228395d203d1beb4e6186da4346228a2b3afaa8ffd5cbf106a714569c80f74ee2e442f7cb09bf643ea285be6cc36b7c798f376dbc4c96fa188e5fb3ed19870cd067729200efe8ab622a681e0a4957c02d24e10d82055dd6d0899bf958bd436f601e5dc3ec86f53e906b3e6271e1122a28b374761f0a25a661b3db35ae6b7786f32fb59972989b5f247faae71709127d2ce781083c7a0947a3f78d0068d7ff24a704fb94b9204ec0845d007c95c4558be372f1793f99ce43e47aa71e3bb14208313056a5d1295ff0be680283347b42e307f45ab0e4538a97e1e12de536d04649b7c1ed8b02edf95109b0c787efef2678b478a16d734a1d9aee5d75c43e25b811084ac187ed26b5c9a02f845bb308f84ff16b0d4805065f8afc9425be446ece71515be4de6b682442210efa9677ff8973720fc5e717aec5c06981e1e58840172d5743692b545f6cd61d75390b8e719baf501b1b5b6daef62225ca3ac5e2520060ee435bdf743f67607a2345d51af85b69a527ad4446a49e931a6de11d47cbe1a66816eb0e665a44299e7eb4a9823d73b66d43fbe0880f81f2e3af9b680cbc2cd6f300c6e40d36ca623b854ee669e3e91a5f5c6236b6efcce4345dc2cf347c7e34af2580bc21b3b3b5035bc743f9af531330546d71a5bea9eb1c924c1c45bc469fb69b2f1ba00d1eae2a800c76bbf7c87d9e86b9c749c6354b2e68db5e2d0cdae3d111b39103809decc245ce4d3b0b4420efb095564fde87965901b919f97bf2b76285cbe748809d68206f07222ff38cc99b41079c0d7e87076b1d15298900a5bc79a6cac73a611306cce42360ad35b8a6bcc06b3b694c6608ce1cea28d53e84a713887a535e3b9247c7dc7eb5d3e4b016183ede005a60fc62fa4d51cd51e13f2cb0ef1864e4a21e63afad17b5e5a136795b00580f79d1a5fefd5308e188f6ebe23851b51ac15ec687a7aeacf65f265e43fd58cfc6fd312804dca03e84541d3511e22686961a60be3688643f7d17ca40bf8dcb5285580c791426403d9f08a38ee2efde5470695a85791ae16a91de66ebf2eca448a71410bf3bf8c4624a2ee72cf8526991a6c4ddfa5973fad5b7a797fc95ba95a7a4b592b052ff2cd465445c3899003476e6449a40564dda34d756959960ccd7c7fb6932133548d76c6fb9878790cda9fb49230d03868b48b798eeb17fe1ef58f8dffa84aa1e0fcefe8fbebed4316781bc06493d812f6096d6c7f02c3621f62ecf87d7ffa4eb03a976aca2249bce0387226a04d722dd137dd8c4408c0e3d81c6898e44573d5b4a86dd43b1a59aa4d3e285147e88802fe7105d89fc9a0a486b1507b58d722cd98f23635a78cc14b4d035bd4e2414e9d785e6dc751b9b43a45fca4c238c122b7b80b08fc24459cd47b9e0d052b939e20d741e1853f02810f987d0a8d047ac76b0df89629f15b1f4d6b7cfe60778c90074579a3b6ee0555a2848176b00be406c8710ce8902148e26b9aeb168a7fc91a11ffe100e2cd9ad0a1ed18a843ea037f008ad7423df3e116843dee2f75d85d3ea29f935cf0bcac71bd1cb52c383c04b541ec4c1c96721cc4e4ee079e14a001e95c59ebb3d9c195354bedb3d46215e87afb367d5c6b8330aac29bb5281bfb59d3583a04cc205709795ecea1f80dafe66ed94e2c49c236efc12fa483f61c6c9c0be3fff2197c6c6e6b4f303c16802b53dfe3821e8e68e9dbe4b06274cf7a53a4abc0884e027196fb6e8a2a6c0b18034c3d314269967a028753388e2c3986c67e88c9a4841932b2d48885e20fe25f6c69fc42e5df7f73a67196842544efe7d6d97d228e8468fdbc37f36b17cc08a58ffe3497db05ac24b7f889228af085ca6092d244dcfca71d2b1bfb546e0a66b74188a974cd4d40f5068e3009c8297196ed83366e6b08ed336c6def9578b9b39aa6d91d73228af59df3f20697a9d9225451fba68de11df49a92ca219269efd29cabc9b5eb8a82f42fec14b9719dcaf4cbb07b0d156c15eecf8c81f158c0cbc31afb9b16d392ffff47b8dda06e598ea30add74b8b3d2fc78ab829534241307115cf663e11cb1950708ef9544177ff8d4ef12f3eadf81e3add26a15439499cc507e2bdc3ad99e97b84b36c16e6715c0ecef1b22c11a92936d393083857767826d6ca26b4b1fd8826b6c9a06f646df5047160939e6cfdcbe661e06992fb2344de9d2cc2d145e10208de99ea15bb115bffb0db62f058863cb281c5401ef1661b135eb828cbbed9a9c300e7fed62a5cafd7570a43e2018f9e9360e97c207c4eced3168c6063f33f8082c56fb939b3934ad5956eca0178d5c99fa429a0300b2fd0384eca2a001fb85b2395382960485f34d838f6a30a60b41444b18adefb903565a45674f811cf82eeee3ecb39e8f199b0b2c2c3bec1f570bc61d74298091aed58a8a7965f6435f31fb322d5808adedd50813481d84900364fedd7036dba89f1748cb846c888346e9790cffd8b61a915f6fd0a5e2b21f0e393f8d1ce125d29769943da9331b6c509d32a4a6f78667a83fe3da963e16c904209772acfb3152749f90438bd38a19b43c1103ce7631d41546d4f422df0c22e8ed6fc55df695c2a2065d9f4f84a9004d94e20df304f448208d0319402b0b75f56179a2004a5636055859edb22b7d463ea82fef683fc4a07233b451d5ac85bfcad80987a82f752a9542ad648317ec01dfb7029cd5049417b86212503f27e8f7adb82477f3e4afeea294e84526550743e8597aa17578e215bd59a7885d76ac1897438e4185681f999a8c891bad805a46590f509f90ca4e9410e0e21c2a3f6ff2e960f42d0470dcd502059183e13128905615b14156addaaee57d4472818a68bd8b11616565ea1228cd9a39d12687fbc3c0d5e655368b00f27b91231b069ce1c0442d8b711de355254ec22e19091201d6b899d220e890fb75e402fe8d49e3fb09c5a5ec648c80378bb893ed198d16a201fec3b2b5473941657521ef65f3ab8bfb44d99c0ec15a6eb9f6a92fb3020afb8b8b2b5da32afb8a68fc0b87109e8f5399d96dce8642e2d2bf2084f8e9c890430a79dc628a8fbe340a31f44ece59a4b47063fd3603eabc6b1efdb5000c6e2d442c0f3477823fe2a11d7da89eb510757dbf4d012d24bae88d5b3b4f1e09f070c13ffed90c35d61641d403a2b2d4b90cdcf4a3fe76758ecca3377fac8d9982909c5b3f1da031c0d39632bcdc6f912c035b963cd1fb417ffdd6303448a4ee8ad2e750b87a75110eb9044f710149fe0a945e2395b9594850e8be6b84e390044a2ab2205804c46c060aa6c6af01b514df56e12895f64345b30514c92104c80b723f9d4fd7e924abb6ede401ce4340e0f2ba276f94bb24af13d6416431124c0f6fd282503609f804d2a5f268c33483d5d39690158496837d55f1a9f35b056dd75919dadc03e65486f1d7ebe3443e9a2882d63f8752485b02ab4f8b6c31b9368a403400e8d903ab2b0702c37225b6fb7d229089100cd0ba89017524c7359733b0e5fbb7892e2a5e53b5e43bae145db23cf7dd7979a3a1b8bfcb7834e674bed50e2b45561497c4b1043f230299e52f032a1c698447ca2b025074fa99fa55c256324d456810f82c88c6e71ac58b6de14107c51f6c4c91aa0dd7a4af15b753f258ab634718b1d620942ac3af7a8ad4bcba46b99b5eacd0a8ce0ff873c239dc12b17c38c889bf3e6c8096e9ec6e57095464f6aa0cac8bfa55c6112f84b70d42411bbc8457dd9ff7c129b66efe44854fe99e012017807201fc5f9eddd3d51b2546410b3a00c93450566d1b64445b10646b1acbe4080d24a69906e823d210c6e383cad9988cb16908b7bdc455e071a74e10aa45fe935e4a7c8385061fce51c638f43bc1f4fbfb0a1142ad29ed25174e8a1a459c7cceaba5dd2ef5633b5bb903809a8411ccd08368ab7968057c23d2feed64c7deddb410dabb103eaea116a7a21b02da2b8f93a323d4bc2204a04a50d46f1b16d583cfad11948a51d0013b88af21d232cbcf91af6af62d76b4531f378621bce1c4b1e12eeacfe4c258ed509216b56849985815ae590652da61b6241592db43ca56191e468e84c4adc2d1c0825d3e3543f7e132ce4b71590ff14010d785304f1173084457f5e0edf7424d715eebe9b7b688caa1591d196ed3c8ba511142d44363a3e3b1ae663374c59964ab6c335763116f6ad0b2304eeef01c1ef76817e323491bb3f240b92f39d9a3b94099f11029a8b067d6b31a350b4c6a24880bac21c711013099b39cb74c9dbe330dc2d1854cce2d57436cee3fb1b595ef4d94402a5075ca09822129f753bd2023fe2cd7e9f22e22bc93328bc36fcd1962d7c4817c37fd8ed34869ad281c4e198c4a28ffef41a4be41d7172729fa81f229c709abb0415af2a81ae71048e934fc58b12e10c7fc97d1f48f46486f1ff473826272368325405e4211864cc570ceef80f3cc865a690e6ccc16ae6fd1598222b6f5f99bdacfbaa1a8b900078ebbd74bf47910dcccac56a934a9c6a70bc90ae606709f4dd027571fa7a9b79007aeaf8fcce97c9b7cb91bf898ef7ab054efd25f88792652ecd2e668fa61127ece4861a3e4fc8ba36c95056a1fa334e8f56da65bd959825b9daeede984cf7559263b8d0f5470c211f09644ea10e38b6c332f950cf0e2bcdcf9fd43c8624adbb9a8e330af58a668c8e3644d8a6db3e633394d411a1390ffa48cab53027ffe178f20d1a11f4652cae2ae72ce7d9f9ae26d209cab88a360e33ed691e80949b28da20663b79f5fdf8c505b37b1c539ae3983da62d8fcad5c84cf0c23c2c384cf507b26f937103ae17b641af08b458ddb65832deb037b421232a2a4510ca1c08e6c280ee78386019d51928c1d325ceef327b3001d5a0f9fa9518c404a9454de3aad08dd39507b09ec85c630ecc180a371e0ffc6607fdb80b15e33674e18c6f4603445e3ee7dd9209f90ee630b4a31681fb8f448b47092a5d3893936557e68034b65c82a3d6b4b7f5aacad3e556e6c21b2c0e3280ce1e18a22dd6012a96bbe7e6ea27bcf5bd60f11031ee4353729466825e5202a18144db71e5e12cdbde5728fd86a861a5627ab73bb70ac11b90cb5e0f713ef7e65529d7318f91900fe0d1ca23a9ea47616f3262d14aa9856cf92c9ea06ca98fffdc6ec90716e975c6d38b9eb07070cfbdf98698b4aa97862665c2e9eeffda40c85b1c0936a68e85d77be707c0c21ac51cd3a3d2dc1ba88a908423014a73d41929f25cd0a441ca8aa00ec404eb3eb95621135cb1b45989de1bc16a87517a49fb7077e80c2ac2823baca99994f6701ac086a65445164c840e0d17d17aa47b69141010152e6b1485931160619ce146e11d76cc731a37778e03d8d7c3772b4ab964348dcc3832f895e79560de06dce2c5a6e7ba81c463952fffcdb491a76f7ced2330779f4273a9390aa34d0b73b336e3a752b518c834be26d3f94d13d0e585a81ef094034e1e08fdb739fdc94fe322abacc0daf2cc10cbdcc5999d3ab0fbe8ef149ba719ea876cf8e05ed5e9f682dc1247854643a711f7fa6866b94a49dd38b49804a79f4043e251b06e39193c92eba5b6306962844bfcf63f68dc4aeea0b3e754d11f7fec77757c3fab3ee495b6eee12864e05a1465e86275cea94d00de3fd725066d06568714516d7613b07321495af3bb793ddf9ca0d589d4c1a9c874b8c22da3516672ca7b1f089658df37855bada1ad1ed74a3628dab16af5899b371a8146a10abe079f7e18062fa142196100abbc69ccf51b633e576e78cba8144ed23823def94b9975549c74288afb74ac68cff05d5f84c047bb71b970d9e87b868504d34a223dc03509fa64153cacaa1073269730fc534cff8f8ee0362134b3955c82169624fa7c94f16b1d89996b4c4b1fb14300ddba720a57cc19718ff89a388dbf3457283dc5edacdf30adcc9aafb73b48ba597a5de3ba27c815678dd8db4baccd4ea480a70e651d864c03466f0bac1d65275406c44848d0d855904cd4b808b873565c28571c3b7bfccdd13a87919f75722f2384b8dae6f52366286a52ff33831e5ee282d4d72a1230e8475a61eb4035609e78de4dd58c8d337b3a840a0de95bdd7c58d5a45c43fd018512a702bb991ca0a24641af3c88951eae006871ed721c9ef57d77b5ca360a379e5419bae1354a14755dc9d665aed99b11e74ecd5aa793cce7934d9312c36581e86634289925bf5e245f9a68b04990b2b0738be99d79ae51cc08d0d48251990b82405fede79e7672b918145570514e8a3b928404496791e81c13566c6c49e9eb7a131d04dd1018ece041efa09205eac0f8f5e0394524d9784d033a82cc1da4f16162274571935ac18ecd70316290a418f311d6e022ca39fb720b943751faadff411e6875ba93d2c903a880573a10289c4d9b2538ab37485e4f0a4ff059624fad0aaf8acfde43c43c150ea27faa8d8d54729b46a61f387d10d62cfbfe0877e7f61d59b3f5c9a6fadd8e08e197ba9fdbb2c4709aa1266af152aedaa9c7e093f547b57f613ccb417118b1647fd67300910ba3d33cdc82b80e7aca6497dd7ac91be9bad6de4a23ddb7279832561998439a6aea6ed5836be440e0dd05e8b94adae50929c895ec224e2bec20692077d654ef3f4d0d4c0c09645ba12328348ee486321869cb2b887ea2135a710662b3e7679a7cebf9116f963603bb14c06c558c889479e0259f2c71ef8def1bd17cb869881b1f490d67da45cff2bb4402b0d1b378c21641a85888c5642a36558efe145e92e01fc9946cfc37f61fbcccc297b6c43694f5a71013bf0d1f83278fea0ccdad2722ac6955beb0fe0bfc80b227c08b0b571ed8cc7acbb83e15870d531a7be33437f63049b7a8001326959b046b7b89520d710b62dea0bdb27bc667b974d2e6c0387a6aff8ef06727ac1a56124f5c0b3f44e6ff789dfe5a39f8712964379a41e1f72a723112d6dc69faf32860d3fc8b5a051fbf98509a2f2c417dbc8b03e9c17502a37a2bd4bd04a6ff9e8ce85fb48271e381d0059dfb4a15e25bb2e594c8ba562769a2acdf98b5f28a0f2cf947dacd7e1d2c2c93a6f431abf6ad4fd5f4f29aeb0a857eb23b9fe0ece64199fee34766a902c329a5c38d8c2bb1645f73bc93d864aa044823d59a7baca97d6d81dbe394b03962ee19f28f70bd2ca451d1f35aaa06d9ccd52f37fe1f6802d639cd3564bb4bb362cd517a95d644ff2a067c49ae3dd35030dcada3edf98c169f8f0cd4a45e2c030ce9dd4a41326381f0fb3264993efc3ca19f5fbf924b8715b86ed5183c3dfec841ee34c381bc39e6be587c74015fa1f91ad0373285c774766c5cc92f921263b3678a8c00c865153b3b60705a4bcb49ed53786e0ac0a6e7a377a3750b7e3dfb75fbf85d45196296db26948b5921617596e58edb6737173f75933f1a2a11177b7e0c7a27716c96c7ea6d38ad5829844b45897defafca5a6cc59c513fa9752d284754111b06cba4cfdeff60d5495b5dae0ac79618db8e5e8754c4844145b07cb5be4d536124f76799b19589909e722196e1966e1dc11d74ff3e60894d0ea5bd25989e7edaa555004ea93aac79b47cbef3ae0a868f29b6af2cc801ca9b91147dc2ee4eebffbdca48dbb552c109074d3517493d7cb43c3b48033f0d899515959977cec58b3be70c28c3138672fda06a25609b106f5c1aebc0dd404976f51a0b5ff690e341855aa39ce9c3c9fcba748636a8a6edc8fc6a6f546a26449ba02f573b72bd0343236c64971a867e30b502b6ebaa1770c6cc515436503a4d87b4c81fd098925ed8bfbd3f29160066c247c7e0d88d4aea5fbe7e74f7fed5f7225980b9344bd3b834bda8edbb7d99c93ab8cadd7283c79954da69cb44c0345b10ba9770dd8cad740593233a40b1a869c3de4dc454a5aa2919696e9cf94ee35a08e5eccc79c1496f3f11d16873cd822c2b3de198427e9555008fa8d1ed36dd640f3fadd963f3c190c4fb7581e31734533ee88143d8069faf930fe5470e3b60cd1488a56968c3da12ce18999123bf7831eea4af817d60a91b83b109b6a6529c0d6a80e66b7c5ccea55e78d89d9196fec77c7d3fd73e6c3856e8a24cb69c74342f169f51816d571e0945b36b9eae4663a74b175e73e0c14ce336995c52cdd406286d7d00fab8c191a29183090d54d21f9635b41b11a759d67eacf442a00f9a4faf943cdc33493a588849962abca4feaedf9d1a5083a94b854392a7c5df53a767b854583a21058d0157186750490feffd49b1606e6d4cc5c13349d0ddcd0c5ae9cf2f46d54a3ce41f6ee33e2cb0e774e86d37933ab1258430d46398993fbfe94e537d0098d4d4728960958aa3386a112b632f4830279b82b60264b9bbaadd6bfe5dc3a2b0eea4d914c124ecee8d5d5b9664c6ec9ddee077db9bb5a59d1760ec900a6de3f4889136426e3affcb838dd503fac072a026a5362ea5b7d8177aeec41bc5b9e226e6e3e10c4790c5deb80458be8468ec5734ce1da09cc72dc830d950954ddbf2d17d44b2fcca514c3a781e73cfe401c823f985d2a007a5c267389b2d070747107b20cf8f4f0632f212eb4f16336d507f62c201237f1b7962e3090f818b356dfdd01717e528badfe642b67a907edd47e80c888a63cc14624d0851298b03b199148900d00ec583e34dad105fb4094f3aab7f17f5c4c7b2fa401e6be153499e2b39bc8d8ce0feeab413b4bafcf39df0197b7b1c1447e320ba5c07d7de66297febb52dd63168cf9d853379c8e9ed8fe09def45f59c6f45bbb748b043c15eff14c4d6f48ae0b95a3e6ea8654ce7e2d13efccb741f6a28fd7fb36a9a61d8cffe6fd2a6acccec1c886e62625d4b75e7acc64238225eeeb8c3ce1271450782a59da15b9dc7ef244273a5a25e08077ff8fcbbafdfcab3697900148857de84997a9b846827d3d05b700c6bc7c7724055f4695a037dcfeb8e0e1b25afa920022357df1d399e2fa7ee605d28feadd3ecc66676eb56751ffab642c5eeaa40eef00ea760c7ead962be9f152afa6964785ed5e53a3945505297cdd7266d73f23cb18cc1dcc7cecedee1a1331d7b2c9dfeaab2cabed47fa4569f92001ea89d289d3f71b25aab9b793e4feed6251a72bd623495899e567f6ba10936d1b58a09cc7b8ea8f2801a620a4fa4b626d86b2d7e3c74bb07dca418aa7ffbd68b6e6582760c00112441bec497757e4b13413cb3869b0492a2673ba1deb29db4c2d59463ed32f65120006ddfbf02dbe545e5867abc8a60a11699991a0745ce815175ae124e90f326656991106f2f4718284066e2497778a3263a411e0e3df6c927fdfcd4b70d1fd6f2dfd312f87660fd52ae5bd0a03dcdfba281dc86db44dfef46949d55f7fe278f1cbfc59666eafe6431e4197d238a1e6f93fb3a7bbb04a52f99d062dffc4140c479960409cc9f6755b1ce9d443882719d84f12a60c1bbe3c57249b1655a2f504d0df618c6b45404e8cf17a80a1e7341727d8ac134719ea76c4261e03870bb49e1e7b22a4a91921982861839726628a9c2419cf9478f05a5766eb9d0a29bbf97242941787f69e5e91baf89c63a8e8cb071ab8104b8c4ed29b0f19c3fb07439819d1a515244240cfb07e269a1d1b84328b791727c68682a18ae7f5c44df990fabbbac151dc7d82db4ac545425913a5e911106356306d03358bc71e5553d252d8b0b0e17eba7ac90111ce11f28e532bdf203db2c5333594a47471ad669dd73da526931cd3ed118b2e1f2019060dcb05b1b444c0757f7eace65e266d56d06367f602fa2dc5c6b072c52ea24fb3101b9ff259cb6889f7e12aa3144911d14417e086724ea7a46f7acebb6a40f862bd7645ae0a15b34342c78fe93f8f3441c9570764ea1faaca90984d972f034737888b98cdf56ecfd0be5a4b0b5b3c45a160248865d85980a1ccdd8fa230a41121db1f8d25416b13dbbc23668898e5a12a66550494e431daa173362962366d276b397298bd366799852e9c91d9f89b4216d3caeef0783a3bb9f5d05435757e4cf6e0308b90ac3bf4f230bcf9f71b1326bc68383733c3921d4e49f5460e2c477699b9afa4c90d40110e4c872fa78dea557a55860b53c0114c243333a88b6f186e461253727a7cb37f5a7066009b99983d071f757b03d3b12625571f8a0339fb5af030ca3a5c9a31931ee393f2590ae66741e93a952e703a0656997563c539ab0a89336ddad951f7ef2a2ec29b978218ae19d7673dc37042fb4cf1cc573b91f99daa6ef141daf9245c4c8ee8871736a87044d75d61a6097740cb8c98c317323b73529756d427f797f2f4e9897a43f35b7c442ad0c31cda368939b6de27e7b4557c6a3132cb30d66ee345356549800c0dacb305828e4f8edfaeff32a960760fe8d03bcec2d14bf511229284954b71a3202c9db8628a4afb819ef6c977a399e82c6cd32a9e7cf1c8017f48527c24162582b79bac004837e668eb9884853ec819c4c0c04cf26675de0df3f334ac794ee1524e664b72236eecf290832c5138acc953da0903a8aabf9f24ad01eef9e33da5e2b080e2e5f6325baed5e050e6854beee1201a1572a90c3834055c8e805755ddbe98770b91791f6e5b5ae26f2ab74fe8c4b1a269123216a7b4f3625e794f523884e04162e91709e674809ed95225288f8e18c27521c5093d3be4f06a3deae70a1061dd02f0f14cb7ea816473158a282bfe895e7e65eed8c12542fbff3fa890ac8be3eeac4b416d84e0460ee144695270afc16675d61eed887203b300a250353a7994a885b2209e62502739c67e5931523a2fbeb506f9f95cdc0dbf691a23d7d63703bd93e47244c7c8cad2ef4684a19660036b27ad2e6d66edd21a77db1e10dea5714f19dbc1cf8438e90b8aa1788923daafe5f55d3916cede3bd1185d792b02aac28fcf78909544728e99a37c544667c51b7c191e5b6aa6d128e5527154bcc97221baa8071089b4d1d5ea4a8cce75c668b8cb3b5fb1b62622d6e4a38e0caa211447ee07d9852c6a165fd1523289fd734968e7dc49789c8a5e84538555ea38a6a3abb41b0d9433318c387d386c3be0d04ddc66bdb1499c722e8b01187a40ec0a615e4fd692f985a590c7fda0537f905fae6a33bae253f41f2ce11e7c02fe7df85c025bfc742ed0a48b9e9e4b2119c8131828ee419bb31a67cecf3e9f3f2a91160a16caa6fea02740bea39e286db039b12ef17780f7509b5268db4fc8b5bea3c3c0777eda3ad3bacd153dcfaf59f7fa120a4e0ff6afc7fa94f84630113d05b3d5d30d148cba3fa2b92a70820879611cbde02ae9fd5f326d30b007796774a67b04f15cfb9508148bc02ae404155eb4b15561f0e85bf8cf5ff262fa90f8c8c2b083d516f341c422fb9325f0df6cf0b31946473fd91acf252e7088dc2563ea08d5fca42e6718b89c59fbf6000c3dc9f82ff824a2acf3b56a72ffb6b345bec4af58c54b1603da4450bcd0b4f747d942bf9b5ac3024517c53658f72282cd93dc7dc79fa036610ecd5a2bc2cc2d141ba356006f72b7e2ee8f71b08131511ee85edaa201f3357a9db380a11a62522303866af0ce9043d8b00f933ade00f3e8e9a61176a3906551199bcd40bd3379c7f606e2691838f909a6041d6ece9bfe575a0f14433dce468482d25b993e800aed9e0ac14cc80c6c0b9a64d3e0c9cd2427356980d32bc9471053a4f4a8483e53166e82ceca018243df62be19d0a81e9cbc132615b9eb75dc3478c7264f4ade5004a356a11c62603978a2fca16a1b5622333ed1a716c26b5239da7885f645ddcf1f365c0094cef297564893004729437233a7f781f3ca31053f369cf8460af6538f07b89bf5a52d1c8d2532e330525b8f0fceff7fe6ec85b5fce72757ec9202d6db36af3528f72a45361eda4d2e15502a6c3708c5713e95e6cba7794d2857d035c01967808932839c67213f514914762a592dd247f1c66699b9dbfa1d89cb8707e0bbd9c430799f3c1ecda4738de9831885dd9e6b95ae68787c7f84528a1b6dd32914c1bc1da210bf246758f9e392a7504752a90ddeac1310279ddfc8426e44eb6afb1e574e684d4aae02dd45dfc77de894e043e7720ae910046c7e3f7d91717b44fb3396440d2f88682b3d05682b4aece5e10951127da7c1382fdbba2fd8a2914b5f58a80fcc1ad882c4d608862847502eadb0de3ef2233d6111c91ccd4cb8bb22dd8fd491ff6d33c7cd7892f771cd832507c076572ee3921da4bcbf30a022a13a861d7171d0eb42fab8d5fcd6595d4f8682d43c566ad8ec439c3b1a5e7a048848d3b3f75c411d2564326bb42b90ae981f6de448410ac74a2334ad6708ef1bae0bf545ba8200952c90b7c80159a0c05fb4f2d6934fe89e959d8d828f61d83539b2d22d381022e937cb1dea19e39e36ab8384dd81eba988f939dc44e7a8ef15313902573c63c8caf14103b88b97549af438728863f41ad01cc54460f3ff97232805b4c7fe67adc74969dcae26ea9e729dcef11a16ec04dc27a0f4a4a069fe2d3de12d2efa4a393fad6ec63f2c4b4a6988a4f650231c1ea87493ad7ee5a490286b800f2a2d414f35b3362fbdb2f461db8492a207beb1ba90ce494590f48710dfe5c0950bc606b6d60867702bbe2c0fef75655cb4b6dda5a3ca9d73544d2b0644d0fb7af24c0b9a12a8cbe36fbf8e3cac99431333770233d29ac169258aa76efa3c980eebb0652c60db126471af888c4a3068c3bad874c95833de74601e7be830c004ad09a2664d9cfa98fa5ae74736530f2707e1f2b217cf1a6434c2b471095d1c753a4800390857e165a4dd16b2d9790d0b82d7d8d8534595229ceb435955a41ac38b3ef77397ed7a09b0cdb38ced310d448583257720d1965009d6a775ab92e25b6cffe5671a249e358b81c4cf46a7c8e472fe368eb2c06dd0d8a7badab3788980f5adcdf6a3710d7791f4a79a6f9755cf0f0c47c898f381e8471371e6030c341467122c69f7f568f2219ab33534949ad1d14f16affd985dd9f5421f3bf4195116be594f2f0db08b929e0e9db7b472443e5e48d59c3f31e130d17f3ef02b48c4d95356eaad838c6bc858ba0412a974fd4df71b578a6af360f26cac7020d1992a08d5f1f78b3f9e2b51ff22575b555d1507d5a6d34fc1157c7d3316ba2477ab707631c5e188b6b5824b561405e21c4bf51cc6383bf1f3f361dd628c035e6130da504e1961f311b7fcde18a81673e3d98dd654023dd127b25db7dcf3e8159559ae427e8b8e4bdf4cdcba0d976b367ccfb721bd2aac85a196d966e6b5b2d535bcf7b7450ade6d5dd6e8b048a0eb45c469c4f7de46289d8aacc31c99dbcb699d079301143ee59945b501eae8e2244ddaabbccacf57557ca80258da77f3e6bc1ec1e4d035661f36b2afd510c1b3d681df5a490c7a5259c8181b0d3e5725f43d234f0913b39b55da897f5a92e30c7d0f4a3127e68fdb0460deb0b7d06f705626ee4fc89659fd89ecc50d1674458a39ca81e38e3ae658c78e71e4b8030e39921d3e82b3ca9c2ee85f64b4962303975fc44223449b2b0dc67a3e170b9ca56ca45498f45ec1290f1601819b5edf62aaaf2d26a4ab97e8460901d6d6b432e9b3175febf9059b967bd2408cfbe6b9f4522beed109b6847f4705519777cdcbe801383d1126b70e75dd74d8440e71ae12be2db718120d11d555d0c9abbad2e2f3e8243b4f266c091698a4f4dc14bc656c895b82512b7f01af1fc799e2c6f17cbe855b14a00d154172f6bae19d0e3817d5a138e5ff663dbfc40590e7a1ea2165addb434a241da9ad961904ac881905f4b73ff745a4aa2b61c3a5bf8f1ff0439e227698b1d6c4002782a3fee77a815460bc7e6d5a9a96b925582182a7e41292ab0303af66e26009f12633aa72b90993ef0e2d07f64c8b198d48395518f4c34186c03c044a2314f5f84d4a235110bc53b281ad948e9859ffdf4a934aa7f0d6e23bda342a472badd20e3b0dca283ff33d0f2f3f970ba414250fc1b642c72e60828e0ab654b558aff761e2d084c7e42f0258b184f51ba957d6e98775e8bfb8f8b0c401d22da712a53fd5e38fd1807496cad6f0b2572809d840c7e2cd00e78cc798d71fb7f2a487729940ff8e918705784452454520d11c79c312de29d146e03812620279694540c2d81ca2b025adea7d8dd41089a2b84e2b8cb8e70f8721e167e4292069d7f2a60d0ee1fad91ae458841490561c95700fe8ff68950204507fb5162ddc966dc68ef37732216bdd01539338528eec511ddb62d9e0c2efc34f948cd41d459446a0aaea70150006e0eb96948f28229c8bab6fd5ff400c65f41cf193c55f9f9bb4ce4003050fd3a0407ef64bfe4849a4e8cc4e9a1c091086d5960df734d1fe9a12f9a7efdfaf918b9f2a2aacab6080f9c91ce8d0297a589cef64d6c4d486028196ed022001b6371631b3febf2898c04dc116280d405d40dc9551fd7f2f88009c035631bc7e0801f851b821db0ba2270e44316188a37e301be0b6730e8295246f89719432c4a80cad0eefb6d1929047218a1059e96de56d17dbe297f440dff43c8f05b88bd277f0448bb3ec724bfca3755c3521dadc0c3a76a8f3c75cb1895d7a7bb0f242fc1a1a202d119e94231e9f1e13e5b33757a241ac7f5ae9e34159c24d1f6c6c71eeaa396fa3fcbd257f4c1f90ba0b91d964b5f04673037e32ceeca694c1a8295bd7557b94f7496798a2b6e82a8d1c49a2593eba043619a74423ea34e08fed0cbc1f69ac5be79e0203cde9981cdbfec4e200e89e6a799d6645aa3692e2b9652d3fae0a3e81d2c4a7d17fd5ac9a172a57582751b080fe31a75b91af4b1d2abecf5a19e768472d73240a331ede7d6f15d2d7311f607a0016eaf5f92cd23371e22a552ef33f5bef05de767938067b1e2ebceca711943c1ec8a52154a199cac7c654382af4e80b1cbd2cc7146dfadfd973a502e7fbcb8400f9e7d4f3d1c9fbda7419860f7e9200313d52fe1b5ff7d53c40f46284ec23a09db8121200a612ad18967bbfc3d73fe0f5f64c54643f970df682c335a54ae10784d3035a6fa27d5c30145a4d07eabf72d4a3f6e798c0cb5e8ee442992e861768ca2eee8d950c28abb7e5e89833d77d5a94191d5a1d2079b3fefe1cdeb71f780cc487d7ba8cfb453ec78c5128b15129ce8b612fe14af47adf7e0be94d9b6cb9b79429c914a5070f08a7072eb8dc1a32df8463837cbf336a5176442dca7a3b28403a22ede7ca154dfa807e40031acc66b0ef3f23fd9dec765a8ca145e9210dbe91ae0ac23a7b0da82db66845047714613e6b1d053e5c51edcc9f218f5710257aa04323fee7606144594d96d6431a34dbd190835eedb5378d3ceef6d91314993e506d931aa53e297d8d52b9a3925faf0c79a4ac4044444040ec31501d868a10410945942821fa21d3b5ef725c1af86f98ea0bb77e35c1d8af0e0321f367a8ea81be7cf9c8d77cf1d67a3f6789b6431af185588146b7da12db4ad528576a810375ea56e298a02f9979bcaaf637f0784d1e2f9503b4df9e47fb4de399aeead07edddefd446ae6f31b9c5fc11a5cda68517e8fa9f32f079b82b10c1572242061b247e7789f04225208913fca1f3acef2eea9a3ce953a2c744d843582eddef4a384d9973694d23b07a5d142275950f1603d943fa1ecd1a2144f602b4b1e4a2e0dfe2343699003c10a963a2857cea8555653899bafcdd0d3a20d0984036ba566a5ee800879bc512a95baf4dea8243653b27c1b9e6185143dd1c434838978eedc83dd73dc3783dc570dc4b1c2f237c7ce1d779d77210da5ef3801b6f93b0673f48581a9f840a50634f896c2cdabc1547ca0e2c39ddf75a6efbef4f561287df7a81f4696c1b44a2fffdbc57935baa7dfd13047794b5daac1bbee1b04553598060d54c1d01caa6a30b7a83d18aaeaf3e54055fd796b4803be112b59b622324b597cf818c2c794294c5f7b19dc7976f06b09a0bf343cc747be3c54f530c506fa9cc53f33c4ca8f2bc35187e68d483065ca122500aa2155fe434325105262c4f27b3c47c5a1ca01f4fd79de439f231cf2b8872af6f1a7a18ac31e361eaf5aaffd7ca688431b51899d6d058868f643ec4f986d0bad9599640c345f5ca12563c81f4b97ab5c415e0e4791e60adb922bb4206380628b3edf31389a98afd63d6de188c0feadc2c31dd9c8b9e7155be534da3e7927061a75a3b75f15ecd7c6cc3c04a41f3cdfdf24432e073bddf403ab5249d159fc6c6589db21f3ebe460471da49ecd78dc91c7eda7c1124390566ac1734706f15072dbb9411a6edc6028ef3468ef3f27cbefb417ba6bb841196ff05072b577a971f272203f572ba7f1c673a6e016418723d006fbd70a234d202bdf86b595c888a7dc1868b49c259de52ce9605f8e9fc8880004d3c07e5150c321e8c5de8c1d1e98fd6b65cbcc3403924e8401dcfec4d7284f8b5d7fab3ba25cc146c6e86f118765a890427d097ab79361e9ce392703660d55f4fbebfd61e9108f0f0f1e1f1e2ce350064747474fa5147bdad552ba74dfb12161a67db1458322c28eada9f3618fa4279802c611d3a75dfdeaa7e1d5dacf65f3fd3ddce13fc3ca346cf9d67ef66d8bb7ad4e0bceea249630374b2a94054b8b2c65b73ba55a0ba9a6ca71a552673261612727d4a8a37d6a93bd253d718bd3d4dded799ee749cfe3928d77e2d3e9748aa1459a7b02b1b0a3086261c739bdadb5d64a6bd974ea1086bd16cdb744f13ca94204f00d7f77a79853a954ca84d2c1f9558a65aaccf881db9d4c286f86e4e64e49eed3f8813b1b1c57f765f4b9dd918bcbcbcbcb0b0c4c4c8c8c8c378312bd30814bec0b282dce9868c02bacaabbdbb9ba6974b59aab95f74aaeba5f4adc4b7d7979e917f9f2d2fd6456c527c41156181d51c5cfed50b266f9609b784283211d127cc8d96ed2624c615d0b904d6301e1332331c201274ee4079901d3a2b42a80e239888569f9a3a9881afc80b1fd7f5998e28e361dc4f22fa148112040ba9fcee128af3797c43695a7b452cdb9b06ee1f851cdfdf9e953f6196487262614597e13a2c8c76997f738ef0dd31277fc9f20a6b8a6cdb0bb755a13d4c94171bacb7203174225887b046064f9c7561146d0030f741072049059111749749c5872c7dfe108894ca725be35d2455afdddb64a202731605e7d30d65485b4dae483fe16e0a0d6ef6b39ebeeeeee39a1a89cd8b1f5467ee8b11fa745d9dd7af9958891181021621bcb07905cfa0db28cb0fd2d7883d4e8cee94b1871c70fd244a0e28a377f5fad63ebb6747058e0f07bbb5c944410b7e1ffe572911339dcf19b5ad8f3c14a1b3a9e73ba7426cf172d6aba951d826e4a44e7bb06755a7cc3afd3aefebe5a67a8d3d26917db3ed241255b8243ec73119470a77c2d320de3d0a472ff5475a872007df9ef98efe10e9f233284f4c52f2682ac9a1341765691ec815c167484d85167c6c50c160b8429b200e12886831aba7e7eb9aac35791fd1594af5bca40dace91b02682c916214eb1d8abaa1baa28315160479024899124a80ef6f355616129a0a2648a8fdb39d1c847a614cc56abbddb42b29e6cb10cef4a5186624b476cbdf8bdfd68883457fee5fa8b4fd3d2a17101cfe11711114cc469b1ff47152344ab14d8f15b92a4595114451851ec5f28b5bf934623cf68115b25135ba56d1982df2214d6ffbfb636aa1324610453c48e16090845bba75d3d9207ecf9d90019e6e89e16fb775a6c1b3b261eec583f96e1ddf6b934c8cfd1dc5f3fcd90a577fcc0edbbeab9e02f9fbeccd17fd9a3e18a0bfb37b6831c8e768003100f4c14e121882b3e9ae8626803f2f6334d277e2ce0549bf934f25b94a3d832a20118f8cafd82b02f59f605613f4b1227ec81c0245768188d107bd4a3e3a195367cca3b1ba459c9daa2bbfb7f34262061477b5b7dfdc28c34d7674f8f6fda67539adae77b43edf4474a3994d6ad73013c69edbf242b7f6b554aa99f6cd8b3db943addde73d1043fa909e512f30285100027ef84429dbc95caab5101f0690230bdbb5b85a2c2ca6432198c6f060514bec60233ccbe1b9f7781181601d47480ab210058d3b5241c3978768c5ed8e8115938f825611ef8bd60b106301d09c7025a908941c6a3310002bc902180cdf4da4141624f90e7d4c059dcfe1a4a1bc2519a20c6f3c49918141414e4927a6199bc19388cec29aca08e01a450b5af0f5371509abf49a1fe58fb750d8ce3fb6030180c75b229c4e0e1c18b849442c2c11be01cef5b1a4917a8e0b61cc16d2d6c90511b054923272d0ae00729a490428c02a8305dcb819423690b8e991120e1d091c308a4180e1d2d760e236cac00a794ed1a859fa9cdf9a14e9e9c93563129163299acd326d5aad0624293c68c5e603a6d52ad0a2d2634694cc8a24e3228541d754e1a139a3426548da4ecf1a4c56167b3d9cc9b952d4ad326d77a674c489e7e06c92e838282824c53fa9cd26342b3d9a4dacc8f16139a34267402149d536d337137853a796005de5d3cce9195c6e8f687736d24c18442b252266560773aa1604c31d020ea7876eacb942acf566d83051dd3024c5e0bf6bf6b5127af9399cf5d2ac32f6a8f8d27e2b4beaac33d9c937a9e716a264187ebf57b4c61171e71141e360059779e6050dabdcb5b9dd3b30b980251ad9d93d7cdcc7833e88333683d9ec7a8671d1478023d8d074c60080a32a978a584db473d4c01cef15c36eca27f74d43f92ade02338e1cdbac76c369bdd96d12a9537c3f42a6f46f77c029b4cbc7a1ad186391b6d039cf1956b85ed99c146cf0c2db60d169c4e38a14e0cd4f5ca08520894524a29a594524ae74f26246fa1441276f0018840092c27f87358a6e339b2072888420a293dd8010e5a127d9c76c94801185d801f0683258de2287f664752ea5cd9ba96524a29a53e5ed464c72aa7d8b1baa59256b9c1d135c9920e6aad2e46419dcd629632aa8187ca02c81a0da54e4b204219fd00c6db4276325ae2332d01886774054cb70424531413a04a5b7eba2840525c1740a528462a1758b82844a0b06d91d5284cc8685c0c6d328a9694a45cb9007216d7d768e21b388ee3c2508a10006861248588992d6052aa7c49529260d22256f4832018527c3663ab72dbb69538192a96bb5cc4e4478c0dace97211931760616244ca923bfe0b22a46861bfcb454c8c70830862d0848718217bba5cd444080689264b6290b000b85cd4a4072e576c77b9a889145fd4448bcbb66d2f8c0c418218205ada90090332ad877a41a1508cfa176f86bdde285ecff3426b81dcd942eef4d1e2fc6971f6b043494237d0f6d12ed44f47421a3be6b98fd80c621ef3596c168b79cc6731a11667436924313f8ab951cc89621e8b792c16f359cc6744311bed8a0dc5260ca6061dd3747cc3746bed944cd3a39e86a5e738ee51262b7722c176505a9c4e5a9c3624b047c42e171d01643e012e171565b91d6d2b22ea8e6f53021b011eafefa59376a13caf93c63ed2d169b5c2d6d2e27c1b22166807a7d5ae173f79805aad56ab35da5c9904f2241015efebe0c2b81464a32998b8edb9f0726b905ddc023cb17c611b96d7177e3fca98e9e565a32c59ae9402cbeda3767194235cb9f32594cee99f96b9246a1795b176bd789e32321476c2028ecd0bb065c0b6f2e339bda567ce9a3f25261c7b084a23b9d3c94b38768c8553387e38b67f3e5438da5428eba4024cb17c6d38eab8f63d7094d7ab264781630ea7a005733805479e4bc3715eefeda3c0f12fca07f516b8f4471d17d573e98f382eca8235b8f728907b6f343580a606bf5e38ca8b01d32d99a4d70041175d74a1e5764f410c986e178e396e29bc61e2409a16e71709516d6860b9c52d043f708e8da58feefccf6530ed42452793406400c5e49054f27dbeaa52269f744ce3ad0d54f5509f5f9bffcc102b35fa2a2d74a1af46c3733808339da1bb807631b7abc559aebf36a704a1d6e834d3ecc13afdfafe12c4a1a00efdbabdea7b15e035338465dd92b0288ee5029ea3fd940c658ad8ad497383355d198ecfc51d6914a0fd235d99359149252d893c76fb639e435d8807cd6cd78a058bace9611d08fdb1b15c200b76f90e3fe40fa943c3c0863910dfb40311b21ee4e2107b83dd1eb0853ef2a5c970477b1f1e2f2d5455ebac7e04bc60b771b86303adbe1eac54ed684fb5779638c3fe09bb2609e6dd23c94b4abcc0ae14a59c4d91755010aefc0e6aa73abcee48f33c8d8acc0848cbeb34a9cd40455df690464190715110863c879180c160301b828eb8a2048797fc8672d4563a875f3ef5366a97d4947079868ce4d76aedf7fd8b6258c48e9c74e5ebf09c1e2a3d1ced4deaf19cd0daf0481ec9172a57ea13ca24436371d64e8bb2915a0bd85b1c06fa8ffb00fd8703f12027e2428e64821ba8013984851d5b3bedf2c642f3cf25eda0af839865047be2b6ef5059294020c15e9fb37e664811a2b81d76d0ff0b0cb582243976a689182cc96939ab69c4d0623f138d3a34765a3a1bc82ce0b46810b578c6e7188f1053e434bd0f76ac62cb73b69f95c0b902614ccca2efdf95d21da7c57e1af6b0793328b5c131c347cbd7021d923042072222202011d0964effd6ddf45bdb5ae2c04af66654b1fcf43b9955f5cbdb214e184e159237d98a83d9c4e7088ff6f37dfc55ac119124c9d050922494abb4886b4af8b563c7911ddb6b13d8c209d0f07504546586d26247d419753f7347c420f7bd7544ad8ea8336a17c304a95b07e1421ab15d74bc418db090020bbae2e5285df0703b6fb95c0a846ff8795c0e476a0297583ae31bf99d6c7a0c60272eedb46f7094d70053c8ee660024bb21f18d7ce69b4e33712fb804e1b8859a9daf466a754f31791615c010920c45f6220429248bfd107b010f41a40d4047ba27404395a13cf1c412a413f7c5e5a227a028b1eeee2aa72ffa3bb4a7e10e9f235aa87295873d6ccf2f3a41a63345bdfa5c49e72eab57087104c9c70a60f00217bc5c8bebde5d7777f749352f081b83168e624be7ca3c480d414b8888404bd10c765842152552b3caa7147ca1fb9b611fd1b1e7b06d754741626e1ddd7c102589ca7d15a0ad4a095a454749b75e2e3a42da7658a2a6a8382a82722493f1c110b3736653492423c0c8da31f14c7316929bc02318e61c66ead8b058f8089042df9992b6817c4b1447c78675e5b7f8044841748699d765386f86bbc3d07895e9cee499c08ee8fbfad378db7aba7f5f7f933bf9d3e79ceef3e3efebc994eb172bbabbe59c736a74dadbdddd6ea5eb6abbb87a77f74c13679e462744f19e692251cc3349d73177658c6466c6016f8b73ce49d3dddded32d3bd6f879d46690fa9b96bb4dbb4dfdaa5e5b37c57ac740c9d536330a57e6e9c66e16a5a58bc420e19a35f8747c6ec6737ad27471f3d08b4d450c7120fb40f1d9ef25cc97b6cebdb39c108d6a37be40a1ee018fd3fac0f10f04d1fe9589254ea244cfe48203a742c49ea4cb46ed2c84b019dd27d52267432a1d3e53b9d2ee964c284d6283a0a82d92ff4ddde4d1a8e7649ef7906c68263d37a16bbee58bcc202648cfeed2b9d349659dd9fc02e75a5da598be3d697359c9ab800d109bd5b4823073b3c30708c7e2dac61a5d1fa3a656f9d6f1934daf52cd6671a1b97be3cd1767b923378a69d185ae46956c3c0628dca46262c3468681bd52852a93b1dd82a76002a3a1ac1cbea4e1943186adb44f886106b599f73ce404410369041d20a7630f49a5a16779e60be696190607251b8f42b12495cfacdea02891baeebb343ec58a70fbb21899949621a151e7c7e44a92cc13510b149058a1889e4c70b4884348bef582d152d4a2f24393a1a92f10177a5480e64781882c86888257418228b133b2f170d81858c0f40ee96acdb6fb1d8bfade3ada07eaeb92f7d73618ffaa54d5eaec4f597b66799c08a4bd8d15a6f7fab792e789bbf149f05b0a5734321ecc65bfdea5b78c3370b23d640816d36744c0343e7210eec3ff74d58b1431a7c336158d500c1ce1fc07c1544f9f30910438a5294cd2dfd34ebfc17ce317145b14bfb39ef58efa43eb52d2c7d7aa53763a747890b776ac8be85cc3493f6803b05d89f2750d51ee8fde979bc3f7dff29f439d221cf497b55bfcbe97d545aed50e500998f791960de25dce1f2302ea16519ef79bc5243ed927979ed9f66fad013763e9216fd67d8432d3a187ad882b35e5eb5f3f2aa0768ef12f32a19644ca8d242d5045e3ee66548bd4bb8e308cfcbc77c2a5469ffe261bc0c319ffa54b8e3253cb285aa1adbcfdf7e86aa1aa5ef2f7d7f4ca872c08b87f12a2d94e1c5c350c9f0bdeabf573dbf644295f632cfe30513cafc11d3fba8eaabe87c95f631a690e7a5861ae07179fb0fe0978c8c0d7d5acef2770977a4c21d98975035430df0bc7cea1fc02fd1592a07b87ccccbe0f231e18e233c316f7f472af4790965b031e10cfce2178fd7c8b2981f5babedfb5f9e5fa99f797ebd8447545a4843e9fbf98e3ce37e034b1f03a6fe0544bd0ce8f230a07d69c27fcf9e4a7b2ddc81f13d268447fa55ff7dcfe3f5c284ff429fef4d088f6cdff730bf43e6777c210e987ff1263cce1526c060ce8af9d52861321ff31380f955a8da898979f97a7979f97a610d06a8d242d5ce8be7abfa55e803e355e1915283aafe17a0cf119e170f03c65b97df01239440f65fbcea71ae5085ecac17210e1536f533eff2f6550e70f9d44fc0fe4ca8da49bdea01fc4aa964902fd4cb174abe3e50be34502a6911498b489ad0a1a113d8481a16248404c9ab85644e64348432898882a67732319b09e6c553df227dfaf686d8b54d27b06120ca0776d656da35368cc8352750da281cfbe7fa7750bb54d2484e69a3ebd24a8b7e34033bcaa3d9cfdeacdacfa9fdac77761c17802decbc63f560d07e0b6b8b9ee2516a18a3ed3beebe54006e6ddbf6168bcdc18eadbbd168b10cbedbb75adb66a5b0daed96e7fc0d9408020f3308c2132c5e5b873d5826b0e212a5df9e46ac0560d6e6dd1ab6f866fbb175b79209b7bed401393086169cb57d83dc071899c814802d6c5ffe7e7fee03803acedab45008fbdf0cf7da56d24a30a040a1e4d677aff5abf5ade7dc106ffd597ac2d6df6aa86edd7edc4c01d8c25209db68b66fa1552cb03a214e8b3550ac94a92955a6dc000b2141a6dc90b2625faa90c2c2a88285109ec4000981082242c0410f21c44420c48a10806280d0e2b265cb86f9de66762e524af62ad7939b1dea74bd17cab980303ccd416bb4cd8a4d2e5a4ab35a57a2b9a9fad1eea695fbaaf566cc9294eda892a9647489ae28d28fc5d03be5cda05ef7d4d169b54466c9709c342245f56c1bd1f3aa53aa75aa9bc6eb0b33d49aa53965e5eac7d56bdd98d99968a3946a5a9d93526d727577e7f8519073cef8b0f29db92b71b53bc95031670e7aa7006e3fc87933e6871500d79bc60667a57548a78ff3697f93ce979f69be9c55243645b9336c75bf7477d1f31f03706942f04e13cccac4cc1faabb4d5ee99d3de79c34a82928a5d269e5c2fa7d755f5153fbec64c94bee3e39f75ab2a54a29a5eeee5ba9a4f151a7532de5dc1f85aef4ec73d378d35834b97ba51bd50292b953cbd30e5cb7cf3ac30c078c1c741d05b97bbbd62ebd1ded3453355116747470e8e872984adb0e4320870b71382b213b410849e3362afe3b0b88ad760838ae9492dfea69606ec0c0a03430c37f7bcfe1a84f0efc6c47e926af4f36f25af2bcd59b316136f68eca86e1afdf2ea5853c2708496f9ed33bcec430931575abdbb65d717451a8f93f770235b5ced2aa276d9e96849d77f4244fdab624b4eb96644e975b6c490c4a776f1464209de8f2b3a42f7d1c74e2cc39302236856c1a0a78dc294b52b6a073ce3989ec514c48e6eeeeee32a888296768215dba74e99c16427388910b0bfc879a80737c871d82041932c4889124d20e5d4b43070203ff61192e6ee436e898663c2941b22119e29ba65f74372450c82424b74f611656d250f24d7bbb8495924a5b4660479f25ddbe82a55d5fbbd4c1fd249b27e8eee611c2cafd3bad7684a0dbdbd4269d25e89866046777aab6a8925a9ceeaedac2302097a7f4dd77a57005e4acb9fae9401eaf127834c1292d4e155d0139f255d0fcd50fd00f21f3573125ed92cd95d09daba13b574eee940e1eb56b04a78056a683e094768daaa43b7faa92545b56b0e9ee3248ee746d9a3a9041792757661f773e9529ed3bd975cf5f9389813ed8d5cfcac7233d48d435d8ddfa5dfd9e0d96ae06caabb96bcf5ae85fc3c31a66f4bf202f7dba03bb6a8b1d8bf3c7eec79d632907777e6988dbe1cee7805806f70db47d273d2980e87ce7dcda30abdcf9234b713ae29b395f8518586a547d0b8a62f5b3026a71ae7cf4cac7eaa7c569a4c2153bae7eeefc2ed601e94e48bbb427c29d10b00bea80b4385f052c169c792ae89866bc4172fda9e98737e306a845977206f6e6c70d90169dab31bafeb546e62cbf09ba11526df26b8cda35de04d51cf9d7c888fc6ba0b44b4e9965a949f29a2bd76b90aed76cb9fe9beca0768d37429788cbbf01bafe3742ed1a6f806e806e7edc00e159d9e592b77bec9cdceea0804672fa0bd8eda4c9dee6e1fa0d10b39cd638b9393741412eb8fe2a34b909bafe35b21a27eddadebf86a85d9b6c9992dfc92e7b20e883b589b10c1779036319d2bb6b9cb46b768dcc26e67f03f36ead93ed936a9ba9c1aecaedb1f08d0b2e5b1576d199cc91132cfa8f3256aecbc06455ae3fcc8625f5e33609ecb22dba7c7f9be4395c0ae885b5a46030bad8f5adf322643da9135e04d321f8cc90eb417cd32aa2185899019060fb674b70bb2b24aba1956c65845742d7df57aa1f5cff0d5411f18dcc6cbbb3bf01dad56ee7a611460a88ff0d50bfb0eb46052c7a0d91b3bce6c85940edaa29e24605ecaa71c2a2bfd7c8b0b8a05d19d6a8a0c48e9a4cdb8176e439ec5a11e138634473a2c95886f6fe3ecec86a905d4850bb1cc87d057bfc7c7d1b23d77fdcb05caf91d9a46a64d76566d77f4c01b9fe1a3843c119a11924334a9ae55f679a5c7f19ae627c630099d90d92172994935dca0df10dd5d222456a91d624bea1dd10dfd03779e11576529b1691a816fada0f4a472c034937c43234570c16e98f9d12aac2a574d49e5c4a9f5a41a7a049e015681619837e497e0c1bf954854b7f9327b8f43bf955d2e76816b982641ee914f36ea0e99654dbf3159816e94f6abf558b94fea8817cdd9b21c398ed66f4084546406204d95d828683c580bf0c2a2276c7ef569e6db577125d2dfd7ceeeb3f7dede79c6108b69fdfb5d61056bf8621a83f9f0bdfe7c8d883f632c8298278128219ee6839f734b45c586d0d671f40fe16721f40fee35c41c796cf119ef9dafbb0b354ae853e139c62c10bcc14f9e868b19f93361edd1388aeb68b591a75b55dcca1457da3800761065a960a2566adb26ab5d2b0bebf576df2d86417752edeeaf45fa46da76b1e82d972d66d5a6591e6d8c2c922ad3a44aa492903e21288ca154809c42510dd56e0359092ca8c50050977754a8a28a6f8b1b2e4499128981089a20648a208e283287c0ce93477b96dd6ddfbcbd9b639e7f48298734e71ce13b4a0eeae31bbb3c9864ed6e9bc84d28d6af487ed078f4a2973a2b68ddbea86844352a7cb57bfc035661b6cf22565506c69d313286630aef69365e588abfd7403c82087121411458721b2d8604d60c15d214522e8d74385141a5831410e58d0e0a575a13d4eed2376fce4b73c674221f4528792d4c9ad9ed8f203501114376c4786fa7b2263c40db768074193522ab7a94d9f735229a5fc396da46ccc256be3d5f06b69c972d6528d6a9aa6c58498744c33b6844a9bd0dbb8ea587aeeb30ca0affdd4c051bc5ae9fb5a7bee3bad01a5a74f4be0487335fa96b369176dc0560304579b2eebfcc19a6a77cb9e75b27dc2b08ce6baa2611186bb5a981b2616298eeb5b3b955f8b6d695f772933fa8b74ed86ce222800e8c0320a004b24b3ff0c5d38f5957704548692996557fe9785cd9764f9432a965f8ef365f74b7672fb4fd031f3ced1a66928b8f6351cb7af736edbcf163864668d8673bad61e45c73c27759fde3016e645fe95f27bcec9f4085426c39062c5545bde0e12b1638caee53934ac4eab059a198365b084390f8c0418d4e0090e8ac0e087255c34414d44d68617cced974878118e4ad6060e33b8d2050f702022096d8b2230812945b1fd7ce7ed31df07217448820492143d18d1b65c0b85f58860b95be8af5dfd493e298990037aa23f2ed09e14fd9cd808160011450f4014c10225d38a2686684f9ae8e1448dc0c4116ca054d89958a2c8896b0da46aa8346e3725b16468060200004102d314000020100a8784229158309c478234fc14000b708c3c805e341588635190e3388c428618630021841030666486863803b48943e97f7b2c8a3a158d34ba0fcb0fc8b6c62eb0733e0274565b359e90d8c22ec8de0f5afac0defe6518e667a2afbb601c38909c021bcfcb05f934230b9886f370490746e4d242d323fb5f62ce503940829f4f82397098b651590d3c2a5324ac5238d14aecbf2c1289625c3069251fc1a77a42ff6fb7f3ca95d4ad75f06cf4b188513796d26687849fe28cfadfcf1e63a00c50c38c3f4695cc8d35d6eff3282d6b50337eb3aa9ae2b8a3e28a6c4736760b2df4b8aacad4f0a96aef5d456d7a31709d25823b513239a60e629b3a36364fb8c235faa060202e9ba69b19cb4206dbda2f0284714eb72bf37a8d7537d35790d33d276924ae7b2c2dc5e9e20b5f85300b652061e9472d3d384317749c0264e40e741d6c3fb5388ae39d6c2c2f0576e2cde4d6f098a48803f138ce6e9b86160c7ea24c456466c6dbcd39686466fce1b4cc0ad1d07021573c071c2b6125dbc55fc91f97d81ee1f8cee886f6e298ae5f08a7261d4852dd429a62612d975805ff5d19fc65d8ede745e1071be8b789cefcde807ade3c7e1069d6877888d1144f586539bc858992968f218466ec701fbc4f76a7062c598f38362ef41095e31af463395eaade87142d8b5664cf78bb113fd83344f6990174e356722be958239d933e11e41bd9053da9bf79a598838060939ad11dd6cdb4d8906722dd609a10c876ff3a3d65f448246d6a86ae7aec47c090cdf0a5ff187ddc75af21b555c89e410e7d8ae2ec701129809e71b0152d2201512f35f7e89e1365dc89a4af160acfe8d4468d4277c6e0ea02c56e36cfffea1b07013c643e4e35a0c17e4f428cbd6822b6ed091c04143f91bc8402bbacbf27c27c7fcf0a5d5571404e742fc1af3290772995c0fd21bc11eff4d02ecb697e4d5d4160853826324f98e621f5e6415951fb118b77c0ff52ae45ed01032c7e7995ae5e29930a17659d7fa552a840a928ea6a2bfe1732ad4cfd10b4f2705f94e7b074016ff515d04dbb305681aed96738d37c19043dbbbc9c765d4e36ae9558ec3e59b0e4c1e18a8b19d8b7d51b29e33b8725afb9d32df72a98a36eda3459703bb8726f9acb09517dc266475d6f478e2ae8ca78058ee72fbef6ecb2995605e0d98c97fad1c64f9c05a1540afe7016913e9a4f650b15fde963bba190704acdedb4ccf4e1ed89b7b900e6a67da3dd040d220583c9e7f4a35c9752adc91ac8323c431476f465d22bc84ed9f3c1cc3ea5ed8bb6a7aefbc417629e0510723802e5c3b78bf8250c005eba58ab8a8bd7a53a0edcfb24b3cdbc88c296b07e53313be5963d68c5cb608e5d26749edb3230ea01f5bdaabcb988822a32c86f3e1881d4fdae94923a01e771b33fbd3046e80cb3339df7081e374da3a6a79e8b4eb97b1048d23ce9e7a6c9dfb099cf593582817874be6b6e85f65a381cb6ad7b217d4839b0deef73228cc12c604d1ba3b02a745abef0617520e99c5def392ba0e7d8313b1558ad3fa844c5f29b7ea5c268144e030cd96f778b871ae36095d6013d2e861253c1501e9ec1fd476c25ea29ed8a6444db939e9e7c5ac2c46a254f16983c34a24cb86bb229706592f7d5e40984cfcc29a943e479c5396f86a9bf08a6d7a9dfb64239ddf9b94bec84ac25dfc808f42091e1ad9831955ff96d2c72896bd394d257670bfe2282180b478476face32945d48194d0ca0db1a07214676c688ab6bd7e0263dcb8b48d14ca1548867981276d3852c292233f2e01add41bb2dc2e4de7f94a760cc0481a41255958e5a936c9be74f4ccc6a1568394d4056db74068a5e9d9644f8c4d54fd3ce3a6f08feb2eb5995e39321e82c4e844e67138a75715634078ed0b336a9b4c371109915e22336ef054d59cebcf22b8f0014552f2579d63c0705f2b429bc2963ecb32aa4ab5ef7acf38c62ee41e6f5481349fc88076007b336090934bc0901b692563b37d902dc23f8453199246f978af0ac2a8c56ae4c8471c747c2e7727b0caf1115c9aa5fb26dadae59a5c99898278f506906840c874aad3bcc3f42e106c1b931e54ffbe749ad6f2a1e962a6a1b139b6c10f5a6a5b18e54ae9858e97cdb668e434b93081e328b276fa4841361d4046e57f8a6d26ba487af8c79908e5595c1016c9394f97080c9d42a8501f47d85b080862103616631b0e5d139804c3e747c3c763642b773a72c0dedbedf97af548947a60b3e40c93e74fd7c3960863891b0d341f076327c48031abb4322a81928709f08d68bf12868a98dd2ca8e818c8a14c08dbd8c8002ab4097840f8d89d26fa525725a15565f8dda569764020c9988aa969218253fa2d45715a0ad3d5452b1402bba7baac99d80e49a71d942c85f4d407aa7aeb978987036bdf8a21ec60524b69c9f39c400341cd442b8033cb9cc46f094cdf76fdbe243515236e9b569bf4ffab90019b5979dce3ee2881c19002a6042f6e820e7bc83f0e35bec10503b8194bec8ab347fe30c28abd7364e86749c79246bf8ec6cf309bb53ec315745aced21c764f4406340e83ceebe0488e2852f99e27b00c3a9cbb4524871e30bc78dd7aa480c25b174230b73dc48220e51e4b861d255bc86bea62620dbf68c5c99396e902273663f0b4a787a0ae5b8f94f77a5082f3c20448e9b716cee0c08312d48fbb1ec827ec687ca2f1445dd056a173e35dbeefafbdab0366a7f1dbd7c87841f1fa7e71a1000676e698e8dbaeeacbdeb0fa9cc14324e81fcfa714015ff350a6c8ccd39126a5e0d6d2c1be9d7cb2993f0cacd0e0985d7e4119caac9ce029d3f27d26a48a075c6a114cdcb15b46b8460587e64a1808ea4ac075aa4e2cfdd90216b76b809100286f373154a4fc653ddb90e3f10e22cf916c2e36082faa6c7ac3bd7abaa26ca01162bb47bb33da3e8c12ad6bc053716f9a7970a3f3a95fa56c725087c1fa9cd082bbcb25800b67607c7c7c15321c91c17498d794ab02b0e17ae64e31563232d4a3b29c88dd5b3db5ba60fbd884d9f07748e93120a89c3413413f38d340f96c515beb7d06c955f1e0378e6664c4b188409bbe05254389640cce502f0e5a6cd7c3588df478023c6663e59fc45379dadfb9d05c37d389dd147ec45c6491c87e933ca684d7f636a712e48ac5bc6bf12634215b54a784990661d5f91496a0513f83555a361f29a734404ad100ad13b1815ab5ab331713060eb9638c4dfe72c0466af621193dca3fa2ceea0fd176446b2cbcc4633a8e1327a0ad6533e7d85a1e33d97363ce2e3eabf91b590ab6fbc653a12b20a5ddd9eb82699018e0f46fd761db87f53a7ecb8a8d235305b8d12bb90b06b85c0909f4669236f12b72101150b3d1c9cdbe9c3bd928aee94baa4a6f90fc45cbd162a52b0a156918432d013c1d76c56efdc7d372e512b400bc9c9dff7e6053a46cb1fe8b6f915c254b67b547b0458c54c10f9147ab029aa8e697e96ed9a21304db4eb4f33655f245332b60ed843fe7523e6c292f30c6cf69b9bb42446ca57a4793611065ea9ffda028c404ed4d8ba7bf17a0752efe9b3b0b2b680016b8509537df7626dd14e4c1e640d6776089dc2b2048a382674e0d6e7b6a43384079e2771ecd125a616d8d6d2081143df0886156df2438bc4192a958ae372662a2194351ae40b91449df8bc4d9a2280373718823175dcb23dcb38a7967a5672badaa925c4d9445df09992d02679a8518146ae7c64984a032b81d7f4117027f1b7eef8060833938d8b68ce45826e04714227bda15ee94d85f7d6c0273f7830fce43691982194f4aaa5487f4d0196baabc976f94d2e238d0b2c00a26686a6ca1fddd3b05afffffd901594d34996e7d45373af44cf950d916ef87b84b757bab770b3e73f4c9dc6f14366cb4bd5559a0abb4d391e9b3a62146cff6039c08a1aad927fa4a295466d69d009d6a7574ba0b5714a77fc50d0f4cad66ad68ae235b98837827066665f73e119a0f50df25d43d06850ec5abe33e644cd0808640062b71e97bab7d663def78c2a183c19e936f8a8e516e16866d1a278a923061235af158c162753ec0e1c4a40a445e52ec78ba99cb0d8c533ba12a28e3d9e44558a2f99d3b2ba4d1160bd059151d9e87b7feb86732e60429c52358c1a4c68019d3a29b806ea44b325fe27617fd5c22299509e6a235581bc48c8891bd84e017b03bbf38f26113cfda67982c40eb8e9b5c222d95b8652da2bdc845ec7a4ad35cebaa8eb34be44da5d7eb6d7667a2070de2df31ce3ed602512d69b8451ef6a38d3e1a94c0043c2c25d0531231bdc4e67b25a945553aac59bcf1a40a0262d8d42c2c997c632b31c3e3f29211407a7e4598065b529810ac35fcbcb348bbe77f9d8308ff80620067bb13444bab38f68169cc775417a77158f980c7e70cda8f10189d908dbf9875236f2d04ed2403c496d19a7e9ab648224b8e6dfb4e454ea009680a6ed0c920a2d60f6786d9ee493c74caa38a806b0ab303e86b51d7251ea56f339e27eb3a80761b952a4ac19e6540298a71de9c5a61cc325f1f920837c87bb446308b8c40f1ac90f9292b68558b1f1e33fdeeb35f1c6171c3f805b4a6db1477cc36be9fa0bc47aba7612278fde1514ca02e0dcb3a417ab7c886d0c0f0e63933133ff1bcc9e621cace03a083299671509e22be4fe1c86bfae58d1f03b68de714681deff29bad3abb067ed18053639cb493117af1e26b8ff4a475916007fb7a1dd1ebcf408d0cd5b64dee7d88c1eeb607cf11fbe70e4a00f4306096d8a24db201fd79b8279414129778fc38b966f18b114539ac162b260137e3ccb86f7cd45047de6921466d63fcbb5ea94481c584be3d5c29eabedbfe51bdff24c40e0a11e696621d8f7b01df50bb97bb810bb1242006d286e1664fafa0647ba34b76ea4cfc18936d44b6aa01e6891ab005f08e8f0f79e0c3c3e7d37190500f1ee96c90c4d1b81f1aa4c7246f8132a9a04cc6862b0c99caf2745b6202d437ffdfcccb7d7eb8fd1e33e73876214f4ee7f97acaf760e68997d958493c031b2921f29ba3c3b23c8d0f4f2c402746c7f408544ba5c96fef8edbdba1c1be4b62faa401a9424d70582f53e50f1161753a1b68587a5448713d398205df98f12d3ac40568381816f50eda9b32d8ceff643a16db3397685fb2f18ae88420989e1e0d7ee2c8212bcbc3dae8e000958058a310084361182ad0e4e2ab98d359c6ea565804a5613a1386d45116409f8fd1b4a48a84634fb29cdbe59855fd5e16055d95f4d0580e6d8ae976e4f5952894a547886566ab83314c1b015974276020e656217f091ad1db7f09dc8ea23d1fedbdbf2f8939b56d1e8ab026b2adbe3446c0c649e57a8b964641c086741f66aaca672638dc004b2fee97394d5ff1aba8040895b590bfcf6ca52d33e56d9b26f0902c86c9c2d3ec8f45c232a2843792548964486a00c1591edd7538af48b25cc4cb3aaaeca27cebe2a597d6be839505089f452e3812dbfbbb20148160d51f525a58231131db51197562fba38c641b87eb2d958c7b7a43ad7fbfa5fd6aac4f68b1c5f6eb180dced4323261c6fbcb5c9fcaf368fd374656630f2933d4409cb84fc64179e37874a03d4710ffd23c760b1caa50affca946b6cd3e05bf522c7518e9f304b35aa4c822a07b45a8f7dbbcb016d51c4836a31f02818049c2b47a61d0f0146006754ca1c930bd4043ea938c662033fa58fd741a20f6d0485c0f9deb401c4c57f8490c04dc720f0117c2390b064aca047a45f78ef60a348b8380ad39023fd1945c7be66043fac6e22c13dcf92326041b19772d66bb1a726882b520aa36a099cc556f21f5b595c5ac4d8664af1862521c46ce30c0ff1fad35dc2aaba59bb525b3682e87651f19dabd04e490aedfb548118a97123d39c569209ec548bca8d23a0aa2187ca0b7dc6caa9fa714c4389b2ef3b4013b4fa2608d195a0ae442ea28280d8590e3f5baa2207aadaaed5f1b79d04b6876829fb9ea44445315fa01274beffd0e6dac0fed1cf7f04c86106902f5bb9557311eef5432539b111c13e827e23436d5c28594e620a3a638de2b17b46e229342751cfe75ae6bc7cffe2fe10f43bcbdaec76d97f34e3f80f715a689fc9adcc46fe2e3403f8b17e5c402aa114f034497dd288446a633abbad7ecdc607ce7c12d05388445c0bced704b3c423eaebfefcf11a22af6e42d32598a72162f868aab559e7ba6e563807f1dca36d7166224927bbb0e82ee006f6824534e4fe283203bb8e9319cd214fd44993990c7040bce00ea08d928902cf7230338520012869207b22b94f20b4ad40c967c179d8db85121f313199a3dd40232a413593e0a884baa6d7920c1ced84447fcd28f6c5fdca071d02be3b0c5cda8108a1b067bab9816535fd99d9add384af7f20408bf58a4076fc2a8fe8bf3050ef08fc5c9a342e7e8d446322aeab7a7be009f1e86787223684afcec4b40e3a2f0606c6b275444de91aa4e6f092ae499b686f17dc4a4139cdf2e2b0b2b80fcca0dd179497a7375bce21c66bf2361d7fec218f3e64e0d9cef5d9e0b2dc88315b8abbfae1ca6c3420b0027279b82085aae7df188176f8e3a58615203cb8af615faa059b9a9d4bf5c0673f7efa07f3bf53573889ee29a37185a99218c577e4eade37d065603714eed5a8ab4a6e70e4e151e4509c6c36ce1bff6bdcef5ba502d44aee91e8f254f3c345c4dcc9fae3ef159d21e1ac56a1446301dc78f84eabcfe7483f42f37db9b9bbf7b8673f1b08a75069444edbae22e8802795305073b07ca196d1dd71821d8147a9bf7ddddc22a7451df183e37a2b1ed0d867da9ee4953664bc5407d248b8484c5f810d692a2d7c9d6890109d8ada334a6e3feb16abf2c727e04af42a695680087105cc74d6ccb70e95b7a0b1689ee9142ade9419da716718f0ffc6a0d1483210e16a8930a058e085cb20342ef953687560158297b27e4f9546caaa307ce0d1c0c304e42ac1e0c3d9768d77e69cc2c0c5911076b4cbce28567984a61a7041b47009c191e9d6d8845caf61c8a55448a0807197b71d3e53027a7037abc49ebc371326253091bffcab0db5764e3c77ab015305b1b88fc0449681a6104ed5670182213fc151c7a6720703a0887959a798b4898a496056087e7aebd9503161a06aa0e0931aeec8d575a002630fdac2bb00e7d37067c66aa1c7f3e30fb47d5f4f0a2d08b2c199090e43e7537258aab840018bc3fc87a7f812f38c4f0452aefbf3f01f855b8a742eb43b20d9294128c5cee41aa048450d1e52ff7aa4c7abfa662c0167aa01a6793d32585de5571f7e2e7b46b22beb912703b19cb91a28d9698ce34c49d729fe0d85c03f27559e9256cdaa1117bcadf0900ea738428c0c418845636ef141131fdd52776fd76887c4dfa67d3a9932638f8f7a40465ef4bd9bb54a7928165f330734770dd2f11f457bda7a82cb703a3d850501da5ac5717c775d57ecd67ecf4045e8185ec561d1f972c2d65c604a6aa4e4be63d0ec767b68d38614b96a0b3f92386265e604150bb1e7c8a481adfcc4aa0081bf0bf84e3b209a5e795737cbb30411bfa76b67ee8a47b31c027a4c0fcd3dc2592e772902718bc345dbe915307cc47c7f5b59d6a84bc7e043a0c04d7b288dd62a190ecfe343cde8a6d45873061c222f0c1035d5666357226dfe1d8cf961bf7b932994b062bc9a2a9d9338d29551ba6b2c06797849a0ffa5537f25f79537637e1e67255e185a984b218b03a2783d4cd494ad413147bad06a40a1613932f628d8ab3e79d003c417e0ae0373dd66e197256946259dc4b35cd1e44b9edc979b1fe90b906ffa7567d7da9a4c6504dde5b1c6cb09981a46b4fc7d42a8a7f7e1819d04df2e4f0940749d00364c791643673fce561e410e7504698ddea0741fd51204da3fe8909c02f54445a065da6b9257ff1ee927b50a95d1f5dd11d716a532ca6b48a45e4a4734bf171053a2478cc54601ae2416c95d41b54505d4632c777d7d028c51d702122f88bcb4fe28393eba6653fcea3df8551d085fa9b21a9e3cd766dedbb1f5a56969cf8aa4e7b34516635ff1dc710259013c0f36a1948dbd9d471396559b1e35a84627da45c4344c0ed83637e0f5b75b9932973bffd432e10a248e64bf7b7d68a96c7b21020899b66afb245de2d4d097a9214905418c33afc421f43203c080d6a33c465fe47d304a0826369649ef0b816c6a0fe3e868de6105dd96d6e59c21863846be420c6605dd9f1de6b2414b904a99aa90ed141a7f86f7e5dac9e34475694462faa3340cb2af8809a5aff450ab70a0de761e018e363c65ae8fc2c380f49e6615b0f9ab8f82591711b790802d1fb56a16eec7f54453ae8fc030721cc257c82e49bd3e9ac53fe620c2d18f57c09df22d4599e23c8f78ad5302c656acf3d27d599935485b7f70e8ba681236751a5dcb466ad0d4ddd6eb6ea427bd29379384bc87cb285208d3c9a94fae0923d27d500022305c5710484b0ebf9d8300d985ba194245ff606afd9429580846cb84b00f0b8dabe8e4199a8abf1bd1509b1d6cb94150c73572b6732b8e90a0f197587aa858d7554b449d79b4788d5998aafad373dd06755681a243ac1b345bc0a621b2f80f92045829201ab2954ecdcc35a9c297f4051c962ffb08074f2246902ba8064c991fc61561a427762a52d2bc78bba73381f39b72f1ae6342860074533367b35741650ccd5bc6e5369b731af8f0d716d5ee93d7d523225646dd52dc630eb601347107a212073ed5831696dbb180624e863530fb37dce0e605a8d0c116b7becdd5645726fa522e509dea16ad9c58f3b1c5865100dd481d797d29475ac10f182f6fc673a747e889eb08723c44c92516ec4f167f7e2cc471b0db84ab5813a3114cf4859bfdf318e2ea8ac5d10e7b5bd66ffb9f0b026830d23086b8cd5bce5c3483dae9576f91220c492627416c7673e3472f10d214f90e20dfe695b7a269233036ff533f8c84dd9630e7e3e3de5d95ddaf40d07b3cc085653a64ccd887820a59dc2dbdfa2270e2385888877436724a38db3e770d43ef316bfbac4c457825e66c9f45d14c5d4f028750c73e3fae890162dfd0b2c696fd2451673f7132eccc22e75a2cfe3640b3a802bda6fb400494110d6277d872cc00467494c201fb0ec2236e876a3326f2b1f97022446e24d01ccbcf8064a77fc557c8863aef3f425302bf4144746ba4107eb42b454b1cff6cc310573fe688e1f08b6ef4f6fb75e2495722c16e4b30c6cd5ed44d836c620722182a0bdbc0f683b8eca12c6b35fd5e09c95655597d0508ca5eeab455eb8cccdbf061c1a339d08f5c86d4af9b015db243303a9511055b7f668713b841f2e1f11255589f3a8bcea9aca3b8729d18fb8d5fb0a493364ff7d5ec7c9d2044c754cff6f65457db7439bd75a44aca1be874a34ecd128e6ea1bb3cfbcf1a6847f051b581563305835e8c5f75ed4eaed1102b3d60e8415d60187c7e0bbf161810747fcd19dca08655c5af8f4d9201ff8573674530221132abdb103d3e46a48711c9fd32e5244f49cc111849a33e424ff25cbd0bbcc81eb445e0855c23c21d8597fe24707533f89ea5cacd67bf175502fa78ca634bc9e9344db4d0bc9c0cea89f1418f1c66d9aa45bea6145cccc70b75694fd645db42b74e1fd4ef359c73aea34f01f2e0a66b83341ed0aa7197ac126b3575ad3da296f3275331730eb9adc31781e1eafb55cb219ae51e4c8ee381cb77bbf1f28ca6f60d32a9e0eb0568b6b91dddaeff66f9c387d87d3d8905fc53ebb33b023ccee8490b961c98cdb4a97a7019fd61496e0c69ad9cfafd8f745e91c43ad01c3ab4b8c6b88968da97bc0534a93a11c774482aff9d389c8a0dc16386c051dae59855b05555a1eb00c6c98b80380c55fe6f8cea3133195bedaffe15a88e96d11e9e07f160cfeac99bb014d190a7589cd75809071115c817e72975a4132cff0e0b1d44b3eec429a432d99ab194942fc80ad13243a4046e13e54b355d80613931057a1cbb76f00845d63fad951ee34ebba7fae91558873bc426b0a509e0b8e0e57d314272061454b714780423e30a2c464eb13a4d1d02b71bbf401146db3385a37e5ca222d6dff0452268be95299ee3e18855e9b4e146f801abb703f165032bab4ba522dfa0528832c3769c8c607f02dcc8259dc08799e688081928feab8f8bd21d927e4d134cbc27b019781041d10c85e4649f17ea67a81d518d7b143dcce862fb8728c5e6318e9f7272131e82f25135ae806b7bd79af33205db395110ec9b9449ea0789b5ce64d83b8edf7d53acadae6bd24181ab29b9582cf4f29f6c9e054b2c567c60ff7c67a4f30167219ebc7daf0a40752396be643124d9744f3574f19947995ee73c0caaee0be2bafa1bf1947d86e8978d45ea0b87d894fa51cbd24f5f138d4665078fca272fbc44b09d124d57c8f73ccb8fbb310174d0a063d44c79f2dd92841feee02d4a455ac4b12a72a2f95c70660cd14ce555797c7a186253d04f777906f733c1a74ce37fd6b5c8695c51b4620018512bfbd426b955ccf40c150ea69a2ee812cb58a2eb8267bc98b9ec3b5a47608ab298b8654516a293be1d9e21d59e15ea488b717cad68df3c2158f95ec1c9e50b9b1c34c47f2251f0500a948710a552bdf2da674d2884a681a48e34ed6dc29307c119eac05e83fe0a45a2435360dfa5e7e28140054fe44ffd164585e1394812724445b1788bd10e3c5ace038467ee8cff069457ad868c0ae3ec52406ca0dd6a9a6e4091ff6a7d4168777c2403e31bba15d877af17b1483f62932221e7c26184cb248983bbd4232c6f3fe23575c40861872b1afedab7110a1899e58e42ee23572657ffa7a4a90a7b6200b0588339676141b1dd06c08544ea0614e775d062c29b9d0a65d841d03dfbffb83d614278aacbc3c70dde66a417a1652606cc4362b61d18c728810efdd495158d807790e02867907d7abb3ecc69cf71cd26f483925685c03e014b8927c31a969543d7a5d9b218deccf07025ddf6241bd92191992e19882a6debb3f91495ce6080c66965c106132ab35ac182613133d0b34db71d3611c30d9ca1f6064b56943ac8eb9b6fbdd6e3556700522c03da6ae20c23ebcdc3a500e0a064beed0cea2ff8100d26ed2b686340132a00199de25d51061bcc7c42478d2799d0dc145221556372c99b9e784646bdb2026c012c837613c981cf8df35aa6b0bc3397bebf61b2f47839600f6fb416afbe1952429c72869660ebf5750e43071a568f70144b48d5190ca95466a6e944340b133ff862471799e0af6833e2286dcec2ece919e19b5a842d2ef164e2d4a0d32c7c21878aa7e4c9ebfd05cc28080ad6c2b38ae3c21b392af87cb0fe88a0f3072389c8cbc53b3ca93c04acd81fc1a62db60fd822317c74782061baf83bd24b2fbf53b6f4abf8d719f333006f102c591a447241e005cb69e7718f73f4c6ce037fd3890d04a24c9de4f2309de8251d225d80780d7285b550636dccecf3cc0cd78f7d6b16e467208802742eaa71d76d16cd8b6b97046f6caa8d9fa9b7c9665085b6d1d0cee6c0e7a0edca0687b1217641d8b9aca329c9e5ad3852a36a54a22564c492404705566dfbdc23aa9b90fb09d37ac45b7ad94fff5c2efb660e35b7508b2f8d70119372cf9e0547acdc4f9d220d6ce7d60ba0bea70eec6f5b4d67d928358d68d7741b172b491f72ee5997619aa7537c55b48ba00d455a55b4a22ab8d6842718ca37036e5f4218e2d1897dd1ee53c8fb28f5885c41afd6b2d2a5e6d5364621a837924b999bf23779d2ff1070960d262578623f8c4cf87720041ea0203b9ede56b2034e5431158cf10410adaa0b59cc660ec2455a794cb346d4d1e2865bfa264c13ff308bdadf8067e21ba1b692001c365b0ca9f4399ad4c8c32b4588f2ab781ec72fec8f27e8c5f70fef4b7c7e5c5c8ff8708bb0daa3af142a86b3faeb7582498da09cf11bbdd74e9e0eb76e2eb43671d79f7265f0486a9be226c9ed0945eef34314e044c1d135ac1d398e34b3f5aba3b0876259a3d984b5fb2349c0439bb2de7783881029885cbc219551381ab326a5b4676ce98f063a450110074574592590ba2f57dfceafdbe0ee69d4894cfad645ebbf1b2ab294559bd9269362606967a495732eb5fa8b37ebb146427c33488aa19acd7d4d66872ad68be2a8aa97b25dd2687b827caaf15e97bcb5eb10187942b9c5d36682e4e441137f0b29414a60947ec91d4e1ae04f7ebd7a4186887d560028c43f22044b920c5d5890657cfa2c9aa08ac722454236e78623250459ddf78b493ebfa54dab0ea90a6b42a4e929443635548d93c803a89e05f5cc3aee24b22fc520544303ab7f8cbc19603d4487a1088f089341c69aca5443d010625831a912a5543da24174cca9290cd786f63fd74dba5a6618a7243a6fbe86b20f30f885b8bd7e35bcb04db546c175e5625099830a184354d0d1b73b638f64603ebaf97d8768b5ebf12da2b4a4b98cac957b8315af0dd9289fd2d9c8fea7b738192520e2eb66e3c48c697d277db360be5ebb36ec3fdae436dddab2e73af5728c3aec64f334119341e39a83a468f5135c5bd95e8a91673f39c31ddc99c869dbf3a787be5710a61b86aeda52e50b4adfa930897e68d0c6ad63233c886d093a724219f2908b889461043b0b58bcd8ca28b8ff79d9ffcc4ea41d0539adea024c7f99150892a3d73a68fe1f4af5dca6a1f2e185686d9a9f66e1ccc5560da9643b4a2874774b801e914d6b166d99914362f59ec99a8cb521a7d06958a24fff58ac0523c18bd09603ad9970e4d530e841af0ed6aead9be70c647197271db50718663fad7cb91202030e54971b73d8d406b2ed8c541bd2a079a96a037bfc7bfae0768f283a113164851959f8a0004e6f9a00a20cbb0ea837a33f0a053c7e2e4ce2b57a26fb8e74f489c81891a6e2429476441a599e0007e4f82adb459b31043d74d06cd3f93e1746f0006beaaa8db0b2df18e36f8ad079d4bff8bf7ef7f861a48b5c32826e11a0a675b68ea79c381ff370df4435d8deb5afd78d95f7a2ac7d19ac88d4e4e1f7be543c1aa0f08589fa82f5d2139c9bd54c81f6b3cf6b2c0e9a6dc1e140f68e89b89ac9b64298861bb5b949fff9098c996194714f621cb8460afdd5461b9f1154f9c19a99454aa27a675e8d39ebf5c49677cc52116009c2b54569209eb4983ca7fa20b13df81976a01de6a8c8b020e33b6349ea4062eef8ceb8c30cec1a68983a2f1c61be33d43fb2c1c08822c0735de4e88429533135dc2044646327ad43ce9030d733b5687106cbe7e9fd24490c8694fbf04b935ffcaf8ea4d72bba3d74e0c0fd3d625e8c08e3d80095355dc1138142afe4fd31057ec6d75b23544a35511900186e4e0938300429d8960a61e1a0315e27e067e689c2612bf49956459b4853953d75e154ab5168e820876c005f5203e2009c3b5db7f2721c30ed94319a67c262204b79140908fd9aee51f467b85d3ca25782063c29a21a15471ff8014a594ff70d9ad7c80e27f72ffc9e23c693bd1d18875a4eb62062ca4593882cc8c56ed4479b6e4808dae88855660065ffd2c5e80d7191eb178e1a1f7663358e216819b33c86afc9fc21c7886dadf1109b8e6c7ce8b27d0d05c3333cdb824c5a94396b03b4afdf2825a0c4fbe060078100bc5a5273a800a1b894cc022a43b21ef78c0cab2cfc16f709e998113d84460b9b38b119c550a773131de70f49181bb3306deab97527e3e9d573b5250efc41ea70e5f4681f4b117fdbf81fa8a00f925ae8adad8237a87424ed5f644c9432d632848e8cc17c3058789fcb3e4a23d75f204c3faaa1beb1bbc2af0cae36aecaa4f452d9cb7e221165eb148f4411caa21b124d6e29e35c435f551418c7b2ad62620cabca80987a191d43259101c331bb9813cd6f8fc3bb58189de246e35e902dff9f634ce207abf41afebddba88442e0e894abcc7c2bbc2a12dba5c56435db7199ab99909cb511f867af9c27d8fdc18918267b9aac80fb8284f4bb46805e101e745a3ddbaa0fbc49347403ac64e534c1499dd051462ac1fcb9410da01556061ae5dc306257acf10f31d24db734f6935c657945fff63d4435ae9d20c8edabb38d8102af46e6ca4113158925167b9ac009396d17338d0722e8579f8611232b86256877f9382807da8b9ee827b9bc92f9ce4194c07c5023e260081792b704f15368a153e47d241e50a8895ccf5b0909c34ec27b589577123b249b2da53532eae293bc9b4201217493c13b7e3f31df70a272e58b76ccaae530b9127ff790601a4158649e8d3fa2129674178ba383da657daa3f3a48683bd382bf3a1ba145adbb083de39a3c9db13efd0e0b293d6cb878cdc953e1f61302ffe6f4819d7c52f676f84814f94f7cafbd1c4f00e91725ad4e67456fe06afa3e403440e80161371ad52c57f4c234f24e6db5ba8c33f32d95fa0bf929d816bb6059c62f5a4b8d25cb2392bbcc2572ff4b924403fb08305999c07d234f344d967d92ad34b66300bcc884b56e08b2795a0d3cf44a29d5d2af983a8a05de70a1e7f878414ddecaa24e1f5058d58cb85c644b00e8b015a8b6c1a451a032af074389abc0668348e5d5339125e6fc3dc0b1ffaad7e40e11dac6757cbead47b857d825388a5be086e312ce17c0dabd80f0e678d839906c6349f33d561e047c2bd0443e23c26a60efc98b26e1d7361c86dc227923980466405c8debb3d72eb1d5421cd1e762d76a8344a4a03d545c0bfccb06bfc9fad3189e8c6fdc3cd567b718b1b07bb82b034def18c7517dd53b357631edc134fa908b9997d146895c9fd770625f8b477254d0f5bf01e709369a416baf99a5c8008a0401eb9ad41faf83a56f51c23352019dce45ab3e0b504c8608c80734040b4721a2454a941cf83c244f90bbac71680816c383b47bf36adcfe6481b63111b0e0412d3c77ced5727102193666a979aedc80cb9784d4b57b38fe1ed031cfd3703600a8f4a02be2a44d33a485928f2dfab4ab28864ab3696dba517dccccd6a411bf6571f4e439b4d45c3ac902a1cfb9f87eca236c6d46bf111cd99aef6cbd739fa7dcfd23c1feef8727b9aee1e81f0cf2d299a7b6e0585ba316a43fe11419615d2610ef269d0ac48ef9a42fec6f7a4566d02aca771584852a4874aa5dbc3443e24546024c844c879e05417a16113a7903e0e798e24827033b9d1fa65568c29c00d1ac01f0f43a7a060e96d6b9a0d00a8f84463502a9ab64ef986d5e672fba51e12fd97a931bf33548d69e6d78621e58dd261d3ef41a7f25da2aedf0a99ebcd64e7f371ca4a8a22309393b6b2c37c20f1c2c4c257e023c73bec1df641a284a714ee8883f1b496fe0e6109312a78be20430026e5e0568ee8a8005d28cc598d161ba27b7550c4ea3768288dd082730109e8fe0afce1960be8d4106a87a4a18028450b51854472c02ea8090eb6cadb82246dce424273e737911355452ba131283ed433e4db22d26e961e192bb5254c432712bcd71208a6f957c8b22e3f66030f9c136811806742c0fb0828a36cb0cfdc0c4b5e434f01b3a01fe5d52c85bb9c0c49df4fdd072741b4451b24ebf918302874285d5a7cc508e31ecc1a9144c429f1033901f0dda9a9a6d8e8c29465049b201b53be90df39dba9eb056abab0654570dd246d314dd76fd5327842ae253e021a9f570053ad81e148531f76598ba239393269d517f6dc4e58a1640ea2cc240fc07a627039a239a41630204d51c5a45aca1f0e5b972961e55d4eb8a79c246adb3c1688f60fc043070b6b783bb146ea9c1c56e384cf8f18d037b69c639e9fd60355b686ece993a9f6a1a30d50890db4d78c11f41b240a1a1f66eaa3ffa94e97702252945f6357a8bbcecfa5dab40d3821a8882491226add84ad560b6e024cd57d31d4ceff376d52b7fce696b231a318397126a3bf915711262b2d3600257f4c9d8c4309273f662ccaada63a25df89003ab5fcc7c0e5ecb814ff17be073edd1860f962fc07ff791293064a89bda58f061519dfc56812d41a01692bc26ad53af4d8c58691c7921ed291843342038a4b5e978d82633afc54f84c590f82ac045a96759d890e5c22a401d3d357322f12675a915ec83fbec00be57134d1f7a4657bc0e08026347490df7b6393da4e5a6482e26fd7af6ad8a08037b894c92a5387decb5482d048397bfa2da05e19fe4535a674e970de3d1244ef7f3944e577eded179276673661c6ae9b5cc07feea3999d84c6612084e77eeef5908938242b8dfdfba21653f21ddcd10bea15b8bba422fd38dcd48e02f310a6f2db3de0a2f69f85a0783650d36313063bdff6ce266d445957df90f61c0e41e91ac92cb79469a80ff48bec1175c0bc6b652dab82deb2fd561b294dcf314479bcb110c56bc40dece7470fa28dc0ec9a77590c842e061427e02f6b570a515859ef701852a5f8c734fb6bde82d445d059830e27edf735a9388e799ec1320174ac3d7309ad442b5bae8dee5b0689eb15588167557722765f75870d51969547342801c33d1b79931aa92dac0d67d6f5847725483bf1c07e1b23a9239dfddea06913ec13aa59204042309d58d90683e22048ce95948f7d880283cdfdcb8e40c1ba3d3347df8c3bb8e242a1f3d83c965d1825abf139c31ac1e81ad46da129ceb9bf718e0514600bfeba3b3ab4df0a40651ec1ba88688107a489ec349697fa586f9f3b2181b9a25525b2c20ef95b5770717ae9044000eaadea174a8edf7ea3f3071a2d3269a6fe548d67fce5189de05f7918536fda1556567e5f903a7ae95814c1bdad1379a333742b7a67c8686355191319b770f82722d7a761745c0f79a6f0b66e340cb261ac683d93eb4e9a521dcaf43bd30f4f50728c78abb4460739e0fcc5021e58ee1c3e2ebbfaaefc57b4c34667082d3145123d0c45cb0a51808a588aa6e4ff57b198207f822b57e5df91159809cde795aa167587d51cb564454beef65b5eddc5acd787ed561a69d1f592ae33ff0b471cff5e6e1485409ebce8aa6b234f6ef176a8a4ea0c76eb7aea2abbda177c096b93100446c90afdda984edda4d35a4f871d93306f25aacdb505a69518a9017bf2cfac9fab6b7952504b01006af9a4f92969a655ddb5611b86f0c22e89be942afce431d2b5135466b4709eb5dee9fb3fe334a640467d0fa75f29a1f84a546242bb42820cd0e9ce5833fb0b15a91dfab91e640ef85494a80ca52556fc701b88128790979f2b482472328d7e689835b27059ab35ca6f910fdec0259b76fc0257f73381f1445fe48c5b3b36e898572470f3a9fcc5ed0288fc7b533c08fae74f9b1366b200d85635b4210ca9d74bdea67df68e1ccb50617a44496cbef69e1fc357ff7bc37d71af81ab73444345118eeb3f1a6149bfb29eb7c1140394fc83c921e91de6cf6e48fd43158d24333cc23dc35d5f00dd42d4ba574f2e89fa0a0c8aaa180ed50510d4ef2b8527756172eef93f34689ea297e430ff5a44032678b000199dd0954b457d15d1784af6a6520f0dc4053dd451b3d1a4f9a1ed33c1554cf01713c4e057653c2a9f256728e6740b46a2021dd8c1d15881e59f0859d74d0fc48c448666eb061ded3d99bb7a14a644dde6ac1e6c464a7976be0db2a8f210c021b307189cd30c34686aa4214c01cf924cbf776c802de761442491051536ccc56c7e5bbf11c8ae05276092ee3e775066a60dcd612f0a9f66124ca6db7ada5a0502cd826a2e417bc65f156e43ecd0f55e3668cad2b80836343b3db8f01147fac342bb9f293c8984b01f0332a02404eeeb36802b8d718e44cc0a4e2757a54a860c5f4254ce786d01cc8ba1de28cf472b909bfc7e048a07579e43cfd6e391e8828825654aa4881790db89d207bbfa3acad8fec3daac23da5cc09a957c7217e6be3f5a0da7cb7365e47e5597f5fb39a25c43fd8f569c06c868381a3afdc1202941a8621b139f563c71d75d108bbd791da53f25332a0373936181e0a109612c8d0be159f2fe47594d718c202c29c3f9ba5160004d8d87856c71013d0acaa6ba879fe1bd21c03236f39dfce92b9598a49ba56a3ba6397aa8bd6b200413c07f2919d8af0f8e9358519736be8e13ecb5fcfc29ce72cf166a4d3469ec175f1ecc4070a49f10df3d70a7506ef257b19fe7c8f290379fa9c6cfcf2a032a74623dc84c04aa60d36d231b54d8805e5035a91ede627e6ab617c142d7a05566a4cb8de41ae57d73a55393ee8e1c90d18560cdcda15f4c939f74a5ddf5dc6f67d6f915aac5a636eac27a598e015f20a5e1f2d8b6d665a832771b6e840d68f4a4f85c398cb01b0eb888ed964e8000fc5abb731248b96813ca62d4df5ec1ad2f5d0310377c14f348c0be0f8b1d8a52d34888802f32853cd4fdd839fd3d079a5df76337bdf2dd334951409c969327767ee2f31728e371cff10c1b69072a0c33125bae882f0d00e7bc180c50a7444a1350a248455331245b85b4eb2f592cf8261da42d9ea6261402635f6b0c9a1e79f7525cba38b4eb5aa0be61db1c23752dff494521cc4036f122bd6771e6a02374320b6e03c7a7c09bba4cb1b1fb022c85c9b32568de294c392755040ee9b11f452cd4c5d0f638b8158f4044ddc912ee2d9626bb4334a7498485f5a4ef70506c3323909a81db2f79bd070d932abba3dfc24ea7a89a98bbb78ce2a166d2394b56d237549dc5989ba8d96225f7236b0263adaa8057e3db13de179e4d7608d0582046348c93516ac2372dc1f59ac4140cca7591e45d1ad766a314ea3ec670e6291643ed4a058f5be3c12d7d59f74aea76551b3b25b6d89f57d5c0c3d182f052e195fad17277125cc9eb1f15cba0932f034cbd327a57ed9ab08f13bc1d66b1857bfb3cdb711b0180c19af7de412b44851a41f4e33d47736b03c8026db19413b2aadb595302523995c0cc69395cee07509e7cb4e27fc4128a74d1315d2656e4c67ef55d1c18f16aac5648725f439764ceebb89aa48c0145370d6ab3b13a5439a9892624f0c6f120b80792d24fb6d20a888107ffd5d309ce125e15e004f1379357924b8a93de3b2c784f35c4c4cb609605142b3c577f07ec61bd2793530e6f3da891204dc9f82362f049739bc355d4221f3e42f8d8f4c3e64186de32999d6896cf06c2297b688c9e7f9409a27d21ad5af323cd87b5b9ee207cdcc7f95ee332fbd36dde91827d47cbe50663ac118f228fa83539976bb8f06a53b11d14ae684fd98aa09f0acf32ab6feaa1bda6a89f21708436a271ccee40f33cf52046124ffe8aa5daa989d557839a5a135228245b6aaea02640886ea1467e1a5e07d73c152f80c9e7aa1e12ae041fe57829db63a1212df056d4ca05ccab095bbfbe4be2b469d22ead342549443d819dc34c364454bf45d7c3d2b05d85aa16457844eafaf5cb3e45842bf29c1f58043d8a7180137e78a13ddb304601f6ce24386be61f4fbb082568b0c8f6124a612f63fe342335b36ea9daa84b70493ad4feceaa7fefabe19826970beb913b1881ecb56cbad832344d5bbae83a800cf08529c33ba8ec30d0d0ccd4d43fcb8646c0778a040a54aa163983cd4a63f41ab354c0dc3899b4867cebba1f916f388c96a9c7df28a88d3df47d56576e04c429299c6dcf89f6c8d4763d6d8c008464c3d9cc50fd97ea330a078da74bdedfc937a5530e25df46b0cf450b8973eb5cfdd8bab51e366af05d09a654c41c1af2fa8541327076c7f8ad6725404c938bd5905db8beb9be6bb59895da37c9429a0cbe3bc9f5cec944f9a0ab7c1c1869695adfe71d904d01186d21821b8ec2b71d9b05b38f9294afc64584a8f49549f0d73d8badcb9398712c56c1466364c82c84cb02102eb2d434eecc16ac0caea9f8c5ab39cb7640614b74c5ed3b5122a2c692f0017aeb2ea653b0c42cbb91cd98c0f14cf71cb5acbaf3500f6f27582f6edfff3e802ed6a34fffa13f757f290c1078e21950019b64ed451b8ab05bd1ec3fe2e530e19617247bf45153a04f8ce08735243c191b2932667409ecf2949add4ce8b23a229cc590aba89ac8c39237e5b0322ff8efbeeea1052872ae2acd865e56e88a4a99f48b4a4677bd16e920bc28faedd6a112573e0b668aa63f41ff1e2cf5c6bd9e6001ff08c9fc867805a8decd5f8c61aa5ac71a43550c530eac1dbdcad3be4bb4f0d11d9809dab99d147cf2fd3a63c21c137ec0a4b26e0a6bac6a1e3480b724fb4cbc754d0b9a759190102020b4708add8d74de71c21fccb2128c23a2b2a3b1882c5b0068398184beda1f77436a6df1205f47c4b3250ca8b101dfd712b65da1f92512810231886d48e0016ee131023613345c2a91a97e3dba5a5b4b7eadd499f06a4a058e05f77d59ef31e41481bfb43498293206d446ff7c1746ef15db769128a82b859010e640d4715bfd2d9eec5bc7dc150bd84ab1868a8bf0d7f645ca938a4a10b28def7f25926b8b179f51e237696014206cf2f014e308fa821ef582cd22e267175622961a3960b05729bd734bb36670a337fd088243f0bcdef3e2edca73ad992c202383516b876f9a345463c0719dd03bcbaa1fb737df02a75e2de45889669dbfe8c045d99f1545df04c4ad8801aaa12088faffd4b184b93503909d97c5f2c3152918eea23caa3775a736b70fb36a8c902ec2fb2f18f28d71d4a5fba57db128dbd270491e27c3427d0d6bd89e60acaab3cd0d23f9970ed67f385b91966601f4b09936836b5080403aa657d71cf6804b5a547a22aa50da397cf3d2ab5ec65790bf07201c57c67cf8ccd88a66e101c64efc48d265177da4ff041c43e1590020e6a303007d2e588e4e4ee39a6997cc48f2fc22a9557e697481a3ff9284ba1efae2ea2c59446141f73262e2f4d0243e0f2bbe69b227b4784bbbc0074edd43dc819e166dbb4c180bdc7bd1739e945a5f6a258def9f71809e6bafd9d7a25c8a59b8d0dcde4a352fbd6693426bab8be1646fee6bbf1b92bec97da802e853e37763ebcbab1d97a66664e716330c16c871cb2557b5beee55c6a747e8f43de39d2f9d57ef7b97ecfb7cae50a64733473ba3381fbaee69e6866440d4152b5a00ee5870f51b7884c918a8b2618bc3040285bd780f4ac41e059bc1524971ff8e20917e3c5152744900190bbe27f869124cabb908c4cee7e7f56279f0b56ba8ad8c25a6324a30810a8210816391ea92f9665cf2482e3d5cc62d1c1e227367db2cd8910324425027062b17448400a200a1a0d62a89a8433263648444d1e0f622719f581baccac9722d08913c973a27069695708cadbc021eb30de2a1452d105bd4dea9169971b8445d1b6339cef73d6c6abe3d51c89dc33bc944a4296e2a23825d6a363ae6c768a37404736db15f8c3abcc3759a5639f5daea2a7073b0f3648eaa40f46d4b3c5e36697709fa3e094a22fce8da1467c5be5273c6ad7b01289a17f41b587463bb703123e135a99811f617cdc92c962800434b5c043e0dea0d40cbf8824225205c13a51430f2ecf5f480b1f708f290024f36d4d28f653d95a0f6bd09e04573fd1584b345f0057e9806f58d6457e997c035321e97f0831300f89bfa209a4dac1fd238c3212e203c549e86e3f0f05c587661fd65b9ea6a95b1964a0bc27713644e0d79897d63bf4ef9437e89e8030a859edd6c1ef5037fb2823f899cad9cff57038fca6a4b423a3e140341e0345e74a2f7d984179dc9f9c75b3cd09ee01aba7469e354677f35cb0a90cc10197ecef886f33a6e50efd606576e3ae16e1d590fdfde4b944091b83735913fe1ad1c476edad99301b595abfa355e28de13b6e12229e4b4a7e1376834bc89f832ea7ba79590ee3228d68152c5d232defbca89ebab83f87623ac139e22068888813c56eb686a0713397ba1b5708fefc5441cfb7ab898a73c9ada08505bb202ea082a7085a2a8bf20c584b4874dc6a23418326127aa42a4cf821b8e12dcb6b124ce8e81e68990f42b66589d57a98adee14f576c0540b06795822f679428d643423454024641da9b430fdf89b1c28be8042203ed47806fcc761430c4cf5427daa9539afc3d3f2c4dd2449d42aa9a13973a23e76995110d9605b293d91ed7f254771f65ac365dd6f92c80e5af3ea2014e2fa099b0cad333c70f982ceffcbdc8db52bc10d07e41240d205d0b748006fae5943821eab802db9ed396339bf8d01e709adecdddbcfc2b6f19f142fe2c3c82e49b915f54072828e150d86d26d9c8bc5aabfc34e669873d1a939f0d6c74313c4d455006384bfefd4fe5a4288c7169dad54b4df08c11c1b5200a5621f21f145dd214cd56025e85f63eb675e6a8ec25077181f5a5d6aec3e7cdbcab2083b765e69bdb301781fabb563e37702effbf28d0fd6bc45f588f50396f7ead1cf21337ded70022d835f690b830848bfbdb4cc9e4d150b30925a57912d04e4f103ae4108cc1ce96cad9dbcc1a4d426a109aaa3181cff1245f9334e98547a3f1b66a8420a490313cbc4df5d43ab2fbb811d95c1769cb4b3117eaee02d6622c265d5fc6c579d827f5c8fc61c651b1223e62f81c0fe586fdcac906ee784087f444f1350d71cd327e2d46798f370b63d4efc86bbbd3c0640ef5bf0a3cd14cca9eeab4714b30c2e97f67e5148a8c9c04ab51320a03854465d280ee3e168fe9d657989a4d481583706f6e49a275c700b0ba3cd7a5dea7e66f2e7b340322a5d17091c8752920e6794a26c46498a01203fae00c80d0d0e0f192a004b51130911732e9d8e802d9e54a8ac3c3da5e5ef01831a3bf0626de16d6ed8e63ad7ce0cc9c6fe0e7e748a72b6ff18597e060684f7952b1317c2f59903d2dfc0301c628a6e5540212b1c4855c3ad77a222f780bb9fa21c7aee4bef1a2427030501c1cc9f5e751b40e5fe8ae37fc5a10ecb71815282112c50f15e01354e1b8feb025a3815f74f0be65486bb7e903f52bbfb444f5e4fe1dfee2b7cb4a3af5f00de0299c856329b01e888238e292d5497a13950d1a5b7a5676c01ffd0ebcdf6d82e202d9508a3f1b10cd39dda3938790247caa0429aaaf7a62dcf34d4db8153720fba38197ad9a17e936b55ecc48d0f2e54c264bacc67a489346e2606cbca5937c5abc14d042ff670626d3602d7ffd163b12abcd296ef8faba71f5471cb1e39e76c261459844cfdb8a41ab3154b760ac86151d612c84d037708bbc3989c8fc239253254c813404e75b147c7e0b0b2be5cc1cbd6f27560ceeb0417e7311259e14b4df74c1ddfcbec237ab6f4287cf60108dd666a193dde9a7bb6441eba5aa47c03be76ca6097a38eb0af46882800495194d5d380e2275963ea5c6e6aabf5a304104b04968183d1d88988e9b31557be19d5dac0283a3467f41834b1e32dc6e3808d593ddb7db3a5f1437b53cbd8a7aa78eca0dd527f3b3640dd8f24bdcce7b6a4bd3df4316fd423c1214310c06aca7dc6e7047d9031ba25daf62f07e23b25ba31403d5bc1262c90d5b1db772dba3adf73496cb5e07a746328605dbb8816f5f3b62ed85ba02bd9d9eac0ca6311a70557817da1e8d92b1fa986de0d352c7b29473a8b7404bff011ab4a706655fe29cce655d92ec4b6a3f1ee2119b771d9a1c4428e660f64fcfb4bdf7b9f3613fdb239827477bec69df75295b0984c661c393a8dd71115edc47310310c430a48b4907f1d41a4ecc7a0b1604b9b21dfca9612793a9189177b9f226776792789760a1f7042937e7fb18634b29124da5c7e4abd5ecc8040637364193fc92836b6c8f6d9d546ce77b3897d6c18bd72142d375a2208e783cd0182f2831c6fe90f10395388ca61c7b7b2e84200e204a21f26c166c2e37dfc1058ce2f39b1e25e6c0791ba879150fbf2ff6fe27f8707538815bc5a453ee9918f057e41412fb6823c5c1e1b9adbca62edbee735bfa9a3e600e81513786559d1086e33a5a358ac834ff7f2f8d4d3d25cd56ac02febd4a43196adeea8a9bb53678c6ad38078f47e1217090ab8ba42b0a084a654c7fe7139d2fc66b3aa98deeeed0c3f798fd39daeff78f16952e50e8b68f65ea84594da1fce734089146dd62f0cfa0613fb07053abbffecf0a8bff76cec4208094feed04704be96da8796e60e9b0d4fb28ad6d6f09c434769f4ed30fcc4a2c80dd39d69d603023e00b93c7fc6abaa0d5bbed4d84307d332c6a9dc217f61995c66c6d4597339b1d07178828608d2518d4170d9ac098cddaebb7b0d72da7661fe0821b62f545eab9cf91e3add1b0c382f0003e950c012e4283b735698b46d5c95c09d6f55446bffaec00b93a15c205ceab8df8b5aa6f4306d16a5ad3ea0a0659f809e1f45fa519f1703f665c8f1b8fdfb221bf546313709460663ccf21da287bc68abb78324902ce57bbb5e40a97d70f2cf4391a5ddf8ba9c652b30646a25a05289c5b242ad63063468d36ddf82415fbc2396240e61aaae249711f3310fae08958181fd73bf6600d1c5a3e4266f10d89e1ad948b755f0d2e695f770e343316e0f85364f0fb250b29977313707cfe0c01e7fa6cac61378df044d8750a6b9d5339fd4118fb16e21a404eee90f0c1236e8193fed2af6f5c65d8bea6d79ecbeb602fd0bc8ad59147dfac2d4ecd0c3e73a4cce62c589f3f7d682a871932ccdca631ad0e9334f87ee491bb2ec09d60a78c4d4036c30c97d4dda79be5de426750c4dc17e37be64f7ef15db45d2a93106f97c598b77ab321eeda01a5978e8b47d868b197e860a5a7d49eedec9b2f78680e1c93cfd6af3e08f4360d90d2d0b946dc955a8e8801094ff737ab6776d9206a1d070a684d3d6e5471db15a47c6c9b989c79a378077bb96d9e2e16ab32a714263d36f57f0822b131a565fcbbd92689795485bbfeb92301f7dbd71bfcc337bacb8faa5103084c2344bbd42ff9a7a9d7752ee08eac01b07124616312fc49072f3cbbf0d98ccbe694bf42a07323e16fb4782c0653824852cd2cabc93b8908744e111e93f73a166ae2d79241041f3d9d724d4b6c57a5c1f55a01793a76f1bf3a2612f1bb66f5777cbce26580b9025307d049d56a4ca45b40a148a863565670174fc2e46f01865a1bb1c1efc5c4ee6f3636f0f04d310beca36861267017b5815fa185cdc0210b34dd6dcb38036112cc341bda1e4c82e707715c594f4a3593cc520fc30a0b691c144d5cd4868e31ea834957ffa58cc3b9289f24097ef3db99a4074ccd8de0c5cfe8105abc5c83fd3f529f54ba82110c85d6fe4f7c0cf396d0c0505eae54fae778dc1e0255ff768face03c5c5439152b79509f416961d30ef5390da12ba2a2b9f406f3f5171b2354592036291007768eb1d1e617a611ff79c42b9e9a73ef103b0df66c84fd3643c90732dd21932d04ab29e1af0bee56bfe8ceb993771ccbb1c040fafba882dfb30a0db4e0128e9fee852cd3578833d77a923b21bea87c7ed9cccfc34a7caac753dbd89e7dbdf26fa5795263b227187301e21ff4cb7eb52c8cb7fa0428538f4cc838d116b0293e1665ba76990e3d58f0aa600e25e8f6200dddadf1c1a886a7dc75fd62bb48ad4e4bb47aef57b950a6d391ae7990fcd250b76229293ae8a9233842dc059a837710bcc93592f7bc95429a033324ac7c8e2e087a2f3633390ae6af12536a73df3eeb30027bedd95384d10920b404371c214802acb7eb84b94488c18698756e43902f0d4738357d8d8b0f32bc744a0a4a234b044fc036821e495fc17027bd6680d454f68de1d191dcca80b4290f0a2fa6ea0bd8dffb88646ecd4b8d39c47072694c6b05d05327d995a62ed5a61f5755a6051273b69c20cd4fae447be0f5337c2927db694427b28fbfaa5f4a3155e742d728a26071abc4030d864a1b522b0d0e463b40e5cf404d86041d342af6beb57dc38d4e7ccb3662c5f52d03ef24769e0aea68632b68d335ebaadf362db4d1bc01189147bceffc9237848f1b1e3543eca0269e9adb3ec7e8042ae540995722d946968e3715d67ba93c0d4e0bba8961e547af914c338fbedc3320e185b8aa5b401236260cd7b32ba7ad2b88fd437ac2c712fb5ae3d956b8b3950175b6a3098b97dfe75312cdd723fa30055579717aad30a05fd6556901cfad59d37cb093363f8c69705c8870ec79339c8f82525bcdcb75b383b54c3fa1f3ca504100a3c3b15e9a0f014b93e4a87db4b510c84a3dbbaec04449f117e6bb37200d0056376e89b3797d81bd3337485a5d59c4c8457d9ca7d366866e44911ac5dbe7ec5ac58c776244ab9071c88e5fb6f390bc644987b61c537631085f10039635d0be8d4a1f88e826d555b64ae1c7c23691aa338f96070e5fe297d7117eb8a44b44e7cc3da060f810828126ff3f6e0a4643f80eae3c97278414268241ca2b42c95a57acc68884b21eb72d15db3943770e500974ee787874bba52dfa8ef7695756d5a89dcc3b2e11bb974601078d8cf731cc0e08364ac3d2196037c1dd817704b5fc9590b23210b07ba259ea0b40c7326d69c90f8c93e698c7ccf0fae5e40acdf0fdb3b30918e250a230343ae04960fed7b8feee06f69add5f28ab2f123d7800ed3f89677e13d4fd067c82469f9f1c9c0e3044dc6ed58a0c121f20e82ec0c1805554091f63df2f34242bf031809f2be308b04d15cf1512068a3ecd108c6b489ea6a93528c7df765cea5cca263a02fa57a9e5fc6080476d7f21591e123f8d4edfd1ca52f1ffd91c51a10e3135cdbc3f72d27a87500301629c2dea22edaca1da655fe56d5418593519b32084f53c090b503fe87438ed4710dad429d55805cd6ed8fd3ecc9e3423bdbf4df06d8ab6fc5c4547df9f0050f3c52111f48bebf3a3835ae962f5395a3814eec10f9d0d1a2841ff83e9b7e5ccc28a9944e40773deed13564e434b12f5ece04c7e7416327f82f0c984707d8371b2f6a84e8aa95e2c33e75f41103167d93a03d07c94ab37c7bf92911e406166b7cd0756caa1b8f59a0a32ad956468b8535ee0fdd594b91d0e8f97a898fe4e98a3ea5f6835be92b49b51a93cb9861d24f0367d66f7f72ad418122621f0e6e59995827b74a2dddd563db1e2e3a15ea94304baf832d5e8c2f78f364abca40395a4f02b9c9067d3eadd950f4e574256a679d7df62b1a5dd3a10fccfdf76937dae903ca255cced5814d0e57a64b5455890aad1faa255a537c427b3a379b3f75b1ed11866514148c4754ba3e3ce6f3f25cd37cfe49e1c513023fa490812b691885b457e5a9f19039e0d9cbd4252760ad7ec42ee88e3cc11202f1302e0f689b403448ea8942328b888738b13d5869158abf07e07a2782ce5be339582558611653d8c367a54b531d4ef8416171d02502fec0a1016d5d7c28c5babd4f383a2f30f5ed8d54cad9877aba420a6f1e85ceea3b9456970f0012ca2ed4d26dfaffc33967b15f4ec9e242f071f4e832c4955dda1e259129f1fc86c5375280e0c990521a0f0d3fdc4ad20c5f93528d9dbd602777e8060ec0833754334e5553803bfd400fe1df8b87fa99f4b6bc9d64e6945792a7445ef0b95ba813d78d5b6000bda1d44c79b9a788012880aa1f50debd13ee99a133861e02cbc3a0e23f3b3d3199f7f01b2c9802a31b4e702e357d834fcaa34f3cd5be0e461d8d4c4c77f5e0288f272ffd0aaf91bb9049d0b4dbae5c9c9f16fd68125d52d073023a4a5225d14724c091abf101a02c748fcfbbb0045ec32c1aa07528b6e92e5dfb474f8f8471a5f9afae34e44b4650853d56df1660bbaf478c97d9753e27d730f0b34c1ee651ad0f3e75f6a88a92595a4a4ac8887248f1222b228f49d89a56335a649fdba38dff095e676af22bb01c2507ad9400c80c9bb901d4df1a1cf3cb58f71985252988f0ed6ccf54e135dd00653a2092c34d43b08029222c8979561f0aacd873505716635969db7744be8ece43dd34345dc432c628310f8edaa62bc98fb666e3d789ea461d53009b94ab2a1c0caa8f3991b25cf66a8a0b673d80dfcc2aca2efb6eef3456e2b37b0dccf0242b0842d5fc8f150a937ae2385f1f6916f984c250100368f4ab0496effeb587458ff8a72e942e689c917f3d65366846fa4effa4f0b207680fb4f596faa511c6414eeca1303f92d873fca2168dc7da8d0bc5dcd4741b5afce451c907e3b9f2ea13e53e85b9c0e994bbddb7de06a912fe19432463804d520b967b86e516a19c155b5118664c793a85e1a6916dd31ed93b2c99a55f281a88b35f26ab613252b73806d882ac68b7b1d12dd6e644111e4da590a59e64a86f54d0f92fd06065de8c3104c3874d135cfb2c2358c82ed28eecdaaa2b4a903bffc95e7c90cb4cde8def3ac4f4d638ae2e635da49bb25ce660c50f980090ab854c7823971f60714fd5c8e8f2b5ce11e09507083e3110fa513f0a3aca5d1453fc22331a09cb09a17d57011fcd6269f58e53a5046c30977e21e99d031ae10700d01c301d93aca405f98356823b19ab9301c2ad0a7845ff95ecae6d944dabbf200f3fa7fc61f46384ccc620449bd2d48fcc740a4dd6546b668818a2ef05939d6f7bc2770559df9a33e9c3f4971888992309639115f638b2bc5c421dcfd03fbe07553a39fdf48690c6d15ce19fe0978ac1ad1012db8d1330ecb10931b7dadcad963afee1c74f64cbc6b639f763ac357af0c53565affa8f3518b4f2e340cd1a886af4f49a2dd6da50b0923a3ba83d89e3cf7f8c458b9d79ac2f034c712bc9583afdc760d54586dbf17520f1fe55e8017385d9dc3e9b888248a048b01bc4049b8fbeb239e6186b5086134f7f9e1ffce755ee5aa2909a632c3af63eb8246aeb996065ed3cd313de9f46a4cdf1d0e29b95be827a3027ee0431ddfbb787f34197348af03d365cfe356cdace8136de85efbba0e322f6d2171f33b07f1a1abb7a9fa4678bdb7df2dff50050d85c13da2749671f51c97ecfd6bdddb0d7f5c816bf531126071c1e16481961e8e312bc31f1f43fe170919008939ac269722f3a5be4bb083cd772eaa2706ebbf6448ad55d4701aa64169a1f14ad8024b9d0dcc63906e4c08e7df444f93077ff4b3cfcdfd685e193dfbd22c40c4dfa9ea58d6e3eaf8cf6c76b9d197d8a8b16d5ba638b642f52bfa620b6d2bb07363bb04ac3f61afad99a04631b8c9240e49e5b5f267642bd3ea3306521b48d988ffa4924da59f443cc1a033cd735756daf8b2b6e3d765b91405f17a25ca1ca0f61a3a5afce53c4b04884766a0df4ae36febec89e60886ef3ba2ceb89fad233376934840fab44d2d1b7a46b17db056ed6da7932a8058da838936bf462cfd8fe430eb890e58b2e3028d74ea68639f22bbc9541ffc7a2f1d0c5106e2f6666f8c9a78134085dbdeace37a799447f2c5068d785d6c1640fc2628b0697bdb3f9a75bf8fd66deab9538bb6e222423db7db4a941e8cc4ea8c22e09e213f9b8bf6a32e504a6c84d9fde3c8e86b6aa3e7d80a8bfa60e6ec80064bb669d78111010ab5e55a5f3a6803c03229f3f5059a636e8572ba2dbb0d3b3454ea035dd4393b6dcde8ae5ab3ad189e311bce02d8c36ccd71c4c1313adb16b62bce5a5ca0677da411d2e0c92ba3215294db15b8f9231f636f38e134e517b0a75ee4d48b5b693f606266db2998e28c4b86f8a2bb0831d3493a846ee31944adfc2b80af2a69bce00126b4f48aa2976eb55f4038087461730b685be3904af2e42c1004470974b914020e0450e30ef298cfb3dff44bf4f7633ac2370966cfc626a8c400aa28bb24536ffbb51c028ab2b9bde92267b3a285c8fe712f3e292bc8cb8505fdaa674b43924c3921105b8949a642cf9ddd2a3b3a4c7cbd1a87fa47f87dc297a710d55269153bd6622810027c95e5fe8d4c9194e44f10c305b8bbfd4ad8ff02cf890228937cc9705ba528c4b229154021c88892f769f2a6f3202d1eabf32c12eaf6f413e63fcd557dcf699b5466dad9eac334d0d11008ab24de9d31bbd7f247a70e21018cdc081e697ae603875928df7cc01bb73892897e7cbfc32bd4c2ed3cff475364c086eb747566eef6d7964b8500954d3634007e9fdc9e3490add81c56738ae9ffa4605fd1e2bcb7b018d2860c84dcda005435fa3411a6aa1ffe4331223d835e6b83883a844f50fb29ddf989a47ce30b4c9b56a056e038eb27701db65c9daa9babd86233e7b88e817d9334f419bdd8439ecba71861049c4dd769a56349e883e0810cebf6236361faae9682f528bff3494a9cb47c78fab112db0ba207e9004838a57191a75457ef66630678fa39256567b35cad3e608b07a86208ded8a21de342f1cd31b17c4f5b9a7f659cb8feb7eddca5a64d66312bcc9b60b30a3e0e8679c10b2d3f380285c9b63610be3cd26924f1a159cd5852269962126ffd56aa3d6e01c08dbc5dbee58ee467e672639e053397dd9778881dad5ce756bcb8ed905e703fe6f6b4c5d186bf7f3772c584499b7ea4716c82b1a8a413a30d0306927eda90d350cc7beac0cd49baf1c2dcba141d19d198a322a7d5b50d0920848fcae76c4589745723d7f01f9bb18d752462eff3025d38367a30c06c63ba81aabde36d5d261523b67d4824c80faa5ac92a32c0eb421f6782d60e8330dee0d60a19740ebe046ca21a8fe589ebd0de67a20f3e678744154b62e21b011c6876010efd3e956fe3d769c2aa17d76c73c240ca1d74344bbcc0351836b16dd08f69c9ba05e828140613dd5f89011b60c10ff0f42941cdf1820cacd508229954fc9f1a51520846edfca91acf41aba84d24d88285cd8c2b771a8326e61ce534d1a1d8f3e75431141b421407f730eddc63699f44cc3e6c507673e6ed6df0f2553e81784b136dd4de3977e4250889e5d87992e81983f2fb359e743c32891771109a7871184f3051c01f9cf1b6ff8355311fb30f03efa5ed4a0f8caa058e030cc7d45c83b63b2e865e81082de18f0ff39e0e3070dbfd9c8e1e26b68d51fe739e6af96564e7d8810ad81de21e53c27f2d5d4a766cafc3bf6af114a20c138b6bc1cf6d6b11d0d0ca80bd152e04f9534bd2075b5a95789af8be1e70ea3dfadd91f5b1527e399f3fd798691454fc3a85a6190391d041dc7c1d6a08d1c569854dd447596d753fe904162237ecffc7d9db997d8829da6c56ab8054f198c921c5744c586a0d4fd45a53f46c5ccba1262fcadaed8c07d22183b9809a205005f54f285f281c251e500c08169e8cea853546243994e9168745905465f939466073a3eb27f78f2cd7ba2dd5a1f8817c094991d7fa419aee7dd1a386fe09ede6824d0befe0dda93350c44eaba78d904bd7ef4d200bc393c4cf470073f47f15cf2a7a05c38d4238e8535131a25e1bd9ee5b4941113943c1b28c45d38dd3e7d04103d9c01584479deb58475b5b879cf69e3bc305c97c8c4584b83b6bc517fbc1be0d6d7f68b9edb3f0c9bca0237146d49b90caa8205d09a09e4891e2a66a5186781750c3b5e001fc751103c57485cc6788b51459d06a454b8e15a447701ea19c7604da250fc4175a321ad3c74cacd7bfc22ab1410106edc73ccba0fec2b626bd4f76a375c86beb81a4df4d2bc35c5b24481c1e8249b7723912985602b9a7c26d927dc1f5233e3ef52712126dcbdcd088d0c5e24e70c26c9fb36aca0dac8a3cb2359701a9888b143b587d70671ed17f643cfc60c763f48171d6b4074afbf2c97cd74ad8e2f7729dd1091c76133b00aaae3b95fc9054ad89d7f7c11e6683bba9fac4869970a90717f7f1d59d0eaf487b1a91758c6d128ab93b69a1f202d57251a40482e7dfc00f3670b5004f5f152d2ba0844595b8fe289c9c156371c0ac1e53b24bdbdd3aea767d57faf5e4d9d9e3eeebd9ddeb659fecf397cdf63fa6f051da07edb9af96ee6042b9e3f49fee26fe9089f226ca872a85df374a4f96ab077dbb862b587d3830cb84913483ce1b275c0eab718141cf516ed5a5d8af9d19f30ed3b8ebd2d236a292b0f7bfa50cd02816089a4210bbeaa58e9216d56feda74b63d9c11f1c3bf1b42f34fcbd774e393615170c0c0d72fcfc2e99302f706287e9d769ddc78fdfa5e7e8d8c242274bc64094352d1082ff7d2d428f4ade5e39f870f5e6a2a3bf1f88722f8ce6bd867707a0b6a1ba6f653f6ed0a324f2aaf1d45e8e0ea76773a4db6624fdf310d7cf0a4c8b1757e0133e390d87fcf0a034db6a1aa943ae0ef4c16d201fabdc5991c8c0451ab1745a605088f48369892c6e892e092ffc38f4d7c00a5e53456e5bf2ce5697efd6557fd2689b7c622703db4c17f724fecdf504c603ed83a125687216c00c91cf7b975ee24d2124f87a8a7a4401ddf8a114b2358dbdfdca32e9bdc56bbfd9c836116a4ee567b83eb3a91e88dd224e11180ed4a3b95e3912a13112c2c2c979ae8f3299ec0cfeff74a6c0ff82972624f22832aab47ad6e12c69d0cf019e788cdaa659f4f71560f10eb8739ad99d0271496841d8625d548f14195e23d6571a11eff5233a4d0ecc2f2840a7c493e11f73e6d974dcf0c1c170eb62c85f6b529e1f3321ab53cc29891c194e7ab7140b8a5eabe40ef9195e72819490fe0834013f14b59f87ca29d5040a21bddb2b36797538335255a635f2bd70c75357300ba137b1d358f06de8b4546dcb1a6d13f758ca802872a02c9ac4106f492ffd5056e96810c48335350948ea4ff7ccd724810038b992d2674e62c779526f2b8e9924dc8fffa7501bb0113cfea5f626f62d79cef4826464ac75ee310130cd32ca0e6c76f06940d7fcf9073ffd9d3b4e9405abdb8bcc8539d05434aa16c7401b1dde881e17b9a4a6b9490d05984a480444289397ca95fe65762a4ca71711065477d4b38ae885df7090a234d87c838cdedafd1eefe38c8ad13fd7b5471d0b47dbc2513fcd55d0a6d19de69f0421282e46d91830423d843258602221a7bc990dc21c0afc7e9c7d5b156714399d583e843611bed90cd9388fa1592e4b06e503d437b185b9eb91ba07b0da972887999191cc515625357b969f5ef6c11451d8c9f0191c63604a74408c8635b9b6fa6a095332ec9c307b3aee8d84002819fbcffbd8ec0f3a3b1a585c7abaf8329132bc43c031a1dce6b5c40d619a7031ae9ba9584b180e3d43e9aa9daa9259fb1537f7500a1c50eb45647d4227e41093298248b4d7937b7a8e6c8ea26402ade1dc8322e5c83a42b1e6e18e70f42ec2cab31a608849b9487075cd1ff908ff66e6b5b4a29534a29a5068406d2062bd404294ed4156a0207ead37810074a6afc21a12035763fba5ac054bf1c542a55fd61aafc99c3672e9e34feacfbe24fd8d500bfabfce2cfae144fa620a8fc1ae07bad213e6daf69c9948328b502b4de10232b923273c47abbc315f84a801df4b1385db9c301d67e1f8bc3fb4209b4476a2b0dda4ef5d30bfefd3735dd51a9bc20d0d845610b7733775d36026d5bf6068fe6dbf0fcf907cc20853226baf9d836f8a3bd6ea13f4606627c805251a4c48de7b96abf0d8ffd7bd783300a5a53430593dacf428e18806a5ad5b11ac3233e64e678dae1281befa86f814c9ff72a1b315f92c14caf170f514665b2d7e643bf8e998ca05ff692e2ea171ea03136c5dee887bd3ae6369bd3450e54fbb397abbd8ef54008842655b551fdef02fac2088daff6fabbe88b302a82d4fe48859a686884794ef471d48a13bd49d515b428cbb205e2673ff59001fdb22ccb3a3ee24de1b26162a06ea15fc60594b6d71fbbcd03f225de67324df1a4f6cb6c5632b18a08ff20bc7258908463648101fd4c3afbf0ebd77e198f3d66f6161e3278d2ded6cf3b6d7d08618d4ce4b6b3213fd352fe7e53a9159b5fa23f968403fa799f6782416c740bed7538c4fa0356e7ca2799af3b0424469084a552a97872f69740d73d473d909b18f0f5df649a8248ed973141eff36a4a330b29b1d8d73197e4591f1f2515090f333333474752fba1bbf7b4d0afcd28519b67d01c1304fa491e67b9cde83be3894531b71975f18a45f5673c643ed4ee18ac7ececa62108d0c502881606728e86156ffc498f4780a3ca0419deae9e9496dc73ccda4dba75b88a104fdba87c787bb87081f9f2449f6467ff7b40f13e8c72c1e47e24978078b9e1aa309fdb2ca5bdc81168488f8423e47fed2f432b30cdcedc378b2d15e0bfd2b4828771f83c7746b362304fd32ce90d4fecdab79c18bf1a29fc946a33af3528842bd854b54a61c62abdaaf434665b222e8eeeeee2e6594534e39a5ec5ac8628040bf8c157fd0e42fcd1763158b46f5772efad11817fdba483e6c1a3f4a63b5bfd445aeea22aa04fa511811733a5beca0a0fad16eb5b6fbdaf5d17efd54193c4776d187b3827ef1058bd91663b188a5261aea2d53b7d0ef271b51d02aa323d08fb6dac5ccbb0b574ad57fe1c2850b77f9b41dbb584a0fe87ed659900d3904d918840fa5b417859f6347689cb3343ca01faf6a671faf3af5f5aa573eb5bf89f0918f573180687fabea97092d4952f79b6709acdabfc325b48455ed578014b1ad4e1eeab7d56f838210017f693c9aa70a68c1ff5b40bd5b274138529bc74fab5342555af547d70ac025b5f038e2090c5c79fcf0f881d2a97e3da95b1b9084a853fbc4aaa76ee5f103c53b1e3f50eacb552043e774e4a9fd3a58b86fe02daa14acba42523ca95d5d212978eafb7ba5271b48183c2cf2b4c34ef5d130ff8d5de02a85b6345ffb50f195a9a84d398a0a2380b07360f77599a6a25b778875148c13b40f4b880945425578a828aa3fbc328e10139650b9a38b732363b5698b166baf990a5369afbb8fe4deb12059d5151f1eabfc2bdc0c6b39ed9801d603604261651569716b396d6605d52187f67a4256b53c3fffb04d36c52b6679e69567e67fc088190ae3e867af5545d4b567e11f56cd918a3609a5bbe7ba72da2a7782758bf15f2209d01084f6f0d19ecc7e3ca7c39d0d3dd4a51035f9e7c0a792d396538e18b6f6805a4e353735b1e5f45e1534fbbee5444f5d159ab50775e04629635a16413d40b480851e9e26c9373314c700f30b1da752ef4909522a7d5132d1f6bc06331de8b6b79b3bd315b44d45b4db01eddfcfc73ea9fccb1d034dfb34d8c1f660d0b653be4c9490a402a0ae10159eaaf906659ceeeefe0169edd5f0f3b15848c838e0bb26c5b52938f4bb0e1d3a40267b0ca6f061717777a2042cbeb0a9c31a4570125eeabc356040f7d979b8f5f1139597872a0efcc4880ae7013200a21acc08a1fbe2b4e464c5c98a931533436686cc0c392d991932336466c8cc90992133436ecc0ca133436686cc0ce92428733b8cb061f66d3b22c10d723f1b4b34264e0984f0bf08a10c84bd10b6172becf666162f96bc904136777ba13b12f1dd612cd1d28bbb9bb818bce8e9fe820997dcb923361bad1cc218e5fc9973ce39e74c325b30a39c997b0bb29111941767495a8bccd3947c94342d6e72ba60dbe27331c6281d4ea6a166194b295bb022bf8eb815e75ac0390bb5410e03ac8d06a36bdd0e275a3b8ea0271e33c06ec78b18b0d016172dc7015800e4f2a26ddbe94f26d38817a704d3c2324fe3a2c425a0865229beb8c07038e8c0cf5c6899a37c482f9c8e9760005261882e5c7038e8907e3e0acc4cca46bf52d251c682c82c2b2898023b8c3eeb76188d3efb11933efbacdb217b5297e570769a3c8e82117ecc94d127cab0204481940a218410420863f4e9d43777a212c8e336f3c55dc1aaf1556002212c45c89179e23ef7b096f1f39c3c0a621672420b0820216c424e78c294bc62229df22435f6f0d1369ea3e2c7d9718fe74cea4d8d7c2a558db712236954641e940be8b7b0ba5a5521b2f2866d91e4eebbf95f2039b2fbbc5a74c5e2641b6fedc58cca5349a6877e266f5681c994325312d90728cbba793ac5489887c7477bf149a76d4f87c60df6ca03c9994fdda6df9fc7f62b5bb77d777467d8a6813bf968542c6d5b0f168a40791607d6f86c02b95a1cad46988c391c15238da320743bcd00e315e3100a902451c240ae18b3d903283ea1c61efa67709b1c918791fc80cadfda833ea2142a232b264a1644434686927c4046ab56bff8db24b30e3a116d693e173fadd60f27f133c5c54776b8d545ba2b9fb8ca31be8291c04f88626f14316c72943d7bd5457ed885d9fcd3737677d74f2c8993e09f2ed22b153cb1389c0079cce1ca8bb6d93f4a10b994601b9e42c46dac04a37e1ce53f3f4727e9d9f6240cb2e00760517e88ac16a77bb5518e20aaf3c4d53ef58e0f7bc31f7e80551bc62e740816476b400824b870331428cd2e7477302fcd1b02fde20e10bb8a6875d077c353d9f4038daaf62ec09595fd50e61fa2267a66c2ddfcd35de4796714d8c55362d72fc6e1bde2296cd345fac5adf6691314611b968251de2f7681b9f3ee05eb805b3c855d2c45f710b10b5d449fa07988aab34f9b6aa8b71304e3b8df7e8795df9e3bed40048f95df7e07fadc5328e856dae940040ffa2bbf8efa1220806a838f58e553a0d40db1c30c4fbb183e8fc51cfa2b14d6c351eedc6f6f8591bd718ae997bf3dcb6b311b0c02b24e9504d5d726ee2cca27cfd9b399f908c8c3e2581fd8826eb3c5a008f40361ad56dc813147451a5ad00fb24e35f1f7bbb58991048cf2872c762176ec621c91046cd32ae85ca338522d0f12ff98a453fba4055bf1a753db648958f514e47c9149750ea8099007ea17a354ff519408e04de3ed5e91444e50b537a6d81bfead02b6e91a308a875d58f1b0386ae04ec54bad5068cb73425944a9bdadb39c623229f468931e236dda12344302e57e2371326cceece9ff53760e83a169d080c29a44a553f23dc6186565e35f2052ca51dd4e496e5b696d651bb5701d8cb90cf4577e3bc574c783762ca718aee395a3fcb72ee318d0fd5b10746609fac59d2b903822c51026980115b11cff1616d02fee4c98a2ea0fd41e93f63ceeb038a140b33dd6a9c8d35e77f1487b4271e5282134eef84ec3fc9b012ee507da27d9ef2e97d2b086cd6e8f79915781ac956e968d85858bb15bbe703a7860b676d95892a05fdcf9b8b3f259dcf104700dfcac83b7a8f2e7ebd83abbd87d3c79886db575fc03c42409fd1af6936594966225181898394dd4fd575c7030707576bdda1b5dbf96e11452a8d3b4ad3a65849da572c15775872c93c95b79eeba8e7b2a7392179cce660465985701a4c56c0cfb8a7c18f3c4352626663482397bb672ba711450cf2e9078ea267bc35f9ebab537fc6370307095bb9e6182fa6f140ae57e2332c304855ab731a7b32308d71541d410540ff4832cd8aace5a9c9644160b0eb284b8034f2b573127a0fc6229ed793c5018338c61fc72ce39b713d7cddc276ece395b1e832ab8aa35b6e560e851d598999909cab0c589626d620816e571071677fc351a9ba90885d9591c0284606d1ae6a89dc55953117405d56126a8fede10e807599d5af947238b13739bed1d16557fd8729be601822cb771138cbe5ca6200a047fb28c527fcf087187e280729d0e44f0e07efb4e8714369002233caa1caef31cc5792a3ae3847ed163f548a7686441f9487bfe9fc7aaf3b41327963bff66625336d8147ce7b66b1d78b07d45f27877dfc83483d3c1d968341a693468ccb9ed7147831b7d8e962d3c7e90b4b735ee74cab5a8a30e1aa12f759b28515473f476da798a2dba379877dcc5a86f20e20a25452e1a10315a2d8535353554ca1af8bf6eddfa71178380affe5ffdbdcf9fe6dff3241138304509d5ff3b03dae26c7b91d3d10fbd9b49a3ac6a71837b636794559b9b8cb06aa32df3aa91b611247130f46bdba679154f5bad376776667698c321cc6090f6f537a94d6a3f437767ee06aa5946a9c95473e3bb40b50b506be85eef8e3b5d3fae1910259c6c139e92f7a626001e0ac812dba442af4022c3226d71b65dd69ab40b4731eb960da1cf6e2967dccde06e6a73e84f6b37a977b7dd34d2881bf50085f20f0b7585ac084251500d31fe4f5d3733434323a39b399dba6e868646868c193368946864c498799a938c6ec60c0d1a4f06aa86ac116bd480356ad4f0e61a356ad0749b8c193c63c68c0c9a193268783266cca041c3f350a81a3500408386e7a150356a000000366cdcb8515383b251c3c60a33b6c0d13858e7469be8e6834f2c45a0dce108800006c09365c616f4dbea6e775a6185154a2bacf0b2824b0b6559e15660147f573f1c2a770b28c22c3a68208c4900fcf8b0abfca3b35ee65f1d8054f8637db979797777797bb9096d6978593008c469d4e51640aa0e0408cbb5cc41f8a3a8ee10eba7f6d3ba43ac9eda8115730bd84e2f7f9c863800ab3b04844fed37d51d0262a76abe3990dd16537b0c0357d8de165b6ca14585694bf3693b840cb73b84314a39797797b30c05231249d3b68d721cefee32333333cb364304ba6ba29477b7e4dab6b8b8703a2c49a0dbbdbc30f3be944accbba50cc60c142acc807e5f1f88a651df25efbebd9921d0d75e9c15434576726024074aa648d162033e8b031f3050377630f0bb5453c5a28956eb89234fb89e2092056188c891a12a2d2028988c860cfd70e489941756423ca7879943440554402a95cac8aa871c26409165d9cb4e072ffb6872547fd49976aa06ff258a0bd85a3caee99bfe03ece8176a43e76f2b75a7f85f1e1b52a2a2a9455092453104130b9d82b1ff866136f3d1546f6668e876bcd07d1b94104228b76d93f0470521847ee3363d6e76fcec684f3819628f133b3b3b719b1b0ba451cb51fef05bda7273cf7519d78d62ab8753cdb647f7b0a908ac47437bcc517ab8cddc591a3a357d3a029b9a464c097394119b9a4eac4fa76650cf1fb7c968fc19c5d1488e648c31caade31d194992441a914692a5cb27ed0575ca6bcf894d01603dff1b00701218ac60e76327d597546771117bc3b78e5923093392c6d9c62cb7e91c7fde619fda7504b3f79faf4934619d224999653de3a2bd83bb981250cd03a2df6c91be7fbebe49c49c650d5f3b494ea749249e93946ddb0aa733fa154e076e23e95d41bfa982d5a922d2a52aab4898fb943059549d7758a250fe245168771fa744f571fca46f1d52b71ca0464e2d1bb376717ac645bbb2a8d08c456216d7d3a9d1fb73499af3e9d454c2fd744a32e954a6699a16a3b427e164173e01708dbadfb1ffba0db31645331436fe6f466aaaba29c47a2f363585d85412aaaa53cc9a3b9d92305879aaaac3d98210ced66c2dce1328b416676d50fd4f46a0f0358f5d276cb6a66b4a99af4934b1c856fe3336ab6444aa7f84cc21a07b8310460e7e9f461576afb0d3b801fd260f87a45badeab3355b527234f9e408c91fc9f9a39306c483c463f4b2d38136377334961372c36de918788c3f473f3b1d4c2308903eeb7420653ca0fdf1e443038a35e4f433159bc150f1c1032f47d0adee900f3e9480404775877c50b9f0404975875656b81882caba43abd80a36a4480592a38f7e14b398c52c8b5954e1e56b26d3322595f9169a17faa202dc381d27458f32a6cc24c3351e7d5181c6d73229b7e55e007d94754308bb4db0b965842d235c39121942243cdbcd3a2abbf528258491635cba05316a79c1efd598a0c6ed304618638c1146eeae8c468a114a0dc038e79c114a23249c31c2491a65d188481a6549c0d99364ce39238449c09e241d0989495a919bb6c242a96c29024ab8694b29f5961728bd085f229d8c7a5c5e9a347a29415fe29d8f6cc421601b81b634de0e258cd2e3588eea9b216a58b1636924f9d16dd429437acd0509300eee64a2271b7cb4f74302ecc204281638357444b283d106e7c9d188c4fd2daca6470f580f79b2c18724c922285313c7624441e520de46cd4d910eb0824c4184779a601e8410e15765863195a10cf4a06aa4511638918782f0a46e78d6d5830c6a74294930e25d154d54c7404ff558d5785681819d2868edca5b85bf525408877800823584c0a1df42055b6c51a14ac84404fdb2f52caae840d112ca228b519190511010241ea84508361da2222d52b0e910413564484811c907f25f561003a2ca154950af2b54050684a822033e5441440374a5ae50152060809098a3b64a99021b434290d4f825212b9aa8b0ee90101e3fe249164f78b63f73709e34fe09bbcfbb1afcbb6e9d1f7cd94106c4ae067fca9ec9642a519d8c0844602145284a952150a915c8ea0d2c503c8148090e4451451b6d8c0cfea37780ff68877eefb6d57599a3a0c951f0d751922787dbec301a7539dea30f134cac179be0fd191ed01313778b9ac5e280bf36daf36a58680fce1df842c31bd2fa937c9465dde6c44e3557b3a753df644d9fb9337926929964fecc27b33599cca01965b254d3480260e5f1d3ea9f2ab7711b7fe8362a47c5262a6c62bd6fb22adcc95a0ffeeeee439811eab74d1c204710ba63b4a3cfde01a4d7ba1d48d101592dacc55928db633210f31988c5e16ae4c43b36a0dfc27ac060310405052dd9dd65d7b28cb3cc336766661bbc3397b2bbbb2c087b98b5738407099320201f25307377c8ccec5b87c3a87eeac4f76f4e04d066a6d0aef26f16a7250d356b276abb0d8e624d9fafb16294a05a11582c2b4f1a3d64e916b5283fe1c0f563d68f285f9df22c8a4b0a8b592d2e4bc060e6c5bdb51c6e2db7913d8eea973ddae439e184bcccfda27ad97951bdac5e88748a5f8cbc2479f979f1a9fd2f3c2f485e98d47e3921f4d82bccbc0265cfb62d6154ff7ff419f56d4e6a3fcfb73551fb373f6d48ec8dfe1815a2f6fae5e2d22208c7c9558c314e4163fdb61f96db6cad4d7befa7b68fc9a3bf9d5c5e2fac172416c76bff8cca5d5eaef65c622e456eb3f2106eff723110d07e7b1e1c3fd731e7689dcbcb25c6ffa27a59b98d0bcce5e552c5a58809f465f512c4850afab9bc629dfab6567db90d7581b94d0c0ca19717941715cd0b41bfdf7e16a767a6a05cbfeda7f68baabd9755f712a43def3e17d78bea45556b5c5a2e515c5c52ea2781aad4feedd5441b6ca3b2c55a9bcb6db427914a32df9e04721b9aecaba99f0745aa64909554d517d58b6ae6f5a2c788d8942a4208a2aae2eeebcbd9ba5a31781683db984c93e7cc66c63964cfcaa153cb417845a479a7f948ed9e5967a700ec0d0138a9fd9f8753fb67aaa0b07e3592a8464e277b679408e83aac878f4ecdcfc13d670a92456d0c3dfaedbbbdeb23313268cf3d0fed398d87f65ba783d6658eca6a16a76b3f89442291d89d3392f62412493b6d165bf1451461d195833b90cb94a521a4882841a03245a542020a2d67f7f5656687ac2a2269b037e827aedae036391cd540312d7a8c30425f761923e55c154d559023b3a727ab8dd49e496abf8c904340d7de19f6463f606f408051fdbd4858287eb477030c5c6d7055a782acc0456c71f606b5b5ef9374b1f7cc1414560ec618a59472ce39b32ccbb26c34ca36180cb220cb7ffce7f5ea55afd8a7ca192ae8486619a723eb3a08e3747015d0919d8e8e675b4f26399df87277ff18fd34aacc5b7b406802fda4eb93546a53696f0a17275f19902ed96aaf67a6a07ce23ac3e2349fba36474d4f3f49e5870eaeded9d02f87d0de239d6a4637b24856a1b10595b1202836fcc8325794025f32266328b46060b1015f7776defd5e277d5fbb9d9dbacd8c19b5770674e6fa517a1377636c8d76b8cd683b428770e35e61777767e760406b40bf9b1a638b6f5cb24200593b332fca0a8af02bd5ec456110cb526508a11654825a104786abb5641640adba4340403ba83bb4048c248df0b0b058c255774889201cd41d9a4151e557102f168f91b6570292b5c71e93edd37ebd8d4e919e5d8d5a79ef56ba18ad6b2aedb9b46d65723a2b5d96555ad23a19cd64aa0c60150f7592b64a09c30a493367f76fc33382cb8e055953c3258055aa0a6bcfbba9ac80612ff40d0c27d0af4018525d07c8416309dda00d0aaa0e397207218410c629e3438eecec7294bb8a6b96209ab0ea0e3551d5187587805eb5656df867513280d5159281aa7e10261483188cd57ef7d22ee9d403e9357792467a2949a4f75324ed109ff4fca4784476ccaa3ca01fffb08b7ff8879930506bc889ea27a849516b29f0801a09e2279d6ab70932632e172a954ac5c390132652886255da86f4fd113aac535348edf7550e279d82b0b494705579fa688dd2de11fa39cc8be04a83a9604ec5635d1739163b5ba833935e2267a8094fed8fd07596f3207ba355d445d9e4e6234390be8bdc8679b8a7e8874a1df6afba4d444054bfaf30b7e9a02cc86141b015acba7c04f4f323f4a342d02eeb52972a2b6e313640f983fcbb3da8363442d3ac542a2181c2ff361d3cec07614b7777773f08a37417c6b286b1c15011980e9aeed39622841d3301fb04a14a9b32c2d94124dad2e4684bc3b4531984409ac602b91d46199a22745f6319692d25e8cda5126973612ec95882252f95bab425e6563e202b2ceb748616b4443338438b12ccc2c0c0c0b860172e5cb898a105dd2a848171181898868181e16da57361c186f772532a31c330bbbc04bd7043f3a52d43c1c4e964fc82c60a1a1333e2b8c4e9304c43938e8e59b3bd4161381d5cb3bd616a183060c080c1304627146a4a6b8a81199581dddd2d633784f206afdeddc0255ada5e369a2294d9c5763452baa180e504f4839496a8c321342098436bfaa460fa6ced906ecccc5c629a2294b91be9c0f062389d1844f4e3d1dccc0c21f5ee8592a590ad0acd504626851454508165fb3f755250eebe8dc6091d0d8d0c192e43860c19289862708c172ac0881123d375de75ddc5089f0ba834ceb6253185684600102020001315000020100a074442d148288e64514f1f14000b74904078523a9408a324c781180521638c3106014080310464a486843a00040afdac54170534a324e7c89d94092059114f62642105869278d1e0b6f7cfcbc2a60dbc09f51c2e0a51668d5cdbdd6cd686d16ec10b97dee541dae91929160c9f1210ba93343d5002b5b9c63a1c88e7d6e54016d153585dd539f4ec6f729345d565384827f6aba6947622e03e96e8cc669e08f4e0337ae3ad5a9b47c3fb1ef024d3315ebfc68d9266162b8f328ed9e0085db81f4f23da9cccae34627d485b1bcec836cca6d6b52b14e3a731ce16c5e690ff2c58ca1bbde99afd3eeb2672e86c5db342e479c88e8a38b8640401ca3ecc055e44c575af83eddcae1147fe59901e0c8aee9c10e34b5f7bd90d8637fbc140d4c87bec85daafa7634fbcc1b1931d87d1a94bfd317fed474d2db2d1ebc72d5ac0d776b44c420e4bf744a8e374310ea73ddd83b7f03c4dd7679fec024bf89ada9deb0e84b9835332f24b243c4da99196ec1f63c08f6089fbf862cc8faa2a3804521684657c40b1a48ab1c9fbe6a1b107808bbcf43ca3dcade7796bbe80fd632f30919cfe4acb020516cc3ece3a10a5768e06f8e107e8074f39ccd8a54121bcc1811cfd793843249d0d9735a24c7806c320d343c701493e724d7bb6ef2148336140ac78f5d929a1b0dab8fe97d145b7ba8a271a871b299f48de5d7b4614ae087d43c48ab1d05b239c2218c9291288d2340df259a2b81b81f55de187f98a06a79f5ef034b283304acbde6160ed634b98919973248d70cf78d75519409e04cbef42158a39854f84ca8c01afd92e38dcfad415eb91a99fb702e8eb995a9303ee601042a531a6169ca7f80e96409014f477c25f38c4117166db0c624bbaafe07e8e77531396f7059cb00623848c71e24ab76af775e0cc49e31f518c3ada3297780c5bb67b1b48cd1e2aa332f6ee1003b60db61369a457f93a2bc4b21187cc473500c81d4f0b3547f157acbf047adc800993d6e6eb6e838d9d8485c27b51d5bc9aa093b46ea923134a981c67f79167b3d195a8620841c30051591973d75a498a3f72b555eb38f88f20f0060d51aaf7264ebbed4c151eb3a03f2ac51a2eec5be1766a1c28505da13d6612a05f5b9a21324ef3c38ccf9021f84c570c1abfcde0bdf63cc6e0fe2a406afb8102f27295c7a5a2480c659849697632162f5006d9f566bd35fcc3eed820044ec2691a4709b687c966e5121f25a37a92129fb96273877477fff51118aec4519f85ab01ee665c17790ec6320b32ad460f761496b91dbba07903cdfc08b4c313c4eb433d519270228e36e4565336c0ae74db81da7159b69265e5b378334a327872b97a9f31047455de1a34e4637db3dd61c5183002eac693d81882a63b577360a83e336298a02c680656df1aaf62c598e591c96ac98fe53546a92f4fa1a9ee9837b08add7280bc8ee6c02eb40c6673ca96e79dfc992142c04d45a09c5f041884c22460225aeca934b2616715926f95f374c0d86207aab0da1cab067e41ff2cfd941f2dc06934ed6a10d043e22af3f8a10c9ade322b810491a14950933d98af908e8a3bff87fd92e193cb223e0bed8d6fb22fbe0c42942a3a5e40228f6070369399e4c23a3d088621ec59f192f51f4284f4c9c9886f5c7e8a177bcb990a2ce86a36393aeb6acc81d67b953b6d4f63b705a38fa7c94d35f67e6fabcdecd64e0663cb064f395abe8c7c53f692f0ae26f151a7b5a9bea64b07a1aef89d89165b2e619c8ef4dc0fba25098be6a1309af3b5d6cc9f47c1a184e923a35a4d2c238f2ecedd5fac1bb97563076fdd6b8dd460e14a6f3475b4b366f926afbfd6e6e66cbcd434552529993e441aababe8dbc125dde62abb474cf09bddeee732356e1d5df883f3310e86b04c8d800b35ce86d7bf732b7035dd10d0c95bc6fae1dd53f240ac40b48a9a1a11a091280414e33765fb7699498352543e6fbc1eeebd9066af74c39088b175c96b337a1ddb87c4ae92acdc62365e493ea92b44b05a569a3687b9f064462518e48fcb91fd38f8c0d97d44787a2f1a7626e2583d0883d0f2c502770859660c4fa1eaf62d1dede1edab2f51b4a0dbe356d13d5a903d354b0d808b2abf09c3b6b86e5e308ba37cf45986323c864c994562c7391ae87b0227b75538bf7139aa7e7fa0a1eafe3ae5bea51a42f48708f304ed1b25d789bde75620285fede2e2fa510497633253104bd85465080ad82084176ef2edc0a78d551ce85fd9795350f25279c3fd6846872cfb403c1f2137ee9b12e50b3ed691605a51b1e195437f98594726de5123cf8a20c4e788a694d0de22a78c5ec72a50f8fa81c383163c8b40a0f1a484e2be22e2c754924901e28ec07d8b69d90ecf0bcad41d6f3efb106299eb361e3af21a03b259397b6706d9373b869cd282c2a756f20d138ec6c4c9f59608a770a0c9f300194c707e41265419f7b8787f741b54de3cd60faeadcc29b3239330f04a357129792e746240e47d3f50b50bc810f3b63ed358b83e8a872191706ddd75f205b32c6283dc4a8a1cb987ce1a6a2053565085121cfa287b7096af437e3c802648162b274e82728d6216bc27bce48766344b73f77540362d586962b60235a51f39f17f612e5f814a202a0ac22992ba6c15b5b49f07f68463994e87306132980343d91922a2c3670b4964eb9223804bf8f4b21ac507fd3965e334232ea31b8a7200bbccc7942ce55177c3b6c744adfaead494a78571c7cb17b5278465dfbbc1edcdf2590ae56c6235850d58781125920b0035c733dfa83ea47571723473680547bc66d2cb7d6303a7f4453c439a3bae1c03f0413ac6eb252b5871f05bfd15173f57ae67c720d3fb47bde4dc687fbc07a64690c7c6e66f715496316e42cf1d0a0aa63aabedc5a6b95898d1bae844439c63304ce50a9ba171870d8a2f325cb1591860aa846083d80e238e0cd38d4f74b6e0d04bb22a7b798b9be4a4a69811fbfa99f984c3fa046a47afdd62c9714226d6c3180c8166e2192b51cc0026c0579ad2f871d656770453b87ca02683027bbccb38e306cc040410b096d36bfb2717703e1983bd42d668788f20f6172bee11a4b30ca4ea6cb63820e417e1290af6fe1eff5de8bf78fe26bc65989b5673f5b18d067235cec5d1ae479357603b360261912ce11ee6b0edc15a51d546d982df22ded11990e0f6f27e9a377dda413d55417b97d9d76a31a0ace1ee9cda8cfed7d3cc5bd530eb7c40d14d84e0fe2b03700e04a46a05ae02c445856a9c7e78036631588c926da0633e180c7d80e142ab9a1dc952e42d9068697df384e0da365a933ea35872cf2fe726a8801a4e8a2186caf9a0f83fb78e0ac75aab439ca72bad0e041a0192d543640f01efc7f5ff110d2d7dc61bf4c3b2d4ab71f1783e36dcfde380bf50f0f6caeb2f942d1b4069a396097e32d4301f955eb7d83e78fe26c8782a73a8186ece21f4a25e035ef5f8097dc151d82a7dd18508a2b7493840d8367a2b77f63ba27ffa0a021221957b92249f0813c2f5cddf42b7cc5b2b660a734b829d9a2b47388589a3464cd58a9f1df6c628f4bc034c875e6017aedc514f730d2d504ec974a7dc7de278802c625ffb38c9f6591896ab42f50e3a55d0663b714a4d8a8707e07b8c7e2964ee3eb81ff4fa555bc37ff2cd9fdf461714e032fc84021c49f0c1829442f07683b53888c56c27596e8c500ab767d33e19082242a73e0adc741129c0bfc79556c7c88f85b6ca9384ff73f1174ca9503ab33ad963d132641454240cf54d0c01d01bada072269711059f701a1cf1ace92160992bf112b1612c7b9752417b1e3c3e9dfb3a4fe580d0470632097bde3f5bb663938817f55a475668fc817af40d59c2ccb702d306ac9f97c87f4925878185e519d4ececc2f5a1b53e0dd973c0bf5b2ac555423f72657d656a82801fd05db00b3274f038b83a5d578b98247609e243ef7146148475722197b5f9e5ff666239ab6b899be0aafa82eba59eba7efc2cd8c7f15662b073adeb9102b8b87bc8b31ea60c8983dad9e5237c0998ac97b5078a472cb8cf93dae98449ba686f58e68db72eaabbd599045d53d76a6e1b73a12aace26448cf459914d2614b3395dae6a31ff0be80300adb7814be3c5beb2d0a452f67cab49eac3bb516ec7beacc869d9675a61070650237aa6b202bc475e59848b95bf84665ba68c36aa52c600a5b025234cc91316e80b7d91682db288558ebb282bb8c4ff3e9c1f39e163e3c1228717b0fa486344443fb32c511b91a028a1cf366c340a152ee63455503583e52e13684d7886a2917ccf2438b83bbd2683af19c541fb8338c56ffcb44bd29a0908f7e2c05bf4da5cdea4a647cc338278a3aad7e695edb1d195d8d24d220bc8507f7c86f27b921ba71951900833a369317cf2ba9dee474d07268bbc5580930f9d285bf30089c05289c8c5e8d089a0f32692ddcbcad447c194d5993ef23da8d19f463930eb98da9610ab940dcd642b4173a934108a3286d4c9b2c0017438a75d912cd9ace38f86914ad55cae34edc2d5867d6bfb74bbcba5919638c6eb719507099c220b47cf8177b62172e7e64c5c0405fefb897d051f206102e41c487f43d98b251e7ab122611561f5d00264dab8f8b67755e6edcdaabe6c2c6f62abdc9017cc7223dc68378074a2c764c89b07d817cb9ec15191af536e46cf95f1b934fbc11ac9d308ae1a949e5f6b74ad598b27c48c253dabd43421d3702869702aa2f0afcb9295ce8cd47a9ef5cc2dbd2b4204558336e6962bc80658871c559116083738adc2184c1968e6b7b5eb228273a239ee22cc905f27fa1132557293c8c993935107f5cdd189f4979b9a8e550b0fb58549f72d84a94b630381a62ab926003bffbff46fdeff9e9808fe2433cd50b0f7ba541af943b906adcce9691831c7223d61d861b4180183ba1183d157e4af15bb209ea37b38d8d6ea8b240ef12810bd1bdaf36b75fa9d9f69216c6916f8ecd941acaf40ff7a95a02340740f21b4f4170870d84d27f5b7438465b42926751b6c924af442223d929a46ad757c22d447101a7cd6879411ce9972c5bc5a23444c426df080011b8e1b230ba119b91be1331872cb9084be0a32d948c217d47767849f3419d051b9b5d64a4c2bdadde775275afef044faa6ff3369347e37967c3f14b5d8b8c1706873aecfb2a073926a72dea25566bff213d03a2046e8e2b234d9943d2990206210b0d0bc141be07c52f53c933cf76ced65cc94fda0e7676f220948b90855094a3694f90a969d6c0cc9929c8e7d316d7f0cf0f14a433d7b150c85286d4667554eda151f76909889dbfd10a1407a9b635724160d864284ba2424ab2d47f6a05639dedf50b0a59654b7fbb02bfddce02aac5b8c26c39f944412fc69cd67468c33d0d05f577e07075b9c26abde9850e4e81f68dc835b734e120005f50b4ccae28945c3b640b81d27fd327532050122163c60243feb5c62ab822a3dbdb5e4aef2b2fa00cbc99b5d044fb5cc93dabf50a6df9c9429ef0f71ea04479c3975762354512c634ce314e16cd96883304bfa19f94fe387844b4fec6a5511cf889fb60937c476a15b6f7ba0e5d54a91bae05121f678f0e46dd3113392de8a66cf13f5fc91d1e150c52be389f8c6892f1cb546f0e72ccab6490be1a9c2dfa1fd18422dd7ffd75ff8e057716e71fe9b6ab2ddd3232cbe49bed402c0e58c23f95c0fe783c9a5310815f4a84e23f4b4a45acfddadbcd1f735a9c83e1f1cf059ac81c7c76603270871f9141eee5902a6bc26b3e7e7fa4278e1968fd1f434b70bd6fd0919c95e498d9006d8404f02dfe4f2cc92a993afe2b2c0249b6b07b89a5dbe54be2ee399ecc8c55540124dd60d1daa182c8e5338ad3fb58a7219899f93511d4865a6204d9c068669f91ad1513fb3145a499e52d609073b627486bf5bf67897b4b16c58499fcc98c21da317e93e1f048d9fb830e8a5956fc9abcbf6f74cd305a70b2dfaf42c0a34b7da2b288e26bf6e3268872ae470cae9d9be1b83d2d74cfcccefedc4c2311c17cbbf501e6b8b7b4cc8e262f6d8a915f88b056614d00675e3529c3ad008a1ac9a6f865a57bf8d49f99a0d064429122328daf280b743a3997bfd9c8b168ce7ec1e6b91199309d2850269062d5f32a328b52a7cd3960de3be88086eddb975fd1b8cf7a6c7d02120c2b3257e22e90b8b4c73789e2a7ccdc00a09bf0a5d044a05492f6eafa8aa3cc147b44ea87f84ad3f607187c056c8818745b3074ee4f09c47a22783910d57effec7e5528ad54326bcb8ed322602c33cc9a3099bcaab6e9d363cef81765a767e9834888c9a0479974b145664802da68a667df84d324c8236b3edee161b7c8b44a87eef2370eef8f0276320bee18027dc1ec6a28a49111f85473074bbc635448bb505a463429d08e93c31bd461933afc54a5218da048a0bde0e862837f914c5768a661c5759ee27361b78c8a83e450e0cce66e72d210ead649ab5d22d3b0b41585a41f9568bf3a57118094bf827c02c4ad1ba594b02f09a757d81f326e738f0d765deb10ba676890e16cdf12ccc4460ecbd31993b9a95e8809436492171c873df7a01cb49b30be301a6dd38388df2f17ee42d17b111edbe73d590c7ffacac4660ed341a60024d55b072c6058f98564ab279550faf862f8e594abe42f7649c0fc0515f76d00842ab9171ab9635ed3c76bcd34b01ad0b60064ed9879897b0fcfc86bc34214de0201badfb30283c2d06bc792605fca7478d881e11f33b7de9f4193ad656ddddf22f442df1d56ffbbc52537cf3e1141b9b2ac0a8ce8886cfc080bc0baefc82be6fc077650090b9c0dc4e755dd89891fd65413e75c655f5116be35cef216fab32ba6a18b2055c42db431b30c28715df4e165f4b40d06d43575871f8918fa7e345815fd58f50cf4d820df6bdfbb56bf9dcc785dae20f0051f11aa89d7e31a97e52f14ae5d2fa280303b053fd6b346e5b77172ff2870ce4ff20a36456649e1a7d3f417fcfe744cd2b6b0c3066f8d9b85988bd98fcd3413bcfcb94ffb090a831c564ee300b13673a51cc9c3dc585219ba42ccb46df0bfbebcf90062648224338462c13100c96afeb8b5372f04c9e3007f0be09960eaaac9c814b8ad6ad27092649a529691f94b72acf33f96e92373fe7478635356014c3ed81d0a4ca3083d1e0831ec2e2884478e09b9c508458ceb72bfbae645e5a8253c5233a67ce3abe34de9caf2021ad25ad63099788435e2c275900813a777e5f90198a848d66ab834ccc574d52939faa181b29893731e3de7763c1069ae700a0510cff70e21236301522549feea4552adeb6fd3e7ff9140530b5b33079efdef16e6149b238008988afee4e827474726ba12418d768bdc86d5c819a0cf345d07bf637bb29944e913a721d0ed072c18622a7d84e392705b0d9773e0a74b940e39c402c1720ecbc4780a8de27e6b4cafb21c23c007632a1ed892689ee138c2b7812fdb537e3d7b2a2eac3cc240ac8fa2a52b01c1008d6fca0f385cc4a96c3cb73736eb7e7f29e764aa4eb6f73a996e03f92e968c5c04f574a84c1ea552eda5c4b17c2c10a42a53e4cb0df46cf57b9ba0af98e2c7ac0a3c568737bcb30bb2e5b1db0a9dbe29259de841586019c4b475172eeba792ea7122529aa6b3770050c15ffbe7dd74d06b8443e72be3b0ca6c49c335b46ddf49cb1b173513085e56c9a9d8f2db5b125053795b1b0d4fe298e543e6aa54f58a49e5ced4ac3236be4bbce1692c932496c3bb4b7060a64c5d825a7a41a7f5ffe28a0a5c3b95d30373f7dc48a9629068bd3ad89f424e79a665c0983ba6582057cb9035239e1a8e31748d0eb7d0afa9486424d7390ce773196e83a772ab75c6bbedcf3129b5a85f6319aa5942885467b7db36770044925b2aded5a3f3ec6086680e201f7f97509fb606b7f3b8d0b44b6f448095731373d9db6255ca9f26cb444311f9678acd641d89c85e05095bccaf7dff19b0613303cf6f7394700f995f46ac416ea3a1a5543bba8a41d7339789250a279764fd9135c87fc7eb5a3c14206d0641ba6b0fbb506298751f2f909552cb2f8b51e91d4d664e65d017eba69d5c786758db2c0410b596822637507b3c40e7dc75cf7aeb670e94fc5a002a70a49f61768d11465fa13932c7f02e4c44e15ab24dc1b2bb9cddb0ccb32e5dcddb44defdca44c13f47ee362a05f75a820b77afce4dd13a0c9c75cf2e2c7edba935c4ed2ffd8a194927fd5f5f7557786077a7c49096c0130ab36c2532969c8b6a79e11e3f01c5f62742aeb431af8f1e2c1c1f17ab22ef2a5bf615d8b6553d23dccb5297c0cb3a58559000f220ed2442104e2c0e94f2b71a4504ef8505bd02f84589ced263d945ff13778aaad4d07c1d7efaaf7ac3b2d364fc4d4451e31bb1647c8bcf99718c32696b25ac55eacff52f4eca46ee6361185e479eea64c375367945cb2a8a630c64bff3f8e249cd3e0af3f8b4c2db4a26c3e381936fcd35d7ee7e63ee69e367084f93d1c6cc770963e81b2311923788d9f02911f754dd501831667d97d9782578d8b0e77e6142c60cf8ca5a17ba209425e0ee2741d569b10b72a3bc3a86f94de3490e74c5b701449b2e7f565ddc73baabf3b156a9bf855da03b9aec964cdcaedd056cd488f011bb77cf810932218a3027297e73498ec8a8bad769f9515aafffec009680b6202a2c410bd7f88594abc09d34831aaebd8d40c3f428335f8e14479d5aebee570d77aa3f4ead68bcb6948d446c22dc63161a84c0bdcd29370d2f40e4bbd5b17e1a9193262aaf1d4e1de2058c7c15a11f42da2b11c71161adb1d35f12c006c433c7039495531d2c02c8938a19c8fe147b4def99b5702353de61b5378fd0cbdc86d544cf38250f760713b2a22610020b294ef1cbe4daad9067318f36215d48ee9bd7ee59a5cfd7855c7d3ffddb51ebb0204bebf8e60e0be6ae80fa4d5ca7f3d70e397132e0ef848ebfbf9e1ffade25ff8109a291600c37ff2c44d7572c7fda71c76586fe502304c53cd9d6d931d6a2271326c55b1b31a44976d8dac42c4c1266f0bed1ac4b3259189fdec3d30a739300a1651d6d3d470a121d5347cfd88e8507e26e82307e333b384f12dace0017854bab2927896e573f9727af0cf816e928127f986ac9b98d84b051259ef212003998f15e76a5c205de1352b4ee369ac69eefd228480b824a16b74d1850dc83fe662b6dd502b0d297c93cd9e97fc59f8a14d0f17359abd34cf5d3e0cd329dd4da25497e7bae126fad8912864bc384e8bddd3dc7f2bfabd68bd61539f59100343033ce6d72f863796240fb281435220423e56428905743fa53a58ccbdc6798a22118007a4a12b55d942f00c0f12f6e4b4ab0893d09a20a7a309541154c3a74785fe5e68b610cc72487ac0f2f4809080bb976c18046b8712384183419bbbff6f28fe5cad134f31c9065cc1371261a8e276a26f356122a93d263b0946006776da6e912455d02a5289fa5a242f2980c489b825b6bebc832cbeb2eb09620870e8df464ae5a68c99f590e8d3ace01f5950ffe1e9c8dba1edd32881b63b0129e557df3feb93f1a288ef2dcb8a7f0243a7edb99757a64edd3ba5695f4e49ca31f36178721722b2760654200bba3b0a31d6ca9c24e735eff21ae89d6dc32e7494ee4f1ec1e74d705266423d87c3ff0ea97cf90658648b042abc5d8bca686ed4589f455b7fa355781413f1ef641e28afe01db0bf32cfb8d7fa72f8525e29ea84192a75b7bd25652e9652eff0d9ab878460911da73a0b5821f763bbd73f08d5de78d0a3fecbdcb692310981b52a24ca51c67833e98fd771ccff9fc603d402b6c04bfeaeb3626e6fdd978f9860ed5a1e4ce06a5069eddc868102bfe472340f4d284e56fe56de1bf12c42ed0670c5e3432dd3b758f9897e70fed9d799eb016d4c0c353e7c1ac79bc923a60b71b948038cd11e824a48df9bae43a150d0a06a6e80573f0a2f08b3b8cd4bd16fdb052087c8709289c716a83a9e6b43bc9912b6da1b1784c689c4a3c7398bc4826b1cf3168ae7cc742b329bea3b55d6a7350ed4306cc8e0cd8b31d674552ec852f99eed00d559e8879e73f58ae6c9d4c2e25b54ed417ec279e2c3f745433354d62b346883158c4cb2f270b561a923ae97d588b2c2590dbd81ad77abbcec803bea9a7144da5132934734db713ac8ccd2e378da5ccfb1110d05233b46df2b5d3a1253b0e91a7e80d340172213365d91b8eb93dbdbdd723da82daca5bb402d68943823e7edd2e1d618ef1dbf3afe2c38b74166b6f4cee880f1d5bcf5100dfaa25331afa33a35cc68cba5e202bcfcee4a8e46510190a28783a6efb9807dabd8d6476e278385ef5af83ad4a13374da341c2c1e221d50c584e0a805b80c232137f37b510484d946047d87cd250c0147aaee9f0d050e1e00551ffdda55f59ea36128a5f22af4a739b936de6f85873e15e9804482ede298cf528359af930899e3be98a3433bec60997a329e3c6a49a8931765d657b37af856a62ae838da0fabc7b4164a9997cae3b2f00d89a205341fc0ab48eafa6619c9666feaf688c2738d68759f61e5f967ce563aa121beab8c2d2d99b3417ebbe202796e1e61569450a5e1b207ef2c8ed2c274c7e3e195d03e802118a9bb944c605350e57f13568719de9016caf9d4a42a0ddc826b6dec0e54918c5caad89b57e9482e38dd8c3d1cee3b2b5f494ffb45a48a7a7bbd773168929295a078337d2588d18e6874cf7fea3b5671f807ae20a441191ed69e571566721692eedf4d06a8ee69769c58856d394bbfd77d9456137a32e1765f5c26a69e2cdf1470ab193de8c9fded0e8aeef5cf9dba12d5f83628930eacec627230712e1ae7cc527b3c102ea608a86d8a1a7fa3f9b46ad9cb1bc6dee60993b32cdc59bbcfb453f94c1d56a19fe781fbefb138a7ab111c2e1a85e9433650f1cc53f58dc26cc6992cafdf69125dc48370f98f3927f04ab64f8109ed61cc5c22b288dfd4b0ea9e286191eaee0d8f0617a403dfd8c990ec1fe70e51b9b95f47034732c46661dd8a49a75c2e62beb1357f3f4f14d9b866a4764046ee9a6f2f8e9d094c12b6768bad500288b2f73ed49de11ec3d1b5a75b2ef8dcc5a9c8f796b3352ff13b9b881ec1dd8c58ba49dfd758c9e0308cefbf10e6ac7cd134e677bd1fb6f13ec7c0e582c7ba0ae4c199fe11849648d96b056aec7129bbcba0739aea501e5b40837daa2b829d86630e8af45f49ae8c85b43b9429d5ef12b4d89231be19b59176ec59fd0c48aa3c44e7a58c278aee344aba9fa6ceef47aada7ebcd40fbe743ac6b996adf9cf2d5199957adde8ecc129140223f06147b1942f6a6000ff944e3bf023c00ba7e546e714557ae2f2f2a9fac71349df63494aefc9a7fd771117f21c1cfc672b065efb0e1672e7d476f02492d4477643ee102c48c44ecee97652a68d451c2d2ad98624f5d455ad862615b88b624d1034016384c0f615bed8a7aea39fdd36da9717d716af82511a8871245ec64a13281834d364c5412331ef497d5eb2f54027262029518e82a2e10c00dd26461528f3c84f593846fc3fe54d777e3f4b0335b0cd7221ad20ffcc5535c934849f5ad2ebb5c746e42c02ac88ba202b5e6c915f23baa2b4aa04ea7b42cc803a53a5c5e6a8af8828d02a91bb2a7cdcc049c57495013a87f3ea0d29ba0f696dcb939294319f5841bd0caa9e9ae5432e7f91cf7785ca685010f046204e2d80c98f12b59100255c7b981b7b32af4167806276f647f3f013847622206a5b35a6c3916468a7d41571ea1bf6acfdbc859f3f358fb23ab1841c6f661647bf7a6741ed110e63347b8427f3fb0b28920c77c0cd97b25ce2073ead6c0cdbdc9b91804a742f357f385d0db3ceeee9bc032e6ab2c00d7b7eb3d16c804ca82830177e68602f621daabc419741a81a853ea5b297c5e4f010920653a713821c4259515423220ac5a16b6a044092feb23a793fd8b59f202203cc179586408629935a5877e2f24c0a12363a49685fc3e46fbc61194f0fb39dafc85fb0014737f8b6c2adc9e199acf1a1c6224b87ad7d855d73f46dda07d3985358a768f0398517b8096c705090ce7e51a140622baf3ba23514873019c93a4c17fe990b3e4651faebea640c391978fe378ba296c8432b1e4058388a618010d07c87464274109f3a02f52f1d87afc8c8465282c9811c1b0c0458c1ae55f7c39bd0c8c5af6a30efdf576d72c8e463bdfbd93237d3de0f53b7015a7e6f65997b67bc5dce25ab2cea57ed42b2452332a33c4f637981e8f1be056dd5e0451b3b3bd428622e5fd0a75a88652d00d54653f83e1bd43287e0f97c853e263a2a20e2320dc9da918ba1e7ced39f1af51db5637b32a812fb4adab7dd122205066770d61e845fa18594ce64e3840c950eaaa46f83ec510e5446cb34557e578787c6197e13ff3010294b240a984df33a167381e156609492be8602a26b0ec683ed8d5d8ef9cb4b5df25a83540df2e8bfcfe29bd882bcafdf0c709e836b34e7ea3b7391cf7c49696b234517f9f6b0729f9d6310bce32c850b575ca7b51d09738051f16862af47eb0ca4a60039d843ee02a31b2b081ba764725607a7b23360caa1fcc58029e86936e075214b19f41540a118e7d32379b8a69a3108b7b928341fd8efb88333cd1aaaa179a0067c151375df007582582f36715c1535fed59aac9e4518200072817fdab7004703e7ff32b50dd7c276e94c680500ba9435eb2b8902cf0f6ca93a4c95a91d3213f00cba7c4e3c126f771179b711a3a67fe800d99c3341c1e27c2f07bb4d14b7a3b04c3b06331db5a95862f19feb95836bef556aa9849de698d9e03d2f8b4d0cb98ccdab819ef69553552b2daf3c52c4564a8c644dfe816ebcf7f0279fe166bf2ba98a8034e97889ce9522635ab91a906108016ef8ce492f14b7992f92a2766f7a45aea42f2c464a1a641966cf8691a75c11a727be30e091db8efc3054ff01675f494061bed2fea539845175a4d45c12aeb1690d0b7744f1dd0cb122e062a2afb754734b24475916479b47c588afd43006ae5db95c1b45b1141c2689fa160db00fca2145850e3d75f846e692e3056862ba5cbe8ce5c20c1d85bd05c1c23f9942a61a3ee73440b762411d11da68e5c4877b92606a462c2edc8d9e70e369e59ba55e7028120c8f5d422b44fa975f058aa23d5697c9a2b20e3dab32df3fea1aa2693d1c860a5ad4fa922d5b1546f333ff469f740b5a338c79574e956c778500f8ccbf6c6ad966a54d571ddf0b2e85bbef39d78e356472aba5044cf46d92e6e95ca594669dc610cd499fb2656465d3ed633ae4488043d10a764a7e65d7cc66b87146b7dea97d3a498ce65f96f841e3bb67aa2a88af5305addfbf0a4d26ae8c4d01ce910fffdf52590f705541afcc0782e2d6a74328866ebd6ca2bbaebdeddc3697f476690ceb4e248c7fd01af622c91932c00bc6a2611678f41b65185f9691044e5df659023750ebd1271ed3cb7a99074a929c81d4104a4e03f91042cb426c2ea8fc6a0923e774dfba15e3fc50103b12aa2272bd3124b15fca036866c24543ea25f030ae52ca5ace476a478ff91b7d2ae007e6010d10274e2467131f32a5a29caf14506f0f9c809fac5ab9ef7829084552531ce8f088d129d2f73425ea01cc35bab08f2687a16078128c24411995c7829880fe15f4087b3d1298ebcb128a7c21b30dccf59fe0668eac79ff6b15e8522c41c1edebac8b6561592fd74619a4d56c8a9d8f1fc8221c9cc1edcfdc6eb40023971336497b56d9555adf285a03cb7ceff2ed290899417cda0dabbe5c329c3aacb5969f2a2f8b879e88b4ae654cddc044724faeaed8647379c6e65e1ce0f0aba0074a02c408a9134e53386a8823156006d1cd4d38e77b92687bb9ff868e004f1fc1010552fc09c19cd789b2f696521159cfd6bd630381be4070eb1dd01af99580a30fdee3492f187ad02348fadc397dbdb28e63a09e7eed4323b3b3377238ae44b4486880040ee151d356aa8d77c82a6dcbb1d2167170d2c4a8e0e5dae5ca0fe5fe25ebc61281200823a429fecb1c2b9ba3e3f6f94569f25bdee2fb27b3fd23c722ecb269561d065984f142ad15e4dccebaa72fed07ebf29ce66509ef9ccf0ba606e6a9bd0c8cdbfc1459b5a8dd374725c48d3e8fff300ddb45095b808194200fe88d52ae372d7984d549c647b32d8dd528a33ce9dbac8a7b4b06e704a7b39dc03e03ce152f5403e510c6420d629af6a4f33eb8a96ae5c90ec2c75527763f8ed0cf93e3f6de048908d2bab4bf1af871355cd478e44e2770df2985502721fcc5f3a485a12f4ac64ab46284caf8e642309da8849b43637ed8c94462b838b3970865400683b23cabd47f69b15a0c308140785851b4d69fb55fdc51cd7553cbf1045d9bd1249df10d14ebabed65667ffd9519aea62ef76090644fad4d9b2b508b7ce6f86615d8d36d03c0a2b758ddf3980c9e3ba1b86beddc2da67817b0b4b5ea8649ceb65162ab32e92a3f57174dbb21ebcd085be156f2cec0a9ae4060a9449c8ae231c29c7c318ca79c6076f3e53827ea75a9be6e0d2c5ee5b6e59f0341096b9638d1205ea95bb8d184780e3ed933adf4c074ea2f4a4027a9003fee876c9d67399d2e329025a97aa751acf7ee11d03f0b99724fa7ab9fa00fa4d81ec87f67b2695e54c6193845f7b5e9cf1378331a33fb44f287e93497eac4db7def34b6603c95ecfe435c5685491d74274cdbcf51d7f989817e839a7981683e4737a68680d78a5dcedd054c181a691806db9b808f4431f96c3474c864a8627944daecc114805b51a49e0774894854324f413b9dd04909238a394b471e8ad2bfb262580551e7848ae0ee7ae2d50ed5fa2665aa5c92d7a5f869a892a2109437ca49f14c7165209cd9edaaac9c40e6d0d47ee1503403fa2f3c12116522ad0c4abf1be45224ddcbcc02a8bc5737b7eb425bae8c726de42c1672ec39e2b3533e8009f2a0ee27101dd72a7c17f5d9a04d5c556ca800d42044551609ea01f462e57fde253ab4171e6e8bdb68ea3dcfd125f0559e8862594810e0e171ccd8597e61410fca5f98af15389cd29baf328bc24c89e5209c9c6435220019936340c67330f4d1fed3576d301de141983e2d7cc456c7887a762f201ff26f7542e10a9d269663a1e8398ed0aebb123f7c41b7f39e17095d0b3a14c1510b3937e5a3902520e78630bd5ab280e3c54d04236b0f8cafacc5614192c5c990e4e032058209355296e9e7e0299faeeba3060186b95c0893b0d9ab0e16ee364a9ad9a1e3ad6261184435cf738da069fa3508d48722ecf611977c45c8aa0f9c398c02403f71c871c1a54bb3f62e275635e49438087d8b8f843fb7f36761b877bd741fe4f2ce4689ca7782ac581874bf810b91d888a301fa26f8608c5960279dcfc0b08f3445c3b24eaf9377440737eb687b9b0709005681355e7822f8c4a7c64eb17014a39b862a1136a190c2e71bbb30685a96898b733b04db3b083e18746e2d09331877831049ddd65a5abec4eeb07fa02eda5553cdf108feccd33aa00460fd04f71f83767ecc77c250a511d6ef75fcef601a0af25d934277ef5f725f6147d5b80fe049aa2fdf4510f3a20bc2b3607e2a97ca656e22756dcd241333b91e14260af8a499f84d27abbed0967d4035149075f15a30c005c165406fe5382c12d18622c936ba609390ad403bb63a84480248d1a23402a81a41362bb9820168bf7e648cb0deec66f245644e932a8413a263bddc35a7ba1b1f94ae6f3e9495a6736f5e89616fa96628d5cd94064b0c1c810beaa405db00d7ecf2507a89cb49ee4c424a09f3e4db83295b034a8ede3ec96bc7fcb71ca0e2e16ccbbc1fa513ea80cf5403efc588f4fdb3d8518ed9e8189401ab3fdfd45f698075b95fab91fe0feda25951fd872edd8dd073d974b99302089278f28e59180e9a61bbd0ad61cdaaacb46d0ca34204fcb716a7cad284fe18c4f36f2b923aaa5fdf6c811d27bfce19511949be4cfdb86ce8e75c04ccfe93fc8b9bf05facb01c605a51a41bd90cead5cc77935b69f9b8cac92fe2297ebf702d43d768fce4c66e0fbae931a8382fce08feb32216a37409fbce426422a0cc311f67b5aff203f0281a7811d00931f14dcdccc064025c1e0733c381da58a78fa5e6d66986dd2f98b9fa29d7ef5d6cd59225784b4aab796c40498c30ac81c6037cf5bb5aa3ebe9ba257a4f175bebe30295eba640795cd714f9c5b60c2277d195f2dd9904d3d305cf8932684c9f643caaef4706c86216ae629a4b4c973706f167a988c7db68d8d58e3626349348533c3aee9223743099c1ae16d97bfad6aaebd8bd9df371caf9ef8b1864682c1f748b9a7c589aa7e26bbf30eaa0238f7c889f49cc5c7e73d4fac65a1ee2bf8cb5919e8cbe67bfa1c3aa1189b38f778c3b13f50d92bb11a721ecbb9899a5cf1d5cf44491bf9e0c99189a506947df5d1b08f44e3f7ca2f13e25b0800227284036e6cdeb5fa84a09f309a9314d3a52649bc20945c7f10f847da09de20338f03040f1f2e064ca55c66f43bec2d066eed696d720cc1eeeae983709a3c6439932e34fcd8fd7e0c3192bb9bd05fed0c10f107b14f6b1bcce71f60882fc45e01b09c6a75cd1cab89817ce83c49c9b9f04cf1acbde57ec47ee30c29986f86ed3c469b749f454eb036bf043f70bf5d0f73e467dc598ffa0b6189b7b517e02c1185bed29c727715810457835cc175799846feae085e549aa67342f1f4de7a578226fd18e7d039000b046216a3e2205c39b4f5c67916c53e3e7351e651b5d44ca0434b8ccc8fc981bd0e5565ca35919dcbb60ed6ed420904f35b854001658ace4981ed38e7485728e7640e727dd39ec14232e2678f08d57d52fba621ab28b82962d45fe107cf58a85a80aa5f539b5f9533acc2e5aa2a0c8c04cf017be17c92b50a9d4b82d6fb6f37cbbaa7abef1fe8828c20b9320f3b5146127838979f04b719f448fce30fea2d9f5c6f419715b29c9b327b1b04462163c093b17088df87580eeb3aebeceedacb8b2d813def8022b94431421e74a7958eed59a3e1946d6aaa7e24738cc167c4dc5331c016bb1f50de7501ca1dd029047614eb8af55226ac2043308df3d52e5d1f587973a72e6b1f5b86096152509f2832a7a91e0d58b094a188a200039ab558243f929df45a7e1474b2858b433bc14fcb9a021cf0c7b23620ab4f8ac559184335554c175334cb12e6dde29cd02769a6ca8f5b6736a33dec472575e88e1cfe325b98d60a2cd3e2cee813807635acb04185031f501ca32de963de285f6beaec564ebc969ac1f9bb43ee4f844a2e61054c550f09e268761922f19b951dbadb12dc0d9229a95733bcc51126e512bd2737264f3f4e7b484cf5b08422902d5146aca8e49d6dcabf20808bf1049a751d0146c54484ba1e1a6a6af852f6e1d4e91c6094101241e62149048cb435221057fe8811b7547193afc44124bd66659a30ccbb12816116e2e07eea10e92c70091f91e041ed2c484a9b2f6cda02f3124448c5d9d426173c7b5a2ef424cbf0c1385732be804096cd1bfcbcdcdd0f1963851a9bf1e1e3c8b7393904fc7271a1225284f039488527c95de9470fd8818ed1f153bcf7e2810ff9f43ef66753a694b3db7aba2557dd75f5a2451c9a893811b9c850f2aacdd5c9e4a49e26240788e44dd429a88541260da7eb1c41ad37b44f4af75c356092c8599f7162d152e00f8dc9743f4aa89cfe18eb82fba7c24901e29b9d2c55161bed464c40bbce8414c57b21bbd126a4e58abceab16bb1bcf93add517126a7eadb9b917453d83988c13f225d48c07d658a98aa1f74bf8b05b705502b455a3bd58ba392756fc3fd9900d1a29417f5c2e78c83130628c05a00a7c3306bd4a06b8cc5c037a8766a0134b970d409aa459ac8e285af3cdee06b2f6aeadc5a0c092e57bae7a3217cf3e90ae599e0b421b4d62a149ed21548b34ed9188ede9c5519d961ab8812ea4af9b5cdc9115b3e2d3e748d0abd9cc32b54e8f2b06e7ac4fdff76f0856fcb1666e2b29461cb59bd70d9ae7f9e5bc3578e1aadf87895fa4399fdd3968c50a35878660d488fef37a635d5c2cfa536520b513ae7202d01c086c476ba41079705a92dedebb872919f1165a917b219ef4303776185dc8e9ef83036dd856fbc79785284aec71954cfc8b3423c1579d73bb3b45fba608bc72443adc0392f8c8f1faabe7bd845144ba81521c9b929a6036420941944468c21c5bd6f57f0105b2b9d8d0fbcbcce721915018b0d034f04a4ba57c5d01a3d3127b3fe90e6935c99a050801b3e06b332e89f2160cb5fa0217a853fe0c0b22aa6ba01845c5d9a06d8900f4275264228b23917c6b2f028504d2444e37e883d98500ce6b110ff46e052695aa45cbbfb1e20944d2f29e0a60748a7d00c77b5d587a2cb7b0c53891a9287d8fd27a00b97218bdbe337ee586edbedf678a9f534ffc020a56b1cc0ca0f525df73a8b4a04622c8ab97c0867db474d2057adbf32692ea7b499d420155fc4026cd258617a3f13ce6175758c1e228bb31588250d38215b72ab37cddb6a04e889af95ce394db2f03c003d0fd3af1129cdba71972e4a6b5a6e1e8eb2b331a5947de44378c59fb68345835c6704fbe25abfc892a549cc681e879f8d1fb054f405c6cb9744c785052d74045f4831b439d68079e14584a1544d50f49658c22cc2e0f92363b94b9f73d167439c0cdc0b4ad0b273d0c6c323db7b7be3c16697d80ef67497ebb86b7062e745d7963bb6e49fe51c9acac2b103e324d3b3227da01b1abebef2c0ba698aeac767e75119bece5d5690182a7b9872ce6775829a6158d826d6f4b58d16d10c2f515f7e5a2e73f74ff52219d2031741e243ce918210b58dd17b7d50603600e15664dbefd305043f43db4485f0065b5961a6d3a627295e584c8d23a6e7d4d2a06b24e573009dbb588310d2c23877913ead4e0714a46c47fb179733a0d6ac87f8101209e93963eeac846230bd25100970222055301d680be6701cc4a082209e2dff4f270d62964ed198b6b839c3d23a70cbc8ceb802b7e0a0c3ff1e1080ef4d5bd6eb276b2aa3aefa42fb0cc83eab4b212af163d563225ed17dd10934564abef77bbac8548399f0c95acb747e40255250662b2248d402facde02586f88dbf2f381454ab76dc73c50c8c8504ac9b03f33b1e14d508c247d473360bc2fc678a827fbecade1d16213e021ba779a03762b3b634c927a70f59e0c5cf636aa069a3cecf9de7515437969ed2d264465eca3372dc9fac7738013cb22fed2c25a6b9de009a29819fc0ce8d35a8c6fbf4d92706d23b4e7aca9417c6d67eab728f5065cdf863e5e0ffb7cb68ecc368dbb771b3a52baf63449921d905e830981edd6c370556a20925b76f372d9192579404cb3308af8ac1559bb5c434700f8a26b22cc6325a72421b58f4814015787e8c1dba6f617d7de66e478097f84230b8fbff1a1a6e071834d5547ee77e4afb60f3002a04284d6b2323a88e56e92f0ae6e45ba17df71c3502b6536a09ca90b9ae5a6a9e5c99c0dfc4e4f9d17d85443423f8f42a59256a9d30045212d4182e30c66e2a1f617dab7e2a1a441edb55d5eff71443514cb1f63440d823ea6fb229cd4d56d424533a7fd19a9778fd5363a010b8eba56f38fd451387267eb4b8614ae7781032207e6d5c3d4d59649c3d10dad1ed83c6ed1606a14f8b800f248d904c626c8abe384c4a89803df0f3a775ee2e839b2ea2af01bed5ae4603958cd33803645a72ef6a3a63e636006aa6915ba82c727ce11f787e8150145c405f029bfad3848522d8d3c39948942043ce35adc49004c37efaec13e0e464b4ae888b8147bd7853cbe3a4a47e084c3d45f373a7a1fca923b2224a606c33916fc90c3f358de2a86070caf7701c64087bec5ccae9fef7d9f89f5a404e53d52478a4c8a59b27c6da9f0dbd8951bafe4ae53f5bed89cd0d7d2c0c849afe75f4ae35a3cd02469b4d63b094e475d0b5d14a2284761485571e2856600b36922929a7013514272811f9010b97f7d337aeacb136ae0e1762d08d9cb896d79e168b2195f397d7bdfe8512b1b82da24de5870843cc4315b060220f24fcc8eef763f5f26e0f5d5795da85c47377d50da26006ef56f8c043c2ce43177816fc2a3748f91028fc046d482dd3642382b954208d4d0a6dbc6c7b3cb7a60e394a3fa013b868b0b7d2c48af22f55923af1b85c6f760767bea30493c9d1a35051d951d8233d870d43537d6855da588cb800abd6c5e1418c9f379d4ba58cc01d3b21bdc4644571e26c4e1bd8c0c7da41e72ea7132f0142e884ac9c7ed20704430e087166448e3736992300a2eff75ca2d53623289f5a1de94a7d15ec232cbb9c39141e367302e1ff01b25beb5e6008e52a76d682394cc2a040683f2fb6f5d39eb9b5361f25868967dc8fb01c7e1f0adfe1fbc67971286bbf53678875ecbbe59845420019b3416d100d34b6ee9534a483077faf32973876a73126d5cb45d1adc39ccb8793f3d3fc08f0ffc679b76e781e21b087f490601507de9b56c7bc2c0e5ea702ac9ef97a87ed5004965a0758c1d132c5bb669a614e794b35003ac60ace978bcc1f6bcb02571c28e6b0a69e86c7a905584de421ca73a61a9588f957de0f4be3c75b75f616060c7b2406d237a74e1991515e28f12fb17f1f02e01d68b47d516cdab9ee146a01988323c87e0b1e1285cf0543c9cedf6803243bf939e6bda5bce01b083b69ad34811ff41b49db5ecb4796459eecf3089525e35abcafbbd6ab74f81a74fc64083c05521c5318a279acd85aace2c0a31043dbed638b55956f56bd18fabf1da0c64ba51fc68aca6893188b9c8eb1b6db2a928dc6c4bdbdc7a0e0930a32b9d02c15df48138d3f50d4f7ef32c42d4b625d4bee629f21205dc5424311e42e93b5295672e43c8c74dea2622f0cae280344fed0bb6275a04cec7649f5f3fa00749134e5abc899a2136ccab350a7353e0f65dfcd563a5ff9fb9a207e6be70146e39ccf84b4d11f68cb68517928a6fdb4bb171c26894c5fe45feab5fb974abc7c899dddfb2431abc522fd34a7043ed281b84d1942cb024f19f052e41cc889b794a6b66cfd1265a85d9f298ec598cad171671f46d1cf68be47e5425febb1a625089f0552290dcfde4b0123730168fed4abadae510f0c92ce825160e0c85459d2b6b60ec8e8d751f63a3b890eb5e319839c211947ebb9463c85b0038d08b0fcf30802e95c5da796512879012dadb493e7c0a33bdd14bb3f2bdd0dc33bff4265c7b820904e6d4fc2f7c2c2913ec1bc62c0e1666d579c8e60908c1683cedf62c37c68ec965806ca346393b820bcc547828142852ba2fd926146b5d9ab78a6bc2e156bcebcb24d9ca9ac5bbaf2e2ac6d39f5bd2e93861b4df3abc0157246dc0ac7058ba9d6eeef78e468045ce257ac3bcc7e9d292f4cb843f47e284817dc4423bb22a5d04921ab62a935063cc6aac86009c6d28053141ab539a292fb20f50b8e710bfeccbcace41ea1c332fc799504e93387f482f805e8b200ba387bc70feb18ff0c8674463c141d4c46d0985c6e4f472023c948926984bb877d46f4628c9bde865a4b25c9324f48f4a70c46e9d56ed4f947a03e937f5398b2b883c42d9f0e0a4262e74ed04a29a2b9be5310e93a5306a5d274a46bb64295f21cfe94d822a3aa367b5982f6f45a10113ff3ab82414a09a6ebf3cb357d248ecd1de29508c76cc30a9d3b8d3e1ebdb5daecfba51ebcb0c04c6d43ece8ceab792a6fa6c8d0e440af16681c21e858556fae70880580b95657a00c016c559ef7a194ea83e78c2dabc448fb053f6691df403894ceadd1bb8505ee373968b23f720dd81c338b818eab7764e08a4b10a9315f8d33aa01764e6f181bd0b83aa627e3c995bcf7ba6cecb669fe1289ddb1d32d221b2e22b7e8af251261069d0347543ad08c54d5d044163337d93b03b8046888f88074e36f9b31ec1f8946d52335bb5de2b66f18160ef5831ebb645c311f228cb3a1d91949e2e8e99fa3c92272667bab87a0f47ee90641367c491a7a5a72b90214d9047d9ae66dc5345ede4ea29387c270c8b14cfb7a97d902cff328f480714b8451d0030798c180b3f786ddd6016afed99992a13a99428e10f9ffe94fef4e129b7ad077abca286ed5ed75799378106526f749d2aa693c0f0bb7693de3bf106b5263f95b3c82685f7e88e8b5011765ee3807fc5a19cc032168487cac351d53a4c8a4011a5222737f1df00491152dd1c4682f145fbf13b201738d9319a0f9b9d915d6ec21848d11a01b058a9b67f7a2ddba64c9f91103c98c29ef32a8fb1a18fb170d1e44bfcc29fc2f4ea2477508251901b4545a8c4848b3841d060b20574363400283246c0edceafde0e72e976b32eba1844f02148d9187ba3840a206b568521a7928e88f7c3c6a0177e644345ce964cd2a663110c97ea38095dded8cd04e01e858d403062be55a5c18ed38533b547531665994e24ac76774a248f4a34c97aac73b8ee7fc8d3e5cefa9ed10cdece8819876a718a6324bc5f919843cf76f162d02d390e3d75bb64c811a9834ae9a42c3e102afc4924f9759011081f1e8cbcee34293c3e1fac522a134fc418429d47e15dbc96cf6afe7119ae313713695d5775171764509717558cdaa77138bb5c7917c37374e8e650960e1d9c4812564fba0f083b60667756233a45099e4d30a1b85764cc27e07b9b1b4c7875fffd9385e603256af0c153c8707e7ef3e9e8120bc9d73b30a870c9b8fe3dd9e3456d1d272616d6dcc1eae4be736c0e26b71ec4f5377b0679b2675575cdb08d902e75a69381cf086dbc7ca2fa51e5a5a08bc65c919bb642ed2bd3fae77adfdf34947647f1cb834c6f2684d7bd3c2ac37e3ebb43f54df2900261ce8a0ddfb4afc58ed4e2ee65ab50ba5150a9e95d17157cea6570d41b1310afc1c1edad0b35ceeb5962e2e3ec662d7d0bbd64f51991787651adcd458b481d9864f656c1f5eb06775402617141d807706ea94c84fb8bc0eda73c0d583f1cca2d5fc2b6d1829d4fd58d9720c2c6af1faa8b468d08085c9726fad1e4c8357aa37fe02126162dba5b503061c453369608408b550c892cc14ad1e72578e4b5b71b25fc959dd420169d55ac9fc7ab110489b17dabdfdaff0c3de57417f1d86bef39781cf7e2b609326dd6b5cb3dc2f388a9a63e5155f6c7a23f7bc8efaea60b791ce2888aebf2e1d18925b1b252b53c08c32166cc0eb3dab09e8590faa9fa67cfcf988c6a02d7a8a8796199a631f916f5b5b694a0f4dcdc44ded7096b6cf7bf82ad132365e73821509d2010b4a1220dc0f592eadb1d2432e3015c357b9b3d149283e643f948ed76b192501b687c09652026a82c8de409dc8bcb72de254339b3c4e9e56ca314c726609d1c58a1ab79211aa48c04350ff10d153a2b89361cea6c77820481d5fd5aee81485fa50ec2a2f7ae7e34ddae46f5fa4c6ce76a60a9f60836c4285f2877d3bb8d80c68f33067536771a3982968489b077f3110fd5e3ac7f42c15c9d89ada3cbeb3bea71d72ec1e1ab27084b8a765188956f1ff2532caaf3c36d4eef3f7f20c2ffb43521e20363e59a5af9a0dd2dcdd7e094e23fd3ae07fcac2e4f7d7cc6c96d843f9c3bbffa2cc0127852ef21073b4898d2406457165a5756003eeea3c98c619a5e7d54c001134819d48ac2c63a93c0c5b870011af3c14bbdfac539561e710b74d9bffe5482450637ffceca2e093203ba201cd426d1c736828767da4fda558138a7d163327e5ac3e50159dac28c72129a29a827a76709f96af4218f11cbf833ecaca12e4866b59ece11e8f39a46f12f7f00ecce40054df6d2bef92b9bd56ebe26d82b5aad7bfcb1912c4de542cf65c12199e6f91839b3c1dabef16d9c106e5bfb86069cbb575703e7183f92e9928beac1c1a8c1c926b671b1ededc1e9a487e4577fe951f1e567686944e175be0748ec2564c8bfa73eb212a7d1ab9728c57f014d3e8d6c91401ea3d97c93fe09cf4fc0d113c34d82a1ee74dbdf6380a5b491cf7a887c61d73a648b28017cedda2e23ddd70de04ad5e2870bf48105b3cea2b41e9cd6236d1c9b529f5cc0bb0b05ac68025eb415542a4f648b7aef9258070b3b24dd19e13daaa56e10d444227440ef16547b87b7fd4e2ea849c4d11c17d83415ab7180f1c81b02ee0598c369bcdbfbbf04b5ea7eb75a20293963d5865ec5587fa355f6a285bc764b47080a5c66aa616b2329ae26ab020ccaaa59163ca5fe5b8ec8d5e14dc928db0cb2d32b3a41522710eb655ac222f4d494b0942ccb980a78147a803402312897c19ac35d7468a1638c5d9bb801a3495dd4808a8f297af55cf6fdab2596a979d74a164780b140b827d87fc645a6fc632f0494c5487ba7c457bfa6978c92ba29e0d1c5e3cefd757b7279d11afd70d87ba11e21d92909c299885a0dbadee58a8f91f312c9a7f691bcdf2346c0e8687eeb433ad18c6bb8ca44b51209034da45e09e75c4d902a3cad098aa5be2eb5b18588fc47f0caeb35a6b2da3f3886eafe007eef120423ea4de1b5f9d65199ab66b7d53d87e7855b2d77cefa3335de6f8c40e73632c20c05813e01ac5df7d420384daa1e3d122095f36287b31fab2bb079132123c629d530f867d8a907bd87a14f06fedb600f1c1928e9dc7a2ebb37877a30a0d552626bdf7719e53809926e26c6e2a674781ff1b70c412948bd8661317a91b88cf798699172d81434ba2cf2444ec6e43cf7ba998fea31909a9721993dbf3c9dd08c311eee5acc276499adb323bc9227bf3e2180ce87e7a8a22605e0a7a50ef579a7a57e08570b545a6ea1dee311800e3394208ac2a9f3b448e1dcfedc61d31fe0e3629cf3863bd280802a95b24f538ecfe597df6b05bc4789fdfd01ec9f38f68e714ebb547382b5e30b72382547500d61281c22d059cf009bef3010b48f227a1aceb397210b09a10eea7486a128ab00c0d4b1e5e1821d384ee6719efba264c3fd41e9218d1e31b12f106d54b88abaf02146a375349d9a31f4e9b0f4b55f2feb7a4d70ed64374a8a57289a0f7ac422e063d0603ef15fd180a4dffc7050dd36cabd7572f4ab54d9b55a8fbb3ea254a0e6bbbc02e8ad7e81f807a693347188badab0f39ab6a13bfd6a79b367fc8c0aafda6da36c76304e300ac4d1f39aa798f5d903210266a077f29c6fe9125921943c8eaae81d74dbde24c16724cd70195946ddfa2bec38bbb3fb72f8646048d62c7ee8fcc440f045e426ccd257edddf53a1343a5cf7374835e62d94a79974288f9f33ca2c181feaefabcffab6c030136dd15da07cc595af2afe4d17b31d580321390f012fbf2d55b99f88e88947c56c8e0c2c155fcdd011a6b965dafc24b86f6cd95dc7bd1d09386f4e75873102ba709f698c831e83d45b9f5994c15b96e6d72cb009511b76a01d0a4f729798f0afc92c03a2a1b83394987a01b090650dae54eefefc94a4b8d453cfd3c2861df2d63578271c2753c9019ac31f82e9d7c24b6b381dd143875610c88bf9707ee580d8c612572546bc2cb165ee3946617ef2f20aa61285fc13a3b446926b3c824fca0bf6bb9776159566074544fd1785398805d8f0dbd7b4a1d6b202c4cf1200fbbfb9e604f73ef0b5b88ca794056ec7920441d054066f3c50eec85b15b72943b4c55fbaf2e6fe639238e2fb51b6a06864ec5cba18c31b9ccefea50173813e872a10104df600ea3ad2470751c3ee0e42967d3bf0765a724c4a494b85c28f33f9062493f8bdda52e93c4e65ec94f5e13e027974004002a45e428b60a59623e5681340f440de83ce8281d2bb5080dc3f27f44f7d7504fdf3cd2b6ab7ad52b7901dd4857918e64192ed19f4195a42ad55608ad09d76e09400d39b4b6754dc68bdcbb62af2eea5201a0c50695fc264008e048c39866eb79d0e379620a6620a26df4171faa2e34eb65b5c0e94168aebd14d259b719acb470ad9e14fa8c1f354b3d940c6e5a1abe2421b2adec70dd40307c11d61a078807e590aed3283880d984a893b95b7ac009737eba9ad8111511f320fcd70d56f4bd4f0f608c928021ed5211217cbb251571453cc0ad0ccd7a9475a94ad2760f77c3216f50bcf86d9a64a5ca3362f4e592a7fa64bdf7bd397b0ddc4a8a1539c96d84af9ab98c21fa482915bc9ce48cf7dc200e4e66a729cdb42c1445778b4035a66c4fe9dea4b07615e3b935de33224b085daa7e98b77fc4c3d39806b38ed7974adaaa1e7786632dd5d377eec86173acd6e28ac779e86804f2f6c95cb8d3cc9632b167927a7b1a716fdda9427383961268f0f4f07a53391fba0f0fb2324b13c7e834bc966f9a3f15718c636c5973229121d95f2eb5d6378d608dc982eac3c1289475158a57f33c6f045af37de76fb28e0d73c53c73599a6b8d8f8c179717b7a47e90d6acf1447c4372e7a2961bce4657d6b576ee064b067ec5118ae40d92ae0eae1e2a4df95dbf412003c331d26c81e469a53a56775bc661cf17bc786935d12183cb4f64423333de82e02156f5129bfe3e8c6f3c408e6206fe5b6109d80f46fc509fa32438bb7c23d499d299de4c40dd94036216f54e13aa90be4631ed56de54c51554ee447e64efca8f5e1a7c4233cdc2cd8e471aa24085c772a528be3e12f00a091e35c254b4537f8cec1096d6ae6350b4716dc417b24664eb198cefd9fdd12a823be4d479f6a1a88aff6bc1e4c75897b43e9c43ca4b39129e53ca1090770362eacb121fd903e357bfbf5abde60f7232f2f7fc50165b6201bdd6d59a4eb5c8183b15febf2e3293fb09374a3acad4ce93e19252b28e9a8cb6bfef2e541bd3422e30925f5d80d060c516b9d4c9477f4de7d89c22eabbb3c9dea6b18a2579b11a999834b88e4129419067ef52078170a29294661e28814cd6f7daf9322c37e10da81e7631bc8abfc7e14fbdf38b971abbe0b2eae59827861413eee78b630e70508b90124a49e5353a0153cc663a3be2c71d4c3fd44c430e7360b0f3c10a92ad3887059bb31a0865c54d7d71ef314e522a2655e66c57f2ef0354022edca9e7fb81b63c805ad43ed823448042c0f8f7e8549f47ddfbdd96be81defddbd6873871dce7bf3c6a95c9950d91eeb02f11eca04b5d3a75bf5bf3b993db9cc0ee1bf9dc2b75c1a6a964824c71515e35453a11ed9131c22191bf0283b431e5c56680a0b6289bcd177ce83892f89aa07a3bdede52d09a9e7fe9f4121155271932c6764fd6900d76ad617e462e519ad9e83b2984970a98df3653d85e3d1c5464b86fc2d4fc85e62000f74bef6d0981b05800aaa72790d019e62f097072c577621931fe412c92e8e8e046a9dcda99619afa2392101bee5b21d94d79a968873a3720b6100a5dec140025417f75cfff4382bc1cfe205b06f0b5471eaf1c7cbbbc5fd3406176cd8e5f24fc925425ff966288bc7baee0c8107a2a1e7b8486ad2784e1b31d58d91a9f05fdc08f714261022f45de89df6d5ce580d760b92a5eab5e99794d1776b98c34bc423207410838758d2861612318cbdc80bc22425d0f39130bad243c50815f10030572d82ed8d5339615ed82bc0e0616bf96cc3be48b2ced61090cf054bfa52a5413c023125108194e54625db61897cb18c688d743407f4cbd2e848d46fd6744e1faf7541a008a5e37c56ecc5e21bb930ac5d276785a23b14e72b7d801a7a435d9ed630722177d317ed028c3d136213ac4d5d7a3b343473034a2f926f59309cd5360799c21191915a8ed40367a9600f18f21a71e5f415bc511dfedca2940e508ed675aac19da260c85ca71f0b92362858188c8111df35800bdc5d89c64d7681d23bebb075f0a62f3ee2a75164f2b6bb7be59652ca9464d206e506ec0658e2af7e3eb96aebe753eb64912d6309a3427393931c24734b8f71d18db88c5dc118f39b92c3bfb97b6e3f43ed059873b05fdb3401874e0aa5dbd010618414ed90f90618b03ba1010ff4d862031d08a5166895b571f817623ee7cc2ec949194b0dab894685d8dddddddddd2db36e92ac558767599665b5134529f28ec90f0773d8a47b3f62f6d5cf63e11629c7c93ed20c75d35ef75eae072e67dfb2932d97c5fe5281439965f7d6cc9bdff325c74316c241767e0dd39eafebeb20a446b568b10536c0a30c17c080044d0b43ea700ef9b908902109b2198c1c7e3a7bdd9683b2c75c14352da359c9961a5614d962493648e61d2574162381124702248ded1d9e672e5b0ddbe059bbbbb117d873f6d87bf68160c061d7796ab01f7e2c01aab5f75a7b2ff65d77ef952de35d194949818814a26811a58b5a5db000b4f09ee052cc0427961d053ec1fd791ed007c8fd433c2484a45fa9d68a6158fdd1c2308c31962d3660b06329f25a6fb70d187c7388b13c2363d87769de5baa4fabb59452b0b117c241f77acc5a1b30d873883b0b71bf9602f3908083e01378be046e804188aabdbdbd3f27b27799a1eceb52e996542531e0cfa154e1074816ff2ca820802b70d8a54aada559b53a5bc0048972e3838b7c26b468686e688634116db4d0820c3500206157c4b01b739138a8e59295a7fcce6497e3c8a379ccd0bd18775d18ca31c641ab04c9c9411b48e0ee5bd302cfb728977e5357d5895224b1c82eb34572b515aa7431be6c8ac6602c8a38c93387778883ae14146972914c20029c05e4c8a61cdc3ab1bb9d28625f2bfbe524fb37c9ac158d8332a94b49f65f925dd57d8278333bb7a35fcbc4f0f387e970cdfb513dd7b776499eebbb412e8c83d9f3027cef905b063cbfd02ab9a5ab74ca37267bfd6caf4b0c12844571453b44e7d0da5c51b63886baa56bba4344eee568fbe6b6bee215efc5d8316b635ba155d9a866d56463583786bde5ba43d589b3607f4f486a0c14282c3c32a07df6dd1329bdd0be10a3c215afa86975a4010089062da8906aadb556e9241792fdd6d1efa67948654b71f96ea9cec1e91c7c4b71d725b55ac30a786e9ba721d1543c4d89b368473428648b6b2a1ec97fbbc9fe9cced1cde97befbdad9d9080c3cd146aacbe39cdd0469a2c359039b2f7df9a90229314a16668cb917dda17640e4c4890a6b5b26fa6ec9f1606d9e29a93feb49646050eb794e6573c593968871d8d33e461470c5a129ed4141df9d7951469bfa99ce42d3559327729647f2d26e675f8a5b166c82b4b4b4d2da5890eba3239dc524db20f21823e43e6fc8f9bb9f70cfb6dd338af5f83e13927250ccf8e38de0ec9f1b487e125b1801ca97cb83d21fb6f29c9e5704bd10d8637475beade3ade91a3554ee7535121c1cd9a13197f214beeaf31dbfb177279fb90f3edab31b56e9b86c7554da5538584bd9bc16206311b12a0e0848d37e594d8ec24169023abaa3464834601b4181bc6e1c6c072cba051007aadfde46439d1406936dab8d26a1cc4d29a38288a83607c6bb90625fb2624bbf57b31eeba7f10a4a7c9e2f4444fffb547ee0b1cdabf21e822f0bf703e141831ea7cca77de1f04800cd124a436e989f3299ff2bda43ce77b916148311901994ea410865192f9468c421a93fdf339719ca29a725fe07e1db3072f043d6610f463afc9ef1c587d7bc47a413c76afc7decbcb0b8c2431c2df9e366aa367942202644f79e97cca1b31ba9c057ca4f21ccfe303e7637c8cef2586d6f1e66ab2268b7b607c73e5e1bef3303e86e7f141c6c77819df8cf179b887f1510a33597ae4e1be0af848e555bed9fae6cdbda2235a7ac2b080436d5c390c29fb5f1a1cd213f7ae8da78be381e3388759e51db2ffc6bdff0e99fba46cb95f0804c5f1e4087b25a0811550a3144f8e360782ea31d3cfbc2176480bf888333b1b47e0f053e873ee17448f793e7dc2137976d3ebdecb7923389e367ada4ab6d8b741c2f6436dccdaa88ddd34509bc78099c1f248694d3384912ca9be15e2a0d2102431d58ad51ac9d5cae44a6bd59c522e774a1cf13348522455b9bead9609bb44ae36897af355285f60d2bdf3ebd141df0d2f604bb2a45a6b0bca0c561758f0a054e91634996ec1cab47e7394565a29ad1f082aa5b47a75f7fa75b4e794d94917a49444cc10460a42881f424c25521079f57fffbdae43f6d7a6c02e0efa3ba07dccd0553d1676b918779d8fd768b80105ffa8b201d8f6d06fc31f35f73bc005f7d62803eebfaeebbaaeeb9ab4ce99ad7d1f33f4cf7ad6d57fbdd694863f6ad79fd6b3d77e3d1c741e0ece10f6c183c29f65ab3f2780fccaa486bc4182e65f1fe290b5c99db41e01e5a04b8983ac64f9a8238d6c49714e5c2ce10a57d8620915e3381a41deb4800062da7477840e8819923636b23b80a83b42f731c016b873f8f9e494522adff35c445ed94a61a3b047e86cdd52ad5d6b0d2aa07301d77badb556e778b0b7d65a6badb5deaeebbe76bc2c19608cde9a302d07c9280eea19641299a729ce21b4a594628b2db6886188f886c11a2a2ca5942dce106e8cc18f67fa794ba52545fe05e92d29822245349c41bc0cd9afcf5bde4ac9309d846471d319b2033159fc5e81436f410187d2060829929c8be174c44ca2255bbc0a54e4cd845d54aae676504a5b2d7b8d2b1823e7468c114f48504a96acc6d44c8d28a6523a744c7c350ed8041cb678bfc5f97d5d0e6f8b0e7644294240284b514acfb44cde78a87df9748e13db37f7438fb6ef05c8a84f93454712ece2001ce0b049a4f9f7da80c15d44b6f8d3245c7687985dbfca4ed35f8fb2650b8cc93b39fd3a640b1170d8a20d18cc65e2146d1b393988c459fc9bc8168db459f2a9dae214f0f53f330cc3340d9b5e2747fb4ab33e225bb4720a29454791fd4f4630956cc1be4e8972c4de3ff34203e4c66480419336c2a692d2260581116204753211514284bcb84dcbb0cbdd8bff41f0fe0f708f6699735e57dbb06ca35a7683dddc9beb86dedc544ba9b5b49bb397bd21c25a50b6b46e52d5351b60a48fa571623f1f97443e1f299ad943d9ff1311204524c0069039fa23c1cd9fec946ab4bd99a513f73f3593e56252b22a6b7dcc10462201e1c4aa5cec9d728a2bb41047403a2bb4469977c375b0d65a2b37046cd61b030ea52a880b40c0250292021234df09981f612a29542b2dc6184b95cbbd5dca908045cc8c9dc2904c594832b5d5869dadfdaaccd7e5c5b0eef46906017d4cbb4f82c39416fe20d191dd52ca29e56782e07fee618309ecc9eea3cf07046b3029606b4a29a5df430819e7ba7ed2c3f140a574efde8c506bad986e56f835e24894843e3ca4a807077c7c0088203eb339ce5f1e77bb65578e87fb1a67e79433e38446e494cb041ccab1d29107c692decd411ca3a361e3268a838dcab28611298d5d21411de0e7068e04f8e0b2a4c965adadb5624b2291bc2f30c8e206d8e1eacb929ad2a95d5b4f8dd65a06ecd9088e6b02bb026949279029b0a6cbbe204f5ac17a53a38c20786f0d0b3504dadedd9a95c07b7fb45a4a29a594526abfbbed7811a1d4dd2a548c9db13536a3a59173ce19ca462ea5943e9234642ffb7b12448304fd3d09a26c14528a3e9fc24a919d63aaa8cdd2bf7fad0782f97d068a61d88f7afdb42707dd8a0e1ab1289b9a1fcde69c73ce3967f6b94c161f1b85a2b4b552d26e300355abd629d12619a314d590bb8e933ac83e0d1670ffcc611db9aeb5d65aeb65ebaa66066a6cf15a5d97102d831021a3740a674bb997f3bfdaa2c072947dadf5baaeeb7ac971385fb77d3e1a0862d7b7eab81eaeebeab6ab1edde3e559172b2419569421c3c6482428254b569ef2195b93fd65c897a2152bce10a5488ef312e20be8deff8271d0ac6faf530a4a76e996c6419c83b6f7b7350ed2ec85a1d279c7ef6fad2d2243f546b2b8146196c898cf909d0c32de6f96f1d913c8902143860c192f63e5ca7478733cd49b1919efaf4171500cb165ed8ad779860cafb6bc0ac5c17e189e55f13a9e15823d5b4af1ec108e674df664915894556263ac8c8376891d2d8d83ab9aceb3acc9b2429ae1da139a94f22f8ed1d1b8a103c441d2eeee6f09ecd65eddf6765ffb841def782f103c7a70c0c7071c24859050aeec5eebc8cd7b91a9130c61b4fd7db961aa220565c4fde60149400f46db6bde17389423105a032b8a8cb62f097881e3a770ffedec002ba1eaa96553d3a6015a3b30bd964d94b43116e5d76bab84c86851d7375e2f0a7befbdd7f3e6c991777c3828b4a80f38c83f630f182c928859be60544ae283110a28e4eb5a24d9dfed4cf66fa2c4ca7013904d6eb857b5e9b62e471e18766da5938b82c3f4dc78581e1b8f134fcb038586101a261aa5ec4f834423080d22d97fd2eef6f4c0659595ca8a524ab3189c554be7b43694b0a104a63f3595558d83d86a295c835931d8d3dfd9a3529355aecacac3b2a13543786583170460d96023451aeb26dbe024fbd360c312d9df86920d2fb2bf0d1b1a8e647f4ff44eb7dfc39222abb2c24770d8417945246806114f94220d34a30909fa879e911938789514613f630cd9bf06f1f2567855e398e520ec2096821469b28589cc816d5709cf35838883f0e8339a9020ec04b9c24138630ca1caaa48f6d74607d529700715aaac623096bf8a55f61a8ae41a44d9e25965fb7d1346c8d70fd12af5ef45e382ec160a2fb29fa0cf30dabeaa9a2c4f68b25f28326d714d70e86179284f8983aa8795ddc3f2b0aeab8e34ab1a1c5299ab3ce9b4a7bf1e3cf70c61241d3c244d4f29a5fc70b27cd0736c9d83bf740a94cc400823200b78e28a2546f6e5773201d7cb1cd6b000983bba1400038eaeef455221ca08480c28236b0019fa48d1cd5ebd5d072aa5fcce81c98d33bf4f16708803e10f0238823832810282a446402612e348fb10c4c84e685f11e0675fc79a488ca3edb30fbb2f6c1f0e50014152a310878b0f168b75af96b19aa47441a51de6a6a39082384812f1218ea4d5fa7ca4fc7c66e85e8cff3598ad9f24459fcf07c49f564b8a14d02d29eabccd10f6a8ab5533cf6b82b5cf435f7b2346d8e7a1df4b12fa2f9f0fdfcbf59a80a980c36e81335d051c76ab4739539a80ed78bf1aeca473f8118d85ce5a8daa548ec91e762bf493765d970d396c980ecb36f6b3ec2792c59dc465fa35be02639f7debf321fba64891c133f4f9b45a9f96c719c1b6cb58163cb20f5abd72d83040d8de41926e853d041cb658adb558ab85a9cc8042b6b7cd1e7df92104101fc8fd1cc8dd238738cca697278259af9417b59eb416ebc66e173dc28830a52126904c9d1ac98ced39b91d5886653158ce093361661892ee013abf7e941da49459645c0536e97777c334cca8448886c30cbd9752ef0a38ac37550c5d49f5c669e4b0de5821ee94524aa96a098d1c5e27f9de7b1365b44f9053ca963de79c73ce8997e0ebed7be370992c3ee5a8d26cfb938087095c3f1d3730c1dd9c5dbb7badb5ef123458564359aba9503132a91907491b6dd468ecb5620aad983acb564cd55ed7755dd775594c5e97b517263d113466ad7d6dc534439a632d9b568438e82b301d530f300d2612549d388d95146d5fb940a326bb178eb08249f6a7612545f79b742f883da80658bdd0246b859f9e64eddfbe7f0d6b49a19f2c13d99f90382d94671f36ad98f25d3149917dcd9b292fec1deecefd9da1ba72967e775c6d349486cab2282d2837acce18348c1dd1b574f9dca0fdb97241490edfdd5b60d35c976865d511d3d9aa574c3967cf9652823c12ecfecaef2cfe3924e8efd393f28a2364c8c7f45e02f31a66b294268b49b6489983481109fa33f1b17c7c2916edeeb6d6d660611103278ec50b887c9aa2b070c1921c766d9f216cacd7c899b22c935266db0d1c09a874be1cb74f866d5e678dd5c4411b270eda15146089aea0285d51ada05662566456522b332b352b362be30acd8a93ec4f653f953fc34ba5a4df1cb52ba81b505224adb85096446f20453d041f406171b08262e2834c3f547d02afa0b207801480209f15d40a6a05552b789f90a4846271ccd0d75abb7348fcb2c5bf4f0a2c6a000e0648d07c77c781e3de550d8b7484a3503132a9991a1bd6484329a56d62c2d42813110785397c7ef0017dce6951286bc59b0512255b04d902091743f2086e16410a1660b46aadf3344bd3241a9151a5504a6477a752a9542a954aa552a9542a4529ad61054cbbbb692a954aa52edc7d7f9aa73ef7f8b7ef6586152eb819bd00e9846194a41f48e7c0c888f3468cb6dfbe174ffdf0d726f17ba932182151479c2f49f61b0f3cb8af4bb3244537260ce42ccd215254bf4bfdac01f7cdd22cdd590a53ea9198d9441415f0d1f65d2649f412b299901f7691691ae2a0142607c9b771046b3f4b59be5660c9dd00c3a563fea839fb3cf5656e95a77e3dd329227846e1d7755dd72ccdd236c268552332576982985aa5544b461a2737ad6ed251ac0c19365253c84e4a8a1090b38e49f6ce02cb37505e130017d87eddaeedbab87edaa27813e5e6eb966cb1e9616620b6c0f60b716ca9d40ea9190fdd6f92aba8998226a59a29428f34d52a07adc5816388ce9d4a7d4960fa49755bc0ad9aa11f76ea934aa5ae4b45e41cb1f6e686084cc4cd0dd58270100807afcbfba2f378248a29e01b60c0df441491de51784ec0a1bcc9420421de6b735d17c773b1aa1d13cb3ec4f2e7574f6bafb6d6aa6999e7190807613f5ffb9ae4a0e739bf17793321c0a409064170ebde7018b4948a555575ec2c6daa131b24fbcb7afd5e8cbb4ed69e73085b6b0ff103cf1cfe942d32077ffbf980a0ead61a83331654154b15787e1738acaa6c22525555652dcd4a4b6930f8481db113d3113ba70e920eaaa3a4b3a4b3eaa43a331dd9ddf7fe8bdefe077c51fcacfd6ffb9a94a0f9d6ca1cea1756265382e8dbd7eebdd65a6badd73967b78e583ba227de4b841475eec81bfb756274287e1c52b4ea14e91ce944d191a2237644dbc3e22fc4aab5b62376c47bc71ad647ea1861914c24d931621b6999963c00c9e22f3d94019912c2fe89112f1cf31e415624921471242942003502ce02befe76866dabd58fead2d669fb37f5fa354c101c5e143cbfada8944422594bd361652556bd61d938694111622ad92044288b45b529606d955d1bbbbb291d6f0aa594d2ebba2e4d0ac9e2af4d917d458b912d2ee894fc3ba5393ba552a794afe6703ce72e8e674797b783c3f1e8c5f126beb81e500ea232154a1ee2c7cdd80ca5bc7f75d2baafa578ceba977559d995e2d951e6ed90f9ba3e85f3a17685ecaf8d1f5e6d4cf128eb5ed66565578a3747da384395c5d2469636b2ee655d5676711cceb579aaab5d557655acca929365db3cc60f023a5c8753bf6eb5f3eba1ff47cdf62da97ed6b6c5beb0b644d18a1100b313d937d7ddf56686b2b75fa94693712fa89dbbd7140048167fb05b823b1b27d6b69ed083121746b858821d516bad18638c31feb07aefe2038a5a73286df00cb9a8546088391e6456d9c002dbdc9f8bd8a8d911efcb7967db4c2a9eda8883d7e8e0ca9304ee1cf41ba280c58e9400909eacd6da7b5d775543c23226128c90d210243128d188eceea6739bdacfd3fc7c48fff98060d78d4b6652314a8894864c9214f59ca7498a7992f64dd264710293425826fb28f499eca12fa1c9ee2e47dafbfbea03761dc6ac21f39174e7229324769db366a84f2767b1ba50abf5d74ea0f31c6130e44e2d87b215812c4fc0497946e006987b4f3bbabb3112864dd30cdd28cd298339e79c734eecc298266992eed532182c1a3a50a15c26355363c31a69e6ecbaaeebba4e08324cef5e8c5fe331433e6aa1545051c850c35c6215a69214d95f747053027e37e2e0c9c11923850cb50d97f2e02a262605d9bfcb025791dda7709b6ba3027fedefcecf515d7f7efd1a06316405b84b327228736d7f391e64fe7cc091e6f985af69da1d713994ad1eeadf77d40c8517fb3a3b884ffd0bfb897533d43029301f783df6bd45cd100c47c150b9b7f3c1a474606e92a33ac6ac724e4e9f4e319e73bc8e9921771358fa09d3f94d4c0ab2e8aac053647feef3d93d0d07611a06069b73d63a6796655cad2854ad1c8c92e6346064649a00c5093353e8eb72919a8d2560bb044cb32f016399c506787e8f015fcac202ec722f0b1358ca16ebc28345091c76ddddb4d69a612ed91d3bb3c2c7ebbae425ad94224f14dcdaded6ed5d472ae5ee1a462261586d92b1d4b09c6844a4838610011052be6f839b5b6f9ac712011052ce3e1fa683649e12f489657f1e39647f2226f71bfe784568dc73fede7b2fa7719ed37ed37efb1fb4ff817bcea7e33341113c52be16e0508e4524f121e5f117b13de78b4879fcdeef03fe946fced35f0538bffd0f9cef07fcf5e0bcc5e30bec9ae6c9d16734d27ae33c6d7b1e2f2f9c4f4ecb7d2fdba77d52057b60c815099a0fd6b899cc7a726aa67159a67d9635b1c19cb3eaaeebbaaeebbaaeebba6a5d11a58800b9ffcac15fa2838c4891e52e71b2f4775f5f98d22d7186fa090f728ba1c7c9d25cae9798fbfb6f1538ecf1fa1abbc44bc456351d095b410cd4d44e736aa9134a498c0c0d6ba55aa235c9fe73da50825edc9a21ecdef93e3d58e672783930f7875b0eea0087dac90b09aa4db08d145d5d60275a58223b3d42f6e7d848517ded2445ddc50d5a906638420ebcc8fefe35dc0cd7d47278ed12377861068ecd2907da49b6e0126e9d2a6e65a772a6b43e75df550cd4f6841a65d0c10633947a5fe08edee6fcae6aeebd3455758955ca5a2baeb5ce690306cf1cdeecbb977559978b7a3591fd9b90a2be86789709e3aeab4faf52bd5080c3b7cf9af7e5a41685aa7d6b7713d623ce623161924516554c11d69b1d76c861bdb99f65b19c47576a2dcd25a6246195e0a41933e718939a512d69d2b2e9965a86dd6bb3dff6f968f7661877ddff030137785b44dccc39e7b457a6dd3b53a9eeaef762dc75ff20f8f9e08889d1e1225b6cc949d4b72c5aa792898883da1a9151a5504a2ced6ed949d72417b8d65a2a49915d4286bac922457d44da22d9df3291bdbba96d6bb243ba52f655a9b3255b9ad1ba2d908fe3411c3e3724d063a6e6fef7bd6fa5bc32dbda3694b8f884ed875f6f5837f7afffc7301a3a6f5f5365d55a6b12f0bcf4c75565d12e82e8aa177631404abb1b0b29e595b7a90c692f676e7707388bb3847249ce3207ff06d0c84e8313300fdb474313b0067a50e186d5c9ff63f7de7bddb32cab61c996263662b68227352c6b2dca241a3921991955313256b6c9d47d279eddfd09eac8ff9a739bdd3ab4398b7f0c67714c5ae193f39d211f71f41b691cce73388f9ffb5e6a7061062f462f40649860d4263f028911d7f9cef7e2e9c75f07e918d7c11f891fb58ceb00802c8c90b0468c7878fae39ef3f569b2705f8b5b0ec236e998213992f9a5cf200499278c5e8070aa3832e2fc0b9001b860b4b90efe40fa8b168cb84ff15e3e47462f405ac988f349d70148e760c47d49b4a74f606a32b5c973dbedeba1ffba3f6ad63e8f7d99b1e7b1df764d264b0486dd6037d8a4947226d3e55635ac6669de6141a7d3e94818a2105775462e22d7900c254aeeae201dec5eb6d2140eb76959a7d3e1a4743a9d4ea7f31d189ab67158e8607f185e6795daaa5082c008290d319d90a094c4c8a432223768a2058d16363065289d4a2622a21119550aa564892d95582c97169c7ccc900b769122ae740f90fd491f14f009f0fdb04956fbac8390db07434042d83db0c97cb048ed7f79f5eb92e57670d925067749bec7072524d1050c48a491f679eac723cbbe97249e1f5efb5e9204a21ba8f40d7805b5642302000800000243150000200c0886c301b16840ae4b82ac0f14000d637c4a7a5640190944498cc3408aa214520611028c014300406086862600dca65ffa758d088e0c9fbb2a80223a854921dc88db41a38e19c71f2e639496a7f744dc657595975523788ce5a50ba1cf153e2dd552211c9e8bc5d80139f76d0c3e85146879db58f205aced32b4176d5bec0f53ca2e22834ca258ecdaafd24c10685e9ec86e1ed6d9e0008126fe3cf031cfce5c5d169523feabebd20e83ac87a92f953b9624ff57b6ca76a2438acb79f3b1fe96b20f5f6f1852f058bb1d9bc9fdaa614087ad612060e5c03733a5b038b1285a4564be626c8be87a89d94226cf7d2044cf5f9d66456fd05671fbc39b42e5f5e63eabc96d6f790938bff207bf97cf44a2aea26140a70d9f5d5e835580a85454019daa30a0cae0e2933ad423f897084c82f159f28844e09bf65ec415650a9d66c9c427207227f18de17dd4c24ac5a363f0c10c9e1d11845cf8618ff211116793ee4a6e27c7eec081c303b885b9459f5b7739aac05252485fb85f7bb52df86713599cabd5380d6eaa498a483c1ec3ace36930c8477924e2db8c9af4f6435178c5e0ee2d748feb9bec0a0ba42344cfd679604f3df7302488bc4b5552151b37fc8a50d5e9134145e439e6a472766e232c34e08b7a665d3171b582a4003dc6b3a69aa6b568f0430dda12d426c0119563a6846bf4da3c8d07495df82068dc87bf01029b123f8f5b1759afda636fea2f9f779e383506588cf88a2cb373b213e39ab97b7cd54c73700d11db4735437e444b95bc8228c4d7cee30d8e86c93c33f0a0a83d1d422463be6bc7458b48cac2cb1d1816054cf77c899fe3d25e251e7e7065a238bb477cbf1e2a1beadb856a4f542c7882bca20d9994d6dfce419c8164fe5b1a015a4ec39652e722804927eaa3742f24d7d9e159e4e102e263baf083ea3b7114d86197e454b7925e2e7e6ef1f9a159ab1d82f60f09f415b7f8cab9a3b0a7b2c53a95307116028b74b9a0603806115df12ab9f38e8be0a963080b5d848692c00e1a2f6cdabf922224b40bef60245afa354b958637c12cabd2205935d436b14ffcd727fb6762e3966993dc7747879ad4f8530cab94e7f0c2bdd86ce70f18be2f372da00fc5f4f314501cf851e897740e258dab24e1342231feb32478435ac707ae266404e513434b04a869a56922cca61eaa75c509f9a31e74345d81454d8a1cbb081ada731cdbb7d44f713f2391e3954aa386fd0048799eee1f41e403eb24546b78d05ba47656a447916807c372e413c2cd7800f878812309501c19597344adf556ceb5013eb46db954f5ed95429f072f5612ae78424b8c8fb08abce15e71c53ac698e65048d165bf16c097b30d47137b4bfa3caf8ed3f27021764caa4134c153c5533fc2df91043078433b635fc57f15301ec9693f567132862509e779b5399affa58001cb2ff4c371a259ac8aa3501a6b6a4db9c685fbbb337d8e8d014fb366d263b7ac644e50f73dcca9950b976f306a9a471ea58f9c66bc88d314150c3e55435794f18482e7cb367ea1001f220e7f96d591a2f71ebf00445fb9226f80a124c2f88f6419059732a1efb886fbfeb809b4936f70a98bb6e0aecc8ad095c093efdefbb857998afb56a3f4db20759d032ed6f3593d3c148d7663156ad9361f6411285d269b383cb258b5f4d23408f240347c6ef8422f4a60ee6759efcfaf45ecdbce013636b3d3924f66be24ed4efcb47ad48a5608ebd5cfcdac2fe9e8cd536261e21ebba14a827a4b49ce5412fbc77a63f661ad31950404e623c6f065ade08683c42a8b9b22a0d61dea5e2d945ca20a97f46b762e48ddd274c325bde1372ef9dd2cdc6277a892d79c9d0be94c44ac4adfc55cc8c600a1cba04f217989472d92c29364d7ffd6489be6d3f7629138a77a2d2431e931c4ac1f04ad56846f8f2639ddaf2b93746fbd3c4ef401222e153527cfca03b211a01a2a66759b6f929aec638d95011d567318ea67ec855e6784a80813c378295c48f8978aeb1e59d0472629d1c680d188f66f0a1a0ef320bc080546746602fd037a4dbfb87603dc0ec9c4e219a25e0e7d2708ce5adbdc12f912543eaad33921bc2ff158d7cbe9ca3d5894d5205442a6942b6996fca768dc09ae7856c02014577938adde74164ad09012d22ddce24110453ef2624a02df1e9a3e3b2abe3e99d6440556456c4eeb4364e4588a6a22e67f29f2c75c2522fe02a3f5e31fe5557f4700509afc185566af0cd0e26a2c86b7b745c5294c922949156fa354802f8d5a5732530344c3ea36af71e1decfcac3274ce67b1a92b8e2a609e93c83ca5cb208d27b90c0be62138e6466130223993f29436551884f9a2e3488d79b6e2ed1e90eda73d2899587094409d8b7d85f4338d286723395811cb14b0212ee4753d6b85beb09eae7625681bc50eae7e459784af48844cd13d661f588a0b3a5b8cbab5f9c9933b367a3d2fc14f57418b81a8926017dc693d3526d1cd8b1a01c6693138a98d8a78572c152eeb0455bcafb5136a3f6e5ee8730371b612533ff28fe3b62387b48f7d6b5d728ca4077bc44086bb052d6418fc1c17a3d042b71f54b1017b6e25e61940cde3992ec4273a808556e072c2cff02eabe4d01aa7b9bd683fafdf963d447c5c266b5efa0f6764e7627db79d2bd64bffa67069fefbee62c754c0d3921492457b3856cda2ed310777b26d8190a3eaf569ba6ac559d08b9956f9c898e0d4961ecc3ba5793f36caa0ba866c0b773d05f35d87fe5470ea4cbe25121e649b035dd0377a545fc775b507e1a2fe8fea1eee09c20b45d227cc0e2d735f239bab14a719dc93c3c1578024f2b469223e1171a5e2534202fed853be3c860cf879e7c6fce99e184899c61753b2ae5a4e8c9e2f7f634d17b3d5dbd6697210c5653d3d59bc59f9678ca31c04c0c558832a6c68d842d5d6439667625dced9c32e719c4021d6147f6797646bab974e70846b07041fc99f052b1081dcf8cc66c34729d0bee04a8c08b15007aaffacfd237f4c6edd418fe038be65b6f238ad40abdd791ab5a218494184291e2afddf65530f8fb4e341b104263177892bfd5703fc4ad75b595e0698bc161787549da67a43e360bd12f5a85b5c27989954dc45df959980ec6820c85a94fac897ee793bcd8ac0af34187ed1321f9fa308297e8b6f3a3680aeda7cef416bd52a5bba20c8be3ed0cd2b2a818e95e6fc74577ae1e64d27129f866d813cfa6e50b4c26469b7acc61b32e6d95d854660f124f0fc410a36737927221ddb78c6d7fe67ee789655a3f047b8fc565b246d8b22d66d80b70e8c0d00ff61013c8784ba7af8dec22e8b6aec01e5896410c2636db3d2e6059bf1c9f03eedc48f920a5bc9b3110bc1011ae47b90a853eaf3233d832948cbd12b38a2492ff088b8c0608b2671dcae971724df25607de094727c9a8fa01d0c1e9924f4c7c947e284161aa94ee1e510f4661cd7870fc271f7490d8f531cb87d22d075a481755b4d3836433b0814083a00e8da726ef12483ef84578debc5b52667da3af290666687731de0a5a01d8ca3376e290e485dc899514a6ba077709fd23e1bccc66a55e6d95ad0295076942ff35af2efca1bc4e2e1bd188cced66041a5b75a1448e40322c89ee08efdc8a47f252618c41aef71398f4ac34e83f182eb139b1b14dc62014412f429d30a4602c19da5dd8104800a4733bcbcc0e90e42826c0021e7099287b348da5b05765f1b12460daab3472bfa4cf145a17ad339bfc8a868d630cd7b898b3d512bc5fd1f418b5160502e98e37ce8d98489c87e58040dc82eea49133f5ffa317f88bb8e74683d25ead83604dd46d9c5122b831768908cf0881ec369ca3041196b53324e7bd917e39731ab62af37ab3e7d83a43ab6fd48cdc2cef381944fde011b05e667423f353067c3739f64f5be0bcd320045a16919e7186e418085350c66b8411d4f7289b8beeec6b2b37e55b0e855d7bdec2629576ffa6453ab8a6a933cd195bb78a5202cc5abc26e0285aa55097392afe92009d8c9b2283d7d913ec740c9bbb98906469bbf3ac36d051bef3582b0422633790c6888117da680900db163eed28462c0c0a57763174b560560e3f9bee6e8b6df1d572a6fba1bbb673a0cc55d27eb9ac002c67d0179359dbc5cf102d0d8e411287b6aaaf2345c028e11efba3aabce7722f4f91191248f472df8370e7fdd8b122369ca2a39ae310e2c020b967c9a9aded74ab0ea4d032da1408f987a3364bb6a99590c60fb615093a29f342741b935e82b0325bed9582a1f9bf1f9e02b47060707b03ab3fa7833f60e878560871ac603fca29143b443dd88af70b661e7d46bb35aa6af3d45efb3816150237b5f6404954950ba686712464374c505aa4490a6edd3c022f46d6876ee1c36ac98663000730e3b4d412cc1f4e4a3461ff5fc88f2d46267a643e60a00aabe54eac9eec1e3c41656de54d4cb8a528eff3cfb14c64018a3d89a39252af20b55cd335db7290da8ace21ebcab9ba2599542a5f7e4ef3d7a2805cf728e612b1f2f2ca7d335402a29d4f476d1898d5d1e4e420c343d6d880a7fdcab37410d4f7d1eb7df8cab26e60ab802a3414a5b4fdd11b9da55c13b4292d1e9f00749c73e27a3041663263e4f2409acb2bb7cfb0acf359c23b06d6f5e9fe5c0f54e9fa8fb4d058bddebaa05d6e226aec3affb3fbb7e65434477b5b335373fd4446bdbded304b764c5648c2c21ecf93b707c6dd96b3bc7bffdc6d057e53707e52186ac9e6d3db40ce74720e7c0d5579edd483f531c4e2c73863c63c152bc6c72bb54b9efd72a47db6d758c34bc053b1e254d56cd97ae2c54daf01c599c58de1522dcced93e78c9b7835e9b3404cd2c60941bd990ffc9e4e4ecd5234ac2e942faf11e3fec7187fdff51ba722e0465d3715ed34311f90b50b348aba084f1c367dfe2f24158c8e3a6b2ef382acace0d62f936ab42b1caf4381eff65d2b3048088af15adeeda97c06fa7cabdce6802ebd07794e23052f4bf6049f5d86fa5b10f58b5c4093c0ec420222890acb675ba14c9c647db86006f28ff875bc0c263257eabc4538b1498f909dc8223cd90bfcef706069ffef871119b96c6f5d5021290aba2f81da860a507527525baf514389fd3e1a6d8a0634c7da9d5139428e0bfa6bd07a0bdd2ed4c7fa34dc9a72c08100ea06bc5392e744965c66bf8e8d87a9e2f3f65073d7ed77305b7d402a6040a361b23fe1fa3779c425ebd2f947bd4c32576c983ff5a069756907df4246d66ba5858d32905b47e0d320a81c5d92e08d5c26c7d806cb11f4fe7781545a715187649ae8e6f7dbb8c0d4ed0b2a4831425f3183de507f8f339e97ba7e2dc6a9ee732fc2bc6c095d9ebb9219e48acf28ad323176cd0036bc7566133e3e181eced13f7e08c17c07939c2ee903017be4d6e65eb81d8a664cde9e1359738734ca22f4beed2d42d512ce3854f6c2916405b329d7635b33017edfebe362cb28bd47f6015d37059fc02a873833b6974deff97e7d97fd4233e1aae5a5a43ed1fa7024a8dbeaf1b972b9df3dac6eac548106026bc49e2607877460f03a89d0f486a3986ac406478737e30006fac5a03065c9ce86c1d6fb40fb15d679f15aa4e1afac2363f3916a7c57fb2ba997caaf5b4d74db016b0c3499a25957dcf2234225681320972b08fffee2e07caa71fefcd81679ab92f13d752833e412229bbd61696bcd7b2e124f0c025098129744000111f2fd7534be547cd1c466de31fd9c019b3992cab9ea1d5eb8c58767a65ec83ad64d29a76978d77ae013ec4576e8655341483eb70527d078c36577985422be8e3204052bf33424cb9816ea134beff251b89d04fa7b5c019b2dea3c7177bbf82bcb983eb1ab8e9ad8c26b53e0dcf38960c53a8f244cf162ab14162eac46987606c1269e477c80af59f1f387e9bc5fb8326a3f8a77425e2d0c41c7c13438d14a36550c4b6e9e99e0296790a4886fdea0605710290d93584ae999490fbabbe9d18ac2b7f4bcbca066dbf6f1cec0ea70b229036f8d0fd968765f3412c347fd23b83de97d08e7532004ca689eed308314864c334d16de4258c7006e7361c5683f7b6b4c01b48e923365140e90b195f21ca00c40608c5898aa06045b05c70d329c931068c1db40f70947efa93c8bf41ad16c85e5342f44643eb916072e6ba84b545c88ae80d9f7b2861a15a85cf8952e338ed2b772632b8a7e13b253c187b0484ff90d91027871936d1b99393489130e5379f220917b7a2e1917a315d42379454212e7b01a877725040f88a3d685485ab138609ec0c74318071dc15ea384e427e2ff4a1c273789b1977568a6c8662d121c2c622aceb5306a2ad509b760f57f98de39ae1f851b5fb3ce84f60f82751536a8a341950e2ddad0c5bdbcd1634b72614b66cff13aca80b4d70399c28828b34ed69acde3386e1a56d87ee30c354c7a4c53658d6f457d44e1d2b2fb2dc90a1c102a274afbf0d32363bd702fb722fa3a3ff2c5a011e04a0e65b17415086b0302b6824c70fab9f7007442813ffe630be123f19fd7041d1f9885f9df266157acda0ce1b00208171c0bf2ff16c374465707aef66c9a8cbe63d0701cc618264c0e279b154d3d0fa8b2645c8bc9f8bcc7f16b4b18acc1312c0e540bfa37610d2d8bdde03e41994bd98db3835de83b47388652039b940d45c0d775812e16461c2c9dc74fb249a5932851dd4b29420faf416f77937f297970f5067ed0eaf02dc15982f9ad12c2559fe597bc05cfec648e25ef4dd4b39a0b7ca8088c2c93d2994d364e2a3afd9a9e1a4e18d08425191484e6ac2fe4b400b844795fb01a6c88eb122acefa225b1a771f1babe0bd6e31dd8ea8a4eb365ab8d60c4b136e02eec49b21a324421b76c2940ad32e177f5a7c6c8671ce3a7483c268e1497d002483503316f2b12516a44df873098384413d6d41369ab7af21a886808235217a5adad1e0e6e5fc08c851b695870c3f76676a978b981610b072f691c5e1c4e58659deb01d3452e72ea29620831e152bc805db5c94c184e785cc05d9d31435e1f11d86c629d126c440e05c10ca69924043e1a0a3b18620ce7ffe6e6bb10a8da1c64733c1ffa13504b52bc7c4562b5a2306f22c9dcde131d04546c15c4e0ebd90bbfc03dc7d07e49240974e6d09ee023208ae7d272f57f29389770e5f10e29f044b583588b7e43c364aabf9e81d013f5cb82c38a08574a3963c404a8975c57c8ff992211f919ebf61e7938a2e43c306e2e71ef378967954a4cc1109ac28fe20bb1ca1accb194d44511c5313ef3950953c3b2360cf49514b144cb413ac4966338761b4d8455f696108ceeedcd911a8841bfbcb47dadb18f08249c2149270f2ecb4cd9e4b6933b80cc7039c670453423922a79ae7efddbffb5da7e158a206c259ca883c4a5576934f4b8d21ccafe2235b1e3d11b1f57d31339a204dd57cee0df44a86cf26522d50ea5bf440838265fece68130c7a551fc6131d404aca620403887df098915b6cd8a0aef16f93ae0383adc37eb640fa8b6b2f9cb9ce64b2ec43664a49c114ddab5807e67f4dc4bcfcaec131b2d04ce73996e0e4a16e396581e4dfe561b82278817c46366623a16e85f0d3ea00fdeb12fc22528e330978888a84bf6c9841a26ae1bec9bad7352d1ce392d6d348f307896e2d01cf7a4744b97729972ea6d6f0a23fe51b0fbccfaf7df5e2ea803e4b067f12030b502e368ee0e306c022c35b315677961858a42009bcdd172a222d8a1166f066dbbc45e0b2909a4ee9140162ea67c3847873b15c78b9f32bf32acbec64488ffe6a4ae4dbbc20e7319b345902ec07f0dc23ba292cc9c4190550abc3419b00f2210232ae6a7856583f8cfe692cb5049a8495c91a109f4394f0d557685d6e0a58a3965f21253bf954277576697410d2f12d5594731d30e9dfd5ea14d8063cef82149ff2a3f1cafba9cd26e869a7212c8031fc5d0114c0448146ffea766c61eec9684e3b3f887a27e58668cc45d71ff4a80a5ad0239a126abdb3dbe73623c95b374d2837c18386418046b507cd24a641d44f9b6a733deca929687c1c03af9da869fb0f3dfe75861951bb9b48894693c482c743c1a3e8eaafcb527208229ffc0562e8c7b3d4588f0d799fbb440af6388d289101d756516d7abd923fe82b2f8ad290bdc29dc9b5f5fe377e2b9312a5c0972abea62589b651b02f5a3a6af577e97e0917f8372c81eda93868926a9f94faabbeec74a902e901942873ccdd12305ccd8cd36cdb6381e450e84073840a6056e8cb3866ab64137e63e8d9ab2e155185b84daab0cb0a7b124900f31d2cc40724d9176d6eb0eca4c7680716d32e6d25745c235b1097df9822d50317c5bb866927415cb6f93fb7b244fde84cfb312e3d7147cd202d7d320e023c51e4c54131209b718884231ab409349e4fd6b84b00d3f71251438e458d3a7b441397a2f54230387d6e0cc1d49f980313d93fb03e18969451684d0375bf026426813ec447da0da7db103653494ae00bbdbcdd2d39c70d35040a23c7ed2eebb4e07872619789d032bf9bcc9a57e0e585852e07b7c464bff65e5a517475f8b5a1719f83769868bbbf8a3c9996aebb049a7a5bae9b5c32d21b4df4ee45afa3b178b863c4f568705b2a4698045c824bb5086725a09555e17f6886a46144ba6585bec824d05a30b0e9e428a35ff3632e6e2ac3c8f6fc85d1d1482ac83930f0e05e31971d965079e971ed5429b149e34d0341250a564d24349c0e157a45fdd71ea7ee0608647d75fc7e563a71279db41127fd7d77d52e86df4ea9f721fe9576b6b38c93a90c489960b8f0ae6b30ec7a2afd60ca3d5264cb5d300c1eea8f8e098b4a0a6f4c7eecab23708b92db7cd928120c49d5aadb47bb7113e3e30fc89971c4d48482bf38e73ab635724bb3828c815ecb9130da3384adc3b03207123a8e4fce8ed5c58abbba9bb1373adcddb19e16b6af963d83a8277c7d84e6657459cf21acb8a6807341113d56918f310209e990185f2944a238735c80c0ccf6d52d1a94137a06b8e4c342f7e7405f104cdf8d14477b9f0c82bd03a5056edc4702a5a11d41b50ad7cbe5426eae6311b9b993514d918e445568966191e26b3f561f821b8c408d8938454eb267d9d42112260cde13ce2f9899b65dbdede9b8539f971275f47cadf3501604e12c08b353ad1e3ab52a58147102eb55ea495031d7ebea8bbc4807409748c67a69545a40d4d4c14572986d7321034cfd14065d2590cfcbb701aac6fc28caeee8ccbcd1ead3af68d6ef0ff97b7f85e9a28a96b71653b947631d8bcce23bb020a1d574e6449c24ccd1d719907c034ded12d921ad74167c2a032497daaae46518ec17129ad7096fc50c91c667a3d30a97f6a856b8d390c3a280908f5575754ed4399b4bf8e33d9e764e9dab3bf0c95a5fdd319ea045ef1718c692d3009686f43222f41dad53c48d33f5ff5230b41ac9e75fe51f91fc5e85bccbb9676cf96a93150935f75e7eef55a7d1e0e3a613380ffcb1ca2b614821eebdaa6f832b842ebb91567741a8f9e5d84f189e41d4cb65eeb94100c8f7093d295b0daa1283608027f55f7474041c9a5a1cfb6805b65d50f019ce5a99232e2e3140e31d5d57edcd03432f70ff48d77759ef8bea1cb01d099be4a889bca5939c33fd3e0daa6ed8dc4768b0668ae6f3db3e6fd1cbb6a85da56340094e7d1ffc325670f84a5ee4939923ee192ca40e79971bb8625f57fd5aca4dd229b6e6d454c6f974cbda939aa74bb681ea6d293f1f5df2a254303b7f2e2f40924121125e431605dbbbda93bc410073b86d62bac7d3f53c8ae615b2c2363c02475b861d192b2eb4b442d11cca5bf2bb6c940842f3b0394cc3d411cc44eb5c3de4a16ef4aa0e707d0f3a0b4859f992eef6a36c8154428de03e35c08353d4998a327117fa90faf926508d3ef5507421d22c49c9430e382d266116ad88426a0a5b8da7f4550da15793560a5d3c9bfa1fdc808b778d396d5da9467b8d523dec1b638a206bd7d8884c1b535bbeaec642ea6ead7d3b9f167c13711999166d5f05ed61e8ee4cd4f033705008988638f212ee2b3e8ed5ff4396f7fc8ca4dabaa1ac050c08131520b613c31dd9834052860b3dd4669230546b030b3eab684e9a68a10f8363acba1a7f965d89761272efd0cb4f0f5a1f6efecb2d8a80ea985f1d18f39ed333b420e9cfcf37eca297b804abd844194bae15dd07d802835f43c714674bb15d2fd8dea5cb80a974a0b5ba029483595970d8e1f29022b5686930b1532c97514ee8c1e3d750ac8830b55403f39dfb40ddc8de23d000cb311bd73d5ffeb4a43efc2681296d11279832c626bd84de5a0c515040aa587c46db2cd3d38f66bd1e9752ae2e2d6a4f0d1f0068a03675e5c0474d87f3a40631bc348cce9ec056349d83dff1fb7912792ab4bd8970216b593a0e3753a1f07dd457b84315836334c43f725aaa2d97398d9922d55981c1100686b8812a529d5e56a4d11b3ebaa48d820f5dd509a195f645cab2ab92061fa3601a4494aeb442010f76d41da9155b55d9b714aa089f00cf7247fa4a542a76374f888f1c6c8b69a010dbee65c865bf30229eab1008d4a522a2fe399648728359af7813874ea790e8af9638dd98b8bd6f33104db55108820cb9f9ac6f6e6c3de30a66fe8c7efce94ead3ca9382172e4b8a5b96fd349e0f3099908f32ea59d821c6ac463dc6a6744da57d97baf7892d5e29873b7d9528f94a76ffa8e8c1d930045f45c426af0cc6d4bb7057da85a4fcadb2d38b2b42e49b25eae4ccb394a3d8eec78e1c2ad068240fbd1208dc8ed7ac96d19d4667ff89ca46f97688558c8ca9f1194e098d436c8569962633eeb0154cc38cbd13479305c2e64be2483022cb54e7c79e96a6e32369a02ccdd69007ae7f647f0b7cda410315302bb08f774e6a2f63b07c6739f936d32bf41aa50e4096f925e9d3b7622268747a585c5e268147084729f879863b597b32cb26dc712570f64b1f19ce649b6c82f9f260e19dbba5a636fc4503cd68bc54b1574c304cc56537e65d9feda0a9e93ef4d385d9907d54e0794a261a999b4bea271e8ed3568c2f7b0c097d5e3487f374b1421d6fcb5f1089cc4003fab1de4b035776545b50c8d7c2bd3f4b10990a629c028e0d5596adaec7b5e2d8d9d2e3c9530c20081337a559fec08b1185d515287e3397c72bf4a94f852b7e1b6c64b6b3d0d598246ae273045373fd8c0825e91a67592c92c5b8065c49cab3e0703e430fae4b3c14d55bfaae26516f6bc715057071a972a01f43198d4d37a64981bbd19c77662b502ea6d30694368d41dcc72e6ba3af115a127d947a2b8bd2f3d8de49af3ae85262dd7d26ff4f1703d50649301e7850add0a194c12c6781fbba0eaccb698a2d4aa766c588f183f0b4b0ba52b008210e5165579f47bc064acbf9208a6907bfd4d4d411792e888620e6fdf2a708ac9d1730e1bef4ee2290935b94a3c097b6756b5b70c4e6d1734abf96005b90cc641f07904f2b994d718b0ed473eba06098110694b552e9b99696771333f65586e70adf7e20c5a45316ce6179ed2e77cbc6f28a78ac01fe0ef14e2d18260b50309745686da85871dc194f00c116e9402b320acbf6070db0cdd54f9c4c7798f355b2a4dadbff1193bd803ccd0e64d06461737987e0a393b2d302808c01971565fd2fcca723a5e5fc3710c068cefda4df6a2497c4a059bf031102c58f64b519c71c0e17d1ce432d523892541d4f0ff2dba07383dfe11b300a785b0481797d595ae2f396b20303299a82a47e6f670b0e7771d69ed98283d498284b1d540b42f0dfe1223b54e632a24a643a40a886070f45f660cde023fff568554a05b823c7717a34a4aa9a91669cfa92860905ecc1c5443b3a354269933f2701e95f284ae026366dcf192a5802b9840d7148f72e3f344279418333f250a339155b1faaa8ac140ad732c0c6244c19f028d6a75cd919f1f2e8969da6f28556b751c0496f89da49529ddf6c9e8397ed50587198a494007ccf6f69187c5699d47d40e3f18b4bfe4328aa65d48ff086bf90d0b538b0624e248c39d6a28ddb4466b35358e33337bf83d841c12de1fd4973f8914023d4d72c4230fdbc1704be31c781f5670ecd7793736d598568e9627f7f84d6414bd04ebf7cf2e7b686bcadb4f4d7f90f958e2184f56dddbf225536d11026865137c20bd6ceaeb6718084205f53e75611c1a56eca30a2b4129d8a1ed0722712ec85e9d33533d79c0b9cde5abbf42e831c33a6bef3c08fa8b524766ac0b40050405a000b89550f26bb141f5a319646109a94df15967c4200d7bdd714d3b871dbca281af1ce3ed4b3a78739979a5ffbe786235409f2507f22d80aeb4432c3fc8ae704f93f449303f58ccde1cf5f2cb0fdf7cf0461f86e89993cb91e729b4146c5ab15cd3d99b4bb101d3c6cff0944e22a0fb452e3e146051e1f0d8544730eb96e959a1489f88966da159dcb9c498a2bb6d879a203be30e35e385365bf848ec3932984c9f7f90a8abd8d160bb362dfdaf3d48ffc2ca7c3df8017f1f42db336a32c9322ea909b3aa7d69951e51034a3163e5f8838e368b5b061da8f42a29cc29fad8c94412ff64d815bb6260c47cd0b9cd41ca1a8970211a6557980f1a1454a63d3581a4ada8994646b056d38a834dcae9767b2dcf37320944992b1bc3696eeb22d280b81fe4cbd2135ee3047b3a18724c8d32670d652615857030e35f5acff416c2eddd42b1e3c0edafcb03078f8c16619787d446f8cecc7472b6471b6edc7b8ba37be28e91ea429b8761fd8a7256cee8c42590f70032c781162b62c86c65e5be9f2de9e9d49be23ded5a1b1901bdc5913e0ca4a138a38403d9dc0ed1ebbf155910ee3a8a3b9659232568896bdad6154e6b328d4bf42bf97b69e0fa24f2f2ecb993618a1cab429b6d2eb5c68ae6776baaf9a3803dbbaab0a79eb021c3469715ed315fdae932cf5c8e95e0238aad7114b4d3b6d1daab75bbbf2e579cb26bb53f5bb35377cded2a960b5b0e5b54f4ece9235172f67eb6e9a7a473cc8e3e45ff7904529b370f7302368cf72da7071379b5c00692407945acca2ce40f5f81e4c0e1712b1471923e8ffc1067eb70c5a54a7b50402f2e7522a333e6a428ac8be5263cb2bf88d2dd8aeccbbf3cead12f2d1ed4f56bff673d3940ee2fbe9e2cb955bb1027abc00c4153f8774b531ab953c70c964ae668af1dfcf70f3875d80f72deed8e0fad791a9ca641eaa2aa428483c1d1324ef87f13a9e73da80a4e47ddf00dfcd6ff5430592f1807b89f8373eb65760f0e85c0ad6db55396c5e2f6ac6878108f26813a225d205695f843e046bd5bd9bb1a9c21e2c5d28dd65f8141e9b9b358990e212fe144ab700656078a66c2a8a347b0d3684fd2348e7e775b9250414d3442e6dde27bbeb99de7fdcd8a9ad6517f5c6b3861997d4a30a5b6b4fc3aa2a4ef6b9195c2aee81fd42bc696a929dc805644c01348118e171e747723440144d41da33b8871f872ace86689bf8fdf3b670238d00d03f2243565f80a720a8d2b741a7a00eae1b5401963a1715d1a982bdd4482bd0a6afad0c47a837c4f1c94f8c0009357ca3f498438627fae4b9823e79d8cab766db3380c0dc8455e31421852c744a91e9be55d3dc4ec45704d0b5523f3689fb2cf7992231f9eeb0a7d7ce6809f08971bd367b3747f3e830a4ebb4a747b2001fcaa2621d8f37bd31fec0f2c7c2dfec095c67c360d4c055e7a1695533573a7aaa252e4ed0a46f2eef2ca01eb339f169db4ed3ae2b02557705fe60710bcce6ebbfa631b08d254d5daa6b037bcbeafb03bad064c36e5fb1210d0c4240d7e69b47977d6dd5d6e83bdb6e9d848da16512fadb481a0193af8835ffa5df26b6427aaeb0ab4f79aa7b569b038c2a59784c3ef6b7cae86e70c7e098745ac71d72b549965c312fc7242ce7627da43ca919a6b925fda1c8b623be8588f95d00c64797d9e52d660b5a98959f84343dfe8cd3dfa58389d4289710199f61b7d59c9e384ecc69805cc6310210472914dd9ca19d59f950da534c0e246832444b6004de9cc58e13453448ec0bb27f90e3201cfeb26f801959d62134034edd83c397858bdecf4bbc99728535c31a863b78c48363e06647506d9f9483fc3e52f03c8d4e787f9d8945eecf3416caba8f441c7d7c7864f39b40d472bde37fb1ab68c5648bb30f08f8f239b93852e398c9870644962fc9cf019211aa00517787057e588d3c5978116292213503a0644e28cd0b14f5386c85acab1210b6655689484f4f1c9c4d8a39900f59aea30395a4e24c57b546015cda90c2d565e00a095212de82efbb23c26d316310de31f96bf6d5d9c3c2806c9245e532c52b668eb4ee762304b0068dd1399417951439697d3534d6c5c842b9ba11612471b5475790a7a9737a4415ca3c502c0434827b7bca3d64ee153f204b79724c12bc629b415830977018f59e7e0b403148879b7ae35a7164460cb529ab990305c46814e85b2d16b5401a2824b2ab036541d6f8f003ba46ec400374a84891fc4855f4b34b10d2762cfda505e6cb3bcaad2a75d479e1cdfdbe32e9465a577475006079bc9b9a786bef35be808342bd0723596bc49d30a301085c91bb74e80064999741b8419fe606c23c9f16706f670b37564754e8b1b03446544eff1a400e9758f8a9f1d8de9d3627042207f053bb3e402469f43c40b22ec73915f09c64195b81b3da2f1f9782606b290a5323e89549fbee62eb7171bd4500019c633cbdae56139867d1b6b85351bdbc31a6b90c58bd609cc1d6d273e30ebf2fe5606ef3f2df7dcc340f3a6064e9003cb30db3f9e9cd9eab2a104f342ff4386fe3737b86ddd48fbb0b060f80e69d7122b80ed4392b5667e33a51f96e377bde5ca9665ffaf472cf8d657c0692b360941f542f6a35caaefd452f314345ba69ba0a867055c9238b097b5a61aa6a3329ebbaba8799e276c9e184a73a7cf76e18cac99019269df4e78daba679dd6a757b8021c818c9467ad034d78583173aaf87b9b8e5ee8827168626cda2d3c60bf6c7ba7c8624c1a05c6e58c47d28d095b9b7771ad1456ab5dadb768404a0fdf049c4a1c19125cc3f145d6197d96a7c8a332245c2b3d428d21392ae007c398419ea5a6686dcd1cb8670422899d2abe00243fbaa84e5fc60ac9d30c743de3b6eb023e913227cde93e2693fe8351191b448180ec062a301ace4f38cc8bd3944844b10f213bddf6155d19ad9088f711e7a8876e35fd2e29a2990a6690dadc6a1e3ac1149cb78507cd851662ffbfb1c08403b588a2d6f44d99c8566621ad6b2bdad5564f0313d4e2eebd90f592e7860f1335b59a23eb5dbd9d8baa581decb225b1cc63f08593f50a10f600d3bcb50eb2e9504e1edabe1d08d0687082ab9900ae5c8a1e160398610526f363df5dab7189950a39e92d2531f45b0ed37dd828db740a4f14d22cbf4dda5cb7cafd87e18000ced6e5562ed9e1532ec6a1a8670891a9021e95fac2446b42e8da22ec492d7182182081837e4c57122c5c1d388f003ee3793027538212ce4a2b82013759a0b337ee2a54c8c0c7afa19efe9e155884aa8bd898609ce41f080be3b3dfbf36b369bb5b2b2c51f320050590d626efb7e3312621f92bd59f0c6e9912550b4d128d071690b0e4ea6eb8f11bbc1803ef6aa48724261666f45e89d7431eeed48b73a07231d6847383742263bcaccc8a6ed6c6ba037712b43fed3b1d05072b046b8e16f32148cbc465f6b2d588dd0d8dbd48aa07c0d19feaab7447ece5b47d9a7ed55f96709a7e33eeca4b3aed342659a62fb13d535f0b666440f04406e5acb3fb311c90662b2741e0d0f4e2897a71d45131f1677a40a6ddb1583b4d3f919b894225927c3a14892c4f4e5093100d42c4f4a0ab5ca55d3245a7a3470ce655cada6e929a55be9933312b4f2fb62af4c4c8c37b4288f11dec9a4de80c9cd5021e70f187414ebd179dc06571c240d04340a7bfc3a781ca49130925ed2902b39e89fc6705b6ebb04b6fef51903cb3c62207988b286086ad4e6187a31da1469dba416f0b8fdc4d4f36695ba52fc60e24aa8bd7856b500667b46c1a69d61511b0c4048e82b5a18370376a7c573045e7e816866784c3353a9019e3f291cd5f249c8847d884777ff01c96faea944c2263438d1215146044abd21b14e40d0dfd812d327c97f0eed4ab931a463fcfe9585416bd406251b9edafe8c8be67d64580d431391f1d44d5a086620f931412b72b1bf53f843cea451f77728a757bf134e2a45e4b1f2391bdbdc23f84392c42cefe190e2d5713d26e096e4bc9dd347e84340f9cc49c7a2b625ec8e9b1bc2680bcb33233eb61d123964981d4c368ecec267f5e071fdfff94d6470857c5ca3b8cbc66144fcf50a50272cc80ee5e64dcef06f66693987a8d8e0d0295952e0f0f5b28e7a4e7a0b6a0a967193b4fad4ba2cf99d8fc95f7b4c3b312afea2208dbc9e16dc09bd12399c826c4ae6edc740b0ef41139a4e84f418c323d7a7a8ad6b60dc2fd72583e0a6e8cb01dce1b4efc106344e35c31cf26303057461ac79c7020dea46608fae1ac7c983fc38cb2a578efceb4d2b0d15030328a5ac7b38e160aec93214be35d118792cd334cc8393268268db4e105868bb08dfb1b0011eeaebc73e265346f927933fb875944d927d33d529af404aca0c059d8e63a60b303f8048500dfd2553cd34f66601b3472378769ef5b1ebb21f5a38e76ec1f50ede56f900dada0cca4801cddf592b219ea283c29b3af4fea1a079d55597316f32a86a25cbc4635d011a5d64b6f23ea8f5409eca7b58ef0707def68a00d20758c91d1b94fc55cd5d71acad08ca7dec4353179b3e8b11764ce486735fd7651345e3320fd18e92397bcbc31bdffd19e61a328187962b930075a354d3b158d1766ebe1b43bed533830405376a9b22b1efcfa018a9277005c8749e17bb721ca564dc04c6eec9f0be40d42d860d3933baeea0b61831b22ade9e0d1446aabd7510b1ab97def9074996a14cc9ea791034c7918e3a481df819ecc9ed63d0e07e8eaa7af495ef3e1625694d2e5be05a8fc56e80f6b01ae17643e5d0fb3126eacf284ab2670e42a34ed7fe2418362b5b5038e968a45232fa2c1ad1e6843bd9a7e5bfa3955428e39ea4a4c5723d49862ef5f1744e0beda5c3b80a1f6852ca1d7d3a8ee504a88d382e6ea73905ec86ef2e982dbb6007f776a47b5a2cb85270686e541dd961212fa92d2bcef44033583cea38e8e29e696925a22ebe632a74baa25ce11013667de65fe1e7103f8b12c3e91a7cad7a5db7ca482567d44efd5fc78d60c5f9b0bdd07f34192a77c615e67934642d9b4e38310b0c8e1d093e4f326b40e294279721d62e04a84a04c7ff53ac998230c4218982282a97c75206d906612534ac0fd131ec70451cf8b783d67096979efe8e44902f708781c99516e0bbbd11a30bb22f4d11f227c4c0df30af8bc00276f7f9549d1604e98c96831b17849507618ce77051efe4c24e786f0a81e5e7d4f0898eb7601eb0a14ff70f55f05f36955bfdf43ccbd7fc89fae38bfff9461422439750fc3b7234209146d3d3987b38c7d10e3b7daa0c784740b7e2278796f4c601484c371cce4c80f68c2256bf023fd8e6ed1989b7f1d73d2a57fb068147af27e734a6a88125aa443dc72fac578bf5260508632d98573cf59c5b3ed8f4dbe92813b74b8bc9325c1b482a91d476d19b10dab7e3b6465888d0430312d29d835ab00e27fa04d0208f115be953a34866a3f240bd66cc2c1c81e50a40c92968cff5717eb60794263ea168ea22e389b9e5389d536316138eb9c02531367d7600df68f1632e19a11f227a58e57bf2d84e8b569c61c59990396506b90084f9c06260af5eecb49c63acb5f7dc0e4444528c2d9bddd3d1e33f124158e1cd2c58b96777f8c1168f0b85b9febc1702605e3a499baf2cf351cbd07e1c5f94275c051cfab8a3e3232ad7ecd86646de5754a5a3a5f2e86e058abd5162662d3b4bee23e2c2004c041a1eb39cd8806efdc9201a43f548c992576aa54f5d90f9e66a9aa17e247e2679882ea0798ff380572c00fec21af7c0a0e8daf2c7d4839091076a371d8d24c5ffd582407e6df38beab4ece57fdbfb31500a962a00f01ef5cc0ca27994d9c923e900dc3dc2b5c9f3188d97dc3a9926bbdaf85d2c24a3bdf7e5d695289c97fd8168dae9e3166e93bfb02a004832e278276d4b26df81c1016208dbd8ad55d733b687099f1f347ad743f6aff180955d2bb299456b7dd43d5593f22fb4919a7274079fcff230dcca1e4e015e5867e7f5f1bb9c6bfc918141d9d02e45f58c227e8774e42a7a6d96a60e71e733529c8c1e58f17b738e44877cc5c6437ee471cd2c181c9c238723cce548e4b849275c0253553cc914ed761dcbe39ce211d62664240a267a239a349e6c99facd774d7fdf3ac5a0016574d6976f3b5323de118bdb174df7437b3586195438afd67fa865f434aec9e4563dbec25104933d9655c48e342a95445fed0ecb538bc727bb24bb927eb003a8075d99dc18125235620ee2519023522e492dc5af265b4ce5ffe5acbbb1e0ee76cee130714cf61456150749460efd59746f91b2e543c61e9ec6120680f5895f35b57fb7adceddec3545e83123c3018fa694c7d26bb9e13cbae2bf43a2e3b999f19d91ca9204c19c6c3025d56233ec6624696a3836789cd0759d578c4544e08f2a77248d589b22f4ae62f3843d53f4af18179b0bd56161e2f98e77874c9814b45f2ee30971e973ad0ba71275b50ab2538ee64db95b397bc4bf705ab860d1e6138468c6ae9c67be20f4c6db1d33916ab0a56a4136f8366cd1a0f169cf867fb5ee96c4ec2d658d71c100e827aa1d09c0f6adb8ac9c3ba80808a484e6c8581c1b2d4a271edd1bffc49d5c874aec714b2ae82f1a3e6d681c48f6eb7c7597d79b4f19bbedc13d2c6ddaa5465ae3743005091769e29e249418b7dfcd0058495cd9befbcd32376efc456aed878179bc5d8d912aa05ba8d300bc8fd24a968948d3b63cbd2f46046b21ca5d36298c91b066596e46520a492cca33f7acb0d6407dbdf9cd4dc24e00efa41d6432a92edd42b2be6ef9e7a34a80909098c16b410a62c486107257604c8759edff6b84c55d66b4d03048127aae9c76791223be2ad699ea4acfa4a7cc951badea33bde8afcce650d5270c2ccd99042fb9084faf246a5fe899363d122b194cfa1282ee5a49ec6df333bf245eb0609cf3ae7f90a23b79b6a67f4df342d276a980a8b377afd33464b1281e52868a96369994b0c8e09bdd1681e2f31d68b4a2aa460dbc3bc085f7dc48df5da360816b183a4d0646ee439701a1131303cd8c773ea5ce1ccd04d36bdbde8e1788d1e9685244b72582d026b39618095126c19080be15fce0f094b4c08e8f0aa0e0576836a2bfee4a312a124885a9c69f4e393f07a1f3d37f78e3a1922bd9c33dca5d11297349e2e9f471d681a1518339e47a35015d1da764e504229224ce19debdcee14c4afa5044e4a702329e760cc849294e1d50ff8d1cd80d68d49b5285545ac57a5aa75022c07e5512a4b680faf4e1ee34f78ab7cd6cae8eaee3037ae42402b1551a8abab14c2a82eb5377a3077ba9cf2ecb0ac3ac124ca53ffa53d66a719107eb71b681e179ba95d7796b85c6d2576d744eccbe48f809453a1fe64d496f2119cec4ed8e306bf8ebc2025a1f84f909b9f280a52eff136b01706119446017fa495cf8645f08c20a380d8a8c3515714bf3afd08d883d2ca2a67c4bc373a2ea0377b0451f7a0c019e1b84deb4f1f226836899b0ee6a87d5bede116df6b6fc9dc3f99ca8e8a5475f1f8dec1d4b148030c6100954dd6927f3d8c5730c2e10e240a82733efe0ac2639afe2e2d254f777c61941504fd6b79e26663bbb440ab499e7215215353af2c37eda74e7b46b407f4ad0fa4fc4e590d77887a0a4c04b5f71ec01bed301201df72da641231537f840bca6115fffb40d6336c58583889f7b4ccae6b524fb04c40a17d49d8218a7ea3fb903efddb36ea5eecaa5f66da07b1f63b702100fa830f89be71b031caac7e2a4b473b740d8ee5d27dbeb984dfce78b9969aeedf1782ff530aff7646c8c49d72223ed325a15a5e51363c9e8977c5f10ae14c199e04c7ba799a6d23041ddfae3d51b2de48495511ef6af825a887650b5f95b3bf684a91902171ffaf77a1049ca794a9c800c3779bc775a130605902f233606e5b0b47dbb324f5fc25402dd1d61588ceb27aecd9e63edfb48bfde2ef6d4a85d832d307999115c90c5e644864420374dbd52718fad91418d8fa87d64b8a22732c1d9c64dc21a659b07cfc971d4b193185c5b8c7f638f3d0d2d1f672ad63f9f83d776731b7dd2c8cb5cccbe1d38d236d423c4de166f895d6531f698f5eeaeface4efda182b7e78d23ba768fdac92f75a41420ca774c40631b5908663bb8d579415111933f9305bc4b4a52a0de507de82aecaeb1b950498b3285172fcf5890bab185636227dfacd9d7f154ea7d633d7d91f40a799e73f9975a8ecca980c0cc3631438f3e0cdc7931b1923a418aa984636026f7d7c4f97d1de6dee28ef98fcbbdc0241816d5f58cb053ca1116c71724c9f923b69e6a7ab97db61300b4ee15cc1090e4836357993f23ea6ef6cd280bc7f44ca05f8d2b566672aac59097bf0e3f56b519a6eca4269b0e8992383c9b585f308d0cb45248f96644abfdc141d7888d4cd6b1a3a26565034213e2214a28d8e5bcbb14ffffb4cae91fd1877a74eb9e9140ea6a35fc7669111c3cdd7a136d4f57d56d3696bdd8253f8d3c1e72139fc2823af8ec19b658056ad977d69dc3f6bf754ef30ac06bb8d5d32ca5f13e3206b147cf93639b19cbef251e962cef17df524ceb13945665dfe25f8f6a88c461041c7775ed2a01c2b61a07665607c031e628a1227d83b7a051d9de66bca220ee85ff587e201b72b92e4d5c47f9d1a8dcb84d276b7f4deb7475301cb2304c7d053753773d411e5702757c30a8939520723b46eebc140017b3544240498fa884f108baccda198c470d0f650d1bb0908b283bf90342dc4ae9fc4dbde918e80547fae1be892f85d27887e3bcb368ee9a94acc076183bfa405c1f156391a984d9c10183f9f83183c7cd024f00aa9ef079ed1a163705cff162ea1e7f937f610b058c405df6e7d5ee4a6fa3390d14840986e134b1553b4af2f9dd166fd319858d06927ffa7a9588d59a1aea55a312dff8186fbf448c14b380917bf14fb03adbb5038d8cf71dc13c12221ed5b430013d57598a0317e4f22793f88ead921b842ba3e60c72e18ace1ece83d4dd7c7ae953ae93ee77e75b53d530e8ac30f0d9e051a463ff12a2fdd5aa4daf8647fea2c09962af57751ac2f90f8cd774dd392c6b21924f7876b6e2975bbad1075e145ede5667ee9c75d0e1008a7840fe87a1deb2e1be3eaa64d6eb0198ab9faba9abe275efb4e278289b222edd1475cdee46beefa5ab5a2b1d710fbeed944e9a5d0a11db7672b48b09b5612e9e603c0b3baf0ec9e8568046e2cfa15c73b0e2de271c82340abbb6ae3cba3e01e63cfe6b56a589d027dd669cb0be8c4750627378cf8220a4968383e368cbb12574a51860668eeb6384a4de77a8f97771475f6acedd6cb1086e51efda7227f5a80fe04d286fd7ff76d1ccf050aecae032c92409124423f060c74fc0692bd35d52da49b57550f0b7c7e64baff873e1a8caa4f81268fafbf9d8df631bee48d6c51954735b9da8fada40807550a4b43ac0b6e1c3c0edb25fd5571407da8203b39848d2d4a2c265bd977234843dc161219ed9ffaf7a863668e42679c3de73e7c670475a350a658a03873d009ecd94bd784de56295c5ac56820eab984a7b19011ec0ab2d92c4d0f42476ca542e0a591e9b678b8a9396894c0acf4a063be5e30dba0678f5839e481c21d4e627e17731eaf1e6efa4cddaa39bb751928ee183df79c1f70f4d890067ca68f2751411b0c08cf782c4170efbdbae06438e86589ed728c7801ad9161f488101d4d9ed0c89adf43f9fb1ac2f53c330880f253a7474d410275db58195b2550f73904a3cb6147c40b6a8c4919fe24efa5ed65ec972079c16885b781488ee4a6c60b059e6632d669b6fe37bb466ef6736a2a21c3b988254140f76f2451f1ef4cbdf4c8162b822d6ea902dd90309c504b061d1c288be83740cc0ca3be395ef500fe64bb743917840b0c3c25af12ebf138ff1ceaf07127ce54bc7cfce7bbb412ffdffe07e9aa7ae74ecb259dead979a31c584fd85c630d3ee18af68d0666e7be58601edfded8567e913b67c2d6c636ac56101d20811198c72498f3b30b0d7201da1cb1bd74e12e3ada36d2b295dc3f95a31fffacb3485eb16b6b19570254a027d65652144471e17329503a65c54394925c8d13c3759c89299d5cb2ebd05e4a0d89de502a2d7283a7f5e66ba07d36d895f5829176dda34c0a50b0c608fd009b9a05a99abb7423a73afb1240b9c18ecfecccd43b7cda689b8773e6ba175af5870d3d681d77a391894cc3990708c667c12e5e05b79fa8397f787400545422725682a5bc596633e512e629a48a59c262cc8a650e0695bc415e100bfdd153028c9ae5028346563703008d480963c4bebe6f33d2b41d6a91ff196f631a3aa63f39e583f2b9b92f6c681b7d690563f05c9a16500ea1e420d130a2553fa188cae5a9d8799f7f7ccc2d124215f6904feb436f4f982dfa026da733a0a5e82be81c0e2af7af66ead25d607fb7e62c2508f9a1476689b2707879e3ad950ab54a15afd2a81026f5fc5f8cbf3106203938775f3ada0fbb37d30094a38f1523ef583da1a00d70533e1dd5c466d9ebe15435befd67aafe1eba8cf83d673822c0bb62e9a050b717d6495103c62175a7740bcdcc48347a2d26bce2a81aa97144f154fbe944409236c4311ba0893f360758cdc7fcc131aa7a9b1b9df86ef067035101e06ad31083583709cd2c058fe1248dd11b90830c1e63c7aac12e52b35ce27e9af98115b46acdec3058b668e08466038a873e27a4ef2108b73ecaa82393d9f75c49dc32f62a87c75c43de943209045abb8f856e1db1847840c651ddbbe6e0388421990f12a84ab19642bf50f1356dd507ed4bde651c94b855b8cde74c83e643cacc64ecf650de1a2eaffc4da1f21cea508cb58ceed0dc0a3e907f2aaa42677120655f0b341827b13820c29358344a883718f308733380a66a80ae5a6b341ec72ed5f40fcb557081163cf9b13c1b315aa55880836f4b99812f0e68fea9367b46bd07b999f3b912daf7a339801c305775562829ab9dfe75405d3a6797416603ee871c06084c37c2e00ad23ee22bf88c2b18e8e84fb6de444ef126b52e9d1bf31ad0c9448d1202d12bdabb3037e7898a831134b69e71521ab6f4661648228f7487cf590e7c382a8050088c956a6459532f25ffcac2ed4e95c8d25ab29745d31e07c7ed658bd7730de92baee1a60a096e2348c025f7600495f912418f63a07da8fb70beb82cada9dbd349c5984ac7625faed4838895e2d41808e28caff7ef4cf86345e62e1bc603dfdbdec209db8368fcaef1d40b16a6465c7e899d7af5a82195eb6e75c827c8ad82ef025d60d42ac0750a292548c60a5d20b5bfaeb242c77cd51f627dd97386672a244814cc740b63fc2b0e3a8b09f552c361765b667f29ce57cd6871298271bc963a7316b5c9c61cbc42675349b1dd4e41361b787136841985877972a07a114578defe7f7308c400c98d9f168afe00248f994ce0de1a69ea1dc796c65207999ed5e5e2f46809b5cce14eb8225e0392fc9ac56c59df046e9ee43bb48475eda52b1d4d50457d42e74a21f1cb5e44f00b79f302bae404e4511c8645af627de7a4e1657276dbda0c08ee8a5b271e2c8915dca7928da052b8adb91601a447f62498778ac0d8a4d2e340dae7b3d42af6621b522c254b5168fc40d70d18ac7842588cfa4e154a14d4161156289c42e07908fd27a41947ebecdd699cce403124a217f2889b617ee13e5f1f322e75dd5ce9c8844ea54c62a7fcf2085dc036a86e022fdfd99f737f9e189397defda94f314321778b57702514a0c311059a2e562d4603bafee8b175ed2e8b0505a63c8057e15aa88178901b8f1108ba14d616092f216e16a3981d860ae2cadb02c059149d28f6606ab7260aedeef4ba6f22277f5d15732072230494da8128e9391452aac2a1532fe1a8a50d0c6f507b8d4c738dd21417f031e4834dd90d4e70cbc7bc5339ddebbec1896521b93e61b13f761ba6c5a4209907259a53cc6a52cd9427030e0b5392d1a3fb8e51fa417d1d36c81a441923d2d75319fa4688976d9be2c2da5152928718889851c69044b39023cdc24af22747886f3cdd53a18c4bff3f93a41400bc1124224147ccbdc5536f91ed871d01e441f37a804bd5db8c8343acd0dd13619f35852e85c3c164b53065c4c0295f184919596a29420e1ed1bc1c70d60cd219a17a10f790d60c12c011caf98fd19d414cd03689461244fd708004119235f1b00f55f82e15aaf9f54d6bfa3e94640b8aa6048224498cd44115edd09f843956ec687e9fedd40961defc72e69bac3fd721a00f25278466e33e0a6f8d81b18989e1691c1cbc9ff94fc1297cdfdbddc3235a1e778f82e16835f897f92468149e0c279e95366879c905ccee73832077975d2ed4bce8fc78f929d24c2b3264a83ba6608e9b43aa767988bd9766eace2532bd6953b50d03b304a81fd37ea46e61b2b946acf425dca5df0a5e0de216c1faac1a111af6c415879c2e9117b2b2bbaab9834efc2e91221ab8bec3b6661cdd80da292586f6bf96fccd737388b5e9f22d07fe93a0d3ba39db2ccc3fddc32eccf25841fbf7c72d9f98147321aa88d756841ebb94a10f9dada772733dd9e6d1d83c95cc938f48fb6d4e24a786c242a362a86b328bf38336f6874a88dc3080ccd709d35f73c424d1e93e45ef1da936aab38fabc24378995d5020073aa15c7aa8d8ad9eb809a9c86e75b6e8de6c404bed909bad8f02644b600c6191730d8c66736c8d33a5f7b212794595645add1d6cfd097d5f24ac338523d82c63bd8f4075836729c30a56d2435d9be74e1148d3173e5d8365fbd78ee860b9654b139868f3b1ff46e82c36f64268b7c262a82657ab9bb7d1c94098ee4a594620d78e1bb8d5442465ccb084c6267b029ddd622603fb384207cb2fc9ebe4c9bf50240958b18d66a74ea7cca8655db2b42d278c487a5f6057d188c7acd288bea742ebc5d8803eb55a291b82057045fa8ab0dcd069076eb8299a13c183828e41e11f802c0f4dd30d8ee05f4051bf9d7ef18572714ecba122779b5dc9f31d3f453150fffe19d75873457346bb74c2b5ca9e582ba15b772c540c40cd6c706dd27823c65471115dc4263710876ac54e33b98adca2b041d405604c12bc5332d6be844ae18b283aec4e566dbd78be5c6ab3b141027dcb50ecd0af2c8c8817ed0eb78a828f09893000b36b1d93f68104d65ccbcb53a7c6d668d3081d23f43ebea64cba4c21b3cd358f5ee611a5bfd9a6ead29794c610abbb3ab7f289b679697b04524042e7532bb5bb95a8371a0ba5e620380eb14b44840234cd23f53c244e347e67e82c9ef54da146f45ce0b66d70871f004868a2c8b37a4a1385b7bd00aecc13f80f6e6943efa7f70c42e0473730ea9451ba4aaaed6abd77606d23978cdb29dfd0e21a40fa225144a281c617eb944fddffd253b6b9d0379f30d00c022e79dea43b80b9347874fdcec6dd52dad7238488fa2e69cc800018439f2e982a96d94333a50f0d6be0400aa67364b7153d7ef075c1920076aab8add39cf984327e6690168a093c1db58905bea15250c4ace254c4b1e98c0f827b79a02f165230354238f8d8d8aa0d2e12526134fc7281344052a3d6a2add14b0fdcf01d74233f6806bf74631a0623a4a0327265099232816a48b384d824660a8e5938c17296744eba66dc3d0a1dc5c8e9a4ab84226b0d77547548b5ca2ae8ccb53d045f36b1685b5a3bcaa3511a4586f5121469ec3ee4ef0965eb5f4ce2dfd41e4d37ae40ac33c22589ea7e978d99bf7d9d65497bb6b3a94778086e948e698ca3ca26cfe8f55f5e5ef5f5aac00e246b7674af354d909300a949e2ac19811a08c4f30ebb689fa45572691b07ed980c7ab8a94d541f1dc831aecc4df51c7ff2878efc291eabd08c3ab23783f584a822bd00dd46936b19029784cb23ed372cab7869fc3970b0a74700fde5b01523f0838bdcf5618f25f5d1e1caba30226d8dd16b885a19000db54287da200487eff2d0a6fe3582cc692d3834d75fecd02837dbfae21bd426d1398508f0b253e3f4b00564de73099edb942595b6284915dfe3748ace0c95dc050937ece727b55f94320897e98237eb859452c3f4180b63f4c96b3f02a3db082f63d34c9800a11226924f4eabe04f08fd4c8c856502f2f15d2a71a22e31ae3d91e29242d525d9043f34d1dac6b4e1baa136876751bcb9cf7c316aeb1c6d0fe3a12db82af6fe0f8679b62eae890f57c60e90f8a0974ecb5c7bc3788aa680bdcab6d41a1806feb1665b5ed556a993c2568952991e51049d017b841a85e655b83ecec949f78aaa30a693dece33fe390df3d8a7625b691a3f5d702d08ccd2ff54250487f32fe60a812c5aed811b70c891b1bb1b555d590eac65ce4f89ef2a26c525a35189b298c0e5c23b294ad6c7ec0c7b959abd2389c5d4674af11400f3a5c25aad03a7944430cf2f6e82b8b53eed795cdffb353491e8be71d4c26458b2a1080b461ab2ac0615b00a65faaeea89c46e20e24a1db39bc0b2ef10e88d79db614b2c9654d67a9b43a8d16b774075b85b96e52b564173a99c4e408db680c7c133065be5e3c3be3482cd16bd0210beccc2d5eeb53f2cf0d6dc4114d833345d8405ed33a874ad01cb90d100842f7766bec799dc69d85e56b32a448bbc7161d227a54fe7fa512ebab42aeb8a73d4ac7c2af94092043e2d10cacdf870c122873465e34582f1bd72e62fa5a5434464cef01d9e9b8116c09e7cf4642e1640793fc6da6f5ad3c2fb4baf8abed5c41d6976c9938e0d15c8e0d0a65eb6f596c6c7f2d0d95cfe18af3cda40e2c10c062fa969ed71a6b7e801edc0ff7fce7a8d184ec19765c6811aa94819c12ca9d4a678b891c028d1317e21384b613694c301bbcfa1d2a013aea974ecda0c0ae5956a9deb3e48aa17483aabf32032a476a3442f3476846bfc33a91780abcb703b2309a49fe88f8797437b622bdad31c2ed303444020533c081cbdd5545f113c3b4ae519e7946658afd4873c877593ae323b27cb0618514a53ffcb10ad92045c6269eb287303176b09759cbb9aa4f98668c5195f1e49d5ebe7b7c4eb9915518c3fa8bdb162f9b16d66dc86af472e821656c14f01bbb2961d2e4431cb8cb2c779ac78830bfa41f433468216a5433a93eb056eb8bdffbc27fb583b998ca2f6329405057cfd8c1edbf8891ec7a46d13fb960b69a4b59b29badd2d16061d398b61b4771fca8e4faf18c47b75f9be986a8061868823ea913b6caed3ec07f43e40a644139fa6b83a6a26e61319857eaa9a00517b94c3d2a6236b7137bbeab012d0242ee2f45f24b43a9aa3368b43116925e48e54ef996c06447ad5ba0ae5543d4d8cdac86465d05f10ef55e3e99072c8b0f78c6429b742fdfab56dcb6c1ba5000b0a605a562674d988bdd04e90d708afb8845a594a68405850a1e27303a58d91e74b19494a8f6694f1429587a9e0d61c643126aa9b4d825d1e5a1ec9c6f164a95950cc0a6e53a7206647c8aeb721d742971a220fdd91260d4777f607a572ea2a16f9f3c597892dddf8695fcbb846605d297171640e4ac1e19177c27746f8902a76dd83d3d1eccb7715bb3a2846dde6ae88c03e6643c743e0bf890dfade86e829f4d9c04922ffd911c2aa8f971de5ada151a3def8253668752ce44868367c3520102bf03c6a1a941500e50f351ce754efbba0905c8f42801dc01a2283db4158658ca9a2fd2108cf0c945854a434e024830967aba3afc5d29770413a0650b2e32889522d4b6ab679c5e83b5b47dcfd9a3f7d7ea856102616352e1ac18be68c92ee91a19c7118aa7f9c026ba883f863585ad7be4deb5c6487812aafd39f041cd70135ea81174ea7ece05848b63098923cfe8a7b0992c3421cfa36b81828a9626e935c390ae242d2ff9ddb82ce8febee8d19ac5807d9315a6a978c72c803b76cc2dad40165c838a3a5b03e4367f2607d3919f9b4c27e1d2be02d55e2cfdd778012cc155ff48110d2bd37e79d57df4e761a526d90ac8b5e413c3db1d8b97d9a1681e77f31087d7417d447b2aa67a79081892556495b60cf1acafd31ac4a774451053140847893a03dd11d9991a09372753b9dcb9f6e17783385d24ef4f76bb9591fcf6a67b80c760cec09eecf1297486d1ca741379f6f2ea7ff53780636a25c93b786587f33e9f956bd150c7b84fbdf3f67ba8bb320e63c79de91f659528e1215a82b88ff32e0558dd169800acdb42b5bc93b7f228e59239617bff0cfe8f58344e258b5da193fe01057c2409ff20c16bb976a3cf61176fa9726b1d3b18bf9ad13f49c493ab1d9bd6c7be9690b9b181afa2c9efa0980b2b9516ec5043a345743d421c50e30e120c29699ee1bbf3b7184714affe8c587a9c9bfee8ce071b2e4ec810701d87a0e2ce8128ed8b7b887db9526c2462afd01ed304b2bf9c8139b99352fe083f875a6551f8bb12c4f3f4fa27ab49a08f3117eac2b59b5233a0c09761fb9bd76b73701ac3d7bdbf074b403d720f647f1e3db74f7834fea207a7a504415c1c71af272ecd3997203c389a61d79e21908a48b2d863eb9befb7e69efeb87433e2400a58bee8bebb8e58ca233fb0148143b6677d2999e5929ef14051d1e1e7c443b67ac67baadd824caecab060c1b4e3c8b1db00c0228442d54fe0d10254503a8af353311d3db2618d95fe80b49f6497094830823c2971829adef49ac5899b9c4eec0c078fc1042b69122d9c41fd2641a846c6db07fca5adfcc831b22e3321ef23481f7ca719abc4007f864c7e456e349f9f2aa6cd6bf526e6c81a8315e19285e138133ce95c6f9be713cb1de9954ea7d1d1ed17dad741a3ab1e4ce4c494a5a46bc49b338eb8cd515f647e8b45b38d2f4b21857aa49c3422ac9f9fd45daaed04a5a643da5ff6daa089415088127c103ecbe2d2500645b659f00f67faf3915a284b790ba1fc9e94ca8b871a9d908dc4b064401b3989abed899a923af85f7f1b6996b16069c7cdf6323cd423652536fbf1fc3276ed536fdee007efa68b2f1f993888289f456f019fc4ec0e212f646db5a0a30dc333144081729a84014ebab2487b59b39ae2d0db916f52289a9a2830a9d7fe7e3390b549f4569242347047457ca11d962b843ab8b667d8fa1687c3d6076e3d55bb4688ea4e08631eab2b8811de89537a2a1c8ad20b4e0db06002ad69405dd9f841a2e988c2a845f55861d818751bfd29a6be6c781f28b448944e0883934a7cc94f21dd66be0a32228e06e426578d155c28f05b86b99f07abfb1e27203152eddee0111a8831bd4d48b036e67efb6825ce574711abf852a79779d2a0ee66c184c71dc8d47cc97947bdcc6e171fb39ddc6d1edd595d0006e14d819d52056015d6297d01e72974a99d745931e2f77c97c074d6fecd37a86c90840d09f2f689f6466a239df97f0e91f0fdf0ca5d280fbd467946e0e53eb022894123778d445b1573cdd8347f79f84ba589ab572ec48ce8813fcc96b642ced14c5dec72478bb5ada5ea0c0146e5ab6dcb8c52f25a7f3a4f2815e92c30ae261cde4ce5bb8c2e34447a201d4fe02eae2ed605c409ad5a80391287bc7c5798d7714e401deb06797db6e7925d587080e40d663e75ca95fa03fb112be10fa0015383c701e80ca6a561b4c0f18276af321426904bd10b9e1eb051c0bd8d8884dd7b21ab7ad1b0afa7befbda59452ca9452e305ea051006a51864fe731c7ac6f41c95bd44038c85e5015aeeffb47f77d75a25fb1d1f489794eeeefeffff2fdd9dcaf8546e0fe4bf972ff50aec1555def43db40c39ae050c0aa4bc892e1c874be154c000c9c6a08d2c5d86c749f4f7ce928ec3857b129ffede657e97ab4731cb8a45ae6b72b9b35a49fe5be17757af48e1c66843f67277f74829a574d24a5d2e4a2baba3426175f7f49769c39c37ce39e7b451058ce161261f89c8708cd1d6ea6ad9d82550faa1b91f1b204b97bbe7cb7394329e4cac514a29a59452fbb1d6c6750383ed943a854350324958ab192435dae9f47af9f0f17af978bd4e70a799fc04725493a6cc1da849dd699ec7f8a7699aa6d96072291317f453c560bfeca95d068a1d04011baad0349c1be5fc34edd33e2d6e1cd79d949aa66958761cd7b5eacdab575cdb7346acb56ddb79bc906580dadd3d5bdbb96240d3344d8705798e316a37af50436559966daf18ea8675ac962a9d124722381b5db19565ff5b94b46656a3275b29fd416128901896099918b5d65a6badb5d65abdbb31fe27b1b07c48598531d231606a101da230981eb990bf2e5191c8f588fc55487e901317ac3035c56d35aa28cc5a0af328ac1ae9950f22085889e4c715a657de460ffcc4af307e7a3589c1c0cc891303d69594006126bb90dc4a8e009244c5e292b8deaa69ff884da50a503c737f8288b05185abc2750cb2b0587294910583d85d473e2aaf2ef7d8b7746d526115e7c7a9645f1ebb6c1ae2e4344cca584819066b70336eada2e197420c866022ede032c0990214a42dcb32cfc551499076682594206d5e55bd011e8334726b9ec8eb4a84525d315cd654b518da70784fd956575dd5550c6dde0cc75d65c550e6a1e00d5f20c39da78386b3ccc33a702758f36644970e67de8ca8e11d19d670c49ae752247a3b34bc792e1cd6b0cb8633cc038907128a37c33d22527093507093e49c33a6802ce882a407de7ca3baa487f10f68d00322b2baeaebe63f5786357cd2552c8aa1ba44ab7c6d227f6b06c77f10b1adab276e75497aefe703e22cab0b042c59d60a035557758962a84ad12a8f63855920f55561b6d43d0358b7c85fb5901f572dda00df43ab7cfe01b4252547bce41ab995ccd4e4ef26ae38eed180be28acbaae0056d72bf3aa6b555934d5555759c6f8d9638cd1bb1a220e1dcb32e2665557757d54f5655411058d124ab477d7dafd9193d65a6badda56419f5e61722d0cad1be6c032418d62cafaa2e223274bad2c95a5feff9665b6daf48aeba657b61c2931b6165b6cb1f50c5a1b8638b6c8089190d2211485c31035048761ab421820380c8f28f19ac2860a940f374a9e9327750a87a0643c493c2ccf8c0789a766c6621fb3d6da4a842049721321c8910cda88e5c703c84d84172df24639dba30f7986bcca873c31aff223cf0c7aa5717882b40c8f97dc5a73f4cad3bcfe7b1ae6033e77af484cbf75f3ef69f21e9cfc9e9c5674d17ce84f9e9afcd8e341f22daae841c5d0a3b60c7a5627d5c92373be257bd77f364e5ce93decbf26fffd0b497b4ce096c13fc26342797e6471c14e2c3f36e5ff1e4aaa10c6f47202d235bd9c203bee1021484d7ecf4b7e3caf70c18fc970c17e3dcdab3cf6965cf02fcb649a3039a6794ef13da799e839615392fbb1ee870b624f901eb95083ab0265f796f64f08c7417a947be5f1c7885b44a87d881b4b2ecda05d72a58c1f4f72c462b177f7e1810e79847095c7465e45e47fcf1057642f7dce7f9f1117c4d373724fe88961e2e6c83df204e995c71e213ccf05173a1dcf096c95c704cf29c733c413e339b9e0829e537ecfc913c4c6a9479e538fa2c788878847088ed55aab794e9e53ad1aab6573a334438ab0a55ad1b06a9ac460ae9b1ca9524999a954488098206a62091aa9e4688852dd56a9181071740aa243c218c965a0263920e28a23c8e20f48ec33c6383d50464c2d06d95cad4767a28aaa5c45a9ca3d15953193524a29a59459a4319f4a35274e8cf0a4071307f7e8df5e8c414cdcd851344522514d0b268b3044c9a48ed0b458aa2436340c3ffe89a1fe7fb9d26fbcdc9a29a594de78b99fff692afa904c49a4a14c0e0c55dc99f31f8abaa4332d28e7a2a78473896ea1418366a301040dd3b7747fd9a3f2636b61f6644ff64461fe63d22df405f4b45141611c10eca99322c31486be809e605a06e387fc2ea480b970d9130c130d130d53b455740846134d609cb11229214e0961bc8070412c6154d1a1b9048cd74b0a29329812b66c22bb30bd186385e178ac172bd8b6fff7d831c6f8b2a59432ce3925e794d2a6542aa1d1755dd7755dd7755dd779776771412ec6487e5a840a1da2e911fd69595c777794d89568c86e725c57a251ea5177c487f010d7f21e3ac4a56257ead1d6d17c97a443928dc8ad2238969055105510f9b919eef4046a0a7ac2c5c48e6b3dee4aa518e9293b0dd77b4a111ca4b4aa9b870d12b8a173e89b969ee3c6b0aa1cdf42f3e3067c8baa472277c7d9bf195c10638cb12a07a529e1cab562d5b46cbea54b316f22bdbb29f0a4cac2f27d9f8fc55f8cd1629b95af56d25733477ce856ab54d68e44b77ceabfe741df3c91fe7870c36435235c7554891e635cad8ca8950a57fe67040d624ed4b4629c38f243ad75d6e926937b2a954aa552296befc5988525155958be0fe3d4939ce4e22b204750915c7658c0165168cd10840d664845b6090312624effcd4f93d9c15f7a618a16d7dad343d049f2071c73b806addc4a6ab09221b7921a9cb2b5f7726ebad6e4a6525391a7e76f8a214fb9d46341ee973c4789c77a74d25590bdd703efc77aa03df170afc0bcc3388cc37420b046ae1ef844f28314c7a961cf167c21bbbb3b92ec33d9793892dd9b38c75710183b498ed55f872213ebd0c12eb00e2fb007e31c3dea0fc201261d5ce00ed6c1835fe0f9c1ee4937c3f1053a9e0e76817774b00bece10149ececcb3caa5768c82235c387fb30ffe33f1894dc09ea8040d04972054012a2482249c57ffa10f4a68e2ad905a8495af664dec7e4c080849baa6f7a98ffe1c3ed615b079d73ce393bd8dacedfaf910333e79c73ce39e79c73ce39e79ccf596b571f25a66bfb2d8a1e5edfa2a3b3a524570c3dfd21db25b407568eb4ae578f2c7d9939f959516536a1ae2ab6d56a654fe6a65d8a330f6f17f45df70551d206d2d1d95e942edbb89b65d9666f96659b3d4141b15dc6655ba6651967d3bd0b2ba09cca289d3aa595b39cecba1a6426a3a454461965cc3ccf6f79bc69b6d26cca8c3b792fa3f9b06285c56882c572bec5ed4b0c2ab440dabf0fe38f606461f9be0f0c6691fc27a1f9c4fce748b63243f2e37a4587aaaa613ddaa0901f8683f8fcd08316f9714da27bcb60555d257ca0a854e4ff64e79ccbe1cab8ef362c419ad6d530abd5b68d8b31c69883d66a6d9669dac6495047931fab5a824eba1a8ee4c71b4aa52853a2c4f7d6522742dccbfd17da568f3a57d573a8c8faacae2acf54550ca56c9e8af3a4a7bab6c634b9d103fd64edbd61a636c200c5052b0cd65e8555588555558515d1be448c31aeac75555401f2211af32a4ee9902119ec9a0c76120e6f58c399c58f5d66a6c22aacebf08d185868102120073db1b897c10407ee2d1bd74d8d8216396fc3e67a7e520e1fae8fc8c272ef09c340c53d593f9de20fee639b75a7b48c06e9a0a753d7823967d3b4fb9453e2195544356070c1cfe7856f89f88bb9d323a27e1fcc56515da6ee0f1fc829e6886ae6653e8994524a6982910136b1c820b7c96472af2e2ca6097e9c604a2f31db83a0031cd040cbf0787ac516474c452c5fd5e6cc660575c0c77f593b915939eb55077ab4ab35d0a31e5adc2bacbb7b945276d5d5a3d6964d97046ff7e8b1c583526ed3325b7970adada5b5b2966dd5d61137c618638c91566db3d9e65acc6ca51edd7d4e96f683e973f66cb7271db769993de9b84dcb5e10c29552246adf5858b48ea974304d7386261820a79823aa19948cc964ed49c76d5a66bd136b3b8c33185ed7d4d1bf552aaa39e79c36e33a6deb26b7b1b068df77a7e7eed564aa157fb11cfa9b8d1530345840028bfdffffff7bc360dddac6757d3d1c442d82c144b0cd419d7190917110c5fe9e845940162a8289449d5807e7bf4eeb820eeb74581d5686c17a1471e87fc07a94809b57f1265c1160b01ae68c891130b1e72ab13bcc6f608e82cdf8018ac91019f419972e4460060cfca1ad154d510b8d23c38fb72db6184c0c6d2f1ac79179db924d8b6ed99a606d31cddb9ca06185ac502b820a331b86a1a665295a66b5101566360c434d0b516166c330d4ee546d35ecb84e66f1862bde3aa0efba29a903e9e8ac69b893828241ae07e1d6852761270cc36ddb3aad1386e1b66d9d7653523494ed64eb366edbb8cbba41f9185488a172c54af5a5c6b85cf7ef73a30ed14cca596b5dc9d4d52329e8148ec3f127e602a93f3e39f25b7241ea72ff78d405801ca04008352512484bf9fd6689bfa547153beeafa019eb15ea955425e97add30814e5829c6e93e61f2c18f0a68e203cc405dd445a965d5c4506db149f77e0755e1e65602848c77fe2f254b4896854b9c90a01e4dd3b26ccecfb2ac9b73ce8802a594524a29a594521a05c6185b6be3ba098388e67491c867d3b40086b4c3c78a16c95a908b39e79c2e3e29d77385b8e027dddd638cb5bab5020bcbf76994524a7b74448f34e040f0d0063a0a44f0530cb567d067eac94fd64f613f9103948ab4c3dbe044e2020023f950499c5764d340af9c52d75a95975c72b0d6665996596b391b970b8548775b20b6c5c35a6bade536cb6d2ec28015d65afbff9af6da7c983da74fef6e97cbe572b97a587befe783b1ab86ce5f9adf5dbb8eb2ab41e32ae5a6e468ed342eeb38ae7324aebc759d0f59e55b12d29dd2f7f0f38d3c914f9020fa7ff09aff58f6f6e851e89384fee6c6c6a6a6a62412cd30838a0a082443464aca975c1cece57a0ce7bf6745168ba5815679ac458fafac5a43a98b276cb03a308fa903ebc43a39a5971854e801e291c98f3bf354eabf868ab7cd41d535adab61c32c317cbd9272bd6ecd5a5ff3ae7ffdcd7fefbad9b7707ff5dfe79f0a1553f16752d69220e425c7a023f1a9f4ca13493082c46087c37466d05313df5872bf5eb19e735ffe7f58714187a93d6a87a9c25eb00303bde4840f10b7478f3a57f4ca77aae02a8f3d3f74fa8a0e16f26398910bdad99e1f9e92e7e5bf0eecbf87fd0783fb319cff9e89fb4d020e7751037560a04eac7345cb7073078b5e89118b335a8a2bf6eca91e7927d4e1418f3a58f48a91c6d1b962c9fd5c33e8a90e163dba42874ef0e3ce16ed514177608e23039d2af4e87107c77164512346ab38ae6165cbe018058452419166c719701cd6b55e69427edf263701991fd60f6b0922c167951e695ee70a0178a85305cf051732f875605f07f675703a3938fffdd781753ab02b3c588f9ad5a3f7fce0e901ec68018316d3d66ddbb6cd5adb6db8b70eac03dbb613d6ab890dd60b37e8b8344dd3acbdf7f3c13c5a9aa6699a76afe6c385b52d59dc7998ff297ff5a8bc799ee6756682992bc863ffe1641874771696efc3b154d2bcd27c964c8824fbccc7f103da0929b9decc43aba2a57911c6435d50a4f1f01e5e06442277918bdc9fc3cd719cebe6d564c23a2e4cd435670f5b39d305e94c3ea243076895c75996922223837426c690ad57c7733fdc1e94d650971059b8456ccd49fff80aa89fc36c4d5e37ab24aa5ee9d063bc9493c30e110d2c9c6cefffc67b1da17051aa61ad33214a267584a6a58a496abbfb0b181ddcb859429dcfd3dd5340b1d3700714676080e20b5044c55044a26758a1b8842a03750ae8492f404eea809a0403e4f230d8820e4ca417f1061660e01778071416c9c71be0f10b90cb0e36a6802115e9f00e3300e9418b54648b61d8a3517e1c676228c78b16ebae60e0d0c2c02f6a9d318ca838e4bf0a03e4526447a7835d606097223b5270c773e9e014ece2c12ea6cfca034c76ec020324ddd213dc241797223b60e0179ecb0b0cc39b7171935c60e019f784e2813c9c7814701e6672581e33a44781268da0b7d8628b9c3c6199e3f004e208629e2358c08bce8b2517205c45876610410409224408112246de4806db15c176bd0a620ceb5727aa578470a7c712438f988a333104793ad18b47aae7a30331549122904347b7c46e5525e4971d509362982dceb7d018c6d0b3ad69d9b85c9450beb384ad855b33b2c0a3631400d3b194d6daca2376d227e062860f6030a5b473809c4ff87caa9452bae7b0e69c724a1a261aa6a8d252ba4b29a59c5c8c938689862985868986292716c3042272414ac3e42dd12d9b8db7ea91b631f168321557e4c7200e08f931eea4c89f120ef9b7d3c459d74e2ce349c76d5ad6d1987befbdf75e7c3fcb59adb675271725a74cd8c47931fdf88fc25020f44451ff51199a3af2df0c45922d41e288443870173541dd18f19df4fa4116eb1e17763b5c08002365d87aa817911222c224fd5d059a94ddc830ee550ca2f082df4b494596d52afd0bb66ddb1a65c39d941c409f6fa6857474cee1757408a55572f8985c102be0e2c7fec31360c2a48b1fe3ad2fc861502aed260bf4f71600dd84d2211d3de330203f59e086ff3ee5445ae506cf4d442ed831892356000a7eec030438f0c8c0b764d8dd4f4e4eba462225c3e232279dbb735bcb663689331655bc7b141f32d8d6dd9b7718c69045d117db2b61586d507133bc75ffb66ddb3663ffd50cda8a84d87f3144adbdb6f4aaa62aedacad18dc16485f435235a96fd93e40dcc7dd920bce588fbc16691cb6082d432b864e3cbb7920e64cd4143d1832584dad4fff978426a12bd046018b17156205155e322f4ac321282328a1e98a896e51d22ddb7cbada3ca7445f38bc75772eb76ddbb0ec1c531997436232883305921d8314480671c6417b3069a171cc285a86b0d26dc6be25eb91c51405b11888f364c22483f884c32010eeba136eaba1a55ea12fd494c15c1c910a430ee5e4661b877272b3edc3facc0f2b440d298561a994dd6fea045f578b463ec11b8e2ab1c329c01b08056ba00da3e01468f804770a6e0a4e41e635de40dbf599a8820262798b74414d82c9e1e7e39a8677b4867768de8eccc39d03522853605971efbdf7de1b4336aceeeaaeeeeaaeeeeadad0c3c7bdabbbba723543c8103d9a09c81f3dc42fa5b4a1c74bf34ad7f34a429cc8c78ff8ee677e1e4e0fc4dc05028643690d07436348622d9daf7923b10a0b6c11a8026cadd67533a3055a433f1f9a59aa02e4469cd9ccba7b65cdc0355973be589efb4bb0f7ee4641f16e607d3edddd0dfb4c69eb87f5911fd6677e58ac564d8ac54aa5f2636b62f5e885d08643194e61f528013e035a650f0bd30cf696c9c4fa7c33d670088b4569e704236ad5b60fe682dd02bbc6a53606e2dc413f2f29fe18638b07922ccb32f9f1474e6e245cc1e685dc4a7eb8b267d1ce2ccbb2ec435958be2fdb3c1512bd822b076a5f82f5ff2a9528d689258edcb7840bba4a1543495cb05b436a7338e293d4910f10f78487b59be7abce5528b899e7aa7b842b8a11b839e20c1463c40fe8ff5e3ace6bba6d5bddb66de35e4dc2ce135c7bb76ce92259a9ac2a33b82045a150288aaab4ea406d392d8a12cd89c3952a0aa6d0821b3137625a50239c73da5aabb5d65a6beda4b57a5e9e57ac717a5e73ce686df79cb456d096b7c95598e7e57979683cabaef5d508d22d2f53e3d4a3ee775023e679000024f26300a87ab4c515d008921fd338f588934664b43e19a91e51567e58545941d14764b464189131234395bfc25a32a04039a1de043faddcdda52e798d2be8e697f9164feb77d02d1e289e07710532a4110ea4614fcb03c5e72519ada9a24cd88c6ca95e91d1aab0b8795ccbf3f2bc7a6437ab7d7ae479f5ca7b1ed87f238f15321a87a70acfcbf32a40102e58619e572775fc9fd8b7f68405c389d5085f4c215b4a97dedd52c6d55dddd55dddd55d5d1b6e7885423a726e84c80d5d4af9dd5ad792e26d7254c272aadfd0ffacfdf74a334a69c66aa504210a1a259488eed1c6d8c518630cbd23f214f4597673ce3931adc074af2c568e8c9465d99765d996b5b12e7b6373325306b338d90f8b42a15028c70e62b1a80d2a6eb5d65acbc4b23e2cbba4439bade991638b417b93bb9918da3ccbf26672c88a212ba4553ec5241361d95254f92e674fb8a54759255ccbb22cdb4487442226485145b530f72c8e116ec4e08765a39852f462a2e5a49f39a7665996a569325227476af55a6bad3146ef6131cdacc536c70d3cecacd4c6b549213485d7129278e2464c0b605274959a41a24a62f372b16a9ac4544a561b57dc984a7de8cc07a6e80c3d4265a84c4ccdd023ff518f86ff792a445f5ec531fd91c14f8e8125cb5c7c364dd5af120e39b898fc870fa12f1f4eddde18425c1e380360097c7c4004af2cbc7c4c91e2aab5869b9612d630ace1c97759966d5a4a4daf3c4e01b56896384153840b6e31705335578a019e7ea8f4ac5aab59a84600000000a00013160000200c080583c160403020cbb3181f14800c5e704a745c3a1c0a64490ee4408ca228a48802042002083040880cd99005710c50afadba54a793bff4224110d47c37802b676114503015164c626d49ef0b8a42f8a0ae940875055936c6554393d739505d6f4fd4200c644e253a9c591aa496d4a668f60fa6be33e32a443895ea699d53192d362cb68133b928ae3209fd469fd8fcbd2430ad4c28696c1ed7e808b30bec7486d1e559474badd87df8889c2c600adabf8163f258e3331f8b07999bfcde2dd12b15c20df6e02393c227b048a02ed75f2b0b29b285502005b6be878f7c09eb4ac552a2b4bddf1ff5d3e3c12f6e61602da9959c661f11f4bf21672920605af1708b2952b380e7adf7b7b4b1fabdb0c88bcdab748422a683e3d46a4d0a7330c2b17906eecf425368ce52bd930895fcafb78028a59fe10f93ba21a907ca26de99bb62661d0223408f912b1333eda2a27cbe7eb2a19e5315f02f3b8bdc30fbb95dd9d0178756dd7f0ad4a24faf119f143e8c381135175d8079d6453ba9f38a722462180bb15954e0c254be729c47842dd74eafad183ce02bec0a9f61148735b91b64dda2a00f94efa12953750b72af0bff5264a9d1f0f03158d080bdb26fda469797fd842035f7fde94bcf379f83ac5fc1a98eca56fe523daae79aa851c58974b034c0988d45b1de4f4281f60841b49a8906c77805737d11c7b74424b084c87c8e8dcf80ab75a63a083d703dd5d5c0dee1e2284e1f3e29fd6f93293107e7c76ce862f56d400d7a8c56a9920f22f72e1d1e9f788cce8e09d5666c14b3acc7531d439942ceb814ba5f62f9d70309ab10d26fb4e2001eacb7aadf921f69c442a5cfc4d2cce1684cf0039f395206f665d38221a535b5159c96e07ac21d58a15bc2ecfc150cc150ba286841361088c2b3b40d4f3a22a251a00d2a986880d341369e662db504e9b856ac1c2df858bdcf0071e6181b9b323cd97a5082f438761f3af5e4049ac5895d1404774495c223968a1f025a7cd4f79d7f7fa91e1e5d246d5715ecfc9d4897803043c06240ded8d06a1a764b3af3fb6de5745072782f858010efc2e382f3415ba9da2b2420afa4dd03970a637a1a3b175042d8c26c08e2488d1bf8891d4b5a5570a4deec2e7cdad62c6d72c1d2db05af1d49183646ab28151b3ceda8872aed1a3dc6565ca6c8dbfe8ff948c4b8a8440e54aa800948a3c0f95bcc07805366447a19a1b4c8d5687931a95972913c8843e7a606f8ce902bab01e898034b759f588807484c8b8ec45de6de8417e86a520dc433b5935af717d28476d077444ca96ff7d75da52925e68b4c99da2d0c457f8f909f4127c12dcd255bcfb1f730baf4741be051001beadccdbdfecf58e92ade37379f95cb31f34ddbe5efdfac8557db78242cebb9472a74894679ac6703f6b2973ad95f88486a7838aeab5658007e4211da81022edd814b018ee634460020113d1f91f8e88f6f9b29c9880f6d0216671b0ab297e2fa3de003d408401fdb5b820958d0f99d2a24921a5f8d3e3a654b5ec50c6f4973c8a36f299d2f4db31056746b7c1dc2859b53512a8424c2b13100d01fbce04ba3f21ae31f7d509e0c90469881f00767be316019682df79cac4c4d289ed7f7198c35775f2ce9d1c09067286cab93651927c2f5c81a93af3e6a7c8fe49925910d18745ee23931a1dbd5dc50d2d21df5d31907ce3207882a3f80043f1e78e867167b07aa9b0c044915a3f142c7767f465c315fd33fc76bd6921f8e0092360b824d892e94f5080c45345ded4a335144ec31a38da359c5438a47dcac6d39c5467647dd3c6283fe0357b43d39119f204f63c4c93c2d6f00f53f6bd01d3dd615cd17434123f25139ef844807daa67c156b7e64bbb1862822f3ee1105c78ebf6f41530fda9eab8ec645b2f395333e3d3e92c6efc4e75b069e57c380deabcb5c14799e6770c7da63a76f48e38c2e5c8fa23a6e85a540642fc7da361a4ba43574dd519595e39d9c5f51114cbd5e785222c98a36c4e01529b9d9466f269b803cb8487fd4766147bcfe5463576bc61639449858b66ca794168205036d09a0654434f6ccbe47aa3f6b74800e24ab683ec57b110ba18f4d3e1e70e5a84de5bd1119c450f23071401e810cc8610362159a6ee6eb98e49baf063f910c20c13f60f48af623b20f0c88b361280d9365a8ea192b4c5f8792e824d68f8a4dee9e097bc6f445b2e5f164b10c83d1a7e14a87fc99959085b0003659ed59614806bd4adfca316a8bcb09a9df388868ed80163160e223f5dcf7fdaf9fa2a7570d7d005ddbf5c4a8076498960082e3262e7315a30977b9c4bfe3ce2c20a4a77221995b4e4e72958af2664b291f6a848d1fe98e7081f6719718d137230540d894f0b54743fe1e338f04080e7d25517c79be125b1c8be401c6044332c916991d23d229c0e90924b2024258b6b973be3d8e4b446252ad878fe844d5b53ea3bc45ac1caaee894c6c13fe47c4f425977a5a725ee1f8c9cf7c093d3b152b8277174624d196c223a615eefde46046d5e226899d4e775c5621e5ab5a8c75d997d9b2c1a0e241d0761470b2794f6acc0e93d662bb3e0e16783f1de41475a10df3fc235a0047856ce698abadfaacd0734f9fd692f9a433e020ee71198725503a5d4a09c2d79c18718f18c255801250603465802c54a7a96b71d46ce597a453ae38f1a9bd354f775c77d191294d1f5ba647b43eb47a21042cf4ee89143181a7c8afa71671fea7a4b56a412acc29df6aaf6efe48bd52dc0d73db5243370ccf996e3c9cbbb5b15fbed2f761601d2350e5d01d2b725ba2cf1b7cdc581e7c702920285c0cc9eda56509c1fb871d29bf30bb071449352cfc242f3dac8cd9207b8771ac34cda3abc490f3abd71bdbc9d74af31ebeb6ecc69c07972d74da455396e25e2ada1dc388cc66727be204eed5740c798a812ea210ce6a5e7957d39f57c97c0ecb639b6e41f933be6c91aab1952c461acd1047c26083955bc68654704dcb7396b898e155fb195e73c4940154d30f4495316992763c3a4e1c1939ebe26fe67565e761eda2cc7b45f95a64cd4fa82396a07fe0009f316241179fcbbb3c11666fcb639587fd74e39e90af7d17ee0ce2d7900c28a0178825f1c122e8f0e12e41ec4d0462dfb55dd6cfdf323f7cc3e31e642bf96546dcf6b2ef3249f96294645cf1bc9f53432ee78c77b9fdae14dede4e5e17bd822006c07163d3234b296d4d26da0d3f4a82ac41a08786be13bafaf2c4ede2ade1ad56d3af25c499a7adf1a855884f0c5864ba5afbe96b4e36fad6b64108a0c285d94b5a8e17d83a272f7f5c5b6977820da3d3c16838fc94bbb36619b4fb1247c8099c7e95c77086bdf7d110450af8dc6d3c49a9b6ef36f4643d0b3e10c196132021fd7c065d5c9f6a138c01b04de01e7d6add1c23f89faf4e0a95ee2495f6b6a77b109047586549f924a602085b8f37cf693f9b9c8ad0ee454a297aa1aafcc2f49a46f5b9d826d8246654b468bfa539785973a950d81509db711d95e24e0595574a2efb4bae34dcaba2ad6569fc2bcd3629178a2e9967c2104f01a4a49967adeb563869ab4412935ff9203a125ba95e1ad9d02b2aed40d1dd7e2318685b2dc2279a34169b9ec40d9153f5ed1c44048e508cf5aa12eef596e1fd0abaf9dffa33a9001edf60b16ea8086548da8e4d72792059b8df80205bd112b2b3c68feb350d081b32fe584edd45f8bcb9975baf24803079560a1cb1642db584a191f0c3200c2ce444a8d84d5c545c871fd708b3914c509a8b010d10171ca17ce7da28de3ae7f0202788860b36d217cc5f9a03391c0fbe4a6e5c5165dde212a3624a4199630956f7b1d733c045c0daf5c4a43bbabfa55d012496be59e94aee42593e35eac53944a851db0ec531c8868a0bce17cb6a1ca5a4e1e483912ae7fec0ad2394fa81c0fa6112dcc1d6ea065f29bb87221326d9381389f549d656185885d00067b306ee71149ab12179267c46d69279d915f945e8342ccd6842acc71a616ea8b30d75ca8f4daeabd7c8b6ce2b5877d66b05eb5129d9d0b53475879899abf41c43bdedfdeab800384e118ef71f5c1bb8fd6fc3bd5a31a35bd948669925eeb0afa5d7a60706c3525cfba17c347309cfce7df3a060e68146de48b5a9a93c5490414966e0900dc7d5f34b9fee90791104c72be8bb3083706e3da38c6846b2c111d472a101c0ae8ba4382183232cb29a16a8049984c3252c223c2fd66323e92df0d1a806481708df022e6119dc24b3c3abdfbb6a4c41275e94980c9c680715b5444644273d2d4198675b56acea6c100ec6bb19052b5a68690fb5f5dbd16b8850e886ff43a223763455066e03bc6d030a6ee807ba4fea4ad7203a37caef401b1e94ad31535956eae6dc8cea13c86326399589d2bc24253c52c39fc81a6cce2dcca3513a35a518889190c5a202723475e752041ed2921a5bce62418246d9e6224e4841ca9a3806e7a92974e4606923afdfd12d4890f615c7ad9a4377e52dba7eb0dd4434b7059c5eb7f524f4ccea1e98312d509d253081e7632e48527de0cb06c2ece9573359736606d069ac8c16e7cf40306e36d950569e74988dcdfd6ac59a9147a0ef0456fbbdd793773b4a7732ca1ed6ab051b2c507613ddd82b41ca3e22366354a60047364dd4d74db1b8fca38127dbc593236839e3556b59842c0215e3aa79a08faf63501345cae2d1278783396d5079607c772cc79e1dbac35789e08f169c7e11832daa9a80b3c0d9a9c9cc039a87d8239e133851ed24fc314a56434a4f4dfd58320183cf1326e033408b6f5052caa6fdea3ffd5cdab824a74628b924cf546e60112125bb41596310ed93c318300ba287a7d5b46cd61d893c7fc1c7b46c216900c3ac553519420176aee60d1a705e2ec9da4e890d8ad16c2e6e49469d7cdcb04d329ba1eb3b4dcab8b6c37355c039a9c39f80462b02a2d569b262cc768fe70250be6491333ea8dc1b02261046bcf61e056b97ef7e3e12d7aa343703b4c6d3baf63b8ab7840748b2ec8317811f8551541fb2526be7191703ff08b926757636469299158c981aafa972e8068a75d5091aaa02849b82dd525771b7d4da7f616dfb13a3fd85c6070f3d6c10ad2a2588b47d79a55ef7c36dc8795d853721674525356253061ab33fdc775c814a3946700c1c722f21530b339fa129617d13eccc654f25639361a6bad595b34f6fd54bac6bd5d50424c13e78f1a13227512cad9dd9d0138dbc4422da5d25a59f91a0968f2f851e2d9fcf542170dd99d63fc70afa89661f5db105a56e822ebe6bec665cb679c4a2b14bedae03d30ba8fa9c6da4dd2c3e66aa079c91c37398f8385b7fc704e75020d63ff7e38c175fb563367741a15d6998de5738e9402333de19f2fc824e9976fd12f7ef9fd8de11733f207d1af48dee90cc5c701b78d309d073b73660d63652137fe35fcd47492fe6349ee6497436377a7f50705b9b05d42e5e79914e2e14d67af488b188da123fc8a63f4155c96a426307278c1badab1ed9b84462541979919c35aaa973093ad46bb13cb8d8c9de0f712c0b4ab222284669e6c10b4558d2bb9d70406e91b8a56a0be63b498fa4e2a812a429c6f2c572a3c9f3dba16578f28a455d1b6bad6b8a1be7228324840d5b5f5ee6175daaf7f81657c678ed00b9fd350231b43485de3a04589aa300361a5ce919a74ad38f67fae81a32e4d715fc74854a85fd21bf4dc8c2a34d2d20fe9b9932d8cbbd30a7192afeed60021fdd8f3d0f4bd3c20610d5be43d6c44257de6c1af328d44c09cab2d96586c1f7084b812dbd4dce3389802f4185e6842907f886a068450a408c34f7390435781319cd5bf350e4e2c4b57f440ab68c70aebce6bde8a66c119642cbbd093757f88cea8f62417d1c78cded8c7e362dafe92a733453bc6f2b9472c2d0013a655d1325c00549410281e1503a100d9edc7ceee3dd2c7df426bb8ac9d027355a015a14a91d11497aecdab18ffd47c9cc92b155353bc6873101fffc5f7b6547deb7c0aabc17a1ee7ffa6afdab99488997136f2f81ba3b1c8919222a987b614b76da680ba1d27c0da49cc4a586a1ba8ab58df561e88dd4030f7adb7e8654b394153de34e8d15ed6c6352c1da00bbf0b5f83c00d401ac33cbb35b2103b0677dcd1004a2399a65fd619c6cd1c30768539390cdffaa585f34a5b8340324660039ebe6dda7ebbe2d327a3d2c8ec5d3560f9878c07a986ec42e4c15831498227f1ff6b510097012e84a3c8c772116705ef4ba98106bfb2ef05697de2242af0bb1ee16e13e698e9f960212257bf01bb65d000ea281a0f92fbf8929bb73acff43e7adaeef7654ac8af42eb15ebb1085a9e58e1a2f86c449b1f2568c2f4f14e8217f8f57d25dae78736d87afbe0c93c9db462c6f7e4f9dc60eb9ccbf5214bc2b66429db8aad7861906ac943563d2931ef54551a7ad9a223e3dd66cc4921ae5f13200cc05b930e7c099ac0064049b0ad75fb91e512230fa5a9e0aa359428cedb57eeaca885b2e5b5ceefe51761e78df1bcba06f8d53fc83cc42035a312b50407fb2ff93537cfe605ac72ec65dd94cd1fcd78bf6ab15ca4883d4d42f4ecd69ee4095235026ea66f83ad2a2eb61221c36352e963183931ab1aef7e0dc1fb76b442be80ccc2ac320e52062340a246f84e2c686319852304e4f28d6fd3adfb2c4d215bc224012e77a04d4308ff30ee9401be4d33148b60d8b32f9be86c231cbd13075c5ebadb8366546ab630215c8053bc3541d0eaaf2bae9c7fddf5e8bc49aac0b3925a9a2225a7ce2fa512bca0589e8b91ed7a7c9758b7c337ae22e0961da9ee61dda6e37e2872a8779d83f30402e4f97822f6ced7ecdf433829bfce82fa466bf5cb2f3c96b07edad4530bfa553e256fb90afc248322431a3860b92e59eabb74fb504824d8c12162ed1af9a06a598ce9b2ce793293bd0f0d000273aaf5c808904a9c2d3325b462f914de793a53e5622f744f119525dfdb71b43e3eb4a5dc1d7d40f5c37e3625c6feed1ea7475d1acb96c77086a2961ef7bf98738f28cf6c5c7ace506fa7968223f2156fa81e65eeada629bec55ace80fca090e06529fbc814d4a5af65c5f090225c7e528c3f8c26f880d94924d0a35af82066d46f7152d877bca44433610f35f8bc3e04963bba3955a18d753ca4097896db6f6072ba6e55e4172f8f90d09d1ba5771e9ff1097f42b795b17bc7903656f8ebce9bee3e2022ad8931d2a7854c424842df996cabbb80a48f3a17a623fc038475aa312ab242ebe153b3731db78848b2e6fa05a1463fe928762a3d84ab3e1c5c97a10ba2a24a503311a262daf3a75e90dfed96838bbbf76173877d0e7a7fa35b192735b0b1b859d783ff488075b6cdb305c2743f25b2e079da35f6c4222ed38246dd1f63d81ae87142f75ea7a1a29b5de95e48d8d766d60db29b82bf3bc85f018ad7412f7b3325efb6feb89e166819c78183a0965ef24a4df11a73aec03389803e36ac07c33585e77933f8ff713e6fd6233ded2f0b0da6966c3d7eb72f2002ac091764445eec84cf79973e9a5a447db4e5f1e295a2d73b48b87bac00b8e808fdf2ab989ce19e949c5c0d617e6bae4881fe83035eae69660dc3514757a613d1e90b5f84d92cef51b3ea18ce3241506b8f860adb6e24c665123e86d8e0d3763a2c9a4609725f66ec9351d9a67f56fae7362910af8da1d43ea4be0b1524e69231b4aace1e23b29f7533a60c69852a250268cbf2ef40e51a2a20bc5b8748365a97372117b0b96247ce50b01962f302cff1e83acc4c842dbbe28230f7f61dc1733b840ceec507396dc89b02604b3a96996a1a36a845fcd27252a6183549e4a9782c566645265b08f0a6890a51ce4e563b6f27826d469fbe7aec3d795db28e1aea1145ff44020f7cacd49bca6391f2c20331b48b79a839efd0522b3e7bc41100ead9853524bba47cf1788aae25b5493cd87e3b9263d8092ef8d677f9622f4cd62d3bf35fb36f8465f6f62dd11e212566fc23374db95b07d842911e9b5571ed137dfce1cea316a0e69a1e95bf51d9877dbcf632d95db265ae964aa6ba2293750449f4c28fec58a888991513408f5cda1291da9483740ac595f701d6c1b6d1ca480c5b79e4f3c5342a9a549b3070b5ed3181231a1b6c5f3f541a113608adf9dc25e11ce7277e824f705f631e19b47635a8e6a4f533874cb6ec0c81a0132d01a17f512c756b5880fc7646eaa319bee7480948c139c52688c14ee53bcf93b6dcbd186e008b266e1fccc5fa3117758de641aa064ac56eda9c606e092368eae072f5e133abd5ce198cac8badcf42c76d1e2a78c453b096017922aa22fa08766d347215dc7148b3c09e64063d9f490cafc8851b0050cb8491cc3b0b1da7eb889050b0efd38385ab122033c9b84a5db0216ed9d384b831185d93efa68d0b889b764817b005af73c560d8ed9774cd1a6d801d10b08c239e12e19922847009ec43473451e06f0f5630996afadcbf32c087efaa0e69d549ea7f21ca960518012946381965057beae3d0fcdae339af29e3649f96814226c1a1c661e22ddf1a53d912993efc2a9a41c372bf6cd160f074efb0037511c9e8f656bf457ec60834a1179b2e6248997b4f62767bb65368685fe9c6d85ceee2c4e677f63abe96ce20f081898ce36e7747625d4d959b01f4732e3b367d0638efce3855420d3d19bdadf67e129fa5f71c217b2708ac45885bd44e385eaec8c2a6164b3930d8708dd13832e2c4164f553c995cd5c130a62bd0e893f411804b1e8320e9145c139e4a33ff93e87c449e3df5a735a21a902f626c3b6670b22e652047c76f3124d2bbf930af38db5f6e6c186e6ccc299c53bdade7794c13190226d77cce2ecc56f0eba60384f9d11f913a2b10d706ce2afefc8f5273804cedbf15f95ec0c83734be13df371f84485cbae813783ea67109c29e14ac1dba88d74274a42770586552383591426368de78bdebabeb8d0460811908e7056fd50391fb4e3afdd30c221c0674ea34e6ebe345ec5a0f7123b7bef4915d8088ebaa498500c6a524bc659564bd2f1a1256aa12eadd55cf5df9bff5c6a7814fb34c898ebe5efbd2bd06fd40a84c01d73dc054963da1d8e2e1db757e5da7e0f25c6598b3b4658d8801f990c20a9d222ac4f86bc3a6c2f117ca9f482e31a95501785ac0fe97edf0d1e2330136cc9589139b82a669810101f8044d8c2628b8835c7f416118b716f15c5cb33afbb87c40a726a161054898912152ee98594b9b017331b6a073236382d7f8d79785dc3d63bde95c5260dea8737036a0b5e7b994bb4f451b11f0592f8ef83610a4127e1d4938e6058d448918c367c73e11a37d65074e2ba6adee416554f717a6502314294e03d818e601096b870921e98335f6c866af4baa738410f266a45cf785e64d6360fe60a54e819b9de8052cf8e04d7d69dd76350a5d9777731dd872a3fcd97dc1e31ec687707f984b3db5a4832ac042cd41a3607e493426248652b7f77b2b0bf192349802db94f7f5744974e9957083d26ea73c3a21ea6897d4ac6a48de572f1d987e316db756f751892a1201a94eb40f50eb23e5e11fb098083ee01b79207830998b4b05675e2a1b9856ffb309331f164d6ed181060dfac3addef8a8e6b72c91dcb4daf165cfdf8a9da9e7459ec9cc72cfcaa88272ec0101299813016ab60925e33040aebe6697d96839689df6f2fc52f0a80f82594bb006ac3f522070e0789d71b3d8e7543aa6b79cacce1001ce524de81306c1c1afdfd361ce933b15b18361c79f8bc4d67038892b8ca2f90e8a44a3d9d199e8d3069f612c6dc5e5ac49ed50575b03403ee12cb20d1a0bbe931f094c8ea1242f0c4b3a25d0286dd68f9a568a50dd985a3f4ca34090c15c223d86edc29f82d8cf3d483f6cf7b09d720198b146f0046417306723e05c3087bb5cc05c0abf6afd59b76eddbbb8e50859f3a84d440c174477916664208e300e2ab031a1a0acb2847575767a669a7f7cbc72868a6f79fb416e4c7fd35b1ea049d3a59e5b71834b082cb5c77f8db021f87cd1334e3be8f93c5a22791d841ba3d50a0d1fd6b65280dc34bf6ade47d6206d6c5b5ae60682829f1e132b37548861984adb21a620affd04fd64f3110871a9f0558402cdfd1eab5899a8d37ee6ff92bba501ce6cf5c5113e350ec2e00f46042cf3ac7e79bde55fc8daccacb8d3cfbb9841df3d31dd3b38f2ad85b073e88ad16fb40125a3da9d760904e4f0cd846440fcd844ac5168316beaf7ca98426486928fbe57f68d050c99c0d3823adfd235ceb3e670b884e583256eb293c6d0b89e3e9271753c59de8f39a0b320b93ff0a868f6e09e03cf5573af4c0baf719ef60ccec223c06a340fe21fb678d808f965d1b5a7fb12231ddfd02903a37faf159a34ef11a510ad07e7e885caa547c715db98d8f92d492f9cc1fefdc32f75143076210e986f0cbfa312acb2b77864b72a61c59ab5e1a62aaab5e34b5679f47b87efe53ca000ab52fbe90ff9eca21588e4eee6cfb7cdd998c21c6ea54c9c28d177b27a44466522034ade6157b959490f300eedc3f7e51091ff98a65fe6b84bf02fa2e2706d90232b4caa49062c01015831197608d7edbea2c57f91a836bfbb0a7738acf282bcb37ace928954932074d8908e0fc8ed9de6632cd4ad56fce4399ccef0a631a4bb4c56494588e43cad0eb88d4528de5cc1e0336ecfacb4467ee5a70eee2b6a4846f3460a0cc04fcdc0ddb934edf40552799a5dd22ee7e839241522322444a898c927854a3a168c374382dfbb08ef656b658621788b8d4e1eb16a47ac47c547a9cb20111a384d81e0b935c89378e42de9d195ca2b48f4f7da632e1b692bab94b3a0e7d9cdafde1050f908f263f727a3815c969d6d1e4bff411f1638c5ee01007b98d54069f9f0d43d3cdb2248b01ecaa869c40322211c6d2519d9929c1f9c80f71d99f26a9aad238325bbd929692151ee46e24f00f348f1189231f333fbc9b0ae2846b8a63c6b6df962400dda72681c887794246a1d0e04c4453baa720d9ed4f5e1df8c1741a782f80ba96560caa3f6965ff7764e4e16acf6c12851e9644be66af16a2a5ca5dcddca2f602f7afdba5658129fecec4a5171a0a3a330922d2e96c3edd7442a2264a9088dabcb4bc8126be74172f2b3c682864c664eb235b280f958f236967695e852c4cc9af59318c6692023af89a84513011290788d06fc2a9242c0d3cf32ea9f49a794f6fec1dacaaf91f0e357eb6cc65f05e58885401d0a35aeaebb5f866cf4c9bc757314f7bec63295da4b4abccb72c3e64f86fad2c2286d9b186c73d80c84953febed36c6f5583f0132d941a9fab58287d4bc7fe29a6cf5be69eaa81e486f1078d7811a8757eb6a4ca2389696cf9e30c3bb045892f32c87ae95b30024bc51315f0248f34fd0a57a44e8658492f3f3ce8511f498defcca377009c169cb44dac59ed7583c2d3cf6b86a2395730ad77666d18a382d83e63405da61605cccb14e5c80ef2a2f96f893a13da6e47a556aff9d5ab87941aaaa8be3bdd7aee9bb07fb14faefe8c85b1f84ee66ab16e9ba6c7efe03b573c9e12b8bc0f235f98cfbc4c372e482d26a3506578cb2f0062a02aa3390dc38c195aa06293590afa4e294124224fbd0b4d31dabf649b6fceaf19b3b0d92b972b4f9660a0b8e6fb9d460461e6168e4f2f6c78bcf67a671c770f50b9e93247bec4b190ee70e638cf10f172d8a7e5d56c4b06d1ad18fc94861e5438001cfcb60b994a59701f1ff9e8d0bf9de4a401d7fa422d4dc9bfdd36a0c4c4fb038674510944d54967323eb93e2a534b5f183c6bd586273fa3b05980b6eb4336a3ea3a0ffdfdee600ea588c7d66a564bbf996de762758562a3ce6f790ec5eeabf20191fd5b1ee73ed7ee0d454a68cfbafaa642718b2a1a3c77f085aaee63a105732a50ec4efb454e44bb04b9cc793e30b1003dead1639a85b56264ad40d0535f02aaf14bc8c1de4db1ad16feb018a5d17699069fa2c8e691072f7ca34c3cf379c0ccf119263a9abb863f29ce89c8fbbfe76cd9ccb9f1ad7345f6b00a173476364ca690ab09e69b2aebe1130bdd54504515f0dac7fae4dfba47c2772030e2e636d9be40c8a1172ed111d55c3e029b7e7f0a440922a2f040a4068a6e1d470a6644bb8e8080564fb4c0a6247ea46a15e48a120d5c36e23486128772128699a791bce121a45713a19144ab0051bb0ceaa70811c9e607651bab6b3ef011cc67f74c9b2abfee58a24ba6df6f980d1178eaf0405df75db163d306b2a6f4772f7f5e803a243fc58f49cd0f561fabc94c214ecce76ae4680266336355340f89d5f93e37b9e53ea9f96c2f827d029624a25a58ad65aa255a8204ad455f09c1bf7e11ac5731f479651005adec48fa2095a4b27dacab03e99c39416603092fcae89c0baf23b4a2ba4616a71500dc8503a54f7d559d598cfa70437ddd202f31f04cebe9ce259333124afd6a11bc8d251866b9b6428f9fb2301499a360c0ddb0420e1665c77ee82fbb48ef966d51649d1df559a4ae7ab21372f334f65663b1771705d97832566603c89f81b06448f971f292e761a524ae1b8b931655ea0e74ff5351d53f1117dc2edc4eb344c7afdf3d4a8de9f843b6db2ecdd0d8661e24bb856f87850b8fb08dfbd5d0c0b1e38613acb121730a60fa282cc644cdd89a6fe62bf43c1e5888138663170c3da4d50b89d4b9c3033fb324f09477037b23c8b673a469f5efdf1acd1fc9837245b52bb92c0a34a113bdeebd90c34f14668843e912aa459908e331ed2464b35a711342952f0107f3337473df6ac510fb1b00bc586848a15554c02e32810ae919160d4b4ce622f5b5d3d176afe3fa9fbca210d6a52f5358a2fe8fa1ac14e651c7bf1c5d988b6fa8686915127d4217ed8884f93bb65547168e9e90d8ccd0f27277c2c210f93419e8ac621ac4db9d918552282dc759ee78c0be86fe4594324d14f744aec2ebb8334c50c261bc11711af63a9f36d8e88975be559d0e69894acb0c7d95abe604dd0f1adedd66059595f1258b3433a515566828a061913d696149755da52fbbeea6508cdd764e52ad3d3774c63e38cf190387034112750b33424106ddb202cad7e8cb54042112aad2e9d63f3c85c6a8d004d25e58bd7bb7eb41e56d60f0b880f3e094d60a3e8c33b134309a0be3179e6821c1a19c561133ada2bc74a3dea2e36cc2570df3119fe4dd6c565aa9a4ed2d73ccb9b77e6b6797d3bdc95b0667c1bbd1ade4927db884f20e05b25832ff037c2553b9f69da766e35909e48e4bb6959451d5b9221e20e12a2990afa529d26ac7f05b460d57c12c61a53b712f72f00c612bf95980d9c35a697e25c2ea2722dcc188e041a7413235e35125051e41a027e219c9b9deafbda94866ab291f2f8bc9d18caf500d087448301deda4a3078b4ea23bbd28ae4d2fa2aec9d64c139de7173002a6970e83f42498f52254b74055944b0b0d3b64f9e6a7d29b6fbdf1b70075021dd25fa2d3aff23d39894e89c95541d7667a001a244c1969a97141441960ebf9198ea9c5f2f723bbf21d5dfb606c7e18f7d7e04c5192329c43857d5ff5cb87b97c59472b7cf381ea13d06645e7aaca6b4b6e56b178df8a67fac0114535ac9d79f42ce4a4469097fe956745af2257511865418db9121382b070811ce37023706fe10b439352d0b5b8ac4251c8b23a87a13bafaca4c95bcbbb1931e518a80c7638c8e85c517dd18bcc5a019f3ab68faa03f6be324a56c1c9d62e1c4243498c1ac2ae81c917ea5c0f58605f9f8a541f501b9f6e8acf84342d8e293627ef8d58e1402a50d71a7592f10dba73740d9f616af5b3e38bbf46dd966f842b47d53b4eb8658dd27bc5ef8eb9e4ed2bb070d300ceb4b449cfc8e6071c5f1b79641276b653588bdd3af4add8b148116a04277c2d0fe6f2e2997529adb780711030d5d50db3feb83cd6052ad16edaf3c7a7d72b0a3793d0e82f176800def0fcd6b2011483ebaba8ed2294a30c4bdecf03c07d1f377ce4b58f37c60fd0c9f1bb68992fa70faf9ad9898095e3f4a0bbace604e1ed510423bbc61b2d1b9abb126cfff89b887d012aaa4a62d4269e4eb6f19ae6f487f29eb0c23b6cafd9312b09fcd70e14205f81c279cc765a513b5258846a3be5c9523ffe4ede858c143a0db805aaccc85d975b35798b0ade787d3c0c906486ec5b4558b34d9d211ab9e33b74846251103b854e3d9d42370a7863aba077382e4cb7709ce2976f9b9f1b2e76c1554b0b87940990ecb51932c87b1d88bdc11cfa2f8560963c72154a06529b5f1ad16d2b452c5aae34024db9bb27cd27814430ed764192f9a056948bfc22519425835b480cd4b3cabad1782dad6cdaa40b7ca8a3163b4a1aaf2dbae6badc61c58bf445ef47b218b025264a4a5ff2fa8f449fcd9a4cc7f07debf7de3064cb5cce0b12e2318d50cbda16376ab94a8b93c6bf242558d262f3011761e12669c543b025699377eaf2bade680f2ebb9c1a0508dcbd1c254938b11b980c71c610d92a098c149aa43a6141c44a0a8332719fb23d7afc4978840b05b2e8db0714b92d53d8a8d4c854c30d39a5c4e11f72c69bb749c99f2b41d289d5919dfd108934e37987794a84e2fafafc8b7740ae771cdbed52a207db1c13874060d2e1b2572f7418c83581ffc7730e48400c7ea8d41f1e98ec2700feb471bff116346b3cc4caadb8425e5965d581c6ee86e49d67a81573a37760d19a7f07e30943e0a7f19b6c5d651a12c6818b77e8404c9cc0b8b8447b17e0a535f13b9bf2a97264599d7343121371feb6b57364f1170300a2df919a8b2d8b9e17820b3b19373f9b5b61ee19e5203b64b0cb6cc86f9a861201a4f613510835ea15b1c6a3c49ce1db1de5d27923fb9e8c594186db008de34befaabed880c7d760ad0cefa2962fc30a69c96fdff858ccf1c714241ff728c93aa2f088368163d47b06f4c425966b166a0a2342982eb67e27d623c65419dc8e76b5050eb770e782d4fa33151c622b371071a2289e11b08133fab2d6a6b6cea8b23f89832af8fea866319794816af1963e1221f698dbc78066a991ad68c0e44aff8a41f14bd75eca4f63d876c7bb227a15cb34a812237a04b6f8b51ed6a4509bf907f150f32afac028e83d2280e3d46a4bc1c7c98f275a58970ae08f01710e683ef1837377ede3245a661e2f0b08c5054b57a36492acdd2281a0ffa8f411ea7915286685be37bb3549863185f9189fa5035f4264970cb18f7e7bf0acaea32fc757c2e5919d525e1991997f6e9c361d4e344e9058edc640267b22eb6604f395d098b49e46e4296c45eb921cfe39249cfe20a867d302d82c4451d9240be9f8b6857a62a0487d4128a5db31f6b05ee7d994331ca923f68b1a08c17da59d8107eae9551bea61eaeb13f121af4aebdf015e09ac46ee36b0a5e93641582c057d0f90b4dc439b99d94ea8667692130f6c544d0cd5ed388707a7a410f2af8c6dc11dd7ddb6751f833812080e9accc0c4893a9518013ab2f25992faf467eafd1c66cfc654488aaababe94ed6dba3bcd0753a242cbdc2bc0b2c366f4ec00a07874a8d344c93f22d85b358851d1ac8c62ed30a154689dd5ce25241e3d8e45d98e67f3c1afb9d0e8ef8cda44f19d91b38c06fd9aa430cbab24972554ce1cc6f42f03a71d2fc1ab1bb48e1390bf3c2c5a6c7c7c6d9344b91380fbb9627b29b4c5c0a2646bf4fb9ddea4ddd746e9fce20fe1f61b39139a6c93a8aa1fa2c3a4486e820ff1b185c2796c2910c0daa091ae816db6f02ae12f829e693343f8c6fa8754cb88e8c5db37dbe5be8a05875afde147695c9557d5228a5a26524055398531946d94336eec05391cef1dcd9e0d25280fdc3a6b311defda3ceca67e5e6bacb027e6b3c449915b39d1fbfd48dc9f71b157d620936010a92631b6fea4aa891497b4f2794c1e01ba4a030f8c05cedfee1e392a507a23df5a2a5da0d1334c8fc59e0672566160309a191c0569f1eac485feb3c88be53c454b9d70161196da33e5152cb0c498a90c1a0de1ee0d0907bb59bc5e4e238ca6b951e2d85fe9e8b659a9007ea38114043c22cd266baccfab959540f6f3cf1f1dca41714b225305cac9a36ab036f9317ae2243f1540c499fb1a7426f460922a38814bd98350c48cdbb9a980fed1a210503e707b6f8e91237de99979eb917343d6e86497105695d2b1818a5fa4cc2c050746017900d413b0a8f6066eb3503ee617ed8c22e156339255cf4682f382db89c214320f06ff6461a4888ff8778c2b1fc3358507884d835091c16be8362723e34ae132719059a82306080404fbdc5885e410d574b44e9ad0f09691ebd416e5a100b2576523717ebccde4027326f8a61cad7315698f8f29cc92ded25fb7adab4693fd3a92655b8afbabada203d508433ec14953451b200948b5af90cca6a5b4c67c9cd15f11bb4374545a2f6cc0d7106bd48b249d7c8bc5442781eb7dcb0a3af49ba92d55dbe67f627bd9567b7ceaab6ce8ec9d7c15821462454f61d1923dbd9a22c6a42302372e7da567a521d024cc9341e986314992ce8c77dbec7e26127fb88c1a252497dedc381dbd0370c606da9477350a57cc6593e553434d144731792ca85fc6f3847d69398a5c863dc6277e5dd0e3d806c42937eab831b6d52161a50d8c6cc28757eb130d8183c5ac82abd7b0d6a2f2e4d4aaa6b764b9ff3aefb756546cdd7bd36917b3151c537ffea4362b364a4aa51f5b8b979d535244392071ebf0436edafeda4d83d2da78dc66917627be390b055ebada94b4b3230ea86f8c1336a2b1942a725fe329809d99fc082eb9a3d52c76b069d1bb00d69d3b5db92c719992a1e19da15a50c4951125cad77a35ed82111102d3c8219b6bd25c3c7f34a687fc28db9db134b6494541122227c5378db0ff9bcda20876a2b42299eadb419b23913cc03ec634662e903f7eef181833f254e0a4169cfd315364b4eb0f4c0c20df3e024ac1b05577913fb59a4954ce599dae58f43e6869c12f89ffdc2548cca0e33ebbcb955933067000922e957a008a2711d7d26c0bf629636410a088152a6cef1320e43f55fc98b61080dab58540062bfc66046aeeae4397b8f02cb2d84bd2d56328398cc2e7c8099e77f426ceff975c2163089077e477b618690ca7802fb51474474c4cb839ea60f7a260b7bc991223afb9180195617c28c8fd40ff5eb8cc2671da47e22b61934d1e3b140a82d92bb0019b86612339d9acab061d56f534975a6d7634b276b16975706bae27f9cd6076a7a09d4fe5251d169cd65e6fdaccab1fd20e8a93837cf57a7c4416937d04a185c0795473b0c96fd88a353be1cf29f6ba32a9e4638b09db19a2e68299ab482f0cde05453b30724b5c40c11af5b59386ffad499d29ab7082f684cdfaa6cc5886120cc18f0ae325d0bd81d787373f5fa3ddd60369292bb25b03df03fff58882e960e3e268d049ebf3cb296fdf16042be79a56424f9f570320512bb72e3ccf8613b3861f30d5a0e3a2ebb4a08b36f37024f342c7ed4badae2e063c38193e18eba7f26b0af73ca393aee46bfb08de37373cdb2eead92284b904d72aa50515bcc2b47eeda30f04375767782ad5921e771f54d9a77922f767ca549e3f0e8d3862241ed0153473ba94c59168990599777b8f1fb8012171131ba3aa77aa7f074e7c308104394874c54801fd5274f2136ea4cd9130a68702ec43710da214753fdff7d6c14f8fdb17f5001e81d7c08d741579f093123c3370d87c6b534c7c2f725ae159380a80f4663867c2ebd0849f3a06cd9160aed228120b4c3e75e6ff07b89375bbcd6bca5d89bd0872337c5a1062f7332afbc388d5dfb32a8a2f4810324346179b3bfd3691c9b56bb1cb26ba530456c9f3ca892189c4d42eab61c80fbb4decf5008bf574e7de674fa5cef6bf696c3e9ecda2846839b2485b27ddc58a1601ad94e313c272e1f873aa6b9d9a7096ac58b99f4db12cde69a92597584e0195264422674391cf3bfd009ebc466610925ce897e254e233fbd8c316f75b4bd34df45d3c84898857c74a3b079a1bf2db64c435a98e2621265e90865f57865f35ae87292a033ee0658c43e490020efcde1ef711d645c59cf944b629c47d44bcd03bde8e837afa1e40f3d2ca28d92440fe7f4efec2948f143e31dc40974889986a87c26e81486dad2d310b4c706ce4a25d701a93899c6bc217a9f1336608485ddd9a0cbe3d4fae30c5c3b95d673cfdaea07a12dfdbadd893bef9d788eed5fdfd91271af267939dcc4195b6cd0c9ae67ccd4a0df4961dfb765472a3f52b02a97276633902990d22741b4dd48bfbf7fde272b61143d4ed1d9bc2bd6304ec88fea4532f4c3245f1e9161a2700828c0cb8697ae65bf8d89663d2668e49e6e5b4598804a2964b6d9ab2a6a50bf3f8d7d01503218c22b950859b65415bdc94ce3b9cfdee87a9241c6f7285489ec7bd8d8b378ea25dc75db5dcbaffecce2a6f7cb2c945d9a4b26c4a4ecc6674789a9d67ebfb23a0e9a9e2ca5a25ff1e814fea26968ca46a67f91fdbc38c31124edc0cde1506faa4c0deba542eeb6b6e795faf4b6e86b3d54da127be3049153e8f3537637a2b7b318bf62ede46c0427661b66abb84b39cc32e64f762301e8ac592ef36bac96d7c509b50f8ce69d798f3bcf90821ba0ee3418f96609b624c71ae460563e9009ac5dadbd2f6c5b3d0f17ddec161bc51d1c7afc0132e9b68ff3e05b819cc96eda1fdb792959340a14941dc9cbffa74c2ee4678183e082df67122b04bce625c4401599c435345942e1052c619683783656aaf65b5287d0ed6c86814a4219db492502f89b05d071505ec53a83c75e47fb6149322f653622eadb376dd79ed1524c51c9c17f92533b6db0a99f252da56c3c0bc21b699db1a4124e8c50f549eba0c4c0f97b9b039ba532e356081bf6bd0f70b771f9c79a5144d6af7f70c4efaa60dcd9ffa89be605aaaca702f13d1cd5f858246b40f9a5c59c8d8f35e7e13ebe302de6d3278bd912c13b6dda42990c8e699ad7f659332a62551643571bf741b37d8e8f5b329eca71efea4248eb024d3d97cc52eb738e65c50b488a0b9ea4af0ceb9959ab3d2a2f9a29509873c546d74655f93b25c2e8dc63a1593b1252709b6e0a131fc7c254e0f99995872d1c31b0a83f882f783a1e00867ddcc11ca1ac30136b5a796826988316b3fb45b3ba28e34e5105c089845079309e094700dcf849b115649da0e60c5b0f395b0454314d54b6efb6cf4566120cfd791316cbb846e839218a850afdef466599d777e6ea80d6b8cd78912e47a2c4c3c581808af7d3d76b61a3d89ad9c3f93b9b3a615b4ea3c114d52a52ea6795ced145191328283979d6fa614a70d052e2eaeb03c045850bf78239aa118ebd592705e951bb00ed87c70decd44cc03930651960306f6fb0f649f038171ec4487e044a554bea14473249320e3e3128105ce560cf94bffb0b5f8e8aa8c366b24507f0783d690e60742cde0808735df28c1259e6db0353b92847f777435a44bcee4e5601499896b2216aa903745ba590258dcdd6768948d768429493754dfbad1e0868b9505f1b880a7263ecd5827b55093343472ea935f89fcaef8d8791c4abde7fa1248c845cb4f1689d298a583a568e08d75c92a1260be803180332d6ae529a529fbf650c9c79573ec48231cf89b87ceace64e5308d26733076ea1b2b1711f71a7ff8f5662fa5992d06a26de29022153e216bdf70fee8e943ed3d04b24e24086a13d9861bdc99dfc3f30140584bea798f76dd09b99f88178d500edbdd048332eaa8b682a68c30e5a1a5f7093af6dc20e2848d494097fa1545fcbb047eab9f5b88e3cbf86de390f47db23d727b890e358ce249dba81eb9bce387d27e22fe68d59c31c23adb98c996b17204ae7e61e6e39895a407ce9509eb64988c51de1dba6f5ff1c41ef5b2f4c3830a6110922a4d85085688d2492137b5e426c170bdf6ebaf775017f5f1ed3d0c6fbdf7ba1868b85c08012a573866aebc9721107e30cd8903c61658e6574db4cbc7cd2d187c1cc778e4693e2535521d7d48a1a5a3f8b654d27a3b6c706e081a3f7a2ea292fa7afd5f8295292eca5d91f1df692245597b2c864c327dc809fb717ca9092246bcd094d2eb4b4d18024f29488c25fa00a1bb7c79c756a53f8b3e511af1ec51f0460a3f9f79854dc5d302ed6c1b5e1e85c25ff9110c087bc1e9461071a13e4f9cac5e4ad01ab08edc0ee963022d37dd8acf8a3a4076675579fb87d8d80ace0ac73dcd5b04ef206eeb647101f15709adf0c5e4ed6ac39ef489382dc50910e7376470f2f73d7cb33f880fc2faeb730d6b215af73be5bd727b5cef78f3a184812327e27e447bbcc9db5871646f5096f02761accf32a68abb5c5b5f952a43626ed345b7d059846dd90aa1de2ca1b249cd01e2aa2aefe2388bfd632d47858058950eb9876e4151313ba62956f6a61f846b6f4b7e3cba1f61fb492cc519607d72537f362b53a3530933d36c6c1248b1dfe9c759c01075330a80c0cee24e0427cdbdf2d0f9137d2c28c3421c9fe396c15d7c83137e81cf63a487acbb1223f4348c28b860bddf185b7c3f1794f52c807e5bb91c93325176c13c596df8a806bbf7ea5488d3d4aefbceafece0c363dca0d40087c465aa0f693729ddf685a9b467052f47b57a38a368e3d5e038b6bcab2b0a68289a5347cc4c1b058bedf9179bda137024fdcadd11cc8fe606c1bb71569577e90acd1b249a28306e1e752888092a04a5bbd808ca72565f5da57ff94c061bb3a4d6549f532142f990d8a010b99e11b8fda01ad8892efcde4e549cf70a4571260499747a3405d7152e2764d4c60f4f017825b478d02079c55c3a0673329412dcc8c34f6d6d3bce9d06a95f1930c73ed39dc7a7e47d11b090208194712103d78e5aa56f4f3965c12f3eccd7deb06e6ef83a588d2a7ec2e5bdd70f002d70c93700dd835cb01562e7d6abb3162398345a17081ea6bf3e17bef103158e28b8e9236daba441e22255544b95f6c7999c029520cf9ea6edff56ecc83688e1eb57b7b82aa6775d3e8075039be72e9bb7b3b648c790c9862197dc349d9a89d405a4c9e8f9623a76164c61116b0e9628b94c9e186d4b8a9add3d599ec5c31cd7f594fa26e5a67865a2b469dd8966832744f0b51e857f5283925aa3dfd19cd271948b45ce7d109193593339aa3cd278684918bf8fd65b4afc7d55d2a6b8d5d24fee7cd75f8df7ee7464e9df2a8e3003f161124b566eb32cf3f49e4f22ffe1bb7b96147d163b691ad92ac46173931cf377f8f9efcc2c3ea02108bf1fcc76b6266722e5ff7f14c4a00df3719aca5c7f35c15a71d5fa342f3c8bbdf745680d22ae68b976b4461d858a135d4c62552ade874993d967661b4d8f51a70e149fc20d3c69cee3a7346600b85a82fd8061c4d7936137e9a47a05d2f12c1ccb7451d0176c2cb4de135a6d8eef2fb06cdb22c9ee75d31da50338c7353762b420714fa5c2aa2d4883c0b2d08fdf07cc7a9af17747440465bf156520f6e09ce8ab23e30bc595144f37c8526518666c4a4131a18eb21d7f0ca1b2bc75a1f5aa139c5d444f46e2f8df03a6d4b38bbb54180424059c09c2cb429c7263fe7460027687ef0b3fe41d0e5bcd19f24eb636b4ab8fbe7eb223e239f06fc990484f63d4e9304b6a2f017657eaf24c94ad67d461ec1ced3bbc130f00c1c3682552850f27a4fedc016f3d87a95e75aa8e5456036db2a4206f2cde7af62bc3cbd1c62c4eadfc0da8949e50e5cde7ea62ba8a8263616476e5b27441b294a54090c08f394216720a75de59fd29262ba053256c8f1792f7320c4727c928bcaf935c606608aebe7ebaedaac2175725e51d281a1d660f29b55c0507d5e889d89624706242ef6b1be66d98e61ccc1d6f27cd1765b65c807ed8850433871c5c2c9e18be78f5a82f728139b3781b4604c6de01af5884c2256815fe9958e355ffb70fca1be02c95e2b459aa14d471476e399b9e7ccfdadc4f040b219cf14c7253323098b3b8db38c8e3d40c4bb1b80e8b3d64fea22d2cdc0dfb4238145895945b5f78c9d6e38766043f37d04493986a58210ff3eaefae807244a10d23f0429e82f883e3f42fa34156ddb40f239a6996a6f9033bb68129444a5d622e05d79b2761a11181c5d05da813ff2295c6bd510fb9742f530f2a1ab6a4169c4733b04080194224762d9ae3d4a352c8a369aaa79800acc6acee7c5d6f9c960ab0824f6a8973427928132a0bae6c612b2f3589aab16cbee2e2cd5cd1d612de59ba281a15f11383b506dc50c7e272215349d7b746fd6553ab07e4b6c6b5a4d5e0cc4722e90f9a319ded7bc9e3d740b699c3aaf13478e43dd081c5ed47681fa208ee97bf236be4a0790c67f4b72c88eec604045964741322116c0508436356293d7a557f4a99e8d772982a6f8ed0ce1dc3952889fa82691d371c4c6822812b6d3228dd33f18d794b9afd1c2e4e6acd8b6eb199e2de2ce8c8d8c7cfe985078aed16517ef12dc395f0287484724a50faea3a7f4d871fa4e299fbe724bdf5314a6149fc7f555d5689536a977453ec7842c82de8ce7f2b78d3ef9513ff55b50c65cce2f3f63ed4a937c24b88d52b18e744eecaabb611dad36ea883ffc0150dfb950080371f1e51ab683e188f11d499578b9c0a899f92b678a78ba8f0d571d0a3fe19c99709ae0dd4045ceb6f972fecbab4f9941febbd4b15aff29489fe91d2b0db30dd346e0f0727abdf210644c4c949b16187130ed3867d23601cf8b4eaa2a05c08b893be3e4c4ec583c9916740bb9b2fc99a293d477f2540b488003c53474d5981a8af6eae08327d9d0dfaf212a37a1592281bf2794ba4b69232442ca0770fdb1dc6e93f706d026c3b43fd976aa235ff1705b92dbf6df484cd541fcaeb6815ea2df5405b40a559041f31c387495a6cd54ef5871858afdea7a81f329a2a528c88687ba40b1ca3de39a445bc91eac690b06ebd5efcebf31c2519ced40df28efa291646814495254a0079ab656c82bc7a05fdc0dd72612671bb40f0b818b5bfc2874f9f278c6c555da1c62dd09b660f93c589915bc1eed0e238e800202e4aaf0802d9567e3398508956bb8de09418585bbd14f3b76ece5cd85f325ff8b36797b46671a105e5b81053392bd4bddf282ef09184a9647f71953ddeb1a4a638d57883e58dce6edc62dafb0d7d923e97dce51b81acd30b48c3814b2ec3cc3e1a43c29ba2e3eb92645dde22a2ffa6bd7407b36ba0d523d8b4a9bd75e25688de3b016011704b46e1deba98a5720c9a22c947313eada43f2dd73a80119f1cf621fb1ded41ef89e5ed64630ac86ac10007e0b23a121445b666194c0a2681192ab97fbd6dc943b78e19aa6e0006b74104a251a8a90341f8b9cc9b91eb4f656c0092d1160f7c7c23fcbc8d3045ee79cb95a18347a66579d9030ccf0b553b237bc1955b2a8f1bae320dbb8d7e3f2f6be12e282937a78b7340060a5d1d544744b2260612221b83c8d5be6ad1ead1079de949d02209abbab4182cd9cbae6a3e570599a78babad662d5964091c52429c39d1f2100f352003d7907179d57798b9f997c66b12c106c3877c5c5592fe24b896f379fe8bd00f314cf62fe7c21adc1a5df867ae3e11045dac60f99b7f28fdd330501f61a2f5c734f0e1af49eddd39032f4f56b4b1a62625566b0152456723d001c53646f49b5e4c98702e35e90e3a2fe6aa348c11ece3e0310e4d68a30ddac5237b13c91e37119297ecace329395063f859ae1463a07de15e85b30bb330c98569102b6db3afe991cd8a72c6da839529d3828e942d7445d079589d4403fcb3beb1831e15fb2163a9bdde62126633beb7e087f8fefa69043b64045680ac64cf55952f565ee41ddf0d87fa4f0fdc7f68712ac382b0a51125c37c0d2f7f86621879eeed0e63f0adce3433538d5902d36084a3c0ac048696a47f009ba9044c488e9d952fa1e86db9212066428e25bcd8b760c09bfda529a4984bbf66bc6a5a6770c07befca249231d2e7f69233ee6a4e5778c438d55e91496b3858ae72f1f8c2d4601e342b22d29ec775496f2ea955d88ac0f4825ae2fcc936c72d097a8c85545209e39a9a094e612e1bd505937237e4c3a2a863b377a1e9082ed3c0f7a0357f28f44db626067cb4a4827c4c34a242a78e5ec1eb60371f10246605456d99aec16acf75ca374728691d8fcc874e042273b3d53f6ee3003843efecb9a6f01e524042d7e4f25839c8ef3fcc3f3cb21fb2de22df010734f613fbf463a62d79fe6d107d077426203313f1f12a072bee71a9184747316903631c6f7f299c80eac75caaaf0da2875e4076d5983b62b197d4dfe7ebea0116fd2f144fa08299610e0352bc0c3ed78a20ec021faa4a0549420f56246202bcf341a42ddadc00c1a286750301146c0b5f7e708aec91ec402106eeb205d3cf114fdab314ccdfbd9c6560c8cfe6b4374f637fe68c33bb183c2d3593866ed6c29bdbdad8cc409bb194f6843e6e35caae360e2a80073f8d8f881b2a7c316e8f39f6db93bda6aae3a41a2e34c4692b6334ed40130803894b82a685f18ccb90e1fd5f7ccbf4d6209103bff8a1067fabc442352428717b16ae7a8c28bef54dd787b3ba60c8eda01883f5351d681f60fbb50c029562347b7e3aeb8113c6fcbf560c2e419c022c30fa49714351c37a0712ac8204dae60349934346efcccd831712f9384b2022bdb5dc7a8df559f7d15aa783578b6e9bccb4be41a231a84303e3a6dcea1b4b19f0abcdaaa43f01e64d5c9f00cd90bf486880a175eaa6c8022bad765bd2a5cdd7ec5ac678a68f7a3823d1aee529202456edd399d1f8a7aee96c4a49e1a0d50a781a9a3c2dad4cde8ffd6581ef79a18e7f651e42e3817d2b171fb53b8e949b85af34ea85522f1bd1bb640712d928ebc26861bd9dc8daaba0b3fb106ba0f7a8a31893ae7792579b4cb30bbba6e1dcbeb19ce06da08db1f13239de11bc14786d1800e58a87f1cee28330b745995d163783cf5c661c631d1b62faa5d7987577adaa93430b58565a04f3c0fc6956d256a3a3223b11ef5d4485eb1f00e5d8a86b096d87d17bec505d99a5ab92180b2ad76bf5be8942fea82b625f72727f7aca6a0531b95396279b91e99fa53c1bc478a87fe3769ab558c5bd40baca8da13f538f07a07172545f861f4f0969785188db3c629a2ea58c27b78109eababac31e20e55d8c0ad887b695b0a19ec0e7f17c4ef7ddca7aaa09c82374a1396ccadccc75f124e379b1029876e29890576b20a10bccf4e56ccb0762befe35673a3c062cd82b4eee3d882bb76f54ba27f728c451b64e62c0385e7311c5d6d0dbdea74f0a0662e08b89cb648cd2230d1a7f6c1c2b30c801343d8280e95bd992b00d302f5c99a9b2db1dcc899cb3f28aefec201b416acf7afa397246cdb0a0c2130b94f36320264c75e03099d5ace837e96992c6d338f270aa98e2504762ceea9d2b64e7abb1fdcc93f284bc997db4d5c2f1656e717853e7ae383741d8cb9280fc71a10f898c3779c3e3fcb631bf9dd4c3a22bf974a8ac177ac678e5dfafa6cccf9a027a999b6a3c50025e31274831ad3fcb04b0755c3c71a950d33b6a84857a3bae540ed14623ecc50914c0f17bfe6c0ac555224ad1a945fd6cc94786e35b2424c322a4bc8c1bd2475d881ae982d6bfe3237b91ef2c478fe9e57b21bec347d3e3b304dcc77309d4be104493d4e4a4100bce1e2a02ef45c5953b3c9c55b88137913d1ea2249627a33e6ad171cd56e4df72475c4bc614ceda39ad241e397be51114f740153439ec3e56171d0717e0c62c6b5f65687c236bec48cdd09bd0a286aa57289fef2438f2626ba431e21e0d2d361de8d398a330d4a686342019d48cd9c9b0eefae4308f36f0b0cb7027aacd5565b3056d2380779eec5907c1818a100aca65161108ddaf14a3a4e933049304d51af8b7743b1f20a91eef72d5f74c67bac04c171267d2ddaaf85205c38be3539585cb9cd2f08cb073f043d766222a00e556b95efa5252bb79452ca940265053b054a051a88337999a13a7dc3108b70132d3fb9688a8c644f28f6d4214d16712b36433a6691450ca32f9f8a41a43c38ed691270dad33c70da7bcd10073fbdc64d40e1b8e5694e9380c3e93432f536ca0e1cfd691e3ccd69da7acd1951d7987a218d2ce216279b2b4068407cacdf514b2db516040204b6c7f6bf1c318806e2f5edb491f81edde846b70d084dbffe7f7006a922de317b3e27db53cf91e328daa22f0efcf102107480042c85fab4a745eaa22ead4d61b8855245c6f8c8d87a34ca68b95228477560148f6bad1cc65c4c86e74916738b4e5373866558866558ce5aaefe1fadd65a2235a6be48f48f33ebbfc7ff31990d6a9db4e28ac39b6c6fb60d639cf2846c9bbb97f9deba6ddbb6959973838bcc32e223bbbcf6ca111d394497b98f4ffd98a169a3c2068a57b56ddb4629f5ba9999e37558260ec36b9b22ecd7e2ca9e331f5de7c53e95f78412d65aac59ac19c11ad6b0b8f7061d7d9ba72613a554bbf4b54b29a594524a29d52693b529965bab0877fc432399eaff7f4a45ffae19b9113b295527e5c9ece42625c488abb52ac2e2617c32002e6e795557e5273f2955a10ae67c52da185fe60a159d9427e58d984bfbbc8edbb0f6791db7612ab23b8e24ba5a6b2591c2506b91a8d62397441289364fbd714676aaf24fac30bad789219f265eca2c57f1d36b2668f6d448a8569db192b57e663573e53f364358ab9410fa2fa29a8e26ea47bf475ed290b8cad4538c3f3acdd1dce887a73fce913d5b339c1d9b4e796de7dfda1f55507c8e1b756a66383b35b643d3c9b10c93337641e6b03831d89efa65bbc0ca8f84fce00b4758454043f604a9b448192015869bd3628e1c9d26f935d5dc28d3111959e4bcf6d4a39a5cc13a57c46f96b348a475b84116e9438a99652486ed5d6031b333eb53d3c22206dcde0516af2cc8046cef220b969d59b4f43982963e35d8267f6e4420211ed9875ce59111320b5258b4b060bdddce45cc11bbcbacd60cefb39046d63350938901358c24097e4a083c0e2f493ee48b91fd216929dff933bbc071cc9d91c822a753d25256519554cd5cb91c52cc1c3f3dc1e9aca22550297e48d59e427c66eda93f1c92aaccff90a0162d795c2e0ee971713e1c727f62f6fc8c1fd2f52197c81e182d811f0f6c4fddc515375d5c612386cc67662a3172648b1fb27c01cd5c71254bb8ec8fcdfed4ec596464d93c6ee4a8b93f96eff5d57ce5d7fa663e72b70046163fe47fc8cffecccc157a673e369766d3bcadd55c7bea1680a0b1f6e4bc484ecb0c392e1e97c7f5b9581e339c31241071814f0f1c724fcd79d007db2302283fcc70ea0f2946135bfc9420a041943b464b1fcbe48cb4f4d54c95a95b62db66dc53735eb4f4b5e88c963e17e7f5cd60b195ec9b7d64ebe3142108e40fd287cfe8473faabb4929a54f5f1aec437ec857ca8867019250ba028c23aad7faf53d0cdddddd6ba5ee37aac8625869185eab821622b3eab57e7def6047b2885fbb0b958e66701c0b7095a961b0102971614f4d4da1c9052532d5d5da2b5bbddc41b01728c9f8224343c6626a6e599665f9f7de7bef3883c9baf54a1f663831583bfc3221a9ba7d2c9016a11a2442a62e7a6445554266087e91459ac22f303129afd2db13f4a22ab3445fafd764ed57895972cbce25123fd597498607e100899f64701c538bb4d81964051526c731f50b63fa32c93a2de68a98a305e45202e16089154ba85082f1b6d51245b2955ec395a057e7bf028f633bd753964049402d67f8099403335c070849cb0c5ff44524635d47e4dcd80721ec16c28e402d180411a0080b6a79815e16bfac0ba8658626930c7e0221397d098403d0cb047a99402f13e8b52d087a31c9227dd116500bc865833e243208049a01e88524e5f5f25375d012072901e5ef867b2f06bd402f4e867ca10558ce398a4f29a5f6f1638cb1c74cae6666bbcc9e4206490c147bea7ffd5e5985a8efb4566befd534bc8d4452e7353c1f89a21a58bf8e4d745dbaaeeb30de368eeb3acffb3e9a3b23238bed0bf323f1c66cb8301967ed665b339def94b65a7ef29b3939422667c8e414d9537f35737e367beacf8a2f79e5c7d2628b5f4b234104c62e83506ab1a7fe9af0920733ebd7f2d316e3d5289999420689077b02d51a899d828f880b4bc3f3ca0b9ba157def29b5feb6b519ae38c7c5df6eba903e031a25271f0c675dec7019f440a439128fb10b2e823adaf7a17a6a1d9d8dd0ba7b556ac52398ec964be2466b9668f8eade299e067a75ff33f8ec972b9a4069aa6b9bbe6afa5e8d77cacc14f754360d2c0699aa669f4ab7a0cfdbf7efd7adbb62e4643553cdbcb0a183c70c2beb56efdffadb5d65a6bffc5691adafcdfb2a31aa2bf3fadb59ac6c96438315fa34547d9088389c5d4cc15a7249da1377beafaee5e966559063183c05854ead04b92e88534b226d261b48890a81f409c49122a54a781789ab8a0a278111d473f9de8cb5ca97aac4bc8221dbdf43163f0f4a7354dbb24bc777854a7a96bae3c286a4e7fa33c72aabbea91e828a263572bdd72b0faea1bb84dd3176b3bc2fa699d49c14b76c9588ee5588ee55896231d9fbad096d80e3ad2f1de2e26abd1027db1c2e8791e9e792251ce9e96ba11bd91f636cea6c22489243516914861a8f58b65864766385945667833439cdaa5cdc643b08a24fde45ce0265e1239e9a727b54ae4028a165338202635970a1741b1da511cd55c71f1d363167c646323b8050fd9538b78e5a2253c52951b572812e52ce492b31c67644f6bfaea6d24de1bfad9702110647bbfb59196b2a4a7454c7a9ee77977c438671762a5debcb79eb55bd9822276f3a83712ed3bd284e410de807736c3a922a2a944dbddbffb2bc7f1f7fefd91786b465736c3a92f79afa7f18c9658689145ca1a9b6d086b4b6d4236237beaeb6dd57a9ee779f7de52d52b149398fcbe185b335566372b8c2e348131c698a34698000d14a080d080031f2c81f2baae037ffccb0505a4860dca037358fbdc28870901241c002264fab1d9e6944a29e5386e75466c1cb5ab6d625405f64d64987838f52cc7c850b85c238bebc5525de3cbf53243d80ce7e86242c6781c43d8057f74bda816dff56fffdfde1fc7ffdbd99076ddc2431c7e0b87759fa267a8886cad25020eaef25b3ccc3b9de44918580c061683cd994913a65c7ca41e06854c3ef9240e3b60b0184c1886a1adf7de1be394f1d6be497bc959b0b4c613d9c978023b8139899dc4d49c9027332737e3388e528ca39f3c0b8c731689b4beaaabbae3c9a83a194729c65591718b4ec693f1466babf58e1cd5cd397f743d40017112759d2863c68202e295b104ea8251bc76cd92454c29a5ff943efe4f62679a87891bb3d6da0f634f6b1caec0dd5dc39db7715e3792c6d0ea1a8b91611a26b23b8ecae2f26a1d49b243b4227a41954f6aadb5d21d33b4a51f42b4ab27127d2b8b98b0e3a6f2a7aaee81c70d3b6a0553b474e7a7489f721cff2a7afa12ece03a7e0887616a7c83d0c167b6ad3ba8d9818d9228d060d75137bd8abd25b2e8b11d287657d06ad50c49249216f3e430aad7fa43623b16f0c38e1dfc6439adff154d694e73465e6badd54f56019be4e1d49f005fc171b040800c4e50a499c84e553e30b6e3631c08927625ed06dcfb3ff7dd71af0ecbd9cb9b1c93566bce17bec86fadfd9525238b44ad2b32a986886650ddddebffcf696d0d3dca94d24ebf005e5db0a0c8bfbf787dd5a6ffff5aa7b624402358b002c618638c31c618e377f7711c473ad29196c2700c473ad2d182323051c0503f808c60258a0b7e51d3eb6097875d1b76d1d295c95c57e692c9b82bdb4621c07bb3aff98113bb5c1cd799a117c3f9262806ee4e6f8a50590f947e9b524a2945e1228f9a527aad2d5bb8e55e93c9f42693d6a2feae78974fc09efa79e02b3ef015daf93ee6bfc59edac5a7a2a38d6050fc97873188316e61930f2f9d0c4e6bd1c1f0303aa3939f3ad072a011ec688bac812823ba5b59fc978d9648a4699a0d283b78baa379f07407e4e172b4e6e97befbd9ac67932dcdd037bb924195f6468c83db527e6f1682feb6432ade7d64c720064f2d5280e78aded4e466fea6f4a36bf93690f76f30ad1b4a847daee3a994ca652ddeddf25e24b9e9f86f0d3a659e86e8abba9cdc471a454b4e4811d18df85549d6c453b59a893859cd85377b24e766d5cd10baa1cdaa2ee3cafadb970fabb581733c369928086e2c0ab52832c76b2ebe9c2edf1bc1ec7845e1d1fb87b859909c306842d08ad9eaffdff058212597499761a31acb5d6432c3f4d6abb970df2a73bdad31c7dbbadc3197d2a9cb5568b2a9653d9366b3537a278db364e4b7957f7ba562c23b3e5f77db5baa115e075d8445526e09d8947bea98a385ff5de7be76b3459d3e53866cb2e4d17aa329178484db434278b024826d18d4d0913dbe38b6cb592d1c9f2d3dd534f5cd219a31346e73857ab0d4ef0894c4b288e5ae53c8bf015dac46ab69a5d90b656abfba3f5375e5db06074afd0398eb3655ed99dc15cb14e14b1c51f42edad9fa669ddf5b4bb6ddbc68d1cc56d73b5c25886fc94789eac205563dcc86d9b913435b4a436754865d55415528deca9374fa552a9542a15629cc29fc29faab672dbeaeb6ddb46494a929892b8db0f761103d5e63e5b0c331288684183fa01c4c15032437d1a08fee285f230c624e9a7530fd24f7666ae3c4992248d4692aa1943f7b445078eba9035d9f7a33055f16cfc5118912c52f2653f4d6775cb816aab6fa89db6230ee4607cbf984c52951d83fc14f929f253e4a7c84f7d4a084ad2380e19d4bae9fae9f0aadf36942259531289fc280df44802101b700ef80a753f635f0d634c494a3a8e1ae30a49b8fbf52b7251242275c04f762fd9b4e6601ec264aaeb259972542d9262643255fc3f7d4a67b3d96ce683e6599ee5599ee5991036bcd6741691527e5a000e5746feccc6fa4ce9b797f3c66739f4b648baf973ce34e794bbebbfde0ff05c55dae9ee526bb10eb2b9113753a9d4ec1fbf4d49531e9d3fd0d2b4992a37e512b6388bd853e538668aaa505a6a565bebc54050e081abc94b13996a23c2335ebff7ef7b0f77158ebe28cee8afeea0bceee820288eee803f16206444713807d8537768d8537790c8fed970238d5cfaa02aa9206c8f2a68213047fac9b3c14bdf8ae8ed21dc4fbe57301421802164baffdefbb523832c44b56186b9f23e38e96d11ef1e76d82066b8810c380c53e3510f1f7e98e1d4af821cbae47aada6c964c68fa67aad5fdf29c65a93682591c250fbbc8edbb0f6791db7612764954aa552a9fea5b857fb8f8b913aa54f7fe6c3c76c369bcd6639c83215fab3d96c46673f9bf9d061397645689fd7711bd63eafe336bc5b4cbcc86c98b0c866f607f0f640079338a5b9346d74bd5a5c92c4903218cc9cd9536b8ee273ce395d296264aa6971ba346be7fb00334b17984b5c07052cb0c55c22c3757aea09f313b65a9cb23da71754574d5b5937f28fe3445752030f172d4d146abe6889d3d365a2be110a0f4e7ffa037f789a037f6c52d8a04401d14e808ac2ea20a8eeda2d4e9700bcc875739fae9f04268a645242d674cac0e29aaf29b2385dd3453946b2385d0ec305117beae99a2c2dafe32fe03317650a5a079fe1a66bba389cc2b3f345098c2bc0382200a9964bcbc5f26a8191c5c6179956eb26f94330ce596bd38e1ea689884fffd5eade7baf89961c35bf1b68e4ad744d93c96c47d8846c301cf2dc3e6ffbbc2fb268fab4e8b03dc3ace1f31e80c30472d0e123b11781cea969fdbae9755da76138745dcd8a8bf177efbcfb9f94765dd7755d87d3753822c8f1251841101faf23c7c33057fb7da65734ad15b08063c0576ec944793c0c539b409ebe1af6baf905f9be2fc7ebb8267018ded6f0781db6c97751b07fb462c4c864c8191a2177c8878212af3076ad58465a4792c0c6578b538c473ce2118f18e39568b5b5e896a298a47473d1edb5b9a8b6d5c6c234b9c433a7988897341a3f512d13c5607885823d57222872132ed058da0b195ed25c67bca6b03597126c23f6d4d30b43ad7df3f1ce3dbfacb75187f3be4eae9e9898b2668694c5c862621a6ce627d768a8cac4a30e4b11cd9eb2130dd21a288a6ae80a8a1900347bfefc9391bbca06da3008c338670de6d1354c8f3743bc5ad1155e518d35c3a9f7a7842ce2d5c8d2e23257aaa620ac459f797287f3791db751bcc2abcf47bf101a8094638633cc90d5e292647c81511551e999a29b6ea5fd749f848097ddbec495c880bbc82269e49b644615342f6314db5fc62af2f6e02868210027c09a80c6f5ebf1d3fb4bb51bd66564771c55e77d6dd63499cc85010b4d021b5f2d3074c78eb9030d6b77f8e9b5552c365a42c69a049ade56ab1f383d6697d72567a8ad8e909d46037d1493dd8a2314d93c5c10a5f280524574440d80afc69ac7d518fc1185d53fb4a3785cad813f2e8952f70a022df9d25c91456da5ad4ad666aabc686f68b495b6aab54e4f894ecbbeb56ebdfeb6d5c3a2254d7b73be2c883189961c6502c00f882821128331954265141398fd20c9561211582f56eb888be5250673491273592c99ac872c73f73277f6bdf7deab4244169fe5c282519649459545930c3f05bcc4e9aa652cf05de0affa23be871e1798e16d1911dd7befa494e24d2643929c19acfcddb72964fbc722b6d6e62d621bd664f161586b1ac8d818c3fe5dc70c0f43e74ff330d809c84d0340f4d80007c833b66ddbf40ca490863dbb8e93c6d37f6aa294524a2955d140c8a2c964da4c26c7b194463ac10a27dec791ecf1771cc7f18e75bcfa628c2dc6f85aaced16c3aeebee486faa040134f6ba0955283172341016b270417d35503b8e305bc7f11b51d68ce1f33c9db5fb2e188dcd91680361f5d59ded3a1025874d537d83d7511d646f5c11bb819c5148e3273b06499224b991d4da160f0e88f507f2708a7fe831c3897d2047ab7d3299d0104232140a8542a15028140a854236252525e5ff3f8555adfdb7d6da14560a8b9642ad2dd44a61a5b0c01b70d682ca2b5921135ff184e132db23c6107bea30e527ac3f5430d9530f40e6274d839aec9992a252c098c5500b4c61b5905ac26bb6c79a636c1ba58d99a7f296e8ccd8de2a85d5bd1eb36852eda9535429ab92e292c3e2b038ac14d50c3d61f84a8a112c313e546c0ea8c9a653542946785ec9298285262c705818b4a14a61a5b0f6d4292c0c5e6d24babab233c30b2f9830b9aed0755d17adb56aac6d5cb57eba251b63b8ca0c9976c8b443a69029640ad9b8ae900d1b347e7a1bb2211b6a89d60bab61dc855aa116c69dcd2c245948a3734eeabaee1d5daf16972431a40c06e3b9d3e968d185edd83555a676fc92e282f467e4d1777447c791478fea5c1fdc2af6d4770a8f616a5c037c03bf3726c59e8fba4f807467a4c228d0447946283c320d672051a2b20e82eaf2e8aaee8aaa8c50787874d61ef0aa501ef4d120f07e4094d71ed0a5a33be06d81d7b529218bd825fb669f675f2e5aea60ec3257b09e1ab7cd70381c0ee79bcd70622fb00bbf66d8825df092d70b7631f192c54df2187b9ab1a7fec6c816a6c5a7a7b6b0d7f175e156085eba4580dd8e6eb95a5cd719cdcf039b57a8a48dd9d516aa190000414001e3150000200c0a05830171382c1ec9faec1d14800c5b72467460421ac963911c889114864190320a10600c30841062c0504dd906bc98d5cb5b609f949b011c6076ad5833f00bc586f9ea663073bc5bfbff7f24d12abfb30f28ac60a73d00822f7ca4fbf64bee1769fec658e61f3a04a5118dc61f0ea5ada1c76ec0d0d99366329662a2adc109573b89dbd66948b4a09b6af9c87abdea60ca317baa810187f15a91c2f0cbc8d9370d7abe0906a2d5b3e5bf8872e3fba166c00eb4490147b69304c1129626d7a61701283320ad915e065f1f6855151f8a150463125261c4b6f5211f96427b848bbeee7b19ed2766cf175f4781f587a6d38e8cb910f863e1c1c1df23c45d7ddb640141f6142f43cca1dc8e2fc2e10a2226571f4927c6a7be8a63fc7b6133697211cdc309fdd2824c4ff73826e97745c78cb9e95fd5a33f2e481356a310168d6c665ca9c45d2a20b6322074aad3da9c25187d552cb97a24602cdd8b499d91c709c40050620e96a10a1bcc9565fa6a549714a6bdfee1e72fa9f98836a084aaad9a720028a41bef533b6e109d209b346e5468d8c7118ad1df1d0c516a6dbaa62709e06b79d359dee8260050d6980e6f425fe0de04fe6d5307d99a5acc15561a93d44363313ab90a94c3ab0fd7083fe4fcc20b24cdcd70e36f38caa4161d3b5b785549edc8c1604c4cf18381c1d6b3a192c65d2e6648e4bf382c6afde827ed0c2c06b858f84959057c6c23289ff0790e3ceb47fa14a84170eb234abb1b16270a2b6312c27925c214ede8b51ec4ddc8e2103be3ee90f578eb605051f48638937bed0ec92f9da956797539ae9cbf400358ec657f730545e42223c0f96fc03638cd71b4513948755e125aa10cba39e480ece9cb707335f55b20754fe7f9a337d8e0d18e3ac8f9fc71ad44ea597dbcc02e4a9b423cff7e8e8ca9ee2e95561029d859944169d66b41077880fc816001c03b6d3ca9662f9cdf477eca7f943cc306ec54c920143b19acee627507da4c416cd7676df1482a1e599e807a2b9dd027e7acd5f0e3419940cfd78839041ae6f881d2b6da0d966b123145dbd54cd744c9af6b5c7dbee9bc6044e99d9fd3080e311d4bcc868123460cef12c91d2542887234bb723e32bb4b4e9189c3e3244d9ce19088c85b43336bf2e098601c2bc75fad08500bb60857a5e22bc62c1b049113590a9472f3ba8ebc744b83c839916014254b839d38f64dc8539d15b7ea34c119261bc449ec440b2891b037644d9fac44dcea2282a871710ecd4add277e0401577f43af10a6c1d79a9a9cbd763025e14f69b6557448c42b32d54e3454338a88b79146656ab90e7a16dbb376fa6ce6f5aeef8e56c2d3157477597e24b34e47f04386adc55cef967b9827cc057dc31f194375b8e7b5b32be48511ff47788d02888332642704d0ed71daccbb0a1859a214a103b72b734e7f022c1eb14e5bfcbb009e7f821c60ffa4166267b3fdc66613beeedf6431c316423e56f150c9a11d0958b6110404b1923217e37e8ac92eccb141e23ab75a951d434133ee528b1c33c6a127393523c9cc8c9cdea971ad57218fe8ee74656e0d07d889ce49fe7cae08f124aa1d011818d39f4dee0b0632ddd72b6a4f408c2c7226dc02dfd82272e806eae7ff9a682a3241ab86f8086dbaed533703db5f5ad4b032a5ec0938301884e5582aa600337cea89bcf570ec7800ee941efe175460abacff7e5f2227fe3d450d754c39d60734876134ce5bda63606dec0c5acb69ff10486e359694ec6183bb81a2d115589c58092b82a015d8c57587e98d8495d6e8a89298a8fc489d974ef2cf721991e82d7ccdbcca2003b3158a18c1de1344b198f184494a728bea5540b4632851025151218afd8177ecffec40f56004f3252acf20b0dc89eb0573f305e03f3925ad60bee111239593b0d4c8619ef3f0ae68b48e70f4beef14031584eea19b07a1dbceee46fcecbd5fc672671064ceb0965c01946942d2e20df939a96d9774f0c9ff5eefc689f1d3ed70648c826d00f7453a43cc2a90bb8c5a47db03aba2c7bade9d8a80c53f41c1397abc1da4797a67cc56eb6f0397cd3c2f6914a86a26c02ea90c0020223fee46ebd63e1b3f0d25d9605c885a8c7e47a014f01274ed6f810747c906f5fa73ede6a04704388b9e2e6c43d970b6a6a5dfed83020ed93e80954b696921cee3ac2db731591c56cd1de81e7b00852e55e460320e8b6fe86892e0092fefb0545f0e0f31732a8ed60c1e4a2af8cf1ad865c3dce69190a3657b257202432a39d4f6099d63bf3ad538743a9967745d8cf58a8a216785942cfece01413407a79bb2aef8cb225ddbfc8cacf2d35fba6e994889a2bacd48a1fa27e52f0eba3329787b237568709fce80bb18862cd6a04e19a3e11fd11c24818d0b0eabf45e3cd6fd38007781f9a3c1339046cb00407b8bb023cde55390826fb411f9dd65600166d58d821415719d44f2553377cb47a96a3e4a996f943594763cd48ab0bc69167d5c892298104c9aec1a5637a8da874033b8b4c2fae73203ef03358ea4c262ffa77696ebf4156fc0f4bce9751a4057a6566663f6fe8436df60dcfb2818bd1dea04681a11d9049c7998c752eea521fdc75118e8908c65269174d5d465411b054c33256ff572d04f8798b10a10095ded0917bebaae80cc178f8ef2a77afc101d4563cf5ee1b20b2f5ebc5b1396845e9c6aad6953e06033ded1bb01a27b713901cb762e2872a08920166eb7a0c168d6ed2e4e2d05cb5b99b97de329ac2f6cf89b7fa7ca5b2c37a46e59b7943c4c6c32c1865dfec57ad392d76d42658491b7694bdb504e704b2feab5d70cb0409a45b0c3eabbf68c4a17b5a59335d586922914766a183f53fdc0dc1ead793e1652ea593cacba02d90a01478a53fd1e54be7b0b686a14d54a3316fb43f92329bb92f4e79190ac0b8357d5dc3580ee58928f66c41f07343717f6c6a4342e08cd0706d6993710208aa8f00bdf9b8fb9cfb377a3f6eab86dbe58c1dc61c4f068341b2b69f81fb73dadb566f6088ea9d12c27bb75338b8395827d3c206b8b3f52a19aac382dc5ca52c04a8ab6a5c61025211e36d4ada797051488f254c7b8315c2e5a26156d127ebbba649abde3409b21a4a94aa806e30023b027c1aa7eb6f17671180fa26be4250d4e37a9307071093944cbde5562adf020107b801685c55f7eaa81c7b8549420d574448897b1a7612718c950e529d458ac42976c134c1a0ac8162ccdefe5eb17b8dd35a9382bc35aebbd8e74ae1318b7228027bb192e7a2f4778f42f79c263a765f37c18e60f0c76541d985d5a5ff0fdcb4dd54051601236826bd121ae94eddc317b8b712006a8bac5297e1017fbf0a02b2bed198d6c87b1b3967d9e4fea004d520ebfbe682c87549a8d8573e67c31f5731cc63d365f2c01d40d9c5336e4c0d72df595f23c05871776b6533a18d1a95f5a652314e1601ca0d92a27e596a5dd0cdfd380de60ad4eb8a5f1af29563e99afa4bc406e6ddff03a5e5088d09332a8ea6ccd44a754c257a19b64e212b5681ae0f74c12697bd94317a407103902b09afc04273dc4ce4d9f00babc02775bb7778a052a270d50326cafbda2081527a6bb7d73d93921e7222e6218c77aac6fb790c989da0bf341dde0d59e9b9e4d543cda0bbadc57ec05801eb2f52bdf0933091a139e149b44723a3f9539aafcd73129e4c14a41fb6b257775b9131925a775babb762d464360a4cecc8a9c931ae92ab0c45603a331b894fce96e7440b3ccddd64ac3e95815076b175324576ce42c10a2189e4db0ef1527adeb6fa38fb972933b009034a31ee36ea176c43873f0a438289e893c41d4a79d33882b9a2acdb6f1248f9044fb9361c2c307514b22814a8e240a251aca632711a6bb890455686275fa37eb86399df2372898515b84cd14a138e1a5306d5c9bd713fff9b78eb4be1ac27a7b0d6a8b40dec98b4a286bc9a947f323de256e58719d539233cacf08f0aa525a78949d68ef7d10afb0aa5f99c38dab2e11fd97f993554a773957cde3662a6deee531c577a008d012e3a07e4da56be60ffc52b9bd28a568991aa58ac2adec26dc569630f6ade58877454d512cec8592abcc02c2ca359027d4758751aa66006637e59229f18b2a82f3f730f846d38779bb0802065d05e02d568fc8d98e01b2d34482b0d3f808fa392c8f57f3d0100d67e01d07259803b2bb4b6ab240ae66e07457bf8ffcb029e45f11c7705ba6f04af3ace89f9f9d0c0b38eb3e864177fcf9e38fff021863e0941cb36bcffc6a303e33b6972c39d66346169f5d5fadf3e0e76245093ae9b3a9bdee8d1f9b3b41ee92a6ecb579d10ba6a969e16bb1d35dc89c9e0eb79a0abe87dc58fe33e3efa7e486b38088183815564953991c150af7bb7918abaa54d23c40a854d62c8782d77da0391b04988703118cd839f497bba55daef8e3726630cce79a7825b2e00751e9897c7f0fce17a46df15c77ea5f027ca2353a90250ec07e39268e543584d18818ca09ac1955c4f0c1c0e9ade9169f09bf28bc1ca5d33a565edbb5444014095c5d4845b04f97aed6fe0a9637db967d54e7cebe3688fb8bff4e276a30aa6a81abd9ec8f9b5f301f0fd50f4f6e055e152a124f1621b78819d52480422b0bd90aa0f7a06249d802b43d4e11deb6ec472a40711120983f128dd61485901351dc84612225106feffb2777f63bf4b099d78e4f104a91cf489789a664d15fd1ea0dc247d9a5684bcb5f0d63b8862bdd400720203247dbc5f09de416e2b97ab08ccbeea19e58299d141cc3c7f16a1d949232e8fe431aad494484bb76c17fec7f607bc73146b326f25497f7544df9f42ba9aee7c94ac14959427f0a784297b1e53a9c4b6b0c3e267cb65c82cc7d78127239c3369cd28fd1e9e3332a487671f48f0fe99473921540a6701f088fc00f1700700954850ba0c2e5a2c0c70064796eca273dd53e7656a98b568c0293acd43548ef4e51c15bdf0be323b0c002314862bc54ea82219aea1ed142d79202a646e2f6a2a480cde576b75a46d96a198fcda52e9b3acb339b8c0a356928241d7d930381c068d46e93baa4308d3c4c063a8384a28f97ba7efad485ea54578432653c197516dab2de81b24994b5be1f393854e59af5a458fd53b9f8a584d61195cbec04b51596a75c1c9afbd4f778a59059627eca353f77cae57306abef19922d5a9563304835e53a9e870b8cb6a0bb68fcb3a433b88a9daaa2275ac7d6d7bdc340cb1fad6d77814e6dda74f77dd7786474da3dde021277b9b386e1cc8cc18f2d408b36d466dacdbd83e4b5f1b30515eb3b01058c027720b5c5c3eafc61a084ee7af874d02c012d73ab3814be79066370f294642091405342130d41ab0740f71d5b3d4ea9d5c471dac37e9b5c01d21e3235110fca3266bc8239ae1b1fd36bef2af6491b7b0c3affcf826c79ae710b8aff28b85fc58b49ebb3f7953a24909a1e551cdd5c4141e0215b216baf0690ad6c02a03f3be67f1e1c6be119d11b831504f51751ed7df9c3175b79fb7fa2c8ef6a2b3c93f8a9b0e92f4aea5742b7fef268ac40af079e5aa6a499a46aef74d920b5593add4a0ec605b91b3d87205f6fce04849ab556f0c5463a9f3199ececaa75fa5126c18931e9af20c4853ccf719361cf1b90e948cf855c6868ab118e333268944a8ac56c0e852c2eed4edba8a97e0ba7a8d86b39d9438b33df070f9913da612af4e591a08642e9aaf12f8faaa13946a8103b255c72a5a9e3419acf7362eccd123bf7c0b33d81100ce994448a3b0c19124284889cd3f87de511540010e23825a64605448b851d483d2d72c95b26b731302d9eeb57db1ea0971b135de6e63155284ef595198d97c642f7c6e0876cf120976f4557d6691cf16a6b1c402390f514f3462b62cbe46eb58450f438614549a2e75c09f172269e7198774d5278429c5f870a583997dbd3c293b3aae73178f1bfa51a31956cf784cf7ecaee8a507f7ec7085ebf5aba5a95a149a9739b45caf632cea3a9bdcd375d39c19d0fe2c0ef12eefd605c0e51dfa572e7bb213fa062daec725de339d11722317690066f9ab13fdea08f93df06886530150def14c666dc6ff33927076c03f097fb80cce60ce7df23e5c800313871aab2318df4631bd2901cfa22d7ae21b4e3aa71f47ad95a9f1aad067dd1f7cc764b227d944f94af679219d70fbb8b88c6c5dafa2848002c27f1e8881a9357dc7c8c95e1a7202708a2781ca9a9c66832bc5fe35abea4992d51a200bb2d27addf761519ae231d3a92db32987c24d275b98c27b0400e8a4a097fb7126477c1b87b739956c369fcc03859637a3b0b74b75438bd9e95304e5e9d11a3f55ef5865842de4696b98ad636894fdd0adacabf451889d042eeead190c3d71ac58022d8b87424a060e81426090c8575b210f1222b63c75405c13f41a8b4541540b35425582c6f0348960512554ef4d7e411cc04aa77d9dd9a41db95620dab0465623bc3b690016c1915745ab4a3e2400560c4b874447ff237bd069da9b9823cef992bb288f5b44a879ea00bda01383734654004e6852e1ece9be038beaae7e1b5829421dbd356b00b2600afedaa42351240d7c50328c235d3f88bfbed409f134ff0a095cb32742d5bae169a72a6b32bdbf0d4d1d66600a27de038b3b111e809d20c10f5ef0db7e946daf2a04b8b7887ff3552ae93bb9c145c217c5a8c3fb821591ebc0508d21c0ebf1ee5a308479adac428fba10ca9f225108a123f5da6f05324146644ca7cf0f05df3f702b751cfd2bd8cd9cc1d0c3a84ec2b0143c52f064a5caafeca851d7cb235202bda63f09c8a1093e45708aede1072f6cdbe574c2ec2f6b4f254918380778c9aceea6405d654c195a315ccef28dc8d372aaa6701e51816de77ad28970351137395d8930d20161512738959ea03ded4753de3dfe873a280402048ace6514740b15461922e338f8c261c4a35f13da2b532fbd2a23d4b23bcd809a4ee5ea78e5b4b52090c1359fa1bb3884795ca262f24c94f2eeccfb2c7fc458b0e8552b9be888dfc0ecb7ec6352b182fa13066012c773f6a4ec9422751694ea48b6f6a364e9ac062b25ae2b8364a068d284ea8b2ec770f3657a1dae0892e80985969d07166327e06b1b96f9f5c5b8f30d548ce0ca62855a97142c53cfed36f329d85b9acc9c18cf91c25053b190f4b70b7ec4467d9bdb1671f0ef84c98b04bb9bf116442b502c8c5978867c4234d5407ab04519c63e947331c9944bbc000200a90ed2766f8982cf84b6bb79b825c194e137ccfd55e47f1dd9249629a1bb6ab118ba97a292ff734324a1cf5cb05d73e335c9fc72bc7edf7294fa2dadfd00f30737a17284354065cc06bc32860bd366f36afbc9b453fde52905e583df7d262752873c3a033d6875a0ce558f1348c7ad646bb52ffa2d41ad513584396ef3d5285d8182f33002eed807fabe94b9e6b05a50bd14cc6639bdd3c5c1d0846c362d9750a04410f22bbdabe1345dbe610defb399df51a92f8029b39b1a972a06d4b8591cac1f8ab1cacac132a077a0c0286c36c851871c265f2d3c7751bafdb16e4e71de012effb0fb854cff6c9801bad112d92028f95e81eb40278c828347d7a5007ee6b6b14e2d05554cf73db9e2f625ed4e65d9e51203e6cb99e6955894e24b62cb2640282088d95af6c1117f1c138f9c13fa35f320a97f2fa88d1da05b2cec389d1079351e8b53d5a77d1b3cdd8243910bd91864d555009e7f6ec32408a46508a4f14e01442c3826946f0f5a70db88c26a2728d02f7aeca769d89bfbf0c68e031ab2b8334470d66d065ac6ae61e7a26eea7e72156c5c5c0afff987363cb45ecc99adae6d4010108c02661bf65bf9eda27af9eb4ae2f53316072329791a963136e621c52238b09cd0c43eb772e140a4bf43cb123b6b1493cdae136e456e83a3d724469a9b286a817cb2b6a1d893c447657a2fa02d3c964c1cf78fc098a0eb6497d4b5686f5315c4fb2799a5368ff521caee1f09229a720aac07130a122a78d1a470edf0506b1230e4f96e84d95c7b1b9de934f43c49ca35892bd6ccb976cd055755ac823acaab6a61fc617f6cec10d1cd4c4b1efe05cf4dc974e85490b3c5d4880100b71a7856b69a4e68efb6091ae43d28b3cb96f410a5a29f114bfb92d815707bd3bd891158d6581015bd149864bd29999afac00c7a62ccdf16a75e448702e7db7c2ac2935294659022260f83623bb31132e787128530b1e4060d64fb62b5a468592cfa4a705174570faad5a8386b05ed1043382995f947753c8c9c44b0bb2437ebb81840c85e0e14053f021149204deb03c8551c935878169b253a136a28eb5d04557516ea56c87f5712c35035c283342be91de122e837b7bf204e39bd0682623a23d6adff2e123c0d0768bb58a0d03e3af5f1055c1fd14662d3883c05c96507bd7e70e21175b368ef5ad5bec9d283dcedacd63f76bd6a2014d6c0131a3b0aaebec9014dc02b4ccc10680320f8fc07791a2c2ccb209963c70d2549013e39b37aa75f3f4e5cfbde4d0687e0020b2fc958d48bbb3a9fccb759bf73fe6fee2370841009c46cea4aedba42dd31a9d013a21a5b862ed125c7d4670b1c032ae654af4dc62fdab3da01c1f7c6e47cf8df7da4d69846d6adbd6703b7238967fc9021d1eaffa5655ea0e22c285bce9690d86b1ac368813254a0ce1bf26fcd9b03b9740c5edf31de8abbcc8b7044cca9d07130c2825c4217d58d7240d93fc35e61b4826fa6c248fe03d474a1df307162f52cef34b3318629706aa8428079796534f8f45d898b7bbd93eddd2390932548e46f58b9a0a076278bd7a168bdd7f544522fedb9d3194537c2bb135413189fa32b20ee7a147b44e7472534ebb06eb0985509b627c6297ab519ef49291e8eddd167c5ecf7f86b753b0eccda23804c4a50ccc47b68b42359a78f0360f9829c6abd0e6c7156db7beffdc4692444aad3ca8db46927da9ce58329b6e710211d9e6ca34dcb55c466ad8ae9d0bf24b734a608aad3de0b0dd2b21c4dbdac1b6cd3c0b17d72dfe24055ce9eeee1ffa5c0ba017bbe114b6a9e3b8b19fe3ce4ac94b9df094e8e6fd5535df01203dd2774fb8decb9ba18e34e734dc610c15b3250492370513a7ccedaa2a68a9d5cdb634730f44d94f6e4b991141b06430c2ede4edf18e6af0a78c15703f8038cc04770fe6ba28442efdf81a556bd895bde355936b7e33c1fba917740657881c18df196f2b67bec3a51b5b78557f4703c42e9e5f0740423623b42b3e879f0f2158d6c6091a152bc5c6326beb3d1eaa4c2068fd6aca76eedc8db9ff1b68020a483902585e838907ee7241249778fd0bb91fd649294c4568e6c249fe68ec92c9abfaca3ff6db1aea59bd152b00e50116ce3e5072b16256081a51ae1e49699ecd5d6033414c21f13260d7b02b7178106ce2768705b19fc82e086461370106f6512f2d155e3cbd649a2c78391ed9425bb157c5ba743456e76bb88ddc761f40909efe08eab1428c36e1c60b38afbf528189e475f7a72155c416e3c8b262b369f0cea21da73bc24f604cf8860692180185a5d909e8ad6de1458727e1610403a6eaa1721501727e58c0d1adc0527aef901f1639f5096f64700703b7d0cd091c91749f983851900ce9da082a235fba2d6690b855dd95b4fd89314a85a7068fde46250a7bb57b2a0ce98c1cbc12d9c1b0695b694c0d94aaf23f4cd857001f81cc2b26f85c6b80c432c1cd1eb2dd9609f86635cc6c59cbdd48727d5377e1f10f33ddf7e3ad493ab7b51303aa67e601350f84f30a4ae581176f6861ed93635098a31b4b036966142e885157a365469ed8b2c4dc1934dcf94e36afb56075b72ee4a5bf452654806bd6a4b069d5340c6035dc38791a4384f4f368e5f1fcdbf3d6c5b69e081cd50abc407e02a6ce07e82facb172607222e6b2410fc6e39156c12a879a0d07291f240bc50eb355d6f2eb55f1f6ba396ac12b1bcee7308de1edf56200975310fae9fa60b8223cd8f2105b400cfe7f5f7806e05254356fb082f6419615be40c77199d6658e73490e7c85d1c9f3d40fbfa65c679c220f2d7b8ac0166a556091ac10d78d2ce2a7809b25212ee3ae1a3448bb2398910ecad76c5532a4038dfd7b2e1c020730cd9653981d836284816620a7a64774ba214841529cf0444b0bb5b5c27a393b430220e6e57dd553b5a3da9fe9a30ea22e8376c00cf4d0010cb037593023c41e35d90501bd5770fe1e0b45797b9eb83f59b52bb10900af2ea0b5f41c9b633a8893a35488b3f5ba19d285257dae252f5b587c15006a9c19f4d04f41e7126e2db64eb09ebe897ba820fe896fab0da8f4366df2c7939662a515b47d2b3f0937f3bda81ee43b6768349720ce869c205616e156fa3d8adf8bb3d7578e263a61ffc37428d5fd80967486f905bc7289c4a6ed5e812d30969cad55d87709f51cea6eaf0c9d94a6a3925b0ba85d5490b7c796aec1679bd68f392b6515604edf9180f8b621d44327785f0b4f5277c03e6248186b3d67fdaa1bd0b19b1c1d60342759eda57336ea6248d97007868a1a14ad23d6147cf22b47f05d198dcad357ca3e6b8422e52d5fc811bbf62e7a4b2394be3f3c84526c1043e58747fba55bb242900bbde58b04375a87b4cf549e64a07d136bf09d2412aee9cd58157ed921c44f7efd0b3c4316b9b2fd281e1406db3cce3f0c58b69cb33f2129bb9fec633a03ae6c25567fa16c6045657c389e3c4ed08651c8c97af2c81a76e764b51418a97b1071d0eed5aef5a018a8787eb351e3b4bc47a8d73b1684da85f4de7f3a66bca3ea6653966c3459281f013852f7f5b47b1ef95cec9852a3681fac0a30b16052fc581b85ccbb3430465f831112c9278329c095d915108702d19b5998a844e276b4b7f767244f3a13d53e06abac8cc9a500326578d4351888f86b474b413a7eb6b954734a888afaf0e5dbfede083d6b4d1d9cb7aada06d92901deb463adc2d3b081aca68fe9542320666569c8363b9eacc555b2df717796cdf028854f40c6a489d25b563d87ccaa2973d4226851fa9007867558f50bb16282f864656e7c896ea6325133189dd0e038675d8fd16a0bd900a21d06b59d68201c0991e00b1c6e3dff7ae3090c4e615eea17ce5d56e2cda9f0481f50fc6c88621353b9bdc2e03c2ec1e04c3216d415b9294d35152bcfa6ab4e8dd4c98fe7c8041a6fd5892190a94505e19203e314d29ddef5df8b49c077086054c0f3f5a1017fd635a63802d3a6ccde1f5630be2e269810b5c6e7c08d33dc960f4503ff0c9cd1c22b1ccd6ea8a3c18f2b00c49f6c97d250b35a6935845004a8222ef8d5b7a5ad2bf4d4627175745212c01b15166c4dcdb0ba00c39e328d4326fc6866f0d72c58afb61cf755a22c09a1d7ca17022e214d47a9c3daa1c584fd5ffe79d349e9a69f83e1ece8467aacf49503806536313160b80b41a4aeff4a575b4119c55272eb9d478f956326f2c31ac2a433062e822291594f4a30c7e78e9aec2c5eaf79e4c24cb347864157fe908ff4c735feaaeb2a5d1555753ec5249696627dee01cbc58f02655a0af4b29b5cd5014976b3210207c3147d9e7bff70b54103b5220df527b6a6fdceba1838cced1947c613c9668638108a8fed9e2be357f786855b628e9d1300728957dd848505bf119389e0bcaf340d73e5151483c1e9917d41a677bc8a731efb27b3db8b12a9d12790853ab329629f4cfa3f1485840be61d9900de46a14fca0faf65a43e52536d62f54a35e521fe1450eae60f5c5bb6a84a6ab4fda47f8a2f14fc6180dfc4d0711ad7463c3c8e1e227bb19b372bec3513a8d9017679f38d45c1ee51cdf8b52a5d1475647032fc9714a91c909ae7214e52579f533491eb9e4bf97560486415b0e43840a2a2e07d599519b04e276d47e5370148eef929ae4dfcfef5d03b2c8cb68c1d8d55766f78c7dfb1cafa15e9d6bc483149e25bae7befa822b2a86059465f44909c277876921ea9606b07eaa74b3723d501ab5e7da2e9e293f8a35350622d02d00651acdab35fc05d2ea661af6445f98865473e9ae0ef0fc4fdc5c092a9a21aca678f9510c96f38c400b4b245d230b4a397baaee9011055359d12e462d0e313caba8b8effa3cf33a724db5b1798f49a71fbca004fe3afef67a526064fdb7cd64ba283af7ff888f7e67aa0ca78b1c2125c535b0ceb6100cf6e48e0147f5ea45a11c138160078e843fbf717b7b4b63964dfbc677674116f990d9a01ae8132827b811f3782e45067261e5ad16d3a0201438cd36a6cc26a230ba01e531d383ae57d6df64d41fc17d6f3b8da51c573486200297c775bcfd34330c00cd0c1e50b08a66771799253f682f7cbb691067ae2cc7dffa7397385a46b3ab61aa21ce09561b289be5f50689ea12d3291060350ee53a5685789bd0c0db292f57c7e92cacc28a84bb4074e33999f58be52c0bad47cd25a69f4340ad8532ae647900d8b077f2f6e73bf186283970b6638c364b180b8f80a942763bf766585afa19c4748208b7ff81bd593c9ca13a9909feec9014fcf1ed909b17545686cb8c3f4a9cf0968ce14e4fb0a9d60dbe6d2b1c80df24519a986e0b21f75b6308008bdbc0df0cdd3d7bc2e0acaa5cc26e095e3191f3a979fd85a07584650d011c5f5cc8ad97afb375f3353433de46d602500d75398cd26699155da8477d7024140afc3fd9766bb36a720c6e678859dbe1ff4e868c8048a52de29abffd48ebec4f523508e9364f85517210f7084ff6d7ca333196eceea55b38fb92231febe1359a0c591137a32b23c40598da61773879e674f137eceb24ed68facec2860ad0165ddccc57e172bc940aeb5089ef568738ea173dc11b4b3a9e28765ff76703d340d25e971e0a27ba4100b5657f87abc5b5caa4196aa090832e63beccf6d38b1772177f8d18897cc0a472e13f898bd7261e780ce3fb6bdb931c9ede6750ae8f3a018a05670b80bfb8acb2245a2c741d17cf0bcf32bd6e0a73ac34728f2cc2b08d1b574a6d8ba650872a8ac752c49f1116d177805d4960003661eb5cae022ca53d2e887e42db5ec7814bd8cc1c3107309fd32fa515b931979965cb701c34730b80879be72bf8af4d9aedba3a7dd909e0e0454fd62113eea8071272a1adccf1cb5e51738eb1fe322198dcadaf396c2d3ceaf5886909d443eb4732931452ea8d607cda2e69cce1ad7fc1a0777bfb651bbee0dc467cbe07dd819b4ea9740741848ce5dde99b1377c09129cf72f9648816179595e72c71d978fe11b60e8503c2e9db5c3cc72c0c2345e587624dc1b2f529eea70b7f192d7f7598ea5b85a3ea51ac280d73db0412ea15587dc295da6ba4994686b12bab0db27130684d6a67a8130819b23171927c18123e346ab7f182d132cf446e609956e953031963f74c56527fd8a3b96df94b104d2fc8f12ce6e094b7710eba0380eb8454d7e07d41ca29e09471c9c617ad2b0807c1c16489d289cb8157ded63a3b84c12452a1d2050a6201c7c847b60a1c38544eebaec1073b4c03d325e0799b553a1ef894933d33f6b087ef0a506c8dd3914b61fc0b58e1c936e3fb8752ed0202d0be04818d00590033f330513a19048f629561927419b53702acc132e407c4a55e0c68cf0ed50f47b8dde244c3cc673989b19f500f0f358cf3bd27253dbec84933268535fb064090f34cddf29ec249c99477a89324567c3c49b9d0a153bf12e6fcc1b290c44d0334c84b26c280f147c1ae5351644d08b522188b468f3c31e2bec5bb790e114f2448d785ee0866540e0a7bdd8dbcdc5a27a9527e84aa83d36411a295813f9f1f6537e92e396a8f2b0a970cb77e02b0471f296fff99a401fc1f789cd7f2196f7362c4e9ac234fcca094880471bb6d06dac45fa77e7200432013d6f98e839fe02bb7d1f203a6bf6a09ba1e4d50e0cb84b742fa5d89346d0544c4e1b21ded624ad69f9ef0821494986179161186fa5aa3696658f4a661c87dd691c3c1114df879b6c54eba0cd629e3831dadd823162fdc906dca71139535ca9cd9df709171106cdaeaf2d3518b6dcdd30e755621f12c2078a11bb9694cc1fd616e85a6b59023dfb1474a1928750a0498d36408ca3bf909d54ae219f00245101eaa90e55faa2671ecf9a2090f35a41ab042b56f01c4d5b44520163274d3205f879e533e8f0e78b27753518aedaf1e0853c625d6b82a9d7fb5398248bde30ceb21ae4520cd5e73bc2ebeba11ef1691619eadb1b6f7b86f71f8110700f1078908cbe2bff9cadd6185f9150be12b05199e44424f3a540145aecd243d0f12aaa6b543d3eb32ef05a25b6e6346f66ad1c49de04f6856046a0baef60115b9178e876851966128e12e7b0b37db5d75b2e883fc51873204071d4ca7e30927119768dc460b7380176c3c3df66067a2eb26379825801c5eb43a415bf1e769fdcd60a0107207c0847fcc428cb0ad811927ed211c8ecdc10702cd2d992c903e9af1b436714f2f6e6421ec14e080478c32061ed9d4f9caab3476027df4b189526fa960f4dd360002303ab51e36e7e9da7fc6d896f4ff351fb4240220450ff402d80ad0851d669fcba1fb59cb06af7cf97a6b6fdee91f67edea7954fb673a600711c96bf211d3e2bfc7372789add31234261cd4eac39183205bfa527a5074e42d1630ac7391b44cd795efe6d68cf0ccdafa36f21f402a50bc2e6529eda5aecc8fe9cc506bd5bd2676706a1baf500d84f6909613234fad0e1ee6c5fb2b4299cae7743de96d5b7af1f05e4b358e3658e4f1b9821b77876722a56364a2e535ffec1782fedad54c5f51f551aeba91a3ec28a330255cb31a7a5a8380b089b2f1e776114cfa6a91be6d8f2f3e4fc9b87bc56e8b3408ba07031cbb7832ed8dedb1558482002764cb2623deff30a84f575498f0b72866ed1012ca1c3385dc7a913b1a2938e9a2db6de22ede0d565efd0858b56d970d286578ee7e3ea7db8c12062591a7c9e727f8ce06b28bb04f53458dacbeaa3c4d97b8af4a334094849ab235b629d031582d204ec08fcf611dd40dc73d4876dd80a4e414080d2fe4614085ae70b8797bcba3153551e59e6e0d68b21b243de186581c86f02e15e81d5f4700021089319a169579345952a9f078e5147fd98e36b10c4a9336b9ba0678d1231134642112c44b4f60d3f0372082461e2797dfeb50a3c0aea6888c00da9de93fc542bc744bad6a46bda1cd35f955f8ab985e906a18e62e24c5da219e618ea9b394b7461377b3affab718b9c26a5f1542ca518d6bbdf4a8022e5b66bb85b1ce3792b7533b859d0378311456b00855d9e12f991e8b6d46599e4c66b641cc4e60d14e6c879bfc7e704503d5d0e7b57d8add59b5a888bd3070f1aa1dd08a6be9fc939c5c1ea745ac6afbf125c55bc000e3326a921f5ee7700b42a30994750de3f4c27c3f35f10cc322437017dd8f80b3e472cd224342a7ed7d9507ec41257823434bde31339189bdb64b9bd5d37ea3df6075e14376ce80e8cbe6ed71764c48c056055b24d1749cdf49ea44254cc5ef17f50483f920806448709f2ca8d864d763123619b1bbb1196124fce72ddf103743e9cf9c07ec402f2aec3f66fe868813fc84067f7a0e9352f7f1ddfc96638d068b4c0080c3130ea6a9abc02d036301c9805a4f3a8749bcbdbc0c497da262b6d6d05afedd0a8a7ab150caabd4880d702202e3bf498190c69c20e5614ecac663895e75a133c8f263a3b734e64b8959b07a162001a4f89a6fbcf0aadbb3eac050a9377e699d128026405280b046730f6790574356e49678688275ba67bd81e5e4f473f138c663b77d384c9b683a0742b2ac0e0f2705610c680033c01e2110a8026570e3f7ba7bfa7aad18d0bb5c1d458c956a70d85417f80857e42510e43d6a451ab266511461aa367ca32aecfc0d21df73d4d77fbc10ba559e8cb1713611a63eda01ba9bb1d768722ced8aa2d7bdb85cf7d804087cae9e7d5bf79ffb90b0a598f39f10879be2bb9f9503f0abe5ff686bc7159e82ee081eb4f1efd6825cd2aeea97de41a364cc31e63b798ff44638904b73b379755e87cfd244548aaee71d96e948c4166a0c692bd35098b4c1fc47ec3d226c2a86767f8d0587192271ad0bee2f5d642db4534f62348ca7d8813de2981c284a7f4a6f2ff0e3d800ebc8268bdb73508e3c674dac89e1b36691387809185adfe82b7d966664d32e178505dd87f0b08ccf59b688681a55722ff65afba1b8002d1914f07ccb4ff7680c35c7425aa5f4e442fee18abedd72c3e3f67d35b77a01d615d0ddc2ddc67835377ca24aa100f885f6384780e0658e1e8ab2093d2d5dc7198ce99ce26de9de3580fc5f286d76180890cdae7e0719e59b0ad274b12eb91dd39e0ec1df031800eece9060f18da8f1898354d4ab12f319e25353c425c6491f0dbcfc401424d1a69ee7b82803b94d313b63ae9dbe370dcb07576edd9d5d2e2ac02ef2d69dc26b5c3a837f01c5a38439ed182fdada8009c2313f4b64b42c329f7322dcbaab40afe7c20151476d06299969bc7af04698b5991666dbc33fe713e637c8393aa90d63ad1cd2a19eaa002159114538186b317636e1dde637184e78e603eab984dba85041649ec4f9d8d89ded29230f2b63d09af9eb53b8be4f579e7fda1aa3c34a4d21a1cc3146d8b4701e14e7fa49fbdcad1dbf1c39eaa858fdd05ace6fc21568cb9cfb6cb2675692a1a43b370d8c47da97d050c48bdee9ae72ef7a532e2dec92ce54cf7214d38e2a6223f82813102387fa4afaa884c28a26e64f58c4d00f04730592b46bc3512059a1d8d4ff1bbd18c449e92b5e5b4ecdfadbdeb22098497d43c386756f7dd1fba56149d8bc1194673d9d1797111b00758ee3d453987a37132992abac6c3cbed352c2e0f0af9364098d8fb24b327a4f402ace06473aa1b38305f51d8de756e163fc13bc6465e0339fe516adbb570a819e86dae42f95701aa406b772b869647b2775158ea0187f3f15d7c3449dd8daa9821a0f6c7713cf399d1c5c331eb088ca34d0a64eabf141ee0fc34f893ec3519dd961e1c764d78e6b4eb5e1ba9092c72aed28f266425f376705306e22390b5a7654494af0a4bd28b076805856de9c9592ec2aca3056e07c628ab0b9339466941dfe10356fd7efbff052bbafcf0d8778f918e2572b0846d3e59c0eb8157748cb188015580b39094ac9d692d1a3643c570d6eed5fe2cfa530137caabffc6baf51c5f9b699901ed0be32e83cb27b030a40baedbc3f225986371c82bff8dc94eee6c4e357e1e9339530e6c24844d0e7b216e192ca94047b22c9aa866ec7d1e249b96ff6b3dbd142fb604dc2f94029620eca50ec791d6e496c1d4ad2d9e86a20f11b170a9883032e82547b22b97fdbb0057454c61d4fb39b1d031dc0379fb9865366b276696ece1d389d8100c4b7b45231008ff2576ec47a4480ce0989a81f9111ef30caf15c8f4550772c9101750fb820ab923b033eb9e61821261bf7c3928bedd80413ebc0439d1610f5f8bf686940ee96e90e91bbc23f34106f487b922df2ed1dc8616f23e490a5a010e416d734fb4ba52f0b3dbb173eeb86cc841fae741c7144bb433612d44cece2e8d2d30bc84f94733eccb7b59213889f424e21f1b5c865a56d1c2a9cf6b79f799613850f7d6b626825a450f29556f801972169832988045929269c86966da19a13ead6bee2d2a67ba7af81e3fb86acae8ebbe2dfe963bda9139950e375129209be2d8f591947c803ce1df7be4d12eddf690f0ab63c59bd24f626f54495dce730d0850eacefec4f6477c8b6fcbb2a07681bb15a85a6ace074f8646ca3d8772a84ad35e1872147a733483ce05ec431ba3f272fa8fa89dc99ab2505e91f3b0cd2054af0ad0b9db298970b20f377b976046d996647c1e608da886a5d7fb9d21d5fba59979af1bb822a950929c5fdafa0d37fc9d1b73a817432f5b762a938c36de844fe9433d373cb0b841a14728f350f6b0f223ea7c024613e09a4af5bb8d78d567b1b206d998bc40c554146f75b51b33b17fc252aff12225cfc8f6f7b366c72f392710a2700661acd883e1cf8b9b0f19eba0e34bb6ef8045191ad2f4decdc1efa489fdc419a86102fd64066b180bbaedea2c717c554cbdb9a0daba6a34327e81a9790a92b12f87253c4ab74f9ccc9c7a2504a904a113a82ed6921774fa0a39019fe706b27244f4412cec89d88d2b00b5252e65a961809405de3fda2c05614cb85d8c054aa8a96a4971fcf1529256c083a64162730d67116a9bb1c8a638e3c674cd30cfa6cc62116a98a1ceded358a65474df10c1d3d8563a661f85d0b6ef84132c943dace18b9011ded24f68693250cde3a0719673e278ec4923251c844e6a032d303339ffc1a9cd06abfd16f95ec22b7378147f880d4ada6807b36e73179e6c951289ac77d70fdc8a2c162fd35cc9e1db60c954ffd70880fc1ee929457356d0880547503ca30b6940f31495990fbf1e19ef53991acc38885ea4162063640f81e03c85570b9c0ce9770f30c221630279c8bcb56b6be63bb460e2b65cf1f289a49a72af320e842971effb29c0f32399c3b78e56269c6ecd0e11ce76885648b6de8d11f8d131227ed45845ff7af33a209b231aa2001736122f74c8bb28e220b74aa12851bbe8050554145f6632ff6cdb21cc30ab9c93b9fe27e0aa24315b6e59f43dec198e83c9d837e66d310b3ae0edb1cd15801b0ec6099a6646ccbc84fa13a182b091618125a368eab6c6e5f2a18886d4829941dd936482ccd538d87fc38596a3694880025afcb7885f11d87275abce3ff33a670068d2c1a710f090a5ea41d954f040d603d62afbd0d2a4290c035a6221f91e3339bb5fe10da5d6f18c24893c1137dcbe957c12cc8f6f3efa8d2d7c99900e04e968f0181204150c033d14d600c2b310e92b5514691eb166ba4a9b7401d888ccf73780c698797e8eb9964884821995cd4d34f1f8d9ba7457fd9d4e6c414199093b961acf76c4492be47752ea61aff341e4eac1ba46a87d3a87bbc96cd1a4c46c0268dcf0160d91a8167f0a91d7153ab243f52e9db3efb7202ba2f8aca91e3fbf2de22421aeba5d63aaa844c34fceb8d12e512c5eb55cc0948cf0cbb5efe18d4a6e4b283e1b89cb6b7bd2d87803ef8a3ea5e3975831480aded3a447a8c09e52727b3fe508560f6ab067c6042ec4df6664130bdc765303408e269c95d8a9f11be9ae23db579f64593f3599a732f4a0ab7aa3e887083a7c81930685fc374a61e63f1f02c49017c1df540fc73607590963a74c16777290fcab4aa32dcd68941cabad0edc919ce625d1226afa414d380d4a3d8401a4d902a91cfbe7d6d5b2f929704999769f16f151703287e6087e6d1199e19fe428e6086d21a11df1681fd6971de30c611ef07a4ee7d7a9a29cf83fe668ede46b4ac149608416577aecb0bb5f30087deb6011af6afa651c29aee212ddaa4a0905e9fad8f5cf36db2f971f8192ee4bc778a813db7712270bcb598600dd9eb2660a77420bfd95947cf64c46f494d7d06c12607abf3864fe74844c96e99084921467b581108fd5419033049838502538e832d9a096cb7fe70de1efbf58e3ce6e2f761d8a5ceade56f3e67450ebb70045214d1f5912e02af256c841286f8a5de18aebbfea3a9105f7b9000cf044fffabf4fa042042428289ac053e60c5c1a1594feb3347bf413b8709298cc648f83b22c8b457befd294070f98e462cbccbc3c33cd2013f52327d5a76b6b81062aaadea6bc8cac96e433ac28bd4229fc2d9ada29d891664e3bb33bd81dc764bcd31433ecd97c3d5e5fff6ff803ebf5e33f81bd630dc2c75e8cc88c9efb29b37201d3dc7276225f7194eeec3e6343da9b10190d9ef23c01cefbaa3971ce939bd2c25d912b73947b1966ff2ebc693703eb7cdcc46037e8696a1f33d1d197970609cae5352498aa46ad81a5159951afab1b91b648c3bc95365ce0f7d4be88c8facd55b97b93a12e574e919e676accd9239fdcb0579028cf1aa85813d1b3e4abcfe24aa87a8d3608fae0b027f32da46be89a43744c6aad2ea18443bb3c91b7921c46113183068983116b913bb0a5ff594210a08ad17e338a93d8c93e5b7a206363123cac129b53f4629bd1ee5fa37bc6607474a2d207f7e000893785dc57b380bd6e9a35b0b21eb219c398182ad16c940ea371f5235c249c86b978bdc068d7b14f915d8a16077433f860931dfac83ea22a5f3abbe38a348ed2741cad6733ebe846d262942d733c793d6775c65e9cfcaf3b0f51084d9e70dc63181618f209f279e291c5b61dafe46206bc0a888a5acfa723e4da47e5402c0bf732e2b9c27515eec7737464306acffad663b5be9bf8346932e3aa865534834dcf3857a02c9530c6182f6f967f27a92548e9a8a64b5ae7c894f83af21490e7c2101602798d14e78a22b0defe7d0086182385e998eb44c437c3244e96196bcdae007bd250372d209acd339dee6475e89ef69ea6b1815cf92a428d5407998a5ffd977d7e5aa42ab06c9e2059be2d35978d9277887edad7c5f83c4791449e291c52de803e4d727fbc1d7dc12a7f27e6f4e45f40af7578830c6e923c42f8890b629a7c33e47e68440833c98ee6428d354e6fce4134465e58869b4489915186238366d8716128d8ac3f7fbc0490c7e8408d522018fd08d702333fb53a5952518531f2207ca7a858a0d03ec97c3d919be401061bc1c7efe8d55325fa1216df0d8d873da29c05388220eab62e6803e205dd8d183632bbd90eed51dc959a1b2c26d870f98a89b944cd488b2c902e7e906987adc900129c4ffd65c3b48498be2000242707fa36cc2d1098407f99d9bd166b4564a85ec04fe7b8c4989e1769967f351db5bb42fcf7a4ce29f7424879899a8cf759337b9bf9e123d5a5b9c81de68d03417bb3f66cc66dc25dce4d41ac1a404bd621b4245b71e886f0c2127d722d5bdf08114aa16ca15fe38ee47b9246903893dd433247ce513e893da22a9f9a81ce5ab2d42735b9b4f07786c7d4245b87f7365ce51ed517619a4e0a09d395a6db103cff67eb14c342729506296e71482e9d21a719dedf8b4e59a0590ff88896fac76868c929dee4565c0bc524b3d186864ef674a062ad8bcb41ae9f3aed936afa46ca7fe460ee54bb0567929f8da9b95375c2b0cbac8a245077325e178b6088fd6bf1d5dc9b22a3406e8a2c3da6bba87575356c2681605c7e58a96b9ac6037e08ebed0d034c2069f4e084dda3932a5fa73664830d6c5231d0149b47d1fabd7eea694e4a24a33a2d625c758f7c4f2cddf14586c91dd5b5b51dc11358ca62ce807a5ba9172adc1641776a8a3cf251fb690dc7431e812c2a1ac0d304f28848dea19f620fd5298c0179247b40c6208fe4bcf6d159fd67271a2b9f0837cd0f17e49188b3011037a0649d05c823a84c4a68c503b21216ea13239a019ebcd5880a428b1b98d0731543a603e8c4a5db71dc0fe2032d15549b95e5320823bc174a87ec4b7c20ed99bfb4a0eee4a248f6cf38489b718a06f120b45599cb6326e5843231fc3169b5110a3677f2403133d15d9605801809113551eaa74f8ba1a156297062d02785b0b315c9052d3544444df2a2fe029cbdf9681a366c5c75f2976f301e34954825d155681199fb7e7aa422e2716e5393a1c022482e51e4fe8c922962960a678415bfb0932546cfc2262fc48634427523f09116f59c6062b5a2f05370765b7b65831f5d032689d756a4dd9010d554c7986e565d0f2dd004dda1d3193d47a70c51e37a562be89e4d654facc25f2e0ce99ac2f16fab9a2b80868156e43cc744b6910fbeb6bd2a808108817d84d5a225a7c0f3400071d37068b8d9bdb7f02ecae0aa8a4ddf4e001ed991d4112682d14b78bad2149dd20513a6d80187fd50d2e55b6caebe6a64a8ac72067da9064bf02e07b1a1d49b60aad548f1fde8758ffd256dc7d4aedfc560ae00f78198993e0b1cfa6f80e909236c02713aa473930ba100e484231615589f48ea8a394300a6d3fb2949e76e003ca69774ade9f9a934b8ed973c315aee66d8c7cff94382a923804bfa6d1a92b3d0233f45e56ae142113baac40413a19ea714664c6fa1a600e22c9a05162af81e6dc4f2a3ba7b2a36b3584e814dbe0a302da29ad8b5fa7427d0e1165cbfa44021f703e7a7e93193a76f3dc187620134cd7a35a4f9774a81cdfb67e546a2c3e134e9ac100ded2c010509ecdd211ca7ce8e739e17b29837ae20e288d1b3917bfe1d536cd326cc2eb1e7c9fd2ab58b0e17dc06c3cc72482b497d018b8a8b40d5736dcb578e7c6109a4238999e7cad5524385dc8cff864da9e293ff38d86e9c03575d1794a8c638c2252becc1c787040ae2761d7c2af560a6385b2114048e9642cec5354be8ce441288a5e66a4c1dceec91547204e6153a77ffd50e4e10fc755cc92ce0d91101ba377ffbaa29a1ae9f73518579d8e1d62e57e9c249e07e2861f5f3651425cc181ac86640a18bab383471b314a4d9798617ee4eac0a95b4d76559ccedfaf42bbd17c7b9e7ce7472059fdaaa43f26e9264130f5ae8f121cd6eea29b5d0b9a4353e4162fa13730e87d1adaa9f0001fcee55a0bd99cc0ff4cdab34c02b1c9913af7fcd4f51b9e2b47e6de8577de4571382d3ee943b471e1a5f7a199cca411d206e4359fbdc6d7fba86defda78ee0195d8f5552d402840cf10101816801c31b804b947ff40fb83b8814b02dba42546078ba36dd9be12761ef46c45162f006efaba328c635d5f788edaf28d6b9d899b80087cf94b5d23d93bf65fab4e00387dcd779a14ceeae1300cd828bb163d3879dc6cb1b88f633f5b5c04961ccd4f31267c58bce14f8aa45bc50922ba74493513a7889255424fa4a84e526f1191108ebcefddfd42d9f30538fa55effea1434bc47e6cd9591d9b1c6055e4c0279699daddbdfd027f0ca2e576a4ace6f36585f65f02bcd9bbab3652ec63e43109c9945f6cb49e1b1a66d008be0be3b41b66180c8a966454358e8a762b40b20ec1c7e5e3e1611cc37c3465ca82356d77ffa3014bbd51d977a01a9e8738cb15bc6f44c0e85ac34316afa44cae26999a2f42ae3d7fa7faf409fb7a081163a2b9952e57282d6c910e1004c22d003bd3fc80c32828449583dfc41b0a87fa341e85b8d0ace1aed36e6d08c6c2785428f4b0618ceb9d63ec02914cd09560c0e6e5dedd5ccf49df9cf8234133a5629c96a5f0900eb79e922205d394cc70204a0f1868199f8b9c6ae28c089e1035478be68388a4ab3ae64387d3229ca9c9bbb06ea7e4d36ee6289947495a4fbb0d895a26c11f0671bb0f42ed78c293dcabb47f9a55081f4df62c27f0c3e4dc1bfc4e4663efd9cfa3c536cec50820983d527c00ff4c804da01af8b411e9aeb708d309018b0ed2251a3a6c028c44743a70e8f0c8e3eebc78562628b39c6321da49129ed143bf054d3c896b01b69efda754378745f164081ecaf5102de75a94b868036d533a73baa871607ce309c67b72315d9b3ab4beb9d49c677696ba9c0b71a17053d7841cb216425234eb648cd9f24992b3065ea80b6cdd81eb8de9efabd6847a443705322fed1f5ee3096521acfdd89d8c30384ea029ab579575a30dad9a603cd126ed211f06f6af6db6806e6fa5c9a65c4af566ca09702775c035dfae43ade01a790b259f1e8dcaebe94530ff2f3950f380962e8205117712d2cd24d6e462a784eebf7719c3e4fd3ffd2dadeddb69452ca94920c4b056f0542056c42b1a9c44118580394734e29594c5b163f880299688102ecd22a98269c9327c3fa19f64dfa64537e3efb88b029e287c4bec378416cd6dab43256524aaccbe130371c065e97e1c676dc66c8821de9107539b00c10d5e8afd945c77e2f22243d25a5ac28b3b12c6848126b6d02c330ec8a4c87c374f75700aceb1e204c3f47cce36135441150480ba08cb30d340ce11bf7086305e8cc816934df6d7b1a58940307a161d459b67d306db5a100ba1197cb5a6badb5368628d84929a5945a91a453d24fd36f57bb3e9212e1a23ac00ff08db45be84908ba8361d8a725e50451d334a8c19d1ca21c3b3b3b56278532d25f33db30738e666d3d596ba9c41acb423d6dff3577aafabbbd45e0bb33e7f63601983b8f4ccd5a6badd5a27faaa6450f02fca06e04f26a4f3b97cff3fd1829cd14c8bbfa61d0f44af374d2b4d04392d534106807b4b3699aa669ee9bf3c42972422267ce39439f8302db83405f8258804020bb694eb82f9cd9dd7d341af96834f2d16814fa1887e338b90038f3a9a5118c39f557a4bf8f578297c3178457b8fdfcee310e8ce1170fc7b994125ba96e9069b3e6abc958cbdebfc4fde5a691052f14e90710ce63a40b5213d997ec83b2d5ac79bd5e2f51263596353e536b4dada9ffc54cd3361c4af886c36fa05fbde9deb9ecc836fbd6fb615f7b20a46cebbcd5b9cb8ed06f1ff2bce582790ff6212fde98300fe4f96bf3624d458245f90b2bcd1a0cc3b07e53eb83c129788565f1e7dc7cb8017e3a2d7b67c632e66cce3967ad3563b9aab173560d853557844cc5cccebe5ac998b56c9bfe5c2d8761f914de82005f702e7777b73ec353ec10809d53d9ad07b8fd1ffcfa4b36c482d249a97438a54ab11ce92fd51f74c23d256ecd8eb71bb6015c6dc5f2998f671384c32035213f0595d4b382363ed3b3b919913e9f824aa22bfb9ad8d7a73f85f504c2c01a4a2c0598801267715b0125c6e2ae522a9dfe4457e42e72918bdc5d4af728a5bb9472155acd0089254859c2ab0b287465b8c50f9f1789466e6f5a4f93651feca3d3caeea31d40a1ea7382a58fc17a21d0922c537a9a1f3cbc7cf4d72a1d3bf827c62f25571d4c43e3a4947e56aa101553e798708a9c90d0d951a18e546bedb576421b9bc9e5331a8b09daa08151ecf21c955fde35ceccf57061e397e0ce8dc364056862ebb5d0069d619d86693ed2306d837b0063a00dfc04a4d1dff34bf616b93ea08df92618d3a61e538fa9c7d46382a1d4a695eaf51228d812a3765093513b45ea1fa11ea3604cbb6cc196da6432b9641a357b66e618e3f6f97c3e1a56b396949e29f69503293a442e4ca2238403dccfe2e18bea0995cb353333bcb21f80fffd7da10a8acde56d021cc4859fc99fdd4d25cd97dd8eae21cd875d09880b4910af7c171cf874a5e75e09084b2ac977c1e173a5d743e8462f89f9b00957046beeeca0c340e6c2f2f3857fed758ff396bb3a559392e15ed2525c3d1da5a9dc7e0a9d2dec228dd343faa3f2ba3d537c46cbaaf63e035b652dcdb28d9f24127d299ad252b3476058be3a704287b8fddd3ad824e09836c2b49714d8cf76c13269b5a57cf5be7a2656fb52a7529de2b1bde6f556011748da1e6688542ab5558049dab78e2ac364955e29f35aa5f3a9ea71ab2855512ae34a3ac5a74eb9af9cf5d9c06a5ff295e79204a8bf5396739856e9f4474f3948c0d7fd01be384c4a29e5e7f3d9a4263729652a85615a4b8abbb8d04e51a8c4d128954afd7fbc726a446eacd43e8b544a23f22e559338c0f94eb63435530ace149c29f8806677107dee666aeeccd48dfe25edf297341b6c604883e98f6aad72cab490c9d765f97a0219c23959074f9ea3dbcfc32f8f704657da550d8013aa7780950e234061c23979328430fce18fcfd4a0fa78a218d8af58cc96159ff67d6badb5d28b5521387467222c1e3c582c168b050467e7ff5c3c50b55ead9e292e2a43704c3536455aad2cca90afd88fa2b3765e318d28a278611a5f56bbb64db778d552a59cf4b76afbb04928aafa4bd2308c04721430660b60f89086b11dbb5e0ef0c9303f1d5faa7d34073d48e36cdb5a2d6715a7689679acc3ad14b75a8474ac23596e89534eeab34ecfb8d473e1d56527fdf5ca354348b31c86b70879dc6a61f5f369b5a40cad58545bb7d8780d86611083281464ac66a3d369d6671650c8aeb0ac84fe411c4739cb50a896949e292eaff9b406855d39aa1cd491948e93168b97400cd3364cdb72dc733cc7dd861a4c43d6b45c0cf468fa178036ec601a5d9fd5a26d9af7fd386a8c76d450e5e46499bb9ce84009259e88c2891b181663d47070b49012eeeeee57c0acb0c46879d84192735c8b8cc1c2cdf02b5d93583a26b5703046f7835f8005234ca41507a3e5573e03a20623b4483c56ba1f407c4552a426b014f4909aa0225ef951cba9e557be24923246a72d2bde8f9695175e00809471e55da2acf968d9b6f22dde8f965f59d9b4ec1363ad2f23d6d24152dbc87e0267a41227b83ac1d509ae4e707582ab135cf9c94f30c624a3e73844fa13b18e2efea43f70924d2d6e38f85b3a48925ddf18bc45cf8f54b1d2e3b1c33929a5c42157fe46afac625831038508505e8ab48089107a4840704e4e45a07650291d5592283dad95932928d49c73ce15146301f2137066244407c15f705b582cf8094f0191e0acac8c45a146422c0f9f097923ea9544ee8d3c8ee10aebb7bf4635aa5152fe0d9f3b7c49dc3c69c585df851f5ec983511e1f49c520a29e3881abb5b2d0b9b21285155a402985144e1a6e7715495061450262860d70fe6d344c7fe45899d8d21fe0d9db229c4fa79328ad2a059caa39279cd0c79cb007be3edcc03ac0981d600c08204c7f152e7cc0981deb03df883f2f84e9c7b0158ebb01633421ac8cfcd5548591c197d20b73ce39e79c73ce39638c1c03164c27252f98e4cb9b35269fc1e12fcd1a13f7166318767aa669c29944bc3065ad96992fa7a49415e505d787084f4829250e0edcb4ec8381e0e83382624b8c339a2e87c1c171f9cc7431f45899b3a3d1880726564627d404050fbc3a4c7c4a29a5d86703651a886eac651f8c320f664cca478bc8cc31debf30b7b905d450bb7bce1a2131468e2c1e3c6acb3a8bc562b1582c1e735296ec0f159c625ea5544976964871f5d028ec10420fad7cc99f22996207fb8470b89ce7727cc605fe60f6b813576b475332521409a4296843724dac92af8985a4124dad7834b5d35fa7acdd70c0cb344553ce94a6344d2372228283835f96cf6611aceb250ee7e2345704ae68125b2b0b4bc7c2e170278f2b42c5a66692fefa59ba0e5e08636744ad8127415bd0d59afe6c86982a4e7f452a12fde5a0ea91aaa3eaaf698a77e62af5ecf2d5ca67688aa65634b5a2a9cfc634e5332ddfdcd2f50063e7da9991545236d3666727958a71a55d5420a594524a598428887cd658eb4dd337b9350c9b1e3f1faf9a0be8571e08c9762edbb33c1052e67cb38ce3be6f47e857b66e87b59fadf4b4e8afb8ec6879966ff1bc877e0cba4229a5b304a7b8e1b683242d7ea883a4acf3215e49435fd26c0749a10e85680d8528dd1a861a30c7c8cc912311b63462661e8de6ac02123d3e7e064ece39e76ccda003478f08e01516c2982a128944af39e784ac5231ffcf69844aadff1b0ec86197310ce341c352b9562a79b19b9a17145be29fe1842df12932e5affc212756764fece779d3f1f17e3009f39a5593c7e796e04b02b6e64620d65cd549759a939979524a55aa5a57ac28ad15209898d9d95128f7effbeffeba119be81dbc3c5eeeeeee2c11eb73160adad86a651484e97720976f5d0569b1963f3d7c589691af8c42dee6714a470623649ed6b10ea738c5aa98691a9bda1b14a9c73ad80d08231fb64c8a7138ceda1254dda83fbc5e4ff32c8d81f131bec73ae9639ec861fa716855346a118d6ab415382d512702be336ce167e8c2da16aee3b02c782c7481800b0d2c730b215ba369190ebd0e9e0fae72dd79caf5872de5ba6ba08fdd0c18d3cf2aff50e7c367f8b4713d22e9f5e8c027f6d8090c3d16862996bd53dcb9f09f5a86fb48d75cff1e52e35dd332d57d8799542dbb531da08d7ed9a1eae1836de00be1f736fff3777fcc9d5906296c7cf692bdaddaf8f3c5122538f821b320e4ae72ed9538f7dcdddd5dfe8be35e2f9fe127208c7c2452a2608c3c4215f2a1fcf9fdaa96e31bc992df5de9f3812ffd493d7ec118f93f54b9d2004aec9c06e0b15d9f30213934a912871c201e1b5f96aa49fe0f3c7c52d2ff7c868390df9531e0b806c6c8ef2b8314164544065f82607b3ac3fe18e7ce27d2df8400df0d0adb9f49f718234b1941b00996bf07dfc9dfe353c5f2df40d3dff4214b3e7a1461815cc8249a1e74cba14bdf9c6b3334b165b8dd636cade39dfee6d3cc2f72670f12771ab9f331afc4bddcf9d42b7df33bd19d3c5a66fe7cd10d1d251177dfbfb4cc7c9e256ceeb78ccff9bcc2a074cb74777777b7b7a33fd92c39763bfa93abee563afa9352d2f80c24f1c05d6e0d919fe386942fa57cf9523ee6554fcaa79e0c4f8f06c64819a4b0fd1ca5b4be566b77e82f3e2a4694cfe80061e2c71863dcf10163e2ef58cb990860041b1f55abb51cf71f9f238c10f66899f8f1695a264619637c0328b1d0c68de616852a666666f6e2064a82bda251cbb40c44c215af5baa01554c050b7994a072e33f840e1dbecf889c45567a37fc8d1e1c5d7f910c41b01fbf880a2b84d33967fd7cd605c95e73cf1edeec3f9f2c7bef3a93b2b3af9f75fd4c6c563a5b6a64e94e64f04594b2efeeee0e6d4ba10350430b5126b20379af45505878a794d86b5d10edb718b5879bf618a6691fbb8f97657fc363f7d1b28ebe562fdd814b42377a4d8610e4c20d87d07557065f644062fd678ce4c0489428515c3561e4c0bf1f068f80069cb909d409f544ca932a44c018428321519a70c3842541ec4b47e1297262c2102618c16c7cc301fd088c0fa30ff1c2cb176e35baf81dc46089ce0a0bcd245d36a4ec962e9f81d2957d01615a0be2f687b297105b9aa75286037efed6e8fc89641eb992c59a37aced4a29a564f98c74b1b61b8a70a9c070a467a4ca61fae433da14538733e9f299793a4917e6d5cfb6ae3708efa6fd3c61f1b5754e9a279fc95ea71796bdaaa6c1a0c2324cf5c15418a669a690165fa57df3f5d7b7f4dd0fdad864f81150e3d59bb7c437d0d1ae28acbb8cd3094b08ee04a90a42c8d4099d425fb445a5d02ade6ad1700e9803423f996aa89643dbe04e0eaaa22a6803ca50411b09f809b74e49cf94e6aa8dad42454555717a543593a85034458ff4e7de0aaa5a86777cf6f8ec998e831ed172401b4ea750eda8a88a1ee98ffe8c0fc751144d5115add57237373737ade8c34b7f257ae32faf7bf0d2235e838a18301a39c188eb5e11bfa1c4e6a203de1d2f3ce189205bd4d490848030fd44d880d6d09b1d7b5385d5810d50155551ca9d5a56549090a194550ea0654b9005dd59ce6245ac624f695d614bc418679c52c618a58c31ce39e78c5dcecb4fa553cb60224ca41146868c8ad55ab3958bca0b6444ab325696b9582d293d536c4c375c258b3c3b31dce05006aff526c51b1f43c88620a9dbc29698f5b133cf2cd1c96178e5331b54aa9d125495988b84ba1c3a78d0f805e0d72a6f89543b20949af2838140a0ad0126179402ab50ec93655996b158cc76d556885a7304af152c04dabe0bc99de88a382b272d761ec855ddd326bbf3c1aa17c3c6a990abb66278d16a68c1c69eabfa5c8eebc958b70402a94005f8c41e6883050615007aa8e4fe7ca66df4257bf06e58c5a2470dc3b28ee1575fde6a821b9ffdd3d53d96fe6e05b312b208ed102502c059f81373317902154970c26689677104215b7881080e5a6f4b81909a2350aa2304598111448e308408975a12a57472355cc84345183774210f15ae990422a0b0a8028522f50a52caf7cbff99bcb070bba15b2c1186eca0a08a0bbd9041163524febf3ccc60934b3bf1f04391cbffa365986d580709991c1e82546222d726aa76c01a4a2709b7c4463e1bf0f79771e15291465ce09881e438c133852b58c03385174e056f00055d64d1c51298d859024906615b38015cc8f3832eeee7429e1f4cb925fb7c67a98aeedc41746327e446a7fcd42bc58efe4026f71319446c8c0b79a09822041456c86062e9853c5038e9d931badc703473b3cb18239785600c3f44811059732fcb1f5f42c97ceb0d1e8764ae3907bdb588f1815c201973bbdfd06a6d19658d860c108946114689d576ef9594c225953e290ca4c380099754faa43060e2c6291d064c307b0c63e447204b74bb7b4b9cc1cdc6a08cc3f8f0236429e5d75fcb979c778f61cc7c384b40dcf83ea11c02074592ae22b52b6fa9e54a1fa8e0ca2757faa005051229a5940808c2054a8af0c1102c8860c8164e7edff7f2418921820bc24d3158389081611813381108006062c57384275b024705140a1704a7be48d2056b2f64f2051300f0035b2f64f285162d1c012e64f285155a0bc9ceeeeee2ee5177772641bdd4dd5dbadb3954a365e3852e1f4a794466f6cc27aec4aac4ea64f54c2a4889559fd19f0cadb87b3eba4ba2feecbc1d1a462ac1c2d287e5c0e1775a0718235f3e0c9c29318c7ce9f570ee952018d02bc12c5cf9256c65f30163e40fc009fbfd651f4c7e9552d69bb9f40fed41a06f4bd7953f821f7c23a194b279860ef99205a35c39e35fa62be341fc2cd36e13dd7299bb8b71993b17eece856977f67277322ed3e72e77d3cfa676b93b96cb2e527e772eb2bbcfe5eee667a01a4aeccc89311ab931c6085b9ae6fd68a2ff87f69b57778040dee4819d46be2495dc1823ebc6a7e9817de42d2eb75c78e1477b600c8d5b00ca60007e3caa97d128c140dcb4f69460b5da32d78640366ea01e1ed82e4f8f1f802516f4a1d77e7b6863031d9ce1c0280b3433fa0b81340bb9160f2fa81e10b9f17768996e1e82c3366c2ac2cd78a1819b31579a0bc2ab839bb106841bc3082efdb04911d3854d6600e572e7d21e8d2b638b9081839b4d86d3413df8addc951d5c7901844b450a91db03bd2288b77e36a1dc291dcb951d6c72c4eb6698263b17fab0490d86b8f45beeec3ef7889b659afc687003f5e30063e2d32e87fe62931ae4dc8c03d0e4fbc48ff14b5005e5c6520d57c62d551d182e7661124ab810c6c41f8013f6a53f8d651d263ed625517b0624967be030eacdb8fb48e3339e2947e4e1c1941b7f47e441dddcf82368191861105b4744134a27be6c7ea1a1659c75e3935baa2181d8ff62a253d4be95a133338d11f0652eb50df29b7b308d18e51320464a3d87704794d1d11f47af5d0e876187371a1e9141772f557f1f84da371cd1637f5dbd3d463abdc6dbd793641e4262bdcec82fd5fedcfd2574cb4e4a1c8450c6fecbdd0fb8118f1cc1440a29455481b38517435880a321c172830d164e2f6025710330a89015bc6a8de605175808480d1856c851b2049221568843a0e2b5828d0a2fba10a2f5a11221f810266402141e0223a45085138410851148bcd545930f155d5881799121b30a16b860ba9220388f13a9c9e34412975ec8e3c4e996ec574121744a3dea0e7bc94b7cf9eec3da6a2d46770f82796c37edd03321b8c121173e43bbc212c36fece0918196d11e7e8ece4147cb54aff4239a9c89a8748ed87c14aa990180000053150000200c080583e170402c1a525565f80114800c697c4a7a583a9ac843490ec3388aa290410611020c0180008091291aea0460d9467983b2904febfc26e0196c04c2d3bde7a334ee9b17a1e4fad0c985fbdbb80112816a1c8284e5c272ce3ec588f2b1b647c89dba1c176c444d079b79a97b67683c7c65d55da40e883675fa027517956b48b588b0c5523285b770eb13c832cc4e22593fa600061b5dfa219c5d3f0cbb997db857de44ef595df6ac32edf67aad28c3113bf25b89463f8ffe221890fb8ea3cf2c5008fd0cf2d80ead7e786c71ef48248cab6915c6216ab8706af5cc6dbf53dbc6382f3026dd8e3a62a883c459d65b5682c6e708411cf893958a1e82b4dfd72b84a0201ed998e76cf724ad8b154056c8bbbe7ea3706351cae3e31777f11af98a6accd858c9c40e879afa0ec586733b89267a06513f724e5b1d1d39184d54794b009e2d46c1c5f9580edf329a6ae247e8ec25496e2a16a384ac83413e514a0e47419224b39650d9dc5c552e30954ace86418b52f3b68b1d58761acee079276ffc6425be9ce10cbe0d4870306e9d4929fe90ca3def4463d23fbaed1317c59c340d2e858d633f135752aa24e10ca33caf0dba93d9efbdeb35f4ba42847146ac504aad116e9d4ad2780fc48b56b378a1a35661f9dcd09aa632ccddedd554dce4ca8672b09098fc10db86d3a1a10845f03dde5a59a0cb68c3f1681fd128c0d27ceb0939262e54fc4f48c9e53099b909dc04527c8440983afe68d93b847d3cb9417cbb37dd812d69a59590aaf9f1e450bad37a5fd0321b12079339eebca96e19312b21fcb552a606caaa3d59c72e36b6404b44dd8997457118c41e3fa3f01e4f0cd425926f0676170f421884b74db60cb37b08ccdf0cc0d0f25230bbe37d0bffacd668c140745fd905861a66562af4dc8d643f264aedb184dff11ff084c35351625bd5b383d472c3b990b4f01894980171558df57ce9049999fd84d08bfb54f183fb43a5d77e9226e0d5932d59fc2dca3aaf24ee4264bbf486a9b91a69de9a772ba1d63ce554af9a8174b0f558bc508ec38af46d6442cc85de4bc26c93284ad84fd539cd6996c573b373a7100506d4f15a68a742289f0591e83234b228a585f66c72916dde5d8a6636fc430c240c0517e170494a3c1cca873e605fdd423d53b17a0a6fe43959b8d51ae2595d182e5cdb171c08b03681b7d0f6057f49557c5ff028860309a6289b26ff324eabd4c886f42680234c56828a7657af4a078d8cbf64c8f525fd4398ef7286527136cef7e12c5da58faede6a534c48eb9978515090019f61fdd0248969dd82177885085dcdd91a55058309cfddf61a57513b581bfc0e09b8da92a3be153495f4f47151c1f5ebfea5daaeddc173b31150ae4d4f5598056382f77d8d9ac3ff4bd27c62e2b457f8b235371db07a8565615d174406323b62e46d051d107f200f6859c770e545ca73d8067e946531d0c928fb9398da1758e6ca8c5a8f0dea581b3aa3b44701f36e46abc08df8a430437e0912428406586dbaf7fc09f5929a9883f31c6128912a3410987cf9624fc9cb9b9f5002f1bfd71acadf44b4a687fe781df0d0aca6aaf8bf688ddf0f96563c03f97aa7f0270b1ed53d044f1aa6e012897f9f888fc7db6f64eeaaa4d2874b38069ab503c31d5175069004d748c8fa487e0c658a3d81537207e69d56a7a53cfdaece35b43c9f92bcb7e3eab7f60db0a61ab7a03d4399ca259eda45bcaa3d0a10373609843f5fade1f4d590266381070551a36efd141a487cf0589e2be1c70a815b74ed22436f338bcd025b6498f1eb3599e4f194cf5f9fd569c385b7e483b3de783837d060e358bdd58c5673a41fee383ffde288b9a50da285eded9b00383337920aa7bf29908ae6733e1f781bca788c845aff3767de3242cc5dd06a5e6d1cecf5c19843b7352c2c9ee9eeb6d629d88f424ca858025fc72a41a9d0ccd21168b54c383ea1c8e112fc10da9d8a9faea2e0eae41a76efc015aa5cc3fc422ab1da0b1cf7cb30fc362dbb8997a63080258e9c8146a1533e9ba3285fcce0b8c298c1da11eea464bda9dace4b18cb895e00fdec1246bbc7e6669b64a938d85e420c764029bb8de2123070c3bcb5daf8aef89ef8236019751be14f1cc5555873ce60ae9186e051a8b876d3bc4a5f98704e665526b68508d3573d72073dafcae94325930199060390030aad844dec86353fd5b6c03658463e5cc42eb18dbaab39afbb317ba2b2cb833e618c06e402a1622f731eb93d5189b56289974a532801cafde3c25067102e5d96bb01b4cd505453d8c5862baeee4deb438b9a26babb443910e0660325eed7a588e6e2d372a22859e45aea1ec88d28c90af9d8eeeb29e88659489737fa42372d378a18cf538482c03fb7cc0de9eefef62ed2dc60a3020ca3dde611cf320903000d2c890c8c3293d18d39e90ae19fd60ac8a1f9fecf1a64a29f97ef0b1823ae871557f1cdef3a894d025194c038608a185f41df53a240f82b71c8197644b5e3515612f9ebc9a83bf64796934aca3f3aad4b70d38ab9c9c729d87ce1ca163276768d8e7fca9dd094e40114d74a61a2120e9f704198d03daed37e4590318844ae1e71820212b8b9cdc1ead1ba3375470ac2708e8d06908e201cf81c5fab0a12abf96845160b4714d74c4b9f6fb7dca39f9b06400b5b115c1fddd1067de2b5ca15c232b6436b794eaf1453a86cb4a24b00cfcbe238103ad504ec78175e6fbc33c2a68e31b1883b0094905e7a364eff0f2de780ab7f2823e540614039025d7ec44760d745528e0924cbda89730016c751c01a2c68c8e226ffab9124d74e7a236b593e3371c078e41dbf0736b7c8b592259c69ccc5ead354cc5dd21da664546012e8a25d58c6fdf98af91f489cf147d01eb410f3b25452e1ca5693008f251317a6466244179466f1c835335e17746bec73c2b532c41f0862b6a2e5f6cd6538fd82ea08d835603a8cb93ce1bd757cd3c74795e6545dcad2d0dab93c67c709218b02fcd05330e1608838f69485764f20e56feed82c960c3d8ce7da3be4f825622f2b3c53e136e5c717d96ab87847eecf087fc0530d32f411b55a4405b5bb593a4350bb31dce52072fb930f4411fdb3495051c23d731c7b0a4dc83a380e7f89bd7426c6d0c3dbff3668736d2772c07adc07123f153999127bbc9ef61c55e390a14b3f818ccaea2afc7d2dd2cf309fe360fe6611ee91a503a01dfd1346bdf963af21b26928e1dc6bac37a2c13404c860c5a2254bc77892c318db091071a7e0ff182987d12c8a45a2e882ea2c32315011c881d1053d2371ddbeac650a27a93275a814e17a2b748ce36a41e2455be5ce520f2d528e61346a85b711fa1d9efddf2060f8537c7e8bcdb2b82b1a5f00a756bff4dac59197f378ba4c355e28529fbd519dabaff78bca9da0518a1cabcd5453b63cd872d6619b1cec14f8b5c78b6d0ca68f9255319c3651068ddf0e355f6942ff94b58b7cb341f24fc193b52e1e9b3eeb004d536af679e06f4364c7b0e3a2bb71cdb6e62824f05a50575055911445d60759c60b2e772ac43a3ba359018eeedd89a1e813f4115a06ebd7e271250a3a42486cfd5a38f787aee887e2836108cb386ffec969d18b05dd54b313c498366d842baa95ef14fcff7f9a7078b06fb04d046b4b097e2a9cdec85eaf90f18888ea54c190755b368af87dde37511d196e26de56778d8f14478f25edf4c90743885846cdc681a21611882684803ded7d6de906e5a7114ed4f3a99b3c7f77fbbc3156ab8f47435dc811200b09bda1ee4031558f42d86f77e0f74d60679191cbd709f52385e4b737d4def9c8c6daa858efdc93582171b1353ead3c7555237c56bd116afa105d63023ad6e217eb27f1640b24d966d82d4f38594c0dd54ad10ccc44e7511cb8947cbc84dcd74a7de36b88b964f6aab5110730d919f1b2d3ebc7f7d15c14e47414ec691a8140061d106fe85c73014bfe2768b4920ad03d70eea09101c2a1ee66d474185868fd0c556334c9ea8076ee5f089955367aa38d45a4a7ef3969a4e1aa4c14b1831eb58920508752b231daa40a0ce4dacecabbcfbf1812bfffe4966d0ec8489b675b36f20df56198d4f49299676e814d5a63e0a8b6d40284a9c721d587dacc9131d8e69cd8fc04f05eec7784f3589a56ba740f196d6ae47d546c3449e400338a69f97d2b3e1eccdd2fc900aca6d4ab2da52f40410ebfdd10d843effb23bdc6aafe2b24aa02d7de4c910d49469e333a039cac2e4f10baea7951003d3e49368614b004ab626b269175e4923d420d8450f8ff7c4beda89c34e6d613b27a096e899e0a0ccdb31e96e18b30882f4ce572b7de49ee2a7ca467dd80ea4962b284e250cc3ae8d30d1e9ecb81ad203dad7b5d42ac025a6a740d518c0eec89e0b4677a7de84e0aaa0c961f09f01ad3d971cc3d6f12176f02feb1987890230762709043befc0398122e92002e25c042b893b24ae81b38db9fa8fec5b7b499af1e7682142d691254176d859a4cc11c392cb03f347c70969a8952c063e70d5532d7ce648eb9f6143bf44fcef943408f8be3582baa47a49884db00ecd430c5608cf5f49dbd04c78aba6296f95aff815f1a9cd8278ea6db9b30c339c78e24a38887dfa1dfa441bb5551fd1a98a1300006a31c1c6ace295a0b1a23541f985e72b1e17b069f2d12b98ea137018704025fc0fa2b049c083c16801088553322c6f5d5daef10a95ea205b3601d093b8bb36843eb34dbbcaa962ae1435801bf7d2e6f758740cc83a1416f7ebe0efd73dd1050d09cea76c4a32b662328f0df4d3f983ead9a91c64651e6301dab8d5eb4ad0125641ef182493727887c7bbaaa0ad1e61b0fec6ef191093e0d25fcb76b25e463e7231103bce89d4def3b9639e3184a0704f7c8b5041ec52a226cd9e0ca3d6c18ff791e6814bf145d8119e50e2e93de4011c7505eb5ee6c00ae008827ad3f039a79da37e881e6cd36b33a3188ae4621fd2b9370cccbc8585d1a415b096c58f220360ff1eafc3d2967e0fc67ddeb1a41f97b1c5aca11017a46a5bebac4a664e1872cc7e012214c0f639b417116a2032d4d3b1765b5677bfbcd01be2d07f0f35b55d430875181d7fd86642c31a14d641026e6bdc69791b456196622e483b9375d6120c7497b77924a643644d01c361b6f4d6a8ea4cfdf80f470e6aa542e2a8b3b7aa09468cc6b913feba8061f6fc046ce0fff5b49ed1bd76018a57a425ac080a671a94af5d3609d1712b5c5bdacd309ba649577c13b2fce06c5ecc99ab1be85eeb99dadb576cc2f111da3dc50fd0fa3a2698bd5146c7212f28990d48a0d09793c74cf4617c2a38d97c1316cc14e1fc1797e810f3e6469f02100364619ae7ccf9ff572133139cc7d0185ae931777736d7885ba3727f2d20a40ee70a913a146b624641803a09e04d0ab22f6094ee646ea79429dc3a979ddda6e37d3da1e5b3bd924a38b143c4de5b031dcb96f4c20610cf2238de50b0fb193bfe711350e3b7f3bf9db20364f40dd5e9a84fd1d701663a27643b479bfefaf8d8125a81a223bcbbc4a5bb0d28e33a220b933022be68ab607202faaf4a92cb2016030fd9bd7edab42a96b65b69abf1bfb094385deada4e3e9cf1d95b888020fd431c8697a0554d06383400862d6c1dfe131de36b023b100f4276550d0435c6b8a79715c2988e52bb044f610a38bbb523ef45814f6532aafb8c6476142e022d2f624aaca5dd1f894e0803a0b917ca3a0a2f0417a4546cdcd4db3e7e85c4250c8ae19628e477778c3d8a69ac1e364b344e4d9601ed11479be4660b9d7410f63269b098dcdc6ce8bab58b885b53a73f5416abb1a3a939395f5e509374c5aa48c8a8b082b37b010098ed5014145e9ac20a45c8b054a312247885b688bbcbd1e0d719fc5dcfeb0cb70f83604b93679b30020536de60349883b00e603a68c111962b0fe2ea7e5cc304c46917f1d429b56f9fa56963d4ccd32787d5b7501070c30d55a6c45aa86ce00deef09027fcac06dbee815ce3a9e99b1ae1a7694bab888a4e387cb8cf690c5bf9e68107aa463df89140d3c52621d65d287bcd8f165d248bbc7cf88979944e18055006d1c5a6032642ad21bb2082669231f402cefedaa2fa482dde545b9d05c9ab574fe0b91ef175a1debcf91e505750be46b73cb1cf092d76cd4a348d32d862f4b7957c8500fb62f9c0e3788b701e72783e385726fe64ecfef89bec4e9ce6da343adae7494f5b64e3ba7686d3f19405a386aab2f532eba69f2cb64a7d4e4eb2efee7701a2628ca6afdf731b57c34433c4c245ea00e35f94a6e2a45c64d4f19095a28549003c23c93cc9dd07826622220b3861122869fd2d35ce509f173f531b4b2951d0762e835acf3b29b65026cd262a2e6ff7504c36877f8b6328c21e7db205b7be32845b1bdae3b5608662b30f2f460e2f592fa65e2cd1de704a620541e5b6f07752f56c926b1acda80324dbf4a49bc00e586a825b611637f84a02ca54b1050a0850ea1844bbba2a91b5a2fd38f41acc096a0a01f1a2d23431d3672a5f081089d85bda617b88edaf19f1917463f70a17609c411b984695a6a8fa0bb40ec7a4066a53a244a97f7601a67878532529bee72f4303722b93abbd9668c166b74301dfc0f6ac7a34ec9fb0d91189d443ead0a1e70a3cd4a3be90f3e5fee90fa44aa8a428d9b54ded9c3aeeeed32529fc10257a7e3c07d8124406c84c7b4ecd35b17f059c71dd043bc51b52f709ab62cb8be78809b9b9160f288de673a6852c45ede1cb4f8c486e69a03ed8ed78b351da63fb6198cdbd2e4e8d7bd2c16d7273787407f3de3c7b0de6bc79c076727040b0de739ce0ceda12c606fc6acffc3c99150cf1f638c997fd814551cd1bd9ae88e36df04a41f84624d84bd585032e0c1653c12e40826e98914246c35fce0c3c5a39208dd6a3ff2154bf6f50f0b1461045fb9ddb2ffd0e2d6d71cbae17a66b6f9cbf13ef8e4fda225b397ec00fdb1d5a7f9a020b612f909c956bf0af0c00a843fefe71b3b7c991c1c8249ff3be931aaa0e23064dc9aac8581ed2c4283b120c19930ea06af212b0bbd976c8b342f376cba5183c646168f30f3652ecead575f240a9843e50e65e8d9adb255c559dbda1e1f823e2d2de9af96517b45183e2b365caab7ee19a3e3b89c650c0a9f09cd036347e162972238681a199f09c70684f85850ac46811e2957c68eab3cfdcb52ec261457f4c9a0215bb389484df6d4996691109c39e97095f405a446cd904501c9f9bcdb2fcbea1d5d9b33e8c6d370a29fc88da9f5081ba23817f0b5063d0da6ebe85e3b87918de4509489d5cc744014dd46c69cbb2eafc26f38168bb9514ea01b41917e7c159cbbf8821d66a43c8eb2829e81ec129c78eafb29c9e1e26396f5ddc7a1b90519d3398687483d3c8d927fa743ca46021ff8148e49432564be8982559ada0a6a09465d78f38adec0151ada6b940cf559a1c8616239c0ee25e504e01800b867da3cda9ec44b48def3cf690b0f12a4a73e5b30b775ecde047c8c45c7227e623c127747af099827ac0727aef7cafbfa09c4f98522e4cd77308032bda3fa7924e78adb19c84a050a2f5f81b6cbaf7f2110d02de469878bc7e338d7209f517eab3c640484b02ca687de4c26f59e106ae10cee5df03ba63f7902026a85fb0989ebc6afd2603a038b9eef6d4e74ba328f436bdfc863091dd96f31840f6011b66f818b8e557c4b59f4148d2199465aadb2f27c8462b4de7f18425e0236edbdb5d47bf0c9a05db33c3e446082d79cb099643ff25424a281fe68b80c0e5dd92f8b092598ff64dcb11278e8695fd00bc87c0b92191c8af78ed456161f5eded78e3cb7cdd5aaa44c430da9609054e6b440758ee049272b7546eead3cbd3f0395d65f308374091b04b93f33540f618ca38daacdf28c2ddfc4670d67176d401187329472ed1086095813e1877c2b7ad884172ff861362f543a5fdc9a3c9b1bacd0b3e1646d9c7085d3262a23ba5735e7937816b09348e541412d96140b6260963935d208ec44d9cb9797cfff370a8110665adffafe2ca8db374d05807384988edec03ca7fa46dbb35ad224e807e23290a45b66e89d5b591ed85612c930cc20ab2ad91f8b59503a171e1d7a39124d3b416e879eb678c67ed30a3e36bdd361f69773d4e266a97e37bea83515f01382b3c7c706f57f1e55ca86fe0e02b644baeaaad8231f3c01c388962faa70075827b803120d740b8840cad7c912a716bf7bac0f8c24ca910e983350db503ef9513cf54722bf7ddd14a9370a3db626b526745cbd043cf584f202b23c74f429eaa6787c87a5a0a159a00f42d7e860e3262e9c7738c3f50161f71fd9ea217b1ca22179642c4449794d1455cd63d7265625572d9fe9038df1800c508a7f905714745a8873e62d486eb734c483ad87bcb260b31ef910cdf8ea8011514932bc88f557140bd192b90200f73a009f2c61a79c8e38cb2c4f9ebbb3d46177a2eac525c6ad938d2a520155e58b70070fb48ed59c0261dbe0ca20201015098c381d927eac439b89024207b1a51e19608b25949b26053ed935d310b11d498a9b5226ad64ebb25f501ba9112df865d2b1d85d730c7fa29a859420ba89241a190f75078470f97c301f89f3149c758665b1643fd63661261b32af24c881ee3b207d4e622ffdcbe3cd92069aa498c5d03c4ed63e3e08c2e173a4a7237da87006a0944af621682aaecd4aac43586341cf7f32d7620b84675da492ab221bbb4daeaa15c9360ea120f4dd62a56c455cd936f7486c6b5c6d26ddbc28207e9f968db6fc5300ac6aaaa9409f225b8883eee31a5abc8ca56f76ec105be873dea6d63c107dc9d49deac8acef754bd34e1261d638a1969a00bee0b12ae61927c3abfb835b40cc1a0a1ea313d9e5f222714d4dfa590996635e474175982f9a8951e16068e169b631d39f4b8b32834daa313e98b5b8d8c9fd02bdf94f18bffa1fc4bc805e3e497f4fe9948458ec8f6928d301a6420ef2df53526a9953531cac72724d9bbf58309577fa00232cc3a0bb32c68247d90aedf36433ee1dbfbfc6cb07d8bdb13fd73c6a83798822c749b703870913cde7c52215a386ee54c3bc7d8463328fd85e228e806fb9fe444b2e07ed22de1668c2e2ca15e45a3bd292d00e1162906286551f614c4a0aa3fafffe2b8cf6c7c52db5edd91d1f44aa84c90047abf6073f752086321f076af54d1e74254437abcf6ba29a353bf5899cda58217132239603f25e386a8458b8351901f5a235d4089a33f49feaa1624508c70832831bc7a1136c85a7b920d71ca2e83c37a2aff6ee3c2043f5069c55deddbd7a05d663f6931f96bdeab204f2dc7a03b2ec7045a991455a0fe9763165225e9fc9457783d76de1fc8370451124ed1cf17dcc1536e3d024bc8e00a8d28ff4b86bb9e091c7becff6461e852427d70fcae017d04c477befe635d211760b7f3f15c696ce5f3b62f35771e447f4bfff255564e3d188e2067c78d58a9e59ebcea6b88d120809e1632ad65879aac6a32bb4ab82183055df7a705923650f74b9733d7add2e83ab3f49878c95d16d9d399d8d4a1171c3c347441b5f87fbeff8e30fa8f661545ebde4d3bdf26e74977293ca7a40839b70d218ab6b186c807eabccc9adca2b2f32a92cc4f874add26b1590a651653fc11b7b2b2356d9a6dd605890329f9fdb53dd10e8705a898897c111e854959776fa40f5e4404d23317a0c3cc98aa5da7085f0b98e429c8bc71cc27e3d65a19d02b45d1c02a0dd75dd41519b3ee9e7c2786782cc5aca08f7bcad5fdeb3d5358b0937a009a8968bb8f356a3099d617a297345051d2862bdd2e3e50ea49b35c704826e6df66b01340bc7daa063d9419f2678f76aefc49fb5a9acfe726a9033fe4ab60387ca6ccafef057e2424a9369fda8f37bf39ef2f4bc052a210dde98984854ac537aa1af90dcae8901cd5b449b5c512643cb5b5b571abaa0faf1f0b0a0d33221e6848250501cc76f781487c53792a1b5fd842ad1854a20ad23f6d14a3e4350d90ead50549a6f810951436e8e0e2ee768469d6fc755028981a8028515f4e04fd151113c374dc0fc05ee8c0c069d718823d697b217b6c43d3049827073cfaacaa0e4e4ea352417387898b67f119d39d55f112d2a0099d27177dde4a4a82a2f1104f21f876ba5fa4ec3e7134121949f20ccd275e2073ba9716fcba86e730413add6521056ca1d75ab591c2ccdd8544dcf935775f0c543fafb9d743eb9fec265198308947bc086e26322ee1da8a326ef1fdc06e473ea474b99dd0c4fe6acc1f6e0bdd7f6c3a4c995274bdf14042ea6cf183b2868196941b5604df3ce0074683a028bc2f5cb10f82c2ffede9199e19ef0a5a859268c669d382b56957b5a7bcd4166e5a33fd23838d5bdf69e92381917907a086dee012d7b33a438acc5d028e20a9ea7dfac8330f8d583542f1d71becdc435f1e09cc368de6627c9e15de108f62a7a935433f4fd3f48275bd76da9ccd9b038ce0c92c9bedbc5d045e0fb68d1adead55528d5945d67cc055408e6e655cc5eda2a90ffd9bdf8a274b2926783a144b35a11c79b550f7fd764c871bb9758fb952d432ad3cb303475ee23b639d414326d7e52c23191413137211af8f2aba06a6d23624673c588d0b1efab1a57551e25084331467a9b597bcbd3144317da2f494c65be74ed8a421514a14533bcd064373fc98e32176112681e56d3c4339f1ca2d6dff41741369fea9f3295048331589acc73c0d80e1519d5f762c9bcae6636d83ca6b73a11312e9bc39a79e5e13b012fe098d23f158429e6ca075bde090999b17426bfc7dd3877f6caa5749987a51b34c3ff158c4cba94d40c023daa43a85993da192e3462197ba98d031a69d6a4d25e7cc17c2864aae8f8d6b70d932bd17e473a1db8d2ff69d061b9e414bbbd948916d6b99446416095818d777251e9278fc2f2b945c53137353451ae228fbaee994cf9a765788fff8372c4e31051017fc9f2e242627ad151f5a3b7bd6fdd9ef92eed2803e29e07c9a48ad750b665a13105948040af283e02ec2008685a4d6dd1c31fa6b192c0e60d9c94ed0dfda036e8b51210ecd3430fb9ee4c7dafd43bea7d9c9166e2eacd3fa9ad208b3d07443428104e8fde038b6eb73feca40591344d680482c394f13d2866c26869e5ad0d3c35e2678bb0b0d3d179de48e467d1a5f8a447616368f578ec173855f66c0602d809ead27679e92da1bd551d34a8f6e244515aa9ff75283ddfe548a523d1d2d152fd8eb8edc5282985f79d83597e90691c181fa9da520b45d1b60e828d27afb825346e782f7a505ddd8ae1edf9cf01dd6cb00248bb017cf925d5077ed09aa2d3629bd036f8e59f6265a9388f9c7b2922719704aaf7a7c1e0514e9616cc1726131d2b35bb169bf1faebbc2beaeaf00332ef87a6be7df61badd220a6eb57d0b83d2e1055d6b427715fa9fc2bb010e46555ac0621ee40a68812744bb55491f8ab83761ea262ef95c11351c21804f985b9378ce47362165c08252485f0c6760e53a93d7e1d25a8e47cf980a740529c2ea2db5085b47a76480a0a3561975b09cd4d880543956d8b858a8fd94542e8987c2c2910e95cd5934cef28c45afaf77c4c72cc279156c843ba7e04b39867e5d2879fb6e5cde933049bf8e816c59199869ee9095eeae0d16e5bd1cab271f5e36b0ca68ecf8a537562176496431ea679919177d0567d572ce24956d1ecd46494e103098793931a04230c1e7369bd59e6188d8ce885d228f6f34b1ed0cf89a18170f10410ebc23204ba2f85a5a95b88afb43bcf97906a590fd90fbb563433fee7e00091a4739c3ae9f62a582da1f13569367403f1b4ba9c8221f062d82258b16cf17f220f5f7a1285a2efe10e66dc95d63dc1078937fbcf6f3027b8248a8d6b285d3bf8ea73abd7346b304a8448c7ad630b53f74a64b18157d25e11e2f568012d7c971681f0a6f00fd3c0389f58087e435cb306775dea67c76e1c1c15563194a058c9bf3973dd61eec114d6052da2af87dc51dfef0c133e031800feead75736aba37e5c903c56580ede5819d3c209ee3cd9258d603aeff445840edef7d39e1c6ca8dc3c0408369b033e628fb2c98d8da70f0642190c76dd52ea0c6eefcea4f13010ec565bdb9a9e326175da610711f020d0e1dc8c02c51f815349de92dfcc6d6dec147a3093a5276ace1c202532dcf2d4f660e36cd0dd330c02b0f21457870fc21a8ecd1f809dcfa9b5003f80e2d46b3fcefdfaf33e0013b6c645ce3d0923511fc474349143c63948d9d034d0d2770493899c0c8b047efa770da5da65201e8f0a79c774fc8cb16c86e6363b7da1d8c2a71639b6a217ac1839c9c1200e620d0cd098de15310778fd4a464c3d337772b90fd0aa01d3d607489bde3eed4a985309e800d9d667d04e5fa131f0860ec83fbe06fa690c58f47027e50ff93331f8e1ace764cb251367d8749f7e1a44716cc00a814456812a4636055ff5dd314dec09877241e3b18051f3d3df6782239b425a67c794d692d2455bfda9806906d1294d235b780325381181a62a800e8a2e0587dc045c01ea55d7ffa5fc0250cfc98c022d4b683c403d71c831185e6b3dd1b5af5e3ff5d39ffaa409b741554791a29fbe9c8fd177b1563fbd6dc054e250ffeeec40dd4a9cc6030518fe233298de21830be25c3a06f500f55ccda2bb8d6d6a02a81f2b656f7260302f1a855e7ef9497f784b93960415b6bfb5a4fef2cb621777fdc98667d11aaf8501019b0f286ac2445f68d269d1194568b04739803b95748ccd12a419fe8f758619c37245191c7dbe3fda95898e95db0f48ba9b2ab5610c06fc93ca9f3113f9a7bba82b66135fa68583dd4612c2b9f5b940846026f960708bce2ffdd8379b9f8807166190dbb7660b190dcc40f48c88d692232a34587c7b3628d96d11b76a28206a5e5bb83bf92e78132e6c0638e75634037c68fbb6efd401c1e9640f59fa3b0b2a20dd9b5bd49d7a49183301e5398b5054097fb77e76bccd90500194e115fdab6149d042ff9e39f226a07f915dcb102ad71302708b9d7c93d004278ae7710dc8edb87553449417f91177fc87e2ddbc8dc0c57b621ac8ca090346dc1b82b55b2651f8f9c58403b8ac565cfddb251bbec03ca29219656a4fd71cf69cd3566b1849132f3ef3bee694e35afe1954865d7668d32d6156cff02f1b27bd66f6808e62c047f46644967163146b2f1f0bcf37d4150588cdccdeb1812ff84616c66fd8ad959205c5355588aa9ca9f858260dc97486ba49c5d3a7f037b26fcbeacaea0da50e3df6ec22343927a59b33244f742674216b6d07b3a566e89f464e0bdb09969a61d57d45d4360c19a3584d1af9966e9ec998795869fa3d8b3649c6eef73a993a427c3e73d6781408eb9b0350f8ae5f7b128b65aba9f919ce663febee32662c54ac456ad39f33f490253b7d51fc07fb12db9175845672e28b56000019a2d5073f788a81199d2a14568209bbf7cae0acd453424d8e9ccb86d6c48c7d9367da22ab919af568d9652b86f6364aa5b17afdd25e89f8148b4b0317a43d9bac8eac7ac692d92c106414edb54e2849a94ee84699847447501e9bc85f1929f713bed11b631a371ab617856eaaf956bfb7849e813a387356ab04c8337d9e308cc1028c61f247ca4978e765a4d45f1a9d5bbd1ef4732078896181eef3aa228e75158a16458f94fa01e898ca2acf863fea4b04d72dc1bf7307dd44a45f15448e88dd4d345de3faa407a4aa345ad4f03029a100fc57449e79563f251f31ae8d6eea9e8288079355cab8be1636ac18100a0a481f131a7a6a3b604e7e1d5f9771a79fc74d51307b9fa54917b73d5ab51b3f341fdbde7fde3c84ddb91a01d984770e2535b088035726ff9f343b9bee032611b71fe37aa49f93d72d8aacfb2033ae4f7ade07e123fbd5936bcd7a334242cf367ea0856db0da45cb10cc9f45a58921365f9984a8f40dba3eab6bfc6088c4fac9633956103db49b4460a41a74f4931dd49e11427a748dc19124008d1fa8e5c11942a8fae3d8c60f9e4f49cee087da91ac0493866fd9dcb831512d67341228e2c3c05c3f4b7474bbc5b8a23868e093842b0957dd9bc76f725ff3c404f62192c836d2ba399114b03066c2c4f1836555a026aa036ab52668878d4c098970725bf9cd6b426be688f8413a4179040e8acd55adc6f7315b68620bfd5d71517f708a1b008813371fc071fe8a602a2a4fe742052f408aee6040fc447e1d88782560b3e519e61c654ff3134f421b2d4d010eb3ba80bd3dd09b738441c0c8058e8334f821934c493ea082e93465191d4a3364441866d3caccf7e18e8d646f1a74bbfdca0d73bcf3bdea4055f348741eb99f0e2034e256a17341c532cc9f8e57118e9c699c8cb7986f2e87c643aa77476a1dc42ee11ccc4161974e92abf8ce43a0b93712db546c8abc6905cbda8a5cb3e457e554dec432862da0b93de90147cbb081d16cae4587dee40fed602107cea1fbae76ec068ac5392a639cb483a4741f34a1f65386d48f21f3d5287e6bdd614c02a336c779209104919915ecb905cf97932baf98d70581ac956a56dd12cea85176235d398b3766cabe42528d04e12c46a58fb6523a4c9154873b79269264e8e4d0ab1609d0129a793fd5bc0c77963ddc7bf452dee269b4c7cf1885cc344c83810e4e27e4175212f440e34aedf45432d2d7798d6d18b653dd2418182c927be309ac794a0133d0476530379531421ebc846cbac95a8bd4422ccc0f903cd71331e9e09b1e1c0889a759c6e39ee57940e66f855acc3b1a3bb9520045bb166bb235756035e2f978865daf5e97ce98838d3b9a4d9e266eefd1c3c92705a2f71d17f51a9ae210f4d4297fae7914ec2b02cd7b8b77daac58f612d8745fc33a4ea88525e282c7972018bbf846ddc0e85a76ccf2ca35395010cfeee605aeffdf5ae6ce013aa29fddca07e5a956ba36eed58fa09291f8e824b932c6bd63460ebc6d3dfbb015f3468707bfdf93592d486ed8410b67259e4411ffe64122441cc2453c587ecdbbb2a45ec938d94373f4944cbb10e2f83682ceab71587fbfc9e028825eb254fa9c4eb91359e2eb440144d095475038dbc5179d788a773b9090f88f73cae85a72d4b95e251f13d001d6beefaebe1afa8030902ae32164d076382b61da7b45bd58b1b559281105ee8fee296af109d03e0fb2af88b2883cb32c65803c61fe421fc3953c663db0004f06db246502ebb20787325e96fefa153573a10d71e418b291ed60ed2da2e210f1e0926ad31613db1327b29d119d800b8b3e0e1b167d893b4ad0d1b61576e94d1dfd82a76c9313dfe6a5754db4150c96786b6f68a245d03e2f2ff010805eb34069c33fa440a31255f1349036950491f2cc9405f66545a61e550c53589fc95d821bc7ec0ef18bc0b19e2a89937dab7fd485d9d5e2459bba856f55adc1a95d2e2501f64dacd735886c9f49b3d162a9e54a69edc9a830c90978a7bcaa4fc4bd64acdf2ec27bf609e477a436c3860e8864dcde6b4083561a34c4c3a1c15e84150e47296c759a98c22c9bb3afbd4959e8a0971cda3a292b0978e27708f4fabf39474f1f23ff8334db61b75615e7d064f5330bf116af75aeb36400ad9c90258f35b19bd3886b758995bbd13bda2adca09a2cb49c0c94039bb78c6c9e80098dcfcb51cfb9637abfaf8264ab1e6084c478b078516a1cd206d4624d635dd7681011dffdd56ad744c681524b4fca122f67e3c6a835b96c45b68ed2b1829dea19f06516c53a656eab42fefb519e678c3914ae1d2a182dfb64a6d68849885e7a868c1767fccab746ac59984944df2a2bf150a11813faab51449353c40aab8dfbbb60fd9c2b25f0151f30e8126c457af624231237e6eadef4899be0c83d607344565071ae07f10ad71fb7522a913010b5326e8c63a916ee56f33615752e28e0d838b5348a7f783be6fe5d0aae1934f5ee9d350c20ccfe01186218ad32c79fdb104816c3bc316b6207747dc0509c7a125f79e3ab0340a8f39fab610eb4b7dc8eb1e5c8e590c05b45977d60be6e16e6b02e44b08a08caadadbee1ad5f5bfb756b8e414a3b226c1443c4a5182e81cf70be106db15fdd7cc31d382aa6373159500b1c6725634016fe64aedd105f28d0fcce808f2d85d3cb2e55a057adc8a2f472617aabfb2ed0cb04c4431c6a5d6eb5d1aeec0614225c98d2fcefe2a6f9570cde76038d9c603aad60caf84fbc8d09e1d8cb865b386acd5f782832389cf0c3a58049862a6ad064397425affac3df2dfd563d49a20e62632b9cbbbdd03265870a308e1eb18c3ba8492e96ea7918352191dad6756034232496fc7b983a51d3d66cc194c5670eca390650db172792a93fd38358d805218fc25331baec9cefccd05dcf0497e73bb35fc88c5946f2681de1147901b68ddbb9ea47002e91dd07a4519ec80b4dc9ef4d1a5108c7167367d16ca4e85f5ad60ce91190f2f1151c83a594b5a05cc61ff6654e3bddc64b61ba04f4883096085a879b26fb029017675c85c5fd73e193976c2f767fd8bec2666843ed8285f7f2fe1878f70fcc58c679d49629ba64046d2e8276b79cc604ddd66acb5b93787a3bc7deb86eeb753d208e46cc477c8e1f3ce9122926c1e512c8a36f2f6360014219296c4d4abf14856990aa6445ca46cdd64a167647657af9c1ca16d7d07fb8697f91f601bd58c66e2a89d188d10937b3995b30a405a29a9d3e26723fd2008241cc977d2f623025207fa72bc1cadcb6ada1c27494677a4501c1806e42f5ee1a4406f262aeff523200e9545b57832a4528c3f1d6ce71b1ea938e3312eca0b8a7e081ed627e51151ef63fb15b3f53b23cb4084e195c208a6d3dc574c09676539c88bbb1a260d8878c8e27cb07d6720dc00f278d28573b06c0c87a2c7091b20e846404416b7b5754fc9040d6d2ecc5f86a2342d0d0e9d2c41350dae9ae1279835c0a144f44cba8131ee08b781e93b7853a39c1b37bf1ef51ffee02f19a21dac073c13380cbce2cfe66c6d674af93f09ccf9380c467dcd51802b81b1a216e4900326ffe626315e033f84f53c1dba5a9ee7c04cf520f9c1d2b16585ff6dddfdf20eaed901446c9beaea917abca42667e466f0ed856c2e34bd29e29bb46fda244d2fca896b93854be58932e511581549bcfbe21df3f477b6c4ef0519d826a19193c2fb5b19b77788f6ec429ef255417ba1914847d9caab1be74d3d641c8b4a5395772aff88dd03baa7a5166c1ee50597ac9a26a82303d91fe36084241f189db20cc8476887118a4366f0b048a8aba5d90b4fbcc2c4b2b187d9cbbe2e0df5f38d7c6b8714541d629f054cb16b3a14e6de8583fe0f1bc3ad61e669c1ca70612c1fd22a9644c3bee1d8520cc75b92637f248438ecb50c175dd2ff2c9eda23d3d5fcb8790bd16521aea907e6c5a3d76f152585da2d0c175f7fa34bf0bd9a73b3277fb6fd852dae2c91468d494799275d8f950d2913ff5c387b3937d2bb31e4efd357cf8793fa9c7aa36b83d58381935ff83d84089fef8e9cd1e0cb1f129576b22e35b8c61f10bb5b08fd57066d05e654d1a6e97a8e17a2aaa1bea3a175540d904060a5ad7f5561c23a061fdd1ecf6e864a7e170ca91fc2f23a7a8213969deb8457193be875e399bd2196ad57ca158172d1714f2de6857280e5e2ea8ab3a46cab7300817ff0803602a5fce825ce88b2f7c51a64a8b0e1c87d504c741f8f599d51d474baed1bfc994501504a2548655dd652aceb38858bdffff7499d53cc08d3baad9061010cb8375fb52d411d9e9f36f26bfaca262a5bc99e8a2cf59c6e49931b028afb33d9af0c6983f69b176d92f0f7fe650ea7713177828808caa4ced5ad7f0f023c893e5251ec56005b6bc720380ac92fb795a1da4e267e66129dc9a6ad8ef2a856f6ff3d3591fc0b60efa6963992dae56edf98934211af1d28f10914841f7fce410655a971b2e014cb032a1ef7f9122c596c80d3d8ad41f727484fcafb2c37ad0c8d0eb41cbe25255b735b031b801a2a70949f507630debf3b2688b5a5207fdbc9296130966d79a1a8642fac4aebf62521b108b0c2fbe8288d4de7cca371003ac5e7772a63a46321fb51606bafdd985ca10eea50cc2434f943fd3223ccd3fe24c915d498258d354961c40f3d85c6c5a7d1c6a826d4d3e7c6e140d730a573fc43ff662bd68c6a24a35756db863b73716ac0b5a519d66e84c0ff0691132d6e6d8adf84c5006f23ab9bbf9e1f433fc44f7139a0e7c57dbe014d364b7f6995fbf7a1a377f7318f46ccc64bcc5939e306e81a9ae4bf1a73d70b7ec231e8983b41471928940f9fec354d548d027473678d64fd51dece837dd49a6a62685169d85282381e4ff41fa425bdc5cb88783971de8f24b0dcc6fbc7b0cf5ae3e8d112622db115d96bc9b314be339c7a9011c662b8ed8400957cb59165598505b8e3d4b55fd3bb1976a10d69f2f004fda5932ca6cfef43004a86299892f752a0c40484729f3ffdaf8b84cae8550ec956a3149de8eb3f674d6f1f472639b328e75144cddfe886a3a96fd5a7ab1f1189831c88ec39540a68955a46cb99ec9823c9b2b141b3589767c39029ffc4823cfd6ffd500ccb4b4721a9cb06727aea65b34f345815b784939fe23b2ccc6c36e2cb17cc111294b68318eb8650376b9363159157e3d73e2a46de325d0d13b985fea4e5674ec02efdaf7428dee194a9a703a8ed163358aaeb17d9788c21622c93144d6667d4388a5a6ff288c9cc483214dd802c4a315ceb73a27a690d81afd7db60fe70aefa8f96653ae1ffe0cc73031e6327a07bd8e09e473abc09dc388b70222e7af4e06cf440aa8cfb262ff90c745a271beea641b2cd7a57f1b543c4ac766d308dc0b3e2d174e47ff42db46fcacc2499a8d21806e77a9cfb7b90345f241a54c2f898cf1d3a188f55665d3e089d8c0fa1f3b962ee994cd241bdf235ac7daa614f2dc6cb428f17c97702610e2af59ded60bc089278b4720b3bd8d4847e553fa2de9b124469d0eaa88e49e923f9f4d8262475977ecb2054dd35eedb552060aebe19ee4be12a809cd55ce280e5f43dc8533e2fb0dcd16d7a54ef7780d58840bc220dd737f27e6a213627edf4b499e824ee85d0bc52ef56b3cd309e14e5384d5b49da8e652ebd33784d9722c5097a0b653fde25120e99ca815a873e2e4b41d92905deb2d6a6211bf6b629f0dd390dcf7f91ca2e43f2f238a98e509a799ac1e2e0f55d5d4baac134ac1db24a22e714ab123695124cf9806dc292a3d9f0b288e2bbf6e8940d0b064ad9a1c0127a072392603a2d3f054f7c1e1208a4c582dc3fcd456638764258772c8b3462f503b72609ac42aa57617e3c7d895f8ab7645aad245d94953b25f2095cb15d19ac79b551b2c0a978a2a4bf7074333812b805f5403a811af77263550d972329d35ab9faed86e4843507256d0a8c49b73a0dc41dccfa5a3f6c3274da498f9ad00a5b143f5ac0810a581a9f2286e47ec270e7d95fcfb3b2e4d9ef83a98c872e90df2dcce17b8c5f71da7e6ed3a2983d497593181bb4ae1c3fbd837246cd2e84ac10ad7e5e369b0c11832c9829f9d1f2b21794cfecf594455a991e18586f9f812ce0486187954aa5838d3ce184ce20ce3c5b1cb9455eb4d3ce02927ed9e2dfde6c87c05956866c8d8662c945350ba49f6bb60042a2737e9fa02ba6e2944f575b69be2a22e6b513ce7cdfa83832b5e1a7ca6dc7378a02c1ec9cad8bdb7378c07facaeb1949fde3bfc7f2ec1266d689a9c8d85caacc07803b59e8ca26a16a24b6d0316914d7df6c47357c9849ad85b273349edaef7eeb213694ff4fc7699aa44c0e2fe92878de6091edc231c38ab63b2ff0862e878645a94204995d67613f3314a7e46c39eac9bef846ac851f6015fe2ad39afa0da0c133a300b90978f24cf3ae8f8366f229a8b1dbe088685bb4d402520e2efc6d683c0fee9f0eebbc55e3ca65665b862b621457e45b7e87745c91940a0fc78c1d4605ee17dcb0888e1e17505b3b0f522cf2927e16ec1b291a707764b44d99c7b7761b0d75e222369c84e15f26a31eb27a94125364147ced76feb598c363f50cc92ebecd2d770e732da33dec36315d3734748c6848f4db5ff3edfe7ab869298209197930179e48f0fde8c7b7317b4894ac8eeea3e98885b0a4091c15093c4842471833a6d65fcdf3a1d823305b48b6ae6c30558d86e36c4d547f81027ea45a3ebc4fb0517fd1471756fb56f716b96d811dd8166da3b64cc52b81ddf467e7e17136043f4a895d5248bd0a3d8d7213a143846905d276477611b0d4813340514b3bde63ab5f0199af4df84c16744b7de46cdd1575ab4cfcca92d95763834270c98a25a46381f1aa5f1fcb4ec2b798d1bd1e9d2284a80a427894ed67c59d988ac013300f80c4ebbbda1974b880ef09a383bb9bf46bca6e844f73a17bab1500244f48df1fb745d6bcbb240932ae7577ee4125ab9d0aa1096ff42e98538d12b94739586793c2adee9788c4ff88a0e0865074c13d50b4f32b8c98cc4fdec480d31106c1e900e2d79fb1692877b48dcdef850885d4c2ffc510b7779c73721f1c3b6b01c6a698304a468bb9905d1e127bb4118895bc6bfede14535243eee4f1e09b86fd9e9d2f7ee17dde9525f6b61716e88162312f40f1028bb6282c826480aa0af810c24094070ed62f5199f91082d3e0760d77113d2b7ee5d7fea62b22958e4e5c8858d3156ed397b8e4a326d20f3db61bf9c73f4d7e29aa741322ee16df10dfc355309ad0e812c3ae4d0ba489dc8da1cd4ec861105fdc7ab91e99745c01126944b6395158649d602db5df585b2f2b3b33718b42f4a926400a0b60da1685e72824cca089dd9f17852cb884b7f4589887d02afb0dfbb8e7e75f82f11bcafb2f3c2f610583f8717b485971c90cff2bef34bb7e216b26fde0701ea2a69c21bb0f102abd20421a1eb8d6039e46cedc9258c3e90409ab40edf8cdb987ec2257a26f4c99f31d298e691eb47f41c9e3512f7e4de772da6e77b90f0bf28e0dc7485e676bb846333f71baefe7524d20976db311d80ef54f11500b45a5d09973da35ee0c7d9ebd960fdc7ebd64c3015c14eba28a09d6798a9cc62464aa1b7037f4956f27e5b38c5782ed0e75d839c82d05dc5b4b9e7383e661d3932318a08be41b84a657b3943b926dab5c8f3ad87407399f534a06452f1e83c11038573cb0540737e22c4ca090e29945457ab4ebbd23e8bd2b2cb15941c6c10208413713119bdf624c0152f519875892c32e481c68fec37c0804c46f82aada58d9531a3462ae971b9570be6b6b4c030453472e7d2e6a68f744653f820936748982835a74c19f9e2683047f28bd07e6ddc1582650c6b7ec4e1ce249aa530bf6504ac793e849cf93547b28a6133495c78a27f6e4769dc8204faed5485bb9c3a7577ebfa2be6301d506b14c42f3ebc253b6a025f0cad15f31369ab4ee36c0750bc4af811793b240bc94986a8e16ff83c62809a9bfe6b829f702349d95c8c8973787f95772ba51c464457dd6430e31a4dec9198d9f0aac8cc24b38114c3af86736a9d830b9524cf0fb45a402266f9ce405394cb47453e1861131ccc3f4f44ad4ca1cb27f7249f67286d5b361ed23c27dc96e354e94142e7af52140b1dab6f8ac3c9c28e981293702f24729299f8912d860fcfb87998802d7b22546a22b4f0de11b12b3e5f48e1b72302aef06931af187e8f4d43f51ea8d825a9ac3dcd79104eab58636dc2d24efd16620f45fb1a85eb94ffa94c6853b1647f111f90eb9e17a824a61207db7e0117f5de945a5f594dbef322a4f84b5a6fb13a0725ecc248a39040d4230bfe2d8582f65891d5a121be5f5206b1312b71b5705e8a71cfa3b036a3f67401a5de1ac388128f2ade146a853d28033cdab43bdc56d6bd80d65bb3adc222c872f991f97ea70b008fee43b9bedd0324c871ce370f27359af6d15878961877c27a8555b10ccab6187741c49d30a0ef1218b0d2bf90aab71fddc85c160302b7658ad16ceac86ea4adde756fa2210e9dd1a1ec70ea3505ec8dc77e6a89381751ea1f06285ca29649d346d9514975eb3cf68baf8a1f451544b123f99073b439011dd217875045ecf6e495b3d4c3ced355982765b8902cf8fa945c67cf8ba09c82688d476cc0b44e5a871c005cc6905dbc0aac9877e85050100ddc0de6c92ffb452d4086c6cbf06bc34a5e0b54d79901cc3a4cdc05e8a712600716f0fc03de244eb08887514e8a7034cd52182cce839a766d8eb4f6fb6f567c8f54b569b3957ceb594304229107f055979bd314a80bf1de0d9f519397d0e3a53a44149d5bf94c01362c4b8c487c3d70599f786717b1d8c38aa3d17a18e053227f1d82c6dd285f4eb610249aca841a2e27c9ae7004fa9977bfeda234e4191c17a76e2a8dabe93e8137de6b15a7b60057cbb32287ff5584be0c9a76a5b5b17aef573a88074cc933d06c2fd64cbef4968e2f31758dd14dc4e80d8bcb38d0376bfef41f8628cdfd6719268a4c655b55deaf417f1e54cf0a1d816d7591249dbe60172f79f8275a1a7719d69f16b4e3252747d3e00873ad5fdf422b41dbcf50464b1e13f07bf9245673017a2a25cd543de7d83d7796e1f9ea0b76eb87a6c0936ae3fe160c29771e23b47678382d87f22e786f74683348e04cdb6293c224bee4a5f9d1bb4e31f41e9ad33b71d6f8870e1cb112e340fc80123070c3c127edb89d630f3722a7ee277bad4b7c29de6bdb11a434cfa7b6e3e058b0bb357dfecd6db174d71701052935a8a8352acced9fd5e8ef5951046f182dd9dc69018adfa7b020a413cd529cf106b58d98ec318521ce197fb2b7239320ccb288e0e45513fc8ab83c6112e0edf7165aafce28b4fa701732e32ff359764b23fbf688e731d2f1ad29942da75a4260120f96b2fe6048a3a1972b74e818656e6d9acefec258f279cf0a82c57f5514ff784f790ab074b83d960701731c1628618552cf1fb7d2a756dd4fe00e9400ddef9a75820c7f1be8587830da18fbfbf50bca17d251a30374193953c0a98a4162979e995bbc3e13b6fa297f3dff977a5766e84a08fb04b4a1c0358dbc8e13353a191204f1e06d0040f8cd9d07cd61d58cd96255a723874e074e9691ac9e70c036be578940baf1714b00f37466ee73e8743df1cb9e014eac3391c3507a17fe82147d7929b2d97a6dc4d03717b5160ed0ffa9182d492ad9c45ff1b608cc4c080b4bb918661da9b05080a7422b5b493e23bcd158c61831756980b20a936b7f4879d80c6bb48d8c82b4e076edc5ee197612f750b3db9cf4d3cfa6c96de127a0cd1c88167f182a1d2e9fc29eb0ba13416c4785332b250778555e7eb9364fc6e383b5298d5121d3a5e167f68d38e3dc98060f5a176d1169034c1c61f44e8ec782a24bf0626c1175451768d89d9a4402e5c83b1bbb44f9eec017ba9d99a60f10a9da0f4f905462da7dea16cf36da53b0082bc56c173bf2baa55c43f85fa9c2e9ce72865ab6968d5244058c5b69fa17e0127218b642017a61a2049d27093799d09653d69541e824ac485d626d4788df1837de1cca46f38058f5c95ea6044e894acc58cf8bdfbdc0c88653fa426a80610181831da732575ee12d1eaba4de1d244b90bd5c00ace45007571fae7209c589b6c360cc2eb0e308d157a263fb0e8a15aa8f84fc7903b74768fadfa6e1044cd512806c83c41616985e859a2369c40a8168e83f6be7d4020480e699ad6422d8ff1b8f456fc12e3fb34635d62d14470eadca1a7b086a7b907bb3bc9dc0232ac3e6ba5e30e8d7060698f6f163e521239be0408d7f247305695200b99c0cbb12dd0d7ff77a78046a55065fc27607c018fbbb33f585688c012de733622cb5364478e29ba3b3e3094fce05a2c1458a3e281d65cb3ae055c408b404f261e751e4d994823d02d3639388e0afdeffe10f0de77f00653732ff6b2c1babfb2e164a088d161e8d78e757f74d7385fee1a96a15891e36494b73e21c0fb4317ab1c348e1558adefe3c3fcb3ac5148941f6e8a20c4fe5b105e7e298dec87eaf5df29166cf50bd2df0a2011d62ddca0405faed3e79055ee576f0cd2166e3a6b5c3f374717092277c10aa77e4a0a5f94f96e74cd270bdbf0111a2f0259e34308948862c1ee3a9f4518297aed3c1a3bb2e9d60582c928982bcb2060c0414dc1a99ba0a399b04339c5c8c5c8bc6123ac4a89a917bb44b94b56fc16a2da2085dffeeee694abab49d63c61fb33149c58a855d2e7ed9a5b37c41a177e6d158b64698a7cd1daf5fd165855e2bcab641a5b1dd03baa42f19546eb5838083106fd76762fa4125b1662e14a2d571b3232469b2996761bfa84e306adef592188f088134c5d4d8a429d69a068aad1204334df458bbf4a8b71d13d3496d000f2ced5c2c039bf29e2c575e42a998a8b13c0a61a8bc5957f486ea7ab380f9af19fe01ed769418a95e0833852a7358ca908d08c1c6c11f926796da0600cab55286f0e20b099ffbcc167056b3907216b7cf062d9b2441da372024a0e272a6572e25a2ec1e9068a7819362340d30736d756b68679f0dd2cf4c2d935fcd0e2d68651397f68340a62bb5926a9dcd93af953f1b3daaa14546a9f02310097b42e0805027b68d1f2e8a6385c025910d4785d3369ac271bd608d28c2c00e0e61a87de56019cf0ff2c80f2b4b05406f99c65d2afe0752fb7fc460532e0681e506802198fc7801bbf823222995d6708b71f7d52884e4e7eb92c069f11a740c500b03ff809f1e7aad8be2a64ba74d86d8296423d639698e447e396fcf5f24f07e8c3810918c660d4a298735a58f4a04fa4bd6664295594b275cd905c2e29b4fb560f8e60c13db37500ec789c073696aa606506bda6c696af75c6fd907c522ace95059b3d0c7c996e8ede17bab0684a02cbf8d57f93c57fe553e6f45e619743d0fca17172ec54b89d4a95fc900a29f37f5dc7c6cd53f84afdda0cfe7557dbdef9e29242975d374b1a4d6321c07dc1d23bb76bdd042afcdda0689117bab106df4a2be0afd0ef6b6cddc1c0fd8805df6e265ee1245a716677bb6b8060ff9971d9cc1456dbc794d64e67b5e23ef20114a6e101b004afbd8c245493ef3230fbe34971b261279a0c867b4b58d0e20850a651e93db758ac880490e424780718341742db64e433d6e12de79a67b57f032bfa1a53ecff1b7f50acbb18a045b9b72a2526dd68c5a43700defc0495b554c8b785a59903ea2c0ae9aca8bcd1a815ee2779090e19a600be9a225c37a44232640511eec98a0bd5e34033d7fa8e3849c61a37bfd71df046bd579ad93b06ebb8ff5b6760d00ffc5d9269560de3a01ae08814e23f02f9aa05d7ea0d230047a5cbf9924912e00371903249ae8e46a046cf6884f5c747ddc2b8a97850a305c294c2c28524bcfac2ab9d594a103e782f1ea42670cda30d0d910f151e997d220f892474cb51cb357a1e3d5f94318a8849f0d04465ce891a18d88bed119e1ca1f49e6d04b19d72ab6329ea11e88da85ab4619ff6dc121922c5c051dbeccb45e01d9b60e350182508e3be1fcafae77236708d26e7989027075414ea41bb856fb161ac0b08f678593bea548411100b73fb8b34b0700d6672f3d690f8b43ec33c9a303ead9fb2cb8da22c66f3416b7c56da0493f50ad1f938499a7a3c2c69ca0b149ed422763a21b90e59c9b2832de220cbfe5b32b6929a3120a78c62d5eccdb28442b3290ff4ca01ee2cabceb41503437caeadec9f7d4e2e72321f1cb67b850985776f7b7b3439e3516124c0c0ccab4f7034171bee1f2669215c8850a478040cf810b48c94ef031564bbf6aba85fd5369c017cdb03cac97a8e5d3052b29a0e696555f0305b32b4f52691980897b46141d51a45760e3e10cae6154bd9b5a2cac821475f2cfb57ae1b80aabbfaa13f7cec79c000e400122a3943edcf04b210c7fae1fae50fe571ba7595b76e24a4edbdf7967b6f995292018c084f099208394db3fd8fa639fdf63860be69b6edc1704689da7fe228a5de77dfe964fabe5308da919ac06a0abbafdd473dda7174eb81438df551a697a993298469917b54f82d7229eeb913c7a1b8130ac5711cc7711cc771dc09c571a71c0ef51cc771dc736fa369b4e7fe14ce2c51274a8542a950a84fa150a9140c678930900604154de69cb3893addddbd2710e6cf4ccace3219b20da5275b641873b67d3327a82307c5e48dc562b18cd2582cc6414149b1296cf988a3b43863da1f713f39cb4751184637af47b01929339f8428b5fbb13279cd67a2a62962a32ec4f1c0afa9e65b5359250705057d4ee96c710631b9a143a5b32fa78d728ad2fc2ca8c5f93332d4ecc5d9560a91322aa8bd94450a26d4cbdcb58d8e54478b994d9665df94716c32cf085f36808cc9fe892a45674f0214a25432c29322e0a0ce16d99b9c1449bce73c0ddcc139e7d1908570488b243c2119e42c6b7b6eb39b7da145ee678bdc7b34e4c1da9e089f304665f9e0d79e5ffbee69d8214e8bf3b9108516e777dbb659f9fdfcd0a6c5e9e1f65e486dbca6d6ba5a6d36f365082ba89c4dd370cfdc093ba8dcfb3373ec04e42fb2badb0e7ed0d6fbb538c9c0e2a11d4149e5bed69cde64e335272b647a2cccb8ea68c36fa30307050e75b43861733e51b3d186d3c29bc1a1b6f7b469668b9e15a18bfab5d83d4ecf2451bb5f358de73df5dedf39f6b8309bd4f33a4abd90b323edc291c7e776dcd785da7f9c46e736b56c4e275f380f79e5b30860d47ee6e1fddce375e6593777cf649ee2b95059dd8cb3af63401260f37dce6c06893a3fcb6466cee69c261ce6dca4c652667ad291942b918ea0cc5c8974c481fbc32dcd6971ca186b3522ebfc6071cef92e7a0d9d1e23654ae055db49bf1da29499fe3d7f0879c1edd7223da2faffe0d1ff9a863bd597efd57bc7d3a35e526a454b59a6fa3f9a66b4e1b81abce8e3f4885dfa2ae40849baf48bbc304a2b54ee171b0ae38e928c4bdf5439978ea6d96eb874ee1061897a5da1405b72280e986f794abf86334475b6485f7e733f9344e5acf4baaefbcff4a83006d4a7382e857a930965b9f0840a6b7d1ce7c213aa86dfa34e9fa903bbcfebfa8431aa9f60a825c2401b0d9e14e18bca3a40a5d2fd6b6f2f2f33114db32c1f623f4c28f6f713d1acd8a2bbd83430aeb9e6da08d3a2cf145c7befff6e5bcf6cf096aebf37e78c4999d9465ee32da09ede4f072af298f913c99ddbec3066eccea43bada549455e43953cc65fe993c655ece88e1a75ed9574fd1dc8bd025d9f5a542c2d6e626c4b49d719f037b35a10e77a5df76063b8cfd7809a6649d3f052a685d434ed5d93493276b10f19622c699a268fb4af41fd89649aa5a1154dd37ec3f1188d66210de5bb94526696dae958a078b2a70d92d820e888db4856946edb237d2bb0ba4756d702f4bab0650982cfe5ef6136e24918f9ec65eea00ff96d89c8efe7e73259e4bbf2a5fcf1412b462df2ddcfc3f1b32c1ffcdff37f7c3beeb5af208f6e7eff5e64ecefacf735941dc3d9b1c887e35dc877a35efdecf83df738fd8563fff7331c3b06c8ff5e7acd7bf5e7bfa95ae9e1f8f71de9c2229f7b362cf25dce12912f6ff611e997cf3d87a3e9f90bc779bf09fe7c3094ee85da7fe1f83d5b2e2cf211f15e5e3bee5cefbb9fe158bfef7ef333fde904ce3b43fa9371bc0b89b8b0c38523b5458edcb6459c48bfbc0dce67d0877759d3fecae5f3cb8be2d56fcacf9146d0e2c703000ffed932dbdd76e882e4246f7e4b8bcb7eb411b76db56423058725773e0a2ae830b9f3596861d2d01a2595a21feef792924313f3372d93527258725facecbbef69d1909569596824873e6777a86dc0cb560f8f99385d80f952ea98b1385a143b50c51667bb1849e416820df5b3ff11731e595bcd4879caf1439ad0dba665a9fc6ce9008a6a8ffc7e4c05f0cf9f96e7375bd6f37bae420f6bda14acd822a5b5665996655996653fb3969c79a6993e1c8093ca3f6157bb47e6f395a00b31f7c8b4ac14aeb4e3062edbb97471da1b4093eac4455bdcc7c0595a1c8ea6c1d1a2f81ffba2ce1f59dbcbdf6c0ae2952217ca8e61249e4905523afb161ed20a7e70258d2b6158145d7eefc44935bb1286c51197bf45d1bd464a97270bcc3bad942ebfa58c1c8015e1c8502e8ef312356e65688199c2e9caf92c1fdd9dd685d39532cb1dfdbdee02bcc0e31a547e89f208a003ff1175b419eb6d86224a93db5d337dfa4f903a8809d5d4f09c3394ef196dd1e77e0b5db4b5cd60d3da32fb637b79736a8b6a5a669d50f9388ed314693681b4022c3063b774fde5f3ebc81bd5f37351bbe44deaf95b49dea09edf8de44d7dfe09246f4e9f492baebfc6435cff4d86eb4f9bcaf5e7dc88ebdf79556e87dd35bafe4aa415da163cc4c6840c4b9a0af5c28df03cf63ad336ca75de37ff149abe86a74785150c53cf57662fade0215a86a6e246cc0ecc2ad708b5fda829c92afd51db423b713f6e4c6caab0e54ddd8f74c9f681a1ea4d21e8fd48bda09f29fcbe1f39286e4bd86f0abd0bfed885e0fa7bd4d412aa5221a3c2ae612b4919fe53e846520648ca30cb2b98080e8c5dc595b8fc5a384e1c2e7fc6ddd217833781ae7cf9f2e59b86300d2184a76d94a3492317b54bc98d26d09599691bdd6851bb94dc6802cd4cdbb44d0b472e6a97921b69d995492317b54b299b59bb7c94495ce4dfdd2d934c26a8fc2ca5eca14ca110010043210cd918620dd518a231b41a9a3104800f87564333865e865c865a865443a11d520da586504375e8346447183a0d9986c0a16f680498a16fc81bea86600230d40d7143012061881b22e1c6d00dd13fef25888888888888888888888888888888888888888888888888888888888888888888888888a823a1a39bc6511730b87d66da46b9cefb40d3a9a252aa169797192b1a35583642f86040338c5e945e5c2e452d492d3e2aa115d0ed67cd30bafd355e946e3f8d17d7ed5fb914ddfe192d49b7ffa5c5e7f6bb84200200502008f419794a9eab2b02816ebf4b8bca73ddfe140a005fb924ce870a6d310d4bdb6b76e7494e4c10eea9dd0941881ac080f9b4b4274c5168b163346cfd47594446117190d8b4e86c9d68df822f2dad64942509eb21c123ae9ad9991b55c4b6284b6200410e3f3191524a6770c0449b1e2a34b189f90471e70cfc9bc6943a9fa5d2ea13dd6da48cc348191b794323c0f206bc1ee435fe2f788d6cf71fe235eebeb10b7ccadafc6736cb7a80e94fdba3ecce93cd9aecca63fcabed696d566e1b0eb14517025aeb3eae9383541b464894978ea0136eb76f7f0aa91542453b31fdcadf4dab51bcfee09116fda765ff1b2da8ec750784283df9b3710b27534a659531ad49b9692af45cb7367382a08e3296f33f94c664c8e256f1e60a89ba6aa1f5252083298319130329a5ec7e0923a594b2816c49d9154961dca00a3fcd342c32987f84b128da5c2e97cbe5126f5b230c050d8eb85ba6e4359b92d256a4c45b726666f6ca2b3781a41e338f8eb2f67939d1640c674a734e6627aa441a8305575bd27ee049a5cb73ced95736cdf48a8a9a467e933be2b8382ed32beae8195d7e0f055e1425640e294d683ba22e94a681358d91bce9f7a6d8b8fca3270564c011bef38bb89452caefb04a19edc32c09256bb8ff30a4410375476a823bc65cafc1066c2dcd528fe14c29aba294f9e072160677a5949af594944a8095002b015602ac045809b0126025c04a8095002b015602ace872f794379037f3399437bb226f62f3c6133583654af28659f3a5150cc89bece5cdbcfc994bde7cdc4f0d6bd8d2227386e58a5744028f364d330c03414a29e9caddc5517eb7c4c16366e613e55876b7381d6c40b79666ba11c0850bb8d062298b152c4d2c5c6860689b155458ca0c443e448981061aa2643c60917151830c05294afc64b1e1099629b61fc0c8015b8161a67b0241348bbc10d0ca51281728e0b86842b9a022e3c205d904620a2f03238bacc7072a84e8c187255b94e0078c1780714402a21b5e89e4450c5f40b9235c89d485d2f5a427bf0ec7225286805d035c296588d805c375c766728f9a6674fe024b37cc873b7efc05933b764c227961749979b26250c786b11b79a89c13486951def148f60b909f3d4ef791ed28fd92d6c9f6fc30189ec8df6c1fb5d8a48e0d9332c607bd5d83145d54b93b6e9196a5e6247e6666666666a0531395a54f663908a845661f76f11266a6462c5df963bd31a08944c611920e5c62f0e0eba4fbda71d45d3dce097b22f3717a34a59e1743c18790cb8f8342d3643fada6254952471413cd159381883b7a4ab11d2a8a49d3d49846b29f5eccab42de645eac1ac91b0fe66778e3893a6a2ecd47deb0955b45de682ffed4513c6166f49474d8bc6ac09a90bbcb9226540474998db68841390abaacc431b4464dcae5514bba9cf9209561c41d352b97df5bce1a55d4ece7084e540d887ffc64365b727243893a7ee69232ccd90c7dae7c8f3127d1361de8f6ca61cab04de182d88c0b4658024aa24d42d0fce901481a35d84de21b6b19ac83cd0074a0ced8cc88ab246f6a9908e31c6d63a409310140d163d4714614ff57ee3e33c3592ecb47dff963cf9d7dbb3d32ba4872b44317afc3360108b2f93a2b77004eb069dd577f98293e8b1894a6991ff39a2ce44df699f7a836d3e60b9ba7f2666a3f330f649a09d8b92b4bda0665a32428610eb5695a4c73c157ee45f03e59c6f08b9b56df6b366b6359a0d96e881abbfedefe028355cd6c9d3c50b905c60aeeca842b91c008baa92b916e40a573609feb9dbea6b1c0bc449ede163c861f8b902b3f92268ec7c026900a8401c30e57109145113ab4a69df118e6e1e274875b0f777bdd51e4e18e3624b8a33c1ac11d651213de81936210424a1639b8a2a4498b45706f96aa6831e4f304890c5a38308ac20758f8200822b0d2f3430310c6e8418a222a825a3540e8e0c312448ca00620b4d80544f460081c7491430c2d1e1e48c28a2cb2c8e1035fb4f85bf09a1e117c11461838c4e0c39418b4d8e7e23416660eaaf54aa432c240c5a07a572295b185d8930407604e74d0440992e8c295946103a432762863063bcc74e300b5655d1481bad9af6698f0608c20cd23011745145b4c27537ea1c4fc8292583167d18a789144166464b1810729e60f3c7cd151bc4860daba48c15d39b9de95485dc0600539405899428626578881d4e2312e7ff58107083e8872858907964832b7608018485481c48b1b7c00c591bb945284c868e04d989322274ba8c0490a7838e226ec8e6fc512139933b919d252d1cdb2226c4005131a6a40c611adec67b2a3ef4aa4a5264b474820dd400ad2952529406471747158ba6c8f385f0348199628782d75500450085a1dae646851a1c40743ad0e3b0aa5961541908249ab4376c152cbf3af435ea2c9cf1358aeb436508b5ab20b40020d5a1eee300c576479b5367012620c201808b53a9c01446b03cd6c82132ca1e2c7a88a131c5d015c59051244978a250deed06f024b13455538e1bab20a2682aecd955540c1e232b86366a8ca9bcd7c331ca8db8fd46bb865a30b3d8ea8c5ce858d294b37d519ee7774cfdd739ded01ce04519d1a99775621c6954852acc828ae4492c2e44a49c20232ae4462c1177dc395485250b99e0477cc40a9fdde69a689da75ced9699ad6bd2ad5696057b3fa2daaaf55a57a0f532a29532a55980a478a7a9cf66056363efaa9906ede076a4534efc1702c02a6de6b2a1c850c69e108fb7012a0251cc4fc532487ca979542a6d36251aabb2872f8ab73ce79026f064a33b3c7c07d4729f7b2e33ecb38cb3d0d353bd28d861ab785fe9ce6194ff6e624bc19266650506597235b6c4e8bf26788a8fd3c54b03dcccc842745d0810861d4e92981dffc0354291e7f2a306c26fd6ab149d841dbd3efd7b0784dc3aaf7ab617efa694fdda7fa0edcb1316f73e3d197b31d2465b2ffe9ccce1ff2e02c8b7b22db77cf6ddffdf6ddd3f7a647b790a1340db749b6e95d9e939a86ba84e1d7623682925adfcb3edab0d477100ad6341ceab90c76b3902f43a9b54deed1902f2fc9763014207f5508a2c21a8e4ce56656282739a8c5cc04f2e0db826753eb66d362466d084cd4b183725acc42a634a34e5ee817595d16f7dc73f68516a975e2fad6cb27e298f1605acc1e4a07bd843fb20b30c3b79ed868315bb560d36266bfc5ec475052b95932d0f6933385a2cc32abe306794cf6dd423763207eef9b3d6f3c2343c561cb4b8042067a42136b076d38743ddcecb9ece9c60348ca64afd909a4846a5519de8c13352505914d85a2fafbbbbc19a3cac476327d05bf10a6c5ed4fe1b7b8d5ed37703b3deb034fdf77dab66ddbb66ddbb6ed3ff0b4fdb66d2730ab90c52f2f7ffa20ab47adfeb47a9e4a43b666cc9841e34f34683c8fe967bc6c799d52a95429d4a764ab2564b14bc862cb02e2f2ac0fd2f2362ccfe95b4edff23ca677f9907d50c0d1d182108fe917e93d4ee01c0648ca71822a94ad2d94ab1b2fa8f251f764fabafbc2e88858d2142c4c84bc49bd3f17c139c0778f364dd734b1a671124208efcf5ee39dc63beb475eea0ebaaa1f394a507dffba45ed6be35bde6f7051abcbcb4bc832bde812b24cd6488ecbff8e8b8be862a9a35a6ccc085f9e46e8f2441d442394ad55285b3542d9ea58a16cc1b82a0d9db43c2bfc99e15b362c8bbe8d57bdeb5b2d9605c4c6ab9e456d101baf62056979976f7997ef42560addd3ef2ccb47f7a63719dd9e4b717ea8356e6c51472eba2fcff25821abfb212f21abb346725e9e25846577745e965e5eb65a7e94575e4c2f5b367e9449acb0c74bccc6b7fc288f4cdf461ed3451ee3cf7a7779f76f096d84a0f7acb0a3b490aaa51439717d4bf50d3a51bd296ca316ed5b888bba49d37cefdfaf3692d234dc8ff4c3958ca99f0aa59441594a654c7d11c2da12c2015a7eec28d755ef36ac9431d5ce163b6422a48c3f1872116c82bf6774c4523816f29490b1b884dc3e2dbb002fe18c306807b3528b8b5eebb3d3a2c4724d3db54f3b70f6d9fbece7f83dbbf3036f77774f73017592768e51a9dd1d79495e11a244856349ce31777f77f9ab973ad6492d1eb54b08c6519aa69fd25add4fd841eda7e08e6cb372bd8f8c64cbbbe70fe2fd6779b8f79e2d0fd746a0e5e96cae5552c75e6a2cdec3ee3cc9e19e5f3a933181cc3ae159794babe341674551c8636ed02e9fefdf3790342c8514fddd5d43a40c1fb15e55c80a37aa74ec7ba2f1a6c50f3c1f9238cd39e79cf3e8ce282db67d20ead84b37f673ce296fb23bbfb178cdf6f35570e5256f64d08e5ed2e2fc49a5fabc0c760fefe00e233c7be9cecf93a86310b285669dabf9dd83a4612412266fac3ce8236fd847cacc67bdea9c7fa30accf4a63a14f143b34d6ebe369f88e69d77de69d4bfb3237dee3dcacddf348e736d9b76a66956f8a1538f70bca6dfc1243e7dba0e758927618e60362c2f78bd86e7c97c1ecec66b78bc0f61441610eefba7cdf1de0b59f3bb972d1610ef3b4bedcc7c66ce2ccbb22ccbb22ccb7cce647f42c6d3bdf75cc803fe479ffb0774effd939ceebdff421ed6fc69698b598d16549816b31b59d47ee7e8953099f71c438beaaf428fccdd516851d2d954a06c3ff841a98a0a68baabefc842ddee736699b685a30325b9feee3ed71fa7b15c31c6c6d2626c5a97cdeea86645de4b2b170315751552ca5491ec1b7415d957b8bf94adc47f714786b5507604ee68262dfa1220d74fffb4e89b06661374f14b289cd72fc3e48d56b342c73c216b68c8187f2b56a8aca4701c0a45834618c6c40c6000e34aa7693ed64fcde60d3af943c1d0366508e726b1169a869bbc421c3a2e73fdf98885fcd583bce99e3e4c863d5aded01aee814be2170f8f8569b1beea7950aae767d11cd5d7e71086456d9094951e1344657ba0705afea007b125ce3c5cfff1c6a51f00998347204df0a7e34af5f461e44df7f45545445ac45362f3d79b9fd6c2d28b72a6f79c9a787c3ebea7f65b3cbd04a965f9009f3e0ff0a9859132a7efb912b445c46beab938eddab3f660f8d96f7189bce9ac28657c690b75844eeaab5a2d04fcba22e563b221238a2266afd1f7329a651cc759aa6594665ae6a2ce4f0c062486aa0d9e8499daa5b4d6d5ea5ff41feecc92a28efc4d69f5157d4eecaafca1e3306d8a07f21898166db21f436090aa18eac069d13950ad402da960d77778567ca989d0cb7b93e7fd0e683d0b5af93dde33f83dad530d3949c9037fdbde6b3ee2d52fced1aeeb5d17f27b5e6beaab8ab658548bdda996c110279c091964010141d483bfd99c54eaf9c1fa29bb63faca33a8b1ded4839f937ab07ecaeea41eb4f5bf4d9f837a93dd79b2fd4e0eea4f76c7f428fb1ec3dab655157faba95052ef5bca781eb70311e07abb907b90a854abf5ff5a3b284d9345c4122e757de576cfc99a56f218ff4ede7cdf7545dea3211bd550998f78710e4a656b1857f52c5f5cfeee3ded634679a067e977b2c5629b7a9efae00749f198648b819c1ef5414e8fb23c4f78507ffa93e551594edade3385dbb631802d43798ffaa99e4e15e5a9dec4d3f2a8f74c9fa37a53cba36cf518efa9d7981ef55efdd37b3f519f637a54fd93951ee3f13cd99e07f5e0bfd7a42ccfe953ef7d05423df839a8072dcf137e1ef0eb6f36e7f429cb63fa14f8f573c0917d4e21ea73c04759b639a64fd9f718efbd1ab2f85bf018676b2407f5a76f806c9dec0ecabae947b984b231709616f83f4ec84195adae05bee94719e3e6d3d0e5665fd84ade67f1de73cffbcefb2c2b85efb7e7f159d962b779e1f30ecebae9d2bb85b2452e4a6a291da5a1f8b7d27ca9605db35c40af777677679feeee3c9e70426c86a00edca014f36122880e06c311d2a2afa0e3ff4410584148d36cefcfc20b3b0e903974b0bce14f7dcbfb0bc3aefbeabacc780f47caf8f70eed99f954bfbea70a55cf852c660159bdea59281b64f52a56101a9f7a1a9f7a062dcb073fea5176cc21e8a29ebfe7ae6aa85266a49799023b5ce0cb5246cab40f19f20225713d514769d447b4e87f638af3d1e52b5ec3029ff5b2e5bf62a12c0b088d5f7d101abfb23c4f725a7ef53c2e4f23c8ea693c0dcbd3f22bb98341cb02b2fa1a1f64f52f4fe36b589e27392f4fc3f295190fbe6c8176646e29c376a4389cc3c60e75e4239d99f1a59429d2627ffbc8733f6b3373615cf573f04f21117ef03d3ea14e28cb4a01f5dff3409d4ebffd47ff14d2e721fc853352a677c217581012aed0a2ff4bc82d433cc67f86bf4b58398703a409feb09922ff71866cb97054e7867ae305b54f6dd24288263118bc18c2c51d3a3a4d6384190552c69f9558c1dfbf5126b90ef30b6af6938d96660b5e63a32365fc47c8a2b28ebc01e9bbf3704fbfc3c072117025d292d26590e973cfa3fdf63cf4b9ef6701d17efb20f4b92001a384dd7e1d262220a020825857c67e902855b941889b99dd9dbd9999dbfd496841f59f25eef8fe2e0591183538199a82450888b06202c14f9325ae2412883354fe04c06e58622951295dad64d822882bbc0cd78fae2d65d4199d76eff6f6aad3fd23479bfe43c7997f056666f618121c6a600195296a0002193310d5d0edaef9412f17d0962d61116349de689b65659ce536cbf324a70bb2bdf79ee5e9a86565cfb1329bc35956f6decb1665e55856667f80ff8daca4d44b617b3e4a4da5452a494b49fd5aeaeb53823eb25fb58fff118d2529293119e231a1062eb7b88dc14b536249536249928695827c66cbe230a6d4e26aa9086777e728eeeebc5df95ef6bd206ffce2c001245c0efd9c0d86c120ff424d42637ee4622cb1184bbce49237d9f5d5aa56d91b57f1b92357f14972446b6cc112c67603b19bc69dabd95f016db16d99c675db779a16ea6cdd6f1fa4fbadfb20db77dd735d8ba34fd449b7c93eec3ae60f691a239dbdf6b4e648c7789126e2b9834fb4f7b7e95ea7ed90ee79e87bcfc37df71e6d30fb2dd4e9bca7cfd379f48374cfb18050cf769d97fdb86a75d96756c80956477965c80a4220206f7248193780b491328e139bcc3ed916937a30467582e11435fb17e44d90ed6d3c66be2065e6bbad5f92981520ce01720ef0ca222264cc9d4adcc0a24eff1584d8101ac97e7b4fd3b42903d01290367907bb8ab8082907b1eb2faf44c201952baea435f294eb0c03c281137766cd6dd23eca0a2d8485169d7b2eac1163202b5a0b90f01c9d12aeff4a0595f2ed10fc3c87ca98f71dca98cd0f9da661e6246a77dff7fbbef73ccff3bccffba2d4e64cba49c6187cede50f863f3e9d2ee70747639bb5d144f4002de26000ebd1afee41c6f8cf24a1d7bccede9f8a94ee782a52ba1c0da9ff40bf5fac201f820d402c79f9b4a865fdd879eae2167d11a078b5a8e5119f7b8900c56b65397776b9f6ce9b1d5989eb594bc9d334f25ccdb251df1f2ab4a809e9f0699ad1a67718d9a48f8f90ebc448e40df85e6146e3ca6a6fd3344636f797f72aa5aa5e5ef5d27d5e54fff2309c93a3fa97974152dfb2f324a7e55dfe5f5a2e2d76e5314eedd88de2453dea74f2b28a329950a8aaf929ecba37852e70960b5ad1498b9123552729298701a4092d214e0f1d4da3230457a0944e4d8100e595ba32f653451295cff5a69f0d42af6e4fc6c0c8582d168fe0446d2eec578d586d20a75247bec27c83862aa5c0c8e8a67179554a8d995248316ae980a235aeae94af57d3b8cdbb13d5356f2151499d9ef68daff99ccd9a8915a05db6fcca6cc3663618781e9dd763c1dd9d5d73ce8c0577f7eefe4b57dd3dca2a57feecec93215f498548991f493833994d77264a29a50784840c3948c256ae58e1176df0d89b241851fb4a0de4a1dd2b4930a24ecf8604232a07a6c064b4e8bf428bce821029557a8cc38e623e499e1375082bdd982b1ec73ee897ee5a665150a765a0249ca4ba0d7c7c5c41948088263e33c84149cc87491042fcc466f8b9f42a55b9e14a0c53402005cb0f42323683d01311c911ccd9a7bb3bf38f33bf83a3e006a30dc9932ae98d2054f92a48d85512848249f9d36b3679074b37a2044e83d9b325c559cd397facf3ebcc7efefcf7328d7fa56573f66987098392a3eeee963ddbbbe5d10a5f8194661340421f9062e5bb32f613851b2d39fb747767a551c68ac086e0f44072b4431de95dfa6187236275d582b35ab5d4bafaff5fd5dab2aaab1e28bca0ca8fc9e0630369a565cb997ed952f64b29abacb2ca2a5b66724a9b99aab3423777650c86cf0475a4374b42c58f0c3d7032650909194e6000f4ac2376b7fceeffa1c3cdddf3b39c1659fe8f9ca6c97eb6c5d122c7729891d0d0dc6c547190446b0112f4d332ee02dba4fe993481be30411f9ed14ccb00e538eb825f6a67b665feb20c4fc27c5fe62d3ad40c5c0048810bfaf0cfc7bcdc7bd3c7f4f1f1ae3f274df88e6499c6fd117a3929e34fe7530bf4e5beeb2c9532dc77811b4e39a7f7907af5cc8c28babb3b9617b214502a28b5848b52400d545ff0712354910b469886896024c6b82db0119246caa671418afed3d259b5d44b0732901071c715123478384d5b9ad34da31f13c240d2888129973110bb7cc4e7f2e7b3f5b66dbf6d46476020e9aebca8a356d461114de8d22fc9f5ff9268459a116d752d7e1eeec8755c96db356e50f9f329a209f977e1d692600a1c63f1cbbb62f1d396ba04181f100562b2eb675a16a3c57ea2e9e235a7ffe1927d8c9895947e64185f39c9eb12cad610d49bc2963fa97e86ac14e67f3f2dcbc77cee3996ecb91f98d3352c202e9f7ad3b3829cdef4a737d99f27dbcff02d132bb3415c3ef52e9fb23fae6f997e866f81ed436f6c51976eeaf4f3673ca6bfa7950a59f3c5eebced699d52dccb964bcae54f3f4f3aef65c677eafb888b58889bb4f8422271fcb4e86225a32493e5241dd3ff635ab75e8fd75c19454c61aefde5cf77cbec2f2d0eb1456efcabe110c5995fad347b24b3d1e2af7cc55d7f5173eb813a6d5d8dae69dad3a6d934d99aa8d54f6bbad5761b30a8f6678c3bda8844318ec9eb7a1f4569299cf5e6e01d1936bfbb7dfc328271afd7ebf57abd8296bc5c89a90051f92565fc25f48225358c5ee77ae98af6ede2f73e08fdcf7aeddaac6c6d766c2013f8e3071603d62fb86701e1a79fc3d47a51e9f3e750b6d2637260c0145aa8411fdd84b5b2d1a2376cf5633fe5fa7a776498a68494f16fb19590341c0229ca9b2d49fba057cdec0c0e9b2ae22b6b2f0cd4a99a5a5c5ebe47f53d206873523ba84ff57cafb23b4f3e9ba3fa17bb737ad58ee9533d52f5a770c6d730f5a8f0e55b5a5a567fb23b3bf55bbea7c7f4392e6f7a7e138d3fd99d1dd3bb7c8f29b4f1a790f5350ce151e18c9f31e37b5a21a45ef53929d5cbcfb03ba87ff99dca0a59acfa19cf6c73663ccbee9c7ec6ef985ef53d335e5c5a54a9daf3b53783275fc2e0589b9ba3bf87015a587dd3f8962f32dcbc915950d4b16d1a9593c494798748994ef21ad6f722bc6cf5cb8ef5416cb09ea7be8d20acb7c1b2b2d5b9c0b7fb2c0b08eb43f820365e041b1f820dcb491ed3cf637a96952dee25e8a3f90a12d5b35c242d13dd98d2df492965b6a298a8c42d56653d0b15918c04000000b314002020100c860322a1603020d8f3bcfb14800b82a64a744a9909a420c86118a59031c410600000000066604884a615c25470e8f010f189065bf4445d10b8b739b138fbc05893b52c3095e2ea83e6a8647a56bd77012bd51e3b6c9f3887742f8b20ee74a76fde9910832823f95d470083776d74d1bd868c54c9c931ef85466134463bcc318b876871ccd7dea7e1ac032819e1b65b597bafe9c1d59d278e2a2d962bdb15a405530967cf3788e411c9780ff2ea057afad6521295ea5e62226e38d4634c9ce8f25a5cf3ade504689716624e9772a0676b9c0254a8c6db688f243670f17d23c5e006bd59cb78d6aa32c1d8d7f28308082f6cb598bd412f270ae9ee8d8e7a3601dd6d39c61ce0fc640777b7fc3d6096209dc61c80a4bd13f86b5a6ebd987cd1b3bd8d7d18bb2fe8f56fa2f100f29f911bb2b7890035a7540654e02615f73010fe565000ea747ba3c6bdabd1af619f341064f88b497dac6a530156e1cc6534bc108dd2eda7788727cbeca858af8d6c3966aacbff080424d8e00850b128dd61a37933eb3d51f210b08ce82b80ae80016c850721253bf628f95803f48933683fa1fc9900b81b074db6b0b176751690b1b8ba6cafa7193b6dc39c86468d4cce4186041cb5cdf928754d5eb216483e0ac7b95c90b0a5d00095bea17056a4b211666bd557d56ff501fc7be05d8a62b6a69697a595c08b65bd3cb0044f378c103c4bc3ffe38cc5dc561796bd6db78d860d958192d0fd0af14302ec503b9dece29b40976330544f683355a455240d850342bd0457e6e538534ed3847c015ba04279aae07215ea38b21ef56cbedc145432396aec996804b067a49ebd213d5caff4593cb47fcb90821aa03f70d640e49b49ffffb09c40bc4f98844882bfc1218b12652d06f314d962aace0abc10cdf4c7b2ab6fdda9d783b6c0f87cc4ff7b8c111d7c3ab0c749ace3439196178b4f6c53cac2c01e1a6e08892a2acc6e9f025e0b4e21c29037f9ca3f186af1ae9ad928e321dd99bd7e725207062995f4c83a19ee95b2b5f9e8f16e4199700408646e3261482c4a73632330f60e79a39b2701c9c7c0cb7a0a70fa2e7ab31f7bd461083991336428b388419f1b4c21afa2775a3e3699a79ff8c2d4a305b83222d77af91e09de4c2a8b3886985c8be4d4a9a17146c2396f1a930cdd24324e9f5ea19d5f83f3f480f32888066e592d3ac26a40ff2852b61b29b6643f15ef007388c703abc909389937e78a1743539db5848079b8f91554d6918454d911687b50dc4a3e0fc4f1800e285d35fdf80dfa0c8b5c59aac688b3d22b4545c028dcd4ccae874f91b1e3ae2e053f2250520dd8860ae4bbefa2f6506b56bf913ed293b6df6be9ae642c66c9525c1ea8679fe54f421e88e0d5cfcead63c83b00d615d2f7403e42c04a268a8f7f54d138422c6864506ea23f235601e69060eb09ef68314ec109fc0f55db122f023902932e23eb01f67c357ea380ee81ecbbd5bdfaf0a0b21f582108050c5456e894a862d53c380f6f74b5309e6da2f4f455783c9134a77acbb79b078fa1bd2165cb7165bf579996a8d86179330ded40142e9c57f20acf645a16e44dd5714284cf8967b55f2cd974b3c70dfce67b0581b1f79c89c204977da5fd025fa51a360be647336b9aaf3be20bc45712fd5feeb3f629358e96c78feaee0decb519b509ad53c8aae236751276eda5292d4b2a8a2b4960a790c6af067158226678789f94ebb00eb96963cb4404f1c94f640406d8db0b13bd75bcd4e6707adbd44a3da9fb430218747d045266a214a4f460687fff26e435273598468b5dc1a2afdc829622bae443ee2a39c8b6c65fb3b8b866317299f487e2dd9a7114f0c74ea2c70e1252751b4ca6478dabf167427e6a6f69cd66cd34bba19680604b962633aeb6791506c6749be6216ba7cfc690dc180383d8c00358b17bd542a40fc33529b08c21c15a0304af3641f487e339b397bf7ba8d9251c870fb4c8670d29d2e6ba05916fbb6dee3eb468794245767e9c2da92ba0288c2b4ddd7d91d0b466fadde43b577a06a937a8ae88ae55ffd5b74cba41aa30ca83a1b4f6d35cbb4cc3b0cf146a36d8a5dea9ef6a3805c23e51e8ba8ec03fdab878df20e5e9327b1321f805b5483468c997f19f2ec7906a553ef16b877710d588f982c4e2bb6d6b45737b37e2bb74fa75ac7bcf78a2ce301be4de6ca4c3c346549f8d8d4e3b49b3dccd8d57879cc57dc52d26d5739785fda8baef19064bb06f6404050183f64d425a1d8ad4e1a1f6433fdcdb669b754ff2325f23e3a8930abbef90c004680037b5004304fa85f9fe87e92374fd246b70ca76365024553f9f050ff9d4cef2b1f40e664cd1f84174cafcd457e5303a543005559a1866690800c8b00dff3f9935652ef9c607b059d2bbc07a108df83fb911a19c2c7648c3b27a048b9c468154789f8fa8fbf55fbaa1e2ac3f7c608eb7b5de4e9e555308f1e1a28f5c0225c6ee0e536df9fb1d59df865e8b0b951dc36880503444fb56b709776e493b8bee32c9159ba0f02f7a9f5c9c5b5907b0fdaf6afa911b44c1244b07a85f6f645fa4abf00fb2e3941f01ff19e82de520ca473ff215d694167fcb3f8d816bde32ae356b487526310db9f820e04bd94c380de06fd19d9bca85eb55dae48751d34ab6491bbd19d67feee46210248036cb1360627fcf03f541f345f0cbf8165646eb9862255751985c43241598853450860ffb255a4d55dbd519bcd9921bb8a434e7e6dabe30d75ba1c2c09dd1820bf64d18dd7c68d09fb0867df2d50514c671b030829848c1b00fe7a04592c8a36124868f28f0cfb05a9f25c2efb0001ada901e309e14ac063d209a7c51759cd01fa0c0e370b39652a3318f2482a2ab7c9b17b098fb453557c69a94e9605cd1e3727f4609aba3305e4e40504ea09e94d048f4cc81bd69a26673212a190463e659a28b5ee763be46fc1a9b8ccdeaaac917766460bdac12570734aba76d591c386523ffc21085c1bc4330265cd1829ca3c9a999cf1c382c4500c6e57ea54bd0d490aea47e4f5390cb753eda2564fef53368229c82bc12027fb95a190d8bb50a1d1ef897b587a3486f46322019fd719c0237cccc8c669d8b911df5e6552e0f2f6bea79cf9a4d4165af648c4cc7ff453126f2256721f612dcb4c74e9b96b089d98559673259f94319193bdc21599affc7085ce20bab22d473ccdda37e1671910dbcf228be46605aa8f3f9895c29a39554db93d17f0d0a9ee816100d156ba574c92378f146d21a18c2dd2fb2081c183c02c62047b8c446b10243d67366270445bd5c313c7713e9cf279d25fa53b39d5492c435c36d9c9d7e1900b245f222a4275b14e8c89b026c34ea479e33ac0a675f70c26737f21b540d72acc898a1c73f742cce5974322315693f09691986be793ac27b5237de69e678bcc4df255c1e9f4fadac31dad044dc1e6e8ed364874bf25d437e4293ab291a6d8c312692c8e464468d5b7574c8a3f4cf01811db3521b080bbb510b0666ab16bee1880ebae585366287f9751be12bb0828fdf88c2a3cef2564131f5c6cebc51a03d79cdf6dec8bad1370a71e16de23ccd4d79a040cb86bc2c98eecf84b3ed3f109eaf9a9bf73dba4e5a6e9be3ba2f3ee86eef5ce021a4a32258b7ccc55137ec469fa43c8ef77f914c04aeb9271b1a9b58479406d42225ba015b1b0a5bf6569345431a3a570ee6df5a602a2883f378bd8c7bf163c6f45d4ab0be84f08101634db614b01117f7de32f562b7cb49e0dfcece4c20cdb69f1e434784a911812cc32d51945f903b9e1cf9f4032cec695ebadcf52550ee3f17a8592a4fd80091faaa187631b5abe3e4b2a95377d6010613bb571f2a9603b9f4a28885b109b30a9034ea36f62c0b0d19b92440513f8a8c2c6f630c7d8a2b5c59dcfcd4693a9ad8cd6d0855ad055da9df449f0bb2079d3663bd7f987562481203c1cbf4242bf745ab03a6c7026abb975f5d9778352188c012a85124b79c825993be82ee3af20b45482bc58a53bf8865c4c2901dc24083d8b0771818b57ff9d79214303aa8b1b86276229f97430ef1503b23725f5747aa0f24328d429c462385e8ba9424030dd05e4b51fba5dfd9450d3f5ea1d1b4098cf5ddea2f9e4cf00112f16aad5a1088f47a7fc95a39c65601ee623f68c6b28e19b9ffcbd6224abbf1cd42c33e5fc0211213f24317ade6b58cb40aee648d2b6d78f99cffd4f2d0a64383937f9bc8e08e3acdd11f6b420d16aafc215df4c1efda4489b0d3451b4e8669685cc633902525950c41b17404966c7174d7f9b34bff0bdd0182e591549c54fb70c98a154dadfcbeb24cb9cde24a34b9f1dae3df224cdb52b497ec4183e4f6725b6a4c43eb30d7580f6df2aea44eb14b951f4179cc7d2a992fa0cfabcd43a5ef1698d09afccf8b3fd19a2173f974463ca2e5f301e6cdd43dc6166931b319a17881f2a1e2fc27aefab11a3e0e5822d4f6168d5c9c89b52ce5b20dc43aa05b9a82a932a2c14c6680d8b760c61e4038fca1eef5887c5fa87b839b59617a343b60965850a43f67b53d79d378fcb4504162b0fd21f49f2b704776c9992227cf2f4cb0263d746c8a9117b63cf3abed6f6853f2e476a6cdabbccf24b0aee4361faba33b0dea4825527b251880a86c56699337145af63b88e70be9b19a3593b077215b8b99f0954f5e952017bfb42b12167a9712ec1123a768cf5489ffb39056610b75e2e9bd691a985c0b64d21b3fdef558a6cc1b83092058b623151629f0bcb995a18617aa56cf565ce9c421251e74e33bc28d27e85f1202144f0b7704eb545bbd7798a67d55031cbcc69afc90c194c80a8476265dc4568c709a9e326506f1d331f47b3e68c256e58a8433d5c11bbe32ff94e6a435334bbd876b6e33db9f3535276881f33196a272d854cd6b39439cab92ad04f01e6c747ef05cc7c515525a046254a84f332a9ed9f5539879c973680d86716a591c318d488ba38999b37c4637a81f757a5791687013911ecdc6b6f903b7bbe91df051484c34db22d9623d12aab375a95408fbdf459bdbcb17f028eaffb195c94d01de648a20be754124c0a5aa9f0fbc6996a3ff8a13ede018504d314337d7ce2a6497d2006b8c5920e10a52350824b6b8ec0e8c9e45346bd92060778f3574eb374554ea6ed79f6ef0df1099a36b3943e2d06941fb37e6d003b7c1e0d18ee9a5369906128f5760f17ce937015378fe15a6d547eb7998afdf79e8ce150285829c3ad010b3070f2fd4a01b8068397bd7956bef95943d99fcdd409b4fd0443c70b72e519e9959a43590b460c78a91f37f73e646f4120138cd01cc3d469291f667a906b6f1f64858814d71b3f14792db19e889db92a897083d9e9d577ba47fede66627cf2de46e01090b4af61ad6a55e7a0a2048e0a4a3a8341373205d02b90562eb6c1bd4184d67c4a5aa49cffcfaf4586fb4db9c16489d52f690362cc8af6877e3deaed0c590d0b9e76b281eef705c0f72c919be21ba755865f0ed47f5aaceef36eb8d000b405d410442654f1d2437d6e9081f5e54d6c125d39aa9e10803533c77ee1770dc38901defbc22a06420bd8f4515957f48205afe87e27033d3005b3b14e5f8081fde43c65ecc8514d30db1ebf0901898a1f886fbc8d58e17c831f2193a04e04e19019c7d2318ca41655b9b0ea7df2f4e5db2af3215bcabdc6c9409de5d26826eb6d73ac7207a70ef32182a41c0e3cb7f4133ad1c4d3aa7749a862a8988771218afac0621d1e3058ef1d271b4a9fc6f753dad9a2850c24863eacdae7c4e394b58d1b04fae0df7e144cd5d62419e2f0fe5529e38c9a65387d5aa5fcac01fd106298c82929dc0fd4c2a61bb055b3d1a453131d319388a462e51dd0d3800e0d96cb02dbaa21757fc39eea523d0df6438ce452a857c24be0d80b0df3647d6a38e76590a443e499c0e5ad11c469cca746da94f565d3c70c360eacc2afaa6e3c22670e34d5ad0c952e6d39d0fec0b2d2e7e28759cb71e85a6f050c50f91a70047afbf29a90c79cbca52c91f4c59d9edd687d0e374097c8cba579e07cb0a36b0290a763b08ca44e691909fa51138b1b5f0bff86c41c5d779ba824fd3a84e0f83b398f3ec2d87485373e9ec1570c3bb514a26631e27af642911dc80b1683658904d9b3a4090996ac30ddc42d316969c136b6f9160e150c4fe318b2ecdd353e0f02cebab7773407838ddcf8afd6f0f15c5fccae512d52963f5abba67e37a4affc98c10288ed26531ca2cf2df5d89df502bac042864cf0901e40e6bed50c85737dbc6edc592715d49535d0e09723eb8e330a5d1c7021f5407cd1c80a9f3fe059fc5792ae356660b74c0d9353d2d19f656605090634bcd49ea6354313f139f78721d8c2c31eec67d4a6a74be565cbf4c6df453c007d9fd9031f235b8709bcf72c7fd0f8a96734b4eb158115c9c4921540f982c41b6eece4522b7a5d07321b4f27ad65723274ee683ac495e6417adfcd05c9eb1668c0a6ed8f161eb70dd72c5b31cdf5773098554625b9af73fd36b6d7626595b373845cca7230aa441750fad3aa32ea9544d594bbf065e88f99dee28ea47f94eb0478e859e51357a2ae856e67f94cd99fdecfa0b34005002d0c6d25034e8a6db1e2536cca82d702469f5d88615fa4c598afd6aee5e1c0c51c9403191d989d8d819977f80c07633cc3015190800d23fb7961730c3662f9587da0e0e31b3d12e9907dfe7142b3e018fd160d9b64f067ef3a9e8a6b1ed10c4e2dec3f718d12898c7522c2de7695d2e44a0e55553cdc7df246b3aaef804440ca2c051cf287a85ee215a0f40a5860f8cf59fd24a46415038ce27deae40b8bb456cfe13b023213d4906a13fef4ea1d1519a0d90f3937cc820922a99a4932101c2de1dbc0901ecf2d5390fc4010fdfbf1ccc00fd0caddceba8175c43483167a3614b195a49a1c33a379ddf541f190177d5627cf426346f4558a5a7281b8fe2c7b88ac8fe793f7137c5f77ea1839f3d26a29888bc0fa7aa306c830f4d50f0816a00031284344f661b57341da69844abc798341203c20b73ec748a3dc83960c180a9117dff5559914ed85398104bc999a159b15ea734d09c2f2520cebb86fc6442cea436faf7e3a1348cc4ffe4484e1a139883071a1a8928a7bf0b27798600b7bc443e91ba3dff4d29919d93827224d2b5d617f1828b8eb1f284350fa583af5843a45db5195c7f9dec48323c2069a56c055ff66381de4d11acd0ae1cb83d66ed76b380912ae67c6041f730f8adf3479e4bea81d2963e0299b9b4b8aa022605b3ec3d5d1e0fb94109c4bc8273b06fd3c1cc9a830e202f2d3421fd5d975a59d74211d8ab3cdca04e3b99b381b9d0a1c46f71e581353db7e08c74fbb9727e7060555f9a485b3032160cb4d20fc7362cd825455bb2b0bc5852c829fa181e1781340981c562b060c16ae2836def6d2f6f2b1efe0a4e696aef6da160cfac75b77b627f5762d4fab23a3474f45dbac2b83c59df83e38f10eecf33728d4b6dbcfeb255a24861be3c941de4527fabb6e92a1945268287c55e643bff0213f660da8e1a616b0865a38998b6fb5ffc804d5b2e4cdeaf2ebc7528037cee50b4eef9aecdef707ae338b14f37cd2b523e9ddd6aef2bb098757340cb44d982a9376fd9cf6a72432835d9ea32fcd2bdb71e3ad7dc68918d1f5b77c13abfe04bf0b05747dbc0c3baed999fec41fcf4f12379566d364d902469515f4a7bcc063cfe92286d33d326acc081582168a3133cbebda683e852c5631d1affcda2752f862cc8bea5130b109163b4b54e06b2881b12c776b86525316b08ceb2fbc5b9b55ac3f709653484c521a053a1bb61bc1c43ff14b18b06c1ff2968e45df8e9618c732a238dc8b088fdebafe3aaa54c1b84ba17e87dc9911268352778efad21813662b7020810b7233dec45adc329e20b6a8cdb37aef6811932c5587f66888e81035c4ba6e4f38cac75f85015deeba9263b1d6d57c7ff0e04d688c74424e3701e030d2b798cae91ea5ad6a0d090d489e815da06f3563bb06f9e184c24b1c9c7a55e5da386953b28675ff97a6e80b390474f5eee72d4dd7d48752033b1a86ae561d08ba82622e4f47ee14e0e1951055d7055e8d777691e86a50f0b92dc7bc36de40c144564913b7a299b2e40cc2f3ffcf483bd208fc41729cc247d46fe08527e1a5e57ca736eb57a82a41707b652ff3425db8273ac8e8645a17e344cf552375b6f552fd8c5c1d16fd26fa9549c0ba39d4a4f1edd872d1f92c41f086aad8ecc54f2831eefde8c6590e013b87c96e52e1705ddbb9b590607eee4646cb6e1726e0b612e660dafe21b7ddd62811362e3d4c258f5c069b69964daabb3fe3fb725cef93303367b14aa48b5eec1d2a51fdd273964630929ad69374fc19d354123fb14665b4c15fd9abee282b77903662b8be7072864816170549aa0546ecb4e9a1e5344fe80561b9634af4c36406e0e06aa0b727a8067b488f47d6e4e72e5ea2e9c34b4ed01ab366d0dd2fa2695a4665bd14bb3b54d1831fc96cd7e6b8a0e4895372851f1ad13382dfdd27f8c8ae6d4821382b1ed103780bf30d6b08ff5a1b2201d5096f6a667e394305bccefd66170b051aab657d89d944ad6d3626eed17148d0e24dcd47c79e6af54d09b2281d6d74e16867eb0d76d81236f0c08d5dd0775ebc032e79dc458bd2f2bf5d6267dc53d37b539876a97216b5529732bc2f5e158614b367d04edb22aee61e7fbaf61043171587ea5adb32e9d88b332ae53097b4f408f14d32d84c0da94a9b30fb167d40d05eb54305c24d227453ba685b16288279e3fe180a61b900842a934f9d6705de6a4633181d02f12d057071678ffef94564a69042a54924b007c182b7c6b83292d74de3a32900ea89205c0b649ba2754dc82b1834fd51c99e1ae0ee3dde76707a856dc420957e283e4a900c12b49b83d230bde5b45e9f86d4ff55500fde9325b1c99b21b863c02a40a7ed64c8a0a42969bc6fdbeb43924ecec841b81b22d55b7518d27b6c3580f9ce6d33e186ccad382bf0fcd085d2f5514e8af0df92ef77c294728724f480cf0c19019c98e5455366af8aaa57989344d80c38b68303374265aa89df26efb895c1b3987a534c47caa935180e9ed207e65e0f9a30b685dba085c4d416a1878e33f735a5ad818ea6a2b630f9854f2bced44f6d1eb53530ebaadc0dd4b930a956a0010cf303b7caf12236f4833430f838b5a946d9d891bb09aca41c50d38148000d370ee83c00ba11d1b638d9e0b38941f1bcc4889bbc3f41de2c06bf4f98a4307e47edb04b48b5764477eae845e732b4beda13e7bbf154c7a2eb17a37a03140361824cbf39760deadc17244c92b8cef03566889026f3c05173d0393c830eadb1dd41ea4942164c02f26851998c1f208ef49280a60fc55b1cdef521a0d4b9b946aab05d01ef262fd9411a1558d87ca8e0d630581462ce587fce772743825745d3511c58d441dee81426519bc7937a4d148741032b478c3a720462545fd2816d035de52d7344a255d035816d612bd8ddcbdb3cf670a8931212a0d541a11c802167d1b902f0ead26de517a54962915c7057d57605ffa50fa599c9835d38f48499b53788e22aa59520fe5f44e45de3fa91f4111516177327b005da94f0bc8ae7aa6a6489dceb47887e83e4596a89080b476747b0d65150d03cf3265ea0a356b3fe34833a8dd8f7470c9d04da10ef83663a1b9f5903ed85219ac39b802a4d8b0627a75f2225e531f2679eefbd7293d973ab80787f9172353389a71aff7bf96b356b755a19c52f14878c094db47ce835f128046dd6af6033b504eb579fd53e68be769974032a2221e2bda37570aad997d6cc8c972a2080b7ae73620302b6982243aa2d445f72fdb765769a8ba263eab59acb940d348ca906c2301115ed53b79397d6411958328be5ed434cb3b40843a2831401406104c39b32c018ed3000b783185a67db5fc20b8983f0c2f7d6ac591685479364bfdc13dadd87eed6729d738bd5be4c5b35b642e8b6a24d767777015adaa73c9032a5514b11fc980e4e3515ef3019cd4b92bd71c1e273e0f73c5494c032c21a974471e14dc05e44053f590bf0e3e6442918030ffc081cba6aac622221eb6fab267b65673fc0d6b211b9a0d78987d940855ba492a199ca17200001de358474767946063e85a64d3f8578b64c5fac7331288abd6b164ff274412b00ec6f4a041598f3358014dd0b410f127620641d9d2c4146b93e6cfec8c4cf75c573425cfc7ccb41710d8af2cc469b181480a48ae977663762977049722d114650d41804640d27221fea5c7884eacfd5a42b190b3eda3c9410a791808a21767ea2382b82afd803a0b8b249b4c5640c26dc162d2eacf7f600eb839fff66e9a0d593dc2700de487f9c6545dec3765867b76f53833b83d40f06d9d9c2f42e8a88b6d1da413e59230318511c183d65216f3e2fd9cb0f23a410051bf16f693d766a46b630507d41fdab98014903627d8c1c49008280f0856064e12032446d90b554e6339d4f30bdfb3b8e6669d67cfbcc3886c0b2aa08674ca1bef0a14e8c80e0e6a3145a261d171ea23b1d3e134b4d0ed3ada74708b991c664caa82d0b12c4260eb4a12ea9772cc7914983b89606abca426761498ab76269925ff80c04558470b78787a245575025c691378cc99fcfd9eb70a3ba147681cdebb25148e80001cf910c937d0200e464a068a9e7d27bc7727806326e4be673f523e551266e0fc5d89c43aee38127722b72538f09413d03e0e3237c6188846adf51361df9b179a53e513c2b2b0bc518cb702b932915a71bd0ab077aa574b593d1b246293e362723308722701b99152056c3658b3ae704e2721ee30d95d42598c7859e7680a428aa5933fbfc7cd14c25e686a9fc558413ecc33cbfd9469dc78463e961499b4ae9ada0fb7b514020f1e07199aa13ec8b5b8682e2f7115daf72a032581def76a10987affebcf3ff96dfe5ac7a3d9f933727fbbbdf6e6e449e26f75716f6c1e9ba1cf90b507758e482320e4ebe1036c1def09e2837a9cb6a3c8a69ff729e9adf9721978953175d513c8ef9016d00ba0bb37c34e4cbb8e4b0b6ff8f33d6c554054a193a743c807048fc9c3c6195af627d0e8742eed4198117a7f1a0b1d480bc89816cd074772c38a5d09127c4d40d59f9e4cd7bd6469030244863eaec99cf25c1a6eadfe660618d6467ba6607545b6b4290a21874f6e4a3c9eb051e7c2a6478b66125d4d2bd7955534bd0ca6127d2c45accfad5e0e902090f3d7edd767dd43e99173605e6fc99920d1d8cc9200bb9972ac61c458403bb7190a5d1ccdf0c0e1e2f265ce946dab7c56ab746ab9512d6c275bb74ae58f0aac695600ac19e531c070192d675318116c378d3c8aa14b1aff8c0805125f86ba48256977b3ea8684f22dbab88355b9ec53b949ab7663fe5afc1d2ee6db1bad66b7b3c20d8eda8c88189a812386415042ed0d6b0270a5868c301cb952ba414b645c47eb714a08e8b776e7fe74fe0889839ffb13cd4442e2ca7509d2bc41e2a49bd678339dc0b33f0ea45ce7046896e684dded8799ab7c1a3c574102a501d0c5914b813eb06cb448c5300299a666181ef31713aea4f9875c50181975335958c378662ba73fa64618beb9b48a9843742010f8d10527ee64717f1c7e8de0c844ace8c854444978d84f54c46b24d472603f234927226e799d81861125109d97056bb303326239844d7b2f6742c96ecfdc7b362cd8eff33c7e787093489443c4ebd36b9add4a2b1feec5fea93b56a4cd9b453d8ecc91215ab3d41eecc276f4ff0e2798b10b79e054cf8d024e2a7583d5bb5791c5a053a9b38f7f539bc835e81eccc5281748e783720f9e866867cf2c005462ff22f9a5f8b20f5df0754437024a262ead2123af76cf986f947deb80d5fd15550bc0c9d7e716c8e6a68dc303226aec08a5d67390648f21b7c3be82c3bc75a796f08b310196d2edf093d80346822135cbe061e4b36fbe4dfbdcd128603af261f78d0895905e3a5e0a757ae22b87e77b6acd1378507e90ef814d151dc846d0a328d6c1769ef95c30e318584ae82910ae9d7ff728ee630ff9042c32b16216e04b2080c5e8648413016b87d638113658bb2fa81829d2a3c420184791c93707a5d463b295a77d8e396b49f1d884633c3c6d070130a6a9d569fb6ece01143f08308e7ec89391806533b001f900b2687c0550e19c0effc753ee2b09bbfcd7f222b658e069ac5a6a70b82c5767168ba6285f6dbc3bc4c9b3fb8639687d5ce457e0883153d810f087ae32dc35d5cc21e0237092f64b64254422d44242fa00e398d7f8a7f76c634da595025aeeb88203ac16b3135f13bd28151f9cbc7ae32263b3cb13ea3ab9d40d8918d47022d75946a06e379cc182ef068c5696ef4e93e5d369a1b788c075460f8acbbf08f40aaf56341e0d94b0d7117f2378f24df90ab100eabf811bcbae470fd4e4270531c3a36d67d7b4480314ed10e0fd401edc8fecdeddf04f854d0bf9abcc37a96a86291cd1c5924ad228676895c139674aaacbb3aa842bea158b6da699d176572515f8d754de50580dda02cbc520867c73d0021e4584f5eedaea7b917ba6f810be67204bafa080a9f7aa04401811f761e9554ee506a183cb013d426b22d6190250855073457b5a5f02875c8927e92cf3e1011f22961089887f0f1d4ee31f77e5da9fb34590a4dcd57890b2bf6f40aaafbe7ce7cebb515fc54ce9c3b2717a650bf33359d39a3b3912b53eb417835a96bce2eca281ef9103b7d694df7598d21188c56f5d84354ad5460b0e32bd797af662ce91fe8369cc3fdd9a4578408a440dedf00413552b7e6e615398a8ef7d247186d02d24faf6476f4ada3fb6a1bba98731876a632ead0ce13b2c5d0dba38d54a2746a3e8064dd2c41cba47509bf32b737ea98bdb81386ebfb780a004b16215e7c8697cc023b4971ebd910d437f1719e4f46f26ae27cfa9bd96f0721fada7666dbb022acbe4d710a80f2d67d5e4062927c10bc712559f2d7cc77e5c65849313ff06cb31241b7f8812d44a4436468933473da363d2f6e6bb4a087728bf5c3490aff63000f92ab7abac2ee10942f21b5ad961e4a17518f1b8c204e0005bbba5d925e0ec0161f5d5b0bfb67d3888fe00f3c22eaecf7d78b3d588a9210db8a38f1dcdd2748254beb9434315c726e454b3e7b46d1fbef875dab146b7c59a611491001ce6180a3f4f537764c57d75a55b90f6f97cdbf6b53345fbd87df2a29dc845a47b38cdfb26ef8d0d150520d6e5e51dca56666af7a0a358e4c0cd22e43a3fd294d50beae511180d09c18a916e701dd985ac9979747658153c16f5f7d0af46a919796892bb74c28bcdd8531266a62b0affd6a59d8979d26b9ef4f178974156a59717f6096064884e57718f65356012e43afde88069a837fcdd57a4637012c7abd9e2388df7d0d9e1066364d64f2c20ea277a0a064fed89978c56089e901f08b3af108d80a73ea8ddb0a52aa3ff2a927888628487b3f4f7652ee1c9df615a0ebeed3eaf9104c315f61fea1d763843c9a36288acaf424467e8c476049ed9f25e278d6b4fead7a567299d433494e8323aed8057a55d6bd7d3ab46267af9de5a9dbc1451bb35d3f9aeff1deb4c4058595de659796a012444bc9ed3c8a773c1be573bd8800528d799aa142f1e02b53371115a223b40d7d7efacf65ddf8b6e640157eec123390d9cfa35026d631445b77f0df22a0bb6da74c787bfa8bf2c0fb8174891e58a86274cb4dd5e3003e9b9e5925ccdda27fd98e5cde02c713d12adc04a1de07d6bc261bd90797c74e15ff4c66504f9d8f5f29bdb967b12edcd3f2a29fcbef64686b881fd275c6cc554789b5dd353824c24353516254602b346667b92fd3e59e1400482bac299fa36100ae167fa46ee6c955cdef16ff0ce4d4e39e13970ff7b298dab6ad6d84313309eb2b3fc4e75a8d8962825aec8b5c928453cec18ad603c8b1d0c39d5fd972453d6987e8f3522c23f6bad8006409cc5897b5e39da544138163d1b658e99ebfad2a12299711722d95c0bec67cdf2888bb00606d6068f7e940d3353d3ddfb9905ce18563d3dacae1661ab817135545c2511bfaf12260d0c72eab671c5b32a0e340e14c9554b071a149e3505d5520252b834b116d18692ae0b186948f37a3733827f86c366401322974012c33ff1687b856886ea1f744512673cf5c71c53292f0c1607fccfad329bad53c4e9059201db48a8197077bc44bfdadda7b20d129bb17080771466100e4f249b7b4f45d60199ed03ab5328a85baac9ad6b8101f1cc0cc7370b8390a87a01fbabfb660ffaf3b915b4963195e48f0d41c1258d2b82768b349025fd6b93545d647b744cc81d9f6b6b257651cdbc54655e61c8ac8ca8f3f9bdb3c1ea4ffb564aaf646485f33fc39096b861f668ff57e9a552f63380aeb147626c06f4a0decb1bb394b0080658764e69195ea6e7626debfb2d23433b933b5456754a0e2867972f9da15dfcc307187f7e645cb1b40008ad74dc70c47802af57f06550651e8d63fab6731c8a09301ff3ae68c8346ba1686819658d8c1cb3aa24aef9a5a01bb8d3c863f24797273e3af16736bdc0ce5ede1362c9570b5e87b89ac00ca69e48715af1c096db8a6ed2d61aa5e2a48bde01a5f170da0878b2bf161071b52ae2a289c3ea91621cd08b9c4458a0f1d96d7e4a5c4a2b9f05c4317828f329be12fc23cf4ff766b6720586170588d54d1ef560d6d3f2987ba38e840b6e7e75d521149d7f7ece6b7f1e169a0569246d12cc88c1183c94ea3bedf849c73aa110a76845944e7de13bc8ab62a429071a65349db979e67af230a9010b9cc4a7d7df04217ab609278fa983673978d0c242d883c913cb634df08327ae728e9120f4e06f6054a49a806df159d4487d8cd0a3c0d8ae5ad2294d3390724960e95637aeb45dcc8b6014f4fb1e44fc522c5c8348c591905d7a6d925830a3152a5f105071db42d4e350f1ab9f0f7f009b62b0eff2468a7ad03e5d5cdb7a17a58d8cc61b72f461080359391d6ddc1614ab4a879466f2bda90aeaeeb83a3ae2a396633e9e5176446563eae6445260ca33815b72be8120653d9bfb7aa84a6d5436b15818041aa67ad8533488d24772ff8ca3890f824922176af9a2e16e2236e6e75be085a62417812d870d5961b9e8137a285695b589aab5710678b0fa8ba6c51ab9952029308c8c3eb9fe1a31ca68cd7bf4874b382a9953c23adced8bbd06a6e4ee81f1dd0881edcba498c357da4bed07d6c50104c1325c8c5b46513598ae8c1900fc1aeefaa32c81bd9088cc44154c023608089aad020ffd404fd7757adfe7dae61fa81626a72252864e83f853cf052b4748c72a6aa13a8ea75971c69d997ef15f9ad48b0cbefca29a6ab28162c5aed25ae36b88ca56c00458cc49860a3b1ccc32e9d7dc7d4c88212e0784d108d172e1a5c19dc4db3e2953840481068044b5ddc9467492c4f000e9e27396421de5ea8cc2ceb5f7982c793dfc889765e016f1c233f5470bcab715f6aad7493f031a09898501403af3161c24efc8d1206c52c1b05cd62c2f24da06c329019d77e870a753f1b8855f5701b8d207f946e14c8d5b1316454323d4144ff4b32caf40e93477365168bee40c8288b11558f880620cb47c66f2bb1ca3efd8794bfd4eaecf67bd335592128acfdf9a9908a96b465485735e31e3841e0740780e9b0f718822b623f660e7a1492755738590781213664098e89630b5ef8e6fb8eee9bada6c433b64f95c27324534de524b0140bf6da4aeea7230cb6eb0c4c04000d1e79f8c733e67f83f366cb2ff2598b284310b3cd2531192f5e49b59a714e49b008eac3c15c29caaf0fd0304f59c69d34c477b6b19953dc84c0076bf9386f0a632c2bb7766fab10fd19f89ba8632542d20e1b355d9df0b9e0093b25fc674b8ac45a0192c15d579352bd0618913b0d0f03673b8471b6a2dd92adf6858c4bd212c24d2929cb91dbc5b098034bd5ea54af54a70ce72b1316a835d2881310f442db3440ec3d3b35050e142e0f597c4a5ba095a05b073014b6f628e4911fd94a45e19a2b70746136ed9c5e2889482d9fcc79bb1f0d5975902680b3169c94bec1b5081f75d7de1a4d9614d0407c108c9a7c5eb264e365e7efafaaf0fd4c3e57dbf2ac1a100f755b7a40b53a7a5cc309e5335fedb34836cd4a1106510d92ce3aeee3898f0af0cacc37e58a7501dea84fb07a40bc27c0963152cb67287a45e6908a518fa428d46b2c8ee7a9e653910a21814d56bbcb871ea7aa46af808829adb801947353eb27c0e9cacbc97033dc29da0be2d10f02df1eb1db68cc8253fbae8692d1c0fcb72eb879be86127ca35c771fdd7bcd97f193111b41bfba00515d15d4e3399684628d191e268b92a9acfda878610c62996f9e2ad9c934f04783c75642eb3691d4abf907fa9ac179d32e008008198485e24689581b30dcf53f8ab955fd1be885ddcbe9aa5b22b567ed7f0188b7640152fbb03c1d0444204d5513494cbf0f18769af0496155672c74ca48affe63c2190e86ac952118d1a7ad152dab61c485320c2d8754f479b413e815a99729d33413d91bf3f380bfe9507ec3b1f48bc0df5a3886553234413e4b49900a9c2f83dae330f6a26338b53f0e44fc3ad2a1e77c7a55d3d95cbca02e9a207716ffa419c0acaf92e08e2c40ae93e25b05c30ebfa8080028816959cbf2755abcd65dbf68099ef77ce40e0312d44d5091ab326e13c500cb22d1f213067343c2ead63852da80eaa53f5aea3b385adf31149e6eb9e7d49f342b8951206a830fee4917bf4fad94a9bfa809104dea15871b1cc480571cef8b50d86226212448ff9444e6e500230675ae47861f1d0705356756b53cd7a81b055b92d88953c060cb359c439c1f539e3859be135ba95f51f34ef5beff7707e1dc648e6207cc6ccb32f9d450bcf77fa29391a7dfc9e6bc4a80b63f7168ab86283a8c888314a6d55742fe5618a3a731013df5f4bacc15a3834967b7824f74c407b9addee292fbf0953c423239608e7cc11e039cef68018079c6294c745026e33acc0cf40325a9611af285ee51df75b265300ec547b12a4fec47772996faf1c6121dffecc12678fb5f2ff65f451591cf4526bd87fe340de1ed063c8569baac935663ad2cb50ed95d7077d31fd4c21864cd04bcbb6e955c1b12198669fc19ffb729508f019b3036489abd4f54f6da3d7d98dd669c148040064696bbee654e86cbe7eb4741f63ac28c0d4c154d6c3459cf088adaafafa629f05141a00423401014c26f6374d5d52de1a4403a305880693be4fb27f49865c3da4d23adb94685346468629003a38496454907396ddbecc4c35984898d61484800ae11b6e3ed3cd2d4031f82fee88c4905889ecb93ed9a0ebb786934c878f4114417e824dfc30a0211d0d9f4d6566380ebee97f62480d51b73b977e7dbb5f6f733804061c262a50920a167d61306ed0f937ae71c85538e4230a4bba36e486324a8903eb7160b6492ab39b26f052fe47ac213a2e4183a6b52f8884a1eb0d8e870d96d33168ce392736711cdac9e9fef8bd40cc9d613d858be4d8a141af61bd8e603f84dc401a8d5e94888a04dd2c53999073b48fce56b1822030565430153ef6a045abef5f099c34127383c2a98c725ef4a6068106fced04c80269926c22962c8a52aa22c6cc1611ca867f16458b7556ea40147a804a81203d0cc186110004aaf88a393e5dc8b3bf42477d4d5c001b2560be0e3772109bcc3955d0b8bc87dfd0413e1afab71963c70e58ca37cc48e0a33870e7f60d3d1d61584c73a1c9874673ae5806a6e30449fc62d985603a3624ab5eb05549216a2ebc21fbe978caf7a0a90406c71545c649a640b8e3a8202897d2f87802c5b48bb3a25315022b0a0239e2b3bbfa5e9ecb2aa8ca05af415329a9115573c3502ee470a0d251df3ee47a887825ab4a20c6a7a6707cd447904f20f6cbc9f78150fd3bd9b89ec1ad8fc8ba7b94f7ac2c04f7ea132880a5305a54b158bee46cf947febe08f6db01f5a7511d725b9c43ce63735d02a8d51499f67ad0cc2dc1b585a7b12736eb65050023189a9ed6f4a219aecf2118038255d2a0903312238a296929245369eb38844434e73e631b80dd10ec71746791e4a551b7174b82e5b3ea1ed4f22d97a2e68609537051b17c2068c65e114c4cab7953ab6a32e30748a8fc1b9d036dbe52b620ba0a8e7aacad8aaafdd5515a4ee04ab8aad94648638ac30488819c74ce4a6cad15dbba3aa919cc923d5f28b62cc3add3fd9e128d410d7da17784b972e5c73be36a2bc084ec346350b9a8e8d2f1d26fa54f6fc1a407091a55448f0628cd37f1c8d810134be218db72c43853386577b783016089481503e8b63958574da675bcc18c6b5c62513c9e47ad4174e606e7f663757564221c5e0a6ee1fd8128fc325452cfbffe691c0503441b97a28ca4aba56437e29683e3e6a94e0763a1d1a25e88717625781cd3f006fd7926e99da7f767f2deb12fd70f7cc855111d8c798e56060f745ed1b23a642e9cbd558ec77dcca789079da96a59ea75928f67cd8de5c3f1a996678f15d583ef608b2f2325f4c0d32c41ef7b113e8a510c682489125b35167d986c3357576dbad7e4d9d03c4afb2732ff6071069e5ef182b2664db68899e644231301f0460fb6fc54b4032ba0f5d2972f9e55de0c1b98c834845960839f1dfaef5d59233b9ec2a26c02022237de1a249d26488a1200830925dcc9dac3a49e9da1e7ca001c589396e4025d4089d56a1c30606f05178a9b1b5ecf90abb4906020996fce009eff1d0a3a6744ffff8c6caf73205498914e554b976fc3f6626c741de68085f5fd364610578a002067a034e1f8bfafe8df7f5e949690dced44b511c90d1959a607859f9500f7960621ecdd5de66e1e062096f71eafc025dda5196076426b3bb70953ddf4daf49d950e4a01ebcea44b3a1fcca397364716cf6b686648ca5f65b1dc1431a8b6c82fb8c8a41d730f1ad43be872ac064159ccef49a09ce04af7c07b589f80b0cb97b1c587cf44959137db774b826724522bca81d3e178d6421fcf6f222310ee2fcfebd382b8451a71bd5f848fa6365dd84035739d2a134a3fee466b19d36d1292f867fa93dd1b04dec7ddc79086fbbcc4e1e86b11e37570e65c010985727a5c3527453a07842d6c786eb8b333c7eb9239f2bbd731fd9c3ef9db9b98a627d3ba42577e7998522ed8188ac5fdaf7ef3b8d3b90662a008c464d1b3192bed24d57f1fe59339ed129c0531cd6c685002a903d7c107eeefba6a9524770441376b94c5b40fecbf932f86695d8bf0a4dc7350e24b0b5950c3fb71909f8e77938e4893827aeefa4384b4f98e236b22c17dfbf5e948e225ebd342b202b660d1d5138455c3658fd6d1f942b556fddd23b44f1264d84c0505efad12f961d9d876864baac1235c05eb022eb0033060048522217cdc5a1237bd0c2741cb7549109752232b783c7cf6a9f9a7eb3cd71eababf761f97b48428adf476ed82c29168430bc92528400fbecab03580aec4756e730922864f2cb34b0918990ca7c3fac94802c63736a0fc8bf0f3452810695581bd5245e5c08dd794c34016f217627c170f68130eb5dc142c9d6266847e058473fd74d7c84624b377ed153d1a0bd7e827b365ea9045fb00d6160b1c7e3a8a71606b1730e55665ef3046ca61c651d5189715a0d2a2202ed75ae2ae7d44d04f45e8e215ca021d4c0d5783f636e9659a1dbf5424d0f6b7f1abc999714e79b39040bd89f251ec3c9449d78659d408f1a5fc339f8e80b777e872626d018803697089c1659c832c90b7b10423c87be402882cc4068e57ef566e2b9e2deeb448769b31c8a4ca9ba9b708d2f69c7e581add40926bed6885800ac145853f8a3d275d480e69c246f0178d1d4333e60ce259c601e9131c4d86c3413c5a76aa5b9afb36694d5ac5c22bef1f9320fe2ca89075ee7ab605f26d499e13bd10a2dc863ee453245b14f91ee87183bd159667293dcf9a66f23bb82a0cb253300cabe507c445f5dc7b3822c551c36f9e8e3a539998c4005487082d4f57bfc4348242e9e1d576d7dc280cab50176314fa1d3d707a896d864050a185241645690499826c965bb62fc7323fd12af1f6202e34ccd44d836be93cf1656021c57b71db3f9987be3b0294284eadfa29755c02064de85c272063b720ac267fdc72143df5960098884634ef5f991aa674bbc092262fd850371727416539533e8e8c24138f1104c7d89d1aa5d2f114ad391daf342eed5d3f3e6e59d49038e78572421bfe1f77291b1e3f5043c1e9cd154522c1da14ce424a9ac20ee2b0d964d16bbeeab0c85c6f7415aac39e869800eafd19901431ebb8651947881e8b64270a9cee6f2558c4b1cea437cbc9703d7dc090f7f298c84107ddf3ece85740bf91360767da4a321a3553a3e3e062988f344d50d28980458f402833e9d73d1971bf879ecedb6dc7da85432bfbb30813944e594a9d8b1070935ba5860342dfd3974d9edf1e9e2c3974ad642972283fedfc430854fc49865fe62efb1eb02d9efcbf2c9a30c698a3ffc7dcd1e24c01a0168d719d6038a19909a2e38d60968e0dbfe8c8882bed66b59cda6b9376696e9a64c96ec13dc5fc10eecb45d6c1b38f3afd3b64f26e22d60eff0f57b09c1b593618a7a4be0ff30107256548a77061d556d271a0b8ba58ed055c76eed12f5a21e151bf4cae9a3cfaa84b39d76562e053aba7617548165d044158ba0b423f035523451f8266c4fa8f6f0715337b11af7f57ca253e7f6b163f9e287652e2b0cd8896dcecf4b69964f50d4295e13fc181b19423c89cbdf8d0bd36385624f0ea4098b039c1ced49282ddf20fb5cd6a85f0d1005030a340691c73dd2100c4d9a8700aae98d16b9388a64c6eedc926e013ffd40e2be52c652b38c526903954902f3d004d45d31cd27bc9e4a33d2abb5bf83f2459e43c596a0e4c365dbb35b6e7974c9b7017a1a9f48e192a706e8ad5d12a6d422a3e7b7c053a60946eae3c31d59ff3c0dc51a0606a7b99c04869f0fe9c1eec341238ba605e244678054226a1972a27f6222d9505c6ea3fa9b8578e06b71819c6f5ced8d06d91ce026cbfb4944cd02a83321951494857bdc1db7f3e4d4378ef98927c1a40ad95d411264534b7d3c78350a8a3e6905f834980ac5124d2d080b4fd5ecea30ec52ca65e177bb7283f89c929ba2a91f1c73121ce72460ec422e28102a99173b7caca3a2269453b7f7eb482a7750799459720d30004c40b33a394b6767ec35a83495da8604e4a2d2acaa81a1c27bd3f4eea7821d5a452443fa93064d10a3fe10ecc222bc50e6318a616495d7214da6df3b9b74bfb194c396ab5a48b6b4895eb52ce0e851ffae63e14932cbd7e1d1e6c8a61ce6db2181a19961d3158030b7fd0eb55e97bd85c441fc6fe8badb23d60f08a0ef9534e46409a59a19a859acd8bb395ea9578d6fb3ce97a536e0023e9a25168611fba276034c57bf81fb64639b0ce6c5febaea97f0c6bfbd202f457e9ab5af9f59125dee72805e38587b8eb67a3df5c3a5e8e3d75d5ea62beca0222d796509b9fe812dcd54457c68402cf3a255358ea9e23573c8edf7b4616ee146e42ba717299d504ca0ccf26ac56d7e239db9c00dd96e295735a6b0919b4ce6a9d3b89fe25d1e7e56e6b89bd5d55642ce11a85e9b8debf7bb782e969d604259bc1cbe3e24182a34432807660f951ea023c8f2925fd6ae9b00b80f1b4ad49a180e33e641e4100b3b2ff75b5643894225886362a91fcd3a9d5cbc1332991ccbd73f76847625da3f848f1c9d90cbe78248a83cd1bf280e63ae0811aec9b3dcf2aee6bc3b35ce0186d222807bb811ba6438f1ce3268e640dd540c9962b545da443cd48e8ac887e5ae4dbb9ae7ac22636ab7a94076f1a5cd145a310e6ef5a4df8788cfa4206954714517ae9554615cf840b229fb0167dcfb4ee877906b5f57dea253275c71d9d6d7a59bb182fd492fc3814c50b0b5addce4604e2c18d1968de82d5bca7c366aa66f050ef760c7f8ed8285890bdf9ca9c6de78fb26c41f74713e9a01ec9debf1bb42faac41b6dac762b66dd3c0c028e8e4009d7e91f16ca77e2452b045ba8fcd30328ddb2a38848b0fe3065be2271291967990621898fda99f73db0d59cc3da722a91330b841405fa827558d4cde5912a892b6d0170cfc50a4b917fff10d9f769dfaae263e144936f1fec1d6ffb88e72df1cdd019d4ef2cfba49c688541a9c67839d682e9241981e46602a23dce25b16ba883f4686a2fc8418b3021e047514e0e3d21b00408e34c327054187ffd5abcdaa350fd2ac3c7e31e8c059a84215a190f1b22c7a26f5de481f084ad3f8777ce016632d8827865d2c888646e5585e349f10cacc706d654540b90548e1a04bfcaa4b5318684ea0f5ea5c8f55789a42a2cb4f64654e460cdd91dd5ec9615912dde9fde34bb50df329c390305b8557e2d7f4ed311450f6d226c1dbbf2e16e38c3fb0bc9d4c517eaeb1c889522d798963c038df42fc6f77cddf8887721332b4a7735ed2fd2f2d1a9a50be27bba4af8898e16f4248a5892a43acbd16ea85f456faba1b7e659fde74d55c5592e7666f162ec2e8b6fd26b4348312348f446ba28f4b94060d303d403bdd31e371f55dbace651f4f7c34e7224efd263b50eee80cacf73cb5d69c13a0e0d9a98593167b9c9ac68a1bc48e3cc5c02d780c3ce0c9978dbe8f55904796b019cb958062717379ba3c5a761fdc3f27ee86d9dfdff0e8c3d24d84eac00af6dd2f74d048e9af496b0aa4a6876b29a7493069df08558e9414bb2231126d2aa73289b39a4579aeac0362b983a38ae2e98081161f6cfa0d1eab44419a6a878f11fe5e3ca5d4f3693f8411638c6aa66520f6e2e441a66070302dc6c39c653d0f391e72518f07f5798955ccb322daaa433742548c28c297ab40bfa28fe2b66ff74a79e6c98cd29cfd65744a0c57d7a32ba4d44df7ab60d8cdba3772d56d7ccab5d2b8da0f228c2e6d6e5a2171879e2e5001bfedc1dbdaae2e057f4e1a0ae3024dc5309958f58178914299baadf7e06fa7fbeffbca11de7718a53b8c3bde4da4f6dd4fb8f9315e94e4dea31471e4cc5f312323a44a0e9bd375b7657ae4683dd936925003c8130aa65a0e5747e06f7cb1a82f92634166d873e692c5dde791b91d603e961dc3f80164234d27de92ad1576f05a971b1bbd51224c492f240ac882b34101a468179827c2023881457334d191883886cc6e44caaa7a5e9ae014a09bd45a40ede122442588939d7555e1c4e32c6b5b7ac4a386440ea4d2395b1a4144f88bd7d59fe9d18ccb44a97eaa81a8bb2df7230cd888d97147cbaadaceed15bc04be58fa84361e3e9b807b6597c700ff99a58f5ddc6a016f3df8f8caf0b551d64ec993cb86d515970a511b22520e4be725d16cb747416abfe4a0675b368569db78a3f412ba3aaf098a5367543ccd335a71e0618636f6d910dc7d0e14c72e9178fb93c63b24a88e978c086baca9e80002b0191b5fe763e6c597b9526a4904ed80bc658d5b7dec2f28a777be78f1fef8d6f291c287cf78c18702776ffa6f8ad52a389fd085f6d3d591e8c1a5464e6982cd881c1d002956a9f8dcf655515d9f80021f16eba98432cf0d57fae331b42f006e07b4680bfc572778f26c02e76813df5c8a0e9f6e6d5948d7a0525b6d63f7e99a964c46195fc0480bc5415d6d0bb8f4930b69269c4070261d97b8cfa74775dac36d006211e134b44c5e8eb464830922315339593e31b2f6a8dcbdf92c3ec6999ee91fc2169324667ca72a7ef1fc59ed238a89945a0c35a6ef0077787c783fa2839c71e698bdff419cd05a65388138fdb6afe3b9ce39a9748957053b2c93ee487976ba3c84813a08a4f227d01db6400198599c5ef6a20080b255a0dfa993f852a1791029aa6aee9a6ddf36e4de87920ca457bc6e1433a2f0c8fca39d12fa16d690a2c0785158ffe80ac9321764e621a3f3f91f658119818110b8e3d08d45d75793da55c721d4e603d5ba3be6d2a3f2853f0d9ba282bf1c9ea9dc9c2c46350d4c9145c43a6fe1d75184b15a782bfab590c155f34f87a4b4968da0386f9d3e132d28f9411bf087764b9e858d79e11a0d582ba1763d88d93aa6e08dfd6d1bf43aee2a8f7026a1bd47a6f192bb09616a4cdad9224eb2d0b95459618fc8880369299522ea84c93b9ce9d782ffca24a609a34b6ac368926d0198dd820367eef3c266a07123c08764ba1060cbb016e7264fe1579331909247630480eb8b6e8e1753e6e72c73d6646dc6fde6dcbb1063a588c9e45356f338a00aa12513829095c833ad5eac9a30ead198537e20cfdcff4a8d854a95540d8f358aca745da52c7d7a5307d8a5c385b08e5729fe966e08c5f185b03dfa36074c69b01f909381b24047f818893aa3f2c7726e04e93ba15de26c222fcf4d7e36f428200373697ec12e60808da3c34c5e800c140011aca0140605832a805e4fc750f3cfd0006e801403e885aac7c43a8035ad0074e74158523a56b5c79b352579b30af2454034aa5a4565accb9c6846277dbe79e10387b04183e9334df460a544737c6afd51e6f69d55f947243cbfbe54cd6a1992aa4cb2019e9de65ad0d6d6a3aca30e9d17b64e789c728e333e5ea9af06c1bec91928f1e2b55c93f2ca0be70226cc96499109afd10e0016e75555b21b55564f05dc9b6f3b7f70078ca5f60eab8f81093abe01c561ba724387e13f2e6633b0e130b89604ab996f951dacbb62c32cbd39c745546122517a17517d0bc9db71ca5276b664acf62eeb7e9b8c6e579dff9794572ef335a32268c3835ca5d733bb4d039d0257d259c91a45b8fdbd30a4f05d3242c792ac5c540ac9dc1e55a6e1b16caf5839ca246bd8c7ec6a36cc597d2b07382b22feabbcb729d47fb3000c2ec9eebaccc86f00694a28d4674f94ee8fea2387a442ec5f133872ad05f58aa058ab47473a23ba14152ddca028a9d7d422f509135c11e1e1f024c9e309f0b879168e7e3e4566b404939631775c12053402afe5dae5ef9c145c7888d9589a5b832d191f9c903f1e788935a78b3db231b61b9cc77163950f18de70ce430c1d52b2265ff304b9c344b00f1e1e4a6971be8a7147b0353b3d906795921a7b96dc6a6bdb7ecb248f341a7e8383a00ea9e55fd129bae9c043553abc7804fd37f11da45359762a0227cf5f6d5a472b46aaafe299c1bd7b4316f0138b99b46a5d6627dcec9559db5c863ef0dd122f2f161c20c343ec42ab761d96e08eee462d082576acb4a629b1e34c2ee250eb9059dc3e5952ff9825f53a737cacb65eb3ff7a6c4af2289ebe4327679ed145bbdc1fc0bcd2bc50a459839ba1c0f846182684ef355ff2a231fac6d58ff3b7d1954e5e76c5d95281480c1d698f8de5119b120f05dd592b32c47640dcf8dc16ae587c6d7066f1acd830f12b9f053789e23d9e35bca066be77cab46ab767818d33fb5ccdf0da4fcb0aa6323f6778f2d2c130cc14228d38988fd1d2622749d6391c92c5e635ccc026882fee75f7e8029495e7bee9d702895f8d01d78ed41735d7a26ffcc1341f2f8252218099370f7fe5008b647757477a332560c26444f3d8e86a7651446d10f80a73d8b3ecbb8c59e09d9ded62c3fd2cebd45f2465d3026002e7b3f0da52527b8d701837b63f44499f4bde2184c0b50349d9f969454f122a8f1faa82ac8e9463c4c388b853952efe74422dc2322a4123b04f7c1981eecea0e7634a3049255c819f8c37c67843b1c5aa621e12c9a795b8d2772702c6861c8867f62b3bd7943f1616b654ad8c755ee2a6fe71bb9c0958016392f9dabffc41a57ba9063c0cb2287470c4807aa751ac2efcb4f73287a6a435a6f5c2962eeb75634265ed64960f4d55364950fdc4c896179c1feb7588236f51684b4e45ec26ea84285a2cbe3682fa2acfb13995d5c457442c2cb629fd35137d6fe25585a65e475a63dbe9e49e102ca38fbf066d921f55afccf8c017965a0afe59061103601411cb249e7316d0fa126400e6c8201b81b4c9275f96b27a580dc3b28e5cfca28f81986118d57d0c054734158361dac72425612831a6072a9e604cb5bdc051c520d294740679bbd15a6930a3d9efa02049663c8338ad743a4b1b16d051283ef9ab22d5c9456a0bf608491a4a37d35d461309406cc324ef5b9e9816a4cf0d0722dfb44a5d965996447c59f275d943672145a9ed5a224a2369b0b19a555cc8f9546b50f0bc54cd7edff8aff96caf052705526142d7c168b64e385cc9639021d6863c9c344957c33304062c5a6b3944ead6096ba019a4533c96d9cda99a0992c49797ef373d97a09b43b0f5af0aa165a1ade6dbb4254b0f986eb606db5828dc6fbbed0670f0947466bd3373c0406d58cd8030cb29950743b0603084e3dc82de3c6275befea09063b4379cc68497174f0b4d63bc8de6b0a650389761ee28a1ac6658ccebbcbe33695100203cef747afdb5636fecbf09c6465c3efc0bf71b7b64d8e214220ad21b1630d7c4884870a25b4adb24434a50aedc8e012feacc4d2b122ab3163ddf44a4f6d8e742db741aa879fe36d2f302dae923d600cb82917fbbf1e42b4ee1803688d72cbec56628366b7b8d548c2e42800f956696824af215a287be10260a82b605ee241e164c760e5c713266d05a3b3a145d38c9c7eb7466a2e191dc003669509bd110ef1a586a6aa26c4b40a0f3602f84ecb360d215a74483eec44f3cb43936d13298b6f00fa9df7809e94350a525ef1d1018bfa094737ae13cf474a0dad5ca903903391bdcc2539376d5351f46bbaf4def712ddda897a60a201293329c35ed95227e7d0ed758d1ce4675d091a1fa9b10b2fc7f9bcf11830733bc11f159109a0ab42a687959f05fbdd403d277f14de9c3c1bdb862a1e10555dc3a44718451fba468aac3fffd5a0532d0d13431848d46bd97aa184abd5f5cb5aa51ede27b0cad16110cae6c3a5272da2d73628c84845de06c11a8b4d696f94aa90f7c17bc7b1c65e1e1c9660d2ab05fdd2b87ddc2574ee1cf0a50935d1824fc06f689d53293a532e4e06d94ec2ba034e6f4a4065f693c19650b4d0f53a8ee303b634d4acc1610e86fd6b644b54593a1fd8befbc682d6b41eadc017885b199cfa447240b1c9b2c4080f1a8040d31d002b5c54d41e3dcb50c397a070f495dddfc3e11d17d292e85c5d24341a209a8cefe4f5073a045c7e6bee62e50ee57de597cc15ee59c1f15700ca672de03c88b6fbc680f6baaaf5aa10c51675913b48b4e5e6f963bb39fa7af33f7b1383cae97467077d6e7c6bc52e1eab0ee43316615ac4c7c87a0ae61cebac20c9c8af501f169c712a00edd16e5d628574bee056c394e77d43c89819195789b4c050a890148c5acc4ccff6f942a7fadb3bfb0c6751883173cb8e6113ae4448085ad6e4151f38d294a00d857b59d0fdb1ca06c420226d85a489eae68f9c90362d29bfcda784725a0c31e0b032fd77cfef4f1c2df19f5e89b90cd86ada1c7c94ef66ec97bb0a8343dce6bbed489738cf0b103300d57533392f52d609d48e2dfb24dc74feab723082415528e9eb9e689f860039b8c0beb068561c20f0fdf886303f77e1f7606952531ba8b2a34a9cdf29a21b040ce0d53d565ae69e5515fbf95a684a3e229a3db52ef1232dafd0301679790ee07b2953b8fe300015a470016e374b9278242f39cb18c495f6572bd3b73924e1f60ff03a3c3217f68bad4a15e17400032f03843736baa8d3f09fe19cf1c3ff5cd77cc739abb1d608a63fef7145411e6624c894d829a4dad2d10c58c5ae1ccc3fadaf376943682700cccb576120a4b85fe049b04a719d6dfae9fba036db4f82a7d8b62dc63a5a639d84a643d0394cd5b08bac01a5e0c1f4300b2ce2bb8548dcdce7b6daa4aeb37cfec8c09389293e386d91eb2668a54e16c1d7dc7c1b1809e2c0cc8b2e9d0f1f7bea4fc49b4082a426e8ad75a7c9bfa8434455556cdb5a71b3c0773cf89cefb5910aa73003888bf258437d9d4b38279499d7e066395a37f7526c4cd8bc5b78201228fbc40b854ec52f9e26791016363639e1ca8188e3685657ce6da55e0de70b2303bffbaa313230b4193b98bd8943d56f887a58e6bb59bca997783ac30f39035f0108c7e8eac66c6853d06b5f506b5a17490cc091060bbbe7f2225083a0b4ff0fc88be91bcc8bb1413339b4aa46a1596455fbc5888c98fa982e22b581c564269824555258f95d12806ad1ec1d69558ba2e58c4f552afe4440f1cee1313f3e1bbcc602f6d0501699294a7a97f5e4842091cf5343d0be14dc609a61f357ce4f656751057301ae899f10ca301d38f32a2143280269874e9e837f3d51a3646d83570774b7001ce8e1a714bec50ed97b2a887399ac4f8507170a2acbad935b56cc5104d507810e905bcf99fc08270d29bc8ac7f9b7201d77efc21c6945525ad9a5de007f5972c9afa83a12a013e4040550eaea15c628e94f8124c8f75004ca411845b42d60e40e968fd044d96bb658aa2d2d5905d75669d244f78787d5b14a2ed93f8ca9c60038c0ed6d7e230c0905e5afba66b0057dfa2f1bd72a0b1f5a7a72bd8c53a9acc6494fecf02c5c29193d9dff781a54fa174cf4a13afe8a99141e9a74061b019e2554375717dbd39125ffba1921c939cfceb7d8f13cc78d92ed84f32469da601f15ea83f5ef1f965816386948f266bc67cd73f1f818a3bf504c17596be81819b494e85d8a56cef71069cbd4a2c5f03d404a5df76253b20948a11c014093fc30bf3d6c7e243ba048ba8d1e692e595517109a5fc365be5666aec36f09faa915187558d784b56147bdb0e2d1c9f12f49eb57878d064de61304b4a7184da8d0fc13fc53f1ecb205c1acd35e9faa57026602fe8195c4ff991b62002b06f9110218d0b98abdd14a58d0183eeea041902066fbd2ff1aeaae7ad2b98301f05e4daed2a32e3387054983a669a3c98e39c802647227634f5f949451b7da599925efa851b5555cd09f083daaf5eed4fcc2431b78de1d6955e1bde2622d24766feb788f3478e82996dd851160beb214b4b24a1051b3dfe817588da275121286662fee488cd3e27d20273411d097983333c64af05fee29e61ac59750c0a9cd50e2be0be8e5eab966ec67a4d279e8b522d541e2ef4918801fc6279fe1d00a573e7a985624829486f383ef16dcf7ff191119f8c7b5b0adc42b832890df019fc5e180e24b386290e94bc5633a49d9611bf2960ea0245ff64eb6bc5c24cf2557dbfb7b7bad3689d8b1ee236a59a0b4b9a867f263d1226b6210cfacf662695aa2f2cc5b4130acd0efc1399295ae1c52b2684d107695baeeb94463fdb442aeb4f67d2fa533bca4a957e25d0cc8fc4884471ddfdd4dfa4fa1691b21aab68e67c825d0a044a51207da8a329c95f77146bd5d7e010148c1a509c158851bc73b1bda92696e6a032c766ea33e0f0c6b9825ab3012fa54395b2cebb684cee2d305eb7bae1c9865d1e6d50257adf1986d074479e9653ca99b3beca8e4e13eba39a12bebce2642e96d97d6b42636de2a4bf006c627f3fde03e4fc4e9a8cbfeeac14ecdd4eb7dadbdfc6404f031b2f247f75667eecaac9da189aba8c3ab2929908c5635e88593a8bf01d0ebaa5bb2676d4c1e359f0b6a2a119327c39ae2e7030499625c446e312787f3808075c254b18b0c79ce95925e7ee8c395db2093975d1c985c48cab7bf43871736bba6783d52e12c8b2fb3739347fed73d74709ee11d18cf909a29eb7fb7fa33a81b64fb2f0201fe4c73215c262cca24e05d6026bae3a3ddb74536e6316d78d080baea1d0dc6c6578d8bdc9a477058f5258380bcad25163aea436917a5c6aa25d6563ed87b2b2246b20a7a83b484e43cadcadc037f69fc555b1571588fbe9799a43d2ff3a27be6621dd9a9c36be28ba4535ae26033f01caaf699a669541047f5b800d3f466c6894dc0a30ff214cb269079b795db8e10d9f6400ed09f58baca8e133e9597596f2b63358b03517c5731fcdf4847fac2b81bae52702dc0cd528cb952cd27543366979a728708f221e9aa29890815018ed7c54ca30c86b58ceafd4271f90c55960c64860ca6f32ea8b54e3c668955228f0d351eb899a388e69100a9c594e4c3b304a38f2c915e16d8a69c1b8820bb8d010df28c6b454288da0e00951354ab75d896769a41c6df4390918472c8f15207a8b8f34419d03161a7f339ec7d8ad5620806eae40d17ece0deee4ae0560de0ad9af58f222999a3c2394434c6bbf8437fabae965434589b04d9f4fa303533c7218b2c5906f79b63957f5334f635157472d5a3c5e866966e52ea0e7461a034693589a1121e486354c59d06d435e2bf3cca32a3054ee435f800a7bc5f91680e5099f911be875224b9b4d3ac5b580bc7b5a00e2d5c77c6a3d256e9905702d7b7535b0d0f50af053f478ab6e062262ad80221cfa8c976eebdc80fb0174c4be0efc22fffe2a8002e47592f854404d50f389bcbf4a275b34269fb1a7ae191b68d59fa2d6b0067b48e27653af8cd51140a93af60d2dbc6f7c681e02a183677246b338b4dd16e31e12f431e34ddb229debbb28401336ea4ba56576c0def1143375f9d8ac2c81d4da3f157c2c67c1cbf5b59c15b17c5971a381e0cf2bcbdd72d0211a55d7ffe4e5b5cfde58330f97099b7851c897c3d241a2f0b4a7d68335d0b960cc8659592ff36404ec68e8a335aa1f648baacdfc799a81291713e025b7ad708b40e192ab6d12fdc7da4bfd17c5b707f8f67e352280995a332a6a8a1908d952f2c6e5394f2c48c9d4139f8b43d174f1ea331055ef6e8abfce304d26a0849ddd782cc69bbae8fb75c8a677cf06bc33ab4881ab7e101bbd198525112f796e070d9e453c645509bf2e5f44b385a471f79150fdb08007801c7e71ef66573694173b4f8e6a8a4f1670059a868566f2a2aca415e4b5d47751d89434593a5ca6e46ca02ba80934ff63d1ebc089dd4c5c235861b95ff3266622e986621d92f86211ad1bcac0b492757037db44c7eddb4fd2dbc56e98cd2c8263b042b7c7f89d73166912ced14431dde74333e03a716bbdc77b7dcc19ea1165ebed23e609f52548589176cab224ed31853a73a6b59299259612735f4c2593a9e02b2e32edbd5da1997ff10fd5b853d2f0c8dea91e91dd45c46af85358273e064ab53ad1ec761d42388fb2f86f0d22ec3530b70993839af385c1d253303ddd55cf4f6ee8b32b923b91b11129bbc8db88dc9d486c047146dc4b418f2d91ed8bc4dec86c4462532477223862b440dfbe48ec8dcc4624364572278223c601f4ed8bc4dec86c44625390274610376c896c5f24f6463862342b84e9141c0e21ee49ec7d94c594048c277381af9d3347db3d0b9d3bdfe2dcb54f9e0e12dc5cc283febfb1833960077a400773400e28a1af833b30077a600e74000bfa76b007763007e74006fa3ab88372b00719a0d7813978074edde8400e7a568258d64c5e9ba778dca03313a4dfb379eb616c8325a50edb0583846c2f87d25747cc023643889c08cf0e8c57c0750fc621e4b9c3e088f1f621f80630ce7ee77c93c5f160c08a9e796ec9a910a37ec9e1ddba9037c3dbdc91d9083f41c4aa9fcf5576633efbfd1098363215e12340530e4b61e0ad9cf543047d37a95e3ee4e9b640f6100752e34c669d43a5b0fb5552f99ef040882e980df59bac7809ff17f3f2b20a4000c2018a640dfa958e845cded8c5484ea4f3021aee11655c304ec29a0ebb16ff5f56e63fc39299a387f274685b5747e9998670c5a3e276d1fab7b438334b7c4703219e76fa2972d77d0210200ee70f898e8ccda6e20660d00fe4e1921dac7c74bddad86b88785eaa4f5eba91ddd6e49652262953210632061d06fdb5824e443a4be0fe19c5d3b7ef6f41f9f641e8e7427026d64c5915aa75babbbbbbbb573add4be0bedf8225acfeda97ef00eefbadf4e0be4359fd0ec225d897a1acd250c7095c448f6ab05539c1734fdf8932eb57e1f8df77efeab93036c56fc4ab9a1b08f797d5ad56ab5508649432b34020abefdcc9955c8140ee4b5b1d774199989ab1c0c8d9144539251debd397b4863fa7fc7ffa1e5271aab1d17777f76a694c61cfe397a9f59772eff7b9cffc09e23e3502edf341134df588b56654da6c4b3a09030ca6ef9f05729f2ba1f55d09567ab4e6dbb00f07129a370cfe04b542d990f7b21edd8f9fc8854084d451def139e867fd0565b3c0b148e67c3c608a9e573be8fbbe1e677486c0fde3e598743df33b438771963b1d7d45f002350359bdf70d5ea06618abd56370c5fa156bf5304020dd7b1f7b0cc6bef3c0f1b3f7de77fbc87ec4d9c30165600cb09b56d37ff32f4020fd37df7dffe23be9dd84ae1f85d4fc8563ff05647ef117dc802f2e009bc78bf1337e11874d387e1f2c1c31ae09c79bb1ab7b0c76ff02473a0aa9b9c18ed5a2114cbd876f5e14a664528434abe0227f162893c910842e6ca7c958a1e8404e9b5ebde16adff5458256a1acb6be7b1908adefbe15cab81f321bca3e60b158cf0a89b4c22061b5d5864fb97a4340402ec1b1a546cb932b8f8c7bef57cf02651f78bf7a191782e085b2fbdebf0c84ee59df85b21bbee779def845825814e0c9351c87b20d45e0c9228e2c6528abe1883f4976b32002e8c071939249344cc2b7055644206bb596569f866ec36e77177ba7c7eaf5ed7b7d20d6ddbd3a457266caab4ba8211f3f3f4046902ebd0dc3a55488236817da210a09edb00109dd7bafd00e1bd00e2120a1eeee242f58c1e433fac83cfaf8740d8a2874ce393fdb6f5b5c619e206990d2d5246a02b289071ca8a5943ba6d8dddddd504050edfdeeeebedd7d47af88fb5a6badd5defbddffa5e0829ce5ac550117128b7c09b0c0e8a0f9a0061410e13142aa68020cf8cc10170ca25104a40481254788eeeef6ee6e77f791b63de2414a51d7334969eca3b4f114297d9cd94341b109cb6fe2ab8f4c04b68d93674875825841fbd0fd72c9a5c2fe4da5ec6944e2f81eb07c9d234ab822822daa18d992e52badb51e81fb2796fecce04b7590c04d44e50ac745342cd16cafce83bd78f1e2851be39aae69ef1d9c9828048e6151083c5251082c25acc5a3c39faec50ee7474a29a5a45f8cf360bc3e0ca326064c668363e3c168b61737341b0d990c47c60c0c30902163c68c7f100c431a22558d1a39399e939393e3c178f93166c81e07031a349c068d49e31f04431a3466b31a357268ccc290068d598d1a39393a3a62ac06cf94ed60071383355a1dcc3047cea494f646bd7183deb871c3a7bc71e346e3d0abd1ea60e6e8481d9d594e0d9d1c9196a3a3238a349a0d1b376ee010451acd868d1b3770e0d8d901000032c8c0c6ce8d9d1c36b4ec0020c7cb86961c4a3aa9a79c12f468bf77777bd7eec7eedf7d710b4dd1774cd11fc70a1e3f1ee9ffe1cc1ed95234894e7217934b9dc0020c467460a2a10586063d1c85fb21e04df40d86c0f3e3470837a21f1863fc23841b51083f887ecc9e66ba7ed16c9266833de549e94b29a5940f8a2066e9af19ad5556f938536caf75d2ee0027cb6e3a83e8054b3af1121eb10d2db80d8b378c2de30177e8ddddddddedfdb53bc9086c69cea8702b8e4dd1bbbdc391e6af1d6856b025164f54ae3ced18b66fc3d8873f8c71ff4432d583ce2f46ef14bf89c7eaa4a1d71d5ef095058fd78176080109f51fe0bbbbdb027173ad82fdbf3c5ffe6cf759ff87aac5b556efea6e6b777717b100a54badb6fa6be97d3a1660a48c94785a2109c7ca51982954981005942da630924221469a16858476d88084eebd5768870d6887107520a109f401fa839254ea26f5bb25d0cc81c2f5c11607388f3064d22a26e48a850b172cb9b61034e2c8d589cb0f4ea79c5f99fc487daad5567f0050d299a59a2c49b43815b8a5726729a2514a89347be495575e79a54492455622cd1f21c8a22237534d801483852468985c292b30c6104043dc0619e22e648a1e44c810ea4186b8d00e3342660f111ff22165c449c6f18f05588468e244c9e8367ddec250d5b085094f5c61540413275390202751c28aaf50e555070f0108103bdcd356c01308eac77d866a4b280c76fdaba97e701f1e09711f36c141dca73ef7370c57c04342ee3384b6824c917bcc0496794afbf87bd8c7a1ec3efe0eea515f76c32198100c0ce234ee6bc0214ee38aa4f0d001a6c87d60dff53d2a0f29f82f781d3b8d8b31041e22648a9c58059ebfe2be1f7c47f17efb0469eeeffde9da7c8ebb1cc75323c54dd6130732cf8ff104cbef07f70659f68c2c7bf68c6f83194d93dfed44963f6e90e543a06bfd72ce88cdc05e249554d22cc0fc955d8c4081a4592bc953840450595258e2141585094e06314078d4bedd71cbf6df4f2055d443cfca4a1d5c8b07f582c06d63e20825d6978a3411c116685c50c10e25d8d2c59115a44a290dc2be8ea420fbd65a2bf327f34783a0ec7ff6dfbe689f67f6d8d79124c8fed0d753467145e9b88c6b92ba86c30f60afc918f88d20bb502186d35698b1691c6545172e58129b1a28a46c9ce03045302baf9798a41a2d2f179924ece5a635e6e97585181b6f0c92eb0a2c621d99aa169217ac32549e139b555177a575a1686295c0c53de1b40a22669f90ba58dc62950c1487c5153774cccd6691e4290b279803314f59cce0e220cc2d0b2d2f0eca30cd4f8baadb6a6200c40565badc682153042c0c8ee58e2223c6460c66e58e2293854d127615d92029b3248fdf4213581afcca1d55e626aa4c962db8953baa0c0f0aa89a8a82428a4c73475521ddba9e8db1a24cdf8adb99a63af3823d562b77ad0e5ab9d2f7419f3235149906711afd5995499054363953d75699be3fe9da741ff9f46d98b04c9152ea32b468ebc73623ab4cd1690c6ef916d7d377a6d9e33d7d9761f6744fdf9bbc8a3bcd9efb3d4fb3474bd7ea535738360a32fdd17768f16875156cbd7eb4effa1638b36c79e0fa5728bb9e025ca1ccf532bf7e456bec6b8b070e31c699227dd710497cc93574261a055faf08ecdffa7e31e378e56e555776a74ce9b77e74261ead90678a94e7a70309000a4db17b504aa933fda44f6301fb8f35565455574c30fd4b4bc29d3fcf7fa069c6044dbbbd776ae5b8afbbbb1ba445b84fee971183ec496a31c1239d03c8fd382dd474e47efdead6802f9c3bf157980aa006c07a8f712d83dc995ad0677e2981c75bd37a8141b599f362d430c197e72747eeb7a184c7bb0280545203058f94e5e53081479abd761f2bf2478c6d1d4ffd70bc8bb10de74e7a5caea037c58f61d3e261a5add4e7bd1c05a5b042efc3f9cea0eb1b3c53a2d4437d7865bb562b48ddab38e63e533c52e2aa77e44d2c765b3cb42617cd4c0c255e228803f67478300d3fcbdd49fc55eb2b4903eaa1ee9dc9301ca915305a3cec8d95b1b7bfc40c2578a417cca07219b99141a3083cde4f26050c9c1832590ca88f0c1e29ce0e18d8644421c3a7d837b9df7332e382aab0cbbfb85d2df078410f074beb1ea59e5d795ac71ec655826ebf135b3cac8ecc553695df8fc1340e0ab3160ba60f8e4d1c1f1df933028f14e7e878f7a382c72bff66670e285dcf3ab1084cbf1371665e3027a5a6f8611fc0fdd03a806bb464fb355a66cfd8531c4880295aeac376dc6cc602671df8ac27016709fee1535deb2ed9be8faedd6cbf015df3b74fe43ef3edca5acb711c178eadef3c90678af65b208e29da6795c1dedb560b87177ae0f8dc772f5b1c70bffa9ee20a01afdcadc04f47efd8e74057feecdf6bad7d4772c3b1afa36b9ded2c5b1cd9e61ebd23e3de87ec09afc2074cd1fe184c6301d35f5dd0b3f6db3e6641d9a8776df5db3b14e72a0a961a884695024d10b7f80929e92a2ad0b515641acefe7d483ab26285d3f7c3f37d3c53098f7b0f1ebe20e87a36f23c0e79a9f07c3aa77fbb3f9593674ad7b38a9bd601ce230ca154babbbbbbbbbbb432a89dba9e59e1218562a77d614c8c925302f3bb0c756de9b2a5ec9772ce3927889faca0136554a5db8a9c53b44148760bd97010217f0b22640811a21fb5217fbb8eff830c2142747bbf17e31ebfdfe50bf962379c4f804965180c6a8a22ccd6b6de99b2e9367b7e721709eaefef88b0586191a0fa78093ce4b409b3c16cf3615d60505316c9a4ee596fbb26fba07bd63ba09b72c02abc321d30172ac1fd30295a465e1d2646a925cb975a88aa508ff68d52e98214d18fa62c5f8420529a90252d925d56c93286ec923b8f5f500c293c431cea2cd144670199e5fb038846e9344a2c988a87bd45a069d95b8bae24049dc25286919b88148a322bf77ff77f5283190ac5e89a0c0bd03bf6795a5ec7fab1c922a7d9ffdcc7150a39cd7eeb5e0fe3eefb58ff571ce2b41b6834493fa3f0060dae4fbfefd6d0ea8126d4945c41c1ce4202cf4f9ab3ae309f070df6cfc0044c9f47eda7997e064630a5e32a8ff4b9ef2194722b37114260c9ddf2401ee5910b6f08444a06e4b72d5b2ab03cca9d474b8403948a0b087808b2325fe60107448a0656dfb68c6465840df23c6265840d3210db6abe4c9a513aa2ae5dcae3fa86c2fff2f6f68f492a257db2085751f1c4f4118a406b2082cc31bf9fb4585f14e244318a12f289132f8da04ee06286d0627d21f7f92102c7fd388d389026fbff943724ea304562c0e050d3eabfc01b135075f2409ece9b567f05e2cc3394bdd65b6fbd40da0c375758b80f51011257a2a882c31332222042cc8c0823b81fbe1c79713e1cc9c2b91fbc24558ec3b1af05ab1bcf8d2ca7e538cebeb801b77247a191420ab6b9a3d08c3902051f65e74cfc8163715c149a1d32c771ff22cc72fff3fc4c44e38446863c3e8f1da29b5f6df26787328ae3be738e9364acb5b68694caa4200fffae88a554a1ff8c42e6596daca632583ea534744a8be6135dcf469c1a27a755fa3defed6468a1f4468937457a832443870b769e7386183c7a33c8e011c674a364d2ea0d52538e655bd435efe5df7a1b6bb8186529eb012332e5ea6b56f87bd83cfed5e390889555d823167b22f86dbe48100f1d2e78ac5531d0a65275d03df54e7d1ca8dea9d289dcfab1860b158c0916cae6c32c58e3c424d7af374bb93ae92083bd06a96b36d79aa45c6b9472fdee032b8df550cd77ee811f68d68432fb355f240887321b92d0037f4d4864011d84a798eb4fd60dd2cdd20d53aedd7c85ed3457f8f3b312aa2ba895b52d1eb1bc92b4fa2216fc7afc63dfa4b81e68d6204eabb5e82629bc5132c5fa3a69f008638255aec563b5d2b161a8fa2d50c715ab1f6914ac5bd7bcaf6766fdcafa3ac6bceae9b80253a9ec81b4de604ceef37a18d38fb8b6c2f1aeeabf403a69ab67812eb0274d226120068f37483748374a4db3e78657c94dd2ecb15fff6669f67061ff0dd3ecc191aa0983041212f6fda8bba2fa5f13665d628a53764f9d0e5deadb6807667641284004cf9cdf7b57359403637605c2a8f1dbbf9a61eaad6bf567d5a2aea07ba7bb7148d729a5f3522a52496938524a29edd0ddddddb1b73bab899fe2ccd205319c5972b3846bbab0e9016315c09e60ccc4054bb8fbf28209e6bcbca0c285963c3e0e5c4c31c245930b60e022c9962dd26cd9a28a980ff82677d416535b486971ab3648d60adf4c692ce00a5e51fc3e2e3bcdd64cb3e79959d445f9129499b614d762f7fddd06f27d7929d735ef1bc759ef85dd3b9dfc428a2d9d5f087027e71173d23bc5216c135de31f5d9896701043a5c2132e4a0f5b64b036179896cb67f852c52a8ceb451caddc512de0825bc1a50c296d496f76eece72f066775f557cafbbc597e33e6a67ef5e79c4eade94bae72e4a9cdd59eee0e790bae751ea20cd4e5f18507173c0d29dfa4ade1c28bd96bbfd37b42f7bc7d25aa975f73b7bbabb67c8a6f329a554babbd329d650e93a968d0b04966f03064e70e6e41a34da0beb74e22c6ec9e596d80021fbcb6a5917a81503f93b8f95ebac74d2d0655dafda985a6b2d95d2056bad4d656a09e1b4721cf7cda8322a0843c6f7618023e39190d4e0601c03862cf4f9cc20914c303eac21536b0499ef977bc18b9b9607b7cebceeda4dcb0015c8dc537084e10b5e70356ccca6468e0d2ca77560353aa2012000be284532350d0a1559ab5757ebd5d1a8ab65a3d5f2c06d301dba9ec9e994e59c73ab6e258b6451d1e5ecb5dff7896828c1f281265157dae2519dfa886f77ada5cbba5ef5258b50dc2dfd65ac7d2e6e9fffafbf1bba6d4793edbd893cf8dc361e6575abcb627acd303fe89a9414cd9163d6dc2f5f4a4a2a478e1c510ac831cbf1350af949f9573e6e22cb8f19790b52801dc9ad674f1731c3480b8cc8624c76e95d6bcfc314f7347382db95b2a86bb3264f100da6b42fbdad402a734f47e81d3f40ffe859ce0b86e5f682f1cc0bb6c16648903e4292c6d1f79ef53d44e6be00dcfd92b907adc0417e84e76a58c2ebeb73df289d32c75dc994b9fa25b8defe0d5f60307d1268c6a06d05e9af63f6c88290376401c58b0a98e0808511b7650b4a299d35c44fe029c28f189d21e4516a8291b28bd8d00416252598a0c1862a9c16333539299522a529f4d0201a50e6c9920782f8018a114e0730486ac794e757af95d65a6bad7506db122c52bc888952c491400814bce0f1dedb359f1d1310beb425a97aadb4d65a71fdaffebb8f90322cf0d242540c532a04d516eaeba8b5d62a1681e737a5b3870d8e4441454c982853a0802a19f9000af385a6468c388cb32dc1379329689c48d1720407ea42ecdb028f78ce12d0a3aa15edd50d27a5ee5c3e50624c135694f8210b961c8e52d04a236563b13226092d43144181807b3a9a42626138c20914942788d8a18923598e8058d23f9c50454a133f68591286c301012778628317148e2091e486231eb83be77416b220426904383c8581da01cbd10d4be45c6240942566682285872e5f381b8e4290445671d40489cb3997649723252a6028466792a6df8c6e2cc870b4830a421871c28dab41894ca5f0fcce34538a5120657b80871b94a8f041062348dc09a32290ea527f99e1a6e4d445143180e04a16166a027ae8e19682d118295c7032bad277ce2065b75aa8baf2a54b1157aaa081ca11cbd30dc4962aca18d18509a6aa66304281f55f1778fc66de0563498d8ce6910ec250e4921d8eb8f03486872c56ae50a11ac10023b468e14a125888c181ab4266059f2f340c283b48e164459507ce70549448a1bec0802f634830834d8b12482300c37d56d8c42224a5b4851e8c985088b203143e4cd972730cf7ce5799e1407907ee7dfa22a54beec4194b87a98085165a349159418ba629763ebd8d93a04b2a5818fc87521b2ab08862429417262704514e4aa6f43b8347ecbee5de49291da294524aa3d29cc994524abf6978e752f7edeed99d64b9bbea56dd2ead948dcd64297f1505ee977fbb1b8fc9dd8d6f539449a4d0f0ed0fa4c672dc722481479adb7d46bbbb1be3e9454a0fa9aaaf80664a29a519cf26f8b6cc54724ed91fc6153cdf45e09ce4b79cc0d3bbd46ddd9d3dddeeb676944a5a43e7503954d56784c0e51c533b68469908985f9fcaa0f92fd95200ce40a8ffcf105f196f07b0ec3650b3a7f5f2ab4d4ae9c94eb2e44a5ec949a9775bd790ba465f862d90e61691dc7ad9aa505db3f58bff142e2cb40f27e5b4d9b5a4ae512ecd13577585333385a37ac2dd9ae4f1662e1cb9a9f15e2dbe1061a748812ea5de99df5069b854e560e60ad5949b3f99921ebeaa2c08cb9c94fbb89e4c4db95da1cac14c767181caf3bb241aba6aad5277a995c3f8ad2cdd1ad029491042b39422190832a8be0caa219217541f3bad5fe62fb3cc8357f67f65291aa8e1759acb2eec77924ed124683ae04a253598a14d9239a4e89a0c6d077ac77ad666ed5b9b8dc2daaccddafef59eccf274ca69f6efc55315a93a55a47aa55255a48a54912a5245c2e12bac5495aaab542bfbce7d46707d5a5555659f4a75cd7bfbd43e25824eb94f4d6893feb6c211076d8add6b8331ecfba6b2f542fbd43bf66fd2b892d3ec5ffcbd9243b952b6b2869aba5199e91a0c2ce108f6364fc42694815053820d11d8dbccd610ac4850b7780c5991ddce5e7daa4ff69f9ee613959ca23253e5458ee44953724a4e0d994833692a4da6d9349d6cc75a5d4e3675956c924ef249da2494ccf7fb3ee71002dba46c85867c10fd08122bcafd9385041eeb53b64f3649c97d8a04d9b74c6e9b6890b5666c741073f7b2d65a7befbd2ff070420d5f96cfdda52a5d966f6190557821220b2bcbaf4e82784286c690e5e329a8307579010657963fef9d0ff6958f7990d292e5bd5c18764db0cc958655640f6738fe6cf6c0b2fcbed27544f7381fc3b4bd98bbb54e4da1ac937db2360b65a5ec1485a250148a42d1af555da35fb5e81e3ba5c526f76185b6e8f32e8e2c656b53a63a60ced626a90117da229963045db3a13dea1d1adaa6dea16f04fb4f5ae53e4ee534faf762fc7dff5499fe2852aa44e548548932d126ea449fa8cd91901cc9911cc99f1c6936398dbacda15ccaa76e4db3694ecd260935a76e5466aabc484249a82a09f5a36a164da4994483ee0adf8fab52a9a994649374924fd2d635792fa54fc59c43083cfe645a846493ac9265b24d3f40ee532488da867cb80f0da2376f05b61fa082c6ee5275e0b8312972e1c863c3706c9b9017d2905a4f03ffcefd3fa4061e4a249d63d6642893f4ce7c28b0ec10ca7fb88f7ce2fd709f0e325385249fb0c823dc999b95a92361049926f70f719f19c4c1cf108fd3ec73d0e180fb0853a0597992bcd3209cada8a46d98052d54686800000000c3150000200c0a0704e29040280c346d0b3f14000d6590467c5636974723498ce3300c8218638c318600408031842084c8a8380a20a93ae0ef8e5b8d2b012d9687ec3d9145f2a3d70cdf0904b3335447e2ef2dd46f5ea2d6a06ab4793a636febde89617ff85ee29ca08cf731d4731a85b16434c5381f629f34d68985826ede26e7f649f4abc3f6c357c947c3f51bcd6630ebc3fe927b066cc6b9f1840e3e007099c2bea75ec762734322a7e01e20d3129ba6199e5431b84298cf6972ad21d2ed5a88aad7b5370d489dcb5777b6bc48fba388d74821dce2f905107e6b672cd9615052ee230f3d0e3a63152427e0fa0a346c0a688207f25c6ac528c153a5fc6c01ed2ac4d88f71d4b1c0d5cb46446938589de7fa15f64c21cda0164eac2c0281609d96ca199199071cc7ce20173b22ade8a627b5c8fcf5c023a37508b197198856ee74b8c60da8d37592dd4f01cefd105f468c8beea50d7d117033795c6f4d708c94b91fa723aa22fb8b314cb904ae006ba2665e440f21953b84baea1e47635659b6a394788c033364cb8614569dd18ec72f0a930bc686a0b05b8f9047da7442c89aef91a96c91797536906f38267c6239fd1eb8329579ecee0e924897aaa05a2bb4e0e225101c0cff461244ab9af151dc1c25a1326137859be91e9625e08e7178b2168b72526d7bc41868fc05176947f392646278829122274c66f95104c3098e1981226fbabce17a2631783ff2995d6e2f522e47e448efba56555c909b79413566399b7549c3d7c5a8d419c58a1d627e0c09bef9ebfb627ca92f844a61ee65218d24028fded8676118f3458af1b86bb1d4e2f49b7eff5fa310a095324a24c0dc309092a5a8178e190102cd148478c1f843382547f95889397492f1f1fd4ae8b59a7a1acb004b0ecf790aa8a8ce4b3f678544a194c383c260ba140bc417f7e580a62d1bd822de074b8d9723f23925518ccba28671c3f14780311335d1e7443d4dc9c2c988fe997cd82a5fe9a9db6e329a8598001e0b58cbd64e00575c62abcbe8b6bd4d87f666505d7fc2aadd810610771914f0d228e9cf4d8cc2924aa54a96493d3932a41112ca7219af7046e4117f50468749ba233047b04d8a15ab1b8d4bdd1949a3574703701d08147172461659501cfcf4593c2250229acfc300f93507632f88e5eb4d2bf90f84870538107b5054770f466b3fa9642c59ed90a41d251cd1f0c97294842d752deb416da859dd690c801031cca2f6e97f9a4ce49c443ccd05a07c56187d4c54ce9bf2d81378be6c8f50e7a863093b03e47d428f1086a24eea20cb8b146c795a7adff31822bbcceb8fd65806f147481f63e24fe82a120085331a78ba01342a37831226e64e48be0a22211bb57b293ac3f2d278efe05be6713565699b9a2f057797799446c0ee4012b8c00c604b2ea31082997549d582e8c40ae7f5916e0e9b4aa1cb4dabf9f9970001e6e1b715d5d8ed35bde3ed0d0f7c578235cfe407ede500c88e609b7e239b825544d0a098331b36fae22591b06f27350d75e8e6b11280403d621814f2e1c1db4bac01f2760511f9af68fbee09db11634efcf046c214c589626df939930a96e89b39d1084c56e8388a3136095390dcb46842a3791a2f9c464efab6e291234fd97b4e7b0a3b35b717a4ea47f5ec9178f80b0ed285ba2f5aa9875e0c8093561eb1cea0039de6873b268572ea3a49cbf9d4e00588156578e3a8b065567ae06876020e2686398d4461cb1dfff025a06bcec7cbb5bbc9ec36847408d85374be9e20c8168f9222176acafd830107e0e56be01e8e0a061c965ecf987de7df5b59c309f1a471fb3bca4fc09caf03a67bfd397edbee2c70999875af04b6d0e5a0b445fd7467560a56ed6b87af8a4ecddde252b1026463050a226e17916bc202c4073cfd2a1adc14b849a87cdff2c86132a7ae1a398e3e1a0670f187dd577a11581afc642c743cd669fbd0c20e2349047da8d7dd9b94cefe2f2aecc3b44b6972a496179862cab939217999213a999b4465782d86fb6d678103d1b114d38d8029696038564f4777b25b71f308e574a881bbbcf90742cc37830545c884ddd209d88b344fd339e5a4d43bf149d78661d5a3fc135eecbcbf98d69fd280676426cebc26e1cd85e00bbc15b9661aa4d25f3e45c1ca049bbce8292884a66473e629fb3c6dbb330c3ea06122a67c11457d8a160cae7882e7b620653e9a92024ccc299304025b152f8c277efae720b1275bd7e7a092bbf901444ce3bf6404b4cc5251ab3fa4d3fbdae1aa87e42286997ead6da8cafa5188835f626e6a065d1c3a320c66846afec000cda43768813e617cf6fe0e98c6bf9e58504ff6547c1f96936c88aca48c3a6f03028dada5dc633b21fe8a4696dbd958170acadf12e95dc1863913b150f5a1dadc27a42be6aae1fc2397654430ac9703edaf0e023a6a32b2f7fd5393e219731b40f2a04905b709804accd02f044b1bbe7ebff2f3879709c2980a54b7448042fe68d732ebdca18c0c3a12a20641bca3327a4c99920f98678974be4acdc3f193416acca76a536a2c66d41fe7de3c25788442062fe0b9b83f6b7419162ce584d082a73a584e3ecd25e4b3a4b02f67fceea2a1fd0ed959a6528e4d08d52c90c25ee502a919561b393f63882009039b48c24907ffc55faec6c388f25f49590094fdd680b436105464fc4d216decf73fbc44de9258ec94e2bf6da862b74008bdcde10024ad4dd125123f9375ba7026de6da164aa2498cca06535fb10108b88506b2a054072d75a352713e7688cf021ed8ab26059e2b70f47835f5748a23e9c079d963e960060ad0e2341094073e345746b2b04f2b7c896054f7fa34c38959a98bc2e5ae4318bf67318ca4ad0bc980e545bf39778b2fe9a35c6fee0951cbd7a1e36b0ab2870ea7cba53fd2d99845934720c1309e9197049e6789aa305176006009abc2754470cef553e848881e0a017f3a8ede61de60d174d6783a6801403c6a2de6956284eb4146b51dd430c45e5ed25ee4ac73ae563873ebece0421d39aad9701c0c9182fe5d1f67fadb4b08c5820b2b8f2fcb6eafb82c014dac21cc5449bf3e5df428794cfb8772e3888bf74668dd000e9f35d63b85adcf6bfe0ba2eb094c003653d70a1170b253c7a0ae0b25af56f83bc8434f42f63455daa498080076c762ccdd1a9f08cacf4344b7b26e85ae6460b5d346d9561a7d8c3a94c535293643cabd64bf19221a15cdf9baa3653b8479938536bae7501645de9c91a432497ccb464774d7030e944cd158a0e006e256b593ba209ca772445ff506a3f2e898d1b6bb867262a33f7a88240f360e32722ea3011a411d72cc4b0663526eed1a428436794d9f4fa410689adc9ff81eb71df79b313eacac0cf4d3c1e86b090060a07d52efc18e37ba172ef0794c05feb585bc74fe8e1bd969eb60a07b9c81de99d7cfe8e0800552ff58120b2094590b01a025fb584262e9f6630d25731f1fd43054e089dfc7a2bfa8f49e4cf280c219fdc3239fbf97891590b0a6ad961c1d222e3fadaf78c567929c6643daf4223878a14d1736f6a98487bc510d328ad894272beb7b4495811fb33f04761d6c944194359e7c3f3e4e67408493ec4984c64119b1e6b0f1055022371bf4849dad9cf82b1b292823d4eca58d0474b3ae1d08e1abd63e04c71241abf27b85767441240ec12c83ac2c79c203fd0c8a2ce05974a878a84ff1bd9e113f256f16f699804e64135baacf61499491b015606a40f9e48f21efd58a6ceb860f9898ee4a0cb2f8ddc2cd841cba83b39235ff8c7f5ea5fcb1dcd7bcb056d848d8d1d126505e2eeb799746b0a0e6aea530ed594a62ee5d0153b1b4d317368b5ae9508681142a95359c02d3892421000b09296c3334b033e343451b54b2a4c41b9005abcc996ff1607a71171e00902302fa5c16a78ce8ad8b61ed696d8856a22180379c7580eaa395c654074b2b8081db12cd3729f1afbeafa89dc74083317949794c8405faf2c68447424fb7741b0a14609793a21a992c022cfe4fcb871977437bc248a3e71561c3811c514b2f41b17c2047075fcf233c5fbc78d76fdc33e05a239714abdf9335499ff86af6ac02c3c3962a105f69ba903fb94840904cef8b4243f5f7e701bebd59095254ab81b2c70c4b844f71dc8f1a468f5093fadc570a30e4e814c8af48e391db00e46a9ca5dfcbf7d82e2ea58965daefef9594b9cd2ea73118fbe0406f7c5972fdcca3156b8f5d2763bd532ca76d2f2b85d1fbc13a5aa2d374af2789e5ba992712a9632c0f00d8d0f0bd091b91310139e4873f4a699c7d1374ca2f57cc77ee7e5e3490ccf7ae62f6796afd86def0d38de992f69603d28bafe4fb997d7e79240bcf1aeac6c3b59e9a28fff7d33d4221b5550556e565fee29d524ac2a6e298026b84eba309644995db12f7128b1017683900bfd6e44ca924c72145d53e83168fbdcb2c4490e859fb4478687c8bdef4612d41406912b5b972cbd5671db17678de8a278edf6825814e3e973ad6ef03a34b76633666a3112d4e46e8e6a46f10977dee66361f12ad4a25697f8cdf0bc056bad29757439d0838cbde43b30f7526564d00a90503a08caef1271c7efbd03dede3da83193bf996a39ebc5a5b35ce6996d994a236d519d8d3b5c61b590aa723da532b8951dd6e4b6a19de192eb76134d13fde0cbd63d5c289a2381a0a957b942fc08ba99e249441f0cdcc031072312f08f3b29170cc12bd1c2ce514120adef3c8c668343c0d090121845e9a928857b78b89adbd50b57d94a2ade94f5a34d4d5de12cb252980dfd948e343b6eedfbf727369224bc52ce66f1d392c2fe4ddc9ee9b84fcb0a73189f1bcf1af1d7de8cc70bf252042d846350eb3c2c6d00fd8dedb3a83da8f161ea67eda9a43a023cfdcadc6166efa5b2dcdaf57c123f501673d70904311ecc72765c529de80e135e0a1f816a25ad1f4a81573a90be298e78c72e5f7c71d67ea8c954545529096635fcc2ca063968dc292b9ef63ac29d8794ae2b3fcfbc68160edee7b37fb30cd84afc6d3ad4a45d6c090e7070194f052c37072086404c02b7179dd1091ad5ba6d104134591f6ad1f3faf918647f4b9c6e9f7102a13ecca24b69c4b366f18a0d683397f41c0524b20a22ae3c26ad17d0594848f7402c429759bc8988a7613a6b84cf55efd333ba2e222595a391c8a7fd2c53980e2adec814f695e1f97909ede7ba1dbb26e55ef4816e4a5e4f1cf043cd442450462cd6de269d7e3d4e899f9f9dabeb418e5693fcb0a22ae300112265470ba6df440af6c0e91eec389d6d0dcd170dcd1a22c496e80c31c18754134114be7ca856eaf6f62fa55e1c08cfe915765458c922d30a4cce248f575dbf349abd72be75492fdb387ecd35bf6af1bf6d5ced3ab46b08a9d75e084b3efb75c0f4b1d92f114111d6771d3b58573d490e7c7bfe05c4b4d2956c08a08848223ff92ccee8a2099b29c889f46c8f317d9c870637748719a2b430c0e09a1832fe668c1cb3668b634ead7e6f83e0ab6badb3b24de76a07ab1c8e7009c09c14eda3caaeb87b42cf78e40903326a4ac8c4e2f729044ee294bd5886bf21c39ca4a8e8b7b6cdca24faf9775f1d693f54c1c7816474c01402202c995865f40f80ea8f45c9526e84b0dac772d7d8e653e0c3c6222e3fb896bf76fcd32dd6e270a883d601d81d5e13df9532edb7924c004a98d924d31cc52bb4b495e92823c9d8957a3f9d65acaa50bd5d4c9b6e6c813858ee67b1dd181611ce61511368d3ff7497ca0fe9e9393559ef298b323d2509d36b785b5191c048754e7086f5143a9357fa5e0e4a0e43d16a837a7d97d3b87207d9033f05ce051bb6cc2ad010784b9aaa4879ef8ebaab26cfb3ea38f1a952c9c51fb6c54acfd2debc133de04d6ac5152945ac95ef458b948735d041e4c6b2643c6987c834d74336a2db4bea697c48889108842c2bc9e286bb8acc9b1f70bae800055655c392a7b35f893d4081250934c436454387cc242d293679cf1e4d5881346fa668f93e874630a5581344144963ae46b4801810e159f85a37417d193d2c2532371297e965efbfefa5b474ae24c75f359470e5ea98fe51c5e6e3a4aedbcb4d90472ca60210fd4bc2ab3940114526dc824f0b859898e28bd91d8622d9bd4dd23d94c4948bd3a41c1fa48a3ba05c2f5828dce05ac6fc00a39bcad625f6014d48a46f5e16bcfe383141b890a081278f1fe3350b4a64586b816599c78e2653fb61c3f9768e1586587c30634312e3ebfa659a78aa16a96b72c8970f551b8991b73f9927982e5466b0ded608b57dd578383357ce5307c84350b101e4ef9ec7e2a5a9052ab435bbea04e9345a8f4df1a1913237b1270e5f73c810da4cd037cabf50588022268ad294a621982b8b4ed8bd8870c2e8786904c0ff942b6a4aef9668438683d5ea27f15d9c3a274c7f1758c50ca3e9a350431bdc2c8d23893922576b43f0fa4b13953c7259fa4e2e70c0122966d436b5ea0f92c8f3f55b8d217a6b6771398d6f7eb5c95edfdbb23bd0c54c5abcafd07ef48523cfc8883897101839ca1c488365ae4be3ea4c98d8526aaa14f225e53819f145d20d7a53c70fa67e4b4fc31cc9ab12d269889524ff740f21a04dc6f1bf507256f0f1697e594fc36520a7c385c1528fed2bca1885d11a32c8e5e3ab7889c1e70d9d337289a75f2201ef3a0785551f3c6dfa984c438b841b9420d2a7a5c0fae5f7b8af278ca764e3ba02b80fe10db8a3aecd3f158817c829b47f2e2a8184ba5ea54b8210c1dee3ed86c70f14ec785e6d8a2f0ef934e2c0bd1a96d7d54ac209325aadecf1d41718e39f15c637d8cced5b0e8b2b44ce1f70042f6c8726d876e01aafbe4440c19fc18d8148cb1ec1ff1b4080ed87ecb5089cefecff4aa6cb4bf81ca3405578ef696af4400cb0024ce33b17dafaf701543d7614e22ee753f8371266c6c0c0be770457745addd675673c182ad8da4abae242b9a55a3032963420152cfd867c025fe449e0149c971eb94a55ac29003a5c33f839af7e5e969720738701cd7fac31c2bb7c355333575214f13139a011dc56aa2103ade595bf0d4c67a7a886acfe563226cd82ff85171801293e940a280d38b61070155b286876ac6632dc0cd92af6924f3f7d50d47309ee59697a0b09de8bd4f542a35999cd950cbf646008984d4069cea52c4df1ca6c6b93c99b0e5223ec90046eb4caafbf9f9c89a14ead1059260ea474c9e653774f4d506c0a157e00acce56561cd030db015e38eecb57cff97fc25eb5c1f6ff9d235be93e477b43b2524642cbc05b83fd3b53fc21c0102cec2ea8baf2f739edf825e2671a3653d40b7059ae8ce86174bc04b9f30119e71d5211ad7240dc3f65ef110ab2a4c625880937b9d1c75709b922bbd5c4fc673414f7b708e446f9a8aed8c412f91752d51932a24953448bdd864372b81b9e4dda8b44a98d97a50295f3926d671778a420a7d8a8f0b9e52a227d7d357ae924157de236a2e6d1b68c6f6cd9eb1c002bc0a30e01a837954eec654501023c49d8862c91a91f7d74b3825848a952785aab21ff1e9caf04b61f77e5656f18c0210ea7d673b2f9b39fd478cdd619aa09c9fb0f5f31532562d26fa96e8385144da4d3bb00093c0744adf907f2fe8b7500baafccdf3f38b527685e359e6ee2b0d7843dc211438b21294e1b3efac816baff6d2625dfe13011420eb40f4751e34bddbf6c91e2c0a42f6f22972597bec6873a0dd0b6bf98a7ee9feb587f2785f0d054d0bb525ae0f4e969c44bd5237e4e714b76b85b576ec6db78824129e884c070a6c5e4f2358181a0c17f38c9fa616db7201a63ff0c85cbf108644b542314453536211b24b9f521c064deb8d842eaad568cbc6c81bbe340c927b36ddf269fdb807f92f8ecdb7cdf932c0954b56525dd7a1916e69f8403991ab92c5e18853aee004a874bd9bab2e08cff14932feb4d26caaa7fa451caa4a85677a9163905e39a0d03b2db3345429278500df0ca909455dc53bc76566f4d0aad091626a2756dce78db39aef127592c79c4a50d3c50e33cf4832b97c793863ef21006d29847c61be5ef6137d68e622ef92ef7491216cd21956f2080e3fc7aab2208df42495865c582cae268d38065123a34a56f09fa41ba66d18ac8018fcc8d0e1c40f2371ba19bd22f86ead13de1d9d9cf29ec8ba681ccd02491f05b36351b37fa988fb1dbed74b9f13cc26dc861f69e7a3dd46f04cbc6b985247335918b4f063f660fb40d3d7cce79b2350076b810543a3aa1318553b62a956ae11c2d9ec34d3d4d9434e1bdf939d49d7c83679efce02b95de7ed1fe5376257573c76d3b1c58f45835769875b61dba5e50110ae0884908d58f1260defa5f05443c03ec865ebcd9ae52606c6580bd7a835a92f875c3cfaabe9ff1c166ecab77847e76f2598847c46d78e4687e4a62847e62cefb2aedfee29bfc956b09ec502bef2b12708c98f4cc20a8b31e955659276b3eb156c6153bf95be1ff43efc842fd1c195c70c3293a50d9cd29ca59aa2d781d52e9a266dfcb9b05e2a62833781e2b5646054c0f99362ae32e8ee1125c0d39b8cc51d600d14373ef6e6ceaf9238125af38417fc4f9975a891661919373705c1ad0850cc35a60526b5b3d598b45bd8b0bfdedb548e667d2a2e127f680468a0d238f418fedb5d27f86f654961084677279e6ff139359dbb6988c35b79efa66751a91d0225004c81828ccf283f2d4f8230a77141951f41b6d9bbde162ddc8cc38ed43369e235d8514b99d58552bf71f788132cb58bef9bb64476cf0f59952d41c4110bc6e7616bcc2a787369e590156b5365dcae5e43004bf2c440b60ab6309c58f688dc47d57eb7e586c6b23377a6f949a61ea9b98da90c55543608ceb5cc5ec5db3869d4162820b8cf6879e3c9503fdceb99af4de4a83b9385fa317f5eb0cd99e7290c5f5271c89665ea398c9d7d4a3a19bf235ac79507c6a26ad2e8d8cf388dfbcf304450a4712a9ab98378fe4a650f847f69853dd517aa1c0bd71df3fdc8ab48f3749690f7fbfb9dd0f134e6c7dff1d5e304e03542101788ad506b7ded09358e70e6b478c6e23b89b088c5d16c9ed9d4201c2460cdd0677ee1d672357334343b81b56e1fdd697199ffd8c245b5b370155760015c6098f434021a887855533c5a2a4a9f4230c38e738836089c240182ba0477c791b32e21f9942a10eb8b39225322ba82ab38cced79cc8fed51db71ac2cd67e0a4e256f97028099794ee772e18d8031c0705710dff2005ca711a00b52579667dacc4c98ad6683c998e9c09376571de6ffee5018d37e49a3db4b87606a09bb7842a81f2bc8b2d4ce841c60bce77c26809ccee9080fba76907e8f7948d96f52d30e98c4975a173f471382c5ab7860b774a5c7321a37305dd6fa3dc9b0ef41a2becd189dd99fe3c7e8843d8c03bebb1b2b69855565e2a4fd9c82fba57b9dfe8c938d8c742319f8ed24dc95ab1f560a2f6196ad254a2821dec00b6a623c8e61d56504ecbc7066c2f452a4115ea0ac31ef7436eff5e84ed7dfd1db40e3bbdfe1e9d1396efd295d512605a805138c60a063086d6d16d428bbe37fa7ab72d9760bfc79492d786751fa794859a4abce9b1080721dd681416d5b3ec819b0ad4d80866387aa28241387594073793dcc03f4a86af7c295ec1aa2eb0594f95efa2a386c77b8edc7cfd5f00d58ea838e7043404a84a5206a17c706a2887a04de17246d6dfd076927b29ae8a45c3999c533174b709e5d35a7760a664bcff6314de60561370ee79e9f655a7c6c32a044850f13229a0a596c1b05e23e2a6e80348b76d90812a2a0b6654490027aa845780158a02438ca84fc46413aaa4ffe6faa35280f75b1ca0da972491a5c530164168bd024319d792c561b23102ec96abb47847ddfc74df996c6243f8996351dc0f6c77ea977db026e28502f2e2b4b4d9f10382fb5f6457189976d52657029ddcb012127112f7ca8193ec5910b62326bb691d4053cd1c1722d22e1bd6a6c210a4667a1758ea42c2601aedff68e01fe8c4d254ad808eee1e6b423bace8b20a05b1863a171cec882d07cfe08fc872573748c66330b765979a2489f40ee28002a6b7957cbbdad79075eda207d0f77e0db3616525f16fde91d0700d51c25916c6342d5a24df00487e3065beb6201407a5581467b4ff341466ff22c8abaf51b642d5c032962586ea44c5a397a89c544dcae96fa03804a8f913065f67c406048622d0b7ac66449a02259c592e4114a1334aa9837e0a29b1542efdb6bb1e4f30f614c5ffe657f79ab2dc32149831aeed1a00e0d05ee23f7700c96b53e997fd1a2b85f711e361196ace96e6186047cdf3883a5bcf95a29c00fadfe252085f998e910cbb5d61dd989877c44a98b9ac22aa26a8165e2144804baf040e7084ae7ec46d2636f0367622256d8f73d81e53c820b259b1396e30138ff10740c55b08a129db116548036e9e1473b5515c1bdbc74aa70bc105f71385afbf1f70ada200ac3099084b60affc1116631f0cb145e17a0f8dec078d27fcd2a0fef12a289ec254e923458f32c4f12835334d5e1f89d728aa4b53f657bacf93730cd649d20b1a087e5730f8231722d29d0777d2dcf25a477c6d21da0230fd4e4a173a05c5c15acc19b28f5639ca2f8c2a20401e45f374c7be06a9abec57021d20eeb481ca66a7122c18c2ec23ecfad52ed1ea2dfd7b47ca78391ed89ed73ad002399332e9a064d4620982294da7e2de1bd47e078408992c62299b1f60dd5f076b302caf451da1fd844614fec971854664f030273d5b65f1390722e8502d65a1109b392dbfd442fcfdb7ef3cf7c2c92fa8258da6592faa7d0627f5c3d77aab735d57588c27384fabc9792d31a28b04ee5bd510528baf1ba116e2b51ea59275bbab111379aaf6686918e2f879571ff57a106c5c50d730dd7d4809317e0a6ddf062cabeff6ab0ceb2ad41659e020b1709f9fb83641a93ef5dc8335628a53915880d13e868e68ec0e8d28e0df01476a0870d155d8f12fbd86471606c74c2472479229733f3bbf85a2271770aca9789cf5778b91dbb87c44f56ceb952543140ae58fd7f8a79cce8bf229ef81730722149e7dece1224c407cc0d0ad83c3db19d33996b6ed3ab876a5aa1c2e6e2b4eaf9ae5d64b7ead3076cc6e7457f7fcd5a671177077d7963e3eac8bcb46c02e1ed3d8b784049a9a9351a384926c87973a477841c3de49401717a24575e3cc755a3380c62d95b07945f3f845ed7076ddc4a11a7b94db242ad04f178352ed1b2a44854e5a798b5e47f90b435195fb2f5b35e8436f05d517c6b37ace30ea1d59050dc4c001af7787bbbedf11a3b320a46b4c8f44f15354ddd92967dc23a6fdafb7f63b32ed3f42385eb64ec9af8da248caadc81848e7a4f42d1db5d49a7232fd7bab957fe6febb4832624383a3047877a028c43807a1b26489f5ef2d3f665feb636cb0542532bb84753d8068c60677b73791e3a908c9b062d6776f392de7dcc071e5a183b20443faa15c57799c14eac6e9450eeb2f7ea12d16ba3a0d0e982cb427bb3d18cc81eea3965704f05362651bc7c98021b5aa05c776d2e4d44c868c3f39f622d8ad54c49f818ba6f86cbad2c3f6e0626db89420f5457d75b5eb14560862879da0bd4eb9a612d66e7377fd27dabc62253c9a6d9bca19857450524a8d1ecf6eef3c5e4f20dd0149b51fd6b349e489e7a4913cafd9b6b04ccb640eaacd8a96e3d64986a389b3f53fa334be4e08c51f2a52662d141ba57df268b9f15b30ef7536bc69dc5e544e4bf09c62f3fc7836750a6f86d31f0a1b726bcb877f90b5cefe61cdc60fd3727dffce0b0b0285b0b054e69f0001c3b4e20ee04d207cc5ae9302b322d9a8dd93a219f1b48b626fb3050dce014a8de755f7907e1188ff58fb514776324c81cafa19f00d76888ade31efda917bf4c8e1564f2d30935886a755250342901fe07b5285d3391ece0f7acb94bde2283c9d1230127f8b97a3429955a3622219ab4553f321323fdb951bfea1d82485ccf17a5ec9c739af20d5b9b3a351eacfde7a141ae1fecca970b5c07740f8ede3a4ec50a4120fb48d9c0f33dfd50d4a037e069b99a1d1a39f3f7a12d3cc7990a41751118379967131e800e23ee9dc224a7d7ab6a4bfe5f639c6e7daccdd2300842854bba580ab7a21b695301c26ac90371452bb11d56cb0549f1c88cad19c4a345d9b32b3b92826bbf40a3ba9f02ab4d9ae0e4af5425a00ae91260d1c902c2930c56d4f69a0233189869eb8d6ee1e4f035467a407abed5003553d0adead603d27692145440d56f1176068cc59090b0e3176a94dea55a61769703fb347aa35d3564a4513cf1b72525fa72959e7edda665a8585a7af3db44e8e7fb69bbe0c8a8d8dad3da53dba70d43687dedfd0cad61f2b17e50a88ac1b8911af7abf47d2ae54f56aed18c2fe35e155ac5e519aca9468b0029fbeb6561d60e2f3953b97b493a9577d39c9238b5bc9694105b1b4d025b95578553769e16c2f615873e5a21ad65da76cd13757f14b3b08b70525722f87d3efe5c4a386c919d859cb845057110dc00a0df142607872e428371d7adb3584ce3b69a723a2064dcaafaea67a84bc90d140bb526410047d6ce09bce6550290df654b238146132719c3e06f5c2b6ce6d88d9b3184b83d676db57cec33c92f31287b82043111496699f50cd1d765eee12c772dfd82c21efe9fd0b4935967ddcab85615822dc632c97d3e31417c079413708cb2e2cbe311e9557b246f92f8aeae209cd515864dd3964812d43b489c2bf608971aaa421a432c4af2faf8ab92b8ca09ba78e71cee6e295a1fc3a8b1a06ddc0c6186c16b2c470030302c42995b9a70ca9a1f3fb08ed9ae8f412eb3e313750b93cb7f2694f943925b55ff9c326df8b72c9b123da875bccf4bbad51644e1a19c488746016538c7a52082c7bbe07a45f9ee4a82ff94bcb34b477e7e1678f1cd7f971e59ec8f20664aceafe9bf8a4463fdb580d4b5a7289b3d7340d06c7c609588da46d2c51b25558d1c3b271561b2e2ff6c4962896f4341c190e64183c9e3a1a4498a93c6238c8c078f454e04204b3a6460e5f24580c9c1a5f6430903c72b40861423242dc88b05661a4f89061bc68aae011875553230213114c474e052c8830d77104d5651a4a2540b9d75109e439f4121f92941afc904d704c6a36fe9394374afb165d76d21867a97eef11a1164fcf70d8832857c872306ba92edd27204387f8c2045ac48a5706a6a00b3520f210743bd5a191ef6a5688cdaf98c13ea1a3230c382dcde37e6524f7b5b42254b8944ebd0117691dca91b7b5d79bdb69a574a1de5bb529e74a8652038aaa89f669da02b83ab0475025d07fb0ec77a0518a7bda4547bacd1c535c9fe211054fd80b847ce525bcb56b3b4c8ba437f12c163827f1828290eb51970656058e5986f2ea1167cfe916404d1543bdd58e810933f4a3a66fa46e67d743ecd56877b77fbbd881bdf79b60f4eb8690daa24ebdaa4e0a4ddb858801fcfe25ae2de80f153c06d8ce6ada437ecfc08a4c86438f31e040facf8a54ea6bf9d355f4932376193de526be487eda0a175f4e14f8a4d0303141f6823669bde509ab64c511200569f08c88baddce0dc51610b7c2da8a512c3b329b2812aef74158fc989860d3170b4804f11d777843f563284c18942d13a6b703727e944e4fb6e7887a2b4d88fc5f0967ef76a2afd4f3b49a2fbaeec843a83220adb7da6c2bc373edd695fc3a7b1e07f9821a525c7aa82d24747e6ead965ffb851db305b3d2fdf92eb5f06d4175df2e634c6c50e41b602363ecf21b9c424aea3b4a9112a800a4f4b6acdf345e2515de8f1c4aaa97b38f45e6b97fcf07c67e1972f616c5bf879a8f2efe14fba4d54b08e49fdd60db344fc7068f94b86bb71ab4b531d72c30de2c0b2d48d97eb3005b44b34d80a4cdc8cc44fb887145a7e603710fce60aaa8d58f57dc6b58d1879ce34ee3a2fa39e561dbddd61a619ee78a1ae8e7b12c362346c2331157a844456850cfed8ea7b6a78ad5b8528799ad7a8bb621d28f5ddf6ebc57b0eb377b1f8feb6d9727c43ce14921afcf9634ebfeec0e2f926e378029a96bc88685c91e514a7e4200af9fb1a0303a0e5ab86e8a66f65c6b4649f7f50719e3944cd1c00ceb51152b5ca2472b192807914d5161786d7a67e48ab4327b0a15610fd86d04cb0fd8946356c7bd92614603ed431a00c629349b207612263023af88655ea445bdcfbc5d6a19802bcecd4350d163063e8b832aadc8499898fb99915be0bb210b2e312b72ba60700e30e04d6e6895d4a958cb4ef08ac1a497ed90b8e18f3ccc7b040c52c711936e70683184c6b9c3c15b46d6ea98a817ad491e50bd218089adedc60866598f981b28afe57adb8aacfc031bd533eaa2804ca3678198ac40c8d9ed5400eada248fb85046002fa362579103fb5ab54369ca31dec7f8dfe396133f6aa9d7feee051fc2a3b2406e8d64fe47785274a2d7f688b316c7614878961762835cba94ad675b4fade5be3ae03d575b037433f12139a73c58edf68994c3e4e7116a43fd3628c6c853a4ddccc89f084d15725fa3e096c1cc040b3f80078420ab9934c55bc3c332958f3ff5464412206206e3637932c8a2e0f94157e01c651851eb67361fade91e1674730b51d33dad704dfc1bf0dc45dd2ad6ca3f59bb2cc1209d795ada04050d62dbc122939b351b3b8de0b3d7765a9ce8c6eed940df135684ee58673e4e4ed28159ab46d0bbaee8d66139ddc155f5f9cf4bc3dd72d51e9318c7fdfda86c584132cb5ea2b866fe21a847534b9bc8f82f352ebb2876c9ae3d151501d61affbbf3fe0997ced4435d21d774f8248540770b679aad2335595925c964aadf51af48a59d5b1cfae4acd69744541e9a131274c2d1940f6b4a7491513ef51613550456ff41fff7d05d0566c48b1941ad76e40c7430fcc60ac1058f4cc6aed7a2c84a7df0729a38ff3961801eb6ecac5f2b6e73042e64cfc62b69c217b997a293d4e0234b604528b174431b08208b21653a96c682e7ee5a3aabde63eb8c40ddce7b9ad2788f7c06f2c62e091fada48ed64e495edf60471a5b68bc52cd48f0b1943de790448b65e96109590397acc36a3995fdb7ede3720b696d75b9cd48c56bec9329b7264d371acbaa80c556278a564609cd16b8c451519ce383ee28a2c9ea8cede91919f57c5d39f520e0b4aca382f1cf0d2ba3adf4d486b543ba96a60666feb8022e3612ea174193d6785e6e768604ca5e7344c0a8c42996aa540545b37c0b1d83181e38744682e072beaa6a2d1684c5930cb843e261b9c6003acc9f169320917ff4b81924c90ce91ac85acf64246d2d59203ec9537e333d882ba0c43821faced582293575e9d2e46ee8acab793c0141b824b1aaeb85a783f9bf173cf4c8a246ad01d81ad86f8ba1c3ca877001958fb99b2c3681588271ba036e28cf408f4d28a679abed1aee08dad5a99136ac067af6c389cae391b369f82e0527e01d6107d91b3318c192e1e7f012bbbd0a89dde4ba407071dcc99ac936614d660b0f4048c0ab2c17067319133c205a0d3e4c408a05b8ccf24cb489b68a0c14f0cccde967bdd6bf2c6045d5e94e472797669e3e2f35e1aab3bb9311d9fccacbc2e32b7a195b2828dd0a751b4ebf7602db2715a8a498db98adf685d11d20e049103dfc791560f21acacbae869b4dcf0d20555bf53fc0ca67b0a0bd7762c3775b79a9d51dcf8d3bcba984d8a6bf6a6b839ae181d262b1ff5457a081303f509e8eda3d784cb08d282177cdd4d5770f5fb8f69756d68a5ea0b15267f65aa22f3dbd961b3caf9f019d09436d0c924edbdff40141b2f6011a6e3d10739209b3c44a807e785ecdd3ba5c6026982e57fdb4703a46803cc30fa7bf11041828b37cf391d812a9c49e036bc192e68b3453ff067331f0df02ced36b34125d6fbb31ec0961c2eeba9e0ef96976d53130e600a213b15b36f2b7073e18bebdfe69055a95546f5a2f7a33c1281984eefcbcb4e9831fc1a44f6d68c65958608ee2142bc373de9d4715b50cc174ae3c68f86bff958bf511f3765c8f5528a67b9c93945813f2f97e1bcf76cf757d81e2603f9d200266572539c09db84050a5bff088568f396e2677713d3d802ed439b8b033c19bbdbe1357e1dcac7127ebb6e7a18d1ca757fab8aa717aabb2d6132d71b5504ddcb4ea8b758080ea9e39e52e7a979bb819f13d97a0a617329bf3d49956b551fe1980872550b748dfe1d97ec9c78fb4e75ff2b8c5ae171b411efb74c0e6801381da941be1ec15859d88e0b655abe4292ea80805291d77d493ed6defa7434fe02369bc42f362f9b42d8e8b344ce1460c94fd16266dcc8ab4804d7a8a1d1ef1b1beb50fb3a74c3f73ae899c4fb0da3913aba43eb14be3f9879ef3d64b691f839b0cafac3a3ac76c5e0ae58b0503c77b1be9d461cd815dfe1dad0eb6684e95ab79dc28cf59a0b01211b970f29b508d79756be6ccb6d7fccbd4693b6bbded06ce5127a8dce11552d855391b9228a1ed44bf0dfbd12c8a7ded358ce59151f97445ed18be79602dc65c9b2487529e4589db98100c1d9b110643cc0ad35e9513e31eec541be12162516856c6549998701669a2a2395910b038f55090d05795ab4bcbe171eefa6aeb0121c1e9450e36bc7f3b03919c8d8d8013ac498ce3e07ff44b245c6f444f2fc66298a31e8c338c79d05e3641d4b79fe2d8293fa25a9611f8df630f1bd2ca2206659070e0f33ce7f1d31cf4e88429e6938a95fa911488dce92622967e3b4ca2bb49b94964d6fc0dce90100b54f544d0a5b317844a7393b8ea5939e3b18e9c7da6aa5ce96c96830bf11ea2a94f40a1e0f3babdc15c637cf8685b656c3b20155b4aa74b746fc9b15d10325760b641703be9861a504da88dd4353e9afc9b2418cdc0523111eef268e5706c0e2fc3b4ea323171654e09d7c19c8bd9cb33aee24c0a50ac0dae10f291b66ef541dc0a4461a0b61bcfdda2d067f9e0082222f906dc10f5b82cbc8e19910a875855dd926ac101fc9673b5c6777d4e4cd402598003bb51504ab5fa15d0fa141283be5732a5c1743549a3dc206692b88295dadc4a24f81f1638abb21a66f66d909cee1cc4828ea80f048449b75e35f5641a93589e1bf20b9f02b20bfdbe59c5e745dcc27ae8fdab378bcb8e8f043b79c055f5a52d591b625a6e432de19dfb7e61c5dd5f55387c4b70cc6d2dbc349f979abd7a541c23163a1a5222e4d9a0c0a99445bac3d62b66b496be9a70453396a11e58158840acf8387eca6d8a053e90c7466ab87c13dd91b0f1665dedf7f1b18b768b87f8b29e45e6ad6e4f573672dd321232effbf48d5c105429099937787356d022114522384ea9f2440acdd551f979fcff753a2064dac216f78066d4731ac9381a64cbcb79ae14d59cda7ce9da6f61fd2daeab5bd20f2d0d3c2f43bcdf88442ff76139598eb0c7f63e5459e5e211445b2bf6c88ce5c58c36d10c86ef71a3db7260bc716614c44b19060850fa40bd53f234163d27647d20853bf85ff89750800b369e0153982d15645b694a34382753014d9a017b447db1fdbb4645f038d7e4ca7b733024a4a920be09e0a308de9697e425c1a9a04671007bf736f57dadda6122447bc6ed3722706c289c2270bc6171cbad4b776ceba6aa16e742771d7c8add1aa704ff01434f22a2a41fdebe71acec4cd381111c5abaccd74d98c3da13e355dfbf067e28a7339d6120680a5146d9ac2cc79e21a4e8470c0ab091312c2b03e08b99f3dcd5d549c4658d230520c0fdc1d4546df63334a8132481eaf4bdf3bd114fcecbaf2e398703b09682c146e3b050b605954a03678943b300e19c104c381d04722553ce7883a400d830264628b1d165c638f712403d4ec4d09f255ead0d9408650f0d23ba6981d2a365b184bbc367081d4779583c5323d4f133bb0fbed6585e314229947c4973cf1d85402c16a721cb6d26a9518e20e4f9d38af1c34464c560bfe9c884c1c2496fcf73f53fcd86b8cd8c8320887f1beb559454c5963343196b6e12e8a98aa5c9c0e16a64d4c4aeee78c0fdacc7a7f9d0a922c0ea7dfe1cc4c31a60d175def842cc05ff3a5d331e2725a3af1d61d7368643c39b1a078d5f995efed49a05bf45901cd56506b80206b5ad99886a3d2bf0afd5a9bcf08de5d87c5fba188509ddb8419e252a3768d53924753a70d5206a18cb2e7c64c8733dead2856b428c09e0710cd7d80cbcf473ec2e0775c1c84d06e03e3b9b7bfa3477e65662cef0aa8063f37c85588f2c97ae4d11b5dfa68852115403df78e0cf1cc881992c440c32af2fc859b4090e02156c744ff571c542e1accb1ef34f3e73d734c6ee01d5fb2289fa8fd7041b100ba4cbe48720df3bdfb8e87f0999cf1fd30f77372611dbe0f9eba4f71a0b37dea2c094b89045cb0825b03c0927f08c3c261bdddb0749d527f63eaf9a51f246dd98878be8e759ebb4e8954ae1e668eceacce388bcbf80f4f0832ed11ba447f2a308d2d9f471dfc37c46d71e29b3af7c0e7178e82218f89d8da3d4142280f858e65e12343e058d4fd6b45290b5db94c3491cc5ef35dcc733923f34dfcab5f3f6c9e0e9a9ffdd280c6ba25a07f55ac1107cd511b900bf8aed60cc86d364b9f8d916253add859740862eabb29c05f5b0c6733e3ff8dfab118a544dd1efd0b673ffd4ff4d61781443fe3efa3b8e06dffd43d831abfe8293837c2bf2529e87aea1a4b06410caf7076db752f8e39efd699bdf86ef5ea608472c7a677a232b64af55b7e1f0bc0fd5de926d3d4466cea71f8f40d05f94b8927ba4c134b298c485c3f73cba19f48a43c610bada53ffaf6ef61d0c4f9420e9b7dc5758d4e93b9d99591783c50a13cb039375488bff8387a8c6198b638994eb18b6031cd779cb0e88131da011b40f9f49a0d80741f08aab3455aad927dd4f6def4a40c53c9d3dac7e69b1fba826b604f95979f224cb0ad96dda7726f2582004c88f93d467993e16b179af09981c8c39faab34257a513047288745b32da046fd38f121b507ba3d03ad9493491b9e497850a75db96590c3602772f92a06ee363221e15b934fef2e1757b2ac4bd380e6f1d3a3d53f41d179b2430cd044e8fbacf31ceef7defc8657034370257290693d497ee3641e52c941d510c19dc80c65fd00eac2154c02ff2046ed9d8868a1bbd4a4110307546570d63422b055c92f41ec4adec2c484ef51fa91fdc1625295ebef2fd4a4bb3e4d5bbfb995398775405d717abc24808806cbe5f57bb8bf6617db6a10b4cff0c01b1431a672ad28a9e67d8c4f441c5c11d1d17775b7a5455297cf20a97524d5c34964b9d05e45d492afb8f38b96752852d0b6a4db0ea57c0d47bcebc415e8fbb261625f169bd9ba720525cca672e99876eec5607f46cd765c098f879c75abaa2307e582adfd21ab1a891459dbdca18bd5f1411e9fb5a9061747108503798b9ed5a2cd37e9bcb5fb3cf77282c9737bc2dd2d31f502deab54415e9c86643932a875dad0a86e61b4e8313d283bdd07dcc3f6560040546430943ede923f5931b0d1a3e91e04f538bc854618e6a12b9a566764e348ecb9b07ff1adbd7f937d9d48929046dd54b098a0614e9611cd4518cc41c360fce1a68420c047df0793f53250e887c43f7da4e2088797cc1021997f3a7970bac911022157a441510e65d78a241256cfe4581f6be94982b2e43f4cd2d827861c5ac54aa81b9069f53162aaedcd78240f17e14e518ee5cba01a5720b9529212456f260d6e71b60179fd0bf1c392bcf385a34054d1506decbb5814a519416fdb74e2e95d884bb85bd0ffb61ffa38e83283d633b4b701b047bb541d8a53106cb802f61c1d79db5777ec8deb7457b57b4d99de083333a2b13d3276db6efb7f44603891492bd69da790e2f29e142c243915c362e7c8e5f8f1ad932cb993444873adfe1649e9c62e32ea2fbee660baf29434caf33b1293675e0a48314ae5bab8a23c128ff21002abec96f804a2c797d33730e9ca23473d5e4752cab6829ae95fe04de1190b219b476c09b27ca1a7ce0e4edeadd3c8928c9b48f4813276a05d06f977dbc31ecb7fd38632e0490834759bf75373d962e9ba21ec1c8b1ab0ad4e73f5ba3e6181f46a17345759857b7e85b35c7941fcb1596bb019bb7b1196784b62040c12542a8ec4a85a896068d86faca8536d200543e2011905bd471950d31608266578786039d8878a2662c03bd0f7db563fcb90bd909d38249c4e04d29d3a22f3cb3ec6be2c5854ae1208e47a6e4d201e4c82db1c84afda7f1cab2b0c2e0b62289cda5dd16b365d168a23564534d9090d688acac5cc458e8c9eb95c61924c332e38154b3a78968bbe6c90a8d5eb5f7ebac63fa8beb393b5a847e9dfe8fc1dd30a60afbc8817c9968f3707b15e9309081173d724fbbd189dc839b91539071dba6b2c3b3e80a770c002f3d4f40eb8c71d442cca089dbdbe6582b79e2889f2a03ff080f39fb002c3d7831110b83775aae725310407a57ca36b584e62f4da09d11bc2bb5acb017c234b721333aa0230c1a863bdc2ef719b27e5435f9c30f3adacb0209f2ce55e4e9d00bcdb214ea4ae68a07181fb4d55fec23859de387d851c27c1d4849d5bbc4140a8047741303d3c927e03ba411544b8ac9702466f61d51d905bdb0fb0b7e3f0f1040e30be6ba756a1dbdfbe38fa008eeccd9e39471feab5051b1ff24d27c70baa4179e2537e6204a8617b645eb0a71846481a8cd9a9fedaf323ca5450a5c2481b247f61cb1da17c5010899289ae7aff01d9093c578db06ac6de76150e348a688b4c14a85b2e36b2d30d95efa453b343fbcf06c3a93dfe57fd848bf685161e5fe775324b6b01d852ac6c0e9a1a75f9c491614e6e8ab0f7912f879ee38af4818fc2cff77697ad0e12572b388a52b56acd14ccd8eb5272262a5e2f1bf1aa98949caf0cb53555fe9fff0e4c54c598483477910cfa76334b7b10af22f7a2559009d43dd07d8a4ffeb64e3e2fd0b3f5a34fcdac0ffee322b002baf916fe0daba2983fa126f28de1085c9c12048a616ca5016001c8542eb0028a9f98156061fa449bbbb938fcfbe1455b812caf2588060b740935e5edbcf601197a18502c421b9c48dcfbb014e65c2555dfc02b4b98bb3f8fa578cf9844ec7b3c49cace7cda0997919352e896ce828c05e20452446ad86634de98a027375d27ac967e5e5fba3163d350fef956cd70afcc5e0016aaba2a24ad1b6b4256d18b0a7ae1ff9d17dbc36ea0bfdc00bc26eddb238a5da9bc5782fc55ad9fd1b39e0f29f6a720dbde71cfd4b25cd0f38bbb154b66956ad86fe8aa7c75f4f475236c60fa48abbac8df366d94299b9ca0f165914c2eafe6ce60c443ff56e1cbd5f7fc5191a46140a315f0c2c1099d16c35fa2f592be61fb76e609acaf835dedeffc5cff8f5036d9b30a4f4a51783e6dfb2a936924492fd6142efda6dd0a5fa4963518d373cceaa8def3bb983eb81c00469d558f0604cc981e218adde2b2da63f4d73cb531293565c660a02b9ab86e25fd66680792b00669beef5684d0c65a13b70c4970dfa537722d9b7f248135a643bef2df14d0313d8a96882396a0c2743de67e3e2ec9ddcad7aa1239bee6d6682f37e10ac7b3b20654189811ec08c58b602c7b9fb1c5cf7cfc210e866bf247aab78fe94d360439e54dbfe96e119ff515814c6fdbe832befc25081ba69483d3f7fb4c844b647abf1a466e782567ee97b24c4baabdd59894d40bf40f217f008d0deea5a3a077b728fa1a4fde4af155a986e0faf288b2bb62d77fa501b3b2060b0f8d998384efe010407593b4ece6760b43a3514def765321539e6e94ea79df3271ffd89f9634db06f6638f2f0571a5e1afd8ef4dbe6fe4fff6efef8503379ce3a3dd2df7c4efb2e0e10ce2c20d179a4adf3a66cb0a65b141aef7430739ccc4e726e748d0cbb1964196c98fb95b8c0552b55b5b060227f91375712781c9832cb930f9225c1af92153a80e61d912c191ee1947802a4354f1c4963613a93fad655c838d11091a59ec2fe8f098ba8358e9d6211236d779f6a78bc87f9ed572d3c5defc7190b81feadb4e2e3b7b7aa3e79bf8bcb1ff9b7d3d14d9aa5d65aa1e1fba9774de01de244a0e2ff99eec2c85eed6775a3b543e716ee51a54bba5dcfc001266f6e2540c04a5847ac31915944c1449b854bb25e197dc2de5fac2922e8042bd4d58dc26f5f5bdcda64c18e276d76791ec063e15eae5ae856ab7380198e7f551bb0509548b4a26813cfa0a3939985829515f70991b6acea419016a4d580eeaa6369e5666f6096349f66db83d879cf96293918e9f79058f9182033b143ce21cef8e7bd0b0b6c67937e944b07e5d5eafb129774832c49a64c5699c2b501f7e9aa9c81c00dfe5ba4d43a8cfb356801fbcdfd21a171476517ae10d8443bd9db785bc39f1a1bac62217093012582cf1b256c18398bb405617967a56f181a8c0d148cfbaf274601ab45f6547a1e8b1c68318cd0f4b4c036c4f0b6b9041971562a5ff151acf301b89a664f851b47ea896661be994076b6371258e015202c8717c74ffec2c86af482a8b861ee64bb9fe5ba5ed4d98267e021397bd95ff0b418e199e98695a1143d1726cb786f3c1682490f0b839a6af519da86d0126be97c0397cfb712123353ae6406adbb57c9cd39576c66ef30766fe4b4c381902c89a8fe631a0193247b98d22470878ebdbd867cba4cbc8e1b41f11089c40c2079ca8bace9abd176d04ef0e766f18c2adc5f47aae1ed4a8ebbe6ba90eb2eea8cfbf71e6f438ba1bc7d8b8cf8338c2e83862906e28585538f3eb2bb087ed883e20f02f20d0dd1c0c72cfd5ba23215c7faee64a22d02369a03ff9b714ce538a515859f52ac0bfc67093a20e3cb6ad879220a5ae942e6260ce52c83bd7822681c84a016c0f319af889b6452df83024e6a1dd7c842c2f837410c0c7f54892694dcbd3c1509d08a859d131be3b7aef4ac54e59030ac57f0ce7bb267bf0d184cd7cb61ebb742e6cdb292a7f24d6bcfe5faf9d3a0df6ced2106678b868fa9670d208d9d4733d2e6dd9bbc45ea4ac7f164a5e106d893d17f86342d6eafe875e3014f84ab03c2e6f00e75992a0fbc1bd171895cabb112bdf31e2a132edc138123f1bba1ecad2f9717a16fd18cbd457dd2d20d3bb7b66ba892891097dcd90f2883b6e089738db10a2467418ad9a9704da1b71ce957eb416c70746542c9655d026dd0080619ec447ea59f4254d5ad035b8f759ce9b8ccd1d6ce383b15fc8030199e823490d7b6a21e4bb122a6b06cd395467b32c6074adfc904df5ac38c75d56cbcf76eb1eeb9d4190af7b9479480561a525ad30a60493afa1865d609218fa665da3be00e58d08e59d3e4819e7f627b2fe6ef832776b1a91cb2475a0d2350aa36f35d42c8d36f5b9149894041f10e769cec50bcd070dd7e76640b280749ecde97645b736cd2b3849d4aae72a05d261296963cc16e6a81b00328891d77b8bf5cb63abf20a5de34e81c59388d27deb94f2818ef22524d324f5f0b947b7bfee0fcf17e3124a58e2794d83277ff2c5cbc0a49595837133c2ebea9e4b92474ace5785b4c2326114b27f4712244a44674cb8e932a0b7cf7b11a10fac62eaa1a636e13a3f9876c76fce9704d320731b5908e6e8237102268d9f93a66b52af022c181340407f15a065fffcc20288bbc82a9ba71cc099bd9cad45643b494e5a01562805122f116486b9648b611ed644edf66c97e88117739c95217119d20b4b7f14def1715010aa3d941d85fdeec9860940513b6c38b7c70f449155dc8469c59444647a288156b8b53e369358ba1d71a743d86c77e6ea9dc415a97ecfa0a0c57b03314054bb97d193c9876edd318de8574a30e0f16638d318a28a1e555c22071fe9964b8f15a9936d3044437dc2cbf672d1a2e988bdb2ed6a512cb62a47a96d2a3b96c6e28d43f284b0c842d110ab3c43e0199be6a6a2e1b23a0d3009c1566f59e8e59bc52dd01923c76d485df09b148997349e54f4096cfe3654b021401d447c96b2e5762a74d1c6dcb28534b22e719667e3a2028b3e5bd7b1a567691c4643550eb9f66d6912099b1a6b74981303b3492f8a4d6d89a0d12e7714f7bc2d8d61da7d3549dc90ecc093665a8faafa56e41b63ba69f8937709810ac10199297e49d2523b42204523cf0e51283f1727a530c2a2c68ece0f7f39481f3a6fcd376daa1e4f2347522687997af12bcc90f846c4583882d6f0bdc3669031858028403859012443139f0cf3747d776dff0100dc2daa110ed4c9a21e0196eb20a0c75416d238c35beb42ece6a24fd2e6d5eb809dc8eac25e694d874d642a67347057669a19c12875420574ec3e00260444a70445741cbff49a6d8a7e107c73b1335cce83241388953773f8d69a30f075d312f6a994c97ce5da9bcc8b88982244af500344cb0b726925258109d78da0744d0b43d2344030c7e8b18959e305eaa893ff1bdae1042d4857adab6d2021e95260ca3769981c4f464ac3619e594139e095a9e088f73cc4229f950f668492a83c3279e59a381008811244c4b66b9833aa4b17b73ead8ffd36aa7bfa1b74e195576fa69f413cb70ae00b3913f1d29104f54873ecfa41ed0a41c1d3443abd3f02af50c4978b5bf0992e9755dcc59b0b7c46a39d1db6a7d617d5efd7f76533aa28a0a87e6d1450c3963bae1bae4d64c408af0b432dab0c62ee204447959d294504556ad14258fb82f0ebeeae0e1111ac2d8b3642e6c05c31c6258b0747f13b390aa23f4418c5c27c711679c8711c00577de477ddf460c343557bceecf56a4869e2d8014460b8245a43c7b7bf702125fb95c6f38ff38b7562e8f4f3172d1247f6604ea6242eaed3258afdf6bb8d581eb1324179b2fa00eef5f453665f6a40209496fb845eebfa2b18b38879ffdfa8f104d1a906625b8eb2a91072e6ef5d07d4187e2272b3b2b6dddd4e3755a038b489cf2960e5158af1c394caab9118d7da5ccbf4a1049aa12fb4582056229ae6c9f36df7c86fe447f6a4cca632d38e1e3e83c5c589c0775dbc3a8fe3c07f4060af27f94de839041c186f6266a000003ad84f8778810a42649c13fde33caa10e76884dea90dace60d5ffbdbd6cd7a696969c90e000c1a0bcb0a489020419db1d5679dd8a9eca2cb54866f648bf0915c18c9cb175b7e486418db7bf68145ecb9f8e2a8e2d7e343d5d987c52a0d44194b6d9449f946d2aa480317ce2a12c6f91867f8e58bfe900340d5f554ceebeb7f39bb4e4c5dc7b092926c7b8b95a4bc969e4c1f2f666cd9d2b4c0c01c02b67af92cbed2cf4baf92f4b5d6cf9b4d5debe5cd8939e00540d50b1236f847b10fdca388bc5a400f99400f17200263b0c7fba0236a812e513569105973485d7374639b3108d915d37951318629c460f6c2aedb4b8453974ad57285cdf5df02635ad22b2b9c873a378fbe197630b3801c86c896d8cac0c51699605406ef29ef79d2291f1d83198c2ec6511dddc978a44b4d7a843abbd6ea81d22987c7aecc69415c50933036ba299f81085bfc0c7de92f48d8a6ca3311538feede43ccb41bcd46e529388fae824fef5abb3508ecfa19b4d84c580e0d8031ef777ddbd1ad563352099a892e34bba01918039b5eaf42e6afbbecda4738bf5679bdb99e44537026d2295779d5849448a3bba75c9c112662eafa8d74f35eaf72479f89db25624a550c24bbe628a5946237c363375d1c78ed51bbd1b255171b3d0e7cca337ce92aa7a3d367a5a7a8dcd7231a47a347ad6644ba279d0a99278dee28b330667439baab236ca3c711bce9065ec3eab59bb2d19e72ed29c752ee76cc69254cbaf935e9a33fad46e52937ab6020cec190ee1ccce829d84b7723e1940de9d94978f46c84eb67a276332cbad775a67ed9f43e94ed00a37fad631485cd3de565f4666cde955eaad9e1844d70ba103b34a763323bb571e9ec18cca2c83b98d153a494f6f80d3ba84a91f08daa4927610755239c3dc339b41a27e77a9e21385ddbe1844fe7d9a139611ed34b18e75cae4550e57ebad2ab24e5a6145cc4e93c43f0ece0d3b1979d4aa7d3e9743a9d4ea7d38906a7884fa552a9542a954aa652a9542a954a25d3e9743a9d4ea793cae9743a9d4ea753e9743a9d4ea7d3e9439c524ea7d3e9743a9d4a2a7773a5eb48616045d4f3a0bce8772a6badb5d65a6bad143b6743765df47b65e1c2068bc841c3234495524a29a5a43c223802105ce0032964e1053f34f4f33c43f07ce049164cb6f082224ce1051af9212ae689afb5d65aeb89f04153318fbc115220821327b238430b1a787a5d9e0b8010c61152e001138aa0717952184182911874e1c6145a340f6648b00d357f5d171bda65d44a4f0de3e460cff641c45622ef5a648278217668e2e50d41bc39c3b6bec618cfb34313310f7dc53807bbcd76e80bf350324f272e229e475ec678c913cf13cfc383a2434c3865707951ee09607c7144002c80470c31a187465e478512d060309b34891870c1a299f2a6789842382a948066e2ed32630b832544834d12ac61c60f8dbc3a9ad060f4b1ceb0e2098dbc2b3aa0c1aa1bc21631f8a191d7c4031accda9006144d68b02b23001334584283890c60840a1f1a791d0ddc82ec22e479a69c8f2e56b51551cf432b9d527edae8f268002fb1fb93ce3cfaa56c5015dd4bc9a02a62c90390108c49bdc3bb96413088043dfd1e0f404250f5042c1e730f0b52226ba873f04eda885d34b3076f82f4daec49306c706ef3da7dac2b6ad71d26332c4889761dc3e84932d8b2bc754def6c32c998734e693fab06852d4f343a7ea20163aa13a8ea3c9d900155b1c924633a994da02ade075b9e42b30b28a361231a340084da75da67a084314e4203c027f291d12ecab776257429cda11d606e2a31cd39599cabd45a9cb1b14197771607b1a18e77b6cb42066d34065f74508e6c64cbebb298c248c3cf808227bff0220c2fa2f086105250450e80f04518c260038c2fc048e30649e841167e5cc08413be70b2050c844cf084282678c2462b88179c7801cf099cc0841cb4be908420196401544517d81002184940c20e0d9e388941194e40c1144690e08514710b2bc878d7eb556945a2247281848a57bd38e381e11305266c6109475690059ad905155c1598644109464c7146133d4d5ab66bad400cc9c64b10e083f70809b1ccf1c6069dcd724e9d202c480916448bb44832d8dce1100d1f25110fbb0dee401506c4dc63428af20f477eca48b9a45fbf6e2101d49462ec5a482069d7aeb1071d1cb140d613c308d81101732e92983823c618638c313e9fedcd26d80c725498f1c8733070ee603e392f65159040820926a080620633b002e27844523a8384e2d08b2fbef8e2b3a28af8e2ab22a6007bf1c5175f2c0293175f7cf14526b1e7bd161d7c497452cab7087d49c4820b1f787185b04565e902da76b56de328db3b8ccf0ba716989a606be9078b2336d8aeb5821ea8b0d60a6cf016556c97843790741645e7af50805d8ab8f2b3c198f7de7b5328b14115a2fc8a15f5076e37a8411357178c20c9271f154be493cf074b62845e5c6f04e1c5177d98bcf822132650bcf7ae80d1c5878a0f49840e660726c15c4b8e41ed2409d2166173e2848b2dc71ff85862f43b8c5a7849d04c64d5f6945a4ab948024ad3da94524a5b2be869ad5d6b052690620913212c59a28a254c7ef8707f2d28b3659603d9125514d1b39ddab58e4883045b8e76ad2396d0e4073896d874b46b1d1105185baa5deb8823113e075ddb57f36c946951f5aac70dedeae78cb1c72ac649a92a5e96a47a38a85e0d10ce581b804f2144cd9583f0d52660ae25c618a57cd2242995946e34c618a194324a09e393524a29a59492ca29a99c524a29a5943225b1237181b560f162242c42699d4a43f8f79b21743d72c4d12795a82a75fc848fb55aa1213c6ca904172bb677e79c7356cea037238c8931c61823bc7373cee943ce1e7435e79c2adaf26c9d73cee9361b6354cd29e79c536253ca299dfc4abaf8bcd311dfe06052c210b52b7b290e063bc6014d8475a0ed1f268a4b54b144154cc428a3fc99f1e7bd1fbbcd14777ae754e2c706306aa26cd456bb6ff3a1b1db67d73998eb58cc5c30d1455d584295c5760993254c2250768394f19a9eb66d13bbe95834d40d5b8db514b55189d5cd876a2bfdaa6e3e587bfdff6fc3021b5cb355d770b930f7986817895c2ccbe8ee2eeec773f39be8d9a576637f3d6a40765afb7573098876fb4cbbd374b0d73e03a1e8daf529bafd965d8772713fa0b58f5a8d48037259212c11827c01566bad22ad54b234d351842da96c24155366a3cc35fbf4b4f91cac13c8564faa4ef624dd91a6dd742065b357ad5ca6e8c2726439b49af81bdc8fbabac1fd806d37d40d2f3d1be61e1cd90a0495dd804d3a6d151dc184dadeb8641a0e094e2c115ec006dca2e709ad5648187c515b2af81992dbb6bd960a7c7e1843135c00e30c217cf10415345556a16b75f39a563363e4ad11553082082d9f6db5a7d60d094eba4802d36ae646ea9c5923749082282d2fdae8ec31c1135deb46b34081155270050a5095c78a5a6ba5938b1f8e8b22a228228d234d5a5ea266ad07e8baaab1d65aff2acfe85a6b6d3abd9051b5bc15a365eb08142d99a09c183161b109aa1e4aa8adb5d65a6b9d1089e002e4696badb5d65adb3a4113a6bac311acd72bec68a30a513aff0484273d496c3ada25e1c913377802a422b4a5da25e1c9182ced92608534d8c8dc0f99b91fb233f74374f76cddb197455f170210b280316636faf0b15aa9fa7297bbdc9545dbbf20f47441d2ba8c0af836d9441c0cfc0b0ab0e8eadd37d37bb8408e36b61e340055176863ab372e48b606a00ae20bdcb8a08e58d2e7e0e83998181ffc99497af0410994e00530a620c24fe582881e1ce104114c8e98492494324a29a54443005f202149122d48411657d862899137937ce00751a421060ba8006485231081a4e74d27464fa842108cc0a0091c2c518588286205701bc1125098c119342043091618810823b3065f5081856000821378c0840e946c81452d028f168ecc241b28028a9227a038410fbca844e039e332a1da403d210c28a8420a4f40030634528b963c5068f9e3411e2ca2a089d142f88239e79c730708356002c5185ff0f014413387d09307899eef39e79cd64208b769e77c63670927a070a18c263040a227073cac1f6fc623a80183286800041f0cc1092c08c10b221b7461056d2a91f27561640a4424e90207375090861016b67044145718f98205d3da678408cf08fb8023509c51022aa8f1c4106a1602184211a070a10443692c215e61a4072970e2ef46490cca98021a502c6982094c4637d89424e08d318a30e3491b2ae8420d3222c591f916242638438d1514810a2d8260248925e900d50359c344115588a28329442106409001ef4874a18f98aa8ed05b0bf14f6bebcb012ebac078a156032f92905231a08a4aaa7aaa1f85da286c423f039f5cb767628d76ed9a30a244bf7e4d34b9b2a11ea8a2a72d3a0455cf09ebc991a1079964e80397ac11259e3d43434e24946d43a14eff03216c88e5151248064927d327bad05bbb6d28d4904f9489d66e1b0ad58450135734e6a066335b447d4ca5676b2f8490fa2861b993165329a08a9e056f258ce7f4994b68ebc696e8c621a862b1a08f9125d6a6e4b30c822a9a836b275a401595912449775a8eb3c730092f82385b29a594524a295feba528a776bde8a6e2aae565c4d892563d3a69bb3cbcf22fad2dbe2ee5803dc4d8739d83998139b273b2a409297a748995a42e5938ee4e26151d3af00a46e11c38e29a61a20b4aabe92794d68f426d5bd6c25aa2d6d592cf92d503aa608eaf568eba34b2826f64a3b0f491ac887a8c28887afd02c696e3e6150eccfa09b34c38a354b0c592257d90b0499c4987cf32e8a5c32e7d26e6217af4ed6622af4706614c745589519f28e362a5b1561fea83895e2f718562c0d64bcbda6dc324928a049b34267d6a3abc1ebd456f6d8b0ec921ea438386a24ceaf4d327caa4306da952cf8fe1799b01cb6063c01bf691412f5f6c118a839141138a0c92413228684299502694d9c646c2f20a09045530ca0b8b4350f5c59602f2ba8c6d28650f1f218e43500555f4beb45af1ca2ba04a0241158d33f0c50a5ba6ad4c44d5ad1fdae407c65c0163808ec5cb868e41c51848747cb6baa1635031464f474c44d5b6e17d0163cb92155959d52da8a2b165b70df5d3167d4903129b427130f42f626c99fac8256c9245cf84194c88d14e2e617b4fc14331a08a3e4339a4e1168c710dc58031f414368932911597f8449947434f4f2914da01fac4255186465694a1ade8428fe4f408abe9af257643a15aaca67f4163a3495a3e43589e7abcb948c7223cb0e0db2c5f6be2a1b5f17abd3adacdf50ba76caac2242f616cf2b1fa9ca00d0bb007b51af9dc838752c611d56aacb32f7334f444411c5a5e0d538926f6beb6946acfecb5147bb63938efaef3d46ab26b74d26de0d98298a171eaafc666e6688abb4826054dcf71b7b91fa33b2e7a0e618543cf02f47c7130f33947bba39ccc8e93c341f56a98771912245dfabb34ddf4f284cdb5c438efa5e7cde6e1acf2f8d2a756737ac1c2e65a2eb8a2b36b29f1a4b36a088cc979511ac7df952bd781840c244048d0e8edda95704309347064272d086cfac3c8069e2de7f58d178828bfe1edf586b5bf679a0eda71de731cd3b2a705c9f177a769aee5b581677bade3dac0b38d9ee3e6edefe58c6e03cf06248eee6bd2d51e2feaf2be769a96326aabdd6cd7fe92856dfbfb4b16b60de368d72eb536fdd26cb4c715d35117c50255a6cb438e3b64bb1320dd1e46f7021870468cf04616902c29ddc1942d25e538704af4d3e5a174310cc36e10b1b1d1e8969422d9a8e00c5be7b5f6d2312d887c0907115f4a4bcacd46236d34c2b41aedd87d3dd248c7aed6a41129c33692a6d56c3845229d848d320cbb4e6ced3ab4b553ad06c3292c858d3ebaa88c85de0b40150f43265055f32d0f070bb81ae6a7aa636b661a7afeba39d7f34ebd40d4e7e0e4bc286d03cf966303cf763d621b78b69a06a29edede6cff4e6fd274b0c739654f0b22faa3da49d7069e2d88da398fd53979a7817030da2576edf6c2a61a906703cf56e31c8c869bf0a0d560f8e11d5e9cb005f19266e39a34c5f587da15a7e8ed757bb5beae046648fda4f1006952c77064f66a2dfa0c4c5d175d52d7553c1a3b65f662ed341d74ecdfdd25c52b36c048f0bd47e4f5386adf7b1778475633f6a031461a532f42083175f91d81ef214fe56c94f3bdf7de7b6fbe98531bae20c4a9d703aadced1ba900732dac0821c4f3bd236f0894f7c284ed5de57ec0c776d9a5df9dbb734310bb2c98a04517a05d164db068cc61328310ce534a2785134a6b53f3f06e62f99958af74d3cd4478b34e6c688bf8a081eea1694e918eb5f34ee7d48e973705dd9f13a84a417c2359edfecc802ad77365e14374496208663046f6e0c162b38d3e1da882458460f5e0b1b5d868e419a1848e6c07e483047a60b15824a011a207168b958a485211bb24384a40302f676afa703ce1bb83aa09af73db0ffb90c4e6831baab3d550cb8e91feb4e867af503d26a3f7a4d89edf92244f8967041a9b19f619c9618dd27befd8bb1b5a22d4eff9bc306193b88883799f81f5a75fbf255a74dbd3aedd12aca1967f2d310d88caaf3f20e9849abc5cf5fc8c340df243dc8f00dce5d999d102b83c0f3b3c3578b45cf57071316fe88731bf7c0b8c99e1f5f2165ede4b9cdf152f656c3248916cf3965150ea4d551a6e4afe35eceb66555f12aaaeeba91da7e142eca02100371580d354fd7f2f6f4afee52ec79c445600ee8d6c0a03f096a0a6e1005003220191702a085bae034301c057b00c180addc8fee5bd91fd724c74a516413e5208094133220baa5a4bb47a47bb56125a3446ca524ed26c66975ee4bd9f9ec792965aa0cf4001bc5c24ba530ba1b86da2190455528844d3a78aea14593ca5b84a603e7d2efa0e931cea210905c6c03e06a383f633103ac9366f3a9e512bcf1646218a5774dc45998de52eca581906804ac144e91387a6cf713cdbc6f1bc358e6754e3787ee358e15903b603d881f3b6c1e0098587c89e5e8894a5d3e7e5caa02ba5b8528b2b7d7e4ea701e7ad4f0f00feb1f4f24248fc9040950a064596b760190e009c6de37b6517573e9168e4384b8ecb70c578ba0c38db18300b4e611d18f5158cba628e9b65eb744d37dbbee8556e26a26a792a7a15dd69d6a61e9184072d3f5fcf4d3d220950cb6358f62c0dfc10ed64191b0f7b7b0955f22911fe0c9a3e4bf868998331b51d1c69015de0a714d005be8b86c762e80a2653c8c134d9b2f49152c0181f18e32292282387a20bfc634f1c8a32d267480e5df5a25fb25550256dc471238d542a95ea511d5e4b3c671054f9c820290455f0191a5d40177869068a8c86528c866f63cbd3a7a1cff4b19812d6c61e9115c51e2530775a8de5f18aa312b127cac060e963371f1eb1a707c62801654ea58f74d2ef6e064223bad4ae054e9ef6e60b84f9a2d5d8cbde180ddd8b640983ce8e8dcef1c9186bf40fb2d7884f94b039694da1283324ba40685b5b13949309855e28c8c76adb50a80bbdb762c5ff2d61b57a06be84b164be36b92e7a185b840255f092258d4823640f92244ba0aa88fb2149a30c13b5a878b8919661a267d4338bad53ba63eea56e62bfc30885641aa13496ec588b4875f1b0393ea15234bc5cd29249c735b6e806cac88d904a409988067481af88fb21e393880654c1b8460a360755f10954c1172774f4b21d6050155d74d1bd7cb1cd2ae5759dd835259f574ae8295622fac43da00ab25847e44dcf6402c3de734e4ae1002beb32103bfd9e1d273bceef22d838f3aeb13c444fd8f63575d88a5e2f4e4e10af87682cc341bc862dea1e6acc79382fa454427b9d78bd6225da9f5643e7219650751b5fccb0120651359cac56abd56a05b4eae1b15643dc0f1c7b98821fd00a08a8070828e2d4c3ceabd58156404db00002c20268b5025a01ad8080562d69e06a02ad7a4581269004025aedd063b55af5c01e7bac5651a6842f57d646fb4c04b36bb18b44bfc16e8fc95b9c12457964b55a39e7a4879593d50e3d56ab1eab1e9cac9cac9cac56d689939f56125758fb9ae2d47b3d266f754ef48b5e27f6fc4c14dd7cd9f0a9977a18ebc47e4fd1679b9297f8e5c9e6681e4e517c8355666cd9b692b8e2a9d48dfcab02e65af26ba9e261bf23ef012579489044991246a1e20b9234d007b4633c62980fd9842d5e3e657ffd00162b49b992d27dd821a5a75c74739116fdbab9080f25d1b1a75ccf445727e6229dcaae019dd82251ea7ac4a9eb50f544d72ffc88401544f202d7e59f2604bbc479a405a937fdbaa6a75c1cec2927dd8c9df452e92a37b572d7396e6fafeb948ea76eea06bb8e63d781532b18c84eab3c7583fa76d4b76f34479cb321c7d3b37c065e475d95e7b82ad74f1727e5aeaf9b70c67ea9dc126e81aa79968b737dcbd7e945d7078e86310c48fd6bc2e65a3538d2f556ca2945a2d30c88384540bc1c665a2463bd3fe8649da3807e0ee6ba0eed1c0534bc3933b40f1d7b9039381e1393188837af9be12a0b2ee82a428a43c046bab5f51785b28e24891463e48161d9ad177d0e06bbf43aeaaf63f6c2ee348bd1b6b2eb8dd9858d5d59b3ec3e25b2ed9ae88e24b62c9d8389dfd1822db3d8d3d76aafa8136f1c6c9119a43eb84cafafeb05ca7699a08a458d2d9b7e3dfe5d9fc0101618f31270e434f0f11626003e7e93f733ef34c5521280d7fe00780defdcfcaecf5b775a745d93f9299160cedd19634bc76a614b4f0955ce478f39a7291fe628209350cae7e668b620c618638c2f4241674e18638cd147bf97a43842123ee2832fc618231154bfc7f85ec6a0420944500d71eae6e15746ec42ebc4fe7cac27c06350c6bb86f24f9367b158fdee7466478912055ed94e7b4bdef4b11f9a29f459bdfba13dc618638c38575c9fa605c15ea34c6328d36a2a8d2fd60baf63250580fb96006096524a2f47a2d45afc474918c7fe223d1a849070867d9d86cba10e00ce35385131010038ff8b23ac601db8d68ae5faaacdb4668fb0fe4558ffa274a333bc0ec4217d88ae37c78e9732beca353ac347fa283bbcfe8eb31c5ab9dc9594e7deaa29c6a9bfb00eece844c5847e6fbe996fe86743bfe7d5bbd36eea49d9aee870bd479c5f63ac03db3e1803ce56069cb7197046cdf05f7ccf82730df115679bf82a24bebe4b341e0ef50fd35a33cb6146c2a9277da409c96286fac5c733e018700ad7c3f7940e161c23ce926acf5e44c5e788c7718a37d5a7b0caab10d36a329faed5d65aedadf522c12ad1b8f13351c7d5be72b78f6e86ba392e8e7bba2a178bd8c7dce6243dd7d0b3a6682935a8fe87df7befbd12f6529ec538a2d352f6b10509c52c8b19ae447af4f54ca44776e1ec5746717e19b63425ebc84ec1a9cb87386ba841a5fa51a86d1ba2af447ab47d26d2a349cf2ce9ef5976f68d5e0b628f43c2f9554d48d676092e71aecc8933911e4deb651a0f074baf65d9a95693615734a94824ba4874592cd3783554d9ae65e2f713503183245408f5aa5d8b0a17f40c8c58c2fae9aceb27943640bb5615415d454fabdab5a87852854f633dbd517a49c744daab37a29edaacaeebe57b7f2f5e5733b1c3e6bd8e611367af2fd6381fab0ecc2ecee843f4ac77b2dfb3fa0cbb385562f670b08f4a42329c618f5ec219365652c15907c688d517310ef6d1f3c35b4fba23c410457ad63c829ef925e94c1f2f4ef621fadd1c1b1b32ff94c8899d9fd48464d8d95368c49e45af15e7d75331ac037b8475608b70adaf669fa3f78a53a3c7531de61fce367f1f0263e2ebdf9187c37bc5d9cb269216a4fe619cf7eca31a4fb309ebc0ae5789b33e159c1d1941e671aa90ac27ce4060418d61b347d735ed77df6fbf6741e6afd3fb0eefe925fa942b722492ebeb3dd29b7fa43ba87a3ab031fb397176644c9dd8189e3ad4673af1914838553f3a9da787fdb263239c75a2e8279da85d981d1941de71329ca72624ebf7307691e80f050f871a11eee96bd2ae19046dedadc516aade6ba7d9605df143c1ab81e221dece064b5460ae25cf1fb8240b23f4b4cb82085a3827edb228c24fc31ff723b21ccc7bfc892e536cef130c507c583bacf1c617ba60d10c2d1915018c2d7a58342f88c5a2798fe6c52fc400430b16cdfb6b459ae7b26d92234b0351263e89ef1de941f27c222b2ef969f22e9db060cc9128f372b004254d68de63cf9328f3583322914f2290174e1e2b47d6eb7150dc50e7c89a3f53805acdcbd09417b5c3f2898309723013c6480cebe96610845a8d7330eec151c4d81107031f8c72d22964b108eb99420b2d25432d25463ab6a670a3638cd3612640ecb40766d076781a0376ee2e10eff03c843647e368f2a60dd140093df0410f0b471e08893d3043bfbfc72022a608eafaf9b4d71c043bceaf539e3de74501723de745d12e0e9b67a3f2d1a12644e5a3e3b859fb083bf70308e760f2e8a59b701efd3445ab553e3265edeea61bc4b5caa126e45dc3a56ba18afe90fd071ddb29d87fd0d97ac33aa826e11e6a6cf3f2a35ab59a511dddd71903766e44b0491260f76dab234bacdd36157c67a2e966d40a4edd6432994c2693c964fa4c5cb9ae53a99b50a9cfc0959cdaa9a36eca944ae194093f23864419c8b276dba4bc9442b08d26b28ced88ca4d972af85015b35bc2b61d715a38a13b24ba4819a28c0f29ef1502aaa056633a16c37d7d2f9462884549f89e3af6948aca8acaca0c2a4fcd709500e018b28ebc1e18039bc57590d82cb80854c9cb70874095bc0f89da3619fe341d64c7d03ffc0024b21c889d269b8497af69387d0b0068c0ef2700b8050300a36ec2d9b669055fe5d8caad57b9efc749f9644a65e5a6547ebdaa5cf6ca532a2b40503867d771d353d78ec52c7551299c5fa78ebae9aadc5ca455be72b3ed95151d57b9d957ee53a6ff4095e9eab8d36c503865ba6c95a7307e2da8d2896dba8e9b4a7d45a54645c58453297c95e7f7b372b796ca3599ae12fc2dca40564a0e1cd7b2bfa38ea95ce80355f228b972d38ac9f4b74cada470ca741d5809009e32e11bd92a57c14af051181a81ac2803004c9f03e70d077ec31f168c912669ba092bc15779259ced26af6d0555f2450af93fc8f7233f9bc01f19208e3330f7b2d8e4b3cd328a261d37803918859054bd9e10c279da36cad8973336788853f04d349cdf36caac6e871421694fc56738557b40558438452aa2dd2150d58a42a8e3b33facde1da276a8414822e114fc082b49814ab66731050f892ef1a8269bddb44a9fc562a7ab3cb594d214ad975a5aa356f32e9cdfa534452d4ed1533a2f29a50fe3541d1ec4a094d74919af79bdcaebd6779892d784549c92975d7f4959e994b71207111b07fec51e88de82c248bb96cf1a2d1fa1262d28802eb2b69f26fa9c50d8e8aa13bbf65063bb2610fb9c17254a94283ab1a7b42f880ce41dd73350084dd14f2a7bb6c42730983ded61ecd2dbebec9d84297bf7947d3db5972d3a661d144ba050220640bdd2ae15835fd86fb66d2f6fd681ef98944113070d206f139fbd39a509697b516aba5f3735ebbc9d38832a2a6c3307718d43244ecc81f8e7ec240206663ce146bb5292264eb49e40a371bbd61342d87b59f639b3939e32afbd482265d9356d5e9d78937dda64d933fc94360327e998bc339523d2ae133f9a4a4a774a52b0783d01d4f3f40542499e34163317658ea4e4e3274ec9f80285edc967f2da67d7dec9cb2b95a47c5e2525550a4aa5baee3aabaee866a913dbe21cc475c5390a0882b6c4f23ab4656ab6aa110763648e76323b38b1c4b9b89f0cc814c4d2ce09a116fa8384aa203247439c39982780762d2766d039a55f6f0ee65d07986bcce97899c2a61303e61e9fc3f03949066a8331442691d7231f4edd3c89755e47ec5e19d8df17c03052d46a20561d849ac4f27d0756e72e937ace64589e4d3231c8c8f0dc320396e18f018562d9280fda049496144f1aa65d2b8a274e2069ecd189235395831850354b10e6f86a2b9d32c29a53a465adb4d504d329237cee87abaee6d486540c15cd01aae87940d5d4d1438d0d0b823de2a8ddcc4b9cbac1c1ae99558ea3f2d2e361c4593ec3f210f5ddd6ec22d7b1a48283788d7d06ca8cd9c0c6306d0255f4d9a5622861b3d9cb32dc3ca08a069a86af8b4404c86cd0b64b18534f22d926dda4d590ecfdafeb1d34c8a91a10f7468b8e1120c3a08c3146e75a46335cd732dc6671ade3ba5e719de3bac6e14e373f349ade7473ecfc847e78a39bb34eb9ae371863ff9e89ee6b94fb8172302a59767770b1b9d612dce80cdb689173428b4eba26d915bbf93a96baeac334d1b13f2dab4f89ea7befb2b1bfaed798bdd783d85f43ed264763387fa045b8fec212b654b0adc05c4b86ce88255b7e46748cf1a93484f22f2573228422794c74494a61a539d1065ede07aa648e64b192689df7d751bbc9d10fe70f48d681b0c1c7c8ca1bf4e1c1dc5554e802e6acf377f460cb3646333ac630dca865848184be92ae4b0963b22b5e87bfb0186874fcc888784c8e91a4b5e708e308184d9a8c8e87a4d7560c3762bc133b66b3a96936f394be6234d36cea29ce152b41d18c3ed36eaeae38ef002325d59348a40b938e592dc8f669bb6a3538727c069e6c725c3b1151cb67b7c9b012d4e5536e96b21175f69467c7b420ae951c390d0a0f21a2a1813ca6dd5c9de1bcc3619436d7754c94892ea601797d3d47a0530e7f69589672a7d9c4a788349b948f7e6937da239cb738a2c7bfeda6432dc876a3c51c18c7cd298d1371e63bd026524a93bedddc81c6b99ef280efc0891a28610a3f28820f8d732e2aa79acdcd22959ad29d76337af61948f3759c78fbd1cdd7ed556e26e17c1dd60b873e06e1ea7c1dcb325f27dd6937f96ad16386457726a65cde0de3cc7fa02f9cf8149caf6943af1d4bb9d7b1a7a95cbbf3d7c5849a3e75739dfec299f4790ad4d8b7250d0692c67e1d9b5453c9d771483bd767f61a955fb774ede294aed97cbd9e6a42e8f305e4faf64c03723dcb6eea86f4eba45f38a5f294203b7d3def744ae5291bd24915e7f9d15140761a754b77231d3b09af7c08a178621c0dcfd742f408aedb3b445f3b2d3520d7a308cbaa106d4fca46903343037682d0d8106d45f8ea3ae7e7ea6561bbdab5c258d211978880b9df1d5f00b56bb5c8689976ad9614edb49a77c5d66a19d1d9a222744f89886d4decf7841d38882fbe2f76e060cb5b103334103b30093ff38f5229a994d339e9e8740e4239674e7ccf4518618592dea5e884ce1d42483521f2b46259e6dce7a4873745a79b333ed7d465639dce51eaea81d8e94921bd91b821760e067e62f7b015e4f76a9e76130fa9009d73ce39e79c736e0bcc3d1c5e3b8845c8057c38e447af233b8beea2f40312fb3aa4f633ba78ed9d68de622a6f6f314e4b1833678e9f120ad1f13455aff9949d534609e7d38220c108f8092ff1cef56a0bb6186a92764dbb2e91e8128944a24b04b52014622dfabb44221186c9ec61f83932600dd1ca6c8aa896b5e38cb22cbb62cb0e8f338212c6d4bc4929bd70c38b96ec6da8736a07514a5121a574bc0853c94437b399765f6fee8776edc20eea20688a7663a7044137271d4456723f7e78acce51406b8fda81d809c20fabb563a751c763550be2b460b176b0e86175dec182c56a20e20fab359c258bd53f08b15a5e47d462b56613a1b03a274689d2d905b15ae2d2abe1d560832eb408b64c713026a88a5664a2bbe367cb1b8c3175bc2eed46f42ba54597f9a59e7689b49b656b97bf6e0a1b6529aa5dd793971469371ab6412210abe50fab25ce895058ad61d1ab21da5743bc0db6cdc99e9e2cf3f13961d9493b9d4ea313e9743a6da7d229e5a4c2c32853a03b63f4242e58741b91b2ec66521bb5e899949a26354d8eb4ec224cab79686c5ad67e65d7afebb2234c864cb6e8754aaad9d04b9cb58f5e47c74677470e36eda36bc7196937f4a447cd066731f2a4163d6a35a2eb5a4eec0b6721fa3a76b3cca3e7ec993ebf8f328a3df53029af9b23444bd273624b1210dc23327af4ac5d8e8e8d70d6b01459edb2c545ab479a3c863bdbd6def5011663c4291bfbe0912d9ccccf3713affa4c7f6120a28e0e068828553110513f07f3449d1bf66bd733314788867f1d637ced3488611298abceb423073bae80ad230cfdaee5eec002de20e30e1785783b2fee3896957b64401cac118d903e930905aa42d6c975c51aa223f75df192b8160ebab892c9830274d182723484aa9193326eb07107a93e61cb811b94a7e16d4a06a10e90b4ad6434bc75972d61676073e6bcd39c0a88769038bf08c43d7e2606a1a78e1d18b483424fec1c4c970007422d1d8f79f778238e774224ce423410f79e8151cb2962a4042460b5732fe21c213ac7cf1793b87e54e943c6478d5c8f5447f67b662fac0365539900d1ef8e27a08d2e6f070bb61eec7b37c196ddd0456402f026541bdb565fb17df1c2e6fad12877304fc6045ddedd0e24b64ddab9fd3161e3b157ab68065acc5a6b31767314509fdd4c04c94b0255f4bd676f76d6fdc1f719089934b43b9cd8ec77f86ceef92141122dee61f1f5bac97e74c7130f66f8c9b650de2880078ca1421cde42551686cd459787418cc75139d4d3c79dba9737b634e4d04462480f9327b3a75fd0903969cf9c53f648d9337bdc4e4329a3504a295db9a6d9a41367694538675b86b3a9294b531e4d6feed1f42f6b6c19d57905af5f9f5826baeb1e2debd3a8a59158f28009943c6f0f3924d39068508903a01b30692887a41c822fefc0fa640e7ade6c227befbd1546c1b0ed105731fae8f99a58ad56ab15b518cedb8631bd832b1a7d94a438020b3ae294ec88239e40948da5a609ec4d343667a10aca0763e8f5ec03221f3f2f8ec4d004b75625c4bc2d2f6e3c7a4d79e59a05aa5050b56389ed3d23dc2049cb6330ef36eec7c8fd78fde8c5a93174e6cddb632a979658608cede9f9d40dfdbce9b3747b337db61fd53b072333cdf4a73f4d88b5c2a7b1d3d2e9ddce42bafd83c954c83c4d390b76fb472f2f6faa74156afae9669bbac14c38557aea4645bb8623e5a50b64a753308ebb5d1c12c6fae10cbfdbccfd7899fb01c46b9ab291b2633bcd66634156c35a6f14e243577b1ddad70fd775680f5d3f03ebaf9ba3807e1a0376ba62e778441caae530d3cef1c8f45103426fa8cc1cccbb7c97aec6c6c1bc0ff1764cd02221af0cc3eeebecf55d594a99331de982a402b007bd184d39927213498947a367972da311698ee61ccd3b98f7ccb6686a35d76b3c91968e8f05680b6674fc23d272c302b48529741cbda8851b18d1f0703b69a765479116634c8c98747ba8b1917e3d4ed2ef34d296836b129624b95dadc652f8aa331bce2967b03ba417cfc038d0d238f5d8e9c528cd2d4def30118661d7755d38c7451189e867a2c44e27075a1a877eca3baca55ba0dd01838d3eabae430c7bde5a24822ed8457f5acd756d3fc80b677762fbd8d86102ab82f0999d4d5b3de9e5c0aa27c6915862fbc8b8623d07508de3e24587d7b2b1d9bb862221417000d515e3c8536cdb694024ce6013d8bb6bc1de9fe66060e660e0dd7d429b6bd50049d776ad9f1974b6ed7eb89476ad1f24eda0aaf5f3d30eaa8c60d2416094892ce569ece130677e8e7446758c4d3a1e6503289114a585f8cdbfac13b31d48b68c42b1dc492436106ad7aa01194d8076ad1a50d13b4c0b7740b1dd770963eae5cb173679b9c305db53e2217938bc9edf215abb6d28d4af52f97859a8c19296d702e6e056ddddf1c4066fab0e543df97ee0a2488a309c571c5875dea17144c7a9b717e1bcea7c817e4474fa15e9775474817777c7131bfc75120f4c33b5c3201ce12c7a466d8de19c75d6992de54a0e01732d311ede69c162f50f396e88c56a9d528bfe438e023a3a98ebf5f1420c75e373dcf8d295d7d4a4eb5337f255c76bcdcae3757d3ae6346b45a42c7f41e9fa4883278d5d1eab19d56a562e2f8ec73b3ae63420cec10809a8fea8946d3595412d95aa19090000007314002028100c088542b1603ca04892e87a14000b96a04c705a97685112c328858c21c418020c0100801190119969053fce25c4d67c696e42f064afcddd82630290084fe9f6fe1907fdc6de405449b7eac93309e0efcd5409c3bb086052a7502ef3c405de888854c4f1402053bd0fdd73983f31f8510895ed3b74d4d62063f0af7fb92638804a34ed455e8adad1f42e62f2509f83fb4ebafa34a145e534e6f630ccd0d50c454f561bf3c6be0272d22eb3a3a56719a2de225601ba184418326490ff2c5cd48412b5b81731314dbf194a0ff39ce45b89f6dffb3ac68b383dd040189937fb22709881d88bcd925561a040415286c72beac136199884c6169178fcc140bfe4f55e2e6eb08d222ca2bcd04de3ccd0a565075b107dbfa62f3be99fdd841bebd3ee37da03bd6e4af0d751ed09f24910b23c69dfb89983c4e122571fa0a4ff5cf74bc114ea1c2b1f5e41fb3020d515410495994b8da542796ce3cf26e0f4cc9d89d0e30326d2d5907a3d5e447a2ff8729a5c728d8c932666e214acb20871b250f3c85f6a603dc8ec8e1142de291f17f2d73db1d63de59c39b38761716a22092fec8f58d38e0874a73f5e6611923450320187eb4d2937181aaa7b68452410737ad446a8a498a865c1b39e6e549f63a33cc282ecd447a65afae6d229ae687493e77245983b936ea9279a1b6767cb7b0e09ca2001d153722a53ed17f7e80c967e66d377a219c6ccd3234967d2d9831cb6f06ff2d42c59699fef3faf8c60a1f954cc0cb8437f475c5db8a59c2f89e00f9e0fda5f646b3dd7ece111ce13741df070994bba98703b1deae87aa97e8a99abc4181a718dcb8dfa7a3e1af02b2d632d0707304b1b899682c67cfa37e8c27a249a3ec5a862be4aa9f8251efcfda6e03532f8385b9d570f673f596ab2e769213a6b334ce3ccae710603637a20003613ce4735657139049cf61e69fedf067d387341534b72dc3414cb3392182b4859667a213297277a293856423eae55378512a1417ff6d79206272bb9153ba96c2d6c9078cd9157653025f1a86941cf08707d9743067a2484a4ddb7fb526940311eea8e90dcb74828264e016ec2c173ae4af42930768e113b5fbe0ebec912194a3b6bc0d6b18195aad101895050ea84d9670a73a49da37d53e33fe7222024617505f196a36618e341937546f7cd227b2910a8edbbdbdec3d705e9c3dd0245dcf8886b03330109e856d262bbf018eed402ac06ca58c1786bbc1f0f888487b5ef21baeb59914acec5e5ba80d0932a7c21403e2b2f3044e7cd01a81560eb1fc729d98faca61fcc68fe6b6f1b10389da2ec8d3f5e2de38d1b02dae8be3ed4d03c525f535656308a5465b7dd88ec9228380b1dad21161aecf31c8492d388d03e158d05accc23aba4167e55adeae94a6df3f672f40fef9b175be2eb6dce4863bd1e1e83044164cad974237140ffa5d85bfb31983742516481b8d0958b323fd80ba83a8e998b67462581870b3b557bb25a2576e557719499fef73a4ad4d773632ca0e71434d5c3790c5c4fc3b290b3ae9bf1889bd688b6e4c9660bf8d816872c61c59c0e5b13019f3a94618565bbb24ea691dee98b730ac085887ea57ab0a5096c476f0cb13b47c4b6895d355c810fde0212f065c024e640fd06f5c6aa160b8f8a8bcdcfa5692fd2a5315298bd474c37d612364f52bc936f1eac7273bf64aa414629f537456d1f5615e22d0e4889def116675da811f3a66e3535655ca8967f4b11aceb8a9d81ce9c7bdde2fb84974eb0a46ae0e68ec209814738b22e6211da0482abb8eeba221063ed1f589ddb57656956f2d59c53ebd690816b36732f412967f3796121fe19167da8560d92515cc4c6003343520dcf3fd88b53959c1d96b9740e88375e9ef38cad4eb1a600033d5d5474afad541d12d105b6602e7698c20ae443d57a995149c390c62aecae237ce5d448ed0028f0b5e53496f5376b8499840aef25eabe40fe99825c7156c706735d277500f7eb1daecb9aa34808a9b1c5cb206c805cdd311826b5a736d93f4a667015a898b662ebd149749e4f7b28dab34b33fcbca9d28cc8596d93db951633f6ea7505776699d7d88210c153a3a46859cd0dd795e00aa2905626c52fced99d797594772a9c4baefa10247e83073597f906357979c7283a4f2b777d98368f8bb9c8b3758c8810d75b3d31f49aaa683a4c6c7ac333c246513353b54a9965aba88a47f39daacc190b14e946fadfd18f1c0e2d722a805a8569c811e48dc2fc4b53a69fe7102eec9d74a409655f613c36438d4cde2a6d08c09d3c43d35bb1bdc81c065b6ad0cc657aada0d2887ea55964ae5a8786bf4eaa6d4400fd820fda2d4bf864f230de2f0e34ddbd49a57919f9e8b8a5e6c6084aff16c0768c1cde968705ac2cb8255a4ff9a2a6970c28917f11c6f22fb10e476a59cb2b5c349722c349f9d57320f797819bc53a5d68f3199df8627c02a46a59afeee0687ed27645e54a6de83719a6b18505b4ed16f2459f82f9e81958a6ba10f95ffe1c87103844892c2f0b403cdbf5772410a38426ecac0be8daf541e316d037dc5ab6a540bd61d0300e2e8741c10bc42db43c21b2546a3ab049e9ba81c246a29257759b12d1f284dbdf7dac4eec1a5ce267574b32ffebc05493ed0aa3532810751a5d730f8f50ac4d33b94c65268d1d5734ab5fc7f73999f20fcf6ab1978151e175766ed1c6de99f5a2a7afe00df11798b587a761748a9502f7b93ab5500563e9ba068df5c0c32f53cc32bd163da377b0829d1838fd53c5cf945058302d845ea0ce29550a9bdc66d24264c06a51ba47456c50e85d02403d2267a17ec9010a7ccbd68ff0793b91c715198d1f9114120066487c779945bd7377c7324aeb50e77362218034d55a087146d4f31369b24269e10e26531497dde49e6a97a0d3a767502d451a8822d4c867d4e2e31a6ba4b98e116de9e65e9448d2ff0904a4c3f8f6b5e6ebff5df3fd7df2fefdf2fefe79fa3d7996dfda07066683d505131491222195936b3127f5f830b3effb21cdeca2659cf9e69d1e8daae8fd74b66d8732cd4f84d6185860cd17b5156343617e5509ebebe98b039f9b7a15dc618d745c16e3621a31a0405c7e3c467095badf50f181f310270ba645622dc574afb7e6eed4f6771c5476624e4103809b304e2f4e636879f11a42d742c0e9dd4e6ad849a368ed8b9d3f2d5b5306a20605df450b1a479cb0d38e8893d75629b924afc343758fad90300ad8fa7bef7274522715f9c027e26811506ac5e751a5313e7a781c8ee692a8cba5af471b6e967ceeb72df7ce5527f99201255d5af246febdf7b505b16d2091cdb306162b7a2f897c5f17c389edda6308a2fc0e6f1830a95c11a5eae680a1c46a0d539b4cff584fff10b597789951cb5b86002317c0c53831d9d8f96f410b4ba8ea150319c37bcae5bf3c314bf6c25740b45ca697fd99295b6ab3e08190fc8c2a9362a1d28de336985a3e42a6b65102c4377321597b13ab33e214c47a8e0f83ff52f1e602d5aee8b3cf1219802d8c323aa6a45ec7f514f84a92f5c84d5b2a742bc90e8bef63b1d80786572ee6ea54fdb56f34b3efad13cc1d9f258f95ab13afb59e8e159926d191b455b6fcad4b1145f9e562f53527bcd3ca08597754fa5c6a0bfaaa08c868ec0dd24d04f2428b35797080a39724f31413b58891be3dd63a1ad0ef31181d2dac1818df623b56625258f7fd7fb2bebfaa4e6b1bd663f39965eaf523444fe8050323289080312dc5ce32b3f9a3a94f54a980e66037d573fe7e6fae42372ac0ee4a8970b75d96c2b0bfd2a2595ca8be35c64154150855e8350309ec537c474266687772066233bff7f151b5ac55d8f2f212b7c335a02923feb09c7fb5c4dc7416ceda71347dc9427fba27af6a5e0c7a18315e6b0985557a033ec061c6c747af6e0ba9055db9a678f22c5516ba919e6308416dfb95a466fd5701057f0894c1737a5ba772935d66082cb603db10138c6dcc2afd63d4cc04a27d087fba2a30ab94a2d9e040cc2ced5511378e76ba88a3f902a3d0b34dd792ce0f5405cc5df3207e4d4ffe85e7082d0a4dd690fb5ce55e57716e73b48486b0a024367a55bab9637daebd4aa291497decf0f4465eebc01ff94ce8ce0df4dc8295c98bce9e9f3e57f9e735003f295a1635eeeecc0694b65c5680068b6503920fb431c0e43b900605bf82edcc5fd9713dbd46b1df79852b1dd10ec2758a0af4095935627762f3ff272eb0273e709b40603fb1c03ee1c06c2202ff44efbf279c02bb4c34207829aff4ddf8aab72b14d6c773ed7b4f6839ef85e0d039d2a521d8c77c6a9cd09c09bbbc860d35d06b141dca20974c68822e3a67457a139ba2739829f1c6b1cdfcf63da596915ec19262a6617d982d234e70419ef5c26a0a5b04813fd4d31594e6b27c1244fa0cfa1ee2b06031610b8a8e672f7a7f5600d7a0a92119fdaa9f650bcb6e55652d34a5aadb8d55f4753ce84f5e442c231f37f06c729fadad008e7e705f10b0ed4d6ba1db935e498b80e4b42b3d1e48871b37a193645754227d777ac0f05a506cd18ba9b2b16cd4bbf9cdd5ecca9a45221e9d243832650a48362f4721afeefaaed2fdf9f28da151820bbf54847ec27637ac257c1e087d1d366eb28264bc707498548e6def1bd650a751ee7e7cae25f285563e853f6b87859503d228b6e20315dd254eb840a33bbb483b9d7b33b2b33af60ccc26715100e9aa005f754a41870aac9ba6d2d6d6c3ffe010dfc554d1c6a0cf706124a58156a52f27baed0ade1c7c4c18cf3a3a7d136f5b37fce544405a41451bfa248bce823330f7a2fdb5c4419b242a8053b96a1205719333034f6f92a3cb081a5a88a71d6f475474205257f124a3b4f89a3958e6e279b464eb23f80b3f4ce9f1da13bdc81661bf2ee3bffaea23162b9306c6900e917e07222011421cf8fdcfdfd5043caf7e1c98b4b29caebdbbce45b3a9140d9d24ab2348dc0b1870085b6f96a39d58379c454e00e54cc6676c0b053e7f4e9f00327185fe9064b26a23df490760e624aabe16a82668893b3db2c7e310c8921f02fd3226c55decc336b60b5379f83aca5a9145dccec3c1eb7189def9762dcea975f40adf9a21c79ba9a382e0acc9180b407ae07877a03cdb5d48715a1faba5a15cc16db4aab83c503eb238bd84514f89647824b79dcff8fb04e793784c8508f54f31ca4fb0f6bd2e3f12f75a97828a5c453a9f375078818e7c8261a4ccaab5a93cc9bc81cf9f84e3d554b30e60c4d73627446482f0a7f5ffda821b1d08c9d95a2397cf990aa3b6d739711583c09cad8a1c0ecc8f1fd2b555322d41ed80a716bab5a6410a07f2f84e5146075993b0d469bd69b7d6141574583d0b21d903613c2fff59bba33ea476bab62f1cc99edf477da5875559f5b0f4e86bf65e49638ee1c69a0c419362060fc3c72b89acce8e9c6b7cc5f80ca034c0de6b71efffb105dbeaf2bcd1cde4592dcafbe7787a3bbc8e8450dad94f7fc3f0854c535f967aa5974bbbf0f786c8a720aa2615c784fa21b9cd7585fe0097d71392859d99bd8c8f38de0d20d8b597cf95c9b91abed27d7653764323346d8bd4c71cb1c52f507c84de450a46bb30b1f474566d83c7e6224f74673f8b3d8aae64f019e2ec768e6ff6ec726db607ccc0f553c30d2ce58f1aa860b112e059d1a8846caa9184c21f3c0e4491aaac79c6f40a86c4392b11618a5f365b781229edd98c4a4e5bec22a401224ce70558da296ffb4f8420d67ee0fb327cbb84cc10630edc1f5c5e153fe888a47f471f2476c0fd030905c66e74a76de30f19d0bbedefff00bbaffc383de0f3ae9680919e31ae40e7ed172fefc2489c7ce07bf67fd9007bfbf45254ebed67992f71f3070925d84dc0e4a05287f3cb2c48b30899b9ea1b7d8c861370440a893cc00600b964514c8830a9bc7a4abcc29dd1149c1f4f78bbc2e0e5efeafefc4cdc5d6c2784377636cd93e8e73bdc537ada8bffe2679a1f6b552c8d9afc8273e307a631ff6a9356c8a24cbef119082c0c12accd42d760fe392fb42cd1782eaeacd042c803b95956c532a2ba6025838520a4d4dff7d235a406668a5e05d0ab548ad4835d6e9774e8709e9a8cd0c24f71f1f4c5a33e1a97b5c44c9abcd82a95093a4006b0105ffe430e47e28229cc2452e981b598c6426c6d7bbbda7c5fd1476b0f5ae602e2265835d2123c2b5449ac3bfb78c039a4b918a83ba808000ba1c3971644105c7f9113071b183a24aac97eb8189424b95d4f8359812b25d6dfff2b1a30bfe95a9ebc5ca3ed3fd4196759fc601a1f94f5d61b5bf4a4a36e6e0ebf64d12d8202de4946e8e7b968793c533fb7ffc0987fd3f5c4562e9595162ba0309d77c6f0617d14ac61a79d23bcdcaac193853050bef87a329ac9fc3976f8bc12836e51a3709b968dff14478ee6b7520d91612c56fe162755dd99cb699e7cad65a0504cba23164128bd93b32ad9881d7632a10ae0875166dcbd9ab2f6963432582d5f8abb3282c53dd71aa38874b8978e31b1fd2bfc7fb6aa00adf0118c62d573380e37ff9a07028d0352276e3899e70cf12567581230bd20c474ec6b062c33758a60f278d772ddf1608e17992b863d48fec2f3b6341dd553d43bdf2fa0481876f4a87f55f0ad03535c52a87906551b2a4f515ed39065ea031ce5f17ff820480dacc2e810c998a2a0363fec47979ee624544b17c29f398335aed828c122e5bec01e7c3968f6729810b3216305569d9c00679a144f11e522a25ce06792ef6c74b726662ad8e900dfd4e077224f44c4207a099cb6fcfb1622fefe750a4537d13a2ba335b1ee13c67bd0eb9c519a0c2a36edf84f7770bc4da6ade954cd498d4d755868ccaf5bb0bd60f39b686076b015077b57646c6be5cbc24cfb7bbc94eb9a0281c7ea4118df0e9a40c6a2cb35eee7bb783bc0e7e43be24046fa79ea027dc21b51d80acaa93e78a7c292eba828177641d7538cd91791f8c1102707514f059bd9522120d8cad12f2d50dd474dd4e435ebc5e8a6b265504f16c16054ca13b3d701bbd5293f11ee1dc02adf67ab6a6e93f5c55cc2f3a78abecae6e6c7b86e696cd0163378e814ba348a5b577537097fc84ffef286563073b578e0a49477f529c4236ba729c18a792db7e490654ffb96969cd357ddbe1f03ea69f7e2c353f7fc18d7a4879264113907b035b9f4b5a5b28fb578c68637d45fc3e83a6e17f9a86db694d5a40d4dd31a306db0264e622e2988f6e41ca7a59fb9703c2a6a7b6cce753b7d0104c12934dcdebf570d5ec96a055b91f9a7c3bb6c5950351eb8564e8301a87725fdcf3e7ae03c0572983531063fb2d23b8f718669d026e5b75acf96cc9b8867c7fcd5e51c3fbec5b634e94ced42b2244fd0fad1d5cfd319df189724fa6c0c3df052cb3c528af3d945f845d228aee948a5917ff41c29a21cb903de3b71aaab49a40fba115b72d023995273572e1b18698ed532f4317e099632712992a550149df06b060095d534049bbd73b378b1bcce360ab11cc72f67e0f0becd51ed3c5a076cf08da15122c4fb52efe25db73ab6e3e09474c5eee11357b601b54c31ee9ba7a7204d37edccaba760388ba304f6dc36d4f7cb681b8e0a830dfe4533cd334fef2ae234cea2d4a3df7e72682c50249f851755475de3699d69d719b5ba934711d0c3fbc0593211014cae81ecafead337a0132f2ebdd1d02683bc259bbf052e4cfae16371061a48262e65342a2c18e575d9a08a0cb3a6743bc9a33b663ee40cb4ed6537051540144d85fc7503611b584330ad171c1829980c21ab10126a798d89897a94e181a008b9d6a8cd64071430e20db00e5b18d7974489cb021b86845bd401f808121fc4c9436b1e8dd3895c1b699cef7bf3d68ef5256149b5f26c86199c535e4105c0b5b1c611878da3d7546a76f31f74733c2f32c72dedc99d018392b5fd65b5fa0acd5cb2bc556196152ec4e90e8ba06020ccc4ea915c1e326d0c7c4aa748171b1e2b4c84f98fbecf91f2301cdb29f6d4c66a5ff92ab5e4bde2cdc71ba414a6f4ae9a6424b3e3fef1451c9538f349a5f51d587864ebb2a5d002c854ecb522076d01d588ac3e7db1dd3cddb61b16a56e89ac801a1978a7ce6b9861f4b180452625108a0a64a15486974aad85d6932b374512748088f54204e5d34ef3ded8a39a9af74e1f93e44a1f88c32daa527b512cbba53baa50a7bba02c35ba192c749f63bd4b0d62a9c01f552c7fac7f75bd2b74f74d7bbd97d053d0706461794425aab0f677908531c975161e07dc969bf43762035c538584cc97226787aa192d80c0393cbc4dbdc2c39091c226ecf4b11fddbe076a0cb3eb94d2655e9297dd74bd05d299a44d1c9a6a57a15a9907c62d7c843f170480c860a198c5a6c195386343f4d52afd38a65a8a4c4284320cbd67c5a7af762c7b705cb4a64844cac87f0518ecbbba4797482762d9ff767d6fd172ac3238e0af2e2b27b289991898b5bb7d7f07e7887e1d6b5bee4260ec9b9e3cc9eb95b23c7744020d156b37c53d726c074d800aec303bf2976702d1f479e06b6e381f0ef99bb382b59801b0ac16f442fe89469cf3a717b35f0126f97c3d0bf90aab4ecfe3f74d1c6be0373bd4dbd5f272b744f5c3aaf7aaa48b77b67df489db601f280c6e53b498c052ca8a6dc478113317562c04049ecef91cbf287e245aca0e30b4d4238dd4de60b7c6d8d325f63ae1639f31ea9e6df7751c200d9230b9712a179cd2c9c0693fd003f1501db3a9dd1d4835f0c3d29331747fa463e6f0943bbd09a57038d909901d472a2d6315dfa68373561fd31db4681eeb062dce3980994b5babeb26132ebd10282225fa2c165f90b297c090d95237db8cf017853ce7226aab7d6e8fbc6e47b3ecc0c22a98603143ec1623aba5cc5dc253076bd80589721d6d189645e0e577180994b71d4046283a011b4308a9ac07773c98a01ad018dd3cd920cbb8d511439c794e216ea236b01455ea7c045f93743e2b4bb775900a8a8733bb0e5030391b08c538f433b80203a57472ca01752387520de00d11f237a5bf9540ad2b0e69ecd69d6910be90cfda09bd6780660ced560856e6990ba265a3bd4f89601c24f30130d5152b9e04ee366c0be52083ab7854112f65527ac679da3598e59e2e4f45d7e1e34b5e0cc6ee688abb0dc2ff79e897ee2e9422f4aad02da1456787b288a3914f1e0028ba6cc22ed2c3bdbb7abaa2392216d1cafc77206484ebb8d98e52dfc901fa7fa651989e695e5e110f508eb740288414804ba262e8aa192a6894d7c6d70ac6bb94c109b02772eba61080d065275715d7fab4629c6d47d71fc4e4ac714ca0099e60754346c0bd5113c4302e2e03d38ea97375cc22e2fe7ae8e06c84b1a24817244123101390cbbab48884d6f84d95acdb8348d33bf76cf464b0de1b37668e51897e6840e9320d698e71a282d4bcc9ca102ee7b8516f3e5b749363e18eaee040af43b4ad31f4434d0223aaa1b845ec1bc388361a1e26906b5bb06173ca6102f329c6a61b246ebfcf4e90f801afa09c7057842a02b90fe415f4b6681e7ff79a68c5fe9c1602e2bf4b488cf5ad9547d12a4a5c9388a0f67f724f95db4a11e1c9b40446fdee12b52350df6a91238834626aced96f5bf8ecbb740fd0c497029e14ce163677ce3a135415c91ba9ff9f91f3b466af99259ccb3eb8c090672bbb4017c4acd0b3370f0fc4b4ad34460829a349061f40005d6b69de758ba46dfa81dfea33840ccd8708f0500c635587f165912ea8840fab7f0900ef4c8c38aaf238572dbcc7650db07bf8b8df38273147565204910b3c9d4311f1c6d943083907359370736370e18768835a00b2360346bd777769b06115b41ba6354f2581d579d35f1a7aa0be7db747da11d5dd9a3283dc5d7265bdd3b91a2c08df78dbd3b0d67b9cb8c27a4f2c3209382cfd5fd2b81114cb489d41c82809d9df2d6222d9b26cb7b963dcec1c77f413a69955b61412744029cb5d8429488b9029cf84755fd47cc53185b26f4b8a514eb8ddaa893167d3671e34c5844dd9c79c00d410837cd80ee18f2b8f96a03f485db70f0cb075ce9ce010f2bdf82121094d523fbbd725ed16179423945c14434fd228c3f3bd9d21ec0cb39ecbfd112120248ad1a60953d6588a6716473cbe8e9bb535e546b9c511498e71b20edb2116b5ed4bb234b7d3cf615d031368a2bacfb425323562b62a8a65b3d3c1235cda8767e6e788afa40fb317f3e914fc5935d7b078cf0d8c8910d0a0309765afa07e96c36596d314b68ecb9451b07864da61c20418fef35a2048a340b0cd646dfc44d981a09444e5b0571942a05921a580fddb951736a39c334552ffe6b67737f6e2b58c1d974e49f02e01a6200c61c521ace76778a24f538bccc3767e9a3db4084f80f554b6e1eb445446c90cefcf5206187bc114c5c8566fdd57d3af1ff383494029edf0d00f6fe2153c4e1e820297a93f18cb72742a7fbc942368175376a093f80b2b07a63c9fc428bfe812949db85346b3f4008eeb296db959d21b7ec7d20c5073740a4e40cfc5e5370d554e9cce070806123e4c69d93b11f8c370d2812cd99315e1ca71d6e7d467ef48e4ea8465d1d943b4c5f345b8733fea9f80c2c0d2d07b547cfda7d7442332f0f6f36b2ab2b89bcb484e1a886dccc1ebff08d519db20f7704f1a86bb1d2c235ab2bff8dcada97d52d8e78e58a41daddb4af0f752db14c163687d6b945ec7d4782d7821b89285c532348ced412e8ec51051db18d75fd544b58332c7abbe4dbdfe780f89767038f696ae4dce6ac2919a4d331512028e3f5533c628fd805c21fd4060ce9050dbfdc1f913d764e94389add33a2049bca12c393d9d1d8b63d8df84e256f443dfc640a72c54a276e7032fc6f4b66fd2a50f0b0917022c16ce8d01056811ce4b86d041ccc68918e6976321d0d8a8ec7b212b48cc924eb08dbd755a343cd1242b82d99b13d2186a8fcd6690a7cd621fbbef99685dbef0c65a6d3611b88573e1ce4537032ca59a3e7d48465f31d020b08834a2c0b8083f3b673a69e891c161f5686f7ef9bcf982f10bf69270a2971e449b5af9d825d7acd99eada65bdba34c9dda18913c5a5b5a6980d08131f0e5a12fd40b955227ed274af03db2d8be35f0c1f3a52e93fc8a92f0116683d818a64c5c1551664e35b5caf25e1d6416a4a228a74c3f7e6a88074e43913bee8a5f1280bf69320b76690e48c8d20bccf5503f2346dd8faf6875bb44b9fedca1ee7a30e0d26797d79a8b28922b4e4328d1cbe58ef96c09aa9d0b559d10749e6d5b99f8fdcc8183d0ce4fd431ff77260f894c5a8ef9d512224222cbcca1cdc2cf0f588cbd6b99c054b80100848c03bfac4b6c24e51db09c98853c916051d6d7a20ecdfc4e16a71805163889bd69de704eb06813bcbfcb4b2c8ac58987991bf06c531f57bb10cc8fceb4e10f2d93feb69b72976638ecae5376014f6ad545266b11f3357751a0cb826167591b2eebb81c049c1a34ac7402ca0e91f3fe49efabf5fdf6ef4bec84f1d7d3f184654816b54a58f7d24986a0d5c9d64b1862177b81e84fd445864a108b545b4d63bf715a7d49bf1712580d2aa77bebafcdee8d5f00ae25b3b486ab5e7b0a3a42d9826f7b592e626e786bb6837c53e80bd6358530adaab1fab3f26c34315b8282a03de141b067ae6c9672cfae24f0b7264730516964f063554e67d739989523cff198d14c945083a1bd37a32a529e3d3df5e27fc08221aa0a98adf3257789d28e88cc149a5308af02bc7596f2b629cf82dc430503978ccee887b96d3c2fddec5695620897c7cfcee43bbe4a8e564c94f10b3b4e4848e461a0c742301a0d66e3642d9cbfb22883a3a2f03ee7382e6ba5750e066121b9cab395c378cc628dba2f921cdd64a90745f2acc9313127ee0f2886df2c9de205f4da2e48e83f43b49b009df288b38acfd7ad23dabc600d481defe1998744df12a8311c6e20f5cdb3e26db78aa4e9ff7249571a7be01b8939e559f2dce25bf84e0e7154d61cc7bfaad8271328db2f1a2b35c2c9d06adb88e51dcfabec66e36d4fb790e2bf3c964c695f0da0dc0486c6473451326567775a3a774418790ebd9a9630e32c601716c90376aa4260549492c89068ca50336ff6734cb354a491c895f3a3d8926309d43797ef3d7305b37b9383efd1ca9048b6705dc878797d8f974a6f38d67743eec121212d61931a4f1ebca494b8bbcde4d519fcf9c1a4eeb9cee61b4b1c638a53d2cbd3d879de805bb90ef1265742e6adbe3470cce0d884bdf9527e53828ac7e8e2d5a4a43ed82550da3d259154a817630be14f00bca2814f355bd8a801ac32b82de68342c17fb9dde9e90845c06f5a3f99575135249dc239f9b306b868d761b7f8c59add675be57f4256759a7d810d84f838844d97e2a24d4e37a0758b0225126fd6c5e51261f37b178ff60b033193d13df9c2b92fdf733edfc98f6f3e7400ca4fbda5f4fa24cf1f75ff9e9cb778d5c0295dd3e5bb93e31732aeef9e9d76e29aa4de23e3585e436eb7d4e2673aa18e639972a6edbd6d0edef651fc3cf014d1a5cb8af89004e9954f8948cabbd045a6cb4d5a0fd189e082697f240476ae4e8bee37f9b7026ce3923367be67c518fb1b2686af2f174290f9b213408bc3fe5abd4f99fef473228864ddd130e978409a824476c95741f644f84ffae3cea6bf22b06c7ea4e724609fb8c6d70fcbf49ffddf4413307813183e23c2d2a9faef3edb655628e8c6c20cc11aa98d092f25f1937cb244956a55a1413e72315d20dc0e3da98bfb9631906bb6bbe8d1e561466bcfc154fdb7b30f4b632646a469bea7bff3003a6659626afaa48043942e4b885c7df4024074ab9775556fc367ba7573bf4a409287354c4e14bc1d6e3f4dde9b32731a9f7410822bb4ac403af540603b52daa7569b027e74412086ce82d36dac96819b090b5fb58fc179ab2795f7a033d97dc9a0616ceb3e77e512242643df0b8f74b44bb6a5515784675289de1b488901df9997d98fe7b70ba7ffffe488f3b06c26ff8abc6d03dc6232f02ce2b88be0381f29da92c6f28641d13d654d975055195302089ecdb4d2920518c2cb3bf4db918f97b2ddc735f4a6779c691a84f12f34fbbc486137ca2726f150538ff0d5bf9e6ffd455b16c23848c9a783c1c373d824b143f334b74102de839668df23b3d605c054bd32636133d3764f654f65e65f4d42d12138fd03695d3fe6eeff837d70a7b1b3e772f8ba5a7933c918e26f2d11500bdb08d95ed5b908b125171eb8d25571a676512826b54a046978a9b08b4694d7c23ce090bc08f1654313d009e84177f0cb1f110206d1f20bbb7128d362d007754991dff5599dfcc29d46ebe49f08264cdb8d799a226d2356996a53649c24b65b9cb066a02babc68e80e3b244bceaf7ffd79a6252be984977c378553c8be33a6a328bedfde55d4d6a5b253e8e02070f3257eda6ebf84042dba49e1a7b3f2c48995b53317e7418c5b59d63c56a838f07e0b74e4292c476b7260a5608e6848853ce434d9f460823a5fd8c7c716267cc284abac8469d39d3d24fe2d7e7f5005b8ae15b29e53997d2c9fa619be632c15c3cf60b5e0a82587ddda7f54da029a5a1d350a2943e77db1a9209abf95940d28e407ab02b5842dcb5c560435289874df76bd7a800a8f7759d17b6c06b130d8a025edba97fb4dfcc50d9de2da7ba201a091ff1e10fcea83688cd2089f0001a1bf00d1a9bf32ca310c3a7d35c60a4fe2637ceb23a67e417d04af65f655406c82024132aa9cd431ccd5f03d3f312fe17216985d9288d3c41940f2bdcefac0c4b56ed38a92f357fac24b47ac6b8813d157854c080877208f12ace980211651a2cc1c6eda7e7937067c6c5f37b4ea85bb991de013c156b531293092b2e15f2d386ad3170b6a9ee53b82f9dad1a70204ec2ad488311dd1a3a563d8e0208f61afcaa9ac893ce4d477496da042ee27dec38ffe64cf83191cddefc511dc9d2abb6a693464025fa20a644f08de16e55d0e7839cac3e6811d6ec4746087719c58c4790d5f9f9be72f43c3966c4ebd0effacbac5feac369c025406b426b41517e6d0185cc94247242f31024a2ff04942adb5a20407118982e0549805584012ec41f6584d38b1aafccb2f0f9e559a7397928f1ed0fa0a2f3af0d29b261943dfa3eb707231b26e7c8b9ed2cf0ba71e33243ce6145792359156f5d8acbb9585845936dc60ea00908074d5127f8f360ba9a0648e4173c943363294604cdb9eddbaa9a457f13daca518615d7f91ffda400100f85682de2ef98e0255a155f57331a98e67e6f6cd008fdee8e25f7bcd37965374f2b151bdb3b3f5f1b08363734845a34f2d326109359315c2cd303166e8906647e01ae9163e8990fe84185cb41e9ef72b05ba596c4ddcb5ee0f09d7cecb6677df5a06128e75547ba170cea2252da7723560167a8407f717c549a5d5a27953e68f06704887e1c6f5eca11c02d7278410c29ec4fd9b910b908e816736203968803c8c19c9b00dcc5aa6d3425711db0369647771fd148b06283be19bd3acffdff32e384c56832610f5d913edd745254d3afaebd102acbba7270880c7ef6b109ded8474c4ac9fa583164a93785c06370b33b9b20cd1f32f20a2a08f80001c0cb96d68b549fe9f60de95f153506539244b000e15178bd35c4709dbf9a0d880a1a3138bc94a85150bd3d068e84c9d937bac3e1bd4b17b45b3f83b29bd91c8c8f9163193b7f86e01dc14863a32ea00ae0542d1795e9cc9319350d1288e493aba318bcf346c2f58ae39e6cd8dcb5de2032e0e1d1bb5eb891545640df9e4d3b86e104fd7f483fecc6be8460393f02000008d8a3887f84806d2676b0f4e96175b3d0321120195af59bde2893f278e2469eafdaf065168004bf3cbd2b993c27e1472ae8368a42ecb724e8da65c1d6e493d7a116516f1076b6b8249e94bbc0ac40624293635329faace5aa7874e627f586b2b1414dde529e20c624cc49a9e9de4c275d4ff558acc9367a47e2330453c1a0f18dfff2eef9c923ab607aa312e2ac3243e0d073398eb9982281e4284e12d80d29023de142a1c3106c36aaad7d18f6a78c9d8b0c38937075533f02fe8aab97ff157f7c56d1b0e495558e6c5daf121e2cc9bf55e206b5499b7937a8c432f64f251bdbd0f5df16ef151cc067ee5207497abd5615fc0c59b308e4859a274783e20b06865a3490055d8f208be262661f0aa518e27a6195d883a1d3026b9588281853dd5343266e544e006365ca67052e38a7af85ff8f7d7b9fdca392c7c5c5bb5aad22a1b8d7ca83468ea2916753f0d00a0f9d7755fd392cba3c5fe216a5276fb07b3faeb90387b1bd2d600dd151979f03bc06f4d8354b581b869765f0361b0460a2a9510ab1f6c6efa264265157d20aef3fd5f74d4b68bf9f2f705c90a9b42343d7c833db74adbeb00ecc90deebcebb1d42e34af786971f06c305a684cf0c16aa6a24ada4917253945a227d5faaf7bbe902c9f4e489babf8e84dc8ac626468072b771f815e0e3255b532909964082a94b46aa4cdcdd9b50bc783503a3021c1c8a83bbee317bfdcfe20ee684c573a82ce0712b1cb889b5a949b30a350b5895c778c022f990003fc480d5620191b0fa6b367b959b1820409955020423f0a8a22036e7eddd3ecb2df520f7a97924dd17b88c0024059ef0accb9f90d04460eed262066aac843eb85e733c3d5864db386c89453c974938e23fae5ce21efba117f1dfb2812b0114c054fb7c477c654734a8fd9f3d11663f75ad3efb1e3b286cea85b90ff8dc8b494c358373e5c5862d3c565d6f79d7d5e20da49f0d343025103e3acbed3761d2b65bb102d48e78aeb001ca9b120658f997a2e59ba9507dc4e6b0764090410857883f2a2cbfa3ba87365b5469740e504835773d9819e3f6d0dba35aa77688e89c81aebd4ffe427bbf1cb603fc76b59f6dd4ef6c053634bdd6ba945097ace2ce36eb8a3ad239e55e7938e2f7bd3852450bb24fb24366cf4f9900826c9f38d944d94c4b05827007b2215848a6de0f14608faf597befd6a261fd5f426c1b7762dc37b5bb5222de0315573765703dcdcba31e2a1119c92717302e970cf1df23318619bc2adcf19552381b5bf4d4a3e436d8cc060bff03b31240f0e5ac99e3bf74fa393c504c05c1cb0814cdb3310fcd12ef4c40b1f9770896022f4e260cccefa55e14f61daa7dbdfc335ff3a9c7549ff7b930bde298893346476a76f0b6b8c9c2d8a29f8efc73d67bf299c96eec0edd2f498c65865d267c75e868bf0ec48e7de46f2849350318fa94a2a68e54027df45b76d1f4a59226e1474e005b0da668d481f3bc164c1c68fa96b963419772267a313ea1b108d53c39d157fd713a683299436894dd006014af337d8fc4096cca75a82f56ef89a12dddeaddec68c736bd9e6a3f9b585b68d071a33c0f44fac018dbbae3de226d92db0741dbfb1c73687a80a1428c4491a4ffbc19c18894e5d8c3a7c3e4545c3225b0f1656cd6677ea791fdac5e93e95f9431298c1d60d4eb7a1ae92e03a36ddf8f02d46c7442d2556f2b29255002fb1716442b2f6be3da44c05d367d7f1c6ec927208955df1738e9a665fbe8a46868a51e87f82abd4c8072d8bf2e975cd0f8c1a1be00831312950b005522a2b182297dc2c6045c2dd2d794795d32cd4b01b62d5146247d33ecfc31afa722151fc1d6365b806eb55ca9df8781ce1fbd32f3b57a45fd04c70e864f344738efc1376424d7c15fc0a8372460bb9fd3b9505ba8d568100a7368bb14f3827f832fae400d68685a7be90b6ff25b413b19944c68e3d4744eaeb674ceecd7c411f321d8c784785009b578cbf4c84861307075086d9a7f47b39a9fcf58239b54fbbd8072756c6f7ef20287ed3fa6183cb3756d1d4867041a99d65bdf59c54fa5774b0d79ecb01776755db9ca23c31c7156bd7ac1666de5afc620622cdeb2f6cf65ff35d657c24132bbbd208df562d495c6fb4e8190ea2252cb7f9459436dc016d92e632c505e27f89952063a41099503e0a045d6f842b1406e04cf473a3efd76eafc96a0b88bdc16ff23cd01e659d26166936e36ca626ebfe34a2caa7c484534bdf299053b5947f11e96619e8c247fa9dcd4e2950a8203a836cfdeb3cfd7712900014108d7a58bde2ec00feacd4b4095df07a27f45b5e771c355234309f4e6a6468d7b46f21ef38ef542a9449d3ac14da82556148395c0a2d3f0f4ab1da7335f98025bc4b5f16b7c728f1682772938551e005c89a85d54450a367e249d0c6dd86e3527b02ec8b22791f5783082c2f13d421b3501ee7531d2bb478a7bcd0e004dfb0a79a1fce908bf05d844e25559de1f314c9be482fdc88609b00f2b886f06ed9459b88dd672da0a18eb395bf47175548556a9729e32e2213ca6a6120be6eb293908d0f030908eeab2e2b988893b8689c7ca933d55369e984ad865a5d12fc12911aeecfd28c4476a7ecf0108472b459f7c8f6de11155c11e71c528090047310c2a7a9db9c88eb90e550b2db1cf0b9805a8aaefe3d524e00cec18adb50c09cfa63b48413caee25ca38f692f3086c1e2b68eda3048a5379dcfc9b9c54a0bdbcb9697c10683652f07882dabcf11376430b793ed5e6c611ac789faee2fa93c4434e15d8abb482cf3d587849af51a27c8ed49ae4452e0b9c2688b54a766058510ba49012ba901c62f14730808fb41c418869208a2c1fc78faac7d8d7d96c17ead828c023c08100dc0a37a764a123c941fa378af926f422208368dd02058e7fd4b271b61ad26a74fe11c352ef199ddc615cc44ef00b574db5c792da084b764c446e5d6759755b34b5eecf60cf410628e2b90884b748985c5ada2184fb1dd03fad8255a28b366489fcb4937bfb8d8f7152ff0f755f2505c4c943e24b6f6afc90f16959b03139ca3b5078134dbb26563112ceba5d7a2c6e62323ca0b77313af3942e77cc1ec4767dec711cfe777829ec6a59508b463178e9110f5b00f98af42eb584cdcd9f32b15a8df6d0478232ccd70ce2979e47dedfe3349a9b55c36d431a9fff42a1fd03164a8e4641bb9d17bb8651069aef1619cffb4ffc5d584d4c994d4eb533d0a1e3b80a487e7191f7d576959fd67c1ae002975532df9104ef88e7f7cba4b41126f85a9fcf9b336006a4465efe1bd4709445f509247acdf812f8fda7bec7374ce2f1a9437ff150a921048ebab9ce6ecff01888fe3f8a14b0e54eb973f6fa2f00f2f4c10ecc475004723c1eb7fbfd072c01ce64ba0646fcd825c590cd309d94c3d8e0ee791c00d3d7b291b458ee6a374eebd78f659407d27f3bb765c5d956afb62edb1ccfec52717dc0d9043edfb315078051cdddbfcbe1577443fb99c53c93460083dc58285113e8001b16dd1ff50b421495a2ed6ee97902449f62642c736c5c310c6cbca86a532c36853892d353e60f1ac5ceceadd87410c6d3aebb66ec2be500df7e88d0b9a1fb3058848c1e0ddf5de77e7fc108f137ba6a85600cadc38ff3f80107120e0f217524a1d4dde1d7fea1ea9112f8fdddaa780ab15801e40d2e6339dbbe90153c2d0fe0da84256b123616fc9889bfbe06130166fd34755338111a77d06dcfaf27b070fe2f25773f14f008a41301e1a1c71c390107189082135e0c53cfdb3b833350bfd4fcf80740e4b57bf7ce1374078aae2781b4c6bc6cd9196a030a59816baed8d5bdb73f0b70d1a9c3de24d8b84da673b89d861967ed019baecd57816dfa9756b100ea1da9c0bb7d27888b6334f4a1d871dbc55e55b0f958a9f63420b78144f2a637c573be23c03a7dd2b9ae3297767f295d989734ebea6a3145a7b798761fc5b8110169e2a2b032a38f7053e80ccad07cad3788e9d31f18013fbdf153bf313ce9a75275a84d25c01a780aaac99a93679127c5b5cc6cc9f2932d3fac8a770d6b655f7d03db3b50649181488747a5c199008a57547a4bbf25eb06b8fa0c1ae602f651a5025b5ddc1ea9521a7a36bc19156ca143f18a9f80673ae1b28a95e5fc29b4beefaf563255b08d5af78e898f522db22aa1de41b89505fe71e7ff04a20c9d5d390163fef92001145517e607bb0175b7ae0095b27a96ea1f15bb88f0d91f255b08531da1ee47a495719e74e9944f1a4b2d473d8670ced96f70e0055d25ad17d1e793c7f512089b704b46b2b5e3a967e1fae488fc2a5fdafa5404410b8ceec9d69f06af0e74678c7030a78583e9c99e69fde34c2e515c5f88c744fd1fe93ea2cb0db1803b63735b31631b2c1016f5a52804511b8696db5cac0ddd7b6f24e0d305ce170f396b3d6c05721260e7ee8e120b8e4aad2124bc66303a6e18776f132e0003015b0a4065c0b603fe1381bdff6cb694427b4551c83281c5664b43fc8970e21f51014879b43662b740f4d47f123f0cbd4538c0c26aa97ba6bf5765ff6a84a9a675be388d7522c174af1b6872c47fd6942823d29ea300ed02a4e93d2778ed5aa2ee2d48d05eb7a72565c4318571b5f83f3b0c7285c81c3ab17c3e888a18655040469bc091b9b3c147689f145c2b0948967d2477816c86645d0972c96b412b9cc1acac769985d744af35b93a030d4bace6b41cfb502a517bbff04c252e744c3de7eac4101f337431e0fe30cb158dfe531c5792e8ca3f9d415109c73e1daa6fdf8330d88859673ee53f96d3de8c7c4a1956f4d845e2bb5e63abf1fd9eb87f0f31c757099a23158e1e30e733934c8d8ed5659bda6f9caa92b0da8e92995ccd6701bc4e5aa08741286e4606a6b3aff8142ddaa7beb8da3aded62cfa675455d4e79799ac873219355b03d0ba5d093191d86624c06d52a2dea2e94c2a15ec1c60f3a10632707dca9ba3af4dce69f56297e7fcca43b481f96d041ecca7e5f914cfc168cd6f721ac7ee8001452fb26296fd50f8063fc8a6f4643a80eb11109eda7334d9be47c64eefb633cffb784f3b14a7517560f1c05c64d77789017a1151f9149a8ccd7db68dcc718dbbe276acf66de8dc215200272b5b750afe63e1d1e091946d14662c61aae4eda2c1e66f7f0c2e127f59f95156ba08c08451e03a603dba14a5f271e0adcbb5887ddf22bc8aad71a94fc21ec081c7d27a5134827da6bc7ec3402e4c0bcd2d59709cb24b46948376a21ebf167fcabc1d88279858d51a46391025b86a6815eb5e27c2833279585b65abcae63554d185df06ea3fda2fbd97ee271ab2a800983ef9c94d06d1eeb11ec0ccf4d20d5ed1ca894aaf4f5d64cd45e9d77cf0498cc5f54993bad293df8ecd6edb8e2b0c2d2ab3c60c7becde67bca6eaa6792a4e9cba207e17833e55c614d1ec31625dddb5fd4fc7212a11aac37195d7827bf1b51fd9075690a83eb34f6c1b850cb75a7bd2fe22202647228f757fc5bface0dd8531a35497f6a8aef5a998419e855458d30b97dc8e3b93f68e27fcddd2cd3fa6059238ef12abb970eeab7eef00397631729d0917d5d411055c8448442e67763821bd853acd8f8b503de14057f1c18fc52a2720bba84445483a3d16cc71d72f44b104b68213790332a1645a8caadb6b8e849cc3026660c269ab2e0c35d150317345a64b5dc3f9d6f8923c4dd2260e59564078fed18abca7725adbe754e0ef9142e2e8e94a18beaaa49b0c4ce2becd86900ce481a4ef74e7222b42589c1957b297ce8e4c27f26578fa213261fda2871b093e5b2911f990a1421c47b04870fd0129067cacf2e0b8fb02648477f9ea85042a16575c913caae6f9d15be21d45a781af7db62c845fba2f62fd15245152f9c9aa4f5b5c38b90a65861ea810efa78fbe2f1ece40476a84947e437789cf3e11e733c42da3114cfdcaa4689eace9a64693b16d55f055a223f486d5c332a529e93736d4f7e1f3470e9e40d50b3cdd5c1174e30e2e2ac7fdb9a2f352e1e51a4e408c6b4d63c9985d88a5c9b538c18aae3363ea77b5b41015fa5fed8cdfe8297cf606947f56b32ad66fabd5a43d824255175b3c694e71ad616f7a49b21bcd6e718d8c7795c584be29d0ff05e796b182095ded9dd0f2dced84e0794505677fb2d5feead15964acd0cf5a085646c4a2f5c4d31f58d250002efe649d301a9e9d5d0ca0d30aa06daddba46e5005f5a2cbda94bd4da91a8a7262db713492c0ab3f6cea3c77881889a5d6b614e45684d4d7b9228b9b1d18d54692bd0f1230e1d00268383c0b19461b070327c48c2da1c3af4e51bc42a05e9903b41173543b4cc9ce41a243104d7cfc841018adde1c9d036866284ade62d9054070fca43887a9b001e7360c2d763b73512d6163e8bc67ca09829c5275524ac0983c6abf8e577cbc13f3fcb40d0f3287b9c14bd3f939d45b61c46f46e9a07465b2f82753440a47c6a94a53b6029999be5146abafdf05c774c929d30190ffe1469862eb1d0adba4c657eb5976ac1893533c206a58a462fb41b50f17b826c36f299a45aff759c3f34da79fa9748a8dc0e6d69be2128b1f2e574c6bde83f3dc4cdd7586b4441ab06c58f550055725c1edb96a973529d3f6f1d8d3ff770e3b305cf5c385460c7a200b2e0d51902a9705191d142dacbe12ea7389cdab39ee26d3bc27e34ec8008dc7abfc0efd8292ec8c34a174641939cccddf470567b97bc7627091fcf3f37a9a3da1d17efa6d2dd4b9ff590dd613ba36063ca8ba9ad575414c539715f5b0ac082e1f323d08363a2932869c2b00fc0f20893430f7de0b21d0f8a41cef409afa6db2b79adeec71dc594afd077ec2473d73327de5d6317e8c509e5fa6e4fefc4b3a3c8cfe05be4dd44838607b21e4f4fc7d3d0601e738a325ee266dc58dedf64feeaf23391bfcb0947c9921c34e539e689f410c33a4737bccfaeb10250013e82f2d2fb2c4580f1bbe6d455238ae9964140e63a5df7900a243fa0f718f9134cc381d835340507d2e8216450fbfe760dd468d0b7abdee149b41dc1691305df8bc0579303146c0141eea908ce4e736e9f98b855467cc9212077ce30d42142e3bfc2981c5cc6601091d3d412fed617d7e4a1623a2b75f2e89d5403e60e00661eba1ca24cec59270ed8da12475918bcee6491331927f06f0225031dcdb345360725f25fe843249f46c07a61dbcf6445542b5e99cc6302ec70c692ee9e2f538dfe02e0af02704d273f2807e73d13926b15a30d26a003ab663d8f0f9e6e69e1e33406e0ab87e81e654d24d9a876d31467f7ec9f0acbc567da4b99f5e56917ba4601228b0ea54df07d7598ec552131f33c0a24789fb9a5465933221e4aebada5d4900c02c811b5b289b0dac02f00be12f2c1559e48ee4d6787a75f67f4a50fa293584eb205a1ae2eb2de80b9ab4420831baccb04cc8dbcacef237116780b505f23c8d9e91e0c40709643d1b5a5fbde88b7b2d40e373092c9d7010053971db0babb569c7484fd00e0f99588b6d42d965d657eb9f512cacee16c253f8b782b8605956aca56c5d6a35625c0d07bb1a291ca10fd178e641150b481b6c9185daec36339b204f69f664862dea0f17844082f51bc59dfe458b971bb40c836aeab6f64e70ab622c92d3b4f391653dc704fa078bcf20db5ae18c837678ab17f4d6c5cc8474c23617c53f339348ce2f133d3007878dac8308cca11e350d6f1dd4ca693e24fa738ccc0cca7379c42abebb6e86c48b4b2953305c550e7f13c22d3d7d4f7966aa40282a56a89fecb5a3cbef8bcc9ac72c42a354fa56d7ab152c7bfe122b8320cccb1363246350c88e9941b668aae649f66b3e686e4b02215b3cd4ff7109cd91850d617e5b2209414252e3bc1638bc4c92f15551ac101d63026b77ce4b7a0c8ea3234500b3aa8a5770dedf61d93752e45cbdbdcd2c71adcc6452b668c257f790396be557f86df57d57f718c0db22fc4a2511b2a1adee4126033c449f6598b52122f888290de4a6b1c8379d22d1b2c68420b5ef43b82d5cfe4d0566080010a7856235697939b3a27ccf139594705107be6f7697919b9a99621e7680e990cbb65590f4ac8ad683739c8ed27c0fe4ca011e8a981a84ee8f2160e4e0781ad8c6130fe6e978777a5808fd8b1dc5c3e4632ff2bb4ee600375a0afa29cdaebaf74de2737a12738103e6f731444a91e0a83508e0d5fe7127d41c82259ab723fe8d68c1af39cec96a57917d3c84760051813d0f7003a36b4a39471d1a958957f7e4b5a4162fc2592b0cf699de98050327f87f2b54d078307ffd26137bc67fca320cf464e4c87ed24f353f87bf81ba0d3fd3236b8551e5fb730a0849d7b55451c1e751875b5c5c96c6a17fe55203a4158f75d4b6dd1a11b350109d1040ee60f486ee8eac7f9dd81b4d672e7f2621a5c636e70f98f1883c0e213c325329a590584c04255768c3f34959b186b9183fc1f8ebf9cc34219068c23886d5d70bea3370ae75375002505f3f7b737e31712a10c03f82dc81c8e512ba952056319f9de70d9fb03164fdfca37174d0b0006345810c9986270b2ab29859f2cd7a785c9a6de4101948cbd55215c5e2e21cef59e5457b2dbc4635091448184fc8b7b71bc0eae6ce67d7e793a58d1e041197b624fd1141dc347b2e2a03498ee76b7eb789aeefad5e01103ce5791793540b7f5479c6d5b99a13803380bebf8824fe9bd774f1ee90623981a2239067809a919bdcfae4137a6149803194774ecadf164fbfbd8d977f87e8393c043ff6474a989b63c6355624b692b9f4cb3ad132e02b052acca4a95af452e2f8309720455683cd283e4b028f608e944f52d47be01cb693b943b42f67d3b1c302845538b811067e7c3585c38c035516c5270050b7a2d81e0a7c6243585012ed4c159626f1c608e51611d0d8bab06a2f1c7062455246ce48fa554f26bde2af8648b68fb48741e87f60018eaee12a28b0d5b5aa9e4319243a3e600e5c34500652b8b05d133fa6716c681c79aedf8c93b4dd775375d65c63b0ec16361eeffca9fb93cc0a15dd20aa33add6a0e6044993b5e5c29127193cf3b0354547f53fb30a172b601808f3fbddae17d718abf258702a2c3044f3b103cebe427878d990c687a78056eaf8b2c50c4369359b62a4487286421ca244b6700f9296ce61135ace648d82164b7ca105b43773120e8fd75005935d797b5d4a08a354a5f543453a55383153a35fc57afaa859c4c3d1eb7db5ea14a47af26b25e75413238b6701e838c5e25db4ca5e4e099a549637af72061c843412e6be1da1b2c3c801d2a13e7bf6a2d2e412072a4f801095f7bce61d6238f9f80a6a946aa4a665b5f33e21d92341e1020bfc05c63cef1848c4f484c9d5473a54852315f029c2ccd91db5d7e6a275719c8da05f3ae430607fa50c7bbe66806e36ab0f6287c88aa3dcbae4a25524baf893c64e054e50816704c112d940a4ddf5d00d62fc76288455289e559c44ad55b32aa76c905fcae24ddf503801198ac3386243069ceb3cc6c745766bf14445a3018669a005f73f56d4a49feaad21db69f93abd9974d6dafcd4db389f2ee21a62624184d27a7e937208001480c4d5deac75e304697c1a150b8088d427b5ad6c367923b21c5a3d8a1c2c017e331edd9d92226d5f12a9c828bb9fa760298b9bd8d2320d8fbb5633699aaa186044c19de1f138e0c79d8a100a7eb76fd56c1d01891c561cc7597bbcff16f28ed27a7d9c585f43542c9f08ace66ba3ec8d688b962b2a1aa505fb2a3f2ffa0d9a97338ba46a35627be1431551929eab500ec3b260ea8e2cbb628d2e8b7688a0f9dc0822b9a232d99f03cbb411f9665edd895afc1b4bad1e34eee13d9abb9c8a7d58b9d48c863afa0d813586025cb42a21631f39d92ec402222dc64cdd84d4af47d6000b326b6a9517dab8b39f0c1feb063466a8a422e1fafa2b22b770e618c63ed30877c16604a9a63a326285b4238f7d89567d923039e27d9ac2f1c33162aee3a59e327e9533589425317c42cb55e3a073d7b1d6f3fc6aedbe7075679b2065a46ec910987d631d3c811df880caa814747c5bd46f2470dba8edca1db4ca44a7b064914f09f0f8147ae114bfc88d533e7549e0f7991ff03413c4fae9c94e304e26037170d36414ee73496819e8c6f49adf59c9726d0e65a25b3b31aa8a6e63e228d5c1b83e34bf99cf6f4e0652a9584d028515a2e7d3fd9fe4cb12781f1e2b5a14c6bcd43b190c851ad05fab27ea18a4eb0308cff4cdb6a1acdf413901f9d936f7658bdb2c9321583696577913562c54f2d3e775cba7177b22f802aeb4523033c6f97b45a55e58f5072f996235121aa0e2791f5f40c5e6c15dd192492c8b54a160c0672e739307b837cb8ab73121a3bf5921f6df57927707baadde4084f170d89a85f85357c56381b7b8a8a25730a75a3bf56cb618c341a41076d42503dc0fb07a568da281b060945e27685912cbc72bba989f0ea4f4b84e3099cca41945d25b4d5661abb46267c8ba36373d4122a6837ac37e1053183701fc46715876863af610ce00fc16d2307389df6a8ce411445ce1d3fe7c7f93b5ba20683516fa2af2ec3fcb9d90762353e423f450e060684d230b84c3efa1e1ea7f87ec67b08f2a342a455a5c5bd1e1971901f84c96fcae809669c958c6d09c413358fecd679f28a700071af0fd00d83265714843f87890f79c7e42a1377928ed3ca1577a190bd4da45e1b5d9c00903e49619f801800a508986c651b6f0d42dd4cbfb75c4d33d0122e715f64f6a832688f07b430cbcd000a42dfd2425800a6966b79ba4b1f130b788221fd7dbc71db4df7304426f47e3d4b831cb1cc5a1779aec1114ee8a53fee04031a62d8a895655cc394d87e21704c092ee4325b488c24a6d60cf927c608f161fc13e6a1c796bdd148e6de1fff16ce1974e6c1028224a4fdcf63f30ef0b1651380948c96b836490570f765cf80d614a41389359035d44ec0acca9971d0ef00d60bccbfd5443e1bb9064bd500f715d46f7e8323cd633c5b763a5ee867127a017c9c4398de46d4938c0025c0b602232882e7d6f483ae65d6dd5240030a5824cbb50ce2a1541ec1d33546d16b4af597377d052f40b6f4e6c582fef7e8e53226467755594451ff58805c26929788634f484502024a5abd6476ef46104dcc8d1bc82b5e3225331c420471c377839e1086400e1839e388f476617ad110e830ebacab5d21e56b5be2e0b3e9dbafe49ed283bbeb30fb00dc31b0296200436e9359621d015c5152cf1fcad5b9bcb9706095a559bdb83df2db5a52a6e65be0b416d8ad02bb1b09093fb57eed467850a61a7822fcb0b078644e8aee64f9ab3e79ecbfc19eff71fa83d2acd94d423224c3a132a876c134aa710ab52e8b4209d509efa1f3250b75757f533074431e594a3b0e23c651d75d9b13d5465d0b9d00ca95445b1f34a5322e48828e40e1854552a50fe69bc92bf3c2eea4d07997e1417bcf12d0ede228ab494b46ad960bd600ebf75fee6efa74abcd1af58ffd53f977d70d832a1a73a433fa5fc3f1940276baebeadc51c8728cd4f68b56356e3c5a7b7977888b42f092dc76864f901ec0cfd0980ed77050fbc5229d1ee16b534f9d0821cc7fdb82b69c8685512bd1bc6217ff42546781de01ac44d43ff4f0c92e842d92f694f17b97a886495962ec89b0ce4a4cba436b69a5b15c5e492bb9cc2f20423578a61ec4e400d1830c2879aa8eecac86b7fb1c03a4915b679226afe7aa3fd4d5ef90124438ed34e2bda671a2fb871d5f52f560a8a5614f4ad3e88ae0c2118ba0a7ef094a8f4d11d0ceb4664770691b7a4578134ff7ce047b2b081a5ebf39c3a6d90e8cf59c0d1f8710af0723e6356e559609e1e6f82adbaddb7d991c146823ffbcd48f062c98d29772b8c8892fbad70fa3f5c484948b9d288ef9904e4d353421ceb2cf7eadf1dca232bf19270b25a60a8dbf568552c7eaa778d91a473444e6ede05a3f33b30472785927368225c5e50850ceba9de58af73521de51c8a8bf36a2ab99e24a09f9be7e140727bad82e50b965326361e49909a1f73b5875019d73db6f579a2e1c818233e186540c573a220889188c79b17573279ddd4311df743e591af648934dd5825c65b43d1be2298b93de6488ddd0c0ba9b4b67ca8259db49742aeac19405041f8491724dfb955a6cf9dafb388eb172ea0db142f6db423cd01ae5932005eeb4ef06eb6a918e31d06db4acfb91f8cf32d78cbcc33982761778e074264f323d30bfb2cf4f87fc816544426bf1fa8e601a559243910e5958981d906b79416a0b204202c8f639890e50c54ecf06089a825eac2ad7095b97a052aef32380952126368def568d0f42a7b7b727c33c46c039ef219a796f26cc845a8f7884639a2023dcde7825b326a23fc21dc8b11b9a411dadefcdd82c3ac1c89775c0f79a6d0cf9436afc1b2e34a764484536c59474092f35827a186d17f66cd27c136919689b53437321bd1991412155b493eae55817a8b0dfb63798160e322db82db9e1a71b44812ad2d3c828f9d8419f9a105ca7f83ff653366103c8d2b9ec56c08f18ee64aa5099d9840b677bd9aa402fe39a2e1648e5fca9a0116708ebc15bb018b6e4fb98f56c89c499d3da4a19fcdf747184d21dbc86534834779f02d2af386d6d469f25010c50e943dd8d225da9d5001f58415e9299984e533820c734a3c28d6c42036685acd689f0120acc457625864e5b5bd0c10eb02568bf477febe3e40251159701d404062786262aba2b7c8ecd0a5b46c40800c10779d887ec64aa488bdf02e429fd3aebc425fbc2276d42adc331fdaa02b211f8667d60db09916c6331764fcce652fa4fbd160c829d4007cf8ee1cabcaa0659d8124db0f5134db87267c5bf6cdd1a12355f6aca267dea715ac34077675bf4ffa1cef2d2cd1bac4dce410dd30bdb3cde935e1baa2f1c4630422cd82cd5180151598a03249ab7a16c805b2214cc050d801adb50d0abd9ace9417522b0da70da15de037cde06791a04bc70b6a58817aadabc100752ee738d37ace0c4766d470deb80eba6643a2beec2a73a53df7cf52e921f73befe00dcc1914021bcb4194193c37d60803633a4745f3affd70e35d84a05d76836dd18b827c3ae30884f5c1c432d744aec0eb13b9fa4ecdc8e42d1cfa3fb75258d7d10680425b098a52107a40bbe2a208a99edca09f8380eb5548e09534800c66a6c85b8ba724a6618fdab1f4b322b5412e3b59bedd09253abf2c278e5bf1f93b832e7db2056983a1e95b3f11ae9f25c45b6fd5c15e97b4f76aad15f06f39595aecd139f4160371cd5c19e12538e17e6b403bb44f4c4af689ebdb544c133c68f04c00426e8e7e3628a6d8f06760fb4b4d7057ca99c62194e7fb338ca0d21b6669aaef6ce86567ed7b31a9cd98fbafeb2ab1d29c21a96d3ee94fb7bb7ec9af9bae59844bc022b3d750b0448134d88b91a50858eabd136ffe9127f5a16bad38d8fe52222970fb8981be0f49c57e30ac889bda119a0f62195c6e2fef82f3e804f7897572d8c0ff09455bc6bb4b70f2db7f10427e17c67ea3bf960b412cbb41d81ddabde94f0caf7aa70f2f4e642008c3dfd9eda8443a692fb160d30860aa817aa27be288b88309ac0fa6203b3c580ae4dc12645adc32a5c0dc0301909a9734542e42c94ddf8ddd34d1d200273be31d2b99150a0a990d66bc1b4b125bf7803cfbcb77ab7b4c91464b4483ba009644d9bad063453021e5805e8ef30bb6be50cf3e1ae18127c96a56cebf8f176f8342a06e1ae2ffaa235bac5289354c9d7b3750c3ce5a353d7e20997e04d9180b0be50a921e12beb6e04b3f71489f323d99ccf3de4f621ff4a4d30e8c20e174ff65df7d97a1a456548c92e9b94eb937ac759b9bbe7aa3e2077f948ebb9ec129c24325add580fabf983d559746d28e92da88365e9bb1670fad1621affabb5f9743ea790a62837b2edae8f5ed3c1104d9a72f7b363ea66509a2f68dfc9dfbb56dae06dbdfba92d121402003986fed280774700ff1e4ed8bccdcf2276c401b8ea36b0c572a8cfabd5702e3c7e21d62f1f0ae3a7753d8fe668576a6bacd06b0d17e755f06c1bbe94938fbf1b22f20a4690ea8a38b31c0c4109596d6db6875c0c5aea62150c28aeb3e791e4f7a09478b733832e80a452821502e5ef64ce06a45fa76e7c3b2439b282710baa91917fdd6079e6863eb4ac04cad80e04277aab247e9535756cf0ddbd8578fd1dc7f6dd1db5e26503bdfc92046afa4cf0a0522bef3558b7a08196ff27c982c8f56bc0ca63b2a8b833776096ae46ef622d08da6137ca3aa4f15d0e3c809363dbbb2410788701d93627ec13b02035eaa81cc54871850e8b78b9e66de5838c16482482d4521220646af7341fea11afc9984cc8ce8c33654496f0c0bb25483b0ab4381ef12a4de6add7e4b03721326e8d206c37455e0ec3012842bb99c7fa81c4344910136041e4e3b27420adabe875641e4c6e1d1ac97b0cba8e90209776ef61eea2693d9aef4f20cea412124701652d9c2c58d6dd687d05f62f0f1b25f3878a9066097fa24c2053affb9346904a04bc70939775c008b2a789e83b7dfc09529d9629d35db51d4297a7be7e0dd5dcb97175feb42b73091a6dcd54dd7b839f8e1842d830294c483c99b83177c1ae874d259f363fa6e9c925dabc8705a2e54ce54b3235e7cc214924f19de2df278722c20e9a655d59cdbb5fb2afc63ef727654580a8d234c1c190f1241d2bc3627f5de463d951818501031778a3c22fd414539a500fcaaabcc142dff0fa4e915a1ebe47d067655f31e41fe4fad752299d1a47376b9bb4736619d715f44fe4f45bd24d23c32e226122f7800b3aeca40a49f510f9fffa774d99583d217b54c8b43e6ed414b1660df3219fae2219ea13506550a2808b4748dd77340cdab1af972199c8636a909df6cd779c8b2ba13bb9be5570f2a9181745abb7860489de64b52cbd47ab9ee751ef4c2935553664c3bdb790948ef5bd8175c742df56eec52c2a3f6bf14d46561d1beafba55bea040b9c18b124e8daa7024e711cc2e98e34a41a8d3a37089b2c55ec7654ae5a92b725beb408c477b7e51f2ee0e20bb6031827752d3967c02ecbfc12bb636b9d58aceb6db88ed1f329448594b6b51d8fe9e3849fdf3feedad93a43753486b700b0f3068580a13cf69a1df1b82416c9b97b98679d2c98f7fdff3cbb868cf6628413da24231799bc78025799be6419c2cac6683017324c8541474dc61515f131f35740b7b944feea4005a2b3acac92d229de764cc39fa9e0e0b3feecac61c2700dfa6f579040b64708d321678d8679aff79ac95b23919213119dcf6e440825a17199419052faeb46b2bdfc4f0d4f427e3301367e5ead6077780f2309f61fbf3afc7a53c670cf257f5cc177d9a6b1e0a6145ab34d8c253d467014060c887e3974ac0789b46f45cc3f3858379b4547641073cd96674e50675174d7f68e16313aa8bc4dc8c54f6096a1ea604273d42574b48eed31c076fccf4a2f05b831678e0dc69aee6e9d7424f9ad1442bd6e67c9ab8f2b3a88bbb682950a5ba056ae724eaaa19ae8240144f2c27253d079848d562322504483b6930d97e5c97998921a41dedecce411b5c704b367683237e4b7aa0ca1ef3b1794e79f593c6f07d5646dab9a98dd1c06d22ebc4de5fd7426d3bd271e9038f27abf7c1872fdd1f3816f01eb7e68eef7da2c4ac591b2402e885e4e1b91c32d3fe7db1502583b0220f7aa73ebb566b56d37b116b3feb6c51450b046d52e4ad540d34b3e7816b96047f55c163bc4a928c17543ba3f68f0a29c8bb01bd5491b949a580810558aed5247994ae55723ac3c584e892c4bdb75cdb50a4c9ff2ac32d0684dbd6c5b8ae29d15203e8bf497eabfef4076565821ec525c4278ccc9b30e483d09eec06229f55481787d0a01815f76805eed433cf8eda44f68245f99434cbcb3c59954344eecb1dde8e753340a29ce9797bc00d3a398432f33671ab68f4e83cae38881f00ce8bfdf0737f063456125fa734478c250ef40bc099b1cbf7b43d832fc3377a517c64dc8f7bf30a449fd4f343e81985f1a07d3ca513f97070ae38e382f63d29207eed3cfa9158c9a91b769fc28ea831237276204bddcce5f59f4617e85abc82f8ef31c9bb26bb22298c93cc42bfcb316daee3ce719cd77b8f5c95c06f002a20a22e3bc4549d9d631b005d4edb7deaf93e2654ce442eaae8fb39f991af9f6c72a9240c0977f2e963246c25749bfbe0acbe1c20786befbff15eff5e306b53a220ae2e533e93941b082446549fd1707ca27f611924b67c0bc7967a0fcb8519a3c19f874bb36691178121614700940ac9a74e45d6230e89149faae63cb4e1dcd8721b809b758e8d0f25efc536529f7c323df535989fe9a2b491c83773b5ad7b834b8d35ecfbd7266283742f9ba0422612f04e2c981d1b4c6523a5350487eab8c06b85e82d11d5840630aa0c82cac2dd4a991c0bc1a895ecd825424673efddb0be1648cd66aaf5fd9c5e40c8773306fc2ef9619e5025c9b5df41bc8f7d4af546292db9c9f291c346ccafcb17c3cfe5b4ca3481584901e881103f28956a9a1ab6b08d13100c4b52080b1cb1d655959c34109674a847932e83eeee195e756f669055ba47e3d877fcb35ffcfcb3df3f67267d6d01a94b0969db6f00d8f3b06f1a250ac2c808e1a3717135673027aa080177764a95f1d9820779e58cb4da31e92eb958cc81e710198a9e9f1528f3ad096115cd8f55d0423caca09f7c27a63b488c199894fccc013b4a3f0b4771238fc44e68590e3667dc39eaec7b38671c9c7208d68b68d81edd2986c8a7b4d0233de3968ada2ff61edd49d374d73a17fd20412fda0e0dfb0e75ab1a6fa3095ee38116979c5025d7c8e42cf73eecec2546c14af509273adb530511f6cc1003c48808a1139b076ae9fb222bdbb9af4e2f0abad94985dfa725f08d45b3253fb11fdc174887921a646e9560256975f7168901111d9de5988adeeb3ad0846f1a15eecb2d383103cdb72c28bd7c065b9ed2a8ba9be83882fe48436bdadc9b8a86e51417c71301de1ed99e30761bf9c4ceaac432d17600925bf580fd72105db10be880a38d7f2b29a5297f1fc4bdee2c3f1a4ff4ce1fa861cb5c60b1ec856b93c68c3d7f0c560e26c88875d2d3bff0fe18a5c50b3453b7fec6790f3748374b66ea7c162d2219772bb242e5a904b14b6255e81e224ffb42e871cbd827b88489a847d70b6fbd78ec1e7c08e70388b8ea01787bf28108411f743c0c8d12b73686a7b167d2365e22c24f40e2d65c6e964a521649b3c77efaebf9a14c6c3fd2e6316ab718bcba6c1ee197928fdc229f8a31dd729cd54adb95d8daf317b0390474efc74d7afb03ed65288aa522c1b8fc19c30efd7917b2fef4384642a648d2ce5cdc8376c8e002f775f4f3c639d8d9b889f0ee29de35d15282a96bb002fa62636f05161bad1b65d107a44e6f2dd1837372cd6754f25e4f01d7b47ce2f75890250c7aee2c091bf1987eedfb6dcb8fa1a8c00aa5d81f8ee641e702fd9e26c16774bee67b1392e9a3f2fbc7d4007d14da9f2bd6088c5c35568f0be16c314519472b59d070d196bc12620706f9dc46d9b47061ae627da3bd3ec9e1ea6de95e57a503f2ee9eda5b354c2fe4795c66aa4c7e5d3d775b69eb6a03227004d29f1f3058c665fd3bcc8d8687e95083230cef45e2c1e5ceffcbfa8c8ad38b5cc35104086f3a411eb052beeaa613e109a74ecb366223592a58ea02368b67648877cd09e83f62a56dbcac11a00a90f6a101a36a36b873219aabbc3706b6ebb1d4f4dad594de6c3290ddb30d01018d910e692ac3bfb03b0d90ee472b63895580cc05edca70d6ec1707875daadce8fb1dd759dd9cfbb7a98b9762df815b609facc6f5e41f4068dbc4cb80a4b3809d0cdf14bc4d94087575990069190e79c03ffc387eca7976e81d5877bf635da5d5be6874c6776fbffef1d255ce0490c419ca47694b534230c401380c5e3a1384920893f57882c2dcaa89673bd2335ecd86f9e74e67f00cb2017f0b450b7918acbdd0eaf3af69b16042736bae8ecf591e76de9a784cda7997c00a0bf61f93c4d037a488839c70902f110e4aba4701bda173eaa8844cb2084c3b6e1a1e0a94c29d26d20e66d233ace66e58042aa69b2754f617caa2401639659adf65d61b1fbed5c6d0c7dbf2a2261e4a715be1e7b64ee3775022e8b2d226118d4b3bee40e0e0fd33896ce0d9384ab0e22f7a1ba6ae467343ae281ad9bd384ba7e7c97c9586128e22691243445ffbe9fa0851a5a3e6f731795e5373afad96ef94d9ea565bb48fce853f40e82da66ba4d253dccbe9965cf05ff86f002e8120cb461993fca9bbfb43d6e8789b614502623d9caf371947f4307a7060101fa71fe4bc80c893ed7b194cf499b92979de0066fdbbe5123419b290795c74a3ed6603c156a8b02e9af0ab3769aec6958b9d7d84533a28c2915010470218ac679e874d19e690ab05d16bee3316dfee717d35eaccc92cd09907499d9b340bfa6d4557ef5a71766320778b9cc982dd080c9f9a5be1c496813a3ab7f468d80aec23933cbe6d4282c89c9b8e6df208d78a0a1400e0664291783c5a32f6b662d967744c68b6580d4993d1a9ab470037d2dc9aff5dff15ceb572e797629a0306a6cc7f8c08cbcddd8d2f4c81c192170dffa0d189e97541b20bc7c5a5a0cd070a8aa1a218d0def3fda61d382652af6d1bae174147b7e8861ddb2369a0840c0c67a9087820dbeefafe96fa188a2080acf2c70c4eb6bf99e853fa93adae45c8bdac3554507b9b5a9ac023c057376602b8be405b27a7962bf163c7971f40b4da961273803ff4a115d2b888a5ce7b11871e98bf00ded33f9d2004a62cad884069627cb9ab8d3bc9548286aba93fd38efe483585f412c280d2953e9ad0ba29e6ec2822f14209ff97cc43c2e2e2e6f6c609ee08716f6f89a2e627f1bd09599eb6fd464378f7af8934683c4a78ce14a1a5b963811d81f6928778f047cdfabfbb0a81497e00f682c85887132a0fb4e9b253a30adb69d7682f2795f50c496120a12e1fb15456a3f5a9da6c38bc8529dd7d9b2be23ad1f6069313006e6d4c998a0397d7fa9392e9a2fb92814ca62bf13c28706946b325788bdf4d34665813031cde4a2f20b36d0d5c5e2974f3bf363c00be7750edf9ca18faee7a84b82de02cfa47db24ed5be0c1146857470df00172e82ba16461622faf5b0382ef295915f94868a0cbf8310c5d2400f825f813776b719b9f3ca27655c14e56b0e9cbc7bddd929e56b880a7e66c443dc5c1f4a42b564806e7c8f5cd947a127069a862cfbfd9e84185d670341c7dcf78763e860a8b46a95d36d18655f6d13f1cc0fbc71b434afda4cdc4ad87a7134a65b5d1316e74feb1d9ba701d73e1c0d1046e0db71c1036f121d82875cde2b1eee4f51dc3b2ba1c1d8f63a27018b8b5e71755b8c396ef615096aa0067392f20f25806f40c321ca94a41ffb60f4dadacfd1d4dba8916d756327c3207bc870bb181d21bbc0f1bbf47df0bf2f34e6836981431eac3b82a16d76bbdb22122325805d32f44a8fb810a75493b582f8ff4ef27d047e0a23fd0cc6b915f7a50f0cab0b14e0c3039769abfef8a7e0645122152b2cebecf5f0807e603c39c3c26a5e18ab1702f1a8cb8576c9a8b6c2c58d555baf9f04f36e225adaeac15ab78837456ea44b785f0210a684331b118df62b17e804b6430b30399f216b0d29864c6062a82d84dc496d3ad2d871187c6dd0348c5c5da89f290b4dc736882535fda7e200bff079878632b78a9899755f53e1ef263a88e809a1e0b825624f8f4c7bc31071f25aaaa1093b3f55f1759d3f767a7b8d59bcef24b14025034c09088296be31d91e546b0c54a79e328fa9229a2a12ebde204f977141dbc20b2d9ed4f1c92acb808d1ea93bcd3c5e9ec8516e5b633f6bbfdf31ffeeec4809779a87b1ee19f392f82cc37979850331bfb90494222b364430813912d5cc6a0380b5e3d8dbc8eac08f8a95aa218bb28f7f5a0ffb10bfb34ee5add1bf5d59a45ec4a03abd181f68905f95bbabbb4c2b2ccc344af5632354145b96d6b9681e1dd3fb77cd4278e448e3697ba130b784f66f3a18bc24d6f922a31f67f145606f5af772097e13e9b7111de0695041840de24bc275699f0347b4982e08b04d026f23d02c165473a49d623f902e11378040e5b3d6ea2528b0d3d5949315216c1cd976a9a91548cf5cfbc94e752e72b7795fe7edb1d49734695c8144c2996b8cbcaaded87c78203f9ff3a7d6c6b4b784aecb708c54d1dbc3fed63bddd7631325514bbb36110973150290ea7ce40b7761fbcd47666ecf09aaa5d7e5d4ec86f93c28804d5c3c5a506eef7c701b44874ea73017387d70f867d8a270d5ed911e91837c4a52804435cbae8509d1ff08bd9db29b63e3ba9d435d8e2baceafdf28202e57bd5cb07f4c897f6f612bc6deb059c4d1ce42870a26ff5a0f775453aa940847552bfea0323a94ac5e2e5d4f30c26a452560c55f2ca9fbb02d5fe0b16f0c5fc2d0b19648106a7decfb7f60cfef0699c5447f9c337a90698c189b8c4338ec464c00b93c488f0e76f4ed1168ad32b4432d8afee85f0e97e30fa6e36b0b3784743c6f65503747362a49379c871ec2dcb80a4b2f68dfb8fdb193ec142f8dd634ff9efffdab1ede72552b63bddb5606dca66fc07d38e4051a05ed481dab9ab13b7d96c3cc872df0215e2daf6907200f8ae94b242a5d98c4bf92a50ae01e682d273a743b10735d5308f2b2da7402d4120a0baf21ee3dd5e658fec7fda21b1a559c0e625e56682e421bbb2fb6d5ad5fb9a764228fa88bec93be5f5c58aa8bd6609a84dfc221d654682226cf4853d3a05653697c591e3e2ea71e60edee124a0bc3c9f81dc09e7a90d8a3b479589764aee2592a9798c912ad9b1b7318a42b69ab6543d520c5a30aeba36723eb2bd7e77296e85d759d8652c88e9d5118f268addad9e6686118add0a64d3293aab04caa540ed0a98baf7a8e4dff0fee755169cca885de9288b1499d1dc7a45d5cfbef21f9251b0ebb9e16504919dd192ab4707c95452cc6b59ac447ddeaabc2e7801aa879badeff7177893d813e9dfddca53ef4cad8db703e28d1dda30c2ffb1b419a71b1d2022d2a502f8a6774ab191cdaf804221544620246952a15be0aa200b3728a9acfa0ac9827eaba05d1ef170072d7951044f0488d54aea2ca40dc0d5bec8e57d2b58745267362457236e3e23638159933c770359b120556dc25239d9eba82f375265f67e85278e816a93aeaed2e61696f74b1325a4f5067369d1dc086b005d114a2748b3cdfb3161568ebc33f17e8093f0affb3f7fd08815af0a6b0426b908d64607fc81d0c4ae5fcb56584ad535bce8d0da7e1fd9f54e5db24c17af186624312989c555c6846823f3e5959c143414a99ac584fe96d63b38b5903a0ab875ed4f019951148661348beb24e35d5863b266b2821be78ace129a658ce73e1a38920df9c087d080a551d3a7c5b637ce5d3b877f7022a05dd6b46a3941b15e5f5fab98e59538f7bc48f255400f095de18911147b26f512242b82ebb7940cc834576eea198e0f65ab2c4922b1c1d6d73693bc86c273bb71ffa21763c79683f2b5b6f691e60d8ba344bb63ffd2c8c651b0000f30dee6f5a74d8fee928812204c815427ea5376fc3c4b22f1c11a85514bf75fd9ba208a9af20ad1abbd3180f7c9207c924a6df203b8c6b2bda29fe8a7efd55c4a1fabefcd9d16bdaccec0f6f602540efa1b9e9c5fc77aec0801d81288473c43cb08989fddbf32501e759dcb72ed622207eb8deaa063e198cf4755db5cd59f70fd6b7950294f2ccd0dc3d2baed7e39f63a561423208195e87d31a4b061dd9f6841ecd8a277fb6fcd64615495e6af0f1efb1526048f2581f7b0a267ef352665ede5670fcdd98d6f331a2887818bdb5bb695c2eb31adc3bbc49bb2a64480588b5d6390da0a480ffb8b6d0fbbbb05119b39832006b4689666bab9f9c662ce021877ca019a3f4f85b5f1154fe172d2f2069a79038eea284729bc68f90fe6847608d6c3aa7d95c05894b81e1584b7919f4df0e14783a5e55e01b55a558b945aeb448d533a55a1b8b3b319970e2a2d6a741c66094fbb755e306c001d5256929e718999a08e1ab7dcc231e2e2927caa8416339b386d3556746095529c776a2bfbaa4de90684dd3f719be1e94aecd17f7326819629f44edc76e0457ad40fe97c350204fa884fa813e4a6f649def117c2be4c06f9df26d9d69f4672c825e473f6a84e26c204ff652e6d74ead69428a1c1790d1452f639d3e8b01f15a00981c863f4beadf8e03b9249ecc020f9c80e34285b9ab15113167c739b7563ad57372650f8e7e1c4cda384607d7dcd1ddf520c18c9485910550665362ebc928f647a94c1cad6a71965a4c017cd303aa794bb254205e19a7319ddc8c95f9419b561f7ed2fbde615c06819b50bb15d13f2c378d74e91df559ad81ae1e0d60c00cc03f108359664f7f859d5a30d0e566f01fe8de8d6d49ffbb898888086d5ad2b6947b6f29f79652cac80a850bf40a964a6b6dfd9d41d0aed56ee3b8099381519b00683e7cc8ee44cb94d3f2a769acf22b4d8ee3388ea31ca59e8abbd4d1eb41a5b970f3e8c9d1a8e7a7d5f1e238298d91a3dd765abb8d528e7b766ea3996e418a169ce818de2d77dc2bc78538fa06af479c4247e26dc31977ca498e93f24537ee357f1316b92d8c32c2eed19b61cc10be2a4bdff3df84c5982d3e1a6486388463a27c5184b5dca55adcefa763078f68c510ac8610e02a180c775443838915a23588b2086999d371c668be1c128211083e9a334d6f1a6eb9d18dce8cfb8db676555659ab942ea1cda3b90fe82db4394896d119c658e15311e1c639b528352d462dc68cda5ac3cda3ada4b4a374b335a31cd7719cf6bbe12df372e696ac6c6a91c56db64e4dcb322d6351aad19c9d522d9c915bc194a732cb68cd42fb53b5bc94544e6ece4d6dd5e8dc366edb4422f998493927a5d9a434d36496519ad14c4fe7a400086d9ec849cd49f6f8ba3266f32b6599cc7f3d46ca171f01eddacc59b680adb347de885bd4536e0867b90013462b306ddce7024c180a0410be528c0e74542f088a1313854feae869bf9a5665ad73ebb8cd4ed60fedf59a96639c5c980c4cf3885668a01ac02a201846a6548b47b4a2b4865216a419e37476cfcbc9e464f245ecf188556c958c9e3c1ef5db1a328f47bdb5dc8643fb01993635a9516dcba13d4407da66d7a2156f0a3d31bbbca419cd92db2c3dabd22c9b19cd364a9fd07ee39c74679bad99d428ed414e0f08bd9459949282e1d6c757cc14bef83be58673a29eda6518731766e76c8f193de7e30c6398f8e2e5e9d5661d421f6766d159298dda66b58cce99f5c07940e8b3df897fd8b419d61edc18274061c6e4136885427ddcf5da0f35dcf4104d4a272e8e37a313247e0994f0049e38d133c0101c2f04017ec4d131af97f171221466eecd290a43af9dd6bc61263ccd09a19cef095fd41127e25c5169c228d6214563a8142ec6d2eb51af1d6721d943d0e1e0f7a00911bd02600f48a7b7b072386f20aa7dd5b2d7ac76dcdcb20a8489f92138777a3ca2153c221478ccfcb0a1ad357a0b6de8e1486d509c98695ab555cbe6f7c6eab8b9d95b9969cfb6d95911e3467560cdcf001f3f6699649265cf3c9d659565332944db67b9b26ec765676d9994b6ca5aabdcbc0974f1e8496088951007de31ce39f08e1f69cc8e3e4688a28ba0ba0271220743c020450d25384394243bf0a727802112883bf08f59045dc320f53b35dc80eb097a2173889d191637e609df766dd3340f5c1ffb8a62a0f0b1767c64af1740dc3162032e5dc320578ba1c2a71d88edb6fb109dbebf9ad783ed310622282145df0e48a7b9b07b05b2bd7b3dad5d67e50d432e66e7cebab59317a2ef6be6b84cdb58b67695b3db76ab01d9aad443acb4466e7cdd18287c1cc519d6b4c73081b9d0b95b59920bdd9ab7c8b244d49b38e4d1b12c17aa211dcafa11f27e74dfc22df516ddfe561c03e50b127a86639ef0713da2159a88ebef5c0e22baa8fbc2500e79bf1be67290ee99c7a3fbf6e8edd0b11012c82e7098b80f418743bf43b7ef41d33ab20b215452c6400425a48c81084ae0d0d0d438efa98374b71a08cd59f969515c51f7db65cec397bbcf3c20d9b9700fd137dca2d31865847eb328dc5edef752d31d0e390f7b1e1743e766a4214fe370d6a1de0fbaef2b8ffb799cb96f61cc41b490d5c3104f6a52e8694923d2883cd2fab1a9c1f8b3008599a37f52e40d5944d254d6aa152299b124d4466e61f9c87537ee1c9051e87a79857823f4ba8228030a283e1b3d22b8eb6cef11a5d4d6723da2fe5aee7939517fd6da9097f31d67fbfb7d4f647af06d974f74fd26ba21fcd55b60d6399fd870ab2111411649fd5eb9d73b7a6dbdba5e2fa3cc18cbabe8f5120a190bbd5e6241de6879bd9442def8ebe516e28df77af9835f2f93983672bdfd72d41fceb9bfad2c939041413d73d3d1738553dcb6649984a4912e9034d588a4a1e28ea8a6a3d7914194650b224d7d28cb174423f22b7d224925de445d6da6ef966db8fef56e74a9bb9128d4594f52a14245d6cbc1a9d6fd4e755714baddbda19c32613588e66deacb619cb7e065e9824d1a99f2659944fde580a0e8a8bf4f4e915324956dc341d4863462a4ca200db471a36769c495e5112af16bc9d2084b9647be502661ad0fec48fb01492229aab9a4437db894a56e65d9822823060ca8cebb1f36ddd612f8d2cbc12ca6d605f1491ea130222eb44ebf2ca4908c4194512f939034f572ca141d65c88ce07a3a2d52be16cbe2944c6295a50ba4118b33b65b96262f475671799605db166c5dd80245a12f0cbe59064d989515c49b30e822f2869c1269bc9c2d9455a29793ba8ee9c2f6d8666c5f602ba3c4a7e9e803f4a3334f476a14f5724e9f5e8ee9b2c485a48b4d00389b17d866297b4ef0c923b287c7d4d2884c023c0cfbaf860657f382631623b31f65980c078bf1a22e815f8e7a24ab7c9fe8c789de928bafc59a33a05c20268c5ea607df0e9b96055a51f48e41f2490c924dd8c0e61829df9e4966126a639b30188f1e6f23e688c11ebf63daa079bc0f330663c6e5f5f808cc58cce32d3063311e3fc48cc978bc068a983199c70b9137f2e33d206fbc3cde087903e6f133622c7ca4a9df252c74fd66f188326a8dbcb1e330a20d1f2f62ecc513406170165d3369fb6bad7c27b7ac43b74d863c2c7584e86db46d579371bb611b6ac38823882011b940020a298ade65723efd1c3baeeb421ebe9dd4f7fb7dcebcefcf3da21e1d636ba5e4381d2aa5873b4e8674a80e6d21ee232c121d94a1efe5f0b5d65abb75dfb0deb687b20ebd307d7f6ff8dd93f9f7e8e5c85cc7bc243c12fd96b00d8f7823a31065ec9037241449e383da904d906812e5c88f28e60adf967794a31ec55cc7bcf4f6dc2b92260a51284c9541d20a85a9bf2243268a4b26627b11dfbd3158c81d9e3b9030752ee1881174ad130848705f08a304f998416f5ec85307b10a41898c83b65e78e5890309abbf73de20260c79de20d2d4cf11c81b369c398834f53224f8b6ef99045fdbf0dee21784c49ba86d78b31a7fc6ec72f859aa95e2f0a5e6bc1e501a87b77a42a28ceae5088932ea1774f78b313ed6f82b31f16dbf56cb6296c5f80a712f792a0172c36cc2b6db709bb02d3462c2ea331833144633f5959c8c34b405983c95489afacbe1c0c6501193a79238719699c1177d7eace8e83345121df568142e21c3678490a7e2cdc6e1735786cc1766818e62728c4c2586ac0f3e2ce28430c25ff7c48884c16e891226855460c2a5d01a50f8b4a1218551def7292e38450b6691592267f4bb22e153961a66758f5db0df124665a969602dd46fc6f7be8b328c5f134e65a967f25c426160708125f5cb72c2aa2cf50bcb6d41e1950b095aae2b855959ead93363af70de20c2ea49e0ba57e15696fa4513284da0fce61566c95287792ab1728574d245906fc8c22d596aaeb4956ca9749c655014d3eba3e96720bdc6298348af290d82df2a781b4619323de17d816f0bbb70206992489a7a1d33a68aef85270a63acf0c98b3c1e52c396788e9ae5e57cbf2cd8c5138531517cf2f74545df9999a4d68daa97475cd151ac4822f286bcd2243a9137249448531f65949964a79258e1a289ae975096a0ebc8f529d0d032c51a583a12b4423afa00a940b35050f47de99ed0170627047d61d607532cd1370616651925be4e471fa025b4e6e948bd7aa63af572529f5e0eead2cb393d7a3923bb71ddc51e0e4d11c8c032a0161daca1518345b527caa89741e29b4b609288f28c01c217ba9cf9b4e82498cc9dddaf0cce66ec6add37c9eaec153db344210fdbdb75ac1f5c97b70c26540ab562ad5a2c2dd75d39cc2f97d70b8c179818303132313334333539d4cca031a346ac868d0e3637376e70ec8023878e1c383ce0ecc8d9d1c3478f1f02f8e1c30f3e0c00c800821022081f7c08912d5010d94e01225b2a40b20d1a40b6552890ad952cfb461f48024d27132a855ab1562d9696ebae1ce697cbeb05c60b4c0c98189998199a999a1c6a66d098512356c346079b9b1b373876c09143470e1c1e7076e4ece8e1a3c70f01fcf0e1071f42fa6a9af68d3e90049a4e26540ab562ad5a2c2dd75d39cc2f97d70b8c179818303132313334333539d4cca031a346ac868d0e3637376e70ec8023878e1c383ce0ecc8d9d1c3478f1f02f8e1c30f3e00fdfc90ad131fb27dd243b65004906d941fd94a9940b63e59f68d3e90049a4e26540ab562ad5a2c2dd75d39cc2f97d70b8c179818303132313334333539d4cca031a346ac868d0e3637376e70ec8023878e1c383ce0ecc8d9d1c3470f4f5f4dd3bed1079240d3c9844aa156ac558ba5e5ba2b87f9e5f27a81f1021303264626668666a626879a193466d488d5b0d1c1e6e6c60d8e1d70e4d0910387079c1d393b7af8e8e1a449134def235b243db24dc2235b2539d92ed9912d130964db44967da30f2481a693099542ad58ab164bcb75570ef3cbe5f502e30526064c8c4ccc0ccd4c4d0e353368cca811ab61a383cdcd8d1b1c3be0c8a123070e0f38585f4dd3bed1079240d3c9844aa156ac558ba5e5ba2b87f9e5f27a81f1021303264626668666a626879a193466d488d5b0d1c1e6e6c60d8e1d70e4d0910387071c8bc41ee121d72b38d9f6e86c89e8c816891cd9168940b646b2ec1b7d2009349d4ca8146ac55ab5585aaebb72985f2eaf17182f3031606264626668666a72a8994163468d580d1b1d6c6e6edce0d801c7d557d334d3c9844aa156ac558ba5e5ba2b87f9e5f27a81f1021303264626668666a626879a193466d488d5b0d1c1e6e6c60d8e1d705ce162875c8170e43a2500b952b9916bd04dae552090ab952c339d4ca8146ac55ab5585aaebb72985f2eaf17182f3031606264626668666a72a8994163468d580d1b1d6c3a7d354dfb461f48024d27132a855ab1562d9696ebae1ce697cbeb05c60b4c0c98189998199a999a1c6a66d098512356c346071ba09f1f4daf43ae4e6c727d62235728b15ca3d4c855ca0372f5f9461f48024d27132a855ab1562d9696ebae1ce697cbeb05c60b4c0c98189998199a999a1c6a66d098c1994e26540ab562ad5a2c2dd75d39cc2f97d70b8c179818303132313334333539d4cca031a33aa94d68e48a6446ae490090ab921c725d52932b1307e4da44967da30f2481a693099542ad58ab164bcb75570ef3cbe5f502e30526064c8c4ccc0ccdcca6afa669a693099542ad58ab164bcb75570ef3cbe5f502e30526064c8c4ccc0ccd4c45528fd4239a9e266b576672ed91912b11995c9188c9b548037235623a995029d48ab56ab1b45c77e530bf5c5e2f305e6062c0587d354dfb461f48024d27132a855ab1562d9696ebae1ce697cbeb05c60b4c0c982b5c70a1e963640d08266b536059a302236b412f59abc280ac59c9b26ff48124d07432a152a8156bd56269b9eeca617eb9bcea37fa4012683a995029d48ab56ab1b45c77e530bf5c5e403f2e5973f2cada9317598312662d4ace9a940564cd27cb4c27132a855ab1562d9696ebaeab69da37fa4012683a995029d48ab56ab1b45c773969d24443e2ca5a9296ac2961c9da9256d69828206b4d64d937fa4012683a995029d48ab5cabed1079240d3c9844aa156ac9586443ba21dd1f4ac9c5d5965ad47953522a9ac2181ca5a910464cd48965d4dd3bed1079240d3c974850b2e322053cea69472468594b3203067551090332b59f68d3e4dd3bed107f49333275fce9e8872062594b3285ecea41c20673e5976cdcbe19c34419225c994644b322613466f809c354161a81698e86db9d0f4356748268c6647268c4af1edcc88912c89782335a749a96d59966d9bbcdbc5d76e526e55ab75b3df3ace4eb9f5e8f82204a221424c494408a7940b52288e5a906ebd664c432dabd16620e2eccf0ff73a859393a354f6abfbf53ccff33c11ea3a26927993b05e7f99ac5e8fba3e507ca54d8787d42391089cdfc7dd2be5fdee95525ef9c9cecb893aeaebe588cee54e74974c58b5d65abb5dcede7bae095d3b8cbd9ca845dd4507d2f6fbe5c48c79afbf4dae93cefecc588efafa783f57c9b4215a42618e4c1ba2239789ae76c99249f5a53f16c852118553ec8fe808b56181a8e82a3a42edcf84dd28ba729b2622b340574abc895eb0a2398edbb6bb7ddb76ef76efbddb76efa3cc98fccd6ece19fd3ed15bb85b7afba51854fd7462ad7e3a9d4eabd36a754a653bc502752254b63f76ca84d5d00281f85aa0d249cf7a66acca177a6909933d81f85eef5ed053e286be16ec6516f8a84ffbfae89f093341d1a4548bd4ca768a677f2c906994a5deec14fb6381be1fd6c7f27d2d9b7595ec4ff6e58dc1aca7bbf2637d210f4b294512e39f227a8b9adc29a2273362d868501928151d2fad5079edd8fa6152669865a5fae9f1972513618204b48b2e7098107139060a9c39a93271971db6215128c47dbbf7de13c7711b66c9445a67b9f438ee75ba8ed9ca11c77e955f9baa958f384eeb5762aa5f3fa7fc92d15347cf1ee325295d732867b4e24dd42c39e2e0253a6a8d71d789ce12853cdc755db75d4ff3385546dd94bbaf72eaa395b5d6da4d75d36632dd9a54269589cb47bdbaf0cde33aef940f7b9deb94b898cb324a34c1e517c6a42cb52887973468f82c57825198fa0b62ae0b44d097b40457c2dc7d821e853ccff3501e17f2686cf15d1d7da88883e67e4d98ebc2135a85b7cc1a3da774eec354ac4173bf28ee9d97c36d96cb7fa53c4ef378485d3ae8d1d8828a2b34f7abc25c139a749247630b2acea0b9df9256a225592a952217da20d0298fc7d47f8157e5709b65719ce7b570c671c75e0eb7598f850452b9711ee642215128d455d1dba66b596b4df385055b0bf6da5e63905252b971872fdbb6eaf9107e5b666bad5ae6e530f178c8a825a192cd18cee49e34de9820dec87803347f26d0fc018a3730f8e20d8e322618e48d7803839b4a7dca1bd58b13cb296f78515f8aebe4017ef5a2969141d6d383836f3da9698e71f2451f2b51280faec4b44a95372895b24a9a5197d0dc94e8244dac42de983179e3eb622093f5f5643c588c021303eb81dd2364a954b6852bf393663945df7acd180d63ae90da98a099966d4400aa893a72b1d684dd30dc6ea822cdfc9eac5494315372cada59b1d656cd22b15a566badb53ef3ecb32cbba6691aa55956b56ab50c084a6e7ccdf975e1a35a46a595536652a35ca6ddbbc9aadd16d02c35a53636ea446f189d3234f84651c6fc94f8aa566badb6d63a7b4c1d81f0c9cff750a978a02317b63967cce60e2c0c466d6c35f5db75a32569ea378b8e3b20719c158a0bb57eab4a45b36b2a954af54ea5e2ee8c1e6ec91b8f34d7aa77f85b56e10e8a1e18257fb7cedb260c1f775dd71de71ceba1a697c38978b0da72a7ca30ee2e3bd5b76c8f6f459907abdb51acca5147adca52a3b24c0d0d224cd81f719cd5af9c1a2606bbca34660da9af8489e1db8f1165745df0606051c6946f5fd7bfe8ad9e0d63a2f84c79bb2aa7fe9954a66f4b95b8eda87cfa284b4d824dd8a9cad830a60956b8d0f29bbd22d3d1c70b26d0233ae7fc80a822071116f5bd4b601006f665de1d61db852ef497a5e6381c76d7416db8090144154b4498a86384b1bf20b65946892e5cd1f78457990813acef519b7ec47198289dcbacd1a32681d731319e54479f2a4a38c7de4d86682814ea640d6d10e89a09ab37793ca6169df0b66d291c338c55b8e255d4a028dbb61f247adb8c6a69de0835b3f4953e2d7cd93fe79cb3d3c2a5db763fef754cefb788be9ea7e19bbd67debdb6594a29a534ab1dadd5669bb576089877ef621926d55229a946e595d2daad6a34bbf55e8df531a3746b54669de5364aa564fdc8ae5dd3b2ccda70f36413d62d81b32c7cf4fbcb3e65a64996a5d67634cb6c4ec6c447bf37a9359ae3b6859b476aeb6551c6f472b228439e521b465ab23c229f4041c31528d0a277afb1c9a29006e17eaff480e07fcb98bbf7cdbdfbe532ecb5af6990fbf920dcbfed791c0af5e8429752f8e443efb40c83602fdcf71b6569aceb6f9e35bd29b795b55a314a8b091bce628ce223db708c3e566e7ce10953af6083a7e78c5ae893d6344d0bb709abf531168bcf3e3a410a3e241da3380312ad9dc313567378f2c53a61b4d78a832ffb84c30d8310a3e83ba3d0516a31587c5167b01e64c29a49c326081f4c66da885170e86134e24da471859e73c6b66b6a3a69d431afb7ec52aa88e8e883061ae878e98541b267fdd9c315a38c4c079541c26725abe28909a6e8193a3e39e2476b3e6440320625b741e4880d87c8111fce7d7722f8f138b7660dfa9b593107fa2eabe20c1cb6262c4cc51ca84c922f7bfdf6cc6ebdaddde2cb1eed10556f2107a8b6a756d79a0d417546a17043795b1d32031257946dd143f33e4e1d002498d0b1d1f5dfb7c7831edb68cbd24e8f6062fe7badd1307d9ddaf48d3236f86eac5a164517bde678510e82bfbd8b9c68abadbeb532d155577d370d89d6b4a66f970515d199cef4c5f48aa69aea1bc2a1bca70ebd8a9e7a6a32009141ca957a45dba02a7a3e5486227a3ef45ac2d2ebe1dd72797ee3b887a27ad1d4389c77dabc6f70e819468f87f719ee7afc2f13f97e04133a3b687b1db4dee8216eb4a8070e2db3eed10d3d3acafb905106becd33eaadfb766897ea9dd166fa50ae791bb183b541701f793fd8207ea8ba3ee405c1ddf37ed0743df682f821d3f59d17c40f34881fa6ae37a1423c42d74e43eaf5d0815090d01ea2a9a6e70ee43e742e874e73d5d63ed32c90b63a984152b411fa8aeab94c84d5dc3594c6af9ad33497698e6a6e6a8e08a9b92d3f1c6eeef21bcfc6c308cdfd867abb13ad834906263aea0868af87eedc2fcd60102e574b0b0b4babc562ad562a550aa350a793c9542a914820381a7ddfaedafb1565334604fe9557243a854226cf2b614cba17ecba11a7f1f77ddf475f48e4880f07f55148e48813cee9448e68e1984ee48810a7742247c070482772c40c0e782247dce07c3f8206cee85eb8ed33bcadbe97285d5f4f5533695929a3243ac1b9a510b20b9c510d427681f38531e620f7aa87792edcd711d03b027ab33d9e98c00a0f1cba86e11e423177bd85ac1e66106d33be9ddef4d5620dd51f51062eca604547118c01c92b2a201b61fbf9c871f1b1e372e4388ef3b82d9cdff6ecb7fbd6ae8771eee1715e163204c7e3c15dbb1089c384f6aa3d71e33d20ff9287c54c47bca19f88063149f8a68d9e3f9f7cbc8e496d643d2c98328f6d6a68a46e85931a194d53f1f4df13175c29736483e919db44a07dac40b25f7ace0c88618a8e3e62201206296170a2461fa17265eb21b2c5166ac86294182546f141a6061fbd94a9c1b7c52d6e78c26c67f8e8131b44644f768c4ba556ebf592913ee8888834d2d3d3d383c344fdbdb908a9ef0ff9fbee4478bf2177435c880b7161aeb7b9c7d4971b72435bd68c6f90fb2a7bc2cdfab1f5f4f4e8ed556b40b21e20b38703227bb670d773c06a7cb9a50ec249afc73d7743ee756aced69e4d0c576a99881791551f2db5ccb44c84d4dab32aa98c326ca5f264ffd0d91ed2034dbd1f9d06426735abd96d909a5d0b2fb369658b2dd410062434747cc2c4c8a6397de59d150c4434ab0b2daf694e679a1b585473fa56cdd2adda6ae9b4d266d6227165bc614da1e5afc61aeb6e3efa4cc182142266318429a46c51052b5041034e8c30f2379b4f68b9690a45cb571d3d1a5b4c61a2e1404b1a5b4c498196544b8fc6165344a0258d2daae042579106ceeb21a39441c748d375b5eb3a3a37d9755d174fa11d023def83332df28832e2e38f8e13568626516ac81320661326335a436eaa699a166ec0d399cc0f3efa3d040dd236344ec3700d201fe7a4f177e63db3d32ccb14201fa9f62054a335a2569fd5ec52fb90a38ba8b370039ea6a1119226a2200a1d234d0cd2b302f28610492313306d6c14081f3aa80d9b800923659435d346cd84913fe243c5121d7dbee00343479f2f2cd1d233c0109ccda7863c0286e0d850880e1650408108477a70843081011c449e84c006e108098196831e1c267b031b987a885b049d3d88165e2052d1d9b70eed427320ab2187a04686e041c1153406a8111d840a2047173a0b37e0692d01df8cd1ef22a4a6c7f9cbe2a3dfac78e2c89228b8218a295ac0891166d355d7304a9aeca587804df94f9bda1aae9454522c73d41246332aa5a6d51c69ea0c36fbfda5365bf38da228433e95fa9cb854ca20f9401d7dbe10037de7e3378d71df59cc7ee31b1b8d36c2e46dbe11268a30f2d325af85d9a63f24df75f401da42cbf0e0dba94f0da567047aa65a6688c38df3a4a3cf142a604841a7a30f156008f99078203a814f1554cc2b62ae00b53cb5498318a280346816a94214681015576459a6e91f99f4026c081850cc1543600d7f21ca1bf76e758b1ab61cf8f4f67b9b6f0c14b7d3aee8de6dbb9cc5f7de9b53bd9c7bab2365ec4f908e3a7a31244d85d9eb2d813b9167bbd0a341bce5223e1df2eee6c5f06092a63ea60ad0fba4628a1e15c424fc95be7b7f4d5ed7dd7befe96eddfd45e12d7357c7ec3a0f08f7ed33240a85ec0f136b8a22d41d39d26d9ba4eb64667f31c638077bb7db11eae5589b61cf7bc8e362a088ba0b12711cf77d36e788ee6dbf39dcf1b76dbbf6dabb1d91f7c3a0177597eda7f7ddd2f5becb1c07246f74afefa6cc18678f58241cdebe2990452269aad497fbb62ddcf7576aea85ec916d93e87a6b91849cb04cacb536d40410bc714b88ae284b0d7e346167f8ece53f3cc2f8b333903447244d1547ac47638b2aa8a0b9df0d57f184e63e8fc791aaa38f17a0e8fb7d3afa78c1097d51f866e9e408053a3261f51b5d44b2775e7a43db03da263982c4bb694371dcf7619ce262562bf72ee8eb8236d6a2efc31d1780f40e81a1272fb6b8648b8fdb930e5fce860146af9067e300a7ef0098bee39358e9510a02be8a3b4e497d472a31e83b56f977d4c2f57845f6c45adf92880d057c4b245cbea591d7b74ce245dc12c90222131d9d80f12d9bbc7c4b270cf8964f68be6594996f2945c6b7f491f99652c47ccb9f067c4b201adf92ca8c6f1904806f5925876f69a5e65b6ae1806fc9850edfb3c7e67b12b1f13d91887dcf2235bea791077ccf2476f89e48707ccf2401f89e4a6e7ccf2537df930904be67133c7ccf2638dfd389fe9e4f747c4f2839be6794ef29c5c7f794a2c7f7fce1f13d8172bee794d88eef49c58604be67d00fdfd38a0fdf538b1ebe271702f89e57623fbe698f8d097c5322427cd322417c5323407cd324800ce09b22a1408ce243cb2940017ea5b76545b2d49ab6655bb66d314a4e561feb0b6003f651025ccbd90b40ad644528a53e7c00a20033866f04a80d038c4e3f8406664c74fa226e849069e300a7a79b4e2f8bcc58e994747a99c48c81a70838659d5e2a519da64e8f3a4dc0e94f5da72da75266ac75059cbafc75fa17a7e1e965d08ce5d3059cc638853985c188bd30e094e674e6f4f3c88cc94032633231a70d38fd643263343ee3f4d3891903c0e9679319cbe1b4e609b5e1001d6c4e6d9c7e4a3163b1d31aa70f98b11d4e3f83660cc7e96795190bc08ddf40e0f4b467c678383d25326338a7a748cc983e3d2d32633a4e739c46e0f414c98cf938ed717aaa64c6789c9e2e99b19cd3532633b6e3f4b4096a4302a7a74d66ec87d3532733e6c3e9e99319ebe1f414ca8c09e0f434ca8cfd383d95326d4ce0f4548a191322881810a7a753660cc8e92995191bc029054e9f1120476d63aa20b313204b18b5e1c3a4339665198e1d70e4d0910387079c1d393b7af8e8f143003f7cf8c1870100194010420471354dfb461f48024da753043e5948a177e6930514594441c709f3c9828a16c18df3c63450d1231d7dacbc41476f099a7d7d8d55b220c128892c9bb07a1e6c5bf8c52df8a4410bec93450fd5649c686129e593c510b238a2f7f737d4d4c828a146260935324918a2a6660bceca109cc7f523d453e7722784085048431618639797be45c7dfa1d0795a74e8bbfb0e29f5101bc6200536cc799e959edf3b22f033dcf3afefd2bfef0b7da75027853aa8a73c80832674e10c2008eed449dfe0572d1629dc1d28c11bba70834824129dbe51ff482492eaf57ab1421d978fc680840812a8ebeca0be8fbe4ba7d3e93ba78cd8c10dac24813a08b27c9356ab55eaac5027f569a1008328608142a14a47859bf5f9edf2531886df2ddfa893e8a9542a15ee196eab640925b8c2057ca9d46ab5be3f0a75beda042454a10610045d0e86fb74d177eaa1cbe57a3112855b035243125770717129dd25dca256ce190441d65f843aac8fb22dc22005155a0fbf4b77b1b0b0bc98673d8a15258850fa9e0a37ebe1b7ebb9a5a5e5f417a1cee993eac0096d28c2f77da57fe1ce0fbfbfb3fc7f21fae9f3891b5c21a5543acf4a97be773ed74be13e3dfc66798b482412b5fe22d4695d14ee30dc320d5ff841e27bf1edfa4ba5d28b704b2bbc600431f8beef9324f0c1132b269369489226672801089ca05244c90b0445aae0a384eaf57a09498210729083954aa512e20220c4c00a69b55a79e04919a454014522913c00832ea2b8818742a13af082285d2801e8799e112b48810b80e00282a025c212182461e4e2e25297f4600c52bcbe53a3d1485362ca0c5ef0b3be5954df33954a7def8459198430c515d6f3b76bf55d9a738639dcd34a152734c93f7db748dfa252a9f4a904201894e0f4966f16d4b7492412b158ffc350e7ffc2dd126e790325582003cb7576585afe7dbb8e5faff388f4cb64327def84d7d9c967fdff633d8842142c6f85fbfbbf5b0fa954aa6ff03b843166b158dfd1393d3f0c75f259e17eb841c0440d70605ab55c670937cb59dfff6bb55a7dbb7cbf0885422d3f3de77c9e169d851ca147066af87576fed65de17e9df5edba8a44227d8fbec3172f5e9c4ea7efe87c6f69f929dcac707fc00d5674218556abf5bde3bace8eeb7f2bdcad9fbe595fa1503b8761c8f2ef2d2d2de769d12de13e85fb033d45ae10e5bfeb0ff7eaaaefd3499e771e91f69ef379543a7f7fdfd1799de52fa10ecbbf70abc2ed812648a1081a5c2e972bdcaa7fdfa4a34010fc2e7dbbfeb7fe3acb5958ced3a2593ad08436e0000ba87fdfac7b2e2e2edfa2ef1697eb3c2aedfa7ebdced3a25fdfd159bdf5975027dcf6086368811758d7d9617da783a3d1e8dbf4cdd2d2721e956ef9def1aeb3a3faeaadb75ae769d12dcd0a276401e8749d9dd35927851bfceb9b7497542af58dbf5b2c2ce7516996efd5ea3c2d7af51d1dd455f7421dd557e17e853bcb02164ee003d68a749d1dd24f6785dbfbeafbf5d19ce711e9c96ab55adf5157a954aa8985921f2c4ea713e9a7708feef2bd7aaa542a7dbff856b158e75169d637ea3b3ae0bfbf843a2ee19e4986f00429241289146e97a3be539f2291e83bfc3ea954aaef9d97ebec7807ff7ddf795af417e3704412a2b05f2f994ca6effc4d3a9dcea3d2271004bfa333baf79750c73b088736b0e088176a7511c6f8fbdf1f89741e95267def94aeb3e3f2d1bd7bde795ab417022568c84213567f3d156ed1c1efd44de1dee140e7e9d079443af4edfaf6bec301aabfeff084f4771e95febe47a3f3b4e891cb4ba18ecb47e106c32da4081661d0e2f53acf4abf525ffd35c20178b9b8b89ca745bb74800a2b2ae0c16ab54a7d650a8542a15068f33285db8823dc208638a452a9d40b1a16066d78428bb0668910def004d453592412894299d5bc411452b004d16111265732091518410425d70b05822735d0c211fcd4f7e82d2693e945a4b4297c844991e8a8af421dd4a7077ed2a0042d989efa0e9da5b5bace4ee9a2a350a8f3b46854075a10871228994f7d836fa544dfd1c12f7d15eaa4c2ad5d014a0ed2008abefa1e9d8542a1506129759d1dd3f14b2f95ced3a24be15e859b52610a22538caeb3333af850b8bba3be55a552e945a47429fc220ce3f3b468fc1d9d79d353a18ee938dca87087c00a5c38820e4010fcde095d6727f4d1c170732f7d9ff0f70e789d1dd1e74d3799ced3a24d1f000209d87085d168f4bd53431f7d9330c62f22a571b8ed39cfd3a2a7e860a823fa0cf728dcf6045f38410b7428749e950e7def68d7d9a9d71eda5f1661125f67a71389ced3a245e10e853b4b62491547f4f6422288e0404acfebd038f4680e6c7a9e081d7ba5a74717b1e9f922527a8631c2e4f74e769dfa1dedd9f70e8fd5f53b3c265dcfb3dae1e974f71d1e92eeced3a2bbefe874dfbe83439deedc75b86f2fa2ce2ce3af946abd640e1ddca8e3bcf2e71b5d1f2b49d027cc26f8186189119ab0d2038a854fea2dd2540473e34b6a1d20f3f23f58d9a3c613f64d6a29655cf0451f2b4e68798fce2237be76cd9c73ce99852529c99065d88a0c196aee174425a4a1868f0e4183b44022cc8864419911265f9d73ce39ed36f3376b6b8cb0929c97303d674c1abe999ab01d1386fe567c74c3f1c6472b818dcf0cf790cfe24dbce93e4f332dde789faff1262442dd7c9fefe2cde80624953e1f8a37a71b796308506b37fd9a72b6860f752a91c0d1270a79f876dc66ab954c5ad133b6994c9ff166bbe934de70373d8b37dd4dd7e2cdbde935dee09b6ee38d77d3b77853bae95cbc09ddf42ede886ebe9b8ee3cde8a67bf106bce9a17843bae9a278a3ddf44fdec86e329532099445f4fc284ba1e745bb027a1efbd0f397899eefb2167a7efbd1f3d649123db78ca2850002e80b1126ea3b473afa0059a1b35fd985b611da24371788620576b0b78c0d12ebe8e5ecaf24b3032851bb94524aa96956d3e88f8ea752e8781aa4239da223d08435e184922534097a8422418b7071a58a15a0293e523c81e24413254b8e4c18922257aa589942c5470a28519c68c2048991a80595024cd84f149b00c8b4e2e317691046c1bd77c618638cf2f69b599685f3dbc4818ee4b4709369c1a763c2c01014869e982deed4318a32e6e39c35dfb7e957cc2eedf14d985445199f8ea4322df83eda8515229a1e3c818f8f3fe56bca13bc919a07780df53bc14fa9994ca720a683d761ca3a5060b8c19f4ca69f4e5253d32fc5a8a34c2695eaa9d42965ca44a454a6eb982ad353275318a3cc29dce0b36bca41c0fb61e9f1000f9e9a320551a79f72d4d20b4519f2a75fea81f1069fe973f41bca1a0ff0bb8e796fcde04719fc6bc6c0832129343dab07f0f4604855f7504f1dccaa704b0dfe9453394619a7a3b229ef21da0462a185a637614145db83a483997b6bc642a1343dfbefa70784de14eed041d44f596a530e02c6509707b38ed788745428c19fc08c7fca2cd2eba38e9e29f4d24f79977e6fcaac1eecc183619052c822853c8668117e3d3ebe059f7d454560b8bb8744a2fccaadbc05c137c8165a1f3b6a68cc21a9d9bde10c47f4f6499f59ad93f1c1177b241124e40da9553afa5ca183efa359035ef420df65786ff47e5979fe4a6fe6a8bd20bd9d35c36db656f84a2ccf8084de2eb9d0a44f2fa7f5994ff7f236dde38efaf4806c97e1f680903ec33d445fefc7c17b199ca9cc6a3d6ad604f326ddbb9c390878d54399d53aebdb3bcb4379b31c7599593d905842562be43144a7ceea8175d559575d75d2a36e61e55410552893a4b274e294839842b96486bb14ee219a144a29a164326114cc5fb8e5bfd3af68a801e79d2fdb8c320df9efbb260c027e3ec8b7c177bf7487a47c2824a5943754e57d0d11515f440512012d6b482614ee794e0699b76239bfcdeba0a32ca7c62d9701a372a8944a1ca89a9e546a666400080002b316002018100a874422a1280a14496fd90114002481883a523a9688a260855118a49831c61862080001180119188cc6019d72fb003b9febfea45f2f352d55753a194ff4888c3c3e8397d9c9b0471493ad88bab2f77996c51f1100dc067d6d89f8373bf7f9960cfb507b068dd9b4ad0d083b27a1776eee21dfcf3384a8be9be67496a7bfdddd6404270d761e3e946f4e27480e2334fbbab4f8c0dbfebc245362cc4e6be2522d0fa8b1b9abb3cc99072046bc15f2c8a415b5014aae993ee7024d43bbce7ee4442ad1341b218acc74ac24f4f2f235f0bd23977af7838a3e1111b8396530f3ad8b85f2f1368edbe266a4f76affa7071789c60cd0a658eb6620f9b3f8c1b48e3e1bfea545ecf1324886308125255132ab81c5b450eb5c1da3fc0118dbc0c16f7c239c0b09fd5ee1014187c438674897e61aa826a47081df4865d92350d4c5aa5c7f408ef004de0342907b616686cf5f5086d0a3a11ad39e1db8159d62652f4b0fb4da74bdbb787feac7d8c577622afa1797d880f1b7e8269319735e64f87652051806861604adbbe78a001376736fbd2b55c3b7a2c467c999f397638339bcaabbe7a31c54993ab6a7b79a18b025783002d764af337c35c971983c832636174e53c5e61668f9b93d1aac7bfd94d10c059b496da11cfe326da8f133a414950a9747ebdddcd78dd387f7bcdc0c43c845fd625da32ebdf70465cd0fffe07e78979ac03263ccd115f3a2ec16f977789f9b6abebdd8fa1af06eb9886cfd1787d9c134fc34a116aa9ebff73c2acf54b44df2520c1fba6b5ab78bf185c11bbec928b312e54cf582c21d8249e5aa5d38e8870fea4335f16b727df10e650156dc279aa11d7ee6689491bfa141e6f1c40bed3bef5ffe7a68c2b3b8ccad9b78004df8c3f55c267f2934e16daee6d626fe4113fef03297c1df074df82bd5b9b589cfd0847fb9ce65e46f8126fcc5f5dcfac45368c25bae389759177f1f34101e7e8e355175756237470f5c78f35d3f0c4b1dfe1feddd0329fc783f06ce37d5611e9fdc3d38e1b7f70bed0bdb5267eaa47afd400a7ffe8ff135a16e261f68928bbe528d5469ddec551c4b7053c7d64aef5d9c69d65d48cc2411e3fb1e4776a2252b32b0cf29eb5e4863a1fb223210a1a8f7d809defe9487ad8b33d2787aa6bd55a034f30c84eb59d56dcf6af89c7c6fab8239e5d94fd4fdec910cbb697b41c887ea209f230e18cbd3db37af052d70ae0ebed0e59e19efaf637df0aedaf127d03862aefb50414473f7ea15b63f84bbe3e80ab6dc8365497baf7df00d3cdb4f0366d88d2e441c44057bdd1d566becc5e2eebe116f4f9b3e45eb5fb235677b256a1c33c3fbb2c0e47116e3c53a2be184d6f339273c62c2770633837da1ce7c52bfd7f549b393c72a543828a1ff02553cfeac02ac8ee326cecc61c816c0d9f77f5fc1903d2884eefa5cc2d9c43f073f8e808156f113541b5e55af42d904a14c2974cadf563899ce0e723c30cfdc41c905531c50becc649def40da082074ee47e93f33b9c919397c69d1df4e910f5ed7ab896e2a7df49b1ef7eeda4075dd30d57d017ea3c110ae754e0540547a82fdef37e695e7e2a0367d906ecba080fc5d48025f4db40e3820b052177ba0c3b0dbf8c6dac7ef98b26922236d23f34bc006e26148e1e05a6fff7599d0fbc73be29850a72f63c11a8939e068ad8d3c1dcad5aa5ee0c2ea16d058149300422d1c7dc37467ea0fa907529422a3b8e2a3924d3715bd10bb6da909c482e220bcd9afe32963a530fbf4ca0563d74e3da5832155e1a88d4ce9594b4945983aa21dfaa9195214c1af800235d1bcb74279aef9154d350ae3321054b14917defe7ed678e3bfaa191dbe936c5610f7e9e84313fa6debc4f5e6e9fb0c9fa28c395027233283c878b1b7e731081ee2d0b80e28f058c5830bc305ca9f9b7d39b3482c122208f93f88ad9ba58e50b2bc74a414843546aaf56d6d2c266504a30c80029b2f39ad227ac3db304f80f4ac4a97591838c1b39217daf4b55a026cff47633eec66f41932b9c09cc49a6731441b17cbe885963de6230504c24a81de3d82768e44fa1ef4d5329a0e657b6ed2cfdf3c9cb99ce67200967d4320db32e580117413a11b06426f75e3e3a030aa756595496c985eba0ebc456338b0e89f00e4ba0802f1a25438b410644216bc67193c5357cdcf26e664e87fda243244523224b657afa0f894132d8a7b347122aa637e33a8a1fb297441f749767968a0ccc66707b386b110982c05467723921d288d258833c9c1e8b99c91b01ac193c4cd2ef559b1d32c0bfd056cf32118c2bfd9b58f42d147a960da499d826bb579cb8762258efebdc550952c7e3228d9a4792beaa2b23798fb5ed2057113a4ae1fe6976038475644b073e012d39ced3a194b716e5751dfbad7724438d9d472399350a82bd5944ceeb3e1b3212e0722dffbe43e6dec9a58807202d463b5af1821d7f076f114710a34b17d3148ecb77b68f5588bc2bce8cc4a3defb0d8110aa780202bc8503f06c693aba5e3d825366595f22266bfd657bc47a4ba193b50d1afcecdd445d9e0da6d4c6dd4a0764f4cfdaf5e3871e5488496cd08c5c459bec1174e80e4f6893ba29f51af8206f65c01631373b43f4b18f08803f9d442186319620878d92712404940f6f91760e2f4547a3543f377e9bbf70fdd23184e98608d0adb714ab6b7a10fdbd782851d92cd3d6fef3b26241d14d17311ac65b08ed62ff6992c03c696e388204dd9d544073983659f0c1798b7cd81e5049080921a2f3afb932c2237eed6a73987a79933fcc857e3b18d3d6a8fc72469d146072e6facb901839057900f5989b0480099ed00141fcb3b3e573582d7ad1c9a335093d8ac318ac3c8289edd0f658b862d5d70d4e4e1a241591475c282d24016929fd972910b00d5142c5c2a3c2eacc05c78f8b963c60fa763d1cf733c262c45000dd5406e02df50a6e9adf989d0058f3d0258d73b2a7f9d2029fa6849acf1ae0f9e805653153fc2460104d9e2eec6d4afd6b2227d14bbc1a09af77834735c9a3dd0521fecb6563d79bad8a526e86bb120794e6a5a06fc1e687c7981683338eb47e8818aff25b0226b47e802f1f1923d74f8e4ed2139f54e58a39ba3e4f2a9c88b803bcfd4ac76043d50715f025464ad182d25e33670e81564523d98fcc617d3f1e3e56ccbda459f45922253d4832f1c62ddd7fd7f74af0ba6015fb60ebe90504bcb14a450fe8f77204249e9bef3da0cccc9a06eb5235d6ec95b99231920ebc0f5321227ea3ee1392d89fa546861a14f2b2515bfee546b140d9b4e541775aa9aeac48ad91d7dcc682261a973c6f0cc87bb8f2aacec39abcb71f77b73abe1c6ab9b5206026bc37efb7b4e14c47d58f9e29e364d2421b245762dd497209cfb51ce5212b0e6a2abe7fb0f9222c72a4186a0d203c3b72a501b8c134c0e3a72ae087779dcca1a992ee828b401fcc9737b3ace8265222495fed264b5b3c127cd0ab51ac9ff081f2d62da108a60b18185cc11865e58b2f255659616691de138303d1f3cb01cd09fae7f3853128a611edd7ae15db417aacd9783120c04668219991c6e70f9a5dc01a049f460b730c90f44aeb08694d21486777f999c9fc632575e59f4295ab0b1b9687c68f36a30034642700b643c760cde0f3f63e4d41b2fbdf503f8cbd973098ae70ab44fb96f73c973c2e2f4ceb61c6cde6b3231736ef073d2ace04fc15c320b368b4beac7291ec7f2f891df4bd1feee065fc9a7ad85a9a0f059ff359decd159ea6700008343234a26297f3821573fc2289b9ad5fd3154bf01bf4aa255941ae5ed5ed679076c48b8b77b7b478662dde4cd4199849a1adbbc0f12bea8ce9538720fd0d361ab9aad4a49d46b3e1ba9378dedeca7d61178be49b6e3ba489f08df60840f151c7b07a6f83bc6b0647b72c74ae108fa2f60578de3d58db44ef233b9d1af4e3ec972974e98afff82975c67a98d3308be68fe606094816ed8a1191a5a49302ad2e47b432833a10be9cff3719778a1d2a9446b51503ed02b13f6858199557afa62fb77b890c43821f6891ef42be1b84e66c6f959082bdb3af2868527a4c994773d660b5b618453ade7ff5b602f1eefbdb07dea9b024b9420fb4d4eb6df813963e520605c62f4fc049c584a853889d082a6afbf70c341fe24e1e0d92ee650ec2fa07dd5757cd53eaee4431bc150d5e950627952d3880dff88320499b2263d3cf5550cf912c6ed0501682fbb306e2e767f02a8c2ebfcafe3d12b07617bab449f57e0aea549ea7205fedccb0d5fdcd429ebf3998b54df319595ccf1f544625efc4df389476c74d3a8a50804e532505b622c96d2a1344e810b2d90e44be01421cbe81a849dfb35486c04daea00c47b1dbf435a00289107924c1dd8bddd2703c651880de6a50215dd5dc02d688dff7491dbe9d8fa3e1303dac5737d624e1f8a7f9e208bb8b0cdc56b25da04355c7a408194f4378c6922dc486e356d3c1dc94d2bbfa9527e399d64c9095cfad3d5e5c1a4db7367d5fea46bc7332ffd0f9288ed707dc13402130d4822d6e32769cd1a7a949b3151eafbecded222c479c00db33599c11c34871b0ff1e42e884282c066da8a0a197934c935af5b864bc0645a538a9bc37ff11085755cb3c03a9611522e8e5d2aec9152e2511ca290d275b74af46d18ff57731fe6d48804f164d6509d7d995b7d7f28a49381fea8f8d5627e18b103fc1a97ab90710ee154bee6884af64c400e72e908eaf4eade9996aadb268153e07cea0ac48a17b1fd515f5d7e7de702ad4ff76c0852d82813a2c0098fb9c4fcff9d88ec9b24e9a3a282f2c1abf5c9d894005b04fb9e9d72d818eb80c64b80d1cf49d39322a57b104eb499a49c0a5acc2ee29a93eb8ee934a8f3bcfac1711fad08cac008a776203ec521608ae9d827e082a371786ac290ffbd5c3267f0e20c07998c731ae6b233ae1f258bb4c8ae42da7f5e0cf8a9626ad3e86e561a67f187d53eef036f1e001daf56835c64c27e26d63936f71065393794e0017f0719bacbf76e458e9be9ad5da4bf865469417a7942d233f4b72b36331ef62130143e65a51885a7bee8a61b4930a4021dcd49f7ce99598a2f57c442e9a7e0f015985e817479f94c499ec897d205c90fec4631d398b72208b001957cf6c7e759c5ef91279ff85fe5be4422cac318ea7cf5c22b7d650e888fe5f15a0cf18e089bcc60817d0eb8601e83d688053b86b41fcc4f2b28c2cc76e2c62d4dd35412bb983483c37b1ef08d75473a251b29c531a3d6657e1d513dc0cbb4d8806754c81ac924e4db85db1e81ab77c0c488e00c2015449ee42f1710722360482e14e06eed6b987eef988d23be5a924b68a98c27460fba0988c06638c34588229444544f11dbb8f68db0a1562172709ee07906fdee47fe9d44930b430cfc2e625f12a400d641a3d5dde21f1b986c915f7f09403acc33c5080ad801df2396c5f5b0e3ebc94e9a7dbd13899cd4a98781155220487892349ac1d768936c83307eee4fba1d6770df62b25c3b243f62a100677a2af34cf4d4768f0c407b2725c7c048e214a581270581b6a4ff6629b8c73f0585e1f2437c8fcc0668b93ed8f1289a6b1065e62f2b78692bf9dc37953314651587866ab8c7ab2c44d19582b4873e61973146c1350b2323647ef47713608695a6c9995f2337a35aded9f8feb42ff03b04726a6f312f7a187511b57e6b50ba2da20f0c020f4604d42348c6860a3117c06c0da1137cacd76dec2625043ef334e4c08a2d63a0208273a9c01380267a3b743c33c48a1f900be6adb25368b581888ef1edb939bea4dff75e7695288ed789ee844f93c4bab7f8952bea88d619a78e63cae836943e1e7c61c12df3f331765bed2e879d8d070661d9029e95ce2811276121965dd21be8a08e2ad9ec40263640380c1208b12b8808025457ec6de3f69bcf677429aadde16c62b84c09b82840f316f00ddfe9cec8d88b6cd6202af60dd6c5b2081c52487e577d8b41020930371a7d49dbbcfc5b1c73e4db660dacb904242dd4622f06e7c6ec11cf42e27f728b951df3f05eab3b8578fdc52073e87e02a6057bffc40407dfdc7ea2653b56ccf26d446dd124e454261a09a0996c5d0e0829088af592cb9cb1bb1cc3a7e25cd1dfaaa52b5b695c05a9d01859348c9d53d8589a12ac3b64577c504d01f11a37087b924ada58b0ad019dfd8da5dc5829300602fdadbe8f776ab34ddf6604ad99529b330cc8b33a144223727ad7840b106d0d6f5ab38a0a41b0bcbb407ef7ba2b74de97ae2bc111156fa575981fd8c564605ba0a93c2aa53f7f288c2dc5f2df81b193fba2ac7782ee91bf4dae9728f467c259564f2d491ea0864e5b2e4065f13c19827ae4cbf200eac4c8ead10195e415fc0aef95348f4c5604dc70a9ca963c417f2827102bb9d703ca80e6fa4d5dfa494f3c9d08085350cea656e333019a38d97b40f80b22cad9efc0149948615dd11a2d9a22176b57e50171f894416bdaef7fce142c11b7c630aaf78f5c0baea06b816bec2ad2ae253be1439cee9a15666ee43d88ae62d7a22be89ae81abb922bf50270e6f0bfcc968cd2a69fcdb541b055ca5727bb3b2b6683138db28150edc056b470122e8f8bab8ed6945715d35db54e3187b6e4cb341e4f233ef3349ee951f934cac42bb5f54f11a0b36146237454d7bd7c9111e22bca256f627ad5f100cb266944a0095abe9751ad303db4d676a21bf1ae8c03c3516137f29445acf34dc6aea405e43f78e00f6561488f5db844cda305b08a5832ec74445541c11d9378f871185db83ebea313d004f183478c41d08dc0e7c95be702f372e27c16be2c57c2ecce98bea2ad3297a5caec7be0192180c5ee90735387f60c9f32fdc90c48ad68bdf59295179ab941225e7a8a06708c92ab246e8367397064d749a30045bc313bcba6e008b23852cd5f50dc1b35a05615b6242942450b3ab149e81121128c7f8d0d5ee921b1f696d5935555b71ce1760e5fce97dca40534e62e00102b24f0f116fc6b65c1cd949e01f0d5d2c3016915042003319b971dae7dfa082477cd9671f99c9ee5753cccda043f14461d7e253e9faae12268408c7b03b15efe0b7b767ec452cee89e8f6ad1b6003b1b0cdfde0e7ec8566f56552812889e430ef3d511338000322eeef4047588b26b5b664d82e966dcb3a32c0951f0e6a4ab6881bba5196a9642e4e9bb19ad35f8120d2b58b04623593f52ba2b75c1bc57c91f1c00a3527d705ea6061849a4aaa2ea838d1bae82ad0d9497d40a6f37ea65e03e03154b13b706da7d4aca91b6fefce50f35a818f44c8095333780ff26e6c5fab7022c43acba4df20aa353ca82d34956d7f04fe2464fa9a8b90f6211dc3926d1ebbb4514c4ac3355312813e2e2d06487c33d4b90f03db7d1694fc2a5f3d963edd01bb179bd715ca40ebe54cf2c33a246c6f2a9ebd85b14ea20fe16861c2c14ad40266e06b90f938acb83bf919a40836bd216d32975da167e1c94d45d28a7e561b8495a2a3a993c742440944dd8edbf3a0e5af93a051bf315fe13a7f09b21efa34ba30f96143b21ae3348b908e4d667c4931556a4c109dbba3ffced658f4e79d4ae67953777d4b9c66717000b8eb31382a72a9bdef6f1d6dcfee4e5ed07d066123e5f5b8f123103a63e816bb4981f80c684f68d825b3e00370e7738d9f03558f2b86ca20d1f93b4a023e807340b9d19f2ea73d6b1c54e4589ee149d247544bce747394175dfdfd829bc35de13e7d46e6ce447f78eef1864f17fb2bb803941396d6c82594495c9644ae900f2edc956709a05689d707e638cf5a17d354d160e17a7107b08122711d918612f0024ce3b20820c05f45571a84e1a20cce4e9379622140d88662ff4d5d3a53022728e9959a6c770de403101bd442c59c2d93baa055bd05e7c2ff0873a04cafb2f7901d5c63a0f5638687a0826946220b70736083032885591c7edf103774378f1872b81a71178eb979e91e4a196f0b283e813c7fc40993bf795489b2f8a8fbffd20690762c6d784ff16270eaf2bb3f308a200bd53ce5299ab0b52ed2ad4f8aadf2bf2c77dfd5d027b0769a86b7884eb301ecfccc573705262e89aa39f8514eb9463b68f66e03da3a0db948a9e66bb32ef66da4b3954e22dc110e6ded43245f2bcdce01e0d374ab9a6a6062224a36988a6f16595e856cac428d35699e8ea7f934ca913b53c57fad4bd9cf8f289c6c12a1afcc6181411e1ab1fe7c32265f6a524edfcadaeec45ade63df2cf30532520d7af140b180c8d6928ff82b4d8b640a341916c53aafe986c53277aa9a04b0849c3bc6dc3601f5805e884c0f085a0e9b08a02e015817b2a633fff6350617de93af83394a2f7ed5a42c252438e0a845ba69e01f4fcb8a9ee8a7abf1feb23ac69b52f69602eb0eaf6811c14995a830817cd20def4986e8cdf95c9539561af1034e48761dab2afbc33d9557da5eaff164020a82529fbda17616b33b2becd7bea187f596a365281d05e2e625f97b6e37f53584cd9311940de6f99cccdcd94f2cde2bfb023c2d9d9f958bf9853566d64124b63a23a6e0f61747a73693c2ef8deca29696b1c9b18b7fd377178f93a3fd8a6a89867963d1f7ac53bcd71958129a047aaa4a0af20f17930459b6a3d5884ebc35768ff0ef514cbf52fb432452deb87c5e8ef6f56e4dadaa51d6c3aceaef30e19b71ca78c96b4e1fd23258aa8f9883c81e7fff9967e62d988e3626a8295eac126d19e122284249d533f35ca9961bcc38d9f857d493802e57ce45a0baf3364c980cc438398db47ca1c5d131bb471d06bcfec8e1fa065c2fee2f9e48f4547d5db83874f8df00a0889fc31cf5b6b4690b778589064d2a5abc4b83e531b72bdf9618f0a4d7ec4329f1982a47f9da9742a764e4db1cbcf21bd0cc5d367724ecba91dacee70c114f4118343528e021e337f63f3f3c1d8da6bc0bc46617d2bd1221beca7789384a5d2d28acefb87beeee32367377dbd932385e2774b79a376b2585cd2bc770f7474ab511cf7b8133b986e802ae5487ed59548473d6e112b69e37cde37ec9ddae070bf5d92c8a72c0fac7ed26f07db1f597f0d6c3e1cd939a2469f8bbd17cc4acfb9a37c9a08c003ef841fb5f1feaf38d036d1d660e8c81ce76c0b1e363c37807f3974d8c4b8b861e6e929885409d3cb013e2adc7f7c43fcff201e27255031934893e8687e4fc0b3c12615d4d0dd3470562328a71bd277cad54de438a2f36f2ae8c5e2855e8405df4f5cb438bfb5da99d3845b45db036fbc4b676e7634b90e78ded75c57b68093eb70b0dc019ec9a776e59534f368ffc8d91b0b1062cb19f65e8f961ccb2a1f992a218f2a51247c6390c13e034c163d9e53d429045c475d74edaeb09e056130b4affc7622db2fe601692970a4c811b8645ae27ae4b11f19f891d21fe4eea113d939f99d1612a05e6c7f946c7478b78e52116a6079f67932a57a6189f30b789f731ddf7c7c62bd94632bde2df6c4cebf11b52c12b856131fdfe58377ebca1fc9235e1b5b7df2f110cb2519ad98b5bf12e8a5cc5acfb7072f528f6d4fc6744ba84596dd4042fe34182717274857307016f2ef1216e159358d2189f8085ee47f17db3d67ba5fd7d83118b2bf1e5c13ca4f00f6981575cac43dcd3400ff5ac58b8246e60ead28c9fc04543220df1d66a7a7cb908d88343f63c5c62bfad1f8188db64a3ca32404d43a28e3a7d4503992e5e7b95df159281494f622cf1c7d19457cdbf95b81ae49ddefd15da5e0e4d66caac3fbbcac3964f3accd38ff7acbeb19607839b293df5771caf3cbea6b1874d32a63ae642294d3b131ab97b657801e2e7599f14387d0b9b3e35bf8fc70977c7e086fbdd973fa17f69e7b06b718eb42b1251729632413f6cb864e3824d05260f8d582835d67e3b10304b96b9acb3f9fe4ec3f7a1e4183022894e77c5a47a7eb7d0a1378578d3a09f76e95c918882183c629241adede01839f571e2543ab6579cd48b3bf08cdf824199260d164d58f8b9e384990fa556138542ca5a9ff2dedbd2a214ef226bce141388123179e75eaf35255a5a45e05b8f0862b469bf08a7074fde261a6b23c59461a956b2a5d4b33375330c35c7bae16dd18d649b7b38fa3d3c0a3d29d82fca5066a67b52203187f8fc893551d6a638fceac8a1032749e2308bcbb234154eacfc66bcd556ce0787f28e84b4b74e5d511e600f82ad86700c67650e51044506e40291f2a3447f818cc15e6883ede1e9cd073f0cdb895e2c0403c57b9b10801534e83b589465b90baee44e16da9e4f0405f6387f9ebfdde4d27105ba0f03bb0212617f360b7944f4d62b7cce79105a88296ad4a74b58a5f9953033271e38a4a9cb72e63f194d21ac2e4a284dc16b4d927c84ef68e50d942c30be4d9158b621e594a6e0b47def803058ddfc9632ec9ec5550642406ff8e7edf2534a165126bbc90907414f8455920cbe50a8eb19b3c4cf596134e2fe2d2c39b2586070422733b5e206006358f89ac7a616600c6af1626bd45260ff71721843367a9051c2ffe7ed47064bd849db6d059e4411a81726173942ba88c75b69ddca9b38c4949e0edd8c6739b1362f465fc16edcca2ccb02bc67070209b4f3e03be1f0f916ecdf0057548b070676bb9d180f93247e47c9eb540d1665f2bbbd1c662e4587b3696f61c0cb1202ecd986fd6b52b711d15e8fe1e0fce50b7b398196b120bb706eb21ed0de41f898b056e0805528e9d1bd0836e1378b79e28989a34f60e15dbcba0dd7217e172709b1f06ffe76d78fafdda12e1dca2d3b511a2749d7b17e53bb7491097ec75bddf454634377e80bd356f29114dc82d4f4926759cefb0e89d32415a566d86700088b44fc610aeb9bf398a81a7159813cefa856b07b57b0e27e16e601be13f0e7c80dfa02cb495b2f0a91f2e8ff3e3ae7d0a8883d07b9f6fa939a85ee28c388ca6375dc6472031ada6430c0aca050ccd3f88cdcc612b6b7bd2343ceb2254f9c2ae711c9e22bf515d18ccf048238872b67f2d297adf789c5cc2ede4b7bc6262ada16bed652ea0b4ad18e5cc2eb4435195610b8a03fe6359d4a8953dcf5bbc05a7d781a7444a75754bce2402d1f3ca32a4acf3dbd97712806b3b108a4fdbce590ef0e892c18a4180b7e1a0f3d948a83bfc18b50632e01d6a662e1f43ce364d6540322f19a3334ac26b26691d9ae07dd3a90c4af7162314e3527cd5288dd193bf4c4c019556914f4518e980c8d111a77461d0472aa080ddf7ecb30f8c6c9cbbda54be3507a81614f3226e137a470d601f00d338c01ea1b45674163efe3c04467b5fd08e383aae74de0f41d0702c06b74a8076593fdcd409f8016625089e0eeba47bd8af5f7d94cce27998f59dbd595f8c79b0607b961d563c5664c80e444c9176c962b71fc90e85b0c9fd3d98b1c321e8649d6ba62c9a1e3b4e29c6402e520f2a60655abf316074bcb8e9d4326f50431b58012098d439642248c18842329a63150940ec29f1605ecea8a7145ceb33f1fe9e5c9b568ad71d4b45b54acdb4ce4a57fe29dc52603302254967a3f5805eb842864f404978c74680fd63c1d28c7820ac3f7a9cb82cc04fd1ed16f411470ceacb05cc58171461a11e592820513361b4bbb99db1510800611bcdad59cf94875babffab615a34a591509f72c0cc92c01775a6975486e2543b3ad9c71887f748a490241102dbc6a94543415fb774a5cce8a95a8a55f203ced63023bd8fb8272a3712950cc16a472f7270692dee2096de6863671957f82afd504c09172fca3ecff087432406e8cf05304fb22e18a14a02c1eabe09ea8a29dd41f99a681f664f6aa2f688b84f00ceb6b624afc4de011220aafa8175a347484e0eb5c32a97d2b120295a4591202d41d24d5a842f8e7e122cea4bfa27c47cad54859529d05188b9ed6fea6b6f5d184b66a50b5499910ac2d82f5fd33e7beb92b1b42355c2da085424c47ef935fd5b4b37cd851969055697a71af3a82d78b98229c18e9ff34b28e70dca98d0a2e1baf08fbae977705959382caf4ca9919e821a04f1d33f7dfb9bbd8769796b5a09d424d430883dfd6bcbbbed1d0c4b47d34a444db102a1c7676de4830969197f1935dd955e6165045a1063b7f9bafeac559fc6c22ca90a2b53a0a310b9dbdfd4675bfa3496cc4a17503523158498dbfea67df6d68571bb47ea6b8b6a3d1f4a826beb3ed8c75021dfa71fa1e677a40b509b818ee2d82f5fd33e7beb92b1b42355c2da085424c47ef935fd5b4b37cd85196905d64644453172abbfabfa3551f97fa0ba9df3717d7625ad06da106b1089befeb4d5dfd60e268bab2955a0a7508151fcd4a75bfeb6f6605a1e49552335841a88e2a77dfa76636ab2cf185e6afe4df547d8559a5e9bb907fda1625d06d42a1665652b2812a2244c4100ee95c7d6be527548285b4123212d402a8450a77cacf6955687d294a176f03f607eb5702efe06ddfa1db0ad0c0ecb47d36a444fa186b1f8ab4fdbbc6defd0b0bc9252467a081514c45ffdb4ed2f6b17a7791faaa80992eb370f8c946d2de677815c00980bf6cff5f3d19422d243ace1287eead32d7f5b7b302d8fa4aa911a420d44f1d33e7d7bcbbac76171544a8d542112918b05f2326877124009681080bdea73ddaf950e4a0aab5114a04b408121ec548f537eadf4a0541a894a21c55150ea7dce3f285e7c289b543a82bc91a02a2b721e04942115c2b053be5cf9baaa435969053a01b4085310863ded67dad76b3d8854a6c6876793d945c979801796e67181bd31c958da912a616d042a1262bffc9afeada59be6c28cb4026b23a2a2186c2e32933b800cae5d98e7f944f56f3bdfc80c1fead52cb52a23d380a3d5b85db854461aca6bd248540f501523bc9ae30e7ed19cec6580d23158285b45a32125613a8450a77cacf695568752d148a436f102f54b5024946f2e55760abb350f5cd4f78f6f519355d014a409480700ea6b8fa93ea5f54152d88a22605a022a8024debbce07005269cf394858426a0c61b7fab8fa6b5597a5d28e6802ea02a66288b46fdeac0a0b9d4b7aebc4fd7b5d510f27acc4087ef6cf36dfd63b6928af4991d12bfe62e4e18474bb3e424c774917581b1115c5c85bfeae3eebd687b1b046ba822667e148ff47e492e0b58f250b01ea05fd486db68356416a861414c25efd32edaf4a176765349f594901de726285b09dde7af5969572e12e7a152b115403d4e5db9210ca2c9db7e52f6d8c1bb890ee07806af666f3b1af3d7cf5b4da0f9295df2f170cdb69a98371573f454d9641d39012611d00e8ab7cbe7a624cfb1faf79e93c29c1cedf3393ffd9a535b92ede851ed8189f035b85c55119cd67362fe097948d1475b7578edac2a1e511aad209347fe65c37bb0706a95f1537435b3f9e2cf34968f3dc07fcd16abd2e0453ed8dae46d0fdb22165f3de5adf6455d9f4729c07ddf382885582db641de6824bf4815fdcb6474db7373514bb04ac02569dfe2cb1b6afb5a91f29617c5844a48ddd04e346e7483f24006b8899c8cc4eb985f5d08d58cfe53c0e08e19b6273698f4b8ea0c994012a5d0e482bb62e5a1c5a9b0d8438c59f4c41ddf7126e889c7be6f8922f5f913e54ef9dca1fdc83778087d0005f543a26d026d474c7db0e6672a7c2ccace018c8f7472dbf7558c5962c5c4c5d2195003351e6616950108e0d95c6b349941db7e2036510aef718183ae30bcacde0adb783587c1107b842bf4def4dd806776e26843ae3c821459c78d042d51b66d2de036a7a3d9a92080d935b4d5a025bb52c8ba5452f5b1205645ea5f2a1719b90441f973e1dbf63179e5df50694c78ee932e9d26e2b01ed5d2356c4a2364a5c9fa7ad53d531674931dc6b0a4dfc67fa53e15224f3a693d8e68448d542cb29d89a3082075d786f29f4737bc6c0daf6cfd1e0b85fc6878bdc99dacfb56ffede8df354b0e25939b0a5e72a12a007261d62278f5049d720ba6b800f90aaa92d3cb26bb4d52a2a895b687995ea8eda06b0122c00aced692f4bd12f16498b5eaed334756f0d97731690dce80de89bc0bba1e8d9855d9f39fca6ea5ac85b1596a1731937b548c025979b5de92958b4176c9238cbe39998ba6303c9b76af7c39246f42e5863a1e190c629d4717228ff931fc480a516b1a177a92b2fbb967e33d9b25cde7f3871130202889a6d8a32b110a36a4f72c0a249e33e1c906b518024b19564947968522ded686771d8f981dc40bbccc8b2a94dc0ec8f0eae1c7a5bee5f94fdc8433a7ce4f59a2e21b184d1794682626201a8349cc76e074905d8bea094a4cb3b610a4ad0dfa3987a4e7a65690f7f170915997f60581a9fbf821db52b760f88b7a3be7bfe6f15de365ed5d3b3912c9e768ef633d80dd1c83e2e213cb1b71ec9ebfe3cb6194e020991369079502520b9282d950e2dca63a7c30e9a6b3662ec9ec18769e4661010af47a30e564697e8ba6253f67cc83694d1bceea31527b349e304fa58ec26a68ee169c9a1c647550afdc9afa8c05e5e91dd343dcac74e81b1f707ec2501b781cb4ffc3db6d5fac009868fe47acc438f3a55d635b3acc4e345e9c80b16f71025f4dcd1cbb727b96e75b2401b73fb8407015f427fe6c45740493cb6e1e87a83064c543a0dfb62ec2ce28e9c2d6bf13b437399a130048e31da791119a93e6643d33b91329a5a79aa351699accd9143f0353d38560f1e62398c274869c9eb100f4394a622c63d67addf3cd174d741f6742f8b860fd308a18da29d81000c2d71c1de9f0ae88db8e7ec31638a47b80a8281fb410cda77466a90cb3a11453c89211e09aa3154037190f926fc061ed0519e5bcc0ae22d009f458fffabebf1e08ed64467ccfc1206373f5386a83d4105e37d316cda3b491d5522fac18c78b453debdf87afbf1010c9c4d8a34a49d6e8853440d64450d6b5df534c3895c054797b7ad76eb6fdf61c80d093d4fde7a709961747d9b0cefcc71122112bd6f06f3bd1191db62f1d783eeb2615becda17ace71c8e93dc672ae41d401d1ffb0d2c963d2f50b680de883db2750f47def3b74d5dcf4feeb685bf8c302b6f1b7f77db7875dbaea48e06e012648adb8961b3226d27508a395c9e1bf5f87a95336e85c90ddbca7102073ed62e1f110dc6bb02c48dd4764efe94dddd8adc2a3b540030ff94cfa73c5c7333af1cc6cdbabdea61f7f180abc32beeb38a0330e7d2bed8887c6bf05f8fb5513314a815008fac23f14abb42d68f217eb06e3b63d56f123f445a43acc0f73f95298a6d344b0b0674effdd4eff902ab15c71ed4db4f8f5de79c77bd75c105d17dab516ea68d9f9dda3d79d94707bc14697ed5e92782b921350d5b3bfc603fcdba3c344625cdd1d4e84b29d30dce3167f1957be3b7fa774b67ef183dd57a88549d9e32a56d374ca1e9c7be6e9047bc0d581af85ebc8a3c06b8641fb750559cab815b0a2ecc76945fa47a87a5907a014213d09cf563f7ffa00162330a69d6fea86ff3f7b6beff04cbc50b246215184b58bb77dd67c8ebbb6e0ba8207e3329fd109d51aeea87a30930fb69dbb341e47bb06cc912acbcfc49d1742a2eb0d4365cc9269afd4ed6e3130d49f1a076a20e9e22b563656492997c2424a8a5012eee067c2d7ccd3a81bfba8c1e8e9f41c0ed456fb4e58cc05474f950d6527f7e832e2578e70f4b289e59be276731f690782f74d7571b49d7f18a5591da3b5604cf26ff5cdedec78f2b6dd20b1e954645927f8a8336a22e8ab744885ab4add013da939d3e17a1c6c2d6112d332eca09d58e381ee121a137332e4aebf0c09bd780f10e27a3f4a109bd7666524aeb11fe56daa71bd071ac3bad003e22a6152e82aef5a887869152d254d73dd41c525da477ea8e274e99f16cee57683b9cf6700ac4aef1a7f031ee07b47b8554730705dfddeef16e6de5fe24664db93f95b6ed2b3a2cb056ee1fe230b03d840d9bc3c9e8d65095eea05ecd29cd613be566b3500ebaca751dc716e72fa0d98f54786fd2773a3db50e36a62ed78beb41958fdd51dab3c38c9602fa585130bd64272a0175574d092f5877025fb4ec184e58adad193a87d3de6b26e6f59d1cfc042cb0ad33f2334be8e74add8a345da6c09d7dc4aef2b05d4992a9254d0027b901e7b454e2068bd03c552c9e571ed84bacf1bb98206a181cf89e9be3fef1e8adc876484684c6ca9c760abeb0a18bb9b973d22493b7a69e9089c8b9c2375f793c3757a55a81aff30c9f73d0dc42460d289631d7725eee8ae69e4d48ae9a5b0ea30c4ba2bf227d706175268e2fb1b19130fc736ce8c541f45acecc9abc300c1a10730b835f5a3029b398acec6edc737b9b63c18a4ea5076ea3be96ec4643e40203b305042d1f98b6410dae842785d3617d98b1eee96d91547bb2877b649c58aaac6ff3fa60e3ec47a9cc9bd50cb53fbfdb8fdbd6fd99b679c2f29ef9f84a7db2bdbdb8fd47d97f69138db1dc14fdf3885de807d13950fa7ec54a94fa6ea5a8914f8bbfcbff07bc1b18c9093af1c7448e21b3914eaa63a2b0f2dc005ac15eaeb8edbcefb1654c14e46162947ca6429b40adf3b57fe77d407ec660f14300a358868caf52f97463c9fd48963d1e45fbd2147cf145c4224677062ea450accb2c3265232e479aa21c481d24e21ba944096d75dd909bef8ff9d3118d39e3ea20a7f2469911965893decc24f5764cf28f7f5d9df1a25782584c32565ddfbfc6c9c4819c0623b10a71a399f82fef097888fd6932708d08f49081356b420f3510a27c72522330503dd2c4d258ebacc70dac88e689e20e5fa36e72faa8aa4db4094ea88dfc481d24206c32a020ea9a878d405361883ad287f8ede212bc60d8425bcd961710ab0af01f53007d953d27666721d85ff9f0d83df2d8e152a72abaa2dcc82551fb334f9207c9a6284f3f5206fd9042a1a6cba9b7cdc68278cfec8acb4e18272b63e2e9efb8cd5c29f7a36eea5b618d7ebb9503cb854434b5381d3ae7acf4998284a3d4914f0173016849666c8916610b0a74c9bd937bad76604f04d15e049bc9a8e4dac54b77a857fc474e33f3c4afe027ede2f68e8a23b3fd9585239d0828675b0448c84620e0d62270c009455818af31e1605444c4aeab2aafe069982b412ae14c7b486f66b76331fae69e8f7392b4579620a1d9affa0c5467a9212fe2b852340e7980becd2a00de709728ca8b3345de2a0c1f919d6b77707eb6352628ddb626168f275bb82d378c16b154e68036d2a23c3460239643c814487b15c95b75447546bb1dd9155c7c46f8ad90018ba826ad98217f8764dcab4f7f74af48f94922aba743a21d2dbb1430d29f7bea1aa0e1b805e4a70329668d744ad3de70c19e44bea61e5e194ea7f442eb7a3db8bc6e75ec3f66ac71dd0a93aa364289de1fc4be0dd77d9bd6950cc5fef7e5090126f368e162220d1d22466a5e696b7936901edb4b380dbcd8cecaa68ec42c3a7e8538bb06c512b1f6b0411e63e4bd00916c6ea46c52f309b6f7145e36cf0709f64f2cff840dc921b65920f3c840094f0f03928b858f3e74cedc7c11a442f9cb7f2be761451be409e9ffbcad50a7305055d82be53c6187806edd83a624cd3e8ba8b82e92dc9cfca52097f461b882734110fb8acc368118768cbee84228806b0af42b68caeea38f1f0d193ae0051d11a6327f9db131ee899b0b6f3bf40d0133130941dec0cc575da708e334b7410e507d100a54444acdaf7cd6478fd0339d03c1967443438e13b3882a5f58e5219ad47e7261c36e57c965a4bf300f0066c67a3020668f3c1343384f02e94daf87945aec81cc3690f88e031412b4a295f7b4fbb374c45e001ae40f784641a798b55c7492f07652d5a8dbd199f798cbc47282eb936772bb1a8bd4ef1df1f45e63e197333f7f12cee4d5fc079b2b3efe95595d85537893b78fab9b31f9997e212090a0bd373254d8cf7256b18036f8c51c772380c325fa4e10d492a6e82a43daf8306afe78da7bfc0b7c07ac86913dd1b289a8cef772500275e243df9fd67b4425c64efcc7b77a6e40d7df05f054ea8808081411cf5f8fa10f93914bac002df9398c2772a8472fd7d890ec4c7f8f6622596e00fd53c19f04f1175f3f75c3ccf45bf7fe6c1feff78230962273a529e1b7649fcf1fdc53575ff4f97a85fc2321b60d2ddafd4d262cf29678eef141abdb516d215b7dd6cf35127ac536f902890aed620e5107d454bcc5d291fd3e5bced9bd01f4b2ebb87030e12bb0aa5830da4dfcc1d25e600640fe4b1bdc815ff5ad579566bea1f3ef18f23e2c7779b8789f13d872b3b0ab771fa53e0f41e4adf80ec99f0954d1a809015096e76aecc1a3d01f771b3f36144864a50bee6022b6c8d0b67401531924ff488248dbe708a9db730d40dd2beec1b9d5cbe5d65b764e08bd07ea61360144ab1778b56e8992091c37a22e768bbd809a5d7e76f42ee8e97034c6a19830ad4161f011a47c3d2ce2cba2a0c15d8509b2a0710684636706736ec908a338f107f3c1ed8f12ddf2595cb9d85395f41efc60a54e0efca333852d47f59fef7bb461a785f82faf4842d9e4d9119b9a394d5d92b886b79e1abc66435274e5fffc45224d2d1143f8856bd7e3f2f70708ed9e5a728fab7a50b3d2a89a80f95351441abad3bf8555a317340ca97d376cac51ab56f123a65d018347a479eae83d98bb71e743b94aaa1170152fecdfbd6341a8b404a497021ae99e53553bbfdf5342a1bb95993daaf38deb3c3c11ded2127cd12307b6c72928d9f556751b98027d160fe59b911f797b530589b3dc0a93a2ed50cedf7b73550ca65819e4ea69595402053eaccb4d91fafd49894b3cf82fd805b2bd38f0b613f5c4f38acfaab9bedfc12583425c85a1311598badf8385a708a1cb983b75e1248448d91072047c0c517579d82111e16ab1a576825ea82233670ae99c24132bc2b7f7054b0e4b5450d8cbae7faa69e418e31c13fa1ce14f29f627c2002a76dbf1150bf3da1a9d2d9091cec4450bfaa0762541a77a010dd116744f030e15a234e8110d4db23c80f47f27776f0e37ac1ea056914c3f8685b2ebbf3cf59365f47663d5ed24616cc57604e009ff724f3ddc772b3d527a577f9a51a2b3ad8d88baa6d4a2826694009b0f34457122f8ba9f603c9137c9a9c42fdcf2ec3f54a80a52d438fb6c87524859f8ddbbb81717bf5c72c21ff743978d843fa7b1219fd446469ce4bfd3884e39b925dd4ec8d83ea773b9659733495553592060060b17c05c68a75dcc4a7e584647b79294ad30b87dfe56fe77286b71cc68fc9d6dbc46231c3b7c37807363456dc3660445b50de697e8f97ed2bc13524f03037c6e39f9601e6be75d52ae4161b20278eb2d491104a0159360e3581acc9cb9340e554ce4b75d90033ce72717535f688c75add24f947b521272f4eef19de4404dbb90faeadcf097c426e783016028dbda537f6a20398390e00b9a207ae23704fc3c420a4b1a09c8a9220c72e864766673fa3cb9972a5859f19d805c2d63b027055a6771b37e7f4e4c1058bc5558c30fd012d5f1206c12182fd1bb6a733ebac5f789f4a69f352c2aa15f683af65237195facf67ee6e8bb0364455fadfffeb1ed4f9a2852fa50242eefa35302a7b681a181c5972b3aa1418c0d739a275dbb6da95049569a4b9a13577965c788a226b54bf21b704f3e22c77bc71d8da9b5101e04ea955d77eecb9d12779877af9511e9ee93def6b48d0a3f2e6aab5bffb40a94f84e0980e9bbaddd4653b1b1ced6205a1e01118fd27c1caac8f2a808f6c6d6030e4131cb27f4d95db37153e3848b6132feb919fe711304d1aafd661470acb61ee4dae9beb74a0fb9f89167166dd47065647bcc4f3ad6989bdbbae46d6644682d5cf7209163c6051fc089f349656f535f30e69fe5edb8d15b7634b41c325e407a5fe99f2073ec0f8e15a9d17fd47a8e704c241fbafafeeb045fac40eff909efae779886e71976a66cab3a1729f86212afd3ce7ae62806eb257af9199d3b22fb86603112cd10040c0240c7ef7b6013fa11c3007cbdf0ffa7ef4f9e4a4b4a0e7d2155306ea8e64025b7ab2e7bf4b3ce66246157441e82f0777ef649494c26eaa21fe4bae19a25be9d93cc1232eb471078450d89f7bba342a409af112fcf1b06df8fe45be350175cfc00c18ca6dcfcaf0f114d3421770dc4276b144dae442effd77e7970e3f310ae1cfda4ae17c92cb53a55036fe6e3ac79bd3615f43e1269f85627f3b37203ccddf97c68ea301e77188f1475718cb8c44dbc821ba53cec691f4a782e0925b7fd31ae3f5377ee873b6a97f3e68f16d6591618bb0d7899cafba2e5f92321ecfe8924d579d37c139628ef38c0e2b3b973ab935c67e28b0ccbd83231aa1441ebb33d4af4f2bd72b60cd4b785742a7cd1c05bcf9ca7d6d03de1eb00b6849d35e1594864a4c3819cb72f94b48855e52d7ad145f44c72745397cd200d171ec06a8fed26991badd3da363df402b17cf44f419e8b0f5b8c352c9dd4a865451a5100b0328e0ac5eabaeb77079aeae1e654f37ccc1565729da2c532e64ad6989312d4aed31f8701eca911ee4667f91bc8302649eedb07089d8926d89f7fd742ae3502a0cfa071bf7d5cb5844bd01f6223d41e5b01b2a817eb32d3a59288d960b7dadc6594070e806e9e15641217772229db4bf73991e8c44a0017da303264f49b0bb04236503686b4f7a4597856243c930b5587de80bf9348b6bb917759694da61448ae58473c76015cbe144a75397e47e97c6a7f658e7fcff2422585dfce2b99e4aaa0eb680c6e08354170e27233bf80f86adeb9a7ea79390e12764b16499c2689cabfb00f30911581c893b4a34e31ed05c1d31311fd7c316be76e34cbdfcae1707446f603f1685fadafe3fd93ed88aa2f7fd71d42aa94b32a64a50873d222870cfff86da7c5bc5ba89061b69fc2ee413e4f698f303d0600cfbcbdfe596e098e8bc8c5e370e65041436206c49cd13ebd38914dd95945ffdb1bddbf120b64f857d5736d43f5f1e10f1964618da4f79874668d4f58881f129791d8bb0808396f6905137df5648dc5702d86e890625b633352f632f543fa6595548f0b42d44d97795b328f2d332630dd7d35414826ebcdc42992ed233bdd5775deeef948ebf255bcddef4314bfb2918640753d120e414efbbaad8f5e676a84eb7f177b624e627c14a13dc736c219022c2b581a9e1f0ad0c0753d11f737d1d9ceef90c6bd963ab4aba407a4c48586ef38c089b4331b33cd1d1a62a2a51d5926e3046634834cf5cbcc5551ff8390effa38cbb7f1adde344a9e358c964290e4a07dc238eed504e960dadea3ce55862d4fe64e405091b6f0a7a6fd1d27d081f5baffd6982c77c612fa05b2631c78a44b7223608392aa6de8e3d33d9f1701a951689a22d542ef1ccd540e0c022e9d6d1ab01a72c6a1a1ed5f06bb05d4b76f2b681ce05412ee104b9c39db2b1b831fa148bf9acd966109adac5d6c448019ee7c6b4d651a36de8136b389811cd179538efad2846b035a2cddc84e0444f9e267ae904aa5cf2b30125aee6745e7f969ea77d887162e5cb19fa4f20f9dabe1c3393c1a2c67524960f9e7961d1f346102ee3719337feed1b29f00a5c68f0ccabf320a476ca5cc0296ca31fb5dd1d86230d5a82157eacf7e234e8cbd4d674aa6483ca07ed8dea5b70c2c66bf2aed9e18a39a78c1b8f0cf1137dc994194fc361f7fd494a4908cc59792c0866993c56fe8a2ecb00efaea4a637ebe4a690bc351ee74bc33ed34fa1204c837e0b8bf3b14a33d1e35a3be077c276615ed24c5848640204f76e56634d5063ca704a90a45900d8649e00690a349cb819bc21ecd8a0a123efea47458965f3391921004b09aab5e21d600b75e08db15aaa9e5873c40920aea3b0004daa0b1bd5ebdfdaf59efd65db01504e84b97c622b5a7bd414ffacd0bc54ba14f2120d56808d7ddfa8337b64da75ef44044feac99d6d647bcdd29377fc5a82dc95a15de65610862609c661a7b1cac331ca6e5fce9e4a47dd5cadab961fc5d4061141e0836dec1d9f9e221aa797f64e751c2f443a2ad41efd12a2bf08ae8d39e21c0e1ad155e8225b0bd2fd05edae544c05bc2251852cb65d6b4116133a7990f8983c193200c330e52d151f4cb64e280f2e59986e8e29e2aca9960d0a4a175b50a34f85b22f888d7e67b237ea3145c08c6b0fa6e436bd0b39bb4a05964deb512ba39ec81d5706272e81ea7e614f20ba2576702a952f026325f325c5c19b5b658e5526426ee258c5c42ad8771ff2b3b53330d4abfb77001f3cde68cf9e9d0d1ab91241756bf305b8914e4feb75cbc0c77811d3f1ced2a425301eefaa9821451d7b3a8dfee5fafc2006efb9a8afa00302869c92d8ba03c1072424f0e3f7ece8e2555749eb510ba8907bc57f6ac103f06ead1c8d293044bcbc616ddf1118c1dfcce3a646e1f3a8b1a328304c0db970e57c379811cc1d3120c6d5af82bb2e7585967b81c11330e3098a16aabca271adb4031280f36bb381670045cf4176230561ca85ea3389f6945f131e17619d1b23d3173462cbed3605776b321129d2ff0b159a938a9bf379a90aef04a60509041b9a68107e422079d824d56ebe6092bcd0ccb10e60c6abe8dde00d01da8bd1565bcd348f896f37514469457db80e284d249b7c08d0a2e1dbe8181dfbd67a11941f4c05dd5ede5d9b67a5033792bc1000eaad9432595722497c32ea07477779a4896aa242033daf3791bffaae28e2112e45a49b87904e774b7d444f112958bc02baa4fbcd0a0eb3a73b09bfbf477af542171c8c0859fe30232cbbff358dfc7123edc7fe63c4176460d3b7f1b5d1603a990c1366b6da42093c36faf154261b41b9abdadf5c7caf1a0c086e770318184953d377528ffa75e63dbc66e8761d611bf65741cc62244491852eb90ea56454166a9a629192243da8f2e18e958b2f74445f8b163b1955eb2b2109a4e13c3027e9c7b7756cd2e5007e43989e2eccf7f5ac2545277e494b01531a1265fe0ffbd8498fb09eecebd704ce64f6e343941be247030668461bf23dd9c9d6653dc9952257101b028211642eeff438933ed7711b8e17c480fd2b33821168a7679b0403ff24204898305c6cfdfbb16e932c67cd398e0460e508cedb7fbf66277b67fbf28e52124cfe8b4811eaead268c3a452fa234d78bc6ee7798f02e0b17673e9ed0ec584bc69e373bfc29bc5013e708f6a4a3cdc9b67d7d8e29700973a8b11d2bcdd35223d024c1c14142f7d6326cfbe28a8d6aa7e09b5324ce8aff5f66549803f51e3f7902da9390550a0a95cbb7238b90489b8c6ea2bf38f217d5c407dcfddb90f1c80c516dc89b9695724df8f05b060e6c6bcdf710d26bddeab57283abcde270b8e49a576f4d3551f13de77c5e5dc9af6d4ba93c1353580898fd4b783439d6b0f0b5d095b897c153b05c45fd7d6d44a18a28ed7488d69adfad3ef03eebdf796d33ed1869beb215fb88df4438e314dc22f66bed8cc97d0e3327c0c828d100a2535696810c2d81ea08e3e214ade9dbeb82b612e2be0a5026a477c805c43731638c1f4934616ba170360be81d558c22e40b0ddc51b1ccd283d6cb7acd59b116b3cc810236d63a96ff132e6334eb2b11577afe41bfcbe77c6206912cd0c16d9e64000c86613cb43064ab94030fed5b36cfaa7d39acd196c0cd99052086132a5e0e8a959d6ec6b3ba20b442f79f904d148da7275d562b467c04d1f3b0dff5a09e593dda03862fe29e5a299f4d4917bd81473953bec0bc1018d645c84a9fcfb59e97e60d24385f00bd94446d39aa001aa41678fd591a752a5a5f913fd55ccc7e7f11f0820fbd8df11473311fd6a63016d1f02d8f75e136065012b394e7c3dda7439a5119eec65ce821b13745604429dece2ddf1c25398ca85562b773d6dbf523bfbdaff1f255f6436fb83448d9557ae290cb51f113b860c6af8ed4a1f93a4038e85afeab32be5ae1c7530fc0f905741f8757efd5e5d478e4f06a13bcf44d1c7e21ae11b5c056d90a37bf07af9145856da072cbe5e39ed19fe12be7e7a5de79bae2d7df4937d887d8d4382aa3afa55e4ca746a904946a7d072b0ac5bc0cec9b028f37f7044b96022f699cc35314847f4c416238759182fb0a90367411df06c5bdd82267a7cfbc89289e872efc324e8fe9baf0e16e7b5b2977286a0e2c45112209b2c7f3f1a955b04a7a98890e88ae841e40067a66a88fd998d1954d153f2b38cc150d7f167da0fb98b3a70c55fe4eb10a596bbbf7bf8441f363992f8e424a5cfb6657b126b0fde67a452f76ff2a23447d5fa0e67f30a8805156e35eedb1462a67f7419d8c9dbeb3a6dd077c512865b1020ba88966359a4f805cabda24812fe6f27040c9dd680659f89339225dbf7e8007d298477d1007a91701214871b48a3513c8123a37a75dad5bbe77222069aa17a18920b99e636d69179bb47a729752d45ad829f4b58c359a191303418e17f06d3ad27e00fea8952352b1e3dd3c78ead0ca479372beed7ca8e32b412063a68d4d1f2265ef73c35e7fb649db674a31c44775a8955d290f0d7326e5ca31c491fbfbf4ff6cf0ef402aeb8ee5ef475c165b0afccc03e5dd4fd407cc460d4f3af07c15dbb806a9e31bbe3c6572676e64ec75caf3ee31e1ddd3dde0378d27e86090e95646de971c8d539455ab74f5cf70a617a800bb4a644a3436d302f91af434be1e76d1ab47bec02776e994f69b907f23b5c9d297c0c56faa6b63f01be9350014e52c87b74b3a1b5c171a505bf2a22cbc9d3e3d410359230b63ce8d71c6ee628d4717b01813491f112a78208d872b20d327fd69e572d5640a11483b5d2492d5b8ae3d9314835d67f39491457ae56df8546d9e75ef2b54d8c4282a32a9153a13cbb5650030ae001f7a9139c0723454ceb066d29067c91233669865b37cc2a3674d691bcaee626827f6dadeea36486cff0b926f98a8916423598614160d05c5c8fc425f0c8502bffc8173ca957ee4f47612fc0842966c9665718bf54ca80ce1e9fd9910e51871729608138a2bff5a7ea11d3caf453909c204f260adb1b3214c8c4e482a00082449ba842f85cf71047430cca97109f8178431e84cd9d0b2095e69f5cf51290d4cd56218710210e29799825cb514f6e50b282bb0c70de38668906623849103c014841e9d653249ab4ac8d03c34385a7a0f6b8ebd722e3818ea0a13435a35b4bbf8e49e23918653f1f5215120cc109492d250f0c90b85f7dee80b86fbc7e73e88a4c014847f6f8f61e39f1de5398261b40c08c1e1c4244bc0f2aeb77b2a7ccb80bafea163db415391250cadc211c9dc703777c38f07cf28b0ddfdc7414375f2255cb88595dfe2c72f2154df0e1db743e605334b4cc22af08f31186345add94a26e51a5e92d593f386e96084eed89ebfdf41d79392589ed642a23019514e4237fb6e443a39690fc36fbe8d03074f5ab7cdbb5c033150d5a5e928d11e2d2587cfc39678957191ce0d61177fd84a619e073129ebc76a0e84daea9da1e45582d59826e2f7b6b62ab1339c38819b01f3baa7259eb12732c0f77264bd3f09c0e853ebd9555d1e7de96d8be9720041fa5eb0a91ead424900646d8377511d7148fcd128252f9f12a3b3265538a5068f53cbf03ecfc62992bc36d781060e9a811bbca1256b6d1784d497921e0b9e7ffd19b5be079d7f3e8320351521af25a471cce18f0d28a277c0a5a64bc82fa50fd846f2c4da31e14d6709344b8810cb5ddf2a215e8b6a09e997d7f3471544941015c4c5f5e2dc5525c4e7803d41fdf903b3f34a08031026f8f8f5fd6bcc28f912124ae90c91a59a08c9aa08db24523f013bb0c8bba7ce44b962ec498c91bfd670205b04bb0c3958740d72436ac50ec887a28ef648814565e17595890311574f23e8fdd590f31d3dba7ed79759adaf06421f07ace63889553578afd9142c2e82faca0f6982fda4110a0da63312836768320956bcba0158fcac671b3f7f9d91acf58c8db68031ca7e68f0f452a9d38e142df1d98fb06bc6e60aa1e00aafc9d88a64966f03b93450eec0e8bc74b58411cb9f6ecba8a4c422c64003b830091eb99a268f7e9920678a69ac8798c4beb108fd6c2c7b872c437b0f2a1b4d83a75235d8eb4d08ebfd952fd551d4d81cca15fba87e014cef4ad5d05bbd8eed0c2cfda4a4b87c897726d00bf99439480cf8efe8feec8c08d86f19b566cf5314fb7497017888090bc5696649cbd13353acbbeb819aabfa8f9eb64f90c5056b0fc39fa8730cbc5fd7515d32f4ac70244181075bab8b0aaac42bf094e7c8726f69604eb1ae784aa6962bc9aa06562bfbaaece53a406700b268fe64843949cd66642b55cb0e6cda29552df35361751e6411084b6ec05fbb212034c8a19c885cf2f4a01d5cad02ccbeca2cf04f48cc0ed2f2f01b528526d711de82a2e59d4e92b976fc02775ae5b4a09377ef2d45a862521876851c19f845e4aba3161075527052e063f44552e555d3bf67c5c4ab604590950923f4b28cdf5d6aee7836026641894f7619b2ebcfd13319e937ef347b4901e2c11fb35cc2a9b03b232338c073304edd30acaeeb3db5a39f43255d6f73ba7e32097456fcb42958590177206a17376405c742536c2d3e67bf0c7d388c021c3dfad68415f3db4305b2837ddd32e253e1f8a571a385207aeac822454be6813ec69bc4dbcf1b94dfc6172eec201082d3e5dfcb53facef34067f8e22f5e463ec113e5e4a56f95739d04422899937f9a694acf8b60076bf504dd8bb612480734826e6306bb48994bf106e6ad98ae0f2d8df13e5a87c5d8414bc21d3944404800218871dcd5357b741349dc74715ed0c26995c7a2fc1af14a38d5deaeea19ad4666962c3b484468da771b3f0dc15230dd185c94f7841702cf3d1aa95764ac544d1141dd9ac9e8e30a021f75e749cb9bb6c8d71ca23812f72d5cb8705a3a9e85e8d6b1f6db567ae2e765e176138354c832ba0002367525ecd359d9ae294f72d8cef0d7e99652ccde4956ac69cf79f213b380998800a5f1a05bf79b43b8f1b68dc4f6671e5225ad9615681d327beb59a3974908d8020dcabc9aabd42a22708d1323003b40918cc0c0b60eadd2f93e27ce89d853f49c33276d4b3726050a7dc1d5ceb9ba69f269cede4110d216daedc7f13bd7422e17fe128f3e13d9f3dd4ed958249de5e75068faa4b62345e160e3f7c708f009ff1aa70ed9dfa2ca6a0abd8e0008ff020bf1fd8d24d47924f96333e5418f0a285044f00c69eb5156d3ede4643a5a1ce6947ef1252464515989ee1611c2c13e66f61feb5465ea62d696db8858746ef52b971d1b84f1aa2d446e7e5c91178185a8d7148a498c672ad5131e224447b4dc3e69cdc44408ef1520da77486427880c3ae456004da59a3c7fbe81753d658924f0bda449d4c8005a290a6ceeb048cff2315f4845daf7ca3ec41edae14403e9bc0f49ae1d916e7621ed9f2adf82a0c3b040b7bc29efd53bf652ab11e8c0c8503c236dd942d6bac59e9e40c00b52cb98de178c31b8270bf67611555654ff50697a51115d6c910a00f0e0df56b277f9e27565ad917600a2b2bf7cb9f024e0ad4d0bba68da5226ffb88316f075b32615c917c262edc12b16c43a9af03af3e96c8d4e5383825ef3582faf2eb90f7f94c5d73e550bd918b83bab8d860c757cf018504b820f6e3b23f43723b3240c04dd60f5527d9e137223b28ee1725dcfb1c812fd7c8bfea284dd72041e3dca6ee421dc360be9c3a90fbe02f15c39d6aca0dbd70c86d5874fb4e414eb8a3894253377eff1b25b6d287504d8f0dae6021e417affe671358beb29940e35b8a565ef0e19dd58e99246f82f84f306ace64f94c64d32d52819663d36bba18de728457ebd73d9973de25475f72241ace99df84a7e617936265b05f2b416e4db1f7c08d03d9490231d05c4a4ff083e65daf295b5e88827a53fc8a80e97cb186384babea888395b4a1ab4dc93950f2818c55f56963e4536fa04205b1fa703ced792d08f1101e9e07d759ba64ca00112cfaa0faf7ebad65b48f2b105d63e492f76a7799b6590775d1658c5ffd8230431a1a452735bb0d5f326e3456c1eeb1e6ace4158d49a565ab066617dad28cf58c8d5afebc55fd63b6008827f0b56d82166bb62cb1b8ffc64bb010a5241485b404a71950e110035b5253ac87902ebcf10b9247621e9946b425e361d2102fc5794dbf53b616b30066c57acf37b5ba0f609ef14b54fe07e9bc3dd6da680b8b7f3452985ec37f6a0d8b064aa1a81a8175f12b2f7267b6f29b794490652048204d504533146d85a887f47f336485dbdc05a1ad6678a8dbfbb7f3f14e2ae4f02c9f6456b6d77bb4a150280824c9fe2ae8afb7e47bbaf42bcd90c28d707c2fad333d247bedacd8494cca1c25ddc148787cda6000869932a44bd4d7178bab66ff24647dac8e77f05718ab50c2a884fc8763c5b1fb6fbe7a8b65a12f9fcf6e82784b482b00fb4b5e9ee682aac67800a9df77188470edcbfd2e8be230722a8255460af3dc20932ed4209325254b53fd3a03efd2f44f6aa67d97d0161874c3b5c8530b99439e4fb4851b6fb201c810d3f5948a69df85327dcc0b78f864c3b59a5891ee2e4f3f7b543f7effd0faa1a7c7ffffe540a6e4f468af29ee2bc770aa27befb3f774b41ac8beefbb49d44b25cc61468a72dde28968bd208358d0f78d1fc4ef9bcdc21361ad1a963f8496822af4c183d0907c0a6d2ba282a09f90909087da27fe80796a86f0f3325214fd161f0b71a6dda5f4fba8ee3252d4d52d9e68562fb04f06c9ef51a87d110dc8404409f914f10011222cae4a8513403972da34778463979be2f270ed7c01f247defafc20503520b2b83c5fb61592f4449dae68c20d7c7ba65eb8816f9aed2345f9062ccbf5ec4613dd637dd6ef3e9ce0c39a5c9fd65bd469a75285c4ef485b6bd177b91163d330190fd4a6784ad8ae1d50ad3f1d290e4f131c1eab6aad876f67eb8bb8afafaea3f449482bd1f9f92819f9723383c7982f2c5a65038d2d842b3482382919f9bea27c69e9fa52e18b052ee7d96de5ce03994cfd8b808ad1dd8530595034f019a0531ab0f433fd1909219b811ddace5a10b682a0ee1474445741e03b459e5d53d45dad8b1c245ccd8062024244090d26cf4bc7996fc6178f0f0be7e562875f9b765f495e3fcea8d8612689150b1b42b864f9647c09f9b0ee98b903074c101830779ad8b9fa72ef58d92e77ae76b729ee4e96305eb870a953a78e8c2b7a268c549124584e40a3c217c34e922c6707ca4e905acd83969ab5d65a5bc3d55a6bedf37007823eefc11345d08679a892bddb6db003411beba2ee2f15cf7231c6574bacfecc3e4df1ddfa7c0749f134c674ba36068930c61ea4d439dab24d7174dc745facde583a31c258bdb174420873db5409d26ccf8c169cac37715cb8f77a70d2ec7bef9d32c1a6b839521bdc1437276b9fb986f142fb34a4b2af34a3a8136218d60f1fd427626fb591ff7f909375ce76c87b99ee1ea6ed87b476780e1bbec36f78a3a8133f5fdf7bf7effe847fa74fcc665a02da28ea0487776d54b343de73f80e9a8336226187bc77edfd066d54337a3be4fd8fa676c87b58ec479aa88da2c037121ff6a03e21fb983672253be45ad4461eb043551bf991527dd746d40ed5378a3ae15fb591f7fe465127c477efc5371a3fd77a703e1a4e3ff2f1276165344af4d1bcf7a119459d085fc3cbbe87f681f8b0cfb40fa24e88da99ec90f7b0ff40fc0f7232feab5dca0e79ff818da83f308aa20025ba8f9f12c1f407f729d1e952db43aa71b8e41cd59890fb246a082401fc14a044f82be04497c8a76cf58858ff202a2a0f544142015e98ecf34b2ad9db34f702c93e6bdbadb5b91750db3ea5bbe60758626ab952ab4da9cd6626d5cc94720484879b17759ae01942f4c2a64fc202388b2aa4bbea0ebe6ed7fdd5a8448a81ff68f728c6b6388a31997f3dca34498e058e2d21adef349794862b97d4b514d2201fd185b0e993388052f6afa8d62f4fe048f229944bb2aab92429bbfe870c6a965dffcb5842dfb40b69f5c4f0c5574104347e6c466b16a2a410253d08e67d104c9f411474dd5bba67f85d44216efc332a9d2ec25ac87fce4cb3adf2ea1c089d366521b5a94e5137a5a405a193c9fe5482ce5a6badbf75514ccd7c320b329ffc58d0c3eacc8f275d1bbdb2f4790c4538a8b9ddb805b9c57c0c01bad81972e1c746bb846c2c6e386e0bb06dc1d160b372f32d5d6e329b14bf5561193e366ca3573c6e7ebe50472a4aeae88c0c2b271a8070dd467cdd445b190bc2732b14e0002fdcb428b0f99c01381da53817d828941f373c37096c5868dc8b0c32d80c60a35a406e42a26e5d026c48fe854ef130736eb48c97b4e60b4a8b8d16553254d980053173bb549848e5b9a9b949296d3a6e706a369a25cf08b72d606e15d8a200d136de25c226c26d861bed841ba51a6d5ed3cd83cdcf04c096bb65604b61cad1548f17395c8c0d1a83c738c385857eb9e2201cf17273a26e60b6bff7fed47befbdf7dedbe1ef4050771d967d2f6edf1ea27bafee3a6b44031b036c4e82921bc5c2c65ff81d30dce87661854e97394b92cc5c595104080b540c981b026c44fc0e7de34be80cb82a5637676a710bcd0db63a6b6e74ebea465b1873cbb6109ccb0436109c9224a94b19178c10b1c26285062028dca81600d8dc0b89b7a154fc4d8ddb9ddbcc36a4aa40e10593386cd27041caaab2224b0e42bfa8a8153cb7a91b94db071ba502c2180f086883f1044a4b09ee8486f1245e0ab07996aa1b999b9120afd3012b848d665991a92adce8381b4bb182c0a85ae1e3898b98292ec2201447d76060a371b3c0f6e44d565018ccb88b1b4de371aadc4cd0369f71fb2c6093a34b0e6bc6095e4458cac6b91523c88008c0e65951281a1f6e5ae8b1b91d2e1dc5d8fbd3b11c134ac6efdd97677ff56746c97477dfd55be89fc7caa6b819acec0f9be266a8b1e96802ef0f182093a8348892088772ee488907a102e4fb3ad4a07bfa3202645be2c3dfd3ff9e5cca03c8de23455dfc415f0582eebdf756a1fb42f75e21210f5503fcf7137f3aac2bc849e106be3590f779def53ccf0b21901ff6de7dcff33c4dcb4851e08bb05004f183e2857560ad6e09bf93d95915f220876cca6e7305c14177fa0657e7ae0a055535b5fab6b5d65db5938992e4689fb5ed210295464132c2ae75cd3ec53d7380896cdf73f73abfc561b267c7772bcc041fe0e4eea9bf3b0924d33fc57dba08b6d37abdee9e776375dd87b733414fdb8d1c8c26ec77fab45a771403da5192be0aeb554778558c1d789eedba1b49a75c7d4408aa1649a7dc759762f05d9a898e52a113bfc701feebe10fbcb6731bbb1fb0fbeb3c13f848288000f80a42dd5b2bc556daa66f39a86fbbfad6fe1d39c0c0a94dd0765167ab876d8d90d6dc11128a29209f72a5800602dff895f05f1a0de2e34f8f28e8d7c61fd3678db1bdfbaee45e7d7af745323ec245329d48c64d4fdfa34d2b50f1e312f0c84e60d882c689d49029a24b66dfcf5dfbcaf0a639a71556745eddad57aad7e45abdce4ed1458b474bf3af846f5b4151a442fe4ec712755bbb37cd3905d921ac84ddf64318f56abb98fd129da61ac3083fda7df5da4e3c2db5feee7e3ac555f8de8bef7592b1ef7735840444f7de7bef65e394549ac9dda63927a4224d5ee68eec66036d9a6bea62652525c459f0bd7111bbdb18d1d2ac46b4f33581e0c136cd35257d6b98cc8462a64c6d6061f7d1cc7407849548792a9767f2968c33e50a8968b6b1e9e9c8abec7f7980506e36f116757f24099784feb5c33026339b32b5d994e9ceb6d6daee2a8d2c30c6de0705638289200882630998a5b94d8aad49ce5b7a422e0da2e76c6c6432992ce7247cf403f270dacdb66915faa1be7fe8fffc6c7080d53724b95bd4180b77389037e5e598aa8850346c9a63ba9a137af6a12128ed6c0532c5e0152bc4546046f1daf8a8ba7bfe99e17484d45e8c493ab96b9b37c6ec3333fd00b3cf876d9afb81dbb14d733fa2ecf3eb9890d6d0ad773926a9ed3df1d8e7c7a4b4698ee9689f22cdfda8b3c34d733fd4e80d34e16802a22f6e6f03514d2949734c5536cd314d6d5ad6a80534c4d711dbdfd4ca676dd744e44098da3d9be68ebe6c334cfe20c2dada878e2622b71465db4d734b4ff6591b93c23e6ba50b51241c275369a93cb251fa5812815461e988d4a2b3628d89646684ac29576613962f282b28216730426e0952ca20610b0769c5078cd28e8f1574ec984bdae4ce94296895362ee4152bd306d58c15c82f2798524f4e3f56d061b6e82143861e48240b5e77de7489c169ab4ce3a58e0b3fa6b46862321d29899032d84c183c4a1d3c6894e1d1c254010fb9240e0e34e6129912c90b28e04c5b951c2c702529a7a0c434c9f1b165470d373b9258c893664ef9430dd9c5455a6195d162beb852f29812a24217134a284048184620f3dc90d2f182850e104aab3a251936e4160c5461ca365b483455a69228e5d212b28e14d982103725984772bcc911a33421070b2b774c14dcc8e92a6f88c1d3858ca185f2494af98589c9040592c910274c268e1d371c33ca30384228997c9941e098486428978cf1fa62829085cc428584e2c4ec81448522a49a5bd9a44799e58692c9c20d176495196cc8295da429d59431858021ab72275879f2e48514ca1d51e597d39c25d28c0df28e0d11cc281b4733e8705953c660864c92651e5d6561e901254a49a9c5480924488e0433090e924a0d1864931a2bca397694b431879c99a24562e1024306adca2419a4ea62428e39224291184d65094b259c1b6794609060945890595e24c0315da0298f94298d6099265c91295479a132733029571ca12a426a6902b36416b951bea001837c81060b928c5719048ed9044d9c32a4142c12cf159a2a9304aa2a264e8ecc50847cd3540e59227203c80c186594192ccc1a5e70b8d094b83224169619e3aacc5345b6a1225d60b2e6c80845b09a4aa525ad1b3a64c0a8228345925719070e149aa73222609946ae4c165562a8b83021a31c295b28d2d4443e592aa5dc0021060c33068b2baf320438a5171ad24e19320c560a57258d2a2254260f26e6ed08a9a44899d46496b074c20d2c3060983460b0286be4cfab84ca1f1c724d9a15cc9457b44c1f5e9ce04a36574c1951c8d569de6bf0a48abd712cd123f6783e6389dbf3b0d10371dfaf751a6a3d4d7618866158efcb1ed332cd7b12f6c23eec447fe1234e1fc71fc31fc30dd986d8a03f36fef9b98745e0df0fff1477a83d16d340df7b5fab8d2ffea8c35a376a5177de532fc686811f088220f86920831dcc02a1f2c7043ef959b3f6f50ab54122dec704551d7bae38f0eb6310e75eb25561f43d7da0124b2b92c5f0c7043e59292f268b11f9916d88e9b36ed96fd067dd9ebb7fb2ef44e1b9ecaba0e739e8814af6097e0acfbf27506a9fe007ec2ef2bafaa0f7b1cf8b55106a834f69088f0edd9fc086c7daa7a2006b8e79cdb2c7dafee76920d9d707df713644752f3444757fcf0326f0097f1ff82708b52b8e7d0c579c86afb8cbc17bf0ebf76007fce3e84195298c93f2be03f81cb4f71504b3766865d65a59ccfb276137d0c6ffa17d3eb41b7e4cd5a321eafb58a28e76cad62a3484ad4287ee5fdf6ad343933dfe936e6dc97a6894881561ef81188b187cf14317f5f93981443ea79d65a76c151aa2031dbab87d1d57f1d6d6e7b4c51f6912a0e4f79fccebf04d800e7d7fbf2d9cd3068980443e26900806a140226e7a1627010b3f58540ab7ba29ffb690ecfb6475c5a3d3502bdcaa20aac5153f61daf86118b3d6da18ad48a4326b63b16a7d422d1f61bfca3cf6a2fbe81f12d56967b8b56b78ba571fb7ba28f6e2fb9f28541855cfbf8669f6e9fd472bb23f82ed5dacd630cb47e090ab8e1ee0702bd4fac2adaa1d57ff9827553f633e1d883ad4d234209109639c55ad0db7be1fc71ffbb1d10331d4eaa4367807fc45f50777d0a727ddd727077d76f8e7fb44a51dc6449146772c1613ad0eb5f08faf747d74a5792fa37d4fc2e2f0ac4c4fe3579932ce18c7c41d6a79d228ee31e6622cf6e1fcb0ac81ec1393689fac7d4ada9fc77e8c899ec414fb1bd363a825ea50cb4d4fcb47d0fd855a9d8f7728f2b47fd31c902c213c766dd35c90ae0dc4ca690ac7163787af238e2159fb824d73439c9ee26ca14d734f563b370469875be4daf7a826895b22d7fd3ec735574c4124896444ae0a0263dd55215b69f9c3b0eaf1b17ff8abff61b1cd5869a7ddf87d3aff11ff583f1f3d7afdd13ffaacdb8a5c5557abc2c82b3e3fd8629b7d7a9fa2168dd5fef6fe7b71cb47d4ffc42e3c7ef5bef7f429726def53d4ed58636c71d5e0b52ab15ffdb91dc4fcb1fddeabb5be7f4d12b7fc47914be4dadf679a6c2cc1e15dc7387c3d5d5707afb30fc54cac5f84bf3aebc21d74d785f58962c6a1ebaafafc461c3bb4d6dd833bd6cf1afedba07feebbb8e58f69defbd0c427616bf81a68e76cf7d0724daa429fecfbb3c648da559f286418e3d9768f4c0c2ff6f5c5afb31dd345f8bf1f451f47519f28661beb8a612f7b1f4db84c03813fbef7301c756671f773a65f7fd6187bd41fe064142866019055a8146b9a705ae7100d0d004000f316000028100a85c4226192c240a0caea0114800970aa3a5a4224a24a22811043411083200c80300882000001800000c2300c4619d1fbdff62ae26eba29ee702381748989b6e8528981b1b920e4fdc20cfcc94279561952ed9a8b581f2526ddd88277cba8518421c1260eb455e3c559a51523db249f352906f7c5b422b74e87c930919632c0162367ef7e7145a0f7ae1a3cc91840dc9489239750a51130de45d9250d23e5da6b781ef1668649095d7b377e1b215e46ed86ec550aaf72a94b4dee326d83aea7fbfa14676077cf42e99281b261a08224df6aa74235512d979242f504b158675df0547f09315a3843ab988fce8cbf5db3de06bfa1628541675ee73e68e0edd81f63a24950d11cc4799479dc4dc79cd30c4b18569849871e2665a0a6d09cbc8c8b13fa19695f912ca19a21dce5b38ad6d7f5abe5ad84c8f95cb5c7b32fdaee1ba2ef7c47cd0b0dde3a750d62c254c58cedfe61a2f7d96b5a4278617a0a6037e1a96b3b863bc2a18cf27f30628d708dde6b1346a0d4150ab1dc930aeb109bcd084342d26533c2800f6485014745255291008f2d9a049749b4d44af1fe00fee2ca940ff4e9d7516f981fda1feb767f14f8de20e1bbc89b4df3dab6110c3d8babc157e97cc083e6598914fbfec8645f677f08a7e44d28debc96e7bc3235c61f5c97776c749ea840cbc98519aef79d46d7196f1cf6cd4e5b894b96a997c63b20066b9a06506bdda7b8d5661eda011295184c2f7071dfc62b218a63308a65f58cb57bc8a1ca70e187e0dabed83f46b5721db96fe62270cc8a3d2d4dc11aa5788a59c39d5cfb5840f66126b4e85d9c5ee739ed2f05a10810243605e5771f577733d978b56cd60e9682f9369a4301513539077443307dff7bea88ff48a27ab8a3ab59aadcda09380a333b107e40051fe0f789ffd13423d210e11a4a4b7423507f2321600f1feec02be989db3bd2ff1f048036f785ae61f1f98d0c5f3c2349c1ad3710a2620cc4415922f7e2f16d8b216b297b1ff8ce424ee312f8ac276604888e2329dad0b74ed5c29342871e06ec4aac9108660dfb04468acf7c89fbc3e793f407a75581b130ca4d08c8f5d996edf352ece51c08c0f80e02c2927b31ed1ed9030908c8de44e69baed2a202a888d5ab7fb3567f9ac28fd244388c049e1d4e2accabef86d9aa5f6195663850debde5867ce4771d0db47a84c2ce22831944cafd633fc9ce843ecc3579905c2f46af28176f9bd540a68b47ae960a0f1a101058b7088fc9bf44700a89ef75f6b44e7f2a027d894c346e1b6d27189bca1732ae83ce46dffc6af3771cb44238982f308184cb6e0701dc7cc49a66b3d339a38418725f42ecbae343023b5dcd73488655d11b0afb32127bf157f5629eebc31cc71647a05bd39b17346a5d789ca9d46c096202d43d47af9b6ee2d3d105cda34704019504d10561a8d264e8ce3082d01825f8c26dbc08d9fbb1eb161609e2cdb4cd47cb36756b2fdd86a8b967cc2b30b674f1e44ae65cd7e9cd1b291837c1cd77ac4b65ab0a136870a1096e3c784f7a67524282c44c3415de80021a14ea7044ed3333e8bbc44b594679d42e406864996b389ae01e8b0405e50812db9747b7ae3c3638a164923bcfda630188688df39bf0d4f50d5cf3050fb0f37adbb5be3d39f4f7d293b3fc645c19f81217bb7e1f18855213eb523af511e1ee8a9121983342d122df4233fe229fd12e410c8e4faa3924e41c29a453612dc1bf0d7f4244c6a3aef5e3d1f7da4c477cbca1e266930cb6e9350b9f8d1262236265cb49669281da9ab2457b30b0c6ecbeddcb9e3187d28a6ecca6133b155b356f0960e05e11d11c1a2f9aba1052814515b45acfc01032635dc14b76d93cbac96408f1d6ba722b67650af6403564ae3dd77799449f5dabe840f0b6b5e6ee8deca026a306ae4cd91f04b406a28a9bfa8607c148d5cccfe63a23bf17c7c939ea9a24950e58b29e34176de9f7a25850b30e42421d94ef5d6e7bbbd16f403d6f779f2a243276fee9887d485bebe850516f2c6993f901a2250ca9ea9a5eef88334652ccc86df76e93090949589d715449e0dbec9d23121776964c4220ad43788826125666eba6405d0c21d7294581d54f1182fe04cd24cb65a5d376aca18b2e910b5cdba857554d5d5a5b604b56d6ca8cd452b44466cf1f70983abad5d907160a66723106c7125ea55c674b8567ddd20c3fc24153b7463c5338d26493c168526006f03525e37363a3420dca529cf3c1843c8b3f5736a96f3155e145530382464110713186dcb3214e65d74b897c10f13a8683a7a12b5f2926cb8e9f1c8b987b89a4c7599634ac87ce3e4f6de26b24741771b0db7126ea55bc2d3d2eba3c76329e2aba37630c44843a857a65a43ba02cf392ade3c23ad1a58e5d6084747ca98bc5f491236d383a5c037b299fa36f026404241c7aa4b4f0aad32dd9878c49a8cee330090f1fe5ffcbe646cef5d8f462f65b244792ac7c3ab1c19116093e5ea4e950335776ab1c49962e1bd99c0c8044531bcda81d19c551a34c4dd12dc5c93a19aee6da8fb43d8110d3f6c25d4500c96427cb126b50248de696eaa25c58fe58e1686f1b0e8e309e373ba9ad5462a57cdfee5837406ed592779754184c8ebb1a08cdce8bf2f2151eaf45b3195bdae9c07da04c50cd70f2fc8e85003167a82e190bb987d1741e5d81b069876adf895e2e8de6c2c555acf52aaeacff569567da41e4228e3865533d349a59feb027f6876701660fbd06ff5c5d98a42f01a7c362425756147612b2394fd2652eba445416283d628ee3b5a4551136f195476d700502edd824079af50c4034b01c73626c64dcc57a820cd33f0067fc3c575a6f6805dd58ca48149f5ccbf2c850e8e90cb04b4efa2a624ee7e98079b3c968664f21b284d30d12ee0e013e331abf305aa7b8ef480dfaf209a68c5413da982f85fa3daea17024e9d30a16a5ecd00597442d66453b9cb31de220e9ce5d0bcb80f67c0e8537c62d69042eb61ed8993bd9219578e4f572db5ee309d0c33bda6487c0cc18321cc9762ed8f30c6a08a239c6ccb55aa4fd0a9f0ea25933eb32d096e01655450d11a80822bdc3b0fadec7978f3f688a7265b2bce8a31638a2a1b696476adf504d5b0926cd943dc7f22f15444f03819c02c68cde10911566c1a7eb068c560db4e731e1303b81b060203f15dc93804e0ce110d98c158f0586aa243a8d5c07a02081de0ad3fcb7b68e793cabb71eecf8ce181a0b4516902f41b4a5278d3d1f0b652e6ebb99b944c8e66b3716553c14c2cd9ad30838bacb80d88e4007de2984bc4a8e147ac854186787c2b775b22731b9426357d6a15563c2e3fd6f148f873810e54122897d83619c27807839c3e3737b8062d32835f8b3126c1fb1f474ea08891f198d74ca86eb8cfdf0e32675e6d50e334810cd90c45334ed3f2b95a89f79102b0fb43935a5b8c148b276a4a03dd17687909d49f8198047074e2cfed12ecaff662e91562c6937b9c89308b605d75cb7c355b1be2ba1fa893ae1156f0d23f78069e2dcde014745802b8d460c949a034f0366c57fcd25b7bd30a0a6e77363769cc68bc126bdf56fbaab6740be2d4d9f4fb32ff2d4392a52cc9bc7f2620cb8e8677250d453e98643db7c4ea0eadd13ad0f4889948d01a76f0293e7268c36ac6e127b30abecbfb99a1889858e0bef4f1bc4d22dd1b3e5fa6f85cf44e530682b642f0448582edfe70ed51199fdd348445b43448541a58ac1ecf650206192116686cfdf798ec42fc1c948e75b0ea23756baf5e6d271fa04c071a5a53bac3ed848981c27f95123bcff1f2bd70888805a30efd16d3cf8a85151d87bf2775fac6921f33f1eec9bcada6e57e1367bfcbd3d1af2df6571008440315ea834742f5b591f6e97a9b519e668a45dc1a2504b5492b08a223bb24eb6d914d09f5d31246695e8298341e53a04412e7049ec24d1ad411d67701a14e2b80de8a918b3ee9860b74cea09cac2deffad266ca87c68c134312e6097444d454da20f13464f2cba1c504d15433e14b822665a5d7dfcecf79693c40c8313637283f07ef83b4fe013c9a0ed039a883ed84e66ba6bcaa14d7d77e77e78b6a5fb15908e2553722ad17a8fbe3a31c5500f00133e381b5b8de3ecb9a09148751fb57d5323c2270418b42a0e6d0b2eb8d208b272030dfd29bf32b9b2bf31a23041a4005d80c2e28649bbd221ef390951190a1972ae58c827df44829640025b056f1f6ef19f3b16d34b976fb6e55fd9c8f89f284616d00fdd00218eaf619affc54db2038df7dd851789a057d1065697e18b6116f4e420a09e01ec6c98ae191a4c275cde6b6af56941bf3dbf2a0294db8a06fb66532cf0e41eb21d31846d365ff9d92a7fc43a4b859b43a9a0d1d116166f20eb8d83b9d1e8710f40576f658e661d65af0ae9f35ff2c72f7ca901c318af9ae133e445fbfc8097eafe7e14f6078414f82bdc903aa6c28afb06c395abb50c92e466929c46d426d63e848b8ea5b48d7d15a037519d6d74cc9b9984b89006a8156307001433fa0bafa03756bc6a560469b38f0cbd0b3ec385c7cfb85e1ed0dd91d9c266d2886cb80ac04b7b64d9e1964ad40b818e3ec891692bcc852a8c0492a6416a796693b815ac4388efc39d12217109c856f0208de63c8cdd963cc27571130891a17f6134f0dd6365bd8b64346239dcbdbb96787913f2770a8f35e5a1bca175a502bb48e5247085ff7bf597351f97d9752cd423dee3451a50e5ffe2a9b834fedebc03e12bf9874a9d4a8ac5aa142b94d6e4e721ffbb3020758fc89c31acd6e4e291bfbf180c9b776a297f63dbb2f603e9f0771cfe467d7ad9fdf90489b8d085f60468f79baefc8d4f6560e93916f3274591258c0569a84c24aad2ece174cb736f0ce0778921e8c12cc48d2637e7880461e21723d90680896b014647f5b509b6e5db84de4185a1ab2331ec1452b8b1d3519f3f7c3cd669fc8c0f713c7bb47b685afd8aace4f1573fcdc426f0605ddfb79daf603274ebc0900c6004fa8d7904079efbaa5672ad3f85cd28df862f6372edb1a8f300e3fcf9be74e70934a952ef93537d867c568cefb699fab94380241e7b637fcb539c378c725d6177e55b357636e84587f6b629bb9e38afdd2520d679625b8173b1e3118dee08b0f9b02eae6f9ca96df2901db47cc835ea0469585f51984bbf6ab3cb625a2b7d46fc42accb63c5cf33f3a064d163b63610eb9ac582f403f05cbc832981f95eb7d52a4d6eeeaaaad8c9827a2999b58ff1a3c6a10aaac370cd0582f21ab3dbd03655d74a32f66ff4f92b3185f4778e5953c17bb26648170e87cc75bfe68b190f6ca2899e19adec5becbaabf1e96a074072f986ce9bc4c7f4d7edbdbf85abcb055f58c2a1a02c31e1938ca815d5c94897971aeeeb4bf1dc562cfee18c5d33b2b5e1111270ba37da4392cb7c5339c22bef5f598d947a7777319827120e65e37d7c1be4406a6e95ce6a0d66f65d989292c311b40cb8241bb9bd65278a878ea1d91f54e859b497a79ac812ea1861867d93c69879ecd4146d0013d3b30c610f78817301e14f28d8f86150d3a44987e9ac2bd120ff3544612137c4e4f0b78723dc930610c35d848bd804ecec936fa29ec2feb019023c055e286ea9ac139c2c21f327ca86e23d18e5ed93b0b3a7fc9c62a98d300619ccc020867d08224a7fb2b202700db2a4e323251a6c455452ce55e5c1ec1e88c1310e3b785273aa8b814641e46a2b8c179bcf2084229b8c0490cba7b5def40c8121e1d9c928ce6eb5d070031cdf85d77256b0bcf99010fa5033917f6592891d106c077811d248bb59cd31f334323dfc00bdcc6112442e79ca0a82583f47a6b34dc0863e0b3e2434134d822fc53d1af0a1e71350f57e300b253d6f799dfee9e100e69ae822e029e8a5624bc959ce0f1107c20ea29a264d5a4c615da92602ce1cadc59f0487022e8f9180cd76883974322c38c0b55370e0829205dbe0e14eb4c3498c33afeb366e0bd8916777515e5b4035d2f421091e36548a0ef0510b82b7c2f1a8fd050395d409d571face8eacf52e10c64e3fc571ea66aa7a2002bce16b109e69408cfa686280308daf9cc3a99bc07e405dab5b937bee7438ad72975e822d81104b247ae38c1cfc8ff69edfeb51924c73b4812d3ba775110b4749d6c654497b1f489e64acf7c811c28d45177726f87900f5bedc33093cc48d5dfde98c857b70255b111adc8ac7e04adee0c481ae88e6e81fa2439d9c0474c0a5e20ad9497e7142f985003858ec6cccd644d77b871555d8e993ee8613c24ed32cee3d6fa54ff5495f30e3e24a26f444ae7120e1235cedfdaf8191ff568f8fe7b8d67e89dd39d7a3ba82a1c3a0619dc2f886d0f8bf920843fe9bd905b09acf91424c687ab16c5341e0b562e1f5158105260bfe4aa4a10e09b8f555ebce7fdf3afa11e8c4f4a6ce709effc6c75fd00121327cd8fb6ecb6f485ae46fdbd16fd67e67f865f237b07e73f88ed1001f6a8fd80672134d3baf34b40317e7093062c3654360339ab117b0658e3a0ffe4acd816330fd818b7b35b162695a8d9c166f1ec435e291a4cce24173b4742a35980c5dd66fc81765daa655b6e851154547526f0b97a65de898ba3f78b98fdec317c50a2e461082118d93bcb5bc327ad2f19ba3eaa891a7bc100a7b8b340bdcbc34ff8beec2ac7dfdf483a5c58435c8f8149ed02c5d428f6cea6756b5105c9250f05784e9d108fee4c7694a4fa5fadc25949969b68394b9faccbf8445451cb9206e3a4b3f2ca412754684e7e720dee50ae53f9efe4fb1073c25fde01fb48882601716e146187b15543c22b60faff4a049beba848afbd5be11427db143772c4385b604e3056dbffa94366846af32a61832784a6c21821449307508a7ee378e3d5889d45aa8fce97a8d8e46a1b05b9a3f914538dc0c0e59ac41c74dfec298d45ad7c429b344be6e1bbd510438e0708ae4304654c879001dfb9bcfe74cd45c928a802cc0cc464f06009805750be47c5de5b05ff5249d5c2f19797bb5cb63856f94dd2ac78a1fd784fed274944f065b5ea2a3f0fa186632745297f9cf663de9c9f1ef18c38a873300521c0ce4d97185bfc96b90117650004f6ce2c671edab8a04123fd2bd31403bc6843c890c1c5b6719f98712e8947e720f42f8d0ffe183ac065182c007792d8a14c1a6247fa9e6dc56a9e6ec03aa8aa7d43e88207754b449f4c18348f843092a254572e8875b5d8ae8f3a42055c359dbc85432a489466a3d3310897e487296b2c13c11996a24a30771ab904aaf34614ff5cefd4344d1904041bc40ba7acce8470264dd0f6ad5a4bcb2b27122334d826a402770a962d7528ca46c20270aa90f19ec2e042115fb38e05691a96dcfa90432c594bb03a18d90f2af34694fe59dfb07f143ef870fb2e243a9a2954000211237659c42f911093b25ab3c7d787c50409440d8ff90849a1a53ee0f886df9d4c8b3486429029626fea9e6dc40087ddc01f1a9f4a70a22f30fb7881439c9f3204b3429fb4c0a4824da521989e60f13dfd47e2a7e90f391e8035e90935aeaa364fd6013903e036232969c1924f42de9f4316b8a2c5f0e6755b09d689037c85f414e34a9b24fb755a9c9a4f08712dd94d7a76d8494e10cf48792444a793907392dc812e7947eee02529b8c9437a4c9265535731f903fcc7d48f7916d68cafaf3c4666aeaa924977220b70a12493b954186e9a3ed7f6a2f690151223be54d99649b5a490c08453f949c523d9c8e8c94328634d9a656e71c04027206e1838040a641183e4420383e9c3fd681e8407c108a1f0a207f3e282050822ce94bed4ce58f9c55952d0c794d33a50693a906df315e1b4b0e627ac922704f123d0941b268046c4ba29993ac55d75a2d5d91cdd7f9eec326345158061cfd09c83c785537f111a037ab7318e616c148c687e17c130ce84ae8ee788600028922488342212cb02b3540935b478697d334a0b7519445a434d1494d27952ca464942790f3a7f8ef58e9720184ff23fc8102d1064800c4524ca945e27c274315fe2f2b3d893ea603224948ca7ad2c4766a35733f207d98fbe0f9080249811c03e4442cd558d20e425b21e553b63ee0fc61d2913a4cad802c69a7b24b3a03b12d7fc92d4725482e020140276546695291aaf57af27dc4f547259a945d56350bb1bd4a35d9c9762d35f574db4ded96b47e2891d9b46dc49291ac206f1f743ff47f78419892dc36aa86392d51a43c2b4d4e5269b3f001bb754ea4afd38bc5929458f5b20361e5e35a10483ea57c37dd2a539899e669d999a957b2c9ced44e86c5e8ace7b10a0e240d9a09f15fb2b4264d3aa9dd5482c84022411e907a1ffaaa7a12a18f1ee4401f92a4a4244a0e819cec53559ffc2f4c0d67e403c187eb630dc4ba0f25ff947d72013203417ebc204c93f00fb862cd958f9c7fccdd8907fa88d5f4c0fe6bf92c8c52498545e6f943c92f55bae97629555869724ed5e7421f7c90f01f2810f663c64296e452c9ca591fd08290e491ba33b77c28399b6a28a39968bbd5974a952e1091c4ce183aba60e55d7fbae1ca9b915a18a9442985513681f87c544194407e2abab9d5879233a9e6720751e2d589fe9451ec4f1422eb518553ec28e5e96044a37cfa0c6b6ebb4adb2132f840bc9770efb35b05d60e749409b116595551707811a6a5b3ff6ccd00ec0dabd46de5e7332bbae7e4a1359aa6582c9e1953cc6b5e53209bc30cdeb0ce12b5077a9c086ffe402f144effff06feb2c734a1fffc66995375eb2f93bb59412b03f3eb552d8b9db4a3745a4fa1b18e738528d632dc241d31f687c79b92fd63769928addf4328454130d3bdd4943316c4d5ef6d30b6dca0a160d0e29539fe28e2e10bbb38348af741eb782af73ef057afc4c1501a1a0cf2e24fa6e6d8dc83e74d45fb747c78cf8f19bcb6b3bb796a8fb163967a6f9dc22ba4fa66d2c722f6b3b2b649528a824f26b1926c953e24959d92cd6db11c761748b3cb8cacc5c2f0745f060874e9f36489a2480c69cd324c5e0d207d8c1bf3b16caa36dcc31eece5adcb9317b479437c329017315d5b68b516950373e6136303c5ec88eebf3046fed5addb6e0d20dd941c77816fbcde72ef7749e098330a075da48373d8cebbd399f63592f55961b231c28a8e5906664347c413b8f50ce1256b02bbad5107116a3cefe7d0496351b7464c0a81dac64d9340fe1ecf960b09a89d0eb9cdb119f41c3bde1afc191ddb482598309ddbc607b2b1493dc0e167d064a4cd487e05d9f368eeff592199a938c1b2172f4c47ae2ba6b9e0c15721ae893318253518d7e453407e8b5b711bfb92d5546410b41cf3ac36b935ed1df55204925feba0a182baa0c66611e53cf08aed907be83c228aba8d3985c746210c339ab26585c10e2aac8045c4ecb349b4160dfb984eb37276c36bc845400c2a2be5a2760f133d106f49d5c093c22a4850e7589b7e1fc74e2a0e71ec330faf108d294aa0e0b488775f2b62678b8bdb80b13ede9ac4a211d5c77cc9a3767f924dbb9ae3b01417480b72ce41e54dfbf844ad7d1c2f32e7c51db70b7482b2862cae3521434f13805dd2c38e3d37ab05948d736faac815d24de8ad37b376eea788a1ea610413737f8ce012ae62c871ce58dfd4cd1d029f8c2199a1c0f2f6017b8a284d5c006ff92b452325750727a7fd2de402226f0f88a67e7802e784fc68875c22862677c5d0a720f6d6e21d7056abf27f184a03fac2b7e1f107c8b01ff4ba66523b7000705aa6c20112d75789445775a7709392b3571d22d2d761191db00201b5205fab57f65aa0cf68475e968eacbc58b431e999628f327244b6f2e6fe7a7947d1e8645975c11f8ea562419ad2403c5eb015cc3c13657b44f4a56184bb93265780d28ff787b2971affdfec1bb36677317bb9cbfe4cc5e345aa0a59657b914cffbc07c16686174995a9f64abe27197544a94b7a874a45249da1c5e59f4314b349362146c09bff1a2fc48a6921e1d0a369b4138476fc7d2dd3f11be4e56bc4bd591acb7e4e2bf3066ea3801e0f40bef97211dc5958cbcd3ec150d639cbd30dc0b4c8891668ee8cf4da232eaa65409e41fb8467d43a0d20483576ef198fae60489b12f4a9ded2b9120429470f18bac2d300234403f45bb409d26b11bc394140f97e35fc044dfcc871e0dcf939d248af949b2576966f0b02d6804b02f3bcbe706a84a775d6426d9711de303d8016011325b026cf9d6ce7c0122c42b256eb55ce800a0115e4ca1d33158d7fcb3544fba901c99bcb5a2279dbc902a7b8e5bf62012c69c0073f8540088f8d29e8ceb16f83ced84b744f1124f62eb3ee09022d5d1d3a7e84403633acad0f49b16555b8681983d67d58a07fc081fe23f3eeea945b72cc99f26ecd747ed123d3837058be6c2690321458a1250a0f5f73f9a34b4926a459fc400ea4f7548d76fbbb7d70fe16f2deeb3e6abb35d408c73900313cc60e303cb442d48c4d7b5ba50658766d794db0cb16b08488a4361015f16b09131f0088973ea1a4169b4ce9946553e54056db4ac2794b482240fcb466d7bb58bcb391d8089c2737f5400ac98ce05a12ad6be593d6798b2ed6f4cd6a87a2d1930405f83358f98bf5ac6cd5775f545ec02b7d312fb3cae37c82f56c69f1885b47c619a97abfe660dce49801be970159831f12c143e72c85c46653a667a3f6a085574ac66fbd9d3265e7ff6123099cd43faab91ba80ca5b78652254fef78f01d3c322f5d350efbcb4e39b43b65809b66480baa7a2b34c46a9bc0bc8f481d2018914023a95adec65af4d6091e92d96d276d9a02fe0711a7691a032c5f5c434b529305a3ac7b3f98bd3b330a6cedfe3beefc6fa18281c1fbcd314df905bd8023eac39e001c6314c499a89729ed2f149bc2746f10ad4f14dee12f92c331886cec8aed2b50a2818a288e49a5e1743571ec19574358e227d67fefac9157ce8b26a59ddb341ace6645e7268235b9fe0528fcfb65d9f2c15073069037051e65023beaf3de991f7ca012219ba83f9e37d6173cefffb1752d490a1f144cb4d3af1565d6abd4f6ee2d70f85fcb26bb4da4e1c677238b8ab1cfeb6f2ea0c0ca3502c4680dc5b7048d87c6da1f4831c08cfa48c298091a164858ceeec15f16fe44c230a8faf7370225086dc92c365c8a80d123fc13399053c1a642b7e17305179dcda8e3e51105094fc2ba18629fea54518d33052d097868c245890dcc35084a58d64d584d1daca380ea53a08b26417091dcb069f856081a301bc7c308c5f3d3d954383612d213328e370fd99c2461add455057f407c101bcc4285cbb48d44622ed80e6950f2b88362068f4686df927839d53daa8f7b1325aa4c5e19569f130cbdc372eaa6648a1528b78124d292c85e17771cc2c8c81dacfabb86ae5e69f81583fb482a23f7b7d205ccaa243fc0699df099bc17d4cd68ad86e339276f060c8b41be1884804d349561ac5f76dd20d2a9bf1de6bb987df3dbf27602969f00aedc1b859bbf73bafef0e8a71f30239775290cdc50c7f8eeb44bb1d0ea95256b6bc2253a89005dd3f18c30dc5f0c0653d1b5f338adf83d3474392c390e6dbf386f4eb90d5335bbb208418393adf9c6a653d1d62a4041526a0e0398b304ab9b3a33e28eb77130582348fa7a902dabd9d82a05fbb95a6161f552b9f8ae08faf159316344691818729cde7aa5c48d2177d28a0ec756c12e33f77bd2a4ad09f10230a4957b4049292b1fa07425af440b5158eea239d83aab14e26774bf5390f093607f46a75720ccbbb3d2f740bd1f34b3550a2c346956b6aa4e27eeab0b1c8f0b9d1a0b9322c4a0880f5bf606465af65aeb435a35d9a3c4563c11bf3fd684e773e7cbf8ede342f1430449ab2ad1700be0cb43f58199351a7d67174fc72338c0149873ac4c4a3aa979c48e64914c729cc1455ef2ea64313dbb1edd4b7f22c15c74a75222b0389ae68e439c8c03eb0fe87bbc5774f642c5bc22a9a5f34e0ad702cc05f8c93ebb6cb263b3dc7ed4ac750d6ee31257a409c082951283a21611e13a906e44c1d6945bf48a925d1862d5486192e5f848174beb60cb3002a531b2c70cc4b43494614ed307b726f8322876c0b47089a0c4e69a8084d0c6a405e69bbec501a663744ef70d79c47ef98ac0354fd5c3aa26fc7645c7a1724936b3c2465c8430a77fa60c39ea3c006e7cc7e8f529c05db57be86597f66281bf9894c34369d3d8a3d31e75dc98937868f10aaecc3fb1200545873fc4756663ea6d91079963f7bcfb2112cde4ac13130e88b192cb7c24cd52de49549a11cb8f61a46f6cd463394e60250bbf12a92de13277a944c8a7d9d30cb41a86ad6e2f3493fcce771ca4035ccea9c51e8db9cb578f1246cc7d0106c1465d01ab3187e2ae2b901d0908c4f5a9220ba709e3039a9f8f2167b8b512bd429f0b217ec536cea26317949ec1f4df6b4d28227900b45f4d308637671aaa206280ebdd66a9e760761dc185df31022526ec3c31df6c3e564379d65ae824343c50404722d76f73cb0f544ca85aee12545ab4471f074df58bebab687f2b103ae1d602ee54150d7616aa6e3730c634da4ab771f72e9026d6c9324095d906697b195f5d7c9efe0f34f86ffa7a13ad108d5c9504d6b42799a4793c30c5ef2ad6fa5fc80580dce4c775f6521552b01954932b3833703b0f396a758c77ef90040a62abadc751d4bddd90a7e3d8bd49072cc1650436f9881fce405d4a314e83bc38191981a2cca1f91c627341b6b19025d831d9ed71c36995c9dd0548b0a34ee4fb33060623afc08ea30a00349748222849002e8f1f22514f4d13021f106bf7d4a8e0e404f508100d8dd17867e667f4d32ba5fffd719b8146acc83898600468fddd052fc84f8a71a7ea51486ff99bdd96075b86508ed53ba741249d19bc0a5870f1ef09191fc5620f1c3b64a7e6ce13162561000f105b5e307288cb8d4db34fd47e07bb331ef260da8af14d51a895122891af145649cf1dda55b1b73bdcdc6e990015a6b2415013be9132a02c159a8230c4ccdf5ac31b8d420f15817c17b4f28984a72cab308c03db405348c59dbe924923186d9e4ed4c9470577d879607cf8770a7d2f161444a00acf0f188672ef670b01c4129d70897c0ebdf74eb54fd735c2d13157eb9e8d35e52141613fcbce95df44519f11f8c6701967185156072f72ddfb1a05d9ae1eb34ae926ce0db58afd88eac2522907ae4231bb8f00cd309a013c64f423fcf189d9b323f1169372d3edf97e59fe5f621de5452cc183f5c633b605db9227482634f1558258c2ba149634ee756060c729c172c8cf1d11a01c30a62961b976bc61050874a010bf887322f8e41275da43c6ce7aac0aef27e447106e65426e37de5ee8bf4bfd77ae4fc68f54ecd14b6680f8056611e29d8060ebce0bff989069c8128ab3af50c2ce522941da09b80834317c937a6e3e43517cf525ea4cdf975b4902f3390f244d04fa0aab975a30145ea503898cd4157575661ff874046611eebba07dc17a584c619312e8f24f8fedb2c74ba844ff50c24c36770f919500000603c0c72a01da49b62670632ced47531668811208c8bb06e028025a9384ec2dc996524a29934c01f7087d095609b32a3d76c43e1f7b6fa0b7c0ef18df77520e568d5ed5a4687adc77135de68c87e79c73b24738233f671e86571520ac180185e5439212248a84746d893280f2cffb493b41aac11ab5cd7bee64502426b10089d79e5b4d92f017eead8b6057a55e411c86fac8a88b88ece670f8e7d77bee7098d775c518bbbb9b5ef83007972cb1bb359a60b71adf7ee3637856b6d50d676a37395a0d343fafed529b89c106ebbc6768dbb88e46ec42ca0bbb4187f0badb7555a74aba56f7d565d12fac731cba9d7194d22ccbb2ab3a3950e6d24f994bcfaec45ee8eb49cbead057ed8aaee351ade116d3b986d29bfac2ba3333bc1ccec7fd5eadd57df8eb55610e541d3a86cd4bdb84fec234ece97453a012f50755e2e4a10658a7af2614e972f2d7158aa445e55417f5913e825dd4477d94a532b6e569d25b83fd6a2c7afdb27608e723228d7278f188d743cea8570da1430db61067e46342edb9e377ea7e39852af9c14a513e6fed39ec7739a957ba2a1901bd9bd8e9fc5ee34de7f4193a27bd349ecb71cd9c0114242d28465efa55c417d267c47898d2ecbaac858e41cd426a7bf52e7a39d62b79812ea0c9e392d74ef7d9f1532a00e9a6294925c5aa747d37a0ab85831e7060f44de70a8ee353d67939d45fe700e91f630cd66127f4542a59c943ae4b21743880b87f3e97cfabe2e168bf29e331fb4d990f4e9a1e1fbe734f2f642cf6c1312a115e5cb78a30f2dd2d22bc7c67007befbdf7f85df8584796d66021b1acb7797c37faee7dd2eba7843a81dae79066b1c03233d7105d2ae566caa584bce0871f6a2a8ddc184b89dd688adf41c8d687fcc0e2b7eb2d60b36b1181e4b9458491d60dac706911116542383d4ef9450cd792c75b6362ba44b09d2164478f1f2f03c1431fa6e3d15a6bbdcfaaea5cb11add550d23e20822947c7d18cb539df3d06fbe8d5802074ede653c2eeb61f9e0532fa535ba4ca9a49b1c624fbdcafb139f5e7702eb2ed62bca9c34c4932f1e014f95fc16b71facc45f855c4e64cb6e37433adcae260f2912bcb0594da336c37f5d95b26eb0d406a6e35d5abb09b6bbcc3d75da194fbdb45716c3c13e9f52a39a499b81ac1bece65eb3faa2cb0ed7420460d6027f741adda5e33ec5d77d9a3668f21b7d6803a487b0061896bacf6cd7a7e77e32d52836c3fa525fbfe76f1b72daf69edba2bbe74585cddecfde10f59e1d52d5e517f5e8f446e9432ff4d7d4a04f6de8b187b757cf0897932b08aa440c7a5dd7e590fdf9d0476dc35ee8e7065d470ffdd47e60da1b92cef5511fa98cb5465dc3e6acc7fdc9abb6a5be6eeea4f9f09f30e74c02109e1c566f8fa7abdac17f721ffed355991ce8e4d24d27977eba43afa35dd6534d589bb4a1bfb41fa9a76d87aaeb2f4a481c6c78b12d4a494a6df42e9fab4b9bf16e36a58429615aac5ca9d2ab37630cdb8e69a149615ac6b0ed1b7d8a592509840a1dbc2ca42af56a56a55ecd76adad9004e14bfae76f6a7783f07aad52db1c7ccffbb92633a2d0c46957c7db861e12d98662142cd7bce8e40ed529a4935e4b2f469d60a25b22bdb05761d8ed11d147bd349173469d63ba62920893c024b007eaa88ee76a1775e1b2c4a5cbd297265c969cd0843ac1b644242a8c5fa270f11205d342ab605cde39299d036b547a47afa84b1375d1237a444dd44498962e7a44f611d147f4cf44bdd6fb4cd41d9777535c302d483f54ae714547ef6e0d2faceb7a67ac05c3e4b04bdd0c28d0e774734bfc4ee39ff1040b243dfee6964cbed439d14593912e3269f479795ede176a7211be745b9c92e3e2943aa73ae4d239b3dd0c3090943ce78fd64ab11962d8e94a339e601d0fec37f79b9352b7bcf31c576175da6a52e4943ae76d4ea9971e5113a2cff9c7cf2d265bb87ba9627133dc853e622c724acfe6f512bddc64baee06af7b69cb1bb58ac5cd80174222ec686808d72bb5cbac5be2d010ae576a175b6d557245d615b511fbd0c238778e9d3198751818eb10ab582a968aa562a921e95d0a9e5b4e9c40e78d63bd31ee9cad6e9dad6e9dad6e9dad6e6334a04d3a75225fb5cdda59312ed45e26192f9fa7ead5c6c4d8ea313176c396ac85f16aad75547541ef635c47db18944555192fb7d0ce18eb28945d81c2d81973b7d45bb74ea1751868aba3a0c9a79f34db2bacbaeca7bee96ed22f553b8d4828477f387aefbd57b10c0de17a25ab57aa922bb2ae28dbe0cbd3093b393f1bde1856b1542c15cb51d2105ffe00cfad21a67c57dfa6c31951d15174831f7b384c8b5f99b6d91f1a82ca50a80c5bca1cd3804cce59965d8e658e05bd47399107726e42619e619751f4ccbf3354b6c2cc4e1996a132cf9c76e6a7ec5ecf2ba6c5cdb82ebddb94373ea4a9e5cde7f3ca9c13daa1215cafcc39e774589526ca51d651be65339bd89c73ca786731307ef218cd5e94cc29c326160c52283cf9de7bb41f103f0f3d85f0baaeeb3964d375410883de76f92585a8f20a786e0981e4a487cb8991105baeabc617f6429d321fa036a15e8682586318867577a350a84679ff48bda933acdebb0d615a3078fde0c94f6ccbd5187d9709dbb2657e22b2afa73ba2e997a3ee66ef96ea9ed6678c5f77b397c7d8bf629cba8cc66d735d1ea3c168b2a7464f1976b7367a5a0d2f6cbd3f523f7dfb917aa6ab8d1ca605d382697972eaa94443de9edb7e8c3aa714887f832fe49b7b1e04d22fa08b10474170f9fa321a849537c0732b882719cf66837627395d0d09c3eee68a1e528c37a56eb1b7308e5dcc63346e1b98bb9deeac7eba9b2bba346c1b02aad7e445d815fd5d20e7d365c5022192ed5902007427f5915236638c40588d5176ec3e2263ac11f31afdc8f6c9e78c7da48f3a27cef8a4b776720680d78acd69341bd3802ca3e6c4bc8d1c8e76ac91c0789c306e8f381cd323aa1bb3307df4115a6b61dcc278b4f1aa6cdf6dc7b3c18a9189de4611c3fa6866d353f019e735f3d99c69472ae6ce5a3be92b8c8581b12e3acd7cda4f2e3587d2eaa98f6018969218bf53c13de5a9674385cb7a36d037c7cf46eaf2b381329c4db9cbb33ee2666457e5d7d426b6633a8c7da48f1ca9b58ffa88924ccf1401131d12ce089a9aceeeeea90165b57b4ed995a3518dcee8a50b75edda0d5fcef639dbc18f77fb8135ea94f9a03ce36e6e7759d450ce305e6bcdb22c4b126d8cb5baa39ad90b546366a3118c7337fb8161edf1ea083818de77a73c8bf18cd3b097e855920f76734fbe8f784283599c037abb067012cc4cfc14d54f01fe39d073033cdf9c096a7e23c1b3b4703f06f8779940da6d80b75183592c166b26c8e9d9237476091d8ef7fcf4f1b946dbf8b0ba5827b7b0343737ac1bea5c8d5512b6d53b521f168f398599d79252f4efb925a5c8db991458c7cb9392e4b5a434814a9e5b528e78ee95eac73d91863b54eee7ee2beabd0a1fab098e19a705fa76a894759e7befdab987f5db01067d36763c9b764aad4da5dc5755d816289714541c503e3b0b0e07ec611d77736300033c5319947d3ae757238467c72ec6c1020b0e07bb661cc6a1c3cdd831b5c082c331019ed1befa2e5bae44f1fdeebac0384eb03bac03ef89711c8e773137a37d5e15d68771da29d63737353534345a0ce1db7d5887bf6511165487a2ac43db7da87ee283ce419fc82fa8b1a1a5716aae4eece686860683fe9c5e48efabd141372534411ecedd499f3b87b20e75de3c543f973b771768fae518d59e3feaef6ecf29ed95733c2ea7ee8371d683e5f3f971a946bf71dfff34f7f5619075e24daffa86d539daa6bd8a94d412df4f28f9e8ee5dd6e33eb2be57af8a754fa1e4111dde4df5231dbad4d8b9a4d3475e967cbf06427ececf356e6e6868ea66bfb8d1e585b6690c9b99a1a1a9a9a9f135301616964974e7309ca3681513bd7d2605c67141df56786865f45c30de16daa65d473317166699f929e9673242e8da6736cc32c97ca3364ebe6118b551678e5e69346df35ceac5e9be031d6fb0c2b858ca73152b4f87b6a385b6791eb517a0b6810ef4a672ce9f03eb951776a3dfeea2770f98f168973d3eedf002fdd0cf9e2668c52720eab9e58416614427b2fcf5dc72620a2d4a4a92a770a249133e605da184e9597164892278b0420826ba5042b970e208ea44d26359d16ac2054d20f942590aed2281309e8041161cc0f0c1922450b185143468000695294e3041110db660c208efb9c5849518b4a21cd11ac2132c2ae48c503071838c091f34db18c8c4345154831622e0400834a05a30b102c8c40e93091c30cb50c0bc3c9692058c9767194bc60241d21721c2e0a18b264b6e8828515e5e2f5b515a2fb31d29254b0a26a06022c9f4046b8a2a0f4b15568bab38426b0a15620821094528972c5a439082c310969001b30e2fe1e555786e05e1e82baa3e8cd584554d1ffa7937f73ca6d34aa97f80fae5ecdce5aa9ea63efc575ff37e603a7598f14c37aff5898cc38c23bda544510b085e9e7f7a049ab7330c639cb80d4d37c673e76c446af88c47134dca38f2aa644fbfea753467f1f6bcdf66524397933160b1584eb0b2b8801090048106ac160f598ea0c28b227470240c2c84a0e4634b08358061456929a1e4b1e7961249b8c896deb225ab89272c3ba462a1b3c46620847eb10e75e819eba4ea9402f876202e806f17c0b74300487acbabe2f1806f7fc0b7f318ef3360b186d044600de10ac38ede5f5028b00dff869a40125dd8861f5218042be339e3e18177cef0b595f18e88255c77bb873977d9152c203ca2a4f7d8a912a42b082d25d439eccf3d7eddcc19df1f33b08e0b8ce3fcddb8c162ad56eea99465e560553fd706eff09667a5c884aeac1658d84aea81d5c446e7dfbc267ef419176b780121843df08a73269024035ebd26fad2e5b9f5832b9fc473eb0749da9dfbc23aeecbb3fb892eb08e73e1a56a562cc8ee188cdace353f28f27223e3c1584158fecd39b10eddf9cc53411dbdb2c2495b2055543b2b08eb9eb5c46e944b2f412fbdfac221b92a3a58d60c2cf59ec238ce5930b05b2f29bd235272de4abda5b9b81ace88719ceb68d60bec466974b7fa25586c05d6c0318ced9c3879f7e4194a94efdd19158cdf77834fc34a62b7d5dfb0a08ecee91cd593d25b7af7c41b83956725bee2e21534b29c58e933c61863355d945e946237b0584258e8b1abbbc93337b594f2bdf7e6c44cfe4cf5eacc744d3925c558b0086531b1b19d95643b27730ce5186ae8b38c526a4fa813e653ab0e9b7113add8c649d7a374c6388d312f866504ebd4f105dddd43356abc722f1900a1c3f75846ac7d6e2519fdebe78818c73e265c91c262629d6584657fd199c5d7a5c418a31c621db3dd3dfb3a0c73acdb08e6d1e4f2849a8e9a7eba54e8313799b40d6658a60d3d56a5b774a963c6da3108483841220927cfad247a7898440e53648c43a6f3b371f4d918e276e8a4fd3c7af4785946ecf386168acafdde7befb9ee14cb06421d85fa08f6092490683b6357bde2b8810ec8d0edeaeb7ec1b133b9ac2fbd4cd774e1e63429bf61d570edd15be81c55eb884b5d743065073bfd390b0893c9e43b5ae89c1adda4b1cae4d4647293c9ab5f15c61c2689ed60e705027fb33645b3ba91fc91956aa870e907db5e6b8e1bd7f5c21249508e383969d2031286e4c848513644c88f193ab081176290c242b2db0d5575b657f0aa60df9ff8427af5ee7b3046879452eef2ed593bd650a65c268c9a62a41efd01c518238dafbaf0ea2643ea3355bc2e44aacd44d3b52a558c4f48af5e0cecc653a2bbf06cdc804078e255457a553106178a58940bd0dbb15c60a748b690cea47c8a6d52a12f21e1e49d14cfad1d5491e145872f6a2cf4ca29714dac3b2377044324242446031b98261676fc48fd7348e89081dd5827d8ab273dc27e8fafc0588d87d5abf6877a44bc9550bff3cede953a9e8d0c29d5bb271b9c694b2e435dab1a2a7ae90c878c5ef670af9243462fe361f5609feb00c2339d075ed5bba798f16051857220f64b88bfbc74ef04871e3e23f4b2d02b365dde7787e9ba2cb078b01ba5efa99eeaf9bcf227fe73eed142afd8553f38ec2f09068a7ab9a5eb727e39a1bedbe53fdc74d7c5d5b9eb72ce5dbe5155cd9c5d7557df4d06f64bc5f727bef38bdd694234560cec7683fd07f6f38673376e08e9d5e599b6b197bfbc52beaa5aab576c8a941a4cb05b8de8ce8abbb2c571715d3aa73ae611bb5b1b7db6a35731fa8dac3e0cc31c5e8e616e673aa7cece4e284ae3301efda6734e6e3d7a7487d26ee4c83416b41d5a0b33bd8a34ac2236bb3cd3aa9fb2edc64716b0a9e3ba91a373a8c74b734b58120b88d66870cfeac10afd46dd9f8d5751dfe0537704945e459fd185f524f72449896ba223ca3c9d1cf6c9273d9d4ed529c738dde4d167dc344d1505331ecc5a6baf0ac681ac4f87b13eddae60dce4432ff4274b515ae69c9d86fe9455a7af5e93269d26cd79a7c8287640a484a250633db1d219ca4de8e5ddd87fa4dea9a47314529bf62aca88823835d5ece9f1a553d5bc3f5e1e3e4b7937197e93fe23d5ce3ee34b17d2ab087df0fa51a4c7d2c13e67cdc05225979399849d9192f4d68aba28c360eac9e77ca1fce2d831330f8c3117be868e5f3ca97efaa3c3df489084a2014d3282e439c9062e493620f14a509e5b59ac6471f2b136811f0b929d1a75a83133c768f267baefe6d97dafa4ab22fb5312a5e6064dcfd088511f9347f50df35eb5a5339b4379b949d6ae41ee65673eb00ba566aa9555303ae6f1084a1ef32d424d08fecb7a609a0a8b4097531fd7954ea7bc3b1e3afecd23e4cc87cd9584ca5db9a61ae1c973ab0a295520cd2b50ae20a1516294da48a0a76dbe7f561f3bfaeae35df9a0d249275d318e36bd4ee72a4a7df5d3e15dad9a4c9728e734944ca7d1c43ad6b91cbac92f2d08f5d7ed21dd69419c5be7a58a5705d1d2f3d32b465e00cf2d236c7121f7986f73464de526c5347855c7a24f6cce395d4e6cd23ae1bb5e10f83eafca5d7737eaaa9fd54fa7dadb543fabffc2026decf4fecce77cb35ad150628350fca41394a624d5e78e679cb3ab9c5707dd95d593a33e087cea42f063ca4493aaaec7f9dc867eea00619cecaa82dc6fb087e906b9aa78f9457d3349870c21ecb9facb4df0a23ade948e7db6a008448faa379dc32ae8cf55eead6ee6049aee683b5fa04dd270553fab0be4bcefcd3b41f5e17f4b7fa504811f848a0e7d73734eaa92ae921e574ffd5a3dbdcef99cda5df5ca65cf0a12aff3dcb24264842a4648fa9b1b20ce99719e6fcfa3bfb85af58a37e9d16b843484b0eed9fd455fbd2aded5c31b2318e53369e5ac553cd89dfbf0952677f70d3dcc7c44e71b24f3d1ee6e90c7f4f2980e7d5e2009f4ba8b607e4de9346060653ba5cc99ab4cd59dc66ebab0497fa473865593cfcd6d2c542c7d75da23e4de390d18d8e61ed5a50a029f3d08f57c1d73a76d41ae07bd41dccb7c40e7db9aeaf2e9f05dd5757f567fe9bde99563b6ddaaec80589a820aa26f7f416ec9f973ae21c63aad138b487ae840cfe10b42bdbc9bd3dcf773d841dcf7a5d1391bd497c5932c90b6e84078d8a7a1fdf27979cf2dba90bbfcf975812e22cfda76f9d6d267952b1fdd1dfd733805118a3e9f4b1504bef320d4bb5b1d663ea4cf1bc4fd75b7e7d0df0de29eeff63c62a8a7c19f8f772f8f19cff30883b820eedf4d7f2ee45e02b50bb9a0200787a85c037d2a2d814ea5587aeab252ec3dd63fd6d3df582bd028c20639960d7e39febd25febd57e5e6af8c47469eee033af5b8412c36bc4e331e68f3ee0249a7d0695010f7f36e1dc47d74a07885dcc30b63132a774e90a31184dda09362cab7c320eedfa5d7020e2d952e4c134bbc02359f5b518441e54b154b10438927b66802094a0883ca0fa83091429778439c337ec9c10536c021090facc0c1135cf06060a292826bc9f342a5064ac5045da02065db04a52d680bd5c47442521338a844bc5613538b887782a2b2c064744d305a44b155821963442c81a371248a214c3844d124d2c0013bc1952850294252d1817ca1091cb8d0011268608316ec48da84975498bca43284b4cfad28aeb4a62cb5a614d140419c1206508890a0a50ad1168e424b06b2b5e4d1286a45b1c3c7e756144c6441c3043472c8a1832e96ae2822092642d02f2ec04b0401081dd8c0881e6831861731d0b881c60d3528c649614e8f1418dab1c0d08ea351c43e2ff21d080309f86530b0d3ab0a7243e20ebd444c3b942774aabe3d45430441e01dd7f882ccce906b872f730ef668dae19dd4438f9abf38e30c2a0d2226ecef3d9fee8eceaeef074c8e093bc347a4e711f1961de9ecd2731431edf02532ed48cf410222a61d79894c3bd2397fcff9134208111111116b4ca6576d73346ab040ecfcc3eeef3c887321444497c9f49d197dca77de5caa739f26226afb42f6c7608d6183d067f913f4c69037e88d21ed3b0fd24444cfcf43e6e2fbc341197368e29a3caa56ce7cd8317c3cecad6d447ae0079e3b9fc1f4ef7ec0f47c5d03fd30bdbb1f306dd7733ce83b7f4054764b8e9052c5eee3887ee8ebf640ececaeaaef0fd3b7cadd1eface8304cd77ee889e61673c64f8fe30b94be7a652a9e67ec997eccb677ef94c9794f2f0dd86743411a23cb7887004118c3ef5a2e678c2bca41947188cd22e16e88a99c38cc7e5993fc7dc72848117a38f067a79aba9dcf47ad280e80de2de3d7e0e9e9c71a0a3247dea0f4518cf2d289ef0530b9240cee596f9561de87220ec98cbab6a4c0bc2dcf954fae95572795784375755b657f06a5a080610e47a5809f88bf5cc381bb788f0c54fa1003cbd29e9d5b1ce36fd4d7ff33ac6a1ce7aa96dfdf4b974fa5c4a8df5d24d6fabd5a77651c66116bbc92f4dd5f3a8781bcf198f947703f24bb7eb37f609441427cfe911ef8afc83c2cabb224f5ddbdcbb9e04fcf377753493a21b9e3bf282c4911a76a8b6cddfd8a94f0d883ab5e1a9f497fdb822ff1cf607b9ff7135fcbb5b739fe665e9eeb7fe5a44e586d2b7985edddcd4d4d0cc0839e860d63dd7670b0b2f13797fb44dcbd0850b928c32c545d85f5fc7148dd7ac6454331a1315bc35979201801434198d4991efa870abec1818548655135d4105df6eccd38533291aaf59ddb06adcc8d1368f8719277aabe0af7d827d1ea3cd70afec45655a8df67c058d9f8d0a5a149b8585ae1db69417004d6d601d19bfd9678c5a4abf58e72789b9195158daabd7a39f16e81e7410fa36a7f4aa610a6a356ee4c01e17167a8d5e65f7a1d7681b3fdaa61dc3666668686a6a64807e4306be5b06ef8f5ef5095e26468670ce2e39c71041ecbb1b34c78802d1439d20f4211c220e01dd183b43d894af66601cbaf22fac67d34ea9b53fd88b6f0fe219edac87648ad1b7912f98bb33b40ccfa1b3c0f800e3f48c2e2c16847e52c3ded01aac668cc3b719cf06781e80a35006dba02896e11ce9ec881eea845df4ce9add953b8d8933d239d0953ce9a10912236df37c73475fe3630d66da303b933dd394f578377b6d8e9528cfe669f6ab56bd5ea0be2fc41077f4ea59495123179143e2a2bce749513ef5ac1267a457cf0888907d14ccd89c0effa0609958dfd899807314ad72b0ac733abdd381715cff5c05ffdc1d391cedcf3757f40e05ff1cb6bdee4bdbbc775e94609ff7601c41a80fd609926ac177740e7f773fc1ba90ef758c0fc618639c8cd353d2e0a02bc1c310a45e8871dae7f7641d8e3570d4394727947452eadbfcb7848594524a21f5e997976a37ab24ac20dfbc4789c074ca39676668686a6a6e6ea4bb7f34328e203448ea7b76774369e49dc683bd101111fd26641b4264c3bb8cc78b02d16f448a107dd010d1d7f0cf9971a6f4ab8a753a1e0d43440f31ca3ad70f95e0215116811bcc08d525f10009e672f876ac7344e0a6d01aaf734c36cc67671bd13714f44dc6db6a16c036ed323c1bf1062af062082fb2f000073e1801c798f30a82d238da01084964f9a2872876e0620a2eaaf8186394589ed8e006258200e34a0b7a8a844cc3c9154bbae841912ca25425f10757781104175d40e1810b1804262439bd2e7c403929e495514a29a594f1524a29a7904ba28c31c618638c312a200bd2143824f9a1c8869dc8828f31c698821d24490104125e7085879d88e4638c53a6d0c373920221972065289670905c04d14a381c283881d28322508650836b055c3cf125f052c1125d3229a46ce7a4434829a59452be270cfb09c94209484a40c5073fa002b96042146c490d4be9a46059e2030a7ec842c90ae00d98500506886631b208c1845296294d205d2958020c66249c730e197971421282580297221cd999473fc5f8e9347342e841380714a1d583122c960811c68502a47e02051d4ec0e58b134a5ec4600212d8bb8e70a1c5bc7410860e3ca082094ce8200ce8840b889631c618638c3e43a90f766084092b56e0c4071dba8831b9307201c19d20a907151479d1654b13700829158878197181022aa7fbb1431849b088228b0c50709d400946d95bc20d4eeecac1cb5ce2be18239b37ce39e79c73ce39e79c473fe79c7342cb54889448a2c484872c4a98400948af077372204a148460e2e4053960e22ad2a15b4ae0614ed8c48b49e2c3020b0f5ebca088154780c14ebc70f8b804167cec12c65b82004abe780214528c5064041cc2124e10598a2594402e60060fd832258b1bccc0052f58c27503174ee0027c983405c5ca1caad52df591239471da82be75a478e619fd6a6413aa8addb9ea67e69f6b36bb0d4980dff10d3f86c282ca3595461276e3281bab039db341cc7994e8402664557951ad07cf803e351f8c03634dafa0af9e0d179e0df4db02e3d058c2f2cbf00352cc5757097849f6435261787ef9e5a8633914db11515f0482dde89692f9e83431d6f42afa665987756aa2437a3d9895d150efe31e225919cfbd86728ff6545025ccab780626d52bea97cc5fcf1c4ff79d648c33bd8ad137cbce631ed32c8ca98961d42c9c60a1e4ab6b86723a3b16dfe560f603e36de87a50b9878ce00844434c3ee4f9f421d28710c9b1139d08cdd10e11ae9174131e15f088e8789050d8a95e2766d286f0959daa0d79c04ef57a61266dc80076aa571366d206b0c5171467d88989f3a90d79410721ec0cb99c04d48710692e76a617350c75c7dd21433bedb56a2a0af04e11deb2e35ce5429177b4e39c6627008ee6d288ded1ce743aef90a11de79cbd802262c73991e87a4b8d2ef32a1e5dd965bed9a32683dcfbb8375d6ed2a46f431118faeb3abe618fd765bee107e98534c8d1e03e48c697e969a8a9e28d13f6933cde1495552f38972e03838bcf190c923ef3b3611c1a4ad84dc6a7bee10ade9a5ea99ea75ec6cb609d777b64a45e06ebf0f7fba1665ebd66dac92bd38862b9a58595dfb0afce2d2e5f3cff49e64f5ab55a1376c62f9fd647e6ed8549c5d0ab6c870a523873a15799cfaaba8cb6811a60d818156e0c315703bdaa6eb5d3af9e8d15bcba651debd5bd7360bc7a4de7a4bc3aab7332af9eaa0ea339a25e555f417345cfa6b258abd5e68fa1300c25c3b7f900c06438009c8fac3603e354a751c55287bd3a798d984f0a2e5d8606c4d53c0034200ed3b69a4f41db84de8cb699dc871fcb7a367f94fb43b98ce642af4e1ea36d5ce54f3231f48a3a4fb1306e7b95b973594ff7c052d8ab8cf62af31bbd3addcc73f48a3a74186d73184d3de2e9b31fd8cd52f8a45893f3603374cec9ab0b750e0a8579a6c9e7ec745fe623d4abea427a554fd7097bf9c64b5f6778367408c9d86b0cbda28e754e4dbd406e0aaaaf2795bb95051251509723a17ba70571969fcd0d61b76b08e1eb796daa5791610a2f7da3691bf6d93c775a0dc6790c609b4763807f29fcc672168b06115838d06763731f6160ec13f6e49e550135a71185c5b1390c32764c37ba78a55348af9b1830f990a19d5a4d9a6a06d50cefe8dd6592790076687602b0c38f6647003b4930d2c2cbd776335376aabf8c02bc63030282d8a9f706ccdd8e491bc04ea60da94e84b7ec989c3318b01dcc5f10da1942c30e36d9198854c14063a7dee77c664766c73de71cfcaa0db99c8869c7a40d994ec4b4f3aefb1887deee213f82d113ddb1ece9a54e9999d5c538cf694c616f40937b93f35fd5b9faf55ed5dc158b715efbabd1abe7a9f784cb7c4a9528525239dec60dbd3618e8367a667a05fdd910f284b5da3c25c32d097936dc176d03ddb5d8063a84f56e2bd3dddc684b1979f885bd3c4cc9b0e2a1c7223cf4e79e3c945ead2015fbac67416f2847c022acfbe1616ae9d950eaa2ce39ea248d44a10962ad84a708cbfacd9a2e3aa58f150d7353180742b7ec60b85734bd7aae65f91d5227998830c73a0c59a7bd572fbe08b5d47bbed9c785cb96e756165e7eb35948f98a8a1e35550f3b7bbbccbbec879df966b0f92de3c019281646d50426a0c592cc671f359987466a7b6b33af0afa19db2bd3d7e740a4f3043920337bee32d7effe5d3d09b0771b7adb3e9b7f769971aa8ac70a26375dc7a3e3c168db73eb98565b53fd54a0ccabff5caffdb2ce998f2bbbfc00ef9867aea39fc60f0b2448e8f240975787994f021e663eaaf7dd68e849408fcb6ba31c080f75eb5705621d26e3c96c90731608ca79a8c7ec07029fddcd61ed7e520c529b796730bba8be8044a0ffe49cfd3831fe721807c2d39ed5ed6514460302e33ced10801d258c590f083c0c6d1f0e8ba1251fe4b23c7548b354e0e9c5fc3db7aa1f7f529068cc2701ef18077bfe7c0ef0df627ce5a90186bddce458f5761e331fd79aab48b8f2dc4282932d4dbe5e58f304654e0366f2b7b55f5e5dc7ebcd8388fce5970bb9affe7afc2f9e93b3d363413d416e8c9ef75f1fa4347e538c03bd351518073a8d2058fed54de7dce815643d8b71e04625e3b09d396d519fcb7cad3e323c93ba1cba9bf9777d60a94fec3e1d8eac057196da5562efb937e77b734ef80870da888cf1d8b58cc3506cf7b0db51af66418ed1071f2885bd6a1fd6cf40b11d539642b18cf490f20e2a77dd1283ecb9b525055b8c54c0ad2bbeb4ae4042c38854eb8a1bbe9f5b5718c9010e206ba992a587e72c46cf4b3cbbfce2a13b2d5bea0555f06a9cb13b6d3a6b3fee1d730fe7ec33eb31ef830f9d7b9cd139a772d2b932eb4c9fd37b6c43aa79f31c8fbc2a77552ae7b247e5a6bb79f69ba731cb7c387f310ad7e5eebadc4514d74c715538894e79cdcb65c6c349bf544e4aaf9c77f6f3e87549bd724e9d508f494b7c941f931e464881a2531ef142534f77bf944da4d3244d963c8f513e3a75129dfa7369c5112f7dca3837232313735d7509299df30090f5b8a48f77c3e85348ddc5c04887b1190faaaa4e9dbfde9efee8ae5fc78b58aa869563c70b1be89c1662e4a887269d034546ccb026d845531803518fec12cb7e5ccb0a2bff3c46cf7850ca6306a7d3a854ce548541eb14d100000008004314000028100a07c462b168402468b1ba3d14800b9ba84c724e1767518cc328648c31060042080102004400046668aa00c6255612461a7dc0acbe7c44027a4be74a4819804f658b63dc64f4376e5d1ddd68e405d132a732980a0493a6d2affc3f714254a5a4d0d34476d94b1ffbc7145345ea428f282b2e293d76f7530c545636e54f596ede60e6d45fd2cef45a8ff12a0f15a8e158996ee29c251a0986dffa313bad8a7cceffeb06d87ffde495ddaa5354b02a0d00d7058b228b6f81c90329c55945383111af13fadde1f81d7df60db2ff7c62e79292937560fde55c6ccc1a3be65d5992b24c5ca57c60590db3926222931e974fdec8dc065a59c66826ac7737bd7041161209c5eea261f547b9dbba66f4723741788a0103385bab344e3f10d1e58e35e7a7c835ac6b521527d54ad49466d3230109184b537e4a71fbad60270654dadef8a1b2f407288e40f7925deab1c172fd1efcf450d4218272d7cc436818c6d8c5fba384c058812cfde2dd2217719549df7b4395130c1edc64d1d3f4d1d99313cba15d4e600047924a8c742592ed7fa888319b69f3addee99b6157965036c94afd2977ab22aa949cb3b6831b319aafd8b734afdc0756da3da2728faf850f0f0d3c1d512c80200bb44d2ae0373db76f220158cca760e05c43495791c4d30e8d78739af1c614554652c4e25872888c0da5b37f5bcbdc30aabdb825403b7be3ad2de6a0c95fd50a93f2872c6e18b5602f51136ee95125265dc995f640f4275e1b199305e256d91b219019eed0be770633bad2dff19ae5b6c68086135a40614975a5445018ba34b175f7ff5fc15b1dd291c1c48a4b4a1f6f95534723a36cf54ede74bcf51276f462332fc5a2ac76dec45a350c67d21aa05deb0d95b592b367926537010f54e9407d2be803394cefc86685a19600557aedd201ea4d7d5c215c09fd2ed79739deb663b3246cb19a7561aa8eac2171f7dc7b02736ef127d43e89ef014f8c865dcc16489e55b7151ed7de5c878c29a1f2d781f407aa27b219ab243ffe4ba530b292e6d3c535023119574a16573b31df3eae897429d4aeabef95460d9d68c8fcef1e5e6a78899c26b497389c2e3d5a20d694efb073ab18ee7198a4410485a37cb2b46ae78dc48e57734f38f18d0be53a6c6a95b21ff236b093853809d55507d247090a4c5432a3d904445744ea391730f56d0ca18158243c2106f4ec0638adca0b528cba0b96ba82270cbd350bb96972225c2eaa381d3510c544a1f1e54a5fd77c38e460bfc05508b2c035223cb9493df8558e3a6841c968c075d44961780093c72f5e791964edcfebfba6ce6ca768b5850947688d966ecd8dfa96554d401f7a269c6763f4c2e1c774b4dfaf197d48a4bcf1bae6404b4924e76298e5e7e8aab5c3ae8945d9ed82392e4e7ea7f39d1593ea2733b99e32eb999a1e293a45072c7ae2f710aca922a0021f82a50ee577f94d0834698ebdfed13a9180fca2a8f8a618f52c7171d9722f5e33eacaef83303c087e675b066fe00aeba36785ea913e42a40c203e80bae6261aa58f6e7468ec36b126c0ed0f8907afa7f596f40db5b2aa1db5b83ba53a1084914e3ed2d1803d6747c6193495e2afcf4b439bfd0752d492bc821638b96f7cc529adbd4186da01511a2ec18d6a3fbd47ceb56fdeca7721eda59c805da5a617fe29ca682046da2999545ad961192f7ff6710214a5218a7ea7c6a61b4a09e0fd0c5f4fb8061f5d67ca91995820250101afff82703304991246b19488e650437c317fdc360c25d2fca4c6015dcacc827d8c2700146314f7a39b9617c9b68159f057fc61bb89fb601780fa0dbc283050068c48e2d1c89d6f0bc4d8b56c905f85e8480fccc651c300e9990d648997eca7fd6113913c57be224855845728ae9b0ad10e4eaae3af52e2c074f5e4d22043200e902d6900738363564797b5531497771a81e71725e7f1082bb2be0bcb9a461026d06862c8e0e26e32132fb570f08d0b49c04ef7760ae1297034837bdc9f6984e65983b1eba4ca61f6b4a2c656359b92d838de20d2a0cd1feffcba50157903bbcd3d967b3c0393100b21fcfb6288c2385146078724962be732d2a115d7491bc487fb76497c6fc4992b240bba2469cf0cee004a29db1504afb655024a1f25f8dda9e582d5ac16e17deb01f3239d4dd595482cc3e0bcaba37cb2438c2bf5f688fea76aa6a810a5c6819794c16d4501fc3cc6aa58915f3624919ea0ef63be1fb8baf1c8ac1aaa57d27efc1de80fbe5f90b5681aa84235590bc8e87db57d99ef358f528c56e213ef556d91de37edf1b05cfdb5411422f7f8d45751f8746d0bc23ebee6c5fd63d7d1c04749676bb68619c177d8420d8e07dc57b033ecd27df91b90bec47efc7d1c0cf8cf8430eeed5c71990a857b538199111eea2d4fbce7c99df447fd82cb3cc9b79c26fec4b1ac67c30a39fb3c0fa1e0d39cefda08c2bede4a6e91bd2fabd6190f90224f677c71d955f173d3ef7e0921757b20475ffae529c8ae18c395fc8d3aba92654fa00e7d3c23ecd012de398243cf4228d8b2b0e182377741d4b45ec71760e4d7bde61fe02525ac380e83ba07b6be54aa94fc76e466d19c425b9eddaf94a50d0ba185ad2a42822ef0c3ca84cd9e34b8396cee8928479b32380ade642b99b508049c79cc7e4e957a8e5013995700fcbe83bd99d2113790b427cbff1b002d253dad7c073ef6764efd1eb4a9e9a09bdb776928aaaee170dfa2e507ed083d011868b720739cccc52eedd91dc11ca80144f364a775fcba7ba966b9d047da2be7a788a38225ff190356f7aa16d8d1f24b1c8c3b74c89db4da0af1e8e34eb5819808fdc8579169ec420cfdb610c62dd8246d0c7be8336a7321b35e9df85e18c6bdfd302b2505a7fd9b003a235773cb50f73c716f88e32920bc7c1569cfa5c564dbfe9a2e6451a0ae7aacdf7b218150995602d20c84537d381c38be2a0783d1727ee57f1e6e6897e3bc2a717f1966961a826827eac675c80a218cc2ca412b08cdedcbfd6e55f86bf06d738a0c7d84c47e0d3af1e9a1fcb7f1cf2bedffd05df6d02a578af5959a5ebdb9f9b66ef218992ea3a66e6eda59cd62e2ae490714122ff15c440528923ff1f3768fa769e8d2cc963414bd7420091cd5324427f95e579d1208f52e8fb30e7a5b6e8a0c4161b9f157851e465670d933af57a1630b296656293bd40997edf7e55fca53044ac5c360977fe797aa110ff254af609d24dd62b98babc8932aff151820e384aa389485aa13a25828a1c21fe87cfdd1c1a58a838a0d3831e61bda606b232d668baebf66e3371080a19901f38642dbf18a5809fc8cd50406ea7eedb17832b99e5df0b92a370d0d3ee4b7a9f6e465e171fc632d34f3fac3c7bc5e034e64301471f8230f7dc8fed1d02739a12cb86991cc9d912a77ecf8dba50dbf90cd2d783ca06775da4cbf0b09160198580aefa677df4908a7ac084f5629945f219f596d0f9e9731001a9eb59ea65428d19b69e4a51d57991ba0e28831bdc6914d9066b0d2b2008c0ed26b52977369b77ccc3610a3888996c5559d415703b9ef3ba718cc920535f56ca336759dda5a911f3788cf702d6d0dfd6bc0ca283e51ecfb7e276cf1397823f6df4a4b3352c7e2060104a7efa28bbe2c1ed1ff6fa48b26b3d7743bec4860213d5812dfefab456226508c91d9a82599f39c693e897f8e5f1c03134b9717ce4f61d9b907657eb2011121b6fa2dc92ea404e47d623d7cc2bf0677a5c10799bae48757b41983799bb8321582d16dfd2741d0e4466e0d8b7d26fa9c8bdefb481405c84cb1bac3ecba886e78e5abb183db7f616adf3300086adf0cb3be1ca314c9e19e43f9557063111fe42cfad2e195457109cd0a380fd954824728445b8a108dcc5349ffa1bf6753698303ee90cf8dc735ee8bf6e6f0eaa9ae40c4a7da8b1b1031f2b2421bd934603749a705765a16878b4201d355ec9ff854af51fedb0f2b574b0f3b624c13adfbcd62bc43637b9de45ae49c2a460f32902d4005b476260dc7b66d8980e5c5279a9cc67cb174915f663fe1ebde50fc3ec47ee4de87a600a6637edaafc7a541db05716d7d9a11cfa8a09251b0309686785e4bd42887070ba13d6f907c324f1f3344f656cd8bed3bf57f16e9548acb6e05a7c5c7ad09d51295ab27d9dd983286466db9ccd0d0f3b0325329c4feebf85523ace3b30a8a21508a866656cba77d1ae32221ba703fcea524b978fd06054add51900b3d663a7606a0575f00743d3ffae14614f1593b9ec0273f43ca0448aaa60251f00b76abfc54268d77fe4cf72924bbe62d5285039c8e572a4b2b4b344e94064afaf179a64caca2eead42c57d711c742a33e00309c9f67cdfabe81e71d37b7782e2bfe89c064409d04567a447dc033e0e0726528cd9ca51aeb65ca9d80ac1d08d2ac0b8ad35eaaa8e2c14191682c9c950c1f1ef4e04e6a0ea5c8641f998f8da6f1babfbf9e3da6e90f9a548c86b038a7a8c3f3f6387d8d1a82baa3fe11c2c1f10c14d66e260f27640cd50448e109983d5f96817345670f097cb60f3721049a83841d6fe491750e6ea7d70f69642b3389b0f662eefbb41f83edca3926033eccb0c18a8376e3aaa13b13cd5979013e73e7f7ec4c2e977247d562656ce3c1d2c2aa4cd7d00c43486b2a27389a7c12908d2da672044cac4b73c610840bb2487dddc56d10446df0e8fd7b80f08ec798bd1d9a90daa9e1fafa396b24ffa47b7dc7418f3084c14eafda0bd9e4016be5a7966da536f97649aacc7c1e9273e019111a70da1637449522b6c4de9c4122a3251d397f36f12adce14deab02f484aa1668449316c9b4f681835ebc64381834d18515a449de3d39a199c965092b8293c30c38dfc36c33a2e193f8088e1f900f00ce797ceda90824c195241573d6e61704d384261de05c1a53144ee017d70f00315e31d774c08018009a9b4012cca0078c8a6bc0ca0f904a9ba6187bf52926b5adafd459ac9acf91b99e6500ce5b89f4f2a19f844ac8219523f196c0aaf3dda2fef62bdd6a89147676081507655c48398dcb476b5e43bd87116a627df0eec2e746b81507b7e5beae7e6888f3558dc55ebb5e217c2226edaf518d1be19d9b71bc90896a363a4285ca551524b649d07091e2b1a6d3cdb0c80db80519d3165bf7b10debb1307d3fc4e14213036c92d24b2b4bf0e3b9de5d388c811b2169d81943edbdea2a5d0b64d907e50d9c9aeda5ef52065b5a94c322589a3703a0c99b45811e5bb796a48c195e7dccadf401d18bb4c3d08f8058d0e891ae3ba06be86274ec62e9f4a9fdfaf0890b8f261efdb529a1116383501f1a64867c8fa28909c0730ab19b2c5f2a4dc55685d6cd9c17261baefe4200a58f2a2021c8a9101fcf024a57680570980b098c4b75e437cbb0c4abec3c804d0ed1004809bcca761cb684478dba8c69e0fa36f5fd703e7783531b61ba4b3ecc8315b752271e8bcd7dea93cb2c8d2c718d1646b4795012859b19a0507d81a57f9d43f77f3f24cf7944cba12a7eeb34f067373b39ed5b73b8cdfb6907d44bf64c1c0c022a243fba8313eff32d5e05c8c14d5c87233fb9bf079ef774849a129ca2d9e0a0bea94f206cfcd8ce5280187231d6a0bc3e4ff42a0e614f76e204e96d7a826c08536b68aa6555d7f24eb51a40bdc093536a97830e6be4cf765a52d8cbde874310de75789cb900974ddf8dd6f4b88f356d69b1787bbc5f6a9870383c2979ff1af8099a243d6942e38fbea5e86bbf03441ed7c57d5fab5bfd1819e46a1089b5d66214dc68f18e4c63301088bc1755deb593d5eb8cf0155c2b7f114455ec175874d5be0f7c2ea616b6e2f37babb5b17be2daf00518669fcb880550d74741b0d49d733c3d7ad5c3ba3f35a0ed4fb8db2b560b1b38d274c6cecfbae6115c913207d0e8ec121c54b81ab2e8fe78d7b275eedd6894dd1f9f7f9d86fa5c5d3ed5fdcadfdd3f509dbae16748a105ca239cab180424df742e8b1f9f3f4cd7486286d7c1dfef7a1fce814c9540e8ca7c4f0ab8a727f31b3f715fd5b80161f8624e264e33ecdad74c17665b1e10a28a3e3a40e1e443c61b5086a307949c7648996f3046d6174b305537b48d45626dd474606da3b65d2420fca99cc7f06af17e1bb58e11456f1e11ace0ffb9683ab4a79ece997a4d65436fd396ea141ad9124bc5a754aac90f90b346d75285691e908f85368a631f8cc800571372314d17ed71ded552e8b9d82b5c80766fb5656232aca07e29ef13d3e68d4a2f69a1858a9f88d650bf83288c8c916cb5f044b5ea1c18e11775e06d50a59d2df9f090412c92638197d0a84f036b7aec4dcb6c7d97b0475494666c78daa292d6f1396e46810c5fd296d02c5213602818efff2e5194cc8d933c03eed3517079073ad1039f872a892b712ce063f5270f2153fc734c47551988ac829e8a57a3330909d709e1166e772034e37b5f347ebef1b1fed867de0ad42a908af3dc6753abff8d1f025dd39f4341189a12668909b1d39872b0f662911954d07a4aa553655bc3953204718fdb07d54abc0c4491e78041a1e7355217066db5ca029766406ac24d0b516ee71925860da5cadc529df17901959944a35067752907432f0089c80da1498391b8a579cbb5990e885bf209a020c8ff2e38f86c71339dcf342a0e0f415ce5a9438495f33cb169a865d919e415cbb0851cf7562845b9ed553d013c12b7a19d36a85f51358da8c0b2cd86b2c0ccce3561a26453a4808877e4c520a5f684e2f41a13492ed5694f3c999ee1f1a1316470fb81103d990e3c439fabc3ddf5dfd996449b6a39734ac47363cad8f8239fba30831a0504493b5348e9e4b47feb9d0df312adc2b71dc3f32a54c1c98e97afe0bcf83a4f5a529524ca8bcfbb7bd13e12eef2faa3b493e0b2a8116652e68a2bd74ed03e824509dfd991ddd2adf3f7e8a4c471b256dd59b6e4f3a2c0f8ea410a3670d14730dabf6557bafd8689839c2417227822c0ac21ed2412149c0976c703014a04e958383806714b9f222d67baa3282d0002148dc6ee7a0a860252397ada61c098f345748877613a7d1be255ea03b6502b4d0b68a8a5cffe3ceb485fd251c37800eecf65ee298e4bf0a5f4e165d5a0949910fca60e37f582ebe28753afb85884c0a0e514a645dcf2e45f07407525f5102c9e2d49170a25f20b28a626369fcd8a106fb317f8927f797f36b5bb21e1ef0e8676ca93608b3bb240a117244f7f8c0e691a740c5d2b5f9672afb3167adb02efe2ac5c48014d4f9bac241d474694949c86dd2d223cd95f3fd3287c3ddb82d0f988ebb9c544c7437398221a014234add0ffca736612a120134d511981fad484afd69a6d6579c34c30c585de8cd6f86da32db820127a0cfb03f714d026e72dff1a1c806165eabca8378763afe4f7c9edb023a7cb890bf82d442f41c40be3534413d43a843b357f5a5609e93fd90cd15800762c5c6c44da83d180a5f361cee80f4b3dab723647fd2836d75d22b080503091e889287e63197ff3ae890c94186d824c8cbbb3ba12e52eedf230a8a45f74bee22c4ad7c0afa00099a6c007cba5cfb1be0ac0ec0680913dc016bac69624c8838c1ee45f9970b9fd64369f6f54e891bd46418ba0ac4a5fc3519c9dcba492edb01133990f18435af02717a00cacb35da33285be942df6810072d441be04ed40a13f1c96212884e50324015e80fe4f5d7252ecff0a1f17fcdc93e65c447bf997a30cb8b7b082ff17e66a7e106878f6106bcd83484db1d24f47f27fd0f557a29d9ef51125902bc5e97931821985a84b9c8e6b4a51abef13d96df888a649010635e7ff3b1bcceff4c0e806457ae008d1551737d0ed1b7d18a9810080b62366dbeecbbb207d8062fd68a60ac290378a2e38ee578df2fec56a41b3890e563ad941b918390cd340bef8570f90e47a82766b113b097d3f5d32e7ad92485886c5654f70fd6de3e164a740ea8acef9d2bdafcb8e74c19aae11ac5e788829090c45b08b879e9840381b362a54d1f19f73ad6ebcca6538c1155aba8915c96f6651b3a15c6437f241292ed2035946896c72d68d9bea45c1583b2f6af7ac244b0241254730f349fe32cf4df2b11b0b9feab8495febfad6c003737671ecc64fd4f701dbecc6b3b02d402bda6453995a43cd1559d9448d3fc19cc0bc8de12c9d931a31f82bcc480f5281ab8ffad0b7ee9b62b092d5177dce5fdafb27d40445ea79baa12d4e3adccf2d40ccfdf3860bdba866ff554c2b4afbe1755b755932ad3804dfeca885c92bdbb37bb176565dbeaacee4550ebe3f425e0af62c83b220ff5f87371065678372530f0ebdb627433e958b67da81b7fb12b770d75eb292dcf62a0bfe0260bf97bc2c2fdcf61d34172e0c9a673a6ec7641f0e359ca9123cf227b4bbb5ef975bd33e15f6bcbf528167417e0ac3b3ba0640562cd4f1e2cc0b34aac83c5807f487b2bc3310dbd9888f8aee2fbf98737291872fe3dbc086575ae42a1bc16c9647ef7fc9f9decdf53f53565e2599f9c9a375b239ebf467eaa73e9c7f652eb08cfa9c746c247f1c817c917a676495c04399094101fcf84c50c415cf2772a38cfc0d79c8ae89d822ae924acc4692cc0535e5cdf55b444c0a38e394fcc2d313c9983637c0071bb4793659f18394e39329f83df0d6755aeae844b899e8b04631030b84b4c980a7848165f4232335f08400d558f1ae032f718afa9334e4ad8310de388878f89e9eaaca8c71ce093887e06e24021ce27eb7343e327e5f232ee7747ff28b9bf5a85829517491ef2663201b5ca4f6d0393e5c33db19f099c7f95ddd008f86777178282ad7b29cdcf71efd8d5d0ae61715ed2e5efe40df2baf8918ee5127c062673d9baf82228f08241d6c87fd9f791b4cd565846e744f02cb64070898f0f5b1b7f09a8a36ff9eefd52b8290d9cfe375e422858a68944650784f663e0c60357f795190eaaf771beaf774144533b0d380eb3a089f39a38e7bf9692187602ac20f3f24b9de1eabdb3c1833b8a5ac53935c6d701b9e198261314a62739a421c671eabd3c6c2f85205cfd9dabd3faad926ba32d1ca2b0d462ada9ff40eedf4f5090405be35b70a0a6b7d05977206e20f0a4be7a953ffef688b922744aa6f94606e3651afd5ec2b9062220a6b4e54c97e2572383b7f1de0b178dc28e586c0ce60df73aa3926447daded09404189bc9b1e05fde9b2c63f1aa7f24d98dd74b9574ae49a3193e859ba2e764450cc774c470f1dee3c2bc514adc3d2f936e4ea748d2dc2d854a4ddbd14bd508dc04eeacb38cccf9c360854c193acef029163b13305f1a8bb43c5ca37a088a0192896ac0f157a54d66115794d2328e966065098ec2ff631b65ebc1959e7dd8b008968c6fa632f9c9dc05b40dd587867160da337b814b920454edd39cc214effcf3b664202542f9c81458c7adfba2ac6707da1ed449118f4adf34b6a6deba8c6007db77abaf966454dd2785e16002a3bbf27301f926156c60afab3747edafc1e8d4c7dc9355d95a503dc0e4e20018cf1bce2b9abd5cd25ea45b9365afa6dee217a74725b8486859f275740b8dc51b22d8f6fd1fd15f51fb30cab3fe70423ac50c398b8d90617eab94981e9d83b55412837651ad56fdb88ea0d6404cdc3e195545a790fbae7f1f197be26a0dd246f3b51934eecf9092da790247525d7822e15038d1bb63d215f31034b5745128a54ecdd79870b2e9a7542a9128107f40eba2074e601e48a95b3cdfcb8be94e326aca768e960858ab7a532c146bb264922219a9e2388adf560ed0c7ba4640d473802dd9eb43ee1352cc4051b8eb3b481ec80daaa9514426c3e69641707de8af1c2567354571e28d990a68c1a8522d5ee162313b411dd31596fc528db38282d4dc57e5549890fc92a672bbb468498453c16b09adfc1c9f099b33d1d3870269a3ead0ff9dfa3c71a1b0337201ab7be1a53bf2a65f3dedccaca59555790af303d2283eab8e907d8da1d8c1b8f04e0d8ac080f3579c129150de299f3af8972b88e9dbb73ea5e461503047ef26f8c38e523d29eb6d559bca1afd62fc580eda39160ddb51a47c1e677fee6103e3bfebd58aff6e1ff9d3dfd1a4372498098b721a362a6aeb1bfa36c37a6383ef146be2a2bc463ac4011597faabfd94f140f7abacd37b14de497db592e4e4a91c4cd0173621158ce45b5f23f9885a3a4954afe45611851dab5fdaadcf5a484fa60c1604c32da42c257b50b6e9a6fb54090f1cebc92e6a2b1292ce3123749684b8c3066524cdc582c72006f219d09595ab34e7537c9d0afc40cd835bbcee3aa4d0bd061f4e7256e35d4af61b1a2d819f26a398e1e8015b5bd913110455b8bf52195a831929ecac2c6fc2db553b8cd86bea934c9445a2a3341f7ed33e23a575e19ed4140c5366116ee0fa349e6c11a942e08360839bbb8e65e16bdcba9079a9e86571eae22d0098796e7a7976eda55d08d938baa6c64d80982b7bcaa0562d9e221dd5034a0574c291e16eb59266778d32e23c2f46c0d03dd4425950a306fea5809ec11aff58ef80d780039e89c694bb8e5a55961492cdaff847ea4955cd5b4ce20121ee9986b1523a58e063e3383850954f78d125b4818630e7ab9e7a3c8d8eb4513aae00bc85d6e57c7cebae51d96a7fedfa21422c64664559ef6f5417778e2ddf9f8633862fb3e9098c172a3571ff1468b4751c28a2a397769ebe26d3f90ed23f45439bc799c969f6f3fb3759bf0bd524459c2058e2039f4883a940ac4fd1a5d626c7bab6a10044af4e15ea86bcfa81bfbcd365dcab19d8e4758aba2505a0ff71ba776d01ea5da9f2099da7bb8dfa1a0d826631c8da7b77a64620e3ccadf05c796b5c4008774b9de889d741dfad6f5fb28fd720d83ca55ec644b24a55b012e7de263638855770f3b9b050578f8851f11e3f6c9e5097de9630dc9764d7637512dff9eb0e3b119382d39e0300406ffa10bf5db564367a71192bfdbcdf5475fbc0f153ddfe5c10e523f2005b7418b0a3eda560ba5fcb8022576efb3a7c81cefe721d745a87b2695299d43d01b063dfb02242913aa965bfa35988fcf8a35c5d259889be6f363b9b25def62dc7c782e654f2f3691867857a0c683647a8fcdcaeda6762b9a35dbd491eead5b7121a7ef4e1a7d2a678fd8e1fc5e7c4565c932be7e622eb761085385433fc840b81683d4c7c5627a3fa2d990ec7f1a6398711583ef69e5a319cfe719f73f40e5e5298d266e5c40fe21ee2805910daaeba6f03f37d6a4577046e588478beedaf086a93258f1b4eaa157342e46400fefee950be723e82186639e86e1731359b0969ccc70e04d338c6a78332a14985d452dbba682ef7851a1c9df8d40450fd6a3cbe7482511e8358523fc6a9ae71611d865f293ccb1ac46f6ae44df549bfb976dcc61bff4bc8122e9d7d8fe9dcac45a5a7979feb6dcb60cf821b381809ade5db236e1c32194ed6e816fa81e337715b2a5af146e7370cb94af138efce231444c78ceff36e3d7b8f1619c90dd4cf9a0680a7838296fda3cc89224ca29366a7d32faf93f9e6a09ab342f21708399d0f57e18b9df805910413a36f4c09ae4ad5cdbb265a4ed99b4a6f96ce5a3a36d7c2d7362f0a362cc5b89e44c23de15c47a8260ab66e0523702d9e2892aea7376f9501cd30a1d5c41ddcafba7674b164063680c449843a167939038d42b02b3df94e5b758503c1eed8e8fc045c8094ed9a594bf5ce40e1caf40a796d46196903f4ded04cd1715b9d876a110fd674677d1b1eb1ea8d2355b1386b73cd758fc993c680d491b22133c91d0e38df86d3828cb01f09b5fb967399a1be408289780f38d2f9ab76f81989dcf7400cefb2184da73eb2b1a57e897cee4c8c039d5a6c513ef35f02c10a1a2458c74584270cf9d7c85df51fbda4dc4982bc6129614d3d5c9b88ecdc4f4d38d9526518fa116145c9940ae99a5eee69e921aca0b58d1af9ad68ca1911570a3e1fb1b979a85db518e9f414c69c0cb5756eb9e2415390637ab791ff2318ae33548d1bcc229d35a209287ce5b39e45ef5ca4bf446fbd18c5e915541922d5acad3c23c48f3e0ef41ab0922d78aa569020992879137087509cfd509be7cb7d59e706cbcd99c0e61cd3addec0b4ffebdeed5855a6b893e4db3206057e4fe07ede42cfa5cff6ab636155572120920b09c5e7222186100536f9d9a0c1f5bda1600965c892e5fabb719b38550ae38403c254869d7bb60023c12d2350adfc709f05f1d2680086db3cb30af03e6ed126bd444c4fe595cf4acb87b1cf5b91b0ebb4b463c2482ae2e1bfb9f5d82410eb61ff0fbcf74a53007ea0f24bc83b3a0b3b567b2a77aab909d81d19ccab4b61fb1fcb797b943985bce52c10598ba1c828478d6d68e554d15d479e9c23bbf5e32dcfe0fbd752f7d1ac0630b7e9772aa95d8825eee7f1afbdd831b1fe5c366bd82aca9974f7e6208c1ef572b6cfa281ba1fe02a1b6e65eac02be5a72539c6ea11cbae442c997029c09e18002f7d5a29aa9acfc3d131e216be661ad7526d7d6b974d982c82315740c54d53a0288f66fa4a64a1e3acbaaaca6732281b3564783f43ec955a2d93d7a028ad3a33936b65c53d4e3e6251f6bfa2699132f772ac02234cbcd62c6760fb18c87f9162f73db1d11bed96c6953c9fa6fd20aea39aaf21877a2bc8eb8d50f3c5379a8f9fbfe52dcf7e264e6f35334708dcb875cefc8c66058db842dd669c54f7523ce68c2c77c400de1d1b653605280d1578a5d5d2682b5f6ae6881f4ae4b391c0c88b05aa99787aa47d724305a267198a475cb3f7b719d6c38eaa8bc2b327abc1cd9c7bb18205c7f81cc2a25eb063751f249fce2a1b1d076c65878e8b7fed4db00da7a1755926b5ee55640145a1200ce013c7feeb24f00ed7966ef7f347b1f6759796febca3b70cd9287cdee9af9973ab196ce3a237b9e129c3053fd7f5204177536d9100cb221f05fc5caa72f34bdc364c8ac2660da2cc3b774afd1553183a89e3e77266b3014a70efb924899e64e7ce7ed7545ae8117c89c989ce4351efafcca381fba08b1d865331ce76d571ebf85f56bcae702bee5782fcdf1ea633190cb62a0328b810b2245cfc464981bf7378547e46c783347c53b59efda35e6f1b2156b5d8a59e04df271ff944ba7b3faa45704c6fc66e572d87284ad97b79807024b4b64e3afdd7ade6523de351b490b14591f97f61d55d9a63419786477521f857a10d680e771b4cc559669ca74d431d1e3e2ff51d6e347f570d92191647209573983beaa659be343940dd8eac76e1da216da62e97fd0632eb07c85da757984145fb96ca8c7be1aabf20ae645bc3b703a69e8f45c3b5d9e17bd521fda82974d978a943faf5c2bdade15bb535ea1c05611a303cd61a13f9bd5cb9ec3da8e7f2b04de1b4c94588923062536cc091a20ff27281f97a518c353614df2c647711d6dac9bcd38c0e02b1f1f48788052206e6cd40dcc980b7c985857ae9bf0a7a4a97ef600a5de9c5b5f0e46d643ad0f37c907e706c59545b4c9b7879d9b64bbea58b59ac5dc7d6d01171d02512984cf5f6dd33518917f255a1a835c7188531957a1751823fc1f14a75178395b7e03b7c6010a8f42e20a464b5e251c534769f45c5577921253b484ba73731daf71592f622ecf95c9b993266234968779b26aaf74b4fa53628e7f54a880a2402b9aa05b41a47fbec05e3e6a1c1494aa33f9baa5f32f38039a930e9b84f557962281118ed0393ebcb6d6b1468cedc603aef686c40c66262632b3eef26b1c1a578524542c978fc5189fef443e91098a0027be2d7341a1f8cc4e1ec0b9c19d1d9119fa5dcc6c84a17a6ec7c3cccc1fd6aa96d5aaf257bb34bf4c619b1ae686d5a15f1dd232b9dfc112c24a0e67c7c192b207bcb1c5282353a3b1084b2763ca3ba095e03280b7b78b7f2cb1c7789e12571d2edab78f1c3eba8c1f271defb4fdc3feb546a561b5ce4ba32fbe541d32a749223329962f7217cae724ac3c4f595d6200aa889cb50ac10eb76b7d82a685cc580b1be5a76051af513388dd7dd3314b450f37ae0918d3d616b18a0a1da48672943b5e27e392568f8a27bfbe738df59dccd89e1e50878e0033efe1d4930293d4b01049864e170d4f95053c5dd1bdd2b709111817259d07df8073d54b3a413ed5bfe39decd9033460bfaf4a221b3a4997f626b195d0c399d4a4c829cfa81b37ba6ede833a439d01bc9ae62f6838eafe8e86335fd5a18ec803a64de6cd145e787f1f66d5e837caaa2f8b59528ae7d81f95d57252a752a383b33b888bf4f76d2fad626049902133989610391e92b04d86a72800e16886a955a0b1e759de581422ed79fdcf1d701244ed72a9a85db4d75b4e199d1cd0c96276fb9c7b27f5fa38b7a8e167ad9059ac076fbc84420623c3abb95f85d230b9c44f8b5eb9faac295eb25cb7421c4a3fcb19914f1f063575fd663b7bc7620ba9929afcc0e266261925a3a1ad0d6bc1b1e5f84665ab7ebce689b321a72cb785bbd60ab79ad40ed0f8b143dd8a29080dd38f5f7a57c8ba35f4a961d13ab25583eee7c4d8f3ab3ed236d1dc311d2c636651d351a2e7933cb324fe8c2b924e9b1fe913e3b41cd74c692fa35d168b9ec719a176337cd0a560dfac6ada83aaa1b96a60675593f8556bf923a05fb7bba4d85064ef31b62acc34350e64e26fd61d90a39f291fe514b9a9d68f64e148c3f94af2950f632ac508d2b76be85c9855a2ac5f7dfd3e88ab07ae1c26dd5aff5971ac991336144080737382d191898d98b18e42ef992896a37423a60a53123ea90ee3b21422c1cf4ac965f2299238de9d00c8ba205a2ad9b963815b7cc860cbbfc33b58d5dbc3711f3aea10fae2ceba35fe0b075b03a93123e333ca60499a94b8534d575bdf734ef3d457529c2550d4edc46c0942f1bb6d0c6268c9cce82a70fc9815593e5ef9b019df4e61f1f46418c771ed134bc956370656f632cc690fae42c197dc22c7abcaad034b7df3d7072607102ab63f4a92e4b57a6754c04387e86b1ab77fdeaf7356b3c60c803b28fd42a8607bc7a688188844115f2d5987d54cf4f7e2e2f47c30c3b39a1b1c171fe330ccc0de19306be822654b88ed52657eed4bbe3b4bc2246f4a5e9b9014af5394b0949ac8734bebe7006e239896a1be3aa08dc9550e6303c2baccccd898c3c82582382a544a1064f162a0bb61ad97d393029d63baf3bed4b12e9afb390cbf874a327108f3bf13c38660d0893992c5bd3b2b7582e2dafe1e75f9224d077158ac3285df917393ad6fba725be4a1f1373e49a7983b619d0f8588830187c3c7e25ad5358a2c7195e2e83210ed0be0a942f0f900728c0f55bba9140b83b4f8184cf196daea4c00ea8781dde2cfe5cef13af746c86a9a3d56924c133b02c9f03e4d07cfcf4d2e856b841deefdc8af9e7f0d0458c80c86f7ca0dea27410a3719e5c627526ea3f2e8074ed4077d1f7722eab8f87614b8db90abf7ac11ea675b9bf0f04e16ab6132841951c95bd3ffc743e31942e1675dbce1e7786aa8fff2ab9b2e2eaf781175740c4edc0aeb205eb8439fb06ab6d5471d6be661a87d0f213573263a1e62c82293f82e0c3b48a2933865fc253d2f2acbe031d7c510ebdc4f3f292ef1873ab305e28eda18e1106ea911bc00dfb0490af9ee0d50b31607a996d19aa0798ed66052185be345ad73bb3d6b8a34045c1234990e5397026006e394e1490c8807feb7754e644e490971103d08a69cd6f646aa7975484e40da129058c5c3d5b45258e70ef9f19a5291c0c7e3b216182c748b537b28f8237f9fa588a1e7da816eb735e81c5ba20596b8dcc253857010fce01a640d49ec2bdacb426418433571bf5478ffb9899097e3e8a9a25f01a9849017c2db2f7c70ca2569334ba8b004380f17dbaf4f7b8e7c3a88aac9033420709d1440219cc3e200e745070755b1433f55e9e2293d851e2d96a8968f6abc497fdd5296774658b5f39a1be767050635a437cc5f3490fee24709d48ec64ca7915d35d8ddb9e60ada2bb5447c841ded5eb1415f8cf6f58e561c2dde6f512b7bfd44769967ddeba3c808c88e0a4c8c50c4bb187947d31687adb849861ddb7038c69bf69e591aa7e07567edcf2d8e9a3f95c4d5abd25ace0d3467e2396a90a28754dfcb1260c904f2d01fe48ff1208af8616506a3591d5e24fe1e700b92999f3393d21e5ee5437217557cc911020ecb68283ef9abc43972b393d55adc0617b7e6f1b539f11170815accd437d761db05eee1985fd869d288e4d0cdf82a0ea7ce3e784c5f5c8b422c9d16d126e803cacb37e54b9ad245dfba9820f12b6aeece035c827622b21411847dbe9886a4d1e20118f0d1375a6034e1c225f0316f825d5b4369d64658f988336464100544e9a0ddc5b9f0bf467dee609fba1a938903c6cfaac593c1666d6c91e0c2e3d84c256307db2a97f805b8931f7ecb8ef9e7e4cffe1c8b0247fff0620592c66b1317b221016955b254921837fc55c402e12e11a385b99977ccf7978de95d1042a62d29140e41a8a0a689523b95c8a12ce3ea69735420ea85699d95ed40eaae0a4b4a73be9ddc80ee857d2aadb6eb4ac98680dd566ac4f6cd5ca080bd8b8c32121744bfc8e000176585deb4ebb5e6f9751ce45c8df2f3d28c49f851918e213926a94b7fe39b27d229216059b8f73b107a83fb68c81d47e082b31e44b130f4b46e90802eb3c2bf44da28b3ba942c4a94db215173fa85a63820269b11b9dee8b9c507e8f0324a00f023e70eefb78084aaa0cee69ba2a921063378b517d280eae69786891da11db91182d07c81be5e6828efc33e625668dfda9ab52c84f5baf446966f2016080f293bd2c04f5a90b1974ba3bca10514ee843d68bd0b9a2680702b365af90a00a1244672b1911448057a32d3d5c816fa92bc02e420077617d32bced81d69d42a15ee03c4a5289b581996605e0825b3121ea0586b683c795b587fe6d279e8ddac3f96659584eb709a984be94d9a45c17df5b6dd745670dd09b8541bf8d0259566c014e96b92acf2bc2e9ff915e0ceb70c8b36dda7507bad43a9b762f05533f721282792b3bd44c3112d4139c3d67bb634cc4732bcf2c67728388cef1924d81a571eb8dc42e4c470f4df7db5cd49b34c0b8f1bbadc86719db1a23bd80e1dce52ee9da247b85e5398906f4c8d8d95c152861a7a42b55580c9dd2178f5d61c67f5397522a862d335533300ad05ffe9cdaa260329c29391e4457e1290480ce91fc8fd5778adc69fa5d7d967c0308ca56c9915df7add5dc3fa1d5462bf506bbe904985a34305ae41862507372bd6f6d09a22d6f537e4b22ec41422d0ed528582fb5caba0a7480c38a66339cb126d266784b94f682acf13cb17f14a516299a8ed024f3171add24159d40fb67465ee57f531fa8364ab69c7125f9511330b5799f20d96fe3e87eb4a775743e753203ae6911331f4b5a12200a0140dd635d160045eece9bc2e934d7c4993b30f9b433820eb6af5df7438f5b5770fe0102f244ae1cf6054194b407c8986db699863b5f3509e32e1fe1ab6cafe5c45c6eafecda43b72f6903c3401c32e6d49cc84ad91d0f498ffec5672481c578713b4b78bea0462b3194facea771ebabbacbfce29616b8c0a59397cbbb9b11f0b9fdcc32436bade5735876e1ad76f75299cd67ebcb8afef88786c9aad447554a363e1214961ae99d5ff33959f929c33bbfbc8777560104cbacef0cab1c7c4e2c075ab6c5da162fc1c729c2d6312846af9da556fc4a6f15e31c1edf45a35a7c57170b761c02a1a731bee45cd8de3e82b18c24a47d690ee059a63ff267e0dc3e7447fbd316215e9c2d10fcdfcfc4e34803de1769109fd493fe9dbb4ac0cad6e605a2f8bdfefc808f71fbcd7a788df2f734c849ec4b7b9aad740486b1f6e6881b1ed842beeb28158d7ba29ef8775c44a4b595a6be544774b6aba2cb4895813e43652afbb26a094af8f0e4aa04c25dac4f6e1cc8fc05ddebf99418ee8516683898f5666871d5875d034d5f99242b4655e8bda64c284feebb171965470200204dfb792c482b2b0306df0c44293afb15b62f78b8526a1d7f85bfbc4e0b52219c8db36ee83c8ac404d83d286a31be243c513f689707694aeb0e0c026edc2524165e2ec895dd3c7761deb190441085bb21cb6e465f150d7fa0395aaff83a1d4bda17b5bbfe49a416360d8c046ac9d2100254b1e27ed77088e23d14e986fb4c4ec27a6c9310bd10e0970cac008fbf2b21cc5d85ec756f8bc00da39605fc688e970060974a1716be228e1e6c8cdde4d56130995c2641f3653335d7e1828f86f6f6f82b75dc15a42cb5cd9c38d7a904b15d1b91127250e0ca9d7543e2908d061fccf779650fb6fc6cd9cb13bdf4197d0908fb875edb9da576546063f926b4722c02371a962194c60eab80fb8ad25d92b7eaa710e8e7d3a6941b47c5364d5922a7cf1d5f114cc2b0a22537a6c0599c8813cc6255ea25f46b324e476315ef4c6dba2313d4d4ee24424dfc8eb58d8573e291241e4f168c8cd548a4e256005e133775a91c60bee038695511e84b970b472207edc206d65f4f43bb0502f473c4c69368a1509066984e7194a10940a08406ead2c71dac23eb3c4741edc05aa8c3cfb28df1202708a12cd206882b0c86a6a1b4d49d8a5458eff072ed1b683bffef9fddcc01c22743f2853051a66a341d01b6bbc1e3640842f1e66ef286370e51dfdff2f3fc172c55a5fc8708f54b88478cf32f46ba24f82ad441100380c685ac802f4a499eeab2a3ae80ae8eb807c604057d039a894d083851c2854f710ae1400e9a886de43e79366c159fa3a0d15a6f119aed810ee593542dd109798bee64adcaaf3764bad343aecc0d5c07002170c37857ec05d5258d465080048107c1d96339f681ae1f195d753165009ee6f443466c74892176aae7a7a857a06560c18e44a331c5fcf8d7522d57f31f5e99a8d14ad48a1af5fb9f184c719a82a92510d6324365274d743352c13ae57209d639eba16f411b5fe367acde723a4bdf8a2c16d7040ce7fdc3e0b7b291e3288d984d55b6e0fe89f0a62088f1d66da94b512cbf44b7d9cb1aa1707ec19e882d3b9a94606851953ad6a381d6205e27d96931dc6ec096a084e05d791b307e5082d21928b0cb8459495d6d84dbe2b0e74cc0544082047eb338850705a6f8e6470b1eba4d3d0269c1ee9d0dd30ca7c09470a0daece49ed54dceffa485654ca3e524fbf03cddbf21786c9921c0b3633c33e67a57bedc91727074787808f4d11861eb692accc7142b8a72752195bab98715c590fa78802e7760aabedd4900bd566262556ac44a63f9ac54483981fbefa2be1b5b1cd4d598f4cf60498265199de42fb0928a8f5c95a49ebaeef399190b95cb5f3305a79501a26d3356aba3af79890f7eaf595fa14e1927bbfeeb2187af7963da045a022f008aec1bef797aa43319ce791664af3864512c5b7984ba4ba0d7bec6af87612cb44fe320c09a904792fcb501cbb2886250c54198796d21f8c5e79c5f4e618885465ff3bcc65ce837e63d6b9ecba684e8a4d2bac2fcabaf3ae5f2aee34cfd9dec97d987df33d309564eb8750165938354614b1b038bafe64d3edb9bc9793a6dd60825e160fa44e048244d3cf549c0aed862572d8f7e9b11a5dc097df44ed4eb36b60a5369642c23744fdb3803714692cfa85e109823a7c13c8a53ae7462ca9b2aebb9ddeedc82541515a1eb96a7cf5284044b7d3308779df8d8350a88e8f2f46f487fae05f9ae0f4f71abd4b9753667828fb905bc1e1758bd1d9e981ebc6a831816a26e9cd99cbb0dcb5c6a7dc4cdb8bc4fb1a63ea18a9609746c8591f4f107e1de1cda511bc9aad465bae66a51b67a101d7e8db9ca5610c3cd92d716b00d2484f8f08e0d94fe12328f1376e21ebdfa63e712562aaeccfeaf90b3145c69424017b82999a76555b3eb38c6b87ed17582451ef49230ecb9f4eb31623677db9dd9fa415e60f123a8e6af3c716749a006756c4adb79965e69e54499812064284100998e6aa97b9127f4ef4fef23764db8b8e46f62a2e8c6178ae38a0602d9433f5ca84b6db458d0a9258f953d17816be5964f0e940824215b2ae7e78d6ea06d22d956949f1572c19c0c92b3737dce47cd098b3e3d243f8954c7f55db8a1f328fdf9f33812ffcd390f32299ec26fd4a05e6cc1a10cc9ef01b1c64b7317ed38741e893319e434f81e9f794297bef855b236f311f69845206c875e13e9d67715d0ee9db308c0a436715747d0cf284449c2ef0484e3ad709dfa2104f18096194e13123bad521084eec82bdddebac3cbab594b28c491e6a657d2b3bc87fee9565d3d912ba03a0f5231861393caebac5ece20d6790b7c060f4d07e140a6402e6c08e54b1e7f8494ab99828c90f212d94510d40758cfe1e76659448f3ce9b2f3b6ea5c8e468216457e3bd7a90fb6c21e585a08b08329e20b7612f2ebfb3bb2d62b050e9dd288da9e43d4814eb362fb8be3012e724abdd0fa4a40528345b5412fb664c1f24f856d3fe418281cd4cc2d173250066e463436fcc11123fb02ebf002fd148ed7fc70919deafe7d9365bcafe617caac4d447656df3e6b68a83680ac01617e6421a8a22b90be3ebe022605cc3636d5465daff4cec9d76b3fc6a85fe0472e2ea0fc0c90ad0e102f405b52090c754c033b83e3c81c9d80711c4d67a227b91c7ffe8a1f2cb0f240d88428cd3ee3c4a47aeb149e901c5421d32f90651b6e5b9b53da25556dc8357636a58da87c7be7bc8e64854724bcdf6ae620f70f95d92118d55fa3fb117ff3a106695673dd1352111e8be3f275cc4226aa09b587a40b214e5fa1c01c2b47e9bac47ac2451eb11b6f84fad5d9c518c70ea72b6816e0910ca3d72a050036472b4f31adfccd3d9d3811017110f880ee00cb4e7b3b3918728d9c6b9f8ba6e1c8839ea0657d6a7506d75530407c615af46ea4c3eda1a5b8eab68f2a07448226045e63a5219a43c623dcfe0883462415be4567bb6524bbc2a536e4594b7c228e325a901d5f206c31fbb6a663c04c658dec2f13483aa6f291b0ab6f0f3b6cdc22c249b24b819a6f84119b68f1dd3f17326fda1aac9474675edcd5587c16904cac1e710ca2d9756c229493933fc06cdda6c91aa26fc45ba91715d59d762a76239f3b7522a02086b122898b04db36469bb7badecffc34c31d3cd5651fca187ed61a761fdf9b44da3a2269fbb441e0a14b5980062663365b6bb8257f468b743ac3218ca2b75229bd6dbe30008656da54e2bea45adb4ef4d68820dc8de90737170179297c3221f520166b5094190c74e7859269753fcb36d9b4dcb01263c45c3138411e8ba7e06eda0b2b7ea1cabba616d4c2fde639475b285cf46c0c7006f22560b564b15f4a79644ddf52c5504fac81e76c3f52a5eb6dae0fdf2246458e7ba4f1dcab2e9e9c0d56bcab7828f1f616d66cf903807791408af94303ea6e2b1467fcc76bfa0e1152471009dbea6b09f76c6f7d42a232fdacdfc514d1dd5e4b2c7b11bcb9ab2fe9160d5350e3bf9a04c81b5890a9d07f618e46b64298522f7f31ad12f13502032bbe65fc98047f89d98848aeadb0d133d2d6fe629c14e45419ef51703d140b949a0281a5598f3ebc59fd04b4accc7207b89048043a3e5557f75b071199b0657e4f1132a642f18479f26f936741670fc183d71dd706d39243447fe1f496958466c56c1dca0ff10bfe62eb4d7844e1895b3a3584f25413b4558c180ca633107514c09da5d745ae64c45449698ce079d240ec7afea7c6a3ea1f39d4a32e6560b330ac656bf5ebf216cf479088e7a93fbfa96fd242bd873f0f8a4372698562b098958b3bfad58f5822e0fca379c1cf645e3578bf02ce7ebdee8e03c4729fea2f70a17b6bdd139237b8549d46abaca188772337f387f78338bcbf81386304605e4ea0a7af5a845acb4c8fb2bd52632635d775fa14f0e642d40cfe983882b05b08c0297bf05cb35c3fbdacc87136778ea561fd42c48fbe197671dc26fe8169a299398e053a68e37ed4c631bcadc3ec2eb46c9cb8af04e3398323ca6c28b3b4121aa06aa4a4b4352a1b965b4642c07a162782d546e2845f13520507bb69fdc11e645ef486bc011da011a03ff553c84046d0cf42b608f96420d3665bc4d7cdffd09648e7ac18b30aa723962efec4fdcb051b88c358da653baaaf5eb4029e48e1620adb086a58c43fdd852609fa434957065bc2a9f147076fe93c4e2e81cd6382e3803c5f085b054a8cbbd9c233495eb8d0308b9d5489297f3f271ef5e386134539f00e6aa9e5a5123864290759eafb6e49018950f7ccfee78ff5b56e4da0e46211e1675a6883135bee3107b742f93af106eeb022f2cb3b2c92804ddbe32e2dbcc061b90641774e7b351454330b1cb120639caf18fd8cd577356b8ef0fd84c09971dd727a0d55f21867f8c2895b023d71a3f15761a311e8a37abb3eb93b2fcd1793306f9e151805dce92fbcf63133411f3b33cbcca0f20bf2b8a68de82e42df33833b9acc2b80caa2203f6a95754280c2a1e05f69319301aba76835d4ad01668d9dd94e9eb648b25829e3dff78b6c13ec70510281caecaaf007ff266a7fb451819276972d4290ef93aa7ab11934d8c63be0e604d1e8e3aef101ce1041c07c1d139f7f753687c9ddad4d8ae5997db77fdc41fa8167b682ec3821bf33d405c779332fe814c864a621d247b90e347bf48fb87eb872c7c191146410429f018d694afae731c8c58c7ece6cb73bea1a94933720d2d3bc3ab7d4b754520ce4cd46ab0865c66d57275f8c61a3a3ab5a36529c40430e779c337015aa10d8273703431439a7c3bea12b5e78138f4b83fed35b4b25f6859c6eaa2c03c1d9a3decf053228b876cba541751b504e765512a3d874be6ccfa2f1ba807d4e15e8483ab3041110f99213fcce3a0ff919a99d2e86815333c9d61d2925984a2e89021a3b29e0e7c110082f2ae29666efcd8ea5ca11e27105889fed945fb6e65a18694efa8d6e98027998c66cfcb82dff84dfb000598e3c7724bcbdb0494c8d8b097d19b44d5556a892a6d7ad89c8ee0e7de702ffe9befe6a948357aac14aceb0aae4dc8d8eb87a47731b2f5c765244c54a981f62b9f892e09145dc57d0307bd307a600ae79744fdf3dd092e51564304398ede22f7c20817ee2c4071eb0884917db27a8d2a9f9cc6f0f2e82e6900e1b6c74ecd26140d765841fa34d6d87cf44a7ec40baf48bf31f44c99c9904470ceb05474e23ae4bc0a28ad060fafdcfa504b3373d992cf6f00e78dab93558ed75db20e2ae1f5e26e8c46692be5db179f021eb21335e77c95ee5f66d763a0aa385b96d675f612563837e5211f2a7ae36851396850967f368d64051eeeac5f24fba2c31b3588d31d2da37f73b1ba7470048ba366e0b86c09dcbd108d95cefd4749e5c99250ac8d85ab8a99641ac59c23bbe85cc4cf53c963d73588e78460ff8f217ed133a7d5bba49cf88c4e1529e38231e4173f13065f5863ae0069daeb3378160c7ca2bb47d4d0fcc9c1a1e199af0ff56dfe6843f7f1ead4758096c51af8df81c013655e3e30312f671aacdfb2068538a90164271188000f65fe0211a0677aef458a89aa578632ed925aede5f4f56447bcfc5ad69f0f8e676d0f9fa31c0d7844ca41086b9ddfeba44bf77ae8c7da0fd8df7cc80b7ac69fe3f495a2c454c429a5689491fb473c4e519ad20b8bab134ce819f3130b948087fa68b1764b4875546fa0fbbeda101497eb4f92d0a70e034102e62a9cceb1562474ac3e0c66b7111d797f48299a5112da4208d64c4c7d115b536a73cbf76f3cfce21c623db2ecef2084fb4d1bfd637a302dea994d6a2326a28ebb433f1ad34cbb9c4bebc1a31498ef6929ddd6a4a3d4af14fadd93c4207b77b273fc7d423bff3785153eaafb94666cbb0b24f9aeb50bfaed7bbb4f34ab0b56707e650d231ad8b9c47ce91e600e2403f11aef3a89a9f0a42cef3d0075b95ccd6e8d5b5bac367a57b59e7c09ceff359435105935065f30a63e8f00c448a92d01df58e5051aefaa50f192890eae4792d71c6211d603e44ba67380a57feb424810879a25250f2b81f62c028a124db1a9437776cc941e152f80f39f315f0c22b9ce998e73807e68eccd8c1258d3818586f0c0c223dd82934355208aadd96804102f9c261630ea5fc8666a23fda2618fd85f182c0b35d230309c48f01c6ab63874263c6b4764b7c38cdacf7672ad6e892f08fc118292a785418abf6e5c339b12e83624bafb424e4708720bcfb29d96dcd82a5fd4f21bbd070abf014df914ca09ae00b299c1bb552e0440a6f0cbb64852ca014b1a340e1f2372b817e5372509fc645b7e3d9caf8ae5c2e3b8a4520b78ca313c8f6e4a5c6c8e98a14fc7a844a051fd5185385dd8ef86288a496c2a07703519b1349d967507818a78c72cf37edb9678086a8becbdb9ec5e4c9920950e9433c6a03ce643ef9fde93df34d5dac45c61860454a8a2a44d3a5b81364d21495dea93cc9c382d3cb2a5011a48e27bb7742efa12628f2ef70a8daf58ae8fd5f67fe40982c9df97aca360f6380b8264582daaa222bc7d12c24dba7528546a656eba88d72c641bfe5dc0ddd225aecbf2b51a138bf5eba703ff28ec19f23ab4cefa7429cb29ec91ec52403a0f3cf76a0cbb0bf0d5cfe5a8abcd79e3f421c21f1f0d2f8a8f2bd5303833788256b45cfb6e75f473cc12a61a9e6cd919900e056b3dc09bade3c6bc18ff8be58870e030b8e8da66bd7fbb5d27723041df6f1c4086aef30b4fe4191f270ccd6dd2a95e3dc4081f807364ad1c153d542cf8ce3d479113b8a1d07de93fb60e81411ee11043680b0781dbbc85859cf2ed8dffbae908e803b57fc63af13b2b511a7874e5445f8f5e5af844147393a2063de4f1b4704aadbdc94fef5192b0a877c8e124f397f75f16995d63ea8f0896b439321b5e3684c60bc2dc0f33f139ef2f680294c0e19ea2826296c46b1829e4ae423e072b66af08dbe029d5f2ee7b1a70fd2585d68f528638078d03517dd6084899ab9e4cb7ae6800da54f21ba9ed3e842fbc090508c7d623469e2aeb418869b406fa7270d1d66336f793b83024f0e46b9c557b97107a0da1b071714d3953689a3e0dccdc9ac2a52baaccbdf634c697019b635ec0c48614f141c12ff89324f3310b284c94788a20ec31ba371d01cb68dc8324accd779659c0b7526e453386155e2ef31d10b3f25fad0c20e692eb71096f1ff0dc5f34c649110bfd8de66b3833329b359d92320181b4db5915800a92e9dd6f3ef7dc4de363af968c9bfb2e22662ab84d42ef34b0672ed0caeee45ceae6462ce2ba206ecb46073242c10b5d896b1f83d81734e8401183ee06e0ab668fccd96802611a330525868d5c4cac6b1b9c84de135ccfbac0ffbbd3b9d4768f588b7b1061e098c7846fc1980eec9624fcd8cd6a8ebaac1d8b6f2fc1ee32c8f5359f920fd9dd628083f2c99040823b5945e9606fa6611ff40fb95b32f7584c808fd055f40cc42a47c2c4c05af8b34eb2b61166577ee7ec3d5c5964118c95824b5b51b1340945874d5496501453a7dd9272b7b54ed6d2afe60458c5b019efba0856b1a907bf640b6cace27ae7a25bb56d1e7f32189527b08a3dd38b371a793bcf9e86a40787bd96c19e2f0d4693f48f5c654f85aafa5d9a3fc8da48fa07392e684688477a8bf28e068a3d58276dd767b731189b43fd59f9f60b39eb97619ef3918146fa8492640ece28f1f1dd3bdd117abe7f17179f2f5ec6e8ff6087b3991ba1ff828631bcfb5513c6db209107a20228d0136a8aaa97410a1b6f5e0da323a41e7562b6863ceb73b1e749889933a2abfbc9e05cdd1b647d07271789d36ec29021d7afa523214920ab20b0b3f62947fe113dfcc6c838ec3659218b211945033a24170c55d1f138c075f4fa791f0cfd5233d12240f707b5d2473543d3eb5f2e00a1e2a1ac44404e882101f47e901fc3313ac0ac9cb70358e5cde3fcee4abf6ecf9ae64a1c1357d29f7bc34fd5c0ca71f0636064c344199825468d0f5cf1528a27c0462003428c94736111a192fbfcb3e888c5d6eb8aeb035494c946e739e8fe4b8fee0619dd5ef1b8c605605c90eedf181bee0978361a233e13208391d829d57cea0e22b97c341a18285444a796facb826f4048a82dd28b2f6a5f0aeee0c05d62e580902d51449ad9f7409aeef849b16be8ec204b811e09a2a8b6fe17912620834729d08d9e1121050e0549104dd4310a873b885344f17be77d261e85613a005170158ff206065ac6143d8889634b3794da690955d5e97ad0cec49f7efd8f53ac2ebe45fc9341477b5c0c4c60d21aaf5668a141c6de44f68071c7b768bce754d102de797aab42664bc742d4cdd788ef7a655be947fa7168b473bea5d3a0592523b039b66c014922a266c7f051087047fb68c62bed676de7e4e3e88b6aea96dfd97c31d46da3004604499cd528ae57e4207b2f1df70680d85a2f510f8580bf85c4f713271febdc96d1aa27091b2d3948b42041af4437f42e8bc0b72b2219fc26d1abddbb7207c7ac18caaf16aa8bf854ddf05837d8521850f97113a9661556bf59ad46309e13e4eeaff4302a868475f209218bb03c121646150bfc4016670333b14d98e1cd02ce9d80d25d0db37201a5cbe5c8caeeb1c53b592ae4a5bbfd3a485541e1bcf93c220f4ff335376766dca91673245346e07a2d6a5c27c85cab9c05dfd43489e2123365d11c1b27222c538084e8e7c1d1c923667b3c4c48b2b4b732595f4ca13e23194f5ea9e0fed6d6a0222b25065bb906e6c5c9cf233e5191ed15ebe80a1df4efaae9211fb612ba59d328e71ea38fa81a703c5cc34412c2ebb4aa100b4e0408e6ff13f6e1b68c233800d1781a03dabc694fcd3a9b1dc64cb086d438b17e59b50fba17608ece1af052488d85ce062057815abd1713fb9b8eeb7b75cea8483f861174fff66d24467ac34c5967afb4ec9a8ff6ca09c9fe22bb058d7366d02a4ea98ccf44883b7a684d6ea9de5caa267001f9f2864606dd61fafd2a1cefda5c32e5fab9c7619d9441361f1f84aaec038aabdb8294707ff66af245a698e8f92ebd56461ef04a2f304956add347cce0588014e4084640f70edf3fd673da188700043461339433ab9c22d8e24e300969f1042f9974a97040a3aa35da1a6cec2a42d6ab8ec51d51b9a5645aa654ae43f9fff634752885e05fa2b905dfa5924a5c7e5fec08000db5107862b1dbb89260cb793221b4b1c43e902f2ac434f2f2436e1f578aa21a683bf07e7bb6f06ff42282b4ee5f14eaf24cc7998c24d1a34636a2a8c162340356ff849798a0c1c0c942645fd98d00d5fb6044cfa91611d43b84b83e295d57b3e6fa05fb9c357a31c1adfb1f15f985ad3df73be056ef6a6f2abee02ec541ac160b63cf52fc0bda7f034412cbf731f7c0a86a4b45a83c5f45f5f4aef407c2573b686e3ab4287c9e7e48c147b73c670e3c42a0e2170dbcf33d957f3e137e8f31e1954fee7221b0258fb8278f3bfa8bca69726fad3a10539eaa9982b36ee32b66affad9053abcecb25488fc294c26c01a69a6277830cbf12a5fa88a3804ae6c726d1f0ce4ba8b557631a72f0de95401b2eec8d95b155ee8f45b0e2ccfc19ebab673802b0f75069cbed0e55139f1ff4ff6ccb1028b359c462f608a0ccb25bfd22d287944e8fd9dcfbaaf7097ca9406eacf81751148d1c8b8d4fa16d2f706a0122785fe0a40d5aacde1015cd4b10828738f0711708c8e537c8eb2c981ec090a8d98e53dba5946d2404688da265474ffa0d6a76fccc540ad51a81b67bcf338e737630d12e0d11b081e5ff886823bc26180bbfc1822390149b988ab7166e5de0c31f6d903d98d2833ceb294b64e0eb63795b18a1a9aa330e7ac5cd61db778948bd64378c7da8d76ba5034ee0ec73aca6583ef0a015acd4a637828488f52a48e0928d49d85b07739be114193388334385aa3f5653a16e39ab31d97a7898024023aab3a450e7edaf37119389e5a4c1fb88c00c5199430260ab8df08ec1989b5bb2546d46cdc5ab7c0448ec24b3a5115b45bcfc930e34008c3b5a719f010e2cab2d17a0baa66aefe49cc2478da17567a17483c816027198849b3478720faa3c5377156e11113d0fa1af23cdbd04317033cb653a756ac848780eed288592c9cc96a100fc24d560ca71940ecdf4ed17aa2640f63915b4a80ab3f46177a04cdfda01748f171af39502770eed2ec78f1efe9eb598f15e5f2a57382c52cac5348d454e1bce11e5f760b54e7fd3d3221a2fbe5d13f01c1be7a40a88788a09294376fd402d1ed83214a603813369a00591e45886e0431425f9633567b2572df86ae4050c3ebdb7fdb4cf88076c234ca487f95970e04b18b2824525142815a3b1408d0a22c7c80c6ee840486dfbe79eb9acb3976cb853bce845a1991b20a50f83b8bf0165b462c2237343080fb3ed19ef55001cb1877de2fe4c44f39f45d9df42c7d08d54ab7a5cece833cc60735db33425303cb500a6a2c5e9b398aaa84af8f19bebccaa4abc3f5139c00e222e3c0e9a26b2c085f5b7fdae1c5359b0b68cad053e1c29380bdbfde4c48cd12a8351ee482bd3b871ac88387c5575a9039497584cdee070a702c925fb531fa0f7ad90c0c76fc12e9e476f4751dec502d68c5d01acf61c24aef693413659148a1841636429d91194466cc8dad0990d0214348eb8e1999ceeb3189222f793aa0c1efe8403ca2f58226a03c92b5ea95e37b8325c00925015c86389e8ccfeb24844887206319c35c379093d0915fa6146ba153f4a6d13bc986f5a0a864b8f42c87ab3355c462e8568e40aae7b7e485e5a33f43e9d703982673f65ea9694e65a4d9295796f80d19e8db4a8f452a9504918b3ce718be16e88050e2ecd43108e8899c6574347d5b886e8a3c00c0ffeec3da05a130e330072e2615b117710c87c9174a6e7762901dc7fc5292003f6df4984b5f618dc51b4146fe1d058109a4be390647ff8c806c23be839263687cde5590c509d00bbe8ff3fab43759137c8e636dfe91fb2c99b25bdb269bdaccfffefcd1a46557291ac86bc95449cca94110d3fd9e76fbf4b6111ed28307abbd4b4dc8cae4d286f2bda4023b4795a8d24dc29e5cb572e51040406fde2ce31355b32040f216057ae93e6fa9769ffc959b7ff78931de61bf911a585a4fd4fb24c05f631162f0ecd78b91c4c298c592df46fdf34bec623ed009803cc3ad40b91369f0306e514a82cc93ab0473c184e1ad2e60b1d52b3938b0332340b62e778d4920926ecfe74057659103721eee3ad6963c480c15d7f3ffb6447dec2cdfe8992c1913744bd4f1fb89232bd7f777943661bd113eb744abc7aa009fb1ba256af33e73ad3c76d81265d096601151cf2ed5129d7757f33dd90fb40e93a99a04be9827c081ec144a3e2aec0303d93a6d1fe4c78d5c3613b86ebad3d4eb0b8d70dfb0af0acbb2c629b359c01745d9f1592c13b27b472e774311df0108130ca3df81249eb36dd2b83ee21cbe7c7183409e5f6e0211a667172558b8d373525cd502e398fb433db5be15543fe043ee3c0dd045c62d9563aa7241ae770a09e0e4f7453cf1fb175af06030c0b36029cbf140ad0effa78fdf58c6b2db34e4e394331b9b0acf5fb8e36b6681abeec871ebf9653ab23775f41b4125357b43613a29654607a95c5696176e2e256a16265dfadbfbb50a5ea7b8f4c044f7520dddc6613f03fa16bb448848ae7f87a4664dbc19488b29ca5807223218d3dcfe84129491bcedb626542de7602e90e891a1d69c70c0885b0802660df92efabdd8061452a98127743882dafe46e65ec0c0a4eb75df314104f878316846f89f7f4003ca36d1a518b22ad590d12def2667819a7d3c984572afcccd7d4f284b394c15f895da30da3d86028d3e32732a28867eb2fef2540eae45090f1c34e0d1423fdce7fb3b6efd8487ed01502ed0c159a23294168a1da0b7040aee044da21fddec8a236a51bd1be83aa7df6a44c48d9c34be4df13bd9d737e97a30102ef913afa684d52274fc46dd1b78fd2357c4306fbae047f98f090eb7d2995788cc80f05b3168bc89b1ace9fc9c409d131b0b1562583cea177cfa3c8b7b475a6e8e7b377e0c82b08c9bab3d0c981ec6289671b31f41e375fd758d2fc983d9731194aaf1b034e93c0406bb2aee29c22a5c0ea849acd34a468787c56d3380100ced2f427dc4cc403864593044fab9e6468366c3a05f8e6f4219a23e95ae2f30c156325117e8d4c04526a5222a5cb11a78513bedf21cf35f275d8407142c81d7e1922eca26786723e00274f074f318312807e2e81845f4ac88ee3b00ef4233389e2d3f419a87ef6cd2b2d150e9df85fb2e248078927d76bcc31f612fad331519451daa8070d261163fefd4f0f375e4e4f24cf703e9d9531fd90e0b5e385af6ff6931533761b8b4d6828878c15f4b33ac21724e32b2002486b2cd988f6cac379507911ebad42404bc466322e64b9d92ada2380e779a63570b84d9ab4a804037e6ff3001a83d112be89eb401fefd530965343eec29fe29c03dadd27e68dc49c59d13efe0494942c16891f5a3d93913652a9f16b60bb81590a49e1f59f43f4ed8df0e194d680d4f34abdbedbd431cd2ceb68d3c2309cb2da15d5ba36147e46c91544258f6a99b8a4ea436b11e0a4f9da8620a0b9139e0104425c7d9530a5cd0e6ede9f633e2b3f727c081fea75214f7058ab32c11f8364681215eb076b42893945e6857b78767ca1da076e414125408c097a29d70c37bd1d47572fdc6c2114a4a0a155c39c3c532312038ec2e539c8295eb83390f2e607d02987e657269a311f2d49f9b576c73f93214b9e0149e1cbb368c368699a53cc2f836c20e85b4d151ce27f37b5faab87e88205e2dc112eb719b95ff22d751c364bda029170e39ca46d51f67150dedd1f4c00205eabde3621e407df05d75ff2ac545ca23a6ad6abe0aa367412fe48aead62ebd33345f8117a6289139ab1454887873be900dc5deba28443d02e0909747635e83298ddd05e6dcdf0c1a7b0c60028cb897c8b3109214a420491ed37bbcd735bad9e36d81b21081971109cec4b19a3b7b6387e2d789afc586c9c1cbf4e9b7eb7c0a121096bf00f8a98463e8ab90229edfab7da07e4cf1c946aaea0765d7b4cd4210f6c630f2da21f91673efc33aaffc4b2b2224f779e0deccaa6f15abd942039829e73dae5dd86c6990ff05fe5fbc81d220522445a4d01f577e680325c40e216959ef24a1550209717e1e8207aff841233b70de39d1de173e074f502b1f0d3c5683d3ef28cdb1d0ad1a72649bdc63be4b163ced72c7725aed4dc2edadf4af29876d1b5459ecbd07e4804399f2375db78f010ca6b33e82f82435000c98eb60c64fd3bd643d8753d420a32d605651e6bf0d349d15884553ccd9c603acab12b1ebf8519b61ebc43478680e73fbb7e32f13c574b9f25917630ca8d0a6c0c6709e32ef6d3214e521d7bcd2ef9180e2a615bbd453c190d965d33e93422908c9fcb9e14133c203f71503ffd3c18a62cec69570f68330a9fbb5bee229f15948c508d9e26055448a61fcab54b0b1e2736fa90135dc5544451ca7c58c080620018c15e705ec7620295e12ba10d11b7146ae2d74aebc149fc6a8438e49bc12583f2ee5bb5b90e89790a2bef639ff72c4140ccd1823f0768aa1e3ca457a83415bb848889626ba17e710dc3b8ad214cec7d786b936119790e29909312fb8610f28deb7f69edb54a504378a5598e4b7f1327348a452d6b76da4b7a8e90dfd9dea445ae25f110223b64a97174a17da47179e01861bdb6ed9177e18a5c73f82802bd3faef09fbc6b94adcc00189617f3a068a7d25e7c6ac066402585066d67e693712e049cf96e82dc30f0f9971c78d872700de4410594790dab8399c03d7407b63f94cb3026844038f46c06fd10e54286cf5b4110acbf83f7f8ef033b2f2547faf2d331ea9e77702e71d3e8cecddf148a5a492f5584b5c2889666fa29f815c90045fa57de148ceb8bebd54e994eac00364c881a20b1854be4eaaac7d819df6b0ab117ad054da003f3a637ac790c6bf17cae08e363c580da52ff7580eb4c0462d8d36b2f8f2636fdd23b5457b37f2aab393e7d72ea5f1d881e6867304c1e1ac06dfbf5f002427ebf9df3639f8744b72ece811e3c869f07567051bc8041c5380e94f30300ace17cec8bd3034c270fa9ff54f0f1707fd607897b09f159c685d97427123327b8da5cd25b2f0773985b3121e14babdc2d1364ce1f960c00119d6de2c2e05ac6313289b000472b2fadd898f4b59dc1bc46abea4b994f0963d55b4a60db298688271df115533a3a80021e2de8e1108700794d23ca610fc0459760d4ac359f626f2a9d6b7f64d59366815907016d5353eb67ed3a07c1762066bcb8751f26177af193910e9ae85156f2f024dc8025a588e0d3b631a36f0d9804a76ac7880283cbed449740247f958df590120a62706d9e3be3a32ee5600c8f205c25ddc8b8102e2abbf1f8703aa99207aff03702bdf5ba3eda738bf16ab60049a9b750cd1b98400d318619451d28b5ebcd212cfda41e7b740cbf277448ebf7a52fa440062a54bc8a356b002e49574fbd928d470f5b1b7d9cb3aec6d8326fe64d085576c32103828a5d223a8407172b67bf3f0176bf126f767fb4140b95ca15e78401c4ddbf1406db3083367bd6fdb060bfb268ab91338ef4ad842c2e797549e4e95105fa62ef2230a6229baafc64c135801743b1fdf64c2703bca467bacdae03d805d93b2d607dbd3d3ffe06396a32bed86e84bb06cca07afbbf434093853aa50e88419f93cf0ab5dc7ee7f6254f0d80d439666b16d0afeb3f40a19f8a9ab7563ae842ee7d1e1ed0ff13dc9912332f4373435219dffa6e0c378ee54b9584bb16b70a16a753c6e05ff24d01177a2a84777ff5bcd346e1a3a289395fef86369e662832b9980c9804cc5f1719fef52ff6eff5c446025efc3693d127eb1ee6f055d111a20cab233f43a0fa87cb88bb5971708e27d3a7176d2cc44a07ad2f9d86a94f9b0a20de214ef4d1f630c9e1b731ee7639f6d9f53e3ef714880bbb50d59be00779baea1530d48dd8a3f161a5b0461caa3cc02f9585bd0b69009aca34bf8f9f8c349a2e8d74803fc7d139254023839fb1deead10822a95a919f4c1a41de18f29208d0768bc39678a96bc89871c64a262546283b79032c84ea0d879389960ad13dbe138c86897c0364623b356bed52fecf23df6823177dd5b000b57f53aff88e00b4b261a8ef8425621a9e489340e80a23255f9681d4f6284ff24d1cf962c9236203a72adb0745e825448bb7ebf7d62699ce3861b43866aaff90d058a1bd14f3750130426c89152c74aae0ba2e49b8a3d79c7d318beb234321b2b5008068b191596a24b32ec7385fe9147e8434b7009c0826b2231e2a1404e1c8590bf8254f47fe1f506a18b6e5ca912808759883de3bc51cc8211b982d5f78e0c117fa4d80f08664404fd1df6b840d41298ab0fdb807c3d8d592a3a111a74ea9a96e4ef5a9956c82bc95c94604c332db1d810f7b2f36a278bc89f052d705513c9ba052d6d07393a782274776a79df730ce804b4069bf174341529b25820dac0a27e919055bb6b7af74363964508d3769f9e49dbd90d42184a679d7899c2f9c7eb0a1bb62df46f995f1cdccdbb5f8beaed780d5a03e9ba618b0554d2c9f06f3b400367400bd46f1dd951b90d64b7ad970a76cef21c8381eec4abaa2557c64eccfe012e68944044109443eae364c720652281170157103e4aad40fa62ee0d8d83fa03299b915a3cc47c12f30a9e0ea27c992234773b0e77381bbaef066c31c789f3cedda8bcb85d1ccfae635aa8536ae0c41081c8708e848d6560b577e8190d7be124c43be19a70a39a15f5012b35cefd1d786acee1ba6fbb15a83a05649d2b66470455377f3e24d10bfea9def41492352f8de019f070f5013e9dbd561cee1c1f672b1778825922d50425003c9b73d078416f7e9dc53afd820d93aca071d16dbe47b410134636352faa14ab5251752afba521af55348fe48cd4f0c7670704ced4175e001cf1256c7c348038a0a54bed0103ea16fb0a1010547185d66f53a2a760b8faddee8245e9896dca9080dc949dea0c9f578f43c508e22e557cba25968178a4fa89a020b989d0b8c1e8988e08e8334858e03f7c768c875a008dc1e159e18649d2a9acf83d73b6375e86a53109dfdb6ad023847cad77f6d594f8b306c2e5891dd506c958d23e57a7b3d36b4cd38fb1d4a69c6d205b79cc4d9093a0c1d9cea3a0cf20c87b0647b020debd423cd4fcad782d3afeaf36999adf8865be45514fe4af006bee5ccd26f6470afbaeb977bc37976716855d5e317e96c4e9a42e0ea292f45fb141d00308c708bc7b1e7a8da9ed6e58e9f799c1391b70ba140c23fd59eb0be547ff998343598167a5d7a984569a6ca25a455f71a27b7149fc539ee791060b37a61539a0aead5ec5a284c2540b6cf173eadefbea40202959b804e3d725a21273052105608fe772fb5d1c4d40e865db1d72eb0fe578ff5325011b66a67048eb3e4627724bb961afe010dc39bbf1a89eb41f286e1d7bbb6a418129cc41b560a01478468303fd0123849b5935c591c1648632a098dd1818e880439c9e54dbad95c127913a375749691fc49454b3d9aa34992c9f8899c816c1cee114abc0d22c846b2562e4e03f6fd347109219520f1349786838855fcc592dc57be637c815e0486f806ce67dc5d5c70d314f577549e4de8bb9771328ad9f8a8e614de4849c0242519315b4de94295d83958da82ead4f39ee063bcd6c4acb828e11de7408e71c0c03f4d68870ff3d9f85032065158e3a8408811417e3ae20f6ca933559dd3b9ab1bcb5bbb83b81df00263ebfb0b5d29241bd32ce9b74f72985f032e59841b25b8a7a1c0e0faecd08711dc0033de1d28814426c3968f36cfb4a11c5f2a656e7f7c79f2015308eeb916035bc5a33de0909e301140390470643ce275c40c0d2c226bbad08b8c0df8a8937fcf03089a95aecc0279a2f5d2aaf3e5c7ca21e3bab20b413e0a74552973212083708423b79a90b02a697b44b5d96c0a92a4ff2c423d032c74c4fe2314e46786b03d520ceb4227fb1910d9510864383c2cc5169a0db874de643985dc9be30cd9fe6756c21ba351994abd152e802ac55e07d9a15c64884528a6a57e5688e2ec1918926c8670af155e611f199d26d85030cd1c530dc6c057cf855fd3acb429f943c9bf4ea458dba5792442b666f3196bd38c3e2110c72b19d16e4c22671dcbdd9bd98cd5b54aa560cc14a8e4e8b915c5edefdae963a546275268fd50a19628ca8f4102cf60e79cb4183d6001d083e976ecd3348955c358346b06fd9b571b210f757bc89374e8b20fb37dfeb00955063bdb1c7b205fe560b67a67f135fc849644ee8bc767f0d9c88058239641ebc26c2050a793a6ba7dab40370b428ceff451d0895e6533c791882f9362957ce83191483b4df352e2519e9afbf3231213d8b68c341d11263cf73e417db176237e6a46bb0d8946c6d7b4c0309d4a2432796e1e43e7813e00d6fb2952b9713dd91028a821794733ca01f04b5d459fee94204b2c3f7f972708ea2244b9bd211ac1488275a2d370c780e3e41c0299db388d07476ca9f6ac308ba6f9d7a369ea5c02f3e28d46125085364e1862a20e82da591831c9343f1fcdc2e7685f21602691fffe6e3b0491258e5f931b212128fdc346d3c1d461293c3980e31e4b0c9d8c62675490d1d956a78dd05718580c3424267d5420ca63f62441cfcc69379a79066c53053747b936e1d19cb3ada8f1a47cc453a63d28e670b1d507532d497d968b441d19766641af17fb5d82fe437774bc2ff62e551f2917e307961306f89ba5bd2a474c3cf7eb04f1e4b6e8fa073af4e7e5e7d90a666687bbbd8b61d26eb46b7e1f10e3b4c58527081c162e3346d5c56b16d9232742ca116763e75a249f2505b72fe99bea1e3d5c39c247b6a4b0801ab24f4ce6652abeb7b0ed2e06526d2d2272c70e388766a89ba8c83e3b65859b551bfbcd8af177c62020ab8195b5f400e3aa2363acc36a04fd57e7d32e4cda7fe012ca22243e04e95bd63d3cdc99e9176ad479150d869db800e34949386d508288bcd44d863c01e513bdbfc51750e32351cb91cd483866e111b220bf65914a08aaaa2fadd9f484a22422bbbbb77bd059105a905a48f41c4bf87bfc1077c1adc1a74000779ba4e7abde5de7bef4973487a9e9c79bc4e7afdc9f9e52f243d0f09858261033f61845fa72e1f1447af8f73a45da6ba4c975148b8339923dfa67fb4fa50922e9954a9f5175d32a9b2435761da7c747e0d8306de23462677f2d36edef2d3a0bac7557295e0d725f9f4fa3a46a6a4df99dca111e18a9e5123fe4947a05f27bd644ec77f640e0c171f49396d83b1c91dfb9546f548b91ea5676b51e345d2a9a4ab3ee2a719217ff71d2af77184ee848cea50772673286ab4516e32c7766ae1a251086efd797625bb616153433323738a817931f151086efd79b9c3d7762d9712898f4270ebcfcb1dbe964602980db2b21acaf521c964080a58511c044a61d870eea40ce1af22a48fa97e2f932a3a984e1d58d1435c1ff957251c6061768217e0480243419095d6501313b7f967ae735a40d3f0c83e5134543e953f512bf415e654807ed942ea7029658c0380e2620fb22a06265e4c91c18b5b133938e92327410dfaf8bc88137de42a1da0e8e3bfb04205caa562032b7164ffaa2367ff38292a38e8e383900229415414c1b0d92c714430b4d0a30a0f1b58f65685945cc590e753c50d3aa6307ca8b0a0835d32a112c319bbda43eae41f1cc8c9e787c86a845696dca94ca40e8d999319945994d99419160a4481489d0d5417f4b30f1fd2658e1a1902c94f974f5d138acc51f894d3c44271c85a8ac92b3921e143f49b912e7f0e913af33581cc1f3d5e13c70b4b977f01a9435fb014e40efe5b0aca3b3931e14a6a1284948b174f3205903ab45667c89d6fd69f1ad4e9d76ab3f46f5d529f74fab8d63adb7595ce6e15c415438bd51343abeb56413a7dcff5b57a62e8f4770bb42058e9046747f696d9269d7e688146b34e9f1fb14b3a7d92fd29d952a9d259ea59716e713e3afd12cb6565739dbec90ef574fa2f2b180b0353e98451c5f8786d2eb0249dfecb0c461643e448a77f92c95819994aa74c0eafa4d506d9fbfdcb7e51a1a8d38fc9d1d4e9de3a7d991b347371349686a6d24993c30b13f3f5daaaae5a61355665466017109dbe4cacce489126480d4cda581b9b4aa74d0eefcbc8ec2aea5eabb5d65b2d4d15777f7d3628369bcd66b35d9c6d6c7615c17ebbd55a2bb641b1d96c36dbcd9e066f6e7615c33e6b6ec5621dfe705370381c0e87dbe088e4228abb8aa3be815cadb5e60ee3a6e070381c0e271b422693c9643252c904739a69d162d3a8124aa7514e58e8cab341b1d96c365b8771381c0e271b422693c96477b55aad62b62ac64f33352c1e55597287d4e5eb0e368dd96c369b61d72c2773326793b9582c168bc52eec769bb7799b37dcbcbd5eafd7eb25a34f6bb4466bb4466bb4263fa0b50f3e48a5fe254a8559b19391d7fa41aff3c78e85816017c7ae117685d80562d7c6ae4e1f6bdbb25d28369bcd66f3aaecc2ee900b0b2f0cbcb07d61f5c2f48575fa36531b4eee745370381c0ed751964ceee021ac6c5b59b5326d659e956559a74ff18cd995c5615776655776655776d5e9cfefa72a913a9889e791483232a28851a30b17285c7f3afd8bc24032873e0c183806aaf5c942b2b0d6eb6c2ab0408bf4442bc716e34a27cea19c31d07befbdf75e8131c638a6780207951a3cf91162120afaf2bd42b57e6f9d3dee65752eb82c10b1ad198e4801c50e285a86783af854fc830cb3258c9032031aac0aa8f4ece0c305fac2840531248722846a0092831c42d2c5f7de7befbdf7de7befbdf7de7b73ec761d2ee2e3853c7d64de01638cb15015b288b613988d80065a90c82141c207470500f7defba4881e6428024bcc85a2d78d0e433730810e970e4670a040b845654d31a2c1d9cd129a7001c105b9820a223754d144b883bd3eb84a708354cf05530bb9f75e57096e902a23b7849327a09019b1c5864e888824eba402c348c8f4865e40b0008a233a58b04fa6108522e08a807030a2090d4282803b4c9c690d51f04089a8fd48020742d050c4051a703168c143dd928b541b5346b0f2210724c5112038d41cba1ecf624a6b9d7203d2f45c35f3525c2103a94bda6a04300840875d57acfae3a4ae80e18a1c54052a2195904a4825a4125209a98454422a2195904a4825445f535145850d0b835dd00676b9462a2a5454d86c2a2af87c19ce8ac23768d5147cacac3e7fac2c0e0434a22e576803270cb6254ecf504dc1274bee7894dada0d7034edcdb99d0e389d6a6ae8b4ff54d23f9dea8dc963677571295649e1a305631071fa7482372447719a659e5e485f8237e8ad41df9d6b703cb8f69a4cdd62caa5951cb4614938289c71e733ef8aeab9779dda4ead2a083e9a28efeefc401bd79b99f39b394dcd1bb34b2f13dd3a05b2702b4ae059f12a62c5ca8a96152558a263ec1232220b21d14de101dc12bbac221e84eb1f2778140e856f1162b7c0b66459910f7bce49695193a29f6dadbd570b5017d4755dce454545547cdfa7f59618b6f8d822e45a1cd28c908a80a7021657d1c08b64e8fe715245418ad0a1a900ba89e6f941975ba7ebd1a123058d25a593c284f5a7b85d7890ea13e499e9f5ad0d1841f44f35230a15473737652ac3459733bd3eed6305684d81ae3fbffa9842fa7cfaa2d5555b7dbef55183ccca0aaaf6f2e04ecc9ef5bc4aa787bb9c79bcaf27059933dffbf44c6f906783e1c88e4695ced106c35c380279469c34e2a418a904f2945c4c2ff6e5a5d2f9526ae222a5cf37dd4c2fb6975a9f0fd38406f54989d02014081aa32f1a84ba86828a72b85b10ce7664124932935d22b2099b3d7268fa98ac3b345729c82521f43979e60c399a68a5f6d26a2fce36e74a67c65deebc6fdbbd2b9dfbd35b8321b79c573a7938e22352c9c5644da64aa7a9e46272016fbcc0bcec98933d9d2a9da793cc8c89a6a6664bd1868565c1a2d2c92266cfd3498a3433bb66da11faa8815eff06a9575465c99c89925f717dbe5c814e0fa0d0923ee1b8e3d50c2184bc291f6b3e95677dac89f5d1834eb500f531460cb44c9973525ab42a6a15c9c0aae96060b3e44780e0839b55107c82d00f828f057e9810c283680a1035e07e589c0c8fb54ca1c596811800ce8b20fee20a8e85e5752f86f8f76388ac870be12ff0f179e023e05998b051bcb0823be155701ccff97073974c7227a85274351d1114d9c3419889ac741d5151c65c5ee9c118638cf17d01e32b2e8c2556e9e02357cdc0af00d91cae34210114443820b2425474a5e7852baeaeebba9caff858bdbfeffbf49e576657ae00f56b833b79d09ee44674be813fc1380a7c6dceb7bb75d674ba42b8da9cffe6db59b1925526e03870a225fa111e11baeed701a100f28574517564a5d300f82477f28b3de0b3f035f416a524407e1bdf5711772bf6003e1669d49829fa5984c08de98282a80840d1cd4ee8febbece3f762ef3ed1eeba45164e358a74afbbdc6d2b765de76d45dcb5a73fad77b73f4b00bd7b15af157bd0bf4556aea151b68ab56fb1487dfdb5d35e6df8f54e9c32677e30d23eff5a992382b56b2dd2aef79474dbf0eb355717f3b5076ab1d6a035343825056d286bd8af461567bf913a269d8e83afeeb0f75db765215aa95dd9985ca1c124eda0b256b9ea57707db45d5e91526b9ea1827b07d9dd60af0fdc07ad5222f79313a2cbe572433d17d447de65ae868535ab944cb000d1b108e9e3ec124b0d587e506bedbd32c996755dd7656f6209c2d264ef3a5f649620d575b25886c02c447026598884b44b26392859585956598cd82008826128afc0b2c0a04b2e845625c143b562c4ca9224f9087e82a3e8acdca6152b5d7e44af4ed422d2617ab1b2854f264444888e7821ed7c6895923985d635c308c2354bfe885f16bfbe17775d061f80739639f6011ae36ee77c0abd53d855bb311883889bfaf8ba0379be4e92e996f49aa668dd1ff880f7be5a90c7e5492ea50f4be209e4b9bb2381361ad0b3c3c58eeae276d2eb6e7b600ca26eff9339f63b900777d2a77936c8f35912ca6a9047cad4484aed973c29495aa17f200fe732477e06797227bdf6b6f6ba7df03d30dfa36472e7da005d1896dcb9fffa5ea30d500d965e3fc3b0be16ad16b4c4214d4e47365b0d6d16bcbb8f59a26e5f97163784a4534aa004292550820941144065d0904996dce69c94de4063068e07314268592b015bc2bd26cc0021f5b92be172e6c4ab8fbc011228c184d7732ac344fff435381ec408a1cb3c9bcc81da3e288450967e42f23063529c4e481a8fa22e615debbac139c50bcc2b6c54148de5a38f1288c6f2a101228bc8a8080d630629b30d788d07142a38155d97341e55aae83d5535e078c269386e70efbd57f8d7250d47154370e47a7a6839608081875dd272dc1005d75dd2721ce1b41c48f413379d6a3d7749cb01d4475e93f81a45ba2f927fe435553fefe5d5013f8c51855bfb9a76b9e46a2cd2fe89d6f614d9fab5deb6c87ebd2b9d72dfd0a22c4d59097e9f20d675ca5a4710f48c02517c4e1a11bedbff6ea97431ff2bcd54f176620f59ec0144698dc5daf5873f794f32a77f9ecda0cc5ce6cc0f3fbde5e7856308ec0c9a4ad2abc5a36b3b4db19525a56e6f40884899e3d292cac88ae3482edbe0c216a155b3190557b98096238a576badd6ea806d17191826113a19e9b0810e21928e5c09e7700959263dc38bc987d61344cccfa9a7894c4f142693e9e52507119a1ea29a30870d6f4d91b6e375b3e307da0e22586c1b1b1b1b162c762441ed29d276d85aec20c22989a083910d1d6c1c1c1c9c0e3ad8014424002092d46809179e1302d853a4b120c500f614692c6891e992c683c7a94b1a8fd707341e47a442ce43c3e85167954285444a49dab2721f7dacc992247766a75ceec82e69aba21f5ad502559239e79c271a8e20b921eaa382e9d0c20b1c782ff49831f954bd56b9a1de755d772f6d55a59fb8e9445be5a005dddd1c514801a0e5c8e2020017ba0e5e48e1a52e693a62e8329716498428279f6883fd3a84bc1b1db98f450e6cc30a6b66d0343ea699205c647ef6a9491863b3e43d5160988e31c69888db2e693d547a88b629874b8b975e21e987cd89f84649bc70870d06dc41f4b24550d2368c3e222f1e12302f31ea9cf0300b52bc5c16b46ccb43062787d7a9064e0e32b0064e0e341e47641a0f5abf5dd278281180135824a49c53be9c524e29a79453ca26526e41b65a93201b50b5f65e8c3bf917e3aecbd9933fa3cbd9f33e229f96ef7d9fd65b3e18da30ac7486f2e5ef0dca1fc9971fde42f95ccaa744a82ba8283784bb050de16cf2ad9413269fd22adfce9e1442e8523ea556ce9093d25aadbd93d66aedbdd85e8cbb2e67efb3df57e9fcbaec79dfa7f5fef4de20188623301c8d3827914a2ed6c5a5d2e9523a995e5e60668c9ce268a7cb34cd1798181b1353e98c914fe5d79f9c202fb4b8607232318e91e34a897fba7c185170f9ac2e512345a1e2ec103da87cb8bce0abddeb47561d5056dbbdb5ab44ca58004dd127e12e99e00248d0e0cffd913b4055677fad559b4c80ac430c911d02c03f00eb95e8f225f8638d419714eb2df61451e1fbfa53752aad35dcc12f4615febd7dcfbbf35617b4deac7c516b076b0c608c55893e5f94a0282501c6aaa4cf261708c1aa7ba85c6badcf8caa3f57acdf89a48e71c5355b6c9339148a74413f013f66f4e8527fc2457dac414b6cf549add114b52855ad5596cce1b9dd4b04aa1c53c0c44c2d29a3ca54ad534a1954071229834e2a842c660436e4e5e3ea75d256af94555d5454a95f262e1086c15c489709208a6118f643ab94719398f1304c8794d1252153dd0f4dd59c393f9d3acaea28eb8af6ef0f957191c8541235499f1589ec806ace9c8f1d507d3976401d506601f510c37a0884c5d01536e9211359651f18490d799f131050af75949339f561e0c05d9cb8d4e40e7e0ec4813810079a363f86551d1727d245fd1f1908f7390df96a248561bd568c72a9c99cfa2a237cd42da05edf4619e5e44ef7f55f7dac3f3f21132943ca10480814bae40efefa61930f6429233fe4e4a35bac3eab2c99339339b5c758917455143e1fbfa47356538bd4e4450e023435a68081dabf1f2d4ded1f7da8d25f5004da4bff8925d438fbf7a3b7dfe847e2e8b38881d9bf9fa08d11066cfffe7b184338cd087df41b75827eefc19fa008fa3d148d08f3f77f9d268255f7a04b5a0b4dfa095a848f84f97aee30dfa3f59075ef75288e9bf43b7c92187e057f8b5e06661f3d0545004798ef8dde438dfa4792061d8d5e8fc47084da22fffd1c355e5cdf4fa38ec6fddd4ff006a51d86101cfcf1e23a18a24ed0bf51285c5cd7288ff74e1c2fae03ad0bdab0285c5c7fb9b8d3dc2fa893da60bc9ea8b5d65aeba42c9f1d9de2aa0d858bfb81871f17f7040e8c17081feb3416b324e627c94c064492596cc6dca894524ecf9b95fee852ff0fdf0e8f3ea13505b80513a0746b636e3d9d3e5e75313152628a62723445636e174f29a5b416e3d3eb48a79f65d4ab30211688184dd1d3ab3bd5783efc9aee16119890972b0621af969452ce9c4fb5d350a7ff9d70fa643b3d394939dd4e350fbc21f10431add6f35a443a7d0da3bbba62b0425e3445655a92567b35c8f3e1d7323f419d3e68a3b50a24b384a6a8cc13991a4d5912a9d249caa1cc8fccf9fa7d708378886d81ef2aea2b93c96432994cd669cd73ce392d1e72711777711777711777719dce2e7b9fb65a573af528ffe888c0ddcc3f3a7dd9dde4704744a7dfadba55b7ea56ddaa5b75ab6ed5e9fcf406491f132f8ba743ccece69c73a23e26d8cbe2e9906ff9966ff9966ff9966ff9d64b60141086bd021d749ade37c1289d7ef7d90e05c2d0e9e35df5d7ed15e8200dd3300dd3300dd3300dd330301c8d3827914aa65d45de494e4839b809464dc22dbada7cfd9b73ce69494e48393a7dca4d70474dc22de1ac16cec259380b67e12c9c85b39915692688abe432c39ae931cdc430d39a59c91cfa2fbb8aa40ee3d329a594ba1cd1292d55d129a5d95e0de3a3ad1ebdc0a0d3af5f08ee6ab5a94aa78f3d53904edf5a6badb5d6e5086badb5d696aa28c54ab152ac142bc54ab152ac1463a144364165fe6053c38e9a24f4490e6a0a686668a1cf1923fa9c28987d9233fba686e0efc94249a77f351f8537a8cd7fb4a1d2e9dbeffbbe7e3f0abf07f787aadca686d9b1e77dde8f42707ba871dafafc5a93a4d3af5dd7fd07ee0ef5853439e8f4b1875fa330ea43d1ccd0e9cf7c7393cb37b97c93cb37b97c93cb37b98cbac9757a336344a7a81b158d8f30b957a73fb3b276666567567666656756766665516365cdac7eaa0e05aad96eb85c5dfd74fa32adaa435d2f0a8bc9b46432ad994ceb47a6d5e99f6af36f19c767eeb47a56aa55ebf44faff9b12ce3b3d3cf03a5e6e9d5e9c7dce6cb5c5e71d6a9f5aed4add38f89cd9fe51f0e74aafd0d265773e6fc74fa4fa560722693b5a8fa7d6c85209c57bc75c38ed7097200228407ff818fdf02a7b188d05843d05831599b3116b555d9685b34227cddde467be3000b7c6d0dc70edce8cfcb361c3df0243e0ac11b8e1f1071388200f5372c6c6a6866ba700c410b540ec71550f68613ceef2bcc697f48b7c9e9a886360b8e38230c2f29d1923b2c847499dcb171d1426d72a7067cca923b342f4362726766f426c81d1912511f4b4af4fa2c44db6221dab7114d2525ba8b905edf46b45f23be08e1fb45fb3422ccc7b868197513add7a711edc7986861f832e2e9675e8680a397d9b18d5db9c32edd4fa20932677e8c386332673e8c485f446a12ab4ce6cc27d5b7a26e42af648e6bc75cbada8eb9945ca37632da284646da63a450c63a449fff891eedb06bc7482eb993776cc77a65c09db4da6d456b77eeb2175a94b5303573dba025ce7867b32aebdba6ee33245dbeb53ffa7c91743715f9a8db540ca908ee6ea3d432a577e6b568f5fafa3e38e78320ea36350976a3c6d9b792db8d702cfe237368e0230cab57f0eb6b50bcf93e0d0a8a5db701aa99993640bd7e99dca8240ed7f6247443230040100033180000100a45722048821ccae298e20314000d54823c4e62442a974643a1389ea4208601210622c800028031c0188310537a5200e05270fa7e8e80c2677fbec62ebe59675e27d2c9060ee777b6f49d655d5a2cd80a322181af14d483c53151183a276e9abe88cea310c155a6098925c60217b470c0b446f60be0af1c1ead5aa7a972c434bceacb302993df01b483b915f4048f032d9db42cbf18280b2ff8d2cb460ee7f7835fbd1c6454f2c58ee1755bf328fa91f5746a5abb5d740121c18926fdd4a006d28d17c0eec4a02244658db1eaf73e2fd2b5d80a018c39f990957e649db5b676c5c981f5d1b00f756356cbfaf2d2ff3f42ba53c57a9a29889876e58a3b7a9a06fb08e077e8664fdba7f648ec12ac309a6d23207ee548f9b74ab93620c987df5e66fd637eb6819e69db20be571ed92b15baa62e511f627b37a314076cca2db00185901192a8faa347c7186ec8fe8f15be1b189c8c6b766abd79f95c4ad81a9c721e0a6aff6739c1f2d55ff5aee404a470d6f6f3212079655ae6afa39bc574e14abfedbce12fba7d0726f4c68ee6ed3c2ab55a91d1050f567cf21f3042dc4fd30c612d3a49330fbc61b5fd3ebb6a7d7c4ec0f70e247c646fe81ddafd3a463d6194b178bd417a2fefe359000ffd1f8c054cb4205a7919995c2a897e569836746d2979738915be6c4835cffe63761b3618dc3893e199703c96027e80ae0dd0eeb30683ab199cd124d358feaee0f19cd238b5c4b4b18e8958aef1db0f5fc3600fbee39e046e983a8daa5996661428aeb5c2b9b162c9a30d8bc8200f03f0e25abf6799ebb4707ff77ee2ca3af143e944daf4ef5783a2d35a7ed3f1355a1ed0a34fd5723d7c0e2dd8503506b64894b25903c25a9ac0604351c400108aaf40343307e594b8c5153527146dd9c09fb8331fe91f1ffa3b37519f75f330f5a4716bffa9eb6b571c55d06cf94151d8e73424c26796659caffbe0c97182e6742bf874c4a21fcab206063f42547ad86d6c48c2d986c741680555185fa94a3d068095ef5a221f116905a006b58d37686e066a8105c03e6b349594aff96e00cd2947b9fe9d26aa0993e4c902d0ce40a7361d5f88ef3e8c572ad89877326db663cdecb52e5b2dbf5b8bc7af895cf1309a8b66360068cc8c7220bb12271090106c1896a084ea5784703a2bfba4be658b8d4ec637354c8cb40a0a3b352cea3da2087884eed210783ed16a391161c5f11d3bbbd12ebf3b0ae0034b05376391dd4082a1711792f9099fac7131e1d449d21645a5caa5483fd45b06c827cee0009096f7767cab145a6777f2b59d426ff76e038df045eb7a0407372e8e5108aa5e7215fe4d6979ff67bdd8877e010a85b366b69e8d61254708f6d39bbd189f5f1c4c85836ac57384131c43f4e54e2e198490d85567ebd022cb1622a70312e059f7285aa2bd33132e3ac1b9e431286813893f6819721c9e4810966f0f00b57180ad39e673c0422f1d44f5a35cce9da9a439e43155a0916c5225047eb971897d4df1d5e97f1f668fdc6f8aafcef6db6f608c6998413202f24724852b9772816a17e90c44762083861f120a71e9095490c03da1d9199b428d79c7a5e939c4822248eea4896bb229dcca0700d030173b1aff33f6b779d903ef820d1aa07eba872dd1d5726e00a420bafdf7bfe21c8c7d7a326054b1bff78af3508c69ca0240cdffdf0be4e3301324ca7fd91f7549b06d4262e299e039c23712581b1be92596ff91addd88cecd6c932e5798ef6c54b320aef2e381e695360631857c121bbd0c6fb616857e1417a5e09822c8029d23f3f78273d53c325f13a7abad283287f5e8fef739c39351c564515de9e5f12c1d94a12ceb1b1117808f09c4c7c75a50e3b26c329a3ffbc343cda84f5ce0cc90f65197046f12c947dacdb4ff1eaf3d5980ea0a68d6376062b13394f870e1489c58b3039016dbfc75739a285cecf71d682c1f82b220649d88b743d4a9ce6ed46ea41fe441a6b23199f4ddbbea2fb76fe45164880a05f42e380fc49de82191255b58a8cdfa5892959db13c9db5a020ab8bd2fba5dcec90ce7bc7fae3a1b6837abc6134e73b16178ff41dc9149d4de385f5835bca2f1052476706796893ae3ce0e3a5624974e51e60db91c0a4ed97f596beb188b15732310bb709e0842eaa3c468ad93cf328fc5e8f162cd124e7e736a88867384461b11adcf72a3ec76e09a385c0100fa80f02395d6dc6dbe9c2b7cdc0a5cec0efcfc0afd0c02f47239a465f5b2f8d172e2d1cc5afc358b8fde10a14ffc4cc994b33eb6d9782a8b770693586150b60c715b32be1a8cea4d6ba05c418fd50af16cbd50b38beabd6c66bb85f061a9739237bb6affea971b7f99f46ab714a233597343a331e0dd85cd1e8cd101aa06aa0d975f13c930bcdeb339ae27c221792ef2e33fdb924f9eef21ff73e98693efe5e6f1aef6f1f2cf0fdef7bdb781efbc73fe43428f32cd1ed2457108ce02a7eaa01da9c2de3c573138637b74dc622588a95e2355b649df0e06dc2d6463cd8206c43957d2063b09c910884818f3b30b9d48369dbc018153f1f8b849a1a2360d8398fa0c5f2293a2a9c49a4ff5e0356811828af26f1a1c2288575aa71aa973a9e688255a6928cb6c3fe2b86c1af6e1b5d8a00a39b02c0cd1700b0c6a28c9aacd7fb7a1bfe7fbb58067de9051835ed9bf310e90662cd118893f2526baddcaf942a9e967884b8b71d53460afcb871bd7baecf14ed30f3191d1724cdc840edf0851c09853c1383b57eb6c00981aa6f62f5c99ba00fec83dc0fbaa97c2c932a870b385f819e09b00ad3c1d25d78c006abf70b16861c0decaf73f01c04bb06fdcdfb33a280de04a506a038ee1853a66c89b3e990c088ff53ec58461455edbc96380e29ce74f1ec1b2e9869e36c5d56141af1bfa407e1aa3f14270a90ee6c9ca27eff252c292171faaf302930c031ffdbeed2b49633be8a41701ee1314770c089b5fa2374d8c9692e083b27eff208018edfc3854051c3d6998b12462376203fe8edd121b767f561681ad7f4c4090de88c24c25994dc0edd9e53edc48de104efce122dcecc00907a32cccddfc2edcfeba92157e42a44fa304eaeea01261747fcacb40d0e42b328ece91e1a760048adfff5160db0449a3ebaa1554c39a63ef03d1355b25b786c91f5c2446ff556a033a3793ff64c03cf0fc870cc1ab3d00ac8acb836693206e110b71e2566fe53e8aad1646a1b411aafd7ec9db776c13e54e0225c2f2018f504e658bdf609cb4c83473269825efe402b62f2690c7effbdc8ddccc7c48dc825892c7e5b3a51bdce92a3780986455fdecd0df37a3fef9c301875de23c9db84b908bf51503477c20f394332fdd01048160c57bf7029cd22c40e6c1f01cef3fbff41f9c2cf9b973a5d085c5213990c4be4b3c2755ed9a076f11061929cdcdcac8f50908302d20ffd45c85961aabbe4673f82bd87e517de8f3035a017218f8d2179f6084ef12fa52121e7859364d4a98df8c1361fe8383558f61034861177b7977993115b7c04f883554d411972fcbde89eae165158203c7ea201cbe8ae2453f250ad30eded01e01902111f58ace513a875f4e1cd0eb6f91d2c30cb0deb1e374e9687eb0b0f83a3490949039744f3f60390c76ac26acb190b1b295cf220f7099eae56200ea95b72eae3085ae27e8c8d7f0b05bca2da86550d7fc8807afea00aaad9d7d1f6964a146dabb0fe7d1eacc90d7d6bcb7001e7628346d39677343b485e29c84f10098fc7937df8a27a4c013d00d7e0b033de1458f197fe3cdafc214a066d84d0e2c6c7cd2fd4cbd81c7e818159b17ff4d484c4171ce7aacb5a33a08cac5f4d674b6bf1b8a081825c4af590e24aa2df4917a3cb5634288fa904fd6a2c0b40b1556a75749457fdebbf90a0b25899a2538af0d76486f09b812b89972d077c4d263230418f40d9628962bad6c83c237f65fe330fb3f6352bea3e9189d638891c2391add22a78a5378bb9a0ed084bbe3ad91a402969a5e29ec5aa173054c37ab01d945a9d30c5a6506bf47623977f003d22e2b7a3c64ec0c6e3353366107659c962c0be82ca998500374c5eb4f48fa226585810a7373738cc6ba8528142af23c702d77029018ca2010ebbcf4be8db0886705c40d06ee340b02cc8d4cf9eaef81890202dc0d263952c3d467242ffc758931870ec74285bae146ca585dc74b08c2b907c20811f6c94dc6bf8b8d831f34d7a07ac2a82c90ac5ac44502d43a2b26bc4b79272b63fbc6a89a04b24abb6227a1bfbd8253e734f234920107449b7df7bc7b28c548dd886ce503998c892e0ee61adff93bbc8fb830774d93dd5eebd19e44c0f729991b4c0a3ee171e912a036895fdd572d6f68957d1c17b7f17ad56e52774fe257fd7f19379643294340454685abc14d7e77e00a3529cf248132be184fbf5ab1dcd7e12519e0ed5d460bc370af095b62e802a4854ebb3ddd3884b87f9eb96f2a1f31cfa15d682ccdf54f5f79aaef81402f28344ec8b1f5cfa6de6456be8c4afa28afa64949e0e329af46173a52eb3cf6f54c48c867a99e4041ee10866b6f543b6e90c5c914d694c3547a72ab13552c6d76878954dedaf147d2efb0022e7e9b32de3d57d1725594a2562d69a18c74c52f0fbb701ce03b400f111061faf0584929db9fb1e2f4f56822d050d6d591f94e799b79128a4637c925d8b0821950a23124ea4bf876304a9b602d09fb50735928bbe769ec1b33418d3cea80dbacd3a7b9438ba3b5895de09cd3fb97a8cc8ba3f7b3647e38d7f8f45bca24017ea9a46a4b5b3dcc423c42f961cb607034544a935a98f801f2a712b400ea3cb8f0d0e0fccd4e874e4688931225962dfd637d7c8cb6cbacc2476ae4ba73d3a13e00bb283795778d7b35da275f1cf4d6a73a21ac452d9ba48e2da8cbfc7379f4283bb02e5224bd4cd71284c43a9eddaf894a96aac4ad0a29dac503c1f70994e2594fa2e1853873938486332370c88291607e0c3422d1b95d117ce933ae32c7133c42e753f77e4e77ea5396a172dbaa4ec840bb2a042e62ea4e99925f9462c23515acddb481b5a8b9194cdfba16d8db2455992e7b694e60ce1a52b277c6402b3a15746ade52ef0c3a31a1ab6b0ed1a9600deb8973dd3901f59c1a259e20031f0f49cc00c8230f127a4e3857cdb9b5583b4d5aa56e0ce96b1ad81f479ece93ebcd0b2015d57ef7007b49daa55119433e03ba1b77cb9580c2bf3c0d32adef9430d4062ba5c18ba60f6440633c11059682369d1a18c0d7a8760f2979975ee44f00fd92642d5e6f8e94ce0f6ef7abc97decf2a4e207046bf815770a725fd204caf1ec6741f71a2782eb8029aff7ffabf1020fac1726b778622c9ebb7cbdb3fbf2a9ca3cbf2d06d8fd5e314cc9d9e4500276dcb1009645830d4cc494235bdbed99ab5e959ead620924f3ebf02ba95e0a6cf9f77885e7fcb42b926ef91f9769c9245f98317f0770033408ad75d8c3ebb14a83a33546774fd0c511cfc352837287931d68f6b510d8cbc5c37ddcce7445c66e2b3fe09f3c85de509eb811728051ea5cbfe7a46e64808db20d24f0ee070e511fb660c41d4df95914f5c5086b1a4beead8cf682caee7245f30725b08f133a29b7ce89e9427812499e9e676b00cad5359a6266522d29807df87817237a722f309b4f478841ce682245ea6b36243512e47380fc437c59b6bac530b7b215e4190f63a434629637b0ca57ce0fd14899d10a7aa196c13d2aa7a9dcabbde602454669cf1086723d7841a3195cc4e35c261c0f619cd032fbe5c0f61c3eb37c677fadf7e46db61d3f4d87b20441d5d6db8db82ac432f7430a212c4bf1a8e3563173d867f389cba63a41530033f6b8046fe8b15236c63bada713b83d3b6a7e75e0fdd7a6afb217caf66ff39acb4f30087690bcfb676af68506bc7c0060f32ef43e849980bc8721b4238cc80e947374b4f49c6d703798d3f38cc46b0a53a45cc7da06706155c53c64b5fd0e08e3e85ca3838ef984adbeaeefb83907dfcd004e214650d44bf02726dcc69c5439e3ae2063e86ca8f4d1c88539035e8c58e2f73f20d4eae11b0d914b4f9eb53a5d59f872d08a240ce5ce39a51d2b677de4e1dff1f34563426d6378f550b5d3f4363978fbaf042b17107c531e4149d21777722405d4fe3763328b6c1c6d661099913312bd4817da3ffa58b0db09553df6021cdc385c1149104d8db5735664930e227960f47c42ab91e624c90ab94361a7aa6ab876a902cb3c7fbca79f835f0b9b0d0839ab33a76c386d5f2b3d596d01e145bdbe5c2814c0ef7bdf3f2fbb95787ccf8de2cdb3fad189ee16b7b94a4f42218ea3c4cc50f843df01a37e664de5573044199afcf6e51113c70f5224604e9118e5e553845fa08222ee793fd90610b978cb66621bcc266339252d426abc753ee185dba7494d2140d2c9ba3dea184d991ff3f4b99e02cc0201d71022a0c0bf613d260980400e7963e92c7955de9fe09fcc3c47a7fa9d5e5e9386ae776ce90a19ff5d13074ed40361f36af3f1eee88fcdee02d393fd73a17c6b7340ba6219e341d7522080e767bd09c26ac3ca67d37b6d05b40264dc047932d710072691e778d55538e0d0f0438348da347649edcb6093c8ac6581867680d958d564a11ffd05343edc85fe72ad62e92f5e9c38de1f939705ad8dbfc43b22eb259d0e423d5325a761635e8e058a7673c9129da4d40b971609fbcc09028f322b6461ec925a8a19f385f221b5d37479b394eaa4d6814745f156e6737fd32373338a263d9ccea1b2dc9916601a0a36ab2c1bc4dca45fb3420b53418066326ae879a822815fddeb5bc8b6961a58f4ae7b98fe30476497903390d4dd8743efa440227653b61a5187d23c8cfb849e1f9d1fc9bf710f86c04f89b6f293e339a2ff326851323f9356f53787eb457b5db7b6502fea06650eb269b0feab7809745278d30ac8188ce3067d87296b0da48788f1812457ebc6d0fb64ae54be18d7bcd0c9b30fbc6bd016747f86dde9bf8e408eb366d97f0e9687e0d36133b1fcddf6c37e1f911fe1ab7263a3fea3acd9b257e3a42a63260ec1a02367ef5b394b6b98559308c93877ebf7b196c48f6422d1f70eddf426ee7f73217c1788a53fe890231f4e247698589711c8b09aaf1dbf411bd2bd84063c6c41367a4d0a8e1404e4cf1a27115344d6f8bea47668d50cf7634cdad52bbeadc950a59bb79a67f0974281f393a880f8a5ab2bf29cb0195864512bf619b05946c86059a405de35a8eab4cf13f5bfc689e5bdcdfbec5ed447a8d859b178fbbad5e57c17cb13b343a68e28d787fc3b181bcee88e3de501c46be487f32db0d4ddf01af8206d23ae9b6d590251ad8426ee4ca0689c5a174ece3e01af22a483d4251bd4a1596e932643ac510553aefab9e6d261a58f50e8f8388576589b9dad35e887c5e55ef8bdad5675778adbbc35d3c43481d3eeaf4a3f0bbabee9b4622a6708bf23d3f9d12e4be2d39327e7e6c44cd9a174ed154db57357a5b07a1e1252628dc5c8a9ced72827b645f8e9f5d1da4c5254c0794003fd81d0057052aac5a5a8d0a70be94d15c379fc30ba02abc9592e60b371f96395cab82de984194ea79e646f5d955eb1854de2f52690e219ca1dea377298058de9969b6e0d276c9c095c3599571cd0a5fa7e666b3b62e10c7832d04d93df8d03663ef241376c1a1543298298773cc63e5056de40ac1710c22b9a41674266817e19a344872857af6eac0398e197bd4db3e315c5619c4076ae5237c9f190c4349fe1e97c57a45bf34b9139c6a366236d2f8e7b1108b4c2ddc82b83a5197bd48828eb7d36edc96a9e22d2b8c1262c6e635224254412a82694a47c8e310942a8c913dc6ed421eac6e34336c3a18c111d51437123345ac7a9f2a6b70d2e896226a2b2268703335579eed396935d7c8ad5cc969ab4a540aa0182216d41a0b9171640e4173db8c87b191d8758ac1a91eb2663b9a643ec6bc9411f33d083415f03b3ed9967e55b94edde2319f580e831b5825449c42dbc3991882b20f79b81ffe545116338b064cd1ffeadc022a26354f75d0687ae530cb86ee49dfc3fb54898d55bb20e007d44be5f9cae43ab7db2f65ba3b8fc7334c3314c4801a7a02ca75592c602207d4387c8f7e8c6e98bc8ab0a17fde046c0022fe21baf48744e074b2a749e8dc27538270cc79a9a098050a56284399e597e735dc11e02bda1c2800242edfe5bcae1552636885ca095af48c1c617d9c4772398c0afd2f315d690cb6d21288a48c0407ca485ec284ccf69dad973098fc72f314b3738637cf0770972c0bd53fa88c178c229c0a805c32f8c95cf0f11405c11ab6d1f4f83e711878dceb5c9af4f9f5a41c88e74d162ce3e98d0bfac5884d1941d72cc1f0e8dfe247a93679f0939e6a11a1f6b2cdbe7660032407137397209a0ad2147171dab3fa012a7107f9de6b07c031cc663c0caabfa337ced3498580b4603afdf71bf3f70c048236f981d85ee9d383a449e6887f76c52f92ab7c30ffe9aa8727129b9b1e2ea46b8b410b6d0dc8b2e9870c98f1c860ed5cb753ad71f9a81d546effc9c3a549670f0e95b63280273db04c6c1a00f39251126479c90385462374c70e32aeb3a0d6e021d444208379c21c0c1ca5af16cad828c0b1afe6e3fac92991b7da667689df78687ee1fe869cb2566bb4d36f5498f5f98921ea76b1c6e232e87a6ba5c761e8b658e47095fa3e82e1ae4a764b4eb99b3bf2b6b326c3e9c946dd8e75d129f231baf965a8c6988784c54f647a1744b409c174dfdd13203df429173636143ec96d60e4d582611734da1de7472368709516357c9bb3c8c0d77f405458ed6ce5c5ff2f91e1810a55f6534853f1973d00bba6bc70d5759959dcdd40686a84e38bb2d7a85b3f316b8e96e1a92ca76d5815abbe2bb7c92ce65356830ac69383358e3fc9f4278a326416bdf0c7d623085e8361d29f3df274bb1e694e05b0b58547f78cc573010fcd0fe14732280cf525138c3bafc1327b081c5abae6c61059c2761aaba30ccbe355cc8cce21937998056ed2221ee3dea395ee1d297c692338cc1b8185af9b8647205b46665524ee2ce0e04ca32997e1e7b45c1663a0cf4bb716cb39d6d162466f045b6450272de81136a29e653d5d92e597d0884ebb18a48402a4427fa7c82d09767ef42e1ab893db00015340af28ca17c40ad047ef549a6087053811cb5f709426545277efaee8e3c1e5c750f00b12ea9e0b8e953633511523965e98ec4390839fe0f4d856f95028223948e68e1d0a0988f3391e451b6e72dffc698692c6b86b219333d615d985e58cb3c99b1d438fad26b81f0967942bf466efd37a30150fb908bb0aa8ab6b9fc63dfc0bc66e4b9b3fd88bb5c9224efb6aabfcf63ba9a10356559e5c0c82c595404e475a767ae7df76a5b39ae0f6d8a721b3f0bde1ddbdf11867034ba415cbd7c140d61e54c04b11c1ed8abb4930b092c228900ecc43dad0c984e385a708fd316af6b193c797ab9200b88fd3ed906857282ee16768707f49ad68b698b37afa56e8533c399771a97f8a3d9f28b580317586d5ed1a991d29dd56506b69f0e8554950236a2989e97596149d5d833468b364bad02b47fcdce20d73d82cc93bf1441e0e7ef008980f2cf051421e082773584735650714ce910e8dcedfdea858438d2c4003b323362bd360a8371a889dde3996c2ff233d1c1838dc7f6fa8fda393f1cf15498bcd74409371df30bb2e706bd860d755391c44a98ceff2ee21e690553006d810b2bfec68e80c52e09b6dfc46bb9f80cbf09bad22434d7c6fbdedbabcfce95d91036374218301b2c07f9cf3150a97f364c1a2ba3ef7daabb0338181ee681d2c0f3055c15ee45d8a25fc2051daf65fb00037eeb2b9be4ab68803c7716e9a47c3601d02bb67661e0c3961454f8d37e9650c6b2b4c68c0e3a8b9a2ffd8e6b40a04c3d0a3661121f0e6c438867ea834089b6ef49d70d45aa984203c35c84f48020077ba56ca048a829150d3bf160915cad7fe67c79356481393313bc82b88bcc11552bc3446689927f6a6801710112a6bd91cee9af927bc89863b7ec7b619457d65db2e3a31b0a63b3b4be715cce72a8b4b18bc34869f5dac1ecb2e04942bbf48db9d3387c71adbfb08b243dde20b524618850d0a9d17a32eb3af16b76215ffb72d92b10fc2630346a6eba116071f6e9ce600347f1d045f7e7a8b0c1073f6a346868823bf0e491d3c07dfdbe68c380fd9026119850e3f876d04495ba325c586e3d359fbf5aa34ee71b2ba2fde80cd3498270c7a1dac554638931f332778d240ddda4ad16c9b1f96671f22fbc8235e1313d056eaec5368ea1ec0783e867a17705cdaf35b79515a92a693a28976f0191f17d709e0ecfc761e439ceafc57658ddaf7ce58539d479f48a6d23a5e77a671d9cb0d2dc2b05599d152b2f72d1c7ac35e678b07afc2127aa35c512cb840e7ae127eadaeac5ad4a9554816390ac37d40ed790d61765c12a80ae1ee3f62291174d251a10232f566beb6fc7dcb481f8862c5b080384a31948fbeda400ff8583dfa54b887d1706d871ee552b29029c30e09efb42bfd2871104e545be2362693e64a4e8f8a07f5166d566b688ef12db3a81559ad12122d6b1ccdf7338ae056a9a90956edcd017d73048a8a1b64b069c7e1bf3f3695119e0e8d0623a7007bc539909d70b2edb4fc93e4ad5776bce1e74bfc5dbdd90dd599ff7d76bdb5a7b728e049da33f4191e88f6a3604cf9c2b0c83a6e5e4a026d97983e8b285d0d44c999a5d22a81d2de5b0fbda4c19d934e0c9925efba567bf4a2d461f08e9efb89140a9d9e38e0578b817b82f6c772d1cb0faec87d7248d2f7fad843e4ca194115ba8aea328a46ccab7270385793f3a63475e82aa1ebea6c966b127173e4d0e0566f8059cd78ada63247d9e1f5c2a8d806405c24f21b505504a5e89f4f8b2529c16eb31acc68a944e92e4366353d14643bf300b191537445183000d2050c7db6d9ba9be181c4311813d03c236af9f890e7bd41f2a7280e1ae5e1b2f025798bd66e86d26ab91a375a5cbf17ed8adc575db3fbb15bf728ca10f451652d6628dde5681c7dc54530efa3264d0b028ec0a34ec5c0bf54fec73c3fae13d8a0b93964b4a5bb6bdbef548d2a2f4f1e41ae9bd1282baf829e60889b83aca3213b2f0a61b6fe86be87f53f788219be715e7905c014ebc1ee4067519101b01848770991bda4527ea5d2c989af00b55b292578565aa6ba2be08a4fc827adbec51e5b78597ab6605fd64efecbce6299aa19d7177b5e07122e666cb5d2fc07a04189a1ec8093dcd5436be325904d534b3e1b5ef31b636b347864aeb6edeb124712d90af504e2e3dc3ce2fa1d085e0ad4b3c82cad8ab2164b2ce8d3bb2a853ae880eeae13bd62e54f43b6de67e7feef030ff6fe21c9c4568927ef53127e8e632002a42a99b3fecde1ac2272e9bfe0daba8d6fb98dd3ee4481cb386aa5ade7b84a93138ad2cb666b55a7a6c93daeea4b086aef010edf41153ef5fd6f167d4f7b437a0c075811f82ec02df3b77cb3b3e7ddb9d055cd4b898153090893bf578a4c89a71d9d31e61ebb3a2c54489793d4330da9e4f87645be036026990485961a4b23c388e491b9747094527812719ec47eb5c1a04a5445d94e2be444ac5b1d932de78287924f990a6d17257550032dd21062c63d3dade0ab97f4e12fb34958178c827aac2e9ba41826760ca2624f38b19f5c035de48559f3c73b1aa13ef27c3c050046c5f6a76917649d3e47372b93d3ca9bb03daac4696da74b0bfa62070e888b6aaf3917cc47a7fb01e522136f79d7bab484f5e1023408460c2c924acf78f64e6ae06150648042cc146d3864189ce7523882c0083111ef5f317aa56e0fbacfbbd6d212dce3a13e45945e482f57528d5d8a1934bce78019e33845f0c0b98f98ea06b8ad7ec4915376cca0cd08a8281c365e41a8fe293cd32cdcc126d13eac2734a567df0faa8479b74030779fb77719ce3b6730c488213ab4adb059a807c8c076ba56be0b29f6d55186135e8773e3d6161d0542ee1ef3734f9a7160a4c3292e58f80bc6a507154e1daa4b62487b18029177acb388e2a5c74970e721c8650e2b6760211ec0c8be602b6ccb01cab26fe00ce6413c44b87186cf3158c50c0ff2472a3421919d67c3329dd92e1ffbed465209df0200c0311126e18790070ed44e35f8d7f79f069e1fbf585f5cd7ffbb4a0ac75261074eaf2d4ca0e03132b511da69ecd049af5c9ebb1b22783afe1d2b4761d753f4f2d701574bf4ede3e3db0e6ffe493c135b4186637e27497ecf119fd4701047162f3e33142d64bc27e40d004b4296baa84c57650f18c833c49ec3d8b56b21064fc1251b369c27143dc174ff1cc94b4e109bd01aba1610a2280f321c931e7b6cc281fc34145df213015d5defc20a51d292a712410d5b6fd75d44f862a17fe3d0eed57b7d3967dd58fb248d800342efc150e38995f7c07416fe43ef41ba485a860b91d2753e1b6cbd671a76cbd6eb42804eec9f1212ac780803ce7cd1ec03d1374772e77e559c2d1efd4640b61fff68eb1a360af8bc8d028a070bfa080feb5b9205f0f4b85260a832a560ae181ff26cd50b584c1923720b5c425d8d21a1e0e04e43916a917f25048d2b140d6da0e74e74bcd3530c7acf707d75f4ee7cdbbb45ac8b40646779d16c8aa4b32fad7d1f748c5f623ec9641f7d835554845c011340cbdc16d6a99a683e2b4f93e828fbe0b92d7bc661b5b5512bce099afe29410582a8ea692c5aa45bb2ea6ff51cad86f4d8382be85c8442c028ca5b2285d47dc9f06f91aee102a4866b49899a234607c49f4386627d708ecfda3cde32762ab3caecc72d81791634d26c53e8fb2e025813ed3af28135207ba5b67da9f15f4a04f02133ccb3dd2143c5f10cdf44f61248551f2416b79ec5a0a79d03dbd268d6ac9dceab75e8f3c9aa550f726756eeff692dc16df757130493dbc5787b0f448315cff5fb3dac75b211e7967d6f94d596ba9f4d2842be55899019949cce4091c9153e4f451fd7be2bc41a35b3b5da9bd01da9ab17dbd081fea7329c5fb06127a507dcf790d06eb1ba9bd80f32e995238287cb353c957fe34e5e293880373d8565655d18e8ef47fa197211915cd43ca402ab115a4332723f3c00e55ec8196662c438b3618b3116ea674fce011cafd3187f64536c152675132ba954c0427a5cb20e6d382f088b13c8c39aa1da0d43aad8f100ae1b1efb9d11b5c72cc1357501c035c65a8c6ad62fa9cdb03e4816c2d80a0e39b07ef558d133215ec8d701787d54a8e9818eb8896541600859b6bebb7ee0925e6038f124546e848e1b3c1c706bad63c1299161f59958f2193ccc8334f239598db629a3476a3f34cf20e373380e6d871e12f29d76c746a0a56269da715b835b6c903a44812703a739633541e2b809c327283ef1944e2e91be6cff93138277a3a8eb5a4a272296b08e2c538eb7f6223fc85f261162ef20673dcf0e66f439b37cc77300b7c77a0f85acd3a96621137c0bd8888a823aab48327a0dd2612742732e4c7644987a048405a779c3e45c9c1fc93f4c4a84d4c926164b07e7d087ad9e6417e13961998c9d2ef612a54f620b28e96b4bc79088f4b4244426d330f0ce4c66e0f3758f517913de4820e671f7648d7730909d774276ff2250ba3db6b74150ed51b393ae91d1799adb04c9c98098d3f003e46b71d1e7c1dd21045c8351f564db58802cf40969b6c2528b7b38c4ecadf8aaa43e2cb05193f1a47c76855a8f544c42389c54df6cd9be3575a0654c27c727846adf29969a7e18da2d4503af279fda66eac08ff4a8293b42f740cda53fd063bc061706ca2e23a9432ec500fffa326d24aebdf1624d0b58ccbe6155dad4de6bdd505cfcb8a8abe3337216572b615bda9131da239540c80f047e88b20c7c3289c804a0d70b9846048b0a583af7e6349e846b95316b5c8b6e93811b803fcc5c0935593a162d39006924516cf4251a5ceb7815d19b90db71ec7ad00e1e1af711f3b458829d5e340dfaf218d9c9934cf764f7517ef53c556b2e83ed005724ce29ec43b05a055ef1e3767ce1c4c6316d84e0047d3b0abd489817e606c124b777fe7036ce1f0877e1c24e5bcae70def3a028a140615988749dfd71b0522eaae66e1a17660e362d196aba3cd2e38e589483528e0e35ee83295637752a79a2888e614c21fb4d33224d169880cf34e4d8f8c5d9da900d823d81505acfb5e7274310487b1b04f2b668c7782d5bce4ac8cb6073a21850ad74efc9f4403cd903f738bce5cf53a4c538410f332cd20141bad2c7a63a436ed00ffeadb56baebe926d9c7755e4fd0e6118ad09dbc7ef86d89ee6a525009534e09234ea184e30ed97664b828b4a11248be0b7b4e17fc1a1d116a280a0f98780b2205b9d057d8e61a7a40e484607058e8beb2be6bd59eb3843df39e22982450d0aab1d9a6b3ae619a55a1ad181ef625ef7fc6d17f1dc5c032a028a4e81be9416fb3d0e97891a75b36d7fcf16700a6bd0b516b3f47aa59d1e98c916fd66e3ba234dc8870da67cdf09f5a69cb97061dfbbdee276a6bd3686721f63c1ef3840dbee8fb742a5f1297b9e84d95b1a40a3bb87d45c6e467f226a373a1750a6e1de029f7263b67750b46e6e480dc4d75502ca053b142c8987ee4fb4dce60276606cad44973626904686a320e60c1dbb0a90a9c65ff7b565b73e37d0a9572f7399b236633e56422be904998be621058a17b54372c9f456b525b142a3ec1e64e6376f5ba2f0dec28c6eaee2d37a62741cc279402a3def544acf836feb9bf3c9656a22fd31a943b336e4a94978688224595343a64e4835ce596a6d4702609cedc5eef877aa2d85ca49790c4cc017713c2c8cda9a46d52283964ea55083066a0401dec7844bc710faa1d6494f68ff5560fff51918013bda585a2c37850f29455e4aae86d677f56fab13248eecb81f3f34d1ef08b1a18fc0ae623387f4b78afb9080a418806f0aa180cce1967a0869471d9bc08289469220586b558c533c765d15566a463e051e0c13bc72978aa8027414d40eebf458afa280e7263282f39784b79dbbfacc889d0e663117364f131138e123d024b1873dc33a65b48ea8c94a3119313f61eec03d43bdda613cab46a96e850b8bc0777c7cccd7b94f2c04779286321a8885668f61d12c50127a6a4302fec3bf2ec2972967d0f424fed0504720a56d791e6e44a0a1fb3533ce6997b627b90b0a4e848390d871e5fba07cbae02d38e19a922705a6aa99ab36d9788601126a3e0e104507aaae74ba747fbb7101c1a88e9ef00de3438f65459da316355188648257e588d79701187b030cd608b2a980d484d7ea89af9405ae2f37c7a9e9e63f2700f51c2406ee955a61ac66725795ccd302435f9e16a868312131eacaa62ff5b32c7dd69390a708c1333da325d1a8620551d38d0b9fe0debd22a0ce2bcc4d22f491cbf6a6b3bfbdad2062db60049b39dd9c62f91dd757c77d00651a90e38ed1ab2aefad080ec87b431be9b5b6d09a40680fba4133423498eb2fc530a24a1e828e7f8c3856d0c1cb07e2737fdd2ab5550a293ab374ca41d64826bc0c8b4b477276658636dadafd9a73b4cd095b3b5214706ad97e1c4d8350cdbf7acfc8dfc2d4c70906828de26d85bbd32e4a99040bfc4aea816f6222c6cd0dea0007b5a91820061d3d44bf051a3bc03c56e3ebb50846e29adcb3114b2fdb5f6a3a4000316508719091dea7b366de2e1a2cf543906da74e51c7c8c14c9a81ae1e556a24a656e2b6a3d0d4374ff511d4ec436b5a9b1251b8e53e9ac39646c3aac5fc27f6e3dbc99bcd413d556c5ba54e406565d7512679e3aebe4870431c8e6ca09653580c587afd96956e7acbcfac96778e7f183a507426ab5fc5f35f42a638a012b15ef76940410662a4fbdfa6ed81247a15849ca2d1741362db8ad900617cf63581fa173160a0c78f1ff10a856dd4affeb9b99eb66e3bd378dfe0825ab38093886d274965dcb4d94399ee899ec23e206f8723f68c38d264a069a5cc4ab6d3a8d47daa636289f03cda5477a98651bf6bf689df5c11b958350ff3761257c447b789e5c9e5dc29503890d6e7ec895ed1e6101b7c1d2043012e4c209ef01547dd4751ac3293fa75d2be32b7670c90c42e822184a4b91f2cb74564b8a86ffdb91455fe27eecf9c6ee20b435354824336072324b15e9ba6220133cd98f7bb81e09175bc3adb702908f7c3f43727e8f5e96e8eb891d292787efb0b92150d91b65453badd30d4916da3c5478d7487de8a549fee67fbd8f4f7c68fa38e2b378b7af023b4c93bc704da9901ff5eb6b9f087f7e9bba9d6e9defd5b7d72097eeb19fe6555cdbc21b4348de6b46d535ef429450555fa596f8ac4e162da4067a5e46fb071519ad062eae111cacf8840c3241fa2d218dd0e0b6432399aa35bebc815a427523b19f8be802463b9e3c1b5c0b12ce88ca8198774b3915d917c1c35f1e1cebb69d574bc928733e5efa15d77904d028923d2ce30eb3e98ed9d847e550b5189c2e26f47da8775e55bd478d5e1d919389a2a3c4458e1682971cfaf88167cb45b98d8ae0bb1d8fdabebbabade5b08705f1c20932c997497239270fd927068852c9a5541f9cea7ece8d5beb66f907f24c815a70ce90fa17e61dde439b148a4b0beb7299bc5ad31e5d2c89c526261b6285a765c97979484a421229eb423ac6d9c8406f121e0806332241aaa1490591b9d86210095d1d3058ec098985b4ded20d909f025f59187dc22a96b15d230cb950b9486e013ba82f086b8f2841c21d1540af33b05817b8f7342f089622430f20abd5052726e482f73207e9c935c4018318890a50bb86992b03a87b11bcbdafe0f74603d3f71ef46146b7df1b79bfa1f769e39d79158fc779e014d5fce8a71fc495751180d6fc3c1a315376c603301b08cd7a25305368c0c08baccf039fc322b1140b7970e944439ba4a3bd2cab682cb6e18c85c14413020860f2c8f663e87b6909703605ff65014d9e5d4c031815819285a43026bd22a219dc5fa9947e10abac4495b6bef289c32c5a03c71d657f337e079a7c381b171cdbf7f5ded08aadd9b5f11df14b7dc9fb9a532b3e7152e058df74fde3a7265ab8a04e6a5ff702af2871098220f5e4236dce5e30960cc58642a4cee43f6ed32dedaec4b698d0c8a50f6e976c017b43c041d35f37f37e736f7b8bbabcb57415127ba8c94b34b513a55c5015377ac5155d7347010c17f648414c8751d0647c5ed76862af0bd27316db494be875ff84ca881a16d0279fe82736d158342a1b0b9562d2cbde0a795d43055088d293cce97376d1a068249bb13908c391260490c1e717128e338dbfdfe89d8dde8aad40e6410d401fa6734f12c4107dae874457dc502b6ea88a1bbae28a1a10df21074533074735ee7d3d14ed7dac7d72cf9088bcc0dd16325f981d9def8bea198576324c8ee50e2bbd9403864804603846c35d8e8e00431a50624063250399be19df34a4610c992e40d8e8cdcd9e6d88a5e90006704ddea5170c30bd9889c9842e9953c4cddcd26c89444701df9b36f076536f68feb2706418b982f591d45fd200a070d38cbd7c0c9a718f611980636826730c1e06e405aead04ff6db104552e59727880bf0e59da419e0d9a9b36d9c3011b4f18e46027255c9340d857b00b18310f0f8e9ead89325f55d0b13664d28c7d26919d11fb63d8f1056e5754aea4dc9e112c9bea1f3981a4c1c2b3e5241c4d3bfb2e711228868f269f99f4e7addfb645b308a73e9e527702c423acb6aa7b2742e821bacf9262dedb7bf29e3b2f2210c52d16939c196d4261f295cabba915330dbc2ad6f1f0b2810e11e7848fc26c61e76492ca99a7cf89304543f87ea347866e6290d4f8609c7beb8abc1df2622934e3222df96b5f5ce3c4440f01b259ad798b86406d171337ac85d8da428c6f11735c89856eb2c50e363d791359782f6e60125f547a0e50ab529473c974019ccbfcc0b858ce85ca9a2582502361f9e4a08f340c5012b6e9012a037906ba2fdbd69b3f91514bf2b2338da2b4945ccc0f291557eb4f7010986a075a939aaf599800de2159c58a14e70889d7dc36e083db0bef1e132f24fbd84503e24d618507026b55e443e0438dc77ff8f23f70446f0099b5e6ef45674acd309a3b513d0ee2db26bd8ba1915e26d7f504e7884eaf2f1d04e383a473693b2823ad03e66d3e3b5e8bc7378710dfd933a7aa60caed7264aedf60b6e506658feb8977a9a78423bc5ef2091496f2fb86d2343f8cf448be53f9e1475e539e331a129e32f68ad30e1b2d76c3508f5a1e9056d064a307bc1d64a22ab8806559a63272c7b3df9aead48dbbbe1c7200e67750ce550b392d1dab0f40c2246417e6ebc2ea115db3f17cab9899d96e100478e073adb98442c1bc5ff4ac59645e6d1fa508ef836fd1d31bb51c52df427a8eacb4270feb3b697dc5b165e697396ba1b1f12422bb6c9261298e004c12bf11f35b575b41abd59b049954ec55fc35c318ce519a570729a30306faabc0efb848e8735b0e581a85e82316d70e014e39727322f3188f5992f70049a4b037e78018c6eb97a201e515818d41cdf0218abc7b9399d8744c01e791b954b374adeee97f14c0a61203d2ef22ef0bf11691bee9c278361dba8073a4a6d2414052076dbbdb55b72b840f1766a775cbe4e36e9192bdc46a844b1710b008d1adb0104100bfa90dbeee87c91e3e51a2a57b1bb5127c2c341cc62cd2a2b976578c882b09d64ed311e155b8198a03a6042fa423a1814d92a57a9b813c64fa918cc7a4508ff9854e3613d55b57021213bc933b01e036c2840c98c02b7fa712d7415a5b1cbe5778f3329d4b2ce2effb04d35da7f74d98d3214b949ed4e8c0546fd925439dd5d76ae89101f1aa8843fa5f29a0b7f82aeead46d24a9a8f579e1d67f1c7d833792b5ec7f661a3476739c924b664930c566d3a7ca31ad0426e0df52859010744b2180e51b2e8190c6fa5c302b7fe3519a3b5b2cffb51d691cb3cc5b26abee13648e2a2c07a43aa82894a1be5b27e6ff0a3d18e1b945e9cc9762dd56b094a62efc45b233585f6b71f282788dc8a238b3de37474aa632ed9017aa8155eb7b7b006d8dc9715ba47cb735649a8b3787243ff8b03990831572de84d199505a0d82059635952065fbfb21b23b32be4f935252d7313502788c57080588749ab69a2d103de449fc0167facd6462c4d7ca3da2fe4574a4361d9042516e3f3be1ed3ef675ee34b0add99b35de0ce9dd28bff02431391667211626cee007a0f2b319d3fb06e000c11be064cf413f37123b90b543603ba4552735f50d415a70d9ebe079c5a6104e73715ea0d31fbf21551660ec8548f2dfb44f41f523b7b03af2bdfb224581f3674b75f23b48c01cdfc9c028843c8c477fbb8bf6c40cdb82d858a7bf11ddf8b8e2999310f44ff81ff641342441289eceeeede01ee0667070b072e2e534697faf5009ca0d4afeb14adaadc87f03d0e37a5904e0e425e618c73c618e3ced426f23823a516c298fbf53be159c494d29bc54a29a594520c537c2ddc74c7bae74a8a665a7884c0e1d317b419b3a84c8abc8adf09cfab49a37b248c7c95fdae7934cfec21858b77cc798648918c5b05a5f2e2f24352044117f54fd01101f91e5cb6e868b141c70c2a5370f92a2f95262a417266ce93a63fa88231f6cbabdcca489048515e4991443da1bbe659758be21922677a94903393c2161e0b45a63fbfd687f1619cd364b549a6878e7352200ef50c32b44be2803f7735c0090345f1050861b4ac79fefc39fbfcdbd378f182f1c780ed5e5b1c7bbceb6ac2c4d7368d1778f7bae2d8cb2c633a1a7318e72723849e3228d0113f7d22b45d8df0a8334977c8f47307655aa03be5b10ab8a5ac16c36e2874afd6186b5dabbdb86e31aeb5d7f3f03fc6a110868542d65efc22299d1836b3ff39af054aa58c4f9eb1b86709befcbbdd40fae2c27dfbd8de34f8dd4a554aec665abcd9502c66114a4e4729e54ba96d2fdcb7da568a2fdcb7bf6d31aeddb61207398ee3387a334b557018588b50e3667c19280d2a3757ce9d84905adec3a5cc709452ce394b94524a4bb5d65aabb5d65a6b3f191f7d1fcb4cf484e9e0952b48e6dc1f91a75b958c8fb62f318d01909f6419b12ccb1e7f19bfb695b6d77edb6e361e2e5f4bc138c176cf5a5cbe95bb572d623a9029225344a6884c1199223245648ac8149129225344a6884c919a4ac1988774cb4d81ec1289658c753569583e8ae200e257d78e31c68bb30f9a30d2de807514b2b5b96a4a6584d094051594636f08e2f259744091486e2fb0e88030f23d2010c67ed76d360da851430db9463929ac5ca7315fe521cbd378b1f2adac3ccbcfb963b07c68c7c082fa18569ec60b7be23228d05585e58482031effc453793f3c9d49c3824deda17e08579e6bb1fce82d425d73bb3b8b8ec9bbdd3d201e0f97bff5dce2b2874587cbcf64d41b9a34d505616e350245f7e50fe07e05e2f7b17d9fe5ab2b08737fe58310a6d7168c7b1f7f5047db1520a73104424e7c7e8d6449a5c8bc9a31c616a4985432431a8d06fb6a0492321864df2b131cbe4e4d1a6d5bd49c3474796a58964d93064e178f8f73adf57294eea9c2708cf023cc529e708b9a34d9944d16954d16954d16d5b389fe73fa4bb8fc0e08c508a499364018157471bfa70709248a28a2eb542aa6ba4e69225a2567e8cbbb4dd807972a8516643d30867e0a2cd0ab8e69930b50d733708ad2323db4fc5e338a53d70df2c4b0b885423286dc4af196e863ac936181fcc86970b8d9507843f7960f63b094732bddd01d238cb1f6ebd7805f5cb05f3f460c7ce956aa75bb897b471853b7128d17b7b4602211f69f65ffb686423066beb0c5b0bb6e3c61f02619e0ed2c140a85e69c76cead358c912a601b86c52df7508680dc5e8861f796f2b7127df9545aa094712c3f5cba899b6e5a05c736f913df4c56c165a034a6d48a9021c5ba7b590172f825c8e1ae468cc07039fd1b18e20bf0458d1ab6d7be861717b6d73ec6b6e1848991e184e975c5e19732ada2b4e3cbf4e858cafc4a8ddf39377e9f52caf1fbb5d65aeaf8b5d65aabf9bdf7de7b3d7e81805cae2dd3837dce60d40dc3bfb080e52e727c83ed9ab2008c137e1fc609afbb7462afb5158695755795e532501a586a1c48c92264a4df097fc0a4a9a99aaa295861abceff9a7a3e67cc262e65ca347364cdf3f79abf5f0e3ff4a4fcf0b394f4636093c9f48206a9e7cb0f7f0d0efc0bec7fd284a6c4f7cbde7e34c42a5ee4fc8b0cdb0fbeb8df1130c42a78c5f329ceb0141e1fdfcae3476880f839c66b69504981c81187e68de5144f9a126442007cce8fd25048ce4428b2f67274c31e32943882e0407120c039610eefb4aa388430de00e48a31ca69ba2188524aab459de6bdf762cc068f0d1d1b296ca305618c4f96e18112b6c478c3468c514a1baa1b3eec9e3f9867d60d1f1cb26ecc1069b0e2908523a571c8c23184c6142971b470004108278430cec8c21184a306eb46931b4260e18882952387432992540659c68812ae048060da811033f8c00635bcb047b89d411022431dadb5f6b26c0481671cb26ef4e08615270087ac1b7ee4fb4197d2b554beb0fdbb7b064edcbedd5d467dcdf8515f5c9a86743245e81844dedc70627980081f00872c1b82588891cf98289fadb4bccaa7847038fd99fbe8c7d780b8f62c2d960d2a3e35109f8f5d7cce9bedbbdd6574cf9562153c3ff7ba7bad8096df9ee63d1a82e65e6bfaeb587079edb7ede3b600fddd7ef1fec5fbfcda6fdf8bb7b9cf9f5f7baef3deaee0b24743d0df3d7db8b5d0f279e3b4fcb67158bc4f467d712d1b4ad1caebcdf2f0435fa73ce5a7dc6e583695a295fd2a4fa528a55b40b77be4280b40f9ecbf2e03cfbad73e6b5fdc58e8dc6b11e07972b8808eb2bb0678f6f59359f7dc86013c4c5aad7d7c6f96dd7bef66331fcb54a1e709ba38e132091affbd89319372ce99514a69dd4ab56ad9576badd55a6bad1dd5d0d8e7d4cae648d4ca555151c7c5ef77f8ea5487dfef2af03baaa1f1df2cd33ed33e7b6d0735e1f77a99a66dd96b5ba97beeb7eda6e3360c8f6f5bcbf76d10bf8fefeef6e9d74cdb6338719a5790b1943182eebaa7c44d6500fa365313890bb10d537aaee03c4d1a6f6b2ded07331a9014c9eff28030305a6bd268af0923ef49fb019cb93940917c4d7bd1e40067e4dfd3cb47c0499ee4cc54f1b8a7fc826df7c9356d4f26204df7dcf78ef7a9babce37464bbe31e404245dcdd1f8999040abc4f55a7e172aaa05d2141f77b52a94e1ba5a1c98b63c481b98a14e0596a3247d01d6fb5d6aaa363adb5dafceebdd706638cf1c8a4b1cdc8a4b1444994cb1575a24e87afae823647260dbf632cf2189fee9f70ce6fa6541680e1c1f038fd1374413f4747ef18638cf9c95c651d507e8c292912631a714a8adc5218a27b09a110c55ff1df8f81afad290c913fea400a437496278c15893ce79c73ce39e79c2ff37120fc39e7bcf7debb827d1cf9f5adfcfa726f2a322af2a442a3948aadd65aa9b0d65a4b4577efbd970a3d7366ce6ae5725181f105f005e6f43ccfdb3367e6dc3b2f11329cff0245332129c22d4018bcc20b9c61018a54e02ac0ae8b2bd8155690332f45b205482380de596efe77bc3f97d7e240170db4540e7471d2d363a6a08b499f48f4b8dd38f3fff9dcdd86febc336c80861a3570a003393678e0061b3770e438e9c021871d3aecc003d583871e7cf800636ce2be3fc018f936f1020163e44308a1350261e43711fa2522146010cd11223345442545560563e435a54c5aaa8a5511298cf0b1e2410f1e3ac82800893bace5c1035408a640a1652343f8b4aa7e42aeb52ba303149490f2638c31c64f8608471ce28c3088a616862e68a4946e284530063e8d1b88774dcb216887069038a2891c3a3491c28919602ddd35399233d7629c0311ac1c8450fc1cb272e0000e53f0008f44223b72505a76f4704352ec0862c710941d4576bc60870c76ec60071174a041871c3af4d021081d7a7480810e37d021083bd0b0c369072076d071d94105de0e31d881098f1a3c74f0f881470f171b30275420011048f40882144c1081bfa4acfa74b57c9faaeffb5cfdf7d922eddfbfbf4f26bcef9348ac0145a117970964c5f7d983c5f7a9434f1b54becfd4cac79487bac5ee98c58a90cb7ed95db4fb09bc6b970fbd3c354d1a7aa2a696cff2fdf2a1970fbdcb67bcd9b8bcfc7d71790955fef221974d4f2d1f85059893bb7c10c66cc977e42f1f72093dff3ea462f9527ee5f3b8cb68083ae5571e05c56e0aa0c15352565698186b1d0afd4f91a84315f63dd6a0281fdd91f251d4ca77514b34ca67af572b5f27512b1fe75af9b6a8b3f269f0339759a2f55f6de5cbb8cc128da5a4fcca8771952fc563ca86300665f7996373329ff6d801153a7ce96c5f8f2e14eff42457bcd3539f39bc53dae949c67cc538bfcef96241e600a971572ca40702160e4c1ec3e0044299a92a2ec63d6aa2ab0a05ce0c008ab82f241a0087bdbdf5f1379fce18eb172705f2001e1f7e5dd4934a7159ff670a37d013982f8e133f052974b72696947d4c055d602e3b4c631996310cab95889933dd653bce0a5471506bc515b2a4788dac912f0dcbb00c85b117f6c25ed80b7b71d9b9b2a8a2a3d2b9b87c95159798eac5ab5429a2258521a1f328b751ba944e775ed7755b101d39f7f2a1a73f653f0aa677b7639c38e0713ac1e36c82473da70abad03eee2dc5f5a4a1799b3486776fc1bba63aa6ddebab8471eda90963ad672814bfb7982adeef0b736de79ed10cba6797a7035d68f5b3fa58c5d9a5edda8287bc2272125c6e305619096254c54f46266484c80c4163082a8a2682e4e081c707b0d60328091c4095c09f1466c8c112968e286a60022374b7440a3ab45d25a13360b14e4860e9b8f1034b8710968e23583a44f00111a48a3031031d301102eb44847bbac1ce930e2c8770ea71fa619e80dc1cad3973d00093399ed0399a58d6a906cf3864e538421426160e271464cab4d1a428521ac38c0ac0cd26de3bb92e83099cb64891a44ba94042157c06fdc8b58451b1765acad5b71b0c13b0895970ecb38f371826ccb4e0d08597c0ed87a548ca1821e59660ed8c9052ae6e4af74b0dc110da07ad3964e550b920c78f1c3d72f4e4e0a11c1a9981a6417f40b372e44c8e43568e1b261338682dd1c10e392a1b8ef0a2c280d710d41ad22921201aa780062db8ae185300a55ce11614b931438e377c58cbbab1538401e46b6fd050e8cc21eb46101858ecd251e81d687b4ac106dd5f069a65a3b571c8b2818323c810f912bc81a528a59c136e8ce9949352aed38849c48f30c64eca52fc8da58852190472096da5776671ce1dd1081ebfea483b513b309d2718a3a4c98b09904b0913a0d614176758a659ad668ddb38dde9134dc9f6e24eead72513201944891ea92383c81f4c640dd314412f26530401c521475444523d4388a422cf1471473c45d314b412e131be6cc949895018a39473d21aa59c93d25a69add6de8bf1c518c3b22ce72c674ddb368edb38aeebb4f6bc9315149694904a8bcb4a271fb717450f171d7e208e492aad8828604e3a56b8483f2b9e5811b4820969b5a2c90ad70aa0152fd2cf4a6b3f5a69d89d3481c2133fd4a388a01c1813dc60a0f0887d0ff5e0f4e327fa917d0f0571fa281f0074260cfd939326b60ac650faa313e8bec2c56987e900e0e1f46b6c2300e81101a96163878f20750a9389b422fdb45c15a8be6a10cc496322778f217e8c34a26d816e3677771a31c6d6c9dfef0463286722feacbdc97ce6ab71b18b3a7af144d56433c99a7ca29a345a6bc2d0c75aefaeb91315a76f020fa742e4f0160e594130e1396a231c340efeca592061012467e8b3502267ec7e82c54aceb4e44cdccfc215474c68ed474ce8ae6d27af88e545419dbcd69a34211dd25a9cb66c264e4fb609393086ba30ecbd904b875c2117a790dbbd2587d3dfbe00a0600cfd93176d915fee17def0c5290b1414a73f428166b1e2541bc2e9e7af07a007a79fb15875136ce0f4b52158094e35229c868e708a84d3df215fd07d532d1a304c1ef78bd2386d4eb7274edf049e8e08dec7fc1d0648473aafebae4742d2455b493fdaf3482ad2118fa44477279ef75d975f3f497b9ea75f67fb15fb9bf2dafb3e83ea4fd18fa2b3edddf5b4eeb5de3df2a8483fa41fd20fe98776f242f183471d1cb280d8d04f73cef952fb5d773bec7367abf71da51da5ddd7cc4ee2680fbb93efbafc5ef75ea6271df5aebe54ebbe7bdd7d4d929a249b5e0f6c73cec955595f6a3549382931c9699da669cf4929b93b37f9aa495293a42689351284126e0287ac207878eee69c73ab5c7d4e23adb0a9719cc6715beb24253899d671dc6bdaa6fd06c3d4b8dfb6cbddbcdf38cd7bfdcde832348db3415cfbed493fa41fbbf90d0176edbd1789fc9a296526e52bb9f7ca7baf9d32ebf5759368d406616ef7dabbdd4be9b66ddbc5b68d8464dbec8f213c050e593f4c3fa6d87e30f94164fbb87d18e3ed5decf61de76298d2fbdabbf92fb7656c9a96afcef60ccab1dd69907e348a6778b56eadb3de7b31986addfbb3be789751b32d275693a426494d120a056925354c52918e9056d97c1397e190f5c311fe6201a16201d1c302e274f2f8f17679ec317efc27dccba8aaaee3f6e6e9bb67d01954dbd93ed667d0c7b0f9a41fd20fe967564eda1ae8675dbf2e917333a7d5ace40c126d638c366a5bc95afb35ad6cb3b1f7839b4d8ddad7570bcbab3c8aa7dd5aabf633244e0b2d6bd5fe5e0d86c971f48a9a243f43f2165f35a0100eaa13b5d61670bb7b01f65b7c8db4f565777d79417663695fd6ac6a90d89730f504ef336c8b8f8f6b666db171f06f2d3e493c80fcbaf51992b378fb706ba1c5ee926fcf6277c97145b12a96c5b658cbe2ed96b8b2b0d5fdb2fd7dede377debf7c0939dbdd6fecd7d4af41120f60bf5a6bfb0cd961aac56f6df1796b418bd725f470ae94f029f6b5ba95eae3c8dd23b6b5a0f1fadeaa8487b3d3aafdabd9e4257278c610726c9f72fcd916da23e1f6b3d7587cdcaff8eed797cffb3a2f6a59cd2abb260c7d97dd716877bdb255760fa5ec16f473974feac652a4396f3561e8631dca2e2dc7a2f4c9f782837d7cef7b7d69bd5fbcd5a41161911685bc15a75dcba91bf755d57d9c8d6e2d68fcbe68d2221da69ca04dd09a24f100b72649cdaa26496ed52489275896944b0e3e72f873c8e241891e82380a1cb27a50711e8ce8f1a309d7b8ca27c0c4fa4109d60f35583e2061f96004cb8727482bbef283dbcf9af69d446d0faeb177c136de3616321e33a62415e987b49233d70663797becef971f7fdb5723d39b1d8d18a47cd21192922ea2dc4b52ddefb04449f9fb3592f48372bbe7ae4a27ad62dc9cec33628c72e374cf7dc7bbd38d460c77c37f494a78df7e86c4912f03c75f9f9c77db634f3a120f101feb2424bc6f5d72f911fb8db4e2db7fd767d07bbb8d837bf7f8debdb1805fc62e4b2d729bf2d17277f74fee17eeb1dfbe1ac1f8f1c7ad85f8f8492ad2910da548e23e4376d28a637a2ba93cde38f8e5772a18feedb14d65e5c3f06fcf61bfddefda897bf1ab6cf8b14ddb6cb4049838c61dc61fe55d0b95634e6e4f3ac2f1dbedd33fbf95a71fcba37c1d496575f849e6e917b7d68b7fefee914f9af9f7efce946fdfb1cba8c9b671b2c7fe6e9fe302228fccfe7a1f79b8b75fb0ef1e77ed04b75ecfeb3e9e4129ef1ebfd63da73dcbb7f2cda0b8ebeceb4fc52f0fc7dfbd1e6e9ff4f3da9354a41fd2eade8b6dd24f3c016fca577eb040a1030aa8004940314135b13808c5e22819a088409d503da05640634708261822d5840a7c967802d553001ba04e3da0842880121e52a4c0033503ca068b0b70031e47701e48f0e8e1e1c383053c5ec063c5c3091c2a282c21fa90d671c2c13b5401c7505c7e570484918f449744b74467a46ba27342fb81da9d0e8c91df01fde0f227105e4d3855788610e79c14e3aa6975e25882904268eb163195a28961b7d2c7d9d956923f6f64b6dd4488d9aff8da9a6da50a21c459d3b8ad2423c4302207273737cc029fcdf9c9be6b9ec9c76a92c413e4e318e3d31f5dd38a5bb5a721e41e7a3ea004d3ae9ba19d7cdeb7b590e5531e58236fb68d7d3d72fa699a57ad3febbaac3b1632de6dd24f3ca1fbfbb9b389d5b5eb13dc578160cddc78286945fa8927c8c73eade1fb610d069ab48a9b758135f1c91d5142c999765f5d4d98fbbaf5ca085f585326a70d5d0906a05b1e2ee1ae694911fd1630463eac2320746ff143ca6f015dc011101da18de59627eea0663bef90a29a77f0fab907a5c36beee1f5332acb76c7f55f6458956559ce913336f229d7548540f56baa1251d5232fe0a4a19ffdccb2f9d96f99f6d90db2afeb8a7dd4da682df44c23383171f999c949f7cce4f432bdf2ab498c3ce6246076c99927e4cc04923395899c81f1656e82cb6c84cbbc047d595df3d3ea073f7e9657d7a4d176f800d24e5204444711942a1925eee15df34f7351eb33137b6018064421fc081379d031da6b5fec438ae3cb97f8109bb2063ef8c721cb4710cf5183d92659a0d10fdd3b3e516a9e73b31905a17b5565f831bba19422962045128e7ce85e0297df5f464c198140f77ff92324babf94524a694f39b9aae6969147252749455af10498482ad2aa074204c999ebaaa605532d0e97c8a959b500f5221d21a95845b8583a44482b999f14c826a0b576c9c7af2be8e2aa302ab9d98a917b8d949664c593e769758972fa54b318579eb1ede6d29112dae69e9d5f2f6c05ba5b1faf15e85e83b0ba031f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f9f97b59f5fe4a8d91719c629392574968231928e88689749c41d11d1ddd6e051fe8888be1f794c60813827a554ca9c9c5a6bb5d65a9b7befbd49e8245c2e9c848e0fb1943674ca7bc4fee6027ca1652d6f302014895c8010a61a813036d95218e5dc463d5adb2f302ccf90524a6b0bbaa81f5ffbb4cf9af69ca669f961a75139635fcb2db87c5f1326efab7d1486e5f9219c587dcd9c737e2c3fcebfe5a77246cb30ece74da528ef16747179fcaa11dcaa4ed89833282f619443f78ae467554918f8b3ea28bfbecbac91d7a75f452245308910b85a18ebb46c0bb75c745aab56cececececececececececececececececececececececececececececececececececece8eeb08ef44e555429ff2282bcfa25786847409293da44409292ddf6dad96af6fa16f09b5b46c5bcbf7b26d182d3a3a2d5fdf42ad50e85b36cecaf6c9a8ad904a8baf3c7c16941595931414949393939313cff33efbbc23b8d7b4e75aad566b6444abd5d269b99a20c2082153dc919018c569f401931026427e0c81c4233204912143040942248812593ff79ede23219ed69ee7e5fc3aef9110adb3d63a7b5a8f3e204489109e2176d88c848c848c84f8182131e2a9f6c505edf3c7c81e7b0d6ea52869494eac637c0a83da0827ad95abb50443ace2c6ce682995b6d63aadb5d6527befbdb75a8c31c678a4a3e54f6ca483b18d91ee4b6f34fb1f8431727e969b9c93525a6badd65a6befbdf7de6d4484963f5d2e22b42d5120a02e03a571a57e8d8204c9e9604dab669544a6a32126a5b5566badbdf7de3b3f77a321b0d110754e696da5745259ba479039674dcbb2f679cf7d0dfac505efb98fe1ed187a6794ca8aa7d554d3bed2b602e45a66bfbeb66db88d82d0d9fc6aa48cc97d32501a999c3ac8ab56a49262bf492bd26a3e7d6cf7a8a2a423a49f4c24ab724a8a6eeee1b302fd50817ec854562168a717dd35ad9a168529243549b41a5a8e663a8d7cb0a714bd473e68a71a2453a29a349cc63a72d47e35d24177ab9a34564747a5a3d251e5a071b04e7e1d395333a644ea5a200b6499dc8c9154bb2a69d9daaa4ab2acae918e0a5499acea1426a0576d528350da3ecc2187f4b38384c44766e3246732d48fda9233ddaaf884765595e8f0a8543a3aa49f8ca4cafa0c7a9fdb28b6553c2a4dfab1af9ccab5098f71635ae39063bea31db40dc236c8b66cd06887c6c1bef26e5bd9b65c3963f29233f05ed4455d1fab9a24dbdab039f6942367f049ce58694f231c503ee48c11728647ce5c949cc13f82c81939737fc443db87a31d3af26e7b2c113913b792237206df950f20de6d2b0848ce749b6383e44c8e9c997f4d366c8be583880db241b6655b17bbf4504d92fb838a39e7bd72bb97a4e27ece8aabed70d755aed639e7dc9efbb63be7bcb3d65aeba4f776f5f34887c6891bd75a2baeb76e926abba94b90f05a13c6be46e1f875108cc99bcda847c7bfc1126ebd25dc662878a74b9644140eb712a63a08bac04d348482c7c74eb413b7f1cb19fe88f1f79316b72db9c1c0b494c2f1074117293408c65829b8fdecc34e73dffad5af6fadb5b66e96d42635cfc5ede73cc241e3dcafdcde544ee5ccdf1d53ec579a638c5f8c3546daa23f77af9446fd9ad5adad8afdfcb078ef7d4c29fd9a16bd15c74823addb9a60568d4aa0ad35f1f833065e9f7edb523a6ba546d096b4f23c2f9254a41fd24afffd344905492b928af4336950029f3fa8b4ed95663dead4d000104000a315000028140e074442814814a6a2a0d80714000c858c466a4c9ac8e349962331884296006388218400800101919119221000605dee90e8f9ad514d2c92ec833f110d71489e850eca1a59de7780c6b88d73e870adac8d3a44c1a5bd43534ce9f228628adbd1f6f88f8121969d5b119b0af3be70166f8b0c3ede2413a1a49b40919060c4f102387f87bfa5916d89c6506b07566d24ec043d0d08c8537cc0952b7909d2166444067b51e2da4f0a1b310097efafba828ff8ef4d85b7af8385915dc4b1b775ce74a2b745350183ea658966a1e3e63555388c0d6ebab7b74f34ae8919b52c40b5fe07ad0f637393a1a5f48bd9c5e0ad5da52c9abcf50ad87dac33a7578de6ff838d3db5659b713fd14a509ab733541d2b59052505555eb3fc327e21549c426c151a3e30015919c609369db17d2102c4a776d681b856a9f0a5dc6c107ba6ef817aab0ecc10a4ac0a2b1829a9a13b1864ad944bae777b3800a481aae4a974620f73d8d835972adb3581a74e7cd9c91e488d457b026beef6adaf7ddf2148a8fb7e17e1d36f9049ae44b13a08296990de84ccfa37262b5411cba5d44dce2f8832e11325f6ed6b475f020c26abc9989dd027885e69626bb4637ef6770d867fa7efdd7ee61afb73d75776a238594ce6959264ab533439fb8825263211e1a026d9ec9501c625673712e331f1735b877c57379354f62c2703827be314d3262d263fd2ca8f74a1a6a59124659e408d936c9b750655e388fac3456bd65dd5ebde28b3474ab37f89903a06489b2ec7332c2d6ca70469cf35735c5a0f87814d423b84e82fddf52277d2f8728bafa5cc29b93c6eda15381d32cd6fb950921a3a0f8092ae5ca242dc5f77d2072cace5760aa4e8a4b391441bd46b48a6dea8bff5f2127b49146f78eb374e1f7c3a75409f0c89a811e7b709213d8017bb85df47a9db3e09ff8064831de2c810f1b56a495e8f0cf9b90432408298e8183c32d2209efd0b9d80c21f10fa2712fbe629400bdddb57c3fc6159ff27fa8f362a8a94bb40c1ad648acf6c4c861d244d2a19c9106b9ec40cfc05ba6934b8f86b918be8b5577080b9fbb0465634d9b2e20cf66e4708ebd16b536f07d5b38e0e6ef4e20b75c448967650745302b6d119a3b27e9e1f4283a05e31a8247c3abc1770249231af666a912693fe3a7a3a1b6e7c50f3ad50535ba9bd97f6aed5341f5c77ee7d7357af13a0cf79ddc8f417e86e0fdfc036ecf1b1447a9fc5cfaa440874f30de9fd5838588fd585811750be3b6d5d134ebd3981ab052139c84ee6b81eaa02b8c10e78da99491e16308e065e0f2091021a1cd1251e706b697f26dccc399a2d045955b20e7359578bb9e330a191b7b8c5c5261a23d30b6fb32b907cd1de2230041eedea0e6b2cb9ec49e1ef38f3be73e2c98c2c8acce4e455590285fe46ba090ca6d97dff53b493f6a1b562c39b72d358a1d800f41e1040668282c3ad57785b2b414fd34675e92cf486eff9bdf4a465ccba4a31c26506a929244bec7ffdc6a8829ffcddd6a755a46cda019ffcb0657d4b5af670e692842e005ef87c1220c146cbecd03bf41a501fca6403e556150b218e45ed6fdb2c7a8ff7bb6e100f0e25248c3b35d9b3184357d8ece078c633609a948f67e2eaead27ef605f241dbeb59a2cf44ecee31ec70dde518ac903e58980561191aaea3967a92e452282f3d1a88c913c0f39a056f6ea1cab0ee0c848f260bf529eccd4a22c06f866668dadbaaf2cc435d85928b52f0fcb180e3a7f4c11d48d33c78453e7719180ad204567ac1f67bd932e72dd1fec29a5c04b480780df968c584b42ce5981ef3f5229cc2429524e9d7e7e052230fd9f6956ef33587c112a6cbb3f7b19bffabd3199905e3fcd3ac08dced0497b936e915c91e26c81633f95458ab62905595e0a89c355285294ec36e833f266f81fc9d9920350429bdf1b2d8b0ced0abb7846e1b93a84734a5269aee05bd9d11950e26af929632aa6506941c0a20f5132f5a371cd45fc56f8ae2efe41d501e455a115e4c512e135f3c77a1fff44e48916faa1a0dad93e861a25d6e83a484936ea8d212e3a883f18dd0528fd2e5af9bfe1fe0dea984e079a8b27a35bc97f1b52a21eac7669e03de4b56d7bfdff544181e5b38c07a9fdfbd4ac8cd78edb44e007e59f5b461a2b207b47a012bd415047bfa20bdd93f7bf2a6d610425d58f932c5fcb63afe4d14fb38c2bc6a6e41ed8ee4750068f346ed13359af1d2eded57864f02e0b3fe26c2bce04796bfb26c66180ce8ddcb9c5ba317f4d66dd6d708f33a32beadb2f4be615461f0e7ea251f1361b6dcb73e17837cb9e573b47baca07dce84161755a384524a978b48639fe8f299aae5648456faacf8b272f1c00d934329d56c295cf3882bbd7cb6c98d6736e269d2a9cf747817bf440cdf6cf7eea2e1c2883f9a2411f9165a3ba786f3a8ce0b8719ab2ff742533b05a25368307f5eb3dc3409e092538d28ac12677b448828b63575f80d3ac9442fa2766d6904a300d2d4df1032a34a70747a06897b44455e0adecf92965ae866dbc0578163f2ad6b9b799d000b6ad704bd9ae2665b42288951b17c690b5a223c34fea3c103f7a153a204d4cbebe8e82037b746335fcd95d7c74e835d6afa91a2b3c64e0b97cd4653ea44b30feeb2c9a8543935f6825d6a1a9929c5e5de6a93704ede887e6f15499bab77de406ca1610d8dd3de4282ecc53b0ad72075507556bf7b5501a3e915c42d9ace84eb7ab5d5c2e6246ef021aabe24faf37553d520efcc514c625084591bc521dcb70561022ccce7cf4ad1355590ad0b3b8c7d41d80ffc26ab172970dbdd4092c9e7e33def8252468670bcd441036ff034f0679a8a289ec4e2f27b6e3adb8641c3d7643852f364abf817cdaa6e9cfbd6dffe0e3e590cef9a2c1ea6e8d98e66a73974c1c9846299bcb37363051b784caab43525e02cb3464d6435eb993df99d1dd13757353fd27b4892ef54d3b32eabac514c103f5dc7cc4e379ca6680b76f4bb5cbac7360563185c22a2b275515ba614f5b574f6b4a3e0df34ebbc1f99366ea60a32ca344934534d2ca37653d60c3052062fa09af61e1aa1968d8a794631e778fde0e557b2784c6326540170e2a444639bcb24ccbe56330530ae1999c43c37b7212c125c5489189d52c74ac4e7bb9586cfa586435c11d306d9cc83be5db837b1ecb72c12508e9608eb31fb98ee8435ac98bf44eb156d8def8f03d7ea65f27b49f97b224fac074b6f22270c66e1d6a1b2c9c501b0d1ee1e569aa9199699851fba3e8b9700a262420d83308c49c6ccf87b7a329577031c47e324bdfd345a985b8d1202af9f0b6df998e03470fddf0f2e1027efa4d252a0f4b885728b9aaab40e71e878e1c737f79fd0b52c21083c0ab5d5cdc5d9e4d4306dd2f8458300c68b029c80bab53ee2cfe955c0ebd030237c8c267900d2a64a92e3e729134ce42dbc1a25742ad8418db507cec53b4a1ad1813a204f7efea447fce8011556bddcc8d83506641a3aa2ed47cbe59bd353143cf2f913997a97888c4438d6dcf247a40c12d27d551dcdb323e4a8118a2c95febecb531eb559a74a39dc232b59180a86e61293a559ea640e87bf87694e3c9dc0617585920d93e0a5c5051599e4be5e84a721f5ca6217c961dc60e806b5b6b1ab0e19eb8ce07243f3f001bbcaeb7541a7b231bc210ba3971e6e1835c089bb5c53955c17aced173312f299955259dbd5c29697fe784fbe5a4f198cd14a22d84201fccd65daf9f7955eed2552c217936d26d21c4ff3e585e353412f35fd4ad15173afc5458d51523a44ef0abaa03952cabc5a7b412e348e3a0a611947af4a52a44bac788d12f84250ba9be6e06f71c6487b746fc4343a84683de86caaf403bcd83ae6c4055eec6e1d06feadabfb2d3a7a9125f062bb08cd17235e6ca5cce568494969ee02bc8ce11b3c05e8bd1aa41ef54774e065e06a742777fd0f10fbfdb3ba9410c07313c4cc1ebc5876e74be79bc083087c5dec9bc7be3426168b6259f6a1884a025c3b175b27da0289acb2a73beeb19a596c00f1f8817c7f85574cbd6d1d28453510ff066b1c271855eebf7ecff3be5125837ad24c29a6bf78c23873b70c286fae56794d792af5e15ec41c84b3e7cc8d6a5d7c81aa91ca8b24f53342aab9d54394b02f96ab5f00a46f514a21d5afff54c9c5bcdd328372200de6cd45699d7a21f22045118fba0d399454f72615a54aa55a96aaed7784a9be91ea7faf6a69de97d3e2cf948d4339b7a2080c787b71c1ec0be94f7047da450ff1b7ade1c1b36c852d0bdf8215fe54dc72c49f967c13b54bc7379be1e4a0830703adb1118adbd250cb59c4250d5808121e500c5ebfbec4f63141dfacdf9c57685e4640c3a311e7be0ecb36de558dfefdbe242e1b5f29766ba5397ca2287154e3632b2d9f1f380731365cf8fa7c3ab258cbdf675902e7e9e3c8fa2b1ab527c912fec03e472c5f1ad5e68613feaf58bc9fe7ac9732443c1452506ada72f043e979704b8ca3140585b7597f5cfc806593e57049a7a99924aec49e1f41f85d37a8181f432b1bd228fd9f270558ffd381f1565a30f19b28f647982123603edf7ebffd7cf2d1bd14098775b0178a29f4e2e043e3f6a616f48bb67da79c452a615a563c01fede9a37e167b2dd096d1559363b3ce17cd8519a5db560040715fdd50c88afd13e5981e658bd92aaf417a21d9fd69e3c79006f37af668710dae40993263b598858494a53b0c13b21335ee46511177a3ecbd5dbb572b46f10b045fe0482dc7cc9c5ae7cf226a90e0c8c2af0f262924cb33f8d0d97ccae30893f06b7d23d540a8025531a0404759470b7ee15ab35840ce7a9775f41707edf88ca8adcc51ccf78c327c0fbf0a4ab2fe269d3fc8eb6b92feb0325732713453c953542b8fead89783a95a2cbcc748f51f0d8219e340072cf3668d2abf7b6f3519a13e01b10b54d4a66f04d32300e4d03367cab850d2fca4d614f7cabf59efd45954b55cbf8166c60f20515678d5de1f1edc9ce2f5962411d052c63267ea5b7111c86d5f927f98641485aa88600c98cbcde3a549257be21300a1154f936ceb67dc162415906882837a6ba46bf9bf2c7a122315049622c669e4dbea9cc5f2d183aac924082268f9cf9861796240520157d2306f6729c349cf92ecd8f5a1125ed3b894af94e87856c60b4beca5fc4509b1c650ca53939f38e77839c2c0e41dbb47c7e6ba6f53984b929b629667226fb31a81a8eccb2555352e0fb5c88603680723a5a76209776901a1362bcb420ab6decb071012ec6404867747f3da1b008c5777d23539a1d9485b77f7639e1aeaf146631e6a112e78daa3c168506bb5657d36db89f58fa21999fb43dfe9bf9c812770d2bed492dfdce7433ba8608176152d8d5e80df9ef631d86475b2f7751e540ad11f22f52905bc29c6d9d3fc36efd5e94fd459530e65de6dc5683c9699353065bb060a2dce21c0762bab88bf0a438ae79249bb1d6119c28bebbda6a08ac2fb4ea54b8504af40351d2b2e7898df88bc9a5244b20aab8a561c98e34abf691a343df6ca19dd4e14814916a89c1c09e63b33a8e9e0d6ffa7d4d9de3fe2447a8b5ee0b05bcbd2fab1e006ca071ea3b8f3194e2f035c2024ab75740edf61bc6d2f15a4ce1ff6a16ca41dd50e624cd3f4259794a395740852db43af43c5b104d139f6a969af514c00d55c633c1d1d6f236945cd7feef28f63821456b26c5a554129b91958ae31eab65e830be3e05260530b1bc92a8119040bd0595606a0d92f4dec46c670626057726de0c051cc95d2691e19f6b7eee2a10f7b6a5be24b0c49e87a4d2d6621aebeed8fc1706a35d6d037c7d935585e22a25e0d5137c69d54b9d65c52d113701d492e45ddeaa861a7016c068e4bbaf9fea9884c830e1f15cc10b27f016f1e6f67de7abf072d5cddbf55b55f7ad75eb9da02ebc21df37f5d90094a1ddb8de8053893e2ccd0bc0d25bb61546bf9d3e045cc293d59a59118ff6c60610da252db76f7a8fc22f170dd2b74452c8770fc2113101872f3ea51fc383780e34da8b4d82cbca2b2f70a1ed6ed3152d286cec603b5a19674c807bbc2e52e9a1d89091704d23e2bc7317480fb598f73b8e4066585101a779eddc455f9f6407dde799145f76d1439967fa3fbcc0ccadef006227ecca4392071dd6a3518f1eaaf687ed3a8455f08637543814def186c2d5f22f2958f4a2b3c3b232cf210c334dc4fee0c286688046d062d7be4736755f9c0d6026df00212365b126380e4e467c9d87da1f5510341b63b69d0cb17906d784527a6c87b0627c63a925c0f4a51eb4ed479b31ce0817c73152189acace97f91fed0164c7f882f1d8dec4519b53cf5e6ed5a277d0c0b9930214dc499f37f1a9873a1fda503fba6a49b64f8bb3978a8e6d190d8af5b567291a9fcdc4ac5cd4ccd80933fdee6622c2bd774cdc48048306be0485d63c6766f46b12a23807d1fbed144a545af392399af5b10b79ee48c0f1479d7efb32f8884cd8a8f3774f5384aaabf03ff3c186d3c399584703fdb5c3c7bfa0d755c10af0f089a89f6392f249d93374fb5201af5243a0105fc4eb252bd8736a7be87884038b815f91ba48c34f3e9a5c674f4deb1fefc1cb856d305ba8d394fc94456da1521245fa1d242135cdbdf5b886cd117c69b88690e71fed273273810ea289046070f14430c0decd96d6599a7f6c43d93eaecb882af82e77aa47e911039e8ee75a1a00a41628ed3016de530213e6e532faf8d74936724722ca7f2e5017d5a54096536575578aae90d05ef675fa50cdff8fae22b0d02d3a467a19a8d0249908af1101954b970541401da3fbd0f8abb8d33ad136341ce745c2740f6cc57ab461a50e26ad7a03aa1660507b9cb5f934ea1716d98cce73868e773e2c008807b8155d3a4d0370e74e355376031737cab58e1abab2011290763d0d87e1ab5cce13d9265f1de153137e238be68f39d6f527143f8752e28114bd6eb0e40ed2adbed96918f1f10b545e50231b3760bc6b0fc38cbcf825c488f8d6560e6bbbbb7f1a51a42e36232d81339e5254cbd3711bb3d69109f9d3fd4836ea7ad449df1db4da3f0fa19dd78caf934be4d3c2c95e83500cce27e3e4032e8bf1d308926413da51f521d251a59a78375123c256b0aa55947d9a3c4b172dbfa92d4f1db0ba3a51f8b6c96d157acb4b942fe19724e4c366e4312038574d4e2daa4ff0069a7998fa9407e4b407545e8a014acf90c20607453a3d52c49faa0d7840ea23af9ce4d4acb1856483fd2960813a1117c2264b5d7f98d654874fa370fc6427e198d1239c48be0ba1c8d3d310fafc811e06a9cb0a872e9556739bd871521d0d217228e8f63909435747da0c8376e74631acba1308affd7f345bab7f917a234225f833cc3420f2e86ab2f22a7ea33cea073b06f16312da04a470eb67eb51e4a24fd15da92ffcd1d7f43e8b026a7f3765e001e8e5d7398eeb4db32a349ccb7a9126b479c43966027309e6383154525367daf211a9a7f355ff76a67527c108f3dade88ab0130ad229ad66ce5d48ef5caaf4450f3694537a046eda25d30a0bed3d9a9f5c868b79a804e4fdda8192d2bb2d49ed2bff74d8df61c962b9f025a0a8e6a37ffebc50610307fda1fabc88181938f31a2e3afbd981a46906fc10988cbaa915594fff41a3d1aabbeabe66bba34c83e602dd10770b0467b233557751470eac4c773fb8d364a61421048288ce41c174f8a0cdd5f606fc7dee5348604e8b8f7ce19940fe53f06cd45dceaf6f2bcf800a60bec12e874f5544defce212a7c73bcb04d58a5ddfc82c0e43a00452f5c12d733f7ebea608ef41f41065ed2fe5cd6c13f6d96d572fc2be089381fc9d9c4e185fe9bc83418e4e9c8eda78c5fd4251d085ee377bdf98cd9baca41be4f6e8a6453a321da594dd94ca78124da55a837e93d69d6c8d6019f4ad1419c995ecfc9d1132ce849222a251c7671044598a74ea18309b537bcb7d02e05c15f6c7a1e56c0176c0d89e89bf344ec061c7dd68da24089d994a8ace9434652756392176716b931a82b5f7c90c9496bca6301034d6d1df89e72409e1c8a9e7f7d1553db9b7ffb41cea1b2d407fb6dfdc08d3ae540bc711ca21a7de9ed486baa076ad4cfb4eeab7f8a09bd9ea41e4cab053660acadb1e970f93ba97d644c347fc850e1119608a2f0bceafc32be4a366b3ab82d4bc152b1fe12e9b05cf93245a6fed95ca05f4e2f05717d322bcee810f1d36d9dc36fa6cede552d1c755e1c1316d152d215cd050cad38106e4dff8ebb64c30ffd92a22732c5d0485406f282d0a6b862a5aa1a9b0cbe7d248513fd8c9115240929bc280adacf727ff656560d29b5a9ecb3a8acea1589fc1853f27c7a8db9323b21066ffab42e984ce0cb6c76530d192a0a6c5c63e2a6ce3a259cc5932bf5b59924abb109771c0daeddc42f336999e763a84169cd2e787d593e36a214ca06839077bac950dc924b2a41a19d3ff41e649a251dcc90dd83f3601e11c1661f8b61c5c5dfa6a9810fe794144b16dc5ea4a952a6979d32440a7c19deea5d223da2bae62d16c12d0a3831d0e58f7bcdb7356c1270e5dea02ca84eea3b8e07f8afd41bf6880bec20875b25809b23d12f58ae964d42e225afd4b08ef9c84ca5cb7a9cda5b3e8d1601caa97669a56e899774fc84bde6073e8c122f61df14b3f1a7b0d205643ef65f641393aca8d81cfca50bbec23f01550b38a38defbd232f5148c1cc43f13342f26f4ace03a856af2ecf022769df79550d7da1f55f532f2ac9a9ce6b4011e0f625bd696f166c5725748bbdfbbcf5a746549ba100437a854c8def2276a1d6518944843d519d70445918ed456ad003426c8c7c639c2b4a12693b10902c337d37f19095aa61cacbad55300f130bc52e76d9a8b35b3c297853707ad2543f27405692333c06ea519d2f29ad696612411387630e5ffc63a543acb9cebcd955c74a59479c01489a0c93dff82474c255add26a77ed58928c600e26018c8212578b7f8da27c1bef3c72ceca35d65fb5d7002373dc58e9f6d96ab6383b37422bf799a5f21a63a107a945c4e1f8b4e9c30a779cb3fa6677c2cd540e15fb498c522b4f0aa3b9901fcdcc9ad5f443677c89d52647492ba4ece4993bbd0e02fc8d8c2ad38df4f6aae916cf9037f0679af1d096de4b92dcdeddc31712e5d55f1dc90961f29d97844e2c6e9e2ac8102b45bb54bf4945772f255e153e075242b95401d35fca734e6d9182672ddc9358110b1424d20a53cec918f1ad2662c61d27dbed524b46295df79d3812772dc8b1cbe2ab915ab15136b22e394362c8f6bd3362aff3d1c07e25b3ca3c63b403c7b0c4f94991f587ae5840d74c5e23d03029a940f9ada1ccab865210cb876e76c85ce3fa4873e1024fc49c6654204800a7c7af892790fa3889ffd58624d5f9365ca45bb2ea7615474cd8e3ad4be5451ee4f2eb450c4b80f881dc5ef87413a31896aad14c996373919ed9118257dbe26e4085837b1256f61fb86aab1f7e818c38d354a00da8a52a90512be2b29bbad1101eadc2c9ff0f160de43b26f58eaa0778124bc0a458f149a2a027bcf13129041797b853e5ce58226aa4ada45e805ccecdfe2c753c653ff6c5ee324e49932c0e5321eca6f9bebae6fa1e3bd85cf4fd1013e1e323a11f9789c033fb47437e7c0d8769c4a94c6fa4dee6d09f22c8caca7b11fc3ea03f516dfb125754174004bde5a201da174c245cf7579ac294af8a951e9e865bcf66dcba220afcb60d1ea61447a4f0157949d7b6d17ea8dede633414b1a5da021265a08d9ad4114bdc7a0101835193b5d33ed61f5a7add9c7a94ecef8308fc7ea70b2bca55eb781b57ae49b354edc88eba5bb1eb0b21e45a3a82e234dc2f98797241593f6f51009f1c7ec122b99c7705acc4cd57b786cab35c4b454801ebaa0a312c1d49eb33c39ea81862c411aa17d8d3647e61d92833700c3b99da1fb2e55782648e19d0d9233d9d00e18f37ea8446d9c16f564cd372b70c50918a3154c00356c37bc4cb06ac77c575dc4a1abb62aed76fd9aa981a2e15024504c964ea842123739232d4c7121bff44b3d902dc505233ece4de5292e4966f434a0f7bf19d6a36a0a5a4c3b10c9027a844ea0003b5371a08a8c8deb9c3e3ee8fc05fbd2927c85e13f2e252713120d4743910ebc08d53c290a652ea8e1bb34302f3b9c72eab388ce85e005ef424aa2bdfd3c05aa2c1571a6f5a505f19a9d832f2bd2b3f4ecf2801873dc85ba73c16211d9008d13e18ad982a6d041a33c9a6f95d89a5276c812e0fbe444f05b99df6a7a2255ddaf6272a003076bc76aac1df4b49ae504e1dde0b5f8a3d131da4f3fc96bf97b6245f5ffd098a2a6044fdc8093f30c8510835fda741f180f88012288bdbe2f66a3d447596027fe9fda290b9bb33ac3ee8c631b94415081668ed54e201c643c0c7d00cf87993a5a90560d2e38d9308703a8f09fa587a9dfa767a4976220d3f4297a17b413c65c8cc7118b6ccc9248089c5a743fc600869678a514769104155d4ce3e349f01cba5b1069fac9045bbe6bee7d3f9f0653d6a74bb750b411d930faf7908ef37a6a1699a315de9979e82c5911092c5e7e509816208cbd58a05733825f157980ee8248d2c2d80efb92685314d71fd8d34abb93669945eae8c58adfad31dc094b853114ed3a860cb94ea7fb424ce844e4ba738b8cfb228fc7ba16504ec97f44e78605122346a625db8a805c3057b17f3ae2acaae29b33411a0b0dadad5c9dfac332ecde2f71bc2ee076965c2bd3c1a51510319dc1dc444a2d6d8b24283067d510f9a327ba6775494d66ee223fe4ce9435a7a94ddd7c3b40308b7d218404bc52c19005a32c8f34b108aca047d318a705221ec616f63ef2295bbfd23d30cdca705c845566b2900d39649f4430f242efd60a3091790a6a87d831f54047a450a4af442e7e1394e5a4df7a508af04ba4a7c862992b69e9c9528c68327b260ab54bc79480d19b5a8f4776b1b6f3c9a3d77f628a758c7b7a173b85007efb671a07671f5f3f81cbf4a74351038f9d1f9150aa542c4e0269e72c1dfa91ffbc4975b8665c5ded9df88744b00486416051a93f23a8d27f12870858192c99e4f69bd279abfc548ff91c20462a1d800564267e50bbcb42e39c8caf173e447f80394b516e61e9ffb40591b20f641c15bd343209faabb5398cf79674f1eddccd18d716839c874f3c68c3c99c49ff3cbb8f0d0bab82b819daeb1ff92bf7a6b81da1826e5187fc104e0075ce6323565d6f38d17fd8f5f966fd90c9b95356b0a62f95f73d7e5713302598977ffb4829bba4b8199810c44d9954af1ff7cc0931f018441d6f518cf94ae0d198c7a137b2eb31c822cecb0a2299f8a1e5e98a018e350a950f1945ddcc490f5437f27ab89eb8a51f4f06d68d5df247487310ca75790192c149f936b8e51d92d68d705d928537877880019976ba3df5144e23454a236a9a0d5ce7e82793acc6b6df18ad3afa3a0daf8eddbb09021098555f54c23d736a6825cbef50337021d4d70f0c05cce0bf50c73fcaf76d7cc1fe6f37814a2d10f222b0ca0ba30636eac8527383c5473f1b325659079f4d66ea4086fb383302bf3d0664c4121ba01b54b4f0e486bd8e879f4eee53394bf191c6d5718a82a4455025add591a6809aad2b713cf7b77fd66a3c3867074c4ef323d7ba92600992208638ae280dfd076126c219eaefda6aab417056a4abde7be17d634a425f4234d9b4afd1e1eebec684500d2525af0f3a6dd7b8541a9453c76044ef1c83b5a7753df5f10295e6a79654b64c6d1cc44eb0d3f8993543a1767deaa70e49366b85ba3499c3154fe0ae1e789b20032b0f3873c75204e0a8dfca23388a38437a183b6c2a62aa25df6f6055b9c886873aaf6cd59e8f603b33ca164cad24aac3961b529c6666d2afc7e40526c63c7b72b901247a87063a8b4490f26ea4568799e5fb569617953c4eb08c032f53a261155507468e99f1ecb071e46221a10b839c62b6d6633e95d774c4d713a39012728d2449b1e5c5fa2047bbd63f11bc4d9a10c3549dd305c39e103e52c8e6dee126d52cd846d915e28a4a04d58a2c3bdffd29d27c773faa57bd48ce3c3c36e4cd0fd3d351558f3d2ca76cea88c5a1978836b87ad4838d441d3927de4d64fbb7deddd186bfd24928e3893bb40b91b2ae15570e2116f26f547511fa059d6e79b4be85440b2273fe3138a13c5153adcb34e20e28f8036800c2ae03d0080b224ed081b5a38b896fe81e2341542261e5700177a667ef45efeb4de6c9313c541c7eb4bb5d3e3df42004ce5174e98270660f2bac400f5687a745a7074af294de4092e382437cb562cc549fb3f198970226dd26eeccc3b59b4ed991fa0cb958cfc37434d5ab8c14a9b320d588c322866d24c3f47b5ea62b39536e136ef990530f5d1a917e7d28b3982ba5d29ea7b2c3349ab61cfbcb43f2a15358a57ebfe2a51d84a2049c00cd4caea96be7fcd4f224caa6b67799b2626b2c952d4c0ea52b453f56eb7b7c4d7cd829581c10408683706d9ca517fb51b1971ff6b109810cdcd9164bc957fdfb5640c95b649ddd7ae6d384f23952506e2060330d74d6aa533d298c1e2ea72c7649defc1629b1d60b342967f49561b1ad76e3fd2fd5392c05d7ab671533479043a0a364bbb6f36d4c77e63f3041a3768ea4625d5c1094a762c6d5cde8e5a1245a4ecd1c4935c00756245ae17fa456aa8280827ea733d8507146e8c5f1ae8e0365e92d6670b3aad70538d6739fba09308fe70b655139aa79b5ded8290b0a080f20eb316ce0cd27130907aba67b83254eff9d89a877041fb01289acbce1d376833271352325b2fca2eab83563e1ef0239e59c32e252719888b54148936d6ea5737288a325c8340c2efdc70215825e65f1eb02a314465cb9df05b390018593fb959a20477d66d5b1dbbfa67af75744ba5d3913237d439bb1171b48df027937fb4fc581796c4f138f3e1d6432516d562952d6df1b035cef651f329802b95e9236157b36d0975abd396803f5273fa2bdbe8facaf7963875081285db04ef5f2eb3c6dc9cbde724b57e97d0da1723156763af6701845828360f19416927abaff0f6703691e01b798bc16339735235956b4284f8305a126e7059aca6ffee332ab50a9f8660de482fcbb28656a21cef937b32292f011960e9013c88157f70d7616afd26a15900f2d3fbc06117a24b944fe0db94c338c29e56d25bbd2a7dba3357324e6d8074e409a276a2d33159b633ed094c69250e3a34b6712185eb29b10c394d2f21fb8a1489e87f491a1f21fa085a02cfeccbbee4b2212fb54e54cdc209e1d6b5ded13c8464279a9d89c22e26c90f8996cffc63481bd22ca662a9514102d048d690683dc3d99d62a36347c91cf3d0083769a5febc877a68af7fc26c7df6f76a8af134f770ab61943ab56316548646cf10a4dedee7a41ffe8a7e0f23a4ef69bc3582c0d50d7d8c9e0dc106f22b39a297a6ce83d8b2ef372c7c3f3802eee1f3b1d84a254edb74db390eb3bb6b6eff569305011a4d4f74448ad8c151be2771f6be83340a4848675b82580309646482718a2721d2c4ed28826c838639959630f09d7352bf9fd51ba8b49517b15a82b21f1dd497aebc7b766383c1be8cd16df6bbd7982ac3edb49bb62f4c0ab096e6dc23bba51e9f029c46f014d1d41ca8e46fd82bc17b72fbee3fb5a9c0d0f6ab64a21c7efdcd337a9054a514e21318bfae7ffe42e3757bd9467bf9d6038d9e2adb9ec4125739ca5b5cb5674c5a5da9b2255050389880882658d0f397ba16bc624e0fdf176cd82caaec496a2dbc8ca04d904ddcc017eccb3fd769feafda6f280fbb80da0b9a4d6e9815791fa86de1494c15e29d19a628b1feaea01682cd2289ea9b52c742710032a2cc661c9d29471e555d124964ad04ad7ca3ea80aca611283aa2a253d4299f6ada3ff1dd61a130bfdf67a40ef0919c7b2cb825abd67286dacc280b136342b6ad38d493aa2552e7100a3c70c512a795d6e0e22cef1132cc14283e3c7c2745f6f6024ef51019c4d27b7e7772b6fcbb0d640f907e826d0c4dad45dbb0c2105f57cbcf989a15b1d2e6f11cefbe898c1c45ff9ecb651edaefb77b25fc1fc0862907cfc37bb96cc123420978c71d802acc43dab425771300ad54684c4b4520b3395453209532d256744fe33ada93c1f13061c34da0caf82bba0601d80862e5af73f197db5503c720c53cd946a88ef5d63aa93c1b247cac5932a0dcfe2a926f1c8c6a3c561445d43bf74e58bf298fdec8cf573ebb3ea8bb66b27696c846fbc477e311aadf56d6f3ac083a122e5d51eebed6e81b894aaefd58a6d88c8c885d3cab491bc5ccb7efc680f74ba38c684121861275463348aa5f2b4603761bd0d0da2f82e68ab35d801436bff812c8d34964585021a29e08e42a1996c063b8fcdac660ae7ffb905866c536ad2389991c2bfd5e110fe2f1117fb727a27591c2f4faa8c75270144fd4706329548a719c4abfa8eb8184f4fbcbcffccb41fb536a3e933492c53de5505b472ea30ae81d7725a51bdefcea3034f2175fc5c9d9c8e824ebe26277ce999fbb984427b564519b3dfb4a105070462b7ad18076bf21f9ebc1cc20847f866ade603e437ca33744a41d512e17e18d09e0b6810e56fd13bbf92851e4d9a9849baa3640e1a9ff8f3e036a1a16b4ddc5962b0a25c81be070fbdabab3a126147164c85ac859803cb9ce61f8988f54d791a5d856cef2acb73f7f3f5bff3edc227cf6699fb37aad4ae6b227f4d826201eaf892574b4c8e2bb938901ac30608104bda126ffc1f147f720a2ef9420a36905d0ddd17f98d452dd1ad4ce75b9d87b39d90f63792a037573b7b3e6dd474b3ffeb5e36f5951a338da5bf980cec22e3e55bd2969012d6991b4335b8e1b2c84b868cee82068970030de789a1fb89be23276a641247f627d8568c0424d02a10b035c994dc0add902ae671a7073f680bb0920770418372ce3df8b28594576fd526171126e895a59536acf630084554775447a0939852758ff9d564bbc472e4219ffdb036fc27ec40f4f3e69a5178684bf22caa8ac20defc06d4a6a27fdee6417f63f4a2d5211c6e6dddecedcd728624d09cad89da2b50c877e7bd64e469735d2c3a83bb14037e8396464ab06b28dd272c0796f6d59868d1c987cf3bd2bfd356b39985fba507854ab1138a2e0733ae9c16a3e375580e5c34e4e89bc39fce2a9aa7adb7dbe139f53ebec16ef24d61e173026771dc1e9d347d326d70c404e9828713370d46acfb9abf8d72a5dcc91d847a60d4d904b02556f6a8691b1fc1924a6aeedd90c23bec865337824deb38e1dcd5160c577c8dd045b3c92f8c007d64abda620d546460bc16bea30c6660e4fdc9c4e2df68e0b44d179cfed32e56038361f98a8c1d1c6ad8ff45f87ff4980abe40993d6a29c70d0c1e511c5a771f54e3c1628603870f5f0b6789a1df9cbf4b9dfed1bc3f1a909a9996e30e28f36327d44332f2484f00d09100840f18782fc04de004c881f7a585fa8cf632ca9bc081b7a62da3004e430c1e4b5ec5b6227e1f2eb25a32885d1b761e3461bc2b082eb0ed9a207fed83017c184ab09ba891e7439ff5ca51ecce239e39accd4d25ba1ec4a02090dc0df364121c8aba2a5d08922a04c29822e16defd1b4f0687a1d9c644ac3caf6c28cf29cbbd8f034cf1c18c5205d1cd6efe2a038d522ed5351cffd39552fdbd86bc8f1417e1022151060488bf3b459ffe32e121412af8940ebc5b4b6b5121e5b969f2cf793f2c6d1bb1a6108867a8bb047b5b569263bc20e053a6e434358e282abc20a182031734530bcbb840b5b6bd3a0064bb7411ae8588cbb48ac9a95236f62cb17305ccf0ac0aa31c58c152b568c183163c588292696981862638a892136a698b162c58a9161588e6d688008b108e87fbc2c3ff96cb9bb805bcdfe8948c0e33800bfb061132e4092cf59eeab1d52427fecb17846831aecaf6fef089af527801aec8baa91b458a9dcee3156146e8e8104398b3b9ffc3c58b675e0bf8b322706692d2693152fd8dfdca442db73ed8882fa9327064fa8905a510428a0b2c7d1d586ce4b568eca629a5015eebfc62cec4c88fd545bbd6f70f0a9d608a05bcb9563882dcdc95c9ca2043dac48dc479f9d96d63c86ba2e7947e1f875b031ca36eb3b724d26a219fe1f287d6ee314a66f3180d83c2cb6721528d23e917cf00b569eafe7367db7c512055470ccbe1fa2c7a96fb0084247a18cc95ea625c92d4dba92fe705ce1386418e008d95bff4583e81b747911d510d4ab37fff052412b1003aef4a053bd7a8aa48c18b8027bd6eaba80989891f21a4c16fe923533a889ae94588c1cf3c8c4212392016d9a4e3affdc2106ed380cfcb2eea1c48cfd861c906570598270a94a2d9a655f04286797d529f712219d68fdf8a19c50d1478b878ff4fefa6b2fcce8a5207a3409818a2aae8f49fc99e80875e4e31485c8acb393f6ce16afb9d37343162173c39d39bf3a6af0ca9e4115c1e362512b75afda4d6dd571736aff156593149e3bca5cc61c8dcaa016eea0d02713c3eac8783bed1756463a47397e7434a86d71c9192aeffea81c8142c78db59a8ab60c0c16dae9c361c140743b12f5d47d238a81c45ec9f47aa3658461c1eb8d02a4e410588c82586af77de8ac63f3715f4de72736b5fb3e74d6b1f9b8afa6f3139bda7d1f3aeb04197007082e7d9f58d46ebad095761cf45750ba88a32febb5fcd5a1cdc97d65c22296a37221275055d6e1f2096c042401688a480dbb09ca6a51f8d63625718ffd077ed8c898a593537526b6a278bad299080e92845226b580030cb372cb878de44072f8a503d73679fbed198ced53b49ab94e7ec0fb1e5f699f26397ee6cd60b370fcdf94a497de463a1184bee4d2e0fa76327558bb54bee1b0f146bd525b742afa458bf295e33aec0625638907dd1b1db5401633deaac52f920fa8732019b1c0c482265b9984d58c3402604d5f8f2bacc9173cf99d6ed959cbb5c16b5fac0db8bae785be0dcdd40957a798d836730fc5355f3a8cca7d8133b200f61df80c50f71ca5b6d56189fd3e0f4b6dbd65d75829ad4ee8b3dee82a47a5bff336de9d9ca316d75b807658361e25906ff0ceb7bdaa0f9d0ba2003f6062d56092c619ced13c18c8a11bcf36b7ba5120a3441859ec021b3fb9a4e67de984a65559d080c5376adb6939668a7a39270f01a4cb820c8281a417032191e22c46a80504af76f47f2eb41212a3e595669d57a14f95b1bb4e9dcf2d53f51d64f9fc37f0b955519fc03a3678ebe0eb67fd476f0c76dcdb3c36241629b4b89c995c5e12c74d195894029a302c3084dc8c272bb05f53e79a821574a563426515b665e67277a081d9536b832bd81bf3adc43688464c352f872a6c1f8934fc376f0bba829bfadc94af27b6e90773862374ee902975039d74997887ac8a8a0f085de40f9a44078b1afb130f68f05e0bda1467c99813668ae84e7e8a99658c36111d51aa4f367761fa895cc84dd291dee442a383f360ee1313168e9c4c562afb08f747c85b416f2265f3e4d71aa7fde0b2e64eb6c4cabfd2865706102b22f1ffc421acefc441bcc9fc8af9c2656bab812d5ae6d58cf0c389a4a03df7f50186de7e2d9d1afb9afee3bb335813865cfc859010cb30462156eb35889c6151a9ed2173e0bec55818b98c89a559723a6dac20624ed500e52cd09e74d8a2f4ad31197a8ad3471fec0f793320ab4adb3373fe2ef70afcb78d07f5c67a02673d8c196a2dff9cbc3829f19ad53f3b639e5b9ae35fa0a9364ec9e418503066360154bd5b5ba909330ec96cd0f3a86cd0da1b40e7d324bcc0edfe00fb46fc2510f33fb8c707e4d5773cfda14301f12802391da996055909e92249bec10cf86b15fd7f516ee59f7dfa50b3c79c29f803d546cece5ca93cc6a82c15f75b2109be02865ad1ef18272264a3034fc068ef9c03307fbb531a6889ffd350d2e6d2337a33409f2bea025ef69022626ca4188ec1036907a66408ea506c3e7102d4e92f25f8819d55246d8ab1c80d3772e9dbc94c143a9f8ba1734bcc48d6a0767292b35df342226a51f78708da20fa7a708c889dc5dc80a72903a1a4552d65c261110b156d1cc42d9adaa36e2f00cb2fd48104fe04cabe231129f1e87d72128d700815cdb95baf28d1342e48409f73054928a613721ca0d3010558fed8d07e02fba96cdcf8c41cf4c49c5578e2fe72064e40a7a4adacd6ceed5f6ca5989036655a15d6a8c919e2053eba13d14fad9ff2e0932a0088676e0c5635c0c431cb41608d96e3c63f2e1b9cecdfffd5296ce1f037e377b087dc7a396ba5717e94cf7a0b145b65e7f45e287043f5295ff626abb6df7e0749191d04807b65f29399a8c9c7b243b780226dee2b80a843035cf9ac71dbf67b97d45d664e4856a3cbaf3484b2b4a36e67e5f1d4db7c424900c283682c4ffc967ed7d96d330b5853cb5fcee478f071034a4292e64070ab538120cd9f16f26b44342deb9e2ef3d503761d8c4188c9940cbd7df10db32d32c11971d534c35e2f03d21e3449f7f9901bf620a54157f6075d885ebcb0fc11e593649ea21d1e8fefd6ff92ab9e1ad9f766501d1286e4baef840edab928475e841c7466a2e7f72cd046979efc2bc01ac46f2ed027bffbc5a11fc19003de67ab6111cd821031d0c4b3329961109b82afd6157d11856bdb6e91508d4e26c6c5fbe069b568051b9cb55e03f78289bd179705e81dc4558c9b7b712d40cf415cc5b8d98bfb02f448e23ea3381d5c16b1b4c03ff02e2911610d6eb3c6c16fd1658031988f94dd4aa60bf7218563f26eac08e9792541ac0895ea71e7033d88dc9b724b4ef500a4034523817367db63ba4bf4cbfd360f99d004bcb7503a580c246c1f55be45be15d782cc23a01cb737d3aae65d6287b7bfc3f0e848e216de472e6721849361fa826b6d2c38cfe750802170d7db926b963705031a2226e7a4f796ecd6daeb796d2c8c96fadc5fe4cb334978716ea948d9dcbf5b4e2c0e967db2be42b45e32890b8cc60ee6cc0aa4445f6c92712595089bb1927e8221fc26669ca9b72a976f2b02363a4caf1c9123114869c0dbab1e90142d17b59845006b787ff35254cf664acb83513ab777cda397a0fc5852e56747fb442261f7108c8a680db2bae66ccb6af1e54cf48a757c82ea101cdbc67ccc4eddae547ddead67468f520d5a1f7ec4ce2d95e3c401cd9dd1aa16c4cb42e8aaeaf23227100f6e0f04f5302697b120285025985a1a91abd5598b65db31185583517450bfe2493ead06ac1eae64d6379132c6fe3ab7051871076c3b0509ce4b683ffa2c86acc843573da5594b4f01e79a5ef9f5a1efde93f594fd37ee1eba18d32c21b6ba318921e1307ecaf3cb7e6f6185ea4cb7e56e875e9bd0bf2aff4aef39535008a81a89735c65c1bef113ebb4f3698e4e37e79cb094feb4fda73b13b021e9f8af229fff4c1bd049c99785efbf97e0f8fb5b77cbef7aa2febfcf0a433836c99ea4cf1eb210d3603775038ac90f00601d3635b67fbeece9df095d49e02bc663e642758c28d62639cbdf7e5c122812353dffddcc90c4ded4acfd9115cd6033b6569d74da7109941aa6b9d841ec11b8d7ffe40f98462dfa66a35e029da5d09951ef11f5ab016f7a5ae8d9e623bf0fe802412c274cd4695babee9e489bcaeddc7caec9aeb1f0acc2c055a7863f93cacda70848ac5f8ef62095f56d54211451b55beada8722d745752152b205b848141cc8230f3097cc769e84c88c66a3a120a0f924cf2dc0701ed0d4a060b9c839fcedb5e765c129dca04e747f0ff33e44842113ad8731d4136a53a887dcce0accb0a95815693c2a06947aa913202922eab237458320df8b84b1690daae4b05883e20de3c3ed8d7e000b9a8f46bdbb413bfa429d8d8d41dca95b626a58cf0e899699c605f7d926c3def34e4baa373f9c64697dd6d2334248057f62a280ff82cad72bae9046aa3c2cfda29daeeeaba0c66e866c0669f4b5a6d811442abc579719ff865b2bb11591b6a6547b3e932f4e8e094051cd91059f95bf9c043130e722c40e45f46758dafd38e845751b0420730b36ccce914f17b43320031f2ee2255af205215b8a01f8fdc306d829e0b7951fbc52ce79772ba147b2f0596831b21e5231f8fa67dfe224a05093f266ffecd7a503f844371648527364df30fdb0892e5da63e635ad11e3607518de18fa9ee317ac0fa62f2705cd7250c36742c51acaa5fe08a6e933957265f038df98fe8f66c001dd8594351c6e87ccbd7565030321a18035186260f10c8d436925ddd76656faa0def02e946fbe93ab516eb0f9ec8d7a262cb3c5384ab2ca22f55f9cda59510707223e3e318550ce1c208727861272eaa05628582712450aa85b471edf9059c7251bef6be235ae509de9868f2c92b43cde188b61de82a585826f6b2d23543fe2bd496da6efd9163875c49aee285d18729de1e0ecef36160291f2756bbfedf5d87d59f00daacea958c499c6698a7afd83b76403701942321eab9197ebe8fdcd17768f53ef0b28f9fbfc7d43e0cd06a496dde5fc5adb8357d021d2f77e60f93ab6df796f2eb32367fe0693d3c7ebff9560eb5e59bdc3fee7929da804291b1c326ce758611c7b9023f6511c3c6e95686ab62affea3e867ec8b42bb689d45d50d94146ad8ff9fcf1db6499b867e2549aa903e8c5122ed2255db027b84a18255a9eca07f09d03cb6344af1a511c0b9d4517265ef60f20140950ef150e659840b6eba4642f25c9640308706169081530bc2343f62ae5a0f86745be1cf8a536324c7a562873a587605537bfb2949e740955f832b8faf3ebead64734891bab3d47f9a075377bb248658c17a0102fc81fe7de86371a5c64dd01f066dfc0a7d0c9114dbdada67cb137062f5d088ebc3ddb90c794afaae316c51bd4ac3421a4841097575405867861a55ed0e443fe98acbe9327158c8d289c69a0c0ac8ec4795fb3cd09ec3511292729c6e624905a51776ef01a563a49a99e13c1631cddd7872502f2cb796d8d694e93c4543d63a0936713a246172380ce4b606295d5c7e19e4839096bc33bcb9c33dd1a159014c74b6a13cef532a7c06eebca6735ef5d46c43748a68fae31adb52485f33fe14a4b2958910b4a273079966426971051464c81ff43d3ab8b670abc75bc5d181fff626dd733914b515a2db416ffbf06d954c2a2e782c629efe81389c49a5bf029786347565d625783dc95833ac13302435612eba71c04fde9067553fd53af2722e5a619d2867e578da745e6a330789ff8aefa2521ab0324bfb6f3d2b8d841bc7e68e26bcfef7b8b5be68a15f857d0c6c09f4eefcc568fa68560746c1cc6cb445f22f6f4711a89dc0e229ed3fd189575c479f04539be8cc8ce4d4b9bce199e1a4f0aceec2954691cb816773453a722a9aac75081a1b64417049591c9a20bade1b51dac12557bc487081117840de0294b484379140276ba191a6c00af0d5abd127be7a79379bb80f2382eb83c705f1ac02124a75da8226961e3555f581e94c9dc9cf07dd720e7d4cecc60b158c91a3d8e1e0271caed73bf3560d07b2e4aec564e7eab7dfee158a77ef23f2ef7bac3e8a521acd65c2db712cf55c579157ca0d50ee51d822f0baa99bdbbd6359c0ffc49da000728dd49eebd2905c345bdb05d5a2d8903068e457308bbd95383d357195d98e712909c48086043f63df24e79128d8d631a6f5ada891cf125e6e402d41577a081d7641db81454f8268b03c70d2a38b6bd895c4c92a5cf45db6db25619880f387a52115148ba1c88722a76d11fa80665d65a905ad519bf69a749022ddcaa61a62ad623aac1548cee8f9e2daf5df3a3021ea52bfd234d50394738c521966d69e2e9da408aeeccfac7b00427b28ce2179b899cba7165e69156a0f801e89b2534ca5c95340b183c4f32176b77673b6a177b638d7e08f229c030a7f31817fd7414b34a093a4d7bd6c4cf8b05a9ed091e6129e66ea217a007378876faafb2adb2f78cbcdb144ff661aef32eb1400eb13f1499fd88b2ec35ee0f2ae5db114e9789056de4dd663af489cb6d921e5293a26f289f665d4609f3020bc2a040d034f495a12139d4e035bd33e051a7b544640528e5a548f2f52ca58e8801cbb1ddd510505677c524747f4d65c50a05250e3d69b49979a08a1b35f8a765247dbfdadd84339440f2178ae6dc46b9a089431d4013b9298c270a00c9a78599e97ad8ab1a39ba3e3c45d9631bc629cefba0df5d5f926113d30cb07b8112c854796a274b94d616e091acafb38f1ace20a9a3272d2019b1652f8e2065faca35bf88972f022e6d4cf04840f41ad7f80cd10a4b5365211edd61d5cbd34ce4079133c75c397ede2d43330454ecd6e526e301775792e8d6deffc59662352757f1d454d7223eec5fcb617cf523ea301f35c3694cd6d49e374e9eede901841ef8d87f118b57e2595d0a31fc40ac5c946a7314611fd65e3686450d8995a9bf32d6d2ad1bd18a15eeb89217d5ab0e81b484d15bd85d397f0b8b39474f54fb49deef37b389acfd984f60443100e4a1491135b1a7e5edd6f5845412d752535333d1536f42c0d578cfa53976bac433ae28c51d2a0f04c4b153ed763fd3e88fd1f1f27d2abe24a682d3b46151aace5cab83d996142d219fa5ff0699a5a137ca0088dd4c5f325c2eac80038590748924cd1d68befd8609625a8ca19a0ceb5680a37bc7f186b8a20f6d48088d1b53fd40554db9196db1aaf75b1530a1f90a1e0e3d2a15bfc11fd2c844d62b849e2c0da5cb09f4c970c98f4458cb57911c8c9268865a0da290e1cb075b8420e73a88a46a9157ef79a5957826c513ddaf57210ad0ccd0bac65dcc0ad39322cb62b065804d9c5f0c7426166d6c9a483f67f746162eb96f3c0ead5d492c51954a33ec5ab00699fd6260c2124f8276814555efe7e223849320e862862fa54776c2f8e7a130992f3943429964229aae23312b01a13aa90cbc30f621681ba912800d731b182ed234fba29897b8a4bdba2b2ac431c8a9d47b69c74c11b126d12abfec145e02d9cedb1559e87b0108010062fb7ad9a81ab92344d5d7defc194304d80680e19ea087cb29fa16ed7c94eb32cfb34d3661c025e5e3612c46f0458523a99ddc8ff888120b30624bb2f6811602ef08b759404e4139fe8ec5f11fae95e8eff74119a56b2e2580e23fc21ff980d3969356b22173806c462759194a11b3c3d874f50ad6c48d9ccd6cbea5290a48101b5227ad4701d50cb691e16a463fccf22561c87bde20ec2636b352f0883756a22087c18ce34fecceda57c4739e9ce9e9b3f822e8519e56a4d815aa05cef58e7ca018794e6fd5d187b9016c5f49b609b104e5bc8a403449cd6e81411f86dea49b2cb0f931dcd387097f96608ddb25e590884663195adfd2b896eabcfa24b44d34fd14c660a13dd9baad3f8975c8c0a3c60c0b9e2b2a0db570b1e8c3152e9710d268d2bd6012ce55ecc0bd5dc6b1247ac82043ef3dd9819f9ef6febd8f2a03d87b1640e977c27666e8bfd7246a7874c86d67328e4eae887ea474d7834f9605e257995760f382f21c3ed009550d088a67c2c55e6a64a76d2d9a06f5d7d0d6d0b7cefced1ef61bf1bd7b16366a32eee4609bbb1caaf9239ac971b227b49b698c9a16265d9137081ca13e93bf5cbed9570ace297e130a2d543f8fb5bace9000fd96a2fd1f2f67958fbf6fc1a47eb1430c034751f370dd3e90bea4825489572c64525dedcd8a3fb7fe2077e11bae4fb60b7f9c7a0a8bf4b22b59594c77932de0bac2381ec5666b6a6bcce582dd35361374a5effa88e43094f62eabea099315d248e02a6c30ecb454cf130f2e8e6080e6dc06bd396e3566742434f367a82e600a10e8200bc9f07d1f037ed09bea8ee76d912b3befc39c49898b53c4deed90f4c006b5aabc82781c39071bb6c9ec0dfc5754a41bed593e38b91c62a26f7d8ac17e8c0471f038ff6cd1e996c2ad78d58ee8b896f3133c1a4c778e56b7a28ea176856b739238f5ced894fa1339f6dba1a74375026ce78d8c5c83a8dfdd1399a7e35a0b9ade2b9b4e8fc080498f622ff26c98935bc5ead67681b7b0929c2977062b81ae00409db6dd4c3d0c71f15033fab7278a6935f25c67c42accc65c30dba1239fe012473b98b3f170509ccd8182ed4ee993085d91c1ebdd87b8d3674da7f016a40806bc2edafbfa7e248c4ed617f797a8cf88e2973cee970293e170974a5ebb18efd7c29d531c9fbd53d52635d5b50d18419cc82a9f6e3e1230bfbcc455128af81daba1f79b15f8d7e160d276670869b7d6f40f89f065d7a42d59b83e68432e220815647c68b86045ffc47fe4bbc48e97730a58fa1f02c8a5228a46c5d320bc2a5ea17db7fd8a8a8ead05c42ef5388d6aea5269521500d4ad5e143bb649ece3810c16d8bec78c903f4ca5f49475b0983acce0cd1fe762114973b038781a73257ab20ec10b3df8377711536d425244fc121f4fb0a5cefe4f907b8ba459a88521d2e4bc09e5d44a7c73c0a4e431f8ac230798f03a4e540f4f16320ce640ff5d8d9e31801514aaab50fc48081df01c71b89d72eddee7fcc3fcd61d6b3f7c3be1bab9f1e5d9ed45537601f57edc7088de8ed029eae5d89115b981d7ed5015a812e6e4db3e89289611beae7b91fb77b93b15429ab5eb6eb9fc1ce9f0ef28581a197ceac0b97b532b8a48f1814caef3603334d7ebc31da293d760c7c2438468274e8585bb86c42b1f64c7f829b6eb337cff3a016994f04145867261071ce89a2bbb4e88350cb0d8d7271e296e65e4c8adaf5764a580aaf36136f2e9fabffa39bf74cf568a083107b85a544ea04fb94c8106cd075bb0c5aca62fdacff9cf1b9d40b40817b3cf77ed157d6f66b866e3f471ccbaa141cc8bc2a0ea79167aca9180e8d0beabec4a6137ae78e3f622f088f451fd316aeb074234eb567a560ddce56083fb4365993de2174062394438edd07e1d5b4fe879b6bcda250ec90201930f567ab0a33957c6c4d50c169eb1e3ba75c4d2bd2ab37f698f97410a8440135025490c3ee7826ac269bd9dc1cb75d23ddf3b7ee967b6dc5a0d9c68c9340e74c1507c8a906a7008da0548d1fb8a48652e4df4084aa392b9038ae23a724741f2459c2f6e51c2eca3eb5fe07aef355666d37bdc8d752158ad4096a7c20c3fce9e2f8eaa0a4d4385adfa1e950014a75681144eca53202608baab1952070c378c6eb275c9a43d2232e3d58ed353391608df785f1c4c15492b24b57fecd362d03c749e3244d6721b4968c82fc32606d06b65a816192e13d49609973fb4fc9e21f2ec7e393438e8366108fa2842250d795f99b5e46bd1f28258b7b639cf95710fdbebe8cbedc15477d07090489fa3e3df4e1a21e1a3c6485b240c262023004d7a359bcb248eee241707a20cd6b7f29ce9cc2202b917a027e955dc3317857d53b54713943ec9936530a95087ab055f9f02c38a751acb3a26fd4c17ea0ec9be458bff5a5ef551673b154560e2c209d3fbdec25767a979a0b696dde502fa6ebaf87c91602664931ce87b2bd61d755b3226bcae888dcc92429837293ace95f6606295a1e713972fbe7c787e901cb4cd9e3f68114c4cb9fbb2ac16e729af48a8b00c508c7c8972b07832faba543c2f77b6299224106e12058a942128a39e8d395f990e1341ebe193fb11b014dc6d459090ad5bcd3320b3bd5def9abadef8430607f6bcb231d22ee6165026e4b6b9b2bd0574f06634c5c61e6d5662dcf3860c0bc5fa307a4916cc26ce8843aa423c386dd1a3f0087e385c9c46198f00dea0f1b18e8a85f5f75dadfe03e8aca7e13b094c2045e9ae3ec95297c072bc383d8c7e48d07485a5d07023a3d76b00960866f50fb80f1710b4fb6b02da84bca9811137cba5daf270a7b1ab528ff05212314ae6309bd3b090607cc3a99dd4e15cb096d9870304ee060b93bbe3f5d91c3de21a29515a64aa6309d5632d8fab9553b2d1e004b2abb134b53b4d166ac5bd32c321efaadf20c7edd2c2410a99cf6e36395731df9dab371386f460708f307544be5e996989d92aedff4d3f0b1fa81d25146ec45fcbe9fbfab023aade4c1bbcf39654a08d5720191c62c898b78ff54d64cda898f0d076c1cbdbc9b6f74ce178b8430cc0bfa00ee9b1a8af07e2174073016746b2b8407b193ec736b1eb36f5acacd74d10f2b45032a0dc2d59a75133c2b309868faa2fe41fa5f19b3a45f261044619a061830e579e3da649d913d64bf4ede981abab5e0abe7b8a11cfed72a69e9ee6b55e3ff8953c129270bebd46c13b32ade1e0319c9d88a37a3b3d613011241cd00e12878135a12decc8904c8d3c8a46371ad96c99d03773e9b228d569c144abcfc398708431a9242a0143be96d720e85980045ac85915a916040908a9be54b241359760420911a8e19df39e6285e4d0687cef18df1095c7d58b6e16a545b421ed1ffe8fd2041b33a9316d4a49c43b9e542bf392316e4f469c02ccf3325190da3a4975f22a452af7258c63361a05fecd94830f277897cb950c4cac5c4112f279f77234eb569e7977c0b7cce4ad498b53c1577e06059e7217ea200953a74d618bd2c51ff06fa1137cb1002cc36c72c0a9584d7e2f934df610c8a3986ca1cbb3caf4702d43c59c2bb1a3ce4feab069e9767ef8db50acab5b3d371f2e6af8637e37e48e25e4cd9ea044ce0052ea7064717591038c98e7355d63b46e97cbbbbddf79f5b82527ba9d50d898194ebffb16334fcd5524e99fe3f668d94ce6f7f22dad1420383b52fbb2bb722238ffe500d7a50d17ee4d95c7e505135f21951fa9a02eb297ca0dbdc5b371192029d18fc16a01758a72a514df1eeb80f59dd7b26650eb8e101c2444498c7061361fc03f73637a0071e7660800e1f9c3daabc5c75834d2e99151c60881608288a2438325f30c38d2656f0410a1c3a10992558c2c7860c31a0f003ce664a294030061d0f8eb2a48063de3004cd14434c1e9ec8e1619eb075c4e48192052851420e73c8830d26c10fc81637e40c93aa8a13062f688801460612c60402c3690315295081e7867499988a06579c385831c1f9c2849db04301ae98c0901832d8a25c8105884d4d0bb0e1e8b4a2a4e2050c4b4860c3028e88a628279003093eb0432245040ee0440943145024e0840b1aecdc9628457852c3881600a0d9419144094c027b0086102031de5044d9d4e40b2d6c6451838b22889287024e0cb1e3a540080ff850d6e0e288175c053c4900121ec82f6e8081085b1343287060037902132425e0020880d2932206520306f0e1039218b80025022d903c4cf9d91931e5004982a040ae60c2111356380283114430218b3ef0a6a0e1f8c44c710989240b1723007cf820ab844e1ad5c02a00012f5c5124b2923d4a40b620cd6048001590312b38a93838e0a8e2ea3f8b2292e8808191968e17feab90a081960264b0836ee2ff02514ca0855098d2430e35b000ad81678922bce8f1df2401503d3ab0f1420dd23fcb0408846cd821055bc2ff5d0a20f47800002a4032fc1792e282070080448c4604fe77882064c888a5051726ff660fc61518c1c30f26cb952b4bdc7066f1400c43bec812810f50c0c655143734ce16591080421049b8eca826495891058420a86849579865b08229b2a0600440025990f01b88e144161d0378f04080ca5708c112596a5320398bf0f103082c892c331020248a23a80020041e8a0803061d88c20195e6e199401061403180162cb00c214323cb87308aa8c0d1908514728041091ec2d0018b0e3d259af40f5ab0218c147080e20209f8818a1f5288218c0e050c8a3c8637205ca085308c1ce0a904145400a2032a14c210824410597c360cecec9884c141007ebdd7ba84c8094bc2904940023de4c0802c5b3f7430aed0220a2c2c9820032ee86005830905ec00bc8ae995808b140c209ae061e5f1c1ef062648c080c24256023c60010e9038000f8c128c78e2a8470621e800104d60643199b2041420384208902330a2202014f4c2c70f040a4004c6cf1536d9131b3e78a0c206060e282628d101178670610b1c307e04bd040e7030c24d033cbe40819303a8600b2d3d81caf1050788385b0072f2a22a68c6170f188148c631c9043c6005f3c5011a90844e8521c61d9bc5f505005410434d7183169cc0812fbec83268f190420f382021812dbe480a8114121b1eaa1748b0e20b1c0250d1a00727217c4134c5173321aa54b8029725021827bce0224bf1015f08118413504b78e1c40ec3306c68e0852336f0ff1f46125e60000519286106c900090a124822a9a535f8279962c4c0bc9032928cc13f0c30a0e4773c9d92eea8a7a4dbf5ae704e384811beb169f55a03bebfa3cdefe5c61b1bcd6edee36aedc6264d732fd559a816a2b5dee6e23a243e7f5bf53db1ef777011ee6d666b29776bed0e6637d5390675cf6ee73aa84e7bfa0a7cedbae839718507b66859e0c496131ae8822a089b2c340caeb0910415978266e1c520320a81111d348078f47004304a0710d06a99304015192588b4c32c13441d2183864e00aa902001ae102108c09127b525e4530a34e8c0c4c127841b4174204a098a7039d11202255e60c5067d0a1d191a4260985020c0a5668022f267a0cc140881c1162558800b2c688558900e81a501e96a410e8b3b52020f5788b08109596c0cfc177f5af8971510f1244fceff0e265b6fc60cf97fc2ff312aff3fa504f2c206fef58213c8180de971a6e453d38e17f4bc5760efa8a63aecdb6a77a33b384811ce7dd5a9fe67775a52cdba1bb866161fe9a08274fe9f68c7cea36eae3dea66d4c50555a3bd79a88b13eae1d13c1bfd7fce9adf8ee65477540f8d485d0daa47c73e649138eae290fa7eeafb88c7c3ffd74e1d3974a8a063ebffc6c6d52a50edad4e751dd5583fa81cfe9ff7a78e1c43b59d9c54dd399db77b8669cece1c2dc428ff6ffecbcf61138395ff4f9e38a8fc3f99f3ffb84ff2270e340325de84bdfedf84fdb801c6e7f4b4dda8e63eff557fde18f2acdad3751f737abb3db992463be40d1fffe40ed2858b2b78fc3f05aa66a466986694668efe9853f73de694bbc79c72dd1e73ca8f396d400f41fcf0ffb03f6d40e0b4e18006fc3f69a3871d6ce870dab0c10694ff77f56fbbfac7eadef97bd4ab2a448f6e7edda39bdf187efc3f0cff020194902ffbf4cd2bdfe3244d80f23246439e1c60ebfffff58213e0f87fa81abe219b3b37aaed8b3376374e350d2cfe5f07dbecdafc49438a10ed99c5eb4fe57c0ff16eff1fe74f1a286856ed386d33d63da758bf5a2a100b83ef6e35eebbc55ca5f99386efffb9ab3b9add2c44b18a79abe6de6e14d31802dc386d35d6eedb33abdde149c3e63fd8aaab9add7ed2f860abba9de35477770f872f6f5fec6e9ce61fe9c2ff17f973460bffafd38d62bdfeb210cdda6d5f9c6a57f756e3db3f80b6c4a75a732070bf84f8fffc27edf79a55bbee394db5cf7d8ff00fac5995a77b3ed244353ff97ee9cf03241e203152c5abe2453d453d352d190d1932e43ffd6d6d6d6df93cd8daf200c9d6d6d69691abadadabaaadad2aded6d6d6d654d4d656d4d3d6d6d6561391ad2d224b46465b5b4386fc3f07ff0f847940ce39fb7c3e5fafd7eb79e081071e2449922409122448901c3972e4881123468c142952a4c8d5d5d5959595955555555515151515158fc7e3ed76bbddd4d4d4949494945454545414141414d4d3d3d39393939353535353131313131311224488e8969696969494949492929292909090908e8e8e8e72b95ccec8c8c80887c3e1860c193244881021428a8a8a8a820409128488888808081020406eb7db6d686868484848482828282808080808e8e7e7e7c766b3d97c7c7c7c7a7a7a7a7876767676747474746ab55a2d27272707070707e7c78f1f3f7cf8f0e1e3e6e6e6c6c6c6c6a6478f1e3d3ae8a0830e38e080030e78f0e0c163830d36d8a0a6a6a68686868606638c35d040030d76ecd8b143870e1d3a72e4c89103070e1c3832c820830c6eccccccccd8b061c3468d1a356ad0a04183c68c193366d068349a0c193264cc66b3d9799ea78c8c8c4c8c183162c4c4c4c4c0c0c0c0bcbcbcbcc86432998b8b8b4b4b4b4b4b2c168bc1603098cbe5324d932449f263b8bcbcc85c6031302fa44c8c1853e622f3827991c562c4c0942e32315c4fe274bb9f7cb8dd6a1f422df97f0ffe6c9962cdadab7babea68a29a5b9c8eff0feaa0e5aacd283766160721c2adcae25baa573503797ef286ed9fe411fd93523bfe491194fe491386fe5f043dfe9f03ecff1ff933e67beed63477f350c7d653b3d5767276bb5d21cafbff9aa5ff96e8dfddf9ef3cfe776233ff4624270c4bccf5ff484e1896ff9adff3ff8ffa136680ffa9abbb7ff9ff69fcd3fe5ff7ef9ab94c19ffe7ffcbfc7f8c872163f8ffa93f5fc6f3d55f55f08da7edbb7f18b8717f37debdf7ff2f2effdcadd96a3c395cf7230e428483ad9a6eb44512f660ab9b5275cdc4564726fdbfd59f2e2c9ebb3577a70654e3c9e9a84f0fcf8e4e2d07e7878f1b9b1e1d70c063831a9a2c59821001b90d090501fdd88464c992a528cbffcbfe3f03ff4ff5a77902776b3adda84e796a3e3cb59d1c1b90e6f9d7df61abe256c53cab7d8528066eecea1ffbb6797dd135a3b8d5c222866a29a2f1a739f35d5d871cfb7af69da515ff6bdec1c69f250fff3fe3cff2c90771356fd5ff8ff97f8d50aedcada59bd54135f12ca36eff5fe3cf92c7ffb77ac54458ff70babe5bc8f10de6aa0d36eab455b1266e56bbbd612ef2ffeff927abfeffc69fa417dcada1ed915f60882bfe3fa6df3513b1cf75917cb8cdb8ddd8776333cc6eb17d6fb7bebe5c4ff970aad735a3ff8fffcbf4ff67fe245be06eadb340d8ff935fbebb5d57e336e354b7eedbb58bdbadf6dc5bcdea75c8aab8abd9ed38d8aabd67d6dd409ccb98ffcff127d9f2ffb33f491eff5fdc2bd0d5c48d8f5d45f330a3dcada19ad82b6617ddeb9a758e6e767feafaff2fd3f5ffa510264c4840024a2e36a4f07043012496443d21040fa8842d05302b920d0d0a84a8d08a2db5183cb1e26915800d2e42353709e0a142bb31809a39e4473c8460352941012d21f8ff2032fe5d02f8dfe0ffa9f87f237ffeebb95bebf1d1a8ba72a30ad4e9c0cd7b6a42b59d1caeb38e4f8f10aa877ee9d0500f108a6a9e1c76a3b5df2bec6a500775b9ced1ed5c0d6a576707dd8ceaac19ddab8ecb5f1d77bb2e920c1eacbcbc94ad2ddc9b332a204293264c9ab86a4cb0b160c912104a6c621048ecc24b7ae0c5300c2f61d2041bbd782ef8854168c132fc354b4cc046af9a2520c0b0aca6093632b14b0d082d354db011895f38560302ace65563e2c720c0c8f6c5b6029b0a5acca0d2a8a4318134814913135c353d6809c19958eba5e04c3ca4b49a39ff348362684afc429246256ea9d98281c12e3199eb63a44a170d131786c124cd072e982c5d625c2e3426083132b18c864913d2c8c426083172e18fc121e5c23198676218fc42f346313158f6829b9046241318fcf2462e4c60700c26693e9061d2a5e6831e78324ce20f5e30cc49f3660c8ea4188665c56a16702c31ac660147130bc1b970cb1bbdd03079c12d344c62c8989a2d139398ac61f201082696d56c994c9a60a3186cc61839b7b6b6b68c4c1c43f30108267ea9d932712965f2cc5246d384349261179a26a4910b7ea16162821023196e421abde097922606933430d88c41c221e5c231d8888961700b0d1317ab108c626a3ec01fc8683e78799199d08396101c0c9346b62c4eadcf8283d5642de058e2051ca34a172e31cfc4246e898972e18f8932318655c086c5e9c2e68b24895e6c5664bdb0aba6e63fe7433049a697d7325f6b0b9311442871e9ba911270b95c2e92245f5a704c6b09966b09b1ec267ee121e6cb7c2d211202ae2556e3a2c97ad5682dc1b9c060b8c6c42a3199d5f22e97699a2ed3e572b94cf33119c324832bf1932f1d5ebec426560b76c1258dd6bfce74bb0bc36a882586e1978b466b069755d6e064355a4b96485c0b960b93355a4b70257e99353093c426cd63578d964932c9e0caf2023c6038b178e04aec2263b8c7b5e87062c172206b604e264e2c1b1b1b1b9b7205371e3f0f54781802838087281bd8e0cc5859b3e34969033523868b0db21c42a3460d583983062b04a419356acc40a2316306b64143cea03133f39a79cdbc6a6668606862332bf8f5382458b32d70666963ceac5899612163cbf4c009c3002b48980e9c484833353b9ecca0e1a280b3059bf84507163388347ad998a979bd666ab462382c1d5f94363b7460296dcc2733d87489d1c53056d406ce9995b79283e6cd1b1a1e3566d0a8c1b29103cec42d3ab0cc60590c52895faff255beca1a1297361838b174e8c0b2a3490954c2502881604e9e9440387024568967de15a306eb0507ce81b17460b141c5061532070e1c8bc562317c63268a8e26240e5e0e8c0307ceb124c74c1417b691c3df4a33280736cf9336a3e1190e1b3ea470c2e01c58aee0cc1a2b2f5807161d5fecd8dac144c71553c795a5a62813470e1c2b5f346660367c2881b0de460e3678b011854a8d297f2bf1cccc4a0944039b7836c5eccacc0a1d4da8e04c1d58a2e0cc17cef1aac1218503e7c03c1c3847cd921e5e78490e8c4307c68171d42cc18175ccc4c0583a9ad498f239a60cc6d28165666536c5eccacc8ad2c62473d0e028310d0ea91c5807c651d6f072601d38783b300ebc03e3c0b01c76e868c1396870b4c468d0b841f3c21f43636666668606abc435ca174d08b8b246cd526963c66a9a4a1b73f6c3e7983807cd4c8a7963621c342f58ccaeccacd07096786605b703e3c0582d3930d6a90363cde0669833f00e1a1d34396870d0bcd9426306d3c0356ad480c16aa6d86a385fb865666686c6c68c0d1af84503c768e021660d1a2df83505eb85840c1aac971513cf66566656b0ce1831332b3813c3d060d9f00167e2171d58b09466d0927963c66a5c5f96ae182f3ca484bd6a1e06d764e20da4cc941b50215bb00c2e2106c7f8a00717fc010c96c1b0181c830783656a78b0d265e3c08905f3ba62d660b95e6ab46234582f34b61ace182eb18b0b86c94270e118cd10e7c2434c2a2ee58b07274ad0f47558dab866aecc6099a91244831f9f343430e50d9ed1e2fb293ba01c7162c988e22a3dae658a8c28244c4a0636b0c4b01e8b8c2836b0d8c062038b0d2c36b064009302a302b302930293022ba29402ab02a3c16a99a902f359318305aeac495d32d8158374e216fc5283f5c29886a4c1e60e12d3608c793418634c5343836bca16dccc0cfe18c63271376ee017cc0e5b0ae70ccc01e621036f1065c7941208268912c8dcb1044c0a0decc234a4c0f852210fec825bcc200eb04be9027381c12e2676c1641045535c300f2510d65bd90165870d3b72288134c0ae1a588794bf95d8069ea9e2c48c95294a20197661d9c08273c98802438343302a31a6c13c8c6938c09887310da6a959c203e39a108c4a171ab306c67a2c3630d68e293355669ca099b132334569e3d2c02461585c31514c38c03cf08b2d89130b86c57585f106f88a06d7e00f7ae0f1c035f8030e6a70c0f00618e30d70c9a306875923b501c61807ac86b741cd9b37650dc6c1c334b8a6c6c50586062b841d3430fc3130a669c2b00b4c29045ce92b6d5c349f4aa991414323c3898c03e70ccb706206d1601796d104e881c0b08e1c38f0bfe00c645830524c25702faf0ee05ecc580c528c4c5633c556c30953f2c3897389813fa6346942c09531602e5fdad4d8b6c022fb320696125c896964b00e9a1c3458305cac464a0b2e831a18293817be4183f542628606eb65c5060dd6598306cb95021a34583368b076f08075e264d0ec9802b3cac0b03869646860569436569436ae2ba58dabdc41c3dfb8f0073e4002123cd64c959a97e2c4825dc1b93079c50c72b9b0b02971623d96d74c951d505e62481951cc1b172ea7c88862069533333833ca0e1a607024ac660794cf71613d16b209f9c465741997905b2550894db3c646e505ebad6ce0c49866a6ca145c0bc61296362edc69687640316f5c18efc801e7d221e5735c184b46149c0b63cd54c1b9b00c2932a8e064447161988c28327c28817e905184d982b1ca9a9a9286fc9cb2243fa72c67905fbe2b06cc45fe93a42b060c0f2971b0b4c48287931c6507365879bdfc60de98980a15f385c5bfb09041f3a2f2f22f8f1413a324c330d7cb5e686fdef064d4bca89837af181aac107031250dd66b8aad86b3c452f203d6898b815d3432f86348d7fa9a021365888379c130342ea5cdeb3525c9e5c2e285e585050d678961388667e016192d334a9a970bd66b0acce9b22213616605c3c0349989802bf10c26075c8961606060609ac45eac3489c562313246fe808b61324a2cf6b8980cbf6cfd8dc42f58cb0f2f380423f205c3c060989a253038c63469609894d560bd88802b3199c313d813580c250c0acc86d206f6e4c5cacb95172c5eb0b85c2d2d2de40b16028e5c5f53702f9897590c062f36254ee112d64f2149db94130b0647da3470c29464165c0c8ad385cd58cdcbc5c56682d3854d18928d8813eba7cce420e2bc122e352d45bd13b8d28ab9530299402e6cda702517a50c8bf30733a8458a39055752c195af2955708f5bbe0687948bcbe3252dd8a5a685275be282652f2549e29224adf8500291b802641519125440a68a0c0b1916b22d6458645f9436322c70257e4d71b990284dd3e572bd5eaf170c0683c162b1582c167ba2e58996275a9e6879a2e58996275a9e284b927c79894992810be145b634b135616bc2d684ad095b13b6266c4dd89ab035616bc2d684ad09276c25287348c19919d89038b15eca17152a55aa60b560c161450a961a58660f38737072ea307bc08b14194ece1c6a60799152038bcc0ad992438a6d03270cc732784d318362b8acb169713ef91cf3c44283c60970a679629942c3cae7982f51b0e0cc269f43bea6d048295150749a3ef3a6c4c3d2a604e238570d960a33c4097124ce004b09141c240e01a723b19084808b2599b8184652da947846d66253e274f10dcb12f31617a2d266a6c49ac19ac19533a54d69be50c1b9d06011e14a01e060a04c8121ad98266ae217120fe43363b097f97ad1e0d099588f5f18c703a68993d284a18179a17982838162fa4a2018013c0a8302ae84c9410a9624982630293c4c1b959324732031162c8a8c0419254e13bfbc7c10322d3197982cf6125b8ac55e2038499c8cccd294b3e5a7c082804991029342e2c80c04018bb5b8c8605260b0874931cb9794571945091363c99861a97262c98072a5451614038633b822030a0cc7d4cc9c35301950aee06440c17a2161e34a066440c1cd389165a961e5c546e534c99a580c6b8509c149e2c812f6301bb67860cdcccccccccc5ca9f901576297ab86159c6b0b57621b95d35432f1abe61cc18935abb29543953305b812bfd88a38cd1a2c181cf99aa28a0f257ca08aed03568aa698b0a2294554801842c5344df2cd182e5c62184d0c9b34a5091b42e5158364e2b22c61b017ecf57a0da9f230292f2d4f92640cd410116899598688e0a5a605c360170d964b16c3e57cc578c5d40c11c1cb0bb605630213533e3cc53cd5c353cc533c3cc53c3554cc5342c53c1554cc5340c53cf553cc53b6629ef229e6a99e629ee229e6a99d629ed2ed7e320202fea0880f781f0ca5ab56938c70755f55602fdd1a98779d6bde921b485c0f8fddd56d11cae9d633eef179313602fdd87c7a8c3ca9ce4277936ef7134a6c778e7d533d35dc6e94920fe8beab769db76a0e1ebbea6eacece4eae1bbeb9b78bb1dd1eca29bd53cdd7715969e4a3571bbc3212ed57dcd7c0fb71b85aaed7e723590b7d9e5e9f5a706db37a9b79a8824d4c3f3a63a3da5d1763fe9a3d4e8f8b3ae3894ab4e5a27f15f8fb79b673d6594c138f31d741555d7a151ffcee37623880080210d510a776b443595d2c3e7f0e2c14182601edc014eb27324f79cd6466862faa74fcabd5111aee7cdf116df1c98bbb5636f379b41cf81bbb555c8ab8c200408781280a30dfe9f0655d7a1dad797c5c15675df14bb6e46717014b85b4333cb3520e2c9280de841071cc8ff305a48184c0c087caa87f4c1f25c6829a1c1210f2f0e9c439caeea984c8af030a3bda26e5f19f8219376cbff4b196287a7c693836ae2ba6696b72c7c6be31ca76dfe7f212ec0db31fd608f4e36879aab836e5e3157f10f6bfe6654ff70c6ec7681f8873b9addfe7b39eebb6d738ebbb5dfcbd72540b0eeff202cf0b9e7b4b72a555035fa7f99f5cf2c1bb85b6bd55eba59da99b5c3dd5a9a661dce0abbeaeee09a5d6e700962617917a816991809b1251f337e9982b28a124879d300114e55b6454a6d69d5d7760aad3c0dcc8e70c8298ce1ff69d4deea760f8d1a6ba2da7350b7dcad05d534a7b76a50fde5b06fcb12917a7edacad5bdab455eea6e94ab474ab99dd14637baa78e5dd5bd97856eb6e7a7ad767a702c11a9c727b7497a7c92ecf400090013fa7fa83f7511ffaf81d8c7dbb747ccf2a57afde55663fdc39dbf2c4edbacba39479d15c413dc6b9453c7d000bde3a3618ca450fe7d6a3d3cb59d9cb6b8dd9f906761ba6429ddafd9bdd3ed7ee26d60abeb3c37a95d6d754ad435b76a12d2711d0e719a676114ef762b4af570a8ba9ddf589e8b44a40fbf253aaa5d77a3b8ef96630c5431e62ad6421e06e2ebb9bbe74bb590abad0ac4ae4e57f535e26e8d7795555706fc3fa9c3546fc8359bdbdced46ecf1798b5c1dc57bae1e1a33ebaeb9efde3366b688c8985954e5adea76a3ee699e7f453d3e2f91aba38c99dd2cafcdc0ff541775830ded56b9ababb85b13f22c14f22cf431f9efee1672bc77c737cd5d4dd42efeb377c2d76ab51e5daf383d6b3788fb7ec2358ed72cec6a11075b356ddfdbaa897aeddd524d7435d7535abb492857d9db8db73a6bf7db8dbf3df79d46dbbc66a317a0d3032b403c18fe77aedb9eabbbda63b70beca17ac875504df4c04a4747c8b3b07d6fb7db4db36a6f5f37090e496c48e2e47df8e6c3bd0f5fd7ddb9ff8792800d6c754777f79cb6d969cd7a08b566d6dd4fb75b4fb3d905f2638ee2bac87e4a22c48f394a6b608f1ff390f3bce69018200618fe5bbdf65abdf674d7eb90dde89a51b5dd6d46dbfde494aa50ffff42aaee54850ab6aaab5317aaeb1d02581d35a5d3ed14ccbc60e6fdff13d305dd8fbfb6b8dbac962a9879ffaf822bd8aaad9a59edfeff013ecd3d1b4008d8a9fedf4930f7ff6f618576ab5de57bf8ff2cacf0ff69ab66b9db75917e3052442b51b7ab952851f98b79c65738a7db4d2b51b98a831061ad44e545bef87f15dafdf4ff4e52d0ecde9d45a228e204be19776c8299f784436a8282329a425242e23de974464a4fba29de0ef3907839a8a626aaa729245d928ef78474a4c3bc1c121123a8261cd2d411120f3785e444f5842494c4a342ca3d21514921ed78483b547535fb3e45e955f38cba6f9dfee0749a5579391e9566555eaa95a86b7675ab95d4aa2827a32b2bfeff087e82d2f170395d535414ee4acaff119cd325e9724851bb1cde1512ef092a7775430c57fd0a84f3eafd7f1b9ce40846e2e1aa74535137527f5e9dff59bb2458e5f0dcadb9baab6e11a8b693e3ead47cc209570cb11c9da7384810d4e55062a842f23c3807b86a8e8304c1c29a0ea6ba084f97c345e17298081b53951c9e541bd01966b655b330a70a5b9d90e7a5a222778968cdbddd4a54770b8b7ae9ee76d3aadb7b434e7473b12deea320676f3754136fb7b4f3de90e79ed39e7bbdd5bcc7e725ee61cf98d9dcf3519af5529ab570a9f7d4db5d55310db393d62ecfe869a98738cc3d1fb55bad4a75e72a7775d4babe49fbc9d5c20ec553bdcb82ea0d59d478cca84e7b6eafa7d9976b77b8ddb4c7e74dd72de4da15f65edaea217f795e8178de5ee7ae0a5cf7fe75ae1a758fafb90daabcbf50bdd5ea5045b55b7493a4872c7a85719eb2d0bd1ae59ed3dc35db635b9dabd3567329d7075b75fda9bbdb8d458dad1a545da828a9f2a5741ae20027d4063d0755626e75b476fb4f4787c7860a05f1fca43fb6ec030464f3b1a168f6497f867c8078843430037b343003519b4d07edfc75758ac4b7eba29b540753d5fde1304eaacb6e8eb221427515477bea4d8fcf8b717a7c5e1bad44e5bd54c8f3d2ed96662deca15a6c4f8b4d95384979a73f9d84ff4fc3a370ab75b1eb1fd63c6b176d557c5cf13781713661e0cf260dfcd9d401e0de6ed4516f35ffe18468cf2c579dfade69d65347b7b7486b4eb39eea7bdda5590b715b49753bd7533acd6e70489566bd846a3969b1475a89bad3af7ea58468cf43ae1eb5ba21eb2e71aedd20d2907597fe5feb87fb7fd56d9b85b921eb2ef1ce7bc7bc6af776ebf52de4c3dcee74cf7d176c5516dc407382092135a4800a24722001d1111ab0105a24209b49400915b0059494ad1613c85182143f702053421302689cc4f41840061f7cc8c962e600331e604287231040c01b401013c0c82a2711277f6cb390670d04aa29ce5813b310ef8e79aa758b85a82a2c629ca3bb59cde2dd5b35cd7b4d75475fb7f376a35cad650cdc42fee2e30fa71aeb5f9bd1ffcffa7facff77057544ce5f7f3fb5657bcf38f79c627eccc535e354735528e4598875ba5b9c7dfa5d73d5ed96eab608a5d38c62ed66acadfe5ffd7f6170886e66f866edbd9e4b53fce3dbccffdb6cf04fb3c43beaacde9ad1fd3bfc3f121c4ea5206c359e1a4f8ed6e9facbfd65956aa9ee5d65d98d9246b52c34ffb68bf50fb719c53d0b3bcebccd6ec7ad1e6ebc9fc0e8f16792137d6f17eb607677e730488232c4c7bcea292c49ebfff71e2dd73bc569d642dc5bede6289c13c9099d2c74afbf9eee99d59d1f794eab66219add3cd4e13a361ea0d640a90e0f104f06f204d97c6cc09e9e9fa19f9c5ad75cedaa51e3b5ddae4a6c917eff9f7dffdffb7f0fa07c16ff5a209da956dd8ee448aaf131cdda5df3bf12ad97e1ffd13f8f903c776b3d9d1f9bd0cf860ae9f0f4e49d201fd496faf8d8847674500ed7e1fddd3a5d0d06e04a097255da9f9eda4ece2fcdd1aadbaf72cf473a98a3f4ab5fadde904d7b5daf6b1ef6f8bbbeec8be69e8f822ab0dd390fcedc90e7c1563daeedc669d62bde1df3aefe706fb58aaa40e0cb71aa3b5015722ba3221ecd4376a33f359f1c54a71bcd3976d5cd43a03f8d98fca75a0b03d9f1f1a007b759d831e77a3db61973cdba99bf5b256a370aaab7ef467b45571377dabe3ba783392ad5fced756150d5566b7e5bb567cc2cae03ffcfdbfd8e876ae2edc6dbad7654afeb467ba9467555aad3f6dd463cb81e9c0fce86fbc101e1827042b821dc0e0f8e8707e7c3833bbabdd55d6de22fdbd5a6bed39cb5eea8cc66fe32e5350b99d857bb5ad8917255b9aa28275dd7bb9eb59b9b22e6156d9152bdbea916a2bb54ab4095f3bca22d95bb87acced56d50dda59aabee16f637b754ee765d2460df75ae5f2d3d05ecbbb4d53b9dee9c0eb67a5db33097b6ef4eeafbe9a89982ad9aae5a15ee5ccda934777394ab5395b8dda8dcf3d1b1eb356df352cf4f5be960e65c3be9964a0f8fbc60bb5dabdfbb6b83ea8e25221d81aaabab9238d76e9ae2582292ab891bd553479d75bb714d54bbcaaaeeb0a7dd8df677d85f28ae71499e909a7a48b927a8a75e1124a69ed293eea80949b7b4eb4d21eda83010a1f78846dbdda6391709bd44a8aeea46dd5d2d1caa286e5573d7473d3e2fcf7277b1eba760ab1a75daea76aeee9acd6e8e2ae211a1baea3150b493aeea1b54ebc9d9c056cdd16b46791b5439cfb8ef160b7b8e5a0aaa6bd64a54dedf7dcc4d4f3ef965599a8fc596ef636cec5def0a427e0c0a99be6664ec65c8570d3206d9d2e30a7ab305d78e58d9d2f2729924f936cada974f4ab984901f03f27a1918f92449be5eb6f2a57c9224cd72892463644992264c49499664acac3145923032f6251953334b18cc4686495759ba9c902e922c65e40b4ad2e55fa4ab34354962952459b65095384ab284b94a72052549c24a528ab4419266d9928197198b41d62049922c874a1a2d2629035992b092244bb347962e998bad84218b5ac8170f3308192b4b178f292b4bf246068804808be725c98c2adff5e50da4cbb471bd4ad2fc9701c828c82fff3ccf279f749125d902b2a5f44192e5ab2c4d92f42175c81612a62ccb1296237b94a5ab2477ccdacb8d960ec8181919942e90aff206e9224df2cba812cb48d7972aecb18f2480f93419207fc811a549c248578c8c21cd2765d972334921932c4b172e615c6cc81749c6765c3c1aec90a50cd652c648f246966513268c74295d2691ac295f923473489797926c8991e5907247b9a3d461bef9a40c092b4b32c6759aaef2465996248c740149171ee4cbab245f648c201ca52ef6e25292bf169858494a912d246996a48b5c22759443658ef2a58c952fd2244bb2246fa48ef2a58cb948f365926410699236a40b09439224107247293363648b8b2c49f24692b01ae50cd255922f173954be9066b98334cdb274952e72a82cc90c4a19e942b6b84a92246fa48e52163349578b8b24c9204ccef86821327fbc489374215d33a48bcbede5088e1de4062eb22c61654c93278d9d9725922cc99224c99c8ffdf08d84406251a4058f8bd070854a119a29acb0ca513480ea04569e475382dfd1f001bdcb4afc140d41c83045b3a1a468c0c2222adb8634d1b0438ba59c63678886199da11c6387a013c4f008a29191402720c100f26599010887f1359f173b727c3994385670d83878c7c70f28385768e0c3301a601b321e0a2dc9fb5e2a3c7691f06ffe23f98f128afa7fa5deeebde1db130276aaff4f1ad2ed7ed2ecdefd3f52ab63b79b7474793bb808bb5ad8f78e0d1361ded5a09afe764bf2700a19ff83ea4f877d5beed672cf690fc644c60107b6622e3117578c16a0988ba9038627c2534d8b0d4cd622e48291215d30b09eab68c698335715125ed882c528632e2e9c181d420dd89255c1a42e9c182294361c2f2a17092322622b48d3d18c84d2257335dd74b18582117c5011817cdd661a0c11a1746560e60c499aa2d70f26b660300da298d090312ac1541221005b375cac6066c0cc50924463d8c2655c6c11751725df0a67ccc58c7965b9048082082dae18301da48c8f0855d4e0e243044c5ab0b810a37c790d99c5865c4cfa489411682f1b5992ac031812978fd8d00815a041690406a450e3dc611283360da088ad9717080309313d3264550e1348ec069008b2d8104cd612c30cd229993a64495c6cc962ba985dcb120ea42499cb12cc2e25aac0960d170e900c76a3c5c0642f48351ee0b0256b59daf13b61eb659e2f12260593bd80c07c1419bdbc2e3d5a9660b2d88d9823171eae27171b33727490410d1f2d3f98a63a1041d6528bf9c4f804e9a26230ae5806af9b09e402e3ea8187c45c623297ce8bc92534847ce130695e35765c5a50730809c84c8bac864b9008b9a7175b8b8d8b878b078c015b3e62b88e5e3f5e3b5c78b872c8f0983a46d8aae99026d0cc71992f00d478c08210bb754003a84889e20006d83080103e30f22ca0467d1e2031725545b58b6a22b27413f2b1e980830db0eb0823b25c614515428a38a8c9e0460c4a079258000e5248426e3a68c0bcc08a0802881e7258800d0aa0018a0c54363d746a30bcc0db65f9628b9f912b5a30446fcf56484105160191c57250c149900b09aae890c36d08c8c68c17594b2c070e0a4c00894ea19e88e89290662880000220c3cacf051cd0000684605515043433c3f5012a5a541505017289c11e60021010a8e1002c9c008004cc30430a504f45407ac0905e983128b1b8b0c02d28afb8aa284ff0b24296a01c41290217266096283f502a5106513ec0744099e5c22279901ab4e878e588b951da2869903366b4978c72469eae18e5cb4b56bab4b494b1d8ab74912649c23e46c6c4610ab1e522c096ab09e60393b1178870e2b0f57ac1c43a2881082e1a785c36606cd80136802d57934b0d598e1912b65c8ab88c983b5e3a0ca625a94508263381ccc85e1cd86af9616b0612115c824c19b2808162eb9565eb05938108b6607a8d105b2e3331ca189097ceab8526345e6eb830820b852d191a191a3367a6d33233cb32c2eb478b508cc89431895a6cd8329d78746032180f5be60b2c0317ce0b8f49ba605c38b2a4d78f5811580630190c0b6606cc0c9719971ab122261823c03230a38cf09ab2c501968bc53d0e74b86e3032b0998b3473cc9c2b0ac606ac8c59c570c49e5e346290b017f3e582314db33463668be922cbe132635431193251b2590c1623cd98cbe6d271912d374c1c22b868f0da612b060f22cc602e1c2d4723b8a018a1a6873f4b185590a0ca07a82031e50dee54708264242448d06eaf68814e8f53a62576c408d453160f2c01020d52d879e2c29017a01881121a1882020e58804ead8303bc3d05eebec0055838c1c41246482004103c4062e40aea492949831d366a046181101cd000103ee8e9c8b15b0d624061022d762b4b185d7081e4888d1ab31168e0080c0c4181093c20850208a0e741112ba8279d121e38a2031778b2d4440994d08011430881830d279440820bb01801134308110404986ce95487348bc1828a29a040c2080b00e1830e2a1040a73d0f901cb1d22101b9ddcc6294f0001232c0a002139d7a4044978404e41623c6f5544ca184073670840580f0e1013aac5000264988e88200b905d9786e64cc5c9f858a294cb001248e30c202403c408715542800019844d14b8244884eed0b2f9a9864623c91c3090a275c59edd44080138ec61e5cb298619460bcbc2863d0b2838b01a50ee502c89e92c7dc216b2f39e60f13d7d0a0cc41e2886560de20675c36c81a2e341932ccd3250313e38cc900e6c64b0ed9cc25d6028b9530d8eb6592ff9fc1bfecec41e1d75feeadea0ed5f68df5f87a7ace1e1f678feb06db60ac5395b72ae62aee2a06727473e601018f0778a4fcfb70b0555175e537380811b6c169ab83fac7e3e4e429e1df87811babb81f7f496ab5da911485fdbcaa6a5e46278fab7bcf431db7bfcb2c9f3c752ea09343ab76ae53ac778a6f6c34eabe9b9f3a03d0e99fb6ba67cc4f1d5edaea53a746e7c42b066e8cdd0d7473e758ab668217a2ac66756e6c5c10e0b2025f3350bf3f405a9260bc1d9891da8cffdcff1b51f13fc4838bb0ebbea88fa121a1a1a021a0a19f21db90cf50cf10cfd04e901090d08f904dc847a847884768476828482828280828e827c816e413d413c413b4133404240414040404f4036403f201ea01e201da011afa11fa09fa01faf9f9b1fdf8fcf4fcf0fcecfc0cd9846c413620db8fcd66f3b1f5d8786c3bb6211f219f201f209f1f1f9b8f8f4f8f0f8fcf8ecf508f504f500f50cf4f8fadc7a7a7a787a767a76788478827880788e787c7c6e3c3d3c3c3c3b3c333b423b413b403b4f3b363dbf1d9e9d9e1d9d9d931eee8138704dcadb16fabd3596092ffc7c9706c64361fe00f300030c691e1c8008031c6f8ff87fcbf90ff2ffa7fd73f101c26f886e3f3e1dc4e9c1a4e0e1cf3fff1cde7c337198ecf876f1da8578c65be9b2e0caa2ec61da8571b5f90204168b8feff20401ec80f238ac0383d7ae09e71aab350b5cdc3188edc7eb83fa63057fbfbc398ab5ad8f1edfbebe46ed7452a6ed7dd463f70fe6bb51fb4f307cc8e2a376508ad5e8d997dca4fc056ddf99153abed0861e3ddcdc30bfcf740b2d303c90f17e1243b4780ef2f88d3070e144cff6508ca2090941d941b98e009d2891b9b631fb2bac7d51af0fdd1280d31fa276bc46c572bc1c75f5cadd5dc0cc49b631e6cd51de4baef2a5cebd1550c54310e0ed738effb29d8aa9cab4e7d57e9f7e8b8ba19696f1e574255028812365fbbb1c1a851e31b1b8c8bba095d4ae56ae25ed73dd55bf735c2055b35d51e80e18dd9a906545b8cb5b06fbe66cc553cbc21f1a09e708de7225b3bd20555ed6ae2e6987715075b95a8ba3ac5fcc538a98a7bb4ee6b541b62f7fd61ede69b639b3150b5d16e1ef260eead465d1d95b67ab8abf1541355ce358abe3cddaaaba38cd9894d71066ef665d55675c269bb8d6a188735ef3a88358a66dce2704da3791de2ddb1ab5377e356c5a94edbfde33ddc24dc24757331e3ae8fb8ef56a36adaaaf888e2dd716e55cc33d62ecf42ac853c5cd3696671abf50f0337c6dcd5469db67ccd6d76da9ba7b2ae8e6a757d3fe1e390639eb62f9055b15e7bd71cf71e6dbabe1bc53958b7ed465b5daaddacd71c12469c4820fdbbb8b8c8f811cceecedf9c8b8b8bec9cc282ffdaf1a7d75f76f510f736ab6e2662ddee1c6f5d73aec6f131cdda5d71a956a2f6fd94eaa754f7fd74822449563811f416fc8c41b295110298145fe58a0d9815481d05f8aff9687c699a7391b759b3f8b8aef9e52fe6aa9087695a15b7ef06e2fd44a488a5973262e8d3346b9df6bae6bddeb16bde3beaac1eefb99abf29ea6a62afa7d9cd73862c6a3c8be0a2882a67112e14e1e47d3e8c624ec43e1fce69a170ed46631f3e6c30c75cbb7945758a710a3f5c01e585281e8081f6ff73720a20c5f734aa125ddd6eb5c7a2c6e1fbff32529a3cf7f9b0167617eba09b8539dd5f541bb5ee9bd8e36aaaf95ed19e76873dbde6dcd33918b0f2ffd8dd40cce2dde2126288a248b3b9c52f9126e6e8e8bedbf675db778829a47e6d000729c2ad5e7b1da8d75eba6e2831a42044cb5fa0e84243c339791a4e004fc3f5a7e186348c38c09f4640f9d38807fc690406fe34e2037f1a51c59f4670f1e711af3f8f98f1e7113efe3ce2f6b31a670c023c2d060d4f8bd180a7c5c8000d195a789a0c323c4d061d9e2603104f9301044f9341054f9ba17cda0c369e3603ced366b83d6d86a4a7cda03e6d86feb4194c8099a1f142237af234a2284f23d2c0d3884ef034a22d9e16e4c5c67966e97f66f9e0cf2c05f833cb0d7f66a9c09f598ef8330b137f6691e2cf2c2cf8330b177f66c9f233998d18194d8b2c4fdbe27cda163b9eb685d0d3b6a0d29105eb67319a7e1623c9cf62b03f8bf1c1cf62b0f0b31835fc2cc6037e1643cacf6288e0673150f0b4208a785a1022785a1028385d9ca7b9414f73893ccd3df23437eb69ee92a7b905789a4b036d46a39d5a3c6dd6429bf168a16551c4d3b208c1d3b288e2695970f1342dfe695ac4789a16379ea685cdd3b4087a9a16b9ff9791c9d0e8e1693412f0341a283c8dc6d6d36639606831fcf0b41892785a0c533c4d867f9a0cb3a7c9c0e3ff67cc64517e2653e16732ad9fc9763f93dd7e26bbf999ace667b2979fb97cf133172cff6f03df88c96480e9cf0cac7f66a0c99f1948c09f1998c09f19e0c09f1990e2cf0c74f1671130ff4f6383060d5a273ead07e0691dcad33a104feb22785a4fc1d35ef3696f064f7b7b9ef6323ded053eed6d9ff63679daab80a7bd433ced05c1d3de269ef652f1b4f78ba711673c8d98f33422d1d388564f23eea71149781af185a71179781ad1034f235e791af105ff3fcbc0460b0e9a0d99191b3531b421304f1bc2e369437e9e36c4e9ff6766ce289ef8330a2afe8ce28a3fa380c19f52fc9f52c4fc29c58e3fa5b0f9530aa03fa508f2a7144c7f4a81e44f29b0fe94c2fd530a10febf25368b1123060c10c3a701717c1a10233c0d88129e06040a4f03c285ff7789d16456789a0c0e4f9381c0d36484789acc069e2653e56932579e26d3c5d3ced7ffcf808921e34ad4cbb872e4655c495fc695f6655c01c0cbb862c2cbb8c2824b4c0c11ec9f44b87f1251c29f4418e04f2210f0271150fe24620134578c0604cad380f0f0342016781a90229e068489a701b1f2342028781a902f9e46047b1a518ca71169f034229ca711013d8de8e96944c1a711159f461480a7119df0342215fe1fc6a586ecc6092322e74f2288fe2402f72711527f12e17bd166a8c0d36698f2b4199e78da0c563c6d062e68c8c248e2cf309af8338c2afe0c23067f6669f9330bedff65682f5296fe9462e44f29587f4a39febf0c2fd43fbd30fee9c5097f7a31c39f5ee0f0a7170ef8d30b20fef462ca9f5e2cf1a7174ffcbf0ccd25062da68ba7c5803d2d468da7c5d8f1ff322d510cf9330aa63fa3a8fa338afc6714587f46517c899151458f97510590975185ee655441f532aa405f46156a0c1954f4f032a810e2655081c4cba0828997418595974145172f838a2c2f0305312f2f2db075cdb954dd55ae5ed79cdbe99b856eb6b7a279f86e37d835e73ec3ed02bbb1b7b2ee4e8dba97dd37bb79035b75a8769678346e37a872de7b3b7d7759e876d22b9a5dad793a557746ed6acdcb5575aeaebaab42ab28275daecaed9a739c93abfbea33dcee11efea8845af722c7a3564d1ab5d54372265f7c565f7c50d5521c76d60abe34395c7b5dadb771be99c10d5bca12ae4aefeb1da6955d1f6ddb9a3a3fbf2ac5d5e14af8aeb606655ed4605554ee5f27630fc932f20e09f7cf24fbae0e400ffa4015668e19f64815ce1831ad81baa6052f582141d682ae1aa049c114490001d5c17c86046ce110230686880859f25489f170448424a141e42399c2000a310512c00d5689b5b5713b7d2aad136e7dafd746c717a78e41d8ddb8dfaffdf60caff937f36804703683f35c87681142ca8e0ffcd1c6ad0218a66812941ff4f0a59e108941301c810c412bf1e23901040eb89ff274f58810637ee8ba80949081527f438a18bff3769a440a5052e3c090204ff0f7bc10058c8256e610cf97f728a17a8b0e40b17a408fa7f170cbe1802841cc082e273f85133bd7e7a08e25d1d5205d2c9106b61ef7be518a759bbb8ef3627e39f9cfd93e7d943fa670ffd4f1eace46ebc765757320060927e82983194a0019f6a15a8a27ac85b2ae009725ad0820455d8060902433fb2ac28928480630cba0b6c1c48e0d16400218e2da8e19f943977b042c2b438b103d3e10ac0928d8a1af00e5dd0d444c00316af0e1899ec38a9120314bf9b222e00852b4b962c5f7c102888410f0bb03103132d2ab00122be403990ca92058c30b264c9e205b9433f42cb988510305040173644ad2b7022449618a0a081b285c914e30ce30de8ee298cd002616d6b7124860d403d55610091a11c3011b0450942023d968a4d3b82d6961b3660a0c6890565b8458c9f12448000188f0fac70e5860656290510c174c230870c804c350c718586155c9c12442002891a114b66012de3bc9d500ccd0987fda2868346a807056425ccb8b909c236804a31b10015948eb0f2a2c5104542d04014b3c7941c788e609f14494d1161d0a40448a2e8e00491ce84013929c0d93c606848420603321c7185104a264c01838a010cc0e0820e8313b0056c99e00161b84224e954301f6480074f0942c820e1085925c680273be4f0808915848c60431117cc5c305445c4911448a0891b2420c50b25b4828e54301a80ce937f201c5b43f0d9e22a4915e850a500640ed923cb4db6d9ae56d2e36aaddd2cbb511a122b01333c59e1831ca290323236e4b1950edcd0800412ec00c34b8882548ca9106e807ac18da8d5c2b540b0012560b9a02038810548f11ab000051ea003508895e5db45b5503adc101c60481e0338b98109776b3f3b3e3cc7750f753a7fdd1ef4b421893f6d90e24f1b60f0e70d327fdec0c19f37107d0d1b403f3d36211fa09f1ea09f1e9ea71dee08e94a97d4b309f9e096763d9b904f540fb73bca2199806403927f565dc910a2146065b8ffcc61c89f3dd810391530f34fbefe7fcd28ef659ea25ae7d7d35d7db94e104f0fd55ed4f0c373574df30e10b0e727a493837ec01d9dfef0e45f9a6621600e7fb73127d8aa6e0d3aa09f9ea51ace1aceffef19777aabb976a33adf3dc4db8d862b2857a074a048c8f352901ff3aad3b6b8d3756fb4f7ba42dd73aaa66d46d9b74ddd5c1cbec6cc1a33dbe3f326c0c7cfe0c2ef7e7b354a358b5ea53ab7ba67b4ddb95477bb65396a261ec65133a1eafa7ba364e07df1cfd372dceec3a39bfb7f2f6220c4d1ac2828314080bb3537b36c76833b4240b62014e8e6b07a0803a35c376a5eaa8b7b5d739af5d2fa63b376a38e6e6e371f66b445ea7c47fd3f962e7ed5bfdca487475e936fc2071550414601c39331bce0a4e4e0059c176c20808bc7418830bef97cb8f33cc41a6d3331cd28cadb3de47a8a45afd2152a6d71bceba09b79bdd5aefbe68e7c3fe99dd6c1dc7741d5c9dda89eea9bd5530320e14994273b2e5cf145443d3e2f77357f5d9d85ee7537a97d7d9d52edeab6b8857a78dedebe9bcd2e08fd7f162ec0e20029f054ed54058906f0a21b756f37da4389b75b0f2572f5c87591b2a090781c976a56771dabbb8e77d52aa77bab6b018a635757b5bf536e0b4e782ee275cd28c69d2dd44e16b0f82cc419b72aabbb8af51a6c558e71270b3ffc7f8df7f777b200c26ed31e9f9705dc0a567c6d5d7591678cd36aa21ac4c156c5c08d71edb8ae2f10a76a8ab9c6c06db4c208df53d5e278aa7aabd9631ef634cf7ad5532a34f15fd44fa70a4dffff2e2e2eb2daf1e7e2e222d3f84687e7701d1d8eee34a75533abb3d55a8da33bd5d1b9f161ef429b24bdd5447d046b21cfc5c545b6736202274efebfd6b90e065fce623d3cf6ac851d470b7babd937e866ac855da7bad5c36116629e855c735cd44f4e6e74292cc1ddda0a6cd51c2b56f0ff47485218c80ed63ca3b8737717f1e65cc56ed6c79eab873d176bb455790a2e373641bdeaa335abddcd51ebfa26e582ad4accba49afa94e13d58ee282ad9a953b7777cfeb9ab6ef9e2ac0acdd2a57896a7a450001f474aa169940210b776b6beead4e5b8d02d97e405bd6f1e90142857852a0a120609ada6cc09c541b5520920aaa104a81d0ff57f15950465a4c3f908c4b43584844a9223f4c44b2ae78d6aab418a50bda53bb8df21c199528098fdc23a31f2bde4f6755d223b3d22901852cea540564dca91af28252db8e13d5d28e4e109291d4484aeb047b743d58494c573b553b2325a5fc16c93c524742bca1560ba4ea191ad9c994907e4029498a7a83d07e253476f63db6bfaaa070f714a58b56513e5942d74a6d5aca45907e4c4a448044f62a8bd712b172fa51c448096b3b4efd901d89447a0f5aa4ab3b523b3d2ac77bd61e216d652372a5cb393d4ded1c7bac8238eb1a751e7a3abad255bba4aba3224b5a529deae887f087c8c42423ae423b1f1ff5c897b4d42723349813d2d9c919a37eb4711b91f229f2acfd54e4695d8beca2deaba9fd3444c488a7248575e56454e2647565a48749f64348a4eac78ac47942b8292555543a142aa8a7e5b1525521d610e849ab0d1a026a0d3db13e4061d40afc1d8b14d14db9565a4d436f9f2a0aedb7cbd49ff787ba4592389bb4faf02441e914291a9d7e98d4629ba97688c629261e5311dc7675ec0a04552449ab468454a774d5e259f540e5d2ac454426154ca78e767e96747e96a88c9a7e5352c59c1316d08ebac45605e923251dabd7ae7263d692d1548e67972544e4d8db6c340c1221b2a4cbfa2142441624452c1e556556a808906df7c386ea8cd0600ec9a709e98aad1a0abac575c986d4b259bc98a5c4883485453584823a02527982aeb29478a2a6a0baec87ab0a0a8f52ba9c1591a8223e197595807e1c57a56d44b5832464b58276c6dcb6fdc8c88ed13becf9c152b3785a4b2749872d2a193a5969f1a264c08e84748494797c7e8ed857e3928cf010ad7692947c9e7e448c601159f2211a891a72d2e964057fa68853c7148a35ca2a42c5b38363935a5c904e9d643a256c94ca63446b27379432baa94fdf198ae22959d72ab4c8102b1b6d514f483c234f39adbd23d2ea17686b81bf9facac937a2b5c3206814519554f96928e67aa2745117d8652a11414c7b136233498437512161450c9e875728d74aa8e574742ac2576955262cc4241449e7814d4502e454277643def1af5436724ca585cda5338ada19d2350cf91fbd3be4d3c6355c6ad451da4ada4c7e8c71194cf8fa5d60811eb48698869ef928286aaa47247563a59ab534478340a3955e98a7427292cb4db6c553c51ed9370aa871361736bd655be2a5aedac785a4621ca51232da9dd9beaa6948845234d3acd4599eed773aa54d0a9bf55382c95677584b6e8544fd413cee84705649a0a6afa813e65b93aaba21257a26a6a93a87634d165a2fab56ef1675562d42403ae6faeb823324c87a0766c15b10967b47315454544b88fa48a464c5246494223ddb3634caf947c7c8ce89e9d948e4fb1f3fcc0021af10cb948412d437faa88fc78817c86949472accbe3e394fab8563a9d2d298989889048de39ed7eaa88b83ccd7b126a22fea836bbfe289205ccb53f9c907ad36e2b914d5919c9ea91c20983b8a39fd028d483d5d55d55302b67156584e2452548c32724d6c9e604e411995272a453f5f1380c362d5541112952259565b4c4cab68ecd48fb8338d583733a168d57e8ae89c7d46231011d7154c024a2ce6a0a2a0a0a28e743c4eaca69a7aab843a4c996d361ed8c10714a3e4223a1212232ab5d56cac2f1743f74502851ca28a54aa9de2723e39071981e1987a270464b1bf7133416092a1e7f3a385c51abff18b9497ca82e116d4a433b2619ef4a2989fd2109157f928a14892fab7f8a5943a25567754343232d95ef824f3ea9d5d59092a8a8b42a2894a3c2d21111a64721d3ea93ba4ee92a2b4e158dc56ec4a3e345acde1e5d10d5f147ee68a4a4b36621ca85784eac2dabdd499b74d938b48bb44e47233e59b9482ea22a4d097d6c4aaa94644cee0fa7271ed3f1eab793aa1a62caa911526ea7dd1972b372db496987f8fe569695b2d9b81148a3ad8fae090b281bc18a3ad2495965a9ea902b53e223454c733f76da44a58f4cbfa19d1355aeb8ad863214911c7464d4a387591dcae51faf53136ec7ea68aacd0af658b1468ac5e0540e6b4aa795054969f178d4865aca1de18cfb4a873454fc2185a6e914b0cdfd7e4b47bbf8fe80aa1a2a411195e86c6544682777a435d4fe7250c39d54d14562656813baa4147564522ab2525a39be814632cb63b53475bcd22831352a5115854a6fd493522ab483f2c1fa6137d0b0458fde291f97c8b37f5345d91511223b41536a10f08d528dee6bac2a5e41fdd83c1da1223ac72c9f9cce7b6595d3e930719e9f8ea8a3a5b2cb85844dac100f8d92d21579bad292f9405d017545dc308aa8a35a26961f81a08ae8b44e424582908a4c69e5b27eec56289c52309893c96432994c26c3e18c74419bd2079d23f8f059e8667382b9cd6cceaae3aa021f3d21e5e4e4e4e4c88220e170464e41dc51ce253a51f9acee2bd47970edbb629250af7aab7cd89fdfd19030b52a32f58334a4dae1a1595b36f443eb25ae4256eece110d2a1275a56495443422621c32126c62a582d29c965b843d6222a205a41eb13f4c57534651413c362b61c602ea182d2d097964c6a6a5a66ca4247764c3a52a14562f423c068d1c73b89fcd0e51f9e8041d91b4dabbadf519420559573542fda82a92637a9aaacad94749cb4694e97029ad21d18829f83b6a796c43e2d295139392904a875b7aca4045a2b076dc258df534b4f9f0a7a528a59d1535c473d5e4e35e395171212875e3643e3ec657b87ff07646542af7a854cc42ee0e8772514a4a3d0b1d091df1764a4a56506abb59e00f26f44a2935eaa4a07eaa88e82ba7bcd3f947c6f38bda6d2256574a526cd39015d38fb5fab98a5a4a7a85522c1e2a54c4e85211c182e2057fa02894913b0554aa425ad249e2094aca2e931125463821599a66269d2238f587dd5985de8cc35d69e5dc6e29c80a086978e406d32c2b9ea353102a6a4bb545749e8c6d51f7eea45044a79faa9d0da8772419502898a58c4a3827ee021d611977766aba33ea449ca68ce4a88240afd390a929533511895cfde879b9111e21a1541e1ef91c89685db1534163d29651fd30028ba42fd027c875d71fbc5587090784432a82cb310555239dce092754049783c2e19290a470463bc52125354ba89515347ac2616d239dce49869f744a4846393939391fd385094b26f870f97f57084a7c1124268cdb4d154162c2395d931155940e6656e7ea60ab260d8351ab9a59a4bed5a99fb65a7350371df33ae4ea118f07f39ad45523a09f1ead5d212f2ba3a86602fae9c9c21dd04fcf2ef274565e8d7a7c8a798ac7a798a7767c8a796aa8a798a7847a8a792aa8a798a7807a8a79eaa7a798a76c3dc53ce5d353cc533d3dc53cb5d353cc53433cc53c25c453cc53413cc53c05c453cc533f3cc53c65e329e645ed622dec28d87cb05531113ee1cabfcff7ba2744a0e876e3dd6ebc138efeff87bbef0680c500aafcebac5ed7bcb6d337af2aabe606f0e43baab1067085850074f8ffd7cf046083004410c09210f76582d2e19acf8735578b9aa876df8d8def067504c573357f05f04d7cf8ffbda3a670c64d8c34b1118011bc6b266aa0fee1aee2dd8568c69aa8067d3edcaa6c8ab3ee3dd4ad7b47f5dc4b5bdd732fd59acd6dcfbd540720cae70600e79f022033818a094edc8ebb0e9ab084b909f8c9842fc1cabfd6492564a084265fc2550933ffdfaab9bb1ac5ee06ea2416bd6a5527264c9460e2e4bfc68f5a03d1146b2b265198ab4c6c1e33f9ff1a099c6f17256187e72ae615dd601cad814523a43042d3ff8ba082084e22bc6c51d972524b55cd665dc4c524eeaa7d7df1d6cc7fcd17420c5f0b2107082400e1c9bb1b88bbcaeaae6a0d5cb3ab899a7fd0c407367ce0fba0668909967460490b4ba496e896bc00600a008600000800205202c64cc9164a2af05f3baec254bb9aa8ae3ac5472dd4fcddee5ef170e7f01e5dc7374aecbbc5405d8dbb9a15f66d846badda7f5a037d35fd3b66b66b8e813a57ffd4ce75daabe99edd3cd49c670de45a45db0d6c754a9694d828b172f31d5ba8e393c71d858c5682ee3be41983301a3b9b8d422fe4159b2842799f0f639f7677ceb7665445aa197591977b4eb166379a9385c55445d577575474d44c479d75d44c3adda80de825de4044e1ff7d5df35e9b511ff6ed7cb91dfe8173c4a8ffdacdcf8839febfd6555667b999d5eed659d9e965c08be49df9ff9a765f14cd78f722e6fcc5bdef3de5626d857df8f0e1a3665481da1de635772cfe7f5d55a63ee5ff8399b3baab7ad7970cb31662de031fd71fab39c7fdb45530f721ae452e6703a5d38dfa803ac5fddd3a2deab68887aac3dd35cfc22112cf3da7403dc5b38b74bbf1843c0b7b43b5f3288eff7fe35c2c5c29eed67f8de374d2f65dddffdad0c55b2b8723d66a521baa5deb2aa8fef0de5dd532bfa6936a21cfc2221dc6e11101a186eb5067f8da56fe7fd7390eaee6bbdd78beecb465da30da08b448da196c95f74d61e0be618c71ed86f10fbc5b0ca4a85b5589c5ecccfa82358a75855548d0cfd6962c1ffe6bb71bef08e760ecbbe149756fa8f6be5b1bacab055b95738dfa34bbb92ee69e2f67a8663d9525839502ac24b056c05a82c581ca855a83daf43d7a60e0c6c1564ddb9c83710db87d5353439557d44f6aaa5d740b9ba6a87284729278543863ac7f40866a17f29c5313a259fb743f1ab93a2af77ce4bbd5b40662de23bfac9ad79c4e098310028532c11f66411e44f2ffb55b6da8f621700b78a353a059d040665a271d415a430a951aa12b4059408be806bf2e6a3e9e1c5d53f1babec03563a0aa62dc559f0fb7ea50edc52d5431cfc715d76e379e0f03f750a7b8e6f3e1e34f0f872f8a83a66dc618c7c7f3d57c3c5f11fb6e783650ddcdc2b6b8d3debe3b6bd7176c55bed71cef2a8b54f36d61d187811b673525aac1a1da7b43b5fb704eed48877dbe35bf1d6b61c7a96655ae0a7916621f77f570a8f27c19eb5f1b54f950edb8d5c39d93876ac7191f09795e728b6e706c88505dc5876a2fe26e512f5d776fa72fff09fdff1124b896b55f2c5cb6f25f4b812a4eb5ba0e872f4fd70d442df224485cbdd3971f4182b590977dc05ad877c66db4ae192de21101a18aba9de5209f95af1d75d64edf1b5f51b73e1b9cea703efeff4c3ff3d9d48e6efaee32af97c3ffd7fade533db587a477d3bbe1c111b51b1e1b289c93c31b6c50ebb1db4ddbbcd397f7560bfb8bd3da05b2db05f652b59785ee75f754c7f360e9bfc63dc09fea24556e764fc242922bbe57dcdf8ddb8cb7ab95e4b4bbc52599a9dda433245864e5e20c89947f7e84e4c9deaee6b819921789d07fed66771b5c44f2ff5df3361fb1f27fe4c96b0dc4797864f85f4b792e1ed9f9ff9b1caeb2fcc8f9ff46acbc1e1e3b0ef7ffbffdccc893df1d1bb9fa2c349d19b1d1991969f9dfbd0895ff2f02c548bbc05e51b75b58bcdd786951b71a75dfbdbbdd8a50b5e7de74bbf188525dee76e35dbd573e59583dc0eab5d259bd5425513580595553d5e944ed46bf6eb7c19aa8ae59f736bbf90dea15f7dc8fae266a7c638371b0557916a6adc6be75cd3d9cf5ba774ead5643bbc6383c988fedf137d4ee1027d5f9e5adc69b876bee0fe3dcf8f4eb769f0fb75aebf597b1ab819cd7a8865444ff9ffb190f06bc23663c26339eafe6eb7bbb3ecc55df06b6c3ac5d7717757be3d3adb96f9ecf867715d7dadcf56eb693c0ff0bf9d98eb82b9a026336356598b58b83535ddc6b0f9fd6493efd72aea65d57737dda4df261edab4de929a93066524f48c55073b7f6f9b2eebc557b9b8b9a5539181acac27db739c991bcfbff1f3f93b29172893a4114105102881a46e17ccdd5c036bb37dff0d86fbe54edf9704eadd7f79eea71b536c4f1f9d68e66235216ba9bb47681ad56b25da06ad4693b83aafa7fa8db8d45af845ea09f9ea554377b4a32f4b3271e4e4b38e1e0f4f5e59dab409c727c1224384d5234351de970cf6c51b7ee76ddbd719a8538262cf870f719d30e4c554cffb5feeededd8d71529c5515e37035d8662229911cff355d0c66ba2959e7ab71fe626e35d3bd2c4d60c9f74990e4d9128ed217ff4990e01c41d2a23ba5294a4b3e099260ab1ef3101f4152bbf1b1e855daea9d4f77e0b6695d5dc45ceb24a59e24276ac7956761520266494d707aab71b3a45d920f9213bbede9acdc7df89866a419905a248c7304490d557b66777f737b14c491048e7a4730b920726a6e063eaebffcdbeeb0d5c4205ef3db66275c4bf5510b3b7fb7ab836d4e6ffabb8fbbe3346bb7b5a91dd7a1d10766460330b2fd3fef2acb551557ebed16ea22e659a8c1cf702c98e124805b9320c1e9eb7bd3bafb6783bbca778b9be1cad9902a86b03084e89320c138ed1ebe79771c8ce372218feb9dce86d41062c527418235bbd1fe6e7c04490d49879910ded7d635a3792624561445110a4542ff9f04098e51a7ed112435df0dc649753e216e5f2006e25bd79cf3a59ac85d1ce4cabf42dcd5999f0591126458bb49dd5f576bc19ab60932b3ae6a4ff5cbf333a22affcf79332227ff1a4724accd8876bef6ebf133a2ff1a9029359ec5f22c0402a5b79a0359d2acbb53350f9b7e76c3a255815ac8bb8d6076dbfaff5cc4bbc5e1b9785bd23fde633684a596eaaedda16f3614c34eb95ac4c79b75cd36b82d6e57b7c521df50cbbf0602df1f9a85e615673ecc425747b52abe09b66a7fb7bb53bc7b4dd7541bcc336f2664e5bfc667424f5ec5fa87519f8f371312c277cfd16e5151d1bae65c113fee30cf9847544464dc4645453736442c7a55c4a2579debb4c7e7356ea319d00a404133a09a9f24663f5ab39fe0cf8c99cdcaffd77c6876731f40daadee7e5c792e1e7df4ddfae0aa707d81b8dda25ad8b9ba559f31b3fba9765cd7ec6e7c5cd320677d42a2c62dae86936a9c8c7daaf001c227fdff5ab0559d72573e9c53bb71ca5d09bb0d30ebdd8c0706339e15cc7806c033020fcece12b31d07ec20f9af699e85a8fb0e9d7257383939ef8ab66a16575ddcf3aa66a0daf361770385c1770f5f8c93bab9e86ea04e15339d07cc746ad089fa1af7e19c1a5781bb7d5976afebee46a459ed05b31a0eb3da0166b5a3af6957e53a4ddbecea60bb57bcdbbcbea89a673946cc72dc59ced4ff67fd0ca70a1c0fcc70569c1ab31f11f8a1ce7e10cd7c4c31f3e164e6a3a9868f7978cba91db313ae690ddcfd88f636a7d6e38371f8e63bba594555a06ef5cf87736a363c573eec6e8ce3bbb9a9d56c706c7aae7c58fff0baaa56b876f375ae531fcea939e5aed23663e01e669467dceaacdcd735e3a4ba7d5f614fb9d640ad813e1ff7a958eba41abbd7ccbb09c1ec06881b206ed6ffafdd7c7b4f39e19bcf87736a5d3d6657d5c2eee6a076317ff171779c7116c7f5776b56ed45ae565d96bb4537422fc6117a6d88d6bd7fbac7d52684d8b14381298656432c40e56a02606071e2c410253a4e5cc0a149495472d5a2009921300b58d99231e0877f591459b274810393058d2e5cb05226e603ff37ca1f70e0046459890580881a2f7c167083c219f2b922550496a52852644f1fe0534887b08598c592aaa389cc8785a5d4599ecca892fd701980bef2e20111cb3c70011b9a921eaa381585ffff30330770f25fe2fc973f4a9b190758cc386052faf82f6f4a9b07cc782c99f1c03074d001dec14168f06b03af0a74d0010e5284d356ffcbe95f425e375c4cb8967085c075c4ac8601dcad7577736376e2ae2eee771f8959c8b56acc4e3daceeba63ae4a97abcae56c3c57f5ee7255b9aa566553dc144f75cfc5bd26b99a08b5e3a0d6f12ed54455a37aaa1bf5d38c9fe930c14c47947f2cd469d6421c9cba59c85917a79a2969dd59e99e55b7e7a19e4aa9baee7c3775fe1ea5bab8d31649d7f2ec5463d5ce35eea9ae0db5ce62a7e05a8a136cd5de35dfb57b3daeede63e1fce986bfef2a39b75aaf260bbd78c7d3ecc713810b8759add8eb966378ab96a847dbe7717c13e9f0f7f8071511151eef908e3609c22a2db0db8ea1d11ab0a77c3ec848360edeebec318030063ac5775c86e74b73e9f0f096f806beeee7c1db2d9a831d6421e4e759a3bef9877b57df19afb3e7635555f2d75d54475c50db5660ab66a9ed9d0350dcc9cbb78b7b8eb23c6d128fba26fbadddeaa354ef0ffb5ce5fac34e3360bdd2bcf421cbe055bb575b315c659e86eca3d1f4d51dd10861112cb8d8326dc0c4c6924e554b694354ae40bcab214028354bb6f941090cfe713f2bce4c3386dc6d56e8078507578ec3638d53e9cf116b6c6ec94ea1ccdaa3d0ab86f6c6a3f708f8f2f2b779fbb3b9a9370f82be4e15a8e7687386b77b3d8e7c3c0dd79abe236a7ae1e6a9e8d6a479de5bbb1016ead44e53eccd556783462e0e6f9f7fbdacd5167d9e08ea387d909d7fa7ed2eb2fb754fb296da980abdeeda75eafd733f6e04c46e87543b3180a000943280b1803f0993dce8f2c47ff7cc855ae5bad94856a236f98dde22c26c830bb45bc7be6398a6b9d749c7273df49ad6a4e724ab5ca6b7556e6699ef656ef70b317a7992c89efa5fad8635123e7abee69abf9cca586ff3fa6594fb95a8d72f52b550037c5dacd1cd78e6dd6c1dc39e63d705653bd7bc63dbbbafb7a7c5e1fc6b5e26eb3b2d4b5887511d7801bb35ac5ba8879ab51ede2ce378b79c638dcc51c6b377776bbc0765d71b8c657ccdf5ddc6d16d6c5a68d72e076ca5d618d77c747b876b3ae19f7cc6383533d1c66b7bb6a15aeb96a1ee21b9f0fa71ac706e8a707f7e8acbcfeb01676265ce3c3ec76dc35e75a3dbafad5e2bae7d57d573527a5addeadaa5e7fb9a5d2eb4fd5f5fd74e46e21da663dd535e76936da4fa9fea92eca7fefaeb89bfa7eea5ceb244ed5ea58d4d84b5bcd67e6046666149cd90bc0dd40cc55a7dc154a448928b155d934f7bae6699af64c543b9a33eba6696675577b2831d52fe76a0f250acf2f663cd74475cdbda1d659eb9a7bed9b0030761e25f658b5c7bac60d06152c6accf9a28a2f90f8a2c9172218b71751e01bd7aa71bb43edbe43edbec356b3a946db77b76deec5c08a1838791162c0c3a873b2fb66187cc1f19a35c779eac5614dce663c41f9194f15f8194f5840cd7ec693909ff104fc194f5b41347ae024b2b072022c41905790607ce1450c608085ece29fe4e29f7cc13fb90599c53fe9827f128be13f79c5ffe772555df0f05d30f9ff2e7c5de02e82e07061c567b5eae4e2877f2e4ae8f1e16eadf78220fe89e368e70b6c5c075d4ddc6c8e0ef7f932d6bf76abdcadb55be5bd2d725bd83cbea5ad9a8571f0edd65d4d6c378a666da29efabdbb54a7292ed554abca94c50bb240e2ff6bdc989d6a1c075b15e3d482358d718046f6d8bb76876dc6d955a174745beb275c3bd2a9c7cc726376aaa938e7f772dce38335df42d5ed6dc6fae76a252a5f57b5c8eaaeea767734037f2fafe135a769c6ae1ea22acf46a976756e374e572d446ba9eaf3f18c62fdc36dbbd5be59bcaa68c6c75567a9ab0d6ed5a0ea6ebc669c5d21cf38a8fef0d1d544dc7510ef8e35e7eeeea8266295ab2a0ed77e2fc7bc876637ef19877735b87bcdefe5356bc66d8eab872f775f54fb7cd8005b516026a89c2b282b1eaeb5aa50fff011d8ea56edad0effde1d9b9ffa7e3af6218b94e6b44eda4fc72c54edbb561355253e956a56cd6beef7eefa7eeafbe9c8dd494456d081150c7bbd1a4ff5c65d65d595af6bcee5dfcb8fc335dd6c76bb11695d73eebddd82a96ea98ca0a1070af06e377ebbb9b55eabb3768febdb8d45532003c872b7a6fb30a7b977446f3757f758d428e47929d50dd5ce6bf510ea05295040f57097856a61ee890a9b2ab6aa305661a4631c7c63b70bec5521830217e09bfe1d335bcc6e2aec6ab177a2a001270a54d8c2627f77afd766f476e3dd6e2c6aa4220a0a9ca84040e73ac538dcadf1aeba3b87458d3a2c6ad4b1a13cbaa707d511d23d59dbf44f1ad40314f2d9b1e5f4dc8d6fdda871f0ad676111dfa6786200244c11c51229aa70732f4db3e66ed62bda43b54ed55eba6a15d8eb9aa72f566fb8ae6ad6efe5bd34cdbfb7fdbdbcd7d557abc7f3bae61ecf3d21daf3afa7517703855d2d9a22c43cf91dac16ffff2d3cb476b6ae644d7648faffbf31841119173af0ad709ea0857749c17902a1e76e0d26823fae2fc6f99f64e29f5ce29f0c01bb7769abe635aaebdd110a350bdd2ce6ea71d53daba96659550b3bd7425e11d7fd684464cc4eb21b4ef18d23e130bb417ca4c3f8078a5d7dd4591803d776e31b9fefb8daf02d2c628e8f5ccda98e2eaa8f8e707d3fb1aa1ba59bf6e665fddea8dd76b5912c74af46dacd75ae1a91fa7ed2c323af4a3982b30929fe3f67d722e95d9a8db2d1aae6a41d538d3be5aedaae8556b8a6b50b5cd54cccb81b75cbf5fa7b778a375f71b8e6f3b9d8d5448db9cf87b34ac4a96e337bd4c28e57b5b72f1e6616eb603ee6ce31d7c1f4fd616ccc2c4e35aab2b93da6586fb7b71b45798bc335b5b79a63fdc3bbabb9a85d15ebd7ed98ab78ddfb878f5d75b7ea0e7384415588334e5bcdf1ee580b3be62a06a2db8d7bc698637703718dfff8fcfc00ed1617b71bc45cb32fe7196b2b5cf3f9b02f0bca97b5cbd3b6d5c28e71d6fc6a69acddbc8b5d876b1b779e579cb61927d8aaec46f50f03774ebb5b9d54e7eaa1fee970cd0d0633c635ac622dec3b9cb67ab7792c7a9566a3341b7595559b5c4d8412410cff1867e8007368269948222072ca5de54439e5ae70b0dd6e5469a43cf93bd4b8a85b9c3190631fb23dda8c9a5330b1e4bf166cd5e170bb293eaebdd5abca5b1563ad64e39bd293ee690a6735640ad3654ac09c408f5288465b9d0153a3add668abcb154a1cbecce1c440d17faa31cff8d887ac6e7fc3cdc3454130c71bd8ea86ecceedfee2da6dc4b96e4adb6dc4dbadb6db2897ead2761b6d6054aa8f79d547ecee7d1b0d376ff37a3a4d719cbb5ac5f12c7437f11ec539170eb3ab74a4e33a2bf75dc771ddf3940eb659881a9172cf477a45f391ebbe87994d75aa7b5eb59b4b91d2a35d9543c6c0ddaad8dd2a310bf50febbe89b8af6f06eab4555957779d623e5cb550b3aa3bbc3962d9709ceaa540a8c46e0b07baa2059d5210cdc00c30000000331240304828180e870422c974dbbc320f14000476be7496441689a2284a29658c31c4100008000180011081a11901a50a9345c4818107274cda9a0c0c85ed8f84ec20174e38f0762d35f3e17834812a5a3de2b367b2c82645fb14053d27c3338bae65f2b3c1ba5ee8881cc5cbbcaa73fc18a1b49548bbcc7686a570487eec2d5d23152434d397e3063ff50ed5a5bbf9c2a6065d22e874146aeeaacc42dbe5e9ca27b8a8c8ad9d194ed8c500aa775c96b657f4b60b8751c68c7adc1745844210aa6474894cc82fc857689b6fee7f8b19cdfd42f9801cbc034be1ad1622208d6472e5c74c065a92df835781ed4a0355d081c692ce7b60af1105962d042f8beb3017bbd86fbdf08db41f9ce1de5b772c33634dcee83a179997defd9640b749d857a245d796aeaa51a0da09570f4b07fd75cd196e51f8bc7e29e65b3ee7f0556d2c8292af2ee9bdf6c50a5da03bcab507a1470a12db70b69b430351d03aa852d822a95e245bd92cb901d18b34fa7135df008d66f8e9e6041b886f0c80ece29ec93dbf0b524d4c02cf83fe975946d725059c46513a620f777d55f082f1ed460e70021823225241513942daf19a6b71dc21f0c82d92520b91df055d71b905d0d51c2bc18b0803849f54ceab59f68b5a8124baf729e2d055c10d63c1c8b17f7d7f92924b20627241d9111b2b36e78cc8ebfffcd95e7c574ee4784651098f40fbefa13800442748e042d32222f59642d14bfc88e1d3f3672a67d1b848592af3029dcec8b4b20d01f1d7c685451bec5f8ca459221500e94528ab762d659b22d38ab88a8ea616331031d0c822a86d8f9eadaa92102e8676b6cd899bfc3ea983182e881f5f35d61355b12512924a13f7aaab162df374a8f3a954710c9ad845a08bd20ed1c5c225003e844d88eb7ddde024967da3dce8192eda4c7377a59ef3473477d81f17f2c7a3b4db8fe38d3438047f7deffb21ddf7df614d857576841c57847705a82b2f05cb97b391e1d17a093255e34b7ef451414d3b3de4fa87b28f08cc364a591afe8184755f587556bff62ea5073738df1d29dd2aea4ff6bdf02e7396b1cd715179001b5fdac83cf28bdf71370fe27427b7a02ef9b386f4cd14d8b9e30a25f549afadb5ae16f949996283215d18128deaf10935295c8acfb210838c44db43f2a07134eb5a934e7057ba1fe97abc4c722f4dee10345e7d0f4a40e3c93067d27690ecf8c6d874c7bd346efa91f084e2d3ab2307a362ea8c3a4fa74a528b26d50f096b9d2d8ddd6a5efa4c01481818289d3748b52e02ab71b2049d6ce8eed078045b0e90b3c7d69f10bdf7b2ef28ea5920c94317475f1ce55e982d6146076f7cc12bb49e3168d9603b9375d2edf566eecf778e0cd4aa72efa214d066d4cc2878e5b1c0b5bffafdd0aa4923e8a0d47fb87e3739d2e3cfaac840f426af282f5d2d5daa3b099ce1e2d87ac5745fb993122909c9b8acfde6ea2a62c2dbe7dbd27c0ecb09f868c4c51cd6baa8538406d8c36851af7104786ed1781899252d191788380e5b5e723019cdc0c0bc9b7ee94a45da59da4fb0c7eda51e03339c336803401d9f7eee7af548a821c5e28b4a4fdcc3c840b1efd9f067ab31997a8e6fe16dd90c8bf05d0d7b765ca22c2b63fc5cd54dfdff1e933dcc74fc12c525bd3760c6d0604ed28fe5607cbb190b94d49ff29764c701337fca5f3faa63679f5120b6c45d313a8065af4aebca133da35c03b26de31dc507f4ad6dbd065efc681b2481004cb81c1f61a5436a2fbe1075260e1d605af0f078770cfb889e0477938e2b60655f2badfb2a7a9970834199be0f0f746bd8962ae4cb70805b2a527f0580cb751b7deb5654158aa12f79eed704ebd721bd3187fc5ce4a5203299a08390fd6bef056e317539be6f385b3a8a5a7b7432ccdc3bcdafd9539605031e6d4c56d24fed4d0c7f4ca4e4b7e14dfbbe9b0591a9ae4d5411c15573ce091e1129a3c4659cfc7c7f11831350e69027005e95d4e5362587be15a3e4c5d7b5e1caf7d8724606b1c61523b0aa084e4e4319b2c40aba75268b2b376a4582b2b068a0c310ea4c6b43defdc25b5586399423805154f9af4284f4af25b101af37af329be81a31a28feb8b1de7923701db3a28164c8819bc050bc4ec7e83a3a7f47abf16d952e1455a962392687b5fa648331839f6f8f3d3ebcbcdc27c04e5239198860b299965547b30ba4e41e9d3edf2507e8ace1d65f9104a896ea57ed04a0990e8d94d338d846bb6e1c2793f07ad7b68fae5b6eab5233197d0cf030f64cc480fedd8ab5d513ec54ef4bdb40f364237bbf0b39f99f7cfb6759777623ca6e701a4d761ec50d32631f5dab9c48ee187598ce16eb2d606486e0e4347a7e15dac9c9221970e3dbdb23da05cfc8c050c15b6e81e2599c79b2f3eda245fc79855aebc75495cf420a9470a155cc313bfde7ed99cd1e7664893394a47632728caec2c7e7dc2524884a87b45613ec3ada006a06e243b0734c7106cbd9309f583d70ac90d91f4ee04c7c4f05ef2d9b5d42b44897f522574157b13af9fa7017adf2e95061f0d26ac51a859b415d7d536a68e59a56bc9a2d008891cd69b74073432abe55c3006b84ab5e31cdcd8b5286586668291833e35deab95f3021077c40e38e29710ded4fa8f9130138350207f015e387cc7bfcf0a46713a42c01ce8dda4ca5e2c7f39c7072639eefe0712d024b0f1014d8441084be4ed32bf1238765da6c7c21bca8fe167dcbee4994549c18a9ce7b067dc8ed713c117f3d80887431a58988cf26bd77ee8a37e86f533cc1f58857e0faf920b5f31b4e8c0406419362703e3c49f6a82c5e7d0db0284988321be0276986315b1f1fd63a9907805d979839c281f39c4c9f1dab4e4f03e22b4bd7d11989116ec85fe49804544a7ead81078fe839407b2a679121ef8db4ed8507f1d38076f36fb33fb307d5683afc28e1d38d57f87f5246938256a0358f70b38d2e0e56b8a70f9227e3de11dbab463d3dba2d6421f127e3fd432065b3593d348584f1b08a40e39b15bb8db82f72a12a849a5556b68205bbb912d3a23219f482da9682625586ed6f969af45eebf82322a4f40d265919869f84ba9fb6938f3568762375658a6bbd1e82e552f78ea7deafde8287e21b36df2cfdb1adffd7bd669600991037efd0515fd02ddd7df16245fa0b41ddae6cf5d115dfa065eb811810a9998fc61d7745dfc1d67230f7756c33589f8666eb25aa1477e11409dd8bb8c0052e37c2760ef43bf00723996670a8db530368a1bf3935af1ff98bead1be563cebcad9907ffe3d2e9f2f263a87a769383e97d38c057e35ced9c1d3c847b9dffc0d8190772864f391adccb5ba522c376cce3d118befcad0b4c334c922b18755038ed43a278b048d1157ad029da898231b23e578fa387110d4c22d272834f926c046ecff4f6093f9a766688e89a0946a12f69172919d66b16618a2f46b4231bb8a8067e776ffb7c75f872d7d4f8393f675411af6a221787a03f5e36fb6b29ec067e8edecd1ad568594812164599b98527ed1ad6f4699e33864150995545d53b088d4f85d1e1b84dfc1b9b63f7239d11a2e80ba9d5093f9933e4b933282d4702d979d4da9471b6982c2b34190a83ac6fb78615bd9cba652ca4606c711936cdf9b3665202a32de1ba0547e0be854fc9cd7a83f61106c747bafe750e7d41c8b36d4e631afddce66874905ccc43528529e242fa4e473e28add15887b9731dd004055465b160e1f7cab382cadb3178d1a010e0a65237119232865c61de796caae51343d977c73c6a6379f5f911da408ea371fd0dbd694321e5adb2cdea5c7c22afbc27424b4b107db4ee344d542235458fa01b2037c94f7b2ea49bf03106ace60f577cf085888527a482255a8a40d67b4775b9b33df0fde2565532034c00ae0ad61811c9e87335d1ac81ec5183187aa9f7e11e2531eec967c51b05e7bf82a20edecc92b676383d7e082d5bd85411cebee9d6a5eb14e629f88c67692e3fb3148036af519b5957fb04c90b55d37b9e27cb11d220a9f22488d687efd681f884359b992e8bd3b3a3ca3e5499880504eb0a3a583111e6450ec5962e010f7795510ab0943fceffea964d8f00bb97d628fe598b86cec8101e47ebc3ed1729343ebf1d3efa3ccdcc13e7fc1b17680c494cc06cdde802162c2ff8d74933879f387f1969300b0012c7db0ce55989d9cf08e59aa0d06cec69f0f9969d46877efa4a08c463ee6afa4dae82de3fe4dcd329c2e83918234d4742c39b0bd976f59b1563b5fb217914faad3bc32f272aee26a3e79e98424b58995085da116daf46aaa6c35d6021a045b8df70b35786dd4a403a29e22ef03147f47140ce1d3294706b61dba7ead0f70a8f4981533a15e74a6d92e7d014e696c58282328793dbb7befd011e711800eb78e50a1174216d13c5ef616ebf334f054d1967799cb83d492c8d2db115a63c711f42b1db7b70a3aa914621a7a576f68c28a3bf29520e9c2ff41d41a024ee1db148e6c3936660221973e13b451200fafe4f20700c7ef2c6019d2376165feffeb3f38ccfad1b3548b3e927b9194c7c25f15d2e573c5efbe67a60f5a269a88ff9d717b861e8b9a38ed12f6593a905eed9fda18afb5740f1ec0aaf7a6ef91e3af158aebc65bf53b603b758e75f293d917d2f58fabefe8419dbfcf422d284bf5670aa27bee1b702c4408a92bd357a597fef0922e51f35297a6429a30b025a63f909269a5cf47c9780070e201053181c00b0700e336ede9402409f4a81ce4fe1a440ae58f9c26ab318fe09627460d01f09cfdf31d6c443d54e95028d69dffbf7e35380a35742e0494217090ca64ae4ecca20809c883e87da03e02bc14d3c89646c345541b5b45ea8f0483036038ce62f81e96c3db3d4886a8cf26181b1fe188628c90b03d58e2523b9d0b471d721f2adb319b143a7c1db0bc7f0dd73aa92d06cf0473bdfff6efce9c38f7f63ff84ef8b2d41ca5140cfe71fbb4b227e76088b25a42ba7b2046f8fff0fc9b6f5c0bd2293ab2adadb7824c78208e89c06015e80fa26c76973a97e0816884d2b936314c2443b0684abc6f5af3d6d1cb4a96ce1dd2d5cff3eec6fd66e6dff10cdfcc1acf65eda30f9b03a93ca470ea66b6dba71b93744d499478f13e55f59c2b9326b32a100b870b2fb2dea3b059c9af5af7f3d9cd72d591b4c5adb2887c7382091db9a51a45332017be229da0b93c384d491b51775697e13b4c20bd2b2f2da51711eec7f30ffd07319b3cf8768ccc23ea8f05db68dd96aa696b50ca13a7c7786d656258a3497080654ae54d8a4948090e2fd9c231e006a914466d67d2b277b832f5e617c1ad27d55f1e78b2f6aed97e52ef17932ca4d4ba4322326ce54fbbc041188883ec78fe40a7d962cbe97bf7bdc67c5940a232c1998c2fe41be4e9e58c8670ce3a084c5db52e40ea1201bcd593d4c5ef5d85a8d4d9095b7041d0fbcda42dbf1db73776794483eb1782403e3f2d33da557065c747a2ad72bcaa86d47639e076a583488954cb40060967179b740b4727f675ec85d6c9e6f0d0ea6403f8741983b234de2943c59d170330c8e356baf414e619e893effb768fe49f425386c765c5326f4d1fbaaa8a70a3994f558d2466e43c9ca823059240174cb2c3cae6c4b3551ec757140d63c51674ac5e423be53f31305aa9b6276065bf2791c7d3f443194308c3f20cd2c9b9d518d51a26d65e8e609939e981d300f1f07a0dfdc338f9140968e6772bb13d2b7e37d8a4fc15b3dfa9861b1f5e10092a6aa1162544016e02c80e7e676a3b7e5ffb99af8791b1732b5f82b96e0a61db42d7457deb41a9d3b92b3c96c121d6b372c2c799252630d0aba5fb4b3deb654238a01ae81dd15ae4b53886ec287ea4e98e865bcee711c6519872d821091ee85c1871e50649693987fc71bf12deea59eed94a6d4ccf907cc96c66d31bc83009aca743222d8e60d9e2da5dd2f48f5e6e36c62ee49d31897caad5c9edf3c8cc819c1a4771e0af9b8cb8013e414118a20f9a49b2bef4fe41a20fe56419f1a6240e87702d87fa6e6c3cee45f13b01ef285eba766de752421876eec4c7565dcee09ca450a0812bc0b3745239b4df3061fd1362208a77c00f2a019345c03fa4b565c988ca096d6c20062b814d8f8839893bbfbd0e4fa85fb89a036c2c00777887cc9092f4b90f7902e6ee5eafeabf0fcc90b0c161261b4620e5caca78a068787f8cc0bd7d9114ee2799d75f3a727ae4575045f33402bc86cd4ef8b9f730b348b52d429f48fc6a20619c4d5cfeb39245fc13be9481ebb244d463e70f758e3b4aae46bfee2d9e5315bb7755bd5cfc18e63566ad2875273a7ab9893a56619b6179e2df4830a17311bbb6a5ecdee0fa95f1bafbd4513672621c8ddcf57b56fe3c1947dfcab88d06e9923e38bf7c83ddedea50b5815caa954f413443ef45d789b52a3f5776614969930fcd117254796a3895482ab349577ba06110c69ea1ddef78035945cd283042000be00be9f8e41383ee9a4ed553a4abea022dee6dea1f6d2874d22c36bd1cf7d6d9d9de9e44b89b06f9213fdbe530865abcab96362b542572b6bd001b1127c8befb54a2a0eeeb4fc33e6aee6f1ced4072ea1c79dc4d6b3c1da8a1420f53de82a9b76245a0011f55018edf1c52e54482c3f8c9b9d74411486125cc455fbc0f4b60267dc9c43f01a0132672672120b27ab3cb45a7126df38e4831332a40e5fbe971bd877e984f6c75ee050697363a4c67ed0a0240fbd5a4dd2346d05cb946e09c109690818fa4bb2948de21d731cf6149a3884f6eb02be4408300ae04da8f593127aa20f5d25140bfe4defe3fd3671aef1e0c2e6af12eef23dd4318f4e5278bb1dbc8ac7c150a2f41f7f5f0dbe749d5efcc0f897f95f33c8459e9e59318f9de2a4d395c8f7ab4b8e1c9fdb84a265cacdce72f1048cdd90bcb18c43f63a5489a27b9e7cdeb1539dacdbc2e9737172fe2b5c6dd4c8425efbf6310f3da55380e6df4a8449d5cfd42c57cb1a10723aecb5dd8956e9822bd8732e9723e2b05edfe91eacb74cb1286d22569d8b134ded819a4315843c3510a1007863a6ab24ae418b4ec416b1bbf8c6ebd64ca15c0332c895fa3d49b1cabf91148a36574975aea5d0e0f0f25c83e1acee30f1582e67edbfec1436361609ccfd1f480a42b5c17443b26e18fd39000643797c79494dd3038e02e9574eeaf1233f718d3953ed7f570789bf29b1076b61dd4fbabf64b6c2cf3ea7da0530b4fa1aff887a7d8d709fad821af82c6e2ecb47b97eec7417585bf6908772b31299e2900a72734730b53121671b0554113f395c2e1d785f1362d5a55a735b8f1acfbdd747ec0248a8777da05c2a87937b718b1fbe49ec6d2e27a111163284f0c7c2a45e6c900d939e56000f91dff5f53b52cd664f9a54288e81660fc853209bbce147abbc28185456573ddca391919cba74dc4067a3c8b34dfb70708d55ca11a2b15809df80f8b54bc3607b5002a99e006fa1803e89750fed54b3350900d0cee9f8af7a6b21c28cef8e5667b2a31e4f8d05a507427358347d20125be02f77af3a40c9566e6503cd1d55d69609cea445c485aa5d44df7bb65ef75a0f0416b1e69858a758ed5b7c45e868582267505617f30c1da477234ff6821518e79759c9e50ab3ad1fa8048896aa6b44d8a3470adc50e0c135121e966e5a7f0f6b91335fc1dd59102a7f1d1652d1edc6566c39111d7b84f07e2e4cce417a7b587bb8ead28669b02bab063c4eec7be09e489fb58384b3d68281761602fb1f33088b875a53ae2ecd5b8e91ced7bd46ed1d822ad5c8ced8a611fe47eb88da88acdf9d82a21685cdccb4c9807dca51b1c77ae397dd24315e6ce3b5e4c5e0baa9d837e61c22cd97bcee03651c1aad360cda4f9a9d93605fd0046fc455b1e2279dd94fd3454ec8f82b413b793ec37d3a409955ae45070e4fd3e17ec15f24e613fcd9f376b81434d031ab13857a502dfccde407b0bf9f66a917627ed1f44679f14a283d56001279d58252b32a5dee877d6c1a62777dc5504ce02472258dd5caba27b917fa8c94d3efce5f5a013590a877958a8eab39deee216f87b17467399765d557b75c7a23d95f8b5931d1f38fbe4593885ee8be1ed1148627116f7118c3d3af01febcc8e9882fab7367df80117c26754cc15272d463d06aa3f751171137a4b79c395985060b3b5d38ee2e9c00609998f220d22724a698713876b2f30da071f7c41fabb44c7f60b4c8dfe5cee4efcaa3a24f5fbc356e4510b5bfafdaa9c8c37c6d2658adba20414cfea29beb70497e50936b0b1e5364c1df1fb99a50c831235dd4f2859900cffb59c10fad41e2e2d934e2225b3ca4f21a2245692960a1f8f27df35860030dc043ba742a06b0fed01569ee1cb07989e9c6b52b2a014025e220ddf52da63344fa7f5aff60b99245e1480a4441b72fdaeb372b9d374bba199083043965f6a43579eb01b94f310917d90001a47e5f01640f6a05572ea298a679bebfe3d785830e8fe866c733b5d4f497237ce66d9a4cbc31ff81a6e9b27b62855d3e3afaa923b74297086a2a39de74e1b4ecf6de2f7e379e6cb334b22e55d60e1603bea21105ddac7524330ff3b3837f7171c25c1512087df83f0f686a0654456b53adadc04aff9e30e1cfbdd2bfa681ca532f42fdfb76d7b86cc047e258331083b75b15ed3bfaef0b888dfa9805079e80abb4324870270e3773e5e5c527c7328c62e74809e5109a1db8a737643dce02063d4fe64a15060ea89f43e8e1c9c27ac825612a9e3795539f118400a3160af58dd9940989050ed32cc5b1460cfaae1671ed2023721f11c26d0bf116e8b825237d7a064d5300a3205ad82f7a1cccf05694edc140b8beaa50529752b222b77498445099024117ab7708a1531730161ffa972c76ed200e68d05a7c48b9b6ee03bc25af908c8ef839179cb5f318991c20ffe83d8710e8333cb013173116f376b088326980089816667317f13bae751e6cc2eaf3c747e8c96dcab912bb9e507a27e881e0248887321574f090dc6d8a7460a8e29e0956cdb160ea94e694997e0dd4c5113e5defea52e8256860f80bc513f53721400f07cb12c917250d7f09265930a542af4c00f90f2d32bf65f692084719cc97e36dd92032b8123e102d8700a7b8b0534b126695e0d83675e04eb04df6785877db1d3f88da9d35343e4b35fad9f61533bc8e36458c6082c9d4c06a3ea9e601f9ce020cd727b45b531e553f34f507f7862e61981dfc617f3c7b56a1e13c0cfdb366c8607bea03c4819889b2ae5bf721403d9dcab0fd327643c766b3713ab64fc3ef395a0a3ebdb20cb134599e60de0587f3fb131ae5f091104126100658223842b52357d90cc40157db2077318ace63bcb58202c3a8e31287a018d7dac4bbc979c34e10e2804a87112a81fef977d8f38797872c66761b3325dba4f2c9f843cfdeb977ec92d495941b0f11ee3e00a7b83229f17d5d80655813579c21d63d7f5f79e6de2dbfd726b66f51579ff6cc5bdff95f18a2dd2b0c10a85c1fa240ae262ee7cd4bac431434224f817ce00332db00526f7416e039632c0724913629f16c4dc74a023e5689755b5c9e4ddc750852a9c153f8a1c2de24ac10176b5a44af523e64c9a23511349fb1f445c897cf3e99fd32e80e0a715b3e87f813e52aec755a53d243b68fe2370d80f955eaaa7323cc120232f3c04e17cbfdeb5e65279f41f4a742d12e93d323a9559ca3ff82debb92f00175f5b0424b696fcaf415c4f6a77d4c604cfc831b168a30d888226829f05c89aa467fe242f234026060b4601247f9a598c974068c42079963a74c19aae4ea6bf04ccaa2a49f63fc1ab0e95a006a9ace602dee689bb43fa01df09bed338188960d65fca6431871ad27d0015c19f43dd72a4a8208ea9f3ff07e5ded5824f846d416d0025d9c5caa8a8a8d0b6ad7de671666d466f09d94d755e13031553c84efbf726eb0c7717b00ec0c5d3cc3a830e023ac09cb25a3ec41038081b12092eb514073975a4d0c69d9dda96bab5149ce164b8be9c8a44f0f98d0c026d005b9bc91ded31300b0c721a049bf250ad259ee5d42d30234cf034013e1e443991f18428f49d691290a5949b1d0f626156c51e6442788b1e89d8cf39d84cfed36554dc0624b06179283791cb3da12cb34f0c6c44a30dd54cad3eea39b0f3ab986650ccd914d5e92dab9c66abcccef4ef7da6bc6be08f53102a57ce938d004bea72822ad547cbd74f1bd44270c264f2b3145bb4926dda7ac3368eedf0238df3306010a390f41cabf27a5d9978b40897c2ba58313f0e5ec606690605bd18475462e03ac8ef02b695c0c15de972c26e8e3cae20433975f8c725eee89e4376ec1312aa7731147cc4ca5a9f0fee788fcd1b1fb408a3863fef273d09df63eef8f91a5c0831beef11cb6378bb12274da545c9a64ec6c8a43f304e821f65db1d46f0debf69ca302a44daf02e1241bd5ee94d2af0682266d14233ef269680a442e9b5e6219554bb90ae80d98a26c5f87538bdda6d5d8292644f3aaedda10114e8d5cdf0566389fd24b042ab714886875bc73af8368107969cd6baca4223cc9cd471dc69e2974983c043f17486829988ce5435252cf3aad808180b1bf17154792a085db2f032f961306c6b648dc6e8de430151e5d2da7882ac27c1d696b1b4a2d3afe431468870f88d48760b9142f06fa85cbb0420de48e2bcf292d9094cf08b90a1c4f0d94c6e0acaf8a76cb7db298b5104cb3ada1e5c00206daeac2996f17b6042eb20a432365db6a40fb57aa96034a0704c85acc929f84a30fa1752a00cb3322f9aadcd17e695a770f163822fc79c41068bc84c3f31aea6d3efb939ec513d9fa871fbb97682b81cf1b453b9b04a7b7520b3ccef76faff77c8041d6c313ccda95c3a01a8b76c447684c38665c1903bd803d32c399ddeb8e144a4f6847c73f0ee9314412cb16e03e14cf63d78e57c862ed687d9a56f0f431addbebce8e5d311fe48e28bc8373d1ba88a3ce2bc29bc1c76bee779a02a82bb43476ef410f3af49c9b9dab96bdeab629b7777a20fee300b6f2b6f39be881c88adf6c86e33187bf0090b33299a458ebf6b617c1bd217fbf5301dd1f04db19d226c502bb72ea297aa86b60f4cd4829a9a33d7d8e46beeba9f650c3b78cbf73a9f6c0aadce8cae864fbae84cb93820dd14ce6b094874022ec31b575fcdbf9ff380e8e519dda70b6cf4019c15932f2d8c8c06c86da35167f3c5989de819740133a7231889eaa18d4fb6727eccc8a5c294fe38ca150a79531c864532dc564163f460e6d945c9994d96cff704494a8aa335c4710eed5a7c82e006bb57101ac24af765a7d991fb827ab7ee5eef05181dff97cde6bfe3f20b7b1f80bf0878727c5bcfa2ddc3c7a4c402fea3bb71c7c54376eb1bf71f248e07f9fbaaa7f20941d0d7be3931d13a0de925bd018dfcdd74875d69e1f92bdd641065be5a0dbc380e9ebf27cb3f0eb3b15602e3b82ccb74ab7d73c3e1555f6f8ad23ebe08d7e146b173ffd6e0346b75433b994f2b6b1066c3fba74db88030360c6c0e15e33efa224ce3c0fbff5868c857fe414da5a1cf575cf4bcea4964a4fa24f05a068bfeeaa8750d7613a643bcc1f3610ba803875fa3a4576b4e5715e7c976de710e7917bc4210654dca2bc98ad05ec2b6761dff0c8ba5ec6db218afd249a60c62644b18f5567799fd0f05aa2e95e37aee81bef1c17e131eeb5d6cbeb625abb4c836112e2990a9655a1ca6885738283305fe0f84ee32098a5b750891c04951c1f1281374cda96806f96dd5aa641ed36621c567325430bec1957af926d68b32b99ea0ea09122dd0aa4a373d37589f274301b42bcaaa6fe59c7b9148189ba0a124ed65bd89f9714e2ae5cb2391113ab6c3eaa3cfafa7a05984df7a8d954b31be97fe6c86c682ccf5e484777b8221e76a782526365e1195b6fe434c6e4601604f3f29bd6005ca5b2083e45d4d9a910f54dd0e56def733b2efe59c676c0a998844dbfce1e2cf06d34e361ca35fd1a2af61a13de89c95bedf717aef2fb12f3b69fe3bbf31acc4fc85aef9fb478649256346021ed9929f339fe4849af9ec01a2d1732127c9e743d7e9f3d261240e0ddeb15c3048f973cb3b2036d43de1613a65f9cf83d4cfb3c5ecec22e3f6cb9245bcc5f258e62cd417fd1ebf4b6b7dd403fee68625c99ce97b4fc97a90f79e79d3b8ecea138b0c842167e5d85276263b1403d49c51ed2ce66d4b0acdfd4f49c87c525280e22d3b0a281bb95e3f81f61798b00608eaed0a0c891f7bfd3e73869e04e6dd117a872edc2c7d2d51a4f20ef05de36478fcff3c8857f763442e82db80514e7f8c1b35e33e36b511ade682702f8eeb0209f9cd6f47b368710fc1f3befe8c04bfd3a7b70a7af30d19091f52838ebc13dd84131ff7341f6da67fff9e461bfb19a3031f0d4c3a789b8942e209306833882893f8d239e5e53e6af7d11665544a3a076e0f60ae616842f4fdd7f204243cd28126e1f7271c144961e7c866e2f46dc0833c9c867ea27fa9433d822e17deff8ccfabefe78ec12e6e0cf71939e8abe47984ad771a95e5b5d939bebd4188042d7d816328773c78f28977dc9ff6226ccbf20a44920c2af09cbb5107892534051a165004fdf5786ceaca8b3099f3d409a18f5489efa23a2508490a4ac6884da222a02afd6438b55bd6d34643d9d2b5cb21b3c3993f09305784c2ce31c134a876a336b2426469cedfc4c743e1ebc9c2d4915f8a0712586005d1ad38769361f2922b7a1e46a46829b04255453cc8c484c87db4c12ed2907f0779044ce11106b3fd79c991280b08735b823a38b43ef3c7966c35889c589749a670d98b95364e5e97010e7c57275407b28b781bd4549f8ff07a4d256792c0a3929e76b17fe739f69eb15e0ef36c8e5208e9f046db97e85d2d226ab8fb651c2540055424f4aa52a53a7a07f18bf10dd3eb1c3022a285bb9a3489a1c85b4c04df62912d199d0010764060f26ddf985fb2406d5c25031239a6e93b75b19988e446b9f4ce0a024b9cb18db707edfbeb851680b181fc60c1278f6e673dce254a82322eaf56031f53f1f67c59b0cde78847f7de4c9429a83ae4e24e90011ba716b9b81dcf04bb2c487223148b4f2701cdc0fd7e50dc2d189d9280d9234a6ec15653237e511246cf10e582fa50dc35f39709e7151a0ea2fca0f7f543b07510d5c6c91ba06ca27c9e3c3721609e8649d096d846ce224a46f7c0ad5d62ab1731e607e6250ed427ba5cf44f7c172768c5aa0f679b7159bd91442658cc1daf3d018dab98bf8c6d120c3533885fae652525e00766bcfbfb4af3a6394f79faa3c996ec3646a33149fb85a4198d2b464f28f6cbca1dd8f57851ae99b7b24b2d4c5f2a1fc031daed6e383edf71e8a707f244bcead225c9f732d12715e96ec84f44f89947552bc5d9b8842f47b51b01d9f454321947d382880ee88f936903a05b373b442d114b25cdbd76283bee246f90d06ed46b094e2c586b3ec8298002dfb8326e211e61a1a599c3bf2b0fe0defff1deaa29be9ddaa3e6e87990a59741bbcc92b3945472a57196578a3dbea6830b8392f2ec642e86efe45b7cd0e4b10b633b62c4c95102a5aaa1d050bc5c5b35bf9bfab69cd57e5e25537c1ef410370320cafe1c1c4773063282df9d6090af018d7c156c4db86a4338258b70f753a2eecdcc636c759dae0ff3cadbfb23986a2bc89786b20b5869a4e7c77acb79aba3fad321b1b07b8959bff7944ca0941a41225d51c99bf3bdbc03f83323f8ed1f101145cb4a1d0dfedd89241e3f2dc44a8b6ba11449f63200e3a0341fe0d6f457da2c3c3fe046fc6e88e6fbbe521e18943d3407d8ae5e3bfe295b84c104eeb5f18fa0046d33643092fabd726653e9ecabb6820141e02bdbfd8a7f2a210c1c23a59f105ff8bf88222808dbb1e8e018c3168e845753fc52289be7b39988a26505e2d2490e0a31112213ff790a2351b0cbe7cb8fb096ddf0f356a0a412b4e91676a9d5b0a2915685669f82a79f58124fbcce3dd50d6305f95115b250b6fba57c58cf9fdb540e209f0103ed2e7a9211bc28e3167b6cc05bb781a7b8518920c34bff3f49d668a0b435ee6f381fe3e1f240d834d29b1e5a59ef71888a327a9e1f3a5c02eaf3781a0de303dfbe8fa12c3e953ad520789b079a59c207d3e4c9dd53b3ea4caa7f7a8dca6a99ceff796bcdd875c01790a0047487f041ac4eaa4ed0a598d8c4cf226659d327cfabfdd787e233e0044637ab027483755d98794f78c44c01b4c65b995806f009ab1d4a4cd862b4d8eaa4d010d1cb676787ac996b40d21ad75a2d50ff6d3ed4fd75902f2934b7a27c88b9d2a3558570646b0ba1109c998b9d0f17d314f635c060f1c0639c8c116dabea8dac1a216dbdd08700f236265506a91007170473e0fb89a93e2f0bc8a211270722eb7c33498a19c09d74e4d1c1275b82bebc34f9535ad53b33a74b80640d6cf966d56dd7190cac669fa365021dbefb5735e2b56b65a1b0126e286ecc53df0a9298770d5339967fc783276222f00844a386e3e1f2b8c9471062cb82602367a685dd5e6e444147dc422d48f1d640513b45316d109f6189079d12e3e6c1fa88798bbbfe1581ff682930b564de32d943a289eb17ff6a812d4c70e88494d6d56c2a342c8c59806f8d2356a1ffa4af14b3ab4808685f3074ff99380dd1c9085a5b566a165e3b71fcd2ffc5a1d6852855682f9c6f8c672b864121c08568b51e8df9a0b49ea81afa7f9edba3c10402987b0c91609e5dd2592b6daa52afdde2c8e8ccfbfb6e37c16bc9e1954127b5715b762f13a198158c475f619bf7c6840dec3d1f83938e16bdfe7421035d42fc57f4126efd2d08c8216068d2cd1942e3f4bac737ee910039b235d4798fb674e95e9f34e430c74a2919d9dfe939b572000b28234240a8ab88029d26c11e6bf84510bca9291a35ce73611c927911c3a0ae3c3996f0da6600ccd9e582c9854dddbca7a2dbe051df341e135e2c5267127d1fd6a3fe1f822575fa8ace147e38fe495f3d388763ed4d8c158ad80e482e302273508d9b7ada52fc160c7fe296ca61e3bbd9f5dde7b7a249ca0e054b0467391f16cb53f3e4c97cc47ea4f62f94ff7bfea0d02e40ad49d359d3d228464ccc79f875196d9f555f4a33f7257eba847a70ef321048483c0e2df27b07c77348cb12ba9025745febc4720c1c61159b77efd63aa4aa935cf81c5ed9baa13542dbc8ef9e0c247beddb86af5fefc5f426e089914523abc6d57821bd317a79cea958895045cc634d95091db6a3a1acd4dbeaef2225370f980f520e29951bbe713a21ffd87c3e38918cdd09c506ff27f34671cc8074902c8844be89007ff6666d8034114390744d2276a8ef26fd238eda115d363437e1efb03cfcee42aebba1e3cce7f3cf7645f4bbed35409460e5a83a557a7648d91f5a01051d409ca5afd23ff4e0a0773bbf5176c98e8edd0307f4a26435432f5752e6c795312cce0b970d87956b40e27993b3c03d596069eccfb051e77c670ab573ed614c1e7fb07163f97d4f4819f80013a10df26631bd5b8ea506ee6b9ce34a2a7af8969cbcd599a8a4100a95bbef1d26e9dc3ba9d6a40774b9d66df4697b3ac4beacda869bf4008b9b1070b21213ed94480b431024f5d0d78b7d43a55c6538ade3275f4fb7513713725f2397208ff9fca0027affc3feb4c8ed075eafd688b20385091c18fc6f4ffcc14617d944ac425b2589239661f70152c4b394814f746522ac99272a25b93b2fa55b02bc9c53e2e4e5582af547a001d53d8263434614a14a7a073f097788d67974d539a5a2c10fd0f876e885e02d719dea5f8cf97e41ad0eea5efdb21d1d0df1168de391fb2393039cc8478a50f177d82d993765c32b247370adc51f96a266cd24d5c7244c0963b480828219430eea197fe0dd11c6ea37cc94482cfeeb2a3bd84c071f569f97fd4d17901480510d2e7147e886fd7610cff636f380d2da48ddee70cacad885a9efa218a055812412243e8a2781d244d836a369d499c96d09903a1102cadb050ebe0cee4b9e5820eac53a2223e4c8da9fe6effc704e07626eb2b9080b171efa9f9b2a6d42bee4d102394db638ffdd6737bcd0307cb6e34fb579cf9a2d010b5de27fc8fc894590e7eb85264aee19e1c8f04fe81ab6e3af2a7f380d7d554de036a891b53f4f187867d9981276ad1d965ffa3794c1d069356c2796087fe670f9bf6dddfe8914fb10758e2f8e3704023b64df5befd3c08453ef6e4d2e267d9a006a0b4fdfa22b121f8cd49686f3c26c758b05d883d809bcb413ec90e909b644ffc08b5dcd60469abcbeaaaa1291788678f5af9d5084e78001aeb0b61220a090f12648329f446fc967417482c8c43fff0b2d4c477a315ceb10a58cbe31cb03101b8738cfa73be8b3fabd1c4bbff3d579c597f849a21593cc9138ece1c8b31448238b04a1644f3c9f5bd56f038a2e0bf3dc7cffb6801edbc10f53e1f6f10adb281b18d12879889f2039ccc74ac0c4ea11aa7b35d189b52bc497025f1f700c0120f45be717b78d7448f0cd19c4074eb7071d77681f830317c91d4a0b7a6c188244180e956a9c224f75504bc605da20c301c8624968418f0ffa9eb10ff2c153cb544b75e5bdf813e2d8819c87460904530b803e72240ca443f003914660694baca4e42a9ab3efd34212102ffd0830b6c0367b20bc8edb5a395636b7a612a5f17c3bad187ca1b6e8ca0bcba0e4626802172c3e085cf0b7a1f7efb901ef82b02120d0a4e4e2707a08b399bb20067132a5c1b5a547c1d247cdeb9f9f6b04bca6a2849b2a20f117e5673682d3be9f5a13c968b9d997ecf813309301c05d843c0063e976fa106381fe58e0f3226c3ebb93aec89bbaedc5642a726dceec16f73228dcee2301bd46b56f40101663a0ae8647d84275b75d77f8c9da97a64e7ddef3c6c566718b29d3f875f9d23db3ff29e460e343abe5883965fb123d1c9d3f9481848d1733d3f80f31b57e3d9c0b7e0ffc059ed9341cb1066e6f6cf990ad9a65dbaa4120efa62efec12ed5d66f3070f9dcb0ee1f7f0d9267bd81fd17e33594fbddbb92b624bc1f690681324de60a68ebdfc0dee1eadb5e7896156550adbc70e2c1156ee3762cbab739201de37914d6f657cf1c77088ebc760ae63c43334451e89b36ee19fb435b2796a31e7e165fb0227c31b032671b5f46f36f2232dfcc68d5b168fb3ba8b49451e146a7c70b3b0db70f6111bdd5bf5864cde54e619a9f8404d3f3feadb9ca3b55a585f5866beaf0de2c3789e33b670fa3371e32e261739ffc97517b8a7971e6e665ab703e9e5d73ea371aea9159fe4a35e9d56165f7cff09f3d62b6c747c95a76ee674c7f60f9af554a588fb411dfa66f0de1463abd20f16ef5801649c6c7610dda9809e822e7368bd58e7e84792782e075a7380c08a8a9707e7a20527c5a850707dedf0e6c3d5c591b7eb08595d1760f5c30f48e87ce2e5d69d7e6b6581e6f0f61b5d8b263819cf0450175d6e2b6a31d603284b5af06009a448026a9615a6bc82a0bd090bd67428aae8d7099d567a197ebc19a749d1ef026ecadf4f58a07012e374872f161677455518c18eea032dcb232f5a3afe9afff08177b5cb831f646a0fee56e117780a6783cbee1402e088760d58e7a9f8d8a07fc02902d052980d2f8faf00058d761d97efefe7251b189220cc913b3646dcf2cc42075092b2b97cd6a531ac1fa3f503b070e5e56adf5204b7fd68f0f072dc562471b0e02254259792fd88a9d86c1b3e3624aab631aaab0d28f8d04a1dbd95966937638dca04ccc8f30a4d10a6d0dff57f7522bdbf0433faf74b2debe6dfec2bae0718b0613f4b8cb15d5d730b484c18a55ed2206040207f7b538af4c8e0a41d897d93b0fbca83689014b7d9cfd2cb430b32171b30e9488d8512b882610d6b7a667210d6d0abd56304b114e45858227a1180e936a853f9ff127364b10ad2543eab60d7c5a80f258919c6691799b1e041ed3b45dffaa0cba5c2b9321b8d85ae7a05f0f99ae2bd2439a618495431302e3bd26e489142e7f3c429b725fc644a5bab7f9b4e0c97c7676431863c9610db991bc598235e18457f8d440dc12af331127d35777f539a0ec0ebe4fab50b94ef62ed35162093a607f5358f49f9a0bb36f8779ace6f1daf1f42c2d81bb17b0ce493f1eeb37c76dfc546010f877c9028d6d8078d01ff2e1d5ccd67e3644fb0f24fdab63efb899a692783303375e9737cee985cb20f8d6cdc435aaa2fcf0c528630d01647e7e1fb107f14f9bfd4b0d4013461e778dd72ad87dc5f6da15ac4877febb5f8a7173794a7218669b38366b5221f1667f0bae76521eaee06c9062a104ac0756d32958f16aef91e282ba01ea3fce2b1746ff198e9ff9b8efa43ec6d9867c863ab3f3310e0d2f1e5c3322bb649fcd0e593fdf227bb7baede71bce661089e5803ee3cf5406f0d4363b973a379c627bf3820aa950a06fabcd5de09e262772df9d809b588f4fc235c7b25d2eb66c6201e9907ab37fc8a54ae8a749c91de59a19e094893a984b9ed9ad043ecc66fe4e5388f4732a1f463189f9fb9d910abc781191f6479e0e1c828fad94e6f88decaa87ac25fbf54050532cf61e066b23ae8b6ea6ce664847200c8a49f563724641116a5662d1e6c179ae632d7730d40b904a963b96ed54875ce92329c3e36263462ff28959998d0785bcf526b4a454926ce637ba7c87179915b88c25ed6f4e95c068eb9f7c47c0347cec7762ac0ef097870d66a50661c15e35f0b7ca4aee092caef744bde889f6e0e0b8f4a3c94a5a21011aff573cd631b9747bc629c7a28f4ae71491f3345d6d02df98fda1061aa8d76cb1248bb81b5d07e74f3eea2f9ac761f6226f6cde18a02e6012cae0e0bdc6b6a9ae2d8a9411dc78d570f50c5797131556144262ca03fae4e1b03e1b0823a6375accf571aead0df86c72d858b9a932ec27b3cab269bd841af7d6b62f571f6dfa298634fa0b8d0193d63d74812aa1716da2e28c49c8919bc6f031b90027a04768f4d1c6f3daec28988120a7ea4f4807ddcd55346fb4feeef4e627f5eae173157c96dd8e779aba277dd2ac4d13269f8cdc2e7ac48472933d116f43f79c3b0aecbae44aa67bc6bd41de00dce85836ada79846adacbdee2872fdd238c3b7bde94780af09eb3dd64ea74e193c8414c5090ace00b25a3cfd2946f8d49d164ce3aae6ecba68d10d2c27749cebe587cd2ec29deba9f00bbe9e51b795f9b522d6bfba3f00d109e82d2c5fb9be2c3c6a36e2b688ede8d73e1cc803032f89ca3daa068953c30c622bef315fc4ba116b59dcff4693869f23200f5939c8b5327585eefc5b2e55418eee0dd9c62d08c58f1238e6af7803c7396c7ec10e522da288055a9b54f884a66103b93b0aa0fc33f14622ed1d2949ee071c595e5b98ab2eb4056213bbeac9820dee4e339d87a5052eb2318a55b0eaabd1f6dc37055fbeb4153ba22f25414c184fc3e87b1cf54a5eaad6cd0fb4040361a6e912f8ca3a09a90920c47fa359189b45efad82f36619e708bdba1c976fc6870626fccfd4783faffe10181de8447f168a2074fcb343b47b3347245cdc8cd1394a788911ae5ae9375740c50fcb53a5763a0c776593163784e8659b06f6fba991da2bbc4e822ee05caee027909feebe0f8e38a8da3caa807b8dd4cff9d0374bd60658733866207c1d547576270802e950c2ee85569c109ba553ab842a7940cced09b12833b74a8747081ee9b28a580dbc76f864a19bec7631e5bdb1185d7d1ae8ae319e0028b6a714a7975c780d7377ff8ddfd1ec8c0800b9dc563ea23b60c614828b01ac44284ebb20b29686c930252e743caa7bc67a0616bef84ff602afdaf2f4db861d0b48a50f8e5d3e70726ce8f2578306835e11fb58a3c026f809033203e0f82eb1e7d1dbbe3dceb2650762ea9bd7c0e5c5e723ed563fb6af0983fb811a22ce10596e9a6fc8a9db00cb0423c0ad5287ec3bb825b22f0f42de37391971a18abbf36ceae4aed90232311b01785d797cf5c3e552f7674320650d1ea3cd95d03a8f4073d53adbb3f509536d5cdf8b2d6e4aa76d1cc01e9da36e0439a1d08ba491a95d164a149bb0164ed7d2b62dfb0baf02a68d9ac66e7a1b6412f22666542d8133837f84712fc76344d0d7a4025b93315c1f858356ba8dd69f24f920c8a3c82f07df0d2a6accdf29369b62934516365865e3931f85d4651bec6c64f1d6c13cdeb3b1af541d38997a78c8d5b41ce59ce9d8e98b3b3bac7a3f690cf2b0aa5fe43c4a6f8efc4566a80c452ad6e96be5d71cb074163ec71eb7021a050b8191f341ef3cdf6438c0820a6cf1592807d975c64b42545b171b6e4cedf4b00f3ceaca55bcab965b60fd33b5f1003c9ee807143f3857edba16df311f707a4fb4fd0cc73fa244e4f6091ccfe9a93b792d1d611d203d6edfcf4287afae8d16f654975136a42c3d83fa9a520cf8e73a55d83f38e7432f6d6117885c8ed13d13b3c93ccb8bd69c05ad3337c989d59d9c3f73c15bd8f032d7e40ecff01e364084affc3719e1015fc798f4e5cf24b3b180476529399bf93b524cbbfabaaf6b5826b1dd8d1a32de079b64c49487d1805569d2d99f5544a5ecc67f8f4782b972c94f1a3327cd1a7afc5699e22ec83752ddf598303333cb70db629c006212f0272299a74c11384391ab979aed7c2ccc9603684b92743b0a3c40b3f6ba4aafe17e7feb4d2fae66ded3d7a8dc9715b0c5914d82cbc9fee59b9216759969c0db466f188f01c6cd43e334775d2cea49d38ba31032e3072ed324aa97878c183ed301ae9dc02664d03006381a1ca346ca1e3008918ba8492bda389708f83f3a2c06a03fe9051ac2faff447c34858d7df16e54300f09f417428bcfc309f6b2746597b1ea94746dc664942135fa3d1fa2d74494b53e1c3fb3aeb8a5c6bbbe7d046b6874d7da384a8341b9a79e65266fcef41c44fb2774ae8d632e5040c698ac50378e556533f74e3a7868602a39ed460a11fbcec75c62fd4934efa0445255be5da49301c8adc0d4b9972f5cf81ae632ee5c883c402aead6879326f2cfcc4e457647ca1875f67d8270878366960208a858e9b93ca878b9407885d4e9407608f78cd139b35f7f513a28ccc465cffe96c281daa47e49d7f5c9eef08687e25c12b338a290fc03b3f84b11442caf2fe483fba68f5b0bf48ccd3624283a5dfb5344e7e8852a8d578f603039a4a23b982fc12019b4df76099d03c95ee1ecf378ce7c80abd28cdbcfc94494e7d1eb2786c8ba4283ebff7b67b8c5876a18f947088e819bafe552d4066d7743e6cadce2eefe964442fc36c423f75ce3f06c43683b8fe0dba3cb8cf33606f9a08eb4d1b9e318542cd966999f469286a473b16e037c75dcb5f3fdb95a851db368d3d208962c4b7053ae25dafa7ae42a3b36e09228cfe84f3af1b4f06717ba34642fd1a42092c6cf877426659383843e986e5563139a099358d1de3f4609d4051e526fd0200af013a6dd32d391141295722804b28e3320d3d0383650c7fcb2467a7b05d8faa548e87b1734d247820f12a6d151e5a6e35a04084511f5a8a370dd806116e633c40176a519e75b030fd15a1654d5d8fdeb7972499c2d9a63b7b7c096d13b79539bdbe099c5ea80d9d4ccc6bc3323f62a0e862eb5c83adac0030a51114c16fef39f5f4179a2fcdbeb706e034e0d7360e61d63912d5a5edb3fec5f0f6044ba850d00a7e6a94bef265c3f1db0e25bec81d70adfa11a5402ea8f4996e4f3a0892c74bff4b7fcc47340be75c9e30bda20cf9cbfbbb7894b09921e06d06ee694f0574700d66acd2be58169daf04925374c664da7ad0fc7886ebd6600059fc31066e58f5f932f33d2453754c09ad56347fb8ae533d75212148e7195cdf6cdc91dc9756638cd99dc10aacdbd66fcd50a94ced6b32dc4725bc54c75432b5f9ceacfeb3227c14bea4a09a1736cc2f388adcb10ba84d071cfd76dabd367ab804d72fabc4a709e60e62af6fdaaa211843ca8b3cbcde59d59324fa2360a6de5816f3f3f117f789c7ed8830b0ec868d8e4b585dcb6be7ba2a42a6dea9ef46f1681b5f7aa7e467b9691d3161b01af98e5157fa4a989300a31211b8a940c5eed4b84d73e24266f13ed3e94b328f7421176086900c732537028dad17a49880b3d67cace1d09d2e1af58fa184911e16e0fdf821e92aa0bac0810fbdcf4d9f894dfb2789056366e074ebb87e5601f4635f0b8d4f3c04e640640d14eb3480a57fc2b8ca31d282ea19c36e589b3066b1c750ba0ec97f92ccf9f43cf2cea974b1b91e49c3bc72f92bffee82a632367337cba121db8c01a6feb8d32506fe616c281966f396faf9e036d46ccb752b7472e013f0b690cd6931d834824ec9c7f386342fb2e5036c45a73029156c4230941c10ae9a4600f4d26ecb310173fec1f8bc8ad21696cbce6ff4590e4bbb8a3b1d6ee0e02e1bc0c4488356b9e66dd20b5df687ba29cdcc5a7e24acfda7eecc236f6986138d069f0b65e9ca2e9d1b61dadac7d63f3d005cda2c6ea256d7fc0c2c59f8371cb6b94b4650b8011ee8c54d635fb7cc1da9564a0058c104cd0830a3ea54781e34251319ee6015835779b57da6962536576caeacd1075277f3fe609edd2bbd1d5d43d5b62fdd27fb8e39a91b0a0b172644eff13b6108cd3d02b0c845cdaf016296c3f3e63a63ff2446fb47c5ef400cb5697f2cce0d64c6c81e6dd8b688ad013f5f0c70bae312970463d303492166b5a772784db30965178f27ce1ecdd5118bf3a9f2544132458ad121af264eb1f34366768ff4ff613be9e65f3f96efefffb209fc82c52c81d2807c09177c1eadfa5f7d86f1ad371ce23e9781259586645f7353cd36e5c59b98a2e8c487d0178ea2fcc63afc5c08941d84f2848de98a1daa4510a1e160d9fdbaa577fb1f27c4071bd3083f4f3da4b649e8b3c77bc78e5752cf7f18e838f77bedd474a71cdcab23c856131dd4bc38bd44730f8d8b7b318de3a0043bcb9d95be5fd3fa04105aa28025511795edc27545055e5ac81dd2189ec9736f6c3f5235d894113be55a754e312fa31c28410ee44f92da13a452aa4bd27a9c4fbbcba9224b1f8a733701a4946732f0dd18771160562cbbe9e748b8021ad7755c030708dc5268dce751b5ed1044738c6806d190ae37f41f8c7f7e495c0adb476aca5d39410fa060821732172330b064c119c2a011a3283f58791592fc3e1ffa2221bb8977c240476c43a6e1f58d51b11be0d0a330d8a3def97dc78886ea62d582dbe13b2d6d660dbfb62973031081de82f4a11cb23353c0588356265a5d43931fc277c4272243ea9665417c6c8cfdd806a3696e08b6519975e0c5668b113264fc87958abf56113f61a767dd70dd8741077fc7c0bf5d0b7a6152b0fdea651ed91c0a3639fe7aa8c03948e2b70db40e1813deef26b138bc5a422646b2b05b6fa2c1d1ec170e0bd7dd02c1e5d6789d822e9d578af7e63166c789c5b9c9fc69d42f04e955bf13d69927460693a806fc2cdd9a47da9e7025fbc477f3f9c027888cb1ef2ff8795a9a1c65db077ee255856500b6e872634193c5760c78087cd2c5625ed15ed997ec9cb577a9fe539f1b58747b6d88dd678c27c0739ba9e009092a16853d189cd5261133eaed0a87ccb20406119a01c9a0fdf9ae148ec935b4de9b89f11c8fcb3f867c99be7519e5d9c1697fa9135d3fa4b083afdda0b52587808795317b2971b9f987b6f4ff30e8df9de189ec91fea6142510f3af772251be39878fa70abaa9dee9823a4d8b5153fd2fa03c38e477acc57461fd95dda27e68fc0ad1e45e8c18b831e23c248eff823ed31b8558dfe47ac70c69ef46eeceee866c36d0fe592879c0da29b064a4cb636f2fe18d41c3dafd27cbd133f682d991e1f0fb942f2aaa14240c2f534488dd7a5fbd7f1e5e77287335708c07048dc98307ee1983798f684067569ef189e17416c11f1a39b3285451b564de7e4def162be025353a57193ae85c5f8bbf83fc258fc65da55480fb4be2818bb1b77855b9a7d9b79eba8f067abaa29b718e4ea01382601b6c9dc6867601109569b2fc02a400cd6ec2fa871afec0f0cb7c13084b3f6bc03adf85b4591d34978f51a1149e3f06869ff51afcfd46f825ed16fe3894bc2d6e562e866ac713a179c4dcde18c51c32c150f0488b3695b8132aa50f9f935c9229c7b77073899bb8d2a0d781acd70cc1a7aa3c283ebe356ca625ca8966df5fbc5b2bbcbc51abb2ecc3914ea2643df5f5acd4118496131d9582b6022ca5c4f942ad78f8f2b56073899d98d2a1ef80acdf0cc1a7ae5c283abe750d45b4e92900fa8fb558d3893f81ca85ee41addabc25e2cc39a6459a425c269eb84629dfcc49fc40b52586ba5f094abe6dddff13f24d699e41342e1902c2a6492c0c3ad30c4cbd14abb3f002c6168d670a4357ee05f11c1e75d30f0830e0d08faa92d209c7b4a378224028f6cf29db6ff88aba33728309be3cfbd000a7289c4bbd9f9d6258978f2bb2ecbff1e9235879c15f17387d1842caf1765d252e33c6ce6c2a3e73999159f312627e192e4ca86f70233f5815d889bfaa3f322a8ee2824def4b495c53e13016ef0db4cdc23451d3215c8601de49049043e1fe5164ec8b9dfd5fc61d4d15813440c3dda3961c9588a609d84693f49cc9b5a8c01d201cf96b5e806cde32d1b244caafa498a3842764113d8c4f7196608d02802841e9427929376118724c2d275183926c7a2f2c5f857fd063be738f6c33a3be0446ee4fa73955b7a7fa86478da92154ecf921385e91e9de31ccf3959e5543217a82b24bec6c54f2a15080236d43fae3d63200d2fcb32b65cd70ee95876858b12d5cef697407384ab942c089cc4bffa92d781d1c17ad26720d3c727917e1ea89bff03948e882795e7f9ec5320745958471fe677cceca10c222fe22b96a06a82160260ad29124cd2047c72036a5a42eb80b549c9fe859f4bd6162d3db02b001b5c013cd5033dc82c47e3fe8faff99680d20bb03c69494441b6cbc2bfb700dd57d1b880fe2e93783048926e5379dfc0a7338e9cba79c995aef0b277996f656688769147b14f0ac6b71310ad42786b54f2b561781b0478f8e29baa5c4103a8c4b8910faa84ac43aa233aa14f18c7e5869ca77742a720380a1175129bd1f3f169b835b62f42c2aa5f7f143b17929b792c1336596f9587ac53a63a4f1b726bbe86490a13bf0771efe4e63f81b4cf0220ce9884c4bc9ead9a591f0761c87d2d3107914b1a3aa0f9bd3e9aec39f04385ae66590f6657bdf3b36c9c7d7c41820cdf13a05b4578834748e6806fb234f5b75bb4f51ba55d812600313d03594c1b35d5dde31ed6bd5d7f166929ea5a1c3204f6ac64c80a477cacb6f64a1d64ff2300408b73869689ac39f8d0853804f87e99c7ba3a2d7e1e9f0a80fdafe63baf808cffba266e750537b218e380d8bda0fd84bbdc9f84febda459b2c9d197ac6f1b4af2b66156d5468bd9f9c0c93711a61638da9078c12c57a625f0f834d2eae3e6ff1229f2ce1eef5c2459aef7830b6c2ba62db36f7cf8e25d56ddb8c575a9acc740bbecc2f96cccd530a793b191d04670de28f3a81052da25b7e5882fcd037337664eae6e07e0eecbb82774d60bfd5f4c0bd1c772cc82a2e01c24a8e2c65dadb8af3f84aeaaea0270589de088e405f4956bccf8a10317febf3570e4e9fd41b9a54f967aa030445a1b15458b7cd681a6ad7467f8d041c1a2573806a62f9a7f702f709fac236c5f281912850a7b78e40c866a2997029f0d42ef60444386c92a7a192d45c7600047eef4764a865d60e89cd6801723b0cde5ddadeb6db038d74647fa9312bc4065a47909592cb1e092eb8e3a08f3c63d4620a62489d908c0e362f10e3e8df844522089b51546bf32e6543074bb5f247e21ba631b15213acc13c086db654150bc0f90b89f3e9ed844cc74ba9faed215fbce5d714c411dc9fe12cb4c886de894b03d76b9dc3928c0c2cdc7f0f34a1c1cd12183be98395480244346169a0c32113d0421a39f7236d69733533ac5ede44f5f4530a0738680970c4d248f9de362ccd203c70290dc7f3cb37fa19062f7372de01ce955d575c85e5183d4935e483af2617574aac16baff1a247db14fd53c11241d6d745e10862b2db6a13b6fa6a57bea37ab39fb16f436467fb05044cb1aaaa5af75fe19c27857ca8c6387221bce1ce07c4f399fccfc925a18d851686feff548638906c351ae82b4f2355f2eb125b73fd162fecc0d0dca0daceb8a01e39c2237f4638043fcc63e02ea79281258fd6df3b38949afd011976a40a9430de8253b903ce4f8b3c1b456d749bc15ca1d0be60c480af91a1d039e2127b0fb10817241516cc8df6e5cf6e1a103ae4953ce38edd100bc475471ec85329b42e90fa0203e13deccfe1d0446cfaef0b2993f1cc2cd843adc879602ae4d5a4ccf8665abf02358df1d0fda6fbf5993008c44b577b5e94d8d34a60500a1b4213c7bd0ec486e86491df0a0deb5419c967b89626d31c4c926ba92f6b89fd1fcdd1367e25cf3d75e00098bd1c9fede14c4384377c5ea685f00343aeff115c4fbd6422e7df131d032bc03cb8f498016e6c13aa81cda7a88d4d714ca2bbd4988d4bf63bae4b2357cfaa7cba8aeb714916d8c7caa87826d05d24650df491cd48f30a546e4f886db2b9e26175435c92d269ae6d271ace372cb701d747f27faff394bacf9cd987267ad7dba2d557e72d4552914d750410cc775fc8f376f7d7039818f5ddced90d87b3ac61973b42d1b4f79baa6041c7b034227fcc6a18c7c1cca22b6ef286344d15bf40e522fa7d89d59a88891db1f24cede3f3621dde8ef30c3577f72c1492458353a0832e3bb60e968d11dc8436f6ba42f230504dd65aab41c2d43ca804f2b9967e57403b602f443805f4132f8cd9c1bc1fbc7b081230694c1b92cfbcf47d458d2d04d8c2bfd447a506522d02e26fdf7a8fff36ce33b574a7c60f818a03f36fa4caa082c812b6dbfe769310ad4a935bcd3da6e16cbcb0062d3020ec0f3332a77b5f26bc8d299c54d41b829f12e0c2c662e159dd23d79063046b8b7851451ecdaa16a5bd1ce96f068581066d0840ecc687c1b09745add195f5e7d9635a920051a521431825591fbab733182bbc192013617d75cd08ce06065146fe6e7708fa0697d1323b92b7a7ae452e56de8ffccb464d1931b258c4bb55c45736097c0620e5cb89f293d6627224cc75f57c3e23a4b0a43982ff0f274efab6936409fde7d9694dc12c6f3a129c042ac90506eb9b7f377101e8ddf1689c7231a39bd2098af991c9e924b8be14c8b2d1276adcabaa058382d775f814e480a43fdd847465e5a03ffe0663a143689585917baff47fe3cb8e691ba67d7d357e6ad91bfaf7a4d27426a7287f3d2433106c44712f7bc7e59cc7bf9bc9c4073e0b72708e55a512503485493e8bd2d8bc459564fd5adde647515d752d961441c2d804b451ecd96cf87a5703bb55f05be42539f2c778c08ca2090ea1a05f72c78310b4df46d07c823d510981dc2955889a21bbe3c0000e4ff76f08da6d84cce12403be75c3430868b042de31de66ae65e3a22e56a54060194918bbcbfb9a6b7f637c2b982f1221ab1ba2439acf6bbec9d5872cc5d80bdb412fb71333abac2acfa086d9792b28fa0d4e4570135160aff11f0b24681ecd710a5c24b20e76e1c55256c6b89ee5f298c43af027c890533b132855bc6317e647b30a3a8f803b74a21e890f1c4cc332443aadb0f2507f0593c3e243c7feeeb55e802aedbcdadda8d4da8105e7f848d042ea6182a162373adb886974218e0b54681aa2d4b1f148d79933dc31e68e43c26ecda1eaf01ab9626db462e84c847446615b437c7ac5b05c8a82c6949244d2a965550bc16ed726460a4348c6c92e212696ba86e0c2ee95543bc521f0ce2c4f931540ce74d4e5ce7593c504f6db9cd84cb98adb1a21a0ced2c6b029f13bc1826278cf321f7500bcdc5baca189654c0646e29cca24c91c8e60af9333de031518e7426276ed6e3c72baefa2523a66d232641f8692086425131449974607f085b91b98d7a710e355aa832cbe1a186e82182108d5983d7a9c301c844e6f9b658a6602cfc115418471ee37543ee8aa498897748c5c32e02b07f3da6dbe274863d12871a77d664910148dfb3b57f8338884822def359030e671f70e159d1e91349871a69d1cf408f399fdcce2afa277c8e96b907e0e79f80aeb7dd12bab8d8d168dacd21d4600feacee0ce48522682d8eea18b59e8f2e75af4ec7736831a5b30564cf5564fafd8d832e335d68167328e47d98be851c2798c7c43fb773b2785cee4ec1208b95d9ec6508eeb5db4ff79e8ef34009e43a707ccd2bded277154d02339fff87d0df17704feb8b54fad160504e3d1e7e7a406283ff2785f109bf4cf244a397c883813f37968915d6f4a42fac0925149eb3260893bc59b8f6029d3729a681a2c992045abbce6dbd4c1e8ed47656bba849dd4f104c30134277175b470a2d8da1c06a3006b464bb266183b14a8ba73adab39bed0e9881d6a72302209ed1320944dc241e429a98683e50c437485ad27515d2a9c2063417b9fb1b18a9a4838f1cb1becb112e2f79eef63eb53782908549c0b3f809af000d045040439e09ca60a8fbc83c30488f90bfeddd47369a299c6c3c034d3eafb64c36f2ae29120a976308c8069bca308bbb95164d513c0fd1230569e252a162bc0988c53cf84b536c9e7fb358dcfd1ec15b51aadee80e7c2aaf9f3584ecc873bf76921c43f82ee88aad635d3b9ff5269b45b32a714e31ab8354e917eb2687c3cabb90796a6fc950a19219749a0aeb739067d764badcaa43c6d69999cddc3686de35e4d445adc3a4c63c7b0cca56c01426c86a4f4d6649a580652f26fc02465e0a2f48a53a2bd25a4ad58b5eb4d0b8ae49cc9c20981b3be81763f09e9a56e325b7eda3f74f2c03d7914a06747310313855c90ed5dd243bcb2d75a34c496a04035ea96e0365acb8408aac5b6bf219b274c8f1a8802240c46e89d4eb3ddcfc502444bf4412701524fc2b854d97db9192360f0126c5233c194d0861bccccb33aa999d7179e3113b2b2f3a0a1f2125d1f533234e0c1da6e23705e7d433c408e43b482412f83e21bca79bb48dcd87e88b00ab89ed949e9a8cc2764f3f117d1ae42ccedf3593c3574a80ebe9b20a6c52da37290a3c46d1ba6ac7a1a568b126527ff33ff1cc4d7001a0ffdadb7a1351f401bf2f703f172002831cb82d00986a0fab290da8b60ea7efcfe2c0c474ea0e7d918c671350870ac77e063026bd27d8e23a6feb3d85df653e366d9ef9bb9a232eea7a134d7c1ec8add1b42bd5ea3fa4c0eb013cb384cd292ecdc7e1f80af0548273691cba8142f6e07b07ca1a8e8a15c75a36f292c65452cb0abaf11c914da57eefe65b8710289ae406946944b5955381d466fb18a5df2c85862e3d7d232c0c726caf10be6fc999358a441a585a53f4cbbe891910018f2af08b3c2497720aaf4e77ff2c90276e48f00a6a068da66385d835b3a2dd3e17cb61f67d477ceee308d2c64b8bdc1926f24d56186d4e54ca374fdb2ae83c8d617f264700535ff7b9c7c87bd8682392c553382af56914c3b109cf87e6f402a7e18c6535d798300f0eeb4381d99c3cd39b42e70216f538a44cea3c54c074e0a4c16758ac7c29048b5877ca94a51b16a201b566a3598a23e471c02d41090eab5c5dfe136e7965a79cc94cb541e0991c5cd6ec5dc5348277acf0b550f22a15e5bbe89bd5a23ac822a59ecc6b58fc875664ecc6799e7f30a2bf7dca98496d06a6949465dfd61593ae69902d749f2f2eaf61cf7ec940d4ec9f5f7d109ec11e198e66e5af669b1a8545f9b713ae3b192bbe7d265aa23c6201e000ad6f611a55c85549e70a655a092ec4cc096ec25752305439af53c46a500f59c3af79fe6085ac0425d9c50468e593013f4f66c321cf2b44d0647c38faca0372bf2f9623bc23db74e0fd5389be476c3aca2273a241930b85a13d9193336e306d0ce107d5ca9efe577acda71cf579a82bea38cdec4245cb2d1eec227092285bf5294f0ac5d8f9da2ca50c2374e98e28ba8129879520b074375dbef9076bff63f808e406cd1ae3aca0c35e5423f540e7e1e273dd37a8a97fd13b140a75bc0d944771e3d59210920b1ff2c0e6e455944e37f169388c60ce2c8c504fd8a96e5878bda594ff79f953bf0382cf833aeb584695300b1467e58a9230cfee72ec05529f4e5a9e7c1ed3c98498f6c5851dbc2934c1378b6e4cdb311f47d55e0a8bdf2f1b0d34aa911302d6217e25932eaa37f47fbcabbd8845642ba622e7ff40a78c8da56562a26ebd859989fb8b9754cf62d7413b76743fe9e1091a94584e9eb13abd788e024853621a2e6bc3621b14d7c3fa85d7f9262d9ebf4b5b760b140a75e8375485855b6aa44ce28f21b19528851329773f6729264e0baad321c1f8a4aa31a5a0ee19786323a3010bc6b671c8b62a826950c9bb1bbaf20c95d6ac1be01c54feafb0cb75a0e24e6a5f8deb2f4a7ec92e8e9a0d5ce65019fa46c5223405ec4923c4824f7105daa145229fa500a1adec9fdf3a49e684b413968d052e290ec8c7ada892cc57510cef535aa9c1ccf08cb8f11ee749ed3c502a17371cb9a08f73eba2d13f47cd494c807984a362d7a1f79b73985cf8cea3a5b8219bdb30f709279aea1ddbbaa6c1d01c691f9b2936a81bdbe135da2bd49187a38d40424f182f28fc3584ad705b4c3ebf0326ab2b2b36c39c4cb65067a59b6bd41ba541261d02e044fae35bef8fa55e09eac6ee4751472a3bcf82c36349d9fbb49b95805fa3f440f25e530f4e3dccd2e5694de53fe40255143ca537e38dd88c84c6c02d53c4801c7108f6eddd06a03ab1d42920fc8030c76a892e58023727c74bcb157d42cb95acd8a2d5687798abc149a88822fea899d4fe16ce48857433442a49efa5934eb304565490b0f743fb892ca7582db987fb2d7617bfd8683be6ffd69561ebb46444073c3110e320395025c9fc5fd096852883c02ae466067c53bac458976758b91cb69fc4095dd2f5d419df9387e0880fad33d7685ebfcd659244f438900432498d34ec4cd209d2551582422f9ba7f353fb7a542742b127a084ebc0a1cbf93f9f9d60cd8c474fe82948b6dbb5ac20b80964b8b8aa81ce72223849e796aa5904f71a1e8002a326c441921608f318970570373992edfb55064c36e979c1dc9e8704403f7e8628a8eb28a80efcd43c315ccaefcc42708d33f81076673da7f75a7e958daf68687fb823ecd34603af688daebffc8950ec55acb42e71e2cd71f9700444e5ef4f8fdcd4bd1fcd5cec2f8880ad7b28e380fba61ba052654dac8f24c00e854dc5984e1b5a849d7dac8fbb16e76afa8a1a315b9432feaac4583b4ca3a1adc03bd8a936f6254f3be40b96a8a67615da88880c1dcc6fa224a2f79f05bc84d1ecb323925f534cc342e54c18c83204f37a732c71aa1b300e82fc10f82d9e72dfce5ade38f0f305bef25dd74c6e1c5209a1ade1f5bac06cba047437abb087237691f956a6e3ba78cc7801e79c980ec06623a939a74f5a56ea6fd9b2b9729a8bfae9f9f588418b49cf288063e78a2f0a9efa120989f86380d16c0783954b677e4c975e26a79859de1d5906612e4d1db42afb1fa0cdb7bd256fc014ea6caf9b4eccd1c226c517ef9db55905a5901df8aca47316396ef26f2c9badd4d00ba545c54ef54e12833798681ee1c2a89b097d13c0323cf42d935b46787e7f04d0b54531dd899f7c243cb0debc97cdfdcf5042de9cf051a59dc4ff7fbc65f68e1af182093a17db41ff75356c80fd1f27c550d021259ed8bfb761fdf1ff7ad0d305314788678dcff3c18eed8a04e857b209032f160180c2d4f2c70bae09e94878c12a96834f06ce20d2dbdc6d227f5a8874a42a6b32715cfc8442ab6d71a243127033042a67bc162218f502f5ab21093f6d9930cd4e707f21b566647a10ac0828efe627400dd942dba0e3eb32645ddc13ec58380885a95c604c49e4bf3a7e0783c840a953e7f62c342d0a93e8566cf1fa0fc36a2ca9ad23a4db6faac5fe9df6b87c0e5c3c9fa407f4eb5f997bee159faeee40aacde00e857f29a09ef8ad49fb6932d0ab00e3a24b9e17a8b85b40bcf3782c420bb4c19fbf21112b47d614dcdcb1ef7cc5dcd04041daf93fc8235a39e71eae80514bd98ce86a77a9f05615ba80c9bc7ca3c91410f15532070a0f9f30a80bec8b494b5d5306c52d3f7f1e2d6bebcbdfbbfeb5fb48b041b4e0370183ccb749b65092e84cbdc38e16ba46102642d39614302693d0033ea4acf83f5a4ac09ce01eb87fb316bad172529dcdd6ab7e8ae6be2a29a4db292c22b5ffda2dc8bea4005af1693913a6533f734dd5e3dd1c83f5c0366c77284ee4592ad8140694970faab341116239023fc7c6b0524ef83563d893d8bdf926538dc742386d3d64279522c4c904a247204edbb297c961a9d2a79b5932cdc69617bbdba5a341897bb4d6818145834f4327441ff75d2ed6a85a7d1a269cfc3e2e3099fb24c4a0f7ffc7827a63352c435eee9daa2387d9c45389874968ab84429daea1ec982d2bdabe91e3bbdad42b6160ad51aa54c1c8a1d604b63771b36b42679c6d89440254aef07054da6e165a25a2c065c476f5d4e9fd1452ddc45cae3663812dc55e0843c461d086b40e8caa3155dabcadf5da9ad02d4d8935cd8a6df5f858d1c96f3018efdd6aa00a4b9fbe0b644bac9e72d888087ba78f5518d709fd36522ec1f6922480143e3fcd68c2d3b69e462eeaed11044fc58a8ee69f9bdadcf273fe8a61f5da19c0b76620f4e4d54cbd11a5b485d6f332a4fae0b49ea732b7b3cfb86e545ac0b7d5c348ad8fe3d218f5e9d3b4601a5aab55872e11d61b926f92fb93e3a74d1c2e734465263437e0abab23177e6c47c3243a22190233ef538e19589114135409d2aab662315d24818367a05c9ec10aa98c615fe3145fd0a58733a9e4d52c8e47214529e2d40af7605ac47175b6ead48cb4b57e5c2d6c9e60bb7659c0c61984f656f3250b07600c666e1aebcc6fcbea44eb69efb27949901263bb5e35e2b8f62925427084dd919e2e19a04b052d9c9945804e08163ea975867779a3232fd632bfd9fd388dd145a2d026a02739c0d7a3386e233accca2c55ac0b2e0d70a8fb2df273b6e9521c8cc40961bfd51ee16ab9688f5ca7d09dd5fc9331e1b1e5b4cf419d3fd99eb0f9a848d78e1585c5f7e8ccfb10442fe1899475b6ec36574d00ce63c1d56c4db545d55d717be8392853245a3667096555a515e08ff7ed4482c7bed76f57b7c9b0cb1a377d87d75d9deabcd2f163ee02e0f3f2ccefa1b1b18ded8feba61ee95d8207a470dd0602d73c875aba9e25d3d4810a01a458cf4231749f710fbf4cd31f61d118431a7c2df347b2b852fce13fae3777cd326334188905da6ecd93d3786af515e2ce1c7aceb95601d0fc598472fc23cb1bd1e8a28d2c52708ed680cd6c4570786780a82ad7053f70dcf9ce27aaf636a43a2b50b827cb592d4ca4d1a2f52f795cbb14fd55d628c7364b909a5d2bf762fc159b47e99a9ba5ecd7a8a60439918f4007c15fffc2f4276604ef96ce7e9ba331a61de275e672cd15bb8c886443afec7622cd88fa1762f1d16c9201d926391ad7d66073f058074b3cccf756afe83a085b85e624c7754c3716434d4e3c95f702870f49aa3bf79f961a57fea6a12c7c891d7e155887b79908b67e88189aceb4b270e7610b54aaaafe0fc8c245eebc77b03072f13142d1e80518acc2f4363ea9d6b64c5f24add9e5b4ed2806e17c5aac3dd81f53ff57aa4e5941943298deafff489d2e0411fef34f432a526cc0ca27fe146beb4cd9943d4ce2bd661f7555a6ddfd80d651b35ff33289a6a5e72c9ff2d4773da196721f893111a73c9854c6ee17d8c87e3dd4b44894858512005b6f95769c3df0e4f56d3ec1b119796ae48649ab2666eadca4b46f22c4a700e08b33639c963d28802b64370e429452a2c8e902321705bca24098cab9e34922f2c73e45168989867004017e31c2562c03e90bcdbd2b6ff6c256729c151c397921261bf51aa91dbffa7655ebed99b58b3fa0202a70b587cf6b1194859b587ceccb987782936fa674db0185951bef812ae6f897b823f56ab71bdef2cf07b52c83530091f10d01d29e195fc40230f900a6023122b1c950868a0e47461dcbe4440b148d43de31d364e4600c20d36b0cbd748bc538bb6a468bce4e5e5c2aa718f92296846e803a27d13754ba6a549a2aeb05252df0c142005da0b17a1521038ee361d7cc73e20f87928b4edcab0e339eac54473d522b2fbdf4684f5526bcaf5f26f22644bc9b1a5dc7d24bbed24bbc9274250da0dffbb102afeff1f6126aa41dc3142a15d5a557beca8856b53a91d29230a100acb090ea4065cd4e06b70430d36a0010d68e0001a20a0e2eec469d142c471dcbf376789b4ff354b248dd27414b178c27ba4f25da8976737953378330316cc808b19e01948f9c3057fac718e0806be0e3f7f7771c7692ed3fc47113feef0830e3fcef891851f5cfce840062670971c8b2bd53f9d6aa61fe9a45da33e55104b6ee824874842259de31a27a75da30e7f5b6e76533258f531833ef4e8a3893e6c1fda1b16b8cfc0d7232d654caaae51cbf7384eee68190d92a6d28e34ed60ef5a0dd2d7837b67dbd05aa9e05b20692ad14d7da4896eea437ab2b1cdd5f5b11d6f135fa0a5e1f3d166c58799994bf221ba4fcac790fbe443db3dea70277ba4d97b64bc0737f788e27b0c197ffc1203371e8335ee33969363606616032eee3e2b68bf4ec600003070e33ecaadc7d64cc140097787814cbdc08c17e81734719fa1a5a00b36e0822d5cd07247a15a9cb75372b600052d08a30540b48089fbec66e0159a9e9de551d3cf29d9e3a6036e8a70f3f9bca3979a0fe2dca558c0011614b15940030b06a0471c7aa071fff74c9c3ccd7fef3d4e9e662c63d3a892f3f56061057fac408f158c9921fe6274054756e0810ad850c118f789e28a320d7d54929327f95bf6930235526053a0e5e1461e378f13f090001e3ce0c1040f137cbaf455c959d459f163f5d297056d953f56bcb50b2e486deda51783a5595f8f2efa594872cabc308b9ce22867a0ad974a17f622b3a59ba6e4ec2c48436d4d7326ef956d479aee8879f28f956e196f77f8b8fb1d2314b42151c0030a48eefe76dcf1efd951666a1bca8c3d3b4477fbd9d1e4046ffc046cdce70998f0d4098698600226f8c1044d7c96b8ef2e69ce40b104af12e8d041822148b084044146f082115431822a75bca08e28eae0a2b3d539f975de7aa42225cb94731d2411fce1b3252444d433bf7389000d154116116ce033efd1254f33042bb801820b022774b4800e29e820820e1fe8d0a1438439c298439cc3670ea731cd9dee08d2ad479ffcaf97cdb1bfdbc528d4ea0ae93ddb5646b74bbb0d45344729bb33b0d2cff5a94a9ee6b3e4cb7af9edb6b9d37766fc81283e60c4079cb8fb7c010cf73751ff6dfdefdddf41dbd003683cc091ee782d951e48e2b33e973675b439b3f16dc3b581616a1a4b75008d0e8ceeb347cebfb86acd494d3f9d1dec5d150782e000b88121362024471f727821c7147210c941003958d0c01b1a8069a089064e19e04006c064e00806e4d0f9577e259cce1159da749b284ea7a4534d5309494b2a889328eef7e8b2796f2aeba5f8feebda57fe90d351e2a9de7ab6e2f08ea6bbb5a50fa39d936f6397aef7f3d6ffbdec27ffdbb1bf26fdca1f840119d8bc719f27ca46c546e7027b5ce08b0bc82ec04dcd65fd5dc6401718c1027358600d0b1459000a575f58380d93b34bafbcaecd2f568006eebe8342b59ec8308fa6dd63a900100a5060e75c1c93f552cddd2b145061027568d052cf0582f841fcc5c2106f3a012812c843024c4840058338d4c411441c49d69060cd02d66c6ba2709c04c1ff4a4313c7d94ba5e9eb7637b6e4d4e1d865db5d2b7be4e79e12a7290f0a45c5994b6a6dbf1649ce3de24cb5f554735fbab525498e93a8fd1bdfd9a51a0e06c0d1031ca437d8bcf1c31b436ef8e1461b93738d7ad3d4a4a3c4c810a764d3f4964051a412ef2a473cebe8ee463ca3aed3a59e4afea540339c5d5cc7d7a2ac7fdd783798f8d4b30d366d9c996d84a9df8696ba6a43aed8a0809e7d910c2dd6d2f4300bcebe0a1ba835d678638dbc860a6abca1c6125f74addcda47253fdb52a69b946ba552e7f8a8a47dd6ecaa915293023563a811424d14351d7889a4abdd665f05856a715c4949dddd7bde67bc6991de12efc9e9d91771126fa949b32fca6fbd4c3f561a63bad04deb16d9e5d3f4dbd265cb4da521e651b6d288e29e061134d6486d6aa1116682b2a231c54aca4263883ca3cdd5bf774afefeaf75c619972922f9baf60c999f3184576748efcca896f69861c694b9393304e0ba68db11b70ef669faedfcc6e3974da45dadbfc559eeee6f78dbfbc2ddb51d98c74de7a02d876051fe70eb31efcfdfb9babdd14c0617646821a383084020025cdc27486176fcf2a76d5d525bd4bf429cbd19f830ab47b0bbf837856daf6bb5fdb6c65f2c023a69a8c45b62af28e398fcdf36bf7ea7f9d2ac30061d630431c6149f5bf6b0575d919e4a940fda2ff6ed8c6392a39b566e6a4e6fdcc45b5edad11c7299e66d5d9952314c0076927277e4e4a5339082dd7d56131d25a31866ec46923a86af1861c4e0de93623471c722c69030c208e3ee9562704645d9d930be30a68441c4dd1d4d1da5d85f92fcb0a049e3180b1a3268acb897d090c068533299aaddee17e12d4dd56e261349ea16d04abeae05e30c18a2fbc679080c1218f87ec106afbe18e3eea1f551c92f3ecf5af9228a7bfd2f8638965eb4716df2228dbb1761bc88e2ae517b41c4dd939cb9c3ddffbd8b71eb8c1af77a26ccde673a1f155e89388bd56eb9daadcbbada1d087c01012c20c04120c904411b33a568d8059a2e74e8c2e43edf255573c430eac96b1f00c703c8b883d4545f6681e469560b9334c43d0f78e2ee332a72d107176cdc41ca05145c7071ff6d732ccb8abffda1a4526fe1664a2a7d54f25aaa7fb640620ba22d4c55ef67699187166db8cb921292507e2d645a28d122470b0038800c07c81cc913f982874da79d27f28539035fd7d60c669c9a3f197b3b4fbac74237fd1bc366d98ab2ff6bc1abaaffe0e751dce0b899299332f3f93433c5cd98662a0b3eb250e373cf5ca92cc6a4b298a273b2c082cdcc58d6c7428cfbc5789b40108b28ff7ad0c26c167f539076fa7bb0203293c9dad30010cc9d4fd32920487b50a85603805c71c615e0c59d150eb0a2b3a2481520a862892aa050f187fbe440fa594b7cf36bcac3490fcf8b37e53e7db1b51dd69a4ae9fa3ceed1937ffa3415312a60d0a47d3f9cdd1dca8465e4141a986288295653b8145f485184140490c248146da238f379e45adb963d274fb3a39c3c692a664e9ef0bbae9dc9f228cafa3746451d450e99109041e3f362cde527736200081870c68d18995b633065c4889cdffe8babf46c0c7fd2c47d1e454ece5c78de2b0c5802c51c505c008a1e7c7754f62c4e6acb3df1c513443cd1e4892563ea18c366cc6c4c0c633a70028d139c133f4e0869228d6b5348b5e962fb014d9c7f879a8493afc7ad472f239ec9cf39239edd2b7296380edb909ae8f8b2ae906a5b39799a2e2b7bd0c3fb61a28b9e26259af939e961fba0cb5efbe9cf9ea4f2c6a8c86a820626fa60e20c135a989895388ea4b32d55d2124e2cd15a42b504142550a0c40426274fb38886204a0fcd9bc73dfb4f86672e907e0641da29212a31c5dd5d0922f95d92d2a12460b0f3bb5e0a0c96841acf2be3b5a69210899288e24948ef11479ca5b09068816b29637f2b889130e38ec4870411316a4c263161b670911e1633e4de650b1789b7ecc2650b1731ee2f4df58f50e39e3a42d685cb162e52d38eca23a21c31c4ddb736624d12a92dc71911c69d869f8dd0e2d2080fae0dab1a2f020ce7d122a67454ee4b3b0a93f816e14ec4993b4a0f13f1799e720d8c999dff67242929284d128c0866c80f6c7e00e3e48715c62af5b6da0719f86086e34a3317a944f2819ba61998e9fb10c57d20e26db40288f1a939ed615a00d10b90441680480f6e8ad4a01e2af0ca5241a11dd5131ef0d078a88207301a0f3bf0008396d17068882434eb1b99d364daa1c90e426678ccc8cc7cb4999312c8889031d162297822e625464483b1a1c14477e794e4916322a140912514cac31b57e9678e5a98ecf9f6ebc81cf53df2207deda21a83336cb2b0198c738c0d188d18eb48726e8893279410b7a3d0f613fb47bf40b3d1f4121e4412a2f25f19b4b1f1cb6bd7c892131c3d6d6797d2d8a4337a6754dedc052cef642379852f2ff822c517f18b00be0cd1c435e2166d108fe00de028b0156ce286627f25b7e28256f2881c0a427ddbc6ba3bd3fb5ffbb50447ef33ed663735bbf4705b64b59d7d61903b71f2bf967c615bbd394efae8675dd92a583fb4db5ef93cf28af6cbb93cdc9d2b42c881508a50873a8401d0c0158010702f713a12ca8e8e92a1eefe087a976657d07b2792d4d7f2703a252543f2880c9247248f38ca3d8a32e312a7239f4892e4f4bcf7431c8442b562f816dd51d4a6084c11931a7861819729bc78f1628297c9edd75b7ef02fe6e417d18d4255ebc3490f93e4ecbee28e244325f254da7f853892e4662e89df75df74ad4de3d222f1f9abddbc6dcbfe7e7c6c7647d35691a6fb137d8220adf75fb1bf9fa5f60d7d49fcbb6f887b7da571ac5fa2bb6baf29547b79a0478f8d53d17a66dc7a9ad7c543bbadf7443b215d1569daf23c709fdfc6a9bc7fe6c1bc16f759bf05774db7a4329c5d7c533b3b9d9d6d8b42cdb60de9ca82b4a786f11a561edf609fc5fcb504efd6b8ef4e4cec6fa7c589b8d63599f5377eb9dc60d7197797a85d51e81b77ca66d232f4a353521ae5eee8bad79c199ff4e3c4c971ee3eb5dd5b1dbe95b91bd78df566bcb74fd36f1ba265bfd2c18dbb7fa5a10e6a7430e3ee3ac85c071d485a97377ea5f6c0d77fbbb4f12e69ba88e9c2b97731818b1a9f568fe122725971f1c067cdd8f3686b8b085a3b3b20487b3e4dbf1c9ac841082d8727390869e3ee9cce8ff7c3382c252c242c783f1698c45be2fd58b8fa5870b83844c1c1c344f2dbf66a0943d3f2458b122d1bf8ac1777a6cf2f2a3598a5882c4258fe70ff906a1bdb72d6dd97178bc5a2baf2c6a7a4d6753a497a450aed0a0e5760b8b281bbffb8d64a23c7b5d6189f5c890b494552dfd7924586454563915006d113d170430d6e68e30628b41b1070c3e98610863a303466680f5d195a3294047bbf31ccba42dc91a411230f03312cc4353f0c675a2fdd277c42d54b4d9e0a871cbdf4c16e4efa1b5b11cb9394bb1b75c62794a7127a2344874fad337db04713a222b4c26acd8a87150e2b9c2037829008ca62a50656b8702adf45ada65fc6401f7c80b7acaaa28e0281967a7fb19c81a7193803abd451058c2a3b548152050054c8a052a9b4a870a0ca808accfc4b5119739c947272f96f4c8863a9522a10a6d031458cfbdc188f5f2475725fe212e96774d376cacf942152ea904201f7c99594c817a47452a000a500e88c06f404908fbb732525f5f459a4f2f3eb5a13f79b7e9b33ed4ee1cf057ec8f8b13f3a3e73f898f1c9d5d77d97fcd05ef189e22344ebf1a3e7fbe14017dd5a8ff36cc1737970e011929223d5450a875400a294a14521e33e7f6398a61f952f0cca23b285614eb2a9fe6fcc5d53fefb0ac74aa318d16cd843b3410c1bae706e43a1765a4f50282de23cd4492852b4e1849d3740706dc78c9da29d1314174069830028493428459eb0717fd045a5bcf4db24c995c477dd94c7c399acf799eb2a95177baa59d451f0d230ff90131a388180e6240acd89e884086a0d4aa35ca8610635645183026a58a2d500a409174d7498725e2cabd43913a12657df25f5f8baf634631804b1a773f61d7f63d826d20a627d718764b62d4ce27b923263e9c49513dafdf9927e46f58cde3de29bc73d0341da9a8120dd6fda56a4ddce6f8cc5442aeab0951d5d67f462d8cfa8ded695b72d3f0c8320ce349cf1a9d100c669f8dc7dae341ae40c6e7c863433702088b3dcf4733243139f4cde684cd84c26665c6312041326f35aabaa765bc266c90fda921f9d18e854a1b3e76b2c8aff45270cc4711c57afa6a34447889233ee3ea5122f9a121692c8e13edf4a3a0e6949a448c221a10249d08c8136f5986c689301b3684a9f20955883d4347f5a532cc5a54842f2e49aa7119cc6fc08d22dd2d4658b3475d9c265ca2c5f3b79719fb1d85f4b875ad95271cb7ba7f5c485411e17065d5becef8774855974531f531af7a999c45cd36722d1d6113747cce0bbad76444bea08be462ae0ee931af162c44829052534d3c39f5fa4ff75f2ebc650d2fb60e9c70da98c4f5d2ffd70de5f442d156938bbb4520c8aa37c17c948ce0672d2b8e9756d7d994394f3022757a9292dc9fa0952b5e40f9150d04a48fafc58b192ea913f3cb225b4922dd69520c9524da93ba41d9d25e3ebdad7b5328899325cfc21d632c8f115831b8fc10cbea918448fa149ec3d1852308871c99d73ad74225b1a0cdcdc74d3aac1d0c467c652a70583b6a0f6c299fc3563ed05cee78cc6b41792f8d4a5cf3824c9d9a52eb4b156bb30c6852c34b6f3a44850911634290229463ef1d99303496882144645db9da854b520d35ac8d2420d1a0b24d058f082052e73069e2e96a6017cb0821a2b3c405b01b642111526a042102aeca8b08200dc4c0e0469779af7c1936ce790c3150241da238fc81ce411c99940cb150909c9c929e1e40cb47283e3cf2d53550a69b4143e051c525081881d44c620e21141c1041a0a7368281881c2160d0519b41332a09dd0c309f404124c30433301029a099cbb5771cd04134ae8400940b84b234740a9b7fd31fcad51a7df4a9448941012953ccd12eb8541921047925f97e96b39cbf45a0fcb2041cab166ae6e4a1649883399ae903c4d79baf80a8b1bf16cbbd882b45e9264a1b84dbb1249ead32963a9edc5527326905a8ed36f33de3825f2c4490f7bb6b35b5b9af1937d2d163fb4adfb5f6ce75a1a8edab83b086e28ae8dc4582ae6b836e28a341d25a159d3d86848d53436ae69466853b6a5a146c49dc73512522484e9522490d0c4672ecc2281c86caf48f049451ba2461b22f3d9a5720ee1b4214d7c081137ee3ec21a6d046d04313e82d81a61c87d6a2324f139c2100f001cee3e33f6aece63d761d7a87750a8d6932732cc2382024468a285604708526821642d049f2e5bf6885d5472f2b4b98935005c400340199f3e2a799a20e0a1814001106220d4a08190c2076bb40f44ed03e92ee5b7370ad5e26672729fa6208bab97d31e1440f3c0a475a087d6811c5a074db40e469a103c34215a68428870774e9eb69ed59ad238a043e380097727c1350e10a071e0d238b041e3e088b60107b40d88e08888e41199a3451e915af6b3b017fbbb3315adb60100b42027d08268a105e1e25c498b3c2259d8bb56e764fa608f86a387866326f6f9351c1f9fba560d881b9f290d48151a90253420d535ea39b56bd49a6fcd5f9aef68ee447311b48eb306ce1a6ae0a871c749c3090ed47002529b3796ae70d41bded76e350afd3acc54f515af787cdee696ac97a250ae70cc3d408478d0d23d86dbd614e41e96f331f7d968831574fe6df1181394830b599cb92410277082746014c4e4dbdbbc71d038c30c9c328078808c08a4c11903470c202a18e19ce03acf6fdb4c916811df2b2c5126a6f6b3f2b3f4088a796411cd469e2944eff3604fcf8b423db15f89619e92dfd3f75f078642859d2cecb4544b87fe81a6c6db8262483fc671550c47973461969c1a6b10b4ff498ee3a493d211e9e481a4117944fe7b1b1429dabded079d9444bb491d48bb0d8a9ced07251224d2b4f598398e93538ea04b9a4aa2dd24a94f33f08ef9b42fed389086595ffcfa2cafdd14a4db25da0d8e2137db36e36cb10ba2ddd9c25c909c05c56dc1314cc917aa8a350bc3d167f655364bd79ad2fc884275646a53f758a4e95e0141da5365604693814efea1700ced832eda00cb0426ffa4233fdf91094cee9ce4125891a654ce8b4d2ab9351dbaaa7f79103da81da18bc4da1813c528116adb56422a16d10f96ed474a8a48a8c5da36d4c7020f3a9e0b7ce4614316d3a886211fa2fa15f7ec61420c56c0ca38e79f18880141da33d46406166b5a6f2492335370bb00d46406ad5d6832038b255f724a912e9fa9e9a6f5d3748aac7fc72ccaadbf829834354acb20df98f262fb71d8bb1b5fe9595922c9d720059293d35932729cdcb4c571736b0cc6a467b99289c47defe1f7b4a579bfc0d3fe5e16944fc4cf241a24b99dd6132efc6f7bf8b4478caf0cf3c839cb38fcf074adc48287eaa8a768f291738a9cdc4cce528e1669489272ee512c917c54215d752fb2704bd7ff95eca7e7e215ce9fc3c5abfab1fa5fa4934fd36ff5471e7678a00379b491c718799cc9238b3c92d0f210a3e57184bb886529069244224b3148698a41a2442c4d314892942893965db6e441f39022512512450129e1e1c2c935147c71f72eec2861552bfd3cfba20d07d7ecb0c056353b82f04da4ff6dfbb59659eff35647565187835a3e61a7057b57b42d1bf4c292774c4f32060241dad3834281502dc68242a150db76bf56fb6d56a49ba851280f7cad83eba8b78e1271c4f9b58976eb28f94e65ca3b28140ab5238aa9160a0583d454d23ca69ed03cd22b2e1dba3458af2dcad80b05e94e499a74968c54c68ac38caf0db7df3477dbb561c6deb5fbd258c53dae190ddad64bded95fd4d95dafada2ff3d190d1f665f19dbad71b86d2aa3a14fd8c92eb63ab0b0d382422d81d59dd24eebc996499318f738be10f6713471c7370e0fdc676bdab8fb6f0a4a8cc7fff279cd185f2386b05f73ed1a2270bc81830d1c625c5b38b4c021251caf8b73ec0d36eefec6129ef3f3d37a5dfbb5bba3f7c6e7daeec0be84d50d99e64694531b6fa6ab8d34b30d31a936b44879536cbca19ab261c6ddd9d0f8638388cf35eec0ab35e25843e677d4d6854197b84613f789576ab4d9f60387d410c2ddef98c52b9f9a17a8d9424d4ccd15351ca47182f9a1694ad1ee34ba48438bbbcf99cbf4ef71a2dd9c894ba591c4ddd1d823bf1eef48f3eb71f64574d3fa8934bfb66ad190cd740e1a44dc5de733e438038933729802ca13fe62120a14694389244d1ef83aff8724b4dfe95d72b6cf2099f187bbbb7e33c6980184bb7bae99b1823b87b7ac20deb58c31cae8412b8308673f0c71a7c16eac9f4732b0e0e21a1954c89035c42f895d3468ce6838bb34024958d722504ad366062a49c979b1c559a45eeabf8e8a3a0d95343d5a1a20639c1903076d8c13c41881185e8821c6dd85248a9b331a72f23467607e116791861c87e28ae80eead1a2c538218c3bdc7dc4482651180a08a389735ac45b4b347ba0b9a247e7e41f421305cd0b683ed0c0b8c2b9c9f9e86fe7d11371ae5f673f0fe78709859d1630a23818448ab0d4be78f34519908efb8b6f6a4989a6c89bfa6248fb6288bb7bf1c60b365eef6b2fce54cae3c5e7ee45157777ca53553b321a5e1bea4d46c3edda4df61bdef5af756d2bfbadca2888b76d65af6534dcb6fc22fd6ab71dd2edda707b11efed5abcddf1da7093d170eba24ceee2eb22c97c180e1ff0e662d2ea016ca47c0018779ff582f87b40137fe3938b351f17613417a425a4d212494a6dc1c6dde7de628cfb1632ef6c91dc428b3a5c973e93e4901661a696fd48906e4f8b290e789372801af7300ed0e20069c68d9934939a0183bd9899e253e798f1c0bd278b2cb52cc2b867f169599ca06989542d1ddaf98cc39d7f5d4aa4f58358940141aa612152c182a4f5830df84003c8b8bb8cd66f80ea8a3793e2d7126351db2bc8f8d4207805d115292b5460451bd72779313559797a9615643ce3d00a2b7e8f1e27afcdd893f58be8d6559ca9e2ab8244051dee77d436d38cc5f05b549ca99552d1a2c27d72175b8e5a58993365a894c929e320c6e2cc75d22fe229ce80f89b4236a720798e499d31f6eac52e292620c5769fa58c39d2b6b297c214c51c5198e151acc8fc41c68ccf22acab7565ecc9a96ba631bc6517146a8ba4925a98e9c970d895b147260d03bedf746b060c71bf16f43cbce11757e9e759ece589a0b8e34128a4703fc16cf62ead77dcf01e69f758c49d9d27f5629e27fb59f5b57e508ff545bc772ebed86e5b7f0c839b8877cd34f6790341ebca3f74b1d57acb9807a41befa41e74d1fb5f0c57951de34e63523a61c6dd89cf0922bad5849a591347b8eceb6d62c8fd2b6e42ba37e1fbbe66828932eeee4dbc3d4abc352638cc8474778977de4b94bee2af385ce20525ec50c2082582945841536248c5a11289d23c3e5247be8b2b91f4b6f1ddc2ad9f35e57e97d4346fd9a366202c3f8c66597376f79e47efe8e18ac324aa48224c124490a800125e787d0e04e94a6a2b3d3b034ba68d74c70a6224c02001b4af0d75aadaac3731637c26a6062fd527a9f6b561052ddd5f8fa8e308315e0a65d68ef8dc9d86471c417277bd8ff0e0db4694c0dd6b0f16f95fab836dd96f5f3ef760d9f7f7c59d11548c40e1e7a7a5ff6b9df417d183af8aa0a10822ee2e2b116edc3d8d080710a125f657da4dc67e45c40cee6e2f0d65fe9d2dbfb855150ab5001a16408202ca50c057ede7adc730f6576251d64b53ef9a89f22fc62ce924534fe2fc5914e044012d0c51877b9214067a71882886b8610852ad29240fcbf9c3cc112601ee9e63b5528912f2116a6971d6daafb5a9aae8b56127d316a420768533ad411adaeeeb4a083c8448e342c87c0af1e3ee60be02e651f662cdbe8a6b1cfa8a83642fd6571c6eb2974e409a99806f2740babb6b41bc3185785ffa0d05b12647288830eed3d3d2490cc75a5f1043ee3e574124a914012140801a77af35c5e12f860016028e1ce00fbc451a63a150ad5a2907c3171f008c033c71009ffdfa894e9cd49a8af5d2fd40fce14044008825420b84101026770f5f1ba00c03fc60002aee735fba658ff7109ddcec8b441a63e1ab7f06060ff70fbe96175bd867d0454f1ef89a5a2b0b3795f9877490102886e0e2ee4576765a4f9e487cffe26d4645219bbec185106990ba0bb12326c2288c1761ca8cc280129593939323477cb1052d1e521551fd2ce9cad6a4b16c89b845f56bf0e5eb7a19ef975200e9e1cdc483f4bc1e99f14ac4ad6b7f563e193febaa7e563e3f2b9f9f95cfc536e37a318fd0c6abfd38782a212c4546838262187c9efd2ccdbaf46b6529cfb3f51854ef88893ea4ac9c05afae9da21f46df0a6ec57e563efa67e5b31f871f7d7efc72ffcbc26305b7b2d0a55f4bebb772319038dc7dc7473f14c0dd7f68f34319eefe1204e9f3d31aba424424d423759e3edb82228bf51bc3463edce145f66b59412c1b90c4146e7cc0800f66dc5f909b4a1d7b8a0304032737c907381d903e864a0823c36275159c0dba18130512fb3eab0711782862c4830e5dd14f5390c5f9ce1329d22079ed8b86569a34f54a2d2121a2d917cb425f37b2f02a7ca27b85350333fdb994a83e0c07dd2b9776140b5ee1915e6214dbee2e379d7d512c8abb974cb32f2205e962dbbfe95ae9b5d80bdef0eb330eb72de370ab17bbb47e70cb785bd94c360832d26bbc3217b9043b53116f8db1b86d1cb83b079e3384853ebe88220d5f70c719417ce3b26f218810bc47a20c328015dc83a8104400ee4152700f42c43d080aee414e700f62828f309a113653827b905110214148700f32c43dc808ee4102e0235c47584b1011dc838410240536ba6de83caf98b7797721fdec39ee5ec6e88e10040038110802827b900fdc8378104448284389a4f35c22dbc0301215a483204246452570f7d179eac05028144af4919736746012ef1767590c3b2d958243408122f3d805a152221561d9436993264d92a10769da66ae6d9b48f67dd650a7ad4f0a688889423d4b826327533ed2e6fc307cedeb5d31fac5f6cfaee44cc3fc9bc626d5535b18d5b25e17a6788718a43bbb689e9f0dff136d2829f715f7c47ec56dd156d78c6352df940dfbb3c8f936effd5d386e8b7c2ff6f7c16d250a9571b7895aa2a4feaecb8f8f500f0ab581e0c7b674d90256fa1f3de197c6babe05aba4aa2b339efa43a98d577895c2abfa3b8cba5871f72236ec4b610f3e11b7ed7f7d1971a18117a9344c2533c9495fccc572f9f1595fbe883b2daf65750fdb8ae8c78ae867b9a2c61603b87b9159def4cc072ed688e1051b3914e93cebfda28eba463910993afb78518618568c70c0e1f507205c7cb190bca9fab987055256fd8db15cd9783524a341b3becffcd7189497869e87418c7be6499eb6a6de7faf6be56b1d8e582668e9be2f75b65fb2c69ff1f72e0f4f1dfbfb5666a5202d91640c4fe9e8fdc93be777a9303075892439ce7b5157a62f4941ebb18086543263298663952b211615a9f5144e4ebc414a24e7b6a4fab32d86cfc993134ed32cadada9154e9e246a7f18c3f63f3b036734367b571639f5136048b0f70f506ae75c6db99f22eabaa3bc92165169faec519dfff5fbbe47595fac2527eeee1539b52c9162d8cae3d5a7e914bcaa8f7796bf7895f14ad73b02bdeec6abfdab2a8a5762d80a12578f4a8a9095036c514186229c04d11f0e0a1bf8e1c08f047ecef8a0e23225aa088fca8a44a94821fc08d1ea6806da98d0702589868370e8137633c0ce41ca0e5d94d9c6f0d2002046482132043eecad88b805f4c6258a488888e84716295204080ca02f46406380c478fe0d8944d547a237d33602022514285080a400e96c5b7f0b3bd94f113f3b8c7ef00f15f7d206d2dcaa5febc8e7012a8c7c4c40d552f15e8961104c01197284fbf551cf0f3d5b7aa6f8f774e0eea88de78c11cf14231e1d463c59dc2ff6d1295c4756b575648d526ea4c8b8c475d474c375c475d4a914dc61ee3e2bae236bdbafeb7dbde13aea6d739c276c984237add71260c9122556cff4088a1c3abb463b0770f700f86867dcf9d18e158992a64da274cf17d1160995a40639dcb15411c2894ad74aafe7e10dc4f9b76ddb9a7a783f6cd4dbb68114572740fc88112aeb3c434d631df52eaea18cbb447161c302e29e867b00dcb87584a00798291ea43103306548225c1b0124a044248a114479e195060c0e97115a308327c4c4c5cb05e2164d8e60f140140e7a464dd6709f1cb70110006cc0e9182dc161d46488cfd1920ddc5d0d8e1eee382b70c751813b4e0a2e752158e4084122244b8eb1e4d4ae51f3081163c5b1ebb0f4eaeb91056d83171499018ce7e18e8387071d0855ec8e73873b0e0a70ec70c7390108b8183121832f8dfdcaa760c25d0b5e8b858c11130fe68f5c522814ca1dc704ee382570770f70483002e1d321e30ea4482789ce13c91218922eeb116861ad8454ad9ed5152a9b9654d0e643b4219958f01048f3c7f6b639d36b254b0655d5fd22dc6a818621ee9981a238b2be8e3e510f167793bb91d154010dffeb344e1d227097784b3db5bc98e63125330692a0ab28e3584c8ffabe7e8d3f1ce4d4a348e5587116a5112334f63ca2cc860fe90a4868647ae2ddc5de6d26200eb2429c8170abfa6c4a74df8a8c0669190df2b08c069172a42e9124122c758efe11da78559faee8a63eafebc2204fec57f38e32bf38759694aa8a44f2f011c924ffa620d55ac41aa478157b208c5b5795f14a4683ea67bcdd9d0ad723fe8b73fe196f88612bbfa98f27b447a18ab1941bc3b70ad1c5767baa0f69f73caa07ad9747d38f4599865f779f474ed045a768f7ec5a199ddcb5321a14c320c57a4641918cf97594e74a0fd1030d81f6eba153aa8b0f2018185109248e510b2a1842c1a805342c2ea31664b35a97cd398c5a68b23166e1b4dc3dc7472cbcf1b1c20211231686dc670180a0613400f0b9aafa2aff4594db2ee6f6bfac1713bfa8ebacced1f5c7fd7536c417770fe6af77ead71ec6794885258557b3af52f5ecabe0d54800307077ba717e323424e7078829050d8c52c0c0288533661d7dbd15fd87153adc00848f0ed058137004f0434c0a03b887364c6ebb98db18d42314ea98fbbe54348f348f7484c216231486f03be62d4dfaedc6f977c0dac26ccd5f3da86fa5a8c356f6b38a3a6c8575f7b3f6d7d1095046269c3132e14817fac1b182de6713cebf83b6316c05e316de57a5adfcd440421cee3e82c947230ca12102199dd190d4161f0540c73790ee8c836294a8aa645f2f4d8d20f8e1fe6047b72d7ed7d1d936dbf5846524c20f1ca3102ae0786fb5d26da379a434236132839219089084229981490d4d7428131d1afe992ca161493d9d4ea7fb2246a146218c42d8608fa11d27f8c38f11089f3b4e087040e09e44a45b8776ebd917cdbe681b81c0c47d480942b4f1128498c34b10c2045e82103070ff40c81611a02204eeee44343f30e0ee5e421f4508d0640f0fb8bb8bc04116da86483a6dc39107643492affb2d3715a513efabe34051010ab86a8b22d7810ea30eea965fececfe7002da6abba9a63a7734944e38190d61904f6449464318907c2181f63b89447ee1d658030e09b8e3a889c31dc78d35ee3870a859c38d37dc71d4a4e1863b0e1b6d78af1fa8f433a7eba285884600000000831000203020160c872332a9743ea8f61400015bb4ac5cc9902e50f328879041c61803020000000000002006946aa5257dd9110cb67cd7cce717e4a4eb884d14df0b7ba26e8eeeceebe6315f23b0e6d6a4a11d168e2bab9a29134cd092cbcf1e3002f291f3dc9852d04fc3beb8a46812e698a658921bc6e23be2e9bf2591f75017a3c745e77a0ef09b3d22d8678c287b4d6265db6630223073c7975dc16b94f018a2950fe3767beacdea2c5726c0f155030d54683eebe2465d45ab8358f000fc148814c897c9d364915d22f371bdbe3add365062d8ea9021186f08c3b2a2da920d5c50e72746fcd6305bb4aaa8bfde33e162c4c5ed391242f81b7709c55627052af96e07a65cd7cf30d35f7fe6deef91bf770d980b6f04d52036b6ae2677fffbaf69eb9b91eecb2f36c2e43dc7e10ccd4100d428e2800af2a867b747c29feb684e29603ce257dd5a727fa8dd422cdaffa31f1a76c0bee7a7c3cec08568b58e3c0cf835c823656ebe02ead5b674eb61e8b30670f50f7be9948b7cad969688522c7fd03a49645a188cf0904f6648879fc144b0c029600745137fe58718ce449e66e680b35f187bba4ef0a13131aafc7a8230752256fcca748ace63493e87076b0d1ea040720457561fb633156a71c7a37a0045337b11a0db11af894c93dbcb5b1aeac4f440430432645f9c70075e5abe02aec3a1b2ad415d3cb989a006974ba63b044bc1ae40f5bdfccc9366165ca29699eb0d00803a7984dcda32051bc8339858efc7ca0d164fbf92bcb60a6b5d4f43815d554a596b90e14eb25ca061b98cd36ed33253d1ab4662b9726eb0c7ebca6ff0fab14d666969ce530ba4e34a17f3aa3434be6007426f5e9753c38be7597280c4eb90aca5ac16605c1aa2ba1db8f3f84539a32c153fef0b3e65d7c2ab3b8c6801deeabed348ecddf86f52be9233c89cb683aca155ec686bc00f795ef249d9c78548363100d9155c36e8d7a05ba7bf8383888b1983b4857ba1ce595f4577646cd66dca0f34dcb125b1d0a38f9633b4b1b5a679473f93350f656d12464b7c30547185ff37664bae833f474614d60132c6854af0c3c33242cc8bcfc1835841437c9966494a5b52ca3597669dd3c6a1e67a81f2eb0c8c61e70b3f05fc4d4b15a9c529d6f991b4c888416790e1f6f4cad6c3ce823686064404ec26add0f743fc6aa14fff83883dc0b465df2271f0899aa648149445a25904ada12bc9aa8ff00a4e8ba76c60a6bb127a44eefcd8e6de5bdd3927bd7dc4d50b6d604bad5f25db8476d68c412d235631b45e6570eac406051403925bb4ff943e2fec48d418485861fe4b6f47d9c1e448036f9fe9b0b0251205d0f9b91962a6964401747e8e061cd3525a00a8bf988ebf4c7a48ff41e7a7d9cb552ab3a65c315de23598cc4b80267cc4a670ce057b919eb6726c2c576d93963fc7732938da684e97b1f169cb2b70b5d1024a020e7d6d5f8f8f338bb3171eb1954fa8f002b3eb6009466a19a0912d8dc055574ee5eb79db310c29ff14cb97405e8f3704d1891519494100bd22bf2b235d2eed268140f3949712dd97c64dc26e1fd8df744b0ae10430740a1c7143550f7b88f56dc7586a910cddeee4134a096de403ab68f7e0fee76ef90ee329367dc693a10228e145a92e62ee2c543071a014120244ca7cd221d9489bd4b6ae91ff12db8e0786f1e6ae4a67c7c4a49c2321220889ba94f43a1c92f1436e644d546ce80c5852d35c8cc7061e6eb67b5467c8aa22f0430078d72b0140fcdd553ba1d9c771b8f5e62697c8268a5f252000dd91ba1387fcc53b7a31d9ef18395c23490ee2c7439ebdba070e0bd2b224878a261c899ca175c4999e39164ab5985684ddecbb494d3c51dfd0ea01acdde945b6768d5d6d0019d59f23e96a776e9f2ff9e18920b960c4bb0558cc11fb90b1c5aba7f68272b5a3f601c182cd6678fc49d31f110fc405d6c461e216d7a1a35dfcb83de41fae864cc4fe3d1bec6bf660cdfdc56c86d5521d8be56ffab9b8bd4974144d236fa62c9be4eebcbb80cac1ecf2e1a488818ad43116b6e6ecc065bdb54404d73f125f93404bcfbe60fe876fdea728c6ea8a064ed0f8708065b31b5fda9a6ca4ce92b56d435be111a97f3f416a3706cb6e02658a8a20e397f62dbf993137081285dcf060decad16e56d7141d2da6a73e834181822139a11fe4573422af1181824296e24489f22e63a4ca386e5babae677ab97424709101642d7b9cdf6183b7a0abb1de894f9b566507520f5f98a18a17a2e86d62be61d9c9a422b69ecf6a7f58648b1881794c8f6aaeea55a2ebe1bb3872073500435c2fb154170dda18d59b08e4ec795f93bf99d579e91bd839950e76f7cc86fafa461fb0f1e82ad39fd77bcc05282f9c2941c27f9dbf6753e8e283ed3d6afa6656d4d092aed7b9ed4cbc1292244c2ac76fd1f7e8d4d37ede2bc0dd8228b631c27df5dfe3b2d6c1fe33ef1e5705ba09ebad3bbb736757d417435f129b580dbf51a758be997222aa37516d0d4f255a1f8b82e6f869195b775a72c74af260f4792ec487bc86e0e2ccd8819ee85cc12015a2ed437e7c8f08bdb68756c3fcfd9508573036858e764b1d14a271da69c2ed56612b1080e15e6da8abf203b36c11ea35ac9f71e50bed4786973eeef86daa9915e93611cc7f9b73605c4c3c3de052b1f5cabb2a9a720688cd914a98553438a41aa929230d7a166f6cdd0e55c29fc4a85b9063e03f0f5197b3ef43b7080c1074c7d7ebb82100e63adc4e308884c2c692697b1b7aeca32d90d4da61fc3374a084c065dd2da1fa6badceb7ea9ac998992357dd2991bc4b2ba84c84996d4114b3ec87e2d3330d39a31dfcc214a1af1b3f11fc21cd84ed97989ce9ebbebe059b873c20880eb7ded5de4e83eb3151f52503eb246b577718525e3815eee25c1ad35329a0d81f66962d05cf3cd6e2fb461a118aaf9f3d44c75d917c85380a0cdc5c8314a3025061237eacad6912f462cd11bcdf30872f53f5d2322e4d1491a9da1425c39d639289fe661720c7a42f64b1422b614235ce3af0a4cab114e618a009040bc8e0240c13d1e482e693402d119bf243883b15518baf6f285b3dc73f27a93f3a4785447d0779ca5718bade7c60fbc8f9ac89dd8fd951909b279cdba5e4899912886d0ee4aeec0b3ad22b7d2b16ebba0da0b02b8406df25cccc315ce569c3320ec5eaab55a1090ad8dd895c1d45271a1010601b29bb272c832d4c54424ad870729a1009f200c232923543a26cf8ed998a8802d35996c499263beacd3872045e4fadd88950fb50e5243fc5591067d4ca355f2ecd52f9d5e0f51021ffa343f14f1038e191535e4a1c0fb86040ebdd0a055695cdfd72ec8708ee3273454f5cd0740302891a91c5f5ad1a269e7f79e0793259be4e4ee26c2fd680ae06f2963e34c184ab889f9fa965cb1dda87e56718430cb1cc4bab8c7d48307fe95fbb54b5796815e29a380a6d1161cb818d525a2f787341b24ac8921cf8bc3ff99885d82dee108659dd12a15dbd024a28461e4206e4085b449ea2c7a603cd0ae9cd793264d43fe5397d30ae621fa6d3922d5402e5068d6ff004f68af37e98e530bcbb0af5a25a635305a52337936b4f9634077a3c2cc7dcbb8efd1111ced26811f236c210c3bc959c98b7bda09280c3b257e29c173eb3bd13dc6f457f2296d6fa720da0d4738e6bac697e319f039bae3398626334d30763311dc83eeb4e741354e51a3320cf269e5acffc1b07a1c3e6e1eb803d4c03d14568ea501a7cfcc561c85cba6cb553d76cabe87fd5ddb18600cb6aea0141ed0f5ddcd789f2a219388f8ef2ee74eb84548fc4496738827f1c4d97965c94c274c18c7320677eeb033dc75545de45b7b1e2690719722603e2e9f0d44a85eb5cb85dc150a1980f803986a34a5095ef58cc1556a38e942e065e5bca5f06de368600ac01893dcef2ad92c4bf491ce9d01197116a3c464e250feef0d6561e8cb97b4c18e91aee65dc6e3f66cec844da0b39a89ba4d48d0207029abeeb186754a1c8aed7fcff288be3794fa20c8f5d7330ee0f3159b6a5bfd549fcc01857976f8ea2889676c7f1d74ba496a1ba4047e4e79ec9d88cfa239c0bcc86ceefbabfde74658a7fc77fbc908bd03d108dcb7d89180861df6c05102e01ac4e5c55d71b885646501a317f1c7ddb04f31d4406985076518a126cc874a1063898880bd729a366e767d0673a9d0eeba3ec55e5a12c2696620026cc0c5f2a3dbdedea58d5ffd7ace0551978b9d7f135ad834bd851c884fdafee3e0f08a7848194a21be2f9ec00d13d64a0d755ec23b3641213167315cd11a3901462fa1e0a6a4c59815927a94e3be31dcd5b9a6445bc73c05b928a8c8cef7d3f423fe6d2ccd1931aa91c7b1e491acaa63803b284a81304c4721423325d183ba8e874b847c30dcf066b395682a18b0c950ceead2f649b244a9e257252f93b5a02f704dbef00684a10b89be20399c814e99639799be0b62a12e540533101d159c7610ca63adbe5960036f93332d210548121a0ef19914b4391dfe38453f502439dd516c1ebe5b37fca9b0c63a6a820dde9e62e11639bbc670d3bf2c81a19dec173eb44a0f34468bc28ad7fbd9b5998887d3678792173bcaeb7b1a2207c6589e4d786ebabab804dcd22e4e47fc769e6c95efa5aa5ed943f1d424774d1a9159d4a38e75175b126848b9d72e662d41f3bfc49fd99fb3d811ac3b2db31423063050bd0f2c86a132409d28c7ad9f632603a1fed18dbe4c322bd6c174a6d1cdbb7e9652ec6993841b36e97f2193b41f22436edad46399bcab336487fd77c8e8029d2554028ee7571828a24c63d6f159936e532b55428d89dc0ee029a98d096e3c81d99152808e6d799fde3fac1029834f12e6ccad405fd49787d22782ca27733eaaf4189674112b3a640b678d84c004e553f068d5543b485a68420aad2f1f69a457636f11088051d1136614faf08a5b8113951a58e56bb1529d241bf0591e726bb1c10370e675b98a78128e7596d3cda66966c1e5d12bfa4418f09ebdf44e4af08f9b4594f8684120a9c2a6d2dbd4b000e2fdb64ca0aa1d529ce77f4bc443c82a1e92e45331b3d3d158e314409c619ef167ca3f823b60958ae29cb2cd5696ef0c5fe8cfb3388cf681e2bf8db4c5fcef3028fa0849df1e020b5f5a8cf3e5e82744d5bef054b5114c8a7d52055fb9332f03ac6eea6e9163fe4e2b844d8a2408ca616adce62912fd7013771df56c7f32e722c8b1149fdd03ad7d4dfa7d83acc4ac08e355baa3f420a8cd83bb76781f23d556c2a74e7baef3f9f796eea4fcc09bfaf8b33a22f793ca472f41c0ff7229e1f4d08823f577bb6d0c0c740370cee9aa372184845709d559163c69c799f97844a0f6e8c72ff089bc9b0b696a62e14080f8fa5baeef33a23614a11e6119e76612dd2799c71f54902a621601cea91737ac40f43cf15849b2a1a40ad949bae85c4456d484ed97e8802ec53bb4843b940146e312b026c06168abb9f7439d52539e77bcb1cd50e273378989d017ef2d3090c2f37c823d0cd62f45463260bf87ef02c7d0ea9e780492c56bcd2d5004353cd8e6a87cfdbf179a41bd0c870cb6d656164b5c74940c5178bcd4d33951111a35444478293b58a5348f085ab4b7ea9bc658385605e37f4815472bb542629088deb6271afa70c0c8dcbd59e856953986f4ab7265062808155c3e11da392f09e3b542f4248f7e77cc9fd51e7ee212b3698394904f8d06808cdf2eb692edb88d34d82e85076418e26bf099b0fabd194eed6a984182fe38a65920fc6a89189a4326af30e0cf700ce9b1510ebbe67b35cdbec5d0264a0c3fefe1e516dc58d3437492578671c230aade06cbf8c400cdcd7686f9bd1902d91a84387524bc183aecfd1705f35783eeec2d361ff71ceb8c003a63622fc26c7cf69e81811e056d98bf43c66ae9d6faa7a2f825c40dc4ddd6dc7f81ae4ec04b8c77463a34854a0f0abf5b0b0aab76a0d365bccd86554a58ec043fec41cef11c0537eec42142502c532c54ed5c7a0823890969c9c500210b83c9c27c2d2258c971115a8277bfa01346e0c04493b98213e771326735ecd08a2b747f584de21fc8be0f136c0bdee29472c6f0ef3c5a7e4d545b45b8279e46bb498e5a7a6d43fa213a56133d2c1a42158e108b85b6ed160d8ea4fc01ee399cd19ff1e861a1d012ee67faa68a2335acaf5724804d1e99917577d6aa6a1324be54680964c69a4d6887e7f445cf84b81ba13a88b41d1c5807521ae9595cf1613710a7ba3355bdb63dd89c46d4ca3874a88bde0c4174321cf81d8c5b372f647413f02d17b909fe3c551307eebaa5c3fa7914ea0d05c5b9cdefd82cfcbe872855bbc47bbb89559a9f974b0fab9227b7792ba5541990a6d738924dc901a86357b0d8a811dfe865ab5c621f6b02961728fb81c2f97cd20ca47afd844b28bb8aa230f18e8fe45a4939736ed845527e3d4892f65651770a6ad5b8bd2482b422144ebf9c5233e7ec5737da09fac05803ff42b91305c0f3fb8accd3ae6a398817d11321865172817edb5f09d36efc5ed75a37bb4f99c28861f6465ff117ed8a725e2d23591ad1d35c3d3b0f7d98f247337b2e8db6ff9ac42b013e52ecfaf4377626871ff9c20e0010cf9c58ab03a955c7fc12fc4f5c6486892e11fa1fc5d11fc8120dfdebb2a9ff3c12fc175fa4efb7bf1431bbab101b28e58293a9dc6cfcbf5b2ffd0d8bb78c3a6d141300a64457060665ed6c5698d9d09469727980237baa8e18787ed5a41466e0f6618f156ec6186e498bb44564c0c10f25bb2f7060b37b3b8f3824a2ef6426c6864950e676de88347b8298c0dca9df7b472e583c518a62ba65cb7d64019d5c9ca45ac96a2c1ac1ca37be831df6b3ee5d59d177225d8a355cf91e072b29e8e079d7b662e194dc57a6c1abbb6715bb2481b6f2a4146fd1da467431bfb0d26b445ba4eb2b120ebdf9ff3eab7996af8e0a45ca7acac428e6ea46d8e2b476d2b424b53e60c219344e0c744dc68382fb76dd4bc5e475f1cf17f1b8b62f4be3dbde1c5c18d36ae4a0303243808db00280c4091742942d9a60c950a00465c1dfb7d80b042c7016338d0f3107a949529d19cfedf9618ef53e6b44b58c4a4d901f0c95bb6038d37fbfb29f91f8269f1a3be987e8e41ecd3249314e8dfbcae277111ed6345c1a3a790ea8e69d099e630bc6d1c30213d3f264e4b795206d305328a5f82c3db9ac2c0eea173663ddabfcc2203f38096c578797f65b4c19fc621eb7b82e340921eaf4ddbab11fac8340443cf320a9d2db2a71f9b4e1f95bcc52cc516d4d5afb12b1577610e6af4843bf184f3d0cae0e98b037731c5f6f64746bfe79819de5fed38b6c82466bf2dd44fed69f86d127e1a72cc4340ef4fcddf53a96d06235f8766ff113c1e6630dc216722f1b476a0daa128ae2cd06da29bcf58a308e65e10af2485c7c0b9aa191516a7abe879011c40b606df72a1328785c154fd0126a5708298cb7f609dd4669b97beefccb496aadbe6f9e4b66df8283149355b1067a458954773328821f1868382cd7850bc8e498ec563e42608039cb0ba91cfbc0719e53180772ef84ba8074d619f25f2fb1f16f418389cdfa3a6cdd316614f13a18af57ea7c9a90fa3f613297fec408da8ff67c527133aba8f03349b55302a66515bb4c2c27c72b07ec27bac4c4760fd9857f68591e23e88c2521d98e17a2c8cb9e2479bb7e57b41649cfd81a8194b9bd1aab05d6ab884ed97bd27158765243d7a75386687eb2c8d7195b1517cd24832316fb7ae56ad34c4f8be589dab92354e48ca7896eebb254084161a89d282a575c4a233666f5d3f205cda45e06de5de10d9101342d5aaa0d5401083ce563217a9aa7124528fc6ccf56dc4c51cac76d43b97cd59f2a0951fca2cd207578ea32e3bf4bf02d5ab8eb885282e05d82ea2119b094325490871cd65d3ba01c5e2d3fdc203ada16cdaa4fec931f02bf4d02d8c38ecf33d6dcd7c4650d2fa99ed852406ea2a691aec109dfbb8d53c1444a04b4144480d3afd7a06ffc1982a1d7e879ad95da859d9de5065c2ac3ab6b7135880b0daaadde06542bfdaa3ecfd0f84a2a4b50d13a2f942bac55c772ec5bf884c10238c755fd2825e6bbca22d5b85024392190774c270e2b2dc53d0863e6914c06436a6c1451d076decee8ff4f1161ed0053b8e1889000a32df25fcbb5e5591442c7de51fd5730682edd1fa21b2f09215340bb13df46d56db7e8fda9e476acaffdc2654f630aa6c430d850696007f7c04b742709804d7583aabf71ec9d86f4d7627e568063e1ec4a4760fea98ca035e507ebe93f0657f8f6ec0d45265554935105ca67e51c82460dbbb532c9a1c63f77cc2f57bd93f01aa42397e9b2503788b68c48da96e47a7e28d09d76f9c0d303373b11e9ab3070d1816126898fe72cf4a2ca30d18210d02553d47f4b3dca6c151e378cfc59c0ae33692544629e4216710c4fca4a26cd8813ebd1d81e88ed14ff5c79ee4331f917e04303279f3a72774d7e3a82189c1172de5faaf51b4c112d103cdf72087a41628ff01636dc0819258be8749c8e3027e6de84e9f0b47f9a0f4871798da04a23f1cc60f410c60615a557524b0404f6e6808c3605cc8cbcf15845ab85ab398a34f40991439b3a56fe10476273f94a019ce1fb4154d835024ece284206ded36391318722ff58da58bf4d802328e04ec8e194cf19c110a1cffe179c6bb102667a09d3f21f0a4cc8760bdd6347e00ba0d99e4519f384ed6a0717f63472e5e9f83ede16265a5d3d1e9886677bd888a28697c24f0532f1240d8dd9ce5a29d88ebf017967fb2dc76547a2796733e677fbfd446a48cf853e144bf17848c4f4bb2c34d3625d25e90495b125d4cb9af4fb60bcc593c77c03993133bfa32200d00290f5ef15fc0092dcc9e907fb047ea39725ae04aab35afd048c9a36c3b7fde4e2dc1e9f5efeb0d46e568f8b2b51caca956c32184d4d47148e7565185d148f8a30827e298bdd69da203e34ae2828245b4f6bdc59a30274faa6d5639eca972db182da5a4b7e2c273302b757d5f5ee639e8f35d4177ebae775a2b3f18b2e5b41dbcd027890c314cd286df4f14269ae94e9f24e4d42c305fc231a43a123e95ebccc4abbd34b0863f79d2c59862f8cbd5dcf0012eaae3e8b393629a62cfe504a23b2350c28fcc1027ed30d4245f8b2a238d25b4fafd43e5ae2e09eb9efb47d8f6f31dfdc126bdfbe236cd3b01f333281f857ffa22b8083c14fe4506ad7c76f416cace6a6fc696a133c34a78edfc1d5c0b88b150c5ce3acb061f6ca8a1b72e8bff385638582033794a490e8ab17272e04d83c56c2f89de01d608659af490c2a29710a1e70ce12e621e6a9bdcc86940486c211afc60992bf148290bfb3d5d617a82f744bd993f2bb7307da7f38ee7621036780bb820310531b5db405283783c3a9cbed725da540de568336adfb0dac671f5cc813331bf586f13597807f883922b049f39bd6606c1ce46d35f7750198edfd6bf2143acbc9df53ec34f3e07fe314858a1669ecd1d87910fd225626198b179e8f9c664f13f75b86dd777d1f640d18a07752191a06de03821c021a3dc03193af567d113adf77f554e2cdc7c3920bb1f6ef955f7980e9794883fc01f449015891933bbcbdb279dd69c8e9353a5ce2fae71b69e8d5e57bb88b0d88fc58a0a633b1a4033d53ff7bda4a83257402dfe3d1c828769dbaa63958dbf43411092cf6d2a5c40ce11f9f81efa4d2d0c3980f2e74cbe887ccda3a270a32adbd4803251a50671b9f93f2be5fc1778fe3a02268665628a4d5b875c5e9917c3c1935b0e9ded8eca62f756d356653c2532e3a32080369c998409726ab8ec47130ea537a545053631dda4c17482e32c8fb6fe54dbda998fdd892650c83caecc61daa744bbe1ce830c4cb1ac37e743ba503a57cdd78017c83a41c37d425f65eb20bc1610aca8ef01f334a6517cf1036834ed65748a7ea8403772b0ec8530a9172fbcbc4fc873cb25327f8ef2eac42e82e125b0031367251c2dcb58fe1a64d9f416020d85903203f0d1f4860730b4c043bee9cfec7d8d5fdc21928f38c4578331cf500e23ec417ffc9a2dfd1ee0b8cb10b107fba3dbc46f8ab87aca8a4d6f6de0f648037f1fe42675fec7fa90fd6498617ea4a85e1529a2b230a719f6a0dc8db654b446ce8dbfff690131f15fb5fb9e6eced7a33543f111a953a1ffa2e9b64b5d1f2ec18410914d62b21ba21b3591be193f4df3bcbc87f103c0213e52b04da3d2c236273400f82f68078b7997642a22dcb4ba7c07776316d63661990a217ff9789941d0a87edbe462de4aaf40f402aa058f2fcab6f594fc8c0b7a63fb7ba7c1ba3008968d4381a385f19b142683b81b149ff3c309829228fd486352d35877d1f02dfb0e369c023f3ccb8efc624e513b248dbc6d5bb862df525f080f9155ffff8763159d5986f1fbdc9cd8d42aac8433e222ffdabe37dc902f63e28567e87f07697184f7ed349d02a79c70cc81e74e3fb92f8c0580e0be431be8faac079ae997b2a49f0ad6f44d1d14dd21b8af6fa868502ff07b9aa38839532f75f003eb37c513809d1598dd888be841a7f6621df05abd96bc4280be5d15de3954dffa2f71d5b68f7d00d0263215f33fb9636cd18e418a82a9627b2a555136d53d6bf688ebdd88514f7289861448a9b3b33fd59133b1059ec0357fbb54cff39c8ed36b46a5274043cb868f8737b0f21d7a2b8b6cb109ed53440a9431c689bddfb6df2cfeab850d3398bd1fa4b69433c3c9f2de2cddc7ab0494a39353b943792581f29bcb19a0e453e6c2a6a5e36a29ecadf62ea7c189cefb49b9eba0fe572c2bc6b4865d71011486fb60d520e8d59ff5ac955406b7aed1f364d5a0fc4db944684e9e2fcd55e5339f835e34697e259a23d2d1b52d32b709f117695036382828413f62b3d44aaf360e7690249b1a133946a08b4b96dbd9f7df0123b22c45cd1d62b849a0ee8db10d31b2df33404bea0c66c892d60e0392b4dee39ca462ef3d31eda790dffa62a7a404f8356e9cf3a7d6953be23ba91a0220a494314b4105ce1088016ff14f56c69178c69c0ba793d79fe0f50d902953af1cdc8d550e883b811ff3afddc16f13aed83e4708c897262ebc9b293d5680cfffc5743520fa35a089fa6c25b7911ea356153176433caf708a6dc491c2a0b13f181f3e17f27578b431123b313241e68c10dd1efee05baf00dce5452cf5474cce2ab4a53088c2f800d5d65e19793a48e2c9bddbc5d8191cbfce31293761f9430f54be9bb35e06c83bdf160d319ef986e154a260b535d526c8395961774642ed706a41c66f07e5012cf60d2f635a0dd26110d60d5982d6449a44a4cf00b8ce1aba2e70f20aecbc5ecf878b20f9815867fc24705a4d2e91300fdeb79bb83ac106294fdcdd182ecfeb4aac84117cc3277c76572c475845bbab430eea798784e072c6c506e3c417c27326aec3209605d99beed3eec5bde6dd452d889d4d874280dfdc7862461b86b6f9cf7509165d618298655be59b9d2c3b9f85bc96b9ef5b69b1b7ec7dd3b46430f5a43a8afd2a58c321ce79555831100bd55a5797ba08a31237520114678e22a60a9702a0ae263a7173a0c43954fefef0afbe8f97112ed1e81d944f47a2d9239af7bc847ae957c6366f2e76052b81100cf2c7710f4b068fff9058196a37b368a26110e6cb0c17e62a8b947e026defba89cc0c0e42c7145089d96ce830e671eb0e969ccaf719a0e50086defcee01562a97698db2e285a2349afcc53a183e8fc069142a0a7508ab9606c56d60cf1d2ff5a4db4e68d7a3276b7cc31c727b3a9431440fd49e161a171fc809b0c50e071422419f5387933e679d636aff641da810c1d9642127e7081ebf549a6e66c950b5a45143534039b557e0fcf896b5b7cd20773d9aa8af48dccf3f9ffb8b9344b20a74a6218364310e14b34cdac30023f823d4dfb4341364022b1d283ef7e99b61a08a3c362d471c08908aa8888a67dec8d3296eb90e4d325412f7dc0da0ca9d973b3b61e3bfa8fb4ce9eff99377cdb25a3bbb19a1fef0e2fa991785d721f186e672addf01e2666f5994566dc1eb168f4f2eb650c3eb8a2ef34eb230fdaeb8b8de90855ff5973b000c6453281a9c9c57303ccd3437c92c60d9086bbde6694e06892614b92e7b399b68d3d7f92ae06a38efcb41ab739923805d73fdef84be005b3acf6f3310ba5da149a0c4103ed474a357338a874d38a7a44f52dde7714984353a1142c100b75081e55dc3c5b9dd0e86a4d985c79e977deac877da904a027d4c6e014efb10f2304265819bc8a3b19c3a338604a15bad0bd95989650cf3ce44cb2d3951a68ddca08a1e32b7c84e857eb4c4ed01683b46d6f85064353b7be7d0454179c39f52bd8edeaeaef0717a5bf5cd84e92adefc2adab4b7c3df55586c05395930a45ce1c48a0fc3896eff381b5429143765d6ac2b51a2b47c995066c43bc319c8d8bb81bde06170f57d4610504420b6472562a63b55108951524c42b39ed936793b1450c3dc60713ae240ae0725a3afdadb23744c7c9254085a0262c230e0159f9e989f40b7a6c73c8826b25dfc98f34badd0a34c0cb600f4dbffbc0be750d7d17e1cbe1d7cf04cb6fe02d4efd60633fb5fcf36ea72da87bba2b51575df46c300c9e2dfe7ca0caeeae6b40ea6ed876991b4410e9daa4feec8ae035e2a257d47543cdca4afc2a5061cb21efd85dfbd31a7079cbf9d72a177c051b42a47dd885e528b4286dac2b49cee6b2a5dc6f7cf48e80130ee0cb4a4117680dd612981d9f19003b52fb219c52895ba03870e96c1aba3bbc773d32a016ed0f26f5d78940c7b3d159d9e283078d0eba81418dea8663d467799bec449a854376b903d33e17609b5ea04d321e94a7e4d3065c1c7b6a133489ad6c5d18f946fe033170d6a510c9a4ca765beda977f8c326ab9b8038d2e34e8c86ab050c3a1af288a09fec3828ac0d38b6e2036a01e78a12dd1f38d25c116f70f4018fe7c8a6585d744d7a1917c7ccbc0a5466348463583a8748df7458a013ad1975c5b7430f772408343ceafa75c75243c7032c2d37a8a9162b5ef54ac39051b536af5a6ae1501cfbd315e6e5ba85424bb9b8f704f5d61c83eaacb381bd7e1588252ffbb6297fe4423a8b0ed9c949efdf425653675d6c28c8033b6da0258f1d495b8739956fc764eb7c959594c5d608a5573534e6269ec1db3c7e24c195005c325ef7f95a35106f484c3307f76bf435ed8059722b447b294281fe92cd1c0498200770fb6a753badfcaca423b8d84512de993a280088841aac6eef0236c02fe3629c738b64c5edfc188d457f852722548fb0f02b8704f2968fc1888fc639e4b1dc1a9d60cc2d07ebf420fa2c0acf30ed26168a22ba8f1b7639a30f22dc3d0d7363fa485c7d540848af24e7a2459fabf8157dcba0df3903bfc45f34e37821115981fa6d510dd8364e67f519b08abcbb776cb3321e842708fef7d7f2ea60e7cb56f748d4f9bc4f315e07fbd1ab3a1f1c203dc74dfe4961d9c18a09ded1ca356c9658baa02e211f5cae2066f129b2e6647032842b3197f26f8e923fe429205c4437195b1fad0a240759a268166187118ca947022db983910fd7c272788a1bf3f2bf9cc943e4c4cfe73040c4be8f613c25e039dd7e19f05866984d0916deef5955949e618daba0698a68ef6bfcc03472ee2414ee8fdc421b517ca98ce0522e060dc4ad6604bc83f52d6130f719054e6b29072034ab2b26a64e0b4b4ea0ee0d70aeaa7de8d6515bcf960683f283ddd5a15ae0e689343002f730075dfaec0e7ea3666ecff35522026b9da06dcedff900631e03f4892cca6074cb4e50273ea8f6bed889c7384467234402c2a649d4a2b46108f4692f8b11eb482a41cef8ea882e1385f38ea3c8a9a113ef090ae830744709f2be8cdea7b53609071ad145449799be071118884e4b887cb5ff93d80480f123da86a38103125bd9b5ffc4f08e658a060e5debd73d226b44b36a78e0dd266248b8cebd21fc146efa8f28f48521b52ae2cc9a76a25de5a8baca24e8f22c125d31cd1f633e1fa571a260d485857e7612be12d23c64f4b988d575582066b6364bbc44c9618f799eff7017dd0443941a39bdaa9d6bc1f6752afe5a338bc5351b5be2cf996dded6dcf70cce2f75ee9cdeedaef0dc203d31e90e925145f4dd77e6effc74cb2e63a92623dde1d2146b9806f6d802823d02b4d5ae61c09cc258631d22e065b5f082c95c4cf04bd7093ce06659058dc291092eabda597533d2ac904a4c0f22ff82502e8d61ec3cc775d04fe31f25c7e5285c309b46eda8149dc2d35f7fd23c2c79f92287f541229e640dda27a79883bb1b1ab111d3c1e344ef294c41b83ed3f2463921609acb9ed649fc54a55509736d48d3b019e2eed28dd2aa16bb45c13fef52e0325023ebdb72068116f47a50c41e18a9ec9e87e842fbd02327a69d14befce18fd43b01e27c6651734efd3303cbbd069b7825125ca3c8b5ba26d66297b62295a2ea42f1c4fd8b4ff79512184b76a6d17450e72a5b7e06243b84009989eb857c8bc1bb5f0bc173375bc7a86228ef2b11082057e55f02ec23a46bc5cf7ae70d01669d36dc983bab75e2bdfdac419d9f598ca60bdf749e4175b3ed3d85ef5509debc9a3f08322a702464b507a5f675068d022feaa3ea10505fc0a77424b42bc4feade695a58aa7b8324017f4081eea4254975693c01b3896587a178b1494ae48488f88d492e4311a36dd12558e8c678d3554c75b9feb836677d5d53317bacaf4c96360c381414cc747da1962687b10832ed0e262431325c39688e1d6b9b04362a28461a58a5789b442f0d6f579d07dc12f8e702116287340a5859811069876e6d8b819d06bad99b0b65a57cc3597ee4120ebaecbd40f0fe9a9c76619ff2c9f59d03add0fa970a7b6173860a33bd41573281fcf7fc727041d357895e400094267e63e276eb1e1886d3fdfde07f1c7a7c197ae3807a29a9dfe08f0dee7596286b6a9782835ebe024f477ea77e1a9cd6047c64f22a8504f794ab8dd2d24df92c4a9c593229c3235f8c07ca4876af037e81534df944fe61d262bf0ef17dd7cc2b734ab8773c28bf336599a0ade5d932ad22a48683c5d5a178a2299c80b08314a01fb5bc8f0d5ca8075918b6acf6274d3b013f5bc4268ede47bcdfbec089beb97ad6401f4a1534fe618e5cbbdea12f9384992ea4763a76aec09e108cc7195f90820f236ac9e55b0e9557458d0d2ec594e34a8630919333531564939a91cf80a98acaf17e9fda36edbaf5846159d6d6e151deb731beb5d0f20598aaada1bbb408f0ea467069187b4ad7b16c71406b595115e91a3a300409fca9e03b66da819f32db23816a0e4577441a7e13e702b946085bcf8b2f804e68fb230408fa59e5293497f93cb121f615a7dcbdc734018c0b5fdddadb93a69176c828548743ebcb0b92025a1aac796979f9be68ef12e711b8b5100132d2c6d896b705380b39deb13a397bbd74a5c6378d7f86e52544bf63285c25fc3d41686f36fb7e15545788c632c3f2e8854f705f9a58508de26e18a61cefcd5540a56603033875f9122f6dd48a99a9690c5e0d771f18fe6a63e3bcc229451d0bbaf8606b982f4e64668e2cf209b201cb10dc85b6f71200dfd0f4be9d46150623d2df07961d45bc6e07e41915a8ddcce1f9b3b7e1689d590f60c3f2faf1de4669f037e70a9c249e7caf13f675f7884c35ad875f9d02280737a66b5c1536bfb6c2003d64b94e91788ecce029c6d43d11e8996e3ad27f65c7db055a7869550535511ba33c9ebb89ecd8f9aa834e2561efc5cefc2dd6f00401ae8c55bb5e55beec2c5ef44398ff25d9d861f1b947cc6f1d9063eb1d0add8d080574143dc113497118bda339d8d1fc34715637d192c1f8b6100e99f030af409be598ac6ed5d1bc17bc3c1bb25054a33b48de23e195a3ddd5d95a78d836292a291cb7924f9befc266eab3c38956716974314dd487ff96ab306253ffe2cd6786f1fa204490e7916862efb011b8c53afea81662143fefa724e35c71354df4c150f789096c9223e0926a2ed0790e74a38651eecd3f5277ce2afef9fee0f4c8a073238f7981d35a1e5caaa427a1af3d4ec5bdc14a882418982d054d2f919280846b6f32161908822f8dcfc2169b0642e888d4f7dd5c1afe236148834bc962ab6fa266f9b5949c79c4313ce49a202f8e456b748d56ebfc309f82e85d82f6dd877205d976bee7a07ed81794311cc00b2331488e271fc7456f2388a6a42b46c92205f40fd4bc1024b32a9e42af4f9b3eea2f36ca4100fc5100fd18b2a91442060a3f378efe871cd4210861cbf8b93f00c719478a25d3bdfcf75561ad8985203600fb8f7ae65a0cf99badd67b95243cc8dddf81b6ff787807bcf70331cac335ccbdda8516209e02068f51f67a302976e7a5f602fb3e51250d7b822204c561e161e5de3dec1c0c9e98a860dc5895854ac2a2df1668f62f0b55951b3765838230708c48b6aa0672411ce418c97cbd5932a34e119ce810fcf051d3d5077c9b49daf2e07cd25b0c070c7b81f0a6be875a9d215569e323c1ceff7705f037fc78b5f3b3f64a4bf6afacb35c19ae40c4bb1d27e3a3f93c81ff50949c5d38b783a9754ab48cd1960a7f8a77baa1711106db2209ddf505db45438dd9c091157e023df93069e5ea1b950fb5d6cb8932ae7f9b21ce068341638629dfdbebaa0d117a718c1d9c597c239f8ce7ef05c7cbb29e51a81f54d0f82db264230feccc1b80833df125a07a2f02a59bda437c1f2ceaa437a63ea0fd1c0d80bd21dc06c23726a4a0bc03971f7bc28af60fedb4ed0e35ac0baa1fc2737741f10a732ba56d7b3635c7f820f3cdd4bffb25104b9b6e232af6431117148c8392b343d3f470716253218e8695646df1b9f5e0526091f8b9752407def073a8f35e5181b90b706f6dd7dbfded8a5d6b7b1b781a5fad44bb8d3839d937b7ba00c8433efd604b85582530074fb2f1a82e159857d558d1a6c83d24e608258cdf12a8c773423d61ee91b84a34d79280ec1d288147f40278124787bc23af2cab7fe360e164beb9c6a03184d21eae897ec89dd65b99a7893810c1a04c6ef771395662b3fadafb11c06b746244f30eae5a6738cc84db55b377ab562a261650ea1de83f847021b93aa26070a133a4c50833924c395c08214b291a748b95c4f072fef9c08b3b074ef5ac00a578b702a9a1ab0da4f0aa4031ab99028aca517ddbbf1e70c5835280f722b3be2cf51905018b06ca44a01f02da5bd9ef7eb0db64cb552e04e67b4938ac7381d95cfb8793829326a89d7aedb6a2c467b4ccf118f2f7ee3a82d9ae04355df05b77ac6d1a6d30975078c428c8668666e2c37ca2f6ecd51faf7cc9712d335f39953a205a48f94beb944f56c8fbbc24278eec32cc6c2557a06078ca4beb12db3bd003317afeb9bd2bc7ca28cca4cb6c425f16be79f885993d45b961b423d3a144bca8e309234718c0bd73c73f1dcda74a465a3a505fb579bdaafffbeef30702114eaaba2b999fce119ffc68baca077bc952ec6567655d61f5b8b09ace068039ccf2a92f676c44bbf29a6f7dcba64bfd73206c23170e66c5e6f52b5f3f5bd6567ac0f3060ae0ecedcb0b37a0494e74c3c6ecf72255b29a7513d7f51d4a0c4cda4dc3d08f10716d23db0ce7840060463f00b3e3b8956f336b57a286c0763885cbb5cadc753a75d877f737a5756f62ad7dcf65dd17051857e883eca7a027075014dedabbe1bc401512f138e3ff1ce049ee5b6c2af1a9ef8da24b674182659420f502aa866118b36080f914511589339ff4f1a1ec40eff1aa64caead041d0420424a29a3839193cbf0d1025abf40fa9b5e83407affa6b785f9f3ac4e1e5933446087c739ea99073b2dd470167c5514ea999e2ffda2b8bd64001d6402b29869c28a464240a08a3812f043777516c98e60932c1ca2725250055bc12fb8aed07fc0a50b7cb2c28306bbf3abe840edf9866810cd4915b539cd4908684a6e351f561bed7235aec687a655aeaeb731553491ca307d1c90ac5daad7721bb5e1632d088df021fa0edb0b70bf9bdb25d403589038d84b6ac193a341d19a5b468f8a469a3e32fb7a2ff996c9ceddca2d241285590206d5e08d4e16ea5d484db222b05f45365172b23db323fa01a49ee9aeafa719bad6cbf0de16eddc3bded5891bc9bcb61bfb38038cef509a53119e8b1ddba87ceb5f3e0497d210260c852f67a32d09f5eeb3464ec18b303a5db0be3553ff1f3ce01e23f0b34edb1620297b687ecbce2cbea922578a079d83d90564ee82556f8032cb8f7cd5921726d8f2e607de92a393e59cf72870eaef49e11fcc76ccae47292ef09b3989fd86089e9467041dadeb24c2fc3b436e14407927f08d17146379b33c025a6f958d9c3788309ede2dcc270bced6b9809075fc0708469bee27761a1c0441a2a1a00e4be5259662e91398a802dbe68fb659e4c10e58d3d15544fd80f604a614c8456239410167677bb90abc8d0fa19ad65338359abcc9b1e583c0257f8b4fa1c521c5ce562c48f36f48591380dd15bc360f480f2e0e4298d7401fe1302c98d699f6b6c8a69ba856266038a90ab855c7d9a6db320f18288cd1d972b26803a786b3316d2d9633fcd694ce67754d07921edbcdee733759ce9aad051118518509ccba04abd9c0c5507d46ccd97f929b04567649142047f712ffa4446621948f1cc46d57a9e50acf501d08918d62c0a97cb9df0a79e21772f23174f06e9f92ccd122a412b3f307342c3f81b7b2b4200f14457692c39fa20ec87f869d313f9fd8a8a0cdf8fd1935bc83ad350f0a8e2d6afa3eda6c2d84c2c10fdfa87290c8d0ea13ddadd4fd8bf940f903a0a827cad945f9244e7a930e4d4b73bb5cf6aeb4b7d342d63be4aa7c66fc23333e705bc39eee9fe7487011352d4b9141b1fd5914673a5da1f904455d2911bec0573006b6cb1589e8a4288a56d63a0c264ceb194458eb38e4c0b3ae99edb52aa3aecc7d8be4fb22bf429a7668659a04476b9aa1be53b0d53c0cae13c25ad59dc114b4e74d9f1c8e9a64656b8aea66c45ff4d5d775bc748c0e42d10faf25bc476023cc55103eb1c8755ca7961d93209f051867ecb406365402e9d28f74a52a4e2648703f4229edde7eb83d7a46fe72262fc3f65073f5ff255027493a1966592ea3eed7caa9a690fc618c2982c26a30b3c136e0458294628eb060fc0dd6240d61f0a78aa5acecec4be43f1fb9e33312320ed7a04e3e0a2e4c1e80a5309c4aac3631003f662f972e2825234eb1f6555cce342b2801a90af4d7616613ed55e201b97df66abdc8351604c697337d854c9fd78732201242ba25ddd2007aeb6aba7068e2c078ba9e08511b006fa5ae0272d3a2f4d877a7cee46139be4ec5cba11aab5132dc5ff332e7329fe8dd826448fb8f337265d3abeecc362717e9559982ff8e68adaca3c07aa94e94b317ee281e76eaa57ca26b60661264ff1ec0b281c3e24e79f6b8c51db8a431351073bfe736554bb1e9c7e551a80543a59703037dd2787fc4b5ec5c851a3fb89024975bec5312e4f467073ff37f2662addb6adeced1c5467ecb5f004eaa96a186ef581efc405344706e444737fa50ec7ae88286805121c48c03ee57f00ff52b2111ddaed715c14eb81cbb09aae47b42201c4f5ccdaec883a39f8f50095a6c59f5cafef0a09c2078ae06d3b4313fe509e146b38670a2ef3b1d27e699ef680a23240920f83e306cadc1773209f253b39682778e49d5a2fc2afd78d06970f946b91f57ce9319475e0e3da4866c3909b4ccdb2891590f445ac6a0f721f98b6f798683aa250bdfb0b6627ec1a0ab04c32608593ab310766e854d16a1679aa7e54d11fb98f558c48c3543e7063453099ef138638b34a584b6642131f1798fc06478a62f3b808dfdba336447031d6671d0a5f33809b18af6d21c5d815b617a2aeb64813b2d948384883bd9844a13a09c6b4a73a584cbc9e821c2ac377b8c9d0c0a6e25bc40183072f4164747903d138fbb82889cd6ec1d01e3f244dc893058b75ca1185658d82bdd452bbda2c13938cfb87a40e46af7c0282f8e915c8853dfe2ac2d467ddee3aa9f78469e0d3182b05c3761281433a159010d67afc7f1d0f6c31605c2fa0bf15b889c79b01628c1ef0e80e0f3e8817de609528cd5810ccb40470fec8ee331f95cfd26e06d044c1778b339e5b19cc1f6c919a8c8943a5c346b17417c472bc0d829c9a95c03dee96850a8f38fd10b22888803457869cf7477a829758ebad3bd334f468e7aae3b59b5d1bb829a9dbbacc0a3cda9fe81a6089fccb892300ef826fc95e465bf4e381a17f2be20cf465ccb0d5163097aa0bf67f0cf27e326a861893f1038f82e6fc27341bd2d20fc2c352cf81011df95047fbf3baec61efb5581888a3273967e008f8c9065cb5c4b83e29dce98b5ce3522d0b688db31b99e64ced1362ff54fbea01e0349aca8e66c31c57bda596c60d6d9075cf65d87a7775616990261a85fe8e369254a654a9473c06a71254307a79668a7e47a6d79ecbab3e896a3da919200aefd4e6d9d5d407099393b9fbe6ecc5ee11949813f11eb42a98cd42f050f6cb79c33f931ad250473efa19319eded05bbc8041e72304c65cba45c7651b7203dbb4e37b1abc38b90173b86be784fe0550ce88bd67c9914bd87317ecb1e6c85a17554cb3f8b03c4621e022df685871cad3e492395085db32dd632cba53d28b2c6c71581e1683c0b522cff23a959cdc4662f9457a6def7fc2057e2c1854b0ca7cca0b7c454655d8740f222cc1e00ded8e114fa343dd841d47551529506cb01fd9eace13d3c2183a4572b4540289e09b0720966cffd9ff96b0d82d8aa1be38f099c646dcebde00727dd18f861bcc579a2bf16816831e42f286c286a0ec609adc39a9fe844005386df749bd65d11c3058d870e56dd9ce15e0e5df05c4614171a92eee524da5b8dbcb622e195ae05621bc3d97fd0b90e553ebce459a832f4030fe1ca84c24f375057246cda67fb971e77c5e26dff166b9535538fca4649332ba4c53b25412ba4d42e7bd7a40fe567d285f3f481787e41cc878491792ea8c92c06e81af73a35d9f4b51c7fcb0c9848ea2e6f4b31b233e894108fcdbd7a7fd000cd29c2ef29757ef4cd5982a82eaef3801e24a70f667c8a5d2284f85b813eaac30e20962054db9b3982f099231412290cd8c599b071afe33fbfc4df6555503265f5ab5925a03a6c2686772a55ab93d271b36d51350f9c6d92dfde07b04130e023ebe65e63e7f2c81530cbfd0e7d918608142039865c0c481edf45ec7d7208b9b0bdc18c8e2b97a48d331821144cd4d7b3b269ec2c26136c7634721e0b5139a88cf2b8c66f7f1207ae9f640f1014ce713d3631d9a8e4591e905d446d77206d1d3931de418ba440dc771929572e23d1c3b079b362ae44db5071fb84aaef0f287386a88996d022e92901e2498c71083e76a71e0119fe2d5519bebf2c435212dad6e3aa06ee0844a12c5f218e7440e783f25e6af97b75aaceb4027769e400404e4efe339110a1f274654e220d1b27aef06037f6079ce6e31a204bbeb4d582ed6c85c4b3a2b82874df21e9c01e3cfb970c66147f81386520c8dc28f6cc37aa1b481f1e605f0a224a07969ff2749cdf3e15bba94a2a64dbd36f6a5c0646fc47955533ae854648092cb15851959d970d800662b1a66093910cc0a15a241c1c631b54365d7b1a4f611f79813b17ce4d3e5be150ef1babb0d773a11783a89c6fff4812887a358ebabc76c6d89a1b4eaf0bf5d7f14068a520662670fc4e2a3b559c6a4587407cc8be59e40eb11fc7f1fecacc82df38d36c0c51c7b2ff3264b65044e8764690fe6aa14f3ed96ce6abd32fc2cdf4503a10f8fc45e425e304fc1e677511d202fd4eee4fec6e326fbcd1b5ca9dc8b813ffdda63603c0231071013565d486b8e747012cef37ef00d456d6d429ebb6a941a61e7ad37325dcbad6d20af2496e8b6fb597b068dc33e55b5b44a929448b6275075e3333afe51746125e9b7a62e3530f2659f0995cb2bce7c53ec4dd794a057f92bd6e8c874b0e6962c7aa66b55b743c924a1f88c794b66d20fa32a7bc497be07d0fe41f9dae7ca9584795684abe9c099510a631f4114a73786c5ed8ca2c8e77c0feec068727a046c0f0b77c623b34d53372beb390ac85728a3546702085db150f4d8f39720da72a79fdf8b8c8a43c3ad0394ac3ca6271faf35bfef42c2be0315af8a1d45614f0275d7f98514b1075f2574c20697cb298f2b9c1d7465a5107ccfdc5d2483de1386133b41612e024eab176a5f9dffdcdd5a3747612a53254c1b617a4321985b6bea6824a5d0a59a30bf484f59e407a200e0745ff30154ee9345a8467e065b1f457880dee4178cb9f242e7f0f9543e4f5a1cd82fe74eaf9fbdcfb13cff6902eabfad5aca0c820391614278ca6b835d38a77c11f22333812237aa98d52ed451d3c818b405ee20c212ab66332601d5a1fe133c6a6d5db7361fd23905d7de045afacab1205e6afc8b349a6668454b2283e410b886365772236660ed71532f3e5759855cf7a636ebd5127ec9ed1b57e8477ce56ca733c954e0319721e3b543ea8a5bda2225d626980f8c3be595f1ce4a6834aeb512807da2a71c0e8f3169b0d0687985819e2b0ad8c21a1d2a41a40d6350c3a7dcb6be152b8b5b033b84228fccf42cec640b1c8505da0e12eff2f88f2402ccfdd886d0b37173d98a8305cb61dbda57c93866d602ab4ef16825f6ef9a8be3aca3366563c7146d8ec90ca487c7cafc9c0a2ee5b4fb6f71c727c82dedb39b46d1eecec81900b44e1a9bbc6a3fbd3e1921c01b85b490a941231a1bea1ec9f7baf7f851835b7ccf135f62442de74fda417e59ae62a60f84106004c95406c3573e0bc31c20c24f1f3a7f81ac5ab57ef385e0468b8efaad8974632cb98933371bb3ef127c8759e75c7e6c3bac199b9a33bdf90efbce2371820fc1af81f1ac28346258d4e48177d7880d2faedc558c734c16608028b325730b6de3856bc91abc61c45347b7b8080c045de93ba3946db573bdbc2d40b7438709054ff59cf0498d506b81b4609fbc2d7443ca2508beeffd0b2e7b596117f866eaeb13b97bc7d329e5a04d40384fb22fc8890c91d2914f081272b5cc4403059c9a1b265764f8e1dc206e499159a7f05df4ec70cd45a475a65a64814705a6e24f53e52cfbd97dc93083f5befb4a8290943a6a6f015bc1d081a0975bad49b50405facff089c20bfa9475dab4d10432c6563450d45a3076bec6130872943eed85882fd57d3d435f02ab7e7ddb389bd55280e03dc5e3baebd6403c3db7672e1e8332698d9df66e186c047ae6b5272ae2e9291ad1e599d3fd3bf38e0994b7257de609f25b842e5d99c3129d7cc15fa931aa9062fe83ac7d47eca6016e294340043ea01e388261d204e7abe9659418ca558c262e4c3103cf82c4640967e8bccda78309fdc45a9e276e7c27300a687dea56f09b055061aa4dc838613851a88a44c9b4ad1412b9569e7e84554741b1dd7624f06544858ab27c0989174de78bf6fdf3e3ac1b50f3c84c7ae3ab58f4fb85dd9b5833f74cb18517d387d776e314b644b715dd291dd813b95a4c06ec251f9de62bb26a4e1ef9982f9ac4343be1b86b2a606e349f6b3f79aa18ddfa46eb0d0cb1d5aef0cf82815b00d9d8aab7c51f1b8ba76c6de82813e63bcbb004cd81c1dee0a6822fae485a6afe095948892b65620cf909811e4b19691ebc729f08ececbb6c20c68117ad3afffd8a23f5414041e8b580c8e6a223f6166272ae635dedfe036a99103c1ca7ba390b253d9ecb0b2454278d41dadfde0d6abec613c4bc603f5f30d4a64511b84210884ede27a5f12f2ed253d445929c8ed5dbb1bd26ee04b182fe50256553b2fea2da9868a0621bb5d15f9093fd267b1b24b728ec7e871ef1e85042605d4c3306d821deb07a70f4ac0e66c6759b14a527aba057acf6894f73109350daf380a2e8b47f95f5858063e88e114d9ee22fedf02da8a73ae79f0b7a31a34154cccffa0f81ac63265c22f32b0e9577c72df3603d151cadc1fb0050769077e35d3693cc40e7febb9cedc78889300a7273129ae5d61e898b86a45093ce4141515bb93f4b5dd6dc6997609747dbf2d3c0b53a806f2a6efe9d19c30b0aab76c96cebac48f0264372ec9130c2326687a87191db5c66dad774165aeb8b065d11f9ffdaec28e4e35ac8ab5526940a421b6dc717da4eadb7c590fe1d81b2a989c934c80f1fd471267f43db36f0d1e02f46f4a0f3f735cb8fecfc967de55bc1336e3c7b30116eb12019591292f2fadaa143132ce74ee9ba721825558e9a268a396439a88e84dcf5e32106b31618e153a1c83ea2f4badf60dd1c8fd3dd01cafa28a8a0cda5760485f3ad0d0b92f3348aa3179f44cb4e87dd302ba4c745eeae885490c22ed1e6986714c5299dbb916b548ac0a31e179a989319dc82eb270195447348fbd7d630beaf644a8d121c489adaef07ec3fc67ec77627e57d29014f69e0bc88bc37a6fddcb075d663d976c896a7f2c19e1b499deb1a3470ab786e66ce8aba5493fbbada2733f24c94e58dea2ba02b492a391c8652c0e46972156dea40fb2d25b0a20113904c6d6da8b63526dc9801ecf2c67cdfd35ac837a8c41d1a0972ba2e1603156007783c2143d64c9ba8fd3162e2d5a62a013cbbc98c453e1a902c08b568cfb4f6a22d4cef162db5609f88c512ee70753fc9ba7d33646126981c06565db69829802562ca706afd9b83203b5de6bb2be15a96223dfdec2abbeed839c779aa929f61fe2b0adbf158e793efe37a7fe6a305cbc10fbef01a72b27dd7e5be049a10618672760639b1dc52ad01b89ba403348e1a294e9f60a8c51bed08c48ef3b1d09f664727a4d25de8b38387e261439d3848743a9fe1994351fa1a0ec4e3ab691e9a31a398667d6630d03e55e7dfa0e5facfa7b4a16edfbab296a687ad840c1f36ed97c9bb4daa4a1db789562180f21657ab5698438b26a98dd91fdea6ef8e6ff37006e0822da0b14a95f7522e7102464f030e2772152d47d5d80b90bf3143f69807fa157dd508686cf412daf0b7e5ea69c1fdc3549446559e44f37170c43f2932f13e01a971d40b549d7b3dc261373b650888727e5c88fbb4a9493005dddb1c7cc2f9e2c9c606fbe4564d006e9cab9cce9c6ab570006981634d6ccf16cc2380b724f548bddbd992eeefeddac2472dee2e979a052add6e1b6975bd4127d6890d5a51e820c946b761295ae24e861b185f5a018c94e69c8b64905eba3dfe14a9305fa215ae94dbfdf8b5c18f3d9a82ce880db01a44c86e25c4a010a6eb7059f7ae90b2c207142a6b1f78649635bb080eb9efd1739fa67d089ce37f4f4e774db8f929f4dcee8c2eb5d6b5465e7759ada2ebfc5f3a1a5ef10999bd984c555182c81b45d75f5f817df0f94d339f853a00905310f75ce50ff0eea548e161d8173353c023907546448ab19de9099b8e08277177a8245a98322a3d5aa6d9b739263b1d19732ee81c4265a8de860a8b125ac8c66e508f8e9db854d2e148785c443b409786109a0902020f9e1ab6a9fa74a51e537e1f65ad18598e0ff4c98469a74ffaeb293c1afba12f617ce6bf9451acc07a651fe4bfb876e47239112e48b3a1efeb4a0f543a981c7282d63a76a755805ff7ce80befc9a838205577d3b50b6a2cfd7251959e0230d107a72eb0c9e8d3e9ddd771df70cb8434c5364ccc68c206a988895099ed2ce0a465d7f1854bfad4232cc9832236d9edc2a3fdc34121bf0d320904fcbf0793bfb45532ae312beed2fa8260899a7ee9f91c6ce6fae99981f01d03e556027f97b5a593c0e81a07db1c6777fd266e1af6bec63dc59eb3b4a4bef6345f0cbf26a07404998af0e3860030b1c1ef92c8ea08bfb99836d4ca6623ac2c89c6c20f6d988dee45db7c02367baf2b85cef672e7a7b73ebf3cc6e249cbd052fdfdf4e07be1f47f773f3aa3b0a3bd62c9f3e4ceb8ac63a727a740153451692b5ad548a1785ef69dd6bfe19dff096d49692289b79fe41f17b03ad5c4cd7d37159176218dd54ded3ef7ea409c94bb7c4717f730caf871143cfe9017c969f4d535e4b1c1f03a5e30862db47e2fccdca068798c7b8c44b565787dc379eed7d933a28db4505b1d6ee3675412d67b0ba1e30fb75953765341c11855e6aecb3332ddff7b7eb2d620ef1fae469f134abbe86b99e12d88516dc9f88cbb951779cf7e3b3f4c024a600706500ae3482f0c363433438e9ea966c9318f076e0cf9a79c737f52e3aef39a379484845fcbcb72ffcc2f9799f107077a5d6de7a8a5a6b5d2bdf6cb7e3cea66c2a5fbd99f027dd1cbaf24b4433938c3851ea27b8ac3c3c125827e67a2e8732517b30d65d6c58b80b508afdd43940b43264641d63c01b7f7d2b42f0109e6183e5d657e1762216c03a4c8e5339f596c0d967c156b9f2bf1fdf648f9e8aeb4f1adc7518323e0dec0ee66fba3ab8b017d0c02d13681522faa1e655a2438b90632a96e9e0a99dca88130c8d3ace4335b43ec302949803b8cd7cad1ce4c5fa28662327421e27f7d733bfbc9726a091cef6bcf55b240b25c2bbed5b91eb821dca08587feb514f29840f1ed0e8e5786b7866ffa1064c6c167e607e9a83cfaa03ed31bafedbd63b318bc1b586cdbb1ba3bceb8e902172769a679780decf1ce84cb4562975744cf7f23ff33e6006e1884685d4419658fba7df1c596294195c3ba08714e911321c16730c343a26725ab22e003fb47b30400be2e104276c3bee62fd44d8de6a28b2400062ced3d17a988a203347e83520fed7a3c42d0782e38385dfbbc5aa28bf37ab0239519236018efba7302c1384f66ad0a6d9de032ecc6ec3de07e28d0970bd14bb2486980080f804996d4baeb810d0475d74981d46c3ea4038bc6f9afa9665cf22e0f7807ac9544664bfb444c1cc8b9d74fd759b7d646349fbea78bab483991972e1347ae7adf6e5207ff7b3a3ea7aed9b16085a3150cebe188daf54725e2f712c496d280fa1ab12d5781c2e498c7dec0a2c11ec38e0fe00d0ecc01f534703785e8a4ae4aec12d6202a01bc12294f95fa7d2cdcfd86d6c3c186e4a6e1c5a4f3172bdb83609eb3bed076e66e970500ec6134edc071343dba60a360a2e461a7f1cc03ff7dab0f68b2a05ecd950718410afbae68c6335f0ffcb0798fa8fac5e687e63cdfa59e8ffb54ffbdf23665c33993ff936a1fe23ae36d7fea4007649429484943e9226bf4127e844fc170f274b82c70a89c1e2422477adc9b769d2d800022a743c9cc5c3b9c6c58bb719327f89f2abbf22eec2cb6acd1d2343aa3799f3215350243e5a10cf02948e67d05a2120abe3778c7b56b742e74ba7003144b7178ff5e0254e3b1ccf47a1becf78b92e3a87d4468efb209a319e7e19b6d6de2265bf2340e346fe06c8ee3502ce0222216fde923ae2d2dde3ada1aca54c935df5e01b9aac477d1f0e3532e0155c65f26eb31e4b642c7dd41f51b928f54310ce356603dbe41f7deca846d341a20ba05a90e10372174dbefab59a2c24c78cb7f626d00bf7927e85f01a96a6ba612608c679804a92ce4a6d1ed4b865ddb56dba0b9899fabe90ef57a8dee68b0742fe196c05e3c52e008f725dd22ed42e3a6073db4ef5ba8074ad282d3a02fd3da32534648618fe795a58390975602da2035ded81982f4db5802ec6d7ca005232aba2de8a4098df060caf44b58feee5d72f79719761be24048f0bf34f2a7acef6c5cf9c690386594cba1ab9a71dd8a14808873db1f4be2087c4a1a68e0b8a4e8b6277427bba5dabd71cbf3c40d40f27f7d07ae0bc431bb4e08ebb55a2709173091ecaab2243840cdd3ff1536955d6f9d84e4cb884c1371e77b0d2f2237f2c16bcfe087f97b490084d101288f1d698c17336555c8d5990e299efedbc45e6f71a12398ccf9638acb8ae08fd9a30dee2fb9624ab3d6a800e641ff9ca9c7df8109a56d8680df9fa35d5759d73b39a035c092e315c1ba7bc2f4fd5977d85322b384107d30f083730ff9583363ae84a11a2040a68f2eb9957e9e4b63f80a1dceb43f441b0f41bc8ee71388f14b46e088faf5e9b198575746503fb908f8ba5f351a233bd990a528409a344e2cf00d6a0454abf9d54dac045b1400ff60c8ef43cb8d9e64018c4e2a2a2e28970ec00444af9001d32f909839f079dcff06d4f2c7abcde2fbed1f4af9f8be1153bd8bfadc1d3facd30cca7fd1f81522ec27b16c4aba52d71a9042e8d99f425183b2441c93188adc8bdeaf8c1b60fa2f0a53a3932ed0eef6c647bb5ddc795b8b74f1c78b8c757cd8870137327eb91c960ad6ac10043f230d1fbcb3298c3f003961172d8352e1d81caa5f166db00d94968ca105259d2791472f44316b20624ef32403c4f60b84e2f20db905e79fcbfeca66c6661fc61e9f26fcfa4ad00c973e4ae95005882f8ba82d086d6330cfaeb3d2af3590660a59fe6e3ebf391425a4200b68606b72882d1d4e6bf90fd38f7dba3d3499d1b82eef21352f60f72dfc7442fd3e52d97d05c851eb64e69443adf2cbeb8b3201b160b078a1f569c7def7ed7adc3b22982f009c44be9ebc7cc9a23f145a2c607a34396e1919c84d5791b17f8c0283cad2b22ac60639de6361efd4a03447d05195f2d247f26b027453fcec13394f1bc0182a4c3c281efd1a7e8924f1f6162364657310951160d2ead9f12214f4c5c2102aa94b163acda3a49aeea6740bcd17df9273ce3810c404318011ae9fa1c3f595238f28cbbfa557f11ada54791a86ef030259133d8670dbf6319e29c99c25b79c6aaf76bd2482ba4c608a93e9caca020a7751f0322ef75dab1520f3523c837833c9e89cbcf6dd5acd8e9db24746b894d71d259fe84d378de2139b1f27a3817f6cee95275e6a7ae00ccd4f9149f9fb01cd37716e5e87749c935a89aef060af434927144511e5bbb2c94a44e8dab648f92974e1ad05bb56a873d8aecf8514c386044aa80b7b3fc0ad001517143d156bcd75cc076933ba7e135842d8356c0b7cf25cbafeeb8427ab6e6f1d0b37d4f8ed288e7538fdf5db59739fdfd02ebba65ad79c97190bbcb781bb31b478a14881a923198bfcd0be11ac0284b2906da70b14a026f8ac677dd547d41007446e9d023d4d10deb3c8e8607e713f37e6b2dec04a12584c75a68eec204a3e9dead37a979de6d74bb8966a00d82d79825470779939b62028cf3101dc5bf9ee3437a47e91c83dafcf73b3c5ae4e344d3a6be767d7246bdda2b4250434134454211e29a1eeb30bc833f3d914fedd1c83b6a4cec81804e14ab75da4fdbe9b8b11e10fd3a00b76e22772c936603989419a337ad72452bcf5309ab085737544b410eece6efe96563654d209cc9b34c0b02f1be3bede39803bb43d5fe8cfb83ff886116372272dec659ca6f1be2a758d1237a41daba0bbaf5b9421b5a4e24412ab547980343268f91cde747e755b6e83dc1b1315d8f96a05f90ea6f14e4923fec3fd5c59ff1591189946cbc3a1d6fc858cc30d43a0f23e73aeb62c50b5029aa0285694ec58be9a710ca910ef7fc94e1b1187a4287bfc025024e34ab6a111e0d0fe3c3645da55780344ffe8092e7c0b4252ced63a3a20ee8b2a119a8f4860755b674e8fefa0909fe7c74396fdb25df7bf8d60b87e6b7ebf2424cf3a6b201e315310106ac3f67726f9da8fa15c3b3b5f0921daeb7a5d1a4e38979b2a7d751b61070d281c6f3427f07d4c2eab3d8215984290eb8e5b7b06118c2978f17fe988b99120b2def3ee9c8df4faff46989774008da64cd81537f9b28680e5fc56b0f66b99476280cfd7a6aa5d0f140800f4347f3c8d3b87b30e67e1f5872fd5d050774c05d3111ac5d894c6297f710d29cfef458a3558491a057bc9df18bf820c0671edd50e7827dd5d2933d063ed9920773da1764232b36e38342364d566602a4d7c2431010be8d8c5ae70d538d522181c1c8d1069a02ee9adea580e3e753cca083e939e0c8f67395d68789f4bbc16f633b3938576246783fd6d812220f4648e0b077dc37341e1946d82e4d01e0262c458165908f1f1a704191e98378f9046cf9d11c3bf6130c017a440822113cdf8a1b8e85cfae02e9868cfcf6fd40da5a7065417fe4660bdde3885f88d1889ba9379dfcb53c61ca3ce7b5026e75acb1dda486b6696c837f8a86687b2ac383ba4fa833d596f42f2c1f1f5eaf9c9a1fa7d24161db590e8b409d426489171f16db7e4f8e8178e5ed399133ef4a6fe404f0fa1894cd1b37f1e510f1a48466270d8c01f08b66658ec4abd1cfcd7a48c80113f3fb01fed4a49f21858c53061a8d6ae41cb348f4c39e37253489873d7df1ac77753301b232e700142b0e441032644ef0a887d78382b0a87987eaff18f3c520e1b714e8e83d114345728a805eba4a6f5eaa8f0138789af8f5024da5a611ba93e014d202a031e9e02ee79dad46310d85224b2a1669553c8bd87869842da33e59e2eac16cc0a11be1fdb7b6a4a19a4ca3bbe5034f085f1192243f4c32f3c65ebc3d93c3ef81b5ec63857c631b27f97e348ff11db89b210cccefa6a1998882628145e13f14a65c09ff70fb2baddc52c0795398ddf6f5ef3d83df978e8d303b3a0dea0c27660be6cd4e1cb42bd97660dbfdbccd2234ff1ace5f8647816149e1f2640ec8193f83c0caeda29b60b0cd3dbbf0c4d05ffb8fc26a8d40333592d89a3512dad991fd0d931935579e4eaf013f356685f75815629726b02e1178c509c057a19d3113cac2d240fdf078dec407b2782d3fdef0ff412bfcc42e101cf70c934193d2cc68d692d189df601be2a1bda14888a1045818ccf81c4895de81502259911584cb0386e03d6ed075ce6002f6d2911d3a16d00d37f3f0950848553c7534e9cc6185f17a08089a313b93d087f529ad2bf9657ca788daada538c7db2733c1eb91f085614aadf2e172118ed26850685b93953555d261c9f6d09ae63b92cbe22e622d677a54534bfc8efccbb46aefb4812eb24b71580cebd3b4d7580c7d20f660782aae15f019bf176c344032666626cc6be66c322da7b18a83797eee77ba661b0445317715375b116149f64af360fd200ebad036897fde89234346b130cff79cf6f625d5e306267233803d23a198349a50562029d0da08159ed2a479374a43cb005c39640e34e34b9838508c2fe31570f37be984aadd20ccdba5e4078bbbdff1394f7e79431e9ed77963ef74987ed1018613c84a43f242534e42cd57456380023ef1e36d64fd728dd5ceface26b70fc1809756ac11541554bf341633f894f7c5dc1a16932c34817ef824c5da877df5e102697c82a42f5ac1a7fcfb5f39072cfa2dc6b750fbe1d4ddde250d334e3eeef2fcaa76166a43c4acf0639adada0b8e167094ee33ef519ced633c3ef9bb97b15c7b33cb8a2b902995d3b28ecd86db69c2e8d4c23170cef549b64b9fb307360c702e9a8b6f41f6bdd139cbf40864ea30cf1dff55227fb08aecc4de1dc4c32a6be8966bea3ce4be096eef4e45f949ab62dcb6949063a9e7d316d5684a307b67c18187afc1c0315f8d414022e19abc15d5a2b2e2a34449ac025b6580b4e5cdbb4ba1dde450fe97c1cf91baa625354b8df8449f364024d38aa48b0804d7d6c723dee8e7d0e002240a5fe8f04b84d7c413957b3dcf13e237982e75fb829c890ac53c9be006d75506eb336eab4805da660b1053964f4a0ec437c48ed87a1a0c30d98e8675e4205f57a0d2bda6b8a66c9609df64af3de7c95335d1bf096de6371fe819c7aa2b1cb067f4ee910dfc90bd734076867ec1b2adffb9fc6fb99236ae46f8cb06ec11e2ee3fee0928812e08511953f9d8a90fe7d3f04105edddbea229cbeb1110460e8bcd7b14ec1da70700e6c8a8a594c88a6719ac4900d0e83312fae5266e00adf35e9a4edd5870fb424138e2f7a387d85bc914a84523851c04962658d068af9d0f9809f8e696b4fcc03373d987e63463d52f42659153bcce50b010c2fb69d9b044f8596805440789015a215273af98808803a39a1df49b4f3105aebbf3d4dd0850067969a677c387a72bd0cb60a321cecb434fc03c1c0bb01e7aa66fda711075079428708d95ef1d5901ebc4bd630828a1da34997eac90eecfdb278c2299b23be2cdebb7a180ecd1c78fcbdb5d9d030ede7d89c2ce3b830d699e8c94ac9c58a9fa38e737396363f00a97a3f98425ace22e53c1a45d409bea352bda0eb45f671c33b531191071b069fb3ccbcfdd1bf10902d3774c72cdf9ff8d46c92257c225542f88d4f4cc1a286310a25fb2dff87d0cd8b6faed5077ea3423347c56d162423d443095f1911804680c24a1ce929396bb3eedfb4eb2bcd99277a45eb9ec7f40515090c26e313f2e8298b6dc8f0be8f068316d6a558e7affc3675cdc3457b7253695dfe70975f6050d254e690babaeb0141ca36d3ce9782f91a2c273de9753d3a91e795c9e3c6439af8569c3eec33d56b1e95c6517d4dcc4c0d15e6f7c3da57561315f4ae61809e2efcf058519b9d9047780119815af680c11e62337f9cdbf9c15038c3abe667d1883ab08b1bd42fd18ac2d1606ff9f0d2d1f48d6d020fb032997e54a378e34f93c8a2cf89eead1c03810163d5b146d6e87dad9d78735b70990dd51fe480e733006a9034377ca702e9a5e5fd5df9cb9bc79d199fa3378840a93b99e8f1e82605fb8b1c2cbe65aa36883211d3de58350393a7dde159489d6e37a194d5495018fa9c187b201adf658e1d7f1c3b96fbd10f1e0a94d764c4a9805ce9f0b4c161e16889e05397b23b5500b7a2edebacf64915e54727bb892742849973b487ee4f15dc5a149096713c95f517ab95d35fff8961b2c668854d40fa0e337ec26f960d1ec084dcf9184e91f809694e6c67936927e2f9f60587094a3dd03490ab000d9cbdb53665d0c4083d7715e902ff61398b696f53465f2192c4cc2bfbae35d6e29c24fb2ce69a69775b25a3100af7c36c2b11c65e425ae829f9684932eb9cae8dfd31c8ecdec6c08404881b6207c12a27aac91effb08f2505b55e5df40f796df51fc4edbf69e93cbff99c945b2a33a677799d545b8916d393a6e404e4c4995b536f7b31e1682fc75bc729c0d2e271f730dabf4c3d6707f7e356a8c0e8e8002741de7da93a0793a7fe4606156e5ca2646a093668f5535837f1990ae2faefcbb3d519f3f0a5f2a8145fb7d98a87f89b46fb10a3a16cc5869eab80b5914dbe5c339ef9d577b1a650f3dd626f109c4ca4e23fb79fd9df55395c850366ce20d73e454e7ce4cb3fd6e8272139eb4be346ea5c5ca8e1439a0ffb4140ff0b8becf83210bfda35791832a4233c019ea29e45c71674724c6e4f3d3decb02c91cb78bc39db0b15e68e20be075195c5608f96dd440df8e1c97fa3beb0fac0d3a5847476172be5c4d7001e64762cc39cb73fb9b10aadb9c4653ed671d9029e32f769291edf4c368059d507c6d7aba3ce2c8a27f574e1e357cbefbdbb17a6eac2adbc163263adabe86bf5be946b61a919299d49a146723be85a4e5a1859bd6b887e382f009ca7890e0b88f85afd1b54852d5f3f592fa5be7213afbcbae11b7ae1b0a6ffc2fc1cff7b9fec424bda1807dd3fb75a2b6b9c2da85c81e7e7e96846f3ebe610221695fd6b0f1cde6832f60f34190bad790eb68c76016579f8b59584e9eb36480f356141427c8c26cfddb5809c10cab71855c400080b205810980aa6d17bc8a092602ad44dd2bd17e4f8dec7954adc8cfe653dffe7eb100a20f0c6283e6b3cfe469671b08b53ddb39bf08d40a6b0566933bb0ed3a9488e7cd8309ea63c3c44f21f682e46ecfe30cb63636662f5e42face9cba6126d06d9aa755c7ee5295b5065edfe412246c239a70891013857731b85c09e385bdee428b6fd46ea180a964ce8284667c56eac5407c8a6eb8acdecdaa8c8957d19ef6b73ebd7c9a740a1f43e2e40ebbdf2dc6f3c2f3cacbfac1147401eb6ff93ce38657227ff0e0ece3a8dadf6d48ba6d548f50eba393c952bb56c6770734186d081bc937c95937ff01f148db231930404d9ac849076894cea120bb113c43f6512383d3c8913fb19564acee07372f4d640b12b5cdb466fe23fcafb6cba26596e4783333ab6d147e0e34610f0629dc0304956f127eadc55fefaaff31698c02cdc6e595f43a8ce3a32d4ea8768f384243f5266c8496db54053d64e0ae8aff016fa0d42ae9cd2505c7f7f127e917db5c50daa115525782035f18f605d2ce16ed7bf398198ffb412f367ba31d2bd7eef3644d1b202873650a57bbcb5b1b913079c8a363b4024f39105e0f940d5652499b2efe6ca168412daa2b0a78d12ca2fa96b42fe77d86ca8e79f4bc83395792c5e914115c76acc41aaabef63a661079794f3398e7006ce2cbdb86becdec37615657acff6b7ef738ef6d96cf16c9a7812d1d13750c0685c9a9bebcf1ca42a750ecc16d9e5b7099b71e90ab5350d3d7fa329b116d0852dc2793a898849680597df330a2d66f84a92fe217754207b1eebbd1d522480e9f6c43a06203544e598bf58812df48a78c0361c2b0454831c77cbd8745efefca93cdbee22d3d9d0e3a866b1dcce495d128d86c9f7f626148d157889903c6ee4d46b68a5045a3d625b6bcc878a8fcc10c6b2cc3e73080104ca3b9cbda6467316289352b4fad01dd3114cc3939908f40569eccafdd7d78008d80a92b168e91a953ae1b3ee934e7b9c7c26e5c039a5a54a3baf1389c6ac1cf40414b01b0887c0843853b17f00b5ce8cb20b0155c8bc269209775d94e159c41a4e8d17790152990f1a94481467301d9a04215fc14a4e151ad2edc3b27844ff25bcad691279f79777f31868aa8c14e28e4b363b1cb4505b69e73814727690f7f6c16d4b666c3dc30403817a04d928c55ded11e3e38a84d502d6f081a4d6bc619f504c242d832601782bb183bf2f8212a32753f3a7941d67ce20ef1d169d4addde193219d442bc3572eae83214ee956035936808efe6e869ea620c4fac710e1a20a847aa8c0b2a8d3125f8f6be3b5125f769840baf4e28c3b339399dc97e7ef43975e0f670ee0a75c9782adb8227cf38e21605a7a2807f609a028aa4f85f560501ec2838fe9b20e1d1d80bd54ba2d33e3fc80853817c31ce89fab8241087ba692b2645a8073da448d10b91fca3d936ad18929671849620269bf762bd7ac7da155fdf519249d42d5bbd8f4cc28145e40346bd0838dbb1a2afe1ceae2f84695833cda626a74a2b80add071ce8c040c35364984d3b690197f247683480822faad7617849938bf8e8a7767aa53c745270f5006f242917ff3fdde85363509aae78e7ff4f22875faa7ba441b17f9b5c86dd4b59c5f1b7b384a9dca6b93a1924814178c47b499d0495a3994d814cf1ba783776d594caf44e486d32b9a4aadec48eef161d8c38084d8ec71812f42b32a22da9e9c0d46a80b09d36d8c286b46121a77ae93581794eb2e7707acfad235d194143e1387935638dd75326e3d78f2bcdb7c1dc2e6b5e13de4ce5e459c8f96940b7e55b01d63867b97c6b6b84d6fafa2b9fccd26213517c96c185d89ec5133e0e082cf537d64b578c4a3011bc38898826504060766afdc3b1b3fdb9424855e1fa7ae1fe7433aa1aac0911bad07fe73ee5ad7f20fe3185d5c5c9990f37dd7d53afe4d3376c46627c7b130d006f477673696b83bb9c08617b2fedb51c3181afd6b2f76933bf45185d4d5c8f09bc6f334602ef124476423ea8c9b2613420c22eff0bc33bfd7fdbcd7bfae058157a757071c280f401510d4f8f430ec0e1775a13c9fefc3b49d6681585478e936111257b4cb4b61b131ba453ac615bb401393b95534aee4058e8827b120178b59464d11eeeb9220dfcbfc34e52d3c830883e862c078f0c0c2596dfb14f7a97c3a63895fd6b3676ca2a9550310da152f236e307e23ae52192a036ddf51fd44374ff5d85f631f1cff1ee039de2e58f4869a9154b31f6297e06091383b9eccde80ab05ed12cccd238d39cf441a44dd89c9b3826f282808deb15516d799445d26743096bb90050d9b9595794a218c7f072c49d3e7b1dd4a83cbbdeca942a27c2eaeb150bfa035988881cdc864d533a89a27b68078a53840c034eca9b4ed88394c9b8588e08c4aa1b78a0bd1615a7b0d8b3a4d75c507f14f767c086f0e7409c93c0f327b0cc42c1f6789daa1cfce4bf9629e9486cf488fd3c2472519b54411ad5f525afea4c19acd3341fd6a16dfc7330a2b53cca6b21ed0e4c09815363eb655c29183f3152f6fb45bd0a0359990982c1ad75aac826bcc481f22f96af8c0287a4be007cc22908dd37c5f39a3f5b147f32efb3c26801a9cc87dcadb9c7ef31593af0848464cd4a8ac42136ba754e41f368afc87cda3bd0c607aac2444c25968d610e018b5ad43534fede8e89bff0cb08d4469cb9ee5b988f9c91a845c11d332510dc99e7ce261059c693b55cc0b987365674dbce30ae0f9d49dec275e8a464d6d246209b05d58a49badcd02d93732e30635ec75d136643451c6b1a91031e83946563614fd68fb054f1114191a927e0bf7d3cc528c979b78e5fad1fc89e7eb70ffa289c9b39b793b5c7690c0849ad48b065f44327fc403e758ce34b36ac7db4af4f84a1b83c16bc5a6f1fc1e5dcc0b229c4753e3b841e91c6e56f45826111c8e31c01697c197a07c34d883e76838f3f49debe684b971a49971dcf3e40a718c1e8bcb6e0530041ab0458c13e5861b1fbd08115e7c7d68fff2558e13a9f97613116caaa81154ef6a41e09567864c6e0a5f0c1062888bab966a913a96039e3b3482a764a4a938e221581084067a4e271b995615cefbd6db2480548bda113520123a211e62443bbabce8354ec2e2854a5011a545f96dbaaefefed784aea02f3e23d648a4fa7a75cadff7fc4db9a11e85dd9e1c868e551e0535458c2a89ced8d4d2d7f59231db8dc51672e61ca8db4ae0e40d7235c08248919997b9905be327d467eb48c771646b0e04a2e039579e273de0c14db0eed93e3865a9589f8f480a3f1cec90156b3d5265a2bf57decc0bc4b80871dbb09f9d73269b096dc85b8f76fd7fc52b03568f1f34d891b91f8f70d153571190732bc995818b71adcb858ca8be3e6c3670467520cc0f7ddb6bca9d0d2f4ca45ead42e6493ae89abecbc176084cdff4a1fd0e54bfe79e629f886d3a9f7082037b8e5b1210c30950e74bb816e06962a16ed5ad0017c92e5a42888f29896f234875727556313d5b1ab83fd5dc3989d9833bab4b9a34dc2a614b9186adb8d88155007ef22ce979742abeef5f18504fcbce094f45a25209f1890531be7f21b04a9557494c2763564486a3c2a33461e68f3222d40e96dd2040d04370f4be97f9a3e4bb78bf87d8e12ac77a5ff5017bd356165bfc3bc901a1522c134c04af23b6460f1da8c218ef75485d53f45614225991a2d26b80cd52a11115f43352a925702a0390ffcc4a208fecf84d1a9519fe62dad6ccf64ccec5ed539f00b5f833ea0e5688adc95dcfa43940d99929e8316cb7f72d6b713e48e5028391cda0b70d0df1ed5bae60111d3186ba02a4d20d9990eeea0e43152a2c6c8c6dc80cd7ec791c4e9123e10e538cca7efcbbcce121f43296786f4bdeef1d29d213f0c3b729ddaf974f444db2eeaa2fdb8da0ca93244c6743696a70324eeb186c1d76c2487202c79d256a0a60210ab1d1d3472a6e7a644ad0186a207f5611949c05e055107be09f0728fe7932c830421260c8e89a65afec21ac2ff5f34a591534828ae08a2a723570b4bd6c9478d79d5f5d6e25b7e97dd0c475df1bc438a9f12ce97b414eb1d8e11ac58fd1162d66eb3c4808edd66ad5858695f0ed8e7967aa246f868e9b586a1ff06b90ac24f29d98e06cbdc455374d5818e7c6abbf95fbf593ae409df6f64a64687ad103a408b0785353fb89a538ee67b2a59f5b16ba7d561d0b146b4c6258eeefedeb7c17e05e36b326d769706a013992e792970346654dfb0a9855d5294be0700923b8866089082370a032cb610b345c8393e8dad181594e50f2eed3c325704f569503cc2dc3b5a7232362c3114db03c8e737981a90a9b02de86eb385adb5817e60a1bc2d36c3739347ee3dd727367b0eaaca247d83d5c6acc28037bf573bbf553e57d2d1c19bb8ab9a801719132b03805f58a0305859c428b2364df7b391cce6e0bf63c3c61bba9f56288f0026b474bb3ce581da17c8cccb2e7079be5775c7438f61bd8baf92319e21845daba227e56476819b95d76f2c07974df2b63f59643c96aff5df44c5b9bdd2f9095073a18dd1281d0d7461bf357d107fc3a334e987b68147a8eacc2169652b91294c28028fbe3186dc5433f9f39b4aa7e29d62d88a185ecc9cbe84a6bef80fcc201d42e6ce762565b6e5ab72931e44d938cc083970ca89518f874aacff837df968401c720fba0be4ec44bed963b5197f7fb014ef76d65b067562f2547ccc40c185272d27dd7a4221cd16394f57378b93128a9cfdb103af8caa746f3d2b750679297a852ba4bea3443d4fbd660f02c1daac3f064904491c92f094f9b7529c09e0635a2601cff99b12792ba141f3c86712fbb2b9a335acd7b7116d24c744cd39d25e7fcc81b14a3ad8244b8e4cdd64540fbc5c9b197ca6c8f8bebb5e5c6285d41ffc9a9bf77d13ae836e7a4780851fb0c7152d5deca049653001b10417d7db71d5f2df7c28db9fd11dcf93933e62b7e19279c1cebcd61ffdfde988b9e982d1227d0ae9b47e9fedd329d919677357eb708d149a39463b398b204b49363eb59ab151453e414dd63f30174c85e293d24f0ba64c04ca4a354faa714a6fec73a9990f036be4dfe169caa0262054f536554d653205b3fee32d71f7cd74fd2c0a3840554e36707c54aec2e9e91dc3897aee249a64ac81c0816a7f396b842a7e334e84ec7330fe0caf04e819c255bef892b90c6cbb6b1527b77e9ea4a5159eccf54916a30161d49ea4ae3a8c8c3b245a03eda2725be4e9d10b59b8278393bbc5bdbaa26d3c4cb7bc3812b4e847d274036db5838c72bf04b35803a99b622b4c42f1405e35afe4dbfe87b62e36b97791ec561f6110f14fb57402677dc9115ca387704e5bebd1db4547220e0e9e2233e6fcde37f03ffae46ad1a135b4eae688c73827d28115531bdda9e37637afea63abbf41160bc3ec35dba95ec5244a3bb0c421233eea3d57eca514ff3e4949d6788ff689d0ca7ca93a10586da02342feb7d6213dc1b8b4e3cf3a9580735f2dee0d2b73eb2451756b28a8f6fcf49fc44ab90b326f811be76b86e4c951e75c6e1c67e00e1a1af3563b59d4471fe9c2ddda9e75d00dce73e34319a2bb972db290219d14d7bd5c05d8c93cfc93838b8104ea94bf1baa809c7f985d563307631e96a173eb8a72fee6bc3a53ede915a2c41ce890ea5eceaf03ca2b6e165cfdc1fc4737c33ff86284204fda78fa80bcfd0071ecdc281b6b2199db5ae8edecaaab63ecc45e94ce51a424234f9593ca0a4b1482b150183c41faafb9f3586a11333b0fccffa47e61e66151b5122c3e1bf02fda762c383946c0b4121dedaa5ea8d41cd9979a6e30fd354064e5cc838e31da395d032634530ec795fc45fc28b283dfce1c5909ac3a846e6f32b98816588ee2d29e687645de4a3c0d9600acfb05beeb6134d8d968169648c88efc168dac9e27b6f09bb3fc88b1982b1710ce9d16c9444bac7c934a6704e04c9e9e861d0e45dc53aabeba1682cf48bd914d7ffe6a3fa54ff55300dd1f383210fe631896b06d6813be92a4f8d262d26a020678b9c3f488d68bd0bb65dc3d6456d89a7e3b8f329c22c74301ce68cd22decd89658ef9523eb2f2c2ce071972140797820b65944933207f2f4eee4d156dde39f452e36b0e8c207f6f2e94d05ca17b244508972cfb6f4188f8396e720cff8591f8ef31299ad95c913991e2bc89021b9b22344bbd657f5a7746afe51a6d935d016be54ad1feab372d05a2016f6b0b31b38af532d1eb6290b975331206401c9a01d65c90bfb94b98b7459a683132eff46ab8ef32e9e8413e3862b8851a5c8d0a2bca628e82b09ee04bf43bc2f88c8cbb7c2c5d0f38206fa4b4e5c3e5514508cc8f1f6d399bf52f01b9aefa029658b99e00b7d805889541f2f99dcbd9d938ee4ca25033b1e9a53f360498921e3857175feeba8adbf190ab89371f17f6660102c056fbd17ec65b6fbf82b41056df3ca448b0d0e7cdf6a87c4a00ab2a9a46d4cead80d4402ca705d9473b3f253c08f016685a001f6d17f3392015d199a3e0bad10debe94a8a102fc3a1af51f31da7038b53c56e0f2cb990b7f00515c2591e0784aa5cc77315481e04df81b3f546041093b333b97a3f5384674b419d0e01befe69dca8044e0e38f84b8e70e52c1c19dfcda9d0f0487aff43cc81a233d0d03442c64fa56b0ee9ba840df2f7a171c33f77e2720c0c0f9efbb37f1dd4f8d5785b5584b939e0d733898a7362b9720618567297bfe900544ad65657937d9c10fdddf6bb712b46d2c8efbfb40967ba01d5c18d3fd552d8e6d419e33ea96017c1528f3d953e0ef1260e3e00bccc25d439116c9b9b668b7011eec9fd774a24e8e0b48436efcb40b32f82be6bb1f546018f8376f302a3ed1d03f60f1c91130c217be0226a93d973accb576cfcad34526fccd8aefa1ab05a9503f8e5806638fe32e2ca67868b761156207188d6a673f562642f5f8c0bd729abd329f39660c3a113f610242a3880e3d4e7da64505f47f609de7ecf4d02c8238a8906f6af0ad7a7f2fb332872a795723b72d53d57543ccaa6e3530e7bda40e384b96be293c6163507566bce5381fb514fdef96ed16b741c02588c0399448cf877959441444523318e1f9bdd5f36013d9116197d781bceb1ccc8537a21dfdde85b2deee86cdfa79e0b89d130a32c1c523df4c085c2c33f1a6c501f8afd7664fdb9e1212cd6d438527ccec224037cd57ffdd16454636f258ef1de170b45bcfb30b6986b6b65c4b906e111aca090b581d6cba86c764fb54c2b7be5ef1af3f13de4cfcaf2d7e8cd83562aabfd1d90944b3bae6cb2fbe2198dd898ea93d93a4a3f95026a80324a780ed70de2ada5c86a1d19382ee6e1728895ffc138b421a1894817e50d02d3b23f4f5d9602092add60a749e283b36be262d17d8456e1ff169d6d9db3a47012009a8fd629d75bccdca033015da985e92fab278bc9f31a13e4e9caa260dc0525a69643cfed3b1f7deb09d9069757d3cb63b1061c419e6077476b48562f83858300443506d0e313d868d84079def8816bed8440b9f1cef62d7a8cc62cd83f4a6aef79c62eaa693fccc29973ac65d31eee2892b5f266408842976c884f601cad25fd65acbbb99fb7d0f67e6ab821659f8f3c4c8d5955b57e53b23ae65796f96a1b5df54564780288ea6ac3ddd0141b5fa19be7be364c27eb1624995cb0d9b0739e7140b04edecaba4f8855bc9f3af8318d90367a26451b7f5fb389b5ed48e7d0b2bbe9e3537db146d23e278cbd137cac1626e8cffc730abbb8f89cb5b3d88fc6452b9c4074956fb889cdba8bf1c565c12b4763da7ac3f152db8fc306373ee9df499ad4f0eac3e34c3bd3b725f3727c59b8d48afc95555478e32f1a0f62abc491084850acb6e0bc98b326dc97f7b2069130f00593ce49af941de7127f0453064b91a907bdf415a91ddcedce19a69bb30b177a6829151e548c56d341e7905d7bcf38d52bbc76a67868102a52124acc598fcf041dfceebdf6ade68fe46afdfa29a142198918247ca93cd710bc4f05178f03e8d104cf7a1d89dbe54bd7f224cb0c826d255cbf2c77e5da041382faba031ba8b2346586f858b77be356afd3b6d449d8da8da69fa8a98ea3ea48cbd3503ee57d7e21edb41e6011aefced544ba85575a02b666cdba370e99e82f61f25aacc6810f5c8efa1a34685960b80388fd0bf068b5110972b9eef5858317049eb38adfa539712cef31d4eb0d935d3df00799ee7570e574757258e4af79669abfa208d4aa4370bd65441a979b021e618c0c8fb388dbe1002445db8e2e5aff851810df66fb205d2e010a72cf84ddd2a3b8a1249b5c4a1be7a63e8dd83d9e2467c61736495d2822b701779407bdd4ab01fd8d9bd97d32845985db09aca618875ab0bac233a4c1a2225a9f9e0af9eb2f6e53d6c628b2d791d3c0df1db6fbe21786beeb8cdb491ec7a548904e41d96530d31616fe3fc7868a722f22c5d3c6a961c895aa9bde0f5b679f9c0894bcad7183bc887d54b31bb1b542031d31b8259f8edfa1e3f23df965cd856abd199bee9d8cdedd7fa4eca3b0fd8035a9e6bf68a16d195341df2b34eda95a89a1d8afd392e83560690f7be05cdacb1cb064c90dabd02b28a7154dd4f840256ffa9ebb1e5b0b351772a195e72ee9145601678b4acab5e78c2c91e46c0dbb18a59413d156e0a4932cc735ccbce4acfb4a033f712caec899da3b584c11b87309820ba17b40fa7a0da8835bb632130fa541c8ef7976fcb5993324466ac629a41a87867ed75b313fe96e669842c6f39c4c09b4c19f3ad476abc1cd915bb2f9ad659f1df9fc1b7cc4f32c632895eca2f874d81b0c3ac2d2e90937bb117d943cfdf63fef524d8c8da7ef3cd6334465c883f16d0e980759e262a2a3328d5b6abf006236955fd4b8910dda46ae9d376eac86ef4e210adc883c82c0e17a6354a85a83b367db71aaadf51cbd0c297dc2da8e9efa1fbd67aa226cd4a69c150d8c843ddadfa129bcc7ebbc9f9c6d81dcc9d8ed54c22d513f527f23ca4f215402136c9385f74f1361dc3086c4d8c0da537b63217c4660de9ea3e2230f2279d65c6653e02eaff23c8931cfeb8e5fffb1ce55ad6b410abe6f925089a103c04b867a5cf3fb1ad56dfbe9338829f8f9098fe6eeab88c2b87ac7ed654543fbc31280994026fb697c0134043a873ba073f097f835e1ffe5b3f4132c8c0eb3a4a885c2379489331bdd63fd063165dbb600e31770860d378f1d0bf1ff8b4c65cda6492a9bc407d3f7c91a916232672fa070e5a9cdc514d3a74866af2f11f83b898165c2d712681b7617d646d444030ceec0aa90dc695bb88ec1c9c8f1de8757d08c9ca63409b3a3dba33cd768463660c2e2c5855bd4d490eb334a2db335ee93f1912b1ec1a8fd41fb6858197f89996b9f9780065e4b94318c27d296e33f25a63e7b96bb412378656347c98199995732ae7cbc86f489bbfa780e4a8490a208098c0024330b032a23e606c78df1f837107dae01c7c28adf50d0e16e63a6aee804358f8aae14adc63d46a01c09c50f8df4a5a6812db936c11ff1a494785449319d191a45fa3ac90d7430d1117401ab94a569a4effcf519f74331d7da54a1720f7a2729c24062bc5246e8fb9f4eb4348a747120ec0410efe27ff7bf2f476accb111a75cf471296e4f89f44cdafb6a780f53fc1b7a52da161e79999b871fc00c7acd6ff2cf74ea5e34d3a306fa7ecc6af5afe93369e1cf03703e01b88d2cec4513040f08a31e9d6cc4202c3d75bc6967413357feed846cd65da97551c6b931f72e21a69fc50e0300a866934814ba06c3657d221141a1bf2e40761a73a0114bdc77a6260340ec96ca7f15525473bd0564a28e8003dfd10f1055861a01656f766bf5ec069fef58511e6fe799b8432980767088a532ce56e4c9714ad0c5d019a24ca60c2cad218bf7dcb54b15ecf23c8a2ec42f99da6c106baf600ee4d3c9da8345bdd8218e2baf28c5c3df99c1d0a953123c0f16ab8151a146c4a4f20e39c30f50e8ba34ac5d7e6a7b4ed84975ab5c02aa4cd9b0ac73178a92439b303f527f3a912512662708e8c73cc715fadb8fd92c81e3bde1de5348e9475fb02c3f70842d486df3a259fa6f423b16e375492fab6f816c4890815c7d6b84ec57885c271284437fc6aa6322aec978d0b9c476c7f3cadee1c0ab4010e81a7d37d045b1d4bf872174c8740962c798461fcecb63b41dae15406e36df46eca41132eca42393dc782b03bc63573e171cbf5fe9f126cb409fd8f05ce68322a52334e5f65144581d1f397fff56c4c901437fdd77f0a5417bc61038d3e30e37f29fea030f888958f12df1f51dd57f711631c50d140ba45e0673a002244c00d8287c8a0137ab94062197698d66daff4b1b96c71cc181c39c64e88c3033d2f167c39a60160271fe64c0a5241dff2b85810d8add7e5e9a46a34e501165243169781b1ae68370fcfe6117471fa0125010340f3c4ba6362e35512f4e126c6707e7af3a74d00ee7acea5e3e8bbbb0eeb25037a4afe9bfe9155af870bcca4534eb12b261d4db15c97bb3bf5b6adc087b1dea056a757d61be83a5163db3aee9a7b28160b1b108f8c50227c4e97c3f83964bf52cb512ddf268b99cc5bee096262435c9aeb84f4c8e44ce0da6ffb7387b8e8805b93543e290a23e18b4b4384cd2439753536ee62d5a2abe62ec0d0c0a4e23698c9002d6d6f2d7a89964a2f3b128f61463a61207f9c24e9efe87d58db84976d236e094a4e4e7332ee668f5248d7fe322d66dce600bec454aa7b8af972b453cea8dda0f1c640ca686be207db72a8bd49d9461d30e2e226ea09bfa55c941e8c800e8c6abc87f5caa1273d61c1dd7f67327f9800fa3181b67327543604711968e4874d6a7980e97c3fd6ba6afad9ebc1a399eb5e25c9265d71f34022a4f647651e3d1081fada8d2c5798d4c29eb3cda7525d223b19d405d8fb1fba22bef8f2ffaa32d104a796404c8d03b4c8079e9d4c832e3310a83a1d68369169c468d36666e68e6804b1594718a0c741765b73a106bf37f810702ab6ddd69bec9be2a0fa13d31afb52a6143230d22eb92e8bbcc704c5b7648192c711e0fa9c26c4ed1676f0a6db3f0b2fe67769b27b3143d2de4412324eaaeaf5715258e83b0e7efe841947dab58b7ad388820d41d424d7e20bf56de23e3f4fd1a385d879e4a44424dd0e5ae58849a6da0da3f4e34880e3d248147c6d0e71258265cfb7c76f0b6a3bf44e578cde4dde223f902aaa43c5d170459a7ee8be400f3e2b53a2cf124ac337f8a37dcd9191ef91c56bdbddb172b4ae14af5549fe410541be8f9cfb6e1f2aec4c70775e65c46f670adbf15956771e40243b3e07cf8ce6e4817534ab148d0094973ffb43474b41d472522a5c0f81c7c50b0dd2fa2d24543c1ab750bec4353da50c2836223382fce9c2ee439c1d723265d8f4042b86fe454bb2393479e04bcc3abd9c463a0fa8cb9fbe2aa0c3cf6468f52320759e8e8ad91d4f91f21883d39f42a4cb2f8138d448af460ecf387614c6d7c92898d276a10e7900035b760432ba27f402c63e740df99709271a40033e6e455485e793e4e086e650f8318b06fecd169ab6f2b17cc613355c519990bf24a3f115a394f2ad4b73da4bd1066fe1e5935e3410c3610ca1bc888ad5114dfd13c94c71c135820f4812eba7906dbe83053cce60c3d88fa161e84a14fdf1ea28b7d753618b6e2588792ea9167d78038fc3f1593e06b32da71363fb3f7004fda0269abccbede9882e98bf5179e36790aabc164e8c4eb60286260186c33bc449d3a5e6d0f02e0306b6de6ae60b2881a32f8d60e18f0cb1de1569c16321c62e461de2cdb9348f27ede112ca8838250c497f2f4f768c1f553ec4114d7bc58639bf204c018dc805f4135896faaf49095f03d0fc4e01ccbe831a453b010bf60f6c29a5919059e3814adc78328640be0d96306f027b7999a126fd0111d1459dd2fb0c360cbd0e43a95d26c68cbb81b1a70983a470398a8e4de773dee304f3979b3cb95e184b1e82518d5b5990dc5b512f57f482ca87ca11e66f1ad3b4d28c8243181bf551e8ce1c4c96762b6b929faada6e51cab9afe3b7e635c1d8e11ad28cbc1a4249aee1d024171b71e6a91c59f8e0e3953f6943e576d2eebc885d0c6731e9864789a33a1e47b0ef4126c0ae6bdf7c8db31acfc7f5e6a38ca5790bc1ce239552d36a4f50fd80c3f99d2036782a9b2c3916ab032e28fad4a7aea03c5f9425ba9306269ee490984fa728ba27446def8cfbf1588ebeecb6b3235fa5cf9cf75388876f8954c205ebda7c5b5c052f0504eb4730b6f14d6e70bf49ccc086dbb2e8211c31f82940f3573a017f9a2c081e42120a9fe5e1fef75abf5a81f53ad2da675117e9ff32205d13e2fa70fc1837f252dc4757fcf67366f51e56b08ec80a8c5f6a64fc4d0266f8960d969e898bbcffc25842439b1cfa1636c89d65a6d047df2d9aec4b953ba956ffe4cf9cf7d961e93283b2bcbc726d471d80be8e1ebaedd6727ac6005ac7e81a74327e66e83363d29ef9f8b5c958107a36cd4c9a072745374300eddd48d2f468277e3893bd280f612ee14506157a5a8d78bbd8c2f748506e1e83901ade062ad1e574b92ea4c7d5063509868bf5b0da8cd4297ec04c70832052e611caaa9b8a8711df56c5d157696bddc3999c5dd686c6df447a3f076cd47f756af33f3a18fa90067b5f07f0f19b40623788c216fee9cfea9b869c0bda7aa0332872f157245de9319d4ef89702875e75eac13b9afb348db6276f8a10166f5340cf957d335c089793cf8107903e1025ccaf1920a31f9d797c3e2c92ec28646bbeb052127f38187cc580033b41b48d079ae2d82708a904f90a44874f6f8d1fba39045e1f0e2c62441f9d0a950608e25f8d2d3bb6127c7a820691a11c74bc8c2ae315ca44de293b515d473ab06144c5874c13c430205f501536762170636410053619148710f9d368250ec107bed3204878723c51674a17c2460d0388a46199a0e1d222472f48c3065a82101c9d720c98d1498bdc0940877c5e2e5965caa420d2328805d984cb86493a54e828b2a549580995811f6d168870c2b5183df4280a10a2317916088638537442478090332a68e7091ebe390f8ec2535781a5e191113fd8390f600346ec4042b402f5a0119ab9eb43110f3e280cd2f972058a91811b2b127d4992c41031070fac214c13024e1e4c8afb4a380aace4e242a5c0163f80507020e140826492352489a6c86e880a24297502e4661f5e298380264b1326823d000ee5c6ceea1a68880b6441f561880a2a7b21aaca9c117b66fc9736254d7658460e12158b4b309d00948426dd5b30970021182a45833f0813b4c2fecc38318404ca6f5026342836020b07e0e032c6479e0e4193ac08b05cb63c411924f188e4510089aa32037e8299053d74f87190c1015009bc3f424a1b8c121da619b121e78a041b81964ea25d34cd3984c387271d0250419ac10894c972a00aeec1cc24c4eb14343820cdedab0702ad06666c06ec01f20ae1e2cdd9e3216205c63d803e520e3c7098bc59f606a1393558e1d3c9cb912862369865b535da530a4d089a0a615db6f34f1a01d8ef860538582099bd80a3f44346043371d21c12d1803236532aa85c458da8705277c7065b0e397204d60815c01c4e0a78baa354240f9a252d8ab4e1a323106f709af8d7a1f0b08a0b8fa348121c556131c7e96f47a9917e68f93485f850d1685194d628d29d0d531e55502b789a5a701305e5c1162d4677a23c09c1a0b9a511c29643114dca0cad1c896a105bb20981da13504b58bab5442a24b1a00b63000a9b3f8c5346f216ae1a649bc4845d98a3a34d6c48ba8941d3ab45dd224872e23439b2f685ae4db300e48ad4171b531d31fcf844e85b53e9c3609f2043162e0ea90b9a1aac645419a15c9a8e62e4c68da00fe58bb989c0118b136b36d438f0480e0c8c247a7d285075e19375aa8c34d92775dc03552128290901a092ad8f81b9d12050724c310eb87b6b54f561ace41568852606e08c986c2fce8084518522922e469cb092e4f6b48083d099e8c0aad2154f849e245e0031818b9a28703af038a40453983e404de7006e7148330056959a9c80c22b118f4ab049da12186a71be513766c8c3d42180416b2c1cb6a43b8892992aa0f4aca65a24c17181a3a4890d33c9839ba36c8d8c2763767c9a6128c69a8049ee33b5e4f44b9b8467819367bc88ea04022186e6ea1840c4c8ce92164158f26031c474c74f12085d2a909972f2ba90439b8520b1e4395817816b537283960b4242438d141e6e646c32839287c31125290abf44b8241f309c782097d7d51647adc995990c1635431d5b030b6b56cec418b88354e28cc85a6532c78513d304c1118e3e0d405c80486392468007248a3019c291e3e7881f3b2326ace25c95d243a4d1923f31c3b1193d0575c110d3a1d1e193f3cd0007532347ee9072d3047977a794a80b83b85499739cd364d31b2ac0116ffc6021149448ce445a3cb0420899178670dc70a22343888b2d01a1acbef0b1d2e7542135017f55084f16d9acfc1920d4028e0109ca812e1c0362dc1194b365518c574b16b237b0ae4943e09ce982818b151947402cd610c9788249c2e62e000711787ba2f864ad9053e7c6469ea311a968344a483529521d125b4ef4cc96b87802060d4e9b01502332102c28b9788a24fa08524de4004a511d0f25374c7d29c022edd3963f4b12ad9963186aca091b81a74ef199a9c38499a08806ace7fa546c73ccb25c31d1cb46a2e6b30d20b81eec19f3d620a22849866259dc9a32860a87485881b675556182537a4a4a49c98d13ee27c54c451e810d7273a781829f4eeb23410e7c004056e15a2334fd7003c6a39a511cf6d8289923c8e209b689eb04a61d44242fc2eac5a69d58f0c7b7298b26003e703c20f507c78a129ee6147271e120a61d88dbf31247f16a4af51284c18c2c1d0c477550e3276fc6beca5285a8b18fc68732bde78c4b830120fc820036d11107f1ab2b159d17155694206576001429312bbe4494005446e90009108751a32ebf844593232838285a73672ccfa11aeb823aa0ce09020b63be607adc4300e95b9af274644a44336b60a3b4b46bb30276d425698b03bd32f1123cae344cea74b9f18709d9290b8c51c004f23356a541c9d23a7646ee049935809348cc1903156342068c25589ec829b2d7a18728296d14c1719a68e10232931cc4605017018139e0b22c086184534251ce11420d2a645c0c323d2aa0549464a152a62bbb6898b608483789cef8f1b0d7a34e9e20af06080a318764141cf088a061831828a81cb35269a949d8e4068b541a042b3565ca28e0a02160ae858fb9d220750a1516d44bf1201d822404fa127587c4ca204570e093489c25738424aab4e7cc2227edcda32b30236ba628fca4d41b058a2470124e5a7c4d7880d28656a14080c32d3760c0698bc1e5ce8d36447af00462e858880b09b9cf48aeda931e2b08343e29c117c2d1bb868da8b5520a804811bca822d2e00d1001919c07af326e7a47e2c31409ec10081565012207157d31aa06d01987667dc64c286ef06120459cbf2ea7ab04ee90431d055100ad3164f1c805b603cf1050a51c3b1449f804e643446224350c22a550e469ce049f232506700dc91bb4f2d629169aa26a68e104c3125473e4545ea6335f486915c4a5658bccb1e62c8e05ddd23e2a1170405d1a99b97b15264bee7ee487fb54b01a5367bfb89af71753a762d44b9cdcab2c1df12946a45e49c0a43c4a93dc0fd30e2f806d114912a42d081790143ff4506528dcdf1f55666b5d78c93aa57f676dd52347ee558d182d72af5294c8bdaa0c221e5e8551b3766e3a5305019f766a6f6642f25f9f893f4679eee25e35888f3cc3fdfd09aa0a141584ba570192fbeeccd579fa8c4ad1aa4fb3aa3f32192fae1f87fb2cd9c278ca858fb7c9c2783a35c3c1e78e63843b95ea5ea5274f1ef7b9eeef4f504d4af7e78ca56ff29f746d76d13797e65e85c7ab5369a0741aad03ec8bffd0a474b39af42d309ed2cd80f1db5f3ca749dffc9ed2b6588ee3f78cab73542d77ec80e1a2e85ed5a50e35d48c37de96007c12ca6cc912ee5574dcbd6a4e151a390ef8b48bd6c9b37b559c2a38680454a19142a36c7f7f826fee556fa8556eaadab0a95a43278576a95293c6bd2a114d61551a438ea1b7150385fb0c1847dde599c2d9cfbdcaccbab685f388aa325564e26a2cbb578df1c279c45f5c25a63a8d03ddabc2b87b95dc3715fc8b73af02f3173ba57f21e6679fb4443cb755cddcabbe004aa3d1988f6e9e4add64b63e2f7e7d51a99b7b5597e660dfdedcf617f73dfb64411173da8a108567ee555caab6546571bfa954adf04c8ece55ea6c424efa943ea526dcabb46499a7523e6a8c16ed933eab7d67c9c1b1b12a2c56dcabae58d92aac5465658e8e3a4fe735d6aeb54bdab9764abba5dd6b07db8d8db583546adb2607c7c6dae4e0d8583b981c2c9342a36cd4b2e8dc4618bb4da5d13ec0b2b81acb6532dbd8d8740e14a4024aa3b30c288d52a954f9afcf4419d9732e210895f1e0ea348e2b94a567d5691c28b315cad2b3b2b23649d626ebaad4a814cd6b032c4806b7ac202c5838fbb94b41b9af4d0a960d1ad812bce35854fc0882116ce25e85634b908d7bd50d1beeae77159d98a097cbd1f92f7e5efd0e6065f50034886d5509bfad0a9051a38ac68cff4085f3576c0d13d44a9ec507be743ae75e2523461c6ddf9795db9683ecb6b3122a27671976c64a770e93ab546934accf2fd039b7a80a0646d9a07072b4598df609024e67ba3a1656d8b36a9f733d73f733193b660456caa4e9d0b369b3159866f5b725ade4ee01607cd0215dddaf04a46d45cba48aa601a680f302ca93263a0c0da765d53e3f9bced1689f5787d60bcc2b3affad5e1e24784567a5df10ea54ec390f82f2200a8c97b30beeae6488900f5b2bfe567c5fcc8716858b2b7c96399f74ce67350e2d3a48150c7c96399f743309b2e75cc20d6fc902e6e1b9ee527016a452fb96ace05e1f356fae4a0559f031d8da7351c8b7f60ef9d65e2277e72a5d09577757ab9a56b1d01056032abb85f0008de3d4a9d81654ceccbd2ad0bd4a1a75399ea7ee527086f376302f2f902a9b9233c98930788d6df0ca83ced30b742da45458f03997a0f6059a51fb02e3bd682060df73115d88b2ade707afce73b234ea54e3eece0bfe67b6623579d4ad58cb9d060c087a14dc3dc5ec4e9d8a51ab7195ea24c956528dce3e7250e7e9176ea9c822dd49e4c0b93a7bc974d2b79fa5d00d5757575703a2f1596175da27cbb3d9161e963fd94a11e75b28eca66cdd11027b71f7f5a52472e247ded609423b1c554f30bb2ac22d1389ee7d521305b64cf43921752af606b56212239a62c3060f651ebc3010ca7d17aad0b96d6caccab7d7273785ab42e7362f2f2faf688a175e84725f1e00e615000156a5f07820d3e0159dfff29c65565c5b738d3ecbd2e85ce296dc2997f3fb8be7b9791a27fb168934df2201e75b24ea7c8b44ec5b24007d8b44a16f91a851c0a56f735f9afc2728455373afb283ab8ae5a8557aee5ee55e95e7ee55ee552aeea2d2bec2b84dfae65e85e7ee555529aadcab5054ddb97b4c959fcd261a955a0d1414f49aa7f1dc27c77cd4e8ec423af5aa0a3abdbcfee2783ac7d3a652a9542a954ad7755dd7755dd74d2693c96432994c26dbb66ddbb66ddb9665599665599665d7766dd7766dd7766dd7766dd7766d994c2693c96432994c188661188661187edff77ddff77ddfe572b95c2e97cbe552a9542a954aa552a9745dd7755dd775dd6432994c2693c964b26ddbb66ddbb66d599665599665d7755dd7755dd7956532994c2693c9643261188661188661f87ddff77ddff77d97cbe572b95c2e974ba552a9542a954aa5d2755dd7755dd77593c96432994c2693c9b66ddbb66ddbb665599665599665579609bf4ba59b6c59374036f7135b693da63387675f955d9509f7aa12ee5575746969ee5573ee5572ee55247c2bcd018616d2c238f0afcf1947d9fabcf8aad33ea757ec15a58a39e33f2f6a2c2677288c6e7500e45b1d1af956874aee7ea0eacd0daf79c7369797d64c83437b6be6c9c1c9c935f39a6d7569706e7976666e63636eb06019e05c65237bce25a87bd2bf39dab7176da281e8c370e15dca5ff539cdf2c1ce9947a5c681551a3254a371b40fb06ffaa4f6c95e8082d119901ab7f092aeed45fbaa53a9d3cc4b6cf69a963572af4ab0e5ee52b6f6a27df21c576335f72aa496fb549ef15ce5d2f510a64dc654f93953abd23f6a55fa37e72e0523e50506c663634c56a96ca7543208ee3e954ea74d33e974be2b3c8b9a99a5fdfdc12d5b27c0c95813f7b1b1bc406a0700eebec50cd5e7845b368f3a9d03ff66bea4202c08b7ac20d3d0bd8a40d580bfe9b4f994fefd992d95ed9abb149ccece2df8870bba6f4f99b626afba72af125015c0bde2251b8d5f1cf354b0ea84c6f39f57da5bb3496786c6a6c64627d7444b936ba679490b673fafa7f4cf5d16ce2396585bca2c46a85faaaefc3e347fd4cd69b192b4034f97158fde16fd10c86120d28e44624188ec8502ab0b8c52890d9b65d6825412b4260bd6a10d611829a4a25224be03070e1d2d04aafc6c07f82d00c06b0f7cd67264080000b9ced569240033345d404055dd0670b51260e369fc87e61557a3f11c810201aaea3600ad758b9d4a03a752b40166687621e6bcfee66a942dabc0aeaadb00b8d62e56c955c56d42dde01715e47b46fbbc602f69d56b1d0364cb1bb1e6b2090ae8edd8a9122343047ec0742b1962abe5b4d52ebabb5e17f76a99fcd0d3db8bb6d256cfcc0ecb2929e68aad6184331f6ba40a4095957b55957bd5aed2eefbd17da772dfa84eb9fbaa440a8db2fdfd09aafdfd09aad985987bb4a84a942db14661847b374c39752a954609673ec299cf6b2fda179de569bc66626eaec66952bac0ba672015103a0716d2399f55996d7e068a8131fda8b1db93da07e8478ddda67374af8f3a05a456e53e593a0d1ca4f6399f55c2393a57e334b96f2b8c900d13e1cecf40aaf35925dca36e851170776aebc55715542b9c4af7e66afc8c0e52b736f04952d3d80ae5d8f9acced538cdf9ac3a9fd50d39dc9dea4607a983d43ef7ed8869439bbbb3ce27dd2e456a94a850a03e79eac46993a69dc9abe2aa324472f7dd8809cc7399f24c10335451a7625b1812f9df9f60b40fc31b0c62dcbdc6a27d3e1e3144e7bfc2699c37ed033020d5853b5b17fef6a56d69539a84e08081020406ec2b65ba421f3d835e510a9800a74ec5e4789e32c55631362c2aa5aec89be5e90cc97d3f72df8e1acd70b4f8c910d39d2833babc8840d6a59a9c317847521e0a4330cc381b2311b56148cd0c03191a44aa12324406213a480efc4c0fc998b2054e0408148f64002a1ab1c58b6c196f24b21d2ed844c676808aa9645498187c8cdc4981e1475b8c242d008491e061408ce7a11f9c2ec40e3138c475810ee9440a4629032512a9a0ecc0a033808be29c0c308c210278f8f5a173847102cb991a970e5130be0cf93c710120ef05273f02624cc16d2fd4a431baa10188da0bc33d49f3f000e8455c1f4cca3144442fba2635258c3aa1c28524c3aa061b42cc7021e65dc2a0f037bb78e1a3871eec45ea42edaa038d30133f5c64453905edd125b030916b67400b176e85578640e97078c743e1d4401b872c51d842b247c819d5a48dc2000dce1653887a42403094812254ec113a29b283cc96d50ae19e96310c749f1209db4c772460c929d522151b0897d293142dee8c2999d328234c8b22cead266dda0a2df2365d98a91b812d2ef419f4c1a1c9dde027431aa6fc889160f04d1c462b5cc46b0679ec49d274e78dc320dd1c04bb28653f06bdce6478694bc5287869a37ab495a79360993ea9de5a08802348e3ca4ce010704f500415418ce2c010104c00a76806f50d59d5510131ad9cc767954b881a97fe2479521504c4a7aeea82ab6a26c84291a83b5b55029b1c203171250795d10e129742b92aaa94466726d8a9faa1fe2d695335a5ab415d3e5afda018dc43d56f40a830f2084cf7887881c991e532458ce2e16104148fa9f34d002968a2044dc3524d9940e934c762542a390a180049c4624eeb2e724108128b2067d4a02272c28f85dd2107d66cab040b0a59c0e2b8a2acc04d542913d788a5c034182a2498b3852e108717a6b4263bd002e3baeafcc460f6096430870d8d3b296648233541b20750c1a2344c8c268b2f2d0f52174e016600dc30226d3618cbe0d764508af5c888263631364411554988e118338a5a694209d1548d19511622e4189dda5312edb00542326c2a240a408218393de41400fc532688b2039f40c026740ad61c429a0408d5c205cf191c26c05642893126540a7fa8348521a412df3f3bae25108aa514ff0e87a85902dbf9f38757066f4e900236fe2ccc91b124e041e9f749eb51219533f8b959b108d50c005bfc76d4cd605bbf357e732d9280ba5062f58b001627c7154e6d2b2a617ad810c880156436b9616f15012b6648f25a3b0180ba820d0783402efc84acd8eafb7276a74481be46743ef8a2a431f66df1626460cf58a7be2a252e42849c777d20121b75e9f206a66f409c3d175e4488e11bb46768aacda03b3e29119e3853a5adf1f9cd795e546306f89498046cc8638410dfef086442400be4dee201089db07c61da43c262cc5de3031e7b31a82060288810b4b7414d0c49566939a0a24c215e5ae10486ca7132d2b4264c292890158f91f26a08819ad8b178660c9f02d0098118490921e061d614c1cd9d0cc2784e643027604b559a6f84c08105ca4ee3fc5628d01b1d756be6f22258084d089a0ca9cda846cb024b190c921350368d4ac885cd2db9950ca19cf6a2553fc95194b136284761e083f234d4a884dd198854cf2a6408d598ecb5cf402145fcc018c6798ecd906b4a9ad2e769d566792f55b2e2f4136a2e6f93170e279309101e25b920e75c4692121caec5c9e2e170e1c775c4a6ee041a45c62d102b8ea16d10928231267247d9e6430cc238059587981e53a0e20a720481494fcdd1f3a41cc4710251ebb5996062ec4227277a3adeba88e9b020464fce4a091f50e440e93d1864a2a9074da63c4a8a18f95de575ca23b340d2a6313216f264fca0c28587699ab71668a330121b147948204ab138246054305aab5340c9c40c155a006c214ca3b5a8a26a5517a68788510588aab42f37185c545c450104f028d6c21344c3046ca64b102f0ab44b18de173a782b3c345a3b120910cf4de50660519c093cd713086804b530451e465d97b4e450a43832636d8d19221829e236ca113e6c6b0a0d38dc0990b2b8a110b553543ae3e501459c2622e6e84c4244f1230c2d4d87013f5094e8d1c408870e54504c101003cdee948dbbc6434e2b14614feed02468f0c2f8927167a3c55aa9f5417be7e6034b280677e0ee164c69a4b315e5c3894795daf46d61b078e28b1907048342bc9c2074c1ac909a763a8196e212a6b00b714e1c309545b866a6b42b74e790621437831d95408f601a18d6d849d3f481f2b33a76cc58c21057fad955b995a126f13699f0538621941c313f4c2841856093934a8d4cc879a8151664a2616295122a11f9052de1d884cd89c4310f25ea885843281a49558288800a500061e92981028487c51b6f5a25c016537950163a50d729508fac01f9a16e0d252e810821e4a9cb21b729911ed7943a12883e2920a356a9ce4111083d125950e92625e28a960295826e0c9b1730237362d0c538fb3245071431ba107c3ecc30dbc0e8b4d45ce1d9098430a74894a0b31099e71c16527895bca4809ba3862dc864224681b9b22f3fbe788abdcc09f041e5cd85b72fb940532ccd690a3d9083e287e00ac3093b727d13a6806abe30e5dc0641dc8875b223e70a08e8b18bf347020f1b465ce2285d903082c8a0849be10e093d42475973ea00496440f167acea5ec4854ab08454559a330ecea20445964e1ac4f538b5890427537971758860882c70981127a189e691e11b257098a6bcf133e81105dc99068b58b2942880ab0186b1f1c056165c5b9b0f245b1a33700aa84c11146484c8db230735462942c3f2d6c5b1efc7116681b716626a1815d9f1f076e6e30e974850e437035daa6a6349a0b8116a83e1cf1d170cdca6a05a7380692a845bd449079210525337186e5bfa502a94db9ef6e980c644dafa3c10b412d8a4415b92482a1e7c0a93a0ed69295224399fd2da38249212ad4a041c512a865b27277a2646d091cbee22b921470c89631fc579d032e28e81a5150c4e998df872a463c7161e3e223895f9fb53142d13a1464d88ad233156118631a04145a8e08820d1e0401d19f212110d54c81090674c089b24496c142977a86c6270582053264a0a361800ac34d22515d9d4fcd070424bf1842d6b93e2893e31dad6128d6114c575a770ed4a28423a8da2c46b533cc7b78b01a5350f4f0c9de6a4b0b216c0860e504d443c0801884fa00c0aa48809f16441229a89be0621f8b44af529f482142279164fedb8d9504be587c9a54230b6da9d2b9026a8e169a25624d18c19abe802b53c209b760808f3a586a1ec0433ca8f4b4d506c23c749842434e158a0c42182568d260f432c22a5c2a19b745e40a169b7b2e9e523c3860b9a48da2542b442434ecaa49909d3761c8910954683531f006e830ed3467445627cb4292e2d01980784667e8040736417498f880747e3120770efed8ea30dba260c0b457134b339856f231a8e56c02f5405d7fd8c910d1d0843dccfa6ac4d2481703f03ec3232e55d1bace4ee673a4a9ed79e3d3322211c4f2d3f66623868905a316787101027407c7de0b4640561c1386e5060ab8b93bbeb6d75f9d1f3aa46fba45d6fb6bacae8e979b97b00dfeaaae243dc0be3e934deea82e13e0bfef175c5b96f7581989f5b5dae07c6805b5d170005a3f356d7d61683532de6e8168348bec560d1dd9dc2748b81892d2e385c1f9c3a67b8b5a0d0d6022e3fb0b5e0cf3d0ee450584564885aa50aca7901eecd542fbe6a1ce8f5f7673636e6be0f19aa7a255891b1c2a260c79602015b5b6c7c6b4b438e2d248ebc2da49ebb4739b2a555893a15d322f42dad049b106356df1656a52d04a0dc1dce2005087c785e2120a0a0ec253048800f1472f778ea8e68eb00e1542947e329746c6c2f2a67c0548234aed2d75434d3cc5a76ab000ca74ec5a83c70c8357c8b009d3996ca04f4583157ac0d9bffaa4e41eacf1064a7d207fcf3db1af0e393a71a5b035cc90eb2d4a75f600bcbcc97c9a18dd7f5956556969fcbd79de7b0983a0d9356030ba75b5774edf6f23b0bba12342a10001016a82234b07268050ae01289948037889c5205c07277081b9884d87a13aff615b6027062c5d6b0aa543af5b3ba6ab44f706c0c50303a071656ab51b63a41eec9126d09c0a75dde1c58286f016823f6ecdb0b147c3ea56665651ec6c4bca8339fd786685f5c05fcfbe3f3021c9cfba6d5d80b2af592f3129b6e288456a95240af3e366a601f1d144e0a8db251a97f7f31da195b5c8dd3a86953a95ae13c826a36cf6a54ea5f0c859bce71d46a5fb40e0a4785c24da56a542934cae67cd2cd54eabc17c7510be71155c2f98dcd8c3a0785a342e14c40e1a84ec1392a353a0f36a1706e4540c0630c775753dc03fd9be7e46436ea54ec2f10706c2c2a057c12a6e273f75930909b330766357996aacd55698953924ecda70a885165681a5bdfdfdfec84ee3939144eab7d7fd579ae2a7de3a39e55a9d2aaf4add9944ae9e6594d9a36cff3ac46352b8ce3146cb0025bb5beeb979082e233a0746eaf6fc53cf5eab07a95797590a352e89c5648289d028e2ae43e2a898c14c5c95d506e6b42a374d3793abbc88b4aa348444191a2dabcc6bc7a0859820c052754157797202186fb441df2296e0e2cace6513f9da9ced4199ab727cf7f2da451bf67fc170fce090e6139f21005471e1a73e421b82db442df424be25b6886dc7d8147a8b080b965c6c6b7cc02f9d61903df3aa3f3ad33aa6f9d39f1adb339be75f6c8b7ce4af9169a976fa19dd0eadac2c2c24af4c3b1123971ac44651c2b511dc74a44c8b112353a96a22ac752e4c0b114c18ea5a88463290a742c453e1c4b1114c752c4c6b1142d3a9622488ea5e893632d42e0588b226461212800008947c691786f1c89e7c79178891c8957ca912a908e54c1c0912ac20200c06214e4588c901c8b319463319a722c420192605e0d922d02af0509ba68c43992c6ec481a301c49038c2369f871248d508eac81e5c81aab236bd039b286d491359e38b2c61f47d680e4481b091c69a382236d281d69e3cd9136a28eb461e8481b4d1c69038c236d283ad2862247da00e5c81b011c790382236f6870e40da6236f8c70e40d3d47dea03af2c60e47de4074e48d2b8ebc41c69137de38f2862147def894c541cf911cf81cc9c1852339f870f70309b220247a160445cf8260c8b3206cf2ac08559e1501e9591122785684d5b32298795684110bb6f69a6f6d14beb5a7beb50d7d6b2fb93265c0b54c35702d535fee8ec4c2ea93c5b1faac71ac3e7c1cabcf22c7ea33c9b1fa90722c3f568ee5078163f981e0587eb448b9ae458ae95aa446b81629a76b915a11608080ac2c11531c29628c2345c471a4883b8e1441c891222639528426478a7874e4882b478e50e0c811161c390276e48834478e6873e408138e1cc1e7c811828e1c31c391237a38720413478ef8e2c8116f1c39828f2347284262e509e25879a438561e348e95c78e63e509e4ee580d30383a32c300476690e0c80c648ecc40e7c80c808ecc60c391199608c0bab3c3b1ee1871ac3b4e1ceb8e15c7ba33c6b1eeb87177035ac80a551c59418c232bc0716485408eace0c891151a1d590194232b9c72a405048eb4f0e5480b4b475a08e1480b768eb4b0f7008081018d6b8ed5a8c2b11a5f3856e30dc76ae4e1588d888ed598c5b11acd3856a31cc76ae4e3588d8b1cabb1d1b11a4d3956262bc7ca84c0b1323170ac4c121c2b1386ac2b2f198ef4f2e1482f288ef4cae2482f338ef47ae3482f3d8ef432e4482f4b8ef40ae548098fe02ac182449eb50093672d10e5595c063c8b4b8167715df02cae0e9ec515c795604b18476ea9e3c82d8a1cb9659223b79802b0a08198231bbc8e6ce0c1910d4438b2c1d65656842c0ace95c5cb91593438320becc82c6c8ecc82e7c82c828eccc2c391599238328b16476679e3c82c8b1c99059423b55839528b03476af9e0482d271ca98505022472eb40294e8e2c85ca918e041ce908c1918e618e742473a4e308473a3a1de928e848471e8e747ce24847318e7474e348c745473a3672a42328479a22e04853101c694acc91a6c81ca9958585800001015908cc781602389e85408f672120e459081a7916024c9e85e093672130b580c116968216a71c4938c09184121c49a87424a1084712a2702461d591843b1c49d8c491845f1c4918c79184891c49d8e8c8c22b4716467077a41750f0a08096840453363872ca07474eb173e414d991530a1d39458823a72871e494288e9cd2c69153ec38720a23474ec1e4c8298e8ea422c09154ba1c49658323a9b839928a9d23a90022bb3095712d4c705c0b531fd7c2f4c8b5303dba56230377bf42ba01e54837a81cf9068023df2070e41b068e7c03e6ee08b4b01668a539526bce915a2a1ca915e848ad42476af170a4d613476a997177ab01050618b0d272028e3c6b4ff2acedc9b3f629cfaa42e059550d3cab0accb3aa58cfaa3af3acaa38cfaa42e15955b367554d3dab6a86675501f1acaa43cfaadae259556c3cab8a8e6755f5713771d868334aa4ce303a4b1231c2aae09e57a0546ae26a8018d56b80d8d41985ba7066f827f1635b1edc1d53a1412cdc770477c770610b125218c279c9610ce4a3369767af0dd237175ed2bda7a27004c7d32a396a73947484e57a7a5e651a319267b4b1b1b1b13c2d4fa480cbd98848dacce8dee0eed8e4e0d6bcdcdd30b2db478cb8bb9e5bdd5b5e3384d9dc5cd32d2f4dcecc445c5d9e9d999b1e75ce2233ae28d1fd5b456beebe33b1f012a3fe5d5d5d79d580aa2c79b693081946354434a38e4a8df9aa7a7a18cac8a2d2370b80523ab4aa342a7d438c0dd131540586bb1b920dc51952220d79799842918e14b2e2d5994a8dc3009f8448429408312214c7ffa675de84d0eaee48425b8402302e5207bd305c40321a22194d2019d3de9083189d701e1b9ba37d7ccfb96f5a1db4c1bd7611f77d3884c83b410a82119da9d439af0f52d0963bf52fee2b232b74ee0994657564a0c01581c800818aeeed400262e3fe5980e2a67f22fd29e37f92fca9bad7d806af316add87fd11d0b858298923fd10bad7989797971f10ee1ea38f20377df81ecca6e035364647750a5277813d4d9c149fd521eda1a3e3b7f6acb92772d7161659388dc57731831e52ee5e483d651cc305a49e2a860b7a5c77c770212f0f290c17f2349140ed1b9c652fb1b8cf6fae8a220fa1fb0522f39039860bd26ab4cffd7380921f069e2678c4fcfdc54d3c34dcbdcd0de1e172e49d1d82419076e0ec2176e8ecac0d1932048d73c1a008e7c30ff7177bd1be3c8a1bdc8dd4391318cf7c638e74a0b87b8d55e539b08faec5fc3607d59c18732aa0b189cd6ad4c03e3ab1c0beea2cdd0becabf6d1890dce7d7ccf981a9d03a5d30d5e627c16aa8082d139daa78741cad7c26b43544a8de7e9053d393076a306f6d17905f6d1a955a56f7f7dd5393d2fc0cd9fb701e5ee7c6d0cb8a0b3cd58d80b3559dcfd81ac69746f24c4451fb5b966cba9817d550e817dd5bc1673342fb0af1ad857cdfbaab55105330e7a703deff2bcfa9c50646056860b892054dcddb1e8b4e9e0efff32eabc110128837074223c70981f2aac3903ddddeff628589169f4dca5d0beb434177c9ea179d26a5e9a02ee4ecd9b676822a946d1c4454f2ce3ee7955e91f35d1883ba1530b67bf59cfa15069625ae206a7266239150d2977348d1c8d1f348968a2b87b150b3434dcc921120d9d570503a37d7ad15535867acd51e9d6823cd3b80d370e1b22dcd9ce8c98439ab11308f8248c01a3d4b84d06dbd8585e3496b350c6712a862ca33de6236c56f9f6fa4acc7bee9314bdad8d1a63e7f333da3737cb52b4ea3c27f7a5cd6dd4bf3fb32a356ea352e3366ae13cc24420e0748d4dfa37c7478dd70201a76bd4421269546a9bac332b8cffa885f30899fa479d65295a0be9db741eac52e3b6191acf5509e7b7ba5996baed093ae734bb107371354e9bce84b11b753a5709e737eafc17d837a593d2c95268946d2a559b06023eeda45d14b89788f6b989e9e979fdfd2111f36a31bf7989ed95a84adfaa662da46dd44218d428565a04f251e3b538bab5ea3c1717ad6b769856a56fd43f38a994ce8d706f4e9eabd2372a9bf44c9ec67c7353a99adbdfb42e966b4ee7b81aa7616974af31af3a2c77bcc6bcbcbcaad2a86f03db6bdfb041f5f24293a37585d3aad7181e8a2b46bc4ec7990d41c5182ba8532b6055ac20abac5551e0627a18f6a880152e8c8d4de7b1313a2f0d4f3bba36e8df3c2706fd9be7a46fd4782ded19ed934ed1aad237c0a75de1b44a9d9fd1795693a36653a9da336d9ed5a4d3f94e3a9defaad1796e2fda379f45a56f84b33ccf6a7dd01452e0c8526248c9930241ca82bc0748289f063d717c82840ed2c90668b42f8c0a8df641e973a7ce83f24c15ccab0a4ae3d9599d0ab2c8f31a239c67a8d704335d8b062e31401ab07b40e6091457aa2b616824c944aa8b871d0103f2fa2e84c09a2081cd9220411b80f0c04183ae2713ac2d68a16f57a97bfa1757a3718b79b06f8f05759ea1d5d9efd957a56a54ee1a8dfb0e9446dddf71068ca3ee3acd06fcd35e804f42f7edb7574cddbf9057779ffbdb79437cee7bcf7d43f7fc010c5148dcf767f6ec0b943efb026759ea469d67b5ea3c3757a56f7e4f695b752a0d246c52a7f3605fb46e1acf7f68d5673c153c4b6ad2cbdbb2fb7eba6fa7fb8eddb79efbce73df2adc379efb4ee1be51b8ef3bf77dc27ddbb96f13eebb84fbae73df74ee7bce7dcbb96f12ee3bce7dc3b9ef37f7ede6bedbdcf788cde6bed7dc7708f7ade6be9bee3bcd7da3b9ef33f76de6be4160b9ef0f5364912a2e261721743e6a9ce79e027948c7a57c70af52fbdae6e6b9ea3cd79ce7aaf3dc3ca726079ddb4644a57d53a95c1f61732a8d4afba0735bb58fb029fb3de3b36a7436314fa56ef22c4715d1627ef3abce4da55169dfec579d8bf6b9e9e945a56751bd0d182e38a7731c61ec568df6b91506bb09f37d151e8eec035d2ef8a3423f8e470b1f1fc3736477c002f338ba60e8047e401e90529696b006f74d209070265dccbecfa7ea8f6001c7c90ea17d15a6207e890c9433d182c7cb2076f9394190fe139244fd0586c3e310e8a04b2438f2932c3df8286ea5dc0feeca267242d1659888dd39c981274121c69d1090be070e4c4f3489cdf7109bf4555040784dc6d3f381f11e54232e1a91abc8affe68aff2c8e86a8258dfa388fd2b066f34e1190d6f94a5e5a30cc1782a778d368b54465ed111b798bc239fc1ae8e4f283bf08a2fc2e8b33168cee389270db7e2ea6ffc18e0a9d292786315bffd6618f1182c91e9980791bf838464571150f2ee9443b732e7e2cb008a6d2b5cfa7c6013cdb73133c8977d70da549cc1ffc0c6b9f51048e5cc491a3e0fc7d3b160fdd97b0cbdf93b191a6da7a308479e98dbed83c447fa18b3e167a84f9340822ee406e87f3a04ba9f287ebe06aae1a0b0f8b804011d7ed02946ee60caa19d2a4ae451fc1f5d768accd750a047ef351bb8559e385ff4b7c54785216a2bebfa27da70ed1e09da3703e6dc8424b5f93093c2b89b0e460e048a1e3f9340d087b090f10f1a71f91e04eb165440c7abe0516e0a4c347d1a0c1bba8b02d86fa93bdb895f777e644ee3c3b040c4e73462d110b8ec3c600af619bfea7c10260cafc840ff813e6d8e294ce14ba9b01f7888c5315c60a2c524d870409e16f998aa161e9d53b8094594f987b63bef9469cf6b9065d108c24cdfcd9947ff0a52f7f264625701b3c42f41c7b41fa586872286d2333a3ddd4c2c94ae0182ede19e6bbb0d0fccffe9141acd13bcef528acbcf7152391b37835fc2d19a6379d57422013d1c1004a55b5d92e403f83cd0cf00ef6a2428f8b317703f00cf89cd37a888c709d0b5c3bc017aaaac469bf932c415b87276942ea67e931a353bcd21430fea05a1ad084e93cfc007c363c9e97946217aec317564df318a933b5a32f861d0244fb646f9675c167772ce8f9b6541f072ee90382146739e76657b9b8da79dd0a0f11ca074d810b0b06f635b6d1e889c3896b9a8e71950e001953776916a1327d41adc7baa59fe1083553b205be37f1cabf69923207e869f7857b0d0c04169f0f3723dba7c520603ba0f2fd5578a22b6e3ec45fe088c800db7e67d23b1a47f9852c58d78e2a3057c59f22e073b9e8406322f0104fa982a283a8e4402769e46041e8f07235fd4a8cb63a069d22194765e841c88ffd0e4f533300e3b6f0f96f3bd685f472b922b7884a3db1e59ce62c5d35720defe46198f8f64aacf53f12ab427b548f4066830e85260969c07db49174a19e44ec422ded749911b26d9e42d8c4e3ea25485fdb7e8ed1780c8a31f5331f8b3be00de9e887b1579c2e820a94afd09ea9eed69ed84c791f2b7edf875792c3d56ec078192b862bb7ce6d89247e082eccf2c7dbc12290d7f54557408a0acf814eff47a16079da966c19944e49fc06094cf7bf8f81429557e42011fda530c2e4e2188dfb62106d4474855603bb56278254b5b2e6a6cf5346e607c1d4e7d9e12228c0f95cce2424c1c70185c725f8a8676357796788b3a221e020c959b5944e20fe2c347d30189df1144cac1d000f22f361878b7468834234759cfa451fb63cf170e07d2076fd00eba993467362738005ef681c76ebc10c2114920d1641ca5f9b3511276a22028beca11c957cd12b9a4b979bf00837c6722a01760c7e4cb0e21be0f3f341c4ecb802e6c62f7238a1c78421abcde1d24e1708ea878451d1c6948723a7e89a005ee044fe32fe93ba29b813c7cacc99a2f10c4c3ebe461d1625509bf0247154ffa40e069550c5e8e073bef43a1495fd110c52bb408f341585479a426af9de21225df44c6e773281e782f848c3ed40fb93741e6623b07c5b913530c1d6805cd73f17d780b871ebc906dc8a3d042e52c1d2c1a8006b8b75168937e13d7c325bdd1fb3ec449aea64b8adfb10a72ed49d1bd4a08710e2178b8933f886e274a2657f04080c363830ef815c8fd16cd7d96bfe4b78d513e11a893ff8288d32fdef9f1b81a513622ba48bf24c5d5863ed8f4163aa8704f889b3ccf004d3e0ad9e5fba4a2b393f0c9bf07cb127dc836e6ef2737da4ad2cbe302133f4285093ee90c875ef454c0bb242ebf8b908d23c16365b7a930e3c982b8e75933f839a250fa0866065d4c240b1b0ac3cb491878bd4e9e4c7f25c753cb9df8f8a33820f6a7429cfe0688f5031bd1b89954736e09cdf0b3d85a6c2f0326bc8aa34dfee7cdcc573a50c203959a5f529e44ce7cc1e702cad4d07a7c6dcff6624fd39154cacd9070d17185161d8d4cc463450d8e818f9ae75468eae3e0b9fb01382c7c032da79ead06886fe08175ea214eceac84f82c40e87851746cec3e875cbcc932d32f3135e82662119a8bcbc5ebf8c446cf42ea7c7bd6e6ed7402f0335e1cf84e63089dbdcba23738387436891bf698295f2fe5ca95e329c53cc099baa75313f267aeac1b48ddd4535589f2633e24fd8e1cbf4985faf18d2d006d2a0f049ec30f090f92f4e0463881d25604d4700a46f65c86060f4f46c6db1370e4c7c718aab3e1440d700e8b9a5bfaa7c787b2bb734670293ed018a01d23abfa6a3e85d806c4ecf01d7406f42e24c7c970f8f01b0edd27b4ffb6e08552be666ef9254e58f92b3962dc431f9d3f61e2e54b2405721b5c45b40bb6336e038dc7e6c232f075ce9e4b5160c4eba679fc0f104f8ea786090f3566f0094b58e9052c56f77029a96dbc307b4d04fe68326cb8b89d1c4e5f53b8c6070432a1bf3080f80d3448e81dd14b0f77644fcf95a2f3abe76921cf0c0ee744e44790f21fc0a3e3f17c29f304d8aed78a73e0af9430768d055cde8615f96f3c71f20f0e3f6c417c2278f5508a2ef49af91319670fc070e0efeaa6ce270115e7228867670150c7bf10a27a6512931fc852e7033892e497841479397730bd14b814cea5e5cbafc972e0842638dd45b4be930e63fe4e141b0d2302f1477e2c7227813e3d1e76c5be23d1c9179170a347e401f8071614ec2947a23c821d71db541c450f47d28f9fc4327e8e45129bcccedf8b1a93df4c0925af23d4fb6a8834791e9a8b6302337d371b7cf608463f5ea314eb5d746c7cb6c4f73aca72b88f13875e0a441aff429aedc41685af879185535824f820b4f4fe86630647f16cfcb9b6103ec8c981eff983e4192b65da888e74dc4dcdd16181617e0d2a1c7a0ecfd5df80cf5c0b5827af1335fbc02946dc87dd845fe2b4fb2182c8e82f8078b8de1e487bc6d60a6701e5f52409071c49c1856ffa43e68e1fa26c3f2d27af100a94a7faf2e8cd2aa069b3028dae0086d4750802782a7082f893bc3b1f6491896dc74beb5ca804d937fe7c7c965202b4a7b01cef08c3822e9cc3fe128b3d17a3b3c821e4a07bb94647fecf1d07bda046173f15494f23aac1f81cffe57b5c90712e4a555a51982abf488f906d15c8d22b4d3d7226ce078e22c9072d63859b731a42e9f3ca243c5817469bd11a316f8bd96c084c0c9e66c1025da6880f7f1a22d24c28a8fe6e02de46b2e2920f00c4676fb191f0115740788e48a85c87963e3f5525cfd7515834fbc6c3610c21d3606c05277129cf7653a5ee9b5984ef966890ab48d2d42a342ddfaf82bfd5263e4fa607d19eb6489e47218caf8b43e6d18459a0dd2e505e0f001897a275e1132f9d6953400af8272c0e5e452fcaaf61327047e9e33ba1b29fba20f14fe830b299114afd9c4d6bda4f9194072cd4a52915aa793274ab0ff253c22104a6f036383a388bbde2339101f02c2d54fb1382458ee146a407125b71b02b230ead64c08d6881a12b4128f49a18b83bc155d2af14b8f89953259fc2057631274e3ecb1a423fc585a307d363e095c8eafecf12f911308c1c858e0a5e057ce2a3d2405d8c27f73f7192eee4821d2f81006fdf88a3e739c591db031ce03d89479bb41e3803df45a7f0ed145af076e6333fd332c23d829d23b61973343faaecaf0663de0ec2aad1b450f003eea98de2c827e74a7ae9133780fc20d3f979b0f407aa32e6b96050bf854a999f93e1e6fb10a0e42d63a83794d4c51171fae45c3a7c788c64d523c0e1e5583ea9f1b646183687ede01ddd6dd27cc2c09e4d1c984f90d4e581a0126c413f9a7c8f27ae47e48b6e0312122fa5e3c05fc589e3c9c02e3762098ceba122c21d095af71940adcf73e6509b8123f076ae86b88cc61f5ee9c8a48dc090196fe047c0fbc139e181826c68e525f907e36cd98709327d84386ff405065d9e1082419f0b7cf4549438b800455a1e41058b5dc90d1797700650739d79fd2c916cdf998ab9221bf0d6fb73e5efee70da81d6310f81d1e3832902e13d4eecf1c53c344e00429dd73385e68599d6b82047541f49539c0d0671ceb7a47f088d40781669dfaf9864c945ec68d445fcf0f89a942b8fe64b1e8f334863231a25e95754d5b81cea98f74121a309cdfd6f5aa4751d1059fc44d7854ff405e8d72880ed1a02e07c469a53eea900b88e0043f4273d46dc4f5adc5fd2b2f4d694065fe4a91c1590eace3068e1f510c9f3eb2705ff4605a65734898c1b1ab1fc40692a9772e1c62e1386f79ab0ec71b91c3b9e84f24b1f9ecae1160655712b1ca87e6cc1182f93a3fb1aa9d6f80d008e6f2495a2c6c222f1283f43ffdd00f1364c19713a672abc243592f4f2ac912f151c3a1c1c77ce05559b23fae5f0196c8aec2ccec963e7f2f1e6f0f0050bae7635c99aff3a2cdf27848a37b1673c273c24bfa10313975047882761c4c4dbc8a21ec70b0f1b8ba02c1f65aac6a612f2b9221a22ffa14093370ca1df11d9f5792c217136879678231628fa0fbae9396919a40f3d85fa0378497c12df25dfea80e12b9088f47622d479398d5c9c0562a857f4e4f4421a5a6d3780fde809475d6aacce23986bf25a7b3e7c1447f32ab868f151c9453ec7708e6fe549db68d42471afaf099a8b431fa771a17043b211eaf71e723f2892e0790090b30fb0597b0f189cec0e04b23c98ac335da5d03fde8b2aba4a94377f894f89972e69732c094a7e9631f8d6991c9f18a7e511d320d90a5e34fa0196d1e65b5be0ad132c9a1089e12b651a1a4bd290679049c42ee160ea078c0cead500287f11a8f14f8400e0802e326946b6d20ba013f40c36c27ece1b313b838a427fa177410f3a6b3a04e9a50fa3e3d06d0c76d289558d1eae0c54c71183f33a3a553d154c39bcc5e127cff049f129a801dc398a44712b8386bb8c1ffa1f81568da7668f670951e119781ae4589cdc5e53043afe43868a672365e22bc630f8272f04df6489fd438078dccb2049df6805c9b55e588ff8a2e8851ca1afc8d08ba7024194969a9d7009f1aa8b58cdffe724ed05f1fab8973495fe4218169f17228be3b0e1e239ec68e1a502135f48b383233a43f43a5098bbc233954f92127fa340c04f54dc9ee44c881fa335e9d7d421f23000475c716fc0938113630f00f2e2d78049e238f688b70147753618e27e514801d7310fafa348c7334a88f44966006e402f9438a945403e2dedc61379c6700816c69ed12939e1a5062ec76d9487b102e6ef5e98d12dc45c701f8cd0ecc4c053dfa8d542e701b0c1536109f4568c5a9fe280a13f91a5c3bfb00ae2c925989c0bf4cc7f8ae3c3e51c3fdeef4b1bf73efe1a8ee17b6134e457f492fc150101bf74c3f3a368345f140a497e4a2ccc261208e9344c54b5a84d6c9ea2052afdc304de17421a744d18127dd598496ea094923f6b83491712e1e85814da575332f7775678d9a020f9f9a7091fb48e54c319932cbc4515267f2182a14baa74c44bfd88a295b4357e5c54d3ded085cda9202173008b5d5e91238b6d688e7f8590336fe88e82a7f8e3e90fd500f41ec844dfaf4725c75ba1e60a8894bd9933886b487ef268aa3cfe9664d46b397462d7ad611e4d140aef42cc1d5f1209f0bfa47df20c6e001d4d89771c9360cfa340e933ba38fa3c8a77dee6ac71f729b0f59e50f5e90e0aec7c08b7b9c71055fc1b964c6924a808bf921d994331533ea05bda7a3055f21a6c80b81b370e7c8906aec7d261c0c769d3da42c25cb9dc14b6dfb0a691dff9f3b8ff68f9e07ed6423f6ba13c193060de8d9086c72325a75d37951c314a533ba832f58b98003d6bc08a7759d468678979f83466a4ad8455f93f62c4e83f85be9e91a5485e4ad28da7ca51b793c8c173f21261abd940f57ee0390e8469c3c12e91da3feed8f9466f143c5f0633ae440dcfcbde347a2ec308fa4598326730a8cb37a824e1ebca4c9dcd40c85f2d28741c24f9fdd470e80d844c79951f5c1a0605217fa729d07661a2c543911be373d02cf9e067d03f2c51f93d070eedb03e0c9e054cd4b348e19e82920cfbf91a5f8bcc7b6b56c7cf1cfd5cebca9b571b42a6b53ca9fc952a60bbc15f78b94454b404c1097f4aaf8c47613cfab9b70e3bb0cfa9bfa2c4d4b62b60e0199b297ec31892aff0278716f5c28d0b22647b3625927c9c181eb6184913de43dd89dd272286cb5e4b362b8ac7379788f8437db6781b20a1361b84a80b804b7c03a72e79271a129e908ff90e191ce92ed2109ec0108866e2b6c79b36d61c4982352750c182fbf013f46100cd6d4d1cdc7e94992dbf02f0ca430d4ed99dce34ff4010e4e36984e2cf5838b439ec10e513da1ab810a5da2790e4e6d24a679e0a94c38793618113d892db63a6b47052cb2d6e044dcd1b50f2d97a77a478db1350eea0c2de87a509d2655c4f6f48059f7e6223ccb522479d47b8c507492f69168a14fca41d7a1b9e7178517ad434de9226cf2549ba137931e48a2b2cbd0d2519170268d16e31a1f99da1762bcabaf17e5e8ec682c6e892d8047d7446900fe439748446088fd7b7a7093548f421ba6c6cf6cfc45bc891479b49ff389616a24701a3e64955a5e80764419c4d5e151791a98797e8fae34fba1ebc159bbb91a879f84e2538bc03a9fc071c357c0d668c1f034888beb384f045252a7302636ccf0254831da12ac4f76df9db0358b71f4268e72d5dadf81475b8b8f28cd967e214e9abe025be975cd7b7e96bfa9a8585b33974e1d32cd136611d2c7e879475143302df9c90f68449145d05a83bdeb6457abd36595a30ec8acba0b4c897a9e02f03e3e0b1ea483d872cf16f3294e4c33a65d2d1082e3cc501ac0f0206fa987054da841cc95c8bc1ec730a2df1221558fd66dae7138c8570b9267a7e038902dbe9a7d0e344c1e10a5290f0256a36682d6c2efc064d530714b7713031c0761b85389e2691a10f11c0d145316afd23d5c55f5903b02f3d62f42dacd079870960fcc709acfdba579ec0400e8fa2c05dc473ebc72c29f2470ffef40ea5ec6a6880f132336d4e23714ee395aae1671c987a4a60007f0e13808793ca8b0fe280f178d5510f66e39176676c7212eb02b78408ca09b56578266e277cfdb26033f3e4714e55e07c8727749ed25edec6fbe95780f0f5b19ff983029b34199922ff221185dda1c08ebf54a8b80981647abf4f31361c3f26be8d04a0d7c21ae06b5c7c365b883e9fc74908dd2602a9bfc2428f236bd0b91b2c8eafc5503ddc9a307b531d17fe864f0b6db896e78c3434f938305478853959360530442ee6ccf0783ae8df13e99486d649e1132c59d166d841ff0240a0afdd20f56109a84f618d1b6fa1c5b959c337ce78294ccbc193e59f2f62ad45d8e8659b12f5802a991c4d1e2bbf2368fa5f0483ec1204a28e182b7eab4484fbedf8a4d3e8f571355d531c920ee97f1da2ade52f899bb5643bcc7bc991e8e8b1f1dc69e30d0ca59a2e4ea20f3046f8558e22b9e00a476d27eaf5647a14691705003c9a41773ed0db8aff537db3b5c0e9e3640866ec1c768b9c5586d10c14117dbca3d00ec4b2e0624a42380a0d21de499724ee034898cb78558772038737e3b0deb044ec9678383e10b9549f566776468098bc000e7c7461190a0f64cee0462334f6191a41d14d6615b74bc2c9f1e010731573d0f69c6011374360c70bb824c81b61d0f493e0d8f8932fa73cc221d6cfd2f469196761decd0fbbcdf794f35e448e36e3c4cf29316a7d2097a24701e849378092e4b95ca0b2d35021f0567c386a315aeebc1248a13411019f9c5408c26dca99c503d9309b86244dbe6054dade34c7c09b28b2e5a9b490388736d3ce90218777591dfd5ba2921b2181b55d306cfc479b9c0f4038bf1b901a9e600184d7f0e6c346d3b53dcf56e11eac4cfd1f1584b4a1415acf2547e0265cb3c39534eaedb72f13efc1498c5f2928795362a1362456c26b7d717cb7506c1fe20398edf858e837ed0adb4a6ae81a5220fe98277adc4408b477e16390c7a892c00f7972f2200e81bc9536d0a779b34f31498ae320206a4f1963c0f3fc977b3890f82e3aa5f9b7bc150ea7018ca6b26282431203e9458549f54724407235888bff6170b99d2c0274360024bd5c0535278b31e71098565c49a1a2fd27540277e33ad32bd01cf2462bbc0f7224e9d1c605be41ca2387f4667833a64a791615b5af0023d1cb20bed0634a88714a69379cd0a2ed727c287231117ef81c1d3436093d32dc8408e66b505ce109321c6ed60ffe3553bc9cb0cb977f21f5ed2822e55908c1f9294173df88ecce0b8c1979487c1f3c0ef0c163046e7a537d89beca220b9f2391cc9310b4434fe943f067e6003c87494b7c8d5487ed57447b6cc1d08e23f3e16490bc0f842bcb9b9140c47dbca1f8445cf43c93071efc440737175323f6463ad15b6049fc59a82a3d97c3c5af38a563133aa1c1598851e13ace78f13b322a9e8521fb5feeb82ed026d02f8953c4e534eaf103f0201d8cb2834fc9d2a69d1018f987444767e168877f16212d45ca1aefc306907b0214e772d6438f4181d23b3417f5a2bd39ee56b96c28a9ccfc943f17f4a6c53fafa68197979207e95c1602b9a71d1f7c0f68f3a452f8f961e38fcfa044ce8924091d11a7230f13a1b0ab685c71b2384bb495194ece04cb875e4e00f5700c68e9758f92ff92c8c2736220e80118d23a4f9306ef2a6bb2836405713066a89d285306b7732981767e39f0383a9dbe0702431f284804cda88de38fe9a249236a72e47f6812e17e7bdcb78a64f8769455bed207e4bef4e7c72321127b2e5e961e46a3e38710903daa4d697c6d8fec896562f492b9e68763267da35264be1193143b318de38b58b69aedd2c5e72d0b5bda78c0f338c2b16bac98fb266c6a789c40006f0826bf1f236cbcc49a32ce416eecc1a0443d930ce4cf2130e858bc28f044a54239cbb5c2c9d84a6c397f98ffa90d15df8a22f75e06912ec3408b2f93017c8d8d82e754e4d149a562e47d89437c501b46c7318ad55e965cbe12821efa8f8039770244d05361c8bd883c593b8c4f8097a2117c8bbe502e8a40d87e1120f1e90000db9dbaa0792083a43f8628751bd20b9a8727d88318fed1f195178f858f8d932520e16ab4fa68395150f899a7c0adb578eaeb623c9a80dd8a5f2f84d271beacbd1bb8259a8a99df3ba507362a1f9d7e0e1e1e07c204ea99da8cd25e1af09c4d6ccc231f5cf14356befe48d4ca3b0542f12f80597f636b8df6b4668937d13148e34daae27043f636a6066a5ee54348ff8084f6122ec5d96f68823c040b245c8a6781abc9e9f99ea5071fe729ec2b941ae5b05f90d762498fafcd917a2348badc0bf27dd9e2d0abada9f18f83863c1f21110de985e0df40dba4534842e0f108130f638c809f61d8c3d7f8487847aaa9dd672ae47f1026fa144becbecb4ec1568236f54140f297d140e625f979f99f37f2ef5081c31dc5417c48f09a1e20987c7d25e98252fa78914d6d9e1765cdc751e0f7680e89724c4e9e9a4d2436eec08ea4ef33a3c25f8170e01b9780dfa4c11b87e1e270161efaec0d2b4cbc2314499eeaa6ca2b1957788be9a66772c88cef188adf4998f5a92176ef040d8abde805c7ab98a4dc9070f43984057cb4140747fc048b3a6fc48021a7a204d1ad34b1f34f2f463b4a252caf64bad189422c71678b2e7a0e40e923b828e020e43c791d26a6de8658e429ac40f2d2345f5f97d7c4a357bc1ec13eb033f5b9f16e7ee27cae22fb0e241f9de069e63b66c839b58f00f763bba41f1b00721d24e2362a4d8e3c4682710a4ab05f94c17689b62c2fa6894127d3be3cc698113fc5a6e515b5b1d34b4ecd79983586fec48df380a236e81e21fe781d453c7a4ba74c7f6806e6ab7ce17d081851fe8e17bec7446aea3606d5382750f146ec41eab338a0ea0589009e463ce5035105b804081eb48d0e4e0730f76803b852f186822cd05ec2b6fc2d4296471054e56e384cfc23863c3f741148c711e2c24551c8e43e3e71f12620e2f6ea62860bc861e0b1dc0079c466dc6e9473f46bec7a389921316f7c8cf3352260f8b7916f5bb5f9f384145579112c0f57740749ef6062e7597489e343ee1adf0e1d281ae965edc3440769017598dcedcd8a07b541c53bb512f811b320df07ef877e1384e33a8cbcbb9322465ff302a82351507c2d6e263d264e823e2c0396bb88e3e0bfb406b58f4285ee47b187d7b9e1e863e00cec4a3aa42e3f0eea2d32427c1a8a171b3e62ea351560f46208317edbe3b78d1b10de5492d3c78880c71fa5a2f3013b4a7d280385362267872732e8e6bf3477bc07c33e9acaece8df19155c0883c067956cb62b23c1bf02441f6866e6d52480a453d9adaf256ad02990e5705651cb4971d170014d02ba8906074e224ea507934ad08f3a916a33d0a3f475310638d9629a673289cfcf9d79e0bf2863db11c2e3d18a04ea3c30861c8f9b231f424a252f65c8ce3f7ab0e6420264ed0e718cafe866c933c94ae06ca2573e408f381f69c604ff7136f72ea9bc3dc52b3cde8b13fbcbac4f2a91e97166165fc28205ee08cda11f5346c9bfa44074161bf1d71892f36d00757ab22dd6819412b51b59357f2a63c063e940f1510e7ded176d08dc0a1bc61d039dfa1e7e026db503a65ce6e3b2ab16647c57dda9bd20938137d1888b061501d157d899f0f28041ae34e5f87196615c9903d2261cc3c5492529b4a98a087c458a377b81dba24fa327cd8e71177b9050867bcc0fc3b7ea42f75c0257f8d894f8078071e48fb090da64d82e3d85188cfe70fef0ceb8df50d37f85736a0778f43f6b8ce3101ec73c21a9043f2664e95954c0afd10791ef71cfb41a221dbe4b15146e95f6c3e14e99fe509181674012419f612a7154f32187b258e3a012d76da08021ff70e5c1b6d1b6c883c071d027445c7da83dadaf0982e9a1877d76580645af00b0ca3b3492e23e662c5f4faa271ee8c811ad2760cabb2d62fb3fa0ba3c092a918ba1b1f85e9a963609311d7eb03085f66278e6cbd63a781d33b49f0a11dba1d800b98db9baa756a2e433224cd08d2064f9a330d0979128cf3939b9f340702afc44ecf406778c6f21c8144f31e9ca27841af45808c071366c7d76022421fc45dd97eb2108e0d22e81cfa502f00118eaf0852cccbc7dcba0e314307c4404c478209508aea7a3cc3bea43e44f1d3ad0aea08c233a64c54904b872ea140b9b80a3053e078f91bda74f8ca74055e82d2c42fb0f51e4b857569f8bb990eeeaa1156f487763bf793e3f552cf73facd87cdc5653a771d539dea102bbc80c2a0ee5c1a06744b8e93bfd11d47b5637bea4840a8da9d21c5f81466f0f0242f687f6261d0a6dcf7f11c55772c1ce2189c0da2a04213f45182b4e7738c767bc19e58d8726bd8543a3bc8c47fc4b2e95f60b42aea315d13af06bce9b4c2ae040a6303a8c3f3d3e43989647b5e6cf9e7b16782e6276f6893167ae580151e35882e5077040d38c0f0afc2541d8f50ec5783ec5163a912e94e3a8a2e50bd618f9213e1a7c85aa05ce0897c1d71814f8b523595a141aeb040e71ed65e2bf9f414a7e2e19bf04000cb6de6291fff49e399a8e28ae370ac4bf95f8e20e0a2cd868667aefc5e863b73d5bb722aa4bbf78f97e1e64e02bbd107c126efefc8245067e0f6ed00cc450f10a5c9aec478cf0dece121edaefc27f1955ed01f700f1259cb8f6012612dcc16ab72100e8e17fe876b8994230bf80058c2d6788910f95ea934ee515c0d506ddd76305cc8fc90cf616a200376128edf3b0ba5cbebae08422ec71343c045dcdb3f930c22e6dbe2da05c488a315a0b990e577315e9fd00f6f14c59fab4979ce0b798d83692271797a0354a3ff2f2e94165c2b01d95793e9840481e43cd815f82e9f02fd50fbfb50ce09600987a102e3639833b270efd1d1a9a8191a3702ef597972c0fa7e942e79053c017d930fe1629537f4890cced3c9ae45f1e8df82c8bfc5e861b0ffa8a9ef3b58be89fd319be0940845d45469a6fe06083c6eb80e84d1408d2f025107fc6a0aae56089f448116b342139083f38a3f9a416cdf0431b695a6dadf0b354cc3e98a8c3496dbaa48de419e26931aaec2f7183ee43d20dade8a8c62d15bed8480a0a7c0b8c11ada4afc9e7d98149934a02c29734e13463aa116e499153b7e5d0e33b2291d26bc6ce38dfd89dbe03628a37293df90d59e6b86154d0f6b319ff4cc0dcb6526de3ca192e7e4d13e31f9a3bf41fdfe663d0b0dafe98f68c19ae3c9eb61f0ee707853386707aa22d5874153b0efff525640bc1e29f20830d7fd48580039922443f21a5e7ad148b3c7ce2c797f851638f4931e7db7c7aa1238d18fb4e5632fc850b201ccb28a88ea2eae23e26b97361c0c7df40dc70414f10dd41aa1bef82d8e366aec47c010c49fe484652b34514798a1129b6da0e1e2f60eb8103b1c3f6275e68d1a2e2143d89148d34d548a877b312b5293d6af2885c38f4744e9e632854e8384428f02b9d1e3511349ffec0a36fb0b1a403daf2a8af5e38724a788a6c4109fc9f892679d58f245e56c643735540fe9aa140fb4b49a30f4289bc1933a87c461d467e49c1a277f106da34b0f8b85d243c5de1c2de4340d5c7b368e1f3217a26e8401c8efe608e056de3adeb3fac09f48c4663bf2541aa9ff101cb53b1668f06cb0c5f539cd96932f4b8a5ab42baedc2c0116d19f58adadcfc172f2eaf06ce9957f621e0899a0c7c90dde6501cf9700e08ce9c8108f6cd3847fc952b57ae8943133fe2603f28a5ce0bfd7ef86751712750eefc20d6728b5214e59d064fe86f20e53f199aa10518a8f19fb638edac248907510646b760d5b88ee923adb7c2c6ebb8139b50d385733173b22d817971015f34e8502ec2bc310948abc5ad1e05d2047fb681f3175eb42fe0aafa513df72d5959fe08a0df807160789f0251aec3f18c9b8263648f19b3e7235cc2e44dde94bc1e98a1272097f13893deb88beae253edbabc0ba84fffe94ec09eeb93caff16d57930ac131f292bd01d04067a3e5944e90d070ef90dc0264f3846ce6900c1b0099fecf9270820391424579c0f82189e47a3cd9bc053b17b3456782983b468035df2dc520c33df6000a9efa3e3cda96e0e7c1201937f13e789abf0d1dc25e21a1f10cba26d58a7920f5ac99a9140a0e74244c8a51424fc1f363174941d7bdec08cd8d7d5b87a4044fca90840f5035c3b3d7680e977341e3f0ba5274f4088a007a462f66808597ca4066cfea0cf8a2e40e0879fc81143233231c5d7bc8cfa29965c3c1e4189be004e043733c5f546da54f8e15aeb47b688fc825273769c1c9a1b70c2c019dc41e46a9e2c6cbf52da07a5f1fb29563a9c80a0431fb3c1df00cc8e7d2569d35742604123495672044cd8b80547c4f7a157b67134487edca0a3fdc60388d3f5c8b2170019e23bc0747a5289487c14bf2aba858c445eb508cabe22e6cf01112aeab00af0e31852689b71f2e1133e14d18972c0dc1977e7cda2f87946554abfa66a3a1f2c237a04169fd339d149277660f474c85ce8aa813b6e66c8810e4414c13f1de8a0d3a49af24cfec8d8703414dd0f2cc73fca4bbc4fa013dda8d18ea7318ace4b39f4703410633f47278f8fe083e505a7607c91cff91294b0f8b74306de1110213ee50699cd3806f085f0b9f28e1a20f8c1d8c88f71c0e23f28b5e900d049af23adb92fada5f1072a2aec1d9772b8d46dc41653e4f2b6af537ee2c4984f04e87a0304072e222f94378271f659500dd24a72c43d804d57af8283fec0549e1c5948c92579bae439bef43caaa6ca07b05be06055b2b8b30ed87b1168e4ce688b433924c7b713126ff6648c3eb3a8c8dd9c5afe2316323ee941d409953971190db4f6d608056ee789c8197171390d188bcf8c64c20d74ade922201638820a88b6102c336e3508c5696c593d961d0c8fa4cfd617d668d4247aa0b9272e43bb87171bef238acfd1ccd2bc230037a7e168edd7baa0d970ec80f0432768fc520f4c1e038efbe1981afe68538b0d050e08978924fa52881b5e4fc19ad381c1c3d98c30b5dbea7079355bb27c0b1f08fcc1a42ecd408b0aff04a6eb378488e133c4b0714a9cda1eb0060b0fc1a9fdaa41019a0e212aee80cd7a388a1efd174903761900991e07a0489a8496a3675b83ea104c2be7a4e6b9536502f3106466fc2736556e85422abd681495d7f3a78d1f4ad5c7ab9062e193e84c793b737dae95ec72549738bc04b3229e2503803ec1a4c1c3152ed15a18acfd1512533622437e2f38a975086b0e5fc6a8521ea7b1ea73103a37020e125ef1818a3d572586db5511b796e7256711e58b1b1e49f17427e86c048f983ec9abf70a4c59f20e3504e93e7cde3c0c0241ba849c30fea283e0b78562f1860240d18b0435f1c1ad014eadf2742a09e238211ad9fb7931e841420e78175ad587e9b0e70785087464181d2e46401e8d176783c760d049e771baf1364b8d3c003ce0c3fc117214af8587335d3e2a2f245e03832fbe72f8e46566113ea64dce4719fd3d050033deaa08950d415089a742c8b919b4153e81a6e84eb326fed79de6532accf052bc04beded89fe649a9a7128380c351f2d90b9850701871287ca734185c8f5bbcdfeac839168232ef27cfded771e1bcb1edf30090a2789e049c7ece20636bb1b5afe8f14d872dcef845b1f911049e70357f35be0281f5f580ba7b3b1d81de81f1c4bf78c4e7af1e39fa4b8d626ec3e9c2a13caaba5da0460f642de05d44fd793c714d0fa00bfc0a3112ee0a46f005f299b7d392a213bdb9f27c0eed5e845e128761c0c166b105df1012051d03aaf515704cd028fa08f2ae1c4cfc420e41d730755fcb8b0b6fe289496358763d74c399579ac0e5eda804d04d4c88bd05429a7615247a9e102530bbeed38f27b0e56b1bf2787b2a02cc7c813135c741e04d633adce4a368ac711859467d61f4cd193482734e0e76fc2ca9e9a1f2a03c1135b09f13c2cbcb3071fc098065beb7df49fc4970014c6287629569134144fc41059e7e23d0eb7f89f6369719bc9701a13c93c7c65f6040c3debab1c1b76810e223de4cf20a7d2f761208ad637870c171ac18f4315c8d3ec03194bb18a3e4c3d040e57267a05a47a5f59bd461b04b7c29e16008e1f8afb30c6e858451af6dcae3433654d17a47bcfc4986509e630a225fdb9bf093c27cf95c8d33fb6a45e25721abcec192a26fda9be05ad686bc133239bde6907347bff64514287d4900485e8409f5473d951ed32044efc287115f9420ed632ebaef826afda8325e5f7741d07fb579f22e270bfee4c3172de8d2257f938e6e78a6cceb6501f2280c28f84421963c8253225e0f23a88e2408e87249460fd4f6e4871cf0a05901485f53c384ae9602e4827a50794a3a4c79192b0a9a1363237fb3c2d3180ab53c314411d7f3058f3bd29147bb5dd32109b0db839ea8f1238516740c46341f2a4297de608a8703d8f2da1c0e747a2b0dd58dd8c092eb71f0c80f559ae14f48387208825c6eaa091cf7c487e73f6a7471c64e057ed013b2dff325f1012dbae46d00f41c102ab7d9f0e0f16389a8b8d62944ef66938e6f1688fb0e7a652e48c1cfa378d1f27296071e81c403475373e3191c107aa0a2969fb326c5cb39ba5e8423a53f9c50fd4a74615a09023a1e48419e43897c79009a246c3415fef8998c46b78321c40118626ed883a57744616b2f6b2870c04114bc8b14a7ff02a065739191f032bd357d202ccd67f801e43a3ca9f92c207e7ad3228f2f81e1f0534148fb2a45911e9a8acb4b7053e2fb83991790e0e65d0430bfca13c51d27841b2f8385857fbd35fd43872ae704417b860d4aafba1be58f7ed05d0524c40319f5b58b50c0e46d6a68d057be583d2040441b89292d37e0084233d7c7bf50277e3e93ae1e4fba64c7f852e6659dc0f429486edfc611cebd0aff7c54d60e7f6b34f60e7cccf930266ddf6523c54f7821c9195d71792984431741889476ac0af26706dded4aa7fc38114f86dec245041f5425cd26100088afe999b50744aea7a281615342da78276a7ef89cb4bc7714808f2e7b3af146321c775b1e0b6fca861ced44ce883b1edc4381c1f84978e47956051adec586884de591dcff0843b64f304e7806771e6c0e2a22f9d51a75ef5d51be883d97de2f919b4f5912e70cf48c6fc3f8c037c501f58bc808df0c450f97e17844cf1123e49317fe9e148601cfa9c317bde8e0c4c340734557491ae55766c4f91f2f861e0ca3d953af023c9122767c0080b4c762a3b7d9ac91703f33405fe9c2e760d33afe350ff1448a9cb8a022896f94a3aa5598097a37358e38a0ba20bed76748338884e81b3019d1601629f2377b0e5ed2283b17a3c6d162619eb861251f2fe60ffc867282bacc63255fe4086c2b3a22c71770dae44d25a197126ad45cf6f6fc011c8dad04c5e0e7b1a2a04fc9642f474f20cda231d1e5065075960f75dccd90d49742e1e1632484974bb9f00a6f207c00a525ffc770c91b8e12e47cf0a46ea5718eafa180448b0af0e6670042a43d3151b897b412a4527cc6f34e2fd9c4e6352a84d2926cc8bd1907246ea642ecd41539b6e06ac19938aaa3b5848df1c738cece42b0f796da9cd23c1eacf027871a351f10721eb1c7ea45d61ab9a33c3476d88ce4e522186e3f7e539ccca3229ac703150f804dbb7b70a1e248da286a2c698daf00cb8d0780e8e5899a3dfe052820cfc7cdd16b8ce0e33e144d680092503c5caa51bb122414ee46cddb05a2d47766e96d0e7c107d0c2e2ce701c4d2cfc17bf2881a35f04532944d26c814d701e09136d0627e1aadda77d031c3e1aabc67c1c2e78b39acfc1533196fe68efc0412c0ef37056b4f79b0c5e534373c401adc9370fad18f2475bd25383ebbca1f236fb1e58f2e134d73473295dc05a7c08f1077e51720f37ccb11c2ed07cbc62b9850e803c5ecf8649da1dea2f1f7a8a26f1c121f012e6817a689cc796f03f5b4eff885f02d1b7ffbd0c99d9be882e1072d3278248a0a1dc61909cff661895b25c1e05f8f78b4a41c217c0906335f88c9cb352435ef9253fb1d738fdf0eae79022df27893cb861f9522d5eb4df11ccc01043feb93e6675e95b42919529cc799295a0fa51dfe0611cc2ea227c8cf687ed04782a8f13622d2fcd8904adee46d82bf21de78fc078b0e3528f9615a3bdbc0f7793aad2cfa10fef066d430b90608943ef9b5f83fc612bc2181405b46358e5bf2e344571b0d701189589c0b4a904f3659f8220657dc51013b1ac41e483ee982241d6b92ba1b680eef4267e743685874c5538ade4b12036d89029c2f634950afa570fe973db1cdc18dde6bb9c3f86a9d16ff4d0ee02bea44e49d2e746c45c2b827b007b52842110e7b21f52320f170502716f7a3b54f7f653a7ddfb0fa17490136929ae69f7482bd11d0967f1c5b3f08073e232e575382e4c9272de1748ab6f82fedfd88a0a870c6bb4e1acb92e027c30675132f36be1d9b7d075dddc37194faa54e80de52a8315bc122c53f8502d14f7a5af21755509d4654a80f74b1e59f3c1c3edc25407de28da8cff3b347e7b57e5ccf981a8e2213227fe452f673c024cf906ac57e40763e131abbc7d422c367a892428f61177f0d8d05ba94133bae620ad803c659e0ab8cbc7d5884c9c37e82348b400d5c8bc0019d4959ea116c85d88a41163d9c36598fa34d29672b82f5441cbc871d6a7c328e325c4784b88ff2e67826d332ade88b952f51036a0759c4e1814cbf5e0a989cc7b8f2b23f51fe4a44be6c4a72897ff268f5215cdf9785fd361485d15d9c716d6413329f685090ad8825c54fa296ed176a2cb855112f2f6480c2ffbce9a1ab3018e209e6087f2249fb7d3e95f92096a2381998470f0a8a8c1ff4c8e969e880714d3b407c1b0b0d5e83bbcfc8081797a103c4178a25fd9429979e888c24ef094e277f4357e7ac9f54fe810d820f34458d5ec0278acb4c74bc2208081ec1b1875643a2f56a2043fe43419f87b4a68d8711bbf12588e8d07ea518bd12da0c8ddc00e9876071f3114c01723505426cbc4732b7d023ee05ade17b29727efb0334ea4ae464e8b7541ebec89bb8eba8607425704b7c0102185f274bd0e50008f1fbb1f0079f7e9c82a0a6132e01f2820a0ebd11a701be5806f815f6d0b828394b9bcf32ecb9dac45b5211531ec769c63d70c14e6701153feca0e8583195dd28a8cbdb3ccc3bc424bd2f9b936403704ef83484741c0cc993ff9322e6800679f14d6cd5db5810e10beac85ecb274bef4600f45929290773c2ea3444047ce0e304ad648dd607c0b063e7f1f1fa2128bce83c35c0874b4bf32cd1057e20cc51af2987388b4f695ea646d3fb1c72d2553860f95084b81e91cb764298aefc9310fd2834850d6191d7bfc9e8a217a786dcc69430bf6410f1c9a47dd15c1b40f9190b632e67410c07b529f06546575cc6a5353bcdccec4be565d18eeabc7e42318ff7496c9f14128223eee5f12ae80f3f33f53a12add823ed30f443bd204f3dc3e3e13b28b40a3a346e67c522efb3258907faa4c843d0d5f84618493da30f0dcf5b326b226fff60fa96ff04051337c3c1c837b864c7371401e43864087a11a39e5a4f0d348e618f80eb0989e0a81e61d15da908f9a13a510fa0e78a5bea1bb52f8091bf9ad6ba9a022edf4747e10b89a3e802fe4cbd05138e7c46da8b2f8003cbff38c3f7568a787220ac002d83d9c82fbdb1d895dc123cdca2a46d688897676b24e605114138a440af1d78b7c7236089d382a6f4702d6466bc7ae7e1470478b50f2a11fc9193124f6140119ff3674b67d213e7ffda8c7da018485f4654bb0d4518f177ea0f7042c0b7b084e2274917f9a4007c5e520fb857d11cf429eac03ea9a9661b72e987ae19fc464d587e27638e9f29a17b33c43aff030a20bf90a9866eb73c7d1a1736365b90038fa6a6e6d318833e28ae4bb315e478344ad3f5bae879004abc68bcabe5a7e50dd034f2f878c518855e1f4a7a9e1f150d855afd4993346d2786f01e510d3eeec3c6803f60a3cf9e42067d138c9f5e0c993bff42674ad3907bf16a4ecc781c2e32792a2f905e09880c5fd6b8b782505f7c041c14bfe02ffa5a6e33362230e8ff0509a319d1d8fb173fa4fb10601397a3e56aabc9b2e299de1afaf14819cfc3a1cc4f5119bd0eb31f1b0f9b282fe5c2a07d47ad8893fd20d448c8887a115d6cfa31038b9f31f5f3692b82fca3bb022f02ce0807d48bf30d8994933a92c00f046af91431a18ec9a0f89d8aaa55d419f12fa0346e2037bcfc0d9996ef5480eba3301d68af4b979e4da1b29d5626e8472af1d848d66cf928e9008d7460f55c68a070cf02e58f18e1b32d3dd07b2352dcdf3ef17db8e5d02d7bc8d3ec45fa2548007f019f212ff3a578bf36160fb663d0571ad4a41dc9dabc0aba249f408387cf9116ea039478fe2702759a0623245fa588f8194a17aea18f00373206c4e731c0659fb9507d1f63f2ec2d2db4788dad33baaff0f538500239a23a40dc4525e61e62d87143a1a2ae412ec3cb955975a449097e0ba7e71f61f2701d4a121b81fce89fc820f0453eca3e0e86285befb1ca5f34959ec0579ab77840634f9aef5c0b8a802f1430c6934018fc235a86f85308ab07259d791205135e0b2ae11bfc71f9900f3ddec417475d2ac5bfa70a6e7a6f09ea37813ad36f4014bfef0518a7b10c7b14806e7c83d6cc4f0853fcd5c7a5575048e879c2d6f758cf9b843438aa3e1db49541807f0180eb6f413479550d3cbf271de0472e35f2e999384f8447722f8ac9f40bb88cf2086e819f84abd456d008cd275852653bc964e0037582a1f1bc9ab81d80429774f7c5b1eef83d282782ffe829e3f99254f92753aabb2aecbc183d63db7503e4d7f440b5f10c157a7976d46c789e3e56b4c82134b9e28122486d345cbe381394a06fc1f0b8bc414f27011be4a206fdd0a9a88cf82288487c8a116d6fea13557b9023f913366b731d91f41ec650d28610007c1f95146f6586833f3234e029420d7235c23b3731ca91ab919ab1479102f584e4fe68c43a69bf47c006cdf868e0cb163cd24847fb351c7e78422c447c9fc0badd2a487c3f4810e8c1039fde0b0250eee00f2a3fa374e88b7080e47b42e8f0690fad0f03b1f427d43a27c1e535a8440d2ec3cf28a7d3e4cbeb394ae006eef8710c1116bd919e9d677348697782d1f86dce023a8c1a42e7f41b9c0e182a0e1dc1674379f1eea66585263cf5e5762a1ceac03a763e050142da83a103bee489412bb55678201b0474042b5f6f2a012aff26ae4b0b38d802a8ff807c0cda8f8e16fd0c261e3ea20c8de33571a13dcf8f97d191c72f5169e048b85cd25e2df178e82c5fedeb8863e0e37ac6d389eb706cb2e9b6087da52d81f45bc690bb82ae74813f4dfccb69e7e34446be8fb1d5cc02792e1728421baa44f89b941cd88a578f9e1258a1f729c1e851c470a39f54f7bc1dac4e1e4a0d997bf28467bb251c5fe5c5fba5ab4dbf6786ebb7e4de7c15a813df04e7c5d75052a05150c1e14e66c3db3e051ee1ed8ea3e2d13e92315f7b019a1bdf86439d764149cb330045e3df0001f40524b56e0a551b977448cce556b667e3a3906e6306936fcab166933882c5c7f270d87b0c2e7c131d09f4802c86be9695e88fde174e08c9f1a3c449e152489cf9124a6cbcc59b2e1d48839d83aae3fa1b4c7afe6d0fb5073d5d9e049dd3956d90de910d1c076561fa8dde26ba11888707f4d8eeb21a327e9291272f4153de1bc01aa4e5c8f8bc4ac88c473366c917c66d6d3e2a4e8fbee9d881101472148040bc421f297e4596f58d44f5f9b533709a4f9b4aef46c38bffa352f83a16e578029998cfc493fe2821389c0a058abeb3b55c8e1c383d82c10587fd4c72505164bf5afbb13bc801e3711d42fc1209025e902010bb149a3c9ed6a9eeb336b43d233a664ee7c5db9b2862f60d14393a0308495724c9895772af6c0d2b30f9e3ff79161266bc9c3b093e051af797a1a0ec278c42fe491b541f3db1f762a74a69137dc6381f331f5b0099b22fbc63e8edb869f41610c97d170a479fa9cde93a24cdf1447bb468010d34791e9aab1f4328d4077618a547d8a1f32e74516d0311f045e460b7842f835e8ed3db663dd87ec01e00f75304d0e7f2f43dcc9ce0004045d930880d3f8a81872d234da30b19b5a6797c09f3825741f4281764ef836ec7a329a5e69d2085f929240b5f446fcbde5368cc2f318ed017e69ef89468745b41d3e472fc582d1865832f5218e2a69a307f0db080e7e80bf02e16de9fb570be2ed06daf557178adc43dde46a7fcc1d9c96f1222e8874cc01d86c0a6679054f039065c70af0537b6e097073ee606ce2e3c20e71c9434be8aa5f5a544139f0dd21c8724804d9f2a83c8e55030a1491512f8180ca5ddc520ef2f65eaf08b9ea8b90d34751fd3c9f2710088e82a4fe03794f3c3d526e5fd56a23f0ffc4a0f5514a119f009781b61dabc9d3609de01079fd6f350c945a429d14ac640fa2c3a98b820542afe25c4e5ff6034f00a70d6378123e83ff65c6dbb00085e489c357fc551d20d5d31f4d1b43f9ee349a31f7149ced95491b13f8c35722d59a29a8b48a3c3a12672291eb21e01104c3a0ccf813b2ab2e26ba4b9f1b0c6561342b0c1032c1978812280be875bc9afa0a5f93e191276a565f5fbf40af58af5e8634ee8f9a09836af44c08f1dc8458d57a4e3b4cd1c1a7caee68a2d45502257d0b7c4436511734659f4681e8730ded044a6f7f060930bb03ae02504afbc281b90361f214a6fa68aea4b3112f18808296a1535a81fc5501dcf2168cf532d4cbd40179c6f2249caa6d4b2780a832df6567ce7f1141d6d3a4304af494e8c9e0b3b74e5a1960ed1c2f9291f906c214ea92302b346ffd0b0e82ab4847c0f44657c479b38ed2eee71b705785f7883f14795616d3e20f2fc008e409e890723bfb3e4932644a9ce1b70e040d3a148f01544cc4e268df40abcdee8042ee363e1436a6b80c3e0061ac93da842b4c7db9bdb2c28e823b9a8ed4aa3189d8a234fae200f7e237948b958214c5eca081a0d412ac4f99c7f3cc9b2c5e72119a2013813b80c39ec5b58b9f26bf070f89889c62db510b277c878e369041bf787bcea2b09cdfc9bd50d47115bf2ac295a7e8668a59551e63c0e1ee9466c91e323c18cef8d825e8b1b49cbfd39f1882ae89e0c15320f80c3a3e3982ef2528b4ee901615afe1114271dc12bbc8130a6f428489d1e4206413a909308ae820910ad20079a37c124692d23ac4b68d3b41189a1723a511ebe518d1a5e4869c3b6e312e298b6c06db7beab5f244dea375cd2fcc3994afa5dd4e6230835d8c83f188ecaca86fed100870ba24368ef801bf4260e08d1523423bed205a55e1482cb3f310a7e843b707cca26403e22fee072f00cf84fa9b8fe468f207e29a9e913e12ddb5413317750c951e7e8e3e40dd93df123074afd06d569bf80987c99d9e32f796a3d98671c07038a75c4463fb6201e4e8f63006b97c942f40cdee26c2c5aeafe071cf74878b0f14c437aec4785723c1d9fa79d2551d3c77c3c760c1d387c4d9610fbc67cc327046ad0a74cd5f944362d1bd24ac0e5c8557a4648ee2f2698b0955f763ca651a3de9da4c8bfe441703e01ee8a298a3c1736751eca858adfb04386a33171f553fcd49f08e47ab412f3f530b9a1af84bd8fe2eacec62be3bafba494177a91c661a921ade845cdfb8823b8e59e5587c00583937d89e08e01bef85d9948fe66c34fb77ff4b8a9015e7ec8851f0e0ac5927793137de718d9474812f00a8f58fea688983b1173f81a0a7878151d0437dc338ebf1021c5175595380035300d82470f2f85a7c7076b00fe91e6e37335f8e208be18f5a911db237481a17db809fc2245c8bc981637ef014ca71dc78ac0d37df1bd9f436f9f22079806b416e93fec701f50e1813ffad8e35c5d391c4d3ef41658893734c5c81695698593993143efc1b372a753f50150407d154f625e911e0c8f488ade0b6841f6155ab4d1156688fa0b47e2ec293b8dab6520fbbf87f0843ccc712c4ba973b162bc4c032dbea7d4b13fe500e17640003c7219e85ff099f9de87ea23d946b61db51cbe26ab70ab898af378d244782e93583c74cfa69d82c3fc014809700a65103da60d699a6b9027477109d22e3124c64b456870515fd09ec219996d05c6224f1b44be882e139e40a9349da2039c63e26bdcf160f4c344617d921ac56fccaaf3a5b4e65efee3e5130c60f9102d845cae8ba08f81404e63b883e349fe4878212f187c89f9d0c55c22f24b343ab49e3042bcd49b1b7a81609817d143e3651863b859d552435341f90230c46c51332957b0e54fdb29a2c423e139fa3c7bc1335a00c7b7ac9972bc28df0e3450e97fb868e315d450722f0c10683e4078aee6304d3f3a9c731480c4e8528a966f052b929711611dc5f6a3978001be1151755a465fe15b5152730d8e867c0d25a6f4a42d34fe9085988f0441817f3260c2f50cc1e2647433360aeaa08bb22275075e3c7ca1b0ab7d8285956f5dd627f4a9e47d30d1e931cb1e5e8091deae21394e4903915d05ccd8dbd16447fbd1d35e4310a6dd86829863d25abe824a4a3fc521c5d76982f4206e2c5e7007f16934ccab0961ea2b3540b015ff0abc10e8041d76818457c9517af4cd1e2f847ad90050e1f147728e6c2f67795ec7a13b3d004b0af72a4017c1be79367a60ee4ffeb7043d5e258f8cffbb60480f5970f65516e1b49f1a89dc95b1dc7d82647a19690a5dda88e5d5c82e68659343eee9cd6b0068bcbccbd2950685947af592d956d478f7d12b14f682a8946fec33a167207af47f5aa4f94058826fc12fc59e22a3fc290e5e6f8084db272a62625bc01bfb4a49f0b612c9a73794dbf080b3094755e4d003f51878258918be902935b764d6e17d6872e296dcd636a8422d5e0aa4abad4c3c7c0607c4f80f432a6fc866f7f0173ecfa805eb577cf8f01cb8f0d874e6bc0741206937df08fa376844fd88c052cefcd463176004c005b90cfe2eab93438a46fa2f2b575ee5079c9e2b30c2db39669b8760a817c06866eb2d40fb0c80a8e82913c0dc910640bb6a24cdafed9636d087cb81f4e9fa147d06fc8029163a7e93e24d98bdff38c9ce87d940a4052431e4583c38f03c06ccfca191be0dc391c96732b5be932b06fc50811f1b060c3cae8b84edf955f82719ae26a0a9ef9f2ae8b89e5d17373483d22aacc0710b67226d1e800a7e14182d2ee092869fb22973400f9e2eb682d136d1547454605268bc2a971c8cccde4cbe387edc99fb9824d078b6bcc7dd4850895f26863d09074b1c441b3e1b552334bf0182ce47a9a1fa6b81732f6102fc7039c90f4fe0fd13361adbee899507e184c3c7b0947d744628fd68ef824f3759e9798585278467c2eef303e659b0ec74e004039ed5a7cd7b0c32bf5012d996ff4c39252b32bcababc12b32af78862c58ee864ad8db41d4e2bf7c75fd98012ebeccd200efdab4e0e54292dccf02b387c422cef60c761e2ae2caa35813f3c5c707da4e95036e250b1c4d652dcf930824661bc27172b61a56b6211b264ec80496bd45203e9b26497e854fa09f9b917b2b6b8723b209a4273cd6f8367152e8418e7a3c059c985dbd81c7d7f8e26c1603a63892410134d9ded4a96ce0e111788c3d2435d21d6a9082af4159351014673e8968c7e70821e7db7059bff08f80af0333b801fdc0f0d58da12b5a39f39118a1daa52cc8f1042d0efc994552feecef81af5541bee70a1777e3c2d33bff78d93a0a277d0e3270eea070ccb36030b2b73635f9b72d58f45484d693654df0307fa27cc71e890d08cecc6f29fa690a6c87ae2863fac349f0e32162e88b8430bc29438a3b5e23fb45b7e8aed1d8f6803625d83556319f09ac71115b223e0d96d67ff521fc2a46a09a83dbe89318e5fd9d26a66721707b3925a9de83e3f44f587dfa1784fb918c39f1cb2a57aff013e1569c2b3ed43bbe0601af0b21ccfa498c8dfe4a0a2a0f629df481a4e0df1264a255c478e46a3204ec471420f83214a6ff3388eb673d599cc489012e2746111da8410f0713f145fb01d3c5fb8068f3c4b2c4af0306d6623752b91bdd95edec70c007a1d0f4633b3cb8a8b9efe34095bd1a9ce3677003f436da1c77ec698cf36df9c5bcf8f470fc185d508f15471ad07b5114b6bc9528871c41d61a47b5c5c84ea322f683a4acd892d4a07d972182baeb6b85830d19b13fd5e0fab91f627485c5099e47a482a33075e3352491b78e425c1c4d8ce03bb47cfcc6978eaf31a1ca456939ee25d49103d854a60b110971c345a9f432111ab7f044f397ac10f92c6e706c1e79763c52754ff74870c10780597cb819523e305083fe2461c277b0e4e758da18fa034aec741737224e860cd62b3208f4732d9c7a06a448afe08f9847c67afecd04a75de4418d37d183c2c612f8e26330387d27430fdf14cac83e1464cfd110dff660a73c8fe748a1bd2845ec7c8e39b6191f721c480176afe1a09d131f18af72c183776011e3319d017a0102739ccc0a327721aa9223739c7a37304c2f37a3f90699d278a34e2d1cce9911ef3577e88062de4b70d1bda899ec41085af394ee0ce805111279a6b5245ec790a00feae068fb9101ea3321f91c4a232bffd6458f26a2a1854f414242df4935c7f3b07ce8248553be831e91ed44418cf7d465cd5dab390faf65f1c1b98f339922dd801009722a9d34681269aacec6a984bf4120e5092dbadb326854bda6540efecf0b42e7c320c89b0a73f4bb53db8e7e3979b3b40f8e0517f7ad60007fd307f60542543d89e9a3bfa2b0c12d493d39daa708da109854ae01cec7bb7b32bd0e35607484a6a4277569d4038a24c421a8d9da6e0d14ce688f89bde0ce97a70a10c4134719f0035ab49b1285e389f829f3229df2fc953a795e61cefa1cf3e23e73e5740d3ffa6c3eb916bee248232fd323c49f9569f144f4b0781793686c342406fc20141dbc8021238e4253d7c3f110c82ddcc97a2824f8fc941db56d67499a8fd2804d1f8211c1e39a763421d884f72288c8dd54f17b2814331712a4f1218832e439f87878608c3dcee601d44f90d2e2251958f260700e2db6e5e24bb1317a0a8910bc8e03285b2b062517b0376a5359541dc426b0cd14ebf8802f777ea052a0977754d15c3c50f81c4db65e128279d5aef39f124972c1b14adb509a9b6fb3a26fb719f2389536195cd01f1fbf20092147fbd37b0c2e7468699454ae748ce39530e479984decde8a62f9404a2e69aed7f34d833ebc2a49150f43a5c1f10ee9bd9e15635c871a02dfe9caa73db840d0d5505568310686b893bca52b91d039ecd6435f60d67803743bdc511aeb0efa40791747371c48900c7b4f029daf821742cb0974e8016811e46a56183d5496123b0606068e0136b03d10bafdd246091d85898b1fd226b9ab0ccd712b77507d032ce8bb41f8b61964a53fbc12c7593880be2800e25edce2e633a1a0e45e4fc03c50e7f8067be63ec0a92e0fa543cda39a2460979a63e0ad187af3094b4ef8af617b158b895cd3f4e97e70875764577c004886de54221abf67b7e860a412b9daa916ef5528667f95fd7d0f3c1b7a459831af4489d363189ae359658dbe5058dccf4990b4ffb490a710a3cc0721eaf23c9e5aec313ee07c00e2d52e43e4fa5158a4369e9c2d0e83a949e310f4fa234d7f361f3724de6741c7ef4805c9bf60c9d15e8eded90042da5cb6c67e2bd1aa1bb9549f068b1e9a121b1faf28cf86bb3b145f52202a6ef725d1abb81bf004c844712d3710341248547c9022b00d17e9d1ffa575d184b4143d98548b8e8203095f2348851baab1f1042a10d288aad25fc0a4cb3671e8c129418ab3cdcedc9e2d928a4fd034e1a0e23a7d96051aff9652f29faacd8f12f86a477898dc1916c3171068f23ca041f657e2144794e6e517c1d9fb528f22f9e1591007a02474b596cbf1bc539d4a451ae7b263f37d0af37c4091307f08a1cb3bc4a3b69670f5691dba74003b316fcac09707dcebf26f1024eaabe7f311b508da9dbe852f802d791691498ee3d1c79332d3e8ddf94efb81b87a033fe02fb506e6cb3e50b4eb31f55c6641ede24af63e89717e24959e7fb466f55806bc788a3f287cc99b27dfa6cce06261087f0eb6a0950091e32d029fbacb134e7ea0d490176217e8970440bf8bdac6292c42fa02869afcc8911a9fa7657e5286426c212620f993d3994d4542f83f3816fb528be593871e6d02815cffc7494d936023e45fbca8b2cbec18f32f3e64fd55d48d6b5129e3876429ff05c8e41b0df4f94c2674bc2527957e865b9f5613e2f0dd1c3eee362adcfe8796425b5397d8079813e217a200baa54038af9af1fa0f30659a505694dfd20842434043e55f1e663c8038005e4e9ea2a95fa03c4e410a6fa5ad1f924adb2312dd390b31695e908e525fa96ec67f2260e845e0af6d7596c77f4cbf7ccd942adfa92befb9e2b479d8d7defb99f19e840d369f07907e3b3b2ffe50a54e5e48663b843f578fc04cd3f73c6d7851336eec360110bc801481e339abfcd8143f0e33bae06bcca6ce0306ccbb80f268cbf174e001dbaf0ffb04c42978c1a217ff8d6fbae06a1e29acfc9b387bb4238d31afa46d7c130ed29c2f4cd71f2174e8000235e83451c43cc35a9cd67094bc01031bf48f0f769e6d490b974a9f788b1cce27d38480cfa9b1d15a4932cf4527c1950eecbe830622fa5311a63b9a69d036eaeefc8824d82efc84e4c1ec2cf1c410713e076d94062409e908f630d06cb836fc86275397a052e75fd610bc9b45a79ec80113ef81060197f334b65c5481b7d939f56006c4b99b8020ae06e7f124a850bc893b5dae810ec55620a5f0a72c65f92c85de77c6429c0395118ef6c6826bca22e635c8f87c4725498ea910168d62cf79031dee776070c99f648a74113bf2ef8d35fae709bd1f9472677381adf06de78db69b32fa410a9bf6112a88dc9388d8afdc129fd19496fde41126dfb0fcfa205a85bf229e0df8783cc5a6bd4fb4e4c14b6202633f782b6e372580fe2e787c89a2b30d1887cf29ec35d97467b05e0318d6e964387996899bc6c1c6e2bb383bf8a4b04eafe544dbe70865e04bd531d886f2d4f84026167f063bfd6a933fcde194a9ff43771b11a081bf1317c391fcb8e29f06b89b90110d0f5c2ca4b59c637e6f4a8f2d24548467e364b8f1529970423337dc4d1a2b0f38d8e547a908f576ecc0bca0d9d103a193fb416e723e068cba4b448173530fc06c46896ebf264c6ff725950ee89114af1ac4c7878cb9e113da7039963e2b5eccc2d7cfdde1a20fd491f32774a6f6a80263fe4b92264f632c869bea71b61b3cd73cfc25d0537581f05154bcd8657ea4de448d0d2d615ee457c492bac726b04fc542ca3e806ad3bb652c39dfd894ef02e4ce37b681f1335256fc1018776e890b0f774263c5e7259b0fc58ae32b82bdff9b01e8dbaa815afec3c71028ec113c29e183ef433f19dcf22d4a086d3a39d4fc0dbc46fb1329536ff8a6429baa23c7b910416e3a2cef6e9e891eccf0f0d54cd0f32a75947c1f162bb744063f1e9de83739c3c8f118527d00940a2ef76787263344d0ff10b97e5003280ea90dcacf75cdf922a4127bc881128f00859833114cf57f82eda6e3067abb44be8fa44194e309f4e35ed6283f8863e296c026eeaf045ad93c36697d3253a84da62ad137093a77282d526f2a0b8fde9435e461eade453809720f951838610b463e800bebf11cf20f84caf015a224de5198eaa69087cbf38124c98104f9e406ca2ce84288d8fc1619526e456f834b3992c603eb98703b27105d8c73ea8d81873fa8a882bf6084e1678b3c5c00cba6b1d87d7243312ae93420327c114c1e7cca012f9f27559b57094cbe9902983c6c089f07014ca1b1746adf0c9d073f8da0e7f3562fa7d4e192f3908ef8b0107abeca82f3135c91f8198a21be44a9292e6350e0d7795df845a044b991187d9cc800c72750a1f0170b60f02450310e58b6b6b7944b5cafddf0ad0c2c3eefd39127ecd4742b22835c881ed73b9954ddef09388fb3a1e311f9d0bc86a90f2f62d4016fb1a8a89580a6eee8a5db4748117a872f4336a645243e42aee3186818f0cd7c6a2c6dfe4de181f41096f8790a5f75ba141ed9f1fc54d27f5b14fd0388db86105171036ba27be9b2f0775f7bafb69b9f458190e6101f713dca3aad63939837cbe064ef212edd0298c6470b4bf29b28fc78ba16cb479cfbe1815bc8f88d56856730b0c8990c32a52b114af9312645f612c33e7fe8678b572931f84c9ab4ed35646ef8873220ba0a08d253718978e89d407f2d29769655f015e980d972d25a7ca000289e03cba3af706443d3a19671b60450bc114c920794f7b81bbd91398d48737ea822d45f50f0f8ee25a6bf6d98f06f38ccf021cd39aee10bd94b2980e35f5c19e3656469bc8d11077f93b1789e0e397ec29fed39ea18f80f4fe92d6049baa2aa0b0ff3b5e51aee3eed337b9a1ee50f9e23512ce12c1bfc6e826c78a6ba3bfd9661f1813ab4d82d4a957da93db1d641b6e2f5c41e9f5321972f20e36ab72ca8bc4ea23e37dc5bfdd4b2d0bfe558e204109df89d38293f650045173e797c0c0420e841358eb882c5305a8c1e05ee69bfb6e2619363e023f4711033bd963841b60d3c597c53971e1acb69e8673c0369275a811e0f5da33621e19367fa13f6290445f14defb81dc3be1cd5870a7a1204c467a037c26d0cca7109f09dfda9b0826ba226b71e1c4067c6b8e39fa2a8fc141e057b4ca101df65cb99ee7445bf873585fec8abef352da9f15e566cefd828b6a91df8b8d24398b6a242cf2bf380381a9b41ff12616a37b194e824fc98fa5000184e870c9776d024f324a9bd3f42e8e047f9b0f2b196519ee61092374329c183c2c2c5fd44a8e34e0283b661591a6764f8e5f90808f3f7b2e683641e1fc009777b1941cadf1cadf496ade9a77094a7b11e99f925907efc9a133ea7e4edc75926793283567a1021b637f3a7d1eef086c253e281b73920c6f99a2e7abe09dbdd4322437c18ecc7e3199243939973f177181dea4f5ec987d6c0e11d94685e93a72bdfd08cf30538ac681c4e167f41cd8b1d29470dbf504480eb5104f43f140c34d655d50760b1491748c3f402512aed492e083d04a7867f1006c6975132612349c5c8978825701498c0feca8be83a8630fe1d2ba3740c12403c4d4f915d2307d2fbdee2bc10034abef89566cf10bcf3576d5ce81d6b2ab8b6c4e71f7d613a9b428fdb93d876536053fe018500be434f8a3fa0b3e46d14a0a28f586df9193128b8dd02075f38c6e82bcda5f9412c25fa4b93394f53c8c43d9d69e28cfc6ced00578a388cc3315e2785cecf40b073a68a24cfc1099d6da7e0cae55cfc784d54c83ca0a618de01039ebf63e8419329a6704191523c222410fc8a4fd8a01e8d381f3543b481af54ce45f1f787b2156ec311a437f142d059386d9f27a987cfd994c0478081e4182628d991ec70711280e6cd75a189e78d08f14f38097a3313c4b6193e4c7f2471669b795af37e7f8f76e3172c1e2745a29b9ca27ef668aaf5ce78f8602431dbad8ec25f4801e233588d712b3896ec278032f81bd7c2be1403c667c96969b6e9260f559db39548983890aa241f238e85ef90f3e633ed40fc2e4366fff246e77fd4e6f764e4edfd8435fa9e26a5fe8c021e3b4982456fa291915d43abce2f4300ee0e67e0277353c6b3fc86781799da43c932f5276c1cf9ad15bc981d63f692c5ad5fa1d51dc0bde414385972c516837e920e2d1b500dc1b7e446c7d1ccb0f0568e6cf0210a8e3c2257c16e1233f118594a3d5c8521ce48a782c6f22875423a98e8e7a6f5ebf6a6f8d68ba9c353e4bec581446f22eaa41f319ae46c9c7cd1678dba388d1d37362ce0cc29fd85f9a5c2c4975f48d13518173fd2a34cfb11989c0341eb7b293586fc290038be3a28e84e25f30ffe743825110fb4280bee8016f7ec026832b98a4560fbfdb0e0976f9ab61528a71c4b1a005d278989e7a14486f311a2e9ad9e14d17e758af89a12445fa0c3752ca6107d0d1f9397d445c3eba0da792b3fa7349b1f5bbe230da9c97c7aff45d7104fa285fd3ab4375b0d80e6ab6074e7a5306ae16628a4da26bcbcb82133584fa44fa06772e78813320ae27c84886c0b07ba7ce21c913d8a6df357429978316e34f95874bac5a46df20740266802a5bef884226a5bcad8865fa395e067d4d0f172e2266d1a774a4f6c456c5389407c8c0d647f0381a3b3b1d26427fa245eed14f60812057d4319d3e3bf4c7f0783d4adaeea3ecf17047d8848097fd363d459171a7cd24aaa0da30815f77026cfddc4413e1c184876983c8dce7282f10db29e78f202943d8246215f72d7e5c5a069ee44ce5e31cb8ec72b84c545cc307bc54557eec59091ff091b1f67c08d975af3490b6a23e1c95c82f494caf89e4ba444daccb0cc1f0070e72b6958f104c6d2e83a49232f878ddf020f3f57c221d11fd823ea9f7956ec54859efe485602ade840ed4fd821d09118acf9368a02f7e3967b76caabbb4cc8f364989df4639911df655ad588fc26f80c254eefc38485c71034f9a51eafef3161c519a83df94125577b521bc257dc1df1a473ccbb68b1c171a409fa1e5d95def08aea675837fe0cc0e7b3a8106a42721439a017669bd3e3a92f541ce09ca25dfed49dda962245ba95bb44276a92cadb9058340b670cdfe2c5f59e924cf9ea54c96694c5915711cce40b08507227766ab6073721dc0b090bda0e5387176c3ef78607381cab0e22bfa208c183a892f7583e02781c0e98dc4b90297f864b229d5492e6d554c1a04350fae349a0247a1b99e0afd13bf053a87e4fa58f9d9f2266c71539c9a2ab1832e493b232e939761c3d28071334256923575e20e22ab69070d90fa07719d1de9484067b69c7e7799451a4993b06bd19238a7e5341f51de417defedd792f311eec47868c6f47838eeb6913e49b6c92e15e22209d3019c00564f2f273a0505b8cebc22f9035f5912118fc50c6b217ef143e9f215bbe869be767fee8700233dafc1e19bd3dea080baf4b14a695893c7d8e4a69bb0bc40a8fb4ad6812090a5d54744c7b20c5e8721ec76c0f4312fd8a52c1335735c7343841a780c1e83f069cda93dc48fd11c1584703a4702c15695e02d1c16b51ba4f8963f29cdc8e6cb844a44311d5a7612451971369876725593c9727a42768e9f27b6d5fdec91d407f5141cafeb29bf32ca71e5a141e02dfa40cf552e8d4f13e4d8eb897884f9e064ecdc50896793f6a499c8e5415df0b15a6db408a1e24d38bad284b863772c5dc8028f579f28e0a4d68a380d77024c5e9dc2073c61c5c768bc3121e02d3809d64539ed72952e0dd60ddf919272474211dae17b324cc05bdb9f95457d169eeecbd230e65be088116de82b06b67457ae1747cb83c53e379078daee8ea283cbf226a8ade9bf4e57930ce5b0291add728ce769540b66f81b7c4175df2e3fa51d44dc87ddfe149e3eb01a1f07314fd762305755e539b737bc973e1b72425fa46b835a7e04843f301b2f65c4e5dd95b04277857a546ef838cd61b3ad9dacb08301e91aef53868988f70c0c1af1123e88937b4166424d28bf963c8c9ccd8784a52e2e8b92d22ae8005803de3aff5b268d59660a3d19d666eff28470cb7a264b89188427a9ff981e6aa427a25c9075e640da817f4e4b283586578317b1a6d37794efecb87b07d06c401cff444f0cf5c3d1f14c3a87f50b97c50948ee65261812f3aa2c8f3186db81d4613af78638ffba912e01faf12dd4723e7564b41ea5dd308bd3210f4a2789cd207d464f9991901b6163c329f812775b34186deab84826772c7e74867dfed81a3035220b229a19a7d929b45da8699ffe31b301b4097c6efe44af14133a47788f1b5efa0d073ba448e6f2236e153540cbccb1734af52754313e1e0e2cfe0489f2565ce0789c2ed2de18e873933f5a28e7470382919f6030a487f429e9c5215f5adf0d0de6480d89b3ad4fbb9cb18af2a7bdb7552edfdbce8649392d3e4e701fac990cafa4514fa6c42403cbe0503612f9ab3baa4114a379103957b2ab2e4c91e993c9798437a1d1bf265fea61a5523450fb1e0507749f1e70dfc60db6255189fe649725b9991f02b310a2fa0cd98eb50b46e40a3a8eec1c81ddff44c7ecc550287c3c4c4f3b0e873681e4e1f498ed6774294f8cb5056be4604833732c98613a1c3e198581bfa05d282f7f86be1a624157ab240d6e30094be8616364f6851f40d49b86d23f315ef24e0cc932a13e38a70038d07a2c047e852d309ba40f90d988078a2347c1c110b51e3399f0ea8c01b1da1cecf332192691ff9dbf044c87e04919a6dd2a97cdf56f9949dedfa8c213597cfa4d2652adf67bc74954cb9e57b59e6d7d08f9af1ba7432d9f585e524ecb66beb423b6a3295ebcb84c23374f932932cec521b359fedd2c932df240c2b9fafeb54326acef1bc269fd0f8b9cacab5852e1735a1cfa7527ea1719229cf4a992dd48a9a4bf975996fdc3e994ab99d9f2ddfcb265fe844cd560985ceabfbb6abdbc2f29a44d49c9f6fab9c676552b9be70f2b9e47b59b695ea43cda553e9b233b48561385ebeb1cbf7b2869acf6452764295acb2755bf6752ef95e56d95275a1269c84b66d0c9d656772e98459a99450534eae70eb945f1766199b4ce8ba542a99f0d309f3bd2c13500f6ab6c95719b7f3ca4cb250a87209ef096a325de80cb7cb79665d280bc33375b942076aaecc784ec24e7796e5767699cf794a95f2bdac9f06d46c6367fb649fac0c4d269db0f3e57bd9d6655d964dbedde54df59fe6525e425726dcb2cef995e1d74f53c9c6701bcb4b767db239749fa6fc945b16fa64e5e73cbbac1286dbc01830c9e4d36c63d84daeac9c845fe61376957c2f3bf785f655e20bed6b041f355edbd36c5f585ecaadccaecf57096526d7967ab1b97ca1cee7938d974a3829c34a177d2ccb32b51ef87d95abcb64e164f25dba2ebb4c2a99f0f39d974ae7d3855f36562e09759e26db2ad9d9f926e7651b2f9df2cbf7b24af67dbbcb5b359e66127e9f70d285e1e72ac32fec7c5d12fa4e937d5765d219bf6ff2c926675639f33d63b4b96f4a272686f64517a2701ec1478dd7d0beced2dcc4c49c72de175ddb57538ece7d533a313131a532b973683b4d66ab7c59d85d934e5776bec9f72b4eeeebec0bedcbec2baeed6b29a815934fa7dccaf3bb7cce4fbe975dcad237e6ca92e93acd24f3959dee0cb7c924bb2ea1cf3f2af339356bd967b490ea8e693a4da5ebc6affc5c9d2e7485ceac734e73998ca150a5bbbe33ab8c97cb98ef9d65e99b0b6b39eb13eabe4fd9a97465d6292f4de8384d66f2098599ced9e964a1ee7285f95e76c98a8945a57d55a752704d5ad1709af0facaf2cac2cc64abdf34e165f27d425b2754f98cdb55a974e3bacb956de195d9ae2bdb325dd65dd96792292b5f67bb26dd7895d758b7692ad7d8c96c97efd3096567d6f964d374bacba453c9c64ee6cbcab1dbb27d7a4d13ea3a93cea7eb4cb2f072a99c63be975d2adb353131ea1c5858cd13139b6569544ccc7dffb49ae60b5db270cc2661799964c6719eb4aa646759fab6b2b32c8dba4ef97dbbcb33d3699a49f75d9f72729e5fe733995c977c2f2bff49a1685f81b19b9858600cd8f2d089cd16eacaecd39597701286e5e8fcc7649530fb7697a7a6d134db569974cacf1686a1cb3699649e692adba5727e97ec3c2f9fee0bc7669a72bc742a956fbc842a59b695cb349f4927fc643ae3e5ebb6ac33d992693e6739a94cca6b32996c5ba8eb8e692a57d98d5fa5bc949ff07209af7c2f1bedcb63c528e176994cbeaf9b6cdfb76d97ca242bcbaf92855d79853add9985571da609859932ec4c2a6765725e26d795a94483693e65766526a1cf64927561263c8b89c1796c9edbbedde53d12fda5f94c3267270c5d269f71ac9ca5d5a698d87396a1b39c9858f529269697b77a693299710bb7c9768e5ddda5a99c5959669d2bfc8499cf2574e57bd9a4527369aecfd519c749966de11596e1765a0d2cd35b9acca4537eb2b1729697cf64bb84b534df767db6eefa6ce3b59d59e79ca539b370fcc22d94955d386e934a2ccc65cbb2c93509b34a97659930ab7ce5f9a94cae2ff45d67f9b926d72b4da50b2b972f9c4cb2f19365dbd94a937d425b671256c24ba5fc42d9e59c989898d8cae6b12ccb2ca3ab3493af3cb349160a7d59e833c97493682acd986599ae9b5c42dd997ddf77161363e6b1cc277a4a338e59b74dcaf2ab9c67367697ee102da529bf4c28dbcac97676c2d0d8094d0ad1519a7192855ba813fa5c59a533f92697701eab3cd4509aedeabacae4f2e95c99f10a65a14f9af2bc64caf2eb7c2695ca3529ad46d9d0bee89e73e05cd28b76d294d71976be5066dc32633629cf4d9a4c68f29ddfe43b27573676e5964e49433369c2b0d385df64ec4cb6b3724ece626285b39f98189cc716ce7e49e50fbda4e984592774a984b6c955a97c9931dfcb4aa151e6dbd7da0a7e7d39937360219d9858f2a5fe0502f6c9d04a9ab0ab74ba73ab6c57e5aa642ee124cde553c97c3aa16bdc2e97f0daba27346213ca642a9def537edda4d219275b24cd16ba64a1ed0b653a65d975dfb54d1f61994b787d95701266beed32c9aeacfc3a67660b7559f965b24911da48135e5ba6cc74ceeccaaeb2fc428b345717ea3a9770bb84aece27bb420f9bcc182a3b6339865b662b2bdd9948f385ae4f1786db785d93cba72c0f69b6ac72c974b64ae79c5cdfd7290b6942e57809c74978755bf7996ce320cde7131acbb3cbb66ccb42974f2690e6bb7c32dda53cc331bc946119fed14cb24be533096de7f709cfcbf7f5d164df182a2bd9e5520985e5d67d7b3495cab69d95ebfbb249b65d42953c9a4c18ba6497f1d2957734636772f98426952b0cbb6efbd4d17c26e3e792a974c6cf363927e33647f319aff3ba8c9dd0394ebeb3cb1a365d38393b97cb7556ceecdcbe389ac9769d9771ec54b2af0b6dd995ef65d5bee8dabea8255e5699b7b26f777969fa46d339b772ebcab0bc7cddd63933994e6da3c9cacc978d97cae50c75c2f332aed16cd9a7fb74d975e93e994ef7a974976f7779789a4613daaeb0d28593f30c85be6d3b3fcece5609659fcf187eb2739caa19c7ef7385d9350965b22bd38d512967679c9457e61bbff1bc264f35e7f66d59a5eb94e3e4927565534d560985e125d3095d4293301bb38ecd95f99499cf997dce4ee7ec3e5d65a9a6ecb64fa532099593f2eaaeab529054b395a1ae735e673686dba7fb7cf68d6ac24f6592553eddb75d2aa1b0fbb2f18b829d4f9819cb32fbb67c2feb2edf50cd395e5717ca2e6736e9329db30bf711ce6bd3b985b40d54d3e98c9dcaf6e9ba4aa60b752e577709fdd4949f731cb749e63cbfab92853eebc4a2d2a8a766ec743ed997b964dff5753a9f5040c1a898d83c7ddfeef29edfa9b97459a5f38d99f2ec6c99f1d355726a3e5979e95c3a9d6bbc6499f0d3c9dcd46c675766caccd7856726bc849954bfa8201f1a0cadd68989bdb0a6e69b4c42994af9955f3839b3ca27dfcbb698a3c9e93c37adceb1ec3bad5293999a4ae5735de37576954ce62c33a9f0b44a4d7e6353192b93b0cc26e5a5f27d3a63372f3affbd6c61a0f4a96465a5e017dd975329f8c56ce7c7d47ca15078969dcb27bc9c65b67d95687fa91933e7a712fac2f2bcb62bcc425f4bcde7cb2edbe40c852e6168dbae6c1eb352d36d632833c96497d067ab84bec965da536ac6cf25bc746118aa5c9db052e94e6acace799dd7f9e9b6712caf4f36e693d49c9fca566695ee3b2b9f3133f9f2bd79d4be9665466a2e5737f9bab3ec32974a586605fda4d2bfa59c174ff7946ccbbe221e5293b98432673996ddd6e92695ec92faa89964b26bf2c9c66bcc84db58d9fe49a54e47cd765d95d0e4ea3e59e752d9326165a36652194393ca79752e619751f3852a974957c9ba2e93c96c996f7251f365c6d0e52b3359f87d2aa14bb8552a6aba4af68565259c5cceed73f9aed444cde713eac6eecabeccd59d95c9bcbc658ba8b9b6f2fb54c24ee6dace70cc2a97ecb44a3dd49459e52c27d927dcba71eb4259b635d464dba4ec3ea1b2ac7c9d33bcc68149b12fd484a14919eaca6beb74329fec1af3bd6c4ba829bfee724d3adbd8b964b2ef3a8df99e7952d96595d32a35c9d864593876c62f1caf4b66525e95839af1bc5ce7a7bb426567ec642adb17d47497b2eb74c6f3baba5068bc5c3f50b375ddf71927e136092bd978b9026a2e65770975ae2e2b2799adf2e934f1a7d9c2ccd8c96461e713bac26b52396dfdc0f11296e7f9294399ab1ccb7c2f0bb7ac605e15100af7619f337365ba32bc8465e8ccf7b2ee52d0edf934e3d829b72bd319cbd07856bac936b9f67b9aacd2552a9f4ae63bc7333c53abd338302f4f8e0399ec74aeaa31ab80d0e4875f6c26e77655269fabbb42994999f91703f6315ba59e969d59d68de1558693b0b2705a8dcecae91c8db2d17d9e662b4399309b4cb24ce6eac6ee3bff050ad2ad789ace9595e7e73bc330ec746358c9f7b2ca399685ab80d03bcd245486994c68ccae4c28eb7cc67f719ecb2eed349dd0f8097d996ff25dc2cf64bb9ac9719c9818155e2a365ba6d2d93a5f99e9745de59b84936c9de62b2f67787ea14ae6fc84dde56ac654bedde5d93d1d577e2e59385e3e59190a5de1394be8fb2ee324946561568663be974dbebd9c26547ecaaf92a994677765ce32cb64e33465f829cbec72e9329f50e5d35dfec169b6f3cc7ce5f8192b57277486d9374de5325e5726d37d5728bcc6efeba6c9742a6516dac65067f25d2a616620605fb24d93b942d9d8e94293f2fc5c2e67289b26749e5f78095db64e68eb7c99f29aa653293357a7bc3a9d4ae8121ac7526894edd9178de3c4c492d057d37c9df3fb8c59d7c98495cff975ae9fa6093fd7766e95cfe50bb7ce64db26d965fb894dd96d9dc9967d26e179e954b66f72f9769797e2d134ddf8d9c22eac54c64b263baf62627f7ff3534c6c9e9e69c2c976b994d935b97c3a936e32e67b59b92f6f0e2cacbe513331b1c2689c7cbbcb6bbe99e6caceefd385c2ebcaae6deb32f95e5659058456f832f1ec84a16e129a9c57a52b43dbe42af8649a2d136e9f4fe5f25dce4c1886420965b62fbab62ff61dd3846558866198959fadbcc672fcb21d5e4c13facead52293fe1797eb6cb42374c13ca8c5bf7f926e1d9192b95ca2598e60cb3f1fb2a57e713ba64b2c9a5f2bf349531949599acab6493c997653e99ac20b56fbaa76c7b2fcdb9752a5718babef3ac8c9d4eb6edc2949ff3db2ad9a7f37dc68473abf65c9aed12ea542ea1d076c94cc64c2893ef65951b7e4b737661f95d9f50d729afabcc4cf2bd6c0b6b69cef17275c6ca27cb7ce1565e59be97ad52e73c25cbf6599ab39c84df59b9c2f0ea6c9532ccf7b2797f82802bbbba846d72afef0c5e020a46c91e4b938563a6bc64c26c0c3be5950ab37bd13e3fe695e6fc3257369edf95f9ca2ff409e57bd9e8fc97179df3dc5669a509af4f27ccb2ae7209afccb85df2bdeccab69006e6fd09023297f00b2818add2b6ca37e9aeef0bbbcbd76d5f7655b64fe8f3b96c6328335e426798ef65a773950d4d4c4c9efb02a54f31316abbb2d36a2095e6ea7c93ef726e5726fb8c954b25dfcbcecfa894393fa37051b5254c0d948efd94a63b339f2dbcbe2bec64c272e1b40a539f533397fa9cc62e530a93d92a93eb9b5432972dbb6c93c965fbbacce7ca26e3a5bc74ba73cbbaeede4769c66ef27d995025d375ca4ba8bcaecbb7bbbc130fa5098d9fcf76293be1f775dba792e57b5935b9afb79d56033dfc93e63c33db647255c6f2ea3e63e5b2fa9c5738e1c4c4e43e695e951a952e976f777979efe45dbef09275956e9b74954c26734dbe33d49563a8528e63e7fab2abd3757e9326cc26d9e4ca649d32d48d57e5cca4f96c99f39c8432a1cfd639b7d0245debbedde585f8254d26ccc2cff55d26936f2c3f994c184e4c4c4c6c5a9d03944ed5aa5465fb655e4953094d425739b97c5b96e98442f7a27d6d3b03f6d125693ed75556b2b3cc4299f3bc7c57be97cd935659c4e632292fdb671c2bdd250c3be33ca7207565c5c4a27b7d54aa9953704e4c6c06eca31313131363d9b7bbbc77f2489a4e67d26559e7ccc64c37b954aecaa8f40f4d4c4c960399cbb7bb3cf98f34db67fb4c26a130f37dca30935df2bd2c605f95d9cabd91e6ca32e5797d63769de1f565ae807dd522cdd765ba4b987d6566fcbaed0a3d6ccaaccc745b97c97c6365dcc2f00b856ba94c224d661bcbee0c9d97ac93d9b6d0794833e95ce517fac2ccb985b2cc25cbf7b25ff22bf8354f05a9d2bfe797f315fcca835bbd17d284972cec7c329feeaa5c2e5f19caf7b27979d2ea07692ae116fa7c5ba812665b376e997c2f4b2d8c65177edd07d25c2a9df3ca544259b765ca3354fed1642e677985aeb0f3e9ba4b27fcfa683e93b2ccb632f465d9d975cece1e4d9929af331386ce4a66eb7c3a997c2f2bf827e88287121abbb23ccbc995094dcece67759ea3521733605fd56d55fc8ee6ec5c61e5caca2e13ca429dadcbe175345916ea6c67d9659973bc7cc62bdb9a7d8e66fc5cca4c175e57b985ae4e96dd8b4afff2a6d2b57dc3e63ccbcb270cbf4a28ac8c954ea6df3cb748321f475366db577ee5b86d6736669f4fbe975da7523e6a0bff8de60c33992db47532a1c9977542932bbb7c1baceb26d7b75d5d25ac5c57e5eac22c3be26bb062539e46d3e974e3a532c9645f39f9ca30131e31a3f984dbe4cc6457d79567b655ca6842dff94d4263189a8ce7249375c668c6d016ba6c994c59562a5f2654c9f7b2d499ef598d0101fba6d597655b11309aabab9ce5a592f92e6196856599ef650363c0e4175d88bff8296d5bdb17cda51bc7f152862e93c957998c5931313131a50a17cd2553765dd6c9c230f4652ed9d9afef6faec6693088c2a6b35d67a7cbae712bbbf333093b05a9844db865e7b97db2ecea3edfa42cc7301ba245738d9fcb6792193f6165d27dbeccf9d9be0d369f4aa8f36d675696a1cb77f9b2728b4229b54f9926d894974b99f95c9d4ee70abf2d33509a272d6459e65c8d6557596d2a67270c43932c737657a6d385f95ed6ed406dc6f3dccecf996595ce767e42937c2fcb4c2693cab1699365c62b3309753a99f1fc2697d1f849755916cdd6b92ea1acbccef3fbce4f2593ef65db166e9fd0695e921d0b6ccaaf5276e3a732764299cc765d4a01a7b3539954c6499b6d7219cbd0e71acf315329bb4c6a612ce7010a460b6339a9948b36a1b12c2b5f788edb16ba7ca14ebe974d9e01365d2534e9749db07366932beccad2681c75d1fe9aef2b3f93cfd875d956e942db27dfcb7ef06bbecc5519bb6e1b3f95ed33997cf2bdec5c158cf601ae68c2ed92c954325d56b9742ed979c9f7f635d7e70b75b2ef0b3fdff95d6199ef655b762a285dd90f7c4d6532f964aeb1127e26e1e77385f2bd6c612c77d86bb22dfbc2b2ac64b2b21cbb7f31b4f95cc6ce7966d977c92ad73829f3bdacdf3cb79052fb58107313eabeb0527e2a5717969570db4a01e526bc7cc62e936565260c65325b99ef65a382d43cbf796ef1aa3d9b4bf75d5de7727d3e9dabdcb24cbe97e5ab46a5801e9ccd5929bbc9f5994cb64a78e92a5de65adc5c57262bbfeb53c9543a97b15266aee9355fa7f29d9d2d74666527bc845b29b58f0591d764aed055a964cab15286952e1ccb524015cd18dac24fa7b375c6cad7f964a17c2fbbae6cde609f9cb7649b78cdf9995cdb778597c9e733f9649f7c2f5b9da9b0bc9467ea340e5c2edfeef2c8523461a7cccab09b64c2f1ea84955f7421bee6bd682c272636ef5103a555ea175ddbd7b3ef6f4e4c4c4c8c6597d32af5a3a0682ae17676dda4929de525cb5c97d059ee5dee093a67595905842603ef9a71ecbeb13319aff2fa64beca98ef65ab53a933a670825dd7e70a5d325b66bc7cb233ccb2d9395ba7bc6cdd670c6d6766bcba7c2f9b1c61c25d974a7639439fcf25749d6168cb8a28113b6767eb5c5d985d59e5f36d992c893a26db269fccb68559a8d2753a63be9795a57374c924d45d3e93afbbc24c99293365592a37f74cbaecd24dc231b47dd757b9aead9c5cb36de5776699b133998c933053e67bd9bf40c0bebce73c384f633e2accbe2496d0249465ceefbabeccd8c954b62d5d5c53f93a99afdcc26e0b9d5de8f2c9477dd925dcf21943d7a5d36597edeb6ce1e83c38e74901a5d340b69d7b6b325d964dae6bf219c74c794e3af95e36503a95d9d5adc99cd7956d9fca769d9fc9a5cce47ba5d524dbd654265966bcb6492553e92add6554faf7cca3b62c3ba2d9be4b16fab2adcb6c61a8337ef2bd2ca0740a75bfe8427cc1826262cf7910503a5513133b131363bedde5b910d14ccaeebc9ce33986cab1b28d61be9785cfd8e0e4ba3297f3f2c984b6ed9399141313134b2aa7d5c0c0b5b67dd71666b2ebba6499ca95655f1776cab133292ba1f19b9467e52c857eadade05f20605fab04148c26ab80d016219af2cc74c2cee5fc8495f39a7cce7c2f5b259ca3ee175d882f3131b1e95ced9ba37d6d62625331b1ea137ebbcb1b546bba30fb8c5fa8ec32d9e713863aa15029b3add99c593839c3ccd785d9e4fa6ca1694d26bc3e9d4be7fab2b1dc26d7e4920dada95c9fcc9639b74b670c7d2e9f32dfcbe62559965db2cf79300977d69c93c924bb9463e8f3d92695f1caf7b28554aaf44fc92e9764664d9865b6f1ea9cd764cb26e7d6c9f7b2792dbbac0242934b10cd3639b32d3386d7799e9f32abe47bd9ea1406f1a1999ce1a5bc54b6cf24ab5c63e6cbf7b2792f5cd67457786d5937392f9f4a25bcca7c2f0bb3af8726ebb62edb266578863ee7b78d5bb2e61b27619829b350a5129a7c3a67be979d56a91d9af00cc3cf96c9b64f1676aeedcbac1b6bb62ebcbaf20aaff3cbce4e65cb6cba3133f99c95ced6653a63a6d2c9f7b27c54c1c0bca914ba64dbe0e6dc2ad765f27d9d4a799ee118caf7b2d3be698b959dab7d531326aa82805f6a725fabf2ed2ecfc40b335f97b9b2ebab5cd75509afcc65fc26d9a4cbbeadebce4fa553c9f7bae8a30a7ed1b57de545fbf202a55379d94eab81c9792a7dba6f777974cb26bbb2ca179a9c97d0e5d319bf2edfcb4ee7a8b2e92a5d59a9846326738dd7559e676a9e3c13ee29d92fba10737262628052391a4fc55ce6db5ddeef709bcff6392fddd6e954c6b2fc7442f95ed665269b505719c350269c9c93cb151ab77c2f4b8d020afe11b2ecb26dbe32fc84baeeab7cd77976be4fbe97750a529949b6c9caf2d2f93a6196193f992f14e67bd96a9f136ed7a63bbb2fb49597b1ecba4bd89df95e76a96ca973cc64e12a544a75a9739c7cbbcb2be3d07c5bb785caeb2acbf0ba26932edfcb5601a1c92fba105f62625540a898d83c953ea9f1d7da0a7e8989c9f11c7fd1b57de5c1eedb5d9e9b5893e94ccaeebb4293ceb54dc22ccbf7b279723496ca6c3b7dbfe8427c997da17dd17dd1b57d3de7122d6239e6893026cb8457985ddbd785936e927593ad18e0e0df9f5833b974ce4ce8fa94a16c9229cf50be976d219deeb1ecab7cbbcb1bb121ef49159ce6e5756960e7c1f92f8f30068c90614ffa97b717eddbdb93fe6148e6fdf5f9ad172c58b850e102d8862f0b14324c582560f0f28a30010220840753693576e0206fa96c3334b0d04565c0a0957671655820c7f3b44b018404d5798fc1164b7580ec0304945ed06a276435c07280c05d3e3840286d518560c02f7e3e67bf024b65eb45a065f3dad92ff61ac04eb862616855f08100366fe6cb7310c002809682551e5815a0f4f9ee362f2f8ff55b2adbc0e74cdda0f32e3c9b9737e7e55509670aee921253f4e867c0385a25b6288903022e28f18e24b43333101fca3c90751863c2ef52e9265b76e52016b601c3850a605f142648f08a00e18183065d0cb8162870afca8a0ad2e3514948a2a69da75b0d506f1823bb2e0363d6c26071d1d8c860c5621d0cd4c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7548f8f8f8feeeeeeee8f8f8f8f8b7fee6cd1e46ce01e1f1f1fdddd1f1f1f1f1f1f1f1fd94c72f48265c1131c9fd2e49173ea0946e2d3047168ac2f6e2f00c4bcc3caf03ce359e0eef2a88db348936a2bd243c69df898b4fd9851f00708295d0210ab27a4498a7355ed1f43e270bf0d88be04ba3bba0b4e0dff1413d13ffa10781d3baafc0cad452e6946a317a1d27b4f82fc68061406381f1d470ea48a9227e374769f4b511e4c13937d280ae217a8e26d26a7d61e8ba4a40f61b4e4839c8aea2019fefc825a8a2d4685d0af9e78e93f83da8d7c9af22718d4b997137c7acd2730de8668cd675a61e0e1bc2dea196f8a38900f79bad195fa5a06e907b88af101d404d0a9b4f8f8202f9336a2169a7cdd9145fb0c401fc5804e6b9863f41804e4f01d8b87be2bc7042fe002d05f1959e0469858b91e76c6ebf1b0e44e2f50d74e52f82650551fdb62c681603ae2a6eef6fc88c4340faca0e119e11c7e0eb4b5bf62e4a2c1d40a7da84716f619ece3035d001b71cf941366d5783a92463d1c0913348d0c8bbe8fd51d971046c0eb0d52b1656ce179417d146c1fa9107c13e6a39b8d187f8c43246f8269f016beef2378c1f3443c197a4855d45711264d3b6d0078345ab4276500fe8e3c1adb090dd901512ab3612f841e1393f1194482e4394299d14ace0adf0590475e88ccfc4a1e69d1599e1cfe928cc6578c52cab72ecd692f451bbc85974f7ad1400c873184f2222a564734f54f2433c505d7083e2049ac9f42b6f90e16f038830d633f8686a12b51f4c7aba3dc5e4f852dba9520e6b9a45af4e10d3c0ec767f918ccb69c4e8cedffc011f4839a68f22eb7a723ba60fe46e5cd1fd8524a2321b3c60395b8f1640c817c1b2c61de04f6f232434dfa0322a28b3aa5f7196c187a1d8652bb4c8c197703634f130649e172141d9bcee7bcc709e62f377972bd30963c04a31ab7b220b9b7a25eaee805950f9523ccdf34a669a51905873036eaa3d09d39982ced56d6249f2fca12dd4903134f7248cca75314dd13a2b677c6fd782c475f76dbd991afd267cefb29c4c3b7442ae182756dbe2dae82970282f52318dbf82637b8df246660c36d59f4108e18fc14a0f92b9d803f4d16040f210985cff270ff7bad5fadc07a1d69edb3a88bf47f1990ae09717d36cd4c9a072745374300eddd48d2f468277e3893bd280f612ee14506157a5a8d78bbd8c2f748506e1e83901ade062ad1e574b92ea4c7d5063509868bf5b0da8cd4297ec04c70832052e611caaa9b8a8711df56c5d157696bddc3999c5dd686c6df447a3f076cd47f756af33f3a18fa073769cfe001a9d71029cafba9d47e15c434fb8b16ec2f48e5d14212097a24174bdf3983ba1a2118df236dd1b3c400f56a6aa9fcce1b86fdb846cf8120befb6e9bf82f2e80be8e2be6f39e193fc34f8e6f2582db90d04cfa4c5bd6341b28e9d9980174bf059b5cd3a3215a8be0296fb283c86bd959f4644ce6680c4156775447c3cf792be0560ca23ca42a6a5eabc0937d64109a87851af42b73b69e00830bfacbd28fcfdb509d88c5e69d4ce8e26495e4789c463d3a5359f2916390e80cd5364f264669c75833c8c718233c2439405e07a1d7ae0373732e9710355698343f070e16dda7400d7f468af4a5d0c0703d61c6f61a18ab67a9229e11aad8119f5c1b55863c2f47c6909d490f06575ae8f48dd2dcfc102376bacccebd09f6612bf90373292933dff244f4317a167ca866826ffeb9d16c2cdcbc4b05a52bb0597431af1eba31cbcac7383ebeb630e467bc1b8f224e888fa154c0ff48217a4a65145c0e33f1c1daf0790d1d0abe4563b309c9c17232779ff4073188bc51b07d091c38fd5888151b4587464f65d4a3c76f1dfe00a9329fb426ca4f21a3461b6a63e614380dea403e0afd509ac2afc097c45960a1a4351cf9431121db143e40f80b9274e80d447a78861b835e0adce86dd390a68446882b88d3635f69f6d5beb01e52181207d065c4db0580e4678ed2f69e18187fc1d5b82016b75766d0b28518d1e48d166dd898e806f99ae3129da46be352fe04f01041c278fca8833fd0cae185b83aec4de5e15f85a8342028aa2f2168e6a344a17918879074991e261e879ea06f075df03a557af61d9b3b9732a8e2a998ef47f09a7ea6c594afc8b0ee3fbb2eef8bc0c56dc02c1cc918acf724a5e91542d9d155a206ffcba5014e0a49924f1622fe824d15be81a40adbc0853bcf94f1e7a7a61a9e112a3cdd49021647347cd46e715ddcc2b382f3e950e84bc270f14408563e81ce87d77810df6d0c4ef75082f14889987ccb8f1c7fe70d8a3e5376c635a8781d00d1140fa488d595942b1e4cab4cdf0955f662dcaaff61d4a08fa509e090ea163fd1a24e3a4ad5d407aa0dfa4d9628fd913808f48b37e2322ae5f02fa0063c5fde95f7b9f3e3e91c83b80d0b00be1010d81f6eb93f8289be1b1b9cbc0c88a17f1293c70961aaa2b194d2f33472106a4fad299f5688a1ab5d765f236c8736e2e1f13d01801703888d5f30206a43c9e0744667dc4da9028dff7280d1cfec91e003e650f1222be23cb08cc65379b2f01c8c087ddc27e2c71cad7e9a26cb3bba51f18d1f903c03a7a0ee90c7740f3e2879528315efb18384f3b8b2c20b298969344be08f92c6e8092d8e7a3c84b2b8a03104effa08dc93da80f80109b1de4be5e595b479e29ab400f93f21486d405d403cd3853719098e9e0460fc7fdc0eb9d693049bcc15169f42c8e86a454afd27486c7b93a1880fb026d013909af310b238d1aee7c54f0203f285d6517fc7658f77095ae030ec323d29292bbc500e9c777ab1f0c345411f2472e7e12cdad987e4a2eec0cdfe44680b77ea61d8600a167d8e89a5f94c88f05e185e6c36c8479fa64911dda9098c9714688ff7f834c00bd5bcfe8639e4652c5ffc29322b3ccf22c19df594e27fc470f8282a32ef9a81d2d52d440fc446890fd601f0155a4cf00860c91f2224c0dfa14ae26e73bab411bf189e94f93c8743500e640bd69dd8bc791d77ca2f6e18e113da006e1c91d47c9b0057768b4d8e9cd25f04972b30c41dc3acbc91c5fba0c212fa8e130c4e630400e77418f656da08d141387c7d1c33547e754ce1a388043adc9317afc7d0014d08678c03a004613b2729f218c6de53ffacf05471caddc08214cf9084aaa5671fbeebc48967e129d07701e4f86c925ddc4d1371170941c5f32c8af91475671ececfcdb17658f81c869f7e528d1e3e6708a7d7c8017a451f4e36832b433f0010f5dfe0367c52aaf85554980e7de4e165305af2073634f99f235e3e8c8038ae46129b77257e3a6bc59a33b872f24ce6c5a74b42a88b5c52fcaa1e25b4061d8eefa7c4c706934482a7b821f80d40351d451501ff12b8c5f5d07d6d974c99b722d1e51d78cdf1218956fc881f7ace2853759f1c361ec09b612f72a0f20fecc4b4a3d59cdf03e6ed875458f18a4544b9162a87dcecca8c86ab91c01dd869b17728c0e129c8083e92366d1caa03c8930d78f48ab8cc741228505eb0419c464207e0190fd1e90010383d8507859fe08c0867032395cbc044e563778486b078c107f070a35d4880ce5649852e92e3c8d3e9c31d67f5f22d9d4d4f15c2e2cbb490d84b90cc1ffc4ba3c744cae1d10c78fc8524497f2678a6133d95720a4bc6fed1c9c7f14660b93709f004229979261cc2f8842d4f5e8aa13fe77248ca866a72e162e414ea387106b89a4075cf63c2df43f1aad378063f7d1549a27eaf47996b6541da7055f0477501f16c762ab8045379ba439dbc1784dcfa30364affa882ee9b4d967faa4a214ddd377cc99fe413f1a4c3377d71b11d9d017c298c2ce8c61972cea99193f6e2c6d3e710aca40169f4f0c5301cef56087344a9989e4468cebb48b1f308817b5f05e267031105e125143973233d347d800e558e486990a3913ada18eababc0b10175a8d233a9eaa6c7053b9c29cc357aad77336754e8aa49e4c5fa77f9228e6f5b0307a3c73a6b6242b2e5c8cdd98472a62f56f1c553d83ea9b2f72c0b081504273236c9d740d1f609fa790eb2d05c2ff5204b4452d177fede2f3224efd399a0d4a171213f5837a34da9e1cb8137844612f86b0f13a6e04715161d1cf90248b8e1280924f0131ea3d213a7e8ab2d4bba013f66110f2e833321b5ee1ad4ecff061c5ad324cd207e44cb80a4450361f17c2ffd0baba7ae9cffff852b01f04ee475ad0a3cf2ca0e1405c08700e1f2cbcdb9e258f47419607b123f338480c1cc129177b4b8914fff232f11ba8e4f932751cdd0b0bc64b3190c5a1299ab8922f033e4318c1ef4166c9c70892e0d7a82dd25132559ea5534a17b1f0e6a6b4f8f0186008ff920738ed6b82efc788e72ab0ae3c8d19c327da10e543ad01fcbe3eaf4faaf2453b6221e47dda1e780c17d2bb9d80ecc5050d9e9002af77806ce148b25268ba176c0f84eec276a7d0bd1b24921ed056f42c8334db4f93312e620789fd4c18bd8bb7197f224720ffdde78dd099fd87228174054351fe07a23b9fc161d45f7d2df12b8c72cf15484fe30905c30d49987a2b5919dccf1f4c3ea748c83301e2c4376d18f3900c08be2119ef6f297bf48ad678f1449ecaec297a44de041e473ea92cd1f714c5a6a445f872cd2ddec94802dfa204ed1d5350fa249f0b9f4a0e228f43c6884b7924e62f34137c120a91be4ea7169e1548c22f32936597d179f48dc0dc38a5401abec905cf8b2df8f36e4910fd4fdb06577ca4ff9de1f822fc7cd8807d5b3cb0818b97a4e2d00fb9d2b38314187ba710e53f8461f1b7c43d1b14080c4e28cc9d9704278fc3415bec40056d5ea5ab8156d158e6e500657f6835c609cc7f3e58a3ce6fd138b417d838f537fe9ced1d1b02fd0ebda4b6506a8fbb31a2c31d20ea390c4c18fe8d20b04775e66d1f22f3e09dc47835125ee045b64cda8f8b777ea5e6e9796860e3cd0731b6a31c823e9158904d6d23e0bb7c22b3974c09fc1fcd27cec3d0eac92471b4f71e4677c1c3f9479254f0497aa89ed181355ff782d23b90c7fc9448371cc016f44bf880f80dab009e64d281efcbd0e77e64825eecd2265790167d519b60b81a2d389b4ad48e2b4e9dfb0aa8020f44c899f6a0e6eee9d212f5a115775e4c140b8e056fc790f7f4ba4c5fbcd985c136d381f4001794ff2522eb072141743b2d9c57fad3664f3b21f9005589b6110667de46c175167f261e8e1d0deee5aef18fb0993e9f2f699c6a0095bb66633e54a0223a4597afe704488b9b82b39fb003a0fb3863c8c9b4d06c2715389e640f9957b9dae46c1c08d07308f4de4f8d146fc54285d3184bf31374716f4a8bd013e0b0e6bb74e5e90f98d01ec40a43db4d9e16eea30da5973aa1f25b529a8dc44c936f03f3e7814c1d3901071cb6dc9920cfc370d01fca2b7b418586f40bb4508ed5a3d246400a84ff20c3a7cb48a2f3b52f40b61407dc83e1cbf4d1091e3e019f020fd608cd8dc039d9360cc3bc0c4219368e30b2570decf05402f6b8544a2a8de7efca0322054a675161e68b1c176c1d97723c803cefcf4d51f499be5278804c509783fab999e67f1a17e0ee41c1cb1bc9d3403f295972367f56ec3f4407cf05058b6fc2c4f8238ed8f90069966f8a44c5497118f17f9b0cb71b38c2474185c5c75812eaffb4f9b1ff2af8c7183bf3837ea6dc009237cffb217b8821507c0600106fc9019ead639191ebf1a44547e273e1803502bcdd9f0ccf0608d34bd04be53116b079a13989bf71c8a39356a1dcdda148eb3003ead79ce9ed4d775aded3568f9daac0daff707366a7a944e7f954856c228553fc52111ede650ad02d5881bd1b221f3c540949ce61480957c167ccd738faf08b4d289ac4571eaf9bbbec2f26b0bc6c02dcd6120a38140a72bbba22f1275101a5b5ee3cfc20111b7492423dff66c1fa61ce7078b22e41fea9d4e20b7181e23b392678023cd2f4010d8d1f8909751f2145f65860e76e5104c43f17d9b4a18c447f269392bde9ece97152535fd7f6e2cbb4aef5901af234d4b8fc29ba137e430b0e3f84e4c23f792368cf4963e33d19cab4039888a87450cc859116c4942106004090754303802401e312004048281c8c05e3e168481636ed031400044e8080c042994ba4d134c67110841031c4000380210418409099235b056700f75368ca0f3fa9c6e5252b0d2a9572127ebf967022fe21c25aa118d097ba678afdc727aa2fc0c4eac6e8ebe8d19247f1e0eef2fd252aab891c2881f9444857e5d4427c6f83b32115f43bb99071208d40063e4ce0dc323fe6d054b4bd558af163fc3364507347bc705a5a3c25a322013d7927a0556c9cbebf1b910ce3a2a5423b28604706916eeb14109b87892bb05d60804144fe24de39b96d5f63e5e158031fcd7a4f87671a650208cde085df6bf42fda5156bcab84db86a047558fa75a5dc6bc7654be54abaf8267e4ba731cf030f7cd8c74e313bfb71f2a1c99205c61a853f71778f210a2523db1a10e35735cf89d23ea40760466baf2ce54fcee8f14ca14a1875569b53a36b7bc78b9e4bde653b590d7e9c68a9cc0660cfa1acd5b29c6bbe18590317afe76ab96c10de01c34ebd509244120c0c0d6f779971e6a045fcfdd2f66d9e6e6526d4eb1f1276f9277949057d40c78d8af40a57d4b5723a704d1fdd626f8a2b3ffe9b6bc3f2671d40fb8f4f57c86e63f39a49e1a8979eeaa9675eac00fa58ab56303505eeb6a6613cca02b34f0f1ad149d6fd1c58f5ae2fac7b9ee4783a7b662f9b9da755c29fdd550601aebdf39bdbe024eb6f4a78a745b28d62cce693f8fc268ce93dbe0f927427b1f9bd947bed243b8db8fdc93ab6d084574f5734b13438960354650215d6c4508d2838c27c4966ca39779027f5b50b65209bfae9baf19201454c4984537deca969b238b7f024d7dc2f88a8bf817556bebaf740e1e56e5cea08d8644bdd3fbaf91e16dca9f61c871bddef9061cdb2737e6d7702b6e0cfdf07c009ddf80d6b77e3385c1f5cd6b20903cd0828d9bd8a5d58758948b9b7499042d23968f361b0c40d1e40d83434f9c1131b5c415e30427e707123e4b8cbea6e83bbb3a20708a3c2955a40bc06181d684fca3235efb968bffeba93cbf934ce4b2e7900d1bb9e1dd2e4db60dec7b8ca16b3a6c598bfb8cf02fdac987d790b646f1365bccd691cc1e7d171cd03a724c048598c520386c6c8e9b753443f0b03b9bb8c4c9307ac78de37d3a86709e1e6ea5a48b2ec78c41c5008f9e868cbcbfc3ad677f834ddbb31706fdaa10d7490172c0e64c0fbceb47a79eb82a43c75984a2a88e4b8d215a975a41b2a2bc792ae23d2acccc2f7c27c19598b07224fd1676f2ab3c21bc5286adaa646082621b1d0c7dbcea9f1f7c184ef797d0f653243cce07870605467e98cebc6bd118b65da1e3384d6770be1160f7547a12d699eeb89fb2068e26046b9f68f65c0181d684beb717f87b853e185d3d2559f2f70e362bce793b6e686b524b267183d8e41451f04831f35a06aba2964b41d4a3c2b3be855d756b45cdaf610139e03e9d131990cd8b596445dd37e88b19f337fd7d9424b4ce110c17fc2800fa5f4d2f7101810208f9687a3125053dc4662294963a021a4150504f6a1452d9908f43404cc82c0096b67c529c076e250812ea2b6e64a7a0da27d92261c0c02a4a135f0732dff58a980863c8ed23a00b0140d6bf0becb1d19914a5c6c602ca9b14f399a70b94c38de06a33b35ee5b83011331ffff775876c2a374f092918f3c19a278f9ec0c54ac86bdf8b18522368f8e4355223e660bf5912cd5610c00977553466e9765fa85f8a6d207708921a865c868b89ec097d9cd1de9f8255f01cce1a70474f6b15d271751e25f654277edfca1869943776eb94e20ff066d3f06b83966dffe6d94b9282849283d86351a80cfddbbb8e68ada57174eb0e662151f502161fc5bea76ffcd5fcf6c75117d9e3e76620c43ae42934a5950e1ef129191a930d5e36f9f18b12de5fa48b54980d9dd351abc9386b45b16a705a1ac427844b1cded3471e1703ec99195a357797479ed0d4525552d69209fd6197341ba8abdc74f4f03f5d87dcaa93403793686ccd60722cd2a9a5378be4fcb0142e2769844c516117ca66c61dbcba59c3dadf8d1e21d1644548ada602a1ad728695f9d54a83a53c04ef37c5ad552b268ae43a8020104c7802fb179ba886b170b562616549a9e6efc9044ec4e3062f40901253bbf4c3a55a3a901c0c9b64ea336c7160471caa4c11ed470abf9d6013b1c56cf31ae91837634d5ae32b37a498a963a9853b04484af70550c6b60e47bcffe1c5dc3c429ef8abcba494c5d1d55a5b7bd27786f625a97d85d4eec2c03a486957e13ede5978a5b41553f9930773004443caf03a35a514e22eb9954ac93478ab4c43eeeaf512733287bd56e01999ca23ab0d3984ab91f17f7f1fbe9d9eee6329e23cb4c388d11ad598f268a1b62638a71bcce7d075d9c0d1f3c5defd4ba6f9fb8147b88534683558c43e96e49210b74e928684a25433b66b0cf4a69479919a5ff0bc350e3606444ed449cabaeb784a895e5eea3fde504df1208d32e169d357e71447d456d1ce53563d0c22c815a66e236e6aac6cd08c38e90b518b29321f7a411ee2a3408969009210940f38f5756c10a7c87144b3005da7c20ba8173bfc87bc200650279da1c73fe1b4d2584c636a527090a3e0f11fe2e333b29a28043fc21f7c085f86507116a9051bd34819f728b556f34d8e778208b0e3639b0f7b04e12dc987df85ff665b2a789d53855f2644d07c25ee904ef9982fe695a43a4b0118122126a5dbee010a11c20150f0d05e7a4b363a8f98485af380d7d78f0d88101620324075a5f3c758c2a0e15e7746992c85e940b34056d38c5025d1f09518ed448f266699fae4c7c38b8fdb34371cffd39c4ca815aaa78abcd96a6e0dedb7a5812aaa7c29859a934537f5100451e1c0bcf41fb8b210c4ab6f769b8da8e2c9c9f643fc93a5536e29a366e0c60148c16fd334b21d2d56c146d102fcc1d144e2d44342c4e0efd50def43179efb43bb0b47eb5d9818446a8f4f48eb4fef06650ed7157a6e409f1138836122cb36e979c008837e4e0aa8b9c71f299506152acd32c7f4f636ae39440ac20cb94fbfa6b4a50052283e651fbd687cc5b76888fe226c65362d3dac6fd173b4bf85f4e00bead9eb84a2929003739529be5173a5df65c184086c3e5375292138fd12cb00a5b926c9be1bfd1c0831d493f66db0c4d6c050e1aecc4d3937cdf285713d88e62308e0b429a2525076943577a3eef511ce89b4aa4f745c929d085a10bac4a35bdc6835b973682577728f5c6974a4c5cd383b21e70b8c8c2c076ea3ab2ac996b29150b3d5b30a1b3909fe906cc37237dee20f85c98138426246833954cb6236033df533012b558b75b06e0f615f1a63d46854525dba7aaa292dfb8a96705fcbcd9d24ad7a01d137708f1d226702b98bdbb08c19ade0fda4e52529d54a711017fdda315698144304a0189fe36975f3c5aefb87fec83614dc53cfbaeecd18e54a127f532446b1a44e7f9754b128e921570711ecd06527ed6af9569d2f8de0230fe58e153557b3fd9668a3fb16808d4cbc424987d5e931c5b381ba9e92e59220c3fad18065a2bcd1bec104c529c423c551e1852a7e05045417c8a30afc5dd2d41494d3cc609e5d39f1bc893b9aa56aed6c2794a981e40ef8b3e861c7511249b5516392443c1954b818ea7927059105278433f2e4c715145910fbd1773e3b321ef4b98a3568fc6fca1f8504391ff033635b9c2b78599233105866858a0cdc6c0fa7cefb2fe95d9d6c5cc1b32c3f5449e2377fc12cc43321d2d53186a8c23d4997ef7174e25f735d0df7bbf74f81945a5eac76bd66ec815b5acb12ce328cb275a2bc82d85595d11741ce3f6938e8fe1cb35b33d3dc5ac3fdcc18078262953e39558145ccd1008423707085111cc6f789d3d82bc83b5cd33ed9f53de2529b3c02a45ab8cbd40b4868c732458a3c7558bc2f00d0819800e2b4acd753a5fd00a06e0ac0ecff5d2d5bd464f227450658ff0a4ec7b068f069661f40694c981d09855021116e0b8c562c51ae6d30e4390a472ae18f4a1d31007d36684bf337a792a1c94978b0f2f845c2d66f9f6b09d73afe34ad911d7181ca146098064188f52f18deaf4ef302a22f78ede3ff5c02ef9b87f033bfe1024a0ca548d80a67ae0644251126c7b8c34384b1f8af717948d4cbe29a8ddff1ba7b2a89b994f3f71aa2343780f0d43aed246271c9f1fabf0f6d6b5696364261fc0bf5202dee7c6133b44f294802a6e6a104c9a3cbbda52ad4b86aaf688559d1b7ca698670d86affd38cc6c9a2aab4e9f1139e359dfe2b6778908823eb1029d647362499318bcef73886154e0132296df54424746f49ff07d70b33e9d4443ad8760e76931ba68ea509eac3b1d7533eb0e426a5d3c5cd041b30a0be55bee760466cfc8aa0ba4b84d0d4168f411b3891e3153345f8ce68d7e35d8472f741f6b8b41e1d7226498be3e8489c9817d78191d3b3061163e6a32c55564acc82b9b0ce4e6ac8eef11dee20e4dae6406a08b49c984ad28168d476bacbbbc46b0a8bf2eda942bc1e2c63ed7316fdd69d9d99ede895cf3415f00b4ca6fb3ae27b3bdf71c027937e6405a0510b44fe0502d0bb2cd0509f8cfbaf837787ed1d7fd7b3b53036fbdc766faa5bd57470e41647b379e0ebe22e8c4836dc47f1d5ad079571bceac9e9dd8d10d4848bdaa589317066bd53f8c5e55265d091618fb255b5e1cdaa5f061272dbc17b9317bb08472ee0c03a94c400e3ddce296b4ec76440c817b1f78df0827697398e54f7117464a5251731e8a3cd653230ae9355fc72fa61f3ca81ee8aa3b89943ba41718b6270d71a047336693e9553aa820a990d39d4f65ea86e158451b009974391ee1a2ddbc2a424c9938fe4682476606656de266d11b45f399be487105ffb7d03ee08285dd7361042344cbb1d6692fb1006d7ae27b18d01dce7495d741212b94c4677fa8c10d3c864a7916e9cdc713130399c49162801e1c55bd26bab05802002a50118a328568cfdd02f030fe037db507e9c2a2812eb311edbe1ac407dde3bebc4edfd824784e6b49bc87a35b1a131f1884e510eac208297e6f23eecffe28ea61480ba8940891ef9cb0b53d440ec6675f26e76eed8ff61aaa4ac592fc1547fdacce8d1f3a7ec29601febc0cf2ca1b582deb00c5271a06b86278dd0a16f8cc9bfc92cab8ef4924d49e53782dd94bf64586a4d655cc827ddfb0e234784c2e617e15ea9ab38357f6e714e9906a0f91be0b8544b1b15a76ff7569f64ee324d06fe5e09e65ba202a7be0064b1e36fa534419375f0067e068ec2ceacb08e01569b9f16a53fbb2646e3025163498aaf196952937ba294f834a706d52cec77f15c451a3ce45cd08730303f64a7c8f9d2aa7244c22dfb6e5a3431d44e4af6f4ec591990cc2dc4e96944c440a0111e25a5c00ad0a14b773c83521e86fe316bd9dc29b3f86aa602bc8826bf7b923ebe2987b4b2ef4ce2ba997777e3a4024e7f3747c2da7b80362f17df49b38b5b507e88db754048359894674ba0a15652f03449587cbed4b194f3d337db4ec3142b3621d89f158df71e30eafb395dd40dcc416e8363be4bddc0ab384165833f102e0c4fa9e9e83901b2ff83d84ec125733a77f94e91300fb633ea3c9f9dada10f00647af963d32e696eb19d40a1af0196388e9271716461fca6614f9856ea00fd98a6ce606c436cfe5271d87813940c316d1faf70fe717ee1b5278dc27399b83d36238e209886924cc093b57c62fcceef85e4e0562094e0ba17eac8afa83c8f622d9af27695575d30287e7b21f6e2f607087924687a4fbe020329cdd07d835df373cfc4f3315d0048a8c7349b8620883158804fe718d7d6bbbbc08481bf49ab3af8d5a84e5b32c852cd1b521758e4812265bd2267eaba6fde12ce21e2a3d433e994e7c5bb911898cd83ce4c197f64e037128c1066f93adecd1effa7b1226f79fe0d409b0afa9cdf0dec5ad67f13dd9b1696accedbc43f94ebe4c75cc12831e2a21df5ed70b8826abfeae1de660fc0982e5dd959163041a9bb0ab39fe294347eeee56d844e6069fc38a481751d25e402a34c7f6d8b6aeeeed0b9a79d4466d39bb65517d9fddee606910d3266f9a32da5af3d79e0ff1fc9d874e1c00d87659621710a0e3bc690d8a34e247afae7976eb1d9244c4f994cceb71a2a29668d7732b3ea44ac5f9a938189e4d4a86d9c51fe2152d21eba198b5d84f92e650914313ca0f70fd48f0038c4ff7e82d58917927434553801a8c4a4173613ed77d04acb02c2f1410f36eedaf881bb6f42892743c8feaa714dde50ef5057280a89c08f8e137813fad640e03e1791aec93f0157f2adb43fb2f9c2240458d58c90179c256d0bec94879b02e89c6b1b3eab7b86324864217385bd8d8180acc16d03aa1bf6a54cf07b02cc9fbf21175732e958a6ef5172e097f99da8d4f4486067f07a08fca2ade20defdcd3e0844fed241987e32e529294bfc75fa7c10d1e10a9007c37416b4766f58988ff3e049466b06088f204867a0f719b157cc4bf841d0bac7891e94ba168e3dfe3bead167aed1057bb0f5b50fe83c82833f58137ddb0290d4fb30792a87202b510c4efa7cce450dc98cf09189118f63e793738bb583ebbe66e2052fda7d3f442fe33b343d4f7bb76c84fb99e0db2906f7c3c5ef0b8170f9743955dd9f13b38d801beef4078d516c99ca2f12e8517ee65f79ba0ebe8f6469850cc95cc61dae743fb9da3ae3be957ece1fcc88c4b3e1ddac3851ec5db23332317bba94d71bbf96189d8d7489ec6b6818f4cc2a4fb7d692eff9df12f86a970b7c4b7aebe97d35739e0a99a196adbe7fee83e33e66aff01e178f6845c9b547957f0521fe6bc44c2f659f7b7b0339bc524a6e9fcaf48cff52ae48dde04b8ed11b092620202c243a8602b6c0a2ce323670db8ff49ef8c411289d0adf6f3e051edde847be34c59bf092b5ff2980b17a7e5ee3a5108c6da72ce8ca8116f9d6ceca3d0c123120ade55bdb6ef506db44651f6063a2fc20a3e3920515d6e73ab34812e51d1c9b32b5b7cc5cd33106e44b222e16b78d663d3f221956b2afa3fb44e4251233baa77ec1edd41ace337b79145ea88a8616946fb2a0448d7c1c600a5b0628094494029b49aa8f12d31cab987bbab2ea8552cedd9056a6515bbe5b44a41172439f5336997d14baf68b5e7dd1e8e35ec7c0a27f21dfee8bd90863e85f4ee67f427d649ff3c06afb0fa77800bc1136882c6249827ff2e95ce3dc9557477ae0e52c34b585db35ee4d5a9cdd3a9807418f6e09d96310dbb4f57cff88a1e20b2f3931086dfa2feb071e259a511a851f47285f01b24fd9b2d92df52a5ec9c69824d9f63318ecc17d5f8b78e7e38a4804a0f33d5285563a4ba5e088e62735f649c6d9ff03c9468f61fbaa2b0d86d2fffa535fe139e33f5ca9733f67d8d3ffa04ee157ef0039fc2b5f2a424783c4560686f58ee5c14d04691ca10b6cf767f80bc597996aa9d064790542b85dd96ab6794e416f902f45d92d49f202b5c528a27acdfd5fd0ce7bfca6febb3d1c70f9bb8b38846bc02bc1be17eb7fc87bfb9560d1759900cb765784d4ba81c1eb979826f1642d83b1088c7484a14e5be9e62d3d2a297a4077cd7f03e024ffeaf2f765d49fc89fe55bc632b0bf6742cc423aa09227accfcff82f9f3090039be185ad1f91394d1753380b8a170b2e757949f83b523a0c640f176d87c2487332562afe3e7e813555d5f6b389fa1da1d67c5be484e26d31d519060e25b0c4111ad9c0ed9f0bf9ca403bffca56b7e6bdd45ad9d89395cba4ce876bf98b167cf6f9bfa56f3141fe30ce9999f2b24e40ce7cba432d11b79aeccd23b4436a9f3b84e90cfeec323d86fe3cf3d6a451a7936c9f725a3c21884cceaf4f4099d5d134f4c06c98b22a8a879c67aaf922acfc4aeeca6d801cc07d8167d0632f9d5ae7053cf39fd56cf943359fac5914dc369779bebd50e7f1c21d70325dc8c21b28c6f9a66e83fd042e4796d5d361309a4e5b3a2ae2391c82907bc4a5e4b71abfac3baecce17e723d31cc53904c56258aaf0c42d959ea1da619d7c67b0e115187ad4821338c6df5ef97d6f7bd490b33dc54dad8b1d9544442c163e3420b85e3724713b445de262212d78a2f84511100c7d22bc83134b0d9e709d747a6cd0654c8e3443ae911e4fd6632b25e97fc84748477b74793c55d6d92f68a4338da946b0f9ea692408099027fcec70396982fee43eed6e02ae9dec6d3254a848c226aa373d6ed17fe45b1890fc148baeca58a4f570faf7a3f93e84a9d443554483bcd0f64a85f513680c8c1bcb0211a9a5263d79fd404faf85b1d8db250f2ac66cf5ba89384da099d0c65dd8f19d4849ef6c7efa90cc21e2f1358a4680eb24a976404cf85c25c2a4f1c4609288084eef11d1123ca978a62bfb01d413b2bbfb6f49daa22f504211e65f3e520318084e159d9c32c25ce0ed2371283ef50eb243cd3da07e07f17160cb71502d07a8fede695d891a2d54e2f4c9643c1f24e30b740b3e8bf30e499d294eb3aa7df377931b4903d7fbd0c052fc8e1a922bc0f126d0283979de969ba072bb5212f0d1d2fa6596170636f77bac1c3e6dc25c79909363c5cd0247c5da8f36a2582453539713ad8cb1ebe60503cc9b04387a7029143032e9386d9db16c2cbc2bf4e590b2f2f62bb1adb6c2df9ac06ad6bbb470bb0116d30c7d51e8517e4d51534f7451d4d33b823143de48e55a4c73018289dc4cf53213a9d51c8f52ac8643dfe3626a646e9de3dc972d62d3147d799adf1501c877f46892d1c79dcea0e9610e1c0952a33128858b692ca4ad2661f79becc9c2b649f003830fc815fd83b191b22784250fac7748e0ecd85938a099b98f447014b501ed0b6471646120ce6c0b5c1f58cfad67dce74535bcbec0933b4d125f4feb1a71f5ecac7a3ec465f68b83ea19b70bdc6e0a3e8df15309da4c1fe6a6fad6d8996d2a97f458a6e4fc2da3014ddccdfe5fb0c2f93691948358ddf9bcc90d0e90d7fc942a93c87c1e745aa67f3ae663bec9b3ff03dc61fdab8c3dbdec29bc8b25a4c6130751387358029d25ccb3a823a789efef815af50ca04f453c4748b96af9fecac914aa3273a17054f3a1a483143b7bbfebbc693477296b32c2ab3d142da774715caf07ba1bceccb68e290028241b6d782060f125cdf1b01dd6b6abdf27b4bce47ecdb573fb6fb669e6ffd790ff9d4d0a6e9656e7494fff423d57ee6f5d56566bd92463ffc0f3c777ee82ed8fd48b2a6d8090a3d636985fac4c3e6c577ebbe81c8cea336949c5c36a489ebf75ac436f9f59d718a7869ca396c10060aaf8900740f794b39206ea437e3acd3873d74cf5aaeb41676e453828675b5f676657866eb689859dc5a0d7e212f943527e15bd5f903801614f7cc3b07bcda909d3ac6328c079a00c53275fbd32c3705ee1123dbbea5e152fe73862fb03acba563c884c6c1837549b7ce88e33ed7fcf2ce8d3adcfad9e02b9024b33fb7fd227a51744bbf53a2ec2c4e1677f44004e2d49c849dadaf09458e52e1d7bfa79bacf3cb4953a550fbd7ecb8d6365a4e744376849804343d24d5f2f984946761162d31952442525d7f43955daf35e0c381c36a3c7775eb894bc428151b06d46d35ae66fba93fac0fd229ef7ea36be9a80b7821041147fded05fdc70c2e4cecdf8a12262d720234b3b8c76f0cf3ac61480a47f7fd92f7bfe28884f981fd478e48704ecb63cf95bd6fa1ae67e42cd7bbce67657a28e200476f44aa29524b916599dd10187faf039ab38c209d50e963591445e153019f7b116877b34a245dd0171e8cea00083b0b0858e5cef62f589949ee81c62de51505c82fd121e54355f52f07d53251a0241b29915cb18b86a362da2bcdd53116c000d4a2e5edcfd595548b541b58456167876142ff6b013350c866c7f25902539a33a7a6258642751d03812fb3e0c506e5c24f16d4365041e4431b354f6f8904a7a2242be9d139118382a465aba64d3a5926d01cd6a1e4e3012d0513af12d065e870f979f2d77e0f674db6edade65db8bedfbb5ddadbdaab61d6ad7417a83d8761f1aaade7c9588de35ac8e8504a332b2a92ee34155e6a604694f8e69517810543832a2431614e9997d11fab589700233153a9aaefc3a1652b8faa88cbab41d4d898305a47135ae45e1a9c996543a220a4ae331edd4dc506292b2d838645df868503af32ba59eb43e59a422934577d0e4575d468134c34153f6e7b5eef5b62bbc520ce09d6ce6a32638b201619bfb5ebc41e78ca5058eb8abc038ab485d733d7ccbd81751c08bd977f20090120ac932b5c9b38143e22b178f044f0dd4a28c9e70072e9e9ebdf4f1524299e0437165ce6e23842d07b13611d4f1fda577c5a9c061a2b9f3b862e83cc74d764aa02ec1a93d07b5711719924409a233bfbb6e5aaf0742a161eb1d09c5cc9f155c821d93583a705b26583b7a6ac114efd955b311b7b7ff324b2bd49c73ec141ebb41ddb6c74b522338433cd99db225d49a1851219a78132eb0e942807f850b343560aaf93c83d3945324a66b160252e58c83e60718afb34deaeea2f368d84c55610995cdd8927fb326051210e5248c3bb54b16ad3e1621561120d0c2c6b146d1d3ad58fa3e395013f1422a4b58eb25265ee1757d2fe853fadd7f7ed0cf8759b96f709fd8a7d23152ec148c88c0f49852d0fa090f3a3c2efe0c77960f5da753984e103ff32f6ded63d89ffe149c8af706353c7c0f7938062196400b33f3f96e3b53ac8b75c38cf81a1b667b51e9f4d5e5609933c5bf36043b950107cbc960e93ad42b21e56201ed6d13b797184782cb586fb6be1a95b389794a571ba76eb90358b66b9e499c3f6ce0a61617954f054e2adc4125d45da37b55bf3e4e5193fc32500afa029cc43cd5e179a33b1f2b82627b45070e8de853e0154e4cff2f2605c58f53a0f3ce3ee1d06d3b5c624ba7c24c6cc955431ea6adfd1848e9e40487ec3b23849f2bfa2c1ab06dc34229f775be49b9efb203920e5a3bfc88903f95c0be71ae19a9caba3d84c7fa8d8f9cb5ab9fc7c91cfcd83b23ee4cd988ce9c5bd7cf09c1db43bec8a81b624ac20703cab3430fd61688e4bec890d299e9278cd096831a3e33cdccf1666fd271911caddfa7a372669931d266078db64813e9de120977fc50d81c0fa8a9c332c12dbbea37aef753a82ef3152b22f2a0f68f28982f9cbc8ce418f607600914dc86d2a35a4957764da0bc0318a32688cc4000209698e4393cc1d71de489cd2f817f21536714c08ef47a896a2575e7317a9219b51c06e06d8eea7d8301bf6146affa89858aae4b2796213d0ce4a4779a7a8a7de482085fdaa7e307fa16c206a9370e5e77ee1a0be7a7df810149a5f58eda55d9efe32cd69823eae5b68fb3c6a61f3ef0ecd316b95f98e45e942a9025403ff310aeb567f01571418c44d0e03ef786be70a2e9ef0b1f25cc3ab81908d618c028241518c4a5dd23592b1ceaa7f24d3e0e7a8a83933d8fe89c8b38878b0a243300e1ef1dc940a0c833f50239398bea9b43c6cce296935fef10f79a1cce94d0195ba0a020cd798d3fdeecd79c8a3dfb4ad4266e21b1fa81329a33fbd9a3fd7ed44bfa96fb4283fd62a35689007ec77ef5c0ccc052077157bb822d0b54f2816d3bbc177d2202b97dee9ff6187c29fada2cf6363dda39132e3d9a04df8a4bfd1a1cbe7bf18e538ae60455e8e17d599eac63a1dedf74e5043769c480f0165bb79b386328da5482f8a134e12f8d35834baf3918c53ce498d0251872c0c51b74efb00428faaba396b4eeba412494d2e11c59a2b1594ae3b426c09d1ead760f4b11a2c0bc03025392ab5a6c9bbde1f0cc59f03597b6dad1a860a1ffbb2638b6608ee072ef8bb15d75168d40d29b99000137da004c7c27b077fca916dbc27c8b215345db23dafaf0afd2699360ce95df92d5d7bd2838e61d79c6ac46442b1cbc41a9d6dff1109b653341976c012ca7017ae21436e3db2989367c3e05df9c8b5bb94ed0b63df6e77fc4a9640a220f358a6630c21fe090bfc2d440fbf01de4e1e62e4793fc27666fca791fb45519c2252cd9e79c4cd924b93845be5da954d125b4149d361d37be4a96934233ae4c1a44d0699d877490f94319f9da737334c188280f03c1db314a609e99382381721b12f5182890d4884a7571e7374761b9731df0f1189a9d9e681c1f979b99347118e142f67d9e3ca3a79effa7a3e2b4c075f2f6ee4ebc7f2b1c7126a0eb135e3e7d330c2b6c871dc4da2e3e72cf41b04dea0b1547b231f574f1572b13109bf3f77db666d046d9aec7fd311f45418d133dc0152333a5f529d044a012d40aca1367856cf5911e71d8ce9f81dbc34fce910101594901d190afe2fd24bf8314a3b36ce859a00288313f91ceeb00d83f822b42b30abc3ef234c2373e7bc8fd685c3bf2bba47cc14bee2273f462adee91704c5289c7c92170ed12cdd580fffb4c05bb3e7d7a20cd0d95cc830261673552294bab70425fc29fc3f8c2d73bd0ea5f6ecabf2b3b25105a102f8d6571b7cb6edd8b83a58b7922ff243a32b94f1b3bbe43c56df3d0b3163b9f4eaecb434f6b0b065256f1b77eb2f3ac4bc0fb2e3077d7b5c6b558910c2edbf180af3d4c741eeaed09b7a6b192d6a735d49ceb33980025bbe567f4a395dba63553386415f90290b51ecf2096a34c864bdc6b79cc9388ed07ce6806a031dfb8a0a955ef1707984061ddad55e98cc73b5c6f6dde5e04de78497131a60b96078f304c69e1cd1a240e263f9f7fa45c6fc4bbf94b8899f79554accb38674f3be2270371169b40cd10137a9225ea8e9caedfdb72f36c4d6d431c7d01014cd2911fa547391e28356880bfa2fe0bba964cb2c977330b371c858cd9c666fc9248ccdfa8698f689be762e7ff80db47e14f0ef2d87239c6bb65a41660973fbb2cba489914e01db35835f64a46a360c04661a4779bd944ba9b978e5a22bc26c6b47f01e83b7e396812ddece61a39922a61ca93c8c8b25fd3ece57db0dcd8fbdfa1099e99d0c9d997e54943ece5f68ec8c83a372ec80018de7d4c84b0ba9da611c6805b67f614999e86f15e6bda5de426a1fe239cef35a896c68cf94be65f1e558bd54d0d85b4667f35c9910ed1507f9120b16055c38f41fc9bb8a13fda6a3bf70adf5cf6beaf567846aacb33035788fdb0481cdf0457cf27f30bb3c3667cd5fd617ee2038ab17350b18a048fc68666fee08c6f5b6ac2598d77c9584b11f950b2693970afdbc2e7c52f30b30ef8045aeeffecb6b3e353ec3fbeecb9d80ef8513a983501d752cc56ba39d607c3603074120ee55227d4f34a9e31cae7d5a2c6fe582e49f8bee1fb3714e953ed9380e2fa4f8cb100e8e670f2def4c582ad7d96b5838d9972c83811fe93bc87ba6fd341c02aaeebb5174291acece273fcd263d6593881b9d9ff7fe452338ff874beb68526ce3c651d501cfc5a006fe8db66d1824a28848bb8477fcb62d3482e8bd3d72110af08bdb3120f9f4f62afe797f31587dd7b05c292310e34fe819106b4d5c7de32c772a2830db548e5c9270a5ac7ca2ca724cfe46af0f35f43d296c3fb9fc7dafe35141f1c2179594648b601736880b4f5639b6300ff0e2f718ac6ac3fd51564a1a404111875459b9c6fb77d19a6f8d6c597e3ed70bf7104f8bc87a08431c12db0e57296d5290afbb2f19013f4fd68632c4cc4739947e07c87c221ac4d607b515129da8d08de052e31cd1c9ff035290cced357691011408fbef22abbaf9dcdae94a428a0e0110b82260c22659dabaa36e637e4eb851259a06ab126c33732be33f27b6c2421a677f036d0ed284218136ece13ae8fc870461ec6d594506c0fe4c3c5d01e0bf5ec214e815f81788d896c0aff62b245d6b1db1b611d734e1bc057d8f5f9263f697808049495d22aa54c60543c58e4360be2850ef8abf64b602ba3a23cc048f7f5c2e3bcb08264479c73719c51d4c18b6a48546a993d1f362372c880250f8ec4f4e4b063a0a7a40b60a218626756bd0ec7228370afff0f80e98064bdf71c7a98e727777188911a363bdeba4511b586a82f81d1ac06446615226aa2700493b009572ed5a1fa38926656441885f229b08fdcfb8f6c1d8b92b04b85d15c37103ce771919e57b7d471730f09cc846229daffff18ae1c3043d901549c46c82e7b3fb7a3b61fa81d054db3c368158703c0c00b214e3e2a638a1a00ad512c09ca6b5d3a9d47365906e2a773fe36403ec9d9ee490541c722bed8ab13e28b03aa24dbe8be83c154a0c512d80843eab4bd559105ba6425fb659fdf0cc9b6decd6f7ba84928ec24aaea291f1296a1111d8f03032ed3a3db5fe8b2edef0b57caac00560ec9b5425f93bb05a260235ef31285c59b4c6092e28153f03ef5bf070d4028d0384f6805fd57994cfae01809bd410210a893940c95e496728db67dea0303bdff453bf78818347a48806ae256136eb6d731d1f7f18529824c4dc231497dd9d8f92e21bca4706258f32ed7e01615ce2772c0a265c984f4d03b9e5b5156d9317c79ee498047862bf949f5e35bbef45dfa9ae73dfe366f4204d4389b2e09873fcc09e0f3098dd31286429fc3d7cdee36cb5247ad2471da69d96c603dbe549c8601402f7be5c5d3a65cf8ecf98e5915802bd41882b379e99a90628ad07a24852a282571ee46022b63cf923bfb85b4bde48ffd18a6527b13417a9b4812cb82330f831dfd2d69506ae7ba2e0985515822477e99e394f45191d93a127b0ff8c7e5e4cfb294642ed7978646fb9462f94d40ba50e493f86b0470e472cd9ebb5172f50690afe782b7c5ba8621d913367d40c8b235270583835222437c3e509231af2a024edc5d66eaeb08ae0c1ad7a36e7b18286f66831415a11cd1e333ef72597b1f61e0ae07712a56c614c0b6ac7eac14f58d4811b1156d6a70c4ebf09532cf83ff99273ac49668178749b12b4220fb6556558f73627a50fa08f29ec700fadcb74e6b0f7bf55f25ee24f624d74e8849244a59e3a4b66f4e4a91ec7390ca7de9cd381cdadea6377767bde45c1f07de2b7b8104fc7b4e5997059204d01a65d8f5e44418cd0dcc626257148c58715531a7b38e22320842c308ce480c56d674fc8b36d90790cf626f51a3584c0245f9fe68cd14a3583b6a07a3373c5206547acbdef0ae459bbf815365b5dced7e0a574485accbad83485498a3c29c4821cc12b9d678dfb6c54fae760e02f3576fc8fd21f2fdef3de157fca0ab2183df6babb6f70666aff01137369f7beb3c0559bde970fd265aade350ecd64cb9b8d6065deee1fa066fcfedae7ec901bdb5a5f04fde543f5b6b63f14c78eefec95995a3e45aa44e1c0f64c35e84d71945c3ddef8d8bf397e773cee975287c00978d0af69bce6a3188b475d9f215289e30cedefdeffb3e9f72965e0cadfa901e1093d6b9a8fdc723f1a7324ddd0e247573d029e691e582e8331ec579a62cf099b39f78e0a17affa66641f8e7cd76c2e6a1320f05cf6f0f6acfd5291fa0a5e9dd52da157e84bed9eded5c236661563c1d1ff4c1714513de8d478073f768f9cf3023f7aa370fb824d3d3aaa0939f5f2814eddddcdcb644d6bed32edfff48861f9adc19f30f99f384ff77dd01c9f8c58a49496e14dc2de614cd0a0334c5c7630fea365439a3a761579fd9048b259895137ff945fb00c7e85cf3d199cfe56e23f837da77a4e4a3cc688fbc796bdb263a616ecea4fbd16528298cea8cc392743b216768363cfbf26da625f52f6ac05a991c435662a6f354a627a8b3d6a1e37fa66387c0939b7976a65cf243f5ec51daeeb2f772d70b9a84ff3be092db5d03d47fee8dbe38fc99445f91e7ef3046d400511dc124f01c5378cf300bad72fdfdbd292aab2ec94a4c1ff746e9cc3d9be80f96c51d689e663cfff0ba3f97ed22d51470dc6799f5ced2d5a8e0eeca28aefab60d83eefbf9072ba91f7d98d3e6669c37670470c2e40b8eaf2c17e5ee6ae35f41df6915f30a878b2ae9b529113ccc2102a89cd2b97dc9ff2b83317858dbe3b641f538db065e33bd936eb83ed4b5c5ba934338af5c5b08e3d1f85484a061801ca60ddbcb3eb42c438228a3b0597b68ed5d98d238e99ab7e4972c8709b67470a2c33392a2f5c63fdcf559861703cf6ca87e25b8ff97a894bd51703dfe77c7f230877a56ac674e5bfc8b1f910eca15737d51d665bb0d2e2361a7d8a0bcfee78bd07cc0c524d5cca0b30271e656c640f9b8695dbff631883f9c05a3023ae7c1291e85ef8f4179498a334394c9e4e858aa482048a5917d4ef4e27c9d0507747ae095fbb5c5af23dd75dfbdbbce2a731aeea21d17aae4b9f1d71a2d0753a43dc55c4aa864f6ca262dcd1d5c2567fb030a31c83afb32776a97b3410270cbffb5e23e7de7d1d1a0ee3394c3732adb3dc4b23d945f5107eb0af2fbce0272efdd8debd66bf72b73ef71d3e292781fd018185a4294ff17e7a9e67ff69abf33f479e934d772d1b3de8571755b8e761b6e3d103b29e14c9dede78be70d39f7d7960a4d7f5194abad33ad775cbb7dd76aca6efb8fe7be4115b378fdf9f3fe9634562f99f579cad29d28952801bfac21eed4d10e0fde8646f0e05da2c35890850a550d8e6654e11a46a32e2dcf6b6760fe2a3ee1c2b1120d31057ad377fc2cdea4d4d4018d7713affadc8451496ea83d098c13be985fbcccc6bb59c98aca6265f0954397ef62b8cc277c40f9e6330951f878629650b78cbb463d293846c6d206ab97c48423d71709283e4d7054eee566e67a7deb54cf87efbf1df9ec5a56f106214bdc3567d9b9a9de62e761d830f609ef2d360dfae92060dfcd3fb75568c1ab9bfba1926e1da357279272aa4cb077d41b84dfa171ff1155514508ee3652ec064224ec82995a23c51588780829d0759bf4ba88fcf805889e2a3723a186a8b53f72198d91bc8d76887355a7c39ee0b0b903cd32d256d9cf1163d6531a3f6b1b28da5060074ce3fc5678f817203f73dc81c1f34623c80f443de8d1ed13f118df73b34edb9d529d8781df887b0f78a8268e6451f74570b59795f8b5dec3e317e13e571e778808bdc90bca941f96d3707b50090df9f8f89417f7d1cf38fab4b14827683fe5d82b96bda4091c6144456eff702ae4ba0e9ba573778d6f9358b74e1ad20d0800cb4477efe48e8ee83d9af81c38453702cc18b367abc123a48977946e70181feb86c4334b85625f4cbedb6f24e3ccb2425fc709bf69af1c7bf34a4f3cd3cffb9a16945646ff75e28944948a5fe87d9ae2f9dceaf065bc4c53b1e2279026ceb9d78d8c1d84ebf58f830bb5346de66657d47f433b9d6eee37f22f66b3c477d9f9c8cc25befc25a06769a912060e85442e468666dd42766d1dd2d0e27e0e7eb8b9f9fb2738fa0fa5c46f6a3776b904f68b795a19ba89b894e0e148f26ee9997f411e5989c712743a9be0b1fb2b85d52d96042d99186652d49567a44ea3bfc9b71e475d4267f00896a3eae7398d92b1607e73da1994b9ee0e3e52952cc5009d576b907199516768c4b1af812b2fca8cda010dbc91e07c45b71d4a5e70fa29ebad0850e65ceeace2ee8b3be4fca2de9c8f5cd6271f0af88d947236eb4f5a3f15bd8cc7a148065954e560ce35ce8d951ade3c66d6eaf6fb6668e49f16a8827a59a2facd5c7b00b8a0267c3eaa53bfb046fab2f2a641740b7eca1b6ce38064ff3b51ec2bda99b80795b224ff86119e17c6db02c04d5e79bd6629ecd79f2b7f061667306952ed907e8a993713a317e3c72f9a3beb0c68b71cd732f9992510e731a3e3a7ed162348b1b7fdd577b897405db157d98b019864e764fb01b659ffd8c22b4aa8b69d4194d3436d5ea06d7a1fbd3db79b5cf99a874e5de1dd010ea10e794160425b9319d0c0367feef9072dfd717272dc1ae5fdee42895aa1fce46ab308e07ce3c9c915a3dfe712bcb233347e135c1b386a7690c6071a542c1bcb209d30788f1d772b7be2f0f4ff9dfaacdd5cab763f4583dcd307077fd3461bc11f5a68afc3a2405755fbe84fe73205e2d60cbc208e2490c7d6183a3ab95d66f494a03a360a7dc6dc99a2ea2b83fa33a003b6b3ebfe5d5c01a7b1ecb796c1d16a8c35ffe225c7a746d07df735eed54a7b0f3d8f00cd9dc221c96585cddd1ced69afca46f41d6c8578528d25f63acbeaebd05c9512ab68d7d66ee8351a25a0603937188f06be93996341f706306ab9d7745943e4fcb6f055cb2b9d384cf4278093ee0870ebd02301574f81845dd043eb1f43bd53e000fd0160843f881c7eeb2d974c18bda47ca8014f58e519697676f1fa55595c778591d120fdc6e3b67e31623d529cac84c6434f3f9a33d9d4e6cb487fce51b2acc1a95144e21ed959295623faad8a1725f9b4b27ef5dd76bde9007a01102cbe4050edda2d628b7a30342cab5daf881b9db9b1ef360c4fad250a3eac33b51648ac77c3122ad909f28a7b3dea36bf24a1afa6de7a6fbbe89cd9dcac962cb63f3c682c4baa308f8240c88fa802b99278f59258d0d3f15f4dcd062218c6809d43c5e56dfd90e355b9c8bad84049ac2eecb19e00b72e5e373421da57c71a2c14033d6176b0d7ff3025f7b2b051a79d4a43cc53e0c4919c516f7335bb210bad2ea80dc6ed4708295418e19a47dd5ec4543604764b5201aeec661e9c2851d2250cba4c1f5901f5964b635717baafb4aa59c2d3cf64c786798d7381dc27922bdfa3730d20c930ac3783734d9a377eadbfc1edddbe8fdb0c9b767401d1e947428bae67c30e9f4f329f34e0d4586998bd7e3c60634c54e2b76b03b53011259e1d7c89dbd4cf3894dd21eea25b1991df4527e46232e89c8e870cbaca95bd1af867d6a30c2251cb401fd8ef6d630a8bec3a46d6a79a24f2790d155192f699a36a5fd2a7902498376d2e784d42e53dce0098bac71107b18f484336580c134f632393e866d64aa22444ad47b9c501c496c2491370ef84ce6777d5c6f877d7e61e18f77e7d05dc10d6ba57029461afdfdf0cd0ee31587546e66e1b65dee57acead2c5ab7a7873286ecce902705100f34313c3354e3807b8fd97b937c3753229107811ac8be569b86e7d7656ad075531b8de7369b8889e727790fdd848975489eabfe9ab50a53f637c760b52e3dbb48fd79a3d5690fb5fa73542402df4f0267af768265e0acd787dc8a30cc138806fcf5a79c138dc97b311e38de1312feff040dbe21c1790023620fcfca12ca1b7cce848d7136b5e3f9cc197478488ab9b3e0ae5fdddded53bf8957f702bdbead66c10e235d12a11e2e54ea8825445e123621b2388c29af5366368ac9e4f72e1affa4ce0b46eed0a32df18932290a7ade17e00310349b446fab1b2781ed2c5f1cfcd786e35efaf9373de2148507efd0528cc74f3fb290f6e45f9f10dad7a7a0b5d81bc2dcfbc15796e91978a1a00760ad0cf0f26809ab97d4434b78bb20c8eeb894d5c5de8d1dce3b5634bf63c807850e168d77984928b187885a6166bdcfd98f84b21a8683d9da3f2cf083acde7aed7fd1ad6ba37dc69838def1335340215fdb68199ff9628cb73778a0786f9fc585e568453720762ba57be73b04984b7eff587f36a8842c800bb00eeb4d3260742a04d1e6db32e31a2262495260b36249f0034be8ce0672b53289f0bd8d352248015b7fcb1cd690d544c1b6f1c2cfcb115f09d57a218ebb728de6bf950db6a49b5c80fe439702cec25b398fce3e7657e8eed95a8e75367f9e3ef555fc3063fc4bb86d918978c52f88531ac9da3126eb2384322e9732ba4497d8045ff7a5b677d1080358655a1282031334585f8871f293693701314db9e163d88cea90f77738fbf6ba47da22834ea0209098cac206bf6d417549559fbd714fb6f8883d1ebc5903f2e1d89506c85450f0b08a64de922a2e6bcbf712f5b57a7b7d23cce4ebada128576ff869855884e1f92185ff6b329ba1582f319ecb576586657923dc3eba6c03b48d75908988aa864486d88b27e1a0e550c0471362cfe56623c6c36d4cf05b98ae78fbc98214f8d5b51dc5dbda5ec7a3d80314edbad40400fe7628f8da53c388b9075be1561f2c70f748ff3688cf93d6302a002527cf11e6219c125805c2b1e7a7e6591858582acb16c82e6e795e2c0db227e00471af508e7cdda8c865a989836bfcc6728dc4360dda167af5858edddeb737237a181665e7c3427101e134e0eb64163970ca001cb8adf155373d2b5331c10521b51669cfe4fd00aa7b0b66ffee382a9ecd577f89dfb375ebd13cc04f37ae6cc1e1185c8e68b780117b1db4dd0b28c433896596686cae2a7d5c412907271882728ddcf07ef20f8ec3af3f371c3303393ab6d7719e69b6d4c7175fa1c95484d3d087178f076c70526932e10bd80d7f7aba7e70da9eb7088dc16d3351f77fed30618383dd218ef4e3a169a6dea45241cda26fa06309f5e2450e171ef76bef450cee59f3b4ec4e5b477b00e3cda9d786f71aebedf1b1f302c7c89889152bf0739c2a7ba1c78e54a6ae95f7559b99ea0925cdbd94578e3497744d9b0b614e0c666977504f9dd029e9e75968b5117d4c15703fcd84980f42e4f04dbd014a27a8d5b0e83ef54cd171dd2484f01bba8c96cb7456f7409ebffb637883e73f499eee04ff6cea7d9e97e5ca402205f46c6eb74a8ca0a317a028630ab7cf321aa628de20da72a64e8295b13475d6196df7081323816693a67e7d9a47577b56d6edbd74e38e09cef3d1aabcf8232009ca70bbe902e5c624cd497c437600cfd0c4d00133bd1c2033442e681903b39f802bc0b5a6f439f8c066acbc61cc4da342323a44863dc822df0bf8ec6eea449fab497be76903efd25ef8f1fb8017717b459c29847133f1aa5b5c3931da73f2a4ff5f97c54c15a3385ef1a41cda6e3b258536c15e2082626684280b4ce917f2c28b2f8a620f83e99f3a27bd416e514ba323f184e78522469c19b73d137abf08346177f67d169f7884c23cd6ba3d38a8c32cff161e305309f4959591864c687744d8c494e6bc26dfc08d4402a48b5dd787dc1032b93eafdfc2ac9b90f7e1ac0b3a3c69ab5eed74484c8fa1da31a3ed66c236c3c74b2854b28d3da433a7d1cf12f0225c7a9cc8adf11f0331abb534afea231ac8154f7a5e518a34ebb9e7d47dbe7074354528245c5d9ef374ea0b8acea084e5e61cfbfd3c45f74a857ce065078e27dfe09ae84099a7138e7c5b155a8da3acbbcb9e2a40c153d8a5d34db70729fa2661452c159aee3803bfb5e62f17f44507e11e9979ff5cc0446e61c9673d0f1a69d33375678e625ded71da17a519f68698502bedcc8e975a48a4a26d9a2d8fcefc3be35ad168e327e6dff1a5f33178369cb6ce0993271bbb0373566685c9544c90ad2490943ac826a8f42d17f1dee1ec55fa0d6b6a157d367e5864423191b1c703d3b7d89b2cda139f32ae52f9409f8686959da054df34a3f77333a2fbd26768ce90e3d50970df387ea01e0b982618974827388c3de5976fb04e0c28d6fa89e52c0522e7b1408d5d6503673f398f0613d73c4f5e441bf685b465fa98f522de5dc7d460ebca35157f60732930e11e6eafc2760c22208941fc684b22f021d869ccb1659ae3cf757a5ce39dc795a1fcedbc92709643caf28c3b87fd4f815bd48e070f2ac6315d32110fd56090b5168cd5a9c4393f2d1a9bf41e9ef63b39aa4fa94f654f7b1ae32663f01f0a416b7a4de8be60ca78a020976cb367bbec5f862f6672b9f41fe1f77f2ab021e5effb572a2d9957be5d47ec13c4c365122ad7877810ec46a4f6804af39fe9e6f77934f18ba49941233f95c09390862d1add6b8e9c0ae63c81c1fc24e28f7096fd742b3de7cfbe8593bac19e6974f513e9dce1e7d9a03ff2969567e454009ef96422de8a833191e89798924edda61451d397ab6c4ea57d57dd94be2d88508f9531a7da70a03f7ff952e52e8b0832738d68da797985b4d771406156fe17932f37697044341fe6967c17f9c8efc6d4f29b8c850b49ce870e290d0f2f195d53b7dd71889bc3bbcca66abd0b99c04b4dab97e9c57337596b7a340293154a8ead17e84fbcc299efb8ff8a8c00b896f6f1e24cf6420c4a4eff14819f10718a4342a22263732af3dc35604b6e22eaa80a4cdd968977b766084b885a14965b0a0e57258bc28a8c028e354863751ef2f86e6887007291e3c9db868bf9da209edf9309c71f9268deb139de4d9c9033160bd1dc0d1266703622a6c5bde0f26ec899c67bd86383529de13c5388843d5c9eb2b6ffd6991a26a7edce9a4eb8f1877d0e6fa2c9992cdb8818227fa6189801d0757f42bccf0a54cd3f970605662ed5ec876e0780c598de0839aa1b92ec7c2c616b7bff1aa98aeafcc07f3409072f55f609bc20e76bf11bbb1394bc2c504a5f478e20dd39dc2eca9083343b49a6ddcbe526d44160324f50e69cedee128635792d53dac775da664ca2d798fd2fd5005f89b2f9988afffc9fac270e24088c70c7238d2bc79bc409e5440d49b87bda533d9ee0abf78fce74dbb15f023e9cb5826bf8b230a67406b3cc4344a53d03d3a4d7499cc1ec839622941b073205fa02109f318e7722e5b2678a0ae68cb9e289986ea582067ca44053448d5426d1b68e0905eadf4beebaff5fc54d897a56b0dd5b757f05717847de4a2863803ca0d6c340d5c6e12584407e740bb0c31fd99c604c2b445e67363c88b68b6d88c668324827917dca1d276f061c9bf8e981dcf9be6861fdcaf0bc46ad4cba815c7230c81a14b6b4173f41b918cb868403865df91a774a914ddcd4701b2b903a0822e2cadb77ea32fe5082049c0e03eeaa45ce0e3440b0a6d0013c0c3c0c3c0c3c0cac31c6ee1ddd7d446b5f262925d3f865f690e1524a29a59422f3f685672f04faa1fadcadbf1c17f90e5f0e690f48e31449234a7dd01d7ef35dc81409625b79293cc525cb9422295d87ba2d99dcfd5c5224768a9f27dea4082f47b1b8c555304bcbddaa6de1c1a3868553ebe5952d46c10c465e40431449b2f1f4c7a0f2782123e8000e1798a0c70be141222272344291f86b1bf784aa39b66ec7101eb863080f5024f6a5b510352556d4fa09aeabc4bc3bd4cb3b49d98c767944659886279283979cd158353a670ed0e844724ea69bb24766519b0f09823e24c87122d9752cc6f5ce78327ef005385c60021c3e84f418810a686c22b35b8bdd19235e515e743c879dee14b2b9cdb155a5120d4d24a7cb222c8366b6dcfc6a80462612ef35cf4b8b6778768c7c101d3b10a2c3477c0829b69848341df54ae6fbb73dfb12497ba9d388e928da47cfb1e54382f890165822e1ba376678f37ca223730875c00a342a915479a47ebe8da6b839901c414a01c9d1021111213a5cc70bc8d0e1011111114a9448426312092ab3eb928e9bdb095187ecd86178b440442497070d4924e8787562738b7bc63212c92e6aabaacaab3a487f201f3c1403342091603f1657495bb28e95901e232043870754c9d0814646780ce9818f4890da9bb3723c088ba61d68382249c70e95643ea665f8ca17683422b994f20e3bf16176e613030d462489db78953cce274d690b038d45249e76bf6c6f9eafa4f319682822f12e2b2df5ba6610974424d98613131fc57cf347444444849b062212a458f4bedbecd6f1a47188a4a42bf74ee796ecd968182279476db8afd411df8e46219292a8cad1dfed795f27446214abcb289edebbb48348ccd9f0243453da9b2f88c4241764ae5f0b163e1c880419eb2ae5d8af2473102012cc52085d5b26836dfa87abae52a9bb6ba560e1332d97c966b760daaaf143b2785026fcc6e4c8c9fb909445e6d59c92a89c47e643529cee73abb81a43767b48b41cbb7ca284d06fdb888e1f6664640405331811a1a18724edf98398331b1d5367c88e9424a091872471ee219f76f45f327cec3811d0c043d2a81c911634a6bce3e5d85a1f26b8439556572a9a9af195cdb6835cd30e5b41e74e4f06193e4cf0c3070a4444c8f0b1e38008f941c30e49aa72ca72315bba745487a42dcf5e493e6bb64e3381061d924c3f7c5df4fd6899ff2026870a76a4caa03187a4b418668425d3f4abe7d8da3184c7b9c00438760c39c10e1d2e228282198c00a12187a4ee98ee41d54f4d9d39b6340649230ec9b331c3dbdc2b2cfc7048b6944c26714973b6bcca40e30d49496905a59456d8ef300d3724ce88b1dfddf0e942a50d8925edadb2d46be3538b020d36247516b99d9459c75b125381c61a12345f52bf27b7d3fc8582198ce4a0a186c4f0cc5c4fd5a6aa2c0080028d34246cea8cbf13d59bf9e700f26d68483eb1bf29e49e8c135f8e2d0e62a5562898c1c81834ced0ab586caf581e7665af164229d5a6a4e70d8988041111e9dc010d3324aa6852e152a65a8ebb0c89feaa7d9d74e8ef60224382278da5e5937c4bcaa53186c4b8b172ce869dcf4dc5903cb2a4ed8d9bcef1320c09d6fd192fc64a88d9c190682232a8dee85371491a5fa8cc44e3a258b5cd9999b76d5a52c2aec335d8fda5a8507b2a6647aa0bc97f2b2a9bb89cb9a3070314cc60240734b890e8f963c2d2dca56e488bc61612f437f7766ef3ec99161111a9203a78a06a21c9b63a4b46d19cb4fb39b67a04dc5948d2ee2364a5b96e4f3616927c2f7d2625fcd2638ec615124529175d95fd29b511203e46843c1958bc56483c159e617ddfebbcdd0cd0a842720a995ee943ddbbe5a990d4252f9a45139f92b753483c69f6a5fa3ec9680b0d292476888ed9d4c73c7f8b461492544e71a77b979abbf3917a8c80af40030ac921dfd379967c7bcb8d051a4f488a1d6c5773bb4ead25481946052222222223c5f7041a4e4852da31c714849dad959a90e83eea3b5d8bfc64314c48109993fab6c50fd24a1a4b482a35b59fd954462d692821c9c74a6e288bcbfd291a49e0528513f3b4acedf8103fd11eddd8d727f2d14042f2e9dd14f465bfb83e3a42829df0105f7de56b6a232456b0b4e7ee614e7fb408895ed6d9d29cb9876f78041a44480ca5ecf2dda577519da3318404d163294c67eb65b53640430889bdb1724b53aa986af43fca70c11466042349ec72fd6cced5e8710130124c4578f8d8f973aa57c88c5f245ec86e7dda51f19f5435e28bc418d772b69bb5306b63c1e0ca1866f42249657b5dffb42df3c701f1a1021191e645c26eba9fec642a6e5f5830d845a2f99a0a52d4aeba485229bf629bf23ddf77c38c5c2478f78da7b64a44044b07583a385c245b07194b09d7b83933286f9158b174ca529d21e794e85520226235826b98618bc4beccf9197f39f38ab548b4533777954f78f857961609426c08f5964a47575d44a4d44819420c0d3366917ca3db43f6cd29954b2222226508111119a9205a861023c30c592406599674c43277fd8c45a2559eead11836acbd3360911843f3d6697a2fff393d0b84e8f080d588101d5eaa7a043108e4d1bd2231e35ce6e06b3afdc675862b922a775b25db90a7d25624cb07216f2d5dd85c2a2222ac48927be973b8ad20f38e5691e0ad41c8d26937f9aa480ae9ed95a4dfda5d8a67a422b18490a54eeb9c0e7ac119a868c5b2553a2b4ba92ccdaa44fbdfaecc885fac878e12189e22d144462f29f78c9b5211111acc304592aaf7b1eb2e9196772912b39667fb7d0ea5bfcd2045a2766f12db332ae69c3d20427ecc18455289874d2563d97b87449198838ecea7e44e650d4592aa12b13f6a74f4108122f9dc73a3fae5d0e1e74f24075defab4dae2792cdb2d385d20f569aec4472a5a5b8254b06cde044529ce6895d54b12c6f8ead1c3c19c605478611721698b189e4946bc359b6e799c85030839115ccd04462fc184d69bcd86d326604333291d49e4df5c9a5a8797c328c0b4444c8304252300313c941e56d52cfa33d69ea12c79893b66759d08e1996a8d35232b3d866c13fa50ad594e6c3401ac823f32ca852208f6230a312c9a7667aaaa9ba35f4385c100220690625924f47fed5e9532bae7d404444488fe731e4f8402222401e4d224997f8f079bba39cb792488ca2d3a714e764c9f7726c194084f448d87e181e3732231249f194fef13e13d2c393638b8c1e3a820019721ec84891819264de0463e01032e4042222401e07400c8f52f6c8470fccaa007861062492d493968f733a2c5c633ccc7844f225b33842d3bf7b9e71b8c00438aa460acd11c936f69931af967778b6e861462312adbb53d47fccee75568dd4c89e1f6630222979a86bb98771d77211c9a1325eeb4b66771e0c331491d4e5294737adb61e4f44e2a51c2fa81215c773c882cc404492999d389d944ac947818888e9404464a44c0716a40b0e330e9178fdbdf9533ef9a9374472b9a5e47f3a9a26aa1c5be8918f2043aeb410494163664bba5712a5448884b5ac2f197fac6af483488a36a74a79ef8248fa54396813b5fbda32100936576f35da49df2667002251637aa8179583896633fe807a65885d50b92f198dd3a7afe279395a6fe587a4127fffa0c2bc2fcce843a2e9e92c79d153ea0c33f890147aae924a4968cf2fea32ccd843f2698e95c6a285adce541766e821c1834c2a977598cba88a88a47161461e1274cebe7c316ddcbf82872451ee6afa544c7cd433ee9070a677fdfe64d29c2e33ec909cbff3281d4d77c63fcda84362ea561925c3fb4727d12131482f75d76a6b39e67348ee7fbbb0f9313253921c926ef4aa6b7be498d0c7018fb1cf16b7a0e5a9a2a9a0948d9fbc1b0ec99953ff735eac95b04544444478a494c7e1015f61c61b92532b8e5a36a59dd29ae186a48b5ef9528c15bd533fa30d49a2316e3a390bd6b133830d099f720e7aabdf838a7d0dc91a3a66a828e12d9a9ea106456bee525cb82dafd53a19b2d2b55c2cdd399d918664d3663a6d3ebd1936ef9e8186c4f1523fab7da3dd72ce90a4ae6f6ece74e6ce316648ceadaf0d6f6aba5237a30cc9d1c3c5fc1a2da7ad1a984186440d33a6932a357df7c7909ca4c6cd24c37fb4852222ff4084b88888884812668821e137cd29b1316fca2d991c0f044d30230cc921333dcdaf43e9395995edc00021c10c3024e50ef24d5d257ff800f20111911f3e80a00eecc0b04044640706487f216963e8494b97bb722cc7c0018212f06086179232ebd929ef9373391281084444b80e00ac98d185440bad3ba7ef45e952e5d80ac27c98c185c42f5925b3591bdee71d666c21b92c65edce6e1cad3187c3052110418e2046043982981c63e018038708708c81a3057498a105abb2797d6cc565c885370b49e2c40675df11a29d0d998185a470bb1075d971aaf546c10c468230e30a0923dd3b6dfe985bb722222222529f98618524195f4588ed9e907193636ba4ee0833aa902497530eba49bee78c8cf8206364081b11665021c97c4c48f1204406717704e931630a09a7632a058dff3136828c1d1266482129ea7e060f9bb2a818cfb13532d256ac0833a290f09536a39bd2c1f4fa50484ae27f748dca31bbf652c59e906096554fe697f7f41a34021111111120427ecc704292798e503d1121f2f78c262407b5a945e6f8d5df1833989058db35d6ab9982e713f398b184a495b994655de38eb271304309c973326a619a5d9dc91c5b5a2798918464fbd49e772c6ee594ef1948484a6255d332c8f8d8212222e4c91011c1e18210e800e2021c63140c444474bb30e3080932eeb69f2e966e6f7f0c19c1810f1f3bd670b82004385680630c1c26c0e10213e0681dcc304292d2171af2ec63f2d01521e9ec533d7b569341663c74e4082244070567308308c9f95e263c88bdb16ce5d8dab1c31cec0102ab1943e0ab44d542662db77b65ddeaf841efc26b73660821295310c2625da99cf9c1482af51015a5730ea647c048b2ac5bf174325749f48b24994a5fb456f1a047c717c9e3a54ab3284f2f92e23f46df50efae205e2466dd3b31162cbb537c1749c2c3e5e7f02f2f265d242995b19379ae3a139a5c24b50825d7ba9be16c5c2465a7a4bfd3eb292df62d922e86ac6856693fa22d922f06a56cf3e920e3712d12644c2d5dca90ff1b5a246dcccc56dbf6b2b7ce2241e5e6f3dd5aae994f16c91d6e66d37698103516c99a628c0813a7f636834562ee2515e683f6aaab5e91a477cc6b645bc870293a76805b653c0e467a87791104c01509ae99311eede3cb74ad48d2166b6f8be14e098d15097eefefa321634af9ad2241f9c58fc8cdfc29a6aa484c1e6246c5b01a936c39b6ce7210805424c73bff9341fc66f2ff801000542407f9295f305177bbd32992d4ffc5d9309e9b37c441a54d254f09cf241b4248fc2cdda036b574de2618c91a444f640a1634091b1889677266741ecb187355e317c58ed03166109d4d695fb0d51e9aed19a665ecc56d56f7f1969e5d6f41ade43dc7f896bbfc11adb21d35789178329bbca895b200870b4c8003052222436aec2229891aa5e9f2263dd8ba48cc96f46aae07af462e92d255e6fc6cfa2c730717c99af36234844a7ae3961ab7484a2927f12dd1a24b266d9134722b5c565026f4a7e4d8ea51aa356a91e8b13df55950426553cab1555d831689e1720c3bd22ec6a465e6408d5924cd47131afe6dfef23e7ee4778cfcd0014448902d2086070f03840c59247a4e5b52635229cc9262d17bca6a7a5cfaba8afb12a6b2f946bb9c83f6b0483a99cdf478ec945b751e82c373c82b926ebb66646c0815aee18a44ebfcd15a640a1d672b122c9a505f2d32ac48382b697136469dcad7088fffb10ab3abba44cbe6daac662c8a066da5efb9b33940c0021c3554919cae1d662c4f68d532158939a8143b7b42ec9c122a9245a93ea9e16b9d1a3d458210a3aa2dccad091525a3870e111116d43045b26e90f918d38a36cfe9408d52247d3695c554f3cf07f5f8111f42466e043548816e19bd71e341233bf81e552e30010e205a409647913c26d47e46535ff85a145b0a1e66b9c64d3dede4737d96b767518622f1f2a668bac2a679908322d9d2a65825c485533253e313491dd6f5e6dc7ed7429e48f8382a8e8a5ecade722792bdb2758d0961f355102043c608f242caf040193538c16d6625536f59cd6a6c22e9929aa8ccfb5c56a21a9a483a61faa27b1232d53b35329118c6f2ec3dc48547cb2e269274cc9ad39c184d25335d6a5c22415f28f5edd4d329dded2dd4b044520c5bd3d5dc9a5234c80b312648428d4a245b8d9b8c9b157d270b420d4a248b4a31b5f96306fb4e0810a3826220d498446255f6d0b2b433e7a21df1410d49247cdec7e456a188c8958da1462412f69214f11a199d636953a801894413beb7b66976c442778f48acfca0b3444524d4704472e834f11e3693dbcf6cf5841a8d483e9dc544c6848a27d38c4850d1341be2397b726f1149216c43c7542e94ac50a08b82198cf8a8a18824954ace8aba5cafe99388e4399d3695661a934f1191746a4e4dc3cc7de7f01049312c898d3187bc0b174324f56610963c55f08d4f2192d25d86e9a770bf362112d5a4abbe87f960e7d5184492ee932a6339de09a523d41044d2cb8fa5d29a749a0faa11880433cdb58ae9a6640901917c1bbdb269c77fb6afc61f92663c87f0d49e22770d3f24e8f8ff592bd3e6f193b149a1461f92931c917a29b3efdb1744444444e4742022c2e3f0a04f07c6e3f0e06af0217194d9f5670a32c3a80c1fc91164c88ff6408d3d24d67fb41bb34d9552af87a4b260322771a544ac55230f0942d375696a9de85b030fc92717f377e796e771ef9028b24c2c878a7648ee1511cd94e5d39375483cade822dbaf3e85990e49755aff4343bf2c65e7a0cd69bb655cd4107e328552613d7248fcd0b54bebaff97489439266bdd3d9425b3f3570287a69c9cacd5aca5d9da2ba622bdcc8cda2466f48b2b22de525fb7d2aa30321d47043720e23ba34cf3b7cbada9098deef4d8a8c619d5736249c164b1157de49462822222252aa588d3524e8b029aa2645cbbfa786e48fa7f4a84c25ae2ea7c1724fad9131b97472298cf48af5b92b2ec6d2a22129877c4fb2c67b3bc5121c6388882ca1c619924c27e53daba9e6a36386243523ee53d45252a32f43f2b9a6ee7ce72b322a1912d3688a5549cf31242513b519d46fce5e0c89e69783eed0701d5318064d978c7a2a770a189284af8c48133a8a5fe80b4952ecba82cc6691b57921292e6bde75b4508b295dc06c46b552956d5c5cda0a9bd6697e2e24e5ff2857417bdc335f44c4b450630b89a3cec497ca7b46931692fc3c844a71c487b59785ed529277734ba772293393ac14b34633866a602129fd7855fc147b17d715927cbde259b67c9ba62de5841a5648fcd5b6ec31ee874e9f2a24b96965df9dec924fa990a0e1d3831e377d4273a690e03d9a4c96d80bf79314123fc4cf48ab78e94f8f429d6919177651aed6b2c58df3a29f52030ac9b1e26590d14f3fa7477c0819f951d735a8f184445d59fd646e1ab4cf6d4084fca8e184a473cde9ca773f7ceae050810970648d2624c7889ddfe4a764f6bed5508309099a722fd8459f33fd2c216993fca7f7e7e0d1ab4e430d2524a89461c1824e3953af35929098f4061dba4cbb87e66b20213167315df9d27589f174a003990e747c60c79013b0958e54e308c9517c2ea3ab9f7cd68795358c90a044c6fa8c72b99bd232a8518424295629a4ce49b3351121e14a960cf9395363085d57d9bbc5a568b9ae52c72ca12c931c712a564308c9a57273ef86d82a29e2704108520e1798608c91213982181184800c1c2e30018e3c84118c444f151ba3af1a09f2a657100630b6b3142e9c79c55bb214366811daa9a272bad4a34118bf487e4f7d8bf312bda91ba932be04af021384055d410e0e7ea42f9246a74b616954bcf4ffa352070e7e040923d17aa6f963398407da9013242222403ec70f1d474718bc480a2a9ba754f35237bf8beeee3653bd5553b5829655ce962d6a09a54214862e12f4fa7c0a553b73f5837c075a408671018e31707c0f74b400c71838827c074e08781c3246827c18b9480a6fdd68a7e4981c9535df811d1d40c10c46c6080317c9697abdaf4f8c855cebb2d7932d923499f7e7b829338aa91649f971bd9ef9a745f2e914b7f421a3aae86791b49b84aa0bd62d6abd2c1eb5131f4369281689fe992b3fc7b878d2814562890e972e5f4ebf9cf38a24214d9dcb5c975ee6b82231c9aebde8fb3dba3aad489ef5b4a0f3686ecf382b922b09a921ac55246eca2144689295155645721233964fa8bb4f4a4f45825cbd509f39a3761c1549a9f3667f86916f9f394582582b59daa66b2a6d8a4413a2dcdccf42c5b64b91e8f12f2e7f483b4f991489a235fbb9fb9bbeb5a3480a21f36cbf3c28755251245e9bac67eba0bb852259e47cbd99c94dcb8222e17267af8d09b527cb4f248adabfcf31d8b7e79e4874f5f841d676143d3b91f89784e9175139eb889c485051bfd4f9274ff13791202c6637f1f194dd729a488c23e6360993977fb34c247c69d11edfdc554998484eaba67933dce84a954b249f4c498fc8d4711896483093ef74919a2c3d692b91a04e63e8a8bdccc59f124929d3bf987f8599ea2c8c4924dc788ee154fa20d7c123842189e4dce93b4c74eba91989a4ce4925cb29548e8d068904dda41d2fa78bea9d7e44d29d8ae13c871c717e3922297c50326b0a6acb3b258c4624e7204a05d5fc418a503322e146a587dc14b37f9645747776495cc4bbbc62ba56afffbe9ae6eae7159118fab974797fb2155322122db42b87579c0fe9232239bb7c73e85cd694fc4324a67a4b8b3de23e636f88042d25735ee7c6b0132a44624ab2e3a64d13de39881009b656aa32e820f2c2671009e667712b4a08a5dc238884cd31564e59d1ce2e271089dedba33f6868d2dd0191183d68874c414fa6ceff9058a3e353b21cc32f64fc90ec6526d4aaa60f0956a5eb848eaa29e9f9909c74b3528ec13e5b4aef21b9dfacc298cc5339ad8764eb7cf9dd2b699d340f492364e3bfb2665492f1901462ea76972f95e57b87e44e6da3c289af4f427648d88ed329a5bf707a538764adb1cdab9f79939a0e49f1d3ebc8cb5bed56e79074aff323c46af4c9520e8971ca7e2d55ae7e280e8959b3e7aa7d99f81c0e491a1ac455c9549b62de90b831c6aec678aba9d10dc95935b6cf892c3d7f1b92c3665d98b7a4d4d6c786e49c47ea08a1ae4e3f6b48f4cf31b899fc57911a927f366e2caa864b95a52131b3b56e66cf29531c0d8949eb6651b71cafda3a4362e91cb3738a1b9f233324962cf919229732245bfc91dd349d7261214382dda98b9e2958aa928e21f1fdf3c584e5d0973631dc96ccb3b4ae72cc5c4a5696ee295b2e6611c390f47d55232b7ea820ff09446c0b618021f9db5ba3a7c73d9d453d76900211111191c442185f48d06c2633e6bfb3c5b080210c2f2469556baac5a79a0a87d18524253373b7dbfb267a2e24e8be9f72cf1736a8b88584addc51fe2ee78796b4909ce5a393541196e5ff2c247b7956c6b2b6be94c44252a9d49326ab498a50e508e30ac95f99d2e3d70575a217111111e991c2d23584618584919117531065ca445548ceb0763265935fd1e25448be20b48585b1f558e92924e5f8b6b678b8afea5248961937212e2f9effa951c0e44ec62aab3d3e66be3a9cd83bf5f3c9e2e55048522a66ed31f7a52b7115c27842b2aef89928cdded0f3938174009142184e48ce31fe680a9f720cae87d1842419767cf367d5861b851006131236b3be8f0e26a67207218c2524aee9b09f64103e1f232524c6d8771d259f242478e9257d41550c1b72184848da94940c9bf36f784e3942d2c69c45854a2a23245a5de8a049b533da45287a6599a58b3bb1b738e5a9b29edd5e3a6724088308c917df57f335a9ed7a6410c610127d7cabc2ebc5ae5bc210425e55e75dc1c6b54d2cdbeaa9cdd93efe2e58c148d2251bd7f4c54ff7554464472a8740031889a7ef5a37465339fef78b64bbabeb937edbedc91164a46a478e20be481aa14de59455497a56073a502f12f3de664c1599d9f17820233ad081ae74a003f12231c7e0b3a753d6deeb2365d82e1233edef96f70735e53f0f1f6408e9e18347a93284f4f0c1233b40431749aaef2cb6bd3c68c78fe181c7e4223148cd7057eac458a777ecc04562ff6e58eba017b2191fd2825b24281583da185fdebf6d1ab6484afa3c9b8bf86ece5f2d12ee672bec2dc78a13ea802d0a6630f2346871b34830cf3163fa1c3d28e9c922c9d5c488bb68f2739d6291a4ca2aca27a1aba38ab0382ca69c865c785d0e0d8f39af2c7efb8a44ad1d8d337bfd3190e791e377b82251e6542dfc6dec76ff030d19413a769c217fad488a9e3998957f0a163a648ca07f2b74c86045526be6e6ecd1e5d8f2e182213ca0b10a135145724aea2d9a7e1b6e93468066a0918ac4a4396ebe12a533593cc7160868a0a220b2fab9b3280f171e4344a4036eced551572344628e7aab719e5e4a5f83c0423f4434c80822a95faee2a6ac15941b88245d3b5faff61d3f1620123bc558729a625364f587c4649f435faceea9ee87e4cdaa9e67f13e24a531addf514445950fc9b31d6fb4da5cdb0401ec21d963bab8f92de2c399f490209684b5f9fd7f4aa53c246c983851cbe961468f87c42b3d1ddb725a9acfdf21c933ea99bceb20d4fd7648dcddf64bae7d1d926355fc20749790b1f2744830ad993497c80d9e417348d054e163d66cb1ab457248b4e0622a059d9aa774e290a4f327cfa3e45b79cc81438296dc91794ec38ffabc21730ba7bd9b3d6e4870efcfa752a7294d9e36248ed0e17a4d2fccc6c386e49cef7e399b7fd690af214166bad31745df67d9d590242664bcdc77f2f93169484a37be5aaa3f2cc50d1a92665e6356ab8f8dae3943c29a14b5d1693324fd7898c586fbdce92e43621c25326b1b422dda6448ea78224e89daa88af518927ec4bbf75db4bad18a21596ccf2b6d3c0cc9a547e9fc71db15130c4931ecaba6aca5b7d47e21a9b22e5b506dab157b21596455c896cb57ecb40b89b1f3ac9bac4b9a772e24098d7b153fd8f585b790b81f9664a66ecabca61612d3678cf29a75b262b29074615cab72feca12221612d3ef8bfebd8d7e3a7785c46c3a936e5f8818911512d4b9fcd6c7947294568504b16dbb95b992e9890a09971ef329cfa1820c4d21297fb654d193a89b2e85e48f5174c692f1186b1492c48cae86bc2bf5b2a09078c13f67b2a896f72724090fda293de384240d6db2a366313db00802684252c878cd5c1532a99e04c08464ebf8ef95f289599b04b08424172b654296ec36350940094915f6d26a4478d6ec0b2009778e4fb174701f09499ee3c9a44b7385b6fc1192fa62449c8a0b4b216484a4fc51fbb94ee4670e1240119254e54ccbb431666c91008890d8415c3a0beba9aa21010c21492999319a772f79cc11801012734cc92ce718cf729f602497662c574baa279380916c6a33e7f511f3a6f38b048d374fdfa02733c67d91b82232bc36a8e6cede8bc4edcbd828ca548ae9bc48ca6d32c7ceeb074df92e927bb4888c3632ba48bacfb2b9415d25cde72239786ec91f7fb96d71911c437f341735791fbd4592d7fa6cbe678b643b5963614d2eb6d2b548baa42d3cbe85699120bb42d393bab348de74eea7bd2b2eca954582f61cf3b4f54947716391203f841471728545724a1a47bce6faba5b5f917c9deacbba652fcdea8a844f1f64e893235a5a6d4562127272c6e44e7854599194f76fb44b6a7e96721509aa4d33c9c85ac754aa22b93fe628e282053d11539198a6569b9e42459268bd1cba7f31de82a74836b7683107b99e397da648faa432b7eb7d3ca552247d276d6e719acc2745928c5529ba5cc7a97d1449517e4eea8569b05614491b979744a8d5ad9c8522413d695a901aa7770545d268ac67b0e4a132558c70e313c97139d765f498447353373c916429cc2dfbf8a87c3a52b8d189e4d7e8bba1662a9ffa8d13092a05f9994fc71495e91211791da4ddd8c4e93daba5604965cdb863479a256e682269e499f2e0d96f1ab61d3bca002224ab702313c971357f5a7fa344cc66beb88189f7d4fdadd39aa92e91dcb6e9c7e4a9e8ef694b24aeebc6a8f8dc6e41e14625125773f06a0b2693f65eaf7083128977aa4a58981ad78e27919c3bbea956fbac93a50216fcf9d3c3478f138888041903c7182f1011e1f14282948183f339c610630b372491f4eaa92fbe7f6d8c0682473e4e90871b9148d66cdfe775f7414c9a632b085619a90210871b90485242de6a58d2b3a911b31e2fa81b8f48b2ada0925a8ddffb508e15d9c10d47247a7cde8bbfa32fd721c38d462447d3e194507b3f73298c4850fe5ba7eb5d5f737c6311896a25f4e68af6712b223146919d82d22f6d3b0f7c784044043d0f7c380311f2e346222cd9f17363d0a2c9cab1a5831b88489675b3fc975757d6e0c6210c957bf9b2f9402222222222754084fc08c02d6e18a2df1ad9192a864b938848bde246210c0f2a89a9da80bc901d3ad20842a6940e03c40588b841085e944a6de27c63ed83d05ac6cd33defac55810ae6ac9673fb5a4321a886754d8aeb7ab874ec80d40204e8a7bf2bf53e16221434ed00304c9821b7f483239d35daad2e592b188e20d3f686539ebecd2da698975650a9bd161a512dce84392de0abb1f2a773ae8dce043929a92ef9bdbc1ed94ce70630f897a1d5eaba45fcedfe65821407cb4e06af5906072a3bd9eae144ab37948103a69de8e96f235d31b7848f298dc3ccd5876ec306360166edc214907256a2e8ed6bcbcda21513c581af9d93f7719328c1034208fce870ebb5187a451bbe5fad9ac43966ed02149e6d1b13a5bb8649acab1e543c899e0c61c92f3d6d584494b39c38337e4903c6bda9e231df4d05116e4870f12dc8843f2094dc983e7cecff4303adcc73137d85bc10d38a0e9b116e52cb9aab9bccb28d535ff2474463e8790911e3e4682e828037bdc7843e2fc9d77fbd7cbbf8f80f81819f9018210ac99c91104931b6e08620744c899c08d362ce0061bca781c8cfc0041082070630d09d2d33f96509dc6ef37fbc00d352486d2a284e6ec66fadb810f202342928e1c41d2909484e626ed5faf3a31a321c9e6cf93d01a37d653ba0337ce90b01dee74a9986b2cda39b67c0819d9da410e1f3d4682bce10ddc3043d2789a2d0f610a6e942169be7d35dce4e8f3518eadae203f52d082ac203f7cdc0d3224a5dd1cc477dce4e1fb3124cd7dc834ba46ff4c460c891e6329d7e875526fcd46c10c46ca8d30246e0c16b36dd8598fe606181254ad9c579041275b4b8e2d10b00047b9f185911102dcf0c2ef102244c70e09dce842b2081d44c9cf29c6f9f68790213e468214bbc185a45fcd7ba1ffdcffe2ba76630b493247772c0b4b85f0e08558f10d2d2498549d1317fa8d2cf470316e60a187dfb8c28e213cac90f896937fd9e9ca500ffa07f2630421c337aa809049c00d2af44048101d3d1870630a097fb6233fdca79ecce5d8ca1d14f3c00d292ce04614c8f81e507842026e38c187041941be1f04b8d184c458ef6dd9d639cb3652868fe860c75f21df8f911f890cbec104844c901f200841036e2c01488e2023376e28a1c71008dc48c248eec007eaa163070fb88104bb11ab54c08d23ecc861041f12a408c8078f11840c016e10e14f0f1f2308b8318405dc10420f93c3003682d1e375f0c0701e3a768c1cc0c62f7698213978316cf8c20790efc1c80331232df0c00946608202d8e8c58f07e2001bbc58808d5dfce071783c8f01d8d0458e203a7ae848b950800d5c08d1d143c72d122ef7eea34513672567b12d50878c0019413e788ce8a0878e1132bec7480faf4572c91b8db6af967ab44ab0418b4435a1c583ac7a04312341805c59e5e6096ccc223947d3eea6a4534e3a1fa2c0862c123e6876571f711b2f4371b820042222303041d0494444444444444444b6468e8d5824c61331730d7a33a54f08323fd0c8480f1d233d8c0ed4e347c8d0e1a5ce43c70e24a3870e2036b0018bc4bcf15d7e3486d6a44c818d572064760ce1317282b82248026cb4e2c9a8800d56ac828cef81001baa102244c8c88e213c186023150eb0818a740a0bd830057a1c04313c46cc0e43011ba5f833043d909113640136482164c7101e11b0318ac4db1c3ae54f428a4491f0175b2bda7357a7031f3c0ea28d5024788732e925ad3fe9f74a03364091a43e774a37e7fcdf208f9127633f91a0673febe52434e6dcd188fd187932ba6d7822297cabea96c539b6900f2123f7c3ac13cf438710204607233c18f901821048c0062792443e54a74dbd1e33f2417cf8d831f229379170b59ad152e4868d72c7101e239f0a03363491bc27c682d2ce535f990f21239fca056c6422f1d35450c9b2b3ec25f148569848dce077a7d2c71c7a71194080983362af0320434e2911d8b804036c580201362a8190a104901c049904016c48e283181f51808d48ec18c2a3003620919c3a5b715be5f731f6d0919211727ec7b73d22416efda655f7a9605b57066c3822492b27ad6974dcddec437ca011330ed86844e2e676f936a1ef6b4346246bb78a8a9914cdac16b16cca9c5b1ab18ab231bde2e696f48198213908a22eb0a188e4587b5932e36944d37e8c08313ad295a6fd4044c10c46d64622847c104494f1e3f0781e232668410b5090a8200505b07188c490b13958cc71934a691b8648b6eeb4e2154aa5b88d4224c52b0f659b4e4224698fcbaac74b4179741049f7e9d1caef4e93ce1184aa5e6975a3ae9a395c4b3385aeec4d0a44c2a8961e6122442619dd914a1b804890fdb39b33349ed0b88d3f24ef8fd0d6d77d97ea5214cc60640636fc908975ac6d8a7d855e99aaf85d7fde6df42131a90ab12abd67326982bce07ba0a3053d7cf0f851061015f010030448078e0e119191a30307085880831636f8909c1bf3e7c558d931e404c803bb17888808493e82888888ec303a28630fc99d622f74b9a668483d80630c1c2236f490a0b67de9222a25d9c11c23df031d417a043d7cec284eb09187442f31b7a93e89dd1363176ce021a9f4cc5aa6aa8da9d75eb07187a4ca9e6ecd53c7861d92920aa2f2eb6752bd241b75480c4d1b43675a8d35251d1237fba46ac720a65c9c43724c1dcacf44e698b26dc821296466dbdcfafff9b38d3824fcaad98b688c7f52da80436207952a2b4388f618f38684d30e96bd3398e651ba21f9d2a787905927de726d48d29cce77548f6cb02139851dcf3af22dc89cdb58c3729e95d2b865d79758eae69bc5a6b0dfda504362d4920b4a6da8a6936da421318ed21419910d36d090f867d7fffd1d9ed5e3828d3324658a7de947ce6be93b021b66484cb9bdadf6b07f3a2ac536ca90f8156eab840ef256836c9021f1455dcc3826c4f55e1b6348dedbf2106a357773fb061b6248982dcf1cdc72d9c68a106c8421296b4e72e675c5e2731b60488a1bfaa9c43dcfeff7d163c4c617927436d19b25e4e5abd70bc91f458fa9105a54bccd46179242b769eed2412b89d3061792f3996bfe94a3aa6ad9d882a2256a5e516336c64d3df4bf6b2f254ba64e5a48d6b720afd6aed94dc959c82c5e33e62a5af63a7b2fdd26a3c664caf6dbc04272574c9b35d26fdd4a574858bd6c1796376e38a91592624fddb27cac19d18d60a30a09f366c94a74caa94ca242528f5e903974f8123d4f2131e65f10ade8f53a5229247f29996536df96fd1285a4ca9779ebed2590df1cd880427290f58a96729a99474f480e3d5af36cca86131235a8dd34322631f3add8684272a8cbb853f79b3e8e3698909ccc374599d9b01da18d2524fdfd9a89f2741fe22a2131bcec69ac0f17543047602309c99e5a834c799be9d8d182175286f7b081842499ef7c3cecc77b9e6c1c21d14be87c3246891e211b464814b9d821c493c689080216e0b05184241d63a525959dc35ae8870fb64184a48d5796bff1e44b25d9184282ac39c0488e113f954b29ee34f30b937f2e7996625029f71dc4f04552ffb99cacf4c22ccdb0e93ffe749a17c9f6a6b3b6a9adec5aef224198e63e9db7d1ed2d2162e822f93253f0caeaa7f2fe5c2447b554a1fd3a89ba9a997f181e23e82b0e62e062dbda17f91d3cb7488e95161f84af39d6167f1e3df5b85597f1538b045156a61b639b7ec8d022c937e6decbaad1baf52c92942add9b82e7f40fb12c124caf5a944c32e9edc40216897b67524de7a0572465a5b060497fae488e96bd7279a76eac582b9252e6ca8b418f32cdb118ac484e49d89adc19b3e0965524587cc55819af54e5716084a02a1c2d31d1b0d139e72f15d5e5cd9a2e23544543457269109dd57ec783c59c02b9fd6141a65395b14da1481519b44a598ac4284a460979513fd34a8aa44ed25be542651ff9e620c628925f2c97768a17e476174592d4be34f22fbe3a2814492383e6f5384a2ecfa0481e3d5161c52b3ba5f0271ecd8dc15f73aaaca42712fb72e4b52f09559e5a4188d189e48f35225e7f2fcfe39c38d8a629b526feda623691f4faeb51c332ad7fecfc2086264ef329b7076526924ef766fc18e244671026d0a04644c3ecf644778904ede7ffd79d27a6b51e3a0c10647d10c312868bcaad499570377b2ca59e478f22258c294b3ffbe76a10a54924997ff2984aa733ed31922899501e4a854fc96f8118914856f3b68df59c7fdef2410c481ceb634c2756a7ddceb1f5427454084ad09110e3115869f8ab178fb11c5128d3963ea52e79ba1c86071b101f424c8bd188a44e7d3129d9b86ca22264088f9132800829c50373021c63e0e891021c63e01803c70fd9616080630c1c6655c69700c718380ac8e708624480630c1c2dd0523f0c8f91c288d2ea43456335b3aed243c458445268b615eb1c56c3b3e587188a48cafed713ad4139b6321109273ab542dfaa2d543f50055741ba04622022c9aaef327dbaca10e3100976c94e5f3279593393632b7d20862192f42b7baa2c7666252a44521695e4f456c7ca4988046d5dba1b653ee52a9d321c2e0841d7160a6630120022883188c40e1793888f1e3ce634c7d648c5400c4124eee6b0dbf962779a9e635fd0230556573c74f40dc4084472cc9a29c96953e65f95b383188048be8e9e57e2e78365bd6110e30f89c1c3d7765059bf54dce020861f9292b2df70153a37c7a5b620461f124eee65cbe2bef241870fc9699a7a74f6ce5aa5d741313688b187448b314737a93ed7b6a8410c3d24bced9c9a8fda733ad282187948d4b87bdd78a32107f1f1e3c020061e92c39ad241dba70efd81fcb0c2e18210f4f8821877484af23f7f89dd764850f24466fa87374d6131ea901caf2e9a974ca1bd0fee910211912038f0e123c796410c3a24884b5149547c2bfdb70a62cc2131357789eef2b2c420861c12b36fb9c83d3bfd8f6299418c3824c95342563c1dabed8339b682f8481d8882187048bc685a194df3e9eb5ae920c61b922ba5f26c23ec634da76e1162b8214944e489ca4e99392d1ec031860f0fd81ec4684392a95dff121f65cddfe682186c48ded29b4dbb8873cf3eb120c61a12d5f2e6b5cbddf466043b7698b382186a480e15691ddad4e61f3d1021235558412e21461a125b4ddb32295577f1d190181f4764a71679ad416748ea943b65c5dd69a8dd0c89ea7ece9da45d86a4f09af74e67cca429244382a5e0a3626bccfc5ac1c18e21de3b4c0f20295000e0428c3124451b95ec536adb74713124da7832a1c5aee2066518927e4478144f17f3590443528bf80b7b3ae97afc0b89e29ba556940a993313c30b4942b72a4751719414bb906cdd25e449713fa5f25c48d02e2a7dfebe680ea32d2466ca8a6332a74bb11f2d24288bd9fac4b2a84d791612d3e8d44aa64c4ef4060b49a9f9fa1696ede5bf429287ba1c9bcf0e8fdb0a09da9ff2dca7b60ac929eb695e7f950ac9f1f3c94f9b72888f4f21f164900da1f5eda54c2924fe6bbac698b011a7282466ff6911aa74fe190ac919cf3b469919dd2d3e21e9c44919d5b9a7434e481acd67991d2a987bac09c973d5d5c9b49e7b8809093acefa58cab92a6c969014bf6a7564cc59bf2503319490b0ed96bcebcdf7ee4f4262bcc80fa12bf8e6899090789b29efcfa7083d3a42d26c0eef2d3a5aa63142c2bf9b98cf94234611123df359fcff70994e2e06119242ff2817991b2ec72ec6101253aeb8e229fba3e82d86109264f7f7c8a48475d51d8ce4da8bbdcd5dbd3b36301277ef3ce34659cc60ff22312eb509958f9edf675f247e87eed318b634dadc8b04cd3f6a36c7a02da9971709c29210537bfa62a87717c96567de69e4a68b04e951ae541075fbd6e622c94bb48b1a1d73454971916cda2d332abf4a577a8ba4abb4c9fe54e80f16b545d2be9d8d0931f122cc5a248b570cd12958524b495a2487e5cdee2b1973fecd2231ec2993b1335d27f5c9222987ddff347e29f3bc58245dc8d6a9df53bb18834552864c515d8bb12b6aaf483aa17454fe7c39cc325724a90b59f3af5b91702737c6b28c5b32ca8a8419155a974f83ccdd2a125474cfa53fe60953952a12e4a89c623a2925a455a9483cf94977f20f2a1253b8cab1f941eca64f9194d475a5285e31c1004c91e81eb3c4c27a7bb65230f31d1e166cd3fa4787ddec1117d71a0029122ca3666639fbcf0d60144965ab214afdc5bcdb0c1145e276dda53b15e3190c201489393bc2a4961096a2840a8a84313932aaf666e711ed3e91bc5b194545dd2a6da11ab23218802792539d6cbaa991f5387522b16390953e9792aca07322313b74d0f3a6b647a32303d84472cc9362d9fb23bd633491149ed2655bbfd63a9a89a438efd85227fb016022f9c3536751b9bf446266d2144b578fdb6f89c42c514aa8a0947c9a330403a84462d0b33c8f1dea0e0c801209b729423f75dcb2701249294aa88c9b3de5724712491b1a3288d2f3654113890479d995a6c4d58edc20916cdaed3ff65a8f48f60bf27333ef4dc9932312ad934ab5cda446247529ddfdf61be3a81323923c688b99d5639d635a4452a8a496e4a7140d31292249c45cc6de936ce7522292e467f516cd3969d01222923d2c542e1326c468e9108996645b4caaed4c8cde10c9e9d455c959126ff2172249fb8611eaad1bd27c4224eea824caa45fce58428348da7953e17f533d0921412458bcb8d79be4790e428148f0537ae75e71791f048884bd9c994ba7c4881afd21713346ad098b273c8cfc90e029beaa9eb00fc9bba2c9459afa942ec487a4b4965257e9f39e7b0f49bed6165cdc738ef49098493d5b6851d57a1e9294bdb5274f6a33a878484c5b3265c87f3e3d9e3b24894bba19ff946750b243e2cf65a8d2acd33975483a6d51f11eadc9733a24650a7ef79ff428939943c207a56247df2e0747be5d683da1c72139c47a6ebdcbc6cf391c126654be1c73478beef91b12cb4ecce475f8dc147743c2290d3ab7685679501b12e3e94af2b35c8ede860d0997ab63847ff78c69d69058ea76c3684a692c346a48caa35e42bfb6aca9983424e8fa669dcce8a88b414362f49421442f36c7a43e4362888be551b3535b509b2169bb325b63b40b23ed3224080da18316f5712a6d3224c95b5fe6e5b4592c3d86a4ac1ff79bb3ac898e18922bcfc94a4a7e0a9be630248f3aed8b616e2737832149affa6d694eea77e62f2425cfa333d908cd95642f2426531e4f6f3b5564dc85e414ac4fb7ff29394a5c484a5145f34e796a50da42625ffc94b36ff8361d2d2449d3e1f22909d941be5948d41d8b3173a65bf3c54282ce24b4a9789a84b6f70a492363b0ab1c7334ab6b852425a3a89495a7b4745b85a418e7c9fc47641027a542d2f98de610a293fe904e21b164fa182666368d46a590f4bad9f306bd277bd4282426e527cc2d99298b291492cbdca2cce7511d9b7c8235627484be3a9d903c621e6aa3e6bcb9661392eeaa3e8c67ff9f9a4c4892ebb97df409cb71e6121254cc435facb22cb71212734eca44bd9c84a457eb95953b25d34542b25f1cb9a3515f737884e4a09eb4258fa3952b3442e251bf3f335f84c424846856ec4784844bb62b7fc13aa6f1063084046da6ab4cbb299139031042e226d11d35c5e3874f309244f57996da75571c189f3a75da1f63ec1789a5b92957e5ec1c35f345c2589cccdf65bd4852b567a5b456f430f12239a8ec9341a80fdd9c5d24d8684dbe17dadf575d2459306dcfd94467bf2a1749d2de828e39ee5c12c245f2c7671137b2faa3e616c9a641c36e97d0a3ac22005b24b676caa1dc92cdcca830f0c08ef3484404c8ff08420601d422b133656c051bddbf595a2498bace0f4bb3ef412c3208601649aa937bca183b64582e8be4f2d09ce326bd9d358a4572a6e7d0e9c48ca9dc60915c41b8c75892ad7b571904f08ae4a463ac28a21bbf42ae48d269b38ad21a6266f3562458c86556dc303b716a4100ac48f4100df2bb2cadb2050d02584572ff8790d5499cf0f0601504a08a04cb9b2bd672b8dc5ae7d8e2f580005291781932855cc5184bed07024045f2bdee6e327dd9b2a673ec8e1d660c211f822c08e014c9bbf7a2bca328f76ce6d81a11f2646c09f910404100a648daf97c398acce09d934a91b85d6954ab655c4c132912378ea94bba962e9ad02892536ff4a539759e4c4814c95e2ae6b13756ee1f852231c60e325baa145024992ca97e7d327d9ad1279294787b909993f0f8224f2426f1142a5f9d1dfcd38984d1ca31c68f339e520e2712646a7b8a29db94936f22493e77be7bb71f65724d24a69af8fc95e65b3fcf44622561ee39f6c5ec6430912cea4ea78faf9a52d25c021915a3c37ecc5822b97a7b43c7d9145a752592743c4fda6208254d892991d8a5c3bfe8e4195fa49348b23079b3a2766b719544720e391ff4c6e7181b8d44d28a4c979d534ef5b3422259c3c22f59c55476e72312e7c46f4c44e664c9744492a8779dd7c8e674c946246f4ca9a3af9268ed9111c997f629e69613b242b888c4d49a3b4787934b1b1591e47ff75731e518b38989484c396cca9cdf64574444247de51c5c3bd8e8ecdf2192aa55836ae639251f3344b209d77495bb4c9c6b8548fc6eef038dfaa8048e6543b250200a06436150200c06192ed701b31300001818201146a3e170200babed14800350543c522e2c18281a120b84e36030140c8501a1601008068381c140301006c2203594909b000a2a11594e3fe036c405c5883ddc3e418700be1e083f5d1086ab8e07a88343ee8e8cb125bf45db1c8fcd9d385ea24a4d2038e40dd60903577005fb8d4be833db3ec7cdc27136f2d800a94ce3c5c8b0edcdaa86fb63334610139862584ac57612dc106b7900db133bafd8dd2dba7435503fda81d8b1ff575e2e47420daf6e4bdfc66eea1921dee85d1ded846ea499ddd269c0bacb0172c7562d6fb846bb08503e277d1aede6cfa80314995da14124bc830706efbe5862cfe08610155a92f7fb130f4b22a7076663968ad9183690b6686b3283b2ae4f4f31331574f08c91473310ceb70cdbcd5cd4c1170ec3402fd8f11c5f58eb3d31c6e8182056479876c4cf2cad7f45d5e7ed97e1374dfddc1197a04863f6dbe22494cc990d50cbd4605eaa30bca97c1b4ea7df3937103de6c4734c19546bd28aca30f3a03cd9823f1eab1966190e9b02bd0b7f2a5ea4384ca0d0664c7223f884c7d4ced56b49d48ab39e15ead14b1c6562b48fc5798a16ce2f9f9287b7c00f4d981990628faf42b60026cfbc43cfba7bd01cf5f480ffba0bfb0fca8f441540dd341f077744d0d115940d8bfd6292b50cff538957f1b34940917bb2323a44b2c6c085b52d69a874c3551fa7c34cf7ba023b291801020d57795a30c82a78bcbb0c4753450b2cbac8357da429b530a3f0c7be9027d4652fb9c97f3f9491a3d5cbd0c2807f9af1be9de387e04ba5c0b39b56f744b652544f67e328aca0d792d6981bb2cfa2d6a16103de335eb23718350f17295411ca3d5c46d68ec06ce6dc2022cb0dda990b8ebc8be83468efccdfd065038c317ebce09a9da0dea441e329eec84c3821d96c33149579da5a4f167062bb35aa7d26d3178e60f17157445e96fdd2d4cdb5a0553d90415b93ba6b1b425f068c6733c38508ef5bd7d041d58a0f468371f8d82b06c4c28c6ac16317e86adf20d6734a414c93ac77ad604c6ce4b8121e405e70383c4a00e460c4c2e718bb34cfa9342153ec165b389e6537d62c7205de576e1281d24c0f151c823c23c3496cdef1cfe0ddd8a3e8fbb690b226e8a4dedb701a8a36e8821d14234b9052b5c3ae69d0fe9e914b794d3b69cac675319a6415bd4062cfb3a09224480fea802eea55c6529537bf92e60466fd931cf454b58189c059d40fe1283a524c7dabd613ca246f353f0c69078ebaefabe402ea8c3479eb055e1e009291b8cad2020035736f4f1f45c58d215f33eb936a9438a23663136cb37fbffbdaa902fd02017cad5f095f94ac0b6625944f31c614c72c2b7dc8da0a04c5d68c4f4a3736766ed07dc59bd0a77888facd160b14f6e535d5585caad2092b6492366736554e445840aa0351f09af80f3f8a8c339838a3aa6f12740a87fd322110cf034a32295ee3a5a598a97a09febf264aea274a1ebb5d27c8867666b5e805e7ba4c8989ca31a6ee8cce4b6b1b5cb3043af403df61a9d29e6d715583305d9b8586740ebda77152302b6070c4de573563d7f7dfb4c9eaacff1828d0e161e62b0bce99bdedb6a4260c71314153ecbbf32255f90434bf22a393723195a140f97ec0987bc845d9ef95fb73570415f6474d0e1c0743ceb8407950887a571228bb603a791c38945d0b2387a23ec016fe7f0bffa70bf7bf318ce4bf14c61cfb87625de4dd2447d5f1f6910661cfeea378df0c67a9b739333013e17f95e14fdfc9e07b328dee334998c79c1119f8b5376301eee5491a80f5cabbcf98b4333b095899b566f7597c76a7c569778a38ed8a1011b81732c0f5ec4231899ea6d0a8693a05354d45a012f4042a414fa011a44d390285a7acb7ae77bf57c62782c554e8b723d9e6bf726f939e0c7aba282f2535e71299e0a535b2126fac0d22f35472b7d24f17edc687cd76c34b32a0a348f37a381868fd75fbe8030c0488a175a0b6afff2be2a8a53d152bab15615533bbc67d5dbadde7872c64ade91a588d40f61a852ddf2d333e112603178abdc2a53b20f9359b9b8708970f8140d680517f068bd98aef3c36167d3b9206c1d3885ac605dfca6bce960e11690b3163ca49ea967dfb1474c169dc8b39713c92417684427ac48ec0481c35233c624b34792ea55a06a989f9529dc9b7e94d1d6026449f6fb8161a9561374feb0840ff486e097ead78879b71883caa0f3881f7183b0e4230248f6c08813427560542c59101a191d6c4c402bf20950cd9a238a4452c0888449009e191069119e100c09456bfd886d14847a2f57ab29843a824af5c7ba3674f46016ab9e1d956e05e49260e6ab2214cdc9d512be01316d214fdb5282000ea87c3b2fda6d6ee28f8928445ad32cd15f764ad894e8b613a9bcc2030b0fd86fafd6c44c6820d8db0aa9f81d53e41dffee07a49deb231b711902488fc7705025b24f515f3c74b055437522aacc418c438af9e7a0a3dc2247245a2e215063c35025fc0892687b0b470652e1b2a3a9c04c185fdc587ee44e0dde905addd38a03a5033da12f142e344674b7c005734e44f558a31a25fa1a6599a9ce2f8e10471d1684c34464cf391a31824aa3819cb1291991b72c0a6fee4e58c4d4f4b6f7db10944bcb303f0f3a6409ee7e9a91ee80bd494d0a06558f05707cd0db35c5229028ae1dd8298a8eecccd7f4ea4c8a5f153d785b44a187311fff04892a0894e49a3d0a86950b5ceac154bcd272d879ea367d3e1e8b9340c0d9f86450357bfecf9517ec9d25af4667a8bde4a6fd0b1d39b682c1a3b8d4563a03168cc34362d338d89c6a4b1d368d2ceda46b6283bddc6f6387accfae3d82100950cc183dd6ccd25c0e93e136657c285033f2cd442be23b3225f49dc1749fb96fe995648dbe426b999dc426e90df5cee30b749873264ffe438099e0427c193a048c48a3435685725cfc926e423f9844c934b04718236f0dc3393198372938941898913dbc47689616225312d653331293176627062e5c432314d82495005c9402d164f451cb325d50610844016ca2be57579893cd9464696f9cbe430819700258012b804de298014280a6c0235014d80df1cc190c60f3b4f67a50fa67f7a7402fbe8531e68d73c1790e1bb1216cc4d9c426ff1ccaa4d98790e817325ffcb5c655234a99bd4261593dac46acf65a899198289f69a5f3203a20ebf022b0540817702802e18f67564f7faf6c818bd0b40ab2d20715da9ec11036e7c18f7f8cc07f6689846dca8c3adf0df6f07afed2e56f7801dc39c0600a99524fb487e49607625dfed0814486b4066ad2579a38c2abe3db1111d6dc6ca067a688bd160a03119f71f8e00068ec9ec0fd64440205504d0b658a346a52b8ba68b1db0c884c6c7bb23fcc8b26bcd3cb746204128225bd5692548b4116f434f4b6d0f236d903e55c416da6145a6b9351a5c66d09405c14116565bcb2420e25c111bb6618c5dae575886e2385d34d89639cddfff71830d39ed6f7fa1adcd2c79c83437986057a06e0a80ec6f015546926fb7a23e8757b7c90a47692b7bbec3cfaeb552af6091e8dc97821fae271081a2256873f6779de8fe33d19969b5e6dc29c96ab0761addcd50919da96916a7755f47ce505a00b37d6c1472b6efe01dc20f00d9c6643f266de30d7a0efce25b81c0b4e8555c9792eadfa168b165cbe22b986616790ed31fccdbc0bb7c3af1cd946aaf9b8442cb53ddef873603cb9b10588a42e8a78893db3c5c40ad57479741a3b0cc2c742f643af31e40170e4184bf9b6e3ff7e1bacf6e5f11409eebf13dfe8fa24d4abf0bfbcf96463bf6214ce7222f55164fd7847083dedd6423d96e33af160f6bb4672029861ee89fbe520e82006eb63139ecbc424c2e15986e83257c69ad89b5342a738ebc74148b3e088c38bd5ec82c6965fa45e28d52e9137b3947ea3af34655b8191ab113baefe291b85c0e8d984c680cfe491bed936837dc01b63228af7215fff5ec15e6a6643849f1d4e9d883a02baecd0cb63c777c63407229a7bb8857c931cbc4904f6bae8fbac1632ba0872a2b5991884216ea6ee766ffdb37ae9b7672d6b5c8239d42d201ba8a64d757ed27a61f168b15e0a516015b5c5194c4599a26357c567120cd5773b00ecd633b4400c26f9f77d8a4b05701f8a0c4c6bc71313b5b6e4524bc052902a9b6c997e363820289d1dc632696254aeb4e1e129f3a3bb46611d133cf83f715cfae7136fd87c3e3aec49094c791fb7762b64add5b0bde87d0c50adc3f982a04fd381e3cd837954c008f9f9d850d44391bb1d9b68e09bd4f76ba9417a59d11b4d1cdb763e3bf9a06bca4e621b01f0c03460eea1782e8b553387ecdcd839b138673224e63fb957ec84aee833bccafb037a150497600e17833528ca57f224eecd31ffcb7220f8519e6d14f4cb26da223ae2b82d4290040b753c9322f35f8e0b0e6991d01b2329b41f46ad3654b3283e87a6cc3083639a9489daed40066d9c23986a66a63c6ae6c23a80394a0034a9f6dbd8e4c2da42327786308c7bfe7d3bba67426c1690901eca0d21483cfb9b384ffb99bd27576f153a1af255ee8b539a671b058933c4e5cdce83ac114d173d5431d933bcb8a691fe63905bb553dc8d30ca9f7b04c246f3ab337fd4cb70440064bc6b568373299e05de3086b1b59ecf853a8e9fe95a0272af00a5cc024b26993eff0c1eccfdc14862c01e865caa4ed167024072dad6da7fc69dc793b498720d90d2f8c91903492dd15a642675c85eec3a7a628184de929566a87f0905198fa648ac2c6d03c0b5cf03ffb970eaa2b1d344cb1c5c379ff215e53bdf33c8d58d5ebb25d499d4af834b2d36be1642308aa5b5646fdb470816d3a9ee04b5ad1aaeb5d3b2ba61496dfefdb3aed0bf60773ac7087e2a43d2e0b1bb755626c574f0650d7a3c8b3894b4f3d88b76159f840c25a2ffa2878da46d447fa6fe8752e52b3a8467886e3a83770c3872fe18480729e105a7f144c10ab9194731eedcd25aa637c4f9a0b24b83f742e5551c449cc18b5a3437e6c233b93a50c7b893dc5bf10cb028a5937bd43c890f2da379f0e146a42504407fc90dae3663aa2775adea1687411d75f371143191f53ee1b4e6b9218fc078150b8c94151f1ab18e4cc449716004eb81287c980e43b115287bd8f9199013f3b51fe8ee440ae4ca7eb5ba52295f7b76c2ff0f52ad5e1ae476e1577e93ee631cd16ad0f2e14e6a1e2c61a254319735ffb51d9454223cd598bd22b29c9faf02ef139cf40dc9f9f421c980bbe2721df6badbdc74a0bb46aa3e42445e5bedcf3fba6019caea8ccca4f7e69175ec2d773ba07fd16471dd4e6e4976b5272d5b026245eb010c89843b4daea962a078fce7c1b5ff7521bb2be81b6f787bfa990c178a5fdbcb8876a5f75d857baad96b1f5c370a0383e6b6ad7a6ebbc339f31f785976de16780e1b053f71a0a579b9ab75c6ba8ea481f528203f436360e9ccaf11f9028af7b01ee2e86155df3d028bda2bfe4039f20287e374879be25db565ffa9aa6f31862af687134526f105b598b387ceff6da5994994146def61ea236852e5f4bfa09bc9c243a91a1a37a15891cfdd99ea0cc0656ea058d6d94a656bfa32d7e3e4f5279add10d1c1f83c4e30e27e892d40f866ee0b05201285a70513bb062e2cf5accc068bae1210f36901365cbf91d27e2aa1468a120f71c30995b56aed38c06dac40847da3714e8745d3137a63a415452244ff87645c8410dcee89aca694ca3a19e3dc993bc4020d6a31b265dcce2374047aaef9afa1dd704764d2f222cbc4829e4ec8812413dad923b4119153e19d02b535c986cd51a80fd79b48421196b801845a12f17c1980ba34153a77ec0717de3cc001dc7d5225b7135e95e3e03680aa677d53ca6fb6d57d4d9575763ec408f27f6f5576aae9a02d5ab3c5157f14a37c3f821f302021cf66310da96756c11bcba01a3964365bb6d95f7ba2a0abca08f7fcbe497553d0931478172f6f5c04eb4d6525497767407a2f0cd0b48b8b85c2e6b147fa0fd97a16c8277f90d76afc7b0873c86ad127a4ed118c4b433b96c0a84469a0f5198278a2de8385b4bb80b491d616a76f0cab05af30de50e22f2929bff037aa886622724f3fbbddf749624a03c0e6f1be5cc3ae366b5d4ef3fe05622d1cf1aa2468dcf72f3ad29bbcc11df8ec45753b8de94d3cc73aee7f048f89edac655533449ad1cf13bf6da694ac7b3e2c1beadd159dcb59f5ccf670f6a7068af8b933078e637b992e827ca02c455b6fb6eaacf656086d4dc99c49e381fe7d5afae063308c51fe7c4ac451e6353b9dae289bab548922d8bceb2938638610d123b4eb838f567d30149be89fba7969a89a820b18ac4b48451eaca152e9cad013c3cda940380909b0d0b7bcef97a1ffdf8184ea7a73b3925e4e25a85e6e9c452f34daf2a280f7cacf2cdfaa0ec47a141b1031285526a032a3340867e4043d706acdd7d9334ea436c431f193b6f3ca28b3a25d4feb42d12b1ea4a0c6d4850000accd266c5ba145d9a2e07129d3ae5c4b7f575ef93c6c6364942c6860cd982213690f1a3f86593a302497739650003360682720a224dcbe9100dc42fd85294771ec0ab31a3cd5f7381811d67af991328e36b6784f47389311a3724d28b30f1008e5b536829177fe430b80a7673b596d7a9d2620c6cfe208a26f2ab56e115e16b03538e1904768c9abac739c3f096fd75417888f00d392e189e711647bbaa46adca19ac3d7f59c73d76328aea048cc5678f91b7aa361650d85ac9250e4abd283d982adaf48647ee227adc5e025e8648cf0c0c945eb1564d8842c1c62f5509b2a73e2780b49d4714dc7471699fee79fc3c9700c4de3228645584b62bd66cc5b5475961204610ecfa58a58d42ffd4b766a879c32536731f6b5a8139084deeac287870d92efe22cd91f68fd37b024cc2144d39aeb44a61bc698502a74821f967d3ca80b1765f16014379f1462ab228160235615da91cc9841cfff2f9cc03d74b6a235ba63b12c30f497dc9354c12c25a13728e90b81f86c930cca7b9f90b6d16d4efccf151980af01475cb0e8c1b2a1f8587d2947005ad58bf71c754fe727e0863650a6382060a05fae1c2b2f4f777497bbb859263ef4bd4f0756c05f69475cc38172e835a0489e441997af0891ff1f6515b99dffdc1109eb349514a4b0d55c2841bc562625b779dd64dbf8e72217a3ff4f2ad3bdb7e9cf4bad24952a24cdf0afb9477b54174da07fd5e7583ae0c8eff0041e79ec64bb22226b71db2f0a173a0afed4485e0fbc835c936f131d65abcecf0f876b2758811b8f059fe113443a4bb6958b238b650ee6ba02fc2aa7eb4d40f3ff88ebe8fe69c9bdc3a15b3884f64361782526f01120636545fe57167d28a48e66de7e422485d23d7f6ebf18fe838e2300ddcc9c6ac10d3b18bb54e51228ca909e772db8e19d2b8dfce1101fa9e014ab322656c7beed8dfc270229f221308cb81d72d3c300d743c27ce9217936ccd626a4f03d3f37904f5a580d2a6ad990af57166b52306cd21c5ef487958fc586044d7d37200d56de69a55172827388656baba6b6912da9b2c35024bc629adf5cc4241eabda30e0c35f2d79a09f572ac7de219619231d02aa719b7f1d91f6b990069d79794dcfd58469082832daaa07c92e22932b2686d333250073b3425103864ff6832d778c384094a414138dbdd04045d3e38dffe26965cd20b2c30d151c9404e99b081c4932b38c0b542b328243187c16addaf1717d5bc051e6c8144a1d3537140b21dc26352566871412ea8130ecdd8365a7cb38633ea7d44a8e37be7fb2c0c2ef99ca475ed5ac551f1550c4e2362e6219f40f6ea10c392848c4880db00549c707fd451f61f5276095e0349e1d0782d0edc7903babfff1d5bae7e75535b5450551afa3cc14a424225702d8c05b91392848fd255d9ab035078f936a2edabfef5869ea56e0a2dd48f598b6f2e9e2df57e9fd2a9c6c2c0a1479512f62e95e7fd536b7c4a8ad4578ecf2e5d26632ea36e26e9a1419846dca9af858d2a0a609a2e096fdc6f2c3ca86db59d9420f9ec66d68188df4460b4e3a661856923d5cc9d40253344ddb175e02c7a077c464d11e60c4d519329e1dd21b2774b1a3c7606a75ff44b1c990cadd34e4724f14d5aac76aab08b2a07fc8988b271e1fdc3b19cf52d326f9dd960029d91e2ab7a80967ab34c0b82ea5aa5dd4f0cf27dfd33ff7f1bea3add79e5fc15a5453ee0ed8d83a5c3eb3cdd07ecb294070ad762d3d63b900a4832a0b04034d31e0522bfe031f5004668322d7743beaed9048b100e93d916af872dfffe2f2b0a077a518ad37152e288e5862d5819434c6d0dc03b2971312d95ae65e093143765ed682adce71cd30f2985761f81e9bb4a8ae5d87ba466665efccc9811314e891daf1266543ad374ab14aa259ab7540add745f9dcfe42230ca1d60606f8905a148d2a1226075a6101d504ecbe9ba2ce9ec20b905008f45eaec91207fbfa02465bbd3f0133c789878f5f7d32a8917ab895e19a8f60f57afbcde818b2407046cfcf63a9148670fd6ecbee73181264a3d87e1831eac0d336770195fbbe8203702029eb97bdfb053ebb8c3faad48bc6cb0d9b82673816df9514ef6716dd2c04f734417297787d72f2cb15638ea70b2673c87f3aa5d223cbe4391ccecf00fae4286ece387ffefece85e9b08ac716d772e616b38332c2b202b83f1c212c7121e5607d1aa5812961843c290622018bbd08b1c041ad559d4aec82e6a576417b52b2c55ec1a4639465d474da324a3d846a1512d53a551c728cea0aa11aef20c99257b4060f867923d8f224e0096c24b1b4df2fb522cbfddb3bf17007ff24b14600b683e77061d8b4aacc3386a0b2e36c079ddb31ca8e00a0fb63fcc7dc4e18266ec0c96f15b08cbed417f857351cee43e75682e1e079f391dd5dde7ab49224a18394656a8e36834de8b1f9b4574d3649c98099e681116094e60448258089aa0675ab5335430a1126bc9deaf2b6eb78dd2f92a9a37ffe8193601b6c03f921e9bc15fea0ccb05a41147c60b6e742fb0cf94c41932f81216b1c181ca2cbbba75161028e64abcf7bddb6e81804626f85d34987e5921a1aab09857cca2cdbd76ac711de0541a62a161ff9212810ac74238f5f0b2214a860e48bc9a789b042a0904bdb0b69f9f227ef292669f3c1bb012bcad269c1d8d70b3bb9432921129f3a02b9cc019d43834ddc7c147d16ea15adb268296a2d7fa31e51a2ca4158f74d97c1362666625469aeb5c62b76577adf08ca7842c149611690a01a4816fc20765dc7dd43881fa34492fec9f93af1705a101e6725e9204a40668469d8c3b6118d3b36290e67c48e752c4b1bacbc4a57f9a9863c5c0df4d2c50a22fa9f38d91ec52d455c74880361eec583d70b577814d30ea4f08fe70b252c41aa6f00a297c99c2cf783a25582b3657714914757b7a186b7ffc91c7df07fa2bc8f3bd336629c0c2a011e224589f6ba04945d5a233528d931608ba4510d10390c37e2084268d6a4a1d121792e4c0965ad0776ca16de7eb5cf814a75b791738789b85e5a8bd0a11eef0f05d5906379666c4ff2b414a48da2520aa551f52f85288708e7fa675a02e0bf4422f2e00a298dcfe5dc8d25472028f66ae568bacf02e79a63efd72f023a8ad713d5a5860007c34de4e325ca51e8fca339d8b6209340929c7535306b18d26896910bb60449ea139c96970809734ec7f60e430653ecc16ca4950748beb6b2878ff62ee7df9c18bead36a55751bbf87219c753e1e5715c885a5be19222abe475bf5288899a92ded7238228a54d6675d8df3219eb87a1248c57eacd50d041bc520db0ea240851bef8ae533b759a6f117bd874416b043e235e862b9588b409953bca74143ade54b2a8aff95e019652ca18ad2b2d2fa3f580a22b7a21b1b59a8d9963881474a2ac3bb806600876782e843070e08f2342243f68d4ab1c1de52d9da0f7571be9eb414387d571dad99ab7b8159657906854af847a5404095eb08053fb2294e726d9481cbb4f0effad24410b226b0748d104f4d0005febca76a0ace6a490ca0901c7e703ea2b3c4755b269d18844f05579b008d796ab8fc4d83c055bbec7ef4b696ddd31828bcf997289034a15d8abcb13c334704c51f6d62a1fac8d3e5f273716f8ca2881660981b109f7bdeaacc1a19638e6aed96683f88a034b2d396fc7416ec8cd9b7444d463c6b14dffd107cb069af158c5e20d3ef0b6edfff7e08b93bf99dd6d97563e404212337a250f362be252997f3ceb239ba588a0db57d096e740b3512eb765f375e7c59071f9acbb14f637f31f7c9cc94088d017f8d054bd61a6994863156f67639c6a9970d8ba5c9924010307d1da26225ec95f10caca9986984c851a4ec756e00c43b957a47978eb184e687fc7680268b97be310014241403fb1226622d587cd7df10ffe6ebce22303e46281ef3a5d81d590e2f421fe1003480b7d52786490971f2544f0a20535f30b453dd09ad428427391621f839613d293d67dd7095fce2e1dae15812fd908142062d6a519cf9417537a4a6db435518fd14d79563e1e6cafec79c2ae0aa41ad112d361e02317fc461916b431b8001d0961f1a8995d9a0fec5d5c0752c1f9b5ac82950d799603dd1248a852a47fa078e36dad5794156a90d9ac3b3eedb10f20e931dd12e597b660bad43a2fa72b5af9819d5c2c8dd56e1f6dff64953e0decff826edeb067a8aed5d1ce62fe8d27b379361647cd362ad8693a900a2025e80c6feda517e5303c08257cd5e8a96a89822d37ff4e22ead35566ce86e6e9df4b4887d6066d586931daf7b400ed6d40d4b7e6eea701993abef7dafd355b5a1510c62a3348c2dff790ce229e86f5c00039f10f5df15f8b0cc8fa93fdad7d115ea3d0bbaba4db6df89a79989bf3599d7612240a030a59cca28221d29d49d9eaa9de353771266216940a63100415c955a0eac742a93499571c210042902bec94ece3b17a57ed3543d291423130f3a7e61e5a18324cf73934f2ca90383b88df7222557092232eaf467457380b127619ad64cd6caeeb50be11342766b50732ca8ca2a9a658e53de133a7af1ba8f6ac11d27bdac07af3e5a903d638b4fd329c15ac1633834d4b5b9837689038c6e0fef755df4b517d46c74251186522ea3b2b3ced5990eaecd6512c946bf305cb02de745dd2043b8e316a32e45b0acf396e550f2c9183287ecbee6e4cc79bbd8624bb58c649656a6735b69dd88b191e7b35ce2dcb72c83507c77b40e482ec10cd1fd28ba28c37e9d99f6129a912ada3486056d7485d6877dc1d8b150e503f31a6d3756cf638c8983ae3713fb121a52791ee6c12cfb7732a9542d6c3b6e6d7d7a23a1590986a04afecf98dd1a116c73fe915a09a784885f5aa8165ffaae04914b5d5221e92851a3c12d02923b995d20f07f6272995fcba1ffcc1e95f102760d1d144b6bdd8a4e5747453b90c80f9738145800bc4a428d9d0dfaa4ad08cd30372eab494df05c7bb381a324b71adab5e4de20d2801a85cd0a9ffff519c10631168f31ade23483930b51e6f08fd4e2f881f924fed330e8cc00a48b4a8c6d615c9c89dc237e6483785fa9f2261f545c35f2b48bacbdc6680825f99d14fac69cc9be54977e2720f65b94b2989fbbb1329e2a670d3243ae022608ab1ead04b705d842d4e0f725b7c11ad072aaba04c9ee75b117021f2bd5fa0b72b9a4b5bce954d597458f6455a5e11a01ddd093856a722ef1a438369799e624198888cfe1f6a110d603603cff985b5a0c4d56d74bcf540ab1e128d8504cd0fc92cd115851fcc57336e08c3912ac9d157d999f479046dcec8f436531762fad23dbe1081c28f4b3054e024adb3322a32627994981a729cc1da93e5bd8b9592ddd99b464c712c0baee7e931422a05d055e106f25be22b94185b55b3dba8f6f3c5d579d17e0688f4697c0162086865c8506632e7c6619e86504a435df71967c2f40aa87658fff813006ff97c455fe600094e4af0ca55aa7f2d50134c2c92d940f4d2874ea20ea52d6c31c6fdfd779566e7ca9e6de360fb247acd186e7b55ecec973dc258c984b613b908292292ff040d011f87ed293c3825e82c840a67c0981e5cb8894c21f83074eae0f333cf2378d701337ea5d9be0d598141fa336bf7a229d1c2300d1db81f5a491d2c3ba5c283bf6424b764b7f06c80a7ac6e5be6d116495d6b808c509c9e53ab36a729e85deb82201c9817aea9dd1209894db637a865fdcb98479743692af50e4ea6be499d1c32782ec57a80d768fcaa37e471f2995878334d9bc9b13d35b9afa7dac22e5135db374f72392f09789051ee923f75d8cc64fe295930b854b68da983312dea3927b5b40d3904981dee1d0a336feb1a15c0ca303c9b8e9f00a7bfac699a0827ee3c895db033d3fe3c2b28a27409f8128e753d75e1d9b9f329f6e704308d2eebfb828294b916b8ecfa1d889c1feed95eb894bce82e17a3b921ce5f74dbedb85adb4c086c25194404e70621c36a382da0e9ecd03bb6c23f4650522e87670725e78a828f92c1be1c6b5399efd6e815bc3ce0c8eda2d1d29d3b529940dc1e4c772c7a6bc55b908882b683773c7b7ae1e9200a80b0022de1f2ca80bc573ae1760e254062bd7eabad15dbf80616c75e0de7ebaf3f6ad5738e076d03b288eae066bde21ca5ea28936b70e2781110d78d66ca907403c0037c3791ee2fff2d98921bff62fa601161725f72a46a5bfd0979908c7ed02965d3399ea724479c5947bb62e122d0e1cc3d4ff06cf132f2410a368414d5e51fcacded1bc518f4ee193428668d25072ff3714dd3cdeb50476efbec93b6e3c4fd27337354a193b4a01a46ab8451fb43cb0195908a8f61f1e407f9fe160ad5a945415c990280e8a008a1bbaded12dfd57084943cde043f170fe2a32a02d2ea72953ff08aaaae6f50678d432dd37046532bb0c756730017102129edc687a81532a385ada71c2830c106966a7ca27ca3f8808acbe27bfb8c618fdf97d14702a4102a5ad347c53bf73a9b069276c0358070c9dd1c24391fb73f27904e8388d3c0e6a480f9aacaaee86f442c51f9bc73178abd9d32845d8916eb40203c65737b68b80bfd8584a0d4ba90c28b422ee37874c24b61b85ba16184a1bc0346f20d2a3075b70c51d3e25087c1a07118b095d2f5a4f1bff8c570e81330e4ef78281e4ca57350caec822486f18ca4a323c296d5ea6350ca1c19937278698ebe1e3aa93ac5879aaf4c24972202ded45a0198e1b3ee14d01f2545f84b56c97b7c79f35a1a13a85e27947d1f05221c3f8354d08a2a85f863eb0d8fa4c927907c4c904c377e8a6782fcfe63ce19da395787718efa6e1e8a1ff61ee378af10491806ccdf07035bb9fa9870efb4fd44cede7b8dd1593e140c1e4c9e7dce7a93941b4cb2b43ebacf499e0710a314050f6c0e489e315bc4203d5b5e00f55d018ce06b6b00410dd4da6a624c1800608a36963350421b934814a10a6e18d4256cdfbf5c59928c626f1046cec697e92b1c225cbc8ed098136e28b9b2996a28b3e47e2efc20dfc8d4e16941d8b2b1d5e616a6a924d242d12f75c293049c981632a7fcaa7f33aecc678370ef933f984534a5fca8085c3594011d1be1f4b3cddbe914643d0e3a2f7f26fb3f59709ee7bfd756662679e61d32978e0dd8cd6aef72192defc15827f3ae8969b1c26888cdcea230ea02403a86baffad22efd2c463ab0ece68ff4482c2d264013f8834130e66a34e8117961dd5b0ee826740636d469d8321d800dea2498ad86767a063b3b8945ce413d07cf4e112574c10b178be1d0c7474df663646a2cdf0ea786ebe0010eb7b8a6b8939c7afb06b65ad2fd2a805c8fc654e617ff187604e1df8fa3235bf548002ac4ae025e0045be0c3860b02485033033333333333333333353c7c6fc367e7f11db5811216d64e672e50bf28a94b429b3f10be1c2efe01dbc7dc8366bed226d6e952f0dc10ca50c85ac304306fa38e6abd4232d63a1f755eacdfac17d460a2cb4349639a58a9d4424640a325ea1f470d2e985f90fe9235728293f56f081491ecdb61890d10a7dd0553969fa4197048b0c566819b46f2f64f0914b4cc62ab47e3bc96e29920f3e55e86d757a79903fa950264d84cbf3f171eaeff10619a8d072f24b57ef8f33dde6586da0025968e1022d6cd8e8838c53e8317b6baeb9107387bb0419a6d07c503f1c39dd3ceee30d24166c8e2d707881a30b162c067084e1c5035c4629d46b9d8e7829628f224f0a7d18b1f7b56be207f38c428f1a1f260bf7215b0ca92043144a760d3d321f8f735bda43a17c556c4f9d3fe13d16149f50bc2d8f24ab07f57e6114647842cde3ecdae3fc117e106d27f44e5e3f1e7c90797c761a410627b4649122068f929c5c2e7e055cbc6f4239e948f1e463b8c6be39c2688166a1451619c8420b2dac9441862694b96c110b4f26d40f7eb25b553ff0ef31f1c844540e9a318f46199750ff479a2db6465a96d072b649fe711c49595f1995d022264f4a791cd2fd207203c9a880400625f89be463d1d39f0e479b1c38b4a84005b2d0228b7f01171908430515e8c0e7c0a1c577c1616861c3c677c15b84d1366c70f1c5dab03109edcd7e9c62b9581ec5a440bb582ec2f802050d862494cab311132185fefe9011095db4ca7af8c9b692446566900109fd22f23067a4c89e5388165f70a1012ffe8b0ad8b001c6175cd023741fc4ab3c7bdda992c60a321ca1a76c92bc62fa18b96aab828c46283f9290ec819fffa6b00c462836ee2e29ffb6851e464090b108e52ff3f92066cf25622a428b21e385ca963ea44c8e6714a8800259684002d75ca08c442821b6b22a4e90e02502642042efcecc1edd0d0d5339849291e5ba7d506d19a31b480707de00631d50508621b4dd10ae736c8d7199ba8154868ec82884d2b5b934c48dd557531201840c426831cf0f34c5d6cc91470f429b394b97f993cdc70b42df3c9e09352e6f1734815032a47ef371f0c9ca1320f47cf2a32c7a39197fd025478a5b967e7c9f7bf841cd1197902963e5818468918516e902197dd03c5c5ddb5d1ad9f2f0414ff136e5e1d77bd083fd7ba50e97936cad07e58386bbcd1693073dc6c922f1e2bd75e581074dc34dcc703ee80e7abc6e6f7fffa81c123b689563b3276232e6e9d4414df2396bd47ee486880e6a4dfecb911f83860d0c1973d0479d8791b9f9ad73b864c841dbf3c15d798794b25864c441939c30f152da3c1efe78dc4032439001074d4effeac72953b9fd37904a1264bc41f36c9363de3c3eccdda0e96954fc81fec49082c36c844164b441cbd9dcdbbb87b9818482a309d8b0415a6441bad0efe20b1568200b0b48208b2b2ec86083be1d31c6cbcc1aeb3e6bd0ee2a5f8a7b09963179fc40861a743dc99b91736e69dc345c6691ab2c6765aaecb269929f468c8a045cf0112828c840833e1ecce67f1fbffa1ccfa07c9c85c69452ce1b4232cca0e4cb0dcd83749741bd093f1f44329b694706cdcf2f495e90540e648c41cbfd830b327133d864c4a066d268db587947231706c5f32fe4e426491a2a3028e359b24b6ca64cfd17d4f892871f3d8a9962fabda0fcd8e45a26eef57bb80bbaebe7999d98e1a31ec8053d66df7c7e8ad40d646c414f96246b0f224cf2208603195a50cbde6ac235eceb77419091053d3c565bcc21e221648c08646041ad7dcbb6fbdc1632aea0e733cf71d2b96bdcc80232ac40365820a30a32a85076790852f3f2af2132a6a064f6b1779ef188bd611b366448414d16d161696abbdada838c28e816397fb039cf50d0c7a3cdb12e64b878a1c71314b120f1bae57a946952329ca08c578c7d67be61af347790d1045d2287d57469dcc40f13f4990cee3efc1fa58cb51d642c410f9fbc98e95fcb7e5782d2f16d7c2c27b1c693042d2ece4cee6affcd27cd410612f47c3dd39072ba1cb1c711f4ce1dbfc67bb3c64bd9186418a1aa34553799b5ad0523878c22a8239daf69fc0f83d8173288a0a4183eebfb604c624ad9a20b1943d0ec53907a9d8a1cdb628b13340e1418173284a047aab83d1ec882cdb1857f18fd5f94a098404610b4cca925f8a02d50b082df82d49101042dc5a4ecf0a127336b58c60f94142c484c97e2edf438e703fde3fa2f871c9a87d36e9106193da0b7c791c7977c5496b70c1ee8953fb3ad539ac7d1179ba3045b94a0462063076a88ab704f9a75af91ad41860e94bafe1cfa2c976872a0b9a75c9b3b0ff27f1cab41060e34b99c72b3c3e606bae75b5f875c39e3391b289f429c89c9c91964d44097eb9f4cd912ab2f84069a8cc5ce5e29ab87d9c723043266a064efe492d2a630fdba1764c840cd91597ebf13a4de63b81023169a8eb4f638fb76a61f7f030916ea76f8f1492ccd213edd20c62b341f6d381f7778060b3601440c5728f923e9a49d537ee9ce0d24301e4781d10abd2627edef1f76ddc55988c10ac5c73e797fe419b20fcb1b48888518abd0e386fe983a05cda926a38aecd3dd8ff24eb582fd2eb6f0623b154d72ad1c99321d03156a8eca9a9d7276f871f814faf99686c6310f175b984291cadaa9e3c464c9bf175c94427fbb2c7e2df679d41f14e4303a52682969fcea9c43f3f8e606120a72101c3146a18fae53ba3449728cce96238628f4d17c668f7a98b952418c5028c12d799c331f7decfc0da42d8c173140a126bb3ecfc17f36bf952888f109af3b42481ec411cbdd4002630b32307209313ca15f1e7645bf945d92080a7274421fa7ef38153ec58fb5c70d24244e383e4c791e429a60e50d24aa1dc4d8c4a3db8e8e3dc81a3df20652e2208626140d5f72492385cab88891093d5f87dddc162c888881092d227c7eef9014df3d333dc4b8843ed818a74795b323fe64871896507bb07938995e925d48da1c625442f781574e7937a6e41083125ae4d69690888dbff024d4b4d755912758c85993849af1f672e965339faae0102312daf8cc98bf56a4f8e371c4861890503a53ccff38f24072f0f1083d7dcb6da4ba378955a1218623f44148e6bce9bc8d916f84f6bd1922cc77880c3118a146c665b9a9aa388d8c21c622d48858d2bf297ec67314a14bd6545cbb591ed78950e7ab777a70f9528e3922f44f3a41c2fcb84478087ddcd2fc2054ec4148b521f4ccf5c33c9c94ff5cb2855092e651fc78d01e21d41fdd5d25999823675c00b8438c41e831d84d87b20fedc913843ec13c65931f4be8e71108357b9c2e5b687df2c10510fa2032fd583b6374d6ed0f4afaf2d1867699fa38f9419720163ecce4ffd3830021461f348d24e19f2fe68f762c366cbc22061f944c2962c69c9e1f46308b3660c3c66ae1812cb4c862021900430526f004fc33c09fd42862ec41cdf92a989f8de68b0d0262e841ff91e8461ebbfd8977f2a0d4f558b2c6d4ff16731a90401e62e041b18989e1fa7e44637907dd652422a7930f8b941df498196d3dcc672f218951075db287ec5cf5e0bda78392246e966bf9c66f660e4a8fa4c9dc30ef239313c490839e25697c8b9f86560a2a21461cd408d93e5f54580cf7992fc480833ec8ba11b90ff2e3d9bc41af4821e985186e505ea3269f66eb5097471b947cc97edcb961e13f6283a6171aa63375dbe708ae41b1c96333912e5d0e793528139a66cc47163bf8891e889106c57c94e35e54e87166120d4adc69984efa0ccac8871ff878b4298b853ca010c30c8a6518b758397f315b80c18559418c326871feee73c6fd43eec9a07ef6f2d26e8920361838bae82d7078aa20c618344b999268e4c4e570c5a025cdf12171241c2bd80287631831c2a09ea418bb0efb31138241afeb14e72e849e96ed9183185fd07d3c968999533c1fc4c70bfaa71f4cd2b91d11d9c0e0c2b7c0e1553688d105c54ffc83e464fef01f5cd0076192e323ed10337f0b7a8a61f2b82e0f2ce414d482f63d1e65964c31759ad40da42d70b899418c2ca89fbe72c32b8fa2472516d4c862397606bbcda3b77830707c11e30a5a75cedb79ae25a6fd1b488c8861053d52680b9e7978b14bca42030d381fc4a8822efaf9c3ebd3458f525888185450b274df72f6c3e49c008c0da308c7f1e2015e7051821c3b81a41c11883105ed2e844e15e23ab38739175b788103bf0b7fc0510c29e82159bad3f781f6b8fb28a8713925bb3cdc103a9831a0a079d7860b3dfe710b319ea0668fb9e9f0d9c16c27e89f2c24c40a3d9caeb016623441cf17f1b11452d688cf042dd287e42933d34fe74bd0c2c614721e9ee5f9854f097a4bff789ca7af2a840818b5458c24a851d741528574f0cb6e201d190ec44082baf7793cd25cb1528fa73421c61194f8b1414b2657878f11f44829f90f243b3b5efa0bbb2e6214412bcdc85bf1597aa01f2268a33942a5d0a1ac72d8ae1063087ad61e794ec9f4c52d148216bf4e5ac24b730e1f5688110425f5c68b88c803411bd91fcb213766e8f80fb46039879cbb53bbcb3b85183e5067b26465bdb85791471262f440cb973ce5571e44d95b4888c10335cdeba710cf711bd30da41c38b6281583183bd0bb5f2bc6255b1043077a083fdc9c3e649d9b25077a72af1c298feb2c4884035de4e3fc7b4f9009316e401ebd1f667b6a886103c5fe927e768e21d86c6aa0f7a7984173fe40cba228c4a0813eb6ede1e7f9a4ac31e8853a21c60cfc98abf3d74ec54ea91832d033885d5f0f6463ce4f2c3289d18f39176288888df820d6e461de44a143094acf6fddb994c4d810f1414712d43ecf1e5f5336312479d081043de68de0d7fa398ccb47e83882be397df820a7173b5ecc088a458e5f4cca7714414fa9b27ca0793642071134bff025ef31e9aa3d4350a3b2a64715513feebc10d4f0b379264f3779f54150347288e05afd62930782b61f435cb038ff401ff7d8c2ca3c23ea661fa8793a8f2f4592e881857ba08d75eccce9dbc47378a0fd30f6499787fdcfef0e74eb0dcdde89ae8eaf0e947eb964c1fe6737b83950734e8fbff284d2b1340e948b3dda0f7ac91b68f93f4946ca497994a30db45032957bdc23d7ecf1a881622f39a323a6d0404d4176425796b83c66a05ec5d61cb2259a721d32d047321e9b528f3ff5308b85fa831c7c94b23a471e5eb0d0079272de60b1cb5c7e855653f9c34b559ece07b9424d136cbae3e24fcbadd0a653f564e8eb414e2179031aac5072a76bf71c5a2f52bc0a4542e69453549eb9e56168a842d31bfdb1a649a6ad39a950638c8b8dff5115f6a3424fe1c52dc42c9ba6e25368412cd264ca79f0c937a65062c4cef84c86ceaf147ace7c6946b7463e8f24851e6452ba9c3c272fc651e8c1c6aa8366a2d02d4548f767a6173442a147fe7ebb0d69eef70685a61df9a7bef2678ce727f451acfc9959dd9262d2135accca9a655c36368c9d503b5865ecbd14762fe48492f3677c05d9cf395f36a1ce7796c8839469d26c9a5067f3280449666542998d3cf2617bae882126d43d6d2bf3c825d43d2ff91e77b21e6c8e25b41462777856de85985309ed7c9c2f459f58b6f729a17bddf78b973909ed7edc3655ade732be24f41c32cfe5e1c76dfb3d127a4857eac1d499865c4342c941cb53f88eef5cf523d4c9e3c8b4f19dcf3eec087d30967db451164be2dc087d3cb16df27f646d7f3262f790675c8412df72654c7938197214a1a68f3ff67185a9dc934722f4f281841e8f22ef048f2142bded9d0d1f94790f3f84b6417ae487b529fd86d0bf22cf849fb56f4c1542cde371feacec8d105a56fcfb20fc20fb4fa4310835238c68a8bf88b31eb73404a1947867580e793016fa4068f12abaf238afee930610fac8bf2245087277dde30f6a48fcf18b69f6383f289ebcf378547152c4f8f4411fbf5c8f355c7894e6f9a00ff4b285dbddff38cb7b50624fb2bdafb01e74bdcf17e6e3acf51e9307a5d355bf9b84aced241e949ddfbcb114bc83e23986e4588da70f1f76504b82eb54747d45675ea05107a5cbefc343ae3c7978d241bdf0c97db79dc1626e0eda56ceb0e972725072c44bffbeb6051f8f38e89647912522561cc90b1c344b294edece11b6c27603c90b2e368ccff106ad7d142e4836d31cba71839e5dc2a78c3ccc3156d1688396657b7b9c7abc210368b041b9eaf3af921412faaf410be1278fc23b63fc570d9a7ee4a41424e41e6498067d906773f861a4d809153428d9e3eff8c3fe4862db16e60334cea0ff387bf6718ff7324e63067dd09d47b2e13a65fa6419b4102f5b07689041ab081b394bae9f5d8f41e998232fc93b56884131a82952578717adf7ec230cea8f477fe5fdad61d942030c6a1e94bddf07ebf1588ec114d0f882f26e17f942c30bda55cc63f7ca1267aba304834617cc060b687081c616680434b4604cb9fd64378cc7d1b2a0c854fe4f112f0f73e419021a58c8f38e76ce61bc37872aa071851c34ac4075461e56d04896c7d9e38a182dff9124ad5812814615b4143e7cc4f6e834a8a0b6c590e2c38237d003848240630afaa54f1e3e8e1c29a829f78ff9402fb2e3864614b4f68164939648d6e36940410de2b13ed4f4349ea0c4866496439c9d6090a8f07f212b4dd03b488e886091bff24483097a8408f351ee85584e4281c612146dcd696a425dc7b02b41fb8e8afb4afa3dae32094abb8560c12705096abf679cf813f963b626d038823ec8229fcf46ec538fa3610435fbff848be70f5f3a1a45502724ab18f7fac75dbc8144a4010f030d22a0f72e614a27b68130b60b06d8b0e1c58711c6767168083486a0dfc720f775529e3b47087a08323e921f5cce6f27086a1e56c8659a9ff9f40341b15026eff3399befff40ddacdbe3b88e210fdbf7811a2e5c30f972dbcfbe076a8c6d1fb521cb62f23cd0b3041f94ccef7cce7b07fa786c417253dee41fa675a06d581a1fb4c439d0c5b6c763dbfc81069371a027f9d0f457c97e38e11b68123a3b7feed1c4f9ac0dd43c1fa2fcac7674363550ebe3a7fc935431e40c0d1ae831dfbfc514797b7f181a33d0c71a379b7772ec9669c84099f8123b316759b5b1d0a52e2ab4690c9a5312166afcd1c62dd1f2159a0fbfece2886fcc55ba420dd171ee2d851c41be56687e9af24d96c70a7d18ee9764e2ed3d77ab50c2f74f1e8f69cfc31faad0ec2634c5df8f47e28f54e8831edfeae003156a78079dd049ec73e8710a4d346c7c1c63f3a5ac29b4f8b8eeb0b53dec61a550772ca79eb694f7831452a8394bfcf0f73a93fca35063d8cdf9e0272bc2a2d07cac3dcaa88a8542bdb6fd4e778342edca1bfe9a7d90c72794caf5294cf9284f28e1c783cb54d5093d9c6b5bb6af0ff21327940ecd1b42f77a1cf326b42c1673861fc44a59d484561f3a68d09463168b6442cb573932228f88850826f4f0af49766b7b649bbe841a2178984b116162c91996507e5851de3111539e9b51093d7c58e52dfd565dc12dbe01366c80e1050e14740b680625f461b57fdcacff1bc9d662c624f4543a3f9ad47b9f932d09ade3e476b47eae4cd78c48a83d179f6a4ae2f95b3320714c7dfecb1f4c98f108fd2b468c58b74198e108f53426ef903ec5c8cb69841e151da3d3788cd0b38fc731f3c9e4ec135a84b6295992baca8e1b2286021fd80206331451e9ccc7dc1a555a1f185ce4d000116624420b9537e5b318fd4bef0c44a89f95e72fc6f338628f1c6ac3c6e67830661c42d3b9c9839a14bc62792cd81c86d052bce651accf2198c7881e740b985108cd3462ceb3c50fff529e8b1c1a280698410835dd85c9fe9f3c48b6c01146d1c1812387050a023306a1cd79c59eba9472de6ec3068e4341681aba5c3ad55624696f2085f12548090442fbdb79b7105923a51b47185e7051cc01424fbbf3972dcb0f32947fd03bff76235f78c9399360861f148db1bff0611ee5cae3dc40eaa28bdda2b84001171208830b1470d1c51637c2f8e2bd0533faa05588848e7049328f3e1f98c1072d548cbd0af7bdfe617b507b7b906a66a2c70c3da827f93d759765936d81197950427eeed9d1ac88183c28ada1ca2efbc71ffe30e782cd91631f77306b620f4f2383e7109a26ccb043e39fe72c244deaad0ea4d208937d1a3e4cb981c40f155c8e30beb018cca043b160c61c66c841b3cc61c3849194385c413c72da9a080e5908f1924edd48b66e207961c61b34dfca830b3d177bcf9a0a640f66b841c955f107d21b2c82f7b061c3860d30cc8c36a849646308c9df16e0608381196c503f4cc6ff287526332f30630d7a1093891fc61cb3c4980acc50832e3d3ff00e1f864b571e1498910645cc7c2cef038bcd111b11cc408352d2de3f65b93df782f1398a07669c4193ca489bea2ebe2497bc70c10216801b9861063d668cd3ce2ce9eafd32281e3a8f36b28f3fe5126790410d15a2c725620ae1f531e8a1a46cce5e9386266b0833c4a0f67027e76185454987c3a0668e1b3ede9aeef4a7d90c3068133d1d34cff5052dd2e4c6672a33c9bd17b409a9b3e7f3c02bff594098d105a526496fd2f8f1f82dcd05a54333e441ed54f984cd7e30630b7a5c0f626eceae4c3b5be0055ca0808b30bea8c0091a47174c9698a105b53527ab728678679b35ccc802d972d00fd25609c30c2ce81d4473e397fb8fbeba81b45bb8175c1cba11860ab2d0220b0da000470e0670c100e3891957d0b2cb266493a415740bf29f429c3c8cffe08c2a6895233bdbc557c00c2a2892c2f8302e7d06ffce14b4bc11f76372e1979782e2e9f257fa9f543747419fea41caf78310312d14f41e4dc5ff782cf1f9c713742f1f6c6be514622b77821e7e8365b8bbb77a4d13d4bd1ce4b276eef130974cd02a9c4b0fdf479143794b5034d9c57c9553f0cb4a095ab8bb8ed93fdcad1c3223094a903421ff0f740b2041ad1f669bd89f7f1d1f4750f6af36e369ce9fc3463090851659900b6461010964d1c5172a08638ba31946d0d2f496079374e139338aa066f908318dfc7022fcb8810406d5cf2082be913dfc58eedc47dd168171841482194350c256cba7935e086aa874a2ad99313bdd4150f7ddfcf32885e6d165670041bdb8943a6b82c54fa92c3420013cccf881da9db12ae96dbc0f24777a98e1037532cecd6cd870dfe3f440bf4b6375793dfa8db7113378f03066c654165ad8b06183123376a04bc576798f21ea3be60652a10a14abf3c30c1d6816225c8790c53687a01866e4401f45789bfc088b93076f415f988103cdb5355e7e66b4c52406aa30e3067a4839b69c04ebf15967860d94f7b3b8f9bf23879a8530a306ba8fad2d720ed38fe9b22bcca081667fdb216149aa5d9c81ded9272a8f44348504fdc51e8f07954c8f8396266cd267180d6138689f2ee50edf7983d64132b47c4ee3d97183363ef6f0ebb4410bf615f240538ffe6cd02aee578cfbf14c7a0d4a87e9f8a4cfbe1b35a8e183f91813c44afa34e88310e2c1248f063d0f2c57c798dd24ed67d0c347ce18f37033a83189a4905e736ce565d0c7930736b1fc3fe664d0cf87e361bc3ec4ec3168d7ee1ffc36652a5b0ccaa6f8f979d82771ea30e8c34e2739ec62cc518341afbad0a29f2f28a9e327f91c61fff5825a39464b8fc7ee61b80bfac0663c521ebec691b9a0bc0fd2e414e32d687ad31746c4bcc7d182e61572bffb2ffcdf2c28496c82051d0bda877896452e84d0afa00ff22083e6fa41dcdc5a411f4eb8d118d3b2b9ad825ac92e7a73b48f65a9a0e6d59f5b5b874f3b052d65074de537777923057d6f27cb879b2868f9d3e393e2f6e50c14943c100d975d63b8974fd0ecfcf370235c644a2768313e5c9c1c9ba04ed60c99feefd00399a0f97c6692509917e112b4b03dcefa39f48fea53827ad9f143f8478c994b827edeed3dbe499fbb232428527926ef23c2558e8ea0e96f920abe11f4f6698b1c36edc41f45d0b43b4c8eb97f1c2f11f4f1e9f6b8f5669543d03305137febf99c870941cb383521ec76849c20e879976e3af6f0521208fa7feef43086f012d60ff45c62fec17ef2667da0ee6bfce9e91cbfec81ba13e37dccb8550f1e28337d6d61210fc2b2033552cef7a135ae13d2819a3fae981ce249fa73a0c48a7161ffd6318d03a524db9bc6bddb84d00df48dfe916f898f3236503f7808b1af935ca7067af4e8addc23001a6897c1b2bc3dde538e0066a0e55d56cc1c6afb3a0290811af9f312fbcd25feb1d0428555a4c9c342ebfbbe37fdeb41fd0ae5ce2f73489687dcaed0340599df906132d8ad506254f08fef7421a459a14588655c79ccd8ab50daeb47591df3f7605528fdf5b9ff72da64722af44c792fc264bdf0312af48b207bd1231f5bc4a7d0737e8b8b9b2e466f0a45825e2c3b3fdf7429f4ef54973c8796c8a4d03da6fc1d7fb3a4dd5128dfa1b36dff6ec715851e44bb6d6724846a43a1e4758f485e9eec8342f1fafa3cd69dbafa139af60f376c84ad0c1b4f682f9963054956c9359d505cac62528613ba6fb5fe68737f546e4213ed10df2e777234a1c978698c1e990935878f6d5e89097ddc92326946dccdb9841e6d7316c763fb872514cf92c8cca3dd1855426ff7f16e4c3d1c0d414a2865e1f3f52287ac27a1a6fc51d262d3e39d24b4b43399b143ebdd9150b43b426e0a3e92cb03127a4a5921e225cdcd3e4289cfe9bd10f383ce116a8cc4748eec9e49698476db316bd68f9b61462867b1f2280f62ef666d115adea7720b15a9a1082d25cf15661efb1b223512a10ffb5332ed41b088215203114a8a31ef66cfb83789d43884565e1253feddea9b901a8650dc24c404b9389621350aa1c49c2e624576d38f2ca00621941eb3ca983af428e6773ea83108753ff368eede33f4481ed41084ee417762cab0feb8788d4068e59f07d93d427ba4bb0620f44961daf3c73c93d35de30fea757cd38d19362c796af8410b3ffe51a65cf129ce55f4801a7d201b7c201b5c630f9a688f539cf0d6016ae8418deca2e1471626b47979d06724876c9f25474e1d3c68a5e3419285f00eda8f83e46b986f073dc6a818cffcab83d2b9c7ae6f3958e573e9a0e761da9c3cd0cb93833c0725ee7e433cf1102e64e5a00ffa2ad84cfe1e680a89833e0edd1293bd2a5e4a38e896d971e276f60d7c0a91b879143b37a8fb771bdadb629f65dba0e4817b5f0a1179b2756cd06d828b66be9462fa6c0dba7ce5734d3e976358d4a00f46e2a68f982434b469d0a64ae6fada2eb667685023d86d48b23f2ad9cc1994983f089e3d4e55d59919b49f8d97245d65d035b8c5e95455313b4506358d6bd6a0ed1ae7426350732e75c60ab631f96250bbf7c7df35e6227d1894702dfaf17b8041edb4298f0766172973e70b7a86f251ae14f6827a19937774ab657359a30bfa678ab1fee26be4be04391e05846a70a1d860418d2dd4d0829622bae5f6d32ba89185836d929cf9971a58507fe38fa432c3c6cd588d2b94ade2c5fd286554c30a6af24ae6913ca7c6f7aa829eb1ec743ee49436d4a082fac142ae7dd44e41d789ada193e41197181b6a48411fe6ad60298ff228e8f3567d9b5384e6a4a1a0d5e87608e2d5a9f1046d42a69dacd72d3b91d250c3096a654f7e0f69ef083741c9b947974cf43a3598a0e72c3235e93fb987ac086a2c4109315e76378b8d9c3e3a25a86d9fa56a53d23cf6ab461294205f298f3c66774d3e12f49057af799c5bf4ba53e308baa4eb76bf92893fa88b09358cf04024f347cb5c320c358aa056bdf9e8e3445eea89a07ffe51fc0f3608861a43d062fc9007617bd0697e084111eb88f9529093209920a85db5f177dd7b91d91b48c503358050357e709cf02c79e4ffa30b357ca0a698644e6a3b43ce833a50a3074a6565c91fa590c7146af040b94a176fad7b929354a45063079a7b995c4b8512f9c11aa8a10325cec5d815d344f0705e161a68c0e1a891037d3c081f54a4e483eafe70a0c41f75e5c6902bf67853b250e3067ab8698685c862a1860d949bfe90392ca5147ad740ff9020fa319b32884b033564ce6977dccb9ac72ad4988162a13b744e22d3126ac840fbcf69b2ddb4a62c9928a123165a8c31bb7e9cc20fefbf1bf8385868a9fe7f18f1a973f29cefe25161e4c001465140c72bb48850b9e51564a6ee1b44872b944ce2a3904796b743472bb4ca21e798e70d2b94b6ef743dc8b955e821e665b1921ea80a5d3b6e67d32f3b52a15caec9eeb4e1273ba50315ea5c548ab8890f3eba3b4ea1849f1a0f731e4ee3ee308596f1bb7cbc314a2e871da550378fca475ff19b531edc410a65c2cccf235ce8b72c023a46a1e46b884a7972041fde1da2d034c4e73493efc7e1a33b42a1560c3ee73f39bce5680f50e83122cc649a88933fbf81543a3ea184f798f5badb462b97c320a1c3137aeaf8aa1052859f5e8ad0d1096dc25745df5cf851ee0618db051885ca103a38a1e987b81143720a4123613c1889838e4d283fd210ed79e29a382a86983b2246ac0c414a43ee8efec831b657f4c8843ef2d603f1b17444496e209da07174b185d30970744115001e7460424d33d172c925a472cb2574d730e1c3c95a4249e1b5fd83ae646eefa312da448a94428610c3f5a81b4894507296db0e6fd390a3a241c724943c1e8d6e84e01295bc1b4846061d9250277a946383ece5e1f73790b840f2e201140935a710392f611286175ca0208c25a5e880841e3d90785a9b3e69d2141d8fd027566756cca9bc1cbc81f439fa881eafe87084523f9a9db210b37af43542bdcf336797794ee67a420723f4303116957ff499ecb308bd47bfe42eccf648378a502cf445b6f0e341989c89d08761cab4ce7f3479e022826c9c8e43a8b1fbe3acaf89d03f1e86d0f3e59aebdca09d462a841ac1bbcc3b85a78d140f741042b1edc9d569b4c37c5b818e41e816f3575bda14c7444341683d3edade93ea2a107a488cef9d7212b9b2041d80d03ca7d91e6727c969071d7fd03f5f849c932a931f7803290b0d340003366cd8681b362a003de8f0837a392f4fe581f87c3954f04575d1d107250789d5d9228d75276f203d5cd0021c26e8e08352d9d19727681eb78961e8d883e6f9e3389907c1d283ba673eae37b31b7288f2a0c46e4c16828f6adceac083a217cf7bf85d27f9c37407a524fdf5380fe747113aeca0661eecc4d24c21631e4643e8a8839241db36327faa343dc0202174d0411f750af379bce962a86c0a1d735022c62c6bb00db6956a42871c94df0babe8291909ed16641d7150efc79d3af338747ae88083fee3d16bbc0c3a75953d41e39040c71bd4bd3c301fe5fff1e83fbe821cdfe106b56d83985e8c5073d1179ba3036dd0c642c5ceb27924133ad8a07de7e032e5af41f341e4eee4717752de2ca1430dda56181fbe8ff328bada34687a1a43c7e6cfc40f4403d91842c719c8c6093acca048e75108d96d5b337920123acaa0bc65281bcd2519f41d0f73e521b6624e080942c718941ff4b0b7e3c73ea14531e83926eb8e9d0cbe57150e3ac2a0dd8f4230b99af848b5163ac0a0e510248f877997efbc8342c717d4901ce2e39778bfc19a4087179492ce4817e3d658cb8f1f7474c1387a75ee317b7041f9cda9071f4b3cdc47b720bb630bbae7f614ae37954f8f5b418716f48a97eea73c7bbc704b181d5950539ee95d6c6c4faa727460410d2dd92c2a3f75f8e145c71594cebcb3d4f997a9a20d038c07163aaca04b8e9c9f77d930c0285968a00175858e2a28592643cc4e5b9f2a2b745041ddbc793febe6ce2796dd764c419bcb59b4ecb3698ec81cd021858e28a8613cfb279388f520ec400714c846c7133493a8fee8881eb6885de87002d9e86882b677d27ef9310f275ee06082d6e3f9810f2797976de8061251161a6800185fe0c8b1001b36c0a042c712f471458a6705e0815eadf9d2a60abd21260bb0037d38fba34d5eea401f5bc873a0d4778554de89bce3401fa41fcbe4fecd0ddf40ffce3fccd97879cfb381de916b7cb8d5401fd60fda47fd8306cabceb77a4b80033d025579fc885f68fb202c840cb7339042f4d1d278b859a43eb66333cef64b0502657766984fab1eb15faa6f71f07b7d215fa55c591f0996b5fca56a8133347ec902db927c90a4d52de4f15925c85723d1e75986acff1915485563166b2ac7b36fb49853eacc949521e9475f6a042d3a0b12363731eff29f4f0631f8f071ae452cc9b42f9711ebf50a19278bc145a6bc6acd7f323b39c144af8493e7c4f8f42998e217bfc711e4ba745a1e699f80c9d50a897623ebaa343ac41a1e509ee1a1a5fb2fb09f5073db6799447d9233da1a4b808a17b987edca3138a75eccbd8294b6ccd09358ed66484e730576f423df3f145d649974ad6841a62edf7b034fd28cf849eb47b2439c4841e3bf7488b463e6f2fd1556eb7981f6b0965f27878bb31fc307c6c2594f6c15fae987decbba1841e3d1b730f3393d0cf83f7fd8b65cc2909cd437c7fa226680a4642cd95bd7d344148a8c132b633f5bffc8f5073bf684890b017738ed0aefb2f4365c6fb1ba1767f94a6deff81cb08a5a2077539f558843e1eef0f2e841e8a50734d5d8c6521f73025116ae8ced88f82082505eff1864eb6fd39841adec93dcc86d0071a3fd23c8e71268f4268e9752348c808a17b0e1f3be583d0c76e1d3371b36dba04a1eda4f423d71f6da52b10ca65b9f648e44f520a106a9e0b1d7a78f5da11fe41bfcf7918c922f483e6637bfbff0ca779827dd034f5c596583d1e4b0e1f9498dfc79de23d28992cd2d9868d95eb41a9f1f3095e5561e741e998df94af197a1c1ef44f113aec7f3ce6e3efa069ea7108e94b963e7650f238e5d01676f97a1d120db7d341ef589eefc939e895da420ff3c5203d5c0efa650de11a5fbf07791c34dfe42da791b747371cb41c7e38392cf4e6d46f507325b3d461768362d29b4376aef196dbd0691ef460831ae1c24854464c7ed7a0568a98796e9f76b36a50df3737e46d678e360d5a7db09c7e3468504ac3650ee7dd2d9933281be1d6e35196f64e9a41ef7bb9f249731b9365d0bfcf871dcc0717be2483de3e12bb107423b36350b3e661a61fc5a4a34131e89962c494938f4c331806c52f5e4e2ec5cde3100c5abbdf8f73d426fd815fd0ec731ecf9985dbf6bca047740c693ae7ebeebaa07eae18333f0a49b4e382e6d3f723d93cb6a05e8c8d716942b9f9d0825ad2d9c7199b77793cb2a0bdd578a7ce0a3e4ec182161612c647ef15f4091b63f23c12db70b182924779e49a7bafb1875541afcaa92ffbe471fa1415b410e6c45baf296891b4ee473e8c8e2149414bd2315645c7b11e745150f38f25e6660c4f1a1d14942eb3dc13d48e375e5631864f91738252fde391be8ec9e5719aa0cfd486fb1c3a85fa99a04d55d878f32f41b1d8f6df1e75871eaf045d7334fc38c79caf7b1294ced2ff23b13c78db91a0ef848eba0fdb95f123a8793c4a21fff8248f6904ad53ec91857b9d5ce92268622edd2da137c79a085ae6d81edc59a7be7a087af9cde5c1a6ec2fb510b44bff9b6ac6dda50e821eb93b7c14b963923410a8cd171f2549ff400971e3e77777cfb90fb4f3815d1c1ff4c8b23dd042857ce2db1dda8379a05430dbc91a9a67e31de8fb12b73734a225ac033dbcb7c78a21e26673a066687ea70c0ed40aeea3fbfdf23ef6064aea1eebf48b5cf5581be8e394ecc7926d0df43457e692079a629a06ea87fd96cde447ceccc0daba3fc93902c8409f90ca58681de3deee7f6f7610165a8c65ea7821e8bdf80a2dd8c49be8923c7ad1157adc8933127998b7b956e8c3f26e0df97ff8dbb14277cf63fbd5ad420d9b2c8fe57f10c77da8428d290fcb42fb4c071fa9d03a3294f4383c6e7ba0429f5c5afbd3e314caa5cae8711e052d8f29f461f87d5bae8dc12c859ac7b653490ea963a45047a793e77ddfb946a1bd8f355bf6bc175211855ee6dec3cfad1ec7a1d07262d3a76059e3c340a1fd6e8a083fd926f909250f42e51e87e9d0a3ca13ca7bb5e4f1707a74420d27e1666e7a7042cb831c12733f4867d363139a5645984d76212cf4d084ba176f3ed39b77963c32a1c76dfe9764917b431e98d053cc30734f33e1248f4b28d6e25765d695fbb184b6fd3d901f7e2aa17926ed9ff194f3e35042cf9f760de1b12fe54c42b76d696d1309e9774968b33b79ac1b325f8c47429b91cae595afa77448289e53f6fed11fa175c6ffff95e7f4704768fe49520e1f6493c51ba15ede9c2d5132537146e852e383998bdde3b917a1dce5f154da72ef582b42719f6c31060bfa552742c9d5bd9d268d0835c585b07910f5ed398476729633eef948b286d07d7bd431eafb5ce442e8231fa52c2182f4fe845037c47e3439febd66109a5ebe2c713fe57e46104a99c4d31429a53a104a7e2a0f7173aef700a18c5624f794fc83f6b7d1a1537e50e36b53ca1b39cb04fba085a4df31c49af41d1f94f91019ff911b3d6e0f4ab8c983a45b39ebd7833ecaab6dc9e6413dcb56293378d07ee096f95c27dcbc83229bc71ede83af54da414d7f93b2a41e26b1eaa0071fd4e7d1d20bd5830e6a98c56e0e3de6a0c9e41472940f27c772509264b1dd588983de967b64c70207edb2ff62e2c79a83f6067d5cb941491f4683c4aab441d11caa62b8ebe43d296cd0c74c26244eb77452d6a0fcb8c332568a3f0a93a206dd45f340be6a9306bd2eefe798b3588f23050d6a4e2f5596edc77f9f33689e2bf7f2cbe5781f3328b93df56e84f8703a65d037267fc5d6c80f3f19b41f8714f3380f22bce6c7a08cf5d9b95df778941783f2959f4268cb113e1e06b52b861e8ff72588e660d0535b7cd9f7a8d2e55fd0a4c716639d5267b6bda06d9a8fa92cdd056db6f2f82da610233317f4c15efa1ea54e212d6f41cfd394f3a75f538eb5a07cae9c92257df9146741cb3dbce4e33c2ab38bb1a07fda917fcf15b4acfd9942fdf0a25f2be8ff2d29fc707f5cb355507a782e97b4226ecc52410dad31d975f2cfd34e41eff1a077279f4e8c8d14341f698a2f2974e81f260a7a87b1ed1ff5a02333507878aef9e4c7c927a81d37530ca907799c4e27a81fe65ede1dbacc6c825e21a7c903dfdd503341771f8fce47215c82a6717e1162c8332154821a9e62056bcb95259804bf3e77def80f097a654af5e3903a4fbf23a8c993d526edfbcdcf087a947744de5c11f4d4e3cddc3ed2902a47046d5cb28ff27cdfa76e08cac6d99cbb6cef1e216892bb7922b3976382a0c7aee49fd9966102410f293784faf14efc1e3fd0b524f73b4ecfa63c7ca0551e4e76ff288fb2f4e881f6c39c7fa4f340ab7495a2f220fec43b50b34d12911fe4895307fa8fbf07b5971ca81b34f2605270a07ee6c848ce3e2ae9068a6b8c7d3e48b101d840b71993b01cd3cc311b400d74d33cb6e0791a28b1b27eb8a30d60065acbc7d8f1791c266403908122631accb7bd53bc62a1a6fcb10ffa8265b00b165fbab35ea1be9c6e964abbd5952b9419bd303afea53faa158acee468ddb8f399154ae4417c1e8f3dda33abd0a72fe55715fa28dc2c9467f1414c2ab4cf1b72eaf1599012154af6f13868b6303e1e4fa164f0bf904b830f3685961347c73e4f70af145adacee3ce791029b44b9dac4ba351281f7763ceb9a7f3118516398b97dded9c855828dcdc19bd141f5028fa1fd27e8ff309a57a7072697bfa53c7135a9ec7d0bb2179889c4e681142c831316977fb9cd05b5247ba1fe6618cf94da89debd7843eeaca4172ec8e097d26f4cb66e1ca2bb9e71c137aaca8931ec6f9b0fc125acca37958137a5c99b684da1a76317f7c7e6057421f44c6fbbd85f0e39912da87e0f6a36c3fa89627a1fbf5a78bfdb399074b42710ddbbc1e1c097d1863c71fb75fc5144342d31c79ac377bd6107e841e3f7ca59c7b58d3631da1d8858ff81f5aa6cf46686e1fae337de5dbc9083db65d59ca7a26722e42fb0e7fb1b267d31c54843e4839d5a63111ba8f25237ef23ccaea10a186093216ee738cf271082579646ccce6fe9e21b4ea10bc83fdf0258f520865ff7c626dbe4f0e21b43dc91fdea7b6c80f42ddfc6521434c107ad21c3fcc960f84a2b9a5ba4273e8b18050f347b1872f9d64b63f28f251794ee2a498941f94081f0f47d2fccba60f8abfeb45ee880ffa75fc38b784f6a089f530e4d4e7aeb71e94bce8c9a942fa619907b562a6709bc3f606f1a0b659f076ef0e4a4c9cdc8b60d2e36107bd7fe43945dc6099d5410da9c28f34c41024468a0e5a327fbf0edb992c5273309d7cfe4b9192832e078cc3a8b46e65e2915020100684c150180804b8dc2e00a31408001030228fc482d1444e5469071400044528223e2e2c14201e161014140a160e044281303818060282a13018200c070382c0359ce67e49a47b5c54f1dd07e8aa76b4850e1d3b6145facf2950e060aa2d9544829c2cd02945ca743ad2a082db9d9f0fcbc84f361047fce44b6847e42966649281cadde704a7bd3597c48b64bc6667f54cff046dfbefdbc53d3ea10d7d7270ddb33143ccc8aa05b24366a686d5c4df934b8e3a151856832aec2e4f75cd676673442b41db20bb6d8de94965f867e9a998450245facaeabdb3453ebab314d70e9e912141de5c22a44385150b0a8cd699457d90ba69b69fe9f64ceb84751d5c3b9554aa0369f4aeb0904b9cc10a7a72de4aa8362a845d9d99f0b650606736b5ef34d7e670a2a773e3b8480146e62ebe04f6d1e141499bc06bf137bf4ee75de6397f0b829c679fa833dd81e5f37b32a7b995cbcfd099cb3e642ec484bbdf8bbb0bb30fef532cbd2bdfe70bd43e6ea002cdec0bd886528d3e1e379986db9e9a4cda2539fd685721927be9ec061dee3a3737cb5cbeaecb4f7daaeed0e83d9fd99865dbb156ba6ee266d399c4ea63b88243c29c920cab7e7a88774d9c2a4d19251d9a7d6f8abf22d6d3d3878a9eff84a7f94e97f8fb7851e09dcd1b1dfdce66c91c71d08dc26c58816e84959339a4df76331ba6ccd638096847d14fb0ee0d66eaa200f549916475796bb517b058e5577fdf8b73cbf922a39f23a977ca1738f169dfcd85dc303541eba7cc5c8d84802434643ce57c9ab20e1d2ad761d71acb67f6e91f3a2d52cc22d9371f47c5881807fb609aa5afd47911d348c699d4258b381584bda66572a95c6efe4d9916715ca2ecbc9b99f2e30602f5897f25e9fbf8d5238a1c4da89bbcfdba9ac762c449de1572cb999fd2fd5d728a53bd998bc46b3d5e40899ab8bb736ee2ac3736dc0efcf8943dc891835cff8e4eec3617c67d1c2412a7d9cbaec45444ac59a070c18cfb9d12c326f4cf40dbbb3da17e8206db8ae9ff6dce6152d4c1954ccefc4c7ad8b5415146aa172387541cc00d263a19b1428fa2750c622adcab13f41d1a84a72226353c1598a9f477a41cf5dc3433c38bcff24d2e058fabbb8eedd1e5d83a0bf3fb3d7bc8838b8cdf1a3954e2d156f97e3dec6dedc31a5b1fa92285ad785b2eb2996135ed6befe8f77da953962688e38e5d26cf329edc79946f75f717beab339d2eda0efc6e5d66bdef959cd7cdaf7d566790462fbad08eec5de56aec4f4966c35ba092dfbfa1aceecc8464e5fe6c8dce29322d40e564e43d627c1fff1145dd6ef71845ff906655d08b384670833a74bcb05703af1e0429503530a2fdb96fd4f70333234f123baf1a1d85e8382f6191f791d7ac7bab67f4bea168e0797d1bcd9a9b9ce6f4ff3e1af449a290cecaa7a8c3da2ea5ada4c5d92fa31fa5e48f423192aad3b8e155be51d8073ecd6cf14f779ab3a2d10b16d07bf6abbfe8fd9cc6bce8a45640fc21117dcb9539509c6a5b83499a981a1f610c2ba9374b1cc62b22b39a3aa9d891021c1a27354a33f798c12d56061649f35bba364b5021b577e71273413b5ecade65ce60aef8939dd3a261b576aa909b397cd46c9551e03ba72ebaf21398383cb46bb4d14e6a6c2463d394361bc17c364d38758529d7a99b3c9cd6d49f72ec44465ff9e83a1ec18ea3a64e1893380008c5a3a212aff9f15a39ba733aca162a0d32cb338af3008d3d3a1c56e38acb7d31d8554def87cc6f26d33c8cff47093a9317bc20438f03fd5f84045efe04649607b7dad305b44c38cbfb7997e4b21aefa6adbe5a76b974fe343ba10ac1701062d30f3c3857e3d661adb005d889277fee2ef260709e40ee55c2ec4c8399b4ef684eb7c81238d734ce51e2197f3073c1c44051f863268c4b2cc2cfe4ba6df2c02437ce97f00698f5c167f5ced4af050e8149edf6f3336df323ac1849846a736e61863b3436b5e0a9d49e52bf39b7f2bf7e1712e6dc9292b12ce4c00534b210582e3d58b56484282c2ef8ec4a6cc2f6cecdcd9f51cf52042748721c63c5d23d394f70e5c5a0366fa9606a4069f944e8c4e5b3f8c64d68455331f91e4569c2f87f42827d5b076147aa3978b0fe60ea8c2e6330717e2196ee0491246188e7bff9f61f0ed1f8fb19557168fd7b9f988c2e4a8a7fd615247b4042320ac502726943ff15788751be2089104ecccfaf184fcbb6293da0f9022df1ac05caa105bd03c8e690eed2fa43c087d4b37dd5741b0192e7a2e985413aeb01b84e05ab36cf4aaaca8a973bcc2d0104c5ec87e2148eb1a6a7a6dbb6b1272fb3b9d526743cf9abdbc8fc528d9b5bfc654381058a864407973ab031eedfb72b0665c46809de4b30a725b35aa65ad37b6d6885a9fe01ce43434e10329a6a17f287b752c8e935b0a1f4a9edc336925885544d969075fecf36720af5c40b75951d49b5df0c012724d71aa54f9a423681f76729a091562aceb6850371e2b6e0b191529f27064ea0bef41c90785b22b582f4fdbfc88b2768999e70308ed929e11e49e6834485c7cf57ae924dd47367b9d17ad68c2726319902cfd0177d692c2af0992dfd702a4317ac295c728ece8627601ab52f0ab6709565b477d7e2b277f1ebc24450a164967ff24d60011bdbfe2dc65eae5d92526658adf08318cd0c1e7e82f28a0117e3ab7534940fd2139811212195e4f55952ffc36e96fc5f586a8b78a5e811be7777cb7d4879b5a0a21e29945fdec4481eecf1a7ec45c06efdf6403706fff8f8952763225dc552609889ac4f6e93b485589e8ca53fd35466d123577c19eafe4b4c9d73dc7474b46866191377e98ea3b932e10aa0b9a25fbb66572b2425a526ad8b01a962628d2534ee240cb3b99864ab9e1bad585a24ac55f536bf1ccd0ccd20b627709963acba796b4e2ba576033554cc018f8114659af930205db0959f06d9adb4c04a52d644533c38d97c93bd17451a1a1ca1b9c65f1fb6c6abd7b7400c0599c9aa207430dad3aa5804e8f9f127d5be40c7d1b15d22027641433ca8e708dc76819c611fc85acbac49210fc84bf0f553b879a0013ba4a2662f3192c756584a6d0bc45f1a03dfbadefcfeae31379d14f4bbf25ae3553a8192eb73b85266774699821a77e3cc1676d72c7ca1d8d4126752dff500631ad547a8ae0a9b519382aac1d61f74475b13d1b437a19752909d9c29780bb61f40124b0e1669ad282937818f6eeaeac1a147f9ddaaa5a00106e97f314346367e01c11d7b0224517e90843b69af7e7a83e04610cfdbd2e06678e40de60917f761552f11d3686481069b4a15aeb10723589ba448e9773f026b65af1fb77ef48383729d2563a0ccbdfc197c0ee454a3311cac8a41d2173101b79505169e995902dc244250ec56429ef79081527478317627268fcad1ee12476ded224cec369793f8b645c21a2cc0f892e4eb591d0b1e76b325b7e48b9b6689d3001a82572598f5015dd85a2cfd51e19b0dc584536300629ed4985424fb8ca9d0b70eaf810d9fc053d7f85c8cfc82f4778618516e85666b91b3597c29e49104ac5a5207cef523d22bfd6aced08a493c325711d89573e40c04da0a2eb155e6b5845aa4129e21f32cb540e1da87c2718613eb28c128575de6c6c7a881e22bc3637b7c907050d50af0ef5d3be2e19f4a57dc53661e95855301f8820a596f30a69f9228321324e8c2a360868822ec30d242440eab23af002035e779af8e7065e2c114e16abe04a83cd675d6f01c36e8a518241376be7f4ef80ca8698b107a3c36c3b4ee160141f3e323a771a51621c8e898d064dca05066ab7e0c959cc4cc8d292093d4f7433386897e12a3cebf97ee1a3ce06ab8972f59884a2c6e79620186850e181aa614afebdb686680797e0bdf55007a8cd5037d9a84a18984aa593a08d6ead11e3303061af95ce603d3e4411e309f50880633ff18cb2ac98ca141c72f2a73a0a366f63c873caa8c301b0a0e66f89667a71345ff23dda58acde8fdda2e6f0107e4727ca005241cb2637bbbae324edaa007e145d0924383a30b906c2a40de20807732fc286741ad68d158909ad2d66d3343dc448a7c2d08bed592f7d5594f2185179751687a1f830f0aa361e2b078b03e89992147865d27fe29b3df53a2981137b961bc00d45e16239736ac51b930c03fcbf5518067995353280fda3afaf3591002e47f9c8d1ad88a043ec20c2b74c6e70550bd01c0c4dbde7820f468be866236d65683420c668ba7e4aabbb22cadb8b39e63ded237b679d8fdfcde522eebc33d18b767295f04b7a9f7b87338affc2271d40394ef33327d0c314a86b034936cacd6f7857c24a62ee0443130fa4ac46ea7fa9305085507ac300e9602b29b3194dca64dfcb282b370686f9e84d94e3a1be8e0e0c428f5f83c1ded00801cb2f6d14431c78c688b5f1dd4099bde41456b34ba8774f84a4657240c9d17d3987612c235396aeda2bbb8af9fe40469b714770c9dd4a76c8809a84ef818b2100fa07a06e77dc5a2581ffcce650a16192aa44d5134b8368260a3d5aa1dac8c6e6ffa45996d72c6ebcf7bb7d205f93b547d30261232f75ee83269d8ee950b66cc41af95f614eeec1f26bb10ef12b04bb009ba8e4481a955b77b83441dea33e23cb8147f6f6fd12d2608a61cb40fd72109420c6df46a596a1c9d4c1160779054a1c96a51c7af1cb40eb4030a5248a256665673ee8ddbeeb080f309512225673a618d8d25ed6e35ee8c17355685402d15ffffb530ca476c244fd19d625803d9db0952bd36cdc438f4f9f74eff9c019065433dea639b002da58acde7a5d8fc07f7c34aabdeaeb3588ae809409de31ae9125c808e4660da224c8e0d858d05a72f4598874c84b7947ba89c20ef8fde9c0928a3c45519f3e04d98db320bf3beb229a7c9704f6e547a1ccff8ec409aa228ea73356dddcbb39bc9bb5649ab141a192a2c7ac84097e0e97e9f159d1c7d9fbaa56a4397437750959ad4337aca914151025022847a023a1abed4a312daa0d3e4a867a93beaa634e555463a00618b6914d2286659181f1163dc15b37722020e4acd5847d640d74f7fc48f1e2f9fd92d471e0002f3f9d7acf10110cb8375c7cecf23d295e11146a6d9fb4cb336cf34bb6d32c98ae513d0d15858e7fae19d2c8cec469a229127161215a644cd022e5d6d4bf06554e6bb78c76412011e11500e98600f2bb90da43502bc4179816ee0391009b0343042c198fb66cf52075716eec2258220a04b70b21811c94206e8c86fa05704d43fca4a85ad07d951d939c449a8421e622c31a5d83578434fd05eb9d738880bcab0e20d614d804c3e9e3fa56231d11371dc4f41aa3b7f36686cfa743713dc749efbdee6a4cdaff8666c740b305dd984a0cdac9945aa2c2b6660df88d7c29961ec41e3514d6e005d51cc1e51318b43af90b24b2c26637c8fb8f7ca23d118d01588708538ba684cc7e77b023077ae3c1b1375b2a360a9b3620c4f93a8145e2c8a1eebcd97fa8a012275f24d38422078bfcb04794654a1ad3c36ab73204177a73f9b5294b79a2a0ed442f5f2a64b22ca267e979644609a51e662fb834603ba05baf2eea1a49b181f06b63d049fb2dcce479122c2c0bbd66a376e2169b1169eff26c64b451b3c031134f96b66980be37c0da1724ab1261ddabb7cb4d4c9f181e7c346053f4d4aec1f9c792a3889967598c1b771381b22920cda1f4f8bcec439e7e0799e9898b7e51cd79d6e8cea5a303ade6c14cfdfb1715afd16681a2def2a5d31e22d761ff244a5d81415742677af783f8436f8955590a128ebdbdf07949b188c4b25a36030d31fc03323e828997274b8144f9b3acaed8b37174d7caad890087e0a6abcd8696ab0b68112272655559bbc69bd836300203ebc44d1d4ab10f16c4127bf1422a6ff84c77918c58471d8754935c407bd01abb6d1af57b7538aba46d0c6353ce3415c07bf6d049905c5de6be26cb7b681056521934a24e94225c5483e558294dd066d2d8a65d6768ff747dabdec6f95f4aa083d253c1bbc53bd9a5e1c4f86e705ef90cadb98675a01bb87dcf3cc73d3dbe425d36d73a6f66c828745efd1f9cc73fe7941bcce9637c15fc47354eb4df1c07b9efcf7d9471e7699c1493e8fc35ba0c64f8970ba87878a0858a4557b0b50eb2604aec050963cb4ab578c8c9437c1f3c71aeae0e5fd5408a70c1e0ac01b94cffb4be3ef449d83f79c8ab0c76e1e7348515c38590c112825f76764ae4a890f78fb062c4d521705f6fe72d61668265eb064ddb74592fd9ba2ce120ba6d7272e449a71cf0e165ebcc40541f85c47e1e6a405cdf1b95c572dfea0ead126a0cff9b0810eeffe9cd032e0fcbb87b5127600ca480eb834e40fb01f8ee1708edfb2a33518db637111e33b582b6a8b0114c500f4acea6bb334da8f7582639e945e1a50c6eadb6664712adade155c4feab69f64919622ba8c17216dc0132404f9b736beed8a637803849440d540bc66d211be82614431f21629212b70880c49c2ef96685209a1a925ea68b011d683c4516ee9046c3d4eb5b65e4f9b37021aabf95c2f695dc8b4ea9019d2238792c602f59a487e4613d73d7cbbef0d7f8d2982b14870dbf70a614a5038cb1a50d7baf5ecde8e480d299e6fe8542e8039430c5d6c5caff185d2f842af9e825a60a9af57696a20abd1544a30ddc23c1105f9ad5c25044b3fdd03ecbc9ff5bbb5c4bd7c19a9548cc923c51bb596d50f9e61e1b9987b11878ad6535abf9634325d5acec033b45b642c793f338cf0ccd1e15adc46c4333b55e1717fe50bb968a0b10e1a8a3002f1e458312624a71c9219f1c752defc60402028588cd260023d48fa7f530ce423422efd2834f3cb6804de8e3671cd4348af5c8b46ba6a082b0ba74d1247004c6d5db81068a4e039f288e3a0c1aa370f3dbec6b550d0e2057f8af0e546927bbe1617c6ba61057ef5405cc90dbf925ec31aaca7d2831aed7ff307b9762db5a7d069e8d169f5ba4dabadd021ad33b258648956dd5229a2aab0a73c336901066781888d26264938311290ba18de49810ad26d51e8105f5ca0e54710905291b1ed85dad6c023949efdffa3485b3dec034b974f663f34526398eb97abe045297a9150d172c4125410984e94cb289a26abce2ab1a72588d4c708d70901724f9edde02821a9e0089536304cc34a5d2575447129f689fc7372df751b7a3895840f27ffdadccd9cd4bfd3eb7e650c6d0eae287e1320cabfe0bb4364303cfafae27af953afb78b8731b99918dc793853350da770c2a7a5010a96949cfe88f485b3ccb3169871f46741992e9c0b0e9edad5af6a3121a1c8f9c44fdcccd9d77bbf734136a8a1dc4182d6520e0e0be46e5fbec72404c5a373f69dea950415b0c59d106e3d76d2bd441349c0fb12af4456e317df5003bcdbdf9cc7bdc55def59e41c3e60331482ef737bee46bdab8bde38651dc8b9b70a14c797c188c3a7d154828cae223f215723bd2234cb612afb5bd8c7bcf6e0d6100a5f6f4a5bec54c018c6bf4244dde57ed02c9150de8856f7ab8ed852357aa1013aaf362c9984817f9c06fd2193ca2e798012eb73b31160dcb26a94c0dea7446cd7da39849024d324b19458d49ca71c7b19431e2d5acadc8eed25bab38faecf356b43cd165f215c5c4c91c6a999213d15fbd8f49452eb275096eabc17470a991378165fc810c0bc230cec8b2f0d2aecd02da835b310763738ade3cf4b7bd701a2af1b62da28b570e110e683331d0f3d81e18c21a7fd6d7de1093ee4b3706172c5388e433330d8178f402e04395fe0cf0e53152c960bc7ed3e4fcf057738eba53403d86441055297b891e62d2ba57be174437411b6dcad79dd3734546a7e3f47a023253df46b49931778ddacc12c797304c4aee2e5909116d143551d59ce2e36d3592fe644c4aeeba4f80b0af45e545b8e13e7bc30e0bb5013c0422f44bc4501f3c8eef5f001f501ad6506b0f7b7784e8436fc77076164b4e7f441e547a5d9c202dd5ccfdd64ca3628e78842cc3d13d5cac27ccd974fbe8d48fef5edaa99dcbd001a741e583ae81339df2e5151e8f93412b13892a3d279911e526d87d071bc4538e34593d54dd099a7255c5c19b8a64b4269574c90a00082c24921c5fe4590a40bf0003686555dee4574461465a088696c4877a26fdb34a925f530b328f64aaa701809a61b3348416de04733629860352caa3d1007599d1889de0cdf06438420fc91e4984554b1564be001c7f1f230956ff6322c4f0174d48ef893d30c3fa42de391f66a72e2ed2427f2ed33dcf2983c11a8cfa039a908f95c9fddc4cfec08d1d910cd93db06b45396a3882c8ea0255466676648255be11ffe2122d9cb6920dd4e658fc9fe9bf07f7da23b61e892532efc7ed5e8760be0413bd03b2a9bafb1c81020ff8d439154c73fd50229b05584ccfa98c394e8383cf077819eece1bc0321403ae4977792be719a09d9a2a2249d35a406e854112df13804f93cb7b83508eb74c8c5497b897148d0bdbb1768b51cb09458a8f79c42d3222d3d35dcbef9965b98dd3505f5b8b060a2d255f2eed39c732ceafe26a516b85167b8176871a411c15ab086e6dd2c3ee27036080e410ebc2889ef60224f3fc95a32c2f760bd607a1559d9819130020209826b86bef9c1e25ffc8003bc2cea31e486fa1641c0ed41132611ec016743f83e718dcae4dc6bac33b81f7421b1af4eba52b469fde083003fbbcae3ef0893a3335ebe42663d7b1149727bb68db117c4b33eee376b7baab15e1bd46eb84cda0e6e6f56fbd5585420ca64b43f99444551105fe70e247ba1ab7e0bd8355588a6b2eb560749b5612e571619d335803bcfe68655ac47ddb8b814793bf0e96da53f9728a77da01b4d65712681467d32185f22966da90e39f7ef6a4774d692f8a02710dd70ee1b598e47bec09fc89cf0b06bece904f50d110c35c6fe6cdd7f4d945bba9b7e3a9c4271f52020c38c9af592d8728b394d9b84faaba36c4d9c1624b35eb8d788f56b1833d2399645fb72a9c7d6f05e75ff682920930c5661f2440fff5abab6a4f7c87873c069fdae269d476b57a102e9e24ac1218e4b36c6b52c73e92d631b0c9d81e1bb4f779b1a53e3ed913a77cf62385668a244208c88f6e6777bcd94654fcde97265d61bc4f0a3d029253147302dcb04cf5abf8d2ec33c0952f88da4c151aae0ce9bd67a10265a3b98206a05ff23cc2520706a499032e1e05a059b9c5fd33008239c2b09569931df0da4a3111a89c731d75c31c29f0600c458438255fa6d046630cfd8f3e6880f425c67d9f0c7dd3af45532d1b9e86bc3429843548839fc5e15ee58479c37d2920ac848d31b6f75a7b0bc6ba71b5d9dadc9b9145aba5b94c4b614d8e81859bdd9847fdd222aa69517070b65c9e51cde55ce908bf1c5c86773ef71ccb7ee39d139461c5f18d3f59ca921f1fe2d877ffce2cf1278df99dd70ca4211e3b04ecf1f51ef0814515d2ab95ee3f3e064761c25657a3c52eb848500cb2042057991966be457d4886bb5663e973253623f8f604ff800b5449e809aedff2ea23e7c3b9ada5c0893fdcb5947ef9b00df41d4da7f0a15e9ee905f754cdd9c9c2886dc731056aaba3db5a1b1a05a28fe98e5fd4948ca121a40fb387f3af5249cb4e6859a8ad79c3bfbaf55a6321ccfa94b02c12805c22f1c13332cb397818e5dee670cb6a402af6cd852553037eaab86eed74cccac9a14bc880b6c3e72a759d452b851e1a0bd66fe929a7781ec3dde77d250a1544307ff04743d96a087f505b3b80035ef7364e5bcc6a9b7b31801cf222e281e7a2fb6205c7f59dca7cb05d86297b49cc9f25435ef506b760e963d3f3fa609006d25671479ea70a34258eea7b12cfadad0a35fce8d1bc73649824e3d5b2d08440548b325b54a060ed38f15c4652b4cff8821f3042ce407c98edaa5f7e51d464ace071d1ac300f5c27324ce508a04bbbd06a5a2ab08b7e3971ba7b92b5b604e361a38a0d64d2f757a6694703e9bd7da750f807ffa26a2a8e466f9a48180dcf5fa4876e52b4d6e8d8e940908804b3732b7aa9a89aac8825e6ecfadb2652354151e290b0404e7515af470738e08d90136bdd58a05a108b5437c35bda033d511284c450410f4f4c4ccb7c710179507a34127569133dfb87357789bcc651935fd760206d42cd98ee86eefa42761d5749fa4888df0f20385fc02658c0247235ee99eb87055502589539cf2186cbacb7ab9c28c4ca91f45cf86a47aa783b71a75a75c5ba7b5484151241eee77277cbec0bd7e96de33be74009f51bf3ba60328c4ecdca486b307e812a821a4207c877bdc2833cfac604d924b6435f0613085a6595745abec450862f21b580f5855716ab08cdfa99c2079c7cde35e9ba44d3132f5468e14bd034fd643c0da10006eb5ae164df21732ef7015454b01489c686d33ad9a090130ebb84e7d853a1f7c5dbed209ed20a1ca7a9e9efe43f2342b203db0a59754675bf86f194b09181af8287ebd83b4ab99bb5b2d5bbaaaa80e410f65d4c433dfa2a6af447290e3340d7cf661f38816d384dd65fce66f482a2de8579b548b381a5b7b61dfd0e70eaa8385bae60b7853dcea92b205b521e4c53c3468984a3e54a51609c5c70280096a18ca880301dbe7b6832fdb951cfd63904f5aac79dce7303c73013d96a58f1a8dd736940ef8a71c9909f774490d3e1fdcec821de3ec9979373f6d78bf41fae6a890719a2cffeefd96847863277f2edf9ec363c0efd18f55dec83849fbaf48ba040d8cc67e28d85be8b5b2b23fa996cd8ee9001df832f40ec3f84d565cdd8b5071ee85e91f8a41eaf0b08903ed35ea944e607803fae0c995e30946c4403575a371cc2938890926d2b568cc3b6e0ead5483bd9e94e1dea710922e7081bb3b2e7d91d076b5a08ceb6fc798654fc77db9050ca9cf65f9c56a99a501d02431d700a76536889cc16d7c9428d1c5ec28755d3d7e8d4f3895aeeb3432264a87c313912fec9ef68ab8d477558a3d5460aa46129a0c3d97fad915897db7cb52c00e5cd4816155229825a85dee61e562399bec571c232556f647a1cb71e2cb0302d43ddcbc5850f5e950ac0ebdbf47d4706809826e4888254f03e2847b4663453e4dd0dbaf928fd0d7e49dc1a76a2cd289ab55432efadce37b7ca00ec4216a252a4eb351c315471474a1f6edcd9d8fd1c0f2bb9e12117187d841099cedb3cd9ff3be25fcf3e82745f52b3e530f487ce9e31cb4de4c5ec68ce83b0158c77f3821501f60ce807050fdaef4b7d0ef4edf427de3b442fe49bf413635e61b01e049a779023a38f10c2de5b9cfa8b8f30d73eac844ae139c4200616fd88970f24d1f2b47aa42a5d36f9cb772e5506e61e6171ec938d5823561e282c72a65ed78fb081616d0891c5ff9e269fc5e824d4be72ff142274c9873dd29c23584cb824a7953645cbcf38b3bfac19a271b1b1e63c6aeca627fab1800e32aac7061c78838abededec12083b2b5a775c8794a67a9af66f5a4a0974b946d5a14d1a3044c0b11e2661c56bb88df9498198d4aa82157e977d87dcc57f1617d965d4cb455c61fc5b5d04030a385469d8de857dba5f812e0d240e5d77bf997101df8fc4074a920f4344f9f79624c90fc2185a18d87d6a813bb4a9f86a70bc1a2902031f37a463d80eeb7bef661e27ba165bd243f0e4a07131a36a195621f5914cdf6f20c65954010504870ff73567b24170054729d2b470c47f158ebd45d8a9630d85c05ab059985dc853802ae6afbaec633f3cad834b54d6b5d059720af48ce0340e2b0cf8661d8edd3297f580c3ce20b8e382672e1088d030141b3b6260ba1ba4d629d4f123a6e150f43687882b10a2e8818ccd0026ce0abfc3457e71c72d3c4398a5a7291bb13f6676c091c6eb2a3fa0b827bc8d16650a415e788e9bafd03d4ad97ae149e4fbd731653cf494c415d16c15ec4d33d42e97b99ad8e30beb64412a42323a7f339aa45d3f3ccf4507121d1b4acc0680a21fbda6118746f07ae12dc5adfaeb3d127ed044b78c18975f22c654f33945616d707be8fcc69c11fd4d658b3e206b2ef9bd0f466def3c6d43f5ad377999f9f31197b4f12c5612165e6a6b1acb542bd2be01d2c71a5739e1097f039d61b8def26aae03a6a764df8a8279996cbf855e7bbee0e9aa45d12b14569a784fa4366d39349fb62b1e2a602feb15738d5514246e714bb75e6f55c3795cb45b0bca11decdf431b656e89b45a97571a7f55821f75e868a42d29bc42a3e7dc773d39051e55264a17ae242413c31e89af4bebe22655f5ca13f9e628fb407a16b8ea56194f1018f36870c49ca808e54454d69bd184708bf33114d56251380c254e07f86e16bb2c3b5754b41300f04957105d7dc68ffbe9073c3098ce21485852d073a7c5795b3daa7dcdfc4aaeab03520a7c61acc9ba081c7d00b71c90fd07fcfcc85a5dcbfb059b8b0df4693bc5773966a7ffe5882687bab6127940aa2a16af55399e363a8f3128d1613a11cf71d3b2f95e48a88f98d6f496a8303cf785d1f4d30d88651e82c8ce43315854746abb9e2924cda064827513161a28a051133261349689a2faca602eecbc4180c3150b25472c33f3f3f3f3f3f3f3fbfe221b0b1496e694e7fa5e7e6a64cca4caa61140000a300b4669b66fa7501a380550004870b110c370ce57fae9040b0229553dc8ec3f4bb0282f70aadce39595e56ffc0eda658517e261e513fb0b1eaf207216d07a1f681ddcc95b2931c8da67ce0aff3fbc78d35d1937b60b2f26a0e7aea81cbf4b20e53764f95cc03af39bc7a4952df76e281cb4b76eb91e70f39f20e4c8c9863e4cb717f1cb4031ffd6ac7f9939ee6b10eeca578313aba8875413a3016244dbcf28d94e01c18eb33358f7278e18172e0d2e74e7949731c24471cf838354a5fcad0981d1cf83fefc8f17b10bab637f0f9d1bb7906b33c3137301eaff3e7460a765a1bf86a4f5e41670353f12c932697a89635f01e723fd5a6af704b0ddcb77ef87135f2a695063687e68f837839cd2c34305dab51aaab19b43a03b79ff22dc40c7c64c924bf4a07a153063eb8747bf4edbb0c19b8a01dfd6f5b4e53c7c08e57fd8748470cbce7f657bf4e18f8d03ab8f9e5c8b1c5c1c0aa5b4893693ce2e75fe0729e9018dd036d8d1738d70fd9dfa99e6cd305de2248b41cf4fd480c17d8209e2db0692be57fef285f5a0b4c0ccf397db2c0ee8da84715d2e5c002ab9ea3f5d29c9d2357e0ed3aceccd50a5c8a93c3f1b85205ae6a722d5854e063aefc217720554f81adfb403549c8e144450afc25afb4dcb9b23651e0d28e7545d574ff4281d74b1d5ed55f80271c9252b3c6bc13d8e49719a52d9a8bdb042687623176d65ecb96097cceae9de38a96324f96c0e41c3b4839addf07122570492cf353c8549d93043eecb073ee8d047ebb3e238ec71edd23f01e2dc6a9eb7c018cc06bb54885fabc48e617a0086c0c92d972d0a1abcb2f0011b81c574f5ac60a3905bf004360a2e8b7e6d4bcbdf00b2004a6d737d5e4588cfcf80204818f69f2dae7f4f7f5f105000263db714894f8e1bec783f10b2ec4ec1b57a525851c0f862fb8288b99237bc1f724cd71ee783078c1457f7b6bfb24a13b1e8c5d30713d96ba20ee993a1e0c5df0b179578c6945d27f0f462eb810a3c7ee7e5f1e730f062eb84f75c9e1e51e8c5b7029784473cfff34efc1b045153db66ac1fa76c5cad92942be68c1aba46e89ce91264bfd2cd8b34bf65e1e2e0b5622c69cd268aba5ea63c1e86fc59dbc29f5430f0b3ea44715f31a8f3afd2b9898ef3907295bb546ef0a4e6205d30fcf46c7d30abec3b4cc61072bb85831540e234e04efac828d99bba35533bd56154cc7c80ded51fc187e2a1849e9fd71fc8f56e3a8603c7b58c1263fce9d53303abe95462a3fd0144cda6e4bfcb28fa34ac1558ef3e85d44dbc99082eba82b0ec62838a95092e949cd238b83210ad6d7a38dbe4a28b8de389d9e7a2c4715507039dac4cfac7c821d9de4baee5bf9b627b81829bee59eae90dc4eb099e9953935521297136cfc1c9a6a79bc39c76e82d55069a2eea561219ae02f4f8c93ef3fe42824134c6930d760124cb011436e9334c95207b904e7b795fdb2dc2a554bf01d5ec86d51af93d24ab0a95fd2754f4af0a5591d468f3ee70d4e82df941cc458a32498b86dbad375d99318096e3cc4689e19b4420809467bd3e758ec3a73c72358f776914cb772ed70041f6a478ceb1dd6564723f8aa9c3cfdc756793c6704379d537b83bba676be082e9deedd4aa7085623a649a407121e4b041f66c93f5521376f86083ed27d5ad4891d323b046b1a436a9884689b32041b720731fc26e4cc94178293ac5c1bc9f2e620e584602f743f088d97b7960f82af088d4c527983562e082ea4ce548b29f661c803c14ed75d4a355fcf1c40301eb44b7a5ea4d3ff0f4c743535d70f5cdf7a7b1e7f0fb2ef03ef9f2269fd368e7ce0c3eff71c5d9687760f4cf6782fa5765696e881df2429761ce57830f2c0e546e7b4a3b9961b03061e58dd1452c8a71335c61830eec076e4f0959668b31803861d3893a841347d47951803461d78b1d8c14b54ffd36dc0a00367d771472239568dda8031072674f9a6e572e05cd4f27be8f4381907be63997ab9e4d8d3c281d31ce8d54793b2f70d6ce43834689aa46811377059338fa65abefcdbc0f4a88bc4081edac20636e6c85e73ee7a6a750d7c89c4983b4d35709e5252462dd3c0e730259a77341d4744039372e758d3079e81b7158da9927e5d6d0676a7ec7c2a5ee4f72803df9145ce31a7205e1d64603b448bb1726e0c4c9ba647be2a4db6183833c3c06a442e8fa6966b3330701de87720591930bec0e6fbc721f2a31c64c880e10547cd83df7f64bac0248b1ec5f3471362b8c076e891f4942db09aba933c2db01acda4b39fc5089d2c3031ad520e2c8f05de543cee94e30aac69dc8db53b55d55b810b91a15386e47184be0a7c1c7d464766bd4b9d0a7cee1b6bfbd6cd69330526bd9ed596460a6cc80e92e3a84a251d05ae4e3f887b7601030aa6249221eab1058c27f0f9f33beb72e0516e0b184ea02e67dcc80b6902a795249ae689dcb184098cc794c3dfbff315c912984e9dc30d7d1f3b234a60f28edde4ad987591243099affe3b12f87e37b10ea29fbe47604a62ea9de6ca4baa11f8ec717f24ea71d6a745e04d42f0379190c253223099339e27cf1078cb4c7e17cac35c1102fbb1cc42c490930e4610f8f43a6e1df4e6980303087ce8c9cd6297bfe0926d724b66fa8249bf1b3287f88d057bc1654ca92cbb684e09f2820f1ec4d770098f225876c1a6a6c77429ea82ef14cfa7d443ace0e582bbcbadd54952868ec3056fbb1ec4ccb92aa7d82df810c37bd342936bca16fcdb654bfbad5fb16ac179748e2bc5aa6ca92ab4e03f7dcaf34823f54b6516bce78821dd279745a9c88289fbb59597738d1d0b6ecca2640e3e2cf858a235047daf16ff15ec74ea90c30f1943ee5dc1b64a59b6ed5bc149a4dca16394a68eb382936029e4a6b1feacaf82ff9861e21faef5c455c147a51d55c4d5cb104f056b221d4f8d4775a8a3820f3b8ea8ed71902a99537062922e193505931453b01f49faf3f0b3eed3a538f00f935a789a147c985d66de9a35df1e05532e796e137cc26b517015db73fff32ec77528f8b4cc4b3935a3a516148cb4a68916ca3eeac927b898246bda649da3219ee0b322a8e7ef78f8924eb0b7fe972d4ffe0809279aa8f136c975139cea04c914b27774ab26b8b7bdcc0e72844a9a09fe4359c8d77b1e3b89092ec71b730e32ed7b262fc19a97de665868ef484bb02ff9c5f3a48eb38f953063d050828f434a21f7794a8993e04e4287b4fd0b0d51125c5eefe439a41425c248f081a414735ed51cd60724b8a47a1699ea973e8fe053a48e39a576ed1447b0fb9a721cea7523b8906f633abd146bbb66049bdbe793e38b6043a6ccd39ca3b46a8ae043fe8ead56c2f4b444f0579136638e33e61b117c947c36297d5ebeeb10ac7d98b6c31c444bd93204dff6fd710c9dda3fa80bc17e8eb4347fd657474d08b6c3904a3b6b3d729c41b091420e9dd925be1d41b076f126ab470fd71208eea3cc659923e4407d40b01b27f2bce3ffc04964bb9565a4d8713fa82f91225ea50ffc6db0cd15fc553be7031377637b8787a5ccf7c0474992fc48228f6ff4c0574e871e6b3c3d79e06274f4beca140f163c701d0689e6793cce63b903bf7942d2c78fdebcedc0e54bed4fb2ebc08712a3a7a91c6af4d0814b15d2fd2773d8d3c7398e3a9ac8814f3ee2ea917d040989032fd213e38514a472040e4c5964e6939473eabc81cf410a71427eca6671033f69ec3dc2fea36d0393438d51192a1bd8501fc4944c3b32d435303932a428a9c93e48d5c087695b39d0320d6ceaa02255336f4e251ab8cc2f2148fdf9fe7806deb23ea6110f9376680626dff5954f49577594810be6d1f6eae5d77664e0272b5f2ecf1fe8c6c6c069a8ba9c2f764a0f13039b4cd73dd20d693d0b03af9582a6e40103e7996d3a75ee9b7e8189b4d7e821b162585e304fa36f4a9d2e30216aaf049f960b7c875c29e6abca4ed26e81b129fbec23ad16784bb5f7141e45325960b249c8cacf16291e2cf0ae7ebe2931b37be70a6cc839d6b6ee7d0f6305c6eb3e9ba4ad55481558d1a9e920f754e0a3de2dcff3a3cb7e0aecf5a878865e0a7c47e7385e8ff6b18e022769937adc39a46a0305ee2e93a7ec255d59f3042ee79a69ef6a5fde09ace7c03ddc9bc0a4dac951d948ba0d13b8bbf7a9fc2884004be0e284903ade60e195253408e666ae09b6a30f2169ea4e345d32c155e4ddfdf8ca36f203137cd0789351f7368f2f7817fcba805ff02ef80ee312dc5abc4c16b3277ef05882abf6509ad3a132b4ce30e3282b6154e2c8d6cd398cc8a10467316e79dc297e962c93e034f7f4e4eb13497725c1a70eea7133c736cd31124c0ec4d433d8a4298b850109c6c34a96234453f11432c27804e3e165b64a88a4972304613882fbfc49bb11f38d60f2bd784e31d4479d1546f03f5929f249d48e83e8221857c9b1675fbfa70986a1082e3cfeb4e992a40cad31c618638c336630c6187d460d7a13816120e2c608e310e77febe83e118461083e5649aecec93ae4e938d405611482536df5d78e4a4f631d062138fb89691d769626db83e0cd927be65a7da4d58521082e7a70ef7c1ea6e6646104828f5247ff1ecf1353bec200045be92c447ae8c0438cfc81cf51fac7f58c1fd82cad1e558a173fd6541f3811edec38ba90f73b990fc2e003a71d058f651d6dcee9ec818fccb2ae50413db09d7cd22509ab4a9592073ed3c31c1e638807cee33079cc97a33b70953f8e33c7fa495dd31d84610736b3e3f82a0ec2a803971f216cef63746042e6499bccbc4c6a3307aecd6c54525447969d1cd811afcefc1e19076efab4f7e376f4f79c8203dbb1ae6fece8f42e585408e30d6ccccccc164277031fdd81640fcf17cfba0d7ce665db89e961c690610317f953d9e4c8629ee71a183f5d916afbb0534a35b097ed753b35a1391cd3c04e0a51cc3386a0be3a1ad8f3bd1c57ce9a9ce37b06ee2aecf762beccc07af630ac36a40e831554e0781046191857adb6902cde8f7964e07f327898f36e7706cf18b8a0d1636df51031b09b42aa9d6a93e813828430c2c086e68e3b19543070d1a3b8512958482be117b8cb110f5a25ffae2747185e603da5ff68bf1f0ba30b6caabf57919c33a70675100617f8d052693246e6eb9d2c0a616c81f3df4d5df993730cde0b1604616881a9c8513a422dcd52c8b18730b2c0fe86eb479b76cece868105c6e279a6981ef7dfd4615c81bfed1493a758953a088661056df2c30f31c6dfcef93f184615d84df13a47317efe45461b210c2ab0993fb3e3601e87eee31458cfd11d713f0c2970965a57ebf3630e3d5160423249ed972757db79868230a0c0daa66433f3ec61bc5020c278025395f726a494fb93629cc087541f2569fe46b54c13b824d593367d6dca95c2045e2a6378eb4bc7b1a42c818fbcf227b13af720ba4ae0623c9d8e3e9a654c3709ecd7eac6106d15c9572430ea9ab37354d123b07e2be1e1213c9e381a81dfa0632958945c1f824560b326692eff4cb6f98308ac85a764e61173a5ff86c07e643eb51b9a10989038be51b24f0c761058f328bbc4b1f4e84c0a03084c468fa3b6e3c81052e717dcf7e42eafdcc841f70593317be0a187781cd2ef05e329b9e75ef5974c0d2fd8efb0a2b3e577174c3ecdbe395c4d17dcee8defb7e77cda6172c1e41432c7cb1fa47e1c8a0b263553ee3cadd398730b2e74107434055d31136dc1664989d439a3ae7bae167c744b31435c69c17e9c3cbc2bfbb03cd066c1871c442778d0d19005ef932f4d07ae1ea47962c1e55bcacb71944e3233b0e05fa3a3caddb13a1e5fc1ded9ea4a9e1c0721e70a56522488f5c7984deb56b029b13bdd8ae59074c20a3e1eadbc922d27ea9dab6042ac98f552fe79eaa8829b68d937b58906b14e033452c1ffe694555443c727390d54f07184ea20670f314bfe2998142cc42d4d932938f730abc518371aa5e0537b5817828648c19705c9ba9b937f1e63038d5130153c6d697845148c59d6cada2e6e559150b0ebe671e441e6a4ec0b14dc779c727ce92289e5141a9f60f2b5a4183afc3873f8d1f004d7718cf4e59fca256b343ac17767eb6c3675d617a4c109aee3f4e44d6a96e44fe3d83a7baa7b99ad092e4acecd58a1427256052b60c19f519a092eca73103d3e9acf474c188d4b701f885844c4f08c2195020d4b7013514fed63d5a5eac719685482b1891c9d95a34dad86126c797a4b884e92630ba13109aea4af3d327aec972e92e0d3fa8f44e89e48f18f0417e1d1879843d4ce9d8704932ce66cb5d9375f873e82b1f21c55df4fb0481e0d47f0715dfced5472b22b1a8d60bdf3ba8398e34fcf7198800623d8cf899dd2ae9e79762c82cb9e3429519e151da7033414c1a40e37c690f06824828f6255f43416ccf4541a8860b3c58e7332e40d0cda9061866f0c681c828b9e735c62ae1d06af82262306358041bf0b0c0d43b0ab7d1d121d2bc4c8518656cd804621d8a9ccd1b3be55ec143a83062178b5b434ed7639f4f87e41c3800c335c734063107c9462f964766b91e84943d01004ebae617d79c7ddb70f041b4983f407f350ed3733d000049793aad245a598daf13ff0913b5d5abcf36bb4fdc07a0afe5daa91a309da621ff830bba7f638c7e10217aca0f0813dcfdabf6929dad38334f6c0eec7fd9ba2376ea0a107beb355eee7dfaa1c3134f2c08ada7798b4223cf0591382db5404a974dea0394077e022c4e390b32abee76b0c34ecc045e57b101937fa77a80c1aa800066f810e6c5d1db83e3fabbcdc568faa0d34e8300736c4a8ae4e297b1c960317c420068de4e4c0de7f744ff97d299a180726ddfe77353830eae1c6ca1e0493e8c03770f13248ed7adcc0d64a57941cc4b440a30d4cb6d3dc72f7d02fe6d9c0455bd14a151e84c61a188f83e5c778e91768a881b33dabd34e9963e83864c081461a98bccfdf4e3f8a80061ab838a9be12c173540759008d33b0136d7a3d0a4fbb92230334ccc08558914b542a8d028d32b0772e392978060a34c8c04f4766f57d68f3c839838c179871c6b9d280524d80c618386bad983e6ef6aa9a2aa021063642fe389aa55886d681031a612030b09e6a2fed85495a2b70410c62d06636a0f1853d6d56f7756c12b532b4687881b39446eb3fcacbd09ac1cfe0cfe802dbd271f41df484f230598696b9800617b8d5f7a8b3da3c684b51b180c616782f9b48bfb6d14a73b4c0ada7a8358f60f6d19e05563b74f83183876588c1021fa6daad85042feff70a9ead87b8d6162b70291e6de7ec359152abc0a68f4c969eb6ac46a5021f88646fe53aa7c0e6c80e6bc76387ff91021fbb6290f44481fb207d57dccb39a63c42817fc9ed8cc83f818b122ca25ec766d5111cbcbf0d1e6b40c3095cd0adcebc3839c0ff3000c0814613b88da57bd13f5267db683081ad98313d5aad2df74a06591a682ca1c6a0a104451a49b031905063d03802df92da399e8e989e23970c348cc0fdc741b2fd483554fb45e042a55bc8e81e3c874e0d3488a077142b87efa18ded6568bd195e3ca03104362bb68ed4c5888eb72ed01002651a21e251ab749c528e4986078b0c083482c0e520d2bfd5bf4d4aee8c32d00002e775c1a53d4504c9f6a842017ec1e5b0eb3cbde3290b9a02f882c9b154b4728f3e767c51a100bd60fb53c7183f4ae6196d180ac00b5e2f423f8e17f2acfb5d7021a4549a42c6b451d3ba603b4796a85ac9b1643517fc67c5241a24db34555028002eb8d839693dff6a76eac8a8d243016ec1068b999133dbf27a98591f0a600b4673707b9758d92a786ac1a4e8f4ced7a8f5711c5af0d99bf971aa743ad59905a71df425dd74ca82c921e64d1f46340daac782ffcf99628ebf2d5ea5c0828d995a3fe593e892d95770e9f2e68fa47a49a17505fbf6693d993ff4de482bb8ececdc1eba3fe45659c1df8634318dff7f0773155c96f65054a55405db31a3c7619ba32783a9e03c7eec74713bec2b880af63f8ef43e07d62938cfa99ac723680a3e7d55f75f785c31739482ff8e3ea5f59c7314f59182af1d3d4bafa951b0e691ee4a55e8258f28f874e9bd59735cf1180a05ffd13925677440c164e57af455b57969fd04571ea5a91fa2ec33ef09ae34879690dad2f2b0136cea28513df23838c144dfe4c7ec6f829364e913553445f2a3430134c14f768e9ef3bd4c5a2a4026989032c43d4ff78f2588092697998478779b110a70093e585bce91e86e097652d2db8ea3f0cd71490d05a80423a2b1c31c63bfea9445280025584b13aae34c933c5e8d150a30093e42e9664969fe5c8942010cc13ecc890497b45379dc595f3d1e124c674d67a51021e28fe02fb27ade8c69ed74049f2ca2cf737823b88e3fb68e9133820fa1935ac6dc1d42b3083eb4accee3ab15c2a2087e2a9366b590434e9544f0571d64ce6b23828f7235df985e8e601f820fd2ea61aab491c23604d3d6b1c73aba109cdba6ad1bd31ca72c21d8247dfd418a5b21b58360472a3d1669ad4e218260a2da727003c5689383d0492c9a0aa62ba76a376b6be81c15ac07219d295687a825418318a7e02b7608db1c32e4f8465330b9a742c73947bae3af14fc4847698f34523039b1236995ca76c1830c3146c14d7f1c96a1f57662c410051f74d3d4bd66cfd13e628482ad0fb33ecae91e3aa618a060b3566ec95a955a1196a19583bb81189f20627882ff20af43b5d2328f2c0d6274828ffd2be5aa0bed29fd32b46ec009763a3b7aff6212c9d318c4d80497dda7c47c2b867d258626d6b839922b6568b5c00c33ca7081afc08c10626482b5b70bb93d2964c8970c6260828dbdef2187a81fc6fbb20c625c824dc145434c663a6a1de7803268b08210ccc0052e6880011c6000187cc0000e3080030cd0010378c0020638a8d0127c5cbfcfb1d92706312ae19a25318b1e25257809be931df5425664124cada5ddb8112354f0be208624d860793c861cb8013122c185464f8cda9dbbc3be0a6240821109bd94c371cb28154205311ec1bfc4fcb03b4f56248f32b4c830c34f066238825b75f3d8d1be1d6688d108264a68a7c7d70cea3146f0116f63a5a07dfb6e21408c45f01d2c337dd02882554d957224ea413ef513c1774c17a2a79083cc410c44b0fb92d29a24ef3c558a71082e7fb277734f1b828b122bdae47883871029047bf6a3b97d1783106c5f4cd59fef171d688360f3e78e38a6d2271ee41a21862098a07a57e521f9fa3f6a108340f0be217ba5a73c4e758a01084e7ccc3b76fcfc810bfdfee167e37174397ee02e5fa67c5f925197d307bee3cf9159a60d2992870f8c8f78a6ffd0436878f6c0be7b8e39c89efef08e1e788f27a60f569d3cf0e96fde51aced20d5c10327a172dce1568c0e357f07c682464d9e35e7d8296f0736c71d86280921cc255f07aee387c9337a74bcb1a703571fb77e8c9aa36d8bcf814d1e72fd36678fb6b81cf83072ea0fc48c037ba67eb14a7298417438b09d83bed08f722269dec0e714430eed4082dbc50d4cca90c38cdf7ea9b781c9a1bb77a463fb940dec7a7d1047d3a389ba06267eca148d21a306be2a79d2d0d7754bc7c14603b769222a5db6474acfc0856458c75f3f0f4933f01e39470e9dab43fd2865e02bb5dd7dd8498366850c6c5772115db7c7c07ff4f4fe1e5e06535b0c4cea1b5f5fafc3c04ff0389adbd633ea05033751f5e97168b19df60bdce4108f29678eb12ae2052e455bcfa039860555bbc07887672dab758da1728193f08858f6133a5eba05de3c8cd1263ed5b9a3053eb61ca95ad4b3c094a7901d4fe88ad4b1c0aea8e4fe770eaa972bf0a97d5744b25660b3a4ecd19fa1f9c22af05932669df42515b85cf7f0b23805de2aaa75a899573993023f297edc1c1de2272ba3c047f96eb126595bb85060ff35d4777b76f7109fc0bf5688f2b2943c4e6024598e976d3ad00fd30436fa834756840cf983099c46ab31d5f158021fc7fe11ed26e7c7a14309dc76c42429720e72a827818921f884ec3d4f5e3924709a9234d6f9448c23f0217a98b204ed183931025fc9afbfa2a257885d113875a99c69d783c8be541552684d2162620c818b789b472bc6d110991842e0230f939e545d86ca1123084cc6918cba95796f2f3180c07ab766cc39bbdc27f50baeaaa31c6a86d96947f9820f2fbde03b487ad371a48de1f182fd74e74187dbafe62ed80f8f394d688cdd51a50b3e9cf4716ef7a8be7372c1e98b5eaeb8ffe53c2e78491e5a9e6a8ecbbd051bc43f9aa8d8828bde29e12984b2e041b5602f96a55b2d55d70ea9410bee3e773c2944f5a90f990597d3c64b39fdc3581ec3430d59b09f35a8ea763c39b78e05abe98107591b3ae20e0b7e2a3f429cd47911cc3ad47805d7ae9d394ac518d4c0ff0131a881bfbbe2742b6d6f8d928839f4ec9362eae0a697a1958333685035821aad48a37a88d6600593695983c59c2dda51656839da2aac862af83edfa4fd41c472fe656891118317987b810372e00218644003638c6166b082179ca5825157f70f6d7b4163880a36f859cc8abae9196a9c82f37c39d4ec51e6d85d620a3607193c65d5a895828d31a7b465d0dcc9bf04dc052b28c301a46062dacf514cb5ce0ecc5170e3a3a982dbea87270a3e59d68e12dcb263e7970b3542c15487b97368d4982a4441c1ff7f9a5a8fea137c559764b6e49ee0dff27d9047caa5634c27f898636b6d7b6d0ba182851a9c60b395a5dad6ca21a1c626f81442a7471ac3634b61086a6882dff548d27d9461a0462638c9f99aa38cf1c404976bd2a8b5a5f1127caed6a4faa86550c3127cbc1ee548fdd145d55f89f7438a21a5ff1812831a94e0d3644df0df0c2f5c418d49b02949f630a7cb51ae7d4b163524c178efd97bba3819736424d8cb815e0e2a25724702095672f44996c852a98e47b0bf295b4c15b523d8d2d431f1d1da18f44670d1f662a9790f83336a50d6001e88c00c0a153518c184d46ae9cddcb3d4bb082659c8b5f31c49ac5043117c8cb64134a737e9e0151a6a24828fcac36ec96d3e79ac29d440041f454c925ef27b085ea73447a79343685b13c0aa61082e9d6e8e466f2c04938267c67c1d722031ad41082e5db41c6e111a438d41b0fa614b88942977483504c1fe96869c9ee37695816034ea4e2d3a0e104cf5470e93878c16439c50e30f4c554e4ddb37c150c30fbcf4fb6bc8719a8c7a01f681fb20e45ed75787317b0c51830f95f8deaae4b0df03bf315bde762531c98c1ef8c991722c670eba6a1d0da2461e388f3d474fc910cad298554fa881073e0ed2c6dadc21c79cda1d989e94cfbd46e200ab3cd4b003ef3e29d953c69c1cf2191c89a85107b64afb24480c7d31230338a00051830eeca5aa6ae5d8b3253cd46a5cd925778e2987ee1863f40bbe0c330332d4900393238f42dea4afada5a9a1e4eac0374713ff2dd48003af59d4473fea2ce7d019aca1c61b388fe3ce1a1d85c8ebde0dac07ef30e7e946777129f0851a6de0c5a3a3fce51d9115abc1066ea7b433e62056630dbc2717dfee8cb5fe9135d4c09945ce10995fa11e3dc618e7881a69606332c97d9dbb3b9a748c31c618e328326a065b35d0c0c48f8e25f4da3ee30cac7e88bd7ac9a3d8f42ea8819bf18231c6d025d43003fb297bd49c420ef516af51063efd56f6447944851a6460f53ad845f4764eed7e0d5cd02018a3c618f8201d22a5261fa350430c4cc89759b5a35229240f50230cec6fcceff7bf8a937140a10618d88fbcf3320b314be935bec0d8c78aa839c7a8fffda08617f8a4ba1a2775f80e6a7481ef94bec56350cf10cf375ce09275e451c2939fc40c0e6a6c81ff30c5af8a7b61a9d125420d2d30a9742ff525b73c5fcbd0aa828022c10009c81000106a64810fd6517fbab43a16f71635b0c069c51fb1ca183c8ee3388ebbbbbbbb3b33333333b3aaaaaaaa5aa2892400b0a871053693478a0e3dd4da56e0835d1c77b3748fd553052edd72ac29f888754f053e10b1b7d09f3fc79629b0413bc4ebbe5e0a4cac8e8e5cd54481cb953d85ec4e9b3e2f50604a43f5a3142442db2730957153964ccd524d9dc0e7680ab973879dcc2a4d603ff2cf1ef91292e3304ce0f772b664b0f53cd15c02fb410e34a473749ce6daa08612d80c0b9a4c3d87d6a1930446aa4b7cd47390ff03096ce4641b35b142faf647e043d5e7f4c8367ab611388ddc9da364397e48bc08ece59426c7e179f76b86086c66d7e8b1db328457725efe4f8e2204c63cca8a5bbea1e3201b04f6a3209dfa345896b2061038cdfce25d23f9055b51dd3ca3bd87fc515f3099565deabce3cd1ded053f316dec38eaa41a5779c1459b9c681ae92ef8f841477e92bdd57e5d301a443a83483ebb3d73c1c49892c41c232d5706174c4a5172f4f96b4269780bfee31c6a9ab672253d6cc1e6e8bb651fdb65ef6bc1f5c4f2d3b6dd4fd3d182fbccb4c1528e27d5cc825df730e77f60ef139a2cd8ec398adef45b8e33b1e093e4dc269d6a82b9050baecef275f54561bc820ba9fdb3a7ef7b7a2c06c2700553fb21059b4c2149dae40261b482f51cd56ac4bbcfa1a39001832f830664182bf84939f44db6d8a66fd0679041031c3c0cae3a10c62ab894776e7ef5515eccc25005d3de5a3d7152736a3d155c670d71f70fdedf51ab1b3407d20807c24005b7c1ab2e5de83805f7296934297d0f1a5953f0b1b4f67f4e398a1c16462998be209e831c99240fd3803048c159cc1d75889eb653f3a360f42ca65051c283a89919d42006872858e98a49772c4de5a0854179208c50f0ed1d87f03833846e7f1d60823040c127f71cd328a119e35d86160d4cc7e005661832fc302a0ee313bca649b93ffe4aec48f404173fac94ecfd3d1525124627d84f77a99fa4aa200c4ed4182c30616c825f4b56d9dfeb6718335ef09e72b8c18b45b37b4ca91e75666ee2c62e8e4f32073156d6cefc92b5e1862eeab0a24af2b1b27351e4783c2a3569087181b6b6260d95b6f75b5ce3e1b67aba60793bdcb085ea9d4376dd89d6e767246ed422d3bcc16aaf5f35c36b300334dca0c51be287d319791b281f6eccc2c99ea6d2a493de4990b8210b7cd5e278a7e9e46bc5c2f6c8733cf94232f3c838dc8045313a781419ff328ba6cf38f20367b8f18a7a73ced25157106119ac2e6cc5931f957b3a567c63fa973a6a15da7b7f440a375461db86a416f9f5fb3da920e28e87f60415254bf9a3df5e8ae4f40a374e51ceec0f7f5ae27ecc8e31c6186398256e9802e98d9924dcef738a136e94c27c716fe9d41d4a0cd51d6e90828d19c73764c8669083afc02838c9943c268b17bcd21405fb29337290d483acfe915030398a5da219a347b0cf0cafc10d50303956bb140fef4ff069d3c42a2fb7fc3c3dc1597d106e67a7593c9d603b6d22fba8e4c714c209d6773b0e422bd524f49be0ed5366de0a538b91d504fb615acc21e44c26aa1833c20427d2ef6e1aab83681d976037e4d856166ff30b5a82dfbb8f9434588a94d31ab08001d870a3127c58a45c3907cdb93d8a093728c1a794a2b98ba9c7366d4e827155fb9e8e6107c6180325517ad8a94663928e7d32dc88049fb3dc37a56a0efd6321c1e746eff8c3c80c6dfe2398aa31dd5ca75529621b841b8ee0b635a3f63e5b307569d05cb8d1083683f8bb5a7d18d1bf69f5648be05c47d36d525c116c7e2076ed714248d6248289273d96b33388e0fd42a5c3b00f5c73f42138edb5b212b7d74fad217857b5cbce192d049383dcae41244a882a477977eaf2442f438fdc1804eb418d24cf7f51d59d2048d6b19a8444b5ab58d20d692c43eb2837dc08448d71031035c61ff8dfd841feb758aa1c3ff0952beb731c7b644b53126ef4810fd242cccd8af94e573e30f651ac586ee11e58ddd8711c224ac8517858116ee881f7df94c662c8f6f8571ef88d94e3d6c4ec20528a410dcc3843057860525ab7ec2987973ce4b8718701dcb003f9c3acdc9976d68195501539fe9e141ea4fb841b74e0747cb5acb3e87dacdd98039f95cc722c851c776b3930d59ae38a9d961f72240e7c94f9248d4f76030e4c0a4f29879403ab88a80b4a59010cc85824dc780317a246a849bf471ee4c7106eb881f57d49f5af49b9d1062696464c13f59e254d5a0cb8c106462779fea7c9b8db71d6c07adc143be588d6b4bb1a38b3f5e8eaf431737269831b69602ab895e6c9eecd81050ddc98ad7d2c1dc719b8cbbec8962ebd36aa66e0c4b365e8f69dec77fd0acef0c041831b65e0d28598a92ce7981ffd64e03cc799ad2ee580c18d31703976d8c69cd2a8fb1103935dc162e79413067e246f9e1033c64fd5fd0d30303908b97e53fb05dea5473d457f78610f37b447195a3930e30c1acce05ddd0c0c907581cdfb414bfa40731cf4c3c10ace72818f83103b5f908a999adf021f7828527d1f254d28cbd04207dcd082295ebab694e794ed230b8c07967bd37b182cb0c1929a77a8bbfb1ad32e88c19fa1a5811b57783bce761fb46b5cadc9d814dcb0029b266e0cf59f61c60a3270a30a5cbefd70f3b77f90a2a5029b21756a9fcc17ec2c221820011966dc9802ab292f34e25e49ca4fbf0bb60737a4c0ebd947678a68195a15b811053ec68ea635872155c7571937a0c044ba946ddca32367c913181bcd6127959863bb5051e08613b80b394e9b45cfecc16e0253fe1f19e57719f25486d60c5650862127b8c104b653547d373c9f8f65094cf80735294755570f2a434b09dce7b846f7d2eb793609ac9e75cad1615aade00612f82ad1606f951f810b7996ffb992b6236204f643f3a45c3fd260052f78811926cb8d2230aa919a9dc364172b15811b44e026a7fef0d18d509b6308ec7d102af3841821307a1221e64912b21b41e03afb658f2d24867b08831b988113b801043efced4a69ba831c45f70bd62a4a2be565f0cecb179caefda6b0f37a61487972a0316d9e17dcc51c7bda2553e91cdbc51d7b5e8817fa751bbae0b33cfeccf0d0e378aa33cc20e3b0910b3ef3d795c7fda8c9df0bcc38e31c2ed8d1fcb18fe52886506917c4800c09b8190eb0710bdea23fce93a1463d646568d5016cd8825dcb51ec3fcb51a6b4d4c26cd0c26ccc82ffb8d2c4dce194a587872cf854152f77a56dd6dc1d32f807980741d9d74006ef6498b7c1c682cbef8f4eb73cb060530cd19384b41942da365ec147684badd21d071a541baea8311260a3157ce598bb777b2bdfa6b0820939b46d7a8bf9e2a4ac8289fae22143323c2c6d872a38b37c316fce59b7a2853652c175ce1ade416f2457720ab0810a562f072a2189e7d1ec29432b07858a9cf13458c161e3148c4bb4ea9bb496a1a6481ba5384871902c1e7d2cd18e60195ab9021ba3d8638aad915fc4ea19c4600687b1210a36a43443f0d0f1b3bf8ab0110a3663544e31cddb600314dc47371d2b48fa94834954363ec165a998412f5de694e3cb202a4fb09639115183c7a06327788b35b91dbb7ed2f6e004ab9ab94c37ef4966ba09fe2f7656cd8eeba7febb1930a0b200a955810d4d70b7c942c75188508f533632c1e7e8b97a1ee2a2e9c104eb9fa727526f5d4cfd12ace5b01834e58c2558dbe89a737ba7c72f2bc17f14de217a7a94e0d4532f1b93e02be3471f6fe5f85fb32109b64f72ed4d6f871d3791e0934bd48e5d87f67d9060cbaff2e75c39f40f738fe024ad9be57825ef7354575ddd046c38826fcb955ae9be11bcc594c63e88d1f265c908beef4cbaffffe3386f3616c1b8d4880689a12218f7ca3ff9ba1e668f9308ced37f2d3bb6caca1122820ff2c5ff360f2297d85eb071083ef75a75b21cc6af960cc14678641582cd1d67ab6c21435dd408c1c6a49edef923d7241d04bfe57e96114c7d43c7046c088297e09ec5228f54b7051b81e0e399a6310f9dfe342964850d40701352baec515cf1cea9fb848d3ff0be1d897d65e6947f990d3f701ee4f66c53ffd598d71fd8e803fbb1c6de9d1c57af2b6528190e6cf081cf48cb9e38c9b423e30c33ce1ed8fb38aef41c45cbd02abba30636f4c07d6ba8fcd549cbe390330c90800c12d8c8039bfb036bc949d71c6ce081cd9ed37a621cf594931c6cdc81fbf178db7335e4183b76e0238e7ff6689a759bd6814dd11d3c536d2cdfde60830e6c576e4cc94b2b36e6c0e7f8b1a714592abd9a11d89003ef71d462889dcca3c56dc481f1e8be52f628f9593b0907ce4a2377e0915b8a39d40ad87803abed1f73b68d3951b20bb0e106c6f3caa2d62a5e78dc461b58cba943ac4df7d07e7a850d36309d453dc7bdc91ad8ab4f21397e6e430d67230d4cbd5f90c89a6dffe331f02a68189053d840031fbe6bc58f5e3fa6ae6d9c81ed4e11cf315f92d09ad9304319b88ed25b8a1f6a3a17572b61830c4c9e942784a4e4b7a68f81b5ec9aa27a14547a5731301da6ddc93adf8f62d046181895d61825b7254d60030cec6dc81cd946c721f71db0f105364323d57fa867397358b0e1053e2552c5ac1ca4e4215b645436c24617b8fc418e92a23f48da6133308003fe058d010378c00206b822a30661830b8c667bd039e5d44f1d320bd8d80213afcf3de84b41b2c5e4c0052e680f64176c688195e02a127352faf4f50461230bdc84c73936314fd37a06890546a2aed4c7b1a47a71f30a6c0c29e952949856e0e368e211db73bef9252561a30abc64444bfd16950d2ab01b2ca668c7e153e03a54071d1df95385500a5cfe7ffba0ec62c8fb4781d78d1339d01b0a5cce6059a2ae471ef64fe0434a39fecf1c71021f574e565db69c3f6d02d3296610a9f7b78e3713589b6ce695337a75331cb0b104cef3f7abf84797f797bd820d25f0f1c5ca1e5b2784b48656b09184b3810426daa3078f3e0881828d237099f7e26bcee96ab5bd32d8300297d42f6ba5b52b43bc085cfe581d8a74920c3688c0487ece9543ffcb443304ee52feedac087d39bb42e0738ce8e9eba3fe350a838d20f093a137879639a3ef12d80002e755e11d6d5b84e78b18bf60347f78b41ba94af3440c5f70dd1ef8498e693cfabb0cad858118bd60e3486ebecf8fa246f58c8f8119ea023178c166f8d5a729570f520e8741fb408c5db02993c4892998c7dddbfa20862e58f38c3a71824dea58920b3e8bbb69be86ea8d1a3170c175f00eeb3f486ec18975464828ff778f2db8f48d3e0f3a993bcad68249ab1f7b72ca19a4775a1435babb45640962cc82f3fcec1c5db39de6a02c2ed78992d45187c4826d2dcfdcb9217f3d7e068a018b927466ed1ec95fc175876a4892aa324275059382f6e486a8a9b342a606315ac179ec6bc1bce3d00c62b082d59432a5eff8eb3bf6090c62ac82d73a7fc939ba6839b4570c55f0297d048d1fa824af85f2582c0e0644c26030140684958e0f93140800003c248ec422c1288e436d7e14800350241c4a3628181c2014181c1287c5a15030100606c340503010088381a1709018800783b0372a7e5b7e368392c0aaa8e3660d8e539adbbb9f10a02802acdefa6f8578299b62eb01781bd474998152d4df3f450a4ffb4ff6be034b3b4d37ab979915c3ad2c3145443446d0ccdcd49523bf5810a23ee867872aa4172aa1d79110f977345a18eced9937cfe33bac996b7e0d89fe053cbde0f83470d5e2784478337415daa126a706a138e5b2e393ae3d23549aaa21b352b57e61a74b2b125265ce208559188bc6535ec1f71db11340133dadd39949c2578cec84470de49ba58e2ed0e2e10821128717418243bc55d07f00074097ded3d1cad20b56ad6525a130db7444193f86d78c8d4ec90044eb70ad405be3722b492d230740de7b1a8cf07dc575dad355f323a9a1ccad6f104b80c544211653fee537b8be507483a59d3393ae4fc876f3502fcc6164f6ef5a553454d73c46699bc354f50e6edab0b846887b1d78c51f9e51b4d1b575732d0d64430f90ca7032c672a05d0d96910f4da2e0ef8515ad1f9ad0c43964128771639ae1eedf701311a9b8968f9298f56ed6b8a7f1f1ff0f3ba28bcc9e640da1037d981f155c121bfb9366b52b6a2ec2e5f44816b8b38f1413079f2e8b0d7c582e2f67fa3967d71f074af8a1e24450f81e30371f567209a325c572fba46bddd50d433ff9f4b900a926775c2f0d4944ec255eb02c9ad58dfb6641cb020ddb3a6ddbf2cfc8f39655433f7da788530fa5cdbce8b5423878ded950872d03504c9b4f98340f411c9b856f707a09a1bf0ed076701d72e69273c1d8e0506fe8e0c08aa90b65d699e5e5bc6734424c5fba3f91ebd011586cedb7f093cd80982e8b2192068d69c2e1aa013775923a9cf4f08a5d2846a0989fe313e22cb1c2c11c4fd44702df72baef45c3854f48141f43eaec980ac950d68e121583ad189e0fb418d98c054acbfc3032f7250e69e46cabc221db11ccce78ff734234758cc15f68bcb3e612c3a079d3a80855737bd4021daa2a6c21a16d930c06c2dc1847f8df40fb0497bd1c4976d6a343d13aaa160d2ba91cc4d8c1d6060c3d6055cfe3580217d825dcb43164524f5c2fe43816aead19d7058b4112607eeba3377c4b176232c77983742a8d1a2dfc321a8988433c735ad251786fba3c3f25ef53eaad403ee63d677b6ad6e1178e195c5678952d83cbc9624db8ee8835ac2affdd55e79cd5ac45a606468658c4953dc552a34b19f189811efb50463c12378ac189f56867e28690d049f8716d57000cdeea9301cea4c1a798df309f8029d1a3a424564fd719e629876c36fbfd82813296f6e5bf42a696af3c91968b8f826971a0c11d78e329168ceced42863e5a7154c6539e0c51001edb1da1021e4a108d2adea6239cba3eeb4db3f00b1af8ee3c15550d1a3f6787bce5c08a98828842a4e82104adb3dca6f90833263741fb83ceb181bd0664161c17dcd337e25a080f9d65f1c88c0ceeec873f2e72e1ca0fe4eb48011917e01181f5edff8a905b2674a81da48319c7adfdb8325ffcf3041ac6c7f4bcb08285f08e09e3433032ae2f6c5e4bc1a9bfcbd4480d781a1cd19acb538b5ba1f917f141d177464b51248f4ecd6b597916f845804de3bcd4b072068d40eed956485326cd71a5e7ca9afe8bae819d7519be9f75120c1a4425104f0bd505e03a344f3bd885c3a2a2511aaba45a034cbee73c48c7daa06654213f2fbc0abb9cafb546fa22a8cc07acdd651413a30d5086489a9b44795266aa781fef4c0b6bddb64c8bccdd74c4e297b22e3b1b2ecb0971e83b05551e330a464f004ad30e9613006139dcd8d146fbe42f9ac9ab38b29df8074a0be226dd656b825af0ed78bf56b6f2383c459da562a8f322b5a50c32dc37ed0454e9cad014b2a769adda1cfd8049751e37150c73a3213882b0563c21150f72ef74089e4f097921ae6ce35e6ebe40cc27fee5682960c713d5ec5cfc10161ce88acbbab179e7c6c1326250d4bbe733f605d0b808f70573bdf4c1259e58a041192e32345b8232cbab1ac2d0d28a6a6e983b8f981a7c82b326ef748836c169da6e2a62932c979f49c3d244f8c1c691f7e596e14a6fcecc252576445d10203a734377f894ffce91d97b4972ed908f91b5aa47f516f2e772ecaf2e1ca1b933cb502f148a6c93d39150de86a9b27b49a10ebcc1137868dbf8a54ced7529654623d648a119ecb8a92a0cca046629adba254d96d2852f45ce4404db1b4dd2d11a0d44f9d8c7ac8fb42682130fd2353d7831b8cba36821a054830505f2447293d0f711c670f8fe22304248c1fc78c2c5fb7049143039b680390e83280b529f4afb912e8253483d05065c741935fcb41da54bd97fa83450220fda011b8bdae0836f05af750af66d11f270ad522d2b5407a5841df893364c70d20ad4f78a6aa73a7a722a2af02502837b41695918ee8e083b9cbfa5c6763bd048303c2eccee294ba2f9b4e5d323e91a0a7b3e8d6457538f9e1a18a6f8830c7c6d3a718272e1bb6987f3a005cd027008d53c8d98effbfcaf1bbfa76d8a3761803e34174cb56807d91c2539a012ad4649902b63dab4b46d68f4deedcc0642c1ceb9dc3af7918cb78c03527ba4972506904d514baecdcdef5aa8dbc4156dead9ce8f1f20cc3bc94c4c838b6e94d63484c3dd8c8f465423f930561d8d4023df23aa7199859c7b1d38e8b494cb2612204d7aae726ed9d924da802d0d36574808604fd62befdb4db2469d5853b57e2b4311d200126afa1a6d9b740fd950346edad9c908c20cfa3dc8047f50ea9528c501d6445e781a000de3da14b9001c7e1437ba962bfae64078281d24429175374974b984682d981d2b6a166cdcc52544f616e6c101082eab102b1261daa146413a6574a5c92c665b65ce75f66d3ec301f88ac6167c68e60879046213bf39012484d722557540f7a7bb194abb035263545da353ca65f9ef6226fe0d58c67b7a1d08acbd6057b515fce7b7caaf7e5eb91bf69788332c40489d95c7ee01ce579a0c5ed4501b66bf350833e556b81b7cfb4416df9fddb0e6d5ee045e261532caeab3e313f2b4042548f48afa6955d5c40b517ae5c8a55c694bc4ef249390a3706ac26dd66cdff5eccb85c0e3687b6cee9e6c32dedea53e5e8d3bd29f59d41279a8ad50ff01637bac091d3e8e83372a855fdeb3d8d52d3aff60d03aa1bf8651e18f03eb5aee17d57c019b94d75697a776459c1b610d08f0181b4f97b7a5e85f4e006c81f67c2b6bcdc1f5bb9591bfd641dc54036cbc68e6e633d03522cad0e3b4f56bf785767c83c73db2c3085cc694daa52a7a3e25cc3c1e03ffa4daf0c05a45f8fd668835d2ea6cfe7b286f17c1516310a96a792c7f70d947030a4770a490df3fc8d1f7bb717eb35d2a882f75aab61805843eb51312a24198f9b555ce80bf6b5a8dc160c1e45394c513e2226f147dba6db2ce958dc4d193a8be63e3e635a6a6220e9d8e4ef10b4ff0eb6fc6cf38a517556d38a37b8c6569ce3c7a5baaf78bc8c0b0e8b20ccbb3f4067f46b6a2e285924e5edfa3b6eb2a3abfdfde3419966dd76dd1ea1304db6dfcb1f54b4b10b03ee05b55cff61e6d86ac93e7ad66380f3e871aca1f7686f263241e845a30b84b985dafd99a1c87f644af856c8cb8dafac034a02f90135fc966d03fe52d630430c6de3e9971ba6d3679c39d1261dfae24a568740b26713b94a1931128779cf7a3e88b946716004891e0d93366304a20a1de4b17f79743ea802352eda8e1e995dbff230502df6680f9c076c04bb075c2dd4bc0d12d482d84f5b8c5659f03ac41cb5cfa9bcb1561549b46fca9616270e48c926dc944c3f9252250053ee757656af1f02ee10cb48216567cb23277571d97cfd316fc62e44347d1559f5a7aee8ac287d70d61f3e30946a7a68eaba25f3f26a2d68d66130364ddacd42b095ae6922da01b7546058b1a5f43d66b443d6e0c0c157778536d693c97c1a6da50cbb8b947dc39ea904f8512ba707dc68d55e4872bbeef137511fba1e8147d2d29e2b6a836f12da042c52af508532950fcd393d5eaf5da1c7925a441a0908fc3723583881308aa39b6e99513d05c0a961ac6da8a27151ec7220ab47cfcc356c5d49160c902a3bb6b523bcf1513139a87afd30ce027b742ea338e76c8dc13f5569a7559f3383b2809b4ed0c2e185bc8fb15b1a24b47af13ed41f62c89c1d9234e904718c07d0bcd5c59b962a12ba7441adc4e60240b9f36dc3c04c1920562c1d1008be5cd1fa34ce7fd5243838599bc3a034c9d02838b1b223408f2073a124a477e6e4333ed3df649f022696822531c8f67ea66026d5882c2206b3319a3bf5933349137df7204700d96dc669b2dd43029d09c1b32652513a30518145091a28255d1bb5f50c7911c856df9f4500d917cdde5b84a0ac4c90ea3c13609d8ea783bf9548af96bf10c28fc71533a9f74d62303d99f4ca8336c1dd8fccdef52bc6b239c378fd8f0193b4ac485af57455827b5127fa5b67675d7e505d643ddc5b00a8aa1b9ed28ee480a6bb9eae56d743b4ce174a4db7142ac9794965f4789d489325a03490d135cbb76c6855c4be8ac4b6ea59f729f6c1b32260882e25736d4b02f872e0a5c0084387bbd3b499b7e53b95af81d018e6aaf50265d3f5cf68979a12fa0b597172b180c0e2b99c54d11c1de59b0f3f95b1117f7be7b460d5240023e135bace39646f795db5e7a3f18320b1e0848a91273816ad40760851ead9fcaef6701cf41437bb9e9142a1cc5561368cda7282db0757d3015b09ce8375be759b316fa962c5039c566fad402d638e718fe87460812c01ef08c86416a41009bb7d1b12c5a49a2dc0adf7013130ed5896d3ffa209ddafcef146a632b87f57d7781a55c1fc67d37ab82d9af8e5df1305decd8886b19e044e8dcc55649e9e127c4207adb585b2e8ddf50d0a6ac9080a2a855ac7e36c0867473d17a415f92685c2c24659873a299f429562ca598e9ed4bc3ef6fea4eaf59d7bdccc594bea849d521f22579213a2f09f31b0d700da92b86b25298a763eb181dc1d98f12965f194068968a9530ae483a1c792f882cc9a3f5e6a3314061e83b8ea75d78c44f05d6cb97506b5cce8abe9fb7fff7ceda9a9eff831300582e9c81d9d5f6a248e76b885a8153a1612036d02a0dc6d80ff5ab5cad39e13cec8d5d7360c02e4ae55ef227ab9603d6e610af7420ae59109f184ce4a22828fc5546005a59e91f855c6005626d3e4d8543c02089a448b508e7d256ff4ad1b25a20700c04e8c4c9b30a497be776b79501dfcafe73cb2ab8d8e8de81a249f8e62c4c9e082f2e4b4597920a4bedcfed34e2317561b3f94439b96309c9a78a7493b828ebe277868ebde283c12fa44c2c72e9bfce1ce50b5d409b016618364dd49bbf2d3ac6e46dc9b7814e214ac789d16d33626066f084f2d5fbc042a1c33019ab5e438204b621dbb18bb2e0c5a74e3903ebbf1a0e7c42c0f02b564e4a05af16d631a9f54b344e24bdbc60282c925a98d190037206112cc460b07f35f9d02cd2e7e49c7e839394378213d4b47831253924259ebb3b92ba42a5cfe0b2518d54abf4d5145aef4995f3789ed8fb9a82efbcb988536a194b20a0414969afb23eb4ab29d10287a3061b156d3d770602a96da0ed357368c2c0f590acf834e8dc3673326f0f98c3a73046d358afc920efc865fcf6815fcfb6d8f0dd9140e995bdd8bffac904cc80b0d3211079c80a3dcf49facb54975a0958954f14d7b99f60dff75763b1036c8e6809c34c370e250b38da3763f8c88b4e53ece7a3b66bda64cc1694f4368c2f9b1f82ce5d9f0805bb0abbb6d6850e00e80b5c70924cb6c657fbc144f7ce9e805200638a255437f41f8ec660d084d93acaedd208ce845710895e89bc7ec6abd36885071c6429dabd7ca6332ebf18e02e1b5159f439a0d2347d09cbe831a454496fb3460b95cfe4cf02ebf26ac0df2944eb714aef3170a7661d71cf8c5edb07bf16fe50dceff618fef0689247831db6d4e1b3a61c62cb1e00c7570dd1652107252d40b219374f54590831d932dac205ab63907a67e3b9112a889272c6b435904b29fbceff59d1de1313a7920c4ef0fa3d10220b9f4ef03d612d045f8921426769db62221beb83af4eb9a17553fef0351c69af034e9c43ad57f545cfbebddbcdfcef552619fe5ea39ac377b6b7a7ace400938ddf38d24aa09ef07b7f0b5f1eede90032b548abfa7455384daa71f7ccf8fd5acac14fcf5ccbf3dd6b205d402d238a24a1e0f8a4c052bfe34d0516474057a7c0f4acf2073929e3408f2539dfb43b4f25f985f9527504d00870060b3dcf47555cb14e6c9737ed6608f7e0fc390de8de5f95ded7566d93cf29f2a82ddd82525763c4b06a8edf1a9aa850bcadcf4ef0931fc66c897498e9544b7eb0a4d0084b412200aed3b38b35936f15d2e09ecc240397a2c4f15582d7fb19905cf364827de568f219788f6c4112ad5380fb75a3475640f2f84256280c38c940788c99c2a64a30e499bd65afe2eddb87f3de420540b0588cb4f9ea2878a00e32b6249d5106a3cec2728e74a970c7fd35d26b334cbc80c90ae3e88ae173789ede170c2f4dd2b6e65c42b38422ba4780170bfe2240fce119789982fa8015661f904e00b4a6444ecd04ee3bd0f4d458dfcfeeea1ac2ff5b0254ec9ccb709249d15c6121da7fda48288327b274bcecb834c8ec8b4c79e60da1f8eeef813b742448b9d4dd338a3273be98bdbf0554e12113c1030b79c7c9373c50dfd8909ea464207bde15b896493d183b08a3c32480e3f4171f3c401a59097ef5fe1ce86b48ee59518db1e02c531c24049a3cfbf7277e9f0a370ecaf536fb5db7375d4fe3a14e07f9a1e600e9d6b68933ade898d9274ee3556a68930aa12200ad53513f28aef70918d957a5f616039ad6510b3629908fdea438b39549e528ac492c86517530756f204dca6908e8c48670cae77174096d39e807f4bb37a9b525d914bf3a27d89424ab4813481c43cb9319baf57a3f82e43c348da5eda8be7b0b79bb704243aa53001a7ae0f9bf0581be2a0d76de708f74c505f1072fbe1297ea38b621de7682e25b468970067c606c43d39428a363bd4b2d517734aa99059674c15fae44626b54e59ea5ead7aaefe6615c3f890a41f5af08a0023b371bfd2b78bfb8effcf9ad01a89ae599098c818188f8e659661f4f679a99780924be5f1e09df000fd43dd196d7543c51f3a4753dcb5e6010c063b327defd312b1a86691c72274ff48b5b45de49aea08867c4b2e1a0e4260803725cb869732105a5c33a41c04ae0a9d49c5cf08a0e9f3eb99d0d565e8373de16492e2dc5c9bda9f7a7a4f2bb5068016c7da8b98a7f55df32f3acfcd22732b467683a85bc71a8dfd50b6c97bedf9812c511578d4af0973b5b205618d00496865961213bf375abcaca94256b84c94057d99b7d2f7416cf0073d1a25e9dfc87da8fcd6bace4353714626371a93ef521a383b542b65cb0510886ff5240552bbc082c2d39c8cf5aaaf07a0870b1f9a2de1f9b808e827b76a5aed4751c16dde25976cad1d7e21efe1f0d92fd33e624a0e86789adeafe5e012e23e5224d18bad1f05b17304defdb12e14ebf950d9a6e8a9fff309afd9e669f1683830a420128e0e56ffad5bfd63de8d70b1587119644acb49f92ff5ee166d0ddefdf5073a389cec7d27906affd6700d0d3c49111789e204566607a1019e900e5b924490704af91542e00bc413c2981879716106745ca4a4055ea654ac8502ca1bdccc0d8cbc8b35ec6c8a98c844bfde6719189652c3b26d3f3cab0314a2a1379522d3463b493922dd872e153389cae7b8248fd342ff530c857097c0500c476e45444bb096f197a81756d96a289c396fe609cf07e804478271c0143bec10c3d8416ca7a0924535d048d430d3ee4eabd16db2ae811dc10fe95c362a475cf4139b089f83a44265c08500f0510d60f45117c06b688be1af220bc955e2900faa4f680f1138a5632197a198fde2a0604ee701679b752b968332657299004f43f9aaaa4f13158f16d0e6a6ce9d6d9ff2b2c0b638c4f2e7d40edddc1e2c43d92e6ed3635150aa94639c592f889651554477ecd5d27835d504362f91fe3c30cc438ce675b42250a730cb4b01d96cb7614482b56cfbf2a49782568199588917a93d2124eab9af96be01a3ee79e099df0fc5cd12980fa7233a8895a617fd36dd8566ebfe9c0bf5da6897aa855fbb3c2e9352b2dcbba985244608653baef57d763c6bb9bddccaac17652caacc8a783eef8d953dfa0b6cf8232840f994bb4a8dd495d7a236031f484856de63b0478c459bc4c1a24975f61993178ef5608d6f8a88fa381164a77df004bad145ac3b5035d66006d58fe10fc0c5168297c82569e361737bab900295b971dbf257ffba63e6bad79d14fd3ec5997cde17aca4e54a4533bef2ca613fd424b735f0f3ad7ec6a01858f1ea6583552391b2809c670f7d5a7785d64cd92729d326126f1acc30065366e3273f86e7d6bd454b84cb09f8143647f0a42c5a29edf38d7c115ec7b0936e55633d651c92178e96e575b494069319589573274de136764c348d1968f3b91a4876ada08a759de9554f829050ab5fb392fc7e61841b67bd1c115f6b6a2e9427ee31043c8495b45800953f1a06b10ffc5a071eb2261c8e2600e019cf0ebef4d8a001d087985ba2fae844f72ab5d123504288d6e5ff4af2bae460a39c32c676d69c080bddb442a2676f946d42e1b43060c6dcd165d079b5279edee8e0d36821fa4a749443913db2626b7c0dd6feea125a32d3f63e0586748730360f41d00cbe2705740b9a597baeb768410490040b9391a0a38c1d2c0f29f78a8d8a279f9aa2983029062988c6e28ee1c69556a54057d0c40821724e232f471eb68cb0038c7287b993a067790bafe3c2087827a7210dac1d40089623869633757689b1c05b214958dbb236339168af33eff0b7b4c0c39c13ce86a3d37cbb87f5578ace44463e71fa3b918a4d71b6bcc3936b922b168050186633363dd017668c3317f2cf7aa2a94b0641e1665ebd05a50f92a89dcb880d8b641991604ecb17309d37e28d10818a139dbd0adbe46d4ad94a2f446888d8148c62887990b6ca73036caf6a502e5dc35fa3dcec7fea762b28e2fb562d1c2ec069c9b0c263bf086428743342cf56d05029da19fac862564ee0807020f84f07142199c5a550e53049d3cbae44834de7a37380e5235a9c7f2f4cf4575c80613b2c3515f44aefeea2687bba65c05d1e1d07ebad8b1cf279818b190be371bbd6dac364acc6834466e8c726704af915ddd683312adb38bbf916246a0317a63d4dc693487f4768e9247558cb4830945711c99ae9ef90601405f716c7d68a4a2a980d3bfbb87b47b47849f7892f437c600d302c40ae3048e24ca58a8e19f479aeebac1177674ec51a41fbbd574d95f6dd85563699b9470571cc04108ab4aab19f0b940c8d89f4e95d40e31331cb0803b4334dff8aa32c6c79171d7bcc5e530e9fdb585ff77d581bf19fb0ad2e2e96c97c104c09128c8827970949277a3e9dbccd20714e482ef4ee8940cb70496614b1898294ca6cf780665272b526b01070758aba9512d43ec6fb10e23f3eff261690a8fd78db9bda6db6fc1ef445bcadaef1d85e0c0e4e1b5b2bd69386783dfdc9a4e60470f52e7038cf7fcd423679e543be7884b2e6914582591d1d70ce02378a3ab7e84c42af6f37614a20161cd93fc4122c68a886d2577c8aae786a2c2087175a63d712495d6f60293228398f42251222125122084a54d0202bfff8795f2b9192e39395baf9f6a4296b783a4b79032bc69ba21f723d99a0fcaf50492edd6ef60a61bdf24f16e9638b26ae37c5cde38f01a68249e8c1055382e9734b37123f18db1ba263f320af2348643c9a101ca48bf2325c55c7e83182a9d430a78729146db591242f807bfcbb993fbc05c0bbd743423161045fec6e333e0e10e63e93fdbb408865c6a02e695bdd06a17082da395611065b5b09a4a0bfdeeca501f7ef5a0aa91b83889cad104aea3c578d9d9ceebf38530949c5ef7bad02b5f1773552f6843e4acbdb5a01e782957c9a7267938799a8e51f06d993af6cad5f19deb748144713b6a99c4571642ac9a0e0a3f6e5baf2041ad9f86d54fbc21fa9c3e1d895c73c52604b55165f9cc2c66aaa08e8ccdfc4b7541ce6710e06aa87b7abd72ca6ac0bcdf39900cecef687bff19e2d6016e78d9b7abb12718de85a2e6342a8ac788d994d3f22c30844188ac850e95c41f1d74ae96b70439616150c79446fe68034e87bfa3a9939ba92ab822e80b0d08130418214a5c62b69485468b05d6ac71b9294853af9271c1236f9f013348cdb415fc4e44821cb872a7a0ebca6aff479589906fe3d997d7a1088501e190f337043b253509b017ab9014649899b33079303e0337f168166ce13ecb0f47ad0d7380fb13b63187b601aa9870a4326531906f504e2f5b93b7dbb819769988a6eb34913e76fc65dafaaa3082a58b5ee4c0cfc4d69d658a7ae20054bbd09323e1dfc3d6636ae0e92fc252e1bdcca9dce587861297e0234fd605a54e2feaf6e48e031f3a34bb84bf869a84c77da85a445c6262942cd5a76287d339a6b4969615a0e03d3f82fc0b05e5b26e24fcfe1e0668e9a69796d8dcf93418cd5375c5e96a8ab60e4e4fd8630cd3f552e302fabe7c8e5da98f9cbc335afa5ea666218b40ccb15b02a34df07226de58b214fb048256545987cc94c75e55b66329b8615130f933b50bcd91731c3871730935e4fc2d66bdf8018d2b07932b89a2ed0b6156d7a2e3e471eb36843ed08b8ff4eee3e8f5c7e7105a3f487580d84b1fb277fe582315a4259aa11fb55783ac51811aca99a110ebbd1f37d5db03139e1120af568e7e82174d19c9922fbb779bd676baeeaeb1d3dce211df39bb7acca4b2092115e0d37c567ec50bc108823eaaf53cc44143ed99df5e4c9820174f32373cb5382841519c4c30f141405de72ce88ad31a34e8b02acba0e5ec090501b1fa6f28e301a6aaff2a8392ab219dec6d301198ae0d4d76a7aa340bfb103fc4ff1b6d059ce88b3dff32a269c6a2598d8e2debf1bc3dfe59b373465d7fbe987129c81ca270b1aba90aa3cfa7b6e421ffc53a18e85a19ec51b414dbab02da4b853862522626bed30c7013bb2830aa5b6bf8eb4ac5442040026089f34854f6c676475452fa0f5d213f5112625406a489407dcc1b93f35f0f1ee15bf9b6c60843d406e02577f7a2d071ed421258a9d9f12ede94d8eec9f05e010ce2cebda9ef5a09792a14f4b298fe52a8217bf8bcac6b176cfdf17ef4d86504409763f913b31518b341887207b059807499780a81b972b09ba1ed42626f4f31307b285651a50b02800e043d4649526f5bb6ca59710f8e0da88f96af4421d057d27fa37ff171dc52b3d16cb14b8c352a7d2f82d8fca00c491c22322e08cb68a34938f4dc9cf3488ca13da33a417846ad94d77493132d6d0869a42dda6c0b9f9cc4752d1912e24baba8c5c115cad1280a98fb124723a22748e9125cd7083f1a3b1a287a179586d64091869a39f524c31b441e5506dd86512b5b85262fe7378a909dde2a4e803284d2095a918cd79c409fee269531aea5200239b61b54c62a3b867346d22a6326d48bd2fe3b9a69bc262ab8406640e5e8ec11c6fa8a75c9724b6d2cfe5c29d0dbdcada68ca79508468493c4ce590ae45504de4c9da62b9c8c42757a89d18b188a77d450bf292e666fd4ad8f2eb011075838894cedbb4160e06a4bb9174acfb6d1e713973d287ddef3650ac1ccb400d58075f703bc2e5d7f75a2dfa444b12e97088b6cd493af06c070987850bde59178c547ca2c11885079a46cadbaf43e34d80841e6f93cccdbfe61f1590266d3498e9d1f448e95e5cacfb13fda993aa4137b078e74e18ee4ec792b8f6963bc7cee78e88fec54ddd0c95e82033a73f773c2d7f190a5b50acb48202f22ce715774740790ef23e21822297a24c35d45c59a6e11cfadd664341051dcf57b589ea478f6bd484d17cfedf31820789b89156eb3abb3f79aca08158cf9cb89ca545cb26c54f135334ad796593a54d9d3d6822796ca823cdcc159604856813aa18eda39b9c8c61d4642e208081fd3242aaa0ee53dc76f8ce66b0ac67b702770b43a81f056110e95b8774420460670982336188a85ad1139668d0c6aefdfa9c5507f5556acab35bdceec4f3dd447a0945b1e658262a5233aae3c3355093ab2d6c134ac3d934ca61c8559e73e434c394ed3833e52face85ffa36fbdb1f2dcf733b83f57f07c075ced23d002e2f65ff20b1c64be088b525672beb4da76b03fbe21ab8eead0cfea589d8cdd214d5857778a5f26ce711ddbd15c67d3a44a421116552819179666e6fd32d8b9fb39c19a1309042a772936fc319974333ad2e91c92c4ae35468a71298d5b524219494c4cc79fc21006ddb96011d66f13f7faaac23e7c980db2b431a9f1a27b119c23ba343706c9c8ca48d864048bde25ec99821d3f6bd9c914ef51aad4211b47e5d71675487946568aae229e336d3bc5822627b26466d86d0ee2927db7eb82eebc5de40a1a1be1b49544c56f4a3c1f11088cc440ccd4599bacca5b0edf810edf35f2ccd6c124048c45aee43a918726c3b2e55808dd6846ec9617b1c81faa9d2c01f7417195c7d93d75096b43958ced01c0ef3ede5d3baed3751586206c544dce0bb13612e5ffd7799db4374182467a8ef3291df8151daa137987e77f2d9b207e2487ae7e6bcee0ad5da8131dda0b701e8dde0e6b9080fcca9ce1a15da953bac08ede492cc83537acd298953a8ff2e45b1eb25546227ff4aa250caeabc8539c209323376ceb12e8ccad3b498bfb6599a80ca78b001e148ddb55713b84bc132680747e842bf36359d577723a761174c0ba9f6a48988aed63dea85deb266671babf31a7d1c63017b20ab1f1a733aab10b1ecb3f41fcd1b5c1e909dfbb433a739772c047f05ad2b046188a3d8805899b29137d8fcf0731c2551815bf29bdaa158d6d15b050c15cbae07684fa82110c9952f97f387f66d0f4589663a8647628666419a9b14932d1f8ac5189ff1011bdd1ff414f630534a1028e6104420b3a50f0a4d001f3ffffffffffff0cf363c1c7cbb1db6ee2fb55882899922c95759595620428a594a44c29a96d20d6460821b0d71df94e0f033150026c0b320b7f0bc9e1e35488b7ae384a5c71aa2ed78ff225ad68748c7f7926332bdf6445fbea95c40e4afb89fd2a7a4b26f2c47cf22f5413022f3c4083024ef050455b92921f73cd732a69928a434539451793ec9ec49524fb25b9313c4cd19fe6e51d39ba94dc68297a939d3948133a677890a2132d7b9097d43498368ac63f4f4fcc96f4f9e739f010459f7f26cb62f50845a3a59b623a5e09efb31634780d30283a31514c09ebd54f16fd4497ddaee1f43fa6b8a58727fafe9c7c2de692190d2d3680048f4e74c2a36aa5acfd557ae544973f9b3ce25e4a9229e3b1893e8cce1fc34aead3d369a20b171ad2c4b24c51cb44d7964c4c765a26b9429868c6672b85f9be26b944e7b9165f4dd8cf8d134b741d1e735af839c1532ad14972f7c6c5a8bfa95b4af423c753923da732f593e8b44d8cccf2a91b36e92189b6e36514b7202b948a7b4422935429593a9a7f370889de826cb6244a7c66703d1ef1c767505eb94de3884e4a9364d1990da30b1b65d7a3119d1c4a98923327d961a211351b384e190e09e0c083117d4e52ecf4e0a5f74b4b038f45341bc3bfe9939358b19228a21393ae98989c92887675e5e49127694c551951ebe215118dccbc26564de5108d6acb92e4249774ebc8c3107d07352909cd511db25388634ce2a42852820721ba92a48a499a9efca8271e83687c4c8cce2f49383c048169ddd560aa9967e213a8c07a04a2598d667246cc46531120daa0b35c09cd258a7e923fb46bdab21fdacf5135a5f0a224f19b5d7af4a14d428bce312d175394f9d0ce960ea67e262a364e0e2ede3df6d067530b3225a16e1ec41e7a68332c6b5ef37c181e79e8e4080fcf1e4b449424236a36bcd8a2059fe4b871030c1174711e8c1c383a80021b30f0c0430c3cee80353cecd0574acd1d27fa040b7d1dfaea68a14ad2984fd679d0a1cd521e46996a791264ee8bd3051a1278cca12f51367f29512b579ee5d065fe595c0fa6ab44d7230e5dc9e6af96a1e46cd203873628495241e7da4399e6f186367edecea0621025f575436b62d8981178b4a14bcdeecd2d931294c0830dfd575f8e31b9383cd6a01e6a3069c8b7e2fbc9fdd1f9420434780da8954878a0e1cf2b9fe4d8a152ef65789cc13cccd06b92717ee5c3861c9947193a792d79c9ebb90719ba6aebfe1379160c788ca10bddf137c5f3c692b1181a6562286db96a26094d18da24f69fa7e43975bc0686becaa4c61c375fa6b4bed0fca768f1da3dc6ef510d0f2f587974c16a6cc0830b5daee72405f19cc716da0b3d97fd6476dc24ac852ea6e7bc65398ff60a8da8dd053cb2d08c8a39934105956451cdba4026f8828007163aeff3144d2fa749932960e4f8c2e30a8d7cbb9920dd3ba31721c377c720e4f47f333af76496b4b4eef5c95a6179312977681397d1892e9b5454d169ba4b556836ba89ba952862b924a3cd597373d99c330be3a042db49296db993a07398dc9dc714fa37e1e4d19a377e0ad28bc171c0430a8de5886cacdc8da8d930d8058f28b42aeb593ee7756c6d2042a1ef4e29a388af66783ca1eba463f288eb2f3de211b5a382c7188d12bb174f4768e784564c58cfeee221e27cce8347133ac147f4a98e267b541213da2a1545e47b9e704287078f25342a5912a49ebc182be54ae872279343b6346cd893d0888ffa392541a8aa92b43a7820a1312558125fae64f7b88ee071847399144b9239cfa3240c1c36d0c3085dca26651a36a60c1e45e894a0796da2852af9d9c483088d58117f264c7d83a2e0318446dc557474cb06c2438c3e671f21379a89a295d3850de4070f2174e2e2e7d8162a8610a507e306b2e11184b664135febbe5c923481d02651a252660e7afca0f13ffddafefba037a1c92fea95543925f1e801c2a29a242571f314c383079da4c43f7174aa78de6f153c76d0e73c913175a96e8bb9870e1a555238514f70f18ee32cbaf43dade699b35e672050597441eba725315e62d1088db9839652b27a34b0e85bc64ba89e3dab245ddc4039c2f000113a5ed169af78522c39ca2f74b8a2135dde273ac95bd1c91f9b49924950131dace873b55bfecbb544c72afaa0f2968eee191d84d8a18a4645483129496b5319f542472a1a5d517366b7aca2a24dcf9071f33b5d44c7299a519298d7142f3e8717e7b4e830452f23336617b10a0dd203414729facc69b2579538a2f65c6c3122031b3772d86052f4a76ea595c41877970b2ec2483a8ad647ac4b98d6d8d0408728ba9c428bdc34412dee35a286a360a023149daabc71f65f1f512b9b80260a8a4edc392d8d9f95b24c8a04782fe8f8441f3d7f8c166e31982a1951a341dac26f74b1617c71386065dce189def477ced75e7574a251b26f9245dce420ceece0449fc23dfab828a5326b36d1b79a78f72d7d9564d34287261a259aa4aa723651fa4d99e8a2be75994c3a4cb4dec9acd772eaca6a1d97685c338810954f87257ab7b832a77c4bce98eaa844eb23724d9b850660e4a044a7a1e3526a67c72ba9bdd13189d64d73ba25191f1afe11351b79c6830e49742558c93163124609471891e8620c7ab39592a36cd0bbc08b2d20d1570c8da9e2eb5cd6c8a0e3117d89ba9e4a271dbd53d7e1884e09a2b38e46b422774f8eda08f2228cc30586d1c188366ccc6f623ed6e47147d472742ca22bf9615a7e154de87ce6a14311fd680a3ea279d4943a12d1899c0d56e2d3e44b1f116d4a19b7b7ca6396890fd1e7142fc5fee467c28b637418a293ca2de3894cf2434721fa7d57cf7fbd26a849da4307215ad9dcda39f274cb890ea2cf8f6ddab1748cdd8c20fa11d791259f2f36c83a02d1c96e9d1d641e01a2ad8e62f98396db7e41b56e1d7ee863f6605236ef30afaaa30f8d34d94c72bf468db22074f0a1cf5dca4a5fb88ca855eea193b4a44cd144e79ab8e5c0e1c507364083023428400113802874e8e1ec13d394f4c47e72440d470e2e3af2801d78b88e3bf4154449a967c451bac30ecd55129412a5256b30dd881a1860bc8d2f4e17ca961d75c00e3a349734f4292d2b9b1f46ff8508e6d08652727d727e6eeec58d2f703c187a810e3934ba2ab6484bd12ea664448d47d011874689c9772b07fd39530b87368b9698ee9794cc71c71bba0a3afa06a995ef220c1c491838ca073adcd06bef6eb9776d683fd3a46462348da8ddc8c1863efb644949b8b96bae8ca83d186534b4d8008d2e9009cc6da0630d6daaf294459e92e5e48a1a1a15b149105b722ee93169e82b74640ead513ee6110d6da7768952b27686d635346cf20bf3fa9aa18d25a81ca23f6e0e298aa0a30c9d101a4a46d3ca2b297a460719fa929929c518e2885a7a306ce4b83134bae5ef7339e3f957cae81043d731285132c90cf2dcd2858e30a8f12499b7f47d30b4a5f955a949fe85ce4d66d09f9e1e26222f7499a992a42ee26418255de89390d6a3ff2d51e8e0427b49d23e72d72ab676980a1d5be8674ed69ecd7517f768a18dfd1c2d93258931aa53e8c842a3e2e68ec94344088fc142a3bfbfe3e71872415bae601d67f4d9cb941c4376c9316a46e9b0429f4cc65a864f49f42d14424719ed6893c49fef862cf1ea404715dad15229c9174ab4a04125a3d78b7f11bf202a74496e53c25f2d9720ee143abd99fd9468540aadc97773ef9c4a3f260a9d18b447bfc8d22782421f3ec6968d6d312b884fe8543c8ece616745ac6342c7188d0e4ab4f2e8c8096d0acda4d33247dddd9ad06b4e82a51cee2255e50e26f49f63788cbf9425742ca137934c7c7658097d10939be3726ce53993d0cc09ff9311e741e63b90d0ce9eecb9d283eb5736c7e33824741ca1133f9b8476152d2abd0e23f42756e1a79e17a1b54e9d530a7a2b25b941a1830889a6f034d3103a252d798bc82c792e2f465f69659e354d6ad4601c4ee81042df67325cb849e24518d811843e6c472f939d748fd27e66a003089ae68e5929a724173a7ee0858c2509baff5964860e1f3c5726997096d42c6727868e1e9892ef85d26ca18307e8fecc1cb5d584edc2d0b1834d44f95b084da2092aa8860e1d5c927e49bdde494c8ca959acdd41e9e934b93424401656a656b97c8d8985ae41ae09e559799f521d65457362c8b23e219bf9aa55a42a0a482a1abd5c9e61c387decba3a21f4d4ae7ac64e9a534a7684f89793fa1e4cd99d114cd09a3712e9e20964fcc162f28340029456b4afea0a2244f626225456f3d4a84a7f828dad112cb57c33f596844d1c94d65e1d3c47cfcf17184a2eb4a7252bc8310f90a28da13cd9324439b3ed1981093f132c913ed9fbc965d9212436bbe135d1ecff0d91373a9ca39d175e8a4f7b326a1f1b489dedd92cc0e2a48136d4aee95c1b308b10e65a22bfd9a2f7fb43e9de460a2ddb76062ac835ce57c89ae5409baa2a728e24916c4126de5283a6a4969253a957392a0e2c40b723194e8c40c9f64ff3e51959f446ba1a34512adb799f6bf0af19f5222d15cf00c1e673d48b4df1a1ac3735c3c8fe8a4558f9279b464b58e6834261d62a93b758ab14658153436ca5b944b995d637a78ed94699d936c294634a36562aa08f5afac16d1695653294d64d6d2bf22fadce12465d595b1825022daf5ec71a35a0e22d0efcf497037e143344287131dab32cc255943f4a1e5377b5b7af84b0bd1fe2555153e2ab2354888e632975052104a06d1c8202afc55c9f433b120fa8e9526bc7d93f43e105d2999ba52549cf79801a20dbf1676a4870b65f93f7472ca96a0e2224b85d70f5d14d792241dd511351b340023471f7a4dd5dbea1504e143b35e5ac34f1234a2662347185f300e903df496fb42365af4d05cc59c5a3ae979683bc92b9d7d3b683ef70920786894b0f032b72063bb2403e40ead26490ccf97a3d173cc0e5d25d1619464d6a1cdbfda2a2aa7d57a3ab4e59da4961c5b4ce69c437ff154f82f5193496ee5d0752c49d41283360e6dcbbaa99854289dd21110383472924a2d39a6e46df21dc81b0c881bda12455b66753ed37440dad075f651ba73d20c4b4f0a206ce8f20825e61b2a3a9c6c0d7d9c855af56908206ae84bf82c7282eeb7b0be0c9034580da3021034809ca1b3348d7947c63e4bcdd04942559c2fa1a3ec094d005286c66298b78b2ae91e945bbce0200b40c8d0a61cc5749f9ab605253786ce7a4b0e9bb192ccd11c51ab13018818baf899041da49ccfa516240c5df8519a2f28693a4511040c05e40b6d869025c93ee293c937a2e65e6cf102dc0088179a0b6261fec4e4781c784702902e7426635e0b11ad26e86c0640b8d097145a52c94a3a597f205bb88392657e52c5a4a185058cd142bf49de189e6ed1008c1cbc02902c344aa87789673145b73e0c18d878b4450cc000c142631df76413747d2edc8b335201d302c8151a5941cc456bd1373929cfe82f49414c695a884a31bc0288196d8aedcdf224548919ef0c102b744226133589b0be94513340ca6874e65f93534e662a3dc98b2daad0294ff952c69caa4915848cb6b77ac4c9a525e3e7c500a142335a92b57cfc5c82a6d08949346c6b924ba111d9da1d554ca2d09a981d279e2458a7f440a1dd784286cbe4d1045d9fd0c6d7911fcf534e9dcf31daf4984a4f75e384cee289f13cf2b284199bd0afac888bce24766f8c09fd7b75ce1aae4d7c76e501c8123a499216379378f9dd644094d08eb99b143ee47427d50c1e8cff1c6c049024f441c73c84181d9baf81d841054b263ba223f4be79dcf2f3aee630ff00c40807176162490c174811fa8af9fb9db2648f0ed90084087da910d1417aae9f94e521342e2643be9f3461f20411a3139a4dbbe73b1021b469e209b265524082d0677459ad985227d59b2f4080d078decaa09745e88cce0fbad89a52985259a693d48882f8a02b399ea02907417a60354e00c2834e2893234ed041901db415260932378ca90c23880edaa056e5c14d5031ac8225f89845bf6162e9d11fd4c27459b495edf9a6ea25ac24b588c5b9657c3b9e4a3d72c1072cba4afa290795c41093a657746292a4c2cb7a989f912bba0a73625a4c92b4a295cb51f6041384ace461454afe549e5574baa6e384aaeaea12251faae8b7848999c306293acb5434964a3f47d912319d828ace9345973941778a4e3c539a260669c2c7ebc314cd95f0f8399812374ebe147dd2fe23297a37afa4f28b7cee98338a3eb86693379f0aa3492c8ac655a38ee70a8d216628f00314adc7d0f94f4c4a313e3ed1964922663f5e7695c713bdcfe554613a37059dec441b93ea4791eb161332d5830f4e741eb6e2280fd3a5a5db44fb9bfb844d37b1c99434d1bb8c2579dec5a4dc4d26fad1e549664f98e8040d7a52e44a9e927489ae4a5ff3c414f4f8ea96e8447453a79833b8fea812bd8993ac936928d15692a4ac8f4e77071f93e8c4a43fe6959ca04ccc1749344a7bdcfcb1e413d54f22d1560c13438930d13d2d24fad19bcd63e7f021a32a8fe844b383d09c23dafd3c5abb63a5117d6bfc8ed818c41b7c30a29d1d99c42fe1543e631f8be84783289d1573c9fbf9a18846a95fb854a2a79224d944342755c77e50aa41468c88469729a14d38a1d4337a0835450b1aeae11ba2ddcbd3ff54425caf5888b6b5728bb7589f94a21a351075f04188bea4245f5eeacd26840cf163109dc798b72bc90cb2922a88e6f4b25f9ed964f011884e0cbda4cf3da88a4a32a286f7800f4034d77bf22649ca233af2f187763f9824f75c5586f3fdd02695262799cdd25a611f3a9d849a4a92e09df1c1874ee8e5c5509d726bf8d84397e4ecee5973c42ac9f5d0753e0fbd1e457a8a9d8f3cf4a64c8f503a1eda783267e8c8d83c49ca1d3ad17c4eac8e129f42b4431fc424f18491a5546be3b9480e7af15187e682f0544929a99248d33fe8f0091e3d63fe9ca7e0630e5daa70c2648e693a5352173ee4d08fbccee817a744b5fa11875e47cc2429a778768e0d38b4155f2969b638b6e0c2c6e7d802ed0d7d4982548b61e639abbc67f87043e72763784d82dec1b8a16de8c4b9ced319dd19cc1c5163439bca622e69b5236a38c0b8f11f6be8e272897272dc8b1b5b24aaa14bc165459ee8172ce4236a8869e883923557ce9abcd5e4e28071833fd0d0688bf30de1d11b317830f2e30c9d92539e5bca49fc9c6c44cd1c0d2d2ca0850f33f4a9425c8887f498f3fc87c105f202036568d7938ca23d3787ca213274c27308253fe531b49e67bada5475534cc5d046b79cc2b53b09269861e874deb0267e3160e82f0799528be53ebed026517e296ba29b9c222ff4ae1fb484cdebad99b9327c74a12d1f2d252fe5123dcc5ce894a8a2e424092f154d088bf0b185f62491f1b94989b29ed4c261b406d9924fb2bc66a18f1363522d5996498bf881854ec9c1e74c1099a32dbb42a35292e1173a676f8f3ecee8d42a8c1c8bd1d4ccfa30a393fb9292e273f261853eb6c9a274fa69442d8c1b05bbf828a3377d9e24bf2c3b4ae32e4a073eaad009cfb9f4cb523849eced838cdebf455e8e12b939f7e26de058f7a29d8b306e8c38e2830a5d4c794ddc249814407c4ca16fefca194c506981175be4b84102c40f29f45962fe3515df4c62670c1f51e8af4cf70972949c7c4250e84d471dbf9265530ce227747193ae86feab80e1638cbec32bdb7212447f6cc5f0e184fc42c931dbb2633ba27657838f2698625b4a5a95629b1f4c68e7ac62b0304d32c667446d101f4be8f4c7e435cf520f1f4ae8722649c94108a131e9c58cf19184de43533ce75b6b8a93166c81e30d1f48e842c482ac94c2f6c5af458d1a1f47e837557fd411990f2334dff93f9418faa424c4647c544974bf8756c889d0484d6e490ea321f465490c716269eeaaf910a30b954f9a79d2635e3a21b4293263922f5b4a266a3e82d027a571e3534e46d40c57f001843e56f582a9a5244e92093e7ed0e60de6af9a171f74a9e414452525562cc87071e3c61736727c0b3e7ad0a72083fccef379d4b21f3ce833c7ae4eba9392f0b18356cd72902e32e70f1f3ae8b77fc3259d39579e860605683806b8b871a3468d597482e62e31fc9229152617060f5974260927e6b2c4e478ca8382472c1a75cf5164ca2529bf81c38b1b14a82bc303167da9f8ea26479fce1bf48a0e4912a3d524a8184344969518cc33d01042ef2146680e1dcdc30c42eb5926867a08195bbe116d5b020d20f4255a85c99c64c340e307583e1d973dc9711968f8a0d7a445496d312755a6079d9f6a4afedfa2949405010d1ef47b264a3f6e8c6c1234061a3b68e3c3a4f6d861ddaaa40328b0c1050d1df4399f9cf262ca9d679945e7a384c9794159744a867393ad319524feb6412416cd9ff61853624583c3c582400416f6afe8b2998955e5dccfeabba2cb3ed31da3855ad158c7145359473f5ccc8a32fce75d453f5e5e7252a5e9da5145bb3aa742778c9983482afab7ec16525b4445fb7332fee47f0a638a562c6a4ab9f272b6eadf20528a46851ed541af34aa0929fa0ebf31e9c88ca28f1f4d345d5ad1bd342e0e8a88a2577d4f9252923c14cd9e14bf1e11e7794940d17f4949fc92db6a92bc9fe883f40a5a7356e50c229ee8bdc49379b4096fd5398a9de847a6c5c939262f8870a22fcfc1fc7cf54d34deb99458269a96203f4d7471e1a3552e693974cc05914c34ab7e5a83ec94fd4a4e0434b4d8008d369805114c885ca2d112c683e8945ba257ed8fd1a27c2295e862b7888e4cca94aa54930825dadf58d9938cef243a39b8ac550eb22f06a9243a9d9abde19d740e3237069148f4fd5f2589215320d1a7b86f2abaa9b0577a4423279a142eb89520a7f217441cd1f86f8c9f6314688499e5f25793f02be1b8f181911c5b94600c1146343a4f12839594b466b0c020b2087ca4f5596a75cae2e7c0e1c516783b1051c49992909f17f5e5000d0ad0a040c1349144b49fcd4d8f5b8a884efc70d2452dcae8123b44ff2a6a42696fd10c1143b4ab23db256c5feffc85e82adea3c50a1d5df9b1820821dabc5e417ff0ccd2cc1944eb299a74d398c2ec8882e852d21e6547a6491d55205acb4f6295e8d513acb2148800a291eddb96e2490844fed0cce73831c79f9820e2874e92f9a49254764de9db1244fad08812ffa45e388fbd213eb41d450653c9f426eb581744f6d065d15672b45a44f4d06735b790333a9b8fd0881a92219287d6e4be98143e5f886124657ec0d0e24c0a227868736e5052ccd5c1f1c51639c2207287563e84c5142c45c40e9dde30f12dc91e5639c482481dda6cf95b35c9e1acca17a14363717536891a2e98c944e6d0258d9b4754127c4c2a816107113974a9c433b5e78467f14a8e3a3788c4a12d4989b7e97e9ede92082270b0aa2fac34991c2188bca11332c50aaa4c4ca1e48a1bda9c525072b64bca797e9136344ab9c8df59d34a840d57c68bba5890f714cf7820b2864e18d18d26c51c6a9db9000e1abc068620a286464e7bc37c09be255a9134f425f698b4ca150ad0c040182322b0408a2182864ef2ec39ab323d3c2339b690c1191a119654fe0a273f97de861b5e41c40c6dc9faf265c24a4e164a6cd4e510018edf22c7165fe098408e19748d1a3966f0501029c38de40506284081068890610c2262608048186c6cf185043ee0c58d2d3e44c0b0c5171278e4c58d0e2440e40b0510f1828d2dbe90c001230c091840a40b0f22c2051b1e225bb0b1c517122881074044b4f02d68c1d1a2012259c081051c1f22573880c81936102062c60044ac6000913208205205018890d12541e9a07fb4a6072254e832432f9e4ccf31e7e4380f06ca3183f681c814fa9435caa5ae9c238848a1ff1295d7fb6114dad3ec9d929656509e1481421f2ba4faa8694fe4097d25419488f94ea6637a2263b43e1a221e643c294f4ac409ed497e217e614974ca8934a130a1882ca1f9cf4c4166970e2e1f1125b41bf39ee5ae8966728048123add29bf58f21711dea7f31b30b8394490d09ad0d59139968ed08972829632f1b22a4146e8541273789333ad3c39456846acf36651e2091f12a131dffcfd299426492a87d09634a1836f381d272a2262a4a3eea9282b958810b6c6ca402408270204911f34fa24a14b7f88f9aaee832e731267339f244910e9417b7951546bf8cc9a771ef4f1e7e4ee89b1cdb5dd41a7152a7f29132b68f8ee4474d06fcc9f5435ac24d16dc82c3a29e9294dd3b34264d15f05d511d17b2c1a5d694aa624273193feb0684dbe14a2b15f41dbe4155d8a41941493c6eaa027ae38db83924b8c65ae155d50b29a6c913935851056344a4ce91a624a2ecb9d85aca2cf7b4946099f3457bc901321aae82cc9cb73629fa426be4d84a4a2cbb578a6164ab35370442ddd58eb02cdc004d80114d80000244250e10831291d51b391e371d8ed293a4d3209a255d1a3867344adee4cd185922abe26774a61558b10d9a599388490a2959f739394c5cb194fa3e8a4aac70e11ba28da8cb9f9bc94a0503442a610fd215f50f4792be7cac57b44c34fb49b3756fc688e1b423cd1ee280b426c6cae923a9d68e3f6494a7cd37d0bbc3821204308275ad124c7f8cb55398bbe893e5aea8a1dfc4b6ef0d610a289ae4cd0372413ed0919a724f19e31a10fc1443b4a860f99a57955cb904b34a741459f6f50c25c7586104b74e2c9bd5bc32bb7fb2195784574f73fc72c84127d98f135cd73dd0f79127d895aa23be5d013af378448a2f9d8cefb2b1ab2d547a2cbf9213c7acc861048f4bee69ad43a8917421ed1660bbe59a39eaaf87c0b218ee8e4b0f3dd31880b218de84576094d72fc669fc788462993a6f1645229cc08842ca22de51ecd628a5f522a4411cdbffa6c5099b19ceb174212d1b6650ba3722c1937280d118288e65c3f7c49a26593e8107d450da1b22d28a54f43f47e294c887a5cbb9814a28dd5e2214e1226f77708d19c79cea96e31be85a8468d1a35e4103288aea44972085dd5cba011449be49bc7301fcb2ca9184202d16555ce5f4bfd93a207884ed6b8b9cc6384a8a03ff4a34a6e18e287ce3a6710f2c48f1e42fad0e9292fdd79acb49b9e8b83e3c6175508e143bbd59d576290d94323f4a74a29e7247ae8ad4ae736714cf2d0774ca9abdd7d3942081e7a0b3adb535ab6b23eef0a2177e8949cd9d17df2465d133b343b42f5e6d268481dfa787d39e82d9d0e7dc79474d22ca339f4a259a2a7a5c5364f0991436bfa635945a49a9cc32808894373924ee1458e3061650f814333b2b54de739d1947c0979436ffe26446ba942dcd05912fe9977651784b4a193429fa8a9f134a276c33706216c48eeb829c5cbac4ac81a9a912b72953763e9dc4f1d0d2d2c70002842881ada14da9238f5135cf34a436b959ab584af1067a62284a0a10fd57d49b6b0ec29e5cd8c903374a282688cc94a66684fffab4b5d4b5b8bac105286367f34757bf9b66c0e199a4b3ae94d82321943676143e9782ae69854434688183a133ec920740efa4048183a29c99d63948f7f82102f1342c0d0495245c69379857ca16d1d558b7baebdc91a51bb198478a1cd1f55b9728b9491814148171a1983c5a0e3ee9f786e8e6f0117da6ca9939ff20f1521763fd645c8167a6bad8abf164e670d7281bcf862be08d1421f4bdc0e3dd945c46934b4b04017373850a38608b0142159e8844c8265c7de4e41a74a08c1425f7d2573eaf58cc6fe0a7debe9b9c876cfe865d375cd4ca9a7960b0e31a30faf986485de4d36d3b322f38295cae83f787ed42b95a43cbf0abd56868bf2f029967732da510db2aa43c64cee54e8f3c40ea20431a2933f85e6521254501349a13f31c971347b124b72a3d08af63c172e080a6d7e8e8ed379748c167a423baf16d563768cded2ff3acfbc096e3aa1df3171b9f583fc6e9ad0891e9494a78209135a7d51929ce269095d8c8a239fe28fcfe628a10db9dc92b4e52c3b27a179f7d4dfe12bcdc24542eb561e7ec3ac47683f29c1244189aa11da60263b4719313a4c2d429f04d3184af8dfee7c12a1775fcbae1d7e2d647208cdc5943349933787d888d1c74c5925d6a7ab624608fd493987f038a953cc4c10da92bb72cae80508ed86c9f120ad645c4cf9419749cc151fb4a33149f13ffe727e7bd0c71293d049bc985be6416bb2c757ad4c9ec4dc417f4ae4ad744ed29a61880e7a2db93c8ee885e9d22c1acb2ff1972668de912cfab378c2f2799fa0af8b455f9e3525293b335b82459bfcf2cc3794eecaf68aae72d025fa5b92c433b9a28f673ac64b35d1ddb6a29f8f1eae5de8bd82aa3ca77410d7e1429f9e644f6e1ccb116fa153e2e74d93da3fd4d542a7992785e9491ab5cd42dfdd1e232ec6faa358e894a678498fa76c62f40abdfcc9a0f2c84e7e9633bad4a434c8b8161dd18c4ee7e4b12b6a857e4f30294cc5c57f57466b2977eaf3cf415fab42bf41e538199d56678e39c5a9d026c1620c32ee28e5f914fa4cb2c9f9662d964752e8a4249796b9478a9644a17993c398a472a0d0c73ca9c4247fbf49394f68b7434bd8ea3451dd317af7531ed38290f9d5095d580f6b2536a1379d4d2f912e6662421f347b4ac14b52a26896d0271dbb34f6f24a68b4b6ecc714fc24f4a1b2fcd3e40a21b44742279c5842cae6943f4b476863e5942a3fee780c324297493cddac996735a808ad88cd732d9fb46f88085d5fe60fefd21da1b38021349e4d3b778ce133092f408c3e34aea74aa1a74549de610142e89450be417b38086dc8139bf2e7706d1508ad896d51a234eac9f983d6d37ab7947042631ff4fbe1a76292a4ad353de8376ccefb67a682090f9ad3d952c9b7eca0534d8257ccb1f2ccf90274d06b926557c02c5ab520b6bb3fe5a3e60a90459fc5e5425914efa80262d15c5f09b2c41613b47205c0a231e916374952cc19f44801afe8672e94c9a932860ad31914e08a3e4d8e7e39a5a44ba55c4905b4a2b3307256b45dc2b5843949d5b48a54b4892a1a15b52fe56ad14f722afa331ffd37f1991da3a2cb983f4f96ec29ba1e13d5c2ea96ca5953b42d72435a92a252f4e69ee409d19ec43c1129fa1fcbf193ec23474e348a4e0cfa56495f26f9bdc43d284014fd8a1213c3c2a518cb50f4999396a689f961048af3f39fb0fb9a4f349b829c12224f74622729bc5f578e0b5127fad81f45c9a34cf2f510271296addb44af9ad2941679a2938634d1864fd12a29738b194399e8d5e35b0c9ae413368530d17f3e3d5da2648ea54bb4f33ab34998f6584996687393494d3ff1a4972ad12625c36490254faf44897eadf7b4849e3ef19f44a3f2a6443f13f3775e12ad26b9ec31dd631c3f12a700487461b1e27a831ed16a0e2346e5fcb962c811bd895f3963e71cca4a1ad19fb09b5b42cb88664dc972f2675209ed221a1125a724279fa90952548022ba98538f4ecb54e2a889e87489a133cf72644a22a2175dae169f4baf6c0ed1c8d112f54f1eef7c490cd1694b515c4736098f4d01856865f62b73e55813bb84106d2c99b1262337c5960ca2d31fa76d5de2adad44106d92c47b7613cf93ac9240b4c9ac933ecb8d9b55028836fc778a71f592b0f81fdaf13c173406f9a151a164a8d29774dc247d68f48caa08cb263ee6f0a1ad9872890f1f4f92b487f63c35a89a9c4c88f4d09b8e53e9a17b7ee6a15739492cbf180f9dffebca5e7b8736ee75a69c6487f6c49cb9bb3545d16a1d1add723a68d179f743874e66c8b06c829705e7d026ffb27025979f54caa10f4ae5dd0bf72053260e9d205ac793ae9282bcc0a115eb395941e834cb9d37744aa49af896dcd049d3e559e5d4863e2c636bc59e0d6dccf134d7c486f3f81a3af1e4901afa303105dd2e4943f326bac5acb12cae040ded289ddad99fa113c74498e55b9273ccd028b12b640ac293249f32f4c1ca24fd8f27d4c264e8754ccf4548c7d06affc7119e189a4d82c73e31260c9d6ecd6ea26486150d83a1abf8972f7449cc29426974f7307aa11f59eda7fb2f97b875a13f95c37f25b933c81473a18f9a4d65af4a29a62df4a32a5ceacc5a68b7afba4d6cb3d08552f91fa239163a9da62b537f1413d5bd42a3e926f794a87a3add339a750f9a336fcc684cf620433e970a2163854effa66cd61a746ccd96d1a90c72bd29b35c53b60a7d38372522ab264eb864742ac5f211a215a2dd52a19165622aabfe673e4da1d3ec592eab5676c94ba1994de24984c80fa247a1cfcf9b356f97968ba0d058cc7934c87b56113da1ef9354b789ec50fd8ed1aa6879a92464a9983aa18bbabb6a427be3cf2634fe3b97ad2613fa4c37d35f39df622ea1bdf29cd1c398ccb2514223830cb2f3750a699924f429ab93984a4442273ba9e63349124e353d4217835730d360962da6466864922aa64c4945684b87bef24a194ff449843ef352c7d21f425b42740ebdc15cc48918bd75329317235bc442e837a5783ac5937b150d42ab3d9b43e6dc5e420984564788cc97ce399e7ed09cef6578ca9cd0d107cda8e91ffdb0e0b9eb412bb27e62522a6bc6f0a04b25832ebdf3d9a3e50e7aebe819b753c59c490ad041a3e449118f7f165d92171b4ecc4eaa9745d739224cc409e115148bc6fc7d3bf72541438645a3278926ce29eda4dd577422ab5274ecd117e43ba266a3ca6868b1011a872348020d57f4eeaff1f262f2724d2b3a357d4246cf537d29ace863d672c68bf8909555580da4a18a46e6c25452522e4d4a457b9a848b1d25272142459b4fd0293fde293a4198247f53c8f8ec4cd19e75cee5ee3c974bd1c88b25ebff491321165234d264ff7892a3e84b26f953cad933c999281acfffe14c190aabd1050d5074e656c104ef139da5ff991253fc4e95f144bba193fc13349d68f762c48976b4e86ef2249b68d6b3cb458592734d34d165c668927332d129dd3116ccf2b506136d924faac5932ddfe34bb4b1257c282586ffbc251a9d7193bb62ee936f25baeedf3c49126745a744bfeedfb12be6205e33894e994951e3e2e452424982ab565c5089445f959488d0f0150f241aa5d55acb643c87b13ca27d3579f7cc56b2f23138cf45b9326838a2f72032f75a68cb229646742642c51815f117bac288d604a19412ed93dfaab2887e4764d04b327f2c254534ba74d27ac14f32e5398d44f426f9ff8f85d0317244b4497643ace410ada96cc68b31490bad213a8bc947e72ddf70b285e834e813b1f9cb3b5742749278b953eb6f3406d18593a953d85210adebae67509e3af440342a88d02c1f2db86c00d12699329bcc9b529573fed00915c3c6963c41957ee854e69225584a1fbaa4524ed5257ce8f79238f9c3a7c70bf7d0c7e855e7b81eda91b1b393874664ee4b69727868e46249df570fbd31bcc3aadda9fd5aa11d7a5161c6a3c6ca494a75e82b73896e3dbfdf263a349b82d05319333af773e84c8eaa7f49b67eece5d0e9e87859ba2d2fc82f0e5d8edef89444eb3f250787de4b92e1c9476e12a77d4327c224c14c36ae37c9d170432707d3240997a6a4181f8d36f4b9e43839570ea6a69369a0c186be54ee85d031bfa5b986764d87cf144d7f37a9864e708d39cfc7ef1463d2d0c54e3121fe6de284686846cf2ffe3f439ffe4997a43b08a5638636f9e666ea12e76f19ba7057d3253c6f7f47867653e5accadd185aef203f26214f148f89a19372f2c94cb130f449d8a0e5cc357c5b07864e935242769abed0c5544b96bbf74227e51f994b0e324ba6d585f684ce73315c4ebe880bbd5ccef3de4c4afc2d343a76c6ef33d1421bbb93263f9d2c347f4a8f4e3163a14f935a623011a2e5bd42efbb9d2dba67f465c2e7dd93191fae19fdbb88578c664bd30a8d36152ff9a5657471af476436abd0f7c87219999a5a1a32baa4f753902f0d2ab47f26322694a6d0ee69ccab3b9e458452e8fabc2bba49d13bd088421faae44aac5cf24484422b5ae4e6cbf84d3a674fe863c79262f54b4f7736462fa3c2b5c5ce9cd0f89ecc5c4ad2b88e59137ad390d5127a96242526746e4185b55fca654a4be8dcc49c314f5892544909ed898d1bc65244b99f844edc6c6a6ad262f81d0985c6113ab1b2478c3ccd396b84be72e3626cf2922c5e84ae4d58521d6345cb88089d24a7afa7e121742ab3e50f8d8ba844b0a4226130128ac4c180388841f8cc7b00b31308001838240d8582a178449235e9031480035528203a302a1c222018161418100e83a15030100a07c2c0701810060443e180303422b1b33d290560029d4034e01950060e02f2803fa721f8567e981a9e0a2e5cac220f451a1087fa547c7dff723a14334008a803a6ccb45ac05ba825ac0c6710fc99858cd7081c1d7f045c79906f9635f993ebd5ccf68113e74b06300383002ed0dda17ec943821e5827420046369641d510106485f2cc363605fc423bc0f9600530d8b80ece29fed9e0020d30dc9aed28e32ce420cc4e4fa783c4d8c4780b38f213b6cdda9135601d2cf882f5804c4e84fb70e59283a33f38aa65a020d3cea0edbc802fc6df12fff788b5db4165436e38d060c521345fb904cb06e4a0e4a53389dc617fc8efec1936678a44768c2116cd3074181d92aae4f1e721e5c0527109cf6512d91bfcd10bde156ee0aef959fa51bec25b9bf65f1e0c039f9cfbce270731f0080c031c86fffb405840a40006494833b10dc20b4332e33236f4171e0f103b6d2a281d082ae096e580a28b520d8f84dbe2f70807b64879284b600468e7b054974810bf10554aebb94e02640fc803e8803a401f70817d7526641420cc342c02fb8837e2878acb442e4ecd1c5c5f43445a74c1a8ba9fa2a678c800038a8b23f9b05b4004e0d45f6acd659c10e1c277d6f907ac8a6f036ce343031c2e8e43e6c902bc9a761856b030c49a0cfd2c4cc1292bc6570bc7e3df90a6c145e80c0b08035c84a4a23f58ac14fbe8e4c4c001f7d398f9be9ae403f1d682dbf00bbcc5ff5e5cce808c0a0100d70532465f1983ff831048653d314f81fb26e3f364301d9a40219c6be7cf01f8c0024e03a3a09bc026101a6006540653ecd3ee418fe1a6b0269c4df813237daba940f27e9aff8a32b8883e0332cf7f5ed7007f9b0e2fc101635e580eb61a110b1b0338019cc77ff925c8e37f19813363d670ca709de7b0de9113047966c32ef982c3ac26f5537cc0a838c1cc96e31797351d0bc2a78eb0701956ea83ac0f0717e574425a28e29abcbba595cbaad95d08133c2e7389d926618562409b00fb6fac8062aaf7051f602f4a488f80fd70287065225ec570101bcc0d3e51ee8937afb929b097e1388007abe86bfd65a7b12d15c275f33e0f35cd9dc31656548abbefb5e00d02a382026413080da01d9402a4034fc0721000e040f18e1a28094e12972ce91f8fd70725ed211044113b2fd180e8549fa28d2d3e19ce22247c5be7eaf303d0960fa622dd7d413269a52da22a81be14576994e2e0c822a30559ae96c14ab4da070cecf0f961253fe42c50639b3f69caf5d3c07ec19c25b9f767243d56089d02431a976a00216609ca8f3d828731b732c1282718572b1f75d30c5661c710cfffd13b82cb3e1f052434719d164a507b73c9fa58db9006d70d3dd8c2cbf21301ef209c0bf785e560638f9b8f45a85c99d995309633b816898b6e2652aa5f6b72c70c6f4fab80365c1a92143065abcf7a78d1171179c06f5899477b6ad982f58515ab8e4c20193c46fc1abc1caead01de09f3f49a0c9cffe870da2000c4fa9461390586b171f96eb365e903aef3db69ffe6b0eaeb752d4f875e16fe711da13a3ff202d2785c14feaa3fdd85d5ef67f9a63e3888002d145c6af1bd2884e2a517cf19bc35301ed26d9aae8a86d7722ef082e729874514c09e766cc18e8e1d7e8aab1b7adc8b1be30f86c70fff6701d0209b3077538196d26cdfccd0196466c14367dc23c67581688bbcea0307f5e1c802972de8180e55b8fadb29adb20f87b41e637c18b0f609d650bac0e67c5ecda2fc1f0753fcd1931c0e4ccd6c4b225e73e3a0dd2efd5e3e1850abfe446d8469e33ffdbc7f82b65c63841e12bce0485149dae47d9ec857e502cc6e4ae1ad0a79a0a4847930efe162386f752d4f84a14c000c03e1993426e429c553edda9c2ad7d82cc56e32d3513c6955d250dc01cc5cdb92497166ea1bc68a1da187cb43f8e9ae06501ca3801b2132ed1fec5576cbccd1fb76e2967fbab5533ac109c22c0589238d07f634d550028e81f4a99e11b9d3424c4f045c1da5b0f2e0563c85f63efa9e00dcb632cd19e30d93e33bc3ac3e0d421fcccd8c5cb9c7b3b2e1bc82b20273615ba59950ff10d379310bb0309a6b0d57192a233c9ed3ffb870e520862c4cc9bdf9836dd71576e7965a3de14abac5225ccf73b615889efe658b4650af3cbea55d001b1e3bb7bdcc582bb607ab6daff090990adb2b25e06ec5b8094b2f910a244f790d21e2d8a89bd9466a786bf45fc09a7f4df3c24ab8731a08280509f1e8c2e28f385e5daedd1c2eb0b42e6acdb43948fd7000322b1a3f45d95092c5903c03032f08785e4a623d5cc44db8b87e1720ef3cce79aa01ff7cf0bceb891d2c734a33786dcddf6da3c0db8ff05870a552e9572c92f8a4dbee9da5692def041ca36c3708943f702ce6ebb1a108f5e5d5c7fa54c696975812cc543a99655602f0d56c25b76861f2e672361f11094baafe4ae6b6c8f2cbd0282def8864011b3c935ced809315cd27db394b001e0eeeaa4588cf3b4e9c9698185a5849f5f8654c03c35e813f69d92e823dd653172c2847d014576a833603ad01069af40cbfa1b09408b11db0b0c536a0d6cb96519bf717f8259e2a4d8887bcbcb9d0190a6fd22f1daf248aa8f5a3f80a61cb226b9cf029184f466d8113eb3589d3ea7ab7f365c9a1491b2f001f0c28a13631e9b620e5987873fe7e77c330fda21b24f63ac72c79fd42406bedd59ab8406c869bd62cb1b04830a69f85d3514eb57449b155f193214255aba35d14042d3d4ea4afd707150dd8e9cc9c18661d83b425dbfbd0f89ba552cbaa164ac61f0cd10a87a289f8432a0f4ec26b800346addb1c711488bf3c78c9072de46265dc16b616468da84889fc1915c648c9035432257dc66c620d0b054e194de77c82fccda41d7dd3db1db099cc25e0de2384f6c34200f66114c941e4209e3192edc8c04813a723e937493c2ca6b9033476002a2160c9884b61133b3dc269c9edaec1d63be177d84ea135b858fd63721639f40b6ce8ad9a6ea9283772c36fcd09c46d28b242dda517dbd12e813217e0247f9cfda779af822f8aba8373140d4ee25745fa9065a8909c5101458dd2e6ed2b1ae12253180472ef5b3358b8c36e53bdda4ccd95802f1593295db81974590c090195579b19d97de92c786923c952b3bac998f427e0239ae83ab8239e3b3e2d9a78427d92b7e8b2730b5c239ff76a5c41311169b93278637c1c9787abc632c99ea62eaae6c6c1b94a32cd0cfd81cfb9d8dc3d0ea481281e1d930e866431bc3230458f7c94047cdb05fa426d54f0d8225bb708900b2b042f37023c1c91b738f038381c6e3a1cd0b1085170623457399f7bbe9129181165902f04958328961e62d515aacd803e71b71a9a9da5a9671010231dc431779cfa9b56d15908819a8531b80de5012a17dfa3a92696b238d7e31c7eb997a98607a819e4f898c6b4308440478ae113a0f415f2f550341f4caf8cda47ee401965226b632a7357d39543a4d6933980a1f0ce2863a1e20163cfaa4693b152dd3df6f932cb15c75d2e1f9de808e6a6e130fec52c4ed92924ac3ba649ce0b3a02afcc158bcde0eb6f83cff2bbf349d9a899c32c0bf30911b21b17e9b913d11cdbcf5db07c426ce85239821634a0e4930b5398b07bc813c402ffd57a983e07853f7b6816546eec8ab62605c7d1f57562c42764642889ad5ade40ae98b228918d0e9ff485193f1a1e2e03584f1800715b18407363006265cadb03ca8e73c567114e6c2960ddd126dd00672c6e0a8768ae06806726e2759a01303872bc265e19dae5da7df9d40142a0e8789bbcc169e726179f0f7d7d23ffa1c696150d056678f5855650f14aaea82fa21911579271832c44c31aedb3b0ca359e17549da46d2c325d64f87b3796a3312a176ec642aba4f0b5be2ec40d574ade1204e3e8760789c4bef9c3a7ad3a001ec02570c392b8a78afa6529c96404a16fda030402c76b20287031ad94b176aeeb460991b360dc811d3ac927154a7f9e531a9b1cf3f73c462c4c7710fc4345a32f5b27fe0d45937380c78de4d1d946c8e1cc1c863a4e394d8c302d5d58446ecc6c7d2dab432969818c79bd7d49dba980e776702aaaaae9e2cf60a63ac0209a386bc5477db4091d424410202d51ce1fbb322dcee700b4cab620dff3918df0a9598dfc71c175eda14343d8de53ef065c7d48746da39cfd973b47abee899b4facb35b565c2f8e963865565663b057041581b460e18d06f4a1c3a04425e27809d4f8fc99b39ae4771cf2f2db02f89f624b80574471136a2e9904473d2863fb14edc67c28bb13c3628775346353c65213c994d4bf29687353af455463908cf25ac9ba7d9d8bac48f21f41c60df799cca2c3b052e51db2ca8cc1d76fb42db2e4199d3df84f0b14018049d89ec55eed5ef85aeb690289e8c772ce62dc21a0f35039e4ec9502d80ea8f79788be5ce4c8d08223dbbddc0fbd02901d6530b97c6c66c88c532b0938835c8ef7c0409c75bdc19f48ad34c905ff4a45ea6b03774943a1ffc9315bd54cc2ce2a5ad8028b886baf8e85f324cdb1302a3f6623bca5826e440e8362910a9640d388a527f5a71fb2e4c52ff599462ae875320c5e3478c3d3cb8ce077e798bb7c55c1a11bf8dc92af26f0c3b493998da2f1c7ab5adff0e00b9d34f41c3c2fb046a5990cc04c5afa097afcbdaf512cee75846b356215091a1d6ad504c652255913601a24d158576069f667050a8e4e194e11853988676112860c4a59c7d58a3c862687ae041e61761a6f32402b053eb7d206a94426f50f10a4a395325b0a519cfef5f47bb4eae811a02dde1d11412c7159dc2485cb64a98605348e9a444fb4217219aed4553cb2e6d9c0afec940d32a1e71f1401003eaff31db956094635897387a1eecc5d5080a4cff66fcb385a310c1813c4df86dbfcaf755089f3bf3903986d5324de433d9c8d62fff0bda72027b2ade96fdfcfe9d81acecd38d4b45d209a1ee1728425466f67ce08cadf0031a0ee48d7b3929f9c1f8d47ea1a1e9793e4946be2d5835a369402ecc6cf8c6ba4d47cc3907ea191ed90a6fd98959c35e657476f184d16202514c1727ff7b4448b74c103fb02ed30dfb004a1f9c6ea0f8629e27b90d9d9cd71e39695c088af2a26b23a3c24470350261990301f3a310660c0c50fb884322648896512eb3f331d4529a952b3e6e53049f472f1bd54ded6f9ede53f187d520301bb5fa038313ba9429d69762b82e6ded0fe702de62f3b2add381ea990fd52a90122a8dc7d68d7e0da48ca1d67c87450e975a90abb73b2605e6f177db3270e939960335ae0394cb8866a8b2139d41c2bb47271c517b2485cf6ea08c328a0c2134e9b2d33b9cb899845d67969e8ecd47d623e7397aff75e4e3b9d0618894339cf9d2c4cc241f632e91164e468b866ce63e31e7fe4d0a2f1049f279fb5af3ed5caa983a3e612b0404eebe7578e3bf4942c9b143ba22c3f70a69d4a242e899cf521f69682add8f1bbb25e1764433a53e85c10976848e887417ea47a2b0e69aacc4d09ac466249d586ce22cd62ea79918f10a4138a8f0570cbef0e68974f59b7af05ec7b9cd8fead04a4906e4d5c2ddb60907e9c83f68941daa836c3f29100117b262b6f4f0fda36e36c54211c9a455ebc704a233162778033d9a38c2f0a203b8b8ca9932ea7339cb83fa88ffd076a4e670428770a862e8c085df13f58307965c3ca9593f238d4c2953152d2d1afa74f8cf972a67669429a46fd9d697587ff07b1ec6ce72e71ae9ae09f48902e0c9a7c0c949d14c5a47a4b9a158f0fd09c73e83b1254247b212ab40f15b8f8c34607fd5e4a3fa0d2c0aa4a776435c08f20e18b259ce43eff097bbd7ccac823a54cd6e2732a5755761649f9ce62fc50b347982b19e41ba422c16c459dda2523805e7870279911468f4414d0717973f7759adb2ab39c451d32db9521005285122f126512b313c248fdbf7189e551d14af54f56ecda852cf9fda90fb2d66abb54ca56f83415a09082c9115adae7cc8dc07150da4e3352af3c05e6a0aed8b6a5ba07f927d8260964299304e3846a8a9b04ada5ffaa2ea92db8f436a73c0a967f75fe2aeddd09722aa98bc7144588910a68144d9346144826ec2bf82b544605fe7c4ea503ad1e8cf8e30b8d37f3f7d200c1497b9502d70ec72b0127a4bdf39cc6a0b7a6c97f64f953a24ee731beca9c40007cc5f612ad13ba961d69de4f552c2c41e73966e8cdb73e7e6efcc18d21860e32b334061c19df6f245f346abffa513fa36c730f3d79ea3b674ab73ac777a60263e86eb3cbcd24d36194fd8ecfbaf6150368654a14b4d70875aa43cf3fd1014a987faff1b1ee4f1f106ee8d072bbe49c198dcce730be55e8823854110a93b0835d7cd5ec81fe7b73980b98c7742f623a53080fcd7987d318a1ea6a4919e143c4c11aa6e809f9344bd4ab0648e49f2bc42f87b4c60346feb9139dc37c5b39543e13643c746976258f8e9a1aa6aee1a7f5f5bda6048c9ff93d2a114fb4c04f44ad76917d269280c15cc64c5e011d40157d09d0be5e0e8ba22a235457e7ea8b3ec12b78b837f1e5687f625c1a6d44824e58deafdda469ced512fc295fdb8320c29f7d7566e256d0de3c5d50de9209b71e9a323390efbb7bbf9a818693a550302ab26372dd53f021a995369c08e50640a45a903acac1852a289432cc772ba5e971f0b37359baacfa423e028a5690d4c9496cfe307aa94e7d6e0a92c6e073f5af1aa8557dc409793fe8ac426fbbe79330dcbd4683e903e5f473bc1282a5e9988ae4967398b3e02bc1ea30fa718d33e43a8482ae25808b52eba28050ca770204e9a4ff371d28066b24e28041b44969e5986e56e34bf7895cbd5505d2696423904de5d545a5b6b200ba2993ae8e04181d7a756d633760f2a87fd7e58abfa95e8746044a898f89c5929c4108aa097ec078de2a4cf7648240256167b18d271042f6483b00618023df2843f83990d960078a5c7aa03696908e693110f92a23b72db7eae665cd7a8ff00f55e3c083930b330cc9b0446373616785cd31172a6842a960026b43c869759f17940a499ef31a0d22b294c3eb423281da48f88c984b7aae85779cda5bfb2e653357d142c7a741d7335259c7b8d0e331b94918502f30d51f7294850be564a9db7b026920f6acc69efca4d100f60b631639e844c859a0258c38170471614b19d15481f42a92b5f0f6bc5982d8bd430d9ed7922721f56126ce370d61d72c6ea0c26be6e4c46a6246e2c01e2b3fe0b14e7e710311b862a2158ab40c52c81d37a8b710672cb8e2bf2fa4aaae0fbc7436597a9b43e9cb7e3528e00f5f69f8065cdee4164b26c4ba57a039cb5aeb8332a62f0e033e6a3205c1e0e80fbfac5ea1589cd19b14d6873e8abe0a9f212a180618a04b7424dd7eb5e91670c8b4b4fbc0979cd3c317d93700fd81dbf2f58b2756947d134738ddfb66673d78b69495de39388fa819f040ebf3769fa15f784a94cf33a9ddf5518c269e8714ce857786bcd65417bdfcf3813d81ea026287cfd76734c2c00a66df183e6df5e5ea568f7593437970a59ba08cbe2783b77ee0a4ba7a871e5989e65a7214679d5775ede268b307e242805a7981cf4dcffa2d9366c3313e6bfa9552b46ed3cafc690b1117417cf6a07acaf4c2cf488cfd84cac936352d66257b3bde5c577e798082cbd911fc6921dca83903398f11b70a1568536924add15c1b529858671f895509086d4193e34158120ce230c45fe1eefb3d0790fcb137b0bf27d039df2b592af020b1492a6e4c4498f2a7b76334f387d1649771cb721b77f6e4c0bdcf40f94623dd4388b71811c41443c475d5b98b90889887c062d02a0e501e4e0e8139313f3af09230ee092980c1db2873f42e284b205a837667b76f26407312be361db2ac58809eb904f7e47d349512ec8fe0cd72c3688205ade88caa3c223e6c540ecc12bac4768cd9199dfa564fba50f7c7c109c684166182e3717f44003cff846ebc218108487ed56d0b12f6d23727a9e14d74a8e367e68889c59374e9e7a927cafc3eab48c1d6ea042cfa78ab6f2a6ce184845891bff0d97787426461a5c21c1cf1dbbc95719a01d16e3de222fecc067791c23e6ad2aa29a9a26549ba29fe2707c0892947dc1adc16096787f140520722c2c38234607670d52dbccfb2ba9f27ecd2e092d78c5ba99763ddb783c056bf41a158b54aada305add80515c9dc8874abab9d000dd401b6905c2dd0846da2f591366749e1a2fc971932f271585389ec7691f7eaa147903751456aab64012f57a1ba219f93cda64070a12eb7c4ab95d9c11e5e1d62a9384f336a6d27713148069d60babf2707cbb30113b22ec2d3423f029fd9ff67ee20b094fa80faf68c4ca4bcd0223e67e6ac3c37f240f311b02c83d3a9d663824d05dbdce2aaf5192df7c49c7935b7495b6875ac36e97b6bffd450d93cf7ea7ef75984332c01c4ca02d5199357320bb90b146b2af456f8a1bdb05bff584f5034bbc941cacce693bc92bc9d6c38f654d9600e2630b004a4a5e90a179b548f315fe2717304644ec3d642d4f0022c186d3cfebf350c8dae2ba6eddd0d0d84f36462eae397ec7db5859b59c8eed3a6656e784165bfb1d5670611f45f01a7e3ec6fdeab7424a6073679a03740cf51fe546a85d51594889eeedf9841e548db4c78e99d178cba0c1baed456596102414549387e7514d19a41bd01aec03bcedd95f85508dfcf63d9965060a6e9f403ca4e12d0ab20f72bf0eb49c6da2509472bd91dab4d497b955c9de18693be87ea2fca985d2948757aec9b6a042aacc92ec371f386437577c1e8f68eaf8e74dcfa2a6b103ae0bcde62aff3892fd53c967558ea5bd757f602e8e784472e6feeac04a3bc7c67c1c209a39d523de107e11eba092917f3cb8c2990e8dc9ea540d463d252da664d4ce711155d238a30460f84fa85570a394a02e6ed4fb2cc539bd172fbc6ce9f9cc86691d872a57fdb98ac35f4b525c0a6b55c32c2daff5991c904cacdfa788be72325134918df218931701b6244b023b0851d20920a5a5a9155b8a30f47f7c30d4bec0d72d83cb1d9a56d66e989e08a3a652fff651827f040fd32c9c376dde489a955f7aec436f907476b8aec0de9c0a4f330d0c212b09806f65aa34c87cbe93046a98f2f1f733574fd0849b12f745b620d92dd1bf1553e9f7d172dd0c518bedd515d2fcb4c48a004ac838644af95c141394dcc5696bb3645b19e075e0470c29b0664db1cb834be70da5e45b43423dcf4c81e0149aa053a3aab711648c5f8af4110f8231d0c9ca063bfcde1526038a8cae48eb03308631bf733cdeef1dcf5a6267810864c6aed59749e4e0e822a31f49c2816e71d190af08c92f0c07d9b4e7fe40d90692fba7f295e5570c23099107687ce624d72288cb7a3e57a453eff899012d166a14328429434a4634ad67722a7e2d2cba2c0ac0e6293140335e09e7a9be6423678fb6f9321cc9d0f86a78a8e995396e9a1ca1b7952825e2d98555fc5ae8a1ddfae4c8d9569b50a40224c70a6973af4af8f5e029c171d7251680a9609f012df821ffadb3e09679fa6cb2a05ea5d5391973319a98a5d1b72c823cee7e80690b0053659b94cfc50d4a443ec431f0f464a0b603d62e5ff02cd214f34c6c57ba0d34f0a76b9c144e2df123b389fb020a9c89d55b6b931f7a255db8a1860313fd83bb5570d5f9007c41a63ce6985d144cb17035ff77a1472d7b22223ac05b1231e5bf94b110ed61e4eb68ca822a7f91d542110d62102664e70e661328ee241309384fba6c061cb45a689b3d0ece75a984d22bf590d13039a6ad3509909f897426e85af70a5c5e00e03d24629b88554295b1432537252de072c6494330a0992363d1ab10a7d6d09f1cb3262343de4f626c64631245ebdbc2c4f16bdc2ff34c88cca04732354ec340cfd67a661c7edcc7096c46b57fd0f111957c8025718e4d255d46419adb33ccdf8d236d29610ef5af62e9bfc3f83ff06f152cc96a52365d800e8561b250821071af80a7629aa3fcdc616ad341846aa0a3d963c159f667b95ed1899844c38821426881a216cb0ee57c8170012e42af4b48b221f6f6e06f00887ce5ae405961b24fa11a3e60042a9b1dbd136cdee8e20c8f6b74610b1da17706ab2b6e91e1114206624cc214aa22e42f48b88680d3a82e5d108f443a4d238bad37b869a1b1c3edaa88d745779f9ef8565a1a354e4808bc5064f116e73b0b3c70979487e3a657c5fad945385c919e77aa816e42b482c7cf813108fc7519c703c37a04573e32cba917ed851f5294fafe7265aac1e556f0bc0c1626cfed07d127b65c91d5a5e674ec3ad3c6912e1c0b1a303c3a055c796d92c9cf02ef9e112693408b094c541fbcc2f5cf99ffc49421515b32acb086c6e310deed5f3f467397f2e496b902f398197b0ee4bcbba486b3b59664b266bbbf6b0e89ef025ee74ec5bce82088d7d8c79858d16e7041b8a706fce5eda4eed25882bdc655ea2fb5c514346383d1b4c75702c0342072c81cf42fbd8337fb22b730d361de709d6a7f68b0414ac573131bc6fea3e9c838e133b9d432266dcb14c71fc5f3963963cface354241e3fd34465b3b3f475756838071753c5e0837ea91c70d1366fcb12911ab8741b4bb985838e557439dac18f372b0178204f0b0ec52ad4b46f921709ddc5219f4ddf25b5f44548199baf0d9306aecccb9668ee4a302a078f90b8f415f975d04736c88b33c66b62f52fa9e8a0d926e1c6d70accaca964caba73a0b8dcbb09a151211ae9103ad289e76eb3266e1d6000a10835a62f2f8a65f9907542e683abd0e6b99e6fa964c2190fa3f3a3421b539f75f6dee546525abeb9e65fe2ec08b95fe319f63ce4e3dfbb5bf6729c069c4cb326a1bfd1639b5a963a9be3539410da64e2bda94aabad0a18a132ee2130508eabba9fa0e630d3778c5a560d6b620cfa4d9aa3d03f23c83a3272b31abb6bcc93a98b5651ef6294045d0834621eacddb247fddf0c179a473878ed833aab87c7e9b90cff917215d91baa79e62473143b05234b2185ddc17f6914632da0c8fc62aad56a7184420d2a263c0650d3921de8a865066cf407936ac352711a96e8c1b4c42396511c3aa52b47a32e2d2bca256fa1fe441cb8272d4a51abd889a785139f82f01aaae7161ff701ea07b7329c8a54cb1314b92eb57fc8240093d409d5f9a312f103c6a4345320377196ea18deed0df0856b60b0b68b79e88b059b02d97438000d45ece27d26e7e9e9b752a6fb0e9a8eeb74918c00253b3656b7929f1817f87e070940afb1231e4a4b6fae009a0df1663d6618baf7e240ee4455ed747016387d98005a229dd4a4324745e5f0b6af17e9481cf3911536945647cdc4e6db4f186101abb31efe3e42a109761dd5a0377f30bd4f14e6bab8034b04fa3db2a7b791bf9619f9ca6e2199dd0c1348ec65f0d2f48180619d1b2fff8ac68af32ec717583f4c2f52bfdd19b9c358fca51e1867def482e6d7dac2add48cc9517d7c157b06da0ec713d99c1423d7fc40cfdca5a679f1d1841a8d306793c98307eadcff9075c4e8dae975e4fb7d4805f3bc7c5a22d9fcfd69f01b438b08aa1bb977d6c214233d7d33a85fb736335882f9397f3b5ee0cb1fc68414dcdd222476211d6cf3c820a65a092f540054c802e85c85124e33242ffb18c17d7d80f500393b730fa7a09c3a0be903f8a1edb3abc0e210f647a9a6a0c675f085db6b90ce8b3cdc7edc4aeadc6365d23ce5e137c48bed5bd35c9c19eecf88d186a030cd3be33060659022bf9d3b598cae34ffae9707dbf97a550cd628fe9facb3cfe69d0a59b9146498ec3701ddceadd77151ea9a27aba072bdc242fb87a65d122e7225f0363ebe1a0265ccce4b585987d75583837972ee0bc6174233d6886dd06976e6c4ba3880bc0a2b68476f1103781f0720f6972b55d667e48c6c570d8587206dbc6b9268819e50cb1e7724748bccbea1db014095eb5f73be8060b400a4373654df6157800a9c22fbeb9db3c32dad1c8281269d7c7f54b05883d919a269a8a91312dc776c8ac323776beecf2a7e5c2ffed0f9f02857057b2cef87190ed893f79cd10646fe1e40dcc5cc8209d927f9b6b3651e4fb6ba34d72346554a3417c01f73ea006ec35a3a1620dddbfb47a77f4d96e8b12a1bf55714cf33c6d90aa9550f898dc48c8651eabb39d235a5c563431ba7096bdb0f3bec06028ab1db7a20707133cd64932e0545abf82e306768c0d67a19e8444f5752eb694974455a66cb63f816aac420a9d104e1a88f5bc34e3e9f0a2cb16d7814485e2e004d695eb066e07a927da878313868f0876572382ecaa105a9ede6d3d8b2261067cbab5ba23c8e8e13839f35773eaf6c2c00d27aff7d660e4809de427fb45076d090eae8064bc8d41d0f0c2445f8d2b2c39b838caf26612a84a4a209dc939f24c709860b1348daa75f200d32c22a07d5bc5505d7274fa382752bde48012b2835080210efb0dd52f8567b3e62b3938fd7aff113ea0ea9dce981bf2f0c78d86915f6960e6b9c23258a4e0fd143a45af295069ca5aa875b205189e5df6016f235844b63f644868bf858eebc12a432d62d0ceb675e526def90a2efe44516d71e33db4302905b475f9d20fc7a6b8e893c85027b81c0d5719c2f5ffcd0cc5104b8b90a76d7537b366892bf300d7ac085f8cae4d163e063a858faf986219295fb9164091770cda519327ece620de38531ce25d59dff76ed89bd45ac22b0df7ac4530b7ffdc81eef0a3072fe63711f031bac76d2e53af69edf9424283990b749258a868c95009e715aebd1069708c859ab1348c0cba470ec414a5e5610972b46bcbc6ce23dda4aacda241de41de2ac039c904677e8aa446a316d7b61119b7471ecccd50e6b45a2990e00eba506cca50bcc7a4ee9388ff5965f1845112a14879d1fe764ecebd683564a9f38c93c17dd24db1adb7e38c632a308bebe29dfdfaf04eb7cd5ca56183062363417788a05e673c51a533797252d10b19c2c0fcf12f0a2e174a5ef07dd10065bd642cf1a94d85dc6a3933c073a38d41afd0027787a2bc4dba0f185dae6a89a77a7018c73c743999a5785195878f8aa84db27c3ac6310b77983826aeab406bf243e407f2f1407949f11f8513c994dd00d0a2be343b9db87625acf429f004d705f04631951c52c43bc1486297665fa935cb3747cfa20da853060e75abaf5628c29e678d1096d9f3ae53389d39df4b0814ea03db20222000a6ebc62ec74b8011dad677d2d61108ec20a2dc0890b9ab0c2bc85e64606b09f57cc786aae5a6e486df6a20abbd083b2e7a714158284477099c74a2ecb714a23f1d3e1ff301c03e202ecb12c3058dc9ff6a84a49b799013768a9a6bc25c640303ccd785681e94ea4eeae385abdda919a7460ad57762404537afcc01b7b128f9e4a444d24d236b3fccfdfc8b64f9a7c7bedd350ed2e1efa8c92f7af72fc56badae58a86905e236ff2568bd045f8edf311a072db08cc154082f804053d03a87b81d9e938398718c285e9af0a0526893a0b0e04abc9cabc84d2cd16845c1921a1a80e5cf645fa5e43964261aca91cc845b606268ab296e3ac9f80b1c3fec454bf32f7669f33378594526c9c3b02cf12aff7d42fe04258cbc988da908a995a72118cd94db8cdbbc79350d019cf708024961b09709cd908c1e96d3ab61bc88f3d15a0e1f75d0c17028fd04025aaaf1efd524f96805fb1581f3860acf5212b139e3864c8ed1bd74927176510f9165d3b4ce902f2f83f8b26da41c864296161902f7e8699ccc0e6d21cbd1eadb635164d3749cbd6be884e4f3a38768f0416bd18d31165db2e53b80337d49666a78ac5dee9ca2a62d8eb461a1946a701fea984f6b1ad18de912160c7b67aa670559ffd80041d1cd172cd684c1951547b3d52a5d51af394d5ca88ea0cead32de2e7dade8b4aaceec62147863e6da3ea30fb872ecdcc52670136e7ffc81dc118bba02d97b4987fc2659a5e903158578d1404a2e35ba20208669dcfddfe954ea7b4f92d52d2f0ac1b5e0332cab02feb8440f0c3560b46439330f0f0f0f0f0f0f8f39c684d4d6da21909a924c124af9319c37644a29c99464df8d90644158f81769c31fede08d5f90810d0cf80b430c793809955490492f040f875331f8a664b102dc8174da95d62aaa49c80e5acc1353c2448c741d342932fda611ed75311d5e4d33ea5dd133640ea4da38a771715eb3298783105679455d88110a1007f3592e5196a6255f0038902de9492aa52eb92ebf81b0a167956e5b2337d429315dea36394a8a6d3877f96611ee351b1615e49fc80caae5351c539ecd05a196e32535d4751b4cee34142f315de38e864392d1e3e3f7caee3467c8c7c46286c2479fa95419ae5221eae575a34a2703f2548685a4b6f55dc7f05852a3421383b17c6448d2730f110b433298756be8c0b024a1c167b4c517fd17921572f3870e4b79572f586e31cce6126ad38563dc1a2d1b2552eba870e15a97f3dd1a992ab285362e6db75be6d40a6aa15029645a76692a0ba7b5ac22336d8605634b645d4cda35ba7a85c34e9c7ca2d2b2c229051366ea42a40805a8422ac5fa152926b13c2a904c2d898ed1bd0cd3148e794662d8440b31a85f0ac7487aff4d371f859388b98ab0e81692daa170dc594d2721e909a7d331f78d1ad37d899c709013d205fb0b42c5899b70aaa0cae24beaaaa0629870ce1161a5cd334b38e9dc6cb2e4c5574f56099a901b6385f3dd24e19827c8163dd944c229e697debdd0c917c7231ced64c82db55fa77e239c6561f64f45386daec969d2fee2c44284f3f96e89a07a86411b0a30044baa9cbb8a423808cb3e2193fcaaff8f0a0508821bad2aed4764d1970284d45ff43d794129fff50705cd72dbf88098e566439e9cd0bef7206171c22e4b0c4958001ea04189d2b72c3146b983ff46bbe868d917e9c0603392b499834e74e9a9ce2493e41d07c6c971016e704c4b79dbb28d0a600345cd8a88b597e6ddab05222ac4ed8a1647d92c257f24ceb6cdb348c47c9dadff75aa65591c54b8e6145d9b581c73c55f103329674a5a589cf436a48a9e2276a4fb0a654b99cae70a4497b294717525cedd8aa375caacd6f62529272b0e419d48924bb88add94960c25830c125520fc94491b35f1236fa9386bb434fa7726f60419a8e86254f4fe267fef14bf6be4f0bcceca8c9bc29a0de1235808517e538ad3a490c9e42d4f8a424cb2efb423bce44771b61efd96b19176f22e8a43f4b5ba3fe115b7e4a13867300b41a5b89aa937284e2a8a65b5d1e6965b7fe22ceb1567e6675450224f1c456dfaf27f3b719c6842933ea55a9a623871aa56f13849d1acd4bc89734cfaf7d195cd829a385804bd7651eccf429389f35fb0fa4b5d31a4a4c54495172a2b5cc6185fe2385a52b288ff88955e4b989410e2be249538cba8481a944495ac494a1c244dea9e24e7492062d6cbe9e5886fad24ce9821a810f248b0aa6a13446320611499a26a953eab1e718a1a9624e6d511a69090e4eede88d3659f5841882fd527230e2aed0499a153375bb8887ff6cfc28c7e47122922f91022250b9361ee4dc4a9c4dfacd7cfafbf82886365887b325888c8213ac431474c5a3d9145a9ce10f748b4a094e94ca3ce42144c8abce815429ca297dcf8c610376277436b1084133b972cbdee8b6fa4c2602f4e86208e5bc1cb4547ae0d83bd386c828c409c3393dacd8d18ec4d409cc4c45c46e9ea492dfde1107ca4c7fbe473dbda0fe730a5e316832635651fce7b7731a83c134658880f47f1526f17ebe667ea1e4e6ad4db64963535b51ecea5646c6cc49987d3fae5f291e9938107c3b45582a49060b9c349f3d465ba89bfc1e47638e88be239d7194d556da3e420a30ee74b41b72296a94977d520830e275dca4583daae2c0132e670101517564aa47c6ff10f5c608b94038cf60ec8e124d2694a21c6b628496b519011876334dfaeecfae37d9d7f7cb40e1c5ec0e17032ee2a5f628e742a5db000038902fa86834a7b9b8949d84c2c3bb0c3254081076cb1c5072ea023078e084841861bce7edee7a6f3b7e118d64de628f9a7b2335f90c186835ea650a5b69f5a6d2a41c61a4e3275c86c72535f2e4d861a4e71a5a934c609f12d54c608196938a6e6d2b96d4b025b3ce06cf1802d20808693d490d338bab933a66738c8ef0b7a92e5e593918f0f2ffa05fb05185e780146172ac830c3f12b3676978798a8de156494e194f27f57dc8ca334a8c9701e7da57e4958cc71221f1f5d903186a346d4d3be8911c3494eff6e583f35273361389d925916d6f54f7426030ce750ab23f4fcd2ac7d36aa0c32be704a17646dce74aea2688620c30bc7c93dd173ad429031eac26135263112f34406174e3d614355b4c4939174432b6520630bc7a87979a22ade454b18385c506020430bc798986c17f8175eb704195938e5d97fcd0ed98c195e24c8c0c2d9b448b8f8a5da3f4969041957386fdc97521f7135e26a85936baf88242e3aa4955538e9ef4a936f5e116450e1945c523e131f1b4338a770ca9b26d4e80d1d2ba9094186144eab954ec498771d5138cc9be504fbd2ea19430c0832a070d29ded946862f303194f38c5dcb45851f2ad76eaa20b1c2a70c249ef45fe6bda0619e3261ccd65f449de4cbacd9a810c261c4292ab143a5a9964b484c38e52bda04a1fc850c229769c0857d55dc97249389bf4be9ca59b45cc031948388b6a665cbe984a56e408e74c4988a0d515c7f6d2810c231cc49514a5f72e1d4538954cfa32cd62eab8fa86968d1d8e02229cb4ef6ba553dda1973184734c8a8dd1c2e5ca6c84708c72db173ce48b340867cbcf9882f69b989064389001849388d147d9049527b493f18383aee8253f72694657860f4e7a262e59055f13056820a307288307a7982b8910265d193b388813763257969873843274705013f4dd7f97fe55282307a724bcaccc43290307e7d96ce30db591634718048c1c89326e704c933a162ed7ae6f1205326c6062d4424d1083162c481c316691c8d0933974793164112316674d32a638a1b1fcd23a581c5e6373c4143b2b950721c62b4e5f6622379e737e22571c4f5cd6dfd36a396432462b8ee619b4964c4177aecf8a93522656a7adfac429ade2dc7fc2d25e6f551ce4c968d15915724f3815c79cbc29a717838a830c4b39a2e8f414a716714ba364e9b6a598e2f035f2275ff929b34a294e16d765448a61d7f4a438880b62c4bb3d8a73dfbd659e18665264a238a99cc82da9be7e55c508c5295494f81b82be0023c7dbb8a18305619032314071146d97f9a4297de298ec644e3a19267bac4988e189e359c87c62233fa4de9d3889695c1022069162843871f84b9bec3f7fa5a38cb1097d530411f484fd2e1143132751aa7d4c6edcf102dff105189d758d88918963369f0dd3287327dd189838ff28df924d99474cee86960d3076d8d0408c4b9c6ae38d66b81853347f5f8861897367b4d269d2ea57f42646250e6e722eab2fba536b4a9c6b4ceacaf96685189338551052c7437f74e6599238a6aab244e268fe5a3bb252dd5f4a0d312071d04d2f1b1233abe4f211c7204dab8c90bc3aa3230e735e71ae26d48853574c3e096230e2a4e75531699ab60b3116519c6b3b6328e2e03a59cbd4c46439520290831889388b8e6779ed8c08a52eb08881886385944bb48f90df78c0160fd8e20139fc46ef600c6cf1802d1a10818f0f1bc80679458c431ce3fb24cb35b1c3521ac31007b554a6e49f59888310c23486f813e2ebef181fd95c8c419cfa92e6923795076c4134b0c503b62019d8e2015b100c6cf1802dc805b678c016640e3104718c669623a2f54a5e550371f84b32d68db290100310a7a49d235436863ded1721c61f4e15724d8af04fd397ce01822d1eb0851662f8e134b96448f9fa364f3a3f3eb462f4e17425b49ce9cf75931846c4e0c321f904493222e94a97f522c61e0ee2ae232717fd2b67f470c8975a4972996b6e350f0769552a24cb0c69b1df7a410c3cbc6e996222ed2a487b428c3b9ccd4af66d84f3102b9f8e187638c436ad9bed4d83d24b8e1875388d3ad72d71e297217a43bb88410753e3fbe4d6236ea4f0ec0731e670301d21d5e90932e59637b40c0662c8e1bc1b34cded65c6caa85a20461c8eb5f1e7cccf4d26c9e660efa24f0231e070d60c22e3d76196fcbca175b5c50724b04599186f38b84c6c7d91ddda93729527861bce124c29d53f2af79f260d31da7096a4d634d6a898f8a33fc460c3d95e4be586af247ecb186b38ee86952072f9c6968a9d21861a0e32ec2a776388a966a7e1f0bd12377da4d37b1e1a4ed972373ec7186738954a12b73463105e6a0c339c5c84f20dd73446198eb12fe526f764386ecc3a39b44596901fc3b9f267093be5179b8be1a031ff224f0ab12a0fc3412e84cc23abbaad048683129a7495e6568c610de77d450ab96059250f4a1c93d2b3dcdb2023c8cd631295e6ee746f4b561e1e514d36698a3c62feb3ba808724ce1f3265baaca5b4da7001e7281bf8f87001e7988147240e7abd2d7596c893a607244e1d2321995026e22c1674c121481b608f471c5d2da8fd8ef817a7b9a145828f8f127838e2203f4d67be6b50972b0b3cf0f181430561e8c88247230e236452a7436b4544ea0ee0c188f38698f7910da337bbd5d12a0803055fe058d691e316718ed199f462cc56df53d58e2f2840030f4528a9ba2aa59458b1d4346b93f29a5341366c7824e22076b762b7f2049f11513e8ac7218e41581227c14ca901c43c0c71d69130ae236251737e430b8c2f6c98198f429c26450a25224fd4823872ecb0414c064860830b0f421c64ca23629fcb8c856c031e603b5c47043c0671c8a2d296fa8d9e15b50ad80b63000f419c35774491667f2737a78047208ec1eb5de45367b7321e80387897ebba6cb5aec53cfe704ab167399af42e5bca0e0f3f1c83945d9112e2e9cf5a87471f4e263bc44dc636ae890fa7d4244484a8cc1e4eb337c15ecc5bd328f5700c29fff2a68c7938bd99ea7f08a5364a160f073922aa79053115420c041400c1c7c78e2f70b0e0e363c717385850bc60c1171e060c76a8c71dd20ee95187f3c95cdb0230767c41010f3a9c465f69d8a442ed9ece630ea4ce430e1e7138a85e9e141f390f389c4704752a7a376f38c41b51926a52653a150f371c62e7aa89d174e0d18663bf5c309db549589c0da7b518522a593ab424cb1ace972d8a85470e19e3656ee0a1866392694b58676d6baa74181c78a4e1bcd133e59c2f95cb180dc7d4ffaec94a4aead89ce1dc1d2a3494bce83066380697dcfae29145a8b70c07dd1b93714925c3f1c4de579a74aa47c4630ce75bef8d30ee2b4a4b311c5289532a8cac5829a14718ce3a56997b54ed0186c376c952a72567636fbe70982c4aa531592a0465218287174ea754eabe92312b29df85f3052933174e49668cb1905479ac650ba75379ab52e1d2c2c13ddb3229112ff6ccc2692e64eaff8875b190207860e178f1925c05bcc3ca8c031e5738fe848fa4747c6d68d6040f2b9c4ccedb8f0551154e2652f0921063527a642a9c3e725969b578db78a7707a7bdd88666a829aa8144e6341d4775ca248ac44e1205bb76ff795f2a25f7058f080c2692f7f5ae94a330b79c221fae8882ce9f742dca0e0e18493127963b94d08cb5eda327834e19826f9d4dc59565b9b09673b8f13215746068f251c77ecafb3d2624934957032993453742d5a1099249ce4a44c377dba73f38884735a5e0c7e1fe19854fded8aeae1e0618453ba18df2c25d1202eb311068f221cb24fd0763f5a73bb66060f221c26688e65ab90c710cee7a73b43beb31483ed2184b3cc89b4d974db2ba58d0d2b7804e168256b824cb2bf00c30b2fc078c0211781f5c10308873cf6e9f396d6523cbf000347cdc1e307e7d55041a890b32e761f9cf3f2088ba09dab750f0eaa257f58bacfbfc98373984c7631ee8a06eb77708e206c4fe6af8353e5f64c16d61c1c4ee97c956caea6e88183f3a4f07b6162f84da2c70d0ea276d729522e95e81e3638a6c6526bf12cbd3cafc541d85889fcf9ffa5725a1c3624f99c9c98894c9ac539aeebe26b4c92c5c96a4566b0d2904432c5e2947f64fd7246539b048b53299b4b4ffb15078b103437eb5864d1156753b115532bdd8af3d9c8d4991483a9a45971fa9a2822687e15c70c4a66c92575c48954718e53751a265608254ec5e9f462aa78763a9245c569dbe2c2c8c913d4884e7112257c2be34389ef90294e6983be1407b519228df0f57b1393a2d469eb1bba8fe278a12bab88c888e298e226496651138ac3a6bc1125084b212f288ec9e59246523f71b66cb78b116b4984eb8983ee9ef4db60274e52349be995b79193e5c4c152881049d398108b6ee27c79f37efe9a4056ca1ecac4216dfbff5c8989a3261d624b26291293f012e70a12b78248d012c758328ed4f82e1b7e254ea7924bda9e85595d28714cb71d723f4bf9b6651287b4b15dfc92c461631c5569cd32424a89c4c12fd826bd9acdb687c4e1bb63d4fe6e9e8e1f41bc8941b9f6788e5853372f766dc461f4c24e6f54d2da33e2e0b3b1cad2a6dc978b38e8cd939151d16c838a38c973bb4b1a34a5c42c11073d277e2fd924661811a7b4d21bf95e1de27c2f31fdc6cb10c7daca1bb137970a932ac459675e37a6b4dfeb13e2389ab5b11b1dc4492ddec90a7dc1a4480c296608e2b451635698fc06e2a42f057fb5d11121df026600e2a8f1a7f9d45de9c8ff0fa6de9c4dac20e387a3a5dcdbc417a91bda3e9cbbfd54fb2557b537f9705241ae65936d49d78f7b388876d1e722a209abc80c3d1c7ee24af23f5922a5f370ce8ba55c6210bba74b33f07088b1b49ae55ed55bfe0e33ec608aa694868b4937a30e27218488ee0fa5197438e957cdf7e61c4ea952c7dbec9f8eee6b891972388e88b54b29d4586a461c0e675d36e1445288dcc3e1b0513d4e86e47a492550cc78c341095dfbb6ae6132253931c30da7e05d628487ecfab436d081ddc48c369ce62a288ffc619a4286d987196c38eebe464ca65294b13ad9d8e1c52b0cb88b3074e048ba33d670cc1242e56dd2666ba91a66a8e1f85f622666cdce48c3c94fb78c2c15e4c20c349c644c9bf37e62dbd32486196738a6d5d1911de373299ae120528acb7b56665a2633ca70eabc4a418acec9708897336867108b71d9180e4959583e115b5c2b258693787ee8fb593b150de4f01d2cd0c0161fb8c0161d701d39bc053820f01ac8e13776e0386e98118663cc64a32fe85df74bc1704896c1f44ab85849fa5f38484d71b9bf47a49d7b4298e18583fc3a15472e2c871944cd1fea4c65e8008086195c389f4ad64d69bcbac28c2d9c7fd3cb28b51e32de450b47d1dc4b8d16cc546d569891854318716215434ce8cd60e1a492c914e2894849857a8553ba52b94e8dccb0c241b8c85acb4c6046154e2567358f45b77c397f2530830a87d1f2e1d91763dffb3682195340b9fa6b04130433a4700a4177dba4f770db90edc08c289c424c5349527231a5cd1b5a5038c9fd4b96736366dbeb8c271c948a50b7ca9722ed84538a4185fecb3e2ab67b8e194d386bde33adddd3d15c99c184434a51e267d57533ef4b384bce97a8512da78ed286b7a00b3074780efbc00c251cf69288506a22a8d4ec0d2db6e13bc068815d604612ce19f2cbadbd3a36db1948d0194730798a6db6c828bfd20c239c46756b04e5f2fda2bfa11586172c40a402338a402c5113be244295ad4bbc86cb99326308267da1477ca5a9d809660881949a2e2d2897d8cd08c25143cce737a41083484ac20c209c4653d2db2072b566ff83532c154ceb68f6e9cb7d7050b2b1432ba67b70aacbbea4d9e7c15194943f93fd5a51e11d9c625ed15539e1f793d3c131fc05adec0ca5379e83630c62bfc7fa9f8183b3f76d9214a2267d313fe3062715163bd636db429f66d8e02c5a76c2478ecead512d0ef71ef9947b4c8b2a83d7c83917f76671ea493e7749999ecbcbe2906b7c6383f60f538ac549e9141122bcf42fc4c0e22062ace4f6842cf3f615c73832d8e5ec72ff93b9e278294a2cf7ad38cee6e62b3d71b3865971ca11f9974bfaabe0ec27d7e4d39b72559c4ee869d1d7669a574cc5168469d20b9bb6a48b8ad35ceaf8db540bbbfb294e39418e246b0b15456e8ac47e54eb529c259c92d9fb9d93325254227a97a75a1ac549b30851c99aa56d2551281a4a6b6da45d3d14079942c4d0ed3528ce5d17a336f36624ab3ff1850278e2904e36e553a9eec4712fba75aacb0921d29ce0f5beea36dec4594b5c268b3651e46c122880268e415b298dab36733967e258697d9547a5feea061347531a345c8875eea3bd441973222d86a690b3c441c51e8d717d5e19abc479e5bead4283669b2c258e992d8b95d9a69a3a8963d4f8953ca48ca44e257134d525d4c8142012a794b535d9bfa97c0d09620c9f6c7ab2c4d8235057a63b33a538bddd11c846505ad9928dd2ba11874d9578963a94b8301971fa92615a73b388a3eda8bad8674aab878a48c4f92aed9b85b820e2702e49b9a97039c429c43625ac4d63a8ae18e2769315e259c87b3252888352d99d21281d210a3088633e99bbb377bfff9d20625080401cc46fca7866f9debc03c4f1436f9cbaa46dceb53f9cde4663332bf383b2a7b4c910b4ebc341a5537216eb166a2c3e58daaadfc341c8107454ba779bac1ece2234891c375a6a93017578556b344b65e9953b35259154a95dda10873c226925fbb5146a17e294a2994e8d572a4fe90871cac9fb15c3a81b3088535216cff28b97ae7c21411cff828bd808a24452321c5e04e2d8bf313ee6c44d96500310a7ca197beb42bac61f4eca34529a5b9e081b6f68b500473a0898b532250335fc70ce9c793409b54b6993fa7090a464d0ab9274ff6df8704ad2472995fda76ec13d1c248cd5c6541b6a6ad3c3a6319967c54a2924e513dd67656741c835f2706c11b578263a7f7fae8187639aaa48e262bd93cc1a77388a68266fb9cc16410c410d3b1cbfff35b62c4ccae5e34307312ad4a8c3219b6db7b946da94b9061d0e79bf940aa75a8d391c56d77ed3424ef59fe4408c16596316af9452cbc33dc3ede8fb76c66ac4e1bc19fc72436b773c183a4aa2f10d1d990112d8a81a7038080b7639bfcb4218708e1c8c35de8068b6884948b9adba26c6755960956347186fa8e1865334c916d465380921a40da76425cac4a6ab94ffd970d64a3d49bce5dabebc865308572a412368be6f6a38a99d89e97aa9fee46938f6cfa69044645ecb161a8e753aa6845d9f461139c3292cb3c93d75a9e26630406986f39f79aaeb843fef3087083287a71a6538bfe8c81a6593e1e4b1252cdae90bf1f6188e3332b8a69ef9eae5da43f0f1a159430ca73022b88736350ce73bb1a7dcd7cf4e48c0608830553b9fa32f1c6324fb8962a3b9feabe18544527196458a5fa30b855a659746f22a4ba92c7986d91b95215a0a430d2e1c434a13638ddc242466bd6dec68ceb1e3055b385e5a1212fc334f5b98981a5a386cc94c97a80d6b408d2c1c73569420a38db31a5838a8784be61a8237b4468d2b6c9ee2195d5d5dac4d2be34515b56955d3cc00096c60a08615cee6216a312c59868820a046158e56396a2ac624e35f860ae791999522d5c5cccf53389c6d66c89a3b556c2b410d291c3353748aaf06b54614ceb7ab1125fb9ee6586e68951a5038e4082b415b48b7908d27903d44d2e48d3f71c231ae694f8bb496a5ae2bc41a4d68410d26bca0c61218af8ef9fdd6f0bd8612486d6159cd2c658aa6de95e96cff26895d2309674b3b8b284ae7e459359070b24f8b143b3428bbbdc6114ee92eb21a4638890c2126f3b26412be1a4538aea5a9fd65d3a43daa4184b3e691155fc91a4378ec6e3462476a08c139a5b2a45021572308a7916c27f4bdaf018473a5532aab6aa5357e70123936996bcc76e0d081a305668b0f48c0868d8f0f1b1f1f94a8e183f3caba8949ca36839c30a0460f0e429a8aca79175dfd83b1434b2b508307e71895ef54907317a9bba1a503c752a0c60ece696a726eb22fb1d5b7b03e504307a692ddbe5699269b03adec5e3626a1ab5d1c7813a289a5e4dc54b9012716d14792be5fe0378891b2f10214e820356c609694b52297564b8a2fd1a5d25e57e46a718ab467b1aeb12742b438c64cd297662342539ec541c8243a31dec610ebcae26c314cdce5a496f24a2cce6642d3c6cb8c31291d2c4e7ab2d58dfd89aed32b8ea6d982a9ca7f1f1a291aae389dfa8d24f625c3d78a5388983744f4bc285967c5315f0a8fef33b1d9cc559c26559beee95e15278b5732f682affe4553713a71c95f63bd43f7888a63ca9af4470a276ed4e514872d95f073299dec8b86294e27d2d55964d791b8a1510ad4bb2484606d2d1ad52ebf7a5e4f8314e7d3af495978a996138fe2245f72b282981bfd4b14e7b690dd92d0cba24f0b83053bf4073442719221bc62e3824071926caea5f6d54f9cd7fa26cd47bc94157be2ec63af7a21749526b71307d3f43b2727cd024e1c368a9ed2772287b8b78953e51871c2648ae476ddd042c1173834b1dabfdbaeea9f89634831d4456e996b1163e2bc394e3493f0cad1f512e7dbccac4d1b4b1cb206bf90979d912a770f7cc00b30767cc13736f0f191c3559083bda8adc469e654c819922eb588a1c441bbce6abd5fbe723b89a37ecabb67a6bebc99240ee797dc57c7d2eeac9138e50c89f577eeafd984c4292cc9941717af4ee88f38289154e345539ad4d11105d5cd104a4e4c23ce159bd6c47cc988d3281d254f5e2f9d8817710aa74e7e5fe5679229459c740661a262ec2bbc823da09188536e68751795d3bb705b817b001167512a04a1d2ebc80d1a291d3abcbb016130068c27c30c90c046d23844c122a66c070e1d3842906387073e3e7474118617388c17340c71d018f4b5c95cded05a81eb28c4b9424a420419930c5b18ec858df485eba1418873a879b884bfedf7bb00a36d803188e3558ad739a607d010041a5d53d335b659d4f24a25c35dd3c23ee594341047ddd4ff3bf6858006208ec1676573944b1ced610668fce120aca2299926a40bfdfbe16022cfc5d68afeeb210abe00a38be5008d3e1cf2888818692399df8902dff1050e3e1cdbb737d64f68933173434bc78e1c1c46c9dfc32188c4ba4a9d95c22a667a38abc4d0a1ddad46e8d0176084f1022f18a09187c3e9c999b29769c35b37b4ba602f70b4a7c3c34973ecaa6e58a83c2a37b4aaca2a40e30e0765f98216959632c4b6c3f1368b18a1275782fe7538e9caae915b1b5b5b7c40021f1f9eced0a0c3394785b465ba177f39529ecc68cce1f47da696c35936572ec4358a6996c4a13e3fe999299adba183059d5b7c4002957060018d37b880861b90f62252266b56128d36ac6a9242709978293935b541830d4755bf1411cda3b186d3c9ec2b1a26613368d58068abc6d46e6ec92ab4ab2e090d6bd2cca24d230d07ada3d4e476c6447c1ca4d0700c52928e5fafc91454b791038c2aa47186d395fadeb0d1a7b25a98d873940f1a6638e8a493e1d6e1365ee0376c680e1a65385c9b308d6e6eaf5eebc8c161181c34c8709a3fdd2db15e2d47674305ee615c7d41630ca794efd344a869d93bf0f171838618ceb3572fa682fe5dbb6884e1682993349c6ac07094705f59e2e234be708a496edc0daa4e726f34bc70bab9905456ba3e15742f6874e1144b77b55aca9f4908d1e0c249840ddaa382ce328d7d81c32a87ebc8c11bb0f2640ea0b18583482c8b7147fb5c3e2d1cc36f297941b756c37b011a5938ad6e664b0aa51dea7d7c78faf8f094c375d0c0c2c95be6f2a8d39d13b2385e070b72d8d081634b47173876b0400134ae70ce947fe2853319aef2ef1068010d2b1c379dfab30c6a32e9530d6854212b1da28249c280c18e2b182c0c722c0d2a1c4e88916bea972f6aa7318593866fc9192cfd6629d190c2d9e6b2724cbe670c9146148eb71be2afef9daa590b04810614ce6a565a66d4c6d59d9f70ec2f292644ca90acab133091e3424c13ac581ac52464d1482132f5cd2c0909b20de0e802093498709c74c144e8502f3ba5259cb4759d091584947096242bd5b6ef77ed422309c7242126a9ffe5656642c2f1dc54e65fc4348e705c7ff90e899531d030c2e94feab76b5816b9df8d1d3b388c8f0f18ec601a4538087535712b6113060d221c3f833e25359b90d57b08872c979da794dd9ff44b0ae1f499b2e5a5bc662a668370cc5693b61694aaa88006100e7fd73a3e277429a0f183ea455cb60b30c0405dd0f0c14162cbd796a424634a6241179e230c5d1a3d38f9ebb8f68d8c23253776f006ca8d1d1c4681c10e2b3478709cdb782a4296b4201b06d0d8c12108896129a618579aa48393b0d7a0512b7a966a3ba09183c3b598ecffa4b4a34c9663870e0bd0c0c1219574fb8f18a5718363c910534e4c4b25b349c306e7f2f88cc984b616e7f4486b7feacb01868d2bad1cbe19f0a0852ad9d2244630d71892294b51d21bea450e3022f0f1e1450e301e081eb33826533163b8b69452aab238c8beb0cb5dcded7f2c4e3a5fe6c2050f162739952788b8cce315a70ca95c548a76c24bec8af3a974b31ded5ec137ad38f5b668bbac9854dec80a33b2ab5b4c29b666caa426a2c6a99a0db2598f551ce5829d9a9cfda1524615c79141baff5cd60c42f548c5418ceae94abd952435c5000f541c64d658aba4580e1cbc016f018e1d9c819a84c729d4145a8ac3ac2953f54f598d16dbf1050e3036905575a438aec69052d2979a29e85f60a31e055eac0e52c4631407b11a91822c959492bfc0d1054243c3431407db9e0b4b7af408c541f5c9b0c1c4dc28a1f500c571728614798da5ede24f9c523ad994254e902022cf919e38d98f8c7023255aa83c3a71d012b994ae7ab58b1b4e2cc982044ded6d667d32e515559267d34d1c3f35a414db0b516ee2a18993e653e962269d6bf22f28f8a2031f1fe90bced1011878e1050b20f071c3231307d53011d921fc5b528e6c7ce128d04a5f70073ae01e9838d964d92032861e973086528bd958e220b2a72c8bc935a1151c11f8f840c117393e3ed2179cc3a31227a638ffec768848a2521c2f8ed58b687a991191e220839e399529a6d1221ac5c9ce43e5b52aa16e43a238689fec8bbd4271783d15940c22ab061502c5e992a9e0ff2a1acd429f382519245fe8effc8b204f9c841a916b4b7af3fd9d388c7b984c4c7f2b13270ebf212f24c4483ea64d1c47c4eb5811d1ca90268e294d4e535127518232715a1151e269d83d8f3171ca783966263f43762f71b4a041738fd212a738bbccf09bafb4acc45983c7a595d7a04c8512c7be932677bb499cae74879e595efd4c128719affb4c5ac4c4227108faae6f26c59038ecbca68d1be1471c444cfdf33176de3be21c3ba336a36fc471537ec3a4e683117f9fecee52321f8b384accee1337882032c97c28e22c79722693af52a9643e1271cebfbc9479bfa406990f442c97f7f3bb3ec4414d8d6e8590528a6c88b368935af24a55a47021ceb2a9c93784c977318438a4131fb941e8b04c0771d0193c4b8a0471ee125935ce84ac950cc4c9ac92e53d1503888359ed9e58e50f8789a74c248d67c9981f8e299fcd6ac55651a93e9c44b959a48a8bc127860fa711e31354d9997c0fe711d277feeb7e33ae87735f8c14c4fcaa44290f279f57b7602ac2337838c56b3edb0ba9eaea3b1ccc4ca64ac93d34dd3b4e67aec3a92b85fc934b2ea94c87534d783f51f964baca1c4ec2cfef3a8395576ee57034b1294729a12926b5713826b5790dd96f2a4f160ea776dd2483ca1b4e7db14ae34fbe85bc1b4e316d53a269c819f2369c548e8e8dd9fac1862fc9728bd7a1351c6d54cf5e92ee2252c36184e86c49a7f1729c86738c86ea0b115e4c8386f35e9e60a71ec2fa331ccd2dc5fccbeb49d40cc75cdaf1af1a278365389d86889d5a922121ec4cf5fb3886637897deeebbeb2e86d37aa8ef058d1063c270f41ea16fd2453b81e1f0f2b7357e7d9afdc2b172c4f56beebce285536e95bc992ea414b12e9ccc747d9f0c17535e5c385f2e132a279a6549740bc73b5d3135befda185a3ea68a524ae7ab5e747160e1e79d4f2820ad1effcc0c251736d729999a435e7c7150e922cc5d45e7a59c4f96105e747b2a8cb9b2a9c6499d49e31a970dca4f67467ec8c993285d3459f9f778b14cee37aae1333cf4f5138a995da90b56aab86c25956528c29e59e701a37bf52573ae118cefa35954836e1bc2b97296b8895f567c2c94f285d565735ee124ee9db7446d7a86174251cbd7c5316bda64a474938add6ad4a6cbd8d1b241c57f3aec9cba632b24738a697dd58fada4b4c239c529e2431e9ae8b122cc261be34e46c50f91b221c466fd88eb3bedbca100ef25e1b6258fe8e0f8570debf10ee2c262b99201c2404e93a13f3bd0884d38824ddae3784bcfc0f0e37776af684852e7d709468595e2a6308a9ee811db1849c89310f0e9232c6edcb0ece996a463684ffb55407c72034a24b7035b9e7e0f02656367b4bfa18717052e9e2c814732aed3738dac59021638a21371f3638e9643311d4f74eadc5294fcc6d123b5a9c4544927e512bb338ce057929ae85e9cf8a2c8efa95c25c4a95581ce7674cf765cd2d72581c3c94ed099d41dde2af38a99084722fc97f93e48a7345be92db34aa82502b4ef6176398acba0f21569c3389127d4af8d9885671f65149ac6543ac95557138db4b39292615e7b3f81f16648c598a8a93245326612d4d9d75a738ebfe5aec57678a83786b9fdcde6dda97e2f0ba9a14a7546a3efaba228dd0284e39feb29cc688e298f49b9c3d14c710d933fc6a38e92e288e2aaa9b84a845487fe2dc22ab765f7be2f8225faf7a77e2e823a7c2aac8947e4e1cc4e4fd4d1f2392ac6ce2903cd5a2a44b9f234d9cd3fa946748be5a33719ed154693497f8ee30718c16a369a74b9c25690b27532c713653964579055dcd2a71ded95832a88c122711d29252f19fc4f94ff26bd2af501397c431a26592ba47e268deea323985c4b127c5b079841e71f8ae7422a5902a32471c93f2758b575282841b714a0df13de355bf31e2a0627b76e6f089d52ee2605be1f4ae24459022ce75b2af1944b0ec6a22ceea9373ed7c4f45c46135cf282d11a4890e71b8901846c889b6350d719e5c92e6e4a51c3d16e2e0e33b262369cb23210e3935cbb7ac9f58ca20ce25926564aafbee4e10c7d03c27c4b40ac421b8a6ae790588d3bc5b5f89d46726a93f9ceb828e6f08eaf6bf1f0e9b32c577d39a3a4a7d38769a4a9a7b21e5cc879357e4d98f91b8dd1e0eaa4685c83075976a3d1c75b265be8ff270d8cab00e0be3e154ca46bc88255709dfe11846dd89688c1d0ed9943453624252a9a9c331b8bc98480821c5950ea7d0a4c5375b3726e91c4ee2828cb490c4dc53399c648e2f7d79c3ae8e713856beb5f7060ec7f3f4ebd04b4aaee50d874db929e8664a22379c527bd8ad083fb7db704897dd4ddbdc5accd8708825f32b8c848b351c66bd725e4a951b5ac6025ca8e13c793b35894c3b354269385d5bce1422b7617915a0e1b0af22e3c814a2e30c27b998bb52fb8caa6a66386eca5db6e984f6d1ca70d05411c63c432e9dc908b820c3e93662d451758de1a011ebf4655913b113c329467e454a9541c77d26e0220c2711efd4c830290b01176038a4107afec2d1c28855e6897053ab178e71d6d9126335cdb43ab8e8c2314dcdd86c4674158b0b2e9c77337a9814918b2d1ce7c4d9ab67584dd9b8d0c2b1aeab7ebe7b349b908b2c1ccd4a59c85fac6b0862e1386a34a8c9fa0e29e152573856485a7f2ff4c40b3e1756389b8964af419890a2e92a9c4a7a69f650bd32497301175428c932614a5d9223635c4cc1982c68ccda1a31d85c48e1244a69ccd03e4931d91586171480810374e8e00d7ce0e3e3830a5c44e1687fa6f3e4e88d19291cff85021188800e76c1c787377f0ee3020a27b91ad3b9e9453ee114a6d9c4af85cf4afb8b71c2f1cd92886397ded03ac39163476982176080610305396cd81000174c38585cd7917e11308e005c2c217d81c3055fb060005c28c132212f7e2e8b48471761b017555c24a11089266a19c943c48694541ae9e0343bbc782e9070343bb55e2a92fb8fb68b2e7058e0e3c3065c1ce1a06e7721a410612dcd5a1fe0c208a7ed2da979dbbaad4c1d4538a630d5a99753229c376dc2f56cc85de22326022e8670780ba1c557cb4226025c08e1206a74df2a5782708822f4895429cc84481d2e80704cb5144b33f76b227c43eb07795e0a32bd6c7ab9f0c1c1c2b85f87c6dd51312e7a7032a5e36dded75ee560efa251025cf0e01462747dc92664cdec5cece064ee726d4145d120ee0dad924a012e74700abae9325287c6968b1c9c44c492efd6f80d2d1c1c93a6dfb4b10bba5774432bd16e709cec7f5fca2b9c88140abec081012e6c708ee46df12c555003356a71dad9202ec9976f68edef6001295a9c6b2e8993a675ebc0e14599408d591c5b4dc62eb2b23865a850262aff992e128b43cc90cf2f9c960465c1e2147287b6049949956c947bc541b89cf286d6590d571c27a8d93ca63795deb4e2203e2d47fd66cef8ff8696b26163870e306ed8f82287819160e0b011868e1aac38e82d19b4c69890a2e53556710ceaa569929d570402355471d0da3bff8abb462a8e6ef25fb4de5664773b500315a70c192f29f447cbf2539c6df5d24cb5925caaa6288b440b2e6e1adb5542f0d1963566cabe612ac52988ae2c49547643cb465ea0010ed0c0052490c949e19d78939ee1ed28ce1ac247a828db063544714ab2b277a68a23d48a6a23b986e25cf99298d11dc20146086c941735407192b9620c4a84bb58658d4f1cb3b24878bb78e25c21fa2cdb52cb54df89a3e435cd9c675ebf1f270ed7a55c6496c6487a13a7f44c72e4421e5d42d3c4b9f24991a849d34ab66a64e2287af49bd037223ef23ca88189939bd6496fdd2193f57a831a9738c6661251ba82b486250e21e4cd15e4d9e86b5e89c35529517a3c4d5aac3d87da28d691dab1063528715c3791446d526908f3240e51cf4dc6914b374a2a8963856ecc7e0dd1312d12a8755599ba68994c21fdb24c522f41e26c2ac7e4ebb29032ff6074e1818f0f1d3bc0e842c7eaa0c6230e1e9af596a2dd9a501d7136954f29d5a4469cda9258516357a73ac30892a90617cf20c94c4bd42a9a12f9f32de2344135e2c90d49546baa65a8a188634dc8593b264cc4b1d4cbc934f3352b39220ec2260599fcd721b6048c6ba864ed2563f2602c140945e270301c0a914e57b3130800183c200d854291503051855d1f1480025f341e38322c1a201c141016148787a160200c060943613018100803426170301c5a8866241f7c84c2eff0ec64423b28a11144a2eb0721c0ecd1103d5a23dec3cbe72d3d5e8ee861ed616b3a03c074a7fa908f61bd21fd0cfb6f941d155434ab9d65b1ac88b1c16ab6429e82cae3bc5a35c694ae55334c495a5eb22194f1398793924c676b3b4853f5cd7dc9ddf05b04b0f96ea8a4a79802a305b522ec12e47b464611e8e6bf719bbf1a7c33bc1d0d65822b53a6fd5d80ef250332b0ef1dbfcbb69e66d2871476122162a5f3d243ac29cac672b0c070399b9859cce10cd63d33fe12bde17f2ada58f363f52748ec7223009fc688349b889476249ef41fb8e17ca520308e14678c19e6c377500547ee4967928bdc05f2d1b1db8787f54ec0aadfd063f29f4af3e6c405635350154b923b56bae8a7a75d635647a339111f5d47ece83bf0c7bc81985a8c4f42807c2449a334519a92e81e9ef879adeb8166cb51a9a70dcd69ed0cbebbf43395fe86a77cd522f83130d68dcc64edf053de009415af9776fc1ca1a3ea501db2396c54a9fa62cf0959a2a1c8cb3467e3aa0616111bf1c181f568f51c834f294116d88c7ad8d7ba38446ae5b1cf42e5c9e4734358abb7e62012833ecb1b8bc867e2744afa03beb16a467c2f2b4b94f5a929a6517f26ea1499cb78847077bf7d0abcea7f2a12957da99b74852b8f3b1356d75a3f72a5f19a448cd244bbc1a14412d61366f0244007aba70ccf0291af8ade0edc47c0acfb5a75bb5972b87f22fe9472d47b557817915e7c4285cf39af758249c5b0f704de8477f25ebdf4f2cc3cba0ed17576aafda148125e4d99c27beeebe04a9fabb4ed62c279a6d9518e42b4905ca376152e8b5fdb52865702d6a8c75955ad1921f8657da01d5a3c44393ece33039a5dddc9857237da40e71a6cc85b847b9c4d0f82d130f2769105cabc4677fb2b2f27eef20e7a6a0e685c2441919fc3c9987b0729b0f6f1d936aede758c887128fb08029c8df7de2bac2821ef1ce0c2d6c60b23df0941e60989e5f74e794d4d7798a58697c57db37d7da48a0090057969a6ab6af63e601faf5e9db67e1546902de75cc885f87e4f2f3c1b25880b522edcd7c539a6941e7eaeaf85a9a025ed8f9343f17223e137703b4f30fb7fc713a3e6d46ee894cdc6767ff5e3dd393c06e6e2413db0c3b5f4a3ffe3f0b597891f8b9bf2a9480940e55a1d369ec42d0a7b6032b0646021f9052aaecfeb24f02fd4016b8d39a659181f91ea209251f363468fc81745c9d4abfd88c3e526cbdae55279c722f569cd29d68bd0493ec4775e9ef617ab58df8d2c6a0492833ccd4c84b9d0649106561bfda2d0d6f93bf88c4e6e5a5388f49d872ae609f71941b73974d339bef57a8d5a81cdb901b480522b235299af35574ff966fb535ab2d817ba7e88b8bc2dc189148675b5782c0dbb1b0181f15e3798665dd0a7c398f707670818463cc2ed4000364eba0daca5c93774d6a78024637d797f2d5262d684801a8b3762202933ac28b2376e3c30c97589b40e9f3360466f429ebe6fbd9ff4f8685d05b0ef32122ba2098f2112cf79b79ef48be3d83f0d66e125d398112c32706584d8a90b9d7d0b871f2902445714ede5f9aca26460d3efe60944d1d86c346a9d306910965a82227a149c79b1cda576d540bf47b64800d80abeaef003928baffdd2ddc3c41c35257e63264ea125a6098b0998e17a169176734f6bc2936c215512f863b71391f9561e4d8d4013e9c662b338196bd17a90736dc2704ec2fad42b72551dc08cddde5c4897807c981b164874c42aca5643deecb62622205bd02b895e9a6c4413552a4b93f089621a42f5cc7b106b333e097e094a741463a18353e536b496132b281de908013f8d100fc39941498353dd822a849eeb2bb617d1c2a68e3ad0b05ccf453c9056af1746d7f0405f00e7581b3ed76687f5aae263dfc2f99125baba8e5ba99037c77ad695e47d9b41f83f3e9db3adb6eca8e691636374bc8d7ee34018e6a06ac97ded5e939a62ccdc06d32e8a12ca87dda4e8c6a626292c5aacca35687aa62a021bd81db77a8d2767ae38b1366656b014b0362a2b2d82ee39d17c049a10d6b93b3bd536b89e98fb4ddc027468bfc371781b32d6b59c86114c517abcafd9a879fe2a48ffc2302fa9d3c393e2eef6672c252e73c380e7143b97972b22977819f9911d7e414fffa8570c458161ed7ab40210ddd4211da9ba46740fed8057f01d6032617e759566b44dd27a6ccc7946a15f8ff041fba785cda49e8badee9dfddc1800d5f0facb0e2a700614c67b268132147619c224a6b0049ef17c2d2b70821366b98feea22767e9e5cfad52420bb28e28cbd0c69acedf324cc2ce08af0926c1301bf15e07e0d8f25ad802e811f47f1d666018a71918b8448b61e6cdb3705ab5d703cda0b6efd894137f3296771469ca92ff8643e3657280ce3dd26d07a1884995b56b8b37054fb8ef3001e5d98f9349347d781c8062a711a896c7b9021a753b29341d24fd87aa7a2ad4c75c8aad36c870e4fb2f28152d5f912b4907e73cd9fd9ea76aca441a597d305a14a8c60e35d825627abfb8837d4b94e6c5f4004bd99efb3acc89965e93d4c4d454b9335b0b88039869f79c490f45f0098e208a08b83efd87182b54acfee3c01f0cf81e0f3a916bc2ab7dfdd840e1f111e3852a2ab5d8765225a04690d565e5357dc581856b0aabe5bee10f0af4e709d5f6ce9af4192059e6d0ddefd724962f4a411cddfe9ccb2faf16d3825aa92a115fad1805d9c9bd06bd3e71c1eb1ff2cd2b638385a741850ba8e19c4ca98607ba1c83a0c7640158a1179e6138fdb1243f81a8a8fb3f00f00cf4391058c7a170a604a6b021335c38ed50d762eb07952ed60649b836ebf808c04973051e5a45cce2aca534cb437040a8fc81d4ce8e74d266a4970cccea2415db8a35a026ae283dff46171e5ce889509a68975211e75990782bbdd0c53bc20108eac21a288374a9960ae502289112554315deaa357b50fbac9bae2a3aeecba95730ccd6e075e3ec9c9e33cb9f6a41321c8d3fe69c8d726fbc0cbd66594265842bd650f521ef71c8051a8c104e418860812b1f0b0e97ab21b092153b7c4e8b7711e6aaf0786e50cab891a34983b006be967e4ef8338e1e35671baa1a8f4bcd52b75816062c7a05b12dee3de11ccb9f126e9a90125c030b125bb4ab207476e4c9f284617ff3d66d33b7fe555d701e6bf564416825312c9fd8beebc76534bdb1f313325d0fef0eda90a4df39c967457b39200e45cba8544db54836db93c0a3a9d20602f398ad9ea0ce64c87f90f304dc3bff433457e8e4db88e3004fecd86361e9768402cdfe4e40c9addd2cdca954e6273b4d51446ec36a3a85491c96b86c5a2933ca8b9bf08afa312f28da2ebce200f96bd52e255e6102616c9774538e602f7dc1dc7e3825737cf5a5bbb623af0694c3fe16e13725ff1852fba2f5239f0184e86d3e8af2296765b679559228322d08420c4839ac303d854183bbd5a9f0a9fe33b21accf67fba45d1626718d37ac71353a151b867e094e4629955b8143290b353554ae83fdf77ebbaaf5a0b8d785beec8a80b32d6d01864ae93e576afe3c0f89764220c047903a89ca496f94ce87d9780c6aa571219ef2ec9b8683c3a7eede506242e8a9e1e68816d2d409368d353c42f6d4c2bb22f338b7e4174c41b4925ba944920b43fa5d74f5042ae51ff2b3f48f6d27def27e77c854199b2df4948f421fa669674e235f3acce67d64e3d240663112113dea6c911fb91531719b0a74706f6c1516e8e8446588bb801afecca5cb990ca94fe16485978592ac7fdfecd02cb5c603b453cca1418f208a452164ff58af46af3dfd7d930b74cb1100840674efa723e12d5990f016c77c18510cc300837492ea0b1fa0a56694e771f2f839ecbdf4a1037c3a3ca31924c8116952d7a9a3440b3500c821b42064b58c59d29297b75ffd6ba51356394dc1ccd169d03735acac6c32c92b472521928058079ff2bbc8fdab9284df7fdcea340d0506ed29cf3b91bc2893d51a767056bee882d75af6b54c65a365ccc270f291cc198b3eb1c20245a4a9694cfc8a20b771bced88d760a5610f81d65126e7f67a727c194b7c9af2f36a42d289df9e7ea8f1a0a8b30b45a139ecd46678e90bdfb39890869ba4dec0d73dab56417446355253a519dab3e42c994ae3d9620572652f045da2cf63779d154459e2771cd92fde01eba89bfe480537d652d4ec9ae16b9c962b6e246694806ca8fb144776d3a768995f4e8342c4130cb727bd14a1fcc9567040fe935acc27171103e9f14eaa163a1e29d573244c2139623fa50f29d1e41119cd90a83703aa0b3493b9400b652eb57a056bd3885470e0841a151e823ef03d471ece7a8c9bdfde07f3fa3dc01af93d96f70321b230eb8dda158c00055b1b3855dcf38fd9dbf2a17f0ae34a7285baa2231af779f06ea938428fe67bf638fa81db58ce998b563523920d86dd6cf6e1a0d85d2fe89755eb1444dc7265f410ec6ed49c5c8b290147e95801f912da0c80988263237119f1261466332193b4923e9d39c65ce259b0dd3ca0cf5d0dd2fbf04e7ee2eb70413e568151bdde4286758da7c215a8d5b8854c5fec9139ca609933c9a14770c74254aa1c82c0713680b562cfaee8bf47453240a2b452d5427df7df7f8dcef90263d9015d931539b0906508a7f00c152fb0e101c3c88054d505f0bd1569a638959704051bd3ecf8140909ca8ed2eef3430b62044c09239308c007844a1a051577546c517bfa7554d35faaaa0ed57214a1aee3952fc95338e8dd3aa3be78b393340b97560424448666cf3786100099ea97ab12601cc424bc21d23a0e1c880f2e618073acb7ea90a1a1e17897bded3caea5db8f341f7fd040fdbb9d31dd138e63a89f422b6fbbebf5b56c993cd3887a00b71b4dee328665246151e4eaf0ddd0067c28b565dad781bbb4c032013d6252e397110e56ba275e045de26c5d6e1e30a0606461cd61255ce45cecd9b589c056288cf181a4b3e015a295252241aa00efc845562a5cd6cdccb84651f9a1d2f91e7fc2007d4b3170901e01842274036b28d6f61095572664e9521310ab1e1045c0d60d47316442802efbd7864c5cf5dfd2c5f51c4b7027443763e1530b4b54a71d94263f020f6dacba42ce63e1c043baeb4e005fd6d81a95261b35deb0ddb572912a3e8504e085769eabbd8e4078738152a73a83643911d208afac0474a23b5611dff452e839180c6480e7e844330d604510617dcba121c325c6c1a923238bafa22027c3101bf7640e49c462c92b99e65c14eba75509795fd5ec03da3251c3df0a644a1de923fbe4ec060448abb300eda72dddd5f922f334aaf2e96a133e71d9116773d187608c45407bea714937913e3593ee116bf71bc7031edf7c97546834d5a24e5872379ac69b414f55955ad01acf1ebf1d20b4bb330e2ffa6f0c3b8fdde2ed058b947011ee120c93f7a833e9f2e55899f685b8d13fd8fb5de4a4cab1cf315408f14365f301340633450f073a50888008ab5d5e99a0f840bcc4a10dabe17ac187eef4b28966644032589716fad1f9a8b45c479d15a01ed9f2fa4c6485b5a6c310e846cbf7d38c4871845655b437dfa8b48e918326e7710c8d2b37b104391383d5b33c890a54b81e42f78c961afb3b6d2d2e2c88cc73937bd1e7250736c480ca1dd9162e426659e01d4405861aeb14adf80d1f08021e5c446299fbe01903cb653e490e32dc830be8a0229f6f620ffcc38c5b9f5cd827c2956065cae0b1bfd6705d254be5e92be8ef6eca8b7a40a14cb74914c23e825afe02ab2aa6633941d2a6a0c34f3f4a68c054648eaebf959dac7a1a0837540b26d663920c7ed7bc6dba65e2c9460554fd8455ffc3d20c3094dc31f7614280c84785de08deb070c3b4412e3ad69e5c5e655e73607d4b20639e327622a7e81f5c7db1c7d79fdb689ea88a2683b3f7f202bfab6da84c251f23aa4a057228a306e1abb45baf331b1da5d4daf933addaa341dfc21c178867835b150809e356ebdc12feeda19143864b114dc118647ce2f9239d5d0c48716d60f7a8a7c25089671315dc6f3a30aeff73fb7377c452f84936583a6b596db4e83987c89118e4e00c7bc950bc3b2f9906111a1782961dc7c602c05f35bf0ca9600b872c4057b42ff345d14e7949441acc8331e1545901c3f9eb1e804f4f4c25f826cd0822ade2a181a7446a5c014a7129ba5804a20fb5a9bb284f1608d6e97c868fbe1fd1704f71932bc184772ed370a281b76736a32ac18c7a10d4ff9451506194e610b2fab4d98999b65545d18d77020d92119a70c396342ba3f6dbdf191e9a7fba52b37c3af5c1fc4089a7b25949b76b64614a590f2a4f4baf2a01a97333018129e756e9b94420f229d1d5af1ce66719b82fdca9692a4b418374637a3fcc9dceec6b0f16e710134974013f3588046499226592318b7d0aa1548eb8fba12651ad20aab08ffdc71546c5006fa1170e6049e278654e92701150de35b126c9461187bb5e61b0ea478ea4187a23e20c2718db5befb746d11ca770fe0e895ed0c59c90b0cec53ae63f298f602b0cf212ef4bc999928d962df608e02406986f67b75bcd9bd5d5c8d7c4204d99f01e96eb0bdb4e11a9d1bf2ba17142bc5d79ffb31b4ab4144e30011b02781004b9a3a3b04dcc7ac9514ac054dda53fa2516a4e16af3ed415eaac51dad501841208f1f61e44128b681077143c408406dc806f8cc0830d75f0b8b88d8370e99889fc63183e7ae7f028a53e61d0eb71f0c66d34c8a900459c35e6359743c81ac04bd5bbcc25da641d29231be02d6caedf7a56c72b853af9c4d6d553a8e71ab86c5163ac4ccadc3a824f99e59da835987001c9d3c546b9f2df19a391a6c2621e13f3ec45577325b97ab40faa372ef90de2e0a8ceb5fe0065a48fcf4feac80751c5409d9c9bdd675eb16d4f33ffc0c277247e43291db22476b24c58c1ec79ba946657d0a588e379c3a3b7d0cdf010267969a94451164b309f128e5e06a16785373f34cb6a24993696c8fcaa54e20fa4ecd86c4bf0edb175592b9fe2292c12c4b6da3c1cb5270ed3db81185d8c011b7dfb787245071ee3335017e58aab235074ad6c478265ee887d138cb90dd6b5676a5cc6123e142dbbf5dd3469665ac8e7678eaf14168e5e935bc1b84d432fd95db8d9aad5fe6d94a02281a6a846459a2096de316a352b87268e11447b1431d543959d5cc68fe3ae8a478e79f403a88ce0290b61523754c48ec655bd1c4c9baded2c4068560379945db3412db93f88bab8a7630a3ecddae773f6f2aab5b7f740834c87eef7906a8a79eeabda44b7397522e1d5dc874219bdd6c77b4fec87addaf76ef89f79c6de4adb9afd7697bcf67ba0b3954eafabf775f7b93518cfa7ba7e87db3f715ef3bddb4a07bee210a192de1055e789bd7adcf3ee850b9b2b7fe55ff18057cf7fc30807689eeee81de73b651c8de79c998dd6cce573933c5eb57f7adbb751af3c973f95baf2dd36012bbde8c72f73ce30efdc7a1eb60ed2e3f475ea1a8bbf77921d7455c7597e3f99dbae0fbc92e7fbd68e8adf3d3135655de7d6d26507783f9cdb837c7bd7b7971db05a7bc757383c940e3d2cd9689932d237969b73be778ebb0078b2619bcf5997c72d52202f1984289cd0793db96fb363ba551dc29e517dfaa9b377e5246b9bf253ea6f92ad6952540c0e315bb12eedb28816b82e6af93d2861611d0b690a38456462f0f285168c4dea8c08ce48972e9d06516780514c6440532cc071a88c409e748ba05110118ab48a4a46bf353a9592a028919e2f9cb69662c12ecb2056484bfcfcce2229b51cd526a583692890642a69646ab723aa10d6276abbd627cf4905d4e696b4abea0c70606fd73c69c671283fe6d673033dc172cf7cb88642ffa2f96eeb117a43157600f8fac1c6c28b4541e391e9903ff0ac0c45d51e9476b46e84f898b676d98b048e4b7b771c0f6e3b2e9769b1fae9c2077d75d2bcc68d3e99a4285593548235e66d1d3fd5a780d2a6295e1b126436128fa1a7722a1bf7d818b97ce5010351622ec97d624d2d4683640db7cf1c26f6677568102612a55dcf29402d4220cac59b484293a887e6f330eb678b7be1ea3b020187074d9d2f4153fba25cbe31f4de7340ff42d7002df94f554804aa76972fa211917c1ea83c5209603540a3e958c9f0421c93ea38c9acd75d0404984a1a08c4237837ee55414ad32beb0a23231fb747a9750c23322cae934ebed9054e1397524baf52e08579a97b7c2d49c1ad4f79604eec474cabb9a9a40590f46222e286b91f1ab83e78c435bed7092330a8fa59f2f005b35b290d1e3ca063faefb0fe963d6880a62ba3c3c7c20be098adc832c2905241be0e171c2e2d3f16322556d1ea338c380fa3248c8d1d5bb749e729af61d9edfdc5b28a0b72b42aba9c642dfa7c2d81026f6ab5c165e4c3284157badb29a79216160259975e95429f6419835bce42f94a09172dec802a762cb6aa16074cd65c2ecd76de1f7ece4ebcf1156ee45877e2b202d98a205d5da8e0f55e80c00d8914fd8fc6cddfb9b175a23ac86ac455c3e40342364a989d4f00f3187d807625b7b7e0f24412037c1f03722d898a84e122f51d232036c99818a2262cd06286a1c032b53522133dd18e2dc02fc8412a3f7e9f93c29f409e15e6b283fba375101f787cf7e6822ae0d0720b74fb65f9a2a2fe24dec10d6705a66176ded08f5568e9de4486bbf63f1136382712130e6363dfcba42d5dd9e8241d8f17111d36e810af64c8591ab900492af40c6b9fecbc2a6816240245780d5047305ae7720d324c40b841867ac7f00bb2b2046c05301896840805e5ac051294cacc6d2a0609f59157ebbb466c12402790219080cb9810c36410440e320c34f18151bc499d7488311db07e2330e79126aceba0637c246a8995034bd0bdb04c41029a0e712c273e593cd1bbad3be1509eef50e3963eed6145a048a431d81b2126d3d388d542d3f28501b03635862a9c0073033b3df82fd2e35a27c568015017a2832fd4ea16b45451f001eeda468d2345302a01780c70090f079957dfcee24cc227078008804195b0eecbd2343275c322e9c27ab4001a6480b2fd6e22eade6d43e524974ad879815c81c1669ec8120c8845e20e292f4b5c0adc5482020593d4c70d883d3332b266a5605ee311e02ee93023c0331df5ce83058f172ded501fb7e18491459862d39c35c24db84f403155bc83297435dbbb73e484d60d217889a11e44aaa04fa98f655b6756a0a6d03d207de456beef207bfbd21a514623337bf60e6176402bb99f88c43a615c799070938c188815efe7deda0850a78fdf64a351e0554ab87ab759e7f8e6f27b90ded574efa3d1ea90cdcbec399d4532bf76ab64780b90fd0c1af93b0069a9110dbb66f15f2a2518be7af7ed5f10ef4469477ebaacfd87b37b21d28aaafa2c801ad0530a329a33e1381013d6b9e2cdef12d39b3e64b51ba83693a9af53ec5e1ed3eb53a71546c3e80124dc738a2b8a715db3c423f012ff4f5e8a2951b86007bf4d4b73bff7a087ab32d54eb03fc3a68ca44397473f11541ec37a9af109eda4f9a01fa2b80eb7544231b9cd4ee71541c69d26533e6b1466f31e49ce02856994c8c5a37ddac731e62697fc040690d2330d8381a3570646c6a58828d45df82d446168d3e6a7cd3c08f1b47ad6873a796c6933684d916abd69a931f9a07615bbdfcbe46596f94a0cf01e26a7224684ecf43fa3c0256fdaf36b62776421222a2a8887e686bf14e45a0884f82756636690c08d5c0425ccb1951ff14d111e5b08f8580a9807ab3b376ee976536035c1c449d1100a7f376908ae770031e97d63a17a07d2c1115d3367065b3219dbda507fa01acfd636fffe7e95488db97baca644da68d57fb34014821a1eb950c8fc06eedafe4c79fc103c46e6e1e2cc99a046e7fac59241294eee21ef90657c4c1b10174957afc84b67608684820d44480e08c970dc8d35446ecd070fbeb06d6356efe870021f5ea5f2706c2b25b845698574bed4ba3bca0375aab165434129df7ebbe81145bec1499dabc5d8c172636645670405f14a3dea19875fbda6ab6d81e2901b9e486271e86a148af662ac35e06eb64c8d9c3901c1acac0d3fc3c5e2c9049ca3b10602c559fa41c06224178c28e41598b8637c36423268fda68c3dda708d14e24d0555dec1818ae61ec4847c73d0dc438ed3340451719ca4d6704a8d1aa5e0e0e8f87ce6be0a4cee000fe55667ac860df5e9efd76d16761240db06961e7e0799e81b2de4c59fbf84448690b9bc900b0c1243449a476a0e4158bd5fe1b325c11e8821cd5cf2bec8c23044256d89c01fa0fdc4e52e27606357cbd7a437178dd7882a1449dc449a1d2e4bc6dd0eb6a498914090d486c931a81204a1f3813f6058806d490ecd43f55584a23db77a1696b0eb08d3080baa8e66d1969ca2bc931231d963f45a7678804041a3776c8311128c765dc78592bcfba6556d4343c99adda27c82229fd111a674b2d3f6574a826a7e756ae69ef9e6c40dcab09e6ef25edf419fc8fe486e5429237c262c042636c595af90d461c10525793afcc4542c2d5aaff30b4b333abc17af9c54adb719a69d86d23d0ca6ea278495d8bd22f3bccaaea92c6e21306eac0f5f6c597d446686aeec1d81e9d585517647b6260a88a9cf9554ac5e50f831076a5080ab9b9b08c68b8641409e6e31fc6ab585270472e783f1bc3ad21c84f226ab62da11656c81431fa2301d1a8c39f58fa605d7a5a04fe4f5885b3c373de38f89cf28759843af086598354bb7511e797ecd2b0d01a429dc002fc7d8af8c1b24d6148b0b4798009556f737cc1eba953686f00f03018a158e165579b56d91804430414363c03d482dcc07931c86fe69dddd6e853df32f92691116be82f4821b651467e055776125acbc5310938aa5865ad934686d853c3996dfdc5823c9dec492d3b8dbac1ae070b3d9d9d284fba663877d9184033007280e350ea99b937b4b318e223b044887c9b6225c68ce1966bb6131b928f8b226e452931233ca245e7c676a4a6ca1936fa4fa16bbfb7b4d3c307603f2691eb5930e06b5236be99466fc070c4d240738cbd450a48aa111c5fca79391d4d8b31e98f1f2083851d3bf0036d78fec70b38a2882a81d30336055ba852aff49431b634f0d210e7002a3d702e5f849eb44000c58705371c66a95b0a70ae0b5b31a5c0fd7ebe83ac199bf67858b4b1ac381c9dfd27dafce7f929bd694ae78c8efbd2892075906f0addd62b78e62114889016b089bfa0155f0828986df616b4bd86803228cbe51960bf4f7760543db92a2c0627ae27e1167e2e7e3fd116f1fbf722267499e7927a1d3d33c25d38ffb1166140e70a998c0e2a4d5c2ec2eafef651f277c8c1ab45f88df32b52e4be8d7f58b229c4ae110fdc864aa1ed056e99e1b0f2a62e085c6b64480de3077c00dcd7876463ae8d1fdf3099679fe5138d4f93b533832c45865f14f9fa7236cb40211607fdb0d791f615590406a0db0da74201c2f73a07a008058c9eef73be86e08585d84681518902379b7dde757889c453772f034ba67f51dee09527b4ac26dd8410f95632f2345eb36999ecbb5cad61e2bfa4457f9794da2112eeecf5fe92ea3d5ea380db83f7fc78ea7867dae0620dc29848c0a3bc0ab0abc0f055091b2ba85c016c5be5bf35018848becf2573184dee8e6556e23e348de62237ad8e9193ff5aa0d71a11c07f7dba8479162db8bb014da86cba9c20f3b292f848304ca368a74f527bcd3eb8f3be0702128d4bef893c4bdad60590a253c1ba08f27ad484b2a118d2d0781ecfbd1e0f60d05a6c30f6c79675cca56f85f71f11af3f347e9a749ea223d8558609010e492ddfeaa5751ece6d13960b438af626bc65800a5cbd80df180b48bdcd36c0939faa7bba32a5f78debaa804eb51fde9719535696c536d146f1b0fd0a83849c3211819828294a8c6de87a2ac1482cccb9e33525d0cca03f58c5cccf49ab7bee93e9837e114b4c45c825d15a52e713c7b61467339b412b5a5f8c5086068e04c99d07142f2983a2560fc9062557a5557f3aaf6c625d13b266bd2fa3fbfec0ae91535fb3ef314ef3ae94b5879dba62ca75e3df25c1c54a7e64e55d7f5d86885e660700fe300b26139af2506f811186971a409b8f23155e11db1689a07311c9b9622a03fbf4746b028958eaa07511259ece4c5af0604db9f3c1c4e948cf815b67d0d5a3335d66aecc9354c0f7d93ba5b6999b3c7d7d076d910890a4e45aedc1ecb0526bc7338d6922c7733abc188b1e0fae993354a161c9ef3deb291b16faa6c34011cf68470657d4b0b85b5172dee220345808c707398c72228819d6f089d6e344bae2dacb58b259350b387bc340346d2f25d40c68f3ccd6c9959685b8233ca830bb5a748156cdc223204e893aa501cfdac12cdb9d7b7ca024f090c17b7aa9e8def893f5353e29a8951b8656fb9a4691327277eacf72d962432a3153baa902188bdb781bd77916790f9f95f56730360d49bb4827f7f1f0d372828faca220680c7477a51f6637f5a1d527303120ff059ac69c50df845284b800c175b44bc2267394236d12c71d15d9b99824f16db21d0abf4adcd059aa56f695fc9d2b3d0cc16898a1ec995b7bc95744de899bea46a530ef74fe2be8f8a2ef4b676ebc142320635f0054e83388facb718bc6400081b2555ea21ea4a3b4840850ec87d6990d3f25b9c65252f1578bc32a8d275de2f8411dd9aadaaed8917777f619c70c1ce020514b0790e0261965627dd5cfd91443fbc1f9b5086bec0d1b55c36c92852e242eb94b91c35e0d52e352acfea2cc1c963d971a28f13cb74707ebc67de170348dae1c8c6fb684bb8ff71daf9d3cd8f67bb943aaaf619a77122e36a92170d9c69db6894e77d0d1a75ae3ea97eba8b13432f7f490b2e4585b0f5ade525ca1503f884941f0a64e2e535c3199ecf55ff3e98f4f1bc040d3ad83d3849c26fc99745b768d9601f0bdbdb2e14024fa9d48883c5f622982d786ae529b153bc6dbddc71ace20f32802a5d50432e0e930d9fbafecdd32814c8990b7490a0669030f1b15dae5d8ee48378d4293d1885d6b53c2454df62f9271ee5d7269cc03ea6de473cb1f8285624708b31db90d3b158b746d07c8287bcaf83608ebbf02aa69fbd580b40684530f728d60bb29b1439784a689a8984926dd83f7b6f2c732213141290009e1ecab0b561be77e5380bd91d1def5689a8f07c2a77e6304ce7e0d0c0cd01fee5e7573c4fc44873ac9d713a0f9b4a622bc1f401f280c68061eba246ae36df501da68bb893740b2a4d001ffffffffffe7aab42bad5b3c631b21b3b5d6ec27c4ca9424195354d8c814c894524a29a5d4cfca0adb7700e77c3c1e9b2a1b8808950850089757527199d2fc6083c3665e2b73a2969a6e16be528e1d15fae2e3847a43f268dbb10b8dcf61350cca0d493948bfdff1b90d7a6a43b278c9f7759d6ce0e53e3dc6bee5347ee3d246a99bb8d69078a566f4e9394b0d49299e129929b4f4c44683060d1a34685c11a1ce4892add00c9d73a74c7d1a92339df020730e7d4113f21f3830bb43a121b931e7929933982ba4d7a63795e7ce0f36365d429921f954fbe5d0a05286e4d3a4bbd5bfd62f32b026b22a5b593ededa826a955efb48139df3a0c690983e8a96a711d13a16312446cfd5e616aa30247e92bdda5e391892f6673e9ad0b9fa426d5a66d6621662f369b6a7832aef6859657921c17f56dfe3b8bca9be0b899bad74dad0dba5c6e44292fc91f1123235c718de426298bbd09e23d542924a9f2bcd2aff779b9585a4cebba2c173d5721e61214989cbe952e62b24c8278b314ab6e27bb566941512e7af3e83d2a43eeeaf42c2e9eb70424ec8a85385fc480868d0d0616e14159253aad77d2da12ff27a0ac9592c960eb1c9a35dffc19663c4a314a1a4808c29ede6514763e03038781c1e213950061585e4a03166325da5d27eae06654692ba67aa91e5390585a46c2163a6b0750368233978fca29e90dcf1a367fbd79c53d4cb09c91ff437c7f77aff7a4d48f88d9a57d34427614a4c4852399a6ecc714ff65a4a2d812f7bab96d96e8bbf9576d49dbe141ba584648da2755dd4e2728c062a098927c3f78b4a5b27db2f242495c5919db74d8990fd83cd6324078f236d98161c24ea084949e63159aaa7367fe346080c176584041fa55d2b07f931a8a543c78e321264742d254aa83de47190c38687e3004977af638c153ce08b6256454850f94574f21c2223d1e2898f9bfe144f4d84242d2ab47243654ed1219c74d4ee4a0849498dd9c959523af91f84a451b12aa29dfd6013238cde4b1410129478f58b50a283db671749213ed37c7ccc079b18617824f3364600824b440d5de829a4c7ca59f65c24c9a4aa425b4c3fd81e0c7f3d5c24e9ceb6b143556e91e82b9bf3c4ba83d42ac4e8f0b0b345f27b5ed3ea26675632b548eedaa02b8976eb18f1834336d5a045e225cd3f71f97ea5994592baf34b39d1d8303f22e211868d1d470d0c1c20e5de73e0485924f7fd5bfe36a5582468cf98637edcee9843b0484cd2c3e68effbc226194bcab7429d4c94ed7704572c9f9aa5125e3a3bd1aad48d81ad1b33dcf146ab02249481bd9f6d99edaf31b7c18e83fbea855247e786dd97519cb36055b5491e82977c9950bed8b5fa4462a92ce3f2f6cbe995ebe5091a4f4bdedeaf767daa807354e919c27df9dcfe2354c61969395332dc58611428d5224ac89dd1483debbfb9cdc410d522475b25c7bd828923278ee4b7add57acc72b354491f81d73174bb58572b7f3c60e1c28831aa148128b215484878e392aa048d864aff51f4f5f7bfa13499e4f37e975fedd6d9e48ca233b66f24aba64b9353a9158ea3f07e9314877b33891a02fabe7206338dd2b6ee2a419454666659a48fc644ab6883fb9e9af1a99487c4bffb992c144925fccbc3aa66b44cf352e911c63ea78bf7c19f2a4352cd1ff67d754c21c449f5e9b72d4a044255b2909ef3a4fba418d4924af8f6c7f93ad86245a714b8d19ad0a5a565a9e1fbff3c1e61c468d4824cc86ce1746a58f592d4824a936f92a5e2148c8880a6a3c22c98407d36de9972caf1a8e488edf95af13a9e399ff1a8d4852a952d8cd69d13ab31a8c48d256593a3a78c0a8b1885d65b64b6ed63bc52a687d8eeb4abfd4cf853c1860e4b071351491d06b16ea44693ed870809cb5441447e6821a8848121eb6263a76dab45ce3108971bd5293990c919c72e7a01d57a355f9350a917c99dd6a9dacd598d586d4dd9041d5474d0d422449b54d5ab6b4c524ea1a8348ca1bf45fba70b24d481049d1e237b86771b994148804d55963e8cbdfb09b06c41d4efba9b01e18d4f8439257251395efeade5d3f246ae79329b4bb3e24a750a9e1e1a4a6acac061f1a519953b19bbbaf9c5ea649bc8cf2576d1b6bec2129c76388e5ee9cd543828bfeb354ed1fdc948744b1e071a13b7848f473bb0aaab943d267afbc98f46366da0e8995b23988d1f97490eb90703eba925241f54a7448d2a6527c7d4ee9f639245d09df146795c3a283655afbe390306a7a43eb4c8434e1909c4ba84d398dd21bbc0eb1dc905c613ac520e53dc76d48fcd6b05c514cf98bd8603a8f9e35242921be66c4a386446f2fb5d63971727346f26832d9bd61c9559386c498fb3b9f4c4143c2e820832cd3154dcd674858abca49b63543927fc8e76bb40c897179a9a74cdbe9c9909452126f99935c7fc690a0f42775aa366a53c490a46263fae4fc3024a8ff941edc7c30246d4a32698f135e22fc2f24bc08657994aad1bbbd171264a6f8bbec8e2fb2ef4292ae9c36e5545294d0732149fcf3eef674d5ee5b484aa1d36e89d80d15a4850475fbd9bf948504fb28f2fdd288d8b19024835c5163c24575e60a8999274bace573b08b159252b8fbc8982d74521592465f734cdc54485eb5b7d3f0149245ae7df88ae249c55248d2b90a1fb58d42b27b86c69c9975773423419cb6641d3f6ddca19074a7929acb5898d29e90a035683315436cef8424d52ea1196783ee9bf06e8fa7cd6039139262b61cc7b4f22524da897ef6110fb24d4a48562fdd3df24f4282bec77bcc9e4bc60c1292ee3f4e990c62ed1d21a93dffc28cd8d4ab182159e3c77dccdcc59c32925df3c90d69fb49ec2224c6a46be386b8ba94c9484cf93a2b9ce5fe6d899068ab41dfd2e9f53c84a4ce223ebca864a7a910122f06f1b2561a9f1384e4131a46798eb9863580901c7e94ca9c611756ee22495e5e189d945817c58aa29a3536948b04a1333aebc68a300de122d973d8d7eb18540e1aba4592d27572af84094f932d9263dedd8aa1d7a74cb5484e21cd7e63b8a9c86991b4977266919cf47283979aeb949145e2077131d7f7c9fd639178ff7ad143eb8f07164951c3f3890eeaa7bd22f9b554cccd5c9178c194d5b5d589c5ad603f58568c5554b74eda4a248caa9e15e1a144728a2b1b7486d2b8b1b24924e55f783d95a2c357e9d924d1c78ca6cd7d76570af37ef72bffe121dff6f811834012c848c823bd9190479148d6a449fa7d8a118dd107978d843cca1a068904755ee9435632070e46d41e81e4f840f688a4cc0fcb9c17b3c9b594c3032de41dcdaa1162b4a7e9530e909b8035226994ee925e56ea0c1823924368cfa6b3addf69e583cd30608bd0c5b2d95bca58d44ae61a7beab5edfe5cb3a68a144c1189a3630e1f434bbb52ff6043233b3c446e7cf88d316e808cd4f5052c1149276d64da864044ccc1eb802122c1e48d9e5bae774f9f0fce432498e8e841f687aabeef83cdccaccd10c9cb69ccbb5a95ac10c9a3f9c3e91c84a56d468864d3a4737d6b21c4bb360863c865f7122f4d1049a32afe7fecd398e214880419ea29e34459d2ed0144b27cc8cb6e9a37269d3f24ec78e770d19d3f63e387440dbfa1927bd21997ed436210fd77297b6e64ca3ed85acbf890ac292b77e60c7eb0d9b061d8d2f690a4af3fe6794a38403c728c7888dc08c99170e4401e0ee2811a03d34372c83bcb8df579ad291c202664e46f181c1e772061e8388f8335410c3c2a60794890a22b489ddf13a5e9e121d9b5d2812304e9048e23a1416387dd21c1f32ec77efb57603c86d92131e8b5787af2d277d6ad0e49a1569b9a2a75e61f8b0334688c801c0f1b01394887c4b86fab964935872411972c956b85cf7a914329a69895ad9de53adbd0eccdd07827bb3f290e09325ae6705163eaf179640c0eb4c121d1ff6c2d9938fd99a42309e443a488e8c8e15116b037248ad0585253c8fcf7a70f1cc6060ade7398a0df73e048343724a7f7facff78ffc3f7d1cc2318648b621a937698bd524636c285cba94f5b214b4c3ec353deb7aa6a6b9fa8db686842bf33b2fedc3286b6a48fa8fd91965948eb56ae5170f781d8088ec78000a48f0000fa4e0018eb033b018e66931d4c5c5d65d63ee34635852a6eb3424c85d5242a5a78a973e434352a6981a44692e25e3636748d44c26baf2b998faef83cdc386c191036444478e4333246e34ed2c2693caf9c461654874d3dbf1d4d54686a4d935915a2a271be18a181b6536b03124681a25934e49c55195f2c1a623870e343124fc6dd8ffe76facb33ed812bd18250c495faf753a943a61eab881d0434ec042303024a9136a5e3b7c0e7d0bec0bc97a75f63eea4d750cc5f010f142d2d6c9697dbd9c34e6695d50bff47abebea92c877121c92bb9a8eccfbeea9b82d8169243a9c9184f29dd9117869816927446b532b50b164ca3366259c8f7e23de72b739880068d7c046243c4ccb090584aa7ca72e35f2149a6f23d6979d7439f5648dc141de7ed3d754c31ab42829631bfcdeca172fc6c54483e8d4965fabd447ec70d3e053685e48df5a91b73560a495b156fb4cf3485cea4122c0ac9734a5f868ad1c276b29d60662445b7be1d593a24181412b573c905651e26d813122baf43484f5b3db9d2a0c143302724af5ad038f1152394da84c452e26387269962f0ef0c634282a75d877ad5a613a725248ba59b875cb0d4ef2821e1f7d6366afc1854105a1292e62b34ae9db07a192121316f285babd2b163c68e90244706b1dade8d90d8f983be7cca5a199b7575d685bc055f1da541fb360621b72224783459a6634a7eb0e520c7f10803191ba7bc8d91b343644d10038f08181989d9d3da35664c84a44b49c5ab279ddc21246caa3955d70921b92df9880dcfd22d088929425fc56905910121f182d8e0715e32a5fe900949693a6c3c08466e788046efd05d245f549351b3ab7b6a25e453dac181c540e9224984103a9c9e56b820ff60eb349282ca45628fde7cadf76a32a38643c4d0a0709128724bde3b6fb74832d72ead1a6725ab52b648101ece62ccb35d5be95a24a5b5a03926ac74774a46d122c1d2338e50d1a9592428315ef263c891e12b5924d685aacda3725490672c12935cda2f59bf41981a16092a6613aac6bf10d42b1233cf6c4dec8fb9855950ae48d2902998d293a95624862b4d2f4fb9a9cc5a41b1a2b1f1d0da8e91cdb414fe7259ed7e18d16dad2261ec3f8d6813f9e2ab226184da534ad5681cf15391e85aba1564dda92046053aa9cf8e0ae24aa7e0ce4ce6ee55de62eb9fd025f364f61b46992231e82f5529126d3387cc986fc49d5ba448ae985cb62ca520e37dd528923d4dfceef3b7258a64cfc12bdfda5f8790ffa04291f0d5256490d3d1db3bb77182310a1489315e6b105e631bd6f38964bdcaec121e3fa994792231c63ef78be1c3a712eac45d5f2d165a75b51e1bd47590165ae3c45e5a9baa6a152e55b00e19b7ac346e6aa84d24679a88baf158fdd5349134f699f734ecca44d2e8d091b17d726d1d2612fe3dc930272f9e56579748cc17bdeef9254b2498576788e9894cadc1418e2f68d0c0418e9090aa44c228655d32da6becee3e284a2497e820b4e88e26911cd4d3452bafa494c94822c9c3376c29cb99bece4864e556da6e75d166e33bf3546ced784122a9e5729af7d45ea11e9194152dfba99359c636a58c7244c2a86cb132bab444de675423924674a6cd22da352f568c483419add447cb4f4d9e5a44f2ac5ada7f5529478e1014a02212fdde4cc8bc5de27c4d4472c570dfb36e9d3cc9bc0d1d858804955d515d435b8ef10f916c177f955e754324ff09cd93ad9d6d4f5e88c40a3ae9f9cf232d5f4788abc45c2cccaa861a537dc9e54a7d3588e4bc399e224eb67c0cfaba1c094708dc06c8c717a50491a46f9b9fa46c52dae281c06664dce4b2c86646eb39a1f76392318048d05cfbe9474c7fe0c6de729d67a5987684d84fca2e3f14d3aeb5b5324cecea53a3db87cf22ca53cead3e2426ad7c4a9dfcdc9c151f926b9498986c6c0f899531a8b5a810a5db7fb085fc088ed74372e81feb9ca307fb1df390a4ae675aae25af74ca0b0f49e762a193f06a11967487a4cf4166bb1a8db1f5db2131e5248307551d73ccb93a2408d9612f1b3ec2ce628a0e09ef6dff97a4c7a918d5a3e69098efd2c38652e1d7a27248cca4aa6ed64a0629f70c2a0e89b3b189595dba2b5d76cc24c63454756d75ed76a3562263f2644a8b32b7068886a4f564ea9b9aab640ccf90602f36a2191235a96e6bcde1937b07cb9094f298afbbcfc99475321c7e2ebac856c6905c49b8dffb5ba5a7114d22ca5230c03024081d74eed39f73c6fc8021b94bebba63f7733c15fc42b2ce5b8ed3eb8b29d4e885d53e5c6eabebb3d64e4ec53f99da98fac32e246d45d3a27739c8852475233f9375e6b94ac12d24eea985d57027b62de714b590f45e95f3ca878d1ba32120c932805948eacf953bfa7c72d800c30307c8c708080eb0a0cac959cbbd8c66e6d2d9323ba8598b3f5f21f9e78377c74c8819f100c10da0151244b6c75ca7f1cb6611ac42c2b9e9f86fd3225221397c0ad66661f7a14b5348fe504d35af16292465ffe84f19738e090f4621b1652c73dc4e3aea6cd737043423f9b2c36f7c7eb3b82a1e4221e1baa4dba9e5cbd1729e909ca172baf0184507b9a2131274a85395a9c6262485eafcf857252624ec9ea8bc4ffb12123f7b3ced1a4a66e92025248b9bb0b2bda0a6f69384e4faf48b8d51838424bbb0b3683a7690397b011e21d9920e4a69ff731376d1bb73a45d46e255dc0f6d322fa8c84570577fd35d3c2623596da3a9d279a3c96d899098ad6383c7d21092f4a3c6d8fe4248984debcbb56710127ef4ff8770d5d4ff7d008190ec9e545c396b1709a6f565af16f3283be922f983aa93ee41a3acf6b9480e964153aa67cd593c641c2e923a76d0a9ad4a255f0b8ab1778b24e14185139d53501654670bbc42c3ea9258aa2e8f6bdb371d7e56d722498378909a555dccb2b448eed3eb758bcfb1467fb348b63f99e36515952c7e74e4649118b25eb3a6d31b8be4fb52de992fd3b048aee095ba4c7ce52899ffbe22f9d386ce75864a5e9f2b92dbd7747888052163b5e258d1786e15b9a594425732a5d9bc1f9c2aee5291e821c47ad6517321e46b5424f6d9cdc6ced775a9ea3bc5d140678adedd2b54eedbd28add6be9dca43c2279a548fcd9edb52432cb9776a4484efbac4987c74de44691a459d75a7dd511901b202468c18922e993c5f7702a85c7b8502406b1b8f1736e911d7b1d078ae44ef2a637d56f8659f7898457b9cba5ffe289c4922d197316f3b019af1389a38275cc7b9b62799cf0b498690eeefeeae03691aa3c1d733b67ee033c908207a0e134815faa18f13d09fe863141ef28bb4c60222f912cbacb839a8fa774e996a882c67aa757c8675df25422e93ba58a4bd3d93051c8512229ddea2ea5ad6a6fcb24126fbe2a378db05c2ade278944932adad5722529ead98b4492322163a9bbb1b49d1f2492e3e5a7c58bccd47b22c23d22e9e2cb730765f69f29758e688418c708a4b108451c2de6cd26026fb10e39b1b7f6b26c6e275b4363a86b329d394424cea96c26315a9b4a2767708748921d211afdee3f6e6988e4b306212de57a85481c79b71664a999dd4888848f1ebbb3b483785283718348eaa8a661feb4df20229d9c2092a39ed0b911421fa2e350041788c431795f651ea6f4080122f97f3bce5ede7f484c8dd6211bd5ac5ef643a2b87ed0d9d5e572a80f89716341c5c6cd946ebd717c309f5cfd375beff6b0e3f4902064e9ffacab109a5e1efc1ba963e2f090d8fd163c2c373cc914e21d189d84ef25df0e265549261d6465ba701dbe1835551d4f09f9513a2467c784454f675dc139944333cb564cb52dcad786f59492b8b00a2787c498e682a90b998b436207cdfba27398abbc1e1c123f66d690f9cd6cc2bd21b13c465ebffd67fe0d9a716e48162d167337065dba49916b4361743ded28951e1b92fd2eb976524a6bd83f5cc831d9931a1234fc68f17ead4a95744672284da7b3589a912da52149de2c6d0adf9be24a6848bcf2787a29e65a1e9d21418de5ea2a5bf5dc793324771252654e8e1215f36548127f9d329f869d7a9f0c49ae9e1f43925e693ad13a55a72486e4a4b63f89fa20fae26148106ad3a7f01b967a0443e28e29ff6cba2f245b756e39d1dc0b89a7be6443e35d4850751117923b2f7fbcb36c2169d4d27297cc9fb3ac8524613279dd958dc5370bc9a7f5ac928e8b3229c2427206bdcdaa397485c4fcae954689f9c9d2b142c2fbbfc6a7bd0ac9492e5490a62f5e10a242e2efe6d9d07123fb3953481cbd7d6a63d82dcf395248ee6b110df515c5435148d0bd4bd7d920733a6624a80d2a27995a53160f149242e75dedcfa51cd53c21c9ba928cba0d66b51927248afe8ef6addc1c2e4d48381d2f850989d1ab52ca399350da2d4b489a191d47645b9490a46c674b28df4d3a589290e82ae234dfc585fe0a1292c2789eebfc34b75d3942c256902132251d44fd4648ae4b7ea772c3c78ebb8ce40df1f094463488b58b9014eb4e4c6a928ce4bf4bfe575dfa4b44486cef1c56b27965be212455acb6e56752325b0b2149cf73b824ed35b9414870d1f9221a2b4c45078404bbb495acb76285cc2e92f4c6376ec5f6cbe92279844e91a744b85b251749a1d1b73e6b5c1c63b677ab0def2d92b369dc6c56aa2dc76b8b449fcbad4efbd62229b3e84bd5a5f152891649b2c4a94ca76c4d27679194ff1533445a8e1f592427cfd941caa7168b04bd95ced4c81416b72759e92b922c94f03f4da9b77b572488c54ef318c34793b722e15352b29e3d3c87ce8ac4990f7fe2d62d07a15524cc7c98568ed92633aa48ea3ea57252d99fde662a92fec744860d4a5424a7d57de77c8630f929925256fef9f8a02992f6d388fc0a9622318d6636ad99713b8da44890296789aeabf814711449c2bea2efa8549937144572bc9882de3b8f39c7301449b5dbf715c3d53d73a048fa14f4dd3daa8e8df789844d1e965d9e3ae7ec3c913476f7669f43257d5d2712642c15742afd5c5a324eb83ba3edc9de44a2adccc918a33f8dab89c47c7aa69ef2c5fd6426125b73ad785fb0cb9461227984a73aa54248192f913cf6415ab2ad72cb2d91a454fc0312c0a2001605f0ea1a90ee93492833020d18c3c6c807182038285034cad23008a011911d210400c018870209f0624464470a06008007c3ec000387b171800088843cdae13942742080055e00c00b0710c20b2fbc00800614d00111101d26010020c30b1191436300013023c66910000066c4788e101a06f042000c4040c87b8481cc8888878702bc00c0020c802023211f22363c3c1090b3d0714316e871808c8501121663e840af4090111b1f22c6c30301e90a0419f11c375a91ac97ffb2e76728edf083fb6cc7d98d0ff11003c43d1c04bd0e9162233840588120236280f80e0f0f04e42a465ee4c6df2840aa22297fc384870fe525d65424a86c277490db8ba02231838d884de68dbfc19ba748509676bec76312dee94037fec6def81b28820364c406c88ee311f2364074dcc881344d911c5ad34feddd6ad4bf4a912c72736f365d262992832c8db172181942bff7c851245b16adbdcc7e3138406e20a72812bd54af84997e0db37cb09d1d22a6810cc595292ae377efc5cbc386b9182428922b69d70cb539f4c8f6c1a6d681fc44f257d6c5ac90f960e30aa42792beb4a8d84b0f2b2ab6225f642792a4a7e41616caecfa45427202a5ce2d9b6813a989cbc461e2ec126689be82c85dc5705b39d9fa5bff9ff7ecb10fc3aca012491aafe4754e192512fc2e2ea978f31ebc3a424e224125153796285dbb17492241e8ee58a3e49685cc91485a758d39cc8fda746b422241af52a807bde42392462c7ffca78b264d85413a82f554b550bb70f7165de5a277859d873defb31189b1fe35c660c26444b258aedb08a1a529e54b107211c92c9b316daf08eb2cace22bd6cef3a8b83211097aae7e73929a21358388a498b459e80e974324ab751edf9cefe3de6788c498ad141fb35588048d9f4bb7b4a920b24488c4dc382657193fe6bb3f5a908348522f266f2998c915d5992012c4853eede49e6ad38c69c84024291de17ab9358c3e6d0222393c6cc5b449445ece3523ff90d43bf72294cc793c99f44392daa4af336692f529da87e43a59badecaf496a6241f700fa887e475cbce516e21a395f250acbbef3acd0a2fd74ac14372ca551df7b2cec1e3503042be0478213f022283bc43991dac0e7ba8a8a568655bb73197a5c2a71c4774b6b0705cd17103e107920e496339770c624a5453ca907348b04df2b4c28496136a39f0b1d43357256444870a320e9a70c0c262b9574a96434d54e482bc52b146e5827df986041d725b8352b547bac168b4a1201b6e0da786448dbd9d96738ef7ef9f9169484e31edefb4e8a93c8e86a48cfe9d4a83ac6f4ae61992355d06bd25376e9d4c33180dbc916528434986637c5752163b6e111d393ac76034c4603470061986e4201f74ae895cb45bf1110986deddc25a57ce0c19a7b14beafe2e467e216947bf3328db30bf5e7a2141c82933654acf2e247cce1843bfa7242dbbbd4472e198f5b1e416125b33659e65ba0a99a516125c83e6145a2a877a511692e6936ce99f909997935848aece9369d943c7d4f415124f8758102145e766437e04e48a905648da60ebe1fef22a24260f6a8ea44262e79bb68c9a163a88a790a4f36fd40e1fa61412532cb318de354b955014927fee947edda98b6b37a5194917e6ce3ffe9f5db8402149561af5fb61e51392722cb1a051ef626a921392cecd2da58f9c4d48d4a4645305d160a6f35d3221f194102ae7b7bccb252458b6c5aefff89a904a68f45a521d94b69290b8792bf3b2e249399dbb4442e2cfed768b6cd1417957461e21713683583efb7852d7bb3442b289cf6ea2d4ca629eb20ca3f1822c42929c6b2759dfb8fa24cc4292911cf62acc768ab59d532e899060174a89505b61fc4b974348b0764b1b572be9bb8f97424818b96fff98d64e742c8360342e819024b2f942d3c6888068ed22e1377fce9bcbae57ec74916816f34ae89874b948ca95b46254ecf17091f8b9f4f98a92f16e9188aad6c89a6ab7d98b6a0af27e2ee5830d6d91a4fb7137e6b1bb5a24c8a03af4cba593e2222d125554057db1f3056d8c9011b30ef91190649c45e2b8b55f57d8ee1c51164922bb25b7ddfb316c8c05ee952a8959b7b6969c70cb5c52b4086171f88a646d13bfe1b2ce3ee85d91a4937dd8d10bb62239c58c231f67b4ad9e901549db97ddde63b61159c2015791e8b32a325ffa9ce1525491942be8edaae9914189539114de446392335f3abc52405424e93cd3f8d151b31cbcc353247696eeb58b0c4d818bb01449e2bbc3662e96f29c435224e5da86174d1bd47785a348544d3696f132c3a75e1449a964b8914bd9cc7628123de9af9f4ba2b6620741917c9d3955cd9998860b3f5114f9fa74d113499db2eacc98a61349e2ef3bdca6c9bea890134939bdf3fd52b6f9accec04d247c90df0ec2eecd72ae89043119d55625672251467f34adb9622249b58c58cf9d72c58ae12592572e8a9231bf434b2458a8bcbb6ce94a60fa1f3359ee9012c9f957ef3b763b7916dd7ad8e1c04924970ead7439e9ee59eb3cecc438944482b6d1714c9ab6cc631e4622a93b958a9ac6cd2e730889e430eabae542c59cb5c1c347247ec79349c66a1b1d9198c7bc4643534ef741d888a4d05439e9b8d6222392774f9c36b7b332155f4462c778a793f80a5b296d838a4894f9df6b191543c6ac0c4c446254d310f3332122123777a630da544fd3623c44f2c50dbaf72e6bd8110d1a888648cefdb2f239d907512516224973bad267d5ea129010651009ae692b7ce747f5130b82cd30e51efbe440741f0444e22915622a3e966687be38c43f74fdd9d74174ee02fa21e1e292da7610f17c6b00fb906c1f6354efd0413e246ebc53b1826bacd21e0f1d1672021484817b4812ca74f8c8a49e47bf912324f589180b500fa8ea74bbd152bc59079887a43c97a97aae43a7f81103e221e137e70d15327d873288c676b6abec90283a9f7a260b551d122efd96bd58e55d1ce990642ae8a435c3e951da3287e4d5d0edd4a21fea3713500e89a396468c4362b4aeefea9c4396d8af80705876f3a6b631d3e31b9257dc437c9296bf53de0d89233a53dc65a80d494a8f1ccd95fdb2aa886c48ca2f159fcc646b2fbd06b442c9933aab2131a97bd3c1e4f6ba85cf088976a8c4ad2643f26030128944e280288e0273cb1413130000000c209146839160349c299a2c0f140003652c183c3c2c2024161416168fc5c380201c0884826140201c080402c1401044516b1c6a7ccdb854e8878d85ff8dfa7777780097f8b9a9ad0816a40dec0076a9fbf669ffd74f05013a005d385edf7f1b0913d0cfe88e8de8912e171121bfadfdf0b4d49a8ab7977b5ab52ec81f201f7241e88e2e569a9293f6dfe93d8d37caa56d1478068c553f92dadb82eb7c35b10b6337f61657f29502306283326d9a20261b9cd617b63b308d44f296afcd14635d596f1a9a5e1464bd6ca79254d66c22967b2f8d68ccca3eaa193960a1836b387c6854e82e21cec2b092f8f119923156a74f30e044bee7be117215499ce7ac48c044906c616da9bd49ad057325222174d3e8af6f8f24955ca740357c2222d217708729b6799c000f3bc850e5b29fc43087b234ea99624c9aace84761737ea94c58b268d3251f42fb646693f96755ea1958b3144632ce162993f068f0658a2627a4da4660379f4317e69d0bfa1baae4f8d7f2c10c30274a084de11b8ea5dc010c111bb4ed8177b9cb6c182644a305659862cf29d0507ccee1bb31e2deeab775e2dc79a95a5fd6571d517e2167d32c8478ee6ad7fae82014ff1962adafbbbac94caad15dc2989f28f84fbf0043e575e6833842f06aa5761a761b8739b02633b744acc67d2d96ba9b71891c4dda12b7bb429b13307af3f4d8c2be6980ba7fc1e0a7fa9ee818c8f3b851d7e7b994f2a00e0637b396ac550ac62f6baaaa8cc2404a335a96cc4fab0fe73566b669a2b2db23e8cc4e5724042d4969afcc77c86cedc29d8429e736f1a4deab704a8517379c60c3eafca007c0fe1183a600d7596575dcbbfe9a0f376696480aec0e8292313ed0952fb83c5eb514a4aaa6e3edc19bd41e3276ede6cb85384620300ac832db1c55ebfc87a047be2a94b3d95caccfb977463c4c959387e1339482173d6f140b1b074355f956ea161a5e915459cc925ec7be7504a099d9e9d164a40c525cd14ee692f99c8187fa8041eef4adb45233e5e72e1947e8a6a8aa48f8ca1accb5a6d548ff86bbf25677030153d9f216e0738c46b36e5737a52822c023083a28fa6af881617e40e96684376b93b96be4fca806360f6c889b0dfdc9c20a18aad9efda2f5d8521b94887053c11062d901ec5e3f05e0c90f75c308d5560ed7653d2234e0afb184e88296059d08031a9bbf4247364a8ab4a47525aa8ae2d0fb698083fb1f50ede74c7936c3d94fb2e2b99c329b19cf506eb208829d8b3355841006375a8407f0d2c48866804d718bd0210100c17724d9c117569d72d1bb146faa5c5f06b09de70f6e3e2bf8c032397dddb6809ce37117bd6382203a1e182a759e39e84fc22a058824d86b5303217ea44aaae60f7551fc04f58c9d89c11081c3b46aa092d54a8e133e2690a6497e6139f974082ca479396288cd9c52bab7587da734970f3d052c5ec3b26f34042e69ba7e5840494684438efd4a197a7e54e990f7f475a4ba464f6036728e00326338401632888a3547b16d2fb90b77895bbb6d9a5c417de47e0101d421c3901b5410b39504f8ea5ed9fb1fdc6cf6bcdc0a32be5f957ed84fd371e5829853b4b8b2f21d30657e342749cd14b044b21b0795d1ca6c9109016045ca13d7e408135edfd57543a8652ae2e85e15671a8ad8104a5f394aa442173ef29299eded50342be15eecc75b1e054d943fb50ce0566557cbab96821ffa438d4da5963fcfce65490c0d6b924303bc93532b1bab7e2052ac71de389424ec1e58467dd94c7702a0dc454901ebd3f9a3e75df45886ab41d1421ac395464d6f29122c4aaeae780d119dbc6d6f2c9031938010df768432567afc2a94570df45401f2e371668a8007525c008460f81c31483c1087d6027cbaef56acf5d158aeae228f69c27d4d46d62a090e225e8470eb3efdce82015a05fa9feada7e99bc9fcf5e7a87de0e660bbf38c53a415d6c0f5680d403869a227fc7349dfbb1d8ec23849fa5c78a01ee5b453ba01ba0200000c14e53bb00c50d4dcd13b18375624e1c43b603b383abf9b3cae3f8d2ed77b973b23c95013055f13dd2d9bd6822cb54139615eae8e1fbdfd35b6428d0b0a3444693f8f58ebebc6dbfe559e8737238452e85863459a348f3d865d87e1f5eb8539c1c7b201d84d80d4da616ecc55a6d990bd7804ba691864e6667fa7d0acbd30d68a2bac8b20a1a2486d2c35d4bbd4497914e11888a6534e3207f796f5cc8b47200f73550d609a13f6f2a88a0d90ca263de88fbb6c8136f4bfd73f620d5579998225d2b0ae50232ad85f292195dbe2a94fbcb78f669818e8b5aa1c502439f4a4acfc52bbed68c3c3f105960fd074b87fc9a884475e37fa23aa901af5fa315ad2f2c4c2f8a81712a21917810e996b86162edd77b2d84635d7035446d0c7cf3a563437c9bfab41c246317e4c6b0600c354aee48956f5bd7f010c9f4db4a13bc0c151b46ec11d16a76ec24578b3f0a8b75b114c87c675923718ace7c621db01baa5aa385a8c0358e56937cce97baff1ebd215568400d0cf508f41971725a1e63914460d89812fdc976b45d3a1f2776bd263f46515c4c54a23ac71e4b544cd86354f274dd8c3ced6960c6ea092a39287183ccf66a9faff4c09c4843f8a4ea323a1a47b0e38a38fc8fa1f9a426ce8e1cb08d8609d4aaf25c28ccf8649a73e4869ab08b31e9378908d1434779916278699790d18cb43d021eda4da59a6c5ce8c49c192304a92d940a22f7930c0e3252623339e51a212de2cda6259d7b38ade15c416e5ef2d29d0f233b3c22551428302c07cb26c193b7e8dc6ede4a3e64f8835e258c676df8bd23bed2632d9674e0b349b4d1d427bf6c80ea4d4e85efcc9ff07753b5af2eda6011e6e34295be272f99f3d4cbbd60bccc20bd21f9ef95415cb4fc87bc342dbb87ea1fd126aa4f357586dd9cfe700b1093e051f1e28ac758c3dc1368818cec2d15f31c453955016a32c1e75a4c358f9c4909607ee4d53779656ee0ccef992dfdf8afcfdf59c0b903611c03e7d79c91e93178f352f133e60694785767fd9a9b36c7fc8c1fb3c5bf25a016ed75695c0e480d3ddc787a59cdbc6b3cfb29a8d768fa992492ae46843237da6b2da41f990923ea3bddb784ac4288dc0293bd66b1adf70f888ae03884ea71e74663cea4eac30637b455223e2f4592dfb21c81429bf94a64bdee6e1cfa769a5fd8335158c1468fec501a12de7c67be8d7543069457b255bd282a778b1b49f525eb8e1e94e70106833bba789e7883636dbe887cc63042d740f2e0de1a39ea95895980a2b540b06ae1fb7d8198fc44904313447d581a2207b30fdc80fd5f183534318c61d65b96f8af9cdb2bc46f3b89b5070784977d83d706aa9ded3e5dd87d1940999535852b1cf3306be204e988f80b21c777c0009363a30ab3108d130c6bce72574a492f4360c0f1c145654a7962046020bf983cc32a4210352f6d256e3a1d2b43b3fad94f5920fd52613aa12bb8d43c9d42a826ee2ec16a0c1b9f9da201e026e835052c2af9f4247833aa801bb0f8ca62a0c4d8a76863a91b1a3624eb188c52847d59e7db212656054ac4571c4ddcc049935210457899f2f8ce097ab5855af22678f306b83e10019d7aca9eddbd2bd3d6f91130f289f99bd03bf6ac190d6b8fe40293ebc67c7292b63b477a688447fab9823431c4a9c8633de0a297d73d2bba7fc08ceda6c51dba930b17e193c030e3d96c8bde7fe85e4a80b2e293af1a8e5ac38082430a04bd219677a69b11663ca48ac83440cf0e2605cdc44f814c129b46dc309a71b42d9ce68e46f8d244ac248b92938d566976812eff054f851dc13d8169350909a92be8994343f0df293f40d035853d1face91efb6fb232c184db7605fc1845cd10a807878460246b5ab5e7871c91889bce05e4d3b739ad342ce77fa1a60470888678f87201f07e0bed2d969c71f38451dd680887b7a74aebcca99a920cbfe9ccfdebabefe36280155596df7cb205a1e06ea59929e2fa2220232d3c8dfc9d70771172a6155a033f370617030b08bfd394802ed7d9f1061294cb2d9c99df7bf80fe6a8a86ce94c0905c15f0cd218e6949e9bd1bc51295af05a38828f1ccf1b2841c66edd896d3e845d0501641a9661029f30476e8d364e3aff26e35a4eb09762b094703563979254e48470b0d99bd116d32297fc7d150bc7267f374fd850f80abca562f1946e53b1a909187e998c123cc32659aba79a595c9828502b8938643e18120e4fdac883d6c475f672182d15dbd8ed878ee896d74cb060c5e454571bfd66f0bc3090e8bc6157f7572745f95ffaaf9bf969b7c1cdb5395a93201687b97c055a71fc0b213fdb0472642a97229defef859124e81d510d072deb87d96f3feeecd10f1a0f74f95667e3544f3df3c4c74df2debe4f2174b75e83af62346ea0423452134034280e4221baeaf27f8f43633662364a68952d160e0db3766132a882ff0b919a3ff79c949ada5836536d01bd9b0bd9b142025306e9d4dc8d0b29ae46408d31db6eac06d381e8e9e07bded4714edc1fa9eb331694d88818106f790d953505659ea2234baabcb75f581bfcea1a4ab718bf9551a82a24a1c1df08cbe9db9512f39022f27c800ce7fe7aaed9189ea19e51061bada6ef05308fc7d0a3da7b8451787ae76eaa52cfb3963c1bdaba6f02cb53ab9c82a04b8f15c6a5aa1927cfc214bd3c367ab39000f1d3dde43ae79538a12902d848da45363f92e64aedcd1b2d84f4c828d99349e53d4a92957e6083d64178a39d809215b8dbefcdb030c554da87175b44fc2252afca894ffe7aa3ad282df146d333b2039695bd17260d267ece3ed54a6d42d1620212b4f16cabccdf815594a57972410edf6e686cacda6a21273f2a67568d49ba33cdab90cb4ba7f3d915b8407bdaf13750fbca1957e25462662b508611603f64c30b23008e4fa72108b9aa7911de513c07466f4c578cc39475deddd2f8586bd48053841ee411b046adcde50b704356a4764ad23284513a90b1554b9ec14912345e963cbcfbea2c1d96f4bbd7bca1e78306568036dc63aa586dd792797a458153817d1372560221076fa6e451fb98fd933f76f77799cd5663245128dd73eb5925c57b2b7ac33e7bd7bb7aa28988ae7ae3d7eb38fce2e12be88d1de988ce2fcf5917f16fd8705d7290e71910b944a85d80b4433aab5c4f5bef9b7b6b9c54024db663ca5633f4da23f85dd4fe9a277910413741108afe9239621d9df62f05964a5804a80fc7d1390a46715540ad1c72d0ab103ec87e8e2e4487346cf3847cd54ac228c0ba66d5ebd688af5710788654a26a323a30b4a0ce9238191263a8d90c9239d20ca89bed000ac9778bc3b7a2699ae9aa09acea722d3eb0d0a34a59bf3e8d3f23775425aba7a3cdcae2b9da67ee3449c7b302c106685ec39f12ca055f8fdcb457c464374e1dc58812cd7826ad281b02be40b47d9c244b6a73259103b1a9c5af296da29025f29b301d1845e7c6dffcbdcd2708fbf22d95fa31e250aa2d6004c20ca0eeff473ce5c5d545c08eab4ce25a7fc300d96e0e518fa8dfee7168f71a803a714ef1eec9f556600f75fd9e2dcaa15e42bec11dd78877e0f1f0b371d9c3908dfa010a116ea50efee21d16212465864cab371208aef322945ad403bf47fb26f88b6da0de308a30f70759c70823841371973f69429c62dc4f343490ea1703de7ddb865e349b1cf8595466639bf9008c5c7b990b503767c659e47a5523d56167064ae0c2f380653380dc3c386a0583b3b07918c597c0bb5af9121908da667b8f9db58e5fb85598ff118a44e3ec5b772be98df31e00017cf4729488b9bc5c925c23e202596b2d46a035dd4bfeeb852443981be5231fe84b7af35d49aca3d854d6c443cc5c992e4d0b32496e6853f56c061509d3ccdfba1e508d9bfc01a3e85cf1e51af8f84fcfa3f4f9dea6e1cb1d8f6fb368f580d3d68ed0e2317734556d3d178f15eeaa4ab8b725028d6bfa268497b7ab35635dbec936c7a2fdb2516ecf86a51a20cb45e19a3d5971f779d8a1a51d84a5eea0a82ffe6033533408a78d2b4bba9a19a172ed0322910430966145fb41fc6d066fdf90f185472c46d4ea1073fa1fa0e3acc67284b05b968e6743c1fb853e3819a7aaa509744e94f234184bf7ce935c7c0f209b173a02d3d9ab1207f56e534432e52c83b61046ea156e37342d8b476ce92baa681e9872703618d1faa2d00e15b385e1236c8c1e8c70255e61f20049da460d3099b745f6c38bff49107af8d27db07ba61d23e205e79c44472ce535ccbfa1a7f67600b0c381fba1ccd8ac7103326cfab35f53c5cfff2fd65e1880047a6170875153d6a3cca2e026676a098aa18ed034628f00bf4d34e858171f2b88bace20407e1a1f50eab2d79913e25f3ec35890f2c17f1588557889af603d98a4e15b322dc9ca9bd581ce70fae9211732f9215548bb9f3ea3ef32c7276fe27361331829d5dbe6413accd6851babe707a1bc35af1abf6cb077a7333fea54b3be85dd96ee528bdbff5dc9b6265279f86bce2d29f77c8d485ab2dc07e86842345061ae5079e8fd898752efb1c36aa52ab1c5bbc5c099f44e7885682370fcf67bd67e6ce82db1f38c7de232d949ea52b6fc63ff68c43dba28a2da26e664f38bd03ced0b99e58f3be3ca2bb31c2c4dbb3a44952735a237158d2527e79993cb00e8ee0a65e757700675f072127014b97ba503a157fd0b044967743e3d22fc080d89f27430da48a509fce067d8c05a5d3e63c8566a7572a70d1461caa126b978c485dd42bfe7e2794154cf9f330fc5e739763066b0f02fe0a044bd8d9831583b3d0c652589a1f3bcdaf8da2842f2dac19e9aa2943bc77984b6647926d8518f2d853d8c3ca97b34db24b10cc27cd2111fc0edea7bd98a3731e48208e8c8b03753194d15cb1e4f19a9215eab642916d442a5f0fef993d44eb62ca0e5bdcb9f1f4c4b4327d3c12e5a9ed1d2550b9c6c04f9872a1e7e8c484c9ac6f454bcb8700c2e9885404cb8d2b0440b43a94c54ffd48313dc76cf66f87f13d23f68e445f8019e6df6f33223ee41eb4d80c317dad5f6584200e62d728403c81754362746ee4cd89d81a7c3685513724068c857d1539543c25f30e6928310a7c5ed9528f6fc320a1037b4d0c912884d6f4d0a2f7f8b806755bedcd5603583ece3d1f39fb174e163d0608b5d8c4cb3498168738ce95afe312dca7af9badf39e1c81e382a1b78a16fe3592f2b3bf9aa13a0e0be7e2f808b6f933ead246c1abc49ec4d863b529f031ae16b889a124fa882c26cb4551c44ab40a6d3886fc0fc770d531f1970bd0146c1e6044cb567bf922a822a8c3798e6fc03f42622d5b0b749b597b9a1d8a8ed51c338f84abbe84e697b2aa0a89c871ea934a85fca03f6a07f97f80580e797570ac55674756084b0f768758fa98351298c5d88322e0b01f5f78bbf4e9c75fd2d7798f091f1c9960e6ce11892ed05a1a9a7cda052c80705eed2da348504c6092677d4b2f334b063db3623dc0b151d25977250ef027bf410531c0073ecc1d247cd06764229c0f03be1643b90e484fcd6c5f9adcd5673d9fd52b541f7420bc351c0174687b71f3da99c2db0365b7336a33d8f12441283e07c5cc393ed8da916ad77a94771f9975127c2b03919cba5348c8ec2eaccf2557f0133d56236bd76c5cb2b150e213deace351b1848de2c6b1043fee0d6435ab25a37a5655cc6109e46d2d64e4433882de4078bf17b73fb89d37137c6a392fcc2bcef04c4fa694f89994fba57a5146721c381c4c23f9700ae0522f49f4449451439093ef12550d4aa21c288c88cd08110261672e9870c10b598abd80298158d07d50419e23cafa02af03eb204baa5d681f6fd24f03e384f89c49723b960164703f74baeda59550491ef7c44e0d2a4ed139127eb84b03f19f942ffd90fdeee0c346f48c423d64ffd60b8bb66662e81dc6ad4f933ed402dc3cb2d5613b7fa332aae4f7ec88173b038f1d61e52a614df61850d23750769184807fa0b8bc9e39c5a12120a06fe33d28ddb8646b28d6913039108e9e0a0175a6eced11d1e13c8448d6be19ce7ad6428f979293b05b172c81632381203bed414ec1ce27095a037f411c583ea0f3832d88003da86a6e0122821dd7c6754c45732d7e229cfa1dc779bea7f47d82c516f5c9f3efdbe45066ab25617f64b5e59911d790e50a4402e21ce4013a4f0109346a93b106e00c34b4721bc5433519f2ce484122be5ef161cb59fd3562d9fb6c177c751a5946772ed51c4dea9aeba3908b7eef2bee1b4a6705ce80ffa4052cc652dbf47706b881d6f96772c57322c03f908376287f56c783cf3c2b8097db4f0a064b65041c288b6045b2260fc748a59b9860a999d3966021bc469161c29d38b29055f778280666b93c7931efb257f6bd1c291a28789356dc4121d3bcf37040ebfae154f2c399c14080a1978e1a6be841058684ffb630d07826d2357bb6cc029921070b46942385a0aa243831798ac0e09dd9d2edffa3c1d1572a5e09a5f52ef12acdaec8128461ec836820a70cd3e55eab21c9c0bbcc64638381c6283426b589a2b2809f7b9de10b1d74fe73cf42dfc46446b0c3175d686eeb387a24c9ea30330a74b96026e2477a436a7f522e5acab45d42230fb51cab8dc7c7c8e9670e533aa0e3af29cdb29483d3fb102c79245aeea29729723757d604cb4bce8fdde1f61bfa7329894db2baae42bbabc58cf1557d4d5fab32aa03ce930745e6409ea3e81d90141e2a6a47a514f27f62e2498a4020069140e380ebd9163b0a2c288e0c1c55655b2635b2ca7aaaa9381d16effb6da9d2e398a4b4287037786dbb7e91c8f59830cebe62fcee944032e3b093b0aa93382763c17b55e88ac1995e63ef56f0a28009c100118b1953b84fda551359b4329f34dc8b999e1544006a48413d902825bbf0b3fd70b9e2d0a9cbbdad762d941bb830f24dbf73096f6184db2a786f54c8e15e2e344347db8004c974491ce1a81b32bdbe9bbd3cd2a6471c8a7161ccd6d794ab04ffa082568bd259a1b7bcd96e20827092b4eb607da3f34288dfdd6d878f6dd3c2088cebb538e9b475b880f776ecfcef53e1b05d3f0616b203a7e16a02e48322c746960430482f9ed97c41f5ef3385c8cc78caf0f0c53db31941826d4004e263d471449fa1ac2fdad8422a964294121fc357fd6410f9f7ac3ade81ab5484379c44d68930d6729194c65688984a087490d3b4449a5ced925f479d458bdce660c212812f518d639706db13b7f9a1558e944dff261376b2a181320451f6b80cbbae3a4640361e24724a9b9c4a6a534c455859db3d5f2f19e875313aa003d556f4d70a1e50547871048756b42dc681110e8d51be7124182a3d2a06f00e72d6a5f52c0452b29b0867d95a02063181af1e5c2965d36ceaeef1d24c8d15da594ffb2179ebe39976a924e9b27a886b64be04676f0600d860f73a4a665595d1f9e8636e4f5b5772de85604f1bf4fad34e1c4ea00d48d35f89a90698a5edd2a4bf352e67ae2621421592e0e31bfc6df1de7c3c21d3e9cd9b07da377c089cf668114ad3ed4f66f296ed85de3fa2e91bfdd6ac8fbafa519d6f98b89f15f7f2f30dd1c059ab6068258acc7d35f29a018e11186d6cfb5a7af3a757909bcc41b88844256b7919f136c7628fe195a941d22e16fb40c78d949dd28a7fcdb75abcea847c7b73e5a6cf84523a11dde54e6df24f45c888a58fd21252dbd1bffb186084e9a6b7014ad0bab5b7d962bc24a0d7426d0d92ded6a8a75402728ed37d8fa61006e7d0089e195ff13f10bc275718cb14930715915e1853cc454ea2af53ea328e30851830a12d2cf8fbad6397cc45b5d97b2a35a5268d22f0f8009d1bb664283124fda276b36811ec240e40c617a3531824a66aefb40f7ff900296c44876d3177a9080534e52586e8790fec0305b94912944cede2643f1379668f17a321c2aea588cbba2dca548aaf7dcbe1222657776c105f345a6bf90d20e3e9dade9a6638eefd95482a341088607b8a003f18371b2a1d77d5305fa027717d1a5553a91d3e293d77ee5a036ecab52b90936933a7087eadae5aadfcaf4ef8c74491c2a9e6efd3231c332b0ba382ff7b10617b9a5af43829da1d8c30174b6a95e19a3250eeb28c9732b882436a35" + }, + "balances": { + "balances": [ + [ + "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY", + 1000000000000000 + ], + [ + "5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty", + 1000000000000000 + ], + [ + "5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y", + 1000000000000000 + ], + [ + "5HGjWAeFDfFCWPsjFQdVV2Msvz2XtMktvgocEZcCj68kUMaw", + 1000000000000000 + ] + ] + }, + "vesting": { + "vesting": [] + }, + "transactionPayment": { + "multiplier": "1000000000000000000" + }, + "treasury": null, + "democracy": { + "phantom": null + }, + "council": { + "phantom": null, + "members": [] + }, + "councilMembership": { + "members": [ + "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY", + "5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty" + ], + "phantom": null + }, + "technicalCommittee": { + "phantom": null, + "members": [] + }, + "technicalCommitteeMembership": { + "members": [ + "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY" + ], + "phantom": null + }, + "parachainSystem": null, + "parachainInfo": { + "parachainId": 2106 + }, + "session": { + "keys": [ + [ + "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY", + "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY", + { + "aura": "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY" + } + ] + ] + }, + "aura": { + "authorities": [] + }, + "auraExt": null, + "parachainStaking": { + "candidates": [ + [ + "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY", + 50000000000000 + ] + ], + "delegations": [], + "inflationConfig": { + "expect": { + "min": 0, + "ideal": 0, + "max": 0 + }, + "annual": { + "min": 0, + "ideal": 0, + "max": 0 + }, + "round": { + "min": 0, + "ideal": 0, + "max": 0 + } + } + }, + "polkadotXcm": { + "safeXcmVersion": 3 + }, + "tokens": { + "balances": [] + }, + "identityManagement": { + "maxIdGraphLength": 64 + }, + "vcManagement": { + "admin": "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY" + }, + "teerex": { + "allowSgxDebugMode": true, + "admin": "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY" + }, + "sudo": { + "key": "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY" + } + } + } +} \ No newline at end of file diff --git a/bitacross-worker/docker/litentry/rococo-local.json b/bitacross-worker/docker/litentry/rococo-local.json new file mode 100644 index 0000000000..ecb70c118c --- /dev/null +++ b/bitacross-worker/docker/litentry/rococo-local.json @@ -0,0 +1,170 @@ +{ + "name": "Rococo Local Testnet", + "id": "rococo_local_testnet", + "chainType": "Local", + "bootNodes": [], + "telemetryEndpoints": null, + "protocolId": "dot", + "properties": null, + "forkBlocks": null, + "badBlocks": null, + "lightSyncState": null, + "codeSubstitutes": {}, + "genesis": { + "raw": { + "top": { + "0x0595267586b57744927884f519eb81014e7b9012096b41c4eb3aaf947f6ea429": "0x0000", + "0x06de3d8a54d27e44a9d5ce189618f22d4e7b9012096b41c4eb3aaf947f6ea429": "0x0500", + "0x06de3d8a54d27e44a9d5ce189618f22db4b49d95320d9021994c850f25b8e385": "0x0000300000800000080000000000100000c8000005000000050000000200000002000000000000000000000000005000000010000700e87648170200400104000000040000000000000000000000000000000000000000000000000000000000000000000000080000000020000004000000040000000000100000b0040000000000000000000014000000040000000400000000000000010100000000060000006400000002000000190000000000000002000000020000000700c817a80402004001000200000005000000", + "0x084e7f70a295a190e2e33fd3f8cdfcc24e7b9012096b41c4eb3aaf947f6ea429": "0x0000", + "0x08c41974a97dbf15cfbec28365bea2da4e7b9012096b41c4eb3aaf947f6ea429": "0x0000", + "0x08c41974a97dbf15cfbec28365bea2da5e0621c4869aa60c02be9adcc98a0d1d": "0x08020a1091341fe5664bfa1782d5e04779689068c916b04cb365ec3153755684d9a10390084fdbf27d2b79d26a4f13f0ccd982cb755a661969143c37cbc49ef5b91f27", + "0x08c41974a97dbf15cfbec28365bea2da8f05bccc2f70ec66a32999c5761156be": "0x0000000000000000", + "0x08c41974a97dbf15cfbec28365bea2daaacf00b9b41fda7a9268821c2a2b3e4c": "0x08020a1091341fe5664bfa1782d5e04779689068c916b04cb365ec3153755684d9a10390084fdbf27d2b79d26a4f13f0ccd982cb755a661969143c37cbc49ef5b91f27", + "0x08c41974a97dbf15cfbec28365bea2dac713b7f8b14e2815d297585d3581e774": "0x0101000000", + "0x08c41974a97dbf15cfbec28365bea2dad47cb8f5328af743ddfb361e7180e7fcbb1bdbcacd6ac9340000000000000000": "0x00000000", + "0x1405f2411d0af5a7ff397e7c9dc68d194e7b9012096b41c4eb3aaf947f6ea429": "0x0100", + "0x1405f2411d0af5a7ff397e7c9dc68d196323ae84c43568be0d1394d5d0d522c4": "0x03000000", + "0x1809d78346727a0ef58c0fa03bafa3234e7b9012096b41c4eb3aaf947f6ea429": "0x0000", + "0x196e027349017067f9eb56e2c4d9ded54e7b9012096b41c4eb3aaf947f6ea429": "0x0000", + "0x1a736d37504c2e3fb73dad160c55b2914e7b9012096b41c4eb3aaf947f6ea429": "0x0000", + "0x1cb6f36e027abb2091cfb5110ab5087f4e7b9012096b41c4eb3aaf947f6ea429": "0x0000", + "0x1cb6f36e027abb2091cfb5110ab5087f5e0621c4869aa60c02be9adcc98a0d1d": "0x08d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d01000000000000008eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a480100000000000000", + "0x1cb6f36e027abb2091cfb5110ab5087f66e8f035c8adbe7f1547b43c51e6f8a4": "0x00000000", + "0x1cb6f36e027abb2091cfb5110ab5087faacf00b9b41fda7a9268821c2a2b3e4c": "0x08d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d01000000000000008eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a480100000000000000", + "0x1cb6f36e027abb2091cfb5110ab5087fdc6b171b77304263c292cc3ea5ed31ef": "0x0100000000000000040000000000000002", + "0x2099d7f109d6e535fb000bba623fd4404c014e6bf8b8c2c011e7290b85696bb3": "0x08d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d8eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48", + "0x2099d7f109d6e535fb000bba623fd4404e7b9012096b41c4eb3aaf947f6ea429": "0x0000", + "0x2099d7f109d6e535fb000bba623fd4409f99a2ce711f3a31b2fc05604c93f179": "0x08d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d8eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48", + "0x26aa394eea5630e07c48ae0c9558cef74e7b9012096b41c4eb3aaf947f6ea429": "0x0000", + "0x26aa394eea5630e07c48ae0c9558cef75684a022a34dd8bfa2baaf44f172b710": "0x01", + "0x26aa394eea5630e07c48ae0c9558cef78a42f33323cb5ced3b44dd825fda9fcc": "0x4545454545454545454545454545454545454545454545454545454545454545", + "0x26aa394eea5630e07c48ae0c9558cef7a44704b568d21667356a5a050c118746b4def25cfda6ef3a00000000": "0x4545454545454545454545454545454545454545454545454545454545454545", + "0x26aa394eea5630e07c48ae0c9558cef7a7fd6c28836b9a28522dc924110cf439": "0x01", + "0x26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da9007cbc1270b5b091758f9c42f5915b3e8ac59e11963af19174d0b94d5d78041c233f55d2e19324665bafdfb62925af2d": "0x00000000000000000100000000000000000064a7b3b6e00d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080", + "0x26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da923a05cabf6d3bde7ca3ef0d11596b5611cbd2d43530a44705ad088af313e18f80b53ef16b36177cd4b77b846f2a5f07c": "0x00000000000000000100000000000000000064a7b3b6e00d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080", + "0x26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da932a5935f6edc617ae178fef9eb1e211fbe5ddb1579b72e84524fc29e78609e3caf42e85aa118ebfe0b0ad404b5bdd25f": "0x00000000010000000100000000000000000064a7b3b6e00d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080", + "0x26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da94f9aea1afa791265fae359272badc1cf8eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48": "0x00000000000000000100000000000000000064a7b3b6e00d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080", + "0x26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da95ecffd7b6c0f78751baa9d281e0bfa3a6d6f646c70792f74727372790000000000000000000000000000000000000000": "0x0000000000000000010000000000000055a0fc01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080", + "0x26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da96f2e33376834a63c86a195bcf685aebbfe65717dad0447d715f660a0a58411de509b42e6efb8375f562f58a554d5860e": "0x00000000010000000100000000000000000064a7b3b6e00d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080", + "0x26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da98578796c363c105114787203e4d93ca6101191192fc877c24d725b337120fa3edc63d227bbc92705db1e2cb65f56981a": "0x00000000000000000100000000000000000064a7b3b6e00d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080", + "0x26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da9b0edae20838083f2cde1c4080db8cf8090b5ab205c6974c9ea841be688864633dc9ca8a357843eeacf2314649965fe22": "0x00000000000000000100000000000000000064a7b3b6e00d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080", + "0x26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da9b321d16960ce1d9190b61e2421cc60131e07379407fecc4b89eb7dbd287c2c781cfb1907a96947a3eb18e4f8e7198625": "0x00000000000000000100000000000000000064a7b3b6e00d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080", + "0x26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da9de1e86a9a8c739864cf3cc5ec2bea59fd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d": "0x00000000000000000100000000000000000064a7b3b6e00d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080", + "0x26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da9e5e802737cce3a54b0bc9e3d3e6be26e306721211d5404bd9da88e0204360a1a9ab8b87c66c1bc2fcdd37f3c2222cc20": "0x00000000000000000100000000000000000064a7b3b6e00d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080", + "0x26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da9edeaa42c2163f68084a988529a0e2ec5e659a7a1628cdd93febc04a4e0646ea20e9f5f0ce097d9a05290d4a9e054df4e": "0x00000000000000000100000000000000000064a7b3b6e00d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080", + "0x26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da9f3f619a1c2956443880db9cc9a13d058e860f1b1c7227f7c22602f53f15af80747814dffd839719731ee3bba6edc126c": "0x00000000000000000100000000000000000064a7b3b6e00d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080", + "0x26aa394eea5630e07c48ae0c9558cef7f9cce9c888469bb1a0dceaa129672ef8": "0x319318726f636f636f", + "0x2762c81376aaa894b6f64c67e58cc6504e7b9012096b41c4eb3aaf947f6ea429": "0x0000", + "0x2aeddc77fe58c98d50bd37f1b90840f94e7b9012096b41c4eb3aaf947f6ea429": "0x0000", + "0x2b06af9719ac64d755623cda8ddd9b944e7b9012096b41c4eb3aaf947f6ea429": "0x0000", + "0x2b06af9719ac64d755623cda8ddd9b949f99a2ce711f3a31b2fc05604c93f179": "0x08d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d8eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48", + "0x2c5de123c468aef7f3ac2ab3a76f87ce4e7b9012096b41c4eb3aaf947f6ea429": "0x0400", + "0x2f85f1e1378cb2d7b83adbaf0b5869c24e7b9012096b41c4eb3aaf947f6ea429": "0x0100", + "0x2f85f1e1378cb2d7b83adbaf0b5869c2ff3ae12770bea2e48d9bde7385e7a25f": "0x0000000002000000", + "0x3195e99b3353c0f2dd3f53c10740793a4e7b9012096b41c4eb3aaf947f6ea429": "0x0100", + "0x3195e99b3353c0f2dd3f53c10740793a57c875e4cff74148e4628f264b974c80": "0x00000000000000000000000000000000", + "0x31a3a2ce3603138b8b352e8f192ca55a4e7b9012096b41c4eb3aaf947f6ea429": "0x0000", + "0x39e295d143ed41353167609a3d816584": "0x0a000000", + "0x3a2d6c9353500637d8f8e3e0fa0bb1c54e7b9012096b41c4eb3aaf947f6ea429": "0x0400", + "0x3a2d6c9353500637d8f8e3e0fa0bb1c5ba7fb8745735dc3be2a2c61a72c39e78": "0x00", + "0x3a636f6465": "0x52bc537646db8e0528b52ffd00583c91042e09c64a13531040cd381d55d2e3297c94b9248bbdba8a12604680b519cfdb6f3293a94a689a413bf2eadbe912ec487efc84861bce61587e4ac9dc15a7c6223d1b1760e702e42fb961e0d1bef86fbda4eddd6defbda54c29a5c914ed112c1275e4aafc01d41d838495eaed4fa8921a8ed3fe86fc5314257fde86fc1b4e10024a55822770d5942a7f8b3864ccf7244864520efd1d84805205b50f6a1d8d16e1aabd46b976f16fe59f22d7e5919428c4814784a899451c27e6a0de22de3a20dcd9129a3aebce96b2d45ded4ff8554fb5a1f6db2f399d410828d5fea6fe726a27f4fb07f5f64ba748bfbf6bcf2ffb35ce27f297afbdf65cbfba6abf20118d72f8d5a0e626bc6540e8a956fece9676a8fb0b42408929d72ef9f23d152cf4ef2f4aaab288abe410500143e5883453ded803843b9bb2a57ebf5cfd1a654ebffa79b85909ece0ef3aee781dbffaa3e4f12fcff82372ddea31cbe7dad52804b5e72d788246c7afda730dae5cc976d111c92bea73fae5bdff4ebf366feb3a3a768ffa6e93ed0afbb5bdbf4dbfbaf7f73691abd7b5eb7b064fe8fad1f17bd46fe2d64f44f2dabdc7bdeca96dd7f86de2564fdc8aeac46dd7db54fe5d9f71a7321db59fefef39b3266e35819f139166656fbdfe16d4e8f842d57ec5917370e5ca7fdbc5ef49707bf5b5eb6b97fff6ebf25f90c846833ac857e4dad52fc5916b113f3d3d3dd551a9ee6b2292d77d16c376f53348c466d26d5773fdfac29c7e6df597e2d677202993c9643298bf6b8578f55f1e47f1f4c1e3675101e1286b3fc7cf71eb40db3d6358f9c7b0ca7ef52f4f2bf1b62e8fc7fce3579b9945afdf0a31e23235ca97f2f86351d6ef4c2dda6a1416f8a5545226abbc2b84ebd7c8d51f01e1091f8b5dbf598da2812bc48865b5c884cadfcf200aa1cc08cbc46dd7867543506a6e36bcad5cbfc67effede71ffd65bbf63d17b976ed0385fd8e423f9153ae5d1bd44acc46dafbbdfe64bffcf777c16d577f50bb28dbd51f241cc3daddeddfedcccf55a63a47f8e5b3d36dd7fe8244988e5cf9833aa897a79d190c6ffbc5fbfdfb5e8b1cf27baaed17d77d4ff68b7fdff36f437f1f386484f2fdfb1d24d294437e171b2422a96c97bfd71f57f73df931c8b5cb7f41076ce50feaa05e90487f5007755007b5123353e12dcff8d5df5b0384defe84fc0b12d967b0c80b32994c4a5dbaed1ab9eaeff527fbc5bfbffdeadf5f70dbe51fd42cca76f90709c7b0facbeff7f772fab5d5dfe32fecd7b66b9475dfdfa65ffcfe39fde2eabf2011fea00e6a2946f9518f946a539d235cede76a539d23fdf2fb2545e2ca74dbb5bfa011fea6633f7f5007f5f23825faba212835b318de220947aef273fdda316190a9fc5fbf7646c31c953fecd73ebf4dbf7626e54ae5cf59215bf9978729d1d70d4189b97a4a427eaedb25ec2fe8ed4fb8bf9bb748c291abfd5cbf764c18646affd7af9dd13047ed0ffbb5df6fd32ffefe9c15c2b57f799a127ddd10949817e0ed01c29dc9a0a82357f7b97e6dddcfe9d78e09834cdd0ffbb5b32eccd4fdedd7d671a7ee6fbfb88e36757f7996127ddd1094988d78fb0ac7b0f2bbfa357e959ffffb35ba2a3f3f907e71e50ffbb5953fa75f3b9322abfcdb2fae234fe5df7e751d772affd7af7dfee5614af453370425660f783b42b8bf9be7ef6db8ef03878c50c7483f7f3fffbeff82449c72d81fd44acc2e6fc3fdd570b4740972e0050a070b1c2a70aac08902e7091c2f384ee074c1610267099c2d3848e0188173044e103825683de1c870a4e0e0807343cb0e1c15e0a4a095039c2c3852e024810345ab8e161dad395a3268bdd18a41cb052d355a6eb468d02ad362a3f5020a4c00859653cb8c1615ad2f2d2f3ec69d5c4c6a062919a49c52667c367c35a4cae854d0a5a055854d0f6c786073039b33a82b281c5037a06ab831e3a60c140f5077d484512346cd18328c6c9259c899b4428221a79052c8282418a90279857c425621bf9054a48e905fbe3cba276417b9050e979b3424144647928b1a306e64d28b6ca2d57453c58d143751a04e80f2c1e6a9cba3b3c3260f14161b3c6cd2743ac0b1223587b6464a8854102920523fd8dcd0c241ab8cd6a2b76019f01bec0687d19a828f6023b8081e82896024380bf3c03bf094a418626c02128c00861078a0252603471e6044729140042050a401957b601d86244048129c2f384de00c8103044e0f38587076c0b98263034e0d3834b4ceb46cd04aa3b5c60b22689dd15a418b8c16182d2e5a57dc90b9f1723343877123c6cd165dc60d930d18365ed4e46123834d151b303654d84c6123854d148c43236103c405588c9aa69a2f6abca8b1a235464b8c9a276abcd474e92f9c4b0d971a266a96a829a28688bea366881a216a82a8d9a186871a1d6a72c0c901c704383ce0cc80e3038e0e3538d4dc5063434d0d354c3532e0a000e704383fd42ce10881a3440d959a293532d6132b0f561a560f583c60eda0b505cb0e160e5837609d61d9805503561c2c395874b0e660d5c1ca41d780a5839699161cad2e5a5fe068a9b15253029c296aa4b0eea83141cd959a2a3844d4cc50d3438d0f3558bc879a13d4a0a0e9a801a2e687d6414d969a236a8ce817301d3549d42051b3a5464b8d123529a871a2a6891a286a54c037a891a2268a9a296abed4545143050b4d2b8b16162d3035606aae60d18065863503960c586fb0dc60c580d506ab0c8b0d161a2c32ac34586ab05cc05a83f502160c582d609dc162416b0c6b05ac312c31ed84d7c0fa82d5052b0c8b0bd6162c2d58339619ac325864b0c66089c19a8205052b051e8403c1628215064b081616560f0e064b87eec2a2a18560cdc0b2c2a2c29ac22a014b8ae3c03b58e5b1c26395a68d58d5c102637566d50306634583151cab19ac60c05eb09a585eb0b26061c1ba8205866505ab0a1615ac2f2c295851b054c07a82e585e58413c16a82d5c5956071612dc15282b585a5859544cf8085845be9245841b08060fdc04201eb042c1f583cb07660e5c03201eb0a0b07d60d2c1b5835b0985832301eac2aac25966cf5c43a603b563c58ddb142b3dac14a07ab1cacec58e1607583950d563558d1b19a837504cb88951cab385845b0886065610dc13558c960f5c6ca8d550c5a5ab466ab3656655a3558bda0d5c66a8d950b566aacd2589159a1b16ac18a05ab33562b588d59895939adcc5895b1226335c64a8c55182b30564dab2f565eacba58855971b1da62a5c56ab6ca6285c5ea8a15989515ab2a56547809facceacb6a8a9514ab285650ac54b04ac1ea8995979513ab26565d565c564cac965829b1dab2d2b24a6275c4ca8855112b2256595643ac845805b10262f5c30a05ab13acb0ac7c58f5b0e261b5c34a87550e2b13acaeac7058ddb0b26155c38a86d50c2b2b2ba6950cab2aaba51595d5945509565256b2f029cc23c4c39708d3843d0879e04784778468c21d843a087310da11d611e220bc417826b4415883908e708e508e308e9006a199108e7006a10cc2374237c218846d846542364218842f08d7085d10aa11a6119209d1085b10b2203c235c41382614133a8566846584648463b40a4231c2304230c2a6f08bd08bb08b304cc845b845a845380bb308b108af08c1845684558454845fc2294229c228f88e108a5005cd449882de123e117a099d089b08bb845c4226c2254225c22da19630891089f6121e111a11161112110e110a1106d15c74172110e10f210ac2138458421fc21e421ec21d1c4ba84398436882f08acbd03c0871086ff021421b9a052e4458434843384368c58de81b340e42a65086b08a17115209a7842508a584324f42f5a4c2439546d503150f5477a8d0a876a0d2812a072a3b5475a870a0ba81ea8cca06aa1aa8e850cda1924315878a062a332a3854336829543250bda172431583e6a26aa39b509551b1a18281ea05aa35542e701b546af80d3c862a0d1519550b542c509da15a816a8c4a8cca496586aa0cce818a0cd5182a315461a8c05035a9be5079a1ea42c5856a0bd5ccc3a8b25061a1ba4205466585aa8a4e818a0ad517d5142a295451a8a050a9409502d5132a2f2a27544da8baa8b8a898502da15242b545a585cb6016301a4c467584ca085511aa215442a8826875993cb80ea91ec03ac02a3c1ba413a8223a283a2f1d974e897e0295050a0cca0a9414282fd20b9413a826c032bc4bea4bd784d6b4f130e5e0b470754c313a99ec426ad1f9d0f5e039c8a77ea365d0316837641e128756989617ded444b817de857ff126584ece846f691a3812aea5c5b49367f11f1c05ee839fc0af781567f225a7d2637c8a4be938ba0dffc2650d837eea3c1a8f4ed33de832cd46d7d1687a072d46e7a0ed681bf41c2d47afd1661a8e3ea3cde8315878b417dd5443438751e5d192a365456b06ad383a8a86a2956885d14774119da587e8201a88fea151d027682ced43f7d03cf40ead43e7d026e82b8d43dfd036740d4d43cfd0569aa965e82abdd4547a4a97a0a5b48c9f380f161ccc033ec339b01a9c068be116f0193c869dd80cc60193b132c35b7017dcd4f1c058f0156c036f612d7c859300019422a6816768a1d582264442257037785c97557874ed43474942200425c9100b42421efb1227434242a8e5a126214882e4c405158490940c193159e2848990508f16179e161330fc682dc102d20a4e869a28b143432a083d411242626105264322e8696dd9a3264c92200d2d111a1a5241845612fb4405274c8460301a72a1488809948ae464a80518924ce05b48ec9012274f9c082551e2e4890494d40f5a472c79a26468c98f56117b04c310d1110c43472c20b6883862d20018aad8ca52426b089e9610fbc29013560b88fd615950f204ca904e0b056be4c20a4c5470f24489101328752804496037ad1388d0c212a4e5c32e612284347464e482921ead1ef66888091213a3272c20b9904468052126506a12284b9c24313a0184160f7b7434d4e48396096a5a576e5824272e3c5122a44292a126372d1bd6a885165a8880aa55c3aaf0e489111421284c5838321a7222822742300c1101a045c32e1972b2029323272e28791285890b45434248464fa00c19bd5a332cd2d09190953d627204830a434321106202a5c2a0c2d010acd562daa3212417a01c3159d26ac9405b5576c8088ad0901113178a868c848e5488022584d6d22239196a418528505c2d2a7b3484f4248a909093273bad29cbc25112168460088110005a25386a32e4c449121694084169c18805a1254e5c781202274c80b4a4203979a244a8a885252dd91eb590c428091421a3274ffb44051f3779ec119293a1284378ec0a4e982c71320445680829c912264b9c245102e4a6073bb4e489920f6e78b0464f54381a3aba638f905c8082e4c29300dca069c185a3a32400b8d9c126414ab244c8c913264b86908e981c190d4111e126077b3464f44489100c484c9a30094192264c924449f23776ec1114179e18ad2004c24d1d7b64f404e9e889039218259940ce0d0e56044ca054a32122a327194041bcb1c10e0db930e40205525832b4c20a495218c04d0df68848c9100b4ae4d82324274346432c3861f237713861a282ce8d9955c2e4c8091323a4178684606802054a1221a3a1254d98b8002352f2a4096ce7068e3df271e3c62611dab969635b104a8294644912a4a108ac6ed8180193264998203171c2e4e6668d2552f2a449088486905c5032f4c210eb468d357ac2802f6895c3e634268f307595bc9dc9649595bc87c6e1c0e1c0507893dddd6d63d336cdc3d3363b5dcac9524a9692577acb953c576a9257fa6ac5712038c7ed72dc72dc4ae6965b6e97437121486f3611df656d77355fb94967e99ddab9a91b77b9ce3ee5aed7685ea32dcf9a9d1a6bbe7277354e2dafb6abada6c99d2ce5ae94db80f5e4ee7a08bc8bdaddad5bd7d825fb328af786019279d9a54bdeb695bbdbb6b194d217b61eb3e4ae57d77dfaca77e74ab9dbb12f6fd0f4dd393bd53af3ca6d79e7e6bed2d7d704dfd42eef6eca97e5aecbf5399d19b53b17e5ecbeccdae429d9775dca759feb72999d771bdcbd61d697d3bbcb7201bb9bec78db6ddb7cdb6df3d6b256ee825272b7b3a574dfad9bbecbd2d77d756e5cb52c15e07b3399d97da7f304bddd5df15b29d999a5af644f4a3957b5d27b4ee621a90448e739d759d376aed7cebbadaf8daf6f27254bb9f293db2699bbe3eddd95ee423cdfdd9a9add4580b6bb3e3d88468178db36dfdd367f6dbbee285ef675ffb6ddddb5ddb004afc6d977a7c62b35100477c1cfd7793bd5f2ceaa7458b5dd92b0f932afd39daef9ae4fdef53d80fbd6ecb6a0fbced5d6dd00ceaedaf575b929f61176b79dbbbcf9aec6ccbecb73b59d6d7997a7b6ebabed6cbebcddba6a3fde9da26a7f7c77e3ddddcd779ddddd572e2f4fdf2dc7bbce73b6f35ddfcde5f27abcadd471b9eeeb726adaee4ef7dd0238efb24be7dd9879a7bbfbf4e9534ab9727deba4f49572d3344d5bdf7566d9bbbe2b77997d35cde73aafe4f5f565144bc9bcccabb13651523aab53ed73d7bdf3e9cbeb2bd7dd775b39e54af99ab66d2f09e0d352ae749752a6dadd7f0019c08a59ca1fd27d5bb65c2f9cd3359f13959abbdb52f64e67b98b626ec6d182a384df6cc360f4a485a116349c10b870d47374346404a585274a80049064c8c8074e0f7085274d7ab09a0c45196a22f4429216845670c26485159e34f911820fa32127432b006005c310919012264d42e00214176b68e848a885274b9c2431a2ac254c9a24892274c42404d0d5b3029323318a932177ed084849908e84888c9e880069c8098f084b9c24111a324a02a585274a4800a14912254f9ab8be178696386122e48449121694a8a0c2935ff908c01ae0c91323a1254346434b8c9e0c3131421200b706188af244c990915092a3254a868446207a956000284a8646583214020044f8963819820225c9ced7d36305117a2c69c284052542484d5c48a2c2d012201fac01546062341445080123945082018c8e849e204181c148490838300c110921bd30e4048423a423262f0ce1ec082d304172e2821125529224044d9a3c31120093165a78a2c48572f28409929224474e92182109211925413a1281288912254344ff2ac1003fc4c24e4b05241784909c30318222a4e488490b1f80d0630df0021315868ca0d00f69e8a847cb28c950132542432b24317a8274a413c4002308196088284993107c48c24be885272240125ac10913168e92b0f0c1d60208519c0c39ef08424e9e3039321a8a22343464a48290d113a4244a9e3469924408e985a19d284e86bc002a1b7a959492942492554a5252fa906c52d296a4a42159250fc9765a5292528764939256496943b25c92d24c4a4a9a4894384922516225159255624d2929c9951c49122f12254e4a4a5292ed1c92554aea2d899392943849a991247152522725311225dea4a4a424a50d89122f92245662244a9c9494a439924d4a6a249ba4d44876916c525292122bb1d254928d6495584949c991ac12235925a54652446ee1dde5168e926cded331e9e43dfd1c8d492fded39fa2ee65341e74b18332a210438a136371030938d0d0b28134a9bf80e2891cc4a4f90126a93ce33dfda32ce38567ec14caf8654c6117fe3cd453a99203eb9e8af655421e6285302ddaa73a87589ffefe4f9c42ec08fd9e3883d811fa51e2046247e8efc4f9c38ed0bf8913053bc2fc71cb5cf127d9a45498767cd811fa7be0618a4a26abf2b0b9030f4ca353fce909a6fdc859b81f3bcb158e0a930b46a54a10d8c46147e8bfc1059b36e4c0e68fed657b7aca230d34c2f8218ba45498488051e1be4a10d8946147e8aff2c16a903ffa19ae410bd4706388263560eb651be3430ba890810c3a600bdbe894ede9e989a354aafcc06615176c2eed08fd54aa3c6c52d911faa7a89e9e9e9e60db8ff24ced9f3207dae86e0fbf969333e9ee9449ba3b65b57f2c10fea09e54a97b278b123bfce4d47e7e2fb59fa75f5efb81f4abdba6360bfb28dad5f1631f3c767777ff0599b20d478821eb8e79e28bbaebe3749b086f0c981ed85086b988abff1515f74ee1275897f50163d7a554a723cbea1e5155f92e469155d25ddfef0ff2e51fbc6724a1ee90babf5c03a57ef76dfac5fd7e4ebfe6efef3c4fbfbedf77f5abfbfd9f205e272a554edcfe1395ea1447ae3a47e66f3f7feb2ae928df53e2c224d1f65dbd75227feac054bb4a1db0d49e9f14532295d457d91d413ec3825c8afe9a383f252ecc9bdf82f39be2d694b8b005e707f5a773c47bd47b8ffaae1d0aee81de110ff4e673ef75df6fed5e8a3a1f2dc27df71dad5f6ad74f872db56bf79e7f44a8f7de931f4ad49e13b9ca91abf60e16f93eeadfd1227eeade51e8fa51a211f5f2b92e78846b47c7ae44f28f94aa7684ab4747f91aed505c25d70671c408b71fe7fb91aef26b508f1bd539a2c99f5447be8ea447e66bd4c89449ac846acd0c6f47d85f903b07a7ef975e8bfcde1475e66f5d71ec9ecf9aa8339febb672255f84eabffd8af37bb5d556db7e357e5fa3b2d8bf89b37a93ab84fc52fc9bf29bf36b917f12e1a590df9b9b2bc5748a3fb59786ed12a13a55d2d8cdf0dc655d6ece3046ed9ab333c59521bbc8f505af886bf7c054bf9fdfe211d7fe061db0b5a344fc5d1bf1facc47e26ad13e55ef1b2cf23d0af50b3a60ab4799a2827c7e2716f9d35307e47f68eaf7dd7bdefc163c01f55d8347a491eebf0f6acfbd67d1fb4efcdec123dcf32f58847ba6bb3efc41fd8963535e1ffeee3d71ec285c2df23c4624aefdfc4a1ab71cbc62a0a9f2b5dfca4ec29df130abda6f13d0800e67a4bbab5f3ada3f8f0b090b69b86d8e3981f46bd4de25ab875d1734e2cde5de1df0690049bfe63641a05f5c67ddd90e5b7e64539d75dc37ea148d90beca3d94ba7def23699bc895a75fd3a8193c2254b7e7b6efdde82e90a55e074240290b0da505b5a789236fdf224737511347a5aa118ddbef6ba0918dea1ce9df7ea3630cb57fab4647ae286822fff7ab457f8ffb887f3f7884357a84bf73fab5fdfc1d6f1377a64353d5c4a9fd7c965247ee3771c7844126b4f11c3c81fb31862723fc1a1d5b4ae5dedb96d5ed3591dbc420d7a4b49fe968f0969942f9ecb195b09da83b3b810cb587a83bebc14c75d59df580c508d29433755402a3d5d105137851f7556c25f42deace821853394cdd191037542075673f48c1e0092832cad4222475ff04d419216a5152aa8e48318041ce107544da328417833a22d1108359c7a334a21840154e753cfae2543999acee3ed5fdbadf3c78455ce57b529c92ce226aa8138dca11f06f3ace8cc8526511f9fc3d2ad5f92cea1c996854f9138d3a1e2955f9736bd13e3d3d8d4ab57f66a94c449a2a56b17afdb5f8a34e71a251193ce1a3dc3045ea235ffb835abe8b44fdf2bd6ef0047eaa45fc34a98e117eff13f89d22793b2b02888ad475d2b13f0a577fa52a5617c5dae2561691bcbaaf34b9d36cef6d7b0c760e91f5d95a94edda7ec16e51e4d667fb163180816dfb6e856cddb6e756c8f6cbb3ade11585276c55bdb7bbbbbbcdbf22575ed507f58adffaa8bec50f84a907ff7bef3f10a2be7beeb7ff40a8fd1cb9aada57f5ab54dfa28a05df5226559f6e54498bfce969e497a3f64dfc89337552ed47a7fcdabb287fc1235b060e49758ae3d49c2880caacce17aa3bd932aed4f9e308aad42675da824501d0d842e2d05477eace7058a27afd4d51f5f4f40404acd3226bc1e089293490c9672db20f6c4062872c4600c8e244930c09cabe51b5c80a80c616b2280aa0327b610475be9612ec1bb08ecaf60dd8d2d87e9213218848434a1a990cc6511915998cdfe908a5fa37b82006566dc020893ca63c3dc1d6a67a6b575ca9fdfb22d471690d432bc4e8a76a91afb43378ff9574522a557c60f3996a6035f4cba6f6fbc0690ac726956b6857ffcfcaa052992c251cb986da3fae0c6a7f4c7ee83d3900628a21a6f052462683cdf71fc3da30176592891b8c28411157c0a854f181f933d5c024952a0dd39e690130ff29322d0016eb92827f6c02ded3ef4eb12e29683f692cc87bfa351aeb92c27ca7b1f79efe497fc69dcdfcc7755a1dc80086163ad458a28d313866840b53e2618c2b8410420b3229a803b630f9e34f0a2f93c1bc867e89e03dfb2eaef75ca91b429254e2964fb894e27ce68dd3e67c7f6efe36677f0c12694d74701a51b75df3a5c8b5889f8ae4a452baec6e81123c3c18421cc83c128f615821a07ffd5a1d78da7b9ac815f51ff8bb42bc9fef79a2521dbfed89b6dfff7a557766c3952ad7677eafd80f8adb7722d77e8e7b50e4783fa8393a7ecf5d31e34bbdf7fcfbc47d54ef7b47bcdf0880bf74e4ea3e83452f50298114592d1a45d0033c9eead13a6dd96186fafd9152fde8b6aba3e33eca5b712b288e2fd4068f80747ca16e1f279ee0bde6711f2736e7edd760918f8e5cbfdfdfc022a8baeb13e41f91a53a46bcdff77e2911eaf71b2c82faa545b1baa011ae7a9488fb468923f77ca49f63b06e5ba72845517a2ce7f09884f2c6639652056f0f10f277cebeacfdcb714709fbb92f0480b72ea4d898e18cba3d58567b5508776683536559ddf71a485c1212f96f1d595647ffee411c952b3f8328b094ba746459f55f318aacfb523ca2aafb2e8e2b64949216a9ea8efb545754127609fb0c167d51589db2ac9bc2a2700039c89eac3fef2ee762128f4928436fe5da4ca05fe37fd1eab867c897afc9af9afc0384f37382fa35720ee8d718b2d02fed87f44b56ed35d0afadda232123974cd58254cda68e41823a274dd57e47d334ed9747a3447bc66bf05446b6dfb636d869dfdc7bf7dc6bee1ad7791bf72e46e1ca71bff1b6a7dcdfe957aea30ff0e716ecbaa2d828b74d7b6f3df9792bd5eef7e4c76d748cd5ed5d9c73ce39e7ec8ab6a7a7a734757bafbf4ea323d78e16f9f7ee44be8f12d6265226a58edd176d69a43cd5281cf8f2a74884fab9bdd3311cc771ec641147a50452aa5114ad6a1f65ab474a55a3feec2ecaefe4a76811a7a9285044ea22af28aa63846775fe0489cc979c38728ffa2946e93adfebee1ef528b1a36351acce7717c7edb9a3a352edd8f362557be7446f5e20fedc077951ac6e1c0a5ec723a5cadf89455e376eab148bbcce77d088ac93126d4764ddde41231b25e2775a14aba387b5454fb5a28e3fbf7f8b3a9e8bfc1e6fcf45fab77723fddbf69c11d207a572bfa01124957b6e4fd8fcb7f738b143bd3bea39ce39ff4e34e250dd0735aa7bcebbee3971ece82e106fb0c87c7f0689687454aadabbc871226be2c8757f8a633f8327701176316cd7bed2c72a2e639880cb0abdfadee77bd3df63f067910d03f3ea4ebfb4dfff15f2fdd46eff1377faf553f73523dc73cf3d8b5b19dc225dd82ed477bf34c83b71a75dfb28d1e3c4285c47aeddb318856bd73d276e95cdee29a6455e758a78e567faebb3cf95133b4ac4bdf7122ce222c0bdf7792a54f70c0e6d8fea28d7aee5c491fb0e4547a58a7a163b717c007ff741ce627ff72d88a2455efd3b715b5c6d137daa26e6b46be77cfe4dd4615ac455a339edda1f405d9008ffc6738b27a5b82424922f421d2baf90f1a74ea5690455a737b91f251d93aafcb18bc0ba5127d5c2cd5f91fb2962a0006868f104db97e218ab72d4be89121075fb31a9cedf4dc06e01c69dd910838ac475a34ef68d5ae44f4f55a35a62fb49fec41918476563ac4e3aca1fbbea1fe45214a1ee2fc8812de30a6ca528424d62a5d93dc6db31c4b03183190bf2788112b005bd6d6f5b2c0873dac56f23e68e2f956b8b4c0b8d70fc20412a3fff907ecdcafffc2e122aff08c406cfdb4fc97d30415177c674441dbf36d30ef51d0848f7f4f77baa0d2432b3324690ad4b847f410584a34bfb20ae9f7eed181ca8d47e1286ececf4cb9f6b57ffb4ab37da5294a29184791e7f2b8e5c81b4cbd5aefe0d84a3abf607790dfbe5544963f761be5c21daefcf15a2cde90bc29083fae9fdec7e723fb99fef718fe2e64feee77c9c1592d32ece861d6a504beefdeb8a59a3a9f6f333c8bdcef65ebbea6cb4889fea7602eeb58ee6b48bdbc429b5e95b3cfef6eaceacbc61837e62e6b3ae1667c6487fcf5de45f50861ab4ba332f6380756756d2b08b5cbdb9d59dcd6045ebeace66b8b231107583a8ec0eae8ff87d20dc999533ea287736831175e4f6fbc11567384195bb71a95d9ffd967578cb42d8ef7dbf46e9ea97bfbb3b0d59aabb4b1e8f792b831d5042994c26851b0557eda0e6bada7bdb81706756b05411aabf27bfe557af90e540b833262a75eb564ffbe40ae9baf347aeeeca1532ab7ca7a3bf0b391529a7f6bb381a15ed53ed47daea7c6f038fa8aaeffa8cfedc1ad15efe8227f86f1fd41324d27d9007b58b5b3bd1886bf497bf893a47b4ef6f4a245fa3bb3efe5ba7b8758244246527ae118aabfa3771d5fe910362181fd91d54ff169db8aa535e1f7f07517055a7bb3e4d398ea5185f2aab6875d69e7fd47eb3909ac8cb32843bbbb2a576dfeff5c7e009db73df8923f744a8efde5371f51624b27235ff7b7f4f13fbbd94a893faada3524dfd278edaeb1841558d16a96a14a4aea9ef5f34ea4f05459dd47355bd27bf16c7eefbbd1675bc97d5eb82464259f5bec5aede07758b5c3d074f483d28aafe1353af89fe81a2ac9efc3e71735041d1ab37bf4fdc1e5450eceac9e69d9bd45245fc5455af89fd9fb8785450dceaf54e6e99d239b25c3c3dd57eafa3121899acf67fe2ae5135b145ed5522f8410e8ab37a2aaefb44fddd8ffdfb0e01a52c3a074fe0ef3a221de880a0ba0b646c068bf07f3f8346fabbf752a2f71e7f29716b50bdfe52e2e2a07afea5c4b5a37af2d344ef53e2d156a3745dc188abf7534af5ded340ae127abf202f85de07b527c122bb46f5dedb1942ca4b893f5513378cac04d5e3c45156d4375864c3c864d5a346457b4626ab48ac0afeae0f6784f455f0bf5f1005289c387a45fd271a1599507b7d508fa4d5ef3dfe3871ec8a7a4f34fa1e49abe02f7844a86a1fd4a058f4a36aff894526545e1fd47bfc79da73e2c815a5d15d2028ca795077e2564edc6f71eb268efc20832b579386ed92b4ba12c8db174f0321ffb64bc7db5f9e7167d57f7f9f5b21f3f7bd29eeb4cb7da839ccbd0371efef72a0eefd7f48e8d74ebbb4f70fb2427e7db4f7efc4b07bb4e744ae7bb40ffb35e2547fd77656039aea8fb342b8facf9c7669e256225d7766c310f2837ae5ea6b5733a8bd8e7cae5d75e4efcc0622ea3a6d01a3fddc684ebbb46f8a5ca5c8adcf7e522bcd6e383cfe13b67a2c8e390289ba0cee6e502f93e71c215b605263e62741227567361451b75d122c9235677df62548a4889f6a8ff5e997e009a24dbbfa27b8cf22d7158bf8a9f24f9088d31573d6a77f450c843babb2430d7bac90ada8bab32a65eab6ab5fdeb68a83fb584cd59d55e941ddd5a6f4e6dd52120f9662be44f2ea5ced29227935c2329914915c567e2999c9789eb7a0dc9fafbd37454d9429847362a09f8e4a557e12cc7d410df8378d29c162f21bd62ec69460f2837a1da87fd4e8a423d72d8570ebbee72d9802bfd35812ac4a972213aaf60c9ba2a423d7f99a387a9ddfa27f904f71ab8b0d5b300587f107b514b7b6b8b06d20569249dd8d83776442ed0727c0dfa216122c29c1f85dd40243ac4a0c30f09b005382f107b9c760112d30f037d5428218f693600b4e80698c61fb9dc4ad016f9bebd74a8f43ffa4c87541ff0a7862eee052f757f498c10760618010cb0f6a4939ea4b3c22db2e95c70c08177c805295922a3137c0db0384fd9e53fdfd737636f4b7a94e016f0f10caffe9d7c805e9d718d6f9f3a7ce9f4f42bf649df3bf5fab05953275fe00a9b373eafcb05ffd73fe9cbf3c9312edec062a76f886dbdfe17e831050aa633fd1d2a2a4babf3c4e894236c2db13c29d2d51a93ba3f246b3bed692086f79c675b269978ef3eb382d32260c32fbef409d6ca3e052775feb3406a91b468e1a5e269321011b8180b330723c51c70d53f7bdb9ce90caceb87e6d48a5bd78bcdd29a66c45b84e6d8527a1a85394ebe37454f2a114ee2c0554eaf8ad5c212b848b18e01156e1a996677bd4ef7f73c59db0f58c1aeab853fd7d8ceaef1018d2af9aeaff2bd84242d7d4f10322babe5d4eb4fdd7aeb9da76cdf1ab4dbb1c056e1e831198bf7d4ebf7a52a27efe7ea639edf2ef96fddac4281d017eaa4d837001fc1d6c30c2ae6390ea1f8413f03c005821fe6d600468af4bab5e37100559f9b75fb088d78d1679e59edc9de2727a7b239dad5d8b27df97f3293d2a80d089ebcd068ff73d20edda77ed4aeeeb683f7f026bd32e1d8d1699613146959f42bfbaee6bc0817cb61fe48031ea3e04fae5751f49bf56cc1a6fd4fd262ff46bafc0c67d838a94ad61471df70c95ef4c9715f3821deab8692a900798766d9d6205f048d3aead52ac401eb2766d65a6babf4f42bf58ab3a0ea915c863d6aead2ceeba284f8b5a361a2eef3098b0a68e61dd1914606af8cad68e84a7fd095c1b0a20aafc09450d3584bab314ecd0af77b0c8c82f7fa3926a4c2991f6fda3f673259d220e19a1f6e39c2f5fa34493723fb99110b3033075c5ec804b25405d313a485355daafafb8ef59b56791d7259f4123b28e4acb9dcae91757ede587fdd2e937e22a5ffea43a4d8b6654c6a83ba342a66aaf857bed3fee6ba085696fd32feda798e3540bd3c3383a80703e952e2effbbfb0a28b8782aee39518edb6b2f3991ab0ad254ee3715cc51b5e744aea25f9bb875fb35ca473db74546f9ddf74ba3e3f628aa6344fbeeb5efe8d72ee72a5311cad728d1f6dc3768647b0ec729dc28d1f6da8fdb77df19d95e7b0723a0d18d72346752e945ecfb521f3d1639640ee7e7fc0c4a2a89347313cf3c6e9f7f94b2ae7bf7c875a3236adda5bb7bf7c815b574dc5e7b141db7f73ec8477eafdb524dd47e2cf24aa4fd9c7fa454643e1745887a144a24da9f707b6f0d109671546b8f9a20117f4ff447c98e72b86ddb136dcfef85531db93aebc24ced1dfe8d8e44fef29912693f37517b16e77bfe3183fe9be8cf1afddac5af5dc150846358ddc3712794cf39d06e8fa41d52e9c25fe5615dfafd3fd0edededed40edbf2934755127059f745d473e7f0518b6de4329d0b00fea2456e20641b86974e4aab6dff513f1bf768a12255fccdb0960de65e69f5432ef6a9ab6ae7ddd8fd3344d7ba9695acf95e2883439e67ef052bf628a84ddf79a9999dd7bedbbaef3bcaef3bc6e13919a88e7714b4f49707e9ab7a1b8aee3509ba77d1394295775c8ab6ffbb5aad4acdcadcdeff39eeb576fd55b6ffb3e3af2d42fc5de73dd2f536e3b544e373b14eaf951cf14896b87a2a3f7ec3d117f47bbcef33c8ff37e7bcf63caedb5ec9abbf26b9de779df7f2ffefa7cff7dcff5d6755de7799ed7317f410e7eaf8144f845e66ef612f66ebb9cdac6cba5e4faec7b740cdb65e5ed046cdffcbdfdb66d5ff55e6366d0fb6ddbb66ddbb66ddbb66ddbb66ddbb66ddbb66ddbb66ddbb66ddb36cfe3761697f35eebdefbfe7e8f3d3aca177702dafbe691abf7a3f75e7bef511473c7f16fdccefedb72b23fec17ffc70388c3db7dc9eedf9794be9d80ee6dd5ae90fdb15f7abdddce2ec5f336f4f85be4ffe98f6b57f36b226b1af76dfc1a1d918c5f9999c531a7b6275b4ade9992ebd3cf43646c12a4f237c7dec6729f12c7afdc73db8e94524aa48afaed3d29bbaeebbaee03b9542af5f2535beaeb3ab0c957bb50f521cd14f852caeeb7edbdadfbed79fbc475b0fbae03824a89a394b2fba9fb1f7eea3931859a9fcb97f4669772dbb66dda442ec541607db8f7642765c749d9afa2234f55a566f7a8d98144a4f4a474299fab523ef892038dc807e9d8a1d03d91fc8f3e77524a293b2965d7492965d76ddbf65dd7759d945dd7a93ea855af5271ed5249d9759d6aba4af541aec957a9b8b79192eba4ec382939d54647ae6eddd7755dd7c9aeeba4ecbaae9372dbb6efbaaeebbaae93b2dba677b2ebbaaeebbaae935dd749d9755d27e5e649d94929a5ec3a2965d7759d94b2ebbaf91e286eef75a0f464955276db554ad97552765db729d54ef4a494524a2965b749b93d4bd952ca6d6b29b76d93524a293b49a5ec7e942fd9755de7c997f44f765df749d9755dd749b9a9a4941cf75cbf7838666fca5f29e5771bd76d3f769ed71175dc37f7411ecae7a4dce1723ea9aaa3f4e949297f3e1fbb1fe5cbf9f2594ef71149d6f973529e0d48dddfa93bbb4e0c5a1feda7b653359aa37a8f8e3cd54b6df351dfa34022feeb946b573b1182ff895cc37e6dbbbeef8bf2a31e2955a73a47c0f707df2912d7ef3bd0883f48c7f91ff5effb3e77ffe644a5a6cfe9df37fdfbe6f4ef9b7352cff3cef33cae5ddee6791fe42a716cc253fdbd215e90aabd4d389f631ebfaa3de77dea5162eabd6e7e200882e0836290a3c411c9e7f7cd39bf39e7f7cd39bfef4375a8df2d258e412acae79c737e73cec983dade9b734e50ecde9b73ce39e79c7382e357512ce4046d56cfbf76efea69dfd4c022fe2b6e75af7322ddf7b77d3fbabb1fe9eabfb9bb77ddce6a875a70d291ab28bacd27617d50cfef397b952fe9ed4f4ffd111971dda7a7f9fd38e744ea6a4245a13ec83d716c12a4faa37e50220fc7bcdbfeece8b74b7ba7dd8f53fbfe2ec8397f6db989903f55474947591bf44f7a13a575def671fd1add070e1973fa4f7fa2c95d427e17570857477f71899072e30b55c59c8393b373bb74828efd3c86c736a19310a6ca0f639323bbdda59c5303896c2011b98124b48b9ffb77ffea1bd72edfa88f5f459a755fb2b721f354b6d9976298a076c9719d48689707469eba1f438232ee54b1094fdd21558e41aa74b54bbe47c720b59f7b20ae6dd7f87577365c3af66fdf2448ddd77eaa1c8110f976c9298e4dd6a9ee4bbaedda1de6128e5ce52d35be509908f7f9397ff58f4e970865ddbadf621050b8712703e6421bde0feb90c7841d1c86cb1cb59f07c856fb55b577c6254b4dd56d85f0fa78de5191a00d5385026d5362ebbc70292a3af00b94ea0c0f74e3f333205747aa4b0f54a8a550e2b05ae9c09247d47c5b6c5050dc60d16aa28bd68d4d0dce0f5784c7ae39664d9ce12dc2f889b0422458bf3aee8846fe4651b8ba5ff4358a5767558a1f544f7e52f451bdf9493147c4a9def649b1553dee93e24df5ba4f8a36d5437d52aca99ef7499155bdef93e208d5033f29fe542ff549f1ab9eea9322aa7ae127c5ae7aab4f8a5af5589f1467f56a3e29caead97c52f4eadd7c52eceab56c6a6e5a38296a8414d602ecefac7efdda993761054cf3e75517c89c8053777d8898a34cfd40b83322c0d4268205448c5177b90eaf6d6e664e94f998b9db8939664ec8407ac1c10b931369e6172f4560d1bc80f1a2022f49d4e5b6700c978a41f7b19733a88fbde8c01b03a68eba9f27039fc0f2040f281a521f6fa9abfaa0086f6c982053c7cf092e3637df2aac3b7bc20b5650dfac4fdbb8f8812762503ff0d59d3dd1826a7333e60a1e38aee663710e1baeeecc092758ab5095023f0fd571359445e5093b788edddd5d5e269a36082e53fbd97fd18ceb54db97e98a453be31f398b6b56fb47cef2f2c74533ae93a4a3cbe9e8ea323578a9cd597e08bf47f3dd8febd4fdf7a3ab8edd04d271d1d4d1cdc82bb28c03c5786350d1cee23d8d87182cab2ce128b7d4fe55bd096752d24bed2d6642da5ecea8687f415353b46753c6c4953a329a75aa2c533d6f59fdf8ac1f736a7e0c6d7ebd6732d5ee7e4613ca6260191313d3952b57bca7a7bfbfb160f19e9e8e81b3784f4fbf993a7613d74da19f71a09819b0f0fb1dcdcd4d4bd66a7dbf6472209c8fe57cbfabfffb73687fe8404bfef4f4049b92faa57ece81e68085f4875574e9a6f54935b0f0c3bfa1bc6545976e7056ab5f75dfb1e8d24d0e0e8d81c57ad6dfd0f51ef0c15f07aaa14b383f45f54b4b53527ff33934869a9aaf791cba3674c9e6a7a8bc5fd8d2d294d42f6c29c67400588bc610d21854aa57bd0d5def998c25dca8f735229711d9cc4ae4332a91c988ec241e29d51384fced67261db9c95b3e3abaeae866bedf13dd0c10e1c8b27132b16c055410810219dcc088a62a73ec60063a9e60ee657c994110b23bacd07ef61d7624219341a6046cbd87fb6de3589a4286052fb802b6de83faee279303a9ae34e101068b5316323670a02e638336c3850d60ad44963a7653ed2566fd6ec681620cfbf19e7e141db98e8e1c47c770a363a8d13167d231878eef74fc3aba99fa539bfbbd784a5fafd06c67c231e7ebe812c25842a3f9daefa352ef5df7b11840ef1b85f2680cddf7f2d7813e1a034af5fceb404b1f63098bb86e4debe3bfb0a5ef634c0780a9680cde148fe1db34341a1a0702e91208520d8df7f87f74e9fbe87acff6dc34be47973c8ff28ce99883a24ba89fc2fd128aaef7c8e72f1a9a8e2e753f85a331c85fd852c75ebc679361098db4efe71fc29d2971a6b734693b53e24cd53427deb2c58162dd27d5c038d43f8acbc94185611d794b8ce900b00e0f27d8148f61bdc78433b0293296507ed3918be43396b048ffb835f109423e41386e5934344b86b7741db7a6adc981788bf7f8735c18e6e4d4716bfafa55b665d99ab62cfb461d35270d8de664803a6a326d8b269b5e2699e9c5a68eb2cc64926550759457e4177965d6d1676ec6b1f8accf3896a6339d45d6b4a5b3a0d932329a1f968ddcb8647e46ae3aff10320a42aefd236fa9be714ab35566bce519fd4af5e71c2836c5d781244abecf647326db7ff9b9377b8ec65c366b998ac6b8ed63fef263dc7f34d667da0b949f291e7629f74294831ff32f6ca7585f89b1536cf94a166fd565b449637ce657f5b3cf65335938fb7eba339b17199e01bd74bfb5dc32e12fccfbb1b380bf30ee37f5e3862afa29ca39811fcdf168d8573a1a7234c729a906b6510ea6d18549baded3ae52e24691e12dcfc867aaff3a10f7fb9c036dbf1f3a90f6fb390e347fff1d4882ad89537c8a2fc529be89b129fe9c18c3f9a41ad8f672fb98f65518a67dcca5fcf972c671b39b5f8561d31f75530685baa1312a5540188e3f15261360375f85613738fe2d5a856137fe369465dee35fe3cfa2551886a2b11feff15f5128dee3dfd11812eff10f6915864d7f157deff19734c633eff14fd12a0ce3682cf41e7f907216eff1dffc3f5a85611a8d4dc07bfc3dca57bc673ac92b9a16ce2cdd8f3c934edaff96f9ed17c639ea472e83a24935b0f91d4daa81c9e77e61dc266a62e83dfc53ccf11e7e29f299ba2124d928716f4e5e8f02c0a67819f9638aa791f9d8214c526787307d3b3b84c9e6831dc2b403c20e61e2d96a7608152603c0a6b44cc6363b8469bbd9214caad60e61c2c1d9214c3f7276089308dab743a830f9c0a6381a59150ddc214c9dda214c28d50e6162853b84c9c76a873051d60e611200ac696c3ed301b41d4265ca0663fa81f557f16d87304d980f6102bb1dc27483da214c1fc07c081300604e63fe4c07e0fefdde214d63f2936a60dbd69ab6d19c39351a3a8d311d00e63fc539efe1673a002c56e34ed77bf8936a604c0780357defe1df4fd258ce3cd5faf0ab56c83edf78cb33ce59ddba42fcb73275576affb8025aef192796da3ff6a8fbbc4073b1845f9db258c4cf58c222596a3fd76905982bb0c8a28a2d4d1520b02efcf3fba70aa088428a29be50817a26129a70c2cb1329e8b24336f93afcfd33891d42658a0ac6f403dbbe8a961dc224b7ec10a64f891dc264b3c40e61da61628730f1c0e4f74f2e3b8409084cd2181309b0ed75f8fb27113b84892b6287308546ec10a69c237608d323b143985cb0edfb67961db2d1980e530b48d904e1531ff352fb996c60da3391009b2f830930148dc960028ca331252e5bc8008bbd0c26c0248dc1b05405d3136140f1048bc960026ca3b12438805003cb16323ac026377fccb89c97379ff3b11bee5becf45fd3a10ce1b7ee635d52a01fc2c7c2a77b66e743f9657abccec7c4eff131595fd93a9e0700ce07368fc332f06d66e0c7986c60dbafb64c67f1f12859edbf521b0034d63d0f9d4008341644690c4a18fe0e8db10e8d7d0f1a7391760e8dfddcdc7c8bc6d849e63dfd4f43568f57d1d87a4fff0fca3306815601024bfd8ff6e3cece68a90f747ea7e6bb9c77aaad7a96cf541fcb52fb53eda5f5da952c7c6587c6bad7a17c0587c6586643630dd258152030f05734c66790741629f341fdca3ab16cf6e872703ee7fb69e3fd877a6f56bb7b549f597d97c54be7d0d87c1cda3534d62c1af3998ac6384bacbdc82b2dea59f80a77336d68ac4b0aacaff998f6312612602aeea753ed8f754921f59c97daef5e4363dab3a87f34e61e8dc999f7f4a368accf743426b3aca87b69a7ba822bee98c950a3312a553e988aca8fc932b59f890498a4318dca3201acba5ac8904445d5d5c28aa5172a7360ecf0851839c841c4121838247144186270604337870f422a60820651a881a68834602cb1ba3976e8420a19b8b0ae983a6469ccc034a5290f2988806d4d7513420b5500eace9ae6a85a5d313770e2e1dbbcb9296520f33691e3c270b4cc9c715cd398d4379131c3263024d7e485cb262d663755b1699bd6d4e58e0db68610696409a2cb1c3fc0b82f2ad7d485dbb411b4208917487146197430c1a6175cdd5913128dc6ff00e1831d1d1f3d72705a373635ac55a84a819f87ea366d4a6f5eef29b57740bbb86903bec8618d2aeb7ea18314147800e06997ab5def52ca69824ee321c1d585a4410ba18b29c7a0c0088f7a1752365511437fe2031c61bc200b2b7ca0a20b39b52629dbfba63990355ee002293b70e28c1dc2f84cf383840ff2f3a3421b607a90220799a722b8d801083c3faeff1f3c98c2066840914511646c81830f48f8203f3f4138018103992b409cf106acb5a06387e7c7f5ff43163360b9c2450d24b280b5191d123ec8cf4f12482cf580060b38dc40c304377c28600533f87283322aa8638b05c0a0c70a6e30c68c2d8ca081065128208d1c9e1fd77f9559104e94910571832167e090f0417e7e0000268d0c65da90820a1524c08cd64e1a56b431c3d21d5e7a20248c1b2237b841b6041aa719804140173626e410879938cea08206460499d56c1c561811471e61acb8c2069015acd90c881b803101973353bca458a510860c74502103259ce8a1842742106aa045107658d183531c24705191f0417e7e72f8018d251ddc08b3d482036849ad992b69cea0210e1de4a185018a00935841c51b64a8000e2e3d8c10c4fc787e5cff29f0a188365240658932d0fc7c81657a18e80286145986b8030b200ab0038ae7c7f52fe60e2a8c8841193660700601beb8d2e5d4c0957007d30f49b821c31059f8306dfbc512172d30f802cc0d6d00f9828ae624063ea8b1e58d22e080c100be904d1e8258c10d5cb220b1c41701a491292da898228b1631697ce941e3247c909f9f076cc186193988a288349a70bd1dcdf3e3fa07da2245134ec0d146136444f8f96ab717676abf64125e06e91f7f7ee86a599c00cb972372b0c50d596001f0491de0b4010ef871a0a541dddddfdf00a7414dd7490260786b80d0a9ccd63de7de3d32d3918edd6b1fe41dc7cc7123c772a5f4389179d953fc4c8b9c43a1e40735279e801289e4f3048974923d078d70cf74e488e44f91e3c413b66a759355a3b25b9fa9a57a2a4e137618dcd45e48112bc709d83052264e53e8ef54c7c857ffaf4e77852cb781449872c8d55b2de5c50564361421871373cc21070c0018e01e350ed930dbc49d66c506eb502814e5ca78cf12d1980b9303312ac736cf715c175e3a74a01f73384c172e288c19d4334804d58961bb2090031b5996c8e28c162c80713c950b73a67278803bab6c9cf19ead736a5144993aeb6ac186ac8e61e528c610c38b599823baed5d0b0384b669daf7da47c348e28cf6cfe3ea51770c1ef0505175c9a8628b3abed7f38859981b525cf0c0868b19d87cdd19175e54b06e531d75fc68ec753f865c80a973b6b71aaadbce30a3da3857f8d5396793193fd4c9d5c939336c1773130c1668a9b383cdc951d74679c6afcc32fe314034d5c943ff9fc7d584033a2a58178c1648a9e3ff78ac6de1020a4ee3328f905c00c1f90e5c7323c7715103a7699aa669daa6edd49d6d71a6a2ea36dda00b4ee62d8f14b7765c4845cab670aa5e8347fca95b97cf2adff3227f4a535b568bbaf599efc90623e046f291b86a8414566f7dfcbb2d80d7f9ded4c4285de57bcbbd9ed2689157493949758ccc2a7f56492591652ac2adb38e5c751e6f30b4ad47ddb66d6b3a33abb26e1776f8d0438abb5fcdccccfdccedee2f6b331728d81185182972dc70c716b02d84ba490184b44188aaebc5135de830e68b19df2207b9050edeaaebc51340d4adae174fd8c08b157528218325a1d0c002eba273e48dcabffbebf2e6fb154ddbf5696238c2cde3264e00d77d14b889c15821dcdfcd4a683fee2ebb6e4ea87114aecacd52c76ddc72fa35e9c861d4fdf93cfda2753e57a6ceff664eb5eba47504c2ac697e02ab7218ebb3cfaaf33d4dd3b45d1fd65ea3a3a669dcb43ecd33b73c3c8eb07f0ba68a4346c84ef5870023e8e06b4083397070820c3ce98413ebe32fe488c534317fa77ca715229d968c2ae9285f52765a1f38425675e2048c69aa23938941383203056531667bb6fa2fbf82b250635d5b479e417596a26e1d59756432fd0aca628c75adc10908cac2690bb035cb3785b763e83f72a3c4c24ce5b83194f29747aae0f9b396335994a9cc66c29d6981a672c1c4461db7da5a9ca94dd58ff0174e792a33959a442de2276ee2046c5d8e41b8cf5a56c81153a9ac657df6851c253193556e6a3002fc4595cf60114e62851cc9dff5f1fda232182b64e4ea949bd687c1086385f0efaf10a745d28ad73a4d8b740d1d88cb71a0b07bf6b99210c453bdfb3148f50ec3754f7ff7f46b53f2186fbbaef4de81767edf01501c088b03e9fc3ecf1c885140ddefb3e0403dbfcf571ce8c7eff31707a2aadf0fe2481ce883df672607fa7e9fbd38108fcdefff3850cdb37e9f650e1480dff037e7f727e04020fcfe0b0ed4fa7dcee240a200e8c855017c8b3aae17e101f053dca14b3e7ee7359186f0f4ff37f1075dd200f0aee7c41ebad4f37bde1379e812cf7f080f8a1ff4cfe77e25068006e0b517e16f44912e51f1791e4704812ef5dc3cf73dc4a525105e676758ccaa00de0608ec03107ee755e21208d4ca00604be083f03e1ee5835a49c17ebc0e5deaf1aadfa1566e604bdbfbf81c9db779d4d7884b3a36bff3a99d4fbd0db5e2b0259c577d272eed502b3eb0a5d5efa41ef5525c4a512b0a802d790f028a5ad9812da1dec7eb502b36b0259d97cf12976e386aa5076c897b1fdfd40a075bd2f97eefa15618b664f33b7f43ad68b0a5d483f0935a61c1966e5ef52d71c945ade8c096747e8a40adf0c096725ef501f84f5c0a00b582822db1346a45055bfa1e840700b51204b6a4bd8f0fc5a5294b4a301e6a4504d892cefb3fb5d2035b6abdaafb7ff1595c0a815a69d852f83b3f65490946a99505c096540f025dea6cbee659bffaf0ad300c8417a91520d852f73ee8928fb7c2b09fff435cd2a14b5618a6f32068cfff81b854f33b7449a7c7e73cceb7fee6ad30cc075d5a5a5a52bd00c4a459ed9123babc671f479c80f7ecb7c417bc67ff46e42cdeb36f2372deb35f23fe78cf3e4bd480f7ecaf449679cf7e28f216efd95789a1f7eca7c420deb30f8a48bc67ff1399c97bf63d91bd78cf3e4accf19efd4e0cf29e7d4e64c17bae78cfbe26f217efd99fe27bcfbe141d00c57bf65b642cde33f39e7d254eea694e8bb7f28d90e6a6711caa4bfdfee77da947ea55f82a9bdfb7495596cd2369b5e6915ab54895f3d59b378a222bce23c9da7a249b5a6442d5314262d59c374242d51e6f1445ab3a8fd4d5879111525841782324ae7ef03b8f94538bbcfe30424ad55d1f7ea3285d7fd05e1f7e24adee8320fafaf07f20caf5e1df11e7faf0eb88ddfaf0fb10b9f5e1ef216eebc39f236aebc38f237eebc3df12bdf5e1bf1151ebc36f23d688a9f5e16789e0faf0afc4707df84371b53efc2a91b53efc29b1b53efca078b33efc9f68b33efc9e58b33efc28b18798b33efc9c88b33efc9bb8b33efc9aa8b33efc53f4b13efc52fc607df85d04e1c7faf02b81c08ec65b9e7196a9fe2914a9de7b1c32c23d63cb0ad9eacf2f0865355f0366fb6dc67161baae09851ae3fb9c40f08c54eafd27997e1d494989c2dff0fde71afd3a926ff35b8f2425623deb9f7364a87136e2517f0d9d572614d3cbe432b7cc2366960944bbfc39716211e70e2f00e7489d41d911a2916958328e4acdfb4fa67e156db3867e156dde6f9d35d488934abbfc59a24cd32eff509476b4cb3f25ca394469a65dfe9cd8a1c423106432595d7dd14dcd17b1be2804bfe86873aade1fedac7e4fc468b5fa22a31ba249660236354f34cf80400deb89a6930358e113cd311a1012cda6a014f84433cc10f0e97ba2396b977f9076f91b79ffe191c6a3e33e3db501a68e4d3631d57ba2f9a55dfe3fedf26894565dd1717b7a4a5389e61aedf24fa15dfe44134cbbfc49689734e3e3a726f9a51907f24135e03dd28c3423cd4833d24c7569469ab972e5ca952b57ae5c71200d68f24af52bf38a9ca13ace7f93b3495161c7d1f1251654c7492cd57fcb22b1003973e6cc99334d67b62523970c178e6153f5979ea5c9a3a352f58054cf92c5b37816cf82a6fa7b163468d0a041d3689c9c9c9c9cda69cb962d5bb66cd996b5ac652d6332d5bf654b860c193264c8b0176e865a8ef4c23008d98b065e7b66239c5f1ce8a785f31a1dc39c9774cc79a6e3d71f0db4cb3dd02eff1ef485cfa1507270280b402dca3008476e7ea9fe1a70200e4547aea363183e47c79cdf964cf507d22f7f1eeffd77baf7b7d9de9f4bbdff07fef71c1d1ff5211d739e2b624a448f8c9b989aa21a68973f483df0d1173c8a84a2503ada84a32cb4cbbf68a34bbec81fd168acca97229276f9731be12c533784a4a954d3b02c1db6a7daf18081ddeeb23b0fd8f755502f9d368d2569afbdcabfe5fca4eeb9dfdf69c9f927753f73fa93b497db73fe49a897df9fc4bde6fddc3e09f5fefb214b25b9ef4f9aafadbadf3ec9638549de7ba92a281848c1f0635550b0149df203f5499db7f2d7e427cdef67f201537decbb4ff27efb2a285848a7fc48d158b77d739fe42f9fc9070cfca84717d5bd9c9fb43df7b1a4f91345e5c7923aca7d2cc99ffba4ed2597b469b1a42993bce977092bdeaaf0a42f20a6f34c3e604e63f2635534987fd18fa44d0ccc69ac4a0ae6cfd482c92296738aea89c907cc3f36e54715d49474ca8f5812f82d261f301f36ac30e5ad3ed58e4d8b15a6bc1ad52aa7c5b20953decdaac6a66513b238a9d5dc841fb46c58a94ffa3edcf1ba6d7e92f6aee5039d1e9f333f27874ef9f1b1240ea5d3834ef9f1b12494e4960757603b3e5a36acd0fba4ef531fab8282e9d0293f9e9e9e603e7ae4d018930f180e8d25a1be65c30a535eb7cd4ffade3f96c47dcb8615a6bcce3fe9fbed6349f25b361f4bba79d6c7926a3efc58d2ea531f4b52bdf7b124f0b74ffabefb5892f62dca7343431bfa35d4864577563427a4392aba93a23620e5f9a48fbe474314dd8e7e1c955d02ff46b92ea13f96a4d1af4be09f74bb84fe2449b92e81dfa9ec12faf79374b86bf2b65f479ab61dcdf945475d77f47de01fa954e11fb158357fe47ef347ad16ceef7fbf8e72be88ff28e78b7a5022a3a2a222458af88b6cbec8bf68f545a92f92effd11ee8ff0d3d3d3517f11371d6b730f3ae6301d1f878ead1d9b1b3aba0d1d7356357464ade868930ae9a84ad131f4403a7e1e1d3f141dbb283eaafc283e2a47c79dd5318a8fbad171135335ff498b7e3c3d3d5549c7283eaad3b1c926a6fa8f485a751aa5559bf2bc520e4b2abcfd09f777b302882abe1891fbdc6240e39eccd230c18313e060cb19d1081dba5915b21e3f9ce41083a90674e4008c1f6304171f1574d4b4eacea840230914c7510146e552308ee3260a45b578e115401f8ce338d47c0f25e6a07e0cabf7288ee37e9da85caa721cc771a8308a1e788e4dce57970b36e8a8b32e1765c040f5dce1c78f1f3e7ac0851668a660e146163f426e670c358c61e28c2f56c0940608542c7554dc206a69341ca0b8a8a307f38bf8b522a1227e9a409defa2a42333c834c8b330e263541aa2c8b25127ff91d24ada8076f5a85483dad5df7222ec0ff236c690e22e90f92e8ef2d7887ca75abb46ff454152a73a4556d6a096bbaefd296e959468df779dfc8b9836c0d431873fa8fc3962dae04280b0b9eaa9b89b5cdbc76f0ca5ac524a899add5c4eca77d7efe44829a59474a75d4c698ecc71770689f00a42ad6eff72f58959e52fdce6c51329e068d0a5a8b8811cb2164821c28d3276be94017e71416a96d25475675f9e985f3801a8a5eaed4f9853c32e082fa7d19147b76d3590a16e1b775ac7691d3fc77161e8405339ee73388671dca6cd5f074a5a410db418b3c61b68b4003675ea7cc28b3a7f73c2ba61e810d3b1b401111d74d832858e1ce0c0c547177470a9dbec0b10373675675f98aa57970b3b9e18c21b7f5c898a1414e1250d3475d4c105b61ff6ab475d9703ed6c4110ee6c22c7146ca479b261083072a660c106d69d490144e5ea6a51851a1b370f52d410860f4f347007dae502ec7bcd0738c30b3694e0c4a0618c0ca1ee2c0a382aa846a82df702d4a6691cf7fc9cc609d1440dcab80110686cd901ce112ce0a4f09bba638e9855adee982b70d8d2e4e766091630f113723b2160051c62aa980106153b688de1a09039d43044172fa884b9c205b09baa7d2844d5de4603619ac6fd7c8f13b92f36e6a8120a68e0461271c8f103152c60db73fdb2a99b1a3cd4ad6e63aec0a16ebfd3401a6c7b9e0692b08d8e4d7eaa46b9767d116ee55fe795dc57374c952d553ac14d30bae67e529b76e584dc8f610d1da8a39a16051655f3609aa66d2fdbc574d3d2fda669517ca99a06d3344ddb34b02e19608c9058fa256b1bd9f97283379af0a051264d5d3165ae5403d415c3860b2a3bf119de86dc77963a5fd291ab925710725bf79cecdca94dbbe67b5213c31984f2c7b0ceaf2e368db1da7d47477f0d3c21742014e599f7cc9f334cbbe6773208e58fe0093c7b4e94ed9aec14e45f65270ec34dfde2d7d7a096e2f7853ebfd54438ee993a9deaf875ce473297b0c009b8215c316ca451e57716f9c68e40eafecfc2c62112366e18ce4582b748e18e79c24b5dd51de3a5a936356bcf51a93d6be95e03ea28071bbf3ae72c0561d4f9b2811c36dfa68176f62ba4094f9d6fc393c3845b4307e25f1ada88395c843875c3d0d146957567514051c7b0be13e185fdbbdcf634dd420cc8295b0b6d34cd5beb3ea8432dde6fefaf3d37795dda7b128c80d75149e3edd4fca0e6a436df88ab66d3af8dea4c4d7ea7512da897ff49f99a94bf4914d5422a5d347fd4d73df2670dfbb52fa5aa7dd55efed72fede5a43afe5c03a095a87429172a84a1180421438846684693040d331640303824188d8603415273fa1480118ab458489f4a854994e2280a628c31c6104288218600638c199821ab01403b01a607039a9f2c7eeceee22ac5df0f3a1165807551f1a8b8927df6aa110c1674b1d6a280d2cda534258b42a5c90031f617388c818c37858666dfa00b787d413846b57e048ddb69a24035d43225f49899cd886faecac04c4629171e35786e808d7d18713686dfd3f7f000b586d09f3eb871d9559cf8800e3a1d6f635b304a50c13c06109aff46d0efcda1bc32640d2814c7834bc02484e8e4cd1a87aa62c93455bf647a952e3d3d55a80da40f820edb5276d92db1fe309c0e6b2cc9b2e33790b37d1d988e723ca2af6b7541f35d2ac2a5daeda7f8567d5bc8f5eec201c27e49fee09adbfa923ad4734792634f3969ad4d5825dbd712dba5b7cf12b74bb7cf25be4b6f9f2566976cdf4b6c97d8be4bdc2eddbe4bcc2eddbe96f82ebd7d97985dba7d2d8a25bece0dad9706eddf81d92f71c85acb52b563cf54d1e07211753a37ccb20f82c3d1f419fc553958a2d3260523dbb109123e85ae5fd08d321350bb6151d87e4655e4ecb3e7feced4990259e88b45298805ae594414600b8bf8d7269039844c66dbfb692528c00bd70811b579ace564d99c94ae86b9c928ff509a14a99d0c3e8dda80aef4c441c73842a366d40e35c8c0807f8d8204f00f3e106cae629bc9518a92bf9caa768738c23af7910587b02174db15a8b53112a27760a70da3b23ec68e829e7f338152f6c10c676ce5748b5a38cefd0a9f0f2c7d9fec70c67648b7b985834bbb581a0f7cac0f6cb8b63d9cdbf862b845e706f30a449afe469ab5a498fed4b1417409fcd01820d73436f164f077a7063f8c8f165c9a15921b9f40e6e8de28b30e0e6ad2ba9b9b5228a7f56e685e514ed3df60d62391b6bf9926453a48a7e96e24b38d0784b419fdd1a32f0df10760a278a97d66c3b5db33dde217e32d3ab7312541a4ebdc609651a5d44080ee51e0f76efe3c0b141dcc308b72b5ce88279c18181b407f818d1b85721ac69c16e316e4dca809abc1310932e683f309aebe9be61285e9fdcd6db201013d8ddc1bcd2a8ad3c5df6073120e28d3ba1b32f92899320fa2ffc0461a011945636782d62e0261a97dd2c6795bf3b86909d41c56f476018578f91eec4129a3eaeb0e1639a65f037e7888a7c3df798572b195f0d0de83df1576ab01754670a98381bef29df529bb35b1f4f41b91d8ad3e0f0e79a41f40ef3f3373f361f32c7ac9211aa1cd096e4a4a2075101d2f0bf86d8ad6e9c572102e364dd313829fbf9aef25005ec8c6a109932d071cfc2a523938117185cc0bdffd1a29a8f54faeb6016ec78b862bd6edd5daae08b7f0957722b0ef91812f55bb806a448daf31f8d22c0178a7c4f36de248e997285badc6243092c82972ac31d562fee39db8b4db63721c3dd4449bcbe8e83f30af97d25d2e939386f8ac4b2ea3de570580a4b05ce3b83658214f585e6c9c1faadaf6a40322c1ad58cc456fb5242bde9e9cc9aa09d2f1147d5818f17c69382a72454b553a28f982c27249bb15553e577dc0a038e658941d9bf28c557ebb06132830aca3ffa7d343b7c8445d1552cc25ac8706cf4e1ed92f30de48d5ca78bdc0a339a099f44eee6b9ad9e35b79d94f7f7bcb7bab71ec8c74b4dc2cb423f5b5c77cd0578c8f0b33510664b7c583302e4f5bc8d5b04c3d8b6cbe20d22869abda78f91d434d905555e13bc2135d15c7c59c0c9efa687870314dacd00b916313955581788e68dc1833930808404134ac6f30d2aa9985d19b704a05bcc24e00c710d8c579e51a07446484fa3eccb8c365dedd74d8df48df6b39767bd22f64aced068679562db0316bb7a09038d823eb566ee83814c21903cf997abae5c6fd770713734b0dc4ff5497c0778ef5627283c8e13124e3a54049a1c7b3ae6e5e6a20b3a4cfcd19466e63a12ed4b8f8517d9ad94773d91be6432220f5aec3c506c26b912c6a46db008583d5d8615a2229be045f1f1c15aa4a2a992d44952eb8dc543b1c98abb5dd13475defea9b10496a6aaf6f5270299325f0c7da525c0d73473c933f454aade5c1dfdc68db835a70bd44eb79160f05b890a4cb8781631eb9a93df909197eed0b01fbf003deb0ab9f103086a3d6354f87cd7d2889b319b343d1492323c8a4bfd67b433e236f844583e9da788e75af55f1bb2b3db8b1e489107d25d1b1852e8291ec85c621165767c2d99156e19051d5bb0a1de42a8c3c6e75f6669816e274c032ee232ef33b7f6da653de79d8f7c241d4eee3fac2410c87b80ca209ef5bb10ccc630fe52e183d80b4367867192861b04615e5d9d64da1d5e9915a9f761c93485b771c8e86aa62b70ade658733463cf8cb0f4c51d62ad6e05e8b3393500c76d6840a1f96928bd633955cf22ca935efedbc0a205b4e80b3fde655a3cb40e8c805ea07750444fe4778ae181d9e7c6e6ed99150989a703570a9b960c8fb5da4f9452cad4ef7287c29575483271a7b94d0703e64ac7ceffda8e70c8bf8ed051ff02032d2b6588bd970afab922254b14d1b67c7a4b29733821d1ab9ae3693c5dec62f1f5b95455a00667ac3f4be7a47a3485ca850f98bac91aff96586c133bf34c6ed58e8573d4d40799aed8b9bda480d9648834b13698ae14b4f98a74ce14aa888a18ddbdb554ff700d1bb0fa960eb7b9e42f0ff7fa2b701d1123708482edc3aca6cb544cb6a7b01b71a7bd87ef139b6896f73817b967d89f439d941a7d71e43496da2076309b88c9a58e0751791d15b45e4bd1fe0ef4d9ecff58c0768792283153304a57f9d24d1a79d9cc47d67fb94e54a8e41102ffd3fdf138e6b240e2e57088bae0656d30b411f9bc11339417d68bb0fe556847ded25190a4d114245e13202bf9dbce358983fda0cb91e35e0f36a80d53137b98a0c7d0cc573dd5addaab81ebf62b1d80e9794e6a1471b448813b04f4b26918ed480334a80b75b240480f61ffd34241cb91359dd4f5c47b0ea976f9dc158809628b2dcf1f8050634925056a696b4d85149948fbd9fd0c1b7f9d616e4cd098c620876d92d4087efc6dfe46fb8bc79a0af4c3243eb9482a395b43f04d2002e1718aced6100db0226ac805902d56cf1802a51b59d474f44629840bbfb80d7fa25730490bfecee75cada6a75f6e7280c009f322f222954bdfe81c58954a0bb702b39c46e69089925f111bd89a1eb81665ec7916c52bea636998b399f7004ac3d73ca759730a303dbe41a72b5ad93f6bca29a05b5e0ab0be5c9e491c0bd6273c06102ba4c16ec205af151832551d561098da092fbd7e096467e9c5d518c97f4f6e2589c187b4bb5bfd205eb44f66f015ee7fb45d7baa5f7dee61cd963fb44a43ab971312870b46443ac4ae53cff43772dcc4174a7494775ec9de372c7da7e52724001ad803a9453456220a1586e2858ef6421b20491b34e07e55e3ed4a96df541285189f03a534bdb382721d8e9362bd7830be12bbd8d85260d7ca41b0f34dd51da68a7bab30a6385aa747817f481b5c73e8288609949fa2c92961456ecd3585b6f0c70787bfe74430960d2e17c048d50c6563f000776121d49bc42d0ddd4ce71587bd60d54fdc38a499e941dd1869cc630577ae0f21ef457967f7dfa2b69c1b03090933aeb5904042bbb30bc6146404ce4784c1237f8889d2760e9bdb146b6f40d62fdf881e91b564acdf502a2ddb871f7da98d10b1454afda5a63d2d7dbf85d54684a4d8efa149af22bcd91d1215f68febf89dcbbed5db47d856fee7c8fe1412affe732f8c824645da592402455839ce3c30590ee47fe45712cd937a42bce913fdd785ba56ea4adc4cd1be3ec4669f9a0f12f64135cfc13d343b7d78347bb128a7318d715b9efbadbca25e45b36b537d2c83f9ccbd237f1a4ab7fe8b5ff7ded53a7fdeaa9ffb4d746535c644b0ed7e9da137d686ba37a39139ac23dc52ceb36bd73796a9f7bd3607b19f9ddf0952ed06a55bf9d560ddf1cec7ae2e131ee90b9429f95dde146f2f16ef7bd46c25ce7944cd4a46702ee632595adfbbf410668a23802ec85a1dbdf08d985c88ba6ee86e5ddc339857b723d3ece092021790dcff2fc80c9502f6c29bc1355cd68c7aaf5b4fcbad3025fda1785b9820fc45656e8edf87c154f2436b1f52256cbad0ab2d4ffc69f6226ac019dd58bac0348619d1566648d5a9721d2284c057f627e3113192053bb0b60e98a5bfd70d8ce342aa1ec99baed92ac9c6d6e1d57cdad61db5593d40c27a2146ec944ad028b8d07855e6dc100fba6e5944aad0e76bd06651babd45692a60b943e38a1faa9f7239aef97c10e15fb3a9f7fed15fc31e932675e8bf807b7e293b2dfbfe2b2dbafc4640c0b5c2e9342e89d6bea1dd56e9123b4cde15a58aa38a63f8120dde52e63d933fffe259799bed836dff57e4d5875ccfffcbd4ce68af5ef87bedcc7d30ddecc35f1be080237606a3ee85ab2fb51997ff8b060965e680ef56234da17bad10e278986de8ec9451bb7c8c939683a8ac2286ee4147e69f50aa26d7f9719dadfb6fc7a38f45e533e6b38c8108cc4cb85f47fc2a12dd32f219aba3c2ecc62ce1fac84fa13a5adf72edbc72e87843b792a03ba04e83aaf37d650fbaa6d2f025a47aab143b94b367ee01d862b4b3d355f2781a6504e2e94c3eaa18c2cb685a701593c2c8c3e477f7d820c9525df1d1f1fd3db3b4fd14bc19d8d9d049fcf07e2c9d9f85675a3689571ed3468d0704dcd284894b74ea5ce0ec13b5dee32a376f90e8bae0002cff56ba57396568fb7b32881b3a8be63c47ce50955396ee8fad7458e70aa0195e931f2b04a40964c5f7950a461b9e0fea2f4dbcc232091a60d8386595760578f71d1d8003376f484e8da4b2d25651b8c0dfbfeb67acb1caf68a4557558923a0d0aed18496a89e0cd7d4f9a7efb75c18c39bab58bec3b0a37e38eb3dd321e7a9f56058a1d0052d16c0505e5d13466b51697f15f13b38c16672141c58d9f1c2b6edc1ff0ff0d30de95f651aab7586be6bf565717e237aa2dca02c7547850987a1dc94f7b2473cf0886d0f527313492acf12329d68a869aa431b973fc592ecffb9faa548b467531b58473222bd04a0b3f7d8043ddc4754a9d8aaa01391e09540cfa72cc8f38a7a42577c3454e08c7900b1ffa1311bb725fc46d99ce6dd4634969ca8cdb5564705ad0764ca97f694f42994f953ebc947128846a015256b122a2cbe9cdfb03ec6c18e5816e4ed2b929d59da9ebede6d150563a05504fb98d429fb745d8d5f39eb9cdf1f2388e89edc7e72cd21c1255b651272cba023fe058fe71a976c43ac9762591abac2715984beed92976f257e4b0c5d43d064ceb2e09aaefcb3c1ce08df6b54070fac29b7c6079183b69fb25841899fb3da41bfe70d2215ea78753bb4da703a31a1a9d3fda8ba713f97187ab2bff4fe4c84b5130289f74a06fedbacb074335ea8774536dfdaaf2d130f5e8384d8f7473cd9e05b25a505a6b9a4a75fb6b807d6ceebf501641e73938e78c4386e690ba175e58eda7cff29cac42dd2347dd83eba11c5a29877e9952e7a653524210ff8cf8675342c8732ed16906cdea2e7c973cc02ad339514bbc4754eaf1cce24706294e9d34ca93b52e6a94c4f7b0322a2fa000844e820a4dc71d4a222e95ee82729546f0e6f1fe9f8b2910974b5c6d88180d75b63a1156f780d97e8718456db045fb7255ec801f17eba0efc8d8c2a905c8c0936302851554d425f8d54129f615ea55de7211c40f1af5eb4f2721cfb5cd3fec4c6f0e10d050e1ea92060c08d3e10af805b6784154816fac80d051f4453f778da88c6f70c3dfad46e0add126cce4f8923e2d5c99556a9a8f56aded805ad444c6087ae63ff1a72b1fd133dd67024d42e88f3322494986e8d0c8eee72bd74e3a74bff6d703add006e7d2412359587d40c74b270be035dcc8c1a47f38660913bc9507bdc4cffef15a1192f371dee83405884fc2c9839e8b125de9f2c1494c79a728146c8aac2781381b96a29c2e63f78a2aa83a7d5861a424fb73352574919c21073d01f1d98884bdde77713fd80dd8c2ffd62566d487fcaaa9655f8e01eb72e67d11702d2e8a8ffe263fe57972338ef749bf851fcf6894433c611fc84cd5276f498710ae6778ce02c7b731df6e800b98025ad4e7d5097ab561d7412aa518fa1c313a33551a6c4de8f04928abf4ec7ce3706191081d320266aaad508e64b49f682bac3e4557861c621a4d5a8ea6c2eb3bbea1c3401d691a1b16113e58441ee20afc2917677315127f0b183fca756dc50c3bdd068cfb4e4c3f74cb20e927f6e8f618c9b5f13b9c614664b6036aa0d39477853d9403715f55cfe86bfc40b82ce7512a23cf80ad0374fb504a1a10d64a637d9506e957b7c8585cd4e1535ee6c147efaece05391b7af8edf2667257b97e4bbead88739d369635112ffa43d5eaf5de021c6395cba8fd402857d858f2b650db5b9bef9e859f8c1529781167fa385813c9e6da4c8c04ad71bf537b3182a15e08b20db8d67a6a8e62ca35e2d5dea6edd00925f299974bdbc1338d623c4c6dededc823e0639eed4de0ca8c5f0190b2d0606cdb6381299fb659cf6bf8f1c84eb9f35bf887238d95a03e168709be3f070d696f8d49b185c734c51770ebdd8c1c263d6a726cca91d5f9222f86856ac60616d04bbf8c2b694bf4e2caeed56385852af2b1a147ad5ce5077d9269a0ac5fab52063c6a4cabb4c95fa55e1a645f067095bacacbb8df523bea69baa3c8d04156b31983c2d765a4b39bc6b08caed0e3161afd0c0ec9a3b6c8bfdb10e0df7b98777feebf56769aa45da60d87599fea448cdeec7790faa54e62ec6d883e5cabc63903fd427399caa976a9793870b13582224846d93b5341fed2a4ae268c98958f646bd63e21ea4573f04ad500431c278a8640ae736190977d2d723f222be2520bb6135f59ce83ce8a20a9f81bd48f7d52a481be40cc7d3b67a6c86625d0c755c476d16240febd7737e0862b38657505cbd9d78616170d352afe10cc29ada6055e0626a1239f71e805eb47d48ca9a24eb262b46239b015b31354dc0bf90963e8c29b995b441fb953635119173fde8055106cd14eb8c9f67e053f78e8e0e24e0eda9f4e132143795f1e8877600a8f0bb47894abfc194cf243808036150be6d44be1561ce119e9a56b41c4440f3f556c492e2e9fff5f748d1e4adc4ae9db2500c8a381b890f14fa890f47f8c47a577600e65804fc9b0bed1ae0479a9d74408b040aa049a2f45e17e26a9f757d3098a25d03f42c54a948cf2441981477b13cc6d6209c870524b6847275b2d3d34148ab4c7dcd8477a595d5e8a77081d0a72696c277b62c6360e685d11ea9a38a54063c291dd1f10714886411dd07a322a78f59ba2ef1aa13c0b61bebf0495990249a383c0d8f95b4aae9178960e178d281034e1ead4125a8fd957130901e739778c08cfafab0a2357b35337cc6be801274a66a8e30ea5ea176e7f03dbdcbadac28afdcd8a0698a4a3f56ccb96a7836decc392b9f121b1f08743dc939e9f1f30fb809fb3a3355dbe45e54461c7eb7e289eb24a050c20c636c1522de730391c23819809d12f0c256cf839b89f82b94499b2447bd4f79c56d22d2cc4c2c246dd48c5d7fc3d07f7fc57ed2fab19b070743d073fc3031e91a97829581d82e07e22c4c81ba33f19a512dff067fd0ae43af4f38e779a1eb143477fc80fcb443fa87187dad5f64ad80aa0479e11ea4c757509dc61ba200b1295aff45fe2f6c02c2b683088c435219a62d09e4bde1ef21d04d40cb1e4f79ff7d92017fa638e90d05c0acf8cfc217e28ed0e8e2186aa78dcf0a2d971b1c3ccc3a5afd300e761471b6f9ca0e97b15301ad2fed7c8ff43505f42413896096fb0eba5c759bc82eaa96057fe7ab17ebcee29ec4a7b778b00dfaa7a141077aea239703553b34bc2ef0602fca24ca1bce4423cffc537d25a7eeac56e080f2cc7a8ba0e38af008a08e2535489f726d027e7c0ece2240de1f603cb54ab2e40bffc90f530407772720310d4f206018a85f4844c52dcba37efe0249bcd9b97d7e598843dad0e6319709695e215beeabdaf04a87530f35981bf454529fb75fac72c1d0bb4a60cea003f23bc41ab3e854629e89290ed4bfa3238ddfd99c4c13060a6828e59c9b98924eed5ad37d26564715738ee89811e2c8440fb9560c081e1939ef7e487733b065a1d07ab9b1bb94e868a37d5b263c08b78006e11113344507dc2fef39357450e737e465fea32356cc0999cfad0ba8e4e9ba953725ea8b3ea81f5da66574bec5b86cf50e6a6d0f56ffa0f09c80ce13ef2ff2023742eeace02f05affa5d6bd6be5b089ea5f1a601f087c6eff713833a101594040117c994b6f0ad5b8ff86ee8c20580c077be46c6548043bbd259403e266c3cd54474b10ab597ea8ccf646afbfdd749272b05e5a4e5cfd3b9bbcda2a9eaaaeb460a11fa0389470bad376b30c064ba635725ce997f36c0ef28b947d79c717d78613030bfbf89032593c02501af8aefdc7df17792f0dcd5c1a354a24a5a067b9a1384583ed2cd9a38d2e88a8e10fdfa2407eb1552f522923c35780bd58684566110792007a69f9c556fb92eec970ac992fa6deb2c3408dde733af6857dbd63d7c97a7fb569437396e8fd3b144f00270462fea69e311c4bff39d4562000a1fcb7280b855e3c93d6164e87c3196bd158e3bb6f75d6b97bb61c746070bfaaf6e052df4d3a7bcefab54ccc1cef4d516afba32db33f1ed6079a50af155c6b22f5b9e39edbf4ef0227fa5db71c44a7ca181ccc167866a53ce802f43832a755e1ee57880303246e6a62577841faa1cb688a4f6304f638a1b862a5cad512deb424fc52a7b22bc2b8c25ac8c14b518729574d3dcf434db16eb9f6b7a139f5ed4667cc4cf1e19114fd929d985bda1da00b5fc722878c1f66649b8b049089e33a99496bcde92c9ef354cd60c09ef6d2dfd0c27666e9643f1a44c17dccf39aa576c631b86a5cbb21a0b6b738de03c29a9a574824d88da6378fc7df9318a71b73bc34f3695947151306c1beee834a75236d88e7ffbe20354feee2cffc6170cd70f08b15897b665fbe33af321ca024d396a0cbf83a470acc12dcb8c104da068ae52204d117aa9188aa8707f84e57f38a46b2015339e0f872664628b8dab44385cba787e51a3c5828647d652a7fd83db805bc5b738dd0e5694a61bab7b64948535adc87a50a33f2a7ddf32fd6b36886e0ffd1ffd4f3684663a1dd33979ace3e5295d09fbb20ec1db0955b1efdaacea3f79ecbad57e5af537e5f39a85ae160bdd0148b86d3e460b4ea8e634a8ce4765ce062119c513492f2aa9938de4c5c6e28f5e24f42a3a6baf100b7ed6dd765cce890802761bc5797e1ed0a18370ee5d9bdc8f667b595cbab64b65560cc6dc98de886104177ce7de83380ca1a64e652b828f7c437f4f1e5a1faf7fef5e49564d9a0689d01bc9bd2ceead084547afe837f3423a57b2e9a1300262ed6027c606567a7ad7bdec1628c432fb5eff2c743481c6f24f98e5771fa6438a35c208001b7195b48b661355d8ee030c52cc7af90e2f27aff504c8715a26c09ebfafe1269dfc814d212dc527fca7249b9bf6512c7ea41a880fee91a014b9c353020898e339921457c018b15b2fbf3aa933e19eab9f9f0d0aceeb7d4f9407bad20ceea38852f862774df90681e5b6ece99177a97a7f5930ca90d0c4eca071b60a79411c6427310966391807a19c6f1805e0f142ca0d367726852075075943647db74bf3227e336ce97f388ae3ceb4fd5daaa9a65d1b43d42654b0c29ae8a6f3daab81610222ae1d082ce0866898e1bede75b90b0ca08271f9e2e58d31cc5aec5ee24c14906019f54a0cd4583e9e1fa3204d4a99b27f26912618eb6972c04c35c8074ab95b972d0011981c3d2831184b2d6b0471d953477b582a25c7b822f5b2ae92e12b4f642dd5cbcbf88fb85f1bf02dfd7e07f21bcafc4f535b85f0bef6bf17d05fe57e1f82a5efaca74181af89eb6f709da71598d692bc6562e97329b0ba185733fb69f53061288c04b57d802b8b816aa05b2b981a5a05808d04178d4462f9973144723d7198536c1fd8fbc2cbccaba5f7ba4b41e3e55ae7ccb48c2f4a8562b63f70324a62ce2d5ae71ad5f456a671f1359b7847230de7b7296673888f5b46a5ae52e40caa48e1b4b078c05ade044ff5a9eb3db5d80a4a99057210051102687c500da762d43b9b856d7097e20b7a9542f9c0a5465ca22c1297355bef2f4ebacf0469321897627c50406045eddef4aa6fe27b6d089df93e6861bc1b6663edddde02a629ec5c55ece4b353b12abfa46906b5b558f272e6be7016ff285cc941d2b6c714bf90fad4b18eee3f787a5607815243682431d4a5008c338b7ac124ba5aa35262514bb9446bf3bf42ab2ea27374d61d9bb61d93445af22a71f904d8111775ea042fe6b5d7ca95e190af9e9bcac234130c0acd86e2463d9efe8ea339ece41765598c218e0790019ecb0c07fb85c026d81f73cf9bd24dcd3e0bb758c67feb40d468f755666e0885183776a0341114fe0885bd9a6d0ca23c6dde011619f72f454dcfee99a72777837dabc565ceab8aaff46f2e596c0cf5e6581d1e4ec49a419ef24392956397f95cb1ec75b79a8b4ca36aefc33f3b7ce5d75694f3687acf38f2be500041c114cb5cd3ce9ac32ba8131c81c536780533b478c9c08c44f83932245ddf3650e7618b725063be232d4920c359928ac427f977255b34a4656d589eebe7ab4fc4d92b38fb0753dd7889bfb488c9f32bb9ccac996bf8c135f8ca8881352368c9a315e4b12ffff2ec63b540796d8548ac331b0d913e80484ea1be365c590d564883130de7b4e08768c15d6c1e2119b4e818e36a7b9f61300987c825e440b0d25c7df96eb2732dd2d2555396ed8f8c3c6d3d6c3ecb31265c083e962612e12173e52305e0c4c6e10b68c118f65b2987a8e041cd4864baf484715a6fc2b2990820a8fb7e58f20bebe933bebe10e8f63811bb04d976c2db69edc1eda41d7203418cf409cded15872bfdc075f5480869935eb502085bb849dbafd8a0b5595c7c0bb421229f102d9501766be6d9428f4c3a41240a0d683aadfee4bb29ccc1040ff802360d87b46ec8c4c22a9d778e680d3513021b714376a26371405bcf411c4c510de733c1a7eddbf49a78259d4abb412ebfe402607e67b025bda28ddd131b6a44a9eb4f35c21be74e2f677a023199612a5eb3bcfa8652456dc741fbbe50263b8a8f41dfe8ca71668f43b88e44ad5fba75554d1f40f2cf477ebfd83f625bdde7ac543f63ea0376543c4fcd7ca61513cb197142253ac2c334205820bdd911a3b8b22c7fcb2586b4fcb81fa903f4cf714391c2ded93b94a25b95e0bb7055eaef90dea8f49a65b2eb747861d6a91b22cb8c36d1aeac52556a7e15137456bbd5173c9416baf8153d4a3250c3d7976b0d6dcd93d3a36dd446f2c5546d35273442b45d363908d0b7b9b209578627f1b1bc9ab69fc1eaa39ed85a945d8ed4c70647094a0b1b0097af455f690d5152583369ebc0c3eb13396632b93e4939327823f82165cb2d5f9a947cf58655b4bbeb93387a82daf853fcbec04c9595d9d56248dea38e92c160703cd4fba1f25d4c258687a43f585a26e7bbc474f3622d7a72bba95274a9387018033932450052e6d7fff1e8593e0a3c1fec09d0312d5b5ef3d4a8cd209934687aeab14a103e4e18f6c5be6e3d6e2695803d0468f2adb969361606194ead1cd11dc90047a42aebbdb3d13b3692599aaabf43a94c5720b5b8d1cefd150ad934b8afdca92b3dae1fbb8cea816979e657560d1f0a4f650823a08c174896b736874488fe8510f07912156c3cae4d5b484721e25444e09009bf27f073d902ea73c9716a828f459676d4388bb9b0073a17a9521f2f832abdacec4031f75c939baaf9f6a8e3fa474f1955927ce9b29bb35cbf1acf4a81a6291a3b8cd8b1cf315bb3c127c6f1a3ca8a811c0a254b45208f34f50c185f90c27ec7ce640412b17463d0af43837856f1a62dc81f52086ff84246b9f182f56349314121be1b820aa602642c7715983360e35ff041f5ced65979579d6a87c52f1af683855fb1ed5de5be282aa283bd7adc25787ee46a7ff2e1a50a447cf7d28d77d2e35b93d7e5baa18582a25f768878c4adcf0ba19cc7def9406a8b229043da1fc73e4d285027f8ec918941006966efe17e2af4c21d8503955ec512ebd43457e65a116ec1e3d9c0b00359f1c7de9bf6fe7d28bb190075b41fb9969c92120b8cf9854c18be76b2c963749cdae49412165067ac38d98b89b64a969642a599f666e5047dc9cadf9abe0d67cfe0e3d4a9c58db6ba9ad0f2ff708aeaa900273d2dc10dd3b181798727995b947556c7879e91cc670479e61ca88c0d25472f7faa44a7f7ec5b51f68343fd6415de6c1f11773f0fea36a008d4d3cce81cda0c53da8944fcab592faa4568690419fc24dc206d8d4d9e51366c86d85ffc2e788c82e81a30ae540676412fe0bbc77e0713247831681e2a3f0e94c73b5e9b5496fe38b99dd1d530959faf88b879e1b795f3e05cd907331ef76bc7793f14877304f1869ac2eda4d4c1ebcb6f1506ba0a8d12cd72ccc59ec7e8a1b874153ac78b56e03f45bd66ed0e879ec9256250e45c913af04c1297f8eccb5647ed9205e51cb095e73418809acfbaeb65c595e4125b419b42124a21190d9c0790f03a7f33db6a16cdcd624ceb56c3d3a1e21ba845ce5ed04bb16da5db391784ae3a1acf9950543892f686858ec10939ada34c98d8bcd568a2c403e9e6384f8ae14c17a5b7a77d9b65bb94e7cf6b4c5c20b2a05563d8344f81fb9ce2c62c6b34dedc6302b2d03433c8a263a60954c1ad5aa58e423d5d996954ab6dbb9377c0256b23c99484bf5ac8fde8bfb49aaf22cb37edea1794095e45e0fc2aa0b17dd51a79719bcc288c7a540cc7250cfc032fb4ad145c9372bde51aac8727f9aabb607de1d9882c6fc4f5af35b7fd16a49578037cdbb470ab6b8a7f05ec6772bdf0fbc4bc9d56d6d1c1abad55cf1641633f2ae8eaf227ca9e0eead869a6d1ab171f152e6767c4e38998a9c1bfd4b7be47ff08503a1816775c2446acf1bce925eacd0f3766983eb02f822850d3b40630afd96f7945bdb74a23bf21942836016f251a339c609b5cc9c07de0c2f63d22ee0ca99ac48350543d7759b9221804150c7a7b29da6d1654f0fbc21b094cb5c12755ca8bced4cf68cd0efd0c06d5b71d1516e13281f1a5d6aabd51ad79cc415ae0a60a05d8f8f5102077360d8999f6787202fee81f62cb576c810da9c02310d0d73f49ea166dc027b7acf7802286e782e2bdd232cfcedfbfc1635cf9a2a8c45fc94b3816facf8d3fd116ffd056aefd0d710d71dc1e12742cd931be079947a4e69e77956474f7a30d7dad12435a58ba1578b4accd752bd192f236d38ced872cb6a4ccaa0b91cc408d65f4b54bfb7dcfb58b8865f5be1822f53b7b511288c8551d48a812f994cc2404746fddbe449baf599d9bb0071561e3ffbb5ad6baae89e8e0a3c32f48ecb2d1f6e9428bc0bd0975103325bfa3dd8bed983e6e63a6c6eec614b3784a6030b373a82352dcb840a71a112a53efad1cbfa3148bc4b14038ffc5b0df4a5a9403589e0f0097340a1bee2a3042ac905ec01e9db6c9fcd0a3864acb9c805887267527fe7a082596e46c0e5672ef435834268315018f47b61f04cb337d71d1c96016d66cf96b4f72c9ec3d1c04f7135b748d083d6790e7963edf8c2f2e382e3395788d1424a15ba1a747900f69a5e849463ee8a4d7e5fb54af00ce0cb714d1de3e818cf063bb6c78b1151cd2075cf4ea939fcc6dce031b77d77689c28fc315ac328e34ea066850e7f1ab9bf0c923367290b34f7ee28773c55ae0f715e5cff5b8af0baa3c2133ee6ee304506789c68301b6881cc1771578eea83f00898c55e2affe82616f8840957504a321f2163e0f5288031e49b0fee54b75afef9ada07ecf8f10382b2260dd5eb9600be47066dac2f1aef36040347c2309badb9e196189e8b65998f847d01c05a2616fe1cf3a43d0581992bfc979ad9c994e1d87dff8af126f792529d30c1a83d70e342dd117778407040f6e571676c37f7b13faf2cb3f90c01c96d4c3efae9f0fe301d3a32fa93481c1203da942bb6f0283417a729572df040607f4c96afa5e130e42b879562657f4bcff08d4ac4cbeec78ff2288fa7bf009533f7af6bda5c61688a3166e2fc4ec202d74aaa0b9b2ac350844a70278422e60abd1fef46e34bc580895925d8133d6b74ee9d2cbecb530a23202b8876d10c992fceedbf4218ea907efb9bb74538300cfce1da121e4b3ba9e7a9a2b994d6dd0e7ea23ac1a7efa28afefe5236b8da412e59d324d324e997b0a8cd6b48c47360bec7a462d932e8ec6c2c07a645cf62e179877ff4461a9b6ac8560d0b7eef32ea3809247fd926460a598eec53f871735e771d1259849f0b220e23d1be22f1323cf746986fea377608ec3e5ea1a3267f788c3783a9db107ec20b9f7c518d1d4452b9e1c1c86b6da3b00d11efa359c8dbf50c235ee169e5138daa12739295150437acee048c95b57f9a9245588421824439faab278bad445b10e93ed4ea6e87fff05da77ca9321b84dd8e441c2aed86fcea4857eb79b0ff14669d1d703bf20a4041ab6967e0c7b9e0d28a6a785317fad8af6e29f964399f3542f353d370df654a6f0a959e9735a87286e565164a682a40e7f1a78c7065e763f90739437f57a02e141513e27465b7ad6d7e9e1d26d1e01e41c56ec54def07e3b7be869093bbeb938484692635405bd192cac4896762804fc4eb548ed1d054516f4d2a379bec5b3dc5568eb88350bc29e52e4f2062d875a89b51d3f2522b2e880320bb3f65f82453f19187b6af04ef413827f3797664e085a209687d7bad68ab7ffeb78e4dbaaa3a5c15c3779452ca81609d027cf826d9e6bb21dec3d3916c178780df1c88613d686a6e08297c0df0000e635500c83261c35dd3ec4d01e636a2070f54b0b14e19bf4c8796dde9f6eb7399558cea8e1621f26c9cb92c283cd3ef41ce4f57a7c95001367d418a72a5a2d0430f5bf6aef7105f7bd8bdfc77b2872d587d3aca0508a1d37865fca4e1c50c006fe890d59ce0da72d555e07322724c7e821184ae584597ba98be1b2ce288449d579b1fdee5fe308a4c3a004ee0020d5354a426690b03a0d53da07c8a030513587dffe3c070674f61b1b42feda3c14c68d2530ba05d88d98a000a0158f66d3abc1aa3827a80fab586338edcf791aded69b5f8a2d043491198da0df20907d66bdf53a664dd2b9dffe14e9f8e44f52e5c60f8b51f83b454fd5d31f6680dd1eb1c955cd47e0c9cff7ef916ef32d80341b23d954f71343ae6ef33ee5aa1bf28bff19f0d995cc84a261c237c9d4f01112ee891920d165b4648b1a284ed6e3f7b8b39ff87e858bd5b02f1583caf30bbccfb762e1760203b67f6b9d6128e93d5516f18e017953163b8a11813dcf473417d6de454e51d06c2e3e6b52bd50d185400a29afdd85c8585bf73d0ac79f00a6445b8a682d01c665daab0a3178079343fb40bdb67ba5cbb0ab6612b0ead14efa46907e13d830197088c0cdcec3041b45cb6b9ad86804012d49198ef7a7bde9ddb0ef900ab43486b128ba09b303b7afcca7c2882b7c09075fb2cbd1d38a696ee0dcaf798ed0a63ab38afb03cdbd8afbcad8e295c1938b1719aadeca0338ce1d528d5fd5bcd83618b7bbe7a5d4c361e5da29805a2f96b4daa7c794d25cac9ad0c8db8e538982e0bdf80c2144d8f4841a39c1aeea09e076a19c99787be50c7607872df5d74e0a358453812e780fdf7994791aa2898263cb7c647f7d7c8cce50be231d252efea5ed4ec1d3c0410c2537c76d4fab9d2ad7c3f7e501fb5096bbfa3696601be2e58124ab2bf21a6441959b42aecb06214c94511c02f8dad7ac421416838ab89516c236f9287b3f1caecdd468a88fc9fd1991d30d797beb40dc516122b62d66d975c28134841451c4a8a4273ebb9ae45fd450f510e34ce3d4e5ed46101acd9124e69c531c41f6d0492e8dc8ff2d113d927b2dc855cc95d1993271c1be560aa0a72bccbe2d695f92370106d224a6f509d88212f728658f99320bfacf54fff0fec33f89dd0dc8b11302ff50a32454ee7c781915fb1448a88982be04fedae03dee1fa80eb1ba1b51b4d94d82155a2cf9e3acc081d096de93f9f60681083213dfad7b5f5e6c561fc14b0960ed0d409f3a61a23d50a58bdf579b700a237e32ff83b72fd84d82a7aa8aeeef70ce37dc81a1ca0d0cf190a4529b1626c8bd9361ff56a3542af58b1d6b4c71a188818066a65f98bc67132a3b8a47a653dee89a3c689f28269672f4882e0750fce4a5ec84f648a342ebf6a553b81149d5013234123be08a628c1ad20c460d5aa274c5000e351279741754824260217dbc39b734c5223f788f828e0afcc0ceed7f42d834b21ed20d8e64b464bf944e16be4a2f280a640e74ba8d0b8db4404adef66caf509305ca63075388db59e3fe4621967cc3e30e3b4d0f0739a606f4df25d77890301cb16959d5992da783f37e0cd021e4128ab157643960e26431498492c08a0f624fc18c9ff05fc222ca1023bbff6916485f30c9bce5ce898bd30bbd8f4de9f4a22a746fa4484f15c0098d8883a693594d1e6a6907925d60150bf3b9fb2d092c212d0b6a641439c5320e8a18facfe5b26254d0bba436bef0a4d69ddfdd345db71df15222f4d8781289abd7da94e6d7a9a49d6241884643686ee19397587bd54c1be518c5292c9a25bab8cb1064ec4367b496b280c4ec81559cca3ad6274b2cd4741ab47bcb522d9d5cb62535c99700ecb63998432e3c2526bd73084abeb52a9564460e1d021568a7ddd624db8f6cd58144ec5d00733b1329256d44deb29244b60686617a220b01081726af1dc91829f15b8a88789625498d58df7fefcda81fd335532c9b966aa773614028eeff978e1f659e4647df9a5932151ceb333b3b6681aa2281f2bd9c73d5ca9133a4aad0bf4f0b574c0d5d9b15df32d6c6c9eee0fefb9d85dd5284156ebda7a2eb28ce4f32c0c9974bd5e6af636e5f1731a857026086a6326b686528b41da8e8be3c5f117912074fe0a0caf5ce5343d2f69a98ac0aea42003152296507f4e483bbeb7f31295a47c6b31ce64682b1bcae9a19ed1faae2372ee5725a1c1f9aa51de790999de2200baed28c653c535077dd8103945455bd7cef3ed334b97dcb2124aa75d457235bbc04124fc360d6c45b9c72750c859ab8f64f88ed7d3d2231c1c7c5817f5ba6947a1717187e29625cb0468575ec071b1e17353c253c9de9091774d2bc1377d38c14db5114af5f0a01140c733867574b6c03c5070c88114b47c54c9c17c0ff5c6d4deff21ffc591d504cd6b9c69050177b8d7b2e773c38ff5687423ae9d66548f82ce0fc22a45044846761fcc6ac83f9cdf40ca9cd70ea10f1510cde4020bc0d80b7a5f3975d91017939b6874574535765c06f91366e1595230bea78732107d91c7427c9332c0e251499a473ba9c8b56b6364ee905d5473e4a9326146188c75356872bf51cda59d1fb54d0abc02eb6e3d1b3288fa4c36133ae241d5c0b1a29a56c3015f96d22f964c1c19eba9e127545778a988eec0ecc8ce3a0232729dccd306d3163b976ab1391235c03a582b68cdddd42aca483c08b8c4916cd034f1140806cf9ee2d2c1c77cbbcbee48720357b389d6b68d425ecbfcd05ab4f0816d53ab601731397abe4ab46e38a4867d71053bd1094e189da5ba873c1c738ded2fbd6e5027f4d772e43f762af47aef5c544013d13185cb489fa6402b2f7ad6c306cc7b2be383b8218b7e5f6490cb4cc80753e0815beaa1130612461b14032f956e22f80ef208de89c0427d7c486f4ebc10afda0a0fdbf683ec2aa9826b6fd4149768ab47a1f0cb414ac6bf7a1ac830b15fe0900fc3de360c158fcc8f69767f3b570327f8740977f2ec2cad7a9854a7262382718d85db9349072a9bc60c6bf988a95bd00d29dfa6afe8d5a57724a85176f9ff84f0c2f3467e4736f00446c2e26c0b87494b89e51016534f269cd7c5e7dfc569411208f71bd54fd10690d80125026a18ac5678e9aef7e6f605eaea506c1a64fcb1f9b7325d885544cc790155611d8a73685b26be5cfd201d633d375c59179e3e227b56798eb1ed8db1871ef09d64b62b7ea5c86cc4b4c346dbef93017e6e52ff2ccc422b88c4a6cef28472ddb4834cd04c6062955f861af42d7cf17545e89facc02589e8af8a557faa0d9888ab69ae20c58f38cf4a5cf23a7d8da05a82a0f6d4bfc457922fdbdd48bb8ed4f2c900b1fab59c5c6d92dc7a672e1436330a95eb9d22bc1fc27aa65dd4dcd4491b62f0caad2e312005f27cb42808063e6354357fa7e52942e62eb003ca0975343e18426a89b0c580ca84a719cf3532f5516e0e9a5da2028bb53d844844c6b07589f5be882152b0689b41f59ac7e7b93df2486a4849cbc82c3b9af27c830bd2d01cc17ca7344df4e3f24abbdefe48f4fe4eb078b24d881d69a40a37e171a50029935c047a4a9e6a512e39a4f5464e898d97979857edaa6994aa19d52fcc91a14bb1a4dfe4683a3897936841358c34478e497187891b4b8d2b6ace292fd9ad0c6dc074369737ca5015c55883a0fc7e9eb2eb6c528b7fe8f94de1073636d1edd9377e2c58df5b912341b5cd9ff5dde19403bceb6e661f1864d5d1831dea85d3c3abfc85b80789273d4aff5a1269344aed1d107730febccbd1beb8f1e007466c8d82ac477e968ce609286248d1ed60b69998f74db2511b5a289030944a3e9b957ac70de85e1699c93859508ddc9d9271881313ee4f7733b021c0b45937f060d1d7470e60ff4574c1d0e8e54db93b28a610960309c4896ac3d1276f29effd1abdac90d1da11846c5ef5d8e6b9484dd76ece0fb27a48976de9b5a93d9590f2f94a443afa79de4bc24f5227b392c8b44297d7cf86c5f0cbbf26705255d8ae431e59dc958b2713b4a46c395ddb62eac3db67bf6da1cd4f7f562f74b10b14af59e72af0950f524f2fe3d04f86241e5040426138e196299a8bff05eeeca61cf27276f3526e82a8c33e3a72a1091f0f695ca56272dc6b1cfb90fe9da11553790e63ad2cf531a4665ad582f5b7170790afec3d231a0e55800fe8fa99bcf1968b4bc13ff127164de17922cba0b1332f72de269c126316ffd1e1109ba9044eda45dd780a11eb1bb39e7d61506682c7a4e26ab1dcb203f66e45903a9d131ff70850e8957c18d0539eb5acb01966cea723cf242bfda5fae1ff86837c5d1c602a60cb24ab9621e471badc41dc7e3e34ad2c161abfcfdf081242b662fbc450caf36ea0b552a36d5b57f4dee9ee3d7f49e4a5609ab822bde396b1c5435cbcd7ae7090545b13032b915fea4aa7e0007d786917d7daa3e1e21203ba7a4feb9867c796500eaa9a24632d0072e7ef65efffd089c468514654f5d4f4db6f30be40c1b5729fc856afffc4b07042e698f51902fd5fd76f2b2f02e99e63a16951a2bcab35832e777632ebddcdab2228763c0fe3de45ceeaf930a74e7da2fa25930adcfe855079a3ba9f0be4367f2c5ca5505e8146993b222632b1e80d93a61b759c40b8c222f24159a1e5997c52561a10225e65765dd1693383185c229596305e76e30e28a8bf421ab2a2495223fec22d696ac4e37bf06a50a0583a3e3b2b45fe8d4669437deb8707e3bc5f5ef197565fe5f1cf4425083ac0912ac825ed8505a76c94fae49753a7bffdd77ae39fc6ca5416a3e28dda02411407252addab5e4e797ce08b099bc90d2596e283c0178782b07428ef1dded675d17142e7dd5e30e73895de524536eee533aa926e72ffc27cf5bb8750099435c33bcb34ba62425d52ad331228701183801d001cbf37bad4d4c4e1f568addb615c4883b81f74aa9348bebebae44c38ee7f6eefbc3f4696ab1c925585ea7e74a22bff14e6d15457e0a362c66e63e7d3e8f6581b2a1ac902809f02727793e693247da0093f45f7dbd39638bd3998975600849451177fe3673a781e1ca3c6d1c2dedd3754d2465cf02e10f6f6e0be269647331eff8d055f4330b791dfd8658ff023d20889a65a2104d8807af21ee255d0f75ff2a10833abcbff3a2629859821a0407247823d100f4718760b9ae74b469567c29f1b2124a58c24c416721e08f91bdef8f779b61a51f27ca5dc2e522b5fdc756458d329de803c4ace07200d5342cc346ab00c2a0e9aec586d5f8bb813c189a2155e67c23a90709cfe67b0d891473e4c70d72d22b13a3263fda133e641ef8e41ee21007faa8b1c52c915ed16b9bc40a2bc9248710cf35514951eef361fabfac5e20cb934831db9258046e2197bad02119c3e6c1a121bb57afd6876033df88c676898e2724d964344fe0d6003ba39bd84f913d01466e3cf5533f4d3c03c21b4e05cd9cb9ae0359e8dc3f9287036be28afbe56c7be8564010627ddf949e022cd3cf76f15cd0834ec39a06fe68e68500736d1329b6286e82501bc62d69985584c6294b4d266d0ac41849a9b16045881cf448c4da6d3bea297d81c0afd42d968979e0fb5024913919cc015b27668bca3bd65303c7a2ebddf2d5aea88531e5d541429662660f99490aa04ae2d857967c4931a15015c4e2f2758cea6446d1ff9e28a1035f20c3832cd585506d89211f4367c7874c172a3ac75e4e87dad4ed5c7546768df7af82fe086196019172720defcd026d7e6b113d8e7729d9b3f75c521167ee129c59098cc9b23302e48a7f2a50484de9ccb89222a6f7c81794c060b79a2963ba3a639ceb2bc1b17f76394c3271c5b3d21a0822b7401b9000380f0ee2f813aa5b5ba4fbe5d0c8013df1331da1c5e1ac9fa434f13332b6956029fcf86071fa83ccd2fcbc0840018bda09aebce1d231c9d90817cf4b4b66ae2bf35bcee58195c1a85747c138937080b06ac82a0e3cef1e62da0894f36117928062fc989406a0ac9c4cff41140cd73497a125e8a3cc808483ea679d3d2f39630bb92e768650641b4c4c48b32df011c28b06a22c2e00b79b4f390d13683e2cd6838a487e854747aa12a4c275be5a9e932f95db94bda2efe36a32624d73081cb7778fb2774e3ea932868de12f1667bac3ece38826c1a44c7881951ec22d40e828d1297707eec4ae03be32791675045bcaff8d222624ce8e7b75de6c2774943cd62207e62ad082c1b52b3b66c5faa45b63a2f2bb89e5ad703a9b15528df9d27bf827098f309ccb962887f7a6749177bca8d7029f44574a5fe13cf01b5566170060d35842517d73baf860bf1e48e0a9939e3546aced9e40be1b85d3468aab48d73a2647f654e1aa9119e2c12f8d5cd1343308b1f2a8ea658c1704dc1e39f496ac1a8a883b2baace6d1321a395b1704699dfd337030c3a27bbcdf86663a9a9162121d5fe777e98846975d2bc2fe0111b6d909ae9af44440581ca4618bd9bfd5509a86cdf3e73de804a685c24d1fb5454eacc57867db3f721a440a33cd5026fbc63900cf320ffc9effa32321d32e37bf6a2e0a04926d460e921018f77969994db01038b4dc022305a899cb823286cba9ce9f97fe4b37d406bcefbf6254f6a9f7aee2dfd0bb0f21861d52726578b86f23241fa1c3e944a8545aaf4fedd08abc45e95fad966511a90e37bbbebbbdecf1b3b77de257544b90e333a2974ac1d0342792e14d331f6eec8491d59f3c794705209e14a90973f0a22dd3e430301985d6d974bed283723ce4d1ef0f37dd4d02417e6d5fd420145c74e91ee935618e5cb8b86c7d10642d44f26813208499b02fdc891d0c7b4bca1bdc1020a03e03d64c8e2fbe231f1f85b3d84abfb6084827243a2c8a66f006db332325cda04d98c85a3671f95c1f4508eb959704b7d79a10b31933e97711ba5e941d35f2d0d621225fa7ac3c4dafda0fbdb0bf5721ff2c909d4107ba7ca19cc8244554f8b0cc7ca4f7d264d5a4225203940ea5df2ffd4bf38fd2f434d5bf284f6a788d0c31a1c3c50f1163e92abfca25b4e30ad450eeac851baefc139df64bf1a6d7d307ae7f05cbfc27f6052e203ef1657da0eb6df6653438e5703f3c46d652f26ab02fe72f9522dbdf27d483b309a510104da1228606f67ff4573b236c4cc1cac68b8a3fbb8540cc03342e081c158d700b143e17fb22ca10363c4c2a09484c0e0dbc522083e549edfe08da5d04468f463c2c2a4d8bcac7cfe671849daa98852931445c67b203dc8eddfc01d8b9810e546664e7fcf22a9cde1647c5796d7d24160dfc314b9a450c49259050f0fd36c10f972c79037d0d846469215db12a178cd49de0881a28a3290b9f59640885998a50e31f0ba04064aee28682ca87c4d84fd11d6588157ae93d20e695386cf120b0cf916d241042d96f0b2e75e0ff6dc379a0f51967e93b911386d2dd380a60079056dd6e913c5972e21678fc66465575c6399f644904a75afb194de1ecda7b4bf8d6ec6993dd16d9d718f6d59fcbb782ba18895a428ff09b889dfdc7e61d4bb9a4dc2a1033d687830997c472725a6396b1e4d17be7ca0dd6f084b1b7682d5d9d67b910d8f16ec81f90a44b9bb2896d37024e5ab3ac8af3c785af48340384c9c80cbfdfebea18c93bdd320e9101a639c47e66cf97e1cd644abeed885e08de1506c5031053af08a02d9b8f911eff5df5acc16ef45ff1061e0f5dc860b6be030c61167067bef05a1a80f8704c635fa4b2f0fd01cafb7084e0c3da50ec2017fdaa4a7328940f29bb4cec2c86e668a3566485574b53e92db0a443cca924c11e0a377bf9e6ffe5e737522d814587f81fd1eaa2d03b0f4a0edda342b4ec49a68646622af34c200fc903c9f81e6feaf6d5e75aa5a205bc0d5a7761312fc94611c0fc959f41201d4fdd0a9bc75c25a813b0e75c9e7037b3b55a3c567b1c1cfed684e5bdaf911b466f37ee9b6fbeafbab6b580bb460987b24103d9884fa9c25bba843a60671d2e80409a5aac0ecfa0603d46a75047f1c8dfcf006c7c6db1d3461b32371a9ef2af470a910f89b45ac3a69292c84422ae63a9b889daae9460d9d77a8e7f29438457bab88908bc0212db23e2aa8075234014a59a30b2ca81ad2aaba0762ac0a3277016fb4078d430b2086a5fa64a98ba9a576e003b76fc280f38ea8e4e31f28ce0a3db75c6c935b088a38c808200789cc012c2c4882ddad74dd19d7b9914422da39931a6b46b945e68c02c4428ee68e3e4cc8f506b8071215dcf61b05bbef533eb1d4b0552673c42e46226f61b4fc45d629e0ffc62608355a719092550728ddc9b69175a08974e8c43736d6916d112684c6d4a5e22a1d1449f6e7d89ef19a1ab6fbf4dc48d249ca443ccfe76709d87f038af685eebcd98c20df83e299509f02b46f0b9fa41123507917e83045e14c4ef0634515e92fce85cd0db2d0fad5c772777b4f7f9447a1576619184f871ca72b8b865d5ddce075a90bde01fae5d025f8c4cea9389f0db00af0c6f39779a6143100d97eaa8f76c48859c962307dcb2d70bdfeff937bfd12bd2c44457670dd66af8b3e1a204a98670c2f280fbe014dc9101dd0e701bbcbb6a0fd44b0a3a52ad572c494ed42e079ca990a219ca6ff7e8e92732677391cfb4b860e524b0793581e6bf46d01d9a88998d8fb852b94a4f7163e375d5c151975115b2ae055d16151606b775871ca3468218e3ba66bd8ab31657e9ec1a0367b5ed098de8ae44945ff12482557cdd6c743e509bc9735574ea58a723e49d64da8c515857b9c8aa0c2c3d0bcaf25d27ca5191104498ced4f04f0e333be86f2da946959b302aa68242ab193c242e466c46ce8d856f61d107e6b11ab40632f1b4a108a62fc90488da4e277702590033c237bce657a0465c7d3db8f065491f1cda78034da4e6795677e9102b1094063a5563e3b3417e04cec57ef3bbbff42f1e8039e6acfe6efea7a58133341d15ccf3752415601a9ee3ea9fcccad5fba01abe64af93058301a9807f603ec07c2eba179be6cafe0a3efd3f4acf356e064753e875caae20c255bf70ed652bc661b68ffbf1adf659764952c93375a4922006cdba87b15127a2568a311115b939c46b0dc590332e3a2ab8e4daaa4d03538745b54777a48c572f9ccbe23d3c39d0402a6ce5ccb5bc54f784a073e2204aaee8c1fa247657bdcb5e6d0c0c6c003fa45756ea53bb56842e18d402a444d4864ae0f2ec300220bed4e98d9980d9478178397d698a0d99575c88fb7d09a75ff18f819cf1d7e116f7a9b921ce17d2fbd71291b8a1496f0e9cd60a841f47e00928fd17e74a311baa3ff563293a1046df6d9f2c471eaa9fc1bb399668f9e84bf41e9f9b36c617f7fda29a6cb679e86311967a38d76be34b080e5af0253b4929ec5aaa533acc6e2949afa5f1b0035cd8ffea39c1f41391d69c7086378e34dd27b772700c9cf08d0915d5c7150566771cb05fe32e2bf2f25ea48d6a36d746bc257d63022ce56fbe391d9ff631373d3bc2d285152c2d06cc75443c844caee4dd7f0465296adceed64c3ba8d718ed70614f0700f2d423c1c62585febbf5301800ddda329af153823786bca6a352a0875ea90517339d50822888c628114eea8d38921727234c298b647fc4cd0fa6446a13c752dd51d655491f87f46148a488454f55808bf011994c50cacbf0ce7cd5c7112f0f924c3b950aeee20b35a500394edb1ea87e5a098c703550024f5164ec4484674309eb89599338568bec99a0c099ddf35d30d3a09ac898eecb59d570161e20e9752d464152443148b8881304e7202b8e6f1ae9e806faf95ada18d8c2784ba5a960b9438517f8eadffc5db89bfaeae90f887c37eda9b235a043bb0f401d01509ea41e142af61a039d018e59bf251783462c67bea4a31b600ce7d42baa850c28d9c7c03fa65dfb65a300cda4a071632ceb4840f5f2dee72f743a96c3025a7c12153007b1dd513fc737963c035eb0d4fcac0cc12ee66eb1a3e7478adc76db5d8531e1c8fb4b328a850d7dc574777018d6e1fe39b4063d0df84ecbdf7965b4a29659201400b230b5d0be2963d5a625c686b2ca81963324c1ae39a47501a02081fbc08f1450938362c35229d0de6181b9d1a4fd8e8d9a1ce9baa17960f902c20370cb125ea7673330608d7182715d4b80a020395125b36aada68414288313834e062c3e602b115ab3c1ae37c534222861d6766e0f165736cacbcc4acd898f8f4ac595d712d417fac80c87e84d48e1e3f56407c985947683b6dd0307da1e189539ded4620fdf0848724556cba3c81d9fe5f8b666d8d172e38bee8292366fbcfd09324c9328488283ba474b961cf3528648e48a9c7cd86253eb0c0c3c65862c27862ae0a6047630c72997bfd08a244654d1a33418aa8e1c42555434b6842cf9a182a39888e9823a2e771590c11b09b4baf7beffd1437d7c42855a0672d8c19ce872037703e9463aacc12323d5ea0a2864e50ad8d923b8570922509186cc8d083903461cc5420ea590b3365850b736b6184708e0bf383e656fce8590b53c3920d1343768c6710a331874558ac0acf99334da6ec00e405263892c0d4aeb064363f4a70522f84f9eb98cb39c9189db98b89787fbd373dbc7b5fa05187cb0fad2b1c7646539b03c40bd4b35675a6a33687aa30f502526ee2308982656507223427e5860c9aab556179cd0182089e97aaca872a43f25009a1e18cd48d2ede4bcf5a1596193c3da56c3c757a4ac180c469d5d90b9a296df5f482262a055c11129493cd096a4e0e6c92ec69e6036a6a371aa0b43451b2647365a45af0a202a6679722b0c4cc81fa5323e9191ab967e09bf6ce172feccf17c7156670bae247d2338491490ed4b7be4723518fc037698b4c8b6a3895f46ffc0e82915798c169fb481aa9844940033d6b554c558ac6113b6cfc08c09d17983b1adbb2d8f8e9debc32d0b306a64a63dbfd72ce16ddc596b3d9da2e5feee27befb53648b91146df7b654f652bb2d35b06feee4eda4929a54e66f0627842d7f2025dffcea20cf4fcafba7b1326334cd135839a81a66e85e8b47fce7356279dccf9eaf9598c4db7f3457d4b638b0c55b4b57afeecf48ae79c3ef9ac422daa0b41e060d3d3ddbad7d27237dfee5eb2cb1c482dbd5fc6f09722f74e52c7972c6345790ab991cdf6edb57656ead3ba2647e65e6be79c73d239e997734e9fd6291dd15a6bbf8c59d2136b3855d252199da2b6d6d20a5eb28ed31f7badb5524a29a594ba256bfd5b2b6869ad158fe50a955c41dfaf967278ac9f6580da5231227d5bc74ab9a7291a1d457292078b1e2b3578f4b8b139329aab7283a6b92d555cf6dcf0a1523da76ca9a27a5a17ad26b23f7a4ae118c2a5a7149d22a6d4122c0e033d6b6096e8aca7540eaa8ac3679faac0204f930c8925a763740dcf1b221fdf8cc53c0670f8bef4ace1d1d256cf2952503e6646d0bc60a9c2846a8bd5942e361bd373ca4e151dea2955430b9822b302f72d9820fa65ffbbb684abe7bb0d1770df7e0d4ba8a29d2fa6ae4e6f30ddc4e0c04a419932513627264866d2a4ab808ac90f4e890d948a4a930ef5a482a2d143941cb2874f80a8b30a8a4688f5ace1c16ab295087ba62263c1bef762d9fff798ea0a8c5a99f62bc7c94e932b5b1a2275f60da3f5a2320284f1bd35aa257d81f6bdf7e27b42cf1a550b78c8c55e158aa7d7bdf96295c38f372fb85095a58ccfe5a893d1ba81a30825254864ed0c46e79c458bce3e3b670e8b554faa2871340a3da9b220b93d887972417aaacd0616308a49870a0e4010a1c58717a636fe22054b1555162428a45c71a339ab034b5ba067cd0b5651d19c784cca1b636b82b8f1bd962482e7e37156214b6b9a398b8aa69d2c9448da2808ffd4f7f358a37b6e4cca9bfb39963313286de7efc61b2e362702abef0795e04cfa92952c6741987c00f7539b20eef98256a7e9cc8d4e13fd6715e952eb34c4a6cb0c66486d96e294c244d3652ead972a4f5ac6372902888614d131d9b3585113cb58ec57c858043d20ffd49f47d6b8e162e74fcafbebf2477a9fc76e82e0033dc305cc23b4258904d53f9ab55d82fc25e85a585be97ffd204b3ea0fb4a46606e4c6fd33757481112c4078d224a11b2a5e9c362294ca0b4dd39999477f7f4b3b5d612e9c8fc24d45c9240df2feb73a4e58008aab66f42cf70011a684b1229410b6b2bad7bf614a07e69adb52ab89e24d0d2bab57605aa89e49fe10907d899a4b6afcbd40987af9d3fe79cf3e79cf455dc2feb8b7a4e9b399292945292f47156ca6df9e810ddeb355f58ea72cd17b586e17c412d08ce17fe69fa625e97e7cd179d77dd7c9169cef30557396ebec016e3f9e2de7be70b6bed7c51ab9e2f2885225a5dfa503a5f388522ba2eddc539347fce39e7ab703d2da64feefb1c9ab6c59c3218cc84d75a3fcea913d1ff7ead93bc5f0663319fef647e5d55680e543a84e86f3d86a7bd03ebcff976dace73893d28b998cb9d97bd8e26d1ab0a65956c16e672c7754f34e9aa4259a58ca7953fd1a4ab0a753177b9279a7475b1c54f34e9d66955fa137d5a4e2bdac45fb9e6d975a50834256dd61c9a4fc95b9b43f3913acf45d8b4fd923211dd490e540a259639d72f34aa4bf5a916a94d35485daa3e6a53dda13255a52b335b5ab7db9b2cac2b33b73759565548a060add6da7b2fc698e3b2cdb952cfe0bd18638ee372ce5d478239441f831c9773eebacef3bcef032d0856ea6006bbcef3bceffb40100cc32d9775b92a7557767996077e1f08826118ba5caed70bbc32136e69fa2e2d4ddf7573bd5e592f2c4d5fbcd2f44533e24dd3f779a3e9fb64fdd89f9f4afd27bba8d51ca24f9b6a4ea06811da447780a248e81365babda149b406a5e5d9d2babda1b43c5b590ee5369ff22877e2508ec4a3bc8ad7fcc969797cc97db892d7705a9e7b3d4993604655f12b4d9f9ad1f4a915add556a734a55f4e2b2330315cdb34097388be3ba5b4d66aadbd175b8c2b75ec94d65aadb5f75e8c39cb71953a67efc518731c9773ee3acf7a5ea5ee7139775de779def77d2018da30acd443effb40100cc3d0e572bd5ea215c54a5d0c5daed7eb258aa28f8fcfcf8f096bc244a56ee2c78409180c76e2c4091428500001c56c2c56a9c77e422313f44dbc0918ecc4893086ebf28d2695a10863b88e015920a04a1d28bbf21ca27f22bb66f81e5d8e405bb22acd21faf646a1c439dddee60b4fd3bf51b61767bcc089c14b8ddabcbc409453c8884400e176f65d14d15d8a80b30dcd55cd711c478a36864f659c6b518c2bc51634a7b9cf1cc77199fb4cc442a6fd65736a4ed9424397325d67dceed860830f2526767685c588a64ce5a1742a8ff6da1c22ce85f000ae90bd9027ef13d2a4f36e27844ae8755ec77d4035c4c9469c1bb614f122a4c70f77e79297ad9867d6a0b6b5650b8b9e23a06c6cd318dbe043638c2fc721b95c99f3cb6047872378289d89ea62830b1e3725e24c8a66be9cf3113e7605c765bca531d6b8c21e63cc45d550f5831b29475cd9988bc64b7134fe14f8662a272c742b38f231a6aa418fc618632e731cc73d550e5930c61cf6f4a4ba218c0e75f9443f3888449d7361f540ac476750e7db7dd8751d999faad00c8df03782116e58009307098eda962a534af0959babf33c6fd1d2395b2f4a55687a63285b7144586d35db2546617faba151f79d14d70ad9bfac0b54f73434ea9ef3e89620449ab96871c9a3811e7254e961071ad204995a52e2522d45851c37ca56fcff0ada02734f35868eceb2153231767f858c071d4f147a38862a2a0d6dea2cd0734b93292f505b62d8b2b425ce531c11cf2d315c7c31de12e749735c7de9b905cb081d56089e9285a5453db7c09153db82036b59824e76e9599b5242eb767a5a8133660a0e3775049ebae25c7a5af1c18ec879548a8b47a76cde94951894c58d1515931e70871b75cf97a5a95663cf2c160cdbc9ff82ac3d7f6250c10462e0e771350b115ccee017840acd1da8102755840a71efa111376b51087458a303131686304293d2f945289da56a2eeff17fde18835159d7c142b0f2830b560a895580169b94a6212e9015ce7159c014799b7b187d4a44f41ab5c8f5fe25bee9cfff738dbebd115b5521d7bb4814844923bed2fe1e197482f7df7f240ac0f74825ed3ff7dc9f832ea307d034047096f63eef7b1c558bbef707c723a7133c4e122db44d03fca39955e344db34dac4da2049a39a71e383b6bdc7b65ae4bd7f86aa42b95685f25315bacafac6a013be07ffe392b4bf37069de03df8de83d34a97188ae2a82ae4ef8d59735657b5e8850d5a9a6a59b50869fb73376eab16b9ae506951a26dff4cab45b3b6548b52e0926ad1065fec10f144dbfe9c522d428ab267cf9e3dee4ba52795736bde3c4a9718aac45056baac35ed9f827fb67e1d5fe1a4a5ec4c1c59baf08fd265f6a74b969615556baa4fb568ee015c51b26dfbf3dab4db74e94b55c906558bbc4695fce99267f9ad1679152d4e4cdbdfb76ad1dc95c9952e597a520b1ab46edb92a5d32a59ce2d4a96f3a64bcfa2512e7e676511a9a3b11cc4189d42f4694996a2a625d167015094787f6a4c041425062d400507ea7f59c9a012b493449a96959451197d4baea0326aadc645c440041c5dada654beb9c2fbf05dff5900641357b8dac3ff7db9c2d5e17fa4a532d7cf104648662a73916236f24870dafb354d6fe9a3679d5488fe04bdf17b1fcf7b79d3f33c6fc6e62c4aa15ce16ad74fda22244b77d52862f8ae31fc29ba3e85ea43ba2af9893fff22cbd8c4ddcf997f4e32e8452a60ea27c1f5398ba2ebcbd8d7d7fbbc4796b3a63d6f0cdf4318f36f6814bef73ede8b6429eafa22cbac2b59be8730bed2ce9fb146a675649933598a1c59c63059be8ca874a1ef9e355d5f34a7b92b5cbf4fa3d1c05470ceb2c35ffa589f9c289622f989359c3817452a3341f4af302aa322955130c6715c29860ba8ba3ead95487e91b6a8ef9bfe0caba82ba6d58ed575056b455ff67b078a1269a54f29adaee39bb485fddc7d0ed199a64fa3698ef429bb27b0a40af857c8da2707f41da4617d8bffc3600d1b5035fecf2b754c9248d869149ffed7dd73a6b328971cf77aea1252d0f52faeee240b2aa3ef48c472d61240820b9282a0e9d38fd9c1a2c5fab93ead2427d6985aee20a1cbacad0bdf5c51fa93a635015446e7f4c141f9b907016d119449185467fc2b90807e0a1ba02f83b6a0d1f725ea3534a51e44d3cf1c7e006d41bdc9045ac7a953d80095510c3811cb19a500dae29244baa7cf00dac29222b8a8451d299369ea02042aa3f5e9c39a88fe64996c38986922e2f7d048a4b22a14a32b501d0b8b8895deffee945d5b1e71a4756d2956c0d4955c812ec0ea195e32a804fbf52d098a806a4b6543fc9a6faef8565099a52d66adb5d65a6badb55622cfa16b4d405d223a4984fb4aa6a0b2ca91b90ad5af15466595bebb52988f9648dace219fe15a04fe538bbea10338eda4750efc39354492fcfd46a3113a600377173488a0e91c3a204893ee2f18b0d70c189d8611d3f3c31c7595333406bfeff3ee0776dff76d307f86f552b733e45c48ee340f0ca796caec745a6da51e0486a5b2d085f62f5dd4aeb3b198285e51ccf9abd6c7e7fec762381613c53006d5305d7a18c303bd02ed5f561096b23086d71002b30a553b2dcdae4ac2f034256373687e2c8c5161d807d4b061238731aea63486cf211cc6c0158958da30c694953e3384e1b030069d2e8a73288c9135fd1cd22e8c40180302425e1883d3dff77d9fd3ecca398731bae99de7a24f02ad9d9023a21b1919d9a4a41b1ae1d0e8558f8847c4d22a69ffd22ae90a55a1aeae68124df2277f2aa795f67944f49fd3b38bc22071916f5621c432c7f08f8ac0dcf82f8c2ca31486d730867d19014989afcb4efb979d9e6fc31831f2739724c291930c3ac137fe4a12c1749c7a46912cad4b1fd663003dcec1fcbaa74e00b4c7d13674c09c3fc939875e335c8b60be0a3d41f40d1d60424f32cfa1c985313a9de7908725642aa361095997483a53590d61509d3fd086255c5dce40f086200e4ba8ba3cd2d90572210caa020c4ecf8741f524b3985fa2c8896287455114bbce155eb0fb6ca55ed779d775dd644135fdab4b14684a2251a777be598beedb9ffe73d3b7639093768ff52b7914e41e1a75b3f2bbf2c82013eed347dad78edef7e459914126d8c78fc9a3a04caa1063ea9af68fe1d92ced5f1f69db47da489b84ca8d33b83d7bf4e87d1d706f335c7be0de3447962650d232ee4d73ef745b6e52afae72a629929d555a69a01ebedb4a6bd470f72414bce75de77564387c9db6819e54c2c8a9413aefd24eeceebd1cfee1b9edc82b503ec0c9e18a16235b8ec3099e8b85e49931959526cde949f584482ef244a2288a60e63ecfd2e1f1832dee4090146378aa7878a63c3c603c3c663e2e34f29ee0aec3b8c31de98ff3cbe33cdc610e63bc84c6185f7c87890acda6fc2442c56a5488bb134585384c8471d761e14265c35ece397b18638cb1e7e59c3dec1d81c28ab1ada6ada75babd56b663b353b51167b9ee7719907eeb4b4b8a818ab6355e7aaeee052a5e454c5052b2dec7ce309114e26729e16d44fe736d749aaa3d469fd10d2a9d189ca353ab64e26c6a8d888a4902109ad2152369e3c04ec48c207ad2e4ad876d8d86d686c6b5a375c1863213648f570c6852c355ea30b969395820149e7e3390f7f9e1774392e672e73f9de7b3fc58dc53a1116d3baa14bf1892c61244b0e4196f03c09e32dd411f15c55a9c201a7c71c193647c34c9a13303d6b73a2e63cf9d0bce62425b125660eec42a3fac109c1acdb97cf88588c25e1238920dc4f47b9bc3c7a9168ea9078ea7068d4e1fcc3613853c0db13e8799ee72901ebcc5976088cc2c4989ca78ae128fdf8cc716e3473d8dfe8f9f1384f9fb3d41735f80a404f2a6080c474d082d3bda993ed0d3cb67a50c2cdd41a67810e183a45b8b8cc3d1962e68d131410223a384d8a4e142895832ad35012e2cd18d89b2a27de3cc1dedc60a2f3baf4b8e1917a769181f6e64608ca794313398e737313dd44b9396265e566880f97b91462c011c3530b2da400cac67b76643733805bd624f16a6e6c7462e532c771f5bbd379c9dc1b971070ca191c150044b8ca705c1b321a3f0c6ce3a5b3d3e651cf2e3a9cda0c51850b6b6d9e3095db654b947ee9d9c5cc9618a5ee2ffedb60270d97257370d0a045458f4ca65988b1152926b6571cc26465e949911caa245942766dacd65a6bad44594f2f738cc846e48a25ce7c7da0e1870f41bca1fdc09347736c9a4c2411428f9c2b5b4ca6a46c0e0f153d506d5ed05c069be3f09d36b359e29dcbf7b2b1a26fe6ba7b6b6c86d077c244588c4d53c8711c0772a06717354fd82cd115294a18586401904dc45fb2983793a548c932a6ebeb5b65d5048dc9d2849285be973341cb6041e48405d0102d232c8ae8f9669ce849ae4035d14745a6885e81ea1907d0214021c50293863549a65a9081485597cddda1e3d273ea071f0820437ee939f5438e2b25574654e859bb52ba6a01cd1e8b664b0a4b0d1aa6a7d4172e4eb53cf7f527c7fd9cf1d298e47079bfd61744fbf38ac06aa7d6be870c40ba4e93c499ef18cd3dac9ab96282c3f7023d6b667ad03f7a72b151430a8292684ce9a18716ac7e2831002847ca24b194021f4f5b353334fc7069610911f6cb91a9a373ce99bb97eb70e46cb16ce60e630e572961050d1e1e7af8b05385b91fae7bebbdf7de2f67a6968eec8084921175c820f9d10166ed54c26389abc2c42b13b19517ad3269c7550ed7ca8071bd4ccf5a193965d4883cc4c947705564b890b992c920b9246449e9a8f3da61c3158238b050ed509374041142e89071e2a4700cf18354430aeee899014e14284fb4c810b9a18a8f9e5da0bc69c20685381db05165eb0907992e67e6b089d1c6a9c8edc98e254e924812ea925523c796247792ec8944942d4664b92df9c8c1c28d885215f00051830e2f4495e121c7aa86e3e8f2e7c8b9f7e7fd7cbdcc89a3efc362b568ceb961ca0d776e482293b52f51cd4a498e2c31cffb43a4ed097f087e956e521eb1debb8447ace4ad423e2bd26bb457d6ea8e95bdd92c2544fcf5d2b6b6444c563be26fe5cfe451471e4d29515035ec59bdb39dbcd66a47f4af5f44278316e0ba7e253128c016216a1ed39257472ced92ce2a6a5074c4d2bedb1823440e1653c6a7262db1b424161b903659682c15c1a264644d96166a57a2e20c2164851a0da6adc7963d2bd4641560ae4554cac9f681e68cd690255ef0f850e22987fd555a9dce8ac33429a2cefefe4b9a2824f60d593ad0ec6e2442e2695c6093647f75881eaeeccf5aff8125e9cc28650b90aba031e4b4da01e4060078529620e4acb8a241052403aa207efc108030578c3061b04303ab64937c106136290419e80881b316f9e480b2b483c6ecee9176b6ce0109d639629e43007019f6fca06377230854f6e74daade7469620397197a0cd1b2bb7156e1d99fddb2b424b6b26e4864ede084c6fe38265b5cf6ac1189c1b6bfceeaea66e545d9e4447d50b538e2c4d2504b4ddd5899ea5315a270e8d737b549d3af4955c98d38b1344c973549d3ff5c2f5789a4a7a0f1126477236ccafe5680e0f865908db4c1b14396a600583555a0440d3c061a964052078f281b41090eb49d1f69e3a63944bfcb58c8978c300cf7b18c9562b9018debfd3a561b8660d947f9677487a91f7bd210ec23edaf1b43236eecc82013ba2e8f538faef763dab91ad34e961bd032621affdc1d26311395d1c741da88f54b197ed330d139c860eafa3549ca0b4fbb1b3190b23f4a86ca07ab6ae50620b66c47b068bb1b431e2a151c6e6abb0b40ee0ec00406dacea30bcdfe28289ab171a15264ccce63109ded2ea0d1a1b6f3bd730b0b1ba89dc7cfcbfe3400672d02729386b6e7945da17d39b26795cb90b08938b5d03863db798c3939a24a66d8b30ba07879a658d8f1b48f66cee3c615dace7f62cf139d9d49b01b83fc69140e20b49dc72027b53f59b5e7fe6ca5b6ba680d2517a0761ec9aafd5db01b8fe6158f20597b669780b3bbcfe3d14bd933a2a30c82ecd9b48d49de00f1b1679916c4cedf75ef91473e440aa6b2f62cebb161e7efc8231f628992357bc6bd11b333397d094a9ca49dc70c82ec4f88da68141b1a45ade85516b51240d6119e4569be65846f51259ab48626312d61d1a50d2a8d6e1541b758d01bcd5243b386688d42a5a15003a04fb4e98a3609c0834ce8f21864427eef3df208f6e44d68c42687aa11213a94a6e2e7175d9fdff539bff7f9419fefdee7f5ddbfbe23834ef8befbefbb0f7dc60788a302cebcc6145c230a6640b08132e5ccd29446023258dac3f16331afacc6580dd9a2acc489a54d38f23e3fd236a13bfabe7ba4fd8d78c44bf50b5ed29469498c38b134c80138b3bb9227851193ae4fbc0198a7971d4134ed4925aae92905d50ec2da41dd1cf29f618ac0216a4f2b29334f361c4bb63dbdd0a8dc76370639d941d94158fb9bd4c71c33b7fdd55a8688246efbab5a43ac6c0b6a8c44b954524692602a584b1c9847172454b9c8a36c240223cbe3a4b34467c903f3e8539698d03e308f54c8949edaeec62028fb03bf50c90ac13c7680458ecd05e67172b952436d77230846f627e6d1a3a4d101b5bb3105d5fe44308f6e85c31da6dd8d2ecceccf07cce3dc020415a8dd8d2010d99f0913ae12495f99c177bcb03f16e0ac4547be03cd0d55fb68060427889d7fe648b4ecee8f6c116f82d84737eeee66009843b1df12631dece852b30300672d0a824175fd0ac5481da84de5c4e101b53948f24369ef3c4e2b513ba2e6944d476d6ba102c56a7f17cca3bb90e686dafef0c5b87395483a77a991e5b6bb71ee8f08cc1ff52507d3febc461b3b14cce3c4a2c5cdd5f6241668a0ed6e4c91637ff6ba4a242c409240ed6e0ce2b2bf0ec0598be694d517a6fd556daae77f1e80a21760eaec6f62549dbf0fc099459ffd75e3511db3e7b667de9ea3a967cfe695237a6348d3d1eca373abedfcb31182a0da99740af247aa3330c9c2c0c71edba3c7d63e9a7120660a6de79fc9e630d999ec46dc343e69fa758a58e2a56e3c721f6298f68cdef6a4219430ddcdec2a91e01c71b2da79fcb6ec994100349009096003164303e080a8030f3e580100b2820ac65781c1053120142760263ca8357b489852c007d7d3beae8db6f0b79a5299fb4c2a9be4b55159b6493d697721d67eb54f65d49bf524df5795f484613e9d4f9968add54755aa3054263d83e83993acc0dcde6465615d99b10293857565b3d645b5f65e8c396e5e8c39aeeb403087e6bbe066ce5df77db39b9ef77d6178e581f39b2038c3f0f502ade67cd77c5796ebf5ba7a99d1f3452b3d5ffcc42c3db1f4b4cda1f99449cf207407ca4483d0275a8436d1a52c2c4acbb3b5a5757b9385b5a575bb2a1255a5567302e548fcc98bd4f474a2e76cdaf224bba5e75b2d4ff21a3410d4e6535aabb522e8e963396d7a4ee9e9620ecd77a794d65aadb5f7525a6bb5d6de7b31be1763cc715cceb9eb72eebacef3bceffb40f0fb40100cc3d0e572bd5eeef2d7eb05ba288aa0fbf8f880fef333c732db39963fc7323651a040014e20201f7f7e401fcb373231cb98114c84813e9eb027401f51885436ddc99a3487e6bb08f37db010fc50d0f57d2c65dadd412043a61d46c75204c58aa90ba4b289b1e3eba2599f7f0a2a13eb744c5df6e64e046358fd81e1145da191f5ef4acf9f66f4fc693587442b23307afe2b8c61f5b5cd2131348af9ac505629510685fd94374bc34e844628804e000101c14cfc0001f9884040402f205708040484af06aeeec86769adf64edd282adb229659ffdcf4fc6bbb53b2155e68b482ca66bd69fa754abbbe33b8b2466d117df49c4332ea4dfbd7f1a96c4afc42a34f89cae6af50d3b4a6fdab94e84f42a5a38cafe643cf6f09ec32872fe8e044e12a917cb4bf8f2e3da0fdc1ac2795511b9d725c5230d496a9cfeaba1fe7dcfc5ca509f4b46118231bd9705299287ad9e3b0773deb799ee755cff3a87b33035779a465da3f00ba9c807652a4cda1f9d773962b6e0cc7e57be273c4b36969fa9e68d54ecf2a33b050c545083451353c81c179d8422f37251f5282f4f492554663db8f9717384b60040115a606394e96b4f11d3808f1f2727392b9da10431ce1258f103c8ab80eaa2bc6835b169a892c3d0e9091884af2b245551161c691e35ac205b7e2898d2f52eca061aa7218b004d12484ef0c0c7ad860d950a4c6c62f68e1018c0d0bad831f71d4d0da544952041e77c10a67bb3205c2b4f9ca12fde969bb52048cdf3c8d763da727555a7a2d2b755ffa92ee36508be654402d9d56ceadd895685512e9d2057d8faab1d89cf7b362576e9546c8a8bf9fb5598d697645a3cd2b24264b42035468fb29e8faba92b736df5c51e62bed76493656d069ef71d2922d3d6b4a8a5ce9595bb2a43d6bbeb06104e8f6fca64b1776892e25d522673385fcbdc34a3e78a9824a9698a98eb849bb4c979e858d10f17e86f8f547aef73eace0efd39f3ff13f3f37cce74ffc091205aef7e14e3c7eb9fe048571358ac2acb4ff090e760228f6f4f53faef7f9799f1f1f32e87e055915aa0af9bf6af74afb8b373c9636c9d2b6b47f55017f085ccfb8afc20c14824e70c1def573fb3c0a4127bcfee77f48149cf8d7cf8de24dfccf73b037f13344e1c4ffbc09131198dbe72330370a145bbad2b4ffcf18641f69a37813e3ac422ad43fe1c8e7bf07ff84a39ff73e7c1566a000bef828846fe2ef7f1ea2007bd77b88c2897f3da086eb5feffa1719443f56954e8cf4aa0af9c3b26a92f607aa4b9c3f8adae4e1e85b55a80aa9302304ae67cc88c0dcaf8fc0dc277e060a4127801f7e48a2c0e7c19ffbf528049d10fe7cf8739ff818533bec5dff797882cfc37e8628fcbceb97b49f60d2feaf26ed0f1b83e823ed174dfb7f16059f07df43147e2230770df0c30f4ff850f048cfaa42fe211974df0494dfaa90ffcf4893aa90bfcfa8a4fdc131e8920f983484923e697f91acbd46ab204a46697f246aa34dbac450594bb5087cffcc949b3e302791208982f0bdac5485c0fc5485f25215e26a5c1467e39eae38a82c2bae86b302368ce85f668c864506e0ccae72a6ef5fd23a07f3838638200ae3753905873f00c186505bcca830342682168021111111d8410778c41224fa3cf03eb0c9ac11e2ac421d08991353746d2d0038c3182b3437a79d15639203d7e2113912e317a111a66b6c1803bc2ae000b455b11c97c86289d58315e01ca13807a5678b2081c68840af8311f47c1780eda07ae014844baa8169f72945979d163ddf4330d181f5e003ea4e6ec3b4f8f100f400fc009cf3856d11426884410e97485a97471c59deffe041003deab3ba13485de4ffbe2c124004218416452e08f0e21502e84ea2ad12a7ac0568d3744569c4ea42a404f0176844ff090276b5002d11e21971fe14f9b8a0040041180b910061c4d70b57087e239811fd3d77eaa6d86591ca2e85227ec06d8c806b6180b68c3bc500ddc915e0824c0926c222b07441a4ef97447edddd674de3770e603253998f11fd398cdf3a477e2e2801ec176b457d568f00e08b51972e25076721cd9432eaf95e7a017ce617a015930bc0192085d7f75ed2fe87e7e4c09cdc28426884b1183efdec221ce71d815a319504ab301ab462447fb76226026c01ac085e0d4047c8368ce85f824ee75711405b25facf8b0d005a307404b75f44bf6fa9447f4aab148af8fa924e02f5597d04105fee00f471ecc2b05e41738fefbdf7620ceafb248446f7e2bbc10d68eeef58c6f4fd69ef5b90f13b00ffbd254ce3e74619317d5f8746f762bb2b021200522862d6f4a91148a150d81da79df573220e0630c462030108c9340840062b00408eaf624e0c2e48116441051edc4bfa477d2a06282b17f6ec0661c414374df6ecdec9e10059a85ced991503bb404a9c2635f6ec820102364504db0d36fb68e671926801401a2fd78604cbd5c29ec19a44b08383d43e9a511c74c040dbf48f66f30b931eb58e86161d3e5cf64c03228eee112c04b9b2d56d6062d8f567aea50820b67da4bd631fcd603cb6259dfc67301ebb7ee04b9eab25fa03e48e1e18f6cc9fb86e9a7e35fd4d22118876a3c4d0e5724dea1364cef0258aa2cbe7e7e727abc996dfa4f9a27e4da3fdebd57c5145a7b857eb6269ff9b66b68851d9d57c816f0eedfffa6a2644fb1f0cec6030ef0d11a59b75b32ed6cdba59b44579b1ee9b8bf53dd11648a0680baa69d0f411f389a1365ff868ff597e55b47f53da5f84d23e4bda7d944626dacb570cfaa5a49d32d9b4bf0844d37914bdb1031f8644ed0f05a53e22d0bde22b067a232da28c11dbeec651cdfe2a00bdb1e2c0c38e6d77a30aaafd59007a63073f1859da5f10d8d9ad1e6adb2391f69702044dfc5cf00aed7b23d2fe5e60fe62b4c5953265f6e907dd2ada3e7dcb46db2a455bfbd8fee88f826274e98dd1f4cb91882ebb20baa73954dedb8faea4677f8835edf73d8cf1a3abfd6b49a02de28dc2366bbef8d19504da22d6285ddedbd37c619fbef521d6afb539543f6b0ed5ffb9515fee2196f7766ff6ad0ca2fd6a471103708a188446df1395d15a6d0ca2cbf86a1f920feaeb461554bb23699a3ed2f6c620133c2d247a586defdeaa10d2ee46a46d9544ca4482e9e31f641fd3688b9232b9b5f636f5a46285a5e9df3c35b0126d31a9545509829b688ba9a98d46a3bdb04bec4353fad4459798c9daa854a9d1252ea2e9dbea9489b628e716dd81b670254d7525016d61777c356dbf1b91b63722ed197e76fca0bea70f890eb1fc9e34fdbb455b9432b8276dbfde688bab75f3f8a445f756856e1606d1feb52f88f6af0a5697f7e633ad8a4a7d7eae12498360d50394ebc6d1213a2340b941db473327ff9907b52b9715d3eaa9ef5bbf411cbe1c77ddddddddddfd397cdddfdd53183740658e012a73eb82bf02fc19405b5452042aab459994b9537fed2f522d55d1777a6593bad2658e928a72dbb16796c68d2a54745ed8b34aa5cd9e1f7bf6ccd2e88281e7e88104162d96cc172b4ed2e0d0e34a8ad49c1e43eca359b7a48a611302903d7f06e09b6f9473882e2a606906375a36a8922062065a949c499f681ecddbf5ed18735aedc55ceebc3ae6cfeb32e82a91347d724a8fd03285b6c50215373b56348d407543961cfb683694c60626b294a50a4d11a93d958c10616a3cb8eca3590a2d2b188813c7c1a34615fb4733978e19b653ed21e4881efb002fecc1b203160f5578f60c76431e257666934acd854dc9212d52a6d0eca359d09524b613fdd90572653b55e1f15b0cd72f227d122a7619316dc7f9fe1ef09be600fd334ba65ef881881f41746e3e30e1e1638e18650b9724323a8428c1128413347994ec9983e387245e47da48c1b1c3101ae80099d344f5250c1bad2e4e524d2ac2dcc05ced192e2344d5171c6e597b46a7b409037ba107551c271c989c6142a3b467f44c151daeecd9cbc806630c75d6eca3991fb19293a49001cf0f503cf6d18cfb41cfbe4bdbfecc47c7056df6d16cc5a8b75ce902a60619a4e030060d104f51fb6896eb84d9f88f66ce74c4be3ff3e1e17160d2a95ed289bead1ee3ab5511e2691fcd381f77b6fd99cf9066570caceca3d98a6d4927fab32965d7175fae45472ae6eca3996cdf3f9acd29db89526989a2b58f66dd929c7d49a7fab3978e6da91bc075a8d181da33ec454e98c4be7127d51a1b41ec199d8a1ae7ec1b5866224e0d7bf6d16cda91b3ebcfba384760987de3ee4a3a510ebe598b8e3ca84ac22369cf28191b7a828e14b1672f231b388d25583ab25a8832d99051eae2058ad29f399b9b944ddd06ab3d83696d4a3af9cf9fb91ba0e63474e4b8da994c81b533e95db651aab079da471ee5480e33ec594da23262d9b35794ad465485aab5406f53157aa221de26ba14c316a8dd8d63154a444d8fabdd8da4152e5b259238a3b4bb1184a4fd5170d6a20e829859aa16041eb49a9cea5f6095634d126dcf5e53b693cba0e3c6d3ce63501b0b439c3a493b8f2000a14a5258503b8f1838d94137b480a569e711033bfbb3d427175464cc0ea69d47155a761ddd8a8d166de7f189583165945ced3cba0f4af6477d521b57b0b2761e2f68da1fae61cd4d117892761e392b69766c2a51a46e3b8f1c14d95ff5596b37ce25da5831ed3c7e55fbe36a8e384692761e5500d99f8799b2da794cb10546298c6de711031e66953c6bb6761e53686dc7824508ab6b655910b92c5d5e2b2af565ced5ce231192fd711d9581099ba59d470ca2ec2f83962692b588cbaa45970d8e254cb40aa68c3852c39411476ad8b508eb600aa580d49a7647e2a4249464495ab07ac8da1d79b772d09d9d494cab7b526c75d9d3e5b66fd6910934fbdef68837ab56ec2a91e8ac45eee04bf401c199f378748028533fbea8dd61b29451c2dc289ca19d43f77d2cb30c98f69957c3ecdb9974721233e91105f0030e18ac761e1d093c23c49181697f9407293a41acf6ecd5031894b5bbf168266184cad39e613438b8b0bbf1c8daa85243d69ebd9e7c00a785a43dc363b638cbe8d9dd7844cfe8a003d39ebd90885ca53ec3f7e4f946bb17363634ed3c8ab0c3fe7c4cf85cff3dd29eefbdf748993cea1e699ad1feb804225dff3beaa4fc38f3b467405082b0d0f67db4ef1ae7ee887425cb07684cca20d2de2c8391e2e169bb6ed616e9554bcfed6349b5822695754b5aacd0b6c740430ad5d6ae6f34c3b507a896be648902183447caa05afafe7749dfae318ffbd0fedf8f1be1c29da6fd390762a6547bd75045b9caddd514d4febccf0b99a5fd816aa0d8f617829f17765dc6f85a5b29a521759f611886436bc60051dadde822b33f13518a5072c411b167b01fbc1e7444eda3d94463a4066d777f34eb7ec601a10311bb239d85385d9ac4e8d813b53f4b47cfd2feae152247ae6812953a4dbb1b897cec0f5681d0d2dc2a0e1d3034d134457a28edae5259a2ad6123670b89225939ec0f7372daf078dadd586510b2bf1333093b44d0d979bc60866da3b163c7cee30070b0f16801899dc701d032e8c142133552f6ccdbb19dea07e9d8dd78e43696887061cf3ea5ed54ff9b77e239b4a5e50a6ae7318511bb8e1f0a304f3d3f20308b0f304abb1b5334d99f83793c72ac3c74bcecd99db23faf747a57c312700a30d7a220ac5d27881a9ef6e74ac0b9da1fbd33c454d49ebd966c917a9d7689324b40edef025bd412a20b0c64da89749ef0a804ab580b9b98748c219a01060000f316403028181089c4b22c4bd240f60314800c70b04a5e4e9dc8834992c3288a8228c820620c018400408c31cad0545901ac78b2ade49bbdf08f48aaa9882c2d65da42ae413c4f991891ebcfc13ca6f1c4895f45896a039f90c3a9964389943b28644bc3a965ee03f6e9d69966caaaf136b17a08590b74e344bee49dbca0cd71f1466a6209e3a1a70d2144c5832c311861553dd82cf2a19100e4d0284c86271e8451966892a53047047fb1a4e96132ab1ca8af41849b9d981a0c9521171dbced304fe60d980083c06c435bc83299186ffd9407fbff7af742d2cae8a055e26d1a299942366c605586cbe959e4426e417687011bc7fbc790054f4aa9271305878f8065ea65f910d3576ae1fee50e3a34f21db8164ce41c8f7ac73cbe47c42a2c69de26596f69081b271bc51a9df81d887f5daedd8034e96fb35c63e1c618dad114bf9b1963629faf27369ec42f11c384311e0844703a6edc50bc56cec2274bd691777468693ee9eb6c8727056ffaff08996acd4bd7604d7203d2660265b1407137dc8dc8cab90bf690d95c409370dbc64d77f4144d9c9fed2bcd7e7cd261ea29dae18af2edc9cbd805527e8ea5103dc509235df7d85d3ae9ec177bcc3e843b0983eec88f470931ec79eb028a55aab51542ba18bd176b2d2ec78f9dd1e125da74b91f346b06487b22f89b207d5d980ab03d21d8d3736214423ced268e140227755bae3380dd06f67d0bc7b9157b069b626c1891a5307c32ea7dc5c016e5f731fb21abf4f66a89dd6913581bddddcf6daf70817498133f5c36d4968c5d05a66b64fbd9df2baaea390ac247b4f7012856ea20c51502256cf89434d51c5094ace58957684d0f8ab084e09f7ffe244170036d7e6688c4437ccf775831f99ef726d1a9541371de981a1f6ca61132eba82b544bbdfafed2a2a7759c3236a2eacad480fe6c5aa3efebf67c80dd5b41ce203dec70b986392ab5adcb5ec033366b1ed26cc598bcdd99849b808c9a40b02a9bab39987fa7569dd918328525324366cb52030c641a92d94ac73e61efd3fef4028d0c83a1dfdd6f7b8e2480ca641faf7a8c01d2acd2bbda1750795878ad89b2fcaf551ccd2ef0dbfba16c7e8bd15bf41260301330d270b569cb76c10c858f43821bdac4039fdd3b22dc6f5c2d1a50a5a134a923604833b2f43865c7e40227409910808b3fbbcb1ef0c78c4abb5a5a5850dac06afe0fa2dc1490669b118698ca68868ea1ef177bacf40503872a73ee1491ae582f8e5aae5e0acca08b69dcf745e7af63d4c95073e55dad84f193965bf73e9cbd926908ee691aca69b43b489e2af9bd7405911c5cdad99ae480291bf0d8280d2c1682129b97ba2eac5406501639e9d65438e088290edf794e040abe363c7966d773f70fbae4d0b324c0c197cdfa786ae0273ddd312f976f3e2ed62a0efa429551058c8b4b40c0b3a259119a6599e99a4e777116927330e5fb95ca8e350356942b03901c5806e8e83043c9b12e46bac4573c18a795fc3484ceda06f59c79f5429ef6f7871e64c7209994dfcba5468eb7af3e47b7dcced1963bfcb785d7f21359108962d51b4e4bcc310bfb81fa8056c1d29fb7fa30b635758918cd2c3e1cf4d66c6aa2d22a32fb0b2f2b290c6ac8285f68adc9bb2722e19908ec9ae44652720236f97bc9a0955539c6b2dc8879c1b42de31f89e75a181fe1dc840694f5b33d2a981faefe2dbafa6c10c72a00dd9aaebf56b3b819e20ef6b652e11885a2da6dbfe66ecf2bdaed713632c6759822bef47136c6092cbe2af906a36471122a43e72934e6644b4ea47e8dacf0e20a33e3fcc468053fb4f8f0872529c2c12e18190841aafc409905cba2fb94ee43add2ceb597a8c2fe40bc1b71396396e9eb86252aae1a1f46c881116cc74ae6cbd0ae1c8772c352a861684d2685cc5f640b9d9b60e9a2c762b023d0ea06680cd5db66e10eff98f13e32b02c4f59e5971eb40bf7664a470396d531af383a59751bdee1ec662dc7ba9f70231e239e2e84606e92cbb3b21ee3b6430d4286bc1ab4981939c01f2700c2f94f83e38811c1185ecbb2a9a934391aec548dd3e8a24723aca3b98652b1b7482e0b838b4a24875cb098ae8a9864c139fcd2f540020aa4313141dc3089c34832af45feba2abaca25996b4633ceab46c1acbb815b77b9fa5d2e2e33654506e5662cc4aec1ddd294ded02b7715490b031e712b8d849d4426c38efcd2e5d3e54eaa33ba2dd0b09cc70ca859ca7e02d18b4af60779bccb4bfd206bba1c3ed45365c01457c78b00d7a23be1aa5d855470d70b10dc6882d0caf14b256f02c7f0d2191d95f49f595a7666248e75338c35a436615a37597ff97b6fbf00d4ea21b0417fd0123f797adb6323363ed908f8712c85f5c15aadd030178d044918ecaae2944af4e2bda26ad4c9e777360f88544b57f0874bcd3c0144202f4420ce3da05385e0aad8b0188f9580da4d8740326dcee0412bc875d4ea2de37e18c4ff95e340cf974a8d8ca3aedb906ce71585600eca86fecf5781e2237ac1bab0cbd70ec950db99f651e197c9fd7faebb40a2f61566465f6b1fbfe9b680563c488237add46f8897b90d86b99f05960bb493ddd3db0d6ac9ef72c3f16039633b60b51e12a67c51be8002abd684b6cc7d335291e7a6f5cc432cd29da0aaccfe657438ca039a87a42d8610ad7cb05ae94f45d65af0c7b72ad326994fe9a70f8fbbe7391cfb69ad7cf15ae987cc00c03ccf0972bf949625e274fc616fb3bcbcb73b5172435107117b1782f539435ac0e20f7dc08f6d1b3f4e8074073cad961612f9186f756ef9e05dc85ff76e80917679f32810506785e059d931b1de2bf7dce9a017541712239e80339ef4cb51a28600e55ce155353e829461e6b6904abbd474be23ee0d6cec3aa0b67cd91b60dca267d1fc230ae1c197a14ea15c7ba5882a45205df9c5686cc7e116b26b1db2fb86e2be765af17ee41809c93a675ea9d3f2c6f9b140df5ad862babaa9332df04bc05ba2d11d2190b22365a8a639bba932ac6e0561ac5ff3fa810a94f05e72b0bdd3865a8f387d94bbb933169ee9c938a8911ce0938a9bd4759790dacc0d46a6559cfff396b23bb64b8b270016d9af1c2e21b59d9ab92762fbd1fad8179d58c7e1f1b554e8276592045d0cfd3231976691b5566bee3aeda2bf9c4d72e420b30a7ce0fca6c5f8c2d8a7275789350d40d14d3c4d27208fd6cb1ad89036fc4cebe34e9d4ffd7360f69a791d70ba2f53937b18d987e4429dcd977390e7153c668a37650788bb3afcfcd2e8401ffd0907ce7e0dc204a2b1ac72989fbe77dbad99ebce2474e420cfecd300325d3b3ebb4a8409470ca334303f639bd711408c260acb9eb22d9c23910bd52471bde84e4be7d1ef44132db3ace1878145f98d69ea6c826e5086cd99735013a116ae0413d38c7a5ac8f4f19f0c294171e23e07c2aab2847026214ee119a32ad4badc4e44a1244e32ca851c50aede856e5a460e28ecdfccf30775424b636bfba86df7cc247fc7bab134d22f84e11be1891a101324922051e21325900026a0c57cfce1e20577e8f27ef83627970853b59894b73d031e1b18c046e3d6c37a8fd1009fc821c0cf5af94a8f7ddb223863bf8df103cfec0fa354d355af764f8ceb9a12b902bd3d5115b9b1ae3b4174c85c30230503cd00deb1f153ba4018ceec375eaa2ee1403980108e734fd9287a43b4a9c72316d0a2e71bcf41576e2cc39374a0a91304eecff4c23072c0ecd3dd1797e94cd6b00fa39902fc175a1a73b5c31885a798526aa32e9f5552705595df3e34d1ac21ec533983a8281a22a287ac3d34633b9822129d630455364f1fb05beae0ff0185e6f4cd667378b88c6300b6ac62737e16383641c12d23783a34188fc6a27b111210c890dd46a8f9fa62ac2f6dfd3be3f40aa077d48a8b8b144fd08b2c99cfc472d981ed2c8b9b5b3de7d8b0d2abdd8b182b4070177340a512fc5a94f5622db532122dc31f43c5d9d585630b3be6a1085fb02657c1dff420bedc1fa7bf440a76a702574269db3ba09648e64f0b2eaaafeb59a10646ee44f2746b765b9fb4f515974bb19db84b580ac1355138c9c4fb0107ef2abe560b8e6ee5df904a7a544d5d8ca15593f60cbce8a90ddd93c9e6d5532e47cc115eda0975518b7a8af8ab33134e69ad19045e86c8a7297be19e3444aa06a0b773fa3bf2def1719aeaf5a1ffd7dfd6dcedded0ba4161fccfe8f41fd5039999b3d3727b6895b2f761e116b82528d2a731fd80ab969fec8fa5945d38dc72af8d9726a3bebf066205f1121a96595b1943e99e5945089594d7d2655f41054f895b4bc18404286c12a9d346cd87e4527225d320ed0af738ddb303d0afa0e583153026d2f1c8a500dffda57b80d818f5dfa584314b9e6147305deb817abde47c364d5c1eaad9b256912cb7190142001ee0a65944c0baeecda9eedf0800198578618325e0b489aa838584b489a79e468399385a72e17a33f5c05b98052655681802719732d6018c887f634970f0b7ccfeac955d280b9cc0be50a15757876768da2dfcc8b222ec4ab14c514845dd6c3ea7a33ba742ce0b00200c6ef60a857caec2b4a3a77829a3a02d98b443fb4ee0e58daa15401cd534970320f58462c19762c318eac66278f0e05818191fd133c8af2649ff9f9c7425a083d3a64b2975a51e374ea0dff60142990dbd6167cd775b6b2eba30f3fc59505a0ad8dd21c7cb3328432953840be31d7d69b082df08af55c38020bdddb1aa85b591ea2d2a281ecea2ef314b8903bb8c09aaa67937287f01bb70ae66cdc6388dd3aed2fc64ea2ce0344e5a7a165154a8e86b1bc9710c141ab3af535af66eabffd34d8ec72d9017e5def78af381054aa22d7287d933f37b279e2605f3ff92d645680cbb898a24df2e43354c6e85db268c30b7f891cfa052ae1016e7ceaf52bad394d23097f41a5c6e407497bf65f24e468f56ca6200c9f4a726476abf712fc59a5db3679498118dbbfb4668843c3a0acfbcbdf14271efcdccaac50581f909aae2dedee83ab5ef5a3b74acfde9532b8e06b3f29386f84a065ca43b8dbd0b8b4f1c474646f7ea6de9f9da2e087d6198adb373c264b76b7be4f71299a237a76bf1cc03421e4d88db3f29c055e9c2ff02b0fee998d4cceea9a531040f0e8d5de0b2c00530ad4e27a900ecf089613d51c6f3c9fcfd1408b331fe25c3eecfb28569e9b6b5004641954d2b9cd8fbd27a2d7972e9321ad12241361755c371742f2f125add9e2f195d82409c65883892b70048f73ba9ac8cb48195d61194b08c9d19eea0b7d53a8283cab32f45b49a1e957225848be5c0691c16007d11b8c48a0ec48bdabfb25302c4629179c9799ca75b8f89440b346dd543ebb136f360064b959e14d0781fd2e3c9195df3c727915b6ef13bfb2254c61b442b075b4892585081b56382aa230b03955e23182246f26507ec6283debaa45a5e04ee8b0bd7650e4860c3435a08b69b3d36dd5bf1af03a125c6bcd68cb0c1cddcfc87acea5fc2ee7c044dc501639e8104f6df6fdab51308a4aec429a6ff0b3c1b14fcebf7c621541433822d756809f489d60609dc54c3403859b9be9f4f20db54c89dd6fa22e35598bbf0dbca1907b3d1b799bb822c6ef88192529d39c08ff8ecad92d35fea0e6129dcc985973ba38633ee4016d4a40935c57a9b9ea0079391bdc37542d232755f4c646ee7ad58465e3849357749fc043a68191b566d20b487c893bb5440f0db42d953ba048de98f7b09c1638818c606e26502983897c8b51b0f9e88060a2df81539e85a5d2ce3c87834c831b7dd6e2c07bf78017a0a89d10bd8699c80f9f3379bd267d9eae5d3864a9573565ae07a1fd32cf50843c8ebf60ba5883e8a8d5db0734124e311032dbed4d25ed738ac52ec230b635a4e34ee1957d6570627e58487a84e99882c873ead558bf273146c7045c08a1ea5e719a769260603c7bd11a00bfc6413dd7eb5ba138d892cf9150f953c1c9d9f554287fb68b9c88ecc6d0f9ad3b4070f0fea14fd7f10ae270fbc37e473790ee226286bc70f44d08464eabdfce94952a833e7b8d055a5e73a74ce95d39bec96ac50f27393a404386fd5377fff9863b3678adf2009b90e578e5fa95c8770bf661e0cdc8d7e7a0528bb680ad7ab265c6432662ae368ced5360480a2de8c1ec673f80ef7ced0d3073a14caf1131bd706f4a46ddbd01efcc8e5e89c05b210ae06f04a6827539657405a5e8891c1dd92db555a9bb02b76dd97757519f6f8c0e2aca76136e613e59a2bc68579320064831e2e00621d11c0613a8bb9a95a9f8d2dab68650618662c14d62e19d3e0eefd3e74a95749526541d3c10f4fc7a4779790aa01038d7ffc148f3574132ae9b94d38ce2211a01490e9b285becbac912809e448a2991b2301913ed0913508e7ddfab7425df2a53adf7f62d9a3758874b1d7c5686d06267a8335663c69dd056043e66280285012157dc0b8433e235a818353e1b530cc60eff817aef448247220afe2170df23f306c1a91447db7d15925a15553a81baeba41b14e3e572587ad404a205c44871297ee45f49fb493ab3507c3cce9dc17fba70964bdd356f7b7f82a3b4b07b9d4ca94fc8e1db527cd3616e471777f6eec7b84d8c67075d59026d8f3b38ea1a7ac21caeaeff4402df288bf13bdfe25a5f0b7b5b87e55678a6fd2db257bc5fc22dd23a894f89fd4619fc095155f6337e484188a0a0c668cafa3d5127e74b926663648574c40226855f7db23a3a4a7b9c6f728cda00a1a0c6e8390daf72f3410f0da2177da0b11dcc69dc6ce3f61f42f639033454eb8894c86c1cebdd3843d6053138557a0c0c864ada2acbe61f0d62f6f794a0fe7bf9468cf14b83e437c3ef10740adf82c61d32c91b3f81442595e5d67195ff716e6cbfa3236ce809ae162e13dafea00183453a4038c5e70186351ac1822f74a83488db75ffb83bb0dbd37893a3f7ded2fd3a9f0c575c50dee3a40b4377f753920098687d5aa752aa7a0c44d0f867fa1d14e876533fc5d5c44a715a8fee2db948ed4831b7104f170fb77db11aa8caa4a1a37f2d2f6f4f1824c030a44da8b189d1b36ba9e5a4c31a79fbe9053fee8b0e70549f0e11bb27f2206e52c125da02a6155fa6ea222e39eb6275ea0866ac32e7b4d5437a4c5588e9536f89e7bc9d0d2ea04ea760c2d006aa8544b51f3333b24a218227e6f3156b47558933e2e21681784d514ebf41eb856fcbb5a6ea0d0ccc708d8889144a92432a50af01861884cc2e70f0816f44c544340af016bf8b905e41e954d1c52a2625f2363dbcb4edd842a66e967dab72ac168234f3eaca8861e7547a7fd71f61cfaa5726753e4b99f6ef0508b50011ca042300d59d63026616f296a0d132d09ee54564380626165031586cf59102da9e4479e4fc72c0a0e82dcbd40e11cda77c776ee19d8352285f3b186163994fd91a0c57e1c2d06a0c0ddb8a7b7a733c52b73c73ae4a26324007b0bf737ba0035c7a1fbe93848b0e41ebb4c5178c9fd0f1c42d9075d349df6a3b5818f0a042d6d572c80208e92b272c135a4d8858a9e6ba8024be1717f8143e91cef0bd634fa1674c63e4d73ed1c7dca9d19a2702876db300ef4dcc0829ab2235525aa94700dadecb8dbe1282ab972e15da8b1f3ba94211159142287c75442799f3a02060e1963186ec2d8b22606a9ec598fff8847dccbb43df7a569fef145f9c987dcf1a022b12a11f4e9d84afd517c655a25e32831415d46c6a21e24927c070e24b5a463546aaf21d01d32a4366d5266ba4f2ac3d8833dc5c80ed056a63eb14600bf1ad6c1729fc612967cf406f4c5e57b2ee467034ae8b9c7e0a0244af0d4a03800722c194097c9b631efdff5524d4aefc2ce576ec71c3dc8ccfe1dca6ba8fdacd58326cf8e896c0da214feb24e4059b905afa10a3e6e7b1fe130e004349e0196741b1fa6456af0ac84ca6be82fb41c3bbaf5a558f50d95ea0fccc58603e82cb3c5e25b5e5af05e43078bcb5df79030f8991c588b0fbed7100bf2530db582dc2a35630578bf5d232bb157dfb909bc51db818b518c5615a2712f7c7543c6677acd873db07ea14359d0909a19f277e919bfb20a25d147ed2c71c581a62ed2cabb123979e7d65f3e84fa6e99a42b583900d25d2cba9a14561719635fd738bc3fd5f8f9dbfaba643787b5273bec967760e978d7a604f50300652fc993c60027e9f7cb896afee33e1d8d77d53f1383d5f89fbddf62df1df52aa32d12090b6c30ca799536767d4e559b847ef1a4ee431b08392096cdc81a196f408c57d17531d30a9a8dc0464067aa63b969102b6db31441ab4dae8db458ecfcf0ec67c2db615efd2cc66adff75dcb1bdfb094844e83e42c4578dc5327a783557cd588fe63cb8b3ab42e0bcad8c8ca6fa95a48db8d0fa77547c15df921df78cd991d0600843be8793123c468e64ec515c5b0e07ca6aec74bf9f390207a6dc51e0f0b6f43dfab515741ab6fa526e01f5d4d82e5a7c77efe1da57e5f93c3b9635c7ce8344ea25101c5ce798f52c267ba96f6d03d07c7a36cf9e88fe92141eb8af3bd8500d2103943a0136dbeee2fd3de239e5cc56e23fdf731d84c5d87351db31c7aa37b908c7291796e20885d302771bcc8231f38bd5c57896246681b119b45795153f0138c6c16e784aa261b0d51dc8b7337c16bacd0220be85c45510f8960d927beef3c57ac9b6edb16e62c3a1d55b34f87b9fa61be916041893f1c8c384dd3286bfdec8b4d5eb3bdc78afea5f27be29e9fead1c4fa17d59f89f63f55b72562f07e2aa6b4568468a40bc91e4f8d3716c0fb62250c00c71a284b2d774b3e0e2e092498bbcfb60cdd90aae1e13c5a6d2a29f01ebf9e26a3a73290be2ac081803f98896f46e9b7ae87faaf9239caf8e6e5ecc787332977d8828c99560546f218380d2076a07981c9b4f8f1ca2653120c9e6d4945f04c44a454db2938608bdb16757b68535a01dd365de4f683a411619d886e3cdb39544aae5d7a3c9354144aefa72c3d84ecc2f0f090debc908be53319475a3322138892ba0cc05b608ede2f7584b1bc34a1825a3a60f53b79c1313cc1208d5fb3849566c6513a2b0b8afe2ab498c3b2472917e76095eb28fd43f3a7be49d8f9e96dd92518acf760d5121b3db11f99f9a04591b240a410c54b5e37164b3c5c1871cc497e45cc4e35ce4805b33c32a4b8c7f2fce9eb072b1e83d59292385f9ad98680634bb7b316901c42c0071d0c3af0a085daab0f4202b0ffcc5f7053c68a209585d6029c078a20f770f28bb5e32a44e1419e7a09d7b2f68c8afe0d9e34f7271a522a66a8c217114ad1787b5325cca0f3b433da85bbebe7c1dace28a0f753df84908ec4dbedb9a1038099fb315743d38d25ea42f6b871b091e7f3cfc7e4474fbb61d1c41da9ea06fcd79190c44d1bf8e1353737c8141b860602c88996edf16a2199c8fd057fb8f043f0cbc0a525703f4783b7a8abe8af1322e9fddb4c3a6f1a244216c110190014d924d65dfc356889e6897dc2da801113235b6f6ed5e4192edac541bf44d4feada99d212ce274c893e60d25a056377d1bdac92b5948ec34bf24464e4b72ba670b44c1c814df77aefaaa4fb230a13d25e5f9a9aa2b02620ca8c625e8278a1d9808d44cc84d42fab6ee052a0ac11542f798f01ae3d0b93d6bfae59ca1d61b07fa80dbec0b5f5c5540009da64b27b3f7971d570c01ecc0da067e0b17c242f7e5e9dd5cc0ccf8dc3c015c28e6a6d3b8521f2a03061386da9ed520075a7c1821d328d0232e78cb6958651d9fc0a4539ee94c449c5c3f41da5264a347ee7a83cf4e085b8faa2c59ed73933d5cf10660ad9fc62a664956cd01f39fe78652c9bfd378311ad8ab235f652e47ddb6d3327551970c71757225666bb1857b36ad35880b499bcc20093434b4403f505128915696687b895670da5bc247e8fae073a31a94b8ca1c3242f6ba5554269202c0f288dfcccbd53294cde66efa78d15fde3d6ba3ca0e0a3a970545bceb4b264eb57e2103cb989af5c2a96cc50725bfea2b35b00064ee874f2496230b2b23fe3e4a9f49a19035d88b4d514fd5b5de5bbfa7549ac59bf66b3aad071eb4acc0ee1c85bbbae4ca9cdcc25ba81671603edd33824f5aa4bc75432fe160145d6d9469d08833214c6fd2ceae943a4ae8a801463cd76d279b23783afa598f1a0b90366f0870584f66305a441eb740872c9ece726c1f4969dca79332e8039acdd3758307537094bd013e3fb3aaa39d53330c16b4ea61b82e92f4ba26449613e4b201b442216caf6e0b79ec5654c3ade69105934114ebb1873c5199389c8ae0e8a84e54f8acda718bbbd548a045b0ce388bc824de10cff145bcb87cab834a17eb0b3ed982808237eec1f184b17371d42afdb1fce0fb67b03d99638d5c32cd07a75b78da75d0f10a6ddb02ef9512587871d2e7bc18e0898fefa7cccdc6dc0d3aa1dbc63d0f4c83868529de58e3b377e7d2b47301e4fd9e488e550624617f160cf0747e4d73835adf38611b42de59f219424c8b2ba16b68a1f40a5ed49e1539c202374f8627a101429cf7e8718d480bb62a4696895fccf6ac542b1b28239fa1ab426e36a13e72c08ad0a5214586083ee3bb066677b6aa6431dc12b79c1d9ca85bf0ba56f12c2515dcdf068371b9b7c5a4be39f0ebc428c7f29531d5345aed73bad115b3fc455485eb7cfb968d42fceff957367767c6b6509e85f325b6e7344a10c200865d882d9a24e4b4b3c968e38eb30703c49dc3c4f2f44f9df9e09e68ea853ca751ed3e8e9dbd761d6dee46c6e48b0ebd6a39e77859f1d9e419fe46d30c2c1e94fe0828e1fb140d3ae158e31ac8959ca0154d040cb522bdad3de463a0c516426bc848e72c8c09f108c8a24143c7ca17032c98e5a7da66c21912bcf342c3db30c1545424d560c23e54fa9b5b594e0830cc4fea7e667862841be639f8b27930238aa65a604938e751be20ec46670ace82c61607bd2a688c3896882ac9bb5a8e92a1aba6404837973d7ffa2b86bc559a4dea01e7e7ee1586d31b140c94e09663f234086d4d79725750f15d3298f1ecf3bb0332639c6d121a3c5b41d611ac55eaf76c1b24f66ccbeb4d34c8aa88112b1edbdada55fe9ddf4d2cbe3af5d34b51536ce76bde23b69d5bb0f17adf7c63fbba2007236858052c210bc8c8815f37711c13da31a4fe6fccdd41d871510345e2f2b8513804567f4539f805d1d52aa10a6010ec558b262323107a638a6a97cacede0c35b11da9e300c96b4440f3683751763bb386b8478c7068ab44d62b4d1a5c0ef121a3bb3d08c26e90f56891f9ac9053ef11b93b5cdaea53f899477985e34b02a3886a18cf035621f7fa318659a8147f6ee0d9bf30689bbc19221257c62684c05b12515f30122668267a089d2c694e795c053fc2d6b4c1118ec02d4ad0eeb51f557b7bfc6135c59ba0d44a62e3194f3c1185e5c318e769a2b242bae1e25f51e2c782dbb1fa778943716a8d6fd47d07f12b19128c5ebdfbd95219e481bfa20e6222c2a133a13b9665a6eb79cedc7f91a051ff915809dfc58531f7ecfe16b2ce4faaf9f0d29c7fc5b56bc485052ced4990b080ea5867e083052cd3d034eb1dd00d658f1210409bc19b10b91a10d5b1e09c21f708aabe02728ef1eea7228c630a8849810932585441c9a16aaee125b8085d8d12554ef17118e1e67aebb02529e7612288912cbb1eee1094029aa8f8718146b47329a2685dac9350829324578aacd80424ef801204e3874a41d415e51ff2ac74097531dc9e2a79cb6c0baa46f6c2d7030b2f05a2533b2e808e1d6da631d865c59aeb3059f50dded6170562ffbc87baec343a13ef1bdbc4c5e54588d1eea03b6516df833a3cf785ee1910696cec06df8b993db6069bfdb7549b0b902c507a364e670161a4140d7ac96f9461ec99413604d69e24e830bf048eca1a74902d7c58546b78f754ccc7dc14831f370db06956d9898afd0f715a48dd504e7f9e7ed8d9c74cced1a7fff1680ba32ff5f46ffe70a5a26dc1c2160a2038368f72679d04ed88a140bdb4870b1a3d510d650fa720e4e4112ee96d9a5b7799df8f6f80abd7fc0fd45f6a83174fb97006fec93f15ca5b0ec82b2f64657115cc00ed9a8781eceb978202b8afd428ea3ae837888661a91905bc765265f5ee1c44d35c66c18ee618181cc6f3a650b9e50d65f064001df78f1264395380662b270f5d5549704c65a87aa74daf29d919ece02051c69777487458ce1f64c28e324c05f365953aa4df54d7b570a6125201f08aae607799cde0667d953271fa749ad34d0a68604bc6bd15d224c026bd6ebd1f345c4f0972b1d301854649de1b3a9d0478d4d3689832c84ea713c052651829e92c6e008fa1c4a21fcc044bd3ea497515868734f3bdb60b63409490eaba00eba53bc032d38e9f3a68128f727d9d307223c0b2af36336055b8c02c7f4772ca33833a8e212d05ef13a5a3ed53a701b518dcec9e72baf679185a67cba9eaa57e62f1b85d3e6d4fd90e91fdb6cb8b25e2a6ac1d6bcafe58257cbc5a98ed74fd8fb9b034a5b92b1b3de97068ac769f33f9cda6ca5e0beb8ebda29b726081219ed27518d5c7384100fea1bfee76c175c445fb21290df05b66cc69c39aec8147d4c6250f192fe6146bb759a3db4af388e25315d1a209d7bad9083a0b2e08a0c44e9417e54309909576530e59489eb714fdae608839808ecdd7ee53199c3f8dd0358cca80f2c41a7f0407f2999e4186e87cb14b378601bec914b6d7b05baba36d4fa5d3a72f9bdc0f419fa021e90943f949445c649969bdb8e8d2385490c91dc98c25960ec140f71a11160f3a12939446e8cd1acaca36e2735cf944645065763bc1097d1d5644c72ed2e21fda21f79c57ff5f70e4f3f49ca53b9f59a3ada9126a8fe3ad80a454036c57725ef677ad0c79755217ffee03a4f6589729f99ce0557067ce28a53e0b3e38b2002d442c1ab891d19015824c155abeca541bbedbc9781cd08727ecf3cbf544a68d34585674b9bdd1175cf2b54b9bce5b71c65c09d6243594e74e0c4d0efaa3580f03d1ff01071b36fb1b4e7f44914184fc0717c3e20781b7b75483ebcc0d224a4d30243fdcf47b5c9795d746240faf549ed600fa0b6efa077ea45bf416349df2a0ab623d3438c7f8c0f10b844ce1ccae32dc6dac70487964f58793698a7777f18b9a1c0ce44f4f6f5f137e46eaa506ba2772a3ba7d18af84cceb74f7c48cd6bc6d317974a98a6e2fcce1cc73352c9a7009cc5e7abae48f3be5314200331496c2e8f5b578a93c90975eb58c5729bbb7b8dea1eb88e91c9f6159f649ab4f2dd960bb2280bf2ee45572997b840b1e08d8f062f6ef72f31ff6c9cbb9a20f48f708288548452adee21c6510e8da431b193162cdca1fe51112b91aa9d4a8d581b666ef6599ed381ce517c7d721b828048809436fac5e77b06c8155a74faa3e88328969bee482582a4c2f91fce81e92566989bbdd891f0a412a383872a09e141b3bea71c3ae632f995087b11c920fba8b8be87291151ddb0ab19628f426a6b2b8dbb2a141510655383be8fb40e4b17f11a8d2996fc680d3e12e0550a5cd38b82c06f8f5e9875e56e644697410cabd526fd0caa18ce8a4a2bae281e2402c3981830c7ad4db6cd16827e62cc7257a09a55db20ed33f0b34c50a8fadc3f6b4f3549fa8e9fffad58dc7a6f7d3afb27c4d89d5b57ea46ad04accefcdc662520081eb6b4a32badc2bbaa692016eaae491f60dd4222c503e7e0ec848ed64b425f3658fe5e6a3355e8c173516b4048d033808bcd38eeeef6c8d3f2a7c784610a13999a2c5e8029dfb6ad34521e4a0ac6302cbc7d4fe16a969b837679693daf0c65948b0df06bec82410d4bcf5042c154b00591e3aadb8068b6a9a57580a6b15660de80dd2717ee23854e7623c622f4a47913b8f1973314ddc84e4b24df24ef2407b7a135a8f14931935c20b3351524e27ee2e3bad394e032b6c3d51c1d86ce493f8a28a381669b9517b01c4571354fb317fabdb07ce0dfbc37b84f36096bad0859a20e252c768df1be4b53955d0ee1089557d33cf5ed1a90295d3e84048dca29e79b07d068bce2111f627f5935341ae4f6df80a25b09aca0ea833760cda0d740f545670e050ab8b4a1b359a6fa482d29015d5866b03a5b099ea0305167ff428ca53b7a41bfc5a6edda907330fb609cc565aca985f6d786791c94dcbd2b589545c60d4428ed7675a03f9990323c3129476af0596f764b3aaf8246fe0ce28253f848dd64386fdbebcee04764496836610d67e857e7f71c4133282feb86ea395538b50e17a307cef7b9b645ff568a756befaebd539b60e8f722200b8af4565726130cd7ed757890b7de9a2945954206c9c6a66e1c9181bffab3b7a8bd238fbd13c53e16e011ef82e4b69b0b6f0e5973050e57024cc204640a517ee568ed70f4416793ad9254530f4cd93cf639474c989128061168170001ee93effd6fc27f8c080ce6449f8dc3e1fc517fbc804ab0c53de42a7f04a640760aaf5087b6d0589641ac444ec07ab2ca54e7dd7ef4717aa1467edb6237d629d53c8806873c250468480efd3f161eecfa0bbe1fe5943b12e2598838ba6b19c86bbd083b9199cfbb97008fd583f26f5f7fcb6944519d19a972eb8ad07e6394e5833ffb539ea55aa5cc244a07ffdfa1193d49941bd5d2c97d5d92aee69bf741567c8b1bf2c5eab2c76b521550303e006cfa0e1366a96c72f2c85a1e5c4bc702c02825594518590514e19eeb02745318b29f9fd7c13e8282a2feb4e2b531b9e8c7df7fcb51db225dad8eabac5fe315309cde0c2f244ab1db10ed4e52e6d3de6ead0ff1c1d512c6cb411f16b23c7ab87e8f9f24eb448babbd829403ad69a6ed3552b88cd38d9202f7b9ab25432fdc96a1d91bd97c75274f4986686ba2d5a90bc1d289bc8205759c92a093215b088f25485cb255b9e38ef9625851783a8db0aa649d4537a727eccae1e867a101d8dc969d7441db1e0b203859564851fb78afde2a49f93be9e1d8ac2af04c6181c3f142e533f7ab61cd20f3d8a887538136602a8adf11a39a03f9e71e61c9be2dd1d9154f72833e1da707f180dc89efcac9e1279a6bceb610941650605c3418dc017d02f6fda220dc926ef9d736b950359f53be99cbe448eeece809aff88ef868772604259404b2d44197b00bbb4f3e78d09925454237b98c49cf01e27e2151031a6dd39f6f24b7ac26cf22e782834228a48ac7d9fda15b4f9b781025903509d6c6f8402589162c0a90d1e9b6d3f501c2beb0199491c6780d6b7bcf12d1755c2d93785b2d785948193444fdcd327b8e721fe504ad412eb91119f795792ec994d2b11ae86335f6867697868fb353ad858070492dabb429de90ae12747f40927d514597c52beabbdde932f524ec858cc4effc5209dde3111d5694cabc279503562f744c440f5129efcff0fef43b3ae3e688e2a131a5eee30458384fa7f4ca70310a942072b814395b66d502a0115959f033c0ad5660134b246ddde59696471dad6341a8515fa27a47168484c355a9a7ae85429e7c9000f7e184119ce3ae48de2830259163c1f24a110df64c853e70fe5b14196e7c46ddc4ec6617aca0a2894b78ca8f3c20dd81d63d36f8c4bd62d263d17b078a392b03668098ec254b6f7cc5cad434ba1396d2c52baa49fbd737e9da03b14f91a42ed76d0821d2ca35415a8a2bf4fb9f8a5dd42e9522e3fdab8070556a3d193d5d0a777693171fdc320b11e01919e2e753f18ff92c9caac50e85cc402451fef3962be2b46de75886dea691eafb007dd277da62588895d6bc8b3d12d3f286db4e1da28f44e1ba83e21bcbc6b54fc7bed4017ab8e8ae9fda042c545fa2da5ea293a130f951882f474dcbc08e0b424af7fc68d9bb947ff5c3d14787b66e50f879c7c66aad42cb5b92e37fbf898b52264838fc6c77bd68e5ac5c2343940d00372770dbcc85461dd4809c204aad189e6df5d363cda3140dd465b7723e5688a2a36025e9b5d4f7cd018ed0736f64112d43eae15b037159e01316588281de01971ce9b60b204492083f08a4018986b344db18b35df19c8a3c022f73cae50c3ce6fc822676dc57048218e9a7fc00a6b2079b541c288534803c7e8d552222316c35a74619c5adcba6f0abb1022158027f31c878e0f69ed31bcab5aae8361df2d76aaf1ef0d8f9ca18a922d3da25e8e900098ad7848fd08063c2571fdb38300f82e3ab45666a002f64c5781401245ff78fca8baf8b98265f8e0114b9d93d007af8203f7d9d4e75dd4271a52e3b04601a7ffd03f00543dfcc501c3a9f702bf8591404f60bd605e87a2b8f21a8f7cffbc9a7e6f6986c9a7f5f639f1ca371238034449d894d2d629cdcc1f5a938506c1f766463cad83adbe8f209e109aa06c106bcafb1f6eb8190f6a6e85fb421be5273396b735e6520b7972845cf8188072c2b8241bc0752c0454447f44cdae32a2818f6f1a4a8cc5a6188763a031992229e379d2b25c1c8a97df713035504fc814548db43f566e3e5c6e8bfa38174e7e7c56c39be6529298fb26ea07523e3b1775423da0f385178d62afb25052ff2cda54d3ce0d22f664e8c0bc9772586262fc4f35ee52bd579331aeee629eac3e3c3ff562886bc264f499489c0b766e2170e275625684d9198a528d2e84d40d7d454507db55e05184bad2dc7373b1f167f79f10640628e6f0565c80c3c569e9d6c3ab6918a36c52fb55d1f7d8c083bdbaf119bc2a49c6e4a94aee978f2da2db9109e6c488f45d6297756e7a9d958ad41fd3bca7bc3b619d20acf06824f0f52982c9d7f6381eafcf0e61a0795b7a34331ebf234f4f432b7da384a2efa8c7ad95e8f632691cc0b068bf31d66a130258d5eef2b347726a8e8472124f3c97f110b7db6a23dcb92631c6c4d81bfa29fe87321504b554d27139181d2732871318ac47cff08bebf1b252645d6561530555f81f1566a0c2f413f51992fea9677f54c2ff11c8150f904959003196cd4a5d0ea4eef120907f50e522acf1d00bfcf683e76b300b7330857c0ccf786d31b802f300ff366531af5b1582266c7f91908f8dff1079a6d738381ee2783db18f55014b2f891046a13356a8e40707216cf9c95bd4689978ccdf400861c368aa37f6cdc63f10d525c6e6f21042061ba36f93ed47c4373afa21135f2bd82333db7857849544737143cd6061fb66b0fdc045893e8708bd529865031467e28bf0957f2336ed6a91309b5713c3725d92ea3ef0f6e4a76254f3d827d886bc30d248ff31fe27593a188866386ee2fc68f5accb27b3112cedbc3d6eeb02bfd27573f3f538c1955297aff7824b3db92ebe107779e7f2bc13d47e217849f22442349088eb19edcc1e46900773d22b96cda5cc3c45157d922b7c823f41a0b164d787ff20997e76086b70e197ebe17f7d765a1f1327b5726dbd1e9a22c689d5872990aba7289896d209881188a3edc376bc479489f266730575555c85ed9403756c4445572d7054e8a8192754f20eb34817427d140d1223975cb725d33ff71abea0c86d111af3e3a502b86db69d594f051734e6446ca0698b11d071b0ae46663be269c71557389a4a52ca68bd64a494dd6970027cda33bd6346a86ea91be0a07c853ab81ea343c866ae4db8af912d5aa27ca5ec8599932a4f5ae28c249d14e86d5f8b86ab32105598014f81f9b808c6623c43875ffd15f8ba6f10787de8d85967c86cf9d72882dd2ae98f6ff4ae7d59c7bced3156250120e249f32d24a1d3558e9e2f8bb737f0d5b3a1824a78a49c98cf809bd9199075a7efa73b1a9b80d95ffb1c71557e1a45873fee37b970605e321ae8e309a53b9bd32c862d37f5fce952e61135f90d960b962fbcb65c2aab5cda8a7a3bfe1853c29b94d65b4e1681051c52efaf18561317cb033818ee4f0aabe8ca0f809c764d0ecfb1bc042caf58bed68d47ac31a325eda8de8d05e4860bd747f933d2b88b6a070f0484e410f286f96fb35d2d4752b54c041a033b87b19c9c3c4e0ac3b78dcbb98a7b50ac3e0a2826cc910cb8e06b45048b8536aa6c037190e714b24d6027a024f24b29f15397635292fb92d20d701eadf366af60035335d38141382a466c594dd31116893b160b2f946811b1208e236d25ae4d7aed88ba70fb9862618a6274a40b96455ba2f7aa959b1869caada8eb66d6fc0a40f1d41680404b14de023d9db2f510b0dcd7c3b9166501d2d924a24a27a513568f0dbcf6940d04376ba3df69f21b2eb36c1f4826ab784f24dffdf0219963451a81430906612d4815db5b4aaa5deaca57f30baf779cd638b32a93e0b48b99cd4098967030439bbec2c8ca32dedea1bd572680fc133342fe434ba9e8afadda4382690957d7a313043810f616bbce099ccb5e33cec0d0ce02478103c1f056002fa36a391bc37ee90f8e4b4ce8cfa6c35231d3f5193f7894c7ec4f5b9cce5e395120bd5b9dba93dbebd6fe690378deca8d69e5aa59326f6644e160cba35ce3bd728c0166fe5a0286434b9afa561f6321521cb10c95b6a9c6edad9c580e10f1c98d31c9d11bf2ee2c6e02c55e58ed971598a17d2b066f57ae17fee2751bddb714e93c5e58b7bc50a85437c26e85959fa425558efa47f23c2190e118a469a710bc77b40bdded6e82085641630855687bf8cb0108786a57a1709a26f2e50ffc4cbdec048fa8826bee0557e750bae7cc73bb920e353b7947504002fb316a659e9b3116ce1f11d78bb4083806ec83d0b050be80c516f19695dec586853965dffeae0a2cd4920735a3a2382ecb16dc5b0bd33240d011a7c2e139f009bf4bed307c72034de0668ed1badf02d553d8f62f6550382983b6c317280d61c3a8eb0bd9e3e1c4d77c99d34520c814bf2938ca44fb20e2349db6f88ce43ac9bce7d04adb70a75e1995573878913869501a6199bd3fd0c6fe4a09e30bbc6c53c34946d8d99f86d73e24434997c0fdf5e809338244c87e3edd1f5a5902e31888a1f1f3573df29bcddebcd2695536b2f88adb6be18b4af9fb89be595748c9a84c284e0e1160f0902e9d8a4cc87c2a17914d3e6aa954faa0f96d44b151b2975dd3d0b93616399334fbe18904642f263babc3cbaef241e807bf2eeff775bb5460a3f10bd83bf6d982194a1b0473b963de6808ab2534f3ea98e11f3b7ddadaffaef2b1591a5fca077dd77829ed5af3d5be2d7ebbc5c02b51f7622f31844296dd6898528250df65343e8c00531e199b214a17fb6520617cb459fc8fef26c0c061e1cfb598f535fa61b5c5c25265d535f8c56acabe64f7afd437eea90e220cf88c0df1fea64e9ed07ba391b09ee29bb6093b2f217a2b7fee29bbc88717fee95ea7ff0b7cbe058d84989d7d33370b2809db18c8bec4212e0d95fb289d3afaa49cd17d6804c3f5072355559e96511e656123f2d9ea3950b3b91dd627d826bd0ab3cfffac94aa73f89b017f4a6a11fe39c9f4621a0c97a53218d9ddc581345771b71db0ff642d4378fc670274ddb1eb0d89d4f87c11db0fba03df62d6033af61de8c388c619cd7f48cf3bb82e64c624799138912e91ca5db59074ead5c90398ff0118535daf00b0878a5b01aa80b45642f2cab7925d42924229f3b166520beab7f91416c057ef0b6b5a85891c4a970c0fb693b7437701291aff95f7626ceae02121a3db90ae8b0ed8c02acae065abf4988359525b5a5e2c0623b9a549802accb8f8435f05686c0af8d36d327f26959d307db26f70aff5d1ad1afb46698a980983256c886ff773242b656a993dde1b5565be8ac46709091a3377c436d4fad40fd7ba8ff609820b83ab8d7ca1f464d210d895ccc59a4e4513412931ceefc3d0318d46801df2dccaa533df145a39f46f4ca32317843d239b2895e83690f5144d573233da9b1bcbd436fa009fdb24a33b5219cdcd9af33739d681ce42b761accd7cb3986f26c6fd4730f2d67ed5a4c04a4720078e2f2131e8435a92c79c86626d86dcb34a51e09ad66960b02c8d0e1faa92e64edf13c1e2af8dad34cc6b43190819a2f8f74a01830491b966899eb3dc37b498bb0ea12c09ce337306cc1e5a7b8ab9784178ce54a6836005d69c9e8960b78b01068d11c843d190a3e1d5a98b260474280925a181844e5f80dc308e399a27f9f9f18e7f1b67b2c2f3b72f580b8318c66f477a721fdc408505b8559893ce4d02a51c0688db161b2f45ecf745b7923721fab270fdf2a9c083f4d442046e2386bd6522c315e217513f62dc3f5d2b3400f0fb3f4409b672ffd9067faf8022aa3eec90f21b22784352b744f7efa9a4f635eb0316b224a1cf8aaa4a28ac7a0a83506ac9fe76462fbf59c697fba49ae9ef81452b835b50c42d12bca162ce59c51d2868104eaf27bdfec21f0c8962c50a2ee7f543857afffd41a194f7c02ac6e344976aac8b7141ca5bb447257bac64b0320cbb9697b0d3bf0e3636fcd855c248454dc1f09a705871b58ffe1b89db5873350d282617a860b6467a6657692a410ed25c55de3254d22256f63ec6a8fc9dcfcd00f17d82b9c60aed47e28b53a6df35d93b414ee08783f84ffc7acb66dae5b3672ec9041723851958f5ec6e8666b9ed1242db5ca461bffa69e5a985b506f8722640ca64a21b4d3fd7821a524904ac21b1e9c87ab7ee0ba85a678aa735535eb56f2c1d653e56a7446d1e95bf509e0f549929723ecc888faacf1f5fb671a312e01b27c7b128b1624e9257f1554ef9f1250f1597b9a3aab8dae0d26288062fadb29a7e354b73a4063bd574485499d157081af88b578b4be63ff4d741b26dba8243fd4aa315e18d692d29fb9c0a372563233f3f02c84336923e8fcea2cafcbc3c3d7ee47428900a89e7e1110159ae67a2a55678610362a356409d484e9d7d5b844cb35164bf047e764998e3a0699b158769c3a776b4db3326507548699b277abfae55d0174de62c88b126ecc531dfbe998c146541f0b2501f9025e24f6c0f76fc30acb94027bab04eae641c91cb0c8d2a1b1597a56a268b98435d9723f03b94d912a8b61bca2f010a5f4df70d348803fb1644300a4a819874760c46f3010bec06420e5b3c1b142be370172551116015a47213c1c7d27ac4623d77ba28cac9920df62d7349b23eb8ff7d58ecd59db141481fecb02af4e600e9a2d7b4cc26c822c48628ab90f5ba1b4d304ea104ac47e74972243c4f2fc096262c27a5ab8c25cb031cb233be1addb24f253c112cc6722e0dfd0510fd426d8624e0c10bd6b244130e94fd3d768ede0652b9bfd5816c0a8183b4fca034fc097b640f36712f381306e2f2b8beb0e36ff052b5eeea673906e8f13a194b907317cbaf9ef1de98e53c578c4975e520149659bceaee4d36ea8c7ba6badcc4863501c734484e1958577922c9e5001c4fa97be1f4adfadccbd78f2649fec8671be52b4be38a31d822a591ae57ba952d786ac6c69fc76ff909ae5f53c7940adee945a453a4ab7d5ea8e708cec1378b74d82783409105254ca02162961afebfb960c0ad1e71c5815286ebc442737435bfda20c8cf3544691b81cc8b0074864446eae9810320437d33cd51ba896c53d14c4b8126603966fcb08346158562ee1b06888847362cd084168f88bb3483522aa88ec1c8dd41009b8bdaf1937c1a83c0e8bbf104b2008ea97ea00d9d7b0a276d953e1b4f0176e0d96725a1aee8ac172037580ee5b0461fc8acd058c40d7e8d27295386ee1c6087ca8aecd467602ba0fc63893cfab76350c1a3390f097f200aecc516aa67b00530e19b5478c759fab78dc2a197492dc7ac18e2ee348d287113ee76ec4dd09de7a697f9cc72e8ac06289e6599faca65949874e5b4c24132477784b57f437818dfb48b065cdf814d38504e2eea30c70da9514fd1af59163664fe150a4ceb3c4d7fb61dba31e737bd231d9ffe6a8951c2e3fdf758a0e1eec12397690e7f727efd2a9b64a48e320dd56d663e5748e756c8fb0133cb89f2efb719b3fb8ae0cb8e346e3ed1ebb391a651613ba8de72f0e5cb822d9a3d099b54b6a2e4894df1d74696916af035a735c0f04af58fc0e024a54052bc7e2819c8cf7a23b68475e0de0871489a117932bd9b93938fda00ffb82480dc818cfccdcf1a4a83fbdf854050060ef3373f6b280dee7f1702411938ccdffcaca134b8ff5d080465e04c961c544218394af722c0f312b9494360ab98a9c184192a25b8d7c7cdf24ec6096c4b2c6924ec8977c7b554830cba72bceeb79f4aa3c5945b1379278461a931ed8d8abdfd837de3f6d4ad65856a6afba7e681f2ac99982f910d570730a12fc054bd22d461c538dee846de471620caffc42caad8d17a7383d017a7c030c6ad68dc7654472704bde8cd7ce0364cfe371ee5bcc9fb5db9775ce7938425da0cf0fc79268b3d4010cda2276d3de84a1b51c789f4478d4abe3e5c12c79b0fd5ed77fc2e4ab6804a643e1a9fffe39dd19e1dddc38d2081b1cd8db163c419247453aef7047d0d31e2a90911fe76039f0ea31df13b7b33af90da5211a805f97cb4eaffabf9833c4b73acac76ac6959ec545f8620c4973f6a0a216543badecd04db8869228d0112bc7d591c13d21667f917425618d1dbd62ecbf7232571ff177ef061da07a427c1f4ca80ba11d8ef78b802b32b02745499738d46434675e895aeeb0ab02d600f26d825a81e6fcf06ceec80332ac192c402d3608e78e9bfd991e313f5070e3c839f2afefa54824ac81cbf15a01f7d7e1a7885cd03b28b86fdd8ae138c2d8ebee0f127c01b6a0eb6eaa638e8d0cf1a6cae7aa2b1080541108e3c66ac76e295a13a4f1cccef609ff2ef58c2071f10193b1fbbe5f7b17bc70bb1b9050f35612f24f3f00329de2e038139d76bf04a638391be3af4b2f1121bf601c7f7994595ef68d5cf2655fd8502ec282175dccf50ed81d32d10dfe703f284edad0d39b823bed4d8c0f1741d2c5c2894ac0c97c2456917d96d3be1d1e6cb491cefb5216946951a197e6125a9e8068f0323c11dd5808502edd6568fa1b038eff4db40b75ded1c504ecf355f2cc86f30a9dbae17ceb82d6e024945985c5e2c545884db9e2d699dbb8d45f4a6087e845b84fdcc3be3cb0045452231f4c8fe1eef854aabe5cd794725fc88eee0e03de83b39a733da9a0ca8d236f386274bb114f5bb2fe76438218acd41a4e6951208e315ffa0c92ddee1202ea5702cdd6985e65867f65eec19ac776d9c22948bd8a46b80068a2c18083facaa691aff9c39e735d42cee3e700d8fabb8649c02368bd098b3d0503a6e42b661ba5d6236e3b27a7b1455172a12234581e4399e3097992f27ecd170a893c4edd687deb039a60ab35dc9fdc445a4f1179637feadca27ae00a2e2221606c0f60db08a0616b3e59603b5831f41d1168da2563cdddc01e36b36a2bdd4c9bca880c30afd51b2b65090ef69b97210d35fd8085cf034f365f26788d098f63e472f8c0641b966f9dca12639834ea387b051cbdc7740c6c32aa89278855824d4169b3637a3b7384286e964efe327362d8c766074cf6b795daf084c75c70fa2fa5a696176ccb692fd7bf1c9ae2413eeaf631bdde5c0e116bb83638e96032af5e49a7320ced2754324caee345c7b7e58efa07a0b6172436ba1e012b3d47d28408c4954bb3285a45b4751a21c6cc175b63d45945d726d40a25a594bee41fb6139ca182185669ef7452a7c0fc6de669caa635c6e723eaf674c6e764ef1810d89a4e9c60f1ff851cddacfbf1f1f04a62d1f4e71d8325eb73fdaab9cb9bf7aa5e3f7b359c3d6ae561b5d29ab90aaf649c4d1bc6849a90d974bb5c87146189ece532f0b7b6913f69cec80032a49d7ab5620d851710e7d935237a70e0ef3939311a6337364364249655bc43af0a0fa549ea324a1267918bf84fdc35f3c1879d7ffffef9b07f54abb6e52ca551e7770103004fda46a4d9243bffd6f3f3bcfb624b4b464e59652ca9b0a4b0a7a0a0fe61e30b0a1a175e637c9ffcaefda234ae76fa9fe8700634ae7678d2a9d43536db5579f5fb54796ce9fca8f4abbfce61e5f9a87b74a780e6f5fe0e369930f5e94871c78c841c78e9a1701e2589e8cc30d2f5082e77714e1383b8a28716aa591662ed448b31666487318dbf34aeee0e1d4ce5a69d4de26e1a49f39eb6bf8ea673c7fc956fd8f45c251358b849335255c1954bee9a4711adf3a67f0da5b179470b9273331ced448a2e63da799cd9099c83da1c9bae02d12333564bcf534c6176fa21050876cc423687bfeb2803d02687b5ed26228071e70b8e144e737c184392b16116f81d3b6c067fceb8c71ab82cfe1b42c703bc4df70da1d6e6d8fc36957e0423c0fa72dc283781d4ebbe33a6f8d8089b12d8001c31a61772c0b6c117605768725c25f3fc37378ab02bfe1ed108ec35b9bf3f042b80e1f044ce72fb78b8fe02d70a6c05bfe75beb8083e87f3041e82bfe1248183e071384be03f3c0fa709dc87d7e14481eb3c102f29700102052730410948f0920217205070021394800423f0d7b7780e2f02bfe143e0383c089c87ffc175781f5cd7fe03aee33de0a4479df529be7a15cf5fdae4ffe8d0a1fa1fb2870064018242bce988bde99439cab7ce15af7d074ab8128a3a2b2d01f5010fb098b6e73274a5b484122e34754025c5f4316f3d8ae7ef36aa96cf323f497f0977d15bf2e2caeee8a1ebf81d3abe0c0282a23454d2c2e46909570695509440663986ab0bbc054e0eb8ffeb3cbd029fc3993a05fe8613033e81c7e1cc804be0793835e011781dce0db8cef7e0a5a192163a1e6f20d5400630a0c3888eb7382707469fedf983d1c306520d640003a10e0bfc0572f80af80d4f01c7e127e03cbc045c878f80ebd03952149e99c8f4e3a975fe019e9f44e9b8a9e3a91d3529b21701e29cb829749383e3173b84a69cd2e45f27cc13f0399c0d7004fc0da702fc008fc3b90037c0f37032c00bf03a9c0e701d0f81f254d12bde1e5b5dfb8b93bff61607f63ddbf393ef627b7e1a7f8c3ef2ce4e3d1e083cc0015fb1ac019e33e077b6e70bc86dcf1570b43d1f3b92c96b5f714c3c874f80dff008701cfe00cec31bc075f80278ed3b9cfca68ef7dc74665c7e0d6299ea7f763853ff93737e11d3f9c74dfe0f014c02b8ea67072e32011edc21a71c5374fe5045e707b7fe6e45e7ffb6fe8e7cf035aa579f7296b7c9ffd9c155ff93e3232a27e5d94d1f5f489a79da32e5302933e5ae1d3ee74799ce9f53bfbae875d40e678965b7e3a18368afde2f9abfdbaaffd9c16ba81ddc4cfd4fcd4db9a795bd9077a8ad58395ffb01b8e94fdefa12677dc9575f7a7ebcc9ffa9b9ea7f6cf0d4ff08c0c79aa36c7053007eebd965d045bd5067e50f2a7acda37d75c801871b1eb73d3f7d1ec3f3f2073549197467626c6f68a7a80da695edc1a429db73017cc5b2f24bb1ed91ce231d9f89b0cc739d2fda9e773e3caf3de8a2f3dffc7606f93f39aedf3cca394d32aeec7ad753a6e6d1cb0c93970b2626771e7a3ce3ad82b18221dd78db9d77a40d158c150cb51c204400ae0582a452b1544e39e9b62fea4c85d8a86b1d1f619a17b7ded930cd0cb76056f90e2962286edd561b94e5d6579886c55b292a6edde5ce56dc9e36fd82b6e7e6a7f65d7bb43af5ad0d6299576259ea593bff8f0c5c99cab2d3a957ed31ebd4a7528fda1977d1ebc595ddd49b7b0475ea4f432f8f8fb0ccf3191e98fa927befc5893af5a64d94ffa7c563ff2373d68bb78b66578942ae2c03e59cf30e0fd351aea4a4a4a42b7726d2a51d2bbda3cff6edf876ee8ac5ea66907a923874d17c8a372ccb252fe71d7964d8768862ce08cbeee974f2ee88db5e1115a59e6cf1d93a7bcb7b4758965df65e0ecbb2b3fcd7fa6fe7a2d953fee371d1ec2afff15c34fbca7f3d2e9a4fd2afcff8d1f6f2e25190fb6ab549228e24e24838d0cb0d6dcfbb199429c6a55eab64417b3c526484a8e54b2cf3f22a136dcf4b9dfa71c7fea7a5a5678b2d2f12615911961921c925b9a8884b7d58a2530f8e279dfa6fb3be53bdbea8e7a3a95d9ee5dc2145cc898880cdc553efedfc3f2c31cf8ee2238ca4a19cb68cf993031062c77cb41ae5edae64ecf4d0b7f5c5739611954f8fe57778477786eb447c80456887382f882e6ae488322db7e745db73562cc63acf54b76332a00dbaecc59517915cf4baca8b4617bd9ef2e2918b5e6fbd5874d1eb2c2f12f1549b54ea71db73562cc6424151e9953771957f79cabb3cf578c7fea7c5f3ffc81ca5e52cb1cc7395cc597e871427a78f260ff3d7bbbbfebdf5d94ffe87c5cfffd9711c161f597e85659effd78b3aec5bad3fd92763255329cff995ddf454c499bc4b957a97ea9fa4bd7c7cbd2df3cbe595cca64a76b98acb47ac4dbe6ed7d7fd7a7057d2e5d2fad71e3b92cb86960576eb5d5bf6e0eaa6a4b0ac8a4a4bb3c6b192e6990ab14d4f7d8a733b95db69cab3773228d394af3c1571392967790e6cbeca535f37eb61242d97a97c779a58416af5f5a22ba44edda9b3079cdb2a5f216db83b4decd82aaf244d757ae01eab2b045fa45a5f3c4fbdb82d99f3a6e7c0a8efdcfcba4f9f7a44fb7ac9a79ee9d3d1b6af975e2e5d913ef586d271675fd75e2e5d899fa23b1571a95894fa4e45dcf67208f0d6615b80a408592475eacea748da605b80a48add819be409b172635ef0bc28e6a2370cc3eff3be3ce28fa9b9d87579677a06808a5eb77596039f690f66cd4c17a577673a170075664345af5f1c73c7dd6bb5eaaef85ae7ceb08f6659518c491ddd061d6f1bea4c878bde0478244d3c790089507edff7d59054eb0bf66e5790f6ed98999aba47ec7947ead4ed9d3d9836d4f041c40a1b67ecd20113458b3e22f54dab529fcae8c6f031b2a903bb12d4cbf80482dfe8e9f77ddf08bebc5bd38d515af784743675771a842e4389e95442d23c324a4c3b8653363b144e5d7b7473e7ed7c8ac1b454ececb627b5b69d9d869dddaec2505acfe7a8b2f5da1c4a4ca942d5aa04575f17bc962bbbc070ab2ff9ec5e5fd0d8e424c9aa0bb6f34269bd0b62385221a552e995c76a752efc2a6f2746693dd7fa92cf34ac38dbe5c29a19583844a557bafbc25a295a43abcbb2add257d6756dc559b05a5abbb4974f34be1e536363fa04bf1009d8f370002e9a7db43a1d174a7be2a835bcb489d65e86758e1fd4f7033b1b26ba630248433af8d59b6ee679ae345c23181db9feb97b26afc1ec752831b3bc292addcae7e52ee79a9c5d6befb6505af7f12ba903dcd9c7d1c3d1c7b106d9d969f0687832ef3d9629045db5be64b7fbee20dbf33c8ede69a143326a0fffaba989894151f7d5aa04f399e69c73f7853e7a9ee735c7456df876f6daa5a0e7813f02fc830fdff6ce7474d07d28c1de4016ca1fc6d387ef73ef0c01dee0e9d2016ecfc1ed9d23c03bfbd5e008f0ce61f6908c5debacc3c28cf305c525d692c2a2225b41d115990a4b4a4bcc05e5e59cf1301e03a371226352e335e362426bc6a259d5a86848d9a06e4c1ba71b2535947090726c72671c8d3302400c40480373be9aa793757402c036dc01dc80c34b8d13252596a2b282ca585a5e50b495c2cb299d0ab8baa8957d51b2a8c462392525ec3c77bc72c3b72c5e2c452577e86531ed17fea12ae0cae7e5ae05bbe86b677c01037e5e0e515656308a5e992cc32c4bd9d239aac370a999b18165319e8dcb042680dd15d0995dfdda28b8e06b713e61ad181db2802ddf4bee708cbe28babe515923043f4f3c71e517884f5ef7bb2b64cfa4a573b939a35dbd08bf5c6d63f2cbe59be1e5985e038d78e4197d3c3c247706f3eb5eeece58fcba97e4ce50fcba777467a75ff7c8b8b314bffed9eeccc4af7f3bee6cc5af7f3b7786fa752f0b5e18f526df3ca36a43aae14cbf1f3467faf5b042384e5e5a396e5a6a1c3932d2088543281b37522c998f1121b269722aa51a9812b03c0101a2c19e9c8bb2cfc421a993fb6e336654afd5cc65d240994803692012ba629272a2b0c070f986c3d568b969bd9ce0101212dab19761a56ed84011d1a7122c81a929a9e89021363f99e8b95ceea84641f4b141088790c8dd23600f26c2777bc1be9e5117064da5edd7bdd22d5ddfee97a655134db33bdb3dda5d1337c6d9b851038e1c1b0700478e7446f6f588bcb09e8e06d2442e8d27a4a3b8b31a7e5d07ddd98c5fd740ee6c06bfae85ee6ce6d775157746e3d7f5edce6afcba16726734f8753d7467367e5d434144eba0de78443450b5b911d240421ac853d1675fcf351f961697971930313480009199d9a97894baec543cd20987f6cdf176fe4489a5a8aca03fbc1f329d9aa7606e5fc7b4dc8ad572bd4c4e60de0ed7a9e5803d9f47542a4d2527139542a2aae578fae5f1c7a5c9372c23e3ce3ebf3edaee0cf4ebe38e3b0bfdfab833f2e0e971673d7746f2ebe218aacd75718c7a93bdb030d7af8b47d506fbad9de918c5be39673a3ab12fedfcc1ee74c419ed1b8073c4d597eb642853f1e8c85af1c88a47563cb2e291158fac780480af17c579eb3bc75bc7f1d66b78eb37deba8dc7e1288e6023aac06120387cc4918bab2fd66d9e06eb356f9de6adcfaccff0d6676a78219484481778871019424b20b2afcbfceda92fd6697cbd68cc5b87f97ad1196ffde5eb455dde7acbd78bb2bc4f1540ae0f223e427c2e1340f675d9dba2fa621dfd7ad195b7aef2d653de7aecada3bcf5f3eb45ffef8e1f52f0762e0f6f870a3ff6757f0b545facc386b6f593b76ef2d65fb60aebadb7cefa7ad1d5e788783bac0e8ce4bcc85928bc1dfbbaea3f80fad3454beba52444b607922a8675625b27b23f88aa17b6752435f5c53af9d6757deba21572cb3723d90b7b532b4c4ac3b67e9194b77d73779abd40759db875cdda22b63076b832c53b3b250e57ba3da4a222d2026d9dd6dc28eeea1daeb4be536dc27bad77a8a27d7d1cdd3eb82d490beb6ddbd2ba47d246af24ad545fbebc68877d754b48275226852427894e4a4b1fcb378728bfda387ac9f346174b648ee8a0dbef00ceed0d880efa287e8a7397ccf9bcbc683e79490d740b9acef0cc27e914455297f0902ab3ee89271eaa2fd6bf14b64acbed9d298a8a14e7522078760f38578e76e72195c6b1ec7aeec2d30cc61eb31446cf43d5a6e4e3599eb654dd768eeb98c603c93305f5299e296ca7ee91357097dce3191d04cb12af56b03d7a0abbde4ab54d282c954ed35012cad494b3edeb28a16a53f24b22c1d8d67517db8ab91c7097489fc2b6e8e4a7abb4dce299e2213b35e552d3907dbbf43b7bc0b952b5c9a8124b72a1d4f6cb3dd60e822e8a99481eb2dd655ff654e1ca3cb4412fdd26e0a2970115359d29b8536b8730a0ce6ab56ee4daa4330fd517307d4be6885ee2620fd9b33c7842899c336983e5c1133cd68ea38b62cb536c74f214df4c4f3115299e22e529d681ca53dcc4ca53ec635b96a75889bd32625b3795ee2926aa61c80d1b3b31382f4f3117646892a7ddf6ae07cb304d0b0459670a96ab332d57aa335d79ea4c1d459d29bad39579a6313b5dedd399d2ec74955aa0ffc1075bc63eb9c9bb1e4cd3f5bcb75f5fc40a478a52b54559bac94f3e8624ed74dab274b13c9567c6b20ee81a6ddb01957c576960bc4f5febcb0b73b12dde625b377ddd257ff7eb6b9d21c5434adeeef2bdd8d65da6f72108db3e9d63c97fbb7cb9e97f5ea76b9b5e7be94dbba5daa2d45e3ac9c78fa4914e3b0021b6d665e9bf04601a9a98181475af4415ac44e0be647441178da203bae8f5cfa8da68ebfab645cfa27f9e03d7b403c246ecb403c224cd96b6b316bbe7fd831bff9763ddf28a4e89ae06e5f592c7dd596d2e304dce2e3ee8e17fa17f2710da43d1c11388d1c5cff5094467b3e17c0b007d3c8100fffb1596611f3b1d72dc8ea7fcaeb5d58413f6308215c7fb8a53ef6c03d93bc7a9640ef90ce21302dfbb8532ec409c13b7b0dad46a53a4083ca85a186b2cd5b7dd39e8b854f29c1d6b5166cf814ba55cfa0e8cb7bd81ecdf0e8ef7793a9ee978dba367af58688341a0a7a3cf0653e7293d5b500ecacd78eaedd4f034e368789a89643ccd452d609a877a623cbd3b2f4f2fcf89a7b7c706d3d0067a2d919e821b747b03f3f49a3ced66785a6e174f7d830efa7835d633bcfb68b51e7d0435486a936fc19ee52fbf8388206c382f4e842d032714472d7ae8205896e248d23366c87c5c69747cf9151f439bcb41b02c572b57e8f214dd696873791ab3d3d066fad247973e317d1e2259ce4cc40565ea43a497dce4252ff9ccbfd7f8143f7995bf7ee531afe2a62f651ea5e54f1fc1d3093c81997ccb697ccc5d1ef5f778b6e9a99f0805959ee4e46b1f5b74cca36ef22d377de92e0f731211840d07c667bccc5fffb3e2638a9ef1327ff91577f91d447c00f5963f539ee6a17d3d0d83507e519e821b15649e2dd64a853ac1c09ca912d35996ce13a683c1d75618189818528993a5ff6129daae334577c959be6259eb4bcefa6a61d2bb4b6e7ad9572c434bbef22557d9d9255ff1ec92abbec72e794ac963254729f959f22fb9973cf5e9edd925477d9a73bbe466c94f9f8e40bbe495cc89d92567ad2f251fbd1b6fbb74a6a367771259b72816ad761adaf6f5cebfcf3a25c4c975118d3596d208da37c45a94dee7f63dc71dc30e97763f4adbc317b4adf5cfc7fcd5de93db389ee0773428ed06fd7e7e6df66c58d3b1c8be6e1f7cbb73f859177ddf3aa6a77dc31283e01e71db7af7a3f4fc73fb1df882f6063ef7ce8eacd1d876b462879e9e86c0db9e273726caf4e4b6efd7839d5a165bb5b1fedaf63cb9fd6077ca62db75775f69047d2e30c7960d8f3fb6f5d1479d81170dc23496875b1f85308ded71eb634fb579b9f5d107d358c08ff07404da36f578b6f58cc33435b79e89308d0e4ca3e3d6b311a6d1c1ad7b364c9383f3806970b8c1e69e3166d90b49b6f54e8c3acbb9eea8da90dcb6dc82e4e8d64b15caadaf52e608ca6df2746567975bbff6e6865eb9f558b561b9f5947a631a6f9e87a8a7b9e9719cf500f0d507c0f3c36e70031f739e666ff00100004e4a8541b72a879b7e3beb6bf0d5e3f0fc304df8d8a0091f1bec1c4df8d800470df9677c51beb81080fc1f029c5ead37eef65cff0fb5bef810846daf7ccc3a7fcb1e3d1ad4c0f3b3e41ad0e063e287e7976d53fec104e8638947f7123e6ccf5b19b8e5f176064efe4f0e8f1e1e3d39e7c17065f794e69139868ade8cc332cf75e8e890030f339081d0f6dc3c32c7e0edd7995fa50c02726517b58379948f304d0996bb23b582765a6fa50995b2f311510c0e1df27a5bd5c46ccf3fb64752e74759b1485a657afe739b7e04e0364dcfbef23145d256a72d4dd38c65948f2792864291031062a7506ff7ea6d2e69fda3e7ffadfa9f9c1cd6cf0e8a73fee47876d2471449234f5b8e9e1ac951e777d5a3762c41fa1b37bd0d673d0dbe7a1bcf7fb2c9ffb13170d5ffd81e30f031068eea0183938d9bf25493c4201efe0fd64300eed24fbe08c7712c8641cca53431a8af7c4aa821d40d25a4d5da81e1b08cc8907ac48e16fb3ab6e5c43088b990857a692abf6ff15cb4c79da1b46d19bb81b15ba95442a1502dcfe4e5f296e799bc5c2d6f9b4ca6b2e42992567a8aac75db44b1fe07d34300ee9f3f4f3d27264e3ea72b9c8a4e494e61f0f0c7b2a8171916c6c50549c8066e9135d87367a6eda24cd499494445af5fa1d2985cd4224c630e6159923b338d5cf414863a33a3d072ef4c69f099c6a0ac3375d60af53a4f3ea8db890c7b631e21c2b672d77922c3dc31b93087a260a465ee78e60e36773e738765ee588c5af160997964651e29ff676785f3e7e9ef271ebb893952507db9f64c6146c076ea4b2b894ae3fa7f0b895ae3fac9b78ca833944e3d3e271ba6693901645f3fd9a2d8f764cbc9dbd41d91322509954e259bf53fefdfff9c5e82ff0358ba3e4d232f7043f5e59e7c605d5418d8908a5a20a025ec0bdb39cad5179811d5b64fc6a8b224fb448c8adecaa0e268c853cfa7d5d33aa2be5cd7df32a2c25ccfdfe271519e1e17f571a295839f7d3778b676ea8b16650a3b2209c56e46271f4c63ee60b03c89ddc833f5964f6be7a298a6c5e3ca5ae64eab87b95322e6c45cad2f8fdb29490854a14e9bf53f295efa1f1507ffe7f4f07fdecb143fa9bcc37e07cc8b0071628ee22b9e817215f6e66463018d9e814caf6293844eb9a4d4251096c33258177586eb2a0f1b4a79d80d4604ab0226545f62b02ff67594afb5460a63c236724f367b03a3a202990286645f67c18ea4208c0827db49ee4f8a88484298e6440c23291801038824944942252421929026090db1af9748422763eceb204908dce1515fae2391447dd9e1c3819d305ca581ba81a7f55fa9347e144bd76a13833fb59168f1b8339eebad1e7766cfeb644be32dca5a82ee2269da6bb589f9fe07e6f97667e6cec5a2cecc232a9a87308d98c349549a58163576c3b29e3b338d2eea3151676616509ed2c4a0259efa2a0fc18e7c603724f6e6e463618e8009d93b77060b52511109ccf627620ed3c086a8b22ceac951ec86694ec4a8b22cd41324fbfa75d3e8ce4ec2a8e875219a29748036b1af979ca9fbd857897dbd3c733023f6f59298dbab0dfb164f6ba7c5a3d573d1ebe2b77eacf6c9c7deb4685061aeb76cb0afdb93cfbe273914498865ab2fd7f3bb0d7674d17bc2c8b8280ccab4b5b3afa7b0a37dbdb58369ba16cfbeb7711cf1bbf688f5d7dae1ffc09cb5f1abdedce36bfce1a9f183238ac6a0be6867b36dfcde06ffc7fdfb1f987bd94f10cb56447c00369a809fa73349ea4aa5a9e464a2522a157c6d5db15aae97c98b74226ed4f6ba209062ec3068ad63b7dbe27b7211ea6e55cb92be320cded98c5dbd5ba24c75d909b1c1142d79da6d9c9a1baf520f4fd2ebefaeccfaf8d8471f4192367ea7878ef157499a5ed50eb3885801c8ee32ba3bcfa40d2c2256f8c1ee3ab3de99be3420cbaedef58015e313246f06033b187e5f5771575e14776347eac84ec4328cfaa9ce5a2a8af5e92bb4a53322754e7667fab91d3fcf1e7e2ac40eaffbedf2d5a9bb3b7bb8e2c5488682a0be2a41ac044fb5f9fc66a32ba6e982b0ec82e5cad1988e66df2ec91ebd8fa475b92b3f8d87eacbf52e08d3e021dd15c6281283280c9c1486c0b805eddb25d1f900e4f8ceb4b36dcc636dbd7967ddd69db17bb9abdd4f88e3cf070f551cb71a2a62a64075e04df8a88e8da8a1a77808ef549bcfeb5875d555d74a048b0e3a1ec234980813e1a1eebdad43073b177dcca1e3500cbb1d8ea0a831112eeabedbe1088a788b1abc5b872328823e5a1d6ab7ffa347f0db637eecdf9bb6e723f670e715d5972b851487123546c47c43a063b8185e18fbe223448ab0114c74d1ebdd997e3d1bfb84375ca2685ffdb97e9074fd243d8aa0eb0fbf51b466c9cd2f516e7eca3c95946ebea9742a515ddaca4d9e65f23093978be526df5abd5c4e537957f953e5519594d8e92a8ff22931190c8bc37c4b8cc33c0d98192f2d0ef32e2c335e646a6a78cdcfd0e0356f5343339bf19a9fa106cdec66dbf0fd37707c3f00760e1c377c7f0d3672e0a07dc5bae21a854e895dbde3a9363a3608988a5d1d0b559b1a1252d8d56f51b5c9f17a8f18b1abdf9d6a43c344986257b741dd0bc0d8d513506db2d7d406c04bec632669eef8451f3dfca47b9fbea4e91f59b31b93a2e3973948d24c0f7532a8e2e0974a07ff0496c0941cfc1a951218ed79322897791bef321f9361a56cb8ccdf40b152dbbbc1e1377fd2e2375fe32647ebc46ffe05478ed66802739367597193474d524e1637791458ca4952995cf5ae1957fd0cd56be572d5cf4caf55d5d9aef39fcc753e7410f4f0739d1f5d246b766f1f3b3d9234d0c7da27e3e29b945cfc12951b13171f4646e50683993c39f9291c4efe8b5c99524e3eebb432a932c9e5a4ffd349cf428add78277d0e57ec86a9f5a34e5c3f4cdb2851aebf5563a3acba9635edb57712f4da9b2e8efa929f8f64cd6e4cbad77e744dd63a4d92b44f95e3a1283ee9c6c537116548928baf12ca90a28fb594d5b8ec4f2997fd4a862a4f2e7b1b35a872570ce3f84b5c8e9f854da512c78f03c654aa6ff7288e244df49c075d93fa92db4952e539ff9548daf612cddd747f9989fbab3839cadcffc624471d5bf3b1f632255efb9a1a0c49c66b5f0a6148ba96393e6a9256f39cc73e92da92db73de9d246b76e7f848d297d44e22b1e7bcca4b64cdee9a8f9d2e499af692acd9ade36335752613bed604923ccf716be20e808fb5a4f968499ae8b437c9d0694ffa1d1d771a93a6d35e26fa0876ee9134fe71939ee7cff1f1a43d127b7e9d7d34f547d6dc446990ccf1fc3a1e49abd13a2f69fcba7b81e923e4d2844358e6840824462106dd19cdaf8b4044a13bab42bc893850f975b1897a03e6449feda9e845881389f8f8f8f8f8f8f8689c6b349d1c2f1cdae1503894825d2073a22903475a487e57ecfbdd3a19af371c4242e4ce6a7e3dc4855edc99caaf874477a6e3d7432377a68bee2ce7c89d6d232dc221f5c6330a87aa8df7b9cc99866490ce344c4286b41194992298037360cef39da37554b866f49d46217ed23da2a2813da14c8904532ba9d1401aa80b9df0f9b1efe9e5c21e49eecc3c22e3ce6efc7a680b7784218f10f48218f5c6c381b96aa303e6c09c11567d7ae788a02744332a6b4a6a30a4924c08f6803d608f8e8a8993e38dccf4703450ccd9fa53612321232321fbb644e32f916ae2cef96e3025384a26ec62794310fa70fbfa8d17d80356f103f4b9b3935f079db8331b7e1d04bab3d2af8351dc19caaf83417726f3eb20903b4bf97550e8ce567e1d64c2f3017dd41bcf07eca9361b2462040af13c0d1492544819f1c664e7c62be3b4abbe1a68e65cce8d578ee5c2a6128e1298ef26f4ddbe9bd02a254395364e35463e46463a2637a20ca9420a77724cb0f6a95ce37263097f698370d2e2ae794635a85669439fc0bc1d6fc7e84b92fb907cb72342eecce5d7bfa13b7bbffe11b9b31c7efdc3ddd90dbffe79716731bffe117d46bea20f8b9cfb82d49b9cfb6ed5c6fc6e3998863ba558a61589e3958932910a87cbf13c1913981b15b154926f3805cced6f74504716d6526027da46d942d518793b464626cb498addc8f12ed50b07b932b152271c0e874b4aa2ca0d8c898c9090502d94e9803e7efbc811ede137ed30ecf6be66a36a53226e1d0d6472cd562fd5cc8c261009ed1b9708d8085ef49ac4a83779c8c25cb0ceac57d775963dd0673909758b7dfd769187eccde8825189dcc56804b46f396454c2e463b4afdbe4aec35fb24d3e9826b57365d7533d40fb7a0abbef34855b610c49d9523b5aaedbbe7e32a49e0c559bec3047a8181ec689144ec0384fba7011d9d75d3797903b1bba335c7aa0f7ddce6f0232f95cf49a9cb8e8f594cde4b3afa76ca99d7d61b6cf7aa651b5b9551beda3e721b506d2494f3317dbbab5a7d78365e4ef9022145dff0e297ef0c1965184e3903efe8e1dc7211de3fc200fa0cd66c321a292469b3d47dbf815c7039d7c226038647ed03d91885a461965e4483e66fd43f2f1ebf047ca9e4f1fbedd39f83fdac7df719cd149e4e83b8ea3bddde5205e8fb5f5bb24cdf3ef4bb6d78369465b95dd9e74b4793da36d039dfb4e475b570a23c8be463b1d6d3d25fb3b4b4631284f432a0d36e234546d3e17129a620a1de8a089267cf8504209bdd3f2b6af97b73b13520edd59e7f73bbdceb485377ce28a9bd010908059d872d6da7bb3f891054fd775397f437cdf0782594461c50e1645711cad980126ada041ad2778511c06a106156352572c7a76da39e0521183dbb65c183b243cf10450cc102441448c5cb4864d723b0f14adb51aa840c522a626878e0e0920e2851123b3d46067adbdf708313539747420e245c763961aecba4e035d0572cec050bdd5c4dc7878ecd423a0810a64200b108db9b3b434573a2e3336840421c24266a9bfef03c195590e295a99a5288ae238be56a616776745922489b4da22b541dbeee062a79568571349b3d624ab2fd74d64cdc6f0f96810a2edb2185a6d8a50d14504a858c2ae18d75c8a67ec8c50fdad0ac05ae407433bedb298c2ee4870adbde268a7ba64992ba131acb5f762b12344865a5f3091510365b7eb8da7a48132ef7ae3f1d95665c4026785165614f1c118636cd2d5963788e200ab97a96c410edde0452f127c1441021012848a307204fc03a022b723fbb56a2b0ed203e40a3bc8ce4e41231d902cd4203cd80e0802540448929b75d7755dced5084819beef0343eb8321520b742d0284202040a17b566411208023a908902a0401b25310084aa821491a49922452dd010218a513c60e081e5550e48644e773ebd93503f1a0c80d4811a41016e10a6291db16457c7054e416a4c88d08bb5e140cc3d08ad616f9015191db17febd60ec7c8071073b3179b95aac952a85324f25a6b24422f52886e0e7e50e5f23d648d77d4218edc55df63e3014474dd6529b4a4c253b42f091c42e21adb52527d0c70edb23866d921877d8bb0ee31afc00bb804aa152381f3518af9052a554b82586209ba05aa95641b26002ae87c8ae2bd68a85841f24c620ac16ab85f3b1039c0f1ff4b45c2dd750165ed8d6f513424580e044d9e3d25a6bed7a3d6104f6d81e23762d954a259393a32f9cc04e603e92a0472b80f665778a1c410865deb508185fe8c28039cc6d69778a1c81081d1476757d3a9d4efe3d9d9904140a85faf30768b442a552a94e1450ff80c562b1506242330072b95cae588a50879b810d524ab850595159390d019656ac68180c065b41c1224390012a43653819f400820c1703287665d1282828282c2da34f4a4a4a4a8b0baef687a8c3c54009176d63b0e365c6cb8ca32b7c70b1ad83f609a023d747336066c07843803ec098c10b606260624a23313462686001860fd5aeb81e47a0214343a6078b8ddd0a2df1828d3b239c0c8a50cad49021c71a5d49d4230735666ad4008d7018d7c3c7ae331a0606066666e68923b0870b68d0a0416386199e18027b0c318281a68686465b8b93019092233534d4d4105181edd4050d3634d0a07725a2021be872d72b9ec002f00a23550829c2c612b2b9b121c71b6dbf7a25737db9403b58d080673514832c6cfc73845b820560d08d8d9b9b2788ae5822086efeb071c3868d1cd876aaeb153e9c70c512437449dcd035dcb841d2f277b8277676aa713e4adc4f112bc42002ea09324619dbbaae0e282bae891d5658615f0c0315ec5a83beb9b9b9a9a18614121cfac68d1b3770e0407d8103078e10479723c78fd04ef5c6bd2009bb5ed40e40c8d8f5408f371ef5ac5c8cf5420185755d6d5418635cae5bebf7de1b0b41b7af69addf7bafb57e5f49c66aed17f4e3bbff425c6b6730f2f0e8a13fb06f0986a0dbd6b449b85dd761ecdda71d1465f70559218cbf0f638c31b86d144a6b31c6da92dd45edbd8e31f61cf8de1702975b94d69e2ba35105aa118f1d1d627a88e101e2a235c9b646ba1d94d6ed99e40341fb3a26736c0980b04970f5a823c288c4e8c890909b13d6c7feb036324a505f8cf05033136396faded8bef7f650874eec822078525b032bc4b504188f921c91b1e35e6c79e4c61a94d5346233e6b18bd695592a55b47413bed694ad3d493a284d6db22693a966bbed89c96b2269a605029df82953fd4499aecc320765e744996af0f372aba4e43b8166891a6bea5af03e2ab562b5ba96672d0ecab453e97859ad58ad96cbf57a99989c9cc060ee259255ead7aa745997a9d57aadccd3cbe49a989c5caed7cbc4ac301886c12ecc82a45488d78bac591392167bd1ace3f3e404067307ff41b3d49f973b15157c6d68038c72516c7df718b36cfd7f6ad24e9420fecf130525164b998971293508d6b27641d9e7bd4e1312e5848cbd764d2169292adac9950eafdc9515bb52431414b27663b1949aadd5a4e99595952913a28a2ac49600dddf4315b2aded6e50d68bd633d5bba5765db08b8b8bcbb595d444ae9f42d25e655c49c149aaacd42e6a51b4762b2b282a8ba1b190b5bb7db0653c5a5f744b8b066b77772f9eb5260d95b1581616969a5b5ccc72e6da8a4794d652ca5c5c585e5ec8da6d9931c30506e625266686ae6f3d992c23d3c9c8c8e06b6564646ae942d274186a215df40c9266be6a09d3cd2069f6c845abcf206b765b18181a3464646ad4989989d933cc309b99349a0a43c6c4681a3464ac4ced64482d43d2569d4f59c3d62b43d24add83fe1992a6dd9ea54d7bb833cc686a481a0db69626ad860dca54ef5b6295949918caf933330e9b9999993931999979b96666aea5318317563d8cd8730fe30d3b61b4f676185bc7f6d4d9abd6cb5d79c4a8c808d1877d566609ae90e48c8e1419d9d52bda151361259429f662574cb29ee362dc6ad3caaeebde768eb7284bb744d65ebb349d4a4ea6f2743a9d4e2c122a8bb1c652d40664571fa7a8b35bc7a06a637a0dc1d8d545a26a53528baa7b05f2765c2032925c9a0c54c51276f5dc45bdc9556031a4cef2eda25ed419caab672256f55c74f2ead9c8e4d533aeda905e3d0f559b95d75cc6ed888a3c3485910e8a9ac83e94d8d5b31195260fd1784954dbaede8d5169bc1d8f89ea5595d79457345dd9f5f313af9e526f442416e63af634586d44af3e8e23c65d97415389a9f44ad24acf71c7db7d15f1db11ffdd62c9c68f37eb7fdc61dfdaf10c84695a3daecc891f4030db74b6782eca05ecc83aecc8bf2449244d7bb74190a4e95289a469cfb90afce35344059317cb659e6c4feb0bc71253e9a72416c61cbaa8a9856333892abbb393ed44853a3b1181dde4c57299277b9a46b0538fbd316d162689164086ee0c3645eb3cf5784976ec66268163b72f760b633756ec36c66e66ec76b2d954a6a3faf299bef412f9fd0fac2713c1c42dc08e40d24983ff03f3ec63940533768b6171ca25a612fc87ddb0ccdcb1303e59308a61612af55595fc615b94b564790949437909593aa5b19bb9536461ae973c2dad69f4e3632362559a4327d3e8f473f23911e132a2c2c8c834328db49176f34c41d01c3a0da5484262ce7494c5d6670a5382a7beb4866e403eac6ff1b4784471ed4dcb880a53c5be5e0272447d29dad72b093a0edb123157cbdbacd5bb1f65d53e9ae6bd97f42c477d4a13837a1e32b12f779d294deb4c6350b7a5c9cbd5f2f0f72c144cd9290165e8ce482f0275b9229550cbcf4d9236ba69bdb71b7f69b3fe07060ba0bba8e46a5aab7a9e646a480000000000d316003020140a0985e3799c6561720f14000e638a5a544c589408045990a2288ac118a48c32c80002002286d4cc904600fb3847b4294b19e6bb11c3915d89336877244427c008176c207546f0a3fa7f7f000d1fe93a579733167e455d4be367a25d52db5928873d37be7ab0483b71dae1ff25fd407f7b37d1e046a35a7173419e6d26e720c999ed159cb100263ffe332c53d127486b427ed166fce2b3e59150e2f9a06e126a9b7a91e4ca5040d29aad095d8c0b1a5fe4e7bb6a2cd34505d801c12e23d6a0ffda63aea645ea1d2ed42cc0ec1ef269dab03908eaec0d8661e78b415e51f9406a36175d1168872e3f0595e70c5f3bc908b98efcf3f12bf2ff49012a493578813438f573d91575abcfb573c174c0ee7620cb7428742a5517fbb62aff1db070316571cd53967ccd2f1b23c92c0b465081a2399393dd0d1574223009a6d0c44462ce25be2c986d10a0947a72630f9e464d39449bc078caef0bde81490ab92a887bf7dfc71f5f31ce4b8046af308f78b132ff3ce2063d77c5b814db20876ce2ff5b1c52f70cd17031b386522e7a2fc962b7ec2235448e79422fa44844d4ffeda66757d72a328ef39f9c94a0a745dc7f3c86637115060340168a53ea659ec872e57989cdd68d4ef5ff336addc8aaeb53522a5f28ebbf3d551aa022b3c07e378a5b05f8bc920a7bfb8e5bf922d61f4159accea187e5f1dd2f318f51a6f99bcc9a56130cab2f066032b18b46b92f8e74a84f2682314acf53aa1b3cf8e43b52ccddf37184a0b3166b01526452291a6632973e480cf7c5616ce9cd1bc7b1be9009de41ccc56f7d8e87ed315707dcd98c008fc242aa122bdb39e8729165af87e21012e2732ad0253330351bf76f8c0a72c323501bc9d79d921c170c2ef353facbadfff2c331cba3530223ff668250daf45fbb65ad52a6432d1d5bf2388509f4d4624e5a89df88b83d13281171f1ac210cc6a310e70f4011d16fdf10ae070941cedc625c25099a91a3f4351442af56976853868008a71023c488266aef4bccbea72ded1e8694a609614c172593aee99dee07616601ea8cd3c4b887022752d8cc623f75cc6a0f27b02dbac4242745e4243bb135ce42b317d0efa8a53bdbf7978f84b822df3e3a4c06f84e3de7cb92d1f5a374725110eefcb2d8f338728c9bd30ca483f0e818c4049cb549c8ba249628df3b4913e40a2c025fe1b6e10940d85ae6ae32782d9ed693c459ae97da895fcc1bf896f93f76c7b83ee4592126c01b22aa1022c7b891be9bf68f496741bd4ad54a775b05dddc15b7e6ce4824ade3e8414de3fe62675c3fefc4e83364d238a7de7c9d23cb66a1fbf181cffae4fb68f15750687d1a52a745b49d95818da27e8e86f06f13deea8f26a007a169ae098c403a8616a01938588c3219d5d0b4d0072dff0b88df4b6dfcf8e6e497b496995989c1f22bf6d43d4b4e43d13c2586537f3f2c0acecee04e93783195d5cf7b1fc0c8f322ea3366702b8bed7379a76f57c3628773f310919558ef766c7068394f3c5c0981350b415393f3a14545d5e221495ca7e1b4fa0357952064b3299b99af94217be7c583856a448bc4fa3093313940723401473b9b13226238279c11323f1681e8b0c997375c0c4edd21c58e11fdabb25b62ad281856afa736af23a11690014fbb23610712c46ffff68919cb3cdd00f071e71a8006118912c0894bc4ecde306dd1c527ca80cea2ecd78c0d0c3d0a56c43d6fc6950bcb6bdce93bea75d28fbb7edecdbc57eb10e03720f1447fea6a25553fbc738563013d7d6f723b8a7fb75faab847671086cf684a3415c7f0588d418ea2e9d8cdaeebf4b32a85bb08d0ee2ff9dff5eed400ab3950f87e8d614f662a4f922c36f4432ac6cd513c2f295e346ae6e2d7088d5d2068dc45d336782580e47c5af637b958accd854be8c9076a95db2740634ef1728228e9aaf32bd283187550804a3332b821cda83243260c27d52de87b57337ee11e4d38aaf0e8135ea5d4f4d7c65900117c4ac35649b5e4c45f2c93a1b7d4051fa15f3047b8e48565dd8f7af33a2aa2bdf4c63d7560715c643a2c0bc7fc028fc9a1d4c3e38329f009c3b95949e9fa77f85ebd4f08cd5f70c1a2faffbf8ab2293843cd17eaf503cfe08bee81df51794bb329e3930293c30eeaa4888b4a939e1aa1217211627dd50c50ceaf6e390051c933950bfb6d9193ecdc766da7934dba89b7083a04b77a1e7a594740fdb071d11b79c246fbec465f6500bd74fe1cc6a3afe35676d265679479dd72c586dd45903674ac085bd8fd0a8180d4fdaf68ecb70f223b93e49f74a056ca09a370cd27d60c455ed28d61a03272831c5597a16d5508201d0c174814572ac130fa29722faa3171d92ac46733b022e3f5fb0761114d5b3e860763c8befa4ffeb599d66040d11a26f68f8f188fa2936911a624145a1b13b7db3893a93bae30bd8a6e4b4c1cf85b1d2ae456f3ff1a4901648a5589f9c0d50b3c7aec03a331690abda4e59c4393163d8796506abc015facfe8995bce706b17eb7dc014c512e6a4ae7b106d1fd8cea34d4b4e874de2aca208a22bed7864257da2408793ca026c48a3db18c35c9eef66f2cd2c1b1be9ece9d4970b1d1bd93b7771d403a807e6faaebc7e7463f72197629114faa998e64ba8a15e2748cfd5b4d1645e16082c29dce8171e7b680cfe8840ff9444ca633610574c0be3edea7736145cfed73b64a8006f8689c72c1979c88f91e023148a1ff4fe0e143b4a517c823b7d2df8c5eac51e6434967a1f57a24868e1785394fe4f73458772a83781cf883ba805de2d788215b771907f1536cd1e2c58b52bc58f1a2162d5244f1628a1653b4c8a28b142b5a9ce2c58a16f155330865f0307b4d70d2ea3db7a3419fe60517dcef8acc93c245bb4d7c0e4e85cd6f598a2852468132251452a048418a81f221ff95a11d7ebc4dd70e33f21e3f91d4fd026727c22b2c6425878106e687bf28960c34febcb3b3d786bac3dfe1c20102138f48c7244da5de0492d9f8cad914cb7ef91957e0d753ee4a637931c79c0402a85451c7cf7d356893b10c44812f8992cb263088db55068b8021280fcad78011800eb54722e89777bbfcdda8b86828abb6ec7b045c643415aa0823effd7a7a5999023ca18f8a42479c5642945cdb6730e270c9bcdd7c45b80cafd5bac2ab7e3d53c0745cb76f9990f553b0464701ed042c425c76b170c66dc0e7adbd4beb964e2969efc4da8f4a67a9d64bd15df58d51e950e1c9c9dc0367776ee0b917f403ec93828b557a9046bc4e0b671305b555525d0a67f90477c964ab4c1b81df6448a87a6f0faa3eaac8c8878a0877f92997f13a456dd8771dfa191d1a32bc0b02019bc6414fa375ba1a74bfb2c97c1739ab986ebb504cfa0b48184abb233e3b28c9e424f99ac461a92bea73b3c97344ba610adc126bcd8490d435e273ac37365205d077ef55747a15094eb6b5989474cda5b051c25d184dd7110709bcdf5690e280858ea5c9a2d42d7ea8d3f12e3956f1e022e6939723205c730636b929d904903079bb0e958c9c885d30a37c18550aeb6ae243d5c9e6a1d01d55186e09126b0509f26fd27870d9b57360b712ee5224b11d9427af46949ba6cd653d72d60290c39171fa8244fb9f4af925d9662c60f297b8e1897d4a68933d01a7a3728fc0f5a91989a137d3848c8c3b2b5784fd30c7af4b1d2031dd6ee315800e9b92cd8df2ea9fb8d7b51cc5e8fe1a2901b284630e156c09a24962d03fb2ed50b8ee073b6d9d9e8ca50001de808759ea9e88e98fdfcc4fdfef9c8aeb7ea000d0cf946848404978e6bb6e7e55a5806248a9b81a4dd7450998bc40dceb29296846ca4ab9232a3920c5eb6b30301e8a716630a33c989ca5b46eed1153b09911c8a7ff75d4756505e544b365c6ba2684e13af6e3ed9a5d94c6cb98848729a1d15cb9027cf1201134c98e0e5dc63a310a3e0ce5449bad0d16c5aea1f9935c6b9a593744743042a432bf92158796c25b43771b4e056184b92eaa781414289a3304f1b812f823132b0a8d246db5a9a029636310ee7693277994b3bd6cd366e9dac9b35fac3eb29611913e0d0d9503a38e31357653ebd374011067ae492aced25e799a28d0ebe5328dedf588c9740d35f05f1f68a298f23482a5d88ae8780b4d33851e96c534a0e92bf26ebdd03b05ff5aeca0a01003690eb2325887c2781a93a0d0ac4c74de57587de0630f6d7506e40ac71d60e6a663d945791342ab8a697fa39a086b339251a328d171ee07fc7a0498829d0331114d68e541dc49727fe83acaa20c8b58cffe7d9547657e087c47c09954156667069b2b624dbc97377a050989a994c178fc9a59ae501d1e1e2b95ce9cbc11451460608eda71ba04913705b1f68e1a2148a888fd3d559a68a1214d97c94029cc91aee8d884a9180f04b08a066b5a58966720090ab682f11841b6027488d6bc9bba1582ff8c55e198a049ff1fe72dd4d4ce29658efd8029c43b4710960154bbe8a3ec85f7e6df3e436675840921c185af00cc50ca15755a75885a82004a55c47d8989b759eeff814cc311488f1a60820a0d97d32e6d50250f97cd24c0b5f952a8a3629a1dfba9311319edbfa15bb80d80f24b21982e0a6ff00125c7f68dcb5fb5ba75389a67044c70825ced2c22c1377999d453324795d1c485b72d7dcd3b6057ea37fc0ebb9684a4ac2179681e481884fe1ea635df17812857bd50dbf6977566feec755b0240f242c89b305de1bc079e8dfea1280939d10559864bf222489a5269583441e446775087d431d46bb39ac35e9c56213ea52f6c548804bfa1dd3655d88802f2289a224da85f39fa77338cb0fc6a0e09523a182edd5247b1580881aa14db27e4664e91748cec938452c172a1bd11846962b47cc353a43b30ce11fbd9cd38aae9c1c498369bb5e958adaa213ad9021c452375a09dc85690d3133aed7495a0b90641a1c51a27958f4e4731ad9d09656eca63695f3f7f3b71a75e7bcdf456268747e94c992b807fcd4f1aa3189ab56ffd76b33a5556c31d2d89f5780c2b00aa08df661ac7cb25072dabd6bfcd9cabe434dff87017009316a7e463e1d805608694dff55655208c984307719303850e006e0987027dd7c0481c8115be6d1931e1488d6f8b3931aaedbd2df26d611bda72a3440084890163d154a1da1cf02c9a552ec11b86ca8b42a6e1a7447b12dd169f84911b26fcb09a025f1937cc973471247fdba65f00c7bb4fb6f1d9191da9e49d19a4757ef80445f0319d1a2b424725f9d2df4e5a72fc915b005649b24b650e0233b93c01cdfc2e167c6f825ff987eb9f1f3b119e15611226a51b51b28d11c44098f8e0a1951c9653e06d53d2c88248280f1007d81c6bb0271f2f1286666d329802b505ecc5789fca4f2898de1dacafd4561ddf93573f1bfa7682ea4f93619452a2b908c3b994bdfda6e9279fc8fb8b5c304a7ea8eafdcb9ea6004a299fe09f5f01f5a1b0ed986f0aa107844366d9dfa35fdf4cccec48899745f26c2c33f775e72a609036902c42e74cc41acbbbaa89b9c091f2c6ffeef833fe9508d521091f1eff6c0ee0c6c2f8c9f14c81f5f8a56a554516790d646442f3982eca46906a662e882970e6eaec8a1e299e02647325f4a1a70c02f68bbb07b67362ed2c80d26284cd8a9140dfbb88d723e093aa580205fa35d546d1f51011b1d8e3f2d4ac905ceec59e0c5e9f709a6a280c5e01b2b4780dbe69b71a059bb8ae1e53f8848e089704ed833df7c1b82db2fc94f5b9b8fec7bcb45e9fafeeba5fac47330d035b5a00aa091e4790642bc84bd74d98de619fc9540a16c88c36c349d23c01191437dae431fbb3630ac71f61f35e494e4a34bcf509a37cd5503f65442cfa99df9f1c74a04acfe4315a52f77e25c1ebd6ff7048891bd72e8e96284ab68c1f72355526b6bb16629b5b62082a28a50c10ed4cc8b41e1c621fc2850e734aa07433702beb5cea4a3a87d6a0ca36a070d0e10c59f3e382feed18e50438c2225663196481d27a5e1cdaaf5eabd4296319a7a4dddd0175f098782d33ff89490cc3ce48e6948ab5d5c75f4770b648d4d4eb70a31803732897854c738bbee40c7dbc6c1c65af207a2adc27e63e6a7630825df7de756c7e6e0c657b48550fd41ab07ec0a7bbd37a2986f5a7fca103228d71dc0dd898676dd205c29a5e6e58e4ebac94f002b346c802852c92e49f82fc9e363ab5b3bc3257ae23442b2fd0eab7cd32a7f195fcc7c478d6333d35fc3674ecd88c4818386bab7c624fd086160e994de3c15a9403f1611807313aec549ff2ef83dca12c4bc10328aa9f1a354d4c99844d6614df4106afead7b863a7af4ecae359f6261b1c5a58c47aef133e00f7b4685e896e11f713506699bd19c6a701df7e545048f52916410184e04c48a8d231ebf2c44c50c9160de01af1bd19d6aa84f29d69c7ec0b9fd15cfcb90a35ef76f6ad2fa55e46f937b0311c80fb6d1906a57f108a057c4bd2257b4a07059f2e52ac50ace47ce7702c99e791f83ab4507a164d532532557b41664e2866d8d0e182f4178f2782595d29b91d642448077a3c0b33cfabf2cd4d34323aba30a2f2690d25004d359a2187e53abc86f7243ee12177a9871d585fdb12a77b19fa39ed1e7d2ae6110da83f2ba415e5fdb1148280a99880859405e99543eafb08eda96fa3ab521f690ed8a4b9f662c62c52d16289b69e26354f671de5964542d2be06c31a35ac03d5317ad29e8d40b3b64dc5c8b6c0b4533277407aeaf814655f3006b9db86b33f87ec790a7f024283f158dddb8fc6176bf147c3fc87242e3a2fa93621796ddad3fda79544a559fa4d839cc836fda11d26e749e3054395faad93d12ac8481e4f89903414072d83d9f6f9a4d87d0729c669deaa004b1823b05f42963bd5025f8636d346162a8fd79e175f9bd3e8fdf6b9fca363b05c182bbd87a9996831d544248f3fa678e4477ac1bf01d2df8e4c80999136f1bba660ad29706671e8583322c150b68f87e4bd1bfc715d5d9ceb6229b204e1999b2bcef232c4d9595cec5fc023c8925a74cbc9b6695f30f8a3ebd3c5afbb2c2f2ef86c20bbd50d998794ba38eaa0599b251ce61bc579fb8f20aca9bb6ecbe096afdcb2ba1f657f75fbfb1267aca8f9de2fd6570471b0d5cd5be928d95fb2b154107c51b5e02468a763708080055117e1bba65e285988b01db10da89b0f11ca4a9df61b73a53b1838abc14b118720e30cda342dbc9cc9c1ed2baafff5a1956e599fd9cc071135c84ad1b8134b06da978a1565f0dc214f9dc25b2cbd0a7f832c789b30a3de0bebb348641b317ada0af5e15b8b2db6accd7b45c57c466a82445a72ecfab87fb7fbb0eb9bb7c943d17542413ffc041fc358179b9073453b23716c19e09811a00f8177cba81a49baad6a198b9e41e6600dd10b65d5d5e56573bbc992c0954716945c91b47918350c46d1aa3675642e665ed917f64054f4353e16d4ca02a865c9c989baad9615363e1ef6d0b6339ddab55f9e116a8c2d59e793a3898fac22995faba046fbc4b58a65b34b0270bfadecf8721ae9c796d1d1c2afe46e115328fff7377dddb67a880cc3dac2e7496f04f80d916dc704d42fecea7e22178aa7fe04dd01a6b8c437e3cb7022429cc0ca8689c7ce588a43b7114882f21d1559227208dc67ccd3c630045821ccbe446da38bec12d05376c1981a0bb3482bab3ee485278e994503508d2dc4cdda80625b33e2ea284033d361d5509fcf1ed64f22934c615049af63f3c9febe601cf21069689f6fdc3405e974b15d8116a51dc30817bd47055b5988614c26f6d11e4c6635a3d6d69f704992e304f14c90feba6f2598d902a9afabac9a00cb05e22cb02fe0cf26a5ff7290c5aa73c0a54fc07697a17b053934857806091dc227d44aad940ea50699b00e3eb214e2b423c97689d63b1e66cb16c40310b63834cf72598bfe36aebca683a7340067349fa6a8b1bb7d397755653cf86f9d2c36a04fd361068039e886b070ad8509b193ef8ae8847412be536c1015214218c43a2181cfee88c9c869e9e7b3f31967d5cefafd7e9ab3f1ce1bf2705937c9d46002897320c8d89f7ee8613629f33a42b7ccc792377e58617647adcc679af3f5997ac49b9ab9aba7450a3a3f7a22f44fb781db5e6d8d6aea0ede4ce2ccd2e8c44e3a56b87e07803be83c0690ce65d8d39b283213c257edcfb13e2f752b722abcdeebfd5c8ee3a4859cbf0643df3058d2f879206ff175c4424a0c54d22076f71e1254f99ebee318fc83ffa3600295031db01f65c6baf3ba009c4ab0118e062804cd03b5a47c6740b24e0129bb7a27ed7992e6e9f421f49a965fa79717d254cfaa21636516dbac47406a3b5ac8e2aed5a88f5e174bb60146a2b402f1a5e3f9c24cd2ac07bc6a27dbb26d9d4af9f4ce4b8a8e9d3cffe7806a1653064ba366dddeafab8b644e4c693f7dbadc6da959e255ef3325591d8f54d5f728903f1199649062e9f4c7a2a170d0824c822e80ca8116edc18a1068494ff538ed595e72052e1dd74621238462296a7dadbbcc17955ab947f979388bb5cfcaaa59f8e5a88ae61909ea88d112802f19d6d92fc17b887c05dcc24cdaa8abdcc003bac1388be7ad407f6bb62110e145a9a83a71f4d486e8a8fe8ca03a22e39ab28b974e91a4158d42bfd9af76a70bea900c81e37eeb206d3f65d6ff8aecf0743c446aa6ffb515e7a34ffb2a19420206841546ede95e0df80e20d9aea88084d3a646208ecfb75e66749a1b2811599c2f32736b0fdc94f449bd134a5d88c556c0ed7221bb7e0b3e2ce87d4f245c928a8740b5cfa4bf4ef078a51cdc815f245ee99263e3c6e618bda5559a08406eb3d3d9183ab067fa07bbe12682e476cabc8adca7d3f9d2b477ed74cb178354641c8113911a9fb3d43de64c19fdbc1a80ea3cff74138482b6a0c7b460494a585eacfa01071c976bae0186b155690db285f5bc94224e31ae7d19441a96cf6e33a2cf84a9ba8664b219077ccc19bef7e7a21fd9b3d40c4d59b22cc8264e233b168bb6a41af7776d868b6cb46d8f0102671ca2cd5ae854699a6293b852847f6d94370aeba4dc9b3dc3f3d541ba4a3062ac363d831daf2bb99d8c6f47721fe1ad568e1c4bb69d5c1e83c3e00656b681dc04b699d22faa54c16d4927e9784be6acdcb7f9cec3c8a1ba5a68a9e617cebbd30e5781ccf862db295d4fc641b69eebc6f847cb9c26228ebc91fa2fa01155e8369f15f0e4daa9a7025645592d64dc02c764a60a7f7168d501b2893a58d71fa203275611a911aba016ab998bcc5e1670837bf6ab7ad8e77f5ffce6ad4c368a943c6773351adc143d448d18cfa8ba88bbb5fb3a277affb1b3995cab9a4d5c50e83e6666a4228250c7a971ca318ec42fb95aa01ab7fab96706fd1d72468b8d72037b77d426d50109f093e6ff69a832a7a7efe9471af9cb7e22a799d89ac0e19cb0a05b8ba8ea2892aceff52571ea2e201bdaeb3474799814e959df59615c4f8ad0b09ab3412d8b4268c50bff911a495b73f892f7431a5c0e5f0d6158ac532bd6279abb0d95d5c1f06ec52c3ff84f83959dfa10b265a3392cd69f97b0838d2b14fa20b982bc4fe46fbe0f1420c93be0e43a23500a1f3432309ed14946e15d814dc981ed91e135f84c3900c3ee914ddfb5f6b840e7c9f0770a69bc059c749006f7e1e38e0681887dac876ab939b7fab4757ee1eeb140f9a4220379aa254531fdc3e4f21ff54323deb35cf31d8832241240b137384b4d78cdf8261f622f259b0d7af14d8abd126778c6a183b4e06e71218e0b330ca7017fe570a1bee52f914cd142b12b907d0105c934b8b8b9e422d8df52cc45ed0c7301a327f45fb501e33c0a03da859d305b0de4060ffcd82e2598752124d5d431b068db3b1906c50f1a41f407be6e161b8cd21cd47cf3a16dd189a83408ff7406ca609daecb4fed3df3e2db74d16c50df9632307aeb6210b4cf130f82ff63b584cf5f83125718a5f94e2d5db8d0484fb0bf9ea10683cf2a7dba86011b17430bade688736393d49130c2fb6f300d6101b241d8a7c46441ab7a2fa993037d4e2acb79fb574559a91cffa1d7943961a834d80ffcdf246bdc293bc73ee86222a2d749ec15d73b0e10de963d3fadde474cf450296e4fed16d60b2ffd2eec90178072173bc307eb55a256947188a0c49117d5e56163fd84343c75e2c5146a34520d64a8aacaeb1327d75af4aff47c30c1fd9016203cf992951f7c0ca63ac257dc8feca20dc70a5f565233fd62d0b7731ef0638cda256961d921c7552beeb598596bfe622ed4aa2e3566d5d9d09c41f3f7d902288ad88b121c5aa5cdfba142f4ecdbbc6568bb554fccd0c3222fcd90ac5429480537c77e54520585e3c043a4d05e3cf8524168c4b72d59a53ce69e88389549d68d0b2efafe6f4182be0afb1eb9743f06229a5b265ebee5c8aa7d2746e8c11b9d278a27047d7e7f6db368b74e6a92f24d0e1619d01f7fb837a3b117ead832d7af7f22775942056e99c5a855692a1d2e8596c534136d26526229ee1350fa988c87363c88cf619f78ab14bf9f02435a952d43eeb3560a11f403151dc46623abb0fa6b2d20eed9a24c698c6fd85d6d62756ab4f1923855daf96afa9ce61d4a90b8420e22a92efbe59742f01c0d82096f05edd9697ef82900acac99a0ae9a2409f7c460d4811499ecd98077344bc66115975b1bfb02c4488ee7185d3320d4069e5063bba017a89046e265ab74abc8bebf0a3bd5ccb14e159f04aff9d81acd32c438e30fe8fbea04b5e2027db497e66f75823406a3918fce32cfb03ee122012a6611d8865728aa635207ee161bb13eeb2a810bbc7e9b9ca83c1fb772fea1471d8d575b24cabfa8df79ba8ae60dfd41fd05e4ba36c8bc2b52ff1508b08281b0de383769e5603df2bf117cba463d092c67ddb2edb165e00d9fd34de61c1e7b82144feefb1b8cfb622c89d3cdda5d862e462ab1827cf5dcb155c8f9f243dd4d6befe684e191c9b784b49884e17a3b9c4dafb0c456714984b916883c81c893dbef9cbb6c44586f227eec8106ea8230c6ce52588ada552374a9eb5c8d400683de49a47a30972148870b24fd6fd6cbaff0f464e8caf2b3904d327b6ff2084fc1b39f2251d533eb86f583358d55dca176e97231e38b139de63638cfdff550faca74650d553a72b6a0b6e3fa4f8eb288e5922077e69fd36c30d3b9c00f3ed7240e682ef84d914ec43964fa5c136c8e9d63fb714b10033236c193ca4065183841f1afe41435d500a544a6fd953cd89498ec806f6f2c3c1d26cd7182871662da20189f4f8de729856857e27c3c100527cce3fd647202c749b7b368c47169ffcc863acd7b139e3f6da9bdfccc42c682b519f94ad7336255508a36b76505ced0c06403a968b82c63af4c1febd0f9684072d823e9ea8268d92e8b4234906653e1b248e06934134e880929ac223a46c13b1b6c19eca47f01f6a245acfd85206a17f730a23416ba6c923ecdd86088fc3927438e3cd9c81a17d25d92496c889232cff728d1a9d4d1cbdf099e39d5bc9da5cc34e3f2c66179cefc988fd5c7160556cc6683de9f7830a9be7ab63a548e5d97e175668147e66028af4e4216c5e05e653f47674dc111d9c5319dda52d399e467e368a069253a41c0a36f89b916a19f8306f5a833357c06217af248f7caa6fec4891cf06b1a920dcf806bd543d31016d569ddc9497c826da8fd880cb25dfd99eb3db4d387525f7e0488dc64afec2150798fdf2dc9a96bbfdd83cc7c287072ddb875c42bae7a316f1044c15caa97f8768429dc4f5fda20ea46f4bd38c5b17ba788ca53b04cce88596dfd76364cbeae7a6d653d21a2d49414cc569f450c8ad9472015a73b1350c2abd31ede08743dc5291651c7ea472887814606e96be6f90adc3b69b49bb4dc4dc41435b746b1556230299f0c0ef0f83aac66375005f30cf79301bc050bd1354760737ceaeba019aaddb61cdf2c6df4f920a3c184a32e66400d8b418c1cc6a6ee4360ae95beb7d05eb189e2ff230fef882e414b916ef0210fef145d004f21ddf0e1f350fc5f33c059b0105d7304361a5c40fe844686ecbddf2a42dd325b6ccd304151fe64d864876db2174b3f70526c3d032bf9e6292b09678f7bacd776cf7c292265b04df87874ba08adec0d66f58cbf341c64c055a1274d0e728b89639dd4533c4bcc17280be5b45ea9a82f7f0a3602ff2e0f6fef0b782d0d51133f4423a191de70c6f4db168af99fe640c1769bfc9681bc58fe58e3cc6f06193552bf0705210f5ac1a2df88e29780664079001b1305286f9218291850563904cf9338fe9981a86fc029c8572e02c4dfc3ba90d5f5839b52c69b0c6c3b932dc87d7c43e7beb0f5f49f6f1a67101a1445ded8f417cfd30547f5146a33aa174b4a8fe6b1bb0f642bc3fa7a0d63eedf21e99608a666e282289709e87109a3daf078db687e783519afe53787a066b041f923bf7b9af11bb87dd688ff6cf2b2c09a2b4bebf26cb8cd8c410d2d7c612c18cda6b45f260c1bc2bf5521f9c4ded68e9f9e61f51b293750df0658ea805ed9138c2e192fd8fb7488890919ed006e55ad66847715abc813e8773168420a76f502886dae21ecd3cfca77a8870b4e784aef632d2d13c9ddc10ba5a36c818d9713fe6289a53e492f5ff424b449010a600dac41d0c5faa8df1fbd662f4ebe013e7c8937a88a192b405f1d3c6f9c6d6f7eefcfff42f9868c6cf9cea53925620830379eccc761e40eab192f6af854069f2e8fc3a334a41dbce4fd26ad26db932a3f5103cd39bf6e441a9d36aa847c6614fb8792facb7cd664a26af8e9ebae1d2fd0450790104801d169e2041b78eb26dffdccd93799903ef68470c369ccae354c96ebc83ee081d59678b73f9db4a3847402571cb53db0307ec519a701e1f7a8a362abaabce82ea725470eb79886193f0d9558d34fe11f54445f86cfe79d66cfd6e6599acccdbcd19ef7b6c4e640f13f1fab0057b10f20fb04edf6a7287efea949eee613dc50fd7c961d858c5d82fba68447f3e6cdc73ff3220a0d11c68bd836738920116abc15ba1863b354ba6b06deeabbb4765a1de515182a19da7538d0246023e4d0524e3cbda12e86b26e798d0d8a439ad81c7c47ba5fe3b043cd84a836461399d70ce8b211bb589eeb27be5a18c406734dbdfa9c3e7fb4a8490fba681273b2cbe895b0b7e62cd2dfcccce06b6d2510198cbaea4d4cb303b3d9a4a86777b29be841ee00b4edc89ba90d28060405f38ef8a65bb0eba136b435e65c4d304c6005636f733f509ea4e29f7f5c0781115938a3590e124a8c8aa751c50018aeeb147c86dce5da01afef6a5c211f046701aad00a05028152e4cc30f392e87ceb141f9667d440b619642cc264b6e756641d5602830ac37d24731254e5dbb4e71e164388ec4f0f9da772854f799016e952b385ad670c3934e220d8d2877dfe8dc151ded3ccdf010536c2e916dbe0edea044a341c33091d765df3f277e3eef0064b5035f2e822abb5bba90704b82c30e961355e6e362ff584550b77564ed0e674c401b8ab6d655f2233befd67d3382692990b9811cb6499bbad27a800f745b43821142490e3bc43be087e906a720329757527f2b1285b5329c17546848db96c17d52e110a8d5493e6d46aadf0479c0253159ee541281571a98badc28ec4edb02adbe254e07b4a554283884ca5d427133ecfc1e97227d1b4233d9aef839c1020fa4b9896217ab25156d88064c81ca9450fd8918ca7ef425fb07401dadefdb37a5ca28f786dc92e764b6d09fb9f01568cc1d7771f37587f76c2440612d21536113df6a0e8cff6e2276b0143849163c13c368864a3e0978b7379d3d792bd333dd708b685d752335d11c186652f97fee5b18768cc82d9892b4c386b0547d2a2b6036be925ec7d855f223cc8b9db3b73cbbc2f61d8acda72ebca554f59a4f437df8e12b673827a61595c06c896153016e933cd1288d02879d65bb80db2993d6bfaf902bdc08c030c4a45bd76ffa24fb39a918161c728b89ebbfca4dde9dcc7daf12f700df6c103da516bccfde0160409e145ce6a4835a5b6ae6af691cf5e8a82805027a2469e9e045425bd51fd55ac661fb5c4d0d51d843a9586aae394be6c2c542ac60b5d781379ca281698d2610151429f514a08f0ef02afa1afd8458d5b7482ee244da965472e94970176440d2bbe9985e269dbe9ea732920f6d152a99bcbcffab6b4f034ed60c092a14afdeaf38e5c711296ac874de5c56f57cfe162954fbb39746bb79cd127e925facae9272edffa5cdd2a8d601fdb1b7b990da4e53422062bfe7c13fa61a6ba3c27859cc970304bd9f89c825ef3b42e6ffe1c569d90e5df3e4ae5d3040b664a7916a5f555a81bc2c7cc3c04270c02572f76eccf1845e5da0e9306595c9a5b4ea0b43e73d4f6cd3574ee7acb9108e9dc5a26c7bdfe12e76537303702a7e14bc4fb2c0bc77e31cf0febf9b8361778da2257d8c27ba8cbcec43e6a944bcb39637b0309666abc3c9cf3f141a9d0da52fd9ef6e18042a95014005946f6488b2c62175e045d00cfd544722a6cf808248e24573b48355b5dc1873c48ab8e4261ad32d00c10b49a6ff081ca3ba1498e5f66583e0fdcb59c64addedc52f9bfec6d00f9441fd2653c44e63383231a745550184bc6414cd6dd92f14cebb4386f290081859a203341f37ae7ef75a9b49f4b7cc904aaa1c688ee83b4033cd95edd34a47932cb2f77f7bd8d3d3a93b8280836fb9258c4529c19cdb2dcd1b7809fbd9adea37603ef48bb273b1c270155956dcee6519f54d8f9b508af200328e86b903526035e3864c038451db6d921433136a6fd800608fb81bfa83a30223009e6f1522b7ebfcb2f6e76594c50cc5d2a8a114924758477406c7dcc65b3c44967a5f5b80d846fde5a922cbea1ca2fd7e6ffc4a1f1e1d5c6fc8d0c997f562bade633072d4f4fa4e4643aaa081c164ecd3b130d9dc4d190399c1ab2fd5643c61cc66864f4cbc46f3a329ac9c16ca8cc6443fdbd1f3bd5a8002ff44d87b086d07a6b68b70c073f98da50c3713304376474dda21b49166ac3280540b72ade2f8a7449cbce2b54b60d956430abf9ab501560f9333b53ef6f28794c5a56ac42da8b7f59b5e72df0bffadc493dd1d72fabbff8c0301db623a8c94d48867188b87ed13ade7e1d7ba885e3729da38ba42261186bb780ba95647f59965b20a169eeedc5b6a2c0d818581b3a1404ec8e7199d4ee62f6b19d1dfc9c9e8b5befe0c85b60bf6bc6de1f0bf794bf57851d4a185901ee0f96d1c1bf868e0a98fb40fa74ec20447b5400d2fbf33482ecd681606a4cd5320d5a302f1fa8f09e4870934bfe61ed893d81392035c848296e19a53d21024ae41161d0f3d238d7856a4b20a46383cbf18d8e9aa87806db7ddd083862402dbdf07b3cf09544ef39e00f1d4c3cc5408769e6906a9c6c264d3412eff94b2ee7f5791d359e03e3d673a4b49d6756455b40a5301e552ef7f90d9926a32f71f014aa6579642de1d64136abc6b5d4819bf98c869537eee90deb65da9a013ba16588bc629e6c8cc25ed83cb4631e52e34e30a9ceafc41caa8813fd167ba8b85b3bc7cb3af40b337997f1f4895e1cc4d64a657302365e59c90ee5a22ccca7930151d1082c10760ffe9ca98fc6db4c2566c95d19f68068bcba17c780eaba5b41842de69cb0d119cfb2366e4c6ee62b86946f0d3e9b201443a65084de1aade63271aee36da013b7467c490cd425d246141518c15cdd88fa20bb50ed8656483d556830504a342200175950704d5981435935a43e2cf3e98cd78791bc0eff1a21f57cafcd82695f4216aa710f8cbde017ac23d352e302624add1b3470bb6b479e7ad2350be3abbfbcb34a67db92c91cdf2ad5f0f5e2c6a2fb6f9366d63aee646b3ca2a537a98523b1a9179b3bd336e25f197f6a5977ce536ba3d261c92e9b469e083520457c3be74cd0540860b1776e6c2715e42e3bbcae84f6d382e5e2c16fac605fd4b869b3b95db2901c450f9c9e47c503ff0dd51e994d1b4e8614cb1c937d52fd602d908f434cc11f211aef7de4b644bb95dea7a0c80371e5a8cad63b5bd80d373588c2aed131d81ddf11eee2e36ad0563472aea2535a72c30037e6eb78fe9fa968215d4a116406f042ee6c9091b53f4ccbd7e697ec049a410326f5d2059a2e7bf28b1232784266b4274f31e0aa80206d6ec2255d3b6c52a2c87e441c5303ceca27ae814863bf123fa5861a9833afafa014b702f8490feab9f91e490af0ad4ca6550532700411524e1826b3a0aefd03618c417114c8e07500de05cc400d0aadd1acb2d58caf122641b6d2f6e5463973a6f7a0003b703b05afbc727e3a036ff06b9d3debbec30fd3d9c17f26c96b9b368a101d57b63d4f2b657a9f5c95167294f4bcb9bf7bbaa6e6b1e79ccdd985eb8bb54d8d648d77a4dd34be43781d6c5d952ae6d540cc53cb6f6314896c7a3925b1edac99ade652692af9e6260c2990290c60f42cef11d6e5a161b393ec8241f3f8eef9b427015e8b150d1f7f1a6cf91e6a9a07780b3312e8c7f5e4fd04dea218fce45fab0e06f6538ba60ccc0c249eec893d7009e67df713d17f1650f24af42bbd480bc66b83a1343d4594b4bbb30dd970e198f5bc92bbcb84510dd71acdd84906200f24cdfa7d0857dedd14d880529aca6ff7c5715e50cf0f54d5e0a73f4bf1d720b9d4e736613d8fe5cabdb0f1a798827b25f20f8133107c20ce7e6695fe298a6e769540439218a1bf194c1caf7d221094710b0b29e0938399845518b980a0016c58a80a1a958faef02e6dc4f8652e31a5eab97963761ca0e381ca1fb5546859c499da3099f717106c79bf363ff33b51e5517a3ab27fda8de363f43f048554ef8437aec3d51a93c2065d3f61568347a2a7fc6a4478b04bbd33598140b200d6d8735e2e85006c34ef34c7209c385e36409c90018793bab9db528887ebdde9347a4dd951d822d89f176ca92008824997f70a70a3f5a156e993d58e65424f4835a676c5ff24c2d9d236813d4fc13058305374c36ffaa6801f0b469a890ef30cad842af3e89b0d959f344557c7bde9db99b66ee8ffd40869b0d76706abb1e95d4d5181c9945f99c5bf26d0194533132616841d7429a2d8df1fcb64e1a78a4d6ff8d9038e0e1d805f7c26579ee90481fb4bf9d10b738a97141fd35fdde6482392cf662bef8cf957da60450eb14aae6a36ddfec5bb982dca47d1fb259bb1a9cc58adf7e3ecf865d8bd767cebc0bd15953a01f0b8827b2ef81b01fdadb1ba119757b0339689db2f486ce706070abf02d3ce8deae60402068699da879102d5dfb90fcdf11cab8aa4a98f0989eac9e0962069f3566176b3f28732c8ccf7eff5d214f802a3944ad0b9bdafb09213f69f89f41f2554b87b0eccd0e10033fdbb2cefb53b9de7c4798ecc9d4679db8399aaa069c7b7c9a2d9cdcb203dd11e6ba4e7cb69215d6d8924081ffd673a73a3f29d052927fcb50d18dc6174d68df259591efd2025b3dc8564a2bdf60c0dbb6548949dbe8e3c2864c8246440e6fdab8622e29f142c541d01a1e4a90ae65190137f9e4035205f827e2dc1208a8f7485d2a11132d1c7f5df5c3e6b68ff2b784a468bb4c33690cf892687036a4237071a67363daee7ecdcc78c3d20143154f9b102744e33c116692d6109b0cb8994eb741412071deeb27e8316e8a66f6930eaba7e844aa6f87e85f19c3863a287b96a127c1f025964583ae79595a80cdf18ce2b689c0f1f49d15e7110bff102129611afbc91782e4d86148dd8b8195109825648ca3dbd9aeecc8d87efeb502220d3ac0db227d5e0f538036be950cd0130f41866d784337174292f1a22be9b3a0bf8b377a69f12fdff2072ffd8b8e4cddf34dc0e2738ad69991404271278eac3c92fae84ae36aae8e730590a641a38814507d0ec047d4ada60bcde98a98109b70d82e1b1d724bf589556538d736106b9ade54ae48487f476426f5936fe01d2127420eb2baf45dcb3da9fb993d6af147a853b65b812fdc51ef2e460d1444f8919d5a20279339a90a83ca5d06f325b917eb7ebd6eba86f4d624faa689ef8ff3e77236b5cf4194d0eadde0eeffbe2797388df0170d1f3b8c36c4332eaa4097af001699d50d060fdeb948cb2e0d49317b38a29f335d33f69dd2263a91a8944ea324b6c47ed4dff3d502683eb8237d3fe3f8c50ed644166713ae686a49ad6af0e27ec8e584c1363bc6325d22a607ee1e84a72a4ea65e55d05f47d702893200cc42b81f499c27f102353d2bfcb2f6a843498df3a8d339b905919e4e8830929ded1982c4486b586845d7c372596bb41d9bcc3037ec7c0c863b9ca5bbfbbce97027940519cbdcc0137b7f467eee8323c62d768325f58ee9d978e357d3d537706e6e98fc89b8901a00cb892af9049665490a0e305092e53c3d6a8b327cc35c261ec2961312f46ea8ce505467089dbb29c222c33f558a68d6f748ab17f8cd1b51a49db2796ae47691010e4c2bd9d46bd50f16e3e7f189b8322f86984831ef719541a27dfdab4d8fe72ee1b6e474c1ab016ad581999819c0c2d98884bbce7af2db729838314dc19efd97e71e3e42c2206f2ed33fd1d60afc18589a2d39ec0e766afeb77e9b204752d0134ba2dc66bed4a1f882dff3afb2a406b049796c53d3906faa71b2bdd29ebc02c4ed07a1bbf7f9762724be5d4188ac0d80a9eaef860c014fc9b8f1762ed1cbb92febee2c21c2d1919b0980a80e9cb4a92e010a51d7c85d79e56b8d7772fd7ca4c0d0096fcb62f0ef19cd78c26920dd3954c58228fa8a170fc11b847a6dad4dbd79171f4d32a071b48d4c58ec47c0660c54a2e69a99abe187ddbcbb3ce9be673abdd553570b031024d757f9777a0b9680b77a250f664d9691639ad98d2436dd6aa38cf1aa7cc6e0dfd4bb428076b50d0e696acc4659d655bc6c4b6c86e4e7bc052d79c818fb11659c2d57bf06dcbd029b3c9f79e75604f2f4bafaed73ea368ab24ab18172bde57892729e49d03d83166596fd903963b69ab071ae4e1e5797cdca02f2d3eb897e60917cb3ee007fc376ecb2bd49323a15e02f325f84f19a784d3bc2cccf8a5953f3a0bd77a0d94476b2ff1d4d0769fdcace6a1ca71c294ab268ff9b8e7f606588b11d51f43f2e1a6364cd7146317c6d38567f6a75acfc660560095d3920bb4fc992c10f6e70ab0e851afc83a4b63446b5d045a0934d0d72a3d16289b9b6d293c4490455455cb6f90409bae1c66c1ef246d11eba16d1682746c32e13d823b6de40a0a5c31db4796586b315f777c33453172fe99daaf7a3c486b28a544a65d8175cd83647dc5deab76b446125217aba4ac49e29504df550d74f98f8ff658e6681e39f62cf2c80dd904c853cf4cc77615ca6a629a4781e3d29cdcaec0229eefc297fb985a52a7224e893f47a0afcac0c16c8897873f9b67ce4eef21f5fdbc3afcb612ba57765c69f9299e6e0f9a3402bd323290a4a9d5d091580002ff1f3ddd2ba9100fbaec9742c6a55e6aa985584acc2b1d04a9921fbc3773cce8996eae5453d57026bd4e9c4bda801f0edf92b1e4dd9f3b457aa8f5cccef68f9ff9c8febea6a6a26c15d682ab5ef8ad2e852f3d8b18e20a0cc0dc00ce16af7442c42531b5bdf682b7710ad97dd74f450bb3a3f7215de8c8f194ad496bf28f5d95284b7dbe0e773c1431836d74bee1e21696ca43a515d175b14c576afb6314036c39aa5322c74076bdaac40a48ac40ae4976955925d3911172692d647f2affa70ed85464677576340f592f26c47bd1a02247a7e12e4675a41ddbbcc3881050e13c377dd50173e84931d0c9c6e332cd6c42eeb686fb01ae492e6b8edceb4e3ecdb3486fb4a8539abd8d5d3a56a38d66b729598639ca6163da304567529a356d9246c948aa48638fe881ed7814135fbc17980168a1fbfdf5f84f1d3c3a60b4dfb6440e3cd00e685db00ab3bae105f6696ee43049003ed0800c3d3c10a2125ecfc58ec4b3697745b895e7fb7382fbb23bd52935bc27638c9c549ba40953a7566d09b01d09ec3eb666aad934a2258f40bc17afb3bd5ca47b2bec8af32d7c8b257ce45c789a965530c79d4acdcded6ac87b2d5dc5526e1d5ada7533491a45615844d60f707a5e5f2946e292576d65383ccd1e0d1c14f4f229f36e6ed7f0c4838a022078b9094ea959108b28d24c1dd45c584ddc2a3fcfe6e9bbc6610f977fa4212875bb0b173220c357e10bb5436cf25aef2c2ec9a6a068055e16e256d47d5ca079f94c42aada25b8da83c333772924610470369e7f15743d90c6c191c503bc8466c536f732b6e2b3d71f367b2ff58d8cd0924f19cda00c121c021f5ab9add0f7a2b8a29d96bc58cfc405a984de4a563888984574e801d0bfd4a2a5f35ae35248df4d49af83a810167eced13432ae08251c7505ba410e50aa4e89803e7ed1e042403649c84d063bac08896af11f1b741c97a7924c4458cce4f241897b365dafc228d9ede3bc784aa20ad627ccab24e0b7f6cd9ebe309f244477dc1013b23850544692671af224d5fc52e785849607158960ba0369640252c8aa33e04459129b132f6f6087389b1c073ca1138f8ba5e5b18631afb1af1422ce7b888bc30dc166a71e0a45d0aeeff8631940929de5b5c5ef0441fdcf02b3259588f27ae1d39e10bc58679980223cf77f3c1a17b310e17f883f61baccdeb25ca21cc1fc9ed0528114bccf7ce5ce1a6240ecfa465fca54e50e5868b239cd962df154cbdbaf8c5fd72993880ed60260f13ee98c4942262073ab411b258b1090206bc82014b3a74abbd1de53ee3690032e44e6239c02c39a934f339806a1752148a3769072a48700b924b9d580fe06ad08f0cab91f724b40c040d681504eafda504163cf24dee9d9b8e785f01964ccf285e21704b6901c59eed193f8bf355ac13fcc7aae2a42d18bc46e6ba2d6f57a518039edb102c0394c0c4e41a289fadbaa4c451b9ca80e025c02459e1af08f8baa14f85f1803b2f55ca61dd72f2af303d93dac6349d43d42b5f54aafd0e5555d4ba2e68c318082403f17a3261065aae933dca12cc2c9c4398f0602e0cee7db3304c925cd31d28adb88dbf839f1e8d7ad08c746bce21cb41ec7e7320b5d38009684502c158ee54e61676292079b3cf91d5e6445dd7864dd144ad043a07dd1f72777be23b6190c9eeadf8957463377b93c4369dae2da0d71500d5b38cd84dc7af1f765c7600f971693da81bb41769140220cd0578efdc3341e04f4d0ea3f01d40316b26c4e034beb824561c2c3cab7d6ca6dae102e6298d91687737d66ac7920d343a58fa7b7d635b00334ba59b9555f41c91ecfb26845aac617e668d4a2f7e664a581ee885b9521b1797da7cf95fc4758ec5813c3cc3cb80cf88d755a7ce8af4eb4411e8e1151054eac4002421f22a6637a108739704b8759c70c95553f8908a73f0f010da3d1f96411947720a860ad3e1b83f78f5f27b47bb3266cfe99ee8489710287a4460cc4067f73d0d9a974196274b2dd10759fdab6db0fa0f7142b21cd7af713432a662ea669e3cdee952694d998a68e84e46384752251bf0d25dc8ef9003ebd13a5dc577456147e035a3a8cb70e79e62e610e2bd34024b75ef95464fa605d48903ca8dce9d0bd830611857a171e2a306e412fbd6fc865c32d57dc591ecf1e40f5a2dd1a0b2e8877935cae473ce21c762a14c18c0a55957c15e85b9f4e5c67bb9fff564368916b0ea25144fe1fe7fe6f8825cb45842db994ef1eec09b8067bead380efbfed1551ef7fe4dc3f798820a06ea812f65382416eb6e2de2bd74601a0cd450d400f5a6c18b77828871a650dc4fdf888e441ea8384c3958d61ac207605e18d03d621bbc7ccb6c124a4dcd24f1c520dc34347becb5b6add979c419a85204160fe224b1946a1f80da1e3e33e62287ef5f052410db89119a02943ab6008d79f91587774378fe75c409d99a995b8d2de7a1da6ff167a1f6dd2890f11069464ef2c0fd4197811c11d07941472c3c77c3e5d9be3262a85edafb70b874c96e5fd4d0b219ece0023b8faac8cd673e435ca554c43df41f2b3a0d76221ab09272404617a51fe66af9164da3318b0d0bbf1625f12ad6dea3d886e2b1cdbdba8c6875af7ce1fd502c576a97849006a7e74bab7942dac33d225110f8fa05b24fbddc1e9ae3569694ca2aff6b09c5d9d0d600247b722e8f70527ae297b0df12ca54cfa12b0c695a307756b36c5aab58af4e17ad04e8bbf270ee3966952679e8a0f0e205ca1930e39d9b99af4665c6783dcbf89f6c068bbd2f4ce5fb18ef5fd49bd91f58e48a09dc154291ea03ad522c24ff1fe8416885fd61281e17599fc46c2d322490f8ea4ebc279da2dec6df4b745adf43784201aa61a87577849c1a80a4593fc438c3218e68efb16915742e28336822d3ad6fe4908ea311a7c6be46789aba7547f0fe3ba7b6ceb3234eb0328d4a414392b1e928dfbce0c776485be1ac6b9800c41047def0161beb7a6edfe138345ca41e5be2e645545637b0644700cd30d94238ebe43b22d7323e60ba2dddb41e109139acd1a19d7b5c244665074c06a6210a49e9ced89682308db5a28e0090c032164e35d9f42bbdf2aca5e3964798474c3657c40016a28e92361714a8a601a8617ade7258535377ff57cda2fd7a4ca7c84bf6f1236a2a2d00ff625079a7eed8ff1f2c5ebf6e2c984b6c907f544c292a89ce355d419b02e5293a0b2650506b9ceb9e50cbb5a90a6a836401c20084ad24101e6a04861a8a06989201d64ca3abe398dc57f2c0b8d01b8160085101edf1304e27234f21eead0998a9ab36b27ef973fe4ef43070a7e53467fa8bbd8676c20fefc3ebdba29acb7afaca9f4021fac4662be82aba5f6a1d6c17d121e221808e17986bf87918410d358676aab68ca1fab3faa87f17ee1ebb6e4833c2d793ebed238baf01116cb0c5ba1bdca546611a9b9c57e296c243afefbd46efef9f6920099f00321eeee2e7974bad661d622eb5b17bf3a9b5c1961870c7733580b409f9537bdc2742eab6f94bd7c3e9411ac525ccc79088eb886964d2c66fac7d12a097e56d48dbae8287a238152150fc02d8b54766181a80053011a5cdd5a80f3d634590d86212c8722816fca5076512764fcd9fea764f631bcbe6987df2a24c9106f6a792f5e2f185be0aceb5129573455003825f5ac0b3042b02b625e3f075bad6331e02779edbff1e4883328f3fb1e0302d36e2839e744ad1f448423760704067326e31c0c56aaf889b4a790f876c89df7bc35d772ee3b738b89508b4923109cae28e439f16c341977538fe8e7aa123e7db9f0ed9857a59d39ddbc1c55b8bdf67ed2da28aea54a39d67eee15220d42a2f9e090806bbae675fcfd86afc96a75b0ccc35acb5a951f25454803fc3dee9d1c2678b774c71ac4582344de949b66d0d866d736cabe714357b31c370c7d6ab683ba6e5db0a735c72629dad4542e194b8643429e7c58369142e5177a0b6a8bba87548932565896ad91596d5cf9a5763c8973e0a06329b319333bf829b53766767f3c84ac2d589f6ef45cdaa08ab787a047690e748f80dd4d90a091cc1c817ae2efe0673070004e5972587ce3202c098a529b49e5a82be58baf8de3665fce41535fb19eb676fa65aad874dfd3d1deffab8adc147f6e4a9fbcdb2610296d636af0716b4dc55141b70934274ae7671320b7e8cc1b6e0b97dd79a429f3713a93057ac85975f1744239793a8a2b006f366096420c42cfc127124943f6d30e2059b86ae0b85eec31b224659e3932bc9d325370808f364bdb0ae372176e45f23abec3926ca29429addf57232457edf3085101aaab134451208ec78549358cef741805855b55818b01d109f505bde45d5681090cb983398154efd18b6d00deafb5050b8352096f0e373f5f0466ca0d6dd07324a3ac22260692b016aac461562acc5a35f88821a3a9f18f8bb5f47feb0e3ec3dbb7beb2b09692000f908571315d6409301408a3ae063626b27096abc0605022dca29a98188ab0101b62714d51728d131d6e7ea99bd33d2e6ecce8f9e6bc6b9c9e76bb9e03b7ffbe95bd841b40f789b2afadc8ca7de7f8e58230fe8ba898a5caa5b09a2462fd432dfc80dcf386efad54297f775c73497989e21273874fb919f69954cb6efd3160db5a4e14710d0ca6b64884f103071bffdfd4c053d077ffc501d04f94a4adcfa2dc64d5dd86cf5188f3f58b38e860b60bc17b42d4748271512356e662d88e02472e48f42c88c5dee6ea8851aabb3da8b371d7c61eafcf5216173e08e0e9b7da0715b85e071d184099835b8d6334f6174194557212cc9b41f63c9f084f4e6dbc86a66255551cf372bfb59d1e7e63182e812fa25edb1cc29e03f2b8fc41c6a7893d68997bdebb8ad96270006ee10455b0f3436784f3bb786e91940d0a3b4116fb130ead4e60883efba79afe26d930ce63ccf06268759e8167d67ba0809d279db236d2aaf9aeaf3801a9d6d36e6ceb022f0f42b216106a73590571a26b6dd0e36193c66062dd3f9e4ee4c0e455dfc2463423e56a971bd77fb8286f44f2cbd522d3c926f34806a92bc30f5c694bb53d78969ed571796d31a42b00526443efbef95e5e7692df2434b744a4c6e0f994540cc38f849a01cadfe600cd367d406aa1ccd492a17d0557a6022c68656a3238d2fe6660abe0667f5969a5b2cd9876f6e3af269453a9a216b59098af8fb66c7e17de01156f52e7fe56656135236ebd83d410bd1aa1dd428a0379b9fa48870089a22e4642b0f58c806f7e502aa9cb70e4f944c48f526a7db118de24a9228ce09055eca737a079b3aac0b8c912728700a377419bf1b9114174377c08a1f0ea768e5406e6f85a1a7ac045170e0e5f30e5174d540340343bfe6549da9b1de6d204760d64fceb65cfabdf300089c25d10fb8e6d6827b78702de80d12974b28c2f035cbb86724eab0e5faa16f34f78c09db12a560afe1ab56f82c97c2a10620b3c4302aa96314e56205a16a503912bc07b08c0410d036ae1823766f914d5258b905f4c5d2667025e315ae7badc95b0e0af86bfffb1dc3bd09fa2b711407288ff99679b628e025680e327b3daec8e2365c7a9a1db1ad99b6cb9654a29a51452048e046805a3546655d534c3de351a8d46a4083f8389f0310044f86f34d2ebb11efd75751c45f890ad5392cc728df697fbd10617fec25d4b5595fbd425a189fad81033375b56b65cb20c96aa6afa77966559abaaaacabc592db07cbb3bdf7727e6efa2fced0e7572b2c9d4ddbddbdd422a2c410ce1eeeef6fc00f1bccf47e90ec1b5767bb7aebb5bf58aec372f0fd42c09d5165a6207e3165088dd42c822b9d66d89122bbeb775d69eba26ccf07a7e6f81e645684bb0ed82f03fc2ad092fb1362516138eeffdc797af8c5531c2e5751e87f4aab86c3a8fe3f29942463faa427a27ef5ef71e7b0ccb9877f5e6fdf5d817e1974e9e1296c1017ef6f0b32fb2234769a9da2227765ceceee3d36c4daa7c56b15f86add1d84fa486254a94f88f3e5388f54a52e024fa5bef72d278a63f3b0159ae9f74a2e1997e78aa8164e422619b69b98619b75cffe804c372fdd789c872edeeeeee9c4fc7f5306d6022aa0c6292ae934e893236409512758998a4f74556a3c42459efb4043e138e46e0a6c48a48e0fb86e43d8cfe30ea7bebd4dd90df448915f5fd9974c3db9458fe4df8b7c6b7261cf5fb33288b4ea3fbebdbee1bdddef5767768c16ef6dd6759fe6feb76ef7c1693d62e2b98fb73ef2330253a475402632c337da1c0b0cc9be7cddbccacfff69fc5fc626dccecdb0b3357c92fb250ac5e666bbb128caddcaba35488b28da689c996f578eb5a88cf6aab99adb775afdf77fd70ebeec7fd0c2f2260586fd15a6de0cfde5782a601fc2599f9b9eccb15d38229046e95dd5caac87ce6ef24347d4ea22b1601c62db7abbd98d2e6692f5053462d6bab6b6666fa366feeea0063765fef1680407723009507d6f3dddeb59e2b33cca71b84ed4bbe3f4cf5cd3dc1dfdcfd5503cbbcd97c6fde6d539f80e5ae9bfadf6b5f7ecfe6b281af4f7b39bdb7bb4b9858f1868c4cc43a79cb57c8d7eceeef410bee3e6566e68cad2eb7aebbf58a6929bbf22ba25b582e9ffa2f97eaaabe0179cf5fddddad5782fccacc0cbd4dcd038c88c88a260b37f4584c2a4d887901da725089c94e43c34567f73c42cc6f39349349d3dcb777df53e7df8f25e499fc4e8bd0663f9b08ddab4ac7e1e999a5983c2292ec74e5fc7eccdff391786e8bb97b66b7a7ff7bcc9ffbf3cdc37c9f4f5f21f366bbdf77fcd0d7c6fa0e765bcfd1c07ab954ed2db931cd154292e8cfa7ae14b92debfbbbfcb63ead6c2b9416ea9ab2526e494a3175b31a269622fb1af6d5be75775ff0bdaacf90d569d1b22ccbb2ac64df3a6deb4c913f1e513a80136a34a1b4ba104693ae5b0a773d493858b163417c9bb69cbe934532e2aadb4bbebea40e20af6ab25a78d34bc90449107062d2b097164ab975a5a858938cf8b5be1d97530b5ad1c95338051b1233ad54529beb3ae518f1028df0017bafdf7b4f97655cf82117ad53e2402b49d0bb6c0421c5516a10d85f078135df3a2bb33b3333b78edfb97d747d938c8c5e4f3ba2bfabbbdb9f767777f7e86a982d47727fec5d0f1d1c7ccb7c239f58b59c3e8c02cb16bae7850905c35e140b2e46646636e45623347e42cccccccc2c052680175ce0dddd006ca70fc2020080c8fcf0618ae961d3bfbbbbbb251e3b74682f2ea40c1b5dd07adebc2f9999c9b9ec9664a03e2766f5d9ee56acf56d50f60fc29f381c591145d377deb85bf0cde5245c6cf61433275bcd7910fec45b211a4cd27e2fd908d9ed634d1cd33dbc83fb30af64f1803b2e1d230d7bc95c482497ec05d3463aae1d9087557a30dea363d8b43ef447fe70e1b7de8fc8bfddcdcc9c9fca3c42a3afb80bda8dbee22e70172491840b2f08809b494169818ece8bc1ecb9ccddbda7ced388e969e40cb498bd7935f79999333377593b7959af2ebabb1fb7676766fe6b3ebdc7105a9c4672f9bcb965ed8626dc1a77cdce4cde58c897d0f4210f545f6aba6a88c6d0e9abaaaaff0781413b77f7013c5575a1273350653de154d5859e0800aafc882d2ed0f6ad177c37480917b04e55350b808ffa5c995bea73e5b9ee69fb7e9f5b9dbb7be6513ea5ed3f77a8a905d121a4b98a2cf0d80180120f9211055292817996bbbb5baf476ff120fc899bfc083fc2dd654aba6b5200a83ee1d1791678ed604147104df5c5e094f9115bdcfda95cdc3d06dafeb3dc3d00990561b6bbdb5b5c784100dcccf7153fa2b73801b2dee241f8137f0d43d65bb4fdf7fa84e415cd61a0ed5b906116c7124310fec4850c09c29f780c3441f8135f45fd212423fa9a34340a40612a133b5555ed2b9daaea151ffc4c9daaaaf77098d8b9bb5ba5bea2a82b5599886790e001af6b68a403b3dcddfd598c8594f90b5e34cddd1f1617d390bf40dbb748d09d559d41ff979934f70e6a991b81c191ea8ecba1fb683e966e4da7fedc39fae7dae0bbbb9ee3a6e7eeffdc63323742dbf757bd978457af4d595f7128dafefbbea2ed43ed878f95f901244b92aa23a1edbb0cc9883effea966ffd3c10d6fe2c78c195f60ced8e8a75da9f052d22b9d29ea1dd51b53feb11c995f60ced4efbf38e48aeb467488a1429dd11c995f6489122255752a41091c2c344989999f905b37eaddef2a609dcbc69a271de343145fdeeefacc9d8f9f0b12630ee779f3a27d19bc0b8affa4c9ac0a89b0ccb1921c2297012f795ec26430ae167526439a6793afa15ebd7edfdbaad08581b127f18bd9b551ef93d0c4c552a9f2c62678a259a7789abca0228ae29c62e3b2df9254d94e81c5149329189bd21d99a38918133857435447d22bc4d9458718614b2af448614e29fa4de8a2cb7ff747434ceaa51e212e6f76f43d2bfde84a36e5d6f4aaca8bf35bc5ca811f7b3d642c5a3a50727b1d3df1c7f8e3f9f88202b92aa6281256c5d7efd16bef7deea4c99a2a222678a1fe8d9d0fb453b557da142db6ff7d40db63e2b32730c77530a497fde9e73371baccff22d3565fe6e26ad4dc1da9f052fd8a92cedcf82d6100375aafd596f8718a8fdf990f7cfeaf0eecfb22ba1ed43855592d009c29f68faed9c5b3744ca9128c2999b05e647708ea6ddcf4fc07a8bb31ba1e9af9f786b5d2a302b31adac959819b49bdead106a9ac9c4710b4897023bc5ce4c3fc57e45d2ffb6df53ddeff5eede3285b8baeab92b6fa60e4dcc9d6841a86926d33fc75dd7b575a3cc12e163a3b7a3ef78d58cbebbf4d4b910a163502f0d1b775128148ac976a62261074b48c5b4e2054fcc1fc4b4d2c595f87d042844fe640309393f986207040a858a4c4c241a483964bfd3d1ccb1f59875ea1eff86a47f63462bfa7b6168d6fb2f927e8e48dc1f66deb8f6326fab3fd46b6181999f0f98bd75f5d248839999190a0931afeeee32f3080d1d347474b21ef4c0c579f0de7befbdf7b433ce78efedd8c10e98b9c43ae01d661df00e33f31c3dac58610e12c4cc1c9bc128663318c5cccccc032883a70c1e1e18c82083996318638cc7cc34cccc3960666666048811244650100d61f084c1f3e6e0490010d07bcf8607c653bd07c653bdf7de636607f0179c62fe8253ccccccfc001ce08002ef79f1def326e92b17bdddde7b1c785d3cd47b5d3cd47befbdf73c70831b3033175c30f37b2f043f3fef3d661e016fc1cccccc3d6801a405d07bef3173097c7c54b5cb956a6e66666234a30b726c1393e219d5181eb6196d3d563ca37f69313dd0a4c5f044ed91250bad034294256af792228ae159a9f67677f7c012f5777777777555df7b3f6021f4de7b2ab8e28a399879055964b130637f755a7c6c631e5d905b9cd177a6982f29b6196df0da5e76a049b3366b731b686f3d923e93303d917228ea8df9bd97f37adeeabd9eb77aefbdf71e12558010e958b1b262b552a2063d35e8e98142831d1aec30330c7806fc8c2555c54f153f3f4b5041c5141e1e26a620626666e69dcca1d0a4286561667e8299a3c8c2ccccccef3d2a8fcae3798fcae379efbdf79eeae70c25b4a18433548acca1d0ba189ece09961d2982924c36eaebe6a42345509ed0ba97d49122285b0365676b321e299ab2a723453b4e68478a521b4fe4d723455098a49f242831a12c97f14851ce127292848335c71cf148d1947dd98950d6e625158f14e9f0e3c78f1f3f7eca8f1f3f7efcf8f1d302458a382296376879c61b6fc4544de145ec8010457e534cd514542206021080e00321f00027021188c00324c8783a7046ec1a4b0f3df46e0f1d288167e18066021378b70938806403589224493670020dbc090528408106946460c992de5d920126cc18601aee871f7ec0800a7e2e80050b1040783710170822b3c00b21841016604105882082880aa07a7850a98a28a2081e8ca0404e4e0e05903882e9137da24f8e6812ab1d945042891da0e870b29409654299d0417726b0354e38e1c404a0c8842400052a5476b7a948408a6c77155523b03d8ea03aa5477bb427027ac50a02262cb0c002023e40390c0d69a15a78b71639fc64fc002eb8e0e2015de0e085175ee0f045e60030c000c301616437a8182a868a71838e81b2810c32c8b0c18c1e232a151a68a061248dd780f7b65e638d351a300406c020431b6db4c10022a8708888dc70c30d9c22f4443562d75892a049d0244455024f1121a137de78a30813821690254b13b409da8405a81314a0419306071c7028400a420958ad6207b568d192802da9c85c0313a1512a2815940a35681578681012522ba815d40a34681ca81bee550e9543e5b8d13910f0e4c913042491118912250a11293b91d986839875ca9429364c04d564c912bb6ea289266a9c98e189279e98818a2524c32abe2d8a28a290610aa003fcdb6280a0e550e4e1e13940154f27be6700b6c9864a5980ac3a277aa819ccc0fdbdf79e77cfc00035c80ad0313c56586145017a8868de64832cb5d472198788ada593e85bd7ee4cf648d194e5321e29da591b908c1c29cad91a2731230d2955c791222acb65ec5eb0c856478a7486902660cd71a42867b98c3134483640f7c642aa77a770052c5be82c95149aee76ef6e5dc6759b6868382e2e2b519a7c477b71b7eeb9090d0bd1aab4dca6905d4b85da4d3782c099abbd5768651ff5c9cc4c7d3433b32ccbb22ccbb22ccbb22ccbb22ccb96d3cc647ecff2b34b251ecca6ccb4b2edb729dc3071df93a0e51029a60f989022c298aa1f58217657eaea611b88e299bd76d8c6c7ef0469175044c95c29209267ae283499f7f11d44f938290ecca98ae9634e3a10c7b4614086879837bd691ba2abb004144ecca6437f690d2da534e4b593ca9b648394c30b89590687ee60bedf49bca84c49bd6b3130db3565b9fd9cdc19601e89c7c99d2166db9f1d43ec38919e4f49b2587a25c9ec20f33f9e07191f2fb30da1443e4bfca470621ec82b49071fdfa70472fa719239a9a24adfa90e0af5c3a6ee4d73a0b1462abd603b624e890377f286276f1606060606e604f34576c72963e974c518188c876a3ab21da4981f682eff02e4f263e8b5edcf4545ebf68724b383e97f3c0f3e5ee647e624a37fedfc38c9e8a6c385e34bd01668b9fdd2b6fe86d641201fa722a7e49928045dc1491c9f1ddf65d08eeff149c281c7c37c91cde44adfe3d4c9951e2b6510c53689d39968384ed350714bdb0585e651b7ee611c5ffa0e123141cb35901047d40e6289db05110ada9afd59a0d8ed1971f7275bd20d1d950c115537a8a574aa627ab8621bd30687a0b0dc76576a28ee432c5bd35da9236ccd330a08cb45ceec870181ac40a14d232ed0fe3cb13f5af2b18281d1928f9363d1d7f176a2bef6e2599aa4253a511c517f743d9da86f3d28530e10f30b9034c055193ab3df713630c2321489b87028872cdb40141c82ab8b99d94706a510f7bb16225c9dca88fb6903817266dfc7ca87161f44317f39a1758be251551e2a475ca92ba5ba3c3d88a90bb5114b4d55f5f983042db73e563cb384d65da9219737babd52319b4f77a5ae94ea855a8742d4ef2e1d572dd7c672daed0f0751c1ec0e5e60affd746f6c106128062d9f5abb4aacf88888ab1d938d8ee56902fa850e51cd6ffd592ef50b1d92df1ff304f48096d3b762d4ef9343d751e6a715f1e16dcd3226f57e4d4683dad614d156fa1a6ef114d3846dfd460f24768b1a6dab636daf891af2d04e7099870378666b52c804830ed9ef8d4b9b187466b36f333492c6bc7d6fa934f0e6430a925b207866dfface05a6206b32b70a5d27926d5687537f5c74a6db2bf6adac37625a96f942ccdfb2665152486e3f6b78f5a7bc79af9916b53545966329644d0e415cc6e7a72b9aa1b96845b6c687e5f6f9bb8e39648d10c9ed03b1dcbeea9896dbe75688ac2140ec72b5c3e28c3e49376cc4b25552ec78a52bedef9ce52a240d9943deef736bd4ef3acabeadbbae10bb7f4432d2cfd50424a343abdfb5a96b51af67513d8b7ad7f55288b53bcb735a2ab645f10c3f865a1d1e155a4ecbf1d14dd550d5ceb09fd3a8df32b447686bd4d81a151c69a34239b351528592885b44e42a686a45e3183bbea28becd1ad73c522758bac79bffe9d29350717151aea77276f326f34629acaecc22a64a91054212cee70eb4c2ae46e6d1dd43454484785745448270aa5106bb44168f5239134cb47574ba1f163a9a9bb669c7f92541fd391f9a9a374eac4ab1313f10cead4aae3c3d6f412caedef13206ba0c4fd4e22b9e649c56d26b4c4fd8b0aade315764a9cd4f87d0d8dc72a6f7208719fa79036a3dfe79596ce6139461b2f7cd9ba17cd9242d4094a3487c241b438a4e84db01016679f89f2263dba50f47f2423fe23e6070c07eb58a590156a95a2d941110e626f9d6951ac4142c012b7889cd9bfe06a4fcfb2a15d415b73c6d6b42a669af32a2eafb6468be2db3407da43c597134b2ab84494a07ba468cad66c6a6bf44b5bc3249829a8d46c9ce82844440200042008b3160000200c0c090443611866619cfa0114000d68823a5c503297872281481889411c8431108930140420409821461187144a3a000e1da0bd170baa2417eb875f0ffa2883360c80c4d20564f648023167a8d75285371ae689228b7d2b5b7b8c13acd214d1bd3fa9804d7f3e1b5dc409654bf38ec610379ce2b1ca1a8f08bc669178536e54aeec8e9fc7584a8f59cf2881ae3447620d3f1ee65e636c0c31d31a7f896434c00087d05a6de807e4bcadc2b1e2e1e95890a3e93019c14e3b951b2f30b62970e5fb2b7e8ef44a352848fd9df42ebb8ceae3c6cbf8ac7d9c064ff99f3380bf830263f8e3eb76fd622e5e182e05328fa6db4ac6a34ded5d59d0c04a59465abccf828f7b3af82ce47a09975da77ca29ac6165a826c44b9dce199121439fc9506dd4a4543c6d6afdc56caaa3747f0d60afe0223494d81b8632ca2f315af2709b56db6419bbe5bd0f71ad75677fdf068cc74d449934ccdc9feac8ea7ebf0c47cc953f82c0a4ec8812098687950b8b8edd1d6dc9417842c71c6d34b8d4a300d377fd15e76615ec71749c5d15d438030cebccd8ee9df8b2c043666cfbbe3c273ea90b458c54e3db799fe3ef411b9992a325b733a8eda40c7907d24a186b78b88c81e748df23d039c06460754393a2e95484b0ec62e5eac5b308ce8e54e437e080c10c68a2d0ce6be8a88b9d60deb23e8315085865e382b988a05b2a49aaebee1dacf1c9e0fa3173e7c8073e53d562a2a136fdb61d981b37fc315a5cdcedfd2a0065c00c1f8bafcee81c15bf8e5aff8b7526b226048891221b34da1981209600a4269475d900eea13eb00cc15958950af88eff01590992243c1a82b72f63fb80547b79f07c701a28b8dabb2e0523c8b6dcab62a36282d51a1ce963a90604be3e2ad2cff0baa796b47c3affdf335746de25e508691d306a83144555017622dd2fe3a580f6756be46eadd6f9572e3e0be6a2f95a244516d4a5b01f8f507f756d728fb70af1d4de76b80bd2a26ca63a917e76160dbda1f93d4750fc9b6354456336a0f8a2d538b3d4540a38bec57832f35a6bb18366467608b9e580e138b974bf5379477a3fdeaca2c2b75539f3b24bffab5190df2ba074cd90a025ab0867dff70cc88583283c3beb846ff2f88ef74238bb621e6d0829d0b15325fca09e2e7e93dc023bc952a2f7a7b253b9da7bc4422f4e062c148db4d89d7cfd88946952a9e8ac326723c068ff696b51f3cb8f8a97d247477e0e4cdadf720541ae000c0b8d814ff3dc7e72bb04ea39e998f86ea77ddf3d6d5bb10d260723877bd261138b3e6629b44c87386cffcbdbc0b946ee96f1bfbe8ce33494a1af2f72f8083cf099792f064fe42ec151be61f91a2508f259f3ac9d2b6de808cc1ec5e3d5b86d58d17da77ba80202d50a274fe04b157ec7ba4c61010721e1c38da71fe125f42eaf4eb7ed49ff35e5fbd7c76817433de15ffa0bbcf095b38f2090f1b2b4293625874f089d086c2898636056039b8783248f76dc9219eee3a615a456e5af16116726f9ae056043d889ce67e9d8b3d4242a372fa61a2e47c432f195d52a4a490c279993b579c928d432ba6fd851f54d4d7104a654aa57351f3a64efc5bb6cb026aed5c7efa37b538c042a7a6a39ba52636e978d37451b81be6ff307d7e1e123357cf7ee9545a8f6ada610e17397c18408a2895e5c0b3967722241ff514e44aeb33b61717b6cac12956eeca45ae032644230cc7d02b50210957db7471c74b7ed0ae9a6b2626d921ab4522fcb54a6aa825e0c1e8b875edb101db2b8ce5762467dbceccad88ebe56f21ea716e2f6cf7a8e17bbc7153bc6387e7004fdef62aaa3deeb485dc812aba34bbb071286e148139e8adcca051019cd2d15d5c91589e0e8760b42228af30009bcb13b835b3a0cee1b31224052b313ea9ed021b612684c7e9c9e7a8d6e20e9bb663ba6c48afbb7bb7bf1caf8e285ef502b847b099d7c8e43849c0cfa9a4d7c4f4247c3581155f3be1765c9bf561112af989a8e2899d57e7d7e67d63f177db9765b2e816a44b85aad9c25a4a60454b7ea5127f67c945c0af2bd62dabe63c6fa917103238c4c78152199138ef021715d4b372632f6ea4a6739140349ea703292212c22f6fcaa2e6496e9ee24d4fa797a20c5b859d4b76b77a7119cdec48a07d2ac837c0681717d5e8a402a07b5b599fd98beaa1e91a190cb5186b1a873a6bd930f297eefb7e0af99c9c6b34c9686c7c82c61360eca65d08e6fbc45ab671f92b4437193426183bc0314a9ba01f928a4e9d993a477362da37d2fb56d107f2921781018fed39c0c065e9942f29ffd2eee5af03f65d74c07d7b8c5c8c72ebd0bd61e60a8a7ac9d86fed262112262360322858325db75f475d8a4ab96476b3de106533d8e32f831d78f406ef027b306a154cf2a504edb08bca9c89975f3a7c3ca20462c4e8f19e9cbba56d08606206e553f0265af634011786cfb8499e82bce34b03aef57b27a54d52b15c709fbc44d3fb81b51c3502851e155de118fca5781dd1073c69f080889a8d47e44b3f41eac9a375dc467544f75dcc4b416d27f0f3c6b725dd95b75f2df78626beccc3e8a51b9c1b1b6dedd00a578e194d14479a27dc5cc2020313cf842a44e2900931576de59123659360bf559123c292f5e5f7103694eaa5e8de151d3683747f63376f6f1d91fa3b718a4554c7a6647c6b671868b63954d763b1716928ef4676affa57b7b4d4eb4d0ca3d8d7054c0e512283fb58d4dcad25e48fb1d42c064ed04e1f8c52a0e5ef4ba46bf4044504c36e7687e06cc2c0f82e5a99142a2a9526aceaa470dcb8def0039ed2364d20b862ab8cddc80bd4528ba2843c02fe59112d2882eb754d9a31874a433ae824c655bd9b8ca55cf636cafd0a0d3247eeb44377ffe649f36b751b1722f3147bf10bb2dba8d54ee038d451aa21088bd3fa9ec26bfa64ddaa80c7d0c947c72483dff14c0c9844c837d355c441ad2fc79d3f2a551887e2bb0fb7eaca858199731a7196c9efbfe939d9ff7bacee1e4080d9b35a8f2debbbfaba588e2cce10bd9d06a7911026ff8083a1059d2395e20e4d4881fec6c00931032414b2769659010857f42e61a8b20f6d119a0925372c572f679fd972cb8e8edc9821ca38014e135db43f4312ad183b699a2897aa0516e01c9cc55c2b312fcd7256ce7b9d42ecac0c0e767a6a033489d9beaa900a34477358a6346627814a5994cdd309bc66fbf658315283d28931751ac95b4f813675dd89cb6657cd092087eb888d5e3a48ebda6e4368a71a67378ba07159ea48c703a6421a9ae17c9d355ccd5acffaae0a3b6bd25b0d7b688bcd866cd2884fceb4a3c7a33ab7bda34f5b316071b36847784fcdb2156e942fa3dbd75c2e3a542b0286850ec4d49bbfb25ee944297d9029d3b71887a848148b9b68493bb7889229d24b5291a3eb7b41853b652b51236838831886f162a54cc54a2139e1151ca25830ce911461f2041f8590f381eeee602fb8ead9dcc9eaf7b88c7125a11723844adb24ca69c777d4dd4ef45d16c5ed3a891f308a0b90fc8423d556be54e0f10c6e37c8bed816685d8afdcd24718b337952b602778ec4478f2328d097af2e522a5c1e31b392f164a46f514f7b40a0288cc89ecabe7415622b989be88e24530629b6b65a29e265243f8e933c551d47e2567ad09e54cf6f312000a815023339d4c6ba46e4a753a657a3097263af9d1ec19cab971f937faca84362fc98125513f50dffa641ddf489eb349f26b68b32461a2ea1448e02bcd87198c5693906ed458c15d2d0a51f401e956811faf29e14ce63b62b6a95d279f4129c9dc8290a214208c84d054551f0ec1220923f6c982140b2e4ee5e3ad3a11249a8d2fddd18cde5e88bf1095025a72160e4faf4abcb07665277912822b6b8c13a91acddc93e79cb2479666131263392a1421fe054d38004d3cebb2cc8f0088d2d955e48662f190bbb581b64ef14677c68f92f556626dfc24088f6c98b71f12e6394f883c64dc210c15ad9f3d2b5813171d64828cbecf5eb2c9ebb4646c64177614842bba8a043f3f50e90a327f094f9c2060c8112656eeea54ba59821761b40122a2362d87fc905999e211d1bc064119a6d41d1599ebaa60c78318cbf685d1a8dd070c5c584a6c344ec4238a1806be31ffee90194c795a498b59b6389114c48871128a94c6f85171bed7b9f5907c767cb1a42f795bc7a8fd7c58dc94462e89252a1d595a1e8be71828ecde75d5299ef2c067c6379fe3a3074379d4b831aeda50a1f1bfd5adca7d1c626d5327c893f6c1c83c70d1ef7eee2130f93ba69f4d699b28a6b8d17a8e92908414dc31a2598feaf9f69ec3c6f542917fc5070d64f5c236366d16f6920f13a54d0b1fde6e38ee4739c04c30fab42750340cc8806b1befa348b5a76f13549e8e907f820129a245fde48d681d9f68f10891d209dd2a90264db74fa349421075fc13239231e83558406c2af22c7e62bcad7049cc52c5a23107ea81493b8735cc10fdfe6d3ae44a92e9d113872dfbd45d2c9dcb6cf10890d60baeabf3d27ae89290b4c40100a0f6110d9e7c0e0d78cb78cc1714c0cef9a434480f61cd574629fc53ad69d5a8174b10d539b3732d71d49377a5ec56e2c7cd1da286d3f528b0ab147b74b256a386edb5117f40f76f09f89c52d9bb29b69ab9bf7ba72ea5346a2b80a4a9cc8b2f028ee9b799206c042cfda960ea21932302a54cfbcec601889fd007c46903dc0160e3c64d9f85c47cce964022ab86429ea97d42f6d9169336c2856d893ce1414e4fcf1d32a31bff7a4a4b7c34c03c4e460754e26642c4fff7822a670c725c3320d0e654a9541e0f6cd503e1cc781753b28f8f567991d0707ef39fa8645fc3860a83043877e232b83ce128c5875e0c5c28de2f33f73e1479703b9c812f5c9cbdbe38c0bd1c14d9d76b942189ac6370e1909b853d9a9e14312070e9d9c1c9959dceb79c67952f90b818dff3e8f53c1ad2550507d1e754932e4253d9d2bd8b7cc82ac06a111a405e04ae29aad9782825344dc51e6a5f6c300de978e4d27b7961501bb6132c89b99bd98d0e2d6d1c6b6dd497ea191e6a4b5e8bc67ccc83d32034a94dedc96304b3102492cbdbb95314b6406965089b1baa7b1761a7a7f5c49561a94e6844e582967dcca3f22886c88827f5096e87f5a49c4aedcc5316279845eacc6e5b1f9b1ec528f19e3d16924f888c5aaee637c308bed8d516b934c66ac5c508f3d446cb8d3e447b33bc2fc5cccfc1bef48f6b44f490c585929c8e78a4718f0316b205b476ef37021b1284aaf03d517baa1575968c5424cf4a8f9fc819124f7f380b020d9b59498cdde8281876ea8e23bea18a30629e0b3ef24678b6c92936556a417c28ad79ead3ce4ff4afa1910d1bd12aa100ee38ab678115d589f69894baa10402d17039318d5b0dda2be7270c6d561ff79124301ce36011191e7e1c80c4536563154b3873080c49530010c22ff351180bfc4ab1332a5429af082a877a0cbe98a15cd28db5f06ba3280a478dae72bd135e225805ff35bae773382458a55958c46e6a0c426738278bb20d6551d6336fd5ced34e74b92a2f4c67b13a0730e35da3981f5ac045b3581b0c02ad0db8d555cd98bea065af1cdea75572dea0170e5ad828ad7de3115ee3d3c7a63b670f778d91f57e1bdbb0057bc2a28af806baf5a9403f03aea81567cb77add578ba65d54511c81564fd52826d0b5471545735543ab2fd50534cc466917277041922fa2f26b55c8d7b7614fd5f200f4b7a146d4c24ab59bcfdfbedf7fddcc2cdc6a1e0091fc87d05045b3cd09e0306ff7cdcaa7667c0370529285e57db98d5c87c6bc5b0d9e09f9df2515c14aae05964305ca3066bd8fc50bf5f1cb6e3c65e261142a93146f6306cc95805094f03f57b9a99255a8d124f0e5c3e6b9be3eb020faa945f1cec1d154433dda1ce85a0322e4d6c8ca58760fd77e88a1f7d7e4abf54fce04febba31c6e42ee45aac108790732165d390a6b15f2e640fe439f16d2c0cab3c98dc0774676812d04ad052c647192d83c90d44c2335352cf108860db48a111d434ae97000108fb7fc6a8c6c31a8d9d539ccf1201e72d51ad7a4deac8547e4bd6216c24d574a1b1cfa9a057002804c190bffedb76b926def999a4430c7fef16211d0fc1763533b7c541f0e1e54c37cf5e2e2f361b12eed0a722bbb8067a481328a4e798aea0f5eb7b4374ed1c61982cc9c12ed86238da7c7fd1949f754ecdd9108d8d7322dc4025d354d380c0a28b4e3221f3c1433fe5f404a769849006749a11348ceed2f04ea9092985ea6081478d4b9c0179092730281d869265ba44667e8739169eb92f706aa5f4cddc9767adde0e335fda1cf2534625505e927b0bb7e8c19ec0735be9fd90083dc261db25847df5d200b615b4b73b985832d604ae0785028e39f5e532846d2ba658d7ebebf6b83c33d13fe510303d9340e789b5007c28590e737c9e60cc3711f79be179e5fd4c5ae0a580f972444980a0a34f5539837c96a658806caa6c2342f0925c9da260305f129b662af367926fd41010371131c617da8448fa2532448d8140edc8ee410f3b3f76f5e086a2e9a7c514715567827fb28e0efcfb44f1ebbb17751525d3d81c1e69700c60a77a5f706ffcfd948acaedc0089ebd495ca324961cd55036e2b4597ae14f90b4059459f1cc5fb083042c09fbcd8296960109c56308622f4bdb3905284b8115b471488059a85c7204086333d074dfd46737a0a825212876025845ecbf4a60d82bf2d843391ac4c51b68a5eb669fb85416858d21832080330870fc806c5360651ac2a184c5e2f28c674b14f5d304a4df1cd12bbbc1d95c95fb68774450baa529d9e60d0cb8d7c39217014b5d6e819e8405c88d23c53c63e1a13e1f8563a3141a6b36eb7b5aff4ce74dcd7026cd4dc86163ccfe5e47e0d344755aa8f2a984d96fe5524f1114339da40b9e976f218cd5d87b0cabf016ccf371591b078d9130115878d91e55523f4cfd98256e2414d0439a5e1eaef0188bf8599e603551fc30bc588e97b08f154ce4305c3b88df9f0c19182f6957e3f6a89fd1a6bd3c4fc3b516c2319b1745282948b83179f16c6c4a2f8e98853d0f27a10f2e7444b9de510dd242ff1752f19566aba5b5fea460b363afc603354e2962e017b22c3badc7a3dd124379b286b0060cde7acede4e61134f2578d06ab7aa9167227b8649fce06591411f1b8082478967c0db5eab02cf5cf21c056f951556844e2643bffb2ed3b9b45315580e5da15eb64ca25dea9add7b24a1b540fd74e35c694ad9de910bd74f0e3641db71ba670143f7be36989ddb515b8785d6ccee296cdb6c0c508a9afbd4b07a7e5853d2b8f23251ce1913abcb48f316ed01a1a5707af0bd7bc9b0b4e31bd29f8e6e400b438a95d307786f84964ca8dd074e0f8de35f3fa8fd9d73f66ff4415f8e28ff9aead21c118864f5e0d7efad5ceabbfbc974b6c73d8f16a9bf7c7cfce133bd27247c0dea3dcabfc994d00c1d4e130c8c996f125d78b8cf4bf84eef04340d88b65713b8cad1331ddeb0beffcaf0958a2a8d432517f3e41287ac29eb3cc68199bacdbe79782c11f90c5afc3864b5f610fcb0017befcbf9f5b051a18ab5c6830f3768254ef5150cdf4ce4384436a85e64d52b8bfd46e2a8ac045d8bc3e51b64b69931479df1ee0892253555a21995c31a54a9597559f3c21befef5a0749bda5b0cc891e55cb17579320c01ec6f8f95dd74513e1c962e0c2c2d9d41e32ab7e434c4527704a9cb7cc20e08af6e78b6ab29a8ef61fea84f3220412c2baa590ffaa8a77137950deac4f1a7091569af87324b59be4512966c25777420dff11ad7f4e303f9eed5fca61b3fe87d5755c25ebd44ce8e0f8d4bfd1222e8c7ed7803377250c93be0bf1a07d013de74a307bd5daf71a61f5fd0ef9e8637dfd1835ee735afd98f4f41cb0ff3e2f214b5fc1b2f05a3ee07e838965d47f82d089cfe2d3daa82405682ac721be093e2d2580f12c2888ae6a68c50d7e56043ff06d742fd23460884d447ffc225269c27f270f7740ff340c89c0dc85e08813136af209db3d8c3f0d5ecdc1d6fb2b6bd945c9a3ebb9ffe3cee32baa09e47b339e81a31bb68f080b6a294ea82df586e4cc4ead81eb90c10a10232c76caa71764b7de211206190e89803b30d8a7495e903c00a76c06a3f310b3dcb37f6b93e4f5ee75d53247d1cea7f0165571e52130bb1ddb32de85d5352dcd8a4c7caabc138d50b597c69bf3be2ac518278fc2e2e4c2063b0cc7a6ed0e7b9890af54b726e8559633202b3ad1468fb4ccc7c7d4db86102da16edb8ae10c946b0a02e43aa28c5685bf4f4641d43a4463ce0029301b298ef51efe5e47f14de9c66f65961675670cdbc7aac634be6c1908cb52c9b477dcd0617ac42050a2589e846715852f2d8639803fe2b339ea7d9e199391aa04ba6bd044f5e2a8bbd1beda6a267e660b27dacc67a2e4ed84ae336539f703b2bf18989253555b0b7adb8fc3ec74ef16aaaa42db3730d4d1811f4de085e3f36b3cb8b9dbc8192e71f1566843fdc2624adc25f0913ce35da88314c30e9b953386f2b1d0431bb2b4aa22a5eaca24fd03339e1829ddad35ba43c2655901c9c8d0043e114f3c2e477faf4f7a6ac8289da91d5d6b227d24003566587196c82d3ec91861af02a3bcc701b8c668b35d08257d9e106dbe0145b343bc8edc35b3b2906eae3658aea659dfd491618205084a13c2362d26bc4fa45c69979206247c5aa011bdc605b6f7f50d4b3c4653f0a814319d61944c889247604e4c1444af81821db4cc6de081bc1a3182c98dc8807b68ef8eb8285965f454dc6f335f49735db27e0061cee06fd9942e74c1208c983c9bb412cb40fca757f69bcbf87d3ffc0ca30d53462b972adbaa1f504a558925e71b74f16fa607fb0fc0317b2c506564db00a26cc2296c9c49f037be4414f821e7c7b3b6882032f447ddb406c16721020690773fe0a40b34941252571134920f145bc488274222e3b11fe8141064bd17e96ae6e767d0899896b71afd840f7b07bf9c6f2b8657b87f48271af00b09e38d1f4d6fdeb124ce217941ab81c136ab9071d42b2a7d960a6496947b76092f754434936b9f214b34e845ed6c058e8112efca7fd5c235037e3722a3ccbe2de27eca516ac9baaaa800f9d7a1c2459e1f0c8ca351ce9248b612c513c08dea32d2d371c410a30d27891c52637faa99d4e7b5278a421d5a347ca32127f5a83a6859db8859d51395781ed233517308ed7eba18ce51bfb6ba6616e10e70acde5670e645585a507a17b43a8cbb92f577efa659439c5e225b83f9688c9b2af1fcace3e401840f15d7abb8920ee34dbeed5806aa3311ee0f87d50f62ec815622d553660b125de7a5db775062a6df48a7a45fef57ea0474d16c017dc51acc214a26154f7c3681f359388278a4fe59ad9803e0addd3ebb8bf4205fae2f076c26add06b2a985613e2579500282ee7a0921dd5d14f84185e24908389277275cc1cb436a303912acf882bf289388daad7a6769c82020ac3bd1d6d3a28bc0b7be084efe6b1a9d9643b716d2db6d24f10982abc81cb479e9032b6c5d61be8a0ad2dc9988ca7255be24f8b2c2aa7944595fd0f05f99caa52a56f19f6bdd1ef8d1558cb9b3ed2927469cc82b6770fad4988ca01494c339daf83ab30d0062c3ee9ae122ce4b3a8e963610d9b58f8066ddb3161896a54769b6d35cdd805b39a19095ef2d6b0736529d9c11c038e78c97610db3ef1111cdc227b1d42d77c567907ebc6c5f7c14c0afc23309b05f2a70966a7d430fdb8288052fbed6a3a2dc42f61d0346ba773b9cbd9923124c03936b37c169ca1c26513674ffded05ee6e4dc189d27f549f07d6b720b03750270b8f2308620c090093a6b7e248145688790568866664f326ccb4bb8343910b4e6e6101dca1a0fd63c2da4e82103cfb0b68ac3ba52d4bf013f78c174ced94cbf736c4cb38cbe09442b6eaf8633b3e80b2afea4390dd2d64f080fd1f63f768a06dcd7c7da2200ed05ebb5a70152103a0bc2236a6e0ae6aa156e78bdb1c906a0baf8691d820eff7a40d505854e60391cc0fa14fcaaf4acf5b8ca2e54c6fa601e01e2d1f3a9087d74f34cdf2fc3cfa0055dad28ba6aa13687fcb17d349675a09c0a56e5930ebe0b257c4ae8e65c4d07fc96208d8f1d84cdc0594103fa8bdfd8890fd6c766b801fa77d2ad221684f7db8b6e91c7c97134b781c9f28ee8814e46b88f942dd2b9ea8f12360b8589bb64ffcb831887b2ee9b684d0ec04dcdf065eaa22e1b775a7b1dc9e8cc9fb85997ef3023908e04be27d3244c14b496d244f43f38aba9c9c63c5b226c2c5d09091cee28ab7df44b91c55bdd1ebda572acbf63deb90215d94012bd8a889a6e67e2a8618818a7edb63c2bc859c52cc97ed4de41325800b944cf466ba198fc5d3d915a33d8529b555bb63ea9aec53b6782d4da26a5a54432a46696c38e1881984d1f940b27cd5ee40230200bd3e51faa397ee5ac641040dfa57a318bd35a913273a2123865ac93bf4b3dbb527d72d5e0ca21f140ccab1fe186e059cce11b13ff25e380f7f66f683e9067e456ee1bd1ec72666580b382c8dc98e1e9d4c73a1183ab0f84983fdf89ba6150c6b5dcaa62022389642b2180bc9ad0541e085772508f92507a341ce9ba0cd817ec047f4eda708b2863a42ca6078cd794f357298b28d124ed8d006645257a5e748d00783356e42da7ea335169a2238188600b9eb6cf37f64161afb92eea9c5c079d4fff803405374a97003a767fb4425410249a08b222246875bca9ba07ea8fa55885c3282fcba065a646166cbd9f08bc5e9d6d26031a9b6b14da394bf64d5c83bce2c42afe0f73a8071206c188dda662a31cab7bd11017c3bf2c61e1fe9c006ec05cc1e51fd92ee5eed0881432e7f60a2329c249c961f4da3853dccde7effb4bfb2c1e250cf17e7e84c62f88ec8f3246e2e7f737d8791800f9a3b0ba11ecea31edc2af41aed7ab45c2b0ce5157730428395171977b4df04ba081ebdc1f0cc94caf9a3720633089933a05e9d0f42ec3c4db919a6e8d817c709eed9e6fd1186162da17f937923c68ac030672e4f75d0900b275b37740e34af480506e33f69cdd86e3b0e12fdce42aa56fd00acb955822b71e0898a52983b09c1a925bae5c0df1b3592be23104c00c326b0fa0c03c8c1e4ffc7a69896d7ac652e68106628212902f114ed01fd054daeb5220e53a4325e40a8097357d28108640f881faaaf02fa54b9c409e3ce6603c4e677029899397dd2d057bc76e49012c7647223576ca0f0fb2dc31578c04c79d11c05d73f5150be7dbe9cef7d8bfca8c753bd5fb3e872a3df1b70a7f39fd0602161ffbe7f9c6e825991a8cc0419dc715e1c7af1f49a5113a3a788dae3394547860fb2b01b300ac7fd16ed5a6e734d7e10493393fb81981f07c6789746e4418d970d0a2b1a769184a4af973af9e0ffa001f10bf5cbfee17a631788e69df1a49d9487deb1c634de3f3f275359a81a70b3da9f7dd9db1779428583d033d8881d4ce5dd44a1131f21654c0eb3887f7caf473080c130d8fc649816fa5f3084384e74673aea3cbce65610918cc3e01c387c3d7d095c799eeff42f120d47f203ddabc9416d374061887fb5e5ee53de20e6581da41405226f1dcbf5e42550b588a5bbcbb32796beb0a3aa9e0902b662efbdc76f4bf3ceac121d06d4c20181652c269e5f198fd4e5424e34c98e859112880716ef54c55b22334d6a5da999b76a3b986904f976f56bd7e42259f59ab35110be676906aa5de3d57ba951fce140e8a81ad33081787aa53d9f374853fb9c6c514cfa5b95dfbf2ab9a4b476756f554891d1c0234ca524eed34b20d4cba0316a0584f624267ca69ec60ff25658824bec92fbe3fcff843d168b395b46cb159106060dc8a345e202ed850e3bf7c142a2ee1cf03088f4ce4395d29068631456e625f19348fc5d84ee136a633702a0e7000899b86634de6b35801c26d0b4a97e7a285c9290a9e0b8f156c85429ca077a19b78aa9dff3ef366c8d2d33caf5ae52306888facac242c5bf32d91dd15a36cf5f5ed3e8c571820ab5a0aeb430c32c0e9f1b96344998295b73f9431e9362b6062d571f375260a1a4a41093eb0c65357011a35065e4ed5509c433bd6fdf3fe773afb631e8cb52dcdf42bcac75553e51bb38ee4cf24c2b9d366bac08d38b3027f9ce2f1b887ca1a163559e42d31c62cca44aae5290bf14425ebc58599ddd609a5efe9140d10452b392bd5796ca5a563ac7fe33aa8adf122d717a2c5fb464dc57b8d5e15e2dc998cab1235bf9d84c9e77ee7add7102ae37feeaeb729ba97c05ef151d5d4191537b29aa55ffcb969ac0689b6fb44eb1165f54c9409ac993ac2407ada4acd8a81c063454bf15611e05ead2b53517e2c89d046a50e47f5c257ef7eaa675880305500126702b7c56c8a4094d4aaf992c5021c82393213161c47f18066c2bad24f82390a251fad4a95eea17163251297471f6c03b3d1c103a8f140e3f79fa90c624571a85f64397e186e4fc5cd8d7a9cf8a892cedbc3ce316e382e2d0803387f60078498c5f6c1ddbf78a4bf1b173ca77d0628415d9e688dca9bdc28061ad15535d0c4570f0722ec462c067d0cbbdf61dd0b96fcd88a63b2922b837c430277f2a363584a9f853503f605168bf10e9c03238890253c237ad9c83217ba2f906e0fd183e958a08f4871ea6dd8bcb731436e1a40444785c99f2634795832a9709b6704431d6dfcf2f8ab656017a6d1af019e6d0562b98cb0c99ec96eccac29e4d1f7b4fc051fe707095707afe8e0293236f2a3b5cae40166fcdd90fbb5e15951ca0f5febcd3f43938186d9a64223ec1105a582baea61add1fbe8ab93ccf6948394f6781fd91c1800973218b17bc9c1a7a8459a103ee01ca1de4b2cdc430ee8b01c0dcfdd0f56cbe869bbe3c0dc0995218ad3cf4a8697f4225b94f643acf9330e549a35b626fab16d3689b161621418d83244cd9f7c79e248c14aa7f54273cd0325fa6fd0a582854de9639eb226008ea6ba11a7a98e1e5fb8a0e4a41749f837887bb9e653cd3879f2ce2c74947311bf87ac60ae19428c4bb69cf2c50c125cbe08fadce882e8be501a2fbb46a4ab90c485b805f20629038e924d2eeb05241f0cff12a79b768f11d28cff1e1b2df1ea3decec28dbd3edef12f87d42667ce1e38fb35c2ed24c466f37fc2536c5ddb9cc662a29c992b12b7ce270b300a38eb6dcf0d883339991fd70ba59541c206d18306f7c790402cd6f23787f958ba44bd1992c8ae0ba7a7bad8bc73c20591d954f3d36e3078017e2084df1e0711becd652cea305d0c7da6ffb09109d009982f81b827ff596adb06f0de45106957c03c0c80228627600fcd70f9cde41abaaea328c4ae2457e69fec171a8b42f86c2db171d3cd5faa63d26a1158a44c96a0beddb3cacd3d737029eeb4bf76a2c2a6d600a81fd32125eae83df4db4e674b5375184161dccfc71b09ab0de39397698ef3d94d3b5c099c5da211b21afb69a726b20a128b0cd7212ba0796737c2be3852cb06ae1ffc8688b9403865df6539eb4f3eeb433b952d41be67e211f686bf7e27b41766b96944a5e49de727b2b660213e74ef9d78e681cff1c6f4dc2e3688f42168421f2e060f640007657ff4599428a4a48ac0b21b9cbb251946c972b760da6750c4a879ba0da64838123d43417d634cb465b45cef8e636fe3abfcac9522b46ba6897a91b3b7249e485467779a243470143048fedc667e2257aa00384afb7129f4b223b8c5fdd1d2266f015ba9b60e9612a14d5488c67e696133d02d7c695cbec20a90cb94f01b3a9c9bcbce23e2d08dcbc06466ed8c0b6aa0098364030ad9fc612d53bfd652f4eb69af8f682f3f85cb62cc1a1734c10d46927a7a32b66eedee4efe9abbf5154653ef18f536721228a6100590f85800bcbebc38c561177e0167c15350c702d1022e5e8db926e4a87dda626ff4ca3842da7beebc91527187c3b85300cb318272f79030c751ea17603700f8a68e2a2a91581025206f5f4acefe601b3a46463ae405e4ac05f0f0775fa1e68459b2e1641c1292b3345206f18314439407de20c94af47241691758e36f9c1dc0cccbcd628c2c43d9fcc6e9b18726ff23960e04c0962a047477aea4a0383bd8750ab377df2cfb6e3060c55c09f98a1cbe36c20102f06f3b0c432f809c4d0d3adb730346f1bc2d0c5a1a80bf50b1d1f2e74633fa76791e1418b363c1b2f013727ef83790ff02e7fd046cabb36b778171822a007f2d66d99842036f7d0357ad265aa4efbffbb80527529f5c4a3489a2f0211a886faa51174e5b62acdb4956dd8df136c3317c023c62fc4ad4782c0fcdd79b5b94d469fe1cfcc59182350e06cc06a4b901be747cc7004b1d6ce6d5211cd7f9a2a0e8391dddeb699e909d4f06284f37e00c9f91adeb4c0ad840c6d267c78097cebb7e425687fb6df50aa5bfe1e49ef0891648d9cdfefe05632e3348fcf0b9898616686604d3ca866db59c0c7d800a1934dd792370bc42ddf6e65a4ed74179f2fa01643f8b346aaaac593ba2d68feaa28f350b57198269f58904b330bcc5b94177849c279c2dcdf1bb62c4503c9cbf1273f99c7c6091db76962e138ad0c69e71a2c151281a77f7f5c05f34f67a8b1b46c062799897a69c02e67533581e8f3f00a69d9b7d218d77a2dd3f000422036509f18222a2bb14289848a0d6a6d907395974dff8918a689b80e43af63030579c395ca0822d190609178aae698e073299dcd636936bb20474361681c1eb49007f3bbeee80c714015f4d4b2bf9596746674f156c00199c5d7ecb81fa430ffcccb9529ad89931e2420c12d99f918261f6b9e9759a36c5589574ecf1975658924ed3bdeb8c39e0ede258c3bf4512234b4dfce6cb3c10f4ab8516e64be25141922db0de50ee5a083cda5f16a19939a30c129a1c50c9817552474c80f293c8cb5f79f1360853b3b1e27a4447522632ac452ab4c4a568a9dffef94946ee5d3f793284d574d63f9bed5ecbffcd02f6aafbbad798a256f09092bff78ea3ded1f133ba21628874c2fee7a01fcfbad1d2d73904b79254090944c45281571823878ba5768e81ffafe269f531228ad7ee92d1400da5b2fc97e49ac24996ac0875c1c89a89c3c1f6754c4b6c4a88d674ce3318efec8daf4bb06f5e5831e20dd52bfba76ec3a211f6cead43d5f963496d5b906973d17cbc75721d85717c4b454ea16afb3963a06cb9c128efecf280c964600c115f7cec416337e288eb1f635ffa125273dbbcf476aeb3222d1d614e739a1853dd96c97a1b378768dd9799c491a9858b26f74b9eca54fc017463911dc8c01dec229e0fecd77fd88fbae8a40fb960122da832cacf7ff8a22cb5f9ddaa282a199f47529c7b58d6f18d67c23da78ddb71b8232e5f2ad2c5301c3639eae0734f6d6cbb280a564756c9c835a689b803c349cfe335931bc4fec266375be3b5111b90c125ca6f93a56b672a992593b172f91b8fb5a614039d27b009a94555e9b8e8a601f64c0445026ff2353e9033596e6ee55d3b3cdd969bf6ba753adbf4bdab3dffdeb22a0f4dc35f3f18c0cf4e5ac3814b2a8d3ba40807a93533af0350e18290ffcd8709867a1c7f6b1ad8a5511c791e853d6be2f6c6e2ee4b1290ee0a3e49cb004189222ccd01ae9b48bc904ea8e3ea4ad925058b0448ee8991c52e5969dd13d6143b7046f4e0cfd286fa800cad2ced74259b5b24455d08a181d464fa1039979302ef06ab8c09fc351abb931435a353aacf08e0bc9dd5b1e5c7490e6a3970d44fc5f14b1d85aecae3a18b70cf960038dd0ff0a6a4b75cb215fc7124b75f2ef001792e22eb3ad1abb90499977fc38ef3aab22ebfc6cdf45c7e70b1fd09677dbd0c636b76cf324a33aba15494c67561160ca87e06af0e1ee126d09c0f5daff7738a7e36e386e7fe5b7a45ee38d6dde044ed6fb04ec7c348ec2153fa46795a3efbaf2e78c5c4f812c0e2b4c394df3c5c7ae28df7b1eb243bf1b79f115a19efb57961a2708d6125f8947feec56772b431edc29b1f9256a0f3418689e7ef5b0f3f6217e349785342f862640fe244529480ae5e36403f2629ab7347b2c54b89271b646aff9d58a548cb372722dd7a22e43b8b25c8d733f5456f03fc21bd7338604d5fd0808ef0ff4d27978b89bcb4191ba6bc642429ffc907e33b3d56991a3a8223de2e6962d49244afccb6d71ff3a6fb7d4b7ab9a794fef1de672bd19126b7000742402cdf61adf1bb3f1fa997095595af21a1a1638cff356f7be58c618136ecf6903f5b5738a89ffd9fb2bfe3ee459be8746e472d8ff6ba53ce60484bbf7f39502b33930963f0620b416c5b0f6a2c3dc84e4b58f4f30796b95ae828b74946e6481723375c959c7866083f93f609deb65b86d0f56cffab2c2863dc9627636fccd2adda66f27eda95186c531b334f33fe4f720665fc0c879767b7bde079c3506f8150aea0c3a9fab35ea17a93bedeb74756f39b57c12f8856c49f47b763d3ecd162b6adbbf492be2cff200f00824d3e4a21fc6b2110d7f6120f0ae5bf3736bea08b5b3e099b41ca38dfecd6a6aa06e56dd6912f453854fa2af0f5533fddedce8a41edd342b6d452c342b47025c311e37f536d203b782fa70762be0f34de7db60bd77627f342d69df3e51dd1d5c1c229123fa9362d265577bbdb51b0498fe64e778e55c7193821e020a8bd6a2a4ddadda5c956c9cd49da019925d4d72be0163327cf6a7357f7c259df0100652df557dd251fb101c063c7a1fee811a6f0f81ddb9d73ecdf946f2a4a06e4ae27dab4581afff82c9e824d349e2ab2d672381f7bd0ea5c5ccb48e1b7cbefa453012673a2b754c189e4a0b57cb9c9ee990efb6a07add52090816c224f972540f2d5cccfb3ec3247eb405be91613b778789e803f9e5fe8038a11823d47368793e73561a0ac5ddbd3bd8e6c904c3c62f60e7355d818fa8c4f1d90305153b01a020b6ae207b22ce5f75c94d8eaa0e4626a15ed6f4fcb267a63188975dde99fe6c91905551dd3df932012d45226806c85345039572a3a14deb21d74469bbdeacac3850ee4057b4ae4ce7b3733d02398e63571be8b3c8fed7b8279f7e472bf9e4cb2c68cb170ed65c24584f1fd4e3ef68be9d4e6a4c9f5028ce9d42bf7654f2214c5bb3ceb2893b5f5cc3d95ac80ac94a154622a23b215f53f7fff2a493764b2aff6810bef4f7740e200da3e9457ce50daa062cc69044f2a3cf7d39dcb1e27825145d3ab0d204211e46008104155fdac3d9883d7d21f4f1c8ad679259a7ecc761266efae5bdd79851d5284d9158395654e7f343227d1cc0fc08649904a9b16a378319fcc92c9fe7cd8e73c2d7f141d7d529218291e7268ac47460183aa47824c1451c07d4b67c85dc71375f169f4ee7951388e4080d6ebeccf9e60668869223e1f3721bce8be9a4ce05b26f04d85219de49d50345034e36bc26bc92c589e3d7a90a3a44c8cb4c0353035c8cc495fa4d6e49f0e2ec99d58dbbeaf38954fd4d290d535c85815ddac628cbc73cc58bbb8dde57f02bfd239fa012a35eaf1f9ea75b33162c5ce709cd5df098a358da40c139958cd9dde2d21a9652d4031502f57cc77470b69d1a37728068f7f496a8f13391880255d227da3d651bf607832bc6edc51f9e0f2e158befc535507a1f4a344fc263d39b1ab1866d6b51041d204aca687f6405e74993d0cce9074f1abdd03e7b5e7edea47ce3c6b9a3bd6322c0a0e2dcb576db974eb4f7fbd7d9de458d1a700b8b884aae72f85f834a3e58776ef68710b2bf8a6348a505b6cdfb6c1bb3a5648a5182592b4fc007690d0bff4b4dcd8f0ff446c8a7a6ae1c5785bcbf5eb3f6cd98e4d4735adb8587254bb27e579c3f43b2699d2f899bbbf12bfd9132c987c16b387d46b7555181a2a6e3b90ac15dda957506211c2fcf1fd126ef1fd201c0a7fa4e3d8632a8e6b6a1d7fddceb6c850a6969e741f219cf2b6ac039d6064fc2112ea2877ee6a3168aae3040450939dc30312a1adc1a8861bd6bf67b065e349dee42ac168a5bf0fc60269fce948030c52bd780c12a51e0b80f8039cc632760f9bd4fe78c621d368e698201e6ac78cce343a21d72bd6b2b6c77f578b8b2536387240009d03721f8dd3ab769f7e705cfe3d7e8cf45d26661511e94e136f78a49c6d770ade19ec6b731428934f5b9a470fe33350f532632b1d348c779509be040a5bfbe891719fc45a785e10858b7486e31f80bdaaef38ee4db49969031f0e589681087442f7089a58de9fa0caf7c8fdd9758290e83fbe02201027a8f9049cd00c9239892b3929481730b2b047158b828ed8a98dad312578feb5a07c4fa22abf9a9db0c16ed00248c21305acc1170a881726abd547b659d4e487f30925a2e599de1543f6800be06b945aa8065c0d50dfc741bead959434294adaf0732dd9a0e9f63ae91b48330167bda92e5c4afd8b65128adba645092a3c0c38190a5dbd3c0b0e91771bb765cb771c8e2f84f3e6701517809c029f9ee2732d6cf0c3423440120c9dbe1660043ba60ec08cfa6c6b4b252a538e5e1ad0c47c2588f5645182720393de43173c707e14a5b5b0c2500e2cf0589ae06b6fae951bd3c4ab903aab3ef05064d02ae0108663dabcab291b37cf3acc1b5019f825ca60130c1c70f0e274f5f034952690bf55de59eb555817bcceac44a2a8c6533505e7794bc0fbd6abca5f52c40c4192181c8de859c3e602fcc00f4f7cb6dcb79a1189901db39f80e1b73171f4b76b1377d6cf11b081b2e5b78fd70c75d829a0ecbf51e22cafcff15ecb94bab911a55d6e7e30cebebb78867456fa14b66b1818637d49b8f80a2cfc975baffb053f966338a4dcf21d52e1eeb6262daaaa5ad6dbb26cfc87ec448f5a39bc9fa5f58f89830884f7148528c0735718b131267c46286d4e920eece559df068e48a6d1e2b9b0033600408655e10e48f2144409a8b7912e0785575496276baced7c5ca0e7b5853178531601b9b2394d823dffc65a031c6fbf71d6025e8aa086787f28fd99232e5d4826c8901f91b11fa5bc7d124419884f3033a73ffb253106858ab0ee21e76e34900ca0c8344262afa1fa535ce36665e6890decf4bd57990cb44612dff3c0717fe80a16527b24ca4e1bb500657a403674e3c8289e235cc5e948386b4611d64b5eddefe9772ef2d539201000b230be70afd0a612728e6cda84cb7c2e05703058d10342a2a63cea84c0d2cc7ccac4dc8de07d139c78cd27c649d9d6ece6aadb576b8c94eeebaaebbf1393e9966e103237227d35a17ab4ceabaaeeb6e94b5761e941eac1f334a73a3bf5b7e938573cc481f5c6bad3a5a37ca1cb3fa37cfabb5ae93bb2770f739626e7aa1b824da749e87608e6192a4f9a44933c5c86e5e21fb9b5fd01afcfb5551664e6dc9b96962a14dfe26ce24a34a76f3267e640e5a8e590e9c197cdf5d77d7268e9bdc9c7db7dbcd834d1c3f8d019fe6cc9c9904802287571200f6b71c54b879daa8e5b0d9a855d48df7b761aba88a838800785dc9b8755d0393eb19af1f198d0aa3f0fa096e8a3dcffbbeaeebba4a826654a60851346ae4459fbca24630391b35d00834aa5514082607b251cbfe222826037cfeadfeada23cd581dda0d7e1083b92e65abbaeebba4a562e70f79de7791e284669bcb3c29e7c826222f8608ed0437ecedfc0f2a79834cf8333371bc7dc828ab4d62a0618c2fef66325df3200b4213a4afb58379b9b217a8dd48d32c7ab9e0210856e0b7f7bdda88cff570680d689013ecdd92dfbf768f550e2a6779a337366cedacb31cbeee940e115e327d0c297a35854b1e1ebbacf85cabc0ca0fc724ebc78b8c90931e4979b3ff4f8aaf0f09437355a6b1689e451e12bebdf13e79b03e6b3d1277f5a29bef7defb75dd07764004d127ff8e013583f74d7afebeeffb0e86bf076dd360006a0a4915e5f194fde7279fa4fcf9e493c7f72de2f08311af5a6195c95963aa1ca54183a23eefe1dfa7f4a6a23ee587063df98bb63cad10372c293dddf2b445941607b4f6e5fa95cbd7f6ab5ffdbad6b37d52bcee757d6506521ce757bdfb1e39a4d65abd6d014cb7ebd1330568d48f6fd3f53ccff33e18ec50c4608797eca74322408a990374c686ec5bb889d669e19a4f5abba134e28502b662f02e14f8a439b7e30101f0e1cd097cb8e99aeb4345f93841a37edcdb35a69eb9a9272145462004d7023a5351679ffcd3c8fee7007e3801dbef7cb85760cf83dfbd7def5e0ff4e46e300ca968d3b7f30bfa7edadeaebbf69385ebdfd87fa7e07cbf7ed7c0b4e9d39e91dc7beffbf05b8046fde893bf8fda35f7fd7b74cd2d39f0a351b41dc5439fdccb2c64ef1181215d160377dea50252dc612cdadc80427bd3c29e4f5aebdc009f34c78712fc40a488114785cf053e694e96b949859b9ea73934c70710f484a793e4755fe75a7eb3e702a4384e008c625f141f6c14eb9a0ff40cab9e628c98328ac518d1a826a24ffeadaaa70f744dd7d472f4059d21a251b447594c195981e27c748451ec8be283d50f74232946b10f744d097a26565130b83a92a2513064a053b23f084386467d51340cae045d53dfffa3754d2d63948822a61543834acfa8314b64a7d12d7c6024c5280676b79b483fb4aa57cdeab8b0aa08113775dd5ef6b7aa2fe7c61411e3ea181695a931af1d94e6f3a2f66dd1333fd4d30a3ae615e344ccabbde813adb55652cc22eeee063bdc82957d6473f38c794d8981b979c6b062626e9e652e86e566c9c788e626bda1e626d5428b5bf68f59e266bb46b4114d897c8666370bb87b90825fd85182bd7cc6b09460cf670ceb8357d0a8cf8beefd635e5dd395232be88c173d92e59111fae4efe7c809a32250140c183af91cc560701e392a0295995199d897cf512cfbf7831eee3ccdf7e9dbffbe4302d9817613cb95bfb250e2cbf96a61b9eada579e170758fcb02c797f13a466d3ef61b18c79ad3a55cccbcd920e1eed81c400b57578d5c43bc2fbbceff33e9b0310748ddc791a25b7888398bb84c17901770f838b79799e11cde38d68231af646b4116d44fb609e487aa90e79c338e27ee776bcebbaae1bd1aa64ff6f8aa3625862105d02010355f61e885e438a9bf6a392fd3b237b0caba2625e2c96cd6dc2034d851ff3eabc773a2f929d4856ec2e929eaa895fadd3e9fc29961fb00c43ef45d24b7d6ab5502753d101ad46be4bb2a73c75e46b611515f253bf7fb1ec62d7dddd99fc70c8c0548b9a92ecf96cd5f9e17cb62d6e6e9e14975b6eb64bc572936ad1459556e9e0131dd0990735666eca3f509aee5bd52a24d97a9e66fbfe38be2bbddc239a18d9bfdac836aa89397859879b4c2652a6593451056bbf477794cf116d94cf98574709eefe8c6165a753320d9ddc3b9208430709dc5fbf2ddcecb2c4a3078faebbee7e74d75dadfd9d6bd7116d24c6c836aac5bc6260314bea9f31af4ff7e1b859cbce4d4d65ea83a05a6b1d45811cd9c41f62ee72441bd1b23fe841c15f2d4a4b8dd2840f8373b3549fe6ae5debaa497b6238bf1a4cce6bf06f12860a0ecec0de855c9fa668eafc6ab9e60f0a45c5bceac9939013fbc6c81e03fb227453f6a87cb5954cb350c296c54c6b5d40913b48e0d303a384f309286e9643dfa4cd1e15fcf8cbf48a2eb2c85fa6352d6ef93bc2fbbe289fcd6bf0efe00077400c2013a9dfb9451dbc5ccb3070f71ef9d5a88c7fccaba23e28f4e439491823f6052cfff06c5554c6df61706060981c0c956f0bb8fb1306b7526bad252ee615f3cafee12b5cf2d5c2b2c9f9d5be5a25bd9a17850240e5711a333eb7dcb23f68ea19223ed54744d75c3aa3baa7c90960fa88f854dde1c119ecf7b5a59ffe8ce88cffcbc85a6bed83b57e3c28f4637d495a54948642c93ea4a57fbce04932554b7137ee0735c8dfa7fa84e5794193c7943bff2157ae92227fe427feb543f07ffebc23899eece943527a6ad1e676df64e73f9288972bee58225eae6f451d6eacb1c61a1e4562adb5d6cb99c05a14373f2c964dce4ff5a9eeb5e4d772037d250b37cad0cabb11268a72223aa43dd37fe6b8b92944666a468bfae6a6abdcd46650d397a0a6ce71d35ddeb88af297af7aa6a7641747b159467f59a30f6ed593cbcd2bf325a879a7a0a6d7793f7f7ef2e9f7baa66022ffa04f7e95b8f7d3695d21dcd67585c8bb425e1f50192fafaa9e688ee333373971937b0cafbca3caaa970e8b447a298fbcbc949e44ba98742f8bca6a3219e985fc7a7a92ac3f49e4e052feb75551201552fe5d3eef4ba4baac8aea947f3eafaa33d879e1eef40097828c468f2445224b2fa511163152a44792eab42acaefc5248ff1207798ce1da8d1d753c863a0771bd96902af3ccb4ff19b4bb9ef3637b9477193bfd7440774087e4803b7c0a15db4e9fc85d2883a7ce2c82fa26ef4674ca6a33f6fb8501b464f7a1f2e623114023b04c3b0a435aec241cdd08fdee5e9932a8af4a2f1298eec42a211fdf99da2a3f7e1247245fa977755d75c59cff8e30eecbe7613f00b39040c54a997279143f41aa9970747a4a7442ee40b590a43aa547a212e2e2e0deb18ac673deb978b6744145c6a54b68bc545737d961fdf8793344522690a04aba843e7fae08a0bae9344a7d549a20a17dc95b9e030c638e4e2d249a2d3eac03a4b3a2f37755cd995f87057f90ac75775c6faaef4959bdc59ae7255e9ac0e156ef2efd0c02a37295e752ad56d791246e4ab0a954f8c5c6e2d5d702eb84eabb5f29224bb0b2ef42fabec4f5538172a2e3917975c762a6e7217dc0ac51863dc781c712712596a682554b1b8ca555dd3517554ae12f910ae6a4acdd09ffd2e39172a2eb89c9b6d8afeecd2a5962e545c702e3937690756bbae8a422f1f0c8a480f85429f18fa5048f454b4f9fc489672183ffcb03cc31f1f491ee155135158765ce1e83f64d951d2050e61eaa7b01c3dcd2372d5e41c653c821c7e9321b2049d701c65fc540a3eb842763187510ea3904752cceee28dcb8748ca4514949045b55afdb36b388744221cae7495a5d68e589fd4919d4cddac2492a646244d89489a3f18ec48cfa01892481731e8e195ab3c9649efb18a2af58f9ea6bcd46529022f0ff3424a3f2a8f8cbef430e5912641465f2afd11987f295f5c489a1a42fa700b272a58c98aaba25e29ff95d7ca1237616e7613d97f8549adb9af48c59d0108f92b3d2eb0fbf0c3870f5df3019bf381aea1818629a030d0a033202ea4d185e13b3f3e268d25a80c7af2ff80e1a2b1d23a578438575aa01c6b2b2649f554df435a1a84dc340d5dd3a341b62aa451a03070b5d682c268d44a120db255d44aab9eac2d4168ac2401c2adb42a0ac4056b41694c01954165723960c0f74f508e07051731e2a6fd558ed2502e7cdc00c46b1003ee46923b24898409c1ef9ff9b0dff9ec7cff6b1111879b9e554b8b3fe5aa6f3e60926b7976ab48ada20eddf75f930e53f707963e00017f6e56c75e5bc85f797611d51331e45a0ef1d1b670f3a3399a2b92bd28772576fde5074db8dabb4db8ac5d92f33ccf63626ff7d1348a3411adb2b70811aa225dd34a7ac6bb09254aec92f1b6923bda256311961c5dee3688fedc91472d25adb9dd7ba17f82659c420922110e4b3952e1277fd06d679cb590236db491e3196315462a64ff110aade1663b5a21fb8f5fd0192fa99fce714af6677d8a548e52fce43fdac66ea25ddd44bb465837d1a8310ad5d8f2f0de7bbb91d535cde70b2a4383467dc0e895957c8e2c8fc77a9e2706a6b56bf5c4057c8e3257e2a6bed553101070d60f44dce46f33d202e3a8f71deb6bed553513262a26459a89af0ca11271b0d93e66b9d95f4d92290dfeeec5f3199540512da207bfe3fd0b39e68cb65186936026dcf429cf11e7295b4ab03c472b4458a73cc72864ffb1149b90fddbf562c2fed9a3ec7add9efd6a07ea25da354631c256da354631c28a8cb08afac8c6281af5a922f7c9f97c41658a74cdfd5b7ecaa03346dc321834f73123fb7faee779dec7e663c0a17c7e6c1f1ba5717b9f16e5cec629a24c4af6ef0881ebdb5384b1b06026bc9510b342944561e679211ec208abe22363193f9f11d635adea99d18856f5bdf75a5294416144a33e61f4c95bd5aeaeb9a5a884305a8c657f21dc565d718a2afe106163c0fda708f33ad97ff4cee053c0d77e93a20c52fc75dd6924db26bfb2d4dfe5fe92acd4653be99814f8f3cd340b1d4c01652adadcac70f9e498156b593bb97f762c4665daf32c4bc8c2aa186516d63523ac6764f55445a33e558c300b039bf4ecde8db05108fdb998544bdd8f3316b2d49537624c64e2a68f2d5790af742c5ea845b8a5330a491d176be38e01775a7a0c18440f8041018421110b0bcb9f37c81df5946af289d0b390ac9b0a953c3edfd154edbc1af8ec18155cce1429b610607a85ad4aae2fdaacfc87b43919f4c20f79765e6169697921a167097d4ba8ec5b487c9a12ff9e017bdec3a477f911f632c644a297f2080bcb91d08b443e5a4820223a9b75d5abb575fb22e65ebd989be7bb46276e823eecc8275a5e44b23ec5f22196677daa6505770538778e9bfc33c56b214716f247879ee56537abd0b3bc8b3f6c4efe8ca0af1bdf87af90a24da491b49ec21f59152582caf3e2925596a21437d10ff4a9e2262781f71f2a6e2a3fb74f0e74ff1c65de4873f31c61d9436e2a79e58f59155be4bbf2db173637e9155fccfa06aa999bf40a3054385b8c523c8994ff38c54d8aa3e2a855f8b2e920fb7bf68eb091899bcd83ecef8d2a5284893137b9c864d5e4f6878a9b3747c54dfec175e4832edadcb271f77f726efa8c42501a6afd92f69bfcbebefd8f1437d5f2732bc7d94805cd5e1798057fa8f8c9ff93534fa3103eea87a45924cfce39c51a891c6f53723e677c709fdca78a9ba3aa6b5c95fd8a36de3852b106f6883a26f394d44db66d1d7395af3ad6b18e75ac631deb58c7328b181399743e7543361deb58df902d7b0adc1726f44ae158c4588391456992388ac5479a92eccf32ca6e8cb58ab23ece2a2af47636e658d878c3570d6c125fb68a2af59328cb8f5e08cb8f5a7ed4528a4744cfd2e529decef091b1fc47e6f299b53ce9858cdea53c12fad193ca234d82847e34fa23a26f69799ac2a47af2f7c6c09f85ab08e248850c0b9866d187feb4309b8dbd59893e348eb4514456c1a7859da30c07591ab8746d797e6c261d6e72d328cbb959c55138899ffca548c9a708f37394d129679c41850aad42abf46a95a493e453848d3299f8a3e62e31cb4d1fdb3503fedc3e52dcd42f37cf66925d22131db3301612263171f3de082d39bac622be91a5ea9a51093a53451e69302e1183ec7fd1c034b37ce8bd8f5514a94584893052392ac26d2945e553d146845d91cf8edd00a48623b4000847d65804458d4a185918ca281ba9b821a334f449f6bf66e0ef45df2a376f0e9fa36ccc5554e8fd31132e373b252cdc1a6d15e53fe654144db1fc8955b7ece34b56511f5badcd48321c8bc1eec5a32d471995b102a629776225061c23dc52e7c7e66d018fb25b9668e7269f227732ad3d4903081a051475f8c016a9a883973f5084519a514665fcfd4528286a54023df9934820d02813619e4755b37ae5a6efc53bca6e395231cebc06ff4b06fcfd39ca74f0fe3e8823bc63c05f3e4796f7a51f4a3a34925c9e80e266b942a0fe2d4b37cca1fb7e909883f75dae883a74ef8d325acb46597f6c152542414ffe62116c4ac8c9a215d9df26c246192cfb8b58a2246e5a0b1b65a2b2c939ca465977aca29a9e5ad6f42461b9df32e93f2d0c8749c70e1ef5d4cf4276fe220179096c00521c2785428994e3db23e57852d7d0d033fe3ceaa95136340d60d3d035202b6c001941cc9e6b15056ad593b36490cb0a5bf60743f6f781a334b747113d58dd835ae00a7bdfb9f4e35bc920d8e487f43e1cfc889d3fa4e752f8fd313660d2a0170a18e66db46c2871f3e5fd6db8dc74797f0f0decf22fcfe3e5a68df7e7b18407aca2fe5149b23f8ae5a6888291d593b7bcbf49c3a15639556e546c67d4a6d0a464879945c9fee2f710829a2d60a0267f92371240f6efa16aa1925b7261e7c2a3f742989c8d560dfdc963c7c706f931f29d902ffbd9e3b889f624f26b6e8a42becd4d7e8389ec516cd85a1565438a9f94f048b2e3c6aaca53c97e868d29d9ff63a3956b16cb1b3660646e72cff3c812803398998d58c250d1b1013e6164366415057ad59383649966c51756b9cba79973d3cdd3462bbb59b3d172f3fc9b8d286ef61299662bbc30c58ce2e66c07366a0ea8396cc9651fc13e567fdfdfadfffe09ce728396f00077f64046c0d48a325af904c54272258301a0519a4b693adfe2a234df836294c63ea805c201122d4a03520272b9e9716782825f77ff37fec63f92d489738f1bffac9b32f1f8585d524a71fd15acba1eee489f63667a32a485b527c318ada7f0499aba41d2542709febff15fdab0d9a8d553457d17778e28d09a15dcac45f7fdc87b50aca6abffe47bfd37fec68d3f6f645a7eac185557d29e81c9e52aeab6e4404fbfc070085e84b051ed4bdde82660300c61232f46b591175df3dde84c098a1f734665305e61efcd5a2d0753f269dacc59ebae8ca8164028f82483347a22b988c2ce0a7760ba1c33130b736662d152ccba6654a3335e51a0588e59d7755d775dd789b5763132b061a3d641e8978d5ad780b4efd64168d447c6e80685ca744d37069df1a72d05909685ec4f04c873ebc01cb36e50aca2480f8ab9a73c71eeac7008ea404e40b21ae0ef91c4cd7e2f47f607d94035310a0df019c242989b9dbb94fbc31befc3f1aa49d7a7220f9dba513e89ab806b793dfd0261e7f73df87d5ebdafa01848e6662dfd9a337a225bd4e146ae0f8a819c8064a168d320280692d5af0c63bdc44da0582701836420276ef224e033c71162a018ce540b2c8ed0a143070108308001e4c8b10202bd07047c02d280748d8d1648ab28981cf8a451306ad868519a5933ad107f88fd365a5d6342a1336a342d57947985398523b2839d152e75b2984f7366cebacc317353113d84a0e6c77293eaab418f550d14d9bf064669ea7f3442647f1a15a5f13e88366794a65b726eaa01355bd2e8978d5a083b41b1ef5b722d6904b12a8a65ff6e1d4812f41af92b4b3978df3d0ede77bf82cedddb4792ef77e40de54255442a376fe9725387a4399413d9b263420a1c969d2b9b0906cb527d24b9b66ae5a6dcaa98185c90219fb7fb3e8f5887803b458cb8c93fd7c55c75d664685c93a1436ae459d7f48dce8472f4d64e989101d725e958fe39ecf3bcc3b2adb6ced3e9dadd3d767675aeced531e166f79fcdeb4051f43c51f43c8ff45717b158ee7c76b6999b1dcccd533413e1b8d93d70f3e526ed22e662d22dc9fea118de20e0b3737559fadea12842f6efae0f37c1a84c07ab9dabfb0b04574585725de7ba4b42b950ce43b950ae3b979bba57c7849bfc3a81bd3f3b5727a773869b5de7ea5cdfe7af58e7d9baf2fc66b95f541b7903c600298e137c826df8f4729efb3d35bc5ced3c35ba6bc615da799ee7e1c4087ca9f772e0166e765ececb815000298e7314cb1eada84f87006af29ea4e60e3779557cfaa4f77727ed70d384800ffc4a36146cc927ba77927561a67cb78aeade7bd1dfeb23497db68aaaeffd47a3345ff6fcbd6fa1511a4acb1eadab790d2ef2e0a96e879b9ea77fdf7ec7f33e9b37962b9ff5008c7ccbf3bb65eff37ac7132474c69452913eade964fc7d156dc0ef4891fc6cf5e4bd7f5bc8dea785ecfd3706adc17b52457d3802786550937767d833e88555bc4dc0fe95fc6af5e47d477a1fad9eaaf0fcf79d8fe526efa3c24dde7fb2ec3d08520af294c207ffb379c2d0f39f943afb685fcdcbf1fea36255de7746f6be5cf6ec2a7b1f829ef37365efbd112c7bef79ded38fe626ef3de4577393f76de126cffb8f86a7f0c08f9aaee7d9f2890f8e932ff6aa27efbd1acbde7f4cdce4d96fef3f57f9b59afc92b8c9fbcb04ec3d6843db913465adb59fca4dde8e7af268de872e37ed7b1f32e1e6f71e2d7b1fcdb31f0eaf24c12886a33085acd6ea3e7c740d06ee0c035d63ada5526c92aeeb6ac7f3bcda8f7addcdcd6aa160f0d63cd7b6175dfb6a5ee0bad5ba817d44f6f7745f71f0bed3d5ce941c27f87802e48a38b0e4b35ffdba60d83ea0282028ae5f1407254adba4806afe20091203872f7681cf96e527f8eb344ed3c0bf5ce0fa9e13a9b99627927ecf835ddeef3cef3d8dec999bbce36dd1b352a659e8c089ee5ad756722d1b37bb5a6481efe34c653a78af0357cac1cbfd5eee92869e354edf6a4c074ed47af0a860d975f67a21a59f68adb516873516054ceba9effd586bad156d3c2e6ab5da0f6e7ee3953d0048cbbaa693f49007342a04495a16824675127dea56121f5d73cb2e029da1fd83247d8459fba0632f1aee2703d32e6c50cb4dbbb081ab5720d1e6420197beafdf794f7127068ce36667fc5e59e596b3ce77a0c067d7beeb7ae6264ca659349146ee32ad3d91e5b36b5d6b12c5e6357c9363cf5aca13b58a02cb1faa91a6e1b8c9b1c0ddcc5754c69f808b107193e3e0ac98a9f8953f6c19c2f586ebdb32bcb6829268f5ac672aaa5f9d44a33a08b39e750d901f5640bb7d6443a1dd353d069d692964218bdcb52b707dbf56e0b36bf9e5a675f3abd56ad6ebea4ac7676ee0d5dad5bb7953bc9c2b85d3bb6552bf5cf9fcab45b6d5fb95eee1a2dcb285f42dd93f7df23aebab031037b53cced70110f6cc8793bd09f856d4c81b95de087ce8c17e4165ace5020f8b05f7bed4addd9f1f0050f3fb666eaaa7cf09a68f157009dcec94baaf52cc50a22252c4888ad258f0a76029b22894765e37093414752f78bba719889b9e61ddedee920e830d64879bf082816f3e0f7af7a7b57519f430242d159bb3511a510ab5552633954217b79b47f7de7bb1277ef77a7f436ba332359fd676997cc40fe70beca3f6e0839b34f7fb0e371870f396f7e5a6f0435e2654c6ef925b5995b8694462451bd08f4fc5db82b9097393a3807c968897bbef938803a9a88f764b11025d79c96ee5eb3737dd7b44cfe8f86615b5839ffc6b237123e519fa1420c9f7cbeebb1ed133f5aed47c619043d786cfdba22c5ea84569e8480b12f4b37c477a19043b64a94a583e449e487268e53da24da8c3e1bbe4d99d43f215e5b3df668f44922d49c4cba2b21ed1332c7f5940cf428ebf429e3583ca52ff79f347de20da8ce55d22e20084cad4ff7c47d61f9e3fe56552052c9636179696ca4bd5ba9ee7f7767fffb4b8ecf76dee5e20d5e62c158bbb6f716e52c97da24d7b166773e5755d5648ded555d27a9db8f1fdfbaa65fdbcee5a99b713fce1b8f9cddcfcee2bbb9be75592fd5fd5f18ace5a2d373bdf836bf1849c4c0352b3652beb4a2b2bbdc0e737fb6694a6bb40a80caa93b8151495033db949e58c33a64c912225caf9cdb6c827a5f1e06100039c4e94767e334a41a06ff6e91c130338404d6618b25f2ae05b362b0aee9c94f659f1aaa8ef8ad3259fdf2c0952c8fe5f16d96753c0a7b5b28a6a71f3f376a85f0da27005ae4e3969144ab3241aa501b9b685ecfc54fbc6428ee30c20c571c65c1be2f8b538d7ee80b305fdbe2942991737f8bfdb0e9a685837859b6b06b61f8af6073109b1f543d70ce91917936854a8c60dd70de99a90f65dcff7759febc3efbdf786eeaa910bcba033370958cc6768bb387766f30b05219472e8b2d4791e493e4dd9fee721ad8d470f1ea708e302be7f057c3b8fa7bbf603475a48eb9a21f466adb5432816b2bf157f5c4176439c2121c00965214ed7dc8063adb558647ff023fec8793ec35c8806458938105b392cba5c8c75f7b70c6c69166315e56529cac4562709124f84a052a5ceef46cbd2f7632d9774186bb9ffbb9138fef329b6c4d76d074d64b175d1b0b8bcd77637a11a61ce86b29e09c3e8ae0de3cb91d99660adb536a4e5e0536cd9db3fa334443a0f71937b809afcc7a715f5e97ce8811e18cb53c4c9a588cb93549ac0c0b70c6b65b885fd33a4657f326c7783ad756498137e41656ee81adb35b60ccba033fee12d8760f4c94333406badbd5ac0f67b7025bc5a78b953f0f72f370bd8fa278355fce1b7fcd119885e0387fb9d7db8872c79bebf6d3ce50f7bc3c02d2da3916823624c8a2e51899b3c24182c60d1558a4adcf47d57feb0b9bc6160fbbdbda1cd167e4151df18a1cd5a6b2d142cb64425312d4a43b5105ba212d175c3f64fb12506c60f7a2ba819cadc34a334fddd6ead9f42c4b971d314224e76d10a6a72b125b648624b6c99baae4b714665bab28732889b6ee7bd27ade5fb373db879fd5e8c5bf4d44390be9ffba2b803927c7bf8dce597f34d7113ad79996661063068219f62eb8a812d5829b5f65e01dbbf5d772d4b78499115a271c31c95c9658a1ff49d3abf5b98bb35ec3cf1de5bf844251641cd20d620fb7b618e0b7c7e37dbc9b81f408ac3eda0a77e1ef72b3b9fd08b30dd0d21187243d7ec30a4a2425a081a153ee97076e89a10a767681515e6eae949a342351a876ef1e1be31d46814edaef9c040677215f561e1130316d93bfb51241e8fc7e3a1f87b81c20d640cf1ef2605773e694d861f3f4ddd0471b3ab379c89ad8a62f9953f2f486cd92a8aa5fcc6a02ba52db4e1128dd026b6566e53dcf4bce35a624b6c7daf6f49eeda0db989041383fbb80e5de82146b086740d7d231a9503a4f73ad8b70bb8ed1782145b6badfd80e440515d44b3288dd6014269c4668d81fbcd9882eb37e9b1d9c51b5a4fd6459bcfd687211fc0e16e751237dd2fe0fa67b39a47cf38896a16ed1b5094e7fd6c1dfc4065fc79740d1074a61c524ffe34d96fb42154c60b2c5be7a1967e0e6badbd650568ad01d40ad93f871e8074017be73d5be0b3593637ed8cc562dd3ba4a29e9efa4d393b70f6eb90dfcdfae70820c571aea068f0e2869efc6b08d6fa7dff7962e08681724039a01c50ce09cab920334039548d22f4d4e1af39a0336698e6cf140dd5ca6b858915256ef256911afe2db6c43c572cfb7b72dc73869b9ecb73792eefc91be4284412e3ed7202a4384e97cfdece5b22affcb7f276c532b14b60150556d4cafbdb989b8dc408126af60ca8c9573d036a5a24a8c96dabe5a67521e1028d6369e448e845f18f88fe8384870f1a0f101dcb11874421aa128544a2d00ad86265e4e757babf2ea4cff8c2020651fac2d5f8f87df88a0c3ab5f260872da4a79abcb40b5e7b97d0b52bb22d8bec39b7db94db854265ae142e166c60d4acfdd227bb4aa0280b068bbb3259ad5f4b9bcfb5fd4d2103ff4e31456d0ad78c4c4dfed93b228594da20d21301d7fb509f074bd6caec134bb34f3a08b96b6ccbbea86d59598c9dc2ca9e644bf34223300cc1d07e46512c8d20b9b9c949f03f64f8a0edb0be23a1c72b2c20fe23a307b558f0c3ff4a5e13cf83fd21574d3aa2f723b92202a73e0f8e0f767867b2ec57d69e15c74fdf1a174a5e79033ecd41ac153fb4f35e1941f47ba5cddd42e9067c1e680a0c3f081e686ad5f22bdf9525ef85880f7a219fc70f8648522059eaf2bb5ff42e8f24057e5b510d4b067af2bf396423d12df17d7823f1a56171d4f4e5a8c9bf13494f8918b464103ad426484059233f21be9051d5a43e0c9af453d182a63b855b9b0235af19d45473f3e6209173dcec1635f97f4fdd868f68b390f387a44f84dfe413e05bf209d64d817fc9275838257e2e4e585e2a661525ba3437fbbd334447e526bb8475d925a869a7a02e37adcc656eda1b354d71da5b6da9f023093f08f8e1f787a591265d06091f97468e805e3cd2e408fe0f928b49d7e2c6b738d05310042a8f84e11b317204ffe79b80e0d3d4b7645ae3c209f9ec04c1fff920a0179f8aa52e2380fff342402fda31609a2add7cbe1444fcce1f28d8454569e813f26d511a9ac187c56e0bf6eaa8a87fa828a453616904492ab434d25320b96af2fd8a089c02dfbe885cb176a4c02702a7422c9ac044a657c8148b2aaac8a08722f2f320297e93345b2ab8a3aaa8163ff42defdf917d82484167cfdb07bb4e7578d5a452d146069d123dd821b90a5ff456ac7016e6a65db2badd55bff219b62aeae6e4b46e4eebe6e4e474506e570a7dea1ace0bc60d23fbd35be302ae654f4167fb5e19f8bc2d0b062aa3b261e8937f481b01a755a386d39ae12b2d2ea7c55bfabe2de0f3b670ad0a2a72e7dba2560ca1c4cd4f767a57b60a8ed0db02ce115e999be10c6c27b462f71d1befad686357489af2909dbbd1b77caf7ce83d24bda39596b2032b3b2eb274839f079ac225a87c213bb2197ea139bbf0405321f854e481a644efc33baa9bf03f320cb853da9add82668fb0ad4ee811a93896b775c4e7815d0db1fd8ce367ef076316ca72bfaf45fcfe138543f257b2b8d27d24b923e2b584b6db7e9f6def96428abd2f8936f74b2ee1155f441c3a9722303ef841c6074b234dba77298d880ffaf1bb3288e8c3d248a82c796504c4077da9cb20e2834a413e8f450fde16d00a1e4711cbcb0a4d815e6e40114953602d6d8e9d725b8d1ffe0af4f84be20df816d751753aae31b4394ba524deacc4ffd81d5ccfa58a09dbbb5d5b97dd41f77dae277ade8db06f90e187b4e2b7e87d4afac5fff4115ed72d57e789e4e7c117227e581e095f7cb03cd2244858966ec02ff14053e097847c5896fac72360193e7e21e08fe591f1c1c7e5912641c607ff08fe7c9323d9717dc81648d21426696a4c8924eda86c18f0755d2516d7fa88a41503a697d5ad23c2000000078e1c007059000260a2a61db7533ddf6900a24dbd32e167eff72d2d158b1b80686371b857edd89c8a45474871e775ccd019b2ef11344fb72cad67fcb658f2795b9edba7dcef56e4cef52040ab5bdda25d27b7eea8cc8d470768ab8186f00062f734cc841ed12608fba5af7ffc95cbe3d44a06e38f5e06f85b5e244bfde0d3d4872cf5874f53a047f24053abd54b195bb9941d58c745966e44cf034d0909c08b08505823152a3bac8eac33cbfe42d2940b4953a4965488a4291612894a45459b9b15b2f49537e1d31c24002f22d05429b0a35a213b360cb82bedcc5261c180cfdbb2387cde561b911d096a763aa066ed9a4e7261d7891a78501e1d15a86c23404cf208c79a10a4b87ad65a9b001ad1a67b9aef115ef209f03fe467cbabe4831320dadcd617f09f1d15ae13034ab3843c04edcc80d680a2be5c3d5919d01c1235a24df7a00dd486ae1fefb3a5298baba88b037af25722bbc5f94095a1e8a83eb5286e7e1d95cacd9bab57e6e57e8f914126d925648f7d4e72df60d9544ffd5d253b2e2b6879f75d4ff8c12ba116d20b8c8d2f71e4300d404701761c800693074d0f1b7ca46ef801a4013b3ce086878e7af40313a4dbe17d4d7cae1d5d733fd7d744a372dc1d4228d0c3fd4f4569eab7649a050f8ee0a28c7c7e2e0b5c000319d0c0068670a0031ef800084220021f467092a0042638010a7e002288141051c10a5850a4052e788191233040a20a8590a9b556191d1e8abd07673ed5abfb5e6edafa7db5f3ec8e1d3a7a80eb7f0658755dd7c99434d0d0440d28140f78d0d03051a300052c61830f1f3bc80c60800e256ef8f143870b871c72d0a18306ecb0838e241c000108e8c8c10d0f3ce8502281094c400712427ae8e1880a5ce0023a7080818e3e29e2890993e97b9ee76d6003ad211de8c00d3c0002101881ef7742e0830f361801094890a4042738410d5000041034088208912254c00216b08ab8c0053378c1912344c040a5ba3210628821ee6a45041143cca088226280eb7f34f8922411c20637b8c155b58e38620d24729003359270b9cea0c4124b5461a28926d2e8810f7c60861f2c598206109e782207138210ca3084da755dd72494117fa8a8cc87033ac3ca5f0c90c8fe960cb87e7f427c2d2ae3ca39677caecfd5c980b8be820948719c2fb75ca9c883a7bcf79e923c22564579a508eed8e131993affb7bc89583711eb2b6f2c2730787f803b3b81cf909629a59486333755f156c5dc4745693c571f609a4ff1962b0b2ed7b7dfbd3fc6b65c752296eb2b57adeaca53f4cab57ae5aa6746642fcf9b45ac9753c4caf55db97e5c5ef614b8562f5f6eee9f1544a2181937518c8c463516a2588b8e208a91716b27b166d235be84ce60d164681cf5281cd6650ff434cebee709ff5281efdb0e19caa9ea839e49d07f1780eff7fdfb9db764a8ca14b873e7eb3a56fbe5a5ec2e8d50aed28eb9d9334f839a6d051acab9d93637f9dfeaa99f64bf5d9c9e69278d459fdce53d52a4049571895a5608e52a4ab4833ef98b70404d2211ec89e8073352349bc2185ca953c4cade0528a953d4ca77092ddd12376fc7a48b754edc5c915131eb3e2b72511aef641792a66e98bb3cc7ff422bda8c6fc57ed155021e41a2ef20464fe466d28b1ef438f0e7107a16b06bc50ffe19ca8172ac656e628cc5173ffbd9effb44fb3d885fe6a4634d1cd07f65b803815049822e4f507349879aebb3945786c3bf417c942608fbe283fd2c8f9f8aee1a919dab6342447621b25382cef87f24119cbb252e984f91ab934f11783b572887f1b5a00f459bd1b3e2799b8e4df83f3a8b5a942609f8fb53e4126d8200a24b229d597003614b229dc5925219b03c55501f089bc3bfff919eec80fe15d41c96ddebe60fd9c1ba15b273d2c93a2adcc4c44d5e764bdc245285aab8c9f149c45b35e94a110ecd6b702b88664e20504b91123187ae2c9974b44cb5f4caf34ad1df8aca50e1bb176312e9df64dab1e374d8ebc2708cf4bd299f8dfb6ce8799ee779c2da2f372df12e12b057abc31c5661d561d72645ccd635be448a463519bea46d6d85b6b5141d133989b9c96bf54ef626038baef117aa67ed2f98137c8a62cee408d861f55e8c5dedaa46f07c8b36224845207e7406df66ec006103fa1f9d3b55dce4b95b04bc7276bb9870938772ed12b1442d2842392f5445a4f21adce56f2c946be960d52d9a8968a77debb90784e6ee71a0b92b475a7848b20ff7e1f75b4413e110019fa259d731d1bdbc06273d46bacc4d54903e231dc7696edac2bde6a64ee94e6e144df0d9b8ced5b8c6354e84f35ccaa18fa8346b3578591043866804000008b3140020280c0a87c30242a14c52d4e21b14800a7aa852604e9d4984390ce3288a610c424419420c03c010003032246407846b54c05b1736835bc1ee4720484f75c9ca8f413d08b03368dee682fc6f0e72ebd2aacfe7d8240e60b12fb2a29f648f720d38f8d5cc1b9986e09a1724e2e6894759e436eaa5590e7d332257e0de0160c902fa7afe77088d6bd556db59bc86081544b152d3d7678e7b89a08a25d064cda06c42e13ed9780aceb9910a777ee03901e9694e27d0398cea45169eb2da8b2108ad7db90e478f89fcb44f4e50189e437d59e30aa28f91c03343ee325c7046301069aebed4680017097af936b433c57a2704e434be3e381820f52569c1d97ebac954862f9a7512f858399a67b2c915cf4c24981723c158b77c1790ffcc89df298487dd0c7e4d93b20f968e8b6b49d1ad85db963e4a07716ee4806970bb01f32c5da4c735e20486d8ef56e0cb6c684265b12e9d8b02346fb1f9617dcbde8a9bad1080758bbf34ecaded7d95e0e29cd60238f046da22b7b905b88c80486dce3b6cd1bd9fd7235fa36e200b362780e98ee1ee483160dbd817d4744ce76ce34406e8c4804e131837b855447fdb4e943c86693e6e7575c3709e28ae665cbc941433d406e710632d076b94d2145b92c271eef6579c1d4e9c7432c3a5bc8923393bbf13e862381a7f2c9c41d768146de852313746e98f71f0b3b618592305bbc9cc4a823db13ccfa4aa406481774b64bf521eeb186bb7c2c4f5e43f848627c4a800987dd38a1bf9096ec60ab882b26b7c1325315acbd582c96ba16f21dbb1cd4acced0c29b16200abd7826a3e04a2cc88247637ff9f00d608bb6bce4d2ef4a69efac76f569e13eac2407b5798653924d2a08e5fbd87852810f4e7cb37f85d1a1d91aa4032d98383af5773b25f7e0636bd5034fd0c5dbc1e230c3dcef03582a9b2e8a9f770dae3a9775e1bd3c55348df0431e0eb9a6990305572c9eb24c982e33947a2455f72ad59daa0c3af63f50b643c2060ff823e04dffcff6213c850048cd019bce8ae21829cb377157e57a898136961e74b867491e69e06d9a3e989f46ae0cc00e44dce870bc0f9c4376a488863c2a1720c2b0bf24784e27d100410764fce02c4943c5d2dba43760a3b6f21729245eb57d496a75d7747af909dc5bab80811a2ba12f5d82a2d4f35503f01a9312b4b2d73b462ecdfaccb42e73188203cb9dcb97cd5cd92c58709259b3649a2089d2771431e541e06e02967c9e81ec93c00e54d06001e2f44f3e356b52d93a20a7a1b7ced61fb181b73108ff14be4b1c49442efe1374b2377868914b06974b248f1f349659831f6be63827722001caf5e08469af76b42674e4439bacbe7b5a1c191f1d2ea10769ed0fea101386c761561ef5abdf0d1a9c0f28eac09becac03aca9ac72c84a7c03cda37434ec3f178fae9e581564364d0b09343840fd2da11b9ca3baeda510c6e3a994d2343d3ceaccde01c7caa789c09f73ca54621c32951f68e1b27d3d84cd9ed823e7a61d514949514e7f289feb7238898c187974b537064ce3b7781c382645e6c45b92a627bd8e6ac2fb1763b955f2132a1b8ae50281831684c178c54b4c805236409b23eb1a258587cf0916f2d674cbd6dae29e6e124faa4ff575e867f27aac393c44794431c51e9372f9f568e583795d3ada544ebaaf3f15e90297fdadb537afcc037822187019d2b7bc65088cc4233f9d8964eb171fa8c6727f0cb86f212dc4a009fcdea813240075b93a228af3539ef5151d678ca4061decf44d91d115e3bb3ee12b79cd09a508370ee152ae6186da1f5d6c4c4ab9154cf08a95d2d05d97fba998d8937c003045fb781805eb575c5d88e33028061904da71c9f32c53daec33ef6c9add1e9504c7729576933203ec6860782152dad881c618e97d15feb191e8c36c79a86773de1245704a92985a182f22e1f5cc10e5ab2360c09a8c7020b75f765d04c57c70e659606a13eec7dcf693a161d206909f7e274403dcb1673a6a68cc7db3082ede22b6e993f7727b633a0346a1982ee85b42d39eecde1968aafd736a9f2e33e245223bc60aa9df10330b32e6da409aa3809a259d67aa6bd00dd78fa0f86a3f394238d07b0d965c13f16add1a2f7eff484a30a69376da6c6004a324d26b63f0e38e30932cb693402ae27be42a3de48be9526108202ec992b809d87da6b15580b699a0ff65a7600014eeac4b5983ec3ad95a53d5b2325e96075bace0ceea111f7ce54c905d0d0cdc5ec7c01a5ca96e7876bede7b048e3717b19d9a5da101e4ac4d5eb535a81ebcdc0bb26ec7cb8496f2ad501a67130973dc2be0c8acefff4065e6f89a218731c07851880a3331e95bd443eee132fffa99effd69c15eeba7e50cf4ac3972f4e3c89699210c719bc13a85db17d920768c7dee4080e71ba76ec7cf38ba5e4d71d72f9010d08541272cf91eba96a30b25dc12e47628ec7d789fa7ce106953c1d80cd13e01b0eb1206ad8bb0caddd557fae2b941b2bcdbb365f515b624ba6a1df2a4d2efc15853af2a66af2281201b069a50ee8a38366b50500fbf3e0b45ddbfc80e978168f75c22baa21cd37c495e45ba7767c2bd132bb96df3a8da4d5b3439d9c19441a24e0eba9aedcc53b251fc074f899befeaca4b02ac09644a8cfa74ea5ecbe0c8f7a3dd8dcb5407e5b4c9110a0b9f548f01890337a73cd92cbab33bd06478e10f917fa53e91d27aeeb49efd4e1bb648d1c2212ffa125ca4471ca8b761da3d9272d84c34e2569831d679a33a269d66e76b445e64d72bd52379e236ddcc876d1a2b595b55ecef826d21a178334129779f355c92c4babd4c466fc01011e60b257566b661cd8316d63d36102b7d449e45392aeda7145d33a3929e8323bb6fd16eff3a170031b4620bdba132017f428f1453377237ec61ba3cd01613dc8c67581c10a34362045a843da9826464d3c20d34913a33f8ace54e69d3bdc0d8388ccd6bea95637d2d70e5de21a8250a055a2491f774f1394bd2a88bf8f6f6d014e358baf12051b272a86f6ef0b98eae12aa67b9206115a3d84097bbe75f5bbc642fbe0381f09a48285015a73921f9c81e1c20f3574871fde44e57030632737260b76709ecab152c85ae2d4a5cb1bebd535eb02ed60f5af200a938179c3a7974ac1d2ec2b64411d708ac28618e3ed1c00028e4d8f3819efcee5286caf14cd9dce58f1328b24d4133eaf28bc51fa826655c7c776921c16f9dfb204711312c0aa76504497e24d7c3132ca41698551fa8d29e9670c3a436d396b7605c20f6318c92a2c617ce49f25e635cbce5d23f19faaa06b8778513730e1f7b52b0de649eb9a7808570cd332aa0fdab83133ee9f26c6ec319c3f61985012c37b91909a43448a1f872f8ae05ee29487947e765e7c42158a2626d889bf4b21946e48c2fbcd433596fa35c0b5f3fe0d38d0527cc70598c93a6f07a04422d72f243a052bf90328c2b6bb7a1d29e014679dfb19a71aeef8830941d17c5b709d016ceed18acf190d9db769b66691549590b0adf81917db210e2735caa22a2584357d906c1b29a29017b6e82aca7758d636c0bae5dc0e7772433bba19d96c3ce49b0ee2b3a96086c33fa23930c12de5ada80fcb86894d68245e7941f5a6cd1f5ca0b7421187c42cdf2364b133826957177a0a80491dc45f8f63b5b1955188c82218501833b04918dedd44dfa3b51bf70cfa8f93125b52cd0a084de091f531a1fd0b7e52e513707c17d6237027d2248849e4929096102b817b025a82d809ee44340962267427a0498849e09288963056827b025a82d809dc09348962267027a4491093e0928096285642f7045a82d809dc09681262267227a0491893802e09482409264ef65e2204c199d827530e91222897ef8190c09136cecc36d43d74cf7a4aff5a1385526af652aaac1ae3689a649c9231380c9c7f9c0c2df773fb0761e0825bfcded84ca6c31233e961655a3a5834250d6b4ca5931533e961c554ba5830350dd64ca48b9566e961c59474583225a50d38ab13f8b392dca149b91f6e64c0bf94a71210522ac81d471f8d780a680cefc55a5c11b8c6bdb626ac4bc0fdb3f3eb079cd68c801d6df5428e47c0964b29b439496fb97e351030d725ba365e8729781c6fe79bb8034e6c58000c28d0005dd200181a795270a51263651a3f2a36dbf5dadc825ebcfc74a1d2a3b088c667175045a70527e5651fc0323bf5d3565768b5a9aabab53eb806818c2b8281992a7d63e99011a0a2d7f039f0118fc897f9d8c05839b6508b76d4e9199f119fc4aa257d6b888be6a9caa8b81bd0187460e2aa7a1bbeea3c3031153d4d1f751f449c8a5e862fdd0f2656652fc387ce0315afb2c7f842d781395e952a7acd1f43de42d00e8d695881f629c9992c2bfd5bafd808c455647e44438f9cd5796e4fb472afc190fb8327e0cadc984b19fcec278091542a1e36ac109b9b55f51b4a820c41957a9be7f9e746528f364fbe42c7514e6b92c1edea0c65401f0dcc54e9194b868c40153d0c9f818d48c5bd514c603153a16f2a1de60255f4327c042c2255f70631a105cd547b94bee1533ad8bcefc0d55e870f205ec015bd436940963d4e5ae35cf271456ccbe631c5ce250eaeb028b817aec86c050ec2e77c9d7f2e8d333daeb81fc400d84957f53a7c867c0056f40f25a34c8f2b370731810de94acfd347c0137085fe513ac8f3b8f2ee10135891ace87d7c443c8056ea1f4a871c8fabee8e6282159384fcae7b477e7267c9624c4a335fb5cf2933f735000e59ad61c053119c8ee16f6c50e3b0baf4201eb00269e9f9f0118e2f72f6889211058105d3f2b163db0545266e209a2948612fb2d2417a1462abad750490fffdc39461f05b43e083f001340619208898bc92cda03c570c80c93c85d61af9d0eb072a9fdb44690c9fa8d34ac42086246f5f628eb5a1b0c44b4c8c46b03c304202d011017349c9ca68e9744676b233abb0a158a6df0448f40ba952a57d397ef2795cf2dce547c079bbfa4a8f6e1d1245c03952e61d33b33dea009363e7142a6dd69901ba6daf59bffd863dc902b437411a72a224d1ac5fdbd13a42d18e827eac2d03b56f3249e89da0eea08d3f7761fd33599c5f8d1406c987a5ad98dddaf2f547ad6e4952ca5dd63fab294b0b1b9943388a7f019e31faf8e25d691c7241869d3bc2de6f63a8a6b8345267c44a900151860e45082f8c8f8059d16b47d9c4d78bd4dec7a6342b0ddf6064da018c1e3905fbbcc80b258ad665034d9f87d0773c7ea0bfe662d4b96833c882aa42c03710be25a140aca43def08ea527de9acdd11ae14ea2e3d9ae3fdfeb41d7ad31ea394f79c36aaba462b36d22372212a7d6ac5613e7e01f335eeb385c0c8069a367b47c083fc19d5c112646f0d6fecbfb8603002f440e942878041e0b6ba56e0ee3c9073919233a08e483028ad4889b882ec73d03ba26170d7443e403662c44d7df3fbd10abd4b0ef8a697511e15b8eb785175345bcb242a2d357ab458759cf4e459263ca6e3f1d64759836ec75015233600ac302efa52a4a552c39fede6dee2ac114de53ef954b50004bb121ab0de8ed6b16c55f71b01a8ef080eabf5e4303b76d78953b56ae54a90c13e836b0e000a727aa8b1f8140a9841e6c550926a59def9f28575bd6038843e5e305998cf2f65fded12f93a8323c2c568638f3a4487330d1a0434db2b37ae6ae0553e2f73636f2aa353f621ebc91e248f21630819fb6905777d2ec8cae10cca3ad4526e11dfedb596d0c6420591c212d7f560877093017edbb580d5fa35c4dd8d1eaa9eb5843854eeb0c38e3816383edf05f1526be534e0d84621c9cba3bb98f0ed6bc5671f47121f204955916e5dd14ec39e468e3be0221c2ec49cc6db0b8e28de8277bd97b95e9bf9aaf51db733c20376648a3aec031f2c1087dbcf7607042a0d9802386de826a3576fde2844a1e232508b6046b464f4df1a11b510f0881323d3a1176a4eaeaf0f8d488656ba7f2ddfca1b6e4cbf0c18f58f18827ca9d7a0365358810788442b69abec71b6e17bc010cf2e1e49dadd536e6862e4864de1ac523843efcb065e7f0e2c84d43e350a82caba89c259b84531480338fc946888d85d30ea2830e8941e45f064555b60356de59871e29ea2af051a3b733c74793e647a399220de3ae4004fd89d7d0aa4cdc1d2de482c1f2201951422f2de07865e6cb8f294447cb92de64e9f929150263d6c2d325a527b9903fdf19984bf79bf30b06b0f3b5c9fc26fda14d1e0ae863b725d08360c2fa09b758d629165e3e49e53b4ad54d2875974d1395483cc329fca81bec78ac03adac57ba2ff505749f7a4950108851502469089950625d24ab5d39e19e4ca060c358916cb38738c1f1e60cc219debc131dfaa7c44f06837ed50b0bdfe9dd4756b624319a9b450bb81d324cf9e041a3ab3f82112758c33979df201c1518d57f756a5beceac969117a21b9d9c03ead2fa6f59990f3938f575046f4a9e48f00a36f0e2d56a029b044b1dda8b8d321358c62c19031f3a044f01c157184d2073c449f9f3686b39a6f00e9940031402b80712a887147e9ac3d355bcf72dd5973f9a0b3e4c54b05684ee1c4681e7f45fbcd81a16e00d82b4efb0a52b8c156d7988e20c170733c5eb81f3a11c7a0f26a5c2072ab9b7ca16ce4716cc30b0264529fcfd5df97bba4d5c805f45e30435dd5efc576c110180128b777d2000c951a3da78111566f33f4e54662a3140d54c300201ac2eaeacc124c9c01790c203cc04417f5bf34a75d0d97830c366e90ca973f84767dce564e02f481f907d8111d370af6a0774242da520bc4a6a4bd74fa3182e901a6eef1eb33b026b85086e43bfec2cb195d6f2c1d4792507582dd990a63317198ee983652bb1d2f41ca738888e5dd8a101ac228eb41d4ffd220a2005df3f8f045e4f88bbe5cb6d887c060c94190dcf866642a5bf591c48d81d9979b68c24e244de7eda22a4e8ada49dc69c8c0107b411811cede95360a51db45e9aa00f7d539c8d000c4174d4cfde848ce8307ed319c103bbe3c6e313f2ed6d1a025934e9b64bde307c7a8db89cbe7201994867f4a163251068345251e8d9b0b68a4a226d4b728b203c9e64c17d1dbfe54e4633843e09e56a3240109792d80aaf9bd2ed1dfdc733f2dd2d3837eb166e8792cc0bfc5c637f0726968e239889a973e1e1e0258ca313f62649d82d450fec37e73f353c3e713a088479f776ef7832019c5094b09cad6eb0358c8320e81b11df31f848168e5d1ab2db89e7e7af7ebfa889c3aac558f2830aadea11b106ce53f52372edc6db8670a013b111b800f0e241ccabbca4cf5e3f15643a897036d6c78d9edf1d38c31d36746a9a8852052f430a3440ab5198ea62ad82c69b5b3c71931aeb5fdfd3b0f57a7526dfbdc2c2152c9014301727250498789106365115277501e8e8fddb8cab24aac5184dfd4238bc9173a1ff486a7f582c2ce8b92d45e078097c334644386b6b20deec3ff0e905e4045e81378f9860108d02ce681dd18502d5acb944552172cac4d2c6304d20674ee8fa444d2868870d352f7ce3ec07df58d0f0ae930bc84f6105a9956fc9ebc02be7f0124a342a835764b9817d4984f62393a078599766c5d9ce31d59f7dd9492730ed16013726d990617c974c22607ff7612235547ebc045fc8ec1a20af6cb3710e53b8add9ddb021392a68950f06bcfedb07c59397e5f4bfac636ff30d6586e606ec7888d9e89a1f37078c255d0b3d5eea245b4a39f9b061e458548e565f7572b90c8503b8571523eac5bbc30ca58696060c3408b9ecfe22692f00436d59206164a8658b0ec9c22632bdf78ff73c430fc12fcf3ded6a0d57e05f3571630b8da988d39a78b88ec47b7225b78bd29f702138f925b572d2d091174768a0cd378c2756b8334534cca70be1d1eb7a3f10e2b7c568a15085003b27bcd4e9ae483f8d891c5c8408dde5f8661be7dade9c67dd6b121673638097b207a73d6cd3880a81675fd260d917e1e0ca9180c494b3788bc852a961d76776cfc94195a713bae7b61f3992bf8125aa30d84587b144dd6cc23dc6505eaad81ef9b80becb9bf3f5b5507e7a8113ddd6197566c8c5175a7be4148e5a2fbbb0d22f00ea78be561d2fafb89b803893d48057512d80bc1894715a633995843d97ebecef5d94d3946a21cb445c8b54d20b7b85a8cec17a0caf60330647f229ee82a5699bda7e3f684f5c83b90a3140c6a20d684880302d41ea2930a181f7a3fcebf1635a0299cfeaf1ec83ded1ac089042c73e11ea9aae38b3377f263fef8af7df876b9d26dca6b57829afa5e892684df70f721ebc3a532e29bec3eab381dba77a0a5dae71232f6dd32cfa5a46bc5f80b0debd7fe7080d6618637bc8e541c625d48de1c5b6aa05a639208dd3df38cba1043a413e72e2aa4e4c3b56f8e33c32a215af76048e8061c2617883c777f2c65c47a1d00bd97039fb8d8d1ac3f0c8a76b92d8264231f5eccf10a8cab6c256851394969079cc0d1870ea3e887ee4d357e484a2c45f2bc284bfed1414bf1917fab63c8902968a183bfd4ffe0ba6df7bb43c7928cc02e35d3ff442fa24f27079884c2a2fe4233a312237dc29e0769b1f58f1ce8a7b71a5c3a3d9a1461ead823df0c70ba0e311858bbbf256ed1f0e0a1a79d70d6bfff7f0e19567a31104562a5fc1d9aa2e481032dba8609f56c5d9106ab472b3f0b63c0295c94ef1f8590bbd40295aebf2766c05ad478fcd2e6316e94db02af5b5236641c9a1761e7c5108d02596d3460b61fe5efccad41e0f68fac4deb2deb293dab9e8de2aab9a5a5afc821350edb145caaba650b130eace05219d2d8b6a1d381213d293d3532a36d801c2377f49bc5d14596acad0ac568a6d37332e33bca10fca4d5161d7a6c02fad995608b9e7913382f0ad0b830fd60b5a7e8ad9951a51f8210ea80eb06f93796140396b43560fccb141872f718d7bb25070389723e4a8d1d1a7e9f5799796a533deeca9421c254e467a02d21974c30a5a6c630b4b19ba9ae650a695d1208b4c3bd02425b63657db79abac0c53e23a0afa570183f1349dc13117e67dfd911c693170fb6f770dd4245170497f7a26b1669a10f19c448f3f738b4893eef2a69d5c8178084077eb1aede4e297f207333dca2c4c462bfc1e02640d17eeb3bf87945fa9b09ff062864093e8914307fd47f13891362959724ac656c81e1981cbec796d332290cd302bcf67ce71d275dd46098a70edd1ed493e0670959b52f661222dd858405523c8c63214642b7b449288e04c2c27624f739838e04223fa923bf9b05eb9905ac599a3d7841bc0796e985ed2ccf9cb3c12ceeee8474a87052f3206f14406bbbc86d3aa5d773843649c03225c15f91d95be31b0a6ca78f5a756494d7b1959c474ee1e355303c20e67f0fce446d1bcbf5b8313ed4b07d65f04c5f2cddefd20debca4df2239d457c33b6165631a8a44cab3a957bb430c5668cbae93098e0dfd702db67f88fb0ab46754c3c27138a527c4905eb18650951c1c330759c40690ba521c86cf54d48f998cc846d47b2e140285c0ee603a3e4b0c4cf2d2333b66e4ad24e9c4d9f24df73d286490dcdc1f5aa63ef78a3fb41a5a96374b46acf51ee82fad266de1f3f9c1fcd14391e66594beea145016986fe8294fd42d8701d27947609f321039599d53e8be0f992cd5d9d62a2329f30754f6c7a7e42bfb825f06013b152cc8eb0f69e50e1619e148afacf94b19343a141208aae2482a070c3eca3e0ecd1d1be60b38a0feb0f39e4ed7ab6d9510755d75c0ae447bfa94cfbb52b35b29efdcf07567deab322f4ccb50fddaf03c56a57f497c82a1311341e4d16ef15fbd007c17c7e0f5660c0924c2ffa12165a1ce34e7e7185e12c028fb51f917eed0752c211fa9e0108afc170bf6e54fa9063fc0a7ed08825bc010337380e09912dc8de771185032dbcbfb884a266132609f8703536607344f911542029d887be24df1cb19a82c1610dd135e6dc403673986003272a1b720d0023ec80c9aee856c6452a66a07b25dd5a3760f64ab9182b69dddbdb6bfb4e0c8d6296212052c202b8ce63c1ce6387a8806075b1bb250e5de4ac23871f3bf2a6e02f9cae418e39debc7a2ec39be6fbb1da6d3b7275c0e04a7044bc6218ce34dc7cdd2a2b89032d8a88aa4068498c34681b47e3125ebf3168347cf61537a71de095eff49e73abd60cafe326a71f4a7e6733e6b0a80f073cf8b99ce88271a54d11500add9e18dad6a5683d9305da60e8730ad2069f2820c4d6cd1a4c224e21abddb0d66e3c30cbc582915645b981b05f509cce8ab880e58842cf99fcf0a5c31ce5fff3604c32e6ed19a52609dd7a8aa29565f0e3f496ff6be3851d4dbf9056508234d7040238a489f550d1fbd148e38740f4b69adde86ae54ff7eb84fc9c4f50069a284ddf755701f24beff5fa94a03e0d32e6a20ed4eda50b24e17a87891a243c2f180fe7039417e288019cf3431bbe554079ffcf92c93c203e4030a7ea81a48a66ea1a803c87d0f248b3677cde94b7893ee20905bb24860b2de918452cd210a0ff2f47f86adc402819dccd261f09bcc44dc0980771e7a31d6ffe134140763b157f316991fa142c9f8e9d4014267c1c498b6527b6144c487d17513edbcd6d6570f5a81a3199750cacdc09bc3269891615155590c32300a8abe9f573ac1d8955771a49416276330d6b5cb173783a718ed4ba1cc3de83b65f90438bfbbd1544d1210884e262d7f8fc1a44eb210090183112b2da0221362b1de676aaa1734b0ac7b651fef3fce58d26be62c1713b5174e58e12e194f675b1c969bebb3e9bc55fa27658d856c22904e7e7d8148364fc30fe44bf0fe28ea5a5b503e8c0e20d4f719412f14169460b607f3c8dabec7f096c79df7722fbee769d3c8a60c59b70ae0ab10641f83c3c23f69811833212b20196c65b233aae7f86e835e0fe8e8c30907cf1be7aa6830d265cef265d15b2193a1bed855f93645e7cbea3dcafc428bb5ac7699b18b1de85f3506bf7965b8c166867e465279719e9538234ddc1c16ac0a276686f9fb89ec77e04a7d7ab3449fb107f94d0532e1c08882221fb66b63e0808b8f584857b30c730f77cc05a7e075393b4c0e34b681f1d7cb4759f7bdb3fb02f46934454e12d959094d3b228d084d388e52d782db82fb2067c9355d4b45f52bcee8286996ffa033793abe04b51ef18acd9e9124d87ba3f7dcea9a8867d196ef0fde2d8c769db331d81f9ad58a22de8c3648d6738ecde9f3761e35d8fb728d7425da8225785e2cfb7bd2eba35ae28fa7064c329e12d55319ca2c0ecff686186c31aae8fbe45d60f5bc572af2e6178fc25e4663abf12909d9777c3b9a40605a770759d20b9d89eb6046e5f81251ad2cbe08ec3cb65fd6e62b191da6cde52cfde54db58c5757cccd5d9fdd8331f2331cedfd64ffd120249d6a1413ef62765df55f64fa931ec036d145de0f00c90f9d7977229c9f95ec932ef35b82def5acb602cb550cc7780160c26643d2463717d0108150a391119a99770ddcbd0e94fc2651aea882efe3c44067464c4d15893deefc86da3fc910ec7d9c3e7331fcd63e8be63acc4313a7b7f3f8dc932582f1db2cae5ba910675ad48da3bda30c192bd0af847504855a5595b6d6c5ea28cfe3c0a3298d552f7d6d65f1980203fb55c05d09ba8377700bbf0950c14f23911fde75489f1d85ec52c62a1163bd0df899495753c02a3f2582976e588197c2acbc8cd76a5768208cc97582885cd36245f0f022b976e68a60a628e328d23dea90789b5650b72e40195e035881c4ce155e7c6f88cd42488e59c87667f8f8515d72a2da804c36c4ba2ec910e102db863c006c1dca502acb6bd316258f37c61bee806c7a9df240d9d2a3128ccb9402ad3352c4f7087a01503c354850eaca5c6e1b638d62afed08651699c15c54c1eabca5f76e1cb3a9968078bc27bdd68851e4925ddae3384d3280819f283623b00415047795ac6ac9e7de2b015d913e560e45cab2813285914ab42b8c93d62602e46acb63a3edfe346d31c109616647bd10b225e0df1583e73b867c15e9b9e587b8ee0963312ee4f7fb229a50e955ae41958a586e6861856c89e4745ac51218981ec1b827ce1a711c5a9edb70dac8bf813ef066a638b2c26f62222f41eed29fd0381494867d5e83bdc12024311e9c0918cd40e2ec3f961e4efab56d9a9bbba7963cd5755982a93fa916972512420164d8ec36aa8d86656d731d0310403452aae25513e98ece726d0ae04993061e45d6cc903fa81d8f86fc77b0ff5b3939a225d5915c6ec9546616cd0059e20b068363434664fde58bde7b491654c0c7f8046b2830e205c3a3db367620db14be4214a228f332962f084a750e240d6ac866405dc07fa1622c0b37ef5aaa8ba431ebbcf0a8d1da8bb0441ea1b787b80e580addc63fbbd3f642487adf378f995c2c4128cdc34ae177a56f0918747b29877d1a6268ffe9c4b0922ae1c203f2754b1fdaa32ec498506ede0065f585fc9323a2c1f2ab902259517b8f61d90d3baaf38d30e7b87e957a51e0be55f83b8bf37dddecff2c55b407c10821b57e627115625eeab4a115232140178c4a70b04ef925a926b01ab09ca2b68419580bc60886effbe4777d648af5f00c4fe76f12d8407632bd276ee9606faa88a36ee9e45c16caf69c496fa23e8d018f27fcc2671340e7548fea0d50f1d6f08291c8ae781e90704768e54b5e8fbd576399b58f6530cf51fb28ec950e35a7c4ff0ed45daec2ff1c4dde914e2708cd7ee0bce83f8f0453d077c61a9fe91739433fba8c83fbb8a2e78d4f5b677144936216ac51c9ed0b41f0930853e37475e5b7ecb9d94648afbd57d0cffaa0a5de9ae1b01950a87cbabf9ad6ccee9d6f5a2060916fd51982924063d687e9440e58367a906883b63390b85878d0e39a4a09a917bf35c897befd1cb486072538b6c6bb02804052070fa50fbfc53070e6501c987ce78f9470310686440fd5288eb571c0d54201be8eaf744291ccf8a2d64321dc3d0f10b4ed002993c18cd4021152380031d75e22c05caba12ee4866aa4a28aa06c06e6b935129c8da5c5ede70b98f07bf07999a5f1462e9adacace45288f0bbb4df00ea92db2a62e7ced8206a35ab73c7def8a786bc2e719954360f1e1b2a105078449ec083fe213e87916b2f166a11bd62266d1064cf634338440a3f9824a702c443da66b518c27fb7f16e7f17e5f94f0b611438413ba1fe7835bb8953c38023f1756549ffe39cdfe2138a8e25f05b133ef886dc0958793770d4f2e9c1d97e2482926dc7e6d5e2193a754009e4319f77f340c281f13bc25c2e18d70115d2a874376dd9fcc68a2600a7a204995cf26d6b8a4e03bf67c84927006d4c261ee0764992521cd7a50ab6da421cc4a83a46842ca58e560f43335890d741daadba711d2efbd266a7116988de0c3c4a4e087ff852c73a3ff4f123145f82b6e8247caee4ed087e34e4043823cf4655a6ec84d4dc551568721798421fc287f297994220aa430d3af060ef3acc9b9a3a31e621813b63267a3c00b29dfa6592b2290565aaeed3519cbb0b035c78494d4e603b4565691b3f8552e158ea4413829a6cf65ac720cafb18919f6a7524c7939f1da4abae9032ce95e3eaa1721bc327145c17028c4e1ca7fb763a4c9e4f6199a193038662c6642623644a0e516a6f0549d16f00c662cb1083824b5eeb823af166826659765851f111ff271665468739db3c3c657ce289de2c6aa5bf810e1a24c80eb169f2439e5266bc3c88c847bd501aa21529c0bee9b2b5bd989201a60d040b95af421101ebc0787ad27bc80b3c38b119bd267a1f24096b18000f13f380b65a4c07c18430fdd619ef547a5dc3a381381c63213a7da261cbc112d478ac801bf8ee9e8e4ac5b2874fa83455be249a3a835c025517f6a13dc5c0f918814e599b23268d73c176e02c8bc28bda2d107c06ee43c9474ae269b1ae18d4cd1852aef2bd33624d68e4173f730ea52370dd99281d91d54cbbea84ed0aa09fffda065080bbc5add7d029bba5d0c62f04441fc906f2704dce36a91c27fbbbcbb069709dfd058d565ec2b51117e5e5fdb7f5c3fdb670ab94164ab841a346aa450959d04b32c9d854370a2a9723296dd93ccdb2ed5ad0ab3193a44ddd17664fe684e8c21c9b6305379f3d6abed9cfbf97b2b3bfcc8b9f07095e1cc191f37c06abcba303a5a7a3671f0789cd5c4c81a81abe69c37d330a45a41860012ee703f5ca2beea680de69642a549f0e5ae44a2f97be98b341b1fdc3c5266b8f9a08be3bcbf8c44ab132d780dd6192abdd2afde853d31279b311aac448a6068f31e63a51085aa8bbc5787d852eb25388092da847354755a01bbbc9e21080a3c7ff240e1c25994046001f24cd6cb9434818e7d8c7ccb807710478b479c90097ba7a07e0389323d65445c4037aa4488b49d71a79b67c91fc30833f6205a45b921b6d82ef28e2675392049b692926e2af20801d05b446cebd3b20f7b3869b162c10c6e1ff0cff1bdc748ad2379a7109ec5d4364d8f99c782bdb3c182105d119c48182b1e65f3327c654b6f68e2480698befe97de46d81c8ded7467e1b29acd660a433a22ff4e8a6b7d980fc040b43b701a7eddba03f61f1027a6f2422c8362c21fa88e85f03dd25852ea78bafdc77b2d695b346084cb1806c096a1a5d57b89f14acf50b5422159f15cdb87df914c8e8455be21c10c6473a8ab19436f1c24e912f8316a8ee4db0eb107d5e4bc46981ab6f5d6fab513d2b97c4026166f16d933cd709eac61da500ef14eb0b5c0410d4ad63930f9a55d25275958d892b6890d6f7065911baa28c047f2da3012a42f228326a7d842eda6ffe7729dcb711c109dc7eea57ba2f69ad07dc10201aadc0da9610eafcd53f8a1809a7a5ddfcb429adc65ba1ca7bdf52190e02b7e1507a33d1a0f4f027378319a5b01ccdd5145dced6b5d6326a9dc5c7bc6ec67b846f03383bb43efb4ca94507609d7be3b2a43b59d4ed48e5fcdc457c3587d6767e58704855f0eb16453a237d4b48c64b314a2bb6043090031840af1421f7a88c2630001379463051649d282d1748b7053eb72559d617a085a62f12795bb2e21c2bc0bc05fc14b69021008a54d5256d1c1490fe4df025b5ad774e18ab3fd6b618fbdc25d5bc019a07872aa964c24208853f8c03899f220a0b69e0d37012764d711fe3267829401a581c82314db1ab3b0b2bd2e2a69e52a39d5e4a0f5e4465ac4e9d8cd2d9552769249d854ece14b5ebdc6c2b49d78016111cfd097c6d2bbe6354a34207c87550373d30169b4cb5981ce7cc1e51253cb45d04e6d0f30c2181dca35783d8bf210dca7c4f313fe8bcaf0a0d35527892668c09c1ddb0501e6c437cf90de747530fef557a24b83035e928d8b70254594e3701ce9c46dd37b639d0129dae1e4652a1b8dd0b656029e61834e943fcb12d8b343d96e53c7a113923813f694d2ff308eda77115ea25e73cacf4b27e2db5df7525d59ed38f51f95a0cb70ab41143031c837de77c4048e410961dce2666cd5420a21ec68b9213eb17ad8fe9418058d93ed607131d0c910a9bad14508f207d545bbd1dbf00d0b01660583fe775880f08c91e87c8b85dc613ec54b650ac99c36214e3b2166272f41b4374b1293cdce743bcf50e5d80e8e29b9d368cde404d7793c6f1ec352ce7be7ecaf06456ce8912d4cccd6fef22052056a5058f3edaf7e4093905f99cfcbdeffdace54498064f2c5ebc0c6ec135deacec70c9b670fda471b750999b7743a8b3915dbe0eac5858c3c0a7c997638edbeef9da372fc2c33c5476e47894e7b1360c4c6f910f797af0d9f7856f907c82d4c918c1e52e70efb6008803c1701a02e737a0e56ad1b2919860f21ed1481841c9060cfe7add2110d4395818121a1ae4b061a1f328eba11d816b29668e44feb369fd4c89a20763d08d7fd5d07a7f9b71c8b177df36450862a31fc5a063e63eb2ed12f25d854e62950cfbaa795705e19f76179c5cf3908603b03df7236beb117a2b1fd46d6287f8c41e9f8782dcbedbc534e0ae89c8d3a5797da001dd0ac573fcdf9dde75615534e6953b962e7884fc9d3822434bea43979178d0228689498b6af8709e4eb7ddae1db95723a6a5abc4fba74238d3122a04bfefc98d37180573a0c060ffc5861afe87888656b974a8fd108efd5fb775ba170bc7adb324b836a192d01abe5b1eb9ea4995b6aa9e0855c042b66e4a79bfc0c0485726c0e8555c32d48dfd0742a34bb34870d0a4a4753cb03e4ed838a52448ac4d527d22a7e40e2caa2bf87baebce85d2ea9c4dc6de95d829fa3726bb6b0ffab9f34748bd4f49707fa8d0e760afd5a2bd9e6179965f85a1b7e1aba853b3c76b90077a72d4b0d04e448a8d79ee4006019afd1de80fd7702c61b1a6cbe0b700331f48d8b69fd03aae3c33313d7c74b352d124458143bd517026b53926d15925f0a944e36ad87e5e89e7ef9c712de7605493443cb505a14a7f0fe6509faa8d4035d0e513de7eb19839f4ab9897c65d9c484150077b6272896be5792f0250e3670095b67b4584ff7aec652b83cfd6a400fe8bdd7ae5412bf5af50c8c3fcd38e96a9ef9b75a166eb4b1042b7f513c5d958bf0307fa39b64a9b1953923a8398439a2e440c4520853f0ca6576ec923a869d13d6de3373e9af74a3a715d15d66e64c15a325dad49e6d4f6f7ae4c8a76494b8e2ed5cf070a2614c2b8bb1d3cec688bdc678239d302593af4de8a3d4a1a3039debf3442236403725c417e06e129678401b48d1d07f84af837037f542c04bb4987f424488a4ea9837c0c1a3b34a148800addc64244059558ab26c2555e999be7c6f1302d92370a0d20f289a81fac330353fe6b12254e7a57f1b87b9bb6c69309a97aa40b1561df699b66be1f304dff6c1a1dc6b50c699e5eb134a96888b3d5571e33430e6c80a084b8d3a38308757c401d6cacc0a6f7cca82bbc6ea08289804466f2ce5effcc6897c31385d2ca5991c37b4f439c0e6a610fa02af63d5988979d8aa095a88ea1285d4ccae888129519ab28dc5e38486bd01003481e9a43e4a27800c2186a27d34c231a36892c87fd46afed57050357211167161b96deb325250030c208a345cbdac944a425cbf2d90847906002840a24aea640df360c634a23cb2517d2eb8f71998aac24d34183202c52be44e909a21409bac7c5f3bd79dc7c5436163f4f25a352fd39eddf0b7ea5a8787bb940e8ccdf51c7cb0f5f4f2210321e44ed2e0d9d72864212e362873093db9ef37e32cd4eb40c27489267fad241b277de090c2c0eea86a9fddfd8ed4f68beeb073a1146f068b7428d51f486873a4586bd302db365fc781a73b9c471babb6b200fdfffab90bd1d196fa00b7aef33a83cb60b25a203ebe7bc4b2767c7ad18f46708d820419138668c03429d3696856421cc692027d1b200504dbb9f6ce8e60bec48e1fce274708fee4c5dae77049852b210e3f3d6d0827988de70ee544e97ed08c36fc99e72b8a9ce5e3130eced7a26bf609b404426e5c418b22d49d2fc1baa5a11fa3e63edcf14af91ec8917bf8819354dc6d6d9fc40bb342847c0d246cc971e95a3f128050a995a8e74d4feabb9e88e193a4d9b143cf78da34dcd2523e72f9dd13c4b6e300da9ab944e2e2b3f2a4d1f49780d0b8764a5a933b9db1310e2c1e1026e6ad6c58cc5ff59273cf4f355087994556c99af5a539c6753029b7b75cf19da96a3125a23def5ecf7186d2d58a61e43ccb6c8853de7c8cc1c2904615de68d9a7ff37d9e309071b69cc6b115448c8986f4b06e7cd821771cbd3d893a0baf35bc6155408598d71540839fa6d14e3607390e77530698ca9524bb9db4ee29afa9f01dfd0f4f63712e38c68685b485bea183b49883104cd7a37331f07e43e334bc581f4dcb99532617cad4f32e504cfa0cdf094487d7377073417fda00037103d90dc17e102630019101b6d8144da37235061582c719504ce4838e41124981cb96e09aa7dbbf1eb7b10cc420de017b11d285e4f05373c95a2f0ad2a23341a63b836e36e166f7be6036ea463dda886418cd2899bb86ad1699644a8221b3c11f88a2180a008f02bd58083c9ca070a31c0668b66499ba694e90631e41e20206e9661abf1ca6a37a30801bd2bfcea0b97f8502a916de99c65cb5ed7cd52720643b1aac99e59fdab390096e55331fe6941c0e589f41182e400a06ac3ef86d3f075370e575e4fce142ada103dca2b355ce3338980d2ef29e0c391b64d2a1aeb11b7234ddd5b544f53380a3135a66ec1104a3a9aac4f548f458f0c2210e5944d4a613a4d3f584d321abe011f5e1a3b0d6042513e633d3802adbed5d9954fef15b189e78e9824a08d68d425c135236c898728b41e5a275562488170123b632afaed86d0a61215f08c5356d5261096c1865c485fcaa954dfac17950bc36e996b4f327e7033b8fca01ee935e0e779c9ee3c886e284251ba707738bfb6c8cf137050ee80dfec5f1a14ba43fa2ae27437a8be69ab9c2b6792f9a71cf21b310a433b583560d944206cafc2bc8b61614c3e16718c6ddab06d96a308f8cf8580116fd84ef2076cc93dff9b7eabe979d2e82c31f7319e6fc618b062c29d1f44383be866c28e284f59611ddfef647d803183daaf87dadbdcbb2290f7001b1c9956e8b8041c8c786457f01f550a8d0c0c5972c845359895271b995f530dddce23441c538b0f91ca7542ca6c3902731fbc02f7e4125dd8e8db24a9d6e562c4a89d441216e4696eabd033666061d558edf58d6f5fb94f2d872a315dc1941c3127f82127f0434e7482156687f423ce08ced70a275749e2241ad1a4d9b4cbca907b321e2b64b295452c2cd6d3c5d8429de163093e3160e694022a40fd03d84d3c330ebaf500becb8436aa7b2dc100e5688ee418feaea0a4b8001caa02d66a10b980ffcdd55375aa6a17c633c488871c5297ce85606534a2c7bf8bba085118622c0ceb1e873aeb69e01998c19a5fb7ec09473aa0c3e348b81ac9592c0ffad8c2103ccaef1b359fe95161311ff12617b4c1a78c962d584ec4148476f5dac04772ec2a28c45e2d6dd11d62900ca5514b6c2e982549490afa305aa4ed2e6a7fa63d089a4c510270bfb4286564031093eb6bd665db3aa3b8190d22bf9cf9e900d49abf10a89eead895249721bc3854991b2ee8f044a706a527ff8cbbdaa97c824abfb89def1deb409670a138d9b29fb3bedb14ed9f4f4a805879301c3de9cda6d02c3e89d7bdf9a1a87a2391125eccdf2e34340bfdf81aa880bd4949a5798f3ba27fe2ff998c7c16969d048d9de41e30d23c09559dc2efaa43c5d99fa4a00635e5c3bf2d4f1b37f07b33609a3550309258995937015e16922ddb15d265a51567b003204da6e3db4f161cd948dba1a8771cd049a48cd19529122f382f071a2652f56df86f71ecbc07e5eddd0a336b94f0784fe83843542b774f11701131d41e2a8e7402200b756cffa04a9555d30a3c99703b746ef728fe491b508c066378475e2ada6478550da06425327b77767be0a44e00ca9cb743e42133617800dd3ba43456a761d9a655d9099c5f11fc129b1b0d1257164019545ed492cf87e0d1b56f1eb3c2eeda1c1373b3896af229ea9cc1237b02043f180c8a447e375cdfec9c80a224ac98b4522aabc911a57c9c2b06266ac0bbb78d53b92bff0513deb3dc480ba90d8d2dbbf766bf45ad5435c6aa5b53827212275c4f8b2e0a5f306e70c4a82606847e0474d0d6d501627067f1172c916aacfba2ed98187005070353d75018f030d44b2b8a871b52c107e9b9e725bf6c91cdb6ffcfc6e21ec6f31374c9aec7d037e15325e3b84e93cd5fb63e4a6fda0dbb5e19696fcaa62a29518d5b828b01c6a0a34f0e5463383454d3a6c3d9192c59b712d771a4c69596c62f8a78a1516b670a10ab84407bd589ac14311cc9e0320959261da9297d93b6ad70dc22e2d71f3da30c821f0dfe5b0db81af085b77b2cbd606b5c762cfbe5ad8315ed468bd71ab850dec483480106a75448145c63a2d867574120ed2e41d56eb7347ad836df8a8604487a96d9be389d9e00e1b0d86bf2794916f3c25ef742cf4bdf0294a59ff55a2597d3bace8be19881ea1e7f8c4c467ff4e4994bd308d1ad4f8f129adec6c6c508eae44e38d0378127982209c0ce963c6623c2f8c4df838359fcb1fdae9046dc6ef1c8e4fe7ee56d9fff8bc28b03c24fcab2de058d8640b1c5d2afe4f802ca9de700d9de5acba60893fcf6427aa96a77699f3012a4aa4fba36e4d814c0edc4b2e87bda9695c70fc77805411aae01c6ee26f26d80b82fd7b29441bb207e178b224818409c5f9efdd6f93779bd6acc251370b144ba56bc6f139bcce874cd9f05ea43c4ee3a438525e82cd9d259232e71670c89f3f9c79bd6f57d206374493fac549ea687f670e8115cef41632dd4f4075b6290385f8b08a5956e22e404d043c02b065a2bfe2a449a1723061b1f85518f86e0f7969b6aa0919181e1695b846b0ba868a1e71416238fc82dbb0e8ac20e1234f50abf345639908d49fbd3dfff5db6e6a786e9d0f45fd5d3fd2f9e49952ce271a1527d2ac711ad8621176b928634a491c0d14c02dedd67c6586237b4000a578c0459aed1cc26907ebcd89620c1ae57a80093b56ad11f42b20b43603e25fef061f90b18abe5913bb3be060b05fc28aa17c300c499c8e69248dec56d604e2f9de1ada384f76c5694323d8c80382bf56850e508be09aecf8844617903928829d65065a86bf41561e39ae9c3da3caf9f281c9d18b170a4b8b1a88c256aff42d61250ece449529cf888111b9a7234791a9b35123c1c66d21c3a23c89dd5b184a129005780a01d19428c00a916b6cbfb393439400a6189d6670bd6d2f497ca3b5ea082e043031dc40e73c3d7d159eccd9a6c57f0bf5ed867729b0aae0bec041964f227702405d75101f5c2a64072e14545606b9f2e39d5b576268b730a6bf9e2c0d8be539d431a65b7a41469a21c73fb22c9b2e798af8b313da6b67b2e3117f0a60b0e2fd2a39bf1c54ac7a901ec3a8a2c28c9ffa7357463f0bea17eebbc09cf0512ff3749b44eca319740f13fa6df1601684aeee2467ae3e725869eb7cab91235e4f017b505acb73e2678901985575e5313ccb8a265d7c87a53cc48c097471809ac46fc279450ad0382d7e9346bc50399811dc4503d3e8f8ac0d18d6cd0cd6ef6877bf75c23b761774ef9d81243d0182f9efca3aa2df9e07890d4a002f87c43be7ea37826ab1f7eb026a41d95f99381722c6c33c6556072d0af3ae26cd9fa8e5502bfc085fff42f9af460fb7374059930ed2fe63bcf53c2df213a87bf56efb2a089e917b90e61ca913720370bd38c91f3199b377f281853c36d48add2be184ea59adbe87afc86f58004c03925fa4c4968799122c8476c7e91bfb319834231648d25178036b760a91d7f1522c9c448cfe82c8b304f8dcc1dbace8494339b0df0030c54a225c1e4022ad6fe08cc1e954901931ffaf88a0307b06a519006dea93de1346c80490e82244b90142592eac92a4193b8a35409abd19bc4a28ae035ac9243445b308147ce657f908dc5acdd6652a0e5a94fbc22afe7ac68813b9735c881624173ec660f8d3cd291d246478bc0ff72cb3aead95adc4d71126971839744625f4030dc779e8873175583f07c925c71e9691acaad8486cc418d21485a312d17c5d8b386ca800f07446a6d31061bf213fb78c047353f82edcb73a3f71c999cf5c9141e683217a5a049f795a8332d0419af0f7bf417308656cf3335fc17ff4d499403ad1925caf4bd3d428f271c531ad68740c095ecf60670912aa9fbb613b35fd917e7eb322fae7d198bd63d3a21c775408f5540e23beb1d026061158c5c3d44fdb528218ebe35563cfb3695995bbf3d8329e461e7aec45302bd93d7b39bd152c8fd0d490b6751c04284681cad1e438abd4f6ff000100e8484bf4f70638ba5182ed5cb919d6d28d0cb69a60fe6e2779080e5a2bb7714002a45b43f6791a29fccc9722109592e0ff25b9bf76203bdeaaa1d5f3b05d54e2e05202084757bbb2526ba294661bfac2f25e81e11ecad2c0201845c1b66b2980a81e3ad445f26e95d4ca75599d9c43a49e047b472f310d8f1a4f60d213895f0c3fb9f5493140e8c7c33dc3c341dc7486de836d132fc0f910f157a464b339a066b7bb1da9890c20aa9131fe06cde2ca70ecd3ec76d83d4ccd559199b273b0da4b78ae1d833f26ece8ba16a40b0f1341d583cfbdbb7132ebe71fbab39a93e16605e017ff3d61b40df9aa401ff769d3befed4ce91b7b7db50e7de8ac9e1327196dffa6bbb786fe2896ef208a141600816b1fd354d7bb727ccf5c3aaa1c643e75f6e8944d97d1291955d1292895cc859bf1641b4873330f2d378bb52ab46bc1f239a7703786da77ebe3fe9e4eb88c85dd10e14b9753ec73449433d0d71b5ffb1063866c8c4639e58b243b0fab2fbee294a9bc99306987f35128e03b067641ec3411728349327a5dd10b89d5291b204105a8d7b311e3f99a4c7ed2ff8266b0ed47d29579bc06ddc2249d61772ceebc9c15ec6e64673784af9278a09eb04fdfa97d14cce2595a51a4cd4d2727b6c8c7a5305923787e122eca6f7e59e3182e7a794446f3f8544d423b23cab6bb4bbc3b5c00a5cd764dc8a953f34049c3a0f23ecb92faf6422add9e666148dc109e6a9d563b44e23927c3c1d0d422035b5a3758e755c10372d288dd67201221b0427e33bd1d1a955d1e49282c854a740cd92bcf3096b4ba67229d85ecd1a0529b49e85681522024f97aefeda0b018febb2644992012bb2f667f431b5cdeb2857e9a770a874d9feb4d7b280e017aea0537f4ce30f97323a0d1038c026785efc36326348357fb4dc63a1ffe3a2cf58fd331e01fc4aa0fe736eac1a0203d02bd879ace940f0dc5899c984519254c1f2eba2bc46cc511ef9596ebc5f3a2e24acf389b1bd4aefbe2589cf45b0e87e2c189a73c380cd1199ea0c874bf2d5137fb7e4d5e5e9af28f942030428bc77c839f6b94fdc1ab0327638a19f26aa4314d30c8ab4ad110eba06f984bb350657be19129426c16cdbe92591886276a1b1cff79120421429604ebe3540413dca21b237ea9d80048a215a1fef6b7575707b1d573f5633225665bd444ae761f99e63443c6ee9e1f6b0d45b0f4ee539ccd4b08b946be71c16894a1cc96552df049da7fe7f932e2063e26c334cf9abad3361b524bc32d83bc9362311a0f197d4966593ab025d3df9d2756adeef3ca269cfe8e19836b1c7971fd88d9d068fab7f6e883f632d12ba05bfe208d1560d483000861d1995e3c2b94a0b753b7768f12778bca2bd64f0d3514abd401e9c832417b48be4d93dc6b051c79ba9c1ad0579e5f07fab22058a954c749476af7f05ea9b71d3d3dba82822725a517595f629bb91a194f0a64408a7815f1dd407dbcc0968ebf28e3edae2a17908b78522080607996182ffd78f36a160a1c67aa6e2abfdaccf41708a35467c6bb2c86e20fd761c16cd03221ac19d460b44c7221dee3ce04a13c24e0a67a19c936ba07d8c28ab2b0095ce15315c8d8219e0ac49f1f3e2cb4306c07f73b7f3eb819c538cd39948a940a1eda309ac51e109c669782b8dd0e0e7e1791073a85781df5264204bb4da67e36218a4dfd22f58e09123a46253399d7919e0faf2bf19d44453de49853f56e1c87422f77686f152f79380fd92dc41dde5bf1f045df06f25fa8e60a07462f23d74dd9fad1d260305af891be115a138ea3baacd92b6e6dd95d19972bca1858b7647f70c8b0aab221131ddb429be95a0ace4b6da7ac898fe424c1c6743a20027b62786d34a7cf31b3c43e7f422407dd0f1c227fa34e30154ebc4f6fbcbf37fc309090461050324cbc43af598d45606f004d0bc510aa877dfec1323d62806548fc05a66126bde2e2b9b71dfe14ef0ce97f6dd89aed057625951d995e5b11ed7917f758700e50977a5a0621aaf1c0464495598742eb7e43faaaaa1f2e04eb2fea62ed5711d541d2c7044dc2359bd453629d00e2b7b2206132112fe7aa84e49164621690056d44974cde41e6e5e77142300da6e41592a5f24ac1424c188a309fe233d36b34f6f8701b38be4924eec1728b84f169a4aef77808eba91195a4c818d85ca118ffdfe5a8f9f0766fee94ac4dfa354d7da3e71829b4804c052b9060f85b37b41717f02848d9d3a9ad2e24c63c190926f645c042506730f3b4de923e1c1e67a025448f46ecbfa08414433cd4ee886be5a627780ee0a3581e0ffd4ce308ea43a7334ddb78767c31c54d9e3acd9ba5a90c47c355dc8baf4e258dc2d3e27eb1c33ab86584818417b55a2c5f60d4200dfb62344d8a12d35231b8289b9b8ab24c06515584ddb341b85fc632fbfa3c92acadd518e24614159de187021e950ab67de8f9e9c4aca36d2f03f6d164d4e1e88926453b7ba4f1117fcd86953e07dea81413240c1700fa524c20b4008f834026051e93cf7c84cf439100ae7e46b353d7b1eba82a77a84bafc34fb613816258a2cec9e9b22f8c6063f5719e680456a18084a30c792911f8f79f3a8906a8dc94e26469757e7e78a7a1f384dadefdb13bc58d1cce79e420af1a791216a8b1c1531cfcc81f46078c9156c688631964e03b4a654fe2db1eebc8a9e582d80882059e210c2980e01205ab37b6254ee8953a2c30fc178d55b5f9730eed7011f81adb71515c708e2c019a23c88b15f3210e85091c03b462d2a89cda18717c2d59077a17f2dbbecf24de8b9c630308ba0872e2a19fddb650a0a7d3cb7a4af7f3eb80ad7114ef2a4987f563ba0002e077d90d8188c66845a74f7cfc72dbb9cef50c492989dee88f4a2b67b173d53fd34378bff363c90601a7050e9c3026c19f1f2400eb83afc080ce0f1f7677fabf8a049f3e3649cb31f7d940b91511dce2d2868364ae2388851c3ce220b4496bcab62f4d787b4292e5725de8ef82c977c3e24a45fea32281facda2e329788c755d38036bab08e34ce5d0364de306935f42f47743a8c3ef90b23b14391931249cb7eb00a30499196dee6a7f9781b093888cb25a64f58e0d4378c9f6f9ba377bb16bb2505800c38263bd9475fced2e78e269520c3ac641e710dd631c5fb49a9002c7a1c92546803935a676f9410f5dad80c5e846e1a0a27022042e34cbdcb3bccb34a4dadd42318d1cc9e0bec8f36a2976b2f404b80eaa48b99f56d087ba05bc77a126c84f42a177b07ab8043ea6bd16d96a3b60cf4aa21a7bec2885c1bbb8e9c46bccccd128cd4b63caee7bbee40eeb831df3f460c9f0243b61e6f1579b58194fec8c5444c154a8d9d94e67d05d5f51350a315b9671f0cb88a698c8708d816f418dd5ed4abf0416e9e35393e6ab24e3e266b165da91f6e3d9f7a8fcd0fc2c13430c5d556efbe67471f676f429cd44cfb9e10517d91ae5a6b9e9035679e8a198671de19a0a1139eb28b8c8ba99e549c1262c72757999f724f9a521c467c0fba44630bd4e326b4d77a1dea1bd1d4b8b15fae9bc88b4eaf923f93500171e52b7f7281a29a1e7836a75e4d3699a3674f18200135791fce29e0f16e29f94787bfcdd375f5f26d00c8d59e4103c1880e3640c0f99f543b7030423b7192218335091cc79c1f249410329a08c674fe11e9f1d23c40f458cce4187403d577f700c43364cb96f6a8abd35e6b0beded727daff8d6dd07afb35e59d1fd571a9ad0570cce07d115cd77e9172da438e45a6837a6c092947ad2ae6105b3f8a285dc6dcd63ad7e6fafb0aa9bbb0f45233b51dd3e72b1f18d80d99f0d91eb37d134dae2a109b59bb685206a74ed51fcbab394f927705ce1c0dfda99bd2011b4b00c6b504c76163edf7f3ef21ebc2befde778ef3d6dad2eae72f45d798953df6f4547c2d6abc2f8c7eb179fe9ee00d8752a27fcecebcd80220274a801844bb3bcfec3f12daa6b965019ccdf49f762f04ff56b61cab8fe928efa8aa8708d9c374a58dc4e4ff9aa71f146a6353a5099def3fef577c07278b338d36711d4f84fb930727345800c45e1793b4999230d289810c9494888fc1ec443d53100045d199d39f52b5717b64e021093e0ef308dceaea505d60e50355a006db90ed3f283d52df0c1cacdb73d738bbdd680b0dbabcd2b1e01659d965cd5f5c24d88110b06527861652fd787eeabd0c6e93cdb57b18fe9186d248faecae28809e86b336e4089e201122240e9434a45db44b38fc3ab1ec057920d4b288ee0ef442b29cda36b2d301a9978ac795e511c38030cc0c73ed4f047c5962680f79d3a07b9bbac5b4f4a3948eb1e3a114523c563f48174a765006f13921f3f4c0eab843fe57ce388ecae151854a42fa8c597f489aaf6ae5dcef1447240a2c531f18f2e54c5c4fa5590f78c8e3388e7f84b729dc3eac8e4b40db47e74b6af437b9ec45cee5550147b1929af4a0529d01e7187cabbb6c0fad3d4d0c3b85eba42005122c53b97f44478cb17fdd163d7379e858d103479ef426c64ed9315ea8f4199d0fba9514c4b17630ea308400a754498d79bf5fa2892e0ca1d5f840bf3de59400aee317921a7f4d457321f51b343e318d8dc56fd91c37db2d669912d05e20918312cde37d2f7218cd685b3d03da5a0e2a7f12cd4509e9a56dfe3d5f30d4dbf1cc66a4a227c78258432cd4c1dd1627f1d5c2dd433d6274516975db60c2d2ef69ea77c0546ef4e346085d1c04fd4b4ca8b02138f7226c97300b7438469c06cbba55ae4c33d82c7d338db7f92dfc8842ca8107139f046bc938611ad160ab1f80d35a76242e18144b8e54f5b9e8f2a2ee5ba4e7e0ba87fa825f6265d79bd136e496d2960ad38f9eae75844012875f3c965a9e02cb2347aeb047a16c45aed77c80537c2d2f50d8b10d6f211bf8bfe592992d24c45544e5b6a6b6195021d82a653c6a400acb4d868001ef013d21c291e3cee53b1c28c8fd8d6177d008ef3a2c4624e98f92c139fe33cb4bc21e2c09d317f8141da47a1c76a85dbda2b8b6a0f9cbe728a3c1aa2224329a908f47f29b1c803a26d62611120c46582a148ea81e4d1cece283a7d82a51df2ae8d47c495de584947cdbe4b49f18aea78fb20870bb1b75834eb9d868f56c57b74cfcc25c0226539a3ee284410d8f6ae86f0b2d12334e0d887b9c9d445c3c02311770d11a0430ac5c7223a28e9bc7b1e86dc749bcb9042cca984b40e42bccb6e6f949208d7a80539edf8f46f67ff01457e2c29ed568a5b8a831da726f5cf17dab6e8237db442e6046c4ea1e99c26e53951594b71069d5ed356ab2fb76b0a334b589db848b0875741b3be2fd531c896601561b1d05774024aa768e761a3e9d40875f2ce1ea3ed2c2eb713f128b430581889e1265498b076d96ce881a309f04ff97f334210c40513a81b0c64a2560b93a11be385d7b67db0c9c44bbdfa55dc897e59af06a884d29b8403e24d5cf9d791e8b7f058994b643cf05ee1e0c96ebc62b165cda14a9893c96affb9d1161603f17a4d950f8b1fe2cc39bfc56bde0e37b0f53b90881c281999c9adfee7f0a40d2327281b3b374ec9b3360a927b386c176e69d83c26513add180bafd4ce6dbf594fec90b409d720c4aa0432767e10ea8068ddae410e2cd4108935c46c1674da1bca4179b0c9afb7e944001f61dc960f2df5ccb41875471afe8cb708242c309687012b902ad0af0e63f14a0ec682a6fad0227861c7ad257665ece26f7008505a57039b234cc517d768d2f5a2ea7c1b0d06cb2111bdd2a336d87f3dd462c9f51d13398d7c7623fcfc981a3d95b4f1b6b3c2f0380f61280f78f167bd10e052621136166ecab9f01b4efec2a1855cf8ff2f1ef1400b21d671b925fcbdb0ef0656bca2fda74be006895740b1d0a6fd5e551826dfd4a8ec5796c02533adf0462fc8bb9dfdfe27c97324ec3776c4ffbd6ee9474e5b2626f930e7a47b4f18c334b96c591e530fb10a534d64f00985d4dfca93c8d8399727c2703fe4722138213e862d143c7bc959b61298e5c1c2be57bfaa400dd98fcb3504ece2a8e4f3d08b32a74ac53134abce3d69b4cb83b9020e7df11437c7c28f0b68cc42a9034910248d40215b3e24611c18fbd39ee9403345f465088caa455cd078cf8bb30db5259686d38a5a549aed536429e35374c7631a4cc827350ac24e6fc0e7e8c355eed6c0216d4cbcacf574059d0c837cb2f21ef684a6b0a5141e28c26434a5997a34ae57a55b04ccfb7b506ff8ea0af40271d2a9c26a91405d235fbed1a8a8298e751389201f45840cb1936976c598a2b1933390aacbc07ba7b120a36f1eb52632395322f0ba9abee5b01b08ca7b2ecfcec006a0f363578ea53ed4b70e43c14d3162e25160a40498ad98196b17cccd00982560f2692aba0fdb1d93aa9adadec860212d67be40aa5642a85565857408a4ff80d9ad801dc32d6696df23868b2fbaeea10b3e4270412e45b12fdc123c4d6636cfa81784fef670f4839bd192e6d30e16c47c4853647f8a23a8a32d5e03e5e642b8e1152f4463064ef017e23504be5ab9367fdebf5d950b171902b504c8af6eb8b95240748369b1516bb96c94e0c18b7dfbfe4a23115c7305189dc2a30fa8f3d2ce2ee683a521406031f01c8911829f554aaf653a8a1f7c23ef3ee88d7e76d347e3cb2607458899087b27a5b9681c722230a91771bf1bc10a9bfca9a37901320c20c9b9f01a014da6e63d637d2aebe1152834b6a4c165c7e811e72c183a48928430ca5580685563f63536e12e685c9a5ff19ca8232e590c93f74b18051efe51366846362d7f1a4ad3eb6ba737b1eef448e2fba9d22b8b33ad7e38568122e201c9cf65ad6dad2b7376b7795d7d9bbe2083d29b177af9fe31b43412dbf90363b7c4bc4d66416ba419bbd265ef4b6d1b87b714b43617af7d9fccb3873a8259b428cfe4beb455e7c29866054480a2d09d1c1ce668be75cde8608e7ce7449e1f67062b39b0ec8d74b55141e160e7deb57c8fa49592b902633f1ad70f64e4a95d0a68f9a71bb8099e42d562c44b1b4ee22f4b713436db82d5016a111614016d6744b729aca9934422999e4132a5640fc04cb72b80132526343a551dcf74b3a8c5b1ebb7c7ed1a6af3a301b062e7868406714e2c7729e008d7e1348b23081298910669b91a26c2050e85b8d7afed4e00ccb268dbddc8fe86136ddf10fe919ecb663b40fbf34e0499633a89de7a082b164fddedc77539505c7ef0d28b23c053ed42b250de38a5162f251875f43c453fd14c24b3a0ac00a94489ae21d186ca2c594813448792aef010fdc6bcced4165d9445c504f1cf65575352fcf807db8a4ac9fa1f5f2eb46b67391805c2b078624cc56dd8067865a58d17ebe39e7a2048e08e91fa27115f46f454a019b18af4d7caf39602190df7106d80a066e52b8f008733665dc3a3875e5513b732a4075967312164fe7f9b99fb2a6dcde885048559695e0942d8e7978f374e79fec7f808a04ff1cf73e1da01782c7fffbe36deb9d7a6303ab80801b7e91942fa8a6880ce89ce148c8f043adffbc85b30d6d53a077a70eec0bd5f99d9cf0dff79b0db26a9ff404b24f9cb6570710bff8186ac293c9f9894159ec185780b243f8402003070be36600834683a6600ae6e9d57a6ad81ba8529b4ca4d0de92fbccfe3e9937071932449a44c323f0c590c880c32f8d6a49e3a9a6aaa7f4f6e754f6e15857b96f7a42f9bbaf1591146a729a9a5297c86cff3f43c3bb3345bc3201ded66b3d96c360f92429c6474157fedaa926b70af926dd48d3f25749727414fb7c73d5dbe72941fa1305df8897acd9edc064efcb0eb9fdb891ef454552795a1a323ee8f5d1f53515dd59d9d0f2ae3f694f228dc8a8bd9935dd997b5b4d94a3682bd5c9e6767b31126c245d13a88cca07ccaa7681d210e74d04491148a1eade9fe668ad1ac2a2c1b4dfbda7573cf8dbe3e5843184d3b3bf7fd4ea5daf7ad0eac13d4be3adbbfbedd81ed018db1bf796db48912c5ae2e2a63f1ca9e381fa8a93ed763f583c505d9f5b9d5e5689bd8bd2c20dbdf1be98b1776205b0bd504220262e5ab5a6dd5d59e506d6be9c360af30bcddd5a52ff5e8f2a53b96807dfc1c0e87f32187138a5a2221a21ad1907a72f97a434d44abb334a27c1bca021628cabf7ea80995e95ea4ba8968424d6a0977319ad7a3f902e188e4eddc7befad3684fe61695259e78da3b76ef377a57803e74532b60daffdd1be478635b12ad9196d683b7bad6f9e46e594a60e5bf4b9346fc041c626c9e056d8fe9b234fc4b6bf8863726b01a439b453fe2b7db720928d660ebb0376dfd079d0833eaff21e941bba0fbf7b4b01d1dfd9be4f3e11a2886df3b26a88000429ee902b64d719bc0fbf2bbdbfa579635f4d12df3e87d4ddee76b7bb1d49d4244efe196a4ddabcb1c3e768ce8f6410dfe6b7a57f47e2bc0dfacbb7a1e5595ec625654de2e819ad675a74f72c7e5f2c4dce6f9ecb0ff87c7e2ec7e0fbf3f7fd5b78b0f31c01df3702be3f4fa386a5280863a7bf85a759029fbffa86cf677d03f99753e22063771a0719a0277ff328a5c96dcfd73c83e8ef7b9681d45c2d81fcc7bfda54d1b4963ccfd59247ffa84ddf9dff4a7304fbf32c83dd5f9ec1ecfe566087f683c0b5bba3cd1d5df87d0e3bd4e6f81db0fb4bd1293f7edd294fa37e658a36bd7b7fd7fea4b203bebfa7e3f85e8a82308eef6307381ba4ff32107ee85f5bf4e1d32c81cdeefe96a1cfa57963e7b7b946e84171dca239daa228fedb13cb8b0fd6d0577b2ed39cd77ae5aaedb644113d8e3d91294f41a4a7f3b1c1d3da060e95857ef39dbe2154b30c211d3e0d9b671041e0dbdd872820224214353bfcfb1c6deab039f6419e8fa8e22920cfe7a98a364bdbbe98a243daf4c88ed65ed6e28fde4b130719fbfee639a507b20c7577fa863b83e8437b2d58c35ba27c6886cf011db6e71aa4ee397fbf2c595e972d37ba12078b2eff96332def1906fb39648a7ff2b93447a0a965d1335ad3d8e6e6458d838c1da2fc0625147a1a96548e3b548a7e2c7d74d56ea1f4110719db03be45ff993a9c7bf3a3d2bcb137ef5906d0168920e05ba4cd11f4b0fd4be5cabb94efbaf4ed79e34837324c197b73e489d7a64794a889b1e99127ce7d599e378e2525adf18225dd2e65a9dc4164a6d4ff3b56be72f7f365e67cf836447aec18d2206d7a1f6d8e1eadcddf9b17f5d56669b3a97906ec846d43aecbd225186a3bf4cf09f5061406e80682c200dd4243f84954849b5a53888a88899aa0e2088cbe80d486911ec1816ddbcf0f5e97c75eaf5d43326bc25018ed73decbcbaaa5fce5d3d47dcf9e48599370e82f3f87fe52efd841ada9d35aeb904c7befdac461b4f3733e8362695624f60ddd8b23da48068d8d5f826da774c7cc22b1699ea1ce60778fc3688bcfd117482dddd692d1bffb1bbaaf43f60ddd8b657781d421bbd3b7554b75c8c64f1839b35aaa577569ee4adff0f1cbd2898caabbaa315449c9d1ea0bdc8c9b0267e3ace0661dcec659c1cd389badeb4061745d26414b6ce8bc3fa88c7d96f2cf504b8768f664faea792ea2d68da7facb959696cf11e357f40ed3c7f816d3c7f81d2ea01b95e17c7d90151c040695b1ff66e8070ff1b01da67b73aceeee4eb168826073f405d202fa725de0a6fa970657758bb82b973759d08d732969caf365ed20b2a3e5f5ef58f9f2cdd07973a1f4313e87cbbba077acbccbc770f91d2d5f32b1306da4bbe557de0c9d578c24fb332dafdf661a68eadf5492ee9b9ea65cca9677f91c2b6f5a799795dfa1bfe5692a74b3a7189a743fc6d392265d4dc2517ad3e770f9187a47f92e6fd23b88cc94eff23bf4979e92acc6d1f2fa73b4cce8cfb1f2a5d6a1c389906e944f034d95da65da5d2b7b2a7394e56b967f9be9f59b6e73e163bce930176268a7b98c45a5729a49ab4a5d72d1d696a5e8b4a7b22c3569a6d4c1f2e50997046ed683aa056ed6838a9b398a5b39cccd9a4061702e519030fc141ac24df6143a57365112a12144352218ac4437b0895a2221f5e461dd742f47559a5dff02a931e1db93fe916ccb62a3adc578b97b311763f8e665e9af2c1d3aeacb9aaaaeb1cada51be7e9aaab58665d69a1ffcca9bf5f57a45d759ac36938245df576d6b1d32dd7c8bb156b3926668b04680c081108490854a95d2317bd2ba96af4115fb045bb35f58db8ab5b5ce7e616db6e6288e865bd92ffcc4f1b0b6d695f7bc3bf0f013f70547b3e4f6e0beb82bce664f97078ee60ab1e4aa74e80621d775c16551134b1772d9eb82cb0ab91c656d0e539f9b59d375819f382bbc0bb96c195ad11730acf0d3edc14df67455d6e428fbf5b995a3ac0ef940617a0059c1da4240702bd00d5f31721c74eb3a2c7a3787baa4a950120e1ebb8ea885af18f1eeb609bae12b46719ba09b97a2167d0175e9016f77fa0281711921be62b45a14e3cb9f89f1e5fb972ebcd63a56de85d7c1f2315ea3d1e96688b6cd502de4213f618806d40474ab31219aeabf810e78fbfea02ff53b30eecb0287a97fbde53f93fc6b28bfe56bd0ff0f5ad738ca6ff999d2df5feb78a79b6ebacb074059b23c00ca15cf35f4979a64af9e295f47cb979aa66826ddd04ff74ccbd399f2b5d641e4be0e962fffea19fd2d5ac7caeba7514db0399b4b795d2f92fddb2a4b92d537b81bc784b29070b43c4b8b26f9b73c4db1946f7afde59366f4973756fe75e8283d11d20dfd34d094fe1cdd6d8827b4a00531952ae5f22c00f0523441e8846d31526b2a5f0433b194ca9721e3b6dc268ca29808492d895afb6f8c3f78fd2695fde05bde7c4d4346694d2229469a62d15adf9735c5d0d49a5cd0ad96a7fc3a63860c19ba53fa20746e4235b010ebed836ee5836e1f52bd3f0bcbbfd6c1a249feaf439fa5adb12e5da3cd5174320af115e3669b5755634c6ec6cdc4dbba432e8b03dd404deaa97cfd6658965c6da47be55b565adbd7b1a26933fa75b4680bb3a6aaad2c6567170bd9658152341572c1767dec84d10c3dd662d42dbff239585eeb1dfa597e453f8b0edd58bec56bc2c8f23a747634cb986fe80fbd383a147295282a28a12e4331f186101663ce32d8774db22b1b845d95e59d651c9e2a1f2c45b0986cc6725944406a8ccdf88a5b598ace3c03b74933d81b4440f24c65e24412869085940e1d52d4e6302fabcc362255e86007a74a95d29a94e35fbfd63bca7f3047f9ff3494ff34e3a029cd52be0eb9ac4986908d54cfeaa39e59d46a8de67883e5432f7b62f9fa2b654b19725199cba22f307bba35d65484c65c20b4144a82c6dc1fe6352f6bc63643aecb92c12afd65b1e8dbb2a62cce10eb2cc50845425c0fb91449c9f2fea173874e7b22d977791d52f5432c7b22594dc2f1dff233ff2d6fbf45eb2062f5cccabb681d2dbfe2f23a56fe35c93e4dfdeb905279eb9d7559342bdff234ea9d62342f2b00229835b1a80cdea7961b13c12e8cb5d252de56c64c18e966d1242f7394cfa2771099597996dfd1f2e5e760f9ffd73b569ee5698a84a3e5cbafa145876abb7e0d2b3ae40ad196308a42376bb24746f3b2442c7bfa13081486f0820752b0a5ea632c4633740bb96e5adf01c88071985084a4b56135e6d648b1eb0f00d346dfe5eb37432ed9480018be62f4b62982ddd8569b37b6f5920bb9ca2f817e8e2e43b290cbbcb17190c111ef55d1ac6ae95e20aa30e4b2a7d0cd9aaa3de9f7bc710c855ce59ba159d6a60e9b460ddd54ab33d4252aecbaee1110e22bc6ba4d510b2c452a11cd1523b7375096174835d5d757c8063a30ee4bc4e9b2ac18f5b7fc29937094afbf86f2b526f9b3bc0ea91af4b7e8f2597ea67c16ad8388bf8e952fdff58c7e9667d13afef5eb90baac5ad2252d4b9ad2b7554b178812c6cb5242f7caff9ba2aec4dbcb99952f35b5a699ff1cac498bd1b76f5304b379897757e24d334ec2688a60bb3e09c7ca976fc3ca979bb7e1ffad69f334dbc0b56d7f5663aebeac5a52526336bac6584d727d81d4520b09e3a7b91bc7a496f01146ee4dceb6eb908df5976b70efe51aa41b2b4f034dad7c8e90154990a096852ca4fe45307b0a2d218a858ec8425004f922202721cf7017b846ab3159d0a80c3d52eb421acd895a57c334328b5af73d7c2a7cdc0449a3d9565f5872449c51999a7cb3a70ab3a6983d71bebec8b2a7fcb097e8dab07c83dd6e62bed518cc95a4ec081364ace528728acfcb9ec826482a60b0eb3b8ca4d1979b84711c9fc319b507f3360ddc140830806d6f53205821886d92b470c40515689c90caa0c36015566115b6eb7f66f6e4d1190c6aaadfd961d78fe8c3ae9fd967966fb47c7315f15622cd4f1f306f35bac0401d3675878b9804715679d4956371762b8fba12678e2265e2ac0a3fe52edc5493614d06a130ac9d023206bb3ed9a3455f60204fb2474d082ae381d1a6323eea293f10218c759be47992670b0b61b4db244f90765f9920329aa4cd7e14affcf2887838c3ea0b466ac9bf7b0eadc674f6541339ac73a51ac51a1e350d85e11a43fa5e87fdcdc0332eaedeb9724dc24fb7e392462d0501b2f3a651f8808a0e0761ac7bd43b88f87bbe861de277fef334df20c992b4813ca096c7f27cd8f167f28fef7a46fcce8bb5d126dac425b5555723494f67a4596c6c8be101b5e4d1587ee52e722dbf1ce5a91c2677e1277288d79777905fb98b5c236149d017d251e4116a0337d57782875b2f0752d925767d527c15d94888411d82df040901d55094380b025a6599582375df791d52a44e9370707efc19ce8fdffda87510e9f4ccf81dad43ec9ea66ad0919fa3499dbea183a7f32c492d756f6699671b24e922e5c89f437cd2664d98fa15bd7ad620ba37eb6a8833c4dc10e72587f0139945989804f93a42dac08924e849dc42ac89aecbb9a84caea7fc20562d09e39b62ad24e5787701183d10219535e9467ed2cc2f00082152d0a4b2d641c43462e5a9fc39549a68a57850000d2c350295265aa9ac7da52fa0d2442b45ade903d6f483cf6fd29b026860298e5e8154d6247a24e9f5e0a93e32af074f2526711832c796a02faf8328aad895ccaf3aa4baea0bf5b11423086ae5570b244db4429c913447552198a46526fc5479b86955856459e5e1a75c050ac90492265a21cef22d6f5145b66530284ce6225f0164027a22b3404940633a47913287a9ef9b77f9205f28d82411767d9558139788b69aadc6d0cf546419a904e92a6f9661255c59e6a8ba7225fc242ae1a6fa35cb7029b2441f5e5442ac2b47893f7e1089f861d79b6ba00bae351cf90569ab35e4177ef27ac0b5a6078c752ee22f6bca4c7c9124a58a44ad21bf206d95e5037da93f284cfd810825767d2a03395cc3ddfccaafd7e75ec1ca2f23b15d8638fc98f093c8e3654fe2ca9a2a0843b56fd6555967f4a5660b829f5ffcfce293b41a99452dad68244d743db1e4084f5c5d71c5b954ec7c8ef1b3de917ffc8ede416426ff38b2a6aa49568f578b6710f807a3f7b2a60aabb2d81176754ebc7f3506c28835394b524be07b6f923297e78de3193e8d4a22a9a75a434ab1eb9347284a74914eecfa248ccad8c04fe2cae528fc95879b3027ba441edb45d7bdb686b92fb416735fd759994c66b34c9665d66659ad467e98cb324ff4a11459f4a5722e9682dae06418c495b812571c968d6442dea2208938795aab495e5be269f24632711f8c1e696bb15119da44f5f07b4035a01688b53bef79a7a4ee6be07cfe1a464f494a754a927dcfd3949726a7f3fe36da791ad596241cf93d9f23bf47ef2032d379f177909a643f3fe7f3e710ffa3777434a9e33cc97244cecab6c59b8a34392d92a9de206d2015c9227d9036f289d1246da4adc6d02852f0daf5492635a6ca406bc9e400d9f5495545f3edcb64b471581c7eefcdec97e36ee873114779b908c984a442aec2659ed6b9d6799824730def4911873f745f946ba390ca64f2a4828292b0eb835a54c66e92d39a506dd336a1da9e0548080e0308bb3e8dc544d86b9ba09a5ddf0445b1eb9ba021d0bc7375b588b5b7f26836ff8940ea49ac5951c8ae2ffea0a82c12c1a2323ff8c93b578eb2de106e2299384c7d5cd2ecfa62ad062ac1f6c82fdc549fac814cb06bcda4edfb53e628dcc461ea9f4d4859f7211225b915f1bb44f172d692276e429e24eb729bb05b51e154f2abc2466e9bf995e2aaa9c1b0f1db667ecd70df8dbcfc556b48528ad1e63ccf6f03779be2aa53c118835d5010d0694f9d0a4690aca626834fa3922ed2e5aa435cb988e8aa43aaa97e919711189232d79ad8b8020a42ba72ad561b6b4532f8fe342a0c9cb8aa31662eb22ba875027acab520a8cc7d19ec2ab60008a3d5648dcce2fb5c84b6ebe79a3d89b9e6ca35d155dbf5ddb95bfaa63586137b783f82c4366c57476528284c1693d8206d75735996ff5a71b5120202b23700a2a927d2654d367b123d0cf2e10205b12b91ba5aad4a4e2cedc889654dd95c2e9b47dab89c9f46bd29efcc327baa599665b948ddd025270d6b72ff5b57f634534d5e57f5de7b8dc82fbaec296b97cbcbbcaf4bb6c16dfc3144d1e56913146483b452ea9c68eab0b106b53010464e675b364928726de48879e48819bf49ae56ab95e8d74f1fb00abe0820040710829e5f306cbcdb245dbbbe00bc73654f9e3f79f44853030531f221d6ec8904d1904dc8d8d8bd49da06107a49ba5c981357e229b2c4d6f544d7489c6517d1b5b7bf2922c1fb4a8fbec8c023e9067821f402749b009974233f0d34953f47e581144e108394f8e001420c3b77f5ec32b86a07d2654fa2172f110cd8e6ec10136ba4ad05580b486a0caea48db49136c73e60d513cb9135d9ec2203ab93a004d837de39087a8837a5bbba18b4baa8d1a87a507b040df203bbaf5631d8f5cd166f39b61c064107c2576e85cf3015f6e5b22362416248326cb06d521b6c1fa096ea96c1dd3ce0fbae6aa9fa382febaa569bcd6cb3996dac7d937b50741ebeb235b56457d5d2ecccca46b04741f914944ff9258c75afbccaef50f99447297710d9b1a2751099597915adc3ccc0ddfc0c05d839d02c7020f746d7a067a090296a4d31ccf8418c6691a2334e07815292fc37ff9f523eca9b5cace6442b564b14cdd54a1c2baff229256926e5513ee551fe4b92eb99154dda907270a4004b924af91c2abfa277104979154ddabccad3548e941c4ed0032452299ab4d137527ee5698aa650f45b936f1e6b3ba49636da03be5d5b97db5b4a795538956d72ed6c46c158024817460479ae346f6c2ee4a183eefea68c8d379bcd66b3d93c2e39efc5a7517df36dfe6edeb3799128e4092fb8a12876f336a8e0cdc6ebc4cfef95e2831d6fe340bce5450051ddb6a02f6e859b1c88a39238cab5834161b870205748b2d15edb84c2214e91b719e2c4ee7635849f2c0ff796a8d851160a0ac3c5be34bbe6bc6fcc9eb818b76bca5fd8756d1ab792a5945ccd9a9c8e1bcf2b3b155cda88f2299ea5b1b520ccaa0ae29e9ef69717a9a57b4faf236377b3ae9b75dd5f9a284657d1d1f369e16fe8efc99f844f7ad1e841de73a057e2df888ff18fceb3c5120204041f97e68d8d35e9fbcd77a4efed73165bec79a44f93526e6cee3b6ddea061399bef37da0471b829fdbdee6d40f994b761e555dec31863ac4956933a8d03e5535254f406ff579adde7f06df8588b82d0f14a103f183ea84541183dfd9da75902e1637d43f856df307abc294d2f3c197d7e90487c3c3af13cd62649240abd27f437743725bdde63ee5eef378f43f73df76e3c4e9b9edb826ee13d2d3c8d7acb1634e829fdc9b203a3e7bee7927fb9ff7cdedacfc927fac22fe53b3f95ff1efc5436b8eb1e45c5fea6047d285f1fec424fed69d4c2c948140a51de861410e553e9369fcf9ebee1f3dc479b3ad0b07606113fcd587c8e7bbc29cd1be7c9532b0a3fd2dfd39e52be05d189e80bf5d7c2e73c1185ceaacdd22ef9a798df73f0e7ef3c4fdf80e90697a60e1b6fca9915148c4bd09b9bf7bc9452e551ca95df6c66543ee5bd12878af67039b3a251de7ebe1fdf7229aff233292a289bfc1f07fafc19f7a714dfd311c7fc1c30cb00daa2a676881146d3d6d8d355adacafb6595576e579ae9575d76a1504775671cf7b9e271d6b935aaab75adabce9350954261fd0713bf7dd346f9e46adaa6aab4caaaaaaaa0adb99a55925dc8a5b71dfc6292b2b662b47d99a993d79cd0a3f7917352b5be328ef078539f70f3544ecfa3eb040e455819bc79b0dde941ec66f836eac3b0f3fb729eddb075daf4a2354ec6ce32a7ae3deaa7121558c6655b5ec6c367bd9d3e86129a33882a4bb1c465f92a02f759bee128d429a61a82e2a5339fc3d7843d073e7394ddd5ba7e2689b5badb4d62928efbfc9359c085cf8b689d1b4ab5dbbef7bcb51ceade83d78416e9c11765fca8ab7f12ebc86edcd615c0925fc6479b8c9de1ce559282c0f0bb32b7bb23ab0371b855da2b431fb4a32da2b46944f79b3aa686ae9aa928cdc36ed2bd7b84183c2d9b89a35d919b7a201344524f571ed79e3381afd974a3366c490c0a73b3fe7b4a64a91ec2bae6c30e23745559e61655f6d44e7439a1af3e973e49c32b6c9396750d8aac69cf644393e921845edb946f36b6a6948cd69f18c8ddb6c8dada6c614ba906178d1977a3112a3dd35ecafd25aa9b7d017ffafc4a1b43f8ee383c3c23f832f361235a031de0d6a1c8599d4eca0b45ab1561f57a2267f1b13db17bbfec7e18ff3f04b08804e0035e2bfe96dbc048ff34421e8c87d00720def03208010df3c5ba332373fe7b362e7cd202221d688618837981b7db9dbc4b7027cdff7ad9c546601a7a7323da84c0a1ce53f9262446264346414b22b103a7e2fcac4976804565fe83caec16872ce24b53413653e382c4ecb9e6ae8f83d0603dff00d068edfba30028b2c52e6af70bdd5bf6fa132de8b2a6bca353eed63697325a6d5d2afaca9be16eb77727cb0ea0b5fb369309a9c93736298c3883b5053fd3f9fd5125538db6a8c89619b498da92da931f83d16adc67cd861fc3f7fc0f77ddf77c5e8f9ce9ba2eabbb69273725a6349537777beabfdc6445cb97f1ccebdfedd6e631510e298a37e878fd9d38a145e082bb72741acfb04e41a9b4f803d4078af183fbfa3f39edf41fee7cdaf9911aed8a8ccf7f557bca027ce17c3397f87e73bbfe3f36426e1e8781ef4ac83c84ce7c9cff17952ebf0db1250b8822bd5d1351c60092d8aa4688a084d915edad87b500601214662acdb5cb9395b1b8246749e461dcb0df87f7fdfa5e057a0277cb33e05ea55a06e2bc18d045b455f56e229ee406148405faa485363441a2223478b5a34524baf05741b9758f3f5ebfe55fd95e6b4f96d2ff10d6b1305a48916dc741fbe36428cc4e86d53bc6198a3383e50d10ace517180c030ef65c835f0cb7053a19777830d08739e61658bcf394d8eedbcff5d9b6d7816b6efef6dd8fffed35f4bded3fcd9e8fed32df4c57b1d36cddff7e150daf87b4efcc05c43fc7ad6181f5466f369d7a2ca9e48fd1fcfb326d50fa931dc1bd1f977d953477358d6545363f2734ece994bce594b22b7bfe65d74ffcb9e68ea619ae3031319432dbab438a496f090d1c4b7d56dd7ff1fb8d842d0d38acd9a80a08f02fa2b4789b5152cace88a8d082ffd3e8d8a6ff8866f9cafd8c4152cacdc442e76fd8fbb1b8b3d0884df789f73c178bf7edff77ddf8310082510726240845d1f2331e26d724e1c068725ca1cc509c249c13639e70c9ec15f5125aa6ca2caa6b2715cb5545d738ae023c6eecdaf51893c8824a0a209a808043dbdca5198f62a1055bf1255dc8334501abec69edc0b6aaaef60ecfa353bbcaa0f5f63e39c9fc73939e766f3bf7abc84ed799da59f87bbbb791aa73a11539c14c5950450632eb8793a72740e0e533f0747ddf04a53554d6eb5c4a49666346bb2d1172fae87091e5a155b46e33c3447815432623c34576980bec438ca7790614f1b20010fbb3ef8dd10e760bc39187d7fe3e769ac3f6d3107863950999a738d1c5c45eaab23a3320cf0d046afd1b53f35db431bb1c673cb569b46f3786af5851ae6607ee0f779a1e7a1791e9aa776dfcaa8e9bea7e6c9c243f3d0ae87e6a97dfa032d1dc8818d7a34bfc1e8a965514b32cf67513b327e9b46f1840fdbdbf4074910629b2e1bf18b3807630e54c69e3c595453f52ca91aa0280f16940354c6c304fa52bf5ace03fbf6e6fd056e8ff9cbe8cbe9033df98c19042080c9549627279d8e6ce5ba06b1c428b31e9a87769fb39ac31df837cb50b706ec8d03945e00325a481c4e41a90c95c94eb63513c0e1bb5ac550ca18cbb7a603743c921da98cd126c3729d92a6ac27c39ef2c7785c9e1d50cfab96b2feac3cd829c351539de74acfeda3faece0aa311f1ebcb4030f1835ebc2363d1e97e65c307ab44e49539edb4745656aa7f4d05e63e7c7375db672998354f83d327bf268f7c17bc8fc872c88cc579f4c26bbd7b68408c061506ac90331dd9973c1c8596b2d28044b8fcdb3c453f364e1c182be7896c08dcfe9743a32727014a76f382e8d107fe5a5c4076f38ca67e030f5e9cb11f4a5be57fa90af88114f8da3871d4f714ad24ce7c71fb50ece77b48e7b85121cc1be0e295074b747c1a1b0ebfb16f485fa371ce55270981c8cdc36ddc6d55ce3c668330d35d5d1ce299de5ad21562eaba9142665d654df49996f31dbb586736f7a92d45275f741e633acc4e89e25bbd2649e2c3c341cac3c300f4ce681c93c3019ae315d9600cd625f0fcc9e3c5bc4b6171e19181e9aa78585b8cc7a973bc17aaa02a42de608d39821061a48f0bda2c5dd554261e50c5389bed4b7808c8d000a030037d5b7c2088c3dafeb79e5e0012f79363d184d3f3db684bfe88b4341615b071e05366234fddc1c750fe4803de04c54e04529ad547e18638c31c6188f5638ba94e7d575e716def2025f70c36d6ae007c3103331da6d96300fc68f664f34e5efb9e795c3921f8152190aa332d5bdf02d76c5c21d1bb171ae84565ff0bc3c6f1c795ef6e4a77d9d9e97119b9adab04a9f2959f9cdcf999f36b5d19ed78fd103f318a9a58e359ad4e6390283c233c59dcd665d67b5798fb0fdb1d84275bdc83987e3a521a301df1bf09f21061a333061578096ea23c1a59f9ec3cbe62f6a7325f445092f7b722bbc0b8fb916afbd8391849ffae979798c989e970789f7a027cf129ed7e9f1f3c4daf3a22f5807a3e9af9a2135a69bf9cc67d8fa8fce574137c378e6a896c37c9830d2e1cbc40b779dceb36e565d173f01d73e4c7c5ead4f8b7c8284e599cf3e56cc2aec63859fea13e22a83f1846a8b3e5098fa5600828b4f0c3ead27368c9aeadbf8bc3e463eb0cfebf3fac0c2aeb26eadd5558bf05355825595f053b6c24d7946432356222aab16515b97cb5d3441858a84c1a84ccdf909b9f629e2d3fadc5ceb3e457c5ab5d5aa913db8cb5157e719f9c49dd58e43c2c69fd9e708f494c1b87d66b7d1dd2ff7995199cc8168b32d8b7d40472dd55c8625a5e1873a0c35e946e8aa300c43ed59bbca943f7cd34f100b745a533db162e6a9b2157ecaaa4e93461c063cc91d3e45903d280f4230515b56ccec14288e028df11c55590e1323af5059c0454a8d416de5acd2d5d60b77d1e92efcf429c25f8e32e2a84e5796c3902a6bfa14e127b207f2c532f2897d96e8c161fb03c547079f282a0b76fd7aab0e294575f83347fcfb9f0f139dde9ca7a35dee300c3fad1a83f5e7553bfd31f211b2ebe7e5c2adfc49daf5568ec2358721b5f0d3870937d5f7562e7840782b520b92763bd15a6b3f4cf82987e1a67cab39ca1de53a87e127f2095cfbb43afb293f4778c24fd43f5b20e1f3840f0ceed3a8aa5aaa0f526d423a5a8b4bbaefbdd7f1f7beb9fa33fbcc3e33cfd3245a4bf54d3a8413a836574b2024f9b6c16aead81b2319b1265734f64d52e5d772201d392e87975392354bdaac4905dac1e384eea95c565cb38d8ea62ebde1e7a7dda009ed91f17e48db87f6f9882f91c68154323b2cc594583a143e929ca93b85874fda3a15642d1363f79a79835d189259d895c4c2ae4f82415f00f1e0e70f18a6ea2cc755ef447fd0b3e7951fcd6a183a9246fcdcf1f3fabc3e2f2a9349aefbcedbce0f4de5ee04adfbcc3e33fc35881f7e48d6f39dcfe1017de77790eff91c9d0f7d48ef00c1484db29eaf01a449561b11eabc7defbfafcc11fef8b6c411fef85ee6c8ffb1a1d261a0d263a4cb3c5afcf03fe58e8e26618d237cf149e2cfe4e75c2c2c09cbb35c0b69b4ac84369bd16a9ed1382befe4b0c49aed0613958835e24b747d5eb0b19a22d8e28cbed43a0aaf37128944f9969b882a2edff64d556328a93a39c936542a52f5794d6157d0157648753b3b1a8d9f993579915a72d592d7031735fa8428ecfa30973641b1bbbdcbb6c2dc482dd55845524bdfe79b3d7d66de585fb5c8cb511e4da619bd3fc9357007ea8dbe9cb59f9747f3f1c10776b95f49c936baddfdca67f699e51a589ba0237bc7ee3408866d7849f72686d9530683ceeee54012e642c2402d7ba229504d8bc22c099b0134534b7525c33fb359f79d0ac61a40352d3a8b815a17a8b1a66aca35c0070110968e7c3ccf5b95aced44ff0f46c23e2fd8e745c23e2f12664f9f2350537d2cbc2d60fbe3c5cc55047f5ae15fefd3facc3eb320f6064e248d5c52633a158846e5112155355245c359654f248da6a2a968f6846b351aaed170187eae305ca3d58ec3358b6bb5cd75608601c346fc12826054c68edeea08bb7ebe796792cc8513de4a0a24b15c3bb2391f7e8ef1f33a9ad3e48aa4f140988c1f24002540b562f77eefbd9746f3562ad815e462d7f7c69063807befbd1c01565e10de595fa88f9b184d6fb5bd15bd51994caa4815f7dc766a80ee0d906dd49a6100b7996f2fdca8b8f9bed9b58fdce65a9e5499b9b6690450ca356f95f312cea640f8c104040b3f47fe10d46dd720187d413276fa53f311c2bdf9691dc000997b2f6bf8342a8d169634c4f2deaeebba985348034fa3827474ebbab11fb0d71563e9f34e566edde52dcac4e52e84ba11eb39f78d966823b2159d46631fdebb92116d44aba5aaa496cace4f60b5278a6294a4963a3d9af94a554b43183be388664d5c698e948c94d451adc6789024a3d9122a4377163b08dec97922b2799e9facfc6475727ade38aa4ece204e5627b6e61ad6e607e820bad55215313909a2c6ac6accc979e2a3067baab5b32397fbf9040cb6ab54466cd3db2e57e89ee8952395171d2d46a291c80b954864ab272b2bbb4a18e9a659cd48e5efc14b89cf799aee7bf052f95dae5a721f3b50d30b0630f3365d85825d1f64593d7a8d8a20e1acd552eb56b4cf9d2d608942f024b4e5a8c7a8e519f318798c98c7086e73748e4e47d5d5c63c46ce3647278f51c58e4ecec7a8e2b20cdf836ff30cdddf776ec36d4e20d69eb5e4a355c35380841abc1c8dce5b031254545454f00554c24dc9ed940c016f7fa3f354a9ecb9b9dffb7fb906e6317edba4355b825eda2e06baeddba0db6a5114e377e05aafb49f6bd8df949b7db2a232aea22f27ad7a22a4c67cda81d4920f27ce722cc498030e3e6a09482d69c729701161c6fd4436dbcdcb0b7cd7064b6e4063700e76e0729488e6ba0087bbf36c896c3344365b87d6a1d1444b462738ea717616f318bb6d8e4e3ae27721d7e8de0553107a1a9dac7c89912c89237ef43859e11ea38ffabef2466e8e64309ca33992d9f0bc931f9a3801829ea0e044087a1ab9aca93a8a060f76fd9395eb84888bbb916c24a3c9ae4ae53e72d118f160f4a24d5c4bcbc2b35ed775ddc84565aa297b3b7c3e72dd29c68e8acaa0767ddf819e46321595a1359afbb0eb0556419c9c6205dfbe1319cd9395aac670e3c9eaac31b4ccc186abc2f0f3a8c3b3a68e054a08c282144d11e1def40090bdc73cc64b730c75dbef4ad014621ea3ddf6c197975cc37b9761c3e55c837b51d569a759a1603447b23d92f598d16ade5987312f12b6fff77d170f6000b9c6fd01641b7573329c3a69454b84191534061b21092399a36a70983a928d4632e7b06f46ae99a3ba1dba1faece87ab23c1e8acd5e0a8ab042a6c3f6ddbcf2b9470f48566e559cbddcef33ccf334088cb13d5c836f282be8c6e7b89a34e76a03023299c90a000b9c6fd02bc30928d64aa4e363a57a39a20a3f3c788d583cc35fc64a5da6189a3bc07cd80f3204417bb3ee631fa3e5dbbfec845657c07fa92043d390f3f622938b27f58e26475729e04514bf804a329b28d5210c616828e56404744d05387664da7a33a4d3a50189db4510c0e10436344367b3ae961fba10a623b51c9b047e52a577d1dda92268eba585018ff26b67d996c67c2f6373b616c0fa62ff7d6ae920fee2ef7398c3f4915027c39eb5d8f91613d87911101efbd1836d772a0c7799e9f4cbcc0eb27132f3f9d093fb98072bae0a71837a1c4a0d8ca09416ff45c2fdcc40064f4255eafd14b23c2bff10ab5c31640eb0ba6cb46ef6320c20666c1c8bd2fc05f2135f2c3f32ebcf7440a2d8a6c7fe75cbfb41ba925d668d25a78017bfa610b626df7751cc771dca53213f6fc3cc00d1dc0c0d5e6ddde7df751b6496b648c87bb1a0395a9db5f1b7053fa3c90522f691040067da98f5740ad7dd9d7a8044408ab2f8bcad8af2ee402e689d9d926adc570e6333c511cb56901666cea047e4eae719f936dd4ceebecc51fcb711cc77d0003351d38c1bd7640637a4063bacf327f798e020135ddb6af603f1f4b8228a85af19edefebc8bbbd0bdf76f28e4ca1a64b813a0317ea2ee003cc468fa8bc6382f7ff9ebc4d12ed66a47f8f93a3717448db1b7d7cb5f5dac93e2e273535d6081b4c58ca99c7b5e68b4e0d3f71cd532865abc16477d2dbbfe00fcd4f5d03571d4a7c1240ece7af013e8609226bbbe578237b004b700ad006d601247816080337b02b900af0056816929348235b0b6053d896854c682b70d7a118235aee37e141b8d64f50517ecfa45d4d0c0c5d5a2c46bd716d017234667b1bdc9b2458785c9aecf5263d982a23c27cb12161bcb13762d5264d75709424fa2980a4ba565041597ca11383a7b12d1c08f896e30478d90388ce7a4347b52e1a844b41658a7c4a9ba411b821b7016823311046716ec02ac8133478d0e53c12efc74b500c1d9ae8ef2462dfc0432e1347b025fd6a43b55a70664c24f1d1a80ba53795ee7080d62db519d29284cfd4e1354f00026019c815d803551acebc05c5a2e426a8cf8428bca28e00b5554d8b7fbf785fe78b3d96ce8f76667ded9defc9d626f1ea46ea915af8cbe6c3e0447229a8aead25a10d128aa8596a800680cfe5c5a8e02b5286644e73b9d17c51c4573946b1595c3d43f41b970d65af7eff33c0f0c375e49100441f0fb4232fcc08a18eb363b304f1efffbf07f250e63ae9165c0c1e2e0f9e63d6bc0b34083056bb6498c9b31e3e85200b0d5980d57b3f1ac041cabac5468442dca4245b56bb524a289683218af16c944528868a3e9d20ac330746975e709b6369befdbfcf7750e6ebeee1ce2d2ea589bcdad3bbbb33bbbb313a95421cbb3a29b928d3e198d46a4b0855aa748c7d519d2394245e5a8ce0c3a3531005f336a6aa2db68355271484437d16d468b6c06d7817560a29b3d7560a25b27ba5d9a3d852db25a07d68179b5049674dbeffbbe0f0525fb8f9038ca0588c3b800d9758464d72fb24d15245454f6a4c2a2a6ea71b6a9a202b50982d906df4bd0a93581250e5dcdc62e2d17212e353018f15ff0330e9cea527e95b4c8eeec26b932fae2ef02c451770a0ae35fa970c10fb6f9a9744a6a7396000edee3b0799d75a6c1a6280bf52a7a3c3689d1bfe3f8e93671e86a76f737548560a7c69a2e46ba14d635a34b4bbb08093272744bac05492de1d6c8bd4b2b54d993caa8c21ab96a477f1556193ef8025fe04ded2fd4e028364332925d70141bc5c0516c141bc52eedd240f03de54dcd78d9d3a561f005bebe19e0a55d5a12cefb5cc2afac2008822d614b4bf68f11ba906100411004bf32a4294117c4aeabed3eeaca914ad4440406cd51222b388ce8f682d1ecce96d981edfaa27308477d61cb9ec2d39a7c382aa40959d6f472d4a7c31ebc0745853b5021a84c1876e70e55f4a5ba603455582aac516c068d2171a9a931df4dd5072b67ad0a0bc9e7d272a9a132dfabc8e0c85669b15c8a6c9721bbba1cb1ab0b122c7b9a6155582a2c7abfefc0eca9d3e9c0700b46d3a505009b0a4b8a5ddfa5a6c66ce07329524fa1cac5654875718527121723bb7e073ef820111a68aaf32aac5d3f54719ed2fae7296b2a54d9934b2b54852a97963db5c85c5a2d3297967f58773adf7bca9bf2f888ed96192e2d9756a7c69ec24a3d3e66940df05a64f6f4806af26f9175b25de94b17a3e2541fa2c70e5ef7e5bd1c8563577c7dbd5a94390c96719856850cd3c42a6034cc044cab42764bce8abe80415f9ad875480dae011882a5384474d512bed9912cb661f65ff6d4e990a51f52237bb7af893d141ff3ce9f24ff1c1ef2f39ecff1d11dfdaf19334433c6fede85a2708cc2d4ef783ee693ff7d4f961fef065114dffc2145c6fce6d7805cf8b1373fc6f9f0fd402a64f8c680806b108a9ca7f9b331fe57d25c637c9bfd576c4ed0d3af645e14bb3e67079c1ed09897a3c41a87a9cf811f9367a0033b72596ffc4aee45558d199f23fd4152cd4785ece6e2ed7860466461dc704ce6ad3018f465e50b37d962359e0f2b5f602bc43c203e0cc342886198a3b012a709c14f580b37552531fab284167e126920d6589312477d9f16a110451d7c4a76d55188e28bca884bd09328ce8eec7a850b7602c38410e39ca32de88d8305e70849d04a39501c596274c418e48727c60880a81255ae180c2643acb94cbcc41a4789b59adac7c430fcf442005fb5e2057d3980287a32cf721b7cc34d3c9567576c9b4f5db1d11770c586af80c15861524fb8c94a937af268dcb662e336f70ab77dbef671dae7e2bf1c023c223c166708ce29733d96c71982737e4fdf63394a947186f0935885e8b1c42a44218eba57639adfac1886e89c16e7e4f4a089dce66bc41ad199f80ddfc09e887c5f9f73b6383519063036052f288c14f5e44cea27a9276f526dab8f71208d0a6a1d1e3d7ede4b003ffe5a1005613471d0c1c8f642af0cc5ff4a2f6ddfe009ecec86f3c010a46367dfa927862227088511f1121e879e0cf6493370efbda76fa0b5c43ddd9ff820187a18fcd4b898b5e81287882d3e4e30460eab964a9573724ebad19c22f4a57e86d90eb662aba9b1d93ed8a11ddfff03b7b9e15fd50de7892fdb576c3098ed624d1480d3978d3d40280402793c1f51e571db4874424f3ecec3bfb282824ddfdf630e440939ac5ae29c9c963555abc5591251254ac1e31c8563ba64a12ca2eadaafa9a9f9d8ab6005848b3dcec337461823464b4bae815f54dd6acc06fc3f0afa52ff4f2f85f9311744993d89605cf1b197e265f585fa587c9a9d73da93e879e35845dfa6781345d6c73cbfe3f3b15d9104a9d90cd814494b8bedd91fbc57783afff91d9e55e73f9fc3f3e4d3a89f8fe759e47b9c456b5390a2960aa81ea8242c344949cd3286060000000000c3140000280c0a86c30242a9500f44513e14000e74a0566e581d09c420896118650c420620030006604000044666140000897cdef6fe2ace80de9c648b10f7087c3ad48421003d86c8f51cbc9000ee59ee57351d3b74a259041703b192b9445f4bce7355b4d067d5b0ce0f69bb66ae879c1ad6a26cb17e62693b1e21a557c3dafcd5334fc5aa559ff522384ad2c9df59b309ce166378deab68805e58305a7bb13e6dddafb19d978c3b1a8aa519609e0f9c5f312243eaa528e5f97353e80dc217ae68a03ea37301733ccad0ee048c0dfbc9e6307dd17591816e69aebf1632debc7a602e5e80dc74006ae83fc8d4bea72b1b5ed470d9ebf445c2ba57d04d4cfe1f0b03844700dca40f8bc4133ab31887fffbed2549170191444e4bd19fff0bf94f61fbe209db7ca424d39eca56f807db025050e0f4e1ca098f0c2a4e6e0864b55141333d9e46c88ec78b6dceb803a733d3d84d3c5dc24d4dbcb38f32c49db8a5be991a0054fcd104cd419eb4d04c36fb2902d1bcfbf025d401ed53942dc09569dfe351dce33ca703df72f2d1031e267a7f8f176775baeaab1615ec8f773244c78cae25b699273379a4d8433e8ddbec936a28ab34b4012f04384c7e210d5835b46823f534c070b40db3b944a519616006107a68a47285bc70f90670c5cfbdd43b08120d184ac6251e831943b730e93dff84aa110313a1720e6431ff1cbbade9ca116e52062d7cf47a013a53ba3dbf7271b8aef1a5f3fbc0020b8b877ad75b2e1e0bcc39efff92c0d1e3b22f6d1193ef0f246b8353de38c294aef01bf0eaac18887fec554c4827adeb1e6b069c32490994a54e0650ac803640cf5e33a20281bbf8ab6ec96948529e5e338e8514fba363db754a08529abcf17c2baa9eb4e71a63f32d7296dcea3c017e3a112ad747e725a5c2b1a566e42c31d2917bbaf4fa25db6a44347da026a856b6640bb9462c2f73b36a2eafc69111df14e7c15e450b96b64e6114446e490cfe73fc1fffc9893b681260ed2558e3ea872b7588914c068e007840ac1b2b7b5cb0d8373165c5576adf65e646b9ae1d6d4d2c8d3fa83dbb136979ab76b5ed44d14b09784fe13701d4579bebf84c40791d7fca3840283b06ae6e2f4604e9d5db17a977423e9275821a0c394a6652ca53695e11f61f30575db8880af7d2a833ed4afe60968036c555f3992b251cb5c35705fca1fe711def049c6010cd3e86d42307fcfcb466ae52ab9199170f9bfb119e28e39c02a5aab25257c1850abb22673bfa5dc51cda092712c32822f1b891a31296a1763fd9e6e0da5c0a2930fe541026ca6e345bbb58c0e25a69221db48655cff5cc0f11ffbb6dca5a545e957daf12e53b874cac3114f75f315a1c446f494db54731318b6c19886902e468bc75d8383af3b0124148f8f2694b62808aa1ec693957803132a6d2000076ba30afc0812c63505a700eb6b8b9b0c1ff2648e7ba5a2456ad741934d1dc94245594496fbe5258620e3b93678a3896e56d057b1b89fc108f5d29b1eb29fa4096476fa8c5de463097f7eca967fa877a6ecb5d462fca8ebdb5f04f7b16a19ea3cbcb48308d243dc56f4976518350230deacc6d221253ab15d08c326f5b7111775cdbd93a9fd78081773199853c40b012362816100f8d94da5d6233fe9761dc1f41d1ce164ef9efd28f4a2a5a3b379f0ff5cefedfe82e9ac6f1daccd427bb35ea04b03a8320d1ddb33ab92c1b2daaeb78f3d59bba750ce1219c20b9fa670c67d08e025bf8bc2530cd52e57a6bb8d312c353263747e190cede0bfd84350701adfdc587cd814ab8c55c43df821fd95dceeddcbb97e0571468a502e5a72e2a27c751fbe3f45e64027f2f953ca243f1e36aac9deee968cee2870e7c480c0283ac145ce254c4d7aa249e4b46b03515147eef08e476ca04d110ed5fdab1aa85f7bdf2fe64557fcecbea49dfbccfae446b763dd882b5c1b3b96bf76cab6bea5baec04b77eaa3380426313d6549f0d206e0579fc1abf2810d8f524d45ee49077cf275bf4dd260c488ceca7799ff4e52ddebce9d69f8e7dafc266f924497418a38ef9088a40f643c96f4750aca6cb37a669a217d71fbbbe9df5460bf103b6a27ea04a99b652834e0f2d9cecaabde6ef74a03ff2558d42b7c38dbeac905f9a4d05948d94028ddb7cc0dae69bb693f1f56777695167d8365598c083e2e70ad2cb9952a3b7620a7dfe4a02d0626c3b561f533b686626b804f1d62c4d8f2c09aa2b1d491ddee4721e105f86f7b6e1f92e2721598c7fe7f07149c6cbc4f1a24dca4ae7fce1a811406a1d96ebd1b669b58e64b0d45a3ca0e97104c9fc6f4b62be85c5c757e1d8177385d1e32dd4aa06c23fc547c804a1c237a1b0aa5614a8c5dac213937dfd45a2bc74e5456973e6140f4e5b707c35cf72487c0bca3c7d19ec177e1494b18ad375d14f97084c7937cd024f39b2361c614f7c6c068081f92972d8944bb937464a2e2e73b8db58b67edd2da48340164dc4c429529419e7116205e94f5b4d1a3214789db3ff8b5f1e2ee0ad8bc673a491a4a761d7a2595e85c0c80e81a8fa32506816892a24749d933031c03a85d65cdded4db67635436e0d2f1971d4929895821c29443fd144f8818ed63416a62b5d84a9dd83204de97db2aba46fccd7e06b365e821b0aabbaf52a0fe4f38910f6f782329fbcbbffbd3fb6cdb084438d8007e34da8ffed1e17840bb1253fc71df1e816a59391629902e180fc2db1dc026f5d94763e1feff23b69828090f2997aee43a17e8f14c23066e394f5e7f046bbb0536aca5bf951ed907c11c64bca798823ebf595cfc3c80fd35c40e19b391f06ba7b741051bbf5e8df78f2d0862a478196d26a66a3107511163a2a561d185fd2ac4da6b2c3023847d1b6cba94bcef98297391a4d374643f3b70637fe25f514d862d0bb90dd2f78e1926b5f5b72fbf07e10c3a04847214385aa84945711809ddd888ebecf69653585cfe5a1b999c3711b77514011e3afc9f54daf9d6587671aea113165bcc6d3e9ee3588790aeee4e797a34a20d1b048cad4952b572f27b098b380685423772042bcab92d7323de2dbaa44ac5ca798bd23191764f383f47f77607e82d367a036542a3cfe4fc580e5bb94b84f08d9ab5a07d8ca2ed3c9c054d2c24555bef182d9c90d2d11ba97d291c85d98b050bc92c7380ff4fd3ac8aa5a0da701cd8ed3520d985772b93ef95cfae6712def3145689f9fe4f6792bd6c30dae21d7f3ef03535959ed720a5ac4d957da66666f4baa8f1dea35d023b664cdc976391d2f68376d649fcc729bc385d92686c71846535a26b2a819aa02f83e16502e59d8b58177dea7241aaea12e5d13d57bfa2ccffc8371cc2e8cdb2ecf1f3efec1ef403092211a794ba6ab41754a7992cca1cb1c7ee279277c32a40b99e9fd8aaa3b9c6e74380c46b02b98dbb435f51f3f517cc22c743ff732a656270fa1820d9f838231324774a1b2c964d848f6504c20059549ed68e26e0b2fbded72f64e3ba6ff1fc852ad80cc7de79ba9bb42cda3845c58529d79935ea6a8c01bec600136a161556bd2c22b3b8db8dfbdc334f45c793e6380c3f093dc8d4c99e22a02de5a8db33abaef4f9e3a87b732b7ce42d72623a1af4e6c0d7bc68b22f43157325710eb8bafc5705001d671010c12d73ebf5b9ee72e5a2e963674834ba0e4c7bb8fe4517b1e4f49ecdbad2ab7f4bb67ba34e1a564fdc79efc4c861a875e5df2cb06e4f244db084c079c61c47b4264b2e478f8409e5332855e17d98061252291e3d4179dcb5ac0d5003191ed2035c6fae5224728c09d434c4ceb2b6056fc12869c17360813aa377370799e3785716019227cca3780274961cd45ee87d52f64be3d5d0d45e3f19bef325abbdb055419054b0066b38152ddb059e8472f1fc470045adea1e7c68b7439d2ed467811ad1bfb740e26ef14e902231797e41626ffdc8cc1bbef2ab1844b174d084f10cac4c46fc540c75cadc6652896c5ad1546bfb34f4be8d3c15b01be1d229934e3d77145946d692b486153a4afd97581c71b9668fc1ef1c615223df7219a805e3a6d16446c630fb73bbb3f066af859f86ca03068e2db71abdab909c46faa9893af92890fe51e0d3952e7271f2819e1e4044846e3b37540dd6f930926d3b6d4f7b6dbfce6ca19cb11f040e7fa5a8ca49548aaa6ec2b0c72b8a20cadf349dcad189a2fa82777769e38e2183e16099bfbc9e0679b53d957bc62b5617135323b4f50a47afbbdceaf20acb4d06bed4b7409ae308f1dfadb6d6ec3314bba4eb6cbc18b62f6234aef2720f349ae8e7cc9239e2d56b768534a2f7c0c189904f032a83aca93a46a15b0f83ac97ebfe3db8c0a11cdaab5447b60415377ec95bc22d9fdc254cd7fc46beca11a3dfc41b832e68c1cfa3bc1710c64004ccd42ab4ed5eacd2d4ce52b60a81d259273aabde39321ce69cee240409d196a08877d53e2d861eb82202a95d2d9a61ccf75de4fe31109265f24bf33999232196ac74f23d36cbcc793330c804eaddb5aeeeea874bc75ce5aeff638e6557cac0bc0162d528aee4661b08202814b0a7f6fbe2943fa0b9b5633c7522f2ed8705c3332e58afe684d27f27f3936d3aa8c8577d955df57bd0862597e018bf29d992b149dc97755c4d4c2dfae08ee74d7f8df05d3119891be6bf309fe877947e41cd6afc7a37714dcc44684682d2c90e97c6be0524ecf9a7bbe03e0ec0282dfba1fbb5b4da69313745c141ffa86e9a5496be6f54a4b3866fa52bcee3f831e97803203a46ec8075b87d24c5d5c6819b532a1bb7b31b22255451cc94c9837815d4aa2906340112ff081a0714e83687cef6c658e3d51926f2b4e1bc27e61a814e12222df027414cec082674a539dc65c34b46d1b31bb0027e4b086670d128da55f13969948d5275c756dd2fb37288a861a1f2b665f7ad4cc8f110ad106744719045b5dc95551fdd9d2bf4465cad814f29f59391a28a1a375e5a3209dbb5b081e618836e0de719bff8c5295134b526c0934ef80d14a6a856913c370dcaad01be74fd9da57158e969b259d50038980dd3152b354589e443bdb5fa65c164414374e38c6ffe42fde10f35a03fefb2a64a0d0592c19e79b946aa296eb8ab29653b4ec513d609c55d16294358956ca32e6971cd472bdfed4f933dc447400bdf41dfaba52da194831d36c75b552cfb9488461f8ce6abf7e2a51bad0449991cd641f50d45e75b0de8c901be6faf61d200edbade81fa7ec8f94b75454b3f20f58f422ba1c434e86a3c48340b4e980a6217b861957cd99bbc2e31295861b9bc59d55277011427eaddeafb2df94c4a98084a766a252b21e915f2489094204bd4c040d4e49b3ead3e7d422d06b4b19e56273ea6c75b4c17c6b13265376b5e2d13b88e4bfc623edd9fdd10e30b9178e2fa35d3dbdf284ad1a5b574e4e635140aaf657180a573f7b504e51d2afa0953efd20d192824bfe0d63fbbe8f9844a378417f2822458d11fc0988f6c23b9068327c2a38a6428be50250adeee6c1d161d8d33cac6d36e1c5b4913650f6762b4dbade2c80f379d42b3eabb88e712a56ba24e30c9a001140dcd445d08dd06ed3ffe222393005147b63051e42c79d7bdb432b9e24a40e80105a577a0e1f064bb13fc14d111ea701570f6a6243fbc2df44e7f13bd06952c9626ae9f89727564a74d42377fe0095df67b5ae009bf03465dc0c9277aca2aa7ba63e60c52aa27188450feb0f1f045fa41bb93d0e65081e23ba05fec6fadab3c0d73b08bbd711a4c12920ddff48b607d8cc6af9f49bcf3a77238cf6cbcc585ca4bd5a62e9efa6782e8eda8267b8d0c13126a9a731d8690e8f568028e24c2c00ca1885e1ece447fd20ff7811a8574b1c8be9dfdbeb14cf336cf1987696e2cd5ca7141091d8b7ae5d9a3d8707837e9c13df29555393950d0547ea26284625a58f2f58ad6f4d37453899f00280a6c31bfac341ef51a73b8f6e1f2610ea7702b736cd322b3d5bd62acf74c8ae370c1f68c833e47b43c58d55710d08952d112a88ca16649de79b1611f577e257e45a9c18ca9f29e882de71931db2dba603dc89dab208a237532afe6326a9ee03b632108f126d8718b3de0e74717536111882d04439210432841013e46d2bfad293a3141abcb6355d0a76485d468e93e8f6f1d3ae79093b81edc0c1c6f84e709c612bfc0195bdcc354cb62ac9d4b84baa73a2258b1a154a400c253609569477481ebc05f3c268a4ef7cea995d9e32c95e9fcd3e622e519265a5eb83e29212d270100d17f93ae65f5c85a016af9e7eeada29b93695fd989201b8532d5533e621187d067e93a3af92785240df5506b2e9929bac4f5ee1240d7f3f6a2490f499175800b1072d91d95db528936f0ca39c36a564671f0811f1bbfd6765c6f84341a1cb32e57f851540190fd2d1f1a276c9602f4587c9e95bd4ddaa1909bfe1370ab9cfd0915478ba6652f67b7473a4aae243730f447b97480878bbb924bf00057ae3a10e9dcf1fe9d5fedf025ae215b85f36643acd160c3dcbe301bba83570a84bdb3d40cedad8af705767cf4c4416d0159b1baaea4cfcb489b7ee723d21425aa2ced3def9cef9bdba4644a0f38c2fa843bb6cd9bca8355b883a5eec7bd5a7063fcb95c62d155d6e8dd86c7204de4b7b2dd55100a0e8e6c7486751b53cfd0280594705d48f85c5c51b654c83c7ad1dc63461706918e4dbf2217a771d76d4f0980de731fa092d89342052bc5975dcc796b5b0e4b8aeb594f043a031314bb60583dd0421e8d686c1d32323f0ed86e4ec87b68526f0eb5613724ac304d2666fc5e1db3f09ece9f528b19034a3a4f56e1c5fb5b69b5a93091b09aa88cc523585e6e099b5e820f4dd1d58a4d7d7518b0084b3bfc3de21624fd2b82d1947444408fc7f82d588ef26d62ce6bdeb0e4c789f48b050af15c4c87030943f835c9f46af39b539886bdf2028975e245fdb4a2a78758cc3931580e7a6377ab718d357316ee255c78317a1d5d06998d5529ab57d6abe994c918f35ba7b3474785c9931a4160efcb918730cddee4b2aa72c01651bbde06dab132bcbb032daf6405a34ef0062f2d3d4740eb0c0cd2e13d37eb6c683c0b4fd363559b1e44d5735b69cf136b342e4618506106424b47d6db835534c6d1fa8502ef3cd8ea19169b5bd6bf0fd392bb548cb8a6216b795250082d71bd656bc05748dd1039ce78c838ae434d2f2a37a9a66dced4a3c6af50c7f8742a0cdfbcf0787a19e49370028a62c42fe0a1040f5354158f8d094bb096f21e0b4429fb961bd304e931f0c68e9f2f57368e80372c29e7740504c5625dcf0e97054603d601e61ddcf388c32e6c7e4c6d7fe0559e8f0a2ac40a19a25a6b00046605bd37faabb69f046cc70774721b3eb089c09c90452807fce1e86c8f1b95e6231ddbc8ca524ff971875bfed192c909e61d62d7b3b58982849159e8b4c25b54c187158927e10af7c3974b2ea71801d4f9791ba9c3ccc2e780e9de0251978e242be7549f061cf51a76c0206b1e03dca9d7677d38ab261e00052233e2607b11fc3bf21152695e00a9f0427c3a900f7c727c46de08602ca8b5e03a067c758489e1cad7462330a2afd2c94e09ba5b64b1ec355131e0e365768467818166ff02493d032f1116ea1804480bb664fd779ab2d214b47d4e8c1da1f6b7a0df462e80e401cd612562fdc19024b978a9d48fdc997d4e7af91198287c8ee5437fe0f59bdd02431db7e421f2d6079042c56f5e07c4f9ee520ee40e263d2ce4f0997592a251d792e42d31e0f4fa91df99fd844a6e57d978ef938b56b3299400bb6e46c7df299398fba0fe9d4c312ab3df32cf48a3424fc2c417441b318b9b2d4625a5198dab27783b59d1f7fd954e426584315172d083c9c72854560878895e39fdc8c7a233f8016ee0747459a151996df4bcaf9e87eac9b945626e1ffb5de4c7e1a759f3e9cd4a69d60ea1399aace3fb4a8b43176272ee771e8964edf2135a83fa8b2f60d920fadb0cc82d24a84610ee78a81df6289e88a59f97971f8a24bb50abd8a0417c63e8a9a770533896c894ffff946a46afdecaafa054532b62bd4143265eeabe1da2ffba4ce2dd43e85b0dda728d465ea9c76e18df7e03a59aba21d4e2de6d91622456f4d8bd57ccc0f00a56733d5432b60ebefff1218e739280ae31081b667910504363ab3c470caf5a267448a7ff79d90fc8aa24f646b8e1e073d4cda57b9585d21c12b236a06a943b285a1e6203bb19f9fb65e2e5e76efa43371dfa67636053abe4ae80d61a4b99bf50c4626ca5f8c31c5a36c471fadb425b5a744f35028efb035c228d2dae0ed74ee615ec893ceae0cb41f772e8cf91dcc0a16529cd9292973eabc2aa072607ef4470bdf79d0faccfa2371e3d1dd31771a5cb275a25d0345e31a9e3309b31653fc49b9909e8f6a2311427b2c0e2465584712c616dea57b4996723ed30530cc788200e328d2f82fe1d631a28008a71c76f372060cc3fe73c54944589015b996f4989c7e7212d18a18504140217e7e958cda2e7c8f2381e80583f79d4972478ac1daf33758c8a22c11bf0647816e3d08776536f07b33294968cb053f58784e00e78f267052978d75e2773d98680b199f3a8c6d21049b3a5203458faa2643faa64391d1896c24b4abe92f7bc089cc4be754c5f93584cfa38f48e26434d531634875d908d3ca2b209d0419e9de52b06b24c2b01b984a2e509c84f0566f10610651165afb66ef441b8b2b728b5340f02575e3a3a9a4091642b588015bf36a5f721c7aed93819c9579991eda14b064acd570b82142b93aa1a23e22576f93e97d514902ac49941a184a77defb86ce519d30beba526467180960a6544436e7212930c8bfe88f9cdd510c3969864783beeff77fdc153cedd43f33be584c903690fe36bf7f3e15fab524620ebaf0211b52b2d10bdbc5458c395237a716881e18b158fb49c22651f850f5301fb9ee93ff66ebefb26058a4d40d0201f26d70898d64e6134bd6fc22e19e2a8c14019b755a4418270c415eff951e3a84fb4694150111f478e16bd96a17218c452e6166a227a579fa9fbdb5a8d4aa4b50659e751dd8b26ba6532b71cfc55cb722153b3f7060e7a1cd31ba375b120d23ba30eaa548e42071cce1480600755ca71275880a6b2406309444e54c8e6e5d518c7235111eb82096f9def4843631ae1a10dd2df0fb8bbe5bd76d775290e601894fa22c8a97b0f68f9a236d681bb0d07ab2dc2a4358df108226ed0b40a8e846c2bd221344f751bbee5e9e4a33e65a375b9f5039ec0144753b7d380c1ce9647ec0d49302fd0eb39f5a3aa30495cfee2fd159e24f1eeeac085bebec2b5eba8c7cf90a255e08e07c772049770dbcb8338aa9d2f998de79538e1e73670a924f89034d049a8a45f2dab2ab2012575ab186fe0e6e4c42cca2e64e66e80f2c423dfa5058f4fbb821add1ec15cb26c1d298ee46a64ae4a34aa75e103b306adc531b8b19a1a9a86852ae32c670385afc3b880297ea6734d544a99aa2fc95c33d0695a3baed66ade91b8afe4225087863404b78b24c49af95343ca74a1662472a1115937a3c0e022e8adfc703a34e86753715019699c7a0404e140d212bb142353e78f893a61b34805308468de17e5c8816e86acee0869fa47fd58ccca8683281d97e2c3be73862ae1e8bda00d6b21a2003822b94536e9aa459a556997910055accb852a17a3587ae2cc6155820b04a7f225e3bc8a96b76e8be44d21ebbe0a347525456cc562939346f7b6b2cd50c3b5c6c8daa8717aacd8018ce04ded0fa8a9cf4265c95cb1bdc7c69972c07f3d1002b47818951d5e40847f0bc703e075b0db7c17a9f09e69974b5a69b1eb0550e9352cff16feddb354b17052cdf713ef2530a66703003f7b4bf531ebe1e43efe46511533f1dc309c096b590b768da790c8426eeaa09c5854e7e2c9a24e466315a9b5dd3a466a97211890e853d38d941e1ab80337f8dc2aeb723c019a10229a133dc28c995670d25b95d4c8715f351d60d5bf4bd221ee4a85809ffe90254d2c4ec9750889ffffd5fedef02f6696792e410ecdffa562d369e865d5266a14a88389e0a8acdf46ed44d46630bac1a8e21c8a7b36dd483e03024b4c2f0850c09103020fc851ef8cfe03135281d5a76378662976502836fb42c37f5c3d470152a015fa149842432a770cf1223f7314f119ed1488be4af1b357334461e96cac94432ff89d3b52a3f3a451fe659c6efd0b1ad835e78856c2badb706ee54eb97425be82f581acd0d0965ef20fe0811a4778512552f55a7100affc7c475122abfbff1c1282c127675e6ca78ea086695b031c2e66a4de265b117ac6311daf8b9610156c64d5078bc551bbfedc16b858e8d6c5ae5a5cd73c04304b59099549fc65c9d520dadc535cf10f6afbca73027e7506c72d27c16e8b1979b8216019edbcfe661e2d498840f51c91af045dfe8329c2f9aa95791ebb5150f3d73902b8aac28b2c0194267b8f56ae2c4956a13d609a501cbf225cf5e94ffc31267b37f6f73a12b9addd78f93a06f3f3684ce353919e814edc2781246e742f4d9d8a947966b3cdf50363fedee91df31d741bf9a0d569d161981475cc1b554e209943c16b4f7147588e657eac3714b97d2b334ca0ad4759de6542d6a86acdd5a8dc85f3a11946200094f26749c65190c1708956d6f05d5e21b6a1df49a5648955effdd13942d324d31a6318cca31e159709db176dcc24756c5d870ed0510167519048e08b2f2233b931f6d121082887ea422b30062dbce06f91f70ca70c78060aa9c88cbc306ea35a329e5d4095e21d5c1a3ced0f1635416be5770495b8f114716b813fe7f5099d8c36d631866ca1f518edb11143bea27b88cbcbf77e3be3769dbe482c1d78fc619ec313d4ec4e2d85596c289d48f6d3fee43029663948f30c78db565c260943b0122e2efac52b2507af1f31f979dde5855219cdd159df6fd636d28ce87ccd319cd11abf129a28896ffdfba77f363ce6c3c9406090d7c722e997c324329d45a14a25df21fd44dc87cba29c05d0a5d9708c5050616eeb4880c1db8871934fc450260efe954f572170ff784f0b56598b90b17741db0837177e1224daf721192ad8387ed8dd4c2b831dd4ced64fd74f0099f33997202683357cfd26ccaad50e3790763d69d1065c8873a6e0d8844bc9f12eec312f372444ec105e7119a69cc1030c31355f4d7e2d76fc38f6c91d8f9e6b536194b3e7f7af30fc064e9048195ade675e135a409b41442a01c1332b5331619bc50d09691b83d4636c70f6753ca21b22721795ec14821ac5c3e455b159f8fc18322dba2bd7759fa9397a49189fa59e4cb7774bd2fe817725a9e8861e315d6555e0dd11f720364747a7df9c59426064e4a3d45fa3cdf6d78e44c99c1a2c54c16e8562620ea4be9713156ccc48b889f155b4e3c4c83bda281ede3f883d7caebfc9b3a756139acc10b2acf2f20a8813d25b00247f713b234c1cbfd4225f2be86c13b4feb4f64ce7955c46b6e59851ab80c894ab40dbafd62252123feb41e3fe40df5fe428ed79bad9ca3400c6f71008f5c9ba6d98975098cca111786cd6476caf5581cbf1996913f58765dae2fae803b7307c2b16ca837ecf603f50ee9c8418172d550f800d16ad901060c8f41f4b0550514d20e2c1e06aecdb816e78fbd7463cf7439531da63b570833569570ebb2411ae81827ac5ea2558d02b19e071709f50ad98a7781e328489f3e615e0f9d480c95db694ffca276ed20511080aca10c900295500451212e9a8c68aea59f0bc24719c8a6c4522522f46e48a321e89bedbe59e62ad2f4703092fcd2e7b2301fb5939116b7a16b4380e92bc775a4007b6320d1059a1c3413b39cd1a58a974a0f79f8951045743b010e6350e0ec60867a1a854f8a242b6e9ac0a8ebeac769b34de116e4d5f7f455c88ac4eeed61334232c55831719b8cba9b7f7fc561b64a0015aadbcc248793f4cc84a70641ab71d5618c2fc307185a3f90382dac9449f5d5ef02ac94dccbad329cab5ff967fb3f2197592d4da6dc8207a01527d6a5b88a7ba9b0095c1fe9f1d90ecba07d29cf825d2d7377612c5e6cc4b3f8132c7f4ba97bb8ff828e45f05581edcc1cc8f85e2a39b4e9e6b16b5dc2d09985dd24720625eba7db44afe5a4488829f87384b94803911ad007d9c2ddcbdf30347106f510c5b9e55d09ccf2f78f46c511d93e31c8145a3a88fc0e6a6f66c8ec709baf2233b6ad49e9bc62aca7986e80ec7cad677c89a30de199a5ca80af8cc265cb967c4eb5d28ab467b28025a368b63195f544e47e1825e9578b9095f22a6776c0b7de89ebd12a8d6675cc066232bff9286a95bd3e3333e91a4d5bba08677bae1f18a311c9a673d65756783582f6db8611476da98f5bacecd8959d56444319711c9b2200fc352b25bae1706e1945e73edab379f9856033b178990135c161b56ba78ea6caa7feb726f8aa449dc5d8b12d38745aa69b4c26050b313a47a5e8ce51d21d2a29195181ab412f226526fa6e1567ae860d3346b4288c024aaa6f1d1137c98b9534f006db4c734db31404c6e56618cbd52edd1ef98aebfd2a1b4a34684d4e5056b67a543ceaaa01d7983e90895eb63a0cde60e36541d92bf733d37e946dd1a6a28aaa5339d1907155b4180b6764c4c75a1c00de586620d332cbbc8be5b6ae4dadb09e10bebbd30a426952e1a7ef51e87c467a5ec0867b0cc8488dbebeabf63c9d9fa71332a9137d1b50c695911bc82a3715b8edd6094bcb489d9405e779f7c65511d36065c859bad1eb5ef5c5b0d70e9e6bf81d99d20223b83ad92acbfddf5a5b1edc955d42b0fb0feeec7fac34455ef72796851e7771b1143a3786bac8ded26316a78861fc6dc6ea23df5976f2bece8d50b9abc9a9fa25a76984298a2bc45b5a7a86c21b01319fe02561b681975819de15416ce7cc4eaf0c17ff3eb2c8d35dce921ccb3f73a0cdad9312260a4df1581a4821a0c7767e0ee23ea0a55d621ed52530af400b41fe0ed1a3c86d8d9d9d7bd48e00e880982084910997f487de6e01c8ba262858ad9591b445ffada0d25fe95ae78b9042aa59bdc91ee1770488623cc01262c4bccf4e0ea14c009733c734afaa21b4f87f500cb9a7a0020719f607f14238375d0c27bc1f0ed6ad80df8b420db033be1567cab980061be761905a61d9d79b98a6423cda8e43cb357b625280a7eda4490eb03e9005272670b07c5669b8a5ba534d9481679b6e56e5e809dfab3079066af24b1bed7d9f7f5fefdd044bef06f02716c4254bc68e7dd3c59c9d8abcfffcfb853e0fc8cfb3f11acdd7b22ede910613dbd062c2231d8177f8c635022c2e8f7a80f77543c799bd0b48c7e5428ff962634a8aa5376f21c245dfbfad37333a386785a618f371fd5203bb6f6f9e0601375f279fbfaf9c53f6125ea30f8067cf4b99181da490767a3fffbd8fc894f94b3b80538fadc9ae482c6570f7ad10511702d699f69d71b18219722ad8318d250a5dc91d6f642d471bbfdf36f679a08734adbeff72c4d9510b401ef2e6a1d92b1f799d87da4a61a0a521c3a649332a4ddd9c7223d1a41764f52c4e00dbd5cb4181ddcd40f0cb30bc40c6a327dbb8b98fd24384c3f5248301664540a72e62337f4721ed0ae96941a210b3c793099fdeaef452be99f0b884d904e6dc5b182d507ff0416e772bf2b768f1b8984f18e5c846f7f849f9d5d97b5aaa293e740dfd348f160ffc70ea29463be612c95c7141f4c2e87000161c7f4370c71a84f069e23d7a7cf4e7938321f8f67b1c263b01376170d8ebc8e3820590edad1cf8d2d7d1c308b17857c1ab6b9ed91ff90f5ca527396e7bee48aafbefb697283b7dc2ef8f199616aee9d6566cf2d53fd69f3ea23cef55e7326f27fddb8e394baa71a4007b53579e09c0003d3e82c331c94c92b95229b4d7917cd5da62d24012c5771384633e6d54c04aa1f7707761c4589389748dde62489f512326e464f0763dbbe5ad5fac16cf127b6f5b4dbd44be212034c52ea3af7c2ae411535688786b8aa7eb33b56b26c2e4db02c68c4bcd0820610b50b4b122edd06fc47613292ae9ed3e46b31652c81842da8064db1a1309b3b85a941eb444abfcbec83c9637611ed16957eddcd40719e5b7c51473aa1713bef2bc52c680fbf43a8c8f860052a4d0bee4f3da28ddad514ffc44afa5a9a1aec5c181afad22df102fb85a41eed6219a138368a5f1a255e5225bf6d093ea33aac1c627ba94269d4604dde70ff93bd1519d816c0c729da5b42b326221957738922434d82b46cb2651bc34ff954534acdddcbe28c220ab374fe80b3ded11b3e019921665a1c6a3248c32270f2826f7466734d99060c79c2f1494be00ff8860bf6f9130bbc87b4a28b64512396982910bcfd460ee4a7c470fb712c9b6309c9eaa89c36833ba46aa0eddb7d06020b642f4ba081cc998c9bdf6daebde9dbb8ef32f17e1e8316009b03f9a40f9995bf8c5ce659fb8cdc11dbfdb1615669a06d6407ec44da5e56fdd12e98251a03048501049ac028532df7d1e322f0dace9b6039fdf1b17a80910a95e270fba104022cbe841122c83cde7f1d6d1d5b48434fc9b6ee1191ff76f420a445a84b7774d2f37c19ce9ea5e3a1573d4b9354a67504195fd9d19b202623ccfad83b13a6a6d6c971a939276536964cbdd775833e7b145ec6ead7835906f5a4744a33f7e424efe16dc84c5dca974158d283b2fe9e6d3e6855c9a9ca15f695e926de2e087861fa35a96e15df7a79d2f126cdaf1dff0bd4bd333e5d57ac30faaea4ec981eb0751263841199a7043795b836484157698a0e53a5279076a9a4c90f108ddc1d2753d564e2729e177caed8f62abab14340ff26670c4064cb7bcd97eca3fe658c92877d5ae0c2aff48ce1547f5f629a54739cedd65b1035332c702b2cc03d62f21329b6fb41a802a0dbdf474cc3b702c134a77defda8071e19a89420be485bd216a2ca2507e8dee6c67cd1d9762211091f2a7027623145c14357b2208411313a1f0bd3296e15fbbe0513177b86320db983f74fe72774459fd8fc91051550554ba4a0cd451ec8acdfad6a05414aa7141633f907e9f9a831edf2dc9e7cb2a28308cb171c84d35679d777c19760bb3eb52ec6ac862d5dfef6cd826ef04707049fa9e41e79d3db0220cc6f0db84f1c08c36a7e25b80cb685888671a6332d4bb6f4a209426cc562f91c9335aa4453a90d9ef0a74001ebb3b9c188b7707bd1c9a44119036eceef31fef54408c8add25e4f36fe078667bc0b277d81d784c11790401ab7b4c266b761888c41b2ccf0d3e58ec541cd9ecac92ba9c2238c524c5525633e686ea2dcaade7864328c86d0775098769c38ff536c37ed507b55d8e1733e202fd0f336cefb2d4fa0418e06011e31d40a5356a0907add6ca24424040af7392a7706d311b29adea2251e6a9567053d7486f0482c68d53b30dd4f36c087cadc8b3e782d13a20877f7049b782a34449c59ca20dad67a0f88d1ad4dc9be7dbb0841df7da76e57c5c8e55f57b4e4de6f1e592febc28c601ebcdc51f22e79340c16ca617ef532b95fb04f0b36c4ede4ebe22128d86f27115062851c1d8afee9b6287cf27ddc6d487ad26c158691a4f5127575a599cd27557e2ce75264fa3c2d5693a56cc13bfd72aa474b4ef46c52de891420b735d71dfd029e6720a670ad26cbad8702f86b322bc4122648d789406ffbd6554fac28854c870cfe79971ef117ec5c9f28f83907bbbe7bc4e5c59a33d95d7fb5e07cadc1aceaffaf41d762dba60cc1952eda90a07a08123a62df84c6790a8718ef6d7acc3e1e1e0d98da1ab1bf0a2e43530f4acbeb259efcd12b9ac472a81920d5196f31ac951766d232e77ecee010f6bdeb2b48f20075f48f258b519d18f4607abfe6014615ceab7bbfc2cdc1a1c8bd587e1e783fc36b0bc2c0314cb5c62de60006432a227b81e384f26230010d372fa6864feba696515ce8f7fd791216ea305fcae457123571cccde4e0775619e800714df5b6d2d22e3c9680d941c93b822ca7b5df659c39966124ebd36cd1408bd4422677da679b6acc6d6408e0472f138ac4d55502b9f2c2422d985a30e10292e381dcdeb37587fd076b4bb36ce2e7b0990ab0e7c301799873e54545157a89a8705e25e078079280ec9b4bcc804082eac5f4630588a48186137fe6c0b945c1aaa4914f417e4cdc13d643072c80ddda22af0d3aa2c141c16635d9d38f7439659bbe8bb600c08168410980c23a4994bf4cb723de1d8038ff2863b0cdbc64950413a86939ed67e15b77a8d0655c73e256347fc37b6f07ae1c2a680b9f2d917dee34f755898efc187c7079613a81421810bb91f82bb191085ad3b36a0e038f6c475631900fc05f478b1071b20fb9560905e53bc1eeb4c6b7bd2bd2a1d153426ef10d6cd283bc2efe62a4cbed4d299590eac339a43cdc0c8a0cf5f8d77c95e5df8064ac7afb6ef272576b80344504ccc0f52b238d389e300ce5c0828c0212264ceab3f49f48ada27593a386874d4e687f428409495505a34bf26378912f545cc5671319bd11385122063637f5644f269fc73e189bcb45f47d09fbe4060f57f19860778b35c0801702a30498d30c9d14510421ee9039153793223443c1056fb46c127566741b4a5c8990c848c2b339e5db45ad49f47b69467805269666b7a4b0fca58461402b4cdf2f59b74a742f2914eeace79c863837eac0a74619021f4b675e73a5d8d4a5a2e8a0331a310a084bd50d502dc2567776de9fba12b0e24ec03d1c852c01154bf0c929cb856b91017cc773bec74c2ca02f76f23bfa51a55856faa40d0c4c8e794085941d7925ce8ecee6514c406598d970d0bcb66a361928280a6aa9afe32bcbda0ef6bf6de6d510aeff1e15e57dcb8d4b128dfb5f05d123f5aca8a6be694ed003443c10f1bdf00e63718c9c33c17fde696c2205717f8767b609e3df78f51d3b52871ff887891e54a6eac04f5868ac356ca1a67a25ab5a156141af354bb9c0a87c35d59a12aa5df293928f75d14e42da71bef010b7a697345d76b9b76070a67754de01b1082af031e77b87f4d3a4a5ac99c25e76af932884b9588d4d882cbe3003e38578c44d3479c1dcb9ce961517f483f7f9db99db8af7ee339b00160e5d22cfa101b76af16afab64e90823836bab19c10a3ceaf093f906fa2a2786bce751b65733d74767c5bdd4feda6327c2c5cf254a1fda5ac9b56f264ca762260d09bd1c005bc953b0d420293345b6c0cc9accae7f1098bf8d7464f0b760047721c5bd2127029d003ba52e3614cad3994d66a479fd29d7fb9ebca83352d5d97d66969c40932454604d78123955313a9a5d371ab3743bbef924926dd8808d175ac468809cd2be9759395c5794b9103dde690cac75de4b99ea5d1bbd06c7dd566c60514ac332b6276fe48ee6b27a86a96cb00296adfacaabc20b5c06bbd993732dd4096ee03bcc25c9b3918e0d33a6e31a6944f0821a68419faab5d1418f334e13cd2617dd6e3c179cc0ad9fee4675d94ff5033933948a8da3a2983292c0d78596f8903feb243d820d88af7e3155b109a88da8930b6a7245ee3384d95930e29b755a48cd62c68dcf26dda3e259559cb14760946f3b716ee6f8d50ae730e1b708213b152bdbc816c8ccacc307204da5a38125f34365981e01c463d7c7bc9d6e491100a75cd07a1c71c3297f9d9311a41f79182680f6ad7ece260513099b5077b73a9e4f71d15c902a3849543a427864a147df73ab15ef26ab156f471df5bfea340d321b0209da84bebda396c49cbe3fe21fba62550713dc9a25c7209f5af3615ce94f68b3ae854d4f0f241ccc7b0d6789c9e1619ec4b87a60860ee127eac4476d447f3f5a767f5c1c4587a43df7ae3ad172a3643fea0724889299a13ee67af95843f3e44ff7782c441b207c0566951e56f9baa18c1504ae89bc821163e41dc2386d24cba2fe520a98da6a442b1c1e02d42ebad4fa82c8f5953974a8c2276f1158582ab2398d5c50d30576be4f2857b57a4b5ec3fbf86b3d113d893bc026cc4037b105cf579687fbbdcb4291e325b90107068c2f7d2d37721546569d6a9899eafd1c69700c8cd47b14ffb67fc07ac4f85b05c0791dcaf2c04f1288b9235e731f06b8cd85a19cd8f09c24be1f7b73ac86071454a2bced908fd83786d64d23bbe78061c149b479d35dfce3c8a530288f146b379a00af71738481a13807160910f6389d5ec227e1a09412ecb7b80f959d49e019897391ee268dc7880d43e3d91b9962c48f91040c15c46ff8aecb87af16df3f23608403f222280b53d706e406aa6ec51ea61f0f0751d268e92900058fa028bf61350bfb690567cbd0101370ebddc0306a254036f7358e580576050b40fc58ac7b4d4ea4e704b07aa27e3744d8b5469688df55e984b1a8b93216bd84ed04813efae749db6478acf81e26409b1ac4f90f91050828f306a7fb1d313500751e0822158c055d824c713a88b81e869989146a496b4efa0de15eec43bc6dffb608849903d54df012849a1a2a982b2c374f86e50e4ba2fdaf75d4a010f2318925fc4901dac8d71c406fd120e2b88535d95701da912b94ead6215f32d80752d2f98bf2b86a4dd3102dad0b9eb491c15f757cb0714bf1760d75a036821a642b308b952097ebafa0ed5337d2b15ee2fe2d089d369071c93f3472e6a2fa18de1424c86ee48ae73d4dd5b86cc2f1e6392667bb4c2ad74358e384c8a00bf23ff0d7c5750baf26cc12712705c42eda5b26bdfb50aa466518ef25f4d3a602fa692092ac077ad9d74103833725c702213c09a9e59d86d3514422415a90284f74521a0f66c45efbd96392247c6528b28c8dd3317805719246171684e346170e779e621728aa104e1443e8afa1a71dfd8d5d2c47df4d4ab63805357ea1fa288dbc1e05799916145fec8616886a3ddd591c67f26eefc72ca004fae2bd121b7c5af4422a736580425156906574eb7e9b9149e905551bd12804cf3562ff2847595494381c41481de3a9355c6e43c6bc0c2aba0df77b6ad7416eb8ad21b0853ac5a30967093d657b065f7dc9d2c24cb58edb1873859fbf5a98228069c00fef278a56028c877871bc9f232a07f0f8732643c4c900871eaff9bbb34742b61d268de7a5da0663771462114c2d3fcae24a069e3e2c664167e94aa63c2bdc1358cb98ceca146bc42c8aa8f45843c7eedfb5c70c366b10a6463c617ed258ff6d56b583b84a45bda44db1a23858672f3594a80dfd35034ce10bb37059874e58ac62f72a14c86cf563fb508d558317c9818c0340bbd30b6f222d7baae1e12af96b96e176aedc4a9c5d0eedddab50bdc8b2462cc460d36a86300b7822abf3f31bd66e500c484b3929019d8477e8378a455028b54ce0605a8216976c19ed08263c1a1a13b4f01f9a14e446204e5928b4856ca858573022af675c4e1a130539dca3465326e897e5ed48b72602f075552ed600f53157e4c374e4c1f0308602c9dc81a8087e3cf06605eb12a59541ac9a9d88cf6bcf865f488daa436068aebc00b5d2c0164a91c5f2fe1c519c725b3528367ece3d1e93c221d28af72c561b50fd8270f18aa09bd5043716deb468969a88f49a058db8267cfd0c2f81cf056e8bc00cefb2d461119f6bc8becbe3dc4e3245b7631d80eea67342e60641c8e6ce6eb9b8141686a7359fbfea68152709566287590978381345a8bad6a7e054efcd7963438bc967f178a06299c834d5794aa4d0b5ace3eca9f99885453fe016e21f699ba4bda988c2305e8ede41cb6d7a7f365a060d118df863e5e866b2568cb4fb516e9d0b4b1dad4baf4754a68c47d8c6d6d2adf43c6942cd609cd3d980babe826394de8b4ea1f8ec2fa136db220e964f45f3f3e67c1a4884e8931e263d3c4401f925404f073f6538fa8e24c1a602f55a74426b65fb9cc39ae4b365579a137784281848cc3efbdeb940e074b1fc586c44a7f4b963e060b521905fc32a4c099f828001f17b8f0f3fdab3aa49fc6c65ab202dcb7e78a4c621e23f361081591d1ec5664ee6c473d51fc0750f3583267d13024fde9fad1b4b10b5c7ec43b847703c4f8a5946764cbf4ecdbdf3c6bc2c380e8c4f41b6931d55e2d3dd332279de8220fc6feeed3e6a7cc3944dc989fd529a241aef1dacd249cac00d827145882534647c6d60d158134bbb7c3628743747d67b1a97e8aadc4e277c33986dc30bca85f8c7db50d4b1964de2cb71b3eb21799aa0839521e925716c64c234cc4b49464365c60cee8f3cf10e239de7503b635c757ef323d55d84ef30804e6a529bd3acab46c4c113b278c10fe6df4bbea53db51f8cf1eb75a7c563fe9dd791b2813b151c7960be8ecdfb00745b170c0bc681bfc8de0b31616192ff1a7c384cada201fb0045eb4f1002a0ba1d229c9a5519cf8b968c19f35e157e0783faae2a40ac68621c1f71db7537bb9d24d0dca7a5a156de78706bc117397968e6bff15aaa78d9325f1becc06e3091892022ddf29d600f5f8eb54c6af9a95d45d518492caf89b6932a6f4a6e6d1c0037f0aa96575e90b4a4f2bf0de3ffbe1e03a5ef9bd5e24f91a36cef9c032483adc3c7c7467ffbe2ea67a0b8606a10c4e515547735ab1007c41ded0e7d63f8fbe70037183ca69e4f97392180e118c1038ce346ae506055b3a60c6117e395b8c8520276eceacad34767dc01b2d2a1ebeefbeacd0f77d06890da0935f018033fddf9528bef19e0298d40a54f476f07f8070d758353541295a907a9bebbe6e0a3808d40ff47fad71080447c8a1e156e40ba2a42bd44c99832cf21978a506e2360ac5ad09a8a30e2fab0282d73a158cd08636563bd60947eb443e7c6ce04908abe53448b205eea22b24a90bf2c82136defb0084ca014460f0293c5e13071bf9593c6a1e90f385531550ae0a8d955b7b308f28ac27c95f5f1639813ecc45ad26a330dcd2b5378cd4a93b0787b432ddbdf6d413eede03b1c0d2b43c5e3214ca15f8a7561cdbb6d681ddc2a017f3784ebe46f9e0d8279c50fe3209ad53bc28b2739bd4b1fa9c2e9447ab044d9a11c15421c73e6499826869e82d44d3f3259972c4e51a08348711ce17309608ec55a9f4c8b8c24a16f80f7477c6d03ffd1312b44c0537e0937fcd968553d663de256bfb59ac4ac0ff65cdd56f0ccaae292112b4d4be06a9c95cd091ad379096f82672448e159649106138476c23a42a1714974754275ad3af2bc511063ea26caf08abb580576a2eee87e87899eae398575d695e79b21d73b21fe8502a931266a799aa1a1e1d3a21ecf113202497d84f181e2dbd8f4b0ebe489f14b1763483c86f138fa0d27fb326efde2879029240418d0e5d724f2e6ca5277d3141a71c78265b0097c9710e00ffff1df656bfecc9af9f9bb870e2b0876bf0381ce21e76546977dd2c796c0eb4af60ac367748aad3e4d1e9a49fb6098b4226246a266f2cbe76dd91ab74408aac1043f222f49b89e4054053e0d5b2f8f4be3657cf13fbe9c79790f310f73228e7b52e00634c2db1e014e33312ad9e1836ed64c943f2c78bb14313d4dc423a399990851bd34903ade97e14db044f81686fb2171356d5a0614fd40e1ae97b33647a96c262d382276c9014c280818f06965f1ace0a159845c6a12c93affdeb5c7a44c5e38c047a30bdff302d2d01d97f8c3871d50aa2e4bc17600be087a9eee8448bfd91a98f51a8e763d0deee2f8ccb5cd51e4f8f3c1c4aff554bf1cd466f4c2e330b4cd8bb24ec40fa8a1065d8c4e878dc335b3f93da3ef8c82fcfaec07c9842aa4192138421537a07083882932e486536e6e04a32798426504d0edadec90eed41e083a04d435a77da66a9d59266ff81c2e485ec0cc599dbb7347d8705aced5846d956c8779f9de80bbdb6cb00fc2b5b322b4358a54ae4c7570935ff0a5275c20050ff08515e64ed1e46e7725df91a5a20169b42f05353e5bdcb61c1c7deb34bdb1146c80ffcee16eedb270a8f7cf21759f78a1578cd6653650ad4563671c6e48d145c9eaeea905524fb5fee9b22cad44a2a1240461735ebbf56c607bae54c4cf856c9a39cec1175bff045e8e77728f4af2acbc41030550ddc7282c4b0f379d6fb7be6f0a177d4ff1b1ee1f54026cda8069bbd8c8df1200502818dc4722ebb2ee5af8c5835d92f2219cedc1da98ab6ebe2fdfa1d839e1d2dbc0e46a15cfc67361eb155ec287481e6fd9115cd96969d9e4293ae948c76e044cac53079b3f79394ed893411e0f42477a916f5b29e80984b28e952e0c943551c9964082509aff0d50e49f966bcbdfec6c8ff0402038e72672ea08a7e1bda7e0c9e2e1862a8121ae65b578c260047db4085e4e81613cc1f9e9fb33a1dc2d98ba13ab0dfe796c8f4c907000a012db692ab29793b8520ad05e1012f354329f81627db5efcb8ba79b85617aa4dc174eb0311c0cef22417f4096c6d7fc3ee702cac9009e68492eca555531462a855580d0b360c3318d0696de6a57a77a009705e3d9e3685267874f213ee589af76d2066a05a41bb3513ee4667b5474b5d8fd299b947c8e318d56f58e67a2c2db3872e736639a3bbd074fda2a4a938cd885598ff56fc9237d116d576b0c3bb080b2512a6319c534f319e0dbb3385340bd58f2133ad1ba2ebf651701c33bfc9dde4b025758ace1777f43ac952b49ec7c732cfb9524317fb06c41ee457f194af2752c9390c28e665af5be16c2829dcfb633d483ce9c309ecb6e6e93cc765394b1f3e50977db20e46a164edc4b02fd6512ad7eb35d319b83d0ce3afa8bb874869cf31b702e7d89bf9ec7aa4e415470b73d62d374ac0e23d5b9efe389cd98df28c4e2b328a6fb11db750c4e1148d129aac76a990904a786b324ca6f113e817b3d450d6457147aeef328e0c59067f5cdd8e4bc81062346edafc6d5991855dfe767d0b0d4b2498c229c1bfdda586a78c54e6d704ce2411cb24ba86fa2a7435f3d33696a86c377153d3baf61206278e8b19db52ceb2dd068561d41ec7f51c750698f443c1c0098d7d2072155a6a68eca70ac811dfe3de049162190d5aa9f17d0d30a6d33c681a8d65e8ee8e2090e118824c9baba7848691856d93d8af8cae037895041aa4e2146d1686dce1cdf6af8b683d85c2dd9437080d194692d5e21c2abe7848ed091455c4a27ea0d985a4606a19abe0e7ed2660e65f8f6cf1df6e6b1707cd8dddeaffde6c52c0d574d76f3ff88e681cdd1fe75d16e46ac6b7d620ec80c4c86a2950e7945961eaf2b0f62ba9c8cda87e13b31e0ef4862552e1899c8b32ecc27dbca94a62f9742a8118037ba5fbc7930cf654b2685ce1bcbd61d4601270bf61c70a6a7b4042f61624bf2cb9e6315ae6a1d4a23ef67a976870ee19eed494a0d3958431d9e419da6c252a66421b5915e9ee843ce9c5848b9633a0a753f3209d4b20aa7c86ab069222d9f56d4746fab1de9f95a8dc881dd956c28b9f61d95e5a569cca82e605776ea3cbc9f2981f8d7821c120ff47f935962c83d3bfc1a4a4aa697431809d9fc8d7d6901186e3b0d1d6d7b173e5b25194d9cf52a8adfa2af45b7fe9e980b1bf1b4c57ab0df6b8ef034e3e0c30855b3a8bb6fd6da006e47a37ab03edc15b5e0c5162361b89225be46d9e60fbe5f6537ae4f2a623a5b6935602e579c3fb7940ec7f222b7785cb57d616bab711603da68b2fb4e2cfe508d3a0d4ed2354985d31e7e741d53f3c6c3ee003a2ad82f9a366f052fe20b4cb43b31ca19713c05ae7548fe006d41f04bf53e25575e4c6c0a92a54857ba42770ff39ba8d8c1b50283622cb7657b0369b90f70469aab594bc261898ac4a0a180099ccfa603918eba3afda96d5cd2ec104adeaac9b79c2fab342564111eba7d3a9eee4341d1293c7e0453605d0267997ae5cd98097620ef630d78074678f133d023c09347ec4867b29a72a915cfc662aa26007de293e500212c92b496ca1c0fe88e1d0f3e9104c252b126b8372537391a816fc936f3df4b403f6902cf676c41822a0e79c1eda8d79b4c5d4e1b499baad04baea3f82c7f9162bc5b48699058f27f702c1b45f9021601b5ab3b278cf0e98bb1907fc0b076b66f486985ff8565a57413704dc4dd5ed8d3dea393aabb21c19f6926975babd72c129fe2d2c39b117754160a15da75f5cb292f00c6cfe178c65a114b9b5c0e2b750c8d13a75d5c28488532ed4addd6ccbc8b4ce288f51d977092dabd2db2f5bd3bbba5b36cf6ac794f5d586e412bc68619905228b41290a057d525e8ec918c99c1c2a0c91de48e2d46b5012d8ba26760134131bd8f0047707fbcd04eb2c32b06c883f2da0658db165d97a6861d41ff8c38d7366701b61095515403a763e361118146539d81cdf13fbf0c8bfa72c6dbe3320d2dee80164d54ffa296ac197d8416788793682c94fa2443206f7e11a27852098fbc9738613f8f89b9e114821665392b68791e4087a92059fc4d19c4834a32fcc793d6df4aa14c33235a214ad3af2a0791a0a8a59e5284b3a5d4a618f7a33f391318d6105c09d4e195df156b7ba1decbfa1c17a9e132c3fa08caf9ef5ca75151552a8a0b1d0d24c0302990c44c875c29de30cab87cafb0dafddb5fb36ebe0c835edf7645280cd5c20ce70dada8f580afed9230ef4f806e1b273a17efb0194d1a903d7b04e833da7d5645cffe5d262b10339996ac828359b13b871533d9a4a0a41279843c324fb224ff322441dcd7fbb086301729dd0e8c8ef662013c3264e211782bb34128a04255bfda951b610ffa5332adcf5ad2404cb54503c5b8d017b6218e529b32509cb3cce699cc3921610cd36e938f046986a6112ed6f9df94d0d62c724e11d6090feb538ffa312263980008733a0cc20ffaf71b49b6943dbeeff9558a5cb69fcca9652d6e10e9a4921e3aa1b6b1a10fa9bab4d54bbd9bd5c1eb217d09c02a44082c57a0cea65b1cec820cd5f4867f755c4a8cca15b09fe7dfc170b90048547f0db6a48ba9fe540e958cba28dfa49d05403f997a2c49ad53730a727bbf46d41828684964984ea15e815b663ab1c87f02f9e019e9d82cb406dfaeef6f5f2034b27517b4e7ea77c137b34f26ec7fd75461763414e20ee44984f5100e98335ace4e561432798c53ad25ed069e7c7e7ef5e01b0c24323501c107bacadf9e005c7a8d765039c804de6ff4952ac2c9bfa58307b49e74b541cc459c31c8cac0e63035652f01534199ebde81357968b06f23191f7b73ceb34f99cca1dd9c53b6e403fb50bb1a215b31f6b8b654864cb53a2ea386dd606f91fcba6caa807d5606e1371040e22e2e7cd9c47c910308550cdaf38c8308fb765618478f54e9d19495b357be02c2a37ce0f2a533862814c504e4274ee29d1690e6d06395e01fef6138e7889531df28cd90e64b44ee64a77c59aea86520c52405944db25fbe949ba480a4ceba991a1d46a1a9291c304ea3742bb8caa3c49a7e0d85d3b73e0088426d944630c7b1127ec13c1a8a8c4f29c2379189f0a7a4f138c6c2ed7829a51c7551136c6ffccc4717891f2ae537315b050a8a76c6ecd04028ec978260902446387597636cb4a68b824ef8421f83b801478c5b23ae011220e3f725ea56954533d87fc7c5106504e21026be9f92506eb8d2fafb124758b29e17957ecbb8daf62927c6c12b456fb6b00a2893e51996431ba9b08e03c3078aaaa6d918ceca0c24645103755a918d66a30bf82494c5c7e7c65dddd8714ad3dcdca0c99a93e4e88f31333ef6d6b230fd601dd43febf7be3d56d90a2ea4266c643927b721f3f17a0dea82505124ec9b5fa8ceb38324d40b0eeae843a68a5a5e78f7a3084c723bfee913ca33338060d412d875121098c16003af14a5a6ebf05b489c594bc45c2325a954d244502c825128299795541ad66bac8cf9af4a2f28652c9ed9499821f4e66d83aa27c4928a25ecfcdb9d49776ffbdceb4b76b790f0113a359845338e52c6c3c3f920a7245865f415173a918925f805d131d94e8fce190f1035bad76bfdf199a7e6a5fd4887afb649c0bcdcfdf2328f6345a7c0ea6334800e594bc296cff25a68c20d9c0fe087ed37d1ac82886050d82644b4a579bf51c972e3966ce2c8f7ff8294ba1d24521a2fb90a8b7837fb2ac8bf60e0f50c44fb1b39545929feed3436270482a89874f23a5c99ddf28e3ca6daa8fd1cb0b282b3b9e3e7b8b27692eb6f6d242dade2816b0d7e71f619a32d22f9a78930f0e8f069220203be4abc8083c60fb81ad1d39605304b69c27bbaf5203915731954cb39692a2ba3e6e97452d438aff80e651bea89e47b96bccbff6ccaf0fa5c347e75d49d77a1485899260348f949aa850bea11ae3ee6872f279d926c30c9205f939cbae06221eaaef62c169d543effd64b13f0f06d0b57ae220b935e9ad7c01ff0348c9fa6e4707bd4c893a1888c4500c3f89c0e31c905e2d0311a9d8b6b3a79d23b86c2d77c125e19357829bd8b1bca7e2c9a392fa42b98e27f2b5ce64bf68d6c0817fa3774037c57cfd3a32e6595a956b9bae2dc8c580ffccdc4d0ab0641a8a86391e9bb738cb2f9167aa240e3edbfb94cfbef50d600ec40a50fe13afa53db3c95abca3b27c7a1626a54a6ad7b4db4d1a7547451c020e17bd86713ede5db2e92b98bb2fccf58a29bc267efe4c5949cd63e895c31a0614dee48cedd26723ef0fb0f0c8c88fb7ba10b0c1a387e373466db63c46a32b18e8085e8540ec9318697a606bc7751430ac66c7f3411ddd56b53dd60db86efa24054d944f0cd963e1db7c6a42e69cbd97506d14686c009ae2d69ba575848ba283014a19b1c045b9a8bf20f03b68c8b0210ae6bb5e0e6682e0203b17b0fe2177e7c37c13067f104eaa91669cabb28b86815243afdf31d9133558f29121986c4f3a93366702eba2848065f2a8d72514b2f528c8a69e1caaa26f7027f6a1de61e20aa9608131705aa7e2539b00329759633009f6c965aabb9d6bd237cf51aad79cdac8b5ab707d2b16262e7b96d0e49a05b7c17f570a5132c3693ba67b4ae2eb6c126eae324a8164bfbe82a8278cc4c961ac1b06e16045dc56fed3e19cf04d4580884ab55a92842382346a366e27fa8e15c4be6545133e3071c7fadaa241a4d45115e424e2ec809caaac7e604bae76504df3c5828fc0332a1a242d1769bd3edafd5466f86f8f03db32cb11e806860c206b421ad7b3b1951d53adfb870e95f448bbcfb6b5ee7c3ec3c57bcdcb8afadbac255b0df0c817871b341fda46683690ef18e896ad5f53ddd8eb1e8a8782661d68fe407062091274c94b330664dbb5ba40aff17069fe4f4c569728a394f4ebdec7b13c57492b8d396026730f3e9ae498dd3a4eef1d170f20153a971352f20842526ea0ac3cc179896ddf8ecb499498357609286b14272260a50b987c944e11efc9d6e418c32d475db7630d5cab59b7318a01fde53b1af06e3052ec4b039513498bd8bd73e718b5370738e648bf25fc20dad5cf99e8e6c66a305cd5ae5518bd8c69875b48fa4cbcd5b2a507e65b9e48617873633870c5dd1af76636af708f7ab5072ae02283bd506e06682265caa9bc8f013114a252718812b1cbc0818727c0fad43e1a28273b9c8120ce38501ba27a0d5aa91a16c7bc0b67ac62dae0bf961c22048314f6930a70786c8bcf29c7c03a68210a4b29c79eac050c2c1ec7822acda28cbd9560296ca5acdd431ae666501971499d5f977a6ac682b172e8bd2fb645393648ef44cc715a6c7e697346db674ad80e01151e09c9e4f1bae15662468ed8fdab69f689235c3b699768d4bd3106ef1dcd1f6143145c019b51dec4989cd2a831aa51ccf456fac9491e2ac982522be40ed66854a262255814450ef830e09a559f1554fddc124de15fb3b3a80268945eb02d0309a3b8294c656b9fd5d01a8c595834ba82fb217c024daf6cab0528b6fd9ebbf507f72176bf31fa6e04bc4f7caca934bdd0ba69246da648028a08aae85e419a3037abb9a4908435b7f50b9c7d141a40451e32dfdb39c36328f8891078037e98af3f0e8ecc3467460ea06da02382ae2a1143b5ada6b5253f864adfe59fe1046b23fa2dd3a52479b953c51f3b04b53ce40b48f2279fa7f48000829afa54032dc8f88802879872668fd4959ed326dec1cbca5542b6a0906ed66b7d757c0314d511704f659da8e17a42c8247e1ee34d0da36968b444782060450c3f34418dce8fc4f3c3d290523651fd9a577508d76aead51ca4fb880259d96a7f5ed4bdc1d205031b2a056528789fbc284776ad69fc0b4371c6324537e2a860d6d7ea04ac2382fd733a4f5651d993551f206bd7b0fafcb05087b783ef1b5776e333623dc8aa720a9b53e011139bc786d81b43e2a2cf6e071b84d7769e379aa5753c01c3cefd552f5a4c67cb2c3103cce6bd5e95c2d5d8083b33a45aed3b5e51bf7dfdb9f78477c63444d90f72ba85f527de6a7e14ca2a98a3c4a07cc48f9d2f2a8f08da8b585b48ca80581fb2bb58920072a496a527822b4c01992ea9b3d93caa321b8344f2b7a17a9bcc13628bb2efedec55672e3ce75143ceed6ab0d6b5001dcf78a224e6c36b9b92142c742b6d46b51cf870817be2c255e177f4c20dc00a963ec8c92b7a5033bac36519b4dc115241312d059396405ed485bd77490d38474320328f63e0d75ee1ca7a691e7dec94dd410dc59fd4d7f66621dbfcd9ceb9c54b16e631fa3fa388c065af5fcb6d634bc7a1e11497acaab7c65d8018da82ec9002271e8317739ab481859ab201229dc87e6b8ca752f380a5dbff2b0cef92a99cc4223e93e2d56294df031c7d75f97cc3fd7251c4fe1f160151e5761e581e245db9cd92458dcc105291b30b13fd801451b21b1347746646fdd039d7ae5a3609bd58f9e379538f8ed98d0b911947a576a09b1ced18ae7c4ab859a4b5e663114d8ad2946f282cee321f85a5caa4aa4cba51607cdcd8d4d9ff07599dddcf0cbe741ccac18089cc0b7c8dbd404258d51f236700c09a1fef83f5ab7161c1b5835682a54bdbd791852c2db0a34c368ea3b39b1e4b5192501d5a3f29145b3509d75d0e06c0a235a40c3366b1411544591815f90bdd5a7fea31c839e7ba8f7fbd9c04182dff7b74bb107a224a530a6aa1e4128a94876a52d08398dbc47132cadcbf24aeb61c5bc4851d02a3bf24881a7095b8fb354f73417f57bc2039335632d62bb776e607a05ab946ff1205805be1d4d1b4e05e3195b09649e73630f3ae09dec162dcef1bd5bd8447d9b1f298c86a01de00775a8fb19d06a2696c641c82564b0b6a46d1b55db5530f7754bca45c5a35e716b6003313dd3e650e0d40bc0461caa88b1ce45bcb5d2ab14fab830da8c7284190405033fa3d814534418e6af61022c6dfe7261155d38bfc38a62a206d5689ac4de5ebec20a7433a00fb286b854149a30074cf14a4d576d7525bd563bd7ee7b40d98df5982b1e07edaf52c15057aee20d3b05aed705d7f11ea269647a4483857769d58c135a2eff14a011366dfaca1e69390c8bb966e7fc8f16ef878e1d215270135286b349c3f629f103b0c6dd929921db97e1621943946b4306eb0d4e8181c99d1d4eae2e8d13edb6ddfcf5841a8258b0e74a3a1c2ee59f907e2873b67fe08a6312e96ca7856448637d3c56ad818dcdd22c6572b0b9defe72343eb9fb683f88950c65fce0fdbf5f7a2328d41315e8d57434b21196c0ab45ca95a36be17b07978d9fac350e58fc123b7a3809e130ec93b7410dd073813b8f38f3c24b9a4d9688607727e3b0936446e51d7ed9198a324a65c027162da8cbb94ee969f4003b7c9c5109fd046756b69be5a29eb95c45fcf469144b6cec329738490e28fc8a7d1561dba8989cd09b91c3a3a76fd9a2d86083c0597fde5766f25452faf6f7479f3f7cb1edca5234d78c56c59dc1f66b052228fdeded0358db69578727647a2a4dd06dcc84e3c1102a05e1072c70b7c1933bd83c94ea236e8e15a71c34f1ecd2083977248a83eca0be1f79def8ce51090f215d7ab13de7430c91bfcbc4f290fed0e22d944513f0c7156d118fb9e6e6fde87734dbf823bc078e1d416caef148b0ae39e17f9e14afd132ca87886ed55fa95a4d53645b905761320cf2a6e6f103914f260c3a4d92c7c71a27a947443cc025409b7f02d790e6ac6fb7df17caf5cbdc9f58b96e5dcc00bb22e87d8feb234de47bdb3fad3fcc2105ebe6f24ee66196f106201cd2e6156a857d1a8f57dc2a8c1eac917fcf08c0905da3591412ef3df0d5648abb653c849214a323d025cc3dd650f5a922add75a93446fa5e707a3714a132e0bca371390faa9e9824a9da5cab9ae184ffd25d79af112418b6ca880dd3ab1be0d86fd28d2e338b8873eca7822fc0d74136bfcd5609380dd44464d13d887eb689445d05eb297e0b0e22f09c630d48517f7852edd4358417c01d0b5a6fa92d36f6906a28e07d1bed1cf183dc499b335e22e427a1252bf7ef830c5bcbb73f54654dcce05b06a2953729e01b188536e6a4f1dbbf23d805e50a7c8dbc643ee16064c04badc316a9729f376cda589c7fb3051f975fca85de69351859b3069046fd6a066875c825cc3c5be4f9ffeca6d5b7ec5b25e25e94326968623fd00fd0e593e6faed65ce3a8983fb5070c5e15821663206a850e0075ccea6aa4108568bda68f38fc1a1d43ee9c9a31b8dbd1e4eeaaa1446ea18bf31eb60d6660b83f18798132595260b4e7b696b97be3478aba21996dbdf9cf4263a4b35699f07f98fe527dc3f57cda762a6d491018159e39e455a56bc830119f7784f8349d39031688dc3e7927197076fe794c84a58ed72f240125aaa0bf7c9c5eef882d2aa5384ad5695ef9a20aa7d785f069d80b42e094553ab2015b8c9347ae40111315262e8d7509dbd64b9f6696873a0ea7416a67e441c83ab0395108826948109ac4c52f31cf89c4c5267c4ec368f089885a941acf3aa391f068c81a2d9a0d886e90152eba6a723763fdd4b7d45a2cf026657eb1631fdccd041c8f33cd056f89ced35870084eb7eae5019272c888144ff2f43b6a9b605b44b5f210685e1b27611b382b5cb52909e198d24c5227fd73450ff0cfc8a67364d174c7969109aeaf5bf137854f51acbf758e454f152ed91b1fd494c7d03d2e4d6194d4535fa57c49d442b06eab285ffa1b392361cf24670cf700f8144dd465c24732a4985014b892df19bc9f5e96927d6c4e06e6617f66d8b5b52cf98235d199c5d35710e5898f2e78ecedfddf86d1b1d4439c63a2bd4a69bdcb5f17dd9be5272a58572ac3130e3432a5206d97e6ca1990bdb7a65f3e5ce0b9bce1bb5e65d0d4b78c4fe33b871ae1bd22659f785add704163659b0146aacba468b759daa739f15118a77af56aa77beaf1776cfe9a6e2f0d6d8af204c51449605f179288f92740bea8dee3c5faf9bd3b57e0cfb53b7719f834c3c3207d8fce0bdf3901b56f953a3f8214eb0a30ba9cf0a379b9078400d95019791151ae65c7b2cb85a783ed5c2ee88c256590028136b42c434536671818e687e6d247ffb8e1a45105062eb5c4a323194ece138b389c1881d6d5480ba0d0881d08b4851d58b96cc1a3cfde745073e930d88751a612dfb359c868810f63d47a0d2ba4f355472d24b48b1fedf54970c18bdf43043489e1718bbcfe45050343a2006c60a40188bb3356c8869cfde1d6a9ae4b11f77f73128aad46efb427229ea2cc6c9fe6a113f92bf467d1d0e66adceb927a1eb75195b5100be18499214707ab18c1d4a30c4a39e812a4c94768876878512881861a96bd2eeb621fbe15c2ca526a768021c2bc686bd6fa0e84c7f7c1ed1dd7b51fc00463fe4461c2e0e5e0de1b85cc919f0902eddd2116a9678883e3711f6751e06f30b0520879047620706715023378f449c52df8ebad957ad146deb8b2a2eeddca106a6e9828681449fa3ef13728ecb5adb8779963cbcc8b4174303fc7eee574c3c5fff463f0ac918933c4913fab207670f86b2ece22f0e6003775cc6e8c22fcf84bbd7f18f00dd9d042564bc860a2611713984701eaa0a486121ebf8b52982d5a7984e15aeb5171a13895f942d110ba9d6f25f2d04b2a4662af52520b541c9a22a93c60c0ad03f32040dc1c4309c1fa6cb31a1287e960eede92bb9b22c998c53a82c07d4e775141976fb6e914b7f4da40297f97df7c28590641667e7b416987cc3a82e336eaff5f345d3826b8901fd1bd3f5f2454f72ce2d48d623798ef23be74e98a96a73202846e61a3d1810bc538a86bcbb689c100d69cc8d8dddfcefd2ab62063ea0a4451be31b77cb86e6c8234c9b0a9a2a71fb169d93c578163b508d42367be5d80ca55d1e42468f46c5c6aea2f682dd286ab8b34c0d116f782282107f9008e1734d567867615a20fd5c8d282951a759f86ab02a95c11f976a0aa9440951841c1a2edd3c9455a30a370fc2ccc424169fe189c9966f4947c334f3bbb16c2602b65eaef96449ad5a873e44e48f567935a28238d2b0cbc626c30ec6a9b63172eda542a4f6d7ac55589aca95be5101a4ae64ea81896ec2fb01993766f9d1f35af526538c214c5d65c8b7710a2902834a7146edefb6d4153a6b0ccec06d6fe64c0baafcc23294aaf39e18adde4a41d5c8e67d07230942e0e33d6cd1e49d4b643262d940271b268db3c62e5971f04865bc4c3615ca9c761c5b513d11e060748354065e7718975fe734062802971361bfb28d73b08c6946eb1bfe1e2174b24f3341a9f7b7105c67ce2f2882a36c01b3b381d04b9b40f22ff5f497ab7b7b0cddabc601928cc7789b92c2106f3448f89649a11f431e1bd95a92b69eb7bff55509807daf097d4530102a57478cba5608eaab4d06230f900e1f5420efbab8138c24a1d0a254e36561aa77880543c24f2f5e6ad890cd3b2490bf0ad291534ac59e041b73cfec144596c2d9281f01eeb2840532f36c95c1d61759a20c1475a6a51ec26adbab02224bcd8f9e1ee5eb7a5f6f84704f2455818985412a44f53fe696b6c80377597076679816150604651d1df16621b8199fd4ee41b87f29122de44bdb89a254b0a31d9b4e59387426ec4481faf03b0261da29275c01b0eb0251762e16ffbcdcc8944cd38f3e1f4e547b66ff1763203992e8860c1494e66c444996da1452a583d666f3690a21ceed5e021eb104fa1cb62f420cbf87c5dc42fb4700e42080d7781b783fe62190c4ad68d9a3e3e9449e30608e4a3abf0f6222a6d194f6a81bb8d9b4f821ad9cafab6104f32e86d96f0105ac899a05b94b946f42e30cc16bf249bc81383864b1685b2dfd406a97b63b48bf8f78fb10ee1bc5f26126e146891351a6c680f27514bbd2a343e7f293e089129e8f296ea2264ccc2b2a7de15e366a2c6769376c72df51645ad7584da61e882f228034fd8405fdf3fcfe6c9ace1b3f8e5fc664f46eb88c1032d130f167807d54e2d9850c43a9c240f7f14ae987a9502beadd0c39b5195d00a61c8365ad41222dc26285edb93a905037dff0d68003989e619b01664c789d036c8e3947867afb1f2ac65b35f6ea12f0e6f25b2a6fb64f88925d758c89362a01dae8bf557726397686473fd210681e39510e423ee27028dfe3ce7b54e2e792840f9866629b59cf54fcedf177a64db737b727ed0d49a029df3d880f77e196841bb31dfede10708c5411697397685133a746d8a9ac7a61e1226a28f9c323975e8b89b66fb87f875e6d92bbb1f74e2deb20d7d193bbea10f88669fd199620637b02637c04221bb2c3cc299bd1577739ba84ff1020e531e6e6aca6e6ae106be6bdb6d3a7365a8ff324283893950191a4488843de58ff4e7dfb0c4c177633a9adf84a1a95b63f1b41cc1c0f551a7d5f764a57307805ad722ee02a81e4433611e5cb3c62f6e93d8c9eb49e354cf424e6660a998a4f24bc8933448ccfccbe658d863333af5b1596c300bda5e3f856c8f8b0f2dcd38e942eb28554e9410b462282a2042fed406b07143877cf7cbb90045ce2493c70296fb31eb26cec0ccf0826f416ce28b4b1150adeeb2807b8b0c0eeee59566f0dad5b7f3bece58da2cbf70d5e67400209600fe888e5158f6d0251a2810dc02663f9599d968084163e35a83f56eb5f46a2d691885799dab8b1055e31c741104466929a60562ce4f5b1b6174c496f70535a85683f582f262b0c0a12afd5b17c78d9f14ea6cc2cb2f656ec63c665c4ade11acfdf4b14ea597fc9f19db89424149aeb3de32bbd1af0c1089467e4eca6ab1f8182f925e4939e7622dd3f74413121c6676bdfba26a6b77d51a9981305204ad874f770291cf6dd8a9ea58d258e7e95bb89b925346ab811bd0489ab449e4ddc818110d8c2c7d0875634adace13d65385459848b60de0bd238758b2be59d2ae360486d74cdfa24fe82e77844dc8dbafb59c05b4dab4603c69f3242582abe3b9b544839aa7b990c44bc89bb74b9f7290ace1455c0869c1418bd7eb7331aca21764fdf7ef2b201577dfa5ada09a7f05e9ac147713a47db11dd2dc147e7625d4d94387ee0a3889bc084e02c1edd82bf990e6d7c407867d0223566839ad781218d98c07570fd3f5b50cd024a47f19fae46ff7f316f9f609edebc5ef297375f5c04a58e0e4c352df2571180114525ef6913405bc5acb6e90a273c1d0be6219c227448e9f102a216b8986e86def983247aa9fc2310f8454043a3dfba55a30181237078a6345aac29cdb35634761ecca3c094e47a67344ab7346b5f6e0de992a064871495be5dd23c56d081e433804c160f800d0d71f92e143efc1c14b113c663a447358f7502efa803dec61bf7bc59aeceede227b4b9964780a240a360a40bc1148a7c3a2dc88bb5073895b61e08a8d5b87c694c3686d59bd345047061d9a0a443575682a10d5d4a171188ae32ea60a84973a40384e87d2224078a916e195a68e701ce63accd5748ce952c46ad35aa21487d2d28691b33b47cbf942b1cc5e1dbd17cf5092eb7cff998a45637543c343d114aa8342a1b447d5e03455d121645012554bb9ac252f9735b2661299349367c2b9e4c60be3a4e0c6f99281b831c3a1222028afc7d46c3aa93d0477cfe47561a7607a2bf05a304bd833390c6de1305632b06164bb455ad212bbd786ca90cb4e8f25f2ca89cc8222b7ee455b380c5cd22e6cfaf7ca30949ab2de0e3c94d794c3744cb4f476e0256ac474efbd36ccac1be62246bc848df888d6122e2b8dc35c9dc7c046f20a97b594a9703ba69bb35069566a106acadb8187cae56cf17818ca47c7c622b9b0e7d1048eecb512f07bf8bc2a44cd97056cfade4d45cd176d7f5e09225153e6d3211b9f0fdd007da1051e2b19f0c50e37e7bdf76a1c39301cf7fffe0d7168ef5bd34a946c30f45028efc63f5738b7e61d6e1c47edfdc842deb477f2c8c89a0fb3f4bdbdda109bbea805514b9feea02ecfd4419d6ccde4e100a122d46cf17a4c5067085eceec18d96a4de341459695456edc74aca54e8f0e3776b8911b51d7dafb093d1b4f0a0f099e11367d0f8a5cd69297048f14637b58e43072e7e1100e9fff3e87cf7f252187aa23ff4fc8d96cfa1eca2472e38544163d143752120eecb3f7b08ab6ad558b6fabadd66a1c39b08d71bebd16e2a09bc342bab30c047277d171d8f72deed85a28a26057d1ea6c524ae9b41d71c77eec63e8763103876c8ac72d76505c4aebf8bee445ce86bb41edfbd90615d2b058c89e8de7838aac1859f44c30a8608b1dfc90b32f1d433d532d757acc11fd254c4e783450d474501ecab1a7a4742978e6fa148c960e834b77a1d93381a12604d5428d87e643e930da0fee42ffca1f0dc0d8d99ea41639d8a287d24cb3258c8cb7a8993493c6e3be77a2a4ab6bd0d8de41cdd076541d71dbb33d5361d3177d366172e92e5acc61b7fd4c7b3ca8c88291ef8b9e69d3fb13d3e099fe06705fed9dae90454f8565b2b0a809124ab235e5a13edd84e8a13c5496a172d969a283ca3751883575d54cdbb80e777c7ab42953ca2308370320b2605cefbdb73bd2a2d9a6759d1d6d928c5fb4636765ab18ed9884552dc574ab0e0c56b7ca1debab3542483c9257edca982e3809bb0b5d36756dead22a360836e5eeeed796a5ffbdeabd6a6a2cc3b2ec17293334c65d7db15b05a08af162640ca01bab18b1cd584b98acc24b980b9b6eb4a48dc3541b04dbd4025819581a8b035b33d6eec55a1d938e49acc2abebb91b6215150dc124beb0ab6212ab2ac6c140a8888e241e8255be5a4901ec66157ea8c2e0821107a0a17118cb844dd92798a0e9ca2ec8135eeaaaf05aea9888a248a7eab660c28b286820670ba5a2074436ca9e54f480b539ef6c929c7d3a9b2477473a3068c94322d959a99ba21b31179814752e2fb6b465d789616d6c31c88e7498aa71982ef465a610ca8098bc6bad158fb57224d9e94853f6bd5aad6c642fe411ac9e7785c8f5bb557eb0e46b28862e1e3424986e983938aefec0fd0a04b9670ed7853178e66ab122d9367415c9f6f0bf967af8fed34313f57bf0dee4318fc9dff0dea4c68def3f3ae45a44a38e4458dc808a4a6b2704d5f1a99662ea883e0874aa220ea98c886f44169c3d0366e12478855935a7acf1aa0559c4a5178a795f220876adb8cc4f1fe75052cd1a539989711678c4515052d598092aea56b68bdb111983d888d8b18b93ae04dba235e96a771f846736f7bfdbeea8d938fcc5eb7a11afec73dd45a37673df7bd29d9c803a3bce174fc134e099ca5d7f693fc39d05eeb50b2c68c1840196c174185b83b2811dbb7bc50451b79a1a742af8d4f1619631c79801dc138b33a070a1f0684ea5abe1b7697c08e15508cfc4cc96e9897845850fa0a873ac73c435dede30741d395f3cc82ce1231dd9611a6ad8d924f96eb123bbd5c4a6aed5b1bab103d2e18c1d104ac2a14117ca5ac2a7b2c4ca10f1c962d6aea80cddca5a6bf185e29e325d4116bb554949d907f1338652e183f18b2b745898242c0b73e530b6c65da816268bd39951b18e030000f04cf700a8b5d62e65cb3a3262cbea6ec7cff6162d4eb6577bc458d261b90ae0baae7a81c8d8df1ace9002328b1dd83cc488f884676cf0c87a568fceea4805798467b624d94e200452a1227ae1d55f21bf3cf27553b09a2f748427504578e6da465d173a17532fc65747765c58dcb5ba23b3657498aabb32a60b6b775f74665c2e2e7806c3a76efb1f6a3ca6ae9ea35e335f7c35830d3fe4ba9a2ddd65438c77ab96bbfb751da0d65a6b0dadedb8c0d9d4616c90696bb0e97376ebb22f9c7bc1def3e2cb3ee51a9c6200eafc909d8c4dfffa904321f02f5047004d923d5bb4b9fbcb5ef7baaedb5d182749a6b8bbaed06eb5d65a6d92bced1a8258feef453c4609d47855c7f17eedbefb940e8a7dc36f4f4c63771f433905745d38a9e8810ff60db93d310e2e43a38ebafb3174dd0df7abb621c667c053c8d89eb1d57a752f5dee422bc56cb9170c67c70e2a86766e7627d5b1016573c4fe9d3aa74db33b35780482712849cbb306a6c1b5cd9a1c4c87613486625f03078f54d4c140e8c62f76e4326c4706d851c33855632078c4dc1c6580b06b98a42e460b7325c4433b8edd09c7d46d65539d165616089b7eddaed922eabc19c68e8b8eaca3c3d85447d6921d3b2ebc64ab488dd5063c051e3b2e3ad2a61c0693f864abf0127e0199dab4ebec17f2f6b7ebba8ea9eb3afb57885bf8c80b3479da625ff8c82cc55c2a1f262e038fb1e96fa1b8636f7888ea8c2ce2152633eff3cf557d7fff1c7e610d7c723f651baf9264f7d5ae13a8bfe9d0f573ef404962376efa572d75739c2106b7e86ac5eac66eb5e955a757d7bd974c3743adb542a05b754766091f5975ab954c8d4004f04cb675ab95d57c79c1bef3a34e98c6df7a217b3ebf884fac5ad23133d83093147145cd49e6765fbb6ebb7fb50d3154b437dd23ffbe7b6e710416043a77b5a3667b0d35edd9b62716467c71cd7436095e5dbbfe0d7998ab6db50d55cf604616f1eada138b2478ecbb278945b9bb80c128238bf8844fb5b4e788fe1534416af67c022a06af367803464149d59678855778e5d57a66c782a9271182a951458cd71ab786c3dcd04103436adc70985af51c52358765ee19f12d6c1a335de6ead66c7462b6808af0114d8c0e524c171010c62952298a6b56a3860e35549c37bbd041033a0c71971355d580974eba381952020ff84917431cc604934339828ab617e7eafa0e6041a4982510e80939885f4153a90cc587ceb47e0e87bf96699ae68f82b237403962a31ce119f14a14100a34448fe99284ab745695c5b8cb07467bd2c5892aa6963ad085973e6075966559e619f1d10918353c235ea9ed67aa9fc96174f04acfc86702a18630e2a5932df8885547d461320dea315db650534ba0188092d8f4452e002930398826abd5b1232e10816fd1514e29982f50d816e644459d888c654d267795116e4e0230afd001cf8857aa302d75a24aa19cee1641a917649af2b17b0bbbcd7d2d51504d313af03ba302926dab664f5855d3ea1650946ab69eb428494c619d2039494249dea6efa4932e4e5426209ad9f282ec6f1de5082aa28f8202adec8bf5354805cab9ae212415d13ba4bd96678b13c74a31c915ec2b4c16458389d3aa3fbd96d76ab5b22c03a1ac94742718072ab3f2dc8a8a6725d4e1322b187b4e25e4f11f3e4ba863e56f38b787e519c3f3a1c713860f41032fc8ace810c602cd293a01d11f5b304366caac3ccbb384c2d08dd0b33c8bd6c1f2a167f9ff7f161696677916938da5eb58aeef7b1690e563c282338b92d275dd779ad65191d65151d77d3ea3a4ee3f5fb33f8f43116cf8339ef974efc1339df67c6dbabbd7bc7cca4e1d257db4e8bbd32c210c8fc3ebb52e5af3f73d4b48f17d968e1772190f148a9ed649287ac8087d2b211595503865543c9d2d145209854260680b5d2195502804aaa88454b4add96751a91f0a855e84c16ad64449da5b5d012ab3f2945309ff59429595d065ea123bdbecac44d6c1a69f7b50d274919879b0e9e7541dd1bfc93ee056ba150aa2248c85b17090b57bef65f90ffd4a486554c2d08a4ae8213daa3ad21e151df2cf34754459b447a5438edaf944534416bd932c28e9f3f413a2c4ea72d3afda8b5648d61ec330ec04878ae8a5bdd667a2221e5474a2a2cf6af13ba2eaca041f6609971f6e19f10db1bf20365cd692d72a6b2b5b8bf25a2dafb5591f5444abb63654e4c3a26c28c92d8b63d591b636d647fe367deb83929c92f2a64cccd1dc3367f898a3b9fdb56f73ac5aca41e42158d908568f4ddf6a563ecd166c8b5b71f9e523a8ad2f5a949829adb86c596b6b28a492b5b597160db0fd5ba11014002afa0f773d07808ed338dd7532a896fefd35c6aa236bdf9f255e1685039551c1ee8583ecd7df300ba90a07806ee21a3a2f3a6b977c7e9650470f5108c215645842d137f85e8b92eaa6a10f691da15ff91d3202085d26534225149e321995ab45675d38c8e2ad1f70d6ce2d1da11bff2bff7ae5431fb6e64b8d5a82c14b4249e0bf08ca1ed243a23c24ca43a2c8d71ef23d248dcf0d957f95df21c385427b0a2d4d1d853ed4f6a4439fd07f18ba11fe7fa82d8d0e7d3ea43d651db94ce8a371a032a10f690f49030e2b229fbc4f28674e554778c6c42414c2f09ff06a95565db466cf27f47c28a4325a554bd66a95d52a8bb2a8fba1109311f27db0b045df25aff1cc47cfd952a24514d0ac845386253c811443f89001c3b9bf50041e8a9f1030e4504401cde6de1386c0bfe0b184df4af87d34b3a5e633e2a3c137834dff1b62caf09928e9ab818be87f3638f8228b9e87d7ab845366a57e271439cd83b376fdab093c08312d323d6913cf604dc8a2d7da273816f5f9d8f43fd3158296f2a98e5a1f0ffa9d28c97ecd119be6236286e34238f924ca974a58f35509a94c3ed592d7caf2a9554b99c86bdd4d8742af1262325ecb6b8542501dbd01e8c87f625765a1502fe2469baecdaeae343fdf00b4043a0c8cfb6793a6bc5490fd2d0f2ad24edcc801e170b8d131518deb9f8fce25be0f86a09c7bcc92679a20289c98d9129ee9e6baad34b712b1a9918fe79f4f5633cdc4fdd89463f1e0e3611712f9beb5d662bfd8f5343c93e71e109e67f2787826fc0943fe9fdf21c3cddcdd00fffb4febb061878c8737c0ff681d31da4618197b718ede8b9374ef472ec19c93575486b2e4e97ba9939b4def75851f9840360e7ffb562441b3a71548902e7b5a8144b93d54ad9de35a1fafaeebca817dc28fc342bcc23954843d768d0b00216094853983b44bff6cb1578b9e14b5c3b0ebca816d4f2bf1f9188adfab5fdabd404ab02f866118f63d9cfc374bafc76cf190700f08240ff0c64ebe07f0e42f6fb49fc3c97fef38e41a879207ff46c9838fe91b27ffed886263155f3840a8e80aafcb3e16e61004b3c5c304b2ef9f3061ca34715f9cacd0f3a03c1bec9a32dff684737fb0f67e64216b9863180ac33a94da7befa5b9bcee9fef3a48e9f7e95cfa88fea56ef293186ef293d354fb389cdb76a16f7b3d2dbf95c6e62465ced72d15e2790b9b81b16ccf8e0ca6a84343459fa665ce719724b9f44b4994ecc86092a8908c965488d562765dabc1700568bd1ffeee314bdef496d8d44b29016ed5e428b7c1b090fdb9171d55efe4b8fbf6adb596e3b8afa07daba67d7ece7695a3d6524c43269fcbf00de0e65eabdc6721f71dccd35dbfd776cd7da1a88eae21f6329d78fca7afcfe17b1b396ce54145f42b14f6e6cff7e1d3c8742ea9285b9a8d784989b6f9e2402f29e9eaec3a5f37a9d2e3466ef44cd9be5f37ecd850d1e7bf1735d3a59babd9a6594549ae692ffefec25c47f53f21878d1e7adec88ddc12ec67f6ca301d8ac07dec6bb88fe9cc86da67a196596d272ef10ae768a6d2ed35519140909f0f8d4ff68d14c7d431754c95867a86556c7418d7ab8fb65650e2d2546660f6612e4d5a6c6a2261a4fa556b13d0fed27995737279d969fd5af032715a70383f6cfad7e6fbb6e52e545469caec4977b1f7de0bbe0812d5a02d877130f496b3eac87587c65dae53be2ffae7b2567d5db6e599c68ec9470f1b0f0977a19fba3cd46ca9917df697f64e54a42d71d2b41abf170cb3123a4e6b33ad87099ba199c0cc6674a44aa038d762949c4f474aa2a51226899a3145389444c95aaa540c8c9239ee028452126e5191199384cd98a2acc76c416133b42334247ca4193145daa96a298d079b3ea64d5acd6c41714a80af69277a028d414ddc886dfa9e0f4aaa0ffa5cb990450f65935594743551ffde7bafbff7baae9b876c215f2f6632935444ad38e2c7bedebe83ef7908155d6fc3aca22214a775e1dc6038656ea66d9b86d2be2d6aa8eda14c18be01dcd773f7eda5d9cdb2afa1bec5ee357369d5a643ae5f6e7be7a14c9ae973b65a046dfb6a6f773a35445c55c8628726d750d2bc430c6184113d7a2cb184134edcd09b2d7650a187a2a1a24e4d47bf777c5c218b1d94cb80d5071956692a13f506325acd7c9958662f1be6c8df5595a63271031f5c15ccb0cff7c9becfe3128b818de0b27234b3dfe7d6d07d516f97b11a975494d3e181cbce16b17f0cbd90c86207a5c4f77932f909290d2523776c3e7b260a7a351fea7bf077b0d6bfebe868e2c6e7f33abeff681d9f3f791d256fb2af75eb6eb5a8e30b33bf30eda78c0ef03f1de27ecae8f83ec4d5ec40693b6e622e1df60edb3f94691cbc043bb349b6656d8f7f08eab63a040fc8f724cce3904ddf24c4c936f3658989e30409854a8a925be5201c1654a266eaa0c025e688be1338509052a8ea156510158785156c11386883856c75ada94478a197f26e3e25be3fddd51d9b8e0f32ea0fb49a6818253631af1d4bcb306889999c54541d62b6549a9a5d7bcc18d424b0d8f45e8b247b1ac869a828ab3414ab3416bbae4a335f68ed6cb1d2604566c9ebe1a1681946f62dd2b29c2f78dfbd6998d54cdfef90c100f8dfdff89480ff691d5a33e9a9bf1a8d884dbf2221dfaf3f710d1a8dd54207081dd14e8e5712510df1c84e161e4edeb487f2ab95005f2382921c556feac873ed50316170cb5d68270b4ab262d3ef8c94247aa60d64bed84e6756bf32cfe425819b625a31494ac09c904a73e512538ce9856929307580e8984c1d203aa6cc8459b3a5c86ca1467c44c931a60bfde954a02d9c8530b29ddb62597d8acbf942b1d542163dd4385f2ce71119b26330c5f64c5978403695c2c3f1020dc05ec36e9a4a2824800288aa181de0a5e92ad5254fc8f922c3a66f8364d22d13b25fd6aeec13668b55cd965b837dd9256016c3306bed4d1e5700d0d55a6bad71187b645a28f8a8b457d078067bed61dd5cd8fd256be9dad890e4b5b1d65a8b5dbf6357bf9fe199abed0d15fdd0228b9607dfbe3d98a41fcc1b840cba45b8301a2eb95114fba0a43b5597bce425a70bca35d5ab727b75ecaa41298dd640860e2a176243079a6273536c1c0604eed202c1c9612e4d7b4c97e93160d1242e2cc50729363705e52eb5e435293ef092e300c5aa275a460a4ae530f7a6a0ae6a660104b51485398549d22e8ec6d2a0b0298d693bed24685798a5142fac3049da2b6196a698242ba6363a4ca6755079516bbda8656142810a2a1aab5274a6097142761db241025acd3a77ce0ac94ee99c734e7a3b3ef3bd19156ddf736e3d2f7adf79f1fa8ef55c37607fb1f6efb985163e96506e1a7b6eb184d4d682c72ec09e5b28a14564771bf4f7573b8a2dda730b9288bd0599c5e6f6f57e03620ffabdd80ddbbebac3357c7e6eecaf1b4ac2eed5a1eee7e67ec333dd7393f3ba0bc3ec6398fd1c1487973b187659aca371781e53a0f3d77e0eba3d747b6fadd7c9d9763c6b27e0798fe3bece31ae5b74ededd081827b893d6cdf0e648b39a817e2c88f82ed21f8dcc5debbef69d1a3d8620e1a82ba45dfa0f6fe7a3007cd41b789a745baf39b68916ecfcdc6fee4b5b8b3f7e2f5a017fd419ece915fbc3c7e73feebed7b5c8b11b8ef14b8efefd8fb0f87f1c7bc132db2bdfe138abe3fdfe11a40ef1a87bff71ce87a2ba23ce88a28d875e91c75aaeee3c0f4f51aa640b7efd5e208b2d5e63c98dd399cdbe3f1bce7da3902dcf6a827fc61b5a7a8c8b57d30ecfc4958f226217e9530e5636a0cfd84737bf00cf6abc51cf545cf83180e8fce51454fe7a8dbf3d84f7cc385e990f7e0dbf768d1f7130e83bd15a76a83fa448b7ce91c55e7a83bbffdcea7846f1f87938af097841715612d823a4715a7ea7a1c597bbe620a74fbbab438821d1b7b4fa7d3e1b0ed85d36e4f3481dff06edf1d1c016e63579c4436c937f7b396eeeb4049fef7be3fe130d96fb606848e3e6d9cfb394b24e7a73413fb899f7bbfa1a2ee453c83bf85669392ecfbe5fa3ea6a7bb605828fa8fedee29ff21aa4db52c52426daca31d5487e879f727dcc5b1ce45c17eabe15091964514b238c9edb1315fa67b1388154c1b7b9ff7ca2f66b9dbee144523826b8b94c642218b9486e5557ee5298a92dc0b2f722a102339dbb7a88d22a5d9933ce20a9b3e2582920ad0c1a1a409a40a596843b42c2a70c6888387211c3cef7a776bed7bc24ee72d9ef1e4f015d871338431a21046119060fa2193a2776c0f316fc7c642ff91a3eeacfd0977b11f533d217e1b76df09c5bab1c6ba893bcde91d7b7b8a774c3107dd98d6f9634ccf4def75fdb14fe0ac36ce179c83242727e5665394941ea4d8d4dc956b85695568e3aaa555e1257ac6f593c3a4d8b46a89d29ce1255a049762e3305ee32eab3aa24578a98a916283851a395ba4100367534d4b828fe86b4236fd6bd3466c8b9a8e7d310dd74f2aca72645665031b6b85b866d6ea2de9688bbb2eec72d9c5211c42aff237587ea5a32d1c6c5de980ad6801b4da292b2a194bd542740814cd8bf4e219eb846cb5918a68d6341c2eb27d511b67beaf82612a18c37cac236d74fada1524255d5586be86335f3051cb116b1222558b5553c2be1cc514e0a1eeeb79c076f658585915496d51519549f9187a43ed2645d7550caeab011d780001092ecc49e0257f818f4e97c35cda97982ea85d0330bc073c363522f49a6a359c5a4ad1c81a214d4d7594425b76db48d1705a37456b631d35215f9d924a61828ab27b536ceea7a4a428e97a9a65634a8a8a9848b1b98fddcf6e8a4d4aead64ae44716536c5298a0243105b5698a0d25a588759592b335b2c71635953662984df1418a8d3602a1e37c216dfa764816b5df686a89e5e96fa65a0a6d359bbea8596153cd8badf4a7af8db5845b9b6661d37c854d7f6a11a3c2a634da4869b491d2d495cad7d5beda98832476b6e71646e0c21635cc9ff0940e2070984bd7204cb40b212de3345b684bc8f8a11b3f8bf810a408232819161dbadac6cacacab38472781653890c4b05829461d1221a2048990c9459014af910a5186dd50b7b4a534b95c6874dbfaeb4b18636aae826446dd4c62cbba19a12ce3a1269a48c206a011437032082e4c4ea45438af1a2e1801a5602ee924316343005d070808f6a708e69c0992daa7bc56ca1cf69f5aa62b47197400ab1e15edddd3bbdaf17b7a4225751d2a5ddc69970225e80373eb231459d8fa124861250c77987b1cc838e58fe8ea3a251043ee3aa2a644cd759ce5cd13736e74b0d735f2f62b58bab5eb58bd52d4f9bde23f9d2ab2cfab869580bbda43210a1221bdac7d04bc361962f2b64d1470e939aa65d658dd49d826117a796480ed88e33abd8aee7c8093026607bede41a97be46402268effb726743108a2b04716ab045b2fdab03a198a50dccf25ef7aea80c3bcc96329798749b6b0836aeb22166bd24728bcc92365faecbba476e91d952d2f4a5828fe87fe1a93bc610365555217b49848a6c4e1631e945544754b7b4f7562cfbf2bd17cf5c9cf9e217a7e4e27c2e0ee892f709178b1b05524542314be00d13c490ff1cbb7062cf9148189be21adc8aed40f6c434d0ebe008461164963472bed8c74fd841668ba6f1163eca9c09d9634f72f65effd52ab3211625e0dcaa3da7efeae6f89e37e7ae8e6053ae3419bcc83bdcec3654c8e22d6d282986ed15bb484ce2ab9b259fa50d497a96e50c02711f433bbc69afa2320ca1a21862d8fef5fd96e58d61cf7caf0ccfd492cdbaae7a2f4cea68e246e7f3ebd0dea363fb8e0e613f65f253d6bdf76f79eff558c68a64d06561933442c8ae5abcad4dbf9c65921fec4b973745491725d5bf2555e194e856d22f14d511e843dd755dd795d2b92f61e3a38d2d926d91ec397869ba041cc6834c174f829025ec0bb4a1366516f19c13931393139317e7e25c1c8cacaa215d64f1e2e0cc171c64b65c314b780b2f0285209b92b3c54a21cf0da64026666541fe7d655912b6750cfe166fe9aa5bdef29698aa96647ce48f45b90514b6b354528c4030f0d2182c545642a190af8442211515151515156ee52b663b154d544f595e6109710fd22668673686665f09a90c5e59595959f9950fa180fed882192b61e83d9ee7aacf15968ab1aa6785e5c5bc27c8662a3f57f6842144b2264dd3342d1452191c0a854218ab965e04025d2e639508bd4a78ca6442cfa2a275a8fc4a1325d451401ee60d3fe02ceea35954f5ceb02887f190ee824bef0c2f61239a45794887e1f20be8b7b9c9b1e417702c8e0cce061ae459ab56bdae821f43336d874ab06b9530949f05db57c69fc7209048546fa8a83c16de08fd8ad6b1f2a1e75842add2254b18baf1cff2afb58a4587aa2eebb354bd7299d415b28e56c2f06b784fa753f68bd6ecd5d0f390a487bcbfe2d1aafa1cab8ae03209bdd00a4bb5998a08a492f14cc9db9086b64ac977429187ebbde43d5c8665cc65b5667b3a9dae3dd5802533d7c75ee072e617e4d31c65cdf3c22c859e629bbe9764bef87df113420501a54939226ec7715ca73d099ec0fd4b3b185474bd786f3aafffbab82e7424acee4507c3c1e8f0a7742720141fc79aa2b31a15ac6eaec2ea56b22809d3998a625fb5786dd1559b0ba74cdd72664b1566cb9d0ec89fad0c42de50c28dc5993c5986b1bfa11227db8b8c782ffecd6ebff37c97982b28e35139fb79d9e31d6735be5bfc8d124e97a9a16755b8f7f2dceca6964c4c3630b6ebcd888b3624db17191190ef9390cae8cc1483725b35727276fa5eac014516b7dbdabf8141bbbfbf1971d2e51eff96e330f9e96f5ec06c2a77a1df79312bf94f79793e251d2dde92aa1c6623e29def6ebae740956a7b5a04ed70cb71970d0cba1971d146c461b60d09d6e2f6c57cd9bc982d1b914d7fbbc9260f7afb629633d5b545ce8412e63aaa56c8760862be2c276e474a93dabd711c8f6d93502414e03e747f8a9e0f5d1d82fb9dc6215ecfddb086b971e76f28fe8912ba50dc6163dd7d57d623ab31e8f6722bbdfb108d18686c6504b80fdd50fffed5383c5f29c0fd755739e196b3ad36249c898aea6f25156d606cad2d89fbcab32ccbf2c5b60085b98e4c08e0d775b5742726275a076e820c10988c896e628b2b1eda215cd856a4d4621e633bb2118161a093eb07af8263810dc28d23f1fc7d507812eaab9d8527e079af1f43a989922e3db3ce7335a4a6d093d417bdd5ba426c7742b79d11f8c6ef37ccdfc9970e93ccbdc3ae9ef0cacacb77081e8043df35cc816d4fa77d9be01aea7b4945db598e8496362474546496b6227344b772b6502ff5c6a2a2fc441635d3c4b24dc3aa56abee4e4efe04457be92b13bdc3919c7df7e25481666c983c48f3e00144964941fd020f8d92c0a00e00954e1ef4146735b504d2d94d8a9e75d4f1d4e4afa9322636d458e02ef4b5500b62b6841a117444a3094145da1174a4fdc86e3426341fd7c53476571b1894e494747fc67d4545da16b7722baf6bcfc17efd66650e20709c4307defad85a7365727283f69dde8290dd643759145911e6cbbda9233abae7509197eec5a582c97f7b84a70d424609b7158b33713e703fb80b8f1b72274e8890cba1a4eb20d0956926ed40a808878a7c741c21dceb3fb6b2da3c877370d4c95b1f19b445476de5566eab3aaa2f6ee50dda7bcdca5abaf76665ab8c00c518b6c3fd98aaaf87dc4b136dc38b8a3a031460a3712f108a8989c98b30a8dce5ca54e4bd37f39af3de2871f226e1299339790e14ba0c4a18ba61f2a007691d286fa26d307913ad23e48fa2359a1a6da316c9d9df037426db17362f6cfa5b1937b5c49dea88fbc1451c4d367240dc2064df226702cdd8085d6ff220ad9dea28a59c2f0ad8f4b72accd2c996335ffc41349b75daa569db1737249bbeb885b14ff4566e5e6ea547eba1a5b0b0b5adc481ca9868cd5444deb623b3aca56bbe3888f32197916d636c2fb7725be504b1adea864416b7722bf175351dbaef39b09de9d02a74b5e76ce5c6dacaad4479b1c5acc89132ca2dae5aaf03f80d255dfab63220aebe49b228ee19dabef7deeb82850d11dbb7b8953e6e31abd93e7f6c485c5cf004664eab96b2ecb6b2f2de7b6fcacbadcca9fc632bb7cf91871a6adb34ed8692321d806ba9c800344263093d41c9e535d66d30b20ad0268a236c764b8400335ba9f624fc7a0d25f90d15791293e442a688929ca4221a85bbf8116ee3372a1732491e8592d36cf97c490c4a82981f0db6acf68f2ca9c14796d0940c315be84783200b2ca129bf0fc9d76a42fb52fee4f3264f5b775afb1f122afa5af7fed76a228b1fcb59df97b3a232c020c3b03ffaf3263a8403ca7f3ee4fa06ca7f4237406ff2a03779244e3ca1892a7a7005c992a117e42d14bf39464a900487a844174192e6cca22590f5b5742f8661573b13998325764b073f2ebc043ee1a39493ee92029ff0d2b78592ebc02c80ac92c8102aa21f39a7d6f9762d3eae5609b97385dc7333675998ed92706ecd8e5fcd94071a584908b2c016158160dcc7cfcde9612f8225d696f038d5521d4116d802935052cdd9f44b88a05f7204ca8689cb81509297592cb2e836572b61f21acca122130d92ef78062412450a14c1d4cea1a4dfb6d485313166637f351df2f71bf0c7fb87d973eed666375a08661afc31451641d6cd275f1f647d6800afb0f360c7d362cefafbbe1aa98ea63faec8e247c6d493f013e2b0dc427208255d95ff762436fd0f8c7b35e62c1c56191bd357fb454db3e5db028bfae064388bac59f61c0696e0116eacc8a29f36abd2204c2c4cd730b70882648066ccd29c20cb1dcc02c88549aaf72f2d969c2ec8c29ee9615d1747ebc78b920b328513c458c6c5057951642d8125175e028d7ce56c09325b1ce6eaafc874f9547b0bd4e7058975f42359796e114c65fb17cf5c2ab2bfa5222fa34563d71769ececb33f09bf8eb2370939aabddf7addebba3476c3fabe27be21ebec121a4a4a51519641daf5a5b3c71e648148c016902cee60cd9718760964b1e6cb75a22c1fc016cbe44f7e15b371f88b733c094dc2cb08396ff123377dae6239eccec016c8d22092542d8163549005a6ae2b33b95e625e3a8c9324e930f75ef2aaae0b035f045319a601d39eb2b1a9a58ff57d2c166bdf90ab738cd997c6beead0fd2c87dd602b74358804644d619390c58fb5ed89b1bf61b659d763a16317c3300c732452647cc35d69dbf10df65d67a0b3270641900439b003484e121c424dd966b140ec042441236009920ee3a5bbf80d68c44b7e8412248fe0a58f0b1f7d641d9536527c5cdc7c642d8140b8c029dc0674e286e008a666cbdd63163f560dceb247a825102ce36bf960da25418020d64a827d3e252c943ff91e409ff22298fadc4879d0f770f228df43ca835e0453183da19d100e287ff23750fee45ddf007dca5760caf05001ca9fbc0a409ff23b363773e824d4117a95078528e1c9c7a2a2266ea07c8ad6e165c4000b2ca09141d1a03aa29a1241434d1609f96b7d48a8c81e218b602a01623461027d3e07137cc315815bff1d06b822510c3468609183200cb0356adcc7f6d533c48c5b025444673ed6577e486ed898794f320b2d6cd1592617c82a39cd9709b22ec80259200b64812c90658d90e9768d6fc8bb3e98aaa5af8ccc8754109b3e98fa581f6b5f118bc5b22661beaa2d19417a0116662b56a7654276b29295ac97acb5de7babfd715fb4a96d5354446db5aa2a46075491766b0e20ba350e73c35d2cb7dd9a036c2edc838dd58e0e2372db45175eb26758552dd9160685ada5cb035111ec5d62b6dccc166aa7b8364bc8fee2b529b930ebd53ee1a3540098782200769c2db766c433b72645649fb02951ea0991037c34d62c672a368a794b920997a6402cb5d68a6bf05aaf2b7c22756dc69b54c5ec55dd213ca8c1aed6ad196dadd1305b6bad358a204e73e454648b2cdad6b66d9d26029b20b3649fb0e92d728fdc80091bdc93d442052a6d555a655b9d4a5fd43de2d67401bb6e50d1820ea3d709d585c2aeae1456756deabd31a9e0e2f2300cc332b6b55a2664ecabdf20b908f9aaee90af6fb5c83fc8d8576b671536f67e5dd885596bad7da26af689f1864d0919b2f348b3ccb65ab6657f90b3bf7ece6bc359cc5acb4d0ed459cc5a6b5b1a5412d26db5c862ceaea652d94cd5b5d11e84676e083cbbda2e9831bf3053306dab655b34bb30bba96a69527f1aa770a8740dd437492d1591080000000083140000200c080644c231b14c0e64d17614000d749652765ca04aa42088619442062143100100022222022333b40db3c70c77ff15c16d8f6755edc0f579556dc566a0391b14e1f9a33f818d2eae706ce06ebd407fa4066787621427bf64443e65f6e2a55fab6c8ddbddee90bfafb9e7827f1705f54341a2582f449ebc64ec73ce9190cba6c8f4948fc3fd1dda8e4d1930a8da1ac9e843408a6ae98b1c44878a492316ed520c3c6aacbea43c8233f09607ca87c2358633f16e924b0f3ca22fa6e0a240557f6c196000e7a1dbb08e4eee5dc533378936a346ef7e9de78f07dc166772f0561a7e4663b75156c9aa20e170c61d1ffe576690a59e020de297a1c7197f9401d8d488bcce9433086a18039b63208a1bc4702c22d0f9a0b859a80a02ee2822ec1ce6e66c54db457a19a53f3674267f54363dc5630550800be8d97a6dcba94d57b588decc1f17fc2bd087ef9dd6f439b6f744b11139aa2e68adf562ce2659470a9583ac26a62de516c7109318702ae22297d601152ca1c6658e5b429f97f83fecdb009c77c1c23a14a96d1e63622c1aa900d07e777835c8226532b8c2c427621408201d88fef4a0ded7254ec088bf9bf05a3db91de7e9ed9b56450da794833c60abee373023bb363bdd19d77bdfadccb8226b94ca4cffd9edef2ac62e53cab3cd7a44a5850de9d74a3feae7709987a1607966fe48bb2bf2790358bd059824aaae7c441ecad3f44e3ce78e7d8ebd68e46e680ea7ee7d4722f1393ae4f6f92d983b0e80dd4804923d3e40f77b1538f29fb98b207a2d2d4663bb11d678e4e2924dafed284255219a51f2197c32b4e0f113560414b6edf3d55c9585ea93c997deca9628a545a8cbc939665da34697f6f8d44ed7a13b2b28851c94ad3648826cc122de90acc3df4f1df4d90045a5be24e3484a5055a94541bc34e0709aa740cf48125c0887d6753798102878286d040071a53a643d93036543683608c639fb89cc61e518fce407ac8448b3a16487419a4a03d02ea6a9206b2be88f73ca6f84485dc59a44a6d273e74ae78668034bb5faa53152bbbbeaa92636ae572213fac690eb6d4d20430f0a3210329d0190764451eec6bbfec5bd29d31162746f252651c12b9557a971d429ec3fe7cfa2c6c26dacb1a60538e09ac10670ecab1e7579e2f88f1ff4d46b336d17f1111d80897587a88076f948e0d60ded562c15b644022a8cd6b2e5ca85953001a3cfe6bebbc5a50202116aa450c3aa4df013d33d1c0a11e09772bb0970f98d88897cccb476829010a6384da62ef72d0c7f37c6262374b8173e8ea93bac3cce4ef3833d4e9557251e77cb9830b6e350cec00675ed9810490106efcf173a808e3384375d84dc5836a0bb4f330399b2445fe959ab626bf5e61f1290538e2749bb490a80499477a38401b728d62c6fd4978e94464d0d853edaa3f380cc12d070618642477cd926ddb6781a155c83e4755944cffea1896f98705d4c393ca92e5b37f7b6f0418985078087365bf6815747d65289df3ca032bab7594cccea4b07f0ad0c6e1bcbc12f396f63688a25e242978c749904a6cf654523a20ff16400b6b03b2514209748b3f8b4b4fcd9e1559145ae1e6e4ac617ad3490c7e104e17fdd69c0cf6b0e625a78042230137e323dcc50c54913653ba7e6c0cb45868982001705c0d20ade28f5a6fd5ae9c9279931ac6ab40e2aeb947d5687120f2bb3d12e9c6f7cb486f5277111060ba4a73b71c0bab49cfd6003ef1f9c12bd7c61ad8f3db7d0403eedf037d181801f4153e0ffcc88d50e92ba3a320de2e757e7af776496c393cea099ef46ed02ca23f5d4910fa3883af42ac6dd6d98e51aea83bf4a90849beaaa65c4aa1bd5ec16fcf0ca9e2cbe3f79f64cade5e41e3b0feb7c6360c2daba77a72adb5a1ec184116c49a4aa183d470d83ebfa2e0ba27510e9f90590f3e3b689aa09f8339d0ca60d26c4a1f2489b0812eb077e825efd8c7a30886c2a301f50148e2ef79e9025295ab781b08a556c04f734f704dd6e23fa3faa14597e1e65a73d8358ac90589ae816dc32d8c06ef5e4e84e8a6a01b7ad83cc2da15fb88d71fe77c0273b90d87799091a1a39494b1ae1c99163884d87542c0edcd757cc2a98c0fa0091e8d4ccfe0ead1fdac6ad027b75db5dbabdf5bbf2a5d7abfabe265ddb6302d17074445a663f48c2e7de76a11292705a6d54803f51fbdf0b00361adc2eaf6ed9cf70c5e95ef4271480d8f38baf76c2cab62dfa918931c7fd3ec8c41d67a9728097183a9d6e8060befbe42805ae4c85ea147337671d22908d5eb2e48137c0d8f4194e5355116363065b2e688866dd42101f80410267baaf98114898739d436e168731fd8258bfe836a057240bdded33ce336897f14946147a2dbddfdf93f7f5ed2d06d44e33fab0154a7af53c2f84f5e25b8ef542b57eddc9f7a70f8a02152501efc99c927dd91aeb8f86d83ee9177db16dd3b30c2808a17aea497772d532dcf0dec9119bb5fcca3ea37739c7400644489f0dfea50cac416d854ec52e88161bfbbb75896025a728cb985c81f33828db0166f1e7fc4dc72d3e14b27cfb826ec46c32814dd76fa8e0627f4bb5acb5beaa14498e85f339568b6504397c1745cf46979c129d6ee1a42d5fde4d8c807365f8f90097ffd254ae167e2dc655f9f46127d97be4d3f43aa86e25182b45d600f1c3d159833ddd5cc1089725945b4e4f58aaaf5e8dbf1e14fb87043b76a74b6471c9730b65c80fd1f0dbb84b7aac9d6dad20fb998539c111345c5a07193165405df60144673ea21920689cd6e9b714d998404880bf743df3dd802b04db18ec9f6245f518b696402030cae8338ad325268224a5b25f54605c31130757ae8599224dc913290f891cb51cb855c04e09f52c2f8eea0e4740a1f35d77e55fd1f318edaeb05795ee03ee653d178716b8dbafac2965c2dea433b1eaca1eaf6eb1a04156ad9c3516ce5b17101c1e218b22616ef0cdafd7359fb0c2e07ea2c40013ac27fd2a1fbb96b1b041b708af2683af634965657adfe3d44af3b4a2879bf05f36f298c850c1aebc6d62729e78aa6bcb3a4ace1419a5f2fd861e420f5575ecff26b530c6661d9b814634160e60529e5c2a01ce37ccf3acc214185415c4a9a3e13281d02733a19cd0d67deebf8161fb0c77073744e1510a44ff12812eeb4310e945a07a8d096369a5b696a9d64534256a7923552b4f606a067da8629ce6d54e0e395b14aab8f192f4b429bbaf5ecd052e58f5e9241bd416844b9a1fa70213bd44fbc594348788061cc95349f3b20b4728429e9f145cd2393cf2574215bde9cab94e925f1ad8ece707b6879bf8b9559581d8e7f4a11c6f1907ce194eb43afcc870389cf44310d3139d5ae92e0fe17aa2f46222df3e956ce5200433fc5a2cd3831c0be5010a33aab79b47386da3dadf61e33721d0275597a4393b756a8a1aa762e12e2c1453c61ae79a71b8221160def5dedfe335bbbaf91df1b590e3441476adeefc14c46827669b89430331bf959b8db45968cf6203d6dfa31b98839e8fe06dd0e148d174c2a56df0229b96271c22863c36d058639c83da24f135a9d18a2b194c2cdae03e008e086b96f0e0ec936055503a2c35a6ef45a469ededd6d10e08fe2f78316b1cf3ca84a708bc6c469440befdd576d1e2e32f6d7b57e4fb46b7ccecb73c121c49c9e35db9cd6d9eacd68d10a66e3b98a35693d349ff68c01f06f435e17bd8df0c8290264b59f53ed06a06d0f24b00dc92f68a2af38ae033e5501c4d5310a850b7600138b2e83fbc6c739f08ef2a68dda783a5c52e9d65ab93e62314c3b881fbd82ec5d83aa1b90a2125995f4a49cf936d0491859dc9e9c2c9d5d69087b628d755504bc109b86eacbc229725a9adc810079072dda16a91ba3729b46be70eb4653e975d930a1b8a3873b164cf58343c167079f43921f2263baf3223d95ffcf9ca73fe2cf2dafe7a272d89cd66701236a3af3bec951229671504b0b59f2d13e658403f2121c49f30c756e4513822164e85d47ea168d3edc1c3455c08fd9fd2fca95726c7da3d5a583179dca9dfee93884a930a141983e22bdd513241587928379427c48a1296b86dced43f222eb1cd9d9af37802a44f021101a6d42779fd285d87f53828bd49f5cc968d58ebd6f068c94016f42a5012fee2eeb2738fe2e1d97efda28240392d35da14358bc0582da5c94d96c2d71d297222b1f89e802dd7e0d3295714409098db7ff8bcaddb94545067fb29e36f644eb9526efbeb65b18846b0dd83a8e11d549a548ee7383369a8080bf8e6b8ca9572cca8907fb833b7ba720cba6498d9055623816f7fee0096a5f8ea47e71d66659377f0db838f84c1ed5042536b9a845c9cb3950c52a268c48a1edca5d133159ef5e57a1909a64b77f1ebb87df6df3aff758ebbe0d0a9e214565475db3c0f7fbb10ccfa167fe1d8f90b6e7a030fc184de1a17e66065c0faf25aa4368adcefc222c6ff3eaae2456aa3bbabddfa1af08e3ef6d68f01a1ce43fab982413cf0b8cd673a5db78a899eb0db929882ccc5dde15f34a0b1f209134930fdee356753152af3db78837fa4d5b124c053be5a9a5a7229cc81a994e6353e8c70f4f18efe7f75447805b5d9b630aa6df71898c41e53708b53b257214d351814b095f1c61f4cbebd28d03209722bc4d398ae5daa18dbaa7610a38d534a9ee7bf5b637ddbe85795de48b080743b2472b202ff88931c9a2d5760f2535a2089eb4e2451c85f07478c4a9d119f5f0cf177e4fd86e1b49a4eb1801a0cfcfadcfc4a9494a2ed59475e27756ecf6ee356bb0b93db0a97d0035ef31f5b82567c9610552e7bfe4b2c02b7e8ae3535851409c29d32bf14cf950f9f63b89865440ae3d064b2f805c9ba9e13694f8692fec827a428c0a9f571278f24e112b8248a3ff99b82db8445c715799e20e04f04770dcff0df9b776be10c5b4dc7da72f1d44286034a177600bd73901572e48faebc02058595901a8070a6fa3ea2976eafd172e2c226067bd64fdb53b9d4b4b8279cec7087712b3af1d4826b746b3fc001793a188d97a5ae2b3bdf8d00d24e08078bb60bfcee4b49db1a07133c8df698d5978f48659165976a00ea741d03df1fbc9865580b8089edd143028f2562ab5e99aac01a20071e5446bb7a49228166cdcffe58624e81188b565fbb6227fffbe4e53505b2ff00e3567a861a7291df4a3baf1715ad09d5390c28c7d333b6d6dc42f40a2fe2d5099c2e5da29d701116ad28819441f633085a90ffe233bc359aeca2daa0ede538aaa558bb6fdbfba50bb88b7aadf8e01bb9ae3d4b307df9eaf1e2c9721113b92ed1bc4604abb0f4db2222910c0864fc0f7b741b29e439e224c408c553e062294a84916db8bbe770d2cb9c8ec20032461b6c17f5f0d52fd20b0afb59bc2c663ba559f5be8287f9de91be8f2cba6b06338f41a8ca05f74b4802e3064e904480801748e018ccc95a7dd9867a379f97343520fd66728d3d40146602847e5b43d7f7131039d7865357f0a58d9f69e594dd3353bb85a86d35413b532ea5f77ffe5a1daf570d6dea77f16a767341eaf24c39c50893a300d9e88f8a8245a7c395c87d4c4cd493d4a42ac92e5667743e70e934a237f2853f4df74b4cb6ba60df38d07e077e42c64b838b1345a3b1d78537d6e884343b4ecc9813c98efb6ac6c2199fde544846ce800a652adb22305abac174280d5de09178c37b6772f76f035c17e7e537cee12903a29a57f65dabd1c016cb0bd855ea7fef1f43cb50af77c0adb2ea565ac2d2fd7da465922c833aad75b627158672241b80cc291c8bfc4905970c3224b60b12e3472c60a51fd8fe100da31fd35b0010bd478556bff098108b40e2605df55cae88f48fca7be54ab07f5a899209e960fcbd92ed81fa7ae0821bca700ffa280c35c70255660b2e6755cc6c12ecae9d66ed731fe5bf50e946632d5b1100edffb5a11c08556dab3a2330421ae6a125dbd457d0ce4b5baef05bce4c470f84cda06da5820e30e9556c54ecf697a01a217085567244cc8888112db200c6618baa3b869aebc91a01db0a42af392328ac4ef58e9a8e818531daaea156a6f797971201b893da29a6b4973ef7d20f14f52e27b22e957fa788212e4d1800332b828fb88e0c461f825503090fe9668298258dcbb5644815910c47bc1d4e04053667d1f1e59c8e21de33ced88267f0d1b78134fa2fc3cc3a3d1610c62e702565d67019cc95749aaab36da5c7d8d289b4f51602e2585549ddf1db8ef448275e972b50d8178990592bf1d4198e40a7a015580e115728fbc40124454749d334fd6a6662b285d26b32e5b8886414659280f7c230f008c999d97620aff3c21919273bd23b9512ae551e6f6a549e0be5e4130344656bd25fff2030d5016b1ac423a320b9c6d66c8c0a96d8f715ce15d9482521b40f8164cc323eb6068f280674e33eeb8afe7fe449b58133e64776495182f98e840f90d07a7320224835b31608d5f0ca6ca0f38695706ec35d930fb2b8146c8c6c1b31f6e8f3d00d443e4ba4453a5b086adfafa17339e8b50d8ec2d04a618ce7796ab4c5ac11af025b746b47d49ff165f2b19b4a1a5ff06e464d03d615df144a4a7de0c869a02b0210e4b850436ca0a2064d87f1ab32d19919aebd65ee88f1cba25001fb6c9f5420bbc90a4b66710d2b894abf2e8e1e0492850ec1509f3acf1fa59e94edae650f1304f7f5e5fe24ba91a1d2388957faed04ef5d4284e9b5e9c94bcb643e541cf2a04ee76a61aca4d586119a5c6966212649e657a2fc9b4ccdedc80b33e004569673428db38933f51f37acf78ca33130ca50507cc5f392a875c73f49c81594aacd4a0eee6972f140c8c9f8c2ac516fe255ff565ce89259561fc2816cec6b179f5a677ff81a6bbbb1db9de6df63cfec75148a84c872188217ddd0630f04968ce9c194df679e5592606195e633fce24231e5246d27d98d73c089784e46ecc910083c0e5caf5b9c60a9d4acd897222ec53c54f8ad8f335619c1e96818bccc92db14b54c63cbeb43305b0baa133525b12eabc041eb7b8baa7e397c0ba2e62c470a3fdcc199974211f5fda714fc1b877bc56934807365482f8bded44ecf5135bd6c8e6b2c736a71b821c740d5c9261c367d424d10506c77a2a1b9051dd5587011aee428cc8d27ce86627db0818b0882c762cb67c61494a26ef7133899cb5d7bd5240e7f072ce21bb805e1223615f4a7935be8725b6c387e17fb8ab2e7a605bb9e1ebba7150daf601905d3ca5fe9f2d2fa0daff810129c8b5dd8fd4094d024ac31344e809382b38daca5a05aca1736a552036e58983fe570964557cc509b110700ab5684a2dbd8ac0a6368e3a7f82542fd6a2220772becba616ba7b03b2b481cc2f18f79109527da148247918301dcd929fdcf30b92439162add6d6b88f93c21897b20890d02b0737b938eecdafe22e97c65d966c8f33fb9a92bd341c3737e692c70afe5dafdf3eda2881de8f653ccef001f57b8fab933853d34fbfd63a2dd2c269f2d1494bc01d1bb9e4b2f25d5319eb2e7e868659181c47787488b6411e9067cd07db6d45750dfc2416dcc9f0ae5ffae85a575fb2197329a211f3cec7472d89a89c495f2a707a5d80e7beb3cd5e3934b9a689adfb307c52cf92048b2517b102bd990d09ddb440419984b3efc0fe3cf828132dc7099be1a2eaf60c416c98977f7f7a4948168f9084ff0aa1a64763d86dbf2fcf1c47de91b3f0b46ad0dd5233e3e52a04857ab86d4f4283809f89f47eb14e8259a0810bbab5b6d41e96667443e20afa11c7f7cedcb6dda7a97f36bd326a2e5f29bebd89f28ce9d2d9c928a95b953b81a665c9c90768441ae70d390a42ee61ce50910409fe6a2adeac96d9cae111ce2e871e7a3f5c514aa3490123369b8a7b3b573408e623a133538ad8b0a4c701a186b0655fc234e434306d226c9c3af0e10b6e8af579b8da3ae357c5ceff0ea0bf1181081cada8fd6a3186e33118e6daf6052583692f460afd49a82310b4e04ce67a6b0503c4d7dbac02e855c7e78b7aa9838924a84f5b4db48b50d3d3dd4eef893426b6440e6b65bfba30a38e236909373ea6ed76651e58390b83569a8883daf7386d34946d18d8610bedd5c8fa491f614546c97544f5d38cad1e9bf47381d56d1ded32c788ba0b17a41a654891ebfae880a1c9b1935023579d8fb97fbc894ed91a80753829782f02e131a4c46611b8ae34ea2f5274a40a9d153a7484fe7e4401a7b5dd0c2f55b920e6caa27cd66dfba7d2e7b7c8dbc5122c3610b90e58428d0e070d5f7c450d1fe805b9594b0c3da8ef38679e7f6c9ee6dad0fd50568f0a90befb180e559602092899a1c66272d9587a4ae491a2a57e290f77ab7f6186f8cf476d049a588efe3b5148b98b7c75f32a23fdb539649ae71ca55ed61859b9594332ce57f2569fb2266060901357e631576d342acafe2b88867600cb11f39d04c11d957886e71ba86ccc6a6d535c386b1d562a7a9629c46beaa322d6ad570acd8568616f09b29e14aaed8119b71333b4cf078947a592f69048414001b617c14cd7ca63ddfa0feaef76cd538b004330f25f9f9e0976f7e1be07b25b82e73ab0d4159a6e2da015e312da26e22dda81f48e421300a10ba5d6038d118f714facbcd5b2a80cf0566fc2ec377f10c432c39b1e913c7cc5d1973f12190db0abca41402d24245843980ded4a11fbdeca625a99e43f3a60ee87a2312c3d6aa167bba3675bdba90a116af79b4c7c1a3c7ec2f34e9340bc064abc6b68422503dd4a661876718e14a9c118463e58129c70401d148138172ce8ca4e6cc77308b2348041d7356e0f78861dcbcff101a88a5c741e1f5c1846e27d802cc2280eca4b8698836e24e0fbd324b61d094ffafef7184807c6d04fee52f1027730df1dfe53baf5f5dbbbc96ddb1fa4da63fd57c8c8c9fcfbf78f482557fe118a54ad1b07759b420d0feaccd9d3e8cd4c309ce4b81f0a24a9aed2c5b1ecc53a00c957251e0457dfeb5c9cfc71a2e1d486c093249ec99a10b09e5443bfe0d70520f66ca5fb721cf442c9bd0d88017379745fe678b4f56d752ae0a8acaab7e09f36197b69727a90e3e165614b6e101d08c4391f172f3c077fdd86a50f8763ba6e4b333d676af5af3ef9e8fc22868954abb3ebe15353e3f188972a7956da3e08cd75d65c7677d8847fb739481156e31d16364558a459c282ac04ff3ee3c823d5598a1f7dbc88e7408725d829bd1e0f2f6163d9ce579446fe81b0731d6e318660ebc4d23d151f27af214cdd6bb8e13aac7643dd0d2e8a04e293e8b37dbe5d42a1a219510540f0ffb72bb597ea2d166866a1d01dfb6158dea8ca4d050d64c0cbea51fb40f99365f1c4a9096ab3bf075ba1e9a39d48ba4065b0cd336da2c10cea0e7849790de4d9347ca5c034c62a0fd77bb27c2e7262a5cc612122e10fe194e1674816ddb390a6f3c2f692b850f31dc5357a703bd8f7d707ffd68441ff7c275f019528bdcbd691ec01b3ad60d8a9d46e8c6f79e1f94054a2d09548b628bbb4cec503ff55a2fb84bf3bbc706245a203a1cce26fb8362cab05fd1946158becbeba3fe5f5bcb98b793d7b398e90585cb7491e2967f301b7c4cd74b509de8072ceb85a62a82a8a2b6a787464721d84637799ae404e5148370413e168a268ffe202dedf763e61cfdc1fba1d0592192f127c80ec9b243ca7c31e182abaddbff60272b309f4ba81c724282b2e136946643f453ac17cdc8ae2902a2552510d55ee12672c9d9cea754f1e9615814236bc0402a530114c6c93034f4a8f96b02c4f1881853be1c47cac9d926e07833457175df8096ec4b7b6a3f95f801412518dd3e928f493603916d15afd00083165c9e0f4f119fa564394f1e0027997f82b0b59a7f31fc4474839bab82e98c1a12deaf1c5b5a88c5e53302bf0fc12a7d214a6c886a6039aa29660b9b9b9e9bb42c1a8c38ee41e423396f0734ac720169321d003f189921da6bf72283f9f8b74c24a7c6e3a97c1940984fb30c16d06b9dea5124c74da858fd04a70bbd7342c3d0476af61b94171121700c263129d24a6d453be2d69327f7b8c1e150bd238dac63a4c77b56c75350bf4beb1e4a5a09c53f6d682a64d54347588f1e0c8d70185ddbd333fe487f87f016b14ac749832227fd428ec981f5223f728ea2d5037aa8806c87e2ad62cfd5917d33dca352fadbe7df7a7f50fec613a9656d2443135773e59565145afa396f143418843cbd79d75f03da0cd43fa8112eea0ee8290ecbcbd520166dc132f5dc2bd8dc3fc180daa8cfdd397e8155604bc82216bddb7e79197237532f2634914cf74bff61541ce1f71d930064864107584d05d1e285f50149964af462f102068bf93f6b6212b2a84197e9ccf7d8e83e1710755a6857fa0490723cb04da87a2421f0f41624217ef98c9df807de165311cda1b03980a68275734633ea88dcd99a3316dfc62ece25029ee8829cf5a3fbe82cd8137d49af13c1d74f7e706b465f3ea3e240eccf1a7d95d93c00d87be524b321ed0314aebe50172cd904debf8cb714af18bc93397b7eb7c98db3d755fa6ee8d7f75dcc17a329fee9768b144e38baa5b3540138453686172cd9e71ba263dfc76217ea7a59e1b371d9c57c0a6283b4e21c1bc2e7b9567fcaa4cf61c48ae89087861b38ca7f66e1fe73c8e22c6e0137bd3948bed541b532b4f724b992af915656b85259d9067e9e684ccb2cb18d93f42ca1f79c62f35cf54b89f6100d4a84abb2808a5d878a2cdb3e5e7b7a2eada21553ceb86ea377f0710e08452619b9905c2b4703027a811d90f8191fd69ff22a10ed5d606ea38d8eb5d662e65a29d74024acbf40c956859ab8dce77a16c8fdce17aa68ca03de5a4da03ccd50f76ea632e65af3a5f9bf2fd23fa712dd49eda98e8ed34c849fa331fc52828d2995a3a0eed6e09ba476b011adc86dd7ddd058cdcaa23dcc53e68f6859c793c72f516e0f9c5088febf794c31c1fb1aca7726682837a6a7c3d0e47bcb82c4bc34f5fc3d5268088b0d77d9993f8ce1a2412e9c2bf60643377175580154a3ced2d24535d3881b7f18965a8a3984d249de2ef91930cc6e485c722b903f45ce043e1488f3bd367fed261a7fcba74de4c9f4d1489270b7ed02ef3419e14c4b7590658681afce3a07811e84af6b68825b4efaecaeafa31dcca8d624051a1e232204a38407b0c0cee3c73373e31ba4b6ba77a3152f0b7275cf51811cebc81e2723a4a4e003c65209c5c95bac45177793859525ac6cb7fb86e360c2361cb00ee1b8f8cfe74b1fa94f7b168920ddacc582cd2c80ff3e5932d440cb8750d2e5b6d0f38fe07eb4959ed6cb62ff7ef6a03c50f6440446b17207c60d87fee8b57a4e5c3cc4e915934f641f65b1ef5f01e69855d308d828175baa1d016f1b27b1389f0d420c1869a49b254188e69c981691fada0f9dd5a922a3611ced89996490ee95ca430ae77d10faae549cf66b8008b32d46d8b91d85e5697229e89a0f324ff124f6c1ca0a0ccd81fb861db4224a16adcb128d02630ca5d841b47821ddbe3113347c7e06b6a33a6ff7dc66c6a31c00f72f30090afa722f3cf36881c86f525a56b2913912e8ffe57ec13c9f70f7fafd5bebca37a4472b0cc7d753a6560170058e12a8d92534fc15c1295052af2ecd79ffa62658144c627df953b03b4ef7fb86d6a2a5a55cdd37c70c939252bccd93570052e11f7fdc104b62a8599a392d43079d0c7298ed1e6b5a2c4eb3a906a805da1b1196390fbdc19b96f2bbdca54952d9d14e615f2665ec40e68a5c3be287076a3f5ddaeb86e1ad1e1db90bb44d843b59df47878a2e83921628a285df7f26c975c48a4ccbe7125d00c3a4e96fe9bb94f2bc6bb3314c566265bc47f42045dc41b50e93e3d2091a7a1bf8509922bce22f47644697ab19cde21708da4e4e76bbb51a52a46e2406cae7247a797ea62dcd1e8e88f1cfe43b546465220082299277b449e71155808735297c84e769dc8cbbf62a8259d0264c4b44ad9486750fc8976b5270d97e2a784041eaad2fb5bf37c800269f42e0ce91027031dfdb1a6fb0d64aee397794f032ed899dc53f0b13f65b757b422f8313a9820f219caa007d602998f73d9cd63aa6217ee60c0c4c1126b03cd335538562c245977d6ceb7eda2a206ea39177d54000425c888011f00ec222a3a3ac2548acabef796e89bc338fa41b20c52f7547bebba265caa134222b8a4f7d169f52125a7649f3c6f5b8f0ba00d588bbe8194f0262fa0c4a4b4a396d8fc6b3d52bc592ba46150d8e30ea92d9d12b16a9aea41d3232b75277a3213dead10cd625fce9c214555da6373c5b6c141c1e33e7968fe1308d88a507cb1dd7f955f632d38e18fff68345ff63694bb2abb02b6458b134032f845a90b6516df21ca5cd0b0014033394021e3642dcfc3ef34aae1e7630d15d79614c216d6dc58e1dab667d1f08f65a250b3eac64ef3eac67d5daa1b5bd5b68ad76b7a6bb5f90f242837bce520c91ef12a8ce7f20e09b6202d583443e48eb52a58d4fab617acba303a01f0826e2bcc1fea91aacd7c67bb93efe759ca783cff2878ecf4497aab2534c87406dd4467bb5ce623c6aa2cd3e88116262a8c05d09ed07cc6780694c1de57c8d410b5f9b41685831a6509a3c0b581a90216cc45df43cbedbfdb11af3f6bfcf8ae111c382c388cea1ff5df4251d0f4e206a514148e2f476d8080181282a707129f0c604634c0592a4a837e0deae917bf56351498a2f28ba38c1eafe4747b358328726705763a81570b3de11b6e13b90aa6744cc217c330507bec40f86f3447ead40b7a90c1f088828cb96249da1a06e92bd79e31365ddb06e8b74ea9e51df1374df2d42715122a78b884278c0e24dca6a8ea3ebb82c22f0f35f7219a4f0f10daa3bcbe093f1c43249cb6eff4bafc865d57fc39139ca9c1045e64b12b9bb0a7d53b12642d08b6d5679e56a6b550a8e61d841584381a35f8f49ee163a65b1234c0d3b5b4a03455aab3b377a75d8d442a82b167af3ff9ce0100bdd8a1ef35d5404ff3a2c96baffc051c238787865501abcc5be77086a4bd63c900a7ae8542961d941592136ffb43551703777d37117881fbe01a6a9d73548a4acd03e325fb5bbdb82a9224cc9e9b23dbba55ebbfc5edabff648e26df157f2f9d7aaf89935fa02bdcb3dc43196d7ce968578e4c9b695df2756734f9821e9d9c1a239e8348e44c00e64b73098ed72e7b3e89a6a476cb30333d1f6a330505cdf046867d45b02614386a9d6661ea86dee8978547ffb736058f951102276448c5897c1cf8011856ac7fbfc299c026d9a3aa2427a969fb13ca540cf04e0fbd60bf96a2f57f3a4b2619a6fbcdac5ecc6c813e017dfa726ce467e16cf3423f013a773ae0418c0748091cc1a994f5da4fb8d37d907074592c107da77b22a6ce2b223cf59c3919ce788d4d174c949aa6aa158361b04caeffac5acdf05102cbf2b62fead442f2003677a67bb53f03e912bb56be3302c6b927e4844afd7902aec9d8247a6c58944bf15f3021eb138cc6a8e2748c375181fe511e0ccfaa5b419fe925c05b6e6410a03918e1926117e2210052ea891fe4e4b7bc23e380bb54aa47b90c1e2149a180d6b2e9c185911c648a2250cd61adac904a5079685c61a961598e247e832f6df5f703aa68595604b04b59ac11320d1b5c4958c67155f2c209a9457aeb201147c60ecf5f45b60ff7fff725256568c0b2f29f95026915c10f394503f9391c83e2c34ff7b892718008f3edcab9f53d1e296fcc08360bf704fcfbbffe6db51f83b0d9ae89bba981027fb0f1f4298570153d3ddd43088dc8df93741954608e421dc4a14a26f56fe6883bba2731dfa10f1b2914c640b9ff5a1aab93978078d847aff1e4f7e24325152ab1824324ec73138eba10d77cbd115191e8cfb6fc552218a7693ff7255bcffcbc903591dbf7123c0a4d6204dacd8dc4084961ca4a252b553a024b9f1e46e42c57683fda241e2937f99f22bcf2b5fc9cfa0e07d1d4adc88066f8e85eaf84adf50b50b893e1c4470135d76753911262536556c8fb6ca68c95025f6946df7a9bfd21cc4cc08c564495bd0c9648c24af306e021ae8657c788d3b5f399ce020b471fc81cc4cf92c3f737702a3d10ff97c27e00b3134baf81e7e4890afc48118f67b7d7087e513db752ac386e7cf4fe430cbc1b6c9f0ed4158f610debd4fd735b3c20697a11f33a4efc90e6f65d09e1905ebe5d639a2e31ddaed497c256aeece2f0e7239b066120be7804213bd6195b3ab9d57d34dbda28de6fcc8e47531079f7534376e811e75baa5a3abd4339515342e80ddd130506062c8e5c5f0c2507f61f4b8c312addbebd356ebd3ef50665d05e987e88ee697976b10ab840883c4b7a3a759fa8168b50f07d5c3deb315b2001ecb2106b375c39524cdc06d8bbcc2e98ba1cd991627301ca5ab1e15184fee0fce65afe3e322d3918770ecc3878965e8380126e352fe2fa2f9e5b3319b0c60a6723e22dd033d11f003a8b7e3b9c031f20bea3e99298218bb4b49f8d0619f91e1f21dd15f0de7e28da0e7bbac3c6e3ed895b17c7bac1c5fb1bd45e040bbbeb595c6f8c0f48be85de8cac226f76fabb980da37e83edd6a10488410dc2ffa5f16c6f8fd5f0057e35f8798a44490c260d2ff328946f3c80a08f22b4d1d19e6ef0a8f96ecacd1317b59c47070be7587a22b52810836c8c89be1085ccccb543d80f9d0fb2fdf5f8dbb3bbdbdc92595cebd83b0c063f566dc09483b78693b9b9455f54d1115db06f32d9cfe9901a8cbfde98b0dc5d6bec3bde104f1b7c0a90f9fd814a615727289d2865d345398cdde8c2c1735f5c31c164732961f1bb0d9f75c5ccf4167ba8abeee24a8488f8defa062a730af350261ed64c73b6e5ed15b25414a20b7c2d03b840f60eb9bd99acc32b9265c2ba9fadc18afa2836383a488583f1f41870fac8872235db2d8c7c24919d07715a4711c038c6bbab1daf380df9609bef808ac533d3d8513db0b2563bafaa682674ac5b16016e18c19c00f06d27dfb60a9df092b576a8e197e970d347eab9712865315f35c13e8fddba92774501d101c2a5bad8fbc1a6aa2b58cf4f1ca923dbcaf7728b4601ff6860c312d966eb84aed3422405c382a8b7b49dcd8a45dc997ae34d4f50be08ef4f5c6a3cb14927a437f86752cb4761081dc875ce5fc6c8a722f65da62d84c51b75070633974734bf092be60aa207653ddc51603fdfc30a9b26daaa1f61420af742375015e6f21f343c49a21c018d8f5a9ea42c4f5e6dd176c5630538c913cb0157f54ae4fe57ba8e9b6de54f135844f2bc35fc40b3e4b197548021c9e1ead9306a70a27312781960fb3927877de1a11ddebd10776ff960fc13ac925802b0492728e5ab7f8a0cc78c2a16b227032dbbbff896e0d3d6b310329bb866ef21dc64a14e11e4100b092b4e52be1a432c92fa4dd72959e616fed55c77777ae3e7d92258040913043fbbc02132f1da5f109df3253325141cd8757fd28539cc3d48dbb68b8fc586f4c8e4cb7e7018a0584981f87d9a88029ceb54ef5ad078a2933f709864a243858a9c1ac8bc67b40333c6cb774c489a854b28b9ff39802f0734a56ee743ef5331e6f1a62ea5ff5b2d2137d0ec1e0db6e0032b3e9049b3657042c4eaa8b3b60aaaff5bec9f52e1d96d9039c8c5f1e1f529f6507d7bac86417e53d00231e78f773bca316ef039a53689709d449b56dc1cec425b47189652642376b8533a8c73a1aa3f6d8c8356eef8e79fa1542794a71c34b9851fb85a5110b7becda9e37dc9c4272f2461b0a00b7d474251f9024505b58421e0124c23188fe82330d01354380f5bc1ec921809079d855cb026928569e29265593cf9d4fde0991ca4cb2c89c1d8481236801034124e2e70aeebabec85c8adbe52ce6e5070cfc0f5d4f03579a8955c3b161dcbc19eb1b4466d3e1694e297bbab637ccf34adb810d04e58d706e20f6ff08e496a6053cd069bc5c71a45755658972905600e5cfff7e754e0aedfeae082ace20e8d7ebb0253f4ec61cf0446d76472b4473f201ad16220a590b41a2212849df30a88d98b89ca50b91834d1a16e0e12877bb4aa1bae74b7b9a80252b49f7595df60524cfca80a4cd295ac250cfc8d268a4ad35d23525211740283c8db47ac3a65223e1cf0e2b469cc0c035a91c4064355fd095690afaa164e28a64a2e122191427bd6fc812fdbbfd8ef9c7a27b975b58b9b01809261a0923c1220a2e8c07b83645c7c3200ed0ae8ee1d832acd644cca079461d05be0b1021591d8aee221632299a09a083fe6e16fc2151aeace5545390bb3f9e8a0ab1060c49cb2e940c1756aaa6a4fe7c02d05b49f998c629ddbce637a068db15189885c603112cf429123128534aa498e0107fe72789596f446431f265e6e6a4290acee745f2f4adcd329064de423bf40d352fa1b32c49b23d39cbb30c9614dc5335944bd79a0fd762c5fe4a6fbcdeb5742007465f774d56cb0d5ab9334007b96a4916ebecc9c273bd3b9c2687475be604a55df687d738cbf4df62aa0230ccec27e225de1c1beb5784d87da48dc8fc1b3b5c9fb8f900f0b5ae01a2dde14f9b7edea585abc27a09d74f4016c88656422d36aa1020c6203b1f100438196234b2cb8100eca5c5b4f30397bcae3c565a4844727273aa5b15234761c5535d138d7b4ed6c96b4093a95598ad054e5f7758c262e135683c160ab23f212b237640878c8480a2a80817325ccf1bcc8f9d4a265d512a1076cef635eb4ec8ea0e15fcf007e96a35ee24a337817958d76ee01d531a9b662c69f8749da0b181fba609d2111cad3aac6d1b95bf9f1e5c76735e80f235563a649d0e231cb43def1f6e0696e6524791a9b38953e72f350366467586529ddb8f073dfcf30b3c6448270eb758d5a309b6f0ac62f935e9207e2e9dd019e82d152b5807969d1e18a9061c5bfff7be7e87f3a8c4b8358af71162cf8ca4a6caede31619cedae4e40e938bce4c0c75baab7637ba77a120851bcc96646e2874eb2346a961c92b496e28e8c2e1eb5135765ccf6f1b63475df73fb744cd0bcae96d6dbbf3fa2a5ecdcf6149679ad39aa3ae9bcf8713059f5bc8de26e61781b7474335b2397d1c506bcd21ee651237d551f26334df409f9a9e85f5710fe11374d9edc4bb6a7f7a8d5e83d820432f23ce4257fbc3a5719571ad63274eca2cb26ecb562b76bfe424603e93894d01d43a4b5486b2996b163e08ff06b4c2c8f908fe3e3bdb4839f82f0a60776f189898baf47618a6559867962a0183e327a38e6c0b3c4edbd254a65feb0a6cb89d1365ef87de201cdb5a66dc0af0bc3d502936aeee100cac4f6e4598ddb1d463352e3d02b62bc60512227331899636a3fb110b7f823aa740f0daf75ddbe86ed6653682b55cd438acd5b5a25714803a488100d847f6e592d116e95314ffa8d80ea2e562e50f481b7dd8aec1dad0cc3db944968ae5fdd3af2c462a9603a5602a86e3b52700d8b0de7aa4c932fb8a36d25f5a0483bb064f34a26677896d06fd1332580d705fe18d52617aec08b6170c4e3290f765e15f9e117e2f28b859032dad645a1ecf6a934c095edf9c326285732aeecd9ec66e1fdb4d2c653f1ff4ca430e7cbfea3cf6f23e4caf838e7cb09c0fb0225840c2bdd7b8eebda305f16f056bfd05ba11c8e2f2fc1b93974dcbd06c1ab967d303bc199911a808df56c8dbd3a42ea16791a03256cc23a0c0c81ec66a4e81abe1c7a6ba5876054d5ace9678b6a233e760307e1f0ed3c9f1fcdef7eb7b50d0b8ad8c400f623d1ce8ccf0b0fe606139abb43e387773770d7a88f540d4e358d774f4f831f62c2c14654cba1c2b49f4dd9b598dc0fe9975a699e6f03608f9b540d4590a0b9ea020c0658ee8848518ab00c14c44fd15d91ab9a8048b833e57b978ed26d808dfb341dbc3111ac40f171a025a2ef82344ecb0206d4e861ec1dc8ca5ee8968b94b60fd759f3f8d852762c924d2a43b08190bae50aa4a937e01a5a557d7956c95feb7bcde0f3214a5fdaa70a228479743befd25d88a6dd384de85d7654aeb7c5968819ed0c91a6fea5c1d4573dbe78ddb1445635824eab7267ebef561b8883cafea0d24685723f6aa6f54f03db17767dfd05f40b4f8d6c4a95154cd1fe4e2e9aba6594558f8ef5703bf289240f7e8057ad16d5d519a9c4993e4bda03aaae69e534b47f9464a33db3d319595b3b99fc697379aa5d3a7f5372af8b3bfcae0057e6953c6fc27e68a279061ce853d98339238849aea161e34bc4764246d5297f323b54c872c12a13f8c556e9a49398269446c6f0bc8a068ab4c3d604ab799644ddd89bfcccc468b32f48bd2616a59ecb1764bc86196793f001621cdf8547365ada1d87a7ad082fe627df44741692e5bb5fa432310481eb72264a943306347b661fa7aec07612c010d565936bb39e802d25f423ec15b70dfafbb17bd5013a7cd85fbb77ab49afbab06831334c9a71e88724c1dd2b02d5bc2fdab0db6d43d0b40024844215ee1a632f819bc42c660a38348b52df3a63f031b853ee677fe01e0120bb716e1a032222aaaade21d8453fbfa20969bd419148236903ad1fb05e6923d0c3b6610ccf73b7352dcefc6ad2e302da6063aba881106489c8c319cebbe34039f71bfa943c9e8893064da486732170b7b372f0c8198bc3a9077b367acce96fcdc12716a368111d479a4c51edff8d3f291b73f1091b55efea43c36843b556b517bab6321081291c0ed6e8a56125f43c11a1e18c86310a371d61061d9918663a123969c025acfb5d7996fa827eb3e36507f9a4bfc06939ed9ca07c5fbdbed338f7509a29ded9c313f82befaeea1ec856c30309074c1fa93c54b8e328cc108042225b0c924471434c350ec8cc97faee33b4f30189bfd0a8555d9b7aca56cadfd04d247eba1e174eab1fd38b311d30ab319d09c5197c00b941cb240ce7c64c94e04569b4ea492dc48811079f082cd858d47f3a1068dc5651450795a5ee35fb7324bf303f35524fa43fd5e71eb7b77f0294ea077000fb2fd1772f8fd53bae12b59441fa1200b33ea7a80e2385c04504ea0e92dc631cabc5e6a244a92fbe54fda3292421ab914ec81773b03ea46ca96aad98ac6f75a5e82167e4eeb70af6d8ef74eed5ecbf58c95f6def3bd1b2f725c2426388d8c1ae9d22ac1d84d48540a0e157fd49e7a196749a6bfa088f81e8dfe0b8e5a6c535bd97465419c0b53794a60a1e055a27b3d8e83f5f0c1c2c04ae1b6acfd67c52c9a5f193f763e99d313425ec0708a29cce991654bf8f39a1961aba5b17cf6d64777db1f738e35b0d76c1b35f3e796d75d2a258623337f5e4867526eeb80ae025e6866c9c09c5858bd8c1af7c57631966b2902453648a2c708f8e1ba81e26b81a18871967f746117c80348f65742c9d06d1eee94198e2c4c18b33c7975646ed1b53b33b9311f465308216add7f941259bf9e15f1d92923b1984891e2bdf68db2d35d2ca15346bd9af3faab9d116e0474f5c6db5f8c8029da24bc47ffbb5d4ccdeb80d65480df04ba4b7d01d50dc5b00c02f4791182e0a587e031a1281d06b498ed28216f3f83ef5e787f07b574395a0d695886a69e303aedd51031e3b85cae3af8c0fe8ac88257260373f0c63ae6eb34a3e0541539a3233e87e0f45302d39364d10c6a0680bef4bd1264f4a678f1f260bd11ea2f0a7e2cab783439bcced5e8686d431e52d18dcac8aece979ebb7e04c7da930b500bedd6af8c569e2376ca1c98e1a40e5d3c0ad6e5dfdb13f4b8c10c3d74ce109c030509abc991552f34d2fa1abc4e5cac5f36e550651c0cb257b89f24805e8b366e53d03148471b6f8f827e540d41f186946e20bdbba436d9f93e3e25110738f056d939de449cf42d81fa62d03d1eb2805f329836a0b5b493f353da81c05cd40a8ac632ef21b7186471e0f082025f0c4e7eb5af23ff9290e415d4f540ee47ca5180ed743be6489817b8db3301c2e39ce69144ccd584c2503b17ef7160eda91c32aeb43ea88a5e69beb00b1bf20f28d4684d25904f1774a9795b6008d2ecfe6791dbbe968d3632422d60414e9d2dfb044161e27c5684776cc01bf3c9a8df1ce6245344fdd01140011020158f058c4559c6ef2ac3ac05eb2bbfa99c7a10019e8b3675bedca283c766c0465becd247f4925495221a4b6cc6e939a047a9d2aca5b159f885d21c59875d6655414fa3c3d20c8cd1f390bb4a39f734f29ce85d8d51732e90c982bbe6ac1f5c64bce1d6a7bdc7473a85a34c611a56e1a347c1f5e4e3e6c1be73a1b3e8513f896f47c8705441274e4183481178e778ea696ebc231f19ad0b7e399e083f5f2937bef2016e34ab95f809a445634735ebd75c03052bb862bc82922e18f51fa9925fb68d3ca27c31cdf32528937fe0e205dcf985e4b9705b89f2470fe4d41a2382bca5e2d5c9aaa115a20842217201929e409cea70027ea03246dd69ced85c87ee32c0897095c0e369210dd1c549cf0198a1409649444abade8921afa28916f16d0fc68c0a8544b7e4a565d005d8a7b947e24a3200b5955139d4b5207c5d2e2f020e6a407a6d388c275228555914795a32dfc4502a7faec062fb625f491a013c7dab5e9d0b5f457d8fd7c31093b692db1da5a55be95467c178dbaca6d390dc3b73a9a0f8b2efc81d33daa338672f0d854ef7959a2aa3f904eb215487ab0ce8424ed754b0e87b6c027cc7f4e86c562c5b2b8e81b1043e68679ccd72e8e9cc85943c77c5190acfc178c24bf7c414b2ec93e6410f7e855d15bd67ebfb805ef1aeea618f06a0b252481fac81e6fb96a76e1d2e77db2f07ee673be832b090388b6d4ddbcd250608a24b39022dddee5b3878dd3b01a15d584efabfb989852a2d5e54c5b023f2c420c9f73004c19b81a03c1d33c918e7576df715eff2e771c6cc7597656f9e5f646618a289919eb7bfcb7f9fdc18dd28c66ecc145aeffbcca51b995cafa27a1f94ee20f37a8db9a221996232d603ac100ce03336cd29442753d282c12a85d54f815e62fa4a6f9a3987f5ea7643edca682c1e1bc1f01780bd47471be69057aa91a3590d88d828ad217df69e7f2af681a9e5b286b201cfd767013adda59204746e5c30cff23fe749bc4f9d80985f26bf8cad8e5e4e43d705f3f7006537ef1cf3872a4ecf4fc481abdd8d7883ffd9b3cc2d3f6624fe028123ddb0e04efd46e1f5c9ebeb5bf7289737d82de0a7ed0dd853245cf4ece7bbfe818b03615c542ef7a1f395dfc8f35220e7be4d22cfbbae1b8e30d4a0bb586b011f815f0ed47ed13d3e88b757a1855427d01c2921a8738c8a8cf6fc3100b2e390a84d1b9c91ef790e831bedc615cab8ffb4bcd260238efef2a99b95fd208801270d93164e14526c73871f911aff2b1a91eae07daa56158b082206e262513ab852a60e1e8a1bf83da5f9bcc4081c601be72c7430cb84c5e998aa45bfac072bea914d2b2131700ae71a1135a59ba8e6a09fe2e9e59ca11a9737f083b8fe95fd5f9385efcb1b5f9628a5b0c55bf3f8b8c249385c3f6caab5a38b2891c3c94845adc95cf2df6e49b60d55ee28854a985cfbd410bcdb00f5a6e0522413c900812b4700486c50b4149ea385de12a9bfe586c5b51b4a6ea9f611790d1d60ed44a08c23220afcb2739aca365b1852afa8a006dd8cc27ec22f81b2f2dfdb8868cd4618da2000ad4da40756667795588238a38586a8e2e78ecefb49314202af892468af46dab809ae0aacb7971b8eb013ab311e515dde794d5bcd004aa6ece01a74777e4a5b31464e11379962be5994c39a48f9ac2f66cd3d23de95693f6eab12c29f7f8a871117a35c5863fbd96daf5f04f767c6bc0dc5938ee412c8cdce662f0eb3f1ed463da21011db3810c302da8c5f8d1c48dd74c4113688105a33aa781b562e0db9de0961f861d81b842d6b96940242253b6a84f0e3a6a1b1a46d4c46599c33d76e46b47068fce361f37bee5478cd5d30aa1f7c3d4e55b1ec84172248b1d15a9b1476021b7c953da58e42396b9109f4930d4cd30e47319b49ce0f718663bb898f96e39331f2606d62f770c163f4175b7a4923fb3109035f655d23b57288b800c269c74e76cb5ba9428906a2fc324c4d31339c481f715d5c6b912d7cea1db566ef2bfc9a4275b3cb692fe95117d719fa8d1f6fe7209ea3e71727168066416bc72c2ab1ef6643a4127948be4cec198d18a2804a12ca3c75ef780edbc0859281a209fa6919d7d656d699d31fe33f0a0bfacc3817d78bb07082bc630731cf0956b9881bc0db7022fc64b8f46e80b4470d51fca8e712a28a8f5f8877308e2e60d11f4d2e96622e42e81ddcb32df11b70460b43674232338554f476946e74fbc5fa24073fd9819a056c0656bb3e59cc708909f339b5208e31d7743296a152a6c17c54f436d00f1992a20886c2d86c4dce379c3ba2aafe68c596123cc44ac7b211d159063df8cc4c0788b4ab53b24a0a947dceb0fde37e4f53e340a8c42dce5f8448224cacad9f57c9691b52070ff223a373d9c6d82478309122cf1820ab65c132f6509aa69abb497e4cee72d589e00bae12e03fed61ba08c230e917505c5fadb609d4f548a9974f7ebe12a1be90cd361cb03f315e7502ab70f5de8a21c03a89cc84019ec496a4ac0a1e7b2a21d8026d36393c36670209a0266fff01cde196a54faa9683215bb9990ae9c5a4522a3cca17a8159eeca4f44f8b094e4b7244b1617851496803c112a2f7d14213d77f8b105948862ecc2fb92b8d352580c1033c9904d2c3556bcee3191cd1188c83cbe52749245f167dbce0422a9f8e749cb07297598d8544d09ca07c0a0a117342fbf50d58227cc367cef93a175eb159462cddd342d352083f2f99ffebfc8d9131cdcc561b6419399c6feebc4b2d26376873d56f4be802a209eb286c2b2f22fc21f1d642d3ecdd9d9587be7a3d02357211a8e2d413dae55c78bd64398583f0e7fb36ad22ad8916e0801f195839e99180114f0d584541b77269b0e25df129575aed5025d1877660485fd87ce00deae0acb1232caf28584120f8b803b53ea9406cd378e01bfcfe2a5ae296e79d7d60ba7e3dd061c06dcc16b4b046131a1ebab37b1103731afe01d59695e54338459592672c64d6d274c188b6edae9e95e8e8270327cb4943aadfb2fa5f0b608ef5643efb382f46ab7cf9d2c9cafa27b6e560ec77d845a0247de8f01b9ca30531b4537dd2d4e280e3fd0d0d32029a4dc4ca639b72857aa61b0d2615940e9d5a0b9aeb607633f40d5c9a04e5da3be884773e46a563d269a8c747663c58a0d7a81ed971404796417f783fcb074fc70656b75cc3fb5fd9230f182041929902625088f8550fbde9e5eea84fda678004c5e2409678e2c656b68a592b2a60b5ae453b1d4d3c216d462cf198399a9cd7794da8703438270949b34f2c5f67c59f9224d12e3c7f5bed9b517378dcde32dc56d4d72dc820db89162c4dcdce2f584813b5226028dd4b5dad75a5404661ca480fddac6e4ea2ce0c45207d15fa8209d7e5c1f441300972bec397b920fdb78691ec3b0999a4a9c632e056cb0c5513463f4c70ca12e175918b56ebf121800ff718ab2fc03f97d0d75d83ab7d97563d9d64207dc1c483ec8d339bb85210cad83d8e792c6272831b37a67f2bdd71d6c693b97b883e091e1615578492a92c66b3ce9f00f24d287ba8357bf695925d80047fad1542984a913e0d0fa5883ba25ac0ee8022b4cd74b51a18d0c502cfe994340adf46dd892c60068991d9e5d185b1b2eee85a14aa585c5c3bed59313c6ade09f0e04cddd88f7bc157d8ae1c619b054440fe313e03938fb2c02e1862717a2adb1653d3be5c65d0498afd27d6df5b9e6536682d8ef78592765467c7262001eab5ca401675570f1e7635d848753cfa69698006c2d236adb327cf48758dc8896e54e3a693da93e694626f17c2b7c292e8bbec5149e4b855409ec2b0183089826105c5dc963e912832569e5c9cfd7b9e858b0c745d1619f72f90055e21f58141ece389e170b5b2a40c0dea86d50081b47a8146750e0ff191ab6ff1a96c2a28e9ee53dc3f58aa8b454555b32620a93cdbe3cb769f0d54979f700040b1a521b1d5d21857f9568ebc4c372ac23a20ce5be25cfb9a28ff5d7d7b6bce6ab434017e78f3737585413b1ca1b58cadf0a4b4005b5458efd47a4b3c34845617906ecc5542a857f60b649a515f5b12069969b96587b17053df8dd5bc73806df9ef93530a61d69a2ca65ccc7c3b59b9aeabb6ecdeb01697f6fa7da790583e6b406da07e8d55f759e7c205bf5ed866d6156cb0c60f91e65a87f0c510a13ff7de49e872240589b20ef2c8c88712d066651b99db6a7438c7545c9d914eba1c2e8b3dc3c2cb4897fd6850c6d296334d84571745e14abb73e02e05416899ef4c04ec76c7fefa5a96e2a44f049fa41aaaf850523e91dc564fac05fa8193f5260ee9246677fd666052921a837e83087e7b9a37c8e835048d7d85a8dcb0a1311811db37e0db15372977b4285ba9fa367ce1f16f921c132f543ee4dfeb7ce3063ff04955ec05a1ba64de520166542cc77bb1b0f889f1162ac1092042a338a43012752c49c1eb10f73785fc0414f1f4dbfab854365ec80f047c3c2313461a195b9a9c4dfbfbea88a0f8cadf29ece29195f3e38f905538a4e936c47b3066b292626015beca4e370eac4cf75aa74807062b0f307fa69179036be7e46d8fe32a82b8866e4c3b1a32438a19f65981f069852a098912e7083dc3420b084251ddc20379ba146870993c322b3ce237eb67fca84dd7b2aac5c0ea037af1c3fdcbd156a1c925478739886b58b8ff6f9ba779edf5586b28de8e5d4c2708bb5e32b3916aebb758e7ad667e3f746ca50ba29cfe1385102666a35b81cad026bfc6ed58e3c84e4336734cee8bc9addb4687dcf55edc6d68c23608d11729c4ca664895482bcd8df826d4bd61ba0aecc1d42e03424bf259e889797bb61ce761533167c73aab090826b088d667a5a608c54a2a59250cc3de4ceca5ce64161cffae38691566a1bbce6926675dccf8663717d9a90a6c845a14f65b380a68cd0ee5c10ef9ebc415a9aa5ad0103efd9d0a8c883f3d76eaf7690c1d23719610544204f73f1e84d1d81f104c3ff6c10e90f5370fda0c03ab16011d59a0163da3485c927d6565c5fd838aa90c101dfc6eb339dfb3e6c00de4c9b9ef7c98edd2559de3c8b33d3ac35a65daec1450cefb2bfdacfda5f83024f9ff992880b1fcd9c2402f5ed094a048fe20858223361870f7adf14d424d9a6ea15d8e7229cc263ad97013841f263087a5df630695b104b2aa1c423cdeda2123ea4183c14f722e6658581bc2347155e0f1154b3521f261148b066fcca70641f22f36e27db864c1cd31a0a99553fb7fdd742622e79b30b1cf2f6960650aa82d87d7c3a83745d512e1de3d30e0ec0b1cc81853214f5988c21af5c8031c7fa7515864f622ddc7a9176bfffcda84bf8c67670a4e49205fe2fdb877e155900a6494d8a0e2df8b12be0e3a63426e5e06cc8da1d432a9e903efae1acff0e580fc5b0808b929b30938f155ed1da30f9a6b95b34b8e620a9d5ff1f5c1da46d3eb37f71dd3779feb5ba0d8a65f4d3843bed9031f60b7bab4dbe1fdbe06961e09b77c65fdc52a12f089663575684f64548d440295bac8e9034090ddc82818636047e172f38ab0482adabaf783fe783a03b679b2cc585a90a9e80790633cf81941db6d7f42eeb58a3961e43694722cfec5108bc4420d22a17038b81a83f5ec3a2ef6dae50ab74dd376b195ecba62bd9d4cfe7442dd4a4a8d9069073382094a45a24ed9871ee59042e15653f7fb9ce9b35452f09c204456d0a24a1627001e818a1a1999fc87e64c694c590d87760a2511721276c974c7305c1777e502dfe8eb6db3ac88b652a7daba47b550832ef2d3738fb1cd02d76585f37e38816ff031db9cac2c24eab87ffaa448eb456ad524a7646dc3ff3a5a75a0c1b3af30c3cdf35dcad4415c7f8f7072f655707c418d4a754ddbad7c6fae4e51ab4968348d967aede4b71fa49958d85766d1e31e8727b80007e363322de5698828bb6f497a360a4e06ab9ab5807ab80db31f5aa8e2e156ef4f8319b9c4ade0af800ee24d27b1b71aecd8ad1cbb7cb553cd2c09391d55401a11e1236705f55eca19f96784efda4eb94013888ee014ddd6e8955356064de02efdec8164e467f753a326e8681e56c462b57a97b411f07ed114c819e4daf2bf212d71bab76d89776a64d17145101b5145c16dc9621d64a811f321520fc1328b0c0b5fef6a3d1188ba281cea7e8ea3d50cc8b81f00719bbf8c820662b1855ea4f9cf715cf2b5b1c54041af138a13689e1521ed999fa6da50f40da423a45e0f89de0029f450fa14f48b88133ad5fc720ad9ee770e0ab7282085411fe614743bc70ed3144fd90d6ea79ca03282bbe3d1980986b3cac1331567571333cc4a28b5373c141a2b7e9bc7e80ac57df62132b2d97e2071ea14d79bce878789abfc5ac9e1a169714af0e0959c9945951a1c44bd5a3d465ed418d0c8f2f532e4e2d076362656d10df8a12b7c0617544d06b857fdaa3b19317b90dc142132bf6c1e00faff45466e5c81cba85d4ea8a459f5ef864850995adf423705f6c09b85049c841ea6ab936f9196d4fbdb2cf67a19ce9d71c4f0e37673c8199eee83342dd3632a2a44157c65b93ba929aaee13b4f4ba1b2a951d886e5a15620cc7ceab8245657cd3041ed5cad21a02232d3a24f9ac6293d377203c33cec9e67b0732d4f27be90eec3ab8566e2f81179f5023f7488553484942c951eb0d18443c981e364f101ac5affd801ffdf6ead6c37777f8aab614d1ec16dc8e419f8659bfe95d70df5b31112c39b40aaf0e67eecbb65af5e92a4faf82e7710f8cd0b08b2e6f91c8fd0dd4217ea4cd0dcd2206291c52297072af0ae5e138ce2aec73e35851cfea55748fb51400eed3a39e6f0aba2ab4241cd6041d422624a2b5756fec57bdcba7e4f74dfe6cab0f2cf70ede7d731e76008ff70dccc355edfa26acad052fda71e70db31a81bfa25785e70eba33e44da32841d7df7954347f961598f8730207936a7581b4111e69eb0c88dbaf9d5b9cbdc5bed43a5c88e8d2605a14a87b95e7f8b0e73c93664877ce4afea9e71929eed5178ca51831d18a60d18ec2971c1cc1577906adb78bca6a96c0878bc7ff22e990f4b0ba6e17d66a5b43e96018c8d31406616eccb523177a38d7cc0fe3d0ee4c72751cbae3b1f5876d0730c3e72132995816ae0e39aee305c4f3b87f828fa6ace861a293a0a3415589fa571cdaebb40f44d3125a97d777098e719a7c201d01b2455c0e2946bbc9ad08163ba18918436b54af8ee58a2e77757c736b69afd8b51ea392918503993634d3406d7d5c497ce8da83a01f7e7e42b40933bff3ec042382ae37908c210efdd2aa8a3d4c55be2abd3abc7c152d49417850bd729f21f35e976359a6ee6b80004e7c751fee7c7eb436af83ae136889589fed1e50bcc41223ef515a1b1e3709ed147fa456d78bae33ca991fbaf8c344a7098c1ad10ef6d2652b4caba186e74373b921b8dd6399a2ab74ef951a0ed5a312b9a4b1b78b14034d18b511552e5b8876c15600f5435789ee9928d8c526d86d6118521b9a2e68ef5c8527bc8c515aa4f5b9ec4c96069ea9202be5125540fa894843476617f513a48435055232e904c6d1470b6aa722e61b006862f0432f9da9db85e1c36361922d2be86e0b291b308dfa82514ff18281c1edc6ea0718d029ffeeaba96bdf9269648aaff94355fe1bc83d683341f1356348953951d6c44a9ee96f4adf23de825d1b02f5f4d3fa00115934f0be9297ba6c02beb3b274b755ba1f1a1e2eea892ae143b1c3aa89e294a3e015fa49d947fd3fddbb18d8cd02619ebb6d6ae0c17c73ab2308bf272de23f80b92a858e04bae3a4983813a26dc7028de4c15ac431acb9ab384eeda5c78f95655165376366f851a49c91cff3518175d73f6fed70216938674990825a3c68b886c1865e876527f16a5b41cc5568ac3edfe3eb0281c0a12075848a4542db0ed450b1a9caa098f14f048347bb57ce47b1d6003e0b99c23df4e7e0a02c306b666a99b56460928c8dd13ac6efbbd2e92849e47483e9accbceba16934ee8d9252d9e6de1facbfb9c1963588fd19114656d66fef4c038601e8e272d5b558040728abff90573851ceb3170068c3b46f36b74ff83e8d918a50362174599fe5c1a93f0dcbabb5a7323cc0b27ca586bf67233485c38f231f79b0f4904123e621bd635772627d2fae961f5d28c1551f5b9c7b47109f9da56c7d4536af7b688526c1f5ecf48e556b879213f9abc9c8fe557c0f170608b600f690d0c857eb77d36598d308d8c0c2dba5820dcd123080531747a61a5bc7140d617f498416d83b33f6ea2992cfbb0536784a63ff41c2cf9a5e5e68d9f7bdefa4f8b77d84d8366afe39cb639a8a48e0d5178d2245d9a3d97faf5392dfa29a4c6e0ac039f69a6ee622f42427df17611c7954f578da18dc9b544fbc844d4cf530a73fcb0477b6d8085ada288c2181af75802640123829e4c5467e1d05eb382292b08b6fd4d7431ea2c123f595956c60eb078940e40ede7fa6db88539d23359c1e0fa9298b480d2da3929091ba115799a005d6c1f5faedb296091bc3b42418d64cd12147f5e8ccf3275290aef9796e91e6efa3aaa651e3521764891e104afe18a672601b14d2b04d08f9a8ad15f3d848a4e028bcf02b8a232a2a79bcad4909d9922bc13be4b8c499d64552781ee933aa74d746946b8ea557f48bd339c132edd050e05f783eb06165dd32dadab95b24e0dd15c36bfbb5c610ccea3b35bfba6915e42a88319efe7333c5741f1840f915f5399d1f5721791159b2cad9e48b10d31c91c767025d1e7dfd209903baeea0ea70d3baab145ff710c980fd0c95371749fd018a99146d36bb6ad581346cb564770ac8c494d451a7929c3115c7cce94ba0217cef98422e80f1d8d47280c6930009715e2b8be6e53f691346d1fb577c31a6fd4bf0516ea0fdd26c6b955ab37f3d3825640689d979dc1b4de87ee0cf3cfd489270b6ed120b610aa2e47d70bd09c60936b2cc9f837eac6a17e954167a3dfe09840802e3d98da3ddd2e682bc19e6e37978ca47b5657f0b07f7bf06401ae48f18da64c4217e0ba0103233e55a38b72c22e7aaa469ca76ae00694318ceb84c14d743c5fad930d20e1fd583d49d8aa830503ea363371860f6d5484704ef51ec18767f18b4e8b7ffb3bfa85ca140ec513be52324bd4f03f3bd3cbcd90b95760230565326f6c800bce0eedf100deb1a52d84d92cfe869813b64e7889d5790a3da371a0c253bb50c89da5bf4febcfeb726a80cb08bb88bea46c6ca95d545a0eb0761e07c8dbd362a731b6febf1f5c49cb37539b7d770cc7a98ea1d0c97d59fa80afabc68a8234d4ad57b88a5413945c5ed187b407aa02b7c756a2f03589f9a0ac580093aafb68cb2d375a73bd61b0a1dfc2dd32db560073221194ba7bc3a6c69fc1c7f6aab58dbb28f344c50cf0455e1c5c00cba381b602effdb35a891827b03779ec34bf63a3bae1ba321ef015bd66cfc34ee875b3b9db1d2c71aed630f63518b02d22dd3e2071bc8f0d704e47984579cb989b3cbfaacd70a753ad17100b9b55eb93ba44668efa486e379c986e65ead7e7e836e8979401eca47ef133bc70f45287508977a1bbc28db7fc09140ec99bcd12e0dbe0248cd3b268857612ba9c492df80ff1118989e87d86d54ed1b02028689d45f22794f376b43e0328388bcb55f2220dd92d64666fb826aff58c2724da3c9ea8f604e66af80c1280fb22f08d86f92caaabeba80189d4d04a5478224c3f7fb93f5bd4e1c0222a0a32b6180e8dd9db29e160fa920edd3716191b12b0dc8525fb5b485454964ab5994b475bccf79bd7fefdcad5065743ab8200a929c18551a12a60217f74da9e9d832d230eb2b5499a1d468589b2f02e07fe574563590392a096ec8f5e0ebc18038d9d602a3f335c9ccf3945a70c5ab20858d65c6bbd910788a9882a4f137beecfd91ff1dddcf166c843cd258b0f7e64e7bacab8ac640a090f496e15e6564822af2422b0a8c6ce59831a058867747776202c9de54fe5f8fa36cf0095c387693ed8e4ff24c29be8f458fbe11eb4c431fffd6b614e94265d7893de3ef96e600eff0844d95da1f3ea79bb31c0c7842910c3ac7a76e784163c3f551e51b40c801a480c52d59b66675b7b2ba93f3a970ddf8bcdf80b462ef1df57c89815b1ef96f4f29fa56ec7bed532a5394c6a710ff781e0a8add0911e3bb780f2641518346087577543a213d057f9c9a5ca6865a0d3a3946696568382361ac8ffed72c164e111422df0f57a81ed290443bf129b7b2c10e63996786e7069de6b83d609d109604f13e39e1d14ad0bd88da8628bc606700424488346c28f5ad32271ce1cf0cc6e47685168ea45399038c842613232961f807fbe8f836a1a98e8ef71b394b8bd0ed63a466ad1cb18d68405c9bc79861a8f33be3d2f2be46f9bc83909e0331d1b0135867d277e06f8e06fc140039853daa7115d936db712e9b36cab38b25fd567f5169ee869f572ed25c65e65d18d2a86af731805775cf2ebe2f816be15f27962adf108cb783fb0fba46864e0146f5e2027b6fc3d5bc58d95062e412954bd321973a2ad703618da4709df39f933a6740e88b64fd269f9013e216e5d04cae134f4a9e01c78ae608f76ccc9028e766ad80529f0a3c6135d59843ace785f56c5039dd13d6ebb70e3229c33f9ebd3ab0d0803141c527889b9f3f06b5d6a09f3fc364c5b8f89213aad3a027775ac7f1e67094a8b32a6144394af1972a9cb276b691fa7ef8b0fa5245e4bb7c73e7d8b89b14406b1681de6c135b5528df1b1a8a292970ab21fa618d4ae3542c93f4f1a2ab6ff3c14ea511535b6c22e5ce92679bda6a00831e872c1c6911bf5f8745e3e0ea6039066dfe52dcfa31d6371fe2dadf01aaf4298a3c5dc471ded50891a0439f049c404a74d9df6587c5efec13cc98a6979554e6956945dc279b9d028c6f5a3c6e4bca9c2372f85edccb1813f702fadd6349c6a42c2eee4be9b802a693411426f0ada7a80f991b5dfe446d51b45b3464de2584f8d8ea8caa5bc8966db2b64a51b1b540964e539e62b5fffb3218bb5ab5ad479adf7ed77b604bc2f33e02ba2bafc35df6730fd8e577b8fe6435dfa9605fc05fade61f6db187dc070c8a88a232d95c699b554582b28dc5333445a143cde34b756a134a73d6ddc8a732d32caa47db2f6604a935289d748f9ecc321e7a6bec9ada2428d77ab32a2841d4544e5db7b06a0be402017f958c179275da670a3b6ffabc29c718e7be7f307d7a305e399a55a8eb91298126489117aaf9b426f5c80d203631cd073d33a0775ae09fbdfba6add639cc1d020b8c8b22c459501c199dadb246206299bb0e8052a7f0c4b09414817af559ad6170df0c405b25a9d9e60d62c6a4a44221da296929bd9671bc016a94167af3a5557e19a0862199eea33d2af7ac943e8683ddf6fbb8e8d6482a02ea6fdc50cf61b8fd2608c26ee45da9d0802f0d80e9d2537df15ca933a397e51255a3f30454fde77713cd9509a7ef63f6032da72d9173da4635863e1527ed0ca58ae0fa587639f497acd441cb0353db40c2e056a58abc83610e2ad441403f4fdd74b062268db01731da2cd5292949d95558f29957977b90d0fd5d1f09521f71bb05a86a082232e0ef321861943415ed0757f797822d52b2369b3e7895837327e46d3c7141850e4b6ce8dbd4ce32bc6c321465ad504d0dea456c177be2198150705c3ad2c2134f430ab6589a53cfc596284b5ea7ba8fa56dd5ecdaefb17fa8a6cc964c3341099779a72399c320905bb89eea3cfb5855ed884d3cd45d6436032173257b7462c73fa7f894af6437621f5c4fbd9bc763a60b3405f33cbc8a5f475b720f7feb7c0122b2e80bb1925754f554a366b475585a5e74ba55cb47ffb1d30c6cda4d66be61175f8d4c75830feb68ba4e2aa4ba60566a241226950bd9abd0fb5d9a6ee2e004a1c369b9a62aba0519ba15412ce06ad82b762092b114e549dc7a834f428d40a40f926d4f0643c373e9c0d8aed4093e7a0303d79894a3936017364241dd4d2b2796b7d2645824920ccbb7e12c2a41dd484cc6822f66a6b62567b367f15a6125c85c6e981f8867b3015d6ecabbc120bec61ffd0581a6f331a8ce131f6ba814ab41ca6eed29fa1f6212fc263c0bf232f6730c18092b91e3fff0d4985eac14153de80a7eabe76b5f04524d17d597fd6240cb4dcadc1394ceee5fd20308d0a84b5e9c3afc454396cb72c546a5f05a16cc457a0a5d2223e360fda9797ca0ca0faf1ddb36ba41a8cf00e18a641b8c2a6e2315de3ab9a5b49a541a61cc91da553c23f5eb1fda7247ce564b287c0252007a005eed325def91a7213f6541c1855f25cc1c4c4caa7acc62385ef8dc38ca1944506fd061ac3a001c21e9f427a5854e42815bf366d70a7e34d332445ef25e5a2d420a96dbfe22ac84c05f8e5c75cbec9b647bd340182338fcf60fb8d47a01b7de586688506f408a5af2206e631a4f72f7f1d64c4956fc13056619be510852433d480f9666978c90ae8ff8daddbe58b266e98cb72562ebf71d55dc7e3fb22ee119bdc4005e5942eec42d5215641e343607c043223b4105c2ad7d1f5e38b6722cd438c7d7b9cbac80cffaab4920195645ac9dc9f39b7bd1c76fedf811cd2b5c98d1ad8c2e97177a0d9f248507bb731163a198f42a47ea0cc3883a7691a13696327a246d4c609be87f71a88de0156c3e1d8d4ce2f2836cb15e260a12336c6c7aed6915a36acc29292b0e25197f89cc89f7ff70d18651ab1753488f491c488ab4688aeaae4c529cbb3a59927218cd8cec05e67a0c7ebcc4114da07bf3ff2280033f7b4fc12fe81308c72fc5ee2e72257884512189120c504315cd1cf9f37b2a42f642135deff4dee644e3fd8dacff694d80883d11b2a558cdd400b05003792e8872c48561985b6df5cca5f2dd89f88c87e42a86709fc70bcbf4a51b469f0ef7a5fd0f12491e084b15a2d80d189be604aa640782073f192b9654339def94c4c1f00c91aab70b078dc884228b7a7881bc70b3c0513f160a05e15b069a9c820d7117956c42fef9555ef16e8844dc4532b356d50441c2664aea614404c79a508506b5ab2944e21398c49f4094bbada4ea08dfb28c2c7bc8d916c9558f46e8bb313ced12054d4eac801103536bfdbbad811ac579d2020e9b447a075b79cb43c0c5a3d26866fa23f51767cae3d30cb5955abc2212dd342084f9866f9d017d13a5ab6195f605d5d26fea203fc240436aa260d274c11f131dbed9e3297b1cd1f2edc8ac02ad250ca258ae106d949a17c1abea2ede2f652f47d75abed166ff7b4c887c010dbd8ed169f108b1d7b9ca1cf85887c3eec6d1b0d492120f1e47119cd8910e6b8649ce5beda552b8fe42231d999b062093bb16e3cd62476a4567ff057865f7559a3985ff198de5591a660e3c62e43b3cd3fa0ec5bc9679476de868f5fc57f551888e52d398502d51e899850ea56380b3a92d0b615b5b7e0cc7ab44f64dc19959b381c1b59482a852d0c8b5a4deed0cdb70e07d00ee4ff44085d090fb5a0655fa6bddd61888a8ee9c4ab78e4c94e35b32be6256b6397be89d8b8fb934f72b512b34d370e2e9f544abb83acf6891f92dee91863bf83d0a3e8f0fcd0de454174c4f0bb5808444729461a643d72d6e0819443e732deff6dd0297f261ac405ffc52da9269c9e3a2e9421c67c57ceaa49206f7889328bc5cf5731840f376d11117a392526ea44bcff2632d3b1f18b9e6ccafdc0c31b9646cf815965beeb78134130e3591fb1a5b1090a17de88997392ddb0a03d40f9663140c00d02ad1b9fe57e92b17aa3d3768c83fcff1cf742f816158c1b275e444824e42ec01538ff88f383054dc1e5804f3109f31023dedafbcf162168667bfb481e71f852225f423031a6d36ba80224098fd986e82329d20a2f783f33903cb8a4e352dedc44a68736c4cc4f8ba7151c8cad0c73a1406bdb1fbe3b273bc706435f49e918df20e357f04c291e11c9314679c6b23d89a6e17ec4de6d615053c4649241aeb83cdbb743fff61d43cbc69d52d8147a955317cb8d0e33e144cb9a4a1e211e8ca08cc4f783f12b2d92fcd0dcb4c4066a897dc226a24648bd610b755a94040d8be3b4302caceae49718870c957c03ef958d8ebf1baa4ddbdf9b1d70f0cb466bde4870a63f85df7e00edfbb9b03f05ebb44d056dd47c4f4efb3b91ca9e1c047db0a60ca82a9f871a8fbfc955d112b13721b60dce602d7364559fc90e801ab83ee7a47df244ab925b3db1c5e5243ca1f1f05c5392f2e5bc4a54426cf4591d1d00215f7839d7d6219d54d24c15f53d83693924a4e83460b475913ccf45ea2722ec6d7f3b70499d56ad364a23fb47422f4be3b4cea362e98aa184757609dc71f6c6f1e027166acf1caf088f195580fcbb27bd6de2c34b0dbd36ce0248334fc4d4b568036bf792545782a934687bf69e266d41a6923332d21bf022ccc8042608137374194a26db34fe555c0666c384eb902df81b1cd361f17265e753ac7a4e4191e90fd78f57f0b2979e1d3bd0f1b2cd86a297156e39c7a7d8f55780594076ddf869c28d0b9290ee28db04743aebdd03d4d63f9f92f75c26163f2b91d5046ccd9971b5fe5127454045962dd74f83ecbc811d50b5eb124a037c0043c0fa01fe7d5c4e84a9c327ccb8d625919399005220f18466344c4181e1944f93c08107e939e5949d0f935d05d46a6b5a49865775c5efa9a7e51ffe57f9152034de0bd5e585d3d9cd1f6cb64a7d4826f0fa24e99e71f3b17c7c0a51896db1ca0e0ee14df2b82221cd7a14234f67857181de398b4f3673d50a9aabd70da062b80f7af3551aa6c20ad42c162024c8954d0f1ae9d156deaceb629da1d86bf86fb5bb85133a4387d0f43f3039dbbe9b4e37c20469ab462e463c23560c1ac752b63b018d94431da1fd1834089a1514eca8276ae00cc17640263ae2dff504a7d9f6d5461d55fde30d5b49383d917cc3ea023471044abc0fc15720da15a903caffdc312e4c1aee4ae5df6913fc702822f2629a1686b3bbcf55f1f9bf97c098c21960e638503b21da989f6a32f87bbdba32baf43b8149afab21c88fd8165548451cfb6dc9c6472b84ec5d42f6de52ca2465450c440cf30b2f2fa0e936592720681794f45310db3923f0dcf64d371898898bc9a25d062c8cf640d550355b7bb04158d88908279f49ca3e0a722ec0aa3db1e879e20408527e200594578c7c17efb91670f3965fde25bfe859499727c977d196d4b676f65d5e75dfc6e7bc48adea580f03f32cadb23d6cfaac77791b6fe3f2365cb4d536ac7779177dc3d244607477bb9be3b3bb5bb3e9c3f8a8b9bc32bb9351d97f79f25db20ac8cb93afb23ac88b56d57f79957dd6e7bcc8877997570581799787d1aa0af32aab55405e9ef5362fcfd2373cf66f5eb40dccbffc8bbe81d1392f17fa9d2e6bf6d543646896b43edbdb5d55ed03a8ea0f14f4bb9f9b7f324df7f469a73d8e062ddbaa2ed3add21ea8211a6322c3761366c2abbd76d671949a6e4326328c41032b21cd8d1b37c07c6af2c4649d7eea290834c61f36b34a2c8d6b011eb918bba03deabb28cca7ba74c8aaeb744bd15229a0ea7a793cbba576627b5644aa2755db305fa6827ce68bcca22b05bb649827f3cb9f6ede521d80bef73ebb88efce3b3551e22e1510f273bc8a530571f99877f998f73f0d55174bc5e920e4e778f2737c3932d98e826de758b0e36fdcc82afab567475651fd83cd8ebf516937f44d9deda83e3b7ebe5cbeac3d3bc82febec46ae3bf2ace4bb7c59653139c6238af91c312fc4bf72bc9d55d70e1d3237de259f6e95e49eccb3925c49fcdecb23131d30fe15e7318a0cebe5860d98183d4ef11d7a865345e4d03129f8345ff46a140a0accbbe7f22526bf1c61b44d62be68da7597ab564748535f870d5d3e3df1d5292828e7b96dc8f325803c5fad3c5f38f27cf1d8ae3c5f2c610eb519de875f2958dc256ae2d27f33a00d59e75f309ff39297178056d187791baf0202f3365e45751098b7f1ac7f795510d6bf3ceb5f5e9ea7f462561da07bfa9d56e97091ec22aef29f9c4d5b3816609867bd8ecf9123abeebb5025fdea1f6c747c8edf61be3c87bef1207ddbfe39af9f2fd6972ea443cf17cc971e94237bad02955eebeccca7ba6274bcb332ca56491b30cffa6f06a4e10c2f803cc27064940d79fa8e16cab684f51e2e79f919b2b2cebf5e1ed5e33df72828ee42f568dd33c2fc06987f79b7a151507c8c794bc75b22964645d9fe3df269269b0290672551b7ea32d9c81fb9c8631734c67f863c8e4334a7746272ca679ce2a4bf8e9ca255d295533079fa8e3215dbfe397ab67fab16b4e4e55f2f3a558493a9234e2a41e233439e3b479e2f1d3079be44de16f3dc2827dc355fa826f33543a36832344a09f92f6fe3f2304f7309e62505eb6e52a6cbc22a6961a6956df262b6c4304d37dac322a15dcc191bec934fe9746ab5063007404f3e271fdb5d0f6659b0ad0db67f775d38b2075008dc51da3dd78db7fb40e3ed3678a5606f83349ff6f7027f8094abdcd3a7096938af729a0004f01cc09ae9b6334bab7a24e38ac0a39dd19115e0d2743be22befc0c048567a0949eab1f44632994c0518cf00d30023316752b806d806f806788693c038c049b0129c03ac03bc64ce54125e02338199601ebc03cc833963bf1860b4e4710ca39471ca6491610c63b2ca9082a58048a14025a782c8a9582a059325c4640d91d2c92922264b05a915a48a48b120d582940b26cbdf25a7640598f133dec619cc3b13e3fdc731cc19d5fb8f52e64ccb9c49bdff48863933beff18c69c41bdff588639737a0e8839838239c3f2fea920e6cc4a6ccea8a460ce083167c0f74f0d31674673a6ce901ebf7f6a0573469462c19c11df3fd582940be68c67c474b9fcc9431c9c9ca4e9661a3ac15035daa30333867e1736fd185907034c16fd967c80c9a29fca0848c064d14765052c60b2e89b32901d183059f455b24d6e4010073c000211982cfaa52c81c9a22fe60950a0029345df255b80ab41b6eec74866ba9d824e0600f18e8df6187f688cffccc7b6111002e15ee47779c68f976740c1bd524846b25b2561be9a320e4d562ae66410ed31823163fcc5f1968ab96b9c55729ce2306f5530668ff1671c9a337656a68ea48ad83fa3941809005d32f79aa10e45e8ae3fa46e6e894b107fb9e89b9b17f933d481a4f3a24fb7ea0227497f4e1a280f93d9c7648db31fda438719431f0a9ecd298eb0fdaf074e3e5fdcbea0a62f36ed81b29950b6930f05c188038a773e719ce11e4c9b11814b3bc33b230e8674e38cc6f88908279f1311e8177b467b58d88c39dda6858db3aeeb3af1a3276e08d1cd5b51bc558ab1cb710bcf566e24f36c5cb5a82bbc8e2a40013520a7839348616b7366327197e956495bef49078a136cfb9075a27b15b541b1d9999d8d53eccc3403f794c20660b00b004fb7aeeb3a9310dea9e410b8b433a1195b78ab34928d37eb85ffc8c5ec81aad198fb23d9bf33d1e5ca1b75899262fb77250680379bb838c11a6003d26c620003c21ca4e0ba4bd3cd74f38204d92ab63f2704b6ef7b8c3294026e46bafc7873c923cd7728f1151d67a3929116c323de79ae9636e8c9f60fa2efc34b4b85059a33f4ed8c8ae94ad96c54a00215544411c534c22eed2c0001d8a59d613c8e7827359b2c18b65f8eb7207039def2a9d6e5d3131cd80078fa39d5bc9582f9caa7ba6cfc95824b16003370ba4d16fdf23401d0eab41e87c7e3f8d6cbbc4deb659e6a1b1e8f03c7f536de9f476ee55949d6dbe4d0aca7dac6a5a98dbf9171787ceb63320ecff738aecfe1fa1c6fe3fa1c3ac7c7fca76d787c4be3b4fec653205401c9f1316f93e3639e6a9bd6df703d8f2fe9cfe895e35bcfc3258190e6d3ad1c7988cc7701909ab605f08fb7ef133f51ab74b82f7e0ef7c52132fbfbbef4393be3a779ee0a84345833a1fd1e6fa4f7ff2a0096b2b76dadbae66bda822a501327b65b2624cda10087fa64d3a727bee280c0a5e9760acaf13a3e48eb77d8596bcc31be766455f72eafa29fe3735e3ab2aad3e403215fc7db90afe3e9eb70f91cfa06e65dfee6e5c9cfb1b44f5b25a34906c7fba384aa8b555d36de1f474ec1728a96ba91533279563266b5534c3c95aa62e5048ab1c94eca89242fc0a16eab53331b7984e1fbe5781b7f7ce5e30f5067291d7f2c975d489897121cd2755d376448486367371317a61bfe0078a560f701bc548032da594b6fb7db78b3345f29b1b36969b7eac23b1aef50f25de60c1d872a9964ce8c5e4c5612b3c7e842ea59c93b46419501a38450507c95eac61b0f1bbcc0e3d018c5577ec3c076a7baac1233db034c7ba2c7cec69bfdf11614deea6817821080570abe5f9e7c2e15b81c6f7366ae6e73e6c6f61f87aa8b4cc1c6a131ca789b2c32e01255c33b2924b60ab844d54e4135eb04680c693a7ada334cc0c4628325aac6720adafe7f0a3a3d492171d7e956c9d448e629279c89928d711d8d647887bc537039de54dc781ba30c798b56d738f3f4e9763a7d1ad4570abebb3cf99c7ce6cc13d3358e271f9f3d8ee5e986c457de8f23ded178e6ab31e072bce15b75994ca369348d37d3cd7433dd6460e011125f996e748e64a77001130ade294d378cc4741b4d37531498cc7843620a2750d8e578a351d5b8fc0ef3e5a283803f08c2119a788db35b75e119e0d36d6325700ff0ce102ec71bde59ed7224bb95e30ceb14e12d6e8b5ddad92e47b2233bde8281ffc888d96304a2313e67eef394e36dbcd9d9e8e1d9b64db6ff38ab2e97f71f69d5453e61fb732e59a692645e215b7200e0ee83217c8045155210c6c7f560641b6dd1538e866aadf5620147bdb7d61dd47bebbdb5de9a83da3da9dd93ee49addd937a6fbdf7de5a6badb5d61ab40447bdb5d624b7de5b6badb5de5b6fadb7de7a6f92244992d45a6b7d7299b838964872ad8039252e0e1cb70a97898b63892457c09c1217078e5bbb27f7dedb3db97549adb70b252a8e5a6badb5264972efbdf7de7befbdf7de25b5d6faa4d67aefcd42bd1547adf52649d23dc9c1bd3749ed9ed49aa426a93aa83507f7de5a9fd47a6b4d52ef1492e0a8b5d6fbe4de6a8227549d1d773943938e3b9d7ecc3738ae30cb82ec85e29adca89a50c2eb04251ebc4e8fca27f02b409164f42f044cbffbfa2921dbdef9d0a70d6daaa990af6cbea2b79116e9d2a316d501599f94fdd4a4dd88fa46a96c84c2aad0e735f1167dd11c9520f98e8ca644d9b1d14ba937f3900401536a39a7e267974ec5cfae51dc355f2efa2ac2573a3ad78e46509cbc968853beb6adba4f3728a33bbe4202c57a3b1e9299eff0e778b0b7e3cd7e7c95a2a2fb13e5bdfd9a783f1e144e7a4f7841a031347b4d7ce53fdaf371d036b26274051d41e9be527751df292195ea3afb5d17044afa4b7104167b511dfda150d09871f41151ea73454ff7c464f9fb4cd690af465bd8d3734c465d90eff0ef725785af8028a5e37f4538dd33dc68548291042fa0d7e32d7008fa2a4fd7947e6e1bfcdc8cff3e26e3c1ef559f02f053efc3bf19f9f432b2e9c7acf23132ea5599e55379e5bb67f998e9579e66554d1856f122fd47e74b86aa45c76229c881c16030d4c762a78fb17cf831d3c7569ef41abf89a927e40d5552a7923b22986816be543cdbd502a63a2d170bac027ac40a5c305bd5d509793ab4073d12869b87440c8e89c3b3754247c2d0091d51c360e9db9143878e56113a39421a4fe77bb013f2ae58626331bd2c66ab0bd3b3d11edd107abce884aacb33a21b0a3d1dcf46ea2139e12d8ed63c9b67f36cb4a7a3d121744bf4385103a72875ca11f907863ecbd16b3dfa79275c2d0dda83a31cbd42b89c40775f2d26eb0aa19a8c1bf32685e037faf2ca442f9bfb3af1d5fdc215eade3b6d830f1c687436541acc071c6cf071c3fe88d025a86bd4770b27ef94ba7fb0bbbc5ce0bbcbd975349d052b139576bf70853e4bbb5fb84295467b5c1f1a73bf405d23f0d901f5a13dacd52b1a5353e90ea82bc8f5c1d6dab9e9ce64113159feb24d67a002eac285ced50297b726946b34ab23546937215b569ad0bf6dffe0fb6a3159fefa0a4d96d53f0a307fa60da9bf5188e205aa592b0a693a5ddaddd57c75e9a84375a80ed5a15cbe4eae77ef05f21db27bc45ba8f7bfa8bf9f4befe5df2befa1b2ca7ba82cbe87caf83dd37ba8ccf21ecacb734f967f1685e073f9e6efb9fc231be640bfa43f7bdf3007fa35c4c1009c1735d8826dd3bc6f98030e389cb401b8298ce0826d533de7aaece613a408f251bb9c816daab4d26a51da28ac12db1251562dca1a45133190e20a922e2b2c4f610417425dbacd8b1a6cc10a5097fee3336e0855d062a44b8771225dfe668288235ca1736bb55aedcaaecffd69e22b306027b7e62dce8b1440c962fb5f206ffdfd02bef788afae177049a915b48607c09bfb1adeaf218dcfd53557c8095f6901d79ecae40a4d20aa336d480199a294ae4a545a5969da089526f435f1d6a557e85ee77207c5a66fa9d0a6fffd9c9c4cc27b5a2ba574f4d70bcccd68d00e1976496db520ec1aadd59ae7e11c32530936b0dce059eb398773c8f0c821c3e2790e8eeee590f1aae7799e67ade779de18bc1c329e37bbc025add580aa806d6e3667284d822a417b409fd83eabed38126f75b4466b2291d7d97a3b35198940dbffa32a2290659cc1f2b2a235a2d168f4930719ee192ce35ed9d108ff280f01370914fd8845fc72f4226d9379c8354023cd438de864fb8b4ebc457f24fa9128beef4f044e1cd28cae18b0ef72e5954536f8a35c827b2452f952f4a216a1f095581389a8f657c923300f01494f7a2f7d495f84c257624dfc5940f71ea05aacf96ae5e2cf04126ba213be9aa2022c6613645be5499ff82ab9a45be5a7838f1f5c21812b2b6011d3af90c0295e00838ade03f397ca11dd3eaa4aced9a33cb729b3e41bd2604db1f821185bd443c06ded1447628f4824016ff93ec96abc35f71440fc6cff0c788b520186cff6bff1d67c180c36c4ab9c516216c807b0dd330510407bd4e3ad52fcd93fde9a514839b2fd4528bc35bfd8242d76f72d282694de8634a5b0d401991868cec88c5a4c2bb6ff9c2a1d46ef5f432a8008bc62c074d3508711d538d04dbfc0e5fca9b1e1210cb87ee809a13f42d8e514aa69624f204ec9049a403520a8a91070f621f2b83bab108154fc74c4376994641843610cfd5821a80bb5054adaba2866cc164e41f899827e75d4c138eb2cec04c4e9eb462c469b37da50b31135a33d4e51cc183f05610a1c6c17fd373b19613b0f6a606a3667acb746fff2303762c69b85a16c36a7987812b3c728a331fe55f83881a289132f48b275fc8e2f4de0294889af681f299fb8f83e8bea413981f20143540f18beb8b83c7d97177d7393d33dcce774fa86a7fb9b179b978779187df392e3bdf742831242d9b081f9171bd6dbd03730cf8ac9e4dfc82edec76497bf91615e584fea59491b4ff58bb62f6426322be9b39236e4b3f40d85a16c9524dfe56dc877d1373c14a6862f0ff3e5bcd1a880c43cf936314fea1b1efa37e48d77d1372e7f83be90171e6aa68d9b4030d9873f77a9a8ad11c8575f8bf3de05e6471f98574519b6a7769878cb3f4a77fb36cf7d1712e6cb7ff972b5bbd1eede1361198cf110995dca9686ff07bb95cccdc524b99833733b8c07fb04c6f607a1d85d9dadfaddd339c37df73e67bcefde1bab0be6bbff6ed8f8f98a8979d607b9f136348e8dbf6143cf4adef8f93debe78b7e5a05c4c6b33e888d67691c1e9c59c9d2026d7f1b1eeb6dbc0d8d9343db1a4b4ff14b0b9be287127216cbc676b95c33bc916332fd785097eb79501efa86baa8ebe7abf52575e91ccf2353d94ef6c9eafe1b5158a06c29b0b3d94e302efcf48569c8a2c02463c6fc1e541350b51eda6394a19a405da830a8ace736595684415d56888e0b2bb4fd51578c322f5c37d1836a02aa7603bc67ec7336c0e578ab794ba543f7f7af2eef772927defa82463f3e3f7a350cb483f68f645bf80a07b7283752831ee680b2a176891aa2314519f737de4c43a629b71fa814bc6968dfd40575c13c9de19eb6b87ca9427e39e2c24565b6d332a2953fdac136ddecece4e3f2a7dae9e78a518a8b4b26ffa301b50594ed45b4fdc7b107d3f6f856075a7230f8d954ab6ace06a7f88a0e8dddd88d5dc7715c57b355e28db71aa82da06c3d281b6a0b3d3d3dd6258c5bbdd5db89763ad1aaeb640302ed71aac249a8c70a73c606db1f253b5161f64021a127211b5fa03da8ae61d018771d5818b4c7090834e6b4535d275a254fb49ddd3d15a65b477e79638f4a7833b8013165cc6454c68ce75ae08af188e8f73f4316bfc71177a17a043083c365c397a958005a3c50b5391362d53e8d7a94d1b857732dc0a31744d8346a781f3f36a131d565e3861d31df43db5ea66603c8910aaae14bffe3ab14cd57aec45718638d318704c6333c0280ad92317ece96d1f4a79f9345a586b633a0ff60b2aac64b56d5a851c3857c99cf79d5f8595daa955601b9f1326f73e365f40dcfea6f58baf4768d5f699b1b2ff332fac6c6dfd0b392353ee75543ab7ca0bbc69723100c0074b9dab5ba6c5aa5cb98169dd2e5eaffa4cb51afe812abe8508f461a60acc79aa747286adc9bcb54124364760dff5190955fde4686d991555d8e677df7ac1d6f43dfd8f81d7fc38ac9aaee6fa880e8f898b7d1f131df7d8cbee1e9b44dccdfd0372e1ff337e4ebf89cd7e7acbcdf467ed11afe9555f46f7cce6b67158579fa30307f43dfd87898bf61fdcbe7bc6ec82afa329ff31a401ec0df789b01fc8da77fe38697d1372e7fc3df903f80cf79d590c72996461ea300edb821a768291d3906908255726c4267930164f26fc82e5f439e9b469edbdb3d39380d7adcd17a3c22b3e1ac9787a1c1e81b9fbdbcf8cbe7331bd9652c977d3c728e77651dff75e0a7c35eab47a01e544f0fa9511e6aa8ba2ccce542922439fe90b9ba641faa24d5a36da892a828e0eef1ce8e47c444b96c019841d9743043d950357afa827e0270996ea3992262a68018c1a88da028954aa39a93ed5fdbfe2323747af43359421bd726ab24fee7e3248493cfe94445181414c47960c874b2ed0f994eec570fd8af2399af9ceb3a274e9cd89452eabd07bcaf5f80110c46b2f18bf1466347b27124a3e3f805758d3aa023190ac6850ea8eb44044a769d4611e134b4bb4005b1fdbf2b057f077242608bbf3c8948d77eea088a7c2702f6d677644609a1a0f80ad6a16c2821f7bcb18382b2a16cdeeaa00871d55a1bb357c0250a654309796b86010393e799b88e3a6909f9a4be39c16b1c123b5a4ba219e20082e964d75cf764754f338c93dd43b13b58f7e53884abf838d85ff9aaebbaaa6baedbb728a36cbe1a329d6caa51421a0505651b19319ac12889911209001390801d1850eb32ca890c8584f6404531631c15b4839a62b2fc4b940d1c30261967fe89361abbb433bb83fdc02b059f7679f2b95230dde5c9c70787341c112d13539a0ae9ab5668f6cd32c4a476569297da99ac91ec749b334e3392a970a89ba6689b8349c12127639a2aa9ebf4483659d7495569a97646e31332ce66ccacfe67baf53783373a82cb916ccbc0cef0ce911d0b601a429a314a0eb44648233e2704f69fdb621d781cf2d548d695b81b87c629db9fd210e250af134ef0ecb823f0f73b42e0fbd4d61aeb6d7cad8d230c699790efc3c79baf86720a96d219a374fae299b79cd81ee8be9c4e76fd5adf662fdf5c75399deceebd7bc7dbed36ab1d329deceffb349e658ce4082e310c7039de4cb4641bc9ba6b673a740c1ab70400b0ab51a3c60abcd9f64c5612936569b60733c6e2c0c5ce262b87b95153e0efa255c5305bdc5cad5ca6cb773f2e9355e916656bc464d517525df60594ac5f9510030eb0a581954d567d0f0ab8a430198579cbfbda7dadf55964f5598e784894ecfab36461b2ebdf3007cfbfb2883d42174736f8fe5a15640567fa0ed76511bbf2e0bb2e73543638672f59f98f8607700f94618b465a65b3f2a7df61e54fda6e912e5df49f2883ef796e961d5fd56739e2abfa251aac64188fbf2a88caaffc8ac6512d39fd7cadbccabb2ecd00fbf0951b846f3065dbcd423dd34d453b15c85baeefcd575585c30e2bafc2816eaa979cbe92378aafeaaf68150e74bb5eb2f22c6f3a99b20b55b2fe97fde6abfa2cb9d62a597f942b90afea1096ed2bda4b32c03e84c50eed3a6557216e739b2d033db86dda767d91901e6cbef2af37cf733d7228be7221df51ff09b8749bdbeabb90b7e6ae258b6c688ab7ca1ab4ebd7d261bbc24cb35d597a4eb5be0fcffb52d345c739434522514c95e3ae5960aa925dc7654ea36a0fd028f90c3ff8fc3fcf34a829f07d55f7f655f6559d9e9c5659adbd1c8e5e60ee7b6da640b817c759f72abe49a3d44052e0a991f84aef883d3e29f52cce7c45c5d9a68f64d317e1008b9f53eab9b4a2129166c59948732dd27c455f1fd1325fd19f89dac76d3808636b9aa63d6d48d3b6a679cb5ffc999cd843bb9f784a488387a4c0259edb6748e8e9f4d4f88687fc4b1c45846d8a6d1f977d8b4cbe52bab929faabaef843737f91be58137b7cc42622d01351888a556c2a9622e79ae6ad52d4e9f156a96b9a89b72811e22eb5139bfafeaad74af392aed3a2ac92f4a98844b6e98b3ade2ab15884b7fe9dda90b860972b4fecf971b126f6b88b3d1a083c82c55b43c05d3f0a4b44818921208d528673165f7d36cf5fd11002975ebdeed5ab7bdeaa7a09f54067b2fd47fa3e3ca7a3fe836fd2c82506a97bad34f8be0f3fe1188feb02f8ea87efa03fb38f3150faf43f1ba7ce838db77e789939796cfa75524da7ad56f1d13de79c3587b97da0659873cee94dd67c9a2f90afe63b0abe6f6277772f959c54dfdddd7d5ed29230887d5d7d7382d7ace409684e75b7a2e6923e9993fec4b09ce51e305910e042ed8a71d2f0230db3f53257bef211f5f2c3575e0590b9f2dff1e16127880795efeee0289cecd285029e404970b24b4ab3983323c0540bb387787a7f0a850a798b6b89e8146f85a42f3d7e7f47e22d9639634a62f6f8c08c81798b6e8fb98e17e1ad95f707431290de22747ca5f2200782be7db0b0b5b00fc562ae6c584c2bc8f020e3432f1518085a92bba436d18db089db467d445d7a98fa3c3149ff1deab34377a8cfed3acc83a3a8122811448e07a739e88ecf0cb24d2825bd5d77b1a862f18d07563b57c03929928e0a81dae6ca9fa3947e47bbef9b21a7cb1e3677f174b2bc214b222ce3b69de775f6e70ca59ca63e73a553970a9f33e4f68f4da02b86f60c5756421afb97e3388e2381e008bc3dfacf94e764814f617683cf223e8589375b7cff2f4c40dd22dd20f82ae10e3948f400e1c5114ae08942165e7392e28359cc25f82aff39c8029e7c3838374b06431a95ffba4c75445de66c71458f0fbee7adee415d0e01f7caabfcb792a90c08af7c4975ba497a3b0c75f0ea8af83e5c25a451d114832f0a7fcc0dea21e0ee5e14852576a7d241fcee456d3508c04d636038bdb9029fc2c0b2c8ee7eaec027650a93f9cadbe083210e76831aa4b10f0ca94e11b50966093185c18c38919086ea224ec0258cd2a82fe78da5a24013c7711c67e7f4992b1feda614095b38b2e774a1bc6db31675e2288aea80da00c5511d1a011e22407564e80ef77eaf87f7e9751ae2e09bfa38c125b5754e78eb8e366a9bd756951f93efa0c13769942a9e0f071e01ca7c401978047529c0e37c144047cfd37bc6ccc0e1392704ce073c0294dd98ac79a580ad053dcff3bc1ad2a8c4747c87ad02972ab039ab301a7cb14b90b64119a5a5b74530fc45f13654bf14a7d48cfeb360cdf7149471fb4ec187ea328501da6d8ee21b74b0b4384ec8adc32a41a8c07c25e3ab207ee890a9aed18fb41019194f68da8446cff33c6fe6719c8c8c016615442121cff36698fbcfa32bd85381c988429e27230ac9fca80293662425249acee6de67ce5021dc139c116c5c14368e0ace079439146f75a00c94813291c8ebaa8aac650a2ea8b9e087739742d623858c9603cf236c71db3f8fb085908eedaa09b3717b717f8330a5b4a70adbfecf16367defbbbf437386d66a5ff4f4afa779ca3bc4bd4cadf65f447510ee6f503e2fd1cfb04674a7807f972f23a3b3ebed64a2ecaa4b1efb3d1da3b229b8b0adbffd4ef394ff95e460de12e81154367564f408d98fda0fda6388fb717fd404a95122660c6c9780ae200a0926cb08098098e2c724455f65b49e6b8449fa03dd60fbdf1cbe8f8641872877c318b2344a941fb407a7a90f3d017551257c341a44b140f3e9c16d4ec5647910ede1564c7f8263b1448909da17b721afaff33a98bbee36033df817d40502280e02eaa261507288a33d38fd83c6380d83bae81113ca0fda83fa18a9e4097c6a1c154ea0c534525db40ab40bf409be4ff0dd25fd017f56bce76e0fbef27fcfc3d80375c7a3413448c4bddfe6cc4763c27330261010596cff9d1f1595fd955a75a96c90d49b4c2a8bc3f2a957eae7cb94f2db4a1ef7caa746a74194a6c47439106dce7c34b532d2754699a0652176403cd800e9316c37325d0a0e645d0a546792feb5569b7d7f33189102900731a4729b332edbdfa59461b65aa3f257e0f6bd0b29372fc4306bb8670d020973e50f7affddfc565d4e2b3d579100ea1f0f93c651a4a98d3e197d4983ae15dfad775612f77ef3dcdd7aa34c059014820eb4b2da14e809d0a68d3c3b695e04515f4d64c81412793a27eede7b4d469e60bbcb79428d2b2085820a39c1022efd5693982dea93faf9f2f75b9d0961aefc51cf1264e5531a27f52bcfa271786c52bff23863597758be14894e9b2c1bfd71a0ea42e9310ba701e9a07b054cb7d374826e3e7031471df760f6db64f9fe749d09c1b998e448975567675181b039183b68fbd31e26a22f29cd9798334d4ca759b1e9fb3b139307b3d595770b2118e9aa4ee8b46baf500bc8853838d0135cb78aeba8e4f9d2f946a23af3c06ccde93589b9f2f7ef4673d814a7824e0fbc27b0ebb8dff68f0785b7acdffce6378ebbf6620f40127e92ec1138e9103436c46c5117cc152d82ba60b63a24e6ca777c86c44c95123fd58738e1a7726478fcd01e90fa907054a9e7b1513de9472da54aa5542a6f8618e3839f8c19f3f579be6600f37c8d9c873dec75b8a685e28e7e0e7f864cfa2fb33c98577e869cfe41e595f0a766c82aada2da82dfd739d131d15e4f257b7ea8e703eaea6c41414f82bc28aacb93e2091d55793d73e6f660ba3c2b3c5bcfe57ee0feead0a35e1362c74447eb98f07a9a9862ab9c502ddd0e10e817bc9e19d309cd18352476bef8828c1a123b4834d109ed788bf608d5be6fa2e7fb6834d1d3c46c7953cc957b356f8a9d1a422b78794913277aaa2bc6433f2684f71202bfbe0f61b0b0f9aa4b3257feddcc57de2599adce0a7315e42bf756f7335756a83a39e1db943e7cfa61f8247d8343fa0f8707277c306796688f8a969ef441c217352914ffe606277cf0796cbe277d49abe87ce5f13d9b0de9bf9fa4ff3cdb9c79d9fede5075793ade577108d67ce51ca5770b5c7a7bc713aaae193b296f48c68b74643dd525eae9f1e1b407e4a4b34111f21d9d135c4de93d5b256f7dee6364f067e42ffc1999f45ea69b8634f563e4f99aa1ea3e2d68c21c0b9ff4decd5b244fc88be2d9ba9eeaa2de4e0fddd1a13b510449417ac2f60fa550d3a9713a9e77cbde1534f685edcf05cfe6e9cc90866e1959fc3197be7e300f76a1fdee9a7eccf335ca22a0bb66fc52f9f4aaacf2a8ccf2a6bcf257fcd27bb1952ffd5579aa0efc7e54f9588ce563e2871f5bf958e949dfe51af04b2b2a22cb49e5553a753bde373f4c831aa903c3b004729d079248218dada9b0b0b0ac5c2c5868c7719dad20bddefd530ecf366f9e14def574bc1a8df11878322f46ebd5bc187852d45a5a5a5a62e8e87845501a5c4b778648e0871fe47b92c621fdf7a1c6e1b12169554df82a559027e9c709358914861f3e4ee9493f5fe0cf9727e40d8974c0124956caf3853d995784902d949d10dda1410dfc1933cc906738ed9f864943ad068d1a6a5879badba28690a613d2f9a9a29f1e5b8f6d62d103604477baa01d9d1d1def87f6fcec04edec04d560be18d0060813dab71178741a65c264466595c49bd35489afb610b7daf31f0b856fd2701effbb05f6f1c3c3781cffe70fde1ca5f4c8a679ffcc1972d3f731672a15261534abe6e7eca94bfac37dfb5ca63a99ca9c1e3182f1887f5c594ce9cafaeafa25c237694ccefbbefb20a3e7340e87c363c3fde871baff9ecbaa9aaee3381d5cbb8d531cc21aefbf8969a535b1cf27ada4f7baacaadfbde88370ef691cefb917691c1e1befb9c7117df7f3653197bfdc55d2f6a033e0ab7973b743cc39e7c8a3ba7c4cf28723c05b6ee3adeeb197e704e78aaee8fc9179bcadf68108b87db8f170b8b19ef7ba7e8da0b63e0264bce25aa9189cd86c50f81a90f3b23f6990f365d35fcd1952398d500600bc4159469ee92bfad2a924a51f05298f4d67edfe0cd2a92e22744887ba1669538b4ac01cb34f439a158c8cef58dd80efc32be8f5cbe06be6a3baf48cba4f9a386b913615996cfa53d4a92e8c278b07a2acaa198d5441447fb3c0a0afc4a9aacf63d63a5fc71537250081c9a66fc30f6f4d253851c5a66f23841af1f2233c810bfb93616197d32748936c1ace9f61cd7d1fbeca467c453fc6fdf5be63c07cd917757c45657cd454528877f37cd95525a928d36211bea27fa1e0f9a5a823f68872aa834ef81efee5a97ec9ed5935114a72cfe94963acbed1dc6d6a6f34179998d274f08dc81ba9ae4a7f388efb0e0b4ca47b82a7b5deeabcd5651f627f36a42989b4cde86fc01f85aa9a12f83314fd8dfdd283fa464829abba37f21a6555a76b7ac880afb8cfc32ee321f657c12e8f86d89f05bbec3afbbb6097bded0db1bfce2389bafd897207fee82100fe48ab3c087caff2b40ac8e84b6f33fa92bee1f1fe8614ea9bb0cbd78703d0ed75998a322722429b6451cde87798af91c6e1f11ec7fe48e3d42f751bbf8d7dacb177f77bdaa67ee9b96c4487eec0406e721cc7d91fbd8dfd91567536f5559d1e7dc5fd7c7d25b98771443811c8fa280b4f24ca73e29a63bd2ea167dbf7e6cbcaa8f0a82f7e107f152d6a92107fafc6d6ff1e5f2b8084b88e51a0236cb03d6d6dd59f166d5babfb93340e0f0efefa20dda55f797b9f747b00aae101c87bd17f231fbeb205f831ba5be01a9999cc4e4bcaf4534886ea6bc1334cb9f438affc27535d250f999a4eaf469a06d0d758fb170a56d28d443948059283f8933e991afb9f3f8ef8f5491947e57df4dd5f19d9f43332fe1932cf9d417565905ec607097f860c8dc363a3f2e1e3883540dfdff7e19e4a56895e7c153ac318affa11e9ab98559e0e5536e1fb9f3e353e299b3eccf86fae897559355f748f1f8ba13e66fad2c74e1fc3bf9203c3a731539d92092563a9e1a1034886c64a8f1d14556e0d0fe1bce90092e911397ef2b32d4e8cf7affe3832be5e1931ded23dc3884d884c0706dabca7b112d24375893d3c6829fce5bccd21962f258e3caa8bd27a7e78fc08c1a0cd1392811e6cf63d1e42ec7b33324fe93f0ae20cbe88c36313e3c3c791f1a45fc938313efc61f42ad18cab05a63c4ca01a1b6f91b69d51b6751ed5f595b46f7fbe7f783db0f49d10db7dd17d1158fa19aabe25487dd207f10fff2b65d5fdd2e7bcc0acbafaef7df1677cceeb9b53bcaffa78dcefbb6fa4bac69b901eec0f29e22d5a04ddb1b8f6d8b611829062ff1b5d1e36a880e007df068f7e86be91a155f7eb48db885fd23731b44aa481d427bdea6a9bfa24958d7ff8fee18baa7cfa9654463d29b37c9857dec358248558fc4f5c31a132ddc12ca7998a904ada985883ad904ada2fe51e8c80301f36d878cc97ff782e4661e3ea319e499f93992cdc7576d695adef96d357db256a7deb796b522c6e1f8ebd0ad3fa0df6eb4f276b6671d2ead5585def37e8bc0e77d9e77ee5ad1f7e28e2ed2218c65df5b9ff6eb7c47e1177591de3e95e08ef659ffb9a6342ac5ef575c697d5e1f1b22f84f7aa5fce299ba3b1ec6d9be9ab4efba40f523fac4faa8f437afbd375382ae6ccfd70462925899694de87833edcb3bb97741127b9f7e14438d9884699f4741e0ddf88a04c628b8ae584c22631a71ee7fc1f913944640ed19d2332254470e795b28f4a725f0077f1f890f50f2a91e6febbe00d699efe704fa1f016c95b1cc711f13047e33c6ac40b680c4772a48c0bd853f967a812adbc0fa7544c16f734d327d018ee6ba65538f9c4498fa9bee53daf89e1176b6250f06681f3d35025d235a595cf59c848a5632cdfa26b622d9fa9cad7d4889d1e7fce319617a70834675e9e06712ff315478ff88adbf11ddcc7784622ee2950cb7393e338db737468d3f84fe7f95265554e7d3b95e49e9b6dee695ccfe6449ad6469a42c151205f71df71404a462da2963cca3ef315f7a2ef450fd648bdcad3f0fb2e83ba86aafb1a7ebe72ce5fe383fcd7f05fe31f8764cb948a49725f691636f7940a9beb389a0eebf938370b9854b9ef9880bbfd83dd34a351a6f134fca75540489f3f48f8ff5e75d5f8d1e83f2e5401c1188be28f728db7297d0d7dc3f3fd8db659f91af44df82b3fcae5b46d8e4696f134e4183f431e5fe7199fb3ea3fb77c27e3551f8bf12d2fcaaa9ad4ef305fa90fa2f2a221e7f912e5b9df1b7fc6c762323ea6fad4c7627cace55566c83495961833522a1963a63d94090d3ff735d5253ef7dc0ba9ae95af419d9e05afac882c990eb94ee964e24e3807e6aaee4b6f3fcc2a20a5b7afeab44d49db277d7d950de9ebe30f4b8fa3ea3efcf9c21fa4f4e28b1a87a449a16679168d237e58b9a74195e4be94a95025b90f331daa24c73d7e92c33647812ac919f115f79d2ee22b8ee3fea360cc7e7d959eceff094948c18f18b68055ebd5da4bc5376994a2ddf62b0f9e2f95e8553674c7f839f16dcebccc99b9536f7f56ec2bdbe9e0e13becc778aef7b26fa4ba4c25fdf951496badb57496e74b866ae54775511ffbe504fa6127d0b6442a693f06115fd9b7457c655f887f19f11d3728684d786b3c8d0019397c53069f85f431622d9ffa6187f98ab1bcea55a29637e5d453704e574c089957f83af8557f3e385dfef3e9ec31026f04e3a67a49fdb2eef99e4127ed7bd5daffdc7bf0969d362196b4edb66fc4d2d8b6f6e98fea92a9a4b5323232a3d4aa8592f65d6f5b63dba723177c5089744d4bea3b1f26cbfe10c6188808613aa223fa9f0d55352d2da9f7b0fbd1f82c1f43bd4a87c9b22fca3cf8ca7ecd06a0a4fd704a61dbf9846d7f4c96fd8e09f8b6bce979487d8cbf35323e9571fcc16fc938a96fb1446298ae16300f1d32db7e2af388be25e3d40fbd6d7a96b7313d4b7dd35f6dc3f22a7de3cff23edcd492c34f65b07ef836f5c307f73766f15119ff4afefe9455de944bcf924931fca4efc09a582c05aff2b198f8b1d2871fc31f233df83f7c65df4825ed93ece34c772a695f25535a25ed877956fb25d9aef6bf6cc58f48256d8d4680afacfd0b05d3968b454dacbebf5dc9e95cc4c29cf327497f7e97e7dc56cb4c16fded0391fddba98c45f27345e36560f60faf30db61bc451f570a2bc313f3e6c52ebd09645de0eeeeeeeeeeeeee4eab53777fbf5ee9cf09f3fe5d9eaf6b5f5e9e93f436ad3586073671842e940c1d1952423fead5eec07dd22869dc7611f7fb940a5d283ee4ab28be1251cfa3eeee2fca4358b6fb9502f6ec1b0809d894c13e02e79c09f77c1b181a43707769c8e60c6b572bb3b2ea3a9db4ebef9ba12897d63d91f7448a18b9b1ee5e9edb661f8cecfb9e4bbcbb5de66c1f3ad59293873414bbff98db7511dff776f7612bfa042bbfa28358f96f257f34d4309eae7bd743eabece8d328b8ce5887b222eaa4dd727a25c833c5728373cfa2d5ecc748f234c248295456e15f2d5e32ae4abfac457b5d62260faa5f730870a458bc0d0e32dd2d76771c25bf4ebb3f8788b646595ac6fefb8410a529086b2ea1ae9d2e37489455a36ca55a86ee1ab89bdff4a212c477cb5e33bea8bbec0a2c4577526f2022e59642c4cbc555de3577bbf7e75a44ddabb65ee7dd41ff38f216030c9b951f9c710484c726eb1c43817b99bf435a8ba58645be0e9ab591b0206bba4cb0a65d72f2181555e0c23164bd1f69ed6f73c7fd274fd03dde5b8a92e723729d463a5c3a8742c1557554f32866604000480007314002020100a8743e201894822489aee0314000c7d9c5470549e89a320c77114840c42c620620821003020223233630100abdbe60593963e1b286c0b0eea850dc4cc3b210962eaf75b63a5a6258c86e03bb094183f3ed14dbce4964bd23e1649e2c5e8d158a6f10268b68b7f3b3f81f93e17a62112a0e20180c8aa1cb92c8cb8c43c20f45ee6f3ab956727fd6a0ec581e4129fe20f006dacd6ef84ca5942278f3c6a1963e3649332d8d2575bf01e9281cc780b2391e8afa1721ffa8c026af3201a129c211651b71b06e5711477515fd05203756de098195e34154c17a7773c4678e2c49bbd08b83547580600142018b87c642b307d4fdf1e720aaa2d1bd583cd4895cc4056d0db2a06339bfb43f62c9c3152d6cfee3dcf0aa09f87c295ff6a3fa353b68cd7bb62c38ed206a037ad163bb7b28398358daebc7b6163b20930294e82841e40238a2e63f03c3ea4c5175407344c8b604564869ce4640539fe1238d2422c678bfc2fc22bd08459af01a044b98bdaa0eee8b091449b5c23fee7259d4b9f5188f45c231335f5aa5c63272b81a24a6e136d7560a06f04820a54dde1b2b55f9ab694037e966ea92f9231b46726ea31107ff2f759ccb79b060a44cb4a31b50794fe38810647159105333b538395858c7845be61172548ee776d74577f487406e11c6684f75adb8fcdac0e45944a91a17a2a996fd10d2edffd6e0c7fbf2d30ab014c92fa4b1b1d86590243809d417ecc82be97e13588750c3679de8a451d4525c053f4a6d0a2039fd30249ddc2e511a93431a99ef007da3445470518fd5f6654712cb5f03a039e2f41affa1623197ab2051e9395d700f63e11f34679579cd4e4cc3822063c9208c01cff549d55fdb50c262c00a7a5e92e0f00b611809c1600a40a00171b833b447da7ff9e378275327b571dc6cfa73d009b2aabaf2f32a7ccb345d8b4e2e5994b8d3b42baff35ddc73f3624cd9fc00a339e9f0e2f939067fb99c83556848a2f071cefaef489418b36c3b85c20a1d7cdf87a9fae7a70f498d1fecfe2aa0311395c68b862adfd0f6ed9b919bcc18ba3107379a8a84b4c06020ca0e0e22e230d05f024d56fbb73e53a2de3f8ed4014a95c36dda28830b278766e575a1c8daae9701ba1152ad02a4bdf4c2a525db6f05efe434019bf06cc30c22c1474f6b06723ec3b2db76420013e18fa48d8156813a62e081628a6846acc3c8e9af165ab4645199f49cb0a0b6393460fac0db6434396a8e2716c890d1622de3c2a6a982a1e6a27403265d6513b7d6295ac98cdd23f9b7d1fcbd5ae07b07396a7d3cd26c70e1a84d9c875132df42b9cc6ae8d2bff019a97a78648c641b15a862f08d4c795b8fdfb7ded58c6bb1db8e39a9d94392784853efb47e5b695861b0819f964b842c0b15888c09d94abd7dd5aec51064f5fd64d7948c08406c31dd196f62b541a31546da8572bf05428ecf51e300e71a3ff53d243bbc05a4eddb45cda3504e45a52539ae724c381dfd5db13e51005ee8de267d9b3842a6c6b2c378302cf56b254c040473e52eb7d5e49ad65307e1335f8e407a1ec86beedb467955e95ab352367dd3d69582f8905ae7215768bc25d50c77a8a9e3498932a27269ae452d6cc37cffdc538e701b7ca8fb4feca4098ad44a0ba5e2fbbbaa59433e6b5c961896b19e5ce0eb16b4fc6f641031853c7be06f5a7e255d7a211339244250c74ce1ca51bba434d74374fe9f7383f40baf9f0cecc9f188b091ed37379a43190c1799a5bfa259b16d39477dafaed330644e880b66d07d178bd0d45731ec0c9d2797122ca216e931d12053b5bfdad62ffbf7accc088988976fe93afa8a18e7bc25cc88a10a66b6e79e921e066fb9327073179094e2da88c515eed17f85a0317601fbd8d6c38792937a5eca3389e1102e84d7d3bbaa7682205eddd9f3ec6ee3eeb2c8f5777aa16bb027ffefca1410442b95700e4c68fdfb4635d89a0294b8c7a0dbd0a102efe34490627cc6df954459c777bdbfc7fd2f9aab495de757d672dad447dfa83f08ddf9524b8e0889028aa3a8b8184ca25975624b83f1ed7e5aaeae381c45adb87376558fe39a295d38c7a1b4f085de9f5d093b3b79928fb556261c4925ad094cb40ae258e98722a6cc4b7da8c43e0a19111f73d6d95cc94038586ebc3809f68a6f6cc4476b91605cb7f0c673e7f632d6c85a9b1124c8d31bdf7a9698804720bda008f02b8389dcdbe998ebd8115af202d0fc589df0caddb3c096c3e07e02ee7208e91ff9dbad4241f940d3b7858e58903804d594173ed5ed8adc2714783e381811b5b7eed8628b5492c2b2a35441dceb38beb4098aa0b2e4254f1086057cb57a125fde81e280ef9a8a71c1fb2f14571fbddfc01c6f40a34d60fb233055c71d0cfc5e3a36726ac33fa9d34bc38bd5c5152dc447570c8eb26c89bd68da263733900c9d842875120276aabf873807a1439b43f1bf8e9164d92a1f020a5121cbc6b7ddb60c7229989ee88f7768764492b021e86059f43ab365b530b6bd4f821a4686ef333793347db5c796f34b5ca021ceac3dadd0b0ce303505bf4fbded6eba67fe47947b9368e4f72ccabad1022ba3651d3e87343b40c5c164a0b45cb4cb2c6922c32fc33cddf939e7af1174d7cadb2b86e32e1f782bffb33c768e71f43a0a6552c04236190ca6ca0e4ce0c4b7e436be087977fcaf1e68a7e63b555faa8492dfde3cb3a074d53f1c8d712a6431d5a65b0cd9df2e2c05f1a9368176c9e11fccbdce4b0f653dd74e8f3d0cebf218949038e095a2d53852ae79537321f9e2227b7ce391d490cd948b113a1ab216cde9f8ad5a94efdedb8b1be80153609cc05501880121816385272d2c59f2c635299122adcbb6116cc40ae63a8aed27dd7da66fc8157c7ea377310c914d6d646d0dd3c6e0951a07a15bd410f24e852c82896b5ed14e3b09fc51643749ceb92a4567b93a81b1fe59b4363f5195f1433c6b0e97c56c56d4b324f1cd65b056378d293c6dc929514d272ca98596d6597973867f7636e5dcd9f17e3b1751f2b96d5abf617fdf631b381d892eab07097ef605c92f35378aed6693486a4c7ac1e85fa83fed3af38d230ab041499b9854978d778217371a1dae54f8e0c621b04d8cebee1e387e138804062ded057b375ab8d673aecb3d095f1295db4911b1845be48704eea8e5d93d257b2460d80b9039c6190844882b3de4eb320a459e069a13cfa88dd6c5c15368085398cad734bb81793d2b8a69a716c71f6ad9b75e1fc5afa89cdd8554345a368b6204a0c578a957149f0bfbb5cd7e12823b3163b77e839d5d8af3b66fd72ba707e65cbe86bc95beb47aec33becb8e929e0f8b6eda50e4791748f301a76d49833cb3f82862ceda999614035f7daa11773fd3c0b33dbdfebf4921dc84f7e456a4625ecc8e0cbeecb8d8409279d56edcc9b3806dd7bfa3063b30207fdceca64d4534b83c6b82d95a9b35a489a67b655be04bc4a9b34601a64abe1b59d27efd05c5dc2b4ea08ef64969ca717dbc77d166ded22c078da35c86f52f2bf9a96da2debdd98295c0bfe200559dfebde2c0a287346ad496fefdc745617faf9a827617bdf0e6c41b86c04a1b980796855d199e66cbfae91ab03f1ba6b8fed62365367b3888ddb9b8df1aeb9ea1757397ab419b5f4e4dcde6bb0c4e3eee0448864120b83379b1e640f8e6bddf8e1d2a4988677dc808c95039f154926b878656c60f1e76dbbe6b4db730b478afee651fb4b03a6bfe35b592eeec3266f94b9ed8211aa1a5b38db91c4de42259906f9387cdded3b29fe39622f5c1f38dac51de1b1b2458b7308cdcb5209ffc1a73d9b1a9549de9285366e4dbada238811090657e40d26174df47981b8b1a9f220d680f6c326ddcc4204c7f0cd8eed22b82efc61c6c21162c68fe1f56a4eba3c4489fa59ad8a0735fa10af82c4a172a7b2f776e4e9aedd201e0b09a9f06b6811b414ce5ecdc51301bb1a786b752bae1e509829002544466a13b6c985796d2dd9737bc91bfdbcdf17504b463a6d168d7b0865867a54364bd32a56b15c36862c4e72f4ca8c45ca45fc9d689091697592eef806c1b5cf50824d331bf8e5a1fb70ea9b1ac15ab05184e8c1e076adc9d5256e69280fd86a1a06f8e724a5790685c204498f47e8cb2086b5d339c12c39e2bd2e0235c083a5c2f4ab4be06e7ad8b0773c94c6d54061448b9722cbb3c06b007a2a2ce240e550af632d4486aa52b3552346a714b6bc251011a47673c74a06bcf2daa52463d466ac4aa53ec99c85874c88d180370b738b5d538019f9162bd2d1a7c72d684d58b7c9b971e1c3511c61837f9bd12e18132125810a31012b62962f957a4706ef9dfd88bedadf708fb9a90692a232c22fa0efef23fedddfc3de38e938843ee8a476ff7c9ac93f6e8ca9d04467bcabf5e022488335a97731b09eee8bbfed054ee9f256e9a1730957127bc3087e08066e4f9f5174fee578c1286273b93d4066b96f7fd3699a280dbf57eddab6a5a0d8e985e778f5b62e2b0a4bb70f2bbac8bb434e854573b8914aa8fdcba7bf5a9660201e72343d29d9f08b807eaa801048adfc688f66bcf4ee207526b5238fcaf7ad8adbae5477227737d0621911b2800a4c5c1ae82b8753078cf53da68924bab8bac97165e8c5bd5ea94cda4262050e0a1620bdf0248b54b6b4aca7ce132a88776fc7fd4e7871543a5fc41f6c48760ca4a3bd2f56ea3e41f8a34a795411d2cc6dd1a9d6cc3b5e2b898aba7e5633c2ae0e51f1b7947fa4e4975d3d17aefc9cee86eadd8144fb4877798d6d425b2c64fd4ace74e2b1826b24187c09d247dfbce6c53ea45ec3d8f5ed95994632ff17ceab0998b041662844ef688ceb6bff2a4e4589d875fc7d9d4efc067c425cda8c2a319122d48dc47393761062fa0cfbcb7d1428cc222913b979437b1596f08960fbdabb6500b4e85f3efd5a139de78039d252c1e7ada44a9d5b7278b2d40298542526cc37a4d5f7ca54bf169892dec94642d91a04b02b720e203485377e321d7a8a7886d015dc98ed77c169e6cbf4c83f98812072c34046434a17b9c84105d991d1f947728a92ac3ffb9bc44ffb94048b2ef8023f7dd314263e3a85f862e33291534e401ccbe0becc9c47465b9f872f7511d092a63627de27d0f632d73597ec969e671937fa78603b30aff253bbabf8cb08ab9c441ad9a07a7119fce8b4bf61a5294cd91fbf8cc01ec927b55762bc09bc7fc36e3859da224939c497502b5349cd3dbcb80cc9e8e3dcf3298c490736b779706231523ef41796fcb91f9643b867ae661b2b455113833d41ddc4708e0e8d3d9b9a755b4d6095ba8ccc2182cb13d8262309d7f47d10a23509b5f2db87580596578e87956e445bb8dc8a31c8606a4c3932f4f50dcf4af51c9ce39c31acfea1c11a7e0688304b0ce4ac0b7be33b07f90dff187733ccd164079c7202f3491173ec4f2daae9b7251311a46e2231f225de94431473d99c688eda42b9d3d5e7502c28ff3b100b98d1caef74326459d2064f6e7c090bebc6ecde61086bcedbd2f254a6fb7b1bc469be052164e980428b586d49e482d79efb94c39dafda37085604647621f8a972ecf920e8aa6686ca0b2b76b11cb2d841cf5560d46452a5e4d156555ff596e3d5bdcd4a1849b69491beb2cc7d24e6f8f55e3ebbcb1c0dcbcc3119076aa754a3ddee6ff053ec1b08539f6d2ba4cbef0c2588b7a3f5a3edcba6f5e721e16037d0726ea9758e72257fb79487e21faddeaa630a89f53b51dd6b18c54eb359f809f0cd553e2788681e48b1e95a2423c275e84c18c66144bff8abc2b6aef6970c7271e2be3bc2289be0b7f381935c7ef21d64e99162e57bf7639be62904e673c3e94a697c8a1cc706ca51d47454d5d4f0d139fa95a6a322634b589151463a1f3320225f5e4fb843c02a4a712be3bdd65459d560e9bdb66101d992aecb240a740e5703ccabc6de8e037705917e7722ae4ca42e5db199933515572a1d50f00908930d462d094fc8a1e0dcc9b63e4b1423835c3eeca7fc1fe380684c44aa709999e46b78acca0f87789fda2221032f2719245dfc4b59240e05ddee0f508175132ea9417e2d58285479be7513c8477ae99842ff8762984964c1525df76f94fa478afd9806a67352e4636c1da58e235a67efc638908622e1b57d4dffd9ef3e98ccc7c79a57e8053401b6c34854c85305223ba3b60b744071d054009c31938e611a65f465496717a6b782eecbe7302c8b5b5db4c2b4d911f812762ec6dbcb768cdabb071f17cd34f33b08e60d7a9c6394d851dc0a6d3c0526bc41c770c2e8615c562abcc5ef2745e89305fc31fd6aca05f4fd65e5c3d6df8ffb2bcdf0972e44b7b30174d9e74b80df5fa52e757e24c29148e62623f34c5e3d74991d79f9e34d0986c95893cfcaa24c940ed7bd2fbd0b58bf65233a670a90d607058e815df9fe4f4ccbf736b898ef6f248ee5331061c7a1a7e329f3d39795e1f0fc0890826ffade67e7d1fb9584c5fa4f6e713c5647f384f9393704603dc6e05fd59870da7130c70f81147f126ca7bec9b5d07fbadafef3184eb48962b49eac3f9b7fd1022a9362937badacd5eb78d3d95c281552d8da5bad7757c9f1e83e8edced7867f093af7d35f2a259926c673879157866d430a388f685b7459bac2401dfc69a26c35c7c766f42013dc52108144ef55f3ad6b056b183879eb343225bcd38d6d59cd8bde4d50870064da4f64162edd79b25b80c184d4b755bd0a9506825b970513d153ccf36f365463df87af02c5dbcd35484694a4902123cfd965eef0938d8716de170c4ae14fb4524c8647706e8249b6b861721d2f0ee2a1e5c53c0c83780e6826132cd4e18ef842a08259d3e96145d86b9e20970b7bb2434cbd1e08f14955fc9bc78306ef6b4853513b170a6f967eecc2be31270ba90b1ac1ff5c8d0ef4ff9d072c412554e8817ab1eec6d5e1a024606a93c8b15df0fb23265e4d360b57f86bf8705ba87107198a748a6a74415e892bc021196e261becf802a0d9a43b89f155d939d237b9e2f61e3a0464f723a3baf6917a34425c47e9aed6d0e58040ebc8a0559e4624d12ca4364f11a72535509b04ae6345ab512d5cb68e9fe551bb48c6576ea817295192d6f4d22481338fb16539bf5675426d69e6524cf0153d119ab9060a5fee104f8f506c2154ca29fc88efe13261156facba9a5d537d16d9110dcb61ebd12c16d01ffeb28c4b0018e8d12d3245585579c69e33d4a23cda4b6ef21689543c1caabe0ff5a8f0304b0c1bb5f7a24c1be6f6b68aeac612884254049ec5fa49d3090c8d366bed098160322b04bb72a0573466f16f6029af7bb1ba4a20c6e05d125b55a5e5f17ba39ebb415550066c76ec9f3a31e81a58b24e12af9aedb314203267afe9e4bd3f845756d2cd574933e2ef2d654f707eb261473dce5bdb2725489e0101348bb8d5bf1589a92eab2384cba549ee7b8ae8c23bfde25eeb56d35f3144a16dc489d6085d25583bdf73f0b2139205b00e373599dfc79f6fbb0b9502b5ef9323344f6954c5db485ffd934cbd32604c982a7d86e4614af25a1da7f87c4ce3e056a39f656385f75894fd7b9ffd832e54be3d04457941212f14c8dd3020cbe48dc1aee7ce8fc4287dca07993dca75f4013be0ceda7d02bc8d71458494e92ea10e73c0b97b0240e151b326eb10e1deb7a11ebdce3b7f0ef38597dbcc2cf21faedd17cd9fd9ba54d73ceec0618cb401fb22b3f846ba16e3f990d4e9b1091e818ddf0fe3f33fc7eccd6b8a39e3710a877b96ba48021e051bad91ad4476d5feacc9fa07bf6e202030b2497f2c619cc44996b02050def4b16e9a664ac62bb65fa23de912c72ab1b09d24353b97a8930ea72468d4251c6feb4598d0ff225a918090096f0f69af95e9cd58c29ec7cf56591897b0bcd54a5620406211c9d4dab238bc9b6dd83b04368105e536ac42995ab562608629308d223d71741b66584403af4bb55131c58ea05105bb59aeac7dd87c979f4dabc4abe8d6720abea85c185a90b41746d59b7402dbca1efca355645e180b1330c51792d717a3b958bb6e842a2d6dad6bd4bd7777b817c09f30acca7f9654b4ed074bccff34964cb21aab13b2230c7c589045f42766948123f4b1df223ea5779c355311fb4fd18cc27cd05699cd78d5867e8638eee685f94a6abc1728b2752610e1c5f48fffb2616753ad3a87883b075830d322bc8af27f08df8000be0b0886b76d53f67c48735b8f4244cc944f94b0d9ad1f89557d505b30643f5f2fcd53d20b77ac78c09e7c75db38bac2be1c841501cfbab4513278dbe3ff7844a65e2300046cbbfb11a5c0c8cf6bd920c57222630debc287286064c79308023a88accd49036a388e52853301ace6a3d48d62e8e8e62fd6ff5c65b037dc47075ef623499b1561f6f53d8895193660ec23ebd245fd9ad62975a288b75435ede1788e305141aded07022a9190296ab432041ef516f30495d4a3ae015ef022145d5aafab9716ca632667b56d107a40ac83aa2d144545ae73be5d5981460162e3d43462a761f5774a274b95e5e3a877028af10b7dfdd94c3d7eb540a96e0ebc50af87a3535de37219bd08841617403a0819202d5ea16c3446ad64d4cdfe61204f0dc1b90e8fd3e75a76de12b86f28ca7a3f5326f8418e929c28bea577cd2faeb3481f08165aa9297229bb56e714d7dce96e84603ce59348965a4d5d4c55741a7aebec6182c1cc64ea0a7756266ef7aee2c12a3fc85c9e7d61b9cc1d20fe730ae4587719a981633ab265b656f3d95bd8e68f7a8d9cfe889c622aeeb5fd52cf27945f71704cde29d49d2a69d15b9ba3eef8765c49f8b90986869516dc15fbd032e634e6d74f9212cc6bffe1cb1bdec52d6ec5247fdfa419c7cd57e8c2e8e2f7b501370c41f780742d457b20b618471a998e4e78623ef30a4683597375eaf08b21c2338144f6399003693d313691d448454340b90da757823fa719126cdf832f92461961f629ff70822115a273542a776fcd82aecf6602571016cd570b8058b01cc384e98821b08727aebc94dbf54422556a13a90b7e79affe2981b60e2fafd60463cf86387b5e9ed61149d6f7188084d29cf24ad22cec97e3a3f855bfe6f33118eb03b28172d90ca59709183eba52a2fcb350ba001ccef53b9e76dfdbaaa50873dee21da21fbccb0975e9e1be8eacb68710812fe0b81cf3f0463bc68976bf0fe9bb6d5bfa112faf7061082f84149534f9eeee2be0916d281c434dea70eb28c484c8b64578e9678517cc49d07514ae31ea1d127d7c0a2340610e2b11a1efc516d6d2fd58569f9ae4d9db3310fc4a05d120906f0f9bf94945228583e37766cc7b04e29a4c39af8a8680d4699bf5208b919f3071098887eea5dc31ac35bc69c1c9a868a3728924e8b1afa30b3cf327e5421a2295dc898b6a194cda766724bba4f2ab60ee8578c3998218ab6ac552bc0964b75838dae02cdc6d828ea3000f0facca062673fdf6c95f1dde9417f0a2bce89fbe84f73564912bd89f455eaed43bb053d42b73904c26bd6121e4c8a72d2e3d647e945803288bb22595cf51a6713b7e99686107de7ec563d17f4f8ed0debb06eeb594e3132d08546c017087a437ef831bc9ada4a339cc7027af0f2e32f9dc01e5c18afcd259e73540e03d35347608a701abdfd55cdba3f3ed1e6d6477fd4291cefc199af0fcfe0ee20229a8564444589024db82387db87dd9f47628bc5653dbb4127ac04919070b949f61470b8c58b35bc9c1fa8ce308fbb373d5f50cf39189b0516d5a9bbb2621fa3f16dd0afc03c486b5c129023a7c07e740d81654745b062348fe9acd69d39a732aacace96c6d0f98038a08cc219ce370ccd7e4e7406ed2fe2e55e3b570a787f0bb4b3472deb426c817303585231d10137fd1ff563e7c27ae0684265424443253ab0b4500be0b0b10648c69c910c3b749222dda1accdf862ab2d67cfd5ea013334273cd8175b380d8c5ec02300441e0c191a6c8047601fc4fb538d341b35124bd27d9d3640fd7ee89e6bc9d03f7e7d8f366f19f5504d5c1def0d69e04bf7f4bfb3a8bfc72981b06c3c4b6ba32d76765dafeee260dffe562dc30ab9cee17f0bd63b53ea032f6796fc4b8fc5a5457c4554df4f5b2c64e878b1004e840a50efc54bc1dc528d82f524ba07dca46e8944c54d86815be82583eeade06c71a97b2ef743689a5e85cbe1080edf5dd9a910c59b2efbd583cd7b0718c0553af60d6f2aab3c4c24d60a398914622d741ac54793326e2b70fb51a52039951b856e71bfc925c2a960d1ec654dd38d97eb7e05a95d2be13386745ba5d1f59e78b9646a9357339f578783b32907bf2aa861c57a254419df58dc38df7d295a77e47c38e4887046de5c42c08565b15be21ee595017abfbce6656394b4eac244f865bed896f555dc67686be936b10828a6c2afa5a4ed23d8297d88afe04d9d494512f6308e5302e494933d97bc316e294a7661155f20db996a43a653efe20fca1cf5a3d2bc32de2addac5845488dbc3df4a571f599e081116127f4d77eb26c9c10f4a60408feced765f29558552332d0103f140205555096df123c5d8e16fc38f0c1fc3c2de481081eab170826fd70e1aa267895143828cd59bfc8dda87e841ca5752eb81f8723088b2979a106fb934ff74f2e5b880641c7389d6a2c996eefe865b80cf2a86248495b12e57a94d21576acc7b0b84779d0ee8ff3cbbc419cf735637a90f0356ef88c8d043f677b1ad569e03778bb27dcecc9d8765a7416c8f7cc103c53b3268592ce8c2c6b0d891fb5244acc7d4cca9b29296e36456dd888f0c6c14e6e2566ca2f3362c453e1e6845ee980f6f3808f74d22ea1ed1f9657984f53c4330b08e8b9affdb9c4c276a04f70e2e46c6ac9a1463b27758895156eabcd2e65792b685941b8dc62f1e53c9a86806f2642a04381017e4db918d367f30c94f60830c2dd984501f11eed5becbe332d146051b5ec660e62939404966646bfa2c9c185064fe07d24a8e83df4d14cdb62fe6c2246b78dc5c301a09fc7d0a540d82a485690d5421ab72fcb0950e9ed8147b093f2b519410a3605c14362b8bcccbaf43919b8af2b501ca78194b986dc25f081c4c4f887902aef4e2f776a03072d05561810d540646124370947b1fe895e4fd0d61a8469af4da947957a43334bd52c30d6918e5cebcccd4bf82514666dc3a280805d9abfb702b2e36397a676fd11a313571f3937f30ad57f59c8c2d532d721c02cd4f9be50d6dd79bf20f2343ae265ff031d2db056ac3b359bb7cd2d1efeee7b502b25390527513c000aac2e09bcd9a03736ad40fc9c9a09c1009ed5c3b2c07f54b44dcd87dfec5e85cc3ccdd6306e79d81567279c0c9f753a57de4115d58809fed25cb54e016a883fb3ab5a15e78450959f7ccef94745d3b800f01b7ce3f338373dccd44aacac3ace7c4a622817a51ce69843416d755240c4a0c4cf08acf9bf8180f532682de4abad3a03a1649c6cc7c15665bd789544d591d463385adbadd45b2a12914287c78cf4157f2343dae548c30ff3c313e8154375c91533483c5e0a6ecc8c2fc8be7794b9b227fb1969c0ddecc31befd3efdeec29b1b668704f61c4b290813f248d278e4dd6e4187db33b3088d2a0cbbb878775fc6fae2cf44250ce5880bec9288fb99302edfda6a219d7680ae12e7bba9bfc09c41defdd6da47178c0ebc1736eb5ed4556825f7d4e20bf4940b72a219a8e7b4ec9c14375d8c3bf173c584f3bb463624fe8bc8ec52ccb63c5cf411aa6b53893734b18832ecc7686bd4f58ea4280f5f1bc6c79e81613bd91bd682c5eb54be5c6bc1b2bdedf425aaebed2d6f380364d1b0265d53023c6e3b6ce19860edd52c46e5c79706e6d988337d334f3cc244c93e9fc5904157128704303a086e51e083344eb91add7425acd3413dc38f062c5a25ba8ab9ea3517a5ef56ea5c11699c8f0b6dffa3c68fef378ce7b96341cabf23e9adb7e371245ceb34f2d7b0e21c425767874d528e657d47dee58d8362acb7a5882fa29f28354572c2adc8be32f7412a00c7240099b73590aa0d8d33457ea7ec7be301e17fd61f706ea441fd88ecfa74c9c2c104c346f96b4c81e5ab026cff28088144b1991e379207a96011caa27134287a477fc785bc4e5edf14bfde7bb32e82ab525b9a8d0845123618e09343b6b2cef0345f7db3db65a1835b416399f01c94f1e539e7e5fcb5f2b9c4074350abc09eff0b8113016edde1da08afeb93fabce2ec329f2e2ba388a0bd13da82dc6dfadb4884698a1c7703b3ec581074f0f3f9ae138b661626bc8f1811d31a21949be11fcd4ac948dec1ecdba4e2c708a52bbb2295136f3e3e36b81ce4f729c10af63a5ade76e6c655e240acfb075b647ed6d92548a5ee9b53910b11939c64a759fce3f4037f675a384881c1a655721eafdbdb4f283d814b585e497ee70220b1be745fdf26361164c316b47548e0d2c927c9fab36a2fe4620783d5b82170b9f5dcdc6aba062acf2ea2a7bfa900496e2b5b0e7df29a86c5dbbda2373d07c2abd0363198b86fa1cce5d93653c0e50eec44ec304da8cbab796c8881db30bbe7b397bba70475c44095276aaa5908e06c18c87772d27fc28e7d47862863dcbacbffd693d86b3d029982a0fe1d0d8ee85c5d5015a815ecfd95fc750566019b0fd666fde71611d1c63629c124a7dd41cc48cbf20ebf387944a209eb6d15fe97e0640c4a6b2d82f18a9cd0d77e08b0d840ef8970d982641b94203dc0544da7733a004a232fab61d8781a405317b8dd9182a36a035170e759c72201ddac0a187989e18b74c1a8e6cf4bc25863b5856f6c910831e301e4ee4ec7e08ddff99509b6f9c963571bbe986e763b4727c0bf7504db088b35d3951e645cbe1aede35901d251131974f3332fb2f0d008d0f34901c3bd9b13e750a1b4085a44d9ce45b1cf47cd47b355beaf421c80b6d1d716625d403b5d95004d3e0539910ba5784b73da9523d34a14066f3a66b8e120843040719cdf8b25274135a75b660644845f4512a5642b48b40154a62b2c9fa3bb9e72d5254207d0810bbaf75438c9833b348daf016751199b5a764ee634fe9206b2a8065e2a66516c591c8de6487677c3ca679bee50cab677a73a92d689b05dd32610a5e6c3104f254ceec847092496714a711ec8a8906b1de84adbf84851d03db9fac889d9cf1d684ad5691d76987ce00756a597e84c1a502d9855460861490d1b8d7a5986021d68c663eded63a982cc871ec8846b63e6b4ae9f3b9423e46c54fa65b29a481fe769d5229233ebd044e37657d1455b262fe0daa8285da8cc95612ea9a2fbfd543ffd5e1843ffcea4d07b77f44467aee82a78f34799fb65466531a384a8e03dd0a7c9fd3dcf399023f176deee5ee24317e968a82d75819cf50449840a8a6f74e6bc674a85c9c6b8696c12807a1b4f41a8532f3957723e96731ec84d5bc762fe47ea87e04f595041153e23e409e7cc4fb8c7b0e20a404c7675b20d9a319e62dfd135c69b40603c0149cfb494ddc06a4fbb437a9d2a20892ede7cdf87a60651c9c8202077264d5d8ffb7c9ed1fae24a32c05ea2d08b4aa4a04119a9bbd79431a2f072730ce24652a46458143f5e53ea56f561de9233f3a14a82c2f3fd28458ef950dd82b3804a7734294751cf944d59e47b2e1bfeb922989fa6c88bff7384e8ce46cc8453b26c2cbcf697d0fb4932596e828b95271550e485e30974ef494faf744c74bb5bc5686cc264a9f26d0e308b229a6aa897a1815bf51b265edf6cda50101cdc1837061fe18c0deb8991b93e0856243694c6ae0b2a35049808856d7fe2a015afdae32f059eac1fd145f7a6308512b832e13b3afcc1d2a65487a4ac5e7e61f4b7f6b8fd8fa790af253575ee9b885a54569d655210926b9a7d948214cccb9639a94ea3408d957a52995314ac5d5e686863e2f41da74b3badc31b3b20d5d85e67cfd52ecbbe0ffc46c0c01d44de23aafdb8e7283859d0c5c7f3c53cd9478a65465c3eaad47d0667452c9bad6c1aa355c1dbafe77761b2c896e0de40d7b814391ec1ad6da8aee09f2ef57e00aa5a106567df02f37f60c0a4b3367cfb54403e7fc8abb060df9de95a59c9f32ecd115a123ccff0d031faf630587e81d31cdd50ec872464fd3507025f6cbd108ca1d489d807054e0744811d8707d2f70b8c6815a4b7da172214429e8cacba5769755c2050351547cf3b1fff6313c9e0d0bf8c206086b21c5d2d49fa33ffa28c8a4106ce5dc36cf36773707ba38ea51820b09ff9dbe0c54b1d43fc8e340dd165c1727dbb860f19c71c2558d582651434b10d72d7b08ada095acbb179d5ebe70f03860d26ac4476c3af19c718644d465358ae89b54c43a02736adc96e732dcdc952441bbadc9731769c7390a81472a911f5d41f11a33af332d9f41aa8990e2c34cbcc1512d4c753ebdc834062c78fd49bb9e10244939551e9f8f649dd9a6a6ce7b251d82472ddb6a8e0c292ea1bdb85547ee5e5c601cc50fc4dd7b967065c46ed12bb83bb083d9dbe16db363d9d25100ea38928a0a77c93f8df2112e9853b418adecb375dd375f4711935b506616290047c877e1f104c072f2154acad248192bfcaa0fdd8244ca2d9063e5167e99ca47a0a4244fb8294cb8fe266ee91f550f3a295256460992ae377995812b6a22da973ffd25cc50f9e1281eab6b450ddb9412781938ea3e6f85bc9eb9771fb9ac7a04916db6ba53f8d44217c50a71bb1a244eecc20d6d551d4aa902a6860c65a20aa87dd099d7bd6e133fd45842ca1340b032c96fb9b5afb4c7bc2ef01252a562a527fed495a88ba5209683f68071239736ceca6f8c18321399eb9476b9caf4674e8bdbed00b705fead8f866abd286a7bd14b1b338a14008da8bed676d6b84bf733202f019d60ce6e07dbf7298512c85d11adcc9eb4f8cd287932f542e4f214f428b2028eb25a736d60f5e4f50629c7862f443aca2740a8d049a5991a889eb2d66813c71cfcd310ade4269201a2e2f697301252e832af9c3c30c4350ac2db26455a908105282563e18716f70cac9285ebd17fb1ab4be328acaba3a3c66dd495c0d4c8a4f93adcb61e0c3a09828e2a216534c71258af968d62a4c699df9e0985fdd2932b29e5b2a7ae5f36f6bf3448154424d1800474eeb3839a1dc896442c635094ec6e17d8c6311690ae453484d849935b37ba483a9f170a300db187bc8b2ac29b21344967ff6ac6da6fbc0fa33f6e885d7253b725978d725dd75be59abdde2ba969edd163f5b32bb0569e0290b7c2ead132d847ca96e824c04702e21f37dff8fdbfd42e892664770969fc24ff4b6dc7c2cd753e7e6d9543c2947d4c5c94c1b3b8c3f9d25b59a79ddc1e2ef60593e35b5b8a44c33e0bf7d939a6a95bfa7b994210f32a1de94911b2ff4b090555200bc6b522732c4f5b8ee0062449fe9782bff207a606ae32ab376a0263152a63e90215ef4855741772de245099f928220285104a1a7f403b53f642f7252e77b9b9364b7218abfcfc0e0c7a3625895e74d78eaa25572d994a6eb00bb8330c6c1b37149a4ac1640660215d6074da5617bd541b89b14b0a6e512b19635a1711ed98c44c14449c6989a21f664f82a0cf5c9d2f657cd57019d7dd6d878346d118a437082a0d62207fb294e4f9529be453994b39f05f514237303aca83c56910ffa25c3d5af868359382df021784a6927f799c2e8e9d073cf195c48694b269887cd4c2c23e594e99d0cbb352520c0e38a5ade1a2b4c9904e1cb830cbb4906d03518f27a9d61c773895033e32e0129012b4423c8de57fe2e881829adc01bd239e2eb07c6142b0d0ec0896c2fdb2bf94691d0e0ab4cc1971f352c396d7bea185d2bf8cb47241436cece8c819db84d242921a8c9565634aa183a0d566a12a0b5fdcb3341423002cb115b6d904cb38ff90f19af8fa8cb2590d7f49d0515fb4a9445029eafe8ea9633cf2a0f653466bff24a6f55536995f05bbb96cb00e5587a98858030393ce76aa08dd72d624853f4e84b4389351ca2929e4b87afd1d87a271d4745e825556934b226e2d79eb4a7574580b3a6ba4b447ca1da3c1839416aa63b19f1fb134d334d77d1ea4cb99eabc8b6c24dc889bd63795a917ac5353653a2c71b6f74f605b559050feacfcf8373d106ef4d523e31b85fd590233c2912aaf2920f245734b276559883e089f56ca9f5556fbeb446a0ca49f6683ffb452ab633e1bada6c4a93a28931687ec94aaff52aa95ae5c702c76322214f14e2b5520c73c5ea284fe53b1a6b7ef782a067d0e51168e1a6b501cee124b3558e18e7cf045480dc53ba5eafbb44f6e668b07983dcd05294a91d06ab314ff1f3059695f932877baf9914f115fc61672d4afc92fb6a5523162d74cd4adc4b9ba06e6fe3189123e1c82174c3baba50aac574915ead2419700760d6e8d947564391d339588f5fc055dae2d3e2a4667e57d20269f3965aae260e80ae5a0b252552b2504e57553983d3d1b7d396ca220aee245aa39b76a43ae9818fb8bd235b97a1ec5f29efd02c96aa5d6f45871417e7f302bc357c2ef739fdc46c31625573c12c5ef825cff0caa9a2ae9ccf7e2bbcc3e8b4156e1dde6d32fb7079d6b04b1302cec27fbb46566a20c30a419f305adc0b7bfd354608d7c728589db49dd41377a633ca35427cabb2411be5698ca983ac6941034d4c21d638af976e3481b264edd3f8736b829e2c98d53241fde1853aadfc6a6b709a84b9d92553226e4c1a93efcba9d7b0cd7814922065631c0f4491b20334044050b29499b1ac89ae7664c8592a937b7e2c7a9b1064a2286a8dc2cbadef18c309a20159543f0c891a9a4a01d87dc9bcccd4ae07201ed39b9e4def0a62338655af651cfbfb927f3d3f4676926a5664c199c94f1c30bb0c97860f6508670b58430095e2c89b78cb9516522adf63fa5e7040a0bc5c3216ec69415e694bf4622be22ec4142ac839d658834ddcf7a8b6b9699b99d3a417558affa99e2949921e8bcfecadf8c299216575d9c9a59a5cdbf69016344019057014d818286f251309f77a798faefda585816d6fab339cac6e6a9aa27076609a53463ea4b812d3c531b907b46ad5f7daf8b1ce01682779defcd5a9aa8252bc7fcde3cd7f98b1653f4ddb729ee8b4cf5561a18d1e9fda19e989d21b30d48464ec844ab40d8c9c4c543be3770e3fc0c836e2bcb6bd1aaa959c794e33c8562777e166a0aab89df14131049a87ec79ed1c27670dc2134d322796bfee9501f5baebed48053a232c22c2242bc976ae1f9721c9598f294698e5b6303757265b7da8f72576fa87a3a90702efbe5691058a6653fb9de644d7fe9502fcc32fe07935face1599c8a69b724cdd5233b9ef94506ea6e7f314703a6c6cb444e486e2f51156b66ac0f546c1cb3f96808b7ad735897f5884aac3488e1289d244f3a554487d28bfa0e47058f4f3997088314553d5ce3c7865f8c28a9229031cfb28149158a44da537aa7b7c72f558d7ea9bbcd7583df9d1dfc2dcd8ca70a8cd516bff555d74691105fa4853a574df2ecc5b8268b2beaf9712780aea9e4a631215b3d8fc39fe566262408410e0eb850deac04d332dd5290f325338846653ed6691ccb9909a3f277b9dd4045205b2526b0d891d3b778775ff9f7ff7f0c35c064246cd99c09fe06aba60a71b243067660aadae238c223f08e701bc00c34a74de44803770513aa1118f3572c890bbc44bc57836b926a85ed5eef2b513dc84a80fa4071b8f57084c10ec19aa6df1f3291d8266cda5b42ed89d859aff84849d2573cfc7ee5fb61f155dc138bb1d0c4fc0bea013453be722ae5730b080db8a33c7e4a3ae7f8280975c378d519eabd76cc7dd9b766c3ee9e2e36008f43fe38c3572b3ce234d49e9b146ad3baf6fe7c466a6de5d72f1edfb01c73e82dd47e887ff003ebf39711375127e4760d2807b8684e75d44dc6759caccba845bf5eefb68be2918f89e390b3e71d992f03ba7a60c43109309f86635a784827d03dede8baa1af39d08e3697ad0b9fffab4a3f800bde47176fa0f423c23e4c0ba6e2a170cba66f35ee38ffed1ea044178c3c14daba84297cc18ce3b253f7800b3645137254c0d07c57c74d74e66c492b7ff78250e7b5b01e88332c078498a80f003a8f32b25fd7f982801d12f28868440af32b1f5328a1df849e92ae571dd4dda9bce61f226d5467a352465adaf8e6a88a3c9d8840598c501e1fdd7af4d4ee85afcbd932446c22b6be38deb4ea0ddccd9c55e2d730aaacc7f0cb4a38919e89cb9389504426b6e99d5f01ea268b44fddca44ed94898ebffacd9fc6142964fed1ecefc2770c1b16c9b6b74044f13dab83b2232dd50bd6f2e20752d6988c08bafe5ba3d31cbd641d58894e4274b439d27083feacafa8148fa39111b976934ab0a0859fdc554223e648610e1119167c802cb5e25eadf162bc6f7e9ca21321fd60f15588f255667bc1ff4a6f6c2490099393949174dbf7ae7b931eb8231d1f590d33a4955677132553a08d7057f4a4fb357f112e8f65c370a1de5236229d4656da057376c5730fb769072bf403421fa6f96daa13e58ac15cae0a04629da4f9ecb069b781a2cf689482322641601b54cc1d99b419cb80b277abfc87a0a4f69d93af910fec2bbf90db39f1fb78c710b8f9475e9b8403c62a353c871cb0ad37deb628e95dbbb13997ec399327df93774de47d3436cbb8e063108b6740e1c0f5785d86662047cb8c14b9368225dd8d1f11fb81df0180ac2b8ff0dca079b7439b23244582d85b962be6320145b6e2e0264d8752b7cf3016a44a6f6d408bc04a698fc9672e4109bbec216d90a87cf924a17634da534ade1bb25f66418c7d4f7a1d2764e73409579472b5cdaa6134b9b36b2cda9ac29499524b31197e2997c905e96c6a46992960ec7bdd67f41ab329a651e2c3f15f1b176616b99c1b1760aaf3cfda6df5eaa18914a8504e39797c1cc04b0e7f4a74d0597b55e36758160d889329956c5a40679355db275cc2028d5f16929f6c0a291d1d2e2b755dc2b878091a638b3bc53a35237f02c977d7ea2687428e05ad5661eea180ba1ccb2bfcc3eea92d1c59ad195612fc898e62e2a2ff27e7198176e1d552923cd9b23ef4d718b683d142141a64266d2caa3c9be18326d84ce8eb8c691f624789a8a143cf5b79988402f786a46cab38b97ad052f19e4b4f2bdd72dc06914e92935f07fee141ff89e2fac5947b90a91ba93f356874bf8343badc86a8866c80784408fbd885cd6e9d270d8bf6f1dea251d23a956d3423634efb27761edf2dd586b9eb2c3f04e25e9845750aa4e5909d21b236468bcb9f010bbe9e3d2d5c568a7538bb48f14134be525d775f15f654cc9ed60fbd04e555626198126dca7ae406cd047dc2e46a887fd3f32bfc68676caec2bba6c7b2b5b2efa8d0b2e4cfca415c33513d11f8305e672f0afb1abe4721475cdc8bd3694ed3467d0c538c8489091804591bd66d8e504bbaab21a60353bad5da232dc4330e7a252373273fcfe5deab63ba1ad43c74f1fe87662987c9853d21eedd1d4eaebd3fcc789a03cd5a80b224c8c224f36488eac3ad08c244f50ed1d3b2cc77810c648706f151d4ae045cbf829d7d347b377384e76a80df844fe1e9bd6c4335a1a749b481ed44c2be3a36dff91dc4ed9adebc833e1255d327584dac6c2afb31eccce1b1c3fa463977b6149a4723f53e93ce7be6485341126e53848c6cce6595efeda050511fdcbb73df6e7d9d824f8ac4afa6abfe989607f5d7bb89b4943748c13c9e09ece4a3edb9c5d0eda959df66deaa0a7aed08a5c3a7d51b93769c288b5a91fe232feac0bd5425a22042478ec2c34aa2310f29301eb07e2a4dff1fc9e4c9db86d083ee65d9b87cd24deee220a39b1363a099f21079cf9318ffdaf7e2d54dbea5a0c1da4ad20166be67f7ed4dcb5736f45e9707c26e875993a2da902dba7a312184ce412003c774a33d74bcb56065b024cac98c987f3f2bd601d04298875797555c5ccd7b615b01912e32c60757bb40985f1395f5c691c309a6d6634d3e3bf42b06b6a5429dcef59ab6e1f8d032ba5cd9b901d9cc68e119937551b19f70563c34033a7da2c693b70cd078d96b5a8cca0de8f5856b02e7430b74e1995b8f2cbb21c1db8056f58f61f9d8ab81a20452c19728d00f2a6831379a56f57628ca6405e98d0dae56f8aa82855be779ad05a2479410e57da9dd7416b9c701f6d3b6d09cbc214dc2d2d31db95303a6c56a2793ab15e0c7bbd93d0a052879286b4ff64b41bcac6204d092f45ac443da6c87ce0d5a532ea98d562ae643b503203f5ca45f715bc4d2692af001b605f92acfba040f484727911f97bed925b5c5d20a3a02a236a365aa0bf858e3713e3c3eda9acc5723e99d27e1459b87fbe0531dc4b6217240333ba73d1fdf1f20a53b12aa866ea8368510cfd406b2045de7db6bc29beb0b5a2c60b41de8fb05a1111c5e7b4f23e908d5d4dc0a707b61428801cc0e32883c3125fd4f11d504c255cfbc241a6b878cd40487300bbc58711ba5fef8e39986b942e02051926a4e9d5dd8099bab3c6a6ef27f0cf8939b4da49ae2f27877cdc658061d2074ca4da67c09c5e48d13175ce81121e4883697a3ef8fd1e2187fe99e67bf17c4d8fe34a2676a60e8429f6d2d075d91b59e33a2996658fd7596e574b378586ebfa5407503e09f473472584856af6078ec9cb9f3e9cbe02918408358f89cfbbd0528c98f020cfab68f13e23f14e07c810029af1a5be1f63c2509617999da9cfe04d6c5c401b1eafa3677c0fb87fb5ebc5bc57e3a8346746c065de97bfed975127ac90f009e4ce15992f5d2e4baa71ca46af7f6ae488ab9723593fc7be5551ee60c5e64ddab2c9751d3e024cbd6bc381315d9c833c069f2ab470426a3508ed1d2ccae247b7a3d7f08b2bc3dcb97087a972b632817f441feb9a343b70ef8c2909004cb4cb97f47be5b212591348606493243a833aaf8e0f9ae9ce7991b4fe46c9ad54178ff6fe17ead5de4453eb41194003dcd9c66be021b18ee4f06e3db31dacf18fe9410306128a7e2304e2ee701fc35a893c7a8888daa7351c0087bc07adae5c13ec0086a84a7c26ef65b00f2ce831f278aa965ba2974d15a60c065e9ce1a9e53d5b271bc72d6f390059d651fe8ea460c93faaa4f8db662c1d063ea8ac593eab6b2670152dcb9a9e106f3f5c8ea1c4daab5a7bca5e9aa946d89bbb36249c98250a216484b6feb5cdc895d48d73e9273a483a0ef8a5714daca73e3b3c60b0870ccdfc6a71aeaf8043fb104411471a80ef542c5a4de97c461a03baf6bba022b7284b6a65723eff4114a4296b00c7230953162257632f15f9b0aa498bb3e81c4595270e15e1d30ad5e607171f2faaf77d1bb2b28e1df14eb788af41e1032a50cc878c3f748dfc84b73fefa7b3d7df4252b774df48ec2e10f4f5e51836692858a939e5abb27703cfdf7044cca95a95183658f4268b6abb73e2825dbdd614430713c9b03148f07b274d194295023501cb32f433dbf51be11ac2e4e78947bd332962cfb24f4f43022e7ba09546682c5414fbcdf87a81cde5744e1a50fbb7c1429612efd2386ebd41b000e01cd36f367dfd8d8dd52bf53042677be763d94479337e3f762b6edc52f4fddc3379bc874aa2e7b82928af78b22475889dbdb07fca68d6187b66c50cf157960e204f0a075a850f1f3036c882610e847a24b6c01db7209c7d0269a58df911343687b1283f3774c86c62c1931042f3f1031a7877e409762c3d4a934501b6caee56fa42452a9fad491e33e52a8fd878a245c021db0857191e457ed40a00be94d27d2fdc0ab44ca7364765a4457e3c392691760126d6d6d091afa1e6606e85cd962c26583eb9f05adc502543e8d1a3942aba90b26e9e53543e43f9601db6a34712e89128b08b4d45f35d07a24800afca6c0af67755e13ac0b1b2800bccca8777d4a73c53997a58879f431c3d0ae7542ed00e76d45d81b4ccf2b9051fbe0e7e32f9d78edea91310eebc2e2d072e26c09bf9befef7be0036023d20f9482d596b8e43de5f1c583c14f67edb9d161b8b58f8f254e10ccd2fb7bbd49b9b139d7672cd1a6ec03921525a2ce553e04cc2bcf6396718574b553c5836c89ebaf2dac244b6a70866fa326b1d0ebab94849d05bb1c2ced74806e2f6628d2b58e8520f3b52fc62536bff89443635aaa7451cc04099c1328bca135f20ae54b2a7a000cc006616d82de346d6d83398de7e9e25f4167a61985bc02d6fcacc5304e84526895dd3089322e01887b5a3c23eff429f9529b20b9ec4280f5acaa4af724851f368e574a0170fdf07776cf3b174fd574431dd54230e60dc3a49c1f6ce83bb22224326e3cc0cb0d3fa03379ab2f49830ac344cde6582a304288b8515683e1a3f7990832345ed008961d6ba2891f31c341acb1bfa1f378b5f3bc6fc1c564bb19d1b67dbdf8588cd113e22d07cfc682f3d007bae7185ce249a6f1604012c983c831d82d9fc69e71500d02cca2591e4faf53a1906e7459744ae98606f1911942294c93e2104096b8b5e56ca4d47b64add70d1a9e5214ea2f6786e29377703027d0bb89f9bc8321bc9851de75828de71741480c7cf7bba18fef06a29a117e036acfc8215f0632d12323392010f18e3713988c64510082082bdb9339392a008a71e78f13ba374327f6893b2dc22f76ab64534f90ae11ec1f8c13f63e1b7a8aba9550e21a3a4d793a5397770a6cd085e55a99a7d3b4d9ab34eea5f53a664d40ede46f063cbb33b06679ceed8da0abba924768536158ad2471953b23d5957a555e9b83c2b546a1c3a1e94f8a84d35cdbd85920e19b3be74608495431da87aa54cbc3b589b8c80c0ea2f7b812f166589d5c82bc0da9332bb3ceb8aa017b00a6f0d4423b605b0298f2db1c25c7f2ba665574e9670f5643e22f45b72dc380cb93bf19b624c8ee98f70dbfa3013a4832d5507d8a6aea5e739b2a432e2865f947350633959c8a95b6b746b7cb809b9535dc2cb1149af16d957ed6ed533a390d70b61a3fac36880da1a9c3d8adc2210f51480c1ab044c651b344f7c0d9825032c888b7396fe73a324f9e799ebd1d3ccd345be2a397cf3b159568e649cb8abb9c90128fd227daeda1e4ac65e60776ac0de88d79e91acb6a79e4d2224a7d3b5217dc8ae8d0299200b75069cf9b3705d35d3103d36d8d00c75e15901c62d641fa410a5aa80376500ac6990a592a519f1016f91676b82e124fe3b69fb037a4aa8909708bfb76ad66f8b703a545f78dc8ee5c2eb42fd00a51a1136bd759a22aee68c49b07d1df655dd8e52b019c7b5d152d64f52ed1b152d33922c9eddda3acb2006fe0ba28dcb8f1b03eb6b910c3bc48b9f84647761831f3d97281694127f03cd8de3f222333385cd0e66221d03ed8160e569b807065a8109229252e2a6181f96330c0052f33c0bd9fdf507802de50dc5a6ee10efa36cbdf0568ac7e48004cb549f0e1601fb8c2bface7622374aa950770deba52845cb57cf1fd48b48fc413878d845efb779bead05093bb6ae4da9b59b097675775d25b6aeaced5a7ab4beaeb0261ccfe96c1b35f92b8e82715bed8c12d3e780f3cf0de5c79a1cf5107df47095a084edf0242e82c13275f419738c2a9c992535ccdea03dd3a02a2477f9873ec99a6a30a9905bbf995c5321cd265ea04e88d266ebf8b0b6c3a5103bed919d060af8f97f84a304de84d1725b37154d5daf696f3387d7cb7c1f0d9bbfbe4c646f3cf662e073abd1895cfc91aec7aa9cfb2cacb4aab0b94032f18c7380d4edd9b715f0394487bc52d4c672dd3e7b8a6e1453564edc92f3cc9a7a66311fb184241a193076c96485554bdae6bf1b011a368d1a9b93fe34e1323ef3cab731100064b02f999d4ea6d47296db260d48f5ada68c863cd2e7bf79b2060f66edeef16ff38929a3316d6ecca20c31dbd301abb049b13db5e783a3310d15421580866b209ab802c4c65cf905ce3c35837ed2e90886fb156e7a293b6f537fee09d024a6c86b0d913de7bb4c270470e28e36e0d653d844868619a6c1bb6b0a0409e892331c1f7e4b9990f9b03322aefbc71bd604062adedbf27e4272a5005f1bf249a22450f3d4724a50b25f812d9bfc11bfa651a194be18190dbd4b3dba6d912895dc87697d2abf82b2045a7c6cb293ab00c57b302f18fefc7fcca5d5f49f5c0049d6eb0a52be2b624c369c1e3d7145c2039680bcad6f8c5040e60080bdfc85918a66bb7a05c9eba05eb76a73aebe928d012fc3abfac17c4857097ce1514fea607b55b499c75cd5c6a824aa04df7bd4a100789888d98cce0a63fee7323b14c8c896c430a2e87afc4ed2039f8d6e01234752055598a5fc58424614e8db03691c114349b0f4f05ff0ba55b4225e090f2c9a66e0111a77d5f64215cf24a6147033aa648a26ffe5edb23cfd845cc932f326543c339a092a7291dbbe2f04655fe52ba9b65a971383021671fd93c4151763a596dc02220b052e137ee10796e14eba69f0073fb01cb62246a16c82aa6d58978d30e090dfd28371fa3633ba085371ebf484a16fcab0f84e920c7c62800367dea3a2b793abbcad97e108b012f010e0dcd914f67020518afb926d3d6ef29fec916a3777c0b888d991eab5ba4330eac8877ba28a4fdb44ad961eddee14bf2e913acd67b51ea63e24378622711b874baadca284d3dea32e58d5bd6a8d9aea8e9d3804e3e0379ff59776e5186146222e1a900d3b2098a217e7031e3492ecaa0c80f0082b3839044d79df60eb3e27388549b132831e5e1427308aa03c146d2a23524ae879ceb3cb0215274c211cc751378e5622b71eef1d0981fb073bd96aa3faa46e808976fb08c6993503b4512c0af485268b95e19aa9dc6db8a4d4efcaee41c8ab34adb441b0b430a9f93290ae99b7bf6f83d8d872005d4eb4f23a8ab9596d88e60c964e829d945c7836c1caea17d4a760bac49d98383e4bca436c8a6f2e671db86c65bf5ac2a99d22b48057164cbe0924521a9f26160b60a298e6327232e6e40a0eb96f2d9e75d937ba844e6e2540e8b4642e30fb959bec7c7f11842d92541500576f64ed4d8d666b51135e2d041025c4cd1562a82286bc807431027cddbdadbafba3e258c28eae5c57cf9f4546b0c869af9eb078ca62a0bc515d810cba330824cb64fa25a6421d9944f6f82a1a79d8c8a819cb563d535194184c4c08c25e75f7b73d32cfb599d7459f4ac8dff350b95b559ca3a6709810f8f315cfa5b0c072ab1e01680c66649d61db5c57b69ce856fa871ab07466688cd9a4f9d09dadd96531d4cc97bf15b68e7ae1841ae002f5ee8f5eee02ca27278c371eed32b862e72bf4b06c9a8b40f64b34c1813cb0249856904f38de1c779aeb54ba1fd99e0bad0df23a1e9032e2705d22b033eec112fdbd6bc27179aafb068f3253db8740e3f00699cfb494284b0ceace8213ad693284ab25eff91c3a2b613bd2723cac300b201499005edb9b7888bf23ff9952cf1e30861b874645ee3972e9be76cd3e21304a254a387219e3ebb5b7c6978a879450ef288ed56ed51c1e8d9749c926b1cdbd6814c6a247eda265351cc307b17b99b9cd7b3c2c7a3a01da040e0861d6df2104160933b39bd99d855ef18badbb724340341357715c607da6e594e42acd292a08096bffa5fae48618b4e3cbe24e011d2c5d2478754c1246396923582de82129e522241f311d7b6f3f44dc118e248a4e05dafd6294afaf144ffa8bc9e832a36b5d2dee007cc43fb85568503a162ab34944e0fe0ac73c447eff43ff2322cb2274e9d73fea5a6156a82849c59bc22795accc8bc8c8152e614416c53f2fb7ecd3ca46d464ab248e22ac2189284409654ee698db54b4d24d2c4b7713ac1e5cb43698aa15eeacac9e62957c04c28c01b703ab3f73475b98582adfd222de095c6848666e3a3cc116fb63faf9e486462cc4c8e8a471375d87adaaff80f5a8e1b308de7490d76d8e496ecfffa77ccc3848b149399a74233de29d31268eaa8697d1ae9b4cbb4232e86988c63d67d678eab0587d7468af24da0893a0621e42db3a3a9de94311bee5883e9a61a1acff07368104aa98c1ec72652e028ab048d4cebb6d739b872482a0cd3980d7ce346f48e624caf0d0bb62b8e24ac6cc7674a3fcf18df37920bc21c74dbda288cc1c9712b42ea00b2a43850c141ff54180e2e0192cc06406c1e05a4edbdbd07a055d3452407aa1342376372b9478c960ad6db00979f769977bb816f36356824f87856cad23900b9ba946438ed703b6833b7f05ba6ca1eb3e0f7c3bcd5a224e56d2b37fb4b1d0623898f16488c301d7dc55a74cdbd111efac15614322fc0161321472a676c946a8157145622fb42ca5ec12b12fadcce7c8c5881521613c21171d8613bc0927c7ffa8dcdea4175004036dac1cfb9070b89c0739e144e56dad19aa4bfcde83445a735183f0f80429ee135b426ad8429a017f0acdc062e3c9b741d6de1b085c1358bec6303805429cc5e7b0aa47787904774d29cae740463770d0c946c97a2b9353a3c57ee4c53ed5cfbdc41dd8df51689882a8ef4bf577650ecb724bc502589c8b79fddc69bc284bc4d5c5d747394c2945c59674a136acaf6d5a582684ca44eccfa1a295a0f29a28c2b992b48b639d00d079d13da80b93cca5af5156e68751507b3a4252b98313a3ed1dbee061e46003de0e30f584b16a2a46a3a6dd46b44ba5e944d3420f24ebf885e06e123cc18f2c6d17749372267f9f19069d983b83d94f5b0ea4ad4483949ff59e31c788c87d7ab5e39880dcce40a600207b510e63be18366c96191bbf253b1b54f2e4ece58ada371d6c11af22443c3c3cf3f9e72d6235f93150927e23b4a0a4e6b312dd27eb0840f2998d28cb469c7046a8f2f1c4dc23593b61f2718f3ebfc3ae34f21fa1bf4090b5c5c48d7342f7cd94b28a097790731210694f8081140b0309673670555388125f0ff01155f2c76c89598538360c1dc4178c012a18d0e049e2539703e619deb8a48d594a3b12b8de8ba70aa7306b19a64bf4ac4263b813d69a478d0cd5fa1ea051dcc0db59bd4fdad87db94f27b2332e6002032af0a198090f2e24007ca7e258c2bd32dccc1cdf12c995834a1f12cff576eeb7d72c21d8cc43beb112fea1111f6f90cf4e7811967b08305d9dba9a9a7710b520d6f8b0474efd10ec53d660bc0b2f2e28f9ee0d4d0626caa1a7d7ca7adda7203ea2b7e2b3e433b588608cb78e2894e14be927c1e0e3a8df859a5db0df1faa20b989331ec355eb6dbf032151f832004ab1bf18ec6e03f2f02734a52bd621e8a8b5b6acabc3b5e56bcf34c17040c5915d311d487f45b33eb95b856235791b17e76fc1346f34c757b22fa07e21a51f93c986594d53046c8e5d24f2e9cbd6b032804a5fbc37c99ca419a0e9b9d73d6e8158d56a6703749f7629a57e5a6aab6b0d15ead138b39ac2fd31428d0156cf0ecd40f0500cc65a99c38d0429abc12d3f7b4688dff2e69e4204655e1a723a4077dc100296998f60445f2868e96129a683d788d3f4b3773145c8b8022f45f30de14be9f786256efbb4f3331e1979bb1ce23dabac4722d3feeed499a4bb163ab130aa11b5482781615115de50e8e426284d7a8fe7bf49a2c19ef0df73b1952940d1a1d95c3047de9d6c493520f503f510c5d9127b2e3ebf24bfe3ec02d683e920c5c721f504b91827ec3e94d15d083091600c1dbf234acd85435929365da0e344bf99f5ec12a83541e7c30c6ea4a7b60ed65f909281a54a9ce20555788a1e15f997e3dd4f01acf4c0a131a52a767592e4dc373e53de1683c969114b4677633b86c95d144d44c4d8ae391d125a68f11b23c1546d43d8cfc543fb4e0e54e2ecd3323622943b2bd010c2b21729adb12d4b2503170020106d7ac30942d8be90d85f3b5a125948dfed6c833c220b8705f1a5ae488bf83203d1ccc227728d9c730d840bf71cd060756ab17f06b0ab91995a348b0cd9013e4dd234382dd41584cfd88b800e1a4caf2c085a3efe8b5711a35dafd567a8bceff69cc80fe1dc3cb13046fc440d0abc45956a9f9f95ae145573881f7c160ec97c6878dd2000e3ffc5b4fc7da4dfc1964c64b111ae386bfba2c3b854ff6656ee92dddc5fd62e6bbe3f9e3c1c5ab3a56a0cb1d2278b2c6c30c875646769d1112a23822387177c3a6d1bfaa568db2da19bbcf2c5f413533f3df93698833053c5dfed22aa433c1810bb9ac923656d5c30858714c064ff49e59d3fb2450e523e072a1351ca0b9bc3715b46fd773feed9473182c71b5144136b76640e2f1c26f5cb5fe24a3a36972ea7a8653f2f8571ccc43b2a73a6ab3a3f849ef8113ed5082bee348a3af9a38ea9ee32d540ca76b9454421b435479fca657ef2ce98a256812e175bb7e7eb6f3c46a97e8f0618a59c0c02eb53c46c4f675f529865f7558de2189711e6903ab730412948bd8d637012e71a2e9c50cc4b7c17b4f8ddaa1619868da43b68ab484792a6b6fe90d7d717917ba0a6a069a68ea966a89c4ed838c322ddd1c57ea77d059330b58d564993b3c772bc112bd1cf0b25b7ea58be899c1943dc60dba6817b131b9dcb35fc0a440da4b28e9e37778f0c9350ccf7a5e2d7dd71b8219092c875742816e62a526192e29b807a6d0f431379d1371cdb35a07c1349730aa26d9f385e6d36a7e9c27ab487dcca96eeb61841bab6116a794ddf443c2283b0aa87abbe05fdb7cfb99f73f8974af916d71344062b7b5cc8cbef45540d2a24b9836490a09b85de643145cd4d49a7d041f5aa22156d7d8e30521e8e822413ad433fc8078566fe04dcb4e960229171b354a045b7b4889270206fe90f5b3803cca47ff1f4e03825a2805954f34a81a6ed649be20962ee577b668d9b039cd531a059cf9aaf21b6ca05495f2c2b02bb22c03215e3548b0c9fa4a65bb4ae3cc0d691e08152861550684bb6d7822cb24ff613a2a2218bb3d23226823e9cb6ce7013ea00e097ed4ce7f057501a05a914d082daabc0f5977b4b7e21bc03619439a170b0a2d751104833dc88540b831c10a040e58be4e278c9fe9c47cb8ffd7d4cb4d81a199c5ca079711ef0c80ac463a4c1019cef199d66ceb40887118fc864675cd02c96e56e71b4ac721596b4e608465f317236f9f0a9d60de40aff07e77594d39910de5f60e11af4a0bcac7d6f41768bd0d422c8c9227828517cd5bd98b0320e2ee1862b3206ba899b2d824a01cc0a3978c10c4ccba319c93e5f9e5afa9ff61348798b85b02db7d63c89aea0c4846df3e753f00d90360afe3fb83c64eccdd9cf733a7b6779a98665425d5b372a89dc55350a2c21452fba15c6681e043c6d8a4dc1d4d63ecfbd400d31a0b23fcd682b074933268296c40b005f520478e06fa5e4235584ab2b84ce082125bdd94203dc078134538510472292e0e96f243ed411bcb3d4a5086268d0c676be469d167003f8266425ce1a43d0017470bf84e742ca05afc3a99bcf580d2f0b2f14b6858b31cbf300e861fda6fd9cc477036115cdb4931fb7eb9ba72a848c9f8392e42f6605856ddbbeaa4bbd9b1e506d64b4c18d70fa51cd1a92c2adea720816c4f856bf22a844e3405a1ba06b6a94b1581a2c4392f7345f11672932915b445adce009a58108bb3e08d6429ff6b718e0885910e0f36475234b2689d2324acae9c9ebb231db5febf0d56833f5f5fb3430d832cf04653e497e8fb48b075370e016bccb0b1a9c4e4c7fe2df14191e820d3585cdef27cf41bc5dbac80053cbad2a8cf95a42a41f50d2efa2d846e280803465bacc78e2efe459bc11702b35a3d1920326d1a98d9ac89ba386cb3248ef238b772b25829346ca13874711694e988df75586640aa9d627720c488d47be4d523f9a7a591e2928bb937c5d1cc0d61560fa07298b2db950ecb11e65b613a85409b74f35042d96191e61018a75a0ccec13e7a70549f2387a941f478cd0cdf32a54322df43c3976d4f2ac73a5e9519aaca9cfb5535bd1b818f222e53c4821b066e441b520d26b9b9240eef5ad714cd68774f34c2ef06a5ce4db030c91de05889b30b7e7fc76d577b85db994797149fa8e71deb64cc75ee44cb46341d105a2a5cfbc2ae8ea205aa352175c2ee54803507f83571a068f7765d69443dd26ac7878bcc13be91d94dd6fe7f1bae92f7ed4d59221f129ddd2ca971cae8d31a8d83c9d27358e42527afe0e09d3548c92634f6914eb4c4d58e4a84420d985d0828971ac480dc58e7b2a3f636b46de8d893b633ea05ed1bd922d35e3d08f6bf5bcfa69f2a187cd02d736d2119cb2f4838aec021abbc7dd9ed4522dfb01bc027403d507bca8f8f4be8933ea70c9155f7bf76d205fc943533f76d94116345d4baef1091e9875b22ca49eab42f66dddb3353278c8cc37991e750d3e5799a57436b574dcc77d2ab848e6c59a4b7bb45b7a177d8a896856e2c26b64c56e7407c7916eee897df6c8df2b7ef473a8fdbbd3722a3e787ac7026cd17c3ab3c8d9314162d51d2659d68dae3c6434c93f291c6201b579f6ea1485adeda900d458e93a972c4927967e3d43a8e563e5de717b21a1bdc6a1d7f36401f50c76d2e59585ca8f8f9d4f96e155ba0425077a2fbc65962af88eee950b0ff6210778fc3c6ab11edcd0587be3da408ea5b0da5a96e281235893fe74412927f8a35fce9c5612f2ff9719de5ffa71fd227c03dd0987db280c22dc062bfea3c008111e950f4ba42c17783104dedddd20bb7f2a730d990261caae544fc96c0eac8a4c3d5cf7bac28848a8806c5f5e7ee92b53cb6de7c7444b8b88edb079aa4bc81784dbe283fa0c1cb53c2f66b75b569efc15ebec3a103a1a6f92ff72e0e4845771ccd5c985f4d7bd78fcdf605241247f52477ab5c8134d938ec40546f8f25b2393cd3ee5e4cb4e7b8eabc3c2a473c937694d250b52b61a3f33c4582dbee81b168146d2d2186e31b69aa6a8d760a80bee097a9fc2439ee348b9cffe3bb4baea23b0a41c7403b5e8833a3f051a985bba5014dde5f23ec163b3095588d51022156de1f90f92a384ab8746c8afe8c5d8cc9b2d875a01f2475af83a948dc0702f343fc9ceeacc24eb46d3d21812c2aa75113cf17c2140efb600b32bef09fa1f67ee750c067eed8799521c51bb62a1450859d9b62196b88696a012d26cd17dca00924616d78228f60313130444355e984a6e06a267781e5f85ab8767018892d398004d032b4fb0fbcf7a4bfd7b6b644aae8732438f34b15f8c2e026c15a9efe8daa61650620716b91451f750dd0fcb04d29d463b1f7fd549e5975f6b3fd32de1ff375098c4cc0020c4d62c2bed1d1690ac975e9cebba3ed76c4d40a03ae873e0abd38a7dd4d80a460f02cf1ff996af5549a0d78e87b68c25a411b104edc6fbc34f9f8886029e1478ce2c6b46f1af0a4e083ece3ccaf01d7adad8349b4a43fd1bfe82a73b2b276cc4184cfc53c4135d2e6d0d4341e719483de37d1d561c51c8fa280420442ceba86322058e5014ba8ee679d44d52ac1e9caf5725e437a86bece9c0efaf8c2518971e48e08f53828eb297bd04981aa9d09900e0bae769b81d02626f42942c019b01bf669012498359c073266a89379154f67f64c06a21d4000f225fce8781e2caf32c0ae01e22e4b704807cbcdb0f9682500124f71a5372da468b13b0cf0091be3c42a40fcfa12b20eaac3247152927d443ac4301152f98289634db5c44b2f70733b1bf02ae07f2e3c2924a79655974798d08bb598a6d728ab61cf9d1c66c48a52d90be9992f0f7cef1427491bb1d831b700aa583b40dc6bdb257073ea8239bbe0805cc2cc8f00de69789c7de2db4268741ed71e20ff10010e834e84e07fe00028531fe2d99fdf02b8e7bcf539b92cb6dcf4ced1766510e8e8ea798d16a4d10ee124e40be09f2fed0e2c1c6414f8b7c6e057fe53c3c1402f7c6851d748fb3a0ce9d24216284813cacb235b97d84cdd14b82a91f1108b7128f6493303477b97833b7555df3dba60522d856055e2f3815de6a560d04a3ddde45accd892f2ee3730260bd394869f850ea67e34c60bd471e5f2f9b9920adb7113e050adbe4ba8dd773a34047f649c6d01e9b79db8890a5dda173fe89e9ad30f3e29c494337fb94fe3371cf70a169ca11104e4f39cd062e8cba3f5078ea1b969df616b2565b1ba4d44752d480f6ed5e46900f470fdb0fcb0fde79adb86986a4477b5c206a06220d6aa841edf95396f8feb3d12dc81ebc705917278cd0b0ffd5e3c66211a137de5b0a4cf72fabd34d388cdddbfdccb7d006c8e74e9f8e4fd6a6a0b74756817a84a7c76d61d8f1b89fad331fa396fa0387fdddac74554f0adcc50ddcb664a24aff624c6e61a270efaef45c6a93b0123cf40ebe03e4a105c42461f137aab7d8fcf02b35fbb0551599b695160124bfd01bf6a9082552938be8078b8f3d3d0df3b19b3dd571ef2ad0ba9062f82610e304fd675af64f2bab9773f795bb597f039d8cb5b216e3fac6ab329f110d6fafbbde5f73c3084f96ada8c5eadd449f22d400503582c14918d03d5d230f5d9ea8ec31d6beb2bd3f42a799bbd6bf3ff3f5415641f700a3640ae24c5e684a607d813ed30b24a187af97fd4aa19f36301376c2b0ea4f48a5e530738f7e779c533327d4fb2e8633f75fece1cd256e300b67756395c4be911a0862dfdd3c7e8f37f1a5c88fdf3aebafb502b917147bf0f61713db7e1e41b73829f3739fc762992073bbcd907aca6e6a0f21ee92bac41bf578975ab5b65311f390bf6e30f71fbe562adcf0d02b6affec86b782a021d0e7a26bb2135cb19b0fe6e3c9d5a2ccfaca9daf387bda549fb698992f959c7e4a65ebc760bf5c941eb3b8ae68a36fabbece01e0de4a3cc52605a3fb4f23c0828339aaa25627a0874deb3e06c84e525ab7594f90929edd3a9ed26707b6699461b1825a9e0400e69b529b53b52921a3ff28e4007d89ac7c1ed189cdc1d7bb9d340c6f649295648a59c7e89ae2092cbb0ed98f22be68f983838df43f34dcba4c2c2ec285ec0fac111b23b6619b22804c5d6afadfafdb2cce92f5e7334e3ac6c45376d3307f7eb629550f1bd3b94df9bb0fd836ec726d7b7fd956680db358d3fc962ce6d2ec61cb62fd8bfe80c93eb84f18d2d582897e1bc53b82881562069fe26955bae3ee3ae8e27fade3cba28e49b96c59a336012c2a834f2b07df9b0887c1c7fe2fa578aac4a4e0cbc2ca0d9716af42b7504ebbe77e1a9afaeb8ebaec90701e375550bc0964067dba0a420a1f9026154292e120975374715ce11769eacd602ba2d0ea49a2ac74e7be0a1fb22386483732a606d91ba99f716405271676d4cc4e2ed734f7dab6bfa2bdc43d0a4e1644a9a24b6203af5014fdc2caa3afcde2836f9f5d2f3d58f67dfb19ac43c14585c229366107ee2ab33a8497a82cbbf1558b637ecb015a0005df321c2c951f9b5245d77163ed0151efed5b064eeebcaeb1c47779bbd884c43b4b676362173f0184b782d51b67b3fa0e90df933b8207a6a32a8877c3ad6f6c4115d67670c82ebca9b5609f464f4d8c3801746c03550cd60455436e6d1603c29986e9097e130d58e65c594e454a094a75ad491e6cf3b806eccc0d71b6d99013eef63e6c2f8b65dd023613855191d8b68d976180b6a2023dd8e0340d65bef73c832f4381082c96283e9c8ed1c1cd0b2bbcbd9e076f81bacf16ec9dc603eca3105abf8e7d1450c32c4e4d44fbc224e694ca2239dcba94f6465f9247b756d3130f1f7f808c0a8a824175c9173f7a1c08b0a7c892af9f41443e25ef52928200dd1314079d01c404cbcda46c149f51a4819ffdf09f96ae2d32493e088840ebefe34efcf638663b1323e399b3912b60eafc691369da93bb12528ea580ed10ba6cd784dc665ba81610957e08e7b3caa4e1e6171705668197d0dcd08d6b0ae8812e966b2a9f06fa696e8aaf9b78ad99d2684cb43d089415bbe65bea3681c8fa1eaf9c8b04caa623b258305c19251d9945d2ebfdeee37b0d28aedca772bd3c762ddd806db59e20ce8166cb430856c0c1988b2aa13004a0ecd20e0460bab7b90826c74b120c1c098b02671c652d627bc998cb6e3ffb7fdba41142082164ef2de5de01340b260beb0a9a65282f263eb3f0075a81b9389388bf2aecb12a54a242265588f9528f28c1e08931c6f86901da2c4a5a708b18600fa6a33234052a0fe73c16ab53b6abb91dd655653b9d1d79e3e7250228db4d1dea1dad683d1dea1d63d48078af5a803d98d01428a53dc65885a840adcb533c635546c89bf5cba5a8bf78338f3a897a5f22e0953eadcf6a5fec599defecc58d97a7f5852c6d53d478e88bd9f463ad7ed98a39f9622df100ef7c89087863880a8597efc1c88abb0c315a0c922a6a5554b4027d872f06be18678d705a215bbc3d331fbbe7b45d77f723cda3b17ace38a75551b10af4c55a75d78fe3b391b9f724576cc0b04b1b7edadb2c9402faccd901aa43cdf3f12effc366079e91c701c0d3a1079491972fd23430971fa2696c5ce2b8cc2165f7806ebc7b56b8432797ed4e177b268f3d3a0473479893dbb1475bb88739d9629909e6b809e7203f4b40b9479e9b4811cbb619793eb6cbd7340df710699a1b2e471dc932cf5fffde67fcbd18305e7af1f75cfc49edd80db5447ffabb89a9256a4b40c45ce641dcf0d30d97b9e14922a5614b409c2ef3204e97917912fec9062193045ec6be36d1bf1b6a4b44c04bbf59232f46de866fa844da24aded3818451e06c99af7aaed64eefb6d2733c3cab01d17c3bed8ee256b3bd273615d644856b7c5f25cf94902ca222fb250069b3cdd2a4c5eabaf0b474ef7821707c7713870e078123ef77793a3963053359972e4c8f124f1a663f5bdeb30356ad480818781877912b6514bef462d3d5b02e2c60d1b7d1b7d1b4f129ff67454c85377a836ccc95bf50773f239e471c8dba843b4491ea6166993bc499e93bf215fa34a79f91eb2e3ae9cf29e0f1d5e8cec71e58dfa6e6cd47753a3be9b8b2461aafb7846fed5779fad793192b29439f96933e6e4bb9a2b3f93d094cc600d07559444989352be9ae62a0611e6fdee3356f772af3f9aec33b38f4dd42d4b717cd96705688b802c2533333333cb19399ec980480bd2b7b2efc550c7a1d807e6780811e6725e0c1b01e782f685b9cb56cc1da1135984f907331f432aa2a7c37b32d4e147a48a3e1ff23abad17d90b29d751f33f7e39c73be187ae2c564540ba26f2a8b24c9cd6bd37bf2a781e092e88321cc613b843922539ecd79910ab47b5372a08d0f124e2086db911e848f3b839cc2b20a9eb1fe745c88ddf7d17b56fdddaab20ae6de3196545e9a9aefea3a606e7cd7d250fb617e075e4a43c0bcb920841a8457f5623aebc29ed38fd3f3b1bdc337c5e5def14cfc53dc3e70510f5f000d4ede7b24d29b9284db91de6180f11f4c8741b9f094b126b157b127cc4149a54d503e9158c04b2be6e1e5153c0324a9344ddfc0cb9fe7830fa5ac72e17bafb51fde7bef9d6b455196ca8587ef9da482411941777aa5782352623c320491220c38022ee9c9820913b71f21fb5005c3f7ea650fe7d1501aed4ba088358f46f497f368462ff2685cfe1ed04f77a22102433608b8854e09092e5f7bdf0891a60921e07114065170a937cf04dfa22221cec009b7f27826f8161f17fee00941c8bcd3ee783190c7012e8b9e099e56d333c18bea8b6782df6afc8e1f2e6b35c86f7c400da4371ee699e62bedb13ea1e9b8f335d30722ef07f4c74d1f98c3a1d4a50644c82604cc9d7423c522f30d51336d8d06042767b3795cbfc3b677947445efbafceaf9b0b0e6f860040a7198ebc3168f6b2860ab92756e7cb7b81c84de6a3e23a88bb9745d564bd4ad1eb520f45e8f9a90792bccca17c3afe1cb7612b8123e0e5936be981a9e8056dfcba17a0ddb9a1f48ec8f86383e50474ed53c7f9ead034ef747cfc6227c1c92f6bd1858c3333f94681a5f4a2e0e35210d509ef06030989de41ae875b577ef277b0f00f73daba68dbc18d8c43335e047660a5c137e847e4000b05df5382cd4bf10d1ea420b9b40125048c5c22a98b300cc60940274d2e3d492880f038ce410116208244caa401ea8c44c473bd8a4a12664bb3f72ec9034d0f8acaab95df343074722713074e444073535dda307a90d506ef7276800ebf8ea83b0c73b7adff50e2d658e5f5b4b22bd8f98631273dcd1775a49b4e99df5aa551b28fde486424a15281da519a6dc780628376ab7a37da8c528e3953f366b27a968757ac62e9e75fa7d7522471f9d121be5a7477d4e22d1363d9feabd670d54b834c29ec27beff2e1c1bce703c63b7ef1ae49efa28b77d2e5dd6cf18e1abdab5ade592cef2ed13b8c6eefb4fbb6ec1dcb7d5dcba8c57d2ed7c57d32debdb8ef1d2b552a62a92da3162e2e48304a2f2f861faa315e0c5fab3266bc5a1a30356cdc78317c19956b133394542afa7cb03c1f30ce6f193d1fa4f35bb8b820c128bd3c1ff4fc1832663c1fdaf9aff6f980793e6cdce04c8f46c6bb5b03d22f2f2f2f2f316a75619916daa888a565d4c205e9050cabaa2f2f069eaa315e0cfcac3266bc3e530c3945fe94d8cac011c0c0e408606872df11c01083fbdaf2d072afdb55f761b06550412ebdd47f770873b002ca32a804ec814b6013c8029e79103a7121cc2a36c233dd6988235004abfa6e122820c5e5db3d2b30093c175e78061cd15a10be41de1296b8d5b90a41041b82672a5b65efd11c6187a8478040ab770fc80873f0082b417e275722cc412347869095dd914266341b21efb44240223c23ed13daa3f501a769345bb3c3a987cf08cec034e38a4ae4bae3aee2c7f81863638d35162fdec18bb77ed5773b46aa76d57dd6e6c45c5f07733d640a9c2976e0ee1a217288d434293a09c2ed7edff10755aa1f7905f908a909290a5213c20beb7b5c7ca2aade85f1cdf0bbba7dabfbb4b6612510d2581f1150fe3b6f22a0d4855dd5ac3f2def7e8b6d2bc2c1400ff80714f645af8a56ce2a4e175d5593e7794617f30a897e4457cc2a0282f13afc10f688558decc05f970fe683f96098eda03d421eb1731d61aeaf8ae4dab148fa2c4b3438a5e8a7aaaa2af4d334d0093d82b9fe559158d61522201f511551505f9405cfb87c3e86871088672084160241f80381a093a67971d233db55187472d98ed4241e173c17d5775d2a0e066ef04cefb6a83818e8c133bd1babf6331f50bce88a1bdccd76afcaedaa56be3a7c1110cfb06db6d57d57f483054b8a25c53a7c34386dea5b96056f5504bc1652b63bf28642f62fa63503c457afb8ce4b99c66c13019d972b29d6174842a2e46674c9a29f2a540464455730d75b08e8bbe9443fd7b239a3cf0aadc0691a980598062c90e1767be176bf98f6f199420a15534457fc545888aadce63e0621648c5903026ff1b4a9dfb5f458da1f67d631583726e8e82cef5864f07305d33c88c56d58e536cce2f679c9edc75cd7a2c46d9627b72ddbb16071fb2e94403b1626b7df2c5525ea6e79476bfeffa3fa4e3c4b9828d1637d368e0182124451051a7e8c549c6403ccccb029bd153f72ca18639c314e1dccd54ce9e3f00f6bc31c1b286483096ef79f980286529a929bfcb0e14e3d708614e99e3272139ee9f7f989133c0333d0310b5e11f042eec5f4109a7b98895164284d85abaaaa3ae9e06a6a48cd038632dc5b753301ab18be7a347c79aa3953bad94af95567eafc7acad73e3007e37befe13027dff1fbd57b6f078eb68a6dc0e2ac2eac05d805254341777794289882822150d99c7352150bae260f3aa18926a270421354c026ac709f139ae0c2ddb66da314053f4d581959f739418a24606da20df731371a8d462d5a34610d52c8fb9c90822368a1f762deb10f600d75d0ee7b0d9e291e0106e1f2df833bf011330d08a44228610007a83375ec9ad7652d999205165cd67c3283188050a25c71f9508ac78756006258c5652c2e43861c9a5308518401cc553aaf00e54208e16329108704491d9b401e6bc45c892222821e9c1c262efc102186608513177e8767783c70d33d2ca0cf10b00086db3d2b584f093a004f4d196113d803792a89424a22dd9b6e9a7783d326785341281307d883e9a7041a20cfc4da8512459448854891a6a16de257b40b57561cb8f2b3a769322b6d57b1edb6dbcd9e2badbc1829d3f04cf2928907ae9c4930991608bec1aca4d226a95d29022aa57c3381ca1b29e529cf4c9973ceab563c6d92b76ac5249ee7ca57499cc4f37cf0b8f215cff3c157564d5c592d716506483f91650eb007d3c59e2b4fe3092cd87cdd2ece15d0be5dcca4468378867a3c37d182e8734f9be4fb09f4cf07bc7c7d3ef8320cb708be45f0edce4bbc1879d680489e2d033432b17109f7449ecba7e00e9c80042a97c49c94db12b1218b01eb60249410fe74e1e9412aa59452eac4ebc44b29a59597a9aac36f7e36ba80ce27e2b6047defa88f8c4231ce6afa715156d7df5ff8d68fc85c574498eb0a09c4302aa90083787e245cc2e408243d4e3c8132b8f0d494457806466100c4e2c25987b03b69a0ccd13e5175c51c0db202f5896c70f284fbac800489c816897828828061c00112786e28c0c3232d1214b8e90820e10927ccc0638627210b564cf58c52c6d91457f09a3c904731b4868d02147ea340e424e494b32265d625e7d48034655d58a685366a5615165a50722febda3040e13186af2d2ab85211ca4257873420b1ca121d1b95a251e4c8c22dd845e4222391ac6a84c1286d17a0f0b3ce60f976011611dd5ab04c0b6d54946949701cda9664a25265d14859774659a29c211a451c5962de5b5a70f7c58d66275176a565449390e3360e11b3bc2af8f66129e7b52909f7c6ed432db49022164cab008592ab8e32ca6cb68cb329fbdab459a063b65980c257546c26652f2f3f4e3162c8983143527177f8b29dda1235e2bb63dfb8e2beb34f8999b4b8d0892ec330dbc1dc3e7747bada66895fa08cc8bd349c0c53c30696957854cd1855a3aace1a1df78daa2dc62b0629236552da987386ad6e5c99dbb751afae44ddedf669c8382f5236e3a36a5b12b242e16d5b3564ed81ba5645cd2bcee07abc2bedc0dc8f4aabd263ee5a5b056a4803d2d49d37d2e8b6dd91060d18981a92fb466d6d898ab22c8d8cdef88872d48d1b1ca72d418fc3ba0f66c2d4b0b836e15862ca1aa4ec064771b0b6c40fd696b8c1ba913d2dda6e881bcb007477da860624f28d8b6b138e1cad83636e9039ede081c364619973fa601d7e04400003b0b93704d8219b4078e0a107ee0127480184f8608003fc903381980848808c18311b0528765d52f2b3ec7b319dbc1328f6bc3aee25efac1d77af77d5bbdee7b6ead380bc57ddaa15550a122b1e1ea06b3d5ebed1faab1d57b9d63159758668db2901c23df2828075d68d2f05817ded66f7baf1cd575c0bca1bb9c7b5e4bcb2ab38c4bd1eab752b5967bcefaa3bf1c6d831bea305afacd6754929653377ddf8a909e92b576295cd9e1cc547ca14d9849df0138612ad300f33e19ea6f20314c4308a8f942990f6adb765bda3d629aa7647b8caed5b4cacbae4bec3be3e1fadcb1241ddeaca57575a23daa6a963160ba1ae5cb96dddb653d4ee49b9547784ea67e5be338eec4d11698e781fd491c51b6446a7484d19abee68ca260e7ae560d1118a095d534776c3ebc34723735c31c7fc83f8c937c85c3387199849233305c0e394694b9c34a25976050786af77308f89c3eca1238719b65b121b0f85afe971dfb32b4bd04e87c5236b1c7a502d094b7360a6a16a6ab40a50f848017025d4061ae3679535f331d2810d1466310aa581c287b2a0f058680d145e0d149e092ea486b6550f96dba134cc59330140a3cd61ce50b70ffb70668667683420dd35d2d4648f39be7c401de0997bef976eda3bf7bd6b97dd96524a29a5ac47b2db2fd9851c84a4addb6ec7102680ee286f87c4ad56a896849604859f2aa0f011fad08048db1921dd3e0f8fbcf13e2d08e4e1b9efb1b2cf95f1f2bb72a583f769420670fbdde808e9f601a001e9c83e58871fd9eb3f9ee9dee1b32b149e5febf0230095851b15b1b4bc376ae1e242c68c57db2387191ad8148e60093b5091d3a67ec65c8f9c98e1d4dddf81695ebf8667f8dd3f3d1fd40ab3258d968d31c61ecc750efded0394cfb1fbdddddd1de56c6963b7a8a75580f9fca8e1814b98f46709fadd0b02ea810c8300bf23839c8787270ad6655596755dd76555d6a37561a76cf718438f9162d465df594b3c649fe73b1faaa56aaba5ca06d10f9582e06fe76fd9abda37ab4f4300b5b44d540d55487a31d4ad53d53a665d56157bb0f798e38b81dbeb17a17cdd163ec9fc8480b0bb5f9117f32a282191c64e530d3e51528973c6eeeeeeeeeefe944478a6ab8a084165a71e35449e10afc8f381fd41717dc905b81bed1778b58409e946fb05b89bd0df690bcbc9878af79670fb1d0ef7fdc7a339b5a9ef0394e12981cb11decac21703cf97df4f6c6fa9359ee97ab59da55e0f5526dc4d8874133a13ee66cbe15e424e4d43a44d50871d28d3275511d516348602ae2bfb109d1656858fbbac09dcea7dbd85f0c5ec7b31d7736cce102543200f12e6e012de813a44e0c9f4db89dbfd0795f8f1318117d347bc98eec7c1cb6e02f1c69c213916468bf73df3b9f872011418a023a420e1191e2343ec40264c38814a34e94f19391faa9891affa7194ebaac2aeba04de5ce037f2e510cf13b833be98783d2ede398fd33446802a208be3f238c085374222019d6e87c4831c822f86df7187c485877c23eb8e579f89b9269168077bdc4e097c1c7a2f86813465ab8a348a502ad0a38636f028214a8c213847d1733e5a9837cff10cc330a7e3727f1c84e160a7e3d29f8c3073dfaf249c7e7e753ed734d4d9e65d9ee09b229d6c9eb4dd937282b6ed12f877057b272a1f14df0e1c455152b40f7c02250a2955fc5041059e921c91226f0a1a236d82efd1fd18bd7b69f16ec4b954d882a5e58fbeebcb874f07c8022883f19fed8a0801024a84390899340ba0911c6eb11d89c57694a953c80252c876b4fbccccd45b0ac11cfce137b343989301b42c7c6204caf173729883b6835114018944698f3c2a62bc75c0a3e20e89239a913d9d7c7e74d5ed2a1277bf1573500b5f5ea0d51228a839bbdf7bcf76fdca76f729733c22310761bc364c710eeffcc96a88f389db992e7c67baef598f9a22697af572f782a9631042a841388539ab08d883e9dac7ba1d85904a11404497873e4dc34d3c537c7cc2841b53706314fd6950988b1d0573b1a3700ef14ba0c03286c23710c18d1c05cf881ecf5178262405cf6c3c431fcf55f00ccbe3d94aacc1d38199803231a834cd8ca6a98f4c9af458617263100f377931f1987cf482dce4f9d0f85d6c73f9f6ee745ddcc5311955c6692d09e13f462d01f1e2325e9236881797510a22c6d37e6034f4dc1dbe5cca612efedd215568854f47a9bea8af4d10004244f562f8b21eb51e9a401daa1b8fc513d08ea17094a6c1a2e5f16cc5e8f17c05cf00f1ccf578fe793eaac73394a669283e3c85892b41ea25348b1b5bde71951b47ef580b24180ca59db42996fe6e6054187ff1205e5eb249ea5ffea2fee549ec614858fa8b0751fa0bfbe249fe52102f5e7ac92699f117a4180f35f9970aa362f3496adc64e3376efa901a374d3bc4c6253d490d1bf1c587d4f88b93ec101b2ffd69fda4695e58d35fd824385e7afc4b4d62e33087519340219fa4c66198fee2434c7f716887e078e91da5695e9a2609f71b8fc761aa34fef22134ec4b3cb443386bd3a6f81bb6a1b429d6388c0fa9711896c6615cda21360e6393c0fce5add5b88d77271bb5068dc3f8101a87716887c0fce5988d5a82ff4d8d1ab77104c4dbb048a87d5de3ef06a6068d77d4460d1a87796458c1d0a8af8f9c9ed6c7c18b6f274d537a7c3fe98ee2f9a01ea9dbe25d4bd1cca12ec92582bad56d18b275ac926ba0593ce65275e09b74175b0ac227bd073ec93ee65cb83c742577bb4bdd0e8b90b77b543a98811b99b8b1caaaf62a988ba795a73017bf559642546bfc8cca54da141fa3b24f9be26d8dffcf8d9751819a86ad30135007aec193896fc24c7a6e3c132b3736cf8df106ccc48d74ab6e8cdcf6d68070c7a8da502b80920be367c511caf1d7343afe288aa2264551dc6db43adc25673b2597b7a709a111b9ca7f1ad3b894e71cee3aea735837c83c4687cd71838db19ced2a1db6da8ee6b01de9f665bbdbcd768d77edec678c56874fe3f29299f9382ecfc99cd8c5f3b7db38571d79be4a9cdcce7ec3718b83e36ed3a64ab94ae3d50d1ab7513b2482ae7d8ddae55cfb4a0b32baf1184cadafefb6bb1880ea81a9ef624f9b9346ede0a5711c644e3b789cc62d46e32e346c575d1a6f9ecb53a8fc000559b11204f443650a3be12750a2f84891e213050a3f61274156988799504db88995201f2953a8fc0001fd509922c507f6c026d0097c02853a0e7d1e3b64ba83ac401ec80432813c56821ed089e251d314455194edf8f63834dfe5364da3becb562eb5b99c064fa16cf73420d642bad923a77b0dc85fabce6d2948cbedb738e074a5d5713955e22bb9a1d8163144e63c5e0402de0de469137c11f0446c47c0bb399d874582c48865d271976a1c785ca6834c64fe6e665c3081be9b1d7f3727fbda2463dfa69f69fb87adcbbbba7cc7669b3491db5d36974f1a50be8c1915883527334551efc9f88b31c618638c31c61863bca48ceb3c2d19968c0a2f5bd88c0a655c312a10f9185f6a07ef0b45512f2fbdd8aeba2f9f5dbbc8f3031444c5ca14293ecfe749e9eeee97a3288a4a9129527c6c4e7d99e613efe01d95f9bdc9a74ad65ffab112415948dbeec80bef0bfb3007ef0b64299887993007ffa2b212dc539909e65c2c2f610ebe450d898136c90e4387a3437876e20ccff2b6a3da524b415a8ebde54aee9ba694a3e4063e69135c0205d6dd6d5956cd1d3d741746a033a7398fe3f00e3e51f21da7f7e777d45395a9ef7d3bc47a4eec4f6bc1de622bbc38d4b7c93a8f6a59d14b39333316dec8bc1404bc9139bc91b1304a9ba0929b1ecf415473b38b34212c2c38c207de0d6517499982a5602e8b1acca0159ec92cec71abd3e9fdf999caa366155aa98205cddec1a00b839883cffa49f32cc103376b27ccc166017390a3f0cf95b5e36ec753a014f0ec03cf553c1fef764cc585399cdea3ca503f1dd4fcd387410dadc09fe0658298baaa48c127569a6aeae7c70748cae9359c0f55c578c11e22fa46dbf11fa5e1bc4bd91d79e9334dc804ae5cb932851ea3d9a9d2b0a2093e3732f5ddc826c00bcff2f37cf4a0d476dc1d395dc11c044ac275280b81988330be294515a11a4acea5ba79a8eed9211174a9ee81506e67bd77e67c8cdbb177ab6fb574bdba57d7ee74290e87caa3ee38d5d726994ad9eddd3c39dddd71364a7a728650c23345e627ca23e270f9cae6f671a848f85cea3c76d4d727992d8bf773ad53a187cef5f52b117db9292ef5abdbd7ac4cd334212d60000518dcec942d1db3a5cbb214d5ad8222ff4099fbb0141c650851823ada8ead5cf81f28c3b6abe0cf6df1b9816107bed0a1c36983251eecb17a3ad10b1ac333f5ad4a240a7a310d0178f9b306f0ca20faeb245aa1aa7ea70d6355b52c6b47ca8be75a8fb58b3c3f404154ac4c91e2f37ca474132addcd9da8d44c91c23e9665512932458a0f6c62436b145171f2a43c8ce73e2bb7ba4559d9ab4a1141ddca1231235a7647de18b245008925511551152b9f53d079895355f459d64f3aef9ecff5f8eb57dd81b97e280c94fa45c51a822e1405b1f088acf0cca3620db76359729b87ebd45b2a84027ddad4dd5d6155f51edeadac8b2450ecba2ed26b346e1a51509bfa1525917eaeb21d773ad5b4d5fd2591670a9abd9dd063ef694bd1edd545414d037b7ace9d7a4441b70f7b9aa6aa2825917e8eb3de9dac2cbeab1159a9a220e6fad5d54455b2eb845aaca72756163e6951cff3d1e3f6bc4def13658680be9fc651326f070125d7f5adfa806af79d8ab7300bc3dec3bb987591046a84923b3f77a0aa28c88aa80a733d04dac19e2027b127f6b040c9f8c508a723a72327aec2a92652efbd8a8330be19dc418634de9dc903e6eb28c509638471421ce6c68a4cd932fbc1333f3a9b1b8f33b93bbb9a3bb3d064a93997f5adc24a551ce67ab079cdedfaf78367ba9c1bbb9cab05a1b72b72a3cecebcf271079ee96977e68557ae04b19911b386ab0b434716536bc0fa0fa63bc563cd4d513bf352b6eb6e19fb4da119aafb60201423459806f2c429e39c71ca0821d4a265001228a62cd726f81e1c8c9326bcf01852c11e8cc402c57efd1dc218cfd193adb94d51aa7522022cabb323b9aa1e3561609863861a10ef9960a45d6d4e91c21bed0e1308b42d69fe608aac424dd5ef992a18eefdaa9865cd6a5e170ccf3c4901335091851264a0a20c4ad02dc45a671193d7b4a8aaa2ac79c94c0b6d94728216b4806173ce89d52a627fd89c735a7f376653f8d92dba85b49ad9115712dd42715ed6ecddefbf3b63486a724adbed488c2b29728c8f9aede89cef6a1576354b7d9206a914e8008788c30d6e70831b3061a2052de020074cb4a00576a2852a3d55a26cefbdf7f8925a0c99f2834de8a92291cf87c040fb44246571e28b9d16933d680f6d55e858a4a3430d484b8c9b0c68c75dae69e8c90879754677793c037866f4782242f04ca9e5f1384d433a356a317a1ab4eae82e5a7cf4a70169317aa91a21af0ecb5d8e59c75c6af7ebe2525d9718efe875b98ccabd546cfeaa3ab2cefade03f56c27af57ddaf45711d61d8f8c25a27d98e745daa0b1797b6631e8c33971fa83927cbaf0aad4e0823ccc58f2a03988b6fa945988b960873713ea1d4523b038a1343a742a1889daac76c5671b03a5d40270d64ed7ea5ad6ec14b28792712911425e38b340db4c00f4e4ebc11092ea0e2c6184110b907092ec0429ce2640c979291448ad7f14862aa828a6720dca810a55194bd1e949b569d87ea8c6d0f86866e212d3b9655cc8eba92b690c6da01dec51eadc7c73f92a4ef8ad506026d292fe93c750a6a40a8c62abc30f6f0ac12ff511206a927ae8a45eb440ffd8a2cc6d956bb223e88ded8e1256aa95a5844da0d55886150a35a9c74d2ffe22e307442c71eaaa26f95c28b4477412b2a2eb71c7ba8b65c54bb2257f4cd9658be3d5462f9754c1369224da4d9128bc579f7faf550c8a67bab54fb767d3b46655ba57f5a10ec21db11f16b048c1bba0dd3dafd52914824b2259c772f1bfaf6d0b7d3db74a88aaed5eefa1b8d2e0a9d5e866a8be81895856acb9f7600786b177a8b75a1041ab23f8c2eb23aa36b56c7c545df9121bb23efc83ee648a72efe0ea376f1ba5c74a8057161237324fb98737964cec51aa0458bda21712b7ad1315a45b53a26331156854e2f6a61bb24b73a55511bc26c37ab2dab6cf6993db31dbcd5b7cd76d8acdbadba036fb555174aa03b7dabcf43ba136ff5ea3af5280fbba852d7fa3dd2ddb6635ba5acf110b29d921bbae8b46e9476a44b2163da43353b6f0f6d1fd116b6abe86d47baf42cb6236da72fd5f74cf4f49bed7ea9ed30ab43fd0a42d9ab7b1855457f9a08feba2e62b19d92cb72ad76bf5a88ceb8f4db5b36dbcd902123468c97975209068c172f4824172e5c5c5ab4188d5a5a585844224ab72d14d2b42cc3b0ebb22eb5eed6627b0b1dbda32ea5a48f6e5e7a1727b9b0ddbcdb47d4ddfe5c6c17eff6d15bd478e95b2a3da5b60bfd7d7b4bfdbb4d6b21160cb33aa25f414438ef528af115d5ecd7bbeb105072e9b1dac15b002557f4ad7645ee7651dddefd6ea7156a3cd087687d97d21e1faa1d123836b77bd76cf6d729b917bc14456ff5292ba4445057ae5cf9b93bf12a7152a4c585ff0b7e91c4a9eab5fb7d1deb8ebc902d10abd832bec8a5a48c7f937a35e39c8ff2d484d63e2e907eaeccaefd7a4e691e7bf6d2b45e40bb8aa7e26952a8ca2a81da249f55f9d3260b3c9aecf1ca574b9e8f784982f2849d5c593111d5adfada346311218c340d644255b649173281ad0501afdc6476c7334500dc78d8c38dbf62f5c30e7aa90f5940ce83318767729883d47c3732efcc1bab1ba46f8d98a3db96c52427dd2baea6546c1181086d88024626421ba6b81dcc7dd9ed381d0f07f86ec77d871a37336cc80c236c86d0c9fb7b244672214d037d2d0621a251137a80e892e853bd99d30703d351c14415322c2183132d1246eee608e5abe2e4360c6ad834b70f9b5aa92aa02b00c58e4d43a749ae674f02857c12ebd8a969058df75941f9be43e1b98f0a1a04d1dc47050da2dc26ddfd501468cf4943b4a9cf1a10ef46bba4214bed92b841274d538aa1f890450245b44342df2c92902dc5ed4828cb435772d35344a7ee63294aabca52a7882ce533ed86066afd3abffbb4c2097482b9beac02a734f481328a2694af59236dea03019580b08e7d8875cc4a3be47a664bb1a1cf940e52f1891a9027b0c7ce69226dea5b555a41a194c905ea643286060cfe4119a1945046c85a108e79624ef8f71e168c463d7a74f7782f0d1860347013187792483fc7f5e944c30c5f0cbc3ad834e7cc3c35a96acedb3c1fdae7efa369b144774ee14e2b42f36f0c773e2b3e6d9a9f224bed66df26e63951b6a3b9d7ab53b7aef9340d53cf6c47c3e35294bd148c4b1db31d89e552efeb52dc330f3b25b70a4966c23325eb45c079d9924551f689d0e77909f730cf126625e6afda53d5f782cebfaaeab658272f1fa5a4a8577dead4ad19f7fa5ca26ac2898b1c2464e099dec566dceb42645c9deb96855278e6fab422926bbdeb4b25b9d63bee2065bbeb9566d9ee7a759bee4b4999a2a38e5dab3ba0d461dc0efadc49d9d41d988301e3cec329ded3c107284f9eccbb1dc9096df24ceffa00a5e799dead605c1817c3aaea80eb56bf6a90eb5693ba35df1b98459cee10d7ad6037e376f2f338d4b43aec243445147e6ee0ca3ffdde7b0fbe634ffb81b70065de7b967f780b5006329064a0f818057b305b48abee035ec6a01d51ca5dc860562ddb298136ab951768f7a4e050e65a7b17d677435ca03ad7e5edb88c9bd9fb353fb24addc8033a42655648bc97bd4d4f685f2ae9249ea97e9e91f0a12e60f13a16658680a8fc237181c28bc33355ce10224214b91dbc1dcc019481769e095348249c1c29b7ffc233f3324106b7bb27e549e1600ea0ccbc6cac7e909788be62e3af53870fd5a7d96e9eb27d3bacaf653b48b5dde9fb82b01d889a5cecefb451c7b81a3d8d083e0494dc5802a2e5a30f69f9a8a31d323a5b248cc58b559aa66955d5c92e4d9bafaaa9e958cf3abed92906fa0c550c74adaa7a65af784336bebbecbc5685b487fe7826f4386a7994ed34dbc14d13725d2a3ea4f5b07db2f6ae46c5a9c54c0312a3edaaf8aa3a5f115f7195acea5c47e246fa78b567d433c6c2ba5651ab635533947a143dda8eef7591edf85a67a0ab4189125fd9aecade555a66fd7a57592d5e9a2d5dafac181fe3b5f3155087782d73a1040aa4693d881ead4e7cf64c54bd63b9a8a2a8772c5a8b5a89a8eb68d52f8aaaac6e7231ebb22ccbb2580b825928d3f115771e466df117d5e5a43aba8bda725a43737e9ba138b52dce0cb3d845efe245998ef6ed9df6ec5dcc325bca2efa7cdc02d4216210ca156176275e2c5efaf9d05dea6b538b2afa64f9a88aec4eb4b41eb0eb50bbbdd27ec82e86c56f96b7c03f94062414abbcd9bc597d57d3b49b658f7f31f216a00ef0c64328cd0c7431a8cd77d0c9eda2f68951b65402027ef420de5b2c003fb216786fb14a6e8c95921b77e2cd2c6f01ca4c0cdeaa4fbc57f5fd695d8cd252242a25217611827c8776872fbc4e5beec44b7ac429e39c71cac85fa0f15d0dff07cf5091022e74c9f379fcc197d5bbf0e728fb60204e19e78c53c6f77e6c5ecd7926be56ff9e89a5d4f89c9ee91a0f6fca8d39171e62d80c01f6606c1e7c95965d747b5cf36760ef13199253bd7b53aa43cb1d256589d821b7db01e76536961932ac9152989005162cc0220acb92c8cccc0ca3804941833c9ae33c1ff04de1358148f7fb11227b42f81ede85966bf807df45c0cb5cd340e63f228dd31d2461dc003bd1020f70c091480d39f8c3137b010950c0820c5190c1e70811c31737c050946081c3eeeefeabdc1683c21c943f6dda82fca1f22a2ccac5a2dc9e2d9c4e53983e92a9cdb41087bdb7fad66a86cd4a8246a0f31da57fa6fe55df3335654f7f1a90283f6577c33f9f2882abca6e892cce3e04cf746f8a8561d6610fcf1146a05cfe911d9e59e20496594384a80e8381ecc01cd4b16ed967b128aafe7eaaeaa7932a08a3a3e607d32cc99c5019c1e55b57c580eae5c5c0ecaa967d42d3805c16d2aab2315eaf4e3de319eb7287ec15736f7421ad2e67100ac6d40ab00783ed60b303e334cdfc7b56a53cf3515f92a4ac39c8639cedd003bd440c71db8e98934598939601cc49292fe995a496186c8e677a7878789278950bafbc8e1d726c9085f4b1411657feb8d2e7061e90efc8500875a5bc808fccdfc34e955a81122e30059f472b18344f15094cc10948c0a4e7e674998a04be80091cdcf038f6e8a9ca9c648e0409580118b4e066c791605103d0166e4ee7519120d122cacdc942313a920bc49b1d168a962331e2b991b150d0213a602ee9543da203888bd29f1643c69f36e3064983857bf9d380e8b80dcb731478777cd618b4c32e813f565cea32efcb26d0df1ed2f8c97210656ddf503deaf2a70181711b8ef96c9a991dafb9550fcb51686c356371b0241ef5ddeca042c50a3c76c4788e025f94537d9be6ac2e5aac70dcc051dd0dc80d34580ae6d8877380cfc14231a7a0db31cce264fab41dfb4cc58162a7faa2c0f081ef253d4e443955a7edae773ddd682d5b65b5cb717bd68060c7b00ae94edf20f2ca952b4db8397a5e1a6f4d88ecee8e5553f5c8e956e6b29a1aed2cb7ed59769bceea557d3b262d991a024afaa11c36dfedc890f6ae6fabdde94ebb5d7fda46aa165e61032b1e7c3c290d740c1776e1ce1ad08d7bb18f39aef20f5fa1a3321650e8cb4b1bbcdbb65dce6f9b3d55e5b7fa2edb6f9d23d278cc41839b5415a5ef6140683cd647a36d472af1795ce6542d95e499faa996a40582c7655e621b040ffb1d3fbd346d103b7efa0e7b3ad48044fbfa54ab366d5dada701c9518f9c2e8d6ac4bc3a95877a96faae55c76d987998a288a0749c2b1103b88e9daee486657efa10999f4afd1d941d22536a5bc490d3775824278b80774344c62ab9998f8a85a2fabba1ce55a76b647e0fefb23d42ba91bf616fec57bdae757a6dfaaa3a6ed5d7ada386ab27e674d89aa376efe7b58a8c60b52391b81e21dd192f96d319b9dd43e4f69fed86b8ddddd4668f358ded08e9d2c068d0806a0f1dbb512b6b1ad71d7963d4b4738dcba91ae22c608fcbb57723e3389c5d3f711c8359bd0dc7d40ec75d42dbcc11ba36ad0a6197b5c9d8e1b8cbb91a016f7dbd0de3a8375498c73a735498b571a471ae95af909643ab42d865f136ed2ba451216bf0c65497dfa8efe2a82e8dfaee0d0c0f39c68267187620680d5020d54df894c603256a6173a9eedb708f2b3a5577e6cd58a63e3675ac04f39f1a9c00055d78c682abf0f0cca3420d5694e826b004375d2fb9b0bbeeb9308302e832d556562bcc1fbdc1c51cd3aee33afe1b9ee38f67ea71e8c463b152e7da344e51af41f00c04b9ca85f5b225eb7c59b2be7dc61863b4256ba326cbd7f8769e8f46ccb8105072657753251cea5bede46de85be8b376f1c645c57a85e2af23a71b7f5627f4cdead4533f72eaa23d72ba21fb98d3f1b69d3d8e1c344e551d94ed6ec891437bd5da31ec1863f13cb178eaacd92ec9ccb01fdeb45d85750c66635ec5dc86b11a13b9b7edfaa6ba032fd6d82bcc744c9e0ba957a8b44c97b44d2d999a190000000aa314002028140e874422b16838a40b7bcd0714000f8da64a78509cc74990c21052c62862880120220020003092844900ea4399496c944bc457d2b1f178d0e5c72295841fae51bcf0c74a5870d860b6be9c31da347d7bbded82a98d760173bca72d0978b72adfd0f008bc343c0017163fa8e118862e9433f8678669db4aab87535a7de60e50d01f0b2833ff06fb9f288c74becfb345adcbb64f7346b4951bebd515c3525f88d6407f9ec5b8fcb8883c1bb70cf6139f4f25fb31106ca8ad1225a6781158f6535a490e77bfcc7ec8e733dee14dd6239b8a69ec094cbff527759e015f8f9ddca03015590db6ebe18c4a7bbf012a25bea9d3d08f4bfa3ec86ec1f6916a792f9e756af0c029facc100d861c4e26dee0ef31de99e92d0da06848c7bf5713f5062b858385ca54a707ef6ef00a46b3b81ead45e414904138f89875c15bd9b621a383c65226f0d629c3c1363222ff03589c07a096023697a8784fbf821fc9391b5be99ae22b3220c0852f85900513f0d348d2c8b44537fd515b2b91cc5e715d48116e887583c1606a733ba5bbbd9960abb3e7a1d22d91b39e35d358a6328a19b9577aaf930ba0afb78a3b77aa89235678f67fb9c0b3fedc5b7dc2344110058efc8e83947d0e6a359eab5d31141c54e68710608198dfbfe3df7532d0824e411f844796a2ec26659cae75c384b109509d253642dde8837ec1ca2bc074e3d06ce5ade169f3d8766501d03b8c0887a90a1f713355c21a290a173e887e587f0508084e24d8f75cba96453a60f9481f8ef4813e24299b446b2860fb95ae6951025a115c890d7ad531cb9ad181e5ace45e8abd391549b7aef14784a7506f6f051fc82d9625afb30104f8b356573510657d9786f6ad91114ed96a27706f37bbfc73d38f8daad54872adb2df5e939ab0de7ce276f0723a93a3c5eff8626f547646321ab9ba5e9509e0f3abe4917038cfa19f05765eff49c23c199401389d6d441f1ee393bf73b4abdd6179ae8f44ce59868cc14fe92eda1110636f1808ea053cca28ec29265f2feafa3e0d82f4c47523e6397ab0d3e00838c4dd01410e856eb821c90b031b3b7092852bc8be4dd1761f19d221dc824b6f506959f35f757f665260d0c940a4a2c03b56a053a004e152c8901321d25ff34a162015686eb626946cea139d349379091612e0333281138f468801c8012f1938fc20fced7eb61be5d0b3eb19d812d4901f99e280361ea07e566879589094fd534f85f333c06c5b1cd2833554d68b09a09b0a36135ae9bb070169d18767301b46ee1cace452722ce318e669c3148196977fdc50287eef7fcd1ca18ea1533e88742ead7a0a561cf8d68a191b5e8e68883a8abcc3eb18a891d5c421fe9088405f348805740adefcd95148a3923333439d6c1c73f845ae669059c6ab0aba9df4298244b30525da43b08697355c4d9dac92fc42dcd5caa3b34aba631b1888f783d3dabe64cd56a8345223fa7c6c3a558bd18c3553544275e120d39b4452d4b0d0c54ec342dfa12f8cfb50e8835fc6f597b7a70df79a6a6f28fee3dbb0d778c84dde44e9d81e9874923b22f589dc7fea2d7c53d8651eb593c47b6aab66c1d62a42b602197f19d87b79f4f75b9ff82262b10b3aea648102a21716f77fed04956034e84669657c2e1999ac98ae04ec83d2cc518b1fc05bfe6e039bbc0816ac2b8ea8d027dd82cb2431a1315be6932ed1a86b24d0a74e93b3f00d4062d62b179c6e83acdda0213948a4fa377df06ed779ce5c7484e6b3fe6a61a7a773e928696eb9e458a288cd1b930eb0d30bf22140e64f7416e4e691d040be64bb5c46b80e382be0fad81711f0714d484139e14c5c25c154f384847cb4d808954ae886742548aa274520234ae180c86560a5844259c75fa217bc556d53b014badb71258bda4ab463d4d3939f19fc64ce8a8c2963d770229063ef927ef61f9e749a1c6e82973067a76821358fe02f1b0f1c6f4d3f253e788d652c323734bc04007488eb4a41e708a6b3bc9a8525db524962567fc2c8560ee942f5d2c2c9e8fedda502e4575f1cc7c247d81b2eb0166be0e80947bea4418bb1a64f176d53717760a15bcab9766fd45726f294edb896107d2742e07f48228c850cc4a33c7e03b9e516127467a2a453c743d2f51b647b12d8a37d87c346c32083dc59a58bab2e1cdf01f5d9a0c4991550fb02faf9a4a248c7976b421bc28875e5718de4426719fcc3329bdaf368cf98d966ebe8508156fdf20bb4abd4e21ec98de1cfa9d9a88211c4300ec4e5085406cb944ecffcff67d6a7e3f33cc3cb4cb4dabac626eaf192f38cc112034d810a9b351bde0301cf03e2bc7ab46c1fccf11af4084f1247f65e70405492ea9110ffdb28a8cae4084e3d42b24daf996c524be3f7b3bf926d518f36e00f342e6c4ea7edfc828f2506b7cb518fd6d85a7bce8592ed146bc6d18dde650c960fac42efa290d6f5ea238e998f381a30ea4992d11949eed56b5ede6aac7c932298459530b62698442c1d6530ed072231d2e3cc594b89b2d1aec6a558bed6ff3db05361e95f923619f164c1147b7099cb42296d5e03ebdc000294322d87f9d3dce1be86e1016d121f61f37639224f65a616ee3fc0ab0c4238199896b035a4928c82dabacad0f658c9ded8a08d902b225b00062e857eaba07065ab4bc61180ec2edd274c3ac89ab3781732665c1a7d260dc1a16af796f302d8bbc0f4cf59f46b24f1f242b0c130b2507870461824664ee84578aa1c8ed612fb8ef0e930b54194fb6c9b59373bb7dc5169413f12ab5e6c20076ec0c72425903e21aa7def4a127e2aef5f4765180f0b236cc70e92852cc99db3a696c41fd5ffc4d899f90224a94881c581241a41882faa948511fa5e45f5530f892143404704b2a9d24e2754e19b72b1d9d29db65455934f32d28973bb5cb3315d0d6a7135f75338a74ee37d1525c79158565b489c5391d090d982e855bb7084e03b817f896fae9d04ab008c6aabc5e883f853e3eccf3e84b9a4050028ac39261ac639d4a73e5d5c0d2c5101c7d93d42e762e7e7825b1c6ca85b64e5a47aea332f4a96b51e7b4048afb6751140d0480933834827cf2776fe31ff8f5aec6b7120efa45a26d5b0f12d616291157ce7fd2db1f0f3ad568a45437aa0798630fa9847f1c72d1bfe755c68c1564444ab5104a04dcf9ca281a2f414f2959e223b2f74deea541042719d5f7186209542912b40138518d070cf4d33d0c305adb1912b788646f21e12bc6a8fb51cc736181b29af1b24a05a5792a93b8f8554d5ed95307e281f572ff08d532dfcea31c7c473018797d5222933917b709d199d98b9c4d21e8cb92cb6ea548b23db317326918aa622a37b31c7a4191790f9ef8ba271ac3816b592910b35d935a3cebe3ceb3d12826371a6e1a6d82a085778810693bcdc468ab50749ab1eb887410764851c0c401eb9b2c753a536dbc15247245685ba6a155017d0261d917dde261b540b55b13986ea155276aff4ea763438ad0ba82448613206e31dc1983640fe2e6375bbf08a11e8e2788a434845353cc8ca912f78896fcc24e8a5481b2082ab71894a3acda475375563f2f5aa512b1e0ef1c4a19ccf3e32ed2ebdcdae3c9974f4d4f04007fd4f2b2465ab787d27ee74e64e36eac7aa8c89df76d84f8d37f1b22c16805fdcd3c8f121572ea80c18887dfae946c8383a39f4ff0a4c4ef0e66751d3e45950dd16e4114d16be2d40a9b122ba48998497f56715827df959e04edffb3a529e50925589a6677dbcb5563053de6dc9598a3b8ad81d4ed4b3a86fe8a9d7f0b871bdf40ede070b5930bd5c7182f4c14213f99911f960a168fbb7c1b4d00ba8c891aacab30e657fa636465570cf99c49d298aa0bf721f896f4535b84cf1ee7a376e2407b8e2b0bf437be150926322e6454b06e2e3d8a9a80677fc026a32e6f4e3a7cab198e62599b0cbc0a23b5cc75d152eec5dd708dda704281349d24e33c76e7d062ab8aa9baa4df337cbd85f89f4fd95b6bff1aba551aca2d0bfc821e8a4ca36bbf61dbdc53618d14f4ead16643eb37b10f86c0f55e402a140e8f7e38ab224b85d796989b0e733599ce913cdeff4a43815020ef4f25b9ceb189e85c1cd71485c3b0b9d0c66fe4ff9a2dc323e33e305cd71bc8e56a38032048e6e26e2efdfe328d2021d3d3313d82bcc7df8c39d4531e8e03ffc81b72d7ab056feea826ee96c303d260d4f1a77a3e28235d0cc8e6be065bdd268ec1130ec526b334e046277cb4e1733bf0b743b9ead684991489c167b27d84d783be27924643bd08789e0592be466a8cc416e07709fd31349b7c8f2785cdf4e40dd5eeff2a4dc325da49711c62a0d8f17774fd9aa8cd40f48277aaad0bd6d1e67d9cb3b6a912ef3e98c0a0811a768a2d30314cc467e0c924452a87ce7ff4d1dfb0a134b8915d44c32a86021ac5af30462ca6c9dff5873544781562c02f2f66d676887c32b5d4768a9a166151dc6f880d3f9e9c21ea89d810efd03012d307adf5f84084a2207a60e964fa7210425e9cbddf766e118ef8222f438513d8dd0cac58db54fc216d3e1ee93f00e029f723ff32c0c73a29a2521cdcbe557f70d9968de17b21141a0f6b257884a90b55653d9c3481300d5ab904fbf5753a7367e6292753ad48006fb48b0fc5e8412d7d22fe7ad2bbdc9a8677dcf00773ddb7f04a8f5fd7fcf17662ad16595f9f09245c55a2952c0b5d2405aaa264f7cb87b040bd4bdd128be17ed0b9457be40862e5de3d2ee7fd0e4eeeb6d782e4009376006a642192bcd6bc4cd78cb8cebe18cb7459f977c28053a2bef4931d1d5d1f6734144407e34ce928cbea0776107cc36b79e8f651f617ccbf70c812f6a5121a78277b054a0e91a443b53eae09c31185cc5cfea9f6616bbad23fe76a88e6f6f074a84ac100421e442b5f805f2b7b156d30c3124b633c659db064ad858aea83349fb0232b7610bcd0ecb1ef4fbbf46e034c416f7e3f73a554b2d5c698ddfde920d7bd8abd532d0dcdeeefbe997ec23632028f9e075bd66949756714e22a95af44acbcf3dfaf36123655ab20f30e490e50ae27ff74512d9c3145f76c3d5917d92070775d59cdf8315d69c56fc837c452877748939301e79922e3720b563233e42477da8f2558a432351fa0e24543991e2070943d224fd67adb15e3ef4bedf6ed0cb1b8af15947b299cdeb4f89a33bc4d0b72dc7ec02817de53819741ef860bd595d3d0facb1ba39309374e245014a5da55c75574051cc5946e11d15cde863156694574cb96546e6440863c1080cdcf367b5cfab88dcecd6bbdc2ab7de28853fe1361b8f1de94f42ed0bc602e5964f188f0b5fa8c2dc09f3c85e758e60d29dfc4b1cc6d372af63b51551f391212d80643250215161947e2dedf9aff531b0eef16be5dfb37edf8b30c8ef2e46976bd0f103ef62899b8d03fe5fbe7af1dfe21739dfa4a6b01e9210bca0be2a5bdb66a3d230033120f501f92333224d2b78a3167dab89fff22daa179bfc027500d00120dc0e08491c520ab3433188c0013b2a53d66b553ebee52d385d45e385a43a1760aa1a68de253239a25f7c98cf21babc8e521ce211280a5ec0bcda4d56679e89efe7ad246e9375fe4c3fae5613ae1461f6a7097f838a6c3f6b88968c13f48974edcb94609c45e6cc5a7bc499a80862806b42e8adb4d97203af9be064a39d5ffb96deb838e65eb37e40e78e69186ab19a8dd60aa9cdf3be29c6d3b769d336af97595a076af38b8f9cb3aafc28abe4e4c75bfa1e82bad475db681e6ea32d559e53831d9abe4e8ea5390b99c434df198e481e48538ad3cd650aef95c236663ffbea3cc0b61100690ab8b62b2992e0bca700a6632004c00bb55daee5e3a4d521274d653969f597d3fd5666ce496b358f685fd405e817d50fd1a27dc9e44dfcce59db1669176b747c292232efa4c9ad5afc1231a434f4a1fb49b8197e7a0850d44cc43f84646b69679e58384cb10c76fda8410a4f4d23db8b6758f47330f611b0233a0e4e6a60299ac072ef3ee66166230cea016f4e5e340efbf054bee2a4182259a23f9e237399df0f9df00a2f9b949f74fdc4c0d2d0f2a13b6328a5c906dc0b4a17c03c9aecc59b54842274f3b41383a6b3292a1d04535928ab6287bc1745d4239e5b7f9ef49a34cedabb5b415ea0380e381c82867de3d55e5e78f23baaa584aa0629d2117546f99cc492379e6c033c57aa04406996ff5dc56a886624e8c52ec2fa0055416365769ab6c5a1159864c41ec953e441dbeeee0ec36610c1d63cfefd1d88f33e89daf057cd2f4364183ea1be14f9b55819fab9914b47e8085c40006bda00ee4dad3e2843b75cf23fac0588c4f5ff3ffd6867fd08b32e3882540f51b897f1f6c17c8b5198ff158a850478626337e4415e6431e3c03e64e07211b94e9989ae31809ee822f04844ecb6eb3d9ff945c02efe7cb306f4004431fbcb12ce4c055699f19416430bf5b90f92eea098172ed53c63eb97808193d73d5fe22d225cde0245f4eac9f2ebcfdab6dc3382c188a5e7ad37ddd3abe606bcfb2d934446fa53eff9e2200a64bb007fd95d2fdadcb208ffbdd3e68daefe322beb3dd0a3329f24ce535552f4454546772183deff2f611880b6c41156fc8356896c46f3cdbe1ce4266335005999e2fcef48689c8ed2b8367bb23d7f3790839cf9c2ceaa98f22ec5e374eb515d77287087d047cb240bafa1fe29edc9153626310e158bbd63a5e2b02f8e2708efbee6b35b7340c40b6a0ad5765cfa969d505506ce4be7895cf41b06c5e32686fe820b73162555c4e16d38edbe4ca8f13e534e9d12e4059fbf965836c573aaa10880eaba0a9545b520313edf52a20a699e71d5c63ef4e8eae64a0d15cdb48f3aaa03aba47df1020fd8aa9629a47220bbbcec56c83d5f467dfe04db7d833eb82da8e145a51eda4f2cc997c8dfc8044b1a71a7db07780e1a780be24c98b1d8c410b2ad7f86c77a0b2d64fecaf52ae95f819e7057fd3e65f962065ed95f0f427fe5cb65e61b24b6faa3b8524dac0aa0a728c9560ab3a4a062bed2cc9904029c8176031f148d57b2e9b0f5c6664f56106df56720b5dbd2393193eb64f925a2a065154593445fe333063174f7fb32d9481182192819fa04c02d6b1db7064ef2b1fcf8dd686044fc5ee1cb97b2eabcacf87838c6dd0e77e372151c225d89d09276d2f1c90eaf8eca0cf928c4d43d7aa23695a4ffd5916b6a6c1775ca4bd3e8aaccc9b3a4fc64ce75e23e2f542e8a0b84acd65923ffd898d94eaa58fb60286bf926e2d1cdaa557d30c9481d7548f1f5b2632c0be993ca51a0aee82f52670363ddeb1c65053611e4d0ff9a4360079572a6f9c6f740c033537c004df105b803f99fab80cf0e33013614b12dc466c60cf66021196db19d49e10913e8bda23f0263834151ee5d7d289abd779b063ccb89df6f9636acca0b0e428485352343901fc8c4092517fef4f9b8be90a020acd9a574107e67bbcdc4a0538a8893a888e5e64472726e05b102c0f3fed6addd035470d160d2f8aad39b4275c32fc0976cb44dc972941eb5bc6469a1b43a884f8d573b1240ec91c4a13c9f8f64fa3ba73bfd57b1e5573c23a3d72e912d81305df07e17cc3c4641ebd965fdb2d154594084bbe267335f93ab45523aa670c4f34ae25b79421009f8ebcd4b1e2b74b84f397c89eaf1ca04a34f0aeff1790dd4a684a5b943239aa3c7af908585efaadf43e67fb49e03cc9b5ed9a483c51f7e346951cc425b4693153a313a40b016f3cf9ee1ac8fabbe54827fd3d44768bcfb2c0eaa8a68aa648c3bf3eed4badf60106b9e2446d7f3a643a04f73b0667bc1ed5315c0dd879af461090f8969498303ace9a4b70f9a4f577f44784fc5d206024a583663efc646b29fd9d4c822d55d033071f57ed0a3e30c06025d8978c4bd5459d5ba32661594fd49a3701cccaeebbdd9aaeb3972f34bd4ae76cda068227317ea1c44d1ea84b6ddffdb8dc35709cca8c721358157b7c059fd23a038901e96756bd0a4ca1b1870c0d275c5c68c2520bd79ed5ff72d6eeab91c622e72d46e992be311b38f0f065f1036de54109dd787358f305583aefbf941f8f80c1aa8e9a471844d3e4ee851f5e25fbb0db29ba2c2a0fddb78cb1b3e4a63a7c6c5651cc56b6231f75beb59b75251852917b320f32a7bcd584a00bcded2c1ec9ea625a4894392447cc2393ea4415fb80e4a1aac0c4f4149ca6a5d9da43fd1ad156bbf34c4252c56954cc0a88afa3b2162f0f46f2d0ba5862b44353483c588fbbc179542626c6aa16985f87a5f70cd777226f5b63ef22eff157efda3951514fda50f22b0ba60a768170f71c3d0fe692030c8c1dd1a54279f5e27d3bc77cfdb6ffc3d08ca28f48c713d8706909d0b198b0027a0bbfe28eb1da1bc24b788a67024249c97eff6ff0658bac75b07703e2927cc95c6f1372fb54b9ac2ea7048e2c245796896c2c83059f11c673a45712e751a0f2b5f62ff5fa1cc986572fde65a21e0ffd7e39d33786bb431f161a19c8d8ebf5d36cb6264f63f83ec36a119e58b9437b449a41fb3372c661e7eaa2cf36571fe7a0fe1d1c31c7acbce7a7beb6491fb46819ce36748bf82ca7933b2560b22eb6423a0e4d8738214819574c83e5fce9b055114e64be5472726d8efc3c2f6cc449d6cc09b750633e3960777126a31c9f53eab499f668dd6559fe9b96ec0d47f564383495e17fb1152a93100c30022d14984cc15d0f83cf184a705811ec490e7f14132a1132b5baacf6a854995901bc0dbecad771d102e92794505a1570d309e4ffc40c38433f750d4736bb0c8fef310411ace803f497391507f4044d94bde4bd68ddf70bac7c7ef74b53bed055eb47861b8198b7c5d02d1fb0a15d3f4ca5bab2ce3ee118d53c2e7752c32a5b6530c40c6c8268b337f6ec3b1b39bd1c21a1a7192d0977d573fdf36f2ee63b988f4935cb48f50f2675cb68a7b659fdc4d713ef1f173994e908823c372093074988ca180b7d553fbd020eb14c6329537c59098809d53e3c921131dcf87c07e238f0e7944be7136032ff0f871ee41b0c2b69271bae8728228f9f5eb232cd5ceb9bf75f9b1a602cfca88d52823b8d72d19de8743d53e0a8cd91b3509dfca83ab9d75400c09de219912ef26575624437712231a9b9dc9385ddc81de57453496e5a0b1a61188cacf3e4cf92fe3d7d0f8dc98f83d30ee240704f737f758ae506affa130691685dcadd5b73085ae9e941565983f8eaaf31626fa90e9c405a1ed0770985b532e80e25f74ebb11496f65439bc477d81ebe553673c612d2f87eeb98dbdb79114af5b6428eff2a28c4ded9d37b3bf029d9664610e13d13d88f3ad867a7c59e56e5c00fd11d1de53b59c2a7e33172c97f120d6bfad449b88b2634b53f102fb50d93320920660f651f96d254a5942a1b74493af6f86ed126eb9d65208f13607bc7ef7b4716b3fcc2550bd518c637b7bea4371679319cca2af109e6f5d19b412f8ae366d1e8084c65a9107b215e3656da6cec36cc7151520ee0174998cab3a7c69ea39a9c15bc24b7f61dbd7b634d2671019f53d030fdcd7656100a9af0ea1153f6708f7a8ebcdd0e10b1ce1865d0e0336eca3a0cd5d72310ed75c5be1e9585e0c9c2ed13009594349928e5d041ea7aa66b613a435acd35e54c0945b244318617c3ae26449dd4d740ec437f74b00b90b4adaba3bd2ddd022d732364beb65b4f5dc6594617b26ac2aa334e091674ce8e37694c070503917d250c020c67360035f43b10005cc8ea74941d97cc85b9b4ad579927a330bb9aaa7a404aafe34c59615e79c8d7b75272efee12666fbe43882de1380d96ce67e318a2335635638216d29bad49f311b73acfba9adbdaaa472276813644ee7fdb67e41138965e869a8107e16cf9e736081fb1a5fae44196f06da41ddf008e2e64d26a7e55260766bf64d5e446e3850500fc8e014cd5a70c7b994b7764495ded894ecc5c6426764b475b8e5064f9286db0cbf8dc6166a94bda30f2872025156a2152aa46eff2d17cdc82f55a723968c828e1a07c7ba0f5c85808a3a714754492fce884cf4c5d17c0ac52b7ce218dc31f3c86c2a3832466d07851651331b855c4da0ba2c4331cb944cb50408b8fa9d06fc4d828cb168d5535d155187e2c2881c3c731aaff8163f205baf612c2d3453517771692bb395838097a5ec48729933444412792186b197bdb6286b014f0fa255ceade4f1320074b185a1cf9ce76591e07a2bad342c6949512095adc5572830de7b994420af52a501455e56a7cae879a34eafcc56d3ae3ac315fa278b62dfd897846c537edfb0d562ab7dc08e11314ffbbccc44ea4364081103122f93b2ee5b578432dc7409cce39f49279f50831676c63bdb9cbe0e3d2f2b4bc2c61ce6ec9380f3503d1449528edb2fc08b81241e58fdfeefd9b704de8aa8cc16379d57258dde93e38cbffef5ad36b306d885c1cd64e063cc66f248bab8e3ebe38b06b3708f43aa59f101144430023084273e2dcc0eee83de0a3fdabe05b4a9354b5d6bfc7f3dd42bc66b475ebaf769b4e88db84e224bc63ba20f9c9909deeb65d5323b3b6d9d568794958adaba0f1203a4e4dad6a9b6fc0a800a4398b3620a66ad9a1fa3dab18916e9e230b966a8c537c42baa866326988f22ee86a3f387debe6f42bb6ae3ef5bb87d75b270557c2faafa605c9c6ffbe554fa1add8660d723d3784fcb77fa6a40ba7951da2ddaba239a6dc3eb355d30cadfe7c749388deac28d93e622c7948e32e0d80bb7c27b7f000828a8cb842b0d15a92592b52ca7a689ac8a35b313aefbab3fc5f1454115a3cf57ee1b320df346e10cac90d7d3085821746f3c9cfcba9f19d3c4b434c561a30db772cb03b0d6bd9c3a66e1c78e34e85d494b554965a613f8bddf4e5fa22e94dee7d474c47dec9b5f35e995e381097d058dc7419de1b7cb3408f0305b3a349e4d22207117d7eebda5ed7e3b3b8cd37a3cad04c398412ec074c97a4d54deef8101326cbadc86fc8acb2e30e98da4aaa2bdb8c9a49d120e328f7825884932c219a6c59c3856851521ab982cc03e97c37e5c63f5017a4d9e776d076f148e9f3707393ad41117b42a132fb42d070f05325d6fcb402af11ea12aecb73d028fdbb487cfb75d1478c08ff05d52fbbfc6c2adf4d6f181492a59f97a5bf5aa38b06b51a7550b5b078b0fddfa40e1b18dbe5551a0f3ac454cbcf9e9549ca89ce6e2a4fbda3c2322117098a06a531dfa046a04c420a3265b553aed98b5adc8b6471e5a2b1e67e992a04ddbaa5d03fde4b5777653901d8d8af84953ceed56f900f5f231e8e4192f128128a4ad5679d6a95daf689aff6109cf41de763766f081896c1d1bc69d7e3971a220a188b11a476b8c0d9967e93c0379a442b39b6a6ff313c56fbfd26a13b7c4ef0c733ec0650685e5e0f8d56fb1862adb076c4243bb76d0c59c38714d302580de78e4472b48ff28b69da0ea88812f03a13b14328cf85bec1cf5c105f4d7934892e31e4e5e945ea1e1c016146bdbd46eaa7151275db0f88b7eb03c79a2f67896f8320a8a73eee21849f4b1d367cabb1edb8e31a04507c630f5f84ec8b62e885608b2333ed788fe9fa57d474712405a3bf6d62dbe31161dcec4c550ff023f8d048a34d146930cc1995c7636308aa66a8992aa25aacaec9e7e8be973b28f751cddad7e25db5e5a7dcb01f3ef78157f7ef8a9c2d7f60b8bb22778313b82250006006883022382595ad5f8ca95a79b9645a5f13711829d09988a7d53abcc6b4466d39060c07a2b42f26600364d719fe7e08440c8968c6eee81fcf72feca26fad0c088325b5b2a2d06953f0796288f06a268ff70924bcbea1a81f9fcfac4aeab612dbded71b0b823d7dbc8fedb0b31329c0533b6596da3c0bd71beefd820467ae37aa5d8852643ae3e26266356fff9292be428a4c9271f96df5d1a26fb9ad329bd30a1fa66bda5fb8c1b0b3f59e888ad093e0fcd80f6a991f1aead0f6a3231c8d3b83727322339b0c68736a5678b688916f2424a4c0685d65fd54304306fe567ab05e091487810ab804bfd44295d334fee0e29aeff1eba6f481ceaef827f27a7b76961a5aeb6866f65ecee78d4772a6c2344047fd4eb7f1f987b50f605d2b2db0410668117473487e82eaa9096e345d82c75243f4d4ad9987d30a2dea429db0595c1851753eeca329085a2954acf4b2a6e4fa29b05e40f126ffab466be7a8a454115c39752c1e80e8df042551240cccfea10ab5aa0fe990d59dd24611f7f268b4421e6b33f13055357d8a62582eea8a372bc3eb2f91d7333f8202ea29a0fb0f1612be2ce74ef2af7904fbabae7ee82e1b7d87aa1d4974c674208b79f9ae677df262488ee39f8584d524e330994b0fafcf2d537c2958b82fce743f5167dccca5c8e2ba4f331776aa5821efc5743ddb0057e9bad33d59b9f98edaf671fe6ef3323b55b72b887e1bd2541422b657427ccdb81675b962a8ed8bae759c4cfc5ee69f071e2a92cff3354f53f812c498153421b67d4f8898842f1571d53bc43052d73f27efca3c2ce4b3af2bd682abf5953b24914ab313304c06372fbcf350f8a825fa92ecc475e0a0b2043d01210f94df1ad1fc0cd13462d939855e0452b21ad0f28dc748508fb70b33d0f02dad907be8e5da2329525df5a9f172c6b9b31a63d0c837119746e444293c1329dc9142b526a60ed01508aa093f6c2a56a09b7d1a88d7d786313416054aea0474b6019378a93a5c3d4d14230107409d5ba1ec0fb5c6243e31144df8c2f0a3d34de4dead2a550e7e27f8b1edd2955e08de8cbc8cfc31391ea30030dec46061e0961510968db0492b8923e9e4ea5edbeb1e893b77221acaeae986259fb8ed88f724c6f53c40aa736fec48bfa11168e93e726bb5707854f7d9af8cbbce936a3c54a0fb7f5a2557ce2fd10bc2569bec6140e4b54a67e70336bfee88821ad736d0073026d473ffc6949697833da0cc4a54277d895284a807b44357818c7a49ab0f8a6223ad0afa8169d5a5d205bcdd29fbf89f21bbdb9f389de11525d05f01062e29f932d91344412cd1ce063b8099a5a50cb12f5201f6a0e8c2e5869f86ca9c0811a0259aa1a0ae7dadf482e6a206d8288e97bd3d9d82fddac16ac39e9fa52efaaa0df7030e6d8290ab4d2d0f8a5eb8ff1a79d58977eef3c5bb7f063a20a06e6603dea96c09b94cf587eb323a06b8e99725b8b08436ca54b7d85a30182f152be833bf484da8c0b699b42d00a6b837eb82ddcd43fb740505411cb70cec5935ec52f9aa3765c5eeaf16ac463c7267b8da3606134ebe05a92d75fcc4f0f3da4fc6e48ed0008de7b024de6b65ec97e34b9c47d3b5a99323f8a928482c936b2fb549885a0b3753ac02e70c22b0389a817ecace0934c4f08f97c7f69a4273dd2a1d91f07ac1dc3cde450a8d6a9b45e659d560dd9939332f358cd43ac8a5e74d1ec220873c480870f09723e093f094228764a6cc967da79febfa22ea89218687f1a196a32059f6ad5d65c9311ffca219330fe15b1839f4afbb4afe627b7db2ecace817b381c920d2ae15ba73e0634466486a07f15fbbd752feb2d2144b9f5aa41db4c1d72220ff54f80788923e35868f379925986b61ae8a845d99c5039462ede90158fb27e32d3db2df12d00d40146f9b3f5ea8d45926ce654ed03a0da25ea3789d395e359fe183dfc680f4f272a06441bc01d64962fb18989caa61f464135b8f8e250cb0a3636d5bf946754e9eed4804c657a6f1a20ac371fb4b6c475cef37b6f6eb9406e5a1cc0f68552ce1a79785af9040a7fb1f533acd80498621d71aa23335302022cf53cddffe70dcc1b43c03da3b64633b07defa262e8937d0a50186c99b3d2c5466d280f476f1eaf452c983f6b31d52cc24423f83a267d1b8d37b028c0d56f0c53c28bed4018c4974a36e5b027e1890b805fc27fc6e7edceac13d50fcd780f79e6ad688096b070f7888348c12851521682803d9a712ca7501202c8d4d32c0cc1ae0d8436d10009862160aa14f5f47622488bcca1a89b382dc8bfdd585f80ad0936c207ec8cbdaee2630a09e2502637fc5859f1cc1744151fd0143156e2b28df66b3bcbfb238f210e42e2114b8ea6f020a40aa21863224f8e00870b9e3c9c0c5162f03db2a60100c1bdac17c5c18bfb331bf7cafc89dd40852ac93f902bb68cb0efd24a61c520734e82226818c915ad59894bef5ee9aba89661c6a40965b95fc53ab5b309ec1c56aeeb1c7db03cbd4cf93b2c7afe21cec6c44ed42d33ffb12c3eb50cbf002cd48c9ee9bd51c5011ba72ebbff726278c2928500534651e7c1aeed640bc829d9d6f0032db7a3a5b5c9f333b2a692e5a3a8b71fa323ef67b51e8ac770bd7ba029164faf230c1cbc64e8a133162c41bf2a4c271c89dce233fed022406c573ee910868d7bea2e6529148697698d7e8d42931bba46b10a9abc0da91dbe8537c2baf8edac424f4a9f79e0fa75feb1f2d0c92e8c1ce0133f661a4f359a55911213643f380e44af0579b88f91d2be75910b67235de852f54b5fbec7bffbff93635626a17d34fa9ab7bc8735bcc14e7fe181d8698f25380b044b497e3adaaa172092f27f17e22a2b49ac02a80c43b01a5078d4338e490ff127489bf71ba8cf9c3105f1241240e7a05289f270378b9460977736b5bf359f77473ec5dd33b412277a6a8861bc1712a2123724c75d0889c5231344287514d8e28605757e8ccc7addc3a37c7715c7976ec913ec89ad2ba3cac0834070b948b29bdd0a096241466ff72720f153a18b24ea96a8d1f33d2b7009aa7db25ea6530496cc9a2646d1091d1280e0289a53474d7fdf51b4200f4471351a14f21136c1bf4be89d371418b57d40b3de862dc6a1d00fc468e5859809e03fb12c1ae8cd4134247bfa3f7d05ff491fbb6ab5fc47a1ae9b505a4c0671a5bf28832fe08555c9ca78beec3182a493d0efc4acfcfd1987e17bd2229170271ae5e5bb9140b683e47d9e01df51c85449d285467d1df1b929af29ee0c7436775d15306affdecb17efeea488ee68fb843ba492047bf9e1a606dc5670650fe46b39206e22c4ae14b62333f3e4d366a679288bdbc97ddb4dd366ea463afcb8df4ad2635d904a77a9bb1af492fe6c70c98c3401229e7825ed78725969f8b9833d0ab2ef8e932034d6d050f11a815eb4596e841e5bce7e35e9bcec48e0c75a42d7db94b97597b161a697412e56b506907cf13636a4e575cbf8c65933742f1e101412e4be65a432f990e4d771547cbb0d50b5242d1609913151940e280c6ae8f3039acb5f4ff801c57e62c6939f6a2406b9e94388625ee1d4d57a4d5d9dcb21dfd92042b17b2d7ee505f85bf4dda910b04c6aa6ac9a15a5093a6b9256af6cf657439254c8243104ab5924d6fbd08e85c11becda295d1112464bcb60acc7f72db7ad840269c79f2f3078249e95706640d68aa93b1e8d07f402d0952e1e55c398fbfea3e3e377bb7f808f317dec15cb064326bfe77e5f8a6dc3f292b365c8e629d25e8adcb8abb4246e02498b864b152f593b52f361e5a44b248e5109aa35f742218d8b2fe72dedca9fe57a4d4d61955e825bb9ce1035e6ee51089bfb5bf0ddeb698ef6e0958e4a9064c877914f34562f8e52c1f28ed88c275380778f5a90c8c1106fed3d21229d7e307e6f7ebfcbef82a1837fa20ba4461381c6a798f2ebed7bee33fd30006e53a7565246e8e3e698df9c63606838bd7cb932e327efe37b3cae073a8a2553eda1128056999f167e8e48c15a7720c848385a4dcee12665506ea6401f4dec1d452670393e31a346480e657b45d119c301629760cdc3f8d0bdca0db9bb8cd6d2e555b8d8584a3dd12d3d34871616e223211ccac1d49dd50499ad5694c7c5b17688ab5f02c585ba5e7fbcac2065e7ba20bcea1bcf3c7f6c9cdf4286e51a713c9c6424c179008b9e1cdca515e1001cc22fef38e244bef6050f47461901722068dd6f66350098404aaba0377e552e27c73b410897b5d3483a006dafd0b137749fb070aac0c6dd58a1ef9079781003d560b32335998f705a5e0dc1a36c4b313590e380e7f61feca9987d8107d065563a18eefc4d60fd985b4640f2644e687c4edf026f02d14cdbcd0f847c27a3c6982acb441deea3c757030e99ca91339c978e8f7d24a6e8f61b9ec0a107b8d715e70f289610cd41c8d3d479c49e8fb3ebf4877a2af8a652549572bd497347482789a2e0c9e149ed88a3c7ab43ed6bea2b6389b3505246e4cd76e2e6f6a2d6634eda070df40525bbcdacf3881d775ba441beb9d5520f78244e0fb650255351437cd5ab80c28237efbd92fb004439619dfc84fc39b193a3d8aa5c655f483a4b843b00bb53c70dd093dbfaf4bb1055b08d5fe8129084d3d1ba8c8ba931d8bb25c88fe7b27ec902d98aaafea475c060d620a9a95356f7233f88dcd0f77cd23f30dbf9a2e757855ec45e79829fd01c3a60d74f9f7ed9bd1edff4a798013472b5147e438d5b137c7414d1af0295c082e87ee5aa3029b5b408715132a78834085d941d2d0339745f49c7423465d96a40ed7b2db58ca511c398278807ad186aefe3a53caa8136a857cd2c2d9cc2cb78832b96ca6d6be52173585408a720fbf803fd6dc70df7876a1faa31107ef2551e598279fe16ce4da2cf752fa9e90d8f4652b63128cbdc8e61beaeae78d22e10060f4cc20f7d1699dd167fc973a073d349d727be5b4502b93d3c35d5d722043f3e122ead1bca2d9875789fee9ed0bc300e9cbfa8c20e01bea36e5ce1490716ea8f87f50e026045e4bfa5ef66b3eb9fb451d271ea4a60d15379228c08378f0461a027639d3ff5eaf0ca4f30dbf7bd9730c7219957bedb318910df5806743ca043d4194a0c1554344d6fba4157a596cba316ecd8daee07c0c4b5f446692fa16412503c6821fca6f4ceb5e6bf152b6d3b7077e6a9bf1df0e2a0b3b6064ec4e90fc1b1917931c67a724c0e70838cf52a4ddfc1b39ebb1de00b28acf00f767c61fd6a2170e99bec28c0a73c7a80c49403f28da0f3cdd08073751318d4e488c3a77be24dbb53c2fe9b1991ebb9458a689756a2c53c53a2dec2962991afb94d84c8db574aca6c4723ab6a9629d12d614b14c197bba58a68e552ab69a46ef3236e73c5276e894e1360f6dceb6c37903c999e341f71c3251e2515c096f4583097403d3ab4f107a8d3b7f6b427ab180a05e5381918e27f8254ffc8e9dcc9f4aebb4849f503c669708186a905df8d03e31b28528e74c786267941994b9c3bea166444949ee7f27d8503ff1625cac220f90587e3d6f0107bf00db93972689ad7f1bf915f6bd60e21b8cb05c42b64d0e50de17f80c6d9794dd9af0a5a7eed1fed8ce1940624ebe48f5763d1bfb95bbfc179dc926585dacef02ae02bb177ed0e2f283ed1bb944af00853a518215d33e27341fccc99c00d8caeb6ce88310ebd9412eae0de429b00da58e7b556298c82b91c737e2bdf0f78b5cff1d1700707c9fb5164662ead7947522bbad13319d798c7fdc0ced55e3b2a1e38d0b62439811984ac905682cd0e10a612638d64280f44f237aeaab93b04d2a7a9fa5d7e70bbc19a5140f38b3c7222656260690e43161622e0151026b5f84d051072b2c5cab6a47bd20a1a819b00a5ea03983be05ae52fa7e0ac865baeb532d1aa30586e5dc1815092cd62f000a3821b129b189f13e7c548b188dd554b1e970212d172368d7e163a32a2fd0841654c555a8f1ff47c7372f3afe6d16f61d4ccf44f79c2801d416a45081dcc6aec65b8fda14a9df3a6f5e1ab7e256d392e6f8d14734982217355ca74a3161538ff0ffcb7bc1dc7d1a8597fc7d575b7d56fdf488582d3fb60d3b03f90da2af0055df80180e0585d55fe5bf8854508e0814f616dac43542762cf0c1285bececb19f06b8fee1a0f26f9a5dc4db45004e05d07c370e65171c5b728fafe1d168ce1ae457ce2d380de218b796dbc22d331f59e3c03bbe698582e2c7a25dc64b59704ba0c2ea30a3b6d9c611df50b397fc64ccc08ba6c23e1df696e107ba04ed3a840a0a7f8b5b09df76c19959d984a00ce2d14d8c8a94416684484f6f5f6387f1c03aa7e935d7a0ec2aba657793a2c53f38d899f791e055ffce1dd64769e9545634b7c1d35c875890f3c5df38ea5855137c8c4c58abac4d4e0f500ea086599e3c1e193f123c9ba7f38f48c4593eabbbef699267add85ac181fcda3c50b980df26cc2c6cf695ccaab004d3ababb8ce94ab1c45eace013bd64d390500bc3dbc4245e6dd005618fcc5c41ca7e6c0e9c264bb3a26d413dc20245aa0db6a066a7eaa9f104456d835f177cae73602228707faa0b89963388e53b24c305e92495cd9ea5041eaf3b43077acdc257a8deec5f2e735a6fdaebd1a44cb16b4669eb49521bbf639f000297cfb57ce5324a7c62b48cfbaa87aaeba25d544b42b41ddbab8fced7125266d1b0857d77b9be62d125ca86a61f29298eec970f008c396aaee7f649b61dfbab1fdb8b84b717e9bb6bede33384447616fba7fb1d75cfddd55298adead8bb87463a1b2d8a7fc1e8bf590bb4a92db4ea326baefc9c94e231f3c354749c0b39f054a4a9aae03d61ff74b9f64c6bf2119591767bf1f876ac31ab958db4a3939cc8c4d5981af5aaeb2eaaa940d79f8d48fdcefdd594eb9d0625c1e76b968822141ef26ffb212c665ec715533f950eed3e6f44a19c4a4685e25d54cf07958b2259e8e8ab216e11e52389aee2295778d4f9bc4b66ba2925e6047384855f8889ba91236a2672a858ce019538f267bc976d84b3f7d74932efb16940253deecfa07cb7c37d898673a8bca1187c6360157b31bea92e16bd9a3088a958437587fee14c715cbe04b8f885e0b304e89336215ecb235f15b0d1436b41f72c3eae1b3c16c940f06fcb83b9c79202a03271b4f43b1dc941a4fff9b7fd7bd97b2942cb3392c9accd58a165f27cffc774a9130f6e9f5d42259cd3794d56ac6bcefc00474c47ab12c56e7c6ae00bcb8c2b4030f6771e236ef6660cbec9516f68b0846f09cd892e6929f5846d47d6d14a97ed96e1cdbb2e35bb3022c27253c89abe99b0eb3f5a58a24b8a51c25228c6d268403aed5295ec425ca2949e6f1a44e94166186551e0233b13276aa1dddd313034310a268f69e1f4f8996cc863f0b32875d4c8daf774cabb42ba8c7c3e780b400c10afb63f7f973816c55b1e318e1d19ed893696e164221c3a268c6c88ff8743db3026e78329487858db5c3e577cb576d4df0e6a304f4a691c3912023fbd3d4346917d548d73e41093a5d48aeb97a7d98e8242c872edae02f1f6864dd04ed14994ac08a83cfba9461984aab14b12f7b3ffc9feef7e9d2b454e6430d81b66b4c631661f8fbe1ca47007a93225ddef41c41b2d8001aa8cc075617f6bbed3daff41e3534394f4970e961db11488dcea2cb295088347e589613bbcee4f0d5b2cb7c8e37ff7dbba61498f4ce46c3611676352b6564142f82e49af3f19a6d4619513d5c46a35c3d846989aaaf8883aa3bbb88d2ad70cd89e841035c41e974f6e68a843162bc0fd8457f81c31db8ba7d9121523a99ed23118e7f67ed3ffd30d25206f4f03c9826452a59b07ea52581caf1dfdb72a1f5ede24c2e4e36cca6245cc97a0473106e24af24fb562794f9f5c77fb3c7b8c838d5ab14758cf3bac4078d632345025e75140914e8ee4a6f63625a043e7c6dfbbfbe63ff27a7aac06111db3e2e746e7cc3d84294d79857328552f9924c9cc5d80e75d0561566439e44ab0b61eb1c7f929d5cc7c51db5eecfbc79e1de109636369b9ed10286b927b66fbf95d56cd933d0fc17ec33dea9de9b95cdf18f76ce5da9b7d9aeeac880cc7f55c5d0aa849d352c4a918d99322a4c15eb148bdcd60cc144498494c17c6a07b0ccf0cbcf5f4f2ecfd7861c10919b87a8b7701e4a11429fd8231ac1c97eb8933d613db050401e132ef986f58db27f8c42da9fa21f3e3a79b6f289c2cd08cc696991818eed5268221f61899b3e370f158c4e828d1732148e5001d272e54ca4e67f23da5565f944c8f8de6c88669a1853b5f726f9d7bc43b09d41358fd95d99cf6eaa5b24aa9f4fd3e1bcccba0b44099d31e0fde6713f260252870ea73a1b9f9c6a4cb5ea88d0e1373e63f2df3d1e9426ffab65edf64e597f7d0d53beb970ccaeca12909abfb0a73e12d5877d4f1947a60b0e20207acd9e1a274ec8f24f68d7b2319ba662068cd6fb6cf71aac0bc435f17886acf736e430ee77e9ff758db0be427c10d917a789d31959deb2a5a209c81f59e287fb919fdf9f44f6ee5c2898266197c0335f589322baef69a4415e21d343e4cf73597a5c9f0c8f2e7a468b29b1ef09cc789f0fe2fa8edf58bcf54dd7e5a8bd068957f05f1268a83c45da97d7fc0de5204015d03d946b023675eff4713b0878856686f82a337d178924e33fb82a686d4486c0201676513c62c13f1c4041a12f39911fd9e2caedd3f50790b6a0bcd45038edc243bf97b879cbea599cc19677ad4ce31b7144b2669eb6a22c5103678111677e7c5193dacd9b51eb8783ae501dd9e6baba6f93274f51584e3bdf8f18f14333e802b940d13f8070cd47b04689a2c018af866b59a1c65fb82224cf820f12511db6942422c8a42e22108b2569a19562643528ea62d8a13ac5415908f021b1401a475c788629ce80d42230e8806546cc24d527f8d430a7d4f41cbc4b891921c5326f61cb337e9cbc2409ca66849b3541bf18d19e390380c9167de1ae45d88ea594dcc162cced3de10dc1440e41e402f26dd872390201b8a3b1692fb00500386c5639b715c94a97449c21477d123d829d0947e964e658d97b77902c0056ae82339f61d595b7a17d163c49aaf1d99f8a43210d38a506315c83486821459a01ffe00031f420f39ea28831f38f16132ee599e366d03bafa10362452fed72ad4ed3c5fb2c8547a2f677875e6fe058a024a2a8df4afafc2e56d4bb643f1848ec8d4ec96840fd448b693a950e61f2430c43478d7f1566aa4cef7cff5040bd742806914f8064c7269c75cb875f42b08bfa790411c71aac309e0cbd37c2bbfbc022b3a21d13c2699862c9a0f1f6357aee344035948112405a23f23ef722e85b56fddce6a852331d6ecaa31d6f0df6d950451186359300724413ea5aeaf97dc8abaccceb0f6e292bf5fd740fb2b4aa468d6727bcd5886050dc6307ee4547c8af12a7af11e0d8d4ef23100fdb6d2b794d8c33cce194fbccb35328888ff14fe0f066ebf3d5f55a035ad00b525dd47bcb04a037566f7805167a07305984b5684f87a8461ea6a73035836430ea0f8c6af9e0593a975780790da71714c947c22e99e4e19e617df0363f97cd0890b23575e09c96a68a03b7ba8580e3ba40bcb934287fa1ba0f7460d18fe28897a394a3bbb9681b0590533020cea0b0015f7207052a213fa72c74e0d4e238e85eaef73136d4e8bb48359e2396bc147993a378806598c51b268da7640f2baf7a2656bf19bff21603ce29d40188f2dfcb2cafd2ad1f2e8d6d3244243864bac09cec7d1f6f7be8651b191fce98050a90ad173c1d0476d04c87eba3a8307f2c8ad6e4ed9a8098db1b6238530af9efb81a30489024c1faa06d2bebc6cd0fdb01cf9b3d5000008064f85cc00855891088c1805b65772172420eca5375a70bca892d95e3aced628fb2d6228dcc47e63d78ad5ffe63ef8d149b13747d8e00568f74622815203ca29b7882530e95b0d5aca20ab403d09a3ed4562f133cc9cddb8458ffa62f108118f0500a90d5cc0d926bc21f05c27d06433abe1597614152c175de2b0a990046eb26d2fdbaa0db2182efa297f1aff67db86149b0de7d497a0095956f4a083ee0be5c54b6f34f77f2cde9e0c56f3f46b5a0b6d46e1014b0ad76724d1c0995a05e01edb5a51128ebf672d8237430a244213f712a00516031512c677a631a6e54b564d47c6c4a49cefba915bf12a4114622dbc800a422dbbc116ce809beafb8238c6fae67784d2c199b750f9bd7deb4e33afb021d8bbcbd26c53ccf45fab5b0be151ebce176fa4975ca15f0bc0b992dab3d111595658a8344a390e7c5cab0b8446bc7bf01513994ef724d8e81f114a8106bb499a820a743bccbdb6801c75cde204d31b697eb61d6b20df2d639d45e31482d9a2a95219235829098b2d8ea06b129026121ccfc13beefa873d4ad16d3da7fefa327c32d221c708f26fdf3ab2b41ab2842e3d59242ff90ae38b86b849b9474eb8ab7bf0d4b4a1e291c0c80dc44ffa22f8537e38d154e2e145299c4836ea3fc46085166faf53f9ddece13a2231d4b21eb229905830455fcb24717ebd9086c06085da9170641afa40d5833c441bcf0a7ede6bb3239c5c17023615b101065e230732e7b28bb92775f60b45ebdc9f06ae136ab8e7065528744dba66d1933297a338019945a20736a403f95ed08505cf890a73d336ada1c0fd82e4a7be81e59862151af69b780de4fb1c7be734c3a2dc9ccc160b6863c839bb38aebbd313f2bbca1fd4ee891780c38f2574d683dcbdab3ba277f9e8f57cde02cf952003a74d10d36829cb4c4a14565d396a5fa1ba6ae7540615544583ca42a077c32d53afdebb417cf84fc04f11630e101e012f97ffed4dd58db04863587caa812df31c980868ed1b2bd7e20be37c2c00d586044ff370a927e47d87161f90139640c38dd0869d2df6655190ae2088c289af894af5b89ef6e22f0d28e3b9c56ff899791cda9278b963a367abb3a6dac315f425cdb49a27f0f736a74af9eec02a9a99786a29faa4b310fda3d8f98e66f38e5b3b2934dc7970196176248a214d9f2a2eafe01508c5a0d2a8d4bc7193ace457979380ce8748fd8730a0132a668eaa0d5599a80aadc9ee1a437706fee760e1f31b122e4129e5566ac2a2337a182d414a612c68ebe56ca0def2ce9d13e28aa181a8f0ff3ab1e0fc371bbba202b0f3df869d2421f1ad6de13599975db5c2a19675ca1badc30148828090abe3ba8e90988e09169ff3e23dd1f222e034dd1d174c5fd352b5cf58cf9a81cf4d70c445b514576d4d36f88cce9da0914e58501ffb319625c506e44e5a4c6cd6bb6a58a04e45178bcc2c038be7a31e406a583236416d30329928912309bff62531cadfca6f25668116e8c60f0685561960720e3c62b3085c027470264da7a8c0d9804666c4932a3d8da5f1b155af537b52ff03e102ef6195d04dd14881b7eb6958dc0f85dafdd7bc370044f54637b1e2ecc473ca63efad7c0270cf0bb71a98919cae01d0bb48d7b4ab53feeedb5fdc6215f1e0cf8823d10ec3c02236c3448847f9f1f8fb7f86d3d83c0cec30e5dae77e19984fe61a7ddb76ee70b140dbfa985a36a76b20596a9c74e9a7ddc488f6322d6a7930ab11f7823558dfd06f9d905ed6749034b3aa6828fff9c2c294768d3294bce27ae51f78f67317eaec7d414dad25b9bf651cb95e01b45cdc9e88e3e97dac9c0441f28630490a37a4269a3cdce063007e538ef4b26ab3e79a6ff8810c826a56387602b221b97b299a8bd400b4b9b06949bc324dff75a4ca605bc8d222a18885601374e63357b3df38f8bc806c18cbdd360f8501a8d50c1345afc013f000372fa9ddce0cd19c252d293a549b5372c973ab250170a1990402a68697e5ad3c7cc3bc29f70360680c7c9fac53a8703035de6b1a0b4f3efe44051dc5b94607b2023646369566c9de992e1d6c07ab06872e3e0d3f534e7de0b2d3a54472daac8c49c34432c4ed387fbafbdc22adb05f17aa22f37651b0ffd94a71c4335f4759481d39ac7938e6b3d5ac6dbf2e295cfe39169e4e3b12e4cf587a6ab24bfea69e2223b49a9bd5b6652d47d42cc5cebbf152277da780696c8e1c4d5b62569d1b87aa26a0960d6f1340e1897c6a5088be9fb0a7b5955b0a98f85142b00283ed251137a51a937fe175dbfdfe99e5fb1b0acd95b0a21d7575a23956ee96d09c16aefa55c053cb4b69fd68ef7c84d37f1135bbc470f21c4be31e6cc169f0d742dbf4c287571f9baf847be61c4bc7d171432241a9ff709f68ef6f58933066b00f98d2005b9903f05b75f50593e2f879fffffbcd813cf2b83818bd6a94fd3e0fc0c28c9bed530265ec70a7894ec4148cd9e3298ae4f33de82b5722706e5942903a2c52fd731b1767bfadacc95db53619e56e531e98dcee2f9d40aa8155211cb7533adffadbe02854db514105fbd809cf974756fad4b8be94160687d2a6a0f35a807964c887c13eb1e5db9aedd9074ce2ac195cc2ac6e33a45dbe6f4ad0048db00dd6a4b38666e2320e68034488442bd0041539887c2abfc78f29a698d596c53058a354780722e9b74c37e3931280110aab0966415da26c6c42f769ae7e40db2560fed1bd9bc03cae9930b349f7d11dc5269d2c3b2a5888413f9e9be5a851eee7474ce1d0c5106cce24b9e3700d14757f8d7a1dd7471193b7587b192851e867b8c1171a0189f07cc4ab7022a6f19cccaaea6a1267f049c5996cce57e5f463da9b6fdaae2bfdb6f965109c60ee9499c22ba5111a35557a654989111c5330521962d06838e43e00bcc34aa3d03ff95c701b0716651c6a18a510acc6f5fbd56da34bc65f89c59d4a0acd55d1e760946ba5b35007e02a06e2c43ee3eedcbf5cb2f43ceceb22b5038074a8a16b273e5650c357142ab66eceb0e6db50d89797c05aa2e0a8c3b1c6f3c92f1980ac05ce1333f96f54e03beeb39f24b81ec86395d7010b1b170dc46c6b425f1f2fc7478dfd83b3141a05e5d3864ee2ae492ea18f76ecdc31ce6daf88bb9583e1d50a220e16c760856dbfcf53acad19103841c39cf2ea0cfadc7b5c320efa1a33ad51707b10a0b21f2d6d14e41aa07a9a71f51f4c5efa62d5ddf4b920cdef3a5a062299ed029919419859e5cf5e54c77acd568adf29320770e2d751cec116212ce3de7e609c702297f61e18e189f5220fcf6533de62def1367295ff0696da3225cdb7bc58830293a202d22619b016cb9113135ac2d5217e8bcd47e5ff58356d77703022a042f750135a2db19782dc6baf20f710c3baeb95170c8f52278fd2718f3258945fa6aa4a4e8f85a9f403528b82aa8fae236d74f5a8abb3871dd274977d5916cb3acdc53bb357fc960b332a7a71a7f644ce345d4613dc4f0af052aa90137a76ed346b964938246c72596b69727597d811547f6c3e50a8f07c486c3f4e8388fc9349aaffb1be9e6bcf65897e752e3a31439621f12e69a4488d0b45e1945994a023489b6a1067a85f1fe06bb7b474fb7c3c4945aa191a87320db54f92b9d1758fcb8f053d5f9b52756720c0d0faa23372f1926e5fda819854bc24ed810e9674eb21dbd0d82df4274172c949b3d83a3ec5697c066d6b928acac8a74cf99c9a4d25c44e2c6d749e9715d210fbf6a345c86d5b3eb1196727aebb841336503255edaf262b8641b3811ab3b1e83b4f11fae9cab0594010cb029c504b3c926d2dc3b0f3b95a43c4f054862284f0051c3eb6cbbef96270c340239aff45a635093690071be1f0deeb1e1f18a94da1d4c8d89a27e17dbb4d92c352004a25ce04994a2537ff1a404d1ec52c16cc366103caa9b8803647552234f664942c30797817025c31425c2ac0c7d13ca6ba4156386f42d74f7834c3b62679d5d512611c32f5532f53d9b265f3898c52fb008207fc90c2326ee30310875df9eb1cb3a5159d07210e2c6b01368163c80440adde303b0ac818723e70e5350125ec9820825ca4b3f249736292d1d19c4602603b71a5583158538a890955350f86bfb64afabcf2425bb042f17eecb44405614fbe07e39c77dddcbcea680a4d91716dd0e6652387bb84959f4b034e4413d1ed9107bcaea9faf3453c7b9edd90cfee36c909e2799eaee321a4395cd65db5a71c2f589fc1b2c633ce289ed2bba874d437acd380ecb137c486031461c3588b8c5eb8f887c2e07fcd35a3ea702fd472c3d6a85084af2c38ab6596debb2bde60b92b21a358c18116525e18fc825904f68e1c90f3e7736ec44122e2050314905b8ff7692fa260586e0c7c8a798e9e187fc891a0afb7705be8e8a80dad29f0038d4ea272d3b528854faaf7e7b74293141cc372f044e48e84da00c006b844e3226d9cb9e80f8720e894eef990ffd0fdd65844d2e6c7b6a2e2016ea309f52758683097e21af9ac774d7eb912d0cbc5617f8c6e4abadc168a82b45834c833fff605c6c50449f13963d6928da22dc63c9659536867dac8af69cc6f6652225acaed42b0ab34277d64e353221636268b119c54b574071918d3770fd76e84db4ffe17cb05f505bc85b161ebcadad11b60a6f87f9872e81639afc1f602798df45ac7e613bc8c798701758fee10b75811933c2b34b126209eb47020f0b683d6fb5488f0529eacd7ececd3970236db9024457e3d999e503c0be2983789847ea576681fbab08adad6c32ccb49256d066737eea3819d131ee5f93e591fe2e1020c0f395193af4cd28911c8a9619e0b98d054bb692c6cbb7574dcf8a2a0a19d0a5f9b6c6b1ae4b263f613f144d0c9c140de39bc17d831411049a8527bdfb5140354fc689de55212226fd69062e548932bac87d4bdf354056d705cf0d0c4efd5ca67baae1220f4be8b879ff06a090514d694dbfff411f6e3bebe69411ba206885d0b4b7350083061538f62ff1023bf853421ffdbf75f408fec7b9a38ec272145cffbe3a98351b4791072f03ddbe0a9720dca599c25d7529ec2a5013799a5ce3966aeeefe22ddcd685eefc5a53c26fc55da43f82ada897d5ad5a8519db8ab3d8f8d21e5292d588b82225456a3ad2707d2fad570737343758518dfa493c0573f68bece8f5f90bb1dd63ff7b76761f2c9b98cbe0d8b30980644a38f6b40864105dc6792aacd53ee23ff2d4a0a0d6b12ed93340c39f493c856f65f42a9a5cbeb02e09435382f157ca8d2335d0e471c0f231f51aafda1751e404130f10dea7bdeef7993654ea03c9f4ec52edfc3820335f22c8c8da04d2da4f884ca7d59e7d2e9d1e4d9689d05ca0ca9197dbd6e2fe39c8f865ed2a2d2a49392a62258e7fcbd387be1470f08fa98aff438afcca0ba1c6364c960894c87c425ccfd066fd2f8cf544ffa7bd63d0c195c6a2e1528f7985500010d8948ca36b5772f4d2451487604626252f9098c1dd052fc4ea4df7159973adbbc3e04bd70f0670458cab9699d6ef0f75e5f45b9f2773c6d65261dc0a09167eb7fea21626049e3cfc631fc986de641ad88ab0dfb9dba6f5597350074ce971a2b277eeea80069b78c9ce6d645b3471dbd88e986a6676feffc441d640786e3f979f43320b24bf071786d517534200ee825c3ffb2c19894f8f5fe39ba4bb2606f2f080aede0a3c560a51a65748cb2dc863f05c4d95c6a720ee14eda00846b7cfd32fee2e7648d303b17c8dca0270fda4819993fa35d8cf39db0c4395b7cb498936f418a8259bff5077068ba24df3cd0b2c0198d6464f50548e63b7aceeab0b748543b515805cab5eca20247e559df0573ab2f8e5fbf73297e91bdef80475c230304d1d6b8af363f5bb8fb6cc6fbe0ad3d2ddf66acf13083d299087bedf7816a119494003ad127aad4615ba4c8d6aec0bb995eb4d70adea6eccc8c9312f876b6537ca9f40321d7c8c5ffbf8049f6df36036b08bc046ba8c6038eab7008a11dc6a8e5601ece35a732757c6c46cc23229818da7b8746d78b97408e6b20798aeb03bc7fa75dcf2d0ad4fc0a17218d2df5215b1dd2473537cb58820f86f003c086e792245855629b0bcc104c3e758c94198dac8ec2a846b82e31307e4f25a015bbe68a7f14aed784868264391145a55e5e1618845c1195af3a1da6b38a4239a502a016230c153cebef12b2d580b71efa084e0573bec6a52deb85c78ae63c43e215679318009725796310834e79499ed29211233410cfe85398476362b57109a241e23f63b6ea2c9db8c61a708f555e3cdfd7364a847000c81833d7246d258e5eacd36e90d4bfa4b63eebb36cc91f158fefe9626e72c3d0b220f49b976d702d75f12aee012e506822ec6e175639e00822b48cc28d7c897afbfcefb0ff205a9a114b21412e205fa7af7a6e90468d1db114d9787dd39eb4b030bb3235383ed9fe13a8ebdbf82ab761d8cb5ec8b0b66f73f1fde9d13b87be629a89c298eab6bcb7c3cc88a0661f7f5a1472392f7fb34615096cf5f908c0c02112bfd3297f09d2af01046724245f959d4ce807a7284968da9bf078fefedacc77e2678726a902112be0444e36883f58265c44bc7d99dde79dac37296c29702d627cf1443c13689638eba361d0e7515209b4bc5f7c0bbedc01c633a3c356d8411fbd1b37a8850d34d402ed5c9f5c5e7aa09273684dcb613b2bdb2cc8cfbdca2d0c6038c25d5119523db842c7aed3059f2775723f3b49abaebb24ddb4e4c18b29ef4fc315439e7d855e2506502f2736583b85f284cbc266faded287f1b00eb1adb1ba2075ad9f5225e38d0648cc0fdf5872bf6b80d349aeea96777cd5a0f24e06f2f361e271040fb9448dece190359c509c20368aed02290f950de516b1eb505715dc9d401cfc3d1a48e98e87b64399de6405446e7de1d51efa72b75343fa93feb93b8b8caddfe19925b87a234eec3fce01a93099bcddf42d327ce717a04cd8ede487964cee353e33d4e305be6a160bc0547bbe48815605a495e2a88501c5d3e48d1623fe4cb146fa7918a7be730419368735c38bb6694557aeb8eb2184d4001313cf45342d099f015ccc52a684867d7cbdcf14c8a0a6dbc9152e753470854f41ffc652e0fdd01abdee9a9ab7b8dfd445c3e4b02b0599e4c7c9b50a6e0a27ed33e713ac92c871e0f3a5e45fe58e3febefed42878394b1dfef324f29e26ef69c13bcaa3fd1d04fc93bca30e2f2c4e042df58388823f47fcc8b180f6916c2d78ffe6a50619334bce731597ce66da196ceaac06f34fa9251802f0a6600444db0933c8a4e9ba44c9a3262abdd160a242bf66c48bf78b43e15151fc4742c5c2a3e294d55b96aa7d322cce804aa0d0275427b5fb05771a73bb7afa6e585e6cd5c8052ff9c162ce69913bce37cff8627103b048cf1ed1a3fb1cb4847798687b23c75891fadbf79c382afe85c9f1600bb4b174ed1bdccb5d7a1738dd35f515b35d7f6fd7bf1e46a0cc2d0b8b4d4ef110393c1595d304d8987de7b91618232177b9fe58c07fd312715e4af736c77c25cfab3cb59f58839b5348154e2406334cc41eb5fa02999a439e9f74e5eebbdd33b77bd84ffa471eba7c498317ca66536e6a25d69216838abee08c49244af93df1ed9f08128ea4d16e6ba7af918a7223043f3788a61755457cf08775d59cfeb548b36b8760220c6c89806160b540e1ffeb8c2913e09a34041aa53ba3aa0c037a09c961fce59709aea16b64c96d77c1c4048c6ddc15e4f0c03ed83e877a56d244c180b16726aaa89b5d0b70fbf5c73eadaef6161f2980aeae7157815d3dae4d72f875196453cb1982cdc3fcc7656f81ccf0f6ef4ca60dc2dd484c890e51179af43efcd1c297be444c8ae199c4bb11d3052809c52f8a230126b7a04fcb161a7dffe7c64234d4addea8a6a34e171b939a9d8dd27c91272904d34118d10218f5450c864e1bbdfed14a7dc1c57f83cf08026ab202ff11e3d1f44e3e6fc09c240c8c45139dbbf1b2479b8216c42df2ca42b22c596556574cec9f32788c5d2f065283207ca0936fda575e027803b5bdf09523c337de0c465fe4a4fb36159b73fb3d6966902f1ba626207d32ffb532ae8a8b7215417a227e734c9ada1eb2a3a1c31c401f72b0aa18c3410f19ab9f6c25b66824fe17b47562c2b52a363b9ac5f046833016e73d4633cdc47557d6d438b546c76d1245655243c183015a9894549b1de890e95293c1c03f32a7bddaa1b81c2f426dec398da0d254191f86afc014d6f450077de85439ce2ff3801d804aa060a89884eec647877d2377086e7f07caa4b022cc28dccf25fe878c798b9d16d0875a47bd7f34defa01e5eb82e673294c62e798a8ee19cc80eec949a9174ea05477e4649a47f51504bf0a70efd64c3f20e8d6a32aeec7f7dc9d3ec66001caa3451d38c77aeeb732b6588fdfc8d1f0e282c601798664ca38a4044c21584ea21b8b8ca508e7dd6e5c0b877921813c11cd5809c484300e37041869d25b40a9136d4f334c677d23bcabcf65871e60317a1fc58a474c78519d59929494d0e536a2261c375de7510ef6b053c47d63c57b756829b57825d7e90d45f003f365239258f1c12c643c62597034f4c38c6fb7defd07f689e761befa6290ff1c795ce8ced2764f9a7036390a04628f7accd73a0bbfbeaff66ab259b629cf27b37942ef7cdb8e5f6cee18147deb6d96d19aaa7d2af5adeb78d797ae6e088e75f70e03c89c14530519b25aecddcd88c87231113adfdc6f2497ec6828d9490f310bc8462b8e84b15041eb6c3b61a24fd23c423a62ada1b859c7ecc82c166e46a8700382e116e2b53c00af633988d9940f5bdd17f8dfb4f37615d3f9ab2fa46c37d7ed6540eb99c52900b8ed3e8a2a662a575c8178ffd6f204df7d1e190080912502a6a020211252ae9fb1717a6ac25865bd106a0180c608d6d08a748286ea618e3a0087225f330c4dd25fe07168b84d19614267b82cf40b22cd1133ca6a6eeb2365ec379e1bf123ab4cde8416201e758ea823ff872b8f7a120defa9efb9a3c7bb1a7ffa21ea7a701c07d0d9d824af1d1ee633f80e6e82c1db209511a099514b8a4b60fe3d678a3c6d3242db82898727e884701da109cbd1189b3370e874af08e78c9631589e0ae2147f720b0a06a9bdadd0376deb022d9e22055d5638321875f0b49ae043c8f7b50c3c4b3221dd632ae7168766850db3293906cdbd1f4485d768bbc6627225af49c290c043969e1d57c70e3033c432d2f20b0d1534dd80f86573a059c38e461887f8e891b49ef066b500085449354813210ec150c661d47556a931dadce2228c41f44d9d65ed0f4d8f3be62e2902cab45acc734d801fea051a04e667f0dfcc4239812f034e3a90b5f366d1657c0afe262aed4f072d3ea3c18bd25b98a91d1653622803d9e4e670ce7274266c4da17d1f823686b502d0cf62fc4398268cae400391fb3b9db102a397bc69ac587e1b758efd12f279ba492536620fcd06e4b26c047491f6339954b4ab217c6be35b61e9da6b5e521c1c2d64e16a1842ebdd0498142b50a3f3fdd0d83756f45dfb1a5942da50d6ce02882af71227df6524c82cbb3934c579fda971e2df265dc28efb694a12d2154e4eda2baf9f4f93ce9e3117d4c21003b0a7e25063d6533429caa14fd2910e7a212e426e238f25625caf41adde91be3c0d8dee3515a1468a8cb47d9a87c624d4851a737062a80baba2c229ea349b79cc353ef385de17453831158438778d895a7115742ca37770dabb8c39cddd43b584b3b7fce3733815578cf049ba91d15aeebe6ad086495150a4511bbca185a949bf8b380c87d07e94b4b24354eacc2acc627a61353dd362da1edf697cc29178a880a9a8fd50f3402679b356a72c8cb305b34ea527ec99058a4ac2adf58dad0ad4c209be24c6a30579a24a9f9e9a7d25793c23d9e80918c702624d01b99be69e17d09d161cbca07b965fcced2698d1c3088756475ea77683375545a36b885855a895d686dc0366cc93fb92695078c9b211ee9ed5f1a88726d40d39df35c5702280244f77c7c3df7dfc06ca6828306286b4e037443904be410b9ea0d39b6dccae6788099ed7925d4c67a4dfb83cb1f4c2e7094cd10e09c2df12b11da9ff30c3607e5e29039fcabbdc1283b23905ae9275afb4909c442e6ef8b26a34cb29d1e70dbc26d7b9c42300a98bb9330edecf370d072099990c5158c89939b6ec20e4b04846715827bdf136bc185df993910f3f4468be6e70ee80b3d3cb29930ca4efc5e0d456bd1e287b0a9b5a6c479af2b6a9a7cdb27a9f9e1b134d764c87a6d1ad6e63fa7daf3230b141510d8c91f20de739acbd036a8aa543294cf996a3c10205eabdce5162c73bb93de1d019f8efbc497eb1ea602c6533a60374831246f45a154406e684e45aba0596a321e394b5c00e5994678e78bcaf4310bdc405ad2e827c2a13852af013b43cb7b9bd2192ec1bd448625e81c33b900c2adaf5a4bb3239f270aa402bec59afad65c3a77dec0027bb7fa7472a90b2e47a3c260533f670b2c1227914129dea08a12cd75720da6bfd6cf6a63c9cad5870fb66d0d300753d08c2c44ae70a22fa91697bae4f83ae41ac044dc83d2f71facb0101b433a631f7075f4305989843b005d14af571d322d62ce10e1844211e41d889cf9ec9b2df0d5733ca83a5b4b5c2ff701d5cfa85719e5c2b0075a5bb6196c05aa1cfee818513d311dff72f9b65fc768c7753822883ee914dec8c11ef253d2f16668464b07a2c754be610805922fea0a1091025b28b6f381d7c8fdacd2b450a444d3c057c17d7b9b7bcd688dfeb8e834e22524a767961897909c5bc68c6bc048f7901845e52e9bc7820795e92dd238c392ff145b7edad47f4b279d1c0315a180878ddaa6e828f75b6eb357546c3eaf8d31d11927729dc9b1e290165dee465deef33102d02d1e88b76669e7ede6d55ab6bf75677c1d5b581977a66e8f537f4663bf4fe334fbde977dd5f0c5a37c94da6fc69f8834607fa7a7581992f79fe9ec6d29d83f3f74eb112421ff3d8e42c2ca9586b9f05bd1f644b2811111cf02e53b92d7ffa63029423e1d6881be82086ef54aa49d6387c764684479d8631829babc9d2ecad63d2bf1e357bd751d991556e9d051a8063155dbdba509fd8bc56f3b9119c57e8f4190f0c1ac7a4cc3be2a95df701bcf02ebd21fb633b03a0e6e3e672e70b5b77f501614e190d5e7775b85674ae2fb9b41dde970dd27e63067f6b770ca2f272a5e8e5801ed4bcfe6214c4586dabe8257688408a151f876158bad9d9d14b0072aee50fa6a07524276072dc2b12a04bd04e6b6f67e706ed4947b6ba67c423fb922c29880b6bfeb9e9c8c54d0a340c6df67f5fc0198cc5b4fbeea12f8d535961e0f8f38d421adf7a64d9d3a996064ce32dc34a2c6aacd743c3624162841577e4c16ebddcbb9f7442bf4493f1627c4004d075b07c6c27288bff4be9061b7063a0a2b3cbe0010d1c092d81b68b1ec7db3dc7406970243dd8bd76e2475161c325caaef755534e518eeed7f2b767c4c715e39c577d1961c783c48c00713af2fac3f747a03183a2ee72d1629acf409f8a12e867ab93c30df97df6968d64e9134368b8e7ae99fe118a87517711bf5a6d3c06ec28dedb337640a88cff7ad4f6ad745db702e8c7b6bc95264ba088e4879dde0a097de416782c17ca8969f8a8fb6f4ed3b3f11cf8aea4bc60e59433eb30268d4bc130785b2332dc169b68ba3ad8c01b37e16821e383043b4450d3b8c689c0f805b568ae18f921f9bcaab28cf3c96df2861d633f03173b14a8ecbf1541aebd896e7b35ee7d67947380b7e968e81178a57a78dd1baa1500e138514768170ae1561770dad26c6fccc77fa3ea11482dc6dc7396a85dfa66f13648c1403d0552c04ab2d2962cad9e5e63b49a10d69fee1b978dc197e8f6210d303c351b26a5b0374ec514372cb0711519cbceffb7479aa4caeaae02f3fabb7e7083ee5829f24a4ae8064b8db8e8a5c70f4650d0866924def19fae1c655104313ac0bf8a5f06e136185f0dbf9e7f568bbb76648468e6ed3459c9c233994f6d72788aafa3fa98715d62887d340258b9f144bde735316489d84070fca58a75e49297e38bb2bdab02d06114c4c7cc28c8823eb6e3a28f5c8c2a463c1f3412007a3e4014cc1bc20a70278a3ccc7832965146c12427acfd477b7fbf49f5f7699127edaf6ac225fca6c48114ebc1999ae1c5982c60dc69704366c3831d2c6d3b1dc6cfb7b087bb31ab2c38fe107fcbee32c136a030edc25e7de13e411ee9ac17f63b201cbfed7064883cec1a0c3345c104b79a1b1551b604238f4205a04a365fc4de4dfcb2ae819414bb1956ec4fd46549fb66b50fcb337d55efee3116e72df6eaad1d2fe6f8378113e3624f02638f5ad8db7d99ede8462fd9d8537d3876a708021e3b66c5699ac789a4e8801f869d5006c944f74f8a1d7355e283673a1b501ebbeac5ae534d9d9b298c07c7625ed70bfb9d4549a7875361010a0466304a6096f802b263ea9c37686493ca7c03b23f07d8393f00907d0c7c8f285464c04bf280ef6a4c47665a9bfeb87078696d280f8e556eace0f28d8a4f21feb795d88ff55295793d86b6193c7ed4d67599de01770ad383263380211023194feaaa052225654d307c0ab5cab9524fe872ca499dd31b0f0eb87b57a58695e1147732cbb5fe90e993ba6df8306d8d1d4a7d8e32e16682890ce68065b46404fc7d87d4c8192d0effc8392fd958a4b456af757a9a5e21f80e9c96aeb08118fb3f2c0e795efac97832ada1b752c28a6d47d5fc4f62526030bb0c4a24631e7b0da0d612e28ef982317d7e76870b19556543d5ea8282a8c3def313771989296c69ed9ec8a18bbb07f9a96152c9a4c2d12adfbd05e7bd1772ad96f6c2d47cbe31354f0190074e9b5c2ee2ee44fe34361b939d4a97bef11f896eaf36e268930e92df1030e0278caa4538ea9b08bf0bc21489b786918f5d9cca013b720d23dfa11c199eb4c811d05881a803a58346a1029ad0f36c1b0964050116c3803f7aeefe5eb1f9e734c534caae04d2b648df92098cf25203f5cf3db1d59b355a92ac7b680d96915b32da237268c451a543f554878fadd66023444c2517a7dd4644ccb3ab185554b881040e7dadfa12cbbfc82c63f07d12d9e6ca05e181408390f6b55914f03d9c9b215a6fb0b90a59f0f15d384abf94b4009a581299f1a662ca4532edb64a12f1d8dd5604505fc78d529825c32211fb91eea58e74155c7c7931ce8d1a5a55f7ea6ef12a239685cd11f5497c9c557700b4b204e8fd941c892d8169620ee8013d14b8d812bc33fe84280385a65d2fbdfde67083c37b91a54c2a74a80480f840a3c64b2b4eed3f79892d3645cc62ce36498fe008fb82e29905f7634527de823773b20729487e9d6c27bb77902c38d8becbc5bfb7aa871f55e1143187c8e4ce13b4c6ce2b407dbb00e2540f261b5b7cf64d0ff1388a36c40b02f0b60dc87c521e0b0ca0a2fb8ba7d6d9379db2e466253a45975161a8e44e03bd28fea338eb8d3a5c6ea8136f00aa77bcd8ce22ed13db2f1c2659c53cdc3e2c240f978934705e2aa5a4ca470c66df14f52bfba655bc7068bab301b939ec94beda6d81558bb146c1d59c75807d42319280174856bb5ce4b6bdc474f7ba9e43e4de14494e95e11f2db6d16a1015755594428aa32ab26590edaca060272a491ccc29c7a4d12a73365334847583b280788b8dbb590b64933cf43d4808357937ace0c0ee525bbbe9f0bf4ed3f38dae859a481a7bc8aa6dfc57d0c04e950b3ae3e2380894d5388fa8b9b0aa90c7a87e87902ce8f0d044f978b8a720f7a6c39239ee1d6cdc4a03675c8aac7fa36748861fa9bb791b9b7a7c1aa842fa482ca2d786f8ac900b472746f5e2667eb19d2c5203e0ae0d226cbc376a3a0311ead2caaede19421dc1072f7395509ecb33ac2161182657c884c01d7dce8d8cb5f134da99b76c51b1ba52e22907d1429be9d2850bc3fe13ee695cae4253dccf276d2addb7fed1ada43edbb821f91c626b2abe5ffdc14c5e46d51de12ee9c684924a87e57184b0cc7e58923df3d0cbbe15c878725adda3cd3d3d9eca47c54a62423e9b284d7364db6efe0c7feed915edaf949feae35fb5908ef6067aa5c607860da6a533b50390f314eeac241f5c079da5574fe2fdbc8872dd89de46d266677f3fa66cca11212b8f8486d4346d4cc6227fec2e6a912077aaec8ae53d30c46d7543d138365dac39c275642e2944e848b5005c7e30f2aa2cb46e77459392857f9642781d5fe5113eaca2eb9f904c68de1577d701adfb6be6714aef6c3d242bf98720db9ba0947c5de869b551458e9647025247163ad5ec3cd2efd74237a01fb456c211885b5af768ec1b51ba367ee391c0e538ff697d07fa2be6e17679b5b78871eac7e4795d530ebd794ed03ea9c406a2a1d5ad66ffc57590c16343a8fe219a598fdd1602309a63f07a0cb286931b4684d6fd42efd5bbce792a3148754053004c11a4c29a1580a198a0fe63105f7f211a19a7be3884532c83272fcda0d7b073b451c0c60b886ee67cb6814fb31c8b91b1e724e5584d664b06a5272518234441cc23966edef52572a3e22e004cc19d670fcc2405f924bbf32ae12a72400b30ceb4e5db06c90e0a76cc7a1b44ca1eb182500fe293d2de74793a1dbc952c4b0e99a9cbf1209443ec415cb875c0dca5584cc558d403ebb9c4091c97563eeb7b976b874e3a0d69cddcf6905692339a4936a094589e88c68e0cf38ce257db2c63a52d32024fd7d3eb95fc54093b7d88d3328f531b453e74aae6e5b97880aa89ad0f57c613152e97f80ac2c7c1e0e182a8db30c3b85880a09bd3e6a49da527f49a10b4a8030ac9468854305e55a503ff3c49cf9c994c0728760cf075838197587b5ee66d03931dc3d83294390cf20e6f0d36038543f98a55981580561875fd83490ec6660f970e77c77204e522f8d08245cb56d9c8de7b6fb9a59429a5145608880868086e2ad9ac7c89512d2dcfa816175aa45403fb933fa15b17b5d2fd30cdb16c2bd777b6957aa7361095eadb67c7888f4b18b18e56f458bdc76dab849590f9aa975436d71432edd924104c9ae69aa3738c1c9dbb9f12cd358e1c97fb4fff96895cd5c22402c72fe7309d046afcadde08b9b51138b56568b41239fa69331ef79ea905b86a4473eda242da41f2bb61606172ec68c506b6cb6a7bed99afb2301de39ce65e8fe6dea369da6363de5742666b47942aecb7cd58229c9679cf6399e4d8e086638485d9916a8cf70bd8998c46c6caf4bf57c0ca40a681fd9a7bf11e762623f5bf2fed8b9589ef425221d5c7cc70e10c9b1f17b524ad37155d98e71dadc02acf2a21932dde9db166e42fa9f68c57c160ca5f9880ee775af855ec0a7ecbfadee4f71f1289d4321b9fcf471f7495ac65ba1d71e39cfa9e99cc7d529248be3d49aaa2cd8d87061aff978fb43588e6dcaaf0c9acaaec985292a00b3087d1fd618fa32e335395e6485fdf6cce5548cdb9a8ceac3249fbbefcaaed553c937f67732417bb04be201aefbdf7de7b77667e710bac86201620a962c91a9e280915cd018a9118663fff2bf95bbfa8defae5dbe0b7a88ef5fc92ea14b9b19e5f47be1866c9bf5f7e0909f9fd25a736e47fc986f5fcfcd33d5691d24c8be4ce49f80bb4046cf7642211c001db9a1e6b352850fbd94fdebb807ceb33eddca3dd98f7eb3e1e7711b21085acba923906f5701377cf2954b3cf3f5e4d4a6905261889d38e1311a1f638f5bff7de7b551585aa194c206c1486797229a78c52c6f851057e37eb9b7587880fffd4a74d876fd0aaaacaa29dc7f7f8f1afa81101c6354c4d6fd049723c01e9b594fddcda412275116c4f1373fee6f8b1ff041fad6a3f032db7b5f319458eb0dc3e57fbbbaf11ab8efeae29c70fabfc302d13c780822fa8a1f62f566b5a68a484a294b3af6f6988ae4b786d77777fdeded0e45ff6c17ac247492adbdb6715308dcc2330cc2591e6e4eebd3b0c4c0737c01f7d61764b042fd884224a6a8bba4d2882a40a334685bfc4cecc8de19c082a3b51e1ef6e1c2a84107ecc62e2542baf0205ca9f321c78822d1ece49259dddb7d852b6f5b939cad7b44df5b08228dbc94dd5af54afb2d1b8a9a217935a2dca75fdee751ae294bcd0c967f6df67faaf165b8a8eeae55fd71055b563992c93aa037b1d3b9649ddb14cb4ec5b1b227bf9abd5c82e8d76d877f1772c937a22a95822569b61637e8661cfda10a3bf6887bdf619ed3230da6436f2c294bfdd8e65d2da1118f6da167f88c52a2cc3fc51fea67ffaa3d0ec3fd03f6986d1aeb23ecab736f9abcd902842d8199a5084c91a96101179811dc71c23777777777743dee96502a43b881934cd8ef14653d3afb272e209dfbf65cbe1a6d6b257d930b8d50441c584dfd1c0942dc70986fcdeb146546bd93c84513646cdadae899fb055a8fcdd831a9f445a8f2db713011c50e3f76fcca9652ada7da2306ae03f8dc65648772c931a5613287cc0ffe8b3c032a9309aeb35c2c9099df35d10698db120350728b4112eb8e4cd7aab7a29e5e9638c9176dbabaaf89272ddddedb8b79f07b085793598479a6367ee244ada00bddb3ebcb40c93612769254c5b89d0fa6b212a9a1e69252db38d246e1d54c55ca63d2405f83075fa81db986e25224eb79ce36d4aecf33b60698fe6fa75f0ef37d7bfe1688e57ba89e65022c7cd7623f5011cccb46308b7493e675d9f2b50717777777777a7e15524b5b47938b55b45c5e70115f9fcc68827f727c92d98c250fd0cd5bf3bc0ce20b126ff8dd46663fc312acc8eab27ae65fc7fe0f7d932fdc3f38144e490aa1ec48966c77f2e0f6a99ce797c8a9669ff712047e24a9638913b15d5ddafa8fe17b7f3b8efd4b4e7ed592dab6c9e8c52505ab0aca8b491ed232bf3b3323e3be303b7cf4bfabfe3261d5fc158b8f8ae7fd47d9ea26700f01d2729edb3908da1f2bbf2cbf2fb0cb43148bf2ebfbfcf3f7aa687ef1808fd8e83bc08a267fce7e646cb9cfcbe045a66fe7e8f8dd1e2f7735a06e5f739d53229bfdaefcb6c63f4ef4f95130c9a9691bfdf22d8991e6ef217c0778d8200ecf7f019ee817901d04e068076279589b00c0ec202e1ef41601ecc008076b24495b0327a8ad277cc84bafd03437b7a38062ba38f1ca9be7fc3fd650fb493946e6065b4112373a8fb387a868b76ff012ba38304d1425d56b2bde02b1808e79fe11f6d6570928dfe0bca03ddc1795c509e976f6d86cbf78b8bd014424225dab53f93dcbb65e3ea3c3ee33fd2e5b7965ad4979627b5fc4bcb934a2d6acbbb501d2dafd2424b45a8d49757a92f2db4a5e56b9a443bd2bbbc501da46f21bd0bc521626bcbb7b0ac74511f49b2e353a48450fd5b2505a57b8ca0748fbfb79827451d24a508a5c8ff8d64a5e40a254aae1822d68c3a9047d19c3b92362561194e8405c2934c9fc2081be39fa4fa476d88589b6a8f615bf7f8748ba48582e87e80a1f29d8b2e6220fc3be5c9a69a8fd0bcbca739ef22ecfdb9885d857613f3942289423b39bb49faf989fda5cd68ecf9faad8534e71911b1fe649bf734e7f551e7d99825ce73752e8409aeddd33258fb5cda0c8df26cba63832af64a45d054eb69aaf516cd9af3e13dcaa339df709af3e769ce799a83d47b06c0f9c0037a8f07e1c264e7f9617a0fe0708f613e6c11a2b0ce7cd81e0af3cc87cd51d8cb7cd81a85c5cc878d513f6cfee32697d66fcdaeeffa311dfd17f69dffb404cd528d131d756bd7b434eb8559d5c87f36c6df071f702eaaa31ff39f229ad6d8ea6fdafca70de03aaebfaeb7de9f47cb6054c7454b45bc4a2d8ae33fd5df7fb8731e0fe23def6b1a3eaa32476398dd12cd70cfd1dfd918fd03c9c54b01a07be04214525248b1822544575811450f1794e90fc64a5a179669a3938992227b78c4994aa57844a1d72f6b37efc41885f8ecf00419720488c80f7f7c90532281e66e34c7afddb37ff2dfa9f28f02db56ebfe016e07e7ae658ba47af51e9c15c368f7de5ad0ddbd5a247ef54bb2484e42c004312c922d08fd00f3dca965da8f00b9fb474913040d0c9a206ae6732796c7b4d1c9f60c0d37f922a9a97e4023a58f68f71c9705614135cbf5f38efb886247ba9432be1aeb61b48c254fcd390ceede9f26889a45b2482a0c9f33d3faf2003b61eed20e42882d84f0c97d01b6a7f9b2133e3929ff3bf5a9392a66778a69c80fa339082bb9c1680e9e68208924a5255f2a7c182df36685347842b0c005ef61712b6d73f0b7565b49fed6599709435380f3df74f81ed4c26ecb6c5555951149fc8486113602a8fd005819350b847ff69dd4fa4facef1b5a06b1a26db9fe1bd53b6995488bfec6f456bd7b10cd79b74ba061844d738fa399ccb22a8b2a20610111352ca9e2070fdcfe60ac242cc2ba27a07a7c7f99e2f7e7b204d53ff2f84ca43205ddddddddddbd999953f5bdef9bc1425498fed642217fb955affede230d3d226c619cb431af13c0bf8b4b5d1200d6a5b519f261364655f7374687ec304278b544613ec9df078135695706001608feea5b1ba2aa91c26c0c5b8f6d5defe06a5c82eb8080fa2c593da9b9b7f58bcc8ac824e2eed5bfcd7d7485f9538584adf6debb67a91a312c6ac48a6aece2901a755cbf0125d5b74e3b02bb68b70125d5df9a51e3d6d66d4049edaa6fba436ea55769302b9fbfd8afe047988db2f11949fa25aa351ba36b3fc1fd3d2a7e4d73738594534888bf44cf917e3a49464ac34f34cdb54f1cc113b2c0a28a27aa30b283bbbbbbbbbbfbce1239af3282bbbb233183924a055955954b29a5fcc5c1c5954bf9d8ab58ca97524a29e525bf92cf52be94ef524af9355d49995205cfeca7c84f59d22fe14b26b500414a1655fe72ca1baa9432c22259c94a56b2675ba206bf2762ebb5d7bbe4252fecaaaeaa72f9ed52be5fefa35e52fe5cd725af21cdc9198934278db401e48f924c96bf3092ea68c123bd80d12e0ec1de92b9ff6a8c7f3d16af9557f5d7f6aa5fabffa25b55455c98fb1d14aafdbb31dd57d74523086a5bdb5a55fc40edafaaeabbea5f4544b5f0f923dc1187782185a8babbbbe6f334232dd3553d5dfdb59fd588684053684a5c4352dd352aaaffe3ae7a2a1f21d5130db71a1a11043c134d1059106500af78f90e3629f5432a7ac6c537a9287e20fe882e369c97cd825558190ce43b7885da2a421b0325280ea93484b0c2648f4a709c65544118087f528ad089d048a34052551096a109c95a7c479a5e05894aaa573d7503ddb0a65d454b22a25e283605b89ca501d2c6cb754b0bed38c0f2582f8b36447b22e5af0991ef5a8aa6aafc8b0aa9fe2854f3d9187f4c8ad9d1683e349e0df98ce673423b39a7960d557fcdc769e804aaf57ef9b847ecb15eee514699a67613d7cb1651349a8f46a4fa47cda7fa6b1a0ce390da71488d02f8cccbcb4b216ae97964080b0ff0f4a0c56b2ec6ac4996868dc988dc547d768605a2eacc6b7c8281a8e2913655f13bd949987148f552cee9581cb231469aabbeb748e409961173b040545fed6063220e6ad5d35c15a4399e8da9e290e6aa8f5b24d25cf511c84da32acc2e63923294b22485494a938df1befa14356c8c2daa101655b18a55ace21235b83a95cdc9eb59db56292b592d26b74ed688f5963569aefa8cc9c6545fe1607aed3226b5fa2ef5fba8a522e4f78cd2d6d75cf5232350ade2904a2e4c4575b4e0a9ac80c508c0c6b48b9e21798b6dd9d26419300c44ff0cf6fb01d8189e0991511aaba5aed49d1696801f2090a8ec3dc0754061bf434265cfb10c8bd23010900ac140f4c388b131fd9b5fa81d120afb6ca3f1191a6c128265e06020d6092d5198f153b59f024b44dcd188f007b5217436a65f02f12dc7183b46bf46ef7336a6ffd1086c4c3f90d84f834b10819dc9e9135448985c992841edaf44f081da7f83024bc34db08135310b6a3f3ba1f5d8987e23cc1c3b70a003d8890a45d626c984103821054f54114515422ee650f5875558765994b5aa5795b4a4252d29ad4a5a6e5995ace4655dd76549f9efe543e2e5d631c9676a639ce20966acef40e882145a60032940e10d289f30c0dc3be6afa1d1324cfdd7da68c87f4ec39b72cdf991298411d4bbbb7b66d4db63b532d73fffc732da5d2f7726fb8bba6b996c2e32fd7770272168b4015cc8ec2276a80d5748b6015b98ae81aa93aa16bfa3f898c718a3fc527cd22f4a52266e58be65465a4282fecadbf827511dd2ffaf50924e0bcd912b7265930fd332292f9fbefce9332f5ed26e0757fbad9e0ed23c5a98d5bfd8280d37b17cc98685859624a356be6483576849d2120448df42758adc90bee5576849becbbb501d122d72d1528debe15f0f69a906cac7165a4262e559569ea56483f42d4fa2b424ffe57da09e96e4cb1739f99c12f6a5d1bfb8d012fc927c97137ab33d7d4a734a1865e2e6c5eff04994462f6f83fecbbfce0e3487c64dfef46de8bcd01bbfd112a44cdcbcfcf649380f3cb8bc8bd7d9680ec7c3db70f12fff42755c5cf840751bb47d47f3f28b72b994bcf845edf01d575fd022a51af1e54baa03e5e3ef0cacb3946dfeb5a1fcb6edf02fb6d26f2e9eb51e4af225b561f91b3dd022f15bbea661de076a6565a58787a1392bdf032d723de97da03012e9577a9028efec6cd1f62f4fffbfe31dfadbff0b2dd96cdb33eac58b67d48b9264d94a92966c587eab94f4e6e57ba0392cff428ba07c4b29622d1b0bcd2992c4a27ef4501ee226ff295aa4983bbccbf3f02e9c87dfe121e0e25d68897985a3f0e79f1863ffc418bba7659a5a80ab3ab287cd8361109e9c9c9c9c3ce9a4e5492dcfd2b2b2f21042f80be1ca8a500b90501089f48c62617946b1088d1e7d12dd1529b3ef2dc3465b898718bef523ba5d29ff82870d66dbb983e311f76601aeeab83e669d8f2e6e2db6d2e859de074a6553f995bf51f9951ffd0acd2932a2372d9e85e69446df92c3f22b6f83f42d54e7e549bf425d9ee517a5f23e50f15b66f4f1615a46fbd8f22ecff2375e28937e35266e5ede85e6301337f9bf50a2dff2bde9942e7ac342a2254991f06ff952456df8b7946cf4b37c3f4bf52d1b7c162fdc40395979af32b7d1cab6284ee1a04a5086ae66898347ac8a58556155c4f8b16dab112d6361d18a59ec526af5d6d659a05a9f23fb483b7e0c63eb0b13c36abcba5a6f55494400ea6e0c8d96895b1bd6b8b5754dc01c4fd6d5e233cdc0ab906619bbb3035539c016067b2ca3ea99ea7d9398f7f5fe3630a73a456efa313755efa68ad45cf5359d91603ad529025fc7fffaa63afdd8b3fff5374e4befdd6f9a9690d0fe46a3d9f7976eb2efcfa874acb2fedd5459d486e4a6ea1755bda43c9aab1e2e999c721b600bd39c179c3231c3dfe6f1fb76830c33871272878852af25b7942db9637c779a59716af5f0698c1ae5bb69b7c32fb975a72a234be1d45ac6a9106e34cdf9efb0a92f4679aa90564cb2a7e2637585831f261d4e40263859988da359abadb0ab3bd346dd9936eaafdca9bfa3e94c1b75a68dba336dd4d58ffab5ac336dd4d58f7a94695df5c65495fdb1652aca03d686f4757777632dc180f1855dd88561bf3ed37115c374c8efb7beaaf2c52f3d066cc5e8f510fe65c9e622dc4af4554ae6f428740aa779b40cfceaf10f1c3e83fd5221d2ce2c2231e1611e1e168a51081a279a206c2490c33749f56d52fd09b58c91ea54b47caecaa2e6fc87e6ae80c2ec38a225966b37f82041e51729cec6b41527a88c634dfdd7c6b90f9f2ae424d29cfc43cb30b740cfc833f28cf05c174ecb74a72c3830c147491a7ea441480f18f8bc797d582346d967c9d7c968341a511ecdf5788fe234d7b2c8cce981f1680ea7b966ca4cc4fee8475b8f5eeeccc9ce9320a9645433a2ddee12f568991ded3eed465b0f1ed786d32dd1e82f8ad3a365b41fcd3ada9de934da83c76673e22891a30a737be43497e21f1bc33f4f5aa430ad24fb4b5536d25c4aa22aa4dd7d920a739fb39062772f7ef9a043ba52bee92e686f5f7f74ae137cb086ba404c88420aa26802a4490fe7841f0819a262e80a9c17e1f3e626b83bc2686ebfe952089f6f588cf1db234d779fb0942412e4e8ff0850f7458fa78d59f818c2e7dc2789e1c266deb78210c1c14884324218a18c3d56e63d11931b42413495dc97f333ecb230f08055c39261bde06307b59f790a242f379a2036c91448dea8a2300c50a3f6a76c30230d860476d4ee729e76f5f503927c0f66610a932ba0d9990a84a9409aa315921e2f08ed46ff9dd56f8dffa2f657dfbdda1ffb2b971f2b49e97b1765fc6fcebd931b179f736f989ee1285f198250e51586706c8c3884a8aa8818e11e9f277e9008451154451c211e8e05f7f0ce6e518ec5a1c4cabcd77e4f3573df66ff64e333ecd27bc650f72bb0323808d300c767d809179050c0734a0953bb26ea50fbd98958044c854a2cc739d614c453959db9ebd75c511c1bc3cf33b05152b3263ead6979a8f667198e8d11ebfe10d6011fc818a59cd31b4248df4e77c37def216456a2b9d7ffe23187a16e2ff57ebc753cc2b131cf46c97beffbf1d6b86983767f9ebcf71eed98194302495af407a780c80e38a1491a8ea461a887cb920fc64a5a1766030ca802431b03c7c6e038587186cad511e67b7e1c4ab40c7cfe1c3e139f49cf31d31346d9a24cb99394739248ffdca92a81a3f4de477d8c5a2d894671dc16e58e8a34879bf89b9bc2e80182fd96048940a8c9144d96fc6e8e5113e68d9b1ea120173c7eff753b1c24929433987630955ba430bd6bae39f7e798721252fe9679d51f867bf319c9a209f5410f0c558f9144a34e7ef74a794149f9744175da3d0adc61f516ff686ee31d4e35e74ae48862566fe3a31f3561763b34da6eb4017c8766ffe09dd1bb9f7c06c7d069e834f444e0dfc1da8d3a9d5ca3a3772b809c28820fea84ae9b38c55120c211d4a2b2f7aedd9bc15bf5279fc1713a5512cab57e4c76fc7a04c5fcd66c306ad29c2650279477dc04a46d3cec376e9a1b21991da7529d4aa56af5a5f89266b448454b11a20c599d016177b3b62c380487c2b0a68643d8cfc38c683698fc7e036c614ed39d26889a57a2397f1eaa5e92937fece0f498c2d77d641527e947c5c5f41929e7546182930376342a131111c935c11d39de8e1e7077b40cbf738eebfd77b40c530934e73317a571d39cf737539ae66048e1247f600bd3b9f854e90b7763205663c750adc758fb9e1936b37fda8cae728b464caa6aa74a69f39292c867a604924572c867e2b032b62516555aa92ae51caafcd114b39b291a4599f457585a3696ad9bd2b2c2e4faf547519040412f5da8c63fb9497edc3837c9f738cc9393ea30fe5cbf29ff86aafc111482b40bbe96c1acb0ac76ff6430350c6612c8a503c12a4c2b073b23879080368602aa7ccba765e6cbb79e681994976f0db17eaab47c50e5bf74f1470ef119094487c4229b8aa7caaf76aaac52445593dc8fcfc6441aac49be3442851a7350e57b4c41a0d1136617e5472776c6c64df245305150a50baae4816098cec483e48f829c562f83dc6423bef42bcceef13c9e8d71653f9262b6f8eea5e24f57da8c66cd01a3ef52de88ad44a31631a24bf8c809f3ed54f93faa94ef87fc6a0873f4ddd745a1b2b9ceb1a892bea20dabd87b4295df99a49054c29a28ecc2ac684e919beae3e7701c88e0441a88501525b907bc0e754015e9f7edaaac6d732fa84a22cc4e02499c940dc7671e8f9c23f9d8c9b68f07bed583e2f38654989d998948da14a3689334420f757f5b1991080b84e4665a0d6142f8fabdda7e3a716fd16a0893eba3dd6330638225d0c6c41f3749396590e624f35cf49a3f38481b40521ed18ef444303be6a9927b5e9ba1d1dd18f8951066bffc8ccac7b6184573f2fd270853be94724e0954e53f1e97df9a037649b57c0977f1d1fa8340054f132cd460e445865d96ac227cdefca87cda194e9e57b1e13ef9baaed57b907e731072af7a98eff7305ccbccfa88c819593c1129132c15521ef0518149c9f11f0f88bd1dc2e4df198f35806bacbcc18f0119765953400821b4e4c34d5609218410563046580719658c51c618659431461925109e204131c618658c31ca18a394f1e5cb28a394324a29a38c52ca28630e109e203d4290b83891c229cc9c92d203084f901e213919679c65cc3d423805659e8c3805659e8ce63c39414149496106c213a4a78794cfccccd285c4cccc2d4c62176616665e61666656e1169cc28cc2934f78c4cccccccc52327b6c6116665e61292dc92a6c710b4e6146e1c9273c626666199969c7d633f3c7582a427efc2899999999a3e418394a8e1ca38c9299595a1c394619254b1599cd93971b86f212457bb9b2d2626d2d2fb7aa662f535ea6b478d942b2c81529999999995d482d2c2b2a2d525080f00461a0ead2018d35660ed203816a7f133b55caefb849e522d2c808731fe322cc89915a48f2504f90e4255576cca4e3265532114fc147f887a3183244ca07c4c342766897f432d92bb668b1e014ffe01d0642c573e1a2fa7c4484f99ae7a552b4bb51658f9b6854f95d0fd23bcb773baa5cf9eea64a1f515459a3f29d1055be214376488bef7c3c512590ec9a6052e5774d34a9b209a22a9b283af9ae092caaf491aad2c78f2a7dec54e90348e783a7cace47902a71aa7cdf3a1e55d24ebe4b5195720717455ada9ad52b788cb0000c46de80d2c11f2886a08882e14fcb7470488da265f8891cf80ce189523bc2b3931a3f892c8086b40c11232d239b7120d43c53c04151ed278cb4cc22b12249edef283aa8eb23b5a114b2b0428544576852ad2847d55bbc56afec64f4d686712a5547f3ad239c2755a7f69603ba6a47a8a8c8dada11d5b3bcdc2a6bab6af6d6163b4379eb0814972de5ad23525654b4a54b701dea6808b36b9eead329689e3e43e5e99dfed1a9e6b0d878c9c6499a63266ee2a2d962e3233d7238b5f1cec64036e6e11e16123481865420254f286ea523277554f9090d48964a55e669aeae56c3795295779aeb9ee6ac8f47546f51c6a2b9fe1a2d24d654aae6d460a054aaf678959734d79272122ac453602f9d83d97dedaead4408b36b82a776fe3bb8a8be6e4e2508b39b1088d4a438cc1f9db2d91b3e53554b75f6799f6909eaf057d4fa45b97b8ca78697d5352d1f3d75456d7eb0fb3cf862f7892646f9608c0fa3432a9bdbfa82ad1e7b1bf12faa737d7c8cea14b9b93ebe0ef6d55f5bc906c3aeebaa3e5e18865dd785c5abc22a2bbaea1373c5836d4275c584cf920db3e9966ce2974a36e04333ccd65c6bbfde8256bc2a2bbcad250c894c62845fb1a16a43c586ca8a32c0b6e94ef5795555d02b29bb6a4b429774c0986b7e87e15e5d198fcedd0e18f719907cc0820eb240a2f1a9b189d4b83591fad21234697cea561a9f8ab1d63f524213a10912a2397e184f0328d48e9b0d57c07278839be075e66f7b587d3e44d643a2122c410da325a9d39fd1925c148430755538ef822fb7e71e7bd5bf0ad21eb49b3848985b9d3bd292fc9b525c54eaed7c72a8545124fcb38cae9b1ea36d985bb70a09555de560a872c3280900f0e94150caa662c3bc7153592134c4829d2aa45dc2f47d2730ef27e93cf127036160de83d9fe55f49ba3cefcf1b7c69fa43501333f7e3ef31e777c574713cbb842c051c71f7b59a437fe187661d85fda758db0ebb1bfb91e7b7f61fed848c3aebedeb628e7f7d7f5de7b4755efadbff11b7fedafb7a1fd95bd4e29fe6523fbd18fe2f536b0bfaed73979ec6d5c3f7f529d51f68b8aa36d9e4e340c5e33a4b528299d80f17aefcf53a31cc83d3a69b99aac86624d9b326a6ea63511a01e80880a1f876ba042b9314febac4e0315c2353d38fa93cf8ce86b2e668686c9b10aae95ac64e5dead23dfa79b604682f901f9fe1fb058c60b81d3d2a3a5477df86319bd534242caf7e88df54d73aa52f55685ed8cd526b7f88210e514b9b1fe3dcda33939346e825fa464f33e89453d0a69b809be45496e82d6eff6ef722e8514af7d4733a237825e0e374158aa7ef43e502508606ffd8dc6aff94031b5684e4e91920d0472761865bd0718653d0f7113fc920d7c1f28ee295594891bec359a2329fc2416d5c34df07d30e19deba5e09ec72007b909be454b36acb7a8cefb455db454b9f5d7f53a192d59b454bdf58b6ada1d3fc7bf23bdc1be6d521ee517e50375d1ebadb771616fbdce454b6fc3c26889291427162d55148a8e832a7c212141f50075915461a4ae76f3e00ecad63c930cb3994008471b0f694a94f4549deaf141951f3fdbb08d8b76887adaa7c21d68ed34d16b0b8be933d5c3903695e5faad6d393949282338e62e874ab695105054158928a8765f65c32d6c261d4e37c131c4d8324c441eb3f677d3da18f8bc5d0c047cdfb2364196114350f76943545f98f275faad1952be94ef6f59bd6e7294655dbfa88adec8cfc95ed2527cac646365f2adbf916fdd589fd19c7eab82a5f81325b752a436d24df0170521848f4122aa2f4c7fb979e605ef5802251c3182062068080ac048cb30182b695d58a68d465a869df480e1842c38557bde79d8cb9d81737f603b2d036946f907ef704a0718e55415b58dc7ab907ff00eacd958361c6d80f723a0c7363b7c4da71c25b53106505f8b2719a9380c834d66276bca6718f578f8277423887fb8877d7808b6c203aab11b3ec34142433786347acae80f2f7b2fa525d19464bf9a8d8b1b9c62a1e6de632f3696e7614b79df50beb7969fdbcb9fb8fcca56fa1db6222d98486251254de5c5a6f23c6c2d7e87ed04fc2812bfdb7f67a2da459bdeef9c50fdc39fe5df7b9c11ef04f1e11b3ef31e90921a269989c6079602d4f72ec3711ab55169c14e74c0d9043c82fa22e554f65af61a9d81a9a8ac36dfffc7c9cba3fc0fd2b77cb5956c583e8945b1bc0d1b17b4f43f7ebcfc0f9467f91fa4ffd1f2295fd3584a0ba9c482f2e2d2b22dcaa5ea9dba9ff2fe3729ef28288fc9ea25ed783ccefac25c962175fa51de379d22d5ebf8a7a4fc8d7fca57f4a61fa524ff7aeb756098a6511d1d671433411df1b9b23ce9754ad7bf07a1b8a8f4ccf784490cd58c8804000000c314000028100c06c3e18058382418d7311f14800d8ea24882581c87410ec394418618400801048802000000002303ad0007789d3eb36dc3385c24d098c3684ae6c7f2fc97fcc797abab4b8035a7d0f8961593317a364970cd8fabd1821b97ec79a29e9da0602f0ecf31414dd11152cb4964e431e72713ca4ba426af33874c5e4086abdc75feb33db3227617fb4e1ff8f6fcbdb6eedd7d9cc812d246c61558217453312903d99337e8453d0693121a9fce76c4e491f48994721279f25a7348a5f22411cadbc97d54f5873f166549db8c815bb7f7d9634c97a076ad971824ce9a357229ec351f23850f978745751fcdeddf9caf97094908d1d67a391a460a69f556dcd68b9d9b484914b22d1f51cb68bd97d8faa269c183183399584da0adb90aab25c3d457462f8564e3af24a9120464ba992a63aae412e6d6ad569c0f6e710ba7d1855955994576d1ac9bf122aee1365b9db92a43c3de455aa516d455554e925a445b81ac1649d8141ab0e0a2978547e7a478090219b913ee499cba06932232133d6bef1dacbe69cd1aca94488618862cec4ed592a4e2fc481a73c43206fa0234a60289e4984402c94f1fdf84b869067b7537b083ef7c68ec414b9824f49551a9f20e523279795f3bc59e449a26170977d730ca4c4bae2d20922855debe2eae04b2c9fe9505ab363344ecf8839370811498546612c8a38e5d1548e704d091444b095ea75eae40ba355072212f2966987704f58a1d8ba7135142a9aeb83455d6e03548818c6365d8bcb65b4b1fc5603d840783f1d91fa9bfc9f852d28a46de7a21409690b6d697e7284e18bbde038b9e0cfa51badcb0588304183971e9c7ec88f24157dd82145ecee5164a2d7d20c3d231cb4a3bfe537ad6c5834545d22da2563267dce6332d17febd9ebae78bef3afc28b806f8651346597f7f6bf516e620a4647f2a94fd2fb60545d37d9f10b75375ec177a5d5b6a0db57f717601ceb4fedb1c04e46b1f6b103166783b87c2edc8c26303c9ecc5e377beadd7722c19c890d841d91829c2cd939b101e95b92a82e6979ffa47bf042b8512b5a20490609730e27414c5a3d26043b3c064f651c1d420566d8d038fa16c15283951f9d432043dc1a5e4ce33b685a672ce4746b4892119af99f63a43d4ac8dde311af104e5a79bb73666b29a3881c16f6f06116da7e57ebb33b155027c5a8e26c861ee05dedadeb71c1e7418d0e3bdecc6f5a10f337931853e7a5a2fa7504a5b0397da5de8ff870eb2a047b15424880a94dca08dcc517a8c88aa9d788bc4b28830dbfca7328871c70fba975039a8214a31d999ae71c0683869427cc00f29b1364456251ebfdc7f9d806329f4e11f478cde8ec4580ace29986dcf201561fe9fe42ecd04ede32271f3bd442b2a212988fb2eb149f74918ba34098d643140cf0156136567e4a910be0fe469d8b6074dd60162c519a5a5cedf345cbfce9b74ccfaa1ea9caade468a2f1ac42a2b66ea90b6c0a3c81dce4182836b81dcb6ca8fad2dcc41cbbfa617e2289da52b58e3d04f9478f8cd49918a5bf388720706ee6d0bbce5da78ca4175a5ba76465fd25ff3ea6dc924d1ebed59192504156e8b94e2a9e3c435d261d098f78c06663dc066f6981c470b5c909c827dfa19abbd294b3a1c8f2a3fd2afe39b51a5f5f6bf4083e0da0e7ac4380c6b8cce6f35a0170869e58a563decedf15f29b6d214d53d5b628ca4ee619fd005f187264fa3561cca1a89a2e724ecfe321d1990681a2db25a1b5306798f45fe53d6a15686004dc196580252c915c85db9bab27516ad54cf34f4c89c471ab8ff1017406561c1621a1037e9694c6ec1434490330ef0b71252812f24d0dab2d6322d058a47c273045a6e2470937c3056d7bbee56078af319683b550c36de01591487e87b3a674bf5edc6fdf68b165618c54cab61bace8e0515a219e1b7d8fb3e0aa74b10998f7b4aaff7e84f9b07dffc0a929643617d6aaae158b8e9a7fabc2abfd20729789593bda1ccbc0d220624a01871634f58737fa0cbf6617644b7c1eb10dc7f845258eb23a0ada0a86312693eee25895dc7253018ee4ed58316fb84a5e84b7fc284a4c0f04c1ffc90672f3b1af914e3a5184cd8a2c186458be55c2012bca1e8b3b743cec09e69dc9c8aa6f157a388a8be9e960121e8081cabf2e5536633d857ffaa4b0ce693006b05c1fc86a217612588ba2a99b26d6706269868c18f9828f0cf25da091dfa921ce779ef071f663e293110b2197c123d9916a634007ac9fb2221658c0c069be4a48e383cafbd85bdc635bc0548e896974ff5b5a061920cb4b1e88c55a6c087f45733bf30258209057064045e9c32b9685a57cc042760a4fe5a7ee486aec0359b4aba40c2b07d499f32d7caa17469a59d57f3896d1e9df8e47d678b455973b254a13a34fd2e7232469ad3b2d2cdc6ee684c7ea668fba8577374bd98ab8a620a8adf9e2a220012d8dc83430c78c35f70b1c32506e1f167e6735bbc7217d272ff63333fa0c7669d35b88c59f6103568c2dd60d266dd5dcfbade2a8314f99895c8dd376ec097d72aed572b1553eb00dedcd1070f74c1b1b6d391f337221f16e998f37a933652a06daec6ba83bcfafb7c7f6280059f8807f261c58d00da2e5c8a58165ececdebf526d19859360adeac581d4b7b2d68a73ad2d34b8189312b670c20a5b84cf16d22352bcbf6c0719573f70b4cf13684e195b373c5309ba19c60da5367c195b393f5ca043240ef956201ab8d45a399425a2b67d645bfe176a98aa953396eb04ccb3e13e8150626b17bc40102c146405874362b82b198572216e7761062b1e1e71ab03a2e937549d6d6840d23eb0800c49287beb24fca66f7891403b3fb4d21277253a6b03c8440390c85afb40031448236440ad512f5fb6c8f430a42196c131138302805e0c6d3bf90e6154cdd17bbbfe15a15ad07efde8f00e8cba85824b83f01852c7e4a346da75fd7cd8be7022d3e406fd95c0d5ddd30c90aa474b26b7496fe90ac061e74b5aa320786d2ec85ffcbfe72baa1bfd373bb30a0a2d395ae7ba00693b94f77fc89725c43c1b01f85e94bd63abeddd620bb31594c2ab067130d0a2a7d1ecda4712537c5bddf74f712e4f1e668a2f61c5d8ae12908be8f07a987f64b47c28b7601f66c200bc120e5184310033ae29d493093510de4e88542cb4dc367c434444b89f80efb59a0236e9e0001b4204f3fcc42bafc65b7fd54e2458ef0784aef44d27fefe0131c45cf6248fa7544775f879b456d6fc6630375f553f426e7df2998e978f9f334d2492bb535988c8785fd389df90d6b5e54db591e62b6809408920cb6c8398488731c1989b7e75da59c26ea1754086c03318aae08ce113ad573c53ac2116249a7846c760e533ea8311b3467e9cde519c96ee3e2fb454ec7a38cc7f8c171276f1482b223986be9016023d158af0dfd22b7e2ba9cc8dc11d7b08903f727e71004412eb479842448452e6d646f3f3be60290e85f10b42364647f0641ca481ec8694f858c4a6142b1c709ad45cb9794308843ca4256d02a5fb52f282896cf4e76c15a1b3c694e88e267411e2472a0b15721f426dd87669c41e0df54463b4f1bb09037a72647534c3e191f42cb9052bd09052af3b3fbdbff37056736627119248e0346c76044c39fc7048db00c9fee16e1a97d150d1a7017b0e419523411f3a53404bdac46c7669dec130bbeed3443b3d4c490b0713e0c5194fe442a7e30da81540e62bc0315638650ddec0196397e26a9cf6fca7d9729dcd85fa8e420085da48451290134b08bcefc6de5f81153ca156fe5d8b112a5847c1bd6cc742f8e204831b297671a82a1672e5a42ea8041e39aded3dd3d88562609f0911ad4caa9a6b6f5971317c612353a4355768d81632313a90767633c6bc06439c568c4451d31828e46826602c568c4161489b10c92ec00e43a91821ad0c5a07a292fc646209b8d049845004589aafc9e331149cbde7219d90175a023486d10315586d63877297c960d354d87610c0e44efd824da3cad489e19daa355fc2d081359b06eec2751e83ba7fe28c087e6804e0276281bac1e0e446eb9d4c9b6f94744d19aab33ceafc01502bf3465e5e8e056f93c6721a9a31d9fdbc48020100c79a42fab1c88cfb3fe5f38b540caed13c9c8dd36a4c947d5d0adeaecd2a5e4553f9dea8171879c46d4ba297ed5c293a6b1a0ec4b7068d2013efa29fefbd433640f62059f31d997f14f8ee0e8fd8f6f274c30bfbd054d791909568d7a4591c2316185366568394daf3e24463039f20902ae029a2d61011f6328b9268729cd01a606cf51273cf97150073d697614001cf13955e0cb1c2e8d754fef7cd5fba01c2a661098467019317990c088d87c6d5b2751f8ca253e2800f24ba50c8d4eca0b598c36dd0bcc2680e5748b78ade9a2989b871efc7adb518b18f9c8e01359a84689057a7b6c87a8d9b05fb16f4a57c7c23b429f5c4189ca9497a84670aacbc12bffe8922514b19c08e517f42407384ad1cd04dfe7789047d742bc47720447248b6e9c0a8d071ccf89144f1c0241458717e6d1b37880f87514395943d7b690a0808d5a07cb51239332ba096e9e1b156d5788750a190d175a201982e5a63dc0d02ccd7525ef43cfd260b3e57f19f993188e0164a43960c91beceb918f84046610eb3d28ca0575c93537634837889c6f2f0addb1f7705b88c8f953a0d2688c6edfcf1b05f221dc969cf5f2261b4a4a2bf204ed5adee21ccd357f4d87349b51a9c68be8a04b39fc15fac75008d28f8ee9ce47f5f3a4972fe3be9e737c804e6999f3b9f49db928a4859e0515e812b515aa669fa960277d8032596f44bd64f6b98948f639ad8d7126d32026a8450ad036144c9abed7eb60681bb6e5c7ef08aa1d905ab82fa0835c7a557cc3f066c2281d8f2ba289e421e86a647640e7a89d3c10182128674758b9a2c29780de279e4f3bd7962df503d6a97cb9c5ae6e40e5a80127adaba128fee561c56531d7a93eec25ed59e333807ae6f8f7dae78851723857d2c639f0f6d0baab1df0fb942d96321f408e9baf150ffba7ef0bc69ad3160260840272c7dc837715a85539c07e6a724a15d4069a0660512712e364c0e7e7bb39a544765ca5d4961f95e58c44ecc42d3e75139b1457d62368029b8243cd0da480ea34137bdc2da4bea190f07acea2a9569fa41486d036b0f7700bbe83e53a3a2524aeb2d64ca69a1669bc8bc829c99bb9ca3c61ea23e8ed9b15b59edcf48fde1a19d8592517ae68072ab91d5ebf32cacba875e6280a4b4d57fb019df16aeeb1935836e374cf2e08cefebb9f5b6418167e1d69a1e8ec7ab6357be79767d0319f2d79fb46e358b9b1726cf8ca7f4ceb6e63fa25d960a7d509c8b11ff8ebcd438e556d16d10ee43f533a758d9a0a6697b7df56218f0491eaa21da88d8fc83adb5a85b808c3a9a5b5fed596c416b2b6c1680aea404fee413c30e4f5cd3b87f0c2e9e9a1071fcda3e7dffed6231e1495c367feeab54d8b53015cb46185ae68a9bf6a98aa68d540d23efc3a1282298a78e779bf9b1dd4ebe34d67ceab9a624d9dbe7457f6bea823c99d29be18c05de66258b4d5ea12935b6f06f67d33272bd75ea77d070334b0451ca4b71df6d1e36bb81fb07bf4e2be42ee7d43dd7965f75833c988cc90803702fa196528538699ca28b34ccbcc49bff8b3807e4396027f2894e72d854b63cb4b4a04afeaa797313f564f473a780b380f413face4a8487c832a519e49abdbb22dda206347d7a29c4838f181c050abc4332ac9f4c3fb2c0c0972987165818c075ba5eb1fcd07b85524b63a448b14d2496803e802755fb6128fd4733c906dcc5da6959dbc30290674f68bb3bb603e33f32ee9e7f1740a72bb72882ad566da9a960185c519a6d347f1e49decf7c505873818ccb09e1b7c1da66779684ae10e940ee3d08a385f204ea8c35b185c12cea78e642714c102062c44abdb30ea6d0f8e12000a5d622d26eb31818cf681b2ba35ddabdb36c6ba043383561a37180b3a42d019932ef3bd025dc5045fcdcf4d77eadc2412bca602eefd7af00e25f7dc81cc95ab462b5ac73e3b4a8a30e020f88142d8859a70281b40667ae95334b62fc79ea90070673a3ea5ca8eeae08fb966e3b570e9e3cacda302d58120a292892ed227e21cf41bedb20d641640497102c72f5b7f25ebf6dd3a4c3f836406922a39e6e51c028377738691f698ab048309eef400a341eb6e3ec15524208bd9de5bfd7a3afdc95cea447fa2fd0b8c7ce0dff691ac8374923187375fef4d4a54d48ef3f8c74cabb2ea29859bb44812ceba8fcd000517369093691a7df3050b4b7ef99caece1461763ecb41897f67ac2909719f9351e785cc023866af1f56e6a69b7de01826642e8c2eb22531328c49fc5cfe0b30442b5fdb7bfe20d5e10a3de423e958315bd026cdc79e11cce34357c5aba50559b9047b7df7343e80b8e16e60583cdb5eae7765545fb0956b7bb118ab6f9b001ebafacdc854ef07634e1a6647fb2f11a801bca97b78b1ac1c1ee53c306e979906994b96f607b1ffab299485105a70b5998bbe93c9d5a936658776f95f16dfa3a42c1857ff14dfab1c090fed0f874842bbc115fe3c91d7236735e9684baba5cae44727358ede86ba5ae72f5b23a84c592474016c5745c81b578fb3cfaef2a90b1a137e16457123aee05c81e81420f9a7551790d865f58ff3a0febab16ee2871f15040427962aed92ea72d1ca97523e527b79063fa7c083b6b8a56085d1cb7271e5df68d9a5373e516e1b5ed45db6709fddcacf477bddd4e3651eff9858393257651d6fe88cb7adf4773655de061dcd71c7dac4147aec8ef5361eab74c8919a6001bc64eca3c574f55cb871f8093a6c02021205f2208e25e87d166a425dbda8d7e268637756a3479bb606eb9420888a1e5adc476f4589d63637665ac7b79a0347166940f178a163e30c8e025023192bdcf0b3c8aff690351755cda7f3ea40eb5545067c43336afe0845b907dc097767364d18861b16b8b41a9bb0c85a54237cd9223ecd7cae62d340a6bede95efb87b3a8fce306925ef140c36a48956d5943789e550c76d2c2b0a99c9ed301e20e7e5dbc9d016cbff86fece67bd0d13c4fbaccbce74499aacbb8840a4d91cd92a025f653b7fbeae904a91bc150ee0f320e34d5c16c9bb546171842cbb515f55e439b25b63143a673335dc316676bf9b800ca53cb58717ac343289df94574446392ea31a93d3d24ac1cd42ab1929b0eaef2d480a1f8a55f4d7684799175187c3db9d4a430e3025210ee809b505396f709804ee1fd8dc78d74c8209b38b3a05030c673f764de04c4662a19122e4de3aa8a89052a5ad83781e07eb8284d7664f4dbea0d8bfd755d9fb73c8d850a84beb71fd84183fae7c40d05c8c079d3f106a412feccc740a00802261d5c01af8fcc41b33ea6b755eae9f11a7fad726d7325d4f3c53df6ceecfa2b615139902abc8d809eef5c6f71e7fdbf4ed3d3647400d5d2472bc1223a5d25b4c3cc5b1e79f11b304cee64baf2f5f8ffbf6a5ca42992e92e4df215e81a5e05c7401a64d5264ff5bd49206edb9e89601e20e6760afa6ef85f65c3dd573a1405d09f72f6e7f7b12d0c3e0e1368aa2c482ccdf11bf3252722efd800b71e7694b9d73f979d3881291e4827070459a726a0960e1507262f4239b39631dc431d60d352332b8979a20bb645960355d857485878fed34449f201a2641e97b851e5317d244972758a7435e9197aa20ac551903348b107b4fbb783f6484f247ef02f4683e8d960b2d62d1cb76e284d880f3d031cf2278ba8b7ab230badfa700366a8dc46519dc45a5692f2a23622c8db54e692ee92f808175148d4229b44ff6ed9e48f626255e021c3aebc90cca7dbbf3600e67475d8cfcbe36c055c89d8d675efc1c6a901a8839ac8a862ae60412099722429c8b175bed4ea797986dbd97ceffb4cbe3cf53606e9e301aa12d729dec9f3c7e864187e8058b52dadb09c1d7047f20d3fce083e6d1deabb57d969d2add034a5f923c2a38e9df08cb4c138410887af118d89df10154fe0b0016c9345142cb3b522381ca36c00426a3237c783090680d87fa8ba51ce0be5534da2cacc47a8ae2b4b62f15ebc20547e3fa111437fa562e2fdad4716d969aee87c7f168558a5d44a2b48bfc2d5f61b9bbd62999d1cb218dc1ee5d60318d447e693c43600e5da8a7ece2b5b8c949bebe80b67c3a057863acdeb82f5befa8be2df53a307fd933caab00fb64a6f3b9fb7f09c4b59f44a32ffcfc2920150ceae1b37c1dc73b631cfe1c3b409de679a51ce2b75ee8f213a7b9b51dc74c8a6830e49cdfc14a266fdd734c361d7b711d635299bf63b5f098e23c0638d25f554c7b9e90ba76567f8f2c589fa90832186eb2a522b8280b3428d283b8db33589b8c6ff35eda4502799b8cb8bca9aee3f75fab174603e998f444fb58a8cc881cbec4038175b1b8e60dce5ccc77c2b5160df7e5ccd5a26fe90ef69b3505ac0f2decb2772e4fa251b668baa6fc82b93e7d7a763a5d1f2f3e90810db3bba976a8349cc5bdd9eab19e866fdc180bd1e1eb54520cc3b58d094b3f7051b2f4f93f3d66196777d310868a82aaf21bbc8b862d3bce13da254ad3d33e0e0f791cfa899096bdb484f753a711c20c6d6552c0b3c6e5fe6fabcd06a575a58f0b17b9e312b7717e627f4484e3c049eae578fc93e96211fb8a29c7e43e4b738bae132d6f528b86309bdc4052870c74de4f473b543fb54f19cd483f5fa8d5436113d70f9cd2426c372cefa300d821ee81bea2cacbdfe0062587a847a51a4897cf351b0c7298d7a7fb9edb7ad3c91f601d84e6753ed06770666f82f5070276101d4fdf127f069c25d9eddb91ddfbef1e22c89e664a98811b821c4ff9e4c566415a1c1c8c20bf60897dbec55be8fdade3cd3a964f83963e5480f996fe3ce20718c0162cf69c1c4548641ec94d26054aaa795718fdf5becac3de6287bd98ae461e491614c2ab39ec602d6b3e9726b01215ebdc2ae2546024d6f1d5dcd3fc8658d09a48ffd7f87ba147027f6a5841fd6db601be248915e4dc0bac05823c7d8b7b6055fdf388adf8e5b93ec43ebb8f5e33c45a310bbd84794da3f7d21f6a69c0afde5892b68d38c6a8b4bf74172b8cfc4c6c94bab25f83d239f2de633ec1ed9fb26805ebb05feba0ae361ef45163be068d3d46b73422075750a8ede62e0a9f30dec0165a2434cea422e8874dffec4aa337735f9c75223cc2b94bc89614a89a34e9e9c6e238ceb2f804ae3d1281b4e828ecc17ebedcd387a4d4e1dbf863eb058e5029d308f28d47937f27b5fab035ab8e8604071f5459a1b4a6abb0406569e0ef5008eb27da45fbb35d4662388c8e5db184310b8108edd52c8d4f0ee2ef89e8d95730a17d3dff41ca353e2b72f367ffc3f0e395a84e9a775381d4473edaf6cc81c190350aec6c639017487974fa637c67c49a4cf1bc8e3af14ab8f48a18698f04ac9ff13a209982843c09862ef1a52c4212d5e358af83f721eae756be3dec9e19d8ff869ad9505a377ab9e4825b2e713bf31b688366f33a7f88b1a7a73f527f954bb8554acb4ae08ec8a4783cf5dd9d9a77a2826b442355673c19b779826bf3ee7a37747505b85d7fb60b08f7bdd760da26c69bac8e3774933cac087777d9e95a784279a001ddfad387c384ae34d9fd190b3c85cd11fe9b98cf909e038b6d0e721113b017a9fe3579e2f045a0e46ad4a78c2fe57408167579a1414a4e97e0dffc426f97bd89c8619c9716825712d765417bb5bb361eeb6b9c85a97549a55a3c090e09fc7c2e55c1dd6e67b3318be4a2ba72e0ccd4b4e607e54aa6f7224681789b8fc7c57cd988d03137792e2928f83c716bb02bb5d26945fbefbcb1a08e701910b5c9c34c7d658d5c4d671b122ea2711793b34d8c0f6ff61f337ac06059e89ca246b8feaad6cf4a3f809d73e78167ccef9aaea7979de8fb436cc4626269fed92e0706d0bf15deb5dbfa03d812f3f74d56deda9fadb5457b171002ed095065d92c30628ea97146ef1f3bf05b14293c52da672d1568bab0b990ea332f366ae4706cd8273b917d1c90ba241a66edaffce7b7c78aa0fde4df68c0befea84d26bb34f77199de47e42d05a421d1216ff8b9c946d9fdaf96c8276569eaf81ede9e51f65fb141437db8c005161c7bb7746f7a2cd7d8a642755ea29c77c957a52132d9ada9434c33d9fdb225b33416d43653c1540399d03aab790c2e718bf798225520ccff10be6b046a03d1df4da415cc9640ad8386b80085c98db9c3abc1d71842a34273945d1b9c5b3caff1155a31324300d89e494e9abae887c218b61cbe306fab893939905d880a3c342b0f1ed3c50755ee3a27c24f651fd0b1b1bd71196a1fe8aaae32133d4869a40f7b4d976fa4593290d569d468466b8833c8bc96ab5ee6229fdc8566e7f7e48c9c206cfd29aaffff98d92b793255b28d210b973c899846b0c108aeb8289d511523ec92c138e3095ce6b8729edfc4c0e85c129b99359f8d73dd52b0072d349fbeae5f2323df39ca63a204845f83cf6572c949b547d8e8bfb892325e053c35f8b85884fa26dce0676cf02fdc1d264a63f83cc99f4d0e7467f2a482344abc1b7224d5c6641b0e9bbe539c2d7b1c74785acc163e2aa7c98dcf2784679e30b99765cf18e21ff58158dabacbbd3212c9baf7438a5a4f2165fc6fa6a8c2dea9f02b02db5ac51f15e48812fb193c7a838b15f4a33547b3cf606762a1ef773d3a3f62f15b39f51c70fb33bcdec96dbfa4b304dc0abb7a82b034e15577d0fbed3364558482e161892f9b0c27938290d8dd1c9e9de085ce530777bb28fa513031e4085ab3e9060aa23488bcd790c8fc511b516beeba0f38b54c882fe921c8f70410994a5ca030922494d5062e0c3c056a2ff1074fba19782abce90d1a7ddb9aeb08c983c096a9a784ea7d5122f9ac017f5caa7dba75e81b3bb449f22011a8d2650893ee8f239dc38964610b5b0860c42c5ce531365e13a632d4c6dbd89ee8c05ded3d7b002ebe5f5fa7da20be5302157e8e9d8f4be150896f22e3d7cee837c1ecdbe6f8705f0bad31734d2d2f364931f1b532cdf94ae9b2271176c66827f1a949292702a53b832a7add1f4e380e6b1088be719d6ef3f9ab038e8de7d32fdc0dec158f0a7c9441d79c6b7e7556254ecbf387d266863c99270b9816c78241a70720ea79b9ed29baa43da7733b959f3f1288352fcf30c9b78a38643ebf1a50beaf03842cd06e16306a6dc9b2c813b156eed0dfc72064f6328756aa3e09b8a5cbc222ba4124974ce72b6602bd5913fe68e2367aaa15c0f07e6b0dd80ee66260044772af3ace272bd50e7b775129ccdea798a05d071c4c20162b7ecaef015a8bf7c816e8f904aa589447756fcd9edd05095c7dc6df6fff2502d54b412150cbc8fb5aad08e3e755d2144b4391d8b6e47a0771ec4232a6554f11a04d7f35536f4ca7c9097bb6944a134c78b46fe7bc25ee220c0061b2b634d9ae79a7490982030e6057fc6baab40f97cb5b5a317fec477ce6b1461c0ff0bbbfab8018ec6ed34a4d39617a4102d5bcf850e23254a08c8129199a218a350c3dc0705b50b2704fe8bbc5946999cd10357a6819cb30c38c322c33d343fc597fc7202707cfb78600611551bc1e40b8b40d798acb766cd6bfc56c55d1983995fc3141a6cf1f087c5caf4c0861fc1644beaaf1eefe00342f1f71fcfeb65a9458b1a48f2a5b177c7fbf2e50ffc1183e41e119e3ff3afa8e541a764bd36035bf569ffae4f82d7673feb2f59b613ef2e8c2ceb664e10121562c86d60f8a6eb75fd2239a2285bd1fa31e7c965995844dba22e8f5c772a604ae862165a52b50e6382ab2b151b60c8798ccb7360ff329dcac68a37c1819edd6b9e71b75272bb15f16f6577c7eb4d27035285e282ba8e682ed716e8c328c261d2c556df6f3077ccd253dcbcb37c6dde18f980afdc072483be2d128b21bb921069beacb3d1ad3a753b6f729948adb41597e61a018f0e38dace49a77e450e0fb0d52e6433658539a97ae37066acfb12966853d7d067c943f2afb2f3563559cecf7f1dc4c7e828f32a1ee824a1dac8ddaa36448cdc2a1c5f50f5e669396e9f7a6986d813ba00d7c525fc9c6b5375b0ada6954fbe6c8e04ae05731077d98dcf6654a892995934c53a1194207c97bfc8bc24dbf395f84e6086375db62911b7f0f55ed28361340ed8c5c33c55fd0eecc26382ce01809c03ddae6370fc41ef7e3ae3ec478a8d5c84fc7b02f033e90bde62a7410ea2cb77d5e1f13c4605f78025d4d3bd6c3bb98ba0fcf1e12d6dc10ed8b0d34a1bb27592b42d32857c7bc4c8eaf62594fa13322f6c05419dfd36b737f3649d6642e60106835ed334db832a4bdaef826374a4372925a5dea318a955e9730934361b4c920f157f30352ebc6e44d56fb93f243aa204be10add995a50e712a962f974d562944e13e4d417fe0cf41968e17bb7a4d89476b511559ec12b92dadea779438b2b8a5d240dda9d9c57298525fb724fea30d5e961922c691d562780d1976813ebfece778c64e3ded03541f5877102107c3c060898b56e5979685b5d70eeff2667679bc9e1b1c8629b16027283df566f13bd84e0d634b1b32587f612805e010d8dd8469ff5624afd34e1831e3d718e1a3da005619b872d5cd2d53bc2016eb98da2f9c0fe8a5d05ea9637a750261d5a8b563ae75d0f20f6a3656eb6451e17de763624e2404370bc744c2500ea526d35c09f64337be1a2ed97cc5cc0d903173d3c99966c26ead111d27db195ce7ca137a16dabea5b6195a24b62038136a4103a366ff405c4510608232ec4015a244089332684fe11ba2db7f167f732bacf6004a7ce3eaa54424301cb72df418897358550f963af314abe1a05b99ec0a8270c510a581154d9e5b6f2c0904e5495eb099a98ee5a50fa7d0a3c75ed56ecad3978edab4d42521403f55b1d1f926b8c07c1d7bd703af31d35f5ca76e9ad27c25f4c7aa24e9846dc615605e19837e6ecfb4d33e8fb052ee5a16b14a1382a8179a3f4c9ce95fad5328ec6a542963530ca94a07a79f8b0191872e952a0132df06ab39593938eb3f85d1bdf5303694249f3b52d04330fd1316194ee2fed02aaf5850beda3c4de826d1e9e466e3f3008b4a76b10086234bf48da9c491e02edd9a3f476fa9d3c095835e6ec0bf8feded4e99cfd7d869c56d282c9066e0866bd3337ad9638bba09e77d290e4fd1d4a615f4634c05b0ba487f9ea372bfc0a997a03ba8db54e4a3ac72ecf897c3fe291e8c00544f030e251818ea2d872f7a25234b7e405a5c12358aba3c938cb8d179bf556213ba6d9c6874c819bb5af984e73fc69862e4088d28c2efd4c4febf0c9d49f679dbd657469e814945cea7be7f0ea55891ffe25e0687917aa1b159009e0a9fa9cbb729451dd1a00fb4210e6e28d0c8b20aa6a60595bc551d866437efa95df45ec632fb2eb9bead9c8aa67ab34222ed0a3fb3450a37f960873bc122251aad37e86510492e487a8e00081eec4a8eb7849714338f365b975e5152de2c8f6b0d4e2706eeb4388ca4ace8cd45b1d7de700547ff3ef669246e6e0d6e82d17de539522107fe1f28e0a6bff45244ceff923217f2d4121416fa4a7bfac8c650c8588c7d667079d5828a1332ce9c0dd8995fe66d646a6b5593c8870c072fff29971ab9cd64e7b105444691ecb636353f36889705685cd8099808e31c6dc706e52c2868206db79881a4c20b6e2315e4e02177afb827c34d1c7bdfaa8c506d2e3598f97d2d993a5f5cc71a7bd19491e2b8ff73f6bf5f9db6c3141eb0fc23e42e8e95e5a6e50ba6bd477b16915f93d758a3ed1a6be5ca96ce46e11af6dff02cf2b079732b04897e006afd0c8b42b22bc39504495cd32896ff4be839165cc773a0b6602a4f2a7784f66949c938848245c5fdb411915f56ee9c004c4fe0fc45928ce27b682ca13a45f58b716284309b22a98939a808852783236c79c7e2cb765350a646f04c043b98f56babdb72d4a1e9c685f1f38113b4381cc7a820cf8beab5d5a79a6110a137573dd3092df4adc0d1d12562e8b7b9716d581d2dbdce42459d07dc2ed944a0b62b05767c10bb70cb1fcc70a7179bba44595ed98c8f0ac01c66465f99491ed022b898ef20c19afcc091d48005a2bb98131d7dadbf7362389528dc39c25276950bc116c83a4eb2edc08cf2bf226747a00f87e082e654bc1d2702d64c1ef61303dde991ab3aa7421c5fb39f137ee158bab80acec60ae68b91c6dd3e7675e5bdc7ced73c9886804566b59509780c8ee1dbfc664b698e048b2c0306f68b15809e5e210f351201bfa2db3a74461708b389a5ae1f2833e5acf3374dbe6f20326741f0eb8e161ac0d14d9465e2e181f77351178087508fb8dfdafa1a64aeb8d0066d34562772a1977906f4b04b69e68267b4090ddb48cb004e5bcaee1e5ca59c2cc93853c70071bbfeb9fc50956bc1fbbdff488221f0075300400f6922acc76ad0d5c21c665fd22011e0b3051c53229f2d17cac3c4f1805da22bbefde04aeb2af52d6647f418520f03c5d4070ae985363b077f890e9e7b310c109dad7e57490a9026d5e4e33eb8718f85f1cc6f3d860723efb83885e7c9848e0b6b1219725bbbd22abd301f2724e7355a201a0a3db39cb605693f3ea6bac8cc5aac208db53bbf3a1e60a21cc87ed11d568f3c766dff5d6329fa9ea6f602e0385e4189e94bbb5e584329431799e60aa6517b3cf5c39f458c08f0d2f4b3681fc783e25ac0da8ad5aa36165bded82f01178c1808d7701b41740f04ef5f6d48991fe4fd80cf618898d9318222d5fee3410ac0aa10ea51752e65d0e6a8cd2ed6fcfc57bed8b81876a9512a52e4767805fbe06eaa2e80ea0b2c24e54ff81db06ba02b739ae6393f9f2230d2eef4a86e2c44ad3ed3d94698f6f5fcdf8ddaf5bc5e74ee0ebe60a65a050b782fc3e066450a69498e0b7408ebbe674945ef87fc5f27676eb0f1fe80833dc73b43069224e6406c993322f07585a86983af12f7a0acf2072a9905355dcefaf4b9f86a1082afe798dff118b96d30a5d63cc90c1cc329629a319659451866546384a7efff3134c2e729fbc99f7888a8f7bc6b0a5fa5bf9b61f233ec9dd98099a1015db1903e2130a83cb9a100f01af65e096a0b7cf6064049899946aba6af09b880efc6884295ca8c1cf44c6915c40a6c232d2764b9363a741314148c258c6218f1651570e0847ca8f3a052f05a149e2d75ab6b829d844c9a5c5dea45a6510ca84a56860828f21c173f199bd1a75a6f0263a804c57fea8c55e6002dc268cc187eeced50bd63597ab135ab6bacf0377f0551067258ff3f13f478b5bd5ba6f8445cf443033356009f8a9fb2bb0c56bfd9307ca0dfd60548bfda348f469a6bbd124887b25e987d022c7e0b54a3b4d721775dd1c7ef1f64f19a2034c69e5b698c32018ce56f3610ea1fc73ce275211fc11e82264673c48a40bc849f4fe997f1ed7910498434bb86799c6cd4c112806a40f0b37f5c68aa849a0ef974b83ba5c4328f50aa944e569c6bbc5124f7318f6be25f0a27eb69ce29ae1a3b03c216f9f1322297c46af9a0d781cb5d22e7a75333cc655066dfdccf135ad800e176fb153232df731005a6e4d64483a3e73ab0b8f4e2587e3d270895241f039d967363881f1f43f04e19e8eba27e9440854cb5a5fd4838ac9364a77059db2e33b79fbe6dca4f64dd5ed9bc99d1c9a440bdc9e62de1ad5792d1f8fb131da80ae364d4ee865a29ada7305031b9404dc87381e438790f25305fa800293c68029535b04926a75b6f6b1e1251f48f0789ec9f365ef067c4221cf797ce118aaddc6af5809c242214dacc515da4928bd75797c8b321428a7ddf7628c1e1b9799e01b9e5066b3b59164d2340372aea64bafd404c9f85eea047c606c5a206dde708aa1968038d9cdcfb36723455acd89c44767a295bfc13b13e740ba8d1350586ebc50deb2d1e843aadff7571f82717279fa3f443a25c18997a6f8102381b465d256ee9f70805ec06bccbb1ab935021937baafc0927059c9a46854c9160bb2595f0a596a1f1d2b9f8d0561a8316dd3e6beaafd0ae68df973a8a8c78440cfc1301b58e75290b87ab19fbe9a104bd68bf20c4cf7b6cfefd62bf158bcc718ed077f67021a09156d96f69a33bace4365e3da89aa94050541a6b7c8fb782a2a22979c3ca9ef2aeb91d5b4169efbb6417185ad8180568cb54802040a5112756da8291c10efb10c0214aecd17fe3e2624ad301ea03bab0cebd4440de83d4c56b686933fb275f9b58799d7cda6d7653eb951008703e3c2af509ee0c7c19d48cb3e8a2abc56baa73b8161add029e79d286f8af58532266785911343a401c2b02c29113c87e29488b0dde0c32cf3106c866ad62f2f1c98c3681be09d966068657e58f0b286275314c12390a4314bb7f6906a940690de23decde85d62839be1cc4867c65ca1bfc85c900ba10bfe718fdb65feb63fcd4f4e09ea08e2dd90ae1d935c64acc354f15ee4c84b22311edd07c30c5067d82208e88564958b8f2f0a60ace6ebb6a7925c6625d4025a0a4f800733eac0fc8359482bf461aa2d274beb21d71c6c6b0dd3fafa6e7f0fa2570e3a7a47342340518776e2ba584bc815b04d387c723679b56efb2b981cacae4203ab3a77853b052099015a6716d54f27dd3346901d62a4a73a78e2066c475abd2c9b18eeac52cc812c3548d1863b886b8004f089fa9021a5c4998230cbeaa9893ac897f4ef890e1bd470bb278b00d770c2f3b1bb3368922b0634634579cb389192ebac9c83144b158714c1344589e0bdcba5ce9946a640ca25f7e1d7d3c6bcf4090cd1e57f5618c19cffb6c424d8ff79ea262b68739a894da833c8344319325b660c36d8600b1ba1ec4f652328ce3f643a6fa9c42f5dafb96e0ca3c7eb6a673f49f1bace8fcaee750b4d1d6c8ec589759f6a8fad8a9c584c34976fd8cd4089213ff62cbb035ff473e26269aa7f1564c0ecd2f20cf69e6b5b59a6fd5d90397495c6827907d7abdf951a23e632f9ea72de4fbe5da132ea3ee5459025fefbc5dbfb939d46c12aad8496f60ecae5a25ea2b5c06792ece19aebc0419a761d2c62d378b362447a68d3272c069123ef6cec1c80487266925cc1cdabea1115052a7c1a2ab12830845150a9b05198d909ebc0f26703d3cb91c08e5724274fbdc30d7eceb2cd5d162f7f76eebb1166618f57a983983afb34c406b3ecae30ef49d71ef99284991aabf6a4bac08a8c99943b1cb4cb6069ab294c2401155298374605cc24642b14e1fada622e77fc5ee0630e87a0e6b5d35a74fb591f8def3044e3fb5d1b8a4f21c4cbada9d70973ec7c859b6adfe8e0fdff20fc6b804b1064e762b9b638d23ba3feb44642397c3496f259f6cc45ed006f91a7c2a75d45400c10e6c4fe977fe22ea7ca7c4047ae273c03635a3a4577ea4433fd84a8a36d6cfae39024abc29e9a264ec40e5c93fc706a5cf433c8f75836e9eaac1fa21bbb9e154af8de3908f1ef1205454de0973f16e929d645ab539ac4192995d678ece26ec10060c24a40b3d6c951448e6ae9dea569a4b53ac70a61c3f86d13d3a04d8be61cdb3698e697e6c11fa2579c59cd6e4e1f51363101c46830fe8b7cdfc8e30025b47fd28f94826d12cb6d073351f1287cd6e691f56b947fe7baf09fcfaea15b1b26cd8ebad44c370bde65908dbdd9eec9a1c06354907233ab76fd560bb78a67f4fb25c773c1d5e0c48655b6d46728430a3eee27a1c653227c967542ec23758c003b4733d8566f76b4625734bf9c962aa91dadbdc18d5fd78aa3f824aeda2e43ba16ab8f04d41b8733f7d8802fc26f32fc69563caa072304b875fcf6d8ff073253ba2cd420b27a7285c687f8b6e04af368befbc5bbc5c9ca376e00dc2c9e1711c06772109977b42213ec6f91102901b64dbaca4167e1c37cf8bf47a173d00caa9f07bc9d429bcba9c32fc1ad69dc3536a1a7ef4f9b815522df785dc9f3c9b54cf5e6f96729c656bf98a3838170905664af58521c10342c685ee081627f7148630b48e16a3c64f006100bf8aef464a9e2ea5049a6284d6bb492454c67dc4928b3e88f1f850fe8b849dcc7f7f8510c5c61d2cf4981ec6562b1da8ec846215f7b4437459b0edf58e1b1400a5997976e5484cfc644de6a8ad44e76f2eb46d49ba08ba18b7a0d580e2a0ae1852b8e5a29d57ce47547f27ac7eeb0b4639dc3d813f42ad7e453b055ae8dbdb7d69e2a5a3d70605186fa6e65d7036d18e5c76572a3f828adf639568268084dcc774df8acda73c35478b1755fddae8bd4769b80376156980fc3ee74737bd62941daf0276834e8674be437e0ca722464a43da674ca7875ac62e6a8f59422ca2fa3634cf53ba72d3b9141162fd66538527f169debdf00171972e8b37838e9652c52c038d6d44254aa33fefd51a57683ad08ee580b29f0033e93618957498d289b8858165fbd6899889094925e9ead247c448b862771dd9671d04d3644df8ab0342122eae3deb0c13f43db25d4d63227005003d0a7c416a94a666a256338a184df89f8fa397d5e50fb018e6e8e27df23fac6c0eebf31eab6ffd7a57e9a205c46f8424ec69ddbf2cfa9fc83480c110efee5f14550cdf6285d9cb70b89ecc6caedc2168da6d05e732d9e695153d223150cec236e0abe42d52cb26a7c49fa801c69abc7e368bcf133dec9045bcd33c794399d5595903a6db8a84aaba94d894e5778fde7010d8136a5c7b281bd43202afb8931cc4337036bc4d7d8e38fc439b6401e93c1fbf6c7491cba52ca408a5407736ffb223f2c2a7aceae6efed54855d53cd78f9af0869a36b629de88defd564d8b69df7e71d592f5fa1897da40a083081d4911710096a29dc8a632dee86805a38f2620213a1405af904fdaebe560f8ee1d04b367559c206cd85b348056536f3e7f5d1af982eac22e22faaf8424e617d8c8b1120cdccfb6b758ce42969ad676437e2578048dc99c44b28bdb2101519a025fc626ae86d9c81cd130786cdba806207ddda149180693db3fb9a19d2ad93794162160131e6976f2c4de53a83dcd67dcc3320607042930f625eaa3c0a20b8b8df23f66e264cba6f16f2801bca8d295d2dddd13c7bab256e3c3dd8a1d1b8a47d524faf187bfdfbfdd1ae387a671c7f9422aa66e16b6a4ed2573b8eaf503ed8fd0743f2911a8ea9435a50f0416a61810744425e33c0f124d2520ac626431958dee892b117cbe645706fe642c460f84ee3bd340bd37dd67437886c67cee84c2b4c62a532fc522100012c31bf1ca81d304ea04dc6e5630f00252ff795fa540b9414009d20d0f5b3a2e437e5b8759f9ceb4a167ea0260fc7dd4e27040d14ace1263d5000cf70d680986e93bbb9269752e8b5cb9b659a60ed54c119dd51274cd8d42263575727577421c52d02a3cb0b7a6ebf69bac1aa2632c472e03984155adc007813335d0d310542ac3705e245ee51cc308d1a04efb920f139b4964872fc7b260c93efbf9b3096484f4c1d453c070d5ef2a245f3631205f5e5f78758600509463fdc6c446f44b0560671c92c1021a68ddf6ebd52d9b7e8e840a7c62a6a74720280ea6ba75aa7465139b09695353d81a41787866a8424ecc16d09b2fdb480988e44dd9e6274382693d6fbd93bd3fac31163d82eaecf0a4461f446635cb8d9251642facc04b680b7ec8bf4d8d68a8f0259f6ed5f82f6cefe74ad3cdb89a05554b2c394d29cebdc4f74412d4ae20179ca41bdfe335051581445c08e7c370d6f11db6f885ed27a3b5385f5abdbfd4aeb987b67c2f51eaeb470db4f402b8a912298478d2852fd56fc032b177c476a143dff66f5eb34d4f44b1a4f77ad89b34615088400df5b8f9bda377dfcd31e049a31b2ed16254f5751dbb038456f37c6d2b98da51902148421b9a1885d535c7955670a8e95baa8af784cf10a8e7d0b3296aed374adaa298a2fd32831426f0be6f8f88f96f693f8a98aef82497f6f115960702a49c35edb676902eb1d71b51a6c2cd71b23c7cc95ee4924cece1b699df73a2a8b037e94250c99ab2bd8d995746df807b6f1f04356dc1689a12d2b02d695a671aab8391427ebfc939747570686446419d665e11ad9a7b745ea21ba299bd34e7079fcd5b833c8ee371b00d6d5dd54f9ed7fa6c65ee91b09f70bd8614a38ca324fea027490195905193641f262cf772872056208c69746c38cb9ab79f5f6002389e231402f912bcbfac2c4d2aba9b9d7a40ad580cf8376ac4e0e2bb11019840fff41f9de31cb97ffe8f63ba5c906da7bb37548f5072f11ccc5dd677a59ff40084eab7c718702f59c6fed678513d366f32d95e1e241d06ad6bfe7eb662c1185506571b95e84064fc687366860be79df177dff678d08255fe24877434ce35ff52bc01e1c9ce306093e05d2609d490ff3fe4132e71997cc9731471dfe913c8786091b4e5a4ca82e0d89aa6dc95435e7169796cc5928b0fe5cde4e000a0c706b11942864a870c29af4ab660b21a642ae15517cc369ccc9f8425150bc102d454b4601a2d86fbbf937abd38d64a1e7025b8f86634b5abca0956cff233e1055372e603357b062a7b74ca679d07ae8716450988da3a8cc6ce16b86e706161184c2425939b8998194c306f93082eee80663015a4b32f1e663081d509c2fbede70340a8c3a7cdc3517529f5c94a8767c329c49e347ef0e9a775e2270da6db3f71962ffbc8737fb190f93904b086c20bd2f9a0406b13a58b1d0ca8adea218b722035644200580368320bcc23f55a684ebb9f7dd3135946146c05a89d689ad9b19f75455c1e5757a83fd5cb71fbbc42fba36a5bc80c80ce119152096ed7310df44c72fe57f313ac07e360cd18e1d0624314b53958c8876e8563fb38324e88c814b1c619198408a47ead36a47fc509c0adcf871acb729b470faccfe09bb577c343b6299fc10443420394481b56de4f619cd2788a3ea758d99e8725b65022c1c68c6275a2eb27325022890ff2ecfa2446500e37afa83f45c3f77664204dc44b869476d97fb9726f6c3ea97cad8df28f83dc63815c1f9d45341a4d6b9c5e1f824322d5eca926d4fe4a4d295c5a0d5d8c16412d27c165eb39078edc86d94ba56b57d4fc6525b908bc2ed7a2cca4e69f132dd7b9b6672943d74ee0375b45370ef08f26e00b81128f37f36b64f1b5133b04bbcedc7b6117210a21d0645ad38c56ab7ecc6603eac8c29034ea5bcb6fb77f22082463cc5e03972044a1096016448351e7535a4a516e2581099f1552d5a58817f9ca69f79e07bafdca88bce349493c62208527734cc926cc7c9ada448a1377735b070d7fc32cf8bb4ccf4920597b07d42d4240e5fc0514ef00be3b49f5c6481db1bc2cef05c7b00ba92c17b7c7f96e978649d8853170b361d8c87cd9c644bbc0090c1c34eb844ab3b6a3e55d6951cf89336b6fb083d8016a44e21eb1fd6fd20b04bf577154f9fc9a1170e96e92ebff215edc8529614222b1b1b889931ba1e83a67bc4e9e139cd05bad774aac8bb7560737949f42b5988ca7c28cee6925bd06a456c1aa560b09ead0d35b635abe65084986d04e786ad0a6b743b0724f30224ab6f4f9cf4fa0a393ca753e922d192bafb1ec029d45320dc637208269b6f330e0415aa25613483d167a947c5ccf4d22be07e14ca6299f54f6614d95a7866bbdd6ac3760be8e4a64c8d452dea420d1af281288bb7700630e1b7db69abf8f7024ae1821ec810fa193e6587f4683cd0e45e53b894b60f5a67a26f2872a12d283da6f189d102b61662265d4c004a30c31308b8fdc92f37e366171b507b7919da88812f5a72d0155a2682caa1935254b07d1678c8ead16506fe101f2e95959550b77e6c08dbf73cf606b663495e532276f03574b90d5d7d0e4996ac5843c96e77a920f585ef698472be49c7531fd2985ce47cee105ab2e14a2cdcb7af738c85a8695c9bce942422ca629b160513e55e9b07bb761b87c3ba68b94580c4db890ea3939a4146f540bd65b232bcccf06355b08c394a1de5e3f6b4757fc68a06c4d8eadde012dc0af1138e470c58d139836c4568c83a2a6824f7f7668260253279061d993f8e00d513e0e4c413521d94208177d041207af24c4ced17c87552bc76820388002dd10a9fe23f9e01f087e41d7e4bc1bd526fb3c0f4a22b449b2ec211a8539a872b554f0dae47e8804592b63cce86b9ddf8241082402df5b2bd8602813f4734806e77fd65f5182140e1edc3097b6b9014d08410604792e66a76b5cad01f23cdbcaf786a808c923eb3bda6563f514b0dadc0297e807615d3dd6d586391e66a9294747b4d1f4c120c4bdfbbb5e87f21e813e2991208bb05b760e824d98a715fee7e2429935dfe6081f1efdedde4b9c98d3e81d00cc06647734ed1da15129705596791c06753611d80c8a009dda8a85102489788f6dc40a44649287fd1c3d76223eaa5b06b4c18f7df8eb5adf639abf46c19e916609a9548ca89cdac3e4b10278dacbaf67b3c9cebabe9d137cb741d8c36941f58d3d714512d473ddb22c112021368e81dbd19dfacef78f13b610c732005a7fa0c398de2071844c689be50d468ebf88bdcf1cd66284789d1293866ff62de6c7cdd45fe93785cee117d30711fc16527de7293c261d13a1566bffa39cdb0947b60a47cc7d00811ca4b53ebaa4d1c1d134c54e6b84928755ed1c417c1e4569d593a7e8d005b67987059bd4c7d9e54988b553cde194bd397d5c4792c3ae45282a55fea72abffe6e9039fad8ea7a879f9dc50509905a388c9b438e0af6b68245620c5bdac245828770746d19a25d9e28473b3ec7a815b2126dc03a6203c0618e69bd3a8499e6cd04dc85afad44808a9a030ac9723fd80d2e6ef14232e0ade3c273056809ed41c40cb186f61b85c19d9a5fba5b1d60d4dbe33615ea10e376857945335c811c0a17d93a9808282881c54941326a8803225fb0d10831dc986d0180e144e7d44e000bf15817f3c544317a7127f3685a1fcc53dfc23632af7828abc90f8b3dc148c48cb39eb00afea45bca9dd0f1589994636562a364b2f0c56df4012a664d3ff0fd10efbe4e0b58894440c014cb533284e5f892575e25ad2fb71d1bb9190a6cbac4cb2694ef65dd2301da3aada1b1d65f353f4671acc36844b3e9b6db48fcaaa8ae5773074308e720336d1fd84bb80378da4071bce22877d437fd9df1c9f03f7a0ade304498eb4e2d247de4772a80bae872bb49a27e5e58b13656c0f0479eef3290866934dc6b054ff3140f724c5ea66adc35971156c261dce7405d400ab9224a12a803455fea356e9d05f13457d5c2d252edd0f7a5c32b48c6525bc5b1f06d419dd74c3359c5edf0ced25745a0660f348f2049f9b2385010597294e6221d5d72cd4d431ecf0870e2dc7c5a80a9cc6ed34829e95d7b2d4b5d1d535cd74e4edd202c299f99457187e4829f145e950344c5ae73b2aa24c75582f947298d36b56e31657d1eb50d7a93b8683b8322c00c3c95c0c489caebbab9813e9a2966921ff5214a3a7ea6fc4592b164f2d2a835d83cd612b8e034d093ebe9dd578ddaeb6ef4a1b841e000ea39fcd205275d883409b2af41ce239de1dd5573c11cbcfe1c207819e45db4a39d0cec587d02c53f9ec161f3a226e46d997249fc5bfc5c483d77557653536d82d97f2983ac48203620802df85ac9ee524f653263dc96e321207f9e872068378ec1ac337dd0c8c506a94df1affa79087cb1743ab84d109dabbf8da67bdd2d1ef1084934a712f7fd160cd9e93ae40859e33667dee072e64bba447654e77c131171442275248c5b7040f7239eef3fc3be45cbc3b4782514ee5e573cd127480b5a05cfbbbc9b83cb1302a02c2b78f11b19a18ffa4b9a507b5aa14ccce30a9b65ba3a0ac645dc1c5d8a37c714b1712ddc1c2c6c1fce618b52a94dfb28f2d325671638aec0061a093d13e628eec71c82440119428e97be406513fef1a6bb11d299ed7d04a7a7cb4b9bc694838592f7012d659adc83607e54befc4939f4cd9766a6f2625af422f97bfd3de2d6f264659bad29cb4f4025e9e9f5ad7f452a06a958f91af1b7e9f47989f02f7f6fe4a8fd0d25577e43866fd219f1b9aa0a4e281e0d4d3248eb63fdf4e18486ce5ac9b935260aff954eaadab77226abec02a4b27a47ff7944b243b3f856878d0a85b393b4d40e717b27f301c3e652b95f92cd39fa621c843afe7752085989d4ed0b3e7acc77354481c2cd978352fe23305ff3879fe915c9ea69078e4815ce361226cea79f3054760b77c06ef0b8ee804d36c3b1e21b92961072e3d69b3d06e1ca8758c05fbe898d0ec98662fa55c4b43de142aa29da252e7a7978eba7f703e2cb7e61bb91a4070eab8bebb4787612c7973896b7b58b039a576986449318a1cf1cff7f108b26225a5c60c6cd0581618da1dc9cd1c90916b53b9ab045a71bed07b355ba1b6d3174f06ffd689b82c5851132aa803ed568955858ca9762e9999c6e80fe01e3dc01126b292c60429cf67f5048af7b6ffbe8ec875288c4ac235841fa70bc874784b3ae17072324d87349f2e67de4f1f366c05d9bc41b53fa88de5e83b63461f970a6c4c8db438d4facd1fbbf231af9ad05ba5485e0088b121ca83a08fb828f0191baf4e0bfe23065fbab2a9ebd2e27950f2c3bb75d0fc3715d9b86b032d67d302db7c760d096ff05e7767e92281fcaee66a810bd8cffe5deafe11bfdc525d25b12db75a7be55d59692f358c10f0f02f1e2ce893f2593cd264a202167409bb4e132662817fbe03b18000d35b19eab2218e71dfe108eaf84f6c271e461640f61bd7f8175e85ec330fa2b6bcd39d40368dde6c0a2942d82a5fcc216daa10fb778695b91026aba156b03c3f1da58fb73fb28d02e610170c7cbb64ee4ef6e84c41faf3eaaaee1b75305b468d27b2ad1b8421431e0da61df5b0e404aac4d353da47e8483a2bb0adda5f3a9b451b8ab3f41e976a9080e3891b99171c3fa6bb20647c31e740d31e6555e7865f16a56854c664d5ef6554cd3bf44e8351366594d60df8c774156406a5510f1028220dfb5c2ccb29b3714f40582650057db00d73edd6e22a83b48ec29ed88f56b70e2cfbbda06afa9890a87fe8c9aca47742044347b0e99e09e4b781bcfa92b2e6d17dcbf0989d509d577df85a532e75f4f2aaaea1b5f801ab47aabb368700221f1d0984bcb7f6091511eaf75dcaa694037a14bbf4249c9bea6425091a013acfae6636454fff966d97509fa3cfbe1d2e7411eff2ac39903256483cdde20c70fd28024b9ec7085df8003c0509f2d6b3830d8d5c12b88e6a768c4209cdb5ea85c62435350b9e023a0a651bfd943c12abdb8ebfd3df23302c4dda3c20a71dd5056cfa522306e330eb20ad16a5cc95f4395b0b48c2789b0cf29976ef036cb59b79a2290c746477b446cf512d1233c586f68963f8d9ea9e50bad53aaecdc604aa656b19d0da6923157546d45eab870b4e61106f70e7366c51b7a169fe1fdaba839caf3f6765ea2b3cf91ce8a19faa61de0fedb3a78950fd6b7f70a32b60562e09ec5d02e1c54012588eb232ef2734b148fd676e18b3f11a1a3f102343cc3a371ab49efbba8f71355f73d91d680b9d09b9d6e3e0e0d13b93bff63ea59f13190264761a785df317fd4783085e260c350c94b0856e0f0ec7b68f8b305ca20d49142443c26f291c828e00324c7f2a7e74bc7d6f5b68a00f001368df354b7c5e1b3ad9661194e65f973a79147b127a11505b8c6abfb80d3bddc410e88eba84cdda44182e26f1513fcb17e3b041750a8b31fb640d99d8dd9b679a1d72eddbb90ac2b8a68a6fc0dfa430a3adc5501de470d1cfbfa6fce41e49ca690f907ef0367883fce82d0042f7fde3ba2c38fe505078792529440bd8964d299036d47e0217769fee0a024f00bfe615449f38196b87ad27f991984e8db896403555ead7b7466ea7c1df6a66a9e0a168b4383c52834d25f52528ce3cdf9f227cb7625f12b0b64d9ccbb32e92b363e3a5ee66cde912ca02510462523c7719862aba56db247783ac0ff013d358abbb17497251d09b9b4b2561e92e60dc8b0e1f3ebade519546d7ccb1ca2e8bea637b3a20789df88d870ab89467499b64392c96cbd46637730662441b3d84fe05ca878149af86e55920dfa9676d00b5ea882561d6303ec0a52616107017786047517fcccac03c3675ed3fcba1bc8c5bfe4ccbb6e00c03ec3753f3f7c9ee1ff539eb11bb311e487800994daa734c496fe056f19c35841f90e150365614d0fa0e0a04eee27f6668bb2428dceb6cb9c2623b9595863cd88c5a71cdf52cfe7a91b5f09dfb2a9a48b4c60165304c07a410406db97a6af35363ef405b77498aec42a31acd34a565334c55805a8cf278b7d2876bbbf111d066f5621ed4144b3ca98194bc743f1051d8ca0d8adf55dd3f24286a32aa72e13340f84a82bc9453cfaf9010e0147d2b536395451923d5b15616ee3f61d92dded03012f10a1d98a95310cf8d199f91aded1f4bbb8e34083d704e5d96fa82cf1941c24b4f006c13cc68209de352951df9ace1f2dc2ab546bc05b0893b3c1a399fdd100a4bd2f868521e00aacaa0aac2364101f0d49664c3de70fc2ba76f54a8e9b73df3c62040ec64f550e74b22255aa60fe858d0dfc252e28f7e5c8e7f64830af634993fb38e79ec6dae823dbd0b0a5f98d3d18abd7f39ef310084843ca0c255fb85754be3d4752ba38c8d32924f929da887490de8e7ec62e0be135aa67df0c39179e6cd2faea90198aca2626d4c76b15584e3a3fb232d5c151517d77c257a7ff4b40dddc5ca4a5216098bc5908a097f43ca598f98f71a2c3cf51b77c1bf3b3e4569018f0f1adb50a954968a68f9dd20d6b99a755bb1cc400ac6b736adfe21cabf7c96e5b6f661cfeffe79c5753458e0978b37ac2d140799bcda70040d4a2dcb5fa602f5b731e8855497fedda65545eb9fb8d58957427bbdbe7c96f2e237cbe868f34e1664be413f3d665921c8446f5d2f84d940484e4b420333098f41cebb9cf397d5f857ade1727b8093bfba371887bd44fe0c6cbbb21191e3c6f9eabd1738e8e6903cb637067b217c037bdaf27e440033107ce04675cf8c5bf3526f0c3deaaae9b4708c1289e48341902db4a6f072b829b5daa555affa7a8ed313665e88036648cec19af8f64123e49345aa2214eb1c122d9de39a7d93a9a96d19dece84c7f8851ba62f81dc68544279b941480e4ae061641f7641fb64e767d5e51dc3149af76d50d6673a8a88ad1da8eaf51e4f825c5a15a8ddb146beb03336e9ea4d53120e5d733dabeb145ba6b784d42a37259f4c14f6523b89ec6c031d7ce24f912c448476dd6169533c0919eb96d3288de01ccc571be0d743bf78259043ce6aa0e2a2921863874200740ee068e9cabab72676130826b95c108dee5481d1eb37d72588865b3be5d4b00849ae8174c35670a1de92dc06cc82590a08ba40f15bbe4f7c29e65547c8f3a4f428d2bf55346fd6ec9bbc85371b93112fd0e6ccbfce194ba09b65328bef0f19a8b1fa99bebd26c421c802f137adaad734487bf3b7931998df3e8a0a0cd35832a6081011af6265a5e6d963bd02b7da49fdc411e60d03f123b3011243845f52a87989c8fa1d789eaf460eea69d33f3f9ef2a420918b0fb612b2df5823792b8b016d9cca86bdac275d69a3e2f94157a5c5b98b5a057866f006c26cd50dae7257754bad05a5c6f74be1ea3ca20c314fdb242d5e7433ed2ad23096be892fb1222c19761fa4f807c27627de098d127a47c015f748da45a100a399eda096b099bad7e4637813680af8cd6a237ab6bafbdecdcccda25ac54bb84a0c712c1e1dc2cde5e3faef8cf3d9bc9b71d2792af1c05dec63d0e4dbdb73fe5d4fbc7aef8bacdc1ef97ae0bcb407647815992b3e0db9e4bd51f89fd94edf025401299409839488b73390b7cc31d1713560cc27e324e42fc9010f174f767b17672ceb17715f9e888357ff976202476b3cb0d3cc776a350b0634774121eb2c29578aa0bb8ecc28fe7a0c4856604ae913f4a9666ece31e86d660598a97165afe5826b828faf87f67f15bf511ba50c3aa4d086a38105d6b2654ad390a9382f402e985059e3c37387472bf9682436ec546e67c6028f4e5c61234cb5172f8a48cea3f38229a1080cc3a2bfe57ef5a62c83851062bc635884a06446ea8bbbc9d042931f4de2ba3ca0d6b80f6d2e408710c98df32403a597c548288779b1a14bcb69984ed84ca9e3b3316288e44f001a5502d81be2c8015624dedf368f9bbe0701c7e245af453d93e26e0194a70aca1e7ef6a266013e29ab5128f72588a4324516d3168e325b3a6ae17490b58aa36efa00cf794ba8640b990c85ac8ed2b34948012148372fbf52d855ebf1600362ccc4fe478d0c4ad6bb5d31a77133d83bb5b6493f9b9c9599bc1e8a849bc9182340bf9819be9495a141f92430193587ed6c9029a17b7e9f8c99436b2355ec4a2b2398537c16051c7ca38088e62d1372e427469573f319517b7e820142e5719efa33c2b5b87a42625747bb04fcab1a69511477e8ebdb46d7421562f30a71f34efc839f2c9c0190c317701ed9622c7592178ab808a6c08e4c5c942f39ec5da2670131b2a040a7e61a3fe6d678243d7533b65d38241260e13332ebb4f5ab22d3c3ff6e45903eb354adc42dcc533ad1bb5ac1512ffa10f85abc424bb04b4d07b039b4e258aaa792d1e60d072c49711e236b837d7cf812fe9cc2fa82d686e9fbec93358339b3e3e37cff2f38674cb9e4e8b1b13428e84771ae5ae0896f78d5c296bf477a9f42eb1f5cc5624a498b206cb7c097ac4876cd299b810e9f86a6034c7b86480b4f63fb0ded45a8dd98d951efde94d2056d97c527c738a75c7d4a88010f6a18981a070a6860a8214f296bb80c9812fe6b7b59ecc637910c2f8aab11449f5f74e4c7def9397e1c1988995ef40f5023999e1e0550d1b29f5e455f2390a202f393ab9e503e932ccfc68aaf18c954ee5586f4098ad42d406379b062b3101314177a5e33079be8f116223e852642870d6dfd9c105968baf6d8f2c528d3052ab3a9be9e8252841b92c0bd8c21a0fef1b2e4ae8d86833b26b74b350da45ade9aa7ea7376f5d98e3da89c2e1baed8c9b641c1aed66d2029693f23f2d619debe9177b96103b42529a69e34eb07d90bc5299efa0e4114d1bb7fc880a9c6c0a916fa8e245da3645c18e75b877ec0cc2e0f81dd05af4c82a99061a8a36faa5fc0748d67824824e4d595c7e7dc807f608f094fe49b1f4595f0d739aa2aef8bf3371829d0746f91e1345501c96504e844dc71610ea97ff951e0d3c8fe99982fa289c564fbe159af5c7b46bfc8049675730b77aee79d263623c87a32d0818adef97b4a546852872fecb38d3b19057c2435a56bba007d28ae121a68dabcfb00e1ee2143780e441c8a462c0c1c70684176ed55e21c0ca52d79134a3e90480c0852d01261dc01cb9b5d6dea6f4bb595ddfc4944f7d3a1cb538d648a8cc776998439696e00ff9f85df8aa6fb71758222cd0f9c9ff45e5c659a77db28c2ce484b463ba4115259ac58b22db644c5ecce14fadd87175048ade608526b0c78dcbe1b3f3bce2f5dea34c2ba90ac9bcc0982f697d61e49aea8040c080c15b6f45c08cf62328047b7a576463f853f7757e537c70d0e6e08ad69df1a9c4b954af19ffc092f4f10d7319da7cc695c0557878c8591df7df32a8da19032768919cc5702cce5ef45ff0e8d9debf9b59f6ed2956d0fe87a9cc06a5bad22db73ced370274336532b38c32c83443996592694619ca44665e9ee461879810adb1a860fbc4ca093c9a5034e7307693b3a98c40caa8acc9cdffd81218600e5fcb0eec75d446b1b01166961d0e209ef801cbba904d486928b0a599b65187637b6d414568dc8fe1db863a0d134e57f24a9a166d53d43e83c20f1c74c0fc56bfc2c4382e5411d23bb66b65cd8b670a1b7a031a8e8d4c0e0224a0abe718f985db23046f013a6311435c801615251de9cd4a644ee22c3bc229eb8ae3c5bfe16153f42239c2191b022fceef574395a5dde72aff9856bed129bf11299496b7e46fe66fcb24f6fb093c9f459dc5607f68be35b437e7606c96b496b456f209697b932d496b724b12e20337042b043b8270648240418fda6d68503b7070841bd46e63a3f22f6b674a32358fa5a34a3e1e4bd730304b82ca343dfa47e5198b32cd1b71cdce70896b1ecbf402d3a851830c8a0349266f43f081ae6057b061c386d4a9dedddddda57a296aa95e6a29aaa9dedd6db8d4525453bdddd83be4ed795b6f91ea1a9cda7b76edbc3f6fd0bbbbab26f59bdd83a92a80408f1d11c9401f0f1672ed884806fa78b0902bc3b090108f47e47061d8f77e3e20d08848102a400a521405298a8214a4280a52100447a00884bbbbbbbb249b36225223c6069057632a400ca5bdac8e8c7b591d19e3ae65753a3138e2c65d1a35626cecc0c38d11fca063776bc4d8c84185191c3b70c8f810638c555555958a0c64518b231146aaaaf846155355d58648de9e37802db6bb1846a3c6622197d5918b855c5647625848c8ae65753a35626cecc0c30d1addafaaaaaa3a4452555555552455a8daaaaaaaaaaaaaaaaaaaea5555555555555515f7aaaaaaaa1310fa2656555555dd5c57155755d5abaaaaaaaaaaaa7a13ab6f2ada55df70afaaea31729373d18f8f5d555555555515bb8ab18a5dc52ac68e5d555515b92a563176ec2a46cf23f6f879bc1e47aa09cfcded7176b51e418fdccc1e638cb1aaaaaaaaaa6a4324ef9d6266e60d8739bc610ec99260c0eac8b53a723b1d291f8d1a313676e0e1860ebbbb104208218410420882235004c2dddd8dd9f76036480f1ebfc0102038024520dcdddddd25d9b41111203042fcf0b1222b2222b2223c7a80e0081481707777779764d346446a686a188237bcfbf7de7b9b2f8713999973e6c78f1f3f7edb8bef3ded510fbe91c78f1f3f7efc445ef640ef7d9ee7612fe45dcf7a9d271f6fcc6166fee3c7eff1beb7e9ed698f7af08d3c5e5eae9ec8ab5ef640ef7d9ee7612fe45dcf7a9d27df4e4dbb1a767639bc6fdebb39fb5ecac119f5c53cdeeeb76fdf7bfd7ce0c8f4eb6566666666e6deb7222b77762ab99feb7b8d8cc06f7fdb77765d6b41d9375b6d47162ef51edf782fe6717c92f97408a2cd116666de219b38f0d2e063736342e65e7377581ef606f399999999f912b86cae6a7c4f18e906e9aee8f2202d896266e60d8739bc61120d9436037d3c58c8b519e8e3c142ae0cc342423c9eddcf0704da1a313678ec767753dddddddd906a081b520d1b420a52dddd0d1b420a52dd7bed3d77bbbbbbbb6bc4d8204d81c37977777336adbbbb475aebad5ba4b7a9cebabbbb41fd694f37d6217db5d59d961dbbeaeeee6e0ea77bd3465aa4b7a9ce9ac321e134a849fad39e6eac43fa6aab3b2d3b76d51c4e37edba5b207d869cc3434e77777737e434840d390d1b420ee47437a761c3869003390d610521849d86d447de9382f250420821a4e076777777d7a54f0c7569c75d7ea3d31bede4a8bcae82bb8bcaaf4c2e9e98dc5a9313f954473e6272219f2a7639619ec9353ac03a32ce9d3294f8c8873762c6913265b470958fa60c132f8122e5e44ec5bc114f2d2b62c4553c28f3461cc40982a468b4dbaa9db74b6d76c9074cd36628f1a965ad19549e42bf332eb544bf62c01c1889772675639b2c6c9b267a2c9fcbcbab3c96ec940c8ac9c98f3ea32507587c47dd68112985e3c667f608644091d1f641865334cc46bb73b4dbae51320dc3235aaa41ac60472df95a2de6435f6be9096803bd4dba4d0d5dcad9a402444fcabb132a2befb66a05604ae1c2ad7817a6c984b20fc0fec400ea7ee500755f420775af0284ba4f2942dd8f9630b93749d34ed24ed26827ffe1a88aa775f233ea95813eb3e3acd89e553f7a6841057db23299812e41a0cb98b40c8b5aa6a3ef5099ca747aa35068b270cfec08502d5a32e98439b4b360e100d3cec23f9b74030c4604b4bf4e553b0b945beeda9ceaa8e3ae32b919542c80e22a9f5a3a933bd9dcd46d6eea8e2e31009b482288a9f2dd8c1a61477b9cda5eb4e3be8f93ad17d60beb1aed66d4f86b5a36c0e265d48efb7edbb6b958dcb2d95602a617cbbd90df2f9daab4ba14cf5d72b379ecc036ce4dad1cf795b3dbbaa996f5aa3c89eb71be3c2b07751f6fcd9d31d49d71a35a168968fdb22e5fc765e95af4e5d5853ade88610e4ba298a35338b66e6729a59492bbdc2685635223c800b6f18dab78423c96ebbd37bd78ab0698bc0c29905445c4e3ec7a88ca1f816204a5761031291b34c0ac77540c5bbf1e270c8b72cb2d65b115bb9a844dd3f437a29d25e3a91bd408281c8f65aa8bedcb8bbbd14281e2a38f505873238d7142654e2d28e43669385161c85b9752bb3e5db48bdf18e344a5e144ed62a830228bf82e86ba6d97d6ec4e408861db36bd8669181c33c0de49de759386782cdaf90da4833c16ee1062d8b671224abb78b9cd194a3ce5a3ab783265ae3c452586b241ed30d5a49ccf118253ac9ccf0142c150345a42da0cf660eab4cda99e984c7a28fc95c9330f859f3279c743e18f26eb78287ceb87126f26e6d4d2c2755996156322a1cca9c56359160786007bd5440c0c74300a5a3a0ef2c2566b0125cec9d0c2ca5bf88c96c99a41e59c0c291f7d44658c6e82e60079fc8004322d29a0fe4826d33001a6d12e86aafd9a9ca45a5ce7a80adebf91bce6e249aa33592df69a5d0cf5badc28e7423bc95b6854c46754b99dc9dabe4d0b5a2d3817dc5ea1426bfb6485be71ef366bb36877829ba48b648069ef0ee2ecdadc695953fe9a914b4cbe01d671496534dacd6869417469378d2827c3e8294f19cd683951ad4bf99df22b736a19cda9c5a25d0c2bf14b393e382029944b4151c1d6650b9ca3703835ea8ebaa531de1002e0928fddd57e80834b5c5a2096c4a59d992131122614be137048a1854b25f6a1ee72d7ad33e9a22c5ebd58084e01000e42478f1e3f18c863997040f3a3f2373a3c96295272670a19bd8329ef3095775b00de8d5c787702e51d0158e4f708782cdcb5ed7b94e942004426271fcde9a5e012097a42b9c4a547b9c425d830c6fcdca8fc11509db55a84423f79674aaa66eb759e48d5e45d8c89744daa86a2a14a254b0858277ad7a4995743db0e21866ddb3f1a3d0270e7e382e4f22adeb3c185a4fbf9b0f0fc06ae39d8344abbd07baaa139d59369326dd83ceb9dfb7376cd699f9a042115af7819e7621b3b517001082a45c598482f3a5170c1072a154593ca41e9b05a784e29a7ca86e99886e918f8028c2385382b08188c08c478ee7272019b482a18a2765c7a2cbc33adc363213957920a622af38fca2598b1e1c5a5abfcf68d7615e02a69f7b97cf6c97a419e8692f75c52ae79d8b099377005fd335dba8268935e2c206472769b2a77f3c2359edbd91d83b5d3d9401c64d4505fea5e6bc9658fecc2555217be42e8dc86de0bd7d09ff5620a6d6a0c71896980c0f652c28800f1524c2dbc333fc03a2e7189691e8bc8f9960fb0918b8c5c4e283342bbad23d77661462e722932618e1a6c64e450064683890dc35d52f9bd9c26182617bd2331227172a969f2da463b1975db4c80df4e2bfb6e02d3b4b2d245468d5ca50b93983d8c2e4fe6045ca669457b0f34de92427b48a17cc23fb8865178022e4c33adf0a7696529fb98288ff6f8d1a436d746e558c0f8f540dd0ed4c9dae540d56e438cf1a24fd60b91c2d8c32aba8a97dd648a6654d1a72aa7f61bb86ab45bead235bba884bb0eea87c7cfcbeb939d7d5c9fcf7566dec11c84468c8d4f76c10ece5034548fc7e2014d96cb0a92b3d80aeafc592e2bb2b3d8fab9e4744ae6562a46c479a2de554237d38a88ab78222e2a4246bd2e4ad9c84a4a98ad159dcf4b4a3e9dcf27cbaeb30f84d8514dd4c907426ca09238e083dc749e5572b9e17cb22cbbcee7945c723e979d95bc3f9d4fd485eb874ed34af68c96d08b5236b817d73fcffec22eae7fe80d5c33fa42d50c74ca5a11ba5c0b06d03f7fd68a0fed5c363be893e5b23530303035a35cf346a1c9a5370251a6f901eb5a4cd5a5ebf51bb85ebfae9743dd6725600303532f6ac315bf9389f88d3cd7cf0daf72a48b4dfd7c63bde07a5deee3e52bcba80bd78b4ed3ca8746dac38852233ab583e6f6d0143d9b26ffcc9377268997fc20bf873b600e1e8ba4bce38df8871e6025aef20ea6745b09ba9950b8ab508ee3de8823313b3f999f9bcceca219fa3641d726c9b991b975ce0e8e4019393715e6782c22e7431d8f65a188c8a7494404669ab8498b2bac19517540dd736953af33a7c5abe39a8e7d742c44b734e44dca4a6697aa26601eeedadc4ab7ca1d718f379a4cf350989530ad30236132c19f4eac3c1e60909714c40faadc01b65d9e9b53a59b1a53e524a7cecef8253d16eebcbb96a872bf2e371db93340bcd13517881260dcbb9de1be33a54ff6ed336ae7e6d69d792c403c96ab53af4c44bdae6f5e0a2e7dda98aae271d3ad1e980505eb09a3389ae151679c8089f847c073be79ffb35688f835b75a35d85e5a4db05e0805b1829a3a52a71b1881877a659a16e375c5eb8adb54936587d68a8ce3b8cfa8db2da0cabaf3e5550f7dc09ad82e67a75237d0b7f9f9354b40883c44bb374405358fcda5c584268df8093d9fd3b2cb6cb54b7a619e73a7fbdd67b38395a3dd0c15efe41e1e9b2abf0bc40235aa3cc7b266b08e4bd612b0fdfc84814426f784ee79f739899394c8c75ff452fe4d3e4a3e00827f648fdaec70a8da526efb7e3bf7c85149b54e3b767db76fbc8481bb767958af8dbae0e874c967b3d37ef239f7b9fcf599c9cbfe3c3ea31a10b0485f787eb260f85c52189f732f5c237d79a3ceaff7939790d0cbd7015d927cf34624a11742f73c34bb1caac7733d42a06a1ef948696701aae399af7a5e9074d26807f2ac89879a1c646242bbad1ed19776fb91f9b2a0afe7208f8786eb221d93e8dbec70a8dbd95a21d22105d9e732bba41cf646f2dcdcaecdd0630af850e4e54773f30620ff991d8441f413d12f11bd5ed017aa1a4573358d76d93b87f1c2b5f37729b377a29fbc06501a324a726d7658d524f7e9a5d8b6cf463bf99373281cedb49f5c056b53f4cc0a35d44f87662f5c5fbdbed60bfa6b7743bf4e8119751fe5d41e6787438de7a60b8dcac7797d13759f03e0dbec7270211fed4efea12f5caf9310ed66d4ab8a4458154d7ad004525f5ea500989d04eac9b1d9e1504fce968baccad32e9efe820290f4272be9777639e8a84b69b7a9f497011350f71d0e1978cbf450ba1c6aa8f22a98c693ffa75714405dda29a0c610c0c90baf18c19fdc7ed3491193db1193dbcf408861248b06ebb854d5a9075588421020500236e2949504cc420216f2eee4216761daf021f1123949ee38a08aea6a20ed2be415babe822b619dbfc200234e35d21bb8ca431d98a42c040fc13dd8c71bf143937f30108bc5ab47c0e4236d1e6f14e27e9d3be8dd75719cf62bf4eebab45f87413b8cab94fd5d9e2bcb66979a47935eb02063162189536094d22845e5a068dea864f22a9b599e4493979433727360940c0d49d430fcb0945b674f4df57cc2a4944faa8cdea4c7d279cd1b005f1a01b37ed10edb998d648a666732475c256586fc592b486ef1c04e660c51256998d6e18d98c61b00df2a02d6354cc3700a8cc663993620a0a99d3a9182d8400fa3194ed134d645693851615ccfba47a4925a3c76f630ba94dce56c1f34ded2a4d9345dd33dde8837b54b319bf2527231d26eaf71fbeddaecf6d7be4dc67353a54a3abd51a4dda8ca6c761bbda29c11550937dac55fb76a8065b4db360ea4cd1068be6b2e26afd077ca50e872afb9a91611300a07c96c1d2c984cf049cc76c1b4d23964a615e686806df5eca584a90048980c10a7027c281d3964d60091b20e0965362bc9be02741a8a75ac01284a091c83ca314a29634c24169386895461ece7038dc6a864091e099b9a3a3443182080006317000028100a040322711a853010cef61400139694506a2e9d053214832886821020c018008001800000880000013284891dc30d385ae5997d2299abb4610e738240ae63ef46db964cda312d541a8270305c22e6230f8835e6ce13e81c5276e6d1c17796fde3df6c72e9d238c62daaebb688980a0e120b81887a633b51fcc1b66532b222cde1f4a02c2854c53f7b8dc007fdf4f8b991599fc007b2da0fc8ac1127c250f4fdc3501a137c390a7d9d8632bf21a09e70d93145ed6a000b93288cd594cb17df07bcb57486f95fbb4f5dabc1f25f233ddbe483acda8a7017249b61f8a3475db833cb3a87235afec9cca14f2342ff5d2279789bf8e89bc293569141af44a10ca431e22368bc2bc7dacf707ccd2356db7e4ac26b2f262b03da954f34a25c54d842c00d5748c361e5d3b4e292d5712d53ddc93b4aa296538178044a0c0d301cee4aa7291b68791106c629883fc5b1c429e447efd069165310f155d0c2364ae19d3da3029515bfabd27e60ec586d221992ea21acc75927a02ac18ae6fd4f597b613da0df76f3b97d9263e810d643f5f1cc3e62af14a1f652449710ba5c46cc512560b6d24e5cc9779d91d4d0d4887297b5f004324de94c6c8d060d6af450531f4708431efcd87b4efb91d2818814ff648a81231c7e4291d02947cf1927c6fff938e3f8f9232edb39621f23cef8e89ccb762a265b8b7cf25adbf537d42d64d52cf51e501ca9db4807333754a0775dccd37bb815dcbedc5de1035a0bcb674a14c31a183a1a7231295990bcd570b763798ddb1e49b691a6998281b39de0fdecc5c229eeb93c5aa38dc6c360c9801b2be0b6877cab4c7f9512a567fa1cf023c39893d44e8bb1ff683be912f681e4bd413aea4ad29496b8eda1daf0c2e75ca1e9814c59cbbc40dc3c49d1af945923ca6f2ecd87a967fcea621b4bdf3aae8306a09756407542be5f5b8738a74a34adc16b45520992dcf231bf8d7b251d1d8d2ba2f1aa8b5499c1ef05c77d75d8c684fd38d52882fcece171e32104886abd3b8ee057da7d4907b94ad2675db8ee4f8cfa1b1065ba0a50c65496a3b99f9f3303b3ac22f687a19fe847d03bda40e4f6d73d341018a090cdffdc816fbd4ffc0f6d29d58d4e61ef3c0383c0ae8575b6973e32097c248f1c7d145758808f83b382598d36965051d88a7e0b551fba5cbf63900c6659e6f3310c818745bee4755b8136e9a353674a8670832bca049a29e2e2b1fb1a51076dcf2842ab024b412f70b46047adf67c344e4afa9a2bcaac95e8345485b0149c53ae62676d756cec8b25ec213a8bf869c5cba1242025e27e1849993367e12a29151f50f48cd771d300c714b18df218e27205338b9df755bf7269171fa472d29b41d78fb5f7c3fd02e010e339dcd8defc2a5b84566a11c612fb1b5b418b241fa71cb227cbda7f0324297908451d588c4f6ff41e916e2b5d3c8b32932fe7ff51aa8e53f14d3cea501a6296c9dfd5810bd5b28a230c9b1b561085cc592bdabdc1fc81d2af2f78394106d86177acd26215a7c8daf533b3f0d7d9c92562b6380160b8b5dff6261d578b2bfc703f4928e7480b0413ac454be0792cdc2978e02a7babbd23112b358efa118f4defe9c99901c6dad39c6e5a11e12fc8e695ca3f2d03749ccbbc0619d88d8a327909bf8fc55e035d841fa26e0a2d846e9746272215ca71cf896f9205f2bbd04e6cbd1f84c4ae326df84c522570e8d72dd60367e848e82b15ac8af44a6319030f10db5a89a1a736e5434ac70b2a8a62a92ad7ff4e6efef662f1829fbe46fb8a2a5aa1bb6334f3d0f403419df7d10639017a77f1b3454b74b18be348890dcddc60c17dbf513c0eea35099b4cab20b1aed491764a483f02c8d03a89a60be612207fae82c7f169746a048169d407429a97db290a3f92c6133f320ad3fcb6b015bd63f3b8401290ceaf3d25add9068aa213848eb530f64041667113633480833539412a4368b65a9fddf32cc05ebb084614cb943770a9029177d1f6850947f3d3b905c557e1d6d55973858da49575259e5155f275da6b8feb27cde2b42d326449c30ec9a9200896bdfb501a41045b786add609c3a2a74d1098153b06e894dba0d52a110a1a8caf3bd7f665855d9a00857186d2bd4223b6b55daadc36c3dedea16f158c280c3f5df98af27e5841cd9994d8d4280702b6bd7a8169a8bb2b9e0f76ed80df6eabb8a9048a2d0e0cc035dde16bdc21ff7d0a420b098dabd4717f8b7bab9c7b98177b2c9e67eeca0e189921ac969d59fd9da5bc2653d242e90bd493e096f87bb14e6eea91aef8730d659753a3bfb423cfc95bfd83cf0c139c1bfc20023868b127b32c5b67ebbdea6fc57a73b59756fab570d830cc67638353698614f126b1cb7cacdc9110d7a6fc61a956620492103454e81a86b679c49ea65e720a0af7063a81b60b9da4b3b12f0bd6949024b9be5c8ab207174f0c4997c961ddf54efd32c79bf769e631e93e9e7fd089b654240f6120acd090a0621c0b2cc3495c51ca996af4401d9fe7227c81b2947c885207e5ea9dbd51dd6256acdc06615fba3ef0b760da80ce3afd9a0a200e067f3226c63d1624768907b5523cff7ab6875f8dd4c571bb3810446793d0944ec9b8d2020886d2e211ef017efff8427723810c5b54862e73550e82f0c1ea05357880f8206de3f0bb8c449f212ed22ef00b15251cb383c941853dfa36636f963a1a145a7b916b85997718f9a556b84fc1fe813915522f96c2eb69ebd4df11099b12975f0731f0fa0805e8e454670b3630c0d3a758e1d4026d046853201839e61a4e40ffcf48669e2b6a5021e8c5e24b3014c4fe42db34445b5b35bf72f15ba5a144f94e9532be52758bfa19928204e873348b36b9d84123a039da2dd4691ff892918a10a0fa3234dda2492bcf05fa1a8c10dde98b1d528f66fbb3fd4477aa2aa8b64b22e24b1eb4ac7539866e083e8ed9307f4bc6ca48b576c5b9920e2228dbe3bf3106c12617aec13152674dd57c64d45da584ec5d5aa49be8214e2e8eabc01f2727054a92d02cf68d37c558014d6bca1bab69145bdf3e10363c299f1a4fdc68219c647cd598a8bbff403158efde4fac2fd4c99e2719204ea0d878127e89b620fb8dff012dbacbc727e963a8139518ff8afe8ee7d7131ce4ecaf9e39e58f1e7b63604b260391c380526a624d4686a808b806f0744598d8aae850a6e334b5aa9ef72b35a9152b72d3bb1c350d9813faf120dca35974aac33c3e6e2e52c045298c88ba204b4b4089d09bc35a15360fd671dce32de302035751926220407e01a01e49ddabc350984148106a3f839543572b70fe6b47cdd55ec536b7859735841417a0477b7d00119303ad6416e3cfcc0255447c6813e6f4cfa06140efa9775847cdd944f97acda24f63ff3774e904e43fd7ef502041de7a463bf0fd637f5f1b2f4674b7dfbc61591c5ceac86348a53dbc255a0ee18aa4128f86e552cf51854903057355c8d5d9961783d981d85bc79bf7b4527e8d3aafa8b27b05185ad449a36767a4a65c9325845e369c70a7b66bc46f80e2eab9106d2e9e860252b313b1d2156f851338a05a855f89978d13660fccbb2e31144407de6fadc706a060523462a54b4c13bbdb3451b7a520fd40756376ed413ea80d4f33315bf09b1d224ec7fe59498e7e7ff88704bb8ad94ad7cc17d50794cb22aeeabaceda1d69da1601fe1a29a2c57586580ee25d259cc23818c176e28897799b0a59e9889523df3753e11fa049688ad930ee62fdc27065c545c3e156391139d15b4e890069a8188c5c6ae19ed17c53670e0f5076e1812dd4e5483b40fc468647e3f86e54e0361ebce00112c59edc90256673ca0a3971c567ef3891fe1ad56b1bca95170c5f69627c85db7025d13d3fad3ef8945e113e6e7592f177cc21fae99298ea489dcca0091c0e6acd6bc3b823805ce4c3312e0537754c7184b6cef8161a1aea0455f800d9bacdd79d206fc5a546d55142556ef96f2914cb2c3d3e1089fe996cf8577a163fe431fb1e5f583c9517ab4cdb40d3bf2a03124897929441d9cfbfb0b723fe89c0a19c546e714743e4f4b9b697e9acc78e0a7e776ce9c1d1004cbdc916203d198ea260a3f2b0f5af89fe8f5ea2ff51177809a97968dd91f129bd050141e47aca8cfe593bb70644d515b2442f8753c509c253bb6a237dd3b95d3da5846c5b6e121cb6f7295b1fb7c0ff33b79cee5a46394984c7b63eb7e9c4e8070980c813b9d4382f8a6d3d98bb1581d534c61c251199b8316ee44e3fadc213c6f8583d9d667c0baeeda63e7ee973e9ac088d5eafab6cb122800741fa9ec1c936703c911f83f2c8ceaf88737499fa688b1ba88646e1856d762be91c665181825a645423fa0b144263d89fc8f039ac7e7712ac0ce7133507f537cd9bc568eea6ab430f5d7a355fc84a24f599a090df3600fba580cdf79a2a2f9c3485506a231725252d5021cab8581c54d0003f708a2817a161fc9402a8227afeb21f8950afea79f49299400f513f3682040ee4dcc0167cdc1300a844c65fc73b93a644e643968a4572ba5e8b057035fae9789835fea045f96eb1100bb70fdf09f5d7ba7d9f1c1de63fb91ecc6f4f58e0a53bb8cfcabcfa5cce319934e1884bb4f148d43ab2e2a8a3ef7eae5caf9b7c5f4b5ff61224c8f9ccedc109c0aec43d0df2b4b8823f505180b0db4045d6bda3edc5d4245c596c9857efee2f2f9f7dcd8ad4055e61a9805c7fda8fe9ddb6f2efdb769ffe830741baf5283a2d6b73083cee9805823b6e4da13d3c0235fb42eb604125dbc398a6ee4307084f07deeb76c5fa7d365382012882112101e82abe78b26176484dd2144f0613648247097c4788f07028547fe9c38cb92cc26695ba005d0c9379708856ea9e869a9c7f1125b5c14fcad8f044365e42dbeaa63e5d060b180cd0d399ecd8bf1e370eba53a4345336f0af1e90731a874897e3049ff0f68ca1ec8bf64893bc8952adfaf08ab95691c9c77fb2474c138599f4ed146e7cd498d3cda299e9be6045bc370f4e930d39b88ba9b51f4dbfdcd56e96bf221e05f149bf06d076ced00051cde280828bd8be0f5c476b0b77f448850051cf1071818fa7078de1c498a2bb69b2056af7c0b4b92a1354c30fe7137a97dcdc86e8056c009306d4d02f2e945b82bc5a7c93ed5673b884fb53fd505cad3f5cdc6def3ad38f725805c40461ca2931b3633b98918f6e5a01bec479b91e962f73c25f07ea72d198fc5c36504989bdcb9dd31dfc07684f92e1f19eb56a33990cd28f703b4f4e7185857b5db734c53abb42cda033c278b1579612b00796435413076db46662a40160eee5568631315be652ec32243669fdb23cd1c84fa0650af8ffb430b1d1dd2aeb93928613bb7d8fcc8ce08612b909e38fe2a4095a48e53c30fd1c2a2ebb5a1c556570e668b242799f65a85e3d521d0fe0044a1e3fd0195f0508ffd8d2d52bcba079d2f9d6e1e0fd1e89b11307f10fbd8714289d291ee34f3a7e0ab9c94123279dcb0ddf7f9493f70587464fac21c39029c62b1e9caec92ffc307adb31eebc55e27530e749bc4a779c1fda5adf90d937d349cf071c286f575be829597700e89846a9670c087cab4e94efba8d2eb65c5daab9966004729a9156fd9f1df7c5ab563a3209da6fa3987f429b1f20e25debdfd41ecb51236f0c21cb5b2cb242c28c2f607e36a90eee9a16157b8af8d5d7ffe7c7f5dd67d18402449ddd1e87965201f4faec014e55b6cef9190cbfe909e430200cf151f73495e3d6f124b761ff6c90c916db8c570f11670ec2d84c423bd9a30c978f324ceda72ac882fb123d57f5b7ee1f5dd4d0905040c98958034944abcc325a978dbe031eda18924eda3633c47adba3a77eae4b9b6dd43d2e385058eee6b077caa17619a03d4a671285464f843964498f5647b87a636db6720b86d977d13dd3959cd710adb66dd820de5254b4b553055e68582b40360a31b3691438193b1b87d85f0a05440929b028926e5c834daecb28205ffcaa453c7b314e0b4281b0d26c229be569572d966f0e39b2fff66f737cee0b456ae5044927ab7e10d7062e7ab2f9fe7248d62fcb0e691d361e490b93b4ca04ceeb33189193aa8e2652eb90109881b264ce248405b4084fac97c8343b992bc3d2de5850281b48da255817cc42986f7829023310ede1a60eb8b118b1e57996ddce48212685c60246da25d27f4109defc43f2101920185c1a8dbde69b7b413d32a8049b412f2c7bd9b37c8dfd2b4ab27206b7d3aaf5eaabf6e787235f06a6fc5b437406b4c39b091c85809e1a3b50f07f57f76b4d13f9be5e61de74541aebf225369af30dca16836813d1d0a3bb49f2086ccc9e98937401fd94a374617b4972a3528804e82b405ebc7056ba704c8438be2a6dc23cbeecb2de12d7f62a599eda1618e86201c114f262ca1c8047bd894b80fe53464b106c3b520786f81ec85c4770fd1eb0bef2fad1a6d513808a0b68ea7d1306cd35cbbe50af9cc1e15bc98a28e0747b1cb8ce4cdba445bce01d1440d237468fe5099e94cbf8f49657315143d17d9e590649c8114b6d3118db5f9f600b009a5278f90b9b7001f112d2196586b5da867cca4adb9ff0a386c1560617f1672c67a601707faf28aeb7d3e169b3b7a92e32f4f22b4e1c2c6300ba68216457be07e4e724aec9be8560e5f2ca484a7a03b52c2ec884562a901025fe805994c68ee6e4068987e75c22a59f0e6bde4ed86ba65f026d9a8f6e9cc787f7df779d25f988e5a1bd7c14685464e24fd8795fd91213940dacb9b1910db13b49a1481643c788e3d8522be7a5ff4f77ef4d9d5f5be25d805db4d09b8a8c4b6d03827a054fc8d4dbde12e02ccda080b608bf21270674bfb92c7d702e3b313b9183a8627a360d05a492afb5b586bad84e8d80e39c9982d5144299886339561f918f863774b6180b44b4618bdc3c3b1a06ad1b7a31c658904fb0501f27676076bb05bde30286cf5e3ebe52b990368d1ea556f08a83109a87bc1fe0dbe66d3b61634a52d69ddfc662f9631948a02a98d8fa2ff9202c46b7427184a5c68904268aa4054ba9d2fd802f93248d721d30cd2d094aabd010970319bcc25a5452848d8989a02107255392e3a3cdc52a8ff81c9e0a2b74d7990f9cf8d6c5a363f7b18691015249f6cf87a2e39551aa45511cbad8c4a83b485ab433f141328242c6fc3338182870c1b98a5f004341cea5ab6862fe045bd54cf02b32fc6c67ae94745d8e6e91d9d02f769f7d5f131cb801d49cc46527945805d9d0af4d713e17c9e0d6c7404b17c4b1d57ab8c095325a85d0f47f8db36eda8aaf0184e9a640506773a824e62772dae97e12a0bbcafab9057627ca6d30d03bf37d7cf44630ec582c2d71ac53ec9ce77b79c668379e390db2bcf56f225e358bf54b4e78d17c3223d9ea179c557b9f0e17a621fc058d903c206efa84740d6188670541ed23c1758018b2a4d90717366cdf733681b619d44c2eeec4545ab512400267032bf7796a7181cf18ec0cd8683ee995f1125eb2c1d838abd04f614bfefe176cdd8b817e46191d0c4aa2b3dc65be2320388279141452f38b09ad703bd72c662fda71e844f42376159cb1cd9cd8cfdab5ff0dbc75d66606173ee205e4e8909172dabf15270d2dec80985c4be7d182219137c6c1879680a81aef6b957aef630ac183b583e8286fe91d8009c6fdac1389da2bdf91d0aba36b40990328fce7e157c24d0af700812ccd723e1ab1f7d9d7e8557e6bdeb3814eb6b7c25266490eeead093c4391432cc24d35f6ca1590a193b8a8ba094780dc52ecf782b956c86e9b5b9a6a7cd45e9377445fb58fbb1c1bbfa71c8b1a8af6f2c4ae3ac1c71a65a731e6ce2a13772836a3aaae331fb8fa51f3872f42c4ead51fa990c2e5a83835a33d02f7603d4b57286b290ab39654e98f3811f985f6fe49bcfc82b9a011fb03ef94917f02ce04842076a65d34edc7584212e1d2312c6fe92f4d4c0210a443f0ead1c4b9cf6ec722c069f0549c8ed80e8376072165c6989cf973841a61826c749f1e2b0801b3a823391b4e4edbeb2aa1229f767b384db59cb68bcb5045c8e21b8758d2f041a88c35bf1b9b4778b9d2fa4ec5cc2402dc11b0459a958ec5cf03962b4f77b74c3477a8c75bd4758a93f6bb2afc9a82bc6642d59a403a0cfbca3358fd543072576ef16f7fb0b48eefdd2fb87db14a4026df5ff07147a96f04c30faa683013bbeaccf1f61e1de2febfd3364ee7ea9f3079dea07412c5517b3d4d827087abb3ac37aed1ae595940d36cb8e17fdb08076b0bbc588974af8837eccff1168afa322cf3edfeace67bfbc9ebfcc6b71f78623eb09b3549b28b8183307c3414208c44f248b934ebe206f92888b37120b5dac2182af3a1db29d88df169a85d3a89aa46bac3f091cc871823f5ea9eeee688ef82df2ef8f0a87000fb0589f9787b5bd61a540870fc30ebd6b138d7f7ecc39bf16af5974f4474b065a06f1db6c30de7916198290f075d19705895c112a53887f056905e444d329f028ff883d8815b1a4daab0a6115ec6e192db6a00b198420c6252d5974e830f7e425aabb3af83030043db15084ef0d731359a49054812f2c09412cfa23d38296ca955306f09203d6b889832cc790512cfe8925a0f336936207b1c9426422c17d681fa79e3bbbb8ad32f8213ab7a2c5021f9911b6f25d1f3822711e0a4f9364768aed682c65ce4a425514129e4af1eb43dc4c25862f3f477ef9195950bdd5cc98880827169dafbbec4a1703cc320f64b2c76619c04eea1aff811d25ac43d589e5b60ee4a3ab5f77847ec592d7d15410621aa84147334cb02426f5f2d477c0d4112417e267e24b614bd2058a53abcfe8869a1f45364013e20a358e4c9956c01face867bfacefcf90b9252bb04b27221ffa4ad215644aea30348206d14c675bef395d91a9c562e02f54e1c2f2a97b68731d1a482833c06ed93de50c19531bc34ec876f2949eaf0601b7355330380dec88d9184bb2274151f887a9492e79a82674867ba5d75bd2afd2ff53c88dbe3710a45bff61866c59c0e59982d196f846a1812dbc2cdb35720a32552f899a6d94ab897cd4777f08b25bbff4428b7cf28d7f64a2a869c211aa552a0710916571032649d1fec50312930b43cf30045fd7f8c0a081717851e4ae539492710f6129021d636bf934c8a5fd027a7fa0057a7eb9d5371f24a3f99b3eb491e158c6cbc8154ecbfe526cd07c365a450329dfad6880f5a844bd104a6919349de5dc0090530d146589866217b40c32f462dd9ff7bdd9119264eb46d73830e9ed501895f4afa9748a2e67e17811198c410564dcd2247bf5e7dd45c5af22d1c29a37a0ed90f6c2b1c194b008d7f741143e4d32e8104a373621744239d9863490c8ce38fa2b5a9bd5a1bba45b7af7c1ce62df460913949e0f54646b49bbc5ae3ca192f5e7b389271974915db5543263f1fd1590cb4c963c35eaafdcc5911dc40b2fa0dd1552c02b0345d8a2c363e5f3c9c586e71b7249d6054710a3bf72099cdb4e43b127f79213065fc60a3a16aabf4213e0377cfb2dab9130ffed981235b7667e6b7c7fd8fd42d406e19fce25083a32e2f56cbf3f1f5152e95d9cb0002cd202adb08ea1fd484865fd005f2ef3e7e78b5684edcf47c61e3fa58979f95ae5157d94f9f32ebb1aff9d71420f4d26040c21c931bd0a667fa527495719b74e17ff05fd95cbfb04fee8e5a07fdc67a4fe4acf8c2506acf7b53aa9e9ba4ab0306cf35b8cfe0a7d80ac4106484450f1d008898c237f7edcdbfe87a557db48fc562cafcce214c12c87049e7a0f9588fd2e21c6493ec0fbf25e3e38666a9a0eb7f6d293ec46cbb63867054a5e762e22f623aa4e1af8f3dbe6825768a9e30bb42aedb0d84028ae57e8cbfe9f6402b08aee88e53dd4952b803200a070688556bad61f6d1b6065b94298173f003830e9e97afded17ecfdebf3b85356902ef824e0898460949afbec0aa1ae863109c4ee32efaa0144907191a1758bb2bb9406dc90a2c75bfba29d77477f7dbe9bb102abe88596180f98ee132161c27a902760c886c37cac4b410030bbfef3195296e723f492de2f158210d763daf6fa10c5c0d287c80e42c6e0ff1f6789871ce669c0d4e3f0ac57f5fe2b821d6e1ebf386a0b7cc86cf897ceeac0118973693ccc249257cc42b72cef430285933060af63b31f7002f3d49500ecdc97c413ee231d14db457c5c55835dcb50d60d5ef244f00f2f90c846a850f0d3ffc8fd88145bd062e3e543d1886051e7b21029a0b540ebcecb01a221daa446422d607f7c91805f59ca71121157277f16038740888e6386b1b6a0ca33323f3e2c308cfc3c84342843be2cc42ac0e8ee803a7620425e6179be5997ef8f8b5a2f240ba366d4e1243f2662cfe0a6e0c5916285efd4879c74d6073c9e989f40c32c9178c5979c668a2a467b37b4a4061c717581c18c1a1d0d24c22d55372153933cfc0bb796388e408f35075f56783db0a5c33c0005ee1404d40c56209e15a703b7781fd7ff9c6c0be99c6c2b704450658f8aa1339033c331b59c1a39da215d2eababe42b47108c336a3253be8cff6e9683f0af817b160d5dca8d4f2bed924b1f6eb09f9a889090b6f7de5bee2da54c3205840c5f0ce40cefa8140681cc5aa9350ca4bfef0f813f43279243cb0182b8fbf45a83af85a304559cfb83e1188e447438de421dda0d0d77187a0b7638a2febe55ddf0efcfe138c7c4ede22804d5a7f7420fe3daf7a4d1f775fc91bd17850ee638e5ef2ffdd9d388fc23fb4a1ebde77e0b7dfb6f47cccc71d4e97b1f1e69fe1e7c0fc3efa3964848887f88fef4e87f73ba27bd39b17774f4e7a64c6d5a15a83b5d41c2c4555829b7a51c532a97c18457399dba039913ab5c241659e8b3b0000a2780aaf42878cdd2d227769c6a6ce2acb004c7d1697ff4e77ac8cc91544a2a6f4ef59cd699b98386fb826cc652aa69ef692d6ab426d3f749eb4bf9943ea5f2e7cc3eb8e81c4eb16844a05aa59a46b54a5ba75ef98c16fdfbedbcdf2ff42b907104597e7b3692a4f2dcd1e6cabdf7de9099b9eec121dcefad14d7fbbc7e9facc2f57eec19e8a0fbdb30199142e09f3e14024130040e314d8173243716724ff1829e3cc50b7632f70e020137d11561550eef458fc37bd1c523280a85a717097196e94b7f32859d85cc56c34027e11f236c0457c5fd7e6c21dc29fad055a9a010f27b18af600ef0bdd65ab321d05b79ab813640108bdde2425c74d04ee17e984ea089e7db700bc71ad989b8e84286582873da695f26f79a485105245840e9428e0fa4d11585c0cfeb38bb695574472452c932c1ab3fe7046d08e9d0ac01a1980113361021894ae27771bed8d83137051707c5ed1899c510c2e0031bbc5e314c40d0652a44075abe5cc8bdd991481d261d17bbda6bf83f22438448e1e2b05f9f889021360ad7c3f2670a07852b7f6eeed69d7b72479923e4fb69ed13973ac9f33d21b3256bf00322cc579e373267c33f5c9cd3fbcedd8ffafd586b7d1f3fa6b539f6b7397d18f1637a953f447cecf8c4f1c9db7429420e62676e38675699435bd6d76ad881faf7f57a654f6e333440b31e3bb639e7237151c7899c7ea0ce454be6cb488d7ef1da51dab1b0ec732fde83f7f68ad22863432101b99f876eb9ccee5b2693d16e86d296751e36758b3ce51148f6febabb5b94a6ec5f8da535f4abd12ffe6967a8e2568154777729e96f526e2eb1be8c0fd5615c2ec254ec832b45615d64584f5581d72ce37ce5f9def4252ece1d17a7f7022359669fb9cf0b6cf29c323baa845ed56f82560a577e14973e35c37599137cc58b056d501b26d47bdcc77998cfc9ba68d6bb4885ac5fea03a0c5f9a37b9117f0e3c2224f172bc04cb1d72c5ca0d59c2b36dbe7382936ece73ddee3acd1839cd8afd962d3f420fa1e04469e6f5d8afb5471e54c5ed1ddb265cb2d3416c9f23b26d32df31da40f000eb43873f46a2e20cf1fdd329f4e1fb753b8f2e77c5936b8f4c2c50a34850b966499477f39abb30b92e47a44ba15bdaadfb1cbe5de72c7ae8d5dcdc66efd6cec521beb3e0b5a298cd77de6aafee09ae18eeee33ef2b68ff4971bc9f53fede96b98a3c2b5d983658e8a2bbba3bf648e237196d4711cd7e997cef6ebfbcd6c715f9f9be28238c0bc61f7e996fa350b97c316ff5cd929eef8650dd4d12e8e2a4e8a2b5fda6479a3612eca95cf41b94dbaa53e17854eb754f771b1faccaf70b1be9d82fbe410eb4b242e56fb833bde1cbbaec3f338021bbb32b7741bd2dc59f25d3383e749504a29a5f4d91e5252bfe29a11c4b4e08926fe2dc5134f724bf14415796411e5521ec51ef2e8329b209d4e0a2323a79c72ca5046cae954b2b828ff8720a4fff576aae2625b45436be81789894ddf7442affdc6b3f56cb0d9f26659bba1ecfb2ef444df857e0620dcc4c81fe8404e9733a4a43e0d3b4614bacc95f6a1d035579af65f283357da6bef55f0064b767151fb8a45cec8ed988ea94f7fd48066a318a3693f9bad1db3acc5b2bc992b6daeb457719b8eb3460d286f3bb385619de304c9cc5acb6c20c5c916d3c6ad49a6021476b40993d9604a1e3728597b4e6a4039412f67693fd8c9a3a644d35efde265ed65ce6baff9e0cc567ded7f688ee7d4b4dfd1c387a6239128b1e5386b0ce2ceb2affd766443e2acedb32a38fdd2b1acfd06836e69bfe1f44b67ed07570735c8da7b3d04e6c160e0c17a0a1159de78f2f63408d77f8641361ebae16c392e6a78fbb2b8a3cc7112b8a6e32cedb597399ab556d39eaa00815954fae3fcfadaacf5bb729b56375bab56fd83084376843c5afaa2de54087f5aabac437cca2ceaa7beebac3cc4b1e0d9b0dd1136c0505f53bf0d93d0a7e0634a223c0ec922cf52f923d37d182785a38b53f88ac2205f9e7fdf9361ca744512ffd87fb1d72fb2de6f1aef8bee285c01c1ccf76588c4115bbef8082219c825dd17fdc54366be1d822098a192650286d645fa99522bcf228e9ca382d72ce305cad3e2f1ab013d7718a884dbd96b7c091a30018bf1dcb923581e70dc74c205b95bf3bdf777cb32b473d573256d17ed166afe8ee9059a401efd69c750aba958524ae9113579db36fb5e6bafe4e66338ac84c376aeb69003477cdd02cadf34b949185424e40f99d986c44700a16ff37cad560c8299e53f16531cd1e1820d177a5cdeba5c176cae305b43169b56c71a4a20546cdbc539a704832822479a1d4b2fe834b1c59878fc6a563ec67b2ba19c421541b098cf451b26a4b74eeee94b6f0a4fe128f349a37fcadae9f4273f85a62f85970bcb842bb3e9c7fbb3127a942952bc62aa14d77df2f69fb3509ee77940cec3f632de46b9a3cca71f4dd334ad86a3978b9b8cffef6d1af5b4fee9293d7d3dfde9ebc8c60bf7747a18f76a48bfd67795aa82553950aff23850af526b0d4f4fc31ebd9c45faed4736a31b2052787f2489e6d16b7473ba5cb8b8d9bca5f00c6ce32f1c4861057ff4aa56fefe380b855540d4d7bee2517e7d0d8fa8d77efb95f03a0fdbd3f0cbe29a302ab4dae94ddaa34220f43594caa3b02a477dd4e3a88fc2ed221e69e9f4a8f0449d65faed2f17ce2afd095f53685ddc3adf9fd9fa0be4aceecfc54d8447372e6e4fda7ec91db91fbdf246696737fa7d0da9b8f7a65f5a0a79cbdb7fcea2bf8df0984a5dfc7ddf28afc8da83da178ed60bc7af0b55e1fdc9dbcb08ad8ae2205fa61f23ec98110ec9c12254d9edb2065124578c04cdf43a13ecf6fe59ff3effacff30828b6ddb7c541f2ecaafff43c8f6630b8d98f910020404547d18f163036d6c9a262bee0182efe2f5ad8acfabf45abd4a9f4ee5df90d9b5ed6fc84ce3e28cf771a1ef172717ceec98dd536f91bec363902fdb0fd1c8aec531233329ece64124e2ba9f606797b34478ac991b41ee44364c46a4a7e07defca16b977713fdf874e24b35765bb1475d88769c3ce33343bac7d69b9971c55e500df3e88bf0e7cd90717e7c7715ed82d725d67391bced07058dcd145227d26917347d0f005d82b0cfab60bbb80edd4c82e3cc10a584cf71e27a51978a6888294233b94524a9f64fad5a50d7d69237390e904b5afe34229bb900bad0faeaafecd6ce5a0945e136843a65be8e77895d4ab14d77dae91af9d3b68c36b288d581e481c69c4f280524aa9284466b6a40a7a459fd2a71313e1600d042681e2380f5bc7c91ba712471ae1b2b8f2edce1de58dbca12f65e00abc1aea185b238bf04303584c3fe1d21f5d7eaab573478faad570fdd8df7e74d1344dd3b4dac387a4cee27ef37ef3de7a3f93c592f4f07e6c9f69c36d03b2bd832056e5e01e7c1cdc835bd77987b3beefdec3ae2f7f3b7c781dae315f23b2843ccad78f6dd336ce86c9c6853f5cac58fb2124146e219844fbb16d6fc344ebae75db8284de24b205a0fa3fa690c22cd71f52a7e0d13922755c50e9144bbc2a8f135f00caa34c92eb262798c3331161c03cfa8542952db078c5d870e996fa1ca855481017abe5c1adcfd90d77b77d35d2ad7e1021ce437d0ef62379445a78cd22e32cfafd49f2d85070cba4cf34414cbfe402f67ac5f414605cc079c5b42cf7cb98136f7db0d7eb9582987ef9644666896ce22d199304c9919851da8829a09f1a6f750ccc6c758ce7fe1d72263d96e54b29a594524a292bf598b3e4e80e45ba942c654e13f7614f9ce5f88794c39820421ead4c0bebb38d89b9696d5fdb5cf686af744d93762ee1b66dea39f044b9a960454fee183e288392574c5d71f19d87fa364a8a524a29adb0f6c17266206edd7d7a5b5883e3def3d0daa7ef2110eb3474ed71ccc7a37d10c82219c6b9f7907bfb7576e1f0bbd8d1ecb2c24d49cdd81cf0e4319561aaadd6b3d65aebb53e88845aeb8347b84abc968753d55afbb53ef7855bdf7efd156ffde0fee5f1fbfad66218b00968844e0696072e778b245ec062bcbed236b9fe224b117a885204584ccae4e211aecb9394046a4317d97621050f186e4a35c960885197031840faa4b50b5eb38c5696bd51ea0401c1ae03a594a04e10539632c9f5b2d7d91ddceaa00d1004b51d2f83b34bfaf1370d779e078260f75ec8f34010f440180753aaf764dbd757f41b680387547fb74429a1f86abe04bf70412f5c110e01a00eb08bbb8121ce9efd3cd07b300440f6c21b5b06dfe3e4e721efc130cc5e388a2083ef853edbc5d5449fede27eb68b0bd2f9d910108f53430643201e080241df7b1014a2fe0c6fc85cd85144e18aac815c0c6e7dfa1d3065ee27a883160196390c643e9763aac0effc49a0d9cc17d2c83a6e86a4292e5afb3d20cd803c8b63be6a470f172d10b7247b786409ca966566b9971972c732e35e66c939c7b564a4285078967c01ca177e62d227adda5673589ec2607e68c21dc53c451a2b296b53268a6385a02fa4188307deee173087a691e70c17396badb5e6beadc5502a27546892614fd3401b1a17aecaa71ef5d39e522ab385c2266b4fb834d217851a0cd49e447167460d9627cc45d9088f461ad6a4c8aa4b76992d2dc76a5ace1367897ebe16c3229198452e3f5ba717896467895da6b52eb3be9c658ae54b5c8363c21db51c2d6788cc3690e8384bf638cb088e8bdee94bbfe384779896704b6f9aefe222a239a2bfa137690dc7f7a185a35489e26a39a46f508a5eab9984e90ca40ea21f891e66de50bb71518435235a8eb5de87c754ee7266cb195272fa068bf09813eeb912e7aaebb6e7ead7b72a89352459d3d17280aeab864686eb9a116f758c4b7e39cb66bacc2ac5b5ebb7078acd15506cb8c80dc5e60c5d1ee5d14a8189b7bdc6d57051037f0ba9b669da734ab8ae1f1b4633edbec10fd7705113323528597b981f9cd5af69a6d75edb64dec24eb92d3d986ea959b827ec9f44e9e79b7012a8d74a5fc4fc122ec21f852dd7337a94981f8a0d940c7e33231de06f2e6781df67670bf5df8722893e3c06717960122e0e1717b59756a4fdf6e0df30882bdb0fe2d231ba3c30fcbe26876679e4ca20b893413c8e46611057fe422190d15f3c16c9171c05718d4220f447f02d3e628a4220e0dbd07f21e80a6b20e1bae8086120e06f2f04f82ecefa58de8358c645edb5b7f2a569ff7918e876586471517b4b866b9f6255ca45ed3b77a0816079c50bd8cc06b38d7440f7d2e0f5cf9ddf445a7e089a75532dca0f8121916e915f0ae1b1c17056085a942f6f2a25662c5c07c303327bddb4ba6d75d3aab50d269130323fb80873814725f7a9da8daf8b8e470da74cd482e1b64bb7c8b7e16f6275efc26b164dce491d0a5e4b77cf6271a7dbecdfc49d3329fd89399b57d6ca29e16adfa14a729e87aaaefec4639c12aeaab1aadfc21ce6fe2466b10cfd89c71cd65f254f9d54f2489e4975e694e2e2f4711efcc125ee386532d7f2c471d11d96254e1eaf86e58eb46ab814db33dc39d34c40a7c401ba5c53eac2c8d45aeb0fb0f9e3ad95ce39e7dbee67d8c1fc2093ba1346c655e3ba63d5fccef48be4d1857a767c63cb47c836c84cc3efbe78fd06c1b5a7d56ed5da6ab7aa61164943251c27991085cfac4eca052ef29c25c9734a9fb46a9be53aef03435b0b244f0f8e177080d9ff0ab12ead987750da75df390d1380ccfefa38faebc4a3dbee6bd871f63bec226766ab6134364c44c343ec92abca41bf668a55f673976c98e8e4fad72f6096efc99e5b682cd20fe3357b2d240977e6f18eef23fb24328455afe41bc0678a3b300d077b6d28f0fcdb95b7ecb2ba4b29a594524a29ab4b89bb5b6a6cef325b1b7eb965d9acef08b75f6742d1a4945fb8feda0f17148b3beb9c6507ebd3d0cb3efa45e6740b0c9a25a1e80b744bd6a0460d510cc3183146239953a9a5160cd75ba9b1af68299501fdc2fd7c18d983fdf931fd428de8160dcc664376f942ccf36b067c744b0ec8030da86641bd355d2e72df3f4397b9e29e86e25c71168bbb691b16d77f4491b9cedc6f1f7a19dc0bb837c259e0f7dc732fc459de733fc4ad16b7722f71e67398fb24e8933e89f9a30adab0da76815e71df1bf6d12d5cf749909e4a503504e9e9d3909e62d5f6a6a7d3fff4f3898b9c29c4359c9118480184d72bc6845373c53dc784a6f4a637e11a26df973093eec79474e222f7df6f61cd0e02217b5ca4199c81e1175a6fab1c16f7cbfd246f7e168bdb71dfcd66f6315be25c716fedbda9d4bf98b951dcd12ddc77dcc378c5c2fde122f71d36c245ce82e156160e0319c1acdb2b78fdcd32629d1f235cece1a26c0db4e1f5ad219adc7d77d885416868368449099b2dd2c360248c258e8c1251e08423ed8e133284480d9d9e76c496ed6dcd3a10b20d74140b4730d046ede7bab8de6bef03f7e8c21da1114057fbfe202087470dfff0bc37020721c368369238a26e04fbb4f04710b0f1f87904bbb1315c292e4a19278651fe48caef4492c7c3a395a7d1df1326593bc2bd3d28a3c413bdea5c0a659488a2579dbb70db315b23d85c492eeee8494c8927f287c72f5332dc71041bc11ad7ff7c35ad756121fdbddfa3301cfbfbedf7ecad1b0fa940e02059429146e8d22217950068945fb774edda759412878dfb0edbd73caeb9e7b0f529791cb2715cc7711d675fd3ac8e0db7d481e3c271e264cd06d51e66b6f61b25922be528ccac6311fa5b68b3f632d739714583d7ce7269e9d696e38a1cb1e56d2441ae9aa6798eb984d461ca5c69e8ee4b481dfca9a4c21570aad72d5dbed3f977e6c979644a2f72c4267b86e67b112babcf8aa8b1d0b9dd0b844f8260b54170b95ce0ce05b2fdf7dd7feffdfc1a79238d749ba4b8c70e1f3b9cc5f97096267d8040f8a83797903a7c781ea9e00fae0bdcb9328faeccd11fe612332757970c4c8f1f425c2ef9f3b384d4a17ab8a50ee3c4d97c969a0ffec5a315e1f1ce25640f128f45bc777d2eeae1d103782e2175a01a17f610cfda944c8b84e4a705af59be5a975c4301ec1e6cb8953e6ead5be93bc68e79d6becb863241b8d8c30a1f22f2ddf38c8b419c25259671f11584920b7eda7b0d769e89c55a7b7bc8b8e7d2a54b97f24b5724258b8bf20bc2d285ad7d5fd3f73da156be54bae16f88f1335e957a1c38fb3274edadfd1411210dc6fdeeb9f0ba48f4a1ef38cb59ce722a510faf4a91733a42ef3d37b28caf12e11c21ecb9fd1b8ede7f313e14e32d568962ba960b6f0cee2f56897239ac23c65b0c24c6873090d4db202cd9e2202cf986778c834a7b7b031e4f6ff13843a53a794946a94bdcdbae54e25ebed5be52e81d1e4f255f29e1953fad3c8c97c2153cca5c7af757297ddfd3fba9a4f22514f73644bd281c7b64d1cf1832543f3cbfef3644c38ed787ec4feecb88de0b533f66eb7ffebb0a8f56460c3cb264a7bebab851ff711808ea3b14eec68f4359cd7adf2bd95764c8c0f7638463ca945d25fd3fc6cb08dbc51878bcff3162e0d1fbefef7fd8beba780cfd178465ec912ff71c0662bf7bfbdd4b69ad4dbdec7eec386fec91e3c67d52ee704f1ebfbf38084bee82b0e4d47f292e7721ea6654a8fd293485f20661c9a52247f2f7a370ec913fedc31daf71a18feb22f7f0c8f5f0d9f1dd15fdc8cfddc37886f14e87152598c329cd3d7cf897bfee4753febeefa9b77e7cdf8f1f5710deea98ce2ef1f4c1c5a9b9fee7f78b9b66f8df785edf2041be2c7f8a0f1f9a76b19b308516c00086054cf74ee553df4fc3a586b354dfef72d6e9fb7d900962c659def7d3f4f7f061c48f20ce327dbf106791be5ff384384b729c7cb97f32347a53d7bdb59654b2df2934b588fa1da8f731efe984c7202619e12743061e85dc18a18d11038f43be8c7aff54485b44a5be0711d4b7887a07859859e57bd4e4d3fbef40e11d27dca344027b30ba21b082363eeb228769176e177e8bdcc892b9b187d6c3870fff1ddc8ef0470f1737d006c54624e18ead61252b1507b1825df407272e589c948525fb7fb3bac55977b3e4532a64bed820031f4eb20cff7cbc33dc2feee7f1bacc556a14777226e7c5057fdaa8018eaf3a6ba18d1ae4b8d8d94a29ce92f3c3a34b1ee58ebc62e7de702173b8ca0ce313b46187e4fa72fb3697efaae1e2d4c17d971e1d1ae451c276b4996e99725632dcb165343fc11b7474f1e2621a5fcd177191ea2920e6cc70eb8d3ae794b557524a5aa473cf8a9afb65b7ad19c68bb834a22506995c4a5db4ce43bf8d423fa65fa98b2ef65f1bcae262f7f784ad215fd992a599905ee7df186472a557c4d326fe4299bdc3e7c29148e642df3942fd2391dc789cdae770ed7384b86f30c7a7bde63f3f87e389738434cdfbcedb97bf19e36bb52fe3512aed7bf75749894f63be8f4432d858c57dbfabb80ffde4b0ea067dee73502e14c223913cbf432f7a0d8fa1f6ee019943af85b0ea06f8a1cf01865e0bbd671fb4ef58fb91879b7bb8d98987cc916320f6410c44e57dc81c2dd654de7bd5f72e03853af5e9e43f4fdacf90ff3cb916c223a9768c8a633c29460c3ccaeeeed2576aed3b2cfdb695ec0dfa39e6d39bfbdb31e79f63bee7e04e9abfdf980fe21c167be93d2d14fa6eaddf9b63ea81a8bc3b1e4bef695f8fd3c16f6f712b4fc75f09db57201ee77ba54f05436ec89c37a3dc2eec76accaa02720a75fe6dbd1c573a39427f6706ccc22dc0400758bfdd4ac5bec7327b8a38ba71424c52bdb97d193ed8fda4eb6dccbdc715886a75bec7744b876ae823470e3a26dee69f8b8689f0b695ce1a27df985db4fc8b024d7b1bd70d323039389396b74e5c0623c322e1e6775ee27643062ca94e7e3e9d8f71ab871e574347c685ce1ac8f872c89faf493081f7fc5a6d75cd9a718a4e11173d17e189682e64a73a28a204a9d9092d30297f500c809294ba0e1e372c59c35b61531268090833cbaa0084169f8cc78c4386d475b520a32bd781c99f1d0e191c303499813eacc160e4fb323c62ba6c56cce2751746c005b02cf932851e09c67d62383b99a5897936c5d4fbcc9a4a08d8ee3280cbce7c2201eec661c6258720341b3b5f66164666b7b6bed17511f876fb008faff30fe85ae1e17ed77a18bc745fb4afe3d5482c377ef6ac2718f431c3e0cff3d1c3d180d7e1c708d0c6caeece3779026fcc73532e13bcf5cd9ef98dcb11494ed73b9fbb06370e04a41ce02c23d176a3b3de2c9f6553230678da52099d86c7140f665787a9cd54f54c1899327f6656457c8fcd88e49c9b663b36c3bc645b6df715e0a72d6a8ed94c07096c4a9d95d3ceee2992d0ef364fbed0515efe1c4b6cde99c73b662971e3330d20554833cbe9d753cdd2fbb4bd2173bcc364b7effd6ac8f45371c5444dd9a99abd943972375983e335b3268ae72640f1d12f073f26c27c27024d370255b295c4fa74be22ceee7773bceb22dfa7fe1d63368b644dd21f1c721bb8ae3eeda30e14024b922c9f36b8eb3e85b97a1e74ec7c5f97db7d325e1a14d7a9cb8080be9131a73714e23797e2c8f0e0ba278de743a9dced4c993ca3a9e4d0aaf59c6159d28f5d52dfea1dccef2c245af412efa0dd99bdf0cbfec51af7a955d69dd4215c845176531f77750b89b141909cf327bea0c1b0dbd272e7a37ce3232c251c1fa2587ec9f83a31d59c11deb0cc85953ea8fb364764ae9df06cafeaa19fb16d7c8980dabb422315f7f72e1bd8295510aa341ae183631ddb207a3e1f5bceec9f5607945476b3281366ece973f67cf59ebfcda556f8a5d224b0d17615c6635c88c3399f807175dc6c5245c39332288b328f67e32d3b0ec3c98b3c5406110846ec90d42170423ee7983e25dd17d8f5e13dd8f9e94eebb66a904af59c67602e84e9ff306697addef49d975524a591fc67b027db2336723dfd3401b56d621ccc5ed399b4b6370fa8594375b6f9792ff62e68cdcfba311e3bc662b9cf56a7b7b5fb315ca5e79bb3e797b5650bfd81ff57440b83271fb9194c94229ceea7efbd0c759336f2b3eb95bb9a2c334c8dbcb6e619c5ec1640f1e84dc8d6cba3caa18c95deec61ac331e856080b6198090ccba3d16834ba5724f2a0c8527b499411b468168ae73df9558ebe925efeed54b74a2ffffb25f412abbcb2a769dba781df733657eb7e600a77c829eda093b7a7a08d991d70e66afb6ee78ee12c9c8553c21f67d1bc7931108d7838a20af228e264291ec9f247f126cbf76c40842c4701f0643906400559fe18809b2cc11c28b29c719325c699f13a4173c1c22f2db27c0ceb1730cb1f712c4bb9122405151d6409eb972ecb5779f54b29cb9851e546c674b73a6654c1c972071ae4edbbb5038efc1d62d0ad95978b3b3091b7a739378cb9b8fd87c3272e16e09531ce6ced80835fce5a79e113346be5041ade0167b6503a2b2f67a1787ce504cd4219a1c5cdb19210e6acefb7dfe1c80e39ce12fdf6a35000b3b9da503ab32500a0b9e2719600ac689411503a52c05bae58003eddb27de783bbf2ea172e6fbf72d32f356fff3ffde2e5ed5b3ef5676c01e5300b28cd0a672d2bf2d69ae5adfad4f7565eb399431166517fab3fb9feb87233ba35846bac5b2a56852a5006a2be0889d00fb1f91baf8f08e31c1737fc85480cb919c7a05bb6c730681db6c747f00e389b87e3aceb138366dd2cb4b8bd6703af8b9cd385df8361f7d767fef6370b734ec9d9dc0ef42a272537df9bdfcd97b18ea75fbcdfde5341b3c01cefa65fe46f4cb4b8fd589f8c548b3cd6d8caab09ee06a5841acb1b17ca07739c559b68d17f7b9089fa24fb6fb389d788524285750b2b0d79fb71d493a5923cf24045de7e5c79f120eb961d504ad801a75b48d9c3ac2019dc2764ee919098943d4c7fbac55f66aa850c8b0310d42d26b8e30e18276f3be0e4eddb09a095299a20834e17c0c8024a1625d2e88a42e0e7759cdd42a23b22954a264e522d28a63f1556c309eb96e75e337458a8183cc9fdb58966a170bcc2eab78e6e8d603df4029a018da35ba7ef1525b2ffd8cafd520565ef49b967ad3563fa65f7a0eab15e8e818c4e86431e553f339b8d7ef4a75f48b95f4a295138ceaa54b41803d48fe847b09fa9ea19fb0a7984030ea914c63d35eca49472ceeb33897047ef664e71bd1b0fa75f7ca494958a66d5998b6efafa2c0a6651a568e14f835e145aa05b9d6caec60643f607a259defbeb6856f7fe0fe808740bf53e1b5dbc6b8314b2ff8a57ca227cbb34845037ce52cd5c6441b354a21256a1706404cdd60a6c45b6335b2b4073d544f630e32575f08765ff512a45ba379e6ae6ac3b5365d1ac9b85afc066eb249b2b5735d12398ca8a1f2ab2ffb8325341915d2643b5ce9c85baa959340bc5029caac9664b46d05cb9ea66b6543b7365237b5035913af88b7ef44a90bd9b755d64d58eaa8967536bad32826404657fd5cd6c9966cb8467d8f48ae2f1e29b9c4af50c9b194cf40c1bd90c9b15a0192fd903ca46eae0bf029467bc4caa27de3acd5455645741390591fece9c35c3e666d1ac194ab4e8a81f2db27b3727d96ca97a4eb3d952fdcc958dec61452675703c926591e8343b05e5101e3d8f289b1aeb16f933949861e3ac0a458bf2691759fe1752a06e911447aa7a662b025ce86140e368205a948f0a75f44af5335b347a50a141f5935dc4c9336686a694afe4a37066eb5764b28766a172b2afc8724bd934a4e4f4307ec23549c4987073337448bed245b7caa59a76abc42b59fb15cdfbadc945ed6aefc94ff535b9296bdba6cd1cb8d4708529e7a13e0daf8bd5599d4dd4c5ba85add95ba5cb2fa6465f5eea1777b48634d377f9b57241a081a75b3a0781869d5e75aeb83d085cc29ee1746de84bda36dc7eb7b63fe7f39c97c5c5395bd634de54a6733ee10296a7cb64b0275c8861d36ae8922af821c47908f2595938432303636271da866b4aa552d6d2ca06efba045543685f9f46c3342e77ae3a8652217ab838e54b27587ec659b36ab25aab36b3637e3f4a15e4eeaefd1ce8bccd881ffda285c02b228d88cc6f7296e32cb5df9e17f2d022027064fa9e4b3007f5ecd10ed7e896fa230f40b074fd2dfc16ebdff036a594cec8643251e6cdcc16911924eba0279a60ef4da5fe4339b613459c90fd89cc96b5f7be86c36e9123ce15a0df2d72e61a8ea105b2af8033ce9af44be235cb489ae5ed8beb7d71bb2feef6c5e57283af8136bcdfa4c8dbfbcb6dfc660be38ea247a406ccb96ebfb836f77b5cedbccf7e714b9ffde2a2727f7145b971705f03e290200d6ebde135f4cc95e07e0fbeaa8a7ef434a21fe11a26f56be88bbe629ad1dfd1178991df3d38830bcae06a123c72fdb797dbe8b7973309e425e817d92d26902d6f7ff54be85f5e76d8610003c058860c52ae3f92b2ec72fdb1cba3bf6e5489d32d9be3b8b8fd28f4d75c6d0f6eff85eda2687b0bc695dffde82f076370b9191b3b575bcf7569c4c5cd8240481b17b7e7b02ab592dabcef7e037548d5b3b8b839cee6e1d173f2e6af0d6b458c70113fe66afbdbfd8ed9babf7d0555438c46237c71cd7c11de3157db8bfdc2fdf6446abce5527cb5fd15574c99c20517ed457bd1603418a3c81afd65a4a7c848c88c84cca1bfba657b0ade98d96297b9b86d3379858bdbf6f60cd78b27b210cb89994f9a7d5dc071d7c9f2e54b1d1ee4b7c42a51ae0d2c9594cacf148f94c5459f4f59269e92841b2cf9c2b4d6ce17b0c1670d50a4e099b47a0149a65ef022d30a851238efe33c8f73bf31229303f34310dd6e67cf15275f427eccec18d2b407a69989d93143f3b9e776055eb3b4cb36751cda8f44648cb452bebda6951a30228dfa727a8ccb66105ab26c5f95e5c759f4edb370c102345bda5b9619ce4d0accc1ed58b0e8950d9aa3cfe126db1c5ea3b1b5a304c4c12dbd9cd582429acd566bc7de1dd20cbcc11d5b50b27d9629ceb22d28ad9dd96addcc957d6b777686e818d2b76e666bf4f627776deab66eb27dee6f28bac8bded5168e78ae3b877992dedb91c6e6accfaa5a364fb2c336779b6cff2335ba7b7cf12345ba6b739e8649b434eb639e0649bc32bdb0791dcd19b5eb2cc4a380926f79328fde84f3889d39b5e364d49352fa6396195874517eddb3761d5c4456c3fd23e89d26f5f84a67dc7307159b3d6cb59fef65efba31066aeacdbf7b61f3dcdf623dc7345a3fd0c090fd13218bba4576e4b9acd9525bd6c7047d2ac6399cd957dd006b77bdb85ede2ce1e6364f025a863d60f0c475406df411c341f5193c1f7b40f0c4752067f823a6a1e93c8e07bdb07862398c1a7a00e2d8f24c8e07bf603c371cbe0d7ef4eb89f47d3cd9143d480067c02a05a0801017e9666e14a17077c7dfb1dd0b2d33145cb491b6e44680fa810284246a0bb657a04e40e1e23d06bc0d760addddd78eceea6fd39a40cc26bc007c427c4d7208efab3bbfbadb43695923d061183006df47b7707c4679d45db06f1cd2999745b7b459b10df74d15c736eda9c9b36a70c1d60d2519a210d3122e23e40244310008bf822e0ede8787012b013486d52ba340ad40a500b4c1f7e010c7cee847bb3fb6ba90c984a27aae3f319298998335f38803a04119f3be17e1efdbd077c4ec325a11c0faef42f420bf5005622014273cad8eb091abc9ea001ce946dd081fc4ac5ed9799e51be0f2f44b5321cb6f14b8f4162e2e6775142a76b27c1f7e989152b29cde29f95245b26409d331977651e9977e7a04ef5b76db5058f6c108978bf27ff4531c36fee1a3868bd29fa6e1fa98e9ee87e99e8e53a97f5174c96d81281964ed5ae70db31bf9b5ed671fd02d38c0ba80b9cbdbb2ab48ad1021251fe0793265ba2ebac440706f06e1fabb8b0e84ebb56b7d59173feeb5afe94e5088995d247d895d72b4fcc63554392a0d771717678d1cb248c6345c94357cfa47f70d3a51806479be1141a6d08323f306316383f10169a1446ed934545fe2c9633f1982cf0f07721a2e35445d90954a40424070849318bd3f38ea44a2f0617c04b608c8f3b80fefc800c08ff2755532c75b51dd20c3fb388e030ae2f430be8543cc1f7d0d85cc15a59f040eff0f86490020041f87a33064a21aa2f4e017017af8beaa0b01200c3d0e458f43c88486f43233a09006433bba2f7923c445ca94ecf04cc81352bfeb42a11b5ef53633fe7ec78442101cbd082741fa1109ab86207de8dd55dce8fd479f4409ab3a4c43faf924acaa1889238090a447c246f733a4577158550418c235425af08420c48cbe8493604233027f3ef8cd914221d2898bdc0d61ea67842a2f2334fd4a18e35521ea6f787a8b7a1b953ffd36b2aa8e89f13636a9b7413df83264628472074c993ac6540a3b665492b921919b1048295529c2b94905df6732adacb0d430c257f25d6eab7f80fdcc14fbd879cdc005ee3a51c8a3ad578802852993562d48f901ab0c63ce4927a519c89c5389a741c4f3d9adcd73c75cf9d8341f3b3b66cb637ec3736c1f2aa9b8422c2bb10fe3d6e21a12c45499c6a3cd60ca6e9cfbddb37b9129e5143cebac395d5c6c4d56fc2ef6d35aab74d1c54ea5aced39038f03d773539186236e9e38158b1dd982932dccd6607dd2aa6dd6725bf0e44b0d09207404a142e4f0973afc657d9beb77eeeb02425d6aa880f0ef6f0ce469ed6c816eca44e7bc1746e54c1254851a74a200c3070b23582c916a903e69d536cb040f0798e5378bf414f70407722f64dd3fb03db86edd65bc168f293937dfdcb9a741feb2e93eaeb08613dc08677576723bf76bd626e17a1e5359bba6d47cd52578f2fc5f71710ac9d2666e0b6e0bdf3eba73b76fe3beaf5792a97ce955b08c1255f49c3c947a967bf73894bbe7ce7134a33009508f42bd877a31a9b5864ab29294928f8b53baa57e050dddc7c529257fe722a752f74e1e899d1bb9fb153e778a879d0b320079512ac9365b92894422d168ca666be27053e63f2e92be2fa52529259fd294d28c0b67cdd3cf9166bb71b2b99ae1944d1f5bfa51e2e933a54c9cd98af1a907f16855fef380662b064e59ab726f8a3e29aca25759e855e75149b679494a4c892af2c5a34fc9d49d704b3fbf246b3cda3c45ea8ee8cbde42779c197aaf6e719ddbe2ca10769c6e992f0a65ae200e2b4b325bf2294971310cb7442514a3c4e1b4b8634391a78eeebff73c09fe68bdb0411ca0d4413e8c4ff0c6873dcfc52493889b5289e28699c3938a6e995490ab394517f2fc89853cbf5b7eee387964539667fbe4994d9c557fbcf34b3267694690c114ba90e797a4784b74295de1a529252ef22c7971670a068e3339e93860b8edfe62e1b99eda028a2459cc4d052af0e41047560f94d4ce4fc659333945fecc96e9bb5f7a21832418fe7296cd8d4c02c539d758c01ab97dc8fd9fb7bc2714763a5d926e67aee693c28ee70bbb265dcf0d3f32da24dc8d85d92736d6335b160a900f3f357c46c37d58642b3187e5ae0968a3e371b103f2efebf5caf20a57620ed643916c3c1d4f179bad8ea7ebe960dd1367755f553215149d3f059dc040d97813b4d1fd8ce26a4fa9e704141f99135078e8f4d04882acca117ef61424672e004322e09135e4387a0a5241715156f18ff539ac82e2e294d51f55b12ace5a863baa62a3d07b5015e351c554326775941acbbee32c0fcfaf3167c93c06a932ef0bef4e78935c9d1cdcd0fc19e5ca9875cb7c15acb3c8df8bc00e07301ca5f74adffdbe31fa9fec78940f7ee7d289141e21db904ba3100729df534eb74c5118a4ca3a1f9e3cffea382b8455b19bc459209e7f779cf56195c42a281e56c95cbcc11d4faa18ea46ba6c8b3ca2704e4153763e794a717136f103946b56c59c357652f2fc39aa622a28f34f41ce7a39ab9bf8e93192e77ca05ca584dad75cb967f1e2a25e27306e6e27abb22231a9b733362830bd8c47810927c1443504ea4d4f83ea98d3178931e11a2612d3a83e856b2eca76d97e85d558bf68d9aa7c8c0a9425ea5742d59b422652e5694cafa2f2266cfa18b826c69bb08c540af5a9979866e555d8f4354c6866bc09d730510d617ad4d730915f63c2d235e365d41a24810c34f0818914d3ae2e8310bc5842921b08a109308c1d931176cc8c95b0633a4615768c0c263429155c93c23ef9c75ca17c543ef5a63f0599708d0e5768a20d3129ac92a850d531a8d7090c17b71f4f41a6254bc474cc29c87988e990dcf1f4da7ba72067d53c9fce36b4e114e42cb90025a69aa926abed7130bc65fa59fb85fed4825e61f2640d7146beb2062fe8641b0029739871d13e8d8b2a1c23727a48756324bc318293ed872f17ed8311beb2e5429bfc04f75686c7aa745c74ce393cbbebb752c072cdb152964267098fd834dddc6fc37b1caab8c7df31e1778cf704f881ae264ec8c064dd7bce2119925fa9d8c1d32f33b295cd160d1f974ff7a36b96edbb520d0bd1eac50d6197ab898b4df088d93b65785c4cc395e9c1324d5ca45edcb163f40cee842b7385e50e8faa1ba42ce3a54ede7ab20c0f0c099a471a3ea1ef1e947922237c6524e677aa1c24d93e9824dbffba300a17b9aa7272b22948c593ed47794d21fc0089b94427db22fe314ec2f4ef6112b06c1f87ef9c70c3affef8515024a67e18aafce9a3a0484c385b2a7fcdd5a31a22fced69c2af61e298a6be866bf057ed6be88758e5df31db1789b1306ecaf0d8f0bbf7d08677ae6cc5e2be85d589c78ec5b295e1b121c5189b6ee6ca36e18ea52050278fda4e2c0cb3990ca6240c3df5073b4a7cc68a06847fc20f710dc5da4f91181c6e387365c370bb992b5b5ad23d576a62bb2ff5cc1961a9a7e4a404735667988ba552d8fd8c902b2df1962c357156979694784a4d5cb4fe26530ad528193fdaec6109c845fbda4f29a6fd684025990624e6928fb7020bc34b4a1b749c3359f13cefbd04149bad8e9121c325e3b39092c5935177c3ec6eb8a11b808e17528271c3ec960841b32ba78237c4ecca7151ca1d8ea3feb9411b5e4122c2d881c1f51831bebda5819bb9b21fe3bd60e35fb784db29e18e2e1e0ddc88d95f0337a9b79e4a3dd75eb8b9b1ca8e5d3c2ef6dc0700edec34e1880883870b8908a34912707cee3b1a1161347191e5bfa3c3794484a1e32cc799883078463bde92e1c9448491c40b2337b70c0760e429a18fc2e07aa5584f4c45133e7e1ce2926caeec1789b1df4c6e916c9f883096709c874484c1e3626722c2683293e838d8724444183d2e3611612421220c1da9e36267581e69f8f0d8e91799c55c0a7368f8f40bf7de13f22873b285c11dbb0e78b01bde831eae80e1e8bff2321c87c0b2e3209e8fb3c41e71b3e3e6e4729839a1748a2bb27d19294662665cd89f1da7ba41ca9fea3b07e1e484f4c4f4f65d509c2595c0cc192baa70dc62d9be8c70bc792cc5b2fd100d9f6c3f464eb69f0a91a059254482a2c251833236cc1496c271cbc97647ce937ed96e7a7e4a4b341d7712339678b617098f5ad0288e204eb6ff336e3bd97e69c7590d9bad077b9cd5f68af0989239946c419f6c4770464dafd92ac5e6ca7a8c2d996eb2fd23618e8ef70415747a9c3c41c50d19f90805e4ee16171217ed1355b07942ca1450021acf2ccf54d95ce9905d392e5a241506c406864c5d740fd6851c2c82b8d9d2768864f7d9a25fbf628d8786628d08115c297fdfa08eeeb92e7fb8bbc5c3d1f3c9dc77f6f552220ff1543e62011c56d5ec2e24ae9c59935cb30c0face789e9a614647acd8e94824a415e6fe0766c0b29d99f0bbde7e1ca712171d67cfbda8ec6f384478f066e9ce5c9e7debe068c386b6220f23de4e1c45920e6d104873466210d9f90c78e8b96c71217ed7b0de2f87090b2103947b86329a8023c5d939b00a07e01d2bd0a082e3b2c8f6d452cf470ba651ae172ef9d116e277dd2aa592ec4716ff30882ccbdb6d32f5cb6aff1f44bcdf63d9c0af0f48be7652b62d97a39640e8f413c589eef599b67d8d9431e49421e3b3c96c4b6e8b12289153b309926b12d72381e497834e178ecf05842c387c60cecbe2bc2b5d1c57a5a8a17157eb28d72e50d528ea293ed874247cc0fdc9003aad5a8646c35b649cf3a452302000000002314002028140c07850291583820d372c97b14000e95b84c78509aa6418e420819420c210480801400080082242000ed460c1557c01823b0274cfec8d6bb4210c10feba7c12133c615b1697697a1c29201d99010dd3f4e3ad71c975248459cc97d75efed2daea1cb2dae7d7d466dd6412caadeec13ec89a2963a80f529647bbcc329bec944c6747f5402bf8b859ecea591a4085f36250f89c3dec3392edbf0c3c64a642607e2568a6504f50af80e848d3854daadd8406f52c25302981f9fd0c7de7bf88f500157378265063ef95810587528b23ff0005c9a86a71c84bf012d02bb327dff905171637cba761c354758ca6d22ab3780935d3b958b9de8f912946e7e776ca878e7d6a951c3ecefcc13aa3440dc35f945d18329be9b77f64277ed9cf6bf2e65d927936c62bea924f7290273267c06d42b6a4c9439313c6470b11c88abf0c4353ecab9a540064ca099ecec1ba18ee52fc39bb76ac4ec1e42a62b7addd9c8adab28d162b525b4570e6e828c0203fba3b1897cb17978870f5c609896e28a030cb98a65387b9e47b82fbb9313c37841eca5d74afc05d5ae516bf96903667ba5698fc7e9adfc722242d523359a5b10e47710dbe1e889e8e681ef7ca565308398f1f5ca402b6d69241309c7dd85a8058b8d3a1a4a5d618809dc286f45d00ed9ad2e3ca9733d31c9d6cb4bd961362c09c25567438bbb0df92137cc1841713794b818521d302445731bb9df9f78cc61e7ade1c36746bbf06fe016bd8d049923101763684337939708afe0a6393142d2e18e3c3ccf421e44d090c2358c066715fc72f5b1cf81e1252eb076c4c684453bbc50ca3808282f7b15b7224f396cb72cb10cdbc4dd99292d838940a9997ba423286b43245a695540595a08930aa54bd79c20a91bf849dd907e1454f72fc70104d9aacac94e92f89b120e4418802dea23978385f11edd0aca405b22171d1a2ed0292909e7e117486ab7c5a024c0c354677ee50e95d0e0a7406e30885704d1fa4964ded229032fc01aa461b03aef06f297267b873e9db03a1efc9ecf6cf12bd245ca9fbee57f993e4b8e995571f450f7a03984b642758a4c6121a0eef9ac91aaa5e5c9ba71adb3766806c1667b01c853bcc2714c093ed127b461561823b5bc91fdf3f15fcfe99163f1eed76a3b72c4d37cca53b3a66ae0c7e2f3150568345fc796336a88a87b5fadc9cb9b6e855bce45f08adf27e0fbcb396d0d0d2744ba05367e7a3cdb371277971d5b93a4053bf248c626ac25cd81301843d53b788c923c39fd188f587aea00c0d0a235c1568e88a9d3811b22a2b3b709d39d07d3d69eaecbc3838c0e3c32ccdbbbb61a0bb89075ee9c798b34b98bedf1a134a8bc87151b3f1a3fa51e79b37007340e4a68397e264550dc7406d578da7c5a76bd4ac09a860fd0065d681ef832229649474b3eddceef6b3ec24c9eaa6426ae356cd4162d955c2add8eb648016941e6c8615cc4fa4dbb6dfe83313f252bd26c40fd545da38dd1c1d375049412b84371b96dab5c58572c894f12d78aa7ff9a8796e1fc1b5258c290816c4aed526c1c60491e5342cc9bb9e3dbaaf4342b584d0928b47e8b9be73862c92631ba2093cda469121ba0243d1134976e4a29ed09271f33fc0dfd3e9e9ab836f91deca64aec52b5758cc3f41a0a95bdbf966cfa83d8fbc24b1eb580d6d0d1c13c170bdbeaf1e40cce72b3e4214d8a86b2ba8d897c3e1b2b19084b5cbdaf02b8f014ed154d44c924ba8c5d7489883fda4d576d9210d47ab2790f3d93acc5100833a48419f4bcadce571ec461a4f623e267b27a8f66849ee7f105c3753f0e89d101a4840ada8a939cb2c770d8e7f71717918d11f99d67463fce251cbd6e54a2376b491503249a8e6eb255d77e87417e4d7be4220e8379f0f404fc368ffc8c65e77e3ca27ae603b7f87c6c80c7a970c04117a558e8bd203a2a6ae81a25b845b4c8b573aadc40a85ad60424667ad5351dd3216b6984ececbe3c6dd3d82710d56f5c925f6f03401f9db416b2c9ef646c3ff7e699581e091a077315eb2d27e78214409fb244b7b28762deddacd0558e175363f67bec1dda4988a3509305a947c7493a607871a9f7f737ae4dfbc056642de8e6b58148bf3e9a737c0a2843bd1fc905254470da00afb3fab05f54c7465582460bfee68b9dde8ffcd13d1681828da58643eb1f378a36a09f7e3f3f781aee05b22c353171de5f6178bf3f6681002497096cd7f90f8e2f0b094a09399cf86745d106d015a4397e0504da659246fb0d4bd2061d88c678d6808bfe3c60b4de79191e83e505cc2fd10340b947c712c027ed5fea27b2d2ca9db60ad188f1bce6c003275fee3f91302f5f1cdbf4fe7f7ce0fbf2bf47d806640848a63642f52e4daf762460401b0df3e37fc820eba24a0acae95c587e3f74201185d6466c1c3f7ec17620d07cfb7c0aba034b3f7e5bddd56982b305ba269029205abf27b1240dd820e848fd9f42d659717b12da43f4affe5476ec01e949ca152467aba3458c395ea076e81f3957d46e53e3b98cfe1dc041054a62f89f8b4998a80b01bb5d3685e558a205807f9b0d45ffb263e20fa3d56f82b2f96e96516f7eab81309dd9c7268f0b2ce33533401f794a25bf308a7a3acf2945a2b9f32efdcf59fa778f93bfec3f273dfb6fb72945ed2770026f80e834f50f855afa5f7763dcefba6b606967ed7adcff260c541797febca252c0e49c2070388cb1e161fed108976f6bc29876a75f194d038436325a54291802383e30924ff3f1e76b963637d0d767bec43c7168498b636a35915ac7a5b3f16b4dae51820f4023cae01d37f4fbea4131218d37e250cb2913f22f23bedef3d6c6e748ad8a086df2af4793441e93d0012c31f7fb32e849e303b012039b0ab2ff5a329756117d3650821a31fc8fd0562316393f06d058869d2f643e27bc4fe587da5052df12a643401ac4679f9376f7cd62ff43da33559e1595379ef9a9ec96eab84f7d5ec6a6a2f06ac8967b96e7985375112576c03c32954d87bc982738add02c15a16d0d1fd4fcecd2b2b2f4e912bfe1fa4fc0596b2479ce7af4de19632e951021f893f22cd7f1fda69c51796d2366192f44cc0eac8dbb55bd23d7683c2c89a929081b702b4d8066e8877a95ca3f7161e4cedcd3db5fe4929bdcd3be4cf908fa289c48ef80bcc32b5972510f309823b34ec98b4ecc22f49abfb49187aea2798da5d71c503f640e92501cf59d62f752934c65f3b2ceb42f7bbff3821e8e8ec9b9102b82385539adcc8c6ba8c668da6a1ae748944e2c02281ac0dc56d28c5f0a921307f5101d495c26bfb2e58c5618ce5b7ec3a9502cc554bca0649ce2811c875645624ec72eeb1932916f0568cd5894d9347f03f25e50a03ef6b72dc2ea81d03cde786bd529191df16971ce28418a115d952cec3e099d7a8e4e6f417b12a53907495c9436f825c697f35454436782b4332849b9381ee15eaafad9ea57a4a229983b6596580e031b70d241d90d6c14eb604a9e962ccc2d2be5bdf05b9632bc5c2eb4cf0996dbdde8459675caf51a2efd58570bc3b9a3a3d1ae43a158efddf4620529dcfaa312ac282e71c52cb106027e008080d2847e803b006a6383c71b5cf6e09c6e084469027f5dc04569d5b699b8efe651194ea89018e7bef75d21c72e242ba36bc1c38ea6c63dc25326508c2ccd950962dd5ce665dcc663d40c5ce9874426842e5c78f290aff0128eb25d0492c5854eead499b658f744326c99432010c84cefeeadd237d6e6bf944f90e312d0f74b0a1dc144a89dfdc27bc90c76f39d07eb05bae73f1a2c0bf66b8fcff05ee4edd31a03b9f47e1d037ad57ae2ecd50f96b642b18b23e6c59ae1e102fce1475a933d5cdd54911a9bec4040c9b89f0e7e3e28bf60898475e62e989fb334e6562d1a0428b06e018f24d37733382783f066053018a869f8409d387ac04054e7c02efc515e1e1e5766f241503a13c7b7acda68560035a7ed2c102a8c8a07cbe93d3600ad6619818b82b537f3ddec44b29f40ec3ee360ba40411f29ae0ec5a6d389803de0409105567430b204abdafc14fc1a3caa89786eabcade22252fc0a4fb5e358b7f72837d623a59b82159c3c79fec18a845bf73cf5930fafc1d835bbd0c96ee3ecd656bef9e505b85f9ff479d8b2cc0e08581a816a8a759018c0bf0ac0d5b715f8f2428f4cb720ebc2065300c88649d1106e2ee19131b59acfbc2fac6ee348a649824174ac9b499e819077f67ac9a1a5edd4ad70a5af5fa417eca9acd3e93798e44ee27a807e60b998bef8f18895c315dee690783105e3a57ff083a88e3bf982020c9d08f1a895ce6941ea4a7479e769ec34b7fa1276535d3b7a98fc9f6da8d440e59cff822874d0a261a54065e1532123995fbe8031a75d83d6c60bda2837ddbf591c8159b65b142a1b15d39d5db55dda0a27b7254dc407708e17e9a11b62301381239dc2226de08346d4ff1ad857f8d66156e307de6aa8d828ddcb63d89ca68358aa03c08440c507224f2bbace01dd5448c077717e4fe420fa6d14209bd8fb0b967f6656643779825d5c0c7416e14e0350c28e40a141d8d1e0fbad99746cc9d555eea4ce33f0889ffea99360be01ee4d39040285f4bc4c239c787af62ee0007abc11d26975b5d8cbe8d80f06956bb8a1a06b8341df49b88935a70e731ab1499f8d8cc5eae73591034002e4ea559251a91f77d9040e02fed6058d4a854c380704ba7a0a13056c288dc136ff916670b6843ca2848e7d0984d8546e5eb1d52db96a904bd0c2b20afb48206ef75a529e4bdac8cf52d7525e7276244de0a884a2427eeda2d4443d2687b780624e92d135ae66e5b3751e8b92673db0c201faae8bb5bb142b42e600e57ff760f02e043220726419b8a43a3fd29304c39524f38dfabeba02ec00320f1375212926ccc29817f8386cb6954ad9ae096695cd83ec8e8fb7e01ec6c23540134f7b82f901ea51b3b317adce3d23f32159992e149a08c5f604b3895a4ad758b35f2e1b6000bdcd9d7fece07fa86513bba048c941d66bf5aed5f9661e22c8f9c9733c69f9e0c610b37dadd9995ee02b444aa7d51f1c60b23e4b347dfd2e5c47d96e9155182a1e3a8609ede1a5a80d81e97b0b1cd942ea42f7936718bf91dafcdd58a8375ac53034a96c49505422c875eff38974ccfc424f5447e1fc854979ceb36256cd046c3588eb7078d7abc7071fc764fb151c29fbfd5a6794c207c61c5bea12cdab930ada768c8139331d94d52f6011e46ba2bd455c057e0c5327ba955a9b689f4b52000aa36b7478cb799fa0fd0937c85d80892e64c9f4ea57ca88cf24802cd8e1f0f7b05d89afd854e0ae382ec00901c6faf4b71009834decb65a76207583ebf0a099bd1469f43afb278df23c8d09502e816611ba486f6e8d3e5ead3b015382ab52bab6077a7372fce5302e4ada8d91e46692a194faeccd993a64dd9b19d4a6214ec2721419c63f80df295ebdb6989063b0a62c29a026312c62a1193c29bb03c18102858ad8951fb5476a01b889d3671c5a3c317091e064bf8d173c699b2ed842e1dd5041cfd80bd35d5198938efdd9444f6a834e94d2c5065cb975e93dd82d71b583fdac7cdfee0022647ee5023624e7a40c7ca2c9ce535f04c209bf9bf7a7e37996801aa32113bcda8a142ba4773e01469360277f061949d0a3fd46afe2b7d4c6b240e94e59bf324bf6160661db87bf8ed7ecbac521b0106d8dd812289addbaca5df5eded55f182827ceaf96707611b6898c198b3b8f3953678d75f1d8fa383f9a6f8c51b228aba84d382498879fd74454c4052eaabfd1cf717e0385f4f7797386776a5505a936370b87ece745e43966bb51d46fdffb5fa86c856bab625561813ae868d860652c04358be0613d831a958a7f4ee54d52beb67720d1255bb5ebb4046bd0494f51ceeac173e36a2e59666dc651e22fbea91c546b1a1a528d770fc63b5cb7d6f004a74f31c3d8021938ff56c8fea297a0db2a16b779b9474343f594f9eba7fbbc04484c1fd7b8974a5c235609131dbe4c89cd0e438dcd5e4d0bc355fa0f152ea4e281274d798bd059a6ef262e26fe5f628e09b60348c2c910833d036a6a9d026e85bec5e0ba35c9599482a24903a1b351961e4defa3048486957b365ae4a8f668c4971f653aed93f91036eb6eaf42fcb7a0886cbd6f6a92ac7c0a805289e62f7a1a6c9cf4a2936d85c1d48c7898d5a21a935bd1c7d0b628f505970fddcc5a0fe26b62af2423bd1340ab5af6df13ba74c7b962df4bef3299a4b4292faacf657c642c16b5ea6f8bdde4082749020e3844f5a0383e4cb27484e471a1ec0d7dff1360b7f860f4853ffc4a26a52e2b5672fb4da148b45a4987c61d490017c283e94ebc2a91b5b555a101de18509c4f09669d25a3bfd56c6a0e195fd2ef8bac45b3c7f2edc1187ce08da46795d4469e724f19351fd0edc907c7893f9f4f7f4d9842292e3e6aa994ecbe9f3e6072f91d2d37c6752954008bcac98a517f6ecb7d871acdc63156ca36c82a43e5c1f1bf4730c8740e4431fe89f62292c9e240ad7b0cf59e4265c10871ed4e9a1dfc0a2b3eb14a659157df93ad5739c582b36eaf37307e0a9e3de06ebbdc456b245c1eeccd4f6e6134c79a36d0bf5d66e71152829cfa17628ecda3a64347c7d1d54423f9d4f5a01aed9b2a1b06556746620a7ad149cef0e124121fcbed70dc64504e384fcc94195236862566c720a4cd87be421f2ff829adbde6b510f222e313482ba742451272d66207682d003818b568d6d239b4beb2510506dcf4c385f481d8b7047cace1b470a9156bfe9a562883dfce887e9b26d4c32763a1c737523e2e4ad4cc729d09efcdadd511c786b022c580117902f5225cc8bb2a84fed16ca19b7da6c56d71ea603818694b8a31468d227c1af44362f9c323400967df20a1adddac65e4273294cce44ea712dfbcabd1b6fb46cfa168149f40e6274ce69cd5eab5b7c301f30a243d2cfb33c5872e8f68b5c23c97e6de4942e76dfb9d5e81bf365a475ced7b4afa735cce12d0c1f9e7a69a4bf8d00fc7fc7aa83d56fe834ebb03a0a40ef54ceb07fb0a7a79dc924d42c6261b8c5822274367d29225739dbff839802775c05eaa60849cc6a14a2999a33f0d84e2231e68bf9258503795eeec2fbcf4fa5203effe04f8318135167fa229793b5a734bf82e7b561d989000348b1b1533bbce2551820d5f0efc1d00dbe24474e0c221ac1edc84dc0825fba9c53ffd0ceed03c8bf93ac2eb872c2996839f07c55ce1b9c17167e6795b620fbb91604438703fb413158952d09f4e578b3b19c3e5b0d2ec9735543a7c25cdc8da3a60eb31128afafff6486906e8d40311dcc7aad93421b7621d0c2be94ce560de844da5e08dc3cbd31950134c8f48c3afd41900e7171014532affe0f07e4c1999f9220c55d7b4fe78064c66d5e3a29ecfd3f639d6cf64d32a54e4ad9d8759aad96603520bdc96d694406ff20f2bdae88b407a520a9592cb4a452d50d4fee17ed90daa3e95d68df745deefc984cab610d98d0442066e6fdeb552d34a1a4798e6a32140bf0a4635d92f688b566d98d4681f9150e3ef3b2b2bc7c6a725d5caaa6c74465460574b606ad4d8357b43d1a1fe616be7c46f304fa373f66bfa1a07bd3e6a797cce7753cce1e92d4c4e957783449de2f142256940be30b55fb8ee31f848a1d861bc3685704f6eb00cdc36072c2dd67b5b1f44886db566736807ad177e38d2d6400335b549f4d34616e4e5852f2de0887d65f4d9fcffffcff2e3b30bec5924982c0df19ef3d5a02eaa377fe4602b7e9056c2d82851f367c95197c24996f15d705b0ace6387a29aac096176492f492d6af3b002c8ac54b0a16d98dfe669ff51c61dbc094ddaa7210fa8a6f6bb264db414af437bdb8b95e7d83aec4908f144275f8f807531c3c59025dc936038a08f91d8f3b34a004eb3edeb37f1d1fab7e985dc067473dc10dc456549e67b8ceaab8555458b7a41008198030a58b2b2d111a75a52e03e1722a8e9a8cb59756827bf236d8e10ee2aaab7bbc1f3fa8d46af0b105f631666511ad1d01668a27a80569e3113fd9dce704461f7142c6f44dec9e2b3af8e3ecca03eafaaa92ca545136cea4f4f6612da3830635b5927535f6d2fbdac359189c7016801f83fec05898d44abdeb364bdbb2c63e3a17c1a36603d5009319c429eb653c519f0eb4d53d9d01459ced4e3cb967f489653e26ddee72de0a6013a2ed9be95a23a4e1e41f0ea1fbb566aa282e6eab66b30aead1d68f4192d53662364c4e121104778dfca5da50ceef771fe8f468b4114c304ec5be87ac9e7822cc408eb0188eeb87f5ee821e01c6d60ef1bf46eb896a8774ae15ecb80de434f0be1b74c10050d66b9bad7031d0bbb1fef3ddf429ed9fe6332bca5166497a914baefbe97c3de99c2298600ba7607c82af23451f4f46d4ce107d443f29f5f746301fd97fa90fab87db6fb2f2a3d1339f12fa49f3b9d035fef1849da61b2fa945c7a3b3528c8dd3e5b33d33ec9f90ffb031b65252fa1242d9d7200dd1600cc50d13840b02b9a7a44947631229fd211992d8b83c665d463801ee8e3139de6f6cb3bd704bd7d1cc04744b12aff5591e3ed2fbb39dd302a1718341e60868e1e20068afbe0d676e62a090fe5459e1242c144e5fad78dc5cafb95b8fed08d81a06cd3abdce9901f62d243d1a220ea8b7dc805d693c1e1df341515f1276f48e8382f209b935301a4effac233dbce1f620833f8afd354c3da203d988983ce2676808e36daa13dbc5d5b4198b28d5f357219fec323e1f104c3f66e821a057067a10263df1ad76e2b1cd0eef471ac3873fadaee3c95f89aa27a33e623d29350dccb3a00777de608973eb84569c26637df5c495d9faa04482c02f1f12c7e340e5e683c2f6e8e139710db85ec46e5b503edeb0890686b104ea00957663d81d9204799ec0deb4d2e36f04d351f6375fcb8e90679e77766d0a069f4dea50dd9314cd3bb175adc213fdb6ca039d517ad2b4184eed28eca321e760a5692046376dc18807389034989c349f381ee0f986bdf55636a7506b108142afaf9bc2f629a120229e0c7b98f95d0410f46c6c63b14c8de172d0441cd1bb68ebb226f22c57afea6458a1d5cc05e56a0b2a066313a7b3740c969ee51ce5d4ffac581a63c282b4dc7a558c7eb0f2fd10387074b2b93cf69224aa28f4a7ff9036558577e7a605f1456df51641f71911879fc3c1d0f15560ac5585a2a6e09c9e43e2bd9aa3a035225f9ec147ef20ab91abff3a30a39d1a96096f1aa9571b71e036b4f20167e6d7407b6cbf5690630eed6335e53cc2e235e2654bb62e8cadeec90a1e348e6292a5a1107582c86f9819619231e115d55014db8ebb71f7303d5c27943164590406b460983598aa4318235e2bedef92636f63fd6d99a5af3bce75fe7eac5c825f9f7bbb3e473ae1c331242caa62da81d851d3727a14d326ac0d9ecac123a33b769b3ef8b76ed3a676e24f91a70cb0df9d024d92f739643ba03e38587f6c69bd9dbacb26c1f1fea01f04368c6a409896e52389c12f2349d5cfccb551e3c9c83cbadb7e7e2acc9359880b5bca87c2010c23ca4ccfb5851028c38da63d8a863c521c995f6bba7150c993cb7754c9fa753e35d3254cdf1b9abe52bbb4e9fb9a47e6530ecf0a14a356e9d6901fb89103b9d7ab817f72335ffa9915f76a221ad6f787ac9b519e4e129ba2efc434356ec49b0804427215a623b7dc8b8da3f1ed3d661bee62a0ed930c68d43faacfc482690b05bf87d932b38611b6788e28e42247a1101278be0beb1a63c726f85f6f0ea016b7f9cc4d459e69e3631dca0fc596fc528afb5f147f249ee3a8cf39081c1df336c958f3eb2375b9eb709151f1e10de6ca2afb2b67912d50b7b7855d44fa6df86ae1a562872576ef2056b813d993ca7ff20d4649a40c298cf34e248d4fcd3566f418949182019971660a98c8770a1ee4c68bc5c69fc97adecbf8f49e2bb218fe2db8d80b2b6dd0be327b8438dda147d5bcc9a2118cbe4312743694a8f06b8325f4c40d253734b4cc560b3563703c9c6a505534eb1902ff29d2349614d4c9f8f56ce0075e6ee5202ca8bc85d968255d215f5a30991d0e93bdc89ebbc1f86b4f18ba36b53be2b631a2994535d2419a966ada47bc33d71f2c1197e466380d124c9cd35869112a732222ded64e1ee6f43d21d87096c484aa24d727824e09bb873b463f7e543b1e43fcf41e67731167943c0530df45c072d57fe85f1dc39a6cad2c74cce248dd3add28d473f41a6d2e57f5ba0fbd6957ce78db70bc89c3abc1390e95050e7e242f8e25e399b2a48c141d0c80d4a740f2733e1c1c9c6d28eb3b3ff4c7cdfd7e15ede4379c6ab8f06276b6f170f68cfeaffde3023cf4c3d8d091a21f3dfa85d815fa346554abe3907c35aa08f7ef60f027fb7c6c508496f4aa66501b5990107cb4dab0d0dc4383e4c607cb2dbf425004612008d569880d62d53b8f7ed118c79a8a0f69629de131a8a6dc76c8d3903d833be151bbac5b731178fbf0f4f050a5824f98ebaaf834b4aade44682ec1e2696a1265c21bfffc69f64c6bf04d7c8c5cdefcbbea433a152f585a2d75943bf5262324b56206bcaddfcababac166d25dc12da261fd78b12d37f5b0f13c279ed84e1469593da0b82f01bc81e0ac5461723bd974f482f668f97284c5aa7db6425add3118f24ad13b1124357639a4b1b675c120934862c89e051fb9db8e3d6d1d3c6e23d79f9fba0d6fcd2235610d5078180be51f2e60c1da4016107ba12262454c08b5418ab6562fe0669f5ede59d7c36358ba3d683898bbdd7e233d89af60a294c0d3211615abf9dd3e659122414cd9d97748f56c9e7efc26ee22cf7ce1a3091b0f743eea1c820a8854a279a55865d9475ed4044f51301a96f57f88d62fe34e1891fd75ea0dcf8be3e10c53e1322c105bd316c9827675a511762f5ebbb006ba6161f2672708c2a692a10c2203413eba5fea8a5da22d5277935602e5d0046c78e47db2cbc3955c657652ddf61b83d6e1b6cb3b71e84c22d8517914d72260fd205f975683a6256bf19cd90868d4842a5efdc64cef019961ac79e85fae69374dd7c03d5820f3b7b62bf7f7bac57b8a79948fb41ec0442b925f298fa7a20d578864f69721125bb39fb3f3b0fed1d3c1faa2a499122f9aed297caa4809e2c66ef66c187b6fa8f940ec9bec3e1554ca2aef2bd6930f000315770c695a85454704e5f8efd155468bc02a19566ab2ec9a823a3b7caed38da1b522c66f95e2c7f66ea0d2d8df06f9b83fc3483d666b2a9a6c96385f475294e4aa72dd8009f667d34391cc4520281e1b164def2d0e88cdc6dd9e041329c6ee6e9eaaa714098ad2738eb45de231ad8f3a1c65084216a9903ae6bb6e5839e98af2e5bb32dcef0b17ef22300c619016cf3faa209783acaa755d0da80c5d31b124bd4140734f7cf4bea7fb07c9068c28e2c81ad94a909ebd270e98c7621a5922aca6a6bcd979cb54e5bfacbf5029585f05e3a56005acef42c59f506b62229e0bc6214acee6e0310ece9b3c9b8142056bde0737a88d0af6c5c17787b70456191ad312e4be8fe8b52fab9277edab27238a93c68d5e8747e8e2d310551722f4367536e89fab646057e5183054188811618f992d85147a6f169654da99fd0ea010b14f8e22c928478764732c869cbb695d5b502a49bbea25bd27e07d92be09b44d84853c3a37506386150103243c35807d9dfb03515ad2cd7b381d7457533473859268bc0794939e3bf945715066da873c428fc286dff5e3aef4920f0de312d38cc82ae6b76c75cc1437d71356daee2233e88ae4c1ab8cb4d952f07ace30890946cbc4c6282d66f41874aa86bb813ed5e64127222f7062a0408e8936dca8eb8805cc4b6f0fc800a7ab395b3b3d774242755676d76615a6d919b91155f625091f48d68b6ce99e479fd1d5bd1356e61c5040b435a827604e08701f42bf0722df74a883e6f5a51bf97b893fe1f732dd08faa908b8f47a2c24fe5cf96fd1f4ff9a7c9bce873d253e100c8da8d764f78a04378f1d4b9b8fb2bdb6737ab004fe2036b47285f653095b3b41cd99811da5083744e849b81a42fb69890dd107a175e5f9efa8c5804b6b4ee6c8c8fee5ca2b38863d95a34e5e4f7910fcedb64d8ef30933c5dff878e47c2149637a7381e6a303bd38910ea639db4f78cbe7c5acbe8434c4eea53a2a6ef3f98e0c436dc85a45e399270d622411f18f60d10179a8b43432867ceea7a41b2bebd1fa608e6bbf8deb3aacac083b7c9cb5499aa2f8a0e9aa31987aae36f1abe4b7601ff640a49925945364754a6b2cbee4867af37439b08a70e82e200619c3b6d34c1620b9d01213fefb245423af422484f3b517130d82825e836da6f7f6e7bc541a0141813a01c3535f418bfd682fb1b4d1773f53bd78865ab031aaaf463794c575867bd5663f969ff27137a20b71be552a8bec917dd8960a1993182a89ac75ac8ffb002759c1d20f2283d13645dfb3e06d5acc3bd272ae9d408829a52cf227a99da8f0aba9c97ec1223e4b40ed2b6b13a9ad101ee2bdfc82ba7a64fabcfc0a907d6cf78986cb7aab9c75245f3af14be5d0207f6df22e1a5c4c78fb392aaf6781843fb8d60b5191ab82c9f2824108e761d1c2949ba310d324b2e9db0ac4c32abf7388423db3f546942e1fc81d62e288b74ab4241c438d55c5799a3adc5eebd45e8ad299c66555c584faa208ca6f9a1f02d78a96532f1ddd1eabc46f6f41e96703f5ddaaafc5e80b183e009f8ca771261924d0ad5dc1da753b15fab43ba0eb2a6f37671f5a256c17b16e577b67858b812c830563ab2af593aa6a1204a132400acaaebf4fea7a2a654b532d224e5132679f9f1f41fecf9a20cc911e6807905ba34a934071342154782b7b69e9e4dad31a846539a5475b071df0b4c768e5b044406b85ac80a95442a573ed04f8a9c3e2900c00f9b784e758dba1cd06f47ff4a570ec5c0e2cbd9f5f15658fde6410b550690647528d3c4bf93dec5c44e5109349e59b12cda0ebbb32aaeafbf198af71179f20787d99602dee522d3b631638394e77b5a9e8168946d9227b348121cba66e0f7fb0653007e823d49a7c9eb953ae21ca4a271ef50c486c2f48a54ced2ad852f1d2bd184d044c9e72e32a98f356313e79a21fcd60103c03d001653868f8c6f71a68f52584939d9e98f8fc835605d94fbf105316a768ed77c0f900688ab19aa6d12e0cdaecd75f513963a4bbde3ee0bfb44fdaa5c06ef92560b0bfc70373655e04b8d6ea16edcea6f69d75efb940079242e7fc2436f48fa12a5942ec325f34d2cdc24bc27e3879b907ae8410bf81bb13341b01cecca683de2d76e524e7e00ce8342cc02f301bbffa13d93fee7dfa34f997cc20557e0601ef9d3bdef636e8f8eeb527a75efc1cae217933862154bace21647fce22c3602346efc58a99589590c88d5890f0f8a39213688ef88d2d72cf0402c54f539ffbf4bec29d75f5f87d45b17039fab3cb018a2e8629ad0e71b51f479a12241e9d1c6b29948c0155e63eec5a3cd19a550c7456e38b858e31237d527149d29118bfa86d41e9f8a51eb9167f3909696440b15ddd5aaae625af9e2e2946a045852b9e1fa18bc0cfaf3942c5cab85b54754950e67f63de2078c5b5926630a347db0585099b8aafa59600e8aeffdfdcec7aed2af3e33b45a1ca20a619da2420a636b49b190d79d6699706ea6e8667bfd51cfe490a915e725f47d80c91972ba36e6715dbf68e766236c5d21b83aecce15b5025753e88d5bd75b2a8fc76d4fc74d717222fe4f6ab02ede19df7b4a9f7e24aca42c97504cbbf844f35eae9705e2cc5014f9f2c5305e88dc54be701eff61d790986b770370e69172479a54ccd6961b3542a40e65288002c5d016404f5cba8716da855a9001eba948082b187f267558870f73bdef541892014539313efa1b6b34c1d1bfaf968b4493cd2918a460109c54535562b4779833a43078803743bf651611a24373f85787b4516ef6ffe4f221aa7001dcf3e4b6493df7265cf86d975df4284580837c961b192b27a0f1f25c36609b57720210082bd27ebebc00f2ffe7a4f422040346ab2e99514bb66f0383df7ac42f50ddc02df899ac5c9b90944278ec01fd7189c3c5cb23da73e0d1413a1f1103360d48624edb633184f93a962645659a2fd0e75030168894601eaeab3e4f078c8011e372e9dfad97ca64b77252f48a436fd60a1332fca08183c77825c0ec4281eaccf6733635ab1dc17696a44a30da6f0ce8c45a3bf6a8e9eba235e374fb330ebb9b97368115ad8f9af95207518cd81e0d2ac17b20119a4b743568acd963863a65fb275f49b954f2e453a26bfa6b4097331c6202856407b4679bd6ac5ec354512265ac28d1f22b7c51944dec41c77ccd03b76879b8e5a2810631e102c5d5971ff69e155b98011bc18a5fa1eca2636e0bf0e070c40ba823a15c0c95ef97eda6c3271bd3306fd7ef416d675c6ac049d465f71fd361b4919ed4b4b63afa7ee2ebf1b61db411fa212847b253a09fc8718607e8b5a35b5db947f78f48fcc5a49b5eaaa08abcf8e6a3a24c1513f3a82a5f21103fa5be532a9774c5dee711ba5be4ba9cde5bfb5fda542c8c42a4035c9ffadb9d209471e826fa460b3c78fd33ce20c706794692668686fbc50e0ab05ba7a2b2193a848024ce4cc5f7ea33a2790cc27f7c047427234628461bfe9a62b289d2212d2bb53b9ab806d35a24ee20a281af15cbf65165c20b649c67d81b03d5b45e36182976e87032c7f4a5203a10c1622b971c15cba41cce09e80cd9e102d79203233f5467d76b306610ab0f2e4aac3b8162ffa1c40b803f059d4c8e46b50c577d714c756c23c5f62480cd08a9735b93667430242dae3fc536f8310ae71cb975253af93987bf2feb9b58e95b0de23be1460a58856705b0528560bf5a3c175f70e5b622cdb0404fa33910527f81bb129de2c0fd35994aff539e2de2a2725a10bbdfd8abd5b995a1d516e5b14126bfee6a4526bfbd889b2d73b31ee9be452791f6fdaeacdf8e719780dec3842f2a8268e9d2dc63d71426a1af7c392b0a0ad03bac72877d31bec2cf5a18c560020c5570e9101603459ee2fa7def922167d7c10f5ba97bf64a645cb0f6ae446c7feb038059690086638c1cbf3e00139aa66cb2c016540a5332805155460397a6a4f452308f6a11f0f90fd6f4db254c2a07de7a53865815063ff565664bca2e0d21f944233ed7ca5b037969e08014732d97104c428b089182c0bf137ad0c6f08f0034bd39bfd0ff133ae333462e8252feb624215dccf2a2f107d368f809cbe386dacc04f039536e7d40f40f446c93943ba53a9dac9b684e30f36ffcf05f5b7bd58bfb273ef4f6b451cbb721697d99a798f3bcbbd8dc7286abbe85f6cd618a11837a3a5e2b83338aaec8654d07067f16565a7ddf2068aa410a939df64595d7fcdedb9a4fd4042693c05357c9b1fa8d301ed0326b277b5eabd90ac46cd88c43425b76d79af9beb5db8ee91b45c4b90bf354d8cf2b484e9d87524b84a65e1438893a0b473bc39043d5d02ee5e750d3a09a922e98cae97074cb03b199434ea5b111492991df98e92dcc0123a16ac7970e7fdd1fb7be4637484bd0341da7a939622ab6c0f7c1c150e8085fbfc2c47c287aafe81237e613306f92e9e8c4fb28b31763682f30f284b9647f7015a9ed21d3c8b4f08130a4ffa15bfc51b3beef5337f0f4f2b09dc59de4e32458f85d181766ad867492f06070bde8cc60b4c372984ed6479ed008ed37a6887e815042709dadb196c5f4cac26bfbb7147ad2044a76efd324f778c07359b8cbac4db9b5d03e0080591a5143181594525fef117332650bda2b3c12714bf7fa56e2899cb3d6b9226c7a0045141a3d346bc8437d30c04531b7e2aeaf3d2fe27fad268379a944aa3c40dda6b7e58d4c612f1fd6d4442c9aaca907a2bbbdb26dcc9e4fcc2768e01cc03178740818b8af7d6095803d6a287e045e864114d24dd6e4ad7675965e96e7ae81b89e993c7d9ebbb7ff52ad2ddf7bf6c0c462f0a881f523dbd1a46838725520955825b91f7ac7f1d1cba4a0e5bd0b3077e90fcf662dc7d12a36de80c855ecb6e219339a0b9b39d14663dc1d7abdbc1d8e74b618ab939c96a0af6876fe7fcf427bec69084bd90a944dcc63ee18556d61808a531276bab1cfeb4c949d896dbc8fadea848105b2fe4c4e176c51f8ecf26e13cfaa6efe934a5eb21421a2f3e78d64a3001372a1044bc2805d5308c8f4c4d1feaa3fbf31858b4957b5ee6884afbad58e4f8d989f6c387c34f56209cc692bd05d01eaf107b21a3fb5cbd5673ec5f9751d3057cd2c6d8890eebae97755ade174e62ba9aa5d7bb1fa33ca68f86cf05fbd3030cc1a88d5d00c44b0078a97d2b156ebb24185607a5e99b7a683b738506ee50067f54485988eb6ab176bae265fc544e51cdf8af2fa4a1ad09e6a3cfe95d71a6c69dd5708c9bf9a33bcd1494a160609aa68821711d2891aa05f7af20fd99e39763cb52448b28e20e6f59412b6316c7865f36801461894e50151841dcf3dcfc7336cbe9412ccb2c3d3743b92694a2a3f9e241374acb5f717002759f397eba3663769a8e3071be302ba2de917273da97ccceeb8e949ecf8daa967ca049170b3001b56cdc2a5c638f6a922136fffc366c62549919b691679f711cfae3feb6ff925a627559deb5b727c4e75a04a1fcde8526dbade82018fa21d69c1cd9c49f875271be647214b3984301cca1966d6c73e0440fb056ca75bcef0b2a268a4054e5679edf633b7fca509afa9ef9c95648306adde1aaeac2168f05e38028df4a0fd268070cc84daa62e351bad03bdd58a3feefc24b64655fe766fd4db76bf08cae84b75fed14be0abd60699502bc7a474cc8ba78c488fb44c9648289b0c604aa042d4a35da205bb748372979cb8151b4735b1bedf9021dd360cfc60fe157a383a83de24c3a00f1e89eb9d793d879f74edaa242a274478d2534b07a47d72c541b0cdd015fd4302724cf3d6030a20281309692998f9dcd8f0bd940db217ee8815420b47825babb6b4f5b6dd433683a1dc33b6ee6fd5794c9c7d680907cb9a3e5c00b4d4fb5b7c8042816b6df12ad1a4a1eb8c7f0b9b7673496cb766a89e2df435d8598c1cb66284c4619381eada128f2cb6717c9490fe25db3fdaeebd7291e25bab9ce62ed7a49291c8c830ff34cd4ab7d8efb2a232f12dbcee9d18682ba09e714bd407a860800af2de63924afe1cbed521f4119fa4dba7a45fb8d0dfa126b0f8d6c0df722d853081785c0942d5176533090ef4ecf1ad07d996b8a1585f8b6f7deaf2802a0a34b30a003c505581bcd011079537d5a17c1176e67b28a3859d75bc4c7df1f3263d08b57e14e743850c068797cc3151c16f0c9edf71ba3b7028242b36c944f3fb2107d2dca21dd2d32a7f7cddfa0665104c9a88744f81738e720fe41c48aa6aa65570e59a3e4fda8859c105cedd0f4d562eca9be45ee2778e987e476fd29b90796d19d072e95d60fb2149ec6c3e1feb10e4de9643a461f11c7d245cc5d8c43f71d2283491835f8d1047f6b4c404de9d0166ae9e57ba5fde471937d0877949f26893c86d0f56fe6cab893b62ba304c943bd58960b405fb131af9da940383462c34bc9297bd1312527e29d69571630dd867983ddaa190d30304a9368bb6ddbdc96ba9ca22f40466416bb37cdb93a3598d5fa1be60a281b10a024677bd667be918b4b75d55b2cf09279e30d9e693bc4489dc563236b890d18bbb03f8c91ce0f60ee482ed9f874d4610184a5ff7a38ffedc1c9873b480a00460827340996a2f0ecf50e88a94002441f5a2ac7141781eff55336a58715be03aea6293fa6e71b89cf8c26a154b5dd02a2e4897ffb22249ed66f9d73a349a2e35b1479c7b323c9a9484b844cf593e4ac385b0aace375dc83d81af796d93da67fd892ff0766cd7328427d06c6968f7dcf29b80d503fd5b296f9465e41e0bd43a77fda53dd019b008d50018b668ecc90ae27bb92c5d8a0f85f14b1386cbbad6db57ca9ed1595ab48f021ee23cda110c6b9a1bfc77ea6de1004c480910b4dbc4465221ed9cc128bfabce32d4ae1c549c572be02d1898913e03bc3c7980dcf652a30815faf642ff867ebb1b58eedce8a46a3f7bf9012f434987a43ba499380d3182ca3ed03c37639284c04e2aa83a1957e3d39f81709018d689b086d665e3f122f1a1efdd9f2bc76f173d05279ab825d98c8b88afc3f6cbed599402823482c2543c95aa7c11f174c2d5fc877de5f3e3f20edd8dc1f10e54768cb6a3bca7ac0398207bab5c0a5ba32a35e01c1274d5a69e6f41ea070c5283a743d3d713eb459ba1ecf54f97b60af1898158f96a16408005b8da4892ef0e6500d232ae502fd3c781fd978b1fa20fd58b4c244619d935c972a826f66f9ea63b3745afc3a6dbcd70514583999daeda9047c66e280d68c3a02dc2e1e20b35516f207054942fabcdfc817406a98fb01d1622ab9e030c44ce3926eea6116d17a2df613e4c62a1435487b0391e5a02440b244dd7dc409109bb51dab6796971ae0ec6c833816f7f0d70ac36c091a5119253061a30311e7b71ceacae0d82bedd8488da9564118c9f2ab012c07a10dd8e6152e808b774f56875b020a6858aa70f88484cc510863e40b35a6557ba6f5ae646b3b80903700dd6df83516df26934e0f0403d70e063d3bfcc08958ad7d783347a564b1d15780c055cb20747edb31d089c4cf76411068ae804bb15b1ece71a686fcbab4adc03bc63d558ffc923fa4c432fb3b4c74402605a05a8eca91e867597c92e25db30ae3dfbc9406fa663141da7aa0cf93dbd6e2875278f3d815ee35e5a3c027e12d8af63a09aede60ce7c7b2d51cf6657965b01d3bf179f38222a8020d645bc4cafc9cfae0468ad6bba5116805bf2b93a6bd12800bd678f37aa748e3fb6e854d8a214089c22fb8fbd55cd9f5726c5229213651653bf0ad6c62990d46371d40ef0199d32cbc4910719704fe883f298eb4ba5d5ccf148c6a90db6db15cfbb63010743cbdaf658c951f23abeff127f872928f2fe91eb8674d8fbd11302395d0736858d883c3aa658c886793b78288f26e255f81bb6fbf18ce2ed908af2bd71e580b4bdccf1445860f626eb1cd84698d8af42d40ef23a2b0771cacccce3f9719eb513bd70cbf4cb399f089f4a00281a45ec722b5e2232085b6e8f786134992193060c91b409cc00825b9839890b4580cac1dba5b3126f7df33ca77dbb38e646cfac2f353c65bf3fac4e5a7e415fdc563e39d144f8f23ee454e098102887c45771c05fb5c4205468dc3af8ce0450037955b2a74f0484d97030e8261824b8f10629898e0f594d2b0fb491467bf1a350c17cc548163eb9d8bd664629bfec73a897bd77110ce735bc507125b1dcf1822fe864a4bfe58a81eae543a47bc33df30f40a1bf536819cebda26fd035543434c766317c25243bf0b0414e257400ec8ff7526821d437e5086aa5feca42eab0ae00d5767012a4ebfc14807ec8c73990c9e100279d3bd1ff110a92859c09c8ad79389c485734bc33e73a60c4b56c30112829576c14d6e7fa9d940f389be9587ee9f26d40aaec693d0fcd12dd8b17cfe98eaf29ef4c10e3c492b0a7b426f17d3a6ee5f2a5a273ca1355d0718853d6eb127c41bf1e2a5ffc19bcbe2cd277ca92c12323be9148927d1363b7fbb13967f6fdc87347b23c5a0bb7f05bf55e86b306479aa3c57f1fd76026a62c08665f7941177d76c1e3a7d52ac981b0cb2175a25c33eee684e841173dc9992fd1249fb3b112a54df9ace4588baf4c54ef0e262850d09e14828aeef005d4e12add34b81954ac277da8be2124172835048799496f7463dfe69110fd901979aea6794f7ce9154d58177137c2e696ee77091a9c84e3a0a6864bcc34ed47c9d10490d12b14f1cd86137ea6eff81ee806a948787a8221fd0b1d0b4cdad27d2ebcd9b46acd3b947f3317e007439511487427a0c46c19aedd7fccd985c78203009304eea257f6cff0765c989f8537e895ac928cdfe05db6e1d80df6fe844e4090c8cc2c2efa981028543d6b84ac7ce0b84546ba69bf1f884f7c001442b42acb199b758a59819ab1c16089b44959faa9e273d9807d86b1a5765e4b048f6d42c6c993841679e11d43116ad59b15118ba16386f816d3e37fb1c48f591fea8e9a874a8ae4ef4c33696add78f355b56ab71b59831419680b25999decb9f27649eb5f776c9daca93cd81296e6daffc2daadbd49a0f12ebf6058c8e3f0d3223c15ab57703826deeff9fe6762037bd6aa9c91c5bcc939b6a55e66dec94577634d69a32d28c9dbafaf5c9cfdb126536a8fb33947a8a44ed10b799219fb5c05f4ba4ff0faae92d11da665522463bc3adddc82d58139f17afcd984b12ddc1ae83788ed484f762d48cb1f686cce7a9ceca86bc07dae666f80c65df96473dbc929bcd6ca92177a5ded8577d4057366055c652ddf4e2f831f34485ad2c9fea2c0a7d2988be3615bf2f6d686afae0757ff94cbd42e79a5132bfb4193d3b72531f88d8ef2dc40c4eed44b00976a0305f63307763fc81d69061951e1e82da0c50afeefd934c5d05e93dedf8e19f1dff7a32db77fb4a71629d51994c23afd42a3a8664cd6e7e7d71103b2069c0fbf2ebbe5545c3b60c7bfe4a21c5b768b2e402b4156870cbb1d66038ed591394c84294e3a761449156cb4cc919e4b94c79bd28ae1b281971d5b13306539e714ba0871adac573cfec5a119fbe50d7da638ebe0467554af9d433552a7db257c1e54d4259869eb157c13c0b6f87a66f0960c62fb9e083dcc36755850e355829938c2d9bf49c111fc1fb92d0ee7b4ba9f6ac5cb726fb3411d416749738ee7c5e39fbbc9066c9ab44db6756cd19e0b1ea5676aabfae37a30a20c8ea9915683aea6d2c533af92ee44647cc0b9295e4e64eb6a14aaada27d5d224aa82dd05d9bd78fc906076bde4c95a9e1b2cad2188d7f53ffe23b4f0d2380256d022c4bf6646d06cdac1f34ea25486b756cac7c8f4148999d25dd2ac4331ce09da9c03b2a78a9a04d2844dc2495ad5b6bc3a6bb0ca00ed4de2903dd69016caa18f7fff219fdc6cca26141958c6ecc669fd3654ebac37e269e09bbc17a396d2bc37566c534600316968c7a79ea0763c1ca9799fefcd4881773c864bd19b094ddfc1edd4903d545846ac9d54c2dc2d45de4b1aea92b1f85f73a0350acf909b2364ee38630b276dee59109b526a6cec068af7ad3b82f2d582f883aa69ca593c18ac0cab8a60c1a174d57ad5274a5e8138e2144b8c621647ece28847b121caf82aad28eba8e4a3e446d0e6b3296a1e63ee766d789ee1e17df6ddc8bc9e356a2bbf568c3be1173ee2d2c56ad9101496d123e1a71c37856995e54f67eae32569e27ee31ac392a069766c4bcb322dbb5b41938134d9356dded9b6e28533747857eaf1cb726419f263ffb25603996992f93c643985f5c7f51d7140f2dae4f4ed88a1c58b8a6ac2833a8610a4a124049d8c5392cbc1358d98b087208dc6780d11accfccf7d928f146dc35c3d06c9061642b4edb157f9c83d54520a217057a513f0ae64c1d2889483c0fb1face15b4d39dc006deb28111372e4762ac5682acab92e904b1abc4ed1833d61511a3c61f496ae1262da8c5079773d25f8fd981e0443cddf65ca942e131ca82b8d1533706a26e616c789cc9864a34b88a934d347da2a759c4ad4c49cef44b5a66421861f67407d4c359a3043d12cd1ab8773b7762d68b231d4ed940f2935dabb112afe6ecb60df715895af22339c1b8fed05f1ab60435ca6f4cf73d44c8c84a10d9eed44842e866d8dea1e1178b224d83acf78f4d1b1b06a5960c519c5bb38392ec0b2a7d4e574d9f9ac1ecfacec30801ff49050820943bf1f6938fb38fd4a01182f9b59dfd2f0aa5f67c49d79e82f8911706437e915a599049315d382c6fd884d5f5f5040d77496594a0e05d087cfc5b36bf69cab09bd6d8e2e1eb6a7625ce48bd40058ed5d6544b56b52baa3646030cc99ff12a93479f1269c5763eff93c7071e8e4fad4896695644eac16b0e034b7a5afc17726ad13e949aa889500c7e82d03cab72ec2a9101abb14d205e6cb7dfaf21cc08ee2c01121539e7fcef1524a468af0a8bc3a1fdcf695ade5e57d8ddbf6c54204a1e8e78da3f2fce2c6d7ed40dbc3ebc67185df2a836b18d8ad5b9d454603eba9bc77915da207bcdb9ada4a32a04dcac4100c90db17192087d6d788cff831d4896ce565b5612ab1b6ae110053ae2c0fcade86ace63a31b12a9b7b2c87584a544838f3109f720dc9ca28bdfb478da8faf122a9eb9ac9ba67cba6fcea8b2c38df91f12c8b9c1dc1051eced7d3d4bbaf84fb5073edda39e94c6a95cf9349239034902ae0dd6574c781126a5fcf08449a6020f74aff448e185c19e0a1564bb48e256240eacba5c597d585fd1fbd969b2c9581cbdd23dfc9632ec046b388f7533f4a68c75a40f049becffb923dba34d2dd358fee0ab157ebd2e6e69f5e2e5fc60f77cccbd44b1cf6b02a00125784a5d270d66f5180d45deff3bcdedffbc36c00b2a580f667737942f5728e3897e2d137ce75a9768a106a2e39078ad950f00ad2fd64d60e7d979e4ae0d21fc7df13d0854651519d100b4294f0dda9b3f009cf4f9bd7d5719cfbf60b8abeeb644cf339177393f56db52eb75566b0e27eba4ac8411850c121d711e0843a3435ea102c277e21b2563237b7dbe8ff9042e091ac2827798df8fa8cb3eb5299a80435e3f4f86c6521f9d3f0bc135e989902c104572a58da9e6efdda2dafefbcdfd883a6ee586b7225f7a4f041b5a2baa7d5a0660ecf5f8341995f6705c4fe808bbe500ba5eda6f4c547f94bcb73b133b2627253f13c7440d24b8b807e47ec2e26c0514b89c49804c70a6470923ffa60c12ab8db2a497c3da15dbdc8ac780f4d05de480d6e426f289e66d13ea4e47710cdaeeecd72a5d95e6a9271b147fe10d5e35574d2781dfdc173eecf71d0fa808b0dc3eb7ea67812966e92794ba29907cadc1c38b6af2437f94dafccbce661e1c7cefc57fcf8d33ee1f0ad2e6a913d3f97e6bc5efe986638f5c320953a8856c6b91d348168a7c51bcf5ff1ca3b12332b15a9d2aff7f08d47e1b9995132c5cc01ace9bd286ab3ccb545a00143a955830d51796cc0c70dd9758b3941e474f2013e950485d4d25cf54c63ebc1c835fe2b32bee0c87332d05c4e48ef862c8d011472735e87a72d1751948a60233c8a2fea0cde6384b04d1cb6e2f29cc77071a66c9cff1320bc95188ade6ea4fc198d2e35da9793f07f13271898bd16b0eb266f4ac45d215674be97a6426b3529d831d04a95935d2a22eaa9b02a8240f87c30116355fd7cd0596b30bdca502684e13e81d77b4f1a81fce9a867a849ffe3d0fee2d7b58562225e1387da09da7d7559fa994bc68843518284dc8b87160e6daf0b5d820d1009b17e3c419784a2175585ef14c6bf5d029fe7f8df6647d6472b02374fe4c78db8cb5db9f709ea91636156ab0c9c9feb94ed04836042263b6b11d60f903a5fbcc89f64bcf8c35c68144d9624e78401b24e53306a6ef2cdea84ab86be7c01c5c8cb5b424548e2a1d22cc81c0ff974b5455ace0acbc6ad6920c36a77bc6ff0fef405d540bfd23409288230ad082901a61e1e25f5d2aa1ae4b3bd45dd5cbf37308af996320c32c512e80a1e340317606d98afd0b052d456b39d8fe539756aebf52278936887ff9121c087ac073c8458f7513e9a3015a8e2649cc5534938fb2306fb5e5a2044dbc679ae6d9aed0e077551191d6d3f899b2a7fa7f4c6936e772afa5bb59b6708c5eced84f483f270e7ab3e05df3bf95af5addbcb61fda0dec0d5eab3a5b502bc30c8090239f55d7f83961af1da1a1c42dc40d055a3a8d8419d9a67b512b6dbf5dca7eefc00e7b8097a69d55e04f873aa41e095d32b7e2988933f6ae85f8b1262c84bc10a4fbdd94a4428684e00df2cc1cf5bc02c963dad099d5a4b3625ba119fd79bf153965b04e9564ce7d41e43a42fb4b030938a2f53b3abe903e8eb3bfdb259749d96e64eb26da8d68e306eaf149be90c1e2de17ddc351d5b24babf2578b7f6ae8bfffc2499b70448cff8a7c4d06c4c3ae9466102a66158873beb26437dff71926ad5e63641d46c028dc84f9e053644e3d1ded2784268e954e9f2f00971beb368ad6d88cfc151b16f2bcb39e6a750afa3d83c5c9f07d960d62150c37c5f7d02298d5c3a5a274028b834cdea08021df4524a833da45b83977f11c874cbbd842078be3f641026c53a9f5caa846c83f22175d4666a2806461c2e79869cc4797b4cb73aa195432ee59b4aa4cfcc5da9bb85b9029ba571cdd988025f3b7208237b6e38bbb2119a3817e79063f5601bfa7f6f42ad83f7499c1458845842c4efaf719ffc2c5dfd41f445f71207c48ed883e396b35f734241bc897e20b70702c7cc5417678acdfa07141ee5d2898cedf1a56fbf0571c1cb347e41701547cb143106c540347005f717a9c8f138049c5f9afb20093ffedebde50a050b478911f3ff98a63753e9c5b522eb2da5cc5c6143c287da51274305793dd1fce652a14b772bc9891393903c4ccacac6d019ff72b23dcaf2d8e3dcfc208dff48be8597a1668d52f1e34044479f2eef46f463861d166e6e0a3de907fe03a78f703dfd4ddfc02f6f713b87a8d388af548c014dd49475a81042efc6a83510bd19e68b8348786c20b20bf4977ab4857be3645a253107822dd7ea86d230939f486457189e893ea289a03d749f7ae06a722a305b801d51d7bd305d38d69124c1509a91a34b390f1cbc5f1984f06653e0a0d69ad0618a723bdc4fc11c47515f8d070969b637ed1f7e458cceb710e3e723ddba28ecb4b7f70d13e6f34737ef8bc6906069bdf49a54f272f174b1ea057a8093df194f89b1c89cf3ab5a145834822a5f370bfa323beebebec181fb7b1947108e87d02a188628c51a57a1f4535e7b7bcb5ad85255a2fae4a1a8d6861e2a437d56ff0b08122a47cadc0213c2609d03db632e3c800e5366ff147bc523a6a347f9379641d8d136e1c7df1869c8654a280633ba916321b9ca81b7909c1758f2df5c56c63f0ef870fca98c0e43e36ed1c9aa90ec595d15ea98a92a5a94e548ee2a2e5dcd42d488672e09e789ca29c153626056b640c9478c1d10daa156cddcb06d95c8bf1a03ea5625801c85f344e45d867f877e1bfa6cf4092c8fa89498e7d9a86b0ff045affd70e9e84cbe8fd9d09175f02376424165df0d03b1c4ce74024a403cba4ef3b5a11fc33bc45e5ca77382524c469facfd4748b6aac620e795386df3b3b6e6f6f6ddb436c50f364f87ba3e7cc2b5161e1683c132cd3e84a6228625ce76bf0bc1bedb7b7f645ec3cdd3765aecfb97c1ed121188e03d5464ec8de9a078687e19181881b5d34cb1756dfa2ab092efb48529aee508b5137797c3e8a5f280dad5cc860f8ce3d4c95aed178458989d453eadea5544f772c03344dd70e68968ba3024d994d73b0e3a10ef3132769341d1fa06235eafa11af598cf9b674e772e1d51953fc2ace44fc830a6b1bf009028cea78f4ca20a20106e24308e16c5b8269514431f8cc7e32617a4431095fbe2ada8ba45de92a6aabdbfe9b832773a1161431e798991dcac56d3f912ad20e518b95a31826332d3bb53faf9b033217e9ddb8fe54d9315a58bebe71cf4f6c05cc53fba1ec7d9870e8dd921be611fc5fa8a6dda915c181ef72a1f5bda719e83582b6625c7186467d32006ee62da0aec82860cdbc42daa8a7c98d2f362cf3852e7e5ed4247b73f574ad83cb05c863cdf3373acf1fdc9ef43eb822f04e5a05d8a1798e7af8397be99176f8cc48e7b4e0b403ade2ff4846a4a10e392737877e32975cf9f2984f1b52eddb47899ac822efde1e87ead4f17a82ccd6cb4a93e997d6fdd196cdd52f2fba44b156fbdd194bfd1baa477d2db1f7e035f9d2e76a038d4709e194072ea3edd8823be3aa1f4a9f4041707c11cdf2b8ac450f2bfab4fd20218450c5e5fa4369a1da5e05e6aaa22277f186ebc169488e21c37408e71167aa69d18c6460463759705aab9966608460f060295874567f65cabc73878e0f3ee392a95024190db680c092772b6c07b354fc5f694446ec1fa469222430958cd08b04aa2a250c61beafd14435612af8701a11179156db8b48b3443ea01997cf9419f0c4c182d7bcdcfde17deaf3619a1cd3572681c8f43f83d0556f26c6311b660b3cb8427fa03f57db3dcb4cb364fe446ec0c8df3b3bf896cc0b859809931bd29eb61a92e2e39b886ca7d332999d672c427028f133555b712d5f778c22d7a94de06903be491774bd6ebbda428f02d1e9f1614bdeac8cb85fe94609a5ee9eb87cdff82d485b5ecc8ad4d89b15a123c49be7000d71c58b713a31c3d31f8bf869260ac1c122627545d2d891b322ec3128f92a322c5ac4e06b9600b6063e5e52debe5f31a79246c0166655d4463402514bf563e5767ef20251f1338e7b159845207e8f23eaccc5d4e6800df6c9d3fa01a1933956b3e9748e0de221e87a98fb95cc31a266cf4c7b8ca245febacca6f77d2fc558468a9ab18fa6490f4c92ba2c5d638128bb857a6443a60eddac99c7bd4510063a36584f815f4092f7a80f2308c22c9a4b446e9ff5739128e6398fb44eec9d5adc077f59778f901a61f7a2d165352a3e2071f5986e60e113fd5f155a0fafcd70d7af174aa4666f9bab9015b503efb4ace9241be7ac983f8d914ac46490f1341e6c5b8d598b263430ac80b479dae5cf6132b8e29f684f50c8d50464144c12c4c3f428e36be978f2729bb6b8979c3abd04d0d34b8dd687c83cf062596d1485e977142b0add90173d8a773be09b0ff43a452eca1bbcd847edd4878fd688806c7f371a0434a82ea570e5a36de7f2f6cdfff0813db8d760bd632517e7df575f82cad5b76cf95d3a881e3757bef73a56dcfaf9bdf224de13ef313ddfcb600349ddd45bd9d9b3891b76630830a9b98fc24493904d0bf2f9b73c7bc36e1f0aef7d47439ff3420bb5b5efe9187e4177e3416984387acfddb0e94689600a6cbefa32dba91af2f521f2a362cb60c4ae5651734623c8abe5d97e79edea2aa5ece53fae6feb7888054cc74128bd7787a69a1a444182b2a29234a5b479ca852b7f4b3be0db7865235e70273abbc1fea9971c4ca8fbcd95bc21c06aafc25065516256dfc78ff9964109ac03aa892a02eb13e0fa99fd8962d9da767a50a837f5c49092d623479dc44b3312529ed82e973b2de0e1bf24bfd0048aff17a29da4b4efe017f5cdc4cd1a7e9fa9581307fcf12b89b052842de49bc7ef1fd20b54890ed188f9468bd19359920469b35f6a467b0a8828ff62a2debc12d53af666c1d820e02c1a83c864f4d325284b3d85507b6859193de9094e2cad587c89b8c3d9347dd8f8039cb5684caec0ee685b48df3bd712f2f931b0c7ddb48de5305196c593bb84c854384a17a0cb5aa67c8fbb2f9ac12936c2acf4656b781fa7c11ae5949905e4d57a26b354ee097782b91f084aa543a23a9893ecd88b9fa03a34d6e6bfc58d591b10fd27b3f80d7642238b61990d114f6eb1fed543742ade30ac435ca635f5900eedc72c4cba04c544f099108576d7f0594256e82983291e5d5cf0d89a3668de57f900dd30269fda11cc628c3c0d4a17e91c0090bb99957845f8211c396417b65546daf7f238527f9f9144d160021750e46d7adb9a4e11a058da43c4f24977cdd4e5d32a11712a4fee1a1d5b4a5470ea4d7f610a49445298871b0f458fd45eb65f3b4b36e65f335b47a8bacd5d689b07c4a0131faf7e75a058fc564de74b180faecd2d0d03182209cb97690e21284d8926dbb86609542ca0601aabdd73d476e8c44380bf51e8c0fa49ef00bfb5a424e79039d6507886666345b087c662fc8d4c1e60faed139568adc2e5d3e84dc4915d4e9214e867747913fd53a14c4d68798a7a7669dba7875173f67843459c98d18a078804a9a64d8fe6689c7a0c03cf84cd269f742a15166181a2311098b32a1962fd06aeba4cd19981a1252050e706b12d91ac0343d931dff673929dfb0fcc155df4564dd64340a80d014f880b98f8fb2f0942eb42bd8d8da8037b88b985ea38e3bd96ca9f5b0806ec5738c05c3b552859d800020cbbe6b902aa606ec088839b117f1045d3bff60b41a2fc8c4263530311581301666617bbca44c2a3077d4a9e6d4ebae66db5c680baf76d12a9fbb8a0b4c0c27294f11ae6ee56c58576f55ce039e10a9021f25c9f9b072165b6b3286295603c2774967ea6d6dc0b797bd67e21440354f92fc975364b5a3c27d44a04f6dad03ea3f0f68b267592aaeb2facf1fe4f5575f82728cf04016f17d4ab732924d0498c94df730434e6b1260ab33ed8870910ee3f61e3e8812f48f47ee4eba1772fdbc1bf94970d216044da8e0f9eaefeb66928cc3356392fd2ec8a187a22a8cd2f0d85ca5216f9ee245b710e7000f126483cdf50ee294b86af8d144ef775f5825a624a25acffc37769d33b4ffba8ea80c429613a642bbbe3162e2930271065939cba9a01e3761548342440bd6858bdb0e06a814b925bbd78fc9a586a195f8ee0224f1664935800610aa1fc74379c0bcdf04a2ac68b2932c5c4e9d0d44d5d3654335ec6f43fca1a0d0f550fcbda9cca4fc8c84ad1c0ff8e175820598e1aea7684ec7d158fb023dca49b98db8548fb358d55dcde4642838555aa4b274012740dbd9caddee1c451e840e74f179e11cf4e411f3037c2679fa277b3743c1e348da1a8af4aa9b4f5caf4171c300577f7618a67568382e2e55d49afc09cdad0bafb9e727d7f12e68827a6f6e0bb65477835b07798f7bb12a78220156080829b7345b42aba22c5f3932e3c97cd50fbc471219de4a6197311779e41a7faafa7b02035ba6d2c18a20268bbbc77505df4f9937f97209909f52eb91cb0e39d0f9bcc35899d9c50ff54f59456bfc051ad06c63f112507b9d121bd98b4111d2854ac56786eec2875d58241f3e739ce2b8ec4ca645ad934aae7b0c528198636192f1730f5a2f1c708c21114c37b4cd4bca0a90159e46e435b986564ea6d0ca53a0e7cf209fd280f10694a4129bd54c51e35ef298e923e82e800a3af2eb36ace39cfff6d675614d9a45c893b90389294e735777424c070a4f2d6d2fc7f454ebe3a221976284ed3e956c9ef9b5133202c7bb9d0a04a53da9b753addaeada7c9b2b8b227a8767fce96f0e985a19c9f3a44e6031c46df16cc1ee0e96f8787a171b8d01c55f5b23e97526dc29dd2b52fc6f158c9d734c7a94f9f3d8cf5712297a0c5cf006b287e3bd90db881550053dd997659ea759d6af0f1e393e93e2108117820cc71f7d7b4663370a0e291ef09359ee9bfb1779ee295294462cc2db2e5fc71519f70752f39c72923388c36eff4d6556a08a292940860b0c2d63ed52f9ff4abe73d005c2f76e60d8a1575b162988ac4157cbae8404f6767b647548bf0bbc34bb91d24aaf62241c5ef755da76f914f42db09842400c48dd16c9dde0963dd0071af59ccf21e7b13438bdf519260d992fd192fc18aa063b76ab76bf3a0995e233fa3f0a6004a02e8799ab69b2649f4c63861314f7e4f69b92dd14cde91b6e2229e4234216c30fa133d0cddb8900b09bc1aed0598869a4df05568ff658edc912865cc9479f2cdee5ab16968f5a7794be7b7a6346ae7bfd45a32cf8251db24cb50061238197a347c23dfc132986d0e1fa517e6aebb55675478f689ff107b95273bee022aca076bf2f61bab501f91bbf123ba973dc9a619de2338906980b95d8cda9c26eea257c66bbc57fe15725ea872d08a9fbc51e53d1c4507f3f433d62af16ccd9d0ef90bb4dd4a0ae480ecb6117c160555b2f5ee0b93c9cfa57bce787893ebd3d0edd95c590a6ef2820454fd832557928f5f9e6b19ed320be51369cca84b3add1179eeeb30c45d12f0b31f603f0a1bd2f8d8f1c43a078cc51065143d6a0c8e240b195f7b8557f0c0227db403cf120f7615cf1e66571268c7fa02493aec6e7f1169d08e712ab66cba530d1375b487240d33d73471bb63d60b49cae6aeb60398be20799b1d306131f3494f83f4f79de788554026102d704378737e10bac7d7b34677773a40ea4cd6f6952939c5a678b57f64a4ec601e68390fff3aabf18aa8fcb714a0fdebe39c52e992a75b760b7be3d5e7e4d416a0fb1ae990edb79e1ae861e9d43671c89bec1b3a2e39c3ccd11660042c9353ebf9bf96a3d13a1677feb7d987bf49bd30c187ffc7a9a62e551300d1f14d16d7f623411cf07d5de5b982631d30f3d1e73a93debb7a5ab538e216bf586211537ce28a5d2c62170b05c6b8f14325ac52b18fdef06988c3a29bf30a6ad1cf532b4e8f80ed657bb067ba44440ca83479b963d475819a6889747d8eb4d79e08226cc365dcb769854695f8d081ab2f6b4b442c94d019193db09d8f2b8c5d617b9d196d1774b17fbbd2d265c54ef6f0cf17cc2c344132cec093200dfd62289c508053f1e41a90f16567ee34ccb67fda726668323a3ac3e22343e23adcf52dece1b97b4b94a4b311573e41da76b18dc83c753ec188d0b744aaf3545d7a5304cc2f463e5911bbd1240c4ff96cb8b2bbf0e2b25f918e705775e6f11a108087852845cfd11541f78eb1f998afbe2a39df2d7bce7fa4c2761bca72a696f559428a07e6c7eccc878d4c09fcd2dc3771fe43610aa4f076aa9890b8c8a9678f6fdd0f3bf01a9f5f6888dda0196101643078f0b345e0194722ad43238602ab13a18408347c274954dc1181d1767181d398ad79f2238eca2d0c28c5a6d00cee45ead3971c8ed4617be608cfe9532d708fa16faa9765af1cf9bfced6b851989e580491b48b44038eddf03cefff148361cff3eb70f0d5cce778e70415902b2ddc6373c53aa9431ba572664b1cdaf4bc6afe45284d1f090560e9045b88a35c70b23b5df19884fff2fedf4cb8bfd98d167f79d6a4630064915aee877864335c9f1446681cb79853f64fa36049bb1a142c11e02111372427144eb31c466163b915c6dea16fdbff96c491ff817df75f8cd3da9f1c7c08d033dc79f05263d68ad8c21e8a7065babf79dc14413c7e7cc93bb8c9dcf676a8d6b249dafd3ed6a25a0a479bc5cd17eb267b9a8b70976c2de1d48510362e87a9113a6e69041f20148be88b2ca75714d161bec0fae0267faecac52811e135b4c92265cec508d51f1e78a8b5704d5c8ef7b251f4d5161eef1741cbb0a2cf59450c6d2c419bc74034c399cb3bf526cb29c42422986f1d00bafdcaba71797b220b93d0c6def08377f9cb62f15efc224bb3bde0fd60144b87e26167b1e769e9c7175846bddf9f8fc67680512cf2a187b9165d2d72d7c5a0252186d39819ec87b88e02b752e7c6a0cdae3bc07a33a545d882e873a89222225a9d3c425cc8e9f1b86ef6bd90f2619d1e38e7abebdd0b18b49497a26857705b90de086ac062c42aa7a134ebc41d5793009aef07d6590746668f1152742a9101bac83102d624c71ec843fe0fada2b076ebcd78b78dea4cf289e5c89a4748b4008d406d5b259b44e66b14652d8daf401b2f47015308bd347652b5fbdff111b45300683a1f60d5d1d61d82f11fdf46986129c6b80c2477022dad0b70773915d0ffc1fbc628936a38cb54377ec4bc2d204cb5da55d2ca20783d1594993ed8567c106f27866366aa3d53acb9fbdbeeb1cbfe10643b88051d9a784b4ee4c1d72d33c481a37be0aaf993d785e3d8e282eb867649cc8f0b17f36e6727abc6c423e08c18a4517c3378647380402bed37ae7d0a563957c084456ab4bb253fc0ab6f9523cdaf9d994ad750fbe4e45bb64464ca3ffc38aef1958c68f93f22c4a1c63040ab9cc21172a153a1e70eed992f28309e8c958b58f6149149906671f82b99a1b511ce72c9bf7d7b1a2f88c20d33396e267fe2ae52fd21465202ad6de12584bb4b1325abcbda2a20a65cd883d56185e2bafb16b17ee1c14d12b17c9e8b44975c3603d1a23942c82c8b67ba6a8e2bb928a89e2c9c943dbbd0a79d994918c7e816f9d7f5873629d2cf69da0c6d42778db20fb4d67ebf4a923c5c8ade4ead5cd750d6dbb77b91e49354c180b51764dcea5ecd1f36c508ce93403ec033dbb22959737b415012b99be96b6410b399db545a305bdad27dca42fdd7447d0fb6d356b8910857bf4fb75a0356f33aff5749711f27bc75536f36ace41d86852fb20200ee307ce885ad6e2efe0516d83a16f12fdcf9a285406c2681175b2e3ba7692b9e8500774899c81b33d05856484e8bf74d016268d32fd01190be8e89fa6db5b8dc2630083bc3d13469bd61328bb59b5bb9ba907ae30b08f5289d35b2c13ded812fed1663df6b3106a231a806213d492f1df6734aca7174ea3305c6aca675f7a284b4cfe90dabdae89a81dcf7444f2c4066d68538fcad7aa90f53b341ddf087676b17b34e2a7eedfb572b9b8bc75ed7814be3e0d8f910d8ec03940aaecb332b0cb0cee3fbb64073196d8a4461a39b807eea106c8a369c1325474599a4c0d2a396711ead6977a56fc67d8b1c7f9723ee5f2cd1dfe520ae3de6600713631c8018bab585b12120700ad1a4d1b181b8bb7ee161ad021e67c6ac784a90efef79177e4ae4f015a06d898a084304799f0c977c120638fd0d3d5b5ef63f1240ab0d65ffb6de53e156b781d5fdca3792915631949dd866f4a6318264eb42a15c4c9d7622aa09c3034738895d7522b93a9ce4a329dc892c2a1377ddc089ad2c39f24783a86dc4ddd908b10a34d5fd1fce7123f6e1911c56559871105e9759be03bff618abb0ec960ba0aee83f60a98f1bc13a20fd5e712c78625071b0a5163e18f8f14342e8e172ebe80fdfce902ad95add56e210ed6b4bb24d6ac98910fa96c50eadb7d71b4a2e55ba62cb353238d8a96b24813a0043bd1b865ba34781af5347ce27024f0cb072a330e024aa2a950e7fa98e063443eb57402deb674512d2147c1eb671be8f6b0d5a14494e3449dac70d4ab2ce8ef6098045f26d4a48d4854e6ae58160db58edfd12ce1ae6c4cd8c29e2c4c4debcc29391a741c5fa834e5908b1881bbcea222242a95f38c45749a432c27ab955347010e57fa4fb1a9aa813ff9fdf8c121cb1309ed8f7e88c5b468799a36e375b65fcc4275d9e7333dc06fbe659db9a813565af7f4b0e8030301d6af4f17515571ae7a7d98459939cf22a8096a4c4923eb1c32272d746b60600d40c5b23b5df243cb914567f77fe4ea5c77f2b4c22213206815934c24c67f0c84dc12c035d0f001bd53bcfaa8723796c83dcf48ebf73d5b89c2b3b13f48cdc2ee7aa22491d45a424ab486c96243fc0968d52d3f4c8a7706e8d6f85fc39b61352dfd9945b25215f4f6a774556094132b92eca7fc94fdea903ec034ac7aacccb15cb7032d007b298aa5e748c7112aa76e014788a694b2a372ea5c37df151beea88f5ba1776024b2865cbff0924c77ff586be37a8f990b4aec8095cf8bfb898b2d6fd3673a98f613b4cf9a09b8365b11522a25ec24c4ccf68af3d0b9c5f28d6d7320111a1b0b39f08dd72bd5e7c46d44b731e0d5eddd2a30fc819c865d6119a839d0d934b94a4e304a8f59893167e379979c6f89890638cd38e5b31095b33e6cd0e31f6c2d5299dc626384ae6ca444646561d35512dcf3077883231bc5078a679ff72ef4f82aa8f53789c7f9db6854345178e4c1380ecd5a6c217928a2e4cf5dac2ebeb133f1de23bc764e1759d8429d5f3db150e6afa2554819b4e5683ffab8ce96779bba2c6c592497556db4548dc26fd53188477fb5028de74903701c8611ff2a34184e611ee81f85afe67c8bf3b683c7283a162a6b483f945998c10e410f366f5ab2f69b24aefdfdc7cf8823214a536a9f5a74d01960c7cab55139da655df06b21ade9aad82ae3a762dffa0f05b813cd9a0995141f861e57a94d771c1a29952465314183044cad26b4228937642a474036c737c980a94336e7624214f92e1f40399c751ef9c2b0913697eb772c4695208e21ecfd20915a33db1bcc408acac4d53865e15d90c223d38bc6b4c15b386c769db452839b86769a7dd3d5cdc81d734fd8a0d5be110e4ed790ce44b5a03d231777234747e7a185e2e7cbc1803e8ea527b32c6c82dd1188ba747fcf01dababa9254f818f2f2f8fd59173f30f74ca17bb9b90bd993ad1d66f63b8f8865f47b666772f5e419453235540f049e5172c674d6c7f5284693461bec2ef4850f8163615bb86fc6d34f223ac7f841e78c3934d669c1431d40f08c72937117fc7bd555fad545be49e175ba3992d6c11de60b82f34dfc3ffc2016ceb5d507bbde74deecf704aea050d3e4e7c2d3ed162b3d69392ba3bb37263cfb1102c5e8203e7ad3f536f6cab221b4428e53fa78d83f11ca60f829ef83f3b5f51efc3662d32da1929806b912ace29cf4cdc9ede0a62a3e3f1da54ea1794032e35b3d6d0fa6d890669f48f8c0e45a5c8a1a46793532004970d46e412d22814b55e5168099594fe2c14ba2ea4b14b4d46461d47e910f8a3b6581f3529881268067cf9b2c695af65038f94114b501d5c0575371cd2743d6b526e0965cc34158218d17fdbb813de9a324d89a85d7d9276c6888802d96a05b1d9391de61d11b5c9aa632a165b8bb1da3f18d14fd39c4808d49a843adc8c1175b4fe2d4b67c9ca2240ab5951d12c5503f111ed1ce43ef4c133e4a2cdb38b1b21d1aa7ed82e9f5e909ae7072a3b82dbca6ba57288165ba28e943200a83682439d53bbef4dbf1c53f47b2c1d3cf4bfce80decd7cd5467e93f387c7a6255cc918e63fa7bf8792366c629f4567d673fed428ae660bc4b7040ebf12aa0e5974816175996ea131e1a330b013e2df41329fc6f142b7cd1c4084ec60ca50fca4ace77473b6d1ce87cf3bfe9acdd6e87c5f1697cdaafae98b5622f26d5b27cd2773fec9d4d7e72762be6592f0e1c33df829d2b6e1758a238734865b580b168892294a986a6ad3a13feebbba849c2cc77ff8fb84e1be1657a7fb53d773c18d588c1bc0d891af67a8b75350e512614e2d59960e6ec9ee23376ffec86fc4a793a861201bcdec214f21cde85806d2b0a539a75dc0d002e66434d891a05e589932b3eaed0e0c827317526e7792169dfef690f9ff2c05f9afd7f288495f3b1d995cbd20e9f81bea4c80b291ed4a2b452830ab76ffd1f94f47a76b6f281e7872cf8b521896f522dbe563575ac5fd2c314673c46717a9fda26cd82ab84a812b8d0891571f5e35fd02490b4eef1e19caae06553df44713b874f129c237cda56e972fbe434ac6ef057611cef7d0eeb7b8b98382f2d6deb2e27a075ffc9f46ad0d34ed513ed55eb1d173e838eebb92244a387369f4958185a5c674cea38e75c075737d690752239b884eaa977a54191c091c5b030feeac0c7db80594a49c0d643bad80450e2e195841daf71ca4b6b961537a3b9f8971cb7f1ceb507b2c98b742057daee20b14b1442ec8f5c5682ff41fbc5f8b26b6ab09b93e0050df865e9d3a44a221cbaf532adf9f5213b94c3d3b937547fab1298a60ef188f9be3ceb9f90e73afeb215fbe798935deb50fc6e2c222e30497110aece02b470e806861410e635997fc72bf4b145a78b192a290609bc59d12fe26faa5e36f62cd59fb83ed6ac316b0acd24c67a0535d68d091c6e4d3eef67aaf71ebaf077785300ce70ffd39d317eafd2e6d0e229dd3d84265f0cec75c7461b5f539e01d295fc6deffc9cb1d07e0cafc4ff700cd1c128f0c1d280d91b5f7b74b0e06dbc9624dfc4336a21b774883479ee86716c7220990d2082d43875d7540cdcc74e9a2fc8332896de234178d9c6a057def1a91c2764bd5ff958e5e70db3f5a7b242056a5a5426fb9dd74b4b9447179f164db3f4187af59a97d70cdca8ee6022b699ad59ef2112c83918c530406b73ac051ec1eab34ab328f575ce8ece03c5c0f34137309a1fb230618e1e780d933f75d28be28c28f5dd09c38f730c244569e0c31cefb9067c4a7611c45d5b182d347009c26d0bd2520522396ca43d7f4f5afa11e4bde154694f54bb9a0e792cc35746b6fae02fc7529c06147200c23c8c0c7916c12964439f80b99c57d0234db7b6478a1de99e9b9b007f2f785ec7407a68460f53a4010f639fa268291038e623317aa9e330dd224b7896589624359afc4a5c39e7493ecb6e73bfffb430ea8851831a63b8f3649abac5f3efdbd85ffdd6f990c128e4f7efe30b265c242c01db60f1a55d59c2d93e3dae737ac473a8a31baebeefea3dde41b7da2a9b5f00de7b274ddea795302860ed0f11e5684939a230efbf1ffe6f09ee0131031f685ed3f1c04bbcf53d90449af5869b693818282c9a77ba501539513345c57d331875ec3a92bdcac468130443f06e75e1ad96958e18b460127067e10f42466b3ac89898129ec2b03141bd41acb9187bc05fc30fc7b9b306b46dc561c65b19788471a4640906d761f2e29e25acc7bdada06f299afba7d5abdaded321f0b148f63c57548b4de70c8b35abd1856632a137bc78a49cc7cd38b46bd4cc0e8b1339db4e12ec3707b40b2a663a03ba43fdebc2f91f302e005f75c836a298bba7344887edef3836d47054f6f57e0e518cb49a24bb8986402bbd7671433d8fb8f44926a2d3f4f364de95d6f948911b54d0152e765632dc2a21d47cfb1fd3e006ceda4724b19c97805605312668e11d79c31be1f2ce7daab32696de44929450761a9f3a048163c01dcbef693450affb36567840416e1f21428e3c6c919bcc6869da1483b08d99513f2b0579a10995664fbfe5b8b85572cc1806c904774949676febd111da38f458a65129a938af91c240dfa7ba598650d9c5168002183f179b9e27cfd3d4d0ecf6ad1d432e6082c2adb0e6b67cb2fdbc7aac1c01c6cecac876c961c800ed3023b1d7d40aa3f34b62a196b693cb406625e3673a1d1ba9d72a6cdbd88d1178e37366754540ef3acb49bcba2233034b491b41ab8732bab7ae2e6eac66508c6586656513331b5f25bc61adce36ebba88dcbb57c41e6df25cd9036eaea082434b8af767a5aaac9a906c714cad1e0f37416c0594e51b2c89eb33eea992e1f9b1f37cd97ee584bbd448022167348488e9e15fc0d9a2f7d413af9db4348e24437f5d670c9d288d807e69139ff82264685055424ef5c18e958bf74434a478305e2e9f8a1a92d620957673e0d52a1c46a1be9591113f00abd5b1dccc9300b1f6fd3c02a93b9d1911d32ac98dfeb2b13b907dad092d1ae26b3bf2d94422ad9b60229b1aa288fc46695382d1ee82bba713b45fc9c8c09cd6d65ed611d1769ba3159f46cc9b48f07bc6501c8d501532ca588a9d43d34d1474913191e7e2b8d864d57401def63796fb80b8379f04e22b4ef7f38c414b8731cb68392fd2b1d121b8bf4f9d4cd1a7358e9a00db36580b6a5f4618d3c6f8d2456dfb4f24a2a83656d17f0d80ec59e49a9abd20d2d0e0bd1d6e58b270433e41a50a1bb9f5593a4fa1e93cc48ecd0f3d36ba0a7e64a5164a9339720058cfb2523bc81837c9dca82f2874971ef8878faabd9b2e2ab3631a22e2df9f3054fb4a93b06f8c124f0cd5ddb6f3a766bdd6270bc1a0d9be55addbbf460a02163a77cc08c3bc63a0f7c696bf5e9c8b02e3710245df4c6c3d57d81f6c781f11af083d75f03da515ac5db894245155668a2592a68359163cb35888e495a3e666a6b6ff5b6db9e570d8601f3a9c2992a71e51327e3c21cea330fc0a9be7265fea018679fc5d6c666bd032245e5d5a5d43ca4a8d69078a152b9d1b54e309972230eda6546fdfee599693d20c5a120c8ede7719892d2054c3c1d901d03392a90fa56fe84b094baf080e55699e17add37b3e987527fe7c5dcaa9b376b89cd5bf6acbd48aaadbc550428045df4c65bd0ff41a73cb06ad479cb87b94723ac26775eb2c82f22d00cd7d32bb61ecc7ecb10b74582206fc22e91334b7880e4bf98fe1659c499364b701eb406bb70e45729bb55f8bf3bc1a8a07e24b44aff3231da859e91f6d7c0e548384c72591638e72733a518681a228b483a23e660909a1e815e8232a58839a3e619bbd84e87cfc76e02076e313267c19b7bec671a7da22eb61e156ec726a84a84ddcfd7309ac0bd97e8ccaf28eb452f43388bfa96ccdfd314fb32701498d9356d01052d59aa252ea0a6b755b3252e2f37ada3e0c973dc7a4903772234d5c5083ebf322d0d54f8fb2d79e69d1013d9f6da1cac6234509d2ac40e97d8c1f87c5eb518527a114c54c9df7b04f2dbbcae6131aa61690045139ea4a5cdd4bf031eb9ed3b856d2771309c92e2801e7c609154ef114409840f6cd11041d8e8a941ccf6174bac35c19d320be0acd6b8771131edb85e3fa0c6ad16db2ccb3ccf1d383a7933ae20a1a088694c0b492727d5b2c4ace434b9ed5b359865148ca0b03de34b1a4171fa15e409fe56b0c36947f11b426ef2ad628c19dfa5ddb7be59b385833a58d19bf9ef471fc639225cff9e76b68878c9e85bea5ae38bed296e6c52bc98ef8e009341f53d1ac1e40537a47ddfd74c4f6d60f172de9e62500edaa7d265335e062d3ebcc83f06caf3ad8fbf26771383ec0202c823aa46fee8c60798e3abeb8913db1c1d0a0364a685b068909ac6751a430a163903ead212ec284090cca7a03f47bcd454b04b6370db2eb5507c5f23279a86629ae4256d19fa10629d0de7757d57fc546b658ba24e9565cf82a5ebdaacebcf3be7b3577c5c8cc5da50d83ef91a00ba1f7bc8f019c73b009164e503f898787d7491fd419887d8060c27026838e6250944ebe633db549de9f7cfc52f2dc3b83f3fc5d0f6575b5e4f0477e9cd4bd5d3579f40a59fa75425a444ec3eb5b4de4dd7cb899e8d644c59fa9ba54cdf3781f522272abda4c723c08b5b0e9884862da5d77d50fa158a050a957c84162a8c7891f5acc63e3035da8f09731fc0c0341865c4ca6da7451720635b8bc9f88a01d4d198c106e63834826f0e7ef2da53476a0638b3619ef044d8590903fb457093bb00a8fa685290b75bd930c56cc69af4b38359afb83f1300d2dc66263af962e909e542a126e90fe3af502067e0e3fa9634303a7573ad4feb1fe055343b98ba4f81294f62d49304b450c98d738d4e38f2355d0b69044c1f4a4a5032a07f10543f05e841996b8a459d11a379196a8f613ca44d4028ce0753b3ca87396d52ee47dd05901cf51962439f4174c6acdf47b22ddf14e33a695fec2dbd1cbcd05d93132441dfb50f098affa3cc79ff8abeb74d80b602cc69047a4a9fa357305c19a703994de5b582c281f8d697fa6310dfdab5aed65771d3642a7f3ed79fa4dc6a1e0bd92a2524b6100a072beb862ca16524cc0c0274a9453e0a61230002a080c8cb0dfedbffe2a7899090b6f7de7bef2d534a4906310abe09f2093de2dbc06a8fcda2461a4b5dfc2b262ba08beb392823b28aabbfe41a633af9a0638d55ed64f2ef1480ce1a167b2139fdd83ef74f2cff3ef631477b2139db6d5d37a4e9be921cdf87b6cfb1bf6d190d927d7f28149a3af83db07b0ed4fcf973f833cde17d4783f07bbbd8bf30ba44cb484dfbfd1cda2f5dc93448d320b1657669101c6ef6d2907262ceca7d9cf6981373b40fa224873f7f102539fafd8328c9a17dbffca54194e4d8df68906d35d3204a72f02f0db23d2d239f6990e5a1ccc31f735ceec71ce64c095a543223bb46031b3ffc47c472594a96cbdd2ddb6bf08a6963358660248668bf81cfc1c14074f31781d8fd5e1a23d64ef2bb0b91451659500f88fb0f34cd4d5818e6c618b9193f4e97587fb6fda6f16afb8c9757dba6695473fe95eb03f92d2b8e35c5babb9b03ae22d4f0b58662b95d6299b6719df7854473442a9954564e2c2da894cb0bcc83f4861800e090834a46871dbc1a6088305ac4171cae1802f03dbc4dcdc7c719a24611bc42dd0000d69104af782cf1c3021c643484c816e1558b8f2a1f7f8dec0e4beae523ccc7fff8dbc32bf0e3ef125ed18f2e4d789503af6474f8f83b7c74f171e6e32f145ea93efefef0eac5c7df28bca2f15e2be24dcc471e70f8fdc187d503f1343cbc0c0d0f3438fcfe0b1e5438e4f0cde01a43a3cc7d9b1a1c4e38a8c013009498014d313c5c80f3862576003dfa430750032d2083c3bf0a0755ccefe780030040878979b98146d09bc1b544b72aa09270014fa993121434a14c3c4070b6cc251ef458bc1f30a076b2c00bea575c502ea5df4fa15ac0a77efa64344d5121c6102ca08dc9a6c609fca1f443112b200d8906870ae822aafc472e72b4005551e5bf024f51c61f08707e365c85c40fa00fa0e8b3314f4ad4b63135d3572a9102d083e732709ca6a08db8d16886c04dfb4e3f33266c00067ef63a3e3085a592a8fdf2a444079adcc48303674f8fbdd5da75f020f20597b0480308585586fefb287aefa37664f673cce93c7083700522ac1c1d9cdca4265daa787815db2155d28c886b62efde638fc33ab4293d9a515ec1078ab07230a9f5cced795667bb5110af306c93dd0634b73f05993798feb16e4569e1ecec35f03130e6b18c8e5eac92db6d96ed264757d86086a35795aff96086abb3728df00a95fd6f0f26996c5898feebd52ecedd61955c1d172a9e262841ea60d28a38e39994afe160f21783553598bbb346944c7ee984b93b231d29abc45ece1346627d4f702b280b6e6215871ee46153b1971b0fb4b9391e084699fe4ea6f6e3b4beb39f557bd7b88d866b23019beaac5a8d2592d88ead64ef76968bd1d3c679da74c001dff1285cc7a3701ddff19d9697ef53e7471a5177f6bd7f610a25331a6ee8bbc155f97d344eef7de4954eac58acfbbeb3cbea9aff151592a4db4ab9d28fec98cf44952c52ee6fd96fabb1d01d5cf638ec512c0ced57b6bc0cb9ce6f097da7ae945df8c3c31f2ee72f8d969d90204c540b54d9657ea4869289ba60d855be7b95afb91435ecb28feee0fe3b4266df69bf4b43dfa9ddffe0caad6b292763745feeb76eebb6225524491a31f7b99760b814355ffb4e87e863873ef6e8a5fc3d42ba9185b19f6dbf812b54cc1f5cf7b3ef3ef4f9d168f9a5a216ad85e963975a3499695a4be8a3217f47a6fdf71de1b988866836a252f37c6ac74d8ee3386e6e747f5f846ea476cf60ea1b443d0bf83d4e9f4e60741d5675be42559e44c353c5e99a17aaa365fc273d9d98c69631511a5ba644a728344574879c512c8ccebd7a1ffe70ecd7a33be47fbfbbb28b71b5adb45566c4687e88a2424ffaee75f89f4edf8522125da162fe90758e50dbcddf31daf9a3d168443b9f34a48090ba2ffadebfcf3e199f94358449297f41afa1efbdf52816c6d6fda9b3cbbe53bbfdbaef386d59da27a46620bbeaf6751e8d20f629d61070755054a3ac8e2f4b6a30d3504aa94999c54c6659e4615379728c9665353810f51b883280f7dca330aa00ef399402b4ed3b0df440143627d669ddbd07c61cada3b165c21a95878d5c3abb468b32feaf62ed39302a8073341a51fba02f75568941b2bb809b7b9999b99fb9b7e94ac18674240924b0e99dc262e1d3bdd19b1707dd7e8ca902082ca89155af6217107c767d735019082e9a3d4207eee61a136cd0e3ac3a84253c35dedca00975d7b0ae23ae53bc5902129c55914bb0dddddb7379923c8986bb53a760d5119ed569190ef9ac310789de96bba08b35ba14353e163db24a01af31ceac62ecee6eeede41e76584bbbbbb9bdfdf6384d41856c595e91487552b33ca0fce7677191d17431407b799b12e4d8cf24cac46205ca9b169152db0428d9f8d95ca74b928baf83126d69667d3363b6d785df6d8e088a1a7ee0f510412492c115d2ef9f7c3f9430c0e6ae8a2c6da6ca7e2957ca7aafa48b0c762b0caa37c9ea6651bde449514c7268e564a1c5dc3438f0d4e114824b1c4c62875257fa4220c585497da26661aa30973346dde419664ad8a95a2c6d6075450b7361867d8fba1c6ef60b049e1355211861e13886a74058148508d2e204c0967a4020c595407cce802c24f8ddf3552118621d5fba80843086a04390a1da6bdf421e3fbed7fe095260a7f68dcd779af72c1abf931aa441fa3c802138c5125fa902844c320d5fff39c9d7ae40e71dcb6516e75d0e7c9d4efacdaa1a62ba7a2f521741fbf197146f46f469cc158fc7542d731c6185beaa87cbb5b3439861a8ba0dd8a7de2c51863642ec65e8f9bb3dcb82251bcd1b05028de6498e679f1466e5de51bef8e3908f366b32c763716c6186326358f71f3345e79ddddeddfdd1c7731c6e8c5d80175daf228cec4df65e6776621bd6c858e833071c841a59291c922076f4322b33aecd00619950e3258c8785daf41871c545cecd062c685898799d20b1e5ca41734ddcefc19d14c3288a44ee803e2874f469450a40fab3cbf62eebb7c55077be82257b305f172e9546dd362761361685146254130f7bf593e31bb9dd81139c3dc8fad2d06733fae8c6affa88612d842efbaf0380873ae36c383f642c35e489a0ec0697f0022092e3c6c463a0dfbe033e361180d0f1e12ba5f784bd3c3115e784cd3036f009a7708c00068bce93d34ef94317a909effc9a130b7b718f06e841180cc076ca5afba866dbaa1b8f8077fc23efebdc16005c40f40ac6a6c82b881114300031002a7e610800043c89841a3868d192064cd696a36b383e09b8581c90c8795d7d4c43dd9d4e8625dc088a9f1f8c65536d29b0520c40d4104c137370b03860e31be76c3f0b6233386121c03280ee0f3519b2a1167e2c3c088e109200e618765fedd17318e83235f04200530001722a685c0e10d636ab4898c93e322002f15c38bf1460ec0858820833b040a47084db4a19c8f00ec0db1dc2db7db6a3c3122e4fa76018ec0d182b355ed9411001b42cae01a6b83884dcb308ea57a399ee311c06bdeed0876cae9ee0c33c9707a9b6affee6829a5a4617f779708a00d91c9c0663011454456916478de1c4732b0192749c36d1051843b0d3d5339cd8d22e60c1f68d4f0a1860d1f6cd8f08108227cb8e143113e1821a231bbbd6eac860db91d2122c6993e79bb134144dfb811978bd0768dd0dac54c01b2508d1a1bf263778ca17c1f3666a500fff6d9f6cce056b31fbb7d6f74c7f6fc19c8445d30829bf6f510550a7c8c33a1ff114d7d930e64818862dd4fa3281bd9f7ffd88a51dfc1ff63aba43db6f6d8cadcbabf7c6835cb6ad4b40f691f1289befb2ef39ea1742f8a5ed8fdee08bdf60e86214cd3b4973642af5931ff06bf68cef7306f9d5466ac72abeef07e7e3776ce97a0f7f35bf45c5d4daea8f245eedbf6d9f6991549ac60007f488a1a9240e83f9641912adf495906864e1a7d361c73cdf36afa666cab4a1a7ad5bb6747f6db776337d16723fb2d935c715a2219bdd6ad48af4b8245a76527ef77b5e3fbd087a6bac3b5e8df8d95c114958de00ffd67e3fbd0fb77835f7e772cde3ee155b7f3460cfb76eae387a67241b3402b8557a26fef7b7e8731eaf7a1efefe43703d4fe0916bda47b9a4937e9563bf199d53910e3687cdd3e738e861b456d8f751256b5b615480f51d5baa7890f14202b3a68888e144996b49efcb8145e8dc0ed3b09afb6ef86494e30d22afaa94d0e6cd917324efb028ac93514815cf73b82892a7a9111fc221a02e1bc6a502abf56850ba6547e763591523f4ffb8ce83a2ffb8ce8233474da49b66ea1ef06ff06aec8f34864869da4dbbcfd3cda637a4600d9fadde8bb21d27eb9ef087eadc7d60ddcc1d58e3dad333da03a0d98bad11e30553eb6fcb5e8515d5439da43b4b5a3316b8f7d55b94060b83bba8d260d8c986c81095139da43882a777b0e0c9968a272198d7186fb66c8e757f96ef0d7eae056ff68085137da4388ad58ec650f51802b10accac7244f1ff157885139e8ba65cdd06b8c31468edd43ba18134a56f5df656996efdf544c7160a6feebd46334a954ea31b06beffb2e769be75d27479355de37b7e20dd7ef7d363053ff09e9dc85d47d9cfe1ea7f909aba0d4f4e7df35ee73a2de7ac2fb2e4e69fd461915955751796e655e9497778e9a946945f5970ff90a0d4b619f0f1b604dbdcb639f0cee53a08c05b11f8134f6b1191b2ef61521a4ee0b18bf1942ea479d552a7137152fe5535bec8455fedc90e911e969a950effb5dc05879345915fa7e7601b77acf921d97226ecf2e5926db648934b9c1144d6aff4e2145eddf29a6a8fdab0a8a4a742dafc4c2f0de3fdc1157a98769914599fd169f023baaf63d30c6173bf3e03e0cc87577772bf68b7df71521a462dfe83b30ecdeebbcd6e7d372c2cccccc23668ee2fd1762669eb123b2cac549cb69a8b50e9f23d20bcccb88f7dbdda5406674eea554a9f7c0703f5ac50c766affe7eefe3cd57da765fc392766e8b917fd7c8702e42d27eee32e5e9ddedfa1f00a8857debbf713a5fa872ea5bae7ee5e7277f7a94e83eb884656a5503db6ee03f1fa7d0f51fdbeff2890ad4bc36f0712229f03f33fb62281f9a59c0666e83d2aa36db9bc2fe11a98f7f71e5ebdbcff83aed332fedd9cf13da78149777cff636bff0eef7f6c75297a22abba91a779f577928bda58a76a3b92eaefa658e33b51c6bfdf3d0531f41754776fb54b5e1942dde0eabdd73003d5fb17d061401fc2329ea4aa60204361d7135671ab65fc5d68a8d514edc9aa47bd481313fbfd966701c3ad2c1eab42cf3db7d887ddb4525a59f9185796c8f671ab6b9468197fadd56aa15b448e3c56897e7e12e24d8f7dd53da27fbfbf1bfd2d1ff9dde85f205b3b96584f60187d4286129efc5b803e32254c744a894ef1779c2178e571a19f2f7affef7ce49fffcecf59253f551803466edbb66902431752b3cf501895ac1c4cd0c5988e43c1c4e9ea343fd8c4e095f6feee7fea1ad2fb4712789a2de32fa23eb1c8aade1a5b976edea1ef42145523d6d0d38835443370a4863e9cd87fddbfb71f0d394add3e8242aa07fe90b5db1ea76974cdd5b18fc1b1a8692b1b416a3f263dd332c9318829535445feccd371114303c4b8d3b8e7674d8b23ed3749d74dd1b3c373844913aee134159151e525a2d3daee2c6bfbd3a9e368e4df21bcdae88f10e5ba4d906800af328a83555c04abfa25186a95c605ea382b81d3744be9eedfed4e9702919d02cd33dfe447567152460dc39c9d9dbbeeb1ef3a4c7e07c62a3f19586fe1521c4ac32a771183559e443f370db7c60c280e1a7d74d4e095c4b1bd6486aaaa83573e79c8f779924038d05c8ea00b5b483572353e479b198e32fc2d4c6bd75048e41086bd8f758ac29068df5105bae09a98d3efa0cd2221f2391a7531f9db081d8d0bd7912e1d6ccf3266e65048adfb1db8cfa0bb8e47b12ffc793f037dc7330962be0f822ec6f436da217a7d64c7b166e89867d92703278be938f8a38acad9bbee4b8790bf6521e56f6c982eeeb7a9f25531474a23a080480d639c09dec5d886197e8d16b969dccca88c9525cc6c6b86f94b2a362c660d56f1abc2ddddc7a9c135240e33e3d4e0130f087850c3e78941751d59664feb9a762596f0b1353e97021965e44781da2f3150fbb7bb76dede2f4829b1c7944c13afe2efd41808c9b27ad0bc414fe5c0d045e59699b9d7bc35ccf0e4a29e52bc726fd2394f27f9b565fab7a7e230b7d430fbbd97f09a8665d989a59492462965963db6856146d5f79257d007582b68ce76773762ddbc20e6b179296b1e2b3756b3ae819eea9357d9bfbbbbbbbbbbbbbb3bbbca934883bbbbbb7f11bc5a1a83babbbfaaf6fbc7f08aa97f83a6a018f78113223fb25d0b52b4f0f2176f2c325b68a0420d4fb1091f68a2f37750c622d1353dfc8035a4a93471060d33c648bb394489ec46c3ec8fff02b0869a0646d7b454c77c0d352f743146c628258661b29f419087a9faa95dbb1c84affbb33b848955aeda9c5a665fd3e6f6ec2ef669d48711aa7d19ccbf953f03514c77c99ec00439a8a14d45196073b68faf3a376ad3326498337c0650688008b527941fbbf230559fdd86196ad526da041165f6a34d9c79adcd2a4105506ab8db63a4f60099a0bbbb7d9973b08ab3777fc762654d5b9e12f0a4e1a7b14cdb58b610a494524aeffe6ec0ac6c23742e114ce15eec7d8c02e92a1d7bf9c9c056d2930948d77e16f84bb90e8506ae576dcfe0483da99e547ecd2583262cfad1756d6cbf462356205dc7a075d728c1ba1c0e448e8d6e94d92aa064df9989ca4b7dc8178e0411253d6cea8e1f5db357552139db773d368b21db6f40490f9b1a7b6806fda321a4f26fdd2a13a1df2855f95de6ed7744d77e0cdcaa040867ddadc95046817095d8a3a043cdd81a29d7b0c60fa7931b552e31b02f23734852de20225e6958cbdf78e375dfcbc6ae305bee771b06aaac1a08a4761c28773f903f1b5a9c911fb94a263670ab1a5881ca815d3ff0b3a17120fb67c3397025f6d9700eabb2415ec9969804e29a5c41ccd1bae64312ad30f78464b6cce66c5648a28b31caf620be13e85032e236dd5dd07422420ed80004ce42052f2ca068569014a253a712e3e0f7ec1e13bca086a7d86ce4b5384489768a74b2aa658ca069769c4bdb7b6f56d39490f90aba28bdba45612ea00b3cb29eaa8d803a30358d9d577e586a02db969e969e6d3f6bb5f4742d2f35e1d2aa614ba989ca5a2f616212e85a5df618fd68b8d4cd6c50b70f5b7aba168d545d9ab53e28f841a078b33368b6ac55f941206f8607043ca46b77f0c414eaf2770caa9c61ae0c4f924406b6b3d38954ce30e3679f0c95336cdc0102da249b24b4513943acf19bd194175b4117634295d728c98809afc20ea87bd464d41a2519f58c968c7c46508078f4a4f2e8a7f2484ae56fdf0ea89bc2ab100baa523a2bdc794857dd6ec619a246f6da472778c15fa33ca4abc6101c0b5a38d8092a63418e7d889d60fac4192ca8f2674dc50c3b201aa43a7de20cff2809d08c5255d139c2c4e9ed8056ce2b5d1a958074d57e6563e8ba2e7e34586235cb362fcbb20c0ce527f2e4ec485c5a5ee92ab1c98bbc7262f13496ab85b5dc8661db7998f6119929efe3808bf70223faf7187f4cfed78413aa10fb307b996119e87d1b98bcdf139f13310088c1010038e4f03521a383e7c2e3a498bb0ec6196f1e80b5df90269c984cc11b6e00400c0e3864600e8b65983664ee0e3ab870317ff6876fc8e40fa56b81f0b4e7954d0f4104217db8e91be60722f28a59db8a816196658e81915559f63559964d0d86878137df8dde8fc118e88e619f6518f632730c7bc7fc73626a03f03e27260be17d4d007d1a98fc5f13933fd4228e101527c7bb80cec79afccba37e32b02c7b2ca3cb35e7050f332e76a009d118b105001098a7728d21006a9ca9f187984a6f80f1a08ab58f46d61a44f410b424f430a1115522e2cd42e1d79eba48f3524cba66adb053d81fa7a1a986fb23e2af86fbb35588331c85ca3f269821b398d5cf622d61635331a7a1ea9b86a793e408248427b6aa4bca3cdb102a8698fc7d9c70a4025163152e2b64eb6c2ce5c4bc4b3d0aed3fd64c8211e51f9deae866eeb306bfceefbfd7bb93fe728dc823e00e6c775dc78db49c7447f7d8b793de3f7e478c9e4443aeddfb4eed7777e9edeede5ed38ceb5feadbbfce7d06ee90cf446d90b9cffc33daa3eb8eee8890ab7cf7e7b8e6fe07d78e54c3f2cddddccddd1fb2340d7f7877f792fb95ededcd46604b1da428ecb3e75e4749e4f9370d6df8b74effb6ecdfe732d247c3f43d32652b5485b6a0fddc0f534657a8982197653f3f1afe3b9686fe3a4a347ad4fb332ef4c9d8e87660acdd5dd73d0e37f738bcfe384d02bf67014f3f02433f41ee57d3e9edef71f8259522772943066ace7fdf35b3ef56b6a76946743ffa74a2d9b7c78540ee4fa0c6321cf5fab58f86fc1d1d0d37d3d1fd90327b6e7bd7c13e199b06ca8a61ee8ed9e89ca79c4eeda00b56b10abf38a1db5f908858b5df5e488d60f83a3afbd7328a81214791debddf5c83ce9bb973cf89883562ccbc4c576ea1108ce3406721953519a5cac7690c7c56c96e7e2e74dccee4e7ef62c464d0711ce856eed4f8314a23f5155b9155bbf137bef3b8145804fd4059d2d33a5dc48a293e4e8e300fb3b088f2c364c91a599d178ff8a446b731c6c499f8ce2aae04f3079a38e31c5d2a56c508863192be7b7b87f6bb5b2c366732be888914f50ba591ba2b87f815fe0a5bca4a293e272cc3ef58746b48fb14a9a1e66a5765694452b7a2faf01a6aae96b2ab61e1c745dd9854ccd15cae3d21d66855a85c9b7e2d56b958c50be4aabc400b4595136f3c5e714dccd9eed6bae3f6c7deafeedf0b5b42c7eedd4e774a97cc3aa8424950bda9b10a254d2a922475546315488c54172e7cecc73823a486fd92a21ad5f4065585d8cb284d62985be3479494afaafe184ad21baaea5455bdc66f179c8356e595acda99ffc854c96255ca7fbce54e5c4f7e6a034599c2abec9b6e3e5de3733a9df6745ae9ad5671988b62f68b57fef22bb8660b8a418e458d4172488d41456adcf1560d4fdb0e6b3c3349cf94cadb6b0b6a4df31f1a5fd77ffc27fb993d51fba28f555477a5dc7cb2974b7774cbc749dd5e5916f2ba8d93dff77dd987a790d771fdec21afe3dc9dfa8f47c1b490273ff49ffdcc7f4e31740c49f2645f46987014d6119fb6426749bce1709fd4fd64349dc11e53e5773b2dc35ebb6b875bbbb912cc100dc99daed9962c0c8ec9be602e88db5902f6cb6f46d7ecb7a0aed97c38260b836bb22f4e5bd01654994996712864a2f6e89ad106533e4dbca31ca54d2a3f67c4c7d6f0e43f8e058f1339a5480f142c488a562685c814ae787305cd0fee3f2dc3af69739e4effec3af9c419b6e1f8e29bc1b5e9c9c80c3d4eb23e0f478eeeda74858a195d2f8974cde6d3279eb9a369739e4efffe53f94fa7cd87c6d7de7c5ad33adb7c2a3f0966463faf416e04b3c3d311dea81b2b2936a37f6c75ea3531c75fdd749fb06a9f0bed8b932ec684fdaadbf7f6fddb6f9b6def76f6db6aebdb5658a1b2896bbaad10655836936ea058b3404c387b4e04730a56f14f509b3cb54f9b126fb2069a126fe2f6ad6da0d330b2ca5365d4fb85828ed399dbcb960698d4d8d240912a62a053631530585277a8b10a184051f90b1b5b36d41a114aa7d5bc3090fbc00cff637ce9ce1f6afc58fe47a7612874bdd140695be6f55823360a245220fbb2e98c7d6c51fd19aae90d559df1430393bb4c8bec328bd11d926a3fb6b214bae8c3dcf0f4a15a4513a63019a08b0b833f3e2f8cfdb8f48838231903c219bf588f411bfe1d11c4e57e363270437ebbe0a7f60ba9fdd11052fbf733826b3310ceb48f3dba1ffb3542526755b6cd81b0ab4c3d005db7de6963e47ec5b5fb2178d5df7d11df80eea5d474dd15b5dba8b9721054a31535ba725084b2f7d5a334a2852ea5eefb62ce8b454cd3b6fb888d4c2e1c0455f99df603afbab7e1157ff7382dadeb34ade300cfd5be7b8f57da771f633aba6359180dba2947a42f71ed39bfb3ac9b9b70cdc9093fa91886fd528ffb358d06db2671b4a39d996994699a898634272c9bfd1de671fb072f193d9635e8ac5aa26b541e7baf530137caf4b7006394318151c914b57b92e847d8771ca753b31f7d9765a3e944c5a7b894d6f76db649e83cb6347b0cfb24348de44dacf5733a8d98b00a7bee89997dfcc92fc642c540f3b16717e9b1d38a8b1f62a8b5384d7004ae5095d389627e45ed9d6ca7f667d248edca23a6a280789ddf435427fd12d5c12aec88fd49816c25d1309b31a256d4fe1dd97a1ee781c9756046970ea6d4e8d20150ed62f779f19b812a3d10afd9f710d5f74a600f234814c8caef08d18f2890ad9386fbdc7bdf8def331da8d1ef67ef81a811bda1aafbfdf33bcf5b30a3d1f346a04c5d57791f0d173b38aa04ab44348990d7ebd8f77617b95d6ec442a81b5b77a9730ff7f092cffbbaeffba50dd83ecdc346a18fae2544964994262f273a462af61826127d2016dba3ad03c37ed3703475b51412629732c42d32a30b07532ac76ddc3d73dc3e64a9bb7d38da8da66978b5cfeab67d8c22b8266e5b8cb239a9dbf61bc3aa6d7bf934dbb66d34be721cd7c9d8e6382d66932be81afb4c5641032b6a43204ae5df9e541a34a922edbb70b38fc616bf87a846fadd63df11d86714c8d68dcaef884b9a3141903f5d3344c98a04ea9a214abed1c7d4c797afee638b8f328b56d0eb061ee4af7853fa88f19c1af537cec94c23711c8691380ec330d1148542ac178b08ebc522e2ad8048623e05b6b0423145a43022a22d445eacd72be60b7d32b8f7ca7ab188601cc68d5efba205090fd01658564ea4d1fa966953143af9ec0b161d56b190a0bfa5f4aafc2c4990c49a9314a24ccd0a0d694e34549146eb291f12e8b44f4ceb24852da695c5b456625a5a4c8b14d31ac5b44cf4650aeb9ba290c86bb0ab1b882485eda46042230f0391a462503127174b12161a8ce4148538cc25a608a21067fa6240ad65f653e01c8598d0d4b9f2a44f86ca933e1a5ebb9fdfc8e5e462d1d917fc9f6c52599220e161395143a37a962425242516139624376049c2928425098925c91c51962418d8c2625589be4c0931e15ea3a08884cad110060a222d263c2e608b0e91962147586661b434115f2ca9fcdf144eb0e874b48585bd3012c775261333875c565ec585e5e4bd6dcbb39c54bdb385e5e4bdb9b438f122f462b578d5bd38acdb345f0965a08f45811bf89c988c4303f75af9b08646f52713ab1454c222a6c582f169192743882ff88b50f9b3a0291c1ab8d78a0c5aa0128598848a30104b5b587166092e4c246ad1a2c5c95b58fe747af71696933738eb8bf5e2b02f44fa42a415d007c9e5a5b4534a4189a7d4851250e9552a83f7b6b22a2ca520962492c34e3ea725b0982002955ebc62e16155a90c71c5f282d33b0d6b68361aaa5668f827159625f89c5c2c2660d17901cf898635353cb9fce4729d5c538548cb845c585d1330ac38d3c28403b1077e17b0e589e8033f0a6c692202d1d332fcdf4867478a298e90680bebc57a71d8375a0191b8fc062279f91006fac0fe87567dfc9895fbef8525c9139f569ce1120f4c12e28b2238a92d5ec10c61bb25040186f59a1267609a08410c7a190396022bea8b1798647183209fb085d5a203b638d1d2049122acc2680bebc57ab1247995824e2eacc4e385ca1fc6b42a7fcb4e0bebe4ea9a9621462a3f76721599f4650a8be492da564024e07f2012fa1888e4e5331089cb87c01fd1d75c3e050e49ddc0b32ff8798ee40c711f1603c2dc00c2242102c14f419856cbf083208c088471c12c01617ae24c926f42e587a1020a97781606cc0de20bfe2964105530522abf0613a5f2937250f947535e7e5c21265df3e205a0294071024fcd0968545c88c94b1a2a3f1662f2328610931485f12905b15e5c8610c18a74d8c68119b6b05e2c5e75438860453aac1484711b8824f5a8d4c9757a424cab5992300b0da22aaca151852f7d5a80304ce20cffe909304d2af30aa607f125087c017a75cd4b1aa20c12e2cb2ba6d5352f5e8832347891c29284572f5980e9a991014d0b5427a82c820a456598262abf5c359cb58508d8c26a19c22af6e84b8849e5b0145a6102c20481302f982b582f169152d0968148528f69298cc3380e63b16a8358c54024a997a90daa21cc8b6705336c61d51616f8d335a857500d5b582dacd5505c55b15878c7119c2514b3bb7910a1ebe2eeee013a292857f9ab083f526cf887c0c1312a43a9fcdeeb555e9dca1c8316eeeea4777756699d7c612ccc8910aaf4302f24c705449528ca002efff2395cfee54bff42832829d11c2f0f4383fcbf7c1098777921392e20ccbf80dfb93aa06e0b2bdd141a6e35c929b5f412a8249fd4d2cb24c4d5bf7475cdcb974af34bd4748669a211793ee6847cc1bccb3ff1fff2292f4495ea3b40ca0b51865f250d5186a77bd82743a42f7dc75fabbc0aa9e5c3510f8d14509ce157797da5e78f023348354524cef097e80c5255d989334c2ad11e9b456a4abc213d7fead5355ff23ec655d855f4318abe6f01595e2528decce75f6175cd4bea636a34923f9d0b680b2a34944faabf9c52fd575cfe301e3f1a4e4a05557e5398f242e8c2aafc2330544943e54f81e18a4ec73abb46023daf64126ec8a6485794c9de058c312351e9d3c2f4130c2fa053faae8b9f8717d0092fa033a344437f92e9fb5b4a254a431e42aae9b39e60ac24300c85706495163d4eef6bf118c6f2a75fd9517a5357024befe0ec2f95be65d43362c2a32695476ffa12387a91c8292af4fe25940824899e64fa92935efb397aa7a1cf2fd1d82c2a6982a17ca14274c6665149b4f4fea5f79f8fd325d267a9d497e8dcaf00995702471fbf026c4d85a61fd1152aa689a6be4477a43e4477b47cc9c1d0949a2d9f3daabfd4e27d898627cf31acf4a6ef4aa009c4486f9a1846fad29b54a8871951a2a449430ff316186df15e8b1634c4fc39f0c756ecb1f730eeb1d07f7334fa6e31f9ced1934091c9647aa7a17c5513fd3efb3e1a0aa93d8a383cff034b1fbfd2e370971c3499dec1152aa61cf598c0705402b275fefcd0cf289544dfb137c1d077ec954a3fbb687a07c30be8ac3831fd43f9da6f46e9498fd3f50b47bf3d090c99a84eccf0074f0db31f855ef459887e8fc3fd5e07eee4215f150838eb068612e8b9808e8d16b53b760d62a053fb71d805c5a81f489f7893bdeab261f22fc7048b29fb7d8aa4e16ca27ab75349fedc1ae6946ea7ba744d2031b066f7de64c2ab26b3359df02a722ffa8937fb11887bf1ea0a2e88c342f6a07b2139eb79def7de7b3488f75f976175391a8aa6d083fa5337cabdb82bb8200e0b5671629821f79a4cba55b97da6ab07e062ff6894614a9f2a3f7e422a0fe953251d0013f64547ef55f9bd4efa00491e74fc118b4a6892ae143c4a3269c55cd487ac83a36536c855658b13496322ac23b316abe467521ad9bcc7616a81deb980dea3c02e052af1fe09d65a7ce95118cba3c0964f0da03d308665e47fd734b551f51cc24878dfbd02fa996680bfa5cbb725b5a9b9767faa6c498c869a4dbcc95e7e10375bb35b4384ba3a4aa8f26548f9db237fa55c28552e8eae9172c723106764b832f2655443952fe5b3127146c629327aa0308a83a5e56de20df6f28388353b04d992eec31fa332b4dffe1836bccac12aee322aa6945dc8a8985d7dc82f6bf14356bef4fbb34395bf3e52abf2d5ca116ffce5272046f9e157c3e892544c6679d423d1f2a98f1f0e97770153e04e792de19487b77cfc5038bc8f15875b4016b03f077ff7f35740d19340ee55c0d1b700435f02bfd7429ed799463f6488e8877cdf0961e1589f9691ffc90d8a2d135a20d9c25ae416e6924c4224b7e842c742d27865811be20a0351c5ef4baad86718d88f51b5340ca2eeb37f28aaa1aadae0c499fdae23160a31507b887a6c165b5d99a8aaacd29a307dacb634c619d98a3365e8565c1063424fa7f6771aafb4ba9e5795f0871334d522d46e3d2994a4d4aebd2a8c3ca9b10a23515406514b5fd4559d5bb8626548edb08d58877af4a92e189d202505b5931e4b21254a6551a580660234540f8ada691e83a412d46ef316dc4182f237790c72212852bb8e41f99d8883c1f458dd7921ae704c8937fcfdddab6bb46f8f4845406745d805d566538d35184fcb208180b862405479a7613c48ecf73340634a4f72fb75748df6dc2b60fb8c6620fbedb9ec378adaed358ada07a306ca2c84180f96640595a56e21fe42d89138d38f81180ce24c3f835f5d3056b1f383ea200fcf91b9357bad050fc61acc052bd3df580f6c70d0d80c6a7f28c3bd60a678a4ab65f6331ccc5daef67740f1264a9f3843aa184f6d778c49d7b4e8604a38c391da8f4db184571c95608624b51f7bc2abd825c80931273bb2084ad0410db128b5dff9945a928253cad371f666782a63718b18d6b52af6fb994bab76fb1a771d0d03a8b5a844ad9685410b15cd08000000059314000028140c09c462a160349e88b2221f14000d8ea04a6e5098c8a31c076298420619820c11000080118091d99000e3243164b85a6ab514ce7976ec0853598da5107ac5cf835fa3ee00d3d7035cc6117c808906c57f01b9a76937559efc07d00f25cc1717b2c3608c762df81c25cd946349a30bafaf2a30fda4a89d816ed4490277013ec0d47dd1323d52fe8ada5efe76315a50f9ba7f8be0ac312a51f7da7147bf2784a173a8481298963c64d802ac459e06133088690809941e6e365d7278addd19645a13b3d9836a43ae09599684226902e118109ab8ccb093c43bae01d3e520d45cf2f137be45f3d73c088357dc8e8efb2d3b5dbfac7d90fcc53d806dc8aa0c8000af86195bc988f6b60b4c67a4803b8595874d126aa9a057dd04c8b87a6b55a314f2eafde5c9226d495783c90bb566dc1d6f7cc73cf753c5f6c5aad673d8ec36fdd68d5e140ec4723db3ddbae7d8c0447dc360317863d36a40fc59b4052fe8e3ca044c97808be3a1c4fee7d4c33949316dc7ee069b0f80a9684c10c2cb769d2ed3d0967a253993cbd2bb36c51befb09e252e92cc3101057645bf2815134c92976a31cb3ffd4d2890d52373c177d0af1f5309a6be32c821fe1b0531a41cecd61da29bca1d6170565abf9ef3a3ab689c75c7959eb53aeeebaacae5d22f260e448ee9d2a9fb9ca217da775ddd02b155915c1b9d7e71fc04b592e6d8bdab678fba620868b29a970fa826b58a154cc64a80ac2a38bc6c235a54c558589ad9afd8a552b3d7a05c497d601cf6e6779f998e7fe98608db7b94e1e43e62e7a170b1e0a6cca08e4a5e160855e75b9cde8d01b0a2deb57ab693c930908eb000fc721d5653968718c2c7838a4cbf54dde47606359834bbfcfbb3224660c82f1d063f06d743595d8f5466eee89772747ceb720377029f856dbb0685b4c2af684fc8976c329cf0c138a7e9cd1d92b9ca607709a79499d41da0ddc4f7ee8e65552e69c6759f248445b97f5e03ae7f226ab57f7c8d8aee46e289cce72d940a2a68a5203ca6f4c862ffa4ed561d53df75192af4f8c174fb7b9f6c81889cb1d97bce6aafb61b03b4170a96d0e97a86e446a8be00bd54d5240bf44c3198d459dd235e3ae924745307df09db3f758a12985d685a9846a266a5295a56ed9ff0f083e908f968353e5cb63107942197aca5b38cef8019923591724c04247a5f2b32ea6c7bc8c8e0746329ce1a1e77f9942f9a287318fcb5b52c81c3694baff251877aa9b21bc37b837ddcd9df6114d84d34f7fabdbac9a48ec4bf5302b2460356c96b44657d3508ccee178802e0725f7e3b67d72dfea03164845344100408fd1eff16391326f005814effcbf8f6289d1eee39b2ba8b0f4348ae368518fbb9a44e721c5e508bc8212c506dd8e491e46068b8f72c180fe1f94c88e60096f2e412e65a4f55a5de0089a21b46137a5fb6c64eee783c98d6b036988204a6523a3d054c91760102437e734530535590569a70e52770870c05493aa8c3df8486c631c23b461de405fc06047f14c16da2649a4d5773123de6d697f8e1c7c32454bc7661834d3d0854f94208a54124a62b91042fb09fb56f7e3ffa93c81dd56c12bdde89ef574676a00599da8d1b7bf69eeaf84657ad57fbac68af3bab6b8ae13b883a9f99863acabac930e587e1a0af04ed4a674322a5619d6885dc54ae2231d32342d181f28ac2d1042e796f44bd14a97db1e6a8ad217a56c1d03075f57b9f8f3f0dbec697d94a25a555683243e93ac461bb3b5526f82b11e0f83b06b6aac6c841bb5931914811e7230e2e4d991ff5aa0d78cb73eff71e07e94957bb64b79667898048a14a498713c059ee33f6612abd3eb835eb92d7dc085b7d9e32e5e9b9ec0888b43d4d2b3e9b1ee7a9d1b1de64cbf2af56394c07ba929898133c57c55cb8bdf4c4187acceb98986486390178699c843059c90d0c090c81da68822b8729b25765ef5840842113d5d3d4291333956332937ad5382f52987f2ac3d173e144f0e71e91837a4ede08053e0f8e631580013137f1a53b5eac18bea359af24305054d536855db9926815ce295c14e031c0c27ead1be657e0b05a875ce880d43f8b21e4033951bf030ed917713fa83a499645862b6e3c93cf7198bae7e00c710c3d0193ba1a4412e027f816bdbfc3a4f5a0b66171c660878c2c6e234c49ba5900ca8b601ff991c3ca923801c3266e8e3dca91c4bc13b70e47a6fa6950dbf9fa4515070f532fc20c255edfda20f22159559d44613949a0e32b0f96b6985dab06dbab7623abcf602b749614eb4f2fc3662748a13c45ed8f50553094dec3d4d712954af737f7a7dd53001281bc462ce12e03c37eb9d39e8b1871609a49bc1a8845f361d636601c5be78cb1e232c3f5708d9b785ed94c003e9fb251156a26c69fde70f5d9792ae12000af6ae4923d2e000409d9880114561305ba28dc6874d0518949b7a622cafc19eca9788a90455f0bad32829852f689500be524fd7fc0c43ce9427a4a83b025d4df5583a53c688d6d2abee6b8cfbaed4f3e0b1c495aa75261f48b39cb47573688abaf943d969adda1a8097a9ac512d22884e25804dfdd5bae24a28f8951e8edf21f25a4b406760cad98a18b714ceaacaa9361186b97672ceea2a7eec1ad0b0cb1a7888fc0d08ac30de9b2cea4e8cb1f3f010448cebd564d4253241d0a0705a32b4b1543300a6a4c2b926342c9ff951adc2c25ac8a9bbbde0ba33e55014591ebb1fc091a31aade671831bd1ac2086a9780f7a981d888455915e05d931b9af3ea74fec511c3d5f06da4709603713f06a3d18759ba43321021263a7cd5a7621979ba1270442e3254051dc0d42bbf8ac1f0479b7224bbd85625683108d842424da92ca148ffe21881230f5ec33488a75ea6019760640a2b27fe542cb34f5638c1b1548f40a62f362efb4a79d8fc57adb58b5550d8054b8965802be18bd05de52d22598ecd62496ebe03e3b204eb5174a41698d0acec83dc1b39352ba9c0666510361ed66eb392c19fbb09b7fb63900e3834291d2426d6f534c9af0f51904364d0fa27ddc7938449426d273c703da471c47f89d0d9f26345037776135ad08415bb987e4a136ca995eaa803f718f2c2f4a84ebe4f04d3b587603c7ae07b0092d08b1054e9326c28082695800b8fcd16cce3ff651e0040fc7f91df6f1e7d117a6c6570bf5cdaa874f085d94f04f822f45a4b22a2ca779d2278424a0d291ae6b975214497163e9cb9cff62ea7741c938607be4c65fc115bd018a26613edf43dae86cb24da00df74246da58949de68d9835d38b7d247d7232b2b1db183011806ed445bc64f5a8f9ee8782fdb32316a15755f3629a7031371e21d3710c29500378f0ba62ad81397324731ff559f54fca317a160acba6da167b3a031e7ede9a1096952bcc4c1143283887d237f6dd0b9f84990eb2f4776c17b2bf659d06391a03c7fb7450c4dfaf38b7dc649985905d063afb61f76f7d847e886aaad569fb05dd159f4b75a1c4f15fecdd551be33c69962fd8dd095997844f9ae29341168ad32645a20b5867f39b8d882ae2c3c8d7e6b71a1fa94b64b5dcea7640116a45c7dc69b565f5cbb6a44ecfe7d27152d3f973881a6829ab8255b84359ab199f3896c1d184f7cb289fa93e6c5e3c252a3022fde965b60ae8eb68b89810169d1008163319fc33ab720846944c4565c846f728af64a1f7833b0eaf8c68ded178059187278f25668970875b51c7d2e768916611883c58c6512dee7c8544cdde836c3cb3f460ad0a6b885a9bf8b33fe75d2d80465490759b473e5af5842f438d5433a05659112cfe1310b1f7191f07248210d6b13fd47ad797c9b58ee5f93e683a9003d2686e338852585b7e68c3aa21a8824719b675ca420437211f7dd4eaf90bfe78885b3c375870719c92513d58909c10b35c283d4fbfe9be0965c3188df2625c0b79c403e0144ad89b7f720c60b357a2967e7cdf3d17cc34f9d3ff0d9ac3a5b9b834dd936ab4b1fc350e2e2d1978e8373872e900d3c662b041e0d5f2323e0dca16734ee48b913ae82ed02fdd70d3b59f613e194a92d8ad3aa10719f3b94f0d96f9f8dfdb9430430a1b54bdb50440e2583b62c2106ddc0ce3acae016f3c23758635f1f4c32f3b44050d90a60e059c69db7450bd42b4300b8a02beeaf6380435267f93593b21ebac7a83b91293f84a2fc752693d29227905c16bc71975c87294242e0443027a71c20c8367af8e2c8343fb87bba6c2b308f1a8c4358ee9383477239b1528c8dc119d5bcf70f71079132c5f0e83a3ef3437bf31327714c0d560354963e06164a48715c4f0ced646bc04ee7ce854cea2a67e1f96bf894c6f9b59140bcefd4b6da87378794e1b43473e020a6b1a3eb88559f2eb389f5064da479d385d194b98ace1335a86bea2806661beacd25f501f0201b1115dc2b96b796db392e895e8aa148a4500207309a4a286a8be57c7bcc036dddd5491d3b424fb9057385291c7b60fc645f6dfc019aba011593b31254b300147df7fbe60432f628836a0d1b98090a64befdc063f8f1ba92a7d8cb5abec74c4b98993fbfd833499a70609f3c0cda681383cc3850404e9ae075c5e38ebfddb8316164d97e5a187c3d199f14d2d8aba0d3c1f9f214eaf53740b764449961228f3afcaa2d8e3a28456cdef40ca782a4eb9a247cb2923e484847a5dd3c1cd2c3630ce477fa7c5d25012933e1055e1c5b7a01448f7262ccbe908a4534f5cbecf860ceb5efc6d6b01fd747f59fb7b9f84c31d105b7d161f26b6f25f24840e3bcd2242cf9ddb726a75cfcd88c4370f7089f818766591bee4fb5a75aa682b5ed048b38c1787d042c813baf2fd2fce91182cea778d4fb29b1a64858149b4520f4b3a29d1b9144f3534f9fe41f2d1b9a76cd0b4a39d78b49721cac113ab9459e765b31e8905c2009a18b1508515638107d3cb0cc1579feb36a27e0be1527354d8bbec4bc5bfa46a04faa585e5e924d184e49e87b349fc190e6644a908842b42d362453f74ad56444993e747436229d670406c2519a34f951f7fd92fa752b73029917d9115d4a3a410b6e7d6a91776a32254d0bd7c0a14fafa404d7e26efe5dfde50fd68af9d0402330e5a31a5f73282f87de229d02c6bfcb9f0014ad1d7a36e350546d1dda3778e851cae7b5c7e384841e7739800c2d409537be7b65e1a678ea5d19f0067d5207eb99a9fecbe79bcfe630a59bb838ae1bc210d60d40858a7a77731cc3531eb24b8e868cf5d274fd1eea3d587fa0943aa54d0801be5d50619e9475bb46a7b3cc63a195c7891fe7417657cccaa9549f87a07477e74ee620df92fe748c87cf47e9b83b508eba5ee57c0c190d5efc35b201f6bbf3b2435304c87ca9b6942b95e55dbe99b2c64a1230475c9af95bff1a39669b983107829c41546468aba8898c6e518b29b3e8d227b7dfc2e213898cc8205771c814a537cbf3b5f13e0263866b4342824c99b89ba54134b2d89c1d8fcce04a52128773b36375d2f226a74986d5e333b2a597b68f1e360225f79e2cb7faaf0e287e4f9cde0cac02e29dac11a4adcb8441350e77364a0d46c55005c26156a87353dcb240d8ea22452ffaa3f9281bccf06c98c95cbb35aa24ab0cc2044bd0baf71a7566f93b8e0ab661f8cc258ae1a7530983a75a1dff2a34acb9d60e7be55f75c449fefc530f934193fb8d1a8ea7e9078f56a641d6086cc2a0806369118456a0b2c1f748e0e6bc769dd861c81a8c5e16fca782cb87f8ac56f662a432ac3c02bce192c9ef8bd4d9494a04359db9dd38381b87cfe426009ae8b804a7e79e2f4faa96c673a1aaaecc70f236276e6db42d73197944f96778c333ce8f7cf969d7fcdc9f4382a7d2382e523a062555edc572508860f56236be235ec7f3c983009803ecda04609aa3495dc69b582ee329e8f2e48f405ea9e6239f6ede607d857b8d95e05a2b6ca908af9454dab1b218d8c767a9a2b99e339a16b2eea72087e3cf259b67dd5243eb14d471be4c3f3cc08a719ab9da47f247796dd3cd28c6a12774fda1a7a3a64569a9134e4707ff7dad12cdb7198ac66d3a9b5f83d711d0ef047089c14a079a00ac69164decbc5eb910add204fc153354e6696ac55e3e657720270f26e532903488ca5c001843e2025cd03c6bd67c4d4942709ef95525d49dbf24227c9fcaa5238209b5ecd3fadae14bb54f25be114cafbdedc973c51f05f999279dc57844bcc4f1a5400f41e11fb7201c7f35838b691cd2b9a68d7c21ada487a181e5cde1179b8687daf59e607452a5c6a1223c04e80aa8a9cbd7e93fd3f9d0378dbcf7b229b614b4693769a8ec45906ced32acb5ba4980380743fdce6679c19ae0416031e6bd24d93f98a086ed00e02619b9730d4d6eca93b62e2179e053850cda946daaa6679ef53df0bf5e50ca478c3ad9c1b8fd6219581fe3a2b2acd1a02ff7d2b6a45af07e134328300c144ca9f6f977aa197be0c259a522b271870f82694328d894410f0ee0553d8373189411ef240ab11490fbfbea93b8bfa6e76157d121cbe7ecac52e16fac0faf989bb046fd9211760a987b3ef23c6e1b42d3cda36947afcae07c5c345b5b396de842391cb8439703fd72b2e78bc7fbfaa75b36430c5dc4bbdf8023309590580032c69bfa1a0747abde3c22bc9a18e418bad588537b0c2d197a7e7f086210dfe58becfa7f73f19c58809af15f3729a0323a6910ad34c0b54ea54131041fa0f8f52214df196d97602aefc5a34d4e3d4ed7e18c536a3cb9fc3f792ecc8739cb8281be52f6c26ef0aad48b7a036082cd5fcc8ec4b723bb8ecd18efacd85444c2f32ddc3c9c38235e68cd938284595ef6e51e32945c155be97d0e5d2da40fa79d8040d482c010f3baac584a1cabd4fd9eae5adf12e009b184c1f8fba1d21105af07098a582eb3bf6e3aa0cef06c2f29ac003af095eb0d851af5d314beddefa56ca48de121862798753bb1948605765e5f0af87106743f333c3b7e2116d33141ebb14e2389340dbee0756330375d80f0a234c40941e55b05e1f6937555105363516e487c84d876f9b79bdf06fea4308a4f7c7105cee45eaadaf818e808b8f80f1a72edb72488e61fd8f46e6317350c4d43e30c99032a98af23063a158b8e01070c96532f0f3f04bb5d5292ec4b8b8a9101a21ab82e7e36065986ef400698f5c67520eb03d7858596e6c17ae17c3c2d6768f565450fd08a8aba0ce98c282a4a2986fe7165077a176e1fb30ca9b227a4331e2b157e974792df03b8b6b5baaf8d0af182a81206dab182b99bed4e208e380966f13a78b363dea75cca30b48a494ba5700c6e64512875e3c439aaec9d0535d0b6db551cb3d2f2e4893679d15e7a269fe118a3178a60a3aa59493f20dbd7c5bb5709e5b212e6d0b2f4fde69db2ff84c0ca913759c1b2256829387084e052a5ee92de6f109d4692e1fec588d9c0acce1cfe0f1ac4e95c5e78aa23520bf7dd1f475d5a3de2a1c31163a3b9cf73231e3d23dd95e6edfc13075350b97c36bf70a164aa91274e8a84abbd7e53a3c4112e060b00793f379ea3a5fbc6944e5715e8d3284e34080fca99f69968b6f466239d0e4cf27b8652e944ef8f63320798e255dbc5838ff76e94cc7f1716a49e8dfa7bc69d8bd179da5daab7423e890bf852d2742bbc8de8095633ee31178a153e862fbeb62e5543cfe86c7781c778df8b45b60af030402979892388d93c26202a07d076fc22b57c4c64b9bdbcb989ec4748d3d04c2bb71847c289a563f92fe56353d01d5a69b77182b40ca47322f9927a911c5989a00ddedcc429453a9279e8290dd2a2e899a2bb45ddbf4a7e5a0dc6c97097add7de40d31104b8da8d73d3e881bc689a37b32e297506839c3d3667a528e72ff30a9fd176610ac29540809e7b443e29fe955431f6bd0ca6b6917bbaf7a22d43c4b237d881198dbff4b2c4d56ae3004070a24f56acecb916f1ad3c125a7db05abed53026d57827b186a8b76253e341e32e3b4ba248d2ccdf0da4e458d18e361221d98586a3d08fa9c2d734b0668566f334f42708e225ee243ecf8d9a4d1e47cf1e29dfbe5afcb9c75347f26c8fb175a9b5f1a3ac48716877e6e4343c2d89207799991ad0ff53112ddf6e3aa4f3a513c11a828107d382cc195fef21c7782dfc9574bd02c0610bd84d94eaefbbeca24fbdbd8876f6ea9d67ce56ce5303e539f70101c640889d1dba1580ccdeba1e3c3a7357f40a0594a54d1af2c555b9c1f7e4356ea130fcb4b1be9a530e71e9184cca392356416745a8e1f22f0d1c657bb3fba6c918dddc6271337bddff337981c9be259938913469fc4e7aaabd33db8af17c2a107bec02d6e43cd848372b822a51c0fe50e62965934e2f6282e63709263d68b6a1f1779cc0792f08a6a7d52d09d3540d8037f2897872160044c732c249accab0b1e2968f84678c41c4a2cf3e49f47e72ccb26d3ffae9db08d4f1411cabe7009071b671fd0a54855748d6411177ce57e3af56d009ebcc29fe44d170dfd7e5065555b2cefe49d60ab0d4bb3a829627c0f780a4ef8638e5212531be5b3c44d94e27943991d46f500e8d1617590eeb5e28e2ce20b91d6875bad26a47b42ebb8cee112689f564b121c77c9345eb745d060e2b85ebd0f9da416bc29a97d459c883ec12625a5e4fcd90511dacf86036ec0c05cc7f6894d13f6aa920487c9866d64474523cc5dc89069dd63833a46ccedab5e3fe240a94cb7bbcbdb0d3a5693dcffb3ff3a2251adcbebe8638f1780e3d7a4ee854e19e626676295f4d437c5638e7dd1f75706717c1f448a371d1e5491713160e76a08ce1d4c0438a5791b18d6d61bd0c48c2ef81426c85a518a095ee158667ef12fe4ca33ade1d75ef6bb4b8f1e86257f78ece39b05caa1d7106d5cd9bd438cd1ac195edf05a067cf13373ee6f9976100989c9e695751f186885a4e3ac9a026d75564087cc0789e8a7c7423d64669464a73748fe2bda0f330c345c93673c9b956d3dff818de2800bf3d51631892eb6b71d7dbddc27a714db499bf31f83eecbefa38ed53d7b346cb838e69b4d113a04b6ffdaf24f6d47fafab4a82eebf0b607617ee02a3afd048be959267df075a8d5ff5dcf397e1a8b3c5c30ddee29f626d5482a29426652c45e1d2fcef798e2da8ba2fe0a73cc3f63680c801f4b460cfec477d58bd3c88f4463e02065c959be25201bbd1afbc7490bd2af22cadc0266b06cdfec6194b86b9ae32daa47bbf256be89580734af9c71ddd7757a3196d23278f0b9552ce7ab33f9442fedd9740965dc8f6a8ebe9a78edf135054cdbd07b328ef66784c3f3f0a7e73fef18c7cbaa2c07b1be5624c792bc261ec67d9e611f16a9d46572b9e9483b9145006a583bb8a65e42410edaa8a1960190636cc0d0995e0b65f25068c5c40302bea891b5d7f6e0c287e4e9c6e6219fd2150d7f8d2367b1416f877152e3e38d2a04ff12ab5936d6ddcadb02560c66881bbaf9acfc6d732b2bbd84a95d9b970521cedb0065fc7f32ee83748658509ccf5a6c6690107698db12c74fe6d4802f81546f53998d384dbebec502fc9a6ce8f8e934d503209e0f08417a83279379adad4c94183d0ce2eea9e207e9292642f43d860252bad17f22ae5a53fbb8c48dbf34e85cddfcead95cb73ec5ca405f6520aafaa37f411b70022b56335ab833d5da78ee18b49cdd9344f47f3b44465eba0601988842730ea79e3754eb720b3cf8fb4156a5c40cd663e9bf05acf504654b6b9235a8d625806fa509af3e160a837747e25d09215cb04604bf3ebf344e930871517d305823603a9e262c253e9d9714bcff02b9c6cd5b98217864e77f282bbe05d0062f95b673512b7489cdfb67d1ef6a7f9d97b661fc8dfe93b064e3cd261cebc624a9879e7919888f4b8e68af49d9d8afe0ee9f87a51157d732f17e3610c540c6c7990d63c0e1582f5226ab540289c0b13e9a79afc3a54771c0a9e8168f1201b10f89588b9f30e2c2e78635eeb23b721a74f5c712b120e486d1e22a321b4d86ccd709cc6d06ce44d3b0a8b09bdc0b04c524957fc79498557a6f8095ec57ce825c2399ec4c158a3c9a02f3ea2aef3a1c39edca58d407e633b08318ce9b93d38ce0f7a0e2f2b9146891d94a81f571b1efb206e62d220ce30cefcdbb1bc3a666bf3a4f7418f230008640ef7811c4c03475f8806860fe0b2f6c02e97abc6270f278dc16faf8625734505f94887e605b38f2c03a40ebcef152144c03eb6fa2fd5b154aac4cb8f1d77e093e0acd633845e478e192261e39df9a3c1e62b1b219f3c4c6c513585482d4ba05dce26767b3d24a1c2e50d526bdc07af2feac3349ab5168493257321af3891ce949e6e85993bc7caed34fec5f29e237b170e7e5e745fac732f80b9a97ff6ee53366bc27747debaf44bef7aa53baf09d844890a63605b73d764330e8ad7d239056bcfbcf9c0988ce7e0294e897fcd88db38d909a64bd2c7473b4af23563fd50cf5581e172cabf88b377715a11070584eb80f252144f4081aac561e3a6cb51efc096e00ce63d1e22893d706e75890400b510d47517c4ec5827dbdcc6ef5f7aef965e600b9a1c77b06939b34ebc51259989f5e62b317efc57c075ad1111f10a883dbc0c06d5ceefef755c6a81b460c5b8a2266a765572755c2d90ff1069f98db6f8872253951075be7cbe6cbed49ac7977682143f24d31ade49b3bf6a231d1fb360b3ed6cb80234f53a7cccb2130101b8f905a80c873975ddb9ca812653a8055b5e16f8acfaf8d457281d688710dcc1ae483f18f672223016f9c31bcaaa53c5881a83db380c6e244d787e395818801ee92a18089fbc204f5c79353b0dbf3792382120beb8c80d08606438fc849f3393f02a4d587401b9720af5f21521170e40557aa14bf11386bcf646c3fe423f9e84d9cbce925219c3dcecc5200a6210dce68d0c99395428073cf495f05f039aee0d3143ca6b9d3689e833a0caf4634adb4158f5f70e7f1304840ba38f0be4d4f4a1e988e5159a47a3c3c3ad17059b15b3698e21573f0fc4ddb3c8e39958883ac49722c9f1b46cdafb502c958dd30369ed848429541711cac9d417c256646cfd7fa464c03b521fe13c3db92db7cf3ed6a775b865c15be65c4c362161f2d08b4e34dd628a6ebf0f8e63f0ae11c21d9dd8cb6d754fe2a4a758c69992edca3bb6646df1d97f35435617355c519b0d24147739bbeba1adb3570a71d3b53e37c77e2851b7bd968998959b078d566bd6b29cb9d5e912daf2181bbcea4b5031929d5c7a300ba7d6c8bcf33dcde7247cef8e978bb0f50eee20196b03071d119bd76f69636940d76ab77226e34131585aacafc5685c99c6c4ec582036091c25c1173e4cbe870439dd3d377267599ffd14e55cd39936e34c0a6a1ac20ca9b8460d074edb47a1fde1e02db586ba604cbadd2ab4f63452f9c1e7012d15305f013db669e6922b344c69549c4c553be34630262cf22229a3d5fcdaed7a78f1b82337ff6865c45c417cc21b62fbc2b2b9daee0d5d03ccbd55a789535d433c50b6ce51a0421dc7b7d4e3e25edc2fd86c5ac3093c4e8b1400b9e5768c91c23ac3747d64963f7a9917d68d41e0d84ea68947d35e6fe1ae87d1cdc7e1b691fd1b8bd8f1468e8756e10bfa31e87e8a996e1ed0d87d509721b175f13a715fb0329b6e5cc98bb7f098b2e7bfa93416b3a92b5f0a5e1fd7d60006131cf5ae6221e3c1454641a6f2aa311d3037a53d47a7ecebcc3ffe153822c8f066a5d8b0f7d1bcb168f27d6d70b15280bf67d4b488c661a9a2dd960914566bd40f30902641210ddad9461315a594daf388db42ba8adf4eb277945d08abd3d0a749e0ed7d330bcb351ace7045c0a592b10edc6633215dabca7d72fa6bc0238d509cc42acf2c56e2e8827746bec326d3469ca3f678e7e00002d2a9ded5ff47983d82a54f6faca56396ddec1bc9483fda40b436cabedee743f0e2abd15428754b3ec50456a7d1de561f65af5c667853ef73398ef479d5b6e043dba15e758024821c75cc9e66b6432f0c10a41b4594d7fb0785ead89e1e6754688e80284019e89d85d77caf965aaf3606e7cdbb0d41ad0446072c2821aca03b3c1560ccc3c80c991efdfe011d6756ea2257700542bd7317a49c5016607c1af2d45901a83feee0a7fdab706f372cc25e54f1bd64f5bffd431161970b5771b9656c1ba3f9a6cd5092da43a5306759821cebe8357c8215e7a6e2327d5b47e0bc0fc2a6a9fffd8250c93c8922f4c1fe5e05f918500f7e043c40c6ba04831aed1fbc0ac8ae19cdf05a1ccb81f4d56a77f0380d960fe48185e2d2767bde65ef80c99671d0c443929954cf714d87d62522b7a2027ec58ae4b61868b23c98ea76cc45700537a313fc481df5c1b7d8da12f4ddefd46e0701fded58398051b57b9ee262db8c83e9bf40ecf8bdb53a078a72fca8df9c1140a2adb36c3e9e45081bc0e0c0a09ad283ade9a0ae198d3498456e78a5c317425cd7b0c63af7992e258ca39f897a6dbe27dd0e287ce13ca2ec785d678a02fd445a8b7ffdb27a5c88ad93f99fe4951ae4812e1eead1e6c0c81e10883a7b0ae924f8025ef540cc29a1fdab30b2fc82847e3bb8a0f7a3286ef4e1547e0cef733391903f6a100a1f0cef5add1c1da4dbe3291c92b180fa31863fc7952a44eaeb3ccbeec5c7fafc6f0a1cf6a01675cd6ac3f77680cc53c057490fdfcce6da59d0cca4154636c60ca9dd01d6808f33878c5bdd474f83b4a6644219dc0091e1c1e4f3ddb24a0d38fbe5f7677c19b8834bb0ec9fefb61375d0693360b95fa397a879dd5723dd0b63c82eb28b812bcc960e8c306c35be05df86bc83e4a4ca07ee4eb523c5bdba715726a2e38ff938abf0a3a0232d332d4550ad6232c6218981dfc740d54ee770a3fec1fe0be2870214beeae3cfc9282d7790048bb8ce28ff08915e57940606b9ed0a3ca98d3a80b10cb6b5798fcaa474a101b197946b7017e57aee3c98a50ef692e2d7854120438ffe7fc5747e3726e89040fab4a199130ae6dbd223463c1dcb9457934a600bfeaf7f3b14fe5eec112b8eb467608af82336970ffde00ce02b1b2804606dd3355b37979da4a1b367d2083951ec47ebc29fc5b237bb4700a5975093fe65891ff2793564b1059276128dc8ddbdf96c3b19fc7eec2a460e34e730aa335f50e8bee4ee25bec7088cc50d58254560591b27b9a59990e7038ae2a77136b6db1de8f45fcb249bab3e35001b74561b8abf92ff8b6246afeb2b295bed456b06680a38d4a3edfd54040ff7d9f9c4f775ae5823f0b29c9f63c10dcece5dba96c753756def64960a65d2a37d81f2e88c517f51adc91a9ab23e78a7e1a774f07d63f2b14b7390f1172a1c30ce8b0e3966a2e5f4b5a1051fdacfe5930f4aa62d0148058f49b1fbf9883f01b2dbdb2bf06e813143ddbda6379980d0c050e33da57bc0bffc6b6ca7b32fc23ad5ab550b0eda0d3fbfcac71bc2f3b770f50d478065b93cdb277ad74495cf452a80a1cc0b1936dfb71f3ea65fb47599cf863d4909e2945b1b269e5a6b10a5fe17724d34881939b039eb3be881d40b0563d0347a4ef4ac293375a7e0b18e0e0d6a9bc1471645522ee0c4cbdae29f6c518ce2e1a3435fe4a9fbff607f18c81cf12a7a5bbcac1ba6abe0ed59e3e9fcfdf98944f24d6e1e8f301a064d7a8788ffda28e0029c638e84c4ee90e3df423dcae0ff549a39aa7ae12b652159b063280ba5400b9a4b258f525f122ec8d9f6c2ed9e36638fea207ede70cdda786e7ed6bda96ae7e57019c6b56010ffae68a68174e756e4c606d3f59e7b512b8740479073065b7ef4b31ee5e867696560ef693878cc068ccf236078342e26a65b4b1cfd8dfdd1bc5c213e06e08b878c52f0aaffd36c2ad6e8f9bd657feb7d69ffe706c4d76a566b6313e696a2bd7d72eac39c5cfa5a2fb2635d4e0b65bfe98a26f9494434151ee18ff4c07f072734733cca4435e49ac360949d9288fe606980e6ac2ef4927dc2baa609ccf043646547c50d563a47d179a698bb0350efaa61f8de1028415bd311fd50560448af833bab93f22638dc88cf253c0d6aab144be4222a82b77588d07690e63532fc83fc386d0047ff8cbe6c390b212db4bcf4044ef3b6388d3e7627ac8af53fc470350ec9834eb3434c806d085df910971208649f729a9e74e5e411015bb880a2fea2faece60522faf46fa325b055305eb77200efa9f29ade8149e095496045c41981d33c28adf5e34e603812446f678913f3a97c705a486705c3c1dcf21d6e03d816d29d7f566ad2d654443724a561f6867c9a6e6177b35bf273a4f7fa0f24a66794eebb88cbfba6705daf47a061439cb7087613937a2a5eeee5ef48e3236bf64b49a9650025f0b27c04096e30de1de7f959419b74878a36db121275c7b4b11c5d00907485a60bf826103b9f2205b40089be4ad2fdc2b1ebaa25bef76ee2ff202603a5ba86171d364a43736fe2bad57c3076119905ee351542eff0a40e5e653e3b2a39bfdca485ff7f3df9f27a2b3f5a5b5773195cc1f23f8121be6139d566b269800eedb23441b663c4a0d460a54b7a91ff3f253e93f34ba285b3a895da7a0417c4d5123aa03eb0e780fc355ef1b6041513c60e776ae36ec5fe13c128a13f2066b594cfb64e25eed03b8585308b89bb0046af291581befad6601720225aa2ae8b2778a899c767b6ad53869d447eb2078a5d0f2ec17c9b9e09651042b6712b9e73bee5c69b60cb378f0f355d925e3527dc23836e4396e47f600e89b0e0d9fc544405d23d2402a31583b339a00fae7fefc3d4f0cbf271690f24ace4f9659c7766c0f2e5f77a5323728bcc4bb040cb25e0a9b5208b12f38a7c6386095604e4614dc71657c53d071b27933e543cf3ddf43899969a44be167b8872fc45ff4c794f8f6acfa6ea2d316e0847e94270c58d9fe319f639878954809a20424fe6c434feb0ad6aa86dbd83484b1b6a974e2863a0b67a9ee82c02483109a426611eb6aa4f522aa02db1308409e3b63c5b4c8735cef998a179c1646a82c8df8082db241b4b2ef3c65ec30aaaf7a30b2da3c545b8b366174e68b1d3e45430dfbb987312064ec4a682b8c62fbb47be0cf631032cde574c5f71906aff937ec80c87797a70de0d60e9b4eaf2075316966ed236b1a3f1c7233e784802851b20b5c384046aa70925bdf8aba957a3ec38d5f14cd5916af83e2285821c597f9e02974a7cf67b3846eb63bbb4ab2d57b4b57ac4b1051adbd035a7e5f6c18dd97d3d5f3c7962d2434519a58b6e076656008b6ef9abb425ff029cd18377a9cf3155ab0be09ae67aa3f6c947d2344852acc7fc299d64ceb01f6b0c50af7abe830ce1ff96be9ccb8f7f93374cbb6b3807a36c9ef4495f35e8d92ff7e79827a218d5ad63f6c099005d212ffcfe517fcf76162d54c1c7091ab23b9f6d5bd394b1ad0cde54683e706a00e5f5a95a6bacda6ef4512e1d823233e9d56b9451f93c3fd87b4fff5419596ec163b2b2d6c8030e94c68783c3fe2b0e74d24934a34863d1d89ecb5b8766f055defad7edbd07b97d3e51de0abd06c2c175dc95db2cface8085885189ee5a2574a7dd19b62994ed51091bf83cb261459ae29a16d24b2fec89778dafbfcce04649030d9887d02c94ec9cba5cae869a8ca9f06515e043648d9e232fb084dee100da66248b87e905f24857cd39ad5c83482669b08538fb27d1b2e31d544d31b1c99c0f1895f767b52a87f1ceecb632b44ca30064c0ab8b0403a98b07d26b7aa1b2a72b0295c2c322680ce64eaa40c560f405016a6459d55c88bef8cf36cd416b7b06901abf3e0f49920570a48470598b294ad81da2d629c7d8087e4df808bd6e10aace2665cd4cf720441d393e87101327d928abe34fb9aa7f7671424dc977b2681751bee6da52fa86ba9feaab3e41600c8f8b8127d0f300252204c18570a1e96ef3607618f4ffccc0a225f9ae67466f34702299b906cf9004e0c9677f41cd2c098a1371aa9d05679fceed38623f99ad374d2b4b9e905fdb0100ab9b92612012b41e36c7dd451dc83d26d5c1c4719618a1004d86aabf9e2558ed4eddf0c5d80948bd2a9e02d37f75150aa6b69974f1fd4025b8d47051d91b386cad9df34b5be77e197726c87a7b453b0fbac1842e2848fd33da39495dd5e17f84142c0cad250277f1ab5d93f51b0fa064f6b1bb8a8ab863131479f626add1b0ff05409c44f8ba3937c289c418a5e5438a57628bcf082ed43209e16262751e25b6fa6ca4fa574028f4c0755f38f8a32c1d98d20ae327ecaac1892e27254883cb571933046fe24dc146f317e7d34ab387903ca7c83df0c06bfb2dade1dad954c9cea5115ff4e9f6864270d53f7eb115eb082f56a640b1b5d4f090a8c1039f915fde9aa0b84ee788395263e532f0d9b0cd93ae998217890b03416b0b90e12d3662703de978d534d307b988074fa49ab642f40f58b1f3cf84508e739b907034343a74cbab79c5d4c4e24166fb72fd62a2c621c904c76a25894286e574b51b874880941c44c7de1b703cc8d44118c22a0d4f88b78f36e4528302e18786bd80840c76022fbe2742ec5e8dba7e382cc340f33861c3e48cdf4b10c1645b11579f112e2e7e89ceab54e72c1dd041bb021d8327e7df54f7f0aacee4ee0b32c8bcb09f7e099af8a13a71bc3257755ff5dc2052d2fb7f8bf810fd2c53b95d3ee7f6d798d664f748b845f06b87d1ad144497e4637280eec11fc9dc3ff1afde9b8f9d0bb7ed7e850a91b4e137ada1451d509a81d0d1afb031bad534dc13532869fe83d9ca7f6e0c20166be764f38a19c209ac67c50cc56530b5ba9fce98816af0bb8489f120d9a5a46fd2988b6db20fd675bd1f1f0db45cc5e0a755d50718d1ce92c634eed2bfd7183c91f5229283718406df90376e03c2f9a017f6c83adb4f11e49b8ff43bdef32801861f39df22a4f94d224a6618355548db062c047294132d1b07ff36d6a5a0df6393054a908211a1e4000616a412d29d671ac072b04626f6b25027c8361b9b2d9a37cf8fd406d2a5fb3cf060a52c32947f91182b40c9127ad2546530c600359e669c883187d315040d3bf0c4000d7cb914ab56ea1f7d6935f9b11f1e46382cda7b2996363b03310fac56cee88524ca030a0f751431922bc27483e82340f801b3b1fd04e6eac6634fa7fb357533c81ada9e3e22946c68f0d413e40928245586d96dfc8e25023d00ca123ab2d11bb35fdfe2d928ff1f7486d11c84445e218757675962d08ffc82a7a5ed142a185c0006f2d19773350513e35032e12910bdc4a24a2109b06adfd80512f6980639f60ad73708b691098160b1d8f041136dd00e47e39fb86247b25f4d9dfadcb815e356f5c88e346a4efdbc62b7d7f4dfe0c28c49dc035d4981d3e4877d770690f3f43f8fcc2a70f2d10af6dfabce3c1821efd2ae6c6c79ab471d83c174494274acddb8282920e1e0cf91d7bb8e6ddd482f623552c336151870e5691936fcc305422669e2ea3957a83460472e377cd41bc1efabd70951592f3c5ef821adbfb00ed56575f48155acdb6c24e9b662bb53e0b288bc46325620bdbd5e6b2ab1b58e048f308132a3102d8cca30a473cc30f4524e4d4546c3027dbc0d9170e0bb93acee2a8d2ffa7759883f56ab4317a854f740c46a9da86aff34cab314f1f2832b08846dd24a69779720331abbb27964b5091b7e31c7a10ad88a6a6f7214cf0fc0eb203a7faf7a8f5fb179473963c49a9e0ebbdfd9d6cd6d0103dc89569bd418216523f37478d2ce88ef5ee3f6a5ea5aa66c1f327b0a28dd829afae363794b6bdb31c6c80b4e73922cbc2a1f8764edb356a837216fc75007727bedcb986aae95c1e93208d66960c5d276ce11c2fadb92574a2811bf79632a9164606d0761f28eaed493104addcb5424db502cfb375e891dfe2c67bcadd0ccb5106ca512f9af034be6b30a779c6251fb2c947b5b78627fdbf97b1ceb13b783aa5c6e7d8e50ee4c17d1eba2e5b9e32b5fa77680e1a947b145a31ecceca493632d912d27b6b2ff15fb9a8150a8cd1ea8ca314e8e99bdbc06465fc0468a386b1ba06e17552991c556e31aafc7c806d12190222079a2e357515ff891ec2b4180967e6ccb4f44222f5858985169433fed5892ffc5bf7dde5b032db39e12a8fca57464c3540cff6cff4b87a174d3d64df50553c434d9474feb812de20001f3e7a60349468d13aedeb67ea6d4044681ba6d9a8ade6538f3750a78674f08006b50d7c011464a592932e197d01b0af87097264b79b3ad5682092e733e11fde55174a34115821ac512f895164644ad1829f851289e902cb5f3801cc0a4c8ae6da9d639ec5b9ac6ab6f3d490387aa3020668e64dd074e4fe9b409e352a4b58b07209350fb5c333be0aa4f7738bf3a140800ff5fd23fa78c40edd16fa18ba7afd047d0ca3bdf0c96134638f6b8c535435050294ce6a23af9e5f2d25d370d14c8ef698d426e464c0672e0305c058cc0946b0001adf04c5f1bb99531f40c77e997e228e778712bdef5c2e596be389064ba83242612ccebcbd7807a603ba73f8ce13b6aa893c7fb991a1384334da06f6316b3adeea690561e7611bacb116275defdc40fa03a2325e39d045882cd684e15c229fb2420b89fd74fd2c3310ba505845e0490c609cf20ebee7f151f0ddbabeb5e6748a9b13098a0a929cfb1bc626f4af1931463f8b190769380131bd66fc39c181fe07306c889705d8f21340ea59213122599bb42d2a34468e28bd699d4b46419499918cb2b42642d3a4fa090bc2c43292f0633a4eedf0997461b6f8d5d4f4ba98dadd575bd543bd3b488b60e8b262db43a3ee87d781631bf18b5525e971faebec95f960d2b478f4d45a4352d4093686894405758a61847d3aca5054ea400a86d680c9223c54c83f28f6e6263af40275c288d04aedbf1f0d512028b01f3d5b76f122bf0337e22f075eab4a640c44f19fd7a84ab7b4632d81296611f0acdc23fc4c7132db0d1196693774f3483eafa5f3d67166f4ea714db4552b3ea33d2902dac6b36205375b3658c7f3006862ad4a9e0c8b700b045171e18301dbd50f71ad4dd23c2b8801da8ea6c2193841f9d1177f0e362437b7c44abcad06bb4bd59f35f3ba4143f866f4f8b93c3bbc7cffb52df2fbc2d768831621b1ee111dc8220c81471a41a46df38847255deef8f84a4e662f7e4b22ed6134bda0fe62b048024ed553e416b2e47d2a6cffd54de634ea9a37d68ce82f5e8541e59324737309e74d6b88815a24220bdf90ae401b476b8c6c98d9187fb0f7c1cfc79fb2a79f59575b55fb574eb1091115425902493d0b283cdd0ed51a247f501d24763373243998f19b3b03fe85cf8a8b39a631e3fa0b7d3d837566fdfd7a2c420723aa51fee62c80d618d0f79ef6baa5aade9fc0f5a4234108df1b039d38167ee58f1f9e2d49e09c06840fa6e44404d5364ef8379b4b884f9b8114f59994ab646a4fe54033c65afeaed0b31a717eb25c930bb51833b8eab4757afbd0078e08305f415744798a21cb245a2c0df3138a5139a055bd0b221665257850ca0380ded7aa2f1da493448b849e9ed0294887b9c5319985e634eae7652de49721144999d68d29431da3a492c6b13668c7eea1fd804945a26ab3716c441a4a04dfd500474556237b30716162c117c2937d5982f6c99af0d9af272a0dc8b01089b5468d044b761259ffccf40789246be3112b2304e419323b3ca813f88e0d1a36068531610879af748ae7491c3fb278e796c0eb9772ee1cb797d1061462b73503c8f0dec6429e59b58b509aa16b7e5f7a819a0252653564d960b3de08e3670169a1c506b12e0dd16087740ff77e7d6767c3604297edca0e66122011465e7799372028bb168c1bd0290fd7e2ab5f25cfaf46413ba711ce6bd84acdceae46f0f3ce56f5e2e5e9637e82f17390d35d04f0cfa20e81860e32410eb3c5ef009da2ba3969c79cad083291d1e4f447fbe6a83d0b11b1ae94557db9693b8bceb28ab74506583082d8b695eae864a83b9f5bdd0a3593fb40e82de1566b3662212ab08bfb95d18241cd3942c32eb99cea9c7c5c6231f87b6a4cb63972fb0369d3d668b6b01098201547930abd701030b2af9b13640a41b3dc8b5076fbdc34db4a423ab8fc7024c56caa38be860267ddf218f42ab76c79d0e64fd14ba2a808dff9b8bb5244fe96c84341b73649fdf2ce71cd7581fb34b298a78f11a7995ee9c7e88bdbc054e3fd5557604b4e1cea8a42c86d18406472434e0513a87c33f4f285cba2f752452e2431ac2f718dce779491a26be2914d4f36ecaba8adb389176fc24b3c47e9b6cc65c48f5a968e041fabd5b830903738de3b8276c669c7001fa3d53d35067cbec8b7298fa3170a1649ad2779750aaf5a8f01fd874be1929fa5c231385364f272a565e83c6dc00b7f4f61f579c2760df39020b05815328b5cf26eaf3dd6e98c6c9dd3a271e16a6046c5c80d869273859d33b3c1cc556228cc4ba3cfba4a57ae710d812ffc8bd80dc3451b582d98dab19c451dfd2aa529bb1fede98f80c04082db8f0a3734adbea864e892f6242331f9ce355e356f55056b9643208cf3d4fd2846fb015b1142a0b15dbaeb539d7ef5900069825b700e530a2dec4d51a2b8be5de8eac432153db966c984f35164c88b9c0a698e907ff82a9b185f4a0e345feae08727ad02892ea460ee30000bc818a2d330bcae5c4717f054be194693b733157e6a6c414e2e03fe4250e39697523040a8352e1dd4cb1b0f053a834c16b294e8ccaef9f3cb5191639a6bd54435943dbbb398f4b0f4c51293a678936b0cc4486953bea77645e0cd1e5e19b09bcd1755ff5f00a9e6f4ea089edcf246a8fbf3956a51324d3d6a1a023f8816f82086ed560b0ec9b5b898c49a19cdf56303a2529243a4ddd325dd9d0b76af492cecafa07f7bb1a6b1a4a9c37a85266c9b4703ba0db122bbb7b7ce27b0540e9bf4d50348b51f0ed50c62d0c0801dcd725941ecb9a9b518def1049216500362fa7d8c908b084ece5133d0f8a6a45b9ae0e0ff028f11a77bb749e57788657803333f1a1565153284d0acddcb7bc30b5de9f7b2a6417467256220a9b28686f31bd733aa0464702c7d7a77adfc4bbb4b89ed675bfa1418d7183c62dd8569b7cc36fc893718ffc6e857068cf5e388b6e319b2a2277bfcc64bc6d8c5a6e9ebbb9cf468f997cb26233625280f893d7806fc2e4d21d1a4485068b164fe06ce476afe17728a843ad5511a3002046a95da7f6f16a4840bfa3355f802836dd4bed426695b41244202c2e44c0120321e09b8c8430cc407c1222a98f92f47cbc24f5f8ba1e91bf3d2eed42f63f914505782e96c28a93db6a39308989ef4f08786f382cc5c347a9098a0b5ad8f4d8f8744f042a0b4816eb078c524efea8aa5989ada459990f76423044ff69c5d81f297a836d458404a6581da0219eb505f8e4ca098ad418c9db26cadd087388ede5844794710ddd4e2d84a3565d00ebc6eedc86d5155d0c6d058dc6888ab874e367ccb5a250fa5ea63cbaecc92554eb355abf71ac5e785b3c65a531e12e2eb4168c2f6af7c2d56a1b1b334b859aa34be2d4d946af384428f03e81dd1b8433eebd16ba737ebabf5399bb5ba58b2d295c5894307009b4e3d86825b8bbeba3d8d29ca3a0670b940fe03c9876ea3b8ba8f9ca36fcda244731de8ef9d63fd254ace177befa27fe3147ac4db03cb2b39ee0a9c444c65621125e0337034a989ce3c1a7fec6f8120a0d3a8901a321f6e32b1cbb36f12395b3e65da9d2a83931ede105dc84232c0198010ed7deb80297674e840781f1d2bc6c5cac35d3e19a04c753c371c59f3f50774c0dd8ed1104d537b0b93ce90e0db586312b084ad5a0987b39482dfc8ff2832df72d15ee7e8558c4bc85cc6f309b28c95287114f0f6d8f729e8839b4a0a767517bbb0724dcaa51ca752461408d3f43e26e7b03c9c0eebad43c23178ecbf01590571d2c369b33f21fd9312e9a22f19846183645816188ba2a998e902bd650607b96c1a25378bd828ca472652dd8a43a75fb75460f3a80544c205d6e1a9cef0936c993532ee047d6e22642a53e8d6b91f90d35f99828b7dfbc5f0f09df58ac9ecca005717a98b602180ad5ffa349bd87ee17374a505ca8897f2f5cdc64d226504b140d536bf1a061a1c44eb986ad265229291f73cb016a7afff6a50d94d42d42393ca6bea6e5dc8d7f808bd1ce30a44e05e65f091c06f5e59882fbfc9ac8a44631ed09b60e2113ffd3cae6074e3e7fee78850031ac14bd6be02ff68c2e8a05708d7f8c9d06ed8a2c44e81f06206e864e356c106f533496a113b4df01b8b2660d76e9a2dc95d9b03bda4d8c1d0184f5a9bdb8e00db2838059174e6084af297602547d0611a3412d27456d31e354041163645104be896d1c54e3eaa1124f5d6842fced8d43221d51131067a58f3b061d4e71b83e9d3686273f483bd2cb929513bd9389d4268c46213e3512e931d2e30ef1dc04ecec519e4c7557d18b07f75fd9105ebbdd32379a2774eb05c2664f6018281e715661222d26e8ce34d2f93c7856b9204492684f3c67780c722b517851191bd463debdbc0bb021537ac009239d87885b52cfcd596f6168745675e8aa216013c3d95b9627275a2cc8229d653cd7ec5836138c377d474c700bc918f781c76b720e6a450adb41721d3acbaaaa17790ff3592d37ff13d501501122fe5e86b0f037482c50a03944c8041cdc1bbbfcb7c715253467d6ad8777be71fce84bbee07b8b395ea496c26b7b9200410f5ab9702017d217acb6a16baf50d23477e2d66a633f5273873d7612952f520ddf068e6c371e6f84c3dd095c47ca6a6ab34861cab043bd54291e1fa43c7ee28cf1688b51aaff087b812a3a91efe0f10de38b695d91a715788614acfc5da5e59123bdc59fc00b5080f42ab61bcc4ce283768f2f76189b14f4f458293475e44c0b6a86dc9d93907d28dabf78c22175150a4b21870a6c7d5172eb396dbcc18741341586f6f23f2dc1d08717c05f3e6b3208637bcc43089561672228ec07554b6a70cb5f363605fb7f81fee121b581ac368381b0314bfa0b7ac8b7f1a223de52a766acd7118ec2c9eed47448ea37a14e9cdba691b966715fcecd950ed76f90dc170d21b05da9022370f9b8bd34479638922e214897f13094c6754292bc2a8bc5cafa4f10ef0881fe07404b7373deee45b33ce285ca2066320a6135100fdc52ebb70f20910e2eeb8c0ed5da681491805f4ff1d4141e540babbbe54b22d035d858f4fc20efdb038c0107d8d8df673d0e9340e7b2004dd15df4e8e0f256c7948981472d1016b634b24528c7fada18785f345424e34ed70fddce28afd15eba4bf7995d542702275db0538e552f4e8f26e757a732c578abfc5e4b925001c766bd1911d3a45ea0fe3dc3fb1bc125ac261b7162d92951d8694388ef093cc30e9a04a48bb0c47e436b18d8d78f0d8fa73029dee3971c1162e2588c7d5017275105d76df19457a1362ba5b2ff5ff7a83ca80ddb0375d7e79614a073226addbf21f792549935e0e587265c26d0370f40cda5692cef5f7abf51be49257cfa35f1819dfa8bf181fb412610074cbbe74dc10a179745783cf1081f3668f8ed5991dfa89522c29236149e8f9e3f83b0b11799d0e024cd2154867fa6a0908c4a94257bbcef3239bb49a6d906d32f749cb05ecf3412fd7d70d1339fc2054a5f268286e5add17c6149cf26b7f50adf7f9fb41bc5c61ad3a53c1e403ca75a3baa307a11a6bc452026263de26433146af52e195b41f146ec1134b29c09e8530f977f6d39540fffe4d43f9ba70e7dc68909beaf62452c2f991334cbf59633b77ce46313353843bd1921726657990d5997e3c0b14636a9471a992af59990530c2594851046c18e6b1a204431e218bf53de659824f632547bb3501d94411508d708cf9effeb03208d9d45a8e56366784cd31951f21acb9aa6110735358d511723d381a608cfa97dd0f30f13e280f152ada4402bb5e52fec028dc8856a78660e7ed8edc8270489b6a3f268d75692289a04407accd469d6a8718b284012537448a68d3d32bd35d56605cc02a3f0ada03b6e47a831acf10a44f2eacf5d4d5e0d4bf0506d83d2488b2802beb0e68235ddeb8e22935ab059adba6f804bc795e6bb4e81d07b34c0d8860a11def8a9a72ed562f0b3cd40ad769c9325b8ed6ca99de289b56cc7233de4ae2e206d826f6cac7f87fb76e327f5e6fd5f94a5aea2859d7da84168ea069fe5431a1b5c9c973ee55e65412d2989bd0fbdf0f565570932bdbb0adc86efc070e2bcb68e6263fdb1108c41ab82a81292fc5cfd8ce2ddacc4eb57d62ad4cc625dce069b668c4a3f3dc9c1c3b06c0eb514cf68068b29e726a0a93c7c8b3ab0f60283519695e26cd0511895379568103d0bbef948221860a59ee609ed4c07d6740e0582a1861f2d0136ce762687188029f83eb214b4349cfda2c3910c5f67ad957fc61d32a22d4b514c16bf59c2f51325c223b3df1cf6372fef5b43881ebf83dbd716f1c586909706a8abb9e78f0f504bef1ef6b61a1fbb6c0cbc411868d2e1c405813e74371e1eee2afdad28193bfb315e65a409c1b99c27c16a35b539a0ab328b16ae416472d69cb1edd3d3893dd9af887318275350027b601d9fcb6161a3d087517b9845fe06a89ea5183a21348e27b1b0089f0ee310f921793b115d0b9c91c8a6c760884d029d7eb261970401b81780c64713215cb56cf573025e1ba9fc46aff5f59fd511542cbc90a48f04571e613d1146b2ab924bf28ceeb35c05232d9aef2ce5cdfe1f6b3249e42e0c0fbc66d84e06baf0aa972e1afc4232dc2a28f74af23ea0813daefef4ab40c879dc2dd8d2658155cc3c61dc8032dd2286c4c6cb09ce2415c02dc90ab3b64e27a5e9d83925f1d8021e5cd633fb11222035bd16abf136f7a685d09c3fd7d5577b43887e294715d599daafacb10a3d39b9f50652fe400bcd46bc79ba99a113055e74618f55f4b689ec8a749d7f3441a6d25125e8c914ff55ef4c2b0555895c29737d861419001439ef57c79b3cbe60b111dc8ba9d2ac5309897ae28e3f2c91407c9aec9105c5d7931300f160ec6d8be8e8915d3ec3df47b30bbae60db6b6a2bb4d5215ba2e70d06eb8f795507ff4ac817bd902fe355115e6c54edcb5105c1be1b623d487786d5b14111a4fd362c5c0b6ee7ae495e1e3a201bdc28f685a632258e93d03ccb42ca00a5775567f44587c969ca953572d61d0dd41421b0b4e99874c2d4a25fdd9094366d54cafa10e30eab60b2f69a644a280236dde4740c145d9690a486b4d67a33e5a11354e1c412c448c49c0246a62e0eab3e1db9422c2e76e9a5b16d9901d304bcf96eae5871128b704492b2d457c14b4ba7a2058d56319e77fe2d0d4da305018fbd6baa9a96e68341a4658fcccd28b1354d5aba06406a7ffee99fe65442feb7a14cce72c8eaac90dc27fcbd3f7e3a460dc1ba60b9a64cd04b9e30e9b4cd1b413bef0941994e082faca72171cc3d99a0e0aaf650a59fc6dffb0292781982f24c50b2aff54f65e8d77296fd1935aff3a01bbbc5482fe9ff67846fa178d4a0dd1735f3951f3118d81f4cc0143b75bcece964ead264a30f8f10381d7a76718d1e571c19b0a399b0286125e099a6e3919a0c5ccd4405c2441b654c061152282e12599a99e84e17100e38c68208ee7d1a661dd4358cc89bb686b22890287304d490be04647cc724b8906d5f73f7ae27d91820b5c8ea67be1c13ffd8e0a02c4a871793920ff1a85a72e149cd1f4cb7d66f56c168045f07b2b183427907c94e1e39edbb177661275f4cf2e520ca0575e2964faba659368fba02f24574bbbfbe530aeb1c477d07912ba01e2d2dd3d33b898c9d1e2edc1522921a65184ad4ef0f4e5b1926b56641e664b333d44427dac9d2bddfa4da6c6e7781b88d7dc847cc6529d207e801c7868308ceb040b663440d050a8826dfd2a9382cc7e180f30a1ed81e9e87bb969fc92806391b7aa9a651026d8c02575bb2b05018f65e9aa0e096a1932ad5a18658ecd4848b32891d10520936f3231bc8ca6207060f7ea8a42287bde23d728b2fa79c165ace311d1f06d8cf84c102aeddcf8469f187b810af2a324535a0786d5931dd6671af3d0ca266d8eac63c7ba1288e261308ab4b5424191fcf523387a229a414ffd1a6eeebc1ca5a3ad8ddc1de7021489142f5632ef31f02fd63a5762f4ef3be929a076d68187c16eab730fb43eeee5e8d9434db1bb46171ceec0d599caaef01f39f5a93db1ebedd463a0afe505259ff8c5e158e65430ad0f44d0f6caf0f28db26f2559a5ca95b6df7cd6ff4aacf4c50232afe0cbf00e79c5c06d51ae2ffea1c2978258ce1988218e5da345a65f3b5f4844a9c52de57770f4e6112f4ba9e643808725fe865b2c04ca4a1c19d4ee40bc5194e2e3e6d56ee79c80a48273ed909eaf97cdda128b006b988866824c9cd5ae1ef98daaf4403251aaf70d54dc314ae2b3a150ef1199a7be7048677be9f3a830a543bdfea1489176cc112b3c17b71cd6a5a9ef281d4edfecba1a5ff1fed09359a622d1ff1e919b2835383ffec716f1a91d03013716722d1fa73f815a1e20e2e9d48f1b14ea21bd3c4149cfc8eda3b30055f1310f616cdaee60461877a7a20ad1dfb8b65e6821afb8cd986084725d0163c3497b1af9a7cb82f9fecd3aaedc4f5c8ffcad585fed18e0124a23604a4d496b7ef05305c1294b0705c8231bc3cf8c7b8ecfff9dfcbd547fda538261334e5fefd83bf73763b377993080c331f7c3d092f9976189a156b37329cf601725975cd1cc503a3e5032c9bbaae2ce664197d22982a6be5b52dfe77b9905942617bb7703cbec3a0b4865e7dc696afd0c54900990609904e4383e645de05590ec5dbafba1a97e00c2bb108372da63c0c6e7ce49bc87371b715a88d4c065a9a4c38ef595774e98321e0361e73acbe793b6872d65e98989b08c6378dc7e2d75e1a041274dc7a3efd436f5e018e12c8d0e44266ea2353546ca5e77bae8177ab5158b1d48a40bc7f88b59d845755fe39841c313197396785a8016cb5eb23183698139c8bc9ae4875461479387b0cb066a0e198966007b5642513a58adcf97de565573059597694fb2b2ffa9954c0fda4619d8179ca481ee50bd5cde0d21ae867a640de1318c5735860843548d1866a358f5ca10b5bd8a1640544d78aa93ab76c9907d99962a40a4cdbc660eb6e07a31dd27ae9f7364657771996947c04207734e9be061c0c925fb9469e1636f29e570d6fb7b28a01e947e403ff88bfde4bb8c34787f27dc83d5427fc32ce5f4da8213d5e3cb6c678bc8e76f0233ff20e3edcdf35dc2f8af4b912b68ba155ea0a95bfc6e9d962c01e17d5bfd0c2e6e8dd8c55489b997a1a61215e8ee9f5e112c091eeed6259c03473298736a1a3041a3f017aa0db11a572852c911b3e32733f063d13df5c309b81588cc488f492bc32035faa1601f9aab60e8c9b1c941bb25882f2550253b7f4d949933b7ec0affa1224de9f8b3d607e59fc53ce550c0a1524188c017c02f80c3a2e02052885914ce4b4e6113fb4820d2c0b93e9167faf1a7ec2bbf0b618a3ff2b5f6b1383baa6bda386d4a11894887dead6912961fa4e734644ea17fb03375073dcc083b2448eb0a5da91d3345ab77512fbee06d32186bbfea4d7b3954d8d33045b77b5a6d125ac8a3aeec24a44fbd90fb764b96d01d8707c7a6a4023e1a8552c86f9c4a83492c0df2cf66448301b41f90ef19a725d1de0b4170eab5255e698fe17cb9d4c084c98691d6efe1cf78695648733d5a275c18f5f5edda915bfdc65ea13565abb8caa7b2d7c48b968fafd7b16c5617c8d119cb9efd58c9f97b1c40695b98d7599fe102d2afdffc2da3f9de2523197d5b278d6c3d9765681ac47fd0042c9b65c8682330102ca0e108a5ecc25cf9e8321beb3ab748050469011006aae8e8ccad369922d30ffb42056d207b06941c7a9b4c502e801a8cfba07d771ec32983da162f58683100c5f20d083304a8d0184e0d8f873ba70acebeec02723431a569c749a6115f9518ccd4988571983bc5c57292f79068d2182f39ce108af3673a3e5815d5d239d731a6b3344a00a015ecb3301fd53b37d162a2b19cf532824fa12b16d5bbe83c3b0ff76d7761c4264b925881f749064080a52a3f2268d6e92416dcf159081539308c19fc78e64dcbbd3aa6a8d6dc831adfd8e5a168ba99e3afc63431ac277acc08a5f48e71fd1569778dfbf6b7cbed45c4f6fe19fdd518b689895d19e530a92847c65e871ef09bcb0a4b76f0f32000fcab5eb500dab9780f67d453d6833e9c84242f1bb1f8dd6541f0255d0b85443a24ee45d287dae4479ae7a8f12834d688d4b0432e0142483e079978b18823ecfd0c924357dfdb681dffc4be8d733b0a8ef73c7d8b020aaf1f701c1d4229f529d78671846ab8882ddced648fcef5c03054bcbf07beb798218e993ccc468dc85105100fdc3e99ef6e00e21180967d534c83f2e4265943e6f7e82da2e80e4859ed4aa92e4e4b7598e17f3e07b4bdd46125b1e0d2684072e985f7287577639fad96759e05182dc12fc327d23ea8728556422c306e4f1c7e44edcfac49abe07d99abe9550114586387910645c72090f5ce50f9b9620568024100bbf267fabbc9fc202509428147de0f087e0716f148c3d124131ba614f3b95a3f98eeab5791c4dc1d217232fed286db28f7ac7e672ad8e01461182de4e4119457cf985dc21ba5183a9433e89fab148be5931e41ec4b3a2932807be871b0ebdfa5b6d0cda40b24b9f4e749ac2c736fdd4b313219e485ffffcdb9f3efcd1df3ffa117f9a7b03bfe3fc6fdbff5ba95a772e7e8b79ab823c5292d6e46e9b9a9f422923ba6f879763d00df711007125819e30162b9182c2681d3c6e14f68690a64d452ff789fc136ba57521f2df1f12abcc84d1d4985889893a4df9900b5b35c4ca022c2ffaf3df3ec27cc579592655584004d166edbdae063c36683aee7ba3d459764ed0a92eab5485f2ef386f0b97cac56b0a231665b8cf8c80e1d6da206b61b624629c6f43a4f52d8d2abd0251c9de0db5915838cfa79810cb4bc9c50fbeb98e894e38876a46e05cb1a4fd9f029724e3d52c99679070420d5e7cc8c56861d647a924f789ebdeb21a8525926d839081e87fa71ff4a30547921243cf37e8433fdeb2f27e399a3121ebc763fcba0366be73011c1f9bd233f623f6d4e83f7200d95fea144bd95509f9b9722dab225fae36da6ae6f8b2501a3880fc80f9bc42b729e708d5ebc5b09af32bc570014aeed2cf654d517b55020d548a3971dcd30a957fe64068bbdb3dcb897121f4273c6190e63b4ad40f6d3ccc69255baf1a528cba2ad9638723f590430bccb6e2e9315d18f4eff43fe271750b54acfb9dbadd6f6a94d562f309ba98a0ea7413e15e3399f83bccd2107b6287a7bafb52ecc29301dc87e53a8f9e29c2d3a86c42dd710094eed0997d54586863c90b188bcab22d16411d7f1a8115f5bcd01b1a54fee0ef53581c323b31f2422bf5fee45b6132ba049ad6f07740150aa92b684acb67ea88a70a55746356065af33cc9ef0addef4b15564988ae0e57287a6ccf01d30b825a123fbf16cb757717610decbe47db71c5bbe108dd47d2f55b5affa10d28fdb3ace4c8ddf2d54655e2862f492b7187558f063ac0c27e507037941ca54ac7d8ac05dfd3b53fd622bce9ccd0924195b1c7508d4ca4692b0f30a5b81826fa68764c0adfe01800c9acdb487125c2f3bec0102f3cb4a1255c960268b569316563213bf15ff43fc5898ac43da1696040f60d6bf4ae3888604c7a4827fb4bf00973fe92c8ca3f1bc26fe5755c7eae32becae7703b0306889d4887786f3393a511a041aa00dbb2c140796e8d7233aa0da16cd6901cc65c47d80b1b3302426abbd339eb607cb837604d7b543877460ec2b3daa0160a3b4699c2e48b4ce3538af966209a5bedb4b47f9bb486c124aad0dcad5b6cacc3ec79c9b618465fefb43e4c7302e2d0f251411086ab94a1408e98a9440fef43555cebc5f6a3bee0aa888b0f928633bbfed3a1707534ba7fd51c331419a529b01ca6419c39a1d97675bd81da143d4d1a4fde29dc464ab1795edc2aab3d210beffbca5271ab44a2060811cc5f436c5a1136a3f09f4030e1823de4ebd7522d3c0562a882af68e1729725fa87fe8cc99d8a049e4c662bba2d8911afb0f5cc04e6df1b7d62520130d50eb74fef20601e6231bdfb3e4d31c0ccb6af4e629e8c11e9f89fda176637e2cd76a397dc510df92988fdccaef800d2c66c52b947329d3851d8be94a7da0e605b92c87e314d7a2b5273a85f060378858cb41267d9037e68ac3e0dd25a37caf6efe8ad72ecd885de37813f0f7144eea69a89a28e80823b3ae0499b1a67238c36ca32e6a5d63bcb8164169ca7a5232e8d96943c533e89a29174fad0b5c7ac1bf5c3a39252876c8b9005672531862c19396ef0492554b0b60f02e751c947a262fc4f0554c00fb5363548890420bb2b62291bacc0ab1d41468afd055d267dfebbdbaae5c6d9722d150c6119b71e3ceeaea7e3d5d3bdae44bdecc53811ea6d7b566fbff62c1431caedcf0ac8d3025da7f06b37ab96c799e8d5b216b0b8a5572f4f128096c301ac31bd161e69e0ef2351b793fecda07da65eaae4a6410f613dd5af980fee5384189c2944834dd7534972308695b98131ce3ae2355ca21ec079cdf26e9540569e8a17abbdff29d8e8767f1ed277fac975c53319f24bb45262270836ec3ced4da4413ef2ad5c8b34830cdc2210a02b1a38505d856151f65a80ae548a41c68599b46ea3595713455958ee9ff654f0adbd9b1859bbab113ea47a7fa130b295f7d14c4df0e6f54e7c0a668825bf0e2468536e37cefe4b73869f799a5bbadbb386b78c49db9c52dde3c48686a2c07695aa0fb8ee053c9f21813b90ce9eef839eba48b741709aad5379b8c347c1518d1ad0f017274aab7e0fc7739245cd122498ab221b29298b9c9d224581a7189383a6ea608ea8efc8c91dc7ed3fcf426fe9bb33c5720e5ed50cdd38e162f9140c0e0ce8920a5ff2e3a64d8fe20293cda6b1dc9f69302cc99dd0d3c4ed458716ac95ad00035fad542f81df05d11296e6a11e43ebd948f6b1d2eaf743732ebb12f317c2a4bb404ca71cfa58e9da57c782440df2568eae8db484c39cb3d1930eb2497e9fa615b430627dbff941700a4f86cd250a6ae0bca814faa921ef384aefa25acf2f5013862c9268fe4e596ce33fc6a38508b67542c877574f377358f1214e797e35f2030467a1a5573e2e8c6810b3c09fdac46f85cba7d0c929bf071ad9aabb141d2cb6de6cb74395284ac33162b709f460125ed077c769a2ef5e8bd971e778823b6a18acb609f9d685789a6b6cd7221d5df33b833cd0950457f63139ce621a45f744c20c542a23d610707036026a328780453330677add07614f4ac420f01b70393a1247a444a3a6b205f76bb15bba56839512d568bf7a8f440fe48a9909a4dab3957c6c570126ad0fa17579f0cdf51acdaad0b43a4b6594eed006842888ec8d68b260276ea0983d7549d6f6255625fe24df75497a6226d9118e4a228bd7c3280a9dfae00bfbc5f92a61c50ab95a117e7dd837786de922639686781e1827437e3cc5876c7487479dec2dfd04171ab2370ec95cba2c30da8d39001ec139feaa8dceb504f1b83281e9876ebe22d13e0961d9152947f25da42c9161cd4b60f820d4b12ebb3620a744ae6961d207151ab777d9886b3721b822d922840bd7e0d7a3a015d78dee3dc1e56dedbc9b265483809b692aa5c6817f64799f72d2db6560141ad6f9cae8cd4086058c9f438253f8d0d17b0d6acf4751dfeaf9f74ee4b8e7b1f1bfe325e40e9b4342efeb72a7b8f40e43e8a8e3943fc9d2ae5436e96570e3787e63f8a7f228cd809d5729aef532d62fa00facda0d6ad476b933d832b5bdfc69246101f6739f748661903f731c95a2e7d4299c58495ac6d8fb074fca98f8354148e51cdba3e7216af685787796aa4a593618bfa8eebca957311d2b4712eabb8b1642a7755f9247d3fecc718bd9a6d2bba3896d153a56ef76c6f4c447c8e3871177d4c8819b8a3a9b36cdebe89988a9ce7c4d8ee3d33cae917e93e190d917f88db43fc9542280fe91ca38e191fe224ff25ecef6f7c114db6e4d0ac23c4e36e8ca5b14ace224d7073deb907ea037159d49472ac82f00897db1cb6f86f78dd6c404e7af29c362329d0fdf822f4b2e70d6b61da7744f65343edcc3adcc418b6e0ec04351e6aac0d04803a4c11bf0f52a636133153777707617172b27b791d0c4f169936b5c12960b8eda13d3461c46f80c57c49b3dc8643709b276b067241340c9b253cb8149496b7ea2b0101450e1f2035a5d045d87a42f0da146f9486f868f62c6ffa9395a77d5f301110af90a56a2d8f5a2041a58ce9bf12f0154667369115bb3cb3a184715777f89e14fd46f08c257990b1b1fa3bcb3e1bf206a2e63c0beb013a22b465ee24661aebd9fab100e564ea69bf082adb9c797a8580fb6764bd0b991c314fa862f0fbf3c03312d72e4e72b9b2533586f460e98bb66810b3e346727ee89010c7ad1e95c3359b1aa5674a9a1978e5f93162e2db53948672ed6474a3b39eece6ed85b81716420a1600f95fd6d3570394f82662afac1bf4c97426cb0870cebd8c7168becee081b988213e85d119c0e51310505be8443a94eb647e4447f9cd0c44115678542858c80e6f44b6626268ee1a0b1c24e107d08f9babc70ff11a072e8ad089424d91158360ec1405af56ca57445be46174d7cd558d2576efa1986d0b473747f1af9095eb63c18bc7c30ed8c717828b9f102c67a144fa1430ade2091dad35bdb5a0f2306ecae8f7a0c4bc028dbf1888829c11abe7326be1143861acb69fa5b33582946b7665e106fb23af4e0f1f8ea387bff41f968d399d73fde04a9071c11d58e8984ca148a17e32290dacacb22f40c73fe40928f1ba14b64d09afbd4cd7537782b5d508339c0fa2956a707368f2e283cae014ec2c8245686e84f7a7496ed5ebe9332d2ef6e416f802080ccf58b4b0f01b38a34c8a21e627f1ecd1f737fbd018608c3007a0fbbb3d1f4d316fcfad59dca6dd1b78fe80a23890bf2615682eb26a62f549403a28af1de8c954c50e726effd1be845439fa866fd34096ea0268d674ef128be4d36980f9a3821feaf85b9424518bfa9f4073edb3335a7bd66a36c722674cf08f2040e1f84587482921a471d4e146a77486019d4bd22ed0395e8d5da7eeb0849172ab6b7dc59561ae0c67b97014a8cb37edc07eb50fa44701e0901467181b5585badc89a7d475e57fce099f24cd6bfee32d5982f6b555f8db799e9e7e6331a5366232c9710428c71bac468cc5f224308f4a9cad9d968030ae8ca5226654109804f2ca55cb3228e62b029be35e1ca2d0c1d3a1944a300f38f7b19e242c4328310d3c574bda888d63ff7bfcbd9747e199403ce8d1c74cf0f2fdd40c0934feea247351c7e3c4bd178ff7b928f52ade42862808cbcc38c7efa29101a7f0c8ba63224740444d0989f974441c31838ef05aaf8a84785565900e2562b0c4730cac51004c9409cb95647effe71c229b8761545a37184931fbc97f5341470a5ac0103069a6c5190e05696e6ea33a86b50e389240ee0f91841849b1fc75b8b7b125e0d88eb712a1d8af4ec2197556ee60a58c98fa8a3316fa2577a81ef95afe7b6fb26ea3802fde9769f672143f4bfc81963d694b24c5158a93510f54727b311722546cbcc6c7458c910c5a8ca21710d45e703b2549e013c545a6e01225b2483eb35673a1585d958e0e3f37393d4f9a779ed5f3a5d6a3fa48f37b872f6536679e9c25b7a5d4c94b259aba898cf3af7030daef46b2dbe91a2ee441384c5c6aff11ef0e7d2e4ee08b3c0077f8d8e49d9c63549cc0d59045d44922c594a1da0dd0db79252f592560ba01c163fba2ea4b24bdf719bacbeb903ecdadec231f88d537d46d43a622754af26b991344ced1128a0a5cef1e007facb1e83421222937df52b00c77a84d687aeb465880ea3dcd6df5fcf61dc9aa8a9c2a2752296faeca2675019e687f3f46bf3e8220c8d3eb97b6c7b521ba126675d1b25bb2ed90395127469ef7386f2ddf371af7be7eb7f255b95e0af85ec9af0abc6ac1aa61b1fe0805bc4cb9c49a3c9e14462929e63d366352d9b21494e292c9d72cc00eef3a7100e21b988d8c5bdf35ebc370d89d469c0421435cb44914fbcf83d18938955cd674e11895c45f56b30f4a86ae3ebbf7795a14de7ae5f94e988200949e18314340a15023f29ecc5098a835b57cf43011aa1cf0f621db51e0c3b7b2fa70f94f99ec04985d5693e2d24a625985e3d40414c4af40d647ceaf2de3fc3d97f525d264fb2f62f57510011f52e8ead7c09eb05cabea931753a2c8e2569ca024490f1bfa95174b199b926ff413d74c99d9b0174cc2a4bd2dafb06522aa27814a389337255460d6ab04b741520f81e576052e19f3f8cfe786e3c37c7adeb76af34e8e5ef897d63fdb12f9617ebc47e635e16a1f7c57a62dfd877fae7c69b1b6c9b67a29e588756b223d6c1e88d619a9dc528260f45e38a6f998d1e3833e890488cb39c27462e264dceede18a70f6b193b9b4e50624b61cbbf3da87aa8ab379eacf580d322e95f67f31625cc4b368998ac4580184084c6d5f84d887a47bd53ab2a26bae438ca59d81860b280e50da50e257e4cd905002cd7f2814a0896bc28daae04ed6dc393ed0bd01ce663b50f18865002b14d77fb0b6eb7511c3de50349ff5e5d88d65ad8d7f7b652bc8498d4cad234d34b6c4464b1f7afd128a53e97bb9c25ac4e047ba8eab3b8272a600914997280d94f82cc54b682515f5955a1ba82198891421d199ffa8d1ed044ff8c8c595886335e29801e8b0c81bc63ed3f1378a7e2d2ef5853ba588d777c54d1759ba5372b9f10a94275f4c1c36530503d117c7dde778d0eed0c5da0b40975fec041344b8a6aad261697bf7fe554b89c94bb66437656ee2ebab7e160c79ae7143ed29ed97cb4cf5ac4fbb954274aa029adfdfad3af501d196ad0616488cc8aaf5fb510b5c45a65ac4d121f93e14d1fb68218400fe0e0f058e1fb3a630b3528aee2dd7c9c5e31ce84195243810061d1654b800f4493088ee7d4c362702c66bd9374cd4c9fe277e0bd43c9cd9958ec5cc8b75ffc68d3f1affcc8796e621ee83ff354a9fe4130253f97ff292c6610c1aec85841564d35320b254523898bf8d573eed2e114ca0e2d278fc370ebdb00ce58a6b5c53023109523516397353065a33d6bffd519d969837fa125164566f967c48a87ebe18d44d8fdb208a1305b6dff10c719612cd1a0a84a8de3cde36703a4c87a30d4aea91f9d3606018d93809b19ff37e5879227b45e94d0a473c1383e02b83b8c58c41fbfcd0670a58479d32ef092a782343243dabfaab70bcf9e706269f1b251cf86574f1e36f37105965d1d1cd0f1559d56caae9d51e5778f891474e61022017bc2555bee22b47da8c9573b9eed6816bcc60e9e00e7afb3b617d7fb116c3a64438a55c5eea544218d13857c1ead6af3d6bd48dd773bf9a27f5f89d6d57e6fa3a5bd4ee55a288584fb4ab0ccf859fac99597efcfbfef894c5fc7fc1fc2e0dc77731d10275f8b190f266ffa2e4733d7504a89523e384d376f0a8c9e05a215a774460fb451408e63c19cd890dc8d42b684bb1bfc2f472da99aa6208ce7cbaae4c5495d89e13c67a5d355751b9de4f691ada688a956aed31b8a9e8edc0b15d9993050cd9e2c945b51bbe592f36e35e9a7d75a29e66c0241470dc22773c4886c6e4ad2e6d5d4ab3454d3283c32640de2a3262fcb2b9a2d333fa4d3937d60a8208650164dcb90c8329c3dea860109db1ca6059f214ee03af390e9eab341a91e04cb159a1a5c5f96691a1f6dfeb29286d4591c05109622564954f75b55d39aee8873e02c54116d966d215ce2b4b3adc1d3f95bfc2ccb3ee4bd2e647d8b28177304859b6246656da57780349a3a08f401871192f437c42aca21e1f2086480f072446ac871ac5a0338f32743a00a3177223df53e869f864bf8a71f34c5a83c03160b92bf0ef3072639e0b8810333aa8ff232d31bbb20df57a5db336e7cd2effb0f7d7da86ce4e5028c76e33ec59990af64630f2d0607a474c646d3bb12796cb11880c99500d88ed58230a732ddc617868ff4c937854f1111c734a4b719053c666b07b9f7e79f81b35eccb3d7bf280a09b42afa2ad8575361207144b05de4c44b60d5a309a15a903b9316aaccedcfb4cadec88a0902340fec8c20323575fdc9cb04ddc5cf2dcb4dc4a62c99b16b04510223f3b6fbf001c789c791b20f07d43e4245cc075e90d00e8244c4af04f46900d23a958b2b7dc7b6f29a54c5206e00dcf0dc10d35bb5293f9bfd049bd70e41525a7cac2aa95c566be906651c6b283e58685074b0f96168b8be547a5aeb3c2c54a17306c48a0e3ab9b4a550f0f9c1b510ff6fcf8227245910ee20b104f785dc01153a7eeee797980787e785c2d57790157ead5a95ec2e44b946ca596564af512a4f7fcf0f8d0f1dc504a638c1b885d98240986ccf0e269798e785dc07187a68bdffb7be2a1f4a43fd14779d39f72a0bce951b4496f3fed3e519da3f4a427e93837ee06384cd53c200fc803f2785698e0d08b380ec7b97d39acd9df0467acdd6ab59ffaf9c0777006dc361d7ab8227b6601979ec4d9e7b8196fab31ec1fcdf7bb9a6d3310fbea1b554819dcc66df6bb5ee76d017f39e4b6b59bb5968b22baccd8de3e2139a9d84a138e65c716fdd802fb6f3f5cf5f2e8046152c3fe5bcb559209adcecb410b1cf33e4e0bceb8f6b480436ecba129acb1d0530406cb574e9dfacbf3db8f2d7fcbdd7bae39ac5900f7a12776240ba4f0076bbfd6efef0d99ab66e89743106c5abb77ff08d2ee46155246b5eff94691ed169ca9fa46ec4615528673e086ccde90d12ae3f4dc9f5b6b08b9675cfbd8617d0f1019a967b4529b2f1e180c36df41b9effc461c37244629a967b4479a837986b84706ab3ade10b0dc26b0c391d831019a7faa260310f3c5f452e492f23d267008de6c299f44519e944da547d13a44390ee620bd49eb10bd56289541c95166a51697dcaa7d2604898d28c827bf05d4ed3f83cd176e9eec78853875afd553b2090c168c1d525251909a4d3171d56422beacd462cbdcf60a17e20bfdc2b0e7df0bce50d2ce027f2075c2448b2ef3673b04f28043a5da95a6ce94a6903f83820c6000e9a3a5565a6bada33ce106f612246d693857d1aab112483b461ad73dc21a9a2548ef5ae49a2f244d3f37a4e7603f3858aae6e131672a955a99adcc5696d04c78c7d332bd7f9d6dd23b076b49b2a76ed1892e58c02297cb8be887b74c20fb0a38554b318962d3ba755fed6153d58d1888ff41b56997b9215c8c2bc2c966cbdc34076b7962eeee9e2140307d0fcc55a926aec291aa51d54ed5e6cb8ac74a6dadc9bec8355b646bc7385e69e2aab9520be26181c3151616cb0e5fad30f1d58eafc21f4c2b2ad18f97ab5c2926cfcdc5189ce1b6158ac9847202ce703a0421bbd81ac01bff87063fc8f397c6f3f4bff7fef36fe4aa1dff731d9a70606912b97ed01cc57d9fe9379cedc655608f0823559dddc27e614b9422b60c2d1696b6e5892d59018325138a090525e5f4c539a7a9444271a65a74a9828e4c480cb2276c06286680cd10dbd3230416a3ca757895d8fef7b5fd2bcdb7a564655f79fdce4b27754923dd3c9f5d732802c251a136bd2538f499b5892e2f74f2f6a670441232f9a21f3eb6041264cf1fa99d08535bae927673b0f942bfd89eb08b5ad99ec03a2a2b1ea77998b0e70c007b3e7d010eb79b227785c593027677cf27caf2f9f3aec0a42fbde9e96f395bbe2973343b5b7e7d9b3396a914d5a1076e6efd7c8c91488c715aed7f72c8129a3eed75b5993ac3f52d676b4ed5524c5ca76a51c0789bb4e84769b443916be69e62e22f269d6a42d230764001cb959df982f2292939559b2d283ae579f1455f8976111c579e807f87aba90cf00b70c60364e3970c60c00067bef794e030ca20033873ff62ef55e0cc6d69a1a1067086fe75f922aeef02ced08f00d836585d0000007046f457860c7046f44e83df415fadad75ab5bad9e219eedf3783c9b6713fd98a257160511b96880ebf53a8ed6eb755ce83fa0eb755cf883bb2894c4b5a391296802d8d188ce16762782897244afd9e2ab0004009ce1b64f8234dfbb16a56a0b18426e90855f8a255be6ccf7b87c158548f1c3572a2a8f7a4f8be471991ee55134113bc841fa1211a537993ecaa098265e79d4afcce6cba9ce5fa1a1fce91d90f2267d327d8a3ed59447d1a7faf9a7c715678ba7e52a1f587a6040c4688aa4faa55aabad9e9b0ab21e580581aa48c6c50dc8560fcc57e18a9298af42cfcd104f115f492020259e1bd00c3911c6862c1ccc5622b1257aaed8fe37c9f6f7acc039dc806cf99f1c6eae2d3fe460a1298738cf00c5d6dae12bb33d1f95775091cb3dad3d5f52bc7da58338c0cdc1a2cbe44e3ca43ce97b4079d33bb843a9944d5924ab54c09e9887f426d2979e126122620754e7303dca1341fa124a3ed117bd644af944f50e22974ca502e662dc1057d525384cd54e3f53a1699f50f48c02c72868365b46e99b6e4c34fa5f040254eb020e0be6779e56840110baeb7b5a40cc4889852b6cb41d2998f0d8756bc1094cf54acd0938554b3199dfa21361ee9e3fc32bc2481b72cf37e144182f725dd7d159cb5d0a2e14d1992f2a3f5f345bd2a59a4cff95da6cfb9b55f20eda1ac246e51d960b51d85f0ead3733a35ca6b3081640135238429bd64fd5e69c9566ba892e5567a5365f2aadaecc95dafdbe385f48251836b39461b0523bb3e5fba8a5365583c18271038395aaa56a2926a91d183b60d8a498a49aa47660ec806193aa895c9e3ff50cc0ade05aecc962c3c59e7f572bb5e89204cf170f6cb64ccac1529e0eaeefae1fae87008203305f398dabeffdb9b8f26014f498207245982ec2d43d6ff7fe4244314a2db52b4c8a8043914b94e3abeda528c755b526726ddf16fd788982887e8880888288602217121ca66afe97c3dee23ffda9b7041c7a60a712caa3bc89a463668bcc717a92038838b95e22e5495f3ae91a19d7618c6591cb0730eb4907c9daa50f371e5be620b71ea9524ed57ce03055dbb5d48eafe29e2e2c725195ca67a1cf3b82fda3af4222d0b7dd784ac0e176e3341fc07c538eb385012ee333233814b94c3ba626beaaae174f6bb6cc9f2fa6a74382d44a4fd2a217e800d2a3c4d70e9d09cc646ad29a2f3e6bb5ea109316b9acc0f5c3546da5f6c2404418a72f4bd574f84baa068385c49ea99d3dbfb664872220348b5e712562220e1157a21f51e592e1d0033bb9c90393dc36dd4497f974ab764c51aa7184b6cd962f5f8c2fa68fcf2121be98f4cace6c995fc249d02b3526ecf9237066a596041c8a5ca995d9cf16f92a6e06be35be187a609e21de323d7330ed815581c395d003dbf34db508b303840de6cad3f299e926c2d44fd52ecd76bfb647a9d836f5924c676683f7b436f784e0ee43918b5b028b30574d9046b4abc6d99e0e7fa8b14db5e8e5aa29fae1aa22cccf21b764cfe7442ed316619ded50e4f221beaa315f5199affcc8cc57f2e7734b7cb5d1b2f015135f6d7a08b96776b826dd0e5f9d5cc3606d183b5c35534d524c7672aa06d26c7b06af08963b14b9766d8755b69dabedf997005f686d5430366ef83e32c450b5cc40034b0d2e00903123003456540480b26100ab97530d02c0d8b881563b5d46fc992172edf9272bcaf15598b256049b2f30b2f99a0109228ad1f67cd111d10c47261415d953a4b3e7475b69aae62bfff92926be923e98612672390517a6308525b166be6acf1cd6189bf3554dcd8cbe6ad931fa6bd239b9d9229920e1944e3aa7cbf8fa31849be8104ef5498738f51072bb8ef209b3c8daf32f126c843eac46d81e6328c72823a4368a2dfd694fcaa53fc9a41fe59317e5d187b2e84139f4f27b8830a5972f5f1186f4f2dd26c29cfce8e5cf9c08237a197af954d68debbcfb79be1b48911d65ad2501d8d1c8133b5b08b94f5c11c6fe7cd0f62148067b3e88fb10d4853dbffb305464cfff781f8a6cb0e77bf6dc0f4560d8f3c1efc391157b3e073e122eb79190428b2e9fa739e526ba9cb83c2218ff973229f7105d5e6ee3b399135de48332bd892ef2f109b6e77f4e5c618d628727ae3d3f49289bd8f2bd1cfa115b7e9743bf624f28b64c62cff0eaec69b91d52fa328a3d2bacea9062b1654a3e919f0f40347a2331bd9939fe9939b3e999b90d05dd861661be2d5f5ba65c1d75f65661b41ae7d4b4e6728322eac8978dcf664e486f4e39783bee90d2a47bc20eac841e60b95ec7514ff88107e18f07ac9e5047b69e9008bd794210bcd09c949ad252f26ba4a4b17ba38c6195ede8e56cd4a376fc18cfb54937f0a30d4e3f4481dba3481404e9a35028140a8542a1502870a324d2959148596c97e19ce8e24570c8d560c9be2faae8365f50aed9e2ff6f32b1509605e620493319311cded8ac0287a82034a81d5d056e940bf59a2fe195c54833948b8672b16c120d0938bcb10d045b4617fb753bc5a20b69c6dabe371d71887625dd09ea30b7f717cc420cc16d8f2ef7c19ffb12b139195deecbd805c1e6debb7f3d3fc5224cf720254e4448b39c044809d04ea737d1beb11b7395577066d3b788abfc51f9c65c1bd5456a6ecc57562f51c45755d7e02a97796ecdcdce04f9936014317e4a0d8e321920b1c36f7bca875461be442e87e7dd1c656ebc6e04268ab8c00af302295c3096b471c8175e395e0631a10a1c991b2f37822b90a0453b2a7001059bca7d5eae4c9cf092b91d1740a8c95c8f074eb864eef77999c3d1086248b2231356cecba64fd2c48dc9f3795935435e01451397aac6ec018e327e039913663261d5f1b29c89e1092f998b8770858dcc051dc1053832371464072f992bda81c9dcd1e7654984255e32f7e4f3b2018a00024be6923e2fcb2048a125734b9f97bd072c09990c0dd68e4be6c67b729818764ae04cd517f545d0bd76cae1e938c9974b88d0646a64bcaf91b9f944c40ea4168226ee185dead37835ae5d63665861bbbe099ca9f7f479595ea10a3a3217f50428d064ae8a184660237357bad0029acc65f9bc2c8ff840042e99fb31d891b9f9f3b29c020a5c32577f5e9657ecd091b92f3e2fcb2884a02673539f97e5106a3a32574719a44f194a329850524e5106196440a9acb07cd6333cf46b646eae91b9997b2f5f30c77dee3e08e6f07ed33a76982df3bd1d60ff5a39fb8139581da50c27a5479027f4c0a65a2635b50f71461de4e20373d3b5d5f268409f46ecdd000b41370b8bb892379616616af3057cea740551453fb4596c6a77244be2b86a057125611055f46528c58101f8d9e02a8a2f6ad3ff4dbb4d3f5e14e050b6e8cb96af7cf8cbf7547edbb5296d4901c7fd3df81e23b8c30428309bcd6e8889309206d1853efd1d5f640d640b7dda32551d4a2740528732079bb66ab80afcac0d7d3ba3d50657d197afe8b6c99cf982ba914b7e008115913a540ed954b6a9924d7fb3d5860bdcb0e94b2054fa7cce3d4eb897ca00c75a4b8c31d6485981eb31ba2ada80e3fdc4546d010ea5a4d4622968bb46b965956d3247c18da930466bbe5899538da24a3694a26ce68ba976aa9d7680ecf9a726a81da81b5fc521b5217b3eaa07cab5029910c5634f161376886addd4b8d821eac79e4fa5dbf8aa74e3ab702b2151e211e388b8c2335745985ac46578c5b0c153888104136468020423126d907c481953b8af482e920e308de443da3865e1241f2ed7819f764e59b89fb2d82e1d6ca4174c78f7298b18383ce8c075cae2a4851dc3dddd3e937cd2c2a9cc394ea97b2f2d1ca1d2734e86f92a3c699183e42117e7c260bbadbb838a9d98c415764254cd15d671d53c6971717c45725d18c415490713dbb8135c5607360bc15a970ebc6413434ccb42f85639c7555607ae30c7b2107c95ad88aaf92fa428c4162ef6246971c59e242b807698637bb3a4d7c633120acb063924d28c44b255569550755e3bdbe511615c0971457ac2f29036304dca98bf5d1e7bfe25bde6939ed86a251bdab6d12a91b822bd6677d3484f905ed886f80af3a5cad88f42c8df2a91786b84d9a8af7cc5d12d76e4624f29ecf8a0f88269b39b317ac4c071d56c451799f3ebeee097167adc9d8fe5abf0b66e936f877f6e22ae3857dd0ce47542d417e24b7dcd166f9eb81061e29fb688366a1129e3c4c44f3ba75a84a911c66fcb5571756d002bd9ecfa9a2f98568b481b78e6d5fa9a15d9d3cadc9739c64d9863319208734c861cd50e732ce758d6c9b2e832bd9c245bf11f9499041c03c757b209f285f49a2d4b88394984d97e7e36226d905c52462ccbb215198b3d3fca2c857c644fdafc7c687bb673146ecbfbf9d7069e0e73133b44c592f01294a4d77cb93b93e49236728e94313f9c26bd28e9ee5019a29a40318172a17ea05ed165e6970d3290ddf2556ee293ec391f75b327a6cd97d31762cb4cda386d11654c1b2e8ac0b51317a4b0e7df29258ddcf3eecc971ccb39d206b609736ceee49c4e87a72fec896db89fa75a886dac0fa26d22ba4c971c0b02b69136ac135286259299608bb0e78759b62790e8323fc425d8f3b92460fbdaf3ab8eaf6c7e4597f9bfe5d34e74393139d540ac135d726ccfd0be6acdb3f9525b3996655ad8ecf9f9485692693688edf999896685398b1914769877f6b42c296cd064877ac79ef2e5ab10ebecf9831dda20b53d1feb4418fff95b8489d19241843a2ba6c859a2024b2d1c3b2bba2081e78eaf42ae365f246b32d9f259328b1b53e16a16c19e92a22fe5a8e71d9cf97c8c73ce09ca8f57059b7e38b70c38b3e5a38d7b2365d01f9df8cb80736fa48dcf8e94415f069c79b2099de39080458f23430f19e8e71bb7a89a2ff38caaf9899f1d492b28741a2e5f9d3c7d1a3f7c357afa345ef305e5e9c72201b8f1d5117f3981cd88cd283243e62b19c62137d850430ab5c319311fedcff6ec5b069cf972b2993aac3143f5e9f04b3ac4249d6539a3e4ac335be88b729e85725e9269aea28f73cec255f43f39d75c45df933313575196dac966beb034f116fa230e65513b55c3dba0ea743863480d97ae3f6766969aab98b0ecb88a4a3a7fb8b093d8c910579d009fc04e869cd0c08a93c3f3eb6cd31997ec394f1973b38506568dc5255e13b7dad1155e139f9d4d6fe6cb09cc5be8531c9ec036fd9b4d6d38ba6287279b13d8f6610a13299de842976c21e80e4f362c3531e08ada57060d061403784518f932e06001038a4d67c880b3e9005ed1858601c7e8c2daf3431a589b7e3823b6e9d3409f069b0853377d19b40873e9a774586a9b0d4dab9b130fd917caee767cdab2aefaf673d4b7bf691d767b1d559fecd7c85c60d21e2a87b90bc8d843dd6c7d5b23c2408000f12502718b2bec39a510450f36c036b8cad6a8536116475e495d522a4daf26eed4a50d1b080c5e760c37a684e058041c5f3ee0c65468626dfa7703dfd3e1f56e40eda65f9acd97d353d40e3b507ffa7b65f37b307dcaf7507a94276207394e8ff244a0f4a97eca9b3ee5fda44f53f390f2a63f559d23a5547a942fcdbf17638c4b43c09fbfae08f3f2fe64365bbc1f791ffae8bdc8743d1e4fd775a173dfd7ecf971fa46159e2babd13da107b67b5ff2dee4d927e5906ef92739e4f64887173677488797894df127879fbd259dd26cd3973bd185fe2d0196e08c1034604927c2784fbbea01d1660bfd0a0ac18526106dbe5422987a0e82711d881696926cfa206808280692818e8074403393907b24747365a19b56e8556395487c2925892df4adb02249922b683a74437549270b5cfd4b1f1f97f2e72d5288a7050e4337251d1616930963ffda79f7f2764288ec3074137e9bfe97c36fcbea5eddabfc0ebcf1466afad2f7de7d1a72a6576895d8a27d6ba74338211eaea23774b3e9c7cc18f7e85fd9115fe9f86ae6ab6e49ad7bfaf2ab1009981f769cac21175d3af54c195fa20c35899cc464fbe89b26a223229a5e35e3735f2333a38e51772ff529ea90effa14e70ed3fad78fdb9c7a7a3dc51f42ee53fd1cdcfbdb97fb149f881dd027c29f7b227660758eed14f5a96a1efcb91939e46f4fc4a667785ce0dac58d29f93532329fa696ef691da7f93dcc16effebe100c8832f8191065b6bf5a870ecec4e97009d64b0d821ab3c56b644a456ad07c00feaa98963ab3c5b94dcb2c44178f32d7cb35325dae91d1614a9bee3dad43c705749c2dee1f0403a20cf70c88325e290998f3a674491cdb72e1b8b673df65f9b1e6a9351084cb1828840eeeb9d942254c7a2873e4fea40ccd57a71d76f83b6cb6f8e9b483cef68f3bc7129cf62c7c4b1d39fbc480a3ccb462083868c944191b304801122378f860c9386ccbd43629403712fb677a6c2818632a8c352aa59433ffa0da957ad55700708fd98275d9f13f3cb2e08cbd80af6a9dfff9f9df9c60ca579fbd3bb87e1c37c2186532c5380e33d7a6fe63707015a70f00ea30634f5d836a0367ccd816b880abf6fc9f1a03aa4d5da5c30d356a74356c19b0688ac1610b4fc605cdb0413a06363b4016385fb570be92b1590fb705963a7f654716e73e3c5f369a51b6699728699fec2d6fb1a57e760d02cc81db368ff6b51fcda27db78fe6d0bedc473368dfeea319efeb7d347ff6fd3cfb7e1fcde0bee047f397efbe9f8f666f5fd0b775fb823e9ab96d5fd147b3dd75d37d495fe9337da794140fd536bad4df3ab0a7c701d4ea0199b2e9e86543eda8a51ed1b0f4d569c7bff5e37cc5b2e35f5aa74beaf92ed02a2cead01572dacc79447c9947c416ff24925042091ad08009269a984dc85df5b4c1024b195daa6856d87502b768fc5b513091c0f5291069fdbe42296128a552ea0bc4553787567a734220f4c3fba25e74892e52577d5f5477d1c57f0b38bc2f7973e4cb555bc039fae6007195dfd7bcaf9be3abeb235f970970fcf0b6702eac7b6de1082ae842270649841d8991c5208991c5e8c4e834e14615378adc88dd88b5b8f082b7048ef7f096dc41b6e413f36945801138dc7a70607bd9a3878c83ab9c9b19011907db634a2a65eb09d99ad2ea70550fbe9a3d38e5a6de6c5ce55b0fae8a4db6ef3af34d047263d55895cd17efa58462fe2637296b955fb3a53ee5200fe02ac731ff8463eefa764b69a5102c3f741c9a99b9ed3d1cc74251dfabdfd5ef4104ac5ab50f4f482aca6975285d8eab0dfe2353fda8aaa1c60d72e496bb01b570e36719021c8dc480ecbaa391d88f1d8d3c116bed682476b343ba3d66b3bd1d8d20610c7195f20c504aa30cb7bd9755dd8ce7366f0a02c4167f772be0b0c69e4de00238c81ab1060e525623d6a84258dbffda9b536c4912573458115734a24a471661662f766850b2fd238ded4e80edde8ebcd96147f7f6e3864f3c70bfbd03b8ed89e8a676c0f6dc739a08fb9bc60ee07e935df6a4c0579f72786fdfd371b648cee6ba63ed4dcb57a1b5d91375636f622c0b37dbdff6f0f10a12036261b6c8f6696d7c15d69d8d84d79df962b7f7dfc1ea93033822bae7640eab63d327071061edd7c8f4601dd0e91d74cc6cd93e9625824bb9a308541821a5747ff1f01d8b4085085473c895eff4b3467cdc60474e081176eca0608267048a2bcc3929152283628b2f08220085cc3c42b4b085ece06e07c83b41c8ba40e489c1e8eae064f40392488ad290279886608132848bd168343a39716287b6803b7d2f407970a08281ac7886b07c46820085954f45454565652508344ddaf1e2e405a9500f6044b1630a9ca941ea532830601809021321c8767455140215b210b610a488931d8d1881043418a1470d283e7031550100b00a32be205cb851e5c12488353bc6930e3ac6a7119c71f7f831c6e831fa8c594f8f317a4cc93ac32c9582e12b330ec6c1b821dec2c1aac0d4815859b2425b0162084f4bb6566a9e160c06f342a5eeb6d24a8f14190283c1669e3b0e26856cb0cd5ecf5770e68b968309817175eef099cfecf51997e78e3ddfdba42f719ad79c89afea64cd1dbeda6c90983c7cb54d9cd9c357be7d9e126ba752306a2a653d315f859e580c307df798aa6d162bc1de0ef6c860b3583b6955ea40acccb60e25335af1c9dff43525ad6307ae7394dea4759454def43a48295f727729a54aae31a3d68a4f2a5ff3f553525e45eb48617995d781b2f22991a2bc5da94dd2fb5796951c8b59bd6114bb529ba40994de14672a2415bd129cbe3a266dd22cfb137d2967bea8b866884b39a5598d66ba027b1e07eade9be1bdb7bde779da07efc10f7f003de941207dfa7ef4f2493a942aaef9f271273ae430fe601557690696a8c02f023d07d2e0f721a443b97d2c106d0657e024b9d90e72907cacc3cffd98ebc9a52560aefbb3fb03c14cf7777516db1ff48038eceef47d4597db446c71590c22516cbf50e4ec199556b3a835af4c4ab320389666db2b4d45b6e38b1a947c209f93afe6dce6a456da2ab3ffcc52c7c8a4fcfa99d6d8a239ce181dea2e6394faefcda6f3fdb276d82041bd16fd9a53835458bd5df6be664e871e0d36fd507aade842af9ed59c1aa4c2ea105751e9795f696ab84dc74c9b6bad39f7a69393085714d2b350be378755166fce7c01c9643a3ab3da9ddd99630ce2b03b46179ace6362676c034f3c883ef439443ace1cf8bfdfc099effb1ecce00c0802811e6ffcdfa766e30cc4f67cde7f99fb9b3d3a47375b3d6e8fd030db3e7e95cd974d5f1cb75a06ee19e39c50ec89433f6280022bf988c1155de6094cc9094c0cd861e4c88073027bd9e9081a58148b23f6a4ed4903eb657bce7f5984e960e49cc0429b86d974ba84eb534a29a594fef19a29a51377f4e1d1fd8c4c11a37cc5fd065efbd9f71c9ac0afe0e73fe2006cee2fb7e54f02666c70fb64b9b94f91fb93e5beddb7811f317e077308c006b9f7bcdc1bf73897a8c0e06fffd11283dc831f8d5286b7fdbb4bc3e9215619bbea1bd56049714cfb7e628c3af4480b6a2c16cb04371c21140696198bc582818d1f5c018609708a29765e2c160b05045002ebb0d448820a3625c4565a2c16ebe6250927a8436c7cac20b14ac20e2a7c2f168b55820184a12bc285eb86c5621d6103173858c762b1583602d04215428dc5621941830add0f6ec662b15210001d256a33a600953082198bc55a818c201f2d642c16cb0500c8a133171f1879d5e0c41cb2d150c512d7080fb61b168bd58219b6a832d8582c16eba6e505a09112d4582c160f150abe2d662c164b89185514013e41c662b178c8e0855b04c662b19280810508e4c562b1705249b00d6c8bc56225f1820a21a42ad3b0a9042d419e8225840a99018dc2582c96097e0a2328019c22892754168bc562018b146040e2085860d1152a72b8d81148a44065054870020c5052ec84a10e618112903851d1032262d022c5b5c9ac30010a50a85822d68211a4c024c5cc0839e0a2348326f38644058e16e689144d7a608b80a4052f998f91912170c1c59260036fb158ac1488a83042f4841b168b9544a80bb8081858e02c168ba544ddf2415308d5b01229701085198bc54ae2a3848e0a198bc5baf144117a02c662b15e0012810947e40a47bc582cd6cd1784214c90b4ee131b0c7c48168bc54281f79a4cacdcb058ac127438f0ac405b2c164b059c0cb817c41a8bc54ac1568487273b62cbff92b0454210a2220845e80d8bc57a41050307862dff4b01e5c296c50c168b858279854e960425375e055a84da922dff33818c58624c4d9bde1160fa71b6a51412852c6cf99fbf7c3232a4a65d43a502785cfa9766fa11f420a66b1ca19a297168d69ea8fdb14bb2e37b31ce5c50ec199d50c294043e62c7aa025bc417e24b55416c8943e2d72de2aa461155b1562baeb031ac4c360d624597092a22b64c9a156eced5b732d939ae9ad26b8299d8f3e9e7568491211baac34c03101332b7a2cbccd9f34935d2ce4927c25cdc8a2e399a5595dc18e3f4172913bfc6a5042695f1a91730f5029e2fb79c744381c4da33c4c518611cc554229d6c2f9f7af7033d9f0f44df73cadb1c82bcb0e7dfc82d4405c84f7ce0491285e1b369696464ef6a3a6102dc298ff281dec3715ff3dd2928a612e964d30f3dcd5727ba4cd187f2b2a28b0764d4fdf71a892cce4db2e783f0c7037ed76382a45d1d4a98fc5e1b841361b89f1f8dcbdbf7aab0e8227dd26a395ba9876a92495e2b6e4c1de053adb5d6d25a3ffbcacf66d5be115b1bac29096270982ff4ebef5023cc22616f52bb7e7e5755db950066430d6b43dbce2aadd67c55c3beb0bd632a0940add8cdad919dd37dce39a70ee3b6f4ba15f8611146b5a92ad636fd9818e98e1d3c97673e80ab24f731c13878514c8ec3f871cc5514c7366b7fc3b24d8b60fa544a0f4d9409a6541fc0551446a90a708885a03bc4786442c949dfe61857d103b88afe1138c4308c87e098ff74296bad307fc1b089296cd3a73818c372eb93410cd99e42ac6787ea3855e22bfcc19f8f473e7d984e8cc206cc28a51824604691c51cd12175a86ed489baae8b41221aa1483a64d931b29823313aa5528c2c06c9f572e86d46f9ed87af423a943b84f2e0c71c414141f9181d5f818ff2129c41d112c7286c50321883048533abeb920cd7d846e1cc170e45a370503848626431486cfeee0e0ff434d8813148a40cd0e66f834e38a983e27526922bee98e24ece7c9938238dd224cf217dc973e60e8af6b467d221cb9e38221d72231d62140e09c7e341d121f67473e7b97caa45184e7f4ac8ed14bc534c3be5637cc91fb2ec14bb515ee79c636cf9ccb282f2db5f52f6e772f728374aea9eee2f4a5e7923f23fcbaf7c0e96951c59e7d7a79dd93229f57dbd7216a3649ab84b25ed79afeedb95de5f8234a5f7dec11c4aef3d0a29db1d415dd2dd2cba783c1e8fa7eb4e3a169309cf682c6eb708e3b5d65addbdf471a27c9c9ce72412a8fba9431616141d9ab48e7176b97b3ceb682c579892606db767bb3d21f8040ce5b84f44886c9ecc6312562b7648ad774b68b5cedbf1d5b7c3579ecd45e2f2f0d5e9cedf7e802f3f46168344da8811a6f3637ade5e5b7eeff9e86d6bb94a25539dd932b5e967c419f4eb72b5d9f5e963dcdaf7bcb9bd0e7cff1bb2aeeb5028940e7fb0a00e1d5cc0dd5d97dddd3d6676d91fcc27f7ebe594b7b9a6c807d5effe46116923e6ab2a6ec87c6500d6ee72b87bfb545e86296ddb1b3157d977fb386f4ba86d941d8d2ce14817d807fb755325bef21e9c4b401dde90edcebb5b23e8a24b23753cd97326ce9e78f639b3e4385b481f4e9c957caacd965922b934d5e962de831fba60e648ae28437acfa2edc9fe5e56c9520685e399155d482ef7b87b46277710f422e8271f925c2a79165659664518770741179d6aa5ffd34d84f1fcf43ec4b317f8de87da664f154d59b389aba6687b166daf0878f4e1dcd95367beb84cf72ad9655272dc289b2bacb21d9250382457e8e5849e923d3f94c38ec89eefe5f8ca0b02f362bef2bc229ecc573a9e125f81b325becac25760cd63e235f15505fdd6ba11bb5185b4116fc8b61608a43dcd09a1d45d7f16d583eaa07068beb23bee4a7c9585af74e8cc579672f973d55c80ef916b2cbbd8de8b00dbf75ff91a198fe7a9684faf681d5f23d3d97730a34c51f62913e05035012076c8a1e7efd0c305ba9f8fc397bf8c5de57bd757d530e386181d42abc3aa750c598adf30abf6f1bbffd49f9f3f3167e23e3af0e7c36fc66ca99fac9a2d95f3d568c71742ada574a3dbd7df81da1faeaa356266fd1e7cc5d5b8210601beba5f7f075f755f7fcb35e419aeaaf55d55bfcb2957d51abbd6a7fe9f37623e7e6ebef87f9ecec7cf83ffe773f87f749c58c72b3fcfbe57c3e65086f43db0666f19080fe85dbdc4e7bddce994abead75684f176fdba635936f3657eb5371f1dbd857ecd9ee3f4a4c07ee270e0389b32ab359685ceae7f0004f450df0240d4a864d7fadc66b1fd51dfbe626881ec8a4df3657e2ccf3b25e27b4be008ce1e1a70674a53e0bf7f3f128c1fc10ce008e9ef8241c82edc528f7f8ccb1a4dfcb9c30e23be37c23e1106783ec6165c896cef9efbcb9d78f8fef339beffe81ce0c7c95d1ddb92c6fbfbdb5f8d23b4e347588de108d196f0e8185baa0e2b911f6a6d3b08688de7b40a4260dbcebf28fbb465803f346af385be7d1a3b026009c046004794a889061611a6236dfb2a37b3a50538a4310b5d6c40adab022ce30007d0ff681ab3d96269d0668b05b592c052ebcc689d1b1ce61d6d9377342bc2786f5f171161bae7348e6e6d1a4b68d0261705c01280cd4d0116006bbec813179bd9629f73b10969cc4c9b2a81c39b235d582e45b8eca881896dbf06170d456cfb3d89065222aa403db67d8ba3f828914138d1c5fef61ef50727bad470f96a7b161a335759f92e36beda68d07c00f667a6b1c406873160d733020e69cc68cca40d2f42b5ad13780b4276b1ef160a7d29355e4ee0189f46ec4621005b6cfb01a84518ff1944b6fd192e36930adcc1a28bfdab69cc48b402ecd4786d5413db7ef862c5b6ff22db6942e566db998bcdcd3bdbfed4a10d6ab9d8805adb565874215d11572a37aeb26f9f348b30dbdb154495fd90b4646b9d23b67d92fdd12cc27c6f63805a19fc2f6faf72e358a8ac206651939858c4f070ddfc5904dbaf566099598419c50f69d0b67d1ab3f9223f00b50833df3e8d5884e1debad8d0b649a2d1b6756ebe10d9d6ae68b0ed87a4552bba8431708436a75f62d1c53e65010e69ccb6fd3e74b1d9f6b9df322d546dfb1e10876873fa66dbbf79dbf7f4b6dfbdd836bc3adbfecde1388ce7cde1e4ae612ff1d1c5da69bd26f04721b05213587bfe8deeeeeef5d2974e79b067cc6c99b45efa43ca98fe31f345eafc9036ba2652c67ca903a33f76f5083b80af405856aad335f940ef9aecf9f6c6f2f0d5e8e75b1cc72942776890170592e32b3ae4061b6aa02f296173c69ebfa73749fa24cf9d2694355be68b32b5c91409574dcae393290eede1aae9385267beb80f6f99ef3819b55335d830c3a58e9452ca4a5d4aed8ee33dbc25e59c82be8cd33d16c96fce0da7d31860fbfe110317b6abf6816a1fbca6ca0fdcfadb03375b7e8c76f30d17b18142aced6a572d205bf215a50fd77dfa32477a3ebc856e9dbd52578103a511e8d0d5d0545da34ff5ed5b9d81aa372a2e0ef99172bf7d0efb95d35b7c23acaed1e9e4289e2fa3f4a799bac6e2746f42ad5649ad3dffde1bf6b9f9127a7b6b200856f90175f03c200d57ff8260ceb47ee04cd5de5f9abdaf44723db2d5e800c10dd0de50927df8acbd11b3bf51f083df7e8c3fddfeaba0c73af4fd554e8394d65a41edc3f6df831e7debd1b7379480b356ef6fbd7164b337aab875fb5baff6617bf0e98797d3de53aa69cdf44efc557ffa46151ad4a78fd2a7f46fc46e14b120984b54e00b3e08743f77a07b753804c5568751f0e81004cad16106bc6ddb364a391c7acfa2ff64efed8dd89435fbd94ffb50bffa9ca63ed4b79f00fbe09600f03f8d93ec59b321fdee534a54dcffded3e1109403752837b8806f5fd003823afca1c6e42b677b9de5728d6db5d6bad9a7f235436bae475cd5fab8e9081d9d3f846f99630eb1ef8f9b3e04a16387740fe1a1d471be2c888c076d0b6047235600d9467426e8465a3bc68e46ac0067fc25e8aec3ed3ffcbec3cf3d08f4dc873cfff73f1f1d5da541997bfbf33fedbd284813d66cf99bf6c1d31bfda1ebe6dfa882d33ec8df7290bf591deeaedae3f6043a408cb04267b65d7b4070685bdbaddc70783b084adbb4f704a6b6e5c30c42ce3b93b41b234ee8ecf0ce84903bbc331a5c4e92c6808f28e5f893669bdf2340ade8622b88067bbe1542cef772b02f39502bba4c1c8b2e73b6d19f3173dbd9f37d7651c4558c62c896d2593bb47fd2818b5b9f74d87ce0f4a6e3766abad1e2c654f8e2061661e402eaa743b93f22ad4ae4538b2ed4a6b5e9187048029faaecf92a32d44e7429e56caa52ca6182ce51916d2ae9df27d9805adefe72c482be27437d410849ffda6c5a5fdcd01134a1879126b06047234c803501891d8d2469b2eb8e46927421092d8698c60d5c2131c6cfa30d334c2ac9c9f74fcbe7b0affc1d05f1e3453175292931e5642bdd68cd02cb984e424e2a89462739ca7848e6cce7748daa6d9851eb90cff471f9db41ca4770d3423020caece87ee69428633a492aa5d6617ad781f2539f648d8cccfcaecfaf9a4cf305071c623366747a87534ad7e919ff362a30356d7a3aa5d4d1977e87e8497f4f59e55332ea51f27c53f6dffc46e5737cafa275eca0be8ef9df579de33e4aebf053fe3e25df47b9a71de63f57024f32e84719bf287f7608992ef8017d9e1610b3853eca34aab10eb2a9fb96649cacb1fa81f36b0501ad74da1a2393324cedd495b55610ec2af39cbfc97ca3c89634c6e946e90d99ad73524ae9bb8aead3d438e68e356fc88d3776de88fb68b565091c865ea197fdcdc57d58f868aea2af371f46e053fd9a1da67ed49cb2e13ef5238584abe86fad2d6f3eb6561702e23d87059aed5248bca0f96a7a1b28038bb88afe0b9aab689842a2f582369b2f2f68534415ad60ac7e953da569892b57e7d4271d76d5277dcaa1fe642273d5c9643ad265bbebd73abf3aef0469b6dd7d8a9d39bea04d01c67c3ea5d53a1dd6232f5f4dd311d3cb5554da0e7faea21f9a5ea697af2acc5715488eaf4c434c3193cc74c4579d8e125f2df15547f395cad337656162e2abd3e7ed973e1c6d1521305fc55de5d439beaa1a9772dc71062ec1c01c561d958aaab8de6a6f42269be892e32ab94b9fcce950c7fcccc97193fbe4d047909b273fe709f63cf740cff3bc13cf031d854fb497e77ccf7b9d0aceccf927390609a7f2368742fff99823a1d0e743a10fc7a9eccc9698fea1becace7cd95ab385fe89ca8eca0eeabdc94d7a75c85d10a54316959d78bdbbe3c62091f555bee6cf73e08cca76238c30bdf03d411ca623a24ab5e5b929c883e94514b185fea515d70fbcdbf47eea5065c7135d2fa37ecef9dc9c13b5694e7ebe80c5660bfd0eeb08ea1077ddccf2c118fd44230f18f33eef45a3f7e99dbca783905d7c5e25ee2d6f1b94c317b24dff0363a61118c339f47a11c5a62ba093d3834c361166dbf4f3b9a9dd10d44e21a8d540a7f772083ee84f7fad0567564c1ff107a5f227a13fc18f4b0ffee9de74b3f697eb7e72a2e7445aeb096ceb747214d31002bb7e08816d45b5876d3b9d32aad56ab5ee76271ef2ffe778f1fa8d78a1b596208d74ea208d4f6e524c411abab7afd915a4a97bfb6bb98e7b9a8d1b813c1e93a766f2786eadb63d9e06bd83a78b3f25100cfde72474727272123af9cfc9c9495539d12aff5151895587f793eba3e421e43ea927ff3941f993ee519f13513f1ad56e5853f315c1d76fe28f9bfb237d78a1f0fdfde53e0b9e78f8d79fe35febfa39f2ffed367dcae17bd1d37c5a747376187ae9f9a3e772e83db994b38915d652feb5fcfc8a00cf9f54c4d1cc2dc216a4a116c421eef9204ddda2bf9cdd44bf3d8d68fea66bf6fcaa75f820d477286d4f1eca9ebeebdece590bb74ff99a41cf799ef6c17ef712d4e1f45d376f08acb5a1ef3eecbc999b1b829a8762792f8720b82100fda63b500885fa988992f13e39fdc7747a120be85372e8819b0d3a3d48089ea15c8f14814fa59d91e56c67c1997afa2a739585a9e89005656fb00ef1bd11498f478a3e469793cfc23a8f1b9de490d2b6482f91ffcb1fb8c4d34a4a64fdd970d324fa6c3e9aaa5a58927ac5e8ab0e495c82ed18a78d74c862d22f683422d1875b8b7e1fad3ee562b74dfa795ff8d9ecd2174a4a6cfa1f12dfcd67f3f1f870be1e9f8fcff5fdf8807c7374f2a3f7bc4a93d0cb659e1cf728c73ddb37b24a3ba52626966987af446f7a8127efd9d1e7efb2f71227ba801faaec845e2120a19c50105761fcd6c657204de7bc5ece255774a1f51be5afcb55c7ccaeaba3fc8d7e8ebe7b1b0a8574f84337d2dd4f6bf3fc1bb11b456c066f5471a243b94fbecbdff7a3d1f78d7ed475f5391d0e41eda79464f2d5755babeb7ee6fc02365be8ffd652d9097d119c1f127d129c1e023267bd210bc142b19ad0105fd593af79f42070e624c8cb55b4e6f952ce2fb9c098cd295a586b455bcf224c7dfa5f9e2fe266c6e17dd52120aea2a33fc9717b46fb93c317b110acc4c4a62a3ba4a71f02e2ab1c5f79a02f3dfd50105f959e7ec91561469bfe68e48139e7f4de666ece59fab06683bef4a0bf5d07ce90fef4119f5cfc22cf8b1e7cd47f547c986fdf9ba1d02b443f444343360d05d9346f3f1a7dd527ee47b9fbf9a3efeccfdabde9bd1f6acddea439711a87ec6277f3ab374bdcf7537b7f9a799b336f5f68fff4115cc0f753fbf03da77d08fdec72d5d99ff6425f7a151d403984f4c94f1da23e1f4ff578acc7ceb79e592bc61873f553aa28e5453991fb99ef6fdbcf145b654a4a187a559d6df5fdd2bddbfc084ed07bdecf4e873536dbaf757bd3d71cfe50fa6ebef712d401f49e3747ef85de67e0861e70795cc0f5c3aa331fe53b1cb28b3d846c87a5dff40fe10f55678fbef431eec97d2fe84f4e59e21faaced680dca017e5b85332de2839c4c0ce2ebd29871e70edd24b3087930dfa12295b96dd31060cfad0b2406f6db575eb46b98233a3bf1b4823bbd8b576279e77a26f543112fdad74036744577ef5abdbf6b19e59bbcf7576b656cee2b88aca8d2d8f25feb91cda1e9bbe27c49fbd992fafab6cb6d0e7388c4da6ff2ab3379bbe65d91dbeb2a9ff35a56a2d3169b6c1edce9f59258b2ef4fae76501e7ff9f2f68a1227a165d68e805eda3957022cc7cd3eba36dfa2aa9ec74f4b34a36758eb3255a2fc7553404a47ecc0cab924d9f7b41dbf4b7d06b531ad622b2aac45776b6c432a94decd35ac45793ab9bde9617ca85c0b93471cf59b3e3d5b57bf1836fc4e73def600edc3df8393eba7bcf5f39a9536e564c13f77d5b89eccefe77b5c705dc79b9fbb8a7acbac6888080d6783e7f70e95fbaefe7ce09d27c94d280b5561a8fb5d6d27cb66ddbb60da4c11cc7711cc78134201aad034b3b3a50878ec675b7254863df6a8d23341f4768d32ef6ac7203038dd2e61338a43771e6cc9cd9cc6de46b3e31539a02bf04717c3240693842dbb5c5e266cfe8c5209132e4ddb2dc313224320689e7fdf7355f8fe73b8f062b4803befd5b59d6da4457b1ee87b8c62091323c461683648bd1f195fc4dda4ab7c0313a74be04a5fd648da2e296ce0f8e7e3edebbbfb5524afbe10f5f2883f2062ee06e19ca17072e800bc1907e1f7ef9dde7b9f9424db11b55c8fd79fa16d4c1db1ffa15a4f9fcf657c65de5f7c975e6aa5997b86a565a74559d81f2f4073376957c85f275e3c8be21dbf43970e6461552060de58d98a471dfd8f2497e0ddf90b9aa664b09d25ae3818a94527e0c1229a594523ef87d20cd66adf57ecb3e8c386b37cf7223eeebf6dea85adfa397d9bb5cd06adb2f6d1b8d3c2f01dd8f3ec66bbef2bbf6afec82b673456d7b2dd1b6d7d2ac8abe6acfd339a59c2fff2bcde6cbd54999916627b390f7dbdbec79993d502c8574129aa018a743ceea104b0d8a555ac77131b298235c842d013d08b6ac235b1fa66487430431f7e891481bdcdb217cabfc48abd84aab49aa152f5767b6a83ca87b10c8ea13e8b7f7be760fe2ef1373c472252af0068234f2adf6c1fee83fb99d504af6bddf2af71ea743e9a9b8e2e7938fe583d2be57ed6fdeccedea06d90db27483463a068994e17d476363a64a163d2a8fdeba54625c8193dc97f2863f542f6e09561d23d3992fa51c2eaebea8b40c34b7518f32443300000008003314002030140e090543c16040a6eaa28a0f14800b96b4547250996749905308216210010200000000000000000800081770dd6657414439e5b47a62fec163048ec868cdbee666f4c1ae83eb54f27baeda43e9dca789a1ff260a4503728e117a7fe84a83e4a6d628e857b399e57c3f891973c44e82a523ddb5daf096916ee57d4d8fd15195db7384fb7c146eb356c51331b7dd4215fc6c0b60dbd97924354615a91efde02e7f1ed5f699201836a1b00452f6ad4969d036ccf4e765ad2536d06d6383fcf96d628de2b437615f65156caa0672af620a5e3b178ad0f85f6cceca2aa4bb2cb04c28a2add4d20db58d375c0659e3160740200ab33e02d0876ec708f1ec91f38143ecbf1c51ebcd023dc5ad0517f320688ff0066ac294909c33fbc6487c51dee974654c1dd7140fe15b6d0b5811ff057bff564a04ec218587239156aef0bd0512bdb8e131b47674553841d7473f39af62a0944ce9d8febdedaae55eb9a681ac015569a05769dedb75849d6a2a64f456da34bcb52e7f85d40a30ed57ee5afe080a4de10febc9cfbc824d46f776bdb63d282fc37d8a24616be01e93466ccfe29531f7763b83f2e431ff787c9217ce2d0903d3e8709c2866fd633ebaaed3d3d6a90aa95c5802b05b5e67532a6c4ec1179ef0fc62874686f0fedfcbcc0aa6645c44731795b3fa2ebbe7aa1bc973cf0d3efb51142d3d62f77d8e1e282a446c43400decce80156479eeb14e7e722cefc13bf7ecbcf5dd738f0b5a2f2b1e1dfb0cc84b1b050821f001310d409b4416cdc41795c84d809fac75c08b4f9102f0cc8eeb895e0b0cecedb594d841e14f9c7bdae5ca748431b86f55d41a0451a6a20e338811185ddf5dc9bd8f007c500d92415162f417d4dd504043a32ee756eb5771917366e3fab6c0144e986a1e7e21016528fc055f2641ed99ef55d489d6b804c773370e78aab2ee8306a34ef43bc75fca7d6e076308dc234b069fd0aa058d5db9ebd291b46340b136abf198e0622987fba560b880d4dacd274b9bc1f879e8f52e661ae77d2e6f9b993f8c8bc7a828fc34de0c0952578a5afa6b12073ae449d258358c74e913e0dcd607544852275becfd6bb925ac2729fc38f1dbd0cad501686568c7dc413e538fb6220f5248c8210834259829298ca25a7d1dc2426735292b5b87d8b181c41db100cf566631901b0b9e55ea92e95304858d8202a276779ee15682c1e06bb0e21489bb32aa933c26daa09127522faf6f9500e0ecff8ae7372054aea74422ab291753cb69205e6e9c3ee5a5d0eeb5df464a8baa5bf2d18fe0a12f76fa0d51446d955657f813726ea2d858a6d4818421efa470d64e1a3b42a2357b00acbd341c078a75ef0fae5e20858f8c7e42f74cc4264ab6edc860c023d0f3178a302c8b3258aa97b00edfdf3ad5a9d93b77bfd4b937e42964052c516d5146f9216d730e71ba59c22fe3be95d0246bff716fb5a3df316c5f73faab2a41e5d05ba29699a89034c0ba32a60610cd5ca109c78a6a7eb1891e628db4b4503f27fde95f5fdd689b74a3d05f27b9588a8b37da309378be1203a82ac6101bb88f45f9c93336f552ddca3a78a39358274800a70d2b01ecec1c0511520148be85734bc96fe6ef0a14fa3cca46190be3554def725a299459e780e7dc108ad93454f19ea4582ded452c9025aa0ee2f4a47f83c2c9d406b1442028d7d1e821791046c287777745bf8a0a70660ae6c0800c42abb46e3bb886c53e416b8ffd101383e5890681c907329f4ae067eda29d7780428e85ae19e7da443fdc84f2f93502e28d0544ee43f9956df3e8eddb45d1fcee20b0d5c3b9407dcc5f3117149d014bc74f0fd40bf8815d325d73aefc7ba7031e87f29cbdc43ae727677713bc81d07f6c97079ecbae9e6b8d855248b432322c65a43d49afb673128c1f74ca92bd4f005cda71f5811beb22127b4e616973d29baa07a67a65762eba8b9ddd553b5a4806642ae9dfac1b81864becda304b90e42a09e6c8ad42ac4b6c5e1d6b2aaafcb966af28135313e8e16024de16294eae8e8a61b9dea6318e3932caf2da287824cb9f3fa699acdab34f3c321ceab152baedc3b506ea6ee07d8a410c511414b06a8c508f99df907429b5a10e0d9300d9910032f5ac6a7e5a6fddbfeafe0524e46551958a44c8be95add495742f82d3fef59a8ec55a1167a85a5089c6c741507a2fab59d156c7739e4c3c003cc51edc375e2a2ad22ac27e18e66538828f0350af8f45931adcc03704bb9632c2c7da74913cba0e026d011c9a1b9a87c4c6e886b9078e152a3c984438bc514e76911f4541c5d92800f1254e890a95372ac6f62391b327274a26d3c09c8ce117065239424580c4f548786fa250c6229a4ff035b23bbce10ef3a5d38e4a3f72d26bb813a34ef4e7cd6480dd89106a57c39804f366d64bad384ac1e86de512cfa97e8e4ea8044e43f6eaddd399109ec42cd4926a054feb21849717d6d3457111253d0bab36ff62f7cf797be1a0119e014088939724abe6c954b22ebd13e6e84bf3d5752b4e62c0f0a35ff82b5a62c69bb625779539743b53590ea44a690f8c0be8931745f4830dbb56aa34303123d2361c179c2c79d3735a2afbc55797b33a7ad035ab151e69989201e28a7e69d93a0fecfa244460aa788884787dd31d2d214ad5e5d9fce61ce4f5fd9584c312964c238224f043559998343fa678970d3badc014b4b5d94a0628ce3970a6e78f92a3a275c18406e3e959f0ea41469035fad15ead6890595b29c0c7e24caac2aa9f70edd0973ec0ad2f894126eed9eefe5549ce154a38190e6b296386e7453dae9f8c6dc56d2efb15a8b7ad5d424814e22be55f4dc94aad03e409550f0f20f66bafba1a75d706913c75add5679b254f5e170acc2e2d26a0100c8511cadc906d392b8f583f07767b98408eac298a2a35039f06878671c3ccde242cf172d103c6d7a0fc117a22aa4bfec85ed44288f88ed0c2c1cba5c64524e8cc381f10d651bce4438647044511d203884f442a8781cfab3f485c981b317d2e423a982e29756ba1299fbffdfefbfef6f90726c0e6a97a1fd0127cb3fb5dd0299b6c887d6e267dcfa5f42342d67d4052a1358941efa9306eb2ba1a674a9580548dd784d05800aaf06473c388ae2c8cbee21fbde2ec0fbf197eed03a6a694f522bd7073fd2876440a1161712641602737df7d8dd8d1e2fc610ec20b4b42b822ce2f901302558c44005446bc5590adfca87d002cfb9fed81517a0d3d5c8b4de08950d6e3118cb84f52d7360fa0750b60786b2704824a01480c94a26cef3563506053389ea618b7040114cb83028b5a621c4424bbd9820b954384b0613081d251a51ec6b5b0b272187f7218ee647dc0fc0193f4302636914263189598f4301c5846f149d9434089f5006664430435c20e017e92a1113c6e670cf6a4552d035b2a77fee4ea41d8ac22242c3b0ce08f5886f04f358785b448128ee76875530e098f58a4db3ba9853a55643fe888135ff87c4e58b4d0a2c65aaa7cb4692191e8009c8fb29c8c2c032a66d8646538a7f9e8f87d709e42b2a1924bd2f7cc976df7e0111d8f108008c74272b9e5c805e150df2f23e4d272871b9d715c879c89efe474ec558ce9738fcb2a56520b397ca1da1ff179c3363ad2b690d36e22853a7691a75ea4836b3cf30838cf5ce6239a5b088cc28ecca242c95047dd445ef6e539956d120ba714ccdfcc1fb67b3b7c766717cbd5346340d13999cf9b9a8f24cbe87fde78ea1a09026d17f10d9a3c29a85e87eb22076ea736c1bbac45a279dbfc83b70b850b35cb4a9c4573977da570128c71bd4e8d749c0156a12af46a76ccfdd080e8d192474bb49901552aef159a885f585c33331254ee06704a1e73fc1e8417375a6d6f464659ff574d034d1d19cca1ddf132790b49c4d81a8250a88039f2f10a81e4a6c4f23bc304ba93acde85b82d6157bc56ab0932883eb9a4d02deab60db0517dd46c8fc5926ea975fdf82c56c835e5eb7602081543af45394f1a2ce9e9216d8a8c1e766e03c3996e6d6682950b6943d9f1cfad743114b53cb6683adc41315113d64006b11be1783766cecf94580d5fbb2263edfbd847388bbeb1fe17b595266388d18175a735994b34348e01dd62fef168845d64a942472599bc1a2c4173581419f920f2b42a2d675fbea7fe6aa4f24f211d5ca3c90423a625d322a64f60d4b4276a08ea49d85ade43330c07e40210d54b8c8a63e1d651546d8422795d6f0520d836348cfb431c39d35bcf5fa111dbd792cc14198a9481b05875b2deab1b40ac4203d3eb91b32aa5b9fa48ed5ffc8890312a95c7d3985d54f1d295e6ddb610ff9ee3aef46bf25111771dc55d6aeb8d974df1fcd08625f2f049c168dc797764f3f702ce9010cbb35e0a9fd3ff3c4c96865ce19d8fe7618e11ee0f550839391b8f80e26ba8b9acfd31943f21871e9b54f72ec67c8397317e9e90c04c51eda175726a22526b999177302abec3e489bcb70e6b718d90a6b234792bdde47150daa44b086219602e608890214ed6dba9c5fe6cb15590c3be1c3402553f4232c0495d81b2308303b69d841f0f1f0ed08dfccaf5ce42b3b56f7711ec88b0a79c91208b14b04a338b7150ae035432f2ff0143abce002fa91a35e476e62cc16fd18e3bf78a5e915ac75806323ea89f412caac00d8b4376c2ebe50c14acfda93b4b778e18ece9af8073c635dff7135355ce845b5b0700e329a656e40f60aa949ed7c59d6ffd260bbaae475ad5bab34c1ecad1e8de08b4d6800e980bbab39bd59f134373f6e54153a49f46d57b8e2a7f3cd1164ca52544542aa851efb51b8d2025c64b71cc95611b82e12e7f4962ed83fda40514b5f05f6eec7525de3b9835778308ed79667224c490bb384a02f0d337cd4d438895fb97a9f4205d968883a6bfa62d37ca1f90ebb4ee5e8873b716d298a062b395bd16064f4bd6eca1168b515e1ebedbe6a9317e947c23d37b8bc22955bec1e2dc41c6c0e085db6dbcc2330c5f6ab6610e9bd1cc69c8706d87f3b8a9ed5b4059ee0cd1b15aa22d6b29bbc059fa7b1501f6a24bb6d3afc0a8eb4fa05fce207f9edce17ba9d1875523a29726edccd20057e2bb339f0d412cf032f9318d9e33c294ac51ae6efa829d9d73b8482f3e3c1a3a3fb1794e99b23d3da713e30b60be65ecfe0b2b84f49606be1a4956c6c8bb171cde5498f26863075278b079191869315a8cdae104413ae0fe5ff629682f43dbc48cf6ccf010aeaf7b35ec75ca238694c333bfc277c8ab619d5423eab024d1c4d249ef5a14cb9c632cad658d20e84ebecbd82500877024afae031ae4c1f495374b009d90383664cb9d45ffe0cee2e95c67c30a4426f3bd02ed76f18e6a4f116d36fdbb70884f4f333b0740427ccc86b2b641af711734b8b9509e0d695bdecf3ac72474b604f118ad30ea09d58414461b0007a5618ba58f78e96f208421b1674c4cd35ffa41131070432e5f7f9aa1611a966e9627c755dcc53011e0815423a81bb821f13b320235fc38a862af917e18266108eb0bfb75490cb6a2757ad588a04bbba12d088fbdce0d32bda7953dc79713dbac0c7a4c8a9b9d21e578ed8493f413c59ceac2d2b778e9b9d0350512055b58e94d46967c4dff22de606499c7f1c3c19dbbd7673bbf446b6625a1b5357d0327941495b8d324588487d51671683b7c3a098fa05fe72f38318f0fe128b192f734d0ca2791b9cac16d0bf1cc23d150882fa424de9a687a94d0c6d1786af0f0c43c299894a5e1f546272e043b519debc744fd23d3d40082f32db9ed86ed0ad39df0f57d403455b65053ac62f7b50cb0c5c138212333f815ac50fb042783da0ef01e23371f407c01488bf2afa21ebe5e0a8212ea39d197635a781d1b99830683c83da5e94b73b9105c80f70d526ad4db9ac6779facf3bb9844d28f4dab88eb185e928fe65057fe75a69e7379263821611e9f4a68294217604df832f869f63efcec473bce28fd1c5de18b2909c7f5e4a280925d805e0390bff5aa6e2268c6552e10f2cb593848c8817220c4f3357703efbbcff363ebe911c5a9fb9d60e7accd4b222518bfb92b18fac4c4e69bbdbe89d04bd634484a7c5bf6f4fde118eedf19bf8ede6924001267ec68fd15df754039f5a131f6dbd2656061a8a806ea3cea4f18eb6b699fe568add06d5c132840bfa3b8db9c5209c7dc01ea4b9fa4acf427555c07f90f07e13dc9d16d27a8e32cd137e91236a76d784f985c94563e3adaf7e4b170dadcc485e4ed7ff6159f1c73bbcc39bea76459a62bcf616543046fff261582aa7b7af1fd208f8ecc3ee85e3edcff44d5bc4e74b4960bf7f4a0afd9fe133b6421abfa2d06b5a6ec4663f8bf31e1596eef50b91e3fe2a8f0b03b115ed3a90f02fc976adb736d8de2fd97275089266b1f716c71f87e76a507810a53d8a0b1b988ff000f8a5da3c374e064f353d92b629bf2e6a110187ea4125beca318d7ed68f60848c294195d08bba77d87912ab1e4e0f5550cbed4c8dbab41f112d0182071c14be18a3feb637c0731748168380054f255283ba032914ad3cde07cf30cdf87c8b5552663e26beab0792dedeea05895f3e228295595945112c8d10c2b5a66ebc5695d61c2ad8b01f3825403072b99f9c5908a309933d722f049811b83653af17d0fd5551aa0300ea68dbe01503f2c0692e1e64d66e8a26ffd63d3e411d346bb0bff02786120ed679e5fb7ca9fcdc9a395fa495924dc45768b2627fe73bb257e8b76c6c118cbf4acbddae061292dd9d06f6c533e29692042a5c85bbed06389d73412d4fa8ad20aacc77f6a478eac37d24e4e7ffef7ded3624be998f8040f0f4058f52bd0636d7a60f2458070f345693f49b276b9859ad04367026b84ad8ee1ce900348ba713bb0a146142026efc22034abdc5496e4e8485fb4ea75e78a796e455c56df965c59ff054ebcb054136711b68011691cd200a99af5b61211b5a46354655b2ea4b7aeed2939d6160856b3b0ad044d94bf696154693fa23c217d670ffed5b3340794d214de6748384fb5327903bcafdb5cf189335a938e284f1a2901ea625f7fb1b5c35ae87f38b5bf6221a9c5a36e21f4697dc8f2e58ff086e0a563d0442fa2eecada1d7ce23ad39e7ec9aba33d4116153af91b0060d96c46ab1ee8de75f6e4475e459f96d42d046841cf20f61fb8222523e4737654f9b909deee4467f1014511a0034d35e612ce6ae8ff69b08751643c61af89f23665dee93145ca748f49b17bd2ae412c3f7bf9957ebe319cd8ef63fb02757477a201fe44f8e2eb4e20848e3ee5c5e1f58036dd09ba2c21efc39e602d78917709d766d39a3d814e31f53a48312d8f88c9ae881c70a8b8a457e9af20bc049c48f4b15be2deb5ac5693360bc2197cf1d9ed5ff644f3c1137d2a608015f691ed127041a7ccc3b9dd8c9c046d27342cb00aa86d18ce8c7d145d078f3e1678fa4fe1a03f87e8ba5958708cd0b7d04887bd49c77762954e80358a105486cece805ccaa943adbeea23457bbbe29feee2197e58d8b5a01cae06e547e76217173ae6f02e8607e2e5609aa0f8ff7772867986b952053ac62d273d8fae30452153c1f9467427d113fc019a812b0e05bcc7d1f974be207cb1ab4238ca1d08e061d3dd79e64cc927f5107310c2fc76a98a4f536d68c4ae856a45983f35ce36e0890787d22ebb6db10e230deb7f0a99a27dae22ff23dcf471f098c78a11b904efa5228222794f14540b5f2233220e18bba5506d4ac46a1e5a1bd8be07dbae5432af8b0b4ecfd7c5ba3d754626853f9538e43d63f85ef7eb7561042a35730ad8384547c24d3da8f6d4790d04271e21dd5daa3df572443e4faf2f04c465684694f1204c70d4613d403ceb93f3f9cdd167d52dcf82c91362ee7345b7e7a8ef18fd9f94061cc0b352392a2ac268a4df4d36ffafae0ffb57861473cef861544ea53775db5cd87ce2fb3d75afc4080892d0b02647baa75e1470525c8fe1e061dbec4d5bf968c1115d76bade384e3c0d22c972dd92a3fd099e586316080f37776b632f314c7de5a3d88ba9d17fb9a5a69ffaa1fabfa6ff48cf6ac98b46a7bdaf7cb2de8bf35c34957ee5537d8622e335a8203b25b4467e7265f61fb0a7fe6517d3dad950a2e39a95a2eda9e7aaf85367100fef036fd36a6d21996c36346269f833c498a39082992e5ef68d16c76b01574f0b7385aab8aa907fe272489f8bb306c079fb517bca0840646098f3eec73f71b200cd499bf7d417359ad5f5378980057385bb244fa0e766fdf1040d73425741a0d025cc26a8759d83c316289e495f7df7d43144a62ee4b3237bd747754b080ee74fd6d87fb1ad99e72fad680b2ef24a2e781e11871921d38a17cb28e4887e6cef39c4c8fb9c34a8eb5392fb05e34ae59591aee90c906fbe5ca7b4d1fb8e90086c0523df1b9ca7be4bda61bba5e4fb42f963f9117e7cf2235436263a1056d23d03ee6c93e5c60f8e7d1a8c917a145dee0620272675f1d86e9db137fa6828f17ab1d3d08aae74af02aae86293aea9e9d38123ca815ed8334d100d7a3cb7a45ba92f1633b561aaedc767a5d84ddb6aa45dd9f50498d996062d86a4da4315c0a1c264521879165a0c398fe5e4523addd6d499f410fa8292e1d1c7ae40e5b33c2fc7fe77dc908ab2ca2cf589d6b80d281fcd4f161cc8ec82c6fd2c63cbe9ca7953a388cf2b92be48df04a8a9a140a1dc2e726b02c6f00f4c01d6031073d984e20df0cea2de5bbdcf348065516c6a455419ab53889ca427bedb38664a4a001ee1e818d24803b4573a2a6c4cfb9d48ec2593dddc878c26a8e88c09a7c7250b33888820fee8f1828524c3127cd5436c5082e3b76efa63ce402424b005c894c9b8afca180943571b86fb5be1be5a68774fb35e60932ee55f5834caf73a5dac9650dbd2c3adbd93554ae5b546380e7fed01756c699480f90e64713f9e3708dfd72225d6e3a1ccab79d1869d593c93f564295ed3f713b1d0481be6fe892bb8c578cde647aaa7e2d35428b5e521c9f6916108025792a00cf64ff76c017002942e836519bf025a23d879d04e1407b6f393042cf1535bb7637ca8b9b745b09906fedf8bf2a1528a7cd69c5b331a04a986b1b63dee9c65f32dc9aad08b0a9d446e8f98af579f13b9a7b907188f526888e986f80dab1446f850299b7f5b93be12c1ffdc11c5d2c490c572c0e20e7fc51f092bef9d45c6cc809b562c7e50297266419158108ccc5857be382930374330d801cc7ad9e47788e306cab388159bab65db69d12e7e20e15c0be0e65b1012a9f00bfe4bb7e1839b3c05d9eb633268236ba8ce23d2160c219a70a5ee37ee49b45ea161091dddbb6e80857318822eb3ee5e893bd7a9d0f1412657c85d2b756f564c5b9aeeb40db6aaa7c5193b755d88a7700fcc1fae724180cb5c5cbbcafd3dc02d5be5fae14d985879a7d4cb0a12c13efe28829245446b8ce61c462106a293d2f87a528202e37b544770f69f803e5a23a3f208960cf5757a6e37b0c4a9250ebeea4da18579b306fec6a671518e50516f404ddfa16c141b76f513cbb2ce5feed5b07aa7f3dfd1f75333f549cfdf46f87794290a58c257d904816aaa7fd090ef936afd1f53743ebddb9f04af0d6221238eda7b3bc010c22e35e41f3b890ee712a444fb609a8510f31d8304b5ee02946e40fd13030232fb727a5bcd270b88cd85fbb31d720c9f3be5f8ba0ed7f2eb72c7ea86bda67cc249c0ca7c4a3387d6dd78321198918eaeee316d230aeba4a655bfada9440813e4fc83ca4430a46b47f32e09c00895ff7ebe3302fa9e5e1873179fbb7565a7ffd0490e658809f06a05d6a50c1e6fc6a0a2c9484c521f46f10f47252831e35205277ca2363acc63fd77948383888b8cc414036072010a6385307223ed5c224610d7b287dd510c3caa4cf22b309dc82596ed41c2460eed5abea0d44b87e9cddd2645482051cc10d4a9bbeaf2990ca1f9512b867317948c66600bcef8eae9a996fcc2f7a07e4bf72d0057c75249923b02cc5e9757ed62965734542d62b2cfaa1b65be46813c8c16b8a2a5cbf04629a7db8a442296d8d57999a565bc339a845946697ad6e26cc3db0c88a84c66464c68ddc2c423ee6da6172018d0ad48351d1721da0af7c686b7a16b2ed0f81d90e17823c0fbdf078f07c96bda06ab902d51041d560b51177a8e6892ca1374436b57239d53bffff74ca53c8edf7137b5d2e646a11938cd58901f2d96b994683701d85d8b493ddacc80acc52d43859222ffcd753182a084bd8624cd9408e3a47256c9e69b41d034f96e7dc5c20df03ace238a38474b0791ff93fa7dd132feba0d6780ac8b608a02e7f5528c2ba2631053d90f8a74e077a44965f2616472b056b4280e62449344eadfe9b408f6d3ce78bd5ea312c2c85c16fdc82484e3efc98173fd2a7f6b38401f7010eab6a4558b12c72d20263aa8a7dc5dbee5a07a04da7012c62846d9dbfaf2cb3b18e6dbb7862a643543ce6a46e8f819b81623a8e392e59c456133f0de83c52334e21aca879a53b83ab3bd36b7a44c9dd5f6ef5e0c6010ebf0d5e9b92168be0089f6a583e2c45ecd259834e7895b6441dcf241f7ea3608b69cc89a6520a92270f666f07aa7f550af8c9fb334b6ea69554761fc304c396e5784012117dceddd571fc7f04ee632f23a77a60a21fc5b53681615b7a52291f1cbf42bdc6a7f71db7313a245844f91882bfc1db449f281cf3f21bc4c8a85dbe85e79fa5e0ade8c10fffd1a99416e1244383a62d94314af1f1299d9e32c9ce68f293e2a0d5258c427428ef80483bdd6c774889cb40dd28bad36eac0a36dd05c050a730c926b5e3fc1d852f0877420aee2a148d686dfaf5d7b0600a591daee1fd081cd0a7445f26592ef94b89986057e525b00525a7fb50dc6b5ce0a5d08bb5edfa65ea87e23828bca55fa5f5b0740fa5d643eb8038c2194b6e9c5ff8cd011a378ab0284c312b6832987e9127cd0c25a4eed2d0439599a6a413daaa572c69d36c74569c300bc14ca8de676f054dc11b4c6b31ce276b0868ade8b3307eeb84093f21482fb2b98874d9d94e2c0724bfb47be8b12c0350f7520beb20f0a1eddaaff86d64b691c00460c4c50561cfa1c984059cab711ab5c3097de83cb22bdcba3b1c8c50fe00483b5fce5583850fbb9b3d078fd2762d828dac8298e9041c36df8596fe32acf6a6a7cf5cc22c051e3b978c112e312d90a77224a74b975e8ae23fa70054277c7e8c215c5552c334c96fd49b88e3b8d9e2403c4c95ec8cd1494b6a93c9304c08787f2c3d5be29564b470c0c94388ddac1ea207d093fec6d5378d8ab03e75267dcc567940d75f3331c3537b76eca5138692f298063d3118810f3ec64f27587a23c40ab1adb33fbf5cc9a2ab36e42cb314fd314becb02cfb9f5e9af7e224438c6b522c02b2682f910f0ae6adde730884350871b8b15269539b56e1686a7f8166170b452d2806e6ee2c7c5283ceab7318800dbeaf0e536771274d2bd12e9eb2dda2c4d6e57406eac35e711bbcdef1f6979a9091165cd56a2f1cd6103338eade386104acbd8996a42d1ea4d71aa70f095a6a525e20e67745b9b9788626e84265b947b734e7cb81e47b7d4172da13c0d119ebfe9b3fb3cc6c9f7ba68016542bd41b181453f2b6d05461d494d8fdfd9a4e072159d5ab1b5b3fa45734b3b5d839e48bcfa74414f9e17ec0d4312fd957b782cf07a84c1706c8965a2d5ab460162c3f8633a37dd089a2ae14e527f14d14b7a52615f39865b484f7c91beff89b618161fa509b98b5a5b2512ddad0633602ff4a511fc31175493da7c7349c5a51c724547bd14d32428e0140e43578528ae1b3f717d5368ad9897bc1c171a326229600511aa07820dbb11e1402d0f9a592b5e1ea8ca419c086981f7e0a03e4e4660e9cb5d623ae4d6fe5491293c3d0f98d70d82d2588e681c670769577c7588f5838d2d7d2112b3daed83cb0e61a9d0ffb23e823a6cee28b6f0c8507b6c1395d820a9513fcfbe60a10e339be635de8bdabd0eb6182fc3084e9e6e1ede1edf1c75720362e954414de9acb591665853a434d1be9743825efc66aeba9d74b004bce8dc7b06139debc21f144bf98ce34311277c02c4f83f8356be55c6400394c555a4554ba96e6bad3b46d446a2ee9439bfce47cce50da82db364eb036d659ce76c5c571cd7473d1661928d1c8f7e18fb7ac425955fdbf61d7c6eaf91792d8fe4a1f72c43bd3fa042ae0b63819c8750658b3c4c68dcf647a1156c0042a68210bea15568f0745750c2492539fdac32899ed724149030203eabe6e4dd4c58d2adb6f5da3be7f8a451204ff2e0f902d9fc60d227683a70ace86d729044c13183edc91821ae1d0d63ecdaeb2f938585a8dd7309fec37a00c3f83ae439b63a4541995d7dd34272bb02f50974a0daf5168ca2b50c0f9086109f5bfb2f353812c152451c5d8ef8cfbaa57b12548d89110f3db6c3816830063212344916e3e6545e5bb1190661e0e4af5c0298fc82d07dc7a6f4e5ae7292a481a49099905ced6aa221bb49c6a8966a47d2540b87d043c443f0dfcd5ae8cde2cc9ce4784b4f7a9c02394962f228f1c215b691aa0a4320c3581db8ae4d9678ba3a725266bf33342f024a42cb7b550464a0b51b26b88997f6c32bdd397e4c7044ab0a56fd173031d5957d3641b96571fd36ac5567085530a1e34a3741826611c00d1aadfc522386345a33551b568cd73031bede4098e613cada04396b35d174120d245f382dcf04e2128df9fc69b301fb7354f6e8a8c0062a0d657d1775f4191eda886e783ab7dbdfecdeaf3cd348df632a04046ffac40ffc295aee51c8354b33b9eb62987b611f9194579111b202fdcc0b784b4a216c66bd5ecb5819d1eb6762d041eb6c3791896a68bcde6abd265dc1842b1c59f59b34f8153c2ee709a904858d135c1c2868ede5ca69509fa09ce04ee7b328743de3b7abcd5132d7feaa343317f361e9d157da39afce2e3d79b0766e44c57dfc2d54e12efbd23b0a1d9a26023a24196b99db8192f90d9202463758a259007d615c3481e9734e7eb8eff7e7b45a25eb08758ae36cc15fe26836d000278d33a61d0e06767228280bb6630e3d4762b17d5e8f60634ac5e334594c0d966d6273014c47337e578a2f3967bece64658ee8941b3d7fdc9478d685434796af449ba6e890a28718c84d079c4f4c4143d14b6b54a4a65e8f37d620851479433b6b419e350352720b527db65254e7fb4cc7808e9c39c5cfb228bb44dd93cb88e2bca1190f8d5c955e495dec7627a95e2d4fd1a1ab4655378aae46ce1b7cbc6b7049af853eec178e83f2462496e9c7dfc60eae5753be59f27675e679ae45f0bafb79a2f79d039a31db05a55276ca2aabc503e57a5fb1df97108eee56c9ceee9dd390bb69a6c8260497e272e0d69c954ca325c1c7395699ab8c23b2ccd42af641dc52587794de9f09ae4d7bfd148541e71e6aa539faa6d03248a5dbb5ce1e3f756f5dcdde3e00c8d43f5bc25dae6031a1c2fe9151b6bd4e8144c5f235ba1d86c99f4d4116d74181a943c70f03565399a1ba1c2c35d3d5f801e3fcb716ca5f1e2a725c7c9186e47783799e0b95e02eedc2794df2d2c15a47bce85aff6d9a877437caa66b6373f701424e56a77648d13b2c11ced9119faec1ebf52f68aea72a7c2ae7ee21dacae95d8e9ce8279704ce78c98dd627837348b59db9052a626471aad23bae556d666bf5fd0d85c019c37e6ded8fdc2430d29dce54f96cce1fa4e005c7fba4697aba23f327554080ac66b98e172f73aad7923012f3374c3cd60a63cd41bb6bec2d23116e11833a2cad7e0fa9cda215ade52c708f8c5b9459f84bde370b9a370a8105c8e9a4e62df855eca165faf60771e91f6736038ac821c3d9ab8e8585f3478d87cf2f29232488805c0e5be2369ce222ac5aa61b078087674335c1a7139f056a6d9e6cdab0ec79667bc7c7ca75c58a781d407944251f3f122da13f99c1d02705d926f5db19f51678a080f51d3d47b9a24493afc5f7bcf471a88a00c2ec70ceda390c44126f15c5bf2c3ac2292ae30efc10f6d8d66b04d1e53b0dbff362f87f687394dfe804aae7b0e4bf1633b926b02ef36aa360fc9aab684c0f5edf9ce76079bf5fbb0c4458be3b7d1e96ec6721870c0ad6f7ce24f814de0edbc98eead77038405171783dbb6b999f22ce7795d2e349e79eab3db58887e88c111de977100cc5c2b66c598dec0c06aeccaa2b812316e56622e9d2c75eb13020fe0851651d8cef09ba003a4fc55e8e68a93b4fba92452c3eb134df1f6647eeab1fb6726d78a9be01348389528fdb1162f249f7d094dfa579ae665bb0b7e2a0d622dd28d3f3723cb524a8bd5fb1d895eb2829f6a0bb7d86cbb348b5b90f3e660ac493329128a05974dab1ed222e257d8a3d38fc1e2a0ea7ab8306c90180e260c0d2b416191c1c910f8b3d3b4c623ea0237b8b54ee9c31c87be5350e07f24dc66b4d88017a55411d1a049dbd53e4bc9da4e7ef5c510b2f4a560235a572b2951024956965d5b6853f9a15b0956083ba751ca7ad0e7cdf67134ab2e219da96d73f7ee1addd061024ba2f92d5c7291f8f0eae112c362a6ffdeec71281b8c56ff661ab35bdf49fd0597d518d55603656615c7e54a2219b7a04a3736e7161b8cc56cc1d60453eb5a8b2ed8f1cd15572ac83dfc60c52d392c3c75c25ea1a7a9d9a5fdcb9b06769fd3d468ae50d482917a35212aa7d2aeb6b86e5b910239232eb02583c7dfeeb3c9abbc57585c70095161f527046926823cebc54344ae09b96d8d0e159ad2f0988e5fe6dcc39b5e0c39271a350a8883e27563f945526a7c9d97ea55b197534d711ae598a29249842c07ef3daffae4e91660f751a9c60d820e534391016146a602eabb382b2e910ac2a7164865282f654188df0eedc1bdb80b7babed00035b82abc20cfc524828e36a1d7249789b24b35000d9db09f20d2e418e51551011da8bdad150f4540650d3268cd23696aa7de110526629038736d30ce26150eea9d51e2386cc46a1441cc4cafabf5b763443071e5730eed54e61035b195e4e23a367c8bdc434e6400036754caedb6d1e3dfa8e46ae4d536d99980b04291c89328b6d9889533ffe9bb817d42c184c481be21430a71cc7d5f9fffdae2ccfab94ad3f49c401768af5408ae736641721c82a9a09fb9ac006d1012d88423d43474595385b7aff602dc0f96c0911b892481d38121710e6e79d7fa09eeca26fffb05a68ed73625a6b080636e4f9d265926dc1c55352c83f6ac48c826eb922842511d1e12f6b842c23cae7a6ea0d821d38b52786d79d882c885a67e21db514627e3076ada56f4100fb444411ff24c9ce94c5180e4493f35f6f7aecd5dcba5abbb0decc97020fd0067cc6b5d170a6b657306d2c7edaf9dc04317c423abf0039c4b8bb43d943b66ad43343bc8e1391b7f4b858aa438fdc6b81c386a29e61b3e9cc8370fcb18c703f58da4d8c19fa7c0cf409c77ba199ea20f3f733fbabed58e27cefe6fcca54825b470787c4b054a1f33eefb6d6d97f6279669d9837fc69740d5da52d6bdf81ad017187ba206d77e58445a1b6f1786106baf719f16c8c586b66a4c279b7fc93634da06ad907c92784a3d20f28a172b94382293dc3a462d490558ec0bf182fbcd2eb7ed31a6617fe848d4fb3abc6b54d9f51a0e13dd3ecf792e8b8716835c10050e90a78ada61bbee24ffea8d6911f0d9fad26f2bf7a01bd4db543a477412b65968dca7edd7de752ac5ee2fbe4ad010a507df7f472dfb930cee6eee5ff68d59738c0d6efb0bd1ac9c3e052a29fb4ba05d7ac3d793d6283a61ababfa5d008e94ad82d45f95e32d6eefa8afd694b731fd5890d0548b6a3617b856b994b8855f98e35cc0bfe855f4ecb2f43da88fc2338f16bbfe85212dbfd92361d774529d5547944b775d812694e72c456fb029e47bbdece491cb4acfdb0dfa47d9a4abe1e6884a2f56c91c556b6d7c71670f5502c3d72eb9bc80596b3279b1293fbdabdc831fc00145a77af901285854f8427bdaf8467d6724a15bdb79908fd2147a4adfaa6b4c46a74cc0c4b7dd282405418e2aceaa9eddf1aa22902c3bcbe4c5ee6e0c2ab1d6a6db3c173415d4bae7bef7e3204bcc45464737caed9c7020b015024c0abe8c1b20c3b92235a3281b9cd40aaa2791cf337bc06454e2d9ec42689016cc0bf01030cb2a09057f1ea097a53aea6edf51728e370e609c5b632e891bf0e4e32e2ae1921a34ae17cb65b1490ed45b999d9b6124dfd584d27efeb503fc19d7f24df9170ab9165fdd86065b8599abba2c9777ae6d5f15833e37cc36280419f6c8fd3ac93ef9578ed0f62565a68eecc3d6df54c4dddd61826bf4d8917bb115ef8ce17c32cf187617d2db5994fe05ed177e5df094987d0d95128d6be4ad78ae711cacd744599f5a89cb1a73a29c41fbf541a120b1b34e80f0ed52f302975c2da4b018205e6cdf4eb5c1a30de4b67ba4f850de94313dff029b3066553c740f62da25bc59cd55a8afc6a4bf42aad332601ce370dbdb5777107225d6b74aca64f0e94cd9afb596e27983c9c2a013a687e0685910732bb89871de6db907b63ab05efbc4196c6de1d12a7ddc80e590f7d295724f0a18824200faf18ed86832e83476151f128b231234ca08380d2037828901c08e0480fb4753afbfb71f47756d6016b68c170880330d107010d079c8ae3fe51eea652414a0d4b1c594e49dfa9f0fdc20000f25a31771ac1857b0c3882a188db25837938cb51c980a593544a628e7a23f46ebe371c0ee3319bd88752c5d78ca58e2a5d4c681fa93d57e8adf410b94ae476d855e74d72f661206b73839fa50a65285b63927b9c0b9fa396d776ea743cc8b2602e2a3b9c9387f524ba722e3e5fc31ee45d040d8d161322a4c11aa6bb86a8d4a6f654f08a46a8620850a5883674f1d234664d8d8c4058c80cd98084af9a92c35b36258353f60825544f374d99cf8e35cd14dac08294a3a9abb105973480154e0744c3ff7eaf4edeca91b4a9c481537b2d5a5e70cdd3aa7b75596ec17b328cbe0fc015b0aba368eccd44821e8028365076d49bfe63ba4eb8b7cab5b0dfc3bc84fb034eb569a5006c3a982ebedb178b988841d1e94e0fce079458bdfbc002f17713cc24aa1e098e9d5e0862304f018f32804abeba09d743f855d4f077efc32e8d10bfd86c0213002b24c47ef211baa90c5d1063b0050e068e6f8c01279cc7bed2317c44361862ed95ad74af6d707bcd3447948f1e10c67c3763a1efd60862ef6e6f1ec03d9917730c29ebf2193744ee65839b22738d241e3bbd984f0cb4623f2ef5cc1104f388ef065aef11661c8f00b17ae59759ec9401fadc40ee3c131644050e95c0715bfc567945c6ab3a86ad10ad36e472d1e613c7545de3cc9393224e6a91f6f4bde4235764420fb7fc1e9912c9873909c9b4272e1038eaf2a86f902cb164338cb896962c4ae4bec4c7dc462c33fecfa5323dfd43b64b95dde43a3a00a963e91bf4dbee1fbb3768804194fcff7dd508395179ae96788d9978a352a4da83719fce6e4978848d626489053281b0c6aeceeab693ddee3c17529df0d0926e67a7ae12b9e2609b2a705a3e6e0279009ab183dc81a8c800642326abb9e719e874196d9a457a52bd0876378deaba73dfcf82716298f4d670ac883b348ec9a7b8edd804aba980a4a056f26add2131e5ebedb7b3ed5a5dfd0cb346ccc445db5d9b864c5e27af5d2ae4a687aece667cb4ae7122be071745b6d570d5b47d453bec9cc16b4406b3044632ad7ec190de5d22f0deabcc71f10d8fb383fbe73149810170ffb1526462315b2b74677c82e68412eb36a63c2366ee35c296df723dc5ef0071a8d2ed072c704e667a676a92aee25a3384a23c52b521082a2f20432d34ea79f197b4cca8ab89103a9ce6d367860e418d8b0c363d33df6f901bea81addf31c5122e729cfa92f119ad30fe931d8408b5c03809f43d63aaf663400897379c5b00075d5de9b42835fe03d554432f91c7cc18e29c824da476eb0214ef5b3c3d5a31bfaf2f512227a762d449d283660417dde22ef41f2bd6185f0ec070017d6264607d1497277d449d0a3016a490ab21bfa364977f6f77de0f6ce5df18c253e3a6f5f6a2b9ac85f46f1bcd7a84d8fe59387bcaba030c25ba501ae22d9af8195163d585a03761e7877ce2ae13cc40486a670fe0bd0850f38d36a5c563070b1fbe9f4c24b4dbbcd3e5edee94a8d6c62782c803af53f662827fc203e28a8f9ead71c87edadfd6bcbdd879a15d3e7f11caa3e943dc9c2e519ac6aa06546985898b7b0e24da2921c3f94a1d478203f1bbcec9b7bee203cbec106336fe0f01907e5003d6221f303abb7dc5615bc1284bb10c95669eb0167141ed3bf03aa9f5b61d1f5233f0b602f7648d1effc0bd80afc0e01d9996e423d3b88bad6f4b0b4e9fbdcbbdb8e2d91caff6a8ba374214896da820a69bb99670247aad840d24d82d3bdf3526e97061b8ad9bf0c26f855281e531edc6b373aca5207b15cc4aff05bfb83511f5043b6ea831a442943da93bdb6fb76946dc7e5be8ae608d4c532452784ff71ad992ea223665a53cd80fa36d3c5c7f28dd311b7e7e0da3abda71de4fc35fb10b808abbda6bd22b5d053a626abe42ee127f17f125bb8b51b1ae286eeb7293045922af8fb31d5323ddf9dd91a74c2f1418cd30b0ffd016f929bb119c0b90531f18211a098681d7b1a0664213671fd2e674bf88f284f6819640b637b34193ddfc17fc965b6be59ee1ad28caf5084a5d532f8873c0a23cd89df6213bbb07a268bc9ab2400d0e886e071e335279fb44bda3244270149ce100f55f68b27f899ceb1bf187e162cae13b5b5f7f91d66414afb8d6967a5bdce752c55f629d2ccb9cb572fab301c17b359ae8af51b68552b6f27dd58c72484a36ea19fa76a1757183b8eba871c1d24a27dfa22d789dff234f2d3b2c629fb4262d9bd6c81fc4e520ef60bfa4309f8feb55e884f1fe473aa13ef25ebcf69a78a16b35b797a486f87a22ad9cc1ad6a9937f9bc8a21b115140a1f416541ec6a8c0db6815a16c3dfd05df42ab76f59452b99eec1e22c40e1b66777b946871769806fc14546cb966e6f52eddf0e6fe6090ec924d41748a47f239dc4975fab63f65ff7622ec87453597a272febeb5a2ef8176d44ccbb8061cab3abbbbea82fa4625552bb0b6d58954e4bf51dfe021cadfb16a017143cdf86ef369a89ec7e0933f0d089bb6e52d4af5d4f8be4b56bd0b1357b3c22606c494b59995bdca6eedde40b9dea5f5b7bb281688bdfd27bf4093582a1e1c5d295a3710b8abaf47bd72670855f365e6ad8b08ecf7ac65da04aeb2cb857909ca7e61218a8740bd4f13a99c2ea49a7c978d864ec179963b77c4d7139b34c12c41d17420615d875b33a2e5a0a0c2d68dcbb8b8628a13d533fc69f592cae70267a2bd44f17fcf82bd276cf56c80a2b031de3968e0b65005521863dd54433ede699c6d986b9d6ea0660df78f02528ab9995de3d0363b997760cce45bd502322e4d233a404b7b27cf8507b853a673907bda33b1dae81aa18f01ae59f19dad8fa5847e20ddae9c6586047cab13eca8b7501c34b86e8a843ba7d059e201248b266ce6e6061c91e9098b1aab6db4013fcaa10184956a164adc19a0af7421c6e52a4eb3c2df52dc150d8ceb3a4686940d99767ad06f1d932e21938ec3149d91987e301a692ff96d9378c47f1848b1a0071a3a2078f30904ba1bbad37932234715a94e42d78296bb7d640d005650801221f68c3eeaf64d9acf62ea0a22a16f7efd770e7144ebe56f99fab7c32b94b5ad0328f34623a926d6c1eb381045a202c8a3dafdbfe32849dcc8dc5dfe55fd207cb915e040033af23c228e367389b595542327a4da3f5f0537c286c3747e491858972c66c018a36017a3d4b5b1d07f68967bfc472854bbd79970dd4a08e3712ea8a6260c39839ac4c76c355b12233cdd362a5b37b384390f105205866f02e35ccca25090fb5511919833ee59bd69fdbfc2b2c262f5afbf8ac7ac36656fe4ee0098794bc5b6e135dcbc507d147c7fcb1cf44f2afda555cc342e2287f0027aebf800e1b5b99157eeb86c6ba3a1cd7acc32dd71a410ee22ad1d7e0c29b680fc41a68c57b5167b1c1ffa2240eafed28878d4dbe8f2fd30f14957d92e66b81de2cac2b220a13cc6dae13518aacef0a6b2244bbfad69e576675eb3cc13667269b6f80305ac7a6ca6be6461aa55c52496a4e456cc8085dae2afa9447d350af55d0adde140c1b6c290d7b4bafb83decd0036753feaacd3c38f99e70af2d443ac7cb01c862a976cfd204626fa94f81b3c80276253faa1483dedf7b63cdf16c51a2d3e122d32db16e6582182311562583958c9304bc10b8736893f244d9a7c6e79c2f26f2d3600943f0041b68c8208a9707ec928411578bd34940b2655c38a75aaf0c7c974e44a40f91b6c15a4da5499b34ddf509b168d1c91c557f5e8231b5db4799920229d9682503e29ea4d9e80049eb01873a6e07ce3d4a976b1e4ea45bed1f6938ca8812c49d36ffdef5f089302b5ba39c1b3f4ea12cdd5f8944e2dee3600905bf4f652cc7575305e3b584ba79fc76f8906af38cc4623df6044dc802c8c16e7534c35af05944ec5410472c75fa174eabf1400ba12988acb9dbf356ba08a14369941d2a91cb6ffe21ca2c908f7186a1457501d04111cd83feb9d668a45b8e6969c3648329d1a2f0d3e889268d4d13360677ab82163dab0f33a715314733eaff6d262793e78b8638a16813ec81898f74b81326069c6a14b198b7a7204886d92079febde7f5329fc0e20db361ac053faf169e4cec0509921417bf24040ebd1e2591b857f3b03a5d38dc1711bc967662102993eac05079097fc9a163cc6e7cbb9afc4bdbe46aa662215640fb1343d971ea7bab7a93464a7dd00874b28d854d631ad85d6068367d80a5dd5c85431595f13d4506ef9734a588a949b011d75424041413b2c9d6077ba42e232f21fa5bbed9f48a8d22e420363cf30a6c5a90870b4ebfc92a5349b675802f239832ef1ca7519404a5c22552a80db881704e5d311e0e5272c99efba4004e281594ef62e792f761e1eeccdb1f411f3dcd9ec531a7c4586220fab4cac3c710f7d42be4079ef3d7e0496ec67c2be09c0153f79e81064b8601a8ccda0b2e3cd9b8940006c6331dc3a395b0f60a41d4f2424ce616e7b75fd675c04e89fe91b42ed0693a0b9f03c0f779ff8056c9e16078deb3305f6c462ad8627b3372251f8e7fc6f0352bbafb8a5673685da284a793e3a051a361fa99d5a5113873f4b8285e189be0d84fd967029e2b2741056b1b0243edfb486d1021e1cb15b04b3cf8a7851f7a6fb5c4e9307928924068fac500874d6f3207888d35aa8ea7d72c89aa2df72ef4bb413b7625e85376d11afe64988ba64170e657ccfca52da956684bc6db34fb062a73f36873f6e987f6477f725ca5921aed170eff2b367b03ad0bd51374c299068b0b0a78319ca666a3cca8a2f42651205beeb86c42f4f536a3698d598705ee80637c7473fb93c409dc1b579872983839b972509ba56525f717d3f224f49707083623405f2df1455abce5ff2bc144d80351ee778bed1e9f40fe5e3e1b6c5b43d19c56b40e38eb996a0883d027e4fbc19bd42b8e71ddef225cabd598f147577c882dbed792674bb9da34e55c1a6f455c51799ea069cf2c853f6d06e11c3b4313315a56ea2c4d2de2f6eea5c0336db48f941e50600c2e1d0a5b1197f1cd450d2f4e24193229d0ee19b9e65034fe22e021640aaec7b35072a027dc69b5ec959a81622cd01b6261e81d106c316fd5642338b7fcb978f839e19342e3f20ba887c98e8d9facd48b8a7fcaee0c768b54bcf2838fb1d967ebea2b885da0ea434f32b0dc36611a940136bb1a8ed2514a962ffbe602a0e5a2ef7399b474aaf5b18b380c2be993368a931339b16b6c5af61807ade14b7909ed04b63fb8876edc201af2ee17d59d10cb92ac217be07fd4d963c7ce71c0c13be8da859b84eca135a06057c8bb204d7fc885b29695911ce1782e61f3751c6346229defd5755d8bb05877a940b9e67c76947f4ced53a28e1615677f8e242815806ace340571c8dcf9c69c45f725f5b8f774a994d458725928688b1f299a7d42a7b80785010864dfe5270e99728170cdfe07a860986d4cca7940d14b6873e58527f9b652b0f1f782a496931dfffc35786d2608f07b447695ddffa38b75958f1e28ab24df1bbd81c2e6354a741688e1f0c14f5fdb7e165f2add7560dc3a6609b6853384e86a76c1ed73dc3b107501c5605f85474bb905f1c708bd3368865a5be81f6559395368e6dce0e7b911365aed22c9aaef2aad6382b8ef258f9059781aadcfa44e7998d3c46b3ecd9ed52f243817514c02524ba4ad4cf1a7a5486c2da7079d16086f75613718fa10929c9c9fcc314a8b769158cc225025dea98b11b83940ae1a1500c2fc414f3b4ff438d305acfba70fe46797c24bba0bfd71f62115c1317e1c2744b7718122f03244bfc4730cb23b19511d3dbd9e90e2cfa41dcb88cfaeb54e602d7ac20f51c8146e8c4e099d21bf3aeabfc6034ad85c5a2ec04cc0e368500e8b5acdbc9e7a70e2f507ce393bbe7bc7d024ca6ced61d8c71772cd58cb3145557b0bdf57935596fb4e6e1b3967d74e9f5ffb66b9dedd8ed43ee7d5a2d2404d01488594c78ead46db44364006fecf8dc78864494980bbf37e5f2a68b7c90accd5d55a01d2c12cc5f2edb493841145180ff72c0d909c4a404a51d11068af52d18bba1a41617876acd37d6212a6afdd4d34e199f636e3fbcbca16715da7531cd2d1600f9c1d3ae07c55bf2e379ce0d6ef29eaa49e740bef6b3a39746295997f140ce1359d0ff02fcbe365fcf95a11fef7bb14b60c53a0ddc80e64eab6a3fa975f52392c6486ca4c046fe860a1bfe1277a3ea703c669368e99c340db31afaac4448596f3ab3a080941e29564aad0fe6f80cfcc47eda2fdf3bb328eda75e113e93b8244d5f4899d7a4f7a38356cdaa6f38ce0a325f0d1bb61cad998090efba6ba6f6eb257173db2ca28744f70ab2393f94ede8a10dfa9a10ea3f839b5aa1c2d48d3911a7ab6434f46deb5b7f91c12d2bf32f5ec089948e92ff90e086d600b1dc6941a5556cb6af9eea1d12d44e02bf51d218152ec6a4473d77477118f6256148fba073a9d015288b85877288977c0b820ee2b8d23496720485ef2faf66939a004d272c079208e63c414ea05ef7440c7578555925a1f6472344e144733fc23b84b610b2bcd844ab41729f7317443bfe12cc44b59b84dd5e065794def1635d2398188533320c608b1e650bdad1a4bd160461d363f22b0674fdaf83c9c48548d5eb0970dd7501c74fb5c3c1257ba3dcf7a1d8117945243f5ac53421c0accb141f8d5f44bf49f573424eca44a250ac8d26f39ec4015da43cbb11ffac42b1484741bc9d197fda8e55002755e3677428d9043bc536895e02f8d958e9734501e52fcba999fb978bf4033969e7d8983378d2e279c2d906223b9c914b31e78de12198e1ee853fe27ffe8f426dce50979eb2293080def6145d86329bdcfe6bec35a425eb1d16f0408bf82ebe4ba2910f8c4f1a3a8e357337be1022cb350c5c5f1e978067b25ce3045dcae2bb4bfc8ed13c3c7e398636b7aa25ffacd30c3d9d79797c60a726d15eb0de63e83a54972002323cf8ceb3ae31f9b2cc58814794b27000eb2907d78629553c91cf895cea3388b9fcfb331a217cb5531dbc5926ecf5c87b7615cf9efea31a78b7dcfbf4e0240a9b34e78d713ef2c385959f2567bd14c50b2919055461e4e3e0f8c492b7a0f8a64372d00e59e1344bc0bac6b4330cce8c9f637694db584d28703ff0da3208399c98e5b36a0ce166a15ceda81e733546111a83bd8fed94a93f1be38a659ef25befc183a2e02b13e28884764ebd625e65cb22b0b96417acd4b7848509f008c8386e32dad9b570e5ad94dce6eab606f3b0da19b16845138a1a24385d2cf6117b940d28f0aefa2454aa2197050637758b1603c0079254cfa38f283863c3249a1826f1c3f057ef8d03e65452e02911ca1b378ea77bd227ed397e08a64c7b32bff63c7904952b0c70caaae01ac1d9efe59ac5066dc263052e9b5697255a1234fe35bf6d8e9cf13180ea305730d7bf29f83779ea9df9533155da3eb482111fa2b363adb6247d3fb6d0622d35379f242fa0db65c736067399a28a2c3d0afe6282101836e251ae9233e1a066c2039536e6574e8156b0d3f997990f14174abde6921fe6cc53598d9db4f428d443b730e766f5f0bad32dc12c0ada800c06d867741646b8d69c592827305559f8f16698cdb2c8819e398e3ea46e15983c8f2c69a5a401950d1c77cc619cc16770fd085353be493a0ec60839c4d4be2d0bdd1c3a317f2437926c6c5f5ccc66ae554718dab570df96569881aad8cf5c7fb96ef5862001ad068b1a7ec4ac1ad097dc1168d341fab16b22dacc1f40a8a10ca2b9f02a215089dc51ef56f71f3cee3f9771b637615f8fa4d51205ad308195f1474b8fb51bce375d5c2e50f780c5b6e2cb36c20350026a95a0d423d67fae4fefaa6e620e2aab207e9dec47c352f6ed439c8bf3077cfc7e9fef03a28bce2a6293e58838c46a534cfc0191433379aacbfb36298a752be9324b6fdfc413c4353099e4bae7ae97127a85a6dfe158e67903cea6582c3251f8172c6e79b2ea7efb25d8a11b3025c2130b56bd6f9f59d237fc5346ac72e1581897038bbee855687fa9e28e8179f3819a8722d0362dc24416b368f2c20d3599371c52688a453455fe5ee6e78b077c801d10a9eca01598fc61752ea0ccee92a5f919b30d176de69aa7acc8824b3dc260a44e88b4739b48ad18e61234b858aad09913d0e7780d5c9c49578c1488d1a360266f71a3e122bc858cb8c5f2e2bcb87c81398a2575aedeb411d081d0c464352323c1342f3673ebea89ee341dbcd62886d0b758fd7e8bcedf42b63c37e7b840315eec82a762f5650f05c6e45e2c7a011b55fadb41ff059010858b8309fec9883e2159c61b260d56169d8e66cc531e941d0458825a05c68ec9f3dfaae4da04564192b0ac92edc4ee03fcbfcb558b2050027f0a53282e62e019acdfeec8c03c57f4010437f6d612228c5e870cff4a2fd8362d3994a3ed41775cffbf1fd12a7f574562545c9e1571ec39de7a2846b73075553cfbe126b9f048b93dcc8f9a6fb0a401efa8cf78a0419f41c44a67d93b7593e2ca55c358fd9f6996999f1a23f0b2369cd23f341ee04ecadb117ee50ece0e227880e3f0ed7ce2056c329a9b9dc113416d10892aacf9fdd482620a34e0c9484e81909caac7fa602cb434a8fb04d89ddc49d5679fc1b2ebd870137f70f1cb52838781606ceed366c440531431d0580902adc09dfb86190b5e2f6bdd871468e5ea2771c472d04df030c72834476bd785b5a77205b186554961c14fbebcfea2040175f93be66e4306ff7607d0ebd5d43371045e452e937e38f7ca6326c3d4217c8e825f9413c1dba19846c2e213978bc51676c0e18d69147b3ea9d7f10a7c54ac84cd793e4d1689d01d168c4b822afd9b1d1713ab6af4bcc6e6a383fc461e617ac2295e58d7a11b4d16788cbe4df76f57f90dbf28f98b36ad3dba7836a817a69a0253bbc4d22e9588d2da429bfd56e47f68e58017cb657faa8b490d0ec97da6dc9f95f603581e330bf643aed2edd3e3da1f95fb6dab48ad8844926e35588a4544829e0c8a29956506f8c7cd44aee9dfa6fc61bc361e1849e6304596c57bdedbc85294122039d8e02ab85f04db13f4217d7e60e65d854617ab9f6a0a47be17517d37bab3ec409a340544a0a26ead48ac4ce540c0041027878c86065abe6a83b2624165e37cc28434a156ebe783477c53a5efb2981fa36c20427cad65c8814abb2b41480648d57fa0326cd86eda1c142e4f746bfeeeabdd4c42c8dec4ec6478aca2ac4976416f845f7a41c7c63c1db8611d7b69fa094212fa636b2075e0b47a83eda80faa43d898aa3a87f88f2545889dae64730a6312c63d24b6a3ca383972e7ad813cda910873e06928e9f48008c6421893455877216151f10c6ba35aa05f79906094ce2d2935aad54da09913f089b3dc794bd0ddb3d7c9733d589790c53d3bac29c46680f28fa5bb42f8cc3383b35fe3e555e6e3b17b0b1db4d34a45dfffc29160f3ee87a04d51af7b5a379cf6dbf77dc837e6a04c2593012db0bd2868662c03f8d0790eb72a275999c9280e023732d1dd714a06e0a38313ef87aaa0e211c2fd36c181bb23b9f146d0a2f632b6a0435739016bb9df46304c7337adc9b03eda169893d4edb0639a8e4f1da04b998da5e644c5f827639663a41fb43299b3a7d840b36f44ac7e83c818ffa537fdf48aa5da199ce009abc71897f717579bdc0854ed51c7262f450d0898b8586eede0d2d307d7b1e07d727498ac5a65a0a45ab91e15c1333f055e9b795c50c76388825b4d72dd69bd5b37091a2f10350517c5b09242d8cea965a7239d421909ca4f0bbb1bb48540d7bb3f06aedb02092ec8afa13748a137e0b7a02b85d84c955c744d204b9753d9b87c25f7345ec1bb5aff7116e006aab3b215d0c1b64cb632c0f989ade41ba3404c236821603b9b427b841bb66895de0adb68e1d33553f51a169ac9579169ea0aac0878c1c46de6630abfacbcdb4dadb5efa3ff8a264ae130c426e916e74b98dde97b2c44352e049783487256538dfb5619413d2c67787e42322993c2cd107c4235b8dce71bdabd2aca9169a9257d9e7743dd3a2efa6bd87e532299600135fa5a27943c48296c60cb3e2bec379a7cafcc8328af18ba7288aa6e963a9dc7d2159c05843936c59756eb57ad63483e26265e224fc3e90c937d0f719c26bf53c2a9bbf6a77b94d51ca73a6556724b3815afa8002ba986e304d4e33fd50927d6f89640f0b4e538515173c2e9bb6595d0e6b71ca77b4c9d4e269c6669a0f7bfe1347a8e53f101cbe54b38dddf7092cf7cc0ca45c2a941516e38a1077f9602278ce7a1f5d677ba78c2029d6ac21f441ac8bfc22ae9a2606a83e4a74ca079156bd6f29437d5b540832b7a5b88df574634f52fe818f33d5c7a9ca4154f44584bb3cf2a0238ced1792848c2349685c0d51687572410c77f1035b47dbbb80a40e14c7352a6ab4b937ba70c47337e0b97fd6a64b1d9a0ca5297a76948b62a0497b3e7b10f4671e9c3b1dec4ac5453e41fa097f482703a85715dea9b06523f1787a2082948aa96cd6f37427f2c451f77197edae433872d336a00f7425346a3b143fbe2fd0a0b1087d0b4958d8bec10ffb644e241f51438e2e352721adc6a719dfa349a7992904b2d133b5dc49c70a6798392dc41351ff5f972c88c1878632d5c26f28f8b514173a80aff47d17500aa0549710856105522776c84dc189b4bc4126771341e91d10f18191741846348bdaf8306d409add0ddaaf0e69ca6f61828393dae6e6368f539427c17be922ef95e822d4ef06ab95dd69f33318c8a0ffd73aeb2844f33bf75e9a9566b236afcffae6a5a7ea6a00b4e0b09ad3e55ac62f177190efa75d4567dd7578e3f7f4ad39f13c9a6241b14d09951bf88b72825d55d46103c25993310fbd11abdf503b6ffc5b9d23f828c48d00463970e2ae8671ea5e4091c1ccfa39c59241f2bc22771acaf819988607f4e5dbf2cfc23e82cff8f282c19e0f127c9a8472f84818e56c09213dfe5a09214d7947d308ddf6b6a8912e872cb3049bf3a71239041c137b76056f6ac95532ce28f4ad06c364f68c2927c9e8d1086d75545f59185e22437a8423271a6b0f8b19123f1bc8b4482849cb9545609bc690cfe8003bf12c417dfe714593008973cf128ca89513eb72108276bf271a8c994684f8a7082367edf4f2ec5785dcddef59a5e46887da2491acf2bf1a41ed8169ad75c253484bdc7ecccd2af1492684569385643ac768c65e769235a94c551a0eed878aae4b36f4a067ac441d8b3d11103020435390aff44ee39c6ce13c6fb147db1dd43e508e93fce27e1a0ea6e25c9fbcc0fa5b3c043337af76560a03ace247e36e8c25b6051cab9d9163e619698137eb891195470322f21efaf42a2a1e5e75385f9bc5837ddab4367a3c6457886ac1ca9b79bd8de68e44b940db61c0b4333bc3fb045eec561448b7217cf770cb8e6d525d3e2c8ab1afb746665476c53a25b1f219aead8bb651f24b9f28b5409d33aa3d6598c9eb3dca24a735735e76175c6ec9721da59a90302d183db39dd35c4cc7d1c239c4a2f6593d08493e1bae192402a197f81e7cd636b70c5ee82689c77c1ada2c053a3a56f704e942113695b43fe0a37879b4c2eb4fe5713d57dec5ef73511ea1df72d30e588d00e766f1721ece23727bedb0f51142211a372e375fe7ffe57fee16eb387ddff7e1ca03ac2408b770a0fdda3bebfc3663e1267fb28b9022462556e3c3ddc3d64ffc6c09bc703ece35a1b0e7a97a2b37eef30e3bcd9c9c64c2c78df71092e72b8dbe7ee8f31536151a4b170ac68e38f302f8825bef49311413d8f3668c6f72e23b615ba88de8ada2f3493d89c4430eadd5f6368a2e403ea78cb762f78db3029f9190b9f0c5fc340c461db9732d0585647b41e99a567b4e513da868f4864db08c5ed64d0f6d7f30a1ccecb7c11ebf281622deaed307116280322f8236f04aa974f48dd673ee7cc6c400abefc2583dcdbce5962033dd31d81337d262e11214dbccb546d06a5825e13081369f7d05465aa6af361769360a13471f116afdd20eb5ff4ab0016d7b6e7922d11d5b4907b8ef1e363bf52ad21bc8b1ab43cbed26340b20bbf2473fe809bca8936bcff444d05df0a04486d5ebd148c64ee7246ed7772f2d97b6d38c943867574b12834e94a7ed1bb0ce4831d5cc431408678c5ff7e0313013741562de927ed987f0f02682831a1ea36f8c581af918a8828c71b4f886066f1b2abc178094137ecf2feb7653bc329fc91240dfc79fdb0d6937e521b84b4cdb2165050b7cfe8c6512bebce2d3322905c4fbe46bd92da275696b24247c674817de1071606d528ba8ce183c340d5d2af07715327682051266a08ddaf1fd3f9dc6ad280cf001a26d7a70d1b6599977ab8fb2255c0fd50786490b4ca5098cd321daffa547deb8186666e6e91ef203bffc22be1df813c87509e915a199fef4fe357b39c3f09f2abe43b40a07ab1a060cc9c3591d648a2fb87c6d6bee746e56e1cfd65389cca5844f97f13ca5e374aa763c4e842a1f5bfa9abacb6b90dcf9565c4e0260d59e7f1669e780001077ce9eebdbff6658e5fbaa8abdf0d7c6cfd2ea19465532b3507e7582b52b5070c797ff96ced61d8203b1e1ac3dc9898c316132abb4d503e65ce2cb29145e6e8602532ffe8e16648ba9fa3f60a4d5c4121cc5cbdf9430e636bb177c81d1477e5662c33971a506a17b55ab8f117fd36cef66720414622266a263ff5ba01f348e1e5d5bf1153abbbe76cce8bf8a652bd3b5ff77800afd49150d9dce6023dd99a84ad9cc93d360b35a9e08c3ec2aca8d74f0735aef02b4a9b6a153427613a27a231bf23bb7d5c767790304efeb00e47c141b874aad81ec0e08f9580c343bc60705aa894d66fe1f6dbbbe107758e506a6689d00e1a3cd1b6a9173e4ca527fa8d3e21bf86ce3c9a2cda824e8aa1ec2662c4cb34194730820202562e4a749170b054db4304d8ffbb555dafc77e15cbc34fef36c106421d07199e771dce077037b6e14214747dcabb2f97aae09763eb338d19ffd10d4f84c700232f8e6e848cf98f551438e5beb469c4d6583734edd4b6f3ef108a26476cdbce5384aa28ea421459330eff097c353f16519319b031345eed2dfd9a986f4bff59a85843988c182a94cd2c23aafcfb6af43d28e40b323b536a330f98ac583d88c0ba5e09ae637fd6f9e1b9da10a272ae068a1c2e82d0262297f580f246fc5fe1d9e5bb655d4a1f0aee6d4b87bdfb45b4052ec0e8dabc9432d7826e4e0e95845b5a7f00d1fabbf247a9ac7c89395877319dcb85b540b0ee19bbed9e7966de857213512266d58276b69e44b44e78ee1f9afa13b988f6bee457fd8677ebf616f3e6d43ce10bb97e41bf5885e524fafd857baf075414730a7b4b12dc6c2e44b4c3a6d58560f5f74fecc0d87ffd2a185fbf138f59b803b4f30319b6f0449d0294a86bfa69cb19b10507070540ce88ff6b7c9b3c777cf7b9787487d04b06bf8dd61339f99b7ebf91f5c9f942dd9e6dd53671a346957fd228cb1a92ae8946ef77650cb6088ee2bff514f7a7db6158f0ae161822687475656e6b54513589bd83c28f7248901cd56ea46d60d459a434a9d1025ed3fe23fa513ca29705168762f7369503ef9fb943723c0ae34efcbf03884865be57e1eddbbcf9caf9b8d2f9b0a976084a1a95d76ae98f474ffe3e8cf43f37a5b29febaaaa4a8b1ed48beef436f9bd8f1ac414ca50d6beac86c7b82c2162e200d6ce3fa3920d78351e1ccf09fc84057cad9b526152d82dfef4fc63f8d7a893597ac890acdc150903b738a6f20f67a8aae648f3cd16fe6744abaafd570f41cc4d9041aa253812d362d13feafbe4af9c7fcd92963cf24438657e3ed85e1537982e72fc3c78efa1fab950fba207ea7b4f8b837c4839c076ac8e3c7e7920a2665c5ceddcfd12e51c411d1a8a12be4f869499aac65ce6a89325c922350213ca81b467909f52824b148f51afa5fb4d82fe88c79101810aa94280005571c5d9c16e56aefca2b1f5e56cd9c0944469f743c58deb376f858ee4b14d4ecdeaefa88ccb54dc60319c0c1f45c50d6437785fa0670b15674f788715a9a0e2c8db2851a4b8b7e344df9735d6e85e9d9e954a891611aa80d2005ff664455ed41c626cf66079aac8e7fb2109d5d8f20ab2a697888490b9631639ab94024f3debe0463483cdcd85508b8ec2fc5a283e75c5c4d4d37a657975b95031f0597837253c66334ece0e5887c2dc9787d98be804b41e014c715fe1166e5f1a6aed183c569e4d681f32ec7fded6a2d9dcecd42d7e23578526b048a41ad6feca4c1a68c70eac3eb68616713ff861edabf813a4bf6adfc287374cba29f2dd4884c3d582a745a5f2e77b1de85b98a950d74bc30604de7352e7e9c29d41abc8a68a4b30e3fb6b3984b81d86a0cc5efa102c973c550487c9c947f6530cc11838dafbf048c8845814662d73c1a9873b53a1587d40577d20de5c3abe47c37efc83cb56a844dbdc708eebf822dff41687fd1bb0a2da72a952e2a5fb252f2dd00dc7883984bd6a787d9b51d2f0254ebd68af16630a4b74573e92a448fe18723aff918dd0049ad5e56f23680c2824322b8cf8db40ecc2dfc4cfbbc7525539c8001b6bb0db170c320436ffec96e8f90208cd901e962050c52f834e5870ab228d16ae9714d84dfdce284f39dc0d58bbf134b346703408f0ab66a700d0884353f83ffb9538fc033dd34a0dca709628d7545f5751bd76e57989e30efe7dea3e5f651b714f561287540ff2d6ad4d750aadb100f6836b4137f65fe2f0541bc94914b5732b1ba641ce6e978ff91a600a418d90c8d38bf36af0401aae396b83831a8ff06a6026db761aece2bba2dd42849b4ea82ca55cd2983453646df4e5e398348be505fd90ce18fbc1313cfae85406ebda2a8589ac0c697491d99601a0dc9922cdb2f410ff9b1993015d3aa69783569da8dc1b9831ccd2f883a7940a95ef6fa85a6558b5710932b139f1cd53c3d8e4b757270bc57461c55e7606476c2532965e0ae97b2079bd478a97e420f1215be514a457f21ee070e0f12fa203b449d04d921ece2d2567d39dbdbf75db9214cb69d1a391f0189b5dedb2caee093d533cc219269af15d98c5d890259e12de1688f2434cc449b56a93090141070123dfff6ae969b47a4c5b5837424309997aa7cd528a1da773c2abbb3f950e66e414121a3cf80df562e809e2fc16e55dd849d57ecba05e371ff50906b5c6fde2df6071e91c597f89b7f38c93b6044160478834a1f6ab97af268b290e9cbbc9f0c3c3113ba945fb138fc181b70b8795a8d5f22d7c5cd58e5ee91c9e5fd61d27ee671278048ed9ed41afcfe1f21cb430da0a851a22a4b442aaec5c232cf5b572773ab5dd42c34bb4261337a2e040eb1dbe5b9b7b79e26f180cd2d44831d77f585e4d407080fecb6d64a40b6f7543657bff81f42d4301e6c8be151f5cd720627167c3036b5c825a49c5c679673fe053146ea2869f2dadf3da1b62fed4ba35f146b1233c7768c3df6cfc4212dff427f33229a240a66f40357fbb625e668b00f0dc62d183d1a872af6a4bec2ed9d865e5101bc7e642ed7290a9dfaee64b579b106478f6d1ef629ef6b85d3a18b110bdc6f08ee27c8d97f198fc230eda994405a9e321864afad6367268d80864f4a7c180e5ddbc7b757c1866291d8e0e82305465d7d0f840377ebdca9223e9bb37acfe2496bce2a0dacdb60be2206abbf3cf548152b2a8b4c7ac201215801240647a3ea82986bfedf0bf364c361ef2622185044eff2aa8b1741bb41e344eaa9baa7808c9a3c17a7afc4ca6c8c81567e989da3cf2c86ba8c204e27e70ce070d6cf5a2b3c38761c0235ea34e833a0a640109b084102908dd1ee224f89a335d59eae014c78cd1201675fd633ea8ee1e7d6ae87b8d464e016784793a921aac78c4027f20c8ccffad56c11c5410499b222d92554afc91f74052ca33926f3e47be806687cdd18837f2cbd61b40177d5b5a08adb14ad911e8b1ea8678128ca8b986a99af370fc7f847e7c08abe7c837307809a9d02bfd30d9ddddea16315f3f7638ffbfde767cda3d0dcb24fd9d2c726732e070c7e4c9acb6e78a010cd866cfa78cfbc21fe80636fc6dd3889a0f312894845d2b5bc5cdc5029d3547cc824ed269691f49f94d3b458c3dc397e8e30e1471a31d03ee7f5033450121b23176252a7720e8c42c8d72a158aa892519774333cadda0f8cba650f6e5963a46d7c5031a98b78ea7639112ba7eb4851202bc87765a50e0476493695039d4f6d15269ca06838ae98b7b0e80191399cf766de9bd4aaed5f9897e0fb6cfaa432cba019d11ba056bb10f3f26e2acef791b228160e4ff4dd3039645f8fc15aaa57f7264ba5e6646cdff4a91caa63dcab6fe9ac41765ce72c7dafffd55e98616eeada3fc9a1a6f7bed1b180029ae747514f17c9979e6a74c22bd03206d8a78944bdc2a017b7383656b675bd36dea7315a9e60933f9a36a9e7003f16e2fbe67837892d34aab81aaf3b75aee2d002dd80eb7111c77eb976b68e56c4ef10b2b688bc3533c32b8c9479eadcc8e18520ae62d3632f856261ce6e7f0ae83249a39dcf65492445c41cf02ca25c55ed77e6a793ffad317c5d9b4763125efeee46a3a54e76fd907198b1f434994e7a4db53eae4e2a07ff6b6a18c0328896729708ef018e40a9ad914f15f2e8cf56ac21dfb2fb7666df918625d150d22218d24fedc6ea082317244de65c0062746f7b008c4b352b24e4eaab8949a7df647f4dd1b4983b80512ed8bbcc8fa75c519e5e7cbec23f2c7c21ed90c71727bc7074f177ad6ebcee6031681061fe2330673a815a66456d5b1d4ce16333bd060f0de52410a129dd42551968c62ec2db0f98edcf949d0a1bda01c3289714790cf0ef6ae3a773db4fcd493895ed34177a43df2f7076842b353c1a3d44c155bc90089a212289232390d1760bbe82ad9d1cc5b717b3d1a080d9b878692d6faea19beca8bddee5fffa3644ffa612144e8f980fe339455c1ca328c3087742a87e2f21b80432406ee49cccc769a93813237af641e178dc6abd4b834bee549c1ce1b780d49b2c64b9348c7b3172d0b97e122bd6362554f522280d46e5197d562af75ed90671d58653560108a982f3666b7aa33473bfdbb2d72cdaa80fdacb559a3ad463da813cb92862c9c257aea2b44379bdd69cb81aaec6b8ed73d542406962e5ef38d44a6e63373ed34348e3652b0ebf72a247d656abe6b5a48bc08e913373a91f11d2219f402ae6f02e0c97f14ee344f119166a373cbf6ce23d3b5061c2fce6fe19cc11347cca901d236ea7cd9bdf068b7ad4e9aa7c954fa729ec7a20d9263937e683a0310fab60745a8eb9155f020d8ef44623622ae674e8bf5cf0d92d006ba50b1fb9c94e1209ba0ba9cee8307d670ee4a99faeca1237f5e2f74b723b51d145283a42d6e5502eb9aca1fe4d5bfb6274235b763d7ac7ec034181d780edf65f096458260e6b18658032d34e87ea0478312f88dc3aaa053c880e01873feec661d97fffd089e7165c8d366575d1a6ce2bef257e8d7047da733aaf31a9bda1342d7d6d945e1c995bbb56039d12b70803652d226bef010d70110b4c0b9a9a0adedc2baa57eb6266d0d436db6a60f81fd2f1f2390aa1d462a3b9a7c5147c5b879bde6d89b5bd311f5a01b84e43b9dd17ca1e0418f9782794bb34616fe73ff9aafcda525c19236a549c2e2a05663cf32c95b3d6ca012fce588634bc6751f8ec095107c0fd70d28d39888ab3b0e4ba8b5dc4fb52b9be9ee07064e58e3b58719f3a98fc6356ff2dcaaaa23b2869ef20ef9357089e9574737559c158167efa51c0a6bdaddeb4cfa00eb67277376c44598783bb213a2e94d255036a6aac3464f866b4f6bec63518046f640261e300e0662924a7f6a1d73f7a8cc47bc2f03f09f5ab91f8743a857c6e96366289145f3cd0ba7748ad425aa5c6a222439a8c76a529049c768c6eadedac6f06c6f0a3559235eaf9369e64ca2b23d1a7482a6c245531f5a324551603cde47fe19a2e42805b735a8448705c090490380ef639435aad62ae7ae4ce5afae20cfe036e3029a723707f668da552949478fc70734397d6d3f8d5955bdeadc47e402cd9925be0abf3a020b19c22a695fd88cc40684fd075e58707b73b7b16f18b41ec4dd21d97b75442bef700627cac64c94d18dd90613b927e125adda1706ede28786401e848b565dfbc6405d42ba4e80ab7017c6dfa8bf61aa26223e849a185d1d0ba195439fdf0f6fddc473bac4c41c62db0d1a10580ea4c8f9841becf58fbb9edfc87568293cc0f37760e7dda5c8a92ff62797ca37f9c000dbfe719aeaac97f36472c05d44664349a55708bcc4a92a386a841de4af4ce6524c313dcf0a0e6985da1570fc4fc1cf8d748321a502389e5d64534eb71bcb892cdff8e3db276d5841423d57eca599d202f7697d840940208a806efe5a56158b3eacc3f2a4241e67ccf099f115492ddae6e311d7bd98bcbe8834ed47ec0f843327cd8fc7ac9bd6363ea7f9d1832cac67d73696248cd6c8a908ff012fc66bbb708ecec30fce1df32731853175530747e9362ad07af2cb524c894b63e6f0cb6cda7c116139f10e82e3cdb79bf668ac7d1917df34667f272770321f325a4c10f265787526940b98479ccce9cdc5bd5621102ff8588acd0f826d3e364e1e71515f14f921c7205c32408c602095520986283a9064a92492b780347370d6b25a0ba4bfe09dca5a68791be164c329d400f40cef5858094179e4cee6851d1254b5b98fc5afffbe917cc266fb089bcfbce1867ea76e55062c59558ebf9cab03dfb563da84a573a292c655ef6c32f0a5ca32c1dfb8ba5d14d93f85c6161eae4dd0190573a9c9e2fa1798e6e98661fdd46af83e5c2559b6d0818b6d8053c946e4dda4ab00a998236371021d8b27434697e1d441cc7889169d1dd83a2c559123907a66a958874d80c6e158f51b2d71839698cfccaa592ced12ba3599840ebeee31f852041015798addb6d1bec90093b1ac1b6e364bb178bfca0c8c55124d29953e0b4707c04c0335123ec5c726ec09c8eb6eea303560712c26cbd56d6162cc0a8b9136b0c960f1348d0c978a3648a6500b534c5e5b506898cb0915539228e426d697467931b594ac7a99236393feba4aa5b0421446746a6cccf98ca74e4d74015ea17e4a7d4755b9b5c284447a37dd20c3e8f4ba99a5bd01b58417fe8d46c6876886a60199612a82bf5944c1db120ab7fb5cf599eebb1496612c871f97dfa404902d44aee2d0d5c3cea60de15288e93ca784c708ad65fa7aed1341c0a5108b769679e0fd207d94983827a5dcbc9e8721d395aa2ddf7f110fc148d006a3bab79cc02d563491d9e833d37e11c6d78078378c18f11d959c602624621fe548d33ed5abdd67451eecc95942b0269590acfe8b5d67def2695860b899eb80b89c3ca996bee868c4a1361539d4195fdf5f5afe919b505ac6fb9737cb98dc86e5d7f250f80fa222ae94f84e66330c2c4476e1539eac0f565b22a4aee749ebaafa0689285bb2a960f389a19e68d0226695998fa6af799d50dde14de43fdca3a1ef6de9d1097f87f8a3ff68b630848f49a7ded4901392eefae01bf1626685c9ffd8bec53803813084a5f9201689412c08e33974bad7d340408d499f0f1d32567c14fdb004bf9c69438d8a1e9d0462017338fbafd492f859f0e308dc52210c69ea47b00a8c2b4aaa16d84f4e16c5d17568ca967f71d3ec247c034efc223cc10935ae95006991b92798bfb91b4b3a18f1ee61e064405d4c0d7dbb5ae418e4a7f38a7439657ace12ebf0702df5870faa24f6c8b13139f16959e133024e4ba38238973df61ec9cefcebbb379ecc652ec001ee31cc0be24868e56bb939c2ea6cc85e849b14ff7dd2f0bafb6cf3fb4d3731b9c6a9153012943c29f10434745e857e391be206bc82813a2530dd7f4bf026a2cd6499b32d17ce2a11bb9daa2f80dbbb2583f61b11cccd53f054e0893a9a1b7537897cab4d72b121f1c1171230048c55918a4dc93803e9d002157a7f42184d480377151b0b680885c5f6d01629ff8710236620ebb8e72028e955a454906326047ac2062216dd1cc323fa251d70722b975b282cb9b20b89dc0c0376ed5922e83c0e477495495bc09ae803defd8afc648f21358b31c3473c68649b32ba59ca4f941922ab3b1783e41653da7a2bce6f3046e326dc6ae5c5dcbe61997075ea8f6980270a6b25e46efbbf39054c27c0ca25b86081f55f7f3eafe72668adad33420f2af6a47a306cc15233765ae205901e0d13e7495e0a9eb482fb742f0d4eb39267d0552f5cd5207a81951dc7474c44af74f8228b5dc992fd48cbd8df8e35750c6cd5833d1ba6c2fd54b295498780f46424080a402bd9f95a71ce91a7a7c876716902f84cb060010f00f4e2812b115b7024068e68796cd506dc23abf936247362475eb5a2344c0786e0504adca99a642d7a6e51aa96dc20eb7fe4cd6fcf1379eca012a53740a6395c2ebdb0914eed641ea332b1c2774acc9ee67d761dada62a446ec830679f531906e726302b13789601c051718c3471f1402f5f3b34e1ff899ee6e1043ff9216952cae7e243c35a3b573538812db56ceb7112495a4bd833598ac5c231a1fc2a73c181a41c7b1c53a9e3489c6c37379ea8947d4953e59af394d406bb677c828c26efd19646e0face3b94ea81d2178baeef03e53b44e99bd96b4a5f6f929372bb46fe0cadaa4a8e65224591c773577400ed214d1487a7b075c164f999608dcce4bcdf383f60d44120ad307627b45f609022ffd89a68eaa06c418a21356cdb5474a031ec182ed13cb772b5007f2138e7d08d934968431dd4d528898a006da8d80de9cf5618e3dbe06eca064ffe4c93dc809b13da03bc0d7db817ceffe470a9e874918ef5a00651d46807874de805a6010378066a777e7903ca1b56cedf54e98542aefe3d9d75982086bf957704e0c52aa28aead0c2e083058b4f9d0f98e5c7660ae14e69d7042d0f8d0c1e1ad84e5ec8c349043802aa48bf5931dbde9aa18c5d185467155f7fbfa614495bf17a968ceff49d57c50824676f4b7acd546a29e4f173ee08b3727bd441432e73c0913032c46f8208116d18f5a07a5b79e54221f4eac144fe6902c9a9ab2c271f71e1bfea33f7bca49512027ef7d21160cdccb0f7da490f2bfb83e26a2895d0a7555c348ab13b1a1c5506348448d374f2205d053ff6e889dd8200f14fa828e18b6bf20d7a5651756581fb1691b6fff8d01ad9a3151520e0db5c570a1b5e1e71b830509a18838f3b4049ed77f9aca5535c941aad80b3e5fa3ab6d1efa7a03eb4701085ef1fcb5695162b4bb081b54632d4e509a3db394ecb90667b5314aace8ffce41f828936183486f91a2641a1197aa596f3f029fa14f55c8b6f8504bafb7b8a65f2225f12c78dd02db65b76326132a24add480beabdb7302c3c63cdfedab75f9a2af35eacfdbff2b40207dac76104b953e3248ec63f535303dfc6523934aa2ce2bc35bbd3c7425655a054c3d64b701b7ed49f222d4e0208d6225130c93ddd7aa16e40b3d7aa8b7a53a4b758ec630a2a0a694fc507ae79aa2ae56a474b7af8cc4e872d52ba3d2b98a2c5591cbe52af43954443ec7199252fd1dce322eef4db53a1b678552d5a2ca39c68b86055444335fb867ccda4573b8f517ae2b3fdb5a705b73e4a917babd2c7d3daa88428a1e71b7de92a4796eaf0631079c881ba9e2c6f234b3ff8146f9b9b357e4d46e051dbe284359db8401f4b1dae5a4eaf3288ab7f6c967ac320a1e2b727c42730dac527760128376b84309912b889bad4d99a5c6a02af8b04d6f37e4c5e376fdbf1ab57ebfc993f0da2bb00646f21ee10157d959f2eaa63f35bd6c54b427c6faa7d58d10148be49610dc52d50ff6173e0ac37cc4edd9beb5e713b9d5478ed3139aa0def60db50ff3ad6961830f38b5a2958f70e709efd1908bcef254a93a10fd222f78164a0d102a83d46b62b2b1bae3d8600200690c64639a04978a9f713097521cee71389541ffea34966da3a374a62295c42579d7b418dc0817c9338c334046651f57cb43045d274768dc8d048a2bcaa19c65dc5e97a811b94e656e1d09ff0db2f90bbb2d164eabf9bb97506cb9ed6ab38cf26efbb5f084284ccc485f6dcc890c496302b2fe04e87726b99010c0008241c2dc05e5200effd5df836136ed33e104548a7578e3ae1f68c8c70d831878cc49d4de2e809d83b6b2cb21d0cb71a6641adff6ed1d260065db5f575b19f3d9187cdcc830fb9087e20578cc8e39ad5d6f1395d22f04e1d3e1fcd6aec4c73c8109951ecfff5d4dfaaad78269d2dd0b1213589c5fe7379ff9d24c7ca241fd0c961579de57ab31242539a57746a1284b5cda4bc9f524af67de1e31c6a38a70ca54d521c9b77832cb209ce4102326b2f402a42f4416a5968e82f3f61abeec4ba52088657ad4eca71598105b1951a7f283dd5bdc261e570de6180a3b560cb3230935ae924f89a49310150f1a12ac54c275925b4b14c6a619574c42aad290177f287cd5c9a8a16ed89242165934296f19747bb528aa4585e245e9cde6a1b9215da9706ae0469316426c799a05d8942e20adf91e5b439cd7b251cf89534da505a69f5f5cb401068a3857810c07f30ba242a55bb133b4e690b60971cee46bb229008f47f22fbcc2a7770bc6ae172b0450ede525a95b4e6ae9629d280ba3be28debbbd81d936562ba0679d3ba26b39b59a7dd802d6bcd682c681bbfd4149fa0a54b950512916d00dab8ba2ee9888da8dc4636f4f7af4f3b201db8c34f30b7fabef10f45fdc173b7507d04ad521093845f5d9ba1042a884b7c90aa8388c95b59ed92efd9b8efd01c51e4bfd2632a45f9034e0c9abab1834f6ba6808698a8b2d0d1267776cf709d4bca7230e88db26747967196955dee99cee542506e54477f2cef6c07b2c330c5f14616368a63f6c2d1f48182c28713867b9be438fa5bdcbaba1ed4314a900f7c148a803bbe1bd76f055cbee4b9d5284a2c72cab29e88510516672c6f81abb0d324fe244c60c10121d1711a243aeee140a2e382bf1d338061011dde5b7566945bfa150fdee167d9aa103f37c74dbc2cf0d4db79428f28b1672670868599414a0b622ce5eed6630f24c5829b31bd5098f6dd85347b4c1cb4f3f0e6116f085a35ba19d248a0e6141a37737bfb8871bcc825adf0ad959d535b51cb256134da59df6afeae4a45e1835a4d22aa7292a2c4684f0cf55154e55363910e354c4295ba1248a8c78cd0acf4a3b69aa14d618245639ce5b300232529171cfe58b6dcc217cb75276f77e83f73a9d9444833ed1596e10684396e8fa15cf35715c9035a524db3de6f1ecd9ab29952638cf2fd5efc9ccff587c39599e01d674856f08c9c962e141223a1162f642d18bd5883d1e320fda14412421444c749204d4ec164be395e2841857a122dec1a3cc6f71b3edabf734b9476245dc66273931441642711178d526a4e44c24cab75975e0f5240982d720248cad49635ee38b9fa0809f3b3c04a955ce2c0c0ac9f30ab38cf398407a6acd4d5a2651ef7f1b7d6ab391a80997d5b8f38009fac865cd6cae6d95a017f79b9faf2c3b393d1028d1b8544a9cd03e485e68148f4f32d23ef9f47abe03448dfd18450515f93d8e028c50493ceef974ba58a2ddb45680fdbac18181bb863414ccbd75596d7707f51e438687dcb361d3809e87d6a0d723d5037c5bef9795303e99b07821800c3eae3add9295fb57dfd1c3d19c66be30cdb39bd5651352617c557cf5c8f863c94a318c048b613699df215c0e3422a2e211d55dc16dc105eee5092598da68232b9fd5f1c2937e92ec69584ef8924a35e7374671f91757014c855894dd83081c178f80d99bd9b0302874ba4412c75fca2eb43cd2786379b3c00483c78ce8dfe4028f865fcc3579bedf4186e78dc8a4380a97b641f92f7953c09203f2a2b255e2f2846b94a412168050b1005820cdd7c8def6450fb3a343a37d950813f7c32b0c634677655ecb10f7a7fa6ade00f551700482f19c2eb0929cfbc2a897bf721f54639a6371fc8d1383bf951d9ac723f2428e90345f47f194db7db6d14b9b8aa1ab7130a412673412e2b58bbd90d1c95230e172a222de1eca01a350ed2532dece36824ddcbc76174bac9cefcfc67bbc3885a017a67ecd87b95c9691b56b8ccfad37951c9d3eedb8ed6feb5fa3ab54d7730f1fe5e64a69d6b499b6194a267aa50be30abe01335a502b5ab9ed950e610a202d8a79077ef79110c49d12121966918dc6f75db857508bdbf4a5e9f97cd545049e7df2cac96a57dd7b6b778756eeaf6dd6ea950fbbdd547cda5db507945261e7c079882dc115386a40e2cb8ad36d9f0161d42eed2b1cc14de79e285407c20564a52e7faa91c338b2bf7eb1eb6751244c30d3cdb0a749109710c254ea53f1b53cdd7f63a4c4a3bb465787d57ed77cd8afb1c5e0fb089ff7f8024a569ec971a0c6f52664a2c61896ee88c5b5c60eb1e043d42f81ee82378016e4dcefe2dadfb8b749579a061101d75eb7df9f18f420cf0f5f59349081047155975a3daed0f9398ead556904714f143a358df762cb91267cdf8d1d986e71e57bc7a779cdd2d88bb3338842fb03cf407046ac03a8e58209e514d076d682a4a9a83948eecddb3a32b8e2e02e86e4e4daad70ecf165df7d8d8318ae1e24ab23cc88a018002d0964c9b5b0f79ca312830d001d79ee38864e0e062427f4b1638d6d68f7624216defbdb7dc524a99a40cc308a6087d082d70ceb67ff3c5450a8639db35f4971299549a9c5765c996dc969ee75096e30d7c69fe72d77b7bc0b6cf6956fa8b88ffcd9a36b25f7dbe14cce961397485a65d8af66e60d39f3ed469e9088753aaec88845672c3c5d23cad78929513aeea638c372e9ffc4ad8c691b81ff5749ef775d756b0470c9aa64d25e4f9390e246739231227e3a248da4afab377eafec690a27d4f77faa610a0b514ed93be1e35c6020240b77e00e9ebf1255a89e99a4e5c88af51242c47a63c87f4cf02b845cf15b347ce3a2bba93493539a11904ff73a42a0925947d148832ed2862edf60c517bf0d4c4d972c6bdc72787544931d030c70af054e29946b0942452524a75644e4aeea5a623c76b360d5b8ede6f447a1b9bd54a14ff41d0f35e4a23bb2342d2588a1d4c7aa4702c62a4ab14bba7b233625729c56efb77d1b710dea61f0f747b9d178e475cfb227e9de76dfa1ca75f64ff7936fec545ae52fb953b793be795cdca0ab41cd02131153ae935568a9456eb4820e213c4c26495cc949f268bce688d74d17f5e81ce9cceb6bb10e7719e2af2fcd12b9dee49706d77775a379f9e9e5aedc59367eecc1d2299f29f5d4c2fb61f394266842cbaf76af8a6b6ad47de9bf61ac59b9db366ced983edd307c7186f5c95bd7e0c05f1aa8fbf1d7cdfef3c2a6f6eb5dd4b591197dd88711b9e9238d3c89cf17fc57cc47e78d82a33229319d9fef3be6236a431ce6d24ecd39ee7fd80dae6674553b18cbffb5ada773794b2bad5a86df959b2a6cc4a9cf99a33584b9afa89e5397311898cb266124fbd827cb1fd6dd8459daf4934f146dd851d9ca29b37f371bd5eab54699a667fde4a2badf56bc92ac5ed65cb952dbbbd9d9cf53267b6958c8b363c8563a4eac56e1a8a52d51dc1de5ba94f1b836a1feb2776905b5221cf772abfa9235fdc9d886e3a9d61895459d30438992aa1c0a62f5396c3c0a63f6bb5ee93e9df79ea8a7455e4f9ddf5be7aede9e48bac9eec8187b4f5e9b67327888e1c09c3b73342be61e30308af82fb7654641a04c7d9a7f4ed0f2efaf7f23f84112e7a1132a2487dfc00c4b51f0fb9692804c8c38c27e4e009db5a1b2105c05db56fb5717505043b7aca99b2a64cd9975b06b6f4beb913448aecb9e84f8790a7c49b942ac95d0163ad9ba22b4247843c3b29ba214c8cb54e085164cd8aff20ae8be982d0795acc800142d6b4ee07f5ced911c9537b695ae7833c67d7833c3b2872f7baf56a1a0ff2098a0b184328506b61e5bc83fc044aca8a13292a2a3ac89f9283dce1a003cae28a2a706c88d9b0f603e3d770525474836c031d62718ac59ac85d0d344deb68c0449e590b1d36acf9e46e069af62f0331f5a5667831c833623a0d6f1cb7616d89dcc1a07b41e782dcf588575e21abc0b12146eb5a9035ad6341d6b46e059aa67543ecacdb8b8e6291e75b592867ce7b87e9d3e7fccd04f265e6c0eda94496d3a2208f187bdcf6f79b4daae60db75bd0a94c973fe5cff972b6a0935e73da9d53cfabab3895aa99b7a3b6e329311d4da99adb358fa2e18b4ddfbf9062d389378f6a6f3be7aeb9cfc3eaf9e7399523f98dbeed407cba16d230853420d9322cc2579d7c192b6cfb77d3c6b661214ca756d850a4087d4541eb4ca609aaf2a6c67e9a0a42a63fbebd3abc0b8e0d3145a40a08579bf941d6340a0d2cacd08135b3892211bc59412524e4838dd325992d1f06fff780eb62a0c8b4f3b4982193bd525bbe4b8c0d3cc8dfc89323d24c86b161079992b2040292b1e5531e4896486910a67842c6d8f2a95ef9402732fd112c9580e105890b926d579754e9a0c4345be0525d2ee6209b4e4e4d4e1e07f904c5058ca12115a0c0969c814014961f9494951ba4a8a8d8406545874749f96f6285450b14198c4c0b2ed680a5250b50e622db34c82d303cd496ef92c51555fc8be26ac54486f16b38298229da3eafb13031e26264cf20eb108b138c0c421730986062e0f25292f39c59e22546194a5bba0b0652dec8d166cbf1652ad370e3fe4571b57a810c982b48b11ddea6465c0023a28cacf8ef11535f6a864759af16e4193156c058416ab17d94585801a341dd3f278adbca6563c38218992e38221722242b905179e0364445c3932a259ec68cc7c51edf5d2ac8332b6f4ad65be17285ac628338d9061c43dd258a49e4550dac33a62957ae41f3350475c8ac9d021a1b3cf0ffb77c18c9a24033db47d6c614c8b51dc843419e3f52201b6ad0ac6668d0a86864686266a4441a181934315e685c421afd305a6868686868586868686852685668545068684a4a9986868686066b34978686c656ead37746f7693eb9a554d950c2aeeb78a1c5cea53f2bc6d6efadef9a7ea5f7beae7c17a736ab0e826cbda513b018da4b1892bb1087ccc52ddcc2aeb585f3358c3ba03ca32cd2536f1bfdf6a4cd6e5c28e70cf79dc66164771bedbe54e2d979a673d1a6db08847e381e117a7f0120bbfb90fb4dd37de9eeec08847bd41479d480b6ec9e6af2466e6aaa97d2afe5799ba6816c4ee330b2b75b4b9c6b5074f2654c99d1ae7b8efb3c278934e79c3b6b2d2709b6e7e3fc7488b2ee4b59739530b2f3d324c89aeb2af93c52a19dbbcfe128049d6d5bcf90edbba4df0ebcbbbf3b94b50dd194cb6bb6998b4ac89acd0b29fa7fe156b4c336db61db86282be5455333af4981b9e885ac49a9226f432fca4a89d114cc6b52845cac42d6a46c21c594174aa6642a9b9af85a261f174b3b7f8ec7282b6588a65284bc267bca16b2c624c52f4c19a2ac0fe6a50ced6cba51fa91b433659d64aff1507964016d7727445ef3c9bc0b59f3652145304856c9fb8f5edb0f246ff2639c3308fe8fe2e6483fae36c7daa41f599be371940f0579ccb6647ee983c9be2c3e216d77738f3411e98468a424d841badcd32448d6eda14da051d81cbdc2e628d1e69ec6e44d7e2e34cd4c82ed1cbf38bc3d27443edb33ad78931ebf7f3b6c3bff564431ce9c648d30f6b8157d423be09dc3924f0af227246ff2e8a5fca4ec3eef4c7a0aeeeebd70b449d86389094ce59ee51ed4edfe54832e3e016f9aa708022ce60570c613720005704aaf9993524a299d5ec46fa1596ab7507b6a679ba31bfd31070a3950c881c2179dfd393bf7e85747d65a9b4bbb3e11513f7ea4f4f88e8b51782931618032e5af2259392e5bc7268529b3e2297fb909e55963aa9d616fea6aa28661f02663e36270dd4be7b9785f58bf911e919e9461d45c6a2995b06855ab359798564c279593498abd285bd34f53204d45e10405a24014887282926292a272525931adb094b0b4945a6064184f7a3d3a65fc7978db2274f15c5eba97185c0c199b0c180c236a62eaa666d81931354686caa85ce5d1b096864c8c4a3503ca605e18adf5070fe8e070cad4bd7e752e101b2eaeecf5173550a3f8b1d31f0d36fd5e7bf1fff07e10117577a355de5cceb4e5af7849e24000f4b21e82076515018189130139e3bfc92fa44c025af851ede6949b3596ce8a5e94443f7e10fd18420822cec5b56048dbda1097eb1eb1ed50d8293665414152e56f711133ae32a00342080241743d50cffb5adb7bdf0ebeedd3ea75e2ec9944c4ee7fc25c946216213271661472c67f1e9946867089d87006d54d07ec1b4df0372c480a17b3c85363fd234758db7c0bc39c76039a41beb963af868b1862be8080808080a4ca1f02410c710c10e27c749df755cd4e1e6ebe5ce4a1ac49c467131367e2204ba183703601843f1e2efa7b5f065f404e006970fbb629db8a4cfd80fa94a294a6adb624256bb56a5198cf8ed36aaf66e38608c4be1b963594dee3a2af8020de9eb248a3e76a3c174df9f5f15d3882d88577f793d3736fdae4b6b0e33e7bcaf5ebe132c8d7a32cd2886aa28cf7f87017f6b4dd3007f69d52c43f1fab7adc553f8c2bcdb7527be347a1bb5cecf121f286d7dcbae3f9d7a34d4edee03b03dab80ab4619f6af83f4e284fcde6da2ce0080e81a8a00d2d1c6512d046adf66ed6daab6199efd57e2561528336365aa85dcc7d3e892f1ffc4eb40333f63bccbd36afbd2f5f3e36e26a1e00cac3ddf6abaa6e9562ee6a9de7799d63ee6a20075af73f6ee3b75cb555bb5e7d5949b101e78cbf9c610785cf076d73ef53aa34fcda56d90a2e0004a2fbba8db332050b79b5ee6e587bab69186fda37aaf4da13962b392f7ebac377a7458c05e89b5d5b9287bda68af5efcd936bcdb083429e2feffd5a7744c4a69cadf64ab1be36b2770356aa2c076657bab04fc8cc7adedebfd6fd5aef105e33599f17843b5177e3c10eb3441df8a573aee3b0a7bde3f276451da2a8853c7cf4f0430f39e3e128b5805fe8e791602f45fcd29fc39834d23c7bb58f1e7ef0d4c4e9c18354f9631e3c629addc1f4cdad66efb5f75e0d5b50c3ce840753387ff560b272e68fee043025974cd8e8afb747f0ae7629deed2b9e38da4b2466aeb66d5b572dce0135bcca363bc6f2d71172402320377166b5e069cef8774fc839f266be7fca6b7a1048592ec569e238147ef257c76d233b4b9254eb515a6d47bb23b5dacbbd88783b81f84d505bca648131c6d58e3234bccdb9e7b67d2dfb1b273b3b317ed951ad8643aeeba8bddce6bd940f62199ece3285bfd3b86edef77d78885d8b789fdb942d5560d39f9f47aac2f5a99a766987e577576aeeb3bd8634228d4824522e7d5fcb7ef6b67c5166256da462b6375dd54e5751a9a43b82cb6bb86d635e254343e86d9113b65b190fc9922bbdfd8ca6a13f089596d1f54f30f616d601683a31e11034e5847c871451d65c42367166124e1435a18495b9847c938727e663741027209a20c40f2213ecf2e9f2e99a2eeff321d36c5627ab550f3c6227284959313f6619191da35b3f19b4526cfa471821ca22db5a295c9cae1c6461386c9adaf4b564d918968cea5fde704f5fa565748cccdf596d6152683db0413648e6c2a451f8c9ea6bb6a33874b9a81705790dcdef6f61255f2b974a1f0fa4115471854d332db2a78b04923567fce849a4507e3a0fcb5c992a3365fa4b9c730a7bfe2c02522171dc88912af6fc099b40ce7218d3cf9f4dcc60067196cf84ec971fe7903de77c0d481c2a64ce0841c39e6f84bc217df8a39cb97c10ce72428b3ddf0012873af173be68ca7f90371eee7e5223307e6c19497b1a59c91b8e45e7277168f5d9b3199e0a47927f0d3271ea09e409b6ff585f9465c570c46e64e2582173c67f74af45b5a8d29975c1c86484634632716a9239e39fc4916c7f9f51960df2d98bcf844c9c3a9b09d95e652eaed0e5c4c4a9489038b1bdea70c46f64e254235e5d94229938d5890c231c73cbc812ae388f8af3fc3631f95aa612106502a2645688ec24b442b6bf34a945b8a888ba041f25816d7282124aa942a14e4c4e269b6488cf15d253c9b0fd4f25a56c836636e84d48a34f86a424cb3224dbffc4ebf0cbc8eb6564fba3ee8efdc245776b0639e37f87b870385e218e06a9727f3044a9bacaaa90f72fceb2f4c6a63236362da127960da229c7a9b9ca58159255998bfe41d8066dcff58571b645d6b5ddae7cad2a9311a5aacad8b65fabae475cf46e166151648f5821175d86459e3fda29d4778d44eba52105646c5717274a45f9e44a8f0fd06bbaa66b859447a4eb93f21b5c53b6bb2a038baffe8d0a3f224d51418c4d1ccd9ee4c4993875e2cc8f5ad91ec0d5d1c2eba22967c246bdcd71ecc7666b5ed775d10ecc54df77e27497053e59d73571ae0a268b47ab876e09b9c6268ec450cc169dc90267ca53266bba422aa628643344b4a7cf9448c0b1e5d78433b6cc5bfef6988ba5743cbce22d4ccdd8f60029046cdae364228113c682070f9225e66f36e10382d5451fab1c1993b284074d19c9f33b4f4f9daa7748d12a010859d790706cfb1b12b615c2a6323e1adbd60020effb1d27a78f624895953a32b65580894c59967d171000d2aecfc344025f8fd3aedf719e0e564276c228a5b025151b0bdbca60534f3fe03b8bfd5301b53a726c5dd9fc88a2bdf4e57f05d4b0b8927942a7a115221e3c7ee4b5f50cdd8bbce99c72b46ef545dee02d4519e958bb9af42695b1e1b117ac6511d7ab5dcd8aa27804f145de781abe163f31afcb9bf9f7630f036d7e9833fed7ee206b100c701102fec3c449809cf14fb21dc902a4caff08104295faa6736e1b4ea9f24bede71a4bb1630c44100c789142580b41275fc6eab3bdde0e7b9f98573bf6d2c66ac583a6b28f9c1b3636f27ad0f697bf26d5325fedf10144d4941e6791a84737038c1ea90764e891461103a547931e4db3ed1fead1d36f828d948a1652d168222262aae8d114dbfe29fe287a34115167d1c9887a9df6887a394f127b448d2843b67fc904ab7b2415a1f88c294c6cff4f8f6e863da25e295718bd9d917a00a35edb5f33c1b63b8f0b711775ed354b80440aec41b4d7f61d159f1bbec3112f105149ddfd059d7c39e7e4e2bff5c2852ca994aa18e08e8a6dbf0a22482aa6b578af56a268847d8bb0ab84d15d8974b8f428a2c67b74d9b7017a6af8d69f9abd965eaaeb765d4db092346c7da0b3f7c7e675fb4a7f7bd9b325996d2772249b4ea1e6206f8f3d1f2eeed5ee86f01a7bb59d19640a99aef00a8de0cef42d72d16f12173d11cc68c9a37ef678cde644ce9a3e3e856fbe6806e9cc936cee713887b8e83d21c8dcbba60f65555238d69e99ff286b5fabfb14961f6b8fc62344597793e1d069c8b33d0779bcb3fdbddcb4e7f27a7cc35aa26c5adaf628888aae6aafc71b1224d71f3dd72888b262bcbfd795c211cce1f8e18f4641381c57bf85a34d8c171b1b97d52a0c37d9ca4bca8211aa84292ff1147bfbe90d71d173cdcf8711a678343d977b43bce67b7fafa7d6aff5592a78200d4de181bdfd0c3d4985c6c3023bfd26a3fe776662f22ae1985336194a38627024038137b14f7ef45ca3a00fe4f9e32828c7515aee134d44dde328685c39e971658f9b6c5cf9e9eaf124bbfefc78f0212742804b9e7e8927d93dd5c76b346f81f15a7479d1d1c38b76d1a1d6fa350cdd320bc7eab38407b2f663edd96156bab33bbbb36e467f8a5ced71d181bc46299b541ad955b6356d0917dd5aa0b5fd8eb9ad846d8e6e321785b623f3c74da6d51eaf59c26bae46a75c916d7068c5c11f7418ef8e8435207566c04ad2cb39db73267f1c3aa2432d214ff97da7d2836ef99476540af99aced5b13a1df5acae3a54a7b39ed5aed35dcfeaa9a3e95baa80ed349d098402a13e8dd0c9270e30d7a05343e93af2f3016f2f406cb444901864aca586db56e60cbdbb525b356d37a7abc452b4f63165e595bcb29dd378e2af3fefd703a36219bfc573f7d05beb269631d2428d065d9dc55c4e0e0776861c9054597b35cfead80d540dd77aebbd15e36dbb320b03428af6ab8551d60744ca12b69bc4843060b52d9c52c5d5b7d66e92656134e52098b3856d0f1d30e9a88653e3f0b53ec2320b34fb721dc7719ce7d10d773c1750245cdb67dbb51073b66b9558ded8c7e128c49c9520d797da8f251b7aa7442662d297154f1e2a0d92e0c173b6e92c0dddfc6e6abae7defe92447727a7fb967403a9f388eeda0dc4ce99834ea587b6e56b1a4e571da4b556207318d0f67df92514d8feb3befc1b156dd3276d4b430bc835ec1b4ea9aa4878e5a2932f4f689c363d4e5e9bed9681ee87ca8553de60354fd3407861f740c84729410245d08d5f126d203a4074bcde709c41b8cf41bab7a824640bc8a25d04ddf7a58e94354620dbee00b2a9d419c1ed54577d3f1e6ca84f60c02fb594d2fa8d708801b754bc96628ce9944e3ae5532a29650285edf93b1b465952ca39db72166df9538ab984b37266135b4e27c64964cb6780b382905a4049996406d992ca937c20c6a725369365c25a76b6a4b38663ae5f388a7b8ec271b5670e479b3d7d481365c2c070c4a870cce09f4cd19e86e88e4938e25238661f1f87954ce17c957004e905615773d88afa8e0f68b273da0129f5d9730e8dc2d1e60bc795178ee2d770047368062446b05bf4d461ce39e76cd152a7d3f3075294330a2be60faed856804417db0720c5faaebd944fd8f5a5943ca8e1038bdebe1ea55d5f56c04758aa32b0828da0300a44c53313ac8904ea69baa594daead3ca6b63e079b57a944aede477959d677724f9f33bdfa12cedeb0ce2355748287976100a82d37a380a51a9a4554a29dfbed45a88d3f6242e7ee1e2d442d108b2fcb1ba5ea62a0f08e64c79f6a476670d94d65a6bd55ef52983e0d5a75a3f7c71913e95224f4af309acd5560a782ab02f228e39e30f53e27114c141831c26c19ca9b878a3e25241eb55c3fc8868d5bf78e38d76dce62b94d66da35a46bc52a3235bb5296db7856ceb8ab3820882ba11c45ae9e6512cba2853af57e967f057361bd026457bb70c7ca3ad5d29721810ed942a6b2bf69aed7a4c4c3f7919cf4c4dd04979e3a41e77bedfb81856e48de679cdad52ac2bf50680ca4db5f9699656fb516a6fa57765654e2c412d5c4bef8abcd1f076ea13c87a16f23ce25f6b1379bc71833ccaa7ee04d559fb8e229554b8528a8dcc8b6fac9b6d6c971980eb5c1e2c88374c54728a0a56599173f4b5a89c2b2cb68ab5b2586b61f2c63ed5e2d3a2a4bbc2e86bdd9f3cfef6c794c57560f658393445296bfa8c86a60f655d9ed6156285ec9fca8aa62cbac5ab37c8986af7bb2ad80f3f3b6f6d556e569bc821153e8c6d1e9eed71339eae5301834fa7d55e0d6f5ce7913622af97866ba9e4c282a400227df44b4c977484114541a6cbfb7e268f8f8bfed3c774b242fc30199212cf20f0ce204d9fa074f09019618f33680a3934e5b11f9b1f5020bd30584c2654b708faaa773beefba19bef7c3498f45eafa0b5b552ef30a65374b4de6963e36d78b8eb95146df4f03275efca470048dbff8370207474d3aabcd457996a9b9d78feb494523abbaf75ffbd5ed66a65237dc87e70510a321f407c2d1afeb0ddc7f43b5a438af76fe0a1c6be3e74abd54a3f80a4e17025b32185f96dd73d2b3a696453d6370a83f8868684a02b9bad4923fb29ebf424eeb750d63f8526d0a6245c954231832029e75138ca701b43aaacad9a57dbf93542671d1b51a578ab566db55ffdaeda23eea7fdbd7e65adfe987a9d3ebda64af15e23a6bc477c6e69e87843c3bdf8ca8d0a9aad3e619df41a6add3500811f4e5774455774055299b3ab0c29de9f9286e38c036c1a4af1de2ac37d1d60c3e9d56a9aa6dd1ff206ff90375746fcf143bb1ab62ffff487bcd98eb0d546ab2b1afd8da3a79cb98e6a1b1b1d15ef9d3fe4cd76ada78257328327afc14e9772e5ef38114dddeb4334755f4ea27dc39b8ba8db5a221ac4bf7071fa8c8674274b3a82b7d525fd4984e9b4daabe18debbc6f44caa512d3c9e40405a2a4a8aca4f45818914a0a0a883ab12c2d304a3dd5756272329594607c1ef2b9331a54caa4d1f79ae43c3e5a6ce8f33a2db6fd391d8e527c9c87c33edb1f872edfa7cc0f8bb6bfe32297974d26739c03d238200ea8dbdc965ee4f926413af932a65e5726e443b31c3fda98cbff688f6c8af33487a76f89284b0767e647db84991f6d161666a3a0f1a385c2e2c032615d60937851129441ee6c3aa32997f447cbb3e9ff58679b6e3c3da91f7dc8a6dd9008237cfa3e7164f48e1b4f1fa4acd6ebe8604784c6209309edc02f5c866d6703c14d38b2562b9146388aaf0ac70741fcf2c12f53d1c6d3695a074ba283091d7151e6e5d792375c7e7eadd0481e41188e0ec0e7a005f02dede36fe801fc8bb6791dda879fa171f815eb67b4dc54ff1080003538d8b00830001f3e3812d5865387a100b4bf8080b67f00b4c37e3ca8b32e2d2ef45659a3e5ab26a35dceb4bcd6558a2d7f4367996af9960665aae575e897355ab04cb5b4b0fcfeefb077c3bb699ac6618cbb6ddb3c59f8f6394e165a17ed02932a1c194d09719f0c5b4188a80bd64a7c8a3ac979e6bbafc585d8849828138f8842e29048a4b3d8fe2c319025c60353043343b1428a504a172a442a28df12a2bc4c88f26188f23644791aa2a0ac0c71d18fa0ec94ec1608f33c7007976474225bad44f19f9a9cc8a8c9898cdb5e90be1b3ac813a1cbb774109c97d7a1833c1163b50771d163fefb5a2fbeb3e3429ce745c7fb5a31433e17ccc59720798f37e13e24528997834eca0372a6a54392a64b11af91bba8846e1dbac0c46082d1546abbc4c2d0d200f81b9a877fd1365e87eef133f40d9fd2363cd53f3df4f0393408e61a749ea0895d7183166136b4f85211b2a1071e00d0c3d4c2e252d5f2a653c9a62526262f9c9cbe164e4b4f592c36878484e6cce4fb994493089cb093ef670605a150283121ea6bd130051c5241196a691e7f43ef00622cb485ccb7f0d0d3a767073d5f3f1308484e1f514d756a4726058451109c81c5164229df0e6da77866f46d2c450239e36088c5684ae50b2b2b2b306c0e3a2b2c2c2c6f73d0616161d15e4b07d1f9d8152d3f13feb3b07c2d1a7a21e581a29d203c1a04629054015d114bdd90d169f976d80d03c6d782f111a0ea8060ae4107e7bb30071de4891c4098d016cfd222b30a5176548458663966c480b00f41184b08c25a4099105c85202c0c6988b2a32214d2907a3fb2cc6c0e3ada45f6edb0fbff6badfebf1dea76d9b1e3717058663bf4872f63627268296bc458fbda263fb2cc5caa902aff50bbacb44b1197988b11bfc13f071dbb5d42173050fda3f339746a27c5931292ca41a77a684ae76774ca04db3f450239032455ae23a4615f98a1459854bda4ca4b4c26d356525252525252723262821393098531313cab67909d1d217388cb37b53ee233c245ff0ec6b331680c1da3f583e3026399955866a597f1b55892dce091030382a6dc070f74872d2c53aa5a5ec6d7faef6060402b4058ec0a1a3fb256e28332a1dfe03fa3892822ef99aff1f26b7151438b619033fe39b428aeb498c4457f1c2d167921f6c468d1055aa1812c576c4f231c59aa705c7dc812b684326118926210c9b0192e355c6044f16be9ef6678261f1317261f938fe9464b878c91aa9850bb845f8b862dadc3dfd039efa263bc0e8de36334cccfd0e2e7d0fb535ac653fd73e3753408a3a91bffc92895c9b68a100b162c311621962da4e8acd54a14ff4130679f9105e5646b51d4228c167d548458b088b16cc122c4b158ab155611521152115211521112dadd8f2cb31845bc1f5176b67f8e4bcc05e6251481680c3da58a3eccd772f94e94d347e1eb92ed12e6a073cb621c19208cb25c30ce39e512bba153df8f28cacc50c5d0c079ad5d70421799afe552c40b2eb0943803236366067562327332cdccc0f8960fe7c3686159d1638c1e9830c0984124c128ceb63fea449672b90cc510a110a988e1e3028b11242621bac0051623263221e2408c02b6dd654784a67f3cc828842066a483c53c967a6de982040804079f4184a8f81821ab3ac85408edb5a9cb7ad7e535d47b78760e3fd2d9112bf3266cfa7587b270bc8edf3fd2a1adf32315daf47fa4b21b3f5218ce8f340a1b7ea450ac7ea438a8f12365c20ad114a5436a2e8f8b2c1cdee64717b2a9e6bab9b191e3e967cad2e1e9835e7383f672212eba0b49b6cfe3ae1cdacb211cf1cec2bd200fc6e3359e09648de78514fd4638c23c4e383e6843388279158eb946688546afe82b72755d47f50f0e1df4241a1a9a4534359bf9fcbe9f299bb211ecca9ad1255941cb5640955042b67f897e8986281ea93215814dd8490ceb68940bd583dae1912a8f91918939919dc4545e944a2a954aa5a2615264c60433c54c321d7aeae080b17468a9c39ae19d52d445a9a4c424a7690b3201bda44a860c9592a292198c28c2c0c0c0c0a44a4866908a26d0f42999764c412db805b7e016dc825b704b490e3d834a4abe9ff99a26d3e96422a789673a9d4c4c4ee43cf962c478f0e6c78c4390cf76211a8ae9bcbc7c51e422ab0687f026b4210d59352793919313949ca80fc5735284da8101e32476022bfd974aa552499b48119a622822444c4e5028504e90942307d06619a22921184da9a8908af28edf40faa2a5a5a5a5a5a5855464da21152dd173922347cf46f971dbd9fe3ab4098736cd68ca1433c94c30a021acfccad314a0ed394c465a282a27b2ed940959ce143aa29fe33434c1a42a474b59c3869e434c30ba51af2ee80c119db080b6efdbb66ddb50e0cb4523860071e8c9037e3f7387a5536052e5c12836994c26d38988098e20180e5633208821213e1b2a2b74c5c68a0e5aeaa05e529a60252f25cb042b7996af652ac2b262f97e44968f07ba6f6adce82955359ee56bd9f05d0b8908f5d2d93a654685528682bc21b07cbed1e8fbbeef232d81648fa8c7a149363489c84513ac888b5c084a99c91b56e971e94b3fce6c4cc3939809c6a2242212d1f66f3931c14c453ce59fa35370d0299ee7c56c8381f907c19c3dd8cee67ef48ab6bf8d4671c2c5bf41a38258614a500d65421e4d467658d9a698c90dda04fbafe82b721d3496261865a1307e7d3b606c541067058e07354a48f50f8eb7a151af1f9ed7c111a25cbe168a08519e3fa25e2ba813939593696565c32b239aaf61c3eae7d3d458cde8f144438fcea3d2234d42468f28128c289fed3f4307a84ba8144d39053dcad08c00000008005315000020100a068582d1804c13e4c8bd0114800f6e9842766e421387610ca330869031c40060080000181018126d1b001c2bc52398f1fb9fd7d5bba891f949bb39d53d263b97eb1833faebf3d450c9d708562932fba5c0d9449252522e741b5d8c4395c8ccf550c92934d9f6240f171e99a38132d3e7fb9e30e4cf91728e76d4912c8e52cf569d5ad2358adafb2d4e250bfdfa2871657fe83dcd16721caa24698f922ade42bd867c4206a02c3785259b255abd18c7f6e56c388c33bb3adb3e3b3bb1c2e0d5ae59f7d4576b0ec95e74125cfcc22792a30860c8be344c3b0002bcc1f442cc98322d2cf17557fbf33718ff8a5234083c8dc31f0b22f17d45a5e83fd602e20223a42349642a954aa5492804194da35289742a49412188466acf73902614b4bc3ee8014763bf3ca4da2a14f7b40715bf78b3cbad58e8862ed00ba03f0e7a3950c4addacc49d88711aa90e22726805ef0bcc6c6746d7fbba3dec486aed0b7d0cd097acb5582f82adc7d38fdcd95b5ca2c570b49f3fa4f6ce833e882850ee8d6d9f1bfd7a04cff469479eecdae6e450a7d92a0892af17d4790fbc1c0e143d12b13ae51fa9968a19b8432728e7295ec5d337f86423f6b063ac8de97b274836746b62ef9f453a52f599259fea0121fef2f0012007c71ad0010fceb1d617e1e2b030391430e56900c9e062202842dd84b22aaf8a8df8f5052a97ba79ded030d74e879c6b3dbb00ce408d40da908c40e05ed3b552a11b34ae37543c315ed8b75e3203a39eba9296355c309fc72c3154b0d9dd37a7d5668ab9ce050a9fde015a990d535a286c06e0dca72994fe8171f025faee2d0eeaa383047f7cb0caa01f763f382050a8c9e27db420a661ba378c4b3c50b6043da061c09a1f02b831bcddf7912a2ad719b2110a833ab5d2cfb8040dd0200a314a7592a18bcaefcc9fb6650a526554ddddca484bbab76d7865e48096906cb2f09b1a22901ced26160f6f6894800da062e1312eea3a09190f9b457156c67255716aac01446c080b2c90d5720934c2f09974c8b518010bfff9a9526e8fe87a195239db9c101d1f3d0cd42a6cb443dd53692d472af263c25563f658b8b4600d1ed76e819f223b4d4a3e712a11c80f7d0a8e16c9e1f195512d2c4acd30ffbc43040a78e92a0390e97f400980f1639ac1f18ac824281d9b2be741245e90046a080f1be3935a3ceef538129a2f674345280429f33d2e11e34c6a6b5681d8985b9bef38c26b3f2f3a986361573a316a784adfa3a7110c50eb68e58d8d5a623a8174268b312c80f77cb20967153a0538681a283d423eccbc434f4bdefa8fd4c4c47dff78fb48fc56ed1d597fb3c1cfcd23eb59527a2a0a0016d84d8f95244fd10e17754098c0778f11126645ae9537afaec99cf8bbb9d70be370cb7fb6f609296caa55103e9aaf1fb2bfe273ef39060b463c8da0bfeea4abf2d7df04ab7618be753ed1fc02c38a17b6503507e591ca3a2415818b55a5607771018b06a1ed22829c9b4197140a81c63cfbd957539d2ab1b7e577d7f69ea58f0461dbf1fcb65027efae81817d582f4b7c433af45d0ba073a37cf67cb3efa2bc5f8164f1bac72f0fd7abcf288e93ebf7a72f35f19a17a95a4fef1fdab1af753f7600fc8706f614a93a549a68ad1263f4b5bdf34790e29e57656cbbeccd6e89ddb8caad5a63e5452acd75ca1adf7255d102160b18e86ca00328a6e33e7103da049e594297b5b805521e7c1462c17b9268d68ef5ffaf59d29e71acbfa2615661c57b311060bb7a739d39ee95516689735e264bb64576aa9299c73eab683a83f082d9c47b812c3216d87f2f29a88c4d076fbfc8328c5caba88caf66643f4b1beb7c8bb8b3f3fa2bc0a4467a1dbf29703b67cd0182e21a0c397ecbd04d3ff29b9b214c7f02e43d8a7484a9ac37c4bda34e97440f502f53e6430b688673f305e7041fb998a757c0059633c98f5fab0680d91a0d65867ca208fd151c7bd3a18aa287aadb4aae491330caf2d1f567823ae2a05ecd279ee5ac091a3d62d3ee40fcea82c22f64862aec3095b5ff604c20ced145ef87fa681e6d5ff2d2d3110b3f4da8ba18bc0a48dc8a1565f1e6b4ea69311639611d0ce4de594c0c7ff249202803e2ffaa316252bdc7379e382cfcb35040c222cd83280375f76df04257181317c0efce76bc7b04203930c5e78bf7e22c692aadc2bcb8e8469dd64e36611173ebd7851be14e21bce589fb0523051804d01b8ed776dee7abc7f25249f18601f47395cbd9a32fe6cb1f630e451244254c76a9cc54a9e018443dbae89b61a166dbb1b6d357eb4ed8ab4d53069db252a6d91266e4723fcdf0a82c20122a02e07570e7215f421229d99f77902624d62ddfb3ad9fdfc0c2d917e09272f10d79a6f252f7861c17dcb9d0c022f4dc509cea97fd7874c9a558eb1685a9eb24f79c8a296557d1cec5f313dd76e651f9989f68a67c3131e5a42c66f35556f9681c0d84843ee601cc54fcd9cda1d9b2f0842804f8d9a0c487f0fe2d6b5848f2bbc07951b62e8f56c813fe6e8df0d49551f6728707965242aa86ee8efd96340305e6577578ce38fff6a92f02624694e5245c83f8683514d9efb44dcfa755384886370dd776ce80be7806b35986091bb01064ae8b10b322b5b3ae3e7b59c4775b5b8a782a48f0bad0e962d8c86977cd60ec0315c97b4dd7f74295e8b224fcbe4a9b02ca2986921429521f2904d0c511938817546430001cc7cca9267f7fb392540b546690397b5545e071d606b9e1207c554f04284449d995e38e44dfe621e1f35dfbc1eca0556e708f457e5fbd4bd4b192c699529dfa05beb513fbcea23e099a11bc46d555094faf96fb5eb5cf5c895752ae49612cea94af16c41276db3ab472917a44b2aaa390a6ebc3690298430c83f03c5f9dbdda5148bab351e942e23f01345de95cb3a8f92b2631a9a68c59e12d181a553939660b14e2ae818bb8a5130df1f38f601ec8b05485a96c017ceff9389f147db436794c3a4c0f5d0c5b87bf0a0027b2d525856c429bf034f0c4292f9eeb7b2b10100f919828ea9b6495040c2384e3637b99e4057b97863f9cc97474212975b2c8cd220f6cb2899983dc889fa14cf75623e14c37d8260feb93318c78243982ec4596f50e3a71db029f796c3b51a10aa8d59217d3d94f6e716bedbde027910ddcac720203ba2b935455825b7798afe8c80b9e2817e5ca5fdf70ea73f79831d4e5b3db0cf0ef7138fdadbe178b443627738a8e938961d2ef9be93428aec26c778d6298eba21cfa47ba4fc07e36f5607eb0b46ee1d015ecfc562851b0f8a0abd838cb8772d40b8f7c043a0707034e49d0ba7bf75814d6944c54eeaf661c1070566433fc0ec49fab43b442b7da85e073334ad1c373369ac1104d15798a14a88859a12a605cdc949fb5fc872bfc8bfd2c674996814a7fb3a25a1fb3d4e8440f3159f421478525b6eef489bc2e1a754e685c08de00ddae1bedfd84afd7503c6bdc0c765315506910c21dbb31f4b15d9111f2a4fea06c26953e311fcf644e9398b7754c9f24f0b4a7ca40b7c45c44df0beec087106a33b0622a1472d72f42ab5cad78fd92b02bb2348bde2cf7e83b0a51c09188a542d35f094f2d1d4f0b05e24cbc0e1a6a4e8060496a3d92d482160c7a71581587c2a3260de04261a60f44dcb24c795c662afb15904262241fb02eb11512d05c268804eb4bc96e0a05267e4715ddec3b8a481a15706b750e457bf7f8c8b8426fae33488df0e8c5faa32afb8cc18a4f0f23ae21cd27d76ccc088b2eb0eba64a2d40c8547f206d7eb1ba7431a8ff023b600eaf1a05379f0ef3c682a3d3cd6c38a2b8c21bd220bbddd1f6c3fee63c66d55a56b8f6ad57e9cd3ec68b7a29dd97ba7aa6c0a5f9afc623ebd98f9333e59f559ec4214221804acfd96e57a1518b4d04766506cea163d810e899cd94f5c153a0e3bcbce33c48f9790a71dcafad9e46fc83ff9bc430bdbe90200c433ff1762c0f43aea465067fda9186dafd876e66a345551290e7de7473d6b66f7504815aa8838584b0e39302e93a55fa821c34ee90c18899f9fdcd8c988d13bfc79771c7f252d8338938e7fb9f00705f1a2b8f92b95cf4eb1420258e23fa7eeec70e6edfefad1347f844b6d0cf7a58bfb7b9d13ce20ba85cddcdf472dcb0b9a2742c15476a018aa3000048f5d9b29e31f85aceb8f2030a666346e11b09235bb692aa92e9a130deecf6dd2e1aed62c7adc762dc3cb4fb85bab68876de51c590c580b452c633dd033acb6940b59fe8b9323ff0c9f18df37f9e855a69382620944a1b6047a457015cc39a30e428f71c67c415702193aa84a7491d495d8b864e72b22a358b01d17252f4d63af3f4f72e06e8ec7cca366d3ef8bd4318ffa242860549f120ae0b233893e90a24b902e3304f2be8a094645a3987354f1a01d063926f2eda9bdfe652035998526105fa15e2717af2e9cb88bd10a7c91fc14ca936c9c65afb2c9ad3131037b5b7b34c82aa1cc052f96b918f38c602fe854621d6144dcc652da239535ffdbe64c6dcda7c0495414cd33217703c1ab4ff51caa435adaa3c41268134ae9ab08f75434172d7c1d595c6529110408d396ef8ef5cd619b80aeb1df3ff7198f9a4bd4eeaea6b419c9aebb2cc62b5af992099b3f565ff2e1eaf5cae7170d15e0c2bcfdb1a563250405eee879e20788160299db8dd3a84d561edf8a3849018cda078fa0ae4eb2b88ce487f8c8aabd91c9d4965ce40a5117b6d4c975b625318ed3082262fe583df60eaf85104a265d1681a9c6f683ee464309a7a832c1d0d46864cc0c69b661c686bb669cc1cf4fcc666833f0ec9140bf1c84d6f7eff440ab2927ff76953fae320b4453e611e73e63cdc2f932694add5eafcf81ca2849a01aa8f3b8e9efc655b16ea29638a3686150c284063f73b76c92cc519990d5865642b884458c92fea07facca66de1a2ef2d725818484d666614b53b7cfe14d658cec1864c1def067a6e199afc24b2ad5a4d1a280204ab2bbf1aa968ec28f3779bbd8c02f8100d2291c91b1e293b4122cb149aea0f5e6561077ec9d50cb90dc34da44cb34e123e4031158419cf2750018603ff9aec9b74758a9a75d1df0750a1c4445d14657815779be5edcb939880acb04a0e3f9e5de19f8c6e9e58ce5cd646d5d4c855a07c9fc0cf95d879d433f936af0e97cf3e88d579b1883721695720e9baa34b99c2f347ea01b3ab7392b13fc9d612e37a76629d510f5b804e097c7fad923518fb9a269995e89d8c521b5a7039d3e86f713503559c5138ba28610ba00bbf1b7752c755f35fc77c4e891d3099d2ccf1369ea4e5a9d9bb1dba3978a7567e659764564b8cad820a12eddc14a77792597238a89ac39dd23d0605aabca90a80265a21e927ff1dee13dd1a1e42cfa1cba3c3424b1c1d95bf9f108a73998fd443e4b9d019784fb28502cd9a157dbd62221a755b51330c75bfb5bf5828b12bb0ea66e63b04373b0e66153eb09335e071b2cdadde7865a2b715e237e1d4f7b88e09e34b2803b3468dc09caf474957511a3865b33844dbb88082463ca3d3eaa4f54bf4f1285e7d6342ba5b24450f45863b5fa5fbd8706577c829a974918e0922ae9b860d5ae1d2af78239740b4a3cbe0e37d30b6a9a78d63a4cfe3f46cd296b75e4226763af29633455feef2c3a59790a4eb65d53c6219a53df6be9ad1a0e80378788153cacb100f8c217feea17b9a77c5a19e1784059b65e6c461620505d5ea25a9417a03e3d2525cac5ca180f656456faecb9281a01fabf4a9c21ddff65f057fe54080fc6aa700e98a165589481f9fb0fd5f14adfa18dfaca77c8bd95fb468bbd10475a48b45644d23b6e5f520fdc5fe4cd60d87bd3c4ba1046bc4d5105dccc04047bc19b446b5dc6bf5efa142108ba6870c6b25b609d2441c08ececfc0641abb7d4e1d46bdf9042f0503d488120dc79b03f887da9388e5ba56c0407bfaeb1ea20cc0a5c83f4841ec3fe3599fea457010f0669687022c8fba947dc6af9ef135bb8a55878b784c2ceadd29f2473dbde4c38d7d972a5bbc7c2231180105c78abd5d140b6e7f7405e37f156f0e95722c0dba96934aaba3daa09354f68ab6e396273473a87639241921ca921c4b52a90b6e47860952b76adf5f97a0f83f62b50578b362972e9f70615a9d5a14d3bc5d20427eced22383bfa9c050f9149ebf0b0e638c7902d152cb2d99e366b20163018145826c8966d6cb8d22604609367ef80bebf1da729333a530f5a7400616e285815eeac48b2248222c43b99f40e28e9a9352b90a81a73516dce89d20617bf422622328b7dcc51a659f56fb3cbfc48bfaad67b974411a5a1dce08795e7cc87916cb54a8031f88c0f63d07614019f94728a3f50db067b64453c3f41a76e1131530bf935c3dbe84cb7276ad9867ed4ccabc58602769ef38569e30f72f70a7c97172ec345fa01226289e03c10989a2a512ebb8903b1236862e0d7594a7ad3047d140d81cb4af97067a119ad54b587e85a87cd92b90fa08726893e7727f0afeff5441f083ed2bf5b003691e562d033888933af19d1899e1ebb071ab39f83a0b8c0c4d3dd171cdce24c19cd1969e91a8e577b6eaee91335f9e08c552b9f0e7c5c113e56dc5b42010e1b9ef6e25d2b5abc1d4a40e3391ed04cda4295db7661fce4acb207da82d8face14a2a075f53a5e485be8f6d899fccbb07ab992c86fbf3cf2b9b05b5e2292fd51048f80a369438edfc2f82bc8cfea19fb35a0980dfe5128d5cc550a917f65229e487d6dba0a6a2ddd4168e66e26a940b8932740a32e2e64c3ac73d663fe26601cef93770a8fafb0a2b753865efb6e95591f172e45034879a3f576a491eb46da16c467e95d18b26101cce5e30c4647ea4c8cc0252533a269ac735755dbadc43ebf1098a4a1638d212da3551ad4607816407e70869323dda923bc1150b0dc1d43752181ff7427db8e40a5d527337cba002798f00ce9e7d591e212b45887750fc7e6b8f6de710b0b159f897e3d6dbb01393b2ad275f4acb66380f5dab9946887beb4cd62a2e0e2e516807bbf6ea9311abb0f898446a0d106cd29352c0ff1690db16b89fdec9bddf5aa1c75974b3aff92ccaa5c00ad768df624906f02ff816575fbe42091a617233e60dfc9dfaca80081a31e89e2860ff94c7902c628ba1130e61902ca4ed870e109be6cc34e1e5153a21496dacaa2405855b2d0b0b0e5672e75ab91f417e4062595a48b6498d46a8629e0f8f5d294e3d1fc22114a66a912927325fb1b7bc9955448a5916ff6df7583d782d9893e286ee92ac1c0a59a0443e00c5a0da399368070afaba826e7c71a6c6ab50296a8b3fccf7bc492a4019205c0fd0ce8c546cf3ce8302bc3f93b7633f28d786ac2d8e597fd1e4a05227b6ca4ab3e8e7ba33ad6cf2d5718de43f1471c72121c29bcba5d47fee563faceadb66894aa3dc412bd3822cb27ee9a50a3ca8aa35bdc5c0389b7738160766bfee7e69fd4b8d711800baaa86ca6643dba2dab796214849ac0836babe6eee9aae788d0f9eb4fe6618087b44e0a597c8a4abc4ec4dbf7c218d5d8ce5f91a3aad670e5732050ac72882bd8a84544e617787b329444e81ccb0edc2ded15ef8ab319b485d2ed5288a5e8d134f7f024c8017c033e94e2374641639cd57be06a4e30919795e03d48e275e8a66150ba3c7d4fc098d9c1f91829e118af6aecc33e8933a834718782ac05ad37781eb39b4f299db11683b144b8671e24d1280119a494d50673b9274f78eb0a34ba92b13b0da075cab04bcb8dcafac91e2590291a99be19a5e9093fa80a7f53f71c8b9c5091ee2a313d2299ba18dec8559d5f26e139b01c47762cfd793adbf488cabd7dbc376052024464d3969e7a29815854f7fffd4dc0f041abcf7a0526aed427f307c3ddac539a851e9918ba575930a644cef8a3745cc98b72e8ecc18b900011dba7995ea91e7441b21b6a9025b3480b51ee9ec019060abbc1d4dd54e5658f518b3528c2f3a7c34e9d22cbefa2833057c924d3bf98b40d4017baabf416f69f1c3b818f6446f468b379035683bf9b90d1d0dd1be00d804720843b10a8f0803d96f63c9dce88aa12bfd1d0594c9ef72f6097cea52f506e98ee5240d8cd25806ae1bc3198f9dad9c41614ff00abb2bb53b8597d998c077068b1dc43111bf72e7ddd541b76048b57a8486de2d82e4753f514048dba6368416e8a4763d95d3634d1c00be6205e3599306c4084767ff98b12fced244ada70eba3fcc976e9f88c106637603d23f4554416f4ef066844d0508a1e9030777a5194a1e35459d6ee25545f144b169f5f33b376c8c98969ee85ceaae8597e662183aa1a82a6d34952d3e511c402edff209c0b98df637887bd717013ba81a35ab2cc706af39493161dafdcf78b137bb5cf41b0e3fe03736c3c35fc5fda533e9f236af18a2b974c5df948c6aa8605a5ba595058e0e8e05cc5fe1b2c5bbf02faf1f592a4ecf8cb736e4b105f1e548bf12a72e2d506c9709610f92584041247e8d87f25da8260a223404acf003c05fe087ccf179fac6fcc3846aab9adb1be03c557efc0c6c51dabb2f0ada1ed7bc735671e807fa642d034105a1ffef01ee16de8b5423f2d571a8e8d297c904fd8fd034a511b7322edb4e510d231c66509bb9b1fd3fda9f694989225015a85c7fd8a248be8c29245664404c129f6945eecb99dc14aebb53c74af602feb596a241f2e6dbc7631179ac753abf880fc52b455abee246a4fd6a69fa1de7c29ee385c89c2887692d92cac63757999e4439f7151850979fb04b65c6b9ac1e2d94492a7be725777ca832ca90c57d5fce7a6f9fb9b7183b81e395d27044aabf07cb7a7cea9cd7f522995bda37abc48a9e9d500c26508379a0f4326a8ba068252316a9051064819019d8efc04217f2b2a8a4c24cd6f9a360eaa16a14f5c0890cdd414d44cde0d3c8c9e7aae135fe6cd3b14a94cfb9857525b62acbd49182213128333b00943826087e38aa84a80be46368dd5d8ddc6ddcbe4722eef6da744929697785e442d49332a22d6060f2e8a304699f40e38ad725d94f1c4ee30e704aa9b12bce8481690d448a48a36215ca5169a8afa1af3007bd1d7a85542034413db107ebe63439123dfcd3ae1bb648e085d3f50b992493c820d32a12046bd76eb4a490da5ac2042c0605dedf99573a465952f453c82859fb9ae0c7709fe68a45f84e24d53d515d00935011b4914ed18a70988d19481f89067f2d0e843bbadb61f365eb9ee54de604674ee969c2aed108a0da3032b36fe2efaca76e051e19798c93713440353bad93624c5e449edec17d92b868219f67ee1fd4ee28e81fd11948dbd12d0d30b0025d610d63d37f9ba0228e222e605e452368d0f8c3433f5189221281a94a17d5ce582c5fffd29ffb8612b864947e7520071de7f2ba7bd2460d9e4669b16287c6863b24724505c2f2e3c2753bcaf297cc75d0e155fbd5eee5cc87a1b0e2e59d27be7593796953a69a6732bcb7edd65fa57098510fe8cc4ee80a0c4979e0a1763845013f82808cee9829c82d8a8d90639355b8bd78027d604845f54796a6f465795c8761b7b8170a866c17e2b2f960ffb252425f98ff1769545431aa2864fb69eaeaf29a374f879059380f16a27de0291a7c289568942ea05ea14812f4149d121f82628410500aa9b4359cd617acef71e24c8a4d57c0e420eb2fb3df0a0d654deccb0f1026f3c9abf6cdd0a854e4388426c1da3065449362c6be5a77b905d3a67c1df5f94a2f99c25302ea7db990f4c8cf35983e78dcb52cce6de0651b947b077c1b4ff9a30257b848f107b94526eb824f211712973c6ee606cf97dea54d7ce31c338057bd4c6ce0dbb51da77b68c31094b7ae86da56f407984857a43543fa1f647612fcb87637606f566c19cfd2bb0fb0daa8142175f1818f68b25d15b992e7a0b74ac1c5781665e02c258668c40f53d9cd5824b039d977099277ed04738fa3a35e9db670d9cd5225581b0d433b6aa08050ad42a8b50c7b6d7f883f2cf9a52eb85fed299923a2c3a7bd955b109a7cf42969062ac93357808635ad534694b635fd24fcb327d5185782497bdf5d9491596caa9281b69a3942c389b3f7e55868a2548a4809c86c431cfd8f8ba5082b75af35661a6bd7cd683ad9899be8d586dcf5c5cbbcf852dad8febfd09dcf4135a97d4cfdf35d6909e07a09c40d2316ee2e12e6e13569e81d98841ea5aa859ff970e8f0de0b54ee7bbca943e0f2253f5fdc9dcdec17770b73576cc410ec6909e8f62cb874667e28a4f1b700cdcbf127566644525081984a0c852cd7348ec62ce587b17c1ac1275d6d2f53ad2667ce5c3db3f82c1fdfbbe306da7cbd9fb0647ead39dd012d542c49971694fae5e6d19ccabb8042d339e8f5139bb468267f38c2b2cc399692715163675ab5791c042594914f89ef2db431e71c78713a4d7600fa07faf44f7f083f847d63940c2f8c0f3a4f4d474310a550c51dd84b9a2d74c2469df90429d85b3a48d4f586c9d318073888677e3dd40fb53d18f8fb4707a5fb5a883a417616f5e15d8ab8b5050eaa1b6b43caf73aaa950e73e90c0bac57baae2ed3dea2a34e8b5fbbb535a04614501e8811690a3cfc6846574eb4826078dbe37fdd66e6865bba0e012c3192d7038ea8608b81459c79ab8dbf4b6dff9d314f31fe8f9529dc592c769c433b58bef7a43d3eedb1b4184e6387f36ec989f82c1b786014d005b73670676965dfaa697af403ce8d9ec00fed157874afe9928f0f61fe7bbed734966986dfe65e6804cffd10cb81682ec10ae7094c8a32fdc1502dab01308e5703e82f6fa0e3c0f50feeb5b217d4860fb34137baa21a55cdfc10cb02438303f88002beb02fe682f21c6d1176886abdea609c906f84ebfe72c843993343071e4f8e2445d6fd09559fdd14f399dd14bbd19c3c9c22795905e5593651b20b42c2b31a536c0c3021e363200caec5d36c2a7dc7f0ee236b31684fa4f0ef6e243512d2c731e9fa8cd45a5a789c5193c9879e8351b8d6db1e8d055da45a3a821e1adc75236aec35a39ba7507ab43f1811a4132e5527c6e164d78e198fd8785c1ed5142f1a66e020d7ed8587c7c5e59c2c9e6e61fcbce5276b8fd05973ad81aee7b61d8fa29fcc51d07ae1062dc1e85fb98d7518b9a56f925ee48f47e35398905686ca673d9046fce93fd0e47c3bd13fb0bdd876a16e3726e7b1b59d4caefcf37955d72fe275a46df47634cc932a882e475e75aeca3f5bd6e32ba830ff561aa654c63fa20fb58dd7aa932da7008f468b4b9b497fc5174643eb12549f030bbbfa738e8c6b8c061c4b34a1870e86676c25a47d2498bd611e3ed25ae6aec5f80b3d6d1562bd10b68cae990ee188e6d1ab1a948c21100c94fceae9b6207366b40ca254249ba5fd0149347b2456cd8673205030c044022fa3c14a9157e58bcac9a58d15757429d615912972d00474ca8bf6b46cb71e8811fe940c2cfaa71e1db1f24b9582ea33bb02468f54f54d046ddcdd122895b9a1a0847c4fc3e7eb4b390997cdb79048d071b7b4852665a1f3a26d0306e8d4af4a2e70911b11fe7967d2fabe38ce3cfc790357bea48d810d4d9e6a0caa7a3c582114463c8a5a0281cda3266c3fea8b91115d8399843f74a4ddefffd2803fc9a01411c877db699300f4e3e1164f9a31989b4827c94e8792ac2e550e44f3f0e3ca0cc43e5f9f6613598290e0ba2921e872ca38a8bb7912e662a7c0a6a77aca9ea4faf47bed6eff393e29d3706bcb3c42506f61038d770745d1cb6383aa58352e4047127ad4dd5809e2e861fc295a9613aec5a758e58be03939de750c6e881c635d10047c3fae090f836b1666556d4380ce9cdd2750740d32ab2cdf962ea5fa6b096d233fe705a79cf24c133c23c49a8206932f5ee1c004ad65ea71e77909494ec0aee207d820ee85a241f4184c2b617453a923075c56d843b828500406ed1c5f2f4678724313365e5a8257f25af9a78154c2753f8e8950a62e24a0695154b42393ac2f6a019fbb67615707df86476d575db07883ba170cd6c3ff8c60484acdcc2205b3f915dafb15e3352b2cacc810f67bd404568aca3350fb57895abdf91cc331189e2c2756302dcb798cd85387fc38fb20f73114e1f6096bce7d441c32f1f9a4e82b5652d08825b511cc8966b044108b2aaeae5c4b0ad1934486204a50fa983c466c6cc3ef18a1ee5793006d2b06b750ee71713b5643c5851e2f841264168e2d72e8bd27680ea80bef76d77cbfda9c2a1fd2a1b669e872aa83bffe02526a5036d1cd554dffc5da5dff53d2153d3e20c8e19d4cbed9fc9368b9646950ed455e882dc8be2128ae3b2ecd639ad1345339587fe81d6f3a105b1aa0878d70b8f7056aed08bb2a2b0e232503271e9b4634547741d0b1744620b60ee7d71d7b0a8d2f17978a01952f5800455fbde69f2165fbaed65d75a6ddb120cfc4ce08efc4fc402574c00f61a625847eca9ace6b8bf9465a0307f8509f628f19ceb6f98a0f6610cb268ce275e805b0604f692ca567fc0edae299d60a4e53c6a983a9f6cf3835584e0e5bc5f915b6bdfbf98a61b83c7e34ccf3d9efc5a6a1f40c66c3dfbf1aa77dd4b6c36aedca4e4d52222de39184d7f26d3179bfb545f209141f908e8eb01e1216564c322b49f53c9382193eece94ca6b77dd11e2e03a60e2caf864acc6b53448737a8fc8a3ec274b14dc87e5a7b35296f02993df78c7afd76fc862bb39541504ac2f675e493ddd48902d0320ede265eb906ade01f917afc3b4bf0c33f3269ab795cc2f549725ac7573936207397cc1bcd99f183a5bf295e8ed13e2fae4eed78ba66f1cf260c195e785f7601b6777c7c1dd224677ea59b57529691a438fdea70f649205848ca2031601271c6283100670d6fbb414f954443b02d791d2543eee4791b75fb5832a8c16e745bbb5bcb89b02e73851f79240145af6cae283f68772dc893aecac772a0c25fc165d8b8fbb41c20843080b506984112d93735c267ec9f69b2446022d46b40ca10b32aadc2dc0e001cfb3536975cd8ba976ced2593b591aa440b075713b74788e147bdaab4b1164f01e6198fde991355f12bb088a289582abf946c3439156d222525535d22ecb1aa08d73433fb07439f15fb254db1ba4e4a6b14f216efa1a5b9551b13db6003326af141d8d546086fa64cfc1e6b636ea054550f4a5cdab293b04fdebcc86310e6513e07d88194cd7fe621db7dce6e7c1c26956c2c10d746d9334ddc30376a1e255d47006f76bb2fdcc78918efc0dd6d418c4b87fbf787f3b44446c99f55e20f6362d8ad769f3a29092500434c1bcfc64657a7720ceba3a2ff29365ed6e16072d1a8dd95fea50d3d8a1cf65d31344f13c9baefa8671cb7cb2f5e67068ef07aca725280eefdb899b9ad74f927b7c4cf9a404608f21f06e68a05c3a0e3eb54327dad89c6e5982537a6e9982a468d390dc57f0e95f890f47baa0c90b43c44c07e4201b7c12d22db2c3d31213733351c040bd73893015da53598b7e989e982f60746d923b8e2d38c446c071fef287fd367c8458cb44ba823aab8392b08b79dd3cfc2b567746e0c40e988e04fd621016acdfa973395eeed944992b59a2f16c8b6c407002f055c5e18b0a3adc1d8a39de6b67fbf3b2a55a0b7ceb0a1bc64d0bea4ce1bb6edf4283fcef195113c8bd5f8e2247df689ec109686027a02b81ee61d73af29a0cc1b056aa0a8a399d522a5d35a729c0cab1046e542107a056f3e48b14a76065f9d5e07a2b641d4f573412c87705fe482a39b29029176f7f5c00f61ba8e6116219e61239eabb3c09d6510ad16907ad4e11841a11c6182b2822d9989b5dd79d7ef4ca52295031fd58157d23c569985e4b3465a402b819bf2a6ba03a9fe90a990b5b7c6c1d76db86997007be0881c606ea46b8c119941346132efa46311dfc48d35b35bc87a0b8bce2178b3c6b4f130d5d7f8959fb2bab59e2e4c7fb90adbc090b60506d80fc9669c8cc7048d7eb8442404c7fedfcc98c2b427ca2937f968eba6f8030f362680d033786cebb40de98790120382c6788370ce6c0dc6ec6a7173f7784169641bcf6864a46cc5b20120cb5ee48a600b4c1d6d80a440c0123d80e7f4fc2bd016e5a294e9bc687430919c2e9ed66255d43c4f0690ee2e449bc37a9ce41fd11d827bae2d602b8a10eaf8db1c95da1609e08fb34412b9b0b05d8362304bbd6da7f6b22ace716addc6cd2ec7a92d03c1102fdae422f6a893b74d7aee4cb275c0b9f26041b6b5df23dc2aa0871c720d804f45581d678254e90c9124214a0fb8d75d6ea61ae5f08c0a815b978991855552608d5cc3aa1509685dda5ea0be9b1de3647e899bf2cf88b6453e0b4f0d2bc2be0556bd50e4bb9fd39cfc150ea3711cf4ece717153ba170699aedd721d7f4d9b5d14398d21c011b72407551218352c0fd1aa3525c74c31852232d2e1dad2e797026652fca305109f724adfdc21e4444f51b2dbc25e660b443949673c12e6ae44d30823b5901c119ca096c951c9551cea314a2a0b62d1c04d9ce453f87505b5cb38a228aed73d0d8694eab1bd506981e242ed526be546b051254945e8ae660cc3393bdbb8de9f31e5d1d153eda7c88c71be426a8f9e4bf2b81c143550cf990902a8e38e8374e62eeb7a29c96f7d1745574cdbb919829899daaa199185dab85013d46fe09141066033c832dcd0c9632f43298099d11dd4baf7b8ec94fbcc8dcfd49c0bb2276eddfd3d71d3d2a024aac1a8dee883d602708432149faa1e24b8e57e033c0c125fac811d9f0215f5311fca2a55af83c659c92910ecb2d6096bc14fb90637eb54b2b29f9c517d2754bf2e003cc5510a56e017748ba96af8e866717b1207fbf196a9cb7264daebb501f1626758368fa7de97f2e2193593501a43df489d13162acaa80c5c19623d7a24161ea66c79e891554018e7e0918b391b3c022a047bdcb0681459d828614fd8dd76e4ea40044f908d1649be59e0b8aa18fa0bb34996ae40a947166d30edfabf5040f398689e0c087ce2320ecc68101ddaa8a46ed5ef142fff16f097e223055a20cf6bae28f161dea1a580f34aba30029f7975b46640234736dd6937753d2befa1ab7263b3e6c53f96139426ffb5ee484efb25555199825c7a3d50f63b7bf08c0e1f1c749565875fae6758005d156ef180053f3711e885e9a6875c7ba379440b90b803fd0f1ce2f8556491f7a2711a656934c6f59db9fde357633f0c6f1837c355c18902b128af6aa8fd0f4462443da02b1476e91cf9b5380c5e3e19817e3b2f21ba163acc6417d34c618ce2380871377bebdb5b6a2ceba1eaeaae062a54fb458be720f5a5f21727c87f55b425ec13302ede327f2d3bd83683e9f6e564ed2698439c397b47759da5186cdc5f566b8e33a113c3347b959af4cea0dac86b7e7485c2830b22077fac7f258f2b511dcc8d22807aec9ae3f0564b0dab6244c56b27a2e2d4a66da2a9b886669108644eed0a9c6f925616337e9fba7a3261ba13d7fcb2f4689937f87f00a1ad21f2c19e4dccbd332e6d7bc9795aa7d6df9bd1c8776c315d8f5e701d24e7bace3df0b81ebb1df8e4185f5e61bda09931eff5da3693adb99e680823403201e30eb9ed2299df5e43384d3fe5f7652e00c8e52cba4a735bc4c3d75df9a7135a67b6e5af12768a2fb46248559efe51ea73efa1c4e1aad276454689e1d0b468ee394c1ae028073fb738c445adc85d22383a24ecb71862c28348c94eeddbe3ffb93f11baca56f7d41679932acf1dd44fce7457dbc7f21892cf4541dc1e4b8b92885e41ff2ed6ffb59903bbe4749e902ef419100ed5f1f89b56972a4ade52e2234a81bf0d75e1d2fdf193ed58e1c4c777c471dadf993373ac90cb352fb8f901d8362c684269fac5a5a9aa834e2d20d16b13480895fd71da07ea071b104ae7170243d1bdf8f7c733e26bb3377ab361bc7db95597aa887b2f1d03f268647273b092d3f9981eb503271665355bcc08928f75cacf58eb02d8947819f2ba3ae69df7b7c21273a25ea250f8762f1fd0a05eb9dc3196f6680f78b2c654dbf3877713e3d67c8c086cca0e8321701e66cae0cee53ca76b539210603a9e8623e1697c88191898aeee2c0d4f18ea80acf749139b890eab56b7205b41592029b5cce1d13caaf91b998b7b180c84516c331db651a958de1694abb220dbcfc4e470ab110841a367faeffbe436561eafc232e5a84aff53293205220a4c5e89b2e330b444e525c140ee302a5302047674ce6af9f3d718853ec1ef3c368d21a12595d82ded1d6d23193bd9d0776285aa76a9829182992e222f82d9721012125252f86af791973007220a245799917300933e422e41a878f526098b83dfd48946c3539bf48d52dfa61ce69d4c5ca7610f09e09d1de18ac54ae0227fccffe4ac588f72c0353d738a599e116bd8a9a16f4a3359257a65ec2352d7138d97e7f9e6c23241c6a3317b8a6e8bb90ffc17e705fc89c8b55d0499f5f9b73873d402417a3bb4bda11241cf70257065e4dc0203a5014b0908f4c108607df373d96a34486e6ed39f70034d14fbc84a932a9d04ca90107553be8b61baa46c49ce45b85d5674170fddd3824759c488476684ca949bd6d405eee93fd5a8bb41da3ca999dc0fe198aacfad3f13dc03ae0e738040caf8a5df96b249f68207f0cf90be4b6fa652841ca8d9f323af7958a7d5327e1694365e90f370292a09af357b8bf6196c67921bf23d5d75d577a837581eabcee9ac4a438a79813863bf557baea5226d28fd2896d6815614deb323927a916654820d42305e9958d546d89a8f1ebc657c4da9c7a08574946a5df928d4199b24658d75159cb30be748fedc2e16ec9d951eb98cc232a9bf1532b875b4d6cac55954af875b7ed67b4d6154e9c6845c70c476f34c2b3e0ef298496f332385374180ff1d3cce093466bdbac2cd620ffd16beeec34c80ce166c8d0e6fc4a46228f8c4fd58779cb576b75675bc89b6cd1a3d73e397ba8b490f85a317187e2a71bb5cf93a545a51ded50b64ec6945686823d760bd331b5398c5b28d11c1c84316276e2446f53f956b3c4555f068e97fe0e4288e9cb24dae14df222b5a112f4dbaa22b422578fa108be51561ca1b0638cf99be994d327607842febaee42941e6b1ac29d4a4380094ef435846cce45a466cb56b47ccbdf7d4b1765b658d2bfbf1fa42b925f9504c803781f77a0ad207357ad03fb7d6ecddcac66fe255c72d16de5b95f30a43c4388a5b402929f10df8a7f350727e5ef855e46db61112891c3a9a5fecfe662f28b7f2925c7bb792b1809c00d1d5749b878da0449d4ef990729d11000600dbe5c562e05af706eba676ecb36aebc8d7e4d4a119b9d64a2eeed03b11dffd0a5f361ebe69890430dbd7746aa743c41316992b1a4b74ae5be90a48f04ca7999a3ac26b0903480604f1b25c9b9b7d79ac2ce9dcb14b7c0c78ae3e0f9d17a9e91c5f26a96bf8bde7426178674d3719451fb7c3ddcba3dc39cb1fc511596ae98bd3d57139f05b76918bb92147e2b91a0fd84c316a0d69c4961fa90fa84cc255053aa0bf5477863ee9771ba6a242b9f846b06d370771f87c43ccb5bfc1edb418f21bf296362759393b45ac40bfea38efffd2a4dd8ec9570b0d7695f29d7d27e08f1e8080431708b369b95d1476e445ebd92d9fde7e75e357c235e99059b3d00c3b9b708bb7133dddaada6c725b1a3a4ff4c44be6d2e37647ca26935a22d4ef35c8647bd76468b9f8e49ed5d17d3678a624a2c81f23ba74d241684bca2546dbf2d0afe9b4b445bc290abc11762782c60739ba9bd8e955660863e55107683adf8df57d7598be2655b2e1a894e35c123ae9188ed1793eea2418e2b34f31321ef6c1c1a9d24641427f921084fac38150f6a2cb958b50eeae7896386f20097ec8c204192a802cd56b49a804b7c6bb46f3d8e34d201e4961a427acf6b27da3b797c2dc97db70074c56b7fdb1020fb22c22754af4569460798a09f5b56da934f8e8d236293a84ba9b276c572ef14bbce6333f72c3e44ace757f3d7b9069eab5f7305dfab6fe7b228b857b3789bdfc4fc763842baa8502ac3f0eb09e7249e85fc55f5561bb4864d6107242e72f58b2cf79eb0c0fa6870e3c2a33ee07fe61e332731d7269f330b411052c04d58cf823f15862468f0d659ef63e9e28abd1697bff6d3ea7723170b6329db145c58ba93575287946a80feb95d3323976d35c7826fa44f989cd4865825a8c6320006524937735ce0495b26e3a18d5db0e0cc3bb13c6dd4604f3e29f515a94e4b314d8614a1e8c4e4f1cab4cd22dca828346bc1889dc6533b4daaa79355c0c2ec13eea73654ce03c5096fc71ccf396377ea6f95f74b5204863524d697add0ca0c9ccd4975b81079878b42d1d3239dd800a81d6069b193d7520acfaa65920a3dd95498b47529a9bfa7b4efed62561646ec834c574dd027d2c1639345c60d58c4f0de82aaa99f871e80e1066425f15ae1c78943ccb0840e83bbae1fc6eb80304154d2c685a52685b3a9735209c71dd8d4228658c85ca13efd24a5729334d2f380f4fcc5a94e5be5b8195375ea18c13bba1f1ad2b726a6cd6ea16e7e013b194e0b4eafcac83398a352c0c337995fb8865a6a01edb91acf48f31e64aeac7f109226d72816d2c842f2859f42d84198f0bb883115d03ea84769b7222bb4562f29d3aa1f813fe6b90a046ba0574cbd3c631d82d3541c91296e5a3345550e9b141c11b9b5be1c2eb46aef96f80c9eed62203fd2b4d2b32ebf29d0c5048342499cce9a85920d4fcc6d030a383a8648fb4a98c8a1cbc156705af2df2b4e0c53a049fb7ee737c10aa353335cd15fb46f1480251964818d94edb0a136da194f03a5e1372cc145273fc4a651772d147f24e82cc9868b36279f5e161d92f376da22439485cf14bd45cf821f5e13459f3125c649d242285fa53dc4f1239daee7ab6047cabb490bedbc9116fab6697728c142a1e85ca0631e11c6f658d68dd1cd8b8542c018652bb467bc8a17a6df266a3fd1548cacbde2cc31e37a17697946719d2ca520ab3c5a832bcb42ef1d48f18e39c95f7224ffba0da5373f5e063ee0da9dd91abaaf607729cbfab509a6f817246c01f2dd0a580690b0769834f43a698c154556f37fe6367a0b0eaed3662c67ad917d2cde362a8c0a7d17fbfcf447e78c2bfdae6f0a0b342e21efa8d1d7a1b0a58a66ececfd056d3ab42d0ef3844e48e66e62a8ca4ab26d29be1f82db3dd5f3cb4f4dcb68610e77307f5050526a74d71ea488fe5915a1a65ac2929f257a3edfdfda0c8c575e3366a633fc18dd661b30595b0749e59fd67bf14f5f92d35bcf48135db2cff6df1afa3a144b290b974f1fa348a3cedb28a329a16b5c9cdc3e8dd821f4ddb190f7f6b30398e7028c187be5fbcf04e7c628028acb4ff45852ad00cf6af5460e9a4a9fb0f7fd84e7bac26e07a5f42fbf13d2dc1f94955c3ffcdcf4315a4f5a1ff2e4389b3f1a5b0a0744c728dcabbea69e587d287b57e99a18a258974e0c0ce72aa17cd6a652ca53ec9eecd14ce4b377d8b17e0d8b65a0221005079424d712156d24e190e9d5ae4fae44b9092314cbe64829fb2044a2805370cae09c3a67448484989fe78c7154f4e083da38602804ba8fdc279daf6b6c851ed6a375a1e9333c36feebc8a8600cb687775fa56798864838cbe6ec4647bfff5844c50319523ac13ad58253c09e3ba094390d67466f00012f6c1d1f4953689534faa2a711f69a03787122e4f23a95d8065fced5b49a72df334f5dea7b2b88b3d57445b9f465319b7cdf2a8f9018c3173765a83acf0ebc591e2feeabb8d70b15f2c63c44427df503665034f29ec023d4c8e43902fc8eabf65ddf1a86978f3161cc51e3f6d48c48ad258b3394df43e87b93cc82215b37e7663287ad99c5862651f11a1905b4f3d9b35b86cb1cddebdc9d17e33a252ba67c3714bed43d9a1741b6af9b8fc50b19506a9111949e4d5705cbe7ebdca51b22b8ac9698f63e01a797650e8d2ae7589b279856827b5a5e8b859c78e4cac0c021af7f27b17fc2ec9f23682873070b138db0119b2df05809098183e646239c8d1415d5d3ec4708231c57ca839ed88f19fe588e35003d201f317a644101ae3751848a54775bdc074e4e461a6f0cf6e8e07e4f426d0d130496da4a16092346d63fa78a1b1eb0f4e355335c72b01916078e772eb1635624eacb2f0b3960c44b1aaf52dd3ef2b8f47d8de417ba69840998da8d45ffbe5c226d6c1b070ac2faac1b3e78e533f584bd762884b20b0518224f14b0cc2dabd65dd08ec7981258dc022879eafdb2e73f30ed1484a19ba164312bba03b57739e9f420f93a0c6a408310e0a57e12376332cc2878871fbcbca3b0c25935c45911650b09793e9dee448bc54cec9b401a4398413c99ec0223fecec9d28e796215f02f92f08ac35460b5df8e7effac51d99277350ba18d878340cbee38d22a5aac0a605547dd7e9728ae9e77a841d46ae0939b2b06cd14b3c73421a5d887165092a3c0b4a758e5d327e5e4b496e2df03898640471882d2b86c264abae2ce264bf4d9405c7d128015be03c3cba81617b32972980ce8908d218e4832ec42fbb1bea53a7c8ef9f8c77a782e9183d72264103c46bb05bb8befb094122c066314e7ad31c7f9a66bdb39733f0ac5642dee4abe28b8a919d9f6c27e7fbfbc5614c57dfa80af5a22e1f3551a50fe6b052c340245fd9476b61dc503c4b405ec8e460ddb2bbe84a9236c5dd96aea0e1de69981e69265b089eab5a70f5a9e301d69dc397a2eb8122f1ac29acdcf8fbda78eb2fb37566f55ffc5c8f1c9d2cad3016f55a3e344f6ef84cbe2014d18cb838192a16f51d38e3494fbf2d75f42b1cfc6ee9c86964834a86a39c65bc87990efaf92a09881f7a92ec87538424e74f5cdae124b04be4fbea8c67c3fe4d9a045d63d7fc9c13f554e2f42d3e91f784034894d0685d7e9d0ed70fc1c14a5766389599e84e5c72d2524d86918db8f3bfb79985a2b0712d9fd885127848bf9246ce6c2abe2e7a4877a564477e3a2427ecee37e1dc3bee0c92d77fd24ffbbb9f3ff815bec4af4bce9d1e4b9f69712dc290214404d3c3bdbf9addd0bd890287f6707d2f5873b93bca64ba82973dba30fc03fedf72308065271d8cecfbfcb747110016f8369bd095fd37790699db38a0ce457a074976dc953fb895eddb5a6aa9f32bc8016eb54e8c33338e83e03b591f093b1e148d56833137f141e1b1ac6c092079f2d92e9223feb5ab9cdea3c841a357191a383f69b3b85c00120d2e4563d6fb8c0929eadc550cf5e30ed23a63264a8eaa31e05cf0e08c3e0310168deb63d9cbdb913a921069c0bcc696a06913386e62dd5448c8274780485a9cd228038156b4ed9fe10d48a2cec138e89bbf4da6f7e6b63faf9329a5e61c2a9506387128b03ccc167c1eea93d948ee1b5d30cead2a5a4cd38076ace4df3b809ac2f7481a0e6e90a67192caaf9120a922c89937ec971ce0c9dab76f66ee5a06d3424a30e4b3177cfba51bb5f39186a330a14304f4c4043d95f93cf27ab054bd630773ee6a130caa9207879b503cd8042e3ac38d86811b2a735f3ee51ab01721ab2a61490b2eeb83d9bd6b1e61a277867681c564d8aa1156ba640391b6330b7cbac9ecca73c2e4446f612a95f33736a1b62df0da5b83c9aa768aba6f44e9de73cfb796c7e0679a9d9f8fd91c25b6f522bc85ad76565031cdff9d33e0c942f561e2a0759336461f51b7f2a411326865c6e41e86c548a4728492a8174ce7288e9a2b7db544734833f7862f7e618934f0a0e95172dffe3689e13ee67f50e9bfa8e654b52627745b65ad63cfb542d1ec62ee36174f3dfefdcec7c71019c13f4423a3da36738110abebc5ba4e1e3cd9e444e7302167c4c5fd3b30f54093cb1aa5f481576a2fab74bd4a565509915f42c7535dfd70f518c065c65fc6a7e2b3340f121c07c05444dc3a80f6170238a314fb27d6aca7297229f57a1fcf1ceedaef8a80eb33660aee5de47b53635f7b71a2f08585771e0d1cbbf7c3196ff881b04092fb6cdb5414e62615441ca507b4365b412504af0afb50d313401ec37d02596e8f12b85f22ad79a208e7aec7fea70d26b0135461589b03475d36995dd95dc20639f5a17983cf5240560a29b56c31e65663cc52f89d6361122e1c3a314b255b47625ab6326d61332ca246b938ad5deece8e560a2ccf5a6e8a13cd38e88b8150273bd29b792bc5f21e64d3a684388a2b6931a781eccd7ddc873497989c93469c1452c6bea58f22d30abd91f1303f7e23a440228a6d9a9f5c3473d61ee69af3f11267888c2d225cc22df966253e83747e0b69e2a057181988d786efc81660cd25331e9c15534be8de87544bbe6fe255ab1bba6900475a7443721efb2f20fcc4d0a6b0f6b17adc10c863021dbc093e0e3b2e1aaba9b025619b54dd6f380d3a2871d02d7493d51bdba888156411ff21ba0b83b05215588e497e369a6db456b9abbcddfd0fe29c91475945572f8f570a23b2466003dafebd7594b8912fa7f9f22a34a2d27ef9fe620ef027084bf8d2b4875a12eb28093a07dddec03bccca8d187493ae50d94508834a7ae7fb5e355f684ace9ee749ed45fe67293817a487e66f61934ff52f4e9fba22b5bd58207bc413b794684b31f013e445c86ac09228efa525b3c8fb1f71c18f24d37dfa3623e1f9cd5208525e5f108d7b18e0ac8d3671a608ae5fbdee9936acec9e03ffaededfab1bf7986e1f85026c63e638b9f4e6d904f7216c6fb52f8003f2f06555051348b4c78c52606d60abc2777917ff1b596c4b3065dde80730cf00c444a4b772396a2886abc2a5f487fac52aba5a6b2803e371604f697cb391906545c998b9db8bdfab72b24f611546760cb32a04b101a88f1f1196b9c31bd67cae9e7f630a4334f187b8f290972a35d6fdb0af5d2a6f3cf877216e88eff7e4b5394cdbb763bbd1b70396b09d427fa885ecb62a7211cd43b7527496dc1cb9437ffbd15e85b37e70c204481c3af1df8d7149c114ce0c24287fe6094e87d324bad7f385bff59a18cb5871bd296c2f22ba7dd4f9ef68786962a0703016b9bfc147d031895cf5bb6d73646e5d1793d9eb3f71a1a804121fe58bd4070ada73336b802de4fc965ac7c65dbbec176d5e2b22ab4ccc216b842ad56ded5814ea60f8e907db1d7c6814335edc141aeaba4d467e077f6418d96219227b32c235d7e13c8b4b53a3a8bf2917ccd2fa26ddacb89c25fbcc484ce04e114ba09c99615787fd46f0b59258f9872d5b3b50d099313eb446d083c12678d4f1f0f492e458061fb2144d2e7fdb861b7957faad2eec8facc3b28be4577e87f062dcaffea061498b405ad05b9a20d6b86582f9c56ab1a33e3eb216619bc65ca2667db40cef21116443064ed26ecd8d66b651cb5248ace2d2624ad21cc159f026ceaba613f4945547d98d5d9166fa860a45c6aa8a34ff4c2d8636859f2179c346bf658c729464850e42ab4598dbc540350db50e0dfc6ed1158ae415dd5d825fe592ae756a959fbf9c906a46e636ce1d011c3abda4db9692191fabc03281c7de8599a57951297b0964a184cb88d9ff13a080e02830f0d2a8049c63cfbdf39314c83ccc3f5aa61d6fe9fd1f29a7a5b534bf145a19e2341428bd53b82f7e97325a9bc233243042de11ae5562922b0f64571a263c02e1c32d90ef261716f449374ee6d16cec909ec5fee44691a8a9eb570a51850879645d473a152806ac1a098cf17c65345a78bd7386f2f4cb31b03e53935b1d9729c6e2f4bf7b76582aa70fbe5f27d81f7212eff3850e50a78dd421ac6322f8349665044d92d38d5caa18e0f9786c8a3d9cfa392615deb360575f20c2c10121f2a227a0b489260ad84234d1930acafe262da5ebc642081ebc4a7041cd79d648c61a031ac8e940065a69cf404416b3b50027018b2c2d4925b53d4a3c613e7761a78abfc31e7ad508e86145ceed42641baf8aa411cb75ad0db40dd30b8f15331e15fc9ca86de1e9be3162046752c67a32dd0e90fe44ce490064cd50822c89037068077c353ab0ab86e285762b799101c1d6010bb60cef443708b23c4eddd18f91b738621459460ccf97209da3e8c124051a08b661d914f5fe70564951d4e5ad15272f6176534bec04349107ceb94094a9181a7f7a919302249589aeb32c57b9881f17902265cce2406a44aa9c7328c7ee24dbbeaf4e6418bccd08d5a644f5e72e6f313fa9c7f9730d10e3b0566d91117f8ac3601aa526cc12bba9353e377170db8533d0c6c32d94adc79f233163aa9275e44b811d456110f4b7ec835724267e0b507dfa100bc11d8580143324dad504072d1953209377b97b92c01f75222503ed0a65ba7fb4326df7d072905c167f94b16255af973b9ca5bec5359b24d822e6e1e3064543f22704b8031c442e051e2a96a6579aa7693503e091eb85c45c7bb57acf93789f8dcaa70b1844ccfd622738df6599a3b67405c6f114d51cdb1f60d38408a05902c88b743f0233552c634120cac4c860b5c97c1587f118134b2fbd152caa9346a6f95710175c1200a68877b01fd95919748a17bc2e76443d62f58cb52668c4f2e02897f8a03d46be272b2e1e1a79ca3eb2da2b30c420ce1959ea44170727770438ecf1bddbcb1879be3dd32dc6f887346da5e7df5d46e295bdfaa75cbc184ada3d746bfdf91e7606bc25f301cbf39ae52e9a1751cb8cde70745724bbfb3fa1a682a4ccb3ab9f60ebff95a803aac4ee63082cf71970e6e6063e27f50fc4e4331fedccca58abdb303b67274f4112038573a2c73094ac8631231b09a0f2c3f75f460236adf1d8032bf6d3cd053bbfd17a0654a723500cca4542493ca996d1251d64131b62967fa60b5c42c42ed61b8c30428cd4e8f8cccdb85d5fe72c1cd5298757e59d465eeb137e3a87ace076ac8dfe4f36b6a5666f1afde801ca752bbd4d583546918cbfc271b83661bae4af0c0aa7c21478f19dcdc7deb618ecfa513c450d3029423541fd602d0d890049354cb45f2b4b464c134f20659dc42fa2aa62e06005b8715a9ada30c91d4ed99cf10a8cd2083fe042b4b6738f05d9a7dbd2c019cd9214282937731d33ef6abc8a503576aa99ee9c3d177ab35f7726375db0d7c99381a3b3fc39a36465206b53bc4864f0327d63e7135da5a2f58fb0c90f4b6e26ba2c527d475d73f23e7afab447b835f2274d85649bbac0d44d09ddaff7c4a306600135697c92eeeffbbf6580cd37ec7303e1a451ef4a646b1ca76d258380e76fb124d90b6bbb57c4dd00f5ddeb79c2a6fa918ec9f457a953a0b50d5788ae6bfda151e24cd83d1302f7cd53e8a2ae0dc8d2a361fc23addf210617b2a6347cc6988edc63be14ac146da905d77b87db82a05fdc32ee626462b892ce777067e1b08e4fa3ecfaf76deabe7c19475eb89a55a717c9170544d22352df2bfbdd41ca0c689183c2a02294d44c04ddb233e42bfe047c673327989a6a7f15780b89b8af3fa43cd601700f1a27960209e8966e6a2b19b91dd74680e95e535096aabc14e312a6b7844144f9aa5c163b85b6273c1daee1a272e9bbbcd51e3a220aedadce6c73dd11ad60a6f723782dd3eb4955824c705b77fcb955946457ebe2d4996406568cf3ec20722d95514fcf998df47b2af2d53217bbc6d2dc917630ab1a4850e467c973459e7a8c46b3b8b32cd3d280fe61a5252a88ae3e85155f13a6a55d2f6c0a385bd770e483626110467f530c29efe2d7559b0757703e03a9f0ac7553412eece17108dc6096b421e17097ed26cb7f2e98775fc2e97cad3b272d8328f2573534d42d8015119584d39d24a8e36e1a1a69804caeb7f615a1331a9062d8aa8a3c588c289cfed56f0e660c5dd58c24f45e893903848d95a0567765e129bd0f2a4825b6f5fac4580f72ce572bb1081a2204eaa4495ee1ada0a17806e6b732166e0334a3c2f20a5f2c4aed53a068bbda6a69977b04a30f8ad777b4ab1e0792080e6829763b8577604eb7be4a216eacc6a5f006d00324629d2d1f8c82d85688d480461df213697811c31197a28a536e6d95e1b11c9719dc0205fc5f7e5c90c4c3ad9a10df069c07cb74f60a34afe0014ee0009aef316c45a069247d932eac2ea745ee57f897956a6523f7c6f0828535b09db8a9d91aaa174ea5d617443235458f77ef24073a9322a45181546d9e70c3e20a2388d806f3771c89aba33609d1f8754ad274cdeabda2c034d64159dc9be865f114585d80a64346eda1b5582fc3fa0de5c7ae39d76a1b11f69800b89274c78e938a58cb78236771c56346d5d21789adf3a345cf57dfd674971351b75718fabbe109a1b9403b9903fd9094ae987e36072ae0f56d09f924a0abd19794aa6ea3d52928308d8e9ea0dde4a040358823f9441dda26c70cda68e8a4f14c41bdb0c6f925d901691927a94804a537780ff4fe439cde90970ae0e7e067dc46a46b6e8fb849886b42aa17c156beee13f8e0369214f19a8a41f5aa9e789112a818bf20aa568b4e3d8dd6bf8e48ce97f43a341772925f000411d388672feb8a4492f4adbea434acaac85686db284950b61b1086cdac6e0253c205e5f5163e905945c5d7907ad941ac1402539c9545a1200cfd4ce0060ba453e8f9f43d106f3e6318886cbe5c9bed820684525dacb01eec7e3a9ff809d4dd0a40267e316491bb9e8c11f45d73e7c2a3e7ab2f5818e8fe18597fb8712d2b08dea9bd00ca09838ec34269bcab06f83dd87aef48f80ec2d6ef4991723ba196da3ea141a716f889f136ddc26a1923ad1466c482a38d4196a876e0c46a2f2f7df5ff3ad4788a54f71374411ae7c9505c994aab74f4c661ba48a4d82f90be6a6971f1b08e7088b09964fc2047491d39d421bd2ee9fd96ab9654b0620b201c3f81f7c998d3dcd03479c5b2714633b1a70acb81342a3584aabcf420a284f015c7fa29aeb4a6cc584188c0f6d5063789d3618406054b4777092684516a57fd162859e1286b9da81c870c0951962b783f6348c9d50c69636c221a06b47044d9d0941366c3558020f9ec62d0cc20bd248fbb3cc676d17ee9607b2e302f6602348b7c11ee96c95e2d956f2705c109d7a390748eeddea4f4af359a69c442f4d2a913ae1ba9e2543f6822fb904bc0a64fc8a41c48d15ace9837688d2a923d6d05a9b57ad5032f8c9045085c25a12406597a0d9309c6ca58968419b44ff70936c0027898fd1de683031ddcbd03f2711146897f8b02ae07a9d6f6f71e7d716477bd14a527874e78ebdfe21cb6d73d417218d4b1e0d563b7092a99569de4bc295773ac3295c22674076298658bb12aacb59708332557e9476d231e5ba0c35ac3ca088e543645ffe0675c0379d47dae1e7cc5b9191a29e9a294258e1939b9ec20291c01469c81021311b15f4ef9531f50b9057228e37a7676feb1268de62bfcb8dd4749bdc5fe26bbcb0b65f507be54ef9892e524dd48ddd824294e919d5440f3e596e14be77109ddde4d28096a0511b1eaa078c83c9b9feaecef9f400ebd7143fdc1c7fae4cdcc8d552065ca008ca6ac3f7c90adecbc7e371a0ac3092d7baeee9acb682cd015f193205f050eaa5e97d29b258b6dd0eb5d59e637c8d2b87fca91322998d8f3de34b5afca771ba584a57a13cec4ac91b034e71047c538f2fbda96c1eedfdea4c4ac2886a239222363e16d8939d448d6710390ce0eee18d1a0c9b8fbde40978bca99e088f83143e08ee78b688c54301ee7622b772ed29837e86594a9e9d056429d440255e265df1e66f448def64dd242756c738e64bbf84744db169074955265e80253811e05424cb8f836f68b9745461746bf21aba5536fd83c396132c517ca315ba6335faec7eb933d1c0084f5a70bb7241242a2ab146ef3a3901df35388c7e3077524268385c99ad957f05fb0f804cff1e65db3f039f1c0916312441060b6418d99fb07f5bf8816a6f5a7f8a297bd58fd8612bd42f052ab9e4798d92ca09c004d458dc5ed8f982438b79626782794d6275b3f34f847b9c577b470e350a172360f0411ad49ddd311b20113b433423d5d580139388864a0e5d7b07dc197aa03472871df903234c3f1725c69203d0caa69a00cec709a274b9001cfd549708c8573f9650b577f48b8e667c7131b7d0a56d66b0d5efe89139dc4aed84cb703df9807b82538da4f99906386410057769491882d9209219bbe69bc94c9e45b802cfc4869c8540b5cd87e8a951d24ddd820b49a46ff15844abebb12f9d7200a9d54f1ccebb784117ab3e3690662f0e2afa5f8cac12afdbb9da12ad6081c0326d3866b3cbf31fba5b424157b81e8a0b48f0ccca03f6546239b2a8b7e6c9aad6f7ea0e03af806d42bee8e1f9628323e2b4cf0cf24a33af1a90dc0870a2542dce9e95e2804631265ad2224493c87d703e0d6ae7eccb3dd4052dffc73c5131d17e1fd0b5cdd0ea2191103981d1f281d0144050bc4ff6209a238827a39c584d8c32760e613bcafb50eace78257586344a8f5887899d9d5fdd9dcc2332d97ea88175e996ab1d880c3530fdc4713e721a6a485c3a63e9f2764a6523a1d61abe9ba4008dbdec626e1be31304d2bdae2fca74a181579d1392309dd42af06deb4c7d65474947962f9147c1b7b96cb1b1062d9e12e3e811f222024651aa9c0207925afc76bab82fc1d88f0a0a5d9a332153d698b2bfbc3adac115c9414c80ca20ac007a43ee60ddf9448b1ab6cbababa526d3a2740e4e77be91559f7856783693a158e82f453d610b296f3c77dec6d10e0af3655a08f32cfe0fd175486d18cb8652c16c457ad606b47c8e799c6bc206978ce725aacb5141198bfc07888f94bdf198765dfc758c7d6bd27a35cb4e3cd49bad4a12b6956ca9fe43d20207bd6922205048c4d88ba1680be43acca40f16acfe7d38535c6dc570ebe2a8d638e6c01fc73ae2faea51946f19ae85d12631656adc9094e817d91a49757cc1e5fc0161ca7d27dcf0bbbbfa90e625460c427f8db2264a7eb3796fffb8dfdecf97eb4a1e0adbdd0ccf17bbca59449a87c57236f820a691e1197fd1ea946de70a3e0a0bcd404cf59505484986173467c7f22949065872f1d1fbec5fef7022aa8b1a77548a65dae0044fe66e3ca430f3616650639d7a4186d312fdf394b22f81ce3fb452802f3276086f355a02a0266ee46b28645283aee4885976747e4bf2d49cf18d55a5abea2ac220173ebd4fada6480c94baace0f12654a97e8d675d9e9edf2f9511caffb69f703d8053124d474029216aa49863020a53053d2ff5df47e3159f8f736dc308936ef0e1a426faee537d77f1af81e346633722eefaea2d16bd1103fbc627521a98d1bdefa77f8e0888c09dcb78161870094d64d0478f67f8e9948e4e8d7fe2227583d09e868e95e69a6e5276a36495b65acacd9c12a6c01d1357ad3f8b70b81d9c7274b7697c2bd0b519f1b8257d574616e98119656f51f313e222e82f523ab649558c701bcd5184a409ed00faead026117d00e41ecc6864237fe437dec8c8618f181e2858d10201e0109be4eee590ca91f2d7271da41bb1120b6532ad65eab5d809b94bcd2426e36a6f7ba94843f22118b8a92808227718435de05a01ad9ffb4702ef458bcadd6edb0d8a91b0ba6c75da4ab88cde727d151821b57d98df9f71b2c093fdd179d7a223ec332509ab7300cde0396b7056bb6f8adb7de22e332d7d8a490cede028b0f9f7242ddb62f04dec3aad7f13a322339a15303e4081a77053fcb2dffc0cc9a23d999bcadcb08f404ae429e76f9bd68525d7c5fb830826d34a339ec97821d63bd74c7655751564697de203fcaf619d644ac0d5586081dead8476e9277593d94db3e41547d4f11bb47292c66b27b5e57d9f9da3466ddd6851ca58393a0e8070e5e4124294b9c49640d7be8c61a6e957f1fe4bcaf2184b0b0b7d45a34ac402aba3da0c76784c2e1773966e9330e0dcd8ca2d301fdf1dc12811a6c69f631ad71b3faba850d2b4106afbae93fb20db22db13c21086ef22f4908fcd3e985292ba05f7cc59f27c86f3e8bb6a04ffdcf43bf4e372610ff6489699434f264dc6bbecc167910f8e2a284f36f596a8675a88abce87c78d22193b29e285a426fad2a6041aeb7c7870fa619a1dbcd54b75118e66239a1c6fd570e3daaf84738e9b3484e7b8375bb0131d3769265dc976e5b290c0688da104ca4deaf75dead35e6c993db9499bec9ac17ddae4ff3629d7bbf1eedb2401919bb4557b33f051678f6e925b3f925140647a4d0506d802df67d0ddb56fa195e64008f1353d9f9bb2e969dc2d83bf9b3855260186956dcfab3840c22acb3a498a62ca511e7116d70ea2d357ce05691451939817dd6528cccab776cce524530e8e8c2a2aa482f90e4060af7ae80b72b50990931bda42b082f0f6ea360aab56047a46fc2e25d4ee53829685cb86b78008f2d4b3274d49f6912f5c2c46e6f8de50e53907786af3207b42ad0ce85cb7cc3b7f22a39cff2731f3cd5de85af2450cffdf3e17de6825ce33c8ea12b19b9802491ea84c32f0b02a40e1b3ab056f8988de0d5b9b10c3926f9c1130f731b846b109a3209be368d706f43a37a09120441a6185b8c618938bd5b32b43e7c4379314afc387db0d581327b35ba78c0c69bcef7f50e0d080b91ddcda5108ac04351771374e2bd34b33bbf9952efdb73c3e53aecfb77ab98eeb06f434b9e35a506d2c13f2f40ad618934b2dfee053cc89e7b3e6b1fced96fc4614fdea3e74791f930929ffd7dac55bb497d2ab347471f79b6bae213189593806b16c8d63245ecb8288d548f5a82bc84a2480557b2f26d5bd941081f8b1d759e464fb351752d2c555a96a3ca2b4a9d42dd7d72d34ad2174fe1cc4d152b0df8d5dafe79f645cd1a49da7ce7b144053d5da64787ac62126bb9974a662270efcce1955f4561f462d1a13ec9a54f3c79eec880038c23404bcb7042a5c76adac936ed6ff224f4b248f1fb413fdedea864d029ca0f17ece5c386c9909c4527f6f467098bd00a8bfcfad82830ea1833e8971f96f858f2bf66f52a64a93d54da5712f383acd457a8121938d52638dd0a17cee3a9caac1bab93eb8a3d450e4dc1175d9acb439474be9cd4a65ad6e195a470b05485e4cfd9312465e221012a7421696afe40fc8dd3e8561873f54c69459a64105429f90e10d0711a7d48a0cfb6ee4a2ee68f8732b97b82f47513513f6824899c82067b4cb22ad3ad08c05cc67ef7a73e2709cb2f9ea1f4f98236b18a069c4e2420c024ff2fe538d167dc9fdad2da7cae549a409699a9964f241bc68de6e4dedee9dcf04a6a7306dc628839af1e53c5df514ea83913995007d165fa7e81c840fe99c9716097abdc3052d912a890f3c22a93024cafdf497cc7c923ec8a937f9eef3a89153a43a67ef612ea9c1968944a3da190d7a0acc9c647dfeb2103bcf5517d024598b446276cd961b0f5e6db2c960a56f66aa00c162946d36cabc61c19aa19f36bb94acc2df19bf941e2802b42d87790164493fdabd924f604820b1d20ce3e156650f98323009576ba8520aff34711376d125426313fe640d476b00c4bc2267b518bb97e036ce5f8fefa081878cab2425d6f03531badc00a57af7b2ff439c4843ed0f914e1ed2acf87f737579f898316b68a7487aeae7751d1fb1e3c362d890f0b66386ddf4fb4e86972c6e50d5fbe8d73af4d91c73d576a8c2a48f156c26cf8448ac8cf2e82c1852530b8c09fdd8da343a4d566824990d250c40217c51efb5016309739c442cf572f107b7ebb1af3e40e0262125aa9ba45078c373e9e6e4f8684a475516a26d2acd2601419a3e368205fe8b0f6222f25e1ab4023db6abd288b06b5af75f068b1ae2fed15f42c4ecaec512009ba700f4f50529637abac2084372d4bca283370c5dff94617033417cb63366099eeb0f2af46f5a5db5bc5f3a0791832b601bab01671d3bcd05eb1bef004abee53f671e6dd6aeb40399cdbada74d1f29819987815fc28c0ce9d547c85c4d7dd80e9ae7d40693b78e9d9bca24ec9d6a95f6373c77770daa6455ddcd44915a87f083497c3139d891befa779ac801c8656a8ef5f139fb073cedea461bb2a7228d1779b542715692054fb220b801a6ffec330d294976a0fb669a3cb1701d1ed0b7d30531f1dd44e667f6455942a1c227aae8cc8440d43db4d4479a1421a20171edc4c2e0e9ed679b3e64fb7043bfebe51bf9c91c124cc8ad0080320cc55df269d66fcc9ea4b9d0914d596c82a58d86633cfedb2a5b306cdf8b068ce4006bc1c50cfa450dd646fffc0e23374172db681f0bd69315399a64e62a5ee407feff745eafe0b34fccecba74647ea0390223c10d9ee0043184241415216c28c9f12c8932cf9e1e24e37b851d13471d307af24f9c32cc7c3a14a3d12896ff526c5dcb0a764482db00e2334c2c67ffd7b74505f398fb28b596a02be815686c60eef804c552d5d212810cc303568428fe393aa49aa20117bb65809110b0c288ceb55791dcea52c9d102b67f2f7250b033e171782081add8d0c4cd3fb8eb431bbc0daad0f71faf117ec67eddfdb0d7a6fed7e88d0f701c34b4affc02c77035dd3eb4335d22d2b6d530db33c706702fde8f7a34ffb98f5826854aefcfa58b98fdb8eebf7453b34ea8839f861bc8eafb483372ec1f04d4e207117b978d35543bb7c8d016820ee12918e049dc49147ab5737a1ece54e04f747e78308c3648cd721b642fe36fadba12d12b874f5dfef511dae052053c0b818c8172d3e0e2e3f2a7340cfb720ea0271b2e761a056eeba8e005e1964487f8028786e0f91ab097e53198a4c57a4f12eb1608d25384522dee6ae4fa2c4c6ab086e4f04ec68ecd40d6fe5049af425455a0b2b4d4c02fec3cd23634968dfc13f97deb885dbabc40369ff53af1ae5c13c0101fe6d4f439fc32aaa741e5aaac1a743f76af035528f590c98a94e60610413304246d42c953e60d39661837b1ec07df35b90f254d02a5f0720df74227f976fe385597451521a58f41532633971f15f6d67acb572fdfa9594600acb5fb4eb8334d3e12a05acc1895a27fd6565247123e30309a17947bc897bec4e24ea7791b0a79f110c35f800bfddff85c1167c4b217fa270a19826eef07ca38095b11926910817895df9a2b0a9aa244d9eb4d62e76fbe567308c3ba8009d4e484d54d4417606fc69d2a92127214eae75375b233fc632a0dad2b1c62f435fc35d0d2440054cef7c361f666d1a7e7f711adc3aabb498b07e89deb96b3848fe01d2c75abbb2468b76780bd92208555e088d373e270cdd47dc84dab21f25a187a65287435708e3063095dcd4ec601ba89345aac718c665f146f08f0e5c2c7b27b2810b4cdcfa84d487775af3caa076fb660310570deebabe6ce249838c7a01bd087c6297a5b3375ff894bb0e183bb31a086cc896dd39adcc4245c0a88ae6c54242382d3cd7d3853c6b14fa5802c15967611613416f4bb907d0eae1188c94f833417b208a07a54c7dad73118d8eaa71cb33cd9173e936f472ed98cb2ff12b3738ea3799365d70a643e42649a19b6941ac090765268d2bd7f3c0849f7e13007b0119f719a267f4c1797f55c8caa1ea20aa2aed7c4d294be414c1cc73405f54635ba01087c481d481f2cda00221c6ebf7aad392fb44b6a39c6e2cf9b699f581cec7a180feff684d6841922aafd3d0695e8721a57f3fa213a5a139db8b4eacbefbfd2fce617cc100ba3bee211e8d507fa95495c5ab3d58a6af819a06dc98a8803586e52c9960a621296ea814644a77259cc4f957ab6a509bf3a90c744e03fa2e366f57401c516d0e09ff02058398f10ad946f6904bf807ade087620a1006232d47cd3cfdcafde9b266fb7f14a9e732ef206bf127e9548201b8b2c129c085d5f7d56e5c6085ed844f960f5bd5e6ebdf6c6dafecde524a999294327007da069e0699e78586b4d65a6badd50d57c4a0f6b25a9d3cc001ab66ffc26da5000d4610670d79d3388d8323655c738237475e171412e6ead0907eb70a7902915298db43c33048981b0719d27755e12c107d25552051787481887fe031e6ee34ca69206f4f1222dd919f8fbc3da10b74f9f6348ae2db4361a8ad42a2303e41d82b6f2fe7e0bc22f675d8c3abcbc2adcbdd1f77bc232837146843414cf51444fa947ecfec6eaf39ec60a1a7d05248946c2e70ad6662d26ef75aadbd7e6fd379dbabb5f7628c3986359d98bd18635896695af69c9bce9c69396f1bc77d3e5dd77476dd77b3f74f7bd0862394e9863f04927bbbef1ff6201b8e29866c3458c445449a4e11ccf5d8392cc7914397aaaa1151bbcddcc953578e28698f8fb1c6e686c562b1582c56e78ce3388e3dae562b2466d0acf6d163d7744b7eafae65b1582c166becb1c71e7b5c21b15acd40e3ba504837d21adaa236f486e2c81d954aa562b1582c168b9593d339e3d8e32a053974e7d5d32a513e75d9aa52a9542c168bc562b13aa7733aa773c6d538a60034e27de6ceab47b5c2adcec6bb791cc761b1582c96b3723aa7c7b6011d690db5a137f2a98f0aea542a55a7fa50168bc562b1585a8675ced8393618b119956858c6e1d6bc993841e01e954aa5721c168bd5399d859eafd943557445593a8ec110d0062404829d49b5a9b24aa552a91c27c334168bd559d0e4d09594be62d6b35e49994d94524a29a50cbf55f22585a21cc75913067d6fc1b46949674db70d576da854751f30e5791f62a2942df44921dd9753286bce982f2c2d6850ca96528eb9c191ae1c95d451e1b4c91486ff9ed7758e83654fa7f256cf7a95aaaac21ad47130061dc73a4e751c779c761c4d0e9d26aa624c6153e96a1d596dc014eebcaf2a4cac3654740f12a5c4a8e8e6f72a641a400dd876761a872ef5d544438aefb5fd12ad29a6bfd058682824aa46afe0c89d98170d0e2653d6324cde786b0783d75b3675df209a284cdb0ac4c4fd121dd735cc305939bdc808431d5ab05851e28d504e52b015494985b4830b0d991d7468c1624589379a8192a2e2e262523a7d36fee5a3791a1f8e77f972fcc907e3573e29ca7c371ee5337dc8030f2f4c3078c881e346ca0b52298554a2b161323269eb4243664a1d46efb7a4327ad2e85d464f63f432a3d368e495942c76efcd30c61a8661d975023282b0c185864c584a499991022a99ac9c5e64ecb0c348a5e43b90407a7ac27086c9cae945062964c5a2e725e285919133887644223f522955d9a08888b74a2f171a329aa6b9d0903199400f02e90181f4b0e1e3424306c5e5e3b18392c9d3f8789c4e5ee6e3b183141929272732524a2713126986c9cae94546484386347b4e24171a32271a9ff82edfcc9f7c2c2fd3f2fd252180192e70a268f9c21b962f6c7dbaeef3f97c3e9f8f0066c41a292317a3945187444e345c4ea79348344a2991ca702a038d2f00eff20120470b2a3f0a00004825d20c9395d38b8c914a29140a8550b49013ce305971a121a39d5e64a88144229d9cea8b0c52a954fad21a4a9fcaf7f819198f3299c2f0dff3ba2e1c7d582a29f148e10c9395d308a526250a1c15193227a7d7c09797126fa4b252da81340325a5c41ba9ac945c68c89c944c4adae945c68ac90e3bfce9d442d9c185864c48fa524aca8c1410a9b4727a916122e36798ac9c5e647c28c385860c0acac9a7eb3e9f0fe853202e3464524824527883f284cba9342a8d4a48afb5c829d47734c2f05bb49861b2720a431fac9ca3d8703616e00ab004f4c011a80262ee06c5e4c5a44422b9d090394931492991687c30eff2a152beef677c312ff3c578940f7479192e3d52a14ca630fcd762c06fa41aa946aa916aa41aa9462a0d26c6c99b944e4c4a2f279713e944322af17e3ec9c8138d888480f4acb05074421f844d6c30305111fc6021b1d3d2e1141303e6c58509068b141596965ff12244b9b440e96082c1224525db93cbe9746ad9d1c5d8fa4186f1071946d50815233d4bb45a36a85e59bd7a640bfd40f0bbb141414141414109b1b9a1e11331df9c39b1c4b08cad9d91099b7bd36a9d6a407c8cb2a554baa19d908ec9c98989898989c97f763e6870195b63e8552365584422914824128d3b35230b2aefb8185be3c884cdbd69b546d48b969293cb06868484c5450bf84224128976c6d06bc7c5d81a47266cee4dab35d233b233f2f2bc119b9116371a711cc771249fca3d204cd0f0075da13fc6b1358e1f146ac41573ef67e7f342c38e4824128944a29d31f4da6109c7d638a250209fc2542039203a36bd425d841441e4a9c8873c0b8a099b7bd36a8d2fe1d81ac711c69503028db2c5079633866118161a7fb8701cc7711cd71a6d5a2c27968fa475fa7c3e9fcfa7138dbd52d35aa20524a919c3305c39897e9c5ea8bc506131c27c2439243a8d43e23a692c1f890fd9c2cadb9673cef91482b4406c9668d5b0701cc7711cd71a6d5a2c23202d10929c968f64a42f974f348a6a444ab0802435a38bb1f56364c2a6c507d23a7deee9ec221ac7d6d8aa39fd184f1f7ea2f1048a7efc1857a8b048f9f92b545250405a236f48895827a41144670724070404d4223142a49f4712298ce308d26299a88d216872029e94c121c5ef2ee43d294331f6bece063f0abde8033d0e3d0f900775dd87e49333231a2bf23c78843c8fd077cf03e47980fef3f503abe943e49b355d28a495c930dfc583f9721b188182f93299e48edcd9b163c78e1d120da8ee070a537feadcecdcbc6ebef372469cf9ed29d0f13c497d8ee3387a9eeae76b0aad7a3e886d323d09081a52ebdd2929ee44fc291486c2708f9f4592baef51d075ef810d027f033fe0dd68b8d7fadb11846c83d8fd2e65403b9afd820062d5d94fc99d1d61105333a70d229d39372190904f7962ada1584dde27fa44be0f778fbbeb7efee7a65114634a75a80ed5a16004c4cfcf0df4b9a86d34732b00cddbc6c38bdd6b9ccbe9ce81c01e224f49e76ceee90761397076d6b66fdfbfc91df165d89da3b11feecdf148737a882a67814e417594e841a7a04d00219be0e1a38304124c2b3826650702496cbd628f7b7b01694f3d8fc26cef6d3a5aec1ed4812921442e07578386d446c8c4bafbdb808bed9493b2e5defb12830a3d8661606a03de5fcc8bc9a47d3978ec40fb1e3f5383c6c8401bd86b589649f125a6b18d066fc045ec1beb983572d8e86fb0a3d80af38738ce9d9cf2b44f85daa762a62b35c7a9fae1ce9ad9ea6eb9736ba8a4e7a3e96a145d87aa44dfc0d410aad7b1e3103a53a5c2c0117b8d1fc65be3ca6400420ca4cb640ea2fc104c1892e94929b17cdbdaa764a841bc2d10ebcfee5ac48b00b1ba5cb99f7dceaeb5d60691ea7cd371c569bf0fed636f8c099de32f8647fe1eddcc06f228415751c5ccf63dba19138d41b3942e76085addda121ec0101aba580479737f6072ea3d439619e26087b38b72522b4818c815fa4618010318d4a00639c8810fc45497ea529d0f33d0500fa847bbbf54a6711a7a5393d6ad6d3aadfc1984fefb1227b4f1cc622076eccc8c62948ad9d7438eb641c39beaee18868958d46eaedf15359ceb67450dcbf5aba296695aae5fbb88573e56938584488fe0818a0798c38d143138597355c407a6fc646f12e54ab2a6108230670e85914988426545cacd1b0a23a318c18d486905a78d0da6e5ac619a060a0182f42936e78c1ba5759d47b8c79232bbc2cc2368688b98ac1b2e36a855817da8d0648a7f30ce19638c3f1f10fd122f986aec0d5d0a374bca84bc62ae7391238014ef101a0a1c55e43602dc27aa706fb00d8715b9d7b25c374d5a0e477eeee5c6437ece00210ff20908017144fc20608e883f0137227e97f638ee6b5cdd3e3fb71b38640e297ec092ec2be0fff9ccfff3fee1a13c3ccdd33c3ccee33ccec353792a4fe5a93c3c96c7f2581ecb6379782ecfe5b93c97e7f25c1e1ecc8379300fe6c13c9807f3749fc701facff7c603a873ff4ff7f9bbe1083de87be32104026d1ab80112fd41e00d90d88172c301125db664f9bbe2e7c371450e7f365b0e2996f857e0f3f91d1445d17d40fc3d05dd706422f7b3371c9ac8bd46f3e7a3d4371c59e45eebfcf9ba5be4dedddd6e383891fb5a6bad77c3f111b9d76cfe7cd65a6badc88dc4a1db3ebb71d915f5e1d2a93e668d8e98f21a117f2a46c41f70240edde6d9411d58e4b8cf20f680a83d11220f9fcf8fe3034ad992baad9b0f58f279ff92fc44880e6ae003de00891c2865cb96c11ba05e89b85f220653f70ac11281e8ee7681e8c8144d573530417bd277aaef7c813e1186dac7a5bc6145daf6e976237fda4feda3547bad73feba5b7377ff88da6b35e7afd65aabf69acdf9b3d65a6bf327ead1657f331556835d3a3d774c591c510f6cdb3256b2813a3051d31e03e59631ad7583bddcb62fc19e0871033590c11ba10c4c6539374260ca7752f5d522cd1333c28c0286fdd69b31c5c2ef5616906199a635cfa49dd50fa464cf4a4f4f4f0f1112357526989a494c1a782fe85880e709c270eac89629328bbbe299eca5e8b65aff12e083eb010ca08e2b9e62cd9a4ee9956bb0f6f0667660a98c51e99434e32cf89724e4d2da0c879f4d2933654ba543640f93a1c3ca0c01621452331d40f85a6f9166527ecab47241b2e56c356a6270eacc96ce6c892cc4d4d419c10e0a5e468894d239d21338f8012d13ab6b9fec1446668c3f19156935a5b49b52da4d04cc033ff63247f38f85b8425411533eb3984511c1ef4f4c4aa2a665ff482524a2c6e54f97fd13891a080463a0e532200212223222f24699a4845432c9278f92fdb322f6c9190d4449515991fd9ba2d66225e41cacb2a57e0862842bb369e501b1702a4e8cda848439c9f00664552d0acd060a09a3e1d030fbec15a417445a7b5c5a1412c65241b3d1ca605d6be8919f8fe66a57875c8dca3a8045ecc25790a8cc7ae193f03c7c414ae3030f0dc4626f9286775e4186fd42a275795ed7b93e097443b016ec6c34da20166ea27b916873ceae3a1deb0dddfc5aabd603ad46ae504d0712558120d23474b30e4153499990685552c6751881289f6475ad0c1f0bb4beb29cfaea962851e818d75a5badbd8e2daef53a8dbc51ebee36bb419329292b31f6eeeeeef9d5ec5a2d6fd8f514714e20e413f7ab4cd0903ef65a0824444444446444e43f3245def47aab5f91e7f9ac2d0fe35f7c4ade9c5e87930ea617239279bb254ba1eb5ac43657a3d9d242925d5d93944c168b9580cd07d78d49c2891e6898038754aaf3965ae68b172d26b34d4efc8a6c34f762bc39e71fefdc318c7f18df8b1690df6bb30cd4719b88e7ccfb07910ccc904d87d3d086c278bdb1a16ea3b99fcfc54f886cf867374bbbe8ee9336e95293ba5b34497bdf25dfdda2ef9f351445672bec1ef9ee0ef96e16bda241dfa1efee4e6995ee6eb0519a01dd37f79dbfbbbffeeedebebb906efbfd201b4db3b8684142d22b218b152a2928e0f7272625d2c87b1b8dc87b21259ea8c4231195949478dfa26f128f044c1131f2443d22628b60894242a0d7bf07d27d42a0119733c906d69eec6630658b6095f49c5018ecdecd9df3ce3f0ee221774fb5e8efd831b61948a8eb7afee464a3c97f22a3d075d64ca2d0b5cd4a9b0efbd8e30f86effbc905fd6493279b0e0b8213ec3e2e288c0c3499921ab911e9f631bd926fba3cd2ae24cfeb1ad45d4a095380ee8186f5a514a2bf2a49ccc0f74b66946e2eb1070a635320436a5720d2a7d6082985dd5142a42d5083c21a91c76ea7dbd9e9fa9a41a49fd2a078424c817e8c2015880768b5d328501174853e123d22e80891d2771128742d449dc1be0e60d17eb5b6affdeb1763cc6e34b73b9c7140f4b72010fdbb3a9d92ce68ad468154bd4241aa4d4c815437c3248cfa20156805a01508816cca8931569d72f6a9086c63599665b31ba256af1d92e70c2a4ad1a5f2288e24a03c6e0d8254a016010c3a675c500f0c5281483051799c794c81487f3c218fe2cd72ce1811fd987306d3c78cc1447d60da40a4261fa4ceb47209d4878f1626aa994c75b650c08a6cf1ae767e7df810a98095576294c945a2ba1922ed70c63eb329a9c96b776f77bbdb59af76b359fb70a0973137a6bc7d73c66fc8d01fe4dff9f5fbf1e7fcfaad57ce7855912dfef913f1ebb7bec9eb8c44997a85ca2664c17a77d87ab515a3dc4d36e57c6d8e1cd7d6398724549fd32bbeb63abe764e1c34f527421b3e65b5414d393ce57fd26adbb1ece57b6732870f3d607be945813bedd935a3cdf81fb3994c51742ce1388e17638c2f06a6d8b3661cc76e42d718c618d72d634d8ace24657a3489b6765cde68a4a9473a1631e2ea98bdefb94dd3d4283a8ea6d164e9d828cfebbafbdd590d0da905e98f9c04d6172ace50dcc7d756a730d666af19e756bf6eab6b5eab63d9c7e626bc6e79cbd53313aa87a3edcb9fd6d9105751b19f6d00f7ca1baf36e7ac042962f31272aeee75cb5bae9e9550e20498cab376f706bafd27ceb00c63cee56ddbb66ddbb69b456d03e2c51fc80368711342bc3f430d94d3d6efb57bb9cd9ddb6cca94eba6c335a7d46d88c1977a371eb06ce333b11b683225d52fcc035586b5e74beb4ddb7df688dd930a1ab6cfcdfbebe6ab57e80c0667cf139df7abe2683225552babb2686fb488bcaab488fc854655c72d9bbe7935ebd53e5ef4e94ea3dc85436b5ad5e37a793ab44571e8aa775aa773dae5795d0706d1673080caaaac2690f07abd5eb3065e70b5e775dd0886a8a2e5792df9051a38cb59b20924f4ab5f12a8ded25ed527a5d5f1ad3ea7577c6d12acb517db767cabcf3bbd3e76c7186399bb5a41643b3b1c5f3bafc5d32bb6b785c380247c90f65a9c9be8bafab5737a0dbffafcaf464caf38d1b5579f539ae44baf4b023b511d5f0bce9db63f99981663f5de8aadcb16ecb7bd5669b5acfab5b9896ecada037bafbde9e6d36fce741df08931100b885f48b6842e207a363b20faf74ab5ddb4db278baee81148e8261154cc1538b7a6425cd1b9123b1fa19b3a5a3acbea4c960f5efd12606f0f9da3ebfa3d7daa9c47639935424763c67c3e4c6b35cf6ad5b28d26e391e21986b1e422740e86f84b619a4d87bf0f14c6ef57f7ea9b49cb4ef2bcad433a8c79e0729fdc5d7fec6754db81465f34faddeaa68342c0e90289e2d1236626ff0acf905678268733396626cff7b624489336ed124e8ed18889c82329198de4c8e1ae2779af2770ba1c41f40aeebef47db67e5a92d5a0265f7f49cef0c8be079e6900f058c5ccf4f7c0db0e2b6f86c62a9ca19f0209d15ebe5679d0ef4af05318c7181c83a0304250184a5948d41c21535309d11f4f89d3440972444e7489869add8e36cd2e8f1e3f23a74b4ace41f49733464ac2e1c6266a60263b885af2def32079d16bfd754f674abe8290321be915909f049654056c5f5249af80ee499f17413fe949a09ca9416b500de4473e2eb3a32a31444c511555a95eac4c866e3bbb091a9d2bbf218b48b5bc7d2428a43d0d659913659e5da560750a8aea2c0f5ca930009d99ab31a4e66409fd8a8ce011914e27f2ee7c6f646d9da6d1dceacb3462216979e3b15453af70a699c5b06a547dd1d7146178699b8e11d1a8d4231292099d60e8e6cf1529fb8f2e555fa5fc8597a6d3cdd74af65b204c98b4bdda8b31ccc66402cdc06482487fd29517ba9e93896dda649b8add8242ac6e2ed1caad1088fde4c963aa5473b5f2c16229510312523710c4abf35614c87455576e334cec429723891a0f6040cef16a338c457dd091d6d0155dc9162e7476cba410333d8d981c435d3d72ce39674f82d6d4ce59658c3489d8bec810ffbff420da9721feec7bdcb86df7d6ffa9c07b15f7da9ab3b558b515e369abf50cab6ef316dcc6d0a1830c3dfb30af15638cbd5aac5a2c6fc1e66c319d1cc5a4e00f1f500788b971f56a5866e746ff4530651253afe3c55cf0b65080e82becaf6880ca1cc77174c0c5a4953794888d5e2d38b59756cd566bdf6bf55b6fadb569d75beffbed7abb36ad2ece8c05f7e29b9b994ae713549b998ae0d57e316badb5268b598d9a5ee7a2d657e0c7e0005ac43fe7747904a8a51b8db55eb7c3f16509f18e8a318b61597bc5d8e69c6956cb1567bc036f5208b96675e904fbd85dd3f211996bef5fbe0e8449b4d94161e6f703110485c135d3f2e6e0dd020de96f349b7f267873b4d0cd4fd9d727d4a2e13cf90ff41446f4fd29210bab41ef606809d017b201d11618b2a1214501531825945953fc1e6f34d8077a75dbe63edc43efdaf6817a40536cfffa1ad4beeccbf362fe9eaecb7db9312ecc455d8f41f9c37c2f9fcb77faa45c49c99b1a187342889f6f4ec35c8d9a18ff6cb97f7fbaefffd0e7e27f3e9fd0d321421fce8910bbefe7bc03750f7a81a600f550982972987fbe3fefa0f70781be83653f40f43dd74ae15a28600b7cbc817c9f1441be144efdc95fee43add012211b0eec6df30d2ce1e1e4fb4fc08c37bcd1689a48cebe153f41de24e72ecbfab393cf9e8a21e3b24fb67d96e5d772ce1d6762f2a18d665bd97206bed69d7c08c302cdc949cef77e3a5008dbb8d6df3f79ed9e5caed528194f9ffbedb10f3de8bbffc88841c1c4784971413981d9bbf6fefd7ff681fe9fc5ae4f568027b71f77fefe0c86342182b64e05c47028ccc9d35f6142e43157a324b5af1410735114107351104ce1904568a36990c3c942373fc56596484322aed528d08be35a1898f2422d10d7fa0f988a71792ade0a8f85873d71c47a29bbee25654989e7955eca52e9a524759b4475ae7e1fc089983fd4d221d432855a30422daa1a42057a01a66234163015ba0053dfe2b5f20a5f3aa3bc71b170ad70a9b8443a840ea89582026a81205581581feb41acec31104bea1031e6ef5e5af70281ddab7b89f4a5acd1b93c57e7c21f0af59f7c5286522c7d299a9237628a6b498e6b7d5e3a628a1309017950a6e50c5aed41409216da3c1a3b5b3d6d284cad2797971830a8181b397a88093d0ae68bf1bd7c2ed6dacc25eaa7666bb66a08d47d38d74646369aec47360cd0687f638a58dee477cf9ffbf87c1441020b9d83ee030bc14f6d2afe8a534476845c267a7a42ceb942d7eec26b8b6a57eaadf7b67fdf7a31ce51745d6f483767679caeebadd73e11ee299173b698e38b5d9be987d74b79d72b866127b04fc1adadd6eb756bafd76b330cdb0cc33bbce66cddafdf6cb39541ce39bbe79c73ce5e7ddad49cf314f26d43ce39e79c73adf8da8aafcd39e789a34deff67bef756b22bd98fc87e69edbabbd189b73ce9c55d7ae4f2c5d88ac7db3c7332cd3b8ead8468e39a3312c5ff335e7b4b5f3f6a98e3bcbdb9d3d54355f13dbb00cfbce1a9b1a98cd9e5b6f73b66a5274f4e9cf57cf14ad6344f5f66ab18b6d757cb15c052b74fd038eb9310ea8020632c056ecbdb8578bd55aedc5b34a2e6fdc96bb63a636db6ba543c0d0312f86b13b6badb7b59cb34631e6f59244db978a1417e08a18635a7bbdb77a83b90a1a6ef9aed8f67a310ef01c64c026c980dd7b31c66ebd18637cafeddade52a8384036a65ffdd0ae9b38c456a1ebc6deda6f8a5c06b42fcb3a90d56bdfca965ab1bdd98e78556b2ff68a6fa6bd0c35db61370c753c91a3fab5b7d68bad87d65a6cb15b8b2d76bfb5126152acde6aadb5f6e23a1e611cc7d1061365ea4f51273c92d1844d26af2ee78ceedb35f64e131ec7711cc7ea266cc2a3ad5dbd14dc3e61f89cee354ad03983d640c2a0cfc40d640b7d1fed0471c2559d66af5a53c1ddabcd1c5feb354f21b4d51bb3d52bbe767ef54c73eb01a4c9a8e4ec9cd894d108000080800043170000180c080603224112c561a44d3d1400115d8a4c6e603a158864590ea3389252c620620001841830234043b36d00dd0ea8bd0c64a36ac24bc258935227f89b6e8c605d951e1a7804a72086d1188857bbd0b3d86a16288cf412bc42e72405b94aec9658bbe137dee0f44d9a69fe8cbdb0fd9f9e47c498a57411186ef7af626b875eaf9cb29c89ea7803c0882eba529d6957e4bce6e9f470d5b2dd1ed8bbcfb42aac447532daf4c76f6c6fee35208e662291107894708205d11a0c3be5b40ae17cb9ed91c94cb5a1af21525ad21621554ea02f9301b94ae08bd9e74c055b47b3910d27d512d0d76022856816472373434a1bcb689a46cd7d69c7e0182e4d6ea718a8fa973a36a0084aaa628cfb155ac869f14488950a9bc297f7c3e962c98b972ad32ae3264c5f96559af8279d8acca2b214f695209574eea83cc87e4df688cdb740a01401ab57984e30169ba0584c0dd695b34e2e59be62a70a453cbd16242fc65e05b38b450eae2d7bc13d6e0b6f958b04d7ffa22d8c1761b277bcdf3b150171104c5d4e92d7d66008b8146eb5974e0e28cafe8547c81042f6af1f3093c37a8745b8941e6e84a516867f2a4bd351ff289f0286a3f5b2619799cccbc8efbf44014b34745136da181358db558aca0818707a238d1eddc4ade32f7784c8cd116c15701e486044258c007ced35510f629c817bfe59141056c86bae58a028c3ef7deae28785ad224e449ba009f9a8bfa044b969f3859e0d2684d5810b36613e1d84196513c76c50b876b0ed98dac23deca6b88391f2243e3a6f86afc1ee88cbd9415935df67e05c4a923f6c3505abd349ea341542879a7c3c70a849a938c884c8ae113e492effa58696a8667a1a49e8fb941dc4fe00c38832336acd610a0603fcbe5921bab71d1bdded20aaa06cec8bc5875fdd35fd9e510b188c79a35fb22045861d820cefb5fb0483e189d1b03c2d46107ec62271f1369bc14a3a80057d73a1527ba6c464d976638202976ecf418574d007bb822203681719063058986bee0e44ddc21e63abb38877a9d42125305f16077a252c8e9d898a448396a900257c729adf480439ea102b7f047bb00e45682e8893496a2debd3b68cd96c2354ed4f67bf9badd46352a137c72632293fa13686450b3098e2be5d47adfa8ececb902833a5f624e39c488518639897736ee74208e5bafa5c223a3f0479d46bf90b06dc33f9d2d8bd695e567919ab59c590ecb098ed3e90b5e73de2cec2637b542db7b333de02b7d6ca17ec71b1aa88c94170059241cff51d080e0d61dc5016aee67c1917d101072867a935f182896421162a9c8225d098b65174c11427e87365175d0948ae33999e70120529a99d3a8cc7e85b37f695b81b9b55d33ffbf0aecaf086175f0bba45ebf9d972595143c34adee456b08483ef23a4417c26bd8405b7f860790fca138bbad5860bf6dcd44c3d3f97c53da5bcdd4baab05c96876de805001dc0e0c45d81d10d26e9ba881c9344f609e5336987dc7f63f0daf8e04488428f6d26bb0e93568688c9d8a0049d272bc10e1b3d83de27ddfa434827a34b1b201107bd12ec9f2887cf0117a701b184ac5251f17544919f0fdabe152272ae075ab68c6882f29d67e4821d72cdac04e3950610e746aa37a69db296374fb07a56b7ed2463a7de816d361588873f289930699d62c4c928e1078113dfba1eef380a578241593d3184ff8d9b7bd4f6f8629d867082c984516012970b6582a0539437f5e6d3823372327fa4e6721fef59074b97350927d32a0026d491d2ce7918583d0fd89024c2fc5a72078531c1d2c39b4e4200eb1a126c34bb325bffd4ce8ad10e456f20fede977a6f1e30af5ab945b483e144833cbe0827930747875f26e8d3f5472f21d83fdd9ef6cd09ea89eb4a48df5fc7bbbdb319b0c612b39e0c6a9d1b1c56d615930da4a4b23d3a287bb391c076785e6efc8135c331da0baccc5d170729515c5e54519902dbc28d4cb6f3e0f8bda57a65de344b8529b9e55f3e168fe2f6c2b83b4077bbe529ed821e1d519405f810a7d33c29e3ed4cb23e1ee57085528c140d4f0172042663e2f15712b6ecd2428c91e242447629268b4a84d0899df78b8929ca41002a096c8212e41ca74adb32d3173c0706edcad47f504c3a005b18b497716832d3f80c40e01f4c00bc6e3463f71d0198dd789bb84717a9e32afd0b55016f75f5d5d9b5ace9f72eda2c333ba47a6c6b08acf6ffed3e2f79bae32f2efb90a530e755eee3705880d1013f6083d1aab2d94a2f3ef3eb0eea11265098a3e9a367ad46768fa87ba6e92e2f4950b81133e6ae070cd9758ea1d89836baa1e693afb079a94107e43484892ca5d8e4035c509c8d5e2fdd24852dd5d60c4a8612010baf8e185241a25b129a9e5e1c54dc5aa140de4aa859fd8049c19b9e1cc493af2c851c30fc65f282bc8011d6d847dc3ca27ee47aadc502169c8ceab76b4850ff3500643403960aee3c4f8465e00a4933e6217a4123d45c48647a3b658e466b606a740bc0eaae5c2f8a7647f4287eee507817c879f90476007cb79c939a118110ea4df0eff511c592287a7b4ec9003a9843860f95b6e330cf49baef62e19dce5f28410f5d5db019a72d94db61ec5c0e817823bf12e15f3b151a81376534c08e7a866d45a9a720abf3adbf034886876280c9daf84080411a378869619d74bce42360b818447426a10ffd373e1d7922abc55cb685944a845618982ea404c5f1ffff8b41b3fbd741b2b3f757b47c5b170aa9992aeae1e09133c065771e6dc4ce2bfdf77f5e3ffba30717b37e22f79764da79fd566aa151d1d075d5368481498f94a102ce25a1bc616bbd31addb685b51fe47f831b3ccd6bf6f7ce9761002ba46f0c99910698082bb0bb0efe51694b3495f0a9d67843b45a30f85d6e8c59e9dd59ce2fa918a4371e577f94ac5fc5add26eb8e490abfb1789317c10376aea1e7d1503d363f26b838df804c1680f8c9035a340c790af678356e6382bd0a2b64dbaa651623749cb212ba79634665c5096e560041de91308f01d52ef5712e01fb4a0639151b4369a5c0d6cae4da7a78dc68a39f50b5909870a9e03fcb4c65a8303d5ce867328fc324a464eeb570e2fbb784bd53c6ff8c3b81ebc1096084370d882f8e74b0e999d9c15cd980c9387908eb3be72998e80b4da00dc107dba5b4554f468777d97f59b8cf375e059184c82237a8bf6463cd54abd27bf6d241760d8e5d83beeb5a2f4affd4b5d1f3a0e753189f0c74257104a6fd2d5b2e8faf1456b60c03723ad52e1fd72d63b6328547bc2f07a0ba418f9585863b478156ce98c1ff90eb7e4da4e49c13721d2f31fcc96a697ce1745cbb42684a2404b460b645c667ddc9befe99deec25f760969bab4f372479a155c180b4ac9f4bdcb214d3545bdf7b411f34bc71bdbc4296f93a721ed4c6f59d028a6cce3233ed743c37fb54faf3f1c73582d1b921865ac0c2214146a5ce5f7c71ae080634a0a98fd8dc70c86190b114b152280f059041edb51db450e5022697a06ca7a554e612a07545cc7a82bc1f37aebf9423c918cdf512d71da1d2c053ddc72318aee6706de861509d1f265dd3e807281408318f873d5bb74285e62568ec2051895c54f2c349c7c1162f033bbea90aa959d76a5fb7f594646dc98dbb0892021fcc1e5c9f07ced4503723f39e4ffcdb69177ed03490b6e2a1979ff0679c9d275e732b6cf7745a8b53479df66bb3b2b3591645378e5b8fcebfc419bae7c2631b574a8855a2ba9677f698f8ae391d13c700066c3c787c534d6bf05a4275d312f316641505769f0409e322bb8d98a078919ab467774a082803e91c10962c7e8b07691761090e6b89d6a164154573c457c84e31d8d02ed41e884430f58c42a37aa7f3d3af6861318afa40f858080e60c608df7444bbc82f81255c5e759058b7bd8b7de185ef1942b458b5bbb0cf4e5dea2faa630cc994790b50140b807511a5c74dc9cddda27648570bbaed2e7984fe511177d944997dbbec58d48dd29e9e74c0484121bb06db5215d40c46023ba8c32aa4250cf35a358110e2dc752dc7106186798cd37cf6af75c7a712bfe75f246dc758e7d5a26028d68ae244930fbb427c11fa2d5e79c0301d6019f6661fe4e090f9a97733f728d68b448f17a1df6d3b2797645b6167d10533f7a3fab779953b9aef8fad69d13c9f985b86e6d59a93466bce9e11c9d2454f8e597d918fee116400cf6eb04fac6166c1837781197a7e4fbd38a2e02f9f5aae18ed85d4a742623dc3d14832c5667ba6dcf8e4daf63482f6a9f5b93236060954f355830d577ed5e534fa03b3cc911b1ba7198f24d3af04882e025a665bef2aceadcae9d6aa10ef7c5bb5706f0dfcb652d06dd7ece546cb074d890c2ed3849610f28ed5d2b4958499863ef426c84fa86fdeb813ad16cefd7887ce34c9408acc4a30324fe34e3b043d2f54ac922380a38d44fd0387c5a992b62436bda887a0e0c8399ffeddfba6501b1ba3c6c8bd7c0e8c6110e5e96346f637edbe3c3b0fb8d9200f76bdf2c2efcaab5603d3afbf7c5529acbfde2755bf2e505c02eccf27fbaf4b3ca380d6bd6a4468342e17377b8165340d7c1b6693149d37d78f49ebd5c7c472bb5d09efa81a8123a4dbaf8053cefc0a30275ccc6936d8cd8695d1ec46f4cae52b66d9671dca12b1a804e8a900e8e7ea48a5a36b2180563688ebb9233ad5e924927990cff40b91bb2fdf05e5f436208399292f4b9df30df17d1899d21d61d373d11114a4c92d7a2fb6e1c96b76274f3bf63d34bb418537dfcb85179c738f7b51e3f56f613a120620a49f87bc230120927920af7f1e8b3910754c1076a63adeefff58cfd54ce210ad0060f1fd1f0cd3a735f4d4b1abad9c45c8e1169e8380a7cd8ef058c59bcd0d226d48d3a431083e84c3ee2ae2fde3b9b50ac25c49a896b2afa1e4f384a5807f617f65137f6261bf2be7b4d242948c8dd5e500b30fc28c1a34d233fad345baf0e1cb9f1faef4fe511cfabdba5dd5bffdfbb75cf2a72dfd67889afdc1743218fa29e8de4a6e10c7ec96b75f9a81e366332f758f7ce2689db8b3837af6376e45fb80b6358c8fa02605832e87979c8083af3fab3420dff95f306d1dabd1cd57807cb775a9053b01848771aaa6f2b83c1f41350ff9ff71972b3cbcd80ffedaaefa997fe01d959bf24d01d32f5dd89dee29e377c60e2ffe48221c3b0bc88d749ac858a599253d0305bba90857bd617586fb668d73a0329c6c9c0174ded1f0b300bd44e55368304b48e55daf6f54ac4f8df4c79b3715f18a72bc3980f7b072e6c443390b9b482f6342b0f16c42bbf7be7e51b1c797c3c64545c32c427b47733380f0168d3384e81d8d6602c23b1a6f563a3da15213c844ed139790f9a04edd0833eb804a70d06c86d0dea1d10ca07943e32c427a43b3d980f08ec66756e1232afa69c0d03f58513b6faa5870d2d6d2062b494c786a722ff35ae552c9043dc5ba2930c2ab250f625f381113059f6e0a6b54016aad414b6340c37d9a7253ff0ac574866baa03c90346580f6c30de631b714b0ed24cfd5ee2dda6f04e3b1ecc5dd5118f21e25e634182a83e9aac913dda1d8a7929ecbc2f76d15c77ec12f84902f49e186b0435b584d97bc2d140cd426a17087e60c40852ce078149ed93a502e4b293ae68221733b24d7170a32109b520c1f45d80fe2e599c72cefc0a551f7264da2ddb5417df90ac1d8240b6bcf9b9a12ed8b1fc7d9ed9471e69821b7d23ff13fdfdffa079cf88eedfe9b510cbbf14fb7fd22e24914e6b9ffe95aa4d753a84b89316b371640ea3dd2e3f515bf7ad36456b35a7392e36b34e2a9dbd8152e3b8443305aa3a5a32e4a0dc32fb547cac06c67475d35f58f937ba5ca6f9b863aaa372876e52aa3e79df2dda54a8a5cb4434fad6be04a3ba9b6653a17c21c124e797c20b4f6108dd6633f2ba6a29ee32eba6961d0b6c6a2f15033035fe1333463b959a4df912dcb72d093a30df367df3195ae9cc40d628b68999199b7b106fc8572520be34d3c9512cb796b435f34decf3c85461bb5f53091efdf5327c8a754d05a27803f2f186415d36d69456d52c1801cdab8b1bd5c7d2afd5373ab3b00ae0532a1d5afe3869cde3d5afa9ea03af11544df598ce4ea43879b357d823e76a093cae292de7c746df39ce089292934163a41662c10662c7ed33fd0d10b6e33e5426574c309ec5f3dcfe39da92a229d580f44efba299d7374fb8dffed7ef0c4bf4d4bda6ca3499d420cba42ef33ba199a31e81befda9ce424a95b29bbfb2cee4e95f0c6240492990fb934aa524f46b5b44f83ed4795f27d9cb6f53bac97e2951ac3e3152be5f3868310f1da3dc42db22c80ce5b891749a2e33efc33555ce937e765123c8a370c37b8e94cf48474ab089868dd8a34e64c013cd331385f0de511f0ab3f30ef9e5669edbca142aca44f4ed5d52f20c962590078c5568a4f557b22c946591de699bbcd55ca04dd5705e656348ee3f18da14326cbc09d7c1ab28dcb949d4ccc9d0a6e241aa2274757aac9cc3f5e87752914d850411be520319c91199a7f7b25a6776e8ecbb2e604d19846f6fa5155d9848b55177662aa12cc5369a20cbf8b75235156817ecb8e2f844f8a8d461c843c5e743c141894a6a2ac857a0f39751cac08ae6c08281b998545789eae5e0c0f2de3309ded48e354d2d2e8df7336503a3d5ce0d07fd3ebc209d5c8e0441b9c4d7e6d5fa73f4f5a003c92662d54c570c9a52c6adf9b7f88b1410c0318724170529f9e021d6ae573ec5fa544ea722f04c2127ca54691c68b14a4f5a9e22404453910be252883ab7fac30c0ac04f4db447b2d5c8fe615cdb6a2ab9a090de038aaa7c71ff17ce974cb538ca3a350f26a5ed3f72fa60ba93ed1a17a7830953fd726e8047f54c463191475b8439e26622db976ececf8826c088a5bbb9f6276a558545c0821f70aac1a4ad700fafb66b7e03a3dfacffb511e1d6393aa8396dedf3019df4b4fc7fcaf6c291c167d982b354b0338bb18cc21fba99eec774d3a0383e39724ce1a1548c7fe147dac8ab6b3a4df353dcffd46755cc311570ba59c63a401ed62df81868a902223cd6284ebcbe671d1c818d94ace7122d378bf4e0e77530364fc5ce73efbe74ec7be9c375a9e5879625434c32ed20b80a4b9234f831c794d09ce3310a17756e3e52feeb27744b8938d906e171b9f011181bf058031f173f40ba9616f8f48d53e8f1b5840ec3331f5c43c4e5c1af8830a4fc0be158fe6028b96b98ee6add26b50e14f8ea511bc9be76f327794d3195c0158ca993d480212877c8472f403690584d3195367f851eb583b7c169d9f210a22e759168ad890f072bf3efe2d07a53da43b4bb8090622ac48231b501c1dc785b178a519ab6e0e7f26b1fc5f4b0357fad0b465fcefcfd96498aa98274101bb077892941f7098f6c25449c261b370c89f4909812ea93da2d865fe7e3c91d9bc1a78acae835d16742727ad1f62a73e957c38c612aa27258faae5f6ade31d3870b3b86ebbf618a67b6a428b41d116c4f4f0ae9478af4fc617a43a08e025772dae8a1cd7a627893309539b25b9d1a66f7fb5c4554927c2f514adb7e0553388d0cdb914314eeef13058285a9359d9ca4b773ea5358e25333913664fd32482b178530256ea51b22eb33aecaefeb2ff711794cbc9120ab866b374ed45d94ca886d70c1184c4579f31f8a37a09a7c0a9e33766591440ea38c944cd4b04c28adcb30fdf208772764fadba206410378fd6b3a838b00e51ba0593b92a8cb7708b7b23bf6c46dfd9d9af2c4d4b7b887d8c0c24c6579a985e94973d94c27a05aba849c21b6ef2544aad1ffa28b9775ded3a3380c9df416136f30d6123b30aa2f9ac500cf7992b3206f900c1caa4c5e4c345c9e8d4b490e0d86e69a9a6ce3d0706bab30d62edfc5885398570d971411f2543de85202bd1152d69bb3b12f50e57c4ea04bc18aa75d297cac70a648869b2a4f45296ac46d05e2fb41d502a42773c27f99d1532b1abc8ac96c3c3a77b914112192f107533cf5fbbbd80c3a5885b9feceafb1a959c9c6d09f6fa263cb335e49331bc383e3525ab931a6f72281d7a440774df59f55f637e2d07898a3f3ab84e15284c0ab85d712fa9d1ddc596ff35b4ac7ad587b18d0d4e32d3c2f568dfaf1d25d8ef72e839cc6362c929fb491aad7e351b74253585d19deaede503118dd387cd14832d5bdb6693245ae55c64917b1397b9af26b5067166629d8a44cf9549f5b868dce88b9f1291a954cb104243ca9832983adc6df0c19c2cc2e3047c5eb8f853ba8787dbb87f6ee877ebf3ec0edefd5c883461578355f1c6fafb6429a54fc51f28ce18d5460298b7e9aa4aea4d4a5493d75c268e730384853649e548d24a9bd9a3bedbc40820ac2f84a9e17cb137c53665e5a69748d889ccd0bb7717367317c4038f6e71b591a5ca4493dc7dbcd3a3ff5d701b87606f104c24e2609d7deeeed86bc33e768b912806fa5494db485cdc23293a6591c9a8757a0065e589b56121a457cfe9be9d6f4ad4eb604635c8c463b099eb2579f0b8319959910bf39167c0bfe0391a4ba330efe67622b5551e69d2c3903156752dcc553aa8fc7d4a3094172981af1b448a713fb2f41ebdc7aad29d591546aebeb7271d4f8b0658896496d014a0a056068f8ab671620288c367f95f2f4c1f00967738aad3a110269811ea261ae2945be3709b2a4eb737f4a594ff0750a53c16b4a158fa18b480642facdf4fd1c21d5619d0334ef8ee861fa4f89bbd28ececfb2555e07a2b5aca03d2443ada64f542c3e4729c1e49def8fe7566270a0d52911014ab1dcb3f3af47a92ffb73fdc69f0faf33fd885ccd422e01a8ce56e17371a428a5d72c385a77eb50483b36f2b1628d3b1bd1c511a8380fc41978085bccfb7a73f0a328a55522502376b57c3908d38cab14a51e2e9c92d559473bbf2bcbebef82e0d2bc768a520fdfb8ac8f37bfda18294addf5e2d89c1cc4e6dd8a920872e733e8894e17fe1948c5eecaaca88b59a18b59b1ab77578326d44583b27c1e941bc3619817148879263c54b18c5068d142d52a9174d4284af16561e9eb35b070e3f1c441987e882ca4ae2c7a3c12a5d2e4545f0ab5073e949ab400d5e5a1543f59b957a2b79b1e11abbaf6162314bb82c1ee8b4aa25ee6a194266af7060a97cc1e4a796a6b5615b5ae3e94229ef1743c479312045afad743d573835a8ff0bd1b8bba63d39d67d24822a19e4f42abf793daa809f98ac25624d4ff19fcca52723a5911626b4f2ae1ed7005dc106cb4d40c05bfa7630a225571e421525ff1037cdace5f27ec499d6df3ef17bb3b86836f6e521fc4fb3a4ce686245d3a5fce80af4f0e87ceb7c7b7fdd92f63597aa5a8ec51aa7f2bf14a5159c2e9ca3d5fa964ffd0d30575a5d657307d703b86a4ad9370d3ea8347b2fa75492b7506179ff5445a1b2cc70089dcca5fe8caf9fcf33e272300a1f1eff9ac9a518d67cd7163cc961b26d555c48bd748f560d1d3c4fe1ca1d1941a632a98fe4e770b20e3eec8978de336a9d85da628042282f2897ce38ebea6543b82c5b2eda06fc61ba39c096907cda9c230148b4aa96d53bc7cfa6450372775c302cf7e036312be241705b16e999da0c287153adf480b4a3153ae6d3d90de4fdfea847b064059ac31b2187bbe8cbe630ab9e9bd16ba804e4abb7f84f3ba11968ef7c2b2322bcc48f814d93f60055777aa02358df86a3473844bda6ec8463e51878c4b98eccdeed6d68e5d3156bbd2ab812792688e1cc89f9e1f9543461c7e3684ae824d5450c18c02b5940e58edcfe5c892e435c6ed8f472dae60a26e0d5c249182076baeb5c4785dd0af45a783d9b41ba0a4e41bc41877b761f74bcf0f3a7b018efca9a13072a7eaee13e996d3b9b78f4528e7aaa7e253007dbd078b9e35a0b0a0676ffb7b8561901e9beec7595cdcea044b23310fe4230624f8d741268519da41e1146e8e35b2625e1d63658604e94582eb2f405cd7a26b7a733aeb1308c2a1021dc80aee90c8dba1f7fd3024a9189c9501eeb20827aa2e9a30caffa8a49f3e1dafa041bd2adf10b14c052b47f83140a84aef130b0c0ffbbaf0b5ed37ea425a10046208b0dda658fff85879a99a4410e65f43afff640da304be9baa09930f320cad44834ca73a509a2951f549c9febb6898d504542ab231e3e74dfabb7782d7304c29cad6422d9ff9c6c8e1b3f7c231addfc22059c4ab4800be92724dfbfb18da9c2d484c5ba6a459067cf728fabeddff83b76b4b1f90bc39886d1717730e83bdf911433e51d340738c46e6f768e177a339c8919992c9cc95cdac85453e76280ca12bf40ec8f4208dd1b81b67513102a92bee3fdc3820af9f368e9dc19b540ff685ed82f3e36410613507ed1d8851d0125638b8d3ceda440e4000eee4848294bf9dce2650edd191517ba5471c5d6fd4bb577b76a67dbc68478506e8f91d6a0ec392f57d1c00e1cfa25ec3229f3ac0e0974e88ef0751d3dae96760afc21afcb79c69718389d99da0ca460224ed647eab8e9bed344a21f8d2e104050432f941e5694a27cb089032bc7a753f1dc7c2c715bdf9f9665d34540260ea1a51d40b0257434485bdde463fba0a083da95ed8a934e2eaa0fbc817e756608751dd1369e8bf2c32c4ecb0a2e3309736eb5a7b9e74dca0276997fc4bca10d61bbfabb4c1cce94b2f5375eaee6112f9212b3cbde4ead419cda5d16765170408c79af9b356589d9e28600edac46841690914b23aa92bdc9a4afb94f57574635eb126d008ce7090d509626a76d3e0f8d500a0833ec10f728f414e56a8aad3b96a514e4ff5a133c1429a69bdea44bcd8ea2109aa0028377c808b8e205975faf32c8512db165827fc6f3be27a0ebba86b5d90a9b0cca2bbd6b8f9712552f67d0255fb832374d1c9a0eeb0530fae0ca5447410331be80d84638d670d91d0677243ddff273a65c16a3e493c9aeae591e7d9e606ff945193d8cce1212c97a187d1209f29cd2e86ca72ebc090e00d78e8a4ecdc9b6e3576fe926a0e938cdca204443a7e1fe4ec3e3f765b8766f0c6fd7fecf08a74f299ea62cd2dcdd00a791131e6be169dd4e58dc76b31f2c540738354669fd673a0998e0b02a2825826938344b2d1fce07c0c12df39172e5865b9d43a5de331dfd0093ce9809d975869376e1baa27ecc8fc5c3c6bc1fe053d34739329ad6a22b796711f9f81f8b7ee1bb6474327f17c190edabbec5905c8f18abb0165e11b3a6d615eb8d4251acb3bca75a0aa16d01dffa388890d50228bb7d029a1f68bc12c684bf720f09e14eb4aef3259c903b998110211b9dc69ebfa4b967f6725054ee9b6afb606c871556213277730f7ef611c06b57fe40c3e0c62d4c2cb17621a6cb255795c1602d2217da94527a04b8dcacce1ef825b0fb8843f8e9d8374d169d096840ac0095c20587c2c0df4e73b00dd2ea166e044beab6d93d1eae6705fbb764a500ad1897489cd2ceb68e81491dd130fc9aac787dd9912ab17068f4a6e63576ace738d7f32dcbd47c50608e5846fba664111649968547452809ecc1bba376c7260b13ac247081a0d99689a218c34f6e98ecce8f5a7808a46e34169098b3872a569a4fae42e486d828e50900a3eb19249d45ae8c5ee3789bfda1b2b9c9609c88ec28c6db5578fe4b261214f373a4036dc7fe80061274192ea49c19cc07d246ea400c44515406d06a505e0e524d3d3baa9e0574e3abc3a44b56588ccf9c83c46534f84db9373293bc5ab38e5e5ee1995e22baf46f5a5714f378e83deda48aa0d528a30eb48f64109d8c88de4fd2737c04b89de02dbb5f5d27dd92179a24e935d40e65474e4d4640028ada2aab1476e15638bad0cb24330c1591c3f00e6c48b0d45c5efd231c9b6ef167bb87367ca8f4aa798958c9238390a548f8d3621182602c6d44a5d38e4ca9c822f27e2562b34042d170ecd70b65b8f3aebed2829fd833f6a1349b092abe57d9fd917ba9cb0ad5a262fd1e2b8a104456c4eb74b73293dfb35676c378456051fb332739d4930b4b3d6a5f130d7a626527cf10141ee3832cfcb44b91259d238101544414f56123add2caf0ec474694a8451fe497a7a38f28b0f4cb1767e35cc900c7b9803ca469351e9e9df3b8bd702df909e253450d3e97b370a9cde3ee1cd895e66a578d7e3340429b0b92db3262f4ee9bb9963722c1896aac58b0dcd42d99326179ae965c74970c78a2de735d614eb9d83eb95e384c409e9f351c6cfa6c3d9f515ccd509cfc935a5ef7aa2515a39bccce9c9450024842afc2530b0b9e96acc056935e5113ac2ee948a89c630e9b513b4a3e628706a9d3575780c4ec2f402c1fe60fffdda31ea36d97ed31a20a8def139affd4d157d9c04d86802b73c959f838e53127ee0d6ef90f9e0b55fbee2a16703af7fc4b115cc74bd7ea697e7a78d5d9c04cf33e3425e34a48f842b14675679c75603434ee1f066483ee14fa48b7b7a36251d277b14a82498bcd31dc3a95d95cd02f28ebc0ea7d11cc46a1c0ede9f3b94003f0ec2b7758fe2604e834159bf41a37ee071df20035210d073b4c7b2847d4e75fc18acd2318424d1f421784d8f8058fe2f27ff4a385fca89c999fb372e96699f87c50309936eb39abdcf827c934c07f5b997243a5251baa1f773b5667a1a65b77e0b485eb8991109cce4e42586664f4e4ef6fe3f18004c5dde5a81608172b957917c79cea61572c22e8785a23d90ac5a2c4c2d91959b92af1b77470e9012d9a3e86f0ec795637a9b67ccba37011a1f3f8ad37d81d976d6c99cb8d2076853949e3d7b3cf4ad9a6271c86e7aa7fd3b7b56257c24ef1ee5109d6f01871cd479821a046d0aa0572c98eed0c700490310ee508107020494f11405e0b749324570680a377c8f8909334b0c33b8a7c6c2eda90b054e64ccc875300a4d06b4bf30d49da85e825315829716dad0ffba0714ba5710d5ede360bc183eea4eb58a197a67e9a7aaa9e42d68825bb8fcb4d2f6f178fd64e19e891e154e9fe9cbce636306e3245131b3ec99dfb0406754fa69ac2db8960d42c3d4996fe5b18a026b138f973a7262c6f3bad3f626f60458728de55de9248aa1df143656c23a35a4e1ae9a82cbac5e11180a7a7747c31e55bb596a881246c7b6c7cb806791464fc5227984405ea10a625fb3505dcca08bce12f7454394eea78d924d952c68f6cfddac43683ad4b3fa80f7f25e0d175d3ab73448acd1d8fa3d720a1d5d8ff446b98d8d1ed3ff0d32fbbaebe2c6c7593246d84a9a2b1d1122ffad11d6912f15f9e1f1a01e7c4bed0398aae9910665d23eac8f101206e7c7ea3b14d15241053fe4b1fa36d8580351390305813dd2ced9abba1b5aa2519c63fc737604e703456e1d7363fcf8417759a28a4f801c671e0c9861411901fc5bdf874fcc1c09ae414e50ee63684937d42f8ff811c4b41f7ef000c51e3c433c1041b01c4cf7cf9c125f865b8fe09bb08c45f78b4d67d0d052ac5f83812b9375cedce1828076ae6138284af690151aa770b9524f5f911bbca1258fc43da8287752d3b960b0ab7aae538401b822412533ec0d2bb7ec30f07c2309f9f791b5ba0ed860e12219292d6ce9398d604e026849ebe85fb45a1b5c656672f87ca0b314a812d1d1dfa9bbbcbff3735bebfc046709477abcc3ee1b6ba7051f72abf04ef42cadf06aaf7683fa0d6503912b1769304758321b49db15464b0d197612943b90dc5240f098436b9dfbf8a34fbf2dd67630ced26220e909d7912864f088ed08906dd18d9a25fce3dcfbda38e797b6cf98d7cc1c280f7e9ded2ac0a3c6aae26e9156ba557ab440ed26a02ed6a7bb2a6f7b3b12b3c4849fd47b9a0a29fd5aef7a593294ec89c85a77982c99a2c7dd2ccfc659da53797da099e03de0bbb01a9c3f2cc774d859fa4efaa54a225bde754d88c5241bb4be59a2c47a94d1d5ac252853eaafd3831ca84c46b89aaa078f1e1263a4b892a13d7c0750a43255160f7963089c5b87588be14a428a7c8cdbef6f21d9128ada688686ff5ed87e041a94fb3a660a8b2388f29117b3ce0d50d4c059d4ab70a7bfac7b4ef6c158ec79a4a042c461965221172179a526230a82418fd9ed49f0c52f6241ce7223891c3dfd65aaa03e02465146eaf4ce8774582881f29d2f58f056a65b304dec470b90105697de9c39836140e2659590a5f4f4845f8bb7a442faff3eea33bbfceb12c3c45d4cc5163ab04a31f448b45d54e00d0bd9eb3a6f6d47b62ba5137a4606b33fd61679a05bc8ba52c2913509a804fe81a13eacae2cd5ab1949e8bf7c259b8e1ecdf085c61e0a5ddc2b54e9f6a21f536344f65e9837d3ca0e775232caca5ee9f94a6f7218e5e49d9438774301661fb6951860c1c51269dab218839fe61d50a99abfe3ef1127254442d54c39d948886bf7afe64c9ae6731dcbfd69a7fb4ea9f1eab0d17486ac7e6526920f9d881b704af96779000102382552ce03d11cec235dca672a2be96fa7ed126703402deaa17b66c7ed40771586f1a9a6c2408e60b51f2683e3b5b2b0769c0be6054bb2486e4a05d71d6d822faff9c007015780a76d07a4bfd0c440d93f041d021ed5774451f98b17b0f7f77019f9a6f3ce5f5ffc19301c07f2bbdb2eeef8553c076e331f5e2bcccb804e80dd7e9eedb96cd0aad58d1087e2b751c5aa7fd32531dc7fc3d5e4490c1c327094adb2e66ffd51d1c17c2e65c353518d5255ced46f282d8c9c8d3cd930594215f379c453a3905499f964c3dff90439bcf40f4fdd08d42e2fb2a12dbe4d6af074b40498c8cf396a5852468e61016901613cc307b284b7ac8ce7927ee68cdbd17f6ca82dcc33771399b0f922be2af6588d43979534e88d0fd556ab020f3ae218c228f8e8a059d0f99183e29ee41a70767a270e100ca642012c788d8f82c17e2200cc81190add47aa2efdbbf32c7727c15d2e3ed5128b1c3355dd38c5a3a1c8983845ab7ef12162d9f3fa6302b41b6cd331fd17a3e90940340e2cea70f35f7e0588aa0e56dc136a9dfc975b67223044ef39d26f7754c525d65e72d7aee133f77ff356061a05e705f705b42eba535a9caea0988a3ed8a6054d1d6573b39e2c4020e389ca0d57ff51354658c10a28cd85cea9089a5ff2af14327dbbde1ecc2f7ac74863f4c4190a23b4f2eb5352a85a7113d7eefad4c4cac8a3fa28770929c36eabfe71ea6fa60e1e41733f3bf086a51345c07961b0be4b8b79ddf760fa559fb80f3f3371d73f1798e1228ff5a9e5d929cceb408b11439a6f485048dc18a4b913efa2526e48d2aa9f1aacdba5f36bf731fcc1574f894aa59adfa42fdb9126d963305aeb3587dd5a2e0ae9e28ea02c31e937f4d9c2a889a18540880c0cc9d8ebbaba8cedd78ee183230e4ca33db2f1d569de82b335b226615f26d42d8b1082bd8913024dbb95abcca8ffcd6f454db7a51531c7a16540bba3dfd6ef1af3bb2c28fed35bfc9d7dc78f6483c3647dc906f1ded859c8b870277c99d04215696042a7f7511155183244e180815a152c55591784615e487a8ca89f6568c8c77024ae81bc4009bbe4eba6d98777994fe24ffec4c6cd5ca6de4eb37fd136fcc3d9dfd9f998f1fdc01ad085125299c0d263fab8fccc2707807961a103982b15a83658c898689e726f7b034d773fa09186e6f59a8767dc0248cf88f6cd1dfb4d7d56fb57872f2355dfa137a25bb13fdc76dbda451cc74a420e04f37ca245d262a016515ac1d68d6907b7239ffd5dc15e88800b7f8c62bb92feca063a28c9f3b0c303c4dcce63b604b070f810ea050ab861f1cc9e49ef8016967274947e16f28ebcb31ff696d6dfbd82b1dca463c80c9bc081195fc120065399ec15dca699e0e66281e84ebd068ebbe9bef938a1e1f93bb76eb833a5a65282dbaea1feeeada0033e809b85c0f3944bcb2e4bfd0a4c02b719604e8c03e4514c2ef977e43203b982f267612aac5f0d08e5477c9c296e0bef7c68591343eaaa0b17f918ccbc32186aa4ec0ddc6583c3cb243e22d5030b877ccc819b8c60c435543c5a2e773e79de5c7128c48a2b98c84d2c149e1a38f571635d2f201431be99c4c8914a4e94070a8894addde1a400aca0123a70b6d1c179d0eb7c70a5e73fb90a24c1123f169d2994515cd3bc5e9d2b4c4d870dcbf570041f8e315979798aac2b3a129ce2307aa3efb54f19a81d275c39b3e37b1a4cd67bde18c357afafbd9efc69083e205e6a18ec0a21458893e3fd7949d005bfcc56c63e7bb5cab5f9e87a10c33c95ffc31394805bbf841b764e6d24f54e12ca88e050f5203a9c049bd08dc54e2d0c4e29a7c58e0564cce6c8bde94afab70e1bcc262ebbcf9d0341b8c9a59673841c53756be52147b99b23b433454b4e5802091247a1cdb19ad62e780a587a51028fd1cad20610321d9faec269998319d240dd6360716af7e84807b094475e318032699f7784c68f717083bcb342b244881abb299931dd657bcacaa4d1cbdafd206dbe82f2f86ec69db91b5d720f6104e0657b01fb8ac67033d2ebc5b0ad980909a8d37fb163e94e8ab92e9df1b6c72021023aaa2211cd4723ba74cd88894308e7ab31cea97902306b2c9773921055993bb35fb40b51182e24b16f318a1bacba7a1eea80ca08bd0afb4dbf28179ac5726f25f4f2daf462cb8b9554e41e6800b7fda288d0f272422fe53a5394607cde130eefc3b5bc913fbedd8a19288d186055a14f27ce9e2806156eeec0192fec0b1cc4679ebb8413768363161618f68abfcf41c2a0cfb752d2cfd58832e3c4fabd736e45477b5c0ad7e0adfebe8ddd66970963985e2b70273db3345111d26d25c42fa96dd14f25a70ac6d841f0a8661d272bcb2e56842459708a9c8cf356eecded67dc834cb975a7d88bda9fdfcea92c082d8042899a0678ea3400be6f3e1cbb4f56b9343b8c10e8e08084c7aeee6b85edba7c979519c285b84fcb6178fdc447ce6977fdb02f6d74fd7b901b9486683f4a4cb942ebbcc8450aa1e8a3e13e5ba21fb55307867a16e55cd8e9048dfbb2b88295f0248248b7127d7054c9641106f66cd5b57c8119e65fbf21e5610b89c4198d43b7a333d919077e40d2eeff1c114ac4ef5024fa4b2f66f40eab0e25c29c325ca088c09a2ac37020c91ed2567a329c87aa89e2643dc1babc6c6288936e2e8a9d771ff2b32ec4c42f77ef5e56552f6cf42fa0f535afdc6d9bf5f9e988d5c33103d8fe01cfb72b75941f9ad03aa2b1bbe44d99b74e8020e3ede2e5595e9cf71c659150595694cf2302850de7b2dec7a388fac894b47afa3042c37ae889f3b96159694f3a26e118eb2e21d4a51d49a2d0d1acc2c66a9d021108040862c7dcb2703e6cb2fba336719035e6f77e4e6ee2713306e01f9f73d617289652751cbe96b5fda464e550d216b53cd56d6d281144732afeb065a8270eda0b5fc8b4314c7f10437b3da17146179b87281b48314105a4fed5a770b29a2fad0dc7339bfddae207c7d0127f7bda984580b2fbd85fa52a0934cb38e756ac59978d555871b203d2b615943af30d2fee7ad1cec85439fb463f7d77a92912f635443d1df5d5bab30a68903fe59901231ef3ff52e8b8664a0ac54f7cef7e824caa84e894358e1fa279568fdaadc96fda92c3b3a665252896a0775b533b2c8b3ccff1271db6382c5edb779bdf6d65e224090d7c82015481762083374f78d3c28be07d79144a2f2da238f78ce4cbd4b83ddcd2606cda8023a1698d3b67941392429a788288b454c930289a2a3d19478743164b5556164e742b59e3eed66f8349a8e106d3471867a2a09d93639eccdd06c6846e0364c56d900b8eb245b942b70d766c641f0ff419e38bb26982cf426340f5a55bea213fd2b7c01daed804971b4351d8f677f1d8268385e161c776f3ef74f03f80f3fb44ab9dc64b6350644ffe30971e1b72b03b1fae444df8f253f3466cea37537ecafafdeb7dadec3af379c0aef8d6184420599a91155cc2fd122f5ebda7606b920016ca0e577113da5cf15918bcd00d86be13d37d47938edbdcc0d29c03b9485eb1a6f354c11f7b1c59b2bbd7313e330cdaf7f9b580709b7e17bea2d03c01c63d21e3bbb293471a9736e0985697b494b27eda08f1262a10436f5a1d431bc24d74194e31efaaa171adca49fcf184b19cf1b07d73404d4688763ebabbc7ec492716a487ec286a6def090e05c43a4ce20e15604e82def29daef9dda04587e4f11becbf06562d7ecc2cd784c05afdb6ea61d6bd9f3ed4476bcb0e12f7e37f15d92491f57aab6dc1236101219bcfd11100dfd5b4a0cdca418b1c4e820c86f3f0525cc63a6c97309e8cc5fda5dd9d2b87575e841a6a6ece34078561d76944b7ebd322deeff1e42fe382609494c6b04eafb16cbd29e6db3843254b6327af4ff5b6c08cd8b04f78bd31b53395091a6832e90d64547918a6ef4714ef96e47801a33b3735eed60e23da5c077c91d8c526313c2c368080f76520e10d1ea1b7942b81de8fd49fe89a37b36fcbe0fd6a1090e7a911ab87812a8bb843e7132c017d4e024b738701e9b47224d9c907397d1c01a7be9715822a6e1ebb366084885f7b5387a4619bd36fae8bc3f4ec96e8a231cf2b14ca152c30095f70c33c8bc284aa42eee302251f54b6e8af11293b2529f4786deb686a684d3658e5f37547455aa5f47d87a8c5a316e872cbc8fa4f4ddbd0f9a06a551184f7a7c963f29cd602145fdd06f6320db63f3ea35f6ba7ae343a8ad37549bee0372e02af0c7a2b19eba80d895d8292589104c3038cf8d5a41e99fa0fc22e34fe4446fecd81d149191bd985ca3e093ed285ba1853cf2056c1a71074feade89f1328ecf6370a22dd1ee610b3ec4aeb0ee7a0742dc0bc1a90f7160825d6652bd41963896863ee7f01d8e49c1585b1f5751983081505a86571c8d446a4c1774e6dbe27fff10cd64eaf9cc7e7ad8c5c18ba95b555fce64e495666acd04d7e8d1189912c5247c8a80e1a2bf0915301ec79fb8aa696d0221dfd3b391e372a261f8f51535256464164ebe09ad83f5a61979c87d7500a38e03fe0f3aae20c0764f181b5cf87f45ef22fd724561a41d0c5264bb9da2f2b7ec69a3b089055556772509cfe8e6b0555b58199136c71ec8374a016d762c4a4db565f7a6219a96482f08bdde3bf48fd2d24df96de0f2135ec18cc32b4918a190cfaefff1b6410d38a7f5c3ca96a94320a77892c234654ed07046194bb946382052f20fe1f4a409a5eac48d1a29aef92cd9b536e191c7dc1511ac0fbcd65d79e9f724c81043a8c22f3fccf13ad6791d6be36352c6e799ec4d8b2eb696a0bc67b43374a64af642a20ce7a4058e1c2e6aef695d9b6d27b1b6ed3c9a1e77809f901250827be13e3cf37e83e57ba5f02843ca0e6d8846124dd309fd43dde8fd82c01220b75a744972216930fd20ebb11d2b06c4b33d9584bf6b0c2d58c02daf0729f5b024ab8a77b70dd59c7f58e35faa0a8f7aa901450cc0b19e1252b164c0a28c26d4aedf94d7930c8e5b14737f5aa4a11a3040de862a4f20e6263e07ead2ee06dfd40eea0fabdfa9fc32bd7d01739a0673e12ccf7ed29de9af256d7e7f1924db1858cd22c68ab408b402164f48474cb6f39201b4a5e90511a0596e8822710c838f030d13634458ce0a089b8d612a70c47a858d1a2b500ba14f83182f62b50b020c15dfccae5630c315c336c4e5a937d714b60e30fd9a536ec8f6a6e92f4104d7392c5477d698efc5094e1436641198cb02bdf1590516a504685f7e3de73b0cf2f7a385c638b16b7ac413e797d1628de95ff3ec4d667e405597707c4ca69e8a53ba3d6a08827d155a6d7d6d8225332687fe82923784e8eea59466f43db9382f5c24afcf6b07c6bfc0ee2a453441ef3b10ed625d104ac9688f435a45415f14b9287980de72b5cef83978e4929ac23ef6fdd6f088e18db2108b83bd4ede864100ecabe985161774fdd1679d63a70909b7b6f6391a53b53e6b273611d51ff2c0f6923911424a58b37749ebbab72f7d9810ce6c77ff41605b084d617a5d5fd444d9b966ce3d7b1b1ea358aa12c3fce09ee20c528f2081b2b035b7967636c9515b1cf6f3164f4c4169a66c57dff184d03e6cc311fc71b248e9eec1815a181f615a0847bc6a1cde22b5e08ce6a139c4ead581ffd460e0b585aa7ff125055a314056c95b3df62f8e0ee3a6fb46322c1c01f74b94077e55483bbcf4a30b4d0577639d296778a3319b1255ed05f2395a5932a9993253390a92fc14c0b5269759e098f73af9a770b5ea1696f2a12cb3820870958c66e8d37f7a4fc05c73e1238230cd79ecc8b8f10a5a83133faa49aba4e4943025db033cfcbb5768e4153fe4d5e3f9a046ae8baeda6c161ea2d0444c1894ee6667591d8019596df292a04b2b8a7e8180c1fd993ecbe97290e3572b1fe868ec1d80a1235ffb861d229a5bf06d9efad424ab4d76d6616a7fd18b023901cab040f0769294018bcfb7526f0733d644f921ba0672e870f47695892d314fbe14245be1e0b52927f08e22d5490dae16e1aac2a76092881ae5e1610e5f098ab4b6b370d7d1700123ffe7e001bb6f8dddb7c95708f542441473662dc10f7c6bb00f7a314734a43ce4c2970285c87a894d40ef79739ab002d5f3a9b0237f613d30a36125667b86734e269cee11c815a3162d67b32b2c9ffc1d7a406e1f3dea4ed49344a7f48b6a08d15aceeca747ff799670a670ae96afc2fce772e15d46a96272324b1671d8bf91b86258df8c6aeb51e0545edc576de46283872e61c7e2aee9a71d393857065193f33a95accc5a25a5171541b98e64481f63e6c79fa08a0f5cf96f7abaaae7354c4ec115667d4c4a6e8e874ee15399cbf8e621ac79a930b36ee818dea35ab8142a1c8c907abbcd733cb85eaeed8eec152f9acc6ac108ea179a627e665b8aafff828dd2beb63f442b70260d6762b9023ff3f0a25f4145b8fd020cd2739a55603b5324b37d5c169e049d56ab0d2775d1e662bef8c1df5ab698b81df54cb2f2e3f4f8c1e00e388703d240d10d7df6c9db77a480458bff23cb6a299bbf4fdf4d5fbbdfa5eb61e695f7defbd1dffea93cc5f58515ef18b82e909201bc343209b36d7ebd1146fa346bfd7debeab45737ab31f5cd25402574d15e73efa57ef278872b38b41ef6f3354d04e531964d45330721b06da74fed55efcabe6fb7363421086b37c7e40eba6e57636a920ad2f170d10b3ec3f490993942a23f80938932e2f0b790436c28df0c9e4e509e3dc3d1569a76ed6b6e7bdcfcfc89c2c3cc92eabbd65dd462c9445aff7498c19bb62b82a87dbe42f549571639713a08839660bc0b87c2ad965b7c06320c925f0bba3e60186a96a8cdd94ee84a7c21edc36ca3ea646423a427a83b69163518fb0ec8ac1e832661b3eba82f80ce2be5cf9bb98958766f7b99db1c40c219a98adae5132fa2e2c6de9ef7159a33867df4beaafe8b151813e1146c4066d3b47602ca48049252b9799216d5adf2c92619f238b6ea3bedf6fa277806e18f286c6df4250cedb81c7a5c1945d34423cd3929845fa48dcaba4de373cc090eb723892d86b278711f15bd74a45ff868c2676812473e6413a848a6ef671b6589d78d4557d26b30d5172f5235b31b197a04cc98e43913aaba891ea4cdaeceaa679e08328cd47e6bfd0fe6e3523dc77a0f46ea5ce99aafed9a5303e43ce0b8cf7020b7b508bb97a01107aa96752eb8e9827bf6f7760c04dde9d255288f3f1957bd9ddbec10fc01defbe2ee76496011f8892fb63504f2edd70e17449b6ea896a4a9fa20d470c49649d43fcc807877bd57d816d3e6040e2116606b9008f090443b411ef2640e8d80c867df2bdc4089ba31780590304d4a3def7b76bbec1d8d524711326ea18395b302c091273ca7aadfa435b7db386fbac1be45ca7f4561b9412ec12d9d1c2dc1fcfd570568a18f3f0cfa2a6c208c2732d0eab27c4af1681fed66ec8e41158c1bc3b62b3feab9c1612994ad0dbf49ac2df92eee856734756f6f555a7134a7fb384f884996a5aaadbbf818af3687d7c689014db131280933632779ba9beb5c575613a10e01f46e5f83e28142402b57e0f68a340e062f6dbc533ae6ccd5587078e416f9c4d163ad0d3686cb8fd3f345beea5e8bc9cebc95ecd551ad964abfd57697f1848244a289405240171513cb61d01f8f0070f6f4d4f2749aa11b640345f4a75dc54741be1240fdb13da1ae3c4bed9467c1fc48fcf74e1b5b639219ca9cc07e1ad9acc2b8793f9ca87370103018d04b9cf2a07b3bff828fa7783193634b46680d50c4d3887f4297b7443eb04e61bc76629a58a9a90fc9a7a16324ae3cafb7607d324477334a5f7439460dbfd831254fd55e3d7b7721ba46c09c1881a4ef46e06bf5f45ab09524c2cfc0b968c958b9ae8c4213a84578cfc11c9a8c17efbc27fc397ab1290eb5ac78d85b1cb9c15092feca45268c8724237620298d59853a698c233bfe874aaf31d41222cf37c257b175198084016109040d9744d97075d8b315548546ca2b103dd71554d95aac31c958c834fe27e210fb7a8c8cdd814b28b6390a55dd2ce64906efe41531586194daa1e38fcf8d58085efc8ba65645c9847cfd8616ca7c71afc2a9dcb02cf75c5176afca8da34478b7b43530c35d81567ea476fafdafbaf0f745a6047e4c03d028b24da1bc2635ff6d77c6c44c3024b7ede834761acda1ee1bfb017978856f4cc42349ebb0cb491672610cd26e177bab4ffad966ed44bcedce25979dd3e56df20eac31f3f10c4c796631a45f5871f5699fd0156f4eb4d20f2fd539fb24ff286534fe4f5de70c6596a2059dc8d5569110310f93ca8ad3944d6684a4e57fec1285667a580744472a03dc0d1fa76d2b858853e8c864920eae6ce48072914dbde088a3a60115c114ac6cdd9c9c9d9d337b1ea68f0b15b8054fdd21ec345943990a95a5535a9485035001634f01ccd1eabd9fbc564cab4292c372ed2314961ace783f65462e490bf28395d80090b8993db73a0f88e6f21aa5fecda02706b208209460f0219911ef847e2c800341af62684782fe5402d5aee078644f8e41e866e6b45abdbdd52df34ef903a98008bdccca8c8fcfc79bc4cfcb45aa15e74d220e8fc6e512493be095b67335c707d5cdcfd84f88f0499fd0aff8c3799b2e1b9b3f30c259411143b2112b4d2c59d08ba9c9e9e9f3ab7ccc09a22f7111e872b035a7399e66d6550906b73ea7924bdc0b1f86b37f5eaaefa10594014f17eaf29a1fb686aaf2173b4760d05f3a69a47306398ff6b30678eb949024a91e14ccf734cfbfb5a141c220e85640949d8deec737e7f5ef58a57bc6bf44f0db5cd75d3b852b1d963e25b0b732cc6df1ae387631cb722964531c743b4d84229e67a7133a9539c947748ca19be2b40a86e9f454ef53183ae61bedafd42b160fbf0faeb36979bc4f5b9118c8bec1da8b03061144a6e089cfe747012ff36c1b118c235d6660bd3b14d2d8c0317c1c496d34b69bc06f568b6bc4f3c7d620074749d67a6c54c4731b95c4b04bcfcd64499616f6abd751b38c41b2b8ecaa88f0bec6ac5499034dcffb46a61552fef3e2674001a67d12f3ba5e7fc61979d8749fa61787cf571b210da0bb653ecb4582a68d2dfbbb29713c7a55d3a0ff7b0966e7c23b7d2cf45de9d09ba8e414be38c840c462284aac69eb3093d6758734b6761821d7631406100c3c38785746fc7931964004329836987756d4931fee6ac90613d1cf39255c9a24ad75955fd164f7c08b28417c49f5c8340a33410c1af19fd622de1523b8842b0d9e3b7fbc11629d8e9c832d51697b6cf878d0decc78f8e2927a644b384e5520363fce660fac92dfe9d53ad7646a4573b9d5d20d3d3cd7dfd7ee7f6a830bf8f0fec94fed110521ed2d15c612a1e1c3ef40c078709c7c3c88dd1eb8a6569f6b136aaf5db7c54746d3b74e4766e10887463343261bb38444ec814edbf9d0e6cda9f73cf438e54843ce17f9030ab3483ffb2ca500a1fc78f4d67430a52f6f06ccd0725f7ca97c79140aa2682440f5bf8635ead482665ea2cf0805048d5d528a8f0da3309c993f1431090b6f0cf29bc54ea73e1143eaa44b06d9b42f479a4ea3da168a2d0e0dd2daab03219aebbd28053c6e140bc54eaca268e583b7ae53e8b0231748ab960d915307e228a3891ab49086eb2c177fe7150cf2c803d72e1190df013cc4f40cb8c4dfed0b10a8f8d067df10a7c5da4b1099f717725884ff79ec686a9845a9fbea3452a53c47a5a55f498f6b154430668a74a57f193d6c1bbbed4451c6bf93e242428817b8ec8afb654b94119de49abfac885e4b40e38e53af27e1361e2f3c407038f9fd100bac873dd33a7e1bbb7f1e6e13afbcc51edaa42781fc028e26998b9a8bfefe5cab4c884429d67027ea1072292f343cb139d8b65830c77002a3ea8961daf350f5de09cce82774c496ae1952f46157007ca691403078ace5516845df6b7da3033782f2190f56dc7201578ae0c55e1c5b8103792d2bb8ab1176e1983ee0247d85c846d47c0e0d750752629af65b72932f0b2b46f807b4bcd7b6b9f688e05678b4ca44225d3bba4a98e8b42bc2a814a4bf46be62fa397db3fe844a90af0a75e643d68606d82591bd246b301118fc003d26fa55b162ada0b5a15292d71d81f8697352dd534ec6fea340378c039722b9c6006077b86b403b6b3a3c599a692e9eb021e1d9f7850ac7605d8efe21a1961389d1c1d16a2ec9831ea5e19061e706c215736fb8ac931b11a65bf26a9acba0db26d02386bee3ea0c7d15833370561ead026cb1c6929767f2284c6091b002434561542177bdb48be1c676f066af4c7aee638ef9626fa256bd667d6caba5f69c5c7424d47ce8fbd4ef8a5b851dc5a0902a05df43aa09d71d6b46790e1cfa7594dc5742f1503769c672341d965cc83d084f9a39094cf01da387a9d2db2dc183dfb70d4a55212e68c9b4801a86c3349380a04515186e11658799a5561aca36c01e4fa00b8dbd47e77ce47d03f3938e2c088228ab666e9357229f925ebfad97b94ce4f162107b3ac08fd7f4f615175f936ad08fe8f93b44d640f024a1c589dabdf8bebbefe46c0e3193d9150e1f3cf3a2fd7a06cacbbdfbff910cecdb891065d34eaaa715f45977461bd51c53f84770787954cee5e8b9fd7b2f632c8a75220407b75ec71f3691725eaa48bcac654a28a3213ea4b992f47a6529f8d98eaa1e9116b3fa858605f8c8b8cb970c37588b905d444c6c3820568d499c2606ff4847de1f6055cc3ca91fccb0a73c3dccf1ffb4a8161eea70fdd0a02c1d84f1ffb6a2dbcfeb8c9076ed154ecba79158a0744195e42e8f80a9dced986baecdb5c7439d8865f8408a57dbdf4decbe47985384e89c200977ea3473dbcdd83600fc83de97faec4ea67cd8aff80cfb2c86dd081e2d57d0105514c1f70d0eb0d7ecedc2b5d4b00c305ac0c066a999c9d26e2d8667e9fbb8a54e47971618abb58f7b32e26d87b2cf89b8b7399c88501a1d32a1c364ec7134fba0dcc99e507f51f27b66ee710fa9ddd4198ace80da929fd7469b9ae951cd9594baf1899f23abd8ab8edba1b2a9d4c3262516a3670ca2afc62e8989df86100f79416ebc44000133ef7f1a44ab07dc8c17b09cb243235c180cee30fb124b11b1d17762d1a59fbf7c860feb3575f2829db3aebd90be16cc5f4012a2d75017270d33e8024a4d6d36207b7304d3b3835f29ee497ffb5c994692ab9fc22116e987ea704291e30493d3c662b506cab3cd6787c86d19fca2bc02d1a14565f85641f4d9404e343e35ee416749e90c18b69a689a82528fcd45598bed1ac56edf9efdfda8b36d0e50b54e3070363ac16b770f70647f343944caef8b4de234ad86b1631162aab1f2ef54418ae2ac3314618993a2937538e5c538efca61c29a71c69a71c594f39d24f39f2a0a2f1f05252fc39c198c2e11fea5cc04cee2c511349d71167c5c243ee17f85ef870cc15c5f2abcda103958ecaa59deb549d3c26d168908b354081603a519843a595e6ceab1bb73286340f860f11be55b7457b965b1c56d2b24337d7b2bcdcb6b3d212097d336c14584776fb8a1b7d2c664e8daf78d3fa488fabe79e1a1fdfdf30f03629bb580c498b5bd1f1c7664a9e603527912fb8443fc433b85d0c2ecea1fc81c356fd6dc72e7bf67bfa4f87c4582b3787bf6ae6ea85d7b57a44a0b12dbf3674b6c2d7f2e7f14e7f24a83f4db1e60be9a74e9c0215369a31c36d5292c06950960421794914a1f6e5f505731b177193b3da1866469f4f874b80b19c99ba8d1f4c748a877138c75fe24316bb4e37b756c5a04003d50bb9b6ea8eb7e2f02fcaddf8a555288c5abf79117954c6808009ad84b5fe4a79ec0b220e97610b8341a5a937380ff375a4b225a7311ef53587a8e95b2ec821c4b0c1f04dfda6ef82002ba0bc15a0ca9ba1cff170ba44258169834a231db0a4e4f2f1c0d604882a7992437b01034bf5ac456db10146ae0568d9437ead7067ad06f7c40e0427324cf1ef40f20fd3dcf8ce217c616ee26eb0fa5a6e7f6a201f941b3933841ec94d9c2bd91fe466bf250d36777c382d10d452fe655150d9e4409d1538007c7abfe7d5c8ecacc36024e4669c82f2b2a29049b6f42e18ac3904e78392b390d34e94688692ac605162a57cb3f0faa1725ece13709fbbe0d1b301efa3f0e15ce638f2268b7847b255a4bc04024c4075a090bd0dff854268b6d694a5720335c451db955552457562ab51abe9ffd17bec9c2bbcce5a805a63cf60f19502634ff715484f2e89a299a0ccff42746251540e4713219b6816a01661a0174cd39425cc388acb083b7330e5053951591d37a56d844c2ba68f2d4a3ceebcb6404c9898b59d60c751f9802af8e6955253e832db07e19ec6dd3554bf95b398c3bb86cab24d971554da48b6a02cdf56a74ae365d238c9a828601287f2ec5be6f6edf5619277c6d7e9d62c954715851eb895d972d1d67a116a822a0b0d12f2f32e07ceb24546f92a223542af85a0f550b5054bc53e85e694d1c17aa949b38270b369a49983a5544152846bf55a6974b9b2d46af16ec600b2e99f7bb3caebccab012f66a45740c645f92be745fd57c7e769e1ec2166c9071ff3ebe6404b75928f48be91c2f105dbe5d42acbcc321d2ada6d9c9ebcfbe3aae659d3eee524241fd275b52b316ab2562254c2b5d27aad9cc11c2a0f9bb5f45707e9253077b42319cc278752850c965c7f67d7bf2fb462d6e720d9ef0612c65be9805ef5fe2a2acf5f27cb3ad4f51c16cde2a1f8a5f1f47636b09e03a4a280b2f5a3c3d9b5625e7a03060c4bf43d874a66cf1e3149de230ee6e46334b37af565ad2a340e5889e64132071a7fe3188d22a0c4df2433fffc20c0ce769f7684de3159694d075a4a399ab34de86f3ac897878f34fbe0124c01e6d0d37066b6082ed6478f73165933eb2ee347a7d867c8ef66ddcf6866067ec76eef77131c799d66af66cfcf6d343f24e33ad57400967fafb0bddb318f02df69ea282ba9f7f04cec6ff9fd65ebfb6ca580bd9edefbea81d00c5701bdf5e2339b98384c65252a5d9728bb9da9e463cd48360645c6255b5d00bdd6e22665ca36b7ce9c798b4009f14fd733a5830162a2e6bda1920f984eda10e6a7c831f93264654da2fda189ac956073ce3cbd6927339989831a44721c32f23145593a997382b34ddd34e6480b49a4390d8faaa03f7598a27cb70242d35f23700cf9f64cd21e1073c1c6749162ade1e95614ee79ff57b1f9c20b6471f21927165973bb882a89515067ab5b6b14527407adffdc2e657cace7acda646a90cea8b3b29118586675910c0aa7af9419c4d7027ddfce5c9fc3bc220510d5b2dbba7cebbcf672239a17244794f8055cd6b732b15a00f461bcccf907bc5497323ad8e5af0ee3530c75aebd90e13923dbe91783e8829cf61490e8492f60f4ff020ca4ca821ebcc5e6df7fe6f3641226044db7789a49c0056555771a0f1d547f7e3a235424ad673a01d102dca0efdc56877b16375201747dcf16e8f77f50fdf6c73458d57e4193d021317fd0048c3b483819ba0069072942c5e76bfad00c5d83923a41353e7413a4acf52223536b7fc0bd6effb130754c351c2ccf29d69bc29a3efe82f5a07c1e25d4fd82a464b69de83be4c9eac8971c6ab6c90c1ef2018cd8bf24a298caa646fc930a7a3559e5107d49f40b037a2f6a725f505655510788c0cc32457c03f30ef9a192dbeee0fd00cf2f7bea7dc8ed4e10b86facbc5efb13adb708302914c467cf6d42391840c86456e81e4f346d13c6aa0881f5498061ad4a0eb43d1f91ad88cf6b6e19a0ed5ab2e5de7b4b29a5945206c1066f07d90629a440e102ea191a4e6f3b3d200eca3363b381193c42fe683d3384300cf1877885abb3340b150b8baa25d3321ab5b4b4b4b4ac624eb0a081a9e1d435436bd5f0e90ab712c2306412124d2ab21f8c599cd4ccac70759609499ab464ca9595b22ccbd2444c0a86261cbdf7de7befbdf7deb3e0342704e2a0339168340a9934648b40151d2aef7d9f87ad569172db5981422551cb164bc5a8473be2711462827167e919cebf7e4b66348ea3d168343ac5a0c0d0ccbcec2384889860cc8285cc07027ddff77da698119893991a9789090b9affffff1fc16c88b078cd82a46666858b5552a244494bc4f34444444444483125163430a5514d34b18934d3a426fbc1781cd164c6919ccee73cf14263b1196d9684153b373dd3c2f940a0effbbecf746364860109f0946638b5298138288cc23e2d912d2222222242daa19443136516a08006ecbc60021ff0c2630c40f3145a342fdc0517347cba664242be04ac19f530fa150eb24485cb63152e5f02d6a4f8cf44cfac7075d6a725030a43100804028562443ff34203b36fb8e58dbc9137f246dec81b79a45a4be3d96c87239428e9992ee37d9fe7799eb763c02fcd5ae3480e11985547b4931625fdc19e0eeca9600f37efc946827802e208eff3997fd133e33ec2a9e4c3bdcbe314281ebb8cb392284eac5a585226564a520585721af99f9894908c98c412492424148286e8b5347bd9186e8d55ad31e6ba0af505ec5a6beddd45d47d841cd86badb577ffd8b79a71bd95f6150e4037a4d16aa72fbba3db1cefdb36d8b7334c56854d19fc76bc36c833884eb950dce34bfc6f7cbd37bec897a6b5f457857da01f9dfe0bdba0d3cf8e4eff956df8603e738ad0e186c3ce0d3a36d82c8d1a05dd7a10daa9e25ed435cdb23e33cc923e8d9a0db61b7470d8b13adc3afde414d129fdfad944c03a7dabca5fc11a4e67fba15ec237a7ccdd41692b6675822c5ffc3eb5b6c390a9dda133e672ce39e79c319773ce39e78c65a073ce39632ee79c319773ce98d31db059671a7bf3845c4e2fadd5be76c716bf0db90f78c0031ae080a7ff4285b90358f588378ed33c5c0fb7c32ac385a96048bf8f7b2a09a447786b8555986a5365983055045c892872b50b09c32e566f6c3cb006b43d0e04b9ed550413e6e6ab61c179b7ad74ef3dbbcf773be7d1d8ee66ca4381f45c0edf8b6d487f1bb5e9d96c96aa64a5345629e80271453f73df5951efb0c2d87092a10e617bf3076a0c7ea2504486e3ace4078e2cc0a7171cbda75ece23306770c467e40071d7fd4bf4bafddd83dd783fda69ec97bdcf5eceaf3fe7a7a9f7d2b860a183b47539ec9a82106c2f581372fbf5d329f379f0f5739605fab0fdbcd77fbbe7fe7ec737d0bdde710bf46f73cc71b7837807bee0fafe0e8441fbe7f5a7036bbcae77fc027d73db41dc035f70ddab1fddb37f0f7e9f2ef7db71a3c5302e676b056ed7335a5fae8315eb7cf3cab8985e40f73939fb18dbba0364adb534501bf6edde3a7339e79c73e6d4c5716d2d76519a838b2ffe59de5a0f80efbdf7ea7b35be19df7bafbe57df8cefbd57dfab6fc6f7deabefd5dc7bd6c3e00beeafc638c776c2760215b1c977529e8b82f055ffbe40efc4385f8c330dcfe5ccf589625d40a9c5737a60d348eccf4ec242a7bdbaf8cc94b2e0d64ebbb51df8542a586badbdf6627badc5af3bcef85e7c3f097c521b729cb574ceb9adbdb6de12c8b80fe5810bc9157783b643abc68a0692cef824442021111c6d01ad0fa794524a29a5d3d5008e0b4351fc27c9958ce3c250467728a5edd068e6442204dfce4e0c74f0020dfba1d55aad48f2bfc2e8672d0c0683619a43b7048059580bbaa53b3b27fad5a10874db55cc4dd5e530305a990e683a7f62e77d15c0f8da1a84f83fdd594d53f5575d495e8cdb02b8f7d10699385fd5bdf7662fdf979b33c6f7ee7f85f7de9b31bef7e68cf1fb60e28aadcd16dfba29ce37e36b6f88715f6250ce56cbf11c97bbd65aee6770f7bb6aa7cbe28b317773a637f6d697ea1984d6de6a036a436d30a59ff35b3b27cfd3e69c337f71d4a6c2e4a7f9290d93e23c905a633d42b09c8d8d8d4d9e23ecfac8f81f675cf76585b6b43963ec753bdbad23cce3e4b87971ce77658500ba20fbd5cff4f3884bb5b0feecb656f045fd5bc94ba90abe4cb1e5ba720bd46badc5385ba05e1dd43def5d91bf420a7736c329a45067530cf3bddca6691a66c61973b09bf17314e7eed64efbe7d5b7b7f33a7b29c7536f29bd5a7757db9d19849bcb2164f8596baddd19d39cca9a1a810429d0ef7717c0186baabdcc71fa075ae7bc95d2db37a7cccd19d75b290c2a8d29ad3d251586629a27002cb699c3586bbb8708a9c6f9666db1d5946b31fbfea93f7398dbf7eb283786bcc22972215663fd24a095561c6b23c2aec5612e9ec2c770157e85a31e85ab7ce72b3c0d57f12527637e26a6c65aad48f2bfb602a922d6c49a58136b624dac8935b1a6420a2a525028a71494934c2ba635b69e9ffc490993129211d38846228338cd62a0a13284ca0f72074ca51ea0c56cdc50c43c86c12cfc8253f8045e6112a3b00ac618ab300b5e69295b294c68ad5b1ac589158952c92e295c5c5cc02c4bc966376eb27dc32c9897d40905e544cb494949494949218d6629683d5492ba5c54312ad9ec26e321a7a3cd662e38a31b998eee3655a29de7fcffffc77f6d22526095c96432994c26d90d47a66aed5b4a3693c978c8e968b399acd562a26363959494aa54cb38a788e796eaf04b4abb8ca858421292300cc3b064c5440a971b32598741ad9668b3650d07077403f1107133994c2693c9749389786eaa528748eb754be45f1d6ca433da19e58c66a56ff190d3d16633d94b299bc96432964dc765a4e3e6fb7cbeeffbbe10d98d146118866118ce643933958b2a140a85422111ce6c07967104475696e58a4be94649e652d2a2f218f5f85b54be04ac21ff3361c1bca4b40ba862f980409fcfe7f371295398c0aa300cc3300c67b29c994a26bb219b9546b3d10e556744f6a9a8fc6fdaa6ed37b10259aac4c9894b2577f8dd63770ad94c36c371b9212b7949e632966edc90a9902815540aca69e47f52c28464c42492444246a25008ead1ebab2493c94ed41a22ecee3ffc213ff86aaedbe0eca050f89f497e3ef633ce4adaaf03b7f5bceebf5a4331c4da4f482f0f30a521b695c692086995000f8d5532890ae321eb6be98e12f6d168586ba3f91706820a4d046da937cb72f178c5e3fef8e78479f91706e2c5bf70edc4cf60189c02bb601446c12958f36018e019e66e80391a5ee1155c62ae865bb08c7c8ce2b1ca63171ebb1ec378dcc26317744c134155887cd096fa34e3abd6d73c9625ba59184cd6a805736659a3514e256f3061463a265967c6176b0533be5624f92f8aa2db88ab916e3e14afc11aed229f036b60f002bc8b1be057b80adf0227c0aff80adfc253f897183154e070f1df0a2aa410c300052080a7c2fb46463a17b77b1e5863310a5e674bcaabf03bc99477f17096290f838bb34cf916f8cf1329dc2c5338033ef0c577d47f796f5000756b1004b9cfe7d3814020cf166aab43b0c6dafa097e8a4d55f899c46ed096588a490b4c707274a0f8176bf522df847413ca99e1dcb89199c44adc38796b123bf994d1e4868a4e8df62de05cc79833fea3f827c7d7eaff84e2a392a2aed2d383300c1db16fec6a4592ffa21886372c784e0047ae1ce4c3e033facab7c067e428352f7f83352b3a3a3e2ab9b3e2e2036b4a22f6ad923afa4bfd10b0860422c2c31302d21e119170bf70120817221f3c3191530d5ba8329e624d08c54a374060f000bcab050e805f71996fe1adb71cc70006f02f382b56830c2763244c444444444444a49462438cdd04809f6400e0271c53c9328d942adfc81432220283531c998ce6cc66b446a391e80dcdc4a42496f0613ad51801639625dae4d096fa5c0a987f8928150254970be32946ead8d2664b931c98f125a6185fa1cbf8e250634eafbf32410e382829285448cb82eea40e13486abc7663cb711c4df40a17e3e9742a712a2939d930f88c1c281e04ef72f1acd58a24ff4591442151524ac01a3b16a10344cd4642f23653d55343acc585c2050ac802ee2929604d4affefb79e91433f08deb542b4c1c9012505c50b69c51a892ce7c5aa146d50c6176bb54231bec897f1f5a46863473c8a351299b5346da3bec85262281458f3f2a813ff71175ebbf0bd8b35176e643825f982cf798234a1e19c64b6b4f1c24f356a2323cf02ee27c6536c091c878b7fe1a41095dcb1a54dc7c58b7c984c3d53555da8ac463266c48a93b1a9824d5515dd463a444444444444444aff1ad9a86415ff45ba39c56c7923c3214bcd656000466900a90dca56e1155801259062c28409f0013718fd1423dd9898a4c01a93142b9a566b00200e172912e32753600dea3f95ca07556182435beaa7781f2209449b5875f917eb453e8a1f9d93354bbee0648e2d6938a0afa04f6182a37253d9114920da84358462a1ef5dc6170b35be5664caf87a14638847d1bf4c52668c622b150b0b58a3f21fb945b7518b0b460bb3241fff093ea7aa1ce7e9a6929554e1a7184b8d22be161b18bce65d9c853fc14d7c0b9cc5975cf52bcef22f788b6fe1a977c1451bed7a30d675b12ed6eb8b6e9645226bc164999800c7b24c6226383a268c490e32d14d26bac9443799e82613dd64a29b4c74a389b55ebf169cac91362a1299678298490e26382cd66a4592ff1e898c444622ebb57efe25d66237b29551a5c79ae074aa4a72858bcaf105036957e81eda58d62916b389d9c45a6e785c2d2b2b132762a9fe2afc14d37d3cd54001d69c6aec22622e25a952a94a241155c848a5e23e05859232ce5a8372e22f949bca0e151f5482206f789134b1bf4837e40ed9a3d71f39c58238cd5264640c34504eb1141b9521547ec47a7d707f5e27daf48a69c5b01018662a9de10456cf72085ff8a9d5608da5396b8d57c018e399c7358f5d7805ee988555c029e014180576c118e31696c13806cb708f9f4e19152fcfe2f1879645f3f8c50a03f378b45a6b167a051502346c9b2a2136109dfe09d6a3d3af40e8f404db967796735df39bc2b65c77fda95001d6986ca858c1a49fe3384cef99fe3371d37f7d57b0c54ad7ff7ddc142bd1bf9efbedd65a131ffd1f37c54c36b849d64bbac74b5b59ab2437963c6608cb5a3755d38dabf588c3f424dd14b32c7c338d3cb2fe32e1d01739d6b125fd6f26fc42226f14429633d756d08a09aa626929f994bcde1213a91df0c117032d75f0d9ec203bc8e7a3d55e9cb7de3b48d8ed3ad210518c21a436210debb3e0d58e3b50fd09aa7809dfbfe65b3a6725ebdff8f2a74e52a5fc508a47f03dd5b8d79fb6d65a73af418204096267fa3c715086ca42b55f6ba5f82bc6fd5e6a7bf0812108e7cf0743404310d2a7dccde1034110d2a7f4e778efddd5da5a2b4a7fd57fd97e6b152f7fd5bfff555cfb0b64ff00080be9cfc9a7b55fed585f619fff8172c545f826caeb2f146254982b4f9770ee48810d71ee48418d92100864eeb269b9b0cdca85ff33b77dda90ae6bf32efc156401db882efca10bdb702e3c470bd83ebb0e43a5cf114706ae0d12a4ce20415cf81130e3c2e3b4e5bc30d86a85f08d22cf3e48c3d62b284348ebc35029fdc1ac24ad0098e993d2fedd1c8420fdffe9ca65e488b1bfaf1b637cf47f7e3ff8251ef76d2d3d29e44bff3272c410797d3f06fd4bbf1b6388e2388051468e18a4a7a38c952df593be3492461934a3fe903aca78118f7f3fe29f07f91e65e4e85e46c87bdf8d3146ff1965d0982df58f9e3e1d43461912b0df37cac811e3fb3acaa0b018fd3acad85fc706d852bf0cf0a72db90fad44b6b913fe7451fd251f84d305fae9a24f63418fe32f4ec4e9cc963ae43272c4f01e34caa02e6fa4325bead7c17bfa4b3cc2910332721460baf0e79f2e6fe400fee97ad159d75ffe0f5017f63408065bb311421aad2b702d4944c97ceb6e75fc96bebdafb5163bd0f87a510c3bfc963eefdef64afc1fdedf2781ae43ae02b76b1086be32384af37f5ad3cc0843a10741e812eb4b1e4bae385dba71729a850b6de9e5381d6c1a846dadb5d65a4b477ba3ad8ecb79b9bbba773b6fdbbb9d77b7f3a63d6fefbb9cb9cd719abb7b7fbe7777dfde5f9773a8e451425eb8317c2fbe38df7b2dcefa662874f82fb534bca1d9e27bcbb41ac7d58efc32015ee77d9fe7d920fb888bf1be1befbbf1befbee6b31de590375be5c5c33c6b8ea9c4d2f749ccef8de8c2fbeb6e6ce6690879fc7de7bd6492b0d30c618638c31c618638c31e6a54eea22b7bc18638c31c618638c31c618637c73900dc3dcaa06049aad8869ab301f1026cc878449d6d7b1ac4c82f9dd4ca0636fdf2dfc6ed8eeef96bf22268bfb8ec09f3b0eafbc9d9eb0067a31a614679cb1dd3da1a55f35fe4173d9624ee71ba555365b6e036849b74f53adbda417827a3721b49abb18e7dc81c290f6be0d7e6e0370094d25f3db3da2e84fbfd59d5de56c3139a6d0f2b4f76d20a1fdb615896c11658569b13cdd96a5380263ef7e775ff0deeeafb5e0febcd5f83121ccb3efe28d6de0bdc35014efe5be7a16282ffe9c31bdfb0939f2bd6fff52bb9f80f5cdd4f2406223b191d848e0fb8493f958dbfc656eea622f5d5217e9a08e27d0af9e25a639e79c73ce39737cba72ce39e79c737e9d01559e2f235a5b8eb322f826ca8b93d98ba170ed0ae37befbdd75a7aefbdf7def195b36da184ba4ad1cadade7bb7e5c927b03fb066645a2c7d05a64595e2275fa6a070b5938971458c8b66050ba64595e227df4b1413313127177ff131bc854fe1299e86bbf892bf3c0b0c182e3866fe7b4901a385172e505cc613ca78926991483337c64583d25b26fec7ff987fd73fcdb7fe4ff8066bf87f1a0441eef3f9742010c8b3c5b868507ac88c4c8b6585445ab1e24d9c682bc6116d449b9169b1f495119291d799aa1aadc4c44447899c12256fa2e44fe36b555232716dd6a6092dc6450382e076d1c468ab1549fe8b621882312e9a32e6f42e3ea395f2347c460e94199494941994d6691c595a3233292e9ab135c6b8685a2e5ef3319c854fe1279e06c55b8ea3458bef2bd66a4592ffa218861f0a18096c625f0d5f0b166a58a0acc613ca786abd2ba6d56a999894504ee38fd68f1529550bc7c9e1e44d8c27eb5a41ea9036962eb6a852bccc01e7e44d8c27bb62054b8c8b066cc9cc8ce368d2d23233e3e9742ae1a24939ad9cc096cccce8e23372989889d5703ac17f3af9b1c5d2574aa5b207a586588c89199a94d67f2f2373f226584e2bc65ea29cbc0996538c8b26e5b472025b32332c2b2b567cab55ae8871d1a09cfa296446a6c54222adb07052084eee90b715910f11914f41998971d194654a4b341a8944229148240a69c5b86850c67144c54e35625aa73f79fca7e7a32af52fd66bf5125d2d96bef2f9cfab4695dbce0702852c3e9e8c3f8ab5af46ebb15206e5348e312e9a1494d3e35f41398d0157e7e6e606bbdd605f144271a4a4c49892b25b96a55bad562f69f5962e01cbca1c1786a23879264e0da7868383f36ab91c17863a3b74e7c6b2ec2d14c5ff7a73636f6cdd07556157405b56e0c3c23858125485ad4193d03fc2f15fe26ce9f5b5bd9118a171784a78787878783e65d43828a751e38c1ae7354e89128d63a2717afd4c12cbb01c43cec930920ccbb00ccbb00c2bbb9e733ee7e49c9c9347a68cf8f5318dc942e118098ee1188ee1188efd09ae95302921c1357bc51dd3d7bf375c9d2b13afeccaaeeccaaeeceabc7875aea9dad8d994297d7dabc364a1bebebd59166ad443cc12f52faef22f13f9af506967e5c89125e32b14aa8c261135ce59928c2fde5f7ac78e8cafd234be486d6fbd7e2d914472c848140a6f56f0f5e70d05dd70309dc4e6ba4703d13c44dcb40f986571336a5983aad043cc961aa1a5a1d71fc254555b63d42423c21777b3d3eb8f7025ba4fd779502a067ad012ebb5f208eddd57887066aa39aea36107d67cff79de17d680ffeddde2766eaae8e7bfcff684083f604d28048135a0707b20f75f68db1f427ba70867cd759ee8a3a60fa7fdbb7c73da3f90d3fe7d9f6d7f0827f0d5602748afc07cda270843c4a901cfec479f6f8798f607207a4c185b1bf929fe7cab33edce94097fbeb54d99fdf3881acf0e5b0cec0e0e374c96b5d952061b7dbeb561c25c58254530c91a30d7a692327b3365c09f6f635306f4f3c656df9746af7128ca29db3f70674efb0639edde0677c8e7f7ed708f76e6f6ecdfde96e36ee22a98ca86a77a2a8c6a06eb02150dbd7e4d25914222554bd15239291f523da476a478e8a9184c32c5f301a57a84351e3620eae7e3384a3e242229d15a6bad4bca9ac90cb7e5535fcaa9166dcb2b4873b7878c6c2aecbe13acac89c60c247fca36657aa840e36704c70e89cc83c2c93cbaeb399d4e9bf4ddeb03a9a7881f43e808b1e30354fa388e910f711ce2c8dbda0985dab3ed02512824f54c5512b41c1f6689920105db2ee0a157520c2649e251098541f4e0239a2d6b3c6c40906a22a07126bcd33bda3dda41b46f3ebbe5a08d07eb99aa3ac32cab37c38b618643af9f25fb2bf368982d6bc468b011853290d70aacec29796c59ea94365bd6328859fa304b1e65ad1c628f65ed622fcc3ca0cc038e2f7b831d5f1687fe8d5f08fa80dd170a8135dc87c0163c0863de9429a125e105893933d1dbc1d3c183753d1d8f17c32c6b12480031c2c33962b4334feec93c1948b6a9a489098a2dec7b0758b331b63f84f7317fe1a37d1c07c96f5e829566946220d94835128dd46396f545f2a1937ae8a41d93ac7f84cdb613c48836aad992d6830d081d215e7b67eb6c1bdfb390ef9ca9da3cd42f2f6d65ad8e2358b37f045b5cfd3c085f99a7046c31a26d6f73facba110f401bb102a4481501f14888275df98b2f1844c15dd5da724445412df46233c4701a66b64667fb03391cc7392e10443a14246f6d365ad7463e2a5982d4b36ccb234c3244b34741c50e9068ea443b2916a53450a629624204828128f5e9fe44309a64242e28d20fd200d31ba91f0910ddfd168341aedf89863c9c6147b918738ed1fd5b65ca4658748fdf251ad9223daa8074f76f1eb05ac55b6ed4148967c1c8728ee992debc90d267942abe409564f32bc543e4ce9a46a33cb4a0531cb1ba48038a15598548f930c291e1d5661523e4cb2be0aa682c4a78ce8f5477bf6234c0df199c756d64a1ea58e10e54ee9634433c55033503615e6eab1e4716b49bff2dc31c721fe8853f18af86a5b4ed2bf13dbf2911ee238c417711c218a6db9a95b5eea5f8a96fd61f0030a43222b0a85a00f88411674625f1e212d04e24daa4d191f26eb04b3256cca8cbed2ba11ed1bd1f28836a2a160a7b276827527d80976829d42bc67a01d931582685326837a4046807eecd99ebdf66ccfb60e53c6c33c8430cb3a8185611886212c1c4f60e3096c3c818d27b0f104368e23cdb2ca194a1a6369c358de3096388ca50e631983b1a48d28186a4669c371e30b0741078fb4cb2681fa53ec70f6cb232481781cf5a079bc1826eb04f6f2727af574f070188d2fef06cf866f7c7934bc194e68d9880c24d7cf499cc02c6be4b850fc273fe309ec04763aa1d12c2be4b83014c57f925c8db4d709d66b48b33b7a7d1f6c3d7482d819e2667ff0f01c01eb28d89e5572874a722328c75482ef7e26a03bee315eda2a6959231bd072b4835e7bd0f7f812855345df0b75fa9ab73e8e83e44ddc9b9548defeb0825eab301e0e93ac5d4f07e29db5c900e4c22a4c67c4243b22fab5a930dd0f15957f519ce3ab43a2576bdbe9d9e37a86865532895cf294375eeed8b2f4a1ec616b607b3896b511d042ce64c354c3c9039dc654718251536ccacc76682c6d95ac65ed8234842f53cc1433d530dd743d530689c942c1ac379b32dd574bc3da606fb038e86073f60c05b3ac548f59d6a781b2296bb01b5037650d252b6b289c5ecb1aaa05bd82e188e6dcceefa92ebd619deca3d3ff3821821002e760cd7e0eb6b81dff09d822d4bd31651341f832c5b8d77ce3cffc03a10fa8446c1cca61c848040000200873170000200c080603425116455120ac751400125a806064523e190ac44112c3480821641431061102040444466846ab002837e60dda1c4f0f6140428b4c32f3f59d0fe95740ecd6368754eb5ba5c78d2bd6e4c87389615cda68eefa1f4c58c7aecc3b9ba2ffe1b3637ddf698814ec7b20698c8c5b46cc3b490c0df1631d5534dcf70ce4261cbcc8dcc52ada2e1438b95aeddc6d65f55105a1b94152f2368cb70c38bab96718488f89975247ddec2a5cb8c2fdd71a2113267bff68e10b1bb7e4c3693eaba085064de8d2a3e9925571e46dcb4713b7b641ddc045bda810673d29ccecb4968cd556f877a801d8b308da623e40527ac580ca58393d64c004d7a514eaef1815285fd77d417d1ed58b83c3945a3c5d37e4f774cf27f05d75af1cb5e0bf394e215cc1bebe9f4f41962c1fa4d4a80064a9928271fd64383b70299d955dd55b1d1a9ed166d2650f670ffe8a360ab254b8782834eb2572ecee82a07bd4b65615801340e8ff06d7cee18c18591bbf338711cf132ef1b226de8fc89b087646d54bd293c2e158da363e2e474df5f3cbc6b37586077550371e07f30712bfdb92c584babcf9e4c6a377a09727c9a8fd789cca02abf3794929c1e1a00eed1a16aa729159faadea3187939efeb8daf3cb8053db23025555138308400b0ba9420eeeb10c9abee401581bed73465c089b9054bf9adfc028a931b22e5f8f30aa2227ee6579f77c4ed0a38659eba5b8cf3e8bc93a4a018a0f9fa723b929d2608192294477c2f28888775b429927fce85def28c161062aea7b16673f356b20ff7684571eedfc39e0a3e57d099c786c573e863eb601610f70cdd977560e4c1952ce6f0e549c0d4afa8aa84f8615a27d73015fd8856e93e29b1339a00a18570259ab6d1fdf8b67d950d3eaa308cb674a0cce4b95b2f6206abbebb07e331607c612e0c262ace8c5a5f79c16feeec8167cc6ccef34a6eda8c53f57baf86756fc75f0921a5d9fa6aef957cc2e9c824205baca8d062e2eabefdf9db7f135892d2ec71f82d86477d54d6ef684f8b7a0cf608d860717d5e60759c7267f62c6740bb2d6f3eaf9ac74ddfbdf89069f61569baca5084f8cbb11c3451cfd8bdd2965bddc7887b5507e7299755b2c8401c3ea9e197029fcdf3e04dda30cd3170db304fa2ce1acd5ae0da22f96c50e85c69b41ba66f751bc54143cd0792170c81ae8ece05045ed3c4dd60fa891dad3160b22372ba3e3f420f411daa62449e04d4b3d9e327949ac44005585b06196ba42bd28fdd50e47e56f758ba550fb85494666d02370f96f85de9eb0e1b394c7d44eb04d120a6fcfd23e052e7439ddf04691db1b74255d51a33febd6fe1402213f2962ec2a3c725ed79bdf3692e928b46f657662550307a339d0577c5899367c30d03b4a5049c3857f504bd704f1fc9107430603b942e068fd3507b86ea65a8a266e161c754ffc13f068c7ba9dfb109780debca9bebba223b3abb435dff7f91aae23b2174d784c1c4f8694f31034c613357f59b93e0cf3e006f71a91e34842691109180c5522d45edd82485979b46e4501792871046b1f4d40f3fb9860c438ea4d87ad29b7e81e26e32a403d97756a5d8109f783e4634b52c356037c107194edb3753db2b2d6f8db5859d4edd7b50db135b1010ff24aedb156264b3b4a0e99ab323e710cac3eb86d775da7b04bbeac0c9d22fb12ed4ccf042bd077a6996199d8bb5966f074c4d285f4e06cd70e84fd5330f03053f0e17faaaaaca830ea5ff77734d873aeb8feaae253b249c36a48268a272e4cace218c548517ace6ba5a4bb238a7d99dc526f413f5a14ccb5ba443b4a597f732eb9b81f08c79174a44207c966f5ff3f1003a2e1c82f1313b12045ce8c81545f06ae47d4b007823848fd40f01eac3033e4430ae1e31d99f8c39a9414f1f5ca6f05765246a163fb9801ecaab0e1aaf0141a4a00eb91128ec4c8207610320302c0565200b1bd0c306eb00318cd189d1ea8d6e73f0e60f958dbad82f8579900bb6df1efb4e02f0bf558482b1b49f4a400571d9529f0c5208b6a2c326d5ba9aaa54e4ea4d884712e7e017be1a21adb87674cf2e941bf981e7c178dd43f9b6bf11ff773ba34a0059bd6a322f4405c21fc0b0afa313c778755b906aa6c8febda06d791206347925f283e646f170169f2550eab01c9166d64fb49137a58b51d4b0132bea274d41df77f0e5c877475cba4dca43bb2fdd07e3eb553c6a5018e40b6990b2fd7bd35844e25c9d080ece63cafd6d10d4a14f697de73a6226629cc1c0925d38f93ef7f517c07e4055fe5243902f0419daa5fa55b742e28cb5deb718f83b6ef55cb3cbd52e6defffa18c1a532bf714d8e6082544e2d6e573a789eb0a145d6a070213ec10329d9e7611dd11fd8fb65127f09bb10f8e712f6b46654336b3a47f4872a615d7fc6be3ff74631bf6878e2b71fe6987179acd79dc97018c6c2880af23ea084ef0fc74ef263df3adee2eb2eb79058f492353ee556d8fb3657ff967331b9c95966f01b366839ce4e0970ea2e0b209301b8878058bc0e97571a87f28bc08a2a143bd9d478fd270a7aa0033de820a8fd9736b07a51dea6c1aa1d0aee951e71fa08287e3763bd5faca5ddd1b5bb034b4ee6a44d046b41bd3310c2175202bcad859fad7a9e572fb71e7c5343f1f2d3be1f424b34ae175b164cfb40ccc1822b997fd2986324a31fe15a576b1f1fdf22ff7d1a6fcf6424be3128f56b901e87fc8462d04397da27e308655804f5f8c15c0a5b3f06356c20fb2c5d7527123a8c13840959a379c1ae2d74cdd06920eb6838b797e0337d82b9f43540df14fc403bd500eb4b1ac6c3c9f76f8600741f3efcc40d63a3bed3b8fc8651578f5cbb266f1d57cfb4fd8382f5be85646faea338de37625d0442bf17cfd042c012ec79d31423c552066bc9d7343d717141b6e22ae5eaed1d388ee47fdc833bb8d423f4dad6e19efbc30445a0ff66644e836e5ffa7dcda411d3b5d28271530cb98e4dd04d00dc042c3f1e172d505d4223f6da9759d8404a1005c8108a1df824f3226e930e0bdb99661b50738b65dfc52974ce661dd5aa41f4e875e128c042d0badd66bec4394570c1447e34bb256f93914c0957af54ab43a8035d437b972bfe71803f213857578b4fe85c0277eec23b3cf213ef5daa05f4efdfde9f424d6bea0a2eb719048b44650fb3a2c409969818719162a8ed5c2b5389cec64c083fea9c26eda23f9c47c720d36d1c9c5f2d18918d4246ef9e3f40235ec2161695d1633022738cd655ba1ad82dee1a98a9dcc57d8878d6e233ec5833c00d10d07334e1b41960a9dd28b1be88686b78781d9e086ad9f3c4dcfafd77d6714a9a4c2f1c848316d34f824d6c99bea4dacdeca70783b5641c4da6287f21ae6abcde6b885583a59129fce4daa233b0079bc2b758128be171ca2702c749581cdcc242a6eae632fd6b130a8e25ebec6805a21d1fe276b08ef10cecea78d31d7c47b4a21837596b5e4e096c6d42d378ecc6530ff53c4ffe1a253d6c6667bf5bc07cc60fd5f2c57a158b8004183369930b70d09020ed2bc9d6a3585aadfdb1bc4409fd5f245584cc9d5524660383d0f06c0ebbcc8b33e606af961916af8eae95c9438f7d7103405cde96d9daf42a55b0644de5068de1916a3810806b948d7e18f56fa5e06879532f904536d90909b1d2fef50be9445a59e674fdb97b263094cc1fa93ba43cfd09df2074939d8563114e1cd5a13d2bfe07ca6989f39f45062fae7e1aa49e23f46a46788f54910ad18ee898a9000d516fad8cfa5fd0491ba894ac32cd9a34d0ac4163cdbd7a4440e6d18099e51c0aafbfe4c7b09c3dfa531f59c0183e4e581a624a51a4f06e30da1638705abdc0eb74de7e27bd4dd102c683893e38c537c23726837fe30451f407f3d83fd623591edd9b4f8cbcb11e729f6603fd8fa61d3b756d435e33c439deedbcfcfc0b8e1dcb0d14e94129905f3ba320fabe36a0365ee502eed8a89be18c419427238e586676086524f3895ba922d4ccd1bb46440491d97a0ce10bb7e676f133447d00425e30074c1d2dd9b82ad4ee9f107ac897c0078a840f431a457d80635e5d853d83708b2e5d86b58232e8ee56e3addca8b6be73686599bd36a79d0805f481ac0cb5351922b8f783895d13316f273d77658e2bd71ebf161f79e89a4cda4f423384f38648cbac01ce10d8e496689c8d12f114f5c8c710168e5df7435e42516e8e2ef875f66a12ba8cd8b0c511f889933c9af9f8a290ecd5b3b4990d7089ce7680a528df0eb20649a1c9e414e49106b0ed0be0e29a96888f370ea2b0dd0f3eee7b70ea8418fdd4aa604a4a1770274d9c2d6355469695b51219843b70782812c086dc7a75868198a58be08a56d8c14a363bb20203640de1fe48cb7140f6946a928d50a733ed0fb03d1be1927479382c5aa42bd717f4a8f1300f05a88b69b29666442a9e2475e9a0b4a3a0c9b162f2c65921275f120d1eff963be85ab26325dfc3c07c4c999af7aea944f4636d1686f004711021ec62ac506bf45cefde8df8da6a0166a1bf081558e5e5da34ce9ceab66d75e5da4f0949f96596ad31a8970b35424e282594b2ee08d3479ab19a44e18b367b2783fff32b517131dbfca72a0238f47bfba7cbe7fc148a4a076aa951be720a639e6f85991135eedfe1e4d452e364f06944b0a4f4bed87408bcf426f2b97289f6906dc90129dcc49b68280d85f460af1e4f69eb1737ab1080ca5121266a48fb3e51c3cae8216019b8c7c4ca6c41af579c0fa12543a6e438088c4d84325f47c457e1b0c141b33ce1175ed5440687026d1211ea0c40c03a9fd9165c220af21671c7aac67443ee9a5d9c8effdbed60d1456857e30427354514cea504485151adcdcf4e7a7f953b620a98d85d802d4d8058c7cc046f5cb9059e195107f8097a03e6a74ac013dcbd80705edf1a490b4508bef3996a9f6aacdb8d28d2097a15a5076beb180aa8bbf005b71217d24da7cafc8c1d9ad920a4eb26021ad45a90ae980a68d02b4bd5c620730d27c4e4d751f658ad800565191ba61e8f57ae19b2ffa51d16aa238e4451863481492e3a4ab5e27a8d91a0a702d0893e5eff47811edf34bb7a5f6b767be14091c12921a2c361b462d82c1c82d7e1d4e2cd7b2347b451a853104825d4a59368ce961b3cb16e4dab1f5c450b394dcf3fc707aaeca5ae5904b0e188cda5d817ee02a7b80aabfb66c089bc62686784eb6312d2abb491715037c260d0eb4bc4cd571d84ebcbbfc2bf40aeabc35c44aeab931a275f08355e7d7c81ca07ff55a87ce2bb4954b2eba1c4792fd08fc1cc89d853cfe72f11990c76fb523f3f9ac6bb9fa97d00d59a84525ea7aa5c8479d1947c847c7b15c0176a09327e214ae455b3574fdf6b73b66717cd581822294a34f955a6c7c63b560193808e9ff4bf15329cf503b1825fe6b31061a910e7786ee169217a3dc95ec08f99ad54ce0bc5880bc7412987c4b58fc8bc71f0ae0565692496b46096137fd33678e360406983daca67150ca2b8148dc27c9c9a5734801e7a3b47ea4a05722cff8c5b9fa4b10b56ae10ef9efcb53fdd96140920272d959e728c7cd58e8bb9424ee1c18ed005564449d2d67f35de5a5caa575bc1afd6402c5b3e42c54b2e17d163d0959856a187841e1e1754e2d3311a08b2d7736e55f6a4bacc83c9d12d197e8b9b8f38504e3fe21480f04a45d44c0e606798942bce2605814bcc8dd5e35642b3879e0cc9b02a11488e4744089c4e07e0b743a72b144fa16462dff7116410a5c8af696791cb1e04b581a1eeadab632f371cb3fdc59b4ece8fd5db2ea059e413c7a9fd5f1c223e69f1d163cfc01f8c97d721c4a8b7fb65b4ac8806a52d72b503b46d24deddb61bba15c0aa2e930b119468c8397e40081dfa81b0329aecda7710407239e71d1d73719fa547bb9504d0ae8e9a12bb8fcf302abed08a543f915be7bb6f78da05f433ac54cb626671c7e1e46de49990b31d378ad625e41673884a37e446d91454a05993c40dbd6b826d827c4b00a06b6e74ae4e4d3600cec1e944cc2ee71c6f100eaa54dd3843135d2522a1d8faa7b5c0fe000f121111b4caefa155250dfe03aab8060d191fd1ef89c9fc1ca41992d2ad035c881cbc6848e500c1ceb583e305d4a76b9c001d2ddc50373581a8e8f3a6fb3a54d80e7d6be9077f7d2f83eae69ab80ba2bbea5516b8de84565ae0d50efa6a4b803e85f90a00d41d6eb28e5b0db9496349a368430766a4c181eaa159729ca297521d6e251243910416845931835d0fd2969b2bae06465dcdc3c007485b3a093c950c4a2d36e0c4edc11bbd788f0314f5fa97579ec635ca183b23dee68e715445ae9f43711de0f850015efaae06f58cad72104ceef4cdadf422c34497a211e62897c816ce66cdd95525748ed056d826a6465fa1397683ea542cf752cbbec27f7305f50655e44b11d3525faef8da70e638266aff96e8eb4ecc9261a9566a33b95d50d7a057f6058c28c04dd2d0a9ab00285ad9f151ecb89f8af25f62a934c27d52bfe4833088726873a42de1470457ff46321dedadf87fbe5c9d5066ef01ba298a78a111408bd31e98700b3ab78a14c25ca3c8e147d3e0c373705777046d0999582fe881cfabbefbace168afa830233ed10b9fcd4eec689bd3dd7631f3657cac4811ffa0c255a4308392970766ab481ccb2a03b207b8c4c08acbae28e5114374ad13d2dd6ba6ef68ed4f0c0d6e9e066d9373a3024eb8ec4c69826585bb8a18226d586ed11091d05dc7f11dee07645a0bca85693beddd410347c37b11629d75d5b0032da6ebd840a3da1dd156ee828a2d0d8616884a8ae04c34cd5172d343bfe31291156cfebc91771f2071e9d9fc952854b1d835e6fae22616f3f23e43d22602bf8ea0778190b77edb981490dfde1de434721180ab3c156dc1a307cf113db202f02d827e0dadb5f8e9864475d99e154dd622c48739df65fece4f3ec1735b71c7bb59c66dadd2c95007152ac78afc41a7f020a1d717f6a15137c9c1741c33cc863c74ffc4e1a9f8bde49f0a1bb33bce0544eea9f346ab646ff06fd22b47694a4ae8290c79c5c53408a801250be63213b015213db615b8a0748af5525b4482a7dfc9be67a90b85c22cd491c0a441546a0a1d8589e1ddc1a6e565d36e27b1f110e1241562e1b3be17d154af5e4f86031a3f8d05ca33711aebc9b4814e219a37b6f214a3c907cb6c99d1c90765989f69c33eb76ab80230ec36262bd57460b271a88a7bd42568edf339a6b75e3ed09eae8039552c17e4d42e104a04f793f80fc3154190f154ef8161b754773489a2fc4154f380f71e61ac3b5a81376fbe8447a4b2072e5e42619d8f12a00050da16344c6d680be3e96495b293085570401fe8ccfa18801a0111cc2144085374324947518c47e9e93853d8d9931b1539d6c1b097f689b7f6b0b0f1040a0b2292d3968e10a75d58561e88aa22f73aa7eaedcc3c53134a89238cc941e70ee881af159bcc20d9518cb5d6881c10b3a0f59ce67743ec77a05c234ac85b5550af15e2d264db834d5ef7f68b3065fe120f3909c08bd6fdcf4b0380bc7bc018820afbd064dc7294bb6e3053b52883179d3ab85aaa03775b1919d3c78d1f596b01d1a1c9628cca7ef33d8b03d8949e24ef62ad0e4780a962413f204f0ef2db85751530e15ef9291a363390a60af8e5d6843999946d1e2ae8d36517f5a12244bd9a5b08cb5474698e09de34082a290bd5bfccb92d9c01b44bde830d7928034c7a08facc1a4919bb6da2df8f186aa1b2af53ace2b8b3d21c9132f364c63da742b24b99b63fdf227066915dd9970ab94bf217d24a519d11c35154e4f8f69788055216ecc8942622d2f533259baf6d1240c6a7abc04d371469f4c26c2cf32823c6f07166ebdd0bd336910ecadb67cf7828e131c1a4d898f9a3ed320fb466180c3eb5a3a1f8abd014aae438fdca18e69f5303ad8d29f43d9746bf4472accf7881d622793333ccd78628996c9e5f25007d9933019a79dc6021405582bb01f71c87a68e382efa65a9fa1a6119e2923f179f32b28c89d837b08d5b085d06cecde2dc5a35b2c0ec57d9318f28c558730b5bc82a43ae85eb4ea2bcf42241e57706d6ba636196c145b40b600a73bb6590d657f297e39bf8f1f8d1cfd55c7afcee6db7c2c4b3d3765ab4d3c1b7dd5af27673cd5b37b570cd84602f39aaaded96d0a80d4b89270d6801908537b58ddb6d297b8595205b99446c49bad239666cc5762bcca202ce0a087002f1aededa4db8a3fe55ba74f68fd16ebf463f72f86be066d1d4c8332ccc502413bb77efd21b9ab0634a03ce9569952cee92093bc7f82d9af82c301acb1a7357404fed36e0c96e1668b1768b27cf679b0dd05f344bbb5130ef863861b35bdbeb36a4a4d9ade32a9476438d85f326733cae8c63583c5b318b63ef425268b7f0d38c79f16d43bc3ea7edd630e572d77087a5f0d95cdad9cdeb5d478844ebf98a4a904d6d3f16ab42707c617caee4cb2b3d072331b99d6b85c1581cab1cb358d6e33eb3db30cd7990bfaeedb9d97ecf6e182e8f940c01b246e9174fe4810f2dd7740346b9ec16d03b6737461703cafac326a76f41f305f558af5bcc855776bb007e26059de77fb4367a6437f80b01b4653c658c09d5820674b754805c04d7b783f78892e3df53b85a2f6948d1d782f03ec494d7e2a93ba1685e1cb84338065416297611482b7d0a765665d48c3f3a3d3fedd01734a636ae979f8b1c16a9a1d46f667f8ea898a283d1a9b227fdb2eaf7750744cd9b512ec8ddc620e5fc53b6a26adc6df748084871d65eb28001cc501d51413a85bb7568f110dc51cfbdda286ec91fb7711407f6eea9fef5e6e4940c735a7633141bd0aa5e52b26910eda8165178afb7ec18b527188f73d661af5d6fe1de8a46f4a6581474c87f41aeb7f279b300784bafd82fc528e55a18bd67f1292609d8327f04b93c9b308aefa2f9aeaddefa3e005c9b8d83c489d8b5fb63e700192c7948dbe98dda89b202ff0595e0160983f017bb49540df11e3102f463a29eed083809a51ae2f8582b04ab197033d161c91045545d6d3fad015eb10f3e1a110fc9029906207c4fd7559de01eb2ef23720dc169bf8fc8c15c9a2b73703d586507b546ded2f98d63eb3a9f8ea10be21609f66f37e8bef53de6d82e9963668438e093e93fb7cd69f56e04c3a10ecca2382db656088f7b7108d4d8ba6a0d9d152ab583bb88ec1c4a552ae42c95678faad8baba4e669dcf06e7448257ba43f4dbcd530c36a3a04f42a8a8b3baa6144625042f9789b2610e07a070ec95770b5bde082257558645e93d6595fc2f61e00288cb15467664bcea7aaaef5b895d40fdbf48582c9755d57e2cab5b34702684d812f3e3f7c3a96b0828a674d0d8aa7d27a23b6221bac20f7142d76fb8f4fd50d3465a69a83561e867d9ab33e8d9b468e4164604403b438357aa18793c53e2f17858398eb2371b5b2f6a95d2c069d64c6765b136bdf8a8d03089138b406f114c98670a3495d476f18a751121e5a80d23cd47b6858501e8bd1ee0cb088ada7077bfb46adc008e9d0cb8e0391da52107511b4288856679ee07c79e194915f718983928830abfdfb5e7658bf9b4c9a131324dd8cbb8161e8175afa78dafeb810ca76c00e0c008325b0f9eb6c063f88b8eb44dfd4c0d7952bfd838e21a1580efb773d8b50db649070481648823d6d8035a6f3919a588467bc4c957f7a9d4111a57c6a5c40de573683ff02187202b7910c75b6b4606a2b91eddf9ea3f9570840ec2382871b379b06a036fe240b01219e2082b7a40cb37eeb3d4513575e152fe9193e183397ce82148258fc4f161fdc870ac973c6e144b39c812209d9f382058e987f8c4a63d83242bd8e5c953d9ed9b26fde06655dd10e3609b4726ccc5f49088b0690b92cbd6048a1f43ab5f895e189ba1feca1bd20ea60d78214f1c966ef97a1a4afbf73966b66098289a1ef6a03baae0a95e4dca419585dc37b3a8386c2e65b48f5d8ca2be22cb095758bee5f962135360ec8457c38f59e850a31e6b98e89c8ffa1d45f5acb09de101322bf29e447a8f72a6ba894c4135f58400920351441200d3d41d108049e4f60abb2160a276ed165504319e09784541ee67ae40ecd9104030c25840c4b0f2fbe09cc407979a969f22704f44601e03f7443667303db9184cc7a913bfb8beb60a0ecee342e8005d5da8b6c39adb8e134b224d31a7d5e0d989198dd3b05c74ad4a05bb2687ae810a59b41e32da927e6159324a4f082790e34065976bf239d03485ac7693f2e0d6538970f359946b85b8869ff4801fa969b116e24c1c1ef58f880079fa50f1d50d54666a0aca5ab7b28925baeb575eb9f6da915fb4e4db44bf3840770d944fdf158d3c7d0925c16c7f64f1645aa9aca67f20dc1b4b4838eb3157b7b308f60d5605991beddf57e89b2fa0e7b28ea93149140e9c47ff37971452e042a7d14068f58c79d4f54e3d6c7057da7b9982151a53b2f73285ab3456d2fb99072b535bd096501727a8d5cefbd0403b463a07749d88e6f0e3561eb87e42e1665b1b9fc9a1a7347ac94a962379d239bedac087bf3b013254a39e5ff9a3454345d46203d4dc69072fc5d2ff2897fe37c524871a8cfdc5526ad546d5a611c1cb64594c90e0fa1edac5d2ff92fa5ec99ebd4dd6a7f6e6aaf6d6f66ad93fce2703bba2b1ce4b574806a9a44ef4f2fe5fa8d6c5759160d44dbdfa0ddda11d4222b832064f1bb5360391f2528b86d91968ca98c9cef525e8735cf20cbc17052287266ea51b62f2112c906994348fa432b83c24139a991e1e31d8a131e65fe781baf83728880322853343fc14df0d2bb4d3f487efbea88579951472bec2d2b0e5965ec198b5072bff91d992605df6f283bb0aeb1aff493cd065958df2c708596c068ccbf88af1d70932469f316394b8d1f8c9418d3b0d31fa9a8d59460f5b256b53ca4b18b88a9f630cc9c2bedc72320b8d156022891bb81d515a9d2259cad13b69fd1e4cbbf9bff2762ffb7109f81e889c660a3bb231d95396e85cb37ff3de1467d95999199d2df00cbcff9f7ebf2a3b629ed3fb1390334887446cc0241369b92e4e08ab8d9695d50fa10331c1a0abcf24e8dc9250d88f480cfa3fadb60d94c4356f35f6cdb66f76da270603fdcd090716eac797ddef6e3be05115adc5b2c7521da62254305b8150526e8baa043b6ee5f774c3a705273cf8fbaf7190501de6a018343aaa0d11046b08012dfd14a8fe7286c33f10333312d0ddee12f0eab38609526f9b06c913d3304c4045a92e3fddecc97b4ad5059d42a1fd7bd892b85a5505771432b07c52ae764707948a89898a927e3cac57d56ac4bb5c13685e82fd33ed9b0d958a82ca576ddc8cb6475735d0c0900672b6ad404f57ab0b3431fb6e83da56cc399302eefbd36382c3810a3631e9c35b35629988527cdd274476d59d57f9df8a3087c08c650ca71ea45d5acdb55bfcfd5c5f2a071333af3ec91f5a0d45736cd2511f2015ea005fcf9a48b60fac62b22b5fbde121a1c24342a7b475caa940df13abff8ca1d358c7c6c940598401e15e29ed11e38b15220f6717cdc45e8f4a08460f6845c52515ef086239c1e6d1c9fc509369fcf06e1122944f3c03fe548f808fecb34235fd40bcfbf0cb2c2d88bd4d26edafaaab630446fdd4ba966312dce1744e9bbebcafc47a7e45be6731d670756bd096bb27d5c26f3a8b0450fd2a44fe53abdb29f81bfb29320a4b676aa5f6046d12faa789a3d4380cf4cce5e6c27b2093ebc69913e81e95b18b21068c69f329a9adbd976863004d34b01522b8c0b5da9565d3c2757d6b87f4a43ae80a5408ac20fcdac39ab07f2e2ea138053c8252df0860bbc11be9f6ebc3a049006e69306c7c893c980c18f53f9db461ae24c48d895fb71311fe538808e87f6f66f25540e4781001c702edef0065af2bb2e304edc70be3edfa37767da839e3dbf553e09ad17334355bb4c796ceeb09dda466425ca8cc4bd5c8dbac081c50a3cd6e77bd8a63c7f9270e8e26f9fc54b8c972673ff92e6471fd48308183d48c1679d6d6a043e4d6574e135d8b84123a02dd6bd7af703148ad7dd07f2da1ba8e8bbb224ffcd7afd702bc962f633750d833dd6e22f8aea356916c998a383016b5133b61dd2515a791a45f93b38115714fe7edd38f23d6518b7f5fe4a1cbb074d0be3f92f012f2003df6968d1b1b4c50f5e878f349b4fdbe55191958d99340c4d871a3f2a03e6ed98171b0ad57d4d5c720553ff7b8707121c707260af6182d992b34f8741754a516f1ce1eb55247ad508fca43abb160c5103601a8ed69c29bd1a865d4eeaa5f53c9061a51a366336b4a11a405e2594c622557f500a838ad25a6256685cda036b0f45fba498b48c5edda55f1bb64a383e8b03ff4a367735e1004674e087fa52e3aec773dde23eb7cd09358cc2a4112a1690bb6fa8639e8a276fd8c45498fe28c474fd76f82c24493b077648d9121e1a89f1c25bbd814d98befa6e17ad986ab4e37a17485496c541912ce7f0d3474d3ac0e26c14d1c5c05263616567d4829038b5abc5fabb90208c5464a0d7998d9d854512cd6b38aa7cc1c5245ee3779191b267b3a679a22654bf93ac893b9381593c1776332847fe3d0f3192b22de203519104c5580b4c4827781eeb4fa8c9d316103849970b08d8985a216da655e8dfa888a60d649231ed5260a918047fbc206a3e470ffbfa4b11f10630489155299789c9b54b137ad33461de49828a29bdeb4ac651dcf8355de8ea57303a1a655c7cc49595675a171f3c72cebd8518b27c203deb4b9b139dc2fd66626cf75ae6680c833cf07cd124c2aa2a943f90aeb17b2d13831db43ed265d79a52abac2f121a544eb616e6e6d6d088d8c4df788b5e86ca6c4720b3712d0a3641fc401476a4d182ff5b663e6d596155ca620e24378811b2d8828efa446bdfa28d1c7a6d19bc576919d9e9e39bd72690f46503ea84dfffb2c114d2885763015c732f503fc61e466fbc679821cfde6687d924628399b2a617d3aa83356f59e8e611e89493e0fe50a8aa63100feac3aa41c47f95cb59d825be662489e47fca0450da8590227cc56932f1a2b0526729289443ca09654bee9c7a2ac1fc96b33e3096787d1a387edc004d44ecb073af674d67c95fbce616c396fea683329f57285822faacc98f6d2fe9efd6350d21efe25f653514e0f5e5050cf0b17a50e7a747b048ef69fb68dead340cdbb323799a81bde227c8c5c2b627f47a881ef6942391ca0a7bd25920cf7266258401efa9710e4e1bc1b31b59f97f1d989e9c7830034bef488163d70fc258c1ec39ebd78cfa0b1cad2277855309351e7e3a54261f905b8a098d7c5f78ee44ce5e3e19212626df2f110556db83b69f1a16b70b7ec10d1831457a5870ac8a770f302c499c4de327eb6859b7f65725c46dce3c161e0622a7d4202d1b5240a14d2800e188e0dc96b247c67ed7cee2502703bfedb3b92a90b6cc9365639b61d399ec6bc6291cec83fb2fe9683074092c438986b7838249780e4b9fde8425635d7aa0a7638f00c19396417b98f2f9bf5f54829e3919356597a5d876a92ec18acf56280206b9d8076d9c2fbf2fad4299e99267854c92a5f375f60f012800c1c18844bc6a6f987ec05eb1f748c72bf004c189b068dc69874654d5e873113dff8e2a4b911cfef6f0c5538070425f8c0ff7834635a2234415b7771c7e7e26003a12a4129a89965fb8f6010590d5f6dfa2cac96113a34a0ba9e64e0aeef7513d2578cfeb188b1b78f3e2ea8c3c31dfa016b674d99cf3ead7c4ef3ba9c90109d51f00041436289a05527301b4e9b3e1a3e5a8b47a458df60b73871e28f04f3fd52cfda10dc2d19931e64ddbdf145a5978c612894f67191f327ee79411961d283476cc235d58f477c622b0e521dadc3fc9d87cd47ddef1d76611d5cc04af7c1e965af08790d38b3ff5877645737a9f3d992e03ac3a5d421dc3285014eb9c178671d9be37b207b93f8fccc6088ec3bee9b62e90f81d743fb0ecc19689fbcec1ace639b72b15d3754eb383bfa36f0c5575b6e4b7196b7b7dd58f74289d97fd256e64f9294544470627d48d1f47ff3dfe257a07e5709db7333052b681cb6e73287ab340edbeb2b5310e14a68b2d409b5c95e7ccdd5223672b889c59d6bd19047d2b6df22466ca86bd137eb9342f5d97c7abfbfdc2e2a70caa4f65a186ce24ace7d297bb0b6f49ebeb769f883f13e1235585891a7626143c14e2f87e7b5e1b56d492a67d719c6e02524088eb2831ab52efaacacd54931dc95a38f4d512a0e2759e7c2cac3286c3148fcb4a0727f6e3f5235ea56636b2c9c857312dce8b3c54558fd092405fffd70a659bd9c48ab10818c26bfb86fad65d4356a9bb50d84ad1017aea22c4e5e117606789525f629142e07307b251d187d13676d95eba226dcd2626e00917253e9cfc2511a9a81192a4082954f9e336defe7d996462d0357980c2df664e2b46fe73b4b3b3565305943e8adb7446e406447d5c9588b2ecfb7167e79f9f2d28ba5b9ef016878752c6e6305c893a4adb71c77f88b99a9e667918b3c1ac30565c06d4fee35830402b404044c77a51d3232cff8c09d6e6d01735d7d6e6219a75f037f44d3069f4b3ded0074c55b1db7cf8bb49b9eae817f25207a34e375d1b83bd4ab46f3d113a83e31e48ddbc38098ae4fdb66a8dc6d8aaa49c26e3034f52925e6280d97c2411c550b3d6b80421a370ab396c9b2481882163e4833d627374915691cb208dc17711eb0945080e8aa1153b64c08191bbcd08900c75d18839f42ed86879787174f5e826aa32d121f32324f9e317cd0db700b4c84821ccadda1ca4e56472114d61842991ee6f8f5b080cbd383865f334c39a6de301a85c385413ac7626d1c8284ffa68561ce825a6428b7509afbee0eeaf7ca10e19e6289ae7076ab98aedbe393a5e46a0701d3a9d23ae306cecf40e155f8b13356fdbfdd28bf849092882c270e1e011ad91bf17253731d24c396a17b48184c386548692ed8a1b2f96e64c3d6d380d80d8f4336bb87d55e050377b49f0b43f5e42ad35e9fe8c7e8b521a5d82be48206f862a0ddf0a35f8bdba1cc3512cce35b8ca0ef1f1cb3ed996dcf9a7560d79ad81bf725dae90846af0d67071a60d715c0803b30ee0c81a709fb5d18fb14ee802f792e18ed6d8fb61659d80528c860a321e808769a00e04d5a14288b6800af5a0273288469f2f57a9c115e8a4bc96fd47e2cded41794d3f3702f00d7f4ba1d5603d437115d3a10fb15f3889d74de9610bbdb991264767c356e25b7016e97a804f11ea9e71851c7c698cdc6f3c7a8c9851bed8010a667e50f109a1112483b0437fe0121f70f6ed790d7418afa3fee0e0f73d7d35ccdffd02d43c67a8f079af3a79d6565ca92d5ecde4ce73d59a3169c0056182676932aee1026f1e90fd580237894fb98001d3e2b5d5d53dfb41f19cf30b7b49d3596e2a16a27f80b26f6fd44f037e1e0cd713167e933a36b6be46131201f123330cc01dc4582511c3810c801c0db5a41d60aceb86aafb4a888e246eff4a9dc20f041a4c2374ba768d1ae2bbbfdb92ffd0b9f4b26e3cea2bf51c0579278f6d49cf10e97e9215fcb3bcc321c31954362192a201d90c3584f05a9828023bf5dbfae159edb35247ecfa87ae1e65dcf32e4f990219671468bd22d31b34d6e4a7d58cc7fbedebaeecdbce1d60549531de44db20c11c3e550bb17129c0db3a6ced644c98e7865d2c78993b1d290a7372f6f0fe8a8fb58f77061ef2e933285bacb178156658e09eca46eec2927536d267ab8386699fc684fc391cf93854312bce969ada8c59a52bebb126122712c2cbbab48d206e37fce9626e0c96df8fddbca53e64259c50756d3cb45777880886d41595414c0c829054e8d5f14ae9e49a56da1fbe2d711a12c07d331edc88248a5a7ea69a48301399211a3aa951cf367a5b16279bdd854739af5e7b8438aa54f15613b42ee1c4e439ecfe3e1709a25cd099f7668b7e5c871a4fbf21311aeb70a29ffc7db862c32080b00a5843b70c856890ed84bec82e221df3899a845d92325044d3fcc7026432a5befd6d3b75613aef9ac265857f16149bd959722cd334d2daffec34abdbc37043b577da22fae68f874455656c791bcb54e701eb5d4ee102fcaebf19dd810e8795de4e7a4ffbb7fe50addd97f4ea09ff1277f67c70212db18f8b1a820f1e38b1922e0a0ba4b426011b6038ad980fba253f1278a4a2a5f8ab9bc21083e9020751506d11d75be34e2dec26bc65296fff814c2612ffe0119389918ddf15e7f380ad1c0d6117dedb680d9aa31fd44dee1c4bfe27c554c8138212a424156dc5ec802cae7ac999086d4018c9677707ec0d43e647d293770d497101580b771ab295418d4a1e68d0ab5802db458e8d00ce4a096599db16a4ba897aa161f9349648aa3f32cb6aa006de0ba36b1cc5cd5b13d82b5f879fef5f48daa900efb6a6a057e42e746285bbd84ccdf5a3ac90939632c1a4da88ebb4784baad4d6e74bad20eb54eed00e758c34d275556810204fe0fe708c3b69725b52cdda6c598f61fa58854e70ee011040d81dca10762456321f5035c2d52bd7bbc086656fc43b5e6f3d9e8f93cbbb0e8add9b677df9d3eb95042287a768d17a5f318cd4ae66d138d0d125d5bf85cd9463d5bf312c64428b62d742612992cda36e6b6eb701192606248488a6f2be06a5b722e5bd73281907400e5b0857f1e2e36c9ba757b6bdb762735e97f7e72f0cdfedb31ef383164059b686cae6d0884dac12e4475d4cf5ed2ecf15192224f4d2adcfd94492b72a7f9934d4ac696f2b34a3c6da38f4ca1eadbb1334c245b1c06f98db4cbc57c2a0ce84474d7af5dc3b5a76d9e8eb3bd574434a596471e907026ce42867936c684c3feb2e09aebd6703ee0d921695b88008b71770e764437159fee9c570178dd38f16e64eade876d8930541a29b253ee2797fc63cc4867ed8eb0d4330daa9c6a159555d5e14ca8844480056d0b03a95e1fe634b6787d4c9a790f3f5a250f8a5b13f5ccdf7c509c095f62049774eaa77b86f87b9d346c1b063606767d6e6c1472b6c526d5b0c1b561b4ca66dbf723f7eb7df10cb7c5d6b80b4001968012ac04da6c1be836967f4cf11ec5488d99866a88aeaef0aa8a5b5634efd083b5f25b1c380e67f8bc4c341f86200279ecadcc88984088109c64ba630f470332d807cd8d09ebebbb26685829566294c081fc0b34bc67503a4985bb3c83003a268f06ab313ce528c3843bb4a439a7e4732149ce9d7201923c9db39ffc835c373796788561435e0b757a9d1afb6d7e381b398855d8581858a5f9d9a96886138e88c3577a7ae46e6bd990ab1cfe58fbb461fd3c78580516566c2c7a76f5ed2093090c6a78926d4f6e54486ffd2c114e2ba1a36b5289d39ad62f2c9df350c52c6f3652fdd806aa5e0c1f1f3cc323133ad33bb7555cf40bbcb7ddb8b1bdb581dbf49053706c1b66cc0c67ef505cdce944c1f4cb25779f690eedef304b53c1763a7a0cc87c45fb4a4448dd4579e4566c19a32740e2e27c234fd34ae91cf8bfa12194c0c20b6348b18d6e11a2d210723252a447e7f4721a54975fced0aca681bac838416b58bae1351d075e63a248c2672cbaa1294d67aedd53b0e809d93bffdbe63a2f54a67399dc6f6c6ed954093ade6df3b3f65c14bd0c7d8e3f293b6f672bc560db305fa63efec5b217db0bb04d82ac360a2e76bd5f9b7a30aea1afeda32f18968ef909b0a96a5ba97e5b5c9e59e10c44865e5b109fb7c75fec26c68e0726f6c35b35bd83a3149b894f06a39bbe58a0bc09d1584ca06ab668069b8f83c04bd436266410eac21209e4933210f05a3d4b484a9546da3718eac27d2959d746df6155bc3613f04ab717e37653a5c7dae8f541b741236d3438df3a63429d60a361b198a0a033ac28198fa525bca31958fbed2fe90080637d02939f9d79723240b5b505bebc170bd8dbfa8a10098991023f07b432cfb3d955c6af3cce409d79d81058c207424e274f24a12d5bfb6ab72d03c1caa6b5255d30dd3ab27c890e1aa16887f1b09eea6808789e35f8013c47026e61cc60db3c633fb43608a7bf6d25bd6c04bbce5c5b5f9285d060b1aafb6f21108cd8d0accdfbb0a6ed43531fda608731be770b2d4c311748495c884a79eadb8d2c02be0f7855a8a77a56b69dc53ec5c4f163961b9aacdc21293f204e400b0b2a6bcba06cb595b03bd3bcd556ed479546ee2d83c1b36bb146565b0986331cd4655746197204d6a6b138f94b2923351de43485596dac33cac8618d73b5856ccd5a8d494ce97f5ebdd874a3c7c6556dbf8c37d10e6ec9b03aad0348666113de16ff0a0a22624f4bdc96a49ca6134689f1894bfcf0b4215d7686278678c8c904598f9ed0d316f56bb3864e02c536de1a75b0ae0d8f3e0608c4ee87765ec0be7f0a86d94648de49185dfc83c7a2c536d413aee30f4c32d6860cc006495b1f7e007c774d22a9d69ed4ee20bd76a019d39659d77884f4b4e4d27f8dc75d7ad8bb13b5c2634875d5c6c7314f1b8d2b0fc25605ff0b9ddd9a11bcca4390b80d0a089a7cc45004ca8861e6e76d252cc33f0a036dfddac84cf7b1b6255040934dbd00247dfbff97958054c630e1c7b0a72cfd1a9cd5ac07df14d83497364dc682bc069ad9340a04c8c5446e2b5d2c7ae2edf588d8dc91582fb943f2080e5639dcae61c242439d5034a55282994b12c110a98d59ad4880a381a9ce0b9f1cb86a9ac46a50fa4acba581ee2e4c0733caca857a7a429fb73184a30c8b2bd58a6c42310ff57961f6a385866bc42bd3ee6b81262f1a4e902d9040b2ce9885d9ba940c8cbd2b4bc61bd247a4654dd501ba609417101a1d9db21d9d8f9260e6b11666fabbf69185ec2df37ec03c9d4b6fe241ccc62718280ace783690c978c2410cba06a5a6c97921261fd95ab00c36fa73f82b251a4f3408f1d09a6034c9b27c7293d108823e4d6a9a016a6cecb47a8ed8b80fc6587d9cfdd869399a5ea0ced26ea2096db0d76da54349496da8ab60a6b307a0f1d0c5a93ca0a02225c98d58201bdfcedc1d07f782534f582a45b02ad5e11ebf21b68fe81db4bc40704fb91ea284c34ff8dd64e35fa5a2488808c52700339a61bc5897e1199def402dd0d6c802f04e7dc04dd90c0000008014a84900065d906229f51a04d110c91d904bc842d1976424dbebce7c528ff62263c1f34e853f47b7febf00eacd0609b1f7e4d7b6e5eb1e2cffe915867c01d79e713328d6a1f8ff47f4260c20dd055bb18043794e4384a03c16e5489348b76d5f90b1142855d02cb4cc3b929a730ddd1fb162c076e109d61b70fb4c407194ddc396273d0492de9037161cc1ae3571bbe0721e5f479c228054690e8a86e2ded9880deb812b04f934374b64215a1c4dbdb73a254eb22e5ec531ca152d454fa2a9d0813d2f3ab985f3660b6f3bb2a4d132ff691cdcf22054aed7a4b97288504317d5a686634ed83a6895d7dcc73ddfaf734d2e3419af1605875aaa489bf71e302e231f959ec5f526a2e759855ec4d93f50de27d820a322a5ce076c0f426f372e491844cab22dc6eb4124da87e3120691011ea2c30266573ef05d0953204d93acbb821ee4dff5814d328d9d75c30d289ad655947fc855febc6c7eeaa5d13f4d82f9042427c328818ac3ed8150201dc17ced7220da055c53628c876ca7cd7469cf8cd5a5a242487437410828d017a64677eae9eee1481c4c7ef3f60ac0cf1dac792d8c0d2b5ceb47ca6e9cbbce3c674795e3e5f62b90271ca87eeeb067399a25ba43abac419002b7e2dc2950b0efc5f56acca3ccfcf8b98b4ffbdbe12f444427f25c54f4167edf126eee69d9dc351482dfb89dec9f88b4f14ba68048f1dd2d969a05d901674139aa6c96d6ae6267a8bbcb3d9c0ec867a90fe04a7017661c4484063dee0c50936c6f320d6dff73808e25f52f9695c3977d002a84ddb13f1a4598473a527703d9fa1f4980ba034c67333e6774eb581f2c2b24e79334226cebab7477f835e533f06116fe09a3ce7ce7cfa33716bc234f1d987d0c43ab854dc093c175c2829f649d90e17942538610c1899ba39888b46ababe77b49645e64731cba2f42446da7d151f6cf6537c987abfa90aeb7a06d3d4f57a7ab6d95d05f908ade27a223e6def2a556a32b563588911df7c0083c57a0efe2192649520f458c095e9612734d05f0bb0059315100165dbd4792c87de3f54bc4a195c2f80ec604f283cdd2d193b84d0231501345f37487ec3e785460a3dfdedc5a384690241eb4151230a98c7031750607b8e55553d3af78dad0f691b020605b63916fc445a5396f7ff551e738a2527e9a45881a0c7e4a3878e26feba8b70fc58f545e61a26a9daa59de5e35bbe1d2e5e5eb02c86a15bc1d82a29465dd0f759766cb6a5032eab0dd6c01e5a65f8a5d8a92f3d34c045b94953a755213e3cb4f58d7052563434dbb4839f70a606007c8085c731c7ccc25a6c7135ac478e0ecd5991d81ad49521e20fe2bd55d54d6be7714313354d4f47b5ca730733f40d8dac81030ae5d0ca289f9404b45843105e53a4fba695185a0916f5d42487c6eeba6be9032d243e850ddd2cbecd102a0e6d25740eb6204f7168c98269b77a1e1673fccb80b65ebba5bd6bf1f586b65b29e825e8d06a0eab2c7df02648b9a11128ac18f47b64ac0c275aef1ac6fba89bc6383b6c46fce81a5d2d46c995202d262092eb2e7b1bc2cc6db475f077db6bbce28d1610048064275d2cde1f65a361c4f664d7a4361b4e7f9d6b346d46ce29134892a11434658da69170afe738a612379f55aa4a94b9f5ad6aa6622570b9ed366ba5e3cc44fed6a3aa6a12c86f912fb68a6b3ca13a563db0833cabaa904ce256f3b2d5b8860785bdae921cf05a454d425c666e4cd414d1c8724333b652722fb1b738c542d45ad1a824b45418c9a91bb0965a2aec16242e38f389118a1e5534b169ef45f4a2018c18e9f604141fb8a7d975b7e43231ce0ae7130aed98bdcb3c85cfaa8e5c2704fa099ec8c46fdd908bace9cb6363d71b1d3069a6e7e3bdf3ae74459a8d778ce224240f9bda829262146df26fd3d709cddc802ec7cce4b8bd87668841b97fea4de6a7e44063ec552b51dcf03186668cde1524c34f0d0a9a3940687621d91c8cb201cd16accd88d8a7e7dbd549409923747768ca1e03eb0f17028b59172e3ade635a93f226b7c68e05fc8007ae714aa539db44f6a9988976dd8da51da226b3f52aa61b7204d1ed35046651bf11dc7244870836439f52251a9e1130df104b6ab4d18e3353b4c3c42e5a9035c3c51cb61207480404590828849a49e4d019fc2d5daac12d541da0ab9a5e4614f64bed3dc49dfdc6bbe86566a573a935906c2393663e9b973d4c6635e66afd8afc9626f0ffbfc2ec791c414990e42633c6c233fcfd25eac743d1c6cfb2c6a5630d394215a0535b7f3ac742c2db5167a1816120896efc6b1a2c71c298672c9b1128684bb0398aee00c811004b985846a42e8d0f456b8ee5488e54ac764cbcc43a8f1be3b5dd10940f90df66f8ef45cd901038a42bfc0029aa70b712ed9d45976689e860ac0118c5ebf07e3d40c60c6743935e7428e5c4abf4e87b4cee23984e415638233c005ea111bd99f717fdfcb7e3f9122ccc2ade5aae093a678a95c91ea21cd636cf72028b8280bf0f0449d26965f068551f892b8233e186ed774491086153e349373e448270377c272d400436c2cdcd14df3d983979e0a758815a99d3fbaf1456082b150a32c66f50c2b2b3c0e98d5601915b7eacfca7cf162339b8150fa01549a7cec882cb79466c73fd21d8824b32dadfa342127c09bf3cc0c46a7401af12a3038fc8561ed04de88ceae712c191d86e074af2b5fecda62e6f59fe7d85fac47421aaca61267efcaa55fb17871d3caf53210f98ab2218ff89fa9aaaff0bac71e31c803881f4678ed466f974f634d4373b455965f1663399163b52591790df42ee8eb8e58b8d4854c4b50bbdf2218854b30c455d10a585efbcf04ec2f55f1d43480cddc01a2a745ca3a93a5532f9c4ca41cf604b96c930ec26f31bb969336b130a7b914e7ed80c711c1189c3764a217b617e88845aed54347b4895247aa0a3257b6aa604f7c958b246769738cd4cd2ae48f9e56363ecbec42f854840151ac904a4ea4e8836e8243e995902d9e407e7f8e1579f91ab932a8b7f6e6560ffe8699129036876d91e1c955b332c6319d3b7d6c8d64971d3d42b8d4a85e170c3dd26ead393d19223000f19ab792d876f791eed22add9f32ddffa5fd1383462b17b01ce9352b512bbbf730ddefe494ca6f96ea49787df0ac9a2a1af0de94a4f6d3f9e2daf450cb6e8270380fa1371282b201ea802c26b66ff11033f18606ad731ff76d1e51cceb97ef6fa702fa30ecc387513448f21144e480b8e4a6299c8ad6fdf48d81ece1e468751844045cb9f0a2c5635462ddf6e06a725f0a2087f3d9771b9c055570a42f0455ad469370c9ee7faebdf82b1e9ac3c97ec74be1dbe7b3b79ecf1506756478ee7d2a2007e493f4818969c0b05057ad617a96240c0a2e206684223fd9dcb6d13ebb25bd1eb69f4330978ae23c106fe95cfee5cbd4fffb00d5aec01704e76f2759970cbe83c1a3cea09e29d078669fa513c97e4fa062670d3a2527c4ade2060308520e084b7e63fcb21a9922780eba005a9c0dc3b1afcaca637d152b9c776d4555ce01280b42c3c4609b6b3e9edd705993f51bd3201753fa62076f5dbddb5a6dd30c362a0987906c030605affb56f2a79bfd6f114d6f1edef1fdd1a9141dd11d5ca07988d19d434a81e47541bd1d7a18ca227365197bbf15623f564975a3d1c51cdf12c85f2e7bbd8b782a43890e66e043da2ba3533f4cd13eec7199ccd50fbd879ef826182ef812a24cb24a9acc46b320e3068a783a1a8577ac5231c1aaba2bd0c43cf31261e7e1c6c73a9e65252ecb5174504be9d0c8d4689f7267c35c034701e4aaa67466018431f0c6fa166354ce001ac738f1466ca02c03cf4e534fd59e0227cad06659fe4819ec1fbd627d23732c710210c1a48d681a9163214882e6a4e93a546b127f36e72b9f1aaddce250977d3df72ec54aa05aee3c1e7cb275f64d5473f3f71ec4d13f10444bb9e8045af21c87036e4c1d41c24636e79f5fad6216e19b5e1e57de7c19ec63d67d5eecc25f31c6617ee31b17dd5c30c8ffaf031b39f78f937f3ae830131a6d19d79b5838555b24d2bdff6b41784d531bc180f7777b08d6628ff0e76fa2f45aa9d8c9ef90651f0921a8b4fc87c1d32871d07a58ec4fb971aa50038d85bb944cae85700fe855aa7510495ef0d124b8525703027558b1193050b552c2c99eebfd59dd8d4bd57a2c1fe4fa975fd6b033c132f83a5e6fa513fa02ac124fd203cc7cb9eaada9e4bfa51b154aef9735f842cabafd4bb5e2d095f41d27b530a902805b004afb562a0ce1a446c8081662ba8dabc3ee9519a04f80851f9db6c4cc65b5e67b8ac22ac78c05199ececdc299d4c5f066d5315b5e47a39517ba61c755f931ae29aa6441d51f0ff4f92138f0bd3e7cf36e041aa02b232d3a5662ba00c4e0557dbc37a842bdcfb5581dac5cf88b0a46dcbbe90c057df1b4d9b8fa6629e2bfaa3308ea9f93cbe4e51d042c12b3648879acaa9f828bd5122a1431b1307a906cc03c3955567c0aebb7681ae30192ad27c0c18c9b12780eff7d3d1482c8239da2d210f3b1830518542d82b2d602896cb897ddfe2320f8f4e4ce0ab9c3685300d9a3d6e2746fa15409e2fea58754db5a38d43f9731290d0bc7793ec2f08805f9cb25da2553ee40030a11cd03130f918ccdc6c92dbc9846f8f21edcfd9ff952ae2bd8afc1c26118c22222a99039e86d8f1fe2f82318ecd4b331e3045facc51cdff65361abed0e74b4032ff97ee851c8fd6b3842ee1f7c7fc5f9cccd0d89d820af600ddff62b57b21966aadf6a1d72c85792a44a6d89901e77f6d135404616bbd0a7e5773a929422707c1c8fcaf5b5a4640d77f7d25eed9f27839204023b6580c8e9d2d4d2196cfb2dec4b30ebcb8442a328a80b3c7cd014db1b3a9babd8c0fcb495a7deda59d60d09fff222c90d67ccc266c39c49ef6fd2b569bf86eda094647587ec2aa667efffd6b58eefcd75a522601ec74165cdc2b225e03d3bfa28ef34d15e33972c4f72ff6c0810474759e1df6b25e500c7f2193c73a477faa1a22da8a32ad8a1d76a5f7e5beddbfaaaa4f0bf14fa48e7d9969d1bf069d2191d476544c9518fc64e66f26b656b9f84026f8969a7816de4f33f053041b223c4d5508a69611299b7de4a6d6508c4928f1a1d269d305fd2f7fc2c71e2aa2c8ff92ec4ab6ec844277534123e1b76d16380a2f5d3ba06b3d2182967ee330168e6423d44c6635ef273bc8096a720b9214292396236046cd89b7eb4279cc0d8b0bf9af8446d12bf743bc6b057eafbf083f7e6cf767f57eeee3d039a60b663eadbb3bc46eac7752fc96cc44390831b72c562ec57f2532c6e18b458c3f1665f98a274f628b06fb6c58636a5589f8af8457922a323508bcbe00ae07faf37c4df9376071cd737d0aa4c07ea9e1d7d7f8ea40bcf61e1fa137b13ee34c87cb4898380844bab9e7a00af86be488ca1edc925346663239385ba2eca0b0cd1d75fa9ef866e11538d8b90771a18b36ab2a9091df3cf86e0a184b1e5be6576a070fbeea165ca109c0534e93f572116dda8ebbfeaa33527f2ce766de0278e90593c88016e086e689a6e407d87a9068b392f2328353e0b9fc9b8407aacabb566e820fd2c35be94cb1e1a36bd72602dc5794cbca440baa24d5d9341a8854a072adec749bd5872986020cb405eee6c4050f53201e59493ae93918fa9363add0d493fdc9693f07283decd055cf96c91658aee5dfec64f2651dc96ab49ecaa89ea3d9fb0ebc4c7bf515a4067ada2beda168e47bf33c1a471b636baded463621841042c8de72ef1d0fe50eb50effecafbb4458363381b9ebd172d8a3c671d8afc78d7b73dc85693737e703777d78fbe0037795da5a6fc11dd6e6de5c8b73f1a5120739697b58d7ac3cec55a665da35efd26e87d76ed69fa65dda3c7fd0d19dfd69b7f4d375694a4d674a37dfc4c88dc531cb72487d984a16cdd9696cfaa763d86d7cddf418657704df63daafcd8ed92caf7a531e1167b748c4d7a975d3e3219dc1569637c777e0065f19c98c766dfce8986df9c86626b077331338fe74ca37a592e9ede20a6c13b1a985adb8c5661b7cbacae623f874169b273e9d85cd48f0e990cea860938cfe4e475997958c0b351fab9cecc964ebc90d3537a4353258f6a462bf4e6de4e180c42a1fd6b56b8798b6a1d26bc76e5c129db0a25a4ba8109ed7ee7c52ad29f0fcd5940dbd2305e726c2d9ad8bd9785d9c768dd21c1d202240c010ce2522adaecfebdae8afbea98c248233e6bba808d31f35220dfad18591c6e8d77548e9e8c627ae1b79ae9b496f467265ffe678d58834ae5f78b4d1c7b4ec7c5daea1664904b194445cde3ea9cce8aa7c681fbd87f6d1e837f8b279e2ebbae42e9bc6ddad1169902e6dfdd656343d84396a8c3031fae8ba59fbe85ca44438c1d3df9450f0cc728a24ea55b422469e199be01965945ec95b44caa15e41e995267bfa9b1f59d9a4bfc634a699dc43aad952cd36568e137aa515b2a86fcce717d8ba2cea55e6dee7386bb9739744fdd5117767aa723793ae2cea6fbeafb4a2bf592f84a3d1682489a41572b6a0093c4dc0a3472a33bab166989bb1bf30055b145bdeb92bb617aa5c129f440173403cbb67cfd1e84e38e3aa78c0195aaa57f3d739edd252fdcdeb22722d1171490e65ab97600d12cd737d1bc71ac019f3540d55d563aa661ae71b158f89e56c0cf1e8b989e839cca64e4d2a364f67b28f629adaa95d94a85ecf720a9e728aac9f24ec231eef937e769fdcf6199d7802cf570bfb4b438db75a492f69a2b6a28bfad3c650b3e7deb9b44d3b85b48647c4f432de54f9a0e95f8778149d884fc49e26fdf9d808457cd2df8c4b20beb426ea6f76d16d2bfa9ba753a8f116ccaaa81676f558718995aa1206fe4c1e176d4308fd83fb59964a91220c7caef003289dd32bf8042856c0dc9a102ac93084f0b266e3c822994acd253295fdce9b5335a6e6532923a213fd451e79234f23a11e1f3bf144ca89aa04c280b8881f2481302096392204a7084d2165fd4528fd75ce24246138bdca7108c33aa77562d194de6927baa795344f37b9641cea558e4f2251af723f8951a21547b2acd6294537df5c26d963d0cf14fd758e4ba2e8d57b9a0638479f254bfa67448363197bc6640cbb856133bebba5ec56220938d4492821a790be42f4271faf8dfe641241b90e017265ccb25a9f44d0905e09919740e04fcc7160d0055c83c690e12cac2067ee00f7616fe064d123c88e2eb8ac6959dd04155278820a1f9eb67c9c8086226b1e015b6e0e453f311b820e2b0ce16707076b843f5ddf37fad1b6644548f5d7d25f116a0f3df1e34477775b96d556cfbeec9652c64f582d6be2e84fc6398388993f48986680dbf37c06a1a66952ce39e79c9093dad4344d7b863dcf6fdccc6076e5cc3672de2ab1705dd725a798b1af2c883c2763b7771dc70d42c6b2643716253622081a8280c4235f0ca257d8951dadb6105b4240dc77c67855337d8b481c84a6f1e0e1670f2cc87a052196cab0cbcab02986fa625d28a33f18e3d71fbc66942efd4dd93d724a999aed53051c212ce5ccd9900938e872cba5bfaf6fc4cc0a555608a18c54a842b690fe2491fea43cd237e4739cf4106a864544e48f28d137e4db2621458d871287065c27b52e93dbfc76fddaa6a581b031ec3dfad835b74fbb6d9a9459a7853ab3cbca719269cfa2a8f0d7f3973b7083bb771cbc75ccd2c05be7a0c5e6e57bcccb9b6d1a6337c3178937d8e20eb9fbf2f517a70c0bb13442d56ed4b931e7eb43488550e7fbf91b43a51f65d21a43f55e332a2ac4a97664714818f15eb4b07b049c11af1b75628e1415e6881377babe885a5a362d74514b93b14fec96d559efe4ac5866bab46f92be765dedbafa18596d963c345cf5baeeb5d27ababd467af41cf75af29e49db655db6ca297e6b953edd5ce9b7365debb1746d1a773777e066e4d16eb3b20591c6764ffdf9e0eeed30b68518639665d9e54e36b34c2ae1b62ccb32d4cddee57377fa4b987a6c6623956c4525fbc994bd8eb2126a662c6ccaae5c276975e45d8eda349e5c141aceb2b6ab3d6bb33b3526052930101866610b4bb00e8e2cc0300b5a903233b4e81ddd2061229ae84d3c344c606ab3c99427a618d54eb1db34ce4cd16a5b9e78e5967623eb4d266aa2266aa2a6c7481335bd5a1acf4432994cafb48e1ed3249b99c034f5dee991da58f8baa51d8bd85946a65399ba39c313756569e5da34be2ced317bc454ae4de351bdf77cba368d4d37c7f892255d9bc6f58ee8764fd50787b79baf6bb79f619775b325f2ba4de351773b197687301a88219d91351263d967fc287e34badc891f491e9ce5a7a5b10e25a6230c939fd8a75c326f8dc471de7a4c8f0e0f47175e5a7002d7c0300b5920d242949116aad04213cc7517e9c85e367bfce823cfc2d865fde893f6a0c16e8e9485450a352f6de45f2271da6905f59b5318bba69b627112cbb5694c3fbab9a3e0ebdc592c8b14ea66ef7277bb5a7669e25b205bd0c91f95d6a4904ab01498e3e2cd4870e9d4d6d71b23a985fdd197ac9476e590961ed3f57227ea90af592a91a79ee77924d2a9a42492adf52452ada4d75f54a6c64892ad97b5bea94ce5a85d79c972370fc99d95954b25bda2322b375629c58a95a5123785d45a6fb6b1703d8d82e98548986b1976d982a8a364236e2a436f0ff5475fe963fa122646c5349295faa0d2d05b3f2c9c84f7be10256e708d520991233736b2059146959cf7487b8ceebdb311c3d3c82a916ebddd3d3bba904c88769861f770271f7b9bb20552095e895d095c5a9ec0218a4bec827cb12c6b7677a76a9547484d2a7349797536903879088315f484f504ca79d823615c2b287b476bc7b445b2cccecccada2d6f667b87d5236120ced6b41477773338430581b82363925d78ad81bb36edbaaecd429961d867965918663d83514a2963949089bec15a4a415ed835a7b42c4b66593c2633293119afd8f208218290ab18d39f3c0e793b95b26e4c10d10738e661073803c229e1e0861d3b76d31cd45c719770709770704cc34979baa30cacc7cae4ba998431e5ed8e27e0201e45fcfeac0824a62506e0e5e527b4130717e0a08b8c971619ea17af0bc54191173bbd0387e65284fb40248cfcc1c1c16962471f47af20c4029429705f01462441a461f7312dbab84871b902370e59f2a1a42938979e505bf291307a9470f0bcf938c618f30b8e38702ef94818d3752965d9a856efbab8f8e026d95a8960ed2e4112c62573d95c5c82706b1c66e1f78202383eda6c3176ed660be0483797a2cca5c8b356c6cb843eda4fc2d018795e709dd9804bf188b854b3ac56792232cb2004c213cfcf3701031dce985a1dea9c32eec880832e2b3507fe60481b2706515a07f1870a3290c20e1e62b2dfece80b811d3ec8e145e2645e24372fcf6aead94be32c1102b66ec681fb8dc99ec275d84d0ba55586aa7a8c5167046f592a839a2b7e8572ee182161b89fb38fd9e55f244c762384d14fd5ad65f7218470ce39318965369b1876f375b37b3cf1f1c4abda1f3c8e3858097ac58113911396875618c20f969746d21f3e54e049435face60cbfc4397059af60129665855877c26e39678cd3ba3dbb6315524af9989ed288eeeecbdb234c33ef2daa11c2ee77df2c0bc1cb1535a7eef2c95001d10e7190c6d9b1f5339a6c87f6cce69000c70eed62d7c9766c37e32e1d1c3bb26f368704d98eec3a387668dfa1d9eb99c56a5258e6a009fe2ec30577608427b43518969766560ca90f98060c2f13953c12f8b3c303d73d80cd4340ee610f7df9eb51052f10ecf23600eec02e94302080801dd78b24433774c9147231c332c8f30308832de9e1b0251206f3c17e7e0057d813e0b704530161b4943d7c240cdd9130ba5718507fbdc2aa003f8ceec46c0dc154e17d0ca85730082009238330a05ec9208c0a0cc8aac1f0bc16609632487601c264ef20487b44b9235900612e16b0400632c0010e7ad0032108010939934139bb84e08cc66450a43c21e0e04b75c9ddcf1321f4000732f89987f1fab4a44923ff6379b3ccbcc4707013211041ce084850021d139c00054952a08215ecb0a0052e50f20218c460890c66400327b24cbc580da455c58bd900ce688add00cec0706496d58a837b0a10461f0bd50b29325c0d171cae2957e02ca7903f520a09d4f35e40180e8663fd743f991c54865e9af021e14248551c649205f0e7e2a084d1b2acd654eaffbe176d47db9130232f40187d35f0c0616407cda736a13da926d07eea8e26852e28a80baa02bb23a1ba244846415a95a7bf25f15627e48fcad0d544cc62c70b9fa4c8041006421cc01e40213416204c7b019301871a70c001871d7004c11caac3b70c200c91c641f7a0a885d048e826c01c2c648030b1a7470d3d70e8b1434f37d1d326e8491d3ef600c2c4a1a128042434610a43588039581cbe06c27406ed509b489920b220ca8008cc810a0a3a02c27414f802401d1d2508b8aa704582ab128440e0ea3202ae56728c601341a22b1acbb46dc5bda39e8ebea2a59cd3bab04cd3b68de3ba8e4e4a6547da51cf1b8d6a25914ab354921d4b95542a994ca7938acaca5c59911d572e9c938acaca0a0a954ab1982c58c88e2c32cffa6549322abfecca256548bf6ce9f3dcecac91ca0a9541751195ea9a724fb16061514d954a7654659ef5da9d436db889fa0a3d448ab1e89ad277d63b0bda23e2ee1c4b27297716553769f6ce6a57d11e116354867b0bed11f1760eb6982d5ac88e2d32cf3a0b164d24612e9c5ce78aca75329548b5833aca55849329b98a2e148ebc8aa62a48c2609813d813419794fea65c81939304dbe90fe70a019c31797ac9e4c94ea4111c708aaea2a2a2a222159c9513c974d538f268c76d5a86f128d949327360b5582261ae1de9e3c383f5441a0d330d163aa8a25451515151d185f3915cb4b8705a2e1c55eac261b970ac1d1fe93379b09e4ce3a80fd6cecececececee4e1e1e1e1e1f1b99e5840b18745515151515191b563ed583b2c74503c3c3e3e3ed7930cc802eae8c864638f849953280a1111212a2a82c3e4292a2a2a2a2a02c0e5f9483c3fb0983c2e5adcc93379260f0b163aa84c680a59404444a4d289050044248cf4f1f1f1c17a7a7a7aa69090d09225444444383870e0801bb343aa09dc26d8c15d0407e9535454545454d4227da48ff4913e291629c94207d501b606b3917874ceeb3c2f6a9e8d2cc0d423c2bb34da33ccbd07c4a65b83e1f8d22d2231776b30bc7d645533c7f1df1e4936c334e42212c725b26fbfec1235188e3767c75e7304d36cd746b25ce73b5844262c57e73b580ee10cee1c13169ea7592dc76fa72329bb33cc11733cfd085219edaa66386d46f79a0edc60ed9176671959247147c270028394de234a0cd149b2e18b145980e3cd3de08bc834e0f90c89b25b83a96632ac811829a4bf89bb0bf34524beee10372248a5eb1a38e81263533d540b2708c28e45431062effb83061f5c000c7f86867043d15ffc910288e6a1c67a5ab2a47de2bb4909769bed26dcb543daa39f88bd22029f23a6b7799ee8ef8a9a9b073ec298eb2dd5d123ac9dd33acfa2a8dc4727916e22d1c05269a6fbf61edd375369c459d2374b22ddd6b18d331addcee19e1b077a17ab2b37a77f4a80b30e52b9f4e6ac83bffa505e6b9e8a4f3677d0e535050a75f6a07691a93b24d47323cb39219d564ca14c7675f7363b22d99a88e98433ba43fa633bb491361359e9beb2d26d6f7b9d524145ddb66e7bfc26314deadb31968bea3a1b9975de0d3ec76d96f3386f6362a69e72f73ace23d21d360ccb111cbdcb79b6a3dd29d79d728f2a1e1ea5db27cca1729b63b4912c2825917a24635e82080eb6912c6a2256b1912a76c219929ef3e83bcff38ebcdef33ccff33ccf7b8cf484789ed7754fd5aebb5df718c9bdb3b4eb4ebdee54561d8eb3296fe5a99bbdee2b2b47562c5d5959a1b6e3248c08e20e27a48efe92ddbd5f96deae9eebbacc939d3723cb47300ce4ba2ef36ece50b626e2096764ef582c6c181c8787dc811bcc3dde7becee590867745d67617fd946e25824e2c88da81cd9ebf4a292a32a3a922b1c47da3693f43a4f7a2fadd8d355ace9949ace9d4c92e479dde129f5461eee2025620038fe0e765869162470f13668075504ed200c734e2a63593b20ca30a4020cba0067cedb4681b7879a28da2682b706c353a626469cf58d15e793cd07f5497f52f2c82cab3595fabf6f0a31a55e37d55f1daa2743a70c7c4c4b1e999359996447895c326ba74387da5dd973e513740ed5dbaeb5859b94492e9d0ba7bf2ba73f695d6149e9cf9a62d126d5ba356db6694ec3aecb3a473dabd110d39d8de76c5b81b36f49a4d45c31c44d65fad90bae3c3be42f03e680585ad3b2a6f5126359ed7345117eb1ac26f07c91cd3559d2447809e62692f8787fc88e6a8f9665599676736cfa83c3d6e538cbba1563a465e3b518b9ce6237c76d43c3f626dab6255bd7351a624cc558158b862ecbe2a9776566a7ecac2be61429a58b22ce6e8c1067b789b6bc65f15d0ab5327a4cdd0c45bacaa9749a1db56dd9e9a64baad7c2168df589e3a5f12c3cdf68883ab64bc33d5ed3b47397c6ba85ad26c259a321d2c83a196d774b46e5399b2a9d2624cb366b7e469c8b63ddc774d63d84869836754d4211f08647088b66d1c4fc4b8c31ced948c8320e6a70fe9b96eb8c1747dfcfc54650901f203f461c1173797f6cc4bce0f89c82970cb8f81ff05a8d4ca49987f292b1e2b3ab002182c0012f2f6fbe8937067fd8083a05996532c68edddddddddd1dfb3682c01de36c1977a8209fbb18a53f39d49fecbe9570ee520e220c792a735d53ba4d6b1e0943722e523e4a219b475e665536c5dd6d9ec6019c214fe3d038398b3f435ea294382542171f2d4fe06006dcb1284e91df8135afa8735d97d551a757f9dbe9557c4c1295cc19fb5f77879590436460eb734a251c1675244c96d51ab7d80324482ad5d340660e31905e5d375f413e80af19617bd98d4062bf31905ee588c51b7184106b5e325039900204dcdd97033270900ea6bb2f12467c0cc2891acca088eb2d092f2f26ae7492c73d5299d2cd139790e0ee66f64463aab574273c598849d714b94837d4318cc561ea2a2c5775a5739d35bd64b9f85acf52df5924970feea53b527577e6f4eedeebe9dd4fdecda7972ce7bd744be7b0ae64b9c3d34d1ce9ce9c6efaa9b3a67b369f0ee949f4d5e62eeb4834d77a6d3a335d1a7ad2a56179b569dc5d4ea5125f595894aebdde9c525159b9565a39b68295ded919893b13c6bd4abc72330830764d663b564d376b5809855dd43514aa54ba99d36ce997b589182b61d7308cfbd6bd64b79fbc1538ba249b3353e99074337bbac952483aa43f607769b673a5157bea4aa69f4ea7afac7c74ba4ac7712f916eb239cb4770cbabe92d16360c15d2caabcddee7ca2d122156b1b0bb34a573f15ce91cc4f49de532f70edce0d23bae5ad33b9b91e0ee273b63aa3c4a27952cc49b77eba47bb7b3f15a165fb165b38d64698f0eddaf3cf30d1e71165e96b374a3d58ece59c8c4631a42fa8374e976bb18797140e5a6201e293077952a386e1261baca2dcb457bbded76ea849a65a74ea8f2db8b48d5ccf5f82b3ebbd9f4228d6950dfcec1d318bf9de34143bd775df63cfacd7af0147a908999faaede3b9c94f398c0f4080f1aee10d7119211a45e3cb51c4d77eeb60337b87b772a53bac7bd3b54f1a08787389eeb6c8ef5763637ee0edf24528f6e8e312f710407db34eec00dde1e6b98c0f52bb626e2ca2376e0066f379ef493775533f5dbeba581a7df2e4d770e09a548703d94b329bd7986d2888333919b234eb42cbd39e2606b8e489ced64d64bdcfce3e2e6b71a24587bbeb1dd9ddf34eece43aaf5e0ded16877538d6e7dbb6655a36fd71ed34bccd0c38fee0cf7eedbf30d0ede6e91c6db4c9683b74be35914ee2cb410d38883238de92a47dd4caff2a633a6ab5caf9b8aed54ae6291e0ec9d55cd70379dbb89070a98810a836e2005c75f3f5470bc34578c90c4753723a13f2af778d93cf1e8e69bf8cdb319098616c2095418748328dcec4c96335d8bfeb80efba3984d67bf2ee90fecb4e98fedd22f9e6694c2a1c6eb5adc5e69ba5f178cf5e6c6f5dc377b5da95fd7b7a72c6c181b7c3d82bb17a9f939e24ea63bb5aaeba499d155d7ebbd997aaf3b47f228fdc8a35c67737d1ebdfb6655f5ceac5c357a3de9aad19da927a1a855d18f4efa6555a6977e9d435995afd8d3bb6eb32a47d9ed2b2a17feb47536d33ba372157d7df74cef7d6455f4ced4958f5eb2aaeea5d37324cba9d8d3e92b96bb0ae9e69bd385fdc125a2e9ce90aeeadedd99fa11bc77ae644727d9ee5eb55dc95e27d57bf34d477d0c00c70f91f8ba451ad3a21a0fadd337d45873dd7a66e1317b451cdf38a766b941500e9260161806e1e009cc8d9840e032118143e0fdc68910b0b06f649bc6dd236190cc1d461c1ece7af86c74f8ce3b7c0d72f893030e9f6ac0e15b187018c4e7b301be1d1ee03223c0fec6e16fe3f0380870f8206a1c3ea6747805980e2fc4e9f043a81c1e0890c307f97178238a38fc11441cc67c1ee26f873b2e0f1370edf0e5033814c0691cfec88cc3239181b39283d2492561b13384121d4b721c66ee0538cc0af8cc32df0e795c1ee61ed70e33108f7198bfc378f243140138cc2c87aac396c3c7297a955b1cd2e3387cac02e6305b5f1d3e4211e2f3f0314aaff2ccb7c3055c1e661fd70e1f8b7a955dfee2f0514aaff23d000e1fa7f870f878858bc3374e036c10212fc20241e239ec10477c65715823d81d605707b8d901af81809b81fc460348ab9a630807dc5ce30da815201551010b9c01421c10c4cd406e43880108208400a39b1b700708f1843080004284e468c0cd1e56e3a36b24ab275d231969e4bd011668c0cd41ce000b348001cf7152e3e6039c64817a33023eb200016a3cc78977f3e80d0872b37706dc01405e44058a08520107542088039ee304c8cd41bc880a18a002376c901ea4de01ff4101191448c0cd3f3e000a0029e2394e4a14305160881d0742811f37cb781114184069080a54e04420f123e666d36920816f1ee233ae910c8922fe0309248898814445224711379fb01d37d3b8ca3592c9f800ae914ca50245dc0ce44454a008229ee384c6cd3b3ea302326e4ec0552a704790e364868ce73839dd7c7a11406e563911ff61ca86c84a388050e007901fcf7162ba39e625fc1c1418008dd28198fee33a563c6e7ec003708d643d625c23d9739caca024a023478cf318e21aa93c74e4a0c00b70840e051c217333ea3f5c23d9112b39aee388230aa0809b61fc87235047ace4b83985c5388b6b240bc0795c23198b6ba4cb71f3102f0005721480c77fa0c0cd3dce82027704394e7e08c0739ca46e4e3dc71037b37801ae03c6cd3150198c151c1f62751dd74837848ee7388971b3020ee31aa9a89b65be728dd418309ee304c7cd2b1fe266d4751cc6c22ce0e607dcc53592f958c00b1898af56cf71f2809b7d7c012f16f0806b04c337e3f84a028fd60886994c0006001398b91900f761022f7c581d6602f1c5040070f38bfb708dd409006075730be6e3e699b790808b2fe01ac95a486075b3eaf11ae9563337fb20812fc0c5cd2d24704790e3c4871c272d37b77cd5e2f13e0e738d6098894a883fe01ac9301308bc3800ae916c46758d74980904705c231d0e98e73811e2e619085c889b01708d543c821c272f729cb0dccc721caa9b5587f9cc6364104bef00dbbd01d63a032c772096fe87ed5e84b54e84e53e84a5f761b52fc0cacfd8ed42d8f91e563b0f2b2f63b72bc0ce27c06adf61e5b1dd1e63e71160b51fc0ca1bc06e0fc2ceebb0dd7358eb05b0dc71587a18db7d65ad47cbfd86b5b7617f02d8eb352cf601d8171a56007187119f61afcbb0d863582060d8af7718f11fecf50058ec2faccb65028103c0de7b91c81d46dc1c27f6764f7ff0b79bf407ef83bdeec2626fd1a262619142ada89c4ca5cc6e98642f1434a1e80cb85a29832680dc804716ab82ce1786803d7b79a1092a48c13002d6493cb5ad633b497ff09c6d25ed443fd118047e592610b83e18de9a4b30bcb43c18da6820ca703741dad6416866de639cf316b6ac89ad5718862d402be068001cafe1f802c218d97a28eb9d7046bec11e0ecee62fa730762c3bc69667803155bee794cf435e3eab4a6b4a39a51df282a7a4e9cbbe31d6eec37e2b81832e79f2d4957fd7016a2acb6a4db9f40af595a70e0f1b4626f57c8353bf86acbc2911a9df2cc179e54320114eddb298e9ea112fee1a3da62f6bf1d06e3e3dd63031b235115b1866bf191d8eec152f4717766ab58f6c363abc97c6ba89fefae8ba37dfdce0ece6d32d938bc3da251fce914efa3b1b7f3d62a65ff5a55736f09431faf56891441f8f77863e5efe3a7d3ccdf42c8ec9e6b01ff4dae355a33b43af9d62f427ed627731d2a21d7923eb2eb44be37d7469eaafdb34bed8cda75b9ba70fd3af473a43b202366eee218c3a012cecafc669182aea39fbf1f172d85f8d9b3b0a463da33d5e5e44e226ea0ff501d8138654868606d4dfc4b05fd7900e6334585056a8d7639cc6312a43e31c0d1beb45a35f0ee975baae4de3979fa88ff872ae3b1ce31343fa7263d88e869d18bb9a368508047033123ce3dcc6e1e9833a34a50e5d87f3bc62084f962642bdca9f50af34202da857908a2b823428b9933e789e9b5d4f7fb36b82bb27f0ec9c90b96ec7d3df9c2d344fe7507f38ea39089e31049e71738c671958c67f3866b30d8cbdc843e0ebdc762d9b9d0e559abd9071738c63bf288feb319e59eb31128b6187d8c02abfec101bf83a1036e3c0a8c340ddc5e6885d8ed119956b63a8df7d7f73fe079487828abacbb3061404a4014d53006eaea7113d4b935eb91c62170bb10a04805d225e9b6d3625b7143ed8bce9e07917366f3d78be85cd11a7c5e6c8a3b239feb0d81c8758d8dc3829eba815ac62ad295348ce4f298433214c0302c24c3723dd9cd5d1e4c99ec87ab03be484adf7dcbe6d9204496480adebb2269e51f44a9bd8556113029daa5635214c1bd280b44fc268538030e6b1e00532e0f94fc2c01d1f0e3cf38781e08c9935a021ac83269619a1d2a1bac1cc1d915e87d407cb8f8e1e620d549cc18a3440210aba71b34c3eb1721eb981189c7008db6c7f2001a14024840891017ce1628c242141293d22eaf0e0d0d6759dd77deb3adbfd88a80309215426deb3a4e79bc86d76740a8f188db8d88d6c5324228dedb2f1669b4622ead8e8b64553b4f864739c747d239e1bf566a3256516492b9a287efb1142b86d7be6bedd0c87b28f3e5ff0a6bd747992bc597ed3e6b377ebe697914559a166377b25da8326fbc4a44b635deff3997bac77f4cc5d9bced3c2f148441ddaa599f74edfd48777918834e8bd368df3cdbc345976918834e276918834b6969666e7b31e9389c96461c388d94df6f4181923fb9ac5184422ea18c2a4e69270d0255b38456d4d29734adfe85fd77650f32cc25d34a7e4acb9307bc6ffe800f5ce92e621ca1d943b0847c3d899522484e38b748824ced014a1209cbaf593b31d219da0c6c143b18728fa14c527414f62505cd2b9837ca6f414f110ed08e904451c1cb38583516105c970f9972151ebec28e981e2a7c9932885124486348efe1a47cc27e3a557db63841142c2e89b87d808c233010e1c424818252804ba7a7b23c158892cab90286e8f3a2f2ff0d67d491bbdca567213c6f62eadb3f87eb92ffdc578a5356d9884ae50061ce39d1cb0816dd47a6b4b90d79bf4c19dd4c95179a43231ede9481c79af04a406ca36542d568a050eecd906b22d854782ea3d774a662d2a8e858db897ac3ccb6a6d96265c772cb6837806ed4481a118300c5ac11438d23a821899d40b6a863f3d4b1cd3e1298f142604dc203c59190796e76ce04c33fa7c77a8699fda5b8a9753e78b7a4a1ebdd68df2687cddd99f24bde2c0de2795f11ea5e82f6549af16e248eb0cfcd75fbd55af77f2f6a856c583be83d4d2a4c56e9681e5b539ba7c8ccc360d6dbeb926f648ef3eb279880cdc442ab7a3d098ae6a1e72b67f20d69e59d5fc54cdc35a21ac877648f7feda1341cd29dcd2ea4897646117f57b8a13ada5da09db4b9ac7089f76e1a550a857f407717274fa465fe2d8d6e96f09eeee91dd4be825a5bf963cf209d9e3a22f131f1ed35d24617ac887db9dfad73f32be0d3e8bd244e4d0a3e8afffd3f2a7eb6d17ddbf79dee823cfd2c8aad5fa1ef3f516f90d86d6bb66bd03f5f7d35f77dd6d29fa6b28712076b17a4ce2b40f2ef3d7e5953afdc99c10d4ccbab012a757d3099e5ef53491eff7935ea96427691ddca9cca7a5555c80439dd31f6c9ffe6043d11f7cd237e0717c7872f7ec484a2f938a030f2fbc751b585ed12b4a29fdd7abd1293cdd1ea7f407afe80f5e2aa9db3129fdc1a25e11e9e7884737167937474aaf96c9a7644409dbcbec101b8d537326ce4ee7502835370e8f8c53c8031a70ee1e0c77a0bca2e658149f883dfd833d81d4d2e2f0f0858b969d9fd7aa91386bb1a943fa1275ac7c5e2bd7cab5aecb5ed76362e465e7576cfc9c9c6553cf2ce9e68849a9b7fc25957a4caf5a9e7aa432a91b2b2cc25cec52b6e591ce70b846a461b5b039e21636709ed9a66b441d99356f8d48c37a760c7573d6c7b46eb3aa9841728a068a789bdffe7263bcdcfdfab63d7bdfa8a57d85b38173fc969d4bdd3c71a6df8eb23975ee661bf83aea2b166585aaa56edd15ecd2a4b4a39e6de0b9f2ecdd955ba346d491dd5b23d2b86876ac46a431b75b23d2d85ace691d89c482b2da1b47da43fb7c66b76c3e33816be21e70dbeb629f16f5a32ccb372b31c942dcc242acb5bc46d40171cb8d15fee0abe7392e9bcf47f0bc79ab8d5d273d667db3feac8be5d9d5c242dcc2022b8bc39a2a755f5939dd6e719bdd3e6d6fdb29ceb623bfe96c4ab624585adfac06a98ffebcaaecf39b2a3b766bbbf275d5396bde69fb1b16d3ddd99dc17abb66f37516d431d4b78bb2028b7357a44560dd66b5dfba366771487fa0be5d1ad4b14b43bfdd46e2edda488ca267790bdb944b7dbbb92546efa9156f65bbb5d2b7ae95fe76eb66105cddcaca76e1caec566ef7d48aede6cd5ccace9b560e6bea73e5a995af5c2ffd09eccf7c04671aeadc8c66dd7c037bbb98f6dadf6659e9358ceddb8ceda8acbf8da52f9991faf3ba3e31ccb2b4a350374f2dcb5699eadb3ccb315be4d24c1fa45fbf3e67fc95af77e086db6cdfb2f9c84c6ff35949fbe95966b9766d243e4b2c952a2e59d2532c562cc4279b95c02c2ca46bbb24249dcd916c089eb7b624b01293e56db9c97d92ce62dd1a8929a52eb84fb2f32416cc728ec5c63a5954a6ca5bc54ecc01976b629466a556ce23628bded36653db9cd37e2e32ce19d2553e585e7ae9d294ce72216efa8374b3feb22132beae64bba0fee4b727fa93df70566c2794b2dd5017c57628db59d19f7ccd9e6595f4cbfae94fceab497f1e0ba435322de711318683e56872cbb0cdecc19ee84fc394cc39b579e804162a0b8e6c71d975e9d8930da7575ca82a3f1dc39128396f4ee1c8292df66aa2b217142cf67a7245d19f3c0b7b45ea1dda4b7ee539657d56605945dd5c53a9ffdbee8633974c6cfb0b26845d3924a1f4b7592a36cb2bb0fcc9e6634d9698788a3cb277e94f12f527a3f407addb4139e1ec9c9d580a6d92485a11a56cdbb66d3812869cd3ba73bbf55f94feb8a197da82b9eee41096af59963debd57cf6ae572d18d21f2a1ff3db896057f9b0683218d3429c0f07457f5c13a21d1bac400a49a1b9e17439dbd9e4dc705854710067c0b94215aaf93fccd158def8ca0373402ae0f8acab7d233ecb42858f3867f89308f81a106048a5505fae3ba375fb9e84d367e0a00be712b929e794524a29a594524e292fa59cf0a7a7e4d178de18ef04596aee9800bab8a1c65b9f3743209aa9d416a91778ce396fa6d1c86be7e6339965d7eeccb26c66fd0d81969cd6b51d58717e4aa9078e83157637bc19043eb9831a080bb11b46f60f170f84536569597de95c3b9792abe782e2fab99a5c4fac297f7a957148a029520a39058e3082a0bb7b0e21d25f1541fdc59f496540e083adcf991b08cb5b764807e17925e94870694af4a79d48af668fde40bdaa1fcd8f2e1cd24143faf39aa85b0f252e1109a7e09851991a94093da13f610e5315caaa08aa33d39130aa9f7b77eae52fbf641caa7bc3042ccf8203078b9797d4f7a1fe95540a6edc56baa98bd4070270e9a62ea6bb74f38dbcd61772852481e4c7c4f26641bdaaa25742bdaa16900fcf892770a8b7834052e07ce9e42c08eb0849627bec6eae42fa8bc7db4da2bf983d6741385ea3db942e04db140d67db141d1c9518424476106e12245922efa9837012fdc55738742149cccbe4f47883dc984887e82f1e4710bdfa37032838a752fda3024cb31b53571d04ed4c8147e7384834c445e9cf3a94fe2cac3b664718e7c33d9c9aaf1df9a46f58c7b82afa13f241cd4d670bc64e18eb30f6d930d7ce3388dd3cc405b35c758e45656794a2b2b03ca6af1d0993350ceb2ce8614a4aba87ca05ddcc155d2e41b5385724a17040fd59973ed64ba9d3ff7d566a0f3eb871be762e9e8b8a3df4e04844e464c7598d87cef79425a692c984dd21eb26acc847c258974b24ccb5236158b76ae976d6e2e6cc85756ed25f3dfd59f472533829571d2a8b67ae0863d85dd23758ccb47c74a15e41e995752e4aafb45be7887a959d1bc5d1cd2d058fae711cc771dccda36b1c682938832009a6e14e23af7295739c15dba332a3ae02e70c6323ecdd86d1cb5d1e62c982b242cdb69137ba4cf7985e4206629864730fd5eca262f390866fb134d855570901317787a8ecc458974ea3d1310cc3543ec2546e3aa642851e7470bcc641ec66d55b1c5222542f227187d11fb1690fd35558e466d51c271b5cad3c73c7eee862d7747ac55d8bbb96d39ff591cd1a4e7f96f48133ac537a4ca3c7ba5b838d4eaf2ac3f41691188339e0c866c7acd4749cd4ace1489f6b389ace867d74ab7b1e8d461f5d4b7a35bad6a88eb45f4bfa5362b15fd62f197a63e5b89d6b8985dd0845bd9458a95bbf96f40a75eb76f5e196ea2c829cc02c70b04a47e7469dcd2da526e2223518e6e82f2a33bab988c41d0fef35710f3db6638fe9ec5a11cf66eeb6dc2212cbab80feb0ab6c4c7fd859ec10fd61b7a84c768550798c54b1a5b3d070328cb279621f6c0efc19c2d657ac0af64765b0abd8d24fd6646fe9ce1d8ca4e160d72cac5e4e86148c5d4be81cea88d2e78839e9e3edf46779ef2811dc47f75ad29f758e7623ef5e4afa3342bd052156ff4cc391d6c5aa0fcf99158fc0decdda3b22b8cb27fd4928fab34ea1603d4672d76f73220f0de0807db09b0bce6cd676b0f58861f158fc64e96721085266c4090a8215785e092230ea40a20ef7c8d32b5579eddabbe778effe877669e296e40d35479da853e38f30420370c63cc76db76c2e999e9d746e74ed351db89981715df7d83d768f9dd5eed9ec9dbeeb347a48bb5b8361cff38a401cb9aebb4d0d86b95b24c3dd8d49a21336ee442535dab5d168ec8e9d3e9eb4d92554ee3db33547f076ae8b5d87d12ed61ca1e996d8b6ed5954f9ca3d4b73e234bb44911a0c77af897bc035d1463573ec1d62efd214c970bc3109d638cd7bbc19098e29cd2e01e18c18d9e5eede5336dfd4442570c68c3b5d911a0cc714c019f33531099c310fa977e312948d3a5ea712368dad29d6c4f3f694fee4149897830a0523b2a28b7a35c507734eeb33eb25304a18258c4fe20fe6b2ccf3bc29fd59b149373171d4115327c8709c374a8133e4af380516a5e84f4681e513d89fec2c2cd438441818558a600e48050b0e30470722f63e9faf1358cf5708b07cf66cddc1eb41bd2ccb8314a33ade0e24e59165375e289ed741432e43bd920dc5f6d03f39bd9e9a2dab88cb7232557688bdcb16c252a8a10461794ba343dc601b4b5661a550df88bf3c6b1559527850b1d3c79efe6ce4e1bc8e488a287eb0fc131f28ae6829fdc97390ca2a64d085d3ab6915f5aab11c6a21283c4b9cc052894c2277b0bcb783cac4e51ca40d803f2ed72a9230e4126c1d8b704acf2a8233249e03f62cc3ee8433a665634f9175234f7f725299398b708c822576aa610ec22c7b52b363dfac3585bedf7472f79e5dabc80a2e1261792f5a81e5bc50e485291baad0a444753ecb201c24ab9042f2569125c59ad2abbe70ae9c4be74ad2ab1dcb96ac25c55e81e5ab95a769b08ae64791273e117b5aa8a1f437d45f0b61126baed3def3d6ad4b833529d6bae2c2b1974e7f49b46b15f5276fb5d0258f4dc1d22af27650fbbab78aee62155d38d32a9a2b41b66308d4c08d78c4c76ece70d7b6f818b9cdc00c63f55c56058edfacfce1d5239826f3ceddac25de5e2dfde1697766af77db6eeed5c5dd83f7e885368fda46bbcb233e7bd4ec4c3c9dd13abbc43a26fad618456b0613c6cf38634bf9eb36145f725eebd2a866e2b1756bb05b4403f906c7db58d8ba1db05e8484addb81781b0a6fdf60b1d96059973978c4c1093c81e3a7121c6f45fac3baaecd848d5df7c775454967200769cf4c4bde1ff1f392fe88aa992967e79b2b4a31c87081e72007e1bd1c04c1c39f2b70ef437b6b30554ddc035ee27a4df7f81a23f24ce0f825ba6b232fbc6cec22a5371791d9e3cd1dae8953b075e5e373916f3617919d666bb08b5d1f31decc044e08ea125613d57adf6aa25e87bfae251a07d760f50cbdc232f62ceb30366dcd760867689a16b5a8ddfa6430e1be71f712c675edd6b15fd87569566401be96d034ed33c3d37ad6550ccb56ff45da8106c9814eafae231d91f42a7b76712e2ba25c439710ac41608e9a0edc6079eb304ea0d9f23229a5dd1a7c68b75d5b8dcadd08abe3b6aebbba2c33628b95eb38c8c10d571b447a755d1cb77557ccc16949f9a466d094da75dd11fdf58de8af3f3b58330c0a02858c100263885ee52a04ac99589e83a4537faaedba6abb3c1a6fe71e75240c44030f4e4ef4e915cc99545801c80a403bd891a313160f18d6b0715766617623ae6f4182a8b6dfe00c487f56467ff18884518208481023b66cebbeaecac7c4d7afdfe0eb495522a32f444a1069181976fdc50f13c1ec10ab447fddd959b22715c9975d096e8b38888ec3312527e22312068812438860184bf6a406e9af656a209c7125fa8bd7cdd92356407f5c4c5f11c704a102913026f80eef106f37c3289e9556a761358de56b3c20d479f34704ce885dab2cc93a0873c4ed5cbca75a85d0451b58064515426619373b49bd21e0fce1cd824443b06ebb35228df81869699776c57b42e8267722d44bd3ac21689a5523d288568d971f56bc33de1a77ba482e6e451c74b90e2b8e472ca3a65c6ac4a47b75d7abeb1691b87e3eabb6a5bf78523d84332ae9b3bf7a488920a9ac63314a1014dc61fa1a0593eeb5d78d482412c9a66948da6844e988447a1dd1e7cd06bda45fcfdbbd48239b23f66af71275903eca13478ffad870a5b447e9dc65a3a332d775f3ac36577c8384d2bf5ca7f0077b57bdf1fe1275d4a34ea2deb5fa98ae1175d0954a5df9715ab9b949a8eb5dbb48af37a6afabd23e7a4744fd75f34cfdf55fa4bf441dd74977e5ddb30d3ca2b407fd753b7a6b441aa3bc4239daa39e66e5e6b8d54ab52898f334ec799ee769a47bddb330d250b1a39faca946d4d169da6be9ba35eae9b34d539255d18fdebd46d471bdb3694c2a5d3359ed1aed413a4de9e698d11f1d26bd46d441ba3e9219554a2dc4b5d6d72b62ef79c21a51870dcc45da9de36249b37962ee42bb6d1eed6457258974553efaa4f7e893483d7ab537235b23d2e81e2369ed2295e1be9dbb5a7ff6a7b23a0be6680c8b483cd318fe601b381efea840c14197da3031290b5a918a52a15481e1876818d810ce161820da8d5d9086813b3c1e54edd8330c8aa92fbfe0ebd9857a3d35a7f04cb55cc60b8e5ea9b48b33cc6a63a85de601a1c643973987c04197fe24941987105816312c62594c1de1e56088e8f9a0664864a3847679fa845aaf2b3b915e9dd3ec90fe6494b2b1ee6dcbecc4d7c47848af341bb1a66531198902fa8bf8c7ba4cb8cb2ba057f35ecae84f76aaf6273b26d1278302c7c19a44f7639c71c6186344429f763084db265bd040d86363961caaca47d35817d6020dc688bac7822abf3d3790d4e91bf09a95393b159bf79404f7b7b5cd1dec70bf2f17e976eb9014c66e07f5077b0a6f0555faf4aa7bd52da5e85ea9fa7614b87f246ca0be3d4550dfc8a2a8d8b3067aa6a966b09b6f70532298e4380bcbff00491c0903be3bca72b09a361b0475172a2e2c126e0e453f3b50394e544e82ef70617ad6ee5d0985e6b35d7b963edb69b47ba54f7f5036c1f0b2897ce2ddfbe99c67e513287db64b1f0945af4ebfa8cc69fa48f944b3f209d9a384dae2564df54aa572884f56e564a7147b852d24c15107185e410b4498eb2e52998c09b5c5adaa3a0b92b8a3c5559d7e72617501420fab2d6e4e2c72e20c9aa699ecec2f2bc1cec242954212069a7c600e0884e11309d3e2f0f2470249181f0e7f38271c5a620623c22dfdc1cba4fa3322e2dc88234f6ddbc5aabd39fd73832f6cdb76db53240c781f6c4b9c393fa232db0eed9b9ddeb35ee5ac3feddb67afb6479445d24112063cea2d16490b4918f02d40d912aa8bb738ec6fdbb6eba9a0cae77e82618bef2eacaa0170070e09031e0746d9f122852e8c60054038810da0ec7081a2a2c21d30ca0eb8a30508506f711716042d77714881e4b41c756e76b36609e433b34d6a44cb5d5c201206fca446a0dee20a2161c0feb5a3c5c21d9dcd15ab6c4ec4398b65719da450d749963c51581af9ed9cdcb45fefa1f5cdf27ab659a8b23e55565606f8d32d79cc8065504fd11f507ff03e403f1d9bc0f2e694f4812f45c0119e76ba9b956e21c1acb0c618638c355e9eeaa1768fbf9452bef48d7ee93af1525069628c31c6296d96d5fae11824de3c6408bc5d8ede3526d51f235965770eda3c63534873102cedc4d27e880d9a78edf1469b6de0f8154421bb68738c18764bbccbd7b1bb2ae5119c113806c1b13bc7598eb32c84975606cea286a3bf5661365ea0d45abbdbe17a0279f986bcd8c0ed32311942ac2494e81bfd2dd40c878400a9d8633026da250cd4eee1d4b2ec188661588661a78933aa85da67f9c9dab22eebb22ecbb2acec18cc5a6ef3ba6e5996656dbfec900ee28e59486556600e6cb6f437bb49cfd4f19c61d8ad1ce6784c0fb9accb22e970cb313be4845b2e000e9c304dcb05700ed6200ea98c011ed32f5e582fac17d68b172f5e3c465e2f6ee396e5404bc1342f6e230f51e0eb2a968eb6d3ab9c4dc144bdca9a4e925ec521cb0a4be80757e0160c837e308439d8a3c2201f1061d80428088061900fa0c0d7314eeb22ed61e32f98c41cd29aec3c22563da67ffa9b4ffa9b51f4e7d39fd5e4b2842c28d6d06c43cd969025640d693ed9cf8d1a33fec3a1a4813de1048b4f7fb327b33c9c8a00cbf2a46fcc5b96058afe264b4faf62132d460064344c3645c298f7e100d7887a05e353d371d1e2879b5353e6ed65dc294fc4b0fd4447c2683df7d9cdd5ba332cb7aeca87f5ecd9a5f9e1568feb3517cbb167b926ee215e43d8b375155a138770702c28fd4d6c3d5b423d2ca1c790710867c478a43231ce452c86658280cbb04cf02da15e655805c21cd655629a4380853bb81a26980902ce75675d16b6d69084812ddc71d91aec10ceb02c224ba83f28d8afff70ebaa7398855d3f60d612d7759de5343f3cc32c38fe70cbdefc03cb597c248c0524614c7b673f6b3d1226cb52f7ebb9717356e3e69a9a7173ea3037fffb9e85a15a5880719920e033009789ce77c4581d0ba059806b4098c5aea282d1216e54e6254e7f2c06f0e6427db9cb8bcb8bcbcb730abbacbead9e33bcad9eebca12c281e3e5e5fbfe54aa4d9dc9743a3d51ea8dbc91f7512a956bce70671910da18ea2daba7bfe3780761cfeeaf18db358ceb08b05c963dd17ca0c0b3074fd5cdfabbde228043da4300d7668c9b5bb07502582ad7458b167ba55e58f7c52fdb1204016c6ec1d141383090249a3a78fe64f3ec9940787e65f324c2f32f365b3ab900768979009b352b3a27f03c10365f4bae27780a5d53f05c823dc1f32e366342d87a8be5fec2067103581b99fb6551d771ccda34ce50c77e59cb7aeef0655996e57e591d47d5c48bfb8f20b0f51a893970c2434e323a6eacd6b5e94e879d18b592c3663cdc1058e5998d0cc332ebc359c5d25c77880d7c3de3913a8ca32c8cbfa8341ed3594faf56ae16e3d8cd436ef644d633b190f1643c594f0c9b7537471c747d6ba026ea35a7d62361cc5febb914367886754a65b41d4fd3e96f6a49b41fa00ca85799c527fb61f16181a257f6f399141a10157968827dc0908a3c24c1d70fa888b1efd76d7cb3931271bdc6b32b7a55e3f3d9140ba85740dc1c31109f500af8ba0cd491fd401af317ccb301f075035f335ee0ab05be5428be8024017e7d02f1ee1c1056f3d19a0455209eb59e1e5a4f7f5303da3eb79bb607e050c26c3fadb673db57b6c3c890716ce6e52f7e511e37be9de3b21f50d286d592f4370f8485b886fd34d48d18dfce5d94c70fbffec3f618d6da7973a1a29e3b08f59f0c884507a18e822888d28080f804e23037e300e22b37bf0071eee60f03f1d5cd07e227201e00206eda49e95414445d857acb500b51cb850a02fa69817a0b9f1e1e172e76523e64d8874388ba0fd77a34cda757b0eb2e4aafec496d2bfa43bdd278a4322f1fc0f3b4261ce90fd54ce397377e39cc21ed0103736487874278662b03155271c515f8baca3995eb796a259c27c42c8ccd11c3fc86cdb009f886d6a3f5e438b9aed644f3e91b918b9d97a4660da807cf6b56f42a5b4259566bf60380430893fd4818f300b8f1200983804ffc113db6311601b600d7e88f4fc6354ac48bbf9cd33a184b80df784c73dcd645da63f51891f6f8e1d92f1b4386cd13cbf80b9b237e711823c6332a93c5b8197b8c94f1e2340a605bfa9b3fd85c44e2b079086c0226c06f9ccb288fd5afc3f8c030d457b606c3d9cdd7adc1f075c3c2fe02b11da8346cf5e5a11c754cd108000000095314000028140e880442a150382c54034dfa14000e95b45270561947499062cc18600c000000000000000000008000df370a09b2023debdca7c44c0d7882d0cc7e89a41dfb72976bc3f68a1d601a164de6d2dbeab2f521e1fbd26d85e8698268ff61aa0442cb11481b5041cd87ebe4c35d8410a00a0ef045f62db05c555dcd7c3fea169de45e9dcaca595673589a4a450b3e3fd3e7f0b00780960c01849593a33d668a8567a9ff37d97035f9b18821ddf91272d806dfe34196a3901adc886aa4f73ed83bbb0d6bc81dd1e4ecd9e6eba6a29dbd5343ac8d304f62a871f7d9d0e3165d93c5ae4698b856105287af6c32618769a022fd55ce2a8b392afb68256d998425075b6c883110e320eb700d93941608de80efe677b9728d8fc3f072c592f27d44ec5d1126c42d52915a395ea6e510838e5e580489b389301e7a484e0ac0d5e68a049e7afbda0e74325fa06fa58aa635d9fafa386f7e0d553b958ad49099911841e3435710c6934d64dfb71c8d930caa79103a8a946ce596288cc84c4e8b9fc58953801db28413a258452dc72f0376b98dc7e6046b0769c7ddc4da8c170b13655c8200238105fa99f35fc0f965a65e475d74bb05c72dfa1d4bcad19f7a12196418b72548493cb11d5d9494872aca33d146cc45a2ecbb6f5d5ba02e09328e41b021a68c495f9f82518ffe3f2ff2a84bbb34b01b19edecf68d8c3484280b4216509493e93b8d45ceb53b8f49d455ef79b342dcddf171af0b61e7eb9c6b0f91cc730ae7039a3766d21bdef11ff1f847b0b17a3423765a33c8e9456ddd6c4477114ad5fe9e0a3799f3186e3e826c334c86dc7366b337b1365a9d8487611dd3d91b6257b8cb2758241f7ba3a46b58d26c5c90c11a0046a712c782cbf136aee943213c0151f9a17f5a1169713dd5227879197ffc4d2b48621cf034ab558258c30ab140b18fa677573e1efd9169ef7411c906ddc046592b4515449daf0026bf3bdacbb1584bbf2311e3e15a02ddc5154a4085cb8dc51f40915419d52870970a0bc17f13d48e6eae7e4273106162809794a54d726410e33c76492509b76940c04bb86758a6315429416bb7165ccac151a78ac2be4b3140a429059f4afaf59b76b7ae50ecc699d0509f3273a57b37d1f0d05a89be37b977f050e80eb8ae00d429816dd93707aba0a24b2549c7312d033c9d7bcfde2ebab7fa666f0d0929c8abba070c42918750a19b7918beeb54ca14e3eeb98e1977ff5f286964d1e9edc43a07ecaad4c5316109a929de4eabdb884b041375b8fc72ef17a4e9c82d17735d215d3c7946991d518d41dccacf8380a76ba4adb070ee22c6f425786d72f63da9a2fc0ab8303998755e4a06442a80c51b9787eec30aa0e1bacac71e0e418cdf44a3e940e9eba6b512f7adc454a43e565d254aa2ec5d9a97d1e95c8e499438aecb297e7e7f106fea6dded3569da0a5438a8e20c596d597828bc98c2bfcc10133106fd44a67383f10f7df7368d2848d87cc84f8e30711839f4122e029658519f2f2ac0f85ca1274d30b58750c5a02128c0cb37a157deac56ab6595f24e62ecd041e9c3a0208560b19abd4867aa123607bc646ec7de564701a89660c278c07786bb093930b46b85bf849f457277aee7378048b6b2eabee5222002a24094ce25c01e16097a27cfa6bd5c2c697c481b9daf480fb519e65d692bc1c3cfcb0a8c83733fc919a3152df7a1cbeb6d3cba1d005cfc7123b6a8196eee13a5d42b7b1ec57fcafd5ef78cf2d5aa635fa0922a90218f06185b8bc6bd765053d9de2e287bf4880c99505ff1d21d3f7c3a7652de30ee01c43608e0ba1edc048bccac92250e81b0accb35f94f455ec4d08c91bcd863dfc7b4d99eee29fc22c416181b79c61f56d6edaef76005f27d380ce8699eff5d87dcec3b720aed2ebe1a083164f5e48b4a125f3ba2f7b2d4fb2f37afb42fd717c7279b61e9ace316ecc6ab26895e428fb7d26bc73d4f1b86498504a90aa0e975b9fc57a74dbccc8e00c6f86be4344ed0001288729b07d5253aca9de589f0bd48988d25858b6bfeb0e63c4462c3473d519adb6ff7254fb825571c7821755ffb95cff412ce2926a3efca6b71264fc0461e0975a261cbfb37412351822a0c4a2f0bf3954a735c96b8eb170e8a29e8c290eda2d06620052b516410addb1cc187bec42ec1bea00ee0fe30afe467549a90f81b4c80093d4d099ea2941c697da9d6db7730998d14f2dce21533ab88597dd026daf5a8e1665c6f6932fea4e409c5c38baa20ce8e3f3a4369b22c71df6032b3c8dd5822c37a6bae6498d21d65903b4a1876f79002421ff6747c1f6c295b050fe3e20986ec43787c04f770a65aa5be4f600b80c17034cc9b86b8b56ce7c07af161338adbb4026ab7435d2ac69fddb993128944d9cae87d0d33dbf5066976d48a21abd94e3339192b9e572269a18d003800c55f6400b933363d66c316e383cb15753ab290fef2265545db012e625e98b137cc08dc74ea79f92f5e6e908882c4dd2fd32ac34c7cb816d48c7b628867f89ac7b30c8a7b1b882c43ce66e2f7e30b502410fac3a2b9be3507da144548c96e1f355ccdc988313f0994cd2a20eb3242b96e0a146e20072e1058910c0684183e72752e66d2993537f4e4dca2d5db732e049bb967b071f41d161824f36d6ac1aa348c2b4bd88fa37e9aaf8402c3a74d766834e2db8d4ed4f9e345bbe73831f0df19c3e0ecad15cf92d63c85765ebd57c6cc3180128b80ff0de26c927afd64a96c95aee90703847b9970558804a8aa0c9a82f7602ea8a9f5647773dba08e3767d0f5de1d95380819b20355e14ec0e6c9464f0ce99d9dd26de5b26c8ca12386c805a663151c41c2d0709feb42900bad049e1173e225b34535a82f3b2189e1d6fd5d0bc34f047bb02bdf217516c4412e48bb0530732c2d0bb5a7fe3252e4657b1b6141851acdd9570e1d4859bc39fac958224e7222c731fee4ffde038a830fa69af4410063b5ba1f632603f542918f8fa73825cd10f39173ea561c3864b7b53d975ca291cd8b480a0016684c15dff1085ae905d41e91e049c01ef970695ef40b88c0c0219d240bedf56de8f4ca6dfb0adf1a9a1c3f21f748dccc275d354bc0dc984a942b8c340e58373deda7badfa5efa793d9157fe2262d187380435428791153bd580effc482e8d22988c9186398fc9fa5e1405442a51d4d111bb0e685d2b13adc948d61fdef5ea1c2a6c74611b98de186cede6b70f514e209f27b108ff0ac5f0292dda998e5fbf753ff56510ea164cf3d7d1d4755833ed821befceb7b2535849cd1a54a911e6121f10c9a2e8c0cd6e3ee93c98bf6f5145e5264403aa6b8f2756e86fe9bd3f8d358149f72ff9199021b6a4206811e6524aa19a00eca45497a93d0137a852e678abfdc0a5c3205020630a5b894f7c035808da06f2abc94f0be1509553b8ba93fdba32c04f32fb920a82edaafc5e5b1c0cfe0ec08f31e3fcdac7a7d9ef85e9222dd66c66c377919206ea801a05287aa8b708e28b387997d421b56c324ae2e3dfc4e380aa7062ed8e7100304b118b31262a05031ad406d64383dc811369ed155b7b383ad9baaac2b3c757a05c3c52809b94bcd055b842e80c061438f9adcb65cad2149251457be3dccd9723b36fd5a4da89f4dae7f933fbc6750d35befd10692eaee79a3695e19d6a27aaeb811b14b8064663be60ceec68493bd1c3d9cbed211951e5a373f531d349dc43f39d695bfc5d833e60a156da40ac0ff421e879898f204bfb331808b8ff88c12028e7ba529a5bc5e42284ec8e1d1fa5038fd12caa35e9a3eca22e70f7ea33a0f200d355c5440ff218378343e5a3f5454838c26238e175f5578f5828d57ea7ac05bd1edbc3d673ffa7b03c885603fbc15104ce312130d1ef1ef79dd9adf3066d1ec02561152221698248b5fb45694612d2cd8ad64979e5d2038416bd1183265faeebfbfc432e72d623597062a365727591f9e8540a12ea108379eceb5ff70019bf2035fbe474eecbec42b173dd45f45fc6f9b0d330b2a2b69a9a8f4aa27551a3f63f66ff4197fe07f800e9d87f307956e403a4cf703e6af39c8fa24d4a2a06085d0bc331952b581da192f64a41321822c43f2a70ca86c279b586545a30b01b1dfe3d3148ab11066c7ae78800e7a4d32596215a62b7401b03a60b61ef2b66dfe84e194bea5dde18666b509e9e32e78f60cc988fce97581cd04b27532d416bc83a6573e3874db6eaa9009ff66018701d515e740f5e78780a8013d3498aa9c512867fb38c927d91df387f941262ef4098b8dfd613a0e241061c945de42fb45bc3ded9715925a7a3814d24cbc678644d8a410aed85c1e95867788c46e76a242dc1849060e8dfd3f91e526ae7075b5b324fb5df6d891112074d8a8a1809d02a15201750bcdd67f027ca21ea40d4183de12de10c19fce259394319949418cd5a48ae272ddfab835de1b7cdf9fde7d0e448f349f76b7196a33064ba2a5294739afa8ca9d3087461772933fa077220644161cd40786f83423d3fce0f006db7f94321cec362d3acf20ef2a764666a733aa9d6cc0bd1529b78636a022ac8805c88debffc74255f9b6a0b0575e9292d921e6a0a653d94e0ebba621c61af2756a31c78b3f13a46bcbaf7be82122a058be15ea284658e24362854169f214db428613fa45aad248af22be23f9b789ca229ddfa94eaf45b03717e2ec3266d0538fb043a93d5ca2ad041637ac593c608af19326025f0e11ad8e57af20ad9f34a0b0e22dfa8f3d18d2f8c495bd303d28be32d4f513a51bebe971820317597bede5400e0032c0ca6d681c9a2ee8d6c09d6ddc3e763999ad32631bf4120a8d614f7f55c48c8aef9b81e0b909263275158ee15239e4abed4757b2af78435ca20deab8faee0c539d6a484ca0b7c98f856c10c86220901daff0120b376d23b4c089a7358e8756247bd26d7925b346079e80f516e480cb19f4f427becf6d9172c6206aa22119b2e95484038f0864afa82fceaa03f5039ad9adc15a34741d9c5f80291684d69cc17668d24665f7195a2d414ee39401afcaf967c274bf8c7307720bfdcf40961a9a3f5b3e7aad7ddb856c1196bdf979b0a748347312b646b4c8012146e80c7e674e18388f27d306997acb377baa28743f73a9ad88f3e96d62016bb3459014f0ebd57275f9351e12ba9afe7da89a3e7ac98e60eeed49504d5a97cbf696aa3b12e906a71617260749369518f732f5051154b5af6aaee4653527a483c3aab2402db0a9af88746203a65542afec2ae033408fbca8140c784b3b3ad975e2e5c0d99da2cb2bbc5b781fc4769eacddc3b8e189bcefdde4a4cca1c64c974cba5e8568535b3d57cc612f67b612822bb77d678707576022cf974afacccc10107bd381203c2e5a96bf23fc649a37714b6ffd1f1ed9f1168ae81590e123a5738a7bad3d13f5be1033dc9015dd4b3dd24d43835f1da20d0fa9d8909060f29add572a4748d701e0bd0691a85e773d1007ed31d00797be60da30c1280ac947e100ff88dda9cef1052b7f04157d8d3df273b7caae11deca4ad7916a36546208bfa13d2936ab89698ae25b1f9083c3f38540a9768569f9e62ba3d40a674f4fd900fd3b38f6c39d19a120f9816b4f56467259af435a5148107630136b6dba15c5bb3c06061144de10648a9c7619cc30afc697631884e10ed07af08da0c517d5781104da9d4354191618606c0af8afca725d7ddaf60baef5d48bb1a09c994bfd84d84d4495d0417cdb84677d18efdbaa7c40171de7673846ceccaf6a8818f7917f345f9b86fafdd83da6e204ffdd8e094bb9b0131fd1dbbe96b6b8075f3a4213fd7bc263954f4d4ded3c3be4fe3d64070d2582d69b34465128388ebdf75123bf7fcd7e42637181f1597200b3d94e4adf0f87db77a6e75f46596bf1517512fce6019b6951a8c0a6222baae1636d6757123b72e641ff59f0880d509730611afde4d02ebe7438ac15d5e17a3e414bdd7a30fdc976df57f5fb7a656040661bfbaeb54fc1b1a49add14046781c234e0d5155303e0a98980e81f036c317b6cd7acff6e8915569eac9d3cd09d2f976b76a065da4e2b8d14927ad134bcff6993cf69995f3751ce801561ea05ce0181c5e84690e4da54771b826856634431ae2418c8698320d101f4ae25525bbe6441d7b3a9b6bb5caa1e1c7ad449fb83734df0a36c00162b40d9a96c3e3840eb8d4f5d2fbf3ea5e77b50e64ba618bcbdfbe7ecbe0453085cfc50007f7b7a66b7d10ff07c3546b2e1bea83e822159f947c60b776d7240f0f18bae2142c09e9d070e7944c3d196b756dbed55110cb47b9fd252c636666c6e2f70a0bb839211fd1769353e031ca1da615dd834ea8b2b6bd142c0a52c2981217bd036c4d4c2a15479a6e7920e94fc45652eb45ef63e8ed8db83f549faf99140ddf2f39ece75fb08c410c450b4bf241f0f6363c45090470e7328ab6c22c38cf891319ad620043188ecac326e6a54a185cbc2f157f8e82a4124442094f36bb01430a05e98411aebe2b926b019aa419788788d7d5f3895b6f877b14184c124eda6a67d4919670b8d8d9dbb5fc58d76ff00901ee7b2d55b8843be2abda7880a18e1cc374d25a416f03ab188e21f3cbeb4170be0f28cbab2dc74d0e5f285fadf7d9bd6d2490a07b5fd2f4bf8462210092fb5dd83c061901f2209177891b6386aee8e574cec33a9abe7703f1fb81d324988d73de058dbb710fdce990cf5bc23329f84138481ce76375482a71b1a2694e511c695f1c256a36f324820bd58e47436a741a8098ae2bf461f1703a2f02ba192c86a6cba3024291629c45682ec511bd49a8d3f113885cb08f89d57eafaceea9139cc638dc276b8900fe78c375fe4ecbd8e13c79de08a8da076285a630c45ce299cc0534adc87350784bc047d7200f7174c38d6193337ec4850eec9617da91a375b7577ea190c14ee3e1b86165b2a4dd7a828abed16b2ff7d5e226c2e2c7609909885fc7e3f06fe2703587633eb420069c173988b26401322e2a84d91cf073b0f75f301243f8bb587edbc774cf27931ac8a1da621ff9c154b5c1cf2d2e9669543d26a3f1155e300ebcd1218c937bcbf37098e248213a8be33c9beecf89e94be8783bb50d77d38701c3a5fdd335c3157474b3239c7fa885c6d08d92480e8132dbcca2318830ee8d4e26c291072082168da24103f9fc4680a8511890434916b0cec216aa148e65370f488d04e79cd7d40a34680ff4194e727caa4275ba02f5b9ad9299deaecd311335481a1a2ff6ac60120080ab020d86582f2c43b74720e8e8036fc0f28890feeb2b41d081aa3993ac9f754d850d5e89195eaf6bc00f6e53f64499ccf901c6f157a159b971aa98088273d0b3dc425da23a8b06d824c14e79a72d3f7f1b5a63dc7ab02a964cc64736a7b198e4323173bb4a3249fac567481ad4fb057c46281ef2e882398030211f8e6c0458a4c13ad8a8b489c83214f5061049d5e1d1b7d7a1407b125eef180ead72c2188ee50d780a9001c61b3c1eb6491737be982521b00939fda3a44945faac8b12a8432140c6a64f1a05996ca49d944c70f03dfd35578d4ac8276fdd0d00813c9d0ece57fe71966cc067a48b9ed101267fc5e7bae40f58b8a73913f1c830ddafdebc25c308b4f041262db00206904414e9337f9a15f3948a99da9097f9a65586b2fe07357d95efd1e8d6199cdc2b018226b2f4134cc5636afa7d904450612b8ed89a5d51e4fd0d6b91ae98b5058079990e21fc6c92a3458df1e30fa0e048eedf7206eac99c80509bd288d92581d73805493605efdbc23a39fd3cf141c387b026bb065cc2366d8524083b835d2a4ffdb460df768d1dc10efe66e9396a6063cf2018d1e126ab7b741ed4c1ce3c13c759e881912c1a69bf30a62c471a44bd41eff2ca57b9adeb60931a467c710f95a9d8f09e1f4aaf96cbd6a128de7ac77549ec8aae4f7892e0b83db363b71a8a05a9a2b966762adc978168e1d1edb6e3eb5006b3f17fa33e7627ea5de35ce5e97d285c5b1bd43de2716879856374b342bd6401baaf70e930c726f589fa5e9b4a094f9772cf9654ddf86bc238a27fa7a0b073cd087a39e66900f00c2a3f8b7d8c0bbbdc775b675721fafd284e76cf441edb2c558aab6b0681aff47d288f73a76ca14ddbc0700297a77b4b327c60c6bdf54bd57a380d86122512882a211aeca75d519c01adbb3eb155a3d11085e1025c02972c4bd65daf83c411e79fdca0c0d8d96de43a9abd742dc2a5f696a8e82ad507fc48bc37522b59046797cdb54a4d602c01ca3228d1e3f6a85578c3c20cf48c9b76e51fdc9eafc03434a9ea2adf393cc0c8fb7787bcfa5ad7f39e30a7fa7cb064cf32402d526def96c854801ade29097986e47cb8612502c3f83b22570b0bff1da73d432296d47c0b2a0a2021c2e58e1fdf47b0e20e33ba660e3bcb6f7d3ac32df72057027bd88a9d9e6e7d5efabebaaa12385f7f8534c7e84d207f5fa9c1dbd2af33b2362471090037114617389404f6e7d3af3470a276f27625cf10c3e5b1e91f29f0321ff3e5dd3960bc68134b637e028ab2540d57b2bf2d08dfa74e17b97f626e52ed5a8f810304e8505a1dc819d518b4451fc1beaece8707f1a63a205c5e7db0093d05817b059c856d6b630b02deb356010a282fb43fc3cb5c6df0ea46b571888a5bd3db4593c7861019aed09516dbd07f4f25ae0f8679d5299fb94e5fe5a67b1bc92c3f28db4e92adb105f61ac7bc3e473aff0142d258004d02bf0a71cb0c2e077fbc493826aef19eaca3c10b830de8490aca31e04a619596651e5c21d5a97e5e05a2cf9f4fd3102d180f348f0812368f407f98ec47d186e3da13a0382e771e37714ac59a670c35f7ab1de66317bc3f00be318191b803434f67802ce875272675c3030003f7a4aa58dc78ba21567d0f2d8d068980ac4d76683c1b6fcdb4285f71ff029abf510a634c3d2f0d0580552f4850b2cd6bea1ade1b0a5eaf5281328271bcb19e1c7cff63e1cafea1adcb278477e7ece4fe91d4512769804136538ae8247680483e053e8b7e8db8560751b020f22ab90d444a82d4a85da782bdbdb3775d005942ac701dad46ffddf02cb46023de7f1383145d48f2030846c343ef08393e783915fd6c28b1d379cdda7e9d497f18dd70f62426b74610067844ce2ae6f8b06dcdc5fd694f169100c5b8df67daf9d1c23e3dc4c078960ac092a040b84433a8d5f8bd7186f15df513fb10d5ec9cdd76da3cdcd4cd6c9f4f28828b65058b772c5fb3558cb5c41973c8de01dc7613354758c96c7e10d51c406581062a15744c2424e3bffc4c9202ae4ee5a76c77058405b430ed1208d4548cafe356371f17f540fceaada40f7999ce307b5e42ba47d9301e708f01b7a993d1fbaab0eca61441064a3f020b5d7bffbc6e4fd7925a5fbf3111e5b189209266a78a8420141dc1c149d3a0eb99620fa349420e95340357dcdaa3083c6102010a8c8a9f91510d2d1e3f63d2f6625288e10ab50e71815d80f897defc05825686d80a9bef59fc54a37d5621a6bd64f4cc80b192f8dc2786fbf88442834ef51888dcdbfc1624a37df30ddbe49d71e83bfceb02f8b3bebf43edd2211a8ef62da44bbb81047a0b6c92da23e7dd2439af37d06377fd6dd002e96aff45831b3410d890d0353fc3ecc1c731ddfe37d243e85d6c80d56b8513cb09991bb27c82f6fdac132de3f60e0d3146c6422a1b9e10a8cac35a2ba186c22e2bf3683adb10ba860f83210a14c9d991e3f665ad8db8812b139d46f8775739e61481fe2e9209333abdfa016b290d1915c7101b533ef9f019a6fdcb9a8a2b696c120da15053c60749cab3339ed133b665f13027a1df6030ee875e62b8f98a92f88b0b01a22189915acee3956e510412c4875d6ede5b38c86a442f42802fbefea3965f9a1468a864980d57fde3e9a272161d1dbc20812b5c562048c0a42fd8c023360cd2850ba386f37d43a81a2f47c96f0f8f1f23c2010e8e6306d93b06a41fe9c7990876e02ce2cdd9ecce056e5c1aec82b7f8da10a753bc6a250621c9e8d9daa7d75a1428f65f2e34dc6a5bad0b57df4cec35e1fdb3200605dc5638ad2e4fa99b0cd840904f03e0c5d472eed8da74d21c40d6922e86a6ecb321d36c01e0243aef95eb7c98071bce0ea1e97d7bd76096bb810c20dddc037c2e8722d0d3d94ca9f65e1c9d2f6654120930948a4a906d36ef304e4fdbd6e69cd68dd84d4a9b8bc9b7bea74b35b076a1dc0914296de9a4a869b58201db302d64a74221edcbb4b0cdb29dfa0eb8534039777244385c160c8009936b627cedaaaaccdffea984861e362b3ada1d3bdb89b3f1751e4991043a024fe862d61ed4cab269fc552efb2f20216e96ab3322550fb83fd53b62e889da81618e802a917366323d2b269ed18dc874453337527419b426dd3d9b5b012cfae63829498bbeb178ed75d28aeff828f39bb83d026941e94ee224b52401a150e549af93495e38433c491187c1447d1e137ec0eb51a635a7b4f41e54e900709a40875e221a8d0acececb92b72b04e23dd5230645ddb505e7aad5474c3faa6422600a22a157d84ffb7e8a08878c521e4db71f95d4441abdd65d9d86edd0f1c4997eb93d7584c7f20f1aa54968cd2d0f0f7ffd0072520072a65077deee81506b063bb6350045933fc4818694b1a285ea45ca80546513577238d149859d23192ffa2b980d6b5223b7e592fbcf71c92841928a76be6b51beaff1ac66c8ff50130243be68a648f75ff38acaec36712c60fb444789fdd3c1c495ef6490328d1a2eb570f3de8f690d5570ad222065bd9b3a0c0109431b2dc85331a2685ff5bde71f58a9ee2d0f7a378e25e93ae535eddf9311f40be72607c7664a6e84c9df45f192794c692cdbfc2d2ae3a0e59086b80906348c90a4eeeacc8ccb6660eb750a61649d00fafb64a782ad9c1de09d3ad1d2919277bb23b6c58296a20a2a9843333f9008b33747b366613c6724afb0664b1e49bd1e0b1abdd3ddee569e39606721a7f6cd8d0f63b2731f80568b0a6ec6bdfae3a3dc21ba67a6f22b73b52fbc71f4e55a83ab313835e15a41d9ba1a10f6bd2e2eae2ca65f2f2a21ef6b3ee5bd61d96afe69381aa8ab7e9cf124e9cbd72464b0c1893ac7084d0116af37e25ba36d516f49d32adbbf9fcf24f76c912a900be8c6cacb9dfd94f12befd971312c25bb5b8d556955e4ec41786c99257a5c4711d58929a2eab288d21c3194c496693cda88c20dce8b46459a8d9fde10fa791878f91db5027eb824b269c9046b58b95ea65cdb93d13602172d42f66fee6fa04d3e3e09af9842c3f2b391f4d6078fb2fd0be28a68d19f6f8f8559e6d0f314e0bb1ad23e245a184e583704de93507c23fdfcae47d163bb2e1a0749cf3d185e04de770430c99fa2ad516e0248847cba61c5e261f2a5ebf7c33ea5b35faee5a81da6b0356e46320c17c6215b292b718ccdd395fbcfcd6b5f5981eb9734b8db36df9e40c670bf88131da5a2bfb4f84629febf918928f30a073d463391d1db60cf67409761e1502ce900828bfb0250b2935fee98a6486700c62eafbfe42b45bfbfaf5568933c14883fbd8bf5beb0bd345ea6a07a66ab9414bd5622251b5d26265e3c3c07763ef9617f457d931f95e46c5bc27f3e996f2fdbbabcf1aadb0ee601782513937acfaa69554e2405dd06686e1a10048e2b3a347ac95cc4b3463d9fe6c1d5c1df2a42909525e0e2805af1b27510ddf867b2d64fd7ddf278449d7dbcd001d5f5189411000c6ab90cac2c35e96c269a12da5c5b5c0e4ab22058f293471db8693802938f5e989962e6d8b40926557f6cb0347dc246221166c0b3fba86ac66107743ac3bd9614880f35685e8f632620e6dd2dd41ab886a8d11d80cbb886c1f19b2db7145f2bc77aa23ab936a20bbcaedafb6a79cbf0c3ff095707793302110d9f9b6ca738e44be81582f9467fdbd9e0f69a356e47dee7d3236f9ffd5e6fe7d3825f6f03e4b0e8ccaffb96158771fdf3aec768abca9bc1918075b77b971d583c3081a5ffcd2defa812df40f03f2630299da511e1911a317a8ab23f0b4dc01250d24348379d1722d6d7dd004989abe880851439d01143f6b5ef540501be1520e7d22490b21a8b61e70205a7152db95e5675d635b4bdb256c036806d88daa8ebd3c3b1efbaa66f0d7063d32eab099135c939a83bcd0a6e400f6938a23d11806b51264f698098baa16df7daeb0f07a467c3dade7b6d128fe7117e92d3c2218900651fb25f37e60524d6883c1bd885d85c88077699a4893d6d52f0cdb43604689917e0f14b1d1202f20307bce583f740d3a6146ca9a1aae54099f6857de4b5d2c3feeccdbb4e1e57ff20c7ad186da312013f1bc13d0be82671bf8b07c045678081c602301157eca5e3554507466bb47ebc45fdb1afc0505458f9716049a484949350c0b7aeb30662df67b24a4e9b126c5bda6e1293c782c10528e7df74495421e0b89180a073ab58958dbb260edb19cd0e11d03eb89eecc48604afe3ff487636c964bef64b9574a684871fd273db1f01413d120428cc8ca45c036c0fafe328899ca12c86e41929274d5f31d82d6cd6cb51eab4a03c887b4a0d209f95105e6374a93f03c41c799b1264e2b7d26a34e41377f05ab1f7f22112fe518076dad5cc182fa382165ea41b80e8fcd36ed7a2ab75a75410c01dfecc1cd579cd2e10439d1bc0159ca698ac2040bd7daed6ebb26812de1de19b0e91334ae5ac265530947150d4af2fca8edfe6fe2128c3c7c360f543ce64664a43840022ecc960a4cad79ccdc1777ba13e8710ac19a765920e7a9c10fdb36fd6d75b606e664df2720591afdbd1b15f77f209d48de118b810c95c1f0676534a2b4d54e7bb6cb96c2e8447894cc3b35fe54dc3f3b4fdf3cf09ab94d47003ed6008c761cc8c2bfe23e78f79cc5c59b273b176ad891ea0771fb990fa8724a76068b412b9f1ae828626a504a22857e03a20a12c6055c2c7b00ac26f520a3f6ea77acd85badc3f6e0aee55cac93db60508447cb7ec9f6e9d51772edc836ec5a27fc0ad4c1574f8496d2d6e3b4ba87c82038582c755c2b0262ee59b2f3bb57b9232302b9864f068865c4076a9723d921aba8af5d3b8c509e35e9d025b6ac0adabaa205bb414bd7ab5a356cecd7b1ceecc0ee8b6727027be3306212582df5ab91649e5bf9c8211334ec9a520df8d58d684de5eb763f8c064252f849f280b47f2ccd150eb9418092d9d7083449a0a218a27a804085801a69c80291eebfae42bf99ce53637b110cd332a5eed75fa83421d303b9ee51bea80e3961aa50e0525162f1d408928eb2d800aa0c5e3c102a8f016d39daa482fe0b0e89f98aea91b942a5842071fc6bbe52fc6d4286385b6bc2aecfa3aa2a4b97c8d22070d682dc9d18f14d2d21ff4b7c65930149b556a23c9a7092ce35826c74835dca3fb1924e74e8875e80740b1440b6e53b27cfb5607f5d540144172d8c88c1e6eaa0e05e55748cbf73d027c2c63c80c4eb3a750298ee938c685cf45b204bb007ea7b0411e4f6c6446c890c6fcbc3778bd29d91ae8eb6eeb401a3d0dc5e5330fd5fc08db6d1d4f6853379da3f73250e53324aec51b8bb4359a9e1d91919c2ead4f517d72decdfa8e0976096d5dbe5400aa87c3fbeb82f9aa8a670fe9421dc38611ece2f22634ad2d37fed4e0e8de68219a653765f089210ec4a65ba9c56b70242cf78546d04b6d4185abbfccdbab9308200bfe7e598c933bf8a2a45a473f551beb13b246b9a7809db26a8f56f1920dafd6b06e094fc3bada76de275e9de29d702c4ca972957150581783ceb14245fadc157bd78ec692ae176191fdee5609281a076dda5e4e7b08b082e4687c83d9486b958439355c1d6441009a957e20e3ad09249f39889b265d09314720d93e7bb00eadef9af073e48bc36d52c26958b5b1e73d1b1829e6052154bd03e4c82eac0a588cbe8ebb07bd9f518f03a125d4d195ec3799aaa2ed38987232ee84f64bda477a6af1fd1861807c71463f99ee2545859e51328950263fcf78762fe43c14f420c202ce8f183ef705ff6788a5adddacf1fcf46cd9b7956e96e3ff474376567697658176e35448b561151e4711ec79413576fe7bb261aa965de0760a5c15cd6bb14e3f3dcace968217a1a6bf2084834180ccbaacb6ea49c6d835dd0ba988ef1709e4088992c8ba9e284567671a7abe60c23aaddac5c91e7ae064323808b480dbc3f203e793638800711180ce1813e3664dc27de0b0469fd26246e74bfb9e729dc47872de50ef17fb894144050d2e1fc8f350059e68410b6f2b4952f98b99d9ac9d6843282f39c934a725e684d20561f9ef61afea5a07b6629afaea078bb1b5d4e186076d90657eef3ab8ed3c12080e1c935cca439639f02c9bd17e17a8d4b54e0d2fa0053b51e17c61019baea2f9d40b76aa70b6aea9f797dbef5d388d8278b113be647afe2a4c32aba8e77c7bfdfa1bc6268d2200866e0dad289eda08437354dbd8cb36c541538371d2352bfe70ae7fa0a6b1bd88a3e87c422483fcd821827d085f78c74001d1d9ce729c171df15427c04cb2e6f08593a5b15450e9c88e9a2ebb1b4c9a636060e1115f9b4f85ef01eec8bd32c1856321f80a527f588d08648fd438b23ce4c229af531927cdbe70668b9468684ce73663730bce1a03d1853c2496faf03ffc680871e400479880e32fca6d231c8b55549be3386117dc228329d0eb13ef40afd1d1a3e7f380c1e40d606b38d455d868b0dc5af99d5006b7e02d7a78e3717aded25766a3a7a212ebdab462cdd178702c9d2fdbf00ce291f48a0d6d048ed1c6822368445f1bcf20e9cfbbe02b47ce6ed5e7d355cd370835038562e1ff841332f23db2e4613a71afc818c59439ad1172839cebfe2e625e2ec447c4bfacc303eaf63a6c2d0dc5929201aee6daca304530290056b35b3f6c7ef0d3b1795a0c8d45961ea273f7f7b1d1726649a5f3f9a84a6408e886279bf89c993888b081d0e1ad9a5096d8997fc0fe6b49fe6ef0571674452d8a9604d08aa98b07ae53a7f63ba7c6b43e27aeaebdd92d42144919d1e2c72869c2b415a35b9014c0b10740028442a5a2a5afe9f1f4d5a5932caf912a0c7b8cffffa9ec9281401f1d4c4264ef25f270ca6133ef2f5568aa27d34734500f81d4292b3f678cd94ea9c4547674173b136df34c36a49e0829dc64c5ccc82fe90340c13a4b6448fb1a70198490ad8c5d00f7df090f2e297798b45e39348de9bda4a492111c7d3f387f0e387d54578a8862de6602c93429ff891f407de6aafd8e93549d1e5b7cd1f308e02987880caf29094ca9c228de2f0fa1fe064af0a0b20b308e852b313646b7b6aa6adfcd1eeb16dffce9e05f32dec12176f98f945dba449134136afea441d0e66afbc50c7ff50edb01094b44a94118b4d5076d47db496f7efb55837d54a1a0f795045093d2fd2f861d6824c7770b32cf8c7de4db0579eb2ac3580a248d6cca094042865a2d574a895b02ba32fd86da3f811fb739ea8900a680326789640a5728a79541667f80e72017247059e8899722ccd36fa89fe4ae2fb71eecfa509feb4533927ea69a65602fbade1b89f81a9572f06aade7435a5c5fd8f1bacfa4d17bd42e45351611bf7b8de49b2b21c7e66553992268aa065844f6cd13ef6a3b1e121818eea1e4a7384cbf377c0bb72895267480657c884f73312ac5be7baa18ff54ce4cebb36883d84b35b2a8fac6a9b7d162bacac3e49db8e6c2eebf393a241bb62787353d0f2c56267f53285d1185cff2e47684df78439908af513218edc46f5f2f9106eb2e98f9dc1986ac896052f5c97c53814e4cfd24de79ef75c5a99ac15a9c3cae0904a97443e54655064333c6f90a1f0c897d4f1b3e0e44e1b58af80b893d4a88747b48ec7533a4fb7f2bd42ee2619bba419a1c5459243ef1d12b5885f8eac4a031cd187b955affe91cad74da7a5ade8934e99629f6ad4bfed482ca7fa751385005b3b23b636400cf045665f40678122e21336f33792a412ee33fa7eca01f27137baf47ccbe0cf70e791d54588b40847ff9dd59c456c95354d5089d0aa9b2ffe8fe7fc2a8485c65a5238b09d1eecccbf0abbea5d67533d6ca233b721ee4fe7442eebaa16e1b0711a3062b74e43e7cab23ac747f70fb1707e0d488dcfd2bce4d78886b6b2dae1fcd726ab01a7428232ef80e282025c02b7abdca2ae12b78df8ffc7826c2fb24ef1ff4934a20787fd74a572f0c5669740e733d6fbf23d12a264c524d86c67613ec5a6c076bc76757509476bfb492a81420fcf002d343e25c780e3d31a1b8309c8d4745c56ee64d86f70956270ddbd14c38acde1507a7399de7fe337fd592d56b043eb1cbd023f98b8d3b76996c38629871cda20b47caa42bb0f7651ea0f5bc8c6488d62b94feb470f32762b658a48ffc703de18de81d19ce93e604273cd83ae6546918c06b33a5d76a2c9af27f4d9f93507b87461f6d961cac339c9b604b71ec3b58f57d13d8bdfc50e09182a1fa8300488350d327e86bebaec54d93784efc4305abdefdce39a256d7d6cd48045e691a4f0166c13da68cfc24c040029faeddb6a6e40b3638d2bfe09fed02f98710b779c8d6460c98c6ccf401b262228da6e67ee89208f61ca4dbe56fd5f2709f0a0e8c5ca82bcd4c418b256dffeb38d6336beadadc29b3f8e63c96ab6c6bd311cfad68b0efa3a65bb39ca82ee6343755a3660b763b1e33ca3c5a1e5f5debb74f903a45cf9252449407622ee108104f13d029874df8ec4429c976c577d5003017503e843c64ad2754588ccf7ddf8919003fd0dd8e7069afe24069201a68b4e5cd788dbf815c3464f89a32660be9c92e69f1686039919e41da26c8bccda4a07949ad0ba0c33f14d612f81f45042964b22852e9e45a559216c47e66501d87cd4e0c543945b7716e5919ba6806b8e4d37c3b81edc7b99be067685f251f81089ffb47094bdf15b4dcf93a6697f7f725c28a6d4898a2ef1a605d5c3cffb0c5ce12c0bf82ec898e9bafdadce8d1116fb5a1a9c0ab5f9b45eae812b6640f06a04e9cc954b76469455ffa3b6381d3229794c961de714801fdf6d83812fe959bc78da5431eb277c6c427b7645bcce101498f1b85f075d80def0c00688777b49a39fa1cb4360fa13559ed0edda0b5d39ee58c586f7550a24cf8ca63825c407a7c101f9373d8bf5ba6dd43409e25274ac3c99910a8bb4c75e2b6eccf9b4ba72f676c8c8e9690986885663cf9cb1cc967716df6248e4fb54bcb8c7602399364dd49e4cd0cfb85100a448562c05a6c8224865672ff4e91113877ea3c282803c957acdba4c124acee7a0be49f144d77cc641613c82a866ca46283047233adb0e807e426de7004d1f2ae106bd256f9dbd71e97b262b0c942ac5bb3285f4bc142b815393eaaeef4e16b12bf881cb981da37545a7c7ccf608a0ddd5643499e3a53dfa02ccaf8ece18ca012a4f73e5a6a4712737b2f6beb4bb577472082e08f24dc09a08f6690b1ee3ff2351fe4db4cc97a9aaa1f501456a0777781a2ae5419ce6cc15a2716a89b2bbea6206575bd87f86c990447a305a44f48942ca8a84d9e04d138a360f130f02864d751540a6a1ddbdec9a01117759eb544e19f4218a3cc07204bc1f31f64620fdddad4e64181345e92487c910e097110a204130f07f91b26be0256c18387cbea0ea870aacb25260a39968ec0bab453b3ce31ac3fc4a24962f7b7e99fd7e7f7af8545a899bb075f7666883a2f1c601fbcb28873d6e8e7e9be277333826c569f7b4c8ad6e7b6b8aead73379a8c689605f27e76bcb7b5a4309b4b1c0b13e1219097cb470348bd2da5f06285c6b6da40cfde42b8a7da230c8dcdcf3900793757197595665d361680be0b27d4ba6e83addbd7788f5d0a6f1d96d3b604e8c9cca7b0d19c050c1f0bac717f1b1e97ea7df0c3f8272990e9575855a456ea661fe6b86edfb25d7df4e7118e20c874bfc11ac655e492bb3014eefef38e7d0ce6785ccb3e4c22b68db595dd1dc17a42b98372434921cc0af24349265c2fe88fdee47de415333942f6d8a73fde21631d4086c3ac7f61d3cad6bb88d4f181953e6815e87dddd7e4f8401499776afbc3672dec931071f80ed3d8874d68b8be13200c017e1425831f42bee84aa2ac2e4ff98ce457e865aca19b6de3a93f07ab5229af3e57922b1f455b6315c3ce7e20e9623d8f9f96423b2f22f51c876317362e8e29e5c2e260185e0f65dc862fe93a96814f303df803551f6166d61406f5ee8b67f78e843b3c1c833ca21563f9808e3b19cc4301658749fc13083bea4b52292c31d6dee6d65a536105184947dbca749a7c7cf4865a45fd1522c10342ff20f63d695704065367e27e1cef44dfd5a4e2fecd288c7f48d861215f41603a5efb8455270394caeb7443a62447ec4108c634b619c1aa1df515f0933292e3549d429ad5b2cd7ff9c7775c5cd9b789268e0b8a676bfab9171d3709a718d83f81ed284c7d6ddd3069be1b7b87febb845a42cbb0e595f40af5c6da32d0242507039a1b6bea5ee69182f330cf3b042ade513771fff812cc42dcd5475d493a139a6cab2581d05c899325ab9e23c987226a7aba5a1236e14ab66366762ed8a504d3ed7e1ae5c6eb0de617d019d0df260482df2d2f0e57af06b17b4122cf520bbf0ab614679e2fb091147954c930754e2c0e377f695181f6341d42e89633e4c9a0e677058eccae46f888fea125739a1bc7f52f9a8488b87a82dd611bde49ae936ea4e7f8fb9d6d1c85dadccf5be076ccd0c33ba65f2a279e966aa6cdb824a307402c2b115517a8c19bed20f64e2506d4cdda3f434aa3dee5ec6a5002a3c05e108ef0daf006cbaf20a89ebda5e2985a105f8548403f48703c00a469f8b53408ba89fce3329258462750606395130693e293cbaa410bf857d3afdb5e87a6f42c9a3cd117cd5f51af93f5e99167ca8ed565fab085ec86967c3f49e16e91426aa2f980a6a7a0e10b80e21d981877d2c89b0f69c8a65035145dc3e4d9683621d996a14e5b1779dab3c5f364bd8a5dc2697409251dab3f74ea8e8ef80822819c94779eed34576a85708d759fd9e7a92170d750644f896e2c8bc7545b55dacf96119c5c782001681585bc27740051c90c2d6b5d1c2e73699a3da73605c2708e15748acfe010b0f84be53548c2ed6b3f5e8e64de4fc913522a64c1e3a59ef1fa054eeab7f6fbabf9e9f33022732f54b7ceeb0763d74a4f971d4f01fd3cefedc4953a8547f6d0f6db762d135b586c164e599da5066ad58bea5a1db317ec8464c9d5472d8826d2e64ed8b12e92e5dbc191c93dbf2a89204f56c80aaadfffc619e0ddec6ec810174e6e999063ba8462465a0696591a4a229a0f556af08be065dc3dfba4810d05687810c3e36e1e0e7220142485bfdfc66104fa69401249748568da8e095a55837e7983af48f330bd3234d4f6bc0e2c006aed4d3945bb95ca9ee02d70272882ff4bb0e4b33860385a224e24f7c3e694f924387084e1916bf71ce4a68126c45649772667369584c046dddd1aaafd484340dc950a993b4526380d1f1119b29e3187675f35c3bfc5eb82cd71669be895a6ea178065807d0213f89d73462765bd081482988407966adfcc7b5cd14c90738b43efac73f85bc9fb83b8573b8eecea31f4bca2e2cb25f458278b0017d562a6473a2b971641ece0a7dd1fef01b78d65c7ab59b2e98d5775bc9a534d95e69e1544a8c5a65df219659b6de3032a06d24c1ee27b94ca6efd6ef537237877691aab2d5a10898aea84bc5df2daea4d30a7040a51305aebfedadf3711115f25ea144dc4bbdd90577c4bf548aaf291126d412d3d0ec0ad1ca821026129e1a60285dd051f5e80bbc6440c90076d05b079eb4437bcc32f79c6cc9d80b9a0a2b4d96b5058f8ea90a4cbe6a5f6dea106653a77b39da22d7827ad74fa1fc37766c391742c3fc85a408cd9787628a6e6cae56163dc962eda5018f8f2eb86c51ddd149974e5994f43f546e8d1e39f850c4584adadd0e87b14873928d4fc32d6a84b801273d70e5b5b5a7d5de91caea475a5fc0e3ca960c9da2f61b6cfb81befa09ca33eda53bebd90ed793f02db7c967488355dc8ba732d1c50a378aedd7394586eac7dad21bbf5eee154c68b2f8c4d2ea68dcf90951062b199bcd42c78b42a613fd0a9d81497acd1b8a762c8b61dbeb9835866e43e4c6d5058d1105f8a203110c41e11d1fcfb3b816e3b96ca96cd5115fa843c84ed2885ce1afaf8550dba857ed388e993b16a72dada4fda8378e4687848330714817d242b2e365aa455278de584a3672e28a2d5e0f10e6b8a78cb785a1d6fad823c948dca8fac827ee7b6dc2e2694cb189ff17b6933a85a0f283ebe82b4dc19ed5b6b5f55588af4a6be2de02da199a903ba143beff8b0f656a82e2199d84ad3e6387e6d9d3054dd927d622e2757984a618b8c7575e25e83b5f352d94e02f8b75fc2f752c13b7208ba407a5637ba0b48220279033210a4430201de45d0e8f1a427fd2ccee5030fadb3802d8143de85e2f2092c679c01fbe80596d61d3542fcac866259cead2774dd1695e53e2e18f8dca68514e0d2f679af97b0f1e87bcbb0ffdeadb1e1e798b06d8d6f3eeab6c6e0fc933b17f2d2dfd442c681a1057207ca53109cdd541dd3d7ade73a56e3b1c94ffac3d97e0a40d9c890946f0cac7c7b5571fab42620b751310ce4a34f21b8357c2098a266ac29779a1c28ccb008e86b0a0db3f80816a13ddd7ef69df4bef3609ffd0ddc26fc21acb51bce1c3a0a5b97f27c5102f54ac23430bdfcbaf384cda772026037f029f70571672732ed4129bc4b851d184195769fa269c636aa00ebdbc94ca91892fd3e7d2354af3663360118ed331d9be7c2853cbb14cd9cdcfcb53daf3fc9166d0256dc29b585236058ca489cb7e654c35e841317941cc62c0a9d0799ebe335909293818b49a1b8c8fea948fe598f334c682cb67b61171a928cc711a11feeea57d5cd1cc2d67bcacb3af110237b6395140c7e2727348e6a8b98f6cd8750523f7036be21ae6722a72861895607eb10bfd5aa9426a396f3ab7b6a533cdcb58b52d7d120e96516b42c0ac610d7a455cfa29c5afab1df24190c354eb920f5f3ca67e5ec2522751dc9cf7ccf4c7d769554d41ddb82fc8bf19f77004d793f40c79054a1b8ffb74031ddacde94205eda94c81af42ae8a5d6b9b875b06d76e94fe0bd50e3086cb269709cb072e5b0de382cf7b56b0d1e0b0f176a8320545bec93fa504109e858423b1f5678ec318c7f4d98f55c6689ba498cb9d91edbab960b55f167958644a917da2fb53267255b9748cdc215f5bdfd5f71c055bcc0faa0e289de3f891e2511c5e4afcd28b0d3f78efe203de5d7e2ed370eccc8e46df98c1590b0649140db0d8105e143e5ae1bca9e2481b8272a21ae8380a41768d28ee584752d05c723a6822920096c2c12ac47f7cfc1fdd12150a8919d63c6cc2346f262598fbed659ae2a715f39317d175158a97405ac2bfd0f2ef74f31cacbcf7d2389480b8634921794bc16704cf10c2437acb18821eb301866b0e0a2871d24875a4202957f1d4708995c50581764ea0d58946248604a8935e3289c84da68bfc7bd771afb2c90ad983585d9634fa8605f75c0ccb048b6623b992a3ae691f4f84bcd1e328e353668e0d3ee828a3f44c05411b9f5608dbd090591c8803cfba5d4045559029b78380fe13779a6068cebe0d34c456e667fb846838495c8ed8576f14c750aa650551d36086a5a0e7bf2ce6075ddcbb854afbe56762f3a492b6f6e86134a04432695dc30f74862e54dd9ee84187a0c16321516a01b9b45576a3b1831c59dfa26896521c6621b36f80ead22ce5f8dec147e4d719b61beac162eae9f3a4e602b01f08e56007814fc702e0e39f3d203475f046e6d478cb1a640b9c8bc6a1c43ca4c697942a952e014a9f877c01ba2be0329ae880ec1889d90ee13c28309746549ec97799befde0a82bd8a93872790b814254ca34148d346e8f208915a01ee3d98dc79940e0d934014205d958dc02db48aa0c703e6314d5a60c9b40f1bfcc28df0fa895e4435f136fd0db725f4b48bcfec9278a095dd09462d109a550ae83b3b1f1d2c1a85daf02239c13635f427ce691142fdce6cd1062a3de16398cbb09ba15a51b570bb85ab9d20cdc967f061cdd179ff69194fc73a83294ddf04bc9588480427cf27a14256622389509b403864e17800c2af6fa0049b4e70cd6df773ee98b98a5344703902ed75509a2eb4c2ed43d13924e4415f5ddf64b4e6abb6113920287243a3b9d4412967428f4eb657970cbbffd717dc7cf581b3bb1be8db5f5fca8973a4854ac231d6eae7bfca3122327412021d3b65b3b9e37f8744f316bc9af8196bdc92cea2f63d87badd710e1f85f52ba22b49c62edcc96b22a85bcc2afa7aafc247affafd38a1fd8c99d579f8d64526d590c983d229ab321eb93eb0133b5d586cf920a8084c3f972bfd20eaa847d7060fd49f82c225425a417718a88a64d80cb273a6aa6dbfaae853e1802a663324250d504d5b0b50405271451958b1caaaa62a1a5be46933aaa834c5255e176d14752a7a3a99a0b3c7ef46f4ddd54d02716966b9d9f0e237f40ad9f4a8fe56ea364992d508cf89af0934c9ca7702e39f6738c491c0e6a6a55097683d0ed88fb589d2c73c9edd6c1df1012c021e4d0c4e4cab0de326fa65c522bf8d20b56c6f9ae61222cd4e1a97b1760881a268c32f0c96678be07441de3f0a7a84b014de0fce0d5aaa93ac18c2470aa88228447dc646a80c4edd377a5f0f1e80eec81b2721c3c8326c8d6bd75f690d44aabfdc3594c138a10a0a8be4a1fe95482bc673ee3509dc9821843be913e93c31b5ac05156408bf5addeb7f31033204d09cda88507c57df0f82c3f5cf9202ec4140acc6c86893a8a7962b928696fd20848968da5e171b3cc856f7a5adfef42f026f0b0fdde6d37b10c6111409553bbda9d771c5f012d508e56adb0bcd8d804d02ee82c6853ac0cf610ab0e9c25718f320d8f0fb10f9a06eb34ff9b280326939277003d2fde7c31e049b58cf3f08c2e3843ae914e08310d54bfa5d1a08dd7fc1c4c6a066f8f5af010d4f0341ae943f617819b0c28381d03eb0c07e1acc01a8150682cc17aa5611ec2244ed7f20ffeb22163b402dd0fe84c74a108109ee1af1830920380f21dcafc8d4e0c74c6d60a1d620e94cccf19ce00fee50bc36fcc0637b00a9ee5f310460c8dadb0b98c13cf0252f60803d504ea80f9e3f3a2c197e5a0466d1ec03563da74fb4050a7e7037bc490196368c85cfa80ff3198697fbb1811fd42c39cd6613d87cf80113f62566cbed41696c2f1f6b7409705249153d88a3b89926975580f986b9eaef057a902609d61874f9f00008ef3ee94406843588732243627cdf441cff984971d33b1852073edb1808ead5d356d8868fa7a80337b723d4ce506e1db4098b98f6379519330487943a15d4b992ed152873acc0f93b57ee1c94751fbcde7ec07a26d01ee2d1375bb31a1404cbf69e4a98788c66a802a0c915840ca5d0bb89a1dd77299e69378fa80893789693a482c00629144c3a68dca8235210e81acfbafb4089b10b7899a9765cc002f285ef2ab6dc8e892b938260de2a5cb2aa439ca8316dc56d30872aa9706d7e5e69cd84c00a5ed31f36f2d02aa02a9091cefc85c4bf3c4f60ad0fe5a618b92490deedfee968db8f6a1d49369d10dc993ef41db627bacdc94227c2ef3e7cbc5e63f7f7ebe00319c28e850b648f2ab31917a1a0308c448aa4254879057316d23438ec9089348c20eb79a177d6b2e3763d67e2e8cdde1fba2b1ed7457f1e15cc0e8b04b31cfa78c737538bfc971ded27ae4ec166ac5ce4698ce7778ef83e40495ab772385c1deacaedda7cba901b28ef0520a1f813e621b62946488365a65f56f8462c142e5c0628b176ed3bc585a495898c1abbdb8b92648ff1de66e5105b50b80f144c771510f9a85f324c9374696c1ac332861603b2be99dc62343ca612d7515f3018b7e0e0519c1a3e34e8a5be604f358e5b5b9c6140dc70ae99ebef62f98fc8aed6f5efda54eed7e0962b021beb94070cf1a5bdc538c6e4ac6fde62114a4983ed49e1b33b09f3f92be5c6d3fccc02a509b4fada76d6e9d24408212bb1bfca2e3331fc84340a40a1d6f10726dde1004a85f40e0219621f058882d4f706ff0066c6782935d9dbfd4558f2d5270b1db36aae4c29d2f5804858c1a922a0f084be0f247fe173e9d4da7b7d5923ebc5a36e82a3af0602c1a1a8092c8d2327d15d8a038b099b8b7d4a70faa6dde11d21e25803fe256e72af77b06170a350ab5597571a3158cf330313a4498af9b777856cf0ba60ce5c1f915651aa16c5b81fd19ffd409d987b786a4d4987d812cb126c392cd96c2c1b6a0a02f5a043200eee986c555c8fee9a91e3af95c34008d60119e81acf5011f364cf7c8a28de10fe2ce07027ffb33b39a74c2400bb4736eb7812a6fc3dbfbd42ea416378f351b4f54223e29ba372047cba0821afda7d49a85a8d233205a8b1d5c6c98ac06256e43b5de8d496fcb71a4e091d2115ced9460de3d4ba554238d9a3458fc198ade45740baa5984bf852113ed4d7f88b43ae415a55742535cffa90977ed81d3be08d1c61231372e759d30a9a919fc6e0d90ec36399bc94d490250e7bcc0f3e8c9c2f19d15461bef1f8e24ead734a9b8f30511ec3284d488038911d88a39ee8100173d4625b7aff810b558a43ee111c6547257e74265953fed9eb991e99373aee18c71b5c4f55b64960253864b7bb815f3ddee91824b7b47812e7476f640ea7f7e62bae50f33033c13bcc939073b4bcb2a3d77146a9798d1dff66c8eb84c826b544072ae17af5b758943ab844fd30ae5497bb5c2393618c0a9ab703e416e7971acd30788105f48581d935d342fec5c8b21a05dbb8d1d06934ecc182725597cbfe76ceab87dba6f9857c5976d65ade8b3452efa31a9cb665c6d4fe02be4146d46199c716881fdb48e3d68e97884db9352d38a7148e6c3eda59b4fa6ad9ac2de09fa8ce246e091bf856311fba8017e3711f711679e4f8294456892e3d202ea30d8e29344b3be25c251ed9677fec365b216dd357d1da63604fe2e479256364acf2bb183878658b2df08bfa9666534954f083abd6b42aaa00da58c4f7d6d7e26a5764e32e0819ebcb9114366c3bdd15dddfafb683a80f4694e5dcda1048c52500376eee4b4472aec0a7cfc237c54340310a3260f0c04e0ac304064daeed417e876b4347b9a290572e23683d0530323b11174ae8a2d76a49f05a6ca8395778b6b81318235ea26aa23c4cc8975a41c69a44c52b84eaa8b9d91f918d398f0f5e33f0051f51f600b3e50c5908b9c625685552643b9241b1483b8abc9b95f4a0378c64a55b84c8dc3beaa2a11ea5e74e7a767fa57f720bc1d5f287026a7b59c69d95d871241095c3730d0e0b077dd42c2a918fb534c445edc8a06a2d421ff1af7c82263223adea3fd1542cf62d5a3c0a0a20f3772db7e3699570eaffc14652c08914b87d008760eae0f4260a9d5335cd5ca4d8cccd7472cd17cc59d340111087774f578a34258bb1b41ce912c4166e383e236bd3d8520cbcde4f2d0dcc351bd3b23ee5b409719a653f5cfc0d1f17755bc927dd33db9c5b095d068fa444e3cbd25e86018db4bfcb97e3fae3665b7f21a2762454d96c34f8f7436974cdb43fe0b95148b93868d362a33c7422dc584560e31c91a0e2088f3733555e4c952b7291c31fe10063acada0ca348edda8337c61a962c7f9e3d13176ef9a30c6e41b7ebd4c77d8dbb20537d803b71695f3133d41798ee52f5daba7785946f4d0f3e270e1190b58ae6f86bcce58c1d05a93bb6969fb3d4ccc157bc404c707fa6822ebb081857a1a27e3df2ed30eb7ea3b90d3ce807d6cdb10924caa43c74ae4620b578b50607e73484350a86ce7045f42ffc01d1710298ed8b33e2850e62dbde3ce049f182396820701423ec4fca40b43a010b23ebe15a36198b013fdf1b699e39af004e16099cfe42ad49db4bc543e8002333af9010d3e0e813a2c33728379414ac0a5b48d9c66aa578c3abc9c49dfc5e42e0488cf9ad57147d852c5c388a35542f3af832ccba884c7187f3cdac866cd5223fc5504da08334c90ecfbeaf0dc2181f4ac740a856c2fe899efac6ae5cafce679ca30392bf58864d85941afa53caec00719fcf4b2e7189ceee86ba9514af6378a2ed344b024425a27c306bac7ea00d26c210b24361524f3c80c70ae4f61b85dbc8fcf68cadc225f7d2d79ce6cf8804997d3e686131efafd72a6b72e8778f7da78322b2fc4213ce6af25f94fe6c6ae128176cd782815f4b9ac8f9910cffde8a7ccaa05706abe97e1a2f61bfe538c3874a93f2f4e87af68d31559d6c7eee5e893b2851df21cb9352be91b180722cd2a18152408a77dc5daa759f703b8222bbec96325575a5bebbf4d2a385567f6196e74c89148daec0502738123bbb1bbb745449cca793fd27cba302ed8d5ecb60e1a47d6ad5b25068ad6b424e99790457498a30db60ece46c2482a779faa7556d5aae5500ae1b2eca2a916b6d1e96cf8836db37388ab9e0237c1f9c00fda03130af9b4e987f768fac75ebe1fa8c0a12e577573b91f2dca9d92f23733518f69348f4591830a2a218fee616122a8fb79a2903b8cba0b9a8d63282a4e1aa5a16c5b9e4bc7cbdd82b4ac7ee2eff952cf41112ba9308000fd5479b4dc20638395ad96b99d258a88ad2f97432d5c07ce06820ac59b5acfed4a382ad879240fc1251817ba3c97fc3ccb9133d0bb03b59924dc52c2e47780f8e805e92aa456c2181aa09cfb5d2e476c32fc6e71e1bc9ae18ed2666f09eb6baa61e90ddb0b15f72c043c80c9b842bc46af664ae20822daba8435bec8cbb34a187745088378a1c6f15192e0a80f8e48443247e28da48056c2fcc2baf5923952e6a13c39e56afae2a253afce0b4540800b883fa2a83773f8fdf353e3aa8cfa842e5bc266f16bd0337f858569a5ff6346d288c1d09225ecd812b845401895053895f13d779536589c15932fe7e69398e4f3dbf46c831d104644147ef3862c7aabc955d89fa942b42eb3bec2194a5285dc7806a37615e90af92367b073a869a03ab40070cf56c18de8a90d547c58fe501dfd7a3a6828bb37c19601ea95b310c3a723290382cd70ea96719f1495506f6db615a413f6003462f7434c1169af758bd10ddb9d7da9372515a60a6290cf342952afe9e7be50190be0a3570c60acc33c61e01e0b27f732598751fd1961b406bb22918c85bfe481905b185b81be1096cfbeb42e612d6c93194eff39f76af228675cba0f3be4c8a6edba96fb2942cc59d6fdd8d017194ac9df7489c764130be35e86ba76631f5ad93dce56ee8e9c89e35648616cacaa5ee36acb2a464cab5fd8ea5061c50b0fe3064ca05f9c91c6e68c2824787b40ffd5c025940d8beb6fd5efdf4cea2e7ffd7d88cc923b820e719927d1d5b7520c10c6590980962a9a4ee3196e0f23af81e61552f9fa5502492f3b2961925f78bc21b124f010c478b93cf88707f0bd922d83d3d84126225b530c76c3387ec47cfd8ba50f0fa8892e5588ea2317bfd4e206d9badbb1343c5880447083a2ec5c1270fdc6fe910f3707eb8e1d2f6c7c32521ce5eb72149089ee9c5de8c5caffccf3658170040d10d231cc08b6462fd5ec925b2faf96e578f92e48efa1899b7bdbe52ed265a32ed5b4919b2f798d04fd41132e00a46ceea5bb720f9bedcab144e753391616e3afc1bd2eb3819495fcc4d2dc9b5842f21dd711b80a4147ee7b4e12b70938170b93deb4fb5cd068b67c005301081cf90cad42f29a1795f56673b52cfa0e8d4e4f790014be7a9009e874fe2d187e51fc4736e142b831059f813a7323e664a2c0803ae122294f6559ed98b0b75338d12aaf7f5597b10fb7f159959a30cbcecd08c2ee9784e2c184f68559f619c28e460c49f3cb63c4d0f627087bdeb58c889fc800fd05b77dd2dcf50cd65a59d7d83783233e04e0025a347ce273c8e10a62994c8bf9e362e0870dbc32d0430fb21e1710e6c39efdbd3d1b185110e57ab305fc1db0793f252a381b273c7154c541d6c1a38bde072a8b9c58f1dee9afbd08f99534ae32c7c84db144faf80b01a54114bf454c912d200a17c405d989c35e134dc36c29d60890a2aaa36c601a9dcff054195bdad2a05aa81c5f230c1158696919e01da10576fc8d7222520833171a4afd366cc1a0083ef8c3866e2ed1c9215cc54af4790d0d648958b87314211a5041b13593c0f12aa5096830e00681a6f2053dc03d6fdc86ed27534ac9fb6fc889737d104aa293f618a219d5c789b1641f471306af0fb62b417526f3c6dd584a76ccac8116c06883b53e1ba3156de1dbc629cdeabd2e6cb04052f0da1888b29fdb4a20e8cba0a400de4789cc3b063de7a870043c6bbe27cabc56e87ad89c07d3f07c9aa0db3e9f1b18a0b5e1e7c3b18891ba6b44867499466baf9bd1f89ce2e8e98d948ce8911b6cb80530faaee0f1a9cac1829c6866a103a27bb0f6b586424047dbbfb37e57b3b43cc7ba2e1088880f51df04ca440bc79be2825a02e434499ebc4643f6d0c758bd8f7856ac7fa577b5fa12a13ed31cf11fe6c4e0338688cb877748dcb5ca59dbe4447e05c9f5f0dcd1d1e0376dbd61d59bf0f11d4d9cd2e76646610718339a6eebfc0923033319674b582df42151f50dca19b4cf48bbc2cd4150f1338e53b8e552cfe7b71a681f9227af90c5de48f940b55b37ea79a9e9f22547563228117a615a453951544b853e488f65c0198292caeaae4df8f5a2d1f61fb094172bb5facd0875a56df1b333375f1e6e3c77ebaecaa51359f6540ae6a1179cbed494a22b26fc6f2c7523c195868edf5fb3aa8aca1f1b4f81ef0b4d64da94e32545191c2618ccf2654e63d06906eb74163bbd71a707f174254f337468b0fbc9da15a8d5c5751abaf1b7bf67217cfe19d5b2588204b564e85bef4415f41c1ea88da677980599aaaf317156b95184c2b1065d34aadc28aaef9d32e4fbe0f51eb2f0fefb156c316a9469addc6eaefc9f2e453babc556e301ffa98fdff84e07fe773dd78c3c17883cf216b274f92134d21d0e943d0da1584b7a8d484c2bfdff07d07eb13b41c1beef6c256f8f3d93d27e8b72f5de3e1913aff5a85ad60b19ed0dc655f946e22d0aeade72f22dd6548ded847d609684bf8714d870b6545967e8569bc57008438b54db0919c0e1a3bac79723e00ad0b864a4390607010ade342190e56ae6f83fd351b42ff64292d7490d02db92039ef0d11ac72f450ffd55999b7fe9f86e3a98351b02c5de617e547bab107b513d74a986022d34733c3822735594cff29ce60a60117a1466620853bec23a581763f8c5c82b44218176e3ba81f93613feea6a952691d2ed8cd91cfd95badcdb27db80c1479c96f91312671283c450cc6b1fa935d2f85e8ff71009e0675e58f51144617751de57130169da4aaa0d0de1af7108f4effbc897aa195671f7d9ba2aa039fe810a989aef093847bd3c74a8c65a39351bda0f55ea756405f7843bba49eef9b8a406045551079b73e56c2f36dadf124f18b351d3aa7c22d119924c9eefacdaec620abb365fb30d55caec17d4bffff655d8afd6d42b62f7a05ee6b4fe23d4c0da2a87eb9fae24905b39b01b3e95888a7323e2adfbb159cc11feb6c0f1b79b32aa2a56e06286249a8d390200b13ff8fc65e1b48d301c3abf27f8458b8e8339dd131035e16a2a7ec141e41aa0b4372fd1ea75b61b4399691ddc03aefca62c91eda8e4aef8f1f0f32655d976989d7614de526126267afc56d53450bf84c680cd3fc7fa57890f37f039ea68f678ecd7dfe7dbe9339da3decf592df272fcba72412d88ee4882f3c588f214198a1165a010b3691fb8068518193e35f6b1d68b82701ccef5bd71bccbd118099c2fae0c5133eee9a266accb6f88eafcea93a66cd21515a7b1e18f63cd2c03772abc1640d1f041e0ed008e37c0ab8e8559af1f018f9dfee674815cf3a1d41523762e8f375ad5b7e12a2356417f97757403125ab33e64318e8341cd863879f0e539ad72a4b564c049b8eb102ffa2cc85e9b47e56a66b5c0c2ae8519aff21490bc41613313a3b19f9d5cb4707ac4e969d6589da5b77474de383aeeed47593c28eb620ecd107f0b5767de3169e3a19b1ea5b2f74360fa20f5602611fc63f18584593b415544a7c0000323cfdbe17fb6011429be60ede3dc00ba0c28ead516f9f8b2c77268403a8dcc7a5f0fb5d5aa84c81a16daffa0629efddf17b6c2e4f7318fd2dccc4ef35ef9a2c31119792feb14fa3afda65d220dac663650e969b3c8a707d4cdfcbca6c2e92f32fb1f32c035ff41741b5e26fa227c3078514bab072cd2abb75fefbfecd73476e10b2a5d78fe740b3313d7afa1a0c07720876812c106eed1d6392ecb08fce2e87b3bdca766ce41cf927b038042cdbe7b0aadd6c2dde036bb0f88889c01006c457ea070052e9e6ebf744a507f9d04e5a9553184bcc78213845dd9b3148572aff50b3317135fd4485d8c7eddd0b2966e37a4275f00da34b88683f1ff0c495da739cd333da53e0e4717aa68522c9bdf6bbddfcbdcbe88b63e421580559037754c8dfbc3d7fc84dfb628bb49d54c062ae628d1f00cb0c6ca70e4f1acb73cf25ad6e46bdd5ac4207da425d207cf16f2609769c8619a60e4b126f8e3b2a7f02bd6007bb4a43f1fa71261a80003bda2b64c2a4558b29b00a171f343a2dcbf315f00fcfe3b4886c1a73bcb719d99f2e144c60e834735e6d1e06b7e183c468790984f44725793a85054a5579043365d7a04798a0f0b12cdd0daebe66e26db2f17e8cfc71caa9312c9c4cb9045e610fc2eb20cf632d5f0513d5479d2092594162195da842f65b66961e268d18171a1da274fd776c32272f517830b6e04e31a0662ddfecf66017d103455cf20bea8fb66f95cfe5f1f67cf89b5b99d890fcc76824c31b96130dda478b4dc0d33023e7d512430209d8571792495d3e847c2d3711a0a3e1c845be7b5281b32ef66345c600cb17c99858d5f1c6f1ecebccd32efb2eb5f08b586ccbbeb535fb1c9e3023031fde82d6c9e802cce15c09c134ebd9511d9761b88c59c53491478fbf81d3e0914c158f2eb60e6482aef9df095f4ef721121c6934016dc85c7e1daad30d8f97dbb70df947ee2ddb01631cab97076557d24b29debae03f372f52047bd3bdb5d8f371ab721ebc4a4f982ef21efff3a818606f8c7352a020b23ea4ef3964bb5d558460069480757d06109cff3554b2448469c5a02693b2885c981936f41df4c9a5a1b15fa4b0712688b122ef7f4c8ebbba731b95e80798ff803ba4e707b2624fc14b28da53df9952782183b18c544829361850c46b5ddcd4974b2485105ca381f3dbc8e3d6aa6f3fb0b23db07c1152061af8bf3aa25ebc3ddd061d9311538d4dc01f4ead8d89ca8308067906f9bee197910d3f954a8dc8a0c41bbd6b07ad819f7cce4b8415db1ff0ade9764f15db1250ee5031d34848da1f3bc6d533b9275a0b50f7687f5c0b68588b0661f87c53f535d7bcc4b924fe4d4e490f6fb43fb8add23f85350157a73efed3e39c4465fb56cd24d5b42d63d8f5c5928000fe9834b94319b2decd5c6258b2bc342a81f51489c0e91ae46016bcdbb2b257ee635499b63bd48e0c1bdb2465a97c7bd37621c595536ee64308316741945f90a55c4bd8f3e518ab6aca572341c3462a0c59462e87e903999d0754b6618473011441e343128736162daefeebe48533891d314770aed5bbd38d4404b1163890e7229f52fd26cc65186bb5bb8c2e64929122308b57e400b23ed7ad142dcd2a005454ee5e3e9b82fa0dac74a9c83f9f948c49e28e47e6d1ac5e8dff1f036db8edeb9ddca7a240873b3073f4cc26b83f61deb29c90d052f123393e62621630380c59799742d97e2c5c34c29b41d904223b957925c98add7e903191fa3c6f88b377e67ddd7affd83af5cc20ebc7496e8d3f0150c33c885296e988e1a072bcd047fb186c9de9a2dbc23e35b9b7bbeaf9a32b04203e9aaa96f85b4ffa671b7a705a176c2348d565c4e8531c60071abcce50056e76de162028ea04640f4565fe79c648bb119afc2f4452132b38ad282ef86323de18c4787fba594e9429e2b94307cb42d3df0c235697a5e9067890950793ce33250ca577dc61abfd02fd99e64dd95e1ab3220e95fdc00a33ec587c31d92e8f4d0c34b6ebff204c08840898867953aca83d2e61250bb96baced01a1990fd2e7bbcc6a78c42ff6b777fa3a67398f00f7b4b50f0635ed9799d0b7e71a85ac8fbfbff8f0e853a7ac74d92156398be562cc72e759897c8f57f7f12ea7e1e515798dd384a6f58317db4d1f7242dd672b901e07edf62da4a260f814514211e602285709d1411e3dd5941216816ad63136b4ab23310f47f07d22d513561700e6c043f063d1249864a097c87a59454d6ee2e106f6d03510f86379e5db29b0b77d57a7e1833422aee5b38d26044e929dc7a6a4e5495d9c7b4a4b5a4a93b76c629f5025ead632fefc4440fc010e1cf54cc9deebc56c37403421d2ab9b6e3ed1023c74dd3138d6548729ce61293a020031083b781bdbf57f23b621a00c445e89a32afc956cd4561138965f24f60441c6fe79dffac2da82c229934fce668435027fb88b7a23bbde830ca6c3f79b4ae88acd87dd7c399d9c8fe09f1b89bedf385a4da2d4af0e4a930a75d8d2a6172815f7a8b09c2ba52620cc01a1162a2ff7f655a702a14fe0e4f72737c04e8b4f9ce59830c475abaa18e2707609bc4dddbfc9a311e542a078c651b970172aa7e240932490292d8d03cb9fe38d469169c38206bb4388b508a711755ef7547292d66d92b83a91d5f79bcf048653c21c354a745088afaf10fc92b6357661de1063655aa94e004b4a43a18dc1380c718747b842460c204b0775f4165bc6a82bdf75680c7e1792ed08eb2a08d76b16c574d997b0ba9e06cfd0c0615845ddffe38bf23989b8af2690bee3bb33df50a7d5596db69b242837aa0e8050ea8db58a5a331222828a505471d35fd6bb61c2522285b317b9b8a4801344e626009d2d46b2f9fcaed3ab9478d84966d06b78014025f8fe3485f920a750d6ae5863b4f046e608926beaf32a88a2c7d884ef7b4afb99265e328007248a1d4ba2486f402098032389aadc982542b70adb7c490d20d32a23e8a0c44981ba04502f32881aaffaac6446c84e41c023f7f292aaf2021ef04064f760df4ccae1a0ba3007da91890c38aa5f042539c8f9d31fa806817e9831bb4baa6cc9de0cf7c65c7845fbaa89e53a4cc95ca55590fe07fff9b126634cd428d92e1c281ba0dede788e29cb0f4aadd6d3e6a3bd65289b292bf48e9f827403258e204a1ee1bbb2dc33696d18c22584b820d6eaf0e6a5d1cff97757c4825e38329cb6004e2c3ee5850d1c3c7b80b1fee5ac60d358e1be8f63314e0c3953fce1bf4df83c783121a40aa78695f8490246583fd811eb4e09b6c6a3bc5877e91637bd03ebf42cea8d1304a13667ea6269c94f4c64817ac17f9cc94887ec8bcecc43234ddc19309d556478ea690391a70e01e146c74b6442177d1a82a4fc32d77b35684b505b5733bbd67a39213053fa0e442253a811657cc6853c86fcc2a5bb8457744a14cbc640b8b6b58d602188d1b0acf89af82b86c1ea0fffe793c43b73875065ab8545a8b4828c0ecf42abc03e4a38ddfe76eda26e02692db3d57d76b24c23331942ab71265a4e314874605c5ffd1661ab1b39bc868bce7de59b23c9bea1b28a7bdebce431384c06d8085e0bb8b3bcd5c654f29ead878bd48f1e1e995bbcf2a245c82db6b59386ffc63c46fffe75ec079a59685316f6b18a1d2e2dd365b7d43cd7ee5bc8d3370a96ee5e53105c82f960c92670a2ce5f653472ce8d6fc01db7800ab320a854071f25ea2b5648c2d5b11f5969dd60d170a55d0dba1851f384e5e91c73cf09a9fae03cd4be3df1b6688e428c19fbcaa177d0ce0c1805a8753290833e6a826c71fd47cfefebae398e81768d9a4202f272d25a08284cda2e1a33b13c1ea05aa550ed929cd03f5624c65699785b462c641b25ab32a5d8cb07e6c1a25ba181f0be4d8d85233c7c6feb8b9352edba58b01ddc8fa667c319187225c410e52ef4be0ed5c8a03a8159c6ebf3e42e650343f04ffabb33865a126293197f8b0f93b435c8774e2b536aa4eaf06ab1ce322d5ab96c8ce1547d4a0075d36afa81616553cdc860275be46af824ddaa7505c4e6bf202d112771be78cfc6e52e155a75529dcb86cc003a87e41f16fe5962a9c68b7872cf8cfb4351fe192d447686db08c3dafe0b761b7d012e9a33fadc7b1ce7b4efce963165c17feb0832dd7f045dc925c5748a8383476c261e098a64b2e961700039b54b1cb93e75040e2dd5893134d4151357fba4a23af12e565f1247b30dc5eee09a1d6984df2e0220c9df5a5e4009128a767cace6a710938e43ee92cac9cd0c3465d4148c8090baef45123e80c5cec82e73fe8fe54fcb715282869394f663f6e750072693375c50c1ecea089c18952deadc081cb0c873cd0ab125a54867e0c72c4dc2164c025993b0368aab18a7f32da7f433648aa0bff81180cb3f0f9594f60e30f0417920c755ee6d931b1fcb2ca626a2f8abb1d2a4685cb6bd5c5e8f0c3ce46a5f1d6490fe096419b0afd4909329a178c802c226c9778d838322ce71010ce8b5cf1dd8e83c94d00d455ececc86724bc43ccf4e718dcb011309b9ad4903ce1a670bfa771766c8be118ea6bb66d42eb10c17dafb7a0b6011ad36ac0d3ce8e6fb58bf8cf01ad32df6bdcbfb220703c4ebd4c8be9a1334991a0d3dc2c95e4cf4c6eb851d4e126029c97f84186f004c5d03c96a3278c989d9dfa8231ff6f51b5cc327fc06db446820e8c6a62ee90cceb3982e1d9a390a088213a436937cdef0c27ab84ce24f8a6d9a18056ec313cd4eb2f28bed88e3c2aed0799fb5c0f7afd3ca86032a984ac314271d236ba87ebe75a95357a70114b86e14fffd4ab0db510c237aa53cb7ebade43e5701f82f56fa0197801a75ec910c94b5569b2f8000c9a01b4dd640cbb724a714b22d4f471950af5d10de0f7f2f1cbe9fc34e57df534e73e5f62975fdc83a5d72144665aedd155104746b6e0c3e72ce1308cdfc43cf862755825e58160668693a760f32da2abfcc2ac41ae501dbc988b6a418f717ecd56e3d0cc923d8f80cd9579683a0954ec0c3255dc7150216e7aa996d5d53bcdd67d8cf0f65d531bd141f3900fd2e84ff9b9dddca638d19afb4378d9338b3a7ea74ce646b1c7a8f782a4ba3cad17738af03dae6cc4864b8e3bb22936b33874db53efb5d690382ea89d5652ff856063294f10c1db65cffcd8287542d2b8176d39ba21f6990530c772eb060b15183c1be1801d6869bcec06af0e1d11c8621d628eb184287802ae10dd03833d76fbf849389c4893a06365f643d0290b244e1920afa97c3fe589c383065725c1be0e160a22dbe2a0d10b4896ad75f70f01a9f5244212d56a182ffc5d8a1a281c4e99493b98d0fdd79fa517c50a84a183fb7901df07341947353e141fc0ea528a2b24e2b6945d5f37ba8755fd2ca60c9d087c6b56eaf07742053a307e2ee45e3f86e9dc2433238f59a315dd11f402f9bdfd172169f9c899757c588d3c0826c9fd4cf94097c72288051e350bb12bc12c0a651d39bbcd2686a50ae3c8325b3e80a56a2da2a8de7cf09479d5aa79242d5138b3cd336ca1b483c9034fb023a99627b121ff009a9c60a5e569563ec2851f307dec7d5057dbd9606880b4fc4156ccf9eed6fc3f2ac3ce3345794f2e0754ad4a768aec24fc9f2be7b551fb1469fc88f7a800b089f8bc39557b79d8cb3353d196e44af802c2ba5c6ba0871dbaca2e50e6a129231d670e220390c8393a3961cb0581d56a46047a47598d12e90cba641be18a0507a641102ff0dd7c11118f7a90e296cd8808148d67d089d6869b1ed929026df4658eaf2d1b3314314659035c1214898c5b801c135f8eb120b019621541771a74992ea952c127815cdbe66b67827998725ac98b0e2836392a94a2d60a0e1910f2909e9f4348491fce844c7366d8d59c60f292d1e1eea2008592f62035041baf3c620128393488062d517af1a604ce8cabccf1b2a65ba57b58bb5701caf618121c3cbee4e3c08c12e05d01ba3439151f8169ae071e3cbc0d417f656fbf8e43ecc194ac4e925e9a0a23b55b10169e5302aa2b903b4ee1715ccf4ad0371f7928d5ead4684a2367ce200f9b6f77f6707a3409473770d06df414fc4f62af82a63611c95f303ec50a9d2de3681616a1930cf4c69c74a983abe34307386302b8ead3bdba37cb93c0627cd3656e37097a41530a4460edc4b3dbab8c57f50ba246e289758795f39329e7ac137b66365915adb90ae2ef22cb898e6cdfdc08fd7a55656b608be691057c600ffe0ca6cdd1f01e7528c1af89233f44d55bae0de7a2ae1d95adedcd8bb43707e5f0d07207be0de8ed5e69ece70cc0901f28d56c8859b05586536ccdacd2bee279f89c0930b9f62ce0d9dcfc62736a3034b528544a6413a1847af7ff826a192e8af96fb6f2e2c29ce3915836f1c343550a784b461a4a6f991200a0a40f4b822a2e798e71b9cfd6984786a8c3f911441f61e50e36343554a40de1d9fa9bff7bb192de11602ac6d03297718d7359037902be28d202a00e12a2fcfb4c46bf65f1958e78544a525c4cea4dce73c6a5cf9d0d963d4a58798e49a470c428eb4ae5a9fbcdd9e43cc9c0576e47ab370ab18d6267e30710d5a1c0a59ebc93138d5d925d99c9ec8af0748a212492fe2bffa86edb4eaef41deeee0962f0c4a70efc7766e7da3e9d942155e93bb104767045bb32a5188f51cd03699e1839e7fdf3f42c91879e02d9c11e411a211cf2340e840e5e3d621b924d51ffdc6aa9fd55be598e9cd1c62410f4ecd59004149e111eea90d0ec28887e417083d0455cf27991fd7bed08178ca97137fe1609bf0e21f4dec6a5a648444324a5aca042393e9c994160a7c88837c45eaa210d5eb8765687ac1d597a0a2a2f5230c80e603941b26543f5443ed6cbfa7c3df740cf657caad775ef414ce0de36eeee84dbc01b78f6e8d499afd0e88a8d3fd2850585672d6708b0215927ef65e7f12a8dc5dfa3068e07314f835e2d73f5e8b74149d4386add9fb88325b7da06b2eec40c864ad0ee7970b82bba920c1c283139136ca6fc54efdc7f7a90283dab9a75e0d5117197bf455f29084c9cc9dc3c333ff2b65c106148f710277bf4d5502da62df2845080b3ee00d8635a7fe1865d302973a901cddadf425903bba0bc1fa4cdd322ecf1a731916972784b805b593d1a87887c8e36efa786359e7f924a855aa914bcfc02d192e0e676d72695411fbca75f69077c77f4425566f2feb8e36b901c3674a63b44948915249310dea2cbddb05b9e3fa0f8d88f339379cd0b5527dadd961b969c74816df9d73603ce4fcda16f05579b93467a74231caf69e9b5cefcda184e14065a2a98cb1f69c6389a1c7d3f0743c2601100f8abb0c7b553dcebb7d319ff551853698178231d884593900f6b101d0417e8f8603a69145b2645f30bec471ebaf7f905fdee842c64bd0e16a140bc7729635d6e484c0408a93259043b6e6829bb31119e15103783aa1388c45dcf250ff65241aeb63aaa50567ca78b76ea15434290020c04127776fc2349a84f5338fdaf0cab3d68d61bd2acc3b2310f9160c4d21e265d288cef249d6d8840724e553ce8b1aa62fd379bd0c23930715743706b262828319ae3c985470c82b7c559244377c8f40a1e27238a28e1cea3932d6b808997f8aa4948181e66fa86d81f0b987881f3394c21d48cb97248a2398d076a037f0108dcbcc7eb009e27ed3ddc31b96eeda39e78bad00ddba14340bd5b35cbf74a8fb8c66e33fc8f6e618c3901cc339c7e702ed29ad09b907e0d30161489ff7cf098651b6e17a1e614ca17252e20af5486b8c2434e0afa3c522a618d1a54afcc4c31964abc6b91a012510556bf2c03d21080ba282dc20515cc347753c1e1b9d5087fd740f144e5aa947fd5d41eb2985a8a8f94b471fd1142fc9e4bf874479233067b392ff09b30899f56d188a8617999d9f0ee2b2065fa1a8210d4fa894cdddd66a450a42106b82c1ee8f8ae016af9852ff20272f9fbb232fe6387dd7b5fe82a21a4549ee74666e622d0a6eecf1c49af33186043a25cfa08d3525309ac5ee048d66c01a16609db9d95c7b19b18d041e135252a8ac7ce85888e6ec2897a62d3544d1205b6e1f1e6698f2d4a723c5702b17fef98b5c4c80278f105839191610c3bf80e24148b1126a6a408c0b49dac825879f6ae4873795e21a7e351f396797f344b471f22494c0e3ed874540f503be20cd09d7ef492437c2704c158ea97e4ebde11c3f9433d632d62f52ae08e3258d238735139f0bb59d9eb68075be3c55dc1e8fbabbd6ed76462a62807f859e99d22a897bcc591a777f2ff1f230fa37621833d7060fdc8814cd978706e596429de8bf2db5b4611fa7419a235b317bef476ded57b5bc82e62e5802f47c771919eae6600f71cb246ab600b19a6ee3c1a01d4a1da3da5ff77aac9c734082fa2cf64b6f9bb6071863f9991305d6f61e9811c48f8692d0388162412aae7dd28df2b0267e8e0c87ad3cc773e4bd7df9e0e0eb87c1611cc0949ddac4271553485c53163771037b05d70c2bafe7d6e60d884cd22d064a97e601b86c15abdd4af8915db9f1ee06ebd4ffb2ad2c5d8352af6b074133b30e26b785da487500d2965630b813e33b8324430bbd6bf05831bf871214dece90824568259ca48602e0fc170f5faa6540e1a24fa3f0f31a98efaf8efee4da3dc23ecc4476c2e387174bafc500924618989c40ca942666ebd95e0154902add4f3081236f105b786a1e635ea5b868cc722da0af7c09269f927f523bd7db717e8a51b36f63110ffc9870f78f9cad9d48187f77122f9a02e13ffcd20afe1e837183ab4cd21607bbd4822131101ef1e67ef3c269080d84141cb620b48510f469f8f666b4f7f3b4ad148830930654cb4cd25a440980804b1622210bcdba57c00d19c46994bddd5a6ba62b81a43fb6041908a9cb5e5d93b3732b50e0b82d177dad705418b103283999956a579a79b5d7542a37a7010ce4955c78067ac4ab47c812837d134c81f4e9734084d6317d1246d4bb034d0aa791fd60c2092f942c36cd402570dc2dc0cf4bf8f862ca53f5643dfffed6c3a309b8c04f5ed8c1543a8c4f7ed12620f949c49367a72302cfd346a19fe826fac9f6abc4394481fbe545db6b2edc6d155dfeab96fd4e590abeb7dd0fd5a232098cc87c2f112fa8af917037109ddb15b374a686320a8394ea3b241c3e5768a8f8792180819a616ffad318d912d1d029cb4564a8b2f77229f74f6992d1c38074072093051286904c8f33606ed52f4a075e1998d0794436c2c1873d50dbcc823c2e1c706d8086d9cabd1670739c3f7ccf9d913f0e39bf098623a63955db4be7a8b11e946d43a8ddf8e9fe4c8eb242b2a8457a33d809a71b701f76913d57cd5388738b602b15944967c9bd0cb0c65817b08da1d406eb93d96196afa2f252533416d2fcc33842c159e0a67438bd85f85a2ebbba9116e071d688ce3826f0324f81102f3eeaaf84cbd840d3340a045e911b5ed600980f654509c378a018e13ae08e0e4464ad940a860b08c3864b89abee1e63b495fb6fb0a016de1290819efea9d6316a5462962099ee97872cbd017f1947be5430bb41a59870df0040e43cb675f4190b247044e55849a654e26676ed6f8c0314be32382af9c20f7bca216cb9aa40684a9fc9c0352fda8d8bdee59e1995deed4f562ea877e7b397d3d8739f077a40bafe48d3c7bc9db9162489822896cf98e0a6509c19d29825c3f328c05cbd038026c94fde577675362ca740165293c9a128efd85a58c9653fb039e949cd189d559825dd1225d28c0a0dd390989dc4da617d24a9fd8c72dbae9bda7a74516186c37282b201a27c636e99c5cf2074989e5bb60315ea3efcdc12782c0f2c36a65567d25ffcbebb37bdf8de5344b9f17aba7bc8095e4dfbddfd81e3ece33dc0a00550d675c58a9f2852678cd90f90d4e4a0986e5a42fdb0b066cc847aa9bc20440b4802437b2848a45b4ad8a80fe6c7765add90296bdc4787aa3736e7c91907a76610c439612a31a8c388489c38c4c45315d543a0d07ecc2677faf382b3c1f7eab7bb4b77ca902fd8140260ee4f9de234a53ab96d1dbc295f49e172a3be1870e2149e55e749b4105f549a4adf27cc43120f2d7bfc943a3055c27ea25c177cdc067b71a314399ff38b44e3ceae7dfbd7e9e3024a5df4799559c01d799115e8a3241a14dc0a1cc827713746cb8f30c3c7bc0109f1870bc9825660bcb14c069fc3c861e74bb99b91c1dd4897ca153ad612eac9790dadc72beaa09ea1795a7858147c77003f07a7fc133f769dc5e675fddd304947fa99ffb323533ffcc0cc5a342fada9f9793edb8cfd170ca466adcda4880a169716ef937a3126b9e086f46dbf6e4a871b288496bd1c7dc2be5d203e2ae007b925c5eb9125d01c19864ccc92fe0312ba1e5070fcc5f831d828a5b14819a3c9650ad75dc9b819961fee8e748c70233c98b7410bb2e354b1cd0d26e0cf8fd2ce94f123026188fe4e1444fd9c684a831244a12b88575995e3dd51b083a6de6c3c8d4b4fbd54bc5e41029206945562f532511154b5aa00fcd4d19f46d3069b8ef2f5cab8dac61529263e042c12c90ee027ff9dc14f13481516e0ab674cf4157ef48369d3ec96bb7af3a4eb2c0efd0a9888eebe64f7575d0baa6119bbbb4edd3ae690877abeae2cbccfe567a4f690e63d0c0d4c1f89964ea997ffcff4bbbf46039ba180e7569c6cd7e552a44b519e510ac3b90e9a68496f521e1f75998e6c7c917487b91e59ada1cc69c51afa74efaf117fd2c1cd54763cecb1583371f3020efc219ca9f3a90452ac5ae18451d13a3289e5f499a95cd57eb0b1706de90363597342a142dc749f6d08b41091c5afad684cbcaa74aa75dcd46a0724901c823c375c9e7271647352dd7837618ed5b7eb6453d12ad36272c8a3b6e94fcc30abf5ddfc3a4d1d43cf7493c3f1e6d244a955038c0e63f4eef1629fc603b3e52d250d44828448096857707aa091aee090e7f834da7ef192ff081ec1a2d1a98acd5bf4edc76346191910af6f284941836d7e4c3874b4eb59b3c31fecae346b4913a74e56387b4c530d35c7d27968599e5fe0b719667c4b5efc4b430636e7c88d9aa8cb8f7518cd667625c540574fe007b170273dffc9802df6c7f465340d9a8b591e3b6f94ddfdee5575516c6093b77fd60fa2d8841dd752ca96ba739420c024f2768a86ed4562bc564a494e7b3af80893698b339430b12aceb6badb59cb7e858338d2344a17e629c9f51ebeef128f65c444f2bf8f486ef4510a3fe7ac2e1677284dd15709b800ec12e42072204fea962dabd0e9a3086ea75590464b527e3daaf1fd46a7d1658fd3b8d272506ddbb170e814ec72c2a5b0c8647f31ef3baa905f3bad00efd8daa5ec11a3fbc3648a959a4fb4598e634b82dbad860670b52962364dfcac3efccec74a2c49255240d8e9ea78c6cef1845e6e0c9e36fbbc28027c30e1c9d385d131773e6fcccf226ec71fbd15875976f5d001f00d81f0368ac902bae6b27cfb7f0f5843e3b43d819006e046849ae483ce98356f48b74202e9c57c3010a84ec42f48e7e80fa11ecefd3cd78d47d8eb8405fb9b51faf08500a332f13ef162f35d7f396229128362875203aed930d32223a6dec96e546de67a4bc63a0643a55ee2a5fe44308a08c306024a14073c2ee596bb4326784e30b72d71c57037a006f7e90312501ae7b90797fb30be7a4777ec761a4daa075381c1dec1c738c21a3c90fb062b5261b034ab255b670038d51af80e7017a7d233d803d38951f665455f97155348af08aaff72cd3f728036a2d070b9f05cda27402439736d8c3f617af24cc79a8beb03b34ef03b0b8c9b492bb99f6035d27c94ea02ed57603fcc460077562ff6b8b61e07a31b6332540afe8c570fdf532fe4ccdbfbc6fe90a65d81db8856811ede2d5102bc8351d83661110a277bd861ac9b14426f896113816e36586f138bfbda127d5e1150cc6da76217bbf5949c3131c504f8d9591b7ecaf0f2ea408d53bd4eb0d51abd958e35b5edcd5f397e1accb1a0f47fc4c71d3119bfacd4bb9c680fd05453323fae76a9ebf9e6a12de56bcaa3505df206e5185e188d1294118eb817f1e59d1e044d9a5207e8d11c3b69195fb18e8fbf497fd36654de34cbf37baa73d359887ee90f6eccd1bb08c0ec8ee2325d6e398a3d76102ecaaeba0e210556e13679dc495b8897bad1592ba14831ea93c740f3a04877258a5821fb1fc7bf4a6030311573c1d455944c2a8641570bb2cac671823638838ceeb3219ce164a5f2d7136e979d3052730e0e4bc5ab04f7ca2863222e946a44ce4e1280a13c4f836239757979add166e9b79ac212c8fb1efa05ce5d517bc70d13c76061df7828d1a814846adf91b34ef675760e42e6b5d3b308f61b3a6028c4289085ad48fcc3c6ac86f5a9d5862ce45f39c7f0d66e44e5e687ceb8765ed5f62b8beaab085db170f1300396d1b0685660e2074ac3c71258207f4f1cc70d4e4494eca80af7e354577e071c97c92edc081d34eda9c70103d30f423a072498b6991d80a5828602268d2ce7d4ae6d8dcb72e189d0b499f6b41bbdde9c2b49ac74098961b591cd746ff04502ebe5da875a2dfb15140140f2a78968c77bb78543ebaf6e1c878e13ab928f2a007809886a301eeb646b091b797a38c893bbf67b786cbef2df8a508fa6214fb980d598bd34230d21a83b6d81ea36355b8362e4889cd74d34a39a58836477281fa1501db65d369818a4fd6dadd4b267edb181a94e3b069ee0cedff91eefc66f8bec5fd4973e498b377d09be7776cadca3d3c50ff52374081dd5f9d1e64e043afab768c83be42363112d7629193f161341b02894b0b4ae78d5f347567f623e5e4103c205b1ed9a5540c7237e5d0246034f6c66f6c2f854ee659972de8adda1247961b8c38a3aabd5dd2aacd4b9b5e8cf4c5ef68d48b7fb44dfc7c870a4483d330aedaeae4e9ad954855abcca535234a6246f1e33926e020841bf74d7ac9f0436d5e9be6f1def9247784dd0da3c8bb1b90a2e2866efaf1d137c4514b6df38631b6e590ba61607039d2dc306a2e8759a0e29b5d5ab70f6ce19bf99f5883268d35644c1b0672ffb0b5e80a5df845053405478e72b9e2ca76f009ec393b38b2ba7b2a8a86bfda645e3eeb73fbc32c96fb46aaadf4fc8bb41d39522a28ca62029dda8f89b5469bdf033c6a340fb22ea1e9b70b6dc6ea0b236554d848f4a80265389e84dda8665cb089b07e61b8566e0c5e881a961951ed6c0c69238798cd653a8258fbef3a68f982fd4a5682a4c7a9990471ca9853476e567f21c45cdd3e995262923c8255f592505e55f746061fa887562b32a85d0cda7a574d561a7a502feddd181690546f48a4f84a06a7240d51760c3147d2f9b3c0a422e925170375c96e5ef463f8ec000c0a84f8a973849fc9b569a4a95a9a2adb056776f299dcab3f66fe4834243854a01244b2b57f7f7f9efa9d9d630357b74f8a122bad0a5c1bdc04001eafc3f26712a897de9e2ae07d4a470ca9179e5f75363f3d1bbc3afb5104f9e23a51f2f9430b77d3a2a1412917c20bec4a5bb601900e70545f5982ae738e48f84acb4aef8996acf7d5e864b828422e5f9e5a29801b54e963e1cf77fa91c19f8c840431fc2a60410156a7ceea38dadaf170c1996c36f83cf110559c80e743a5886c6992be4d449cb8df2e21643a4eb6d09cc35854a748e12cb18af4f9e3d648ecaa6a4f58b3ea1b21fcd7ad4d226f956b21b8547b87fd784cdcd64c9024ad07a03b9aaa1ef3a5d8566746bfa90cdeb5d83a64cb7dd76777de17bc5b0b7644aa8013ef09db4d39caa7d0a40b6b411a6c5dc8264ac895caf17c9ba691562df51b9cc3c864c930555b8b35333f57e3433efc8d9def1cb13ae05814f6d0097709e95c0d28eaa4f7aa7e526d105907adc487bd7d79d66135b6a148e2eb15706edc40ca2f540dea4372a686752c782adb3fce3aafc6f628428eb98e907cdea1c2b961716821ea0be139aed4e9efd2077c2d059e4b043d0d5a3058196d3ae93d7276bd6fb2b7eddfe3423921a488f25eafafc670814679f57b5c7ef4ccb1c82a5780d1eaf345c98bc302e876b85f0fce35514f73365199a5c0a6886f1689ffc4b317aa7ea31183defefba9898c9a90bdb7dc3b470d230d0f0d79e52f7854e18257607c719657ae02b3b410bf91076259103e13c68e6046c4a3b04d7e2d3cafc54b782cddf4ab74f0a3e91e36956edaa1741c132ee192e963e91813a58b2929e9f0bd743125453e2217919e097f953e4f6f712f28270c44cd18cbc57c3eeb07a4c8493c2abc4db7f0dabbc974e322e58e29c788f44c885dfc04fe74c2e3f72dfc422c3ca9623db2e9b4b351fad8237ba7914a68c4d8237bc77c7ae6f411297ddf9d9ff779d5ab2ad710235a258188a45c3e9e0b3e11853125cfde4b1f994c2693e9270c3d167ca69f4617f3c188f48c095f5936996eca263ce6d413ea23e683fae960cddbe4729aeb99d137d3c588604774497ca78f358f5a35fa098fbe8ba7cb3cf6a8f984f9f40c0a8ba3cb8cfdb4ea88d14f581c61cc88096347bc137c3fe16742fdb4ea4adda6533e204544eca30329825a5179621c5dc41813a37b31a018a4300684f9f88c7e7d1c61cc48ab8e748ceb5d0dbef0e0f56e06dfc14b49e31a3257d7576a3800542c5e2e65cab1273d03f3ebd8100645ce982a28d26db98a5f4194c60ea5f018b6f852e235262e229850cf7c280d081f76d359be5d4428cd15346644288d6c65df456434ce0cf3ed5e432e00e0b1f3ca6b1892af6f1783b9d893a0945f181085b99e92f254d00b162f173c662bf0f8613c8678fcf178157854b50ccdaec6e9238c41912f4e170917271737c85b2e9e05e1b3164ac6c41762245c60f018ed6a984a25ee2c77c4a0c89818b21188dfa9555789bb85f2059d3020a0930a065dfc1a72714f77c8679fb4ea7a774aa52e1035afdc1113838572325929825c4588a6cb3c7a783a9d4ede4bd8e9e4b1e0c3eea55c0c283c5d761eb650ece85ea67b41f930a052ca4da1a7e3f9946e4ee79292eb3472f9747aed19ef273caa7cc3542e067400d2a9b6ea74ba51c2e3b7c9cf74d9d530e1b1f4928f1e397ced6c989e72d981386b13363de58ea77f0fefd8239f4e57995f49a5543aad5c0ce8d67c4169d97dde093e6b828901c91935632abf8e39a102246748255e4a948e716548bed1bd14d3e9a39b46364e1f7d643addbb5246a75d8def36464ff9b6990edeed14fe024d3704b188033bf81bd8c1108f27f09ee98e0eded129e5d7af11bea2a4b4b5a76b28e8f49d8e019d7e9d4e271b866f2c5d042f33a644e522883120993126b0177ca6931702f9a5a8dc9093e0e964329d0e865776e028fce8230fee74c1ebade0f37e3acee9a6a10b4acf80bf6e026fcdd710a59140571413b87223c0e5312787f744f0a9606bbd9e2d873b992e0f2e8f3b47e4d385c826a17c7ae98ea524f2e905c8e1c30e1b5af2414b3f8d3e7a492ec9a7db34964b5c3ee13127879807a71dd12acd0709597892af218ca767ae2c28c9d72545be4a431f901eca259398c3c54504c8968b8b3a5efcfa1585d2b8f875226c78cc89b001ff2822f260c35dfcc686bbb0e1277c23f3175827a430d7656c5a65089f6cad1e80d3635cd65f5c1b0ee3cadcc52d72c2abbbc092c25c3f0500ab28ccf598ab53e4c6c5592f5ed8f0173fe11b1897c13a32877117d7297213c386dfb8b80d58a7c8a946890cd6a9c981c25c8ff118a0239460090da4e0e151916a7640d0833314b1852444e16302253157b6625cd97a71650b0667c3952d992b5b3157b658456e5e14117970f1d56f5c7c85758a9cae23298c8b13be71f100609d1e28cc751758080a73fd053ec22799b890f4ba644b3ce119a455d7678f8c92af5b2a7c266c4bd842b9ae35f1615778fac7c3c393b7c99d7006740db5ea3a99de5d0df05b8ff1cba7d3a974c2804e1863025392a229f9c29b3e624077e50d5ed457ae29a7e613eae1e9366dfa573a7843d4c11bde146e60a984c7d34da711c43935976efaca377b5a092fbbd3290cbf4dee74736a0ebf72a3f4d32f4ee927f0b32b3dbca86fa53b3ff0dbe44aa8cb0e0451cf50df2c17ded365872a957ec29892565da88b01b5eabacc268c31d1aaeb326b42f854f015a555d753f005a5559716840ffb780dc5e01b69940bfc758c09d3af9146c9d7c12b6f35dd8c74bfd3f56eea2e2a17ac56cdd9402bcd848f5eede3a4890cf54f14204a53738d27ca252f3994af4bcaa04b2ab994f4300912d43c4a84886052fa64526240a10f8b2e8015ea4db6f3dbdcea753dcbb08761bd3c865dd731ecbade59ed96ddd5c7e6e522b79452f270f15dd3bac0ca9b7c7dacb7b45a2b2d9694ca5ab56aadb594878b5ced47cfb049178edbe6ecea6f5a359f43aba694317a68d5b497bdaecbce3967ff0706ecc0320ad383c2cc1d0c10ca3f4855bf470fd767288772fbe092dd871f2e730f3df8d08d7df881013b6837e743d603a5e1b8adb50e6cd725ba7645178776ccc6f5f9ced91d3f0d6797c86e5977b3631f85d02ece95add2384cbb76ec56f9427b87551706544c31c51453b446e7be71973c4097653be376806e47d6b2d7ee001d466284a3b377edb2353c6e3887e67b5996e14e846dcc5f9fd8c5317f6533e3985488e6dae6404a4a290ce54253da9476775fa7d79ddd0e9452fa24cbbe2f0c7f950d85e981c380ac4b502133ccc0858a49cf484aa40039b06a6ec8e1c30e4a9f64facb56223d43477a24096a24d391fa501f7a04933e506d9a84210b501edad333630f691a90167202900f506e39061e99c4093f3d23a467681247906c9c467b2805b9df52f40c69245d9a501e173d23f30d9a28e3e91920b58891f2586c066137d8a4cb68bb4937e99926168965225b7ba45525f8ecbc9954cdebe43e49a474280aa5f17a9cf4939e815204a53423ed11416ba440a811d99ed6beb5972e16e3d8208a834dba8c29414cf832267c720e3979d2aad9640ab5ca4667ad63f255e9159950e40b3b64a1d8285e12a6db211ba585ba0911b6a10a740449901227643edcdd99c02e04bb0a077404099320254e541f233f423dc3c27265a64134a8a5eb3a4b975026357b82cbad443a067dbd2def6c1339e3a7b75190346a12339882a47179a978fc21b3b852c28cfe725dee36b7eed66e1bd43d361495d4e920caf6eb6ea0def216a23d2d2473ad7568db86288ded01532bb3ce8b239a13bf66a22ab2f7768a7e6d9679d8d0f52e7a66330cdbb0ed470ef5c1995e0bd19e9a7dc366ca472a04e33e8a5eebf6ec6d399ce37dbe7e1461f05ba9439b0edee7ac77cc7ae88a307b478c33d1b36f9794a667aef8f6910ac9d951d784533f5fea76e06c96adc098f4e1ac374fe4799ee78926aea73d797bcaeddf4bba0d45a1b6214ad3e2f465287fa5f6509a16d8feb0c0211ec3172c52154cebc8da3ae6d8fa2dcb2cb618273bf7991ac3d2b7e66c10a5a93fdf883b5645e2ed0fa5b19c0a3c7ea5db39393d3614b945f6d66ea5d31088fa2dd4d5e8cc5e5996fdb2f3b88761377377963bb3943435e82dd4bde5ca7c5121225157c3c79458d4611efb8d79ec3bd9deb17a253c3614797b767772e5300dc15c6d35480665da527f68d6239c6357f0184e3b24da2c75b2c4095f100dea99ce2df39256fdca7c4c9b04253169d028c8153d9d42a6f45913be4aa4552afaa6b607ebe6a45fe98f1896559facfa542295483da2fa60af3e3d73442552a39eaa4f256287e01aa555f456213307f5cff50675a8084170c22488d2f49021414382c25b7b5a5585d421487c230daa3d29074fa75ded2aaa357b1d5d3296659f0fd8b7ec3960d79b3f555b6db5d58a3a9bb9b46a629087cbbc271148472ba2ef2296934a5791d9db5b4fc7b09782828498f42d16bbdb7befbe7d6658ecbc6f78f421fb60b9ee3673c9b2f1ab6287716cf6157bdfd13bc87de38ee19addc6b2dbdcb337e6e182c2304ee9d879b86498874b6e79c5a4d3b11246c2552492a22912d9639fe823919c781c89aa08a73e12dd14aef5e2cd9959544722f1a215ecaebcbb9cfd2cc9dacdded1254f6c83b1f573b8ddbd5b7239ad95c32eb7364c756955055756f0042f57564e9f73bba34bdebc4b9cca35cc5786e38954bf5c3f17efe0fb2e773bc8c365f421880ce360a7639fd61ec330ac748b655bbd3ee0c870bdb5f6db4a3ffc362bf876c9a5832b2bb7a1e2fdf2ca3d7d843a5db423248357b9a30f193ca58093679e306d4f644f76c9e9741b84611866c78a1d093d8dd546cd35cfcce50c6b1a44455ee6bd85348d6ce9e4fa63122853267c2b1914be9106d1265b10c293e9294f055283c81992a6fff384be7d9ae4cb894c47b38491b00ff396087da2db20ac44c2b073ff2c9e9d837aa6de93d2a34124ea0589b09db9eae0e1ac7e63429940d124d339a455f4a36b7b5a45ad908b059f3d628d7490e82386d9631fed4fc6c16e7f68967d210d92deb36fdeb5478cb48a5acc089d06d8e1ec110c5bbbc4065fcdf6a767aed3cf1f7c5b964d98210a799465901190d46fdc0ee8cf65a469a8110d05ca93275040d1a4c912b9443ad178944ed4d4b0582ad5ff05f5c027cfd1fe647aea31a1148a4c59827e7a461ea149934c6f8df44c0d74c892efba7409d561663b24da8f940661f7d42a2a83cf662772cd6696d59b6a5528838f724deaf42ef36c29284fcf60417aa6a9103a4484619fdeedcfdbfd08260aa2668b3ba8815a454f39d11d71b7370cd7e774b6399db32944ac65e6ca07cd23deaecc5c61b7bbec368b61980df58161dd3f2594ab31c2de4557f42eb3e88ad9edddaa77ec4e2a048c56d9ed36bd03a362de6b1f41c27147a8b54c32ac9d508261f6583d862d6915cdbe93af9ea056513b44693acbbe8f3693a0254cb23a0615df6c58d2be7823faebe7319c23546160b8b02f08c921136c59cfc8d98449abe4fbf235ac25414eb44a5e091340485a25bf84d21c944e4a733862e42789561169d5113e5af8a0306288909e56ddaa248d7de36f740501d22a1e9d56c977ad2d444e0f1e3b18f043e31e5a253f44efd05669028f334a9ef778f0cd91c78c32a324c108440885a3f99194651e336a4396462062e803434829653da5d4435244949e241bc8737e42610914c0904510d02649a8c8324913276a1434d0640b36cc324914701085125c52888100b24c128527309edc7f9649a4c0811bb24c22052664c6d9006502ad946592293469e9c19c73ce4969c75d057c324913244241e414ba90e5263482549649848ee8c42c930801792b59261182c2c8fb7ea694cf21ad9573ce39e79c73da2ae7fc9cb3c3d15962295fb820715df3734e991d8127134a43ebe57c2267b0b8fc287be6e5f8a35c4263692e1aacc5a576f94984d2fc509aed721e69d5bdda6d71e7925639d193898641d230f32f97c59d4fe48bf97a597732c14be6a54ae5f2393d7a06b5225e9e013ff8d0332d97a7cbebf40c78799b92e9ba9c423df3cb4f237aa69b42660fe9f23df48c8acbffe5f88e5fc69772460d1f676651338b4b39a3c5597c6b71ede45adc9a6bb8aa37d7e2d29c5dcab5b85db916775aaec59519e6aabe49156e71afcce28ef8f72f777636f05d7edc5d8dfbeddef9e11cfacb0e5fb66ae27ffe5ec56db92c37751970775c1ea8db23a755f32a578856cda75c9b56cd835767fe32dd096492e6bf3b7ba6903b874c233e0a436124137347c510a2ce7adafae4f96a2dc536807ac08412fa738422e9194a9b5027740915a24ff23cad3d84e899f99c29459ef6872182e41a653ec9360a035a65eb73d49ccd28b9ada783afe7114af2487f9a46f9c19755ec438fd289f91dd3f2985172ed491224d73aa38844ac9ef95b08037954cd27a2c8d647eb6c09aed6ba9d75619eed4cfb46b98feef8e51d9d39da6ce8483b77714497798eba79394edb48b7e94e34daba731fbf777884913ddc1b96c0cef8e1d9dde3362c23ba3273a565181ef3ce37ad149bc7711c7779176708cb719e57aac1b89b1d46be383a7ac9f34a9e57ba0d2d8d2e4e577aa9342a7dc4f9a038f35de9366de2483867cce99a4fdd4713cee95c22dd5178bdbb3273c56d220dc348f3f2c1d66ddfdd58bbb2fec5ea5f336b575f18b6a32359f39a04c2a9a7936af455d3344dfbc85db85e542b57af1b6cd65618796c7bc7afb9ac278e8f5c6db51a8cdcd7b97b559ef82e3c8af058b3bd300ec51aceeafb32930686712a9699ab6dd61fc8ae46a6693b5934bbaefb0dec5df79d6bdf6ed33b79e674deb04c9dd87d6079be5e0c7333a3949bf40b5b9dadf90c03c207962b1d274073c5e39ccf668d7a3dbbd71d7760bf4e453ee614383ee614790710cd932bf671616e7e389d7cd1df81bdbb1ab8b32cbb80c8b22ca3f6d8adb58e601371ccd70381451c13e3c8cff781e84c4fb10e12cfcb4b2c73f629e56b60473e9b1df9e4b5abe3c2a7e10f9fb0941887f8c94731872794d9f59bdd3161011bf68d4e2b6ded28a5945a4b29b5612a5ff6bad65ed765b9cf56e132cf6f75d6f6b01bd8e511f9447854e539738dfb2ccbb06fbf817ddbc6eb2dda11c9ea11f928f6887c8dc79aa768d2116c73626c235d76dcb66d9b8737cff3eedd867a777e7431acb74b3a77b56367912e43faec6a90308edb64b60d4b0dcb36af061f8e77ebd5af3fdcffbcf74f1e96d9306d741b1de6ee77efce7967b6d6e3e6f5bacb8dba1bde15611866d397ad341bb2d998f9fb6aab6e6334d63c4a4a3118568655a595750786a460882237189e87c7392f49bd9a65b6eddde813d7dbee8677ec9b9481f185f2e3970db0d58c306ac8ccd5a964491918d88501c366e0084f0c45c144144e06b04939239b585fd4d66a29968d3b360a401d08ca93e7fdad6737127acbe60dada2dfc4dab536a594524a29a5f4b529a5dddd3776da733d83d51e6e8272ecf8810154897d0e06b0d8006de7bc0c30e90e288cbb84a71afc6034d82486c1800103460ee6c5e6e52fbb03cc39bb5f5bf5c9da4299281b6ddb9c136762db469f65149322199a7dbcb06738a7f385391186733a5b965645222c73bdbecf82a16ddb8ece102ced99689440f6e2601f226b224e634d1aa2dbaf45d9a786c1c873fc70a64d11fb762a1289aeb1260ded136ba3d38f30f2bc9171199699ab6d1ce16ceb6e888e33c2e3148944d9b6615863edde6de87561d77e75263357dab10c8bf6dbe965260d8dbbd6ddc88ec3651bd6d5d8f0fc60586bb16b526a9aa6515a77f2a89d62cf64e68afeba63cdf4f6688ea6a093cea694524ab93c4fa75c420c9620031e1c7dc2362f5d362a04e5ee5a8748d674b2c92c04f9cc8250e6e427fbc214576916054fe6c2b5aa066d7326a1021297c993a40a4d38971decc085926093af02946905250dc5914aeb97e0b24a79280d39977a05263daf00be5195bb46d54058189269bef5cab097e024c64c406f72f065d977b27d314103068e7060a6210ad011cce7aacfb43755327b4933b91a8a76b292fbfd937d3f55aab84caa382e733959c4bdbb5b6d264d3b1d389108d70c8b6279342a0051f358a370178892fbfdd33f3ffd2333cd151bc3c6d58b638293244c704290244c88526bb596883704c3b02c4bd28425a82c9334e188689465922640b125694218b8244c3490654604b7d97969598af0f8d17967b636331ba0555c2dc09823078c9bb76fe40bee362d44abb89931f1d1f7767d275f77d24d34b319ecdb27a5b4769fb7b3778b68b5d2ace6ccd62a5221448a755ac55de60b7b27c84c20b56e87cb592859368452061ca06617e7c2b92e734eceea75c05e77f0e07276da75223d2744abb87757873bf682efc25e0872c51d8d07a4c845dfdd0ed7e96577d96f35be5671dca364ee42e8f48c882373e7b820993b378bc89c4babb873d7927c5c0fad9a5af89ac338b36763f2f1fabc2eadfab60bbb2e6ae7bcbf8e613be90f3618d5d64a9dc872dc24f9b89aaeba8841080d68b8aebeb5d6dadbd0c995210d2960e16003bdc4910ed24b7410248de40920dbb13fc9d7256b745dba8c32cb340c8f3cba080d63dd8d948bae751099b53712aeaba189b0482f6bc870e4619b26dab48b4438dc87c8d81d69de2eebf6896d2886ba26b24b4c1aa26bf61c36edd848ba6e0c8baea61de38e7d14695854b56f75fc91b56f183bcefc1059abd9b675903ed2409bc5c646b2918ec74692ebb38b3012b623874555bb63d62ac738141671179d553a61d7f088e3da3b481f9934b46f9aa68d2baf1f1b49163de58e33a77cd4ddd8e6bd6e076e664c049a44d886eaba1bd87136cc615b8737124661a2ed49de2c67adb596c3da91ec2af7931da45595e51fddc3e3c782591466092d75a230265cd2bc6bddc411dd5b62d2a898479849a29084af93b467a44b7b87af3be66858ec58547bfd75559ef878f008b36b94e190f038b16e072e5fcfa14978e41166ed45e4fa5e62d2b8705623db349148a45d91766beeb45944cfcc5fef203d53b9af67b85f3ff5128d24cbae6aaf59fb7645ed52d46c0e17f6822c045fb360d488e0cb618056793d48acb5e28df9ed3b19bb63cdd818deecb2d3b276733a67b89798ab5ac48e4c6f51bd0204c32da5949b2813896a187edfb36bda682ffa66a5ad556a6d2fd2a48661bce46d54bdf0c9bb641d98fb52b2e4be952f597eeb5ae58c997b091d9020497e79c94f5c13892019a0ad1924032eb0c011201578a0b5cdecca5caf10946b1ec39e194f44aee94387cc23ae2b1c711a391f1de4f194835cbf86ae1e23f8ecadbd3dd72a2bdf4352b99ff864ab323cc2508dacda05d12be61c72c664817c71fd3a0f9266b660c25cbf74e0c40654c8d78c41be7ce48b8be2eef1ec59469f3dfb0cd2f32c7a9665d9ecb9b44beb2032c342b42ac7c837ca227a4648cf8c544890910ec9d72f3a04bb2aa4a56f9c43b23d906ffa80b96e78ec23d91ea8082542f27539b611f9fa8482c964a2817a26fb90144ea0f493d9a4e792e944ae35b33764aef4a670f49268946ce7916c3f4e9f8b7efa50edf2847c397ab85e73834d01c230bcaeab8dc8717b68d575ed8e3b59bb69d5a5830f7b06834fcb6e06e5fb98fdd46aa9cf6868ab7366e72457b32cba56aab64dfbf470952f365b811a22dae1a819767ddd6c2cc09872ce7768f8e647d6a54ace0c0bf5a3f73af0d54f86727eeea0a6740411445063c4918cca320832189a93f6b0bfae391f01ec38f51389eddb405a452dee2018f86af3744f0fe9fa651f7a0418262646b0028c1e3d337384f861070f9e2286cc597b2072d364761533a07b010a4c509968f64a02138402f0350e99af5ba6d69e9e995276355a089b6933d3f8adcaa63dd24199be83aceda056c9d3392f3a317b5dd6dad135cafd51914ce86a28ea482fecf6c2e48b3e7683a099be5e20c6ec187dad39346358c491290e82e63e76054173c5f5c9373fba64d7bcf0687f599b55acd6573a2736832cf4c95777766ad2aa4c06df49a49d4441444588ae8b848886f44c26042680a879e6eba7abfd74c2d3003b393b71a5206ac629ddbb7704e6d385dfe4570a6ad5f5254c3ac6f5ce06df777ad23338227695cbacc2393de532c39cfe721697d2e552e25fca951628f0a70ba322b2c2028f2a021f2b8f587b2e5b31e2c7ea932b0b9fc28897ad15b6a93fb97ec2b0618e92490673b40abc4df3904cc4eed2c9e026f3269c3cc9326805457c5906a9408abc4d6e25735586f0c57cf59dd64e6bac403badad3999bbd38ab93b2dd69dad550c5e05b58442efcbc1cb721b4af2eec8430ae5ee171671b0c8f62cb2fd27248ae1c12b3308ce0982586adc91b9c5ad2f28be2ff8394510b79098ea4b854c70dc01c13b339356d5a0baa455d5c9cbad00b855a855f542ee3cf82899679447562e6be40b5ff7d1fe64d7fe48d1aa6a87a0446955b51d144336b413ca76a83ecbec8f3572f5489e6cd3dbe8b34d3eaebb41adba72c8b37b74c1a326839f11a8c9388ded9256d54f28bca16fac41b98e5528d7571b7469d5c9b691442219842c2f17291f5d72777f3cd15c3d0d536947c9a7ced495bafaee1bf89049cf7cb87e1bddfeca0ddf2ce2593ef60a15d003af3ed6dd60f1155c5f479dfdbc5cc5b33f2f2e2abe6d295114c5d4c569912851049f4ac188a8d44330698807516f69f1141e3bb7bc051e1b6c018347f0e206b65c0cfb20d807c58b93fa10b9ef4871d0ccb2d3e14511d321204bea53053e143fb2bc3b7ccb459cd3597ce3b105f7471611e3a09e7a7f0c5b5c07d45361eaf3763d400bf8d917c462cbc587bf7a288d1dba8a978263bedf601fc4299527be1a1e8a6771bdee0698fa08bce3cc53ec8735e09ccee061c409c2cce3807df1a4098220d8138ba5ae060b9e289b5baedc726546a15028d4734b2ac48d0aafba2c6f7157dc86b260d1e17f288dcc0b1e33d65dae028f61bd0da23432d80ec5e03164e18fdf986597ab50c1e245050b9797ab08c1a4113614b831c6996739eae2714ed9e160790bea9fa4b13d14a6cea48e7a9533e251cfe40c78d43939d3077051f1178cba2ab0a8e22e0f6f8728cdd5f38aebada88717ff1f1b8aec822f7e7896a3fef0a4eec63d0ec6bfbf7af02bf630eae1532eea6761b9a9abc162b30ad4bdb28a2bf39cf313756b5651839654263d33451f8dfedd99bfa6b13e6fa1d147a373a4aec6287c0b0ec3a35028f19b288ae277725f5064497dde9d0cde16ca9d63334bc8591f4ac3f2c9f5a97b89f712d2aa7af05e432a0bafb06c98d151a35f3d2a3d4f31555c92f9ebae9e5c5f852a14d5c99863bd599774d70bdc0140cf2aace0fa2e2baf3afb94669452da45b69d2339f80214b8b0031ff01869c96e74556bedf5d9e1b82a4a3e7b992b9dddf43ee814534ca0eeeeadd651fda8bb6c76c76f4767d47d8e3e8d8c98c0115d765cd775dfb86eb475473e4a26df2e7bf46efaf6d3dd6ed2700ecda4e69ae65187cffd7437ed5389a9c4542297fa129a3d67edd9b3675f75721faf8fd7b5eed83d4c847517e76ca2f7a8d97776d1c7ec22dc9513b55d01874b3b3adfc7fdbb4adcb4f35e5c86e49bf5e33c329550e22b95e6cf34325f9a4c7cdd659ea3ef9b4646df77643cddfb487acabdab5cd930291c8873e809e7d09ca97c1c99700ecd257a95ebe11cca7d2a3195984a4c2586983ba6c65c508f889acbe6cf3422ca767444a24f23a2c944765d33fb3432695ccf261291487444343b29fa5509fab673dfec470eb776bda964221be6ba444cb29d4a4c25a612dc5462ae1a0f4177b6c650b0b50d103768cee66afe46294bf962059bcdf2a92b6958b9eacf643485933dbb9665bf3eb38a61a9e4a3979966f5bab9d27c01205bc81552b592a949e33dfe2a56ea2bc6c2abf8f57286d4b4b0e5201a47cd244033fd45f32567d8bad14e8739459ef89aabfe4669c50ec4cce3951bdfb077e64bcec0dc8a8a920f87bee9319aafcb8bcecb625baf1bb2da32d48a65558565e037acdf70e4b56f9a0d79ed1a8f6fdae9c93773a653e4a67b5f875e36d6e97738a330d937d1251671cc73bf21aa1a56b5aabe5575f2843de3d2aa7a0cc877e1ac55b51ec3c0277990adaa750dd214fb21dbcbabbaaeebad9aedf2ece22eaa79599c63bf5aeb50127a30546bcd6435d204121be899f1c3b0abb16b5ef5e1bc2e1aedf399ec3b66b3290cad37a8926b0a1700196a42a889298ce458a06d54fa3dfc637415f74657f11fde5f235a52a61f1de31f2a7e14b951f1d17ffcde654bb4d7f17bd7a1e2a3cb4eb49807efbf8ed1556cd8c4303b89e0c1c112cccece36341a7cd2c6ec8a74cfc05b62769b9ed38ee18cd59e499a7bed864fbb4de37b25bda15554b358cdb4210de9993ee9278a4f7ed69ea2e941e19333c7fd6691f0e5f88ec819009033645e914254241941f2b1a42179b6e86d28cd4b1012110a433f4e9e4c3fca28a3648247d972658bc595ad179710234269264f901f12114afaa12a175b6fb0e91835456825d437f9cd9a3b81e858dcd25f2ec9e5a61cdfd92140b6569cc515ff7257ee72bde33b3a7665be620ef15ed95a7181b03cf5ad46bea0b74e3ef9b1e635448fc23bcb818c9e9a789440b6866555f636b49f3df7611c97f990d9310c9b3c77749d0849251e16b5e3111679c0f72e6a5807c6f7a38b3aee47bf58de8662d787d4bed91d28f681c3e8d7e54db98aef2d57e52cf7f4d4355dbca5af5cd245dd1573944aa2968a2b5b2d57b658ae6ca5ba1c28fc9548445a45af4d0e0a430fde1f680f0a435f3aa53889f2d550184afa2125412292a9cc28e908238690aca6594a290d494792a02423995e170c568facdd6674ce3b77d9dc2085cf7a77b25a456b6eb0a1d786451c41d4ac61183acc2cc2d43b3d6908a5f1ae2cb3d968312ccbbe9ec128a535f4cb328d6694e6fb4844869c64843404d30f481d627390434d904109790c6ba618b271224f2904234b40d0434992a085ed073d521035d2104d2b400e4a93d2436f80321cc994d2f3f0f068800625c1063cb4fbb140908659d2909e194924223d2385700327323d29899e01333dc90869436e8cd268d8b15fcfb1f3b3ef39494059ae1802b5b335cc1668b738a5742284cee4c90922c4a7882147e43e66e90fdd534a201481e7f2727f87144d6dc8f4f6ee989807a5d75172a607a96aeddb4339c3e6e93de1a36d51d9be1db0e5d033bd2363061022078b739876d64e0715d66603740e9d651850f85c3a2b812acb2aac2fb58f2461b04b9aa603901d63548598115f5f180abaace14fbec08e9d601620871e4098ddaf55d81b3bc54c80dda666253b0bc6fcae1caa55950e2827b070832bcbb6697d86471eaaaa794df8b26399f85118ec1866c467bb893dcb4e43bef9f1cb01c41e089541760394524a3fa9d52208319105263d4fd0a07ece396795126bc1576f63f87cf23db97011992d40c1172e22f46ac9192a0168a4d26d18be2cec18f4da3d1df18d7f966978bc328029e11b7f4a2345a5cb5b27f6891d8a426e214b12e972b448c824128944225ddea6b39ea1dd47db246b9e768b044943ca9577ed7649cfd86bf5daada66978cc5ac59dbbe8dd21e06a959e5d110598e4ecdadde4a72dc99a0dcadaa5b63dd3f07811d1be658dc745248b44cfba7fa2469f9d428c051fe643840db24b2c1312cf07b62a5fcc8e36a53ee6143668ad96da49e7ccc2464f71f04dae6937472ded6cd4295fd06f95d671882cda08c77a23cc14d39d3a9b09dbd64d8cb356c94992ade2543bbabbe79cd3d69eaccf861e08c806773dfd9cb3a70842d800cf10a02002212be9a5bd729eceefadfafa63cd245b96619db901117c61082d9d21b4265a45e887a84f5042ab487fa7252f63a0a055f12725859910d82e9ba96a4d9598c42486dd6053335f737d5e9b1b6691cf071b39e79cf2def01a1536b5de605353436d6ee89a99c672760cfaecba78e2aba135352c9b1bec55f442b2d1237cf2aaac353db049ef896ffcdef323629394e2d4fa31c7e64ec124a1b2fc9c60d8ae571d367b5d3488b9936ddaa6fbf6f3045b26a5b476bc2e7b5dd99665f8bab2cc5a5bffecb2f5ba2e7b5d6d47d7352ffb8decb1392f8cb30b00e51a09946518522a3f3aa719d240798ee4313b8d4158c31262c084d05a6bad4dab68df5a9b656198fdfa965dd92786596b339aceb0deb14374532c48cd5e6ef5f280f055d1ad12c65ebbd99eb2e5f1e5cc6297350bb3ad6109315842b6978d40986bab668701d32c0b43fac9a03368208fa1a43c453083128666b294332f72d69d68683382f8b2f611dbde5d24c06f17893e075eebfe568b88a2eb187de53abe8b9fa69335e5ec4a21dc8004f9ba2ff2367b88907a668f9c31a4d6af3d24e86d9a629d9d16bd4d5ff59eded7f40d83f28d59fe8500d99a3d3d9466b64cafe0ebe7114a13be7e2aa9b57420296247c46c91deea0ba488d781f702a1073519c4e349299acb33477dada9d1b2ee5e16066b08c06fba7d8010ada2630083877768efaebd9345c8f207375842dec1a347cf70afefce5e7bca818407f3c65deddd6dd76ed4cc9df3be7977ecf0a8bdfbf61515259f8671b87796d9cbdad87dfbd6dd1e6ebc6b3b7818873bcd38da7368cfd1c31c39dc03be91392abde9f6b7db65d9d510459887d157dec3e82b58d4be72d9eae1bb88456de53a4e5f31fd075df98ae92240b68000416120219e47f0244261729c2e298c8e171f1a0c618a9609abdca984c2d4568d1ca4d943c221f6856f7e051bfae6bf3b0ac39479a8dbd9da93c266d666a7d7a151ed3f5ae32786cf1e01b3750a63431f7c1437fed1d73ee9b3df502cd66fa7378d451e0232abb24fd28f750a437f6117ada235a79cb56a862d224114481af0492458018a288ab88672258dacbd35672ee1bd7c685525e11ec4f0891f25938c137e74d2fb8e6eea5b8ac70e911178106666d92ad447a910f760820aaf740249b685d90ad3f772d9d50040fbd0c9a34ec6118fdae4d6a887cf538e58b78e5460d633a00df0990571d62af12fe195795ed15317d5391406599bacbc11c95a96c397ab983f2e72572f3b0bbbdf8dc7ee2b60f0e822c3fc23a96a9fe472f9a58e6f3e1e1e11470631122bdc35775783b485f24bf996ca21778fef87dc39724a9c295701e5d7f8979f0ad7c2b2f295fbd2f189056a44412c8e308e14ea3fad1cc4b8745a51b9a512cb55585858545854545a5aaed2d2c26d2ab7df4245a505c77128d437d45b550a431456711cc7712b2bdce9a9d4492416161616522a75b9d3ca0a577aeaf38607efd823834f5d1ce18823bd06118f292761d9aa1257e2fe5de55faee18e3972ca59f4e81dc2cb567d35c0f06f95f8bea4cf3b4afd7b8b21fe5a25a6a4f2f724f2f798abb3d38a59e9ecb456b855705f51878cb32ef65b7cdcc9fd06bfc5dc1fabebc85c060b46e4efacfba3bb91f90a832d2ee36614262500cf11838522a4c8b1c23ab39551989923e636dd430509577892596489842b30913799804f22e10a46f2f77e26731938a33020dee17b5fe537338ec37966bcb84d874fddb1474e7d237d2335d8584c7d4a3aea10a7804f390abc4d8ff32e4f7d93acd46d7a4bddf9cdd4e411752295efe5a6ae06005e0eaaf856dce4cec58ad79654088a1be4afca8fa5e5968ebff28bdf8a157b5ca0487aea224a24e19b141e7b64f133ace19be5fa82a90e87f89980504ce11b568329a9291e3c8b297e24e29ccac2f356449c53b307ae3ce53f7d9f138f18d7569d584a2596120bcbbd67b9f78dc78de5f62dcb9b4524bee5886c39e98e3d6ab47c1b7df4ed66762a01ab931eded3e8a9a312b0c259d8f2948318a7e5620b1e532e1b7c369fbab2551985094709ece08c29198599a38f2d4f01bf8be2e9ca493775c71f722af476ac50f76ee95e0f941039c463ea29477d75494f6959e1de7844fbe267a7c377f1e24f1fc54b6075593d582b316c49ddc5c33b0e71b3da91c794a7704ecd624ecda7a7e4136e398ba12cfab28b3bf690535ec31d7be494d32e0018c72983dfc03beee42fcbf37edf533e10c46305c1b1471e85c8e30f3b72bb1cbc338717c7079d9739c5e59f38a7ec6aa43c45a55379a77299cb33e3383ce65e60062ea2721cf00f160f2c2cbec0372b2cea68b18ec76c7559efaeeff2d5573bf3d2ac729716571c85c833467fec218a2e2a3e6816b10feae272e7876376b3eb7490d5e5393d0494dc20d8937be47cc8734748eea7de779c4564ec491631972ce2d187acc23c5c7263170606e6ae5821c550afb8d6c8193ed3477b6368e6eebac87628cb56a45674d37cc565cfa85479c58af9cd9f6caab906dd20bd1fde54873228cb56a5dea15c92c3db50928c8014ca38611bf1c690fd720927385328d49ce15f408c1362d2cb733a6f9b766e651b8d46a4f753a4cf83a8a71e1e439170cb88b443ea2109e348a51ee2d10b371a8db8976d25f57da4ed24520a7c83a9de61d475e04b8a2453a2f8ae035552df22302fe2b1f3ed6e1054b9d8771c1d9f0631734ae5258571e649ef4e87eda49376da4912a454185e1ca2f89e544c5dd29ca35fd26987a35f3ec212bfdca66ba4cc6cdaee7141ccfce57bc79cfc727c4721f2cb5beea8935f2e3b1c7249d6827811f1584531a773109d71faa9bfdc49938d725f88c71ab68a3bd6ace22a3ebb1ab567eae265915fdef7e5a99bd3d9e27071ec86d3bc07019c86cb579ce68a7d9ac7388d2bf240f318171beba0790c51078dcf9cc667bea5c2db72c79a5b2ef05bb9ed6ad4f0edf2c4f0e11a6ed35c08f224ca13275c18922707b26c620b4df2169c00c5ff4069449005ae1e83775a168b29504c89a91fd2494a14f35938c3e12bac3204196fbd5e5d8dab75c5becc654bc65d3de63a5897c13f64ce52fd380264eb14a68655ec1b195fbd1bdfd49c857556afb90eeb32422c5b3834cc0edc61bec15c2444b15fa3af63c6631e8375763610b7bc59579c9f5fad1e83755a5f5d279ff59d96ec441e64e8a8b938578ff90fd665b0382ff39d968e98e3701cf08fd563b0383110373108902d1b0a539f0385a9df69c9964d5fb65a5852a964062ed297ad8c1bfcca6d282bafae6c6d9bec5227dd5127935007c15b239c7386200886a48b77f439270a14716d15b8f20e314e0a8f3b39752e7547a3e82b5b40b2c9ce74ba48f4d2b7b3d4cc8233b9cf7995eb885c8dc8e0e726d2417c6331f53e494c7d1e1c7d75337a786c8473b4ea4ae1f0f762a7b8bee2270e9f00d6574f80cc6352580c71eaab1b99d42ffe4ad9b0bff22cf56c62f11f0ad58de05158e5898971baa7308eca674e83225e9925ec7de291e5b5552cf81e163d054cf1c483a1f87930c50bf1e8f5e9744f744fb84defbe0aefeda918dd643aea8e3a19f54d6cdbd908f1b89343f17d795602624ec1149635574e0c6fca65ed12b06225200614435c574e1aad701f994807c1a75247bd2f36f88ec47d34fa3c88c7cee0c3f715c5d545f1dd5d983aed6ccc9cc241cc4cea70e8c0e1981f854fcddba9b053de47c6d1492d8a0f0f7e7563ceba2b9d9b15663dbce2e52106af4e378c23dd5183573d75c721441e568ff9cd0adfb0308c101985c7958338e52b329352b0e9a6cbddfb3815f7cbaa3be6e495df3beae415ee2d6fc916188a58e481c5fac1c292c28458c7ea47cc0a4b118f52687e25c69db99b9665254c6e780d999fd8882c9365135148919bd84212999565135138c105222cb84ee4e186c778026e780c2c2640009f61b1c0eb88f3abcb160b8bfd98cb16886f64ce3a0bebc8f8ea3a647c857f14b961bde63f569781afa3e6322e03ff60bd06db50187cd992c16263910799c7e01f456e643ce63f248591c13a622e7319fc43068ec1b2b5d3eaae06287345f1622a25d6a4c4948a94022f9240192c8e2e82f866c68d8ccb88231932a41416f1c8927165b098ba48126f644ec237331e035e514ce990917110bc2c2ee3ca5cbc3e684e892c587c747d4891058bcb4eac11aa40dda3fe7dbb28962e8a2c275de5291745efe0bb8baa197dacd34845329d858475cc88c122f8192a2958068b5ea7a27b8b4b92087ec6631e5e51441d0c2f734514e661c6632e8258c78c98cbb8ccc511d621e3329781656e43c3dbe2a316979d0f9ac79ddcc9dc98dbe29eec5a84b7c5b7ae4677ed7a50beee46673f6f8865933e3f6a91519a98b76851a3059e9f04ca323157823980480a0303cef995d7cec67ccb6da8ec423ceae4f0f3c65c3047ab2438efcafbb278785bbe934997c56d7a6371e7d72c388fbbd7e9c07da7dad050e75b5d2e13cfc222f898efb474441004f1ea3b2d1b3aaf0f6c9c299895afae6cb1ae6c91ae0f9ac7cabd3e460d77e51202f471577783fbd5d3aa3adf4f5d3d2db7e64bc835249c19776a10c9f313c42b30e6219964fcc678c56de88a7b9de6ca168d2b5b36141bb32c807bc39514d3289268220a23c22c83566044de28d71d0fb3b5711ce9661fbd883a1be1fbe06d7c56aff0289df4ea2bacd38d6d280cd8b4cb5a351bbc0dd8df69c538eb8a8d730061c95c860ca1fe410a754f9fc9337ba6cfe4e9317bbaa7d0049a41136806cd9ff9238766cfe4993ef367064da029d43c3c73680e354f03f54ffb3450f7b44ff7744ffbe0feb13985010fc3066cd3b2b5bab285c2dbc685a2cb45dcbf8be9a5936ee9590a91d44f69622e8a67511af131a38ba8cfb86cb14431175158e4617519d7c1fa0cfc23e6accbc03f8adcc49cf51f325fa964482579cab8ac98bbba35aaf0cd433201532e4eb91e4e39b4b393bb13bf8937f56e9cbae29471673ce68af33197390b87afae38b18d197ef59c527f441ce151bf11a27632ea8ee0450fef08ca2c8aee98223e14318ef8d35118073cea5987033cea2bdf56ee9c228bbe32f3c43d0a47388337bc4e16679732b30f2ade6d72e0955984c2354acaadf6e7e06ac5627d3e0b0a5ac2444666c68ccf6b5e183e1b05cad53324627068084a949c71c0e1f3220f0cdf688366cc00623e9ff50082bc25e3f35c0f40c6e7b77c1c4222641e7322665cc66727f220f398dfccb88c6fcd85357200599d95f1ea44e080593364b2564dd65d5d19372675479ddc52d4ed808958d22e896278f059cf4891b58ac5a234abf7b7d5155317e7657ca71573d6155338071099c7b8383fcfc23a45268e711d9915ebeeb45677a725bb8d75758adccc7c25e332bf91711919358f8175bae633a791798cb35acf38bcf5eb14b9b139ebf5abd5657eb3ba8ccc579ff886008f8175629c0098f6609d2237f92bacd3f9ad8c75280faec701eb480a53cfc23a2d8479647cc6ad39cd9d89b98cdfc4ccebe0f0984f7c33e3355887cef8ea2b8c03d6a197711958a7c88d8cb3b00e95818328d0cc5998ead05c002d34001e01f4d0007a7c581f29d00d3f3468d0002e15c0bd8106d699ad184c85284cfd101e5361dc86cbb0e1307ed870d91a67c8b8b25573658be6cad60cebabdb348c13315b36dca663dcfa7365b04ef5a130f5abc7c4609d2237313198759d2237abb356d72972c3fa0aeb541e0a53cfc2f501ad18a8840cb6e54d2d999a19110000001314002028140e880462c16040a26b8bea1d14000d9cb25870501767398e520819630c0122220200000380a04102cdd10f06d545cb7015d910a8fd1081452cf0a3d21a2f2ad188bc425925d32f55f4abf094a51cfd2f08454c2a1282a3bae9c82d179058c908bad435c5998ca121401d96bbcce49f5add80a3e650659c44cd8a7c4f3333cfb77fb807c59880d216533f6e48ac4f4cb80066a05d051c8987b146f4307bc1588adc75cb25769b4bea38b8a5b78d6a9da3ccf6a9eb24c2bc00aebb0f31d22bdc5ee0a662c486c347ad06cf68d6282191795291acfa1f862e3d4db04b3762fc5f9e0bb73af5cf737ca098ed8d5a28fa145ad74477c3bc32b824f01f9d79c741a34f4e8b0383669485232fc538aa4a45be856a736790c1fd77f9a41a2c4556dc809e272457e0045f9c17abb54b3859ef88b0f405cadab359c045f126c0a69ef86d50fab38f8e5cb32a962f5ff12a0e88a2e96feacc15a0a2188cf2b4ebe8502a6547215331254aa13cc82f488e0a0e234a9fef6245437fb068718a5130ef60a0b1db03afb279d8b0bd054cbe17f75a4a56712cfcbdfcb761bd4101f2ec01936a1517d857290c3a358cdc64d8b85ef0d609b2f8001e209a3e3fd489751a2add4ab84116c94009f3eed739bdc219bca96aed8c9ec2e0f4d0f80dc9943c8ac2d5628d2c4cf9d5ae42ea555410d7da3a85ba59b9c943f7984f05a3667b70be4fb21cb0cd6b0ec39a3cff012526045a57113a3221a754fd44e60cc0f09597a225189e80556ee4885f8fb40f4cc96f2bb1ad611b14a7daffbc240d03dca503007136a01f56daf61daed3c5497c972ddee6c0371787b2c0fec4d6cd99784b8b4fd1f39ee0a0563747134a1d5d914be4629c94dc32237e2c246abc3cc35119b7e400b4fce0dd0cb18ef810d5c1389a40c3470f7ca3dba64f22125c93cc6b47ec3bc67ec9240b52de73da6352cb5ee7729ed6179a492d4c582c2ff821a996d33c74a397593f6b4745d827cbcb8b3e0c0d3eff406506897004a6112e1c30253f221a01ee33312d5fd28e31eb984026009ffca57f49df2d785ce093005fa53f654328f2499eb476847b51720929443cc7bc758c08afd6742d61c03bf31c490fd700d006997f88c5a38ddfd12f19149952100c4733826f7c9f46fe8b299771249ce3a6dcccf3d2d894e5023aef1c021e56ac68d0f50f0dc29696f15547fe2afea9945596f628310e05a17aa91c2b132da93e11c599b5004196453ea0c14247d2db7a895858376a7524412d483e9b1020f8a2b61dcb9bbb6639db4fbe48060dad00a6b80fa912e382c4a669b59144b040309265b37dcfe46477524b25a574810b9160e21710dc087dd8b8a2b7d6593462f94937e240138ad0fd61b1241bea8375054122af9f2c667b419316124286b1cb4fa50fb1453e2c57c9704dc3c1a2f95589d0c8e969d7c735fd0662d7f8d6d380f9b1e375047c0581398c83afbd0930df868e7d355ce7c9b2bb63f3e2c5912de24e7cb9bc430ce229be64c9831cf810468caf50852f60090a64730aa71813fe422e3b71f2823d1996ca9d8a237d03e6ed68dd55121cf9acfc6cf822e685be7ba3576b19ecadee6e6b2d028eb6682fd5023b1dd29e34f192ba44ffae525b6a47c86d78bf3ec21b7a267312d92f07c26d6fc314301ad07f982086ae17efb5246da4513a98cada60ecf6185e193d00c42e9908383069aeec742604dc19a59744bbefb75641ca7f94c35e23f49b0c6fb0e5c44273c00576ffa8be3445c4ebc55accba44750810fdd5a3d9be5b90fd24955ba0ade97bc03e315145491710e7bcd7f08ba44ace1a64a71706f0f320478087b2896444263c58644cacfe4ea534690e14b2af306172525f41986274ecd45b1e4d81243b43905cc13e33b75701be8b19802eecc62ecc8c688854f6515386e1d9aa9c3fd3040389188c20e844c356d3889a1932a964a92e28d84c43beb1514ca0ab12b115c3175290906c86bf49a299a37c2b5c5a604e3e6434308c86bfc646d4f2b8e440e0b7741edf87da3c1ad2500020a51c7df038d12a6e421d8c55bac4a48f68e3b16669ef86fa3773358393e48191ffe7b43efd24e1711d9fd4e9eb088124b55f7520afeb1d3a9c603d3b3205d26a41f0b5ec020057af29cd19881bd00da89098b2add0b6dcd2e7f4d03d2d7d161279948c014f803129ce1b854025818fc994e0adc14283ba1ec364ae35aea3fe4c92948c6740208f123074dbb85bd0a8012661226df201aa639a0550b129d88ed34326ddb19d855539ec56b45aaf99d46e0976af2fee3c7b787fa863d92cda073ca0cdb5eb3e10c41ad123c4ba41a8019057e6cc6fb873773757a49ec467f05e4f40b54187b8b6ff035aa306bb3614c905bbcada18ab94e3746a9a8890de26d0a607d6ce6966a42f5e362e85c78dd596a0aaf40d0531f728e32124b885e8a2a1525e4c69d21bc62d644c06cd3e3402e39fd92d295d8e50d2712258c246f275743db14676c5c5078daf2114b187e3d388c2cdb7b255467eff917faa1683436061a634ccdfb15883fc7c8e73e7572bb2cfaa30b1d881d146257104135314f4b76b0a13d560df597127f6e4a5f4020ac8ff777a19a2d23ad3ad61bebded43e8e30c911636cdfbb267d9b70e1c0c58d3f4bcc28b76914a8ad6833cac04fc10ab03fff221c81c7bc713ea7473f280c9e03efa129a3a5aaf50222becc98ca324e1f05be59a12608cb9991943b5ffe6b6c10d04527773497bfe78227ef80b00dd4c5d9f1a000d2d2375d0f1a7207f1ddcacbe3bfdb124c64a921d52d980114f92bf6bbe5ae179264b0edcc4154602d3659f67f437726f119b8cd2f1b30e146d50d40f0e8d5d0ffe230e8ae12047a78d45081882ec9a21a856e10ff207f1dc71df5bd8981f93f1d92c838b34dbb0537f19c70546fa535738be15e70abad5df0de46ac0f7a9f163462d43d90a63d6d07939c77ba68917fb5a05eba4c028fdf60ad49fc2aafd4e411e823ddfe8f22f77853d9dd6278f40d8854ff096164bcc0adfa86ebfa6f98535e98635e9c77af6b0aa2b89608a30b18fda691c6e6c1c8489028274f592afe589c68893426cf5996a016a842f0cb34cd094d028f26fb537778af792f879305ff4f5ef60709de935d8c2bef9a58bb923211c38e0fd703538841b8dab4d79942582812cf2c449469e2b3be06fcc7fb507f83a16207791a40faf83270c9f6dd57c18a42b910366647abf58603d199c2a105f8d9eb4eaa71a505abe156f66e1bd51d7bd39b9c025423e7d4455e486fcb851c76df959f10912ef896363d097414f05e67ce82b36c460f20a2eb301582ed93a04baf9fb2c8469331eebd4137242193883f76153a947b8ed128605f7e6e4b5a0ed0cd8025b6300403917f6a9990b450a7c74915388f024fff1431fac801f6539c3205e2c132efa10031141861720bb88f8f41c3768a06e626756035f84ef2081c7d25eba96556a44c145739a811f06a6af2e401439b27696c59cec86663e537e68aebe0691b90608cb4775d4552ca37c5241a14b0b3fccc8c409c08c139f6d415ccb0fc355649c1f5808af09081df2e5cc91f9feb165ae23f04539b4acc1e640a1d2dec70863237eebb92b1d99c70812012594e742493297db99b133f3123ca84fb6676d8807cdb79dbe7f7a27266da58842927000d53954e12991e46d576ce37d5c58b0b48105d78dbe4e7543174199efc526c7bdd2ade5a4364489059e12328e5993f769acd40277c2a4fadd941a53c4d6cbb8720e87813675665ad21e6b5b52a2c0ecde283ea479e759cf9c1c6a1329b5206d270c1eb81d76926e4f5362671a7320ba363081a13b8325b4f531a8aa420a954d616436c5a592d9ccefe8b4c8f612cff3d37c042dd1935be6f53be0074842fdf805759c313902fd8075aff5674a95a3ece0317420ef23890ddc8bee507d7552b234c2349c3c8cba47a1588e91193b5fa1c66e0af66f3a70361e0a3a814c99d93b6c5ceca24c573134ed1948158f2c9f577083bca5a09fbab63fbbf3dd4252aeba4c358973d6e20c9598848c57cf63d910a135f4f72cc19c995ab49b2cf548fc023f8b6bae2c542ca23cbb10c44a4d3eeb048d4e1ec4f73c19f51c6a71009c12a0254414ec72180bc74396c5d127c7477e1b8732fd347c420cb7915a4a65f64c8e395ab32c926518928367faf80fcb13f408cdf0639de8b0139a64fe0b0f7d69c036360f60a6340d7fb85797831c3f3d342d090716771719b9ff8a2ed0e42c9e2fea347e7326158a4e28c084d943f6049404b7a18a75db7025fdf7a66dddcdb05b7efc3f96a147f713c3550a3a1b2d425baa88fecda6a68583453c284330468815ba4477b2c6f7a909c13a8901edd2378270cbb6707c1ae04e5c27307719bb74ea84ce799134cd8269bf91969deb8c3590b9bff935de4307a766bb9c1fae1d303704c0947fe06c5321cb3b5f6dbcc052515c336c6599a9204cf4790c2316f926be29ea46d3a18ed822a302f50b5661bcdf8537855d1fc48d3620cffdd568835eb71152da105e8e63642617dc796d71006f230c5283d39836b108e48871b3997df73a26095de6a19d0e8b9bab58183ca788480c58732da57829149faddb0bd8509400e3a3d8cd13ef872dc02ea6f666542ce53af08a48058907d19f1c937d513c82ddf419a965982b53345e8ed44021da2a7b36f48594eb8807d8ed1f532118836271a94b8780260499fd32a786ed263e62fd421bf4e98a11ac3abc3bfba24a4a54655d7a38edadb6903282cd774b1441a70aafe4027c23d8842ecb2640e44e105ef70626909f126e65b73080066f048b8caa6719527e5936e5b353405ac2ec7a8711d2116aed085c23d5c770e2fe8ab3ee443dac493c8ef4161568a83fe40bf1b07c537cf02521f95b770fd15b67396ff4bebbfed0704bc3a45fa338fe0292cede1359ded05d3a3c180f34d2fce8b595add513e88d8cc1f7b686f96bb937507802ab0e65885b30025bdd187f20f68849e0e2e220d1798f53166c5cd93ff1d75e759f190311557632eaf610e716c9b264ef9284735a495d6290835cdb6f1051a68fd2af3d0c65f206338db1dbd6ed37a562d88b9319cc7fc6e2d516cd0464c479facdc78a9cde85f53150f91af1faa52a13f3c0a6ab7f2958a0d8ec3f94a6d020796be908e92155a3141a6299e90c2c03ca4029977d385bfdd6654f47ca8ad037858a38a139b7b9565261ebb1bb4e8d8e9103ea7c2722c6bc78bc58be5172114ae1d0a48b0365154db7445f1685ae35d07650faf45e883861545992c3873d8772b73a005911a01d0932b01b795cdec00dc3614b23a31b703b7bdc8364fee62f17f8d19d6921ca652f2d32b652eba2a7326e37547e1b01f9f0f7f143604522f1811e114ff48deeb735b1aca9a7d06cfe95165686ad2026ad400718e3106a507a9fc4ac07757279240ffd62b1a0d316ba99331ebf614f617f7544c58f1cffd2d0044733e535b2c916e624317a7aea3e568285e630b584ad9f1180b7a2c00a70e3520c6320e33781f529e158ea8de144419dc4038de8c87f72c418673e7acf20095f59212de517a002d32109fb1a79a45126addce2f76cffd9b095617d4b96d3776bd129afbf00ad6bae7f21b7d1d2879ec3fc73ddacb11b76c592812241d00090b41e6891264dc261088cb18e57b1a71e55974b485f50e35cae4a7e76aff76a486c479e8bed0930c755056e0615e9ff5e5071fa23f1a6be9a35a87f68eeb1b03be8d7a26a4e9b6f1e72db19b3110887d04b253c26db89a4a5bf592e6a0dc4797b3c11084674356f2a3a55b7b6782ca8d56709f6a11ed45598d18ae6d3dd71d1f80dd25403f2b5d5657e517839a3173d7c1b26cf2421af2166bea1fdef6e661838aeabe9553df7db30478c2b2461a2a1280cbf01ede6843ff517c55b12af2da360b7bad434bceab54566d495759bf105150cb6d1a8ba5ef394ec1d070763dedbdc886b20d586a7c83c26c496339791330ab188553cf65844e9390df6d435522aca0e3c30ece132f2db6066054fea7661bace2954b47ffdfc6799065a24b55d0d3255c9f84a05859874195b8865de14ad0de8b2776b10aded637cc8dd0081497ca476f24f59e8d8dabd539e0ee13c0c8bb9629fd305799127d3af0a4e0b1d8840c4b8830a0780ea11d2b4c263336ab7c4f4fbca2ae7396e24d612be8f9e729f2399da9db4f9d7f298970a9063146a945bc2de02978363a08891e589c63f6dc23ae13f9f91870573a514b9aab29072367d0232fcb3b06a08b43407070f6641f7ea00786acad6efd9dda429c6fa9314aa21a2c7d999cb584bcf02fad40a615051e8c82da4062fca0cd2cca77d1fb83da05bbd5723d82072390d818e0e65e26c06a06063ba5883150de9a605fbd0399e7c639110d7b032145b96e16fc901754064c3817445d7e98a6ed3155da31bba1ae1d3543670bfa4347ab3296dfeb76295d2c61239d1727b0a0dbf32b29d4427565b836f62217485c5dd60911d3de556179df54401d0aafec43a3d25ede78e457878c864dc7c1d0b46a2988350706eba9a43704bf946e665b289f6b1074e50621bfa39b79fef8fd25b7344283ab18e3b80a4974823bd08640fd39bb7038b335834789f48f53404dca23874f3c2b6f80c70288187b12513b79f3800158180be5a6cbd6196cccd4f4b69696f556f9fa792c8a6f1e4577954bfe040b8e30d89eb5250aa640e410591804f8c73a650631ceddc40253e370fcfedee2c905055a2dd516a47d2bde44d21b1813b8cd5ac78413e0af46added4499f02d36f611e8c827ebfedd75cde41fb48d27198fe6d6609a43b38c221e2106982460509c79b74a35359631878eb49432deff566a76a16f4edeed978809d4a414efe1bec332e7767a6b18cde95e85f2a51e00e76735e23043b88b183cc518f0876e053fdcd9bffd185433a436a72a01f15bc7ff3e9412a6c6143518331fb0577c7987ce9088303670097e4caae62110c68fe467b4401f4e6e55ecbddfd954194220b4041d1c20d24fde7e06f06b35cb1fd8101c08145b40da43347e3e026699ae92f508ac2a6296a6f24e58c225ba304e8a392e6e48a5c8030aff005095fb3d7ca58b59557ba427942ac7dca7b5e2b0e7008f88172b974a4457e06f69c69554c6ab57c500b74bf5e54e0340d13713b0a911d859a1e1b575775db584ddcad6eb748646737543d33e75e7149cc6d910f90ed50545112c58722f31b3e859f7391cd4452f6fe5f48a6130076928267eb55606e326ef57fc5a0c8cd11f04cc742a427cb14bc25880ccca03fc79de21fb0c04dbedb98337b02913d23f90f0f00f13570539aca437cdf7e4747eeb3ce2a5b6487f07b3944f90e072e68ba7800f5eda512006a302dab7157b1bb4bd0fd6fd033de78acc36782664c50913c46b39a330e2ab56d36cd81748b60d0b323254523025430c11b185e3b7ee90b9744ef918d2f6c0daf2acf1b06cc51c8c684feac50801260fd8127a6ef51ab43cfca6f37ec4601d2a87599d241c92903496ee5fbccf29035d326a453caa1440c842acc984f538d3545ae89a6a58c68904466cb89421fab7595ee0a34fac66323a98cf50f7571e9611a44bd016179c1ff5c7ed58626fc5a73fd116fe54c41fa157ecf84ed1ec6b4e0d13ac170e573966efbf047855eb930e5cbf7aab333468dde053d56b633dc54fbff34738b86b51e9939cc549282a32ff3b304033f6120ef60859301993d4e90c9b305fb45b6061391ad3a4b31a89f49f04cef8521661225f8b85c501036200ace7163c15ef20670ed5adc656995cf9cfd96ba91b3e49ced8ec47b7c9200865401051d90576951b5dc1341fc079220a7c96edadd670dcd1d71d769112a5173f046267f830216719a38d3d9382b7d4ac96107edf20a0c5f4df9fafa233d810807de663d969444fd206d48a5d391c47843295841092be1a6de2d258c5f23d77c958ee8a1c4985522f7816aa638515a76e8298cdce409fb6da68bff8cabe4f76c28ca940a45da7c3c2c7508184c39fa801a66614895c9570fb790efb542cc0b5e113231ddf5e89e4324fb55f02c5b7729284efcd23b3bb817d45eeaae857a5ab2caf7c3264f01a0308da7e9aa17e599ff344006b41ff90a10c2f8a98e9c07f9de11d6c503e242951f3d148bbd0bd2221ffa179016038b7897341372194029ed12b571e7c228a609cbf80f625cbfdc3ed96b4c06b4266f24d32d0ff405db6bfd3a4f66328a0c75128c436d0ec3f180522b9885c37fdb3d9969aec438ed0d7dfe14280692f804e963747bb0a8e25a6c70999af52e03e35ebd2b7378cb1c5a55984d555c1fb2154f187f6028b3ea38e49b980e563425ccf4bbab445ef371f1995411688b5db5b345f426d084004c035133a2340d65aca54898d1cc68ac42e2f7407791668b49b89341500e8ed5d2105f7c25078fbbf7df163d6d91a5c25d98d68424092bf9a69d461e9cee21e3b3ce76f5af0aa0da87b31ff800234d95b642cb180762953ba610c004774392bf0117aa4ec937c51e63c1317588da4ea57f8540de536d159183caf47f4f3098dd9e76d43b48a3105c0d5fea3c3371dfbf96ddd030c01de13c4751b491061972f117a7902d4ff7113a0ffc8464e34a6b0020b4e03bc1b6a40c4317ce214963109f1b0d00512dcae7eb44131c9e4c5045aff247a9ca44968648029564c7698c32647f2b0ba04b425bbad075c765f6906f3191def5c22c333ea119155a0ebd3200d82af90f1c2b947f26615d2145bf80668752e3a17433140a8e2efda1b8b32032c4146087467797470d2164ed98258f1413c6803f2b83e21a098764e71bc4e26edae124c72fdbffe93287af7c9c479d628fea546cb1a74c677bcd5fa50d6413cf5e3561c1dca97e2fa867d0baf6566ddb506df4e0970d0273770ebe8db2793b06a7ab058d3fccef8a2541254479024424aef8f27ecabaf2d72bc6c31eb826f650181b0f42ff378ec27a42cc7e727ca3bd94ab0178ec22d818ba6d6bb7f4427e4f0eacb7502019171594c85c7028107971f8db6654ca2231497e494b49d87d4e22cb45c19e9d41ac72c9a6e617667f1388fc526b65dd712e203cb036b63391e7411c18801515c6b5e44cf07327a4e6089a250a2be8fd60b2337d1a0f36b8e971a00e1ba55c6f0ea4998fcee504c21df2c2cfb24f7b22c2c867b5b44595870beb02946825ebcb7c83a090d412fca1f72841a1c814384d718c3bcf641e4f04d53f07bc2e823d3e0af91a3812bcd791846497141358c6dec18870c508c773d8ca70c7780c1f3d6577311c237e74a670e643882c1775558fd4ea6acddc936a2395eae65890da712466cb109765bc1a0560b044fa337fea30434852a8d17ee52e7e6f3aa5f1136b90d1971a03ee1fe2e8bef3140c78deb7006d3cc462de2e73324fe74b73a9b0e26506bc5d9583e43264176ae59d3b1fce71bd3a659794d2335636b8f121f1b6b6319bc626986dd967ed1da706849614b8e255fd2fcbcc091b760225542a8b4c6a63bb18a94145be7407a4cf88abd6c9935b556664146dbb48e1d78707fd7e5527ba73f8a347e27a752d31faa4374b0f37ea7f3cb3416e8339cad45fa5ce6209a43b00037e065f7aa622b2217649e30919361ea02cb1bccb6d9fe7c192ec0f29830246dfa47367af0d233bdbc5a5b0ae1feea8887b4171eb5add23245a1cb7a37f7c93fda9aaa3f34b6402422aab8d3c01ca12034d28180cda152f2063ae7753983216c2b821fdbcd9803a46c02308642027b92ee90e5a02c6a57f681225804f7195b2b49c917cd6b465e00e03dedd14e9077bc6eb0c233815f13cb352ec26dff7ca91858df2faba4603778e54e52672a1dda5072bb08f2020671e1444dbea669a419ea4a552351a75158e5e43645a83b801ead64a91f2837243733161c23cee309e89d27abe8d343c0c0c097f79a078ce0520bf34008dac5d2e58192d350e09176906d63222feae8e27b1ae631e1a03c8c0b5c56858db6e24a32797c9bb473421b171ce9a9eab50e46207431a69de98efb31f2b87ae3b9f8ea8c8b8483df128bf493f8129055e29402e022e228f91343a235c298d6f2bd82478e873fdc0672200aa2773b2032921aa9c694ea22185bdac5b3e10e71e4e00e66df8eb5a9ddf954dd3e93ac90540528b01e9ca0f45461a09baa7e8c6745105224399e1394b359934d35b2a4715481e80f3b83089386eae1255bbf8f7ee90c9453a8b292942c0b9aebf6bfebea901e807d93209d6cfc122340d04362b5821b43264daf59d2fa4754c18907952a49589191f1d36651a83055290ca54fca1782eb7d7e507d903a0c3d9f0375cebe2efa8a043b8cd77614c567d98b632f63daf72cf50538b3cde6253769ab17bffadb9e030076d03ba2cf304262cbbbfe30fd8ab17bdb257228c6a399697e0044d204180637564388ef0065561875d3f6290c1c36b0b83e249e9e7f2923fa6637f5921056bd7abc968a5e5a4ebd760c61d47e88bad8d69f96452355b1ae2d198770d19e8b1d4b25b33d187d81c810bf47aef36034c6471c011585b6df86f545fa0fa30182d9ea70901a17827c574b243b85c42f90bb305f74dc80b5d6b461a96fa5b897dfb90a17f6e29411415ca97688bdbb093dc822a6cbbdf8d8bdbd583b6a2f5a54b31768ea7ad10e4298b8668cba973140e7d40b2f3aa610cf402fe472e33aab0551013740cf451a3b609dcc8bd08d69bcf7d99761871f192fc2604e11a508648817ec40045c118ea39c2145db0bd057d9522e14fd26f73582175c4f7950bf8b7188c50ec17804cf3ee0ca8c719981fb4c155a40645eb1b48528818b02098d4d92295f124d1e01ab852153e4b9f8c0cf2e4c96ca94f090bdd7e8606b5673cbb1661f287471ed2775811c722746fa53a7b326c970258b45d5dc673bf324bc35209d6e31995bdc65db387ac656dbf8b6165366dfcf18a303a3b9292daa15ddbdbc6445696ab8796bb1630d6e5e5c3d40ebd56c36228b9558cf0348ae0d5cef110297aa0509d4a521dba0b2ac3346c72815cb729a45c98b1893636cd61ceab431fb1ec8f6e3093dbdb4187dccaca4184c4546c0aace0d12fa910d58693be85a7ff905666d7b47326fbb132fc9f4dd87e4ed2f667a67f28a5891796e41cb0b0357bb60cd36258023a974d2480103086272f6e83fda8404225cc475e9ca821b7af5c933e14bcf983c975489b6052153e2a3b46b2fcf355ee61bb311883f65c1c36d7e16206d0e4848a3d8ec636862226d5d8b7b96f95572c80f2985206a4dd0bd3d6243e6420d86bf58a85a4e770cabd574f9bd12ee344fc21a9dc6f370fb9574c0502a868d5398f1518919a0d26cd941e1670d7e3d5844bcbfe49fb6028229648bd06a9627bf8385c90b0cf852b6e39e05210583383191e221b6358a15fee9e9b1cfbf21f627f9059fb3dc9287108e675a53869990d0c9d47c4b84ced901f62c31d525c1e67c7c00911c493476ee5cb80e30ff3984f82abb7214d774c626d2efe75e0e289ebb0e814c5601c781f280e8aa3eda0811b4de9902028fffe1aa41b75bb78e1021e671629c27d3e8d21032b51edb6cda4d7dfb3c44a0465e801910439fb1c5dd7db78ee09a31bc973793469b6491c4c37844f99949d537cc4a802a9b89db1e70e405d617c7cfaa96b52167f35608586f121a2d30272a5a123fb805be43c24f26a93a2c1539bcd8258e7afd721f6db6cce26a99f4512b6901ef7c8361bbbe9910bb734dc045783a3248a0e09262f11d1e77e4d5383a8220dec69eb5482633a56c8fe2e3c55aa2d76aebac524820debe2428196475b935025100ab5ddb7aa5b2ede203cc4542adc157a981607cec38b6ca022f5da4ca383a3f793cdd823f9740559ceb28b95adda5d2dfd7d5fd0c752001a33f2611a270d45eaa3139b6964a12ba7c24e100f87ad3d327a25a26927fa9c487ae74d8ee2162416fdf85216ab0c08918083105ac3eb02f0b45aeb9144e9208b679220fe81eb7b89d822e3fb2c762946f8a7dac2d488508a0ae8ae8e1f244e56dbe7543f6951fb6b5dc830ebe545be867b852fc074bfb6a8458834390ce62d89b6593e261c2c743dbef9332256a0a76520847b4fda0fe50f7d993e8786062d20099c2d13baa4f23921422d68fd3f1daf5ba58eff4b1568207bd2495a13b2817a101e38d3440f94047507d237a757572fe056c27e6492c494dde8209ee7997133557789ec7ddde36aa13f7ccbfc1bc628524916910de64536b13970327e68a317892073378ea9ea18d673575343439f575bf9f511d26bc5000cc303e80ee4c4c9886765434dae609440a9c6521cdb4efca8f87e4fce244261dd7b891be6709332f9321946c71e44a698612d5c68a053af5b6a9dc94231b5259e21d7c03bd30dae71b0cbbd22080c76f7e7d6139f0c105277fe8c45033f9540f19452b396b1563f13092ad198df4e27316ffacf508e048dad7c49ec8a8607b200b9ed2a7db5ea8219804a4144adab59ada469c84b7b8e10f346adf4a5fd0b4f5dea28ff6da2693660fec7b83d5ccb620dda69be0f0bf9f3282f68922dc9c9fec8b75c96f220939f4c05019fec667025864d8b02b424bc6fe22def2853da047a2cced285f4793d23c79562b9c8c2034c0656c76237d28624e142c7811de69c40941e6b32286cb90a42c97c5120d3c34adcb4c2c25a39f6371655f645be7c00204b18688f3172c5cfcbd3867c9b35d3044d330834593be16ccc2196858488612cff0c0b553713293c9946158677b72c7a63be1d09c612afd71b1daf5e744e1e72b3f80b8bc53bb685a07a85a956f0937538222b4b5902f7350fe4ba979bef5044e36383093420b8d0cf770125079308912a20924405def8ebba4df3ae34244e198619ed2a68462841850af494f25dd20bcd8ae25547ee1e0a01dfbf14bae96e8a2173fcfa516597d471729ce032b8738a695fe2e890eb2f69975224f4bead43bfb292ace74a3ac401003c29b1122e58885c31bc6b10e85e266d695c09db35e88684c5d443e2eed085809b35c6f47001cd027abcb6a084d4b76c277ebabc6fc55074bd77129e66f4465c063f6ae8f3db331c69018edc2198bc858896ba9d6bd51574ec01c1866f1190eeefbf1de8ed1a52075d9e21fad975f2b96331d33dd35c051abeb6b7b827831ca2b5f8e4f1df812966f3d65429c6771644c5645cfcb3cc8348593c8e97545165963f29bc4bfcbf71cd963d1646b8a91f8800a7130ed7bb04e98eae430e1f0f6355d43201f6049b15ee639974038a86caf5b349fc139cec64f5be8d170dc71d28f34c2cb498629cb3fc0b0cb2f87c6a992cfd2e63d6e0f42f9114e060ede530e3de78108cd465f8495fc14f09df64ed7a814b39611c1b03c3b6086bf7d0b064ae6d62503fa721546fdf70f73fc8ffd1fa8fd5e6008dfc0ecd7e30ac009d51feb0b1b19eca203124b790c9e5c3eb199f9ab4f273727ff579e352e24529b007ca08d0b37fb8ecf4c507b902d7f2be21d51436be5d1934b22970d875f38ba31c5317cd1910f2941abbd8647c514d1f0ccbd2ee6ac85dc8b58b1da2b42be375e5305935c61b024412d8b462465e3f323785c49d2b3c1bd68353422f44d675f58a7a83ec0756aa656ab99c62fc2cec615fcdcd5999ca3c9906f292795bbf727c638c82f495bf06e9b29c14e737a4e92492301033733bd99b04fc01da5110acc17721ece94f7bf0215c6996e19db9aff7439cdb2c69c45ba708bc186ea6bbf49f0662708dedd852d4b40f5368083d90e448b2d1696d5f99b9550833976c7c96cc6e8e05b94d2684c0cdf29a341f25c3191128947e41483320691f7a06736b90b5d035ad84c967fe7faa8ac3aff4024a442d73d6cd26e138feda117a8df9a0081c94c794e6927e44fce286a81b38a9995a2c07394de234e9f6002ab2d8d30af2f866418a437ff8798523a5b3b50657d0f56e5dfc08a4f8e83df8ac71938454ddf0cf1259d3a917df9eb8741926f09db4f75f9424d604061f3d1d031ba6b67dd124b46f9a1195623a4ca8a4d25fc2e0030916ecffa749f3878b87901ee3f164509af2b39c8972d3e412d940efb52441fa6d43eee74583ddd12e53e464a6e14d97077367e6884ff9b430aea2aaa61fb98f40f7ada86cad0fbfe185a5bf4d985d7fb95e8e5a8dc5a71e29a98e865a810452f1d44fcb5e8657a323117d69f209db28741378106e14e8220a2e29c774a24f33b1e053037f13baed672eaeb129a81f8e5f28162709a7717b8bcd72d2183d47c23b83a6a19784aa7f32c70c4680fd4b62d517e899f265376b17bd9de027708b2b4bd72368d78fa7d86abc45003fa48be590c864863106273082f68597083e72eab1b58830fb8c9dc5c8bb76baee75fe46f8f526feaaf16f13239b9585e47a2945d514af4a6a79d9cbd880b15bf775d69262c7c00d2e95c656ac2dc0efc74515f03890b532ef0f8002dc648a28a58772d6177fd98a81a29844069a4e468985a9ef66fd78e90359ef8a911c9adb46a4f09bc695463cd6f1613051e8004ccece36e34257d99b20e9cb2475bce421ace67fabda9940c390b7c9536ceca715f45fea1d66f1e6b3c40978a83653c94371b5d24b4783bf4a3089a6a6403fa5cf7a63a327f18d2bf6954ea726546b0716a102b3bf37466dda78a6ef33698497407ed008b688d0cf0b352c0b62b828d3ec74b0050f08cc22d5ea19830bf658e87c6dc507f66a9aff7c70562c9fc4f8cb15b850daa4b0491be1c72e381b4fa529b6c29b3385138fbd3c5ed0642b260da32049d2653977f90906172db70afebf0eb7c8cf9f0250bcd63c3ceec566d17a043de64a0ec057e0045b3f6322d5f52c85bee5c613427c9340eee252d0381edbefe1d8d3c3143b95a38063e0d29c2473de71a9dc7bc2f8e6fcd73b8b230e07465c388ee755318e01163934b3e65879ae353acce8e0572828b6139063ff03e27d66f9875258b461ef26245c6353533b6f49909131f024c7c446acc1a678c017b9483cb15fb3f28b47ee45b45deb1b0172770962b405193cfeeeb3388f151d13ea890553e8375d332e0ff03f1e3b25ecc611da8d48a88d9b7b9685370ce12be09f2cfbed6abd2ed12c6a23e7aa80ed4b30f3984e292f610cdd37fcd633fa47e1bc82a16fe105cb64fbf4d830dd943ea00d18918945945f0d41753c2703778c5eebe4b0e9b1f64884596e80be33fe4b146d4425c2cadc807a9e45f1bdb2334d526ced0b1c775a1ccedbff951c2e7989656ec2f00a65808e65695e5b37a0438a5183b7441c043fdc96eca2faecef3682b4eccdcd645ee46ab3373465b72a023666711f9958d588ed9416468bcfe1fc509869973ece99ded5404f685522841272f77efa874e023438b623b04f49da5a2cb5202542431f9a885fee0d8561f38b8527e8eb92905f9263469557307d76c45bc02ab38a7432a9cabd11ba1f532573bf687b8a78afd87e9dd971be83476e85d21b8cef345cb7d3991a7a085cd38c697df31ecdc9951ee2187f830c2a6b97a9887597b1bbc25d1f11f2245edb919cc989bdbd52478279984eb75f8ba93c13a55529d1f2c4a2150745485668cb3f48018bd22d1f2d4eae24f793ef36223bfa366fb5c3e633715fde9aaf33e25e0b457548f90a25ad660935258cf3a8f3cdedc1105d678fc5d76169059219a356bf6eceb25bc47f62ea5d77f77bad716d79db05c2f529150034ce05b5e62855f7c44958abc65380bfacfcf7d04f0caca6089dd164129ab2a74902c980f864924b6eb5bf131670178ae947dc79506334bcc52d8d417c638a6271fc0266ca88d42f153608a6069769e863890f647e522b64602f3af288efbed360b8bab2c261297d64868843af1262b8a1c239eea10bb0158939f3b2765e5f522b6a86bb956068b8a5954f3742da72a662d2db075ea38ca60cedf9b2948c29abe06415d932fcd9957fa3b21457be87d9e4f15ba54f07a75a04ded45341769ccd74735847e27377bc93debd575596339ef4fe018191c993557efdcae5b96bc90526c27057e7ad8c0a281db23ae2ab46c230e3aeeb6acbbf18ee7427e72383f1d2d363ba7b2be34e7243d359af5bb39a16f82add0e1d072f2222b09f33675e183b30c02caa23657139f912286fbf7d382bb71249f0037f15423987068b9deaebc0fe6cf03e4a45e5c0a383c473be6e058b526cdb03c3e92da008de547db751605459c264b7b5172e0e0bcddf129085c8206c10cbdb002597883a2db87463a08289131ddc89e15a31efb41be3014709252f198a46417c07c769d34dfccd02048040ab9eaf0596d380464214bf9595981f0bfc3b01a13f695ea7201ec264b89fd5a5a164a1633aa6ee8b1a2f3256d465654a62265184d073395801ac1463ddfbd2a13ac0777d45f34813035c38ca784a3b621904bf04b2baa7e0efc9e221c490d3315d88332f161a6f0e19d0a58bde34b544b136193eb6dddbf40cad7dec711f73585c507c3b7ea1a27a8a8d8c1374049dcb45edbe3e273d5c5516f916bf4e0c7c2e61f2c317c0d8dd6d3cb4ed6e282768d71a5e2fe4471864329e4d2c739735df5bd27d6958eb6a556e9a5c11443069b43469ef3e8d9eb9aebddeb2f887b216f3e0cc320c353fcc3dacc7627f9daa14e577860669f7e2057ca1484af3d7a69387d172ec31d2ea0067a2ee88f686bdba99ea2401b3f12f0a7672c5101675484d197b91f908662cd2e187184167feeb5fa682b11431192ef7abd7e2fac6d46c50ec8182fb22a7fc4e20922e7c5241b8a719702165dc82f65df9f360380c226e8f09e133d5330bb9793998d8008a6db5ab7a6bb09e3cf84b56210fc50f28c5713969a64a62a2bce62a0f157416e636988e0625cf3d8c45f7d0e276982a128bd579d6302e7889cc9ab8f83601f8238484b24a3d6759f7d76d81b7ff5437fc3b4476529852043ed8ab9f6fe110e38b0dcf49c554e34e00f4cd64db3657398f4840f4622eb75ade5a011b1ec4a6c4b7b833e8a807da479451e8ebb10afdf43b959da24a38652d0602f11ccf31376c3719b5bab1e7e156e20082bf1ec807e0354760d38bac6fd4f913f8e72b61511530698935e001f975c17521b62023c97db206b47b5bd38f7751ad7d4b94abcae5809c48cd1ffc4a36639a63644a9ded37143d43c1e4d8df8c859b912a1c63ee9cae6eba146733eab84c797c6b90d549a3477d06b9cfb9743a25841a089b4838980dac299c1ca068d7dfadf7778bf01d904dddfd11df553b7afc1e5bef87ace6c0e4b4a8a86fa3dd626ef781e2fc9cacd215894f680a0d9b6211e2c10f6e37746adc93c7d38b9c48150af14805e80bd6f64e91cd161c53115ee0d41a9a6c3af786db4c08e836635e2b793c748aa37475dd55593c36bd83447b0014f7c7f5f24bd265c2abc960626582174597b644c8f0da317cdc8294fa8ecc975f690eaf2fb9416fdb518cdbbe4d02b362007b2f239ea52fc448256abd6bf9d61866642e74a10e7bf683722d6d890b41a4df2b0bd4decd29776ba32a5af3b4626046de0c6fa7e3d6093db0fc2c3b184a1da3aa8774bc0d74ef9d069f4e4f8ff541c610c60f982748ca14676ac23783ea77cafeca749428e9171f8260f214564410eada148ef6c4585716964c94d6389222aeefe3aa9f2f32cc5a7502dc1c5233dd6f744e3c9b84a7aa8510ee1e030b5eb760d90fd76c23ae13f4abc002640a62d35ae1853c5ef3e07aca4a5820f340e4c08e3288b4b42f5278dc7cadeeaefe565102d67dded81698956bbd79c2bde5c6b74b151fce6d0d345d9979e15a18cc3447837b3d2ad8bae96d2cc7ad1150ae93e92be418dd4b056a2990b21705d98ab30827a7068e06c0e05a38e175f0ad6c1736236073d6a9ba316b305aafbaa25ca790ee8c60a3fbf5f5a1faac8f18efed05f9d914302689c894bbf5077dbe8eeca8f542c15ce76119f3afe09b1094723eb7c42cc4581bce60829fe820de8ce5a0bb13427d1aa034cf0a6c8cd41cbb2598d72a4800e92966a692196a04f43b56dac644094d68be58cadf09dbb726e1bfdad65fdd0ec89b0084391b911cab4ed3763e652a4c2940273f404f71fb8ba091c2a7b7e957f372720b506967d46b1cd82bcc62f7873b14ddc60ea6b3e0906a902d541c5f6ec36a4ea7edfbd0004f45a3578f23fab56f538cd42673c93f6ab019aea3e5d672b55af3c8c3e11d9128fc7cfbef6eb04b62dcd00ea8ab980b94616af838a500b31f286be8a839b0c45592d56b26d840739a674cb1501f4e56b549bfdf2631880a624a01a317a80ccad8a6ed562f67ba2f80dc1564cbb3c00be6188b4b4fe42f6f2e514b56bf4afa590ae2299f5331944e766b447ff76c7f2fd5074baa9fa5bc2aecfb5c7978856a688968e2e270027739279db6a24124f81090939fa168ac8dd672a3780a3afae96b5d8d11be4b81cb49539a3d3238261d0fd5d55c2cb9f6bae74d0006f509aeeacf616536994488f0451a3c1d42245e4351b40ef524b5d9a7ba3eb71d21a5bf53bfdda89afd472fa6db8da82256eb6781a9eb948940a17876ca9d836065ad6e5754ef32321238bb59b9ef5e09bc2cd7e43e30dea9f6f64792f3fdc3d61d6b03fe1e2c75cbe0037a9793e4a56c331106ac46e40e115aed2ead7fb45f3369cfdc3eaeb5fc60a392b9634a02c03fdf546d70d975037c4322d56c54c966f744520c671c09c4d6e07fe80d48473eed9071589add36b74e325cecd515b7866706e7901cf9d62d5cec8071a7105696ba6a129a0cf3a89e004ade10abb91e861d132df9990841f968d7f3a667769ba1e97dbe9c4b980659eedb42cc5060dd11aa57877e19560d30058d0e2547660a35808fae80d7e13bd416e2037f96e18767b65f7ae1c8f02cdfefa4354a701ee88eed1450554c2f825a8977e6cae95d04f8e12dedc7af77ac60926adc9981066b82c63b81db40c77f43e466f24a789583476c4df61b29c1591d1498ae9ce42d276871bf3866a939d0f716c8528245878abf6696e50df169e5897a6c6f8a33765c081493d0d5b44007c64ae49e3c10090e2fe261e0d280d421814a063e85643d80f3d40677e266640b3a2a4afd747b34edbab232b3168f8735733c2ecb327aac36bf661d7c0a1c4f3cead464a8525f41fdfff64f6b50c5810aa462659e5908744cd19c41123a5d29695fb59af777578af1014f5bb2f6c90bcc4367dc0977f98406110c33aae469db8ce2886cdf669cc3578fe91397c7a1d1cdca5a1583056ef52fc140684c2a0bb5165ddfdb860af52f5c5b091ac5bdd8ef9081047b1e0e891ab4af4b1896ab87ea3b303a238b2cb11e02548bc63ad6c2c1906e9f219b195702bb727124aa4f3a03de1eae2c5c136d9bc1b08e21d417613ce7dcc84b3d2bec98cae487b82c09882218dcbf8884326664424667fb579699f652966284b76f8633980790eb78936f3aed231583b1c658a79f3406676b3724d515877d60e4085a7c19174dc689579e087f271fa46d305708d46f0e927aa43f7b5d2a3cd413d7a31d5a39172fd473943012b12087d118d0ec1c7507f44983b83a2e38a5bfac0ceb5bdea55262beea3184e22142c046a6de75ceffe4d02bebed1bcdd8e68143919f1c3a0dfecec132e44578a28426a5e23a3baff3ef9b8ec00f38e1df3592304cdc45cb751222ca25a869ecb8ea27f4783a1a8fe24f9d28e04a0fae3609eb8513ec6c54c5c3e948e046f7a485d81d5c17dfed5866a26f5d6dcf3ad60e135a0d224a77065331ab099c87af23d70f6d9ccb7ed70ae0078f1f8fb592fbc7a8c435a76077d1f13f58fbad362bb937a6d0af350ee0a07ef1618e341e22006f7e3236afacb0465f380c855cdb9878ff51857740a23a78789ad9794c511b4648367265394d7ca13ea37da3376636ad7aac7a18ee85a70fa00ec6a05198fef32a2a71adf5eae4c8fd0928bbe18c9e09075df91d47a526a0d2a9fbc0db57bdb3fb3facf2fa7369f4d84916c7cd01a5ebec54e5846670b6219613d7704bca657aa8e407e0a35fe19d899a4c68e463dff2ba91d93c6d173664f076a004b0436fa8760be054ac6b042663ca064d48dda7a4b60b23cedd98022095f2a45a2dfd68f301ae72f813f27dcca21f7f803531798de5e611044ed89f79268dd7f037a94ec8e5984c9ccb94fb0fab7da54f65158702b35d905b05e612891ca0ec05eedff46ceb3b4ee3e60af332bb650ce52f7b366c09dc79b66b58b4b7c32d72f8cec9313a7b7d585834cb91a0d65b5f3a4852d92ac767984655293865acdd76812578dd828ecb7405bd6356fb3ab462a5a48f622a923002660a5d96e51c97e08a4bf8eb428f8095c22c4ca860496143b6ba423bfff169e6985384a18aa21f818ae1a444255441e934c474b11308ff258c24f84aa2095b0cf76270d0c5efe5f18f5314f4bd9239d8c7894f7418c32a3d3c81550cc12be57e8979d70c730e6ee6af548395c48539362a4ce24cd702bdf37bfbeea893b357e8492e48c4e3938b67323294c09d0f60b57124a7520a640a6971665afe49c564a4b185e60a764efdb5edc4aa21431814c7cca21c29fd774e61c2f9887a82885f5ae9db4cfc2ca5fc938866d914ce0228d34e794b36ec8619e0f0b3965031a73c2a0bf6d16585d03dc914eba26295e5edb4379a897b460b16612dffa8c1892fd6175547b4ed87dff392946b9c1d2cf3316d674dfb81c3eb2bc7ffae20ce641755e47055f1e536674c8198800005687890c686d2b32baabae194945c7b23f6463587566626b1d0135c7c654034ec858700d7248d0246d740e1005972d9be4ebe2003ba8532c84dda55b7325e4d4924bfe21a2097cb806190caa4dae85ccefbc3a64f228b7838e52a161f13c1ea5c294bd301ace88f3d2def8897d3a8c7eaca6e4651d463ffecbade3f64b6036a87f536e71a6e6fe53a756db03b338731eb4c9bb084e1082b3dfbbd49379c0a79d155b96afc31913184df3070114197516117261944f9ba22186b4188b91a61e9b144b2c46b414e73de6059bc94798a863665266a353d4c902ceeaa3c969f3a16e4010f0f9baa8bc7276a4d0dc73e0e4e3610552e1884e701096beca4d557c75c470c1ee18a3944e067cd2a48849cd0563943112c8cc8734f3078544b060400564c8bc2663269d444604b0d014d892634edcd48dc07dd31d73d1426ede3dcb724df8e0fa0b12384ff9d748d104940e239cd5e53723d5b752a90994a8e2ae7891d70ec346c309b40015c2c3797cc30c80d986aba8b6cc0f2d2778c0ce2f413ac8c98f0d8d898854530ace82b259feb8883fd1befaabd614511b87d2bd28121488a8a7624d09c4455401f814a573dae35cf1b2051c94e4d3d5e664b6d780bb27e7e5d98e4e003a9ffc330779490cd3b829049b415ce60642a309388023a82002cbb6403e2c0bc9c89ac21e0d8bbe40602b4215c3126171e19de17f5a01085271c3018c4e4fb22162a7ab1b827e8707ce5add7633e30eeff982964bbb34063cb98ac0a0ee9158a445c218a42446a5195cba3f15f3c995e238c7c0a47da47274c8277883db371ceb322405a1191d93223a6c2211f110961a3090642ef1280c188bfe83d8eb526acf20a297fc6697cac3983c9848f2af241f940355ba2a545c136cd063669d7c6a4b8242e8c36e36fbb0916cd89ef2d20c97164c11b02815da1a35178bfba4aa6a4b0a41d0fa70fb9873aed758295f1867630f450985a052a515c63aac91eeec0157f2f571bed53b892fcc36d271977265bbda205a21654835b3e113cde6c8ca16189a6c0c957ee6343302235b10fd0a891fab36cb02d0cc48b95a1037193250d30566b43ab8e90e5fc5dcfcb610379080a7b7f10639db298a70647cf3cce1be3c95740071a799ee238a7e09a1010217b6c413ce767f6f961135f6df5745840d213b9812d2d8a6015651f7afa82222f37901905a8ce2f6f65398d5c4a25c7e721cc5e7c933121b4bbc2ae4b0885480e1921035136184e93502cd9c4a6f41bebbec6c990029ff1a3676832c35206da25e858f60bbea60e76463dc56df84e69da51f557e184c183d2fafac22c281cdefb686a15389635030f9b2e712e71f6375ea6f856841e65e9d32ade96f148e8cce6603d2ff74e263d251a6dd6f653087406550deeff39a22d7a3707ed3d91cab72d1d862a27104dc9a6ffdbf74e580ac88c14cab5c2d417540ac46c133a5a9c2da742238d7a4459312675b1b836405643d2fcee7f307a82a30919f9249fcea87142b15c241d869630f04960d5a17a079f427d207d87eb2ba35c6714411b35b5a742a839ec8421b8969e496f6d1458219fb9c83a3cd255d0c8a0c496f46861b40c4aff853aac323ce3b3102d8be60398c026e041ff64782709b570c5e420b56eacd47e9bf7b053864a126968ed858da78a3a13c6a7eb702180dcd12941109912ef52818f8c6409bf0b110e30059460f374479d37fce9dff2212197f7b6183f8938cadf98d207ebe6a861010d483f36d1635d5fb18cdd7ab2bf33be0e6a9e17983aaae1f9148e5f10c16be20b240ca4c7b844d431aece820f736d098b3913f2339cd5b9091cc0df2771242baf0636ada1f940a3b459a3e2cccc007966b4ae636cf4e0b54873d9307d6cedbbf86dc8dc005ed211724d499dde61eb42e8330823354934cb4743de246330cb4a0e469452468e5017b20607341c83a17f45abbc419a72dd38e56beddc4353ab5135cf8b7d5510e315c28c1299429b0779d2c13a709cd87fa8a55eae0449c41882d8b444617c40cf11a6d5053ea7ee3321026bf66a8a66f4cf52c0e9d6184790c4d21b68b60cfab706c34b5c7e1937ce4841e7634bf0ff0e4b2ebeb48ba687802d3204b815e549454a28c801636ac7679918394bb17531e9d688a9a5b877d6df7a9693cac6819751ddd631187dc15fb7b2cc5f85269db309644b5e424c06ff0b11cbcf8586ad1c7fb181f8bb051c74d77954ab674dc1762994a09d103a89e3cb5aae563fbc7c12c16fb5838d72f0ff2daae7d2c6c80362fc653fe84b226ff68c992ce81b5f95e2ada385b2be6394271a74507b614fac8d0ca1df500a8e8448a665d60f98a07f90d81b4fcfa9175877ae9a74c789cbe5d11f8733bb167ab40d9d86c6576a44293e560685dc55124b86921fc954b31ba9c29521c4bca815485539ad42bc13a4a5638e0ae2804a74fb4572e52dcc249c3cb26b8ba3115166378711183a85cc5bf48a1231029f8422f73be296815ef013895f80c0960279dfe892af4eb490b785d1a6b8077455cc8cdf50e84fda6b33e352fecdf2fa537fca5f03319147ac5fbd6e2a2080f9fe45f0a0f70d3c244e6ec38b666f670751fcfaa463ba697eb197762451183d5ef337fd0072e06bb84cd3852324f2cd3efba3a51f297ec6a8a0d92738f7e86b6664b3e9664e1911c1ec960b0e491f08c3cc6d27feb835abf04999812fede61ae1429525cffdf0a044b9702fc829b358a9a59524212d6657b5c0aacb7fc8fd6dba743a195c34a6fa32f59e2973cf2afb5fb358589309e7c583786686f9b9e9796c15d6ec9c186138c7b5a9eef2a32d4c0423c620f5a8f22da424bd66eaab6432c6774110ad1290400124c0843a5c3b24c2cd0c10015fd5d73481300a1af705a744fbfc57d424926dd46f17d7eaae0812c6e6cb4d1bbad16307435a1b8ffc9cded254299708acc0682b5f48cc4daca92924f7670f3c4b78bd4452a34ee6340b530b9720040fb50fee4900aede85d1b09830b8e7b48280645ac8898272b6b3e8772a0e17c44830685ec871e57e2f9e02ad4c6fd296ad81b8654a8741bffede199739777642039fc15ca6ef3468c30ad1cce3f0682bbe0ac813011e2d281f9c68b18c1aed10598067c01356bea8d78244c2749ba06a00c651e5102b74994c6beabe8eb7bbfe436e1232b79d61b7f531f39b7fc91a11ec1ac141fec0101409cef073e6d41db65a9272498506d3e7001025e3e50e414a5097e33cb9c93b791af054b52f378840ab3c201f647068b8ea759fe770262fc483bef78eb9807f8108ebbd1fe6d870fbd437ef41a3f0299f0ef6029cdc0cc1cc2d6452a10a84b8fc512348ee56d91e989817eb397e810020204db7702a88ccf40220153258b00b1942d9699a70c6d22a1daf137c047959c60f9d3d6ef51e44727ab185e1e5c5a995634a6ed34796b88710235874fa7c3753f1d3099077d954ad1248bdf52dcae688a1733a91dd7a620bd81194b729b80644d0135c66fffff86461faf9f43b058ba1e21ba0a48666819da785d5e4cb0cc1e4a520e4dce70ad5db7b12691770ae1ce3ee97d187af344f6200c7f0bb7d856675b11e18c0f9461936e3586bf4127995ad279ea6e0b2412f7fd78729d191787768d01bd96af3d1d4d71884061a817b07ab67da1c36fd236c9235005382b3dcb7c2ac4b484fc7bc74c028927d82ce82dac7b7cf7b2a923a41b11cf2467a6a5f4560a3cda91c2ae2d05a9cbeb2ff04f3e6d30bd9941ac63d4c764e4bb16bfcf6edf2d7a54165678b3cc22f9b1d79e7addcafad4e5dff596b37c79449feb6c180fb0764a69c158d6ba85accb8736020d2deab5e7442647c206428cb3f52ecb5d83e1dcb1f0c0fa312dc6721c66c9815db6bd6ae2073ecddb6cf82292920a3cddbed898d2a6305a031b74393f22b9a5e099385b2ad6e55ffd69bed6d73059626648aece9109889d83563d0a1015ed36c16d9159a8b201abb14cbbbc85442242a5592ca221407457c5ca316e91edc9b724e7d128c258c981d9c45aac6731037bfb085dc46995031edc7e31c8c6be2ed4cf934888759e2357d6f4ac548c563334224277bb9f563eb32e1de3d5c00f18c26e8bb28a70c9880c5503183e9c207a98c7d976a093f0d9045806ee7fa07a1befacdebdce0d405e51c50b76b53288aa3889dab5ce377bfe2328277a1f3ed50f55b28c8b1e09ad6e7f27cdca2344bdff5f5881ae06ed8ae972bae38c17866fb02e83b3a3e09ab1da25dc64e74b05928a4b0c78e39b7fddf265a110c9bea37d8cf7a4f35f40d4cda724d9ff058f9f1cf6e6d5fc6ee1d266de223e95fb11d58b7dc92aa7dadbed0d62ee4c9467eec20a491456d6f57ab0123cd9c0aee32e867034d10489fe2712d4538b8236a15aef84cc838d990d89c41a9bd8bd70bac2186d3d431e4907612e47518367021dee5246a6df874956676b17d8acc8afeed906904c66b9540db8178f005c2432db1bbab32849348d4957e4c988bda23f788f54e78e076e82a495e0c43e8b87d956c2ea0aaaa9e79c06907914c1180b5a116cc2ffa430f86b54e4248d2e802739055aaac04510e8d7bce15e8791a5f0cb3c06bf90e0436abf3b0c865aa7d4d1f367088e178d1af181eb233d7b5879cbac76962f1ec9c736c72f4fb44481f14f682aa0b261bfce16e33dce7383d2eec27b57acc8bcc33d24bfd2386bbd233bcb3320a7e067337e609acb1646b3372c1d809589b583876b433f91a7a3284d551628b404c98cdf48dbc361fc70e61eee6d9e55285e35888105d1a3f99a1ed22c0dd12baa112a3f6988d228bffd219179e1c48cbbf2d17a8f7cf9776fa30f86d8e13809088bf904594962936df14609fb066903c208a2c392344ed5b3a941cbd068c87d7f1db7114e067c331f4ad2297fd8c3689a5981fbb9730407a525fd8050a928c88723d8d7a495d33b94088d0dead67d7aefdc00af8138094f24e0ef38124567f9df882a4e197a5c79c80f6c7ee6731af8e743236aef55b140e4d068a80611c59589a4ded7b482579e482274d867ea44a9c5d0031e8d63e53898e1cd0c923a23eb1174805b23530a5c372b4af1cbd7b450c78794ab5ce33ee40a7d318cc91cb904fda62a2b8558343b00e8e728a9fca28653f68488785387a2af72dd8df1039d8c18b5790ac6deff154855a89812ea64702da4c6bf3ea9be7644e4b195ec6f553f2f4124e86be489471e015ba0ec79eb251e33dde023cde46344bd8eaed448e0c3f7a26299ce5ad798104c3f66ab13282b732411c18a9a40dbca53a6ad495d32e85f5bd0835f73c88f6b16c116c2caf66adfb657dc0e1e27b7c31549e72324d6d76e455fe79f9bf6c0ab741cc722db13595368914a556d6b330a026186767ffc1b44ca743b6fd8f234d94758fb2bb75dd99e623f7d518f97be7621fef66d42cc1a666354b176ca145a48fc6e9a878392da05adc2ef11cb206f05c64218b8b649c2c5704153fc384c2225c61d8958b28c438f258d246efd5b91e4853aac2d6681f33fa8f529f20ec4be5f412a8beb9b4b05e3ed95a7e2b8975a55d5a81ecc1f118031b4b07d03f7c6efddb37a8b4df72f6fde37664fee665cfe6a55c3854760fa5235fe129b5bea670630910219faabc3aa8a1bda6572208a3233e962e6e602e8d1f189f8b0b1b334b18212fece3e57b99c574f47617389f5312f891c6d62c6731cc341da66b6f0e5b0e5d34114b19fc7ea093540730813d4e6782955b9b0f8dba5a9a29095da0aa9a4d835503194a8ebcd31921eb11a8aa1d3e4cbf57de56034d06fbeb2603660fedc1ddf364be5c2d4f0001ea3c668ced2e2ab4765d5da23226956b14b9c01e1a4f8d114748f5b997106806dd65a79b4bdf26356aeeaf3f2b20802670a333380827951d9343e97c1eccd542b4a11fc5a8e4ef6504a7f3f29f82d4037e80e5c70e8420361c67115e22eed04c0f2daca31ba75a7b91de09b1d71f56383b8c21c9e749f1aabbede7c20bd101b54e602659426aa8601cfd774c53767f6561c3108894ee78233d8bea19a82a4cb48c516f0eb7e0d72319a4419983192bd8bd0ec57c566dc068d1192b0eb41cd560108f50ca9e0266d1f246c02d42fdaa3a0fab5dcf84fc0c7681a0a3774bbb612ba3dccddf7a26ef6a9103cc496c9609a7feea91a9b698f5ac537b27f2010cf2336975f07bea96f7209e096c6ed513fee581749a3a97b992ed69722c74d97e6a7f59e48086728778a64e452beae4dc4faf9eada54b91dd59a5c029b3f8485653c290844b24cffa5046702ad88000e10e2b2bb2c82d3913bf4bd8dae3c221c5869a6b1c8a22fe33cde5a584dca92c5871ac4e055a22ce70ab20505f3b6067a33ff1e50b9f6aae45cf10bbf4f2da0ab84a583fec053bbf468ce3a07e59c0b4700b1d8ebe948d8eb61adc4f178f45a417ad37ee48f391152fc2d2afaf1519d8d75195c751d960007ef47ad02dc54a9ed1dd837858a1f8a1631ef102c90652c5720dce80595943cf977086e8a876d9d71daf86bdbc3ffd6d25bb0213525703a2a3836eb15bc9206648402565762df24af08314706b9d8c47b6ca0b15d858ba88b5cd082518f985f9cae8ca71bd08e1c391bca1135ac9c545ac7b1dd45c784c56e167ce25a43501570777c29d135127dd280e7336778973b27eed0f1b12bd72d79e68c4635a4a58a16a290912d7c28a2024b4ec00a2b4bd697b6d72179d412f9b09acf96f4bfebb0472337b7ccaec7dd70377229b37fa123dfd5c96fa22cc4c04063dea548248b9eb5c7e5753c61c48964c6d30d96b00e500991f2f33ddcc0bbd426a76d9e370bd5d328880472ccf73cbbbfe8967edad40d0a89d4b9875d6e995dda4cb385380e8cf6198d9ee89b59646ceb4c363dbaaa72a62530e9fded1dd8a45f08d47dd266622a700c77fd3264f43a1e7830bc7035f09b04790387f68f49c343522b1157996424c966c0be6eff22912ee0f4fa9a2c1a559100a2a5a3056005d2c810bc9c5b821504d420d588a8a902f18c57682c6373e3c8d367fb10dff1df8a58e9a6a74521c0c34e166f1a8bc1acfbf671edcff98e85359ec727a4db1b7ffb113873520773f46a99eddcf55120122467e86b2cee87f011e4d62361592e01ece0019ee9844dfd2dbb54a2a7b26d84545b7c31956a0b77d1ae9cbf5829945e2dc14fe30d485d06f330b08be834080a284bac257db59d477030abe94b50eba1b46fc71a9783a4d625ecc88081e5a4d5c50e512faef9045cbb0d3e047c6235e95adf915dae18e8d1c82e2b7dec82f3952f302aa91c8dc38bf32b6dc02e0a65062a479f47412c4b4c57fbce6856793bf6205e5aedeb0cadf2254d5ad39adf700da2eec3733d834a247ed2df87993b04db71721a7c719a7f7458a21f4239c0f7a4af5ee6495d6451a3b6b532f7f90f21be13d923054f836465b18a8501fbd8b20fc31f57e1abfea0d2e0c0eceb13bf299bb0e7cb486db68d11709a102285d179809469706351f00fa1a95fce1139df6c9e9b8030e32cc060450d337cd42ce78c1ba7ece10ad0025d4cb5e3349ac05c11b1ae90158a70261d7e0de0f9d143b3c301fa3d4003778d682ad2e3d0c009bfaaf24b2100aaeb449405891c59b927948112a1668dbb5ab7e6ba87f78bba45151b7f430e6b3b1d20c103ca0b4a9e41b0c9806f11fbfa65a0cd0a47ef44f34ebaa578042dde0740e6b03b9f28e26894638902f6a57e1fd802b8feb94160368b84f60344540872f61b180634e25c17200103248e12146fb20e42440e0d2c2e4804fa8469ccd73c3b7d491c70953beb5b01cdc166ce7929d1e988deb4740f41b19661b4f9a9f810b4382b45de6a418d2d57903888d6cb440013ff974664237f34d55934f4734879ee339210f1b91ab17e843cd1b4c479e4a46f2bcf633a4723e52145fb1ad7305bf01e558e578b3260ae71f69db9334b0ec3fef418da249702fcdb64356df3cbae8de458579ebd0afd6aa2c29890042130535597e5fe82606041eb362d3c3c956447aa468640cdeca1559aa2c9bd67613772d8ddfa3089784b65bb90f682870a9a8ac7c9da0b6564bc013cbd7b964be6c0cf30e454fefc3062360a46ca1182aae9f40b554cf6eedc991aaf595ea43df1f4fd314afbf649bce2ad13dc5cc650c4fcf9dbb893842a47af24e04972732bce8254603d8d88b1511938ab836d99d25174a21262eec31a5a529e714afde0115281d7332e373d942ddf5f7ea23c31b6c3ff8b9bb1328186bb41767a550199787b4c2fdbc396b3c54c017530aceb8002133ceebda6458a647a5f0021ead7ce61a47fb9b7bbd2c09324bbdc312002bd18268ffe382d67f2f46480d4aca5032f4651f96a8ac5cc465a450c7904584d2649285a47396f409f411f8e1acaffd783629efa4d2f62a38ca9bb8f3ba7feba762991ba4fe227ddda6580374970a52888baead6a24f367ecbec2d3bd3118dd589af37cc5b73292b9c30833db8fe4e76d924dee7c76658fc8e4da272757ed3c8dc9a1d3da6e5d23cc9919fcf105c247b33e14c18488e3b0e2ac2999fd841c8eb0de1f9265a3945d0cb37fdc588907c75d203019ca38f03cdab0a8fd0242ecf30a164d8a92e65750d4ca3a4a3c6779eb89a55b9f5caafd56a3491d7d1f5fdb9c3f561f5e346b3f2aa96edc8c4f402df78f0616109ac7dececa67b249309414efcb299d191b76b0f41289c3f8a600eec81979797e8c45c450051d78ae86a15c87e76e2fb8faf0249d32c696d996b8471ebf8fef877f0a1540e8f0fe13f6e748f15772ae6bbfda235056ceffc01202ed4cdba83f1bafd3497f0609c9f0135d612aacae41b1ea1f6f6e7a9088854b039cc61ff542db6a2911a5a4dfb870faabb96546900212b4b426b83801680b77059475efc18120f21bf791ba8a419c2fbf6bfc154ec331e54146a0c8a225cedda9e0c4572c98a92f05e81e17e1804a8399c87c7cba8a94f46b60928cb689c6099083e1b76d6256124a560671b09b7660044895f2aeba1304242e2816313aec2cad8f7cfa6d6e215c623cbcb8090df2840198cfd4749adc7d08b95c61a4be0551f84ada4e383ca717b72cccb4cd1850931782395f433f115298f22c8e03c5297e72020d75b5bf65ead66e7184a71cbc126617a6222496c561bf8d28cb5b0bf05e24b7892af69a90fbc62e894fb0ee24af430c6405eccd09f490111e6d882971ada606aac989026382c93f2a3c3f9a479bed9a8065b3ab4662926e98994bd5d2f82b367b3842521a6eeae02bac22853828d5f41e066020591603a2c353ec362be7d37200999ded1f93df977f886f1a88b75c65ed3196d84d798981dcc224e1f24048f29b9a463d021881008342853e1785739599c639a162e60e12c8fcf8b525bbf7b29af1707d996bb1a1c95d3f18ac8c3b0021de8f3c15c8f8199814ef7b984f0f3330ab8c95640fe472e97074e3b4708ed1006a9eeda76ae2335767ef020d886fccb9cdbbb45194b4cea13442224e89ec1beebbe1004da38a3ea5b41937b30dc01ed5101e33cb2809f6f8855d8b98dfdf82f589f99f836d54e16b8766989c0d03e90786e39986b1421d1ded497efc55443b43e3c1d952330dcbf1e6a5bf47014d298ee27911d95fb84c956de70c028af78284ee4896dbc9c9596774fa638082d555a5338068395f78e9e3fe88c422fbd36a642a97d7ae530b307eefd2efa19764ecd7cedd9f3c108fba8d826c40dc33fd87a6ec21be9961556103c15feae354f94296ea90c02d8a1a8e7e8330335568424ca00ccc68868bc2764f62bd3c642028910b1453d9f9083a069631445c04dffcd80a399628344348d26cd55cc49618d32a4bdc9289dc361b15688fcf5ae78cfa61053eeb69f9c064d82ef11f2d7629d3f6a209c1a3b7ff29371044113a76ff4df767a3a1056c7aa48625071832512ac9e6a6f6db706d90bfdca2fe7718f67dc228a9a0e915ab89b0d7bd64638a1ffe3c944eac9267c00869d80e687b60587b0a14e5a1e488be6a38f0896c9a607222690eb4a79e6f5204ed8e32b4e928e83b092cb422034b320d66fc9347176d0d5dace8dda7f7f15a75e50dad7f0a8298a5ca15ddd64b3a29404e5e775392ddd8a63e52d6b0e5beba135ac0b80744f7dd8e063031f4fcf06436ead2bae7851c07020308b6e096d7cf5573cc77cbe6f1a1958843751879c936fdd38ca0bec5482c04e0a4a8ee0fc3c31e24f775c85ceaf808c4cb4fab902cbb335b4b0e3a2f620c94bc55c59f1899f3b6b3a260366c0f49166057f84a4b1b4613c5029fd0da433ab4ab779402c9d02447086e4c8076c7d2f5d4e4683cc85e41c4057412865bb48bd4fe4f414c9bd21ad303a70f779e7dfcbff5c2fe6bafa028ee16ce6aa5e092bc39dec7b74f7909d7f40271f772a43ec47587add77c06c8a9c604b45d2da3ac42fafc88556b719c58543db90a3425595f3a1804bb1d0c6c9d30560400bd6df388df759b8bdceecbb2d04e47ade97273d6b98a906af5adcc2fa9a17b3cf0bf82ce578b015ca4c3e0a9fd06b5610ee0195378282e57b8dce1196698ba4eb7cf64ad2b928e55d300776cbe3c3e36b2996c0f5a9a19e918469f27238bd98164267d94cb751c259063ed1b85a33383c3aaf1db680012eb6ff8f5df2e63347e8e25f7cfd90a030285b95894d37cfc95ab707a5fc97292c949613542e72e002c9020ab8c424fd86e94db7107c28ea537f192ba2db779a569c67d9acf437380da3a84ab5a5bb953bcbd9b3942cff18a02966c10a641706595d2780db534b37bc80cfb4dcda88da07c5107563d2922459242fec40343cf651288820de146dd2a36c31a2bfcd85fa3e60b55b13af5d29f69a3099c28e9edcd13a88df65ac6288c39ec8ba65931e05c0b06bcb3b7a316263d1dc641f78b0d34822883d870bd744965b9117260d6dd844564c294427b405f7c5ce15c46554c627d3067955d851017a85ad9b4e7857f5a723a652f7d9dc3381502e5e1421a7528db08a4d3155fee0e851aff1d4218d7065fbccae7179b36d1cb1b4df4ed00de51f0b8566953bfd230e992bf003effa9fef28f98d9c034f89fc165f619140e91c663397e238dc6c6696cdef091293c85c3f95f5920c0d1eb56f26e4a1e87bc9f14655e9ec33e2e1906f09e787ba2132263838bf6b00ba3d0096e34d1c406776e148062f21a0a43600b365bf96a614388fc6ceb0568a1c82b416546012739a800cffb964a450f4ed634b96bf6356d43084036d4ac2acfcabedac6eae2d7bb4c6874371730e34ebb6d3e2397539d293ee276590551f93e8cb49e0b2599e5a73619cb438c28e4f309a08603480e65445db91887eddaea5b251eb8c60d71f09828f689915f3214bb8e0ece1dba746102a6a0c9abe164f4ff542c6fd7809d21cac2835a3e9c8847189e26c983f9de57a5266dd7afb40a251b5f335999b596e7aaeb18f15d35133c32ad2d372ae64e4fff7e41dee06b3669b1b898b49b2c2cfa85d8c14fd87c121e1eb1839bb66e396aebb03186c324ade587bcd514d431a8c2525f13bb9987bb65226332b4f70d0d85126f5e47d4f9f970ab5bf2903b21af28eac4f813246dac5728fcbc24e1fecf60c02bf4c274b4436295e85410559d6e47a9e464f3238bbfcac77c71eaeddaaf01bc480f0220bc8eacc0d276a825acdd787b1a491b05d27689a54e465778683fc77d23cd32af481e4014f7268879e1a273d513d4e3f9215fbc71dd4081b91a1e05dba0ec8dfd53adb50b4174e65180cdc8904931460069b7e0f7aab16d41a0a3efa9de4c6bc549bdc1342aed6028978a6769349cdcead61c0ae3319f29860188d57abe356062be7e04367e2adb3ea0b9445502fc40288c6bff964953288ec2b97a72ffc51d33427818b0df14f93534bd2378b9ca1823c9eeaeaf36bb53085b5972d3154960afe3b70070309a7fa55101b0033c5c3ce37611a27028995fb71ae0efeb49e8a2a5d4af9d1c2046afcd4a57c69cfe5332f8f6716c618e852a974984165784ab598e9d168ae8b58709cbecee265bad7344b2d9f2fa91c238179ca61ee9ec96f6515f4021d741b84b716366b99e3818d3fd9385100b3e4425ca0fb73d253e527b9624fd81e05f929bd0674300726f8abeca06d8db19238575651255ceec2eee53bd8725f34c6f6f57388ce2d889de414856cf7c97f951e2feebe4d39bd1c3be889e92bcdaf2fab09f5d2306e5a17faa26186fbb8ea174b69e0b91e96106beb6bf855c65a5f11c250dd135d935ef7eb5ad89e78ce3d0dfe8d042c4892c6199074073f7b9d48014212f8523f5043741fa7ba62f691def3135e647da1f7ae8a69fc4a69890d75b029cd80bf1675a723b6dc500d1586a6ec22e63b6b0636a3e940edba22792b86406d14b2de352b5c098373e8b44454e330201d7822f922bd0285b7f29b1159db77a6978369296f39d8279429ee4d2cf92077d0a0e27e70e0320befa8078293aaaf4b0bed96f923a6c0775f70b1dbe1166f4cca5923849b01b161dec076af7f2899bf66ae1d075d9e663c30e065144cb0655e1defc2f1858c26703be3c245572755c95e9fc1a9b71cc8ff3c3b16544126ba299d52d1a1235fb11c8f538b87b695b73224ca602f0547c7db781cf746cca43182aa6b8843f3560d0823e0b4ad314ec5fd58bc8db6290ab7dd1306e32f7fd190dc956394da32569da5a5cde8dc251277c5d487750ad84a7b0980547882a5c989a0fcdb6578c81618247fe81660809fe4de54966b1e8e2057f9c2a1da89fd58f3d6ddb83d5e5762095faf54793680853c10d9ae45f40c1d6a4ec10345a194a181e75e80ba0605634ca9495d3484b136b779d8f9487be545c355732424773f5cdf5728fb4a3b7b20882338b4d6ad1ff646c088e1d5e0fa0014f5d9102d585071396fe3e20ca79dfd79447b91d44e6d0b6b24dd62ec881fe7b1cb970b4be410cae6f6ffad1086ddff3d0162d495d9db98dfdddbafe5311978ae003ebaa988cdfb85da18963d9a093965aeb9d1ba29ff85693831061643f595da620962040a345f52058eec3d8d6c00f420cbdd23a5462b61211cf6b05cc5ddfff18d5b38c10fcacbd493852c5e302dc3c7e6386d21a1d396884639195a8995d34a386d2a8fc56fb8779004380c867b0406023d0c3c282918c8e7239cd6ac2a4a4a53aeb788b94821753884989a22f1c46807b2e69e40357976a8df14f94f4694280acde41a4269841c5bbce71ccd208f3c9ecf49f7fd161328be27b6725ca26395f8d9ef069d158072c9442c4865c258bbdc8631e69944d61fa6a1d24416df15fce2ce8a2d4480ec9656da3c08398e58efe1ab83359614a96d9c3a4ccc788ec7775a0e909d1fecdba4474dc4cca607134cc3f45901597fdcfde422ce7ed41109b024fcd33f059183add2d051b5a4d7501d048b86a0af09d5d40f85aeb29c8685d798c1a88495b3d30c29b8903d028fa1cdf57d2bcd39e37aa0e6701f95708c0b0cfa67cf94317f4e1eece05105962ba46fee0e5d00da206ac3119fca02d4f279b167dccf8012a5088747c022f7d74ed1246a5ae18647c53cca0059d2006e44da8ac1b1d16ca88b3a3f8a0ae1814a1f687c3e6a6015fa05c1dea4574554c15e2afa2fcb170074aac80646c667aa788758af353004722c007456e298484ef309deb3c2f48450d181bc120c6c6f35151030e2db86a77cb53c7a870182affc07d1331d7597cf14e77b5dd0797fd85018b5de4d7838eb466c4a0c445f3daf6102e24a0c6ef33aece0c5c2d36007ce3a873d2db35a76d5db45e0de41f2c568a1498d819bdc11bf76137ff25f25e54bad511a1cac825efc88f248937fc019ace8056a62690f3eebd39c3d121529fe05f454ec4b97a670d005584fe75d55fd51be52db13993ce6f0cd80920482fc2c74ec4f780d343b0f37df8a6c8099660d8b7f4167c565dcf403b53048b486038016d82e46b23be38c4a28b97f729631d0e695b25f436adf25f832847419d54756da8211c8e3beb2c070a185d157b3970685532b56982ae22ace63c93ea8ac58745025f4028d40e06855670ddc36ead1f19772788e8b08789dc206bbb24a01d47c7226456327df0a55607528aa590270af8b62a7b169d1a9235d54a715c0eae4b04d4de25dd570339843d30c252bd74fa3ff4af2e5fb018f4c0f2be6addd165f80b82582acdf602f605502ae8b088a5b1ca5627f7ac7f511deb319e46b99e65464b9a4144078a77e1eddf41baa20d4fa9823bb194dbd4fa1b3fe24a61960e79f30933597b9c2c8cb40fed4b4dfc6015fb95818b309fe9c2e7ab37af4e7e1a7a2fa9843138bcafe1281f0ca4fb98e96b123bafa9465c7f3b5325b1b289084b2b3d1bee4a86fe12888c772fc3c9da2a7e28d0eb328ca0fd348241acbf45418f5c92f3601b4136daa518325d4ca823a80b7e53607ee54cb0f4574257c2c941efc0afff4a7b07e7bcb164d7dda2f1d941e1071c04379c803fea8778b4eee33447c2f55b98012fd997530c167ae91bf7d2619f1f8b86982f736315b60e5073a47ba11cd99f202046297030349ac8c031de249b2228c687f115f340f944eb9eafe0ffab699340749651814899cd3c01433ff81d75377f9358666e9c06557a397b28bbab249f79751e882aaab73ecb7d5acc8857a4cc6c279520f5aff5fd426f00f91cf65da4005ed6311b72a85bf799752a211499c1ecbb9fa7f21b4cc2c2940c10d35cb5bc22b036434f95465380dc12e87207b7a396f9425359033010fc7eee52aae22f772ca066ae6ab20e2d6151bd4c4f5c928c1a105fe146b4816db294bfaca758141f23f82d34c43b92ecf1e58ab61b477965e41b0a46803bf90228f92ae7a708b946b1652ce3bd1da7fb4217f254515090af53771189d1f742fd0fc0c35239d624a0aca41a95b8214aa838985521228638d1a815752baa95f7a6824cd2c8f7be52a0267a48467cefc007b15348da0d4d6470d3654168937c558f72eab22c4047647d2dc75581cc7d2a38c4e80a41ab3cc120e78458024f2b27b45436c06e7e5d4c21b88891f96bc4156d79ee25ca6e295e97eea0e147d4b34752996ea52a93d696f9261cf18ac9f9102c69c7baf7140d63cd8ebbdc50061906780ed8c937245845351683823451f0d124e5dea6b0c36c27d1df7fc380362a0f224a3814891cc92e824052699c0182a53135f7378afb8f26a2c008944fab910613dc3baf95f417ead99aace350357812bfcc11796124ca7abf9860d11ed6a040789eae6503f83890f515f2d588cf509515da50d6ccd5f6d39cf8eb13998252cfc5b7fdaba143306d8fb635e1cbafa8dc007108549971b8d7f273243f275e333bafacc18f046076b5a2ae53ef0127d3cbd2dd1fc2cd510b19e2f5565fdae61062ced5426ae986f2bf27a43e3ef54616c9e1bf6b1e7bfc24d8eafc20d92188f57bff284d8d7a910bc25f947f19bd53df606c4cf4ff3c0fc8cb4cea937372726ad6dcbf460865c828cbcbd9ef974cb73b561a71ee72dfe6005c413f00d765cf1c92f207bb419fadcfa6355fbe829a340aa6e8702ffd321507ce3eb15bcd6992c83b269e497aa5278da75f64a4749e507ca67525300947625a8b93cc258090096c3fa388ba6899b9bf7b4c14f9321a35a091b024ac8c0fe04f7281d847ee7b5d6bed05f39c9c34e16a5a0a67737d85825a58f28c0fc8bbcb3e082fa62d19d9207a0d8cd2da0968047a08e269485690c2e062874c4a0ebbe6739a79bf049e0c376cb68a4a2b230f08e18b836d965f9d2b71cf527c060e23eaf971ef92dcada63444be28a98f1b1f81b57001bdf48c0ee10cdc83c5ba8f430ec363458cfd0e287b69f0c08f17e6986bb720cf042d7c3c077f7ff66e3e5a6dc3f605fbaa079ae52e30d282c24ab0231fea73b5924d372a2959cfe3bd6e84dc30250172e61da5690569aff37d5078a21b4a3f9db88eea86b24082cd0588b78319ebe4979087768c9316d0dd1247872143038ec163b21dc4c9f87238fd98b3fbb7da6de0a2e0cf3bba4db59328e9802435c4e19802ced5487f5388785fa26b782ee72533bc30fa81c261521104b1d064c700e773acf85c96e64d5340705a4a0df9b88b8cedb3839553d0ef03d141cb763f6f98280e5f920a723fc80225801290b225a4118fbe094bec29bcf8f25733014ee34aa420e1417ca5c33d9f0c43b90fea1f0a562470c74118c79402d36e2a16daffdee3f06abb510086111f6084b1aefc8505052f77ba7f431bb795516b0bf9bf919449cf59ec5efb1ee16d9520ee8edd99bcd2a522bf0edf6d801403578f7d9530b315e967083894f86a13f46c01e4ca5b5ce66fbb8292081b4683ac602fca5e60014b9c28032c1b250d6b04dbb9c4674dc817906779dc8b82aa9fd2071e5580df1650b823a07c77bbefaeebb0ecc6c2cb0724d4a0591a44a64f508a7f7822a0bf5513fca257075a1c3c32bc2e9dc0acef46e1d4adc09eba67952efee33e11dc3c1c3e50661fb60cada731ba1e4d434312ddb402219ffd6eadfbef72cf1073486e5d6d96decc56a63dbb488f88e27cdb63bf6528cb0f7aa944f843412845b6b9c4132ef9013c5deba6f358c169906cec66cac97c9612f2555d50dbcba6954d6eee64e7772a54250c80254f2356ee5d3aef5b12d89aa6160539eaec7887a575282f1c9f43c5fc0ed503b240449a9ff0375b38e571ccb2b931d2074d8830d308e0cc04e52c71daa6bd46d0b68e2a441e8aa52506769ea6af483ba11ce7799e662e0e79a326a674877bfd54caf10ddd8106303f33a5c1794120797ce1366bed7c7392a4ecf87e3b51affa52dd4399d0b2fa80c50102d9ea1951a6b5b67b2b3d2166035e294059625ce4cf03e4f62ddb68d5639df5872a01c92b6abe2ffb91e9e829f9e488d3437d255c6d389e63369c78d045add220120b50d4c134508344a10f0621e6cbdc831c92a4799106974357483a7ec1678e376e6b69fa87782332e71168ce4f1c288030f8774497e1e5fb19742111a9297f3ad44a39b612ed19d0693bdc42036c3ba3d98d0f73095942e0a085c816c21f5f0fefd239bba435186e1224b4d962e6612b50f0ac6fedb6985f9d462766c8d520943d9557d717742509a09fee730a3671f89fbcdfff34874838cade916e7437f8e1a6d551a5c422bec6a6f2811651836fa21c9484cd08307ffe8b0e36485624e943a90f1fadfa69955cd2071450ae151bc0a69d05cbea5327cfe0abe22c61aa484e0a7055de128b7d19b8711da87cbf6b08c77fd60ffe931b0ad05a01563f5bb85700f73e95205ffeb27c655e07a77f8c262057300812351f081b88d06b9a35c1679e4f389cb83a3245641f9d4775e290b19325734c7055428b95b530105033d1aa54100b77adbb6ec9d3733dba2974e50f33c6221034c38e0acc55aa1fe8f3acf3b6c43972a1ac20c65132f325e3c4f877b452d024d6f9eb7f1ccaa10757db62ac041cf11075f159823dd34c83d08da10970d89cc3fd922b5cfb458dec7ea9ca57486c8245fe6e71dd2a406a57845940690e4be83f15960865cf1fe66858e092b07770fd571d84cb9baad4032d8a67e6ebbfe94b237cffbb20724595d6d3996679e5778e37114b18230728bf518bef114c7ac30130cf25392cec700a4378aae18693ba1b13a30e30f44d8bcc3b88e1047aae36f5603e98182a0242a97111c60d680800401e80d6cb008db22a90d3879909f7595d18a07acf9273f14f6c623779e466fb3a12e39c6c4c212330ee66f565d2dec3e6126b8eb979667e689ce09682ffb2961d829c2df8ea8dc59949fe0fc1e6e8bb6613e9f12ec4f60163a2a2815e482c851ad5de5f1ed08552b562185e1d4ea1f2826a6c09ffcadbdaf69c0aa8287124e4c3d6bbc10b5c2b538d7033c76f09f3b7f1021308f3e24b323655f6838a6b2d7742cf3698970e795c9c4ebd66c96956ba15daed47975cfa4cc1e0295ef09e0c6f8d7f32c743de565c3fe4133f6a8c234a17933212463ec0e05c10112c89ad7134c50aa79038864cab4ec01b837e3a9767827aad9f01751505ae9e2c1377691a0682d8bcc9039c69e7c6a44c80381995db5ca998aa249fd7d9fad683ddf33e9be66df852dbbfa3d20fb31eb98ba9a5fdddc0a4d90e1a72df0b0b55bb24bc2dd262d66692382307b7b1da454e88e75d91e08055ecc48e0dc404a6112173fc54ccaa9406c0b5cb85404fcbaecd1b378c2892b8c59fbd16fe3372b93124ee196af79b6ee2fb9526c07d8af5c805052f09b554fd3210f6820c2da978eca22681eefeb020026b6366336dfe0104503a11f6a0b1e865a08cc4743b8be5965676b1750ce9244d0475f9b957f28adc5ce7d32755d8d232d8d68bcf5db3bdb1cb38846bf52e8c60e8b21e43f7050fe710c8614e4ca8a41bfc25793c1cac2f0fc56e291367825318fcee1c94378730142a28f971bde6e12f6f1ce7d0423dc1d5ca15e83ae9d9fb96a5180a1319074f2072ddbac9a2d5e235a4209342865988167aba27f2bbe7a146a73d182d09ad082f56893bdc553f6023ccef5c7053c0a9c0d1ed9961074ca6e354aacf0b45f1eb1bead0fc71873f27fd31de897bc5b07865a6c418df5c3f49d5b262ef74fa8c125ae42875d02aabad32bc416b3968cc8300b1dab59044fcb55880a3d4d8e57a0a4379b7ee6b8b1bbdcaa3b90b86b234eafab6b7a647346ac52d55e4f797d883c73084f5b7baad92ba7593f0a833605d31b7485f8465672bc681e9ea1bd7d1b5c84090896005da72f898dbc0c04201eeac052b8194fb4d8ccbb084e42a5d750d455aafb43446ef06b287de41fc078c50fc0759f28d0e36df1b9ed06bf7a20eca85511cc50e460e7a71b09c7b20fc2aa77c2c4d122277e82b03bd78e995190ec030f90e067d30991b92c580785a87b4961263014938235c2a609b20782af4597502607b0f3e991a3d6d2bdceb24123f7a527771eb1d8412273d37ab90b49c3fc55cedfcb5fa011dffc161c042bf1226843924c6ad112d0b7e7ca288e08538c857335791f7d2a01c0ba45d87c10e1e2ba08fbe0f3d63de5d7e6735b8214848359992d4113114a77a70b3d005503ace96f24dfde7057176935403333061c3dbe5f1bfbb3fbaae6830030328ef3454110feb3ed5de6dc7fe23948c49c06c5d4a7b6163446f943361455af1b47b2046a2483d5a10237c6def09c51ed05c85c47896163abf12420faaf388ff9c8ad92814a4a680e985e096cdb91220b2d8079384140fb029b18a8f53bffc8cdb2c42dcf43c1a579c93fb10020f96584df1dae5710555c1c27aede50e2af538d74fdc6e485f9d8dfaabae45571b8f7f7797904a0036679896fc3ea1614c665d75da7068bbfd517288cebb2f6cf68da70634a9a626e0459e4e1c61e08df7d16964c24aecef3b8aa3b97a46835b889a9d6917293691a0a6cad1961d66a028c4460e0fb743272b591f0a17946be50ea248f337e6485e99b1a495309d03eeaadcb5a9cde86a24fedcbe56d84a8479ee7a94335c2214f32a9b8b6294fb9a2bbe32139512b0d22eea1486cbe3b3b1117683f92a0c4aafe3a4223cdfd44556560475529b6a9b1952338adb4a4c5a38643667537259d3aedf1df5f4aa89cb0320b79d6a5403436ad0feaba7b877ab68e2238d0164c802d72486da5e8748622968a0a056d5a332ab93c576b6ed7ea83c4cc28823d24322e1e44d4c4010eb23911afa89a57238407a1efca03673f6a290c7ab236549767c0aa6a299631be9e8d18c4538122a8d2afbff9179c730984ba04866af3175892a3437ea117302dba092d8e2b86f40cf11ee2636e36921ff2b7c2f22f76edad328d43d5b3cdd7d3f3719d6549a62da209c56081db60803c0ead68489630f5612110b3a711d4e6214d34e9a7662fd983db378effd603af83df2c70093db7e86ba65b3a7bce3f6886522e033f49813dcd107f4eb2b2da7b06228b8d35394725443032499ee09699517b8e4bb3bb8baca7f3117cc29d760b06f5d5167220427f81eecc8caa466cef034a69cfbb511040d46c3ad03cd64d346fdc2db466f1b2b7538c81d99c11c76c98362d813174f1eef7fb3caaee1c9373cb764bb9ddfe7318aa29603be766b56affcc27d2b6df13f6b23612413e6bdb4dc89652ca24e50e120bf20bf30bd8ecc00a2cccc056eaa3d80f22585bdedcb951bfdd442cfaa2a720fa091910bd032b884e824289672f8ad752132ad3905679b18650832236dd8e89652942951f2b2b2fca6c49119678624246c44c18135d96086955d8ad5d24017d8bb1edee763357d28a42bb09d55a30a2a350c5af4700b5f52e0077c905d460cdb6ba44e26ebfea55012f8e56acf406597fb1898a4a220956a71b0eb5b87b2b9689725e34bb359bdd44600b6b5eae80fb4a2915da1fc53d158af921897ba5eaf667c736552a0dc9bf5e5ff0988ac1f18736785ca94826c016617142eb45b1ed482b8e8add6ab7b6f48ced39b2072b051ba6b7da6e5b872d7c99f2c3f1ab894b9ea238848dc661b9d44d4c57774bd4d55f0786105199c42d3c4f7f1d012794f0c54cce0fc52f326a4b549491e2ebb4c75fd3575217bd5a9bc7a1e8d8b435385e73bc95c9f6afc4e1f2bde315772fe2a3a1cf8e663529ad380ba8bc8ecdb106eff55b5317c9f019976f27ab88c9e162e63abedd3d8e591ccd61ceb82b0ede25f70e9880845a35e570e997aa6ad8296928aedd6969f7528cb1ed5c33c5dd7bc77c47b1bbbbbb292ead660bc2593aa3a4389cb516687d1977ef3dbae588732abafd59711cb6597158b79b5899c6cff7467134eac5eeb6b67adb6bcdca83deafb9856cbe42388f35db0d470609954339dd8e47d4f315fd86f945bf19894641eddd460ed850024bed935b572c46a86975136a57b32dfedbfd4dab98d00ba11766d211100844f2e0c1837ff890640281be3837a128a8175d74d14517cd5e74a128d16d909b589948504512aaad569569385e55a6618d72a43a59123d681fd65a5b24a1d75485e11283500baa175da885d8000fa5cfc7617b15456fb17ff5cbaef5501755a7b4d20ae4d666dd556c91d2a6b42d909b588ea3cfe722594170132bd3afbd296d1654f85bc71aac7d76b4e276f6660e8d18408d18609d9c9cb85edc7a51abec6b141b33a1961d5c12619d3af5f0401385df8b657b7777db3333b1320dc19c913d0bf561e07b167c2ffa2f282d288d039a9570993e750022040ed310384c7319028e44313e5d11507865c291289a448030c2082308800412481061000310d134c2085157845e7c1e5e9cd00b8c31c61977b354e885d08b219d908be611e18202f57041816e3e5c91756ab45682b1e166c3e1c682709814c2614c5d8cd95f69ed709451621dc63c1cc63e3222ecc3512119a5bbf0912646fac309b930938e80402092070f1efcc387243303711988cb15ea83070e38107241a28560741027e4022be1846294d587be0e4084e80e3c20d142303a8407a5d05150beca5745726ef78a24a2846094d4bdfabdf56b8a1b89a2a4422e4aeaa218e256dbe96f88b396d2fb1bdada8ff8fbc88dceb7d7156c7e6cfb712cd8a77478df3605bbd9a86e42422f5a74ebb4d65aa229b5ba79e5d1a616db6e014d7bd1a7c66e5fa6488d55b2af3d8e9549fc7b6b1257c78d71027a8efb0d818fdbd06454c522e7f033dae043e18bcc21ce578ee6d0d7bec16b17f9cee73917db3487e218b5c2fdc42d4a560e3e1c8f7c583621f97c74a49fd84a417ef4e3f013ab9013f98de8478390434a211fd22a21a75535aa3471e6c5910a20bdcd201c0e87ab51bb9ccf57b1ea559193308b442fdd27d64d62976653b16ef76050c4d1cf040ee609f44ba7640282bc87735a459f2847e49549c889a272668dca41414343433e3434248ebf1588639f8276d26f41418ebb8965ce1cdadc58afaa909049e4888353401472302f20746452b25652dae0467ee41d1cc90824e7e01c381c9924900c3989111cbc8349628903928925b6c4c18547bec139f805363807f302467e648aad2492a579c2d30637724a9ea3390cc28d8edb290327d460bbd1cf840dd4b46625e3bd10437a9186a82b4ff212c29bcdec2480669267738492031d6892007a09e1485d5412cd16908c08ba92b700e2024a0ec241982d04954c51389a43910c58c971c8736d73acc1dc2ab06087c61791b33964412c4b5fa1f6c32cd8fc1b96b8fa1ae936cfbfa5cf223c987389285fb38d62a59377f47d3687297ccd842a3ac006696969655f3355f0fd90cdc7b1368ee3581bc7b12c47a29a11ae364a80faadd5702603e8353d7b6d74a3d1ec8591e3383a398e636d1c753a23a3a51a3c2a81463e8ed9f4d520d1918f45f967bb3f06d8ccb16878c2d1918e1c9688f2297c7981b58c6bbe1af6a51ab479c65d1fcab6249b69f3d5a0ada49752520249fec1ef83a42460d28824073ad0245142a8947f46461300e14a7e010e3ce846d947cfb59adf967e2d00fd837ff0fbe02d24f907930408bee42400e01f78f067843de8a250e967844da30924b9925f00e841d36c21e84a431efcb50082035de9d742d0952600004ff20d80e0c0e00fc908101ce84abf160060bbd1736ca5d241fcc41e7f439e2dae6f1f98244a084920a9f9079ee44bbf24affd462c799249a28470290f194d40c981be010e3cc9c76e0226196d008427f988a0034d1248460f8ee608109e6492a04210439e9f3ef02537a1ae40ba9227f9063818bb296934f2249304129b93008003cd11490ec22401822799632bd5ccd29b94c0503672007dd2e993215cfc111e78072ef6bc3cf807af423ec283077dc407e7c06dbf14fe5223a73573388eb51f8fe246231c1d6bb8b4fd727e735efa900d37f4233b6792741aaa885c2c7bbe0dcef323efe0483f37c75acd7f4b22aab8458d1cff86293c1649078c9e4d23ead96bd4afdb7018877123ae394ce153f8ac1bfd26920cc079a69e6d5e33babe01a027f90640b892d786be1f7b348da86974cd09003dc9470041d43cfb88bd3cf23bb411d57e46b59fd191dbdcc874a29a998223bf660a7e5e53c1673355f0bdfbf8f3d2cd4a3a60c86ba6ad413787bd1a4432bde743ba8157fb8d3f9ecd47cce36d30872d3ccf7bf56ba6ad977bd9e739e79e2f85a7494a8ef35bcee675a0e9d4c7df06dc6fe8fb6c747d4740df4012d0dcc0759f973633053ec73e5a7391acd5ee30851f8d70c09fd899e621ce759e7f43157cb7e6d8a94896a86df09acdaf8f9ef45372e00f84d77ebffb1ba1e4496efb4d40c91c7f234098d487f39dd104925cc9472499622b2999236ae630033f2c1d67aae07bec1bbcc4f47dbef27dbf21effde88f962af8de842f5df71ba6c080dde7fc96fb0dd546157c23cd8d3e348e976c58fd6bd987c1601ea690343ce16b496e1b3330a6a005544c13bfbcf910253309c26fe957fe16207e362de93d2ea528f4c04378073e2c3d3091901ec26c01c908a027790b205cc93b305b007a520a10a651cd8346d983eec153006be6881149a691903981a07b70a36c5e20e81e8c2ec0817f700efc8327fd820efc711084cb3f913c8d2690e4411f91e441b193bc668e003a07d981374ffa8942a007f2273ee94b35785b7ad281d993b267716cccd9ac392e974248f2dbcdfb06fc25fdc4b112569f9d26208f2a94b07aebf767c77e7500612c5811cbdec452dc8ac1c963bfe469cd610912777416bc66f39b580b20e412c02e0edb718ecd610928170a1540c824215611442721e43710ab08a48b55842a01ecd7efafe6e2cfe642b821891e96787c5abae1e62b5e71d87eab36aaba98a7d73af54a9eb4acf47aa569660adadb6f5defa5a4d87f4432db98226444b2132a53ee2624a48beea22f896277fe318935486f4df670fce1e8fbf2010ba8c17a6fa5dfc4376627608958faa0d111073f41d86d0e859cc3efe867f4135b49e737f27782d0ef017b4a9254c002dc84bafb51f26c1a9c7eb72b6ad36803467ee4233838924902493b07536ca5a2ec6d8e30f2233f32496c7023b384b0cd9c472d6fc83efbaec7232222daf96d671a2d40fc9d2b40fc9d97f8dcbf210adfdefb15ed7eb9a87389ef1f0bf77d668f5783b5dad8ce4de8a17fe93bd23350ea4c71c82c7fd7857ee3937701d54fa84c628fc1cebaf224f11248e891a5c615dfa0943154e8b80984020f0d464d828cd022e4790380a7069eb117acad5db3d88719a2d2da34b101c3d39b2d5c59396badcd555694480d21e505ec0e0d436cdb262c28349a74cd914a33831e7baf284308426ef9d683ceb787906910f2ec1a5808103f0ca1042c7211c5c0e00536e74f0a303a5da6c0eab47101666606cc4e90c74e818c7d75132dfb7a5fe9c0b22c4b17a54aa21297a50fc5345fba58fa58998cbef4b2f45d650afad2c5da94adca12a7258cdc9271e6b155d4d98c2b345c3c76fa63895a09b1531f5b7ea4bedb69157936c64e7b501ee4595a04d8da2ab7fbda3db8e78cb5d6ee20cfbce1e84b095b1ffc50e4c227cbd5560b2d5b2ea6726cbdb0b20503c6569f1a1e3ba5b25debd40c386bad9d1a41a052668b0f0d1db6ad9814a06c0a6da1e1786b9de610b1ac8c6e84d9ca00f0d6a9140f2f5d49d6dcc121e38acaf04347370e2820bc757aa369082f7851537505650a9b186e7c5da12cabad3d35802e44691ac566f196b09ad223cb081a1e67dc08b19bc7ee5700ed18b30d5a833c6f154a434c21e4071a355c75ac6ab49983671c6764a751b4ca050e644895f00214902669d638a9226cb26f29b0ef1e3bc7f0e2a5e887401e577c0d12ae1e7f1e3b85d1b8e2367e9a3c11d2e6080c363fca48bdb0227640f1c243c5b75317585467a4b5d6524a5b9027566aae1d31be9db230ca410567ed0fa4b74e57649a860918212d84c0b891620d0e9bb596aae0a242d1e1db690a6ad54db4ccea6d5b317bf5b171ad5d43a99eb2954882f8d4b35314e499b700e08747df2e52f9763b9668beb39a0cf9767ac2b6cd3acaa89c4c4d64319111e2ad53271e5846939a652de1f3dd5e823a39f9ad256ee091c1e789c68a33546a52b0c8c382cb899b1ac0d26ce96242541b6f30005b8abfde428582e1ad5beb24f0989da727282e5a7805a283060d461ecd8a766d5003f2b45f2b62f876db4e831586635bf1ca0e31f8da19502d42c68abe5d06289490c2e4c79519343c788e088b5ec8cb232fe4bbcae47b21070a7988cac47b212121dcee88003f048a0995493c510e083f14cfc43f4fd4060d5285ca63b7d8c7198fa9c2acd439127625cdcb9a302c74660c09c3aa612a2cab4e98565758161e8f3d0656946287010be429244ad58edcc15a32864c8ac7191c694135ea147730e58e8c36497ef8d122c466721419ea179cd04db6a8a0a0a0a0a0a02a58415d5c5e82a8980f0a0a0aba41414ea3ea040595059505d5a00eaa41415b3c826e4141410e0c86a84ce307f95290880f0a13340655055505050579f9f4411fe4e69e1f5d409e630bb65ef8ec36fb0ae4992d0bb2a05981b5ae82262d3604c842f5ed2a7400be3d05e4d9bbe1519258c20f4bc072440ccb9f2e2c305945b49cbab4803cf6a1d01dac312848813c83ccde763d400625c62606335e5cc6f684c96727a032415b4aaf08e6c7981e5a0235d11356c6cf8ab104e479bbae98786b9d0456ac818c1934a7a91a41609041b33176778f803cb39531a5b72e823ad65cc2c60a2a534cecb0f2c7cd983427d7da317b08c83383b5f9eeb222e3db51f0f9ba5bab8acc8c941c33f870216c31dfed215c7314bbe6a398aff2112b335b651fc5dba5383a08e8ee081882aaf8610825885b5c4431691e8b328872c81f8a67e29fc71c70e31f521b948a0641f3437a843a11c30e25c863ec63e9f3605794171ebb081316708294278f3d0328bc79ec29ac60f6d867000590931f2825df25854995d463b16b8a9cc7621715afc7625795198ffd0358b66d965a52667398ab3ce0a603d4529a74830759961ce87a5265032648e00c862f26e2c4e0a325247dac4c494f7a59e5c9271d48929424b954cce8e0b16ba02c9fc23045cb8910fb98010c902799af68c36878f39484cc89a7a8306952c60b58803c2d578a3a239670382d324c3c0ee7409c87a84cf671eeab381c6eb83b7a3116460b0c2327b4c430f3d82be0bd2842ec14980079e24c5a2e3d2d6b9bcf769cd52a5a3debce2750231ebc750990a76d20509dcd8a664640cb8b15c06f8780d39bbddd6eb77bc3b77bbbdd60e4b8dd6e3707de3c4465eabff99288bfbdb90ddd6eeebbf9786bf1c2dfc8bfbdd8f3d6fa03c8d35a0ca3eaad3bc05a59e1b4823f04b6789295a5c51e17545cfc7971e5b137e00333217606747dfd70074536001653df2cda7cfb027ce388a41dbb02fa2794a34c0079deaad93836049c8c5579414fd4182fc20643e4fbb6391c8fb884fd10186218420929a8b4a478a3e2848a2e2ba6b2ac809305aac9633fc913efb0124200094f38b6b8f9f603d42ad2a006131760409d31ebf1858713610dc593b1a718dffee5bd5259a3095c5b214c6c613a61e244178a168fdd00b86f5fab124364209942a30348c595d8941f3ca578c1902113c8cee3325f5a69614e3d9cf23cf602584bb1406d85c9a295c309192f55533a0274b583f9e111201b5c80cc7c7b19a8c7b7978056ab68244c9c1743cacea0fa74998a3100f2c45e7f607c63fd09fb76124adb3c353ae600c142074d17210ee353c3501e813caf9f2f11b59a54777bf9c3c937eebb9b761ec40168895b7c4e74e0e3438b0f9b3e3d1e7b70a9cfd66317d127edb19be027ebb1337ded9841e8d6f0edfb7611c8b3db628cf10e28dd8d31c6b843d0420bd37beb02204f4b45290094f13231870da02b38948b0e3d01f0f3ed16045bb6b100070d5ad460a182438ab0bdec2f74b6befb5aff6cfacae1787fd56cc96f5905f86108ae1f96f0d8c5a1b805c3e318e828d1ca338789969e3d5a7ba23c76005434bae3cc0767551ed85aa9d5d4991331312e9c516de9f167fc31c408bc52803fdfde41452b009c175ffebce171228b6a8171ab67158d56342b02f9fe761015ed0ad3f03053b503899c2921f6922262ab68f56cb44ae489b5f0c40856b36ea24e15adec269b9313bdb62af5c34af536176bb44ccedb52d8e1c4690637629c641082fd90a2eda9c1569fdee6a2cd36a451aabc4dcc0e9a0b311a6c2cb121fcfa210583c5848dda9ede66f3372dbcd8a9f1c7cb0c3642af1f52a936b6210d42a3d06c69dee62818fd502ccb33c3f643f1cc56d54ad416e5409bcd97ba49294f0bad2856d850b910daba7e28e26d4b7ef84371eb6d3772a8e0e395278d4717a18deb6d5efa799bef2a13ee6d5eebc2e5484f8bc759f438d973624f97c7ce41b0d6018078ec1fea57b33c707efcfde81ec8731c228a7171c95656797a7cce0e24cf3c3601a08c969370883de7318f8ff348a3a89f55f97b3d893caf3b3d76d356d54dd9caaaea6c0588b7fecb5795a96279beca47acaea89993d30fb199aff2911aa4b6a86eca52b6283c5e217cbba38d554f5d48c8175694a7ad5576a8556f73ea265ae6262a0e1b2b19dccc00688b4a868b40c2238443ad38b8f88ec813e77e88fbbe53e5bbcc379e1adf6e544a95c831a44fa01b73b05cb1223c73810f8fd20d70beddb61735a658044b11e508d40c272a1459b4f4c092a3a289dd479ed88e8def31dfdeb3655b3996edbe664012327aeab4d001688fb0b5bed3547c771391675fe77910c57c19e187211e9710e687e216961c378fc18ccc110b4227cf635f125127c96337c1c4e32c66621efb4e4c0b55165baed2c97192c39dbbf3774b75b7c04496951898f899c186b0b3beb5fc08f4ddb787c8b3715e3fdc85f0c323e063ff610803fc3084c72eae78fcd8c752c9e32c35e879ec1e2c92254e9ec75e8ac85756bda73f7d86c4b1b3050a1618a931d85aeca3147f98adf295d09612be3d488a4a953a8ed8e02839fa76f252292d2f5ab0fd6be2cae6687dfbed0540660022c50415254e5be29056623e5299b05bdbd7ca7878f9f6f11adde08dd317af2d2960c2c431404e6a425517edc3b763db378c9434585ddbb49a8970c2186163a38e1f17ce502c676ed65a9bc7da987298a5ac5eead6cc618e92b19e0ef397358759ec290d2acc6fb766d64ab46a253a76d30dc2d0c90293468632648446535682daac69d908a6a42efed87ff0d6ac3235a61801278824d0c752ad441d3baeec2614ccf023c6159622545284d87d95895e79ecde4d4234202fb898425bb246883d5899a895c75af67079ec2154a6fcd8bc2635935383d483f694e25f39e5305b493df55c66453d8f759328b48a82f535cc644fff0d8f27e19b9651a76695497c0ac2d7dbae40a83617cedc44b189fa38be388ebf749ddaf1ebb5f792400e0b2bac30038cef6f0675054b6d076690811aa4e30756a65c40b3aa2eb2b59736960e6b94f8ae6d0193295d76b8407da9a92d72be491a49570d16df476c55564f73112eca454545b5a8081775112e721a95f48349915051912d2a72148a8c8abe70b029b215151539b0a8a8a8e84491ae8816d1a2a2222fad7c519167a9302dc01021f450827be8795c95e5b10f188f7d94f941e4b1b7912e62d6595aabb97a870bdf59768cf198fae2a1e6abc78f6fef1770edb1b7559990b556ec32e678eba5cfeaed17959fb7de448258871a1f3a86601d5dd9ca91e26baac65f6f2105701184cb53076920e45954cdbaf315343fd75a6bfb47fbe81c69be74387d7b5759dbd69af1620347c89c2c696b2a8bae1f65f7681e95ab0330df527272ec70262f2628d42431b373046aceada97aea4b2aaa75d4c8a49ed29d6f4777bbddaea2fd6eb7db715579dae576bbdd6eb7f32a4665caae6c57b6db8dbb9dd7aa3d3ba1dd6eb7cb3bb32958bbdd6e5777bdab3ba7583b3bbbdb6eb7abbb5dddeda450ed6cbbddce6c67b6dbdddd6e1745c62eb77371e7e36eb72bf2ddcefa6eb7dbf5d90db31412d8fb7cde39c8d3e7f3794b91a7af9a5151f1bd9e370ef2ecf57ade37c8b3c735a5cbeb74de2e90a7cea4e5a88381cae975de36c853f7a76b90e7388ede34c873346969b9a40ce9197909ab6c4b9328ef28f2cc1c44f121862b4a9e6f6f19dd31c8b397a0b4788ca1b079ec0da3ec17540cf0d7db45b7e07ae2e3ed86b7de2cc8d3167943916751af20cfddd5d7c8ba8996b17011d632a9b03534a540732249e827da28c8f382e913a3bd5268c6db26b860f0f1ddde4ed4ca6f55814ad68fb426705a68a92b64a86345b50610978d2e1544585c4a6b5aa03ae71b10a525bd4286e98fbd7e9c3c69ea43a91503c4784cad21abba31268553e663d162d8932f95386dc6703141430d9b274079463d799a1419e10cc893c56346c21d9a29bd7eb49476cc9880a973d7643a5c4c907ccf19edc5b294ca214f8ce73b4e73f5ad014885d379843b356081b9ba52e40c45a033ba321ab8969ca86f984c0122c7888c292fc011e27ae2b14db4335c39a932f4b9d7d618946ce1baeaf1edd50d571229949250db502e2552bc923514ad4496a812111155a2269263f6238b88242222221a89889c62111179d93042a42322226a224cd44444554a888888888888881c05a21e6888868888881c48444444244684238a228a222222f292cf1311b9ae4397b76eed8f1f6fbdb229edeeadd735e46945545931e3e3869a34e4d93de4fce876f48a863cc76eaf67c8b371bb1d69cc78f180c1ab470c33be1af23c958d5555ed48f1d96df65a863c73871460869c20e345b525c25faf63c8f38a7f6e8049418909439e44d65aa17823c66989963842985413726c205a879c305358bebda6e080b1f6f655c1028a112979820871529dd0f01956fd7204ccb14787906ff7b958d0d62acae93a63b3c747971c7ed2b8646badf552bb906796da32e695034898edce6d39acf0b10286253aae94d1405eb6914bdd429e76c90b4798ef2f2fa9292d3e0e1cbcecf31c74cf8103070e1c387005127b8cbd8289638a7c799127874a76e4e39154933ff25d65c27fe4c0da246285e8707454d5cbd1276861212a61ef80d4210977257de522cfa3eba7acb695a5ecad9638228b063731a4d8d22406407c727716c68ab2f4d62b166bdb4a651aac506c9195e5c9c2e78f55b6d6da7aa55a21cf3c82005c8883c4e206171c29aad8b639c2dceeb2aca2627b562d6ab1b9baa1c38f15b32f42eae7b17bd21f25b84c19003c85da9c7898c723e2f1783c51cc0f0c286d7cc440e3499f1f8a3ca7a7e7bd789e8bc31af53c1d8fc7e379a129c2e3f178bccce339c54213938567793c1eeff2784ea37867bc1b8fc7e3591ecf51e826176c19c381224d11386e843c3e58783a1e0fc8abcfe3f15c3cc2d3f1783c2b529078f1b3e40814210fed795e563d8fd723da3dfe12e3f5f86bcc0b293e1cc5c6eb745ea190a76ee7f549da8f6e47af3090e72824f6d8ab13f2c45f61c07c6e325e204e4c58fcbd5e85ca94a2506c63e2cb8d3755422aacc25d77e4bc057335a221a17115a5a404b3620c9824b8558821a947c8932756cdda524a83843901688ac50b7ce6ec99b2aa7d017b6bbd1a690ac4c5adc8d717186fadd717ec98c5345243a680919142474b4fad5a5522e499c5e8bcb55e87e4b6a415f225c6a514040beb7305429e984c95faa327d464890c322f84c1a29527f7c8b408c0b7571f35319bbb399bebe5fa0a4baecce57238877338e7ede48246ae96cbe53a97732dd662462e4773344794f35ab5024e0e97abcae572b44c8e990a1db932678bcae572bb5cce2956ce884e2e97cbd99ccdd99cd3a8145ab93297cbe572395d2ee728243d99e554880385cd9f34183dc084b9cf654d39f339dfd526ea7454997c9ecbe572be944bfaa188cf6de5b63ed733efbd612ea6fede7babfc967fbdf620cf5b068ba9058fef027c7787b548f3ed95477789faf6ba833cbbac6c77f4181862459ec7380c2a098b14612cb8a8ea5454fe229f73988a409f578cf9ec55870f9b61e5a8aafaf344445ea5c893080779e2b014609ec7f37a833c79d8ab0be4899f02fdceedceab8d00d041e254c3c3170f7ac29eb6bcf54a83f2a151a745d40cf2c4612850bc4ee7358a3c75558697107ef41a43147d5e6190a7ef45937d4dac9baad9783bd8daf2434ed615285dce70cee338e62318fb88b14e670eb1e7cc6c65e6ab6c5583b4ba00c1ec83b0133c5ad8fba34d50ae2caa2a14c6b48a55102b5ac2acf081014f8e1a7a057976081d42a4ed09730a7b1c66c204f6aa62c9da3b3dbed4acb5620a325f7e77b8a47d7d7b7db2dd562248591247863576b8dcc939a3d8a9e0c02510906faf277c5546464646464646554646d54475224fa3b44080fef8e9c3076d8f9e3c0238cbd4526a82169b313f7830d1ea53c7472d633c512574c08961480d71a69eae0837f8589976bfe10893dfe0bbca34f41b1cb86103dde0bebac1e1d03bd52c472181e40202701237a07460d0e2247472282a148079827a35eba692da21cf0d6d452fb79b52336a24ca4c9db623982b66b9fb08a5a3f5d6ad753aa76d0f20a49cab5c1c51e473a34f8f30b33035a4d8e1836b80439eb9080a5ad6762cc104adc68e2930e4acc962d6278cadbb9b8637e4995f1013c00cd447a90ca850c439a1e48a91b43a397cb8af48cb0b47b09893af45a9f2356bf5b5a1bd7afa9a85b22fbee636ca4ac990faa1adb241bed668353135b2b2323f6cb3aff5d9d76a41daaa8f7ccdfbaaa3c478fa6163f5d6d76a5d75b6f36145ab793bf597595aad6d54957d6d4be7c3fa55b9888dbd8851ab327ccdc55ac5fa5ad76ead52552b173e6ad5c9d76c4eb55aae56736a5613cf5a8cd5826ab5b64fb16a49796a41b51a19596da45135281cb5a15a4dac2656a3b55ca3b55a951aae065503d6eed76ab513b51a5aade6e594aff9ae32097dcd7d6ebed7731a0379f67a3da76ec8b31723ea89dc12396d439e4444444ec9c893080c46d6f3784ed98c3c9ed335e4c9a322bc38655f78bd7df1e7ad5335a20c6f9da6214febe2c9efdcee9ca221cf9d3d13d5e2cdeb744ecd90a72e08eaadd331f2b43627dcdfdd5f175180b118fbdbe2eaafd3323e4bc9d4cccca0ac3ee736e7740c79e6acf551a4626a64644fdd8c8a2fa00a39602bb8c280a989513015317e1c9d7e21cf512c4341a500fb113e3bf5429eb96b7421cfc66818ede9111045131250cc017b9202960246587e72e2b2c5623d16eb265a86f1fd18a484f899e287ec0ba513a8862d6ba160e479cf98a29a1f024398886102ecdb4b20dfee3bc1f50d86e2c7b7d3af25dbd4522a9ea56d21bbbbbdba9cb62897ad63cd34e0a1e74f16375bf044cdf173a666b7b290672621ed891830a7165ab6ad4d21c90a2ca7316d8094c9e1510797b3c8138f51da00e88b4c201e5f81f0a45161555de161c1fd2923f305e8ca156a66dbda4c831aaa2572769cf1eaa271f85c8d31c4ba4914662bb2b1a3dd0fb315ce0a79e632477e9cbefc94f9fa93a44a8f9dc97ad0f8e212860c459d1af6549554a688bb3e333ce873458acfdeda55c70cf2de7ba3f09901f6c5e70c147ae98f3a42fd048debafdbeb1406f2bcb73b9360c6471b2a326b9ce004baaadd7baf93265464fae16e0f9ddf179a0c26be7b657002c7051caaa9212fd0b21f4e376bbff620f9ebf63a5d429ef74a4d6d11ba16e7ab2f3d6654c9181df271c8cb283f54fed0d0d0d0d0d0ce831f1e9db5084fe4390edd7ba4c385311d73fe7ae943419eb73b4f9a9d9c732e53dc1323e450f237479abf7e4df8462b3fd2c84112658a0810eab4c7ebe6aaeb9496634530d01d7d7b58f0f863034a180a237fbe824c40a3db3fe4394a8dfdf5d34d64ca8ead0f095fae17291e7fddf221cf4bafa8950c2c1a4efe94a1e942a7088ea721342f389ef6a05d2be6155e6062b881a2614d8f3c3ecaf4f07a3265c8942a2fec79538e7af2dcd4b8d0e7efed0206c5cb0d226718971072864b941b6baeaa7e08af1518a037b58b274c9a0f460e185f62049101e44e36efbd97878c9caf69edecc898116321064e0b2b2e6888b9a841ec0596d995b5d6c5d0a93263c80f384884b612796b776feb590d52b49c6d1df2b41eb0597167fcfa0b95870e02b858dd9b02891e25337c5d1942b563684e00c48a98462841ece98a861438c45280e550c1444c4599d80a1f72b2b5b6c415156331d640f97163a70a919212220159a1c93546ec84d8df1b6228d0fc751b2767935aa920c516dad58a335ed408af88e7ef548ebf375f5b03795e3436c8927179ebd68a391179ebe589b7516226cce044457d1e01d69c1b48e26c79225683e84883bbb7ac4b931f9fb35b1ac8335f7bf1bdf75eb33e3a74d88892b24778bdbc51e6ef35a9f8e60c00ac0db1e4c500967831f1c1446c86a5eb74af13cd549c92268dcf1d3d35f88802a44f12241962f8faece6e624b3ca1faf405c4f326aa8105af7d903b8e881a68c8f19235484f6c71f33ddbdf726b5214f6bba25234fd34b9ca9cf6c922e35a958c2881521308c81e3e54a8cd096bd6d41912e4e507c744d29135a1f6fa978496bac1a2f3568fd4d53cdcc442c17f8499203888b2f3432eae478d2e59c645ad3445382191917b133d7565bad44b3283b3362a8b921230c1c1d4fac191be2c4963134ebe50d366fad39da32220d4664ecb5d6b45e5a1a6fed98b369c780fd757bbbb0f0f1d7ad18f2bc39df7cefbd56f776f0468637515b6ee088096fd55f1d28fe5e73a80235a37272be61c8f3921933c092b75d5488bd75df90b7ee5d563079db05aac55bb760c8d352b3ca94cd4b33b5b6b453e4c48e245a73a084b6c7d4129c6952b3173548a1b25973ea267772723a21a45eb3219220be162c36514e42eaa3990cb5098735caa94c686662c634b5890a87d90aeda98f416a93281cab46a71a1497ad2a757452c723625f58525123f52e29d2fe06e0afdb2fe47971c16030e8e29a0ffa0816e8835e7ad1d2e28341b762e419b45ff6abcdee4eea1ebbbbbbbb3b77777777f7edeeee5b37b0bbbbbbbbbb7d9764bd90a7699a6ebb90a7398e6ec3c8731c47b75cc873cc6eb3db2d590b79e67bef750b469ef77e91e7b5d65a6badb5d65a6bad75eb459ed67691a7b55ce4d9f96c8bcacc72a9493397157150d05002c68588b07b34ad6d2df2ccf7bacd22cfdbb7bbcdee2ef162091b174cd27c15e121ec1eadb5168b3cc78be5da6a5633cfd90f367764a8b9127677df6bda2be439dad10a79da7bdbdad15a6bade9d65a6badb5d9bcf77a0927a14d4a3287395be5eca399cd6c4bd36d15f234bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbdd5221cfbef6768fdddddddd9d73d9e514f26c2d29b6bbbbbbfb068f31f78d429e0d254a3765a8284f7110633425dcb8c73a4d37958041c7151960f0d8113247c8e30ec6618c31c6de5778c735030b61295c3107b8629c650bc6618c316e8c718927185b5d60940139f224dcf1c33aa6b5e287950c6349d5aaa42c2018631c85e5985d9183f1186e4cb1aca8c1385cc3358c2b8d828331c6e2071f8a631405a32a2cb00d638c8f2a13d0b13bf6e0b8448a1a572d001541025645882bd50f45504981b39492c955f5c1a0db27e419fc61d095fc16540a063d68d22a2e60e8d245062727e130a83406ddc2409e4129a971f76396323f8e595b477ee442f1a35b27e4398e5617ce0a28554e425ac4e54d931c5cde34c991ab2a936896c1cd789ba555969505cb5bb74d2c13dc73e0e20bcf01073e067a0edc2e296d3dcb8246cc4968dd5ed9aac68ccc84b8a2270bcb15ac1b59584bb2b25a2859225ab304051c27a72451b84f7211ce27255d91f2496e91941b941cc91ce4b36ce5c967b746c833d33e456a1b6afccdaae2e5afdb179a0c4745c69b6e4d1fa9bc2152763df2ed76c81437ffe13fb815429e1f5a01edf7c30fdb8307b741c8d3834751cdb961c7ca1d3321d02d10f204fe88fa0c95c5eb7c90dc1132c3132a2f4cf5d133661fb68a3caf942ddbe3031850aaa021491205061d3bbef2edcea5d078c4c7319b62ce639614a9b73cb29d2c45e870add8d1a24fcde10710b63bc844bc754b65de2b15033e52aafa7cbd4161a34af9d0722bc7261520a2eadbb401707bef95b51240fe753dd2fb7a6ca72a939b261a530433ebc9d89be3d59b661614b137b3a21879d3ad8ea0d5487dd9e7f3f9a8effaa8cfe7c7b7f3f97c3eebf309cd30d1e24e10296e68087d388848f1913e9f8ffa7cd4e71b42e6c3f97c3e07fa7c3e9f2fe7f3f97c3e2f7d3ecf525988747dce6e739067ce56aa9473dde2b8bb1bb42ccb1019d6056b833cadad419e4d03638c31763b833c318e92419ebe3ad6dbb5a44eb6d65a1bc3c2f831070c102cdf6e5f94b66f8fb0a60b9e2f527b881cb991c5e66b5dd816e469bdb80f21597c04fa11f6ed968595b252bfdfcf977e49bf2d377afc7abf5fff7ebfdfefe7a50cfff35d652afadfef0708aaab953b3082d8155b5cd861558c36857d22cf5f5b4aaf1a5dcea34551da136ade9ab0a3d4dd73d523c13ad14e83f2215037b5b48493922e58585839a2e64b75210cd93d02fa439e798b0d1a6fadb79f51ea0f0c3a6badb596a98fe523a24692eff6f18cf54155da3d5b6ac4703d16aa9b6a62ad6b5deb74493a9da9d3e968e8743a9d4ef7d38925e900e9723a9d4ee7d3e9bc5625c5d1e5743a9d6ed499e1b9a21bd2e9743aacd339c5d2dd41a31bd2e9743a9dce69944ed765c78ecea7d3e9a8eeeaa84ef74497d3d574359d03753a9d0e85cea7d3d5c8743a5d1daad7e93c4b2599bb2038beb3049192a79d9cc8b3850879d3ade98d873c4d939663df21cfeec2e3e57f3f6f3be4f9336939b61979b6cfe75d873c7d94071f1560aac6d19b0e798e51268e67f6f5b82b46979d348fbde76024adaac7de729ccca63e67ef38e499b1171835d83a48ae371c2da7c7de65e489e9b8796bbd69204ffb6606f2d489e538131289c8402db5fa7101d3848c16133438682cc9e118ae9b2e3a2bda9c053232c30a193f556cf47931de3b92b121cf3c074eafb154ea07d62d5b355d73a42ca5411ba998bb0355b6647949994a7b536b7cb12115038e29394f54340271619bd1f4193c76b677c4aa78f13243d417177546a09a193cf6d5a2cc58d64d342aaa0c09090909a9911aa99190d2202121213910093f1212920d241209090909c9cb388ff448d7ab8d8fb7d69b8c1db363a3e7db8b6c8b986e1f3bcc0f8b8bff30c41aa8356b1ee7f05a93e6c566cb636f307ca4988863f6458c3c91e8a5a2db5a4299405a697e04c102a8469948e3a39524850b5b3258d4da8b4df1d6bb0b797aa989216c6cccf66ecff67a3ddbb33d6b5615d62beaf57abd5ecf29560fa85eafd7ebf572afd7db31d6b3f57abd1eeef57a807ab65eafe7c05eafd753d2cbf57abd5ecfcb18dfeb9149ead143ccdfaa227fbdb9f82dc3c3a54c78aff716f2bcb58219ade591e46d0fa7b7de5ac8d3da06a3653b56fc387a7f91e7e8b54595f5b984cfde5de499ed5b6fae311d3c1e6fe9089bd2b13575672b04296f9c64214fdc52595b5c5a52e6f8b9eaacc622cf9ea594de2c5e67eefc0812e5cc8518685d64ce4d1acb96d48db7d6fb4a95aa52d6831d5473ae9e30f19105e34bbe59498ed24da2d0ca0d405f7074f9f6aef2f5f53e77a0bbbb8b6d7ce78edddd4f9c7877770c3c21e304192d27d2684171f5d89b0ac6de53c81357b328df6edb5b0a79f675128079830aa84a9493903cdddab6d987dda9d8160d63d65a0b853c33992327a902687122a3c5c491276da95591102946ca62ec58f2e20f0adc309067064be37a6bbd9d8822aaee08f58d423b74e8d0a1838b793a7470b143870e59aa43870e5ecaf01d3a74e870d4a4cb469166b2e48a3c3bf4529b3a8102a52ea8848a5b2a8bd639653300000004f316003020080c85844269a2e9696c5907140015628e5a724ca48882698e0339883206296408320680c88cc80ccd3400bbf826629374775f2c58a7cf577c115b0b8ea404c267f22ac7a59ac94280428c769a4de08f99a0dd4dba1c5adf8e2904daff43fca3cf006d4791fbbb3abc0a74d87466edbc10f8b97258df10a1c88fa03b873e4e83c4620fc882c6dbe70c635095f54ddba1be517669cc2e108fe827eee1084a22fe3c50ef79de28a4e22da0c77ce39b6f4b816ff1780b0c74a8ee1cb6a845a4327fe070986b2c6ad70e1b7b262e11a44008a85fa0a4d5b0b57e1200a9c166bd01278bc84dca1d2300632c6efcfa73a3ef52367480e0cf8060949e662546a3a19d3583474bba1a87b7b9e17641beaf147dcfc9b22c058186f90a2af190afabe500ed566941ce26a0b90b4d42ee5ec09b9a0eb9b19ed5c031a4b9d631d89c8e2f8478bae3516977a71ad8f94b92a96e58b1bbdb8135b79522fd633f78422000e3f1621366e55e95971e20677e18b001c5cb6e48a896936c90f41cfea579705b25ebe191182b0b4caced4fb3b464331211386ddf188e67c4d8aefe0f19e77f6e97fc037f1a651f0b0a6441be64823d05b83051319d837d00ce46dc1e46d8d369dea8a6783e0d6b9ce80dda093058cfff2606cf6637091ce0738c4cc166042c9648d756c3f0c86feab5d6657b83ab8134c53229f320061c8535adeab85ce0b54a56605e981c769a5aa38c6d6389432740ad6a0f921098ea563dbcf8139400ed3d3a76d1eaa5184a8ad15775dbe62426afb15e78e55c946d7b951df9cfb8b866083546563e66eaaeaa1a25aac949ed03a0eb37201022708b2c9ab28cdce8301646d0b117b90b5e66aeacdb677c07d1adc9063aafbdfdd9c3a050a424a0d691485cd058cfa69cb6d4134b1aca085d1ad96ab588fdb82406774b8b513a455039e4717e3800c28b94700609d7818bb973e98489ade303fa7b4c4a2f0551ddcda892dedbad618604d9d99fbf32e5861f1c9da81e8bc234d8f67b77d51bc3d17489cf86d4f39038f58c36661fba2734923e84b78809e560660f065d4879e5a86327a48cc14b1bd8a62616bb0905dd7881573ff798bc1be75be42cda1086c81f0e8511131b2f93ae0a72a8acfe29fe54f48df1132d7350e5f7781c2205f3fdbaae2ff3619401986730b4ecf531ed2e723306a871186480cc577a8f07161e5abb94aa392da625045ed92961e40e65bfad8c45eb1e98443191632fc40ae48f123e61bce5bd836d1c543879e2cffb555b90f3b159a39cb9df85d46b74ceb0c4092392624b5f84117ef5165331bf550fd131185a3d06a8824c2107a5f09d1b2fe06e5f3e964ec691e433abc46fc2e03e327129e3d624cbeec95f83467d874732fa4d17a62efb6eff879b1cfec8f4a0ce737d5d24074be6bd00feb03ffdb09f928b27608081d19cea29685c5e3b12c931980ddcbc19686e7896010d59446bf721f8aa8eb07b1e337ce4e600c5c1ed8279200744ec6ae088cb73fd8a3247ada6fd89136d45bd7cb89b9e5dd0e9e03fee10399c63bb3d984127cb5d755f03f6e2b89e4b6c57fb705fd4b8e0b21f1840f3026dcc1fac259c8184f14145a6dadb7431dcc762cef2d3d843c6028df47d598711cdb4d6b73eea410368ea9b8a8c2755aa373db26383026e14fd98f61df4b11f3eab5aeecdd1bdf12f0cb75007f21cc977464c19688e8077587a8b573614ebc586a4ba1f507987de483eb78dd61bb316e1a9b670a523ccc2d696951670a6be162b08ab394fbf7b68fa5348e079ce827d7ca65d433ea01ed70e9e66f9915191c526e6789ad4c133b0bfc616ad603cf2164f4669fb12ea09726bc9056dfc1ffa9647205c13fec856b4b70026aa3faec2e9b977111f43b7f16b04ef27af69e3104418b6e1f845b3d735dc495859a1a98d1f7da39138de5319bdd5eeaef02869fc34c5d2e23a4a8af2e5ff934ec807b53f9011cbf8f10dd0c2dac95dfaa4f7578e9ac681639181b6090fc661fc1fbef8d15d98c2e5db6c1f667d712cd49aa30f06d757fc6dbe5931c9c5af129e84496700cda946d4bfda9e00f1b81781aad8fc28297eee4c9d4034516c6b3d6953e5511df5e1d475be17c5afc02ecb67b4329529e4af21e10df0972679a0affcc44f99f9e80d73ddb5aa5f4cfc62a99225c95ae573be96171a7a2dfed31f13ff015f6bd1121325b8616935d662a97158c969342812a0fd95123ff5a00e50b8fcdda3f39f0fd9f81d4452d20b1c82ae555c247e1eb0c103306524023d9488820cb10f374f3b5dc156141db4f57238e2775e7f68b252f5f71b676380253275fa51500cc615362945e00ab0b27ecb81aee98e706ab48bbc88e1c50a97efcbf419ce748081b4a9ec5f8f97cf67069d8307b3cec0234367c091c2b8e09884e546fc4b161c1bb88591f86d8421e27f451cfb700370a76083d779b277d5107f3630e0b93e33133ef9fbd48d0d268c342a983fe841fe693950dc80a3fcdadfd0d9fdd0875fcbbec39d5dcdd51b87fc3953df9051922f14bc4b396450e3c549bd5f79c570b08d923ea910286d8c34825de9db1b9bf2a2e1a4bc84fb311d7194c494976a1f4b26f31179ee8406657cfaab8b4e3a27949d684af014b08c34f4d9ddfa44929e19801329662f7097c3416465c1909fb8f9987db39ec9f3230c2f2069abf9aacfafb956d7eaa7cd6751a2af615874e3fa66d1bc86af1f224fe4c1d65d22653425d2d0b5babea42010da1e00e28af260b47f8c715f342ed13efc63045cd0d70880f517684fef51a7cac6a8cfc0e091cd3ab596c238af954451c404aa76b4cc32fd483eb56f9a5feb9ab135c7c0c8957829a1d885ca8f9f815ea6f1785d301c79b77cae27d8a97e6e1c63955f0096cdb5a94462327132622dd54c26be9cc57879fcf4f63c7f41a400322392d5c1e44e4a25419b737dae74a66ed0767826ce4d180c323afcf657666aced00d09026e33c9c7ecd7479770071ed83af25240e9662dc8abf246bf0f0b1c8ae424a5b4402a216f129639f768124b9ea959314aec02194a342c52a3514ef99367d2046d2b67161064018a983c32f1cfc5dc7d941c1051f260324d7e9ae411ec6b726700d4e51a6e5a41f28afd335e77711de480f9642ed4699efd457d513a70f4c71f3bb2f5eb12d044a95ce6aacdc5024705d156ad452dd374864ca9f2904c86417576dea52c99f80d02ab550cb510f95361960ec6a6e3cb4e6ef08be41e9c4226063888cae2fe157fbb0afe9ed22969f7eae0b0f9a2567cf8c04f64952c7e62d4d2519ad48406b242ed1ce642a15ecc0b7f5f2a8a58b1016aff0fa4a0d254c8e498862f1edd786b2d4fd1bce803a163d20ae0a7200c26ce844272bde239a59894276dc14b72532a5da620fc5eb1f49afcbbea76572fd8ca47dcbbd08604926fffe8ceafed29447780c4ac8fbef2f98d7fb4e3e0ad9aeedc6dfcc9628d847c39f8c93408b628d4d33b952ce32196d000948a2868a414af745039ffbba63422791688e1e232d411a6c85e913f96257050adb80eebacfc56eb4c8a8412834704174501da38ec91e82ede25bee06408c68a4bac6cfa5119d53b4656897e7caa613a89c1545e9896abf1e210504e3f77e89e1012c09409ac9e2926f83b95291607119cf1f9817184adcf76de9a6cd02e1686e98fd2b05f6f40582cfc7638d134bb6a503d1994c0c3b0b483688c82983b3c5bdde4216f8a445feb1f787606aa9392a00050b300cc96bb2e62aaa9ac130644354803431cc96c567385ce06a3314cbfc4f494853bf44a11a154e42705d7cee65e47f18f9d32c7206dafc01593d116aa8c27fbc3a932948e09aa47c5abfd70139e59925fc83f807ea109f72713231ea851fbdd1e1b6eade591236ff713b20274ebb3d319febb13076b0a7e8611d1e71767ba70418c2546bb99fe035755fb067c735b3dbdf5ea61f75b9dc9b26cb418a35da104975f265deb4baf51451ede97b723a79a7adc3200428bc6af4991f80d8ac09609fa0a3cb2493e841686f953794d10556b87b1c4ac646cc49f123b91016353ca978202812e81f78fba6ee1488e8b716124cebf1e5f8443c0d23f0117508b08c430f5e909e0652c7c45300e11a8524b6b8f9be5a19e881fc4758859f11e328b7881538b902aafb53263c53d50c9fe8d2787932a4bfab40a5ee71ebf76b6c3b00e0b1886068a9bdd49c5543a459b1105f2267dd9b3343bc4509333d81c117d7714cbaa1d4ad8b0f5dfa2da7e57f3cca0b84a9425dabc82d6055117a7ae4ac1e6abc031b58e2d5ee8053a1c3603e72f4a5caf2126e0c19a642d63e3c1d8d50136f756eb271882e90be5df4ab1e92e6b1d008e75128cf1afef51a2ec64e59f3ccb0e466a84aa6a7d801b8fa32b0642ff911fae75cebce2446a112857d41aaa78cd4651e3614257a24440dbf7c1f44322c43a4af204d844f10ac8d4e2f4b1d41a554346e3d067abf73dee455ef58b8ec7de9361e33ffa5386c3577533b15bcfb8ebfdaca3e63f61a11146ba0826402dee498a41b94f52eea5dd96dd47226d697b84d4b430763e80f8de7be5eda26bdc8222856a37355df65cd32a67968fc0aa55ea3ea4019837f892f57c64a4007fca8be38e2ff0f21615a62c8f1b29c86ffde386468506696acb0dd907a94a39a6fb71112a6c164176710fa389ff144efd4c39f1e4474aaa0dac43eeae6d627a1d86ec204da1eb89e07d0cdb53e79614c0715505cbd1c7cda5f087723a21f0c324e9e23ed35423d544d299b079c3716548e9fc0fa65dc1d2e96d5de6d080591655b190bff226816cddc02f7dea60567acbbbb42f7879d27eb3cfbabf784d72990ecde7b867ec9a9a0caffdcd283688a8f2f6cdc66103868e258da6166b9c04494d72073bcc05069bb00e30a43047e35377620a02ffd497c3653c5e01731fecf3d680e09451cf9a82eced0c5cb05cf0be5ff6caab6854e831eb5e8e0c7ab823dae63815398f74126cb99981bd7a48b8dd3c2a8015b8980fefb7596df36e78c3edd2fe113b58f13cbb34a6566d33e9c282a5a1019d344ee2344f5cc5124928ce80647ab77e32df45e47046d49254f34b9733aa3613fcd3ef765b0d1b1e67d3c14486a7d157e61d8ebc8923ee587b36ff3977e3a37ec5df20609ce8e2542c45f5de2a801a8dcdc798051f103cfd6fd04d951213da0e384005e87f7e04c15daa5dba963bf3b1d205baf5ce7ed6b2328ad6d1800237edb87d2bb6b3cb78897cf20f8132450800d9c18da1251f632843f0f297de2205b1c4e327cb3133da8c4076fd23eae6b0822630c6182a5adc6e279e0e27bc878fec7bddbb40e4ec4eebc3778b71caa395cefb1db639a84f46b5b455633412c5227f81ec1c9d8c302115ccbf5de63563573f8f9c181357aedac57d132f8c8a7a5e35ba9097b0fb98901bd72ffc16049e3cc8c50da33d9b4f5d3821b8a85bcb80ca191c660aa44893242ecd12a1dcb2f05bcff2f8b114c4c30219c20602916a1e81d81da1ac946f86e449484c65573ecdaf076880eb7e7cb854d299fc36b95b2dfc28740e5cdfb8f41efa29093d84ffe92b2a1105235df36b4cc5be8ea368dbb9a8f878b86888d88527cb10773899c03cbc43288da30d31cb30f82519235f08c0c456508081c9916480c7f938d8cd089b14ba928b4ab532087cff7cd68c3a05666f219ead0e83f527d0b83c1f51070f02ed8531babc76cc2e6999a870a49cbd60c796ae0485b93b200d0e480a4242b6be70913f60c38ce24a5dc9b6293fd96d6a3cdb05940126bddc4be7782142d6679b0830c94dad7ce64966c1775312424aa334da312564f3216c77d5736f2067d3724b5c57a1b37fad6e9f25dd9897dc9bbcb15e79fa37ba0598fe9d3b11a258b12deec2a5834e41dc0f3ff939e3de07f9b41d4802f7bd905b82b9935ad2439ba576a2a7c060a295f74710489a9b94cddbced15259af7c8ae53b8b5e429e30262e6af2fd934750aa1d1eb47c81580c24e3e1991ec22659980b2592f473785b485e49e49d8c1a174d2a85a98207229a00fad7cbfa6cb50b1560da024a65c081b11fc07ebfca2f8796e477984f744797fb8e7793b7e219b7c7d7ed6fdf775a4a53e137186e72bcbb52f035db30f78bfe142b552e669887c7a0f2c676ad89591b43b61cfcde4d2abeee9e778227615a53a03f8c399ffb013079fce042564dd9342872abeca4d6abd858409310e600aca631d14ee4d677f6465f69130b2c052877591a27a7a39e8ce259e22f2d4fa975d9495a502ca125ce3e4306b5bc04689d85ea2c57db064c9f00678dd9dd0b64b788fa801a67e94f6c38cff363799e7669682343631bd04d554d8cf3529cc3406b9dae902ee15498952c809b36199307b1a206cd3634123e96e87882bc61ae83206801abb8187de138b481822c5605f933d2a4ee2e055c1ab14459e6b6501b6490d24ac004a9ecb617923049eb9d9084ef3661779d3f47781bf394c09ddd88bfea78635d04a1af750e5d12e124fd88750ae6fd71fa1ca67feb15ab460da85b769ca4b14ab4f5aa59e71d60cba2099e66f4344d2f5638c624e1bfc6263382c81b18a04148335f463e9fff00b6c3c31cd61ebe85c919bec3a5d4627fe5e7663d6435ca32abfe82550120a1c802cf2672a029fcd3f56a36a4859e7eacdf8d3d0406afb4babb187fee0736d494504ee8a079aa688bfe1ed3a6f34eb633c39f421aa227e6d7f50efb11cd52efd9c83eb819542d0fb2874ce0071dd05fdc0d59a5a2ec4227db74db930ac8a8ebea814e59746bc568902b99d6f731d38b94743ddf623774bc5b7045637071bf57c178470eaf3785b13a3d5f32bd6a896512fd75f20968de23cb06c01ef95fef3f0d405fe1d69b4b5a981c9395ed11b31b111e0c9b4d55f78bc0d5994c9147e00a4a6c7c4025a0923df3cd52f1a05188c554f8456fec968bb2b817bd2b49870e3bc3093a751533add62ea0bcbd2821ef055d0c2905afe095200678e67321fdae575208a1c63e054f57da366d9018fa8638db19d9ec6c5be4cdfc6d0c7e8038d003d136acf760c14f34ab7542db7e81a4272d1148b01c349e099040dda672a39693e5519603133e36d0228de122ade434a32ea73715b0942a554042b85d9f76754e101132c0d28582c15a9a8b5bb41fe8f9c6b4add8cc5a0557bfdc9427cf11f18b8354a6c107e2c2116ff996797870952d4213d1f4d6bc27c9721aa508e5e2d64271521e058686b8b8f8f021e744f2f90d46661303bdc5f7c6f982c07b6e452b4af191db66b4a53809398f2ba6809cf58882f6a076c9d6d1a40b68e605e9053a9a55a73bdeaba82e107405bbb5fdfda05d8f9e2b9f0e9df87402c7b6ba2b639fa00bb5bd9b7a835ff83b2a70f898339f16cc1994e7afee976d3dd648d03a4a41d0e11247627b25cea0fd5867671874c9da88e1c5809e995a2e0aadcf683f0a9c52a97892768e188d01cd79c48acea1cc3ae0d0e2946fddcf21e167c42a9e51da073488862f57af4987684fe8012921cba7fbe9aba12ab6e49231aead4f4fdf4276a5a7311750482f9fc768bfe9fb6e5f7fdfb1af3b2636314cc6116bf12655249accac8bd731d1ec10c81e69a71c2dd341d4487b94321d44f001c1b204d92a5708245fcf0b98640aaed0ccd74095ee26a1fd34502cd1264bad630a0325d9f21cb5ccd2dec39af1f7329d67a7b79f38511993acd6eb818909610b68437a7a61ef7552badba8a17b6363d09ff3a562425a12440c9ee20bbade53a91aa29498980524283c64a00baab0b1ffefb14fd6c797e439e791379582bafc81d22c5815619efcc40ab14ba1d1d4f4c6986104e1e912d660e2cb6ba24465fc0377dff9c134602ce523071334a4737f99718a9a89c41160ec5f142ff0314d904aba7ff33bd3508f6afa3c1205dd3e6e58fea4275ea56a39f92e4d0e1d079362f39bfd425a9fdd353b79dc8d1bd7d141cc66b5a20df7979822276e41e7f4804133a3265519c0f613a419c7a1ba44cb9a0456682a15d96d582b0a7851f8f0a3631589125b6d9786ea978eb3800d2bb330d935bb4325ff06414179b7016eed9ba63300c7f535f7ca41eb2b653bcc8746c4857e59b8264aad1e2f90677eac19a2da207c5fb6b1e9e30ca22a0cbab993fe665b71fd50c0776923abeb5f482624436320151ad1f17929b54c447ba408c03d18ab151ac525b89cc20736483fc0296f521cf2a99bb4ccc3fd87e975494b1040e28ea49bb908c91356f7b2830186034ee6fa5062920f575a07bf8563498d5d5e64c222e8f31597ae0ca0d20e5edec11bb64b58c1fbbf10f6f873c5b97ebf62a47c8ffe4287bf415e5f35f22c4e67238f1bf931218014453d8dad2188cf9d1e7f8ff36e68e7fc654fca2cdea4b7f2cb3770a27bcf324100a98539ae1e2ed1477294de70cdfa7957b1d9717017eac3907e8108fcf823eac2fd87314e0d3ffc484c9f38122c6c40fae10b4344110779d8a9225c34efec73e209bd498b9e7efc868ec5006f7b43b6472d9fbd990df25ea44308dcdae302d8704ab1200738015a8700fac609a609717598648642bef15bd8202e4c1494d7c77c137cc0942f122745ad131cfef08c25b6be31fe98bfdb035ef9d4c02e3f15e08232972c78fd08e84cc51c78c6e694e38a8542b4976c986351c935d496037f3b4ad18229414e31ade74003e4db696508fa28bb30618780a76154f9db603f2e534832192e430aaee9869f76c0fdb1e33c3a20a5d1bbed511b898a91e9bd5881672f78798b5e5cd3bee9d52ce3f60a0d9eb17a45d0dfe6f662290d4cf7ebebd9a327dd19ca0bd517feb8936d547c3afceaa2f161085062d7e91e57cc225794363534d67c58db9fe6183f2070559c9c9ebe90924d2da3088f76c8cfa13f30ab107780d16119aa33d01fff9913820ba5149197996628ae0dc40d1d1c614573d53a4aa55e66b6b14ae93998cacc334aec0e8778dad9f56dd5633c677946ce0f75777326a8a353b25fadca28dede75bd63bf1bbfca0e62ea3ce928006e15c62116e5c7074554e393c618d8ebfbcb1994c0c5e9d6771bc18433317bbb8b12f73546187df5f176918a560dcea958c27595c4f435e92968697459e39c83d34dec2673149723406b25c5efc84f512da829ada02e48b88fc616b76cfc26830e1f30107ecb17c2180a3918f382160dee4a47cb969aa5b171d5a76741b270ea9054372cd306910d8a9a7cf402728d7fe6ca77d83b689a0a63b67147c9a9d0aaaff798b40ad07d4238486a60809ea85bfbd9eb1d6df9b7664f35750fb428c402b1aabf23c3f586e0ae135403d7471c2587b7d88b2ff891dd5d2e67d96bf1b6aeb538002f8b3b65a289d185fce3845a69b8463ca29f691e0c8b5e633ff652523c0135d5af6a750d5aa02ff01bd143ebc2c93dc26d21b4875413ee68cea8de79c32b36e2e0d32232884b8bc17d072c8c75f72b09255519098bdfc45904b51106ea623085631abea4c0c4801576263364ccc2efe1cf5a0936d49f792fc9f317a80e6c845ed9a428ef31837b8c6b0a6af8ad79482730c0c52ee7d84eab38e4096bcf1c47c7ec75eab4dbc0722502c7f6351c1b978aa9ef49dd2c0c637c8c7a78912f4cad56884e4ded0718577039f27cc742dc27267c716a70aa6eee2cfd2a087bd0a6f2d80f70f360096e7bdc4ca46395e69aab27dcd39e1a641780f7d428fb0cf1c4c0ee14e9061718c4a0d1600d163ec59e0621f7544dd85728250b15b0a7d54270edfe2beb8b1473050297085bce51d23000cdbe3fd5bc92761ed7749eecc5a690a675a11d5f23d4d78604c7d34aac591ac49ca77e1e0a8795ab19e953e91edf663b09ad0e25b90d07bf5103b3101ddfd510bb8cb5ab99b0b6f681da8d1376f0200ded8da171316b412f1ee22c9c9f301c5f49ce6381b9ae33171ff569af99901c020175d98e4408052a8e8027400e32062f75d1f5227ee1f59ddb9bc248ba170783cde78c1b3a7c597164ef857dec403fc87b93b2b1e38d07c1844ee9d51da2ac5d81a882a0346a40aadac1ad03cf5b04a07aa0cc3ec16cee83ec311199a644c24076bd427bc71f59daceabdc012cb51ee67e9cae01fbc31b9b17cbcce016059df1231b520e6979de3b4ca41013e0cb695c0a256adc8036110a8ec1d9f638810808678ff0e3e1d0b4284e33c3f745810282bcdd907a708c45f19fcec33c7c148b626c5b141ecc0c423e1fcee901c9f961f2ac537df7ed4307203dc1a2e863f2095e5e8abd17c52a85deb3e57b3dc6d8980b887f118027166c3df7450fac5184566677fae7d431648c007404a59d1b3ecf68141ab676175a99e1f2e8eca0421ac55f8ae77cdeb1d22830be4641f266e0048dc1cf7f481e2e186f87ee70316d16641231909740d3d9c2c049442dbfd8cb1eca1d2a04525147107dc13a4c6e21e1f4ee02a312d09e12723ef00f3e80645b89d279a3c606a7e0c94b82908a35164e1ed2683d667f85f4946370a99f668936c4bf044596d36cb1a9b4b77f6e4ba99b3cb614163992989dd67f2693a6654c9449b60cdd8acb687f0c19bf7746e052bb49c8115550f018f73965b4e1a9d31d5d324b01471301ad8525be32c96247b195d104149c9a70a5c816def17c756356508d05b0c7991fe655b4c52d58bfb24a6351c3e2ea9b00f3b5642c888e760970676aa0759c5cd5b96ee51699821b320fb750fa17c88182bc3f499918ee7efa1a17ddbbebe81e87f7250a3b6f7b22f7b77d31d4d84abf47773be4a7b3e9668b92b7361e0c31024139f1b0b6ec733270cc0197694963386518d4ac3bdce6fbab54efdc17039a0a7b5473fda69882ffcab09fc571768189918d1013e7ecd9d0fcce2f2a9d41a091fb56d420cab2e646ea3202cded12881f4680e43658625a6faec5ece0f4aeeec8741d219b130abb84409a63b0aaf3d09921b5369075841fd2a8d175413d64ae11fdf3582e51c708f938bfd887719fb193b106cfc1dd1be0ba624b1f77d11acce6e4a3c511338aed21d90da75bc94fbe76ccfd731cc82668f75807bb50b69b062bd851f67f82ef9109d32443c36cf3e27b0bc356542a5607db49a668b3350c3bd55a27b190fe71db4f7e46e75ee782e8747febde083c41179c31ba6d6c688061052b616ad6c14cadaf6b425d173a5d53075641b7f12110686c9f657240264302e87102744481126a3b81c5f7cfc408f9c3c4f0fe4177c0f75ac671c87f6b4598d38d25e779a6cf0fd3ac5cd9a2d4fc9a812a40cfdebace782dc6b03c6e5299ec0ce2104ba0cad2af9dc11833f384d5fd94b179c2209d3f6698380fa9c176ea60447dd2e904505887bbd6c4d54e602ee4316a93c17e70ed86eaa7f552f0807a29670355d687bd9f7f12e81a98e9d36d4122e79d3c9da5ece38234219ca7d420f8fcef1e3c04bd2b4da1a18341e25ecbc8385da1599dfc5916a6cbacd26ebac1d67d76e26ba364f0d43a57ab9c6274499d001b113426b310665746355b864b7fc7830d5aabc574e8b90b4667ea8152a42e1421286ab9a9e7fe41763449cf822267eebea29984da495aa8bba32fb22896d09ec7ae0a9be843f8a20a62c618ebf8defbd9a7b0fa4a552b4e73ebb78034224f5bfc23f4ec80fbbb43851bfcdb17279e12480baedf99fcb879033a8fef80405b833abb027f15809e26288bab7eb19526c5b20f145da7729f162b628f2f77ab792356906dcb433de34c309bd36a5c02d6854ad1c844ed14e19c9e07c13a9076f11293342786fa5c78e159823c097ac9767ae5dc88fadec8019376b0901d3fb5bed6b3744cafd148af931734383ab6e929667951dd317fbcc3d81ef6f426beaa077dab2abf7909c3caf43e13dbd97bc6cbf1dae1aae8c8f674ecf8c347f8af28d6b56464a136276144c2550ed5a145d7229f5fe45cca28440747e229ec7dc1b46ad84ea9896d79e3e635b65ce27829f5672b36b5762a6b3287b8be9bbc41144f3c7fc7d53089b24b97b398305ea6c43bdf237c09d4dee8a605ff9d4cf21876ad6f7fc8ecf74e9119c915d2b10e0a53ddc082ce3cea33874850bb3817338c8a126776b2b5b489fb8f506629cedd8504e8c3aff98107b5453d036c9c67efdc6baa7b52c5dd66f9be1c78a9d638835ea8607a39cb391692774458419c9c8a6c98171ab23d43984564fe16051993b7afbbd3beda6da5baa016374ca3a56b5ddfa59d5e968c0aa0e9a99695510c9494c3100932ad1ecaa11b64760efe59e3d6615cbc46344ac853d9ee6d62718d3472ec2f226d745f64ccd4bb9380fb032b9ad3b6afe32d6abf09e8bc096bc4f249446aad60061fca24a09ab53d9adc645e8cfbc263780b3c53ed7a40e89f75df22d8f2c350bb667a1a346843878f44dc450f18e9057b65bb2f256427ab9d3cbc2ec279583ab3cb514db4f749a74f50b82dcc65ce06a16cd877646b11a638a0f4d92457773aa6a68d51aaf2461bd9aad37b2ef54578fa13bf959fb53ad4a3c80a32fa8e760804cf6394a9f9c5099c853bc1e7265ad11c7482d071c6c37f34ac375e6b149c6e1cf8c293192ec782aa7ec08cf094599ffe3831fa94ebba9641d59746c52335c08bb246ca012757a07ab07695f1f4e36b191a1c8205826c22ee2e436b07fea48ba0b0a5a70192331f3d7da05ca8cfc92088549ff4b8cf49abd8da4aeb633a1d261ec6493eacc70bbc965d2a5a6d6da0e50b3783654064cd21200f6bac8acb61068083ae1edea7c78710f37ff80842c26d26d2b338f4c0e22752d5ccaca1adcf611f66ef4c4a2b0339bb52d00975345e862513c7c018225b791c5b36458fa61fe462a50d478277e3c0d5d0550d17dd9d0c6ff8ae0de57511a5c0253d9b8084450f11b36637352ca6c35a52878a4885426b21136a4cd41bebaf946ec5243eabe0a10a7099b60b97039fc1c1b70c077f37f6d3828b2e1285f62a1d8a47be58582637e24bbb7845975de02720b00deabe000ba5de6499084d26ca42ab381e17a7c30291237e399917c310fb8272067549751d3d76fd6104bb82ef120bf3ba82ce28c3b6a5f69c0d30def8d819e8aaf7fa610de8c5f82ab44f36596a4b1089e119a52a446fb2da51cfdc51cfac23e5b642097c2b2d98ae933a21a1c83b723b4295b9db45aa86d9245840eb40505bcef5a8e6968c21efd3c14ecbef7d06bacbad8a9e28e34760cf1cf60ed8774839fa7a739fa8da5f08732ab775357fd353fb8c4f7bc7f1b31ecca879081f1bc880b454a7461f8a43d16d36d7882e6f903aa531265b7a2692a1bfb25ddce0e3585bced69a15209d4499f9a87a6d9c14b053ae51888c342293b4abeb6291d8ef52d948a24c42a3866ee4db68db0854b0747c63b1834c23b3164930859f1a1381bc5bfcacd0f021aea9205f1891af294fea0b0eb991f6d4885297cdff1b9191c257947662ccd831df423efa777b13decb7ec2da3c58cadc1966d67e603efd696d9462b99580407fa02fd4f448392b00c96cfac0be11bf73c6a376cfe3e0f483b6a60a192a32f0389e66758c4a0d07802d65c41808f3e273c22b7b1105553c7315e4b0330b033c402bf595d451a135e377ae3b4a987528cc019c1fb7ff894d06ec713e963624befa38d3deb7e1bca17387f07a3ecb4bdcf88929b4f24fa6372d39497746c75e0bd7de2f912c390820e159860754b676a44277b06f05d7342cf56d09dea0a348372f944a5a86ee18620ea176d912814180d15772cf004aebfe9704a171ac0333ff6c3358d81ce5be8a9af28496e6fa8f2892b99b948b476b4d1ac31ec0afe588f15ed6cdf1e405769f7b812731e331313f9869a9e71f6fcf00b28e7101525f4cf1b166092b2f403bda3b97556c8fd5f126637b8dbf103a8bb3d86a28e18caf7057d9aec30699f11fd6df5620b2129d883cee306b270dcdab3aad27c840658556bb4e4c81dbe9ea05025b322ada0efde3c211b616b4dc397469ca06531fd80ef14e64e8ef47536e5241c1d8ad313b4868c24760597504e0575efae62e671d8f6c3b231941cc63176253a2d1af038175e03303443e62a6d564c17e95fb6a4e61274b2891a4cc0c5928fe9d7e504c47c902144cbd5d53b7d5958b479e58d30941dd55a18aacccaafcd8c3d6bfe858b639c9261d676d1eed3d684293b908df48c2952953fb05fcb4d30aa63bdd80d0782cd2931a94aeb378dfb4f60bf253dbb11283a28e687eadcd74cbc43e63a77b0d2df072abb9b6d369291a774653aa24fb4f578ba124bc3549f75c04b452d8b41a88857f4c8cf96b228e302bcd119d551d119e3b4699666458e632d3dce25d54856657a0ff6882f4dcd9f7243719ad5eee3af1be7618e322c77f0d204bb4b77528350c67d2389dffbf5ca61c7acc04dc0be53ce4b848a2b60f3320b927a870151a46b1eb8c2508100b885254d4fbd1a20ea1b7a5fe13bc71a43165dc11f9c7c62de5be8f1d48364e6456898c68536430a30064d11f3970795dd107fa67d51ef534198f6b74a51207a61ed61cee4c15129034185040fcded43af5b0b99f460c9b6080e6715f427efca145c5b9a0106779ec740fd618a2c3cdfc6c46420d86271837076482b08a0ca4be2d70009eef2f5c530315a46ce7e98477213ca372d9ec41ed585477acea5b4af2203afccf966b68204b703ccb846b108073041a5de18274abf3b614e779c207a1cc0eb6629c22270454fd8af793ee503395937066d859c1a6debdd0b48ce26789a3143e55c859f80749dd1a156e2df30e85b03afe7affb6a0b41816419aff7ad10e457b6bf53c0c5b996266fe49f3caa5d1511a21efbfcb7c269c98b2fb904bff8902d23cb9286f37d8b9d9c3c519fcf89b8ccce76a2ef79cbceee16ef7ebcb0b4737ea59ad50aa558fabaac645a8eb802ee6e3b3513543ec182e0dc13bd55d398a6f24050238b7a852299e57221a34d607ad17422b97d0bcb53409d212db10cc290866a15424183969166ecdff083e5f3351ff5a1f70d1cde7ac808ef34b2d88daa486fc2179d23255cbaad43de1aa29cb2252a25683943731e1a3e3d35fa06901b81aaca6f28d2f240a4e8bd281f03af2fcb6b628c8ffbd687f0143bba2aa715871e74812002538a8b5940c7062ee63c446e60b1bf26a687bb7989664860fac3d78b5d6ea063bdacc147dfe85d6a90052c5021c0b7fb19ad3b2cc445c9b6ce133756848328a8218a34e3d7e0da35ce5d1d0259b70f1cbd1e8b89052e135b6f4d1d1100d569fd8f1a30bc301433eba38fa93005765d953be477aa2d8a61ffa132599fc90bb12912eaaa44e7378b43ca416095c1584142102e8c842af70a912a71d5647a44409fb92812325b7c6c7bbaa09ecc3d8979ae6d9199b712c2ce4926ecd4c5a66bf8abe8634a9223188143b549507a62bb1b50e30f9bb04719786b5b6ab03a6f79f7b9f3eb1c9fe1e0715b130801ef8b7b065710afa03833d816f97b77d9c758004cd11c666f66afecc6bff693ce0790a65d14fa2668a0314ec1003e7eec83c017864692e15aa98476186b380ed541b82a5c49c89491b2035960e50316b3191d53daf95b8931a5714cb6fcf3a4a1ee4ff50eb390abb2e3938c57a7b9ecab52a92bd65b97f60fa2d1f283feca9445aeada4b989bc8f2d2c28d4aee038695919d4be75b5c446aabdef14e52f1f5f0e613bcfec8bdfcb9a003090f1077f7e0d489b4a6b34f7d5624ed6c7709f86c5465dd3c90aa2a8321485558dc3ce07b960ca84518d85c5c36d9a5394b026a70bc781473b3e9f67571cdbac851acd9c9e70a7562c165e504c840bb141a30da7f60f2f1ef873e95aa5f2f6e621573cc44618894b53ac6fca02bf5a7db930c1d600ee8f46a77e3162febed98f2711ae881724a652b810fd8f4ca6e0ffcfe11f676b2d4a2c515e6e50e9e8edf31ca268b55ed8a1f36900481c9f0210abad249a82e9708414da5a37cc066149c63d3682eea9da7e8ecb5ebdb0a2770d5bdfc47c434cf6f0f26e5a9102a6b071318fae618fed86a1866356dba2dc195cccf6279b52029199ddb43dca8d5d749c227f63e8fcad14c1ba343f908f04980a0546388ee3f6adbfbcb637ebf531fe7bad437e5e6249debdc2496ff7129132b5dcc776a857d81776aa55cfb2a4fbfe57287e2f59e1278c2d475060591cae36c011dc80edf7bb2ec434f152e9fb1030536768e642936a5f333a34f547287aeffaafa9dc22becb12e15b8072459e5037d46f6b2a407a201a3d8dc2dc85eb2cc22c769b00145d7ea77775023811449058a88e30db6c3ea7fae1e1114fc3071cc98870b5535a4927cec81c3a9e7ae632529199c5ec3a1acd92a1ba4dc39b6c87d575a39eb034fa7a54538008e14b919e280300f414ae716af644c13561741dad42849cd210f23cef44dc963adaeb6d158e73c9f3ec302f44902860f41ce7940213e0e77de004ebfe624cfe65c74c7a5ed4c6d32e80006b165b8a3dea210268dc23bbd0036973ca6408e73c90c7f1c3b976cc5a84f32714cf5a63273d544bc2e100125d5b41643baaa6d4aa91d00b4c214df029c3080989ad0939774198e27f7348f6ccfb6ced52146c3dac7cacd3a92224ee616ced909b511f9a08f52f1b7ca4b776eb429f93fc43b9229aef068296175c45a2bf1459a883865b843204281792841716948bca5090b5dd3903f5a10ee05b2996ac70b910f0f268cbb1bcdf853f07d62309c9d4caeabf0f932ae0c381d720613bc9c97a6e622d844269b91bd519ae65cad0a4875c21acf46612f34a60a0d42df8e56c173161c062d68e531f952b34d8234f65f81d31a35518722204581eb827b4694b2631873651b53031ca66fdb895ca27811c80cca414039d2bc06426f7a03e09ab5513402a973b81d54436a79b474b9d6993ca09fd2d1fc59c712a3c93f1e033d9e9821b4eceb0b81fd41634abbfb61cd170cd2b81f4bb265d82a247b8571663514d704efd66cdd39c732ba346696bbd6cc0d5c9507b4c94542436040984488f0725a7640af6f1c1065a55a9791a98f1a9f551d394fc70474ba1658b71d41d5b7e5342dc2852079be1ad7944531b420762178421e37df47b02b83037405dc89725a29c99c1ab10921085188f7b89050398b4a09a3c49c0ba3dc7f16da85fb1a46911a1a7e381130235924b903a25e4736de2d68b5da9e9b2628e21300207683509e7979106f222ed11b6b15ce3c38e3e0baf6712fe8959b800dc4ffc97ecf9de0d42ac1e7b24321ded5d6a751e35cf4ec8e3c091a2f3eb4dd31a3c3f450f1d0fc918552e1be40c94f1824d2c296a150c2de43aac4e269ddd2864858ceec78b2eca1efd07f641fb0789455cf3df438a761537b13b275514fdd1257baf316cec12a703edb0a710ea634fc302b9b54710d16ccccfd0159d84e4b11786e540433fcf9a1264490eb1721650dae4afd4052b82e7414b9d7d24e35ec02732e1610e0d128e42582a148234800c4343ce94d6d7e44c4ea29f3b36b2145818d0ca4feafc36f52eab738de6e08410c59cbe58e8440a07abbe3113c8e73159999bbf11315cb692941278b07e864fbe8c7ea57409fb55624e83672de12fe9258da4428daa2bd1da46023c48a62cd596046c185881c9e39f5cbed9556058d416ab959568c233a875418e2d89450079e85e6b886eec5456059fc2960929e15cd65fe202ea19040911baa65dc3fbb1ac41c6fb782739326a8e6ec4df36677627914157c4413142515bf7726e533a14c4f7bd456fd1e7636a8a4214b0f7a751868db04e6b25c52456def67ec9520408a2639886604dfb96fffe2b60c924e41a2869537fb474e103ccef8e265f18187790e587e397a4baeaf2420e21dfb72bf3ebf80cecdc962460a0112a810ca4b1ade7fe8130063ce21391b44c03f02571c04b4a3d6979c5bdd66dfc36d594e8e02a67dbff3513a720f1cce36a14cac1ccee42bfd2d4ed59ac8dd8b3bbd78d9b1089a16098e5d6f7a6fdbfeb3592b6b89b232fdf61c145b862265b674140ee1a5041b15d63ce79d5ca25e909958c46034423c8f9afa175dc7c4e657b22b1310eb2550365f39f70e58cdf06abf5651af9359ff25d296132f791d2757a56b75033921d8c2f47ac021f86c24e84b14345ff3ce8fa22e340e1f5ffe0b1ae928f6c3c5c75cba07b6ba63822f93a17b619dd89e94ee87661307eb50b1a65b9a3b225c8b5a5f62818063505d1fb4f9c217f94c9f49e6a124c93cc1ebc89a71091ff409cfc0f0711753584b39b76ed5e307971a93f51975e5b52535475c8ecdc99e42a503afc773c6a0e058d340f53f2b03d551d4c01881a01e0da21c47a8bf1ec99e1f87bf812666e7fceb876713fe85691c8b070f9f8d41ea8ec2d9110b880e864fc8b56d351b52f64d455a6df8768e00bf49d88f330a0ef43df547d8fcd2093bbc8fa3ae1a5f014f35b9d6a93a8bdf723946058d9e9818e2466376d8c3853d4af5dc4ba8e8a096edd2390ae27c09f720070ebbc77de26c58b2e39a346e9ca8fa25c1f92af02e959208b6caa797d71635e31eb5d5f5d1368a0aa995c1a3c742424ed4f964264ce391c2e0576433b774dae7358c20d5a205eefb182905b1a567b03e6466d0e9b4c8a3a305ee60b9bd25963e5bb4cb745560b76a009be3e22107a8ce2ac670309684def696de0560577d215c2437f84f9bb4fe863ddfbc4db29329c026a41c360144c45d3f0d743398822cccf0120af6e8298188f96c6f54b4073965127411d0bf0ea5ece9ae5de8e41646a37d1e7565843434569ecab11dac0114b39de1d77825d418434dee3139bb97dd0d9a999091da9cc135d6cd769517f73ffaaf9873318fa3941a4d47813a25d0308b93f80b10087fcb14558aa1565d78c38b09755dba9f5ab31720e3b0722045dac963d273618d6f4d3914d115d13e29fbc88c2ca4c52217463ed2359ef2b769abb7877817dd19a77ceeded98079cb51923c005119755460c3528e7c72d5bd2d6d204916938af46b42fcca240e5fbb08eed74a8292e2176f5319c9712bcf252ddd9990918b0d5fe25d858b8ce8a9a66b4fe48c0ad8a92f58195adf8b91e2ffe36442db0ab5fa965de52b516201a4bbae9fce6f96ab7a828bb622a0d381c15a052cc7ef268639b460e1e5cf315ab41d61783a220a250a5d4abec7d356367529b655f0c9da07aa2f2a7805f2934bc9c272b974b971555bd5c87ad49dabfdea989690963da0ea13178e3eaede7f29073b7d035285e34542dc035a1988354325447532b81c84ed1c1f2b12b7893aeaf2c67208e1c7481d4d720344ede0fc40d35357c70233d622f8e28c5b3051bc6790fdb201d11cdeefab664d5fcf1d93a6c698580113b51c6e5990231ff39887433651f684c35e23be4fe2454c0e9d2ebc612c72e6f12162c280fde11f884606363ed9d078f791baa64f500aa3d70d6032739c5b4cd4968a26f227c2eb61dff12dc9cdbae8fb6a05186948b4d2a31c1f9238d45d421508eb0265ef3a253c6518e00c64f4b77224a842c72af12f0a1ee986848748eaea390fe08144f2b123e68d6ee1b8fda0f39eced921894b220fa3b14671ac14766bc11f1bfc3c157692bd52b8594849711524182efd8ee40d44e1e6ef9b57c03531686b4b43e0784401eb1323931fb98cd3e944809ddc8ba63b9d1a5d55559881ddd9ca255760771ec1d26db91ccfb0caa1807f516e5eb664e3992d505742ee48e4457bc91d638a231766a49e327fc3214aca6592bf736d13286eae445a3424888203b72bbd4f86dc0fd8be9ab1c1c1a0db4176b6ac690a719581109d3693c2b9c254f0e2b0b1c0e6a2cf2fbc781b59b3a85a0312c683351703296b10adef5cbc1652730891a3eeb854ccf6265be3cea134671e8385cb72a2f943c94fbe6c058f925699b5a23b3b37118b195314e917e1ee6c289c6ed958ce5a7fcda41df038f6779b2147af7e7dc392626c2231aa447031c51d2581b95cdad62feec5a72ac8a3ebb37ed08839cdb606d0ed9841aafbb986d81318323b183b31f0aac1e1d7321be0ca3717ed0eaa5df2080ba03b18b9c959fca85dad513ed539bd198f3f6b7574c4ca1998147dd269553650a82103757626f9882878b37265026bf8785c247c09888833368b20d40204f48add46e7b27efca93b7579094c83bcf52b9a76c2b6142b031ffa1f38db8415719251a18582fb5b1cb3e535253d2c9ccb7137b8f203c32387e5124a12907ffc2bc6703402997e408d35601f4a4633c847d83ad82211e7d9f8291672d83d0616623e400c68c048c575ac82c9a03de85441a78a4e6779165aa1e042502aca07b0a27e92f8c1221331533f7eb41be33bd5e3bb40d4eb22fe716d98b8ec95e09061acc03e8b3b8eb9f742d6d2e38e1493a3c455a08f78808922a460315fd6356c23dcc4889b53a0d63b262ceb5b3ba31c7d00772db4ed63ea0829e4a35c2809be3c6a59c81f61941c225078d433dbf5c101dec8aafa17cf1e00d88daee7eafec2d5ce9198203524eec1caed0ec5832f112bc15cffdcd70cf641bfb737b4ceff1e0cbd2dc60d2aee534c50d23e93795c89230769c425e52bd81e872c5e995f82ff7103e385a366e7adda78ab9323b87d50216f3649a8b114eff0a5daba6c926335230c9f63959171202ec42613c2168af5b763a2124e0f8a0b2a28f6f93b216efc062a5f12ab6dd44dad289887385765b73d92de1b592121d60cec67c270917afce414eea803f893aabd627e85f8dbd0178850073deea7ee1a9747ca5c5b632349bd28a64c13fede4bb585a2827794b24a0a8c94c1eed600966e36bccd9e507990098198d7d4430318ead329417f53715b5f58708244da978fe7535c071a60f0940bec100c38b93bbbb83429ca40997671443acc9aea953fe95caa30b5dfc1633f0e77a9a91106ea86defef946159abdc4d2557b526700063a1e06c3205349b5aef122170e0fe85b0e8f1c8bc84c7d367180f548b9f36683f395aab86aec8849993800ee3176dc740d8569613bfbd7742e77254a7219e7ab8d8aac3cdb12b13f76f14cb4e3f88dc8d01b56d63e9c56a309c770bd89892de833bd9cd00fc8daefcfa096f1e8d21a083b1186689caed8a0362307d5f3bfda415124d6e34ce79b4521f2698373cd9cef37c3d68e95cd57244cc5398a7bb3371fbd61775ecf588217d1bf285409c49d2a6e7a5eab15679ee29491ac6f1527faa201aaa3daf62ab06656455d4b88139851f3d8dfd09f93917700536079c21665effe276f81cfd622a21bb3686da61514f240a0a1da8a4ecd3007519d3b7db9202226546ad092da09bf351525fdc5438ea7c96caf9e5fcf7792906d45da395d1dd5a26aa9f53d9c0e10f998b8c712e0e83296a0c8bbc3a2ab7acd5f5ce23d6e9418c39d4d41be3a5974b88a66139556faba0a1247ea404d164945465d953a45e60b5486fe2c76e1d7b374e8ee0f486d5ab48b34590a543cd612cdf4dbeea552b7de434c01842f2d366c32c518ce77a12cd4baa735197427e8ac1e07954c3599624a00add8ee4ead199d6ddbebcbe61c5456ad011f20a839aaa04a6ad0d24316b4db457e232e521821164e8b57969002c740aa388624a61030dcd15f5c809aa064f03b1768f1792c33faf2a8a71cf5745bdc001589542402c8dc0e8e039d9fb813d66101935b24f54478237a2cbcd13d165e910e0b6fe8cadb9d464583368d612b88eb0d908b59a6550bc3e5925e1637cc615befd8dada75936074a58c41f5ce19e1dc96e11613cc94ab42bff4b3792fa23104a10b66b881cc60a67aa703b51db234728394cd7efa9a2d9431ccbd0b3102d72c4c2f896c3385e901a6c84ea60b5b49790a7d838cb89b6d16d00c45229911db6b33225c151af57a57e32bc5583b2da8584c04e9b2cc21b30143960768aab6f3f0018fe2c328cc44f6b7c98d35af2dfbfb31494c2af084fe7e58453a6136689113ed10ac5b447c834f48806d6535a2f8a1a6a7a18f9b988e7c38cc034269960ec29a40615f17fcd00b11ce19f349ee353d50449975391f1ab9a234475a292db9c2731ddf5de30aba8918b03ef043169f4d897991fb9df32dfcd434b027f239cb48dc209840c1982b2ea209e19d514126ccb808fd82b66fbc90f5b5cb10030ae60470b7bfc28e252ff14ab608a2175350aaa4b14db4b81c190adcd522fca9f5aa99305c8379e63cf41775d6220e549437689e178fc7858958db9da3aa48556ccb907b738cb087f5544cea0a098ad3fb0b20546f59a175a2f0fe2e094b85c12b82d9b7019e72a47cc022ad0742d3e0b8e6819954b04f8c453694caf510b44a2c28d88f48d15595026886f624c3c72cf19e9dc34d4f0978213fbe145577787eab3b7ffc7aa503b2b034812904616236e306f804cda9043ddd765d423ae374b1e88af4e1599709f82a35525505f92fcd5233782e5f6ed666082855870e8a1446d4801d8e738b30db829ecc4749557306d4f0719256cc99089fcac993d16eafdbfb8860e465c255f7b19e23a5f07c487ef41f97736b61358d1d5e85727a9a6666aba7501f4a5ff6664250b8beaea1185ec1c53f18c76df101391e8c6f2458fe1ec375fb5728c5b4ce32560447031d2df815004c9facbaf908768f4fd9003d46d0d82543bada364cab773b734e869cb7220f416091e93b6c256be045612ddb8d284999f87409fd2a38854343b81f95758caae8f0a03d49b6c2df6dcd43dccf78c7020b139976910f20419e8f54be29ac25afae9af9500e244bfaf597a537d0d0f04b9aad9e1388ba0ba4e9dffe7259b2e21514d8684760c0a8757d3c3078d709fc3c2533bf9aa39e5adedafed8488b6d43867deaf57273f42c132ebb8e13fce0cdbd3d417c72676bb822993718a488896e38562bd2574ae04a187e49f7b71d9a58e9d90d876bb8c5ffcc6ab1210cbd3a2129f78c9266a107cb5929fc828ed55ad3c5281d8225e898cb7b6e593e0be6c731b98e4f8889c7853f9b6fca5db4cea16c1a9821f749cbea7b219264becaab1b5d9557a09c1158d38db1f09785e0e5af1cbf59f6fd5747f80d6d8da5a3f138566ecf50ab89b939b4e5ae3987ad4e89ad2705fd6532e08cc510da06aaafa9e14d29328e56b00320d81819596f692781d06fe1d854c25d00bc58a6e6970daf612e9c0f352cf92e61a0924a84aaec23ada1c10092ab9bc5c88ccbdb6ce37f50c2039dd9435a101e8548ae90f78b8048989e4854803816977a5a76612056c86ad8d95d0fda3268d397ab2ec71286cb9c1fd66ac0ea3b440db328fe42f49520e9258fdcf713c4263bec872f92a919838b981c7d3296a691072ad99fd195117006e129b02afa1a29b1be68b5e0fd9cb1743fd426140ffbffa904eb01f61bf0404b7c9c465889a4b06e11ab874e539e99149ebca99ed85b6f1848f630b82f7e82c631d481c7d2e5226249507865f74be8b041616a30f011865f57d5f0906574786d046223910f3404f315ceba93ef40f69ccbdcd3d352818ef3d311d1aad8b33e2d74b0bf93e472c70746537b7d3aa0c8bf8039b4897e26a2dc176f157dab1811abec7007cd966c2c70bc08ac1b167b610bab2392f62345a7f69a420fc7f260c1b9d2bf26032ca82e22971549a8e3268cfe4298636e9b077658b36e21bc28ca9f44ee3764090ff3859627aabe75d709614cd401914f7606dd8579d093b7d7b5ee16b930f1056e6471f51cb0842804a098ca7e80bf1ee48a25759001fe9cb796f3c4f83dbc76a8872d3eadd2f1de44d0eebdb0c82b66dac553ff0500184213c1bd3e17233a2685cfda3d838b1d8001eba0a46be31646ac3cf6a6908cebab4ab17bd5e90e309c12a0f9410a299645a4909caa12205b34c36e001fca9573c4fdfd97949fc0acd7e9e5005cd2f4fa6109a979d834ea33ab6ce43d8888df643920c0ac65ebbb6a1dd608c83c74e8789b4d7381fe35b914ecb67db36b5935470f6c1cdcccc7d1bb27e909229bb7636df9426136ab4f623a8d4ad177a076162113f1fd99256f06314daf1afec9e5050847e8b591a4693a27364438bc1442e0330ab09d096968c5ff3814ffb8322246d7164aea80b770f5205db38117de66d141c19faf0c520f907322054233daba06c98f7218893f2e2e0b19d0c8c8610bfbc5c43332d0be2fe390c4a5f34812efc89a31314cce1d56fffa75043bed30dd51af71a8b64af1b37b328f5533db431645b9e1a5038cfff7a2539802833716de0a217e96a9242f5553693c53b6f3894ba7013be6f6380c90346f90bad57bd2a5e5545041a5d0965bfa7df84c36065c836d6e30c44162943a047a7294723ae4f30a022a6119432687dd380502ac6107287dc9e5d5ed6d9a46e4117d933a3cecb4d30e94578df02031e0a2df8d8bd1f0ed6d9c6c1e27a7919347076c0bf95d43e80aeacf248ef9e70bbe08a302183d1f41771add951d44ea451867bbe35891db47946611ca9e90b0870974d3f12c789731b6285423b9f355a65ec1b3dbb25109bc90964f2cb244ece81bb981b8b3a345c863f1f03713734cdfda3c45ac224b35ed631f2dfeedccefd4ced85b9d94cb868fe2542f2aad8ebd9fb1534926a58864a5f903b8bf8cc20b643f00080177c0163c7ce1655e38765fc927300c3b0ef5c792beaf9639908f469826f8706ff90059a87a52ad9411f9a59007064395afd3cc650b7a76f8571084d5b8222680b9f384e850f6654441742e8c620ea7f83956461befcfc25892b5a5b4d6cdd502986abb400d04a25d73fb44527b005b90191c51d839ce3011d946a9a099deb153f9697f97f759b48cc0cef50a8bfbcfdc860db77248e59def8e2e3f2aa4d24b77f36e7cdc994c84e811b1bac4e882db412303724fadf4cf51c612bdd0dd8bbdfe7a7927be4817984fb836422ad6837c72631a32fe2931631261abf69b001c605c3bd0563bf56cb4da23b14763cfc24197f211479a148696f0217e0838b77cfffc8f4b3c63e6d9b4a7f1e42d82428de819b08bc834d3bf0b25d288892d1e763f3abba42ed2f1d0d91563302fcadb1223cb35b4d81c3e7748d7e4913b84b1211b51297790aea41f2a37194b1275df236ffc8c1044dfc6f20d76820748ed19d49eee9b87c3f64f402be873b4a2f5df5e3b5962cf54ab03c151080ef2a9f3ef158a2f9119ccb31a4a447eb1f4e4aad3f190df8ade4e59a79cd0449872611e42a226ebbdc8a3e0dc450ca5d59c61c95154d51e6c4d7276c746aee7bd2eb9c83479ba96a0d7e3d8a1e27e9fe81e87533387ebe2d3b488422bd8a69403cae6a5bc9a9355da1e8a91b4d4b96546f3e555a4475f24186b64d1e29c37e0c352e7acf52dbbae6e936c3f2d230ca8113bf4652869bcac35d2284228e1730dcbb5664152b0cc9c6bc5cce254f4e7e6214622ce5c7bc77637446a0049597e6ed1a8b43d5c3f0cd12f9e97b8c74552af6bb0b63436bee97e110366fda227174395ed05a5d058280dfc7872205304fea6bfd1af094d123fe111990c498d6d1f060bafc290907a5c8afe6064a0a05acf32b1a562e21927b7a2ed455da23cb2bc2b0860a0fd0059d4d700f7eb271df7d4bfc6109667adde0bbd2d599e7edb098c9bfa052cdd8eb57618047886fba00d7da5dbc4a86bdf0cb9f8ae691349c53065f10a336407d942d6f045475dcb386446582ac24cbb5451c0c71cb4c86a42c491594dc97c9ed7fb66cd838c9d900488993567fab7b1d01831e1cb40b1b150d30438bbb67e0df7db78f62eb4104a1b6eb2f4428707adc733b0a24153cec2e45fb97cc3d944096ad7b41dfbbe4c35d408ed8413eb8a0e2ba9d576e31c1d003bb19d2f8eb1f90ab87037033e3abb452cc3340e87990511cc144a78902f115b1a2fcd67e3d0cae0c0447bd2c67a2c82e6d734ba4c8c668976287c1d5972f2c2466076dcb319c528f4df67dbac26f856482a5924c976ddb55cace3efd404a44cca9411ecf8a1e15362050b3ce1afbc526bb221277d69ebf7e23beb42ea7b583c0a503e6439612a70c97d1c38d9515da46af512d2a701ea127344b081c5fe11ab69ac5db46a28a0016422dfb5a95c8eb4c3ce0d9f237d2d6c5f2ef8d17fb87d0f8ddac525c715e01e00008ba142e2d45cea3267c2a1aff5f9b4a874785a20f74fd744d0af2d16ad3c822e5bcd948fb50ade323e68c8f715ca14a9f24217b1a8b8152a9462df43e351753eb37b0f2a8d65937c6da497d5bb2f6191ba8bfdc2c1652c40b8c6c01ac2d6032b40ccb8c3312b0eed86e486eddc228c20cb709c100bbe2568284a942261874541764fac7babb939f6f8681155b9a1d9b531d7080974f203442d35d56531ce2b8d554b227341e1c7968a10e5676675450f1b8975f863450d6d5932bad1a2812da0c8bac3388a7721981d12a51e3ee50a01cc81820673ae7a0babb36a9e714dc3d4a56a62c0988b9fa24632bdd344bd8ebd99dff77295581774fda228e5a3515d07d1dd4722d4539f79e4bbf37f160ac842538a11cdcb08f8582742b19113c460c42efbc3578d4840e4c8876251536ab010fa968d5208d217b073bd187fef2ca0308244eeddff3d9d9862fc71b043dd5c9c3a1238d9717ab0e4af137781412e1354e40d67c6ed728ee78211ec44815c77e75e12bdb3b9f00c2b57c93a4733a5727c11c8e57957eb59453799d12883561bfc937da11836308e6f61674d3e5c0643117be2335172e2e3d871efbeb719df9498f484d705c4f0230c614edf1c39e427cf4c2cdaa8c94b6c84df05d72c2c188e2254852d0b2f260a19d17679902a262cb58d9c1bfdf22e6234d7856e34d6a797968f73551e29a0f41ba63974c2843af00ed7dc668ebe548a96d2954c7f870b2cb22856d46c4b0cdb0840c488e8cdc7b6dfaa8156ddba1f80b80217350c7cd2c11375aa7233c4af3cc0b3128e05196b3a1644011e6daea862a4d2d997b720e3bda24bc9957e2c00e4ce69f58bb8d7f8fcfed12e57fb08af3276f00b2da37a3c933e10218df84423209458df92bf3339d0c469b81c4a462427e810155597a3354ffd617d3d0daf87d3b7028aaeedb8be13140354be352cc56f8b82ca1dab11cc18609633f4ff2d927860b5e7f4ce5051481e4e32bde4f1f5a720cbfe1ac689a26b416f9a80b6be7358ad6170725005549f821bba38f3f0280790b3b1a07d535f0116738ef7f8beb2637304d432ba6dc587320595d84745f8ea47f1301fcdf5014d0716b23333846951616709913b4e9a81629478dd915c7e1a70340d59d73bcc3b9ce08e91c247f20a674bd4410e7624850daa7e96e4e5269e58a6fdec6957f899e4a03f7c6a92fe10fa0c02fda5f4d23c6b1a637f2c291697afc2dcb36b9a37d3ec38683e66670fba934a721be6c1bf72a545accd8985ff5ffcc34c7c1b51cfb9c0b7eec8bd5f3dba38573618245b4f8381283f5c43f02525db84628a66ecba409f4d49da6f5017e4efe7e0ed2b19ddc6cc2117bcb07495df15d1aa494c79ca9d51a139905b2da039bdf7c50a215ca498ee209d228bbe5edb702de419d252959bcf4ac6259154a3ebebcf226087c9e8c9338c5b15c5f28bba23379c226563b39a97886c3aa2e890af47a2df29b4d63fe62965d7384143932d5411da10320f222ab4e40b344939cb7d783a2c6c4c1645282792e4021934401e29768d65ccd83ef49aba0ebfdcb760a8fe5a259fe8b7613ab52ba5e57483c7fb0b6a8113fd607d531a562790ce829ff4d3582e0c896c5b972e883e6df626d4dab802802efe7513047f5200a7705cf899ed5ca448cd973d241f1dc3af578fbe1cc43c3e4031a30308c00bb93927184cb8ba5d0524b698af48b7c30a976a9de912d72e5d719e105e02b6c285bd1d9cb61c34c3d1f8c01d21a0e3ffb4e8ad25cb6d29370fc48275a529288c029d7050db7541fd47743dfe4552f53e41d802e0d257608b34c96ba07c92a90ab59d95db2158b0c859874e87f6575e3ea0838f3584951d39294166abc8774f5d1719dc17005c80f86984d2fdb539004606219e6c31979cec4897e43ff15721276dd62b7e98c7a39259909f047bfed70262dc6c5f83cbbedf367c5e42a55ea03bd58fc54e1bb459c012a53d0ceda892f7acf5bda31463a4101ffad10780cceeba96edddfb64cd55f05c5ec26e584bc201711ac149397a65ac0adf8a5aec8cc9e1bffe9f3486a6ee3adfcc209cc9725552e13e5928bb88eadb62a9851c03b6fec8111dcac363f1e5002250a651811af9740b6745368ab3366c4889b47001416d0943b44a951996c8d3049d46d293da7dde47b32f6741616b5c14aab41ddc4c5c2eede4115930057bf5eaff642ec9e7215410a90a55b6b56850fb915bc0955413bac6d0fbeded854c10aecc337e79d2b5891afbf7b32d040a05b63bb9fadc599c4bdf1e4ec7e55e96647c0cea0b67f0c6f4e21a0657f59aa927599d61899d5830c8ae23aabb988ef89e11b13b80d91baac1ee8b6c81d5a0a47c5208ddbb2b50dea05be277d60e1a15956b26aca3c93e79ec5362c54c0f4c2954220be1aab2418854cf24fdaf96b91cdb65fe45b2b60bab73924c1c9ed66fb465d6e636ed39a12ea33587d51217f9ae3c6bf752662d99936077a0b7408ad2e78162557cc903bae2a3dc54209024a50e9f2705136880fd759e7727158c464f42020130fc2faffbf17a6959c1c08c8c2644374c3547b3d5f24609d329b7b45b7128d50d14b5b28c430887128a6e2529d256fcf362b67b1b244dee2de5de7b079f0d260e8f0ddfdb9ed68705fa6b2d49d74ebf6a29ddfcb56baf176825dd94e376343259e4a3913eb06646e557af5f73582ecb6833dfb39a0832f3e9ecc901139111254d2a301471cfc867f23d27b3d2fa5b79cfcb5fb39404b2ceaf59267e65d55a7867a33aeeac1bddaf3c6702ec13fa2a0812024d6e495dcdc567df59e5cf0e8e11b31b5b4d5a716795fef99d6d3a00529484ddda979788b8b3cb25df59a6d36b6e2d33002b64007688cd79796777581ed6e7d7a004c4ad4dec8d0a5ac418e194044c8a52ace4fbba34c11189b524308c040112f79569268018257c808e2879a2c47d0dfbb2efeb13aa566575f3b0327908f2ebcafb5ab4b2353720d64c7005c11af26c92ad6b1c4e4e94efebceaf2bcfaf18d4acc7b0f5abdac4c65d75fabcaacde76b8a860445d34fd891acb878ec7b1a1d2372e247ca975412a458ecbbdab3066513acfc8592aa6defa68d73bcf212985862b2e116fd3ad213af61bf7298bd61658011b92bc2c952c66b925f4338692d77f804a9aa9114af60bf72e3baf25e92bd59a31bb80e0ab5aed15a6bada3ec98d80dc1742dda046bda39350ac60cb9f72854877caf20c438ef7ef8432e1cf20ec3a15e6aad7508afa5d22b9d96a169ae3fd000d020b48f1aa416598179b82271c5e335e757545ef322d6d46b6e0401f43aabf9e4c6ebacace86b2e02a8d71c055a4c5e731b8cc001f27a0bfa9aab3dcee46ba78fd7bc8d7b8f3ae3c05931aa50213b647162d8282103894487f22b0be881e905c28ae74d3864b5d65a87e8713666a5ec7aa2ac126bafd7413aafb590d7709fb046c813b0f26244f9e17098c51cfa216fdddee3506833cc42adf50e6c341933222369a529d6485e03ad78ad6d6a725fe3de0de242ad35af09ba416b5175932e32e8265d64969363b237e97038a4bafaa1cb0f87544a7e58c554850b3710a518ceac71abdb069bb6f7a89d4ba4170a79cbf61e8543e1506b55d51cd64275afb5b0c646187d8fda7964c90f791ef296ca7b1c46b34dce7943ce3539e78cb5f523cbe42ccc99ab3d6639e7ace6615673d6f2c912724feec939e79c6524cbe4bc61269fb98b8bdc30e56d6c783be53ddad8d8f076ed3dda68197d4d0d6fd5de634d4d0d6fa5bcc71a28b4ec8542de46798f42a190b769ef519885f3c3216fa1ef71380401ca7b1c62358b5e6bde3ed16baf79eba4457b8f59d34802ac6912870026406dbf33af1f0e79fb7c8fc3a10defe9b2264db24306180c3531a2a5ae38242d364b6a78abe43dd65c0df9e190b766ef7138ac8911f6130a73d9d5891f0e794bf61e87355c1dce255b6a8463ef7188650525c663d92412171bee1bda0cb50b15a7d7fa2c6c38ac3900139b9c5953b9638c2bb9031edaa8354138e921d87787608739043b906f70954c2a3e6d129e93c88144229148241289c44c2412894422919873ce39e79c73cebc057b8f397fb130f27a8f1a49d77b24b22c11d6e7cc7d442191a85588ddf4acf0e20212893da59ed65a6badb5d6422271c85be77b1ce69cf356ce52cd136539e79c62cae74cf499b75bef3113b54a5423084fd4782291b75aef91a8892a8c9f96e150186cb3a44ee43c91c8dbe67b240a55a25aa64624f4e36845d05a9c57e767df9028b5037dad798bf51ef50e71f883c6415c3dc9213dd18a98738663f1e37467761764eb0a9108352db34a7503415583340ed914396972c9b4bab3245a9f5f3859dd6d8da928cba282a42014d6b45343bea60458a5d8a610a2f410b98024595b328cb0cacad66653a8aa504f712d884f9ac8b2e91299bcc204888f1f683b806049a1200c7616172b42c4e05cbce630dc942590a8d7b5033046fcf8727115656ebd62baf021f71167d6b899d58d483c6284e5e9adc98a4f1198484452b98087412722704f24f276c87b240e53a5302947d388e619518b382b1bb0d6425637222134e955af295c63450b7138dcaae213f654452dc87098752ec259e90d3991fb86c4e1b0a60522e42dd37b149a5d6003b3c0167d6acb7acddba5a11ed62085550860ba38b3ebc1f34308732e86ab75cd8ff79885bcf5f11e856c4f3f1cf2b68716aa43305886c1f6896d28c8238ebd51a19bb8b770efbdeebcd7bdc17684bdf7de43be372f76d87bc516069b5f424f24f276c72612799bf41e894aa5178ca657db67de22bdc70cc34ca40e98489be33dea216f71bcc761abdc4420226f261e3591b4f8bde1376f6fbcc7bd9131aa5888c43c34eaaafabd795bf41ef75e5718689bc87d7b666675dbbbb5c1c295f4d535e2356f89e02d1ceeb7c7055d8c1f664f685575615a48ccc31aef31b749ae1716869cec4d2fb9f46eeaba2e4f5d1e247782ebbaacebb2ae4bc36d715da1cb3b1863dc66930b97c5755d9eba7cc33fefbadc451283fb376f69bcc7bd85bf792bf41eb70acd416a8410c4ec336f8380ed0c205aaf79d6bc95f11e75f61103f91e5dcd12d9b8283959502a215370a8e4705c228c16489b3599985e0331f19ab73fc05449fcc01387d9dbda13b8a9a9cfb9ce4849e4adcf7b24b62c91683697b65ef3f645d65a6bad75128a4f2a0b7bf830d1f411d6fc81f499b72e5ca2ce6a5655640da41662765b347bdc78ad79dbb314166978076e8ca169f208d1f86868686868686868aa964f434343036d59e876456ea6e8f139f35645cbd3a6788f343459c31a56bae9968fa62545603dcab6a4de5ef30f728ba23df11edd2721e4b0dc21a74dafb42c454bd5523a13534d9da68f6689299fb991ea73d344db557307ae7902eb3347818dcffc054d14739f79bbf31eb38b646f549c5689bd51a14aaf726130180c06834135180c06831ca6fb603018e45866265e6bde9a788f5ab725b644609525f1785e68e5c06973de636e49bcc7a0eaaaca9cb30c1a2db91d4196f6aecb5b11dad539a7411a241111d68285d84ed41c9ba66971eed0e09eb0c69ab0c882ec5c371d936bf2ed3a3a154b4c49852b499d7455e5d24f6bade79428df75b996d3db4d80d1d3082a646d4d2b28284d30c7b95cc3bd4757498e95ddf6b43d5999952a7003720676a6947514e7a7ae24b20d06b3a02e7421bddeea8a222982e4eecd5d957b078305c83a6e2b97ce6b2eb02aeb9a5659a15624d4c24a0fa9659c84363627112793a8ab5d9546e5c135840ba9b6a2241e2725ce2325e07a127901f5e07125ce463e3fb5d69aca7bcc41aea7ac5b736b6baa14122161cb68b9e5440d6e71522405968aac50a9d2c34656c40485d54d4a94f7b8b3ec7ad25c9aad64cecc17d49a0050154a56ddd2bb2ed74f34329802a5e813164f35aa984e753f7bbb6ea671f21e73906bb4f718ccba724687822e4913a01bb4830293ac2b35de3d0b22c59c6f3945d2ec8aacc4598d467207734e95cff798c93864c9b5ed19afe7ac2c014675de280892234d475b53a989481d899f12b3f7b807b08100641da0b041b15e7338e73507ee78cd791af4352f46892a33baeeba2a836e8b675052f389912543c25c976cec3d069facbdd67c43418ac16ecef9e84e486bad735812fdbe3a2ec8755d57837de90b298b974cb3ec738ac664a9494f931fad26666845684a394e889cbc7de61b78f2e23317c113245e50d7d599cd3968838e478c6847d991382157d858b6ebaaaa46d2657696c3c359122e56396617e7f42979d278fd6c6eb934ae5cd85a3a6b37a8d3ae2b3c7bd364bd47dd7c8fc17c41d841c95c99d612302cba1319aeacc8becaa694995dbde6b0122326706f56b3637545dcbd334db0bb4910aa3215981eb313d3224ba25596f49aeba934a74da290b44579253d4936d9f8cc3f70b5ce5259b76d8adc6919db53902173229a6a6b901fa51ed0185c56435120459ff90734aeaa12204ad550daa885af3b8839c5ee5e73201fe3f1647c3e5fe735afc82027aeebaae992454b674c4b6bc96bae8f0c8db918c16a51e35d97eb22ae6691551220ca11e76206514f14939db3e7baaeab9d34119dc5e2492bcb39c475b3d61a096b0baf85bc472dc1178555b68448b3d9a4b5d6ba86883788ef82f0eac5868157629f39c7ba01a498b54ffb94baaeee852904104a3ec8b9997a4d41a16ad2a272ab4262a2d062423ff3043420f30940a5616debbe404922ca13e58c478e253ba1093f7c68251a83ee10f5a4ecb596827a3d957cada78abce6bac77bd44ea79bd59c836362725724c059d54a3cde63502b6ac4bb2ed73b5c570d6a5ebc0b7b5de1b54e52853204600a60b9fcfc74e22949eb090b4a470b2a0bc95555a5ab4415a4f97397220dc5fa238a266b1d59e7d05af27c8063a99759bbba4acec60a2ad12958347cd4f87ad1ca9ce4fde06d096605c8ca9a95b9cfdc08e77504c2dd1b8691961b79899210b2d8e298596dcb1359559a64b94165bd253f736da4a44183060d1a34a81ab686cc7591b6f11e35b8486516621187434e4ad3892ae2eea9a712b5359a17768c0977d8f148725555916f579ae49c4118ca2d8d1d3d5a48e79c736a02143a6e8439a9d1e2488fb83317554506bdc73c438b69a42045a425af3930a949065795b232e7233b9618592375b4bde659730d23671a554004a0c9c1044c47d34fce39d71892697048799de3c80b6258d8d89a13b39e3ba53a33a08b1619c0c8401c9df8ccf3d65193cfca11ca301c3f7a78419ed65a6b0d0134b61a563f3584ce62cde3b5d65ab35861b644ec458a48cd8657510fa31ea3b4cfdcb86574f779eb46d867ae55bcc72cb7a285678b68eab5e61b4e01545266b9b0cf1945b2ecaac68d1a77afb93e9175ab27307442acc759142062eb8e2125bdf32c005ad75710744b0808d0160daead21a6dfd2265410d89c2e74243179b558935ab0bc4ce95297e872b1eb9ae17ccde120221d60de1130a233a56cc695b7ae15c94e08cb1a71b7e1fa6eb34c81130a671064174e8cb8db38bfdb38c36ccab6707cb779daa0a5d918a5d91cd9f0d8f8d804fd6a53a4f4406793f32bf7b0646f5a50e307d9561dd20d2ddefaee81099306a539e58992e55cdc3d687df700dd8af1dd43d483db130f459e7838e2a1c8039287a5b6ef1e9c7ef580ec1e92cfa8079c1d1e17df3df478f069d2e1ab4987241d9c7ee51d961da43a34a3df3b78fdda41e9d70e4dbf720e51f6268d5e81010764c6758723ceface216e47e8c74f0e2442e08ee2dea1f9bd033259a4e27b076507a42787b527072a1cbc389471406bf29d83daaf1c98bf3a7fe51c76d89bb5a829ce0aeb04130eacef1c9e5a543098537ec4883b07e45f7de790d4d9d1e4126a72c4622cee1cacbe73506ae2e0b495f39dc392839419071db35779e760e2d70d6abf6e886e70a3b3facea16f78feba01fa2bdf90646f2c40e3476a87058a660f96f97d8332c4092c1a76502b2daa1971dfa0c4567ddfd0a4d60576046cf9222aee1ba8be6f603a37786d08db5096b541286b68434edfb0c3b3c1a76f0872c6fdba01e7575ed3c4dea44f6ad080631b027222c553df6b96364757a24077d40df98a7b0df3a5bed738616044ad8e3963c9d732ee3551df6b9ed01a35ad2adf6ba2356e456a988ad404a909aa49d614d5f49aa57659d3d36b90bff2a293bd615124bb925d558c2063a8efc5b0ab215c35cc9238a0c0887bf1f94fdf8baa942833e6a8c8d8f123eec5e5f7621c4eceafbcd7ecd4f0b449c5ac36a9b8555cfab5d854742a4afdcad35e6c8b6d51e9574e84b23720300ac2d38206598ab3983df29d1805e2c2892ec9d2dc32ee4423df8b3800a04b128243869d0da3b8178b7c2ff620839c7c2f268b452dd1494b84426c12bd886508f84e446b89cb96c8fc951371d81b15ccc50945b9a36222c54edf893b44640986e0989c84a0fc84c59d48e43b51a9445c2236119d5a1575ad8a3b0d686a6ebf6aa0ebd110d6f3fc956b40b2372e33ecc076e8c268e088877cd790fc6d41d901b6c32dcb2bee1a9442be6b5002ce280143c89619ce57dc35347dd7b0646a68627dd7e0d4e055a7e1a74e038c219d861c0d3c06f8aec1a7c519465b9c61dcb069c81c863dd17e1d427f1daaad0d93d6863c863ec3a0615108df8748d1e14e1ff6fcca854cf62695cb6a3274b6e543220ef25de8fc508743896487ae845bdc85610fe4bb1086149f1b4ae694d8e2e22e64fa2e8c0ae384744ddf8738c31c33e19499b04a88245c123a15e0bb50ea294c0a95bf729a277b1382e76c280e0994c7522a5efa4e03a5c153101b9d92ae2332e24e13fdf19d26ae01657177443c4f4ad4e22ef4f15db8d323f461fa2e440a83b268ccb26896d048d13469bc08f09da6cc49d38443d3439354d22069f9f84ea344b35424f8562408172c0ba2a90de07bd06d19742ec37ee5c11ef626659ba17cd24545841b55dce37b10a90c362da58ebe0799c166525045d2abbc0759fc3ae3f6eb4cdc0c5d30e7d7208fd20c54696646c9dec080476eab0b8dc60c2ea5ef332ce811b4240245460917719fe1f17d2665d349c31ac1c3c34922ee333bbecf38c3facc73064d0bcd1869a199a3199e199f99a09bef33453a3983d3677698611c1ae56e3c8ed36915bc8856c18ff0228ec49740f8ce9d7a38b227f92bcf10c6de70406808902a493b7434e3a4ef199e19a2bfe67871d5f4f1c3a42dee1990be739c1d9e15df790ff7a9cbf0953324c9e094412a435300df3378e90c4a3a43d3af5c26cade84d061244a5d130869c22866757c978983fb3a23726745168d7b069ccff13dc30e13aa1d28b882105d99887b061cdf332093198a32283320adadad5191f192299341fbe0bb8c5a54861975feca6576d89b102d4a503939a38060b8507e97e949ca2835397599a58c543693d1c966322630a86170c3401780ef32394f0ccf27f4578e21c9de50a0a2239aaa7245457cf41d831243130a8c38695392319539e38e6179e33b06a6d32bed3b86300c65631884f21886210c39a91303cfaf187c302001f01d43908bbce056c3fb05baa5f3c253ecfb05e80d1cf70b6a531798a62e04b910f4eb85e485a20b481ebe5f58625ee859798c93bdf941f972a2bdbd91788b097b71e4966465c98ce28a7bcc33063ac16bc96dc9a7e82e47dc63a231713839bff27e61e7d70b3c4c31594c5bbfc62cfd1ad3e48b7b8c538cd4af31cddc14a3ec314abf720b50f626448a1ea09c2a3c51a00c31fa6e21bae168ee499527c8a9b7b85b882bfa1e83d364d75642672dcc088cb8c7ecd8f81ed3838c09ca5a7e8f49c6141959706204c542f3570b4e0b5e16ca84df2da0650bcb6c8149c38259e40a90ae1f6344df2dec40730ca9eb91c3cbc849dc2df4d4f86e0119820412890e9194312124e26e2199fc6e41a9d42d345970ca3f15eaf24f85bb0a6833bc57805650732b7eaf4087ac10867cfeca2b20d99b103fa858213205c98cac23f1d0f70a74388ca03aae4a98d1c5bd8292c6f70a4a6f5871d1276344b0a2e25ea1e985be5758327b05e7af15bc7eadf093756000e97ead805321a7020fcdf70a3e790718cd3b4aec0d0d943776441189e6e88883be039b7e5d6bd3724e89b0411577e0f2677c0732532f1952804431d276c32bee40a78cefc0b02710ad03a14035f60d98c4be0179007d8041c0a25f814871c09d0eecf995c330d91b0b14e14a6a9b52dafa89637c877112492942ba1091838451dc61c290df619e37885272b6f374538ec51d06fa30bec34461e2e89abe037180394e60a69cc054c120c9f00ea304b304e394e13b8c141426c9c2287fe52f4ff646c25318129411d75251cc027d7fd99281c5e4c5d65c9267dc5fa2fff3fd25c4511b138d222e9453717187f1f90eb3d303e303838409fa7a31fb7a59f222f5eb0bf3a5f9e225f3fda52ceca589421c7bd380280ba1b327413884c42fbebf5841cb19733a13f3318afbcbcebbf8fe328020ada437183372f0c4fda5c5f797a412e9579ef617a597a5a9b729380a659c770a4f0a6814d4307ca7e0c6a4e06486fdca29f4b037216c34e958e6a8d3e159f67ca780b4c11534850a203a888ee24e21c9e23b05650a562662c5db32aa2828ee1494567ca7d0b494e2f19d0293429365a2a08265a2c0c2c52d03ef2e712e7414722e7ca7c0d3e4027589b2373a4863e2a20459108cab58c57717250f539c388d1883d1e4197797a6e7f9eeb2dc0155e48755092b19397177617e8aef2ece3097b2eef27441337231323a72e1f99577971e1f97a098ef2e45ac0b0eebb2f32b9fb0646f288cf140bb7a02b2e2448ce2fb04e6cf1042a7e624874856dc2738c348c0c40946960b183d4c719fb0f37d02343ac1ede8fb84b809743f138afc1c9950f4eb04252fee1390262c59f83ec189454e40feca4e48feca7f61ec4deaf505a3884aea8d4846cc9af8fe7b3a3d7786a243383c70c4fd07fd12df7fd1a8dd11940a2b51263ee2fe8bd3f93e016787e727f44cf061757e5fac4e929fd3afbf651bf79fd4af59e1fbcf8bddf929f55fd3af5c4294bd09d102ee696528c896ce539cf35d429c180eb6145052a488e2fec321f1fdb7a3031a4484be56d05d19c5fdd7f323beff90c95fd14ff9435a5b5ba322c1eb57096112ca24a001bf4b505ba312a46cb8841df6266532f9e84072ad1161c622be4be8f975ce4e286d4ce94689b84b403e8bf35d42325dc264068e13514e28b2e22e4179f75d8212f2bb8426094eab99049dd54c820958edd70e476137ba09df25e43ce1279c646f62462cc1e13564c9d623b6fb0eff109a42e56a6a06122aee70dd77d86955865c438a1104177798ee3bcc747afdca53b82c0b16ca1a8273e01d37ee300fecf3fb0e0739e3609c5f798426f6266da275640d49da0f27a3f8caf70870528020cd7d55a97211f70873df23e040489b95ae1d534a92718f20f73dc2131a41adab08dcf708d1086e6b91084c6b910841220445288a8024e17b84a565849e1e01f92b6f71b237a916108ce472ad0af447dcf796b01aa42da5512912a4458eb8b73ce1beb740a1624d7e849db539e1897b8b95ef2d713839bff21e61e7d7083c492d59495b2d4bbfb634b538b548c1df5b9aab528bb2b728fdca5f287b4303b133263548f4b0e28cdfbebfd1a611d1afa715d34adcdf38b7ef2d38ed9153d5db5559588ab8b754f9ded2830c7afbde92fcb5a548e87522f442799b31bcbfced7eb2d8bf0fd454bbecbe4cbfc95bf38ec4d9a66430551db931f712fde9da19ddd1b141e4a4149717f7b5ea403aa603da77e642487e2fe265fa5d2d2fb3aad2a58ea561577bfa2fdca026551736bf9ce42d7c312d6c3f2fc95b320d99b946943445490ac3817686ddf59924eaa9e675d6e3d521c893b8b92ed3b8b52881a5b45a2577eecf0008b3b4b53f43bcb92c9d22cfbcee264f1aa63f9a97b95771618bffae87867c161893b4b0e0bcffb9dc5e7579eaa2b8e127b1342a9870da616289e48bc51f9ee6b82222249465b89a710acb8fb9653befb987663497420d9b1669722ee3ee7da775fd8d387d644f2dd07f5a939f125a94e7c3c7c3ebe205f11cb771f1274adf1f1389fbde8afbcf7e23eee3dbaafded4d7abbcf7aa7a48bda7d45bea39fdca7b4f2aac974c9f00bd51318272f5e416ab7de7412908bd612179bae9b88b3b2f2ae53b2feed76454d4468e2039b5b8f7703ecaf7de4e4fcfc788dbf71eb21734c5339b5ac293fa95c75ce3ce6bf2bc7ee595fdcae435ed38f6660750749e424a5f3f6871da779e958da01d4facb00111c59d07fdce93c224c7634e8ccbc85bdc79c887f29d9754f290784abc25a6fdc6b4e176d946db6afbfb766bdacea61ef6268411273e6f6c5d4378e0889ffc138b2947ee58e8b8c57d27dfc9f78d24c24a0f265542aceee2be95d0beefa6e596daccdd34da2a54a3cdc27573e976ceaf6cdf378fd2852a957e5d9d61654adfdda78ba6aa708d5415ee91cbe3fab841c1ef6e51cf5aa3f2ded2e530c3a037beb7d19b5edc5b371db445eada236d518bd42efdca5b95abed0ac3aec9b433058b29ee1afa4dbeeb688bb3d3f2346904cb679f6b11525f959e659d9ee5eb1269f42c4ffb2af56c73753ebb963dcba660d59e6559d8cee63ccbf2b03dcfb2483639e3d9ce163dcb22293dbb843e9b82659bacf359ceb29c8694b02edd3042501e060606867318186e8459b9606820c100616060666084e67e6686bb74ef714648c9bdf21ef9dc7b8491c14e10271012698491f8f7220805cc1aff7891bdc9f18f1bd99b0e3cbda83c39fd3051945d7c0781d6e2b7c63d758a20e8edf74be97076b884767ec15f1c0c3e293f18e4aedc7b0ccecc748dfdfc4c1ce79c73ce39d0857b8f9c4391c2c20425611f86035d2bef11e6ed3dfe827afe05f12f77dddee31b44e261ee02f30b2b083f0e730e83e46160b85be53dc2a846a44af8b86deff1c7f61ee119429e8585bbd1fd2263e95f7ee21798bf445f5edc7f61029563e5028d8d0894f8a505d78c1b2ffc05868571791819560f032383cac37097ca7b84e17c73678bb2e753a02274f80069642a06891853ff8be1f53f5e34cac059034125096ec8d37976642586f98691431e86b9abf61e6129e9d3ebc2cbf054c5cbc8c87038c7cb70c1b07b19ee46798f32216640670811c96246a3b12f95f2be293beff3c53e9fefc77d3e5ef53f9e7fdc4d7b8f3fa811c8c5176dbec85d28efb1f82b428496c2c74e139338f7b490f239c359c5ca2e70e40999bb58cb6f9ec96aae10855215d13939a311e7cc22bfe0cabdbccae435a76d2acac268e818427424ce2bf2cfa74673ce79e5f99cf3cefce5e5e5e5e5e5e5e5e5e5e5e5e5e5e585bb4fdee38b0a9fcfb701850f2b22e2962889c43e9ef7f97c3db42d3bb819564e8e621f779dbc475f54941454d40feaf7c1eff723fbdfeff7e3451afffbfd7c9efffb09fadf8f92ff7117ed3dfe52c0f00dc3a506f430303e331ebb3434194839310c779bbc47181817732f23f3620813d885d3cfcc70f7ec3dcec43de7dc7dbe47de82f930ccdd25ef1156628cea357b03e8f552a91523962ba056b4b108c262ee7bdc48f53d0ea2e7ee7bdc357b8f3df626022e9624731c893e7dc5bce77198ee7913621e8f0b793c6ee4f15e78a9f3b73360c5c6d5c404d2018b533c2f8807c353ca3e1e77538b9ea7223d8fe7e3f1b80a2d0d65522a5890a18081818181818109f13385094e1429a626576218ee8ebd4798dfeff7fbfd7ebfdfeff7fbfd7e3fee8abdc71f8a082140b2a20a8fa0116e5df14b3ef12f3f1bb2265a40a6a01451c52fdc0d33f67ac2ef754021e37b3d1469dfe33050e97b5c29eabec7c5d3fc1e7793bcc71ed87be455f90c19b8fbf51e3388558143ee88e18347ac775e73f8e83577d13e6e646f6492aabc86c288100131f11d040933dda2b596d11a073c6a518a8e86ccb012eb123a43f40addd31a46f7ecd8d03cfa45eb9fd60c40a144438c46d0cf8f58e70490e6e9ae3e5f67ed6a047cf8608707d70e15ae133b3277bd328956f3f8e65db5853d8fc7813c6ee47117c97be4fd5cfe77e17f3cedc2fff154eb7f06f8df8fc329fec75502caffb84c40fd8fbb5dc59cf3c25585e845bf986047170e09331240a6e2974ce25fb87498fff272b3a3a335058a16988bf885bb5ceff1e53bcbc3f094c5c3f0cc9593f630dc75be4798cebfc7d3b8efc5ef75f81e4f7b52bed7e3c01e77b78c3c5e4686bb5aef5126a8c29b8b44cefb7cdccd7a8fbe66f4cb9ec89fc85dacf748dc7c6f0eeffc7ee3bd7b28d87272a2e4c999905abcf3881d17b5dfbdf7cbde33524feee4b09c4819c53b8bd874643b69f3b6de7b8770c454c4cad10a287731cee6e97207eddf56da79fb76be20fc2084a8ba1da8baab137657772a9c775c3f5c384964708958c23582e83377af54155673732c3fbe7f582bacfef72342040a179d0f1648f18fbb56c60320403fe90e21c4397d5e7358aeeb3507b678cdf95cd76b5e84f1da7945ecb5934ec66bee32dfa366efa25ed04548a376be8ce8b0c8f9f183b58bf299f14b9b24c6823c65ac788256c5fdfccb0b77a9dee30b5cd5d3942bf51e371c89a7a1e16ed47ba469f96eafd87c7cdb8bdb76c50e5306109da6ad1971dd7710684cbea7a954eb6bd99667e208ae4e2ecea92a6e59baf6c98af6d712dbb50dd193020512e455159a53dc5e69a13dda18ad6edbdcead617058859d191288a9fb9ef6a94b6ef2a57bdbe2d9369d9b695f2f57dc541b6bc7644aba16d5b35b3efab124cdcd7a5d5e9db166e5bbe3ad7b037af7645fbadd15e4e9d68407c9cd25aece0c87d6777a6a47d677b5a36884d16d79826a11d26ab261c497154ba5a568a6daa366a67a1d11edfd9284bf72d4f37b4ec8d5187ce1c931135197170df33926dc8f79ca411f75cf46d46e24adff2766d795eb2373b20c16694c488738a8a95ef99c976f73d3bb357cf65f9d981f70c6dd32d288e2537a86c40dd60dfbee7b83626adced13c3e1e78d7481df42d5107495372278b0ecaedbb565659fbae9578e2ae97bed54e46bdfc56339bdf72ed6c75989b90effa2923ee1aed5bada6a3dfea384df72d6f715a9ef676e72dc7f7b68742dc5b9fa06fd9b655b62350238a3a428464c95095ef6dd3d1f776c97b2bf56ddbfcd6d83adbb0b62c95e3696b3382a56247595b8b65e2d9eeb6a5cb31f2eeeef07ccbdd1ef6e6046043538894526d3f71cbf6dd45aa7d77933770778bbe7591be759578779b5ca76fb991f7c003ee42bd470f822abc6362aca4847d4c0c779fde634c5085814e2bc9371ab9bb7c8fc6a00a6f1a9ab7234f73f6343434dc3d028481818181818181e1ae91f70813546163d0e9862418e46e11e0cc0caf22f733333333dc7502a62f706cdf8bffd2e15fb4aaa43545ed962fe297e8bf1881fecb0b07b237e9d20997960924766449e217ee12798f2f9cb7459fdf3ce7558e9e7377c87be4162c58b0c05d21efd182b30de83d78e06ed37bf410f61d3a7037c87bec20816f0951742f81bbb840dea304968f102df21122b0017d04ee32bdc708411586dff77db9bbf41e5f26bf81e70ddcfdf11e37b0f0cdd21c81f32c2cdcf5f11e59a898781b9e6db8dbe33dda04557817b973cdea8b3c17a724bfc85da5f758cc90214306eef2788f197abd0bdf5373db3d0ef738b0c7dd1dfcf7fbfd7ebfdf8fbb49eff107c37ced611856c3f1307791de232ca5e73568e0ae8ebddae04939c173793c1e8fc7813ceee6788f3c969771791928dbcbc8a461bd4c14e5cb7017c77b9409dbd0ab4ddc7befcd819bbb4a23085c1abe0b9fe4188392e38432c4094df199bb54bef327c9efc5d77a0cab841c7f6a0a35d7669c88116beede788f7a0baded8944a793234fe4aed17b24fa5cdec7ebdec7b3cfd904ec7d683bdec7dda2f7e86372f6c321776db844ee924990e7c081bb35de23870a7c5760a2fc0a15f88515849657e0bc42850adccae7f798dbb66db93bf41e5b1aefb1c2998aafe1b986bb42efb1a60223c498fc0ce9616124064e792087e51ec85dd61b230e0e8e4f0ce4175610320772cedea83d3838382462de03c5b89064686bbea7526616cc9a7ccb814a9cbee55cc5b7bcf8fcd6b9c4f9747ecbdda0b473b3aaae65566fc84733cd4e065cf3c61ad511113073a33bc395f11e81654b5ec8b390bb31dea330040f8db81647aa4cec9c885db577393cf62e77596f60975f58babcd8811ba57c0741226eaa3c35c49011a61376519cb425895d368a4b06755fb8db757fae9b01b0a7d90e2a2c9858c46e9ab3ccc9225691de1d11f3ae36a957bed7e32ef23df63a7fdaf1bd9873ce9903337761bcc79cc6f81fcf3fee026d1628c58076e4704597c41bfa9bacc5effd9bbb3fef718fa53d8fc75d9ff7c89b20a624464c6eacea85037ea604993241846248aca1887dbdd6dc75e1b6788fae988abfc0f305eef6bcc70b665fc91c2248211a35620a4f9e02879f9e0277a140c1e51428cc81f91015d1e0d28a8a29b04e2884f5507841415358b6f9497723218e7b4ac7660a3ce7301b9f7358f3337759bcc7fcd482597ddbb6606ddf26f9f12d77576ccd5d5c15ef513bc168bceb7297e73dba29de2385aec78081bb28de230617be5d38fce45db8cb7ae3c62efcc27ab363170d22858ab8a752efd24c9dae0b14ca85ee5dba8ab355e717d23df11ef70a8af078d148a203499038a37dde6af199bbb83bef31b7bdeb72d7c47b74d91b0534d9001236c48887abc9b71c5efbb6e56e09a71794abf31eb59bf31e5d5c12ef91f54d9861f906bef87b2d4e68e16d2f76f5730b4fe1f6c38cabfc1044f1a3cb8c6df92386c464073822065247a8349b9688b8ceb47c224204119be17334f493a2c8b34b4bccc521800b152c80e4b002855ca2769746d5450df1d458ab1a53a2e583c5ce035456712e7e08958930cb9a6ba9eb33b96d92a911594a8ef82a33f2305d0ab7dc55ca2c0fba4a128ce09425fb9dbac10eeb60076a253f073b8f40a50475854854494fdc72e10ac2ef5bde5e798f6dfa6f1e4cbd7950e50192074b1e38fdea41f720f9ab07ca5fb9f1c9dea456d6c098c8d47c7888c4ecd87723548d0a5709e8908a2671378a7d3722e98692be9440c81271f720ecbb073b3d3e61df3d407a10d4b619cdda36e312a3d4af46a6b169f4b2fb6e2cfbd5d8f4ab318ebd49d5c4a67cdc68d1a4089438c977230e061823a474356dcc008bbb9105fb6eaccac249529634a2361477e3d77763526944daa2fa6e54322e51f9f046e503dc87b20f681fd4e8be7f70fbf583f3d70f61bff20f3dec4d88176735b2bc7640ed4c89bdbe7fc0918296ed18e3827222ee1f907cffa0fcd0b49402f2fd03f34353ed830ab55779ffc0c2c6cd26ce86ee43ce95ef1f78a236d05fa3bf721b257b93c219f932f2f161273514777db741b2a44a520c2a40c819014f5522749c493b969ca4169fab4384980bab2487059c0a3e2c9d38a06f448c1f3b05eb10a1e05b8b9050462011a485c417069c27210e0d1a364a0c89b60aac88b517b76e827b67341413b23c17123dc0222c5a9e1d5d059e0f1696f7410e263e4b48701d39b1a5a3e312e30765c604dc8af1f172520445f0084740c1e09ca0a03582c40b0bb5a4ec5d97857aeeb01b3ecdb2eb7a099f66d93d7d6011a3b2607d48ac86bba1274d7e7a38698a5dad243e5e6017a0844fb992d4f819567c565f17f6a6fbddfbcd7d205c5e15d30b06ecf2b8553f7caeabab8e5884aa8444e08222f97c4f266efcfbe91395db12b8a2225b612274a2b2907c9a8e10e1718735d4945b75f253855527750392d52a3839a782509bb431c12573a3924f2d8f8d65c2db736d0e83da729635c0f7eea75143673d1cbe2b34bc7860fd44f9c062510323c20d5663b918f156a158e351f814ab85d9fb3ec56a01e73e2b6084045c551191b11a5752d25a2954842f328c08ee0d96cce5b920a478545270befd944a0ad986c6a85bbbab6f6d7b276e3c8fc7e3f15cd7755d1eef040fdede7bc33d8fbbf078bcbdf73ec189322463543c66acb07abac09be1db7befedba9c3f171637dfdb3d31c405e8f24ef0fcfb2973e78ec74ca79e39cfa086985c569216725f644078644768c898f078eee66d14acb0d2d3246352b1c5249392c9a8bc80e0953dabc866fcfeb48aecc51d93b32a415064d5508255ad2b02a404012201c5e4ac2a56a9b48d211c215369cbb02956468b36ab3531a52d29b80d7429c3b492f88031224765a9b823a217d1273928b820f727ae8b655d2b9ed414927d03b2e1baae0bd4e47399403f26e8b9927b2af9217105540228c71832841195261b45567432709ef29206035b4d39293c3e68d0a55380b2e6cc4e88c91872e4c7930b1b4c5654d18266230780c216c4c8dbd3d2552eb2ae583e5b6d755132a27664a7efc0753dae69d1c5801146e40c09f3d2dd4aa8a2d5b65454e7e22e7689f818c950336e08163180a85668452511cb439af4d610c069bc205eeb2a1765cff269958f0ba622cbaa46238f0c2486e582f2bcfb2917d4284bf894f75aaf5cebac733066022a97f0ea27600db1aa31d856a8d45e64d7858a41c69bd28143bb9b4aca198fb965e3f7a7ccad1937d4a8a12a6e736e876ee16e85d79f36e77a86522cb519774a8e9025bbb290103c8404b1b30af2a3c324376d80b75dd7757d452d3c5eba5da65b325f1dad68a9a25bbbba61e7db5b33cf96bcdcc704787563c9eb4faf8e4eb83c8c5a6d7dbcb0dcbbfbed6b5bdec7c09ad25a97ea6797e4eb090e085deae5d5c4f15ee94232d6160356e7d2ad2e276f3a0a67715d69926271a998728567c5740e4da9b299e9d4968fb529ba8a85d26246e151a547b2c6a6842100766a42dbde030cc1b2d2d694430882a5228d892dc0d2951174003dac98348854898915850584a4aa313601e8a082fa3e8059e5545c34ed0d40ca1e4d95687bf12095e20aab21358ab201cd4222a821696f311d7a62b6d1c0414bb2b5cd631c99b29601063a22624dcba42f8cc088c28387a1a7088e291752154e458e626014449c164c0c41db1560364708dc9a0b4c59114252a8b51360bba6a494fd4baf04f9b13641421c1022716f309cbe3151bd35f9458097b6e0ca5ad2b61f4d5e988a8fb729dba7e66367cdeda5f50852dbe91325a5b99dcf7844ad5571d9bc53253b92a845e1edad83b0264b9bf224ab79efb1249c34b7ddeede7c6fbe5dd6dd0bf2f6e642fa49a5c47bbbad16169d5441def7a9b30595efdca79e40472d4bc3de72901e34c84a13120206d66c32f2b22fbb3d3615bdadf27833db27e50bf2786ddbb6edd2966fcc45438927116b504a9acf0c84486faab75500dbb6e5f1f6de2d67469fb8bb6d79265ad775735c513ab15021c7956482a18332706191057037b464a039a9018ddda52ddf984b51c8f97361b14411d48997d512cf54bc7f4c61b255f96d80786fb7553b67c28bf1e92733bafcf6536654ee95326e967579c9e7f1f8e6f1f6dedba7f43c1e07f278bca2702db6bcf3960b8bed0c8795cfeb1292ca451eaf4a8ce7f1bc793c1e0fe66b516d71a2080fba25233a629e8fe7719859e5c7f38c318f5714aa2a8eda83b9358346eba72a11af75145ae6fc713b5ae124d6dcc8854566dbdab77ccaac92e23b37b2a8ee9905a2c8969271403cc262f58d86488adb91dd13211f4a3d56a44591f291f5e5c543351203a7bc76ab199c52b076a6acbd59f1df7b6f55825bd69b0ea8259db61d4f249e4596c2a0cc505b2117a347122b49c2223a489ee09624bf541edea75c4d6fd4ace694a76c30660da6cf7b17ac4f6e515ab728efc713d34e8e95dd8ad8457ad381df7e625c57dd7b6fd5cd899ef0a9945b540bc45db5c7b27d5c2ffb6db0b304f3ee49f582aecfddee765d7763b56b51edfb81fbe8656fde207ce45b966fd51d6c817c74ebf2609503dde458d420d00508b7add41b916fdbb66db94b0bbba1bde669cba7526e60effb54ea4da997c2c7a6419df255e7b4b3c11d8ca0a65c249cf828816347958c58d51123cd408c9cdd1d93134b72a2e41ce905ae4cac0971828307900060a44677e5adaa12abdf5dbff76e793caebabc74f3bd9f7eef8ce33b770ad91acad96383e04964c4875d4ecf8dd838e15328278d6ff914cad923232843713eef532e28742f42e46c31c5087a8289482aa54c19d2d504a70ad190a30e4337a2d81571d51db98153c573e52c0cec0e8ad19d9228774628944409520434c744a51984ac45958df8e8aecba7c5cff38e280592e493b915403e6c35e4a02c7f3095435c47b19b5ceaa9de90d6755d0efb7897bbb82dafe5b9344f254a64d7a579a2227bf994aa47909c8ea329b2acaa7258e5dc68f47185088b1448a11d5b2786d434498a3aaa1eb4262b9299c62ac7d293f029d79a927ff9948b8a8b1855e5b0aaaa40994d0300a75c674edf815c3d437a5555b90dbcf2083c1656cd30d6679e55cd7b3cad816b51cd997fe61758d2aa9b1c67eec233bfb01655de81af02591e95867c4242164d8b59a16759beaaef514502b7bfc2cb578d3d553791b8e1541457c5855490e69f76f5107bde53792cef76b8c5bb2edf2e2ee72901d4777baa149c7e07272ba6381962629964068d57070bd005eef00357105af5915b36e894755f4e6257c6bb1c7ef12ed79a4f0fe802036117a0854fb9a484bdcba75c6a75df61a52a162c15f897f3f9532e361c1ff701cb2c640aa936a753bc63fc9e6b7ba821927a9e8c9c603c259ac41aa9fef0d32e1f384ac8354e2dc0d6f9ed56907b81c858f793095f51683e829838744ac430c8b28d25ee56144b8c8f6f5ba62bdfba6d8be3dbb66ddbcd35f76dedba5ce5dbddae0b96743ae662b429a333365ef06c04bd364e7ccba75d44577848768e665bddeab6758d7058b0bd4fbb8aa07c844fbb8ad858a52f157698e53d73dd2620f510421bec2cdfb2699aa6bc1996bbc1bc16f576751b8c7179cbf5cc4e8253bec6b8415d2cf60eaf661099eb344d3f588bbc4ddba0aa8254c21258b33ce53ab73cfd74af33ea4b5802ab7ce5c235a80298c997bf605f849ea6699abe2907612cfa38abb2a8eb0a875855164aba015fbadea4c675e86c119554c3d982284e81bec86ac027a447a72e6c849457fe419221974488f994eb0ad8b79f7621bf92be340541e57de53aa720e4ccae3f83f50bb0ae2a8881fa33585fe55de57966abea0cd6cfeafae64b3bb00dee1ca9ce2a1c42ab2a11a0badb353bd5959a624275915a8b6b55d5a507d503613e955a3b7bf853a935ae5cc5d7a6ae76d3d7ed0262c26d75844fb9d89aba98b480ba7a28bd844fbb94987007e3a7217cda7e9aba5ed997e3335261bceb72208b775d97c75beee3b5bc0d420b022fb877d433f97b73e0e617d61b1d6f2e5c6f72bc837d05c677837b2daa6a159cbeca53d62b6a899c2f48f2357701ea749dd95130cbfb3e8d5ac2047677ecbd8146201004902fc38cf0362e37886898d1b8977b6f231068046ee006c24023701b81c6a211e82ef7061a99c66ddcc025dfc00d2c168bc5a21108e439e79d77de1b68dc40d5b9f7565576abeaaaae7bdd7056b90ac33bef9c6155cdc0bc97c062de39e3c070de5cddaaba39acae1bdeaa0acc3b038d705633540502b30a029855d5985560b118965523ac6e10209646956735ab3b7395a902b35105aa2a5055b7aaeeadaadc68e43c1bd56d54d5adaa3bc379ab207611de19c8e16d84e10ccc70de3daaba934578e70d03a3ea86e1bd339c37108637df39c35b55b7aa6e55dd1b68ec51570e733817f9868b79ab3bc3401584b108f3a50a545755dd7bc3708695b6ba6675ab3b6f356f75c35b555538c37967200cc3bc08dcd94863545595abc0bdf38661e786b7aaeebdb931ef0c7378c3ec1368cc3c03b751cd3b6f55dddba8aaea56d5bd73de7c03372fe6a56a54b70a7355e5c00ce7adaac09d3737e67585c38c7b3fe1bdd5bd5575abeacec50cab70de5955f9de7955aa4678e79d778697d1ad6e55859730bc61a3aa6ebe8d7bef0dec59c2b95854b90aab3b3337dfeae67bc3bbb8eead6e58cda933ef0c22efbcb3bad5ad6e0f98df5372737cca31a4057095e90795a76ceaf3bdf8a9550a243aac3bb6284b317005a105c557410b9fc0d30f3c4d796a804fa338383845623019cff2bcde1859ce02b31c78818b651985cf762001424d0091542a4d9d42f5f92c4f53b5681aa7aa38ce16accad3c38177151934e4d925ac2ad18ca0db6155e7b36a98faf4795627ee6af459354ea57b96af382d8ca06073d81e1b14a2a6a864a81caf7aa873c4140d0d101000b3182410437128c9c230cb62e96c0014801060b0605a5c9c49a36910c3288831c6184408228018008c014086a6c80cc9883141f3f1b3c2731648dc77f7dbf08795b7d7a63c4c636e900f1f16655598d1e287e90b4517449281c344ab2bb87a97a85b6158024bf8883251d8811104ab7002ac64820004b7ce5067c51d7a6117554414562ee930545b6cfe03ae8a82ce51e077dc4aae222c9374df24a85eb13ab42726649b899851f7a0464a4bf0cc9d0077d79b2897ec21bfd18709a9e141ecc0ebbc1fe094f1c115690704b79004ccc2121745aeb85b958117c87d58eab0cd8a1b786113056953150557047815002b775ae5b1e7e5893c8706a96fb40cae3f236c0a44193f619f06a1c959e088f17a0a26e02e8a86a515ba37621b35a70eb027430446c46dee427350c7430c33ed8c8eea2daf8638cd997425b4aaeb95a9953814e2acf8cbbe179a81aed04d24b4ec462f87c089735f7ae0e41c3d5fb773b123f36baed464fa6671fd1b3d40e1e67ab3884912e4f60d6ef3392c34354749cdaa84480098a20a95cd32fc9eac030203036d09f06f673b7fc9e1f10134b85ee42a76a3b312a088987084b1a0ce47f520922731943e685c7156ac366958466ce167e2c47281943821e749e37ee92e6478281945a09727e9f920e1f7113da040c50bb924f18ebfae8ae275040320c3b1508b6840570c24c8543113ad2defe53906a5d26ee4e24e283d828562ac96ee8f8eb86fcf1ac9125b8f6695a3cb0f5a557f34004fef1ea3cff62800e30f0f8cd1a500020ca19ca14ae1b0ad8b48dd15775a02d912e79f489fe0e6ae9dc430be675507611023321c6aa04eae176d05c6b30cba90c76c1e42beeea55fe60da1e51d75525fce1c4eaded9fed2c6435f50f9462778dfe730052c046934e1129c99903f8cc3557ade00480620546be289a8f8e97cfe57566ac040f078a2f25165b6963095ae19a3cdbb3a773f32edbc1b090bde69a3280100c6be6e15c148ad94afe5463a2ea326502cc117419ae0087bc28f1e1e13443e6ebba50b83c4cc1ad2f30bb4cb3d35778a4bab193a45731693293af85a52bd9838b6a1936006740f4d64eace430da95e58e4c4c940bb1de00e0e99e95a338aa49a6dfa89aaca2a792c7d9686b287f61160d28bd66cd41a88de0b0961d99fad4082e111c84dfeedb1fce84b3ace61415777f59d34b20922f50f15ce2fe64be2187cc87ffcb611e77c7585770de19479c56b639da0c71f7051eca0a0ded4e78a274e7f03c156b415d38d2409bdf6ea7d8a6dd174cee06c7f2b144d972e537a8a307472aa873c8d330e2f3c15a0bd2e16de29e81623976a66daaa2a42fcb6fee3f03a070eb0175972fa6608b79359bcc77a362d5c728a0b84e14f53eedaca67c919920f4229a1e06710fe501f4c8f049b71322087fba78829e0252415a33ace0793d4296e1f1fb63580a9a3f9297f5317c5ae77a8e280f4bf85b08913f49b595080fa014e29f9e735c12b122402ddc02b01e5f82614e2981624e0a55823518e46ba4ec5c99d4c02b19b8562f98ead9fa7f65fa5528bace666744896a1411b22b63c83e6b9d7aea050f3a3bc8af9e7f2467067908a3883437616a572a0340554e4867a9410b4844a35d6a52622923d14f67f385a1f9a1db685a75eb327fc10a6f78de8db62bde5069d0c46959cbff64bd25bf8d4fe105625ddf755949416b4c94670e49ad2990deaab1309eae81a127c44fe479737fa563dab47c1f6f33c18fc1ce17f8121a0a5549cd66ab9e8cb4ecafe0a75c38f3b5431c09aaad10528dabbeca0c49245cb99c58c1d33f5ba6687d3b84bc3a11493235dc77c3a47f15389506770939a72a34141919dc5176871c0d18c4db25b7f6e6062a00f9f2a6d04bb5549a4bdd9d964d8b809c4c835b1d23e0ba7e697ea1e9ddc3d70dbed4a41df870313aacf3eb7707460332905862ef9860744fd24022394a8352889961dbdf964121b528b4e946098c819107785fa3e259604f4678b8b7d06c94d764bb6fac640cfb067d0494b29709094a9850cda226f910bae849463f9b6455758172104482588e57bfbdcdc5574d008935e1c19e891253c0d851e7121d07a0e7a2b79747d2bf078aef3926fcc4950058ad1747b06860bc1a4292dc5cceee100fe0f24506611175e24b11ddcc9801c126e5cd63b3af96a43e29f7552a120dd3f1b22f6405c8bdaca177ddd0375e69dfc9749be027d5bc3b83dd1032cee092f0b4dd7ff5a6c1452c813d73a6cf32668fd7c127eb0764b76d0ec5151c20f0ed8db20c7fccb6ee2b2c44630efd4cf02bed0720ad755440832409a4289ff258a2a429ca0133684a4fa93feefa2776aaeb5c35b3506c68557a8e02a16516a0999d8b40c6ed3513dfbfded659afdc6d01e01f9c5dc0313bebaed7636e7f26e8c1fefa4059930946e9f57287156544711df0d8b1de5f06c6134928e7653a08650fc2d0cf7a5d16d1b8461968cc6030e00ec61e2feb58110f1b90609a5a5f3b59fd22189c406631e0b3d5c8810d8e1d88e0baa3efcb2ae29ab4621d73b33e7d2b68af0281bdb98e7560d9e004d3c4fada493fa8b41a6ca4c9ec2074ccd2f6f56d2fea29509112db00b5f48661143890caac273bb6c391030fa2eeecfbb0425e9346be8d0dc43581d2a60e3435ed2b3ff30337967cc01649511e76ab6f0dfdaf208117c48cb223e04eebf594a4289731f04bc019a4f0556d6536ecf8716c39f2601c01d46510bae1a84217b30263061d0c7d34d8b1865f6b2ccc893db2223cec9fe112e25f59efb2133fee586e0e6318833ccab2d49338a904c5edd0dc0108aee918fef7f72893e0951153c194a60c067d16d6e5309f6a7cfec534c7121e7c0bf142387c01f6aa998030b6915c7119d83908416b7a886d62bff2c60d62ec8620e4913711f7b5df4ff6fe1ae33aa797490130fb1086f68bd826f62b6b5c42c68eb3712e80b8f720ea71c41f0be9950692c2f8475a8cc9ae232ea1fa9479a6d8ac38651d270561ee3dd07a21b167217aa5b14433f648ae980cec1c74a0f54b62cf127e4d38458a71d9a7c41fe6e6136f16ca3fc737c60a40ee3d88ba2df1c32a071b1b8c93412c7b0f867e4cec58c25d465c35aeaa296e8b9ad8c7ec6a59b46b7c4082e53688f33e426bcc89effa7995b4b5a2b13f6c1197c1e626119a46276e6b4d52d2769ac6646ebbdc0ae0dd77e0da31f1cb2a72a553b41abb48bfa80dae1d80e0da6ce23b899fd2ce8e35f68622e2cd74134f9dd5a0842b8e8bcb60e2a083a8b3137f2cd32bc215bbc536300c160d3ff1219b5f41a0fff15a10f95e84a1552836897d2b83cc1b2791a6f5f0ce41085ac3516c12f42a6b5c67c86e08021ed94ae3b1f30ab2b7b443be911767b2448dcb103d4a3a9b0fd9713e5e0680ed41304daab19df417c3505fcac3393b87ee1508aa1668a4658fbdee60405421150948da7a613b2b4a694ab07d8106f17f4016887c60b55ecfc172db737fd0e04467f64002f9fff5db391dd00c700156ab1c2440eff10be7e6d705c780ee90022685d4ad916165eebc0bca10847fe8a8b3b8eb2c70203b8ff9b903c1c107ccd9872d718ffa1c42696a16132349f8f10b8d180abcd43a1461f6e33c01559e73e28d193d2bb6e9a52e27f183a983061c8c49edda178ccf4b89279b2ffe426133a941ec882b7ef51757343a5f99ca92573c82cf6f49130c2a28a971b1f475993029133d8268d24a63455487debcff8ce913f82f0c7d8622640068af0e826c6df2c0867e99c12d94a19865647c55c02b4e2f6416e913fc732cebdeffd9a5d5bd8d5f246963a958e1ffbcab1e21970bab969a648dbeee36fbd2c2619819a55cec74c2b9d3fc2452f2a89a2a02281115ff1c4a4243228583998e14c2576b2b0777338743b6de5a502525ca542d80c794391ac025a22e5114eec420f00529e50556101285ab0a90a414ed9dffa206d6b3d918061361356c222ac8ca1004877b2510b0196019b696bbcb1689567d6a5d727f8c335c8a306eda3947be26909aec225f2868cc7bd5bb287122235b206355bfb36ceb9df497a615e47e7be029899aa53b0ee342b4758ffc7bef04015462d55bd6b92f5da487ffc038728bb87754de983dbef7db410fcade3bfe711aea7fb04e0fcd754f52163ad3b661ad9826a48294dab86fe7bd87e3c5405a4a752d35dbf573b48b1488348c7ec9204b04f9cade1f6d0a86ae2f398dd256901c8d8f4e98aca88cc27e74c8727d51304a41e03b692bd25ce35ba83859502515b57fe59befaadae78dc0d86a204f3544a09222be203951df65c4628667dd028e9441736c923df12c6d5f7876853afdd983d323090b04a8c5036041e43098889396f08d61da26e7ca60f702aa0bd2f4efb7d160f130f96d1874f5521dc4d3e333ee4d76410d8245f37aa61e5cd5db7654238453453e37c8d1f06258452c438d34d762ebe27c8627fd08305e6a2428aac93063259914a33d2f96ffbe409a1f2110a45732111ae9409a87f570371b28c8350ec60be3c60d60c70dc88edd51885f03391cea17cc05e38900c3f0c5cfc209b4f614585c778ac7480ecc65bc929fdc0a66a41cb19fa1a9e5e50a30e004611a24cab1d9a45a265c81b8645ff5fd054964ad3a88b88e7021de8ce47028f036226c7fa4746840e64b05ace3c07eab1f540481943e6745843456dc01de380a422ba22fa7a7e20b6ad79b8eb0a916d0a546a988c2d470181185065a6230680ca82829fa5407865a57f423df54798e2a21c4be3e965dfc49c7d76abcce0811026a03db16ef7af86b723e6b4ede5210c58735a5b07469452fbb5dc2f5f7e923b871a69e34685a2fb6cb02d584b710f56890c56a298aac4cf88870025d719b6f7cbdb4fdc31cbffba11b134efc47ee342e94a64cd9ec4ddde38b231d522a7bcbde6676cdf2aaf9847684fb128c7060c28857b98ea05dd786d478fbca51ebb53ad9080c197e1e8b4eecce7d6ac85d1f36532ae6b01c0aba7c12a2ab14ca8b7b46d5515ddb3834d6153aba00a46de1f5c32f1946550d480d7cee4ea97fe0348425e2e7b983ed3ab3ccb21b4f3b41750c8c67dfa2b9a4a92faf94d2fb1e94fdc01427a594d53bdadf2df316ea7a8d9612f89565c7a6eb65883b90d55ef4d5551ca45e4d1e1fbb3c100925894116aa321ce6f4cd3c82ddcf6e19ed4a0d8d581d450e8f943aeb93cb3a24d352949014c14380270dabda7cac3088d4f0f3420ba144a0c61aec760e7190b87411dac7d229146251f48ee70cd5c9d48aef406a89ed35061ffce6446107de317a6ce82561e76301a1c204e47841d96f5b67a39dd7d46d17148a33b819b883267c522c4154806bd6907235a0dfe0219810206e7cce74334c5db387819864e36a327529b7a88906841c10e331c2cde5ce146030561ccd43a64d7b80967119a754e8576e3f717aba444a94e2484665963c451e3ea671889057a4afdb38ef1e97475112cb3387f47240d1888ee91db5fd9cbe937460de40a1cae1ee59146bc5c1484e8f5eaf96789fe783544336fc8382b2ebd8056da0d08002be3f1e064d9c02c0f5fd63e007ecb32a6726a7ed6a6f653e23b624550c44e3ecae655c18e6312b44a9fcefb3ee0e7414641e1851178ce967f55699a681198d163a33cbe9ce6818e2c2a802070746f45ef467ffbe221491af452f7c545998ab013b38867bd29ca0b0380ebaab070ef1c2dd8565f011cdf2c9b9248b0d8076073a014d35c0cf8ae048c9d3589796bcdb20b1c36e80f5803581131ca1453c65eacdb2e088e38d4eb70f33d94e73a1df813d0f30bbaa8234dd4a690afe2e0b78d23eac7e79608fb7362e2e5fd6260a37ae52376896e639fdf02501019289c00d54317c1bcb485a925f25832bb84d4e01a34a55984e009a70da2d952743643776e875a1e07a2e19c8548a5a3e28289663110805bfadd7894556455785e757c4068f030650a0938fd79bb9c88e9f69848a0bb783c33f3c4b7f41500c0810f365b4fa491163c444e5d580e0ac18c01aa6be9e4c96193e9b62306809035e0e6a3c9996b5561f2c24e6c65bab057831bc53b35c7efcedaebe803a616c2a86c2a2b08b2936ec530ee26b984a5e8f7011391e6ba4b794715b3a6d0e42fbcd9e39b97800f79fe08ed929beb02a3a3faec97a0632c404aea51f33da8a4af922a67ec4824db0166d376fd34f2851468fb50ccec9f942c2537d20bca7bda9906e46c69227732cb61bacd34e397048d18c42567f02077760c23b4bfbd5b85fdd3987e4ce04dc0a8f60a31c0e42d52bd108d6bc1e767ffb433b3a7618d870844526a8fde2e6c03a2f59d70af19e49859e88c9b85bce9d5e8c74b90f56c1de8ac0d2d5836265dc213d99424a414b6b86ac7dcdb4655d69351049085c5fb3ab91b015ba7b876bf7656d4bad7ccf7eb2da4a4492496ac1bc4cf41b0676a03a67f179899efb3db0de9aa57ceb39675bcc03ef0b64d9fbc8696ec3b8e545a5b3ea05af74463ee0b9fc2cfd52ad156b0708e255200c8b25a6fcd9182b1d9c088afaa0b44b1d4948351afa34bc159190cb2b8f8dbe36d6db4da700c714f9b80f862301799063816a10db5d85cdbd451544c921bd73396ba4a38224f91c471cb05be84bd94264636e36018a4f81582602462852ce614bfcbcc0699b0257ef0a07f416a00676beb0b5acfb0c65c3ea2de2a4067163831058c047c59876e72f70c19b1e487a8e2850b80798783cb4db32c5d509651e1d84d26267700112f7a1a7e22661eaf97136bb78dcda67f6cf28027fc01a2cb23c9ce35da9af3467005b20741f3778e12a4e23abcf281dbecc90269061066d98dfb21721534f941075e564833b5afe6924582cb070540afe3432ccf17e9b97d15b3660dab8a795bce22fd56d5e520f6bdb3cd87efe9beab68dfd9060312ee7edb14596e590b6c984838d6c4dac37e1b811d9f60b3ce3347e8473244f2ea1029ceb2925ac6b7e429afb562c71e16de00a6f2f729b563842d7ad881261770624232744bad795ccafed99c3f74a5c39992d6a46eda90b711d662d0a3f9f2900cb58062b8711e3960d50d7d0bfc8c6cedc7a7fa6a9ae30cb710dc643ef25f9d64c88e34c78de601aa335ae3aa71a684aee6d66c57dafdce5ff28667f817e3ca35b3f4f1a96996da781deda7658b646fe7c11a168aa1df80596581cc5a5abb968f05db6cbe59105d1ba6c4b92af0b1748661784598249422be3be1e9c0bc2f808219ad3812c582a6af89527a03c16454b64c977b1af6b4117e3fe2417ec4873c86f91ece2a03c81fef9ec1c648d502351a81364d8d6ada96202bc332d95135ae9e232c5599b8cebaa5c213c0e6505a73e53d6216208c01b2b77c9993c035661af75a0a05fa065c55bd3ca21d94e04ffa87a36dba0ca809f655e9965dbd75aef7eb73ad15cdf49bf0c2414e3e4d3d904765ab96ca1781e6056cc02eb9ec88437ee4d2e40ff920e1fa0e29eca9315e0b6d3882c21841d080459e77c59220fdfee59b11a0e35022e5f291fd0795d89b806f8ce2ec6998af092663eb6a9b02c313bca896f50ef97b2013cd4b9e55b98e61e7a7d51a0882508d2e6fef6ec2d4297a11ca3c6282dc77d9e0d56f6373423440f455080c633ce8d591ecd3bd917f51938b40b95f56775ca62b6fc0a05ec88ae6e041dd993d89ab42ef36df702c08b8a83b1b7ae4cf56b0d8083367841c3278e93ae617cc87ce2d203fd4787e1d4559a10abc82ac1c67f4a57db87ac6199c698ab46006256e1dbd431d3bd82084b312ee4371516f516ae95263ca39e31712f42fec39939e1f51310315eb7fbcd5a8b35073c2308aa5c73a24b188c0b0ab4e9c4e0fd967d7f7e92e0587e7f57a2449c32769aeb1bd3718963e7e22de97eab988b620e42ad9ebea90bee0d4b0c7e92124c803c72736ab80f911ea0fba8b9760f5e0f2da7bc9bf96f3325e8436bf5ce4b5c740b1ee6768e7aafbf8cede76cbfc081d7b79869392a215cb05a090d1867aa499af2b62a8c873cc26c0631df11a8e303dafb71dc95a2be12e89cf4e6033231bd26fcd3c2af5989a5622e6eb72fc05c2a3c9e02ce84a3bd87a95fc3404c71d61b68851a06235b28e7d6b52a1500d942f99de5c650bc150e484aed468704ebebf203b1218e299fde19377768650f768b790808440fb89e81570b2ab83268ab13abfe2b4296cc46bbf3b5e8de808daf81f73b59144d5894198f1a9927d48b0cbb37ffaddb6d121f5d5658af7a2040826b46a4e99f48549e29cdef3a3c8d9d73943ee94a8a54e5813085fbedab8de4da6df4d706c5277a12792d6cb30f4bd8cc94789c20af94dacc860275eb605274dbcd51a52b2935cbb655bc4c1499d3fd4b6a2bcb976f605283cd495038b9e91502d0cbd44cac13d3b99778e274e3a1aba856105a27779f6bd3d33c88cda461d33e2b589f5b724d5f4f729c53a141e2132f1b559635650e941cc844210eeef2402fd566d1776600a2d4259c43bfe9ef02ece8d4477f1a6f81c735efea0d75a4b8435a06ff9e584f72ed9471686dbbd8a41be6fb89084832c1b4d5db9fbb95d399c7310744e3c56b9f7d2b9eb79c7c3e2fdfb839541721e93f3d0071d4fa11bc3003ab24917227fea3df52d20f7555413dab1fe73f243b593bd2d7cbb98cc9e20d3c89e2ad63183b4e6303d67010d0b2e31b0257b3a4606583f72357e2680b3b299e4f7c0498318f4979d75fc8f0bde9707e25276c201d81a52c30946e80649e7438a55996891ff8e50c5319c234317d256f5423469416fb12dca265384343e1da395ae8407e43abd221171129207cb61a2077a0aca80a889163bce691c29788b74b04d7023322cf4cc9ac56b997817b4594c86c4da5e50cce43bf66f2918cf316ad5a4f132a2f24706a82471852e6b3cf0018c78c92a767a275694e9894b652cbc6cae1af45e78dca9e4ffc8303654b3b2193c27e0ccec78883b54710ce07ac3a336560d40db4d2d1cd59a8bf4c88608e816123ba8b3434474457794256d4b4fb73d8e0741ca9924e23fcbad389367379eacc99472fe871ceebe3068f16d9705884266a460b90c3f5bf81989e1be024b4ac74a579fb11c578da53bf5c116c7f0d7274b7a15096b1503512a7c317206211023dd069a6d0eb3752e470726d221e0f7806947be13147dac2db8b023c2643fe2653f3ff0c84444e5b89f774ce6d952fb307b1c3903355ee7c9631fb61b81801879a310cb8ff08d8f8f8dba451c0f3d70bd041d664f29b0db85fd5946cc8896f1860118c7cb2c79c4ff25543dfc0cd72b0d5496bcc85afc7d00b1e537b45acc301291866a06adfa3b7f16d27eaec8031382301a62eb0a89c58d4689b83c06581d6d7814c4cfb856b303e46e8e960f8b03825a32989056b6349068b1810f520d87fe2f4e734c676412a76f4609c1ff26a16fbd496df35f18128631aa3b22e63f66bf8ad5f6134144f707d16b9b9af6c42c3fe0642d43e164d6467a5e0a064680653179fcae24cc7b079923e4a08e617622ef7ddaa8bce0deb687aeb7bd7f888bd0bb74b99788decbd198655e5a62155e70d76c2447c8f0ad98fb6ff4c03a0e603ba23148569752e988070f3adcf319dafcd691e300009b5f90587f3c0ab22ff15c9279e811dec67882fb05ad2a0b06e37aae5c043ae8322a6c843da6ef043d0b4fa8562a7d840daa8d8d534eab83162282135ec066d88944dcd97f45ea491f59b68b41dae74cb7a24f7d0862bb0eb1e071368bfb7d8b3a85126611b5d234b8e31517d69f618930386bb722347c9e954d7d7c9adfc77180fe2e42cbdd99153c8992aa9ea401c90e59c1b2930fed53453133707b21169df01ae8701e61cd626e7480986caf9e929b3b5225b31eecda966b49695d4928adc41fce96661de1ca6edeed46555e734bc8f4760ba1e4cebb1220c330bb751fe563b5fd8b57315c40d523f45d8a2887c28654858773674226c3951b240aa4071867f8202d143752c1dd9d53176b7c0186bd99efddd5bee5892a496292ae9d4b5a457521f8013423d8016d991cd34cfe52ef7e8ad526ebc6174c127c5d82427f6774b550c65472633d351499e15e5ef5eb8ace7e28c886c41314faed8852d82c82d741b57054eae39c169e2d07a5465b07601199d0353c13a6df5691ef62c1642ff7e8e164e1b73b22cc335ae34757be15d2730ed634b644a34f554761a02cf9abd3a9445b81ff76ba901e4edb90953712b06ec209f011a1d7deac6b6a0e7f01359eb544d09419fff874ffcea17d6c6cc44955793974814a956a51e5a388e785c3a28e0c2b234f5627e4abebb010ac113812e24ed709294fa4211c0c22aab6d979385f71fe23e57c8e5bddacdd8d64dfda9b1f6b9b255324b740b348de418d5d542b1e183d698e338cef86a92102a62d70590ddbda816d0104f25fa687aafc64038cc4281de2a83b855615f910522c895e3800528b9a60684b072ea917e3212a4e32023f4f16b476f73ea4369b91d978f0151d950aa01b3e30e19f54ebd390a191d782d40ccc265117afb090334506d945dcfd1d9d7e6d60ea5cf30bd4e84a39f696a4aff758d871471957bedd8266e473a92a1ec44de804b90ff82ffe43a117f59be16fb45feca829012c7d24100b4808057e75d31b7c17f11508b62ba968fd8165246542036aaa5911a8559d887bac34098947bd7a17513cda2ba5d29fe37d4ba9c70b5237e14c1b9d93d84ff1444c74662b7b85f75e04547e13585c58ab28798ab15e0582acbe9d12c7c20250d6419b22799b8bd64ba8cd185c98de90e88be1049c83291f164059c84359c75cc676247cc92207a0ed970846db2879f709c6d1296bfb795a9fd1a447bdc9ac7e864af5c72a20609b2f9cc81bf70f1f503dbc8826e3e1384ab1ba45e29ca58e18592aa94a5db1279b00e5fd8f5547feecf1ba0f7d3c4702b6ab965c0b57a97bb31e5cc4c2cdebebe7931a34f8eb8ef1b2d93425e0c9a06b356ff2d692599925b51838283caa65d6676eedfdf4f7bc04d81adfa3e22454563233d28349c82a23f7a7ff4ab98263bd0ccbdcf986591d1386a936d089e492da1230522afdb7a8074740371744195f466607c4404ee0f4816b15d3777f18f30515370fac847407bcf31308468b06fbf4fe6682f90734fbc832d3e634c8f45b12bce3e3708347f607c274a54fe13804b9e1d79c98ac271b84cc62d9a6c315ae0051d19942bb417855c2137ab6f4597edf269a55a38d909cd8b04e91b7a648abc4bbfa1de688f2c87b3c43ca197cf86decd077bc35d384128711544948fd8546ebb5509d93b0135e61e41e24a4ed1d45dcfbe8823fe7f033cc3154681c28ab4e38dd5cf4d8852b1f08ed4cbb5ade6a3fe215a3d3763a5500edddfcd9cb1545a674428902ebb32acdb5cfd9397d9ac5dbfa7669e25d46b24ee59e76abc3dc30a78e3ce9177950066f16ef570364729c9c184d0da3b3ad9fff9f97e3859d3b0bc590fffe461167977e23333c8093c649516ac688459d224d6fe1485f6bbedacd07b08db6c9c95800dfdb2cc192a9b5cc4a010070b75f09f9631517e428a4b860e85334b819bf61217c239b3533f985e05d93ba676d2d6b5038121c85406bc2724a7207d1c01ad1eab65bb01a1fd8a3de5626b939544b16b076dc9c2d097882572baa202fe83ece36fa502b7a6aecab1b6381f6f2407a287b1a856ead5e3c3fd7656b9f20c3a3cff90f7f9e3698ffd7ba7c875866cc84d04cb5921ea5abb895636c271edd1a80e041ad32bd429d2fc7d9ba42adf999e6d0073746c45493e4d2db6f363dcda5cd134c26a2de37d532620d89820b64a0da946878985fc2cb631f790215301b019864b931ff1ca493930dc0d8f1cf208d984aa072f631d119fb219b02babb5c4fc32184b01b40f4ba74d268ec238648a46e328f3167aa7e2f52304af632bb644ade3871a0f25a4ba47b65c7464a952979c9458c5b3ac4e453ddbe81b8c1aee1fb69785ec22b4ebf7e05abd790ba5f8e452447fb081046e3d36ba2b90c2b77dfb27ca80bada79cf6c65207a7af51c9e3e4573cbc7e482c7fffa524dca3ae6dbabb3c0a14b47a78c58d532f78bb63ec20f3c7701b7cf94559037acbc0a6b690d715afe4bd61bc6ab73b4d7ec0154e488e2dc6c6e745c9ad58db7eff1b07d30a9ffa410e12971df103acefd11c33f444c32c0f5598bd4f25fcf5926ed010dae1d2ea21386a5f5e6c06fcff769012fdfb35fa0411741994fad9901f1a70290f9d5e1cf7e98b0646506ca36379ef168a0def511fcd4444d2847c182ed040b7cf9b834436eaf03064b72a4a1d12558fc636aac0281e62e6191dee68647c48ba4334a542b19fc75703a1fb7a4cc460ce2801df5063e84c49bf635d769a4944fc19c72e80e2a942343e573b4378925dc9b5af6d7a7852f97e1f1b8f5bd5e9e706152aa854dce9643f487052c25e9294aa2d725dfddcfa197560acd9c94f28e80cc45b7c9f1d416acf53feb4b9fc21a29299d139c83fdd1519304f770f2092b452bab44db8a55f1a71166f9e63ceaa71a6920aa3640834c505595286a4ae18b072cd367d940e2ceda97f4cab4e8b11cfe4598199ea0277d7d7afc10e903512f4e2bc565c2e509c479e135765f0952599950c707a1d3681f58df23060ff8e4e3e0b4adac80e608de5c100c7deaaec98f4f26f040c5e64b9b90eeaea65524884fe1eda0062a9b9edc3ef06a0f898d4ab363992173f120e66eb72a216aaed42764c2b3643342b039965900be0fe64d8d3ff4efea7afdcbeae90fd2602aca746125c03f072ed5fcaa99cc2d045d33bea50a8b73ccc4159a33a164fd7804e82945126fad544139342541a0ac8a1fdce983608fb9e8448f489bea96a5941aede3e7502f10d04c144b90375d94e656058d7b3ca26f0f0ba20844ac2b3fba0decaafb15377c8282b0c8282f1fd98d344d9ebbd30f3a1a03e39645ce582ee15d5944c2f3f420352039d2c60b0f600f05f8751cb0e0e94534f406575d41edbcb9ce5d867f23330a76f7369d2b12a06457a384e41ea51ad5f33b55331b28582d7acfce4d2a21535a69b39a5e272064f2bef5535c80fc33dabc8ac66c1b14ee31209ac4f5305746c9c945e752f1f4b2d065b9a674196b3d1e1c59f1559a5030ab2d518526bdc413e74fc0573a4817119ceba8f1f13ee466ac17e79ea8905b6c494d5e41bbc845902b0155dfa0e472cefa534b5efb78293809c683899b505a9d5541a0816b1df0d403e46384f5a164e258df2f6ed3c177c7bfe20204bef668e0c887a580d01aede0276eb9edb863a503040ed41f740b912e9e21130f88788fec759964227c60ff89b2c03dfa7a15eee4f6f3368b9f6ebe8056de46651f9ec21a82aeb5e8d589e1e29af57a092bdc7a9e35dd536e3bd59424f805c969ed82374942c063c575f41c4cef68b6d0837eb758a0c921258292ecd00dcc2edd42b6c09b787822377debf06ea7c46e5508fdd1e48cb5f59d21030982e6238a1a8c86c4fe93fca417435287dfddb49bd113573cbede94d8064472603a4060d60fc213f5d62c6b62d9ada01f735faec73467d303b83819d4b660158c7b0e3217cf24c62b41e3ec61341f0acf4f2513977cf109f661a0f9f18807d60b3799312b35581cb76c022e34074905147c50f7a64eaa418f64315fdb1f7ee0d638d814e8bf0c8d2abc1efc5718a7d24a88e82a7228bc22b87765a5815f9ae9faa041f9e222eb410bcf45d33313e2c3c1113c10c36ccb3ed4355a2522ae2d69bf2414760209847ebf34d2df3639136d013a2d643ca2b6763a695f25c0e47a07dfdf44ab0a1b999a731d96a5a820910b1e121037fb15a7a6746b5142f552bddf6059546d654df794bba6da92043f4508f0ace3316d18848f72333c1457600a63179b064190b6dbf751b3081dde07d06fb61c6426510d3fb5794a104d9d109c1f84900c5316c4080162422ab40948ec960153def8d49fa53132c48f450c91ce8cdc9d379d4c76e8a2c089a0c3892a98094bc6a0efecf0f0b67b6b771e545e8abb60bcbc3251a9368e134810c84a02792e0a028510bb7f670d2074809bb14bf1582a7a7c7560d7c45d9b03bdfb5d97afde9dfb1413401b12b45db5796a775bd73ee46ba8a38f956bb5b65cefb1043909b69141b426345310093cef82dda824f5b3b75f79a2a983a3ac1c5654d333430b11e138e36cda32daf648180e58edbfdc2d4a70271a1c520b4beb51ce99d9cdeda9b22677065d0cb447ddfe5cfbe36658a04ba6aec5b05d1e2e7dfef68b01a9c2db5bd1dda8a9ddab0777779f3f7d6670f412876a5f2b06e487cf6666a98a059e8ea77c3092076e731af727994a3b1c34ff83806548756f888f2b69bef898cd257f73bf1c74f211c8c2bafe3be4d09c0fe4055f9afc82abfb75d5a14ce3d0c9c55e58e5c57c4a0df60dc331ef7f262bfe496751afe8d11ee965172626f9de1497036c756cbfe9162570a33e262214bcaa4413d0057ae4f93cb20b260bd3cd8cddfb5bdddc4059f842055c2be0e919f054b6420e6a4617ae8d25b999445a43f0c30b1d30bef52f0fb6c7a3fabec361415151f191ee485d084bdd2de99fde9510cc7d8f3b67bcebf9ea9b8a847f3bd7f41db6504ef1815dd6d379ac976f6907a646685612b3c02ca63e1704287f59241c4e397c03ed2d40f357d48b47593a1c0e5ba25d6533073b6e5a3cf061608c252b9263f49ade559e7ae1ebe0c6c5f571c01857a9ba17430a981b438078cf127105244e6aafd4347760f733f328b92006123ac86bb533a31ecc7172400c44ad6ae00a31f8590d83683c10da3da897862dea11c16152d771576f9c3ac5502817c9d8d0504b68f2d15e043b5c64b21c56d70cf381108ebbe92a7b4dde9aa7d990cd1f38a2f75d9bba989049c9cd7278883be87444e460794ed7ae778c9c960879ba1138a74456fe4ef64c31a42e78c46390da6d14aabab40bcaa7f12264c65f2757c82833c3017076b072eaaf9e811e05dd2600fb40994cf48733dad60b55aee4b08550f8d97c18138486c13bd7a897de9c687778ad0efa1d9fc98670d0941f07c119b54f39bd8e5a3d3605678f4cd320ec2cefcb771f29e2d3ef6d0ac517091b2bb42a3ea72d2e33a07a77d05f823afb2b14320a4a433816fde5c0decb8282415358d1b902e44db4f42d9ba685e233440913d3cd116a4ad6de1d36b6ba16c4a408211c6f0eec0e6ab5a788a8f9e2de83790238d0d6606d494a0c1beaaf39d7d958d80e93188672bb52a9ea12d788b706b247b990ce50e7ef3ea820cf4e8e823e6cf8330778553b87e11e4c14704006d4959b197d1bba146c50afd99c5fdb8b469abc0540b7ab9eeaeb80b05e33a7950cf8ae761edcaa7611c37b30718cbe8712e876489c02060ca8b194b6f43efd2e32e8d2af8c8b3389633e86c5fb1298c2c82956136188debd69615bfd5efdfa762fcb9246fd5ac1ece559e71085d21b12dd284e10ade4755c2a8c04cea07d2c8538a9f8c9857ff3cf80250427298859c6f981384c9f03d7e12f9475ac8d4c13f4227d2d5124bdb04a88e57e775a1710afe3453ccfd3e15b23dd42f4ae6c44bc7079b8d3e98d87fae87a4c53c6e9ad9a6b539330299499884f57ee6e0ca006b847086d1e4c75a879a8b94cdd4aff47710a4e33bc07b6a417e033dd8f828b8ff810ccaf9a9ff0e27ffdde64c5619b6ec7a7045cda5c0841d19c2aabedcf510fecd21c6e9859d7c5334af8e8cb3b54dd4a2f60aa0f373ce00d05c174d64e0e942dcafa33d5f64b9d03af12fbca9e10a5541648a8a35e9fd175f6f1e523d383eec84116bdf70544987b636cebb3e95d813e80c10b3502a2b778896284b52db90f81c7034dcc434aa4fd3ab9c6b36dfe5ca0e75e92ee8d34d306c40fa7d9efbe28ea7c0f17318033524181755759353f11e3dead102e5e7ba76ae1420cac2da1cb43582e7927ceb3f19e3437e7a3d21057dcf1ec4347c126b69041d1d472c33a09025bc811691c0c35bc82672368f8a3fabf517829eac83030fb548d10585c0755d7bddf0d13b3207ce8a61c40a2692a56ee5a32183cc4c2cb9690f8b67be80196e57009953626f751a668382d1a7df77246d7419124260fa0163b48b2c75fa8e865ea4b432d62d3b5987e11c1f39e391074630a4b9d1bed1c532a09a33fa6cb3b74f37171c4e1234c1a14bde4615c2a8c308b90b114322a15aa339bda56d7a9718e0bc6d604539c4158cf051848e8747f42b725ed83b5cfa9bbe27ff89c185c21916388a81c9459f44ab794a32c4897031342ba8a81fd96ff106ddddeeadd1c0607c13c069f944a4d0ad34e1bb262304d3a790c535ba4348455d4f350379da72e490180db939382aa95b520af2e4b3488856877dbca8847657de1eee920bbda4b82c8de3689655d04114407ee106e3779823332628a5d09cbb1e66a577e350a23dfeaa47b4b1a04c60e3bc0aced7b1bbf2722ab03a83dda99f53338887321cb3646db33f8a22fce2bb4cb828e3f666b932d70f870b89060d779b9f145349507083b86475eedfc66bc066d534cd2fba95e3dce8c42afeae8145d2fe8b74dc84a022fd1748dc1385a023c7d82c190c6559265c8300225a49b053802aea1519d1cd901bbc1e42cb8f0d09368b90527bb9a6fc27b0b3ab23a9517eac0b35bd07aa5ad3351e582138fd1eaa9019d50794214a2cb310f2f820f2fe6438951a4acce679c8d58008a2242df031e70c35341cab74c0e3bdb4cbc56a47c1739e37b907d98f6907c0122e64579d8f5ffa9221f122dc62ef1727421c8d414c25221651a4c1edf85e257039a5dc879f9e59c50e25edf30445ce502b33da9d752a48a64fbd300067904025802b14d3eebbf348ae42fdec74ab4c5a9efc83c167f6974ac8bc8db5a869c33191e691bfd8eb93a95d3023fb4ed8b51ec89134da8f116a7a2612e47ee582431b215b6c44644fba7f199333da70dbb7653164d7acff0c3e3c492a636d86ce2db72ec88e366998940d3f1874984cc3f682599404715423c1a0bbc68a7e6bb54301bc2685612e35c349d43fe9e32154be41fd0593dc9aa3e41084c96b1e62cabc967be0035b3b701d3a3b32f5ad0c1c46a6e5859d6a9ae902a8938d30046c1336656303638bde8554cdc812e73beec070c889562e43086ca28f1eeb43bf16f13649547cd19a3b813bba1947936b7819191225932a4206d72400a6ddd7bb8155d52ebca384b4203593f8484c53dbeee8d0f7d5a64eae947c262fc8e3e56557c43259284b5ffdd37f4ecf140e242a06fa8eaded0bb40ff9fa6f11982918fb91a1e4fa2974d33382df54df16c70ba3f2ad80777cd46b786ad125ec2b612debd77651aab187acc40ca3bc55f3ad2aab307ac8af551847aed2b5263230d1689d9920a011b809f18bd2756920b44eb187152311a0617af90f76a0ee306906afe6de81b1a9b45644b606029c18a3e288e020f7a0626066e3888cf9d35c4c4ab2ab3efa0c7d1aa5a3a976233402308963a4040e4c6338e9b15f97b9457e4ea5991aefb6520cf842b44a120556568beedd3112c448c0419fe2e92d746e049e0ecc463abb667b1f57b544285f4ed43119a1ab6415e331483a32265a714a8593f8191377450bbfcf0d9a7fd02622fb9f280d73f2b3a89ed7a726ee84a84355ec5854421dc83a41051b78c5a2240a9e4ee9df2fd591dc0b247d4ddbacaee3155a8f6fe0af22973f48018b970f4801a59f9ac122b7d963b524bb0a7d7dee1c37461a14ae5879b8841785c75e11ca26620d1b0fbae0934062251eb188689c3db6b0410918c268560381f600db477ebe81e15db9695a33adee19cc9c2105b66116cbc7a3cfe12826000af191060d8c31f3b754dcf2b7dfc29c89dc0a8f452bd6a0595ffda7307a837b82880fa431b2095c04c236b64a6bb8826f94bf65e1bde558b5141e8f9a49a56a0727c480cc48a102aa122fe2c6ed3b13d09418e49c581c9693a0d114c79fbb627d7f73d9ab7d11dafbf04a44dc14ef67c2fa20d653db96917eb04b7048f2c7cb220335ae0b7b773f29f5b0b3f41e9576ea8566161b7f7a090ff8cfd15b0cbbf488a47e937fa9e0cefb7af0209a8aa06070663aeab09c66ebf85d2601ca298ca9c5da85fe7a60621656c3cd89327dc597497a96f7902059c7c561f0ea82c0f106c82c5f43a5ef100674c94e17874e1162aee59238911df29e9cd2da27723cf7482b652491c2cefb68a2839329d25282a5f261dff24d0d6f7ccafae415041d8eb2790a460017dc3d57e8e5428d621014452a6341698009d85b0b509ba5a370e0111c210c00a0dbbaca63762112451df5eb67a774513cbca03ce83f21302ad25073524af3fd9e9f75976a6395ffcdedf221fc4e38eb9816b3f321392e7b1ee886be1492ca0b04bb1e455e890e37c368145219343a3e6c177d005ea9c6f0a6d5c968ca562393c946df434b98138d8bb08b0376594fa5d2afb9739aa4870a3c400a4bda23c6d1a2391c4c021d7998faab8f5a3392f682deb0490094c8c2240b0a87ac859c3da08110262a57ae8a0b8132b7679f2903b93e10821ad2017a866cc2e72d8471f7d58da078cacbfb23d471b0e6675ef0d5815ae5fff46ce735736364c5f9a457a01dc3b4b57dc4147e5fcd0b015497ec3cfe6a820fa24d39d40569b38109e969e03c0714cbaaae3b8897b2a0037fd6a291c90ca6b67483f6c0a45a8a981a040b230c81042f0795a3b15e65c241a0d044d4fec06cc377c6e88818af5b4cd04bdbf570c7a203cd0acdd805ecaf04ae8726da8f8e4b32d73d8a14e0025985ee4e8c424c41c8d7810ff1b63a519fa2a4656432509495ba112a33188109cc03d5eb2c27cadd17a6f3e51fc6de2a1704e521bc4e26e8c70ec26481394ad472571a675ea079be2104d7db5b041398f1dba34fde6c1e23ef59c081802cd40fc93ffa1c7fd8b01065ee70a56c9ea71354127bb38aaa1cbc5af60f3792ac8e76bc70002e7a8447c489132f88846aea3547cd25a23ecb9f48e7b462e1143d022530e2558eb518aff0b2c6c5b4ab016dce6ba8478511528c42dc307016b73702bf4420c2e850d8b1575eb25bcebc5937cd965b31f6e2a7761a9721749006e40ff6447670b72400f13bea33eed5bd4865300aad7b80fde74d8e065c91579815da08a1bfdc7ab21c176f1ad1779870e8d04db51e9253ceec0148cf5a15e337fef96ee76eef6fc6b167464f3ecef893d546c77a86354cba301dda1833c7e90714ce9521cf831a25a3e713d00fa54dcde23d826494b8da51fbb9f37f8f8a686b9ba9612dc38554ebee4dd4a0b78bea197f97761e5ddc60a8859fd1966128e49000837023c7ffd9e44c9e36440e6c292d801c9bbf7e0b143e1535b4c6d485ce9033ae629686b1ce2b7941cf00e139bdf4d32079a816c4f7de894780237bc13c985d91a48f73f0c49cae33a7c01eff1df7ce931c49de2a084c7ccdfaac751cf712a44ae17924a9a3e9cd5534c96f4c1bd4052c15cece6375d653e2ad5cdf927fe5cf8649939ba59a744ec0856b0166c612b020077a539005fd6bd3990cf09a0541768f4883a76a2ffb3b0dd62299c6c2bd5d8bfe2b3b06cd48902178a3dcbdd00585c92dd08ea33ad88b2ee539b6243ea741184a579c2064a9ddbf0fba9e6df84f604a60a08478c0ccca2b795471131bff4f7d2700668ebbad38160218a28afa92bc541857239207e82ed11de182e8742727d82f885a5c7540efb847f8875ecfe74112157ae505c2003884ef9618c18ab4ea0788a20f97cfce7031e98b983f5dddc509811f5f50ac0991113dedb492f27702ce940dc0ffaf8167aa6c35981b50c0c41c8a5e6849efd152313ff18654092f61682e999d013e0f5641559b5fa82c8f9baf3478001163ac17c2b0e5ba0fed261d9ccc09683bfda54d52fefb85073f9b90de991cc37a4c70b339e1f33af71a14f80850b6db284a7f1ab15a1b33c884ee14b8fff40e1d12130f45ca9a019eb23084b74e47d7824893436fb7d2d87427b362f7bae42a7d1615b4846d03a9c5a5eebbbf58686293cd81d564613507bd099140091a932187066ff4f4aaeded7ded653af09ad6a160d1441d8337c9c45013cace1e668fa5453f5184cd672a20b0d5a1064d1c0c85271d84f4a574e161334898177c618d8688aff409e470a1d360ece4775ef23a62c3b48231d14b50abb2ca15d4b81ce7e08992012e3b99381be1b30d8289239e90cec3f8517d4e7cfe535e5c3b95bfcb53c66e84112dc236e3896552291f7d50a22deb29376568b4f372bf715e4a05264c616f58dd5c49c005b80a54c02b655465ac8015fbeab2580073c516b455101f428d7b5e6744a73293d8949ac894528a78d728f853325acab99f3d1cd213ff5fbc92ea9c574414ebae4062b3cdcf6b85c41c2264dee5a21e600a0c6d549e734aa86acf29392f7e26b69e6d45db99f90843e8d4ca6437f8fc8adfb1c78fe0a7df120ef3cacac068fef789d49993f96392302d6d2d3d1545ff81deda2d8ca66ba591f1b0f57b2bfff278339ba78922933771c2f4e23dbf799fb8c0de5c6b8c795b3eb61e82f89d5ee2fabfac2a5fbcdad367f0d616e754a9ecfc9f3e7d1ee5c967c67bc329b77c8da71acce3769783704452bd9883a8f60f20b868e36376cb217fa0b687d7f382ba5f76c5d6d65ab0f1ab97c63a4f122878dd80b13884f6ac7edd5f7f86a329a8369ee6f1e4aa1513a55880a80688488cd4b9ccef1577c8e1e4dc640f14128a3381271c8cc764ffb98d87ec9fcb986e4a5596fa16934de870751cd4c449e6814171295b8cfa8e1bf3847973a4161c1ad7e2acd02498b07c0cb774659109eadfe06f62cdb997096a2d3e0fb28d817f704492b72250103525a1b102b6fc83cf8f35a2e5c13fd4a19aba434bb4c4cc19c24526bd243d62561ba1abda115b278bec448e5cfaf12143eecd88bbd0452de4eb9faec7f61d5b7ae7d25e53e6a7855ae946bfc11904103f93d65dd4fb16b19abbc3c87d55bc5d95c9dce4e81ee7dfbc784a89c032c20feea9285ab5c5ab5d57a060449613aaa4c8c98becc86646083137170aa40c4d4f8df1802c4867e5ad97981131118816bc12e7e5088824e56a8e4e0f0e0ec01dc74c9cb256230908f5019a0425de66148512a9fa0fc14dbe98f7ad37845736f9213121f72f2781387babb24c52541e5151c8d2ee63a77ddc1e4c02c0d53b3846378ebfb0922ab09476905c9bded13f3011a62442dd59acddd61051f37b8a50eb2eac64625dc1f401b1647e91ff3a57ae2947dc69bf708b9e1258e135030008e24932c588b8817ffb111c99017f27149ea3858858a5f646aa8ae05801e70f78e0be1558a004cd105ec16a239642507a993f42c350a405c34bfc50823b137b835aa3e580cf582c14846ccb6af8f87a25fb3af89d9652ae8071d75912e00ae9a514aea98e782630a51218156b33a0ad6fac81e303b66ea9df1f90a68f4567276d3340ce99ea2d372c8775d8a390eb172c290621798a78670d8534b48a54c6ea8ec4de2bb6a05878ebbb45441328a83b023b4f1b6385a4c90e4ee0ecd32da4994a4027da953b101e1567c8aad4607a8b0f4541608eccff8e05040bf935b0e6a0fec2380a5e7db73016bdd47f95530445099d056613e94980636d29c64b04c3eccc15e2cc6f688b2d80b8e786781dafbb680877cd33065aba84d9a0947ebd6c1dd20b79fafbb9f9a776e2f9e7eb3484277d8b8f16a6c16102d7899334d9a46ab46d9e560085bc52aa094634c956c976d058f0f477f51e1583f4f6d7b40f0508321c135b439fcf0d7112c99ba1bdac3049cb6ceb5ca6397dbe9a97a145015f5d49ef6f21c5b9312204d1a2a254d69d0aa0941a4f2e03176470e6de5f010792092c6a61c2bfbeaa8e595a67b05849099ac92365619e48a60d22cc55940f731e90b790bacb1a642068ffe1cc5fd99e58cfff5a6b45a230667898e5319a02b9d6d5a25a6c9a59e8b7525b409968adaf48ee48490329767e939bf88a8581d087faa920c11ca51148221763c85ab0dda68aca2cc060cacce18419a209bf9b664dc9a561b5d63d37c402ae8039c874e571e701a820bc8180d4733cd2d5ceac132d7f1a24adb5cfc8fa1af19a594c305cff9e72ff478f875ea733500f1e1ecdfe966d368c4f259f832d02c8401f08c7451d54ae7ebcd4f5bded2b862a6e06769f41c9ae3a13f44591c4738f9cc24c682d05e71681a634141ec20be8da55c9c98d90a710a7c30e1f41b1874605823f5e8876967c2ffe5218c021e92dfde99c28450b929f690dd20a34b8de86136ecf1850778916300c9b0344f4b3347afa822348095534b42c6b88d43e6c2712df74d973c523cb2a90282481967fd3bd676d466d8d2dc5c49f669fbfa2016149f6285c55e8729c9c563359d0334983901337ae401c598b777ee1e144694452b03c6eb2064a2c71af8e7d7199fe00c5720edae2669585a9b2c5d5cd38389566d665081182d502c9b282794e48b0fd48c9fec62e9325819d92a48950c732b2620dd3b18ea6f723d3810de91644305c46667fa6ffc73d5d7a71aa77f0f130b3e426869720aa79984d655ba0fb13102130741ff20c8e7efe38743fc6c596f7efb436be37ae4f3c4a62779526ad4404eb1dbf1d456e97ce1d8f35d244ea6f0c5d6182887731d5d42a17c667ca28d81d768e6429f52a0cd66545cf2dd4947680562afa5841fc01d525d3c97938a9ba6584178595ea023199917aa2abdae7230068ff172a3e4cc94b1e0c7d104a1176494711f87cc7c7d9d8daa1ca060d656f529e56868d2cccf2c66d3f99d587dea8c2a90afb2d356514f046ac311de8d523ea5054a1c0266d9f7323bc224c737b944eac43b5c27cc0965b2613c63075d610004b195d3f5d2e73519557bbf6337d5b46530d4d95ac21c533f14fad8b6c509e301366a20b48ed3ff97bb5bc0c084cd90320dfd2b4834e3a8c19d95a7172ea7a14b4b396f820e49cbbc76220ae714c00cadba039da0d55448c2c6c5e35fde641778fd1f78898d7ab73ca2b0b574ba0a7dd254ecc53c28dcaadc4459c8dd6acf2f7b6437b10abe022b3d47cbee923695a3ac80256474502b05e481afdcce2ba6f87ac7ed054d5b6afe960a208bb5f4b1062f246aa795c1937ed71706f1ea53c4b006227d44f4b66b711c4c6417853e2ba0c13f8d2828b43cceef66fd8d28e022cbc2caa80e0ee504ff3d6525f01b245811a47c6debd6c8e5efb9e4d761514293cc217e7462d9e6e4f01171e7638cd2e1a0b1caed72c68b32099e014702efe5cd3742bcd4bcb592e7d14f23ff6e863306227b5500070bbff9870a80c36b654be6560d0fca256c74fd6d6974a6f61e0c91f9382ec11c46fc4c47d1cb28e2596be6b2031b5f19b95012896cb94bc9c04cd882ecfae4f60f13926dd2c765c3a1b8a18fa20a01fdcb7aa8391cc27235c7c2557603368e29fdce3d6155c4942a652887058576c59485562ffa36c3c7921072233d93c251d0069304444ae52397f8ec0b90218713bd1dfc11325d39501406f94150f72bbd88a5a52702cf62dd82998fbe2eb88249f7d47306f393e4db08c03683c7f6e753c19324043d55730621d981dda5673b9845371e20e3dfd94a386683b67b91ec8dd982934a9eeabc561344a0b034d8fb4b9413eb09f3ac12845855ef8474fe1637f80c8d64855b04ff2f31cd0041b860d1ecb4edb8b8878022f3a80f72bed4491df066076a0ea04ec4e95c8abaf42f569920028d5eae56af6eb77ee9feddeabbb10b29dd09bb8dfe7509e874f571573af0a97032247cdcfb2afebdc9f1df03da42eaa0baa2d86783941dd3601f1d72a93877b57402ef1495068e411774e801da8569535d60cc606e0ecab139ef6bb21f0a9e29e51fa2ff3928ff8ba77ec75d96e1d3fab98fdc75c494fc0dc5769f4bf29156b525e2a3a3a3a3d799c14767461f3a0d2f51fb93ddb195829d18f155656d17823775a71c572f19d952a64c222222245f0504050405310b6605cf16b24e763f4533765c941b0d230adb85f5c2a27c577abb17dca681de28b3f7d2d36c458f526b5268c824f25f36d916cc8766a04b44d809225096b0309348c139a5e4a85b124ad1a378450993122345e66c531706e6260966038603db01fb316dccfe101b4577c03058fe919419a589febf0c49136d70d9014f765afcba2837f4290757bf3c9ff98a4f2b9848d871f71657632956e1f99c912cac6a01c450dae6d1aed6355446354d171dc40f7def980fb87cffffff63746fd3455bc0f776f317869c81bcc0b2ecdca1e996181a07df77cdff77ff3f0658d2c417bb5ea14c73ce39f78cd8f5eca4c8c289bd10311c9eda8e3b981ffbff0fe256d2c437bb24aee0faf8a8f911b463868dc8441282c5fbefb63cefff7bfb8ab06ab151d6c259b717c01b7176295f273d5fcfdded80293cefb6eaf23fabc9b6303ca88f3b56c6d257d2c4b7dd537569b6f40180929cb1edcbcecbcf8b1049135f537569b6c4200e3942c168ba7bcda6862b5b1204863583bbd7489af8800f369226922d060748099634f145dd919db5b3572c5a01f69eaff84404e5dd00eb3e14b394d20123e3be4949ceeca6212f2a869b122a27a81848304792d2262e285500af6814e47ad5576c527242c813914b67c2522b5e99292998e6fe02bc2253928a37c22b3225c1b0a2a3dd262e4b7f121a4232b182c0c4c712932526319888ec298aa2696103a6699ae7799e27ca82c1bd5d7404234946894a494b940c5d045d14758d263e782024242a488e2e23475f35a6509d48f2818da059e4dd004b596e216941248b848a9ecd8dab293b592194802012a553c3c175bbf1881a321b47971d5db70654cb98530c76a2b336efd8d65de775f2f5ccd284458da7ac17135b26d79329ce7b22fbee3fb2a2a3bfa770b702ef4651146df4896743233c577777df3ad758829a49c2f30248cd16548ac5ba175836a8c500cd18ca81e44a0becc50ad88db70390a1fbdfdddf9b1c651074b534a3444f842a0213f14f4a42115a135c6f7ec5a227544649f8c7e7b7a5f92790e483346504cc548eaca62a59d31100f028bbccbda6a2ee0652aae1259524ebc34f8606fab0f19e0fdc8abbfb4fc8bda65aaf0987ca81e83a898104303b60482aa4607a5c605db84095a9d483e6663613afd6dd2d2cafc8f41b7afd15997eb953a7c4c13acb6b00b6bd5081889a255a814545232f5ab29ca618f45734ea79b9d73bba697943dc7aefdb97c09d63091714984ad88831c1fca090be2253891828429c9e6a506a78d472e695087a3c0101b1819061972984cca142bc759002670706e3c1d0ca020d18314343e3fbfde404a900f9d3f6f823cd8b2cfcef27c10e11542e929e7cb1706156d100a9343ad857749a11964746771d5f568e2e298ee34b8eef506cd29244839defc9c59792495583850ea15003e79aa0d4bb6d62deeed66b76b4165e09afe85493a23f88514edc6a3698a62c7d993fb1ea888c10486e766cb0780162819712e87a37593f1d404d399388600b02ad0d6a823442448191aab9369db79374bed2d9ca2b328968f21225f01e131bddc88472ac29fd93974e46e8d88890430321456086bc58e2c38c62b241591981810a570f244e5a0ca9605041318da85a8d80e0c45aa60f45ded92b32d98a7809f64547377401fd083bc0200711931a2a881c7e1eece8cd44e237da74aba513a6185ad28123478676bd59a838d524b524f850e3bbd1204a09a8a30cfd1473c32b22f87a83bb1d0dc9b2c265e8adb74da69825b5c50aa61e2124825a193cc6890bc8649211fa095c3f9e12a7b6a5825774da1a2ef5fbbc5b144d97004e09080c152f432719fc87953b6d71cd08f08a4e5b335e0a5ed169eb66c4ca05958c124c09e14487ef9d840b25dd3133b5264097da1bb6368402103e6c6d8a5abee46862322059ece76379a858b5f5e96898a657b9581327cf5439b509105cc54b9b68bd553037f94075213e5cc37de57b1219b51af21bd9a9d331564c0e5341940359293ab097d6203aaad58508bb794e821ee4f68242184bf6f3cfaf1c4913875cc7f25a0e5f3eb7c4b0b200c2a16bf16302cc09d801da19cbb2b336022f648248b820381e6693a29c0ffeeb37411277f7547a52cb24184eda81aa2e1e3b9d1723944caf5f83614dc8b87df2fec8e189ae1c958641d9c801cc27932a4109116b4577fb0b6765d4f96077e730049634d17598476e3e6552ef6ef505f7be9b36d24bd884186edcfd7f168989e1fe0afcc7ffdfd584bd5f1ea0f18a69b32369622fea0136561fa8207d48710096f48a653f02eaaacbb7274f9b6cdbc18e112e1949b6053154d244df39094b61845c6088765fb6ecee31b97689196281780a0f77365597d2530c708631e3c68d5d46d4fb6ef945361c7f240d74efbbe4d96316128f50a35b2c76337e2c9ad019506a4f0d28a127c7e22bedf1b9f0fc7642b064d3d14e85dc79d8f5c82215304a0134eda270d114306d672ccbce5ab6159d9db546436a5025ddb0856db120675cc6a89179e939e7164a088a086a97622f67d81bc80f081048f033f61d47ab64489a6883dbf91122d250b5f3fe1229ca07322f85d6f264da61fa6112ca153630623497788d7194aee67f8f1f5cef0fbbb069bad30a2e977e7c49c897887c69e74b3d5f8af2d374dc64ecffffa788a676dd2c365dece6c68dbb678d331a432b82a3a3940e4913793cc70eb53a92264af1489a585ea539e75c35e51863f7b2bd28c6f0757777de8da489383a3cb9210d3cdd079ea082e06079f9ac98bc7fe29c73365a81c39c0d60c8b21272d09973f1d2082b438210802254823833e00b2a131dc8b3920e9f65dba00a2e02a64057a1ecff1f0b3d36fbf7b14115085c699cf8740b18d34273174fb54271562ad54f24979bbc0b077717c179147737d93bde764db7bbbbb576489aa841cb5d75c925060c346979e0c46bb7e3f2a0cb4aa54b4963fcff8fbbbbbb1be3ff7fdcdddddd18ff3f366b603c9e5c3cdd636edd50b46c814bd189fc4e138f2946b635c2433157904c8b8ad4ccb4c91398fcffff213a0d43786c8f2368a73db06cadc1088f007a74f9d21e553ddc1d8adcbde543fa137b9e92a6babc8ed485e01e6b5ffd5e2aa3417e0e94708a1e84a75597eeb1c1976ab2ad95ad6354345ce9a058d18055eb8130e411d3603574c473c200464f5d312a60b0c563385599a0f963deea09a1f7ddb4425e1b3b56410c63ad964832425f04828939c31ec224d9d686f73e5ebd4978a7ffff3f02e7fd72c5255c5c5d6d60f35245c214e6d8288f7270ccb0a72168ce14f88a483339975f652bce8c953189e34bd3154be13cbaa8b0799957a4143cf5ff1fc746fe9f48373cabbb7b9962097306eedebe371b370a5e49a3caa5adbb6849ee74b9f915dd80e12e29745cd90585ade885130d86aefae9bb946b510655e5aaa6b982b8640314872faec06610a4c4870738203c5f126e7e65906f4567676dfb8a453e5dace9a3735b70c7b2ea2664a8a42689718596c56d01d758d570d520a9f152b1a763efc7122434ca0c67cffeee8ee275f7d114fdc645d24424eec5dec2da185786c586a43d8ea489f9dddd2b64df606566c7677e7c46c867889c023b3d8ac8b0da01c959b29678ff3f678c33ce164c252a3640155222ee8e0acd4a9b212f02896258d2c42bbff1956dc4c449ebee28784a9ae8efaf5674c2ab5f5cd7dd96ec31acba9458ed9c2cedec063e2a30b884a593b5865ec8291516231b0be71f47bd92a282c1c99daa9f6286dfd5a61cef7d376da05c4e08814b6fb688068ccab26d538f0dd5718b35711086cd72e63df351f199e84d4356a77b200a0f0f5eb8d8a1710536847518e1b50376fdcf4d40c2f77564f0968df1e3131b4935bdf81c2f60cc820392343128f4801b7ac8a9b1ac982b23ce2b36692033e2a4e70cc665595a7f191b3fc9b2bb075367d1941d9b466c9be7afe8ad885a61b582cb45d3ec23073f9a6c7b2b6922ea49683c01fa49a014932e3a0a2f14613fd0a6154808e0adf3fe48b62cdb7a509123533c39e2c4e0c8b86713cdedff6f88489ab8eb45650f37561fe42616340a58416abca2ba948f531933665b0f323a15d5e58364b612b0412795df77b8fa6551f0eb854189f946a41e686c37b25a8c150f18f070e0c184ce6ead01f1091dd4cc43896191d4c30cce07ede1c6d38b02967a3831acf08a46414c4848210a752d1f3299b62d108fb37577b5c8f7767777e94b4c482034c6ffffb8bb5bedc61868059fbe575ce240c61bb7bf89bf1492391f29c90ed3553d1623d956f88a4b399f292c29e49feaff251c51efbb3a69f9c47b2f14da222021b95d5afa79df257b3f9f49804b72d4a513042c0a620e6fb4309a2df57464d9042167f1ab2e6511da28c61da07eeeffffffefdeddedffd946acc753f41fc0ce3e6deaa00c2072e4252a4c48842ec3ef7a38d0a71ec2586377dce3924f27e7b114fd47adbd53f8ffff7790eaffffc6eed8c9737c1276781a064960f9d897a4b6cc4e1d3be96454872877f7fc18bbfbff7fcc31c68f3b0d0092955b0956dc89073fb1ed247c2d479b6c2ea34be5f4e1b48c30d5f4d14b3c23b08fe0ea937568cad180f11d7ce48ca2a40c873f0b58742ca8e95a1c42af2ca0e055c5dd5d5dd17bdf4d671898113193838189c1439cb28593cc546f11abac07a747a787a727d733d4a3ebe1ade0c7ed2b0ec5e395655b1d3995dc2a550209a6775e712d64785d45576ad2bdbfa2339f90cb1362a2520cf677ae8d77a0aa4dd84dcc8dcc8dcd0dee66e7e66745fb2c7af199b26d073f6050388ca92e8f532038cd588986eb7d576567593ec333b65552c2bdffff8dddffffc959e38cc8fa5bd1713edc0f07c4057142dc30a796dd5df1e3c0d477b655d2d5b09bed6c8e088cd956820abeff52536accf49e6951b6dd20e8b873cf049ecfdf2b2a1509ddbfd8c6466c464db6cdc5e4647236395c6e27f783b2fef4628c31c6d845270a2369628c8c0d6ee787430742a7638c31761de3d9ce6787a4893f2ec412b53bb7c7c2c127aac5b4600277c58e1241d151f41b3b244dfc1122da71b8d173cf15dcf77f24fdff4a405eefbbe499babbbf97477db12f1420a4206905b3a68b437ce904ad89a104a5200e0eea220cad2bdb720521b8d99db9d85d01ca315fce6611a14c662d7008de64effa9f2fefbb15bc7b8165b5c021f863710e9b55b6dd02ae0fbcf15474ad580efe9a036f6766db5a0f508ca61d2b62e4f8fad23295a63098608dd24bbddbf1a8040491f3886fa93905fd22c1ac64c476c66eaa11d390e9ee5ea65ed98bd4b04d1f615b0e5c3aff69aa858abe5573aa936d8b34863245e74064085d7b5d72c8129e6fe678ff03554ac42b450557cc23c661080ec659096b08c55bba9226bef791133e6afd3a65b9e0bab879c15a4c494ac6b3bc18014982189900186729d0b112aa6a13a82eef8b30a56b51386908553c12b0d619d52f82979275e52784307a45f151052b57ce1c844c66a5b342a2c024abc2eaa86bd530acea816da58153253c310e3a33c15175261602d35dfe25d969f525377cb5b630f7414962288f0741f15309af6152170f78275c84351c55e7c20418e4eeeeb20468f414d5fef059e05a60fbf1086518d3d8388ee5dea1f3becbba8ec358758f901c791d85ed6276323b9b1d6ec5de660c333dc2913471e767c39150cccd39e759e3fc4d93ebee6e21199226dae0767e84360811a9effad7bc98dddde5ac314d0e55052715fdfeff67de329a9dccdddd9386765e77b13bd1bcfd184f312265ca2b07078c0c7ec2bcee7b1f3724b8cfdc4c2385b3b32d11101be0451898938ee9868b0f493552509b9818566ed345e711f3fecf62d81dd324e94e0adabd5fba54674e0c3b8d57ec441af684987f86f041d6104cb64de2117aff83521f361fc3fe35efc7ca0b2caecbd235bcde774f3656e3c263e42c496947acb215f9bc8832d1f5f2e2a3c99309d69ef4ff939a70efff597bdfecd170cd0d1527f944bdef923ddba081aee50020d8949c52c9e4fb1470c35430cdacd44ec5d9b60a6321368f4d35f43df539e77cc2dcf2e1934ac510c662e7cfd7a814cdcc04f24363523595720355d0cf09416a6b928f9c189318db560dcdb4f1d69ac77103101e9ca66352d42fffff6ff895e9004a304bbaf18a2073faada82e4f0200ec934e4586af5136190d3406646fc4d41fb6f5489646f962516acea928b2549ca6ff54cb2894b0fe04c428a4c4fa07f06556d487e32c4ea85ac33087501ab8fcc13b39d051e250bf324591bbfb06a721db16f1b4365a822d598da5318e9eaa5af39134f1070c0a35d486b9e51fcd39670a27b279bba1143a778915d9cb293a9226f27c3f60bb4c09760b859c730e41ae050d24389f09285366703d66604080f12a063a14d420b5d531f70061f3fe939b996343e1bfc4ae5262c7f9ff3d646430078c7cb470d8a8b81d49b90d7bdca250a8621f3bee1149ca0ee3770d333fd145d361985061f3e9545434a2043fc66a8af1cc8b31c6f8ff1f638c31c6dd8d7b3f2d56dcb86543d465a5e8620f173c475b376ea7c0c88894145340fa5eb1f742f8fee8fbc618637335ea2281d7d1ecc5b07abb2734114a62624689d08828b51f7abb1be3ff7fdcc18d132670356e435b984f13eb2304019e966be3b3d7a3d380968f212d78dc380961fae0a8cc88b15c705df7028b6bb6440072cf23d311b04708d0d041d376c6b2ecac85d2a3c1c3f67c46ac44ee6ee3fc312b59b4750a33c886ca48cb2021048286a70db6fdf1f5117b03d542002877e414e27d042d68696955ed51b2aaa6bbcaab1abe8f66b5bd27cae9a267d9903411b7f32344b4bb20ab77babba3abf78c0f3d152469a2f082a961cd76bb00084eab4eb3a2a3958e158f55ce6ac84a67c573b3a2b2da383b5a34c3858a0a092369628ccbb0362dcebde06a8725cf72cef95c5586eeee26562f324cb12ff3c85c35b545e7e27d46d54687e8fc1c9ea2db3a885d3f382f2832a4415e8f78c98a3e04e7546accd5996d7369ce396370aeaaf7c8dbb2f2f1ffff89d84a9a28801af6b68e3e5ec005fc570180846df940caac00c916af9beebed5eb0bb6a2589eef063b34936e38614b9253c10619de055a37281c5fdbb2b82c6ddb8e9b4af4028bebba2c553c55b9aa21b10cfa7d799aa25305a98454c3597b16c6e6d5ed0ae74ae78ae72a8767de66d011d5fcffff203f922602831d8208af76b4ccf11934cc7d926c5b2369a2ed86a3630ecd96ae8cd0eca58acbf137a4aa51d96625fe7f2b1d491379dec1cac7ce6650dcbde503f9743650e7ff28831c8c35ec9196c3732846b26d164f079834a8844ab659a906208000431a0000040018088224ca5a0a3900140006200a7194a068342218c6c160281410842110c3401085300c0050108681184e6b781e28f77ae83bf3c26c4f964f6c326b70260cc4e58abbfc1c38b37b87d5071ee9dc822a4de911ff85b698201befc3219be418421763ddd1d29a4e280eed523b2148f1c0d37a72bf01f54ba9fa8daec07480f4bd49c7035bebe50604d946d25684966fe1f21c9203b08854acf2518b9020ee518746839d961da51438fb0c60f74a191931495bda1a899b26549bee3da34dc723867f735e2fe12c845a58fb2cb0789e58dc65ed14f39b3b04adf7ae0fe13321796a12e0312434ab64ce8257cc091fa340e6a503f149a31ac859f446e78c15964800687616a2eb8289bdc5ce494099d72a2dd71d1cd9ad64a36e310e8be2aa104e02392f4cd17593b468f4be6dfdcae1a073038ee85216ad7879d552f2b54d809cae5aafdfa2a355b4a468c38b183111d632d0c648073f5b19ce1c843c702c7869e89a265682e3b2789ce830541182fbb5333b76383019bbe0f86ce3cf71a4843fd2f30677768f74275a6453f858ddb82fdcc1009ca75eecbdec762db14fd626b97ff237c5aeaed50a7eb7101eabfc7f22a5161ef911df3a3aeb686d6e6bd0018db81d88a31a533f7ebca5804296a259f57de3b9b17411e67688c974a16dea3e28cd1f9b152e8656d1c32d89b9759019d086514992afb72a9395247becc136a20d493dcb8ecdd1b2d3b41036617965ce5f5ed9bc833e95645bfe8c6442da261afc1be68b2bee4ad25b6d948719e14cb9dab6de210bd2b4b470a5ec0d959566745ed0c578561c54c0f7a6f95749e14a5fcfd375e041a9ed814b1433ae234aa18eed565dbd3c58ec7866605283f251acf0bf4866d080a75f5bc8f026b7f0d0ba34e05de40cb41a8cb4cf4b1bbc4c17eb34cb5288845b49f87bc832d6fc832612da93469d13e8f794042e6f38a1a2a5350ccc30b929f068dc674b3884aaec5c748628511f99327f84c452a191f770ca8fb3701079acf670969336ae99ffb0a22fb1f94e93c7d1731b8c235e4c1940ee799ce29f0582a852a95252c0a163ef0b57fe304a55597031c54cff8082990eaef28cd1a1ffc23f791d9a567c00d9f96ac1c3ef98f27965271a09f1d7fa118d121dbf615169a85e25a9937346138f15300cc4cf8c7490240f0bebe5dd6e9538f05c36a40f7249ef22fc9bece9e8ff4b20d4b042c55f41e31bec2265bcad08412e668f3a5a4564fbd1d51dfe0848a66051167d8301cea9962a01b8c20da40514722e0807b20076f6ecedefddad2d3a1e8c42a64a590479009bc48a06df8b6e71f5ed7e4f7e608a5908ccd94f8c12399cd16700aae17107e0050aaf4ea5854341a65c64cb9e294dd5e826b71ee87806670f994cde92280c04d83bdb1dacbef1e9b4812e435ce4bd603f0a93c0c13bb33dd9e0f6651e76e18b94132c057c1176bd404ec079145100cedd99f9d1e685af9d849b1acd4b8b40d084ca1aaf8b5db1b598036d7a5373b8c988a17afc7c7a221a003b5e21c665b5d8e738bc442a6b6d0eec71cb663641f10775852099f08816bc6d75e499aa13c034920f8aa5a9cc5bceeb9a8ca942b118e91bdafe9f89f0db5ce407802be911c91ca5fc8825da2350129cb8d6fe8d817c30aa422d78feb6a5300603d7f3af6c21b2b4f2ce1b838ae40a44b93548e7eda5d3a98b33a0d4253f738fadad259223315c88e084f82bfda87311586bb3624b6f33175651862f816c32ab83d71f25415d0766b1e08d4ea394f3d5504a5170b84d6677403bbc7c0068e95b71c4c5c9028f961f747e1d1b75d14bb48e4175839516fb3ac4770babf900d17414d82bc3f73e7fbe18eafd2ec3bfa8c19e56757bbd17d9654b938e1b512fafb7a6da8d9e8eea7d04225ca7bbbd6a297c094240e6d32096f6157ac6fbcdbbb09954c2994186442c44daf1bdef27a5108783c329db6c6be4cc4c0052c6f5e4960f187e5802fe4c22e6bb067018c73631c13590d8209a80c638ce615b5029e2d470e564f713bd057f63b1afa9c1946d76a5b0c3d90164478f08790d312a205b394e115ac4ab69d4866361d800e9187da105e329f64244f649184f41213027c9992993a41906a4b9601817b83424dcbce5fb52ec55988728418792e1dea342e3adb7c77a028e88e27be4e77e2c53c28b77debb938fa6d930df6a03bff988c65d001136a71e17856bd5602cc9012b78af4a746e6895ec8d3783e5077c140a97d18d8048d72e7cf805b29908e9804158b48d32334fdd85b93e5f95e26e893200db19fa83ce3d8f174bc1678873564b736113e97c85cf05fa9299b82ce2acd5f5cc91455218b72587e7ec27f1957bbf49edfe5ac0171cc58763835a04e94d56d0ca2b981ed721706ed82d2cc20a52724e4de2d34a3409302e6bb9a96143e7c112e65561184c6f36178f42376b0aed4b9e9369d58d9182f49e663557112be74d06d0765152b96a8d2b1f3cbf95cfcf6423032c2257cce567ad90cae47032a42205b971ecffc76c243c3978d801026879d2f307a281c68c73d573d7616229150a975ab07faaa97d029831be1a7488087f86250ddee76b246f4afffae8b5d8d8c2d48b9faff936f59c7b577b10bbc0aea42e9181c6fe2e674bbe69deafbf506694f337353c04ee2b4143c3c395c319914419d24aa17f33c2d2c79cd7e89a393e3f6f20e9ea117a100fe9a9889e5478f2e2a725385149613f89e8dfdaf41805784443d33805b489324b3239cde6ae36b5672db9bea0ec21de9a414a209b08d923cb8f41765a76fdbde51af45812b9eb84ec2703b66bddf074e925142a3eddf19ed2206c815bea59087d8661829d30622f31873742698adfabcd02d336383c828f99d422972e829bc6a8276ed07a130ee96b8a6c38c786efb641e1713b0ccc886c1b422b97a82badcfdb27c0d36dea8fb7d1a5de612f7e0a0acbb151dd838f3e5869c4a7a5f6edd763abd03b1fa9af0722276eab4f570190c7e05267455d9b15f0934a0bb0c0dc6dc8e5c59a39151bc005f4ae4bc0585d99b0567ef7f621ed6bf4de138b9ede32939d47c64667099aee0ac14b7bb2f4f30dd638841218d5683ee365080d9655e7801c406109cb402571cae44fb1417c636bb0f28fbb04cd3153d237b94b2091071f388d282942cd9d8223cbf434f3782789082587a95e8e2b343711262b25c77cfd2ff639b19569c5c91ee8a25d091788d6b8bca8903d40a9aa08b1d8d922191b4b5e889491a3a2995d81ad1f082b48882dda4e46acf4dc7cf503388b8a1d81d0acdb810befa2937e505265ab58fc0b44be66034a65c730cba900d480b18410810ee309a51c9ca3096e96e963e198c64699e2ec21b1cdb65af9ed3cc4123bca50934fe02633415f861be6b1e8ba124d1be713633a1c0037385342e46d1bc727ed46fe50fafb29ef039436c9c59128068cbbd4862c0b01e4064b6803ab77939b06bd35901b679792341294b19cc5f769655d01f873bed3b0e18c1de22d0acdca081f3800b7f1f744b8ed0eee81000f5b70e53eb81870d3b14c6168a544de105cf2e2bb2c917c93634d8a9f9e20594900da2af971b0470fba2cef31ddd08022712786ecc39666712764f1e9099f883c611829ae96c8f8c06fcf2f02ed53038b94bb3eac38597900f7ee594136c7d895129013b83785fc9de3bea57bc44358df1459d618106d9f293a63cef4928732d44a01bb0172574a4cf77d09916271ed13b5d1abf667996316954af20c72764e8ef7e0288edbbd299b6df804f49ff12b632d080618962006efa144144a8f6115bbf51de4c653e7d57cb9a8df6a860bd0d65cb90b7e4afb1a9f9d5079ae51bb1a2fc815d728a0c09b5fb8435ca6d8a8ad39eb8ef044da5d6e5d1dba3b502c03e0260087b29be4af1838c4968a3f86d7daf174ca1e1a1112c0b4a044ed75e9188d8c31d7a32d1707803f3c9b9ac1f30c2485c0d481d039e9a1028fd8f026b022fec2c08e0c2cf94a3088edd25cda97f308abd4af86840a004a8e68c6c7ecad912d05319984637b96779f3ccae52b056f2ad31a1238c1636f62948662648f640423735c3069e5eb6f832c8124dbcaa58422beccbed55a969ab84bfb0a06e286d67da566bc8d5c9e60f2ad003a89a65522587dc8f1f82524f06648d40ab3586631f01cd7655df2d11e3fdb884a28f55c722e0abb25c96b79973efa484afa8c57ac158454bfc420132bf778f50b9abe2250817ead28925ab529d7a4573427c4179a3b6d7368382c917d557521fe17f86ec83d66ff5d80ee05fd43374004c3e2007e090cf605450339922fe53c3a64e32c48e4673c9628c78d840d6f1fdb24963168353219e03c063ce2e4567b1bf6868370bc1624c1d7a5d90760bfe70918441cccd6899d01793bda050dd7259a1b3473bf47b8273b165c62351fe200e52c5355518b43593e54860082ffd71f4acf556d40deec4782491464d7fbcac802c3b730b122ec7fa8ea231f8c2e9213584549f22457f18dee641f2492b0323a90aab176ea1aecd2c7823b93bc979ea40944c08046c4d45e9ce3728df408ab2d70b114dc32d926c982a373f0d266009e113dd546d0be68ec27e945fb0e312c7b24b931ca562736710a01aa84b82679d102826b6df2071a747d519459200ed6d2e49cec90aaac487da9543914f1a2ad6fd641e6efc3460fe224625028c176cdd7d867679fce30b072554f1cd4d6e8dd10bcbda63859b3c5d332ae43095acc298f4801dae19b866bc1c24dfe444d150c609041005941027ce9cb246ab6389c4536a891dd509c46132651b38273d6d9b046cc43a399c5a43abd4cd3ba7b196289986ca721ec31a889fd0c9719aa41cfb1692f51b305e5cc80c4b4e998ee4a2be0041642f7663f26122462d9605fac4dff54d3711cb6e46ea824383b9c53862ee2570dc6c0b5a03f8a82ac2b1d688fc3c0cdd29a1093894b94b387b8015fd685b02ee2dbde3d90c266320f63a5aafae49a189221ffdb9495e7ed187bc3c1c850508542abd8362938d84a11141cd91d7cc0585b910c1f931687e148ced7a639193a0538c84d6408485075c301812ef08256adf1cd829e2c402c847ec2a56f4a2a6290c7421d3ef441c7ddfad2885ec35037ce13840b654d181a653bbca5a02754354a902463188f2c46e228cb106fa02501510d729c31c1371c2d75c38f6294736455ca7d472b6a8d9bed2dcab4aba06a4546da34f1950aacd4653acf89116200e14be0a6c576637112074ed03bb4d5698e4057a66b0f26354bf4c7cc92de6c7af5413864a9604b3d8cc5c7e43167a3c97c1a77cc07bae80bd32ce36fc7a6e22ea113d99756398ffc51b1c851b87a38d3416b7ea679b51a1a95c0c43112381be1903a15da408f444736647a816196bf0f54c2806a85a48f776921b0edc095e5e0bed058c2a60fa122741b1db1cdb28ec601b6a7ccafa09a275819c3a825602f971b481b59f51585225e7ca58f3c807e0f93fdc8a2a666356f14de6b0ee53877f5054f4e713a2963ef908707c910adcf71c7f572139accce2c0cee93216b5a648ccc069a0c38543d9342ba4f8e8458422b761c920d46a43e63ea53052028b1ea6d1fea16d3284623f7b60f675c33e68540ff05360b3e2acbc8a25e7e37b1808e66de11c438c77dc04e86107a8146c01e2bae025fb6b6a2351943ab99d34cea12ac433b1280a9b8d022fe9e238387efc4629bfdc0a306ea7806b7675898d0a66c954475023f81e5b52e239e3a103ad026267c310872a5e7a734a1ff736064ce4a689a817a0dc48b60af5f4b8066ead8b3ec7c0a89e149eee863b1cca7b5ed353e178b48780e225e219a29966f0b634bfdc4e2311c4332110b256704347ae69029e19fb2301d3e5e31b56ba14d7aa28f1f9f4f354d2a9e35f94a30700d825e20fb405ffd8c860b48fe8720e1ea8c1d684988b6c5e71e5ca0b112c0b4de5b63ee9dc961dabc28c883ca5e26105faaac7f84c2753e60b83512b8fcedc012bfb441805970acbc0dc769e6ecf21ce7e495e4108f1329e35118b8694f51b0a63dcf2b5a7ca9d3c9a34967b6cd05abf2111c4932f401e03c22b22a37c7b06096024c046e239bfb12f96813a09a146fe95b81d8b48f55499c8276e83ceb63e1a095818a5c3792ab5420283c3def743f11943761c3eae09b2929dfe8a5153f26819a34b02608f0723d68acb0067e113a973ffd69e634354aec420ee0d75fb81a8019c2b4396ca1f507d53580b09100f73273747c555ce96dda7d8d135167d9fbec41784e06f6534af5168b6cd8075d6b209f7274c0167f92471cd67d873f6a97f81ec48375ccca39c614922715156eab3014da9d08d3eae1dde8450d2b7bfb5c9c7f40ec8d067f8259849cf87dd06057133d58f530ffa88c530ef03521cc2684b3fddd9c372b49ed7af821e01269c3c3e03f9769c9f9ecd94b5473d3e92b729236da4223e481172bb25cd1248ae9be174f8dac534b284ace184f4b17857d60c0513284941917ea0d488da7cd76920a010386a1d3a25b868fd463afa2b1fa8d22b0e31202f154c5fe5102f046c7f3914de57ef0fa8b6fdc43f656a6c5733ae7b87018247216e4272479aae2930a9f9ce8b405879c8220812458b27a41834b844c36b700303a69cdf98401924f7cd7917886e213877f81bc7acbb96cb1a6edb30124102ebafa51cde9f7fc1757d2026faa7e2e671c05f4a3f6b3824a495679e62445fa5560a8166ad24c830da27d27f431fb036b81acbe01b525fff80b225c5de4cc40fc6d412b4447257023be895cc253123d5df9094adc2d273cac77900623a05d9fa9925fb06ab1ce3f764f0c67daa6f7904c5ea602a0881349314d7f9abebf677da0c28fafd390c491b66978bf5ff228e32e8c74a021f309137cac943b61eade02ca946080884c3eb9a1d7a9c364a6318a3e3daccd7f88d3d608468528537db89442bf595a4894894361349264a7cb8e6ec62c64bca26f47eefda4aa7e1a9de92fddcd5345c1dff8499ffa8f023e74ee61d08def806787dca02eb06c839421e6b4136b32b2d978930102b3646cb3bfad04eda6180d7a019d5fd3bf7d05086e0e5c10cd151bd0417baf7268e6415a4adf99342689fd1e080d01898b3f2b00c1b0369c36ba7f0e2dd6839c568a41a829fdf0d0712a023c6e18d243b34a1e196024cc5b344ec53ef8aac783f4e05796cbf35652c21c719bc42d23bfc136a634753c78b519c988134ffbfa42ddead5bbaf486295a88193f47776ecb616d4acd1ac3de66ef8dad523e7be29c46379fdd072a1684f943da30ebcfede9e37a2e62fc4cd2351ce10453c9e1f948d9cf0c7682361ecae39f863e183542ab9fe554f12a9c0e56658c329d7ae69b770ccf10541502dae9327e1cd576a8b23c228fce917e466f3b0c4b627a430d4e522396945177a26469ea46ca8253a989f8068d9db508300bb112c0ba34c6064e503d501552136e9045a02faa0dc8b0312839b398ea4e0d85469ac123b8feae52c2b5a7a72cb4fa0ffa73d879c2a6ac79d8b60b9c2f76c7205709580b22ce267e54955e76034c871e0c71877c6a03dcf2a2507489ac1049c73b66abeab620d8a04333ebcc6377b6ba6fb394caa5871210903a042fe8a77dc3fd7cd6f52cf0ee6637839c9b675bdfeda4fea3bd2c3b75ada1a29d35d99d9387ff5e3f8d08307653bdc72c7d2624f1b4da3dd7b4199694dfa28624406d4517df1a1142c2600f4228426a060d078843ad5036fac8cf1b667f6e6e74c8058e8cb8ade69f05c27352f4e1eca87fbfc86d425fed006e282176baf69fc2e6344c0e00be8b1ca9ad78b755b7b434d4ad08a9307cfd5478e5bb5c6d64356233c260fd5e43ef7e1f3939b861ff0653e2aca156c01c842d2aa2bc7d5254c429e018cbb791693dce0f1e33abffc5d0e499052ac6217788390b5d261bd364b7420faad7c221c55b3958ee89e3b9eaa35c3ef2463067ef5b2795850cfae34b0b3f96f3516814f6c8a7d1824cc45284cf6f4b3442658a52c111265ce5b1545c2cc577a579ef070b5742b0b1ccde38f34b03c8394e70088e6ef63ea339269f0707c327a0bc8ca86e4ee4110965902e9e3dee7f3215691129b134991fc11dc3f0c1515b0d8dd5b5396ae38b2fcb65266dca63330b216a513f0fe57d712dcf9b2a38afd6a1ff7990898b2f6b053e75eb5f85641a0444e3e9ce580f7d28a825d6eb10d30cb0b05dcfb1017e9e9d33d8bb3f5358ca3043e8d08d969202d2047370a5f81bf8faa2e3d058324979fbac83b6431817852069c904057795513fbe9e9f8d04e43be3d2b1c6639939f2b249fabd3159a416c402c9963930136805c9cd7dcdd7eae9e516037ddc0f9aa0789759811f8e20dd98429be5e4c8d6b8f1b9961c305f4ec56676bf26cb1a1b495e908f1b2690c000b05df3d49abaa63d89b6d89a9d5236915d782fbb946ed6c5c7a9266b3d7052f4d7423387c3b1aed1ec2d9a0c96445fac033095f04c671dba7c3171e80aa8b00e79f4c4a72845c6d6618cd19b7458253d41cc8c74c18658e470e4da9ba3a712c73141f380d96a47db354d2d1a90c278a8271cc9b91aaea68fb8ffd5d7b52ad78cc757832e8b013ae9eb862ed82bbc4f73ec51dee2be9b7645665b79bb21996db7e9d0520bcbaf4e5f2714190aa44d49d24da6dda400a05405cdf246c2381364d4335536467f50d6a6a77c339bd741acf346c1a8f2a4d6d2e4865759332f945aa8674bddf27b2d19f990caae0878ddaa119cd565cfd1ee4825dae0e545cf041268562a9fe4f9c6e7e5a3977e2315bba6e6ab02914d6e77e9a55484ce1530fbf96b9ce529a7eea2c26b8119543a346a58257313a8aa0a0ac2d71ffb6109b744a0f6593644988848425fbcb7f5fb7482c0eefd1fa4e98cfc3b6e3d6137779e246590f8ea78f29b8409c10dd8514a1f09ef12b3d4ef157b0283762596395324ae2e8a58d4be24ae3891b718c804f4b94285a5e6cef259b95acd4174bb3807bfeeac1fafa96368aad77b124a6a17f8d784454b7b5721eb97819b5551c8bd8e786d0c8aae62a2c8dbab9fb60646943b0aff934931af9dfada8a4222ffee2f82933797bb91819b9c025aee62fbe6e15cf8a4343f15a37ad766bb8832646009b9d9eb871ecc193accb0f5c6c5c1e7aa12caabeec7b6891f11e9224c3e6102d3adeddb790b013a601408aecb73b9e9b992267287ae43e31c54f3436afd524a77658a152bbb6449ef2ecf372a19da342372fe756ce81dac61dbb7689eb0d29cbef18743f2867dac685e54b2d406a63029750ecf453c1821f0198b331535517cf190ecb36a074f197b2b87dff18fd14de373864bd008ae586e54f40728a8213959c94587b06bcd0fcbdd20571cb2d77e094b61aed6cc9a32af0243b901509ff58cabdb8081a7ff09164dca59847474f4513e96954ca90fbe5709442f264afd72dab852e41895581859f26853d9a42d3e477c2b97bc60d14407d7b1a69b1d33c3d297caa193c8a5ecf5c9c536a125e4a43abf1cbeb92bd8818ee9658ebe90517d7cd31c8349d8050989832d280194365405d350eb38aeac9d2bac6015c56fc3fd1b3fe9bd66cc413cfced72adb252d30cc87b05342e80d37e0bf821733f7349a3f0d8b6a19fc3d8bf2decf941e8d0ecf3fa32a297c3dbda838a9190e5f5ccae3f4ed7f0ec8cf64317037fceb65d6f94d67780d535bfe44248ab3adedf7863467e3c94a5e2afc9642611eb7506ceaeb315a764f614870120b9f37ebe9c995d16f4097f9bc3adf8020e9e0665ea7fedb88e012bca53c9bf0e89e73aff3e8554fb160a8e4dfc7baabbb23f4a4e4b4d024eca560846c45248500d8470f58f2a550c3340a7334869ebca2d34e5d76b9f9c62d6e1a11707ed218157f3b0a92440f2e25276cdeb1cec6662289a7979c0781a3547e994acf83864782633cb22c7ec4793a980c6155dfcfe004073ec52e9eab9c994eaf17ac4a6a21408b62278444beffa832319cda127b7c7391276042fbf61a00b8cbaf3add3473b47d3345a8695683ec75a47c09c18762def3a711a8cfedbe8d27d68d61a091d635d52199752fe0be7314b4ab847eae231aee3108622ada6a2343b3867ba3aea269b8623648a87f5e6d647ed2de9a78829bf093355508c6620c6bc43629660895c1044fad906e081945338914a51a85ace099f07c29d879ace27f860acd525fc14a4198e3e6738bf8446981a2bc35cbe5d0b7c03e744c61670e86946ce7cddefc3d718ad93374bdbf00192deadd24bbcb2568d3d317894b32c601298c37d52f20a06abb4f5afbd16a4ea43ec51833fc6fac75c42f6722252d3ff07de3decf0034acf46072bc04d1eb5ad1d00a09e541b815126a69ed24e9c4c1a2cffecb63e136dd5e51051bc9a231a470d4433e955535d27a5aaaa0ce7a1a573e5a751e8afe612277df0d12106b12043f1558ac82635afe313900cad0a518e94de60e0a1b00c3dbdae91294ce80a34d28e9bb82075b88fb69ccf027738169b2d36d240f61560c31fb8eaa834633cc5a734254c32a4be5bea18e994150513a36d0ead29f2ccb23d40e709a67d2144a3d4815a9933458f38acdde2b495edc30d4014214b197a1673ad4e8d422a1f564ee3ded330f48204b090a2b7c48222abd7c80559e707a1e81bb018859d3468d443527b78c13534e018ac432db19134e59071d6e8cc8c4c536c4c8b0d56519cb89e339c51582833a9ab3ba5ddf419c0347b8c16f9716f8fa2ab487f12374e0b4472c2450014f269721626d463695a87782cc1792ca5c78ae5dd83e98b0be4b62ada97589557175ea2e30bc7003dd3173606f8b75cb465911d6e699d7b55d642ba6ddabaccfd674ad959a9db7cbb960339c115fe847db33f60a14bcaa69e2c37d2d96a565855f0bbbea352f01d81c684191ec3ca0aee036eb6c6d771733b1a6a79f829a8b5780aac02d220a706c9882ca11e29e0315a34ccaed1a42c3234ca4f95efe020c463eca07801f6b28e940473930db09bfbdac6f0b328f39830fdc3374d9949fb36fdf2863eb6b2842388d46459ba48f0c0f9fadd58a9cc9cdf5d89db224cb2ebfd52dea376c698e91418e86ea2cdc5529f4b9965ebad68b5c7a203c337e1a4687e5e9c1cd37ef86a7bbf3178c29ea552c07202366df44a9cdde9d8d9838454af65d54d79a7923c194171c4bd2421db5c6a1a9c44afff14036202ae0fe80e0b23fbb6598968fa73df80b3e4e321f43894c8f0c83518ef12815d2a6d0520a96df70b63de3e94d800f21d760f8ff04307de1cea57d0ec75ee728a5d091ffd47b3fc25691750240e86371898a7ec95cc5e2d49912e3c70b71d52e22bcae6e09b3eeba778806fbc4702bf34a0df93438ffbc341db691e496d00eedf45697590ce1837515fb7341bd158c63da952a69eb14dc11e82d69288b9262490948112474ab7c9a4c202646094b4b8db0f63fa04881d0043d7145dba5f42af208f657ba05e6394869c97a424b69f76aa44c535980730a25cfc2a7fa85ba9255892fac20f3c263db0b867621cbe1dfa06ccb3ed345319a68922b41ff95f17729641da615717ca2bedbc5162a3dba1b24907fd1b84077dff801b46d5b3cdc4f623078ed9be3b718eef7e293c85bd9098c1addacf3296afedd93c93a228a0d05658545b8c1a8b001295f5a69201f82f3027f24481502a84b22c1c901649222d95829e168d60a073c95d41c12400b192b4d3d8f00a24ed2ad1d9c4ba269fab602991f64c34336984c922b190e5e9dfd0425c8c5cc91a8fbe401a995546197a420a1a871a816899b96840f439170bbff96043cb23b0b7822f9d0a2de7eacdd1f362ac831c5ac9f3078e150443a8d0f391e514ac7c910605073cd775f08ea342b1f33b87fc0a629512cd0f8f93bd014e8044b6f5b803667a4df29d94b01bc16768605f68d4afdab28d1f0cd8d2db579fd4ebe5151f79e413d0bfb452e848b12a6513704056da7d1b6cf74937cabd2d68136b47a5d7e58ae4cd8fb271abb0d200f7b2325992b31045efdb5ba3d3561979d3c2c2aaa7e802edd8762681f61837d725473b7d9b366b496debe2d629744a1674f2534c662f2ef459bc65abbea0adb641b52bfe6bd4a2c6d84c177f94a60352d3f857511d36a671962c2bda3aa097efc3fbae89e4e233f6f28fd89cc84420b4b3c48c4ae3688830b0e1c94c2864150d367f350126b4cbd5d00be4d3136ef87ef1d22a9d92e1b12f8d52ee1169af6fc2680921d310f97c7912419ad5e52908932dc979b83cfa5118ebb35249c5dcb2ba086d1a190836792916621e39bc39fcffdf142ecd81c459bd31e7743c2c8b1f4d8efab9d3063a1eea3b8cc1da8468362b9250092df2a9e70053de37717daac1dd619d4e664dac216a6773f4532571564ddc2a553c1606e68154df8d4a9ff2a90e62ae8b96ea5ecbd6986f1a7cf005f76ef030b79a40ede243d3f075c158bb87b4f513c0b9bf0f1dc5565a925142bdaf1c5f2169dac128ddd8cb7d56d85d4b0e97af3946cc9842382d9ea283ad94995b864823e0cff735c0dceaba44749c6b355578620e5b78aa41783b26a758f3563d5bf4eeabdab3588d41474f21083549b83832fbe8c933cc58138450ff355454fde8dd9d6b775b8ade2370650b4986568321686dc579a9b9e91794b7fe968ca75cf1181efe33246637960c209dc9a858b16c1b74593e24f74177b410f6ca7287c95cd505a6d27df18dc707735cb30062a3164b2c906fe7dd68af0b290ab0ddbb3fd67887783c9658cc2020345030e7c7557cb25bf6b0679c406c1c6c73dad7ac4198da77d3511c019a6c9b0e7dd470e68c1939f334ef8ff54089f82eb24d99b2c4b432a2af1da35b16c04e1cf61bb530bb15c77445085c22338dd68b6bedb70e51384e4999b6769f46db00a4aa4794e87796f84104226848afa814e520f7bc9e113369369adde122b8887b13bb1b42818d2e764bc759f28b22b1ad0cbb84163193527b0fb754e489b6ecc13907387cb5c4f0e027b0f55049dc4edc8bb3e69a0b852f845242d4fa30d06502177eae9460d94defa27622adbed476399b05adf24488ae51e0ef447b43d0dcf2ce6061d8294598ae2ffcd30664e05f30f60529825c5d8750a5517a38eca800b1a119151ef320d1feab9bd2373813a24348ac3e1d8394fedd27e3237c7dadb900863051bd0ddb471a2b78c27b45471d8a6d5ab7a62c8341b54acecfeae14bb4c8bf6b90d1acc2eccb6a4188d1f4119692d906a508c80aeadf671a99b3842f0307211bfe6d3041e304bff9f37fdf73ea5a400d008ee1a4cec772ca2732c6009e40ad077083f08c2ea9e660ce05fd70bb0756956362150305a90536f4c6a7e9a0eaae705b7f968a473017e95cf1663174d17e4bc23ee81ba37c1da531c9fa583dcef028d1468e3fad505f010ad80b3c06a0960d621b8b211a64e6c4df05876db29cc161322071ba4e29067ceacdb8c264695197465b2414ff464c8cb0515933767a485ba3f8babc68f6c59cc3742a0e5fcdd40d7153eba5b5a0d2c54fc371271111c0b4040c63658d3b5b2a94ff0c8ae33a965ea677b6a4f84b6825e916ebc3341fed29626f57dad0add60e80f92dd13790174b9e7bcfe3e80628ce1249f4cbc3228d98e88e38c522e1a7e05a0820d206e70c98d6f096cda51cc1a7040020577253b49eec1a9afb2feec0c5719c50dc8541dc9df4cc3ba019f5813006ec92db4919a89387431b4a132c531f7943877ccc2ec1a40eec64bf108ea8a1baee9e9dd4e0b3aa45adf97aa5bc1b660788cf50cef8deba331a63b804cb6b651f71c604a6f0bbb3532e7fa30f9e81b771792c44f23a189b5babb1477fd4baf30086abb9cfccc21d062e68445f881d1a242feda593fc9922764f600c2e46f345bd9e2a2a4066759e5df753d68ca6bc01ddea9513e28e75a8178660e4e30139af38670c6fa0a54830334bbb304d969265ad6a0a051cc23916a254bc6d3b0512e25f8a3228c52ede0ec43d5b0ab22a98c8c944333ef8f0d195d6afdbd33fec00a43458f7c6d3712193982d1eca0e04aeaf828111b138aa9b34114c33baaa3ba00a3ca0a47d8bec67511e71d107f2bd9c54b392232f62887c94445a2f52602730d696ff6a56fb8a073f0c188abf28ea6203f6575dfa356e9efb6e2b8c85129f29490238aaae86348b3148c6c12e7f0aad0678c6722a6eef998820582bf0d3c2483303e3f86a45776a2acf23c509634ee8038440943769af9cfab93f7a26801b429f3e63caa002f9833e756b10e5a56ef5159995328372b735f0cc925e5a0f675e5c9c0e5b965d16cb0795ff7400867b89aca69383226856437bcc88030ace64e9d440766ab826a1a6618f1b8c83adf4560f9cdfc3b198e3aa0bd7c3342fb9d50556c173462ed65dfafa593fa8ed15060cd4249b233956b805152236a8bc92c92e2242d6691e04d8d95133126ac8c3ccdc83b828923f23e2cd7c4e8d609a7f98e833720ed5a2141a00214130a3b8f5594ff02c48a014a29a93e5f7048a1710e9ae96206747f07ce3d796ee748b319fbe83ab24655f5b52feff3f7c91145908373c5e7914ad77fd14fadd642e36242e38a9ee4488ee4488ee408e1be2d46586dc80696b17b6454af13e9c581f5a67efba9891099522611912c09c203a503bc03ff69a7babb1b02995a777733bbbb731fe1f880b0c2de0c0c90764f4f2c729432425068298f19177f7fdd7a49caa7caaee19d5c8454571240f348d5def69fe697ba6c78bd5e1b5c3c65c4bac844edee4ef16a7a248f1a25161eb25ca7522404246a376d4eb9bb3b0435b2b1bb9b4c2bf81ac7929269ee331604329c8b0ac08660042e8a072a0433bca35f87bfe989a6e4f85e142847c6f2ebe414a3bfffefb0a37f6a94d2e9c8cc402b6e2c33bb7777bbeb853fbaa46a548c11b5c3c55103c958627fddf7f767f71a276606620164f9e5ceccccde5ef384e517b9a1815af0587eb9a84fde07a8a9ffff0768d4f8af0834c3e6ee3c4a0ff02c01d1b075d2ff3f3fbdfe7a4f0a33cfa8b9a3105a776a288ab806ad88a20431d51900f9810c822a8a28bfd33ea0d373ad4f38e8f572cf17651544ccbcd323c2429f1d1192d2cbce127a72df5662fdf286f6a065fde5bdab24e56bbaa86b0c5fdbf85b4593b46c73c8b8e51523d216023b1fc9df7f6ff88e61b73bda925ddfea0a192ab5ad313b531f79c5ef01aac1d38b065131331b9c9c97193c36b6e1eaee6e753aa4abb95bc78a1ddd0d0292080b9596989e5e40888a79f1998919eebd975d185674c75095648761cbf7876e54525d896ee6f9edd088f48e61d7caa0eaa644752d0a92e639539db1f36ce64fb2baa9d48b08b271a63a8d622d8f9eea65e8c7270f5e8a8e85d42adc0afde02a94cef4c52ff57751209b4a85939f41b55445547a753e94e67ebb73deb8ef6ad7c5b7ba06f57e87db9fdb6099ea7a2af0f2536bd3171eb4247ff9e911799f04d417a19d764513f40588d7d666fe6597c12ee509f88ba59f83a3fafb63544379c6915f65c60aab7cd83f4141d65fffe1980004d070783a94fcc87800033c86759f4010777db772762a2dff59b2b12e448eaece8900cbdd1b70003fe008c664b49aed43083b9febcf295232ff10b53a25e3dc915d6a0e1253359368acbffac584962ebd2526519251525d85dc58ff31e937a709dff1a707b0ec8dcdfd6b8c58c9abf8a34489f5d1bb99995be58a2153a67e74e446dca8c6a019d59f1182acbf44d5ac5b55fb76eb1947aade56d70f28b0d00f7c3e51d2abfbac7a225ba97adc76f94907455308aa78c6b1c579aaab93942c9f56904f3f92242acfa712ffc1df6942517914ed9a4cac4ea17d475af9c3139cc798e4e844d4661017cc35149a5f3d51e21f4e9564931b3be54875757233fd03ffd418f6871462a5cf9029457585f281da9146dac87972bf08d41baf9862d223c2c20f4c7c5a0552aa72e78fd38d3f44b53bf8002f3a482006194823caab26c458245ee5b44a71a64eea050908476aafc6a019dcfd669304d59b621027c2c25ccbeb3d10f4751855f7deab04c9d5fdffdf7fb959a72965f2ff653b11161221292d3181903dbd029c66e93eeb4449819cf8b0fe1269829755198e04d16652b3d6f783691936905f097a4975a5054d67bef75e36553f028aa23c8958ea7ae236c2c2fb21a43795727710b476245537c8c42d75773fc11b6161973413b82a4f54d4077db6b90bb95adbcf4150d01395f4a062092211491df23b494e1025824c4ee9ec2742ad01ea3060713ab0cb895069d60e6c8e1db0c69199d984928925134ce8c94fdefca8a4a8ae339e59cfcc67b66b367fa84c7777a7e026c2425caee5dd170a7a1d481d374b2879c24784853ba2fb7202e9d59e50e2e01316db93ef73fba7527e03e4e6d62658bedcd8d86b561129df7973d266c7641ac3b6018eb0b09fd0143d11e70b8a1f4d09f325458d460ea088bb688a05aa947bd1a71fcbbd82810783ba060173640ad83ef23360e3d30c842de2d83028851c965fdd228e8f723499ccccccfcefeefe3a4070358041a05a1c95b29a2ae8898e0666e695f39f363bd719b4b4e47377cf10a5b45afd40d36f656a56ed593679272a333333bfc8042f3373fa7f6394a8a9991f333333ffbbbb3f33ffbbbb3f474145455971fe18df9dd9f9f11113f4889a76e6ff7f6e67807eae36541b8a32882740771a2a113e2d097046a908e090ebbedbfd3201ed9bc3bef1af650b5272921273a3b1782f4044a975b00201c5b753bdc47a41437ca82f31bd9cd607bc0e1dfaa67fa23f54cef7a23b0e6e2c738f999999ffdddd9f99d9c5ece25f6a19c1e7b5eb735198b49ec3dee1e8719e8aa655a6baee76b1464957f35f3586c2d57277bbb1fc6afec931be6e8898fcefeefefcefeefecc3f3bdbdb6538d6e292bb1b3ed6c7fffff4645306fbe6b8417579bd5c72f44458e8fb013de4087ac8c53a34c77a4e66d1f5faef2112612192d212d393879e28ee7fd777cedddddd337862dddd3d75ffd9d92e2f1dc653ebccffffdc014e8c27b4251098a1a21cf1d342fd99e1eaee763500a45121a7ed349d6faa476a8c959cd2f099f36d5df4c0c3471ef1dd2e88de7baf8e985079de7befdddd98701fc71553e4509407a298918885ab36debedd4f24e810f93132c44386013ca382e667e7bd773472ef25ba2179277443dddd3d0cad28f1b9ccb81116065d3308d867f9e32327d5d5c742ae07201a92f620b4e3a1adb187a09b0551f7c99f34178ada4e2e9b734899a0e9c2cfdf333b297370de512637c2c2dbdf21a44097eeeed4c5191add9c724164a65231bcaf12edcbc7100b19c246214341cba0b20f261530b06831382351b072e184ed02928e4b0b06b41624231696da8f65442aa1c5c20a9b0537672eacd8ecacfc80b1b2de00d71f3e162aa8682b8c3f925a54d4f546a6f2e38414176dca0c06170b57528eab157689606b1493702b9165c1c561a949420da82858a54950acb406a89e40642c346c183855052c1fc244ecfa05e2c17a6d3914880818be82db0944c905c7c1ddb4276be90b7e9fe6f08b9fdf70992f76ba48a59c05b9b7a492383173ec3dadc6b069b6729459115dc8c8d445cba752215ae4d2d42ec88d0ca91016889f3a20471542c6cd006cb823825bdf2fa7842af094f9ff9fd4e3f3ef092fd5b5476d8485dc6773bf2914835e93f49123c2429e1e9f1deb83e86cee36c823afe7fb01d91f413629d652e3841ab80d6424555092486252a35aafef1f99581fc50dbc9b080b712c2fb7866d919b227b8826c2c29a6de786638772e7f7d5d1f6dcddaf8e2226d65fe278aa446570df34723b59cefcffcfeeeee4c3306f79eb5509a7491a91a9bcd4c432c7fcbbbbff119bea174b6de8cc48f034532333fb82ccccb3259c3333d720093633f3ec483bc24c66fe77777f36496bbacff8d9255f897f752581479ecd224eb608f0d44124e8ac911e8ed13cfdec908a1c4c683597a64372232c2c52a123045543fc1c819622f11bc486f62c7921c0b327aa5de9c6a0ad74fb13cf3d9fb778b3b7d331ba0c3b48cb347022082e862da48759213eea8e1d817794b211a0f9547648cdf5fbedd462cf7da29fc2ef97e1a3ba0f68acbfcebfcc02c7753a9be64f8931a684adebc1953bae62163baccb41b41be1fffffccc6283db291094586f92f959dc48753362a3cbe5d41d24104f1cef9e3b4d366b9c42b41d17d5f546ba9bce7cefbd3cb28b7f77776f63dcac0baa990eb4be176a9b5b4258343a48207aae89fc9929f8e8c00fad9ce05b5d1d08a27189d30120e09981909b4ca4d56a2a3c41968a890edd78acbfcebea9342cb51cba20a83673df150d1cd68a1cd220c7babb33ffffb3caadc091fa0a8c618b34361ccaf12b459adaadf45b2d62acbbbbbbdaac523133f3504f0799d9bf9bd9f5da2153a9fc2d1a0f505b43327aae33fffff3f91ad211542f86a0b3dd1b58de664ed19899d964fe77777fe6cb7ff95311ecee3dcb3b74e28432829fdafdff674111b9445dcfddb712c10e1e8a262911e86417d870075291f2489b93f9ee759d99ebbd5b5d81a23cbdc9cf6e3bdb396c201490fcf273ebf09cdda6bad2e488b090a7c7674784048246a971670904e5c6fab5e1bacd3abbb4ffff1f976b79bd0798f85e01ff7c570120c286c281ca81e281ea81f281dab13914ac60924db86fca7d53dbc45b9b7aaf269f8bd981696c2632a18e2a141b1116e2e4f0f4f88480b27b053cb97b37337313f1485ec022d575098f080b7bda470db164b7922fb4997facb1ded199b4222ce48560d21b4df37544422a5fe424c6fa4b2c82e283751f6d29eea6060e545565121ba888344f345166f30b34359261d7e0465858b6f9dd7f5346244cb43825aa2b0c89a0697ef747b558f419d24c49fca028ca0ceaeea66824fbb9babb4609a666691cdb34993a85e764c55ce807c76558c57aad1f402ca8333bac1f4d1a54323b2b1419521139b5060b2af3a992885ace98364dfa61b8b11116ce681021d31991d3b5c462443248e02b0202a545865701870970390c13fc8a7a232c2022288245021b4e06d92d080829b2188c0d75474e2b3fcea119d659d40368749a65d1114fb5ae619736762a1f379d8f56081f3a9ece3aea8218a163139e080b7bb7014d7c6b931f7b3bb0e16e48946e7d518845641f26189f270f9338052958eea451084cabe652842596d2ece91161a1cf8ee8617a90da254461848e6b0408ac675427421496464ba31b8ca44af97fac807547525d439089b09056bb3cadb1c6afec1c2ca2bad6a891ad94f9ff9f5333022a301cdc62b93675454015981044a0d0d44328184963f0c8211f2498af0d2e2d2f545679cae6b64a9dccbcc38db050877a73f86072fc549b1e2a3a6e364958ba984d135df0e684861fdc0d07157e6237422a3a7e342a1d6e488805baa3764324cdfd6e2680e67043417aa03b5a1d520b96062fd44f1f1254baa367889edc025a20d04c8f23298e943564514fab4186ba8a4801535ad106500040aa6b8e61b0427c20f36025840745ad6e1b37b681538b6e455642e062076043dd90115ff60cc68ac5ff8f9deeeeeeddccccedeebef28d62955abb3bb7d23c9b40d5dd0de324d8efdf5d028deea7078c22a0208d51546c4575b2aaed1978343a12c532b6b8bb09381116e6604c6831ac229215aac812f61311cc13d2051589ce8a85a0af0549aeb5d2646341e2635d27d05a40a224a5c212df4aeca5d204b8da2ca49c20ab7063e502ca5486d216539b922408eb049c2b09d36ac5146c2579c2a23af1584b2a15d4ce0a88932b65f25377f446a828944ff5abb5cea636fdcd402f10fde15e9f427bfe7a2e6752bb3fa6b581be2feaadf08eb7983028b44d2d6198e4f8b6226182365347ca1836946c8485490bc034b91949a0090718a7d8050bc02ca111800d77418270c0a5c29c00d850076484fa6ab5d5ee2e80ac458096009edee7b5680045ae016789bc0e5ac401a86b6d56b319804a923ca30da400c2ce098ab03026a309e0c5730a408a6000ce1e322b2c6c133e98933d2cb8e092a2e662f6b8c1818119033d7c300eea8a0190c3110917005c0080a31a1a36d0e4361c1db92c1003b8c0510a0c28506353c007061934b4a069f091bb109514a8044b773aa7a0000ad31a00000500140672204921940600148004170e5d909864301c9905c260281c1404c38030008a811808611088e14094429260c21b939a9f7a45745e0b3ac776058cf4a9017a4b1b144e54cb51710137e2049832a18f883cd7bb3a57a4c31688e2c0294ba1054363ff278af4661270d4825ea297684f0bb115e76951ccc4893e40fb273d903ab659634c9d4311572c7c6bb5dd8abe051308c6d7e1017f79040e762e4edafb5a3a3d4b97538948414f5607408970815621d5e7ce1aa47938adb88cdba23b0eef03896c75b21d2b093b58fc5413ed1cf2b328bb80683d27a21fa2827c34225e588bf8af44a78c944c440e8e0f5f10f09c70a9c0368448ff0209634b089732311df760a0a1ba3d1c464c5773b4e90ee2be91b56e2204c9624f28c07e39c0c7ede765c305df9d050eaed6bfcbbda813f3bae5d90737789a9e21c05e238d48f80e86de6c00f16ca81f1f401606c83c4bb38375b5f1c80945b0371e9c5ef463589891291e0071e3612a9e7f5ccc00d6ec3e074329a827333ecd3eace2173218771120c5ec07fca67fc5eb4eb926cdbd1e1a6d667afe7341a3320080303dce0871885555380d0367ba4d30996f56a68f3d70bc5d16b1195f1889a2c97b1f15e9151f88a4977bb812d08a6ac0014ae03633566cee218c105339ddc1cbefbe41055f62a2206d7ab0b609aab34d1a818384a25ba49442d1dff65f568d6680318b39c42606af721c9d2b5ca6ef3c9d2cfe12662dded51a9368c730caeeef0659d6486617622899b99897d428842aaefbbe56aa5911adfe346bfc76038208ecb8aa430def350d4fa0c6739a7aa4db4ead0835e9ba5d7d8e1adcdadab78045d2d237a4a12e0cf8e606b42e88a0171e20462a8b822a8044953271ed9f41dc03944e3c306e96631adb69df0b2e1763a3da78d80572eff7e639486c42373d1e41df67c4d501392a30c748fa255690171c2dc68309f415345daa693de3e8d5e1ae6fbf747cc512fb0a9fec0703c9ae9853e0bafc21764d969f69fe085345827cdda9a498b9086900e37d2ea59c28d2bb97e2df890ff47a9b4e503a143537bc39fc25f901063811029badaec4fc51e3441309e6e578d11c9acf8e5b04790c7f0e598498df4b5acbf129ececfe67238955c35bee88de825e938c45a8e6a332ae27cda6f8afa714dd36f69c802c028e1a431ede5b87f9e86d4125960df13992b949a2d53a771608441d8a872a8ebb2bdc6a9e7cb21db7a6491282c4012baaee68e22edcb07d95c76227da57f8c619d25119f0f516c27fb3b92a57f4a1a5152d8403595f2e6bddfd348a45f0479ad89d45856af1db446dd51aa5848beb9ddf3c27e58dac577b0c0b2cf9cd18b8fb84e81cf299b1925aaf1f3492efc43e3bdcf648da4213d9acd7632b2192dda2f3a9c5b389ba93e47213f7c7c4b88f92a0b907f092169d6fc0ffd6fc3830e14baf69c9c8f8eabd70569bd2a08298a5e58068ac44cb28280d4821ca6fa372832141bfd3843737ec6cc291cd22f821efe08a6d18acd44c462bdad4f6d5c48eae1da4a2698d2bb48690b2a60b5af56ceee6d03d86388cdc41aea363203a5d8c7d490021db70f30b1174d82d255314cc7301b27d65c4210041ef6c9e6b41135566c4a33bb28e19071ebb80d17b9a5a8b2cd3bf8e9b1e81dcd6af64e6a24216dbac8b5018747d7388b11f7bbb1883bc8633609436a8c69f66263f622ab353d7d8db2e98410f3f9f29266ba41047578a4213f6ee1300eecb2c0c0b8ba50fc1e530e727202ece94822b21658ad55877473cba56202e52d8230121ca307116ec954d9e28723dcbe530aaa6072d8a0760db93425183a328ece023408e14e926f41284e558d958649a6460c3988065081699ee41d32f43bc9524216baa757370d5265ce3106e0a0b6b2d95cb3eaa9bdc188db4ae0bdc2847fa02040e3516fad3d3fa147bba05454761d80de1cc404797c83eec0b07dadcf764b5d830a38a79e5d5a0c48fc3f0afd58a43c2dca5bff582274e49cf78dc23b216141d3f95a5af5ec5f4f2e0dca1ea8302ceae1d1c576286be8dbb22ec5717d073d1315f60a9a3c2b383f6ba28f76ae8ad50becbbc3c8abba8af4db94476100cfacb0baeaad734157912fa909a15d6fed66550934e892f4bad260f122af2d7af93b2f77ac249b51a4ec46f021592342f567c56cb1a9daf20911eef6aa112d1232ccb24e1ab38798bbeb02793e89f408ade7ea1711093bdc75e53287f57c30bbe9e5e69a9f124a85bac206b5e5cab1084c3e188d030c3e58ba9a1cc19e5207718c584c9ca56f435761824321049e2fa97b351cb3daa9e4832fc9f6972e7aa60d27b34f32f3155f0c743a2e51af4edccf51ad3012f894771281f97a11789efe26ffabb000452c82268d1c42de1370346d39068ba19a94966fe9b75e5b964cdc4a72b5a4ac875b643fef088e09c9e1a695c5f023b95d1c7090bd955640cc764e23a9e8bd3b0bff56cb2908bb2781af0646a8c76cc53918fb510174483604a54a156fa32aaaef83f9d7e35b777350b49698a8bdba804705125948a9ed33afdefa83400a07a1dbb2d00296b8cfb9d0cd7585731c794b00f133504252d03d02fb98a7175da2d9c620465e723ca31af649f85839841367ea03ad615c9b3b93d0eec065581e19ee62517f5dcfc17b99da4e7c61d01ffeb368964c49e52e255e54b2b9cffa775191b6fd6615ec616f9fda4ea45498b6e14f7f7e8d61157900b4bfc44db709d2641bd593b968782133f1c030cdaab7ad724ac24406760f4d40da09856b0557cbc4a62262a3648c3c5b153dcaf16bc11f66d8aef2f44c1dba24a15a11b9ca13c5d1d868f22eb24b6658f4c23c7d59a9ebc8d793a3c90d5edaedf084071c54e438079f5f8da4c1e086da32bd059cb40e51a947fc0ccf226ff1697540803a92587f3dc3b60f3c6d4c31ec61cf9ef128813f53649844b39543f9d4c9fc63be52ef8af6d19c6f914f0e5a66cfcbc83bc3287f87244c7d879a7c545eda54e6645438047bfc485b8a6f691d126360503350c6c17889f6d0b9db3ae1376fba3ac42c7f8acb70f8b5e83e94246150813041a1d32912a1340bbd857d089b164ed08999059d920b200ad416efa4c7604ff63c4d038522dec59fc2810a3b5f8c0fbb367eb7a8a77b4843ef5eebda158b20dcc9f85e8d381d135837c900e392022233c6b309a36284d86911135acc5025d4a0fa40b8d1a9813e7be667264877c5d4805c37ed4d24589092c0d2d2287723136623d258eb938d3075d60447fc3a110f12b94f82e115497ab7101d0603e757961dc4478228e9720ef8ba5a1e7350746e2884d77223f2cf39c7f870200e2741ecde4422224f4c23d16dbe0ac030757ef9d8507b387951876279d5b66422187a495e5172a14c4a49b53fc37c74ba766e5af9bb3b4b0fa492d40062941467128c95494185bf19e8a63f1982b713249378d3be514a972397efa6e67e060bdb9ebf607f565db6041baa23ccdaa0d9c00d3225e905d631b9e4804e723cca53af0c5db2053417317e6e3a6143223d997e93f8fa8194110e1efcf7be5ac8a18d30a684c3c39d2cb8cd22f327f3cbb62799e62398cda8180b758a971295e49413f941371ab333d6d0aecc5132729302b6975818c08c0c9aac6d0608ff3da44d5dc4b591d2aa0ed1f33b150fa4bba81b2a747eed5da982664c6eb1efd810d64831b868e36f154dd630821e38e433b92f4bc18a23dd05ad93772847e020082eb2f538d5687430fbc38a0d84ba6dc92d2f8791741536b42e511b61197bc85082f60e66acf2ab285baad7570c1bba3e4722b7df2a45b10a7400873dc133d6cb5b1e58d992a65bd081f4b5ac9039d2e750ffd2510a1d91e0eac01f8bb32f9d1b2aa6a23f1df1a2402baa2904b6641abc3e30e808e012c3af34f8ba71c13b206d7bb2b4c942a7812b53fa9a8b0be00bba4c6585cdb936bb74ff9f97d3ff3b91221b6619653aa014af236929b5c501a25faa49595f07f838f8e4f923440877f53e86637ee79dd4e884f9bc8a557528387cb147bc43076919854adfb2ea36fdce6594ab353bf0fd0fa5a62f2013dfbdfb411824ee2a889bf581409fa879d5ee38f4883feeb0e6d5a465fb77e6b3f1cd3bef27213c336d4c8c9d97fef074e5fe732680d28f50d9f789241f452664f2363ae5910a6580dbb921c6a782bd67803a18c55beee2df51082e88a43bafbf07caa6f687eaaebaca52e54bfdb84797520704ff27837608e241bf48a27058d248ce1366819eb9c8b1a21c99ab0bef27d908a1d56ddc8e6353903ea511390bc72b03eabb0d6370e97c54da3bab4e13b13dd8b409813fd931ff6a8b793dfbe6e361a865e4869337693f7a653dcde6209ec17f1c8125d9665368c43f6f8311b6fba09e7e000ee7f6612430ae11842102fb274ed7f848ff99934ea133c16f43ab1b6b0f30861d303f0fb7dd0a4cc53152284e4b0879b7a7659cc6ba46fd7100f34f181cb24c4ab74c9f080465258c8935cb0b4417e23675b149696ef06bf3d9cce8bbfa99bcbab8c7a3af3466ca8c3f9882a36c2c498ac8eb708d14df6702d86a6122331a23d1a65cb1a0a0f2bcc8c4df8f86f2c132316cbf5aed878e092204dcb4239b363d62b39c4986c87444f1c1ad45c8c857ba82c060298058f597082b1555e5d6b21fc63c476a601fdc32dd8250d364c49be7a02c7b8a401e97462e6595f0038f058b4542e76b755ad19f88518c14d58e8bd5579bf03352a3d927b41dfdc72dd7ef7a6edc654649af379ba9e83cccdf2fee642cef7c1f27933081817313da2725b3b41b058b59f2b3bb26eb8f6be08dae1bde95e827ea7f597c0497f60b4cf6c37dc0b9690f3f5d55ecd18026503e945f41e9e31ccc4bbd9dbe6e2068d2ad35510f3b45f6148d42f78886845b88f9e538bc03715fbf6873477192678f55985fd6c83ed0e849a55b1765ec92a942a94a26dbe6e956f6a1ac13cd76b56adf1a86f388d2aa8d934b1043015c90887a4c6843e8fedff768bd4d8534f3a944c4e35afdde62d765b66d4f40de6424ca0bc478b7c71799d633ac343f8166da8ff85db198ac4028ec3015eb46a232ba4347f83520096ae085ac8f6b2a41790aaa067e47747849401bdf7d304faf01dcb5bc002204c646ee1db0cb624125c16d2d79125f96ba49242bd503c5076eab77fc242b7752825da8b2999d2d6fc9216ecae19c1db6fe8d1a6f9852c5011871cc56fb661fa3c68fc30b106fc0a7a23c457fc324722d1bdc012b8b91b74187ded0659f6feb9c4732a83cf07e274304786b34571ba2ec77720aaf7b8d9c381b211e541259e564466a68ae27da527b02448f14dd04f266e0ccb5e1adce1f0f9e9447e7089c365f8499292a69c2d7a791509deeb9a4018ba3042bc7f1de7153fb4bb0422fd0b16478ed861eaa1ba8b1c8bae5d735a1a9bb1d99a9129c9623ab77f800e9bd72c1a98475ee39933055ff4e879b32377e7476300684f3a953bf51756af326dc518dfb1a54936f85331acf609fa2468307a83e419eb865abc2c12c8eb1250c7b3b84bb20814fc945a2acb47eda811fa1d10cc5cfeb455e53b46a6523230bdb39bc248438df37f8a6257218b524120fcd678abb38536700356e52a4a1c73f15e92c44ac0b3329858874a17b4dbfa92b473a69ac7018546a7554a26d9406a6803f19259d7ff594c6e38f08092caca08ea22a61ce779bebc9300b52141ea98aadb661aba2c57f9927888f78220ce227cbfb0d45bd2c955906cfc8128e965af28391c26f25b6e1f49a894a3249afa310591e5e03f2b382063e7dc82050f32e6a37c51efc9c641d04b89676ccaf9888e75558f4e22f1eff7a063fe6aa9073d6acce1c8369cc2aa27442328308a453fb9d1413a57fc46ca785d9167c4c19d85de416a64bf3bad3fb9bd4886b2223116f092742c4207bef26c857361d7f033682454813a8a9c7989264dc517058588eff41b36910e190dbcb63428619565cc06ae9bc2100508dec2c25f96fce56174ee896b9f102db82859cd11bcdd17832afba7afaaa4afff23d740ae5ac0270d9b3f72ccb5e79e50249a0127ca18f221b9a1cee606bd4674cfe1698e3a2857c9479acc4334bacbc96c4f2051ee40d1b26d7b5da6ad3ccc0504adb50b38e9c97caa8a87e61c7573a387d8a9e6bb8a80ac27602497df8f1692d0c6099af11a9f61ae31b145b5761569331e49ecb98065b254d256eabebcb1b5ca628ab362a977322f5b855371b014403994fe08302174cb6a41153e480561b5ef0b6ef0425ca43c71e529809f6784ee07183bace2f5b318217dc01f1f86f0f8f9768ec4838273eecd8fc3404b18a7fe09ee9c7d12d267791d8e9d03ce127e5c9cc13bee68c0955f0b246d41d6911aa241340c2edf5b35bf8c8d7c7e61111a357a3b83bc633c77e056d7ba67da5dafbf992112a0662373072b97e8bf2263ef3cc4d0cb7e53502e047ba4cbf7f8a95816d670c90bda6e972e25b4d99ec501325b1dc304665b9732d5badc5433bfa80f99e480e62215e9784fd664ab566c09db66fd4fd51fe7885dd3182bd43de4d67d18d43381945782609c443d15bd0bb935ba7a9ac8793eec27f14bea646215ceab9156f9896d4946d70a1d9bc5ef8f5af6ada690ae21493bb619f8e7493fe173bed2e7dc499a897c18bed643115accf9de39110a75131284a38ccbea0013c2b3e43227845bad216502cbc73b8b5f7d8352ddae6276561edd15cd791ac22ffed132978fea1c852f137a9d18b34a2b18e51b119b7313276e2fcb6989e897a1597061761a8f8201b87ad76db366a0a3f1fd44c2e068dc8b6c8a83c1b04d5cd2209902359c11a336629468c425876356c23c34bff680e17f2431c321e5643aa7d16b2411535dd664d3c5c97d65459a81c2ae9ef014bd40b1783f5997dc04e285abb8b1174f33696d914947d1df74700fd7f22134f21f468f4c688d37403cd0dc5743dff3b8557c248bfeca7397363e045b1a7859af2524a2708b8a0cdee9b571f19609db651c1b0b7ee8b2b179f19a9f44a3127e551b0edef5934942a560021bbc17d087482d47e9e2d8ee3432e496e754ff9c766c43da5272f0aaf11e9425b1926616728be84c93c32e38792b16a6bb9ef507b31d7752330b653e3bec480f0c3b4270578302c8677f822fdf3276ff6c2fec6d0e6ec9d41396a1ef2d149b45a842dbd720f90f1910cc8b4a3ff3816b817b91cead4ffa9b10eeb451c3c6f6c59128c10919525564fa2c4c9781a1dbb328e55b5314bf63b35616c28d7191f0cd9ba5a0651a21fcad0b4a757292f6d0d249e3258b2b18639148d93d2f84a0d08f3c10c84c4086360ba1fb171ac88cda757f0bbb6c00ec7897897d42b1c135003888b5a5844ae75a7355d905af125f6e9ab120b1b70fd86217a841e3957b166ca0ca1bf268ef13b5762a8b0dca5436bf0f5e8d7d9d97a4544d357a3790a75ca3770de23dd4e04e137accbf3083c82faf3b681abd970a594176d087e7d8ec6c5267bdd35081cd31dbeb0a58025483fb14ad3dca21efa7ec5fb2dab198f006ed35c004928ab12bea51c31b314d4fa0c6f364fa08675ddb52270080dc3ef5df3dcae63631b158e4b4a4c9833e0b858d2f70f389fe537803075539b5ba02ddb98763ee6bd60e679a66ddc181fd894220cc04003e8f6bf0213abcb5f3575c850fdec03e8f184a907d3dc07417601688d5f69651f60d5f27020e03405e3564b45e922475e8e0c8f2826106d0d82bfac1d539158601e67546b02d39064f4a43c3ab72e081c63d1f61f760f659d52c2f5cb77c93e0faa11022c408a1aa644763fd9c82086a32b09db758b0066c8998690d15de6bc1f183be550f241993e9b1a231df1ea9563476a3e1376fa9a0b5ad3528400342afe2eec305852000b840ecfb487a468b8af55152542501a35812e6aca08614841100cc03b1c5607cfb130ea1f5e43a93e93d001182d2c32c304a306acc3aec805d8f2fbc20ff4df6a4819fe50becee1f4add357d83cfeb3c650c77e96b5cbc6507f815f6904ff84c436ff61a8a7aa9e6212e8c8db8a7c5fdc7e40db9b5d3d44b2da1d30d81a27b7f07e58368a1e4443e5f1412d146a67004d1de97c551909792b8083e7a0bc989eff2be6abdb9c5c08161cc89866c8895711c4ffc6e065f69249516daa614e36bc925e270aeb1de8ec159f047f2a10b87297cbcb1f653249d29e4c1b1664c8bf81a45d42701d9c4bf3764e1fb015c7382de03b3683657f7999d67d99a3e446961928820281d26e64604d3f39d467de1333c3dbd87017d1e76fdd2c353f1e44d90bbebef97ed602ea365928e8bf08625523c5871cbd4dc1e01ca39ebfd0677bf6cac42b35ae9125073cc40a0793e23489bc92a59b4f795135059a90525dfdf3f24cc812256df5f24cd8b560ba5f7d9579d74ca50b4004865ddd750aa562ad3ed413d0d301adfea176ef4fb4d23248d45ec19a43c40dc4a2f777da4207fc42db7a9d5037aaa92f479b72b2b77f30250b0e7196966b8220f94ea1e9cfc914cf44d596c26889c586717857bb21db4eb8b52388ad01df6f71e5d38c51e3992e947d24a9c12269fcc88f164b186db1e92a63c37190d56fbcbffc796800e193be945103069a5253d0a8d4d9c806fbf70575b7bcde01ea63854717efc30b6df989d08fab5d197f83ab11a6e68bf0b1702a24e82eb0e5fa8758835b8082c6bd3612ec0ffa57b352b00ab794db0a25cc54039e20a1acc53565b5e858540347887ca01702f8ecb161e602435507e57ed2e304686740a27fad4ee1c399b385309083a7a76c0b9989aded2739dc6253e17f75b4c1ce7a9d09989bdfa501b24d0712d8c646bb26ca1ee5b640385722a2fa273e49e94cb1de9d960b10644411ced1519c4a07c55f51d7e31089f14baa9890e34de5d1139a7d85794e352e390b4b18399dc911f02d71b02fb0f2095d6f5e008ddb8c853afd1e8a2d9a769f35cda617321c6cb186e980d2ed229c4a41f7fba5e890a99b8330745c42c1033d1b1ad41519dbd949811ecb3d00f5784bf328d37b95eda68e52a7076bb252b2c918fcf59b054228975480ed729a596888c580cef73f477df2b1fd70ba60cab38a515e06742f7ea8165753912cd95c30913e40a74568bf3efd2abf50a71e39c554f4df3140d1eb8ab0df6f1eb99d8b193635d280f1081bce3f774ef7a3440779797b648cf7a98048dd0e480b519163e065a54fb1602c092135500ea8c1d2960d4e138d6df058ab18491f789a0d0b0740e3bdd7d311eeb3960e26743e0743aaac5cf31ccdf82fa40da948a39589654852afac084cfa7ec7c13858a3dbe8413a00e6da515bdb4c594a1806c613f687eb4738c62b33337021474b4ca8b9b747b363e3a517ec160594c8ea15d65359e03a35fb8982f27c66be6788aa4188c5928506b4ec93e5e0e156b80992e4fd17626efb4db4911b09a2bcbb7159d36066acbc95b5454321a1cf8a3f15f5a6e13ee569508204023b4a6ad0d9f3e65cd39ca6795be0c700eeec57852a8290382fd91489c06351299aa4673740928f71565ffa1d41e3edacd8ecd55a8d93a88a6c0ccc2b7cc6ebe22cb7db59b7548abf926616d882589b6c8c01fd04d94be762974c04584faed9813c3696a70ff15ff496fe4165a67361d4aea7f3e21d067ee618b0b1f42035304f7e4597c8f1a4b8127f660b1fc412213311b6e2b462198b26203060f460059e63d0931bb6f092b6eb0a56a983f0497d3a41160ed1c25c609aacfa38c4e344ec99d41aac402545eb48b5fc9cf03dc7b0b4be3c3d88f21fc1f9936ff658d2e6b30577051f95daf90949fa03d33595bd852f492dcb54913cdd0eb602b5f8b6ef78baf5af601fcc13653e705f3b182de103202f2120a94713adbd9109465bdfb8415612021d52a4558f7f876e10454c906a14103821b8c56e1e8f8bb4008ef86f46378dbde99c34835d4e31182c99d9979d20e763872f00bd52df041565dd511498b4d796cd97cadfcf8730e91f1ad2d2cf8eeaafc0566215774c5a8896713d29725a34dfd4c35befe9c92c45a6a3c8ad0f113fac771854c9838fa64e292c93c01ce6292ff5ab2d6c14f860c36746cc0fd0e03273832fd49e7d3e113f404170000e4cb038a67c7a8551e2ba11e93c759b4a7225824693d42ea0f9efde155fbe45990d187fe83c52cf0ab090355dbc4d0978137fcc4f32c64adcc5bf98ea425aac76b1818388ca8829f0e606bd0d98f33d08171eafef12110a78213b85704c41234637054661b5d3b8b9175494dea21396923718555a0f41f18cdd70e5592083fa8799c20bbfa71e0a58f1556f4a0f934cb67873f982bc212864b815042b6e600bdbf8dfe2a9397e3d4e844ba78593e07e6c993e14a073060134bf0cba63f7b28811b8bae19ca831bf14e684484259a3d4980d26090a660619c447b128ba328b0b79a70cf19408b17726b31a0e224655c8366e7437ce1b50852b650b6279738af857aad11f56366385e09b2e2a95c307ec21e968f8300f8a810377a31dd331bc1d8a17922ace00c8093dbf88d1e2f3a0bfc61a19f1a27587786384ba07ec80a05136afada2546d6543013ff9d323a8f03381f09b33c367a8ea8e8a500d8cc874874dcaa740763518ca51acce17556c46eb91f24ca9246f82f616f6d0751ef6efd63b303456ef5323ec049c240b060d89709da11f990383f2b3b5cb6214af9fefb573cc7598104364f7b18e91b11b49f3f4b767b8f2cf80cea2d0fb7c15be96d448d46435633a6613a00d625f47bab7faeb0dec179ede5f96fec67cfc54e5768aeb511e3f21810ef1522c62d3f37dc61ffc5e8bdf50a1addbe9f795240e996e5a9acf9efb6845b12efbf4fd87db84368da465f67f5d61ddd21c7f63eeda51223a6360a42e360e846d067ae6e2ea19c93d78a56c83825acca90b2528d8bc6ea4da3c62f63a0cfa18637536a35d4a959437732b0016130dc006116f9d030f5310131503f7877286097c7a514d7acbefefb1122be55191b77035aafa11547341daf00b37021ad6ff7c352add35846257a17647b41c74eb1a6e27b55fb05b1417c2fc636720fa7f1474734580ba061fd6d6018968c7ddc51786ea14ad4152c643e0365dd5860f9e86782418325911b47fe9626ea2f050dd6b5015941b8d6392052c175cc1ccf302e3089e63f93422bf45eb86820507ca514a205c5112c29b0568b491d2ea09a1dd0e51262bebc3be90a14c64d9427a2780b92782be22dba5eef3537da6458304f46a43bbfa97ef0d004bd8d3e900d57ddd24068574a337dcbb982c7172f6fa3718e2f60e74c1518774c005e8d1b925fb2de6055fdc1c5fe6ac14f269468f7368a44535dd8f92ee159a2148d26142d1892ac0bae885bab659aedb5031cd1f0a8fcd56050aa8f2bbaa84ad999b5121e17e308864a64df8ad4be6bd1aaae67043d48bb9e2ab7e54ca2a15995b58a8af57bd20745b32e0e3ed698229221cec49b26d408009de0f1db632d8648b0af4a94d14bf7bcec94be4902ecb61260b705102bf2cb334bbc330536a719011621881107f668467e31437f306937f49a4372fbbe6ccf2624f4c28d66d5acc316931acbf2c97da6b9471f0c43b3ecd85edbf60d9c220064a8d52ac99a3e48b687ee827a7f57982ca131668b85fa7378156212fe2403651a3267b902a21ea5115f7d31ff8e9663d22611ed0dab61e0a53865172f53f29514f9e57249d1a3b4cbdaf9114226b755d2f6daecb61fb37e64b5f04381ddb5ef2b6492d231804ab13d67a4c9a7de3b370e2aac8b72ddafde8b2f80ede4a96669ea8b827f9361bed76b777bdd8958b42387eccdafa1fcb45fc3cbe4d9a07ecd0c7f6842044b875712b4b7487ef052757c9c1bb825c1b1bf3576fb989103d38644dca58432f2e496a719bb215e651c1f672c34611d619accec5ef2785186ef71639978d89315b787e73fedd0ae69ed9ce9f529b0a4ca36486ba0ef607c20e9e1633257d9c004a8e2c916bec4d13d28bed31a58c14a48becb66f659ef42d5efbc91c2b62fb2d047c0a6570a6b989f2cfc5df52bcffc0c95f5091b404798f200adb7d0285056680f06942dc83b155dcf639415b376d5c0e582f65b6fe5752cf4cbd53d2d23ee22f3eaafdbf8d963e0339fb0394facd503a4bf01da4441465c70caa04e073a0b143bef2088ccec36bb539976c74d77dc33073b0e526eb358095d8ed9670ea3fe136921149023b04c4d28b2b5b1246a0346c1ba1ce0e1a095e1cad35556ccc3f1ecd136c4c7baebf817d3ad6d7b4b2953927befbd651c0433045404b8078251ba02b3a61764a71315dd032c9394aedcca531145f98251514fb686293427265e379411256a10e1c90ab4e43e57d164863ab309d1a94ce97daf6049bba8ed8beca80894c24cad146f4236d90faa486a0bc223930223b50b7b5b17d083896d88fb29b171f962acb621c027161b98ef070c02c146e4899231b11571f022888269d1becb9c52420bcb6a1e19120cd2cd5caf97591d4dadf5ef48d76a0da335aab5d65ae79cb3d65a6b1602fdfe9e8b44604071f3038cc5cfa921ff89629f443e92768141a18d68c8a668d5bdf7667f36d3f0eaa7234f3ae2ff5fbabd94d1113a4347a50edbdddddd6dbf9b23d170fdfa9f05a9a7bace3967edee8eb5d6ae7f4a144ecca65ed30fab55d95d6bad3de79cb363adcbfbb61b3a8c924f2e91f96072ce396bff9cd19c7f366dcea8bf1edb63ce4cc2f27d93bfa4e12ce7ccc46363c2fd7e1eda9cddb5d6da73ced95d6bad1dc9264512814a80f5bf5371b91f7a0a3da84d21cefd30296d3ddf990b33216d4843d3c58cc99854ba18937425edfece47052bfb7aa7d9b7944a50ffb7c1216977c727686867b3e9e1fddacb2d2a75979987a45d5c6e63fddae46d696db36647d26eef67ab9922c5deb76ffd3f6cffffdf3de79c1d75ed5affffa3e6ec4a9b1b829b18b8d4a94e35ce1049bb3b1b4eafd481a29bdd7aebad717e33544c7d57f7de1b742dbaf776dfbf1bdcec87b385fe36d8508388dab6a1f89b1933b1ddf02039992806f726aabafcbdf7de2a236977c65fb8683c1b3d2e9182652aa59bf78924ed8a95f9ecf76f37fd373cfe1e64583058372c9b37f1fb4c67764ad04d5d9e83679b2d5f2f5fd8dc2acc5d366dc1b499fd3772e216092ccb4a682973b4d02559f4216937e8a53864ee1c336678741f3424ede2ecf804bdf818dadbddddb3deee4fbad639e7acddf5ebf7125d6a1203b69925b3bbd65abb0f7d1247b840e6fb257ed70e84fe88b23be7cf19bb6e2ae3d12968840839a37aa766b2a8c99c73e620f8c281b0a429c84146d57583dc8cc2def7c94adacda073525d4931477d214391be94e5e0d0172341f59663082dfe18cec8e4e5482e7d1903fe50945874df9e0f2108d0adae29aaaaa6ac6a8e1a195455387163459133430fa614aa4795898dbac68c193c008a584d1f309884a1429658418e35a4de4811da8c503c7aa08c58c39276d70a088d18d0dede8f21f5b35f2429adf7fbd77c7203f5fd77aacd6010a3e6ec5f8790a4dd615157400799763df3eda44fd5e4b843b86338e6d3f52248d64ea9c6284da1823af54af74b3daf1e19401e689c34574e255a6bad81a42af613ccc9bb152ee71b142a9e13255443275643a5932add53994a052198037b302584ba05a0aa6880f622eda891927061815bebc72e1e789a8ae548dad519f98014100ba216d472efbd49b8bbce3967ed8e71936f55572f2392767dc0a07058a4801759120e69aa5fb86e7c0646adfb00603401e964603a14d53c44eb68d18e1dc3748d7db0d8efe79491b43b43a383b3eaecb03a3e2deff25b2cfe265204dbc41cca48da9da1a9e1e038cfb3bc9f4780209cf7910049da0d0a872d9222d60932d1a9f1be353ea263e2d854570fc59a0732989b4ded434e0810adde7bef1304cf439de8ed7a9779f33010db9c33be3db0667a561491a8e2a123c4453d22f34025d595b72158b2b8e6208c87b34382c0cdca1c1031188405085a6b67d15ab3b8e66088a92308958d0c5d2d683e48e5207110442affffa7079d2d1617ab7565d996d5c7b6b0eb0ac13f27dde54ad155515611115dcd77209b57499a4aba4aca7a40b6a6a8ab504e482764b4f2fab5bb97297eac9428f78d7a24edfe6a46532afbf5eb4ff19472a2ae4765bc191e0d0f2765ef4f613433a941ac2156a3ccc68c0d1a1457d15a6b4ff37e77f7bd77ea3b850a15555d59fc4e52dc4028f19531cd30d130e198f8c6b1b21f49ca4c5d7338927673b9cfe9d49cd1aab24a3a20af1ea51b2dc8460bc0771cd783f4fe501649bb44b1da505989de2fa582d6bef6b526dcda9463672d1350d091454288848661071dd1e68538a1df7149e9062a0291a980493100644183861551594d270e1331bbefbdb7a741f377a94b75a9690c378de2a641e6af33aee741ce9a4794d566f6376e83faeaaadbe97aba9f6e6ad55db1ba25e9430d241e516e6cc7014b257d3f939ce49c73f6d1f8707c3baacf67f505b1b9e59d88828b688a708a768a7cdef59f3f57ead9eb91b4fb9bbaaaf5b2b4d63a05bbbbef9df7bb3bb9f7f6ed6f4ea96b0c1c49bb395d2d86d19399349752b3bc3fa348d2ee0cb2278251896eebc9965840497c9840a29475def4bc3f8c13275fd45e2c151df19deef7ff716166a62049bbc21ad3509790daf16876c1734330efbd771a011147b0a70311c3854b25a59349df37ef079775ce59c987a4dda09ad25086272a9b15bd0b491432d8a564c0ebd557d59513e57eed874725bd20c3408152bd1ae111cad450d744dc7e8810341d712b6977cc445d7d74330bb3cd034c8b1dfeff1f85110a9fcaa36b3bb99a8f50463aeccd6a3d38a9b376e266b5d648e0869cd442c43c59e3c93135d8a34fcd44500986b3ffdfa65622476519716353126be6e46badb568b47050bda2dfcb74ac2156118b2cebd7fb4b302ff196cf56d0d6d06b77d7dbf1ebf267c42ccfe00c49bb34b620ce5a56bdfbf8eb608fa6bafeb0296917ff89fdac80f75902213a10310752e659339e45b34f130cef26a4baf6a06933aaff3507ed3e70361f39ad636e58f8a8d182c847e1b4c95bbb157fadf3e924025be5ac74564656beff7f94bdf79ed16cd5b5ebffd2b5eb3f693875a31aab24efbdf746b79eda4fa67f5b52a6fb7ec2da614adacd5f5482d5d5b6018fce39e7d918238fe77d31a39276fdb78aadcdb16049bbf83709c2842c73ce61c31d5654fde64775cd9925110bbb48b00b5765f7bdf7768d4bf49d088c8fe172ce39d789020981e9c4962d3882cb198182169f1603b62dd92b5396296bc9000d18c150fd186e18aaa8b9e0325c56867158fed18807bc80a970b14407ea50531827d959e89f265a0c58f30656408c0917396519321ce141b568717b79503225d73b7e218562fc637a54111366110de68b5f8ec3d80b27e1d359224a4c08017ab4687ba3c4a47a4cf38b52208898674f1418319f3c2d061758d4a03dcf5e51e63c9291a4e38a035489a3dac94ea064c07dd2a18093f5b40288ab3744477bd2dede10df58937b7ba3c276b4b3f646853999a5090cf5b2d74b21501f3454cfec5f06975c50b75c7641c960ded3b03ddbcb7b02823a11fddab5bdbca71b130fae76b797f7f484c403eb57241e44bca71cbe751c87889420b243ca51d641ed4f12ed4b65282a6943c41b13d4b4687b794f2f7af06867ede5397140818556b571de11e69a8f8425d49eb497f7c4a3eea8c0c845a357beb5d63bc11de1ce70a7b843260246c40d95e0dda9dacd9a7befbdd535040d49bb383b3e41433bbd535cefbc7f1bb57befbdf7de7beb58a06301088cf7de5b82fd1f76a6ce3987e891b4fbfb29f56acd622d08416c71c939670954a27d6affd123b9f7de252c3adbda45e89c73ce3993c8e974cafb889c53e79c2d18112451b5671903d2079b6dc1081b0b440c7352e056fd69be9dec7cfea74e408a6d66518f99a5fefe9f9752102aa6ba0a7325ef8e5ba4e0d2fcfb38a648dabdca228a4dc051a60543971af4fbbbbbde4827e4aaaaeb948fa45d6070c294d0cc2a8296523d38e87e4da5ee513bf1b82a491c5a3aa8d689bdf7d6b51946499525c4595b25254f87d64a89352469b738018b8c9cd22a42b59a1e7cfdabfab1ea49181dcbffdc59521939bf2cbcde7accb59994d0c2b22d13bc84a5c9ba1e479338dc1ba34e5db827fa4c20067520a6032da110177e80e708afa17b0dc9ee5a6bed5e49cef26ba62d2774f1a43b2a586346a7243114080361c2564e47e34cccb860de955cb4eeeeeeee23691718140e8b3f4108d95740630217705d7d974532544a7777a42149bb450b209195a897453f949247246957ac6c759da30b2b16e0dd50c6522c70043c02a2008d9c569f072f5139146b2f6900a01c5f825e700ccdc234ac185371b39a718ac0b13b794ad9da1fa98a0a004032ad65984e2aa3950d8ab76eaad2a9bc58f97460ccf4ff6c76eda3f3cf66f3be35dc73849fcd7a84ecab3a798f90cb795832f46d8042252c210fd0dede0e0d9a44ad58f6cdde0e212ce6b9638424ed0ebfa8da62c8566731d6bf2b3c702434487090ec20f1c1455fa58a08f4ef0860dfe7396bb0a4babe24019aa4e601803dc2f090b877b541005e90144917321ac8d894687f4dae98504b5eaa6e3af8f6e879f3d47c99c2e118b3d226533c49291a205448525d67766e9be9a9653d1b052093500915aea4ddef0981288d8bef199a42f0d9dd3d454b75efbdcf9d1e4e569b81e49fff9334d7105c3717960c2d93a1ea55556b7424ed1af96a35c0ed239bdb84e741e66550a66f2c314c96a3b21809dcdd9da7219985d0978ecf082a1d5fa7cf5762a5229d17ccafb282b9e3c0657e7e0f84a5004a1db14054e15ce2904173c89170976e88dc0037cecc8c1b2d789411c9114389e7488c059baf0dbd2414a0b1d84107e6583600f7acdbfbe34068c42e81324b9771a3b8c7f90fa4c48eddab7cc7b858f5ffff18e31f5e23ba2c14159f6a7ff6da37cd9595d05284f13578002e24c9b2737b7dc518cf61337efa6eaf8fc88f6189a018d506af9d135b2712d2af669724c7d310869397dfc8d00f1a233b353e1be7d14dac66e6bedd7358eafe5f6eb5bdbe3020ae358e414cbeba96a6141ecd6df3badae0cb4b27e881bce1ea9172fdb036ff5c7b5c41adb7b7c775e2d6626d29cb17f9b5ca2e2225613998a2178cf753422a8bb7635173a3d69b52221d4efe776e2f53172f44cc0e520ca4193c8a8a9adadfa0fd2699a31b274254d05194557b1b5144742e0438011bb47279b7c72444a73dd5f63209d1a085d05ea620c51e72a4318992808d8c1780a929d1d58248ecaa9d453a88c0912188e70490ae00329e1c6c69f42165e3840b4962ff274972878afcf62ab918d371c1a3a3f93a01c928c6786bbf002c030c1019706bd7801b7f1db9346fd25b95644a0415e79cfde6d1c4796f08d2c9b09501d0948b5aaed16694dc116ce477cc84b2125a784e2e9c4ea022f0927a597a784a7a5acc1ef75c40dd511e2f9e1e2cb6c9d4880f190cd527561bf0a2c38a9c051f335b3b1b2ad881ccc822631544e86680d5d020fe3c88225ef91801a2db508685d58c1e27515497af7d56420b1187ff5c3367696431c6f77467df64d9722c3fbd00db3eb0000e90ed3e513ca14c92e444b17a1fc081b125c976bc0ee800d962018ced2900db07463c9a471b2881b463e1b3754336c385246778d1398e3d61af7d21d3a9e4811d52501a5e10c9c0e7d4095998d82ef74784a1c8ed1b1a122b94667a3576a8ec469c4e3b13e9ff3fc6a0850294f63aed3078feff779b5b91103982469a84a70c1a42a9130da300ac4e346e5add5e271ab752882901a91aa730133cc4df1903638cd1dbe63001c6a3178ef62a434baf21a993eff1909b154ca47b1ae3fdc56182c7b8c443845acca60cc195677ba3863439538d59a3730ff93b481d0cbb83c198188e9ec440ca0099e6055d0ad1330258d08862b1e1c708d109630a159efc67803a59b22818538839c1326c69496848e85683d7612ae607cfcc9090949094aa818a425850580e2fbb9f4472fe81a583640d92d88051a535a2f62f7e24b57fe347d46c8d3222f5c3a848065270c0d9e109f169b9309b72085de4844c653873e69532cb24fea0bd51452acf3842f65c9295e2458d1b6165bfdab718a2e19c8950e34445b2c04e34513b6e3bbe3ae07c4520b030a87345188941c5950fa8dc872e1b218ac282a47e401067900ada10840d2298189511153aa0ad0a54287e6ee078dd388188cca516503731965c389d29588264adf02063f364857361c90fe81851d8e9c18148881be70f493444c7974b54d8d61610b3f4f1d9edccb205cc040eb225291fa7138559fa8bb20b307e3c8832ce1345d8d1f7e77fbe482df69c23ecec1c9f6aca0a426a4785cb0a418b0b04127066b324f1572835aab6e7e9f3389549a8f46b9f09c9042a8016c319041400701cc771244942076d031480061ef870a4ac583c241406425118181085621886813008601800a0200ee3289ce414ae01c01f28667066f54065adea83dcd9dffb627ada62943ffae90500f1caa097b0b198a617202688dd36637b9a5a7ff1150cc4017838ab03f5af8deca678b5c76c262ed2d47d07630b5a68846ef72c2ed46801672270095c2f42ed34e1a819a372e8e580309786224536f0085d7c18ed41b57f84bdb16851241359a0a4f6039ea8dbe6896c22fdcdb2c8d151fe093992fbe0ea057050708e071859759266455d4d3e94d0a6a0e4568ee45add22d6bf066ece889e4daff8bbe6abeaa12a9ef6864e60c3b66c0e68c0138b65ab2cdc803cdc2f839aef70110e3d85173672a9697cc8cd352a1daa48d11db7fb2be12ca38b0a5ebf7832b2821c7c91797c811070e5381952970cd584065b84e670b472ffc8f7d765c17a3a24caaabb0917865b04d20b40dd605ab512b923364377711636b0936358988255b4b2344803aabf3449f21f17640f4769ee3523b41f302be903cb4988a402252515811253455912b148a139a97dc865c4ac6a0dc8ae96d8070a25cff6ac182bc165894d08ae32cf20438d571821346f29ddb4ba03ad82021d58f6f49b552b96d061bf02eb46dd1a950c473d505430e7178bfbad74a29ef8a20866a407daf6c02a688b8c77ef95383198e8e711a401d75bd59ef665f302ef528a22a6ed4fd63ec5d737127df72698840438b5598a8e9f6fce53fa5414e494cd8dcbf4777adeceecbb22b2698c729e2d50f33378a904451615700028ffbc2292d8f3484a8a141bdb676746b4f44031164d37a449e16c059fa957491c98834a0ea0f15bf719305ffb2cacbd42dcd704a419f0a16dd18e97a35a4a3f08efdd2ad5b37c38d9afb6da77ae993c270a9ee5d971a3541d9a8ceade68b3c78d43335f6269e91a8172531225237078bea72bbc4434427ed99bee63482030dd0a6304320e26b3a2a5764164af78017ca0c325fce659cb65e4646bfd5e992dc9ebee790a70fba4bcc23515398463b926b4660142283ec02e71d80f08506a6c8c328618d801ad4f1da38cf1cea7741683af28d51013086c980e68f80c0b88ee5a806ad3d78b66f8cd10b0a9c6a460661d6f4a491d5f977b2c9b1ae872f9d48d70089501bda810d7450bc010924be0aeb2b090ee09dcd6466712b16553380b471b5e6f399d76aa8b10014707eda9f14b87e853acc82a88e681755c2babe4d4df6346be82fc01146df96f3cedb2bff6b4fbfd7a9c21d89893b7a15cb460b2a603316570da40a67c144f4a999511c40942a4bfecd2185b4b252475c21f94fc25406816f64491a9ef6f388f10b22bda6a4470c301bbbf5e02d26886bdc220628dd42bc921525e282c51a9cce25ff51ec296801fc205734103850dfc84ac31f3afba31ba178f4d8abda6090a4cf21bce9a4add211b0ba8002bf7b136d8d89115bba0867fe4924c3215a8f68d2442a8a1517d048aab68c53b301ab1a873007b07230619cf4f1170fc89e8776e504df52e52f47f2860b7f7b72d7802e99194a97eb458a65712cb74290a9c11eed35e983d5714ba825c92a09c8be34637c630b1c6b9300039f11b0d299a0017676e1bbb556afb24598bfeb8c1a97017b4b4d66566cc887c70d15633287a8c0eb72bc094a13a8667b2fd284af30b78261f2440ab7d616594b6923e8ea28ccf089c7e1b9f646a4f131f3bd3da0c56e0ec41f13da53d3962533314388cf3112735d98b491c709d9184ee61b8ee0a31e72b02352bfd02a5e95e214a9ed9286a1c588713b5e0ffad10fd3f34ff2f24ddac2040caf2374e94f315db34d57e81e1dd10b81914f938ae6c52f837274a6b029917a92528cef076c2c89310ac73864adf89f2929d7266d182164c67816971b0dbd8ade721a377d5555d15b9599a6033ea5f50bdbfe0193c83db0319be06732233904d0ebd7c56ed26e204a9951c4b39153822bac8336420d92c04cc093e5327c3ebbb4633ad7d76be2204c14b0952259f672a02a0227237f836993920e896772ac79eaa55675fb55eb7fe81ea926553cf065835454b0282baccf594e6f894726fde889fe39eb1742d851376f53f4bdc616da5e83c1ab60f625b8f2efc85930e664f73e9a96180dfceae79cc21d6151705263aca4580b9e322d3a629a52e27ade972d47ee8d744dbfa797e347d757139d328790e56c4c998299a26d3510ea706dd72c44868b899eaaaef4b6fcd3015b7a88cae13ccb076bbe5655f2f2933ddf0709a948f0e78d7e61aedb6408ff38a1c771c82e5bea344a4fb09a9333c8bf46a3b8bbf10cd62f59740b610845f9e020d35048ec5199a81ec7948618b25fd1da47c1d5084bbf584a6c741e8f78d2a4fa9e33d4ed9ace5f31bdf56e06f07ba3ce518325536952d20827d84c15617839515ed72a1d382a9b90bf2303d6932534ed382a5468192298547b098be0bc6740d102b4ab35938b743e2c1983281f82dfa96c1caf2363e25558a9cbdda538726b212f367095bc393d8cf84695fc41880f23f3867e7d48a5570feee7e7d0f5a8d586ecc7409caa0f7feac41564eab95c328f1a462922068fa523e01bdb51c1645323c05d9529cbf74ffd7c114ed05b5186ef1c6ac8e515d747da11a9b04839012e4e816eb057c15a7f327ebe67c1acefa7ac0d39ee7358d440b94bb682f27f5cdb8ef3801760e331f364d600c44edeec3a3e3941650e632dd7fdcccc15b44be55fa82f1f420cfb8e0b4de87eb93a2a4e622f75925317fd1e96e0a74d0b834a89f66ddf01f6c7a61532b2393a34c74e240c79bfe4d26474ae6d0002b06c513dda3e6f654dc6d296c6b1ec29fbc448df2d1cb198070c04f51d0aacc05064584309a0aa179661f301e4b21f8f7c597d2bf08784a757843162106baf8ee29783c4733514951435641297266de7567768372cd79839552973769668fb87d503589df930a038458a41fd6bf2987e7cdf9b5971ff2ae508691a4e9b2a837caf0a4417975d6ca2fc8a873fc5005b609b1b1e8174841f8ba9325e7428bbeb103609f5f4519dfeacfeb596b38c176a6483ffa79d518a3582f2a6828ad847806598278aca080357a64dc697b711878dd4f07bdc53fd803e24f4b1c86701594b0bee7773778c2f4e0cf3136d15100ebc30de6fd02025e3ccd5ab7de53d6fd4a41b0c93941ee4f03a4d106fb8a33783e435f21a02207f5fa7520ce047ec9235824ea4fac30cc911418dc09571f5430610238bde80c8b6be252155dbcc7909e0c77647ebd16e94925b06fafdd3452fb30ef6f8d73358e138008af70eab919fd5abdf3e09751608de823ef9f7fbd3e911543617489bc7019e991d12f846741501509dbea7bc4be338cb47b50d1272aa6e32644266f1ee998b051b91443cc4a4eec148d68963ab3fe1bea0c89908474683976f88178cef055ae575e82f927a578302c2454cb3564c4f5863a997af53fc4452257313de50d95a832ccd78545bf8ba5e0503449ebe97750a76c2a465dad6abb1dfbc85577b7447e30d1ba604b58c2121792ba3c4b2059fb2f482896326ad40b76f41e71b163bdee41e1c3e8eaee27e303917fe58f2033a3b78b7de72f3226e827c7996388001095068449dc829da02f4a53515511ac567a735d68a258f25bcc845c87109c721c456b16112565ab102033dace4ca88235aa9f4e5f045b84f2123dbe6a343d221b66b4abe0fbae15bd721b319a9e240b0bcaf1668dd789e8721bd57ddf7bfeba38a3ced418719427db36c2cb7c338dde10f5c92f34a1b5d173133a2c9689f6a00c7f5394b96e4c3645646ad3854162c966bd66f26f86164ebe63aadaa05bdfdaf669425269ba13eeee7e66774986d7db20e45484d824383fd95476229f1e903a3b081f33fe3489d9c1764a9ff899315f970388ab2864379699f294b434ef6e8d1a26ee93384250a7e4a5ee8c2748ae3bb79aa2a989842b0897a268324a4d0cdaa2a077a5df41f56f06575503c06f443f60c197d33e9178ae097b09f529a32f611f7ff756d3c78a385674075b53be41ff8261960f354f93f26f683ca3687cdb4c11607b592ad2c4ec2f58eca0472f303d50462b52d469d1c4ecd454e327efb51f865a849587c392c2ebf5444b1a942d38a7a6464a990fbee7cc7beddce9748ecb2f9ed1d405320cd7b040a22a4f2d91abc0c4967235977cf3cf8480854a7a9a302f36bf9ff5f922875ac46fbafc17dc45618c8ac3c591b94c00e917e0eb7ea33314dd4a05805146dc70ae8a8e0ca4fe75fec4fe0cd8613acfee372a7e7ab7a271931893ebfcf18cda1391cd5fa8aff55560f0334fb3763ed1490a629ceee7dc5fc955c32dfa81a40c519814641a321bef382d2e177dcc7f7645f3c2b0e06aa8db7f58c6a48e2299bd954196fca43bb77b444ffe6e62b02219067da1a0a374b4234cea426b4408735ff7d86c4e089d040833cbd162542dd86ed5df9d783ec8ec39e4b136e26a98d52618bfee4796d6fb20fabd5aee7318cdacea8745d6b695a42ee3292da4a026344ff1f8afa2e6f78e993515d45d708952b4952e62381887c6ef2e2753dcec96a9ea532211538a9cdc2e6b7ea9f12aa31b0b7b27184d587750b5910c5d84580b984e02141caafcb75b010b58b66f043ab8424fa2abab9eeacceb43a1c5e75f1b88fad6a1f27644e639d54b6001f9ea6185e206d998c3a42f0eb14724a8286071b4cb5ac382372e617e4f61c51d9aa45b60f8a1782c7b929b47f1cdfa8ad032f406c044b990a563ab5af1d8d45f8bf013d10151d74298e6d8f5be8710312bafb828963116bfc6548882aff23a359831e5faa80cac7e3a1abdec461780cd4e8b06e45650d4220d238991ef36414b6573addadfe60f0f5f0646c734aa817b1dfeb44177ed26e520de0bb9c06b87e466e387b63da82b084c0af2675bbd83cb7c04cba5536f41bcec07cc07a10e9a57534538b9a0790cbe187e688ce73e0c059fd4a5748ec35bb460a883951e7a32cbe0119ebfe902232162f0af1725fb78e483be15c19c002c086327821571e2f2ec4dee44f4b497924bc6feb3e254a2138630f5f4dccc380bc80ddbe6509d6cde5a9c218877851fe1f664d2de222ffbe8ffe72698099f9ad6582b2f4e2835614846b1d819a1062424a83735386bc5f2a9d48d11bf1a1320a113bb6dc180ca9f2862eb92d8faf491ae0083d21eba9ab942ab5c152d3cafa1f9ec45f775b59dd2ee840b315c3ab2dc09cf86a4ad42245c14799cab7925da857d0cb381ccc45a0bfcbcf527f097c88793925662bf94674facf68eb1387e427a642a798c445590edb96264ca4435ecc4401285afcf2aa7db15b57024a4fd160ac44caf27a6d2c49baa3e9f1edd54112670080a5a43e7267c7a24a3b046952a70d4db09770f794502885a1f8214a96215ecefe7d6d7861a8da735b7d6ba9771d5924c6c74e63264655d8d75c4aaeb65185098581fff4cfd8240ab42f823f169951825e36dc05e4e02a2eb6b8e22e2336be99d36026a8f11163565ee3db4d31e47d48631faa157fb51fcfe003e50f901912b869e06a211913e2282930ace6e47b4142f8456802e228884614e147382b12894de960dd878a3835b53f38416c0996c699097c8e328f264049459fbb054a0a55e7e3a2cf140517e2e165a955fec97fdae99f51c6835e0de3614ba15053759080d5c2cf03c2d2f744a0f878626041f19d090c85206f04eb15cd1df5f887d9b0412e47b69edc3d8a755f2fbd1d3ce96b9273050ce6e9603ce62f8170052d5e0493c83c8d893a3dd444d57230eb2092fd5b20078161646b526d1bc24cdc9b3432f21eaa99e02c5f6427235fbcb3c39bde74b87edd293066e8700560f637a9a4c5b7abfe87c59cf6387d18497f67a3b785cf6ca03ed344d6ca3628cd024691dc40023d204c5dcfd8cd638bb1e04579c7533ac1ad22ce7c56ec01489e613846c452c0464012bb954c6ae2e9293bbc0616ac0abc2b9d7a4028690f1d77ad43a478d6a743442a01af064d3ed89d2b366428ecceae218590d3465bf0d71b7647bafc7d91107ee4895f837a9348ab2655913c7c1ea043532b9428391cdbd46b0abfcad40a39b8cd4a33fe21717b131801fab917da1b1c300d6d0b48c1506a809d3045643845cb378b559fa358c5b040808f030c1917cb55019926f9074f1e7d35cf530733a625666b6d76144a1fcb2ff13c92b48115fa429e21a28d076360569c05e484d593427a8c8ae7d65bd790a503824f469b5a1e49b57090daf358144f9d03c433604d0f5dc22e163ab000001907535d74e956f90ff3f84ddb688d2482c96a404b69430950aac97ca7374dae2ee5f905f083742a7ebdc4f67c4d8c1f1f5f7aff91a4cb8928c9bfad775c1b93eaa8c4cdc756a27004f7af9101608bc3aea042219a90ef147a45f32175e297988dc47ffe74dc4a23ec16fb5e78dec3ea57293221311465a4ff45f99aad734a50918f2ecb45bdb9d619bb86a66e0345de662604bbb4379c6172029de08297ee1776f75862980cc34ea9ed3e33a4d8223ba70d1318e65585ac0f21b6b83ca7595ca466b604ab274b225ab77d1d5d8dbbb4414e76732fc969b1037a044d620b5fceefc54cd907516433a0fe20ffc550c4e4c0833efdde78906aed48369cc9e436fec559578afd99e2b5462463837eb6ba6c4be877e2927c5cb626a3c1306d2b22fc212ae1b617a5786356848092353a54c83519c21c12ef5bfa1261b8c74901334c0d3c4692443e4052d7b682325d2f0c3775dab1860d919524f55e88051bed801875d8275f16eef6df56713d42832fe5fc70545d08d30d4d06f4d4fc1b59ffcafbb12a0e04a27c41970cc56813e53ab78c90b4c3d9cdad5d97bd8adeb785c689fae478ff8ec30328d8f2855c14f95c64dbe0d3c7a8f4aeea70b6079cedff047449b28674604b094864c824cfd5dad48b6604350c9e7b0eb14cc3b28a6e21fb2f53f8e535cb59317154bb5b0f0170696b3b317bc040ca23ec2ebd543ffc0154b8183db5d3bbd7987d07dcedf8baee4bc4c54be64e3f90658452919358eda940a841523ad4668b77ea1bbee4b8678ec3a5eb3f113449c8e0999d20b31e98cc4296b0e595617dcf84744ed36a3bacc13000c90d39cd995a5309fd99f7c5f2423e8948991c2a7955b78f7985dd220bbfed82bd754c63b28b0078292eb9f90e9fac92d6f56448400d5f6463e88235b212604809c10663b5981d22ba0e9a94641c0d8ee84a01770bb27716fce9e2ae61ff416dc39212cad83115518c4e1473017799ec3f8d610bb19dd43112261723042501c6500debf8fe3fa3fb3e00a7498315a5d2f67ffa14d385282659d2b72116f8aa81068649f5e9c9eec57081d2ca5ef2f059ae66fd7086515772a6493758ccca240c002ec88b1c793a740ec980800b0038def5fcc9f7ad3eeab9215ae0d02884810c684ddf403debf9e0de34ca44dec1616ae0713369c1553d3c2a4864086438afa760b62226b8b4507188cb71067c8268153c6f135439c6b6642e1d10f9960d8b11418b65e430a2518019cfe0940a104dfde0af1cb20fe554eb7d03712ff1415bdce3957975e3b7b0fc7d42460a0c359f2c525d6b1d7c200c7cebaace4b332bada00a08379603f247e0b92a2312984020f9634939c4be67d921c0025963917b2002647a0aa93c286030b354e44e3045a4b2b2527121fd3e656fc7beace8a0e16ac4dfd9e3c3f0a1ea0408064c4ae898084188536272aaad61148c97a63f45df10fe0833cc9775b9ed5e150fe1ae6777340f9e811b0fac7fd18e244dcd7d4a02b5902cdaf361532e13a11754fb01a4f474ddbff2a7e64fd12195e96a5b65b694790e7d64049b74277a2ca34fce77e990ea48f5482cd5ef7ca1d5b007499d23b0a7be07018b27070d66545a6c8597dc261a025ab12473f7e0bfcc0277b5cc4df5b21c9de4265527b36154b0b59abfdab89a47589196d0b9c2d2c2e7c4cf810e62a65d18cd00b8f76869240051c3d590e0850056f8ae9fc4bf044c069626429abf68385df573a11f877f53eca2b2d071d938312d8fc90d42f7c83ef3f2e3f5f6edfa7448701d7982551a0aa1ab4aa8057f67bcea3b5d4ebebed58815eff0fd09c292fb73cb0ebc6e1ce82147619fb3298ebaec8dd57ccccb9365f36d57bf52f23486cc3079171ab631cc985c582d785635b8edba2dfc3f53c67c93173e2f6e31bc1497fb51f0931911b18dd12c829dc55963611d8a5b56400b9f60c91ee664b8137a85b2e18c12c313a49404bc1b9ed33496be738220550254eeddcb728c334a344d9951be3f671786db6f5d0d15f8ee6023b6971483d6a21c28a47de68cbd192544b33751521025bf5a334f637577618fc344fe4ee21911d917fb64892780c3425070856c1d4087c72a5109c23aac64ee60aa499f6a4c6a686034de4180eba9a0fb0ea205af2ad6e8394eca28500c27245821a26ec4e576c736344bad18d730b60a9b9429a58ce20fa8a6adf5e07097c16e2aa6916a41866ad2656942d6fd20306ccc5bdf3a53e713f5465bedb48fe1cdfd8daefd02a76199bc016e3b1393ae2c0044186c59f6f3b97545b48b8e6d1f62be6993ac790ed74a38f78f4352c732334e9a77125d545030ac6ec56c2567fe5b7fd4158781af6ef521ce96c1630f0759b2d2d73da3006a02ea4e9d5c8f1d41b8b0f05e42bb8a257c3e51cc0de4e05bb59ae0980e461a05c84d1ea7f38ece10fa694d1357451bcbd7e734093bd3a25369391cf46078605b042408dd34fdcb1789eca952c270b33f08b2353bfca65b6af5c84c72bf4c530240233b11716be1cd9956b66130fb5f08a27b8dab65a35f4261c399bc1248427598e3b5fe5767ead1ff12666047a33ab63f0ddc50d3268e144892f302c78efd2fa392134e0ad4d082925b2a0aec91483783084279a847323e42602ec56f3439adcb401afcc800591aa56cbbbe62026ec80c3ccfcbdc75907c1d1def7713e1970330536a8c8b6d467b66b3ab8ca77fb58ba16e85bc4c339afeec708bd65892b2940f7f045638ef259afc477cbb4065cc2db4595859a0cab82456445f1e15ed553d509056d7ae0bb351a071f9c905d862ac2714002638bbae1f958cfaa6084f49c95686b9142396604f21c2ea80ed95a6986a8f7756689a32c54e1fb01eaf626460b8e108645138ee451999a201aa130af18a3aea38d38bcbc93106b12f07c1fab8acd550b2c40ef631ad200caf4563610c747de89eefabc174c2c20c6cbf3e3de1dd1d3e7d69c04d937d65b63bc1122e4eb5b8b79e86f800a1d6852f0294590ab51a6b5e2bfbebcee6e0833302aa7b937a6086805230b42d253d4c9664099aab1b0f8b6285361c1cf7288be8c5361a3e65702e90531a725d71477d8cbb79e7d15b006a62330c822fe6d0dcdc05861c09a3425b3980035302de331b501d886b3a2e7705748cf1a1661c3be01e029602a1e82782244523a878808f0f38b9b9c82f266f427735aa2217d09a921dc80b04e4a84182612a600a7c6729451eaff4ddc071f064f49841d4340253a7385e54886cbfc48eddaf09bb0754422b7203bdd926cc888c9552f11aa502dc151da83ea8e9167c230bf18e8364a65f721094d1fa42ff61ac9bb86d5afe014b972b488bb7c5a94c2488a356271b0c53e328961c984b3443876d986ac24d9190f903fa2282b7f08305aa8c642fbbe15539bc4899c8b7f9b048aad8c277680821811544e81696f9c0da12ffc0be7a5446711c90455209ac41694d930aed0d04fd43b2ba2af46a1d3fc68fcb0bb2ed07adcb083a18b470b1d741c991005d1d564011adc6a9e6640bc6a21e801e60d9fe4a75ceae7348670585f276a9c9093a42b6d7ad365668169729ae119b15b98750b4d388deef777a559ad7092b9bedc4a14a94a350df5502f7531c59c987da817cb477ebd65c31cceb38c819927dcd2fd2422226cc0464d5e6c31da10fcaad2c8c5c20544447d8e94d653d4c74ae1b82334f203a64a0004b388c165b0ffa704e1711050f19a24972361a0e375032d1a7e6919367cecbaabcea7d464a3b5361ce42d0e1e81143e97fbb06b3922ce14e2b52fb2d09db6b4848791041513ae22f85589fb3473fca662640ced1d76b74379afb01dbfced1aa5e150ff23ba92d64e327c72aa56a9888a12ea7e8959eda9523ec2466b1693510a8464d09837a3ab1cb3d3bb13427f94f4c607a8807ff074fb1e657ba4f0e52027aa4a630a5e0b2051d350916e5bd448f4ffacdb66586135b080f6d05324550d2523e23f146e7b47de25ae88d50cc9a83a6d2e6f1c151e2ff8c400afb376702ed70cbf8202dac0f91f1e10ec40fdd8790e3b70134464988dac9fcb690c0d853bfd10e22d495fdb6d4e315fe73a272cd4f564d92b2c4e47b0a0a93167c27135cf01cda0342ab170fc9f8e6b58003b43a4ab5fec10f13c3459fb91b7bcfcea5343e1e09a70cf6af857a6db8306fba130e10be73c84d964a34af0ea6e5b7d59f3a14f1f9926d4b34430c8aa09ced7edb1a1c72ebdf018991a330037bcdf275ba1a3d1743ec71836061be546806b82166a90f5803b3c0da6372fa3735308fc0905024c82b30afdf8be9608eab66634113320dfdb6066762ac03801a9a96b160c09a343db334016a602ac63698822c3d17798ae9d896393531b6089e7fb0fe0f5472f1f027126a0a7b7fdbf184675327d58859c5bee20e8e240bece92c889d62d81833c54064d7f7b33bfd0b321d47ec641188f502c513ecb5bc4805de114d18af0e4b195fbf66cb62a26834a749d05764c03d93984a132739f7081f10de28b8d141e51382eaf47406310e05b0d2ced5ead26e4e994ab244f5ccd5687a5d888e466715ad8f9e89a7369b58d1cd1c54ec2d42b6f87bd482312a8621910e36b2f32f8b288fa56d003e8e1c099cd25e2c407622f2858ddf15d046293862cb683c731ec306237eea6e243fe5903773cffff324444cff0d5a4ad20393cef01231bf7e9b8dce9f377482d283fca4483220046a7eb4e545401df28c21b8f8a1817c89d5c9900d77dbeacb501e7d9cea78b66842ec00adc1c5125e2f6855c61089dea751b8015e301bf7a7a637aa1feece550310d2e8c47d3a48b02d78a6c6730a5ebbf7d1ccccc7b4d16fd330240f7cdf4e8e6a6f6845b2aff4cc1f18c7cb1dff5f708ca455d7ddbeea2d6be7859367a4126812ea427bab80ade40aeea464addc3ff9d9978830a9473291c6ff792290774ce3915992805dc1fc67afd4bc74fa345575edb0b0e52632d765f420a056eb50560d20a093c8fd03cbf2485a977338626a5d3d8f17ce6cfcb5ec49135f33b58936f0ebb660305d792dd157181c422ae0a8c848029a244a6802146a6cc1d421659f7acc4b27fdc5c59d326626ea421ebca09b937332dde91bc0d3ab4a883af847befeb1715a767ee141826a117605d9b2896851cf2f9d5294a166714f5e36a7984747e5886394c3cd1f23372cbe79b3e9f5095ff0142a6b60ca2f6e352187284b0a7b467961d6d617aa99505d633307c551d4799d900d70c2222b0211c1b5c6edf82e24e0173aafa5c198c6ac5a6191388d9733f788664e36225d131ee8c992377b68b1b6b2401385362fda54310d14d8f7555062a92dee13c68e605f583ae89a12b988a95d751e0e215a5026520d86f57393f86d68cf21da448377cf4b7a07d78023f5f2ffd3023e7ca530615eb4a3684549128978bb51048be7c162d69134885438008eba862d6fb6d55d5048296a462a5cef4714c0de2c203aa5dc88719839d864439bb1e2d0a68937c102262477d8c192725d6c15b2a9d8a5217e8ca788fc04330967940646943cadbdee384fde639ce1f720a1e727e33fd400193a814100f1af2215868392ec9aa34032cfd99f9c063cf5e6555cde7bb468ef449584c973422ee26ed413ea942c777b22917fb7348351acf5f0b92249067e2ec4ca38666e4f01afd057416bf9f1dc7cf97ee025c555cbfe58a1d40bbea47a220aa156fd92002542d004f296d893f41184047e494c2effc5006070b5b21d76e6c4ccb2f14dedff5d83754e33ce05ddb658146875b85c0a818fa83562adb6a66c8c62467706d035a320a384fb156fb29991925bd2857977ab79b6fe1c24480a53b4a823bd05ad640792ef8ff8dd837b6ca4a1e64c00eba3ee8fbc830bb3bf9aa212c51ad80208633851121724a3cca8fb4fe3ddad817ab1e4ec74152fdde1e88112817b0f071dadaeea93b30abc51035d9d6b47b48f939d340ce319dbf921954f6f435e6c2b413732b4adb9f4af4c7bb47aede2ee05ae8ea685c06394bc7bed0dcc85c990ef4de289c14b67f5d1044ad6fac39ac4b2c8dc132b7c6d191705e9556997790b93a3a98499e93487adec4f95d08b4f52081bf120e1accc7cf07a846f293070f188184be673d8c5b010d7428af961c1c448af076a33247547778b342eb6b9a28d17882e1bfcee9436195a30a520b55a2b167fc82f98a3819638e854ff14d532e14e69af7bf28b35194626e02a22b77cc3a9148e43318ae9b075aed335d9074622fa5d75d2cf4fce156687ac72a26812490a7d39eff5d20a7edccac7531efa0d01c908cc0687e162e333b9d7c433271ac029faa09b2ac772e1b0bf39629257cea0dd0d43a4f4f8375befa79c7fb7d6bf85928f41657c8e14db7fcd12041183dad761788151aecd8bb2a5eafee9dbdad7f9454cda5c0dc224e94035a192eb3e914dcf16f7940cb087697ed8c2064ff4751bd170087a2135bb5464e73b099120f207f26e8c5860994a54db761d558accaa59774a46973f7bd7593a8d2ebe5a16c60b57d8446823a90c55a7dc1430ecd0c46b8420b3e5dc38fe96f774a91ce8e423ca484cb56a12dc2636e241c8d9b44962ab3988b8283668e87527c4e8b68f43f618699bbba06835391b6ec2234fef240719c5240e81a7203af8324520567cb8451af862fed662ea13ffa2da79f7c5e21d6a178323c9a64b07811d2f0316e4c127d3039b341c1e805df056cdb2d7486137a1ba303f0bd6e572a3502fc13665cc100b42d21771e6ac48a0fffa983944caceb5ff8e17b98b6c7c505851a3ce086da9251c5faf1bd99813a30ebd579517ee2291415e5692bf75d138cdec79f2c3a374d0856296afe4817ee2af8a441a8a4e760dd81e9d8f13bdc25e3214f2e0c60285b8deb302294a61a435951b1943933d736da702ccdffb3504fe2302870c8fd74f1ef10361eb5d8ee7fb043c56130797538e433ab361f1eb57d033404e409efff856d48433bec6aa627ed94fea71cbfb617ba732fbe021d50ef6d63e2ed0e00e0473e96b5674c98fc2bc4b2b3a85b1d0b647867515ae4670400ef75567f7811669920069031cf38f5634ebc800cc6b4f4be0e17351b1932b13b2becd7d99d04ba44f60623f7acadbedc8755d1abeb7550398fb147df58da69eb7e44c476dc80976c10b204ea7eb3d3ca296c8efd91210610addd57b7e4e6002f6e9d39d10d25a960252fb7156c34d887ca3a8176626bac05d138c6ca74957237c8be06135c9783b98f491855b8f1237834426a7cee68658416161db7432ca73b06b564f7214c5d87ffe46474189161e3a5206727e24796f2185226cf51660094dad042214d5a5cc5168a5fa438ea3769b79186f343dd0b9a29474601359289e2d8031311810c44a4886b3661a16ab0fdd4b338d3cf84640b1351e9a49c21a2789705ff831f8a32c5f5c5e965ca014a4a358cdce4d9c058ab51963c98b36a46e64df88ae557e61fda14750f82ce02ba227f87059b2d8428d13dd3881260a372f6ada74cf02ee7d861b9a5ed1885c1fba62f3a83779356fea54182314af8958185409011ac2e02b5360502d752bc05200a611ef86006f0049facfadd33b4043189165817c6f37302b2f0510331a349987bfe4c3d92c455f5748f85ac527e50dbf594016a5f27f60a8ffe0eee68cddf775d6c0e06e3225b9f7de7b0793028902f60238bceefefafe7d2da4d914b1c90993e996a3612da8b8a18b4c8a498614965b1766de9470e6e6e6885cb0638de3ddb1e52b2d9ae307f7e63c570419d2c919ca814d25070f25a7793bb72b486420128daef6f69e78dc2f31eda4b6037f8b65c6b47f3b7552cb7291422d5d187064a74c3a37d7753f6c5d8a1066dd0867d22577879d32eb5cd434c02a11c315a5d3c6f4da776a38247ee8ca84dc2eae66548b3c3724361a33974b66e5a3c9063f1cc14d19198d37dedcad98a7480c8e027e39f48c50e8346bd45c2d99127a2973c204d8cc633acdddc031c22852b191ca199978da9159bb41c87db26831230ce788e985132de929b4b3e3a5234756ddbb74fadddd47b48fd635aebe5ca02983c6a228dedcae9144ca7e5eadca6e9d5a43c91479ce1f1db1a967c1f2b1ecf8a9ff2b0b90d0fab35382eb2a04cd60feab0be4dab588eb2232dccb4151b48a9983069559adb85869dee639f805229503d65bcbb64cd8539d59330dcd601e6b30d7d1ef596badb5bbfb9b5fffcfafb317e51c4cb3fe9c73ce2a307661ced9b5ce39e79cb37e93fc9ae9a1c84e9735ccd7e94b3f72cec1fcf4fafbeeee45f9dbaa37e79cb3670dff84b04077ffec9e757658c71da8637737c9f11b9b9cfc762ab5c663a7c4439066dbce685938d5997df54ea7c28a2d2b63c8e8890944c325e72a8dabc17662cbc884666365e2e9ad6b08080c8d5932e4c423eb065a44bacba6da546a9325b4249c95f1bc29c9c545b9556d8de1ba9a7849b883f9003b95aa81ee77a75235643d06acabebdaf5bbef346ac82dc79d5e5aa2190174ec5143749bdde9935457ec6ad65e3a63f95c29dda64c9e7f42a3fd2ef48bfda75bbcdabec3bef7e9e07fd07ebdd3a81d5ebaaac7084bcb4445546586b495238413e45229c13afdbce4da26cf6d8501477b5d5593b815ae6b06315cd7f524042ba420c4705db3f45aec755dd735a6605d637615b6357343579fc6ce09ececcee02241e064c69a1f90ce781b3169d3cc9457480c00fe3f141988d0dfdd1d2aea03f1feffff8bfddddd93445dc0fbffbfef83bfbb7b522713f0feff9f3c820ce0efee9e247a0578ffff4f220103f077774f56917878ffff4f8a05fddddd936a2000bcffff27e9e00efeeeeeb089b604e8b176b3fb3c3fa00b55901cc123491011e70f561af38528a5691062870f9e92df8b91f729c4d72cd148b48f47c285f892089da34894b8513dbf36860776e92a6812bf4f082fe5f800fa7cc2f84d62931367d48a7881a410627694f94c4565b0d292a242da773edd2529693787c6f5558d5f14c9bc8559957889d151a51202dca9938a8d459b6a0dfd41ded855b71827a3168e970b8a9b43aac97faac4dbb641b7d8b626e6a6423c01459b5a424084b34c202d216bfbe9063a3d4b49414b7b72389a586cd7755f67bb71ab66a1ebbaefbe27c7d624fe9d3a9b50fc64c45044931b1b4a8122cb3d6b9ac8ebd0b23b753215c1a9ce4495fd31b0fdffef008477ba5c71636b59c49ae967677f7fcf503be79c53d8850f910b1a796050941c7fb46ae79cf5e7e8d2ce39e79cf5efd42a7ae476bd2252aa4c9cdf5d6ed7fd87df755db7c9b95dd78d63d7cdc2947785ce28b8fdeed4d904b6e25d953e103cb06eace1f528eb61b602555b189a8a883c6519d83b7215545f75fdb16fcef957537307ccbfae292f3b8e4412644938289aac6933037c6bda7e3b6dd69cb961ef9a4c5b59159cc7e2560e0df4c7bda1dc7ae19d3a955268cf1d5fd2e7be36267eae2bcbd6d5832e399f1262348ac6b1971fbb5367535469e7ae68f19c6c2d466c656470ae58cba2403174f5a77d0164233d474f21386beb41eb39118506e5711a09eed4d9538cba2b0c0da2295a228b68b86b3ab00e57513022528bf15597222fa572fa14478e64e9096bcb213c1b4ed894a9398f7123b1c9c971eba80cf9ad16ccd0ee16e2a72105164630613d69e335fe0f8421b424d490e3f22c7a1ee9c968416985c3f40304766c7fb0ae2052866129216eec945449b6d3943425addbaa1abf1ac36a1cabf1076a3c821aa7a0c630b06b6bf6b2abdbe60c62188202e74c8dcdee94e1763392f7d82b1b3fdbb2ad90f5ccb2ee8c8b3de049909e31cf066fc6e56e46c58eae2e4a87361726f7e45115f70497f4f6c24d45db318ab34306864d6604d46ecd4d4d47da980ead1c4c34281c4a673998ad28fb2133712346662c862886170607a6f645e6c5d575c515b5b5a4656463e889c2b9930543d38461c1d2bbe26105659a2dbdaa9a54534a1a5331a45a44012579a05e6a6abcb43cf5709a6bda41030713d8921349a5e434434652918c1b907a62dc1cb9bc18b988805197431b0e395e8815d970b16c518368c6100e2c8456f808e5a86889b9a16525e80ee82d451a8a1b366cfd58f9248fc81e1846163c369cd0d92131a343a268222f270e67eda6cca6ab06ab84140dd3cc910c514c0a98132f2c255c5848b4ec919063612b9e11bf56b2462855114daa0a520f177b417ac63c1bbca2cb5d51c58eae2e4a87361726f7e45115f70497f4f6c24d45db318ab38308c3461c01b55b7353d39136a6432b07130d4ae3409e199911950191196fdc8cadc088adac84e181c57d41bdcebac0b89e5b4b2d281bc8a79193280ba869c4bab91a016335628589b78cab82529d29c1a69e52cb28a82412caa806d113d03b193db8e940040c07225636c0d3202e0328066721c02e785ab0ac008a02e404461210450034344270f3008c034e959506f018885b00aac0d90958024f0496074099200d30121281008a8d05dc7ce80143408f9501f004880b00eae12c0806c0b3c3b2040a8824311a211201828d2137207b301f7b2b3fbc37ee7d6c1aedc79c2b375daab6060b2357601c84e110ec1afeff9fc33db37580f3cb55f2daf7da547de837d8b46952596ed610483d259f1727da865cbdec8c46f51761809ab8f451fcf111b97e05e49d955cbd5eaa08cf2063d3c799174579376f7f51693f71ee3d0f8938f8944a4f1e3dc923a8a4a70c5e1bdc87ac36aeed3bcd6a6bbe113788fbeff7fac97886e25e34dd5adce1ec6f6b3a70bb6e753bf861a7556e5fdbb7d32ab7265c5d344d474e9ddb6a0cbb6eaada759798ea3b5546937cc4c3925d53d10c5c574f8c289c5d5d0d23768a52307814c760727ea7a02ea6b5a0161b2b284eb7dd6d73c9eebf7e546fffb3ee9c2ab75342a8ea4bbaa632a44645155d6184d28194951c0d253d16365094d1a6b396485563587f1d891b807c73b5f7df4ead9062ed08d41ad1ca6b256dc7e591de80326948dc69adb9716afc6a0c0fd7354dabf9e74b9f7ac2645400ad5129e1689c9aaf8c26f906cd1134314b4dce1a14edbe6d0db7f55503eaf0b75365f4cd4854d5188e9325ee47f00389b8ce2fdfd5b877c48f762fb3ef309daf716d96dd190c03833e28c94eb3ec9a5610184bb0d06fa7556f46cd3e5ba4d974dabeafdfa69f47384ec945d568dd30dddeb87c6f6523ef4eabde985e0ebb9560cb394b3961d917b458d65894c169d1b86daa2a9273ce39e7ecee39e79cb3bbe7cf9e6d445477273971387577ffacb5bb7bfefffc314c2441909d2e61e442ec82ae6a75057a217a5b7400df33d0c34e972f363b523915d6e967f605ea4125f9e58bd57b0660a7cb1724a16156fd9d5b7f8e7f71fe0975acdf0ff1e28bc58dedf8d216ddfa7098aa4f6d78aa4d11a998137361ce7403aadee912e669473fabbeca5262ffab451d6df0a78ed4ad8f16021e4d90e0ed7c5c99ea21eb49f3eca6edf7349f9c3c453c40ae5a8971e1e0e821c485c4660c8bbca8c42af8b7682a909b2000231a040080601406611c0972de62071480071ac268789c342c28243020100585016130100886416150100c1a22a0200e832010e35892dd00bf1c82e5297e43dd4a6a1273e9089680ad343a5e2e0f5f118d1671378a790a58ac884c200a82ae8c347bba93e195a1f1ea343fd5eb5a34201282781fb2128fab0f5069658c442be21b00eaeec43a5d2b803b0eb357c63e6ac6ef9b171433978cafbebbca9e364436f37ebdb648d94d439289c4eaf10a6077106c35cc00568ef7e7b3d5347a23feae67fbd745a3faef7b88405ee1bfe6146176f4f99c0ff9fbf69df6a4aa75b0e7d5b231ca71a998ea9b550dcf96031983a42758fd77035d169401ea79be5ed97a7df49f2954019d3e2f85f0061ed9b39088672c325187f8a515b467a58f395c63ecd0338ff90551b98912a6418181b2a056b4de3afceff41669ea39b2020bc9d4431a658fb42a2e9ecc5568b39ab13ef44148a68d0d7a1e5462bfec0614801650aee6ceccf7c9c34f7698ca42c837d411aeb3290af505438d7957ef277ff12c7c4e449a0c8bd4ab5f1883e49703bc150aeb02d910ca7099836ef8df36a835042942178aabd67124117c5e4bdc3aaf2c045e524ae534ac0d97ca95d5e1c48af0054b73666ad2d42c97e9c548aa5f09635e34d887dcc80e85e2fafa9945a7901770085957aa27cb7a7744724bf25cc9f1678eedaaf936f98d1e69129e0108d4e6409e0480d5ef089681bf80ea190e368b593ce7393d1f4737551b3b68431118b540f64c024321ce2870ac996687cfd083f00426934088c95fdcefca9c51546781fafc271a760e2a7d1834aafcb4ab5fa6a46470b49b2f459905b3b86a686f3bbc8a6aafe100eef9a31f7454c3274c5a0159c2de5e287ae8fccb07836dbacee7a59754b1b72c629dd5687a2cc3c31de1de10d1a9ff9a53d182233d4ac55712984a0026402f18689a88fc575a3611e257858e8caed7a2b0a13680aeb5088cbfc0381b093d561fd34969b2890a8b8ed81aededd6cb381e779d08bc5a75f72a8e9fd4203763f781ceb37550641bd61173ff67446fc0215cb2eb355241e080d39e543479880687ac2fe611c95ba481f524235dadfa65af4545540cdf10d0903ac0d32e545fa66c516773cf1ed557bf7910851b9137a4575ad66dc0c1da09e13fb51fede83c9876e8e46534844184b190879d1f211f372e38eada4f7f59c741f637c8f513e0d66d672b5a27f46e0e7762fa2682e09d37f55e54d7d1caad79b3a491fa5d01c246341b816cd259671e945bafdc2f5778e426c70b589e52ba117195670dbd2b138d935cbb5ad98dd09c476ec41f6df111845e0af0bbb33fca0f724049be482a40dd853b040699beff5b595cf458928b050749ae2821cf6d844f97a91a5f01c4a19017b940bd2a517b23e6d45d5e7854c200bfad88637d721e0586e7df23163cdb139178953136323a7eecf37679dc64c13ca375bae84ea2fa86d33cdcea82e7c435c59ba51d92ecf139a8690f24491139ab0f6191f56c24c6b3c0626a68819677d7c57f89acfd1c479cc73e04adfe8946c00fbfcfe2e638152cbe44630ce876d88d312573520e9e6e27cb1ad35b308e232fd60124db49d3e4ff81f84d0ef96b2538a160b7908ae4a3a09087a08e01483abf33167c399be1141fd5871eebddc97ea2a2d3186aec370fb7781f19c8151eb078d69bd2bda35f530e0ca5fb9c44232142770b0ed543b27409eaf5fb15a478e724da13de91f19cc1618ac0ea81a77361f500f950ca523f79b105e436f4e0d6bb2d1decf126a1001e99e6f15c7c88942f01c4c7e1fe7b04cdc7704d17f21064463dcecd416a771dbc5dc18c1b1d6f573a2475a3c4316169c32551e172859aefe0a2a9218419fdc54ef68f371cef362568bb764dde8763001cf2a4173bfb5348b2c69fccb2f5314a79ebae171091fb626f2ef07de6dec3a0efc4996c5fd693f0fc36c36f893d14141e1833e48555056f37eb26d3395c6de32ec65bd598838a72614a19b1d4a75fef81615449dcf4e2d14b381c9366202ca8067eb958dc6b58c931d725a134fef194fb991bdc0038ca96908d768666b5ab2b5223cd07e7bafa26e64135b80e993a0d5443401290d48802867358ac15fd092832e8a53968d31ec78ca0022d525f86c5e69baaa724442cd8a7c7859947d26035d8c0fe9a5396763aea7fd2e8efc80a83a79a45a5eec6b593b9bc88e94b85f4910e417136ef4627b8090ea4a3ca3b620a66b90e9871ed0c82201a5895de984584481b9f1578614f5c93d6d152913bc60e24c54a9195495f4071cb0a7b6e3028b1eb57aa2c75b82e5caea9e7b43506e1f2366f13e08a1203b4b62da973cb5619383939f2d480285a9419528808e70858f719fada3c3a6e80b29158f7fb61398aab724970c600c5c95ebd36b32bb2338391d458802256a40b4477f6bc626007ce253b678082126af840bc7b9be8f40ef598b2008dca2711290ce597361bc90a0048b7ef069d1e6e5359bf8c0117c9953dacc76e7c718f4e9708de9098724a9b7c3dece8f47841d60e652f2a10e46c4335ddb47dd6a0a6fe3e269c8965267e9c6c235bded7e20594a13b8e4858a275126414c1966b6735c6bfd7af8f24d04c7617e6d17c08e1e4041983a9fe08537791fe45eb69705ed338a8325e17f16f1307e6702ffc0f91cf391dc9dfa00de32a51b640f786bbd02f39a895e7c811816ced38dc202d0e3a7f0870f291d01e0ec73c4238681f8c8023f2769f6f38779637e853a85b1cc8631222884517f5f045bca402ee23ac485ab91841e230f2ed2eba254841be7d68e1176d6fc2d998e3de82161b0c27491734c28ea231c0084aa6a884c055e0148e30aacb0283a44c0bb491c071e971b3215ea7c4b38ddf31eee178ff78a0636d8ea91f0f32dec498bcb140c75b8cc98758a413ef624cdf58a0f126c7f48d0532de654cdf58a4e34d8ee98f0532dea4c4e4552cd0f12e63fac6221def624c7f2cd2f126c7e48d051a6f724cdf5820166fb262f2c7828e3739267f2cd2f11663f2c602196f724c6f2cd0f12ec7f4492cd288b71c933716c9789363fa63918c3731a67f2ce8789363f2c7221d6f3126ef62914ebc8b317d6381c69b1cd33716c87897317d63918e3739a63f16c87893129357b140c7bb8ce91b8b74bc8b31fdb148c79b1c93371668bcc9317d638158bcc98ac91f0b3adee498fcb148c75b8cc91b0b64bcc931bdb140c7bb1cd327b14823de724cde5824e34d8ee98f4532dec498f63cc6838d3f19f331367dfc1a631f2cb6dfe2818cfb1ca33f1ed071cf31f2e31119f719a3371e90711f63f4e311b1b8cf8a911f0fe8b8cd31faf1808cdb9043af9e87c698118dc139e6717cb97124633dc6a9bb38a412eb314e7d1c92b19ee3d48d431a6b394efc38a4633de3c48f6332d6729cfa3824106b7971e2c63119eb394e6e1cd3b116e3c48f231d6b394ec1cb55885d1d06dce54ae9ba7519b0e7e8bf7e95a39f9a1fc08707418d51799c67163b7ac5a2383ef238878f8f3e2ec6b1318d396cfcb071111c8f698ce3e3271f8b636c48e33c2e871d2f74de8769638c42c69f8d8b617c9cc63c3e7e6c4c1cc7c334c6f3f1c3c6a23836a4710e8fcf563131447c94c75c3676d8b818c6c334c6f3f1938fc53036e4711e1f1f6d4c84f1511af3d9d8e91717838ac739879fb605c659aec7a93836e6388f8dcf3626c6f1518eb99ee1263cec7c053416b6d016585a5e17422d7f6fcbfdd481fff8234e2968c4038b45ae0968c64e30bc33d3abf9e7954106104d21f6ce72fb4d1788e6105665bede36f0416f75e6c6020e4cbec87973c86187a8f81fd06f978a43341dc643759943c50f1ce849125be4f6012bdd44878edb9e726f543e5995d5c48f4d6821f54e6bd704acff791666f544426ae446ead8c1362d16289bf4c2291c38d88ac241ad97973dccaa24e6e5f8232e9d3c7507fc203d8b39eb1466ee5d51d7ed6e9e943fb39eb9e3cbd3f2c7d073b7f94f43824fdda98facb36eb87944fe3265de2df9bdcb7fda4e7d243d778fcfa1f29f29e6dd79f944fe31f48c9b3f8f883f869c73c7cf51f9c79033eefc39227f1872ce0d17559e07fcd421c37dc8c3809f3e44b80dd810f452fd8452b110e6a8abb22fad70a37f9f4969fdbc88f734b54f20f4a7a4291f0e7cca7eedc46ba7f2d60aa70a62fa1f1caad6e3ddfe79bb7bbed9c5f9763f87fbfde976ff78b77fbeed1e6f768f377b38df76eabcd9d7f96e57e79b3d9ceff6cf37b8b3ff78531321aabb8150cda204b1e713c06a292fe846b7ca56f88bcabe62c1893e1475488c91d8bb23d989308c07fb00ed29850f53103a0a3b292dbb947d8227e93111be84abd229b564bc416d5c94163b8e01e77979ef32e6fc541bce36bd2ea69b2489afc84a2d4a5ada5f6e8ad8db9bb4c4832ed6b900bed920a2640a794b7db55d2d861645551373d745b482edc85b886cd8dba291de6ebdfa6e6483ed6b9f0bc8a47e56d3100e381729fb04a1a2078c46e5c0e557cbb15550daf2f17ddb86c8924d0c5c4255074cdf49f867437f80dbc07eb757b5e725a0bfd51a81a2a867537d20497adc32294620cb4a157866037f1f43be01fc24f08282c93662260d7c226f5839f9322991668ac355eb06c231cbda692b26aeaaee1169b6ab00fcdc115af75124031e2e5d33f2f717aba10ede1c19686184ce127e881c82979514742fa36af8f964ed6228876ec04164bd122f7d84ab0fa9b616359010d4132639237c8f0c3c57f1e15314accb87f96a495872632e460a3d4ed41a750cd74558b8fafcb1b92536dd148dc7b2db0eed52140a7fca71660cb0b92b46ac95bc5d6b46a21fa6e10caa206eb4db114faa91d5ab6dda7ab36c6d24b0e2e52f97a5586c64e7bf72794296f5cafbe48bc788465c04f7dc8972d9ad5950c57a3082fe490e1a58160203e072edb285cc495af9fd753a06f030c4c8e107079bb8adc32e3d8786ce42da36ee3df04156c7c0b34347a9274f914a2699887233874db1bf895f2b69525acf9e268b160c2ecfac513dcf902f127b9074434516f740b6bd3206d6ac80c525c61159c1604bcd0ae3d1907a348b4f9ab078218dd836877d1599b59c7319af5b5f0f411c3a5cda25531ea497e687ecf5863483441aa0f37948f52bd0c9d5d57532c6e9a69715ecffea7ab25d920aa8ab91d4ba7a5ece4147a524f229c5623503c2721efe006fdc200b7eba14609e74644fc5c45b0feeb2365845ebefa25bfdd3396ea73f37d55eb8e9706eee706779f5ef2013ca28ce03cd7dd698f3de2a6b81cae70030e977762a116d56934653c5735c72ceca071ab4b2f12228f78e109191b22a86341d0aded34cf87711de789289fed1044f5d818ab0eb074c47b5b2fab146fb8da753bdee4ece1bdb32efdcc672b809b3a6bd20f4249dcf1caf6f4baa6f638284541560d882ef12c71321a33ac8f6a192c79d92f855c968aff6bef9eef86667468fa0b4581b9df71e7ec3ce0e53a8547d8630ee4fc21eb37d347ec97aba7dacc78354cd25bbbbc13209311e2ac0ea678391d63c61ba7f0a69e237d23f5072f7db2dc7c2aacc0cacff74d9cdd0a2ede2f34b7e3f2e00e63fb585866b0ec938bb8019d282d1ff9a1b5dbd7aa2d4713bf285c54dd5c61e23f9292bb86eb447a527e6580ae90a7c9bea0f431d776710a673a1e125b81d264eac620cfec478e21dc272cbd68c73e3d0d77f1d87edd9e21da373d4a0903a1a433d9f2c588038c6804a117a4bd94da955fa49091cf8ccaa12c0e18b6e471041071841d530080ea1856b98aad0df4a068ec0a19f0485976d2996fa6314a82e783d773978eb40a877d14b771edb94523463894b388e61d9c6f292bcc307f596538191e014c6366a3c0145cbd9b551d4d9b75451f248548b8908a9430b60aa65e95e624149a718357510ad45ca8b630e9a266400f6f0320596958c7589e7d811a0a8647208de22d3dc3c7622d2ddafe4632b464952f5b58a7602c6212f384bb119eabcb994d51c383d671e8b190bfe96ea054ae091f070d5fe3cfaff5a5b3d4c4f0c8e9d9cc687014abeb0f9de72e16ad2dd660e22c7088a2906e23409d09f40709b8820d175360d74e56a7be1a58141510dfc17113baa9b72352476719edff49ef602ebdc9c333a9d70f4b3781e5cd0ed927da709e048743c8c7abe94f75cd589247a6159219c1e0287db8b56d0282e3fa287ab6ef515caa17b6eeac2e57eaf7bb894217a9bc176ea84747e89f518a7ca4defd042cccfb8ab8b6ee8881f06b19a0f2177e5fa36a9e511c6f4ea9deeec0f0fa308c737dcc53509e34364f5a0e5a7fb8cfec9c3a99ac41781c371085ed8da43091486572acdb3da5e043d6fd7b659ccc5568c69a71c2be150a0b7ac11674526cacafc9fe475d8071d02f985e6a528d6cbebff971149af8518938e46bda9fb16acd7db8f8e058b2bc1f848a852ee6c85e68e26dafd20a4716846f80a1983806aaed98744fa256a83809c13828ec835dd3ee52f18c9834c934806b9c76d6fe7f4e65b4bb0e6b407b51775771af1c3347daa06e4e9772b75dd90c27560d5b93b57d08d232d42afcb92e8fe532782ed74bf8fd9d0bcc0f3a4c884b9eea246f482bbef647b7bd12a9ffa7d9db0c62131e82b40d0a50851e4132ccaca51c66142abab37ffe3547ff1403bfe199c3501798530822f21577b4d322c0d94043164e06b31be5e8f0cfe4ddd98c9af82964cbe152a579768cab524a9b472cdd932688ecea4a9576bf6b28700e80f522f4637af848f40e81759b547979e6624180031681a0b7d099123883fdb93fa20e220d6efd481524e1079ed31bdf9b03b04b17d4cae007d1d155f2c8564e94c046f8c0489e11ce6625496864d33b675c2ef60a0cf5ad9fca86153dc8b7e6937b3ba2554d21c579f65c659811d4e530c71cf614754f1f6f34098ffc12774a11a673c0794c18aa9d59685d37cee734812245ee88531bc33b113ae6c4972468873e623c3c6969a042e40993bcd6fa1011f597c0f7229d1fc3bed0e7d498603a9ff678c8b1f1360db2f68e1a582082f7468e4846f20a1cd5ec99786c456087d6db18d1693cbbba3dafa0a3fd141251fdd4c0147dde5a809ba9c00ad7e9d52ea25e168296e74b3bc97bf6e1fb972694f88b17933ba4da4575f446536b2ec5bb0b5d41f92840432170d1149311c4d6cca3a4709888b2f59cb3826bdb2b7e49f6dfa1091ea616ceaaf25b099f6a02ba7ed2f26d748affa5efce6061ce19567056d5b30f0f0ebc1968fc6c07b782513dadc59e4f2d09dfd2194cedd42cbe862dbddb755bf0088c952a486fa8321599114bb4349f765a9d12d613d9d6376a01136fcd00a4f666b84b8ddfd8a56bcd8b852c14cf835605d9ac3e94f95473449d88be8adecee3a39320a5150d560f7f79f57ae1df056a0d24591c7e65af363361717c1df9e4f96f6a2e647b1ed36d7e0fc3008da725a5ceaf2133961b31780bb61dea81677cd4d4a98909774b322b005b7d69cddf863f9e26fb43678e2b68148cf4bf259e88a9bc3c096bdf59e54453dce7f40c523b14fdd2c2555f12ccdd12eb4fc4a1636cc9af03a4f4fc209820661e97243e354e84d5d28c33cb4244111758343dcbc3d96018f355f58b3412e9916e2e6c80b69f7a39c4604c607de561de59cf91adfab146fe562b175a170640f03ecdf30c8fd392b98e00036e064104b3efd94e1e377c72e4489055f581b6cca40bd1f6309da95f236583e18a01e9fdeb881dc855027e6efe61cca9ef100b6e1431ac0f4eb552a4946816f1cebb07cf9e0bd300a4352356876051bd00364a6ec385d615398b90a6544ab8d5b149cd972de044f4579dae4be0dd5c3d288a119152e6f01be28ba932ee3304d94107907bfde192f65d233f00636b59385b785eaa531f2dd2a02cfebcedc163d8c5457517c924b7163466faff59dc910b6b628ac00646bc0a4e6d2a77a0ae4cfa687a63f4475b802442f02dad4c55f5b300cda4a07b61019f13fb60a72d255f7ab24923115bd8885bb860bf9331b0b5b26e902d2fa58e1d24701c35d45f6c1c387dbe9a500c0703e5efda1b0ee5bd50b68e3b8002fe755bfdd4a262612328c6adaff9b6c92a44c524ab96531062006a105329e1e66dc4869bd69e7b6bbb5d6e65cbf76cc096cba6a8372fc720298ac93e39713b2c0904495a5ab301f80ba02d50023715468e226891434a1400518c711b19d771390965ffb7939f250040570bee89dc6c525c11521439bf3f3078c404c0884a84a92250837c4cab31c8dd77df800938f2a38545aa8daa2a3819429122451024b952338214a42a0a3c4c98a15430ce132a78e879d1f6bed6d69f93ac66379b2b4bb8fc0c9f3621a77bf374d98295cbc1c01c2c3900fa0508122d25071210437128aa410021f3eae7038d2054a109d24e8cb0a5364d8189155a49f7a808e00c17292850a0a4590f850994c65b450e1e1d48409643852bb76b361d202d30a566068a7274e881872c4d38f32261859f3a4a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a9a969ca952a54a65cb5f9b1a6e98bb79e6005ea5ab9c1ad384932569864af87949ddddd72ab23613e908832e6881b0e52ba48afb9527870234416094dc20069a151a8720549ed5e7088f6dfd2f275cc87ca6c35eccad774d7eaa11d3f1d153c688e6cf95c2e57bf78acbbb7a66e6c7268a28a9922609a48a7c2992843385145c5ca6ac89b96bd48b8acb5d65a6badb5b6db5a6b6d775b6badb5b6bbadb57dd5ddddddd6da2b21eeeebe84bda113725fd65a6badb5d65adbddf6afb5b6bbadb5d65adbdd56886d97f7c13aef87981ab84283171e940809c2494877aed7bcf2dcdd6d7b5d571cdc005912c50b41ccf4092ed79114623e54e691225a0dc553d1b4b5eeeef6aaddddd7b8bb7b09da00298108225496c0baf2eef6f0e6edb6d67610b9bbbbdb5adb3d2df9f51a155cecd678ad351f84b191058909440431c289153a8805dc3ce90145143fcc406910145902c495d0d5de7a746e3f27adefdb09ddad5d6bad5fdba7eb96a77e35ea4ea96ef03643bd4db1f41be2dedab5d61ad7dcdb15ecdb95e668bcf7deee6ed76c7bebe1da004767aa56b97632b7373ad76b57af57db76ca19aff783290589920228dcb80024053f7c600ded726d5bebc50988a5272b3af86813a8dcae6d36defdf99436addaffc1bce9dbefdab6edbeb26ded29705cf646285afb033996f2dc7bedbd57767d9a9f0c1b629845ee2d47de5b87cc2be65a7b6fadb532c97232430d50a250907499f2dd4295c2b60d3ef8fc211a991b9a7c73f8b5980a4964c7304258a0a81c8f03cefc0001969123584a926a9730425da6ec77d1d23350274a9c6882690728584a74097d9fc8c10b10355faa80e08424db40b29daa92ed92aede28ab406123bd5332c03085021a01214c34c4c9d20585139a043639d54e4571efbdd7f60fd1ac90f0455bbbbbbbdbdaae915e1dd2d028b5eb5d2b87dbdd7bb9d80f767590b5e3f5226bfd60d5b6952fb2526badb5b6bbadb5d6daeeb6d65a6bbbdb56db61649d5d6badddddddb5d67adb0a0fb26fbd56c6c85a6badd74a19aa27b3052b7b8e64acdc608111308ebbd77256287841014b9919e694e2377c3b74163259acea90dae55aae2ec9101d18aedb5551d175921f9d05d67ba2f5e28989eba24bb86ddb3eade96e00be364a68093c771e6072886abdf6694b478bb75bd74e795790e4c9f5ecb5f7260941bd4f3178ddd6dad6a109152024710342cb09aa941992f4c30626d96d80e36dfb094aa7c5c2f240c3d49404d3102c74f161439adb4f26647f3ae486a713fad8291a89112e6b77d09945cc2b9de552c576b79d1d44875370b9622f921d785aeff7babb6be9dcddbde5eeee8ea40697bbbbb79a5448754034764858709953c7c3ce8f93962fc6a32d5d41bf389d6c68350c34e2dec530d4ddd15ea7a8aed5433bba130a3a2a92bc71a71f1e8fb5d6dadb7ae3ea178f7577efaebdd65ab044cd0c6590608284373dded029195af62229d2eef17e497cc89ee29ef95234179fcf7e46a63c9d243958da2914b9a1cb423f232fbc723e23495c9ed1136ad4dc9065881858681e6d8584ef5a23423a17758f3d01450990156ef8c1a597744893c2ca080fcfdddd5bf72a4565f550829a263ffca025f670648c5feb44839e07b6d4ecf8b796bc7b1e999267db31af7b3fbf6e7b6a85a5ad1baf6b7677b7bdf6f68c72bd79fa83c51fae8a707ac2298d550f495de3e44ee1c8abdbca894dee9edccd440487a719be643901c72a8512b258795b7b9ba072777777dfeee7696bfb6f77bbbb7bd7b66988d7d473bfd7aaa987e7d35a2551e17dad6db736df4ff1c5a1833b6ab90518254de8edd077cf028734e3971e8ed6f773de8d21904a9ad0fd9e6f3004c12869f8a9a4611001ffb0ee71e7df5d1c61df712eebe108edfb53983f188a705d30d86d0a863d0fc2cc30490b0283bee7a57743e6a087e12030a4b0fe15b08f5fcf37ec7b60b047929d4f2b47be6f5fb7cfa777a33f7c7d63c7d9bff55276d315d6b27d7a5de4fb2e68b4a1a1cff773cb72cbf29dcd6a0543184fee9f7bbf7b86a3a4c9c08a8b5e260343faddd72fc251125530b4dfe5c816efa871e086cfb76ef8bc74f960ee63b3a1998cf36cf8ffbcf46eb8ec65f8c3f78a6933ece207f40f6931e75c3e5887bf7cf93e36c21cb93f4ec600375d9c97801f1b32b0487a3566de063fdcc77e7a37b88fc9be5693e1231a3190fbf0a8dfc62a9981be71b8a3d64d978fdc808ba38152aeb1b7514103bc52e6bc1ab3b621fbfad2bb21fbfa9c37fbe8fdcc3012100e3fb7ecc3787b6a65f877d4b2fcee7f700c7370e5a3a0dfbc0343a52c9fcb3e3866897d62f6c1adefc12a30f7eda8650ee07084acdcfd0b873972f79c7743456e7d4b495bbce559f4f37b6a1ac5f8f97d9b46b69fdf55d3c8e8e7b7559bc9f3633e559f5cca311be1794612cdb7e1792589e6c7c0138c249a5f842795249aef61f926559ef2cd753a3589e6cf9f533f71f82e952f9c51794291b449a5a0a48d52a9fc93237f0ea9149dba32ca1121723b185ecfe7cbf77ea352b12fe8545e2563cc27f3f9cdab3af9661a4959b292e7d32d79fe9b69149396f29c4c6ffc66d5fef5fbad7f767f487924ad4bd40d53e6f41b5595b48513cbada46dbe7c72aa8945256ddf83f12b04cccb1444daeefb0d2b8754ea96fda9d4349a4770444ce4f9d5c813ae509236ffc355075726554ad2aa0bd728754a9d92b4f9f38838e3fefcc9261a1509911d0ca994224c61884452f14548a5e8d4348a5cac9696967824cda752d216a3485b1463252bcfa753a48dc352359f5e495bccf3291a698b2a2485144c9e358a9818d4e4909ac9b36f39f480430ea99a3cdf6f73136b1ad5aaa410840a08bce0909504763e7ca18dcaf3432a95e7dba81942a63f25b62f9fe338777f1b31fb2be58bc39bef370e3b80ef4731566ef5a337b17c8b9572631066ae20978683219f62a419bd1af25d17c80d604d262986061f93c90718ce4412c020250054be147c656020823d28c63031732276301383c2bde8a0654513b7eaa372926fdc2255e4134113415f0810ad58e54b6950712205831a9c40a9a8471f0d4e48f0f162c4f964889e174d9a60305bc4c9644c9320f9d2a1af8525f2f568712a79010c0ba14f05193e3ebd2024e89b4e4cea2c162923a3c181be3984490db218848993939fcf042762710271c1cc8a6ffa70c10a2cce251798f4eb8bc2052177e7092582c290f04a71822551dc7c5f9b25251011b1a3f3559dc9894bb4604201cab8f72561c4edd84479f91b5a1fd6147ba30958504193444499d0b3836b1a210070bf8ae696ef9440b0b064267b6001884cc9130db8f24504416476a852c5890f4b50d031d49a94bd020c224c1715b0e2b060e4c9971d2078e2171e4faa0c39a10423f092641b866cad1617134ef24e8e639870fa3cde96b2d65ebfb4e658d546051ce809b8541f525a9b33edbd368dd75a7fb05e8e3a342dd14eb070dc7f3264b8dc3c998047561622535a2a1493a649aa06a813dab4139ae39826d2d4da3a71adb7b737c9eaeefa6dbdf534eeb6eb1fa27d07e37e88f6b54bc25baefd5ed8f7b1d0691c76a99250e15e9e8f07e6395225512487df5735b5da4da4a1311ec0872828f438c2829408ba490c63a878be1b4144a9e0468816bcc47941cb8eed4f00d1ca1521719228c11a11846112439315668830bde1c2850a4ad393226e3941b4b172c41236b82963e542937c6f4f7cb44f132e3fd04005cd0f2592ee92314f4c001aa2c17002af8637b5b650c5d43e3cb73647090b4aadb576a7bdddde1cbeb868b700c7c7998815b3da441127d7e781d587c09b289488a2883be60b038e18a99db7fc5620544778b80e132408636d678652a7b532d9952395930e57750c8f5b97af1cc19c408a128efb2f852b48965000450f6ce0a0896a16385c8412584dac902c612d5122091f7898a9420246898f5b8aa06b00362b4c497531228725bd828f1472bef89082b5b7db7bef971e700232627c7881ed4322a30ff1d1872b647c9862c6878ec1875cbef62551ff0cdc2f03f71fadc8fd4638f7db625cd0b3cbddd041a3a507f7fead1d714b9e7dcbc3a183460b8f3cfbe8d5988151f9c32e4973b7512fec13e6ab7fbfbf7ecbe340291735976bb1ef07bfb3b1ef62600c74505a4a2918da977dc5f46bbfcbe340297783f76a607ff64853e21f2ac3dc370341fe7cf466de0631cf5a1e8e02c4891327ff7cf47e40cfe1a3f90339900339907f055e817f94512a78bf4da3a3ac231e34b41d2b7f8739ec4df68799c9fe2dd0b4c06a91d5e27ddc7bbcc77b7afcfdfdfd9f088ce9e396307e07ef07e11efa8bbbef5a0efd8626cf1f000e2d919062c9f30580c3a38c71181f87b107875c0b580540ce7d9d62e8a3d7d7c321d14021210fa5a0f985c327f4449c57238789a4cdd931e9a22ec077a986ef0f18f80691b4f916e00ad4f20b50078b77f1b1d9b9c0f4bbeeca63ae402d8739588439b27d2419d6324863e1028716dc51cb3fcfc20566f1deee370281460c16a929894556f96daf01323e7a1f1c3d929440426fbfb39ce7b403a1b7a02b7eb117c23a662ff4dd4c8883ca21d1ef88564242b2d7317b7f22d977b2658f245bc6f9133dd29c09fdec46301ac42a22a11917e368063eb0fdd12b25214d7a8463d2c521e55c324cb37c9a2e44a7d78150074242dff4419059e839aed512a25906f58343e8fb853ee64ec8aff775a147921ca699521af391d0108ed9d6187a24f9b5becf24548c211dfa1b2ae56be502914cdfbf8b0ef8a2982729c8437f8bb02d4a3e55a3186fb3bded7ed7b7e5eabc1ab31fc23a643ff447475ff44a499d0cebb03ff4b24def08452052d5c836e1d06b40295b07633e613ed92673af43f6feddb74cc675d6dfbe0d7f6b5f22c9da2ec3dcd0cb3097fd8ca481f63b0bca70cc38baa617d377f0e7867d7f1bf61d0c5bd6479af209874fc704ea7f8e968b39f71ca594d600b2217bf9453826551cb30c8c035bf78ba5d7417dffe97550df82a192b7e5bb5fbf6bed9fcd66b57a38b8a1a7b9717fc770cc94e618e6b084e26e0c3d47a9a51ffb2e46e593ffc5210d2177cf9ec31c97671804d9c1d0738f2463b19806feb45f5a0ee4b8d0c6c0221cbd0de8657870f4b68fb936a62fa34090b93e109650f539cf467df9142a35a6fdfd5cce51b273dc60287148f3c5a10841f27da4d93de55c47b8e8a3e7818c37fae8795004fe7870f4455f048650f447e008f7eacb0b519264107aa524db1be19ffb461f93ba0e0c2b16f8e34117f97732704cea22fce34f3b70594ae250e8b185cc9ba4ee6b608073301421880c1c938a861e4936b843b6b1e19f0f8a3ec6c7004588f145e08c3289e6c7a48b3fb0bd112842d1dbc0393589e6779c962f7a38383839e7eb3897f745af468e893589e6cc6a93e70f01806829cf17fa91e7d398f27c1641f2fc1f22797e8c3889421a95e7bfb67cf2498d94b485542acafc7042595d495b68a3a0a4cdf51d9329d2a6f33972beac92605c9fbf949251a6d10e9118f58389b47150a8a495b4c5504e495ba46213e485a45062f1a8d848c9a1bccaf3addff8c9709b8225cb2735d2d62d5d18be16f6efb822be28e6ca994cafa2a7817feb3b97c778db1bfdd13dc246d88663e022dc3454cab40b72d9d672f7b17bddbe0b86ddefa8e556eb77a2dcbe21a478c73ba255febe1c9deedbb76f77778ef739dd23c9eeeeee5a2d26499bf787fbbdd6dadbf832f1e40ea2c395a7db08e0b28c9fcfcbef0e7ad83f4ca8c5838f59e8a0ef4fb1ec1d739d745d6c632f1bd3efa8eb624bc3dabddf0783fd87b46cedd3fb1487b5dc3f6f83823c3f9c67433ee53e7a33f9e127ab3fc330194cc6ddfe180e29072d5e7e0cfd1bf409a3a235e437b7f2aa8843f6fed465b469d3a6ddf21d779c770025a941a5df4917c51e29f873837e056f8382b482e9a23580a2941ffbf833fb2a41207c256d7e05d815ded8cf0ca40e86393217d27f758b97813b6a2a7e7a1db4f80675b47809ea180a79e78376c0b692b40e021bcceb3930f3ebf5e2e20b19f41d27bd0d5e60065efd5c84d14f4390de8d9983be93ae17e680ccafefa8ab861ea0de0d9a839e7a38667e7dc7c9c9cd9c9dbc036260e61718e38b0e0265834e66bcfc8692b60bd63692267f06d89c6b054ef14118e86758f62f1cfb1ddcfdc4f6613d85c3f25d29ff2bd578f9c2b92497c0f066cfeb014358f6e692832f695e58cb1ed87aa4b9e28170d0cbf0ec63f8f51dde798be7234d152d15366a7903c981b4f1bcfc1cd2c65d9ee7a99a44f279c0eb421ac524f9d3f3aabe8e31c6fa14c3c20bd6f96332499a97e7527c21bf8b31857fd8dd66a42dac59ee62ace477555b5d5d9d91364e7eb7b14bfd264bf9ed354bdae4d736722ecd8e73c9bf385320bef0ba7c395f3f8c58d8eb2702e098e4b4acf317efa8d97e3a03cbf8b692afef3cdc56503e0f031a2f23c52b2551f05e89a59a2fc5bbf0062a3e87b4b582be9fe642da5e5fb338f8e99ff14a2faa8f3ee7d9a060109e4c3cc8e0054e289226e7520b0c7fc67760087b0f0c3f0b66c90067803049c32dc3de6df43808346bcdbea56234aff8771c46acaa9d1a8d0f699f6f013efcf2cd7fe967cc2212f923bdc8fe058891fd099041f6c7804bf6a721030381bbe845cf03c3fea00f6159039a3b90c617617f2bdbd72c088735fbcf576bf6b40d627e813b22569e7de7e170249c48c9b31908845f4acac0f0fa7c4cfe0accf33b383cca1794586a244d7e0f0e793cef795e05f6bce7011b8ca4751ef30c1c932c0e419034f0cf073444c8e0697c4ceaa48b003826755dac7dfe1d75b9f0069226ab6b07d3aeb2fd5dcbe53dc59e05bbe9e1b86f5f7a38ee7b20f6b67cf45bfddebdffeb85b98fbea8bb833f38fafd3d5b751d6e30b7cfbf4ad2e4945d256d34cb6f30d2d6491b9765ec1004894317d93ec517874a235065ff8efacd91fd46e53b4256f6bf29e8c592ad578b17745062499a946a32c0333e47777737187adfe5782e13be9c9c479258d266a59497029348cbe7d1f340061aaff314878d44965fcc1fd851922675704389e0bb1e8eabe3823ffef743ce410db8fc92269f7ebf77e5fbf0638ccf012ed3afd4fb8b63f630f7b9e7d56b0619fc8c9f9141f56e1000c7a40c1adc51cb3919d8a839f52fa55d58bbf7fb60b05f9a44f2af9725ecaaae7af98d4467f5bddf1776559575e17eda51fb00031a3fe39124062dcc230363f01d3803833f1ecc08c1b738011125298419afa49464bf7ef46ed468e0aed6ef380c704c9a51cb170c7364da504fd3884a22aea33c2a47a1113a2523c98da04b0ef5e8d3efe287f7fbf0b31fd2327d0a8639e28e8e4ed479f939a6d17bae1d295380e1bd20078630f91469eac4f88dc311b8d7cbe9758239a0e70243987760f8136c81212dbf709444f13bce4b40b46f63823caf94a52bdaf09fcf7937fce74bafd6f8b1ebc749dff1c3bc2b5ff859d622d18c5f3fcbf859f7a98b43a18b022c9ef36ad09ec5dfe8fd2049f78f88480132a9e821206d177cbf04a4adf6fd14d8216d30beff02207440daecf787206df45b7e3ff743dab8efe798643ffb06bf9bd16c69a653d6fe64e570460df7750e4094607d8ac3226d5c54ee175c8dcd5a2ef71600e716b3dfeefd3e18ec6935976b862d781966f115d39ec3432f03f0160bbd63a2bf18000b904945a08d9a442d7c5c0ea9547d9a46f269126159f0f32b13691bfaf93588b4c1b859f44d0643ee69c9820feb549d926758a1e4f96195caf3c36a2413994651562669bbe0670326d14413d6e21b9ad2bdf97e9ffd17d517f6e73c85f1ed760049c0acc93078328cbf1e8e012401534486616158b0b1d70f3fa47d1c95f277795a5ce4fed973607825187e140c61f965167c6316ef38e61996e11db56c01c87d2ffe0e915f7cf47e400d58bc8b4792419fe2ed92b4f9fcb04cd2267fbe0d226db39f02785a0546da6456d2f6736546da5e67a4ad4acda751e8143ac5b5de43c2df7f007f3d288c5bc2b825dba20f0394c3a8148c9a2972d42963330000000000a3170020180c060644b2288b6214c852ee0714800953da94a8a84c1a898523711446511885301c053110003008600052ce38049d34010057347ba815023f10ae6e8b87a07f4a9868966e5a70903c493e80d7c7d59db728457a9a3be9335a4e49152614f64c03bb874dd022d470e98683a6e0ab54f78cfc7df654b74e243769ac2bf0849582ca47c352b3e4e8d3576f0531b7b62d2eaf3a8936c38da08c796cb3fe947c60276891b1c45f88129bc71bf170a0fd8f4bf6fe7928adc34f64549905d18d463bd30b80b2ebfa57c65b8a1653ee99cc55951e77ee41956875554b975e3ef49ee6ac071c82698386df0ce2005827417e20a27b8c9bc5bc23048a5b757aa2489874129c03d625748c4be36eff9b9980cd6dce8183e6b79ef4da8a95d7867ae6dd5e804a024d06dce647002041a6ebf14ef63d26e19c43d56de0ce1515dcdfa5b5b02445049ebda045baa3199d5847dc69aa55417cc700e3a7e504911a4e996ea7daba07f1189cc2596f89efa88858073aef801bed376dc79ef4189a9808e0bf5c3ad72cc20f8fec15f6d26a795ed8223629feccd7f324fe46452d8bf1cd00a969891131a0b7555db20c6e3fa8b984384d4e5fd3a8f4ab4cfe2a8678f6658ebb553977b422ac50005ce2bc9a4bdcb07207ef55a65b5ae62ed2c33b2a72b9752835f5192f36d1753257d9c20e3608dc860a21846aa3b78c0d930e7a7e6e964c94afe3bafe38b511e8cc36ad77821245f4ffaaca68547d703c8d78fc43489d290ff58a8db6f7548ff1331dec24e8adceaf0690c8c9fa88cfdfe71e3daaaa4e1914d3a59f23cb8a7fa4afd423a82db6240d7ec93edfd946d7a2e4ec3bb6e22f6bd452d12558962bf37c7b96e3ef865c3bfd368dceda75bdd6e48e688abc5d445d4a99d8587d9205cfac631ec72580d4f476e54e8e791908754a36bab29464067b980a23cb40e3293ca9cb4a850b34af970224fece4301a790e771b15c20c66dfcef6795ee97b86ed51a34c5d35a62e5a1ae3c8a6f146a34c0168ba79ec1f1713b009e71fabb8e1ac7d3f647a6cf26de5f5e9d5b9888ebaf6369bf67b817bc255d82263fd16b9f0cbdfe4c3aa01956607c5dae3cd34d95b21f6e4a1617146ebb87909084bdd002d54e935d6a18b882eff71c349afc89bbd8c22bb60c3f03023b30c66acdac1dc0269fc44c9a20f0ccec54e8aa813ee93eca33478190fc614d0d3217952dbc4d54f1ae5c6ed424f811ed249eac452137d8d503e1aaa49d566f5ef15bc95d14540f992868e55eae06ba241eff62eeb5b0e680baaf085c7c4458060e9e494912952f0c9c14fdedc503433190464688f0e8c2a97de7de781fbd864b9d953a2d76a486ab1ebf740abf8e2b85edc711ddd4af52be3a039817140674e708586cfccadb4a9e2594b36f90ad8c441ae461e4268202fa6f174d9582649f7bbb094244e8d1e2c5ccb490e8ec30c79992a4db96fe765a45f530885d916bd10ec0e23710f6caed69d782f3424d56f5d9235695a587940f5d0cb4e13e13462addd6e32f2089c4f187320e16c0c629643256cb07e36be40e0f727ca708eb017558a56bb9c9bd4ec769ca21a5bd0f06012c0977d6967ca89bbb95ed07fb9a024bc2ea6fbfbd15f81b3b707b2643a1e69b0b696667441c753e1713fd313451d787c572457291a22058b93145351f7d0562ee03669a6fc6ac1930033de1f98eb1834727ee2d4ef7649379f7f03167261daf3ca6c112adf38a58a9b277a9eb07e40c456b9fc1d95e955ce37035d69040095c3366a8033bfa54dc270bb781b20e9960f0fe173e3f7ccd3a871384938991e66eec1a168576a4b50fb7f6d6169f66cf5469b223a03eda9e4ab90bad04f6c7167f302d63c9068f52f75e59ea1939fcdc88b83f397198c18c25e415899fa9f1ef4bbb7abf675b4d14c28982d89eee3401cf95cbe13f545e71c328070492019e4c752f3d1765f5c52f88cd784dd7d3f4e17bedf8889296db3ffd4abdd1eb215cdfe355422aac404efe8ca81f81b0b032e1c8e603f811553b35893f8775368e74ae08d6c02486fd3ccbeac94088cf3c3826701da01b62a31276bdbc8a25164a16177225891d320e3d5ee3f21ac6024013534e384f8e51e582c01fa2637513ca922aaf81d862dc19c710c070faa63b355f84d43699fbc4cb6aca9c6534ca3fc611fbbee4dcf430ea8c9b21fcb6c8d370dfcf87c8bc88b0c12f4d51bf7f577004a8315ab5ce227e456fe208e48802d49abdf1465472ea407824c33a8f7c6f3ee8e596254885372fc787fd5a2f896fe32cd66f3d561812bfd8c60bf4d73f66839da5d57b4e0ad2c7c1448d1396a2c3f4b4e6bb46d4445b89d60fd26f0a5a5313bdadd0fe0ead3aa9f06b666adf79166fa1cfe2ea17afb8f5572d80865a0bb70d46de6aa7dffe04efce3ca098adaf7e0f23b23bdf56b96c68857e6b0aa715f7f5929a7c8832d09dbfeef30a86fee21bd1a20d50ee34679ffff2ed4f0d465c68d02f224a56f5ce7fc12cb4fefa90ee85b02d21d055103eba581421217a86a0306f3d2c8ec8025b800556e34d16ce13fce85f63917e5fbbabd1b93807e48ecb5d85eb757786017081fa0a5f6a6afbaf263fd0a6160fabb8ea0df5493945e71620719dfaa412e07c83acb0b6c3e2645430d62dcf9ad25d6c456575d0ff1b853eb5a3d0dd1a736319a9ab2f6a5b884c6bc39e8f9580d12574b717ba1f3b582ceec433e284494ffa99b7856d7c2d74b4afd84053c5aa6b19d5c6df09c984927739aa1f463bc6bb02579ead2df57c6b923fdd15b968ee35cfdbdea1e3d569be3e1d6d35c363610cdb75c7a0ec102c1c968ff57ceec3f3e5e33065d0279bf8af10f710e0bb3565893b4d328022cc919fe9c4df34e07165330d7cd5b669a306f1b4242079ff144dd03eb0a06a24467df04f41ddf2c3e4315e447e1cb972118eb48a68252001b85ec9cb97458ab53acabbc9354b2c483a79a4ae875611c42b25811d75084d1cceda18b7c198c1a1fbcf8a7e42b9557b9d5c3fb77a145b4fa864f7a7e2536a376a19b75bd6bf9ddb6b435e37615f8167c5fb4c0f7b20693f0f791c6398f57229edcf8dd23176e1c22d80824b4d154faf94d7ab7102fc848995e61441df825ddf8ae3b400abf82b439138f8d0e3f6a481ba0d0feba4a943eaf6ef82b78397e8ed5dba8300096abe62e1e6dfcd050f8a69851775fe54635caf6992c9a408bcc34dab705b16d6494d59723883de063a1bae5af1d91dbc70d7bc1617914108fdd34dc15f8dd7e166a239e077be066cb1c45db1e2b34c87fed6821cac16636d1fa4d6541675d9a430c8130cfbe7de443c92fb6b63b65066f2c64a37398fab0ed2fd6716e37f48845e2157ef90f12ce81f27399a8bf7d88181ca8b9085f35e7044a5fe749f15d850ed659cd1a8413a62dd44beeb01c67f3bae4f824103905b9082ca2895f77f539f5ee6d9e69a92a615f2e62c81feb213ea83be99551c2c13e56cebe53722f7689c2572473abd7f54a563dc06ab3dd52f6b20958c376e9b61ec8883971f717e2ec29fdbb4b8a69bdd7cb07d6646d0f6e1e3216ff09a28b11a8dc957b76b24e4bb6cfef239d25f9f3ada575c6b2ce3bfe0624c231c131d14e09a8a522514da31baa27a08d7f2380a33f56784b667e74cd4ba9353bbc76514780e946645dbb712004806192f197158ed75e06c4a2746252f511a58acc39186a30a8c601bc3bae14540859b9eccfd4b74ac528dd1ba97ea167e240401cecfaa008da6aa2855c6126dec0c62223d4edd03e43dac7eb8b8af3949933762da998f9008558631515a2ff15507e8f2d1d4eabb0ed4aca0131177c88062d6d7e61e1ac6e4c1a88ddc0363631581eb1ac4b3cd08a5e2d0d2d511bc4db47174ad3160eccb0c175a2770175d2e74732ed78abe9cb32e1f5984052d5f43a1450a414aaa08e887176087ab5e908e2e9bd90e638e10e22199dd3f3edcf8642bc515ba74a7e7b1500cf1c45311e4fbf8fdf10045cb009b71fe4646242fa1afc4deff24a2c079a257ae1356982ea66e3a4f3576d892e8dcd54d0404e75586f6e59c4d707a5125ecb789200b70c6a7063fdbaeaeb75bc977070b2be2070fac378a6ab93b80fe7702aad24ee88af065dfab112cfbd97e5fc3f13622023d0f63c0f2383cd971f4b6d5cbb829bb278b11eb14dcb2445fdd26abfb51fc9c2e533171aa3277accc6e21e9e6c03cb3eee5cfc756b0e508b9e41331f6c5a1f450a62bb737fd397e556f515af3c10fd8a1405b6c0c00a867cfd78438dd42c3d7823f2f3cb54835f4152dc9a30d2a9464d2645aab85b76ef9271d9efee234a1fb3a2569b26472139f4181fd3034fd9c24cff7c356b31c97ac40938592b535f45522b653b6b38be25323a387d552d4e754a828e3c46a90e67b6a03018afe987f0cf5d1eb03902d955c0ff82f5d2cb2975db153d76288bad080b666d2b48b42d37048452fecf534c6fd377d8c1591c9007dfca8765de7b0daad8f40c8cd0f77641a9fc9c0cc54087b0e2ecce5f20c112d01940a7df474f003bc630fcf302bd4555041ab748c8a0e9ffb626892af3921328a72450cd2dfcb7d69255d77e37bb0d390309a48c9d942bb1dd6c6c543fcbdcd2dd5fa90648a54f0c60504cbff47a47acf65d180ad3a530d7db50feecc4f015c0b5a04af971bb56e4778e5ff14003fbe7c75accc934e2cd93aac93ae1844b80b708764c17638e8cd2c05e43e843dd34c790bcde5e1afe572c01cf1518b222c0dde4b31ae81068eec2f786d9f7c7b424410174e8cc661489768886c28244bb50411e0f34f8f8e50c19382f3ea36bff9b4b21273007ee51f337f143c5aa715845a98bd0b231107f298fda827f46314c8f58f5a0402069711feb0558c390715d3f99a575c090c26f9d2b88d86e7061a986ae8a847b780703290f18153c4912a68e3333c8b7cb5bd3c753f063ad84d34c0dae6dafa3f6e18cb0b182c295107c3bf745a8e8fe1eb51a6c4625f4376602cb465e753486981cd9f2d6f9b552c1cbc4af619bd61baf1d8a5bb1cf80575ff5b4b0f4d9c7f0c2855bdc2d6aba048467a1117379e2283de0cae78fb7d777ac0a7e2006e840dea5869e670b8f1303ad2350c103a02845209557ab9d005be33b0428667fcec246960215457fbff5c542c55b9b123778fe0a6ea6ba10af34e131a1fba843c70631fae7b62a99db047f8f250cf648725420af9f5b7affb7504ff7bf5c4a7d53891c3bdb70b970470a1227ce08846bae20013984b35d8c51a57c84d920f2f4c1359fa133a755789f10a0c070bb85f11d3f6f7e563f8376f67417df19431f73fa228b3e964ae76d0de0c52c8cb3ea5b7fccc691045e13f6ba5ce820710452f8e05afb859d9f98c2ba4f1ea354b3cbeb9697a28f4881cc116f4048433f29504a2ae8849d1a02984fcbe41462dd70cd71e4b2151e36797a1f7fb4f0a3e0678b483e94fde373fb2120d5fe55b25ba25f8c3dfd09d015950a8e7dd45832b4d6561703dab5152915dfb1f7fb3bb43b56b8f2989d9e0bb1d906fa5b35b50be15d4d92c1cbf40cc97aad55a44cfc24a608e2c3c878def0c9c33a5e1a8e5de49075f182da1dff3ec9ac137e9e00b0561254c58d7bf0db8eb4e6fd0103a465209c897abbbe2390da9e4991d1def4bdc33c2ee7cb5f8896f9576015692d90294028f25de7e8ce2c1f7f87a6f4a3d76a9df5ad8cb9f8cb8b972a4a24bcbcf3ed217cbeedc80e2cb3a3df75699582bf3f5d897b23e978e1855bf8798e7add54227f841bf675433fb4ed691b6adcb3cac4fd49c8da872d9ce1b5f6ef85c898812bba9f1650a22ef17104874fbdad7ec3643e11f6ba8bbf56c3efb0be7dca5f455ccdd8b2471b688ef394c97ac76be7d958bf1b970c800bdb3855fb81ef9a28c6166ffe51ceec01709708b3c92d906e2e3c8b94b82a14e5526ab836216d85129e2e241d9192f62bef2149b7f29f0058c01c734f04e5ec88252aa6e41e1eb7941e15330288c862889531bbb6c0615f489393c6ab7240ab1ce5028e1c0ef1eebf61e03e58e43aae614de3a317d2b05a80d430b8c324f3ad2f472bee61101546a68ed2ed1f1539db7d5f0b1ed74877ad68e8eb7ab3cc7d9d146a9bbeb790de0b5afbf00ba4cfde8e966afdf06a71b7d1024cd523ae69d56ffabc1e4af612e55c0ea139c61578f596788bb3954aeacacc9de69fe0922cb861a01d4794d7ee872ae614098be49202e93600685a8633c09e4a16f95e91cbb53597864feb53f2d05cc0f7dd7ab6c73129a38087d795a2e5e96a9d6862f41cf29b543e5e75cfa95641c9a91a25b622d868973a05a7e8e78470ed0d4df895773214a9c957f06e04515f1805782305ad8576d2c1c368935b4f36c2135770115918a4e17964edcdc3213ea15fa73adf67078ffd95438f917a4128fb901e522fdc3f8faf03e700aff48ed6d165f8549e977f09d10bc3cf1a06f9b15011a68df34aa6e3bf5751219262ddb1a6d90cc54bb1eceb181f24e0a32cf0d19811feb396c75d4952dea8f43fa5adc55dcf2b7f57325437c8b18fa2eebc1c77f4c9ce66b30abd931b86813a9f38b8483048ea8d05d5df1577b18e4edfa62c616e68b171410281d0ece3b11e063fcee2aadfc410b5f3eb541fa7006a7f72b7f61ecc69e7f9bebec316b3177cc0bdfa76caa75a999a113e8dce4c240799edbef7e04faa02be1d78b2d4d134d8bb016dc6153afc1218524324f5bc6f2bbb20b06f2917e36526920d194025b34cdf0476f27a416fa50dfd85bf6aff9c84ff0e5fed72dbf9f6b404268fdd84983c451cd26dc943712e4ab2c71bdfa3578986b43875662dd3778ab933bcc365927e7f52655795aa8df4ec303bae772210e953cb29ac6f07c97a80ee36b575f4e63304fb869fd7c68dabc8e176bf1731b620906a7d063f002487d6a4c82db2a946f5396da4d596705d863b5e1cff86e0c40fbe0546db54f954b335cd1c9599634c8fa795584a33615655ef7a2a61f36fc7ab2d4a688123273fdbec8910740adcc8a58dda464ce71d6df3fc2f261adb1004a1773852245b148d28d079d21f51f6e3524a0334cd1283abf43fdd3269d99a8df32ee472dbe18f7f05b4a9822d164045de6217b04579fdf769e1853fdfc7686d80968b32d2f2a45daec91eb67c15fd750f25f2ae8170a6824a8da0f25c8913b2dd052a892dbebb505fd0014cdea60b579bc0472802b50c40cdf04f6dc85ced10307d40cfd751a23f81889a2666ac8d4526148f688261207c0322daca9adda49b7b781ce350cac2fd93a784e4d7b7667a7b9f5161dae8a02e2763a7c560fcf33039f5e4e8fb44401e1975f5f9e5a53b7a891fa1c99f063c549e82e3b52166945e432f033e02e676c3adb5fcf57e7004d8402fda49cf5eb52c72324eeca93d9d0b8af49c85396e74e684de8fae03d9a06a13da888cee8dd31ea4d52bbf6692eb07b166ce5f3f9fddb3b90f71d467e5d36eaee9ad8ae375b9cbd6373b616f90fa7c8f9e78cafc530ea55c9106e60660feda5580a8b72fe21c2a52aa5357e082838fca1ee701afbca52abcff6e3d8f51f267dcdf3ee2ba895b864a5340190e588c7b5959f08bb8e23b08423438ba508e75a803a1c7108a69393f9de6280b482582616efb904ac873db35ceae5d2d897e50bc7bd373f5fbba28f88a41d752fb5d251f0681fb5c64bc7a8e4094ceb2c4420f8cbee887522a7376dd09d8cdf2c7c157ba31ac64b0409a961753dc10050e5caa445ca9da633de10af422d518db1cefca967998fcb9db77857ed09576c31a6ea9805d8c62df91011210d9d71693e9fd692ff851d661e7f7e568d9a280adc961e3593cd91a0280a28e3f661b5bb421eb3ce158ca323c2c9983a1e02255775178f987644b30e32189874fc910b2ef7aa5a7ba38516861cb7af35037f48df95efe7d443517f8ebc94c49b106d24b19667778088e3b216614431bbd02c5ed33c736ec2d2daa0a34090d7a0120c3a4d925e68e83e3b4e4ed9bdd17f872f562d3891044fc9ce0d7f3d5dd346f72b7db99a4733e9a958b582f3e784911fd53465c0535fe957feca19c561a16572593940ed96a8dd7e0f01b4c8e70627a29e2fd2aacd815c8129101132fba8eb30f458e62a14f8228d78c70fdded49720e85375c9f348251416992cdcc55eb9b3dc2a98da4aac084984ed5e1317d42bc59c418f9d2d0f10fab6ded3bd0b4ddfd1c9457feb380f20ab1351db59466bd7103699de9eeff85b55cbdcc20140269a7b34ac50d1403eb614aed83dcd896cb17b968d2b441d1802069b4c06c5604d175cbe54c5f3669692937d076581c033fd2d55fcb550658574969c42348baaad7cb43a10ba6b147642a49abacb3d0c584db5e89f70be8323092e541a8317461f6dd081e59a8987145880c3da5f408ca7e1958022bc2e83574bda403611141f74a8fa00e2804196b1fec660e5d55896621b9c18d0f0080ac6396aed159d3e0856167274b7e8280ca2ffd9b465d9cac01f440538b7e825ab551c8e3a80ba61d7d24a611b020cd2d5c852004ed06bba9afeb131168456d2c060c4ae1674d0555641b9cbeda2ea45477b009342ae50b84833abf0fcdcb075e0c5fba65274663aebdc61bbc7215a0d46a90fb11bc2cb676bf045379483055241c84860d2b1754594241c1ebb1293a08fecc717e45c241640097a900b4d683dfb4e04547eb0a94b151261c845bbb554148c00d4a37062f81c57cb942e1208f1588bb0000b6d60c5eea378073b0ac42e1a095087c718122f0ad1bbcb8342047229b42e120b93c51aa6032c283dddcc1ab28956c24859515131021db60744078056a06b30bcb2f160e2ad66133c1084283df26c2cb17f1a1d5cad95641d4c006d2938497c82aa9bc6038c8c7b6e10220003b98be09af1957c19881f34a86838a0ecf5a05a52c53a5f0b28ced7887f8291a0e5a5a6e8b61d44006d73d859768af159344dac2e1a0e3b7be944024a103df2ee1b52afba889e253381ce4ea16d74ba1f0ba75adeb8cc9614dbb278597c8f1f98a54f8aa5e5be115527637481a06562a207496c1695b78e15a1e41967e1b258802b08369bff05abd6e5148652c28552002c1c1ee92e1559582cce0f232e220e7f757f3328c5757a6b8a59a3e4ad52f21d892f020f78ef1224a513228b952e220e77fdfdd0f82d03792f1f24cd4a005c84e26a4ab2e20795a2ffcb22b98775ed5f6ca09bd95de817961ea3631faf38c5edfe0945fffd51265421e94739d57a1fe58c0564b0883e4648d73fadbde0446ed7b87da51fc4f043aafcf06d76f5a412ebf84306869b911383ff9d679c56c5ce7be44a3150711139ff9ea351b529584b68ff39f749e849609ff3da7c4bbef7c57ca1e7aa3722f90fa8ba3eb5e7dca9105a64ffbf0795c189a9cbed0ae1107d87236b982d347db95513ab0dc31dfd55ab4063abd46e4109c56be92fb2c4ee6553ad8a1db04752c08687c53e9371563f4f5d104ed6208db9f9f53993e40a313c3dcc12a66330cfeb357483927b6d8338bce9c8669493a26d5b77101eab50d8bce5eaa46430719c60cc0ec346973459637b64d9c351b38dc50db730e9564bd78483ff4d248253b4fbedb8d37bcf8b66c39d7ce63edda161c2270b82022ae9bc925cc1e873dec925b2032b9b9aa94dcc32ba79f17d33590fe567d6a2af272e23d9762f6dc28b933fc23091f10b387f6b4b5007668475c4e949cc47bf8f0475b404a8825407d3defa1eb032674c31ec8385ba3a52faff6bf216e2d409d12c549214e170cdeeba57838a9997c78b9888feef9d81051b5a0a4fcd385bc31b1547172f3951a9375c09823ac8a5a50eec4fe4d24c21286f3a1937e1c15561ec9e31861ef4754e921c8f308283b77be69c9c31d02d0839296f7f5d8a5570466825b4d458eb940f09ce269d1480ad91825491fcc0c4c180849e8de4d79a69ecc711ceb2a88388a5dd403451c113d9a741882ab0e003e046282d24d166167d72064a1dace355c0bf6fcc23887da7b367046b04a744737b1c1438b6027d5e1f0f26c87268f80cf18efb3c3f013eb99e9683e68f599273734bb138eed9caa64f6666f2f8022eb213dfc7a4614d134179afedf8e0e9335f442e2cc319f27c59e66169c7e502609f90272ac2c9f2886df9c0e892035914b7495d038164fdc763bcdd35092812fe63be88be87e75b5b6621307e585809bccf5421fc0bd18140d10123e3f3e08e6107d480c0046bc7f25c23c4aabdb737c4e5a2efe662c6798e69b7fcec98512e8f22dce33e8d30bb9d1005e4bb51335a473f5a3385adf731777f5b8c4be8ffa6f21ba3d9122898a5d67fc10380c497357d61421bd8da05effedab10181eb509c3f627d910ad27b7c343ea868145c48e418316644687ed5eb24eae6319b905701479f9700dbd0f41340f90e12a88a5e5298c0ffd0b244f07c1c12a990b6bc7c9acfc5fdf52e8215adb1d146e3ede0cf74678d520e2258389a43e3f31f197020bbfbe5e15e3a960bed6b333e90409f44b03cc7726323443c51eb1ecb2a12769a5f18ac25689956cbbd5eef12b839aeb7e66d7dc73822696279b5b5bf9ce411bcbcc55812d373a8274d1e6e134707d7615ee41db7bd54099b57321982f15a23e8c95650bce540b575a37c6502db6cb809c22341632abb17c3f474e6605e6f075a6f45c1d9e2983fc1850dc43d6da2c43fc974e620b998010e75a0a06f3cf59a7f8cf86688692a021da4f627458ace22d9091c8b869fb2af200bda765a5825beecb4540184d6830b204c9f81ad9b9a33ef51f7a484b9d9c97712f3dc94c83c4df184f6e3369570ec38603f0fa0840ef7cc2ff63cd2d0ac460a1da933084c5c3dd56e062874af6fae60680e804a31eb00e95ff14231a8f9e547c339149591def3b84aa69635ea69c30397edaa5063c0e015ee571dc0fb71ffb6278a299300dc41004ac870081d0b73685fc193f5176bcf4adc6fb4770a6219d0799af0ad48d28234fb6ad9741d888289b7687938b8f3d2789e87c212053801c71e3e51fd428657118d3970df10f44a7a7546bafb2509648a047e745ef204b2e74b41a363663ae5dda7ecf8b2b0f8c13349272955eb0a33f228d8e062144e4c257659d559a6953bf99ec9a7a8eee54d39b96822508e0d44d0a46801ec211d7b1c33e38021a7d75d8a583242dc8654a2282ad55f52ed4ec901a272aa91ba925bd00cd8c64d6bfd995080354116b4f09ec2f2fff586551156dce1ee7523e727d7f26aac1e8d1e814d0c829ba94cfe79d03d7395bc6bd0494b20b4310763fdb2403754173fe8f1c44e6f9a05acbc544e6523272d8689264108a4ab1f5d46ba3acd4389c8398c30d97be0c6acbeba451292671373500fecf83145cfd78056931f27b9968d598fb3f5566fa56859b85c84f94dbf47d8217cfe4b2906c84f1a2c197a60f71437a29c657bb247fd91c36e5ee358831149de89b25a3687958c1990c77258a22343e8ce307f2a3675c14551e8a8123fa4eab2295e4298a2eb7b43ddc12171821c60579bd0dbd9f4f949e9d7df80b4dad2acfca9e7cf04db7da0878fae8a449b2a8b64505868c25c5b7f16888363dc8ea0d5eaf7b4eb8c9a2f21d52d851370990eeac28ae035f73b8460317ef68e5e03325c43eeea12bb6b0b2d444c68e00a335a4838e223399c122ac7ca25b2ea0b046b1b586a1ccd532618df72dd0d36eae4bda669ef93108ab46d00464eadead523ffaf7720bdb7484ad0cb1c6731f832a4be2741403c89c5bd0a723d7c218d4bef609545ffafaf44616f6d3085b18c2dae73e04a896c5891e0f056d0a95168cb1f6e18fbe7ae95bd26f145e6e84510c230f74c5feba84b8a10ad90f84d70cfe1f74cbfdfafbb7b918cf2988ed82ff80e07e70a1297ad81da3d30a6ef707e0ae9022242160b0f002f894be92597e0596f4e81bdb1acff8df097a1f309b258a6190f4101248ece557f0a107913dd682b7f0c8d99692c030f9ffeab75f21cba6dc7c8a77360b51eef92b920b4758c31d0e2f1bdc0b8fba86d8d3183ef82b1a7e5e0d176c09a0debc3a3da7047dc8c48f5e36187a997eaf1e8403a6cd61aff6e95c6366e3b0f5bc3234b151847331a95e395cd6fec9d0f21de2133e0a41e3e7fe2297f566f6a8fd8d9ec5e28430044fc8cc63331e9587117f12f1a17363aa26842ebd7786401aea5cd200b3a21a44a22e2704a7b3ec2dfafd624aa28023f806a16fd89588694521f89284fa1b3f681c920fe608ff49c75a033a8c47da8f3d1fc11838638136545c568b0b963840b11092f3f2ebacded4b365ddf54f95dd81d431e1e4a0c5688f60eefbe43b9b0337079dbf985ef5cf96d9be8f7c260adce8e96b3631d362f4a3b2be480487b6fa40bfa5470261d30121790867cf9d11a8f6a3b935c10e68e96130daf8f8e47c24656e47c50e5b694394a44439e22b7173186e4a8c1565629d6e198135071c6384681c47c8f32c2ab798b22748f371fdd119ed56aa95690e6e6629d2dafc74fae839535380d3d3bc59a810c353397b7cc23548e8acb617d91f122106aac5b7428e41d431acb42f89ce426281ac4821e9288798e539c6a858407e738529685cf945b8f9a21fe8bb5828a8ac65ab6a0b17734cb153b5bf61c6f90387eb2c61c306bb19c489e5667cf1340f268f76168008bf8ef620a640ee60845e0f6baa12418a13307bead58f416341ee6a01451e2a31b0ad797766e7b03019566b01b30b56eba9a1101cc382a5e5d7cd2579a75a0050cb659c2d04a5e05b5fdc7933dcbf983a2e55a505f20ba1110092f449ef16c4d102805300d2b0e1837dae6f694f9a5717579c50154dce64282110ae45b697f9b1d8a2d8647613194edb1389ee6ddf6e1b0cef672066469e41c3c1691650e9e7032cf7a39dd0466c96360481c5fdffe7bc2e1fa00c4e9445afcbdaa02c5b304e2d9df73de542407c80a6d099853a62bc8fed3335534c8372afd5dac10746862e0e5e3e349f8f0facfa4545e88b2708a8550606611e339dbbc7f9c73138c9234ec03d42d9aaaf23120ecc2242d5fba5754744f44f5c174060d050e291dc1c205818b9fd35496505b5cc9d26eaa16b582d1eea277c400d7f9aeb6107013f030fc42c199051c54cdc98c01f525179112fcd31325771fb012ef78d39d52b2a9847501ae6d5afed00e37226cd6b87d06eca9fba81089fb97569730935db8f83dc7b60efd0d0f36d9d7447b98d0b7b79b916871c6b19d9e157c712a1cbb29ca269d2d0d0e6f7cace3e211994035e318651d2c58cc2ada5bece886d0494c843aa03b011aba0743e4f1f48bf0310c508c7d1c922a92c892a310c014fc60735b2e11d2ccb243970e667ecd2a44d2887016a32210c4aee1d03c0444a48c021a4a8503b964b6b83d33cf3468561ff1415168e934e84aaf593f8de4e43865705a3093b558280e9829c282d8506a351437043b46c70ffaa8eda03be9d3ea49152abd1aa970e80c689dc7235a0e0d9f23d1adedcbe2e8072006f80d000e4ac5c3413e23e9fb10b7807b2b771996b32db4120c0186362265db41bac46c139c7a87cfd334620fe603f9dda1d13ed01d48c2725b0cbea004730064430b10ff85698113c44122c8db6779b969d8a71998d894f510b80022f0317087f72f0b7c6734b2289f19430f920ac9880ce754fcd069626896297739cb9be17d159be9f73104c924b165e81c27329658ccaad1958b110ca4c2aa127168703a75a0affec2510b174ab4f5e1c6fa87b115689bbe7f3f4d5ec747b261bf2f01ea2c886281c8d2b6a86d9b837d631e0e09386f414454a04a632928e73b324036ea4e205c178dc973ae4004a42d3612868e879b021f1844ec05b12ee8dab5c13ba0689ff016f1ee76dd5d56ac7a191f806000be6a8b7f50c5939b6388d9b422cb057e1c7276568ff6fbd3c1403c748cfe33db74432d71706f31642faf3e9979dc0a24ee07ba2d68a36b7d6d5435d7a28d9a9bd966434eb1a4577ae60cc9d410edabcc8a74afb218c0b11e29b420f6954cde70a78e51542fe96b1a3ab895a14a6f8e4ddccb2dc1d6eba8865654f2825af26c5c681fa531d21dd4576d1e5eb096392427dbd1e19583415bf7fe5029596aafa14f88d99ff54f143ee5a0d48bda498cd351c25254a6226228d1220d198830c0d813b27c605965a0ae4c6038c872aa48c5bdbaa94de6aef1d29f4a1d944052492fce478ca0f1f0367636e40171ac6852baec909f3b67b8ea18cd8f8ec0879aa2b1019e817b8fc23588a91f65f2c345fcc5590cf0e50a7b4fbd9d68c9df2252f2af55cb7165be5135b3c7e2394fbf3ad1b9aeadb2eb49e40e07a7f3e79a170eaad8b680162ecf18bdcb48e721fc84982743a78fd5925e628cc65382d52d5bd60a95eec9c935220a9200d2f18c27582c722a30d136ad437eaa3a67e2e6b1ab01b56d8eacd2d98c23227b1181008852302570006e52a798cd026494b890a2b1bc5c99ec63096c112a3513e4f3486ccea0ffbf2ada0af36686ba09318759aad3e3a2c83df309b24c2335b93f6484fe23a9a6f49ef9cfe50cdafddac5e4066843a0916a7d757239d6db4be4ff0a380b74eba3368397f20c481097c202d5abf8babb7b9dfe2185dd7f5e72ddfda463b202d3d6a010e9ade4a3f14d78de338f4252c0ede5a196d8c1ad8e47481ffe808ca68bd30cd0c8dc2fc6b84d179092949a0b4a84717e4d589e438b46f81ac481071bce136f413e30853edf01136f7f747ff6a2a62e350a0add002d531a50cc595fd851bd894f5dd6d12dba394b55e4717730ef0fdb8b978ef9b89fae77aac370a78c8c56aec1ae3939d444cf7dc89d99547622966d44fbb17e32d9f95b37218b8ac2d9fde5a5e4c05c19278b3c74dbb0114255e1577dacff04692ca753960cb64125058029d63cca2e26d7390f2083367fc35d0d2802724bb33162107f9201f85be9858136daa4eeafe2e4166f83620027cb5db97f00a1c2aa542f1633ea61927510005793e7e8994ecb31e1c0093d94dfcb9b2183e1da951a547254bbbeea61e24774af4833318b7f8837f16e0bafc30e79a9e7c0369be2860c325004c0d2cb8840110fecfb1c808d5ba8fce59f51ad219d7bd343dd37f16563af6a0439526c6d08e602c518e7999f7a626fd8768aee6be805095bf16984814e6f00cb33443b10d6fa0a2f68df5ac799b671e94af641e5589ec55641de48b14a2ee6a19416bfd060741e0095b322e5a1f5067a7a6ea80e9e52cc8f1efdf70eaebf31fdd55f1d560427fd0128eed97132ebce491f0dc78f4231f0d5e36e536681445b9b00923bf86793c85266329b7afe27adfc0a017f1a542514d7d4e7393414a5fb00a09120c021b7c6f5f3014d5d4736365dc3d9e6e94f16aa13a6bb4687f7f5a08d40ecf44cbc6f800064835e88c0c8d435674e6b85745646c4f4b42a7cf8c321456fcefd15cef19405bc5e910c955706b6666690c815a865f44a2196b06d12f36f6909d4478164bfb059e8a131193270a4fcbfd1561c064c83a2c6264a2cc3001d4bb85960aaba8d1d90f7b84aad6eb685018f67f76676e490e4ec1609df86563c0ea50fc861a2926a2175c26037ba4216a8e21829a3dd031cd073db343e2b056b46f8eb502a805794ce95dc45435fde56b699f66762d0ebd38abab0f5d77a9bccdae8b391558e8ccbd04062ffd5c159f35bec995cf23f20fbd4126a2845cb775e65efe4a59a124fd855b43b2f9217d46611735c89a21eaf87bb8c164924aaf07aabba2e29865f49667f655d6493b2071162344f4de0ac3b31e4bb28167ac4b88a0a56b87d8aac420d7f8fcf8aba6fdfede5c51a31d1999859f7f860aeceea1c2a605c3d75aad5a607515e1181b1b87355fa1be32013486f3fd95ae8de93f2dab8d271577bdb6556c6b2b8751509bab1a4e8eb8178d7a8c5187b0c290f106f54a7994d3b2a301e93848d8500f2a5be5acce6fccec85d478c30876ea90b84323858d85406e2c51b606fc36faa733f0bc9cfb8c038af4157f124580883319212fc6155a6ad5d4f96e96e7e2654a0f4270ea3e752407b3c13f876aadb634e54b50a4f96d80b7ec77f076d0dd48426fe4e1c62908f913ac522462c4d6bea5258e235a6e9af4f6d0c94942a844740305684336901ec0101a1a53d2f63ec0efa6c960a4b01d978b14308646019ec437388536b493c8a5e178fda771119fe64dd0b0a7a810eca409161953fe2a6efd94a8a69632bd9bf66d19012602bf93a3c682e06a61394ed4d5b1ffd53678f6d8853ec308a5f8aaf8d5d767e8b2fdfe88508b10d23d7ef5710aaec2dbe36a465f93e96b0449f6d4cf163fd484eb475f3a2213774b1d58f224480192b8e3aaac82e5537e8a57c3e0d288df012ca533dc27830d20e1da8e4287693144953408f1794d2d5c18daca8caa4ea64489c2e2418e26a11f3a31444a15101ae72db12f7c5683a910fde4bb31ed01341f0da9ce8943fca9e7510792e18a1b1e50c66810ccb498904370ebda07c3dcbf6d4895ddfe8d41b58f99c9fb519811f6985f0eea70a0a1a6546dae1bf43a2a29ca1a3797e2cb1bea302573ee39924b05efe056652affc81b168a16646f051ee004820f5a2098594d3a6d37739ab9ee5f57ef11a9418901e655946def56806537666d6e899ce3ba7e32130a95d43cdad71a141632e63d60ff7730ede6f5359f095e5a984115632e9ba465a57b79fe8656879aed879e98684208217b4bb903cf0eb10f600f54d0cf84e4136bd1b22b8fe2016dd1491c99f763b0111f3112ab57ad526a6e8285c0331366e2f6ac67bb34d75daff4d7a6d6de613cba3266ceae87a7dc44bbe4676a2ba4777579e5ba2f368c2163128785228d3c4320d230132b1656d2711132d8488c2a57beb3e1a9ac5ca695a99d66b43ad990a26ccad216b1635756d3044db2fed0dd205c166188ddb6a8296808d3b39e491a292fa3fcac3c8d38ca6d175596980a2b351bdd549f8b5cfadcd3defbccc3b27eb53871ecd3686a31930d572b46ab154dcda42e2663734a2969ca05e5523d5a99366d94ad72a3946f617994f2e035a326f1685362b95dc634a3368a4b51294e895122523c8a216327757b4e2d76d986fd164739a1611ff5508bd9e8a7bac69baa5cb738f5e9f408d6a0755e79a617b49a91c91a693389c35d48671d9334f23d932ce54c935d190f823a7d593496c922599a59585858a20dad1c7de7b51b16b9d3f68d2fd8fed0e64eab673ef07d5f04e3b9c6581930e315370462cae900d0b86dcc750771fb1cab5643aecc4c601895328c9093d832a05df1cc0486113f9b2f6563291d9b3fab7605d36adb368edb368edbdeab7e0999b76b1c9ef156857457d3348e6dcc5498b81dab2801cfedbfb0e1f6360b8a6e0ff1c5c98fa92f3ebe0839761b87c11d2cc48d36e4d87cac3fd41c2de14e38dfc2b172a70dd272e323116e8c1bc62c6e28dff1c61a2b055ad12a60e7c61761121f6144d1c67615e1e3c717df154d0461de58050ca088dd3e2d924d371a8d80891bdb15ed0d4dab3944feacfc588370571e668746a4239edcf0ef5710be3fc458336b70d46a38bf3d6ef1dc6fe4a0232231598194524aa95d56be3a624de7106bfa9b0b8cdcf0468046295e5074c3bb40c62ddd5006952b2f23ce88008d4843526e441a4aba613c7acd1ce20cf9be8e38a30a204429000da36440bfc2df461a32bafd1e10e897bc2b578c7e0945b9fd04bc9061c3ed9bdb5f19b97d17fd9261aa9543fed02e6d645282db37d52865e4c25745119adcc8eae8813ae0bbc7da3d7a35087739ae423c967f0dd668cf69961afbd5728eb126deab4382f0fdb6ba7253832c36646dc574cdb6f8b2e3bcefde0f37d5f00769fabc95ed0779e7bdaae9e82062d7bbd6011a4413421382728fe71edfd5794e8bc94905cb3b3b9394dd5dcbe6d913cc61e74ef992e76b600e3b97a38bdf31d6f0ef8e644965d6d034e46a93334929b5f7b50ac4747bc67e4ce2f6d7d228f87622521474a728a75d2c43468c182ed7bf5a49100b2a39a4961a3715bcd9ed8351d0d0755b93d22ecbb078d52bbab87fc1f2d055808731ae010e2a81ba886198190b534fa7d386ea5acf91332d188ec9e91377da38eef4087adba9ab322eaebaac3f5cd85f5bbafd98eaa2b2ecc6e487794c7da42dfe7d291815120d7db8435ade7297d34b677efacc57562aeb3dfdade0387d664797d3accde2e86c9cf9ca593232524666c57bcc81bf3d82373ccb7a7dcf5f647efa4c95f9c7add896f795cf9677eea79667719c3e572e250a85dab66dfb3ede369ed3eb50309fa773b5022d18cf3453654e35ec2e635551d0ce02692af513dcc1f7ec0ffe667fbcdcbbac2b2d67bd5cf506731cc78b9ded6ab1e110e9d9d0c5c676d1cf7651db62b572e1c2858b958bb770e1a2850bcf854dbd858b9ab2215f17f76ce85d06178fb4858bb7707117cfe91f66e5c6fc7b795fd1389ad2bc6779262c62e4ce9c5128146ac6b2583824d7960d51bfa269502fb6b1b8a8af6cb8c56e6fdc9cdbc6711bc76ddbb6759be775da938bfa4459697fc44c1047cc374d0cee8881398c8cf961601e6363e59f0d19044dd78be03b10e635acd41ff8ca4bcb608ee38839cc71b4e947cc61fe45700737e338aff3bcae676edb9cdb9c1bb77363aefa374db2c23c26c6a29ed3b15ddbec63ae3d6f4e8e9b1c374f52bca0e7bedcf8c410842ecb9ddb813564c0dd661ec1ae9bd96a68c3fd64ac87b2611017e6aa10c889616a8c0c95de98fab7a85c9902692af707bebf8b1a6f0daa471087cbbdfd71facc7fa03ee3799ee7793fe843d45beea9beb272facae9f41d5559ca48192b0186f1bdab39127c0457aefa89b5f2999f2a5f140aa53aea54e39d49ba608e6fdfb9de8a9500c30041b0b2ce9dde71e99e6c0844f51c89620db5abe5f433f547cbe93f300934dc8e1ef3d5fb20b7f26fc5e36c78763e47eee04e51ff017a5fe1401beec41c55c39dcbe4e58b60ebdfe7e22899a3600e733a9fd562fb5cbdeb2eab00c293b841595999f76cebbbf71dfc061eb41ef7d43fedfb3edf7d160768df4d3087d3c14ff00633b8008ee002f89e9ed32b561505ddec5f3afbe374d0fe90ef86c8937ccc5bb056efe4cc3b1bb29ded62d999a32e83da2a6a7ee350f3dd376bc3229b0985e26c3883f250d6c5675c44cf86df4cf5ee32736f06859a6fad3e5bb3f5af8640dcef12acd1e2215af91087cdf8e9dfa97ed4eb2c18c11d2ba7edea0ed6ef5c95e9de7d469d8d43f7530dbb15dbaeaef598cdfe687db66c38448239565b8b0b87c895c3fcc71079612edf7561eb31dbea73c5867d57ceea40f0fb8c930dbbc71cfc8c1a9b06b421f79816ab3bc1acd4785b9e9763f5e9799ecc796e205871d4d90a4fafff6a18c49d56da30e6f3b15d8f09775a2d7a5b75f59997d55135de5ac31e6ecc533504e2c6dcee5f57c3edabd9dd84315ef56a184493bbb2e1bcab9fc88deb7da788eb3d04e27661103eac6abcdb1673746968be12bade27066eae67c31c2e909bfbc79fa6b600f07901d06171bb9b72a3a0a1176b01e0f1c2fc43a1c096a3aef2400f7c4e7b200882ff38ae805f61fd743a9d78e5fbbe99994f06440205512b97329593ddfea986a75f79e7f1edaae7a1fead54faaf7a47a1ce9dd7a1aaea5f8d977ee55f5d798341f8d258d367110145fdfb8ca6a4297d1beaba9e9e2b2b3b779e76ae3744bba795cafaac32079140513604a27abcaceac5dad51ecfed991a46a31a7ea5c6ebf51cdd9917cad8ce4b576b227164c830bafd182aadaada49ab15683ba9eb28e14ee7027a43e2bc39ef28070600b6cad876b445f1bcb91d6d1b2379078f403bdbf96c75a551a151a6dd8e3a2679a011285804ea7d8ad5a454413bd4137486bb086003e333d448438dd755e70d408c51f319aacd035057efd56b5c9bc25268a81a52001ec11a309ed3db76cff33ce96d2d5eef550c44a4fba3c5eb6fa02a17d56bd0e7f4a7b5380e355e193eccf57045b4ab97a072bb070b2d4abf6c6cc8d7e64d80d3f8019ef3fbd075bd3f94f192e1debddfe897eade73e897cb3dcf1e0115566fcda907a8346a0c31aa06e5e6368f61352836558b2204b5b1794e37b81d514105f0505332ea970c6fd5fbf2094e8c1bca980c509b22d6f4b94a0f9194296309de66a00df60212914ff746746ff85caf935eefea8d1c3a497621c6e48a0e75fb12c4a15d30182dd1444a2c8206f0ced3a688473d37bc99305fed86cbf0066b04e12b04870c97711c7ea35f32c4a46a48bdc616b62ef3997f55880b21ac7fffb639a475b9b96ddcca36e73cf79539b76d6e11e4c0ede0ccc3ed2808104180b8dcbfcddb367065f3e6bf73f5c75685801f226f0dd006e1ee8fd3518fa08e93fdb1728f75f95987c87bfa56877455c8837016378837a485e34efbe387ee7a767b72bbe8f2fe79362472bd971d2131d60ce96ef71cf9b12982dbdcb6201b14cffb210877b728624d1fe6119c7683d95acc7b3297acfacd39bd09d670e5a87f5e15e279a7951a84fb41eac4ebc206e17e90d73bd9d6af677f903156088eee72975f6db94c4d7da66a52dad519e0ac965443ed29a81ed0703b4a7d3bc2b15d52ea5f1dc482d2ab2e43cd699777647f9097da04b8d41c6aa8ec8d76796f51c31ec2ceda90d260c3d5c3bb6ce88a11e37ab6c50110a7b4a801380e95afcd8c7a7334a3704189499348e7d68135a6a9450dc06d6aac01f8d6d3afd975946ef762bcaf4589f12f46651ac3e327c8e0e77ada9136459c116f10808d51e7dd865087516db8b97c8e814848dd5fdcf33c8fa5047344700afac302dbf6171fb81df52bec2429dba2f03df576c5edaeb32bee39bd31e9e63bef2f800899ff4a0dc2dd1fac9f34ad6aaa0fb50794cd69eeae375f7cbf9ec9343b2088f870bd21d7fbce79de67e7d9e0b10d7388bc367c8239a20d75de6da53ea136b4abef6a575b02c8b03686db18be552d298618bad96d9da6d4c570fbcf564d4a0cd792945c349f36a434683af5de63fcf172d55be8b70b6c442ef8ae4ebb755dd77d3b588310b9b39bdb6ca1b4c63bb7ae9b30dfe6ec364ec89cf3aa697f74efaeeaebfea2fafcb4f16edd77d5c7758dc5e7ff8ffbc06d88fb3eee03b9a2a38dc9c6442ba645abc11aab370c5f0d09ac81b333d680cfe959836d0d0a08c2c0c0802b988f5bfd9bda0782a0a67dff387075ee8381f940d06a48edea556b502ac871ff40b015d3faf7816f81312d0d89e3b66f0ae1667fffa689ab3ff4d590e6f78d03c179a4cf6e1a9496d249126786bdf17f9ba9457579aba61e430f535fbeaaaa73dbbb87f1a8fb26d4d13837bfbdeb41e2d0b03226096069a0b1ae6da8bb8c35373b980ff1af6b3d5c51f03b8cdd98b4ab8bbe87dbd067b7a2a1ae850dbb181bd2161614fc362463459eac5fddfbe08bf710565656565028144ac61152f8190020c3cccccccce9743a7d46ed58acc7c69971164b464666469552cad65b6acc69fdfeb27a8e8ca1f29da18672289445b72f430d6593db7f51bb5bc3c8929939a1644cc69a4a0c4de576499a947ed9f7b5299c9dd63e469c1eaced21c629364e214011232d6391a6bf1d4402f55cd41a76d6e3ed41706d4ff5412050bef1b10efd72b1215f9773dee675de10ed4b7949d4c5e537dad55bf7957f9f047774f7fec5f8c3c5611eb69811f3ee172072bf7901d91c6bbc871788b12608112fdc0922efb664c6bf987a812031d6705f223b6c0076c900ec7614b35db121499abe4090ed49ace9c758e3d92d8af7eea7ceeb3c9477171503f2b672c0c03cdeceb330f607795177e56955dad5aa7fa899539c829a9941f56d6924372c7a60db124f7fe684eaa15fa196a40d89338f416ab06e83efcca9c1203550b7c1f7c477f379fdc7716b96959db1e6cfe973e0ae5e5f6d48e4aede2bbb09a1fed5ed0ff2aeec90edae4ea7ffa795dde4499e4ea80341c9e8c2b811084a24b8d3d4e0ff4d4d9e4e27edff34f98f3ba1dee77e4eae563688bcd2c65873fa5176136ae5409df5d319c4813acbfe20efc90ed9eee9df668a74e61bb863e6ac375883954556cc6e79cca4edf916a203c1ed796382db365d88345d63dad8ed87110aa3dbb73cfd32d22f1be396ac154a6e734b6dc58cc7ac5f2d6e4e6dceca4de1b068178d4de9993336a58d5d9ba558d3f7a040439ba5db4fa1801261003bac82dea440d268519011883e29eb0b57e3308f72020d776ed4da76778c9eb393ff36b577767eb2721254bbdca1d955bbe67f489bf2020da3d197006e69ba214d0990a9dbd5d9ae399ff331d5c27981a4aebca66955f808e115cf6dffae5da33cd1e83c1d4b92e29e034d9668a5e6b4cbb337baca3767c6e03eb9a412dccd86323e3ffb62062177b85e41c1175f8433a906dbea51c36ff80d9648cd6bf80e6c07d6e3861bbe038b2c493e2e70c2a78929a2783d26a527a240c4143e38c919925114483b90d1807a464a4728816674041db800944a5b919324a42de664091ef8a15f4f124b1825e18313705c5210148cc0d0832946903a01ed18d09393d1089c4c391b819439822d740c0a14a6c1b7634ca3ef647bc10dfb49aa0434a43d53f0e868afe889a2279e10f405af8925b2d0753d33298a244a4f0c210655d0909e1049e1041c629b9213263011057ccd908e90036d7604290401dc927a8a901402299a6889e9d17a78504516669210d292296620c1222d3685112612520762203fa52d86842a484960b2e48b4e2869331e4009ba82863232020d8aa400999236a327a42081e925494b2a42119c1881889e2dc4a21cd9c24700a36de644094d94acc0220aa056c4832158418b011581f2e005953423a2052b49443431922c33171ce1e7a84549224159424f8f15a06a264491096cd0adc4945c405494822b743436a4a48828a699134654f9624ec4a458fa829652a20a23215af002ef940406278c08310483e402272b90624917809e27aa80e205ce543402143c1105125e8c052398b12049143e5c2aa6c4832986984642c0c20bb616312b7c8090e082108a70440ad48b51cf11464034450bb4092797d81350c2e0c4ec0a5770303d488cb0c29b4de079a2092d78e2c40900484adcc0c8280c5dd00195ae4b4292e4c4077c6ec0d51825291962269bc98063e9591223602cc91145928b493162427a42ca124f5ab0b2cd9470f015393154c511dd44eae9c087e40493a022565e14cd991350604a7ac2093378d281130bc90b9d569484640bb321569005ae2526634a48c1a8031df040a4a212505951ea2142a85f93873018f970d84d5649327682881e7602c80b9f13412498dda45fe1f4e926fac57279faf48b3f85be4ee9c9135030814c7a020a4e303d31c503b206468db008ab81f123ba0918b58f1a073e6d165c292d0c3b29cfb5cb77dd5023ac861a048d28626004abe11f0ae90a4f62ccee5b435db1cc808654333d29092a5a0cdfc01a347cce7777770c9f349c5ab13441691ec35d39fdd9d3d4902fcdd2d56a78d8ddf090c2a879188de251440ac0c308c58687f10a013c8c52623c8c58d87011321eb210ce004e839b28c04376628087fce43643b9cd57b094db1c9ba224432360da507b0c7f511150a384d5286f8d52861a630d006a6c57ce010c508026ee3c0168cc1880d09d975163d3e05423b16970a8b1696c6a6c1a01d4d83436d4d83401a8b1696a6a94343064d4c0aee7489a1aafb6c55099f61079717039e042129cb8b6972e0d6f300797032e24c1e85adb5d1a1a6ab800e0aaf172ad3df4ed5c8d061b9fccf07909e5320d4fb934dcf58f86da45cdc4049486873dd443344c1f0945e8caf0aea374b57ad34b5b468336face6075e8a161cf686a8cae70d62e6e2534d47865a86174d243cda48b6870f1945b2fc11c93892f04e1ba6a7723586d0bc794db4adac55dcf5a89046b00000075da2535bc5bb6ec264ec26ed2d3b14f46490a1720d10d490a1744612aed62a51c7cfb6d1940fbf23fd992d6465f297152332758a872395e27578072f904e857bcbfb9ccf55c410a5c0f1692dc303eb97c39fbaba17e5a503282dd5023ac7da6d09c350e7c9e196b3267359cbf9238375c0031ce303e0320d02f8d86f32bd02f9af37b98e10c80b30ce717e718cef65ccf3fcf9c63ce679f7eb9389f85fad53ac39ccf4afac53a9f87fab53aabce2fe733a7cee726fa853a9f8dfa753a9f9df4abc5f9cce727fd6ae917cbf90ca55fe0f91c85afe8d7773e27f56be57c96d22fefddf98c05739538633bff1207c603f09a872e1b1ecab0d157d67083006268b547bbf834d0b8660040eda15d7c19ea8beac3102088b48bffca3332312e5a30955995579567aaca4a5e2a0f3193a27631d1a409232747480c85a3f015fcaeb2149e52198b58c3875103506baa0dd5ea90eaa1e1f499fc066b4ccd2ea9e11c98c3ceed540d76fa48254dd087d3e7a8c35593263355024afbef467202851e4a6bb03c8c14451466120dcd2c90e28b2f4299a449b9cd4dce39e79c2829345e5413280ec3f8373a4aefba2bb6d5c3fbca572c9115dbeab1f2ef9f25f27de53b30f03b30efd7b67ab0bc7b678974b6d5a323e2bdfb0eccf41d188beba298005653bd2169381a79b55b024da2d3cab869979d40a59286df55941268488bdac54cdac54332d62e9e973eb3c2481e29b372d62efe8f69a52c265b2881b28cc926714a26fd8a484e6277bb1c7ff0e4f24a8db08e6ed7d9eef688e464bbf1074f6effe6d41bed92462edfa1f4e9dee494d9a5102bd96c029aa02f64cfe5dbe09238a0a1ec61699774e7696567abb48b7f4319caa18b45bfde64ce466207375c5d3934a7954c8c28df0f5d7ea473cea22c86903993ae589e19b3446134d2010848c270a50d5739dcd969815cf9c9d852b7afc9a837938a184ee8fc4cc51812271a25714d9be09aeb77cd72ce6f1a4f2bedcec65dc5f7451a5da456b1ab1bd062ec7ef1028972724a29fb3f34dbb58b884a02f46b9b536a9a6d9cd8618ccb2e5e5c694378732512a87c5ff9d9c5309a2ff8fa5f579d7885c4381f6408dfb6217fda940e69bbbe3b9235f0c517e1169946e4d66ab732bf79c119a88b39237377cf9797395f6617499a7a433a5f66bdb387d6fbc27545bfba76cd4bd72ad24c22ae6871724284d18925049f96d1171717fbc28c8242e7c11a3c5956ccdd1d7b8bb58be7e5a156e5656a45ad03eaf22217b9f5b46bde050456c8bcfde2a4878ceebcb4e1325631687472e54ddb56bfc545b5fa710a266471e3144cc0e246ac99e714337714463d54e473e5bb7b0a26ccae7cb711b0b095a660420e6ed8454828e2f2ec148c8ba9c55b5479bf9629527e0bac31a7b8cc5057d0502b8a31a4376a499da491ae183162e83a4b7f1bba2eea0834d46415689a96e1776046f8c295ef2b666c8e92653ea75b541bf24e9411e87c91ec3a4a5daeef45d54cb44b7e094aada95d1d117d39d17088c643e4623725db50e3201ff611e88b0da393db0f37152b1d8b76cd292c600efe3c08e260db8a53ca9c611bcd69026b1891b54b16116b648339f8c658f3c1985055501415d4452bd1435a52bfa0458bf88d678b6d3c5a925665e369a42b99ed56c4d633036f200067b83dd4af95cb7097d376ae93c14a1b5da894a6b4c536d9d65374e5b722fa85baf25a52cb0995960c928f8c7eae977f612771ece763489c6ad4385a92cc6c3163a68bb99a2b1366ce7c6ad39baa39f432a954b9d3c89d45b03e91a69126d392244e0c97a8999adf2c9aa91c436d61431ae35ad192606c288355a3b01004569ec63cc4b6762d1bc6b0482b132a5504d698b1ae5f5a13a24b6a497fbcabd61e9234f21a14925c5ce2fb89ac8fdaf50489f24317d7b6937ed23aa09a6cd53aa02fef3311dd66fd7ab17d45bb3a4abb34235a4f0d9b8a20566044fd0facf1a225f52bec28da1489f3e2acc33c4a9c3fbcec858d31d88e5d458d244e844d987c23c5197c657c028b22f9f2ae2d3ff48b79028b226edfb08786fa159f98024f3771a57c0ca883674c1c69fc70066d0cdd6e68f610936ef1a199cf8b6d318fbe699ae07c9579a6c27daecc6ea2e69cf2325d666ace39e71c3a9adb0cc686ab1555d970b56ab121a5a8394536a373fb04e9b664dab624be64e622c9cc5f392799f9dba54ce2684992668a94124793491a79399334f22f8ffdf262c3398f92737e739aa689b524d962c38e25094c327d928b34996466590f499cb8a23c74e53d963145a6d142dcc8c52dc618b538a3ec1863e4fe16d30728023f884ebc3c81ae65f430277f7bc81ccfe74fa0877e314e3373b5870ac4fe042a20e7047ae06975b03939b4ab02510e8401f2abc8cc040d63920c2013e8a15f37a2cccb2419dc7075c3d58a48aea4a6051a3f6d8ba6dab56a2963b40cc177177fc1fcee6eeebada6966a32f062a0a0d8768b36bd7dc8ed0df905efeec67054d63207d42e2b51ef98fe7b54dd3341dbe9da66d9a1623333333f30d2b8ed03d8c5fe15aa7bce7a22b67f06c62ee00cb6a8401da182233dfe3c83c85fab06219a400084c907123c7e04389a676a5d8480f17d1ae0865b6448963a229276e3880cb0f0750a3a459459c55a4e1473a3ba6b172efd3c01adffca665189ab6f5bc4da79cddb2575a2af984c4f39999fb10685777189518206f10c1834813831069e29d56a0e1cf3e08619ceddac3e8850edcae1146dbdc7e894a47f33ea078403b87fe8d7e6d22f8c1134ab73b8c473d37c63057f0c538e3077af9fcb862ba9f34c17660f17415ffc8efb4c7a8bd48a1ee0f766d37d2800d0128c288f1051b820aa22b5ece865c5dfd4dbb3fd8ba8eb4adf08a2a08b4fb7c4b3e1a250106371a5d4185cba04ef7963c4371d9c965b00638cfd54482d88da04e5fa9831228037a348186bf0c12c4aee4ee6f50a0a18cdb32e28cedfd01cc609c4ec627b8871108b7cf952576bbbe6719467c222d1725698a0ed3f445caafb1a6af551b6bfa32244e0c918669c40823b4a9e1f63724d078d9867c43407f6503a1abc208b0e68e9225dcb94bdd443fbc62882e9af8eadef243676840b48f2169fa3d3a20a6cb560724fa79c388c5ec2e1375f4f65fc026accf8038836f7f02fd18126707d6b00ae8f0e518272a6d4b7bbce1108d8788ebcf22d030c66d7e8c28593ace58d96237dec534ba986671683a52565ba021bdddea6e8c9cc9463f38b8613c9a332aa18640a5dd68f00989ef77eceaf08d07a25d4c89702c2231cba8408b0042e2dc2042069126360e224dbc0fe37590345cab0eede253cb0fa36580ed11af0e4c439ecf4818479b0f39098e01d71d220ccdf28834fc235c7e132ebf6d8c42f4c1e5d7f07926713ac6339c79cec207a440e1f2432ee272c8462e3f649e18f19cebdb579a9db693ad4111122fdfc56eacf1ced916bb734687f08dadc357bb94f3b202315d19855ed1498d03dfab4294788f0ab4a9f44be2dc20020591265ebe414450a48937ca4b16631adbf9b2038cd39d7b2843204f7039360c7a244e675b0691b338681e5cbec68ffc836ec1e558d359c1ccdcf9281e50f979456f4a80e00926aca8c496499af859c48d972d93332dca27e4435e74ec765f76bf4e08ddb2dba55d4c5615056df9905150685f76e75941573acfab829a64ed2311067f05b4d16d7b166bf8dff78135e85de66cf108d6480d69f1ae404c37be9ba46ab7a8cd4413ede2bbd436e23e4205e010e58341f8cecf1a504d6ba4990e388e734125f251010b224565a8128941c8420e6800231204ff3c086e41184ab0591f361418e5607d6b718fadcdc889d1b459e2ea76b43da1b21d2199e04eeeb162490b2a0bea8d922a9fa02fcfe9d4733ab5847a4f1d75f032d7a8a07f006e5fa33cb47ece13ddfe69c3d6344dab373a428a321b2a6a9234456989e3388ee378b6bedc62db76cd9ebed513e5917952f33a1ef92ed62f4d9b9a4bcb650d8b641167ec73c6398fe6b926770e75f3e1f4f15853e6128b7f5453a58aa292b19a5f9d7fbaaec69b234f5fd5308c4661f4429e1925d508d6389d4e15870c831031a971555a40b59f2a33a8dd5616682dc41257a593b5e3b939cdd7f2f5f8d6ca328b354658a0b9ccbe8df2cf3bcab3f500a8e8f24f6dcdb3cc5a1e2b9b5c952ec6d954699a3e8fcc48cfed9b22846636b39523b5051adef858aee321da524a686863db4f129a925d078384846edf0fda0d2770b52013b89afdb13dd4bed921da8e6bd272ffac8c6aded7556b793a9df94d7b8ed46c96fe90aa2ccb7ab6e5ab16961656422282967f5676ef1f0b68064d0eaa9ddda49c679d756f75d66a3b620418e69c1d9b820673eb2c95b56bcb51e4cecb6b59a0a1bc52865d4d71c80229651115a66cf29a9025621f4bf41bd9b66d3a643f7d7e036bd0189d96f2a0b2d03f90b141e675fa4e96a78c6842dc199edbdef1dc19b4840225114cd93c90d401a3101c9d0069024511e2207099e0ce9f3ba5bc04bfd5202d596451e5ca7facedd83c70a76c21eeb461912c2e8f190f25281e33d45daa4be5fbc283c9570fa3153d725223200882b397ca3204a485b8a883ff5095658845c9118a62990971b925ae5bc265d9180f1e4ee06ab2b33a9234ab434abb585508f7eb8565c804d6004f2dc47df909cc21c310cbe2be9c6f045f6c0bc706a585b83aa46c512421f56b6597e890d22f95e5a1a45d3b6aec28a25dd74122c20d231451748c3caed53d5e958b9b984d159b256bb374138371c3696f6222a0a71bda2c9d4e346a007121c28837a4568834f1d6008242a489f77427206daf565d27cfc9e4bdcb211ae509b57bb6d59d6f67831ca0a7aad21530879dabb5ba1695ad72ba870d2feeeab202b1e1b21ea9ea3597c66e90b4599234f2533d7a3e0c0182c895720b02c465a9aed520dc655d8235549faa661d641d047330cb455b6d26559d5703595792e27694878d8ee48033c9ba2416442dc2410cf6f14f8c08f52088509f16c83c6b07cbdec430b0625365f3ae40e559d739d2aa8e91a74459ffa703e5521a63599d698a5407a95d3a3a4e74a0c8836f5047e7890e142bd0d0e6c6e766d6af28595507094acb234d7d823ade356b53e526d638f4bd2a7854a03745d82c499c1b44248934f1ce9e7e4d25224dbc9b94396d5756655931d2cc997a4b4d5dc748e2d87858c42322925cd086118a27fd9a739b8f399df2bc14aaf218a2828636556e6e10b01467c4b8ad69de39a80255fea99cea73887655f607edaeded516f878518fabe7748b959577a92d281944b9224a9cd6a3314a65fdd23a2aab9487c6348dca348f52289cfc58a296e7c4ddb47b754bdaa46c499b6643d50d7fa5ece8ea4ad65396c5fa666334868a42a74d959bd89cb759e2baf08687456343349747ceb65cced7a5a56e47a215b30d55372cda35e52c95a50634b459d2340d49880ab771dc4d8fc48952241961ee4150113d9cd4832025dca64521434da1c98d5eb8910a29347173ccdbda94b64d09c84e1b763d885a7e68cbc7f9c71669711106d45ac2418f30fe3903d96d49d270314943d4f213610cf4700baa9c4cd2703db23967111255389f7671334d9bf92cb992abdc505194a1ab491bdef44839990535c258498db0140ae8179384c58c6dec8a2857dc6e36a2b67cf0cfd988f38fe5000b9d8d38037594dec8a6cd9266ed8d4cd3b41f292818228ee5d78c410a42f0c46d4bc4ed5b0f441cce8ae0f653336ad38588c33e0fbacf3b7bce6e56874ce2b08fb58992864e1b85109653724bb1a6852a0f4792069c1503abfb037cfd274d768235ac2665134fbac0e4ca1b9f7461e87efd041a812045c9bda1364ba66f035ffe692606e5bd96a7716cf4481ae9039fdb363613ae34cd86f3abb9ba1858dd9747d006f8fa9cb6d123717c24354d7f0849a9938cebd24bb0460cffd48645aac588c34097ef222e57b9376843469632a73f364590010de31fca479c91388dfdda4986e5d2b25025f20186d92c4501f459e83e945894b0cc5cf8a0e283e56ba5be9a4296b23e1247951465322345d859bfa21345b3dbb74a5400eb5b26b6c836b14da4563b64fd0a39a5db3b7cfab5c9e0f67714b143a85f6cc4ed141234b4b1872c331d23ba6ae1d411348c4350ba55e294240e03751da52b9ba558d3b02fd2d5bcc643b4fa1087b14fd7cd55d57192328232d06d4ce2d058a4e9db87dd57673b5756c789ce9186a472924770074e72064a52f92e619f7392ca48fe499f1a610ceab0deb10fea364b7c3a4b0d4fff78cc50ef3a1e1dfda7b561f74570074662833e2bc73aff5486b10feb4195f360ec5319c6482a833658b37b8e7c57e95bd5c6622a8d795636445e4a2d85893da12c25a31f30d1af18dca63c28039d634418e81ee09f479007067a110eb0906d714d609c91a4b94daeea88dd6656b33cede238ae250a275398858c481ab0c48aa4b87d0e06b763dadce69c97d56649b25867b0068d79b759d2368f65290f95350efd701544e54fefea10eea65243b49bba0cc4dd08a6ec12feb154d2acdeb56bf509d6385953bb56076bb8ba2bb0ce1cb5c93312d5e688cac3b18375e62b954a0b6475e76ac6724b5c17e20c2f308dae8b753c9dac5f7349c768d3318a33ba2fb769675027b25836086771511faaca2bc11a3e94dae543a95da1cd524718da67a5d1543b5927c71aeda8eae3fbe66567a3c77ba91e9aeeead3c7920f2af2611c82920f25d9b252b13c1b3d9c0f7a361f17d046dfc99b0d87703e9682b8338bdb9897c50d7784b8db4eec6e36d43e440a61aeaf8fa57e4d1fdab9aae3e4a85d4fda25ad8e91ec362a75439b25afda7421d6f4bb6ae30586d197dc362fcaae804658d2edc7aeac73724c5e530244e73553578dc46c70ecd298c4b13c94f08cddce1ae966f74343db93648be06caadcc46c7850fe59c23ffc731f49471da52b204b44c7a787d59d535620ab3b5d2851e1183bc2f280b6e76d2cb6989a9cf38619109a206b23fdeaa32954b93742b77b9ae073c31b266e5f93d3c68a6e488d704bd345e2f0cf9bf250d2ae1aaccdf962fd3c34dd39b5a3fe69b55a31e3316b577ba7e9b33a9bf2a12d1b1d6b8556158b333a999f5e6a15472d8f91060f470ca3dff24f9ac06f9a4e2fff4e36555caacc67e5fb6d26a6c1327bd8f7e524a36299cdaeafaaeb88ecc086609f378c7f9ed3361667b05c6c4fbf58de9f36eca6c192fac734748cc29ea08dc6e2ae1ed27a23ab373c37319b2a46db3d69532ba0fcf3789955c321dc9d472d29c241e79f6b8f600f0e3ad087601f4b14e400977b10b09ccee96962a1aaa333eb17d03b5a3174fb5de3f098057dda10c8ea4aab33135201b51938c005aa4418c640f39f7509073e20eb920df08f25c230224314d900fffc00b01d18ff2cd900ff7cda251c28c2402f028ba00efc6389348c810e5439e8291b4bddd0d61aa6b6d4d08925a3942349d3b24a2bc7bc76cdb64c8ff77bbc618c82e412434712f87086191c1b33d5a73d6c79cd87281a31c2083b8e383b6491a63f84bb27cb63c8f25092021a790ced2841a4a11363187d9d0e783a3d1287836c1136e243304c47267158c8da90ae6ccc248e8dc598868e914e073ccb32bb7d1d49368e240e8f99cbf5af567465431aa3485ab16cb8a23e38bad96eb3e4daba191dba45502965cfacb81d8d49b9599699a469a6e1438961f46d2c6653a55d373cb75966365d88306e7c6e7abe106bfa95abb2247196a4eda411dd24edd1662c5eaa7135b2cc244e844596a2db2c43b73f042cdce684cccbc921dadd2c07e638404b7ee74a6ea95f555866126787cc8712d3d091310c3a05cbecf200a55d47edea6de3e189e5018925cfaa9a8cf559a911998e4cbebf432671688fa4e9d3998fcf143db7fb86110ad9e5aa0e998e1efea26a656392a623dd6e6372655536a4d27e947feed9707557ab1853e796b8251da3ae8b71b3dabf5975f4e8d8019d0f63143a6acc207c692cd6481dd030567124694c08dfd0e6a7f274b1161b762e36a4297b578c50c665b1ce46540eb0906dad3cc2d8e70cd660e990f5cb48bf7afa155b3ce10109cac71a0e184dbbd2fec05703731c8059dcb973377d33f4e1861294d387aba9706ce7b673dd0fd661ce71298ed3542a6ddb581dcc290ccc631e298af580dfc5e5e5af076f7f70d7ee5dab9d7c7f71d6eeb272db238843dbb67f524ec9e2cee2de594e76363a1be53dfa08e6d0f2ee31a7a58d39cca5fcc966e9467663e486c7bb76ae7aefaab6b16665fde3d56a75956a65431f545cd556579dab2bab0ab9b76e70a869f63197e08e964bfba3459eab43a66687ccfbf2cdd25b10e6f2f482bab461054194cb73da454a97ed9acb76d9995c5ce486729977b13fcaa5de86d3861faacecfd42114f5e97294cb5dbe22e35d7e76f252013bb795fa0feeaaa7b8abce5d355557d9d8aed5bbcaf2d8761eacb35d0ad869b12db533edf03c1b2d6dd7a432673da725884386f51cb992890f60b1ae9dfa7025d03dd99d81f8a7e648d9faac21ddde5a0e98b3ce9275336995fbc7de7f7497efb6edc776d6656abcaccbea43f71fdce53bab0a02952e401c36341b37173235de8d6b6dffa17d7eb3aa20d096d6df34ce86415cd6e9594ec39dcb9291a1d705e6a8181735d4e1d2b76ae8c3a53076474fbbfa3b643b8cb48ba5e5dc77f4f4ebc5867c5ffef3f96ebeecc8017d7918a790ddfe0e1e2215eb5c6dd9a63572adc66bb3c4ba91f52ba42c6ba32febc6c84d8fcdd24dec86e7c6e746e846c9cdd04dd10d13ac5718ab38a24350ba7d06c16d716d966caa6c0f5966bc751057be59ffe4047548219b2659db6639bab4b3cc246beb3a9619cb36cbac5f9a5dc23f6f692d4fbb240eff586ea9e3919f3c1cf1f064561d27ed62cd6bac879aa6e91cf54beb346d49d2e81ce938d131d231d271a27374d231d239b23256b53c4c50cad3af905b32d2af30426114a3b27ea118e87d1da37ea990bca0afaceaa5f2e5a05ae765a0ca49d0c6bcf23b643bbea347fbf9e9a79bfac5fd74e29f6ab3d438f4b97a132fad73d6793516b0c1cdda54b101d52c8b65a1b2f9d99a96f2d098a4018d21f198c9d58ad28fc6a4d46232529ba558d34a364b3320263755ee887b7234b51fcb21f9542e0a11e86f68b38474234b9a72359ba56bb3d4318a6c8c8768d258bf5a5c92b456662d0f97745bc7885b0ab7edddb6b5f7504a791bb3b27ec92ec6a8b432cb6363f236d62ff9d9f3b3312b7b4c47c749e5aab48b5b8a01a976b55e5e562ba52e3421a2c80349fd97d4ea159df04094cb0234ab45f8c839c90e0ea84556e72356478e7c45b43ae2884d627760abf3ac765dad455828091e200318c042d73162713987e42f36ec924c71c472492a23a93cab51d2fc47fee4002d0a44d46026c40d6a2ba846180bc916546de1689d3b67c3d612d961fcf325fc63838079c1ce6d7de7d29a819d6bdfed5c4b573a64fd3ad916f7ee729d6d7196ab226d176b9711e84d2cc5049d11b439c109661194e726b5259b9c6fe0a3893c0112306ef21d988f9f1e7c83f34f01b2a0820cc637f80e8c6f00732768707439feb68aa35b39ae94120cc29a8e9176c56b6f8aaeaa86ae566db1beb095b83fba735f11894977ce7844ef92618474e7a38c12614188dc2d2c12452a712398a393b85d086475b9eb1869974e0f1674be7b18a190fde8de4cee8fee3ab24e89db599d1e2657abcde47253a061844246d4837f8830514b07063a0f11c640d6c7b6a482291861c4512c06e38e491ad9b173d0c39e41c1483356baad34058d43e4f5f1d33d4aad2869642c9d499a3ec704ca40b73156ed22af68ce396367933a630730be41e51fa2221cc13e062db704aa719bc6711ab769600f5089680837c0414f4c0818ff586b7996f04f0dcad188139d102579a20538e801135188383b457041092d08c24c0a1896b8e10635c23e29a594725a1dfc98afd4568e95cf4f1b2fc7d498b76aab7beb2d1c316f3de6ad7f2c56d0d086757a4b2fe5e79c73d2cb3a15106930a8fdfcd01e235823823b78de4fdd60336ac877c63f0679686d070ec63fb3dbf219a2cc0065caf02ac32fc3656478cba30c7fa152d51956760624550580eba18d6d30ca12aab6217069f5e66ddb7078fddbb48f5b4257ab8ac3eb129cf16f1e617ac57c2b00839f660295fa152fdf950597402aed6ad463feda5e801b23e20c9637f8905e9a47ee2ecd0daf36fc7d71c36fc3d57d71c3656c48ef8b1bfee2850d9a47d006cb959191f959e856880dee8383e2f569c9d8258ce4368e4e2012958f7c5517c052172044aca1815e1a1e76482a039d91a83a5615bc48ac8e241d537428a98086364b34a624a7a04856c8ea43ba3bf33e65a9b7c1061d1bc077a6237a8f20b1011f615b482c114e626d966c6b87863150cb06df95bd810c8a60dcc41043b01d18fbd0304e21ab395de68771f1b06f001e6300fe315025e241c985f1d0c63a4a81aa069ba93f747765bb584f2969f73431506d988e0cbcb5abb593f19da94286d01b63cd00de091161c47808ded026c6c3ee726cc9d2c56e18c45dc23fab33d0ca0a69ad1e61446278602d9633d06d6bf56a7524cddc85651a3b640ca357ccdcf70761c0e25a934b4a47d234ad2a4bae1fef8b33ad6a7401a15002bc036bb878b7aa7cafb8027848633732997ac303ee90bd78f1b0616cb462e62e4e806a5b3304b037373217f52626039a3a5f1c1eb9258beaab150b14da220867018221ce58c97878dae2917178687150a95fa8f7c1272012781467a8fe87ddb5b179b8ba37378f8da3e3e6f51869f8486218fdd75b8e70ce2d451fa04a24c60d9020c11848a8a5b0c414d8d7265e5d88234d288205e19500c640313c3006b244a97f1c9b258bea395d001ea3cbc391c4d986601a79ad4ad3c86b57b48f24a6a1511161c8875b0baebc8c23ee4a05571ea60aa60937125cf96ac3ee1a952b2f63c315169a94fe4caaaa21c51af9943caa6a4bed925fd5ed03b146fefb4013833a7c350bf2b0c1806c43773b3d833bac09b4c1bd743b97ab36a8ad698518200c3c4bc088b0cf838891050c6044d50667d5d6f7785d0071bbb9cd1088eb6ddd2388a36adab669da4b575f6b650af37da7ab5cae6af90f79ed15a599b4cb0ac4e56ccbbbd6d939f34f639debce6d9b6771747ff9047358bd5b1d8625cf5ab1ac2a0a7a697facded91fa84b4eb27c43d54b3bdbc56253973694d131557751a934950d8b6c26952aa59a27953d3da5aa2795067ea93a6f523dd214d32153c7b41dd480b8200349693b56ca3b5759e465e320598fe00e9695a62bc1bf68f607f80d7c799cdaec2eefd51867cc58c3fae9f4f0e5b146b21ecafc45abdfb64f16ebe03d2fce589d6be16c38c4745b6ce8c3e5beba4b877a8c335cdef2d82ff9558ded6ab12191bf7c75971a63cdca86de5f64ce0ac349a60e91775eda1f33477de39873b2fc636d873c070457837016dbc1ee04b8276d8c35e1901bbebcb343644d38efcb6501c15a9f82a957d5784d955e02d410c87df94c0d81b82ff534aacd924d959b18df7aee33ce90e7fef2efa5da547102add7a997d2720db7a1abbdbc7cc619dc5f5e369e5b6bbc34e6fd3610e56abcf1b0c1a2a491f453b340b6a16b4fffbdbb1f8db5be2374ce68cc67a00f1b74109a80b10dce600f22b18a1238c1083663e70ea0869d076e5f460d8f53c3ee55438d0a1c6aa845b9a92108e5f66d6a0852b9fd1bb825300cb72f801835b4e186dc9210aea961ca861a6a68030d358c5274e0e688db77d5196aa845b9a18d6954dcd0c6b60fdcd0c684303fc6b6f876936ea29b60e186373d51bc40938f30b6416d492b44b33d3e2a603ceb61805892241807d913893d0674f351018b306e52234c3e71ae411d8269508760180f47eda2a20b71e5c604db2d67435727351b06715397456eeae7a7c58d3d2062820484a5d89c53090832a57324759ce818ddf4c4802a40872cda968dbe9a4c3b8b56bbb3ae5dde6ea5ea56ab6ea5ea8e749ce83cb14bf8c79337823b8a989b65196251d2012aef62797892d2a142449a3e08964c20fbe9b99ad2116a4cf9a425df923265a90c4cc552b01a4bc16c8fa471a15daafb97aa6c7deec64324e30d399624eab1bed555eaabaaaa61ea0dd6589d2312ba2e6eec0151ec6e56f290ba96aa4c672773cc649145169ff587ce217fb4b86f8ff707be9cc5b1d950b3dde76f8eec860491b919d8b91690e73be796055d9d35e7e4780cf150c2639604aafa80ecf8c0806a3fe4e3e52930a0de6d966e8cf04d6ae1e8e657aa33d8752e5d8caba2aadcd217647757dd6599e5906f27f1b6511bf5600910702cf4e948ea2c91f6d141c630fe69f53803599e210e00e31f2b6318510f9ff0a607e8e746a673a4e3a4074c946e24c28d3d60f2733f366dda4ce6733919a54268b3e4d939270f4f7840da5e409fb03829255787681d9346495394e46c49fac81e298b473d2529cafc7515f54c4aa93425c968024d7296a2d20f50d0ecca735065a0ca711c27e79cddb71aafb7d4c9eefcaa06e1ee26e34e1bdeb8f2713ea72798a3481659647174a50522e36a524a1ddc65dc69c3b93d4702917135f609aa9fcf19e820f701dadae13eee837dce41b688cd528c560cd91e84a1883b2f9940e365a03390dd219334dc072813689434619ca2c7d53be6a54d15511d52744ca1991cf7db734e2520f440892b925886a4b4e10ba8f69065c6326b57c7c3326398cd12b7a4c9b8b386dd52d751ba5a9deb68b7a25fb96eb324a38b7192d6dd256818a13042d281a213258a249d2b749274a45831d39902c536432071cad53edfd7e9d121eb57d4314547d6af903b106f07b11c51ca0d6d965871c60f6931202f8740ba51ca8c28e5e84928a95c1e90fa48ca7f9b1154fb7cf7635a1eb8a5c855d9be4097a49433295cd95d9ffa53ac7f3af5c893cf69d63f0df5a9e8f6acdef4dcdcc4248dcd528cd21b7bc004041de50709e96adc7c22e3362024710d6a84310dec1334b4311e90341e33490314f4f323e413e433131af2f109a23cde1431b81ffb743f404488ecc89894c918b7c42d75b1fb28c2403eb608518fd6143affd8a09ed24a3e3da5a704cd299ba53539e8fc22adc93f3f2f42346d8f1729e263ad4cd23468634a68bc96894a8451a0032833a84468980263a17ff34646935c4ab915b54b3641228d8ae69cb36dce09d43263b61204ea048d4e60220a15b8f033ab1fd88131923350fdc00eb8c30ecc038ce47c645639e8e73a463cfb0eac77e8c149ce40960891b43df888d60e3fdcf9e744829ee47c446b9e93f80eac07233927f93c27b14488a6ed7104c9ce9c531e49a423474757d334242c4fdb983dc21eb90f9e9d8fb045f8e7882d42c4d91e458092209149b32aa7489abe4ce231933845f8e745887af08f6dedd092ad1e3c3b03bd0807d996b43d9004854b62920a8c67f721f3c40cd68102f018c182684182f1cc4e1f49235b9060532697a098b2db05e03182ed90c51aa11a846b0830fee91f106189113006ba4661346b793c2ec1103e8811f9a6fc8f69adccc6b6f783687185182051838861095418c1f887a89b441d373f2f47b4ddab4a3f548c705b11e80feddf0f30c584c676c9faa3935f9bb48dc11a29269493d766c9a60ae7d5d6b496c7c6a2503b7b866e943b647106f398b5e4d9e751e2481f4d4a99e683962436831a615f775fb77f1393380ce493e4483e7f0489ef08f1cc1221d26c0f9ef1cf7996c48920f19da176cd2224aaa6699aa6513ec2f274ec7cc4b6b473128f12a7a5d9d60ef7c1479c93b0458a1cf122b6a53dc2f8c8236cdba4d0343aa2cea323354a9abeb68469349342763e7e807dec8c72fb1c645bda3fc040b6b5d9196526499a96665b3e5ab0600405c63ff7810523213ce81c6489f830821d2801cb696662464962a54562676bfea635ad0e3630cd09d45a4d8a7482c6a04e2519d4b94141c3a91483f5212ab10c6a84710c6a84c1a0484ab9b1264b5ef99ba21b26ed1a8a352d37202ab70fd0f91dac4fdbd2623c5a6cceb9d9398deeb6ddca94cec5ecf4dca814630d90a8743110956eb8fd8777eeb3fe6dfa22a8e3fddb11d4a64a9c316f86be8ef26c475828ba3c665c121ad2d8015ad286ad1c7c5bfe9d53ecd329cfea2cb536ac7f138b336472a925d784a22b9ed0e00b3300821498e9763c1127c21a867eba5c82355297a00edf95d609e0b67648e2acc47d309333d17da21cb15a949fa0ca423e41498eb4a39fa328b7df3e67a1f7e099f61e2ce4336566b52549d33f49965ef988cf73e4d7260de4c1c76a3e49540e3a33a90c24743e52f9e7ac44659f3351e5238fe0b43af0b090cc6a32d593beea89cfed4bb035df837f36b035ed0e3c9bd9f76024561b92342a28e8598933d1434da86a4d244d931d228c87832c079d812c27b90a0aca499c993cd49aa0ae030ffb9c8f20a945822a11a2244149ce4704cd848490ccde8385ce48ce470859229c24681624932df1826f809790052d717e414bbbac61fc33840160fc7359c318e85ad5818708f321610c7416aa457c2a11a2239608cf100780b1cf650ce32367246c0b4644c630f6796bd622443df808db9ae7231e612cf422ad695b3b20710e7a0f3e02094b84a807039d8fb044f8c819e844d8e7fcf31c0954371f49d3aa1fd020310c37033b77498b8708e3a0138946b00db0d037000b371f1f0e3a0b1da911c62f803112bb152d515bd36e433cb39ca44698b604ba0da954098834f30388302628f3626974351220e644d77c4bad4074cda36a0f44b563525742d5d534f3ac44e524aa8c7a981a7646c2ae887055391b6bd7762ea5049d361693884a97c63a1ba39bd3374549d0983c8b5d508930094470051aac60c6829f25aed5be403f1eaabce4ec82ca2d480d71ca05944f637146ad4fa8040c54b7c11e854cd18c000100f313003030140c8784e22199542a6989413f14800c93ac5e7c4c17a7490c53c8186308000000000000000008906c0040c8b2a3ce812d9d96f4b2e3ac2fc30508e6006600f1870a7f4524ce961329c694aec06441751e77781d39cb57af968e7eaaed93be212e577ef8ce34e6562d22e4724029eb82ea42b85e3fffa5a4e3058d9702480aef3980f29571ffe691b36c19d09ee52259a1ce52d7851cda86c3c1ba348599c7c9c50c28a7fa99ebd83f934bbd345e0fce5907754c19fcbc6635a6b40a3de49e21011dc6607a30ef5b30da3c4a24d0719c8714828ca88a317593b738f8080a8876aa7a34914719a4e24e85c55b83bac8fbdb6616fb5657a661be2e8a418305e8b292c0a25b2da0b268c45514d824bc382a03893bb4c1086c87ca21c2227dcd929f7e1e848730fa8bfc11fa083a666521fd6543ce22a7d1e87f44519a37275541738ef0b782ca6acac3ff55ae4fe39f87b164638448a6126e782e6a1ddeeb338c0486cc611973b103a6c4a48ca9d850a5f1fac4fd0acfe22f4d05f1b8fce1114e17fc8a7e57431e04932b11c7852c920fc7f7a9d861b1156f92bb163097761831add1450850710ea90cfc24b214f1bbef98767b8aef0a034d3b341212752973f6e700dd954aaed94b75cff26c597b4839d6015f99533158fce8c377002654e12a1ae31ef14b222c378937b9399e7b315e5a0560abe03e2ba3ca10f1f54462058aa34746778c980e6a4bd44d1d57f0e8c7854a3d205876b2014756fb07d62f95673e0269299862b8d25b8e25d767eb3c2877a2963b03ac6d459f81428b783b2b33f2054e4f3e8e75d29cda6ead9f43cce411e4114df92798c116820779a97010c9cc4e5f102a809f60ff1e5ce4818ed9698aa6226e25caac16449007fa2b295024bf2abca8e0ffdd78e3e7ee5d3a0796d4b31d4de12625a97eecaf3423d49df12c97a4443dc396f4242aa45405ec1dc76a30b086d2f6c2d1d491ed27a5006b2b885915255535a955f7be4aa49118f63073d1a8b550868acf3996537d07b17a2130d483c1c0f28ca230cc47c065576b6cab06bccc08113e00ff42b1da0f875728fff342e2e2704f74613f0b97f510a70d25499a77f6f850b5995ec569357a7e83f4ac8a7e6a62093413a06eb8999fe6feeb368df91fcc76b00e76c9572c1e4ef4d3fa89b194a18fd637dde2651735345eb388a987ae8b2cb65c045fe473754fba915628b1656a8d38a484588c9691e9483b07ca496a9e0d5a6ea532c58a2f5f33cae70ce42dd3c0237ba1ba699b13dddd9079d98206d0a6b75380e048f80ac498fc60e4a8abfe2a8c02efb914b68c9b4eaf60350f8a757a8b9e3c01be32888f0424792a72907db6ce0a240b062d41aa3fac66bd27a7f5a7cf46a67023d1df70f07936d1fa7fdaf2f93ec39622d4f5396639570230536d9fc525c499101e80ba33a2dc591ff6fddfc32f76fc72a27041d28719d1d14501ed335b7f17dafc4dad9c280b28c5e14e9a25f6b7aa3600c0a3dc4a0dd68f80cd0540b7b9e5d2468bf06c5ed12ccdb4c95433d9ae1d8f63863309d338a4e5115f623ae253dffd48df5987e2257bb2e9460982f508cd249837fd70fd3d5344b691de42ad3b3a2cb08746b4c031cf3015cfe673542b8feca4eb0ac529384bd967559dbac1ae9f3881f97655c96997993a9aaed4109bd086beb2b0ece04ff98be5b037fe2871247ca3bcdb23b875a0b74c2461a2ec955bc94186ccafb1841e5f159902a5789602177bb313e6d49b1f924ffebf0b8dbd279ff21790c375b6bd464f313ed8600a84840dfc8d9be0e414e5186f43e236739d6090cdd71b06138d55ac78073e41fa60531cba2c6f8df52fdbb8a2d38c348ece352f543f048ed0a783ca2053e578f8e71b00cba43744971d410eab33345e57d10ea4f3e906fe27075dce27c77849baee5b0ef5b6d861297c0262476250db1a736ac9758e96acc5fbd739afc2bc879d6a4c53928323a8c818856e4938cd2454ab789c1206626d0de1f346eed57ca8423cfc325cd54679c0f8856efbc9bb0fdc00cef0d7fc933c4a9780ada1e3f004f4d45b7bf520784218d91a15c404d6cf772b579af79eb91b8ecfb6f6afd4bed6c9987281dd8d37a11905109a23274ee85b2a9cdec238bc5885a74512f2245027c5941bd9039110a556049bc9a9534cd3d4475f9c6905cb8e6e97ce8c2d2d323633760e50c3dcfeb0df30e9caeee40ac8d325d9ed7f525cdee220522d0840aa8ba673cbf0f9f0272d873f69fe6b6d9647b2461961740960bb2b61bb50ab02f3d8871294d6cbd84bfaa7a3e616b23093faa16d1ee689b11035974812172afbc6765c7f9496825203295092c6de5cf53f2e9d082d138f0f7f3995381e0bcf89bd5aa986b5d9161b4032dbcf0f142c51a84283a88d8bec47bd4c734ba55b09a13dc7b7a330d5f0d560a1a63420b3687dac6f26508dce300713ac000b1458ac742b7f98771b8a86003ddf3936adca4375218b51a9b9f70146688e73619b679b9c34f25febc0384d109c4ae9f3ed175e28703151d0d526a5e9a7002839b9ba48c37635b6294dfa62befa88c36cb173c11a6b1d25e7c0d60b1d19ffafab397520660eda42af2f6230676db71dedf85e427b7dc8025c5c68dc26dd1e96802b7e8ccc615fd7c489ce1ef6e08d7cee810d89f9738367072e640aa8d7944f51dbf00979e1ac9533aad0747bb88d6a3eb47d0bb4a28dc8725aae5fc77a70485e070196a30138a543094381dd46fdfb337757afd5722adb6299c54a67ae22b80c934c93d851ec5143e23fa3771cc124b43749a448fb31d59040e4b001d6b6de21f50e2d5690065914806ef13c7efd901362e40aa672ea08250082751351c427aeac05e6675746809ce344995747a0692f7e22e991bdbfe693ea921ba5ff9f89a719e8a783169c5010f900eadc473a291ff2289e9fe604bf3ae8ef3541aa2e09e5231b80d6abc96b2ff335ad6160d335832f192fd1891e80cce471ad62ae5344da540dadd6f43a4d53881ada5f720afab888743402f48a9f22d2d658a38c42e7aa0f86aabf4f3d692222d1dacef45ae182d2dc87ca60553fa4d9696e4856b2ddcbd1ea3404c3255f83f57eb90a7f8e50f6cb47bf864394c4fe8ba96f00f72bf21eb424ba0125115e4a6604f99da663b458523705c0e4f058476524a095e706ae699c82e1b82fdf4f7196a801d720eeb9654082ca1f52f1908b2e188a161adaa73402df5aff1cf820234e22c251925bafc5c6f86193adf10f90c3559bf4e2f9beff7a7fa615c262fda0b8abf2c4a2f221e583dd2853b73185efba3f3f453c16992ed66b6041bf9cc8acf8511a523461753a3ce70f4a0333e27e87691752484ae98aef0e4fbd0fed219936bf03846da7f82ba581ce0599e5a097f443cb009563410a957b1975e3e23bace715d0d39d09f90b41cad6b2e9fbaef3fcd80451ea24be909739897cf288b860d3e448f8eb26fcccdf8d28248d72bcdcf72bed7adb28058691701e4d296e2c9b6e070facf9c19294ccd036dc5675dbc1f1c2d6ae6917f328e2295e6647b7c38cb50e8a617ae129bd544ebcecae84ea589b9b53d9a7dd4f3b281d14ef271dd2f13fc9d38c456eae8e5022878331c3ce9a795dcb3c8ada7991839e567261b20a0f6eb294eb35ae1b37beda0970fc4bbfa5b4d751a7874257a09aa85531915fb08c790d961a7313e7999c59ca78bf71a0473de54ef1ef25f2bdc23b7fdbe8df827914dadbe1eeeb2ba9c3629237eb1392475bc45f3204dc5355e5b87c21d76f51849d0aa285dbc34410ef0b651ee1819c98398da5b358fdde5f729b084f7b722da9c8525e1450edd3f733449234550cfab2a40886198fe7504705ffea9c6ad8e577fbbdd754a337a5822265fa918ecd8d8316b9af7dccf25989f76afd27207580616fd1a28fd0112893e8995533b42cd52c9c53f38c45e0f92eb4ca43b7bf242fd1980c7a6daa20c8fd9439c0f2432ab3992ca170c1cfbebbfbf5cde38ead814c9b25a1b9a7ebebf821a46fd7343f776af566bed2183cb5c49eb22317bc491a6e782c3f108a72c54ac94e56bbb04a2a812a50df1343c706e29ce2b123d5f23c338422d71e800609de7d1c6abc209293e6357720f1826995c85b213defdf6254e75fbd25b20c4067e5d22f3dd83ab594247197371461b03bdac19cb1a46643bc1f815b925a10b096214743173ddbd05b1dafade7b8fc04108d4d1b027c667e88ff6734599c7b38070c4cb74b156d8a855e9a136596663db5deaa2df774966eececf36c1d744d61954abe371dcf323e40b7bed31088d7f80db738f9df5d2288ee0006fcf8f266a150044663ee07c6db2c72abdf93268824ec73522435348a52893cfb7ef562cab219a45832e08e136ce54e60779e5a9f5d0f9479e5bbb576e60a4bf5cc66a7684a2ff486157be0b92ac58658ace1cc05e1b48962ee05c68ac4b65d24b269d1d8330e3a137a710831d42961f84c30ae376659876599da552ec8e33e59754c04ff32e57436b9e848ad9ae399125b5392fb1cb881c21be339622dd730041d5b5176599aabe82abe66d25f49185fc253b95636af204e683f7b916e317854af07ba792d00f59e2f303138529e6eb5fadc2eb0fac3b90510909a91b65077f579e14fc05276f06586ae87f49466b096d794be6ad48eae45333164c91162e12c3d25e87bcde0fa9264e0ae8dc0dfcd43dad1307cc602f66abd40e324291761f51a7486e4e4bd75d79f9d6e9351e0f4176b752c0b732de39ce588dd31a621ee8afa3333ab91f0f44ba1d9fe1469c8c0b5944955a0ba2849755ab6b291f0341e9724f6088d3e6ac0d42d16fa3ae19cc318b09aea73bd555dde7aa34e619e1619539442ae3369207088f5a019d6a2e821c4aec80c753697eb0ffba096d657384a6bfdb8d29290a25199cbe5297e08fb4a5e7cfc42783a08ef8bee38786bcec0d4ad11b026053fe06e7d214c7410f1bc7e6c389d9387fc37e2428ace2235114805225615ee6f17763d470c5a183bd68c9ba5e1b6dabc7b47d8293f4295c50ad8ada026b969ce2666ff7101ed0815be9b0f72ac76d85bd69fbe1bb74459939fb0ee2fa80ca3244dc4f3cfa4be2b0533e7aff5674513212a1428420a456c01da017df95bade20c10da1e248dba3fe1c6e783cb2b87a1065a7e047048d7022fda1545f0e4543c35373d217a38f1c325eeea543a50c3c2c5e5081748ff896e6dbb06061277ea63ad4637015d8da4556ffdca82f693433e059cca70b8d8014348b3b63a3422ea3cf439e84ad34a746eb255d5d3364b95554840a04c4060437310da2b2480daa0cceef2cdbbfc8f93330965f22382ebcf2d0fe38a02059ec51237e420d773e563131d22d06989715451f770cd990736edf51a282df7553accf54c3cd8118968ffc00afcb1c39d580cc9c3d8ad723377132cca661e26d830459d48921612ec41b297898f917ea24946fcf012dad5c733e2dd60d6e9e77ed257277d0b460f64820d1e223ff74a4f568a3529b2030e9617137dcc221ddd023c7eaa92a380eadd7dd15863d712999459324f1c9aee1ba1d0966cdc36ba133f1fd7378e9385a303c1ffe47718630dbaf41ebc82ca73ae7f7c5ee7aa2b040d8cca0035da17d9cd35135a25446ae4268221ab5fb6dfe7e436ca8cd593fc1524724f4246ceed07d6ddbaae591de6a2a4ad452d43e5d2456f53d5c6ad370b3fc6d802190c887aca85f69a0a7a4c4b3af5226071c0b44729ee848290ddbc5e798d2aae7c18a07a83299eb1e921c1c738587f9f9043c106c16a87c457c1efd461739829cf723044e06ba58163ef9ab00459b99d338f06cd97ac962399a3faf4b5d082ee60cce750500cf31ca413a36df1d34afcf29302957280c1ac4e47278f8ef6ee218ca0f68c16e3a7a8a1971663c9f8b9a8cfc07fea813512f1e6f83ce7d08d3bdb77b87b73c4e2fd740fa003d9df081e207bd96fc5b86ec2fe7517078528e3e9c1d51d59038469e7a395564016a465ce6cdb80068b2c256bfc0c7976512eae68cb61f38327cbb3f127b29f0a7d81faabaee9818a63ff5860df046eb6557f7788040521ecc0960e4bce20fa09698460baaec877896212bb718e60c310426708c0422ca1d424f3b1ede4f82e4c6a5887b8dcc0d910627ae09866bc0969d8b668dd608ec883c6d566bde210173b63798679d82badb451fff360b37816f608f404fa1fe41bac76b8d5422300122adbcafa67f87f6cb974bd62491fb8e4fc00d670bed73057812ce1f12aedad6bad18c03df697138be95934a16182c37c1f51b8a4495372ca27cacac0ccc710a729258c808642181b7993f22fe445185cf158375a2a19c73c2ddea3ef6d789e4dd7af18650d316c6ff88f0411822c5818696ec18983186249d66fed72e0e492d980f38f13b5e25f0d1b3adef5fe7bc6f434509fde585170499ef0861faced05572f89d8cc7b45989c3578773dde218cf91a39d6710dfde9bbedc1482e760a91a8f0fe3f3c806dfbfc6f81a859045d374bb0ac60077aa97a58cb499b7a7e600da6c08ee7850a8b9b76de761434d8709ab92c05360ca130772b206eb388cbc082ed160a8aba487628dc410116adfe626f179388229a623b3bbaeae9270b10b6b4328f154a08340fcc0275096bbcdf0d081c5f617228d18330f6693a04d68f8616949f85d2914f3f34fb7e81fc2fc192ad2722ad359e23447258bfe0c1158d8e28779c21414f6008e122237db6830b134498134d3d92bf52ded2b7b9becc88157c9db697fba1347a7af91331629871b0d8746acaa6119a135a1a5b9c807b97658851a298fad3a9680fce101e576dc134fc4fcafb2aac2baff3d41a5b22ddc477843721f4c2114e48c89aed60f60746d4d4f727c844448be068e619840627d688b5bf02ecaf37e12e47bf813d967b570220eaf80f9b932093c301b9c2904c17dbf9edb7dcd54c988ed02eb3ee96ee74e4ea36625992fc3358f9931c34f1785e67814ff448439789f78bb81fd161d044cdde09f6a7cc662e7ad1c6e1503d629452834d06184a478eafab26b5f95d1789d3779b974447bf53c53bc879cdac5991cd2c1e402493467c8cec06f7f9c79519daaaa3e5681d12e0626b1fd433f3f7b95bd2e29eb2a7f76ed182e7083e7d567e3810d1faaf10ad57aca562a55eb84912ffcaa909971a127b1e7e1a4769c4c7ae739672fd4f20931658b49dcd40be773db5eb429560648d84e674cc5773d61d2bd7876f4e3bb485d7980af49f3a4c17115397a393e1c941b4d80a147fac8465773f41364151828e499016b9f49d3b0e60d56f6bcbdca324f7d50a698c4c42d3aa7ea3f1c1e945569d6740b09f1a09d1c850f378bd41eceec29efabda28d9ef4ac2baf39a58071ea9c3ac29493b67d6566fe174030ae6509b641d74f8b6b543fbf8805658dbba8a9ce6d361c011f2f78a975b3565af9ac1e61370d776b81bdae2a6258d54e91dc73661261b97c846dc89c60de9fb74bd1aa3e5b61c7f1b35398355df4bdd97a84c60f1c6314e6b0f627598e2cefe03d793abe64466f6af950c8aa1562fa551270b4be9efa4ede9fc1f644e1f0fb8501df40bdee88f850c4ad0e51f13f1a5992ec5a4f1b5c809d089a782113594d506cee3b29f1e2a6021de677d45071700c81d2a76933b841e15e19beae41820e72a6af5e872b48fee6c4cbf26a0ceec4fab8d3241612361602658d34565e1d1a02e9a707e142cceb14e2e01209a3c65327104eeb2b5cd721dd7f0606109a435abbf06e767ca409a9d8b9e782aa5fe0ff33213e4e9ce802b8d385fcedf1bf81d11989c79e8015081d1ee2aa19cc047c2e68ac81a4b2cff3b8d067520318d9fc7866d9eb6e641abf2f23bbab04eee7e192fca01b5e0d121b32d2296a8e93b509cefce74e56905cfd222a3d4bbec2174a3ee021e6449c3a59204b4dbd05c8d6265a955cfa2f703d0905905e2f6007a0e325f6193b88c33053ca7e9987ccb92de60936bcb945cf0cf82e80bc5b5dc9632a754833743eb4d2da165b7270bc404096c6135e32035c6d16a1ff82907f4dbaae3c38c6b719a294bdc08ab1943fa7aed911bcf005f2d3ff4f0e063d53cd83f6b140965b3478ff5ba3babe8123acd65c07b60993820e13b7a3428255c269f69080da35a163252d8fa82f9c776fe00726264e3dd7f183e3cc765cecfb29a696270b5ca98490f16aa09442b98404bda2cd5cec88fae42a739e38b3c08785c1dbc832e19993da42a3300f2ee4a0a08f802be55c7708b6a5abaeb405f32285e964deacc5d319a8999ab01e9f6e61a951993810f1b8d48f00bf9b66973d21f42d5847b03313be30e7662d5be1e597a3983e557af5975477a5e99bdaf2c2cee9ef68e1c21b3fad4a993d76fa03ab75464301bb00002eaa5f5707366c1fbb9c52e20c560d112a8c6cb231f9bbe9271b8270ce2796506367a19e42583b6cb4925cec2ac2d31ce7be33c44a36df530a24b6a2b9fc2834010c517dad905548f38b441850f94a7ed0bdc9e9552c8d9853c30649e208fe7375d7bd4ae27f98eb3b3511cfb0e70cba329b12a4480ed24c1aad955b4a6bd3b4593879142a6908984d327f74f7cb06df2cb49359a9c0e0c4d57d744da330e5a2db7e3056a7e111061d638290252e687495c9be3c5acb6d193b3856d5fd56356c11a9187500e9a8baacf7284e83cb86d6f973a310f3e7319cb2f92ec5b079bd80a4968bdeb93fa252731141168ea2c651be59e87007ce6799e2431e9aa4d7ec958b49ae95b46fdc9c33d894bb965dc93fa2b6829390070c0594bdec7ead5f2b2caddf4e4e6496b780c6d30139fa37884b859571e58cbae26a3cc06a7bed15ee2b3cdffb1e86de821bed6f309c0e8d2b256e794c5a2275341727fd5c57ca573f8d0c89d98ca3c37241519d282b28eb2012a4093877a3f15a6b3e0eb0f6e0a92c4a5be65d5fe5990669c57fb1cd4bd104ad973a31ea005569c5390c399904eb6fc435a0d6b7e6ea8cdd95fc3f54e4e0ba63e0ccae4e1f51ce4c35ee552cb6769ee833dcbd965fa56a5c72e39e8be62f7b830cd38d72d8591db7cd1280c89471926167bd38310186300e15bb8893ea188cbd834c4ae8898cb20bf60fd300a2f76b9356cf4e1b69b70ab039ace7a98a67121f871cac68250c0a86db4f08aab8f2c6663f978148a52af7d1e7d56a09a7b4823e21371192188f47a81a3764d2574674883813c396974b1f6d0df4c7264c2633ed69cd7b2164f6dd8f885c503a1fa6b765750abc49ca8ca320a512eb84f48b5e5fb9d6c9509368c7b8538d8b7fe74202e4abcd38ea7f5aed4f3c6dae8c0ce76c23e04d5282d23803135368499b75b503be359c04d6326023730a913ee1cfc8987af6c86dd25b985a66657e3fe4b13bd3a7d66b982691e47a0a8d03cd80056bf6eab8b393ee1bca6fee58a95da4e1c137ebc6c0972aa2f4c9573d6212058d086830d966dc1f63658b882f121c05e6f277b78ee8f15318d3259e7e5139c023740325222200cc3c8c208b03fb5736f1dacc65abe8f849443872a92f249ae4ba4b8c3830d9d50994004f74a11766c74375531bb74e5de376c109fe4fd479fb90adebe29276cfd24d4a3ac675c91b0ac1a0b920a5ebad5ddd2e1d605bdf0a3e3db7046922ba9aeac86c52b156458dedea5a2a3b2907b3e23459adc85bf034e7fc7b9a658a75c35fe6b2b8bf39fabe7f7f276547067ae12a4bc81862d7409616f212b6bd117a8592951478f7d367a0a8f731dad701951d9caf9b98d59f0894d23c836971691ac743da8b0fe3d2c36e51c0e1cfeb8631fca55a1cdf6184755d0acf9a2d8b1e3246e92bbcf18c2d888fcffd0e09777939b513520cace7276a781c9933b08cf6f3c1cd7b7209c40cf0e75b52a2fd12322829ef27d563bab533c75ec4366def312ea6a0dba0240ea64d01de8b585cb6812e38a0dc205d0cb0696d62055a45c72db4a566359288b6c73fcf74544490461044b416644aa1644d74b037eb6f5ee8cc0ea190375ab0c630377d6afba083950298e45e5a99f080ac07610e4ea305db8020950dfa4633a8cd67bff1eab99f84ff65a90d772b8c8778ae9a25dcb92bcabec91cbd2663af56a14cd885383610a0aef1f51d51a15b081d3bbeb6b14a99ab46e75bbf05f9f9eeba5965fdf35bc3686bde74a53918c2c757f894532aee5ffb99c5b34e803858d2f539ddd0cd237650af83a125f65a2902de226384117e902e6127854a9b720d088bce20f3628cbae86b08ddfae08a73fbe92ba5f712f004aa58ae71d82b0804aa66158660a311166267aa7b89e652e1bc7e725f39a851fc960ed4680d930ddd2af7c86449088ac76de749ecfaf3c18d81c8c6711c5babc2126becf5f41231444a5b957700c516b44c324886bc1f156ec1703e5f8fab35d1e35c341cb7955db2b6957aaf8c0d8ca91952353f74a4eeba59f7ff6091d10bbd9bfc32366341fd5fe68bce2e55067a8ef9a629bcac1a480383740baba92345e3ca939a920f81d765a469340527c9abb24a4fd490bd2a0ef7bf16f46a10a4d1e9b138be128d8818e4200fd440ed797eaed81856fb1c4822fd8b1e1d8d4a99bfe4318060e551330d5ca43b54c347fbdd74222f08795cdc024587da0da1208f91e98c4fbf81dc2480d2730952aaffb11cd2b887fb4b8393b8750729d6f4a4d16708df423189bd4cee530b95f45f2a3eb524f2239b721b6b7f6d05a4c164f906696848f6fc87083d60f30a53e01d9829b8c5361b66fda9c424e124e0d0691b19345b907295ec9f047f3e4a63d8e715f15abae031cdc20c72cfb94b0dd5e3274a70620595403611b6ea79054ed7cc191175f4fb1d068f8beb7f06f82949c12175ee0b0fb2c3701d015f063f8bd49358eec8d141ff473fdad586a8f6692a3fae6893f258382c49d6f51a8d2b573db5ec4a0d1f73e3ebafd60cb376e773855bfcb23937ca5950343c1e19ed47f5fdf7244d7c7252c89be4ff6e6eecad0810d047309588a2a109986d1da6001aa43333829ba13b658216608f8f7db91426674ca1b25e11a5ec834b885d9b36811ade3ce8fe7aec3fe2aca6f8e66f24408f22892cc01463fb793740198394787c75f6f4f742a220c05df78febd2cec8e400e31c2a164086dfe424aeaf92a1fbf1838fd593b914d0fd46b1156a492550ca85bb3df08c934bd84ea0d50f307d974bced043f398d516d838f6f18e73bc274eb20aa0347a37d1da2716e1c28f46fb115ca0af57d964dc9027087fa52a43ad0b36cd793cc668d7997c19a9d23406f4d25d43d3f29679579e768fe3504d1b1e0d96523c83748891613023ef335411a944206b5fad478a892d51e0106f8fa4994155a8b77c03c7ae1b3d7c486b8367f54b2147c0dbfb5c9e0ab894eb36d0ac850c01dddc2d86b6d7ef0fdd8327dee1f380fbfe98e9fd5e2f688d81468177702c09c1210ba0e378d1ff094b1e20b547204a623849cf64686f91e8792731c0c80abd19cb7027be79bca06201560ab5df22e86b1743d5201e67e3044b140d9eb79fe815c94aa8ce5b3ccd2a564cd3cb429bf0d29b93aa975e7b4e568b92b0ea3e38f50221dd753f1b987b78b05bca2c851d7469d5f6698aa01780126536e38529fb28b44385f2855a340cab6fe9730aae4ed54a914337a5c9df2bdbbb6609e431ea59d5d2e946207fe38882c38c3e9d7d6313ab8bb2d351cc4d97121e667b6d40fe182e1d533d09b90a96944adfe0388847ac3dc2e688ac0221915a6002afd56912989236bd8019a384761edcccaf562832811003db3652c19d65490425c0e46279b8d5ac256a9be5a0d85f8dc3e5949f9062b8ef4fc649f7f6abdc6dd95abed7e4555ea39897d868c3e0a2fe2bcadec808e0a19182fe26c7fe43203a2c128e0b3bcf775d2aba0a02c19ad57bfed936840a0ae96cd284eaefdaa2e25a3cd0417b691ded86e4ede4b2308a4a6d0757bc8f24a69e002a1c36a471534368b4a7ef4a9e2356e0153a88d8ff401f22d758f18aa8b36e231fbf83c2ce6ba88d3b3018539911155ee1677d6aee28c01d65912e57d65bbb18162f0d948204a5256603239a97ca2cee6e7af641045d6ac0dc397144c0b1e13ca1d9d5c31c6ef843ee9944fef0cf789860522e5b84e3ac49e00ca853b5c9e521464d5597df22530c24b1cfe86bb5f53eb94f1161ef147ac915bd0ad54f2acefdddebf0c972ddfc8952f699b2bfd1e3359e3b29c79c73ff3756d075d51561bee3b6c29e03871160a3b3d631d46223cc236cd28396aca6dd24da35003c141ce3347551913aa952f17e65b149c95c311420c50c04296279283089c13b886332496abd6e70461f400ed122abb5a53bbeb424516c98a276973529e82b880ad75c4d93cd14115ca553ac59ef2414e527df374885e8989f8283d36a9a42e3c3ce62a511e132922905ffc6ae699cdd7a9c217bb1cacadd65bf555cea1734d8e7362b8a47d7aa78e9004089c4c381c35920e08fa9e69affef8422caccfb6d163e4d41082a65bedc788dbb29f63eaf823cf45d584aae62627beb6968d2848bed8fbae320437d4137f9ea4548be152e7e3f8627319ffc5a3606c446b49b3c486c34aa78de099f7c353b530fcd5acaed47b12c2a80f76075b711f2c71053ea154fb1f6de2db7bf946badd81b8af4358812fbfbe0f8458d4d39185456145b9f38994707577b8b4eff07e3a59b36692ba0856d9a7dad5870b4ca0e1fa7680a1602767bd4c4c57058950beb714553d36ff1841dd3efb86e455ed101003e1ab622e52cf2192f2f3a136d46e6e52eebc8b475568b7dcebe295d7e951ed117ec7705dbd611edda7ef6f3a08ff95ae3d87f10cd3dda31930bb9402e8e217bb614762360d11fdda75255a651029c09a634c6c2bf02e4cde91d8022e307b8198157b226fccaf8be28ad2a967cf7798deaa41a3e59f82fa7280c2667add2141600752f6d203ef24925c6747f51086f401b2bb4b1b4ade721f65a36b8adc6e13ecbfa792c566d9e5403eeccbad3ee49e5b4044a5b354739a8562c974160a3c3687884087050fbf476ce280965b6a48aa60445200945385df5d4e639f81f05469104476572f3117184e9f368be2a88894484732c19a749b01369e45e20f4176022361c412e7a9404be22028636bd20a81feb00eddf0aa756ec875e7b4ea6fc68d0962e5d10fd1428305e6cf42323081a1fb698b0879a002c2ea765583e3e59161c40660410ac62096734efc1c97884d368efed648be47f18d4348ab1221b5637339aa925d9d696f8206c54aa3d844b94b3447732d6402f150ab1ef415a6d0b1d0999530b4c111fe119f76ee76295f9b88481688f6522272874e8796855d91ed29d28485c18c0a16a9fe0810e0a1ad43e4d2d128fa3c3bbf45b1b9cd619b270195742a642ed36c429fa99a6dac2bc834d5c7ffcd5a4a5a91d18674c9e343b576980d04d985eebbb6ddea0b0acab1946e4060907e6c47f0c900a8af63a3fbbcda38172c9898d80c0f8df7e40f4ba33e04f5820333f354e074874bdd13d440984291f846ecea999c2912dc692d652e7723887a531fdc4efbd2b9eaf96ef66dd92887a897b4ab71c08992fcb119b7435cb948ef473613807f067d595774f0b58293aff6a341029c146b1973d47cc0c47c5025df6c5255c04dacdde73f9a5fdee8f1d7d1dd473bfc36285166888e5370d669779210904aef81c3cb5a236dd8b9f001c0f1ff4e93430af0fe1164d5abdac2bce509ac289de25781bcab6a33545a2facf9d41cdaba5cc1d18de5d2b95c7583fa6c9cf16d7f5fefc184f3fb66179c3f1b7acc6d53fa37233c2e4117116c35a41aa7ffa85a3860188c07aaaeb98d6d64cc799941385b674aef5e9cedcd503cea9acee6e1461f7cc062120bf6514696d3defbf4eb2ee233814f1645546b3a3ab4fa0932463584d5aa74e318ec7a36395117d69ce115f8508406004584744a3e9821e51aa0d612a4868906348e14d0a0b31e664b56248b893a233982c83e392a9462c5897f8566f2909bf5c9020017cd195316193939a771e3bcdefc8cb0eb0d007c5e204b4cc7f5828980867b4ab4f304c76c48566582489d01a73e04265c82d79e4c728985728103f673bc76f9760869271f75d1463dd19bd30de06c0a52637255ebe1ad2154f298b09d629bf3e726697bbd38ad3007a551364305c8b77c979bfd65b43e87d6f2663531c10ed0647b34a5dbbbbfb93d20937c0fe6d423992197b9fff0c9284ec5e8d6a5c3255c950f3234923bd056307a15a6fbef9b255c91a0895f910f842d1a3d113cead803c241a0c10e20c8efc08b782409efd1a6d32f6c97b5ff34da639fdbcc6188b245765d06f52092349ed4ed0320ef0fb4b5208d81118bd3cd15f50601a93bd917b500b60056242188199219fe10d91297578229f70d9ac4926f0c879c1375239173e80b0252fdb6986829fd049cb01dd3a12a0a1c49fd4146b77cfa05c378d47aa99de654a9a89840215896e12ea050016cce66d37a6c3eda31237602cc2d98b1d58720184977a8ebf4bd53f8beaca69d547d9b0fd9d9765b78be24049b3baa247439117a511beba612035eb8a49cab81bf7da91e4be9dd6bf5078bb4d6acbffa8355935de7bbe872144278fc0d82d0714b66cd99b9f083db8a9646af9d1cb8292a545fc3ff66c38b2c443e5065d220e8e6382f90c7b0f8d3070ed2ac465e511098999d849703cbcf019ba0ede5619509a93e8cb9ff0ec5db55f21415534ed88408b0a6c825042d666596d9342ada7e90d16ae41026b3180a9e248dc265d6b394ae70dcbe40e22c69f5439f18f59de9537a928732b467801dd4493897a8b99cfab63b135a7063e822c34b7baa28989926c4d32a9b5282b333825360a6cd37cd8b71d15939cdd8e964c6710069d044b112083418dd775468e4beaa41060d3dcfc78bbc636b1dbaa5de1dc2c4e1973bb26c97d48fa00c6fd96ee6891a1189eef8ed1de6b2ea42269e20f37c7ca3180786f3705512fa50d6628d98c6c119ce14ec2a91dc14baab358ff956ffee4ccda016dddb0b55e2761f4ca0c20b5c1e7e92079646a311fc85db9d928f1919f03ba200ff7229a26b2859d8d3b79274da1eba206688b751d9a69611cbb35b4ba75e9f1718a4e65ff2ab00f48f2a416ab81a4548dce95c39a09387af3c00a0254b7cde646ba147c9749d725f48ea799f134d80a6f16eba8f8f9c0c3cd08cb3563292792e90c292cef5169cc734d8fca41be46055bcc586538041c6927552df89c72de84f613f621551caf3ef7d5cb64bbbda73182ff36f8bc0d07f4527085e2d886819a320e179ea670612d13f0e1c4343f387d288653e49bae6bccf0d04403f68eaa19a3a20eca960a859b03be9ec153f6b375fba884169723716d11d5f81fc6e01df8bfa604e39323a4cae365e032086fbd2b3e64c8598d2873d3b2e5cd74dcab745e23c3e07fbb3a0cc7e5867915d04b2ce993498bfd2046174ef32a38b8ed608d7a693da65989a28f6170e30f78cca041fabea3ba637923e2bda37a679706112db658cc9e623f45a17b2ab71d0a109134d639e9ecaad836f44635313d60297bf4959f8fa78eb2179a3849c66a644c4381237af44200ac1b5e1919a3c67ef51c2e5df86fe880e51d9cdda92f07d5f2fe1cf840e68319eea9ef08b9c38b5a94b5a89711ba515088f7d898d3d265b05a171e2a084c5c11bd6a0f8a5a633ab42cfc1778d825dc9d96ad040b87d805a39df76875ce833faf2ff4c0b30ff123f610f17f18572fe389237b8cbc104ed405517a9f23a932cae36ccd0fc1cf071b2681e2ae6b207dfd09748abf8d2254806b1e086f3887d91fc864bd9821788a2f5b5d1b28653501c630257e95f75e1ea6327fdc7b76cb628bfba703f8f37e969f720053188c436c86efeab8a6d50e3d67ec4a15ae9251c3200a30472d8aa8db7de082f809b18d9fa54ec8ed6099d3e2d61a3c85f23b6ff110b31c60be4d844c8e62a86a70be87bfbf14064d5bb474cf4eb2c57458d8c441927383ef688e7f0ee01dd2de1b8e68f4aa772a6c65856e172fff45adcb31292b605d2b01e558753577179f7079da2e1d2048db156803af522f3a0d342d46c4bb6cff5828f8df47aef85085124e4a968ab5fe1ea9afed650b370c1753d058ce19a2a8d202c54a6153f9ca0174447a0ed6af3351dac2173a4208987a716884426c08aa0d108908b6a27875ce7748a73774d7306daee790f11746d325474106c5e3665dcfdd340cbebada84b7b35de0f026bde8af14d953b2ade954163730b0df3c7e4ddbe3093667c995c5847811b00a736e5764d1b5f6c0278ea952865c247ef76d146925cdafb69781824668bde8b6145ac04dc04f0344f776a0e0cce0918063e2e0ca459ccda40646b2a1a4a93219b6ed0e30ba8672cd351b08562cf92d693805d0efdebdff2fc78101e9dbc6eebb2a88590d1c1389b3d96b692790072df5895ee2639403bff46bf7da74e31afded299c04bf924320aff19198cce5f9932fbc990d0d504bcdb63a56d575a5af41510423343fdd50f42143b99a564c7d53da6de6866da3230e9db006570881f57dcffe2b51886e6961bea2c7fe651ca03ef4a4dfee64fe46d4f85924e954603460e4f7920e826d29279f0db3c1ccc0a97f697b765ec8bd917a7a55ab60c9033fda5df6d654ccf16db03634ea1870c257647f227ac4b7720096cd6c444c2039f4848f8a2f6e0eef2c10a72844d4b484a2f423e8665002bd95d82400bb127c27bc60418fe01fca4e464a14dfeefd59c9a92509e1f2d0d7a27c86d348db6b74cd59b99f68036c9a746ec3e08d9c34181aff29bac10e136235d3bd60709d54e230f508817c1a1f34577208784455d0814154b39e59b449d60b2df33e0b8524be44d8ce07a1064b497853e0233d79c1492b6e09e3026d04ee73d7c789d9150a9dcba317401e770dfb9ff8ea6a9d4109e10cb2efe50161fefb58029b1516ad2c897bafbcf936a31d35fb662f0c494d4fa932e97a36644fa8496b28fdac6b5dc06a17ccac23df34a1329f0a051039b02a02080d126761ce5a4e7d3a95f761376a236a056d46d1c3c40e0d46ad515ea14c6c1390b78b55600c60a01b51405fadf35b0d0a44acda65ce187b8046abb0f4c6892008cef78c25b941c3bbd3e86af153d7620d2bdc135d7039007765317a0d49803940c9e8b68f255cdb60c58db4050cb411611fea2e57abcf9edf081ccf3e62fa597ca58185c970c25094e886a88984b90ecd29a60191ba646101200c6f5ab5e3e125b95c0e58fb6aa18acf07157320a9f21674c10c206171a2a79b4ce27bbffc02e0454af17d0963f9515058bb4a612ab331d5aa56c1a127ec5eef20b5453269fbf53bc7aadaad27c47cfb147ebe6b15638e3fd3628eccbccce3ce728e97591349b95bf26d666fc8d2a46ec491204afa19ad8f5e1e5f493aa84b944b06bdfb5b5727520ee220add950135a082f46056facfc5db180d4e9b0e570c8071432dfc272253968a600716908ff4538e47aa9606bd451940983cff244cd9219b2c9bc477526d931e10fd91bac7e8b6735add60fbfe8d8c98f30f902ac88849a9d8b4e86abae689b8402e1541aa1de94bf34cdbe491845c11cdd26707f80ff73251acc44aa63eaacc6db5947125a0b42714efbc3e2ac983ad6355164c2cebf7c8db8d0288cf3e540274612796458910835bd40a5de7002e28a9980d80832eda05866f60c5f057c294282f3c11b267729843ba9a6360779704b491bc1603f9ac73481ed95e51234b8c18713b6b8992244f7834e8303278ea41b9ec0e84fc381c5a9e4050fb2c03e4960ac412e6207fe541e8898e5500e5b9a78f9dde2e327a0a9720295108e40a73e38c0158834d576ae5cf9ce8a49a77a1914cb37d3466cf914fd169d477d88b92803145971e82ff8cf891360c43148fbf90379ae4a60a9e19891a1d8d9f5a61b276b81326e21cd046442614428cc45e2879e8f22eb2ea965216a13dafbc876fd8f747fe03d22b90474216306ae50702cd09bb43107785fed20c45b825402497da69bfa243df8568bcd822f055a5924c510f7e7418b5fd1c258b95dd057b84a1b6267464e5fcd6d52196b61b7641e4176a39ac9d5ddb6e79fb6bcf36a3d0154b0e7b06ca090cc45d92ac6e9065579b7d54229ae10a4164193bff04c41b2708e261f1c0360061ab230cacaab9a76c9b07a9a8d2b603dc3f0abc68d4e3c8f78487dc8cbe6ee04592012279eca3524c20c379f3df949532b343e30b3ad16fd512dd65d2aea42eca507abf12982f04542188daf190100e61fa0b780fbc6ed28785751bf0bdae9e3ec461e2fd657108bc7d795c088dbb750a7e9b484c05b29716fbc94ed934641fd11dc3dee8025104087da60db7a14f4b51374aaedb562ba6c714ed70a55fa7b6d8eff356ca8c8e748c68e3f18ce3edc80e363443210eb52864f5b25be488fea00408c6309fbd76706f8a678aad7e177d40f2786e6c9d81331226d83b41c87c8ce877aab7ed2e718855fe72fbce0d0ab595389b815594ead64abc46afd818e24871062374f41004d0012614530800c48bfbd8405c5f6c195926012e0b7fd8872c3fb053891191a877774c6fb595026bf044095946a61005370fe2a94986abe72a51cc1af8b66949d376caeeef8e3f3c39e521561461f86edf20fa5f620f2f977cf0dbdb10ea0fe3ddf4427cec5602fa4ebce1259421785eb1cdd535f276d9d03523a58625fe2262fe806b0a9c185bcad732ca66d5b2ae8166b55e33c17b5e16ce5fa4bdc10d0dd6a60c1264811b705db4d3e9dc868a9b7a17a6e57bff339d961c356c7b064cff57dd6e0dbcfbc0a18a90d73186e4969239ed3e7aa6bcd64e1b66fa8114584b6d17573de02d131138f9986c2c4eb6176a0e96740e2520df3ab79f143ad80d4ac5c4d99facde8723eaef649bce3def92a587c43d162687272bb81523834e06988efe6ffb9e22cc397bd8d45c5bc98b10911ed06b6e0dbc5d8a0dfe7f561d7578bc0b8d3055955d9ce91e16c9f650f8d4530dd8e1daca473af75f2e796f525094c3dc8676184ca9dbca9e2ba6cfeb0e21c5d9fdc61cab265068ed606ec950829e2647590322d2c4d71bc6368dc6802d9b348a349a3479a33c785bf96e91cb2be76a76f9b4974ea55bdfb7a835dfc30a3defb1acc9ad43b55de1adfdfece8b8570d4c2aa2ccfc0cd195be9faa7a83fd78263caa037dd401f784a136f174c0f040a111caf1de04e176098957a034857dcdc99005ba072abcd6be2c629bb8839aa57b28ff48fae72ce0bb7546af274eba5552b4078089f47c21432eb8c6a65e71334fdb05f070e35f7e3976f655c4104eee3095f46500b5c786e8f497d2a0a1162dc3952023022189af30ffdcd428ddf9fc2dc78c8c0cad0e6566e209883908e5202fcd1d135124842189d8d3bc473ae23df9644864ef39d8011545d0731e99988f72a38e685513a4f21b316b8a838b771e0ef15391dcba28f07064748165658c18daef71e3ed2a33c2f6c22370eebd1902683ff9c18a88bdfeee28a73dab77f7c6e5d0ad54bf7d0433226b9d4b6dec11925af52e8f18411e34b17b74912dc4ab2bc082784b778a94e191c5f5dbcacbffd0c73febfdef592ccac143f245314623006000c6905b306271647a27200f4bd80e7b07ccea9d53a0772039417fdea1a771b5c892f31873d839c2015f05a67ec34a50bd2ae1648e7f552291ae50c0c7cdb110ef87237f5121a1afbc7ca877f17904041c03c9fe32fcae9e2f5e35fa42fd733fd4a5a9fab87f916685730edd82a4aa1a38598b5db6ea16eda398b576a5889e3d65122694df4c8a60f203a4a5f8e46a2c59ba6d385ca98b32ff259d1a8d7b86f292fa1697eed94442d0c086247e40ca734504eef28f2064d8f437ddd48c3cf672683c0a007d2d90614c5c52a2e1ca02000593c26cf28883db4ce989a6415bfa4d291b15f921f16030a5b1447b87ec4065832165183c3988b3932ceb84bd27c1d6b272876977e1c8cb1788ab4c20f4d1977780894440c9c624784254e4d185f1d240668d24c3c9d4d4136da72d706843f3e00b82da79c93210eb1e16438ccb42ceb8374d70689535580c6ff1eda4a0d5a8c0b7257930cf490cfdfcec0fdebdac0a7aa2243c00d5d51c661439c64aa885340f54f96fb9fb850bca7b5dd6365c58ee50528cf2c277d88f243236de7fe9459b799422a6d0fd860f1a3e231ad49b102d071c842790bf67b305a6c40435da36443cdac016fd00c08a00f5d10d4c76f06181bd9a4835e3f26992e5937d1f8bed2d85b917427f317859a7d33744c9d83e00822248072dc99af8a1c3285fa1aa40a91860c7202983e3848eeffa50eb3df1990437d644481541164266c0da34f5859362e5279688021bc205367ca4629a1ea822ee08d0c63f320cee640c765bae924a931574997ac70c6e10d82c691d278461adac2b0423da031d1561644444a3fa6e7fc3ba9671640c1112fad31c70f2f7c160527b2e99b1a2da8df0f27ae02407113c134271f93da198eb10fa5a486292410f0190cd09163113b8fdc760c991b91a4e4f855c2f426187a29ff8290a072223673865d925051b947af8c6b0badea767456e875c6b44587cf33729b5abd7f900cf52ad27024620633c3c09ebb91ad8424664e35b05182124cf3fc99a4f8ff8c97faa60e33d1faab5c7fd7e26db3e67b7f5a6017b5af0f8e982b55ea7fd15e430a1c927b5f9181f590017d15cb7e4d67d373381d81f45b7607a55e6ee345a7892a932c91b5104489ce4d1170f83d984d96c3e9c4fd4d8271f2629c445572e97e638fcac89178a5de98db512d9729038bafa8f9e4c084f6a873e5cbbf4992e8f2790768e8a4b67dc5086d93111f62affc1452bb6ef793da21c7d3a86814aaa42dc52bdc8132c94dc027006973757ded21d284804da8c8ae4f46971a0dc3ee9377a7892ceaa9bd17465072f115d6af2c7ac020be2921e6f441c30bd3aa1d86291a7c510f4a023b6f76b2fb9942770b87596427bbfa7df6e50ce74df2e795cfdeecc3efdb8f708a81f83038d51afcafc0dcad0ad83788d1fc633e60133ee4d709903bb055d1fbbd81174333a805ea601837b3d626edce895b487a9f5f049b5e8522a50f91eedfbce28c08a0b8e2e7613ff50cdfb54c844b83debffabbfe4ca25d7161e48b5e4563a74facd36ef81ff7f3a78c1f2530ac47e25b7dd6bc136b532d5a70853514fc374cae18fa69c87597ee40ea5aef7e1ef7783d1ca1146dd641baca533521badd3ab838c81764d3496085f3bd0b9cdcaf02b0b1de34d56359efb1bdbbb8fa4e26cc1ac5d2000f9d0019abdb639e75e7e343eecb24221b3d1c9d56de8509fd00d3f29fc7e752712ac340fbd2a0ca24bd11bf90082baf7e6d12ea35fe9ce5d124ae3d9fbd08b42dfd7b7472426632cb4e8a7d85fe0ae0b2da719ac0c25fc8a59ec89eb59962d094b90f7791a89d46b390a1615dd08f4724026426dd12ddd7d356a6223eacccafdea4e25dafa832e52cb534009ce6d214a706de2fb70661e14fe3f80f6fdfe456fe4a24da5cba768b816d0951e49c74e8daf04efcea86b3071985a3183ef06168056441ad407a06e56ee47eeaa5555b18e073c2a2c4b211a2e41b3b92004e16b4ac483c316ddfa73db8e0721b1ec967a0f8d4dd5185792338bef0368efddf2071f52138919f5c576cc38ecf89121f06996db39bf770e8e62f265e854f033790daf9423f97c7e53c44afda64d8594f751ac57b24e8ac2ab7113dcfd552ccc2daa2f2b51badfc76fd67e948e1d576eeb0a3846b3d4b3544e600f137885174d4f0f3d98dedd445c803debf723ef7b75d3336790e015f9889f0fb2de66fd4a45eff9115e4697952b202f220b5ea9ef9a7aa6c4278978880c907f1f8bf52aeba4085e9fd8f8f96e43ea79f820f3d80dbc82bff953fa1d33d39487c5b8c8d601ed108205af745cf44ff29257089965afd48cbd2c30234a67f94a3da33f82e6bf7e1159f62c0d565489fd19093abf0aba1f41d93b78f25794d4b25beafd342a39881ab3ba9fdf59a2721aa3910b5dc5c043454d6a6036a731cb779f3f41580a2c616d031710bed04dfc4f207bba64823c60240bbc12bc23f3c2b3fadad5fa4a64b7ed00427efb7bf1dc810a72f5f9890c10dffa877a3fa0a6538a7f685491c179303ef16b1aed6784bed867ef242811fd82bf7f90e4d964b49cedfbda927f3570d2590fd3f3761ffd8e3223ec430bfbb864c10d3a75cd67de8172995594a909f074e52ed8722e5d1c969f4c9fe1de6265e5bbb658d3dec76f82c42a0e3af3a47d13299f94cf7ca70bae5b089b0827cbe93c41531950bc3828757ba49b638f214411a76710a29f087e91bbf1a3c6e2301a11f0794bb09b29af9f0c03f425f7ee755d28232096fa6d40d1d5feffe8a1420dcb66ff598e0696912b61d89f27b97d9af79216181374aa1c037dde32208406ffe0ba9439b9b00f5cdeb15212b7079574db949f865fda521e5d434cc53cb2d596f182387f78f21c0a3fa7b0295f6937911c7141033afbeac88a35d2af2179df4af777f01f69c0251b9bd3eb363abcc0dd07cbd8b608039a326b0920840a352eb71aafa5c7ded9c36d1d69158d11e4c86143d537350438481fb8c27b1bec15afeb526057f30bf48f968e7ab9aadfa165447089fc6b5938dda0e5963544379088cb003b376846b157cefe43a2060244d818d636467138c85c693859981a04b06910cc3f5f30b5b43e1def87e4c348ab9c93dd84e03a3171bba1a014de70cade979afc8db6450f59709044784aedbf41e894c85a4e2e5cb2e9a82a3319bd002662370dfce9bf793c051a29278741e6ea51e5adef702857a2ac1794259f22841600999d4c6d7fa1245bc99d7f9ad4d7bf1297e2ad44b62971c4ea1670c14211071e79bc427761771c92814b5ea1c66e4e94164f1cdd1c2d1958f7652f475ad5b416bfeb09de8f2341d63ddedd9f85e7e8403031782384130664e7a5d47200e7641c3ed4707f501f1d37d0220876bc8dbe0a2163d29c5bab1c6be9431669cbd6b4b9d8e4483e2ee2041434303a101dc1d875e67216a861b34b8e5f08f16b7b2c1f67275fa939fb38190fa979e90b81c077d77f636d669ce63791bfe4eb5f20e1973c7f5f28781e3b0f3d108e0b686a58232bbb933df3485959cd06eb1d3dc4e9dcf048c044be319f4b2252cda97c1c84b28cef9cccb5a38e53c5bc416d70a47a93c478cf302bbf20a9f075ce17eca63276d9342a03e10b2764ca1e318babb0904f12905f95bd9e816fefe42d344cfcdd1158719d679eb64709f84014c574c37e58d4999334b46e1cdc6db7b18943db33ee47ddd0225f01362014fba1a07f21ba661f719d41f679d4ab614f49781003bd4b41039f376205c4acf9c631eb7f47fc5249850870cafe3b5bae97d30826fe4e41ec94dfc4dabb547739d25057a574bf6fc1fb4dcd7b131ca443e06e654d92f5911ef6ff97ed2f36f2da9093edea21e1937249f5d3e205563578b311decb55c8771a71ff593b8cba8e7ec87ab7bdf297934e64db5e2e0f4118ed00f729ee65fa27a2fb621081f6bb24f1d1254bb9d4870d886c1b3bf1f1a8b380325bad317a19a9f4383118f54b474bbf27f8be028e1b42cc1020933f17679b0efa2c3cb958b0df03f946725a2a32186656349a94f7bd3301b60a95c8007ebf8d0c3fe899c7c28a5863024a2a113442cfbc41f497247a7a75304915772c0da8fb938e229354a76b36542f1e550a85c2046df6f3f151aef9396098a2668d133dc77527abc0038f5cde6232ef67b33190acf80bf6c80afbff4b59f07c1a9e471a89773a6755e518b2ef201aa8ac26206d6dd30cea1909111533f869b1ab393020dac5f296ab78cffc3d171bb35dc66f9c4d9c98ce85cca146e23c68d5aeac81ed10386d4399c0d130c455e5ebb73e9293192aa5d6a3187185f4e4ec8090cbd2b9a50bf6067028dde0b37cebdf97478bbeae82316f8343c2655319e3f3d693f046249673d0bad8dcf30e3b59c5fdb8978cba2fb2478a3a84aecd849a015179f159234d48e83e072cd6acf5d7101f3623d9180f7b456870848374b3f2170b640bec86caf5e755a7cec0e50762326ee6af6938cfd290239d8d3043fb3c8f62152409807d44387c2c0068ad9b8b3d1fe0750a873de7f1117527761050f49910113e01c49f8ad95c8d0babfde8e73095d76aca4e6a5f4fee1e309ab2f6d7800fa77b4ecde24341f037004d17ef2bb422a15849eda6dfd697d5ab5f0ea17d59d57e15c80201c85246389892093e6176d5bf1a40670f8395caeb4f8bb8ffcfd9e322025aa0dfdd52f3eafb2463e8a4adea83638be6eccd8a0f7a340b112de390650f030320194b27aded16a06923e87f003d320ad7757bc53203ffb72f64a827848a73986031f06bfe784399231d78e1d052648444178e35ac52d4122d8db5af58b66705dad666c1d2cf46b4a9f45413f3fcc32be55d295588ade748c92b4549b1276609253a8120bcb344ef5bdfd1c182450f179000603ddb80e6b8a86679e8ae2553903b3e45c10fd3239ae2797b26324dde1b0cee88018a6b424f30e5d45d8aa5278df1a181e68d0819a310607546101753a39cd2574aff630062d39a289237c5d73347ebdc4a0a6262c9a1f693b3cc62339dc0698bf242f29ed814db39b346235a3a6dcba46ce088d86023c1ab6cf334027df6896c04d106d6c876efe1342b568f283e1940d08a91003aa174b62de40d221eb2e93fb1ff9b888c7d8676429c5b39b98ce2a90d9d1fd51d9dc4d4ba98cb8ddf804c4e7506b4b0e41f43830a46f00983ebf8daa3836ddffdd70fd5c93fac12bfdcf27368065b4ef0ff9b937c3ad61fb54b9f533762defb2bbac299cf73e6694c939f9b8016309f3911fea008bd4e24294def013a1d16fb70a5204589db716729efbe87056d449dc26e246b17ba0b71b60c6061cfa95254d1bbf238e2197ea60b261b9b804b7f5ac5e3c30d8f1a11859742aee86cd8bf9d3d78426333c95b926f215da51d567a028f8c9600368557ae055b4676a579bb7e60a9c8f84ec87233b118227cab6b4428e8a73131dc334cd5580f5abc8b232f3568028e3dd91d87fc4014443a550a97475cc3ebb626ef6b783fceb34ccfc03a777af9f8f417d4a0d70ad579f48df83de5cdfdb0ea8657a24d26451aa5d8a445947bc2813e83697aa643df251af9759030e6203750f4cfcd6ebeb0c43930c0a01f378dc7ea4e442a5fc27c1811a87e4bd4de80ee8cf2100c104983da29e287bd44d3040331ca82c7f08fe6791a6012e66369f0d19a460f1cf4eca30e674006babdbd852dc41450ffef1153635948e94fd4f114c0118a25ead722512513659214000c482f123921f2612178704a20f0873c9456bdef656fdb7e1b7428216c1b4eef728f917a6c1ae241d127feb231a8739e38141f812d81b13635f9aaa1694a9cc63898f470e4153b2054da2d7e3e8e1505102a448cad5a211fb8ad15f08229664c2efaf753ba7bbe0278a2068658421385d5359a2308e82c46b5b738764ae4cf85699ed403206b450b982e1e4cbe6c8c2350caa3200e3cd58ad3d05b0bca2cf2ed93b32a9cc35fafb4090c0c0cd6e8bf2517d9ec85ef0389e0fe170c986cae5d0ae6b36ab9dd09dca7e855089d21627d47a603727c0351db937fa9cbcfded8638a4b9525516dafe8b03191c5d325da7b1985a05207c3a151b3891a670d1fca81a8b9810a451f61d528ba85293296a59b8434863e082905c1739ca6fdb9b6c8a9423114cb285f10ec19ddac6f1c05d184f799e6328e173f4323ea68731aef43ef453f9520d7c8c6ed616c2b18bd5a92185d9792989b3b6e34adff1eacb67c8589998453b6cad365ea7d4810079a6891000cffe112d89eefb77f17e8cff6187fc1fc3b2524f1d7631eb1457e6f4eb641216636ceb9a8acd48f33ab54b437675e80a62d891a11b06f6ada546a02e6e4fef9a7611ec621052294291f5e874378c01c8952e46f957067ed768a6ed0141ef5028d68a1c67ad9ebf98198015bd002f8decafeb40250d69aa4ce2e752ab7f45c93dca6d11248739f6ce431796e1c4468c60a91d8f647833247f51e325ef2f13213bb5acb989cadf759640cac8994c655800d6a871ffb7aad09c3335e0cd9f2f7908c6120f5cdca1b68e172b373d82af680ce27170d880f87999ef0a8d46f2b8c774c300fd2ae0399f861bf5103a6ee58f49d4072a5237597377c997496011ff726d2eff3363973eb4e67ef38d93438106d9f68af057d51e4336ff4106af38d3aa8b94307590c6a4e6325cb47e90d9eea758bfe579d9d5469cd77f53fa806dfe289269928979cfb4a259afcfc52d68f835cb9a58512ab4ddcc21dc06dc6035acb404b9deea01a6fd97fb1a8fc67d57cc7127b055b573492884b68f548f8e2a59258dd2e8a9bd25b55374602c609781e533877b92db0e874f9761efba135847fc1f1040e759387da8bff169dea796ec39e46df89f0450a545cd46d0c0a92a5b6384812c724fa749714ca9758b1f22de951a04f6b544dbc47c24dd43a6091d09d146c2fd64160c4f1018440cf538dc543f8aa9c4950be4e8b5bba796b43b849c76d7a935fdd046a31b449adc9fbaa2a845aac49ab83753e6eb33c480447f4715baa5d9c8ae9910d6eeb516216335c11b7d56a73c146f1701b956a81c1a81ca5a3d4560274e336bcaa85c423c479c7e091702487cfe5462f40995ce7a8527cfc925e2c0ea4fa2823ab920a9ca14b5daa5a4bbfa98f42f20b72ed14ff4f076069aa28992be3189abb25a2664f3ea954ce605fdac008fd2885d5a4bfa0e94e6c4c653fe92c5a8870553727be5078e07c3d10b2913d8082c92e1e26720d53c65bfd2bdcc99d04c5f341dc50a42af6c6300e3575b1a4bd0290fd41f9e475b7d7d07389a1778957a9dea747989f73561b30297631f0915fc12d46e2d37fe2a06445b430e58ddcb492b6d0eac05ae79dc20c20d53aa7716e7e5404d2dd6c30bcba6912644a63115f8560f5f44a2e0bceb8c5e713803d7ebfed7ce039e34a85eee96191c5f0abc0b1984d677686a18d02e6fe4b0c88e92221d36b5be8033ba09e490aaea91370e1a106b259a49aac5f6cf5b9ad59d5052a2f31b0e458e75c2f80d5e41b60a2006b2bacd20ba4cd00dc6c7b6691509cbfbfca5b98fce155bfe2d05a6dd86594a89b34147ea56de15a7ab2ed88f9d52b884918bfaaa7d23740406a2a81965f9d8ca8f9be4c2eb25a2f8b9c6c1af6750effe257fb9bc08e87a362ca9cb5007a7e0a9f905a756af3187f901868d6629aa3caf2bcacd6f74ccf69e4f1ff0d508c87f2b7e0673b8517146f9b49808f202ca1787ca35a106a6a87ce4dd0e9c99416ca40049a80d1c50ae2565df0a395f3c571f5c35a0ea9838c71a951f5efe36afdeaade9630db104ca6532b64f3b32101807e6fc390398390ee0603871857cd6594eea774e9f791a52912405c9827441a48b402d9cc4484c8ec6ea4317ae626b213843e2bd4fcda576c5c30b65253a48b85a4d466d4801ebb29932dea8dd1064c6e4704586ca1c92fa96693296703d10d8753936d9f4da7324c2546a65b584e7ed86e35f389058762090f6ecb7b78bd4caba62245a94d5dc1f07ee879f4e9c4e761ad41a23512bb730b7fc51a0f96dc8ae28a63e84f3f7480db55af0652dcf2f8bfdcc62ad842c56a3e8deb9d905248dc2316f4f1415ecee5d35d8affd87dfd62a102a2e9c17244b2cf5216ce88d5ff6c2b86ecde2da117b663de4e994fca380e7f841be0bcccf0d26696acce37812fe7f7c005e62c27fb23f423efe4671116f6874c5c8835260354b4c767aab93be847f36eafde5068477964e3520120ed7ab416fb4fe571c218369ad477016203a043e11931f857400fa83704fa83a04a6c624694466cc2687995fb705f7b292089c6f0847d3cc0207a88affbd63c23abbadea1a7b8919334e91a6b2d053579fcd75a65e8466c04d0886a24781695e094662fc187b2229cb0e667a8e644e53aa894f3f2f0d86f1656a019cabef0dcf0c7a6e6689695cb6453f1a1d44c249e6703540f0c08bfb2cb9a05cf55ef00b9dc3fc9b037fe9fb8be9bc01c8fe73629413c6a58414cbbb4e27806d0f421a0a0dbcc730ec004ce351cc73225be78a2b8799dac49ae98cf623f4cbeda5b8c84033e13306ceade5639138bf2bb36f18dc4bc0a99b1d88fe13b6cdaab6948fe6945a006ec0082a9a2cbe3d6066c262ed0afc365551021bafd09cb89b3cb8e82f57827ffd185fa7783942309f20319606f07c31e463a7b000e799d052c9085c31ea2dcd2dddb623fced9c457814597151b29f598e8d570cfebc9d6ffc2a6b387b1be0cd4f071e6481ca29da4c5da577f1ed07ba3a0262baa0e289f935c6b2c2662788ee0235589d9f7849604552e48b7167f6eacfb8349cd7a3a5227a3512410a043e40686180d1e92ff086ad3b3770c855c31d059be6eefb86aa830f9c5e1e79c8c201edc40ac07a58230304b64410cfc060f8f54b40f9e5ee0253b67270178fda47d5dfe7efce7776b9c5f4208e793994691496ca81fef69838b25af3aa932812e0effef1828f4dd4b08b281daee7003670e99a171eb83a12d7ef327baecded2dbf857dc6946c60ace0b088c7da8bae7416ea089d7071385e801c5cd08059edf89af514d8970ce52140235f22b18c6710461e1895e9823b6bd21df33cc1b3d1466ca6195dda69d702995122dc424f8799a7f26d480469ee4bcd32012b27af34cb5d5f9c615ebb8133a97325c45df34fd89bc0f1cfca3cd90e1eebf1602df41fe9a43cf240338d29dff024c3ac4822d8baab33828e947485f88016461045e4086df4bfb07863b47b0056d846cafd3fb08b8c61e9b41433ddaf79fe4d2cba2d5f0f2bf83a6e61bb91b078ea145b7777d1aaed0a8392a66084ad72a3fc349a6e5afa7fede6accd601a542e883ac3cb6e81814efeaff361e1192e9ccaa55b37b4b7569bbb09b60c82c922b30a650f82896de5c1fda166fe1e22514adc33c00aa41b8c5e56b3a90ed276d33a8d074cb9702ee098608349937582052a102df9195988a6ac2fc974a6503b5ccd0604108b31b8b0524992eb6ecfb0bd822dc54f443f6535823e80e007abb87e532ca4ec235c71f1da9f4fb4d7c7d9d6d327afb1e13fa780127bf8071619e5e5c0b73653c8d941c2436ba0b14dc940822a53592adb39e2ab528d897d3273b4332e6e562e619dbd2b6ed7408c989be51c12201fc2a2fe3e46aa3c3460979916aeffe1f855cbff147eea03e9f39f854879a5ece8cb3695ae8fec0102283e47b04c2de45f38101f959acf89448134c67108c36d32915f4028b3bc5ce8698fc8c7dbd63da7ab9fdf63c690325f4b42a3a63048357b13351a24a869db9f69ca65b9a56a9e1cad93a2bdf0fabb3f7e63c77eda79b4f12a943519655a9deebbbe48b6fc917783dcb4acfd850ff0a323719e20ea1ba6c4bd4aa1944ada90b5c72f2f85b9cc996cd8567f682694ee3f6dd582124a02585e6c869ea10271aadb409017cb3bf2ca79ada3b6772beb97d86de4c57814554c1b711bd5ce255c4b71bee3f99e572eaebef56fff930d122d0c93138534c0fd2173a142f1dece7816f22a737e337787cb4d9cfb583f79df2c7161cd2bdec4356d0126ccd45f2fe8775ef464e2c82c595ebb66910af566b7a953bbac8ef47cf7a11f10ca9bbc26918f5aa172f1e1be82c6a4683979f24457b3e3c864e790428c9e0536292c50c5a818357f9dc1f0629bf69f56956daeda2a32141106c4bac46d76ba8221fda6175b4a6411b58f24d8c3baa61c90d91c3b4409e82473a2b64a75efb9708fa425dce8ec7f4b0e437586c4cbb61f7229c7ae6c24b75cfe74e87152dc31477b054a0c057bec83c6e25328cdf9000887a797c8085cf393979b0c37e12cff4a1233ebf8162cf320acf5d123e117264161bb052b42eed979ff294997d5deeaccc12530b8875099e094f219baad6123028ca833ad782a8075887e9f9913da4aa4435bbdcbb1384cd8873fc719d851ede1c0fcccddfcce8f158f19479137a1e922112dc9926566fdd9f2249f71a918675ff30197fcee2e5a8b5016837c18fee08c94141e12803620e4020c2613a0585d19223e06bdef925094ff922893c05cb00367e587e6f107e80df4d00818e24a36eb5ab84bbbe9b7014e3a5c01696d4f34407643939b3c4c533a8b3cbb275c9c5d9f7aa39fdd5844a1921539251e91ae7724b45d739768a030c81950c2342707282c387703ae8506bf1f7a5f5017d0d40095c396c51021247104c4962b00ff3a97002f4f2b40b6964b10f8624dc012e8b25b47f8a2c77983987ebaf3290883f1fb07be91a2cd986d825d2135ad40fd69eb6b9e746d517b96fdb74bcf0dda2b26712efb3c7a82ecedc8f3c2a92564a68f14c7e422f18daad2ef366f0e2242267abd84d11772ddba2f259f59bee8fd22a4265a6fadf83785e9e42f68500c3714765b6b2810b05a51782fb7ba66f6eb02d67a037c556f804b5fe2a50d6bc175c396d2c0742f5e983793261b06536ece539837778a8d41b6ed474ed572c6e7dac914e6f66ec515ef07ad1dda04141f2ca0c64ad280ec6950a4b2bf7e4cf2c7f095051d1f733304ef3dc43bcd05a6309681fbda0bd3eb32b4b8ec41a6eef8d9738ba69d247b15b61e3857e99cad5304a68cb3d2784b78de0a4cb978b3f1ab545461fac5b520d86a74063410059c75953a57ac7886a5922e1008ef7b144ea9d3c36c4a7b203196aedbf116bb0b263407e3a399a634fc6a89c1ec0a43fbe54f14bee59154369d34a1fd9fbec4dc97d5d5d252c666f7942d79825bd405716094c898c83fd67b18fabd0239b6ecd7e59043631b84104404cf7d8df3ddfad7e0de850f40dfeae97c0207321d0b4b236ae448125431cd0fccc34d70aa21537931fb8d6fa9488f64436175a453b0e8202fb11164d699e1052be6314a4319b14be3c911c4f85690cfeea072a33a60d89f3603b4cdf7f15a8d8b90587a712ef1def2bce194e0e2bb7d6048af05797f19f70e9a9ac9b752d4a44cdb64e8a0ed7abaa70da8ccfbf78ef0847ffbeb510264db7ee790177674ab81e5184761f1af4d7330310845695c7b6df2d27c83e49045cd8bdf2b0659bd7b0685c0443cf918b2f7ee16f883a2697595c3ebf4dad9f9900b994e8d86ea0a19c84de906b0c02f5a9044ca8a121a1b0baa9b85914a08f712cb896adf105f98004fafefd3d11c824a456054ccfe373a3c2cfbb0d67e16cabeacef7460db850689b79470592031d9e67b925d7cfb4a8bce4ce00f5f7368f84c59b401c3013b9e218912bbcb9525c3077530d5f07dc6af3dc1a331ffca49e98da73b94dc809c5875cfda62aba249f7bb5b7e6620ba8b48e4ed761fbf15e5ccfad3364b56ef4a8b76103bad4438c510d27fac820c52358610093f77a99ba05aa6f69768b110ed260bd13399a0eb8e76d5f3cbb1a4119ba0c22f43a5bbd4ebe24de447976acb08a0a7aaac32c7d340a8d371d087d2470f7ae9e5f26308ed6ef6e3265fe47a06908cd9a2508d1555e29fcc02619c0d6a220a318bae1bb170eec005eda487d834241f442dae003a8a24ab7f100bf76e09ae8824bd5bb059920e9dbdb03fef47d9c7c1a654292faf3009ad8191ad7eaa73d4ea36a1c884ce92cd816f6b0b56540c42e3ce2bd92e16b6647b5ff16777f379819d2f33b54aa7178ee56ac4e0b5ccd317c4b6e3b40824ac6991007f115c6c97c9a6b4cf6048b04d6b3aee6807226ce20facf73e7edb235b5c1a9f58d6e3ad05e1953afec019dacdda68aa4adf462440938bcc0f30fbe61046e44bab2085a1e9ae92246312b9e7a106ff6ac82de4b169ca17938609dc8033d8cc674046197b68b720b5d36c934b523fb3893a6f1b773a6188065e4040d3636a889cd4f06e0f3d2d463c782919eb03cfc396fdcd016ebb3ba829024680198529f52ad81327e15a6374ce1ef84c6c589ede0d7d9c4701b53d5db560b34b4e0cd068ed3b3c80e225e39b19d6f1b712bb3ca6cfa0c9422a6529e55f7ddead2a371f1ec0a9cfaa5e8fc770a878968088e86b33621948461f4f9cb17501ce30fb593b3838bf3218c31c694ea2dc7316734bcb7dcaaaa1dd7272e8d531d10f403a2c4ec89e2240edf437e0aba7225e401b3c22b9948851c64d26143c289287d531d634c2742a5e3a1c117dc26111313f1703b20907f37cef8abb5474e1cfe79d881bfdf5405c78e20bfd7c35c2b0bb01197ed996fd1c92e238500ea5cb0b8917a5e4394eb2acbc1aef0356aa2d12b24c231c6f021326dbcabc5c7605ae5a1c1ada50ebf22503c20ebc05f212e6e982a701fadff4ea30800c6b08114afdee86fcd0596e10fe70017ac203d3f9392aa6f3d540d63abe46b4f705b8f0b4b64d7a959c2ca69fff7a0928b877600da27fe1a3e5aaab2d2b712867e18241fc14df15c0d7dc906cb297fbc3f95e947b31a2f88c43a4016a6fa0447ad3c065f8ec46b7b4a57b236aeb7af9ab49f85227858aaf95b2bdc697fbc08d6917527fdc1e73dec2b4135d0fd2414eb554b058afa06df2fd3845d35d90dcd1aca4da82e000c397db94a280fd5fa4b7c7c311367abce1d3ddfa8d01f2405beb0acec6487bbe6c6a37cb6247b54e412810fb17a6410de948c63f04e3812deef0cf5b4067561a654b1738cb502030202fbd68df44a5db340800ed5595543a3a71f52001aa84de2bbe5082438486540d6b165fdb51c5b55e292c0ed6964430d246ae50c0488aaf2eb47ddca4355df9b6f609aff3813884568303608ed866c6fdc6112eab59356ef3e8b0c87a246d72c2ff218578322c2af6998ca35baa254d15a492745d1974d6ceb5f2b204c3c73ab96ee77cdeccad7a91864362f9e1208724bd9b4e6ede114b42f54a5504c184f452d79c56bfa086df4aad39c1c549e0f36534d56da19ca3bcad7934b6c8595db3eac6fedc0920d9087f299250fbbb649d902b2d660a1c8915cb43e22f3ebc52bc4b6e6303adba979c02e54adc89eb8c72ed5b98d9021efdc681af2c2ff3f1629e29d42642d96f82416cef7c2800b6260934a060e2b5b7eb0d7087593f1e0005638c30f4447421f20242feb176a881fb97fe78251030279d8c83c08587496623d36d7b03b09fc7ddc7061aab0b9cc938704dff1275da6e10543a080dc0edd834f3300eb8e19b6dba5d311967e01568f559aec9e9e2a018ad2b0c91d334b25bbf544cb2b905b87ee85924b2ce8b0f151277661f4e913799a6c8bde02a2a4e5569d20da8f9fc611798feca8a92a9f1a2904777592a8244b2b047c53a5ff52bfb12bcec8cc67d05266b7b525b44861e164e940826f128c124d2c8821fe9c26b3049bcae703764779dffb383ccd11d7ad8ef30df0174308489d36730713eba4d965e3fe09cfc1c8df47e4b1c5cc6a743960385c0ad79f975ae5c7711aa85bc971ca9340c07f3c95026c179dfa4b8a9b00559405931572bb9e86a9f3dc06d103c3ed2d1cb96c82f255005aefce63e36f7bacc9e1118a1d642b14fbfc624ca47c54ddd28c1dbadec30b336dff7566f477bfea5c03ce927dd06da57d940be3d1d869359abe7c4d1eaf3b385938319e326f6c9f0eee4336e984386f0cdaa6b6c09420831c07c959cc47009efb888825d1052b18a52f7d21700e2cf20d7ca1485874944728399e471dcefa7ea1ca893fcf8298d73aaa23af81eecc143e8b55b4e97dc55e1df10438bcc1978a21b6199b95df8d46c95148a7abdd484a78e9d08c0afda6f983565dd1ac046dd69dc52e56e42f62e689e25890d69dfc07e938f04badaa9dac77748b9d9bfe45ef226861f57d11a1a3a3897d021ad8e49f45b4a5c152c9ab2ea816e2cf934062346ecd1ba1d703020fda1e9023078434c47005ca8172cfa34aa89696443d57e4b65291ce730d15d24a60d8d9323d9fe9425c3f226fc203f40da11ba949db878ce79b8c781e24666d7c1b2425b0812bf1460aaaee768da5777a71ae0810b7ba88a3a95c5613828c6e5a1eb56f1bdba33c4433131e1a7f1d532525f3ab6b8173af969ae2c99d3323c88faac10cdfca499e9a868c494e28e8af9f6403f111818538018390e07b849ec2246c4b09823d0149a987c9d07726869b0d7f29076d7c66b50e2c8351c8a710dd1466ff32fa7d03a0726192e137ead2fa179a2cfee85abebffdcae2af7b9d3d834d5e407fc79bdcdda3b8bd8a2cb31eba856c850ce0f96c7ff1760898279be23cc128e9de868b08abcac6ea26f7fd964c8d7448e3960800643743c5463c1cf07b63a10ca0892611f270692cb5d141a0bebcb0a1452ce7e0839f964af0a2219e51a44f9b3971585fad572aaa2c72b651165a61449108c86e9a3bd5d0baf2c095bae5540dedc47f43549d3e6263c2df9bb5e85c201db015d47ed45e8b2399bbc44d95f62956fa807c4144d75ae343439ec217b041e8b4a0c324ea6bfe044b3ad7ae79c006b204139855197027e403fcab4dabc7a99ba0573d9a5fc71fdc130d4217aeda7c2572f7c5d5aa0e3131c3e4e56f4b64a1b8028c92db015743d83d0dfe9c04d8d15b47b82fbc78d0d9fe2d8478d63c82670d8cdfea0c026e7df9bb6bf5f01f2b6a6d53cea01210feedb0c18180d8d3eb17a1bc90c637f7ddfd4a2bbb0ca841ba2a97b83c182aa747bf88edf8e1b1b77e9b84d778ccd482c1026b2f8e03601fb1004cd240e36695a111ba78980a88c66d37ee4afcb28fc9488508ecf3aeafc8a5c7e8aa4842334387e47ff9b0d958ce8b2725c4c97105ad5d461e2b910298f00a9015211585999620245cfc5f688871aa44e4bc4bf0e1c1197b43bec56c6297431d71d6478bb7040d24c411e596a0473bd9709f8abfcf8f8daf2723fb1563c8b003e0206c3cdc150d37ba1e2c73f87658ab85b52c7c5dd2c9e88aa2c7aacde5fd9f2f0d0df8e23d5006fa599f113fec8fe214224a70769d505b4ffb2ca19bffbd1737fd8b202f33d1a91b6d8a3df38d9dc3cb44d827f0b1a9f1c7ca6b53a166f4499aa484c67a6908f0ac5715631fb179b369bfdfea809a1b2cca7a1b9793f24f671cd95e797dd80349dd0088ad57340955e8a92ef20d2001832fb144945c5723a01c9bd214f6c71dc635b937ddc28318ade770565c482870096a32a4438a615be876d473c0fb3583ccfbe9e6a618e700fc8fcf5850d25633e42c6ba67107ce5a9c946805b027e326aa5e11e4a0c1da3958f2563c230e30e6e7ffdfa721aa6c963233278c0a72f54462bc7114d36514cb2e7f9747a8f26a9bc3860699e2590611714ab81aafe2c049cad3e60f43b488001e98e04bde21085ff68841dd5c43df4267bf7187928b5c63194b3188ea6a1e523c37a7a28dbd6ada112478096da024e8cefe429f6c4f5b89d26d05af3a81dc24e3b6f5e7bf946037fcb0eaf4606041edff0b010f7a186f3a168b49b477da65e8c7362d316f3a7f78fdbf76e382213dfd9409caa990f1597b3a19c42315aaf5f779f0450f01237c054e4f10f0e7042b7053d10984ffc1269596688b1e98fb24c1a29312b0ec50038273e63fa1368d01cc7f427edcfa6896f27a63fcb7a61b9105e89e4cef208d4135d7f893019a18c5640f51deb1962acd84d709bb145facf39930f4a7d583633ce8989b9644ef5d27dfeb3eeea9c16b68fd4e5f83f063560dccb6a0adfee81db6b18b53927f853a459b049a67088b57ce2016dfef3e68c5e0e2b8d873a030f521e937bec51e2837d18a6292741a0368b0ae39a8e914c1281e9f8406a91f29aef644dfc2e5863bb6e7c0c08b46f946f8baebe3eb41d5f690e6d90c4b866da0aa29522a78b4cbd5bcfa303366a5f8b78889fdeff3d1a6b731b1a6f52463eed781d6e7ad4ad2ac34827eba972757490a775d3838d36a9e4ca5a6335ff3b3a0fc7c53bde3265fe9ea8b4b5da5c7c90436b161ec6ea40c936694bf0e413ee891573fb1b803e17c87082df0d228750b055cd83f39fbba5ef80092dbabacf3d2266a0faa6b15116d6c954b39dc8dcd8b54e991655615eb9da28360c239fd519c28c066c77944bdb9621551e1f6832b4fe33d7565a4b019181106eb4d013f378538dd2fb4586ac671b9c1630cd175e7f9e784c5e5f2d51fbeba1c3d693867cd52b4cc958686e6dd044e77b71df1195cba763a3439d7ab3d295e435cb716ee361da0d37494a55a9812bc8d7f2d5bae90140cd76523e5983f6fbf9da232a781e51936d157fd61c4de07d3458384fa3a6fc03e5474e57196ad37894f21700e88b3edc47749740b98c3f491e7a391d9f0a8215e82165624dd73b6aec1de823d5bc4c61645a3b12aeeb8707897471a16b5e4029b6370bf9ff9635ad7f7722b03f3cadaede87e1385f9e9eb2dceaf5e3f943d450ddef0baabc12f9a8f484377b3e43b084a6c306fb1b3f71716a110305ba53e7d34cf8637f05f8f149f298e12e03fb3c1a250fd7bcc58fe6332693a6a2133c716711e9a44f23e069837ef97dc4e0dfe9e4832ee12d6ff82601aaaff2a53dbf782e6da6f46b0065a91aca9e9843aca6288b4985e4e856f2d677515eaf9b19bef503365ebb2baf73e94b4cac93ab9000126d5357c2e4ab42aa1c84e39e1200efbf7f38f6c33f67d18dcf5692fa245f7730ade2040e3299ca03fe9c09059d9d911e462a39dc86880fdaff52eb0b0ece0a6076ef0b7b4576df10ad24f85f8eef0dd9c6d8d9cbf2c4a835d75ca8cdbedcfc8aeb5f3a4e4a2a0ad75d0877c023d387b18b2515a7cecf825ca71fdd84f21164e9ca402d574372b13887cba492566d8f91e55573ee1ca29e9e3f25ba87ebaedbca0bccbf80e1e79df40d0cdfe71c0f57d3a6073736b2e381bf48f1314bac2a083afbe0ee6810b27a316b63701f3b0dd9fff115549ebb06b4097c6700795e1bb58dda6ae4ede98b3f97dfe7a09838edaadbd87d33029fdc262450f11a166f4738f0e1ce220edf8809aca498230f7ce1222c97190be0187f6da44cd666692ffeeb07cb9ebacee5c48a137156bb9f8a5909b73871235c9cf86c2e4e7cf4ba38f105be29a4c3774362d469150478efbddd987dcb874a422b06850c140148a7a78b1a36fd167e905f7d490f2ca59d30d489d2a62cc2f666ebc684881e2eddc4b2476527284d691e18eeba107bbb7cdacbb7927c2a9093b0cf8a163c04bf9ae4c2edc65926277c194a3a99c5c0b4f1f1d590106ff043f1083982a98a2320b4ba53881e4622a13b856341ad95368582bb5f00500d89d85653f7485edea1d2b82ee74b47304d7309e16b108518d011f3c3f4c833d4561e2f947b91c9962e93b4b2dfaa9089187e74bab2661ab47c9762cd8d9d2b5327768f954d87e870e2289750451f2c005e9802b13ec6952d6696fdc885f87f9e5f0ef0595716b291d3fe691200196784b7638181fd7222925d9079f990316844683bb3e55afd5e4837f4857b1040c61dedfd1263a3fdc06a3647c5eff34c19d257ebcb93c612e41286c788fdb0742a38101d5ff958760575674284b1aef51cc84dd7484349c0d624d3d6f185caa03012188fc53c031558fbc18a2b5a7ad4fef8104a813c1930338ee6b5706145116903f5580e53d8f9a0c1a139274b6ae30fead32a2e5dbb96a22b794527ccfe3ab36e5975407b46df3d9fd46b3c88042b62ec1a3d2ed68ffc957a982f28794380fd559a9f412aaab235b1a0655f25b70acc5d0c09268b9f01c8468878591d0f57933760aad95e048a18d40e4a424b62505ac8713aed59ed4dd005d5d3c37b1d69e562a91f8f0a9d467a0d1a29d6d697bef3f4c1615d42e6295e6c51cdd39898d49555a3f105871a1bc18605ff3963ba41183068c0d44d9c55a28a7148d22c929cbfd9c7075375db7e83a291ac185a67c0014f82ab186d5ba88a0e8557a8f4606af10a1140f7e2a3226d425b7c1189d29001f381e056a8c967df8aad47cef17540a7145c2901aaf07b557f752f2f7aa2518efed070f88ac9e101c2539aa88bd5e32e974747f0aa54c62ab45aa9680ce4c608542e8902a6b5bfb8d34aadfdc4fdf0988643b9786e71cf9da47e2da9cc47a9ea6bf868313d0586ccb9607d5441802f95abe3c05b0ad1f471951269189337a9737de93302799d7feea27bdc95cebae9fcb207e0861c97af5ad259af99b3dfc36458326f8be9200df87a939c4a5460a6ff93e24eaa4fdd286452c398f08d87865b05819306911b01473e39dfb5f3d18db0309b522682726c1f0e7308ce19e1429ba9021ea3ae4fb4dc9e8fac1385e37fabc28f5d1769bfd3e9255e1783e6babefbc95287c2b0812ba99b35aea74c04cabc3de96726217c6c19f66697540503d27e8514e4721905f32727b4e0c6e9408715153a64c5135cb4a52da102dde36c7178f35c7981e91b54a6c50c497895391dbb682ce3ea39498f5a18bf9749c425e15c9912a18aefbb94f13c86264525e04b2ff128e480fc9d9cda4fac8b13bda0fa44b2c14029a69ffeeedb6b29c12411eb6c6ebc7dca856676f3775a608c174757d54b0a316fdfd22840e69bc75509cd348b84c0d4e2be3122c64d289f48f576ef1b6b21f02a9f585d7a4f1b809c331dfe9f1eb97dae765f76dd3b330c272831803261977ba73d980d5f2be2861920d11965ffeb64f4d6ead47a4929dec8035c2fa344d50098a72f1b8c2e56eac0c2c107405e8f772f0a432ba2e41a26dad3505865f772fb1e116db4c0ed5ee9100e81a15d404fe04bbb37d0f6cebc8d1250efbe9f77723ad241dac9c168b4fb67a02051bf3a8875ffaef5140e04fe812d1934c5e36b16f1bb1fa60cac06df3dcfdf9a8895009e66f758fb864bd5d51694f461b12f08f02a0b61d1b37b93e168e57ea1eb0582b11ff00ce5d63f7d94d6cc7d3dce3a4f5a8e44ae374eacc60b575432ccfd0d2df5d5f52b2211c6d47fbc9e2e4e6bababc25b2e010488f746d9de3246ba1e8a41bee2e3692b414ed4250293575cd59c00f50c18edfa422ffa126e45e3cc49cf0b6803232b545242fba5c7270eb2ba8e163580104585058825fa201d8d7fb05cea5751ee397f506632a73155a89c98767dec522f15107f872c40b804c4f0c1277868a92fead6b59daa65e040eecf351e2d9c8ffdce559e7d9f3faf795ba3c019f13a3b98af4cd8401a35b9846e35c44832def4d516c694b5bac8e1b8c055e21cc81bb04286b0530b642e9af527083d75bf5a8f228b16feadbe61a9f5094a0c7409ec35288e5f228d70466b0e016c7104d92b42782c2d092cebf959efdef934850ecdd40f5676b6624816ab717074593dc120ecd0fdbf7b3c813dc156727ef7680bf8243340c3613b0f43598ef0ce6524ba29c40648a28aeafee3c783f2199f9f243c37046d975d488682c28371f34c21195caa18548fed4c31f1326ad566cac1ff8e788a9c2bda8774a1d6fac601b905c9c1b475f2c651be9335996af0cb54b632732b4332a970fd3365bb304b9911f103e876e55670f76a9ed530acc8dfcbd40032354e58c33ac0cbc1e45941e69d81450cc46c69275b1eae6c14526e4278196230640e04578a83bda630ed54f0a1589bdb937de1ad18b388bd0feec403e9da33667ca0709fb1ce426ca270fffca9871e166462d31523a3d7239571ff68377e32e3b824136b96cedc7b36f7a11bf8d48d52a36f421adfec19a3a22d87c359b6c5b4b9f71f8c8d2e59b58d5b1736dfbf56c4562ca2d57a17d0fd2a90f022a57f6af584d016bb350fd4cde500ce1677c65b14489a30ad9a078242e02686772a31d47ce03ef022f1d70e628bc03ef827ed1928a0a1d30c103183483f6d3171977b8105b70d5a8fd51735c9b53cacaa6ad19c147654e39793642fa2e47f177fe1618227b56eb88e6e43adaa261d3399c8bb9dae912dcc4e2163087c991fd03adcef8ad36bf64bd2f3028f0e4c76ffcbc32561946c65c17d7413093cda366b662e3aad6d8b82237b402bb954d7d2b54cd8af0c54f02486907655b64335bcdf837c9d9507500050c975132361547b9f493d2663f72befe25616c4543c8a2ea0be07a4c8506887bc1f606e26d7da20bb1d1293c246094bbed7ec78d101bc51bc77303028e8eca18f9340a7fc3b181443c4e32f6119a7df06834c2231a159c6631bccb99880a95ee9e03cbcbb42c3fed2d67496b6fc29fa0d0dbf9154d3bac6245e12f369a562dda7036f7556e0d5b9b5aeefacab241df18e5a5744a383ab7f53f7a58a90b0e65a7e29842eb2ce46e9aa8e4b56403120785e88ac5c4faaea3d455da46e4239ac9877545884eb435ab732717c7171e46b70d87a117d074e0e59ba4d127a5a4fd6da7a07b7484e9fdf184ea6125ea713eb389430961e0d61503da2dac5449bbc2df6b9cdde7e2d8e5f93e39c650153ea86a1765f157c91103dc04c64a3952308131b7a0749df52911be5052244bc050e68055a115210687544e980f1671e8052cc97b929b28183571253a62f2f01184090b1a1510107c0a1419a21f954d05ee56170413e1133771f4c19bf76ca5b51c0de7cf5360eddeb02547ff9d6fedfb64f62496b09d972ef131204114911350ee3ceb80e3776d885f1185787ffb8b0cbb8311ee4fe38902be3436e900bb9400ec41d722257c8e90a2e100fe212394dc1a52b3865c2a54b3855c10de2140597a6e0b4c9a52a385de252149c9ee0d226a726b87489d39a4b4f70cae452139c2a7169cd6912973239a5b9548953125c9ac469092ea5f9924b49705abbb4045772971c894b6b1fc15572da844b99f0998bc44370477011dc997fe086e020b8227807ee07ee810b8273e076e049ae076ec4e5c08fb849ae816bc437708f3806ae069e81bb811fb91838929b815fe01e39ad7269135e5e24afc0bdc02d70cb532a2ead720adc0a5c886b8153175c0a9cb6e00af121ee33c55d1a4a0585c1a993fb843ee1f405f70955c2434ac56d41c515a9b8245a58451a836b6b6050a2855ded9a76b313956cad61545c138d2ae1d69c469ff070da1f7ec045728ae874cc0bae8f5327b7c7a9132e7dc26915973ae1f4c9a5559cdee0d227a73cb8f406a73bb89407a749b8b4e704b835d32897ee200a9417b90478012eb539cdc1a53ab8016e91cbdc029cd2e0d21cfc00d7003772654e6770290d8e807b8013718d9cd6e0d2195c0117014fc025a20667c055c017701370075c06bc017701a7b64b9ff803ae035ec46dc029cea5b647e03ee010b845e07c02370297c085c029152eb812386dc19dc087b82d7238ed1040fc6020b014c19630413dfd223bfd223c3f5c6bc35d9bd3b1ce39812d67146cf4071c37387470ece0e0c171c3d18303872387c307c70f0e201c4131b5989a189b989b185b8c4ecc4e0c4fcc94985b0c95989e982a31b8182b31b9982b313e3158627e62b2c400c56889098ad942d6481ab2866c42da904ec81b1287b49139a40e0985dc21a5903ce414f24652217bc82a248eb442e6c82ba40f8985fc21b39040a4163288dcd2640e198dac46d64466237322bb91e1c86cb21c998e0c8a6c472645c6d36410efcba6344957f0beecd62455c1fb322a4dd214bc2feb699236795f56a5498a82f765b826e909de975969922ef1be2cd724ad795f76a5496a82f7653e4d5225de9761699232795ff6d324a5795f96a5499ac4fb32a0266909de9769699292e07d595093b4f6be6c4b934bde9fd59a44e2fd194d934ade9fd53439f3feac499323787f66d3a408de9f39693204efcf6e9a04c1fb339c263ff0feccd6a407de9fe534d981f7673a4d26797f06a5490ebc3fdb69f288f767529a34e2fd194f931b787f36a5490dbc3fbb359981f767549ac4c0fbb39e2691bc3fabd2e491f767b826cbf767569abcc0fbb35c9316787f76a5c90abc3ff36952087c84104ff2e521de9f61699202efcf7e9a9cc0fbb32c4d4ae0fd19509311787fa6a54908bc3f0b6af201efcfb63459c4fb396a4d3ae0fd1c344d36e0fd1c354d32e0fd1c4d9a5cc0fb396c9a54c0fb399c349980f773dc348980f773e03449c4fb396c4d1ee0fd1c394d1a793f874e9306783f07942665decfb1d36491f7734869b200efe7e0699200f80823e81599002c783fc79426a9cdbbe61f92f01fde054d1da8fc0355c27fb8e75365948aff70efa7c99a7fd821ff704aeaf103a636bce5b07b55dac4125a58abb0755299f2031fda14834efff090b2e07ae0cb04c040d486d00ca919d26488cd1027436e86e00cb10dc919a23304ca909d215286f00c9932e43684ca909e215586e0865819921b726588cf102c437e866419023444cb90a0215b88d488d010a921d284880d1127446e88e010b111c9210285c80e11294478884c2172234285480f912a447044ac10c911b942c4870816223f44b2100122a2854810912d3617089a3110c1c1ac21e359c1954d51c195dd527065549a5c590f0aaeacca09ae0cb7c49559a9b9b29c09aeec8a1257e6c3e4cab0d05cd94f125796a504570644822bd352bbb22557b605893bab29b9339a993bab19c19d3511c19dd984e0ce9c80e0ce6e3e7067381eb8335b07ee2c27c99de970e0cea01c71673b46dc99940ddc198f06ee6c4a06eeec86813ba382e4ce7a8edc5995f2ce7017b8332b16b8b35c05eeec0a05ee6c027726813b8bc09d41e0ce1e706745dc99036e8e06dc1c0cb83916707328e0e648c0cd81809b83889be3003787919bc3003787cccd51e4e628c0cd31c4003edb82103d4b3865c2bb09a755deb73a3b96c7defab6a7ca2cae6f73554667f0bef5b13f7d0b54655407efdba02aa350de3fd5aa8c4639ddc1fb279b2aa33c78ff745365f406ef9f6c55469fbc7fd2a9325ac5fba79d2aa34e78ffc45365f409ef9f6e4df678ff44a5491fef9f7a4e554eb8939553ee74e5e473c272fa396539019db49c824e5b50281a540daa49932c9493268fc241f551394dbe9a74f13eaa8fda414941f1a0a634f9f23eead6e48ef751549ac4f13eaaa749f27d5495267b781f8543596912e67d540e75a5491defa37c9a94bd8fc282fa691200efa3b23479e37d14509336de47696932e67d54509334de476d697287f753b5266bbc9fa26932c7fba99a2663efa79a3439e3fd944d933abc9f7292ba6932c6fb299c2661efa76c4dca783f95d3e48f2681406932c8fba99d2685bc9f92d2e41022efa7a63409c4fb21016e104260223a93c68fdb8f9e1fb81fb91f3e3f7e7e00fd080252035203c406c80d105b8d01d101b2038407c80d480f101c90dc930bc407c80f10a01a03d2e306a905a1095213a449109b204e82dc04c109620b921344270894203b41a404e1093225c82d0895203d41aa04c105b1122417e44a109f205882fc04c9120448bc41b404090ab245484d088d901a214d84d8087122e446088e109b901c213a42a008d9112245088f9029426e42a808e9115245084e88152139215784f808c122e4474816214042b4080912728710e0ca80b832225736e4ca845c994e902bcb017265b62bc3917165373227321857a6c395d5c8625796e392352eb9c325b5903197cc42deb824002ec9c3256597d471492b248e9c5db2e79254c84bde2e39a561fd1d97e46958ffe59252c89d869150489d4be690af4be29037a413f2976c42d69064cc9698a0182da61b03149325e627064b8c4fc362aec4e462acc4e062aac4f4c45089b9dd98293d6e0ccf136ecc8e136e8c4e1537c65663313731363cb8313531b528174710948b03480717c74f8de1f0c191bb38703586a3a7c670dc6a0cc78e4e8de1b055b9386e9ac08425f45c98a01aebcec990daa4414447099774a3e2927a9270493f5c52ae61a5485411c19625db006ed98d21d36e99c327f7f32de7146dc87d1eb7cc6125f7c391e8baf449cd4e1a2ccc0b1db2598e9949f4e1ce2c84d1888a16c874bc80a125284d0ae0fdb2b41380972529194ac3786c75c207912443a74800a572ea047ec95027680c6c30831a8d3af1253419dac49c821968b4892fa1d11acc9e538545e5998f8b111f97ebf8a5e7b95ca17b9ee715d1f9bbfcbcd787bf45748ae414b1752f5264e60e355dd84890911f976b048b11a017a5f7ae64ab18081bf21d1aec9c824f1128a48e922db7788bbf70f9e5e0e9e173923f6a339fa9c37b896b321e592d0d13d62f6b6601e17811472ffc39653f6a6c998717b189d2506bd208d08f242669240db30a1f203edbba0b2e0fab5123e31a8c11a0267ddc1a968649fa9862c2fa50e8a961bb63eb86410d63af64eb80a8c1f1b2c6cb4bd84ff281ea5e90aa993a5cdff1b24626c1489f93444265efb39be37673f04c31c939613de0b2fab83539270cf53e15f23deb57c623f3d18303973572e93b7059a3f4132e61222e9f4b0f71f992cda5bb947e1fa9ece1998f0f1e1f3b303e747c48f1b1f3f99872027d40f1b123a5927ed43cfad8f101c5478e0f9b8f1c1f3a3e76423e9af8e069321484dcf73165eaa03e727ce8783e9ad01d3041b3864d93dcdd784bda5597ab3608d64260485c3df1750d8aaeeb44e751337562520125371546c8fdd6fd6c0de68aba846c08b25bceb690630856c72dbb27a0b834f3d69352b9b5110d47cd14b736a27d345f0d638c45d7ad39aca2002e4c002e8e9a0f1866cbd77589fa50c4d6642e92d364edba920bcf49a3882d54c44699e8b0684bc3aadca6eba2b8333396a021c1b291e2ce748d12ac90a3eda8c2072f3cc0e5b01e4edbe2e35de33d27e40e81b7ab7f68b099f459651f1b2c8e2b0d6b2b38720dc3a18322f518338e9e867d6eb0dd5b6577af8531aee1fa853e8cbf5a0d33715094cb22558ba36e8963a7b433394967d62913f72d6a58f22b749abd979687bbee0d3955ef0654b9ebbe4b71a3b8f376e7ed8a92b00515d02812ee0ca9e707c706391a45c2eb2f3c2d581cb347247638f4aca88dd6bb82cd62cb36ece4249d8d1040e6c073bdea9fb5d1b04e44f2f122578c63d2f86a68bc65abf510a9c7f8d5b5356b6b4a59ae8f993b4441b346bf529c56b5d1af7596c7bb4e9fb8b66b43d7b534a3ad95df37eb588adc90fb5df77289adb95c9fd5751b4db6ee3a8ea9c3bbebff785dad0b6b988d1aab0f45b449059834ca84e7e345f6f09c343e5c76178121528fd0b1f850b9e5d84e34a71a161f2ab71c1b4d889e4e58be3c6b139509511016e1cfa943f4f2fb41e573e1f1aeffb8fda0f2ddf47daf2188a04ec8ccc06aacdf893e1b5fe8b3a1d05885cb65452e5125023c650213f18944b714e55aa58a953cab54c1c9a5a84a15284da0c20d19ac7404b996ac1f5d3642744589aa0f43a2e896a42042b94402e730247e241fa21c7228a260974a11dc1c7e7486bcae8a4425efad7b7766307bf4de69137716a5b2c0d6779f2509050161f1c9e1a8dc787672cec9e674a239d58280b0f8e4ce51c98dbbe5a69536c746ebd3624b51108ea0afa649936f92ce20f73f27de3dafc3b8eb3a2038d8205bcff33c4c834f4139f4d2d626ed14d4048609223561431be87c70cbb38a05cc9c4f0da08486e050d5ac9867952a587209d3753eb8e50e8b829070a712a680a2460ba7ed484fd812a36a14b43594886a1aa9091b44954547c21dc7b0851aadabb6f36a0d85bcea853cef0371065459d475dd6c43adf30112b2081fe94e9180843b49b626b2817dee3ad3eae1a4809d5270414b0eddeb817a8d477bae90e772796bb05561a7db15f2401954d4c31f3d4d8efd32498ff747cf0f2ae38f492a000d3d2d5825514257a2e435046da2091cc23214076fa0c6faa1833cb684092a2790e8a4df8a43a1260e0ec136f199c1b2469c2d816424b3ecddf3be1af3b0f7665d519068cb47f3e19bfa23deb18d136c53633a386eb4ec4861859a68cbc520f7bdda8115e34c1a340dab15241159923b0ab3c5ba6c938679af9ff67b47ea913a3dc29d5935c10877096de5051a6de248a4b2203333535d20833604d16690a84105296a3348783c2ed8321e09fa040b545a0fc3ce7bf75c7d80e34377fcaebae5574774f2e8249dc799faaf0b36f47ac13c493f3a7b3749e7d65d0fbf2dd8d1b7052bfac660bd53d287c57ade90ae7b7dd8dd92fea0578842a1fff070d9dd037449765d1778d5d8a3459ac28eb76958e326786c02c6386a3041305b9e604f76ec32784bdce4d946ebfedcc7374d868090fb1867acae7a5fdebbecbd95ba5fed302e5b1826c8470dd95486bcbad1d44c199840b74c67951ccea3e911eea45123dc49f36c94181c219b56d80b1d04b9d69027b2d565abb0a157f0ab2291e82c4843b074e6f1961eae0f2b8b8b4421ef2c58d02a12b110b958dc995d9da509b512328899f87011eea4d12977660689a9051ed0d4423500ddf0a9ebbaaf0aebe22ee2c3872ecee2a3bbc01f4db94588b9d2b08ec98d8e591cf5f0d5be8577121042f70b593d6aad43b0a69a59f8c8eaacbf7cacce7ae8d21c760897aa57ebed4d95d1274fa0624ba64e9aa42ab03da105b5bec8ab2129241e6a931bfc1c3fab0a0751d3b0c61db620b69de8b6f67db6d6d3d7b01f55ee3d755b1b5de3689dd81b5bb335d666732c14bb6379ec94d125a24b9c40fc83ca93541128a2d77a51104d826067c34c2f4bf8fbbddd139cd864d62b0e8aa0ccfaea9414c42a08d62b8feeb112fd5badea14b16e6d2c4d8b2e4bb1169774702987f4038b425d97771f8bbb3cec447c0407c1c7d7abc7b7a4199f9286905e7677c177e6ee8a2baec83749cda3932a1e9d2eaed5d39dd9c5c5c59d191471696f6a21ae380607f647cd176c89c96045ff1e865474c1f715042fc9e1b4400051d3305119ec0f3ba308024f9e510441279730794611845a8609c271f3597b132e71ee4b74dac44be4048e12ca4408844d0e5ec2280d2efaa450b42a8a2ac1561118442d20b000f123b2bd24852d67153e05c0758c480c56741c3c3041b43e0e1d97cbe5ba9f5444a953db5c8d3fb689281450dc275ec2043d815f2516ace3a829b1605162c12a01e153a2503c616bd80ab7f0ad757f35ca84cde64207ff8ceda6033c436d35466f33d879c28d09269ab061fa04b6b6effb1ed227eeab756abbaf167e0d01c58d602830adf5122688a56addf83597d0badb3b6987519b49a3bb27065228aac28af2115d16c2c5f54a7acdcf6c1f7a60b0e52c7742b8b8b8c01760d2c0dbf368cf0a7bb2993a74c8dda98ecdd421ca5deb96015307cdddc1bb5c06bc0b09bfe6498d65ec5d78a6259e7423e24958491499d34b5762ba7823a593bd10344c46d657573df5dbcf2e75a94e8d755f5dca03da58f706a26c3c2fd822265e8087c5c5eb82355d3c1127dac9744db759420b4d97747b5e13f79af83504e9a6cb906efabc09cf449958c6748b67669d9975096d09b5d558f72cd64e1af43f663ea23569f44f9306fdc8f4fa9268125fc2f3bb247136fb3e6b5b2310dba8b1d9a8255eaf9210ce17a5a896bf7f55e6fdf3a1ed93c079f17e567c5fec1b866ed9d5f2f7d12b5a35f6af775ea12fa1811fdd57080b41c3a46fcfa4b19228af2148efcb9026cdf425342c733a88676024159416d0262d0a1d956027adf4f0250cc48f22937ae932fd5209ac99d5d4d8f714265d348d4ebacce824f0a3139e215d7ca3de7df0327df0a33735f61d3cea3351644847e19928af2150efcba0429ff98ec23c4460ca53631f09cfe88078e67b379e311dc416a8b1ef33f63fb31e8f092198210637b0a9d56893d628daa4dde47e66108aa633d1b0032d44c891c10ea200036dd29a471ddd4913ef24d93b6926104791199df4992832e04707df93bf379e8922d32fe119fa7312c633345763df497884677e66684f8d7dff4e836aac2757d29ffc8df02bf4dde6bbb705fbb26b7e6c72f075b9fa85aa9420d7b63b62827dc980ef83b8fba9b1ef5f2e7f2f3e7c4454a31dde203c42ace5eef34519f2c99d41d020f53a29d81904024a6f95ee8c284f95d91aeb7fd356dcf1e4aeb5767884270647f6961d0f908ef5e7cbafbeb4f4650b48cbbaf01f2e77c0e58b4c71f992cb490593f04b3983ca1d4846c4244c575c71c5153422668d515cc25a3644743a352653ea6e705753633c3aa42423d3c8ac3171deaf922e92f0349db484269e92f00ce926fc91644c37e159635d5776359416d24a185663f33c6a6c9e745f32e0fc129a78c3309cb70cd5e4b6c9de8ec713de2e77cb2e57c272d9f1e01178bf9a2aab5d4dcd75353557733a1d4f8eeee4647aafeb78ba1e1de4b2c5d3751dcfdc21546ac2b369d21daa9a8b162c5e5e2eaed6c85aa952a8933595486238023f51c8eb6a4f1a93c6935a71d714e09a501b0338aae5d9cdc096219b1c7a5527776d4adf3755f681a7d84658756c7fab557ab6164f4d7fda306413b2a9df37293d8989772d7b18bc3fdeb4b4fbb634ac83bcd71058fb8228586bb249c36857433554b0e51704d69aa49452f09406822f4a6fca14a499fedb52a3602dc8bbe996b05f50935b483da8775365a3f7433555d6b85a6d095568fdaa437784deaf39983a44f7802786dcf77ee80eda5365dfcd8e67ab329d2a0b4b0f676f351e32e4236a3ea2e6b2ea845a10ba219b9b2afb786a6c0cb3d5e19bca7393c910aad937e4fe7269c8fd7d6d9835fa5b9a0c4d401a9f997df20f19bc5090fdb680b58ea12fbfa027e227c9888867c42b29017811bf8c88279d849584177114ef93169e4e1af8491262f4ec69b1a734e80bfa78aaec6bb5ace5c914fc7255f691e05b22c782dccf55d9a47d5feecb7da00e98f379c1ce5c82b6dc3e5fad16544f40d3905d3065740b3dc3ac8182595730c9faa6344e7433b0b46daaacd2f26c2972d94e6e1968d2d042474d0377f2cc01096f89a85964a035fd3559d653faae6143b0ff6817c54e3abbb29ed69ac52629feba5bc27654b0fd92f6bfb0ebdc3d1f392249979fd45e46282d744a0be11a9116faacafee34bf82987277537e2282109ef55d77dd16a8b17a06dbefa660fb35f49202cdda24adb526f3682b8570be285d70594709bc2237a8c3c34d1a9e1533d6f7b9a2f47680bc9d1a23e514164bef59fcfa3e17d0d411cb34a1d328f1d192a057d0a288ae84a5a55090bd1f7bd4e9fdd1cd8889a9c3236bcd84fdec8ca80f35a7955e8e6690fba32668004aef1cba4f4c475db163f556749fd47c34d353b7c6d24caf2800715370e14af6b217d464596bc09a9f390517aaa4bc2df4a6d6545bcbd3c30dd9c9257ad43ddd5ed3cc47cc49e315c2a5d7535f3276c67e09ed745f32a69f7ec233269ad2516578cb5d8e7e8ca82090e9fe2a71daa430a5b783dca73db0a7975e7a3b5e0e684c3f743d1cd094a7b3e3f17843983b4016cc1a0dda1461ca4017cc58df860d1d74c82187d72b97de4e2a97602a97de4eee1dde6948f2817a1f4cc3947d3de019e60ef06ddf1fe95499ea8d859a5c12b93fdc1b7297a39bbc622919cf6a9d751656c27acbbb122523250d31b25e1ac79f3eb2582f9dc51a29196c7d09e246b630d5055b7e99dad6619fe9f6162bb137e1cf08eaa69bb012d3519856561defe73524d71c76b5bb5af24e6f59b960cb5ae3e95c25a6976eaf12fbd3c3106908fbd327a900a697cea3437b5f32a7db9f6e31e8f392c160aec64ad8de13f642a402340d353f117e0dd1b414085463bab561ca405c8d352e5b2cc87dbb446e8c23416e4ae9c1b07ae0cb1d3e2289cda3839f0ef542ff7aaaecfba9b1befd74aa8cf5d4455cda561e5df00493461fbce0f75365200a26aeca5818aca9b12ebdc3e5ca09eb82efa7d44a610f0762dca534d55ddd1af8f25e1e9e89e27d46f5d23d2c733aea283c93a2295d85678dd19c9ec2205078baa5abf3a24f7d096da7f4d3654a3f9dfe747a0acfdccc1a9b29619bdcb49310a31aea4e5a2a8bf574703069f44db7f76c372508447b3cfc41f976a897c5ea7c553e5cc78c7646525a06d69a91adca4ae568caf759db6a9d5e8e7442a79f4ec37ac433d2a9b1d14eeed1948ef5c11195dcb740b5a6d680401fd996d46ab5daadde996bcd8d2df7ab4edd01816aecdbf9a08040608d4e6e2be080935d795af1069b3c490598b4d3274988d279b4a7c57e54a37454931b04a2b49ec4697b20f598356c9ece1dde67cdf3b586eef0b0f7436b9c60eaa0d813c3a4d147dda679b7b3136c8a0ab60481c0a0516d5433b219dd4c1d941a911a83ade019668dbe07024d1aa41ee03fd1c8f34e29a5dda8e68e6a239a519391cd1d3969d8e866d210832dc19adc3fd5ec8d2df7c19a2a13e56aacef63f373934540a0ad69253c6bece645c1fe7c22fad2bd97f4220c6ab960100884c120100804aa354d023549df07b58041222f8b07d431fd5418eccb068e86f5ef2c5765a5d79a9e2afb6c361d1defa79c3da5f7537a3f3543545a098b523fb60481bc1f108807182c7d39730997880dbbc2060e526a778277b9fbc25ef461b8e2170da3366c606f592958db9a4da91bc2f922043fdfaab251f8f979f18654fc6cebb449731a466988e29aa4a110b54273f4f4d643ab3459f3b4e24a96204ab1644ae9964c1ff23abad364d93599523a25d31e4f66cbd28f2eec9fd9b001e446448d51216a8c96544747d498e28830ad293f27d487d234f94c3740675011dd36a10e4911ce17e5a4422d3765a28927a440821192b091c28d3643841b2148f1c1691358c7064c6e5ad8a151197c864ef90c1251eca3b0384e13d40999286e472802cf108200841f9c42815f323487e2e034e721b5e18034b0254cd0f759db6a1d96652f4ea051284e6d7726004750a246a3b0a38cca13f7042ae88eaec9a8ed50c8d65663b6d6b0198a736a63820da4e49a4bd1ec98909325f7b1cdc97d11e3d0286c2887324c502331e2a15128b0d5e99828d6e6e410b4d91958ef211cebcdaf8631c67848975ab4050787da70985091676b1cc7f1e3776852f5f1369a043f8ee338cbb33c8edd2a23d8ee4586919e52e52a665ceac69212b61bf20a02825f92435f92434fec6ec906848bbf8284c0491ae2e221300482e08f9e4f06d5131b17d119e2c27b68a5d81d0b45a7e632ad3c6c733e9bafa6615fed6bf2d57c4ebe8e32713d27b6105443a34e5cda821e1aae4d1da4dc2feb4daf33a0020e07a526e49ca49a90a369d089759df4bdbb2aaf4dd77ae04d9325c581030707a914fa1cdf3ae9d61d7c74b36124ece23041ae5b334c0983a911b72aea632935964a6329350ea9797c38deb248fec649c3f5f200301f2ff2f3888d98c9df87f113ca04ca7b290a0aa289574791687cf98944f75c6f2c72fd7be8fa3cef7b6dcf1b7f27ee1dc4e5f7fb16a7a41ea58a65c2b9f716c9b14a763292592ed99c687191cc32f8d62d81e4d6c3975c5f34f9dd8523a4b547d7d557dc9540f22c03c9ddf84afae1baeb15c36aeb6bdda576b5eb4cb55ba96ad7d5aeab5dd77decbacef57a69aedd57ffd5cfd5d5175ded304be472d6c1695729f0299e09b678cbf4d651aa79c4bbe85fe8d6ea95b31cbaa17bf7fbbeefc7f7bd03cf52a9bc7778ace2d575278544f744de90ea795ee781a07745f71efefd786f049243f780e40ffca853fd43327bbd928250bdc34754fff011129259ee1e9a6555259d75daa1f0ea1d2ef157a6560b1c89ad9609974a46abae458bafba166fdd16a977ddc3d5bb554bf4d04ddd754b20d9753abb7c4175fda249d5bbc39a34bdfb0e2dc3d135290895ea23fe83944ca65cc751e5fa777f186c878ed5cf16285c5a126eb56c2fb363a52ad7faae63f5a56b32bdab3d54dd55aa20ba17b09aa259848fa43c5290148864267acae5ddaf761f2f0e1b3676d801067bf1e2b9bee4ee2557d378d59d0d1b4d4fe1d2aa7069ab6aecd888cb8f052423992199e5d05da24f11f87a447410043b74cf0b853c0fd7f3a839d51948eebc877496bb6e8a4e3bd17974052f9e0611368585483fbe632af27089448723878e732a6573eaba7cf5bad42299650fd0ecf25689442eb33eba251097b36e919c223a0dcb157f345b445bbeda27e65254bb104f6ddd5a71501470f5365de470eac49d341737a4f5da1a4d17ea70e9e1ba3e84b1ade9d0604b5b13ddefacefbbaa775d474941a617f2878f883e73489f70820d4d78a116faa0595461d9d696280245ab886dfc5c456c1d451128ba771786dcd52872f752746fb9fbc05b77a81fd679d49a475c7a51d428ba3020f170393ccd93d4e3d2279cd851850f54571479a0578a60a77aaed77b1edde1b256b07ab5e2102e978440f02e570d55d7fd701011ec8860874775b9d48b30087a1849e7e1eaebe5795e7d7749ffbe57afc7abd264eb1d7e0882202e4558f4934d17ad2a88435e95868570e8e18d87ab9e87c4c379d5f3de79b81cba2874450f1de7ba0bebdff540f53c6f75ef617bb54728f40f24b9eee260902a029d5cb2eec2483c5cf670797516e9ceec61d279f4185e75f1a5168987cb1ea0f9fe756d7671cb24b9ccbacb2d45b093599f39c4b64664ddd14732b0254c10ae0663f872e8c329a987004e493f3abbae6a812d6dcde5c303f09b1f330c838ca0572440f49934fa25439d30c1961ddcac200351f744fded993e716928ce4557c64d06151c1c9cd42da2532407a7888956e25acdf5b6c8b7cc3aaed558bd35ac0895225468a619d7ba7fb5bb97ebbaae3b580aaae899c20c03089a3a6e9ee28a9b1b4213d812d7706a6c9aacdf6b165dc66deae88c904680568ff13375d4c3b84d1daddba0289154365589f4b2640b79260dd4cb59458d27e39934eacd5682a28a82429e8ac555cf0ab7cad5d8ca6785a5619da5e9ba892ae08f9b1f4e7ea4b2ea67d2e8ffa8f9e81318c6d66ae150f158f033b33e9248e4c1047561b8658da2ecc2904b5cf3a2c8250e40780bc05db6b4d3b02e4109c0bbfbe003a636001705c08700e092949d9e82869d1d9829f210a7bdc7cb2ff34802154ce0d89e80a20633a0410e740025ca0e787083275538813aa12fa02da02e98800422008107d434b171728363cbd181b2238567caad4902bc9f834a933fbc9fa3a7ca28eefd1cb826690cb430ba29404ff7c0e5e7e3ddedf1d0adf76ef7ef865ca2b7aeeb63ebaa3b3e7557375dd54937f5d2359d754947ddd27f596f7151c7f7bfb7c55f17dfe5de8feeeb2eaecbc53b7a28fe74c3e3b82fdf714fefe1e23879771ce6f6f0d925afe3c2fc874b6dfee2cecec3d571d97df11b978703e0ca1e736fdcc605c077b831a74bb8b4e734ae8de7b83bbcc6a511bb0163adc91197ac87a69709fbe86cfaea75a749ea84adda749a9c4ed0f1c9526ef5b54a9339186431adc6b90a71c29b500f952c8ae23b5765b3d0e7def08aadca6698eed45893e3b1e4152ec78b6765800665d327a987c95ec4250dcaa2e95f93ab5449b3c8661fc7afcbe3272e91d0a0cc7ac7ba5fc3560fc35c980b7dc25c690896f592eed01d4c791a5677f2bcca89f8b2daaae4b2cbe2cb8f27d7ab6eead29f8689475d9aa561e2679702d59878c242946e6f29be74d32d91a8c9a278ba43797255466ba14fe986380dab27ddf0a66135b4d5978060cbf026575bcda93a154adda9dead3cb74e6958bdaa66bd3cab680319449f3c7340e25b12d3140c57a095d64a2be5d1b0a69452ea5d242fd9fba161d4a3970710d1862f397585f55abc3473c68c4678d6b09eb9444cfbe511eea1612dc4474358860bf607204d5f5e2ca10539dd4b1645d112483dbad2d9253197ad37f9d230cf0996c59481333675d04cef9a64678521e45091e98b4c2fced0ab1df889be1aab2705f1bdbbb47be9bcc621f1487d0bf6f255f0f4fb5aad975615e156a8de9687e7297dc368cbeb2a9d5ea971eb4dceafc315846eaa0e43a15a6b855d55e8a5b5a1fa83fff045b3139d7eb588c69d6d55ab0bbdd65a6711e6ad23418bb445b145da95d4e33bbd73f6254564d181344971ada25863f522fdf7dd1f906079344c88b0e22a5845cde38726bfd71a529cc4cbddf81524d4d8035e16e11e1a16c262c3481d89da4251a0308f7edf9c457ca26f92a88d1da4d872deca598923f767331caf6d10c3ed0b1fd0d441e79c7427cf9e37794e1b35d67306e5f98913a28ea814fd53635d6d6aac3b5cbe15c2f9c3a08dba93cb7e41cbc62637aefe7cb6d5fa742ebaad75b353f37dd6b6ca0f975b9413ede0aa6cd2723edfcfa7b313f2e980443555c6048914cdc55de860928e8d846d37673243baa9319b960baca4450b2c12d58872553613e35dadc56beb9d0bfcd572e7f37363c3935b14c2a5ad38d712edd0497bcbbbb580bcdb8e17d4c353c3dd6aac732dcf0727caed64a086424516bcd0840a9840eb7f3b55565fe0862d4f72f0841434aa040aaa7045d01553a0f50d2530c1852b94a042a34268830b6ad4d0829a77239ba1349288df2e0e54ea774125ac8484bb1e385841aa91b012117738b146c44a30ee72ef7b36182b71813b9f1aeb6325adeeaed655516ed2e8e77277bf11dde98df531278d979dcecc94095b76b5ce065f24954c27dbd95029d58a35b6b88bf7bb9a96cbe5c5e2e530deef6e680b17bf2f72387ec7c03070c8eb660c5da95863cb356fd0b3b8dfbc41ff7245e0289c37e85b579c37e8c7eb326fd0b3ee6bdea05fdd9779835e7559cc1bf4a9dbe2ba9837e84fb7346fd0db4b9a37e84dd7346fd097ae9d37e849f7346fd08b17356fd00f68d4e317a80dac93218207102245200141b78d26cb6f5683a3073ae7acf8c51351f7cb27da6c219c2faae759a0876e8088222400021a9b2d354e2890792362a592eacc0109e5fe0f441431b3781e908655212eb6f2e8f4a42b228165218850c10299317a22663d34387375f650c48ce210eea1c9faea514adf613103b0dcc35765a351fefa634271d8e8bc50a8ebeeeeeeeef6bafe6156e9cb94c660c559ee22cc7a689262dc6ac15e58951ac2f9e2457d0993427928147aa35572dd7dc5eb604df6cd0e3866487586a83411a63634d89252db9c342a8dded07753fcd2ea68d7e473bf6d4f3041cb0f13b4f8e850b39f04b2f7524a202379c9defba6b6a87055368262c36ed7b21deb8bee6cd8c41f92975cd229d96c29e70d3eed2385dc75fc5785f55ee9c3f2eb545654b98ea127e5d821f3b36165bf76259d528ea7c2f9b870ab04e5c9f87ee9b3d94a1f948f0ab9e252f5e30415d0a9c2e5364561cbcf966914d6cba2dcb9a10b43e2904af2315f3f61debda6def4ba128f1e7144b12797259e9d86d17b9d25e5c984279a20821513545d79819b3a6ad4ea795ed787ba2f3a8c5a2fe4816ff02bf1745ddfd640258761e312f68d2f55563cd1f7b55a9d0a17c222efeda9705f89a76125290da3b9fc3edbd441fbde3d1e3df1115e4602cb259e1ff3a51560c85292528252069dec932b834d85c5b392bbe223127d390c892937d826a9952647175de593290c96bd97cfdd2df02e77ded7587dcbfbe72181656a1bec3e58eefe9186b8aa7ce107b9fbf224f508cfa3c39118ea3e5b28a4c272a5c91aeaaaadc932062e7f5032fdfcc426f9980f85fe8d4e5f82d2a4e8529aac2728e549e7d21c5e9a47774e1849b43549c2a1ad61540c73e6e97b8557893eaa2baa9f2690008b0a885eb56555a3d292e9aa96e9aa49a60f479fe863fb72442ca114d420775885b3d2065b86dd8479b40441e8cefab03f9e3ecc69b2f129a76123f63c1b0f2714c2d2e433c5350154850876f4b1922baea993ecfd25c438fe65a435be62d797b42e33bef56e6ced9297cbf5e2f2ba0b1def78d78db4ee8295b8bc7517561245c6054f0a2ec18e6ffdd5afc6af215c77b911d75db0922832afbb5cc9cb5d37e27216678195bcf0efebfee5b0c7cadbb0d1ba2fef2f215efc5580497bf19711da032b78c0248b4ead4683f1f1be78937a0841c364bc8b33195d7f5dc6f597eb8d6558fc05cff0a0fde57305285ad6606b41ff72ffba2c3ede288d5f438ca3cbc4b5f88885b8ebad3796799d059e61f1d7c7cf449179715d66bc0b88059e29620377915ac20b49b0620bb65a0d07ce1c3120820c5aa0022ad8d230815cdc497bb993d6ba93f6ba9336692c26ed51645a1f3f8e77b9cc7897d136be059ea1354c6de34b5a1bb14dd7a86dd24e4a60e142197c6ab4b26bb96d668d814bb0321ee332f0abbf841603db4a221ceca4bd8c50da784a1beffaeb51645cde7aab75d7655a77e19928ddc23899d65f7886ee505ceb25dd51124546890bbf647edfc22f23f8f718cf447909d17a0126ad45676a9ad63a12b55ffc9219effa7817fe6c35065463b4854b30be66c3cad54da6b779e25ac7b6059b4fb732ae8da0e369abbadb464bae3662c8de3b3be21c70945285f369ece18fe3ed6c785c3b2730f769636a3dfc129de69b6d4e80b6f528a5dbd088264a684ef1a525791f5659b92a5cd761552e54c225cd73da6e6b18fdaec4696311aa5cabd5ed8560d72a2b399267d3649f5e852be594743aa6e9f79d6c275b8d559cc4cb5f4ec3e8676bb2e257dbbe9c2641fcead34fa7490feba482ac2aa7b2d2b0141b6c875fcdd3b0290d6b9edb13526867536354147a3677e65085abb2920d4a53294a498a29f784614a13954f932955aec9d91306285832bd926977b2b54eb6ef6453e1e8186c49678787de443378284f29aab8c9a93c7bc25025cf0ce62945152bc8a56aacc2d6dae7528636920f3a032bfa94684fc6956c259b4fa639dbf8646b526a0db68c818b81abb22e06aeb38981eb80328d81ebc95e577be6d096c31797bbbc58906a412c5e414055c6c475164c5cfd4963e282459f1aa358890b8b3f5db22961328e7789f11c943079bd5cb092d1e52fee72fca284c9cbcb5f87f1978bdfdf98b47812ae3369e1022b797939ec2f327eac84098b27e19a34262c3e530343938195b4705dc65d31b01216984912e399b0788cb3b88bcfa861f2d85b9cc600ea183f5e0c1fd18c193846ee2dee8cd88d8183dd193f33806604c1c801c900daa13070208c9eef4c5a6018b71aab32262d9ec488952441afa045a99f34262d300c9ed74b6fac11348b94095b966cf539b8c9658c077603944b19403376aa2cf67da2193bde8c9d98cfcbd84fcce7964b9f0dc5b1258c1df14724c5c0d1262ccd25eca7940104fb81dd327dc9d662d471b9aa566374e775cce279f955b5c04a5c3f56c2e22e280b3cc78b76be7c75d1077673acaabdcc9caa4ced883ea932258a3e285c4ea05ca660375596b2f1cd4ad8cded26b5737a194055f67dd6a6401940a2cf0c7aad58147d1a8b3eb99716a7175d4e2ffe8ce35d4017835e989e547be5f0172e3a7cc6e9493b5536f322d554d98c6bbeb8fc8595a03418af97249fd7eb315e5e927e64b078490262c1e2b016b197a4a01831fe7a39733264fce5e5f4816125280d76162fe74f0c2b4169b1bbf85fdab8c72f6739fc850e78c60c3c43a7c6e88b3b23873ba3e7ceb8a9b119b7193633786a0c3723a8c67a6600d5d86dc64f8df1ccf0a9b13b237767d4dc193b35562a61eca44a183b319f9d72464da68ff98c2fa78ffd8cafc3c8d518057229c5825ce28cda387ed6d8e82f2fa72f18066e66c4307a665c18c62d74c1305c273d8661ec50170c23575dd80629c6339bb75cc2d889f1cc9e1ce3c9f4a59e2a9b412245ab81a1e12a9b79398bd39774aa6c667c8bd39776aa6cc67517a72ff154d9ccebf7f4a55b95cdb8fc87038ea684c55f6cb4f8387371570e2fe76da6068696c3fdeb18cf080088a6e47779397b9cb0f386839e5cce20109733e8de183fbf315cdc182d6e8cdc8df1726304d518fdebbab8666309a8ca640001fdfcf8f8cc5ac698b9984d0c5ca68fd97662373a319b140c522f48399937e867c77c36c881e2064f70908a418a8954132927523839d00194283be0416a062919a4685083271aaca732b025ec27d3973076323d2c28f47a0b172fc7f7ae1a9146a3c48c96c35fc0882103e6f2f1f430a0ea8acdd081c50eb11aad86ba8c344ea3448b0680d3286169364ea3c4470ffba9b224ea15575c41a3840dda0d8c5a038c8652c3bc414fa3c469282df3063d0ae8366e8ac9bc415fe3a668e60dfad74d25316fd003e0a6949837e869dc9409e60d7a979b5a62dea0dfe1a2d8306fd0eb70516d9837e8675c941be60dfad845bd61dea0775dd49679831e7653279837e865dc140ae60dfa1837d564dea0877153299837e85fdc940ae60dfa1c6e6a05f3063dbea838cc1bf4f7a2e0306fd0ffa2ae9837e85ddc1409e60dfa163755827963de189dc59df38678233c1d839db75ca2f294a28a1a9488cb2fc4a51de1b27558c5a58d5ca2801a0574b23d97219f4c0fe68983c2964d3f26314c1df53db9f46c42569834e8fb8672b406bd4bfd115d97cbcfe6d3b035d8f264cb27dbf7593b4f369c67f379a3976e6169470cb6a493d330180d83edf2b4220c4ce452853bd95a5e49a7c952f4c9f4743c7dc926834cc31d9d4c5fba3539ad08031032bde853652ff093e63a09972528998ab854e5b264c365698acd235c967059aad2b7eea9317aa3a2c6752e67a9ca878ab00a47475cb1adca5456cc187d156c5bc8f4aa30647adb4ea69f4d859b34e8d5502281e5face664519a8bca443ead1ff5e8d4b39b964d3b29382ef43fa48e775dd7fd48770d9a2920e15897029a7613995065baa70369f2e553f2a5c7b4d9aac7836acb3f52dbd5aa61f7e3256db783a1e2877b685a394255b471bb10a5763f468b065c986dbe9924d8553e5aaac64ab31facfda926d54e15eae6ae3cc58b2b5f04bc635d3baab64a3fd9219c72fa1b5ee4ba6d53f5f429be06936ccfbcb88ab75d727ed65c445c978974fdaf4b0e449fa31a5808295724a81f3e97ba4e257101f72df87dc437cc04744ef50c8039d8fd4fb985240c1ca24f579b40fb9de2905ce27b7eea48d77d2fa6ec0873cef725f46c6b7dec24a5c3e7ed25cf7654489eb2d22eacd4bc6f5d75f78c6853ba8a5c211e162f39269dd75179ea9ad11ab54b84c1b4887d71256d39a2b84f3856745ef6ba36114cf1a363f6dcc3aef55846dd0bff33142f67009cb738672d8d949fa4173cf17131f99b73850d18326b994e927a59709e7bb36dcb4a1494ed25da110242527e9dc81564e6233fd92a6488447742d7b9f2fca13509eb9248a253c539a012f8ebe84d6d948f7a84d27be3fef6747adcf46c234143783ec616ad389e20e36a72a0b69383a827d4df032227e4df032af214607ff9a586674f02513bef4b0f425b4109cb470563a6be935eb65689e57625faa7808515412656299d2ed9588275d4994c632f6a52b215d7c686feba3d985763c7a030deb68ad611da5a9692f8b05df752f696e7c497ba82da5623d1c417b5d0e5ed74322ba773e3e4454d9a475210c82c649a84dc3bac6d449c3ba9b8ea136dd976269581722853e49428046f4277843ddfb1660d2682e0796e48a8f787d584422a2ca5ef32e45541978d265c0933e4f22dd05cfb44e72f90ce96065f710fe91eead978685ddbd6c89f091ee21ecdd0375fe48d76ad2c3df0bc53f669eef8c10e57a1a0a838d8aa3619f48f1a435e8e7b511f2406b50bca4e7c5df39b0248721bef3f3b4e61089fc4d1bb99c1789c196a6f7612651d8a41e9f3864499e37bc25cd33fc313f3a8f5e92a74874bbab4860a100e5e709852a724cf5f3a2e8ce1c86176fb9248befeeafbbbbfba65b6bf7f7d52aaa221ee88e32cc8d79a035c2f0a5cd94149654b6d58735f94244ea51c23cd01afdbd6ffdbcce1e2cbbee11d87734baa193ae78f036052f5ed279d4f0d68fae77f076fe6a99a42b8e4c9ac2f63d23ea15af7e97f1ac4178c3ba61270a02f59b7cf10072910d6eb05ab672abce395b2d6b7974a7f56b5867f1c7a3ca5c33565f6faeefea0d1eb53569d4ea23844c713973b5daee9fd864f7da4d9f4abd9a8e44f292eb5f2ca1053678a13ed8b2951b96a353ed0f72a9cafdc9640a2fd4f28c620558f20e794e81c54adec9f41268d99725cf17d164f756cbda3c3f65e0adf298b2d0d763719382b727a7ff49cd6927fcb23437a5b4fb8dcb226ab9ebbbfb7b0d7d66efe1b44f4ed7c12e7666f0d6302a1da32095122e93e4d21b97fdeeb41fbeec6ec220957741803db7c613bcd5d24522de54032b026f2015b087e62e8b3a7bd0c6ce5cea42f1a48f1e96eecca597a0351d0ce9580b8220088220167a300b103db8a565a8d35b5389b60f9426e912a74ced056f17ecc12015d10b22e127a7d37b5b9a14319582c31f1abef36e21066f1a46412761b0f5256853bfa3eee882a26e51fe2ab62a5be360cb2f67536560143346bf844c6f057db5016f93060de9dc423c219d934ea66f7567513885a394e08dd657f7a0ae136b55469f843f6117b264fa504b93a44cc54ce7145bc07122ae8056bec865f843a7d002197229dea820fcc9f45d6d273c37379c9e1ae09ec83559361499beec9c4ccbd602d094d26343adc9f2b3d2354d96e00a323d3db882a9a35399d21d4aa5ca8b5cd29d2b587ac825dda15ae896501172d9346537c9b7711b214f78036fe00e6893e93f2b4d965fd097cbf41e1b78dc6e38518f0817d209d5784199961eced3c2e9939480aed14eb8881aa3a86fa0c6e8c4429bb413c908ea28fc9a0d5b42f3c9b4da649f1af3c9b475a0a8d1d49ef06a7deb5b4d939a0673b7aec1d431b13c417d9212507d6ab51aed74d4ad51a05a8d76c2484c2cb42814a856cb8d5fd4c6890d88431de7060787c2f5767abf6f6c394e9aa414c4d1aee212cc650adee80937a659dcb17d69c083ed19e17aaa8cac3479eac42e0716f5260dab219a508d18aa7941e228b2be9aa7d5a9eeac4ea7551576ba4fac55cd24031a7a7a5d8d2c1d209f2ca3eaab87a6f9a2147d5e58e4f0c2e5d57285a6348ca76156d86f09d68707e0f4a9ac95825804fb0ae265d6bdccc2f5e18d986b4ed501a36067c34e387b3a8fbaba25890756e5c303002ba9424f0b76f61d7fc2ea3c5adc716737447d9252b8de268d265814668255b154afa5d59bb46367e1956ab30d93ba09b55afda836b1f4d52d9354fb85dc8fd5552bcc1a7f3aebaa6ed730f1a66beadbdbe5d215dfabd761ee4bfcccacd7aa336fe1959c4f155b77a0c865e5e1c91493eecce2ed151f7a5600dff130b7e32c4ca461f5401a56b930e77bb55aad2c8ab4e3df14bb3aea2f3d5cc1c0bcec72ea299887ab956965c2af20ac9bfe8375530a0573d585097d72a4a6a208845cb236a516d8d930fb53dd11c0c5a1db4c4e8928f12cd44b168bf5954f932c93655df5d07425975bddc7b43a6b95f359d9429c52d0ecab9f6caec8e5930d1f643b8aa214b6ec7239ea114791aac48faa97e3570fc795f851fc91b17edfc8faea212bc41157acd56a1c45d5a8a7ed4f2e43a071a4695845bd87a73ead288ae111435017cfbaeae2593708d4c59b82a02e76875a14a4ba61b1ae22b170c9ba8975d24b9369089675d38f98aeb25f994653ca64c2a5fde9a1bda10de726bc61a97eba3db154372a5c3edfd11629552c8d7a6adb1daf1771f38d59238b854576f695955cbfe38ab88cba885f3e6816a261f31c5822d3b07adc4f0f98a66d4890c3dc0cd3505c13f20a975f10f325cd22ee5cf0701e2dabd23305bb628922ab13c3789309533b9e47b3467c4497937459bc6a14e4d51ae6d5d0e43a8e5144550aec2ca65e9c22959689b81ab369927cbdd8a4c998d78b354dea70fc7ab1d6648c2d4deec0d3a428e2aa885344282d0b126d4d96c24f140ab5884e9abc52c49c5c459d5c6fb28d97224eaea6d1645a9956a3ea4e964aa53aab1345964ac50349c562b1583c9cc522c1fc4678e3863698df0802e6476e1c00e7d1a10d009ff19f26c7d59db93b87351a311a8f3dc61a59acd56763c10f6b3586376129627b581e6de471a6c2e5c76a59f1c2fc803db4350903a362adc21cccfff037c481912143860c924a942103dbf3a83097e626895d3ebdcd9f3f8c0ae62c981eb187302edea41ea26a493e51d643167e0d19cffa8ff12cccfa924cc31657979a9698300fb4868ac65537767bcb679877241fb0c360171f6378b48506ec962e6e00e0ce7c83ae6edc18c771bcf1199e08801be61a36e3c60d179dba3163c68c192e3e63c6388e2b312ce5c096614ebc0d517c3d690aeb81ce221eabb0233e827aeaa88ba7a38914848d2d3d4936cea34555133b6fa3b3a1d88363994cabd56a65baaaa7cac2dc1519589a4d26d62a6552ad542bd50a9749bcbc3a8cab2eaa5658bcab5b8a47b19eba250b75d97dad3ef36b85431c5b0ca68ed5c7af2ede51145160c71358f1e3a85a625ce1d79079a4c6bf294c11bf885840ee0787b3835c864039f276400dab8fb91d161d6ef7531fe376a18f88bb36ae0d5415828d0ec70d733e0d1b592947b85c57678d82562ad5aaaba862ad4641b59086c403c88551c4a32a0dab220ec79d3c5c69587d0e756eb65c863bb93ebc1151e7d12e7c543189975d5c6a5ddc206f14ea75facc2c1cda54f984431cd40d6f6a6c19e66e315883ad4a142dbe9b1b9c8f146a11ad6e563f2db610af125595d4a3f41697e61ab7a3f9c3819d1d5ef1f9c11222829651c4d5707eb0785bb4dce787f26811c5152994225adb6afd6578339b658fd423d4123a85360dabe5ea6119e682ac70586b028a739ec4d528ae2a6e6ad991c20a352af5ab5134d583a19349a35628577dbc631556fc0a3f99893527cce1f1e2eae36b6858173fdad230160e6bb8dac29a1aab2f439a5c8fbaf9465beac39a26a14d93a121e4fad0c9f7adc49528be493dc4954d1c2f001ce5c55289e2ca268e575d0914d1b0e9b31a5faab1b9d17483634bdd04f330ccc96ce01f3fc28e20d921d323d921dbdb2659f808bd7d7d18a2b038b65830d878841e75d6533f8d678d2c152bc8eaaaff585d7562b16ee2d1a9b36e6a1c572f58b87c16516f7bd48f15b6289ac3d4ed2ea38e52dd23a2eaa43ae15790f1a7ff187f52e152bce94b72ea2cd6f8fa0265432cb99e47df1729b4e5aa6c565947ab7f91de651286b9e14d106e3613b48a892dab8d94ba28fe1b6f8a762bf12b988c2349c1dc230121d94fd290d2e9c73b5387dd20d5a60e93ba8c8bc41ee67d49f735248bf808cc29cc510f6df6e3f8af49f1a3eaa487aa1bda703c5c7813de88e5a9b4b4ebef889ac597ab8baf46d46cbfba48ec51afb0874840a60cb1cb3c2aeaceac325d2366b2bd8c6b0fb3ef9ba4b3c51ba0579534a77006e84b0f6f98946e706ca43858d63ba8611547063c2f3b59acef5a566d1dab4f9d964b72c9baea20689f2c8a399a1d7aa5268b2d9e475d5d23409057b94422ab8c10e5152e39b024a74e5525921db28ac6aa9efa91d44741a9d3875526af2ede72072c630b05db21b31efab06e88c58965dd7e927e8457b0549b78f1a88b3f8937bdc8e255ddba4876c8a9db7b44977158eb3bda92045b8e825e43c43f146f06ee4bb81cff87d3ae26698b8d1d7bba0d9b18d0f0340ce663f598ea07364fe8f9a937a9c6514bc36a9865bc2150c3c29f86d5d0671c028d571a373d6c71746bf284eb9747d5e9361e9eeee8369a727a39e2c995e73cda24fe23824954d17819e66e246165bcc5554f661f733f658b94f1d9b2514f8dd58faa9e9f2aab36f11497add4a8e7335528262ce65458b412c50a60c7492fc39b2a1300eee1fb76608ccbd5612f5b79e615ebd2b832ee8d5b8659727dec26f1b228daf879f418e474144f6d5c9a61770465c61de9f08c6ea73b473b1f0fec142b7ef532cced8ce3388eaf95555cddd196511069b4a508f6c5fa92ccba95a3a0515068c3218ed8e5f0fbac6de582465b9a64bd3eacb15897da9135ae6ed519718bf835a4cbe2bb2ce297f825590c6a589d7975bb1c4ed224ad70cd1171129a7b88a34f16a026c5bf443cc28dac8c775465d4d3a637fde9a1c964b237a554b7aa9f6e69b3eaa1c96432a5542a7c3a8f9aa2b74db7eb3ad53fdd4ef5272945eaba4930624ef4e9987f55580f9c4eeaa7a8e9f4ce86a56e69b3e9743a5d4cddd4258527d249a148eb59f774bb86914817efe4d1a74bb2d744fa249970e80373bb0c73672691707805c46243531a56619c66d88921a94798d3b09b94a5f674f13451523feaa5788b6b8e78abceada78b3f22e24a71b5555bb5d59caa633f7bfaec863e21ea863837b4d9c08a399b3aec5f8ed5e135f77a3a9df0c8863a35568fa271e3a76be3e0147bea7c6b5215ba356c8aaaf2dc20f6d8c597b4266753a3a0dc2d4ee1d2e648241cd6465ba0b0e243128fade18d0c989736c37ec37a65590c834bdbcaac9370d9caa71e285c6d93464d9dc09b058190431202d8052bfe846bad44b02238c5d22c5e55022bbe1cf5e43ac576165fb259f12a12d872d45349281e6cbcd6787da813426992c6ebc39da903957ad979c6e7dc31faa135ea679c70a31fba23ccd11ab5739453ea3cdcb835a7ea542895c6ad527274c79c357678dde1658739a737a148a932cca1aeaa61a857294d76bdd5fa4a0557afd49352a872548e74723d5de2942b0a579e49a396a39f3cfa6992e227b3d78fb234694741265448d3b09afa896734a5c91416730daba2952358f1a5880bd5da34149a5f49c430ae62dd23e80ed5f6e970cb3027d7cfb8a52b97e14decbee8cc14ca386fa19b08c3b66c9381473d4dce1c4e2b7e927a545bd5695815671eefcc3060e011873e38bcd2b00f8a9d7f71bf1cee872f58bb17fc05afb8b8608b3bb269583d8b3b7ab9a300dcd04f8dd5fb1002caf5af3bbb86a56e2aa9546311232e9fc7d756abb42a1ce28ce3c79b3eded096c4cb25d5582a89f8882e9fbec3040d0b8bb77c1657abd50a97e24defe1eeb873c666b714df3a25f910af3a8fcaba25d5a5a41ea687a64bed29c84b9fa4d30977a4212eaeb8829a4a3f994ca20e9164bd146fc2e30d6fc48fa7950d158e8272fd28a849d4ebc39b26c5d78738a2388ab8ec7292cea8f0c7a78920e432040a732bf165985badc6873fe14e98f3b192eb432c4d66096a723ec1e60a8d68f3704baedd136ccc904bb126d727b0c02697a2935cbf1a451fa872491e555fb52ecde25d3df469b2f43a7bf9e5d1e6711c71eb3ddc39633bae188644d70daff8d852e9612ef52605a1fa78f1ae70d9f9305d3c8fa639cc3579a5c9d6eb439f71643df5162908d5595f5d119777bc94d46334dd72c4350dab17ff0a325efcf8d343f1aace9a5925e9bcfae9e24d434c67e1d5254561c7ab2e9e9ea4b34a342dc9e3bb2c8a3f8db75442fa517329e2f21b6f79251b2893e41204799cc9e3a7f8f1532cabc8a38ab766d63d620408b2ea338ff7618ba328974bb2eaab6b8428aba8154f6227aadea93c9ba7d364f87a0f0a786b924a93ddebbd9eeae9c05172e02865b53539bf238a95477cb589e2bcdd4777784a41b065a8673ed4c33a123579bc784551bc25cd92591fef8ae66422d8b2da464ca534acf2744c2d19c1da9db1f2e45a6db58e39204dae07eb5d7202ae1fa8a4cb52d8c11e854ca1110018000000000314002030180c0705a3018148284b92420f14800c8fbe5880541847494e29650c210488000000000000000d0001eeca73000074b226b10a76da5696f1a6847f414268f96c5b45dbe27df3c6fe8f9733f0568925615347c77567d043d29df1c737267b6ac836b2ba37424be6f7877ddb3a0c47e904ac215bc402ab38dc9d1199e8ab30902179f21502f64cd36ccc2051e134f6207873f19a78b64af87ec4e8c0c0c0b7509ff868cc6e54c744824dbf1f22b38f9149e0806c9d71d76942c08b83f8c83b556700c247ad79e58930aa684cade3dbd44ed1c0661702440765e2277e3b19ba1713e9307dcf7be70005c3c9f53b8025f976487f403c1b31072f0ea59075cbb9815ac1800f00575a175081a4931f8b4018f4b19435c09aa180f9861e41fceb0836b0720df3353d3d9fc03cf17a4483fe50e8cfc2d7175fde6c19fec8c854572fbb2d767f1fa4dbb2156341581b83de63fa0608c936ea790554432465724e6c4bd4a41c4c1c6e2b3f466b32f12793781fc36b7d391de27a33d105d44c561bbce9a6d7150a6ecd84266550acd17ced23756b2999c16f42564c546e085a6b52cadadd6f2cf3f4dde5e60fd04f539e8aaf56a2323a5930835df17cf3cb47ba59eb29c14ee00ff051d723917c4b535a49481cf96e26b20264c570ad9e2bba844be79162166f6d69232871107818550c4a9fca4982e3428ceb812bc65455b5d35f857b5fc7184b5b315c62fb98f6667fdcdf116dc564c11534319c2c7a8c535fb048fa43e141a1834ae9e80d3387be210b5cb66258be0323b212334f2abc5c640458a539021b7e269859b662281502b9e0cdc5ba01303162a231f76603ce6c50163ac4d72716115326c6522c6365b88b8808dcbac3d01d1df6a951bc50129b6b6ef54841fd963955a548ec21b6aa3d63a140b4009fdb6eb8468556d7984188b4c917825080c805743a3abbc19b0becee7b62dcc2ab34e20a7902e5cb17afdb9bf7b403b9fea3707b51d176f0e90baa33a1155d5c70c200976ca8c0f9b04f4deec7c1a0cb5912c2764b59668ba02e6d391996e4d1d786c1a01b5a85e5f82426ad37303ef227b22d21e8122e40934a2d6094baa31caa25078be210861172cec963e1611651549b28f9f86cfd6a7be42056677df66d530c9821e1ac3aad3e21a0d09818d36149bb5385c48452d1fd724b8c4b728f2135fd435ad25c3b86b3ff2e14fb4f343cd901fdf78b6cdb50bea2a71d879161d3386bd254731aeb07ca4e721503f967a5f87a40e04f763d8a3088f1d65256f3446e2cd9d3d14375f1922453967d3ca099c8e465847d111daac2798f78f933640e685d07c57c80e3a60971f40c0b4c0f0d9c4fc3860a4e741ea6dbc74fc6d475bff63f018f4a451eec7734e5d0965915f358fc3e344ad128436e0be139ecd5f50ad190f0f0893282dc4df02d83e9c12797608d4c4c191f70c6450e84463abd7fb12841285e764ba82f7c5c939a4a4469ed94131abb46b448bcad27b6b1bf21b281ac3ba804c2942847ec3db446851594a5bd2eda6116a6f42bb4cad442a8c7913b8be1a6c3fd809b3470fc3924ffa6780b39258f4dd90816422ac23e77424ceb30b86e0125ca0821945595fec15d0cec26f01645ce30297a6359800ef9e24cc147fddab49ceeafc0f312dc3d488dd9bfe4da469cffea88ac7fd331effc5cbd9141f98bb342ba863c027d79075f98cbc745e9589c1e107bdb2bc23eba62bc96e763702ab3aa08939523543436433faf75ea61714330bf5c124838c2450975a2a28aeeadd3e2f92bd97d260413dd2aed171ed6acc9639cd2df5ea1468187fba0ed64ec7047bc38ee0e565f4978ccab1335712fb647f0caf1c02657a1969916eb52a35c847975d0eb0f957b61e42813d7b7f1dd06113620580d30b167760a8b79244f12c8df6f6d2f546f6113c39dc6c2ff3e5e1537c36e49c05a9af70640122abec97849334f660bef62bde2267fb31c7ab31c462f190a4f5efc2a2b17a85fd6ee90eec4fed57b6a26539efe7d40f1a3a75960748fa3ac4c305ac6118773a9fc7f7224d124a305eb386ac7c338e56c7614b9c13866931fcb3b58ee256d5aa76b54050576fdb4b4296cb4bb076992b6310035ce4216e2d27e14523c34cb5fa6e680901bb3d227a78fcfbe5f037a529220aedd2e03ef4567096ed382928f73eb2931faed5e43d417eccaca2d4a1be80d46f2ca12892f47f68473fe2156efe03a92d7f69d685bd63e771876230a318ec9068ec0559cb4b446564647a1745f9b5ca60ae60ef2a3a9b4780a2508a5b2e150d477ec3afedd1e5599745598f1bc2cafcecc2caa66fa9415d40b41bc1a14beb3542e52dbfe56dda22632b838c6e47aebdc3442a7522d25d72c85f35d5bf10d6a004cdb83886e942b4b3d4e72972a33bcf59d2ac76c820c3ea6b1e2510b5ba3f9ad336a9857a89ad6c6549ef15787b3f209bd227f78175c30f0979d7b5347a6d585a078774cde506fe800276fe825b557df0c6dab14748f197d001f38438062bdb4766b81ab92976fb93aeb5cd530e7ad8fbf9e07d6f5ed0a3040524d294cf4875eb9db4a9b5f7018b726045b096257c4e8d814ce72598741a16a8530f788cab07bd17813f5407059a16be415b5c963b942e81a93d9802d2d3773c15e86498c30aa10d434a7eb5e66914ac3ad54f4e553748ff9587fc4e8808375cfbbdc7e06a731cc8e42f85cf45fc35a547e2d5f233dc50a7a2fb8117e2f00d24e48c0b8b1c10e24bff3b2b7d646f7297a177faf1d9ceb3e33c015793f9701893f315c65cfcddafbce2555f5b80064678f2185a4dc964374383292076dcf1e21836adb1f6254d271202ddcb991523dc746d4854b64a52e31c6d2a923c287da61e42d9e80af9450badfd04ecc22a386a982a5e0943ea67719d70286a53c2621bb65b0dc201632e07756ab0c4620a96f78ddc781a3b997f71cdebb171e33d9d5e84f793bf8ccd2e88632e6c5b2d7b4b612a47f65e7d6dedf5c7e6199f69d52a3fda00e96223a7d839a51f810535d12b13c4eb46c9e1d6f2b2c0e21dd766a8f40c268538dfc563a7f7d8fbf1f8aa90e4c422b82ae440aa5bd6c3b5f4d5e769ae148831436ae3e02c2414f88a3541a4220790191d9cbe11314abd858c7a040516da6d593a743f896c82473e21d5d9dcada54570934ca33727232a07b6f924d3b404404ddcbf51cb7869d4d15e33119d281487a5db97a0ee4ffe5509dac33fc531998a36aef72df2733e5a236f1d4b975092593dedfdda2f5d698a6de862ed38ed97001599eebd30d8490b6422834edc1bb8151dd0a8a9a721de7e2674bc7282bc07cf22524c2c8765028eb9e58c983013734a492a78f89424ae08dc7aff683f16e568d7da9559883aa8374d660f71206e8b420d2544e1c4c02aff95855b3df3fc0ab108e2067647a09b9ee62b9fbe4aa1d2836e16b6fc947547f9b12a1674105271376e86f6d1aff44d91a98cf43fca55839b9489930ea844b25b7e2d64c6fee100d0906d710015b67e68731d7f47efbec6cb23df8130854478090a858fdcfc173ea8a2937241e14a5dea842c16835b190f5e63c584dd423aef708d72fbc47835f03738bc91c337ad827a09f7d8e216ebd5ddf1e06a5f2c363c5171f46445c0a16e5d8a62179fbe0a317c7542b8c8967358b5e72dce71b57485b4b2120a78f40e0a3cb8ca11c93912b193872d615bf4685c0280a993030d12024404d770b4e5e60a6f4cf278cd8136a3b932bdcc17d351246d067843c5e846c483dc928fb4b14f0703d7ae13c7be453faac5ae58e91be6b956b41c15c78ad47484360f5fc30b621bc14bddfdb8658fa67d27dfee5fd453526a2b9438dfa7ce026f0a9ddabbfd621583a505614596a3b5536eb9de2472b4b555943c42a52c2f658ea0a96a926f7c5c071c065fdf3108c5b5decc20f9fbfecdc7d421aabc18d1236a594327257ccb81ee419babad0b9bb1ab25ce504b945e7d3895c32cc09c7af66f413b7d75de4895a0648d5e3c3c8287dc2c08f6fe502cff7c53de40e367a2389c83778bc3b114f9687deba4b994429eaf2a0b49e18ecfd99811aeb1003fb163773d7771150d1fa51be2f276abc49046dc9ee0c1b203b2c2fd9d86801586b5fb741526f0fdede126741003eda0fe4a9fcecea2582cf55fba2858117aaec890cd473da48959e59603f9e65f2aefc2aea2df07285e25044af291b8afd48d01f2c3e707690b0ae635d564c347d92ec50d002c2a4b10d303ec6a4379fb9dfb98a123cac66842f27da0ef4d6064fe18aeca8a4dbd57bdc0f4d7bcd47fb4ad1fcfe2c74990686565205ee60aa59084cf0c3695c0524966e0a82c90ed56d882a7098311b38bec4434adcd82d16f1f65b0d271bba0f4eb91b18817c17840b07c5335778282cb673abb00daa016190bd260e7ef8d0a98b547753e9b02010ce7f6c1ad70115af4ea1822042816cab31ca862537f235540a2fcd434417fcdba7b61b53a8802c872c99f4bf48d186ac299e8f02276edfc4c89ce42c4a8388e9ce626239730b69532259072011359e7174ef5553d8b05d52de813a1b3a1771f1cae1bf7f35f1a9448b0870b994b5a9356b37a3603a70373a4fc668c84777c91cf9e9fd6be3088d905081a419921d1b72e3449b1d58fbf0a19cccb32344e9b56d7537ee8ab4607b4dd3321ddb98914b0187149929fbf43730e946a9b1619a29f7c583667330543addfa0d63b1885473e96b19a6a2eba5189b4e3e1b3aa427e25c916372574c054fc00737c4063738001726b6f00d786fc3d7692dfc0cf4d6ca31e0ede17720ac3ad964304fd277745ea8112824edffe8f4c942a2c7cc5495fbe06ac384ed62468542d0b5840cdaa7119c0ae599cfcf05d67b11c1f8182877c854b60ddb81863e542d64fa1fb90f023e2a3735d46f1720019f749e840a30c0d1a2c65273238d4c5ef4e44027882411bd8f2bbcdfa05df0b7be69077f30ef78ae18b33b560e8eac744cea2d1ab3e7d525c1cbf122098afff274909dfac936fdc3fe1570ac7fc7b4b0430d4fd5910885ddaa7e0ffd05aad5370db9090654964fc41c2639c90e779487e23d8974df244f122adcfb3941746fe352e3b332ae5e610ef34a543df8e61721c178a28cc71522d2dceee454cc819c74a0419776fb9c1fc84fe6349759802ce833f8b2983fbdd5cc3319d7f88e7a98644b00cb202db6fae4d081197f3d1d4e1afdc6c6ab6e3b26445c6214c003447ad12903779a1e668166fbadbb23e9f6b74749626d48b8ed6ddc957ae33816d9d173b6a381d1704ad656dfdc773c3c3ffea54b51a911c62a8e232eedb2910f1f111b5c400d08e70d87b36091decd3de88063616364f54495be337e19a08838f7d10cd3d2d69058dbeefcae77c6939a3d1dc252075b0e76a2379238e3f023b8b78ebf0e4a228ce85f1c725fc71cd46669c0338326570f0c674370f7d80ba87606168957137ca03edd1e7e7dec6edf0cc6c08bf36b9b884db38fcb14a764c143e81ebc6bbbca2c5e3c036cb639d9412c70d5a1baa9394c536068e27d1bad345e958dc74fa07a2079aa80b04c7465303e940c6f76adaae47f382a1410ef00f59e3f39e05a52c9d4b978c7010816ab268cd1b676c593084381c24c7afcef83b977c7ff99d24917545a90b413eb05e3c51cd36ecea39cde8900e4cf8481adb903e1e3c135cc09b496bdcacddbd633c94aed2d0bcf452616a2fd30e859de105bf627d9eb1c28c4c9e29fe2b701eefca7539e462371c9c5373634ebf6ae3737095b30365010df0a28659dd2b2f07d76d693b46dce8333b3869fd22e9597e2ba24208fb058177d1b6eb7984c71ea37f68553bdcb5f3f706702e64c804edf165a3126c57349896e8e08a39a9d305efd80175d7873c8f0f63bbe8b29b529f25ec20a1841278c5e51bf5b350532b67eb85b02e7045f901f2f9790728412ca0585cc429f8a701409516aa20033d7fca543e87c4f48989c6f9217405848686dc30b3b39389155a02862339747e902fac73e98ef1cce5dff9fe9617b8555e80d17ec8f311e4e95629dca0adf970f4fed6bf44df865277dc33f286a1f39b73f4b201f3653a8be38a364b6da633579186c27693bfd1ef0858627d701dbdba831ec45c5a012d326a397d78509b47ee3f2becd24a833f2424a66fecaeeb7f3c26060cc55234480d6ec6fc7a37b28e36df635943ce7d4895f383197ce4fdca545c590f70b5f368518728a8561887d4d5c2c03bbec8b0fb74f8719270892162b98033d3dc82ce0818115c49b96f036d8b6db966476725f6f9373f905bfa3470dc5c5a84f45208d000a2f329d0cb47ad10a24f946cfc5d64ed59c25f4289debc7c838c7c4768828c429c9900326d71d51ef6abe12ff33977ddf9d5aeb711e6941b730a0c6ead89ea07b2b1d0c03361b0d54538dfc62210fd76f46cf6e1d56b33b4e6b8e716afe547f9ba376ba562d279aa45912d16b692ec12e14424dd30cc10c6e0d8a5ffaed33e8e0db5890e7c41f8ba8ec63a0860b4fb66ce438c4a81646839c6c95810729637ebf944682026b13595e4a63f446c53d06a191f56e9c9446f7903f83299c435a27ca3656e35c36b0bef189d89a2b94ca719b67b1680f85a4759cfff5b420bfa880f5e3ae0c9910d6649a4f2b7390eb7202232848a06f0080dfd1fee1458cbb8f4a6e7af76059bf451204294773cfeebd94e12cfe7edb368ca1cd940fd5bbfdae6abdd7aa06f9efa966c8a388101c308b382d683ee4bad6fd080c53571310c51542729026ef50881446ae70e8e429daa2f9eca65a48ef719fc2e5d2f976dfb60b8b06ba954efc792dd7da9c4ebdd414bdbde88acfb373f8d6f79349e9ac1376e1a832bcefd5a13ed34439be0928497241333edc03c22c213c50845fa97b24930f9c15b272af193dd03fd0c4b166f6dd4347985ca35dbd0f096021e344c49abe1d95e2a5d81cc47747f1a713ee129d0798fc76a2443f7c0f60472cb0d77a8323997e8c0b5a3c26bb201028072fc74a604c4fa21d04a39bf12b39101a2f98a41d44eabc15705caad295f71d032be99166821eca6e514413542f642281d98f319a94978412039faad60e0d0ecaa929dc48f6ad1827243bccbea94e20246564ce607c06311047273a64a4eb08d0228314835f9063abe1b8b3ab0991709af0019969eed6f35028aced99830fa4a185c126f1f9500321f807ddd678d8cc398abbd1f6d52edd98a20c741da8fb0c0bfea16fba5588347294c7e07f31c1d9e34d2cd37380a40ea209704e04ede00ace30d420cd51dcb49d27983f8891a8ff5d5c2671db73c3e43268c98f37c7bfa4fef129955eb2f2e1bf5ac88322c20087798e2db264dccd05e4c24d961192c47eb520ef72249251f34974a4632c1dca639b1244191ffaa31dacba381cb15e63bad2f945b9a8c2dc5058a72dc5e5c0432646e72409bcea2307faa7939a79e560b6d13f1a1c822cf14e4c07b24eacd502cd8624860f1e1d9ac7388599f5b04361b365ba7a82b80d80339fd15c63e4ce4e33db3bdf0813cea31a949c3f48c37ec00ad41e57b0701d9663390f99c3f68f8c49055e17c8b96efe87c08295f28ce2cbf365c5d08342535bc2c0f30521bc9e2abbeb95db70892f77c6460c76411f441ea0e085baed21c576443bce4c221851b25c4c299a30ef820e6cba7c699023e6eb2433247bcf5cab8835cc8a984c26c5d837c4397f721c1bf2ec32def1e468a41b0a530256d2d96203b297048abb86022cf0d20abb2cd20a46d2840b500763449ee6e6f09248d17dbd27fdf63707b614bbf2889115575352239001437a9625fb5a802907cee48b93c8ea7c201a91078c9a443e27876afbc28e37218a1f2ae16904c435a060d14c9bd7985bee264f7f9307b78a63160d82f23f096e3db19603eb00264d201ab864448311e2bb086e968f3f42012eb510ec1cc207b96d00fe9208cb7a7e93d8094a435ea61137ddb7f17d082c4cf58d612f101bf87a174c7ebbce81ffadc50a6436c04640522ce940e825010390c890870245a890d0d8438dd8c2f986ecbaab4c7ea9fba253e8ef254a87f02c831a1cd02788d0c161883fd09ff8aba76b445af226bd871c16802c012d437807ca85d9bfb1e12f9e5e00349bd92f86e408144fca5b1c9e7a04173d0c05e1a2871b5ee0ea24df41264f2c22091ec5e7024929ca99dfad85b68258bd21ec9eafbda2dc3b58b48d0dceaf0c7b154abe86b6735559eee85eec160922e688fdd0a3074cde0d6937811e506474cef3437381c08dc102b8563d4c71a8b62d0343a7fb1cb1b6c0a9fbc2341f7f2aa4138c4ce698699f693d8ee423307a787140aae8c1a4dd4958490235aa4a9577ac1433924a28caf334050bdc5c1c2184b064000177462a2a96667539ee065649c4ba34ae4f117cc1010be0af556edcfdb101ae409880a70ec8f51bab76e5881a91a56da8d9de5395859dc246347f74719292bad8a4fd8d82a4d58d4127252181f4784b1eb27e44c34ebd17a985e1d90d83dba74f79556944b6711903916beef2e3bbb97745382cf90a272649a6a4e7bf8f2dbca91d9b9283ff3eaf2021401daf77cacde2b9d9f507d19ba604bc2f080e9d568a7be6232495e138ff301b0d208192cee1e52e86ecc4f4c04d749fbec4e32018751196d2bac703845858184aae23d32e1e6a6c2324c73d1dda045c62d976739abdb0a63be1ef964bb5c193b40bad0cfcecff7a79ca036fad6efd83a5020a9ddf0d893a84abf91b4ebc147197f71263a272b80eb8217568b8908ae10d2a058e635bb913356213d62f858b14b0a9f6db8cf13a42b3e74aa0a83fbe71aa5e09dd44df7952df1a5f3e7cd94f64caf935889e48a08b24440a3ece447d511ca930eb69e0c2acc796d5c1840673a5b5af9a5c3a702926f8688c58c197d2be3ab68280830f194fd217e341bc60f2a51dfa16b8af5ccb4bd90a307c5f6ee80ee120beec094f7d36d51f9d3a59c8f7b6a39adc95cec44e3748d2400a24bb48af8acd92bcf833e07e08eb20a83a42c31aa33f1ea186abd476eba80cdff55549faea428162b462962b4ed73bb6cb973f06db040a0b4ed9b063f04cbd51cc7bb01945184a967f4a7c375649a9e9e17e031c30598d591bc0fa832513eefecd259e6abe780804685009bb8dd0b0019b2a39b6ba4e785faf35b7c49cb4710f0eec6724b2874de8b8c8ebf38c28f6398efc5f255cd9786d8c6c1eecb83ac402609493508ec866abcf15754dcc854b5cb998e49f1183b5d883c64c53e16c0b74278f67058ba3612abad87f2af5c7612fa02e120b1572d875e6cd9e1dc1147c8c4970c9021b29c1f0dc7f37ead8470e1f1c5e0bda04b2c473289422e745fc49137cf58104e6232ea1d8367c987748fbeb520cc67c5f2c5e73df79520b90f26aad75ed5c7d26393ecb6e73865c71f164f62c6de1526322c6b510406019159277378931a81cf2ef51b1d6ee587924822a4063b6fee58c1b041a56b41e03dab1c3a229fc8da110b10e25cfd9dc2fc86f151ce621b51cb235092e9490f1a2b0c6f5b5bd69bf96f409ace960fd3bd73d29c64698edb7f4d789c09bdf8eecfaf912bd9ce38727c66762861bd6e7a4a7f296f946deec23ccd812c749efad9e5fdc3046a7151a4ffd30e4d0bcd5632a878bd9a51fb4d6ff7db16cc7d93e67cbb3995f731e77003cc5a914774ebf856bdf51cf5bd74b1eda9b66b5a61dcf6a89231a50d943f9cb41fc5205f1ee1d0974f048dde3da37db5ddf61ef03d19b52b27350a5d117ed750bd726acbfaf4b9e5dd926d0416558f4d6cd28060edc4737a64fe00ed80eeee517d1cd6ba0bbc4783b7b70e8dd869b8eac4ebf54b7af7bd45e4141754278cd0440f9eecfdd92a72ef9a9579bb54b87534e95f1fc4237c64080d689deca017ba23b44a389c66feabf9d3efce9cdbe49491d8a69500f03c36c51bcc68a0f68c2979d498ed19a33e7061b9eb5205401f8569ac12754947abb3989dc45531c25f2fa68c53948798dc8ca677c7fc65ca88e836a535f680246c3bdcfe738b601e72d00ae7f96643f27a35dac0236e0d938d9df780923b5f68139022d24f9c4ec0d736b00cc8226a81827be9a1a93daf67caf7b456ee18baa29554a621c2076933384f20de233384539c39bbffb82210216d4db9633bf364072ebbc2405631e8e2730232176638a7897d4cba38388002ed2e704d8199a8b3a6f62af9d2cc3d60d037761fa97b288b3fb9622e092aa34855834477a7e7acad2a53f1561c65eec173c25aa980aa4774231ec96948875ef8d7c903cee5f0e3b7eb045f8641f3aa36c8ed48fb676458423eb8f5561231243f00c3465421e6743cea7c47f102e3e98a5cfff0b18f15a5fedca5a9bd16dba513635bac8ee2765e9ddac653c0cfd796ef6644ebb037264b5a1533bb67d5fa5a4f17b0715919ec8dfbe4f9eb5bb89ea4c6b0a92599b778dfccc1b8dc318dd59eadcf405a5b7fc29ed6a403f0205438649254fd3ffee6e4a2b1ab9a4af45d18e3a79ed91c90e50de4c5017cc7be5500744979f86a7e7a968530cf1e6c46877420ad12c1ef48f70e842e376ec920e0320c952bec830ddd15349ac47e2ec1e344204880eee6d9265f0e7bda981430baae7e3cc622f3337581fb04f309768b7596c4799316812629324d1191bbc9d0635494caaba4a7a9994e429d6c4f952e0b2b1b583a66d1066b4b24bbb8a646a04506f4d1ed778c3b288c48d41c2efaa71b2b7d30b44c53c10ba59053b669617d8c7c0fc4292550dc8bae2f5c608356d85cd85b8c6e00533c9ca476d29d4362d80ab9e48cd5bdc3edd69ea38330ca75eeb54cd0622c469a0a671be79bac63f5bd939bfb1c2e8a9e415ac808b41a7e67510b780e4ee79cbd4f3f0b97438a5971a7f8d2eb6d992a1378360b56e0f7330fb27492019e632292edfcf048e6ef6d97c4df7745933b126553e6ec7f49399730b532ce72b8f9666ca5f41cc41e67dc66e2d40bb22fec003e01f03ad9f3944fe0cc43877726b2fb5c049c946d3f69967e05361fc7db6409185eb1e1ac69235e08a5d332a44ccde4dcf13660fb6e53b133b2ffe09055e4bb90336f106827212a5a8b20e9d5bd89c9b5ea96c6c722adc19bfa4748c5c739ab05a2f0d75583b919dad7ab333b44450e73b1b0b0760ab35b44000c2d5ae9d9ff6ef8a793c339f0ef5e545039f6c0790f4d2fd92bf7252580f0b641b779d9c73dc5a61d541bd780d0e4ed9f1a386dba1af486bc6352c8c9e2eedec88446e9a6e278cb8ad1f4a3e50d9cd34f3d37814e62b5242b2594906dc67767d95f3a8d4eec8d746586865e5dc94a00c531136ac152be7a9ff5e15ed21e94f2144eedd7c00853138923196cc7e1f35544b670baa5cb1ef261772fa90fadb60a6b714f3a4ee3f9565b152d4324e8150c05c90a93520d9b8fd9d22c02fde84836e6ce5bbc381952dfe12e24c7e0e108da4ba6889ae9758f226730277e81cf6a1525ae4718208927bd07c6b717e663255052cbea51cc082c740e643a3bd7b9bbb8e838152e87c2adb78cb02e5c2b47b84e32c3a7f7a0705d531eb11d307be7b46cbcbc17f7045ccabe2ee9f6c6469d85380b8ebe118209b3dad7d0a4489dc4b4691629acea84f7f4614f44e52b7b425bc338b032473a965b6c1afd6747d5bb296954663194924465729abb1846e053cf19bc1f58edad1d387a0a6b440582cbf36813e8f02e81d570dd52c98206afd9406b593096db972b106b323658421b60e6ae2f8120dd87ee3796c130d3435d48ea2681bec055901deda1b61092b152fed315608548f6a756557cff0682b57f4dfe7cadc1d3318ac2eb03d83062419f62cc8eeeff2ecff1b7669a5fc32e5a003ace9068aced3ba2cacc8163ad264b3489cdacd06980437022cdbe828bc77eaaf3c5251e27e2e4ddf387a68a39c5df19da97d2bbbb2a94922fa86fb202d633744b10e06f49e5d9907a5a40f3af60b369f0ba40c748f134ab2f3094309a2be74f0dd9e1072409e345a0f9393d598d765b883eaa5b86c9258e1713c176e5117748cc8ef2250ca75a17c7127023ab584a59500fd02e7efa7352fd8ecb00f827a086f2d2bd1d48713311ba7b722a749006a311f2fb709d68d01d46c47735fac2b974321ffe6e78c4db4d2c30d121911cc8f4eab01d193640e21b5a270e33c100db5290d45558c46ca71ca0b5dc3d106469e1bdcc34cebe104291ef0484eec8e7f1bd1a5131563d09c603926994f7f05fb3a8d3e78f3344f1bb2c89f8cd2a06f8ac5a21d25bd5b44047f87228fed2689f84932342e1201c11eee5e3eec15c532d412af663eacb0cf8760c250cdacb87b919816b3db17be1c8ebe6c6023da39316252d650a96d75cf50c6ed03d3759aff4881938d6ce2b4965f54232905faa144a2111f5106c72b016d6fb3a1816c13079dd3d7c3226c304fd95fee3edbf6e5da6bdbe1cc308bddb89e984a91935481c638bef79e75d06f3864645c116edaac7157ba7979001db9e6402e3cafdac41378e55190e61071426e8d9514ec07395befe42807638867bd775b14d966120f9014729138be7892bcca5265a47db17634599858dfe6f6ad952986afc36af8b7fd6fd57f392f7d77bcb2329420d1e9ab86b31850a6a702a7ac2667162b59643737b5b0600c05e29003c9c52ab9a6bee06bb239cdeae15a199554816969c0227675df7836ad41e24025dba2f43ddd66360d228e66fd9bfd4a5a7450cad75eb8e6c0378b2d405ae38d8834ef10d75bf236d41920a627f1722ecf56a1cd88edbafbb1718977b97d14e427f6d91fb1dbbfdbf5aa4d1c946dad8b0a9e31a5a2f5bb4fe06575981c304d711eabb73515d76f498b8c5d717a0bbca9b5c82b2d7e155dc57d094b52b58687c6949d19d15bee0a866bf46f3f57b0b5d184f415969a6e647f58742f42af957957e02e2555c726fb9b0a43fb2ec99e5b92556a8f92aa1cb1af40cf5d0ed3d1371b88ea6649350fa565d1538af6b3acfb874817858d3b1458cc08ba52bac71ffbe79a47d612b48b589ed3ba5ba9695e4d6ba0c9dc5ea67fc56ffa746ebabd4273683c721cbf8d6fb5fa0f871656c325a904b32f529cd1658506937f03a91ee48d67e8a22ddd606ef1846666f8f6d1cc919f48fb72f8f9e54083fda050dde5d972c02632bcf3de8d279c36c884bb41c5c4de8cdeb3245ff82f37bc46bb58247b97c8af37b26a5e6afae2195d2f475c19a4ebdac58f651a7ce2adc78b0061858cf96e0998759b201c3c07cf8ee8c2e568920523181cc9ecf80e07d5db4b8ddf10f81b1fb817ba7071f50d78f2d85467cb71bd450fdbb0d68199e9e3ee95399003d3e45ff83c48bca28310acf9e114efd77e91b66131cee0a3a8614f15c17c7fd4d852b7e7b01a593c8b369e157109bff84b3de7a80cb7dba3a4b1b286bd298f360252c2d7c074c6df2301a2dcf09ffd5a9145b8608a7cffd3b9174e93041381a9ae73e97102c7f22cb7017c1dba0ef95ec06183456cfda945d228a3fa1db9e6531b83ba0df568479d216a83a57f3aa441608dc36048d06a2b508a19715d494302416d4dac163006da677cbe5ff7d1c9167b0a006a724758aba74140882dad250a8af84d37f590efaa2d4c3946fcd59967498b14fdca2914e4d7f635ae49a109071a5605502df77f22dd808216c80cbca0a2b55dd1b8a7398095773252e5199791ce1c1a71ddd4a93a6762d169352cd784cb599de64de9a2408594705c0c49e4efc456e6c85de1b16112aabe5eb548cc8ad5b6b019256002cee048e22e06573f843683e2b3ed1e72d6a2317d1ddf755e27374a60f5a11048c02dfe7a8d04bbb63e531649bf4f1448683d8e7e752e6c1998a29354605bfbea2d32e9aa19c287787e2c0ebb1c05c342910e71a308fd5c4b7135b1b28dba1a920cad92f3c9a2d3d83a9c87072a0ff3c404f788fe954593488b23d9194870e4335b180f26f3a7c2dc68bdc66c30097603548cb0d0c7604fd1230df59c1240ec871a925beb6206ac0d430e6fb1fc36e79e660833de0f81d649b05b08fb9087552d0fa431167f6a2dabf46ce95d04fb907b681a630404c9121062687680b358567cb7fa70b43e609c0fa4a60f1a3c8226a74de8e226b8a711576a843a4ea01297138a8a831beb000bb7f841b47fb4a161f3732c738e1143fe696dfe3a860bfb61bbad45f394791abd3606e525814f6033fa8311d6cf21a596344eae2c4381403ff689efa9dedb0ec3171b1be510e47c2559e99c503a225b8b97b22853a339ef24968ae39c8da7155ece57e6c1cc641794f271b212a047c5b9b411d4aeac72b220c02b5cbfd6df8a9c46a35dbfdd9a34873ef636b528acdd4e67e2117dd7f1c21ad1caad2c505648af941389e1d114db7524752aeb2ec57b6af01ee53f44b314cf2e1798d9e6325dc070d7e86cd2b4c21099d65574b4b4d1e1b6859589f29b9f56380729a78ebaffc82ad67d2e7091d473d075eeaf9ae409023afb945e8c8d0e562fd515bf011eea9908c83c9477da55004dba060bcf124ef3a685f622abf8d7a6ca2ac24be376052289a1600e8ef25ebd96ac22585f8a27c3ffb704cdf01c844efef4ce2ab42af43445415ee80390b154c09e57556a58cfdab01e6f147aec73c77011088690a192b61159dca5884846398adc5338e5e9b2f2ef96a438efe054ef2f88a47268ac1963ae25c619fabe301b7e20570b6fab41d5ced58f4c8e235b6b555daa2e2a6a4ce65656b51b1004f556ccc4a9922f6c11ae7feca27f7349d81d89dd002ba2b507ad9c9df59d05afcb5599b010b1cb6ac395dd643a40728e0963eb997b6482e84ef5ac24eb310150a04484569c48e3268a8ad761248b09d5f22b165919e73c4c17b45c094e7afd61c1d71c11976d01b1785872e4b346d0238f59d1a39bdffe239fc7994db6988e061fb922a0ff94b0432c2a4d49f035a594153b071a42249fd0af1188d2b5dd2f440a07db2ca33e02e318841de0bc830a4fe7fe429bddbce493d8127cb3bb9d6c10288af1bd927b2929af9004192dfe2f3ab458884f7f0850d7a575542a5205eefe2ddcad359e73ef404ed1e281c5bf01ac2dcc5cab634e2c2739f3e3e142528bf6217ebaf67cb775e0bee6cc0a8c764801ba9a5e9f7396d7d83cf9363b6ffcc27de1971eec68d08768307ec12811e52accbf85d4a046922de47af9e22f2c422527da2d591db9f0f54f11767c271dd9b116716d7af30e334c5b72f6b1e897e6a467bd1159528f81a6d54fc38e42a4c8ec1442eeccbad0128a27d39fde54d8a821c0fa9b5efdbe05a28a171d9ebba831c9ff5b06e5ec635f421a7c990e1d2d615c5e5a5cc3bd3843b7fa678dc4bde78a034ba95ecef0a5283c9331f20a1c961e445945c69c1af42b67225a1dc2c3fddf388f94c0808daeca8b9613989a0ba4b0897c8fd5f03e3729dc9a6082e86804f2855a12174c4ab2341731623673da847daa015ce244b130aa57de94dd3c5c0e0700b3348fd0fb9fcf96776a1be756bca181f331305ce848f33ee53738b7e14c1a96c06c372cf05f53d24579049b6c9404cfa095dfb06abe6df9cbb5574d987a40216211a2bc6c889aae2c3a54d8db89dc0465e8a4fe008567b9484288c8b5cc885d6b334b079c70e4baec3da98668e289b6f6edd27c015a2155a258f651e922e5d3d1455126f98600cb2b4b0d252b5fb549573290a7173845753d5f345fcbba4ad8317c4c082c5487c8c47adf238b355877a97c4271247879991e2c301b69285dcc06c24c552780673065d2dbd90a72a48d669020091a81863d5129cbd687f8807a5e88fcffa10ecc235685d010e092286a5a6564f03b9543a27d56b36740d6e120862bedac0c1b01702a0b200bfb663b29c219f161c088fa879cbf8fb7fafae1787e9a06a8cc4b7ce09122017a4766fa5da98a183d82a5870ec588b244d46ae2a180140a83bfe3f4cc51b33f749f07ecdc07674586a4fbf15705d361126f63cc0fd8dece5e4b600e031f8afcb71f2f2eb9f8c47052e0224f93c8164074aacbbbca7cb642e57a3baa80019b4de2f1350b3516db4419ab9ba811a8f649272bc4ec80d689a7412230819154f647864aacb0001ce138eb7cee9e17455f182007cbf2d94d812c9d1b134302ca2e443e3db2c087c8863a2f0b5c190a34714ec641d4ed3a2d3daa0ae689a376984fb8ce8a45d71e12361ed271ae2345fd762cf299c94edce388881008249856ae3700cefd884da2759384a13f6c15e97f9e55761779b7f9baab59bbff7114e0d88af4d66d1a29cffff149860340585e5c36443ec48e85fda667a85cb68e468e1aa1349e04a03c879cae965c8d8180044bc58d0968b2686b77d0a3fdd1cfeab6b58510d7399851c66401b5a16490224786dc38d01949984735c6ccc39910198f4ca928bcd3cbded2a0646df4a6a827742c3ab184633c144c8f79788f45453eee34f16760485b98cf8f8dc66696f24247cd40b15a0e450705db0c79e6ee3318c25bacb36a1c0f15a69cbbcc0c6e75425557c8688182db3fbb43541cb21769b98705024d5389e8b200f4df297f9c0c271b83526c533bdc1d5cf1d3354faf60cbd78e683b8eadfdc71daaba9c789d7f9d6ff8dac6883ddd117fdbf0283c36778ecd69d74af7e203b03e83a9f1dece237c063e95a568c667441b4deff6ed1d5f3d22c223611d30b4c9ec7bdf0f01eb1116b315f7450409374aa21f512d9c9ad5204b1c000c1ab79bbbd0ba28a2d68effb0f50edcd296d214e7ed4984e6d92c61096f0a512c02788e2cbba145da689ad3f4a1811858c348753b98d4306ffcf319e7ffe5d713ee7934d70989e9dbef77d5bcf253aa5a28abf68e662bca685cb204fed290b86fd951d913dd9175fe0994a8aef3cc96895fb0c34a7df57970f69a13fa64438bc84000edfa89695a25ea4b12856b6b41c60c39917dc5bbcf27e86350ff6d94a0fbc6546ecea7900523f7551a1aa243df0a1156c29be61a2f353c7ebe55d83dfab991b51d11a423f472f1efe0548cc5179dbdd7c08f28747df388c866c07e7e3d6d78a15b6cc258492c027bad80c956b22161d87379c4af53dc5117aae3c19bc8d942ba550f05bce048d0e5b0eb5f543d5a6ce6aaa4a3700673eb4afeeb966c69a4a1a848930dcfb2a4053d2143a9c42289bd852131d927d7d6ab9dc7a400f3ee389d189a74fa8faa7c6365028cf2e8f6f744164a29e407fb8f477fe1678a640d098885835632394dd420d07570333b792688b9a3bb3a9d7054e1f963f5d4be5a8a8a57d1255d4558c304141ab0c3f4d9c6fbae1e03285c0d6ec13af0b59852327b8cf8727d8293ecc835170735d676d35624ed0afbaa69427a364891fa251ba9c790a8b7001f3285234b791878176ef427520e5a59020c0a94328e06d80a4f263b0f95bb5e00b7f4e5d1e4fc9f1f1bc70baa52eb4473f46bdafde6d635736c5adb45cb50838a346af335b83273657ed244d33561e458a2d5f35b5a1afadf307a367fdc10fa0a4ad132c87920fdea8beaa22c8815bf334c1c11d7f3d0353f980ecb0f2bcaf2c60d827881f024d0c99266c757b38cae97c73056cf207bdf1fe92e61bcb64565781b7c28303093824ba8f185425cd7800e43830facfda690bb924cb08a8e46fb16d0e3a448c9e7694f78f7c0394b5753614e8bc8241bae40cff4bf40ee9199b7a5c244ff6856ae84a8c6e0c3f9a423e98b4cebfb2a7c280c29abe8a560c92bc19d8e25ff0d98ca1b6c7d0bd7af52472c0af7365d52e9cee4db7b06351ccb8aaf13ca1c8ec98486d3bee7b025da6247b966c766265fad8a3907fa0166fc2101cf161df01963d4eb29c7b4acc5226836c7fb0a5cfce69b7d7d5c31594bc3407c063d5844c0d0b0bf7fd0652707ec1e94611da6c5189fa3013cf971be3788f703271869750ba9e0f93555f428432fc0c421ded1e42514786e3ab066f5866e21111b7e041bb4d63c64bc5e1f0df6c7522bdd83f5b0c130975ef00c5e0fa3ca0e2d685b4399991e9013aa0d331f67492b9db1faf4b236ad241075c3f06eacd3d93e12430199085ce4ee720b3f9ac0b8b91bf9acf920baaa31156c0e3245f78c763c541783acd4587676e92531fe19eba0582722d61cd000f8930e16c74106c91e37c3249c9ffcf3e9176cf36a7262e1cba2762df5c26669ccc868fafd886e9a6566c67541ae00268347723b95ec3660a5eb9062aebe59195c0020719ac75208db1d89948aaf3ad4a1a00ad782fc129f3f7b3691a2535769d0159e3994865a8cd6b743de740c00dfe8fdd8e0a41214116abc8d6b74029dee033f43279273dd8a637b69e19e25b570bcbf0660414ea568ca1d7ee8ca19c604d03b907d540940189544147e79de4c222dfe63345839fc9c2e18dac35aa0709d297af41fbda3fe5ddfe520872a885f944714cb807f3c4eabcba6a2fbcd2ba8cfaaeb60dbdb9008e676100613e8d802cdd67334bc0913298a7ee45c8a60124a35367529c275e8336a56fd5cdbeba676990cba23f06fca4484e28160ddb452cf8f0b5ef4c9adcfaffd04bd5e8659fdb12a6985b33bc64b591e5f0ddd2bcf834ade6d2df001043d1f4394d263cd8260cc7d365bf89f0b9091cc6461f74234eb39a5d96b454f2f7fc31f84f36111ad7972a75569010fff7a530ef6b4314e72d2378abf30ed8513768298bcc5ff2801854c4af1dc022a2bc42bd1178efb30c20a678304ab4d14e95046225ea51668ce7a08ea6679632f787eab366b4c3cb448fe954abc5ce4b4eaf5d28ed52d0031f838c1cc87d92fe6d1404012faa07b40a74994102a8185083dd757e1c566651c36f5f2f6f17e0c2046184e92e00e8ad4023519da4d5865065221b57cb6e56db8a793e427640d5054d2d5f60617564157b625143f20a6b930f759e31e8b9d1e2a8459690976329b8a3235aec23463d71d58b2b15afb2e0ea3d6774eb9f5a4237afa05531f3e5a3487718e59939de563ec40438cf8d3049cbfd919ef1fd369111cf6bb805c4b116929d74b904a8da77bea510a4ed698c398ddc6f09f10c79dc65959cf295a11895db8163e617ba30be87e37059c7eb2e7e39b3653210f58a9a6e35e9b04db5049fcc312c3bacc943bdb05787967d6dcceeedeb300e941f9bc78f6ded25de44eddef386227d47f8cd4b9ed9f7ee87cf9872f73dafd39735eca20deb6d000b0bfddb8f2ef376d4c954530cc0430db051b8df0076406a7a7deab093897aaa3ad1b66a93f43e2fab2a93a7da5d5d67005c8bc2389a1fe03a8a45a8a7bccf1d65c488a624844548a841b2d4e4f95e05d79aa792254b855637fcb826679907f4da2f0fe086e311ed46cce947af9838f46f7d7df0857744e2b153f03c39c28d829706d2cd33d1a250f8c0a7eadc70574e07d60ac4cf6547c5444d6639c9583a919907d40ff67ee1cd20d93a63505df05abe2a8e4fd44a43c088d404435101a3f07c06f6531d875c1f0e480c26d53b65ad29eadd3ec8bf528096d461b881233215c90097f125ed52bd593991323bf32e466f1a0894c5634369198c144c412302828241c0fb165ff217a0afa52dab27cedf2d4eeb6a22c6a68bd955d0d720e8e8ff651dccb29b02a4bf5f7380fa7f791294a3a6ce081156df6bfe67f94796970859beb6c7251e751c34d8a5a315cbbb0f08f8eb5c338f85aabc54144ea6628c9d9a9f0fce76e44f9b2a6225023dc980c804f33f34775a1fe666650ba98476c03f7dfd1a5c8d34334b9de4cdbcb25bf7af29ecb69928a3743add23af2ea8b5c76293218b9e0d350ffb21e6067f011434ad56795a427a85e800bce0ff2e61b5c1a5810c7c19ef2aa9b24242b5ff3b65cdc3a66e3d5754f1e200e6ed863d3ed2ef24a18f0e70810386f40809a90f29aec2558b64faeb5ce39bb3af97fabbb7b419e6b499e6725897ec37a8ae7793550bb0acc90af8d393298b9745aa9579d9a7a72a20cc846d4f1dd0a28970eb481a7ee25b7fd3524bb4781db970bba497635c4b3b4feb8877d24102df1904bcd4479079f0226e99d4ea06020aaf40311c908be57e09f3ced993e384d64336b3314f1ad408f616af6025951f0dceb266430dd656a69eb1b52e7fd23013db520328528dce191a9838e1121a5f8ecde70f1803f1205aaa2a8211d23094203d30b958c414ad1fd1d44ef6a338f9b71149ede8f2bd362adf573a4ad68c4c8a4424da16f9493369777c7943165fbb0fe79ffae94a824194c0427068f625891610308da11ee6882c0d95c47956d6cd10bcfdc94793eb6144259c4d5a9b98d6004915bda1635e0b816f180df9abd4b456cda3ea75e40493ea843ce3771073c3b332998d0b580267db5af7467dd4aa7d07116ec18a6d0eb4fb4e5373f366fb23844a0bf1a4ebce57a12710dfad56888680532a22e5d74ec1743cc210a83c32e533d1c1dcc0e403b7c64b372c6426c6651d72a1f8a6e8a4aaf68909b5fd62ab5940a170ff2ed0a2edb614677401620ccc51a7ad97418c5a3ea14233a722cecca4db392726949659b56272684a840b0e040c770349e92a4016a49bb2f4c9455616af0d28af79b84254ecebad1c4b134c755ea770d21c197365693104e0a316c7bba0fa19792707c231c0508919fcfdd8b8092205ab94ffbb54569c6f4f3cc394d32691ca4789ca70472c42838f8ec0776be38cfb645c72c4a8ba85cd617baa2f08ea2ca2258825857992e3344ebdfc58ee856b7b80d9a2069306acd8c8f2d778dcf151127e87aff04626e505ed4278f9e40f9f42734efe77399b58aa08ca014d1ac971b1be343f42aec40caaabc8cfc048c2a1e57668a7bd33f83ff35e9d371c57ffd22e147f3470311e56acd2830fe04dcd14923ff91ddcce73db2caef1fe7e26a91b02aa4d9ba57ae00f938c8a713052581a9482dd3a3f21773ac89461c403012b98c3bb4a5b120942148a75e4e390e5e264b19fdfb66ab5099def0f3a32393c6f7197a7ba66f877bffbab60af4e8b98932ad8657639cd20afe34f5f030140875e3a0dc921a5da8c566d50280103f0d0489f30dfdcd3d3a728ce1f2a27d304c87373b167f0c31dce2ae8d7c6e7ed173407c931dfa480e116766ac17de0b72c4057842d941548a2cf9fc1d6c40bb45c20e2e5a95e10a908b54ada8802463c3b09f72a2e28422df44737ba79c917ccbd4cfe9b02b181e876d6511f0bc0684fcecdbc799cb839e4f4efefe62a6017effc98bd4fd7f83209c5b10a9b60433a916748a2aca3f4b4cbd3f217a880c3234e4094acd2fa3172c238a2bf1ee9f5b039101972d3b4f942332a0dd9bbfdca141cabc1313c6ab0a5469c790b1ad288cf5e3c9ca08f4b2ac2113ac0801695c8eb2d29421bad69ce029b7ece09f1f2a78260e28f732e6c263a510df17161b53774d60b2ecac5893926ccc38cf616ab40eb79b5ebec0a1016cf7f99b141d213d9027c01f14d0764146319a2a937b81787931e63c76df75b7108c8230bd3fff707c17818f689b8c73af3936008ba90f4d9773bb24866363315fbdad70c1b9e8dcad927a284276a02f3e76b84800ec13abcb2b391d44700d2d8e9b89e91924de37566f2183f5f4ca8c342aa5d9d3b1c319016172213eee1aec71e179375cb41d22cf0c394f2afab665868c4067403b7b8b62736237fa21ba61e1f414e6e7f7e581718bb8fbebc4b569cda7b9886d1a4236b4561b81581bd91dafae3d032ba3f3d5f2e71edddaacf967541bbdaef259c0b9c375864842a46ce762adc625b8caafdabdc97f42b2ca1ef2fd93f659f31539dcee023e5fa94d7696508d9f6c6362fcf1073c1a6df0caaf18ac55f3d611eefaa49d0d75004b13b39e8b93107b2873654ad9d2a483996b5c0d7a5480c2473f162e0a693e7408bc902c74c5b8d2c6a9048bb2234859736bc5efea845bca6c71dd213bd29861a5600d7b23ab044f5facca954497024e2861dcdd59cd3786eb8a2be4f33afe1e191c5f6eca2566dd7967d7882507d9c298387069bacb4be9081f512c7181ca238c4c3dc6510576428b0d915367967bf312c9b5474fbb3b7a78fefc6c1a6f3f269ecb499ee91ce5e18647bc2d2a7c5a32da5c18d02a799f4785a710518eecac4c50e93793be03cda9c57c520e98f9ecb2409dbbbc6d75418f9b79c5e546ed489814c88db8e0d1b61f016d1951d7683eb775947dd917915349d5ddb689531e927dab2fd093c180e0a24310b36ee791adc0dae5ce1d6a619fbb1765f64fba00181a3c36d2a4a57e3242cb47a7b5129e99e923d83003372a01690ed84b8060a265e8b9153d64a80e9d1a859d7a52c591658a3c6fd0a50151ff15422da7a35e990a7d5bac17e763357777d4cb701c991658a6f9d95a7fd590c76a5da7c6a4f8120aace428a86e4b82c947ebc9dbc56749bf609f2ace28d1e7c9e023b86d251832bc4428ca37b23a69940dca9771ae8ffe6c5f429e51b2d6beb994028c08c70e384016a5e024014568466f529f1ced83b7579e94bbc5ae164580206b2b3ba5754eedc3cd3957ac33436ad24026aec80eceb2aaa4581f9125a51da0a3223feba860fb0a33ddaf031816368ecfcf8b1b4cb5307349b9912991e011ce78effa6c49a1ecbc435d1313e60f10fbb7568d75127e61ff2c3aa9b636b69dff824aa5800fd841606f04cb74b5d54044e8aae703bd38da77aaec380c254cf7faa8cfa27864a5b89f8b1dc241d950d8e80d6a104266057258368d1ea56ea129ca97c8b6132d319634551410133f9d41c29883062263beaca678503b5ca03a7af4e8cd44da1538202258d8a8c2375d87ef5c2058ea93ca568b7297e129d2018517744106257ffab70843dcfc9768336ea68b4e3aada7ee78ec4ab6e605cd6bc3274102745fbc92c445edb12fee694a3fd720852fe302a7bbf1b355cc74b0d9b41fda0b9eeb17edca1a33d436a0b7931cb643d5e143a7281647f2e16538c53f0dab3186dfd1da22adf744777c3dac47c6800738250d7f24f308dbedf43836ca976c75907ac83f4e5006684e36f57fc21a983ee6c664a7a32156b992386f6b218eda84ac999a80fd96c7899298e8a72e5402b2f42f57331e1b5e8d2e0d6c8a2ca77d290d68bddefe5f667822d7b0f7637451664009806200b61209ab7014122e8aea4ad1d65dbfaaebb6d63b75a576d5be572a65c6a40e92596a5fa51cbfe204781bd75a8d5efd884bd74ec3001a80701cc6348b862699025cf873ddb1223e4920725304260be5f0aaff4f11904819221574975d372acbae9b766c67bc9a386beb9929667ba0fee18e84dee82b9185bd198b7ccb16e0b946021874e21b98cd64926f46bf12e2f294318be3db141b8ec7a2a7350f84d4a23419cb65943a6c190e0795485137df0001c872f9cdf0d25d10ed9283aefb7f10b12f8cb8545372d02616ff2ce9d12106573bf9f0a798e995cd2d31025b087dc7b976962873c4380811b715dc7216cf0884d95fb02396df428ea3ec758f6ada42c0e08d89d1aade2c6e79078debdc033c2bc797a40e05320e35c0141f56a9785ca84dd66625a6d44b656d4ca2a58e55b2e3a7c72d4afeec2ea7434bf96a4a3b5355f08e5734568a33875e4965d8e5ca74cea300fec5ec1cc88e1fe7d501fb1cbb1a662f0b79882fc2ac7be831c8ccf6a9c491afcf0b604534afc8cfc451866daa9f24fba2c7963acddf465929addf22e99d23233488e500d037997d0e247c0e7a3e56d00f2751aa9e5b979ca9253a963ded2a8a303923fb5d1eb614e210c7085a889e27b1dacf91711ed1f8c9660ce277a3896ef0c8012296233bd38772863690464b83c72cf27b615aa50f7fb2690321f25719ad5e2512485c9fa3ed8c34f9b0f2675170f2b2e5921b8d0b0ed65d14541d579eb1aa5805baa0cd88c670251d9085065ab76568e334e2d705031c921b0b50b54dd7deb07aa702cef8432291b1e4fabf1e41ebbaec469ab83a96d3c3b8f119af4217f44212d36a0f5f7c4ad35cd793385361ca2bf133854cc5563a33f20dc611794eeaf6486ec01a19a96d227c53fcb73d3069dcadece4f32b89a13019ec7d4209c7412bd3c89c35db602c61d6f9bb2221bca658e273313a80f8392ef818a9969490fbdffe96a0474b633d14440a34df892c667d486c091d51884e30bb12aaeb8cf51690dc86db2db029db5c429d060be5766c2fd5f8e4b1bdc1df1a34187a7cf1881903b592429ab9d67922ecedf350d5aff0c048a1e88822529f56bb2680d82c942e81187cf83d2ac1d4170967ebb8ea334b283442d0422720b75eb01a263add628f4dbda01dab7e74c402e29b5966ee4dd92a16a8ab8c4dce73b65f2c0e8b5731db58aaa49d5c1d3c49690728817a466959867e3afb8a9fa93a26eb5f18eea164204bedc25238b72905e6dfab05d2d0993cf29cb8b0dd0fa39ca3d3e529bc6eeb373b05bc7d9d2503c8ed76c6ca85987ec238f6b72aff296064cc68e3bde7d23330cf5753f0438ec3db92de20896f0d623b145cf6a853ddae1ed1af94328dd3f107336053ff3b059c60c915c7d9d2f5179c48987b2f4bc504d432f9300c1c8f95e1e173bb6ed1149338aa7bf509d0ecf1312a519b8faf4e123938e910b101f15912dc0fb3ed555d6ace8218331d9a63f2e95b05d9ac8e8c88b674242d8a2651107c9d88ec1455c048f09a6fd8c61181ed099e9743839c100c1f6569b78a07e7720ae7f69b1f04e15c2ce3cde8ae7093f358c45f180828a68144d8d96e8685ec81c422daef3c2afaffd5bce37a9a6653bbb680cabaf5cd6c78dab2c77f250b78a84cd9e594399f6937b133d0f2106133c41aaf91ae3e67f0c1c81d9c7bb5be052dbcdc29dfc1abf4fa33e180503d5b771b7ad0640147b6d57c983aa90920ae53dced41c6e51a3016cd05d358948bb24e3842d587e9c48769dca923c46453ff47dfb88c84414186ed89f62e8dd14483319bc9c290ba07435a3bd66f566443acb8d0aad8cc6d5b641e3ad39bca498e27233d30269c3a0beca6d89b82ee3f4299498830466fa87256e79933ba24ba7ab1b5f92c9455d965f00904528b8129019eb2cbf8ea0716b228817a71687cfb3d4bae70a51c52b2c6623f4b292ba805b4be8ee9c5c567e5233e6e61d578a2ad148ede1a3ef6ac7eb7b4c8be4334b50839a95c47f52956b5cdb50e49c2ff92b52354bb9aad86eae0725f0eb54d74f803601d8e255c82932bb7fda7ffd7ff4ccc8d4964f2accc1136d16c65070548fcd33bbbcdb48b2eaade13bdefd6d0192045c59ff42b11b4467d7177b453c99e13bea138c6456e7e1d1b9b99a792a1446af200582e10b693f22bef4b519c8d0a4de65022eaf05126394e39c11688cc1257eeecd612e7417188bd6931c898170464f74f6fa863f34acedeaf0ccab97d46c78109bf4f7a316fad1bc55ecca36c6a35c2c607ee4682873b123fcd10fb2651190aba60d0461b863c4066227ea4c035b84c50ab6f89c292d86712243eb28dc5d45ee0cbf0d41803f28e874b28d037420cfd630e2a79d25c0b84cba15eeb2623caf8a4e02eead568448d1dfa32c8debc4e4b11b377341edc65f1a52a427f78b586c71df0ea6b4e46b8c7d987ddd57b2c1cb4146682886afe9c46b48f64b75cf5cd18ac195a39f8d20ad64f09f10cf631be9fb9d21b0210f48c5ece0396813fb74683635a13efe5dfdcd246b188ad1d0b62649a263506200984170f0a901b9600195de41cd64bba539e1792f4dfd44cce0a2d07d0ffd0e71948d25a2cab76999951e76bb0552b0c540c24731e3de2870eee4a2a7042cbb077f662f30c19663729665d4393a106647626f9e94c0974e90a4acea584fcdd09629d8734ddf68c81a9c48a5332c81655ffd6441403d4ea01240518438fd4981eeca72348dc7eca60cae1fbfec274997670aeebca0e272b1216cad61c7c338c67f072d41d757140a41a3ef9fed2ba63913b92379c8100f6aec3c1353d2601ab67ae2606bcf22d32f84198310770c7b5069668d403f787e0e9c003dd0dc4d74e7696d13086b532a043cfff4ae7c626acf88eadae45b7c962655faa457fd8445603000a7a2c99239e496ff03ff37425b60b5f9f36d1b2ef9dc9535071be8c678534d6c5955dd7f72d4ee6bc097d004309b1f4a2930b5586371ebe0f23d821507f23cfa11b89b7f895eb9f7f26f95beecbf8916500dbb456047ca3b04d401456d852f82b70f96888fbbef2eb282ab04a04642f812bff00d9682f4ef27942116315c71084d4b92ba711fcb118578618e020f7941a7f99d908f78dcb67c797e37c6b2676a76a436529ae329aee02b6a7e8aeb5b1ea5ab04b0590af3ee56edb3ec2d40efd1a20997a64a9776187638a41e2c14e2ce3c799a4e8a6108a5531fc514266367c057f8615a366601ce4f28899abe7948d96decd4e5668d4866b356920665ceb71f27eb9fd9c5e026d0756d3ca0f41cb1f47064bc9ce7d1fb553f288e71298b69043b3112d8ef444e08ce45948c18df5b4180609566d8ad42319270a030474892c340a2b346962b55f5aa3daab63728a2fda20e070c78254a60d76ff373421bb5948a1486b72c1c4d940884a0507c753576cec3971689c4f582770ff4d80a032010cae2320311cad1511df88994282a3d4f1952de001302124b541422935499ecff97a3fa7298f4095365c69fcd749822d08dda4b20c7117f89c331610a2bb5f351acaa9efe3a8b52538f7c74793bb116057c52e4bc95b96166d2e20158518c20f15641cf198a56959dd2713a218e0502a57c972836ef57ea0c5de50cee03ff510a8287132c6469b58f41be0f5017f7271f1f0d8e8873fe8a7a55c361d0028369327afafe4700fd07db6cd092aca44c60c7e50df1b98e60d350d0286cba811a0e08d6c28bbc0bd5d0a495209925e849f563c7fb438cce03606a05b5d5148ac9605e64ef80811e56f87b25640b631bd4fd1c314cc5fd652b84225f4a7ed2abeedd687b076a0e9302eee67e79f864679457935d6f190cf0b0f079803b5ac6e51290e8e3e00d041aba0584d429dc1084d53621293f009384d4acd71b0cf93e97442e8271402d83840c60fe977fd9059c5a4c6359b47466a9396e8feb1bbe5fa5a1b695cc31ad558831a57a979d49dc000703a4a8b1c5086fd364595587fe163da46223973b21937e79d36230fb059b399c0bd62304bafa115afb8d9c0857f8ef3d335d3aba7800802bbcbd8a3f7cf79ef881160d25f4c649710aa6ac3044979225b3a37e057e33f2061b0c693412bbe9708d2a6471f7eb858b1cdc98a54933298c8bb73d89f05280a29f356535d42876634a45731ba35911357f0f69651902a8c7624fd0e538893e80dffa15f6d761c1d427de2caf2079003d74a04693e2c63a2b06ee561453fd01eb17452985d49062151f893016dc374efbf5072d167476e5318fe20750eea48d542d1f18afdabd1a7219dfad1d55bb1961a171898032df46f4aab5d0db9f740d11eb67881b0c6ee7001a075c6d38f08150b7aebec80889a0ca73161258e3de7024c30b271983a9cc0a90b5e30077c3c1c270e7f50ab7cec38d47acd32f889cdb373591744c61346706aa858e176e2a25e60327c377e19c747a5fb19f769d8d0019865d1c3e244f6848f792ac9a930633fd403e543a032dd46e717e7ccee8316d7898adb5310c9b8f7e5572714771879af1d2dec9542a575eeb24659e7dbf9c5a4c78141a15e8a53a3b02f8f20bc00e3b88297bd63ef6ec964977148d56a2492b1157919ed3158ad32ccf196c8cf22dc1ead0b2883c07e594f9f4a479d0075018e1e91a421d4c402449d66a94a284533ddaa6089677e3a0cf74387893b566780a6a797c08d5bb85e33a763f04527656e12a41ff84370c3e291c6c09a3a29d1c32b6e764597ffa4344854b897633742bd51e5da77e8ae7a18df11f414a5de2e4fec4282a1c4785795a65731dc2590b808283e308026a7bddf05cd19c27a862beba419f8b4ae0da78c277568da949782bf1318bab4db706bd337f9db93045148d7ca98ce658c1ea67601f3691709fcaacfe15e67992e8ccfdd281893925002e1160f088fc8861120f360cc2ce1c274769e1f4c08c794c7a6b088db41c7eb76f0be9a88acae4e357d72a36415236ea288b94b1953c342339edbb2a0b78cede7454037a6b61e1bf46ed62be5725eda776ac8a9f8349d7a3560f8113081c70de399eec7aaf78e23e45d420aee5d19e7576890468d311729e66935c0d9c055e140a04930520322ea4070ade7d0bdf09640b82e978bcd45e211af712f17c346121566554b6a51189ba662177b27d29d1365151158484f4d55a3bcc2f706341341a672b10f715c261e554e74cf300198035543be72b142b75185f58daa6b1a0b4c8ce1e91465c3e4a3af1ec06fb2b8788816e29819623982e0936c1dafb552997b90a5bdb90c929822aede46fcf9334c809cc916aacaff608b5c4341ca0f7420824ff56404fea39559349751ab6fa0d175d3d75b941b1ec279050f0c2ad0812fa7ece3d3f99315fafb3bba64fef581ab02f847aa5f818f6ddfd581dcb9d46b222da96d499ed62dff3bd46a65bb0d10b208f0bea1130262945552d4bd3e4101d0525d9b8cccaf7b003bef162456023608dd332d269c09309190005247bd4f16ae860632a36b1010e1bd990a75505f26774a83d6e0445f995bdf8f744757cc137567be726c6f0332346705f55f41fb7d8093a021046d580449f015515be17923f0c8578a63d8abdad36918a8af0979c64bca2d8d16229ad20d077ec61318900a7a24dac1d4a165e58dd44f1947d444b01d0f8ddf29f1f17025aa28ee09c677d668d7b99a990b7e58219398520a6bf186bf942b041c9c571205f609fe10752e80bde5993b46086cc5dfb3c4a96dd645c51d19a40c06bd4546a6d4b14514c4b6042e12a188e522c17b41d90d5d26fb7911deb63dcfc3a70b2af584a74b2c7b300314e9e3096f117188f419139ac54911377e07918614e3f1ac7c3dd93ca24c5eb1c3dc0cb95f8ef5fd7b14bcea67300e3c4ccfa81ed5410bd2334d03c5a3874af805a35e5ec4df84e16337da1b1810d6860b4eed3fcee93a0c705e098f57fb0ad1df3d7c8a9dcaeeb52cd223b2c1d9c558fce01daba9067a905c5b082f1d18f9d2f9699d7b118fb904ba254345ccd393f4c6158de627272c8ec4021d10de4948555c6a203398d9310a586efbfb78ec0201721704144368b4ad5299507db75bebcf52b0e138f5409520e1ddbe42fba543f7e5684c43282f57df2d6e9242371e58c609001221d883690b28a52d48ee09a782ceda285546aa072505e1b273390878c0119b95b7738264f85cc066711234e638f39843594a4dea39ae4f134b5695ca3368100fe1c8b78bb7478ef98414c37971ef571f9ec89b0939e9e53d38065bf1c67cfe1c96f12f81611901f46ad839599ad54f23e3067a4894d580b785074b0aabd6e1e2b88039c079320c2bdbcc6cb8eb8a5576fe2353a69e329cb2ce04a32c3fb2ba04d6c2de341329e4756e8c531bec6a6fdef7a42df82c18878a767ff0491412aa56eaf15d3fb602b2df15ec8b84245781b9c70f444660865e18c5b4b38fd047dc76bb049774ed4913e1e56d2dce598248659b232616f44a9b5b34afc177fcf94aef602caf40637ed370de013a2b9aadfa334288feb7268e09e104a277db6ce984017102f5d9813f77e0ef0efdb1c37c56fa38db1cdb973d642e1d92b6cf0b58534b4763564ec46cc933dc16353a526b483741eef9c2beda456d1b6e9856b76007a859deed8697f38597281f4c7d25b38476eb0941d6a8c431aeccc1e6fe9cc2231cfcd15b5596abb833b9d78320b49dab563d8be39719c4fe6d5705b3eedf181a7894a5e450018b44569e0d677c6a1f045e737ee68228d3f148a938b468c7444d50fa3f173c5f451cf3e75d72c20d98141bc4c488d35227073d49429f8a3bb08d0e9c2a20e4ec5dd011a0044eb1ffde4db09c473f6c3671f910f5777a2a3b1c0723440aae533808c622d1182ca9ffc3e8fe9f9649eb0a9b2e4947d4b892a453bcdddd9c9a73db642ee62d4a139e7d70283b6e6a343b1bb31c7c0877fe53f63a26ae1e27a0b650c093362be0a2f9d224d3dd54b0bf8da84dd26e36f5ce200100e8d2b6443a5994b9c627196ca239a2eed0a7cfc74bf386748bf5ff675bfd0538c10bb6f21a2921acb8fc8fd777f95e003ff74521a199e8e69582172748044dd9179401707fc9a96bcf0dfe359d1b3fa24f7b13e1b0361028094c8cf93d854263a22cd22bcf673480aa64c83d1d5e112af05c5168491cec53767759398e4fe005967780107304cfd32267fdda87629da6babf2dc29e4c861c6b987f5bd6a66d18e9ac205b8007aede2f3faccb0e8864b0a586ef9dc21cbcb6b902c2a601448c1c26ae889a93daaf9a3f9ca2d4ab785e5c726217de90a280851a73e7124c456c4d8c4a299a7d3250b74374086665659d1fbbc17a33e8ff982d9f6f3aa412646c7b5a8802519ac7a6acc9d231a90f29bba71894b0e6622424485bcded4571383dc45728eca83e5426c7bcae31eadcd23e2e336080ba48ea683bc0717f711f5f1c6a27fb2cf48f6943ab405f2d5c460c3484d644b18f64763663276d326e0a106a1ab2dcbaf8c7049cba7d6978b39c19c560f403ef247282a687ed77f624b80e42f3c259a5a599970b8e4b3c57bec37d6fe9cc1c5815bf113a335a26acd84c71979484035fe5dcafa5a1599bb08ad5e56a36e4f59fc050c2da3c2ef30ab6cba4169eb27566a20c9a2cfb2049f70424fa2c2f27bddca8de5e79e9ab834ae52569c970ca0b5b88293748e535aaf899152f363f4f18a2bcecf75189cec9281f6d0a3c79b98b8349a665edb4e415c04c997ec09eff2f7ed9a67ad5495ee930851850e3a6c9dac9ab097442fba8070ca9eabc6e85dd89f00886120b3c20441eebf4f7d8208e88f395c9f4c8ca5dc1be4fbb779385287c927547a1d87a110db694a0f416fed6ff035edad763ba21edb502787dae01af17de584ea0f821af9c5bcca94dbb49aa7543c24d38789e13c18ec60a81afc68fc1656b5e43769a6f63fd3a848dc7b68aeae6d9af207597e1ee47a601e9577465afc5ba6634a740cda081aa1f4a506ac6965e0b2147339f1c9e04bcb9c4a666858eaaf9ed118fd673c3caf732d5e91e50bef52bb53d5b74d95666fc3670c7bbf5bb06b661224cf99f24fd0242c07a5bfa70a5b0c8762fe58e6b64ce8a66130b68da9e2db5c3ceac4dad813f23800b556ee6c83c4a3991f1893158cc0c03ff16f4295482c8687d7e6e3eb97dd6faf7083b8974ac777411f3a25e60e0e09f8bf31c3a4acc46e1f30f2f71f6161e974ff1966079920daab79a516a99bc32a7515d0941a1b938d776a8f751db425bec9d3b247ee18de19ce11c5627e84b9c8153edafa327e16253f33864ec1248b430d5cdec9fd8aca591e50bcc184717d56181c09e8b4af8886fde208104a4a880dfae6a518175ae2014a877c8975d86379fed54a8027b96b9c035082ec8cd6042bdfc4b37ff4fca6aba17240586494c1c4b2320db1429d5701132194ceec91fbf2139d59c90210baa7bf47b02571ab30489707f97e837f73aef613b3f234d9360c1232367cf2746fe2a05e3bf9bea26f5368d688b050bf03dc83bb50649f3e9637bea52ca03a1de182208b840c67c93858cfd188ddb71ccab0af47833898a5a7c3935b691cbea49a3e778db67ca16d4cbae7438253291956d67ebc9335fe6330b2e84e1484f248c7da3a712fdeb981655549f3b538f9e5e603e3546b198ff2460dec97282e0b568900906753586e01d0b5b294c82f7bd9a09f86670cbe5664269760a26cad75763e1c7193a243e9c4586f032d3431e2fb6d8b809375112fe6693e29bccf5bb43f8f2bbec70d14d4e8be0ae2a8f3d55f52cda3f38f275bb5b0f4a7a38c6c81f5568cb976713dffed50aeec5cfb3b61d6724f8ac9a3ebeb6eb78843ba136da1407928d3d100f64a117091e0cce29bb053b301a47849a20d4b5d2f7dc46c455aa5b326d9ed8f5203998979f06f24af5f83c9088809572c2daed191cbb82a1d37b108eb4e2db555b8835095045e550dfeff6fa4ebfd3f7bafd5ed7a99b3954bb9ce5a1aa72641de9282e3a097a620a18113ab0099b9be545a52340840c4c0418b2c0f9405417d27887e2763caa1b95c8fc83488facbacdf1c7fa7092a133210e54284bf610950e6a4064fad8e51e913e0cee7069f958d3d142c3ba43780254b62c5ccf720cf6d61b01ebf574b6b307d5f3c17cadb52ff0bc39fc4d9045d6ff6fb7dbb2ab30bc3de997b4b19b1591acfbfc5af726cc16bce4a55f5fb35eb0ace234ab00f5e2f7e4109dd034d6c347fb8f4f95789905d3a5f9018413f660d7b629737825b81f4cecbc7248a669ab61f3390c3d9b154f07431795f30477b07a9dda2a9535e0ae5db186117b21f27e5c5998981c362e3fcbcae6b4f5f999adcd6e6bb7b7c5dee2b7f1fb982c2c2e0b8f97cd66f2597afd6cd666b7b5dbdb332cbd54485f1b141c448223c2f2f0c868ac41122c05e3f3c249ae51d410be18bdb2e572ed73b252bd9f06f30d07d53783589c20c770d96c06eb707960b56f90a71448af05eb98f3415060874919d10f465e904a4f76b99d8fee164e1e7cdcbe7cfff8fde0899ffdcbfc67b478395d7cbe66dbd3edf2fb375b3f9fafdfdfe3cdfbe5fef33f593d5cae1e3fa3ddeb747733217239fc1220b231068a254663b7a2b44d55b4bf9005c7af276c755eab0590dac9a6b49274af446502549b3b03703389321fc1258829afa7a423419680637b2fd288893b3a140f856a593056c0a4f57b2c1f80ea1d14cf71ed0a4ad7a872140bb75837816553a85a80a225d4ec41c9002a76b8600ef52a50aec66a5154ac855a09944a51a5020a95b04e8f650250a5832239ae5141891a5588628116eb23b03c0ad509509c84da3c280d40650e17c6a12e05cad258158a8ab25013819228aa48404112d6e3b11c00aa71500cc7b5282845a34a502cc4621d049641a10a018a905083072500a8c0c5f4b772d4d45d31aa54555456a8ae52510114bbf2cbac5a7a88405b72b410ed3229bfe44a2c4d29cb579612945e6e2594ad4ce52b79894a2ba5fa8bdaa868fa399b589e91ccba6c3595ceba683525c970310e76f1bb7e1d670efb0a7f445dd2d9175aade74b399f555c20cb05e32cf41a3b4884c718259c37375357191254c9e5c07efbbca0effccd6d7287569cca463685dac13824181b7716a4dbc550bdbd62bf3ad93aa7c0a2f011306f9330ef21b8b0f495106a597f4a5dfdd19372f274652ccd13b7bb5c9441a94b40ba30c5802a22bbe704243528261c32c499edf791ee86cb26c55fb31952a59f668f8aaf960bbcc37f5f235309f42a905d6f9aaf76f1cc787f5882eb6ac458f91cb5eafea7685ab2f98db449e842f770623921ceb6a10d06d85776a093dc1769f63c427c8600c28750a9311c1f708c1769f91fdafd9fc11bddb93cbe8dee3a8de7ce3b0ec9d2f4e41608afac3845cae7182edff1a893c377feb4a11f5b7983ce1983bed075359aa7778e74ede7b51b5d7b79ec446316bb78e841530edef3ffd13d46ef453a17e97bb92bf29ee23bd2ddcf75b7a7bda2705ac4a7f02ef778e0ee20147fa3dc99f036e2cc285f1bae6cf1b4e4c8389f34f7204fe51c3f3db63aa99d69431ec28c285f7d683d03137252919f36e14b52de10cf5143c49e81036c3726e4664f34f0d71c495103212c39bee4d79f9633b08e8b2b304065120cc043bfdb2ca9cbbe6ffc2a0a43b44b8d90c06be7e8a261f07b56efc9de6e562ff856113be55a803c6018b7af2339aa831bf63759c0e002782c24b9ff7eca0fbf1a0024b526d9faa24d552306aa8cfc48bff641498ec6c1ac2223567ab5b44238380d09961045125be2498a990279b771db9e103242690b31a61fc481aff08ff24fcb437912140ecdc34cf5695b94456a11ea58c709324032d973ee15757661eb85831b20a6eaa23c595e46ce9dddcd3d2bfe553a327e65a08bfbc3b3506850067a7abe37627b0c751c89782c2f108c83bdd9f687ea55ab5e10f54228d8ebd2187af27525314b54d1ac578ba17dd081d23fba57217a7510fbddaad783e11b76f8d5dfc537195906bf0784e04f88fc0a750d4b5401f9651c9c866b8c27eb23319b7ccc40242e96b204cde88cd25059c4df680e303c18db521d64d25c875c1d6cd74f8ff3e9ccaa5cffcc887846a783699bd83711e31b736aa3f43abd1d62df19529567a641208718396704550cd0a5ea59f1f6fe58389beda73c078b2820bd7cece8f2350254d6b9bfe15f040729c9406062e18c8625ec12ce88e8f177f5147b71298fa31ce28ee42a082a9a8042a985f67dcdd4b4b0310aced0459c7b88920bc4209c7a060cb5ac01dc9bcc25782216b32af500a3d9768906f3a20c3ecef1df678f106ee06cc1bc7d1f306cad19b454629297e040d9009da0a025da5203e91d362c142a662f8743105c83d0c17dcd77a497a22f9f830c9cf90a7a3f480fa0e001e21a07b299058dede2c1da61972b6b1804931cc9c2ca5e0ef867fe382d5d193bec2b476ede2d8fa6464c11c44107a0155121b60c7659c5d070792184efc643fd8b84950804185ce550746f49437f04c9cd8e46a2d8b275c894c0be9b64babc0afc058e0b149d6447c54d1d36d2711e54888103a273e89591c46b0d65526cdeab7a6fa301eb2a948e07570ec4a351746e2af72e5a9235260f890cd248436a00626161ef7f68cd486acbcff8c50e4ae093cd2faecf377d7ea3aa82f71be59c7fa1aba01d8022be2918dfd90c0be06b39d594b6d69087f2f3d044721aa54207ec5115c7d72dc0d2434db7d7de1a45ff3416f9f9f6d8cdc42f401dd41eb666b25a8258925ce35e85223642d9e3e85282f40319b9bf1f15e466c4c9632528951441c1e64cec0fee626c150402835f1b957386383a96070fa794fda2156bcb03bfdb9fae6424945ad023989391938268946145cebe9189e1aca53ea46c490ae4ca23915c45b0a9c30b794b1e876c796baf3a161e69ef940338c171569016664cda83b22197dedf85f4238f298e8e30f9dd848270e4f024683f1e4a93b104eaa09f59adc36bd5e7c1dcf214c63c5a0160dd13b6250fe7d5cc55bf460d943f130a754640b77603ed5d56eb8f9148a61585c2dbde5bafd62fa537f327eb12e2d7cf7ff2d9bd2b5c933595e4848a5ca40d836f1fbd5dae91c18c3c5e81396608fb422dc8ac4a9059f342166f6ee9ce42777d0ee1d8e939265c2835923a8e5583a7ba68f56aa631b45cc08006cd0845b7bec681742e71a088b303c92499e9ae0ed2eaecc97df737b9116a7434521236b109abc535cb987e5cdb6a6943d1bf33765c4cee20b3156e5f8d93c9fa8b696cfcc613ed758cc18fe7eb2dfaf74124ef42b56df2083b1c20b1424785ba94e70b1cda8ccb9b871704e4aa7558f49acd71210fd9174bad3f298b106d1a288f33b4f29f6f66e33bc045e8695533f8c600ce625058d9604b207930d2448d7904426ef1b7e8f41f2d083e818176f39329e7a7bfc6410be45f92373a5937435f7486028f9f0405ab14aa597c49921e132a6b356b737a3d5b5992a19df28138565daa4945a41fc8d1d85ed8370c8ff7f86a3e4c5b1c995347434467885132ef2eb1c20e5fb9f3ecd42773454f632ad5eacdb2daecf801351f2e33299c348328ced70394e3d48ea314a6659237be49a22067ab0678a0d4e9662934c7e06c1a19d9b6fc3e0f90bb879f849e3f6132e0051ac77f50bdd3cd2440f7f132cc88594ad6f563d47a495685670010599cb90242effda082a4771a4a7420fdd452cefc839a70012646ddeffb04fbdf4c28cb78a12276242e15d96af60f3fd61a73dec424c62724de2f065ec699c9ef22a78755685fe321f18f8f08ecaba9b60d45fcb1f0a9a608dc362f3524d7c5ecdf1dcccd00cc1e165f6524eaf205086cc5f630feecc80b00e71168888001a69507cd16eeed22c68b363d0cf16244c11b7ffb569e36860d53382ee1a0e4d821e39d0e0a8699c5203032c8781f9f2fa9ce8a8ccf9031ffa8b4d5472fe6ad7ec8d090b113e87badabc1d5a7d91dcfac8aa95b3b7470fc879751783f183f42801788c3ffa199b8fd0cd8089a3045465834b468088d224339726095b53111bd81e5d1e2584809d4c0292d17b74bb2c495ba08416e25316d44865c07531d529656c57d7e443fb1fd6f41fb59cb3efdb6238306766427a172ec38dbb4701066a603b00760b200f8fe3bccf22da1170370ff0de17cff79e15608e01c93fc4ca0f86eaecb9e8a3151f66112d145dedc85892a3e7a3e4c13258827faa66eab07f9e2dac0e2acb7f54e688a20ef768047a6df761dd020857d406c0b411594af728140509abed80ab5c4513a40f5aed1e070f335285509bbb6ecd1a06db3e02447097d71a3879ce5c4570e961ac15672dad5719f6193aa86da820f58f7007205380dd7690e7badf9620c9163f7602b9029001b45d5a237e2c37991d64ef155bda615801e6a6917f71ab82875c5c23673efd6c22bca7162d8d4e23148d2752d5b6b7a46e6818e4145b4ee48b92d2027fc4f4befad861997901ac250d3f2d22456ac781ad08c85945b03e25521a2fd12a03945d7e204a43ff193ba820c479e4ac0b6f672719887a1489e8df1e31cb3e8d181a5cde6e4011c9bd870d72f9d2128f75108c8c74a619dfee9fc842481f43636206c88ba2d6748a134dfc67e4e29922800eed5da3ffd5d88bdcbc20eb8bb81302852edbbcd99450860ce1549420ca6de8232b60155599436c7e3133ce914b542c19dee418cadd10c8109ce94c9229cb6b2e5ca2623412d0a3ccea2bc4304f33ca83fdb62fddc2a5c7b467eb8b42463e3bd16fc8e223de7f38f1050c79203f016582656c3d515ca8a7345a3f334ab08191b82963a85ad753c5c21128c518f6a95ce772304ae2c54aa29924197caae441d7d8db25b29d413de2c6f81e173519b8c9f6e151929af9a03c6f3173da73776ea54cf9ec5b4172bad0cf9afd6ed839bc80d688e31548f34484c3077254e14162b5d00d446e3b2dc0e23aa15c0edca77cebd210e9ae38632131b6b4749c2ea90f87c8c3301569a076753aff7c6865e92c5d3cd8395f0e4b07ee9d24ed3d20d76b8658c225cda06ab0d3686641274a6310d7eb1728c59fd075dcfec6a1a1be928cfe159bd4b9526be3bcc6f1eb44ea171830031523d4ee13d1b8bb634bea1eefbae3bcf93a909c6ce1c50f122c866fded90e6e32dfa3c418292a3efb0f3edeada586a3e302c378770cd8761bffe8796001bc1215e2325de2b98b0580c352705c0e9518865810c58688a01a85c49d1535120a6d7934ff9a461fe17e8ee0fcc6c21daea42610f61936e01b99101abed42644600b942f3a250740d63443cd530236c8fa60c65cdb3140b6aea2e7e459b16062101fb536bbe15f105404b95ee450a3032951a9ec8677efbda625928ad79656a8ea8bef72ec80677a04cd7a051678e4a2dd3da46a6c58e883a0811bb592806ed11b16822c5beadf56d552693b23295b3c3b978221e400bcc8af3d3f9c250572619f8dd57f8c1972fae07905e191f985a4e342037a3b6a219b6edca0283796508b5bd12fe090571eb3ec3883f906acd223a8db386975abcc2b75a3fae4c56ca82116dee37eb1749ca5297ac45fd2ac5d95aded39644e491174287941fe902f5b75fe9b75af9683beee650c023988e1cecdc785a98349729decdbba009eb1b1687a126bc5a57a9a7934024e389450016282d56783d49b55149f44924f498cad3154efc2741721923d8eb2ee423587ecf3196479fcdd004887e48cfd3de1b1f9397b275256c7fcb64d0e9a50e69fd3102d4e7bab90405665ac9349d245bb803ce55005e4b031cee098d56ff4914e70f1a4881a78101b626c250edbae314a797c94942250c708e49fe4768faaaa25fa37eb1966c7acc5284f564d5c46aa11188d8ea140dacf781e53310e9343d49c6e91cd6343d824f1ddc0355eb9279996877e6ea65ad4df90c53815accb75b55d77b2aacc626b0618a1dcf5ba374b4881620e447152e077829f23c09356a94343a8f10b4cafbedff3c2f5f8bd2e5abe81648531de33061027fe687292ba2e2dad67be9c5a37499612e4074b64be79a76a67b9f83d11fabe942489de6e431e82e8c65ca06dbbf9c0ae93eeb497f596921ccce74adf2fec312995d6c3bd042c72048f27b7222f8b48de29350d788737a921d17896240ead1e6915a298c73ff0c50075b5d2b955404919e6d9001513e2deb974da021447a54754632033200403be81b940d97e003f181ce2fe8f72754c3faf9fa78804c8c3075335fd0fa09582102486a120314ddfa2fa2810441c54b9dc128212ad0184429aa40954431cb188959e33903686925c9907025892b2c61d345d8cbf6fa88ee4bc88ba9ded8758f8e6bc8c9ca0c04e335c0099698533d568bbdea05394294ce3ae8848a5f5d04e59ca3e0bdb8e70d226fe5345478f17c96103b8ed8b9158a288295b0f0dd8b6e0401463f9023243b8501662a5a0f4f6072e7a032ea1797026d487e222d9c0a3d3e4dcfc1230dde6b16c67ffa6ee89a74ecef45b4622b47671093485eea12ff2a64703ebe00d6fcd914ef0b267e73259ebce2b8b11ab160f7273adb90372b22198f16679caa1b94d2d946d1366bffa2533c5ba0fcec3cac0229715304eece1b132e76ea231077205da0b968abb9b08a2c075652beb6a048271e791947a840c356a08977b4ac64fd146199270312f06f8d224521c022f2bfe9fbafab1920ed28aa03a84506065cee71be4855591b19400c7a00b32625599a08140aea4ea55dd753aef9fa52a42f7704e187861177afb5276c4415fcdd2a014cbc7a7b10cc2e42ee99e962a506518f89b0aebd4410788ceb1a5288609dfeb20d268f2f83934e81718401d57446d8ad5ba9697bf1d94705cc965e5a63da7f4582293ff1bf0c22af81e9b4df14e5b2902f4726b59fe932e7536b0b1ff9ccc71a382b07ea79018f9b477ad93c79a3357801cd8a6047c6122e26cd789e903bcf844fda6383ddbca8ee7f2c161a4e8deffac03282ac74ceb0617b5df1997fe0c5629455be791d8b7a985797207098348347ecc1e158e90b48208b3ba0c46d1cdfb6c3116d52ee76f543cc14fec689e00c42e747e9ad635f5298184c59660929a0f3d9f1b46504aae2f04c88efef1a2163f98a50290b4cf12e571508a3878ee9600f266c10edace59d2ab4177009037db24ee545c68cb96a640caba984852bb6b635ea0d18b6b6923cc01574c77185f3d97fa00cbb1588402ab66642149a8888bff025f5316f448e0481b257c584eb19e47738374083e87e155c15920529540711672e47a16e6090f9cfc80a4541290f80ef98f4413f18e84316fbe22318e71a3a39479318dd4f749490e2934721af32fdabd1a1db25750c5f0f206209cc38dda536fe29a509c11d270366ff0172e4ea9c81a04414cd6ff93223bd80f95674b01c8b6d06712cca24d221066816177da2c8a610a9a34190916527da094d18ac2e2e0ee8005cd5662f1ff09b4d307fde450234f7a1fa4247bc03747621bcfc23527e56e7f7b97680425185c48d1d47f6351441e8e6b0d3df405b887eaf55586e5142f33c83167a686d11e9bf4208ee8ecda5a4fe41b8596c44759ceaa4bf96b8f80f988b724e0d9bc7baece3dda5983ca2d149184480c44fcb619566d08156d99e351dc0781d80adf2b553d47136f96b9b64d839513a9236e30481781d61d83cb2936131dc37b3f825b9ec962d8cfa1d8495222432cb3fb33dc47243df6e4c6b59b08f1635bb172d89a08fca80e8e51a8e883fd54d9982ba081039a40371c5951796626161397b50bc6546097c66b405ceb92b33a903ceb4810a91d0890f9607e0bc267c6531d27ccc45615602e9dea58cdc8bd64720f020c88912366984ad8c43b33c88aa3a52cbb1406548c19f4e86287a1762c5397eaef00187245afce1faeef804f89524ee24faa7c52d44ca867543c61c3e4730028a2c4a8437710f9b4cf7a3d231b85a8fc6e2e063db9d90165341816dc2d4ec137ab6ac4db9d2edbaf87e170960fd8385aee17f5d7c8356eef7dda8160a5253238e14052ee5865457b7dfca29f725e4b2595f04f14523dbefcd9b3fe2e064ca7c4bf3c34871b791c90ae65de80edeb2ad0add547aaf493dbb3469a6eb97f42470de4edade78694ba7897061465076fbf20dfb8a43a9abb7be1727889a5d28c5e30633b883f2e3eb6073101642f90bc30e06ec62bb011c1308457b396c57cc380962bb87264c6f57160804443fdace41bd77a32915088fccae23ed73e0ca9ef04ec140ea4fd381100724d8df56f77c3073109c7159a0a65f6e3f64442f77d4a8eb2ab1b8de6b94abefbbdaf06ea59d0c7e8c2e5b1d4e768d15297fc3c18a8fa4d0a732c5829f5890e8a186dbb8131384bc74ba9e2abcac4f004d816753c95189289a316eb18bc500322655868699b7f8f941655585576ff73640d9092490229ad3a727c44fdaa4d6d91a8206084f0700314fb2a26fb6344eae14f67dc58d6e5e4eed8337f811fedccee2ded92cba9d9c4bb60827785a6796d8afdf300dd3ae66991f1f93e219ead00e9fef67ae1010b128f7a3eb0712cd091e9e31f597cfe315032ef1c371d2759507c85b834034a2ddc41d3634e3c40b67c21943a5ea0393e5204364ae0140fa8b4cb603ac990921eb34aeae0fa3b886de692db029350fb90b18a1f13797fcd9d2ed6b89180233622e803ef3102d47748dbe45f18889ec4913d43cde4a1403e3054629e2d908191157febd4f12a38ae9df63202ee2fea0b4afc3ca73db69eb66e72769f9407619d6c64645bdc330e209a7f0073a5e7d613838c0779d9e3d56b2a49a841d372886e1c17e089b42acdfb0d99b86c846c64e2510814c3faf421fe38268bbd0b48e29a5ac4a36a9dffac68db34c509da80ef154d2deaea1f721fb385bd3adae453ccfc2399aa8733da699f1e99701f286e6c135b9d2a3ad44b023df26f208d747422789ecc2881a8d907b99ab1f0306fa271fd974758729f641bee536add31af479389770ca8ec9ec492c699863bb7e3cca47d424a8c1546d41ef06d0772796a419bb7d6154082f8dc2dc5df41b8f836a34a420e1533e0a4229770a983829fa8117add35ba4c50edd26ab49e920344490e12d78c2aaf58eeaceeb6696d0780ce409055e7184fd0d55205a594d3a4de344ece59a380198bd6512eb6f1789f6c794e3f672d1ae31c8c4bfa995619081b43ba2f5158596aec98d023ef7df86a2699cb0a8a7655ff065e5343436f18884fc7b7fb335b39610b209d97bcbbd037c0d2e0ea80d25d476ee53729b9765509e11cab156b8c462d55a617f2719acfae911dbed9989471411672b948b6fb7edaadf6e2edd1e196c7f7a67bd3eb16c6153a95b7b9aea209b3add86f2b36d572cae2e68cccb216679f3d5e7644f53cacb5bf993ac1ce420dc209497af1c5c7910bb8818daeeb25b797d175e1ba5b69be2cf29d54d29058e8f37c5dbf853e762e545cc51cea76379342fdef7d5cc54aa4030ea9bc762d55ada7e6a3579736bae721c5747d0144ac104b8db480a0cc5161855f2248c9eeca134d55a6f2e19d95ab9b3587bcce50ccc01f7b414ed85ce02c79f3a0d38def61b325cb32c93305ab9775ac9e4410c73a93812b1e94667c0dc566ff2502cb025cfe6c606b6d51b5bfe70af5b3369a08e411993af98d3f710cce14edfaa87f1226cd568a53f1a9130e54aa818572a7172a884e2625398d06e82297753b0a63a81372730303716c9163d8d58f447db4749bbde82366c2b2936c723080328b852d94f564ab0b127b8de95116c9630885f6d245bf455895d62c484be50d4dd8e6b8dd99e3919efb2b53dc683f14c2fdfbcec9c2c79d16ea5178e7b297915776dd44814ee1c256d422d047dcce91a6ccc2906f5530f2dc771db4f1e4e8d1faec2b897b41a58eef287e3eaadb56e31576e5ef6f22c225996aaf4a845673dfb1c8fec8d48fd7db4aa6eea3614a17e79410a03e6a290b67197daed31b7d620db41d57463abb5d61bb5e88f22b510f499b51de5e5ed9c6732c1a44f7f746e9b4cc29264b7a3aea5a8db6714aa8560b7a37a6c17827a359da62c9626af8fb0a8dbdba82136996e9452461b6d26506c8e455ab42bb78f114b2c926d614edf3e1042784a5dd5b73615817a55adce7d65f22067bd224ccfe27949e0900fa61fa68f47510b16cb5aa197ccb743fa6dbb453e6cc48463b6478137d471c9b341c4909402b6e84180e94d80e959205f70a7c629985ec2600d95b01eda3a28096910c2d009182601090d189a6ef0c85c2471c70555b75b6b3daa6a42b55acb1d751b4ac9abf5a56b62bd636d3ffd458c0b6365eec9e4f2cceb624ac5715bd7dd86325ba85ddb8579decedd8622b47d3bea76507f5ea9a64c5e0a9ab6edf41d44df42ed82b5d65aabcaf326d10c9ca42ee55edbd5586c5e1f5d61b7363a6a170403a6df3c0806a0ac34b973970c536401c31d57e26a10c72d695753214ac3154c255783da956352d3673ec0d4a4a3b712672a0282014330602aea656ea3512db01d6b57bd254efe402704d124205981294c4219948c20062501090bae964c46c4ee548aa624646e4c922d7a981bc303f3981c3cb2451fc50ec5c2b5a798245f302ab6c71c20e63297b950c4388971b803e33137c689cce14ecce10e7d9b6e6c17c5021bc3fb01c303521444b6e863bc2145161e21f19ee88fc2a48dbbf5be6481b4ba8b6cb572b1ca5eb22ccbb26c95ad562b96576350e7280ad5d88584f9d0cb2512885e4e2185289551303d8adbdaa85dd40c50e81b0b5a5da8698a0b24e09a055cabc0b5d667f31b8b4395622dd5a3aa8b7a677f59cbbcfc6ab57a71a9808941d1c3781bcc515ee4bc98c40aec679331d806ed46374a8f4a8145a281a29d981f9a94884f76626ea3db48be626e0cea7107e622893b327ffc912d7a94cf4fcc8d01c53aa85b25c1d2430c7112ecf6885197309944faa0bc86d29f507ff433a83f5a830eea3a4b5112464fa6eda59b5b0abc3d3bb4d17d74996716e6582e13e3c178909ebb190866b919f5ee5d47bf79b3bfeca91a58eeb98d30ed206a6f10a6700a9e58c26480e3690b810738ded437c0f1a5b9011c9f4ddc58f451ed3ad9ed7487f22561b2451f81b084c9d7a3ddb27315439bc5c427fdd1c39d188405fb641b0a03e65e6f2dec679303e66e96314c256cd32cccad17d6593643af1049d4d211082ae8a60793df3e52b68f87731c32021a8a3020a308337abb724b8123ec4fd36e36af0f34dd681f58337f666c49fbf4f3847836394ad3324d7b7ff1b2ce5ab5ec534e0cdf5168b1570044822050b141f67399c462599b3483b636d8fe0a09b6c6f9f8291fef64d2a7f929679491d239f1bc31ce0cd65fcf9bf9dc2c09a4252d60303c4fc7c16c9eb8c47dc0c64f589c40fd451ce3bd93499669f31dcc62ad70c6d9f424aff4d772356427ce99121ccf326f96a4bfcc2783cd0c36331f979bc1329812dc7366496491cce34e9f9ee9d3cbbc52374d45646b288216b258c30bc4e0051c9ffbe76be8001663c8a060023278610d2f108311ead3f330351591f920054ff8422602272401890019144c4006231c2f845fa6900a4f28b2219bc04416afaeed4d26a99ea267b0945e8a457fd40c3622c957cc736511c957cc85b0a53a8cbcb9aa1e6fb6ac0b616b5e22cd4aa22024dc44f9db8d79aba7794120d111603fe21430474953f183222c01370ba2e01c93c42538348d1b3667593789f5e902ce2c19b18dce7e5c742a04b4a588b8a7a5c0f1f30af2d239ab8c724a0a276d4a298c4c640f4b29abe7617a48b110dae3e149257d02aa6bd7ecfd2e8315f6a4701e6a980749b006e2dc3a98076d803420ce24ce32287176888564b75e28b1c4282c670035292b8450de0ce1e1e7a390196384b7462984af7e5f85365482dad0cdcf096bfa1d109c8f61149c4bf07052af09134a48618c31d20ba305b2f0f992e668456bd17d39214f7f31cf5b2734026be2a709e04c96309b253c9cb891441a48b131a59cf4b877b364f23aed79461892a813af441afddc78f647a98948240236121f712ca27f657b6f2fdddcdd49b206b0bc0d8335fdeeddcd0dc35cc34af14ad810de90c5ba755e4e99b5fca49d75ff2e16cb46d9b2d112c7186dfa93565a2ce394f22b17501918e1f9ee45ce09a57c1181adf9063ce77c0f813573d6be73f5022b5f6485488b2958f8804860ce76f81cf025218c907ce590ad7ead9605a7c026e022716222f01561abbf6da9d40beee7971cf21585ba355fabb5ac29424fc817f7da1de99f0dceb597bb1012c19a18a508074f1b9cddfce11993ac40aa7244254ac1b36fcc0e9c8d68387e47bc4ea0e02eff431e09157d313d803c17df3707c17d1bb267665e21d128eb4d8a2ec2961d638c31b6fcf47a5858de981df0510946b40a83c18c683d83a1cc0a4757855f3c7c85af126c652358ca5a0241076148935a08f824b39b52ca52d5e68c3efdc1f73c829daf5a179326f52252524cbad14a74129d983ebd24b9d321452b3129466c3a7c3492afd39f90af8eda2451d53f3d44cc01a088918f3b48e2ce0e8c3e743e015155b6e0a1a594ce3967bc4946780249bf22524cd24a9630c14d6a4492affe89483f3122fdc8d705600b1e4a81e12908303cbcfc81b481303c343d016b60ff004579733fe99f38bd2caa9e5fedbc2c9eca7a913bd7f1c6681df36ee6b15889149e16d9941783236227dd4f2ff9d84bef1310751b09b9d3bd7ffa83744e19e58c31c6f7a3474f5e348a47b2054b5e84c916ec599992903bdd7d42b620120e40b0812460fa880473c4b13fbd9e1596973bd0246fc77a497fb07f92983b4fc816fc317c8649361107c60ec2508606b628ba6ed9a2833330be93d9a5ec1a33486bcf8eb7b6348a47134a1ca8c4a3d872d24cab1bd7954c27944da958562d2e5c582f3031322f60c4b87765cce8b0030f5fab64a35d334a910b50a7c5a50bd8071bf9ba393c8e7c0571781b44e468178cc3f368d70fcfe3e347bbea76eef04db4ab2b1dbea75da6c30f69d7e9f046da853afc1348da6561d1a75dabc34725ed6a397c842e878fb176b10e5f0e1fe12394397c71983abc8733873a1cee70c8c3e177f848a55dad43193d1cd21c3e5a0173621cbee627ac7cd9d078666120fe038d37e13783e6367ac6e3cd487a98f1dd69c2d138c666858dbf0962876720323c191d649a6879ac195690cf5bc958f5f0e0d96b87ece095bc92111dbcfafa048ef1f8196fc2cf7b0c938e89651c7a8f3723c1313eefde8cf102c685a5ba055bf424e5f988a932c50b8f07862848c6e3f142054a8c9783354508c623c2454a14515e3c1b2e6cb0bc1a2d358870f1705638395c78372c373c5a3c1bf8cdab5233b5f268e0379fa26101c263fd604d3ae6f703cb0a5bf3343c54ea64d261712aa532a552d6879a9249c7c4a61b3c2c160d9e3eb0fcb8ef07ca9bd966963879af0762f2643499264a1e2b6305c17245573d58da69876c5e49962afcb2d71e9a25061df4629e3f1c4fb58c6a1ad5321a238634608fc67d673c27b542ad65940e56dbc1199c1b1b9a4c7efdc199fea076cd93dab539ad684847585831fb8bc742a8112a6f53c170ced3098f2784f231e6e7a19c3136ec121554c07be073de9c4938b39969edc1fe6036db081f088203176cec0cfe9cc133184a29673084aef8392d2c0538b330946ef899c159426674e2b4cba6c6849bcdb6f900d2cfc1b3441023b0865ae0ee6f55c3c1a971d3d9e5c971797cc1e6efe3dea7e1260d039cfd4a02a110b03f7a0ffc30be548af238226efae8d9fe6869f382a51d5997afd30ff42296b9b1f1d14439e124923ce890307d272323d3ae3e2cd55bf9aaf7932d7a6a050e855420c5d4be88e816bd8dfee86d74890336574c9fbf0f531b9fcd4d0d1f40da057b7005675884e97350c134c8072590b34d3776681429b69c03b4995956c2f2ba66fa8bde674342584fd32e58fbf2317b07212c6179082184d0660332cad8514a29a594d1650656764093851c10e1ccc23868d2f10654f03bca778718c21c22168802370dee4719567f1f3cbd7c7cf6cc8a1052188b40a81d1e9a8c2012b7c035ce4ba4881138b56b5788fc24323f0fe332c56a8738da95398b85b3cbea2ff69434fd75dfac033858be676666bad335b158f4a6e16d68be6e6bc1afa600786ef7cbbcf6320266e0e127678820c1f331cbb298c5ac2714649c47bffc7618972864092185a552e9e6ceab50d2ce8358f606e7c5f966faebaf09226844cf935d49448e3964d433798624b62c78822ca35996655996655996d18c525ae9119e48598ac55dc8761d5be976b3c254ce70be57bb92a1b9b1414496ad4a35cb32a8bdd4410bbbf47a68d251ba1bec158eb366449a14f9da5a555e2112bd6c64458832d1738942cc41447f393adae8c75873109183f673f4d094f89384764098beb398f6e711cc61c1704abbfa2e51b074ca4c82397dfa99c5cc621ee1bedc10c704fa12bd45a245d48862418fdae569f193f9607a9a44af644b307dd53268b2432cee7740b24a85ed9aae22f4163380872fb0a6bd557f10c208040526aff09bb90d8d0d38641407394461c88461bb34978d2525cfdec5d4b76bd63a33ffcd5bd6bc8ccd7c8d1cf306cfaac958bbe68c20e8d29cab28b63f6130dcb7d4df9cdbe78d49b63b046922e96ff66390ee69575f20fd794b44b1f2517a3cfdcd12eeba346dec3e39d9be5d241ad861c9562c63818d40fdcdcf2c66e30ca2454055583b04737230f7bcc19cad8a498416020b1f63122ab8b3604eccd142c4b747447ff1191c2c7c1126dc65576c87a317ac0d2272449a9dd6775dcaaed8128ef33b84b4672a226e812f7cbd9d5d6a1e7dd3b3b22bb671949141c32224211489b848c4998559b026de4663089d8023ac02c72ce0788a0479e210ce2c1b9d02aa4a3af9ae6a99a95432552d3b75068b30844439e40bda1c47be3a784f56584aa5c7aad78b3b97af1861c904614d76bb8ea61b3cd22b99629030bdf403984a3f00942d6a321d4977d345c2bd74e1b53c49bafb1eb03f5c5bc362093830420db1b90f37c7e88387d3ae3ce31dd47a43e92f3bfcac257978ebe3f0ab021c9e95c4e1659038008e73f89976659de71c9ea65d5900363487bf695776790f5addb8207ea05183935363081efee9f01d66647425d3e9e5120227a7c610de6f8c1fc60b944da96e7e3810346e53731f70726a0c7198632e73d87217878f57da9559be3a44327710700871129e0f267e84c7b380bb3c1e0ab88d77e339a1bd009e4d006e2ec05b02b899e734496436d4c5a30037b79e04fd114b6447f05882014782890200e0669ef7c084ce0c26664c26241333987031e19ab2f5799da8f4d975a26653328001ad9b03f08c0174326046eb49a890374fb9c4124bf858620900fc88257496a0e921bb0faa840c253e258e78122a3425aa124af4b859c68f50e2d37828b1c402ea7758c0cc75a22ec075c47b2cc0889905d805b88eb879d3766edee1dc75a2caf8779da8dc1137f3dc88eb44e9881d6edef9cc75c2cab87900e7ae137646c69350b1ddbcfd089e9bb91bf11ef59a123cee524273f128a144d5947029f1eda09da7bec75f9e0d8e9b0df01745dcfce297c79350d1d9945c2fd73d0e1ed7098be3e552e24228e04544bda180cef597028420e2e61f865540e7bad9a4dd9fae13f5c5715c27ea4909d7cd3c2e84122e21701c86122f6e2ee2a7eb84550286e966d35d3c6e3e5d88bf7ef3bd01ae13b554dfdd9c87cd5f3f5e4f42c5fd8f52f7e3fe49a8b8b9b9b3b9b9f4d781006225030410b7b9b191218001ae131abef9e6363fee83e784869d00e1038c8e9b61eee23a511320e3c2e6402440e543027cc87199eb84c54e120073b3cc5d5c276c02606c6e4e693b6ed671d575a262273f5627c075a2aaae1325ece4878d0f3f6c7c78122a74dcece2c709b0ba59f5c3c5ea49a848dd9cba8dea3e7cc781b03287b1373740c8dc0c2303f32454a06e46fd0688ebb80de9c30be205f07e78121e8d23e1d59cc70be23dbc1f7e8447e3467835e7e105f11dde10278057e33abc9ce7f0705e8437c47178357ec3cb39111ece07e00df11dafc6b197731b1ece05e00d71bb497ff001f06a5cd89f8e97739b497ff000f070eecbfbe12e8fc685f06a7ee305711b08ef87db4afa83b7f1685cd89f0f5e0d8dc77a0f9ecb67782d6f792cff3c1e76f074883b08f88cd772191ecbafe7dd8bd13b08380caf2506c67b41c04d4205eb3ec1f0f614fdc1bbf05aae93037ce5b11ce042d952a52cea642a75dc56b5f6389c79d4932c9062ca19f0f43428f868a107587a5916a4788295db300d7051f8684f0a3d383d3816ab8270773a787107b64bb6be679c0a5f879a120bfb83fd7d6f3d9f87c79fa11f9616961695fdecafdac35bfb932a17962b67bc8723f98ea4f51977f5d48d9d032bee39adca47c504c8fed4059b553155ac5d164bf8fa5a97d6532951fdbcc1aa7c707f6f1edeadf7872b8bc23cd1ae979bbab5f7e5f2a943f94242858f9afb709a4331e350b6a40f1749cd85a287cb5ce6ddaa07966bd9e149a868893f1d0bc7609df5976bef62bc8011e3c58b182f60c480313c08bf1795121a9a21464260e53d34ddf064c4582c2a64dc03dff1e15d776bfef20a5f347fb9d9e52c8bbafde2f2f853e3d1782db7215b5e7e0f4d385e0ee3363ae6c97ae7e2c5d8121c63ed8a11b3eeb2841c50c130fef26e4ad30e495b5c8c346ed92100dc1297c4980c4fc5a43fa099dbc3c22d57c8cb61a862b861ccf0e04e0f1edce9e1358762c669ded2c36bde72190fd2e265166e790f1e1435efe1333c28a8601d0a9acf7834c52041f319f74173a19c71d6f551737bb80d09b10c2f470ce331bcec727b5818c6ef5bbc5cf17d174b3d782c32b021c9d1ce0c18d78b79f18a5fb4c0f0625e1ce2bf63bdf0e00b8c182f3060bcc088f112636cc909092f2fad01ec424d45b878ea42c9d2652fb087fdb1dc46c71f59258c77b2c80beb11d2982e305e5e5e6e841febd405c64b8cc7b84424667d08eb307a48bb58d7c98cf78da89464a5171e6c6971b9310907acbc6af6973a35e180398b8c8b97c35ce5c5c45c1c8d65c48da1a9c7cb6a9662603c2361b02fcf10e90547ca1bd25fc6d138f5d559bc0c04cb169696a75c9e6a6961b96861b15a582e5a5a522ea9140b8bea2c9eea294f0e31f2c44b0ecb616ec058c9721c8d596ebd8ee5292f03c1a94bdb9ecb678bcb593c89552ece72ed9d8b2771fc79893197d8e4494cc6287108b25c54b176e51412eeac7a825bd5c4e54258c3a27232e32a1ff99a71534949aa24fd75cbed732a09db1b7dfaf36212232b9fefa92e3d154bca5e5e7bad7ce14c8143d5087ff834ef6eae3dcca8b93417ca1eee8cfbd6e7f1706d642baa7c320bcf187f70c09d202e0a19bd8351a7a986fa6b9596049b5543900ad84330d9067746914a4a21e706cbc3049b55434590095adc00372e6a1fdc374ab598ab047779706438fec09a86589362b3fbdd190d0916089d7c4cf62a6c0a09e6b862906c2159e91ea7d8d820c9f8039f1b567a143bb57be93eba973a1f5d3de7060b650bde1c8b5a3f7576c11ec9966c2ae6a128bd8382fb76534c769128bdbb12dcb7fb28dda2e9f9e06e24ba50b6ea0fb482ed2bd8f81c9154445acf2188b49da0c91320520fe1c01cd3e16bb46bc5d2f28244542a10089d5a7ac9cc601869306c180600d4b18934fa1571608ec4104a138e9620ddeadb9c9e3fd4f3332b158954372243d13ef27573737373d337f9a67de210132f0259568cc19abe0dc7d9d4daddbdf9fb70d7f58fe9b6127854baec6e220b6213ed68626fc255dc36600487b0f31af788a38eec22ac889e5a610473e0777a3f0a451e409d1c9146df54c55279820f701f66259b6406a92fd14b0f4e5529c2b8f753b0e8931d77a75de8b653cf08c54e56b7d13d904a1c6c8792a622724c1bcc8b2a2ffe7431497f5b587a87dc9e3807cb51dad9681aa4bfd6b40f69d7767ba3cf6e4ff7aee40d293dc3a3d21dd25f4f2dd80c8f86b4ab7bba20a50f775a8f37a43f78f423c8909f2018de22ecd663e5883a41be4a6421155c6f8ee29cf7f5d71de5d59367f220ace94a1d24ea4448a37bd75deb4e7177730fa482b52323b44f8e7a2bed876c19138384eaa91f607596d7db05912f96c725eda2d7622c0a28b80752f9215f2ad58db0d4bd7135c5ca43992536b38c506dd9d0c1999c0ac2fd8ec6c176f0590c6c87848f7675cf606033140ce1f828706b49603067bb95add6a4803a349106ac4933894be873e480b49c3dea36dd8d31dde4d59257ea389ed3e569159607e610c19c1fb0b517756d604ec40da4ebb8cbd3a72b899ed03c1ffd2dd1ada88384152db0c0058035ddcd7979604d086cb6b12187d0806d5241a5d68e704984e99168a0e8c90e4c0c7718b391c1c2dc18549630382b8c676b6acb9d6464148ba215d1e8269916c8e65854d4481b4c07b88d9a6073c784e40b49effc3475fa28254e491d9a4eb203f0158f608b5e0a8a8632d03560fa1510cc81312e7f5830cec5c870376f325e8c07e3b940a16e3f6997e934c6fbf44dbb54e2ece9748a32312e92b8f31b833adc89f173dc7694c7ea8f3e86f71f183749344a01aeb56e97bbcc3d7931aa33e1e1ed9d3dccbdd65aebcd1cc71d0be15c9cebf1b049e5e93041a2298cc047497ff40788a029109e6effc4e8c84600e4d395228b2a55ea56f6642ad9d3cdd6548a2caa54b7cab22ccbb22cb6cf4f11ab2ea93f7a175ebcd21f4d82db06498acf124ca19060488a4f932421a36c044038ca0d23b2110061ed362c26c9571b19c10ea2bcec61d4b7d376532af651ac351fb55a82ad958b2caa7b98f35a7a614a71f9863460eea62c30f71257572bd4ea78b57a8c49b08449eef41cc7bd664930ee5dd7c1f056aaa693a95432a14aa69f6a8635d45ab72c904c3f9dce954a198b6ac3b1711d8ae352f6549248c0556601d767b20a5ccf229d80eb5593436d1b0a8542c162b4918bdbc9b459d3adf7546b856df59d8419c91fa32ce4124c951871b7a7128eba6ddb7633b76db574b29c775cbde6b85bee27ee256ea2b6ac665996c1b6eddcf67a5c371b7d039a4c26140a55b94f8cba4628de7eaa8cc1ea4ddb76bbfdd4510638de00c728041cdb946d599665198d42386ea75abf6ddbb60d91c19b9757f8a442a162bdddd9df8f445c6f3dea6b5a9e4914d6348b2e7c8cf8623465efe056ba34dd30e1e0d81511278e28b0763312d883e33bbe0707c3e71cd8ab000ed68ed22aa429db1fcb391ffd5a9d9e07e66ca71185e3b309c7d9baf166f9526e6c6f910889720e8cba3d38f8c4b2fdd11cab2369178f151636063e7e06de1d1f8e37c7bf8e455936119e271e3ebee278730f0e8677e5010b71b61eb0dd6514af5e11f110c78d02c7293dce8b91af8fb163e4ddf1e5787fddddd946b382b54bba046b97520ad63e2716581beaaf33e968e177a61bd06ab1fbd3a49c27086bb467b26336b3ec14b323e2f87827527fda2f5fb35bb3b4a21927539adfc82e8e88ad7cc12156965af5270f898460389f88f2d40aa537f3317c6d57cb084375a98ae8a329c10b69883e1d2ab6842868abc83a3f1afb34610d84137ad45444c47dd89706c3773093d5dae80eca8e739e3aca2f7410089bc52888a0b009d6c4532f7b313b5a887c1fe2ec9da3102ca49e90c39ad855764b216bd4892b335858aa30a7f13c8d021f89b82fe3d041259ec47047051d08e1eef2da3b2d6cfce435293b42085f5665b0d9e35764b0f9c35a8c29c674777cdcebcdb55eed6ab5ebe9e7f6ce06e6c41c2211094358937fc03766c787a9c908f92e1e6ab78139106befeed75fe4b84bf35d585759d8ecf4331a15c1bc44cd76092999600e3da41e1114a6975e6884fcccf25087fc94b5bfc8830ece74b2e79c8285b8dfd3b6000943a2201ce1e36ee68eb026d68a677f5c082c240a02130c8982b004772d63cb53e67054e10883637c8439b066832d7a4a9fd1cf68aab0867e25054b0f71db609b1f3007e6ccd4c0f4d935922be8e0b3912b89ae903b85d04b21f296deb79aa6b0f1c6d8904d2592af4dbeb4f7a99107e1d747b27955b626ac1e3439b15cb0f99a774aef4c2cc926c9c6e8c3f4a3c93429cb7e923258e63333254d829e60fa2c96318182e9b328e7fccc50f794439757583bac3cf2c54282c160529420c910696146e7274fd3ae1396d58b9967695eccbc457c68af4f02eed88ba44a285b51ecb84cc1eed44fc1c29d4dc391ad1afd49697369fa93740ef683cd9664e881900f6f16f8af5d50f055751e69f49ff880fd592460cd77f5a4bf29faebcb7273e549b52bb68be5adfaeabd4275aa15bcb8af622932278b0e162314a7ee91b823de98f828b00af5d53b223deaccd4994ca65229afa78453b402252c249e762c1f7deac6db78f32c5ec41d2db17ca647a49968f34c2b953a0abe70204e5d4217eaa96bd0b57aea1d74a9ae731369b07ce5694fb152d7b3a16179fef067739b2d8601e310c61cc2974318a3bd634d0617cab572a9a2ce4d8be3381e5689953a4fc3c874b085c82b9cba2d452fb370d0dbbfc3912f1ed9b148a3cf7aab05e6b971be918957791dd4a0845f3c8f7ca13a161f03c7b3ae4bbc5d6d215287b9b95336da7ab984b3b73c37e0be8dc9cbbef266cccdf5e5660be3e67f366dba61fa5439b3291d748b2db6c8221553b131ead1b4836eb1c51647b8bed36ef6b0f6e8e5a75edbd553c2a867f761855d10b2a4585880703c434998d2c490be913e927641dc491a568529b81f95f459525e127380e16852dd6857785bc12fc63a266d4e85380461231213d1b005264e755ceac627b0a69180a3973bd744130e38842da03a91d42da0ba10d6d09b23cbcdf1b96331c6ec0e877199622112309cb82f4500b33a814c0a622d19839619d01ab0a440001302986b44c96a04ab12c8fcc89840e6f6a000c6121837880a5a2b68dd2658205b2099bc00062d77092029037a7fd0403661b141ca498a0430677587b800e6a82e10f904e6a4b26091815506964a0b9519546780392a34ac90566958a961b5062bcd069636b8a193e81b60ce110b079873a4e300735aaec09c232a39c09c23dc1c60ce91c6adf77b0b9853c448865b2722007c6475a42405cc3932318cf7e506604e112313c33811143ee2820330e7c82909cc39926199f76507604e11238d654e44e2232c0fc09c23f60330e748c530ef4b1d66645cef315ec4fce53c3e7e2c01a489203d433c235cb01d63318101926902e3496b8a96200a85e54d24f5d5fb1da55d44525748ea5046538b671f4d3862ccee702d10311121a91b9b600b441c591e8f0fef87b7049016af89203d438c3c8124c26292e81395c49fb824c62293feec63139813b3445a1eaf8239b0880560c06030cc3a1198139139111827d23a117a222c27b23a110b684438de027008a77ea308eb6622ac1f81c13027520446e6425e9c87179181712131febd088cd685fc335ea4452fc47b0f2f42592ee49ebe08cbea42649ce545565ba42e64e6ab17894fc9e14abc196eb185179480738f56054e5d880e8fcf46329cba475c60d6cdda165b5cc1427638cd85b878cd61b338ee1dabd966568de7c333c2f363891ebc2682f40ce90f09e62c7145efc26b261d4507af63335e03c9f0bac9f5fa89d7537450bff05ae80a9be393f884f578b35d1d4afa488545ca0e5166a0784fbef7e3143cdcc5636ebe0e7f7922e3acfba425759fdc4abcc24a12a3e4c5fbbd24f597c3dc5c612e73b3bdcc611089570891b805561d62186fdd7cdcf2f1e062071d66645c8f85a5bbcab3401438c66c1122f9080cce5a15f837c6f58183088c3be4c5ed91b941626e133017487f7d222ff7c75de23be2165b6c8153d78817eca391b577e1511c8d6c8c5948149b54c17028ca139c21518cd9885d6ed8b729dec529a59066277b1b9d0d4589613814c5076788e11011e480797cc09c965b1d13670d9401ba54ef371a604eea259c05d4899086f67e1fc11c6bca3c60d304e00beeb4c9c4c291079c219147838d10d1f0911e89edbb11c070c42a4fc24f7bcad3608df6681f002d426ce35151249efae848c6207b38f7510f95706e2ff778585e7b566f4f69e21965504d07b10526bc297a3ccf8bc101a42354e962c7a84d0b6bfa39bb96cdec50b6642b8aa981ee7642bcb43047ded4a887b730c7abf35a5823717c02c7284b1d056d69443bcdcb136b33c62c66dae395d134eff9aba6e7f86e4fa66a50b61ea196c9b0e2eb65691ef7e8bde78bf6ed6a4f63f5a75daadd5f99fe28eb311b4ebba88b1a55bc41085281455bd558ac2b5c500c987e15e18cd24215d869e49b6947f689a30145016ff7a3a62fc654884b9aa669d98771b47a331cd2fe69a75a764b40e86005e6514df071f70e05ad10271a80443b54c839b739e55d3c58b90b6f2c11fd410d24ad88ecbc0dd9137dfaa7a119f08461c0137201cffb8039d10a78fec56379ac3ba960733f6ba25839abfd5f2c821be4b98dcdcd2c2dde5c2f4f7f596aa6bfedf2f614a21b2cf8e91b2c88f50771bdb9cecd9b77426b9a3e133693cc273836c171ce26fdc53b61b046a78811d46d1196607afab9030a8cfaf4b2c5f5e658247bc4f2f38fdfba6debbef5e82e64cb4c3d3cdc4de9e23906de5cf086c29b065f93484257572a3d5219e13ccd2458b35d218a9f56fad1c5cdac964bb4baf5319514b300732accd91e0f5573763f7577c787bb77575e29ea2f6e3824de5e927380e1cc7495976360ed16a159cfa429dbe923a51e7deea1f710bd3db47d9eb694aca7447bbb7b480416d543a8db53aad77835051b8d1075a614228df8a22cfba4420eaee0ed739e0a388861f98c480847a56dbb9347bbb66759967d66dd5c5561e7b3ecce20f03544b6e26112122c694564b3b99d33f5d862aee19adb10f9827965bdc0dc20b0359f5d9efeb63b216cb97848ab29d8592aada6603ba8bb765a04588a7d12d2371285cc67dd0ccaba1994f5e7d09432a74c287da7509c43a5e9099937e2e5ee757b574d4664dfa8308512bc3dcbbec1234313066b82b29fee84d2aeedc664dbb729d4ae7925d1844dd8844dd895244a96306982631429384f18d1fc21aa029b3e71c23a98e4c4e536dae5d66aed9c4445483214e4d3ae3c87703ca442ed824451a2e0f829a55d59bb60ed825498c2143468b592829d873853205c0473207699ceba6511f52a0a365320272e43b0ceba8dd4ad7898cf4f0c5582565631e9686179a5bf285464e208a53f5a3427add2271a046be2a95821d98d4c987c4da2499484e3679276c54fd8f4994a60ce08600e77ed9c470485b3762f05da4c46cc6fb0029974cc6f745eba8282cd4d813050bb62a6acd2a45d31535ec1f1f1f449bb24517f503a9e06d12a38522a385229348a7c7552b7e26138fad81f22220984a32df594a196d2ae89e7b5b8412b908c0c118a459bc79dc0c6108978fec8c4d989a0707621acc9d9b96baf3de467cc0ebc5d21f3dd35afc87c9edfd65d2311cb1b93dd1d1f9e9f5ff522a6c139c6588e403d239cf434a4bff809f1c402e789e7d663c4b60989d1519f65376735b00d1bfdcd576ff5049b6f70bd37db9c77c6e8a8b8dfa3e12312cff7696f8169f717a14cd1f4577a8de1ee8e0f73df5e8a5e803942709fd7ddd99f248a34e235ed35fe06e670afd5dada44f235a45bf1b512459d1a69c46ebb3c8ba7f504de2ecb6bd30dc971c0e548a2d871b97c8d3a46401adbe314f0f6aef280359b9023123bc180cb219e3c2ed7e59b975d172f03303c0f4df4484270200ad810d08f4f920d4801dbe940143b19dca1463719f4bc2213affacbb277bce92f8bf15a58937d7e36cb0eef03e6c026604d06a4bfecab2ad86c63f6f8d3ae7e269f3d661702ad18225f36642b7bf69e09409d25228decd983c09cfaec9695651aec2f91a11530cc89f19d6101c76778052ef2016ba2574281a59f16e6481c815e0059fff76d51488d10b23e9b1b2d1cc297afc3160e6ef87d18c2a9514dd36ed68eb56b10d23baf1ca24a3a085f51dd717c37abd85ce5bbbb5b76f7dbc562d54a35cd93a95afd9c01f9f6f42224db07cd03148b46a9b577908cc921f98a40ddd23e65c888256356bb8c414c367901445dbb6402734ad7a25828da2350bf6eef9eb79fb4b34c3ab69bfb9b90eda637b7012d53936724e2ee7463ea8bcc26fad3eaddf1e1faaadd89aa5ddb75c272ed2594c7723fd5b541c25a6b44dd0f25686b51acd25ff472b482350835086f24fa2112c11aedd38b55fa2b42d26215aa8034a215ddd21eb58858682f2617a6eedcbb9b52f424d09378037959a61eddbb9b3c7131ede8bada5f7750248a44ae928d9c5d77ddd6759ce9ca1eddb97b24e22e1245a248d40151821608938e168e54fa5b81c166da59b4d3e935e1018135dadb2b62c4e207c01aed0d8034b45b1cf9eae92b587b378b4947775113f5500b7590943208f5aca160ed2ad4b38bfaf6ee66f324aee7def1982d63dd72086badb576edda738d978c754b2bddb66c31f568995d3e9352c6ba9631557733eadbfb2b538f0e0a0a0a6275d0bf604dcf90289bbeddc67d3ab76ddba5fc8c5ec422828dd3f2069f86252fbf22b27962b9f5909becb61a78db6672f4fc40298a5780a4f49192a02a32a931f793e906e74158634d3dba4bee9168bb7cf72c5f8a443ae43d12f176334a082bb5ff76e505ed59ac7432f5e0de3fed5a1263306707272f6f365dbe83e409650f65eaf32a9c5e5bd19f7695d755baa53d12c95707693fcb5ea2d3bbe7d34b9c49c7e91e899bb732b240640ce64088259376cd6bf4a57ec11e5a75c1669c78b84926b046bbf464ac0ada9b07f015616bbbf60e8239a66bcf1db475d0f6bce1dc41db4d5ecf0c8e2112f1e94726de4e0485b77bf81a71ae3d5077bb47223edd6c7aed4f33bd8b261c426a7fda8d446c12c2dd48e4366033ccb57463b61799b1898f48056bda7fb48bbb11a83fedda81c857ed56df56963deb5a0492af1b29960aabcaf3a7bd03a2b4a9bc2ef288c4231537946e698f22056b4d056b5d056bcf3642faf259eb201d7def8c2d27a4276dc2ba6ee20d1d9cc9a51f4c4fa85415db72d24cab1bd7954c27944da958562d2e5c582f30302ab1100925a882b3773225686394fee865221698762f5e94acd74919923f47df0e3326da9da6c6079b1e5a337498000f413c094400026f42c6031cd0800be405130c5880cc123114a0440260fc7841c0010cc0f2115380249080e169e97184112b1e2e3b08a0c3450ead081c3724112c03d8c12a1b5100430480ab91e9e40000e7e51262da9b1f800882466fa9193ae8f0090491400420d0c4031cd000204c3060014b28408904fc40c0010ce0a3004920c1d3e3082378ec20808e1c45e0b841c40076b00d010c11801a3a3900c079b984b80902881f6c68dc879b5935a7e921b678f874d861c60cea8577c5bdcbc8b8e27a8f797185cc0b19981857c07821f3f27205eb85c58ab902e685e5d272c5aa65e5c2e50a172dab16ed0aa9a1e48ae50a9586922cf18aa273de953f433f3f2b2ed8dc2175489d957e51e0b42bdd349bf44b26cd2926149be71905a33e81da05c4519f2f803a7349cdf38c0146d11cf509ebd78c4d9ff92304d5c351976f803a134a9671c0a86b45bfa6d0049e2516419ea516127896568adae55901eacc2a11789658c0a819a17ecd22083ccba1269ee59407a064f000ea4c2b0e78963ec02818475d2ee9d74c6ac0b36402e459366102f5e2a8cb11401dba8401cfb2041875a47ed1d8029e3b698967095300eaad45bb621c45a128f1dc65c028182afda2420978ee2a3f9edb0a043c371653daf5b204a843ab1ce0b99b8051324ffa458b0cf0dc413e9e5ba800a877939601d4a15692786e1a60948ba3de49fa45935a09cf732fe9816a9103d4c9961cf11cb7c0289651bfb2583ce2f11c9176a05cb20075322804788e5bc0a83e2a138a52723c472a45a0e20fa04e5605c7730c0246ad8e7a8cf52b2b8a40443cc72703403d2e8926803a99959de788028c9a47dd48bfb22478c5c6734c2200d487b48be5a85300ea684b220dfa219e211a30ea3d302775d479faa5c560518d6768a493f30ca18051d70175342834fdd28464eb06e7b9067ea1ce03f51c30273bcaf5cc03465d07a8a35589346810cfbf796659fac3b3c4a847a8a3598934e8519f8139f62814ea6e54b013cf213c63f2d521c916bd0e6fc55a1712831275ba28a8e79b9b76b10908051192805095a8d30945a00aa65c12048a9a287a8095a8d32d71c0cd4db922d9a26fc00532939898494ba20e6785014b30bdd002624bc41410831275b82a4a4011922f2e9600a11f420810aa1275382807b8b9e9966480221f4505b899454fad441d6e4912d48a7c6d4548dc5c796e0f9ab424ea6c568e581293af4dc8889b2b8fd88e1894a8b35521c0cdbdc57408e5102a42a84ad4d9a0e0a852245f35e94611114503b899459f59893adb929dcc0aa6cf92e4ab16e19b2509204b5a1275aa952196c4e4ab0a05205623a6138312756a951c2842f255630010c2117a09617aad4ad4a950a2ab0aa6f5e6661b043d105e27c54ad4a94b228da4b9e407cd0abe8d4c3a0d99741f6452cdcd8df35c4273575658540f485166dcfcd6fd78b83b5c1d2e12ea7651303dcb3d795dac13ea8430bd6ac62423a95b7293bca4a46e09a64fc128bd28b202a3e8455191154c6fdfc5e084aac0e0845e70429c50154c8f82e15eb8180705868bbd70312ec641c1f427992d26895b0293f49294c42dc1f42617b5a5c88a8ba296225491154c5f62692e9b5015179b50cb265405d3779dc52d06658b6db12d0605d3732baad5a46d4967c462d95b93b625124f2becc4591ed5222b5a11aaa88be83b161d62aa1bb7d08d5977aaa2ba6db39a865315a525cd25aaca35053ce923238b395a81a9b442a88a66af50959e5246a2e935ae312899a55d2097eed39ba314ad2e893a5c51a441cf62d94b9760fa4ef3a2944eca14d92a8a3a1d12200d7ada19b1baa14e09b086724598de4537b4053b656d578e4218a95db9e435965a486f7b14ea691925f9e4233ad1f71ad34c38ba1beaa47454ba456f85edaad06e68b5055bea8fd2e76e0853edf4dc15a40ea943ea9030fd4c49fec857372483248b65ed50fd199a42f415610abfbef53458246223151731627137245f5d17054cfb43453ce5c1093187029bbd4f857a089feff49c7e8505eba4e7f545e60ea5d9ae89218b666605650ce8f38667842ff9035b3b4cd971077a3add981d8de527ce5074d2154fc2f076ab177bbc18a55bf49a17a5f4372552e98f7e4a14b840c3f24a4e0a2bdfb3f4238186a2071d8c4030c290080845b8eb128b6668661b922d39ab1aba5ac34a615139ac624545bad9862a5264b1866215a9c65a6c6cb392e710a699694117612cd2905d95afed28168fb6231993da917c75b035278b0dd3c423de982905c739ef1c9a2f802f9c023ccf1a24f13ca940e279fe80e79309cc79037c01e9f13ca538e27982c088e769021ecf3396047358ac005fd167c7b3e402019e6518743c4b33e4789656aac01ccb03f88a41453c4b21e0789648b8f12c9d40c4b324c27d19047352af5834806799829d67f902fc2c6b60e3f46a98009e3b0d433cf71b02f02ca5a8f12c7d504b80af7ed251c8796e2b00e0b9b980f3dc58488139a5f75b06f0d5447d03d773f34088e716c2cd1b08e698e4005f9dd41d00e2b947f0c373a7c0e6b999e07ebc0273b8f763169ac673f402ee9805ee98064cf31c93604ef73dc72aadb8841ee20fe04b4e912d39f31c8372bcc10ecf510639b200f7a309e04b22c9968439f5bdc9881df09ea11c704336e03e05e06bc6644bca3cc3a317cfd00b1066a1af03bee6906ce58039da631e002c04ee1adcfd823b855b07f89a33700e611c590b70734de24a2470786e8e8181c8d736d4e3e67ac4cdd60868c4031af9c8d716db717325c0cd5687cf16c3f2397c2a521137571c37db1b4148589e889b63e03a650037d79d9b2dbe9955a760791bb108265f15480037d7216eb60180c9d78061a925e9dc5c736eb600b8f23837c7d0885e3757d7cd56887b730cf94e922fed896cc957206eb63f74d2132c6fd3491a8cc6cdd5879b6d0d9006c3f23437c7c05911927c6541b225dfc3cd75c6cdb67533ab08cb7f532a0f3757bbc3cd961584e5676e8e21339f39245fd448c6cd3158f766968d61198b318760cca11773c808cbcbdc1c03e73984a9906c1dc9c7dc1c83c5b242589e35abcbcdd5bab8d9b262e04c7f62742a1eceb293c964026be250178a88a62425c19a7895d7b8b35b6c0bc216b43dd9806415592585b49560f3d96049413228e535b6a73a650c464544528954026b62053a8250d093a3235813f1a9a425d515d49fead3525a8a4923d2d0a01d69465a5103c19a884b5ee38e7bd28421a1a02b57604dd4605a0cb498f6a3f9141579ddd52237201d194181b26541d914b229d95026147f604d7c97653e99930c288b653f5af468465b24211dc12939604d7c268405a2294333b0266e47b066cb02faec8093e2c91bb094698861f995166c3f4eaff16b3b2aad66b6216d888885c59cac5515366e472b22dbd5d463c61a6315db8f387adbd10f385e1271b0295b129643380868b28135b2ca865b12b48a63875853dedb119650671b8a34e433c5f1b51dc9960c02bee0a7b30d451d1b4823e6162c95806357a2719585a339e339242210a00ece6c9fdb677db74b6eedca514a794aa5ec31a5ac416ff0bc35fa8b9f9753c6a3a36ef3209647734abf1a896816610d6684b547ecb32ab2f57942c1dafc01d6bec2829de79ea70f912199a9c7f6796adab17d6ef3dddd46d22748d59292b0760867edafdee8b8ba82cd3e8f8ebad67e7cb77937ab2714b1dde09be150e4113d1e55d87eadb783f44b2221499884eb8461ed75abdda37684190e1d59d6142221084d3105aeef2998e0fa9e224aa795b80f6813e640eef1286a21374f6ad19f86eb9547fd59a11f44ca6a210b6eddb39447f21577b4cb2b5dad24994ae692e965db8dd96c90feb4576f487f5a7ec92918bb5a5a55b1f906c7570dc254a9bfeddc65d55eed11ced3676aa63ebcb6bf7883a329b6a96f4f7fda214dc9c823ac952e8fa416edea6b97483087bb76990698d35d7b29d60b678ad59ff65a392243f037538ffaac14a8842bd72baba2658a660000008000e314002030140c884442d160388f75cd9c0714800e8d9e4a785e9aa8499272cc18830c410600000000600000029204c8b9f83559839c30281351bfe6715eb7b5e1571165dbc2d9503d11a9b2a666aba525527057c34a2535666ecd4d2ec3e69c48743c49064071f652434b7895f0cd0e0f1e99a71f63e154e13f96f54a210a7db3c5a07dd8faf84fad796c17d0cc2c3d40e1e79be2b3f4f02d049040d49a187092f9bd593174dd333cf64b98e7f17247947c5b42c0c272b1f0f947189e57acb1510296bd8ff9b38fdad284af566c3526481eff0d436b8956e88f14c3c7af3a8eeb6c74b7d074ca13bf07bce6dea332126b4c7c54c49b7d214431894fd64f0cfb3fd74edf95b34d65b7528726c1d6c38068479890901180d765a6ea824cf31efacd143a45584f7d6706cc3da4b08e0720889a30cc80027602ca702f95a237e40eac0ce8f7544eb70f7f080075da697d5cfb70dfb4c211ab7498dc08c5989efec01d2357d697c6ac0061379aedfd707fad877584c6bb62a1b8530a7294311562a36437da73465bd6007514f9baddb61a449cf7337222f788995362fda231eb9e54878103b168650c32ce1411cd67298614694fd99cb08cf11404661c6ae2d453f6d899645ffb396d7e72cd0aaa91c03c03b8b2e582957063f882f5e27620ee60db64b10d11dca3d7a57d3b10e2de997cf817c06a17a7ffac09f3ad4997ac355025f8a98f02a5bef2f005c41fcd57b61030651acbd75b44873fb79402b3bae6676165103994094015cf8d16a74d222b84d84494db725b639fe471b134f0cd879550e56a97a76c2404ac47ca8c28336d5acd205036af41696cf6997ee7c79361529ae0f944b8e7046c944938fad804b77dfc6a0c7b05138ca178cfb5747cd5091706ceab6636c5c7d1184333215f11d01e0a8f019ca50273ecebb60b87b88a19046c364aa143cc687361e1c333c0c8a1fcb08519cf77d4467a9a581d693b2109fb6395d43d743ccca656bc3ab797897cac2cdf2ef4d163650b66105ff258a1d414d8e38baa0d939a87caf5a6ae36eb52e7096abb5473e0bfa96e5eb227ac8bf84a2dfa06806caa4b1441b1c762a9becdd4ed4fb7c6ce43263675f84accf904995b64c6ae045fe498de3dc1ff0251f828f82b922c213fdb76a6c0d9099fb0ad2276f72a30296b1d5f36b259e474e81bb264f053e81f729d406d9fdebd528883d78b333cbc8f0e0e49b302a33f54f9f70b4f9de8ffc270678ca5157a6fe31cf6b06e68440d7fe49e745f9f365bba5fc314a481ee4e7018ffe4799682ffb0d8411ca45f004f8afa07575348991c87036912ee6c06c93f17f126ac81ae35edbc5344d93b90ec32e66d2cb763c15ca674029f2b8b1cd40886093cfd4ed52be813e1d6829e599e13e09fb45e2187e3e7cb9ec7cd4ac73755c201b4eeeb1a292486e6834cb5478898f5a75aee78b8246575df2249dd152b8d94eb105e7dcf975a932d948c9628ff4e07087696c1e4898aa0c32d1a949de94f8f7e1574391aeb297e6a0cc81f2f877599b158706bd32cb65d610020c26720719d12c6b861cfd26dee5d8659d381b6d22c8ce5a56e085dc99ff22704c1c358e8f62435e2dc4fc31faf134d5cb7f969b766d02175de26844e2857d8930cce62aa4e6ddc5f1a47ec929127b6565ad33937d43a00aa6a207ac00a3dca545e60045f80324f73bb246eb755921fac1710581b0fa0fb5b1819092f00d718b749c886aacb0e4de6e26bd310ea3e7eb0da6f24c60f8f9144d6143fb3787e4d412dc42fa70a987c98d940d3058ff52a2ca6f260ceeb745edd374c6a4058baa869ab6b89f7e70310c02be008157bb77ca3aaaec175815b7fef29d7ed5d0e91e5cb7432255aa5894015dcc8ca409c709fd1cb3eb1c0e4f5cff5cf9294f8ab2dbc95be0215e302a54d5f3f7dae2a5f89d0066d1bfa0d4e90714f2251bc1448983294424c0002cf3f58e34fbb570578ee210768e1d92eae04b8193294bc5747e44dce610068e632c956c7a4de43517fb37855e0676bd1f72fa080d269ceee648a96c0bba9e0efbfaed90e885dd296c0743240a2c0c3fddcad577bbc40fe5ff59cb4c215eaa863ec08e22a66a5a04369f42e15fda5a3af24f497043da5a2bb84e8961a5da5a1bb14e891523674e7e1eb8a91957d473e124ecab94ce4dbdbcdeba15ab1a5ea7fbc6a6308bc4b630faf25cea83045ce500a17fa8b2cd39e104e10a56da74f1e2a0ce556a6991c3e208ad6a79a083d0465acd39f1a361c852cd39e104a18c576a74e1c2e0cc556a698183a248ad6a79b083f0005ecd39f183a18852cd39e104a18c576a76c78dbcec94a46d070f3969b68fb1816fe6010fefaeff2c3f564454c461f9bbce82929d3fc1689165f89ddde06fddde4d6f4823e6e74637a49af9bdd147de8df0d6e83bef4ed5637a467fa72c34dd3073ddceec6f4907eb777237aa1b71bb8017dd2db4ddd4acff4e7861ba60ffa71d34dd3233dddec96e841ef6e71fcfb15702b1c3a469de59ae069d0e0e0c6ad02ed4e067610441efa7880a875cb33256a351032ca8169004d6661af3a94dedc66c7b915ca410b5a9f04bd7648f470935f8ed6299946d03d1ff2ca81e9811b72bd5b4a59daa0b709d81b87412f37f9f16c9932d180bc4b3a70af1d20fddcef46247a89096fa92873366ec8f4ce613eaf1ce53316e104c6dada7a322cc15b651c518ea0ae21057000d02eb85b90340d3bf24a0ccd9b2ac64544759d990c183789db9cda5177138bdf5725002557f6bf85214afcb84e14754e235200323eb7849561ab54478c56941c2d08897cfd680ad3030b70cb19f73b9d91413322387ad6a0673e2f8fa8af0fdaa171576d29e3da0aa1036f35e4197116bd3ca49a35c23d16d1f3ac87ba2c540e411181be7894115b755c00e7a6453df8f6239f1fa4d18c11cc1c6cb6279fd78f186bf36e1bbf21d4518e951b97e70352a73315de8865cccbd9ee7c1b66397aa43c7f8df580e9ec8b3f2ecb725fe915b965bb8ec884e48da5bc192a93e6d31d23321aaf036dea8fb7f4887203f350427074a944885b56932223912f13e0c0d5041a075dbc4493eef9e78b14c433e9d7382dc25a85ee1b505c3f15141e4f35e9f4b7da7327b4308b39dc33110e40dddd8b03e0307503f02196a60718a77440c1672642953edcbf1e149ad53b3da2bfbe900b21c99a1ac100ac85d8563502ba3a1c06f50a5f6a99549cef542381aa55bd13797deaf54a89c0cd29ddf94d50df07e078a63902248e7326d92af86ab910949bf4645f7d709783f098052c106ceabcdbc808f3e44def5918a6d3aa6d10d9a7b82a11eacc80e86a9c037ca768d5f8e6a0d842fce0e7270f455f90f754ec52152dfec51f344a9054384cc3e3c1a98be1dde04c74924c91ae2ac6c7e1160990ae8161758122dd3361b06b7d6063f00a1551340df0b174339d066327ee531f619fba1c429485d60c884aaa24be1c28dfb645c36e7b808c016083136ce2e5771afa2808bbf9e660d4f877a1d88440e2c3071e453d21f75eec2a200dce4533b45606944226b899f56e17958b46f4e5c131f9f10a912cd21940733fbfba4d51e036a0ea2c1afa6453cca32aa91d82ecbcc0e4cbdb4b1522fb0b1d9cf4e5cca9ca0bc3625f4254d8421ca8378317f88fc6a7c6c02b9c3ac3441b8715371158b42bd056e166d08ce2039bb1944c063fa2322d033ba847e34ad0202014ef20300b94b15b2511df3a252bf40c3ff5a77b2ee5555e29a93ef716ca60b49c3fcb7fcf71fde393c687f246249813f403b41a2bf4f823b9481dd16e2aaec2d0c71256a2200dca311e1addbdc61b14c17ad4ac0ee6f39f723f44a64ec6d281d8b1e9fb0f4dd31a462d452b1e33abd4fdbd357ea438e270b4d23effa76c664b4f3663077553f5a93df59529123f82bae9c7a953e2e7fd7823d27687e42a20f91103e9e0b0d5147dbed3310360c50cdb522b9aae23afbe540f771f7441aeaaee24e410e51bcbb442cfc92061723aa8cec25fc83715f776f25399cbf5370056de405599471282940dc8bcbfa95badb2aaef8a23d1267f3d59e1cb384938773737e102b13134b6076434410bfe5a785f8783cedce2313710b27737e9db8afeb80d817b87b03e7ca9a3419738ad9a4f8ab91faf0287653597b61dd3a12bb0953cd374f809dd722f7d7bf70933e130aa50e2580748e5fec9e6475b38260a333ca583880508f3d33129ba34786ba1322334afc2b38756dc1b0b6bd04ca40ebf1fac4936b8f48cbfcfc0d3a5ee2f0dfa14e669c2629bd03e99f014cbad73fa80341a6e22a617e3198531d3a9651ed8ba48664bcad2f49bbf620df53af7d44d0a69eebfa2f60019b5cab63337109236020cbadd8296b628148623a0f9f22c0a32db369a604c4b40a2c71500c1003d1f705a081c24a68cf1e62ab0cf339621d76e7d0cf3226cfdc33e8bc045a554d9f5f157f118712f1a70471840e428cfe05b517bf6943e6742eb0224afd0cdfbe9a002dd141584baa30aa2fa765210bebc42e0dc340b6657cceebfc8a0ccef28b36ac092e1308d73170a60092138afd689690026f1bad78871b79b70f1b38afe8e463c7e6e5d8aa4cb6d63792e6095693c7b38b9f3a2d3001e6f26b007dac2b043f1fcb2a609b47a38cdd4405469fe7a2b321af6dd64b0cc488a0521e99fc89343b71928d08817b80897f870d42523bfb6d6581548766b3fdfe6ef614a811a4563d53c4ce554499287a1b49692e1bb3154a0ab0f3206a409a817f3a1ca14fb448cf313b87de01c293857321453a9a52b9d9ee0079732b9e2afa783f51ff2f79411706956ee66d3bdab8eaa6f6f665a0a40f9cd0a3921cdc5c127b629238629b4376a2c94dceaec002814d811794d549c26cfec12db60323cdaa936c99109b97780eb4532ca9c81c60bff64ebd91236e3a447426d94bca04c3089f1281d48ee2162640ce9a366a8dfbfe51ac8a7a928380b0652b662c5771d8d7482d079406bde15b76a3e4379512debadc02b80d6391d367f1245ce56be7427a38a100d1a6cb056b15d0d6ef0e7ec6da71687f8f957b94aebee3f362f8b2b9ef26561579e4555006eedcd6d97b12a22c0538560a761ad6c3bbe1a1557695e2c7336369bc9caf34e94b5d62a6b07eea2e2e2589666b345a9d3cb612835b994e7b0aea04b83e68acf4808c07e8a19d651b16664411d32ce1fe530be31ab8ce28e1c7e0ed73e50a6703e6fbc93f76c18e9ca90a1210c093b43e40be00617cad3b57b41039a5a70bd6040f793323d352efc10ee8caa7a8d8b93e93cdbce68f583c39205560bd07599379af257d65ed432ac92d4d7084809a6def7778293fe8bd9e1f2fbc4ca7ecf5197b3a3d9f5b9aae9a46ed83562227abb0b97aa3303e9ff1f62fd520c614c749a84276752d96430236cb3b729983393c961e2c17a5762141d1bec280f18e101f545241bbca2997de1a557d91c241b6011db66a87bcf77878f699cb9e035f4a5c67579eed9263ba4ca9a30bd1a5851a6fc943c5b27cccbdf842d67ae607f780abbac0e356c10031df670400288eb86a3b2eaf4341d48265ecf8f31becfc509d5b6e089a13dce25157a6fd80f236a040c008929c66a23c70fe8b045fd78aaf013f1a76112194bcafc140d33259be63ec7a9041417b108bd1fce82b39fda8c1fb3a849e946b7365cf849ecc7a086856f11cd002580658b0987f64f8126f0cd16492d63a1846e0e491b245fb3e9fb539d27d403bc7773060b1de73a9774c11b6a224972e4caa409f50a42e9b50e681fa28c884f96d3bfced1a1a921b4d63e2285d9644173b85cfb0dcd8ecc24b9b7d62508039d88f22c6b1fbdb2beb7d278e2f431fe6598ecb0e29607992d9b6b3a32447ed7148670b0af6511796c36476e34d20aeed884e9177faa9cc94383cd743e579b6a95a0cec5bec85d4edbb8ce6593357519a69535db66f888f3ccf7940698567a412f6969e1eebdd8a456bc9855d4b1b95039348c53ff60a8738a93ebe4baa41a99cedc4dfa5278688a41af2dcad6ebf72b550f6b4b5f9aa2c22b5e61db16aebe2e07f66019b7d7e7da20b7b245fab6271dc4eeead3e61f9f2fc9771090d08e1b5e01ba9c75ece47b6e9e0e7fb61ef4c937074c1dc9b6a6e1dab9f9c024fd9098089c75126deb40a03630f09beb74312f72596731406db52ddf527147d502b0ad9f76d1d7cfdd19f308747ffb7bf47f13d64caf81c63ef5635b6b0dd728928753c2159f182d28d7edb365bcf669fd37a303aab7015e02ece63729baf7724d80e889793edc230409904e2c8b75e048eb0dad72e6cfcb414a3f309220f916a1532416cbd7b6f89e514170ddd6b998bcfe9137047edcd468ed5f13bfb5ca5f5545a30a737eeeb8a0df643c03a51aac11a885fc55bc2cebc672ed3ecbe288fbfd910245bf5c554556002ab2a10253f5c24865fff0484038bb5e9c59fc134ea1b9777d421400b609b621c68d20249fbb2c6616b527f01e379cce475e3b263a3225a6c62e1fd81bfbce8b28072f5599c4772c3da72a140a1e0542f17f4f005a0d3c88184bf857a187f7b3b716d735dbce6d301351848397b098d9f67718847db3ee98640cbb4374a04c53d31060dcfce5c7be2d1d05e78c192c1f2c9328d43aa1a6d9864502f9fb486d23a8fb3ebdf0bbbfce72ab0e3e31c4b093c29c58329b701a0ead5d745625c804a83ea0b5204b6864c1b23001b11e93e2255c78db0fcc94bf272d9b2380f1edee89e59a8861415ba780f97b3a3fdd1b401a7846c1c3ea59367b2c5284f8cb35ef3592248fb2bef5185caa3e937ea28923a5fdaabbd7d15234f1a2c5181c1890f2565c3dc0d39bf27033247c89cbc463b4f10561013b1febde93291b01800bb63197a442320e2d7dbca4af8a70dc48875c2febd0fe3945f62cefe595b11381ddb531fe1a701a8f87c3b3a6d202e6c46a596383423341ab1543573377131ccc9a71337805c48e266a9c0c46fc7b5ff1f5f8e791ca12c30281fe7ba726032a0d2b22aace052e9f52344cf67fdda5ace70a6385c52d1e4d42e475ee8c89f1971c028cf09279dc58b2b49117271c1468e8e92bc1079c26724722ff5fde9c4c4af830afb7a09653df14fee61127fa256e25282bb804361d3ce83e629289a1313d2ecaf1cb806340e06a90d3c0ff3034bc19a1db7f966a0aa1711e3161c72cf954c4986f3db7b608fd0fa2892b914d6410c497e73351894d7432b232f44bf0efbff386d75a26c9c94a69a25ceb6d5e867d430b38504500a79a3afb80ff24879add9d2a7ab0bf42158f19a970077f9c9070f01923b3a3b1f346c9d6d1a8edece99358b74aa62174530a7661cd0942bf3bdef36d364096b95406bc232d36b6b4664426bf1a7bb05ba8370d44ef6af8083e138003f77b088e3267f172061ca2a3b879bf98df314b0c112870a236f42782bd679c452587f710465ffcc22cad2828c0f17f195a1097981c2896e86207ef74ef0d50adb8160bb41b786416c16a0ad118364d278d0f199fb7e692cc4aad2d64a5105981a900744e2e49af11e9b1657022ef37bae8f6cb94c6a002a426416e804a4744409a6399444b5202e234017b6fe341deb27eeb5b31db9811a2a89e7b6869043fcc5287c582e02dd41cfa0fb0f5f4315112af12963cf1e056cfff171a335ee4c66b27b17435b6b118e88daaf43409eb196f6f2396354b2c0e9e08533c6d89952ca71e70ee04a9ad25dd63c77d54bafe360d15a142706926563c6859a24da4cdc9c132872d7d3712400e6ef0b71871283ed13889514d465d1fa44e1747560521c267a0c3591dd444cb2edd717f233b45a9b2c713cadc97e84a4c85bc69c2bf89d90d9e8b436478512dca857555332a31d8341c527277318f7a5d626f51cd020790dc813e250c2b9bae95b9edba584511dc86d5c449c8b603444d77269078a83aca5efb88ce81be98e55686295697a7371ed653c3edf3bea17b5db5c0303a9f87618fa251a173a909e206d36bb6986dca864cf7e14a75a4b730466848c17c9fbfda8c4e5a07f2998cda1e868618f5b5b66ba545155e3d15ddb6d34951f788b58b86462680f82b931d5d04668a8db106de506cd5d41f83d6c5fc019996653647f7d9a720b4ca96c76226822947d0463d26511e30c7ae8f577538410b950825e5d4745d83bff057086a37b7ce5dbff26e952f7228e631c5f1fad01c831adebe16fde8b3d9da5ff0567ef5e3f3c814cfd97c3c1dd82f1edd31c6b3b14d9eb5fd23cf3293862b7e658d441fa6764827598d38da752af7842f9556c2d7d635b4282cdf6942c59622eda4aa70c92a0ad55524e5416703d9809e654d1ed063d543015bc08498ecc07f4c92469931e664fbd071b06eadb746053415471ee9b019c0481fc198fabd32c66f6772a6408b320361cc69ccceca1c530ef34ca6e64d5b6853d7c4e7dc8d0aa7bd0de025f0d07434c4e4986d6930f936278d8f3c42124f8c61a8458f09a83ceeea8e1e4bca6075359681af46965ddf145329394972814ae8bac464b42e3a43d0018f6f81f953244694e48c9c87fa607a6162125cc3540ef138b7bb0eb9bbd9fa64c4d8d26cd74ade2b4e9c8f5315b19dadc7593341d7307177682f6349f21f315198c862cc0f88061493258c4f529d28dc49823c31acc70515050497551d9cb43156b09f57cd12d762a1d0d84907048ed069a13a70c342d90551b9719164f82fb1c236bb5205f85eb9c9c2707a48a9eac4eca7b4040122090e77310f37b2d9abebfbf11c389665ff46cf278fef5d82ce5c0b8967e987af00217e6e651e9034164794cfe4ebc7a428b97c42cd7b75f2ac44e7938ac9459c7ad83aa91444bded9025015407a2cc616dae049fb21c73613d0c7351d315ac0cd46d1343df705ffe5a9ebbaaa1b2d467c50877ff14ed1c698cee93d748e3314f34d1be5542e3b840c9588947f8673e67d069b1f60fa1495fc20f25a56dea6466436846bb4bcea001db350dc14de998317c12ecc205d9748e0b490d6912ade9c578dfd5c51a04570c8078b28db2c3e4d195764c519afc0a0123d87e9b94bf25170d11116a164c79e6198d5b48995f243b490d38a22d1d6ee37f4e3ee34a69df80ff014b87555d46470a07285552c47e7a9845beaa522ea0962b622e7d4932a6e5b5b59452af2ac48f9072dedc87825b3cb8c41a76b7cad73244783cc01365b81770433b4b0acbded3486d773168803aaa230aeeff7c29be082f7157007f0d2c53e6aacd3fff7b046cacd1f2ef28e7d843def8da20c7637d3c4df3363f57a5d2930368f633a51d0a97858e11d3e8daa4de7bfd40f276272b4908cd5d19fb81724bbad7f4a489ba15f4b05974af48134bdc0be2f30599bce800a7f46a2d350975c17a1a7685258d760ca3d769d90dc84282d5a026771a57d4e844162708c416d220eeef2a0cc28d94743eb07e807faafe9f14130b4615fe82226b47b4b2b86a2cb543c54fba81ba3f5c12fa47c050a68571c17f70613508e878f8f555e557748214d7abee47843ca28e5785dda9bdad2597a7559590041114912996e78432863e89691393d58ea70a381a8d93dbf4e27fa2ca07cc99544d2ad93b467e617b287396692a3b7c2d81e7cbc52735b0a8d7559ea341397b23a8e6427411ec1f3ebb44deb6098803ed2e39107b30d61675961e0664a11850a8f04886a41a9287a6634ddac0190a29296e613fe645973ecc1f6b581b588d0c3952ddaee09850d5ba56386ad96290017f9d4b4c623f83b69ed023127feea4d94e4906daa694f9ba420c3bbeaa64727e474f0a892df5397644f05846a09c43da1d1aeb66c0bfb74a6932241feb1192099416b393c93a3be681ac8b4f78bcbbb75708bd8dcf23f84ba47656eb398f95c2d7f8ac84ccfc6a85247d20e722d74fc9c6fd315a2d9cd4be6969721e11f0c64e85a574d7fcc1095931239699e1542334a2765939f635b152e41bb5efc6089a32d73e6db3baa202674c79b2fca72ea19617497d21211b6aa335e00f985739bfcee47b1a62b48811974b87682885827d8a4a625668c8f1f94ed2c90df54ad618fd789b1fbfbc7211eede82891f21de87e65fb2b6f2ca965425d3f039094f4702f7a1909a9905fd63c93235bb71666acf00b236a9cbd5ba740b20f1cb59e46237346bde5ed98965440f4a542c3d35bbd3d0aba86b9b593a7edfff9a078664bb1595abbf0b28bac34ace9080d41b3ab164953c3008c8b34a5f56dd2a5c5e4ba359253b16b6a5eb685b728c9d2f34c06202d4652581fe671aba732ba851df561770c64a935b058dce41126fc734ba06f052ab43397e6f5f0964ccf50b38821fe1f94e4271fc3b604dbd4becf88e7aa100d56a3ef0e63f5c5f8a213dcbdd2fb46b9acff9883eaac7b09a01ccc7dc6b4301f038dcb5204f9fa2e464c1e6199d72e0e95c4462ce8c0de0dabc3f54e8f065d102a458586aff34de0ae8b38a641a5c0669665010c574b46baa0b14e71826e726b63af1510eb8bd04d8f543c11f0b8cb9bd3308fd076a8c42b8227a3422b7680265b25b3411f7f126ab5e905de98e8168acd05087f69383bc09eb4f92e3024b6d71f0160477a1309eb15b49ade12c3ce50f14b2229c40b7a20eddd9211d73518e528293c3cde00f3831d73db318a9cb86d9d82c347375a3f207c670e22ea3ade20b337f4473d2c523ced5ef33b2197169755a43f00743512aa9b96e33a92c17348df00c31258691ec39e83d34787505c815486f01cfc94689d93e9c333471206171a75d9e56797fa046e7039c072c8f7312b0966f63fba14b070e7290c5d31b89374a392a57910fbbd7508058f7b92ecdec4a3dc7726ffa47420a315fba1e509982372bbc1c4d76f053cb4dc1feda1216fffdfcfe4f8234adc03fb5aa2c604c0629b87e04573003022cb9d2f5530606630c5a6c0d052f8d2c0424ec9fe4be32f43546f633f981e99be8340d67037a229dd9e241f5477df06d0a607a965b7be90d581d00a63ed23cbb48253b9706b918f338636faef1df8cf630ea844452528c6d4136d9616d5ae49ca21e8cd6254fe48234e1813eb39aa9fca045fe2ea453fa6bfa1e3abfa6e9191c0708dd00cf08e063dc7fdcb329eeaf02d45b1e7be085d5fe0aeb114a21a1144652baf5213044f911100593c3a22a5855f3bed4b4a53ab84ba81d51e50e7752d8d8b63ec72c3b6cd6e738abb8877d8eb7260668e8dbcc5dff27b13e747e7c886f8c116ec68c5d4f1e0ad43ac6aa5d7c5cc4ee8733a62bb668e6c78de79a5b812dcd04bee8fe6df8aa68c4d64fdae8a5a5e517217a61f01654c214c7d03a7808585af39bca227310c89e502f44012c8a2592dfc69a63199ce823410477cf03b5f2ee48e3625665c21526992b067e02e255f08b3d76907c2041fadbf9621048678b1689e66cc6067333b4e783f505c158c437df079034895e4013ea34664d5857871e28fb6d0f2986dde943f9b10817f82a31e456ce7da6eb93d222663014c9b90a006cfa3cc69dea93230cf27f1e6ffee3aa79dadf1d6160dfa4f9d8350d0da11910e147864efc64152fe104f952f6232853f0b7d48c9f641adc0a443b924f6b918b685bb2266d247b701913002966247182d73001960a420062f6ece5e735f67b28b49575219205434473d380dcd37409a3498d6803a2d8c57f0cab113fd4b0dbea44d2dabf3a747057eac68d7f26b31b5e21a9ebf5bb5ac33df913ebf38c9009d779f8132e9482d232173cacd8217ee269dfab53dd4ea0cc74557a30204ffb7f83a89f60d0a608a10d9bd844b88e28e2422d362ab80a03fddb9e5623c8cf57752ec1fa2e482f2085cd220b3dde2894c49d5fe254233a1e0b6c58896cc67de1ce51062808b4b360a43296992ade9ceecbc1b370506fe9b729cf3da032d7a882e846cfd43c4025d750f36647c7553b0164f812a9b65b8fc2450af6906ec1e1d965ef8b4bedbb9f2f5acf43c97c01532a87adb7d2784beaae9c42feac8b2cd13ade040a64fa06800b0c02881b73d11f92f9fb28629461a417553e785f78bb09932f865d143d0df16ff0247966fb2ea75ade3bbcf4dc772ffc78329738b1536e22a82f5bf065ea4c9c9936cbe4ce26a774a4abc3923d582240d43ab09ab0717af1353a90a7fa438288f8b754915fe6223f7c456682a1019d9d7e4f192f78c33eb13337c90ad55df40aba0f596a5780a191f433d522d889c99342e34cb7095c01083fcd8853c0381dcca7165e6861a986adef94e5a30124581e500a66656328e2e2f1d880d2e4c2ae7140db41b02fb32c402870886b688eb896086c6deb116bd587dadc1d69aadf35166847af8420490f5d56f2b0d25a159952e1b1e725811869f7bbaf9a99571de1aa83b6b586953d0897da616ca9c8a1cf655fd78ad19fd9bd8a64b946f284452f91faedafb15bc8998f04a4a8866093c574f0a9e95ff8724ca3edba3a303792ef811e7e7fa7dacbd3cee96facfaf0f9911eaf37659622156c9c53ffafab789fc3df968d69a9791482df9008485f63708608e9a8a6762f9d30e1f7a93cbe39663bdfe5b5b6b36ae661c21b453577bebd627bb2e9118268993ea1baa1de26baad0b13fe0071d16636293cb15e631ec980fac99fdd615fcd58d8c04f5edfd03aecff5ce1273dfa807bcdbf62bb31a1a8bc0136965badb3ea471c55ba065209802f9f224ba157caddd763453767f468796502760f0ebc764c4d1181531e06d4a4f7a8566ddd669703731670fa9097501608c97817cd415483145800585f24ad0226388a429ac914311d93a958af87b4ff612ebf99d9e81cee7b291b10c7b8ee41b5b5476994e28f0ab8a28b6e65e45e456fcf906f130a138ebd1a19138d484115d22b787daf66da628e951b7b269305940a673ac0b2e8e5fd418bd7fb545dea9316afe7281ab5f8fa61c9b34b2cf26c8481f20d1b8ca13b5cfd54e902b20285570309bcff38aa65d57483c74acfba99f94ef2e308154800b94a4076022f44cd3901c495f8ff948720828ed818212db98b5ba8e9b8bb6c6ac770731c539ea0d1c0e10b3aaaaa7e3fccaf7c2063e07eccb2aa67ee9333e5a2f03a0f5b5d6e169d821c71946bc9916c68e4a006de1eb0e5c7d7fb216535d17dd3098aae5405363fef649e273246605df510065b42f09112cfa7ccec7b669d3355948c140011e48acc02edf7309aea70920b4bea44203b6f466e6ab1769d262427387a13697b9a0e2580388a530b5a2ee39d82bafcbf9ff0d98a21f40697044367ecb5b56e39205afb79c1a70ef6bca9af72a00c826d4e0980220641524785271aad9d964c579177224bb8713d3f8d7aa49b5b799e03de44574430948c26ba0cd0df50102467fbbd12d0b33ef8b54f0b8ff4497e4b51180ae59247c503f4cbba7e2de8a18fa1472e7a37104576ea884d251b49f44215448115bfed0291340bf74f4c77be12e07bc9e59965b14f1badda40f5eb40bc6fbe0db2d2dfe0808cedfabcd5c54c22db81e6573001cc7d1f482c4a1c5ef8360335b3f609b837c789844bcad8a9f91d9f2a0c8697d5b3d84dad4da719214bfd7120b219197caf31799784bdbdb46d2f52ab5f31b0177aea266191b702e5733b0804e06ba0fa02919134725c3316f11f2522919e3db78ee9678d765e31409a6bcbe40b16aa39ffc01426b40b0d85ad4024f6f9f161644bfaf2eff04f2ff26e4515650902425355b1c02351563ad405ec38e590c579dd1a606d8a88c5b60c49ebea818b8d7301474f679aa42236afc5903962b97f999afccb123ac9672ed91e88dca66a6ccd705b9f0c615847c2b42c03a4e2f6cbd9834f3b6f4ba5e7a116bc1c0c0845de4d3d49961e57d15bf71caef2af40a298aec203579ca596ed0472f8e8841cc3fce3a8c3a08793c8f36acc195766d5ee0bf3e8593fe4d2c1310e636a27b04cc01e12d48a28aebe30d94091492d477a73d553f4c7c5f54800c70c52d0989bf31a20a30be043bb7719cd16fcc3e3098e1b05e1f356d310ff9735ed62961d8ba4354139a6a908ce3d35d81c5ace414ea855f95adfb5fc9c43ab3eb2a495345b0c8363a398ee1e84ee0fade81ff6b1f0215e991a0152d35d3dbfba4cb9c664142d94aa59bb02c319dc82b05722562bc4875cb9f0dc9091774743d76080fdcd8834a95fc3d0ecfc19bb6cba76a213c94551ecbe34bfca7bd559193a098dd6113c7d9c78c86fce0c111565b37752307a64b5e0337ae8d61ccacf721b4a809e3715039568ba9ec6d41c30948f2a23267dce761e0d43e6699a1eef151be621f48692cfe3808c49eb091ac5be1d1fc95f39196991874d1691546079f91ad4ac0b01a6b277b92764c64873392018cd97a1e81591ec15bdd17ae35d6c01b9884600a68f3acfa9248f334bcb9f5824df0139c92199c2ec7008f0010cacf96ffc6e0b1a6e06bf567ee1beee238b39b7a820e61346c372a051d30131aec68f2841c8b24787c25ca23dc82e6a1549db17d755cbc72be6abc1b293f8f8a8795f04494755ad3eab672fc9172b370b9a110f8a7175928827d4f41da0dbdeddb298d89c96a6e5e344c3b2ec9729f6829fe7bfaacf0676f5db740cc4ed7421355f515325344e6829c2cf6c7398d43e00f59c8877b819dd033c0f853e827ea3d7f62989b068a6a6751daa0f456262ca084a763ed47f9599606a1214cfc649d258db7a30331bc73299a0ee4889636745143948ba40a8acf62c2a2b591b63b8f1a3d76c040bab9f3101841040a8341c3668c05505232b1a9af71c2bb50f99836e4dfd38bc4ab944700dd8e420b561e8e16cba497f49b759ec76c1cd211ee96a6619074e9d8b508dbc8178d8c1836aad447835d14f752f21b0210632a833a9d01e06dfa86927db5d49293dcee1681fca999f88b6cf0758cc208b8a41f315599ae84d4193e26ceb7d02d91f19f0dc00eb7d7197fe80033990655104b58f1e560ad957669ac233ded514f1830539a1d9151a44d3f7f47bb7da221632ec2f03004d94017c0cfdbbf13b9834d4ab71e24f57ccfeec74909d24daf1f8e7f6de1e3a1774afae450742583726205ab29b833a22e31d421e9b1638558bc7430000d8c2a227b5a776e1dc35db2fa990dcf32bdbdccbe8399dcda5599c4c69fb18f1d9ae76693e704fa36abe2b0f127bf9ce873038d3e693ff85e88fa1340acb35966601ca3384e70c0be3784b17c00cca05d50c85f48393143c457767b443a8704ef878abdddf498a4978cf138c73d097838c701398696e0338c99417b31f17ac19f82dd0cf83bcfd09236e8419969ba4f678d45d07da770424eedd3032f7ade648d8db88d48fae886043b62d51423bb580677805f8128583dafe5413481db64a54848962f094f285023b0a41b8aef696ba1aa3916e6851779dfc45780df0643e3be54fcabfaa48545b66c84cb74bb4a2932317180faea7dd45c1890ba278766c91a5740a529170c516245146eb6d524fe8109057c168d18b21b5f9a49b10e2dbe05d7a52d6fa429f0b4edd5c5fe60450f51c19334d6eb7733f8421038b7e14e4b113acdfe7fe97e3877ac375ecc1daaf11c2161f5c09b55b4c610e3281c47ded834e3de1b01c8f22409b89373b413c8ccaf63fb609b63ecc01f78929c047977301e7816a3d6684392622a6b6962cf525976710d22eb0b4f39a353100a712cc496bcfde4d1fc28f21f926ab5700a9652e9881d19b696f25bdcd3a273a15a717f319b03ae012293d2d8c3de13c290ed84f59aedb22aa9187073df32aa09d3cea479dfdd407516260c6d13109c019b696a57b520aa880160afcb4077542da2ec796add2c855e411c9a41c1a3d02e2dd47e1290b9e8ccf14d92c10c145313dd236db575827df15a251c605ca428e46d3b04f9473c50b1c4d894c32faa10ef787d864b57e62ba8beff540388a29ffd8b0513f583117a79a0b67dcb87370bf47c05c03c38efeb800f8d4999e1ca329a01f0036511950d1cd3e5fd0ca52cc7f1f4f4db60195a088ec731e678f03043918cd9cd0ac13f61b99593d9b88920d571422072ff72f19dad6df0f6c2a9e6728a5b3b851104cfb9c0a06150b70cc91bbd878e014aa12f7fd96bb368032c625ac5b1f542efd49b04cae1ec293154cc289d14e21582919f9cb804dbc0427a3a8f047412661c9eb7ce03f05bde1482fe9ea1108d5ffbb96e814c1dda42dcd8233e0e705c4ecae687428c73ffd478f518fe8f3c548ad156b8299fd64651b827d42dfd7fc7347dd8d476dbf4215b18e4ab23d46d0ef3f5cc3d1453c6761404348b82b6dc8e28005eca3b8aa19bfac000d38b617f152b84c1e6cece43fec373a347af3fcab591d2619cf5666561716a7008b8bb3a714605443fbabe023bf0a3a1a8fff0b6793634a16c76a999f6e047b15d59fed67c5b54ebd217e55cc393197ca21eb6d6269bec786fae1d44b898871a2c38e00dc06a3b1514156486ca6be8b2f0234d24e8e99c4c822049ad0cc7acedffd93d017b8d314296a3f237524e81a58b3d92c3312acca48a4d4cb141de7db292f6de671ade18c65c171c908dcc05601dcfd25d68b539510c2b6bfae987955eee20ef505620d02f8682c2a0b15ea0ed04ce53708ac16c96580d106a5cdb734a3c49d2b4f57a2964329e9310672650d30e291a2f83cf28b844f202476e5af77acd9d71fcf7a60000ad83354012c7a391618b09168afa27ea6d5b0e78972afaf5b015f3c5b634d37213e870515d0b87f97779c012e97cc282340b4f932a216c04274b7db4de01cafa9b20f112359ea827129ba328800ec1c384dbe6949db7e94eac0baab0eb07f1acedfa91bbe28809d4749bfd964803c5e1c4fba75fe8cf0e761812e78b2f81871d2ed6bc127853321a57c5adc9c189fcbe34e631c31b4a2d60bd64cd97b2ce2d68141a1b9e64a25957fd0070c0f4966b214a52f6c7651b88edd922a775e556dbb313135d52d15f93775deff6eef4bae9a934981fa59a6c7b48b5fbb6483627d0b990e559fa695a97dbf22e4a3e1503a4b87802cf0adf9a4b5e20e9ee817142c030cc6497a2cb24eec35139093bc3d7e2eb1b7785bd1e9ac83a25f2ae9c24263c8412fc164fca9c93c2eaa4efa8972c7805faaebc8e664616d9c7e1a5b531209541e5fae436748959ae059e86d1411d4a4749079a2e6730c7421e713840269140cda6ad515aeecefd6435df65bfc2f0ff9249252dfaa18626e524fb3cf5ee8903caa68ef25f669734e5694ae2b9ab4995e132bd38b77e7189eea1fc1863ed849cbaf06f56562b49ef09049822a0f343fa1fe128697aa61019b0ad52eca89eb02f36bb8c7d602738a2665786c04bf9fabd5116bd6f94b9013eddf1c11c63e6933c1c31f0e49efa4b928cf52ed59fca12f2722d2c06995fffa5bafafb2bcf5fa91e3921ee8008ba0937b0d5118fbfb6446457c4f7546bb02b57c65b3ca0cd401974f138b996d981abb6193859df2713368e67c0fe6d8439d1f05025efc5e7a77177efc542e8efd9c5e549e148b3c91f8d41c7c87c5d77e778539e8ab99829f3c614f28d7e07bf50b319c4b9f0030433d6ec00c3d8fce1159855331d967604b945d39cb5ef890cb5ea04530234440ce24d414cb5e87bc57602bcdebd978a07201e5a2c96bbfa352aa503094719619c63ec8965c0480e8eaa1781a5285a976be23e4ffd4850ee90b43345c49e54f435d7e4b3c9e69bdf8f1d2e40ba4687342e4d536a943169fc0a7335fa1c4bb0c830c11d59df19f61c09312ac4305d63434a530c7a342159bf1051849fe0b78866fee923f0001787c36d697f1a733f8619e78a6a559b507e3cca91e7ab987970a383b28c62d4a8e482ad4597d34659cd7c2663a92fdc94b2f0b13f869354ab3ef48e6665f41a09bf4ee0a9c7988c6bb3c4447c2c66a1d8138454f334c49d88f074529a19b69aaa99c56eb24eba47e5f88472d05a181569e1222ce14d2bbfc6ef24cbb0a339c38ca0f3e66eacf82328ebdbedc0234f0a321c583ed40ec24cc44d8a95c2d35095dadf75b9ac010e88acfdf2485bfa79633ad11598bbf456856e71125a8accbe64d2522a3d4625a9c63ec8647a83c1ea5bbb3c6197a5d129a71aaa085305396d0ef70e62a4eb8b6ac31c17a78fb2776386f34d7c38cc5ad341d20819eeccc772284345d7a659792879bbf445393d5e20d683efc67fe5373a90cbedb253284f07c1bc08f53ff1422b206cc7c5f02a5af19673a0e222abc988d82de11f779b81025ca9a38e13e0140d5afa22c09e682fadddbf76db3115a8944be5c3b9b9bc288b70e546051df0f3dadeb20e6eafa40c60f4a52c5166e6bef55969a86008a9c8fa40626fbc996969412ca39d0f5cf6ff19e30f43d4d5ab1baa2f17b45e10fcf4f687c1ffa99c80388befb567a9d28c74ae1abc25153d3e98491eeea107bcc0baf93890ff623af69f8ae5c477709f1338754c689a64c1aea70c6d74511cd26ec0779692c69d71629f5b2342261a94af126cc268819fd255513cfad0cf2b88455f35739850818378119f4c1be3ed3ababac2627065ad5b8a284ac03e45cf93ae2c2bdc96061becbd11d279c28f606e619c79cdc6dec75cad7e79dbfab84134464dbe4a8ba95b68d0d944986e0d7a426981c1465b188053fcb4c0e1fb83107a8702bc2fb4e684b361f46476c1c79689abcef5c460cc3d65bb2150cdb235bcec41f61995401c698428de04cdce66bc069ffea780e353768dc0ec74aded55a40b89737b9a83a6c1e5c78a7b0a02c373f3effc83e2a382a402c9495f56c59009c09089036021e72cfc341ab890e9f21b27d445a51123e823562d3b780e06c207f2d07116be8bef1faded7cf57a5d359faf7ddf0a6aff7fb7c5308947e3e7a772136b38b12a5728f68f702994cb2685f84b46f5c300e1ce7c3733b66e639a7ae4d78d5c2385aeaf354f1c71b805ef0cc239229cb2639402810bd9015f24d6223e4ac37397c50f048f7c10ae2819025d6794a3ddc9b69a5fcabf8d7696f7303750a176f270144a40d71d05eb22ac2250785d8e1372076d7cb3a0e896e60323cc59fdcda798a9ed58cdd500350d0e410667eb105ac539dc90703d3b77a4829c4b4c6a4c0531a0968715cc19fe95abdc6beb5a24e910e6f014a41debf255bbce41dabc8c747e27a7f53693400a60d0d408e728a7dae76235e08b092c8547743d312e1a45e44d88615cc4f8f66f815ddc08b324fa34f0d152b13aa4ee92abdae66951f31153d5e4ab6fd1ccb4f457b5aa808b0275881905633a6b682bcf0c8c382bf78a0d81934ea07ccac46b37b2ba5dedaca5f4283d458aad3e8c0e95112e74873f81ebb51fcd7d52b0c63cbe2cce7d11fa57fc378498c33cdfff210a2ac9119644de6523d6cc784f19488d4db0af995f384a27de507792c15036c9957f2890e593609ce65f1456058a47692210be16fd15fd1c4dc3329623635564dea736753d2244e3eaac3962785ca39f1836cf983897e880127824d842f34c2d969d5eaec9404f7d06497dbb3ea3e46d246f3ab2382fc128ea43d010a62215103cec1c9c583109b56873908d9e7201d5802df4e31617926905900a3682d51832b6be93506279035e2e42e45b706a5f53d467826502b13fefecc804d969e606960585abab6fb1cd4690b794edeada3219fd98613239ce1b9e1c20b0b0d8adc0198bf0ee3de7c22a165ed90d7a2bcf83317ab607801870fe0708ed72a5a3c5bc81e9a6ec3ebe69b3b77c3af262559b76fea2c214830895505711d6de07b3282e97a5be7cd7b6713d1d40129d358e950f736f63f9ce953bb15c87cf0cee2571fe74c72fd16be87f4fe5127badb433579e35a21d0882bb449580505555d0ec89785d31ccea1f3901f2ab8ad4d4731c918b99466dd6efacd147f3028f2f257a4732ada16697ad88b3f1bb8c85c75c93b9d58c072f3cdefd596c42a1fc9140c91552316c1bc8f66e8c7a735872eae00a276e79d6d76abad324ceb62654b62e4daf93e3c5783b282303b451262d827815059d8c611aa50e1ee8cfe57d8d695798262106e62e28c384b8898aa3a6265658daa89e964498b1efacef6bca40fdd4ea97c42e9b59b22ae46d7d22a8b6f4b62e0f4234db40bde730d6ad497aa1beed5f3c98695bc3fb625b15b241438875774ed889cb89aa21727932da98261ff03eb81d98cf2a334186a420e15a58afb2cdabc25c8249384d8ea21b492a2dbf95e0df8eb04f940d1aa294eabac9ca9c59f99d62bf10dc5a6378e9c9823108a8185d5f65623be53f92bb2e1eccb4c3a2ddbcaf3f798863f79c4f57cdec737fc4002c17e70e5c9675b12cbc373b8f6caa42242db864b1f11b0a91de91f725789092db0f68f8fb041c4e83ee98711d9c402d39770dc0d55faf4a304a77da64b81076884feb689f90aea066b906f5a751fdd48e82791227722437509c2ccb4dfb425b11b405930d05b0936ac9fef4ccbe8bf178d637f1e586d3bbbaea29ad826dd455d9ca828fc0aa96af58ee27d24e648ae85e6503b6c87afc3fb5b4f178c26c1b7503c04fd33ea65f49326ffe2a31b8589e01755698ae22a6438aa27d9f12e223717725375544f5f128723a841b54ffdc530f1e3930e2dff77314391ab6b399145e08dd2fa07adec266393816fae65d5f213c4bd9874424a72538644ca9aef9a8105c1cadf49c9780c2a8ab39c9a40b27e2da28f710ae40e3ccaef427b99f909e2d80a148aaaf5fd1f46bdd47c0fc7fe6129f9d98c0764cc28f9971d87c7082922a3173ba87317e6c68a1a2f1f5efeebd22005f061e1cac77f4c7aaa12b1e60a4aa4bb12712670bb1875bbff5d55dac245cc314a84d9b7f6bd593f9534808916c928730b6848f09edc7a931e7b3af815c24805b3ce9b446b3b2bf67428ae7e32eabb3faf257e2ec2ebd4a554044ab61365a98429e8a7ae1b873cb080f42414c6d56e80e22f20c41d0454618cffb0c5968f6633656171141e9f41cbf45050b8ede0d6e240322c8f19a446fd5b47442b93138e22649253ea8c5c6d416350f4190b727ed7febf10ce194adf352f74949dac49917d31063f2e492a37218992b39f966c5754d27b2ce5c31b3ab436765171513fb7aab908efb2f69ee2c6f7d4ff0bbd47ff12a5f2d4d0b1704516b39f93a21708cf9622533a423f0ba78e98be15a54e44d644b2b1ae055f5e31a0cbf928cdeb954ab16b3a154a9e35e289c04b7391a1fcbc3897b30e2128f1357a8f3174fffea5d219513bfb8a184f178745b5b2c8de8d5deeb7d168189c2b8f8b13016d9d59226f0fec426f1d50d17765b51cd265dec736c886d29747bca9036bf1367475d72bc2a9dc003660a15f8e45f230c49a10989333b9939e445fd4dd6300ae8045e9e8deb6f19b8560ff59273c004a54f939951cd891760bfef41c41db162cda8a8f029d965d3adad2e2a2bd77beb08630bdb4fc7543fd6cbae8b9585b9e9b654e9baaa3d1e3b6cf67da996c681ae2668fc96b2069d6e89b3b77f43bdf2d2ece0f0b65c71c6e028a1390b1da489e79dbf86680734cf32f12d1874f62ff809d0ecbe68950d843bb9b8f3140ff2527681016d82b7b98a648175b3f588dfc8ebc3c21ae07695717883a26b3d517806e5b14ebf4adc8f6cf4d38d8f31e619a32d15957c8a56d4340b063446c9c3c76a36108db53a9481f14c2463b6ad04ffe63efe2540e615f64f7d61c9564bae89cafe4354c14ae6b8c882b505a075813d41f4124571ea55dcc9028460806295c26e0b2c01d4a7fc146fc0275d2a3cd041360ed6d2503599cdd302f2eaeb711be3fed1d31624f8e86274a323a17753a946e0ae1786a591e8132c7c65336969559f29b13a9ae10d2edd10ad6672eca1b613b9f72fc09d2782f7fbf07a1813e6b9d1ebed1043510336e0a8324eabd188fb0e70423c4fbb12ccdf8f00cdabafe619a312e7a861ca4aecc2454d24a8718bd7e3aa1300d2d4d4091ef52765fbe13474f17449c0bd9a0c18d18a2c712d8acf51490a05c6969eb87d3389fdd2749640054ab0b1765a9376a10bc770ab42001c45eb1666deb93c304ba064060a2809574ac91ee405960a43a5b5f11b8e6d32194b9d293c93640cdff1c4351a8858a6fea1fc1389d2b7368270329330795155c33fda2b3410c5dc39c7e9091b91009eeff325b7a1dc5d8a6ec64696ddcd75593b90d7dde899300b4cc1194eb9d1b66cb520758a1fb426a31fd231df8bcf31c2df48f50b1fb3cee794e358783ea6d04dc7d8d69349c7315476d3981a56d99d0bf2a42604742498e8fe2b0deef0aa2cf7417f8a809ced47f3d229bbbc7150f3ec210db6256b0c899572410de088d99ee86e897d82acea2b59b03ba2bd9e764ac7faf803f8e87c12582eacf88113d3139e2de5c29eda8e4be4310c7e84ce611ea7b3764da86f108a767be2efb53fd21f9b2d84fac55b1ad779d90b2c8c50e9010d20734e5cbe493d06a9bee62e19031b803265d61f4a2930fc0f16012f84628370a99e268cb82e1c481a3ed32d8c68437500ff5d9084937f2e4babcf84435c3c0b09761a01010a66411c9167d044a0fa05929ea80ecf11bc16a1419978d80090910a46f427079539310e69365157e11fa31de43869df9ff74ea874f96fd8fee9bb50badf00e2f0105219cd90d219815d152d0a354110ab7c5b3f6f19414aafeda8c00ac904f805dc8b2b333c5b05ca45ed64e98b12b2a2e4af141bdf068dd33b13f54e7dd1dfba19fa201123341d957f9922ecc734cb66283ab6aa08bc66be846530ff9bb082cab6d8fff00d1bcabb9ab63786621c2d4e64441b9561a5da4ac3f3575c2b22dee039fc98d60dd8fee1a38fa247ec02420962a181f95207ebf17d315648425ce1997fab36b8e06636a2e22dd70fb4e29ca52b8f8125d5c2f8dbd6cc336bb139f442fe5d1cd0418f2fce690bd173a6a361a6116ef469c797bc1fb378a69b46ada2fe53516317ab84cc399498de8a6901d8ca737fa13996e5959ee03bce0463780a6c4e62bd939e89041ca8f3530c72ded3e45b7ed7bce6337249cbcbfb78fd70db17978e8a9f9926445c97c599b6d589b48ac0a9b384fe119cf653329dd9e0c06d1ebe06474975dafe8718108c8b8072b69e5925aeec0da48a06037cd5b287557bd5a6fd12aae0a8abd45a9b56aaaf8164d1d8bcdf4d4db3f987831f563470de5c9cc6f69b863abeaf8e84015c458e954c694055cbb3fa860ea1d9e6436bb48753074349aa2b2376979a833fd2c2113652730edf7950645a5851e83b93fa82c3f3972fe226545cbbcf4d69a106643e66c407d2c1bab138a88fe19b5342e51cde83421b56bd89af9a03f6a7446e977c0e3b73e4e513503bf34013024fa018ee0b0c71dd882129f16f8fb4feb753c0d74c4a8a67e304591c4e1d85186f4a0bde0c242ef5376c3e1370bffc3e7af56cdc83928a927462676b9d7aa51cf8ed9bf08d21afa8e1c84a052ae16015d1432eea9472799849d69b816c6520aa29c3780cc1c37c7fcea339af0538cbc6c3c33a2b218848ad031077a65aef1ac06217bd05e101880cb05b94c4de32686ca7a388e718bf879fcc40eeadf707910a62c723d0e8de7e838c89df9d26c330895dc58fd422659e7d16896ee9ae3f8814094457dff40f4698784c2c5edae8abdc9e80eaaec3b84dece0ca4dbc9d078bcab1bcd30a1aa49502a885b59608148f18c6e39687f9c65e73e4fcaab6bb3bb3cfbcd82e9827c0664d0b5e66b8fde623eba384f2257d6ed65d4b674a2f2317be76c160fed1f2e4f41306fd2788b24b2a970c408aab0858c482fb9b2c22e18c70a9261c25819a27b245caf3f6983b6c09a95a12a9861f1722b2453f353dfd7a9078ac9110cd827cceee6028acae30436dd8deac884d9726701ce1fa53807010eb8cdd881cbee679e0329bcd1099acfcb4ca5f1a3fd7c552109d79ac97c2f0a0d2f30fd978d486e473b5959f1887179e93db086fcb89da2dbd62c853354259bdf2609c3e80d0bd0a2b3566c681eb9e4cc0f180a441633c7ab37321ededfd2fbb7c8c1b075a429157d120a3bb2cefa038a47df944b852677cfa39b0a8d29a9d780c4f5e6c9cd1ecf9b1971c184705c6cbade0478b6ad793166b7b4158e8c1f44388cfdced60098cb4045744ba8e930009eb679b631550116c1a76d00c1d35e6a6ac6f37f810eef0b48f070e6ada9817cd0e0d489086aa5dbb9165947a728e44cc661fe974d838e259e506c040422b69a4aca55a42f748225ca877b3f3fda8a98f6e7f4d53f06aad843892dbe9ec2f5edf8256478a5e0d53a5386141c7ad275f9c573eb72e5519a5390423b6c236e152f011edc3fe018144c4f9a2fd0981c602010c4493156887ffadbf0208ccca3f1ed283489c8385dd3b6d849e881fd18ab2139897dc4ee027d1ecc79d16c0f4b0191b7de5cd736c951b69b027296fe24c69b5ebc4e522a13c687ff2a5bc8277e8b23f946cbbdc12fdecfdbf0163507724b4f83bd2198543caa822a221d4e571a114e7a483a2a6ffe10f2fe33f602ff01aed6bf9ec77201bbd9209f2fae70844fdd8100ff7c0ca72e098cd76d67d552ec7ce41a5ad66c567dea20d5dcc04bc206fe5231111fc819d20fa26a370910a76208c23dac25c6b26e32cbf25aa14b10fe7d00e2ccda1c8ab2871bd111f3a7d8b4f1520c3efb5aab7201d01c6f463cc84030abe0cb9653fc746af1e1d6fa4f8b2816f45087fb337d25682c93343772aa0d66266c8d601fcaccd4d9d3766b3829cae3f8c1905b7bcf2da012e66f33192c59c54fe4183774d6e05807d95b4626bf23db2af5307765bb851cf62a4d97fb02fa651a40baaa8ffdc8af6688f15cdbdec79971a18cb3028c51698e1229e91d88af3eb58b57b174a0eca4245120b2f6d15985b916b3bc576f6cde6a9759854eaeb8e2ce9204c631a1fb24fa3eb9f1c35d1b408294082e09f51c1df28a39e29bcab943b20b88c88343686896da3589ea7a73e747e4f7917c0013a6ec650ff39e8844ae7ea5ecd9a49f9286d8185c03aa27ef80bdcad477ac5e78e3bcb63e4b0cd11f660fcbb2b1f50a9195c3311fb2a201c9c53310f02dce7c4b7e8bf9a25c46de66cdc57d1b148c1075615fddf79331ec4df7ffeaea45a54fd5e5c8b17f36c7326b12077a8dde372cab3c355643e5f350ec1d6d6154fb90eb9a3ddb66ff95e9a698586d9087dacb299804f9e3e693084859d6071a3467c838eb68966c2228eee752a85a86a647647aa52ce7bb8720df280b1ce380437377b42691d43ff4942c138edee5964fb7333c958af5c3cef88d69b5ca7d09e8022ed5e178759b2ac51a9f9684b2dc9cdb056f32d50f28ca708d12a2cb925e0e4e9764df5c30a449d7e4c9ebedbd17e40d808c5aedbb6e95024d56f2e3d75b7bb500e33160a32a1bc9933999cc84dd33d0c8cc9c6099cd826e16efe7e9f5d8a6b8848de2d98265503f993e161c466a42f93e26d1d81568eca36f639fadd431578f54070148e7cc042bc82ab2cce8ca5c0e5b1d6679b3e0ee7dc61ab70eb90af285d19efb5a6583ec7620c8c93d520efc39bfcb46fbd198dba1276a9a81b3e6794b4991047b378b40909934ca2442bb45b5f6137924547e6e4a64e0457770302d66c818c177d2607e1b46652c994a0e101a0c7f884fb5b388dc4f54bea81067a0886bb03b4deabe829b44266f7715577c8cdf7e2bc0736ab3f173b1d4f4dba66a8fb64b9f69375045d27852a87a5f449e955ba469449706b1b8a65e8b2610205b14289c487fabe7d081472e5e446926483bd41d5d417e24e440ab16dee8200478a5d59c0a3c58f39690c14ccb87ddaf4aaa9c1a69f3f483df251c87a7f47919b37a7537137ecbcf0083dc3f18ed895049389ccbb2a7df08d7939e8e2c2f3ec5d70a38056e91487d27addae456952843e6d898537b1b601d18723c891a90770b6adfb2c5f3d80148ba8048a20c70af46d6d93afd06efa80670a9cab7b31dfae70fa7f792079423e202f481a79a9dd618825d3063716343a6b212694920256bdd79a65b62ee7c18ee3537d1fbc1740dcde8b14a59e98ecad492eb5bc011834ba05e049363fc6f354faa4cd8237c850e6ccbdb66985e957826a9cb3c82b5bc1fc0ae7d02b7fd1d5b3d26c46fec878e3df1d8d3470cae81766e640c79349d3fad24d8eaac304f6ce00d6ef70342a625931baf8dbb68af596cbe1868802de8fcedb72304c736b511071eaf4f8a4d9d930c6ef8057ee9cb21e0a7355cc1020a14a07b10aefb1b10ad5e169b9d6179b6a27a372ca3b51b17a836e3d8415e121ef99afd5998c7b3defee0f3eb55cb90edaa9b0b5d2d68d0897e428e67ad52294b1fc36329716376dc1e9fe51a315659ff3de3cb381927b461a6441ca475eb75fc4f9e7e8c30e0da30b972d23555553df8613430d3a1a1db1169d36c2983d927a32b5c5be70803819ffc9f3e8c5dc2e40a1abdfe59bed2bc1d8e9f07514763297fc1479b0f12c2242feec119ee886b2bfa4f66ec27e5a1e9635429f0baee64dd453c855ca2d0de0d3785cc8fd96042ce0a839383252bb6799235a7472998b45140a13c6abc86482926553a8759386cf9a370a9a1c69d8e6b233ecab7e3a8280056830a068390a3fdeafd0ab02e33c875f1d47791906735c74237cfc4e982d88d631f55438c17e229ed175d39b4aa2e626857a24bfb932cbe68e27e653ebe6b5fa7a65c997f4864aa09b486e4b2ae1492860a48e48ad94bd082e8ba99645ea18e39e68f07baee0dfd3a7964dc5a430afb9b846d79539cec5640315a8ee85ad23fb839906a5a94d35ad280bba538bce57124fe516ab750ff4ccdabdb71cc1ebd41256d1e1d7f78a2217aaf22f0da9c1764057613aa12419f60fe938860d1a533d0d532c16d5e463478268eab3c19f82c315bb1840aced1a47ed62c3ac26d5988806048df1030327a318a616497170c9bbf74e6672a4828bbbb0419e013e489015decb38d277ebb5beacffdbe78fd93d17c1ec329b50648057bcc4bda52e35a96918626619812fbd3a5ac6dd913fe91b9cb809ff53c9590112184edc9091d2fcb3e8347c8ff0ee36d5d96741fdc82a83ee95a15668c29d923bcfaf1d074859de959fd0af724685b6fca0a8745a1575d2b36ca4e292b3d80f50926abdf1d3e7ed0a440172be471c762db2719dfef4f3588f3114490c45157ea54b28f51f8e3f9c6e5f2dbc27faec93948bfea8d910cebfa74a4e8a55a0a412e5bfe03c761317a63dcd695bcfd41c1da335907af5ec7c89eecf4e9c6bcc515a676561a5558c7dda2fc929a477ffc4aa2b6f5c61ca865135d6a7023807f69e34c28133f15df714652c3becea97f009b8384f8cad492496b7fe27aa56fcbade2a28b6da5f6d18f104002114ccc0daf35392424db8350573e7860875c5950501da5065d3b69bc6120259fb1c8144f366b107426bcf280a156dae6bde4bd02ff07965c890228b94154db179c0152a5d38ed6959cc2f672bcdd5801fc5707ab76c75a06f85c8d81049d42ffaa5d4e07162ffb9ae90d98179da43c952c1260c6e323c295f866fca1f57140a958597d034106d2f8f43d16bd77618d6598478155258ce014fb41d7e63e7846b85cb7d837615a4e1d10fb4a80c2aef6771cd077ff6c7c6511486e312cc1f3840cbc439d8e435c0bcbb458c8215290f0b38eda469bb8b5a472e3652e89fb08ad1f39315742c39c4ff9a34fbda293bd656c0cdd4ecf1959fad5814e4dd8e97a7bf392e3dc9033f79b15ed644ee600eee52f6c82c5a8e1c259177668d60c3e70d4580fcfacc103a2c416dbf3255f65c8a5dd68460b80269f8bc5da29b682c8aef74ed0b1712f6db9c3918713b89398e0a86236005066dbcb8e7712e46ec40ca02c0e2333109479b9216d10612586eed66afdb3d9b49b8c4247cbbddc2e1d05041c9a41e41aae4c0b2977d5cd133f5203b6f1b3ce07904573b206c0fd1443d83423a62e0e75d7f0a1dc9df22d7d34068b55467132cf97f45be754fabbf7c87e581fe08f619e68637cb12f6730b54ed89055fd0f23a44ed3a526fcce5131451ea3ff041ea4b1c7ac918c5754ed714cfc4b51d3ea0ffd29516bd444022c1c1a665e792edeb0b0fd61d20823853598084d03187bf5cb68f355550d91f07f43e63bf4e316662851c65afe52a14340337d5824a2c8677a3316de65ecf001c0f77960a3e729be73bf4ba42a04347e474c693fe97b5008adb71e2ed4f6d523a0f5fccd6beb8801fdacb8abb438c7fb0fdb169c89143aed15992fdb306fb0b44418f15d283d2ea4e613ca17a7b2e98ed03d358645ca21413040704e9bcb6840cd05b99c3adc47bbfabcf23fe933bd870da75aa306a4edb6212dbafe39f4f39617a7d969dd6a093c8fd51d38600a0a42efda8b19d85e63e9af737f62de3779bdc38f48b583c0e8865fa3615ac49996b4b2514aae1d61c584eb23e243f84b485c2e4ec40fc29ec4e4cbf1f215b9ae235e0241d57dffc83fe3b0c749ad869376a09978a98de329d374cb502a427f5e3e1c7d9f0f014f6240ba95fb3e13edd6bf090111ad91291c03a1e05bf0806d72db8a67dd34d9f2785523b9e7da277d8fba7839c7b562e21500c09c0a259183deee7f2b0d81e7dfe6161ab588127e3b031a867c216403b1843ba03ce58df4525b184d11e6b08457991dc0e86413d67cb5243e5bcd54b9e7b89f4df1345540182ee1763870f27b5be12bf64e19a428fa19f24f8a4c77825ba90bec500729aab2488559feba37534a44c940e2a5a2c841460428f9a9c4e9c1e55398d61c6afca68b8fd3614e74e624553d84e4b996474b4e7ab211fd9bd56ed2eac38939cd1f6526d971da965d35ad893adf14440ef0ae923d696c0de494157b072a2549d51debdbac696a68b9e2bb6dd604502d0e151c069efe19a80aa543d8452f3827ae3c31513d56b1a51f9a2f29a542981dde930dc23ba00ca7eb99974657c012f2a582547db034618504aeff5ac53b0f3f2398c6acebe117e0d70dfe4bd85f01e2f6eac86f4f747f80255d23c38a8088f0d64acdbb7073d60e13ff54575264dfb571c8b04fb55930793e208f46ed7e7eff87aca76880cd1ff8e058fd71fbdac13412c23d4e103eb955eddbedc8dee5c26a4b41430c8aab4367ca82f15396da5403dab5c82c49e38cc3d17f03044b341205f5941af839ea81e15410df4d69e20243a1623028ff830fef898cacdb188f5c5842773110745e2a7b5b00161a64b4ee94d967b0fdb20dd51ee032e5f17b02039299648a2554a13311c030d11aa7a7f64ba9c3b3b268d4d9050b8d29b5642d76cdb5d079b0f889cae4d3087e0afead300ee96bfae61cd6ccd2a3e38e4e08636faedfccc3015245095ae61336e1c5e50f9a88c9c512922426ffaea594653d2f6f9eb516d241c00ef410d28cbd85981bbc582b5111c1238303c443c91c4ace7e0f533f02fca4c568631d7e45412e85a92de35165049ea5ac7938e29183f9f7c1b4dc096b097816cda3340c462adb80c010ea0ee784a83d93f772f4f5573695aaccbaac6802a3a4b914f03d99d781042cba5ee40affe4cb851aab31d9263b304b42639c369f7ca0da807ce8c2a01bc9287bfd89360e5c294675eea0a53c96a2ea12602546d3277ccd4c07bd77bf8a560049e2184c8e6e7c03997b8824c2a2e1aec5316478bfd4d11d0b60766ff8a66a3dc3a1228e01780b3d912e2321ed707c1bd4f9c6c157bfa06e66207e71ac01ffd487f77b78d91ab906c1ebb8c9a7c1e4d27a6e215417d377d617b0f532e989bbf69f0fc10408ac0e2ad636292789926ce9b582fdbbff4eac48b68863744fa053e7ff770e52fd3b17ccd36372c715736a4f48429f76ba538b39983d1f70584db330522ccc337bb76ed43e8b59efcdcf5d2c1453d64086f9bbe45ff69472bcb9c5f231f88e4dedf44a0c2def1a97b365a7671099aae0b419023442ee282b2fd6e919b1241a4312bed411a59affd393db517ce54c08d336c6047e9c92fe18c0d8736a8885a5bc4182c2fa46fe70aec7990a23939be3c2b59dfb3876862861abf0c68cdaf26a96ff1fd2c5ed734aaa12863237285f9de434714055e895bc5adf3be6b09ab485d45f32cf8a28d01739e355a4e47993768a51fdafb98067d66bf34fdd6c9e25b78a35c2783b1de4dbcd8add4f19f879538744b96ce67896ed616c1cb7c9b64853f77607d0854a0435c030fa5409a5296db224c6d718acd49771071d88ba84ddc364984e47ed799325c1bc872081cd67e12739fa5694739538ff31715aaaf69326ba66a3a91fdf1dcc321e4fceeb516012ce0ac86b035ae55794249dfe2b099929aa74ffbdb5eb4b3124923a6523f774f2687ba62655fc1fb1920b65fea6d8c00ad9d1498d43508bc9469280283a1739f3f28fb667fe5991fbffd1047e8ef633abf05588987784a9f02f9c3f30bc190c5fe91912a6a49d22395d0ec11e0d1add9c63c1f264618803bfe5029491b900dff1af47cb4d07358c64266d8f79ce57da3d71868bf8964369c4ab5cb95064f08d2114c6cfc16a3d86acb7fbebf2405c5d99b08fac23d9a19856780ce31199c103ab9a74796f69467dbe52db05f8dcddff61268dc46151eab5c6f7a3653a4939d4f7002569aee34d0affab67a8e0e9046679a433b5de919bd83b444cd4ab52af1699cf05857dc8e014d6fd8932c2c19c594ef8134a78e14c13227dc2cfc9bb6e2a5e6003045ded4809c14ab9e20750112a111464cb547a2394a19ed180c01834f239b628a5dabe5c8369dbe1ea8994d12a97acad6ffd567e8ca400df996ab58671d4ab31d7c3012b94983186157eb19aceb2b729efd58a56f5b7de97cb8a500567f10cf3b67eff8429ebfddb9a4955596b9d2242b4a953257ccb9bbb6872c165c9ce82fa3f0946f5a121972d97e499cee7cd82c1f012b193490cc97d545e6d1bf37555ba80d879d78126db7033ef95c03906379434cca3fa3b0c562d81abf836e143cd9656621f283a170577136c080215c91a0b3352c359791252869041be4905f285cbb4e578e142b8808e82d8e16711513388a5cbd7e80e591f76af484905a5f2099da14b1c62963dd897f6684aac4a0c764df801c63eebceb39e824efa512cc257b9697560fadae9f579397171ec93b00d9da51e103019ed1e155a9dfdc060898bddcb57fb245168e262463d1fc813640d57c8373003dcbfb979131e01c7515a267d71eabf39e5db4582dbdc92ff13cf58e8eb2cfc8b720914bf6a53aec20a73d0eb091939b1e01da082ff1c0a1ae2800a4a8e5e1a0e2d09447e548e1558f1f4e986892b5eedd37e24fc7618f09fc142ceaa0e0d90dbe6a28915a17d32d71a39440a02a5961e50d3083df909989f9c3f23614d59888e28858815af877922eec173d7d180c5b5e1458bfe00b4e2a176748c40747b3e2780c06d24cb67e2cf03344070e789bb48879c3475800299bb492591211b0e289cad04f9fcf89d6c03bd780a3177cfef39847e5207ba374ad02101c4d71061066ff235a67933af9565d8561726595298d2f0f47e4af8cf2af6e1d0b923f1531dcde94e2694c53845fd215eb94a3dad2646fd06089c8a9f360fb0bfcadbe941e2509d3d99ccfdbd2ca78a02c9e86c22f6deaf5bd8ad631d405e63c639aab605c4591febf3c359d4d7da4ffdfb5577016b0e8296c607058a027f045c644cb3528944f4509b43ba22c1d899cd56f8df4b3d9690b0e2b0842b6f9a22bfa2a8daa26070cebf393b1cc1a6c4986b699d92250879bd36edb9c1f49c07b0e797a94ada219d693180121daf22f81ebc3b49e6adfd145317c3f664227706b674ab73d4bc953890a8a7641d39aca186f9f0d180987d65f9b3a1e1f666a4b931e21eaa0415eb5bffed1a170d23307f43b708e6c3d07c2fa2e03536251a32013c3dc836ad366514a5cc9da8b412035b458d56538e0ae63174a5389dbbe080ad8c65c8240d34111a30d5eefd8761ad8719e567e9decb5f0a443932291ccbce15019ae2c11874b85408400c3a1d207d5f355a82151a53d606e04311066fd76ba4ed6fa91c773ca5dc83609d1b1a7ccafe487decb85075f577957a00abbf0bdfd901b7043ade1eff75abbe095a0a0180d9a83252f59e4d7c673f7fac83662f2bb9695f3c09cb7e11c595a7d78de048cfdcd4a276764406c44e93cce4167ab4440ff9e6db25cc6e7753aff98d2999c43916ce4ec679e2e6c5c3b201005c1d07db4290d2a3beec894e5119ecbfc060d9d69867312cb6550be18348b52f98b9833057c5a2ad12efae41f9efce552a5ec651ee14c499616112e28c5a7b7e31fef090a37aebf8f591ffd0ccd4acfc85d3927601a5803d0b7ab32c6f07f167b4378fbc71c2a5ff8e2606ec7c167c69ceb7bb20fd928ab0765fd4056c2dc509e886a3cc829aa736bc65bdb693644dbe593a3809fd26d47b3fc22a9ac1ff41b31159a9bfd5e72c693c23d588f56da889476090f39d81a60bade4ce995023ac0c9bb5ed8dff92d4a1df109c9424d4ad5b5c16ad586295ab56bb0b9dfa345f13a7e7194568491b3a19c0d0b2e7078a2ef592fe96c368f41f79fe3fd82d70948a1c435eb5d952de2bc3d135110dc6d5fe3754bb3814b439e73206558f33ee5e35ccd1e8deb9954961aff23827b88fbcd8bdda8b2c25a374657094fd51ddf31af3b7c9f37af6fd3749633f188dca79efbbdf4df21c4d1f72c0b3c30eb2cabe6c229ae2b3f4d4dd2c36d0fc360930baa71bddf1548c5fef48b76268c138e314f20cf400305d04c9fd7d898f02bc339aaed5d728aaccc0a90be058b837829a144224a7742866ca7eed3658d0643cf1d3b3eae3cd5c38d7ae82ad2b3a9882063f1d27ad72682ff62fcd43cd7044f0da7dea60468cbb981bb9560042725f9aba3d9c22b6447e3375e0042580a1a3b33b8cfa328d6f33131771865fab3280128097a83b5044ee6df9f1abe11392c36f8a11f3e4d85b1d52926d7bf8bb26822f5394c35c5562d72028d78fd386a86971de09adc692b938cd759fab904a5fc3ee28fc4e58c6a81e687432dc1a46f5c26c37cbc61edec75d2be792bde96a41a350cff6e190eb9c76839f229bcc3827b2f549a29107399f31a214f8a1be9f145155d195a2b289de531b29c853344b7a6bcbb4cc87bbc49109f6ccccb123bc6352a9c58c713689b005dab759d3d197d7460063d118cf9edfd229299e2f45843df248c563a771b63233b8deabae2ff99d63cf945a3c10fdbe183e570694eb518ee32f2dadcc9df703572cd831873f11df97b5fe6a1c69c80124f1e9c27ebaf747f961d93d383e9d5cf70e9e861a8311a6c8347cacd1b431538d7d76af8ebd76ca64c9448f11481f2cd413bf1040d2bc665d5016bec5bc896bece4a5f3b5721b2e9dd12807ee2138b751c75333698de27ee5c7c212c4381d75a28be6dda6126b18b98e8d4145bb9c31fe99994035b0a95cc939d35b5c68c8e44753bbba6c4f7466defa970e84de8a1b082dddac9efbfb4d0e813d05dd73de84e9a4ad41bea5a4b2b62d96abbb41ed1ebb3d8878be3786dfe000f8790a01cc362bf586c6357bdba958d05c30f49b1b39393082a6bce59904577b0d78918ca2f6c42c77fe03a970e97cb97147b007a19d8ba9743118310d5674097597ec3353e543ad4761edc549ecd1f382107dc672476c629b2dc413c9010e8ac3adf28d44d803334a2e66b3abfb86066570375cccf66930d0fdaddc603be9e40c24d01031c0969cece98f6dec7295cc22e4bec52be6a924d9aea1796c0764d98cb4c6c8adc07775dfdc4e85137648abacd4c756da97d82ec530a7bbb7778d5a41f2ef1b634d793ff14cbde1eb92883ee672fc68d4594062f1dbcd752fc68af0f965894523e0ef1d8057858aaab0742dda94e189863f3bc31691d2296bbe47ddd90b68e758c0ca781052a2595b14aa58fb2a35849df07ccaa6daa377ed358a03c58242149601b64303f893520a5b08f50a522fca4f117899d5cf400dd349d6029bf78a7270b8f88a05afa17ff976a754c3426d48895f55e8cb4063cc943b81e28073d601873b3ae5b549070322cdc2d2f60555fa3104424557d63038f828c022d4f532f2da7415a546d15d81fb9eef7fa3199b776eeb136c55735f641239fab7de3c55d8df304c71ceaf7128504328923f51706a7188f5f4252a66ac0a6387eaf944d12c6c14ad997a04415fe6bffa1be9a5ab2c22bd330e88ee29d65c394915909c498c39b39e30dd53c8204209881395043344acc30e9bd2512f658143054edd2025af73998c0e6b4173d5b9ddc4d23d75e01be8c6e3a84172c06f1c50305b070b89df7e328c5ca6b1630130aa05236ba05056c811398d5b6d051f3f2a5ff5c6f2f70133f5f76e142ceb9513af7e75b5e052db6c02606f50e41ad0252af255f301cb370437a0a9b28d6625925ea258c0c8c839887ce6f569a697e1190214ae7c1dfcf6eb2667242a3d7fad0b5498ec71e117e3de7d4a75fde47011def515f671d393710d08ad6bf5a56827d4e29866c3ace6d4a04c225636117bab7a09ee757076bab53541f31c4a0d8001455de02f147d60ea93398e78633e0dc28bd08bcacb0e7baf67e5761edeefc80034bc25cc7c95b885cb0500a7e08640a9f04d517518fb5a5213723ac8721165c8072396860b2848ccfe253c601307a46ca77467dc6c07ad08b43895f6359d773cb9b33f6d83159a63744f54826f165fd04265b696fbff648922c55ed91a21a99e094d2406905f2c488f55dfe34987879d2d82675c88128a3d807a54f592dc52f8d4fbcebd0befd2eff626acb01484c58830bd4e36f043fac91c2da13520c702d84e01ee637c0f1242b662864d15cb2661bd894320daaa0a2c3db9cc93587150bf341e397b8033fdcb6cdb9bcf3937057dec5d44f1855b0454ae206a1f5c913df71d7c208443904c4dd6290c73feb636c5406d022e76d1e938c6ebbb67fa6898da9510184e36a164aa812a84e287c2f2db0a3563538bf263f953213a8023e4477a4382f503ecad3a219e0b76eb8459016e4919a558f195e8222f1f905db8c46915830234ed723e8f015e82ddf5a1b0302def7415a425b6486ed4a22d5ae2fbb81ff5d3542c7c128bad8432e7718445ffcba6ce4f665e9071d7b4ab6fe9c0060cd9e3a8a36a4c5caf53981924829b699b2394ecb1f7da6fa15c4cf1423a871bc6920d478299f3dcbfb770bb9c3f996402b2cc0dc1319d5912b15fa21ca3fc25a5881c991203544ac8cd5fd8a47f15a8705f440ef836999cc366255124867056f1580674b45f770e42c7a4b67d602fa553583e546e1ef203c3999a460c3c8321e2b7a80c411ee2736e7e055014cc54ee07b9167ed52e8d859bc159b96b6ffe296295731e89d7e0d74cc72e8c65ec7e411eda5a63e6a61af2187391be5a753e774911c2d360e68e0841119431f8398f95a58b09f96518e8607c5b8b26997303baf4cdbfcd0b4baf0ebd25443304dbccd392c41b9017f93447bdd867db57a15a6689c6e53295df3a691d9ca194e27ce7194cd252264422650f9f356cab62be98c37fd4c1e1488401e150f12bc878ad738b570072ff40c6b997b0c912a19d0a52c4341565f28d0317d536d93bc302a9deed7437adef8ef34901cebb44eb9809f651ccb96b3eaf20313082e9c13a6e859c058be89ede7d4880cf0012d99ea817dc27b7a34286ea4255ee0a5f2d4f26ad60141245bcc276319c7a22450d59614cc7f8af71b628d6838ef16e2fd10bd18a0f1de3fd10817f5bbc767ddd6a5c57c9e522445eb0e5193c72745bbcb21660364468635a45e5d55f4925e85856266ab2e955ca7a0ab5e8359ff176beaf8a637cfd1c533470bffccc71303d32afda329b8331307e72bd1f63dedf4f6df433b2dc1e2a3323a59c5b6cbcc797fbe12636fca6a54f364b4ea74851391fe5adf4bad6666a4e98144c450043b51a45d4b0df5d78fce6071ed6286f9affdd3b28344ecbc70e1335d1a735e049d0693dc79235afdc99784e8e68b734942f9ea9ac6de9fc377d5f4729fe4891168f4edb27a478fd7805f9682c5ef577b47e496b91f30a8bc75528fc2a455709e6d608a4630ee90e195234bb31394a904ba7f8b79003a4585651c3d5b085cd185aa1fc55fbff1ee6986485391c9a366e33641fe757dd7a7b2b232f2bfbdf11732c81a5c5beee64c83d2d6caf4d0c5ec46f8686675b00ad577c5f68bffb4c2de7d33a08ae496c477096a0e83e0cc41a0c339564afc6cdee4dbcd818bb00837d7be86974245bd5a35c7d5f5262ec3c7d8c1af834e34cab5fd01ff1c6dda7b995818ed3b5a29b65cc13667f7e127334551530ea31c092f32ec673a7f8908177d53e98ef21723a22a6c0edf0e9100e3d167400e4583fdec734650fea7788e9148fcfe05cfb2e134e58494c85348b08d575fa737d13633018946a4264ed20b878053f3d868fa859a29bbcd0aae08fa2d171775ae9c8f34940a0023c6d4d010be73101e3e2dff950e52734822825a51897abd3a14ed73926ab5ef6e6fd44e221fd6d45b142197e9d522c5bc12847ae9d1a00c5088226a74ce3aed25116c1a800e6e93bcc6f37a1708b8926fd573b4817651a642a1addac0b7969425d27c52970ea9446fafa983b4be8745f4f03a56e78b04e2e035dc750e8fabf201b0514a58554509cb051c24f1a5574212f916e194b22ab37fbbb59e688835dc19e15523c0b911ed704a27595e33985a1509a9254761c3242c7290bd8472165c46f8ca00e188a718e27adb4d4acb530c8c8e70009e740a953a6c1fcb873a7a28820fb60abe65c1745835aaa470c40ed5bd161574d0ad7332420684003edae03bb62db2348131257509d45d3edde541d3230fef2cc9ec25cdec08865d2f41619a7646d5dd6ede01fac416b0ba4b45bbc4607361ff7f63cdac7eb7e8539c6ba63b98fe7e9d0cd3b9fb80f614d9dd27ce7df721bb6ca2d6c15d85a337f8496b400300cb3bbdcc62c741b0b0286cead0d97094d95d7ac0c65d4b51ef556667934ae6c56c8c5ecc564e09b900d7a2b8e71a125b2dea107c0cb41c79efa651d96b2fc432b497092ff38c6a8074c607ba170cd66f2ffbbeec37b6f1a1d34e179cfc7acfb58e0311d9817c00882b166a801385d6a1db8c568f98fcb3afddeaeea8653387db742d995a586af2ba5441214f1b4262843b3c227f1e3f26d82bcdd28729c2b1f91c783d0d423f509cc24e7104cac534a388f92f7264ed300c2c71e88067cd31ddf1a647b02ac129c33080a8403e6fa2bea2fcb6b6f4f4610c076ace5ead880f31bcf3c7ecb01ca2d4071e543b745bc1cffe9aa0d3d0720b1e91a4ce4fabfafeebb002a6e0b68c8b24794079944f6f6b98bc1b299a139a6a3804d6c6116d3a377e1558101641d0ca7fe4878d323c159a5951cef2c23c836988cab478e577b6503ec0b63cf15f27c3e9e6e0563969e6645c9eb74fb1b9a7ae848dbfe38376c3c889fa54787db325a7a2e2403095ca5a31516ce065461e8989ac2584b0f7d084084d355fbf9f941b6dfc32b73408ffef95f40398b1ef15173876384874171f88277431910dedb5bdc53f03572e39d8350200b00fb918b5116e99b19c7d510158e64488ab6a425e8d755b3db74ae78fa4b8176a078f86dd6d2c18ded6d4bb7316e2c2ccd4826fd30bb9d0bdb154ba41498c48d69099a9b7bb3a5ed240efc169e615e3c8b8192bd384eabcd3d592fa4d08dc8819641aafbd7bde3a25f1414d674454f1c8f5d32c1f906ad75c72fe7c97ec880c1aba170d3cd36d499296dee1bd97083fbfd985a19c887ad403b54b9c57eb9edc19c2def6dcd3cd3cde20856b4d39b4c76e3f203dc317e208bc4c20f8b3a428852be6db6fda63886f67989d90e242216e96f9df83c5c018bc7d5b48b5654a068a87369be3b5bf357012575573e6543a9ac5c5b4d819b5364d37ea50a93262b203d9e6e606df2b7b88cb566946fb24f9cc0a7ca388169cef777d782252fdffedec3e9bcdb3fd2bf2fc43a7a7f5754b4111dfb3b4fba7497754c2036a2a4ed38a66f820bfae6061bccbba833ab8e72a353bf17221cf74f9aa31015e78d7a30b9733392b5396f4b441fec24043a5367ab5b301895710e79e47cf378e43cf2c15826df725abadc7d5cc5064eef4e9956f3bb67abdf75eba2eb56f97db5fefd0780bee98307f0c0df1fc794775b16f45baa43af68b1ae2307e750bf35a900ab11dc52ccc868b9b6bb7b4b99a40c520a240ac10a29686fc05bc45fc20e04638c31c6d80816ccf4da767a6d970615c73ed1c62fdad46edbf95bfb75dbc73975750c6d876c23fe02b5cc7d7fd7e8e844ee5e3dfdd806de5608685b4f4d19feb7450bfba2d336bec2a7c70841c45a94f1570acf006893f86f4e397e19b739b6fdefabf1bdf518a8ad91a613e0b1a8ad61f17dd732a0bd36881b30cd0efcaf38bebd5ff90bbff73deeba5cffe6175dd7652ce36ee3395e4901f87cb67ead9ffefe72daf5d8b57e57c5efbafdea57ab574474b4d3d3fbd35fdd7bff20689a5ecda90ffffdeacadbc1f79ec97e4904e6fd1adddfb0fbfb13164cfc15277cfcd8fb2fb4392d6919de7fd57e5e876d16c4ba4acd0e3562e867d72220423b6657235c50c306fdf5d51ad0fe5d8d183adae21d71a7694cffef574ccf5f8767d42d838ff72942985e3776fe3150cfee140cdffe381c90faec16cee3ef9130fc6b783aa5531eba3b8d661bc0db72937961e76d79f7f8eb6de1fa1daedfd5b7d6eaf0ef57dfc3f7437dde160882200882e0a7c1dbf21db5b64a3a95c076db655c63d8de1ff67d6c8ecf452344f79ec438bbe85e7c517c320cbfa7046a1c2adbf429fe302c85d88442a15028140a85fa93366fcb4f4d30fdc5ea0ffa9bfe95dca9bb5699547cf25b7849ea6a9130c56a8b98e08b7804b7f926d363fcb8c4e4cbb402dbfcaee4c550e35bba1bf40d62ef4bf84bb95697e95b5c32a710f0b185d9c7b62be9c226d961a9fc9eeed30a6cac71a8ecd2831fe6b2a7fb09d408df7c119758f7749f82a72f41ddd33df8658b0be6f0f129fc32d43d253d54c3e97740e00a2ac8010b8cf0e0043a887d8e2ac48722b31a2451abc10862a7ef5e3ca14ea7d3e9743a9d502814ea743aa1c63f7d256740f9167ecaa8d3e9743a9d4ea7f33c51b40cf5c4f8e78b1538730884a32240b1d3e9743a9d4ea7d3e974fa1f0f81d1087cc4502814eaf4228a13a94f4d811f25d79a22a501fc1812389d4ea7d3e9746a71cf7cd6b0b6429d4a60a7f84b3678d2b59ec0ef28b9c64e316c0c708327ff8e8e7f661ace3fa15028140a85429dfa07a85378c7d1f1578e8e7f42a15028140a8542f91d34a052cef33ccff37c1e37b153efb840103c30810e96300515d86229270a8542a1502894e92d140a8542a150cfe32686d2397650e008081daaa0821fbc200b31145dfd743a9d4e271e37b193de51bd357e8b8bff24a7336caccdafbb7c933c019f6d7e39dbb5ba4a746a6afce5b770532eb1cfeec4959422d3fbf2537097a9f7250d3ff50b4962a7d701f4c576f8c44eba7c118319bf933aa186e1fd2579607c78ac4f7a3fe61af75330c05dfad427056796de26d9a2933c5f922449b60043a7e0d0e99d1c02fad849e7a845b11ff8459c53e0c6e180d46747e0db3e1b932ff0a762808f1fe3b01bd42918e0eefed310f8360e7cc13771971f44f3c284d8f5bd6fe13777f7de7befbdf7de1d9eaef5445a879c9e60da073ff57dfae88e1cae1f9a00831e50a1881c72319dc367a8081ae0820c5210830c1811fb01ead4f7fd57ebedbaaeebbaee79dcc4badf4103fe1a52623b7278eeeeeefe3c6e62fe3b6828b100071b9c80043f088116a301ebf3b6ece7a8b99a1776103132842ffc8899b76531c618638c5defc03b4cf73ccff33ccfebf40ef0b6ecbdf7de7b9fc74decea1dbafa788ece450f1c1d5974d7d5ae2b47ab8fb5f647ac2bdcaebb6e1b50d2d1eedefa6c05e0ff6ed8df7b55013802663542063a6cf03d5c5353535353d375a918e85e80a3b7e2e048b989d449b9ee6e1c8d61b7354da40c4fa73edbf5026ededab88ec59f82381503dd9624657cdf89362fc0ead46afb297ffc36a40cfbdd93a48c4ea77c01f64ba5baef7bfbdd6bd7f76dee0db5e881a0f721a9e375f5e3f9746a8e254ccf35361776739ea2c958fdd503c3355ef9acaee13df838a7dec7c00f7e47c2f01ec4e1dfbd9771d8ddd5e86e58a3710718f44e4f41cfbe72af189f1b8ba79c89bffe5fd80c17575c5a6fe78d59b3f1c988896feab6babad467779d9de121447fd1a4b3add5a9ab15595dd6a493220413932fb493d77abd65adaefa3e6ead1162f5570f7eff14ef8adde7da9d1b0061b1c46966fbe858c6d2f8dffa89326e7da7322f7e63ebf65e5d6b80d820699b7b74d41dac2e24ccea28e8a8fd7bcff3bef0bf8eebc45aabe30ab3f1a7777b18b534f84331f64cdbfbea7dead8be78c7fbdfdf7befdb74fceef50775ddee8ebfdce16b9130bea467affbdd758f3dc8cbc20d4b542c927341ac6037823ce07f30bcb1f45d7e52a7f354e7e554f7a10bb1c76e177becf6de7b2fa3a5cf618a756a6bc5497529e619bd1d6a7bfc54fc2edbe8316d1c78dfc07b5f52c68803ef5a5da9ee2d1e75aad3316a840f3e7e27753a9dea1eddde83a94ec740b7a777363e1df5aeeef4f1a908296e6dac5147afeeb1bb8808d2bee0f7f8d718714cbaa726d943279ffa8b2f7a36994c269349f7742b272798153b5a7bec1eb5f855d72a93baf6c419740ffef1c5f77e57920035566b2bf52c49801aeb4cb9077f5a9ade499d1978d858c99798681d264f834fcce4458f7441963e65bea963a0db7cb3e4ba077f6a7a1c770f59c0e4eaa02147921f9240052d74c10b496226bfc32766a2779cbec4f4a2f765ae9bcc3d36c91662888f6d8b7a4c799853ae63a03bfdcf61633a6a92d88906528999bc977b3a3d64a26b30f91d3976f8c44a4c4c4c4c4c4c4c3e878966c06dddfff9f901ba8995bc8efb85590c08fd90cc6631a03356f23a4c49b3d92c0604c64afee747470b12182b791d31189db192ffd15193dc66331e68ace479dcc44af4036eeb9e9a60a6b5e8c27c7cfc0cf193c310244c288add47c0858126e0c1111f58820f46a821b662c1118a00fa6143088e88dd7fc0859dd8b0041f18a50008270889892bc09f9672a93a7a43bbebdf54f8e554f8dea7c252585dd8753a54db25bb1a31d4638b3e82a51753fb852fb6b82d1c67fb5ff617ad4ee14fe14737de3585750c747fdad3b502b3d92c031b9fa860fad747cd1b44ac2b71010e33f94cff9b0f76f2f56dce0abbb9adefc3b1e2dc5325eb0ac7bb01d706476be9c5fa7d1e7e197e29fc521886226d08beb847cfbfe3352286b688d45a871a0cc9af34968638cc1679eb7b8c26f1474e236691fd5d22e283e0f838f02ebfc7b4cb775b2a953e0c4be17f7886666813d6ec303cc3300c4b20c9139642f24b4f967458fab0149a4a1f7e5a7af2d3b27cf23b12c6c813fea853f14b8fc552eec26cc17c857a20324408108b7e9fb23a06baaf1edffa70f4238b72a935c2c6244ff85e6489e42a4e8d118aef204a82a2f824e9453ed436ccae45444876288aa27beffe9efff5bf9f001d6e28bd8b5fcac086cd3296205db8933a05fea8c3d4d2403c9e4aac646ac01bae282713339ae46bc3ede146bc48f61e9cc881f8cd85f80ffb7bdfc191e36eebbb40489eb3559bd0bdc15f5e71eefefe0441a10d3ee8e4836feb8a2b6469be1f1f34bfc7b4cdf717c75cb72883bfec8be3ae350d49927c512451223fe4ac42cc9c2d7eb5d9e2cb88e89b2e8a5bfcd05fa6ff072bcef8a248b6903c2229964f7e498ae48ba458f21ff9e5a7de038c129d9ade6d57c89e608df04977777777777777f7573173adae153f491731a3cdee6e54f1ca6d09a67f6a83bc87997166047d8759c7fe4976db778178112268a9cd01b93df2d7491047869cc693130f768a6f1071be5bac66874b7688bfee76328633c05fe35febe3011734cd33972bb2437276852562698e5071766a876c27a21e515fa6777bbb6e8740a2c21cc90eb12b6e4d05a8ebf82e9c5730a580c484ed8e7461f8fef8d485ee505de9ad6dffbb83dfdb8fbae22241f9129dbad04fa70fea4e639d82fbde2eec0bba48ec8a6f88cb85a2ffe7699ab7eddf10df66c98b1fae6045ef7f411736d6d690ab6207364432b6558db63dfd86d840c0a8b79dfa54eba58991c997f357aa3475aafc8a3e2263aebbe42b22f215f9de4c01f2d725f214fe61be3d18c14caf0db7fdafed12fdfce89ec73bce87f8abf4fe5ee444688cef0bd895c436a038b545704477500edca6c3f0ccc79cb7fccf93a376144d7f7d6796eecd51c758bc96d4e96eb7e441f3c18bbb42f0a7f7766f25a60997200e77187c1004750a46f9f84b3d4660dc3530ca06c02f287f428efa87c22348ac5e96dfc283ee63207fa5f0dbb0fbbe0df5f63364d7db4f6e3b9ea5fcfdd248961e9b0c18c72fa718dba0c3f6c74e5e3d04f4b114dd625af285c53b1c4af971d44d983f3f4af8539dc6338d81505f37ca0ef30121ced9e6ac91bfb435d2b688a3ee314a1a5754fc5a51bc7b68d8a5927e40031cf5673151fae70759678ed6b4a43110dea99de20e03cdfc95da8e5f308e8ca0a275a72936d456dd308efcd456dd30a480a4b65220114c9086bfc0f747c002fcd5bda35dcd85a97c8d8a2651da7cd1e51af753fbc226d9e357f20539eaf43e0eebb3c3cfe17b19cf3c6fe6cdae061ded3a9dba1fd2c9730cc4ba5ae1edfa68b52bc699930670d200a7b5b9db033305f7ed02d2769daadb67b7f0b3033b6cddf6817bf1bd5d67f1be785b21621212a02169fbe315a417685b9b9484a31669001eabd7ea0b810b94e47e2fc6f85adb03f386e4a73ad0f65a6367625d892514982d762e4c02b3d96c16abbb7e477ef9f7cf0b33fdc56fcae7356feb56474bef79ff7de24edde2bfa85bd42942f0d936a79fd39cdaf732f861f6d9a5ec4576087adfe27e9e5714faf581685f007557d16221b0d69c7eca0030a7f6823edbe61bddfe342e81a5c1efe516b7c320689af67d06f5ebc9796e40acb5d65f7dbbd6209eb260bf9618df8e6fc7236675d4abd623c752e7a54af0c54749cf1b3d4f7b68c655ac494f6cb42365d81fdd45ef6560d81f452b962e3e41c1ecba1988d565f0bdf776f862fcf8628c31c6187718771a5f1208edfbf77700dadf8349bbeedc36b1ab1143445be6beccf8e9f78527336553d67e760c6fe05dfa74fceebffa7de999fabcefbe4737f889d685fdf0e2c05b06f89f4e590dbe8e451dad200882fafbf408ca385a752aa75804668f69bb1705b18a75bcf7dedbe5faa29b6c92ed39cd9181edb38dbfe609f8be6177d7e3bbc5ed522fd57ddd353c9dea348cea1a47cf57dfe75a5b841b362691b6bfd8a3fb01ed254aaf91ee867d892e8c14726f3f170716dd22b0e8e6b6e32360d135622d98849c955995d8f64f0eab31b0a8b62c784445029337b0c8a828b753d0adb5d674588dd59a52efdd5f6dddd7ade8ad8fdfc32ede92489e10c4ba4a4bb7edf6fbaea806b37df17fb999a3e28773b76edfc7428af0907d7398c8be4645f67d6cc45ffa16e270b8f30ccf73b4e01d4b2530d3b382a127d5a4fa5d8f4ee8160a3948336b38db11d1f65b98744110e73048bef86d712ea74be667dff475933ad6daae0b71df771a87dda918dbe26c6fb8fd09d948f7fbca510c4bf7bb8e2449f2fbf42c47b184cb512c618c35cee1221e588e62f729ce81b933a7e2549c9f8ae3b58ae315c77b107991990fdc3d12d443c5713bc4856ffb02df76a7d3d5ee846ecbf7bdfbf66069fcbfbfe597486096da567bcbf27bee2e75ad2ea10b0b937ab02b4a446152925049f770bffb30a94464579480581afff434fdbffa7999e6d83d777ffa2c812b01c11ac8b69f9ef582f6710e23a17542ba231b6c1e112fe986eff61901d2a1e2781215671c6b6c9040d034cff3df9e2914bbfecd89ba42a5d2e8f30a663a96ba1939cee0afeeefd3d8577f077461210ee72eeca4e18240d034cff33fb7fdc52ed77d9e2f7e5f1de2425c88bb158fc0fc4647edbd38f0febec7b43f5dab2bfd429207ffa771d87d533176f7e00dbbb1c6b01ac348da0e71d47ea9b426848875958216f4e12d7f8c0423f9f9b1c1f6b03a45081323edf41611e576edc1ae45443db6589a99d706babb9beeeefa82342b98f6f18fbb9bdd960fd9db6a8c75b515b95f1a88a72a98e9b851235e40138f36caa3cc2087dbe28fefa268c79fe1c2feb6ee83a0699ef753b4567477bfbbd3eebe760f8e250f0d9e9e2cbfcbe397e3f823495e9194c167eb533ec9a9eec92f5f14c572867ba6a0d46c93b7b5689b98fc68d2998c265d67329a746e6b773baf7c19fc959ebc0ce3979f926306ef4d75e393dd58e64f394f7f036ff11c4b9c7b1c75da7dca87a48bee514e9dfa6c141b3d1609478a4e894f7ed5e9f8a912957bec4e4fbeeb4819a3a853a58e81eef1c7d3a725f8637e90d419c7d4f89f1a3f7c707c74935f8ee4add5a5659071947c91cc29be6d6f97dfc2c99ed62ef58d519b882511982532f86bfc2e356a37c9a9eec737f9929ceab40d9df1756a75998f03dca62f79d2247e6a7c2f35ea1e9bc486ef4efb68ca367cf7e4986dd3f8a66cc3922f96abdd7d69539f6df2c717bfc5256f80db4b470d8195985331ccedbdb93dfc2dfc6e30db58c0ae2f7a9ed6f49cfb46f776ef4af6a8f68d4e779dc648bb85af2eca9a4e1067dbed6dfbdd8fb7b94f4998f67dd7dbc68ed6aee441acabb4a36dfc6559fe7dfb27e18bdd782a32458fd4311dc5e28b6448b4efbb113ff2d96de1d2e399d1f926924e4110c9acc14efa0d03b13f52c6fd92c81d88df2a0e09e37ee9328e92ee1aac3027ba39d14a0dfbbf5327721d1cb5da6d621defd135ba4630d0c63f1bbfff388adde4d3933fa1bc45797bf2f6e44513bf3ab536fc3b92fcc7e1775d177e870b1f23ada4504c52dd4aa7d29d1deddefa0a57602196c6c4c4c404e3aa0be3213421258f53b45afe0a4d45a7e029e4bedd288cbbb413549cfba669da4fe9ded4dd22448ee234c70e4dea255bb6a96d745e8213511e9b7c8a8282f2a9d7de6b35506a18a97b9453761deedbfee4b6ecb50e9827da6b8ee23f39d16efb825d81576069f08be32da9c06de1af229289939078a1e290a2ad51f237ecbe5fe61a76a8c47b1e02fa580913075d1307f57014c951fc25324ec25b5808071989a5d1da37736a7ef765ae61be7d9134f37d6bffdefbd6fd1a555790bf3a9dba6fd2b8c7bdaeafcd517c61464646464646924082f135ba34ece31adda36b74da82997271874a7c090d82a6799e97f6ea6649dec6357c4ac2290eea8492c09d8f837090d0490b26c6e17247b372ace6edc151fc2509a3b56f1147b1c54936f04ec2519c76421bbfc5ef5d0f473146aa2e5ce37e7a8d6a1bd368387fd538ba47a65071c82f9f24bfcb69a9537b698ee2b0cba9fd1b9230ecf5e128fe5bcb82995e215a8a691bffb5361ffe4ad95bf3d7b5e1241c23f96bfcef71dab0f1cfc6483676236fe13f02914c4f3a6da3db74b0165b1db414a8dcd66b62652c73f5c106b38d3067abb5ab5497a552ad6460582bcccad9e57bf950146cb5421898524c8c282333b2542a970c0ccb458e39cb3c8ba552cdc8c0b0664a4d43f2f8a659d1d0986a6acc13274a6080c164448102c5898dcd69b54a61da14afd389498989d2921acb5c85ec55b6b1d910f5dc2fcc36fe9c6d787c2cbff803f4b155d6ac1717edd9b447c4c2b9db601e62a954ab15986d601b9b0d118f6f6f85cd15685bfdea7b9cefb6b15dd5dbb7a99935c62213b0d2321aa862bdb8b058d85d5c5cba979717300fad3e67a08fad4c1335d1c75f622c730db2552a95af3cff2aabb4e9bdb8b4509657637936ec92339a59c632d71e80af5f54a93ed57739e715b8fa7c641d787c8cc5ba3506ba606d42d5b2fa988c591fa359668d95afcb7f2e2f2a8d9a1f0ac46e6155cb58e67a0b9f655d5edcd6bbfab1cc316c14b60bb3a9a1b0a12871717171013fcfc5664a4d3bb5a9e100836d3fad4440b0eda3624bcce47e79015fc09797cfeb5e40cff4b613d1514451f0f36a17fc9cb398cbed9265b41a8cad458e60f7b1c632b3d825507cf1e5e5e5e5a593792f9339eb57659588a224cfb75197ee9321478d769f8f2db055daa1f2309a72cedffa95ea4b5974bba2f27c1b84e9c161405396e960ebc18180624c1783b58b1ecb0c80bd52e59f1f25d3abc4bf0113d36ab56c8c0c0c4c0833c462b1645c31a59818531e72f997fcb37a55d6210197174b59e64356735407b711fe0d70876126b74cae81456760519a0b0f5ca08c96e95cae2f7f269a17d5a8735050ab7e955739ad9687616c45576399576c181b13e33232d7f5312f0313bae49f95ec05f5847d990f8bc2be8ce6295cab1c2393aba7f05c2ef275d6efe5f1bb2c7ece59a59ae94072e46186a8f35aacb1cc381bfc1b604c76cde40c43434353cb19a626a67a1e26faad5fe51f1e664c5513d6ccc0b66e60796051d8576519ad26ec6ac2eec407038822d471932489fd28d9903cbe436d03e6606f607960695e606dcbe66d254fe603053e60b2ac765b35f135c2c8318337e59833ccaf56bf5201935598c69c5f5e3e2fafc8298171094d2f26e645c6046564d0cf853d958bc8db33301da68951515323734fc86cab98132e87018699986c3d141ef6f2504c4c9955a4084b312f63996f5c33341a9a1ab7f7deea9539d7980c3a7ab9e4bb6c7ecef9cb0cdbab2ca3b93c857dd7c92b315d2ed255e657ce34663480441a40175663d6f88913271c868b027b2952b0c017edf57a2f0fc1c2b1abfb262cb19e29738a4d43f2789b26662cb3cd2ee59c1f061864b5dba2b90f143629768e7690bc33ff0beb5fb24d6da512c392058219b2b28cf679d6fc3eef13c14f044b288aef51803244a0e645ee541cae9119cb8cc2cba6efb2f730c060f260b0362950a0f0142f1b9b142f180c06f3606f4d356ff4b2f7373737372a4eb8c632c3b05bf947e9750e6f803d36c9fefe06b8c117455566d9d8b0fc054b9142d682eab20f235d90fbd337d53ab95f2fefc2f0388a64a86f3c153cbe45152a4a2a4ae0378e5946c301eeef55f9470582ac17172038a18f5a0fdeb28f0343e7c381780a1dbc65bf95d6203d6cfb28724afae62600285ad45bcbc6c6a64684195519c8b69f42063d81593f4565664655ae3195ea61a40a16e621f4bd3c848aab4c63267b9d69ccb297b32c878a83e3dbdd5b190e152705e3dbde7f382611a018def63a8d63ab973466d565ff86c6eca66623baf95a8d8a131f8e8af5e2f2d1348ed7b1f24a97644315c5e8e521fd611e6abdfe52ab9413e250694a2d9d73c20e850da913430b92e76e50b76871b3b78a300fe552cc8cc94a50d08c65aed93fc4d7f9e74789d4297d78537a18a96353b3b1f92bd4261ab3d0e636f70733fcd4a6665373d49a480b9a3b3d3b9b9a8d0e36361752a704c3f7309031beeebdeff44ae3e8762a86f779ffa52c1baa32195414cc37c0fd7a98759bd75853903a3b478ed26cd07b1146ea742f7e79e7c8d3acbfb0fcdfafb22ab372bd2d534da7104037d2ce11476dc51ded9d23476dce343e93ae6dfb17a431bb3019adf411996dfbf7c51657cc29989ede8efd9d233b48fe7a09df26fcdee6fbefd31140772ac6978ad17d8dea28ae1b469e3736459967b67ebd5e65766d2fcb685ef3141646ea745a862264aa90f93051446056980983955966b3b28c76c1dc9363b6f1dfd0c21bd3621f8ed66c3ddc3c7843de9c50a102061c1c142b56d8e4e4a4c81900af9c5988b0d1cb43ac07b38c565d3fd4132cbdc30d73cb70a834f66368d142c5de38b1d80a992c27000100808e0e0b172e62f817248f6ff0054c7ef1e2458b9d9d0d03464c000290c1c06893766b688cb75e8c4e0740061974c670e8e5bb175d6fcbfc9c65341991f7323e6f068a8a32c3ac58617330d16dd958b8ad178795653bd496fd17972cfbe107e826c67a1e60ec87c7c77e7898b12033d8f6ab4591d6203aa4486b90da8f0e9b24f6437c1e608ca5c91f9fccb21cb28c66695a5087ea0e95878a83dab22f66d90fd5657f450d520bb59822e73582b21caacbbe8c6669ec03e02facc66adb0621da31f166cc5946bb2d592d886ddb6721d359e6c375b0396a9f05e982dc329a09548c3acb68595693e52c8b8174e15b4683eab28f5202b3bed8025fc7b1d52bb15e51615a39e84b8e4b0e6ba5d23939e75b72724ce4e4b0e494c8c9c9c951c949e5ac9c393727272727e7f3723a9c93e33627a7faac94d55d83d064be4f82f04990eb93a0ea4a4f3ea8e2d46a0493cf3b26419193eb381fe2450e2b7d7dcfd5eb75e611f3c8d1eeee1b04d3713ea4e87aced10ed71f6c135c75b969b471cafe7bce5fd6a61439ce831c218808deb588224692f057753fb27fb0cdb6534f2269418e70c44eefcff6b75e77fa2b3d19b7e9ee283d4cfba9ccb6328eda3fb1e1255c1c2ec326d9587b96c67a17fb68af2532efb661375871f01d478bff627bcb7b75575d44a6dd9dd7007b1df63cec75f85e04789767d03446ab873effb0dfa4fa69cd3da0d61e33227e30dbb6122182d9f61c626945726d9dc1fb61fb579410d4c04c6bdc1f3b03ac065b60fae0fef565de6deeee650f33759bbbdf0fdfff2facbadfe03e9830f0209d9a1af420ff21c6c04cebdf4fc7a0f4d668dbfe1874615e5011afe882a0699ee73f8a7a45dbde21db7efa5d5c87d425d920f7801cb5efd9b0adf7b36d87c4515bbd99d7c3618e745bf6bd1b3c1fdb6a4f876dbd1eb6f5807842b6fd950a9ae7df1a9227995eb510da1cf523db7a16ccab43221df650dbf6492c98d5fec782217e4032b3eb103f0cb171857da712bb821604419dc2a7a70fba1381edfdefb4bf0fd756f83a5df9e0fbc27004d15f9967e5815857a7cab22b0ab9eb77b5e2f8a6b16536f8d7fb0f023235ee5b1289999af6af061de37b83bfd7bc353988f67b58205ee4e60009a615e9c088eb605b204168add8515cc4f47d5da57f3bcf5657ca7b1b9d4e79d5fe50083aacc6ec9fce50bbcc9f1fb7becba0b46b1058c0813502178b9ffdaf56179871380c6cc3fb1be0a6b13a83f8bb37fd75635ca0c336060d1bffcd2109c3fdef5f5286ff7d8f74e1b3bd922ff00892e3fdaedb5b7e5f4d7f61fb9eda5b05f04ddc79a2b992228447c6b80f7ed7a5e0cceeebf66e446ed8b7cb75dff760747a74d4b4ef1c102faeb7852b1e417f5defb1f63cef3deffebda48efd7b53f6ed76247c48db7f67f3e787a8c55a5f75a762c640f847fc14cfc4c7330ce42fb1346afc836733a08d576076493b09473ba4ea722f775b2835984f7029d8a838a5ed475e841680ec5a841674d8e977b4fd67762d220b489c60d6208e1cd97707cf822b5f54662e2a3396ca6ca532d33a6bd3ade575c265e5c5d678423b79c209ed8476423ba19dd000c022a77e55bd903a578be8788798e97963916f1e0059c57f2ef15d66f91419e75bb289cfc9b0bf7928c5afc8e72dc593452078c9a2edaf326321a2b2e06e0bc95f2cb9932bd4170b121575584d0d8afe9fa7ca096d3b0bd24952d26df99bc8285175f9b36494360bdf9f85886fe3589060c9f9ab565484c16a6a50f45f65565566b83d7eca82b4fd5564950a965545e80a4a64d52d954d5e36280a2d058aa28298960c8ccbe657b04d0c4a0e322d7466a6c5044b89d48aca3993824299399dccccd4942a5a75ab2e7fd54d754b5faaf0b28514ad0145dafea7939cb6825295d1f62fc9294a031488ed6f52dd54371487ed30f0e1bc6d0f7bee620cfa90088837d21dd7b2adf8c0e018d8e1d6068249aa71871fe9a2b44bb5eaf2477181693f2dad4c76157709c50526abe4520acb2ace4e5710ebeac77defebbbd5a05d5163dc24491000f4a3e766d7b8717d6238ff78cfe347cfcd06eb09ff6b2b4ebdb19b69d8d96c36bbe0cd34b0063d853f7652c6c9be2f7ee3fd71adb5de959dc6e1de77f7d56075f983a06944f4477d67a7053528dae2b66e307861f7f1e32b5eecf6963b3b15a75abf3310eb2a0d6f2ee4868db01136c246b70b038d6ecb1fc46da322236c746120689ae73f8ad6d460a30b03c19a673b3da2cfc8c80332f2828c3c21a30bfb6eb7a31bd2ed76611f8d86a315e52eecf38c4e22d3f67535f0c8443abd24d00834028d40231034cff36b405abd79ddadf9c21938036746464646b7dbed46bbb070167e349a7b33cf3bfffcb4e12c9c85337f85a622b09177faa9c59b4f2f9fee973cbc759e77efdf6b4560da172d0ef26bc73b626bebbde5d55f75b91512abbfdc74ebb6769b30f6c73a0567fad79b8a716bd4edc3b82b8eb82b4ea90b4d2653e7815697655971eafe34496eff8a5377ad38deae15271c4b63ad38647d599bf1f7d58a532b8e2dc772144b64e95597ffdd825882bf9a2515c7eeab69aacb9f86a6e280b7a502d37e8d0dbc882719c18317f9ba4aab116e41309376379a46a611f3c85fde7f6f1ef117f9df9b48fec2ff693369a72741db92e477def7613c8a251193188f62d8851dfe3c92d421adf55230bec7ffe911e3f7def3fefbcfc3a00a0af5a5427234c85f273d4e842e4cbf7d5550c529dfbeeaa8e2bcea0aaa235bc58510ac4c9ca0be5a3713b48ad3f2f64d08559c9556101337ec160b10f50523c482ab3826de3ecbade2a46052c02264c3a864a0be66728e1e5dd88cd16d9d45d4d74c92cf2a0ecbdb3f8d2e4ce6ed9f45cedc5954714c3f8384cacf4dba48335da844b6fd1306154633bbad0c54184d2d650bf5455354ab382a6fff9ca524559c94c7cd8098f930a3c1a69d27304350c3a6495390d0e48e6cfb2839942228462846508efc65f2278cd8b0ed9f6ca1c250d84e4e7cf8ab767282bbb097b77f5274612e6fff247761adb77f627461e8db3f39ba3098b77f827492c44952c511dffe89edc256287e00aa284e19d827b9b563ee58e613a2ac54e63a040f30a65f14c17128e651b20dd4ebfc03fe8ffe925765145385e42f1441a8a8ea0a2884d8f62d8a22b6fd54c5052aecd4a6b62a62db6fddfca542a815a4be54a440050ead20b67d18217fa9408249417da9b8820a18dab63f83447db1e0a1e6fcc5c2e6e88cd185b1209a49f2178ba2992ed4178b232a6a9f68c668c668dba7995d188bdc6dd1d42e2c86194d91bf62a039a2be6298cd66b3dd42538b81a646538bc146930302880c08683ca2f4374c93936a4dc01be02ebd78b25e9e88a7af5e2f4bfae4b6de9232572336cea38e5dd2b175783a36d6b1c515aff4b48ce63af66964e59757655636692f35140fe7ffb2f738df20797ca3720ac75a462bc7224e4c459c506c3d3115a1a052526cf50f4541516141c928e00b0a850a5d5252524aacb3da5a5c3433e729ae64744a68998f1c5c34332a2926151445ecb0ad8c221947cc9831c33683871944443c369e5c018e8e582b1e19d4786c365b6ea55905383a420b471c6dfba9540995c95e19a2a8fc151947c82812223763c68c204444265a56489d4aa558ae10665a83d05e98ecf345938c8cebcb9c4be41d238eea1d2347ed112c30c6d198053141a531db01aa38e7dbdf31aa38dedb5a841c14581070b40216937d712e4af6017c98d5b6d45ba63ebb84e96535b4052cb49a8d85c55c49b1b4b49cd8c326722d459c4100516d2d656ed9602733e33261a2c444666556660195f0e12d3900e18e8648424b8aa9c58486f5656659e5555e651644361e2a8ac2c3f3e54a8a4646ee6938ecdcf20e10df21c25d1e703dd8fcb54383dc36cffcc2e845ae86174a00c20b237cb9929a01610b40a80210a0308408c84d082ec8115acd4674c31511f19ccc08418e8228e15558dec57a2da395c8e229a5b55e71bd978766be64e65daf42c85f336c2a52505f3378e0a9f1c8c0c682872222886610cdd08146c943d9cc059042018e8a8200c2871a0e2708816b46b36644b70c04adaaf512e5338a96d14c542b33789861ab6126039e1aee565db4197408d932206aa6ca844a6505ae625629278bc53a6d52cabb90431609c9816633170af2da90d34c171417958bca9719a55f5e625e565428601eca2e68b6ac4613533232aecf79e6cb7cdaa85c5914f98b27e747d4170f1215b54f00a1198064e4642051d1da729a2d9fb6c42003fa5aa6bc93ab2efb3c45b6bf768c5051fb297987004217b64303a00bdba9a1b66420f12323e7af9d0c54d47ed1b6299d9a3e80bb96b698d0e9990491999191a323488ef690c9b29a0d5794333a429225c990ccaa2b072003b515b44db5757e339f33cd97f924b3322ba38c5081c3b6af02c95f0538527185fa2a80142aca8287fa9aa1838ab2b0f96b06110ba20be3c9b12022daf659e42e4c46eec630bbb0194537869abf6698790c32a8af197454d43e8b1c8bdcb62d2de719c32c86591a83ad08080820db7e4b96d1802e8cc766b3832908d0b60fc30222765a7121304268db375180a302480113edb4062962c9325c75d9c733741064c826f2972c88ca93bb3099edd4b9d44ade21aa2efb67de9191bbb01d1f66145dd84e086a6be6af9d1aea0c3aea0b67c3b69f2b22082084c8555b0b0c4e1c4cdc098628b261a7d50748b63dc93a4759e7880e924e123a498e16016dfb31321bcd4c9615e58c6ecb1e5da4db4abaad59007e0200545d3cb60b0b400db545c40f44d85c98ec14bd03b4025396792f0fc9e8db6d115d93a1fc26eb4bf210100864c6585a070db3592c6b592d0685723a31294929514a283185d4b1478eecd19922922a5e37e4828a22857d15d205b941bd524b2f491595959134a5cc122652c76eb18485acbbe21216132d2c5ffe402030f6a2ad893f3daacc55882d9ea78cc8da545468cc54545e320da12095a0956ea55ba131a33163e52cab5d184d66da142b67594d76bb30d6db97d164b60ba3310b42b4ca3466254ccba20144238886d01311fa58bcb72ff3e12f8fc6cc51fb26b0bf6a4bca498ccbf5acccaa0d79d78963ced67992a79d876c95155bfd2c7315c2ca4aca4b9428c1a2823296b906217c31654b9428b1e81b842c26dcd6bb821acb5c83d8254a942861595858fc47f7264c5cb06bc929badca552c632575c688b2e0e678d866c2e9bc8d9da74cdd66e4396a8057ca1b5b4fcdf3167fd2cd6afb2046ecb3ee0c8ce2a608380802c6dc80aa9c0ac9fdaec62c3dd96260770516e3051eda9be525eb1be12e758e60a04d68b2d6fc27e6e19523d2beb90809849b2ee07b1ee54deea63792f7a329a75015954c632d71f6c70c80923dbaa48cae3bf8f27f2499db1010c30fab4d7e595ea65342bb3922e6ce7e84845928a249b1780805c265fdf536765b4baab4996d5481d92c60cb60ab961db076f4b176dfb2fb96ddfc568db6f1d6dfb28d2b60f93b4ed87b39f6d5fac4280b6bde1b6fd9da31ab67d2142382d6c2121c01dc902a57da8f48c3685418d32453322000000d314000028140c880583f18848ce73c5c40114800c838e566e4c9a8883510e842808830c52c6106380012023002355a509c6b5091883e808433be56abdf69e4039ebaa9d4e09a89fb4a60f19214f7947c176ec0863a1f1a8a45974f7d9ee137398689ddfed50fe3da34a5cd99556392b86c11908fa350447de7e67a29aed00c92a04974e516d3ef96947a0521d3c1ec757da9c22ccca1a2480bddfbeb2e470a825660df2799ae627f979779a3d54042960602986d4c39443ea1c2e9902a099703c427806fd51270ad27c62cd9d0fb23048abedef36b1697af5303d8cbd6979f4e402156388160f936f828aa58601b67e46f47c105ccfc2b6195c768275361e95d23c4b96b67c256ca2229ae5001c282b97a28d64ced6c9ec20611c3dbb9362150b0cff9bd6156b810b90421dde544a62b4536723054fff2c8ead12d3b61e2984b71190a968e427c9e4e6d33139a73bd1a737e5780dfb4f3f2f2d0abf65f355c4abe4464daa32aaab8826a89ec29117805af2a6e5c4dc8a97a486ec1a79847497101bc50b3ca417a68f6bc580e83dc371a2b600a64819eb672843b9912f661d4a8eb6b6b16df6919e8eb3f308a894ffc40bf64f262bca56d69453f6477e3da59530080ffd71b0e85dab72a8f3a26579d47cd1e29458d4da6b5b2d58ad8793cd4950e3554b25a8f14aeb2eb1a86d9aa777395a6f303691a0c66b2d4a508bbcd95a52270f5d5bdd90ac18496abe68794a2c6a4d33e55dd4f41e91960435f09dad25752c942e0df4bbb33a4a4d65befba067a83705c5558efacb68bada1158e3f6aba37de437da2059324e2899715facab132c9d2938a4affe29db2b04771411635f9520c0379f6eeb71a3a8e6f20d43e33be707dfe7c70f7e564043cd607d998338a057a8379981668e2caf52ee8ba5298411039a1fc2a1294b9a37fd201a2c371ee84500a286e4871bb431014d1c0bd7f7835d61caa85c06f9945a5458074664b9ca71a4954e28eb4388ca1bf9d6cc6b23bb1cd8ee56c0713000629ac76b3270920af5bcaf6727df15f81f77a031c4ddc87627769e2fcca217b59db7dfbc4748ca06641d041f193d5ed4634677099ff9cacc2e1d9a6bd0f41044a89cc14e0c27a7b2e78e5c5b2e2df81d4740cbe21c467586088e74d8ce12d95ae56d7712e23824299eee9c8ceb8b57b272bee861f29a92642fcac065f0c7864100547151a1f83915bb4023b5c3d4814a7b3c2066105df6ada65013423d6191f79af18c1523bc42976f3dc319bacf93339c30179a73119adfe3843cce689d1cf46ed6d6fc28d24cd1b0feb41d8263c3d9c211d45fd8877701fe38d726acb429f9279f678c323e860bc56639aceebb898754c7c8a5f42a68213c2cad9a270b85e002cef50cdcf94b8b423053f12868eaa0d443c0cc4aa904d8fd610a2fdc0a42a065f539d8dd88f990708439fdbf19f95bd7fe0c0bfb36ce912d3066fd3a5c78e873a10c62bc2f09e7733406c1b03e5fa111dbffa6235cdf0074619276d5ef00091cc17adc174d343c6a438fee96d7eb723eb296113174c4c064925e509235d6cf1d8d2d40c68bbb246b44ba2122ba570982b2a64b13251ad99f1aa1713486b8293d3ffcc812d1202f9e599b0825eec8d1b82fa991338393d4095394d8299853df180e5d0e4ea02c34785fc810514e7a4bfef4488ce33c017af1b973dd4a9ca6457d4a5b588d80591d7bf8296ae69ce869ac471680dc0ca394d3e451c6009b59aad6d1917c8e92f44668b93276de23d368f41ed279d8b5bc673ecd34e601ce02e4b598058837083b4c8b98872a839066553a33b73548ad4d905fa7767b725075908551485718009c0bce2394abf1d75ea029b6acd478e362946218dc0411c6d8576b66a23b09ceb1c4910f32dfa31b9bc4bd80b922d5638720a234347726e9deb6e90ed23a43ee0272525002ed278c2b01512cd8ac5335bc5f1aaa6dc86e957882254e42bb55c24b8126d989f7dbfe8498bbf092d8064045371a7917a686094bf8562adc03f53b21e9f6fb54e4518064ba978881a90e661b3ec64ce023547973ae46ee7f1cb9ff1421895e6dc8dbd13af4394a458c80cfa553acb7a3786380146f89af3ae211e7fae2d6f23130b7c7d1a5b73caf57a3095141c57a750ee4fa9f229b98f1e069176556baaf0a3f4091136b5378ba19bd259426b08b826902c5ed35d6b6df64b5c17d4283eb474ed363dcdd27fff8b229b3fbb3c5ef641e20a64840587e40889833ee8a60d7f6615e59798c487ceb86c59a286723ec4789a82e193683fd50bd3b1c2eb413198a433dc06deae7bec7278525d51aaced8af4e130bfb13bcbab1b2b29c75bb32b3b15db4a879d0c977f3fea482e288e75b0d46c9cf8311d47695260529ae321e6d8fc586772b2eb9640a6e8627af0eef837ef9dd1ec8c0dd342658bc36404976ed9f82433f460f48794c483cac50b70e8ee29ad2d98fd8c85dcefed2cf88f9184d482c1936d6139408b1d14eb43fb194b6da275ab5394829329cf5ab66ec4f700927f8b572957279738ef92336ab65898adddcc6b68269882974c8d064b59bbcdb50c730511ce915b6ff7c2e35d6bf76ad63ac71d6458b5696117c43261a89e013017f2c35d96f9511e299b2eb186c34bb09f8f5a7aae8178e1107557bf5959ea5e3fa435aec6982be19becacd97b3b08adbb50e389d51cf87eabd8e6fdac5834ef451773e7813a24c45c029796ecb778ba42b8f53d1b1c46ef011ca00c61ddad70edae6f5c70f1ac80a4b33fb8f7fd3c6c838386f0402f7b21e1f0f73bbcc14ffd83bce9e5f45114a35a10c5a891473162a5e332c3e6b7fd4fdc3d3f7b34ff9ce502893e1175568bd80358231bf6cb5429620b715ff8ddc2554a7d3a5fb9da886b0636ce6472dd1d0df66664fd59cb699d7011ae071e47a8c670c5882efed4b4db230eece78b6f8ed2c4dd357bb12849d97825714f881e0c1c080d3a76b8f8c28f0540b29d592fd0e3c7e17d9bbf1d40acf1bef1f1cb78205d46f9fdf192b4829efe5ea3fdf7f7518e7f2b9e2c0d712fdc4bdf97cde4ae3e64e6988c8999e20b17cca453849808d48dcc55eefeeaa60d02261caccbedd1ee0214c1ce39190383a17f7b3970ff8d11bf5ca8b683cd2beb25f7e53d00d6849ce6bbdcd98c77cf35902931a3023ebd7f79b79067853940b2d382ba292371f31abb961d1ee41588ff276053abdff8f417f5d85eb6d49ebb26e38d500046eb9a44a86bc08972d6ad305b4b23ab1eac79ff11256f47f19a72542fcc2ca1c717a00474753623da681fc0f4299e7a3ab85c553bc58d1d93df095a379dbb2550ae3808d792b536b6fe54c2849e6972f809d8db7bca50f2de093990a362c0e3dbc6bfadb6b11b09aab8d3a6a8e91f187bb880ae838d1a7de5edc264b1e70260dbf6987ddac91df83b88bc205c01ad1ded4baf06f168056b4b1f0a8466ded8d3812b8481305684714a8a910966cea9c2a7ff2432ea63ca136646002b8b955bbc4518523a05ef0da4e91e3e7870c4e3d36753e73f4dcaf5b167ea1fc7ef956f880fe8eba7b56ac5a0e10fb0e58223739ebc8f51ea6f85fcf6f7f50213a57e2bc83f7eae7f6051557ff34a46a9583765414b5ed5fde3e3167bc53fd75be093b53bb6a9945b1e004e379aae9f7a0a166ec498857a32a6a97201c373e21605e6e9a4a279f9630b73d30f29590e9ed422391afbf437a4ee3f746d97a066ece0a05c8908e0dc889d81f833fb84da2fd261227de20351ff1d44872487ec6e62d799f5ea36f0e5f3264635a0c061eb7318890793eb7f4c447af13bcc581597bfb8b612b71b09f99e498ac2813faf7d5c02ad045dbcf6e41ec8c94063d6f20d7cd6cc83d825deac77895661fba346f7a7ecf2e484087274ae02793567c21fdcccd70bee87ad95d7bf864f79a2d0858cee5ee5a43f5c3f9060e20582b66a06c514a99a4d06b20d332aa23a3cba697aeba4ae09bed113e5ef674068bebc219911c03afc2954e731d80dbcb5b71df90c63c3311161d1792ca2d71ad82ef44362f915cbfa3535d4d22fa800ca6dfb73d9b9a445fdcb7e3eaaae7d314807cc1d4db8a5f2a5f67ec0b64069637c24a630a15a1c36ea4056dcd2c6d965d5561b896196066c73fe596ede361a83ed444748064c50c88d680633ec18bb77e125e85b225d57ef06b9599e201a677bdcd3dd2ad52d3a402ce687d5f830383dec0e0f33b3c3d43a4a3725a353977870652864b4abb6feaff8bbf4990cb7b6d134364b25ef05cd2d5cbbf4f52da459d54c873f1c4cc31560ad74878624ac4ab6b13fb4c6feb1f57a57f3436c711bbabd0e2ce16d80f6fe0c05c8300b235f662297dc64c190aed5e75df8908c06f29d762f37b0a960af6629a74f34bc0241b05142018fdf2067d0c22cc32027155c29c6b811d9299ea46496a7ff80b3a8d1c59b3da012c248644f0404ba113a4d6f00d6464b6e6a750fd59c997406f219c034a3f1fde0dcae27d3bb4fc7df40d3dfd9e25311bf10bbc6ff0b8ba146cdb481dc423e30944640e753379d3c961c265cb170bff558df71199c0be9c1b00314a8867ad673756d455ced5ca0d43435ece554b6aa2159f0a64fcf4606028890ab97e830035ffc08f9a11cc96be9d3cd06b83ea50e7dad4ab579d303f180d33ea209c9ed4c99b243de615fd44079b10d871b883436fee4141c90293044657ec9ee8261515931f15d47f1a28afe2766a321814038b130992b486a2779c970d12dd3bdfdd84e5a20c9917d0aa4cf14437810fb2b9097b438ccbc66276fd93723f7993e65cf0a1e5f9dcc07a8cf03535c6c8e5a860f6e2881875a2d9b82dd300ddc472cef82a1b4df29a8657c56b4d09f790200315a9a8a43e2904df5c207690ad76c50b441188f4c923c92fa0401aa5a835c0f1f9f58b139a2e79c41680815f00f6a913a86f90b6f40633aa4c08f4e92df40b942281ac916e7eba072fbe2231b23ba98bc3087b4a2c121e27fdd469e630e11ff165db288afe89d2d210347c63e6e3491636796e8e4ebe7410731f1651df68af2d96e356f39437cecf9f3174141f1aac1394ad7b3b2dd6a5020cb9088517a9c40549e8ec1a9276650b69a4e60bbd60f89e4efa8e99f4a54b2ba114d19115cbbd4921adf6c85df873ff9d762f14f55035e6c7f9daae73a58fdbe5175a0ff93c4eea0859cd8c7991509e92a5fa9ef67ca4ed94ae40f02e334e092a05310f77e32bc74a4ba868f7b857d29889e0403139be1024d6801ad2f48f5568bdff8fd377ff31bbffd86c61e0eb226161665d2011b10e99cf54cae5dbcef38a4b5c18097109a4368526406c05e4f26ba5299affcf98048c7b2dbab79ed26c40db68d8a76822a8d9b7a17a853ee46d7f3b193304fb30dc53e9aa11464a8b990d01c51a2c9710a37dd9455c584cb5d25dc16b86bbcdf5f780f220658ece930fb1870137242db940fb414ec17247fd49f53e04072f2d30f5c5f39cad389febdd3b164b552fedf5717f1d62763eddeb7dde8bb7f593aca8f131126992277d79107d4299cc438226b8278af105dd2e11940c9931841e09d4b606d93912120b28aaa1c14ebdafc5cd110946d623df0337b2cb05ba7784bd7c9f336100d428b271f2a55f857837afafdab715a1659cf6610425115cff7976546f28e682069603f972068829b6609887edcd17ec14898c3a59db4e2c0f90f9d75fcd128785e82d8e975f1407bbefad9dc8ebb6aaa6c75a81e83c5d92d323cfcc34f0c6b0255f8d4e2fd120acccdfd37f0fa4b4025275a30ea9ad97087b404a4515f750392760bf031d8fdef71393b775e59cdeb64d241699d564ce53e2f0afbdefedb9d18036cb9134fe0bd39a56b0ba2aed26494a7f514572fe112977b41e9c3a224d79e3db20a044af557471d602cb97cfb074a6d22822d5de5755c20d066c65d1a15cc28f3dc4864caa32342ae5bba60a08d4b08342e1347927f16ddb6fd19547445cc2b1a7771c15e11948b53d787f3fb96f2da480b52281015df001f4079fea6928e6a7b7232271636cd5618ab342b1787efb324cb9a52a6af388f4a7d060803c61b7033ca2d7f8b7702096348aa2e9f9c37c11f131790307e34d1c34b9cccbcbc32c982dc7957e1a0da009463441f06ad259461c07a62f4b328f9c218ea7ecbddbc88a5f4c485928a4bd49d7add7c62f0f32d48c3eb97f5e61e398574a8704b0ccc835eff3e161989bcef9a6b19bdbdaa9043fabdfdf52e6c547bfd5442562fdf03085f952ecff61d345ce54278416328a8d4ef93fa81fe6284402d539502f45d80ebfc6d00d185b0a4d23aef1575d3d1af41bb9b3d9c8c4e160ed17042ede1264b8d4ca42249f8fc8c32a89662a47d2ffa25dec85daa27a8f65dd18d28b22971f1b1f1fab3df661e1b5ca2cf1c4664a39565d6683070c7d7eb951c36aae325e438f44fa77aac69f52354d8d9074b3858c5f621d5d2a485f674e419b2e13a6ef9addf1af5196c0e3d6d466bf73d4615a45c095780bcc1f78b2365f914064f31c9a4a3c6314dde8673fc32d0c4577d09d140cba7d17c551a550b7b3688e9b148e40741352dbbc9186c43f3466afc13c3cc093680557773160427c9a12f01d3439fd9389df1918936eea872845169b7e21ab294fe7540dd7a2c02cd499c3d9e80e97f54e4d2591567ba47d286f11ad7e6d5f2072aa3ae05fd31fa3c029d8553b21dbbd6469278955aaeee949d1a7a5b101bd188d491164f0fffc66052e309d0dcbbaac840c1849122e9728f0c3aa24d3fefce1a6593748451a39229aaf011d8cb04bac454838f6d3fe6fa1b9309a0d3e0c508de8e532511a07bca08081471ffc8506bd46525e8d971503c87785e64a4ce599dbf9df5afc41c15bf7099f88962814fdb15505cd25d8aa465d311c2eced24cbd5d189c5570f9241644619e71c65a79e7f9f1f27c3bacac573ba57378885654962e07f648a4d541f5875c2655eb10a548561d8b728e831e7f1702e1e2a0d770233281d73f1bf841fbd23fcc18d80903da434ec423859af293f2d5f4b49d0283fd54dab98a666b2ed7aa860293f6ee4764a9a1ca8577940862275d9f80740d707b8b8f7c883bc14f6644a8af262d30b719dc1bd498aa87405f8c1727488f92f4c1d91c96fd71e937dc008b296a6eecd0076d84a00c4bccb2459c241cb3cb73073b22d09bbc7f7e630a2768e827b59b7d901ee6006aace6093c2d87402143b00297d8cd8e78a2e1ccdeb32cd67ae65b927d33993a586502084efcfb094b5cc41ad23f72f48931dd982dbb7b36b99ec18c28ad77ffedcca962b23ee55d622d95be951d23b63e0a6e0986b3860b71b26ba0d9e1421a0d893034c4298bd4778846b176210aaa8e1e550dda396c164c80426b40eadc37c4c300c50417059c4675b194290acec667e29829038606003f3cfc89c51028f4782d142b8c6a72d00ee673c0bd424a6bd64a157307450a51c7d8e3159f242ef9f6f244d8effe192b107537d47ac45efa545421733be2d49133f6798acc3e69540fe4ee98ca6e69b2ae84d1381e8e62a70617044be3031fc2596cb69023efc11a02b14acea3b391a9392ebc37067a646c1eab16dff6d9598bb43d0bd28e2bd2dba4dd21bbc67ef3f55988503dfbfd91d3ae8850174d761a342ef31b46c723b12ecca0e3a0fe010d96cef893dfe8a6a173594213e6741d56a4e17a00c7a862f341fbdde83b7168e59910899c77440954ad3ca1c7f09616f0f42fa5a8e346984b887e230b02dc04d7e918da40743a0a6f634984ba4750b1a8d3311a6ddd3676b96e9a04f1595a83869ac8fb8eae58302e16c04990069be398cebbf2233f93e816a5dd7e13edecadaf64ae9032a26dc8a616854a66fc4accdc8f68d081f80e86f1c6d75f6750baf7aedebbaecfe63c7e0805ef9b25b35cae4c8faf802c2cb4493fb23daba0498fccb0e4c553b9cd92fa3a1eeb0c4d1c8f60ae62f88fe946a82ad9b485e0bc78245091b33daadea01cfc2370f3f744d55d63c6944cc81942a72b3485834d450e7678d3187899a16d6f409352a8993f206f4aa63dd2fc14042a1b61f5a7feec19b982378c131bb07a3bed08449171e657868fe577557602ee38dec8fafd571363f2394eb21aba0c823bfc4acf0c426fc85446af0861897208c66deee4626f191a704da503dc3343e201668acc539683549516047c96c9deb4ca58c6ceee39af0e2eee0088e37989a1caa3141b2977f4115d3b5f463a62624a1749b7072a1c2ffc600a0ce2974f4005e658107d4cdc2e44943bd2e20b31203620668110bc726a8521c20ae7587bc8dbfeb7e21ca488800804d7301924fdc2ab26c412d38234bf213b2b2377cea36be867d210a707aad4e0e040ec1ac80fd002d12ade423ec96adca27e82e58894fc03d5b539fa0bbb0d69fe0bb8e6b8ed8bd35fb402b9e9087ffbbdf26ee8aca0fa4bc09c68f8764d17c2a03e4faa296d22989cabe5271b5e486e8ee1d7185110db25242f7bd0cbe8fa68ad068204ae1cab341ac54a02656c22f09bc79845568b1c7d7b026d51b65f352f0eff6af00bb2952cbe10fb77569bcb36f09074423437cecf94fda7a1fa4b1f490c33470ba4eabd4ac6c7302024f2fd4a3a29f6b3ffa3a8d4cd8a3f319a3a3a24ac1a8eb3a4fcadef9a61b7f3d7359a9d6443ddbc72c5ac7fe34e4b77f79336db05e8a3513a358c273539e9e5f09397f1c2b6716f971344aa8b56bcd4c7eedb858df8f32afa8d9558404b41b3ce59f50209286da7568bc4807d028cc247cc441f75e20d4c482c8bf98f08f29ac4f84b03efc19157d350fd610ee1836b12b440d77454b5b30258b8be0a855a5163400fd6019c15bbdb63c08b05717f71069d069832ae6d850dd32fb0fcae5cb37aed9db1c8caca342156b1df0e4190e90db3ff0443fb2d748d1be88b887cabb9847df018ab4cc04fd6ab858504a663abd7f7251427a0c742c7c068e242674500b2b3a1462c3dfe40d12744a13ac0f38ab3c4e4ccc0d7a7423d835f1b9ac984834d36222b178928f7efdcbbec09270a00f3b477a9f16c417ec44a4154cb17f0cd3b4d61d3cf86db045d96121d421aefdc58651111374005c69548a629ceb0a2dd0ac1dd0498444648e852d4496b35f7226504fee37c10c784a26583e6a94fac084d25bd334a76bcedee91eae26e29a8064ad99015721d9120bf05f4e59e2ca5b7c5d0b8ec385c83e6095c998f8c685234452a430c94e92e1d9f2ab502547e91e9261c11289310c24f5366a39adc9e3b6c27b58973388f818932d552f9b7474131ced441a4f3336ba62910e9f1517d8c05d24118d341a803255356182b9a84ba65b7bb9185cc03ca9942717b144c5b669d72a56ed67561ff39ab8e2fa87ddeaae46f063bef663143a8367d4b555d2e3b157f030ad4b67e558e313555bc38dae83d37e8d5e46f77a897516d4c1d3dfea26a3baccba491e0df0415fa3ab2b4d768bea945589ea92ad8eb2062957963a68393a24a35baf50feb7cc9df8045c714b1941ccafc0acdb9cd1e9ab2500988f97186683cd98080204f034645618df47f609cc4d1c744324b1a9b0c9fd012fd1dd04339a1d3f03880d2ebc8c924a0273f88e3553f56e766c7c7f823afe0be4e47f590c6e90e4bffba0e806fd83ab72cf0c1694766645fdef3d8f893311590614142bb7f7241f68a5a1144c4937efd1cbdd20acc6d262070b6ca3c2c09777f2ef8594ed18fc586ffc14ac245a067f4e2bb058b128d38412e08e5b0933a8b54cdfda9373749279d180f93a24b4e4108a8e46d99d2147311dab7aeeeee27c8fe2b59cc0ba8fa2420a5952d9e7f08304cc3de6f6caf6d6fd3550a2b43130e38eb906171d84081ebcf513d6d991419d99cce6997ab6cf28ba62229f2fbd0da8e3a4d873c455eb2fc46e70d2b61f76d0fb9c8695c662e22a29b8da250212216c2be263fa8f25adb2970af49d0d3053f46c0bd73beea4e957814cd3134dcbe8fd7330890dc3336c113c2bad9576f71c97941a944a2e5b6d294c211ac1d266dbadcdc2f26f9d46d1549e9ebdb42adfb19f147d75a11b884ef331f36eb38591a77a2e8c556422d42556dae8acdc855333f3f6ebaaf5f3386e3f61b056fdcd9c0695327c892e354984179d8114484315704896b8677690218582d8c821f2e499f26a5cc9b41901230d314e5be9d7c614e182dbd47fa7845dd518b27a373b3a57ee33789db44fe4e15a4ef7481a740dfc50fe2b5519cc6556ac147b96ebaaafc3e12e7c0c7cde10030392efb7bd65f783a969e24031761fd15caab6e409027d43fb0e2ad0c1ba345a3e1a430916b9ec8e9a3b23699ad96d5fe658606f9d924412b6f26638921a3551cdd561db88a9d8418efb295ca50700d809af427f785f2e86dda1ac929d924c9cbef34726ef5615a919eea9ee7a9882f50ebeb347db0149c8185ca0f989061dbc46dd354f0dbe637e2a88e3682f8e528bc23aac11fd812877443366c700b558a46c7c7e7d949b15a98f773a4da65bdeda7a521d8f452c423a26cda31476b1e7c05a3d51a3b60a18ae95ae9eb6cbe883de96a45e82d4e3a837ad4f3c969437f5805a90bc25e6a697651a7967d53371551e3a4d0747cf33272ee15a7416aad60a3f0cbffe079057ae411a9c19a157a18583614bc9e9f27d25bc31ce3cd1bcfd33254ea2c97878752442465ae2ff800008d7e5d860c90f22a7bb347d06e01c9f6130f1a95a87a7af30f1f52f04f7b3160e1d89e5e023445167c108f044a0372746c05b9b6244fb1c0350807af37e8a407b4606014204e33f8998ac0a2e571ab73671642b283c26874d6875a8986cadb0948f69a9856330e7c9032a8d3d6c8fcb7b741477fa1457ffe262aefb7c16e01e7b01d140262ac8428386cb1052786511be6d8f94982db13929a1eb2547f9c35f8d9afac85ce05b3869ad3be2bc6b2527ec08eea080b29617a04f23390320156eb911d8980a5098c7822ece3a61f54ae156b8da351c8375b7b6219f7e4d77b2d77d7ab4b8c612ae6eeb4f4e4e5456d546048781e4ad2eb5f408899b202a7d4457df918e8e2b1ca675166bf7c61df9e1f178f4069eeb26f0c302067e214b18dee76d44e314a16a65e52ab9d2369adb396bc9207d29dfa94527aa86b9a5d5e10b05e02b2e28247eefff51e143461ec370d18538139c1530ba3ee73cecbfd8e158504537ee481ed5f0dff1e7c47d76e4640b2d100c88f401841d059737789b950140281ccedc2d9a81715d1c8005f63534eeddd86abf9e70d398c648e83e986a042dffd1d9d6081448e5ce5cd19aa415ff18ed47fcc1cb349eb1a0741e29ba10497c2b5aacf043405f029abed7d423e7f17b709e5d436971b9ba2e604ab8ffcb386c069c2600e07e615f06b6ebf5dd1fdc051376855dd0a4a715c4413abcde0bd392e1c745d8a06e10dd356a4cd6c2e1fe4fa2383862a82419875f24ef36f16836810727754cc395ac8715af0a81b938e7ab947a477316701fc85e0e04009343d0cb65309eec19a91f60d9f68c3fc56110fccdd69dd1499f1cadb2f2f9efe5018c70501c75f2643aff0260430dbb30f3ec8a548885e006a095d1038a25680f50404f5804e2a75ed6259878b85fb8eaa06a3fdce0468698994aeaa84e696d4c2e91a915df33e659815ec4d0b6699b9796993c399ec0f0e25efd35bbf3da9fe96a099bb5fa5cf1e02fcffc1e94aa6d9f36d8544a42981ba05e777327bedb3dc2db517fe20e13e7f0e517b8269cfa9bcbe35f7540af61b76d8ee3dad4f22bdefb9dbcc8ba06e37b9588a396c800b59443efdcbda358b0294ca9dd7cbc7016c29be8162b34a5161c48b60927e667a261e1e1902f86a1f1d6e21ae169da84f840b5ffdde99891db84827ae5565cbf21130da01ec327e8bb03b32651c0fdc3b685d8988751b5ac3c63babfb3b37e130490979ac5a086de199b2b609a572b8932d91ae559ebb826021ce987b9a95c2c7695c2b83ecb4d3e00502062300015a0200e95672e59d3fa9edbed4e7c8e594847645771238cddc4a5cabcc10d58b611a9ee21921d1a51f6417128dc98116a2da94284a36e5c55d463dd2c929977792e88e17e9a282a8012c9e5542efde55b8091457e58e9a2ab875114398029fc05a8abd6b5b6d924a38c5d776bc6b3b97917181e35e10f293e9936de4d0d5d23244913a684df9d6d1a32c828c510a9b7aa0f9b1116afe47f624b973c716f9f851660e7fea1a70ca807815b4755654dd4d7a3ab7aa38e53f71deb0c3c7e471de0886fd12e15a7d5f84498b57618a84ddc2cbbaebcadc93fcee8b37820a39e1b5311dd93f26e5262540c34bc88506109fdc6935ae67aac148645fa349e33bf744d80a9c82812ef57ecf9fd40a258a0d5f2d1472151d87482d7eac3c4a1d8082d5bcc4d6588ce5aa7cf1c4f46ffda70338ee179ecb7b4f5e949a098ef505ab54f9dca2a102ffcdda4ab65c9904fbedc49038dc6a556271abcac910f84230b58e31fdcc9f17d21494c4ee395808e202854475584ff8e4068ffada7e1250fc09e13f9402364426ecec708d8f81808ee2673340caa1a5c30b207e5e3a360b0ff4f6cffc8f708213503fd8c1d968218e78c0c91c24a63da829b0d3972ff6cadb0970ddc100c7a4a86c749aefb01be5aa7897cb8417f2362ff388330fd40b7dd010edb12b1996291b38a13dba5cf686fe5d9a8c9c4141c321e67c8d0b36c76d4abf2986aea0e229e1fed62f5db8e17ed7435046ce3eb30d5e0404008838d15d5d11f3fc1a0665f39bc15d963e415e8d8c54a1b4120433b89326d1fc56656f9501a066edba17e4e0d94468ac04687ba6bedffe9f4bd0b5fae36c58c59a420ea6460163e4bd9df6814387c4c8bd75c2b593e0992dacf978d54c3976c5a0ef73e88c3b1b47776459375e7a60d51933b14129aafc14af73de38c7e52fa9cccae415bea72e11fe5f46a86152fc4508c815a3f999a111ddbb1c636609527a5beb70b4ca505a0ef2e0f3e7a04502671c34130f10b9f8fdaf5876b1d31c6a7a62b1927f38f924cb233bb91bc0b87d1b8199b37e3412f9dde224ed5c8ca8d4eccf4511b93c8565b2c4f15d61693848047c8eafc5ac8e6d223b89c144ad3837e7ab1544382029519a17d8e11b45a4df453ef2b68c4ff51894303ec177c47bc721d308643102d72b533525a122b965f90c23dbec6dea4782e6ab2249ccbec88626960e4b211e53735cf7e9c66ee619dede62dc3ba5fdac84c75c2740e7fe014fe5407debfa294d8a5ac09da31be907d6f44b3a267acb6f73dc4d33a88c0c6fea4b35eec8cc534db228bf17831e80093299638b89eb68d85b53f59b577d0c0944962516a4c43e0a9a3e887ce5d5aee32ab67e5cde32ec095d8920aad1688729286c5686b96717833e74c2d503dc3e8a426541332de94ce5440df925793829b3be5a6971aa4fa304be9328b33864396efb658d06163216e0b924415c3e654eff28f8a590dea8ddca24a6fce4bab3fc1a76ba75e6286f78f8ba50659725d884ff5dd2c1b2954940b647de9d8555abb04686482319815dc1e55124ef32c95ec1f72ba9073c7d51972a50b5eda8ec1affd63b45a6a8d066fd9f2cdd2207f9883296b6860fa5fb06c37a67250cdfc2510372f779d0e44bd238f3b26dd786c21318ff00851acf32ec14b4d3620e9d1df4c0ccfeedbf7c0275ac9cb24ccb49b9ff7c86ad15148fd72535cb75cdc9cbd016f59c40966da55ce4273e6bf804c49a8fc48536f8c67341f4a6d01b14fafb60fe84db6ceb405470debc56cee0673cc4855b01dbc32b9e7303dc35de689aef2e8eac8dda7d296f7326808e3cc944ed4e62e1554e1a6b811350b91ad9de0e7001be05254e871803ac74563bc8c9b7b02673e0b13586e89a11d596b376102f5c8f98798f532d28611314ea886c76948a264afea9449fa3d44dd6af72df901327c84cc477d006eef5b7d826ee7ab3fc34edb66c50fc34538d5bb8a5ef0c1737032c227fd6a270a9af19d01f3b6b48c7c74e69928ec6ec4577f046eef53ff03510f42eb233f01b7f7a5ff80187c08dd977c826ec4477c066eef5b7d82f814c9378e30afa2acdc452f835ca0c41814dd8979202d0e6269809878b48bfcb8c5497ce4336c55fb4f509594f46ca6d0a35bc4184cb42ba371d712eb614b96a01cbd0aae783d29fe203d145c4583f6e6ac1b202eaea07265264eb85550d4cfce344809ca0df8f3757bf2697f4cc458ce9d524959bd471935e55bba38d017d3d3242edc63275f646d5f62fc6b9e7231265ad300aeb15a23eb5c142ce1504cd07f3c4d599d7806e38363df96c7083e81b3548d59093d16449e05bcc0cd587cee1f94b0f435104d04f44ed443040d59345ce21b61612d5e7719161cb7bc4a3b30e68164ec6b61b1a7f889279562e1d9ed9e83d74a43e860e380ae5be3c7fb5029d0fe4df97728401bff1ca050d4108075bbe5f9d85537d05f98e832c3c683f4952a3b2abda717b8aa8a1fb362595997663f74f2fecc1861e4b1ac8d4694a834d1db70190c37f8f37b67122d2d027fd18940caf3d8ebff7fe564435cd9748cb713fde09c33a1ee04179eb3164bce1ab3426e518afbc9fcd89caf6b083080cc54b48f9687d74234c7503bfee3cbefa415c43aa38893a30ce40acbc4f5782c63f747727e9a277cdb6d40c8c3828c3457cb8019845baae6548e3193391f8b12e4358b3c3447f7786266d9132145ecb2fb357ac39e6cb94fa0020ea54b57bda28230407f8dadd2e87d9752da61eb8f6d51deb188d2c0a91a63507e7c14260ce088f94d4c239a721242cbd5198713298a3595435d592a20b8f04211f9937644ffc5c88ab1a9fe32c7c5e3f3cdfc44fdc0662c54d3aaa799facfd823d14c981bba1820b27873dc4f08b73d8f566e48728f7fd8181d17f25f288be31c78c4e66eb18f745dbc011d1e41c1b6aa624c7065624d116ac3a4f128e8fe56fec1ed52928654edd5aeaa22f2cacb534df39dc5de000909de7293ef1aa1f6fb1b97c8763830cff2acaf09e2109dd546ddb8c6578eae49af51326d1293526bd65c5b90173f873191cdd07eb77f324db795bf5845ee0f2e9ada0f594e74b46b5f4128d5a94842f50c2486ce8de0b470afc5cc7b2602b3755b37ceefd1e02cd986725dc8d788f56a3c6f4ff90a5861d2019641031388534113d96fe6880fc4c92bfddccd100973088bbccb22eebcc9b73161ee9ef059e7a64a28a3e56b456e4626ab202a4a3991d31dccea6e23bb8b4f79e9819dddf35257de44a9b1c5d2547459507ab64bb1df6bbe48fb58dc1089abe687f04ccc950c69018bef8d19232af224201f6f75345bd7471ef44bc37cfca5be57c2e0563841a68d1cdccb017bdbd4964e81a77b911b305fd5e51e718dca0cfa63ab6077a487c7350079617c5551c24e2f1e75b5326b1899f960a86a6d398b92ccc119f326c2164103afa92af44da78aa436add1920cd900ea14e995a9f23fb4807c0a547b1f8db9b878563438deeaddedc0c48f96f2f3635254d29fe17cd000668384dab7d345222255600873eb3f33c881bdab8c1ba82880426568c1f781f500d98cdf90b838ef2d8ad02de5ae895b112f817930e22556b97365d3d281a4d9b6b00a394f558c60d567faf1f42a9bbd57fd759c4110c73c68eabed3c8bc5804ae7d87907bc072f9dd4bbf006c9f376803531141d30666e74fd7affbf7cb7d0f51627efde8939976f6f56077338c8fb3c8d7c32651e70b6d43793afa78f34ed3f6b2adbbede52d9e543bece4c241cd709bac3abb231ab905443b770928c2bfcc7352d60135268a198ebd361edf092c2337d23d9e332644abd44048b3728598ecae0a94e0dfb6891f515d5abdacd24d9c907ffeccf5872594ad205293e2077b64fbc001ded2797d69e7277c3f88896a4cd6fd53c363969cc0199cbd109bd19c52bed6e0c4967388bccbc122f51a7816ada448be253615afe8a0b3dac712bff3835721c8bd525def8db0370bf8f18de998ed04fd6bd1e81ef00245c164b519b37cd506895df32c151cd914299b67c9f93b896ca5c17ad4352cbac98e7dc6e66eb8f723de159a19333e978d9fc0b9cbca3c6dc586f09e4c5e2ea38da3bb17726a5ddace23493d178807441a75fb9d6ae749de88f1d611ed36b39688ce95e9665ee9fea244ba6801fc1e15ff7349ccd3987e3e3c33dcb6b0fc911a8acdf8054273e1d0532321242695e469a52f1719baf571bbe65330aefc320d2a82dfcc4287caedddb1e95aabc746452faa3bb9e31db2e9d0664e639b2a1eb31add7872f5ea057a64c36aa2c1a9969b25817cb00655c134519fc06900b4c0e243bf72dca5798e46a41d4e56b6ff0524be913bb298f4514bc624cf5358771e5bb2cebc365a1cb9242a3618c79d6293773dd74fc590caaecb23503d420523cd79dcefa789b33f62e28afd70d07f787f98184b5ea2b2eefcc9d7292de6ac9b3ab227b1f553752d33534528e5c618adcd1e40c8d5160a96ee22f61875753aa53c4b7448840ed94700cf4a9caac8e6350028faaa896e081918cdebd1c690cf22932b57066c20820777947e9f0ae764502cbc8b79f62b236e0159c014e817c1155c0e85bc49a9f7b7be3ba3c497062b2ea49d158e7eb1be4896e03b17d0da367332a860e21db0c063a719b340d60f9b173612a5d186f3be1a39f5da73c9268ff49d3c46eb8e6a7a835f03965c587f35bd74aa11be9eebcb247a2904841472cd0f162b6b19c0354b9138839a97bd82eaec42ec4abb52a907304dd98ac6a260749c1cd730f57d25047dd84614cf6cbbe6f7815a762041ad682d33a15ac6c6c61e6be52a31e436ed32ff2e4f9da1f86d4a1fbd2fe00b2ada0205c6c6a0208e5122f05aa5041debf99bd11d76815025abdec39eb78d39a3e20630f00a7a5439048bcf9fcb307715c424ab4909bf9569ca749bce16d616a7bb63646de35f0dd8659a86ed55d60c795860805b5b6d54bae135a4eb58bca62aa9ef62cbeced59bcd040d8f7039dc49baa85c1ba8e426e265f05eedcbb9a7d5637f01fb4cb657794b0a88bd42a40d29d2da4ab41ff71221e25de87c354c2d265b3b70ce8d90ea60b4d637c6272d28ed2fbdf6d8e24750c53e6f0169bdbb0234f73e49b8a611788e43aa0bc8375a3f36d67f65cbe0418baab6e734bcf07c8347a043fe430a51a69e1e0e66995ea5261378343282e898fe6b1c28103cc80e8c23436b2cc20e90a7aed5bb05e116b654e43bd548496ef29bb3c80eee6a253180f42c0f59fabad3759cee2d4d58e5fa72d57679a5b9162955b8d616877da10ffe46038417cae2a2cbdca4406a384f449c76cca9a8efda786f697d57a7aeac8c2d2f304caf34ca218a9bcd6e36b14150e484ce372ec09126d88473b6f8ec3d688c348faeb8b2e1df045524b0a4334f14cbc8588b9c6b82c5edc37e6d8bd29c9429b70fdd5c9ffee136582902179fd4c8d85dc601acb3885bbd661a38013b53cda538665da02b9b3dc05647c5544ed375eae3e921f2f5719b13c4a64b361cfea1a28d11171e144112f3d98759abcdbb213952319323e2934300f95f530e01b4d797a58056f2893f0b76ded543d44a7dd0aba339f63afee2a8ba062530462c0b411cd50f2fef97d18c2154415e69eff2af0a75d078632736e3fba96d6d314131252b5bce055e6aea25f1d01976b643289fa94f1752d035673308a336a0749c663631b7520e9c228c5f28004da3a0777a0984f6b90fed5be4a7c50078610740c61b4de949df8f612ff7f81f4250a45fafdb46fe95a41996fc99a53425fe975c7691f72573a6566f7124034b351e60ae062377dbaf3def1b80322d153013e72bc75763ebe0a3509563e55f7f47a3731b6075c38da603ac59815ea4149f7593410e38b8289e2572773bc2f9a9b42f489af70eb9e638b616d7b878586b2267166f925e5a00920f3a4e209dbeb1d42ffa866af429aaf871d710569c20915e9f58922bacb8a5c2df72d512f4b93375e6f6aebc2c236f838cc978943e99a1ac7bcb3cb21f7ee55084b4aada5b326e429b380271fe2cc3a40578fbe12e1eca3065d0b8baa5db1460c1b3940ec9f9039cbd4812a278dac73b95d14a2ef2c2db32161a6db0e5d2a5f8aa1ee255772c99e5c3c0864e79275b0047514cb38520f7b85c25b739206e08674c40dc5ee3811a5d7d194f2456e638c4742b492661c106eb01d88f207ff0461e1a6d92621c14558ac086c3ae3ed6fd4c562d95aa9234acf3a1775089efded37988bb627b4ea46e9f73f6132a5b14bddec6c8a00410ea0d9d2ac2728f7729e6b143b63331bad12c86d424cb73e09d800188be90ad6c90bcd6d0f368adce73853536bcc6a0476b6b9817279c190a97b446f6350fead3b0b50f0821fdce3630f5ecc1b3fa5152cb3f3e9af287b1262a54a7d24749b30f120af13f6e054166290eaa80de7a4cac1c0db4525a27fea44493cc1e8f6e11e92d41031bd9e4ca8c659be5072d6d12a018ad558d8285319b3df13f939bf30a1811db2fc6e17441d80c72e0446202ffa1e08e1d0a11696854fe505f52ab143c89721accbd68db1f07714106e52b7e09b9390c89aaf878739fb53aa38a1671d008ec9cfbce42a3e93a834424b8a0edf3348a2aa9ca7a18c8b3839a5862eb9ae2a064fc95cf5ef184f2bb727f6cacd37e95676ba17ce0a9b0dfb7e1c563927459db8a84ae696295cf5ea3c28ad2b578cf0322deccddd1f91848454952e4d5cc5e75d470cf1f0fb256251779d7e25b46ee5f2c435cd8579678663aaa51b226964f7e56fbe47d50f008fe6726e47ee7ae7a18803fe05e22ab55d40c933b81a105a7283b79dd2d69b23425a928496b746b2212f3cd68947912d8c9ad5c90552681f16b946f93ff49d22ea459579b8641d9283025b5d16b97c750da9088bd3ff5bbcb653955f476509d89b9e3b6e759916a037bb3f296f2238bb04cec829858e220e1e50cbb67676cf3e93aea31aa5ff732f29338c42c958e0ec64aa6e686030d6788963a1df443288a68076028645baa3a2609e3b1846a3ed23863ec5cd0c831ab188c3d24d644b548527a03be57287acf5a85abdf62264cd43ab22473cb7d0284b6f637974bb9fd5692b1ac9437bf9ab5299b8498a8ec871ecae4462b9b023118aae0f6de24021db0b22c32879f70a381b858c3b5a4be8ad2580e38e9afbbb98e23ee7bb221b4bc860925ca7ab905efa22db645c5ac4236ca1f81a8ce71dc484784090059f1cfdaa1ba0be1470fa366d9336f90b19c60b7a783ce40e28759200f5c570982225fc660345df63d78509ac0912b16fe360ad52c17e859ff102d088d205eea201b8adf8f1471cfd768e6cd85b7afa63451c7fe959f7a2d126e7f132149459cfc6e07b6132394bd9ac3d3af6efd0cb9c95f653b8a99eb30c271440f3d2f5a8005fc8adf021c18aed3d7b044a5336623f5b24d04ab3b1a769c5f610e4f706b290ce45c6186a9a1272001380498b92b19987ddefaecd3da19dac10e2e4e46163070c6b4d6be70e15f36cbf995093a669363def9da42584220fab19f0036f61417790e0bc3f1471e44f0a825f7ccebd0ea3b0b93686bfd0ec2394db1d20cb0066b806c46a502ffd9e0bca02e49346f28b8b685813d06653091c9c43af03ea484af619ace4b8e1ca1b8ea0cb73bc1ea5b301520783a782123476d1d988ade45facce0e2d5f8b736e75f7e41be7455a9d24445a0f21663118531ff9f83d131c595ba8d0e189aa52a17045b75899dfbb056eb9224e29f9bb5267f8dba62290b278e246aa290f8efa034ab7ca1c3ed9939bfb9ca5d792caca6eb5a5b5b2749e595d7a90cdef08bc1f289d11b3bca364433faae74dfe558c86c49b57d9c081492dab171cc50c5b88b5101a7a907c9f50655795f0a55f7291461f5077ca0080153637e7bd5558474e9752b7f482bd4172fc7ce3bed897f974d92e5d84c0dcce4954c63fdc4e2617929ca71c8c49a1a520ac80be83604725e176c8d7c8cd5c01295447494768a3ef7c5ceec643ef5151e97d68b3a771ecf5f755adb0915b4d5dbe210fe2829a053daca06715d546dc466fd2df5adb891b16d43d18645cdbf12c3c697ae8a0451003dd7bb32b7641a6164a0373758d7ab64c1db16ec1b0904cb290f78067c9e51e34a02f4fc4024beaca7714b5400e13098fb976e51a7aa8e9ca6359cb26e86efffaa9691bd977f53e0f4b682c11a7314c6f6e228dc8f378a8d1f77940dc8920e70bdacf433d98d6d4763ea7b31172be4294c6ba89221c7bae12e9fae6cc9f05fd8cada86c750e928c3347f3f973696d08d24814c20c84778b91f68f3e71ba78810faa3402d766c6a03ad284871515e7823d22d67322c672bd4b7c99b65beb3d39578498c5f0ce0094d01ee34719652cb6b73fe62702ec0121251e06cd4ede35b2e7af26dd5dbf0f7ba715a92223f5e613a20e6f81a8a2c1c74ed7bd5c7ccfd049621cc0666ac61fbc003a35943342c45bbf6de1f0c97087a7c46bdb1edd51b4d6fdd6c3f201eb269d933a6b3d7f2fea1f889179846bb57b4479b470a47b7684e6f2d90a69ee5f20a881d84a936ef2e0868ea882ae7e5cd69d38d603ed5640bc9489a88b7811bebb7be408de7048a032dd8ddb94954d1170202dc82fbedff85aef25c49baf8e6b0789e234ab0926a97d68f2a56054a2036057d717a973d9b23b4ea8fcf32432177777a1aebbd9f17502376c87cc042a565971dfbcc12aaacf9349081831885c1d83a5a3d6476da5b27b1b167b5345b551c5994f4508c4ae394b498e046e45604912b9f1adf8553996fc0f642382b83c6e173567cb3ff05fc06d35810c6a155a96fafe02a29d31aa6803a79615df0353ab90cd94d0ee8654e5483ba66d91950208af068d20a17a130847783da02775a96f2666b805296c83ca2ae39bae333ef014074a333d88e9d03a31911ba23acc4c889dbc09e82fc4de4281da310ded9443e437514413718287863408032a27eca60e8aa77e6d1e55c36aa706879b168414b513a06951f49ccd068e8380efbf24d3536c035f95b8f50b090d425cf2525e79d4ab247e2352af52ab35ca984a37aa7be3b26812f514d0300b00b85884a300ecc7279925259409239e8db8254cddd8449fb21eebb2434b9f745a480922918b61dbeac8ad6a65aeeb72c468d3080d259cdd6a2250a620b339585c722906379680d1e70af7cabd38c6ac221de88cc7e6de51dec0679b52f00fd0ede4d8490495595498b057f4347c01578c9fe34c61019b652ee3876034011f24b774d18c26b61b1739ce5ab2696896bfca65c237172e9c42a82c873038491a70cdf639a39b6a00d8b64d8c0b8cee2e3dc5e0a62926b8f9f95237df07fe9ede5cbc17d2642ce3de8d3e4f177149578c863d7ef9c01b54f986a07f7103645da3ff8701ed1979cb22e3ebc9b88fb96d7d5446268d33478dd17e85f9d26e558b02a588ce0e47ad7b07c4a41847037748667441f4363482dd0adbc2ffbe9fa6e9b4f294e1dc7afa872278fb794d29930bb9130ed29e1f0e22e9488dd81213d140ce8ee920dcab2e1ff8c84f5b925189d1ffbaf3a56ca12e598d1c49913f7813b61b23375a6fe3c5240d81e906570d46136a2eacbbf0560bc3b4dc2d0b7cf85f95a33f43ee40bbd8957698d81516806ad08f1180c4fc7f5cea0f6846e35a71b37ab8990a793e32aa8006f069d2ef7e31fcfac1bf2a25e66ef7344506badb7070b6aff3625eefbea706f699193444e1fdaa1f85138d31ea1652c6e679797428543a77b9ae39fe43a9d59766f41e33625400889c6273764e857a3477eb177b80f3140920e8ae4da3ffd049b0f481055b18c319b7a7b145aebd6c4e655670bbc3753dd4e6c8ab9faed723eec6f2d0ee4c1757da5028d50d3ebf9b254b6cb0c8e7e7a12eabf2c7835d5abf1c0e97f16cde4c013d8dabb5fad98cb4a6062561a8ff0a0b7a410c8db14bc4f63fc8b2fc0a65dc832f29a1f26d6aee2ed877c427d942226f6f6486c59e6dff632af20069bfcf32102a6bff7af03c7a0a94aad4fedb4a6cd3d57f28cc19f79c92d471481da513a7e1870ce69cc4e02fc83709fd3b38ab73e1a0b2109e6323950a5ef1b63c40552c1c61b41b92ea3c92b9f42b23995f5196efa0d2c05d968a81ba34c336694b9f8b35dd0ea1c886e9358efdf74fc1705f284e09b4c2a31f20b0acf09c78498fb30bb8a55df76795162b6659c2809374f65407ec278c7ca39b26c3c01ab242549fc1041fe5da8ae39d66a93953247e9323840a779d48be7a5fe18a61bcb85b03c0ba5c55b6d032aebdb6c6e178da4135aa77c0e69d93ea3087c94a7efb893ab1a41de0bd7d0cb82ef0adfc05689fd26e3fbcdc22d0e00fe69fdfa0931f5ec276d96906c805fe0a80d2e49e702e977b3ea238bfc2e79d5adfe4928fda0554da83a80555d110e9f3cf39b2e3c87b6cf36a8243ba16e7693459986fd9cf0a7d7c672441bb5595b96497d6f536db5d3995eb4ba03b60ed9888be3f63acf25f67c73b1ee07f7c171176f16206223d88730dcf44f1ff60c522472e1f309d0f39d75148132e08d09aa273fde42fe36b5b3aba6bac007205fa614a6319824a013c23639e23faaf303a34c222965a61d08c5b428cf72d2e388375491f7d502810eea9b7f9a3ecab88a135854e0ab82020f188eb686d001d8ab4607540d83fc3c8b8775a118d4cd8f70517786656b28594755a57d6041fd017661fcc875e5d9fb6f6ce2c200a38c678ee111e890d5b6c9939421d7145e4708f57e1d6f8c6da4a1ca23a566614a98468a65ab7192423179d6dd03cfd20d541c81b054963a269168f425f83eea9f9329cc40aa4d29ebed8c6410c3765f3a1c2cc5b808638fc2eaf3da4b019f03327ce934b2f346fb2732e9834617977dbd9a369f34729a85a7955d1b53e940fa003b2d7498dbef5c6ee184babc358bfd44ca49d3a00fb25cbe2fbe5414c7cc9263faf87acf3b8efd71b4a4f69031d75d808db7ccd9764b5a81700e2b5f89568d85f1841f25cbbf47f1a3b385572ed7a454e8029bb98f19034b16201c6257c47d9ceab865502792c5102b3cb620f7db0da5b6ab1875fa8f7a2eaabc05883bb8867da1b35b9b4268aa24ea402c1688ebb11c7e5ea9389c297faf9eaab68775cc90c4b7fd51994471d311280a30fc9c53299e5cf10955365e9b6e16f10f37ad7849058c7d1fd8bb753c51b516c3a528083fda50f85d2b863f6f9ee072cc19438e5987ed68bf324443738f2b6a987667353622907773cf9fb9c9e0584f6b1828945542d3e54b4472c577e1681b4f7578fe95ee3e1647fb855a7d9d2e1b49ca85c889cabe12c517e3eeca674bcbf9c06b32cc8ebaa8476dfd258db2fb2c4bf4d1c0db8941fb94da9ad7d0ac58e11362cfddf451a90e9a486b64ea3a3835483aba9d837a5898ff34fc855092d58d344eb2f86b16e0ff994db2807e50f2367fefa377e8eb22532b4a47e686db896a2e129a0508eafa7c518643b25a6a18e16822415ad5290d1ff8dad1141cddea3f47d91ecdc5a1013740258b00faaa17d868f4a6da2594c78d09f8df8ba458ae82333c221711c4cbd781df24e04ede7a0a60272b8444ab448bba3ad7e3da8ea0483aa385b29572c98badd30b1c13a0d24957e56b18170dba44d9eda02fc832fae431ce90236336d584065663aeb7ed804d97c707e4b2573aba6f4d54b7087139cdc349047acc09f266cbdaa64ea6c9586ff4a0ddd0b8d2664c80126c68410b4e0f092406c9bf50fd7050559507e384a7177d59a2f8f623fa841156d1d079a13221a3f922709af825ec38acc88be02447e6a516fb10aaff25a3ac255939095d8a20a6fc5719447d96e05a114828c6ea2113436173a6b817eba4e807a24858350b23881c34244b5248d74cd09c06b9456b0adcb48395ec6dfda86239068b659ad19f9dfd61448b844b7a3f590c8b1634e20e4d881fc707c08a58f31fbf657d337b2b52b630170d07ba3692ff702255f6d3b34e4ebb2df7a4816e7a06768fc6834ec33c5bf995994304996928f580fc5ad09c1692d40dc4882a46e0ac9c71c54eed238e600da91d281b82e72e05dce7a48bac2daa9757be998410e6201acb618b3b71eaa9d7812d6723c44e84418ed6c6eb5c1a95d2f60be1cd614d4ceb21fe71e986f32daff27e1fac9493b99f7b86902f5115619570fc4b216655e5eb63e97e7102dcd69357aca3068ae04b984f28984672217b7186ac3871c7e88d8302e32d67f50932681dd8b91a8b7fdd25e8013e82e7ef8d024972ef7169148d04b51aeee21574815a00929742952f25e47a2c60424e55d290b6abbfc840fed1b868f342d0072f850903533bf7f09d348b0c00595046703362a8875275246b2d195616040e78215ba38e88c5d7da472f0010509c218387c48d34dea6df13f0357c05684ba0342d24bb821f8f763c4459d711f8ad86860d6b73828263d51bb29810e4b1d645cfb2c9b80834d000b5843ec24c078dd075bbd8ca6c4647ac91a60be451806301b69788350848ec2cd72390d582084d063ff1175bf6748e2c6d63b3cf7977e87c69477686b86df1b7ed1bf30bfd6bf0c3565a607eba598cd69fa6599704f4ce475a222665034cca10b9e2fdb5ab97c8bf82b26063bdb76023bfcdd01263e0fa80ad0362e62ea8a69bed2f809fb426ea27deeb857b359286010995c8887287dca6042f927757f559ddfb45beea62e2c42f282ecb0a8112ec6605c34c6360e179366eb41383eecd90e2e4cc09ac341220b89c4814249103c8241e05a1818d7f5bcfe1ef4024be0ee85322e9c0a77d14c2b17313a64422a5393c74f641bf7cca83c2dee22fefb074e4c430fdfadcc0cdc93aa19ba68253c2189bb281b31472876d674be408d343d69c3229c7aa20b3289d4edc4bacd6c20f9395df38e6549477ff33d8fd1e0b42f6aca35803ceb5f5fbe287f92d1f131a394bf7c21dfd0ff8a304f821e586f35d58e68ad67610049423c812e1c2d86764b7f1f230c44d01d8c4ea7722c789d11524d4fd224891aa4f5b14a150ffad97e13360e262e72880da17468a49adaae9137d24a154e5cb48e0e641b5f7fa56b2962b34c911df3b2e8626d83d06ab1b0244b5fe452e325b059f00286e79abcb2c128c0f7377995975969f44076aae5ded06fa9869a5cf44f401cf0caa3b5c9cb39e584b59d120a86563ba63250960ad327b234d1f83545a2e14485a2d7d9d8254eca9f7d3edadcfc09a7c678780830747ef7a31ab11c6048ed12c436260bfef9101ca279a889553dba5672d12d6e001ddcdb8a236eba255c06abad803f9c8fe49d61385c39739326d2b91a659ad0ac53d1ee16882e0b06b10ccca2f555ec5c1a64df8887301a845722ac101a847f7f5cc847a51542437572f8f76ee4e3043f5aca3ff23d6d7aac3837bfd6267828c380b881d30ca1b655b97bc84f4e7e17ef3f18ca96b0de8202ae4fb3a61a3daefb9924927376d5594dd87145e39e17a2f03f2aba2503a38e5845773f93fcc948c95ab6904d91229766b9f51391b1f42efe9b9c4eaff8fcf7a6d7d04149561b66902714398118b839bba8bde16d4c90b069e6bcb36aeb3ecb91ddee123f1ff46c45ccc67a23679ef7cdf3b3e2ed5904bbf2acd9acb5bb486b26195ab3af2f4bf7b8e7b2a6d1892f42c54cd24475045ff9ccaa96eefa4fca811289c7f6239e57b7af015effaac7077604c4aaffb7cc00acc8814af823c02be6fbe2027739f666e052223a8e89028d2ec04b51d8d4eff883cbcb88b118bfd0819245552e096e179c8d1e1a31dbfbee5277ef392e8cbbd7ea4ce5ef61d582636983cd2605ef12595bf9e2a208e505d16111880459c8b3940bd1089d4bd507f10fcd46d11e40a2b891c0977161a0d68bfe23363379f77efbc9c244e9b1542dfec0aabe4643162c2f067ed62ae0147d5b9791f8bb1672f1f049a8039bbf7a4d963fc1e2f97c807d2d620f5678d0ecf920b5101a723e7fa1e8221859ecf33971c6504406864489fd82bb4139ce1038e596f01df243cbb26f0b5a3e1b7cdb40824d070aca2bac0c7411c799dedf62198bf7bdf431c20accf56b30794c6d4e775618689074e0a3981e852b1202fae815ba07748a4053d2d2c3fdbc059ba6ce2b3566764ec8f23280fc65985a5ba5a6c360f0dceca548b05a36f34291b00cfa289722d859efa301a09d5079134654350792f087aa5f5145d331be4d07e266e371467e6292c81dd8a56fd51c0d61e5740e7e6ed687b9b73559c120d5171774d747ced3bb5c8b2e9c0d3ebd42bb46649d28acc8ce7567b06965268226126c84820100fdc9ad76460f803db87a3da2f2f5efed98248761a75e99f3fbcbde2296a9600ccbed4f0bec46c6d271336d2b46f614cb7e59dc97366c61411f2523fec624d15020e4adff23e125db04bb2e75f267a2d0555c13743e635b58187325248c3ad86bd0cae4c3361429706911488347f0fe5d4c08202eee3ac7c334293d9abf459d6af74ccc9da27048ca7d3b3d83a30d6710153c180ac05338335682d6e60f57c9771e0442161cc996bd085a4dd8c048f2515911c41955e1ea914c3677076b3a196f4402bc488b9b158efb66016e3022c6f35995aa8cd1511c36dc5263e4b4f085f12bc985286f10497cda606154bf5352b098126ceaaebed91fdee17313cd0cf72a0922a350e42f71c96f026c70e54b25c0fd6d8036fcc2bd0259d7499093589146703d0cd80d64ad6adc413699849073637ace001435d9402e818edf47bba8188f76e67e5f3e76da12e0e02cbbc708d979ab812ac8b29d0026dbe557ddb70bbbfff5c34c33061c016ce8901d3ee9b1491ec6e8ad777ea2600c6d78d91cafa76ad8eedca23c7531df62a2844ef02184ecfb4bc47f381f3b51b5764cf359bfc40cf23a58f8469e67cb0a4fe063614f73e05320dee47ac4f6e81a479d183d2983b375ccf0773adfb6f97d42d5053b29e05766e62c5ccca4231674549a532c156b4bbf497f2aaffc36c8653b7ba067659db9ed86e0168fe1085afd14312b4ecaa0757b20fad4fe0b209a850a74b3746ee01b9ea8a7f50d3b1b8fa49c0371bce6572f5f48f7d63829d6e7b69c18f4dccc4034eceef2af4727cc30fd3fd6160237371ed0829f6845d536a9fc3d57d594b2d66665c464ba5bf0881d481e20ae9d6c566c95a58cc58410e1780f3ef55304367c74789f92270fb34d99e43fc01b01dc23e619deeb1225e5aa9e143e14282fc52dee3fc226926c1b745e049a48d0fbb23ee3c6a724cd34981942b263b48123af22e4a58686e5a6eab2ed766881ddf17ab0108506e27ce7d17f556433c15f9fa621625a2feb2ddcb89067645757c93ac2c421b65d4e7c8f811356281d3c11be32d546c1811f7e00618f44c0785116b74245228751cb1c79080607e12d8067d8e11d3f35d3cc7cfe90f3367558998122fbbb36ae049a68ffb49d7de5d73e8d9775b29b40c4350deb4039acde8211e752e07db6aa9a0e02303f4e7121518db4650e7efb8fbb11a02c2160d01fb2b6e7e50c9309813d9812f5b485ec8f9b37b3f4202c5b51533cd12af8bd98eb136698548fcbfba445ede813db5250fb3ffe97755234287e5b9dc03bb5c1203be66951248784c11c0b1abae6c1a093c05ecf4e07e84e7ac68122b77a4dfd898bbb3c77dd36e219ce3d1fd4c4b96c52ae840e5092d18dbc13f4f47f2c3b81355520d7d52f0108a87c8212de0aa83d1792d60695dde3ee55385d9b42f32a00a8293717140870002f2c73daca32e62e54b90cf57f6db146e871a54112e9dd37a5d7d7564ac42662af454fbf97c8b530e9d2ebe84dc2dcfcc32a23d832959d0e1373c8764ee0b7ba083b5c715c1605024f70c3df14541b06012210d1a7f0097d078ad5b5d4e3e9b94c169e2f4b2b6d5c304c81114fbdbfbcfe364fffe62005c542d41eec1986f2ded8c115302e4a0751a97c3fe716ad85e0c1fe0cf48c0bc9b6b7dc16e941a3a9e0696aeefe03772804d42727b9c312401fb42855d918d50068407b2ab4559a21841be3eca25bcce9f008468f04fff145ff25b70e23205459487c9b486e1960211b808ceaa321ef65b79b4a315f8c9c5d3725390d69766154270a51fc18e856a2a660afa40baceb2a11534afbbe4807d1588f0be2730ffe949062bf792d7bab536f9048751369dca90d519f70c04aba49abd2cfface7ea0c266644bd6663b32237c9687f4e5a8ae8dd354715775505ba26fbb793dcd02858537df0f94ca6385f396d1f40c8805453b289c3f3604504287e6769850b971999f4a8ebe82654ca60019d1ad6eff789d9f4da9e22082047ed35ed3e2c7ecf62270013c9b8a9315826203dcf1b6b5c90c60bc48981c18bce4dcc733b64ada4ad9473651b391dc92035cbb37147352b95f28178bb410d610daad45576bdb88e9fc4527c51a741e615aadc4210c49242b61692a6ac149fd1ba892a4137f54f7b1e4e333dbce288b53e7fa6efcc499da8ac7b507a400e8d6b3a62cc9971297beb0e37e57a784faeb0a7e9196ed884ad3af81785a0dab261fff1dddf925a27cc293b6db661123fa5b1b4e0b4d8a9c99d8157edf967673bf1da5b3a6a9b8aa964854591ed30172cc65531646ff2d00d31e8e4ac75ac29ba4d11fb97a66e29c6e79596d291c200d494b66ee93e697f52dc2c2e01ebfa916e11192ff9f024211129f602b4b7b6b642d0c89ed2e288da8ca2e3e316a4e641a3447c3d3ea9b5bbe859885ea31687ec5dbecf2af3e9f60172680b4d7b6c4c7f8251f675741e0cb3876265bc4551c21c65a62a16a3e95318c19a598b3bd120c51ff97dba32194314966bc309c38e30e691b2d4e66354089ddb56e6d6dca474ef400c0bd219e613bb471d28b7ce9716ac35b7308d33d699a953fe6347499937b0e5ce35522dcc15a526ad38d6eff2784a978cd6f14a21f0ba3d828b742203b89f417c9943192d6a60416cc6e7a0365221ebdf0b3c8b5f7c8a23e414889b024ebbefc035fd48544d8d6ac6275cf96b9ed5b6e56bca167e7a3e0b9d7bd01fa640901a7b249a9aab3cb4fdd7ea8eec8fa45586723bb089e6ce6bbb88dc1a22f123f031c4ae144668a871f82267df68ae336cc6c3eaaded4f0989cc57009521e24819d576534b604284c5a7866765cdbe60d90983e0500e3498b1709f033b69ff82b518d760ba4096a5a1387ff0bd08e328ab429f861ef87ad8d4b8adb51211bc885647b827508d78a6f1be964e276b79430f7ecf9897fc6aecc692d6a0ba6243a27d2599c567a4a9ba04c74d4025a97f5871fa8bccc95e48e9b8368df8d78541b914ecddaef30e1aa96561b5bad669f4a401b9443773e1f58ddf227ecd87f9642d0ebb7606fa8d95902cdab0403c8f530bfea03cb719762cca8b434a14eec227e1bea54a1a6353d94501f4e0bbd367112383f925f119d79921f1055c401d7a5eda8ffdaac52fa80086e07cbf051148bda9996e1411c800c53b8b6f7c22021ce96b1d239f1ea9f486b51e75ecb175f079002427c1256a736adc1bce2902939b6d2be254b166510ad5768c7164fb1232cee7f9977c55663865fd5c60af2a7923d28f9906e8b93b0db58c70a78d8ad6ada223c9a00b4e5db56366bc05d431208f736756865d52f990c4e03b3317cdfc8c1944ed3f866cfe81256a062a307fbd488b0f5a70c989ba62707a93f377e21a0bc2de5fb501d791bf381dd452105aeae3ba11d09aec0bbf8fb0023c60757861484255230312bfc354ccb2e9b57f7534398f08c2c31f1fbbb18037558a59086ca87b4bb1f929751bbe9a41c60431974d2d516ca8e2135c56745cb1294564db6f0999f4923b8ea6721ac81ed25690d48040788ec237124cd5aeeeba44029f5d40b5a6203432f8917521ef55b8ef9c6f48e90ef014067211a3a9b698c0cfdb3c86b2b409f6aae197af7d85f4962503fb3eee39e39da15ab3fef4e8d911d21daba6161593210fb4b81dc64d31e40f1fb5f7c46648f13032b66cfde57c72764ad6a81e13b9bc562b7ae43d683e8c6a546acdd6c56c9cf843b1f8f9d0ef04218e8ee6a2512cda3017264f22c75b4d528d9e383b254e36ab00d5eb09e19f2bab193fec74019e0e6da7d1fce63d33b40ee41a60d26f0e198cff09b0762e1721929bccdded58808821e51db6bc72c0eed42124f2f882f7b7ac36d4d51faf7193ce6332e96b828cb7e4c8eb450459a5e971c52bfc41ed0ec0722110961e94028e9c5f34fb97a2ee808a60d0b34975faea9bd065638457286993b209a4fde7b4bb4020164d3d30fc260934616690f8e434355ec601f7ee975b37928c76374a715df331c7ca1b156863ec30ba4ef08e9ba9abd2a7dbd063fe25c88b4712d933d5be126f7fbb177d6b897a80bc2e8bc69588593e7cd55104a8e95b44fe15728e9c5451e80cb6373574779111bbac73655bad41488bd5de2d47b1d9500ba39e709464f821b3962115939a9a541bb65623cbd8fcf573cf5af97d9248c9dc5cc3c0d05b1536694e8e4a9a4c658f255058c9e7f0ed035944881f73a2f26a28b9097ebfa2ade41dc41c79975c0853e766fc66515de179b4953d5a76a226f2de812e4bfb92e212ec9f3e61e03395176c12a63f3fac713f3417a825a7a5801f66f3fa9aec09476ce81bf27c82552d2eafd207be0119ab88ad9176c242fb7945c8e7ae7f7d8dc71cf999ea9bad90c0defd00dad40b1e4c3e51588fb4028d16eb9544c7f26d9a0898b8996da52993505bc76016107567b3b985571b773487284a95ae3cf8743b8e6f77bf76dd984a35c421a3f1baebdc115d0831da08e497a4623a4fc16d4c9dbedf34f502d576b815e65421282ac1430bf5c1bbd698f47046334328217394e43434c4c6240664d74e25b0c9c0a9da2290a1bad37b5e677bf237c9945c64c40bf0553156c32a090403bb58ed4eee0b6159bd9d1b295999f9cd73a7ebb2e3e8082aa6181a7ab0da5a3c61050cfb082639f709f2c742a3e93c22723bf03b2d8a530ca86d3c34f87007d88f1206f0521ba0984f65d05aa1a16fbc7616fe44e37222a40421e8e29d8a676032527c70d6fceb38a2e1ec9eaffa525eeefe2f59991df4ed284b890feaea95737bc9276830be85566dfbebd20eb5d90c67e2286bfc3bbf56299c754a12828ce6ca6d8114bd47d370f2e2da5ab88e80ec8edc2bba214847a38bcf572c297e18a9934a9e4f4ba128203d4c783f073e7044fa24d074050f96a859c8ff61fe091039e2d0b937e0d97738dc63a06ecb1e5f3e90d56d73e6878b09eaa4c0dd8a272001369be2a57575699b1bf4787fb597b611b38027af4360c0b522688cdd7ee2ed3dd132a496d1eb2fba7d1dec09d2947e4a341de608ceaf6f4dfe0010c89c7b4985991f75b2df978dc295d27afeca94e44cf691db29a835ce0a1485a03975c882b6fe1cf4b0adb6dc58bdbe63a2c608a38b645633cfbeb8a1231116f63dd541ebc5b3875b53381104f1ebfe3dadc056502cb201143889be15f2ca30b4536f3a8874173c45a77f44e412d1d1c34245d310fd6fcbf6d1a91e890f881eee40b3292856b788fee1eaf105d5865bcd122f17029c173ecf6585a6977045cfea345b3a364ade36cbac324cbc08e80b48103852f03f6810c3ff81f7004c47b2751596f14cbc59a11cb856a1e963bc983a7b4be73658349d1100c969104679870334d3086c542cfbb28aed027bb5a9673e36effea050bd233a88ce3f1ba47c7eb0808dcc4345d6c505636b014af0010e336910064d22c62b46a77aaabc0fc6a397fad2aba25e814ce95a21fc04d2a006a871aba61a4506e1f10ceeaaf602c46e0b02da0772b24f30d936e53eb1df90bb5824e1bb821aef43e68665f24556b709e8685c04e8c21a6b46b987343f1ce61d9d4a93fcfcce036a488de36ef3c7589fc76b3b19257687caac8b1023e02102bd7551e2d22562e503b72fd2ad7505d401546b6e0bc70bcdb47316decba63d30010d744afa1a8c2ed53308844e31a71046708d36ba8c26e74354750fc157a86b90e41e083846dfe5e131bd3b584ef7ca3bc54a0c89b676ad3b5dd0b1f8a9816f16c0562ab70866952db822023f6ed0fca31002ebb31919333edf4b04819bbb050772ef167ec95f39f5e41ca434ccb81720222b40a29044204adb9d6c0f329166946d9bd4491250f51e7d5a8e458788bf1d86d18150357493af57efdbd53f67221c540583131e1dadda219048bbd21fb429485157f8a0259dd91e3dd0ccc4395d324e2f5d4d89c1997a15004528ddcbf709b3abd76f959fdb1edb7efc7bc9c31ffa7107f9741c579d53e4047018c75429f71d6b3687690e9fd034b460208cf17785de4c52e100d7dbb7d5b540df2da01c6b49489034a15152f999d41562d5144141495bb5c3bbf912c78ff0e7854928734248d3dd02010d198112d149a855b6bf9c49c0c70c917da4818ee0e4d266c49f514e5f0397455056eaa048a0e57205c554d3ac998a219d278638a6e7ce194272fd4f2e4f925d41c5374e30b5be2f83d41f29a6435083e2200020a8010021af2b4fdc79d2696c05d7e983dcc4054deec8af45ece8f557eb546b6b7594288b44d08d95bee1d190f630e0f0e3f649ef8a5410c933d262a76b02dbba79c734e8953dfa820f907567697b7d10a67eadd1191d8b0953fb35dbed5ae29657cbb2847310cc3b22ccbb895a692652635b9dd393d9cecaabbd46a2dc58e61a37bd204abbd1e85655725e312291fd8790dcb7786017137e0b868431f396787e69944762dcb4e699675c70c7b165196477ec9415cb26c2394523cb0d8b928df0fc2a17ca6f3928f78c9218f9c43cff1e01a6729b30c87f4753b7dc9a3b7c43a5d1e9debaedb2ecdd493a1543558e51c72f46e12de49cff92189f28ecc452ce0fd06e1b9f13eaf87bdcb4b314f4fcea8e7753853c773f69d06b1a64564119c346791b1df1d1c8c5289771ac47c8ce6608dc00f18c5c162df71cca65d39c07645899d891cdac8d81154f0aa1d86d51e7520268949a2d07d489f22580128b2c1089d1d292466ae1bf5d8c16301f2484cd2f9a5c128b4d5221e50844e14c2e411285c3a54c9610b7391e99a55494af4ad1194e1032c51096ec297294a39dc91b3e7a493624830a0dcd5c66a336d89fb910e0d459a0f0302424d22341a8d28f52280933dab34c3ba768f3a3b8f288f1db362d986a57c71f48e3a7ab5cc519a67e76c7b1179499fde3c1d376b58fa6457be8234d8ef2ab7912896af4cab99ac4222a1e2e60c4ba00691c828bc99993a1a715dc78d469b7c45181969e2b66ddc5da28b5e43650d879208c77175ca7019c665ef3c1c72e4c999a964978c8a32f275f99a32f146fa4822f2470e913e72891bd05b47f2255f253870d165c69b3a65e8cd1fd0d2b8eea67c82023d80f9f9550146afef31c23de23c5982fd118be250e6b9e1b969ed0ad16eaf90fa1325d81fb128de3ccef8e38d761eb2e269eb94b9f126de68f85da38ffd3ce479ae761af5b4fa1f6b9a86d668ab35768665b3b7cddab6aaacc691bd3dc8511070b2bbda73caa9b2a89edcd95a2726966199122ea85ddc102785e8e2c8a044c994c94410331428c94d39ac34ffca998fa4b687a60c563459581d6a1756d419edb833706dc8455435234ddc19365336289258115694c201a68629a5945d7bb59b9c111c58f9903322e3a4a489390ce370c0198936883218c6ed005b8209c926714638239c11130c51bc29c18830228c28f7e591c933bb4dd0795e97aa41d69d662cbb336354c90f42d898c148d9e580eae6890c48d7e86bb45db165ec8d3471bcc146d9fc764ac9f17de90324c27457bd0bde6f1b4781702a9478593300d0e048a2b6ae7b44c99735239abaabb2a328238f9832cacd9395632bc7992220aa5aadd09442478460e4506e796220451c902d8f80003990f6d93a65848b2ee194dd73528a619916354df6d426a51896659a56477134923d4799a6d53a1a6d1bd775b267b7715cd7791e8954b2d15ad9d396ac35994ea7ef43a5622a257ba6529d8987b3dde444d5b5b75d85d24d94948ed2555cad64cf5525619c3c9d98d8afd4e232a5c54a89d4c2ba74c1025b4cb875f9d28ac1b746cd65d77c529ac52c933db34a72398d732dbaf98a34a61c5da7717bf06e4ee30680463ed6c3695c1f9e793864769dcb3acdc3c9d73c1c32db9c8b95d63a5bd64ae2e1dd9422ba46110c4753645477ef3ba1528fcf2144bb4e1ebf8347bb5428912665a5b2d2a2c4f278e96372e2081448a26817ebb1e531c6a30ca1487397c03c5e5ed12e1d625a8f9745edc2331e77787c1389342e8f328f338fef26da0580479ac7b713edaa79acf1f886a25d361e6f3cf2f0f8aea25daec71e1e7d78b479cc8f341e6f1e033081a607a28c8d760431052f98348833073e60d13239926491640a8142ac59801552c8f11d45cb1431455391e33b05b16627ae204720453d2416f5125c883572c810e953854fbca441ac914d3461831c2f97302299f8116b64146ac8f10aa02555482534945cb180969140008832525e2163724c99d98303c417206be6123f14b164c9101f2aa8f8f9f981020a26644c9f09222132a63f5310597d2157bca076ff20fa90fb9206e08646b6f1a107171018e7078cf170c3468d1a1a00ccc80cc90cd518ca5c7698815b313ac0bc04c9d408d2ae8c182d2c10c60b17482e921624d57496528b159555cacffd69f919bd9878bd98c8fd4d120921ea5fe635eecc3952e779365ee3de38c9c321738d73a58ee4d5bc64bb9237f31a1700b71e0e9965ced9cee4e1d4d09c8b277a3acd96a74a72b94d1721b4236b24510864caf4d05c222828a8b3408204492ff9a1e205c5cf0f15af171401b8a1916d7ce8e1ce9fc9c4026c4e62050f376cd4a8a101c08ccc3d971d66e0568c0e302f43324335864841414125244890d81f2a7e7ea8c87dd30b8ad70b8adcbf9ff7727c61cea53a9437e3f8eef0948743667ccea44b79ad9b9c74261eccf1d5e1272fe74e3a9587d3ba2ae65c44a12828b3254a25dd520642c3f5d0f68b87213e92282828682e81a4b3f8e925489074163f3f4b6ed8a851430380199922761e858422162e3bccc0ad181d605e5ed8856b601a98078cba434141412648b24082e4e467c9cf4f2fc97d8ce2b978cb7d716ed5a57831de72657ce5e190b9e59c4ab7f2585779f1960be32b1e0e995d9c5be95a7838acb7f070c80c9e8b2c948565b664a92493f4f1e99f268c749024423297904448902cb1c30cdc8ad101e605c890585434e4ca88d1c20261bc70f1f3a798ce526ab1a2b24a19ba432d43ab20491414a482040992b944eeb7b4f0525ebaab73ef583c9697ee7f0f87cca573b7bbd7e21777d75bbd74558e53cee1aec5c369f1969573d185bab8cc962e9544f2b2b451f4d04fd0eb2748891219315a58208c172e7c9a70e1d3e2d384e92ca5162b2aab14242e5c5af0c52ca49f07bd82825c5a3aec9d6e2fea9c4bd7e2a96e2fca5dceb9e85cbc93bbf070c86c82babda9d3b9171d0c0fe7e4303c1c12a420385b8295f4dda6b38ede2e4ba00e923d8444c6f47b808086ce526ab1a2b24a311285112351905054f6c424853a05bda5e3b651d5b21e6a24389c540cb970e1752f3c1c3273e760742fbced30c00e86a79dbbf5a08743e6ec1cd8b13c9ced2c0f478ce1c588315bc6a824ec5cee993d24632ce98adc4751d9139314ea24816415124802ad405631ca1f9e3d3305389c54581cce2972bfd4d3f9c596bd3b914c28da8906bb89f9339968308a9657c89a9982d8738a1544987e28cd90fb303c204619c393c81393c88834894498fe28b79844702404d000e3858b1c415b27cb89961cdb85db75738ced3acbd6825be954bc1529a5846255a69393c987caf1b5c676a162bb3e93d3894965514a29a4d82e2fb6ab8bede262bbb6d8ae516c578dedd262bbb218db05e6780e64b1b458511981a45aab6ccc0a8c6a533b47b52c9b93524a299dd7ce4d6d4e0cc3302c3b12726e68b56b46c38882903798814f8761b4fbc14250c2dad5d4dee2ee3524f60e1e7008a2af18e6e1f868b083261559e62cffd032869350296384c121d5994479664b841a6cda5e3d47af0f20ed9ad8a710264b807d2a21baa48fe9d85492b1cf249186740c873a93685e203b6fb0f36124f2217ba60c47d4f5c81244579704516ed3ad6788ace6ce11d5a1ee9288ae4a8608f6fb0cef47fbed31bab09782a68cc5a5925029a8b4a42494fbd43bf6b625acd5a17675af06693d4394b1f68245fe4c2391f0d4b2e9dac9eadb5ba4da006b6d28d260b15aab52fd2098698bd6212153ae4353a67b4d5677af219c6e888d915aad8d59351256234672f650a67b79409832864b3e4d742f199bd4bd66f7ea6ed889a094c3da51a1ee039d0b72ef00a9731205d1af1708a9424ca2bc0a8266cf304abd1c497ab6ecbad7abd43ca43625c1454b7be409fab80e98316a4716abedd221f7a081cdb4aeb60b26a37254926d97f6d1e755edda3eafd22eef73665c51572bca5a1595d7dd2270b8cce5b78806477801f3b3b65ac33a20a519164404ca14dba8a3175adb153383546c6c965c217bf4e81a7d497b6c9c34e11e5209d002523050c2753da2921e9126e6d11bb8e812b28e686fa11a0fb124ff278d4fd7e7b1a1295353033ec4a09027f8109302f6833cb11ce489d1204fec05580ab0111c991e6843c47a642ad164b9218988856bd443d1c0321fd222ec34289f9791e67ebe654dbb523e5fa78c0f377ab0c10175150db69235d8201f68e8051d9932dfcf6c4394f9c2102bd194f98426aba75d1f51834944d7a78608360f389469c5c0610b848143f02f7078950b1caaac0b0e6d0bae47b81a9ca679381dd460ef00714cb0935e5e1d0ea89574150dde78bcf14b0f87c6cd71d7d5f11e6e10bf7185f8eace38ebc6cc7277b88d2b808337e6798b0c6000ad1d660c40882004305b93b68edb478c18c9fd1cb7818a741f373667766f0b1006fb09b10a710b71461222ab4f9f24682ac98dd52ccb469aa66db5562e681444e7c80b9a322b750b4a86c820d3a2a8afc85af01b08852460105805a80414028752a490fb2b49522b495e308a6010996ce144c9091954432a93b76093636cf28b2936f9c426264772d8b24274ca5db7d5c0fb8ae6a9689e8ae6a9e8f4159d8a6440ea6efc3d5c21346c5c214face8b5ab771e0eebfd62d5ac96e87c7c5a801af43c9c3713a426d24df40f8964ea6a9c86aba6071b91e4e14c2cb36899a2a84112c822d38d16201a9cba1e2e8ecfabc36d5c206edc987331b7650a206e4b90070498276e018a410b106dd7695e30dbae871b80dfb83f7c755fce72616ee3de7cde223838af71655c10e8e58247707e08c0cd49c63d61f7944da8130c529f8763d2c3954149924821254a2411ca2b2287864eb004f28a482412898989cac4c3991806282729aa1e6efe8d6bf3a029a302528205fa94e72b7f881091478a4823d2c82aca264ddc0284c2ea61bda80ae8fbf7ef4622cc13bc241e16484a48281e105a66bd8cccd324294592240167b05aad5af4b03a0c8de9aa59a9a8a8b0a87840605945e55d0f57c81335aa24a8809230a1e5174f0c8396cbca4011ab872584f5622591fb2c469890e406aeb1b1d2a28587d3c22382de2421e77043e3dc75b954404ab0e0c2a5055f1645e941c282a9805c6015900b5601a9807e55402cac02a218a567751824b9039a2c57cd6d09f280c0320b8b87c33a8b8783e69fc33e9cc615f2040d1f524eb11a338ee4d3c3152223441829624c9f755ba670d5b0784060f9b805a80887bb798bd4bcc665f5b05eac212cd7651199ac9a83ac0fe43ecb0331e648cd8166d0c27241a0087324c2589369b3d65a6bed89c68d202517bb52484fcf90d74b624ffa489f9c7283b47840ee038a10d231e2ee783e481089600025e91a7741c4ce9020874d0f175e911d2ebc2066bed8c58b172e5c5af0bdd143ca05352e383459fd5f9075411a172c02d590fbab0b12c12ee8a34a82f7be0ac86302e91d0dd67f578806eb4f774783f5a6cba3c17a7b7b34585fba0b68b09e741f1061eaa587e3e15683f5dd9dd77888644abd20804ca1065378e58a75e290e661332d39d32d3d9c90273279ecd145fe343fc881f4c8107b16b62214ac2024f7690ca1394657047aca1e20b2a7b12c48bbb26753e2191a2d1a641f80c212ca90fb415a26369054176c185b252624901344511a61c403da855dde081dbc843658c5d0898e208b8686ae58a25287288d11c3a294b2a2e6a7051bd61c8b841a14b24dbb676e808b2eb13b2789241659e9f23d349ba88ba60ce912bf64a144bc4443ac91af16d85510f4f212e7d006ff8a34f55dd4951b62e5aff0428ba68c0c2a2a821c320aea22e470164d0c8b211c0199436c284f966d2552f3708ac422d8fafea65225a0740f23b14280bcf12e6f3cfcea6e4a7fd11b21de39506f48efaebc911e0f7a53c21c48a274e3bd6f3a44228f649cb15d7a385ce7d53aa3cea26e0bb63e9c45d8150d1235d813634311460a5bfb267a42f068a7f947cc224c86af4b83b3954c9979f3cca78281dbb66bda4723a9c991a669dabf5d1d9411b4696744bbe203da957dbb11ed9adfaed32eecdb7db44bfbf69d76d16f07d2aed137bc449ed3ae54b2dd28855a6ba2acf550d6deadc4e79547560cc18e3eba4dcba1a1a16ee839a4431a0ee78bb6c08e46128b3c1a8d70a89d6e235ac21ad06469810e8d422d496eaa5d288e465867be826827e04003141f315f997a310818a302ab22d321220c0b563ef45ab302100e906481032c4af226ba84d99126ea2b9aa8b1985634d83a39a2a8ec9e1323e9a0a650833d977411173faa5688143a418e383c7ef51c31328708f9ce60c32efacc6023b06373f68108d3cf3c10631aebb111093700ca429eb022b76482e2a02787d92b22e106454c644bc48883d33dbbf943cb72022b7967254b794d46f69cd9c80a7942e22c33f2061b662f39a45dd8eca65997f964436cd7a398d1c6483fb46abb739b94529ee328a538a4e69d30c1ca6b3862044330c4d1f2cebc79274cb0d8370fc78cb22725c9e3185de21861228d82089ac8f50e653fed92198e834583e5fe11592edaaa9db6c052ac274f9a459eb4284f4c884e1c4eed88f9ca6190a29c134f1f0629ca140852ce5e60b01da6a4a8c3af336c219df9ba3dd460136d4838924586842358c857bb1e6f90a2fccaeee1c08068c93f7cc8231c230c115466792b9659f04c0cbf5e53a6dd10898c20fbfc74e6930de99027cb212dd850be72bc9d785af96a2c5ca4a225b98bf0ca809597994b8a62174da154166cd8af7e4d99f7a4b060b3232922e0a20b1172006a97bc58a699eb4eca4e5e99d970458e5058c31599468e50580392cc659d8c190c6b3339d911218728321171c8226622e41082a11c33117288a25dab98a34b9454e0e6a30b8f19d8b0562828a922aba8a85050124556e91416ac4c01d7c3cad3d49c534e8b001b8360c0440e552a2a5367a3b0042549b45a2d9d964e4b26a1856576b62816382edad0e6e8b4b4cb2cfb9c73eab4f24a87f6799fa3d3cad8755a99ae82d0704e76f90ce76078357b08f6e8451ceec8b165731862cf91e72e31bd3aad7c442be760f75ab91e93c75a59bec370ea05f5d025757ad865fb90ab317d24132c71887dbbe9c6186339f99294248943ec34f36eb82363ef5a9972a1651b9381f4d142c0c40fa48f8ef4c9988ef4494981055da57ce5fa5047be421deda3df3ae3b98712d32d9491bbdb4633305f1bb447c817a63df309269b9a44382691c94e227b0e077de9a952eada5367923de7fc21e7e05912e9266b3def768f14d6a4b38834df9451fd2a15cdc2d9d33d916622993233491224499024419292849e5135d92db2e6b773b24b3265289266f56bb556459198bc46d6bc86726272106cb5b2367b348c524d20d52c3a916ac886358f265e0571ba3dddf4019c70110c9cdce4f6363d7b983cc813f6e49cfd34b9f470ece7d551658b4d7aae25a251e449d455e4a642a8f652c0c9e893841c238e2ce00e60e523c7b936578c32964833389c29611206231639da7c89868c8920cf4bee314221e3002682589c3144775d441646610c90e76575a1803c1f41964c8f65ec02d9d6d40ba6cb01db9752888f2963234b48267ba4104abb085e07e47949cf619d9492063ea411a21df2d5048bfd45c29e6149691432320fb039f1b22787f10d87316499a5cc408e3c39beea4dd673933dde108970a543fe640c4f1c2291e74d16625fe9d832867f9432c545b2287b644ff67e3cdb3cb1e004fd91b18fff4094b17836d1251c9bf553829e3f31cb2ac41b65ee32ca3411c75194092cbde4ee35d17cddc3a51cce5787e78fec913d197d26b937f770fee4ded132f70ccb91ec993f3f180e29c5ed356605a594d291165252d8f9a825e18090afe74a40c84beea66bb9cbc3742b3d206a1c9d734115597e7427f5126047a6d047de6e4e3dfdf412606fc276b2b8cf731f512f01169b709d2c8e748e741360b1e99b8fd088ccdd34b2169baa3d37278f38591cde64fd0d91d89940f20e181331ce39eb6c22cba09f25b8e80d81f5ecd973b2b4046898479cace6a13d8548bf61ed64c7a37b8744024cb0e904ef845202f96eb77ff61fe95d6a8ad414a44ebebee2d09e0233e7a45ecf494b227159d7dde46e5e16234cc7ddbb89274f92dea3a7839421a1637bbc89f76ecbb2cd84bb9424ef9c24ddae93004fee1eefe50b04e9f231e7608ff986128544f7e9d4a6c7b9336518011f3d79676609f0e4ecdc0f24f276d4fd21f3e6d9f48625c093331c7f3a6d78a5637bf60de7c8939ee19cf80e0889749bb9ddeda43b6b934838e441da388943d9c349c9934d35339dbeddeeaaa6ed4ee6ec1d0e1370f2aebbcd3c853c1153538c39a3cc34ba2bd3b38f361c011da4cb9bb08eeef1d93105662e611df695339ce39d4b7d74654f8e24d993b91cfbef29fbee7b7b3aecbf049cdc24bb09c9fefbbeab3dbb21901cee4cd25de9d86ebfdd0e910a77746c26aa873593545cf4789c1c8740f2a5374447da30e9d90d2b0f9321487833f1b278931b6767ef86790938f9cc6e87ed7613e04d96974a82774309f064eff2dcd6999efda4ebce65d94fee463ab971b236d329dc99241eaa939bf03821ddccf3480f4defbedd15c984799ca04c3f3dbb2b7bd4fdba6edbbe6d2379dd4feedd74571de671f2ddf4d25d915e7af7ef9ebecb9d22f7180169310fd557a49fdce42109f33889a4abaec9bd2bb3c9b34b7ae96657dd93478fc7098e93c5631273974242ea0832474f472acbf7a953825054a78001098a70c42cdb8b1187944dcc0d48192f2a5ebe653c02456c5046982721a35d94bba85db35d92a8c1fe5083f28a05646e0a4a677aa40c7218b390428a5493c5cd4c19e986c8ea7b6004333d237de8c82fd8958ef9d5797291fa8979f0e42223bcc226ce3c398c58f49cb268d69706c139e408c82c8b220c1576c86646c84bd7e899dcb2e8d5ae16927d04224286b46b36116346a711ed0a553e4230db81142cc861cc2297724b3e6cbd34d839b335350dbf4c7066994330e4c9b435bb52eebfb4ba943f65ea5ff2a666d16090eee91afd7a03d88a3130bafc086fc0879b51bcd9aeada7b7c80536c073533f6f9111ae40100e60a002f53edcf0dcd4db4c4e7a401419e10ad417b90006e491b889de8e8a83c81bf9d79c61fb14cd5994674f690aa1dc8f1ced21b95f19b790ee89307d6707224c385ff2c824f2d319c99c2268463193cc2a721f9bd215ce0ee4ce80723897903729510e39ecdc61cd72d81d88345996658f14364e169d1d1071665328c9ce943d53091763ae53e6892f44d143ee4b1a7a5924900fdec4a1cc39b848fd0acb81613c04d9fc204416b9a315d80c595a218ddc44c80168094be67083875dc59b5a851c18a516359303cf74d6232e70366787e6ba434d2693e9fbbeeffbbeef33994c2693c9643a12a6effbbeeffbbe30d8cf6432994ca6effb3efaee8a73acbda18faea3946e1da9548a34a5128914694824cf8b349ed77591a6eb22cce85ca4a9341cb76d9166db46a348331a459a4853230cfd0866742dd2781f1d7b16694a1f9d461aeef4a3db1b23387a166bb218333a7de9661186debb5aaca131867e74eed208337abd5884199ddb36cf7b3db771ef9ec36da66fa68d3371df38fcc3c3453c7032994c2693c9643a9d4ea7d3e9743a1d3b77327ddff77ddff7a14edff77ddff77d2893c96432994ca6d36732994ca893c96432994c2613eafbbecf74ce8432a14ea6effbbeeffb3ed4e9fbbeeffbbe0f6532994c2693c974327ddff77ddff7a14edff77ddff77d28ce6432994c269389435d13eac61bd3e9f4cf6432994ca6effbbe137e42023cd90d7de49c8d84c30ed36fdfb66d3399b66d8766fa8e2c4be8ccaa324c2d4b474cf60ab84c6218960db1cab0cc083623b0531f230c05b44b6f00996cec8796e90f2dd706255ecddb0823afe1ced2c7cbeddbed220cc6e124b807e1b9e1fa7dac3e8ce7ae71dc37c073c3e10d74df30fe518f3df391b322dc3b0e7b80dbb66ddbb66ddb388ee3388ee38e04b76ddbb66ddbb6711cc771dcb66d5bd70663d6032e767dec7aaa9d9ed60c5300a5d239679513ffc88ed19410ec7ce4b48a718c2f12abf5da0debb59aa5867f64b8883c4679303985c04517cebb52e547f67084b5c7ee1daabcb9c8c5aebd07e1b9f168e8236f386787e61fd943ed1498f5d87778de37c073e3e10d94dee1d7d20be58674edfe2842c21ef0baaeebbaaeebba7b9e770eccdc7847c2c35dd77557c530d8ee42785e5f00f23ccfbb902436ef49803f5e358211393471d375dd393073d3e10d3c817dce39b51874a7a5e8126bb2875b7b4174a797dbe61281bb2333768e25d3934c4b51069cace82ad5f89031f41cedfbb88d44e0943531c668243c9b0605e58028a7e41894832964ae3b2d85ca1a584d0bd24e3feaee43d6081163e8e9c3a63b54276c7dec98d4e2125669f7f08e868134d875d4a57c60353c9fc57675d7345a1f76efb077d873b8d1358e8bbfcce207ecf6b8bdbbd16d49e79c6f50ca8cdde754102ca55864b5738611c938f4dafd217386af08c168ebcb8e1e92071b838420c447113db2dc604e4561c35696ff4c05c1ce560e674c05c1c63c4f230d9605c76ef6db83d23a6796cd994d24728661a1cc749e8bde105209193327ee219590311810e93347e7309e1fdaa8669262945e9b988ec3aa8f0b648c276398a31d766dd8d88135a2c199199bdd1bd59be8c0d2976e64d28d00666d129bc426b133366c7018430384c9da5d644db532c2a14d650d6bc7a28c8f4cda9dc6ae3313c4a90925902063781544c6f00a3b4f6ed1cc492722cc13d10a174c8148137c8ef012020f72df4407b66bb0366892031b5aec2ea0aac177a62569420337bffde4d163abeb4ca0b061adb9c6584799ca033b890189c32079c321ad238c52c9db86c397bc85331bf6b27b9b8c50cb0add755d5d7948f3c356eeb6cc6def3c1ca6afae5a3de5f40a591373ca63cc5bcab7ad566b55aa1f8cc92e7622759471ddd6442a26228964980847a42372fa86c3981c4a22a32ccbb21abf2c1b8d54e7b20fe78c5e51d40cb226fb46af29540a879d479428736114b2510a59b967280ca359e4103bd1cc3bbd826291432c1b22ec7c7a4789a819304ad4625d1422d3761965b68f5012ef74f670cee827ec45970884ac90b743a1480952e40d0045cc48e110fbe9f4ee66de9429a24a5baa989a41857756f5de311493162dce72f29f701813e915d9c685272f7938b6733887fbe9a4cd2bfd388cb167c12db00946c1a1c5dcb12e3bca09dee99c5de56527efba92d548144585439ab18efb09c679381e9616fbc9dc08cb46a3d16844733d61237a45eaaa1c7557fe5daf74c3981c56adda5804d73159e53208873120d8fdea4a0f7568843a345ab92be11ceea36f2533c89aac1fee90b787ad7cf270465cd2e11ceea56fe7246732ea2e71284b38a4b9c3abd2bd67ef574c4c05eb67adb67b761a79f4508746966ff1b095bda78c1e7a57b9d5c3317a8e54b9e60dd1e5d1eb949191b5c96c0f5bdb4330f7b6e1508746eede025b931156f1bc671e8ec76159e6b8ee72dc4ba5933a1adac399bcd52db5a1b66fdb6250de3625798b5698b68d5233c89a56a4517dfb8c4873f2ed3bc89a06c8983e25ca28919492ced9dd90d2c89b2cd1cc5d9eac4323973035838cc96e72439ab315563540d66432a65372509171d9c669363791334df3704cb86f1bed6af6ee6aaf3b34d30def34cd956a74892d448d3a9add67f380b81b17b9aefbb66d2e3936e8bdbb3aadbcbdcbdc5d3c20b86fef509e3d270b5df276848b4be68e3f7aec1eeeeb63b4f1facd0d8a5ba9fbe95d77c2254cf1bdb15915e38bca1bf7ec1c45b93a2e4aaa08ea810d755a2659f60ceb54771461fa26b7b3285588ca6195b47621cd5bedf2b6e5ac5faf2973df6f1fcfc3b5c1aeb30d76b795748ba5ddbe61493366234a536d50d206b98d87ddbe7156e42e73ef2e8182a8c85ce61e5ba46e72cfce913a127712a9243b2f882d779c87c3742d6edb69cc346edcc8f33c2fc7c6ea79dc472314fe31734eedee9dcba9b7df10231c76b6ffb0f4c9dc5198b35ce44e5db8619b79826c1d176220e7ee36b3bba1642287d9773a677424f276c399bb9b3c1d33530e873cd9bdee1e0ee5121cfe31738ec91bc2e75976d2370f6f3824e19dce15ef74ee5aaa1cddae6500967b8743b93357f603e8bee15047f7ed9b77eef2256bb673730b53cf3c928783fb8673b68fee715e98c228afe3509d87a37b0e87b9aef336a0cc556b6fccb5d65a2dde644c285f397bcbc5ff6ee9a74bbacd34ddb8e11e0d66db56bf05d99ceede479d5442d68432d7cd8a6d660fe774dca537006ffb08731b5e8d6e9f6de14ee39326d8eca4e39bbd84c36845ceae7938b8e7783873dc7612e9988743eab02c8fc20ac86e527881dce5ee36cde5fad2b67d0179bb5442d6c8bcf9644e7ad9a54fc7c351ef1e5e21e01e9f887b8c797277bd1b6eddc693b91b95e46d67e68aa5123226d370bcf436104be77001d72376777708669d56ee2a62777777b74e2769d941c8d1ae7e18816c8664d28b0919853c21dbe7d9534e9a905d6239a4c1ec19963e2f99659637c7fdc146be92c496514c28a613b389c9c45c22977236a304f38b998bdf78e5af7e28792082dcfde2e502a3bc5c0f2514358ee1f02930d81eb2432bb7758e93e781071e78e081071e78f80a0f6f5d1e5aa7ed5279abf5ae5d33deba6d178cb78e6a57ca5badabb40bf5d69c314e98470f08f03bec70f0f28287714399611c264687e802e5f22895ca617cc6e38b65c4ecb0005c4b29f6e23aaaece2250f07c505cdd3458c0eac76bd701143c6cb5d5a5e4097ab34a83a8c1b33cc0d7784f2aa731ece0c2c6d8ca9d4393923856d832d954b1b6c7dd57aca4535d86a1d75551a6c5d75bb065b971ece8779b8e173ab75eb5b6e58b3cb0a05b09c53cff27a96faab24f7c86028f31f339ac9a1b738353259999cf2d3c594a41fe5625707cc357668ae714e762d2ecdbf319b90de5f8935720a31a6efc3bb54e37d952af4965d3e75e5adc8a9d46d5aa65252a69e92524a29a59472c6d46d7aa652329739a9cbc83c757953038835f2f5041b0f5db2fcc3972c030340a5b5430c0ac68577f91f848834f7129fdc75b312575e628c31c6170f77641d74c86ee892b3bf78bc612b47952c637459ca2963831b83302491c90ac03b067604e530de8facc766dde6468ab9481878fee5c50d77641dfe02b349d4371db04e0b0635e3cabc834dca536ed3336ecc2a57e6565ead622e8daae6734e39e59c72c6eca14a4a17ff9e651cbbe18c0b179f97e618d6dc651d68a8ca312dd78c1d5a2f1ed2c8f1e778487dc10620521980dc225f14e52defbbdc1dee8cd68db93adc169818f7050eb3ab64dc985ddcf8bc71d5ab87734eb63877a3c539d9b5c0391a94352a1a3c131373beab5bafbdb9bfe0a521c40e1edeedb18006e54fb7887e408491387562facca571d3a787e3c2d2ca6b4199c60e524085913ce39cec5c384c3f5dd132f146f66471d2427ae0582e0cf9183162c49831a64dc7887196db740c1d8e6a99001c068cd661c41c068c5b19070f03cb9787f5ce735c1554e030a320767adfae23543927bb7c711747b9ac1b91a39411eba8727cf60cab3438ffe2bab828f705c3988cd31bee082596611b84719b06af0cdc3508e3ad4b1b84f1985b1b84816a160c1d70a89261fce5d2c381c1b141188f8163c4b8f52f2cda2bcbadaf418aef91e54dae348960f64ef248a7718f88437906ce3161e7b8883d7ea9ef0f88342cc74edee3e62d8edd4e99bc627395636fb5cbe4d869b46b75ec33edfab1db6817fe3df61fdad572ec39daf5e2d8856857cab1ef6817cab1f368d711ad9c837217a84bece2d24b29a59c3bb2cf781489721737ccb04e2bab8ef2e8e1a850cebd68f9392ecbb22ccb5c6ed331bb8bcbb3cb9b7d073a5d335a8f09800e3097a7d1ae97cbcfb44bc6e56dd8fc90438876bdb8fc8e48e3e232f3f018233d0f379ca754d60e1580fb066f8bc69d615d9bfb4383f2306e8e2bc40e1c5b5aee12710bfea141ecf8da6810fbbd360d623f9e61b90f8830d86f6eac0d62cfd74e16f6151b950b5e1a4234881de5ee6810bbeaf268b047b3b0131ca24cb0a7309c0a6bfee44f379458c704a4c136e11d9b1cbd8008d3efe11661848f20b28794e56b76960669b0e79553ce6c4a2925d865ec5229c4f26870870f1e22a92556cec7ab13878a646c4b62c26669a3678ebc64a341f9f27a1916d5a08c6719e7a28d326ed32b36bd72c32ecbb8cd94714f7fa93f9d68b8be87a85cf1238b4b2b05061b46a122a68c509d719bee914faf3794f9e5a31bda3c5a6957ea0bf65fc1e1e82c6f217b266be5321eeb653cb6ebcaf88d1b276b05d70663fea2ca3270d8e547211d30f3c0b243330fa7f925e61603f16040acc162cc94e9e1fd1c3bda358387f71710695ada167267d8caeb55b70a5155a3abd3cab556a152d55a6badb556193254aa951beaa81e3d2054aff1fa1a35ae7abdaa7f3794f98b46c8d5255730d7f025bb788e3545c4987e4599263160545eaf52f9eb676cd8449ad214f93b0d211bef1b71f262341a8d461508190f776450060e5b59c6c1b3dc506696afdcd025affcaa5c557245d1c8dc78ad19c66da60c0d6e8c7f814c991b7769d7cbbbc5ef1bd5f2d8729a16f5a7975bef72197f719bb912f36fb823831fbd78f57060682e9974cd0bc20253a8c1147c32c8c15c995568506f989839932b730ca11a8e75654c33e148868c199b2c83278a2ca3ca08571e9aae1395e45aef11514966b98b1bcaece22f379cc92f5fb92c9721e321cda32e8feca9854a1e3d8f42973c027578f8924734607c84c39773e73a21a0297363f4becd0f3dba376e4d7d41954f6ff1be11d11be9706383ab5b616e6c30c68d0d9e2eebd6b7b8b141183736e8527f6ffdefca4d31bfdcc872431e2319009761ba774300707526a7bc7a41045102099a3892018075a2121737662e47833666aecd0f32ac5c93a241d93899db1562078f1e110605ab6e188572fd97dd75c30e3b7cc3d169d02982b8800ca230249447f8f70830e7c4dc5ee58546ff460f37de7aed55b17774ae878cf9e88615eb80b93e46d5a08cc1a806a58ca796d8b07e846da64e1cca47c4a1dc7ddbdebdde2ee5a18d5cebc338054badf576cad498d0a43c94ea7bfd8e769d5ecfa35d9186f48a439d2894b567a5d1e92fa3d16badb5ca78f480183ddcd192f17ac3567ec1e1e8a7cbb8e18ebcf27a5bdc7005ebb4b2e9a7db748b7b3ac7b2facab9955b57701895e495af4c9157561e3d9c95dbf4caca0a102b57b94d8f56aea2f295d7bb02f3f2faae5d325e6fdb15e3f5a876b15eaf6a17f8fa4f991baf07db05e3f5ad76bd783d8d76b978fd4cbb5c5e6fa35d2d2efcfa1fda755f9fa35d7fbd10ed6279fd8e48d3e2f5326ece8b0ee7a22703873c598696638419bd5c871bcaf8cbcba3276304736983f52f326ed7607d8c6b5917d5603d78e3be59f5305e5c179786cb9d69b936f0b5b9f787df1c2c57881677c7ca0da3925c575fb9abab8c708e06eb57f88706eb53ae8d06eb51ae4d83330d561bf7e4d606eb6bae9dac7a93ab6ab09ee67eb2ea53176cb01e75690437e6d846fa086e27363710a1494a38d931fb954c1a0e79724e76cf6aa8d3e9439534d3b437662cc321cff47474f632ab42f954fe3dac99e52c8fed0a4fffcd8e65d1bba6bd450b355163d157a050d10b225ee255e9d85d956e8f9934cd6a584ade286d276f7c86c31fcf1448c91e559acd2e1fb59b6e68df9d6e3a5dc3274d38c92e4acb2eeaf4ec287cd2049be1214ed770cee9269cd3e2da0e76c2b14196b778f77bdb0bc2bb76e9e9688169832caa6b38fcca8aca5552e59fca173f0dfbbeecf19aca77d5f76138547df2c3ababbebb8aed42b9c421a7baf229aa4bd597f2cf1e45bb2828e7625491f2f1ca0b45d3b3bb7a8c598c2b2b580587f5845138b4258cf20ec33928b728d862d10bc2d31e3dcdbbb5d74c377c36652c39862c2d5aacaca8a8ac56292928282ad5c98989492a85427ddfe96432595b2a91489ed7751cb76da31c4759aaa07eba31c2a070584f0fb51c51b02c57507098e5f816302d7098c9c7157c3a61940bf5187198bdbb3c2a34bddbc1c222b2e9a5b7766b1f3d1d5ad4344d5b5dded0845d1bda4b80271671c204fb2ce3331413123639ec6ec23b58b60f77b0bc7a17f2649b51506e3353aecd9f77d5c995f687368739cc4128efd0ecdda47bea8645e4ce3b27a396b9e0b0863ba7731f50b628fc920985c31917b795c1bbb8bc8b4ccbad8b77c9845d6e8c2cd97df70712d9fbe9fe90d9f33a623b98bc9ef79e06bb854c423a9e359c8cd4795dc7962b1d59c414c0b276244ac7329924f7143e449ac88af01cbb9516d29edcb963117e6492320c99444870e3861c4e26725f8b424a9e0e8cebbaccd3ce559a4bd7ae97e108648f29ddf374ccac9d1b755988e50be4f8923780d24bda4b1956c28ae0db7448ea483766ec62c3ee36725131afb02cb1ca73d8b19dc84d243521799713490d875d2424a31784f421b1e4b9318212b7588e939e7679292057085801810c96f8e9b9c12fe2e27231460207f11b42807a6e0801ba4102e327e29fd0def83e11e5e3b37b84fc0d214039bb378400e592a72303c14f6e89610e39e222f8d143400974799cac19f009f1063f9c41800b7e421e23c0e5f8186300dfa5e5f1a694026bd3d4e3e1728c83ac8ab878bcc177c1398888372e6e8fc9eae35b843c928511d7871051146a0cc46a6f22edad1db9428eb8851a636bd32da45d15cbf8c270add6862a797b48fb748d3e518c51fe2d645ba87d7a48bfe4b5c77e453c2716504ca23cafe8203987e650bbb01309093551839890116b04c3bd64a86bf423ee28d879fa90a8856647fb4d614379ecf3524ad9724e9a45eeb7509206fba17c0d097ae32851c28006faf241245e210003f3f2f12648c7476f47e3ca9578e26449223815dbddbb878370efce731379787fe8a2d232f1e288198c30114656974dbb8b8b0a7d768965cfaeca05b63e1b42c33999c542cb5d3b83f03dba84273db9df8410d4bfedf189f9ef72e037dfb968474fd0c738af4e97352deb57bc4d7ff6eb114b9fc9f2e9eebb3da459fd94186cd82f89b7faeac46624fbf49006dbe73571fb3408b68663839289efa1c4ed3344be264bca9612e3a226006188055964951c83587082ccd1acd33a0c08181219d324a053cf5705db4af4ab436900d52363be2a5894119406228d9435f18dfb255b8908e37539882e93202944b07f7abfa68ca967b28e7023edebb6faf8193191020e1b8adc267c6b7a095b9586c3e39656b0212928d2c8f73f231f14a20b45834f09aae733f219f98cc4cf08aae733f229f994f47c4a5028231106d59361346a3262997cc9571f893019462388d188d188d158ad2a1ef9aa6043d34b2a21573bbebe1096040bc29470292957f2473d88c9898837aa20f63c376fa57e7222e2cd090e127168570f5bd84dbc491d7557f23b26abcf73f3dd95c4112022dee4c0416c70d051412678c5e3fbc93fdc63f2ef27f88923e4e7e3cd8ae255024e8e3a3dcac9513888bc39b9ea3c72152f897a7a7203f5f4ec30c1ab1d265ff1f86ef2ef269737d52b40bcf970132982c5ac90ee11427b56f31fea3565528e00d48731f061e0091edf51f06a620025dea01e6f8a30e2042dc835c72026bc2187fd6a946bbd7ea5be7a7dd82f21425047b990ef29abf9d5796e5217f5d479a09efa7ceafb0a0749f91e0405fbf0dc70df455d145ecda7ce73936435f1aa00df51e7f11df579140ef2c4c43c504fe120fd2046729fe786e786931daa894c56c77f2f88307d5551ee9f60a2dcff4cf0671264628299048d50a89e2983c2e155f627262914aa27f7b7512a092b1f7e3e263f93d5afd5aa4c7e4c7e4c7ef2cd0d068425a1a25d14ab02538259d12e29531ab0f4540376dec3c132cf2468b5a35f41d817ac8912932a96d8fad0242845a4a95244a69e141151ee1502bea38ec21840fd7bbcf96e0a0d16859f58618f3d9a4f0e4940a61e2041fa0504040404040494f249f9a47c523e299f944fca4748484848a85f42edd344faa78df491482333ea489d36431d015344167524d2685c88aece41043fdcaf0c8747bd841812935a53d6a2b0cac424a8b386fbc8186cc5a13d627a997c4c444c3f26239146daa0c9fa7e228c146c4802f29932dfad9229a3052121012121012121018524201f538fd6af21b77d428ec8276463a62bd92385f41079917eaaaaef154d1909e4114d99ef242293e4939bf422f59086b621208aa30422016148a64c1c8d20b79661147bfdb42bac3e4d84231245ee734cc466a25f1c917ed19e99c52cfa8ef9449af9ef7d6c0491044483f8022c053d143691d62f1250bf30241fde48405366239aac0eab4f918a28ac3e24a0ea63ea91339a7094afdbb6f54498de86723f4b6ca284ab1e91166c68c2119958228951982831099a32ef697cd263ea001421e24a2e31bee54c7cd88a98ceb48b4683cd493cd360eb74190b29f5a4fca1658a44963c796a0f650c7dbc5328c789cdcf39ef0f6d1ebbda6d1af4ce78d915ad0c37d18cfc9dc13398c6d704dbb2bb6683ac99729031190b59d33d59ca2cbf80965206f528dd5e3e8c5806512193047d4db0720e58eeaedd70be2e024a12f3283d881cc3911bd3ed5dd506db4ed6d068c88455c1c4d09018b0ccf3bc39e72465a7a4a8c4bb5be9d6c9d2b0dc75d22342bbf480905114b11f5d23454a9748a68cc5c754769664b25ae2a1daad212b4091fb7d45bb4879264ed1eaa10cd8b0a5d2e06715cdea700e95c256a6ad7945b3faa14c3294011bcaa13974850d2592a12c72d8434112890a894aa5c7ebd3065032b23c5e057e4db02f2d2e122de925f2cafcc4b20b2b3dbc4fb92487183da5947a3894ed0dc1658a2f9dd3c3993693de79ef660f79729d975de0b0bbf27a51389419b5f2ec52686525fb8ab4bd44e664b772331d5c9ed10ad5c4d89cf3f704a57496fba6b7f479496f0f67cef9946bc393cf9b72d54579e9a68860f90fb68b5e2c0a51f8c930728c02148a668715512c26515f21339d42582e6970968e42f34e8725bcd3b9743a49aaef0f4f3ef18e149afa0e4adf7149a638d4e95438ac2c57fd3746960a87f43353a5527de5293854ddfbea9e34c17e58a7cb1fca57f0533eefceccdf3d1c39f5347f3807058732ab3e531eea74b9f414ec58e958c65438a7f479efed0531bd140e794a38a71ecbd31b02c33c1cca2599a24e6f86f28e5d1d54f67ef2798f40e51cef27f3a54bdb43c15d839ef7d4ad0d7a4fb9b64154f6ced18e744f5e5fba27f770b8efda06492791fe1b9b45ba7743141027273df55f967f37e595846d9f273d641764cd924c529542ccc368a82344f5de91a88a963c1cf2c45cbb6fdd101d944f9ccc29274136f49177522b2957f9e82d72e8ebe9a59f17eb4ee9b399255011a998020b02fbc4ab52e9a457954a8557259c23924eef853a797ab7e7306e928e510ab06409f06492e791f009136ca52f5dea09917252cae9b19fce65d22380ccf4288f1e01644ea947c1274db015fff4e80d91728a73524ec239d9a937513905b7b821cda30cd30657f0778a43157af22f759b3eb921129e0eecf4a49e7ae7b2930cc3d1c3e1979aab145efd5bdda6533735270e6f927ab4df67ea5fcae429d251dd492812eaa51beae4d267cd2accc3214ff6304fc7c44e3e336558e2c428d853e1d06202e041650ca306803a098549a10e2adbf4004694443a55bd7443542e4d8c1dc5660cfb9c292938ac194339cb8dcd42c1a56f3aa850277b57d1932ebd20ba934e7a8e78f24b3aeac69ca333650eeb690dbd9b4e6f0ee99da35773d82387db3dac83caa4873aa87cf2ed84742dea76ffeee94aab83ca1490b9bbe9863fe4edf6863aa91d3c1aa4f4dd9daf3744cdd0470692b12019c370b85d1e65b0dd71ecb84d97ee8c0d9df73ce99267a7c91e3bda4569e6d1aeed2cefec4c1785ed62fd0492b1cfb3dc1859b5664cbb324794b52bed7285c8d16aaf9027324d8bf136cd5d0efce609f96deba2067b2497c82b87f0ec911fddcea2c1edf5f46a9757ca25cd92422d1fbfc9882340b3869b605552a8254779552814e4b08b92c021f7918f086194ddb9132437414e90dc74e72efb46e20dab503187b60af6f3d5ad18bc72387dba488695b563a3144a6091c11ca550c20929945892a3144a0cc930394ae1012b7217451a99655a4888dc20092be04114b0b8d1726c50a372499665dbb61d47ccdb793290b0cbda47274cb05278a08a5c479727cb2e5c0c17e14eefb4b3c129c3e11c604c2224640527960835c1e2b834d859344b48ea8abb509f2d89b5421356a51d4883bd836159966152c8ab6bb4ecb1f6d24af911d9e8cd21aeb6ec39a5dc7a346b7cd5e2cd324ca3758e7a93346e23928c30f1734e596b064adba34b38fac99868569f4b89c186199151133f5ea699bc058294299e9d65b6e90f0c36cc88f84c193bb738313bc2d35aa2e933896446dac5042973222332a7cf4b48cf769bc686a6ccf6ae453d14ce2622eaa270facc9e70fa64447c365c89c2199bd14f26845cfbaa25725f25a29a5a495bd5e5ee726c191fb2e616925d0c9bd89c7374cc040a1bb672a84323d3635572b5d6239127863d7aa35146e7c470a466c85ecf43891acc307a370cf3326ca30cae05a8846bd78b9b98650ccd88000000009314000020100c088482c1683424a8e16c1d14000e8fb45a704c1589511083ca20638c010000000000000000040209821712711b0db3698c72f0dee37e86a01bd182a5c1ed2b1e5219fd6cd9a4d2490213f63145823eccec0f91d0aa84f658b2c32d6ea9aade94cd0ecbd102494d4d759b2e48ca22c61b19f1410021108524a005bca2defd99c6b096a3cb61c619a66c84423d786bc60d8568800828b26ab6b9570c43a141d1600747ff9ed05a3bef14b72c9dd0be9a7913ef8be4f169633cdabdc57797532c5c472b0ba29f95ce3a53a41a21da260e8dc9fe004cb336f4ad2cca1bc4effb6902afc19b3b3c97dfbfc83888b7d48c2ed08b1964aa03bf70fbce33b7da07f641bd8cab69642bbcc6f35bffc8f541eb1ac3f218150277e6791f442280586d320e5b8f06ffc7b3f1a67ed2a647d44ef37056228046fdcec1e5c6a05615cb364f1f44da62ecd44ce2ef636f719ca551f6078033570bcce196dc5a5fcb8de6033bdd0749fa8cca2afa2527c8bce7a129381d3dc844ec57c56f1bd181457a21bae8041bd181a5524b7d5c59baa30336b97aa87e73738708809108f6756ffe06611c30a0614eea6afe0baac2f80edda79406317340944ecf3453e12216aeb6248067ef79eba304eaafaf771b995792eee63da9edfa9d5550515e2584a05807c2a60305d7a08a1d1d4a5274209443e0c29440b55b14594f62eee3a003b9de106ef409c3e87daa0375f01ef28cd16bb8e87844f359ee84999afb3c42a5a8a8fa8e988f88fa41cc37447e21ee03d13e11e983087f88fd85c80f447d44dc0f62be21f20b711f88f689481f44f843ec2f447e206a9f5e2f81f72400ade3cb44174ad2f180812cebfb6975ad7042c1871ea49f50e1796e81dd91c555c5d0ebab73c7e94fd89754c8d2bdf97beab854c8654cdc4f52b5dda8cdaa18d30c14c2b2fea9a4026c44f4dabe8c96615ce92bce24224888065d08799ab1e51a31ea5dff99aee46613c1fe4c6528a49e28b4343885145f005645adc0400cca068a08a43c44093fe758a861344ba9cd15c4d56ba50cf136c3d20784d112bf66407f3d05c8765019dc580a31046a4a3c0d8629c40642c7f32786d1b225c766ebe98fb85aaf100ea08b821c56f61523b11d4fc8255ca82aa297210a911f7c2f55d0d6b91a4a08788d345738044302442a8ec09b715a7e2da081725bd434de8e5441d7531145eeca26417ee9735b5598f78c0eb3300457fb86f0496757b7c56feedda0bffdd0f7942809435bc574a83d318fdae75eed0a8067532ab9f1d6959b65d5ab2d57131df9b107d781e589251584b14cab745153dac080746bd5ac6bc7c48ac0c4c4fbae001b4ec16208f111914f3de9000bc45f3dd7f34a27f824483fabd95f4896cd7d159b8f253603809e845257dd147d6f34e45c7ee1bb47375df461c58326a534f8cc40def35b8cb785bf6d918e9a0336eb9900c287a96a88d604384f354ee9462406b6379a80e2000dff6715905d6ff3e4e490d8606d1d5ff988a855304b8f18ef798ce846683fb34d6841b203d528f23a6e1daf5e46d4d137db322911d901bc581e16f29037735f46503113db3ceedc9e32521815ba34b3d18d3d294cf15bc9f58a881be0800259c9e6797a490e383ac8305bb4194fd073683ac2b2e7914c119b41fe5802ab3a0953dd52718ee0cc33bd961dbe229026048507872296c3c61887a6140acbacd9817625864cc018c561a35f3a4bce720b7da2e8347754607b9dc10e6607851ee997fa9deef577d59e74fd2f27d3c3a2f2466e24aa448c96c613dd71089296e249180ab6ebca7e5a25a3132f4206cd1b65d1095e913c1e1bf5701cd6538d5b00c30f759b0d216c8440c95f27c2091032ef09843eddcb52556431b647835d08e69a9ea17b316f624ccd99769e514996568d6e617b92b05e33bc2b33a8d716cec5a2488bdb137529c9925d091018d2212823a20ba591a91facc422f381486079afc00862ef0850cd50591db8c7bc2d27a2e1bcf5ca904112342cbe8e711778841eea5f4f0cccda9e75ed09c546f2ce57d7c2551020a8cb972f5c63807118283a82758bda18491c5a2921df478448610cb110531fca1fabc453e9858164c2a585ee96e47b3bc302dcc9c031943b6cd82f9bdc8a0021f3626e3f4305cab9579490233870cc09b92e9c477176f87de25a66b1df3a8f3da7276aab9c4486f2141810f50c6e6fba3f50169e43f66a819b63cd5a22a6e94bebbbd0545883737e0740df52adcb0626265aee5034522a6b9b0353400a59852bf7e4d3ce4563303ff3131318dba181ddc1297609736b886e074e6030d8372bfaf7c827c7ac6dce8bbf7e76e6a9f88d8f34f3328b7e87121266b5e6d51b1cce2a9b3cc9e42159b175b2fd801a368bb34de2eaa0c819e774ac3ce63857173737100bc46c411bdd45aae00d641e05f722ba454c5929b96f16ecb9060861f366601edda5a8892a45423d07b2881cd7eeaaac8b103e2f3c5a7a952cdd02a5ec1d1193a24a547b7148ec41a97ea66ccb125e6a323d1ed6baf80fa318251f648e3dd9564cace2d426dc07455be4df84e825a752ca517cb1a7a9fea58426844dda50c4aac82fceb014be23f6b37e1858a1f39e56a3c878c7111c668533214481fafd02f4145b2225c3d387be387b3ff3222da71d25d30db32c9ba5561b8619c1d85efe7b06ccf077af486d1c9e1031fa488d67993ba26bdb972f0d6524f279800ffb54f50941dcf486ac522220a7c2e195693e140016bac481e9c8be4ec899096f284b1e5559698c385c7cef0e93ee10d059656972b1417d010d9fb9dc067ba2ca8c3bdf046b9b3453c51120b0ff182f518d371bce72b8c91875e4dd4b69248e69d866cf8bdc8093ef51f969724409793c6873be1f6e273687f629d68de2b220a1ecc6af59c7f221231b6cb7eb11da18ee73557642a4b2a01a27836260e901ab1d1820678152a54ccd7694fd94150fbe5702f5ebbe4137c62f5e4820617aca0a452e2f873750db5d386b1f406b9e6bd78e2f10f365178bd8dc70b3db926b8fc12f1ae75aa4fc50937d412e273e8ef80088c52efe82565510338d8427961806f37b31279f89b7e2dd0133ee9bc40b5138e2c1ff44c248ae61316defd4a2243adb6e617291d965e737e005ae1601d41b4a44781f45d25b9f5a11778d9562e2aa2c6d3f9fc7838901ca7cd893a4d12165442fd0ca46ff32ae5bdd1425a38b4acb0afa3ef7ee5c2a8df135f920402b515b02524101c20bb2cc4fdac5555a2904dfb61bba088623363490e7b1549bbb50a76756a0633257088dfa774454f950e9f476732e2b2f97825217bb066c53163483093bd2d34055f23aef7df1d943f31cc55ddf4a51b6996fa7ba42b8ae46322798462952eed71d4e511a233764224edc55ada5e02cfadcdab21970315d1c13879ee75f5444feb9edd7c3a7b8cba1b2f8a7de3d4d8ad59bd385e67cc1fe35726fdbaa1619047b9fcfd6606a80e52910b8137ad56b67d8ef602865e79b5fa387435c8f4ed00e7026433c66695574a2f63da0c82342df885933d2bb02f5f2322dbae5179bd788e595b58edbf9689f21edca8f9fb70229825146097aace3ee9167a320b3cce1d3c48f817bf8e95f6d8290a9a35e057da43401d404a38e42b25921502d48c3073ff27f5fa0a0d5381b86d052dcd8780c65fd285b4505e1f539222829fc522affa352fc6f25fa7f2cf131a868e963e463ee1efea42f61528398f46eb156108ffd0fc46df79092e0ea779dcdda9f9a84cbd4acfda897703223b76b93af3ef5e2400affbbb5de5024a65ce14d1877ced1951b2492c9d1cf9e58df5277a8c44a8599187085ab6ae1f63942eda8766ceb58735e69994aec8b6dcf060d9ad0b778bd971f70e9b057ee6a778da35327ae0b380668e6c226860ced0a217158415f0fb0bacc1c6a294b9246c34dcc1a12a3d5b921e544fcf1b7999a3e7cdb541c0d1352c5938730173310c864627977b0e8ce0617757ac7443d01d795035823ecb7239e97493a2a4b64cc0cf552c029814f031ab9b18618ccef5aa3ef7865224b62e57c9bf688a50ce2292fc58ea423c647e1db23e673ccb2243c27cd80ec6d77f799108e720122b61deeaab71373a462bc6f915014787a9c8a399203172b39207eb100d65faa5cff1b138e3d640345ae76caf3e044270c7c89fe7b059f1071e43108e066065e4c47ee5d4c1986665ce9b4eefeb5445ced63c2b88948c9cdc0e02c5f69f277802fea706ab24837c5ec26a839ae4aa1d433a7944aa70fb2b982dbbe6e4c3ea28ccd5a6432a7af814990cb88e07720656d90c65b7acd37510054bf6637288002d1536ecd6791759408d1a409a15fc4c38aba7b1742f64f5027e9c0eeaf50ba8abb1c4c3a308da54489fe6600045a48e3efcf812fb420be1c4406edbe383e0200f6fb5640cc017f0e7f6020366f47b05edd58c068eefc1b5f53914f20dcc5757fee48a49fa06a467396e96e8f21336076f2afbb0642a10c1de8b42e9b6fa8e5f8039babc194c7cf6bc635665268803f4981d00b1188471e9ec2739ea26d25ab6647348814762080057c448b951a24bd9476dfd9c4902ae36dd01023b826c4751351a98055ac733571e5906900138a0ff5889459ec88f6f0a1f46441e6a401e8ab76a1e6570f105cf000044737c4f4fd6f2b3d0c028a54eeb37e3b721d25e83592ec25343769f25f629320d92254ade6a1c4d31728db773e15186802d5e78687eb937164579eb6c5e0bfde4ff0652d3658bb05daca846162b8cee0522776b561765de6d052cbb08f2951ab9abaa5dbadd297f5aaf25c023df37382177bf0927725ff8948f40d5fc84ef45f1caaf9ee7ed191d4e8204939f13a775b382bd12005b7e9298cc2d3dedd94063b209d8b12b809ccb4a2979f43633ce27bd579f53081419b27dbad912a41df7ac4f1e704a4a8b95903865c5542a525848aeec2157d6bf2916464afe1a3d1507f4188949c9932a32250465ecb22c663775eb49dea5eeaa7e46b219c040c3589a64623359e1b1fd7cfa285bdddea30a1c03968f81ea1ecb5b74ab48666bc1451d87cb75e51d3b4db6f0806e4ab0a96e262b3fd303b7243328a1dfcb8602bace78a4c2b673d1548900ac7a2d7fa4869b260084be195870d60b5467c0789d219a3c28c0e2f2ad374bd6bf1ad817b358d59bd029002d058ef2c0040f88c51df029079668c12ed0497c6b5cd58cb6cd3d50c272574e560587080a23c5ad7f461fd789c2d59a9ad6f3ee4065a2b9e4845634c78f0cff6e9a1c79d6a77fbe4cf5fcb7e080696072400f3de05515c30b14334baaec3134d18bb5725910baf4455478889861d7407456c86cef0ed44f6ad998ed087d8f7bfdc2a72d68ab936856891715eec2fb023430d5046c7147c65a6b218de76a40af0470ae58ceff56aeb39d29b7416b7c8c966feba092ca31c8a295bb4351c0dfe60d7c6394ef1b25b8ffd49244ae1da7c516a6d3818e528ae8654b5a31b6d47f750c2cf7c6531f396f19d03083c0510e690ba1eca244ea4281ca41ca05648bf626d2632438583e79922c5000a656b0c4f62100de2241557ae266d268c5838ba78450e3fccb11274bf6fe7d1f300fee7c1c3341475312db01075460d50d2508e29457d779bd30fd56d7afd5570db589ed9218a0c5f5e45634a88132bddaf084eb416f8064341fb07cd0cb513fa639700426899528cf30e0a1f0cf3d389460fca30f9fc47a0070a0c899d157140d928f53f9b725e2157117b6a6705c156701be4599e8f2fde7bc56065af6b67656deea9babe62e9a503efe10dcb183fc39c80c4c2d30e01870cb689e1fc698dc9c61d90f6aeca811db76cc57bad2f2a7d8ecbcb163b954bf6614d2d7ceae0d6743a834955987534597f23e5cd7fd22d32dd03022df103bdec1c8dfa10d92da679c9bd7717524241fd01a57691c2b3276342acbf8ccaa29fcce89e7fa93cd10387ee9286e1a817086ee6bafd41c0344152772532fda989e3452d0c4bc7b53f8797cdee4a73e6844e904ff85231bfeae6e69b1eb2cf8dc43a15247e0211e1402ddc585a8fb7ec957d92f3c5ff86679fc9e773da8986949393e04e007c7847106ce43122bada82d76482183ab0586df1144c80f7169fe634e1a527260ac890f856d09ad190a585e35ccc23265a67239ce3a35235d41de089625742f71cb7d47d961fff3eacb23e030be1f347b57bf3f4e4d598862b78c1a50e44a5747047e54c9098db0061710d646bf92e3a7eda64681aa8d81b561ea0936bd583af21e4d8445659620dd2854bed41ac21831d2a1e3051156c7455547ec14676ce18b01735fdbcc6957d59d8ef19a6d4569c69754c03bfced6dad8126111561a1e138b00aa1b4463a3de0ddb917a4ba0470e6b59f56735ffc0d74f81f2c6b52f9d084f3bc3bbaa161e23ad336288cf0ba216004970864391b672af08eb479c90f0580d69a8c530e06e452e3b82228919e8091a31279cc33c255114411c1ef9397133951460fd4b021d0639a58e8e7fc1b2e345d976709eab21e2a1a6c5d89039b8c92f460fd062c79dcdfb6e201590176b07dcd87b635dc8d20e0b53d813c156fdb82241885a8d56c61c12099963a3d79e78c347eda861794ab629bdf868fb3c20f6482562cd0288a2301b5fa2885a9d7400eaef13377576c857063b4508d26e197ed76743feefe7f36c0954a9be1f3432519be82331019794fe79e0cc5c41f95aecb382a37dcc6808d5c0c2b15819c38a7832489997cfd49c5bfb2fea538b2cb477eba982ea92832f517ea5b1205410be2e64bf4f344eedb3c4e9da8acc7e0d14073aca044d1481ab33c8f6eb9488d8f8f84c692f5c38efa5c55926147d35849a07b536cd3a9671520973f93af2df361006a3f0e872e73400953d637c50418ab007daa5ba6c542214d31ae560912c8221fc9982f4c5780e18d7876c331d96768f57b532360b170b0bbde9757dff7b107731b93502c6215b688a5c9b3879094c9d25aa12a167336c261f838805cb87d1e029dcf875607bff9b40092d103c3cfb1efea6b1cf5b9a23471c821c2ee36f0c94aeafd705e960d9dda0dd0645e3e7fe2d241f77507bc4822f0adb35e9cbdabf6631324947ee7c95e3c2411982a2a106c3a8852f789c4fc24c04381f32476e1de6ff81e40c67bd7fd4ebd31d19aacdf3b0b32d75cbc3e02e12bb98671898b61a9ff28deb0ed0824c07da8eafdca88f9bc0eebfdf404f156b8cdb01ce594e8aacd863f915652efc3a531faeaf4c01ce0809d3713402c61f44be73907a2ede699da85c14642e47c6599a2f85dd16fa118e24a99dfc2cf1ea8a0a0d18533a020a64865e555294a1557f72376058f4e9316552a84d194546c4de9a4b9dfc43f3196dc250a6bbb950a93f1acb0fcaecfa36e69635ae14123456a1f4de871796ff6c2f835063cbe5a9f9689bd7b0d2947f9c884750570471f0e5b40de49de69ce2f78841bef25dcb31430a8d33acb06b4a8271002f45cb3b8589160c62e596701792602cd73bba7ed1caa3d9dcadbf6f74cbe6b1fa7ca3e5353293e8be62b1879780e78325aea55e57f57225da05ecca12d88f42a875629eb8c5ab1575240116eb5373119827d32d21ac2127080ff8680d08b1aa308f7763b0467887e7972fc68d5e963a4e8c2499f763ebdaa6bbd018560a8a7182265ed0e63de9a767da84bdb4b9a5f40ec5795b4f82b9202bc2bafc0db78fd01b70da30370d979869daecae6ffe9284500942c7cbbc329cc2222e917ec9bc02a1c977677980d8960f22bd87a3c4506ec984b011e7ea4c1965761d133ca78047c2911ecf3883cb63cd87486e6351c0fecf0b9f12f2bb4363d9a1aacd1ce290baff1a717be093dc6f16b9da5b3076305b3dae16f7133d2b4d4a095c9a3f17741628c4e00e03f6c5b5dc2218dfea61b1b8967d10e64f6906e5ac8d76e78cd3baa410e4e5725900064539db4f97d97a54eab26e3094432c8392e163aa00dde417205b0716950509f3ca5fbe30b749358a8d81376784d212be939d58f0eaecc1fc72e4e8e106c518377377b1480c18ae080a57278b109740c6cabc0867d727fd4421f55674cacc374534db8a0a9aab28dc5d97cf74d668aeb05e6854756901ed5f67eef8666ad56e62be56000cfe1fcc154cbdff2412332e95d6e49a29d65e536c1783c2f8fd9b8408651dcf82976e4cc43989876c7e68a5181892e43533f9798cb66a89f5610f8d6b353068c8ee63034cc4d2781efc4c32bb5147962a438c3c6a2ef6162d69507ae21febbf6ff642810d75f166172286acc3efcad1ccc5ea12b9b92ac1f9dbff80e295c569145fee9cfd21ff45eb0507d01418003f1d9ec68d3023d550b86c09b26f080852317c6627d20593a54d69c404265364bdf9c236bcee1d50d2f7bb8a5b768420a022bed90624bdbcd632b4ba40fa33e1c45977f984b1e2eb129bd1dbbe08f3f28c9ce9aec246a07c6d087c7f43b84bb3f7aeca02359a0045df9a57e9b49392401341237d21f328d2a47394d81dfc6176125dfd1a7c7c2746d8630a357b70004820442dff579aa79a0aa7a9eb3d4cc8b4d11db98cda7ae643ba4adb71c144cb9e414ba56d94db1409aa5243bd458f020709e641283de35c756b5986cbeaa334a300af04992240cbe6b63cc69938dd624a8daa979f58ef1d8569f533d9b4206d89badd64a267295050504f5d594f9360fab37e5b6041a65547e5631d4b7c05a6e9eb8b1e77d24bd756f3c87d0a1642f74f9911d0e794dbc5172b2276b4744ca15d7a7a79036bf4eabd97450bee066c27030a11e23099a85418932d6008e2b45ff530d1e86fbeab618551614d06962ab095122ec89197f44f4358a7c7ecd7d4670ff363211eca6b000cffbff2a9ccc8991c5e50d63349c376ffd2239ccb187a2348c61c606f5f562246c165dab76950c10f42e7ab5a53c92bfb10d7f1e7b7fff2ff3bcbdf6b52b1fbf481131605b9b27989050cad0bf70d9faf1cb754c3698cb36d666f9de335f99c435d4631eabf49c59059352820d5e1d5de5f3b7e2008a958fcb121d5125ffec968b201a25fa8129ed975e813079e084e7dd59d3d882025cd956b175d22c8ade3d07ab4683dbe49219184fe0defffc64b93c5bd34ed702358406d1a562aa98df6148965611220d97dced6e0604a87c89d8244fb44bbfbca002415f7bae9215b0cbcb11218ac14ec0aac270012090c6b24f1bc32dcb4a6dbd6231e3f8c9c03f6a14e6e15b17d4672808024c24602504804582433a42101a5fe302e683d0e6bc69da35aedb3ec849685bee54c0052f5af737fc02c8e16eb70cbc85b410293bae808ef1e48b69e02ee26ea7f1e3a00907329156662c21f50ef38ab1963e404119cd383e07fa1a89aa2cd644ca03ed935798e22d69716859f45f3e390145e137eb9739933ee4735a679dcff82a88aa15b1584230b9bc0ab67e6738408ce522418dcd9ea62f11b3359a1f3c92b414d0b1abb3c49e068555c94a85eb6f6c55b610499a91980b474c54c6024a1fff93ef36f56068459f153139f20aac1da9695962f97eff551c4525e5ef8c24fede9f5378b9410c6b9a431b874fd4bd6dea50bce2c12bfbf2ca5a702e763188617ba8a75ff18f3a4d1403032143415d7dd9bd175404dcbc50e46fbad50459e50235077857c47e4fbed7d4b4b8670ec5fcc46d72e3196a9de442ac6b87a3eec51a68392cd1deb9bb6868410797f3e0154b79343e04ac9effa459270355e517b9271610c48c23563b945c9db2539e8e74a2c07fa968e1a9626c1a5ee598f574fd8834ae84124dbda7a949caba590bf6eb51789967f8c860fb66d5d82423dd23bde1825433cd91794a55516f3f4847af24842f58307bd74f8b4d80f0aac6c8e87399305c8356d2b6bfc73e84cfdef379891c354355086279fd2309b25d2267bcd68c28479551fb4eb4e739dc62d4636f3ffbd5365916044d97367170e5d477d4606608f7991e8e692c37d55e243e6ed963f95195f0fa4c9dff146935871cb122c8cbe6c895810ea2d100f872a9d23f85524684e39d255229ae13e1991390c80faa968cd5b00fd03540839407a86339e58a8c222ddca17440ddd76420c92ffbf8f21d192aa8cd1e27fdcd5c5d3f560a30b276f8c319761e3ee303ca509f2fd9a4ed250445efe4779e1a5ec2ba090604f6403d68d09bb11f3d6c663046ad5b69e1aceb720b13763dcca2b0da01be045ebab71f06bb574b4022531b65c4366c90b5665fbdd9348ea4a3ed846a9b4c83bf1ea7db09f76abb5bb8d1196a1655bb0653bcb87aa30670b56b662db626a298d223058fd6e615e44b99535e15fce84282efa1586c018471f9579e6da02f032da669502b76cb6aa149cee7ea402ea284dee6c14fcb670f4cc52b3e8746fd9fe02bfce3f7a7682b142c298e10f724d8d10605f40bed1e282075e073907f7ca69c07eb69dd4a3463de07a31341f4e4c589d26cb80819bbf1b48603831c4a9726b7ababccd3c7e00d2d7ef49ab56ec9cd9624ccd1111acf3e199b3060b676853560ba4b54e8ed6ec6289b0750ba8cc67340662a0945fbdcfd4b94fbb1b5447d9423b420dc21c4ab8d820cb3ecb2f187984ce12b9dda983d2f5465a288dc43dada225736a0a31e3baa3af80d52ed5c4fd52b6b5bf891e647515e5fface58d8090f828842c32ac986dcf49978e74b822eee28c5eecfa31a4741821346cbf39ad84810684f3a452fcf2c6fa21d37c9ed7acc071590c9561f8633237f91a740ee0852c82fbc0e47b879c6009f06a66948d48ce9cd366a256783cdf5d05129c8ccbc071b731db5687dc34a50b28980e0dd7fd44f23f3485c4f04a7c03c1f01a9585654db1603257dd4a6dcc7a9302492d54a76fc6feb1aec8a1fce22eb1bab1f16d2bab10a8d52497555ca028c6ca294057df1387ea38039f4682980325cc9e7caa43182c0a0ec79352177c72089c53ecf089deb1f74be9209ec75454dc5d799cf52e2f52b3cb270bc889ccd4c2b253035a4e616291ad6394a385718adb8855488d3a61aa0d8f6280e321986994360e7664e6f99ee6a35ec2b28216080fca7155149a9c761abdeeeb0a9cb926d502a58b9b6cffa94cffb125a523536f3b35c9c023bd29ee0bde168d3aa061a2b1038febb9f7880bf11c9f7e40418e70b6ce0a5cba7d8649bbcec9d2a033496bd815be88fd3e14b98a2e9e617218ea40a4ca39bc5f176beedd4a2a99c64b5feff82a1809e2c2024c38624f0c680b40ce2cf5ff4015ec7aa764a86439c91843f6a2a9ba8e2c7ca2e02a78547d547eeb1267b34d656f62b3c779a6a261e8bfb1761349313b6457f969069b2d6e3f1b39e439e20a58cc7c46d557b4acc81ace989c1ca68fb78787c4d4aa6fbfd2f657cd2a49cc291466756ef18353a7da4b6c5c34b1dc34bee7105fdcfbe1173335b58ff2fe10fe28c26def338774407a08b2295e545a8005347742804d724a6945035279472071734cba38bb29ba1390e658ce94e522be0dc1a755faaff42dc03049dfff8e52bd190a2c9c859a04fc4e5beb6b855597bac226da87e322edcd08001b585192bc1c4fc5777ba3e9dc491527cb9bcf5d899b6fd70ea9ca1418e640f654431cfada30813c45a643920ceeea6d7a94531f78864b3056e6e2461259cae612d6cf461904afd030b2834112053e559fd3d1d24f4a6a4e074249d6c689026c0edcd0cdc77467639d9eb2f31b77aae1773252448f58c4b46aefb474744f69e7b13d85d90b902b6093da0429d73c7bdd573bcf3fa13b6817ce3d3b41ea6ce046939bd71dc67897367cd4b8d92255645081c0e887bb10b9aa3cc69e1ba66de69a31bf4d2497f4aa50148103d6d270fa8b611d32c310c4582f4b6939fb8065c56f0d2f50cf82315f7cd2225645665311a3f04becdd1b0f9392d55334974f4269a8ab86b524ba179a142127d8d5b4611456d1b4b4b7c30da566ba1d0618f0b946118898d3a12280fa1326a526c57bc175104b538c94ee124307d02d68aa271d1cf8e22f793a5f6a130e946db2cfc8a9b6b8b76e5f030bbce055dd306ff9fc99740be41a9310b0bd2c003c1daaf0686bc793e759f5546ec6c1b69d622b697a52ae9db464de22b1f35784900bbe276859292fb1e8582c10b587c3c38b31162af12c25ab54bec07b806524c3c0dfe264f79ec5505bb16d58a86c7f34c9407bf8c2cd476445fdede1199d98274baa51a4fed59c8897a9d1186f7a4ca10d16300388c901d6d9253967c4451f102060fe3feee86dfe42da4d9fcb9e0e7e0d1314291551006cbb4001d773519ea30a1ef95fc25fb968b4a96c9b140cf2e634ccd1033acf0fae9b40d2d42b33dd9d12158a41b03d6813d7efd1e668b487f6dcd2be95c59cb10c4c2a296d2e784675e0d91e4e827ba75d8aacd3d47934ac479ccfd48318f93dc7f7cd97021c5dacbfcb5e2c606928c258009066a13fb0ad7cd07d8cbba5087d3f23713223cf1187b4e8ab0db566a8bfa401050eb6ec94bad53b5634481944eb0cba11ae06e5dc2e40d89cb679a57abb9c601b50aa71dc9232a4e19f75d63e23f74fa3e8be785e39a51f068d860e78d1c09155ccfee8c19657a55a9020b66541c3f2d27bb604323788c00390cbfef2a22e455d66b80479e2992d856f510b6460cebfd8abf0dfc25a6c1974206678f571a322aca7b2436ece480949866d88ca413614a545e20ed7cdedb54ea8dd4dbb641f1b51cb8e730c6dc791bd51098ef89169f01bff783f21660f492f6b002f7661e550a56998bb9c5e60a80999862356c417f636808597456c129fa586a3d06197f42e6951b60ea07095e8a969308ff7f8800761d489ec4c1dea26e30deb924b27c0c812eb5fb47029963d90825f48215534c3768484de828572ed81f5e921264dddf79ba5db4d358e384d8e53353d58ba67b1fb2b924a81fd954d914276076694597b1476ccd7da54da65b334118521ee1c1412b9fced0bef37f3f9ed7d54717623d569bec80d0e440176ebef00212756a0587a6fba58287c6a453ea81f97536d0e429c3283dd620e013192e6f711ae5324d1d30bcaa5f4e1f97e62705b709dd87b78e2eb45eed79367fde8dca71770e48e276af473bdca499e53587eb33d8dd17d8b98e4f7c94f42f2dd4c4f983afb96ca53f43e7127532a1860a38d2a7a92cf3de69479f30b36048c8d37150dc7b705589665bf2440aa9dc00e867161f0cb9f1ed5b4dbe0491481b07926b089264ca3ed267f70fa10511b046ddfb23bfa5b0ed7f8bc00914b92e62183e6489201f07d42a7dee1116eecf81e8d98ffda8104589efd801534d8105f9f2e5a9139817700bbdc4ea1b455097bf486207e4e7842c0cb0b601efc012444837047c70adbe253976f2f45fc309e358f1dd71cee95d8a62cebd4f5371884277505579a1019a46141a20e6e62e837f40ce500ada119da0c62f78d3121c8f0b7bb3a3c864ff93533db7b1cda7d0d3388ecec53fb8af055c04201c6af3bb1bac4fb95aee72da3a5e4e219dc7e370c6ec65c5050c1b9b4739b55289f16103f06b57dee09abfc8e9a2a3730b1e5964b7aef76ddf7d51e2fa7a75a300bb369b857823289d0b35e1ac89b2aafd3396f15061a1d3c4d1358ba71f7804b3d65bf5a49a08ac535ce80d8800d3402dbab614a129b89c546671a98d812e1852fca22e1ea8761b9270764ce01ca3e9bb0e9c716a2d0e696dc42133732fb83072b5c40d560051f0e3b76e233a47e73544207ad0bc72a416db19e553f667e4e89dc5076a68d06a83970ed8541521685b244908877d2d3c733be1726e06029c4492001f921d5fe2370ec2e4b388ff1fa8935a3bbff1bc9d457f1a04ff206064af872a22765d67f49da880a3ee939c08ae26e03cd95bf47573bfb14dce1782f3289812d9e953609122174a24ee6e900f6705480698d5a8c5bec5a93d1b2b5f4900b618a15fde667a54c1324c942e1747dbed25fd2633058098b5c852c7455362ed32aee8b67764a49e69e68d74672b5444c5a9c1c475f5c36e74a16bcae0dbd03b4ff43c3fd3faa164f80266a4899ab0fa9c7d1eb2f97daa25e70e80937c3a644b14dc3c3735b0b8d15c514eb322daac159e3f042c16fa0c47f0ac1c34ddd742f9f6dec6cd51b6011ab4e9c284da635e4a3f8d7aa8afd2d759fa8623e25b812f5982466e1eaa071582e310bb76837f7b9dd92a2a8c6293e35423bf30c3975a4ec0c23a7f1108fec47052f43abf8c5d90e3688e0161a3420df27ca64aa3800501a4d3e42dccb5524dc4f31a72a5292a9ab61bc0854d48d924e61b5e610458c66dbdea49304a4ac474937cc4d01dcf5774a49d0bbe4c16bd6d0f915c8cd076671c518b844cf8a03de7365d5cf3c847ffda5bb259365ca0633d0d96325a6d06f408764078e7cd717c30431f189b0158705f528008cf998d81b3dd3afa080528ba7fdb55080087628c6337553531ed15ff24fef1797a99fa3c9ebf3e6092624819765c0dc8b252ac46237eb318f3765968ab9b503075925bffd810dfe727337ba0a3d42bc3819ef70be76338e07ca93bb9a1c14333036fe699ca26e23b5a3e3371e0a839f4c969dd9f8472ce3d84c37baf6010c27d03cfbd41bb1aa3130487554dbe98ec88a1c6f34166bf5ec9cfa5822a42f026c51cbffb51b976be441f95360929a54e55151727dd58a6921b1add6a1cc9e4e6a998998a798869495a08019346e628449257e9851cf6cf043314c32144f801c13fc1ec83e775c652ea2012298e762965791a011d8d8381f52d4047c28c5ca718b3145cbb20d2bfd22616064c01ce3ee0b07b4a9d9f7b9381cc9f521d4e46538123fb9d383a9983d21800990458760d083902641c1c1346d700c07e9f1a2ed1aa9829f71b31113e6bf9fd9a96a61375de8123d3bf070cf1fc615b0ab4c166552722f0c6d3686528834c148bd667f66f9a9d2c351492a0f4c65e005d1f18ccd41446eb40efcab4eea623990cd14738f151977246df3cde180f9823a879193613637da85f9b068089f633ba6c254328db5848a12e79c03c292b49820d999101f35ae2f0a33f88536169a5b696b9b632168350a95937c2dbf361c66b9545bed407ea86b167ab3a3aac284401af5ec16ce9231661f051d2137f10af40e3b8cb3ca0f590bfe2d78f02eb124b10effb9c71e0640a062f547d54015d1f64ce1d8f812abad555f6a7fe04ab7be6353ab85da1782de0c568a41b47abfb71feb2735527580b15b09aa46148cd5aac9fa925fac6249566ed58bcda1edc9224474e6ad59a1bbd685b67252e7b3804eb8f27f1c83b908824f907c865705e2c4065fa235c411925d0b0905efc8ef975ec2e7778ae90388d0e8d984cfcf0aa80910301feedbbc17b69c7f84a81c4808a68fe3da429b8fd488f35df24c04546d52aefac7b6114c7736907207e9b4015a99df0630b18d9db064febe0263e911140fdb9ac9cc60622e4abe5d374d0d9d664ec183e3235055d863d7a0ae742807991bd1670f714653bb984dd482d5a16c4b22d5020c64b52401bef191fdff216bf81dfc9f2ede97d54e0531cc84531b745ae905643c3da2c88129b025354a73c056818d4d89765c923bfde193b1f93c506581a1242e8315642c6a7b6297374e16e3425490dfb4c6df2078c4c1c97d38f008af31f69f6811761881ee5f1885f5d77182be07e15e0325998c1322bc4dfad88d293d4a9b2227a3413b046b8191d40e289a87fb92328464db97844fbb3f3b439c91eef980509154a81faf7bfc143e4b0815501e6722b04c31dd3c929ade0615268c47811896af0bc57764b7d75c80ed92af50bcc3d92933e49605586a02012f0bdec0344c1d60dc85921e0db45617a4b2b7b706f4eed273092e7b872fdc92940a63d1f53d0d04b775a7142f7389c5ae91d617dd1dcf4fb81afef5027845ff00eb288ecf47bc74afb0d7728adc68160fd892f517bb7c79ebaf602e7e2a19953ec65d4aa6d678276e89eff17bdf35fd7a9d9f31c95716137469a2271fbc955cbc7d2c95170e761d26d288a0440d55002de3e2a8a337aa73829126524d4c2b9d20e20a404b64bf5ab7dc00d957c90f56fe6008d51202eb699a7be50782887ba1afc2bd715adcf8ee3c2ebe0d412bc8916bd92030d16f3f7a8f316f2c11de518f91c05bfeb1f0d7a785d221113f3d4480fd21e27cc90d610a482a88bad141ed925d632390ff94824e588ed33721bab1fa82333dd3afa0ed028fe26ae27bf2c26568eb0d59233dc8270318d40e458d60c148e781774d087b3828b68c613b208c3a5bf86201b11188cb4a9fb9a050c1418f36c3bc721e71bd6963b4e1440704a821cd2c07c9333f11675bde8c7613a93b079737575bf94e1fdca6342a1fbff2539675f666a9487b74eb784738858da46cd9eaef03b1943827d72d36e91ca0162ab68aa3c6d3443e053d3466aa3778fe424056cd3b3a7a8b153a244ebd4408148cd045ebf3a4ea098915f15aec228b6e20324e464eb498e9602a5ebf373de7e4323e25c545c0c96821f9bde8a2a42483a3f4bee955ad0731168a7e1e1cbb8da88b11a5663678c259784a4bccc0b0099cac12b5686d76379794d1882f7d17b6ec0a955b2e8b38fd93abf7a22697befb8505e9960500d01199b45302b164727bb611234851378d3e7e651160131db8c45fd9c77001f128f6158adb22f539ea50f610762bc1301fa0d8e33e91f48fefce621f3628637d8a7d424e5633212883cce3ef06936bb2777690ca2059ee46c7a9807cbd8619fa2f9492507c51f2b5ae37d1c65533917861c3e50d1bfeb143d956b5e871261a9b6b73933e2ce9ff56e96ff6094ebe65e2026c1fbd815b405b0d871867934a2a8d5eb59d2b763c302e48951ec696352928a2f45b74cd64b17ff5a0a4fb8056fe52da40e6253e9d17d21df2a862642ce9dd1476ee481c3816b48780f10b0ca6b0d35386a5147e92422f408c499b3351df92216e70e0c25f9bc181272a0cbcdf1784e29fbc6b74c8e8b12b4e0414062ff420b7aac8d6682ed2c30011b8184665e3edfdd1c09e469f0dd7c99f719864cd390b70fe5173d646b31388d9807cd56c4e1734f992bdce2537eafad224fa6608e40baeded287d40177e65f1fc206b47bdde239439738cbfbf2a272e8bb1e94f46682bf64a5a29c49a86342dc735a1d5febd67b70815711c62c1604048cd85afde70797b218459f1800fe36b84545863df2a88155a33c14c4af006c7ea4adccb04cc75a301a5499530f059e19124ee9a70fa3908a3d097ff094a0c913be7d363c14325d21fb2657932f9cffb6d3fc6b1017685404c7977610b1f2be33788eff2a5c2870d604350fc23d67d5a094a7095e62de7c4e39158be7c3531b0d3aef47a767905bdb22bfa75a4a1c8f7c6fddc41a4c7761371908848afbe02af8b6e94a434f8f8d7bf82a85d6a73636dcfcc3f6fcbdd3d68243aa6d138969770d53d4ebdff70b82ea9e8d54003d8cc9f4a2eb0e5b2533d5255153ef5c542c59154e3839b4932902e86c23407f020236f0f3cdcf0460b77943ce0ecde5f7880a1ee077682a6a6f5935b68df223cf36e106f621624a7faafaa33dd2a4a02b1e64e4efc0d8721b26b2143da9fa69d5c9426eb7f13902282a9c9c8a8106177f4103fcaaac7db2b33e97934ecf71eb7362824048724e622f09639adcc922182d32c5a6a1352a23a8b74d74958cd598c99603e17e19160a41be92329841d67574ceb67695bb5c3cb5d5d084c7a952de0c08b5d95425330b2b954ec0380bafcc6a63f1499f6d96753c61c0c889b6bd5a496340900404364352865b48b99956d4a2da9d924804c9fd6a4cea182a51905bca7d0d0d9f88cd9b899677d42e5bf11c8126d19b7ff8b32a1e3192b439e643e0136758ce463255f5073b8ad8ca30d26583c408fc79851e4ee30751a91df327be8540126b833ad6438eea507360f8db16b2bddf844c537e70ff951229531557ae4c4945f637dc6797c418201a1a75cb66b713a01b1b9fecc193309fdcdf49346dd3021433e0e94eb5e0617b301949979a5d6c6f3aa8a3906410de5ca1bb1c6f527078fb24bbac40c306119dfdb194eb245432456db035e84b7cafa61c2b6a730bc8063d0ff34e85e0ff28a68589c4d95cd319581306b6cafccc8e7f317da836db24140d8611d8210299716bd80db1f6529635467941f57cffde2a19c90216c4ea1415056640575e63d9039782538cf4e7804e05183915c71b39b2523edaf1c9b1952b0da0c12dc272c00a2e1d5c3ce36ad10f96c5885731de483220a448c34a279ae35baa6dfd021db2f99ec011c003cff309918b83db88b98501d3e63de5a46d9df044b0d0cd40a8853c2333ca2f6f6fb4576f4f1c89a8ec5fa31b4735b3e9f503c0abefbd75eee0150ad2ffbdaaef4cf6de9486f01451f071f1569693c02a266d847e16ac962716a8391cdd62538627a2d1f148cbce2c6a3a69b74545357e68fc6956faf790a24f346296229df9314030410618c76ee4e321703c9cbc68cef6db3b00a485d11d1573dda91a1fbb81a0caa011e7e06432acda2c0ad414220f88a9977e560ff657b0e504e7f795a46f3b2e5a173b9c7d04746b9610c1c11499dc20b65cc23b7f2e707d2b10a74484ce72060844528507bbcafdf491608fd548faf6c369ee73baf234e51be2b1ce707446d7b6e0f7594c431187df7c375074f82e32cae2b66d6209bbd81d949c3324af5a0cf550aa395eea523ef198edc598af10d45e6a1018e739b21842dc7c4c019fd09a4e14e422b815c2a6812fe250db26ad0ec565490fdf4b7bd74e79f344970c7b5358af19475eecd612d5f5423775fffa210dc23650e4b4a2056426da90a3570149fc988983c09a259dc8d9e6ac7dae62878beff94a33a09f25509b38175223bb673b50310359fe7c6b1a5461a0231da9b51a34a72c42bca2251cc045bc96176f9e43bcf2563c0b55244496685acd0e106f67027915054d7031091ae9b8f5c85a04d02d421fe42b70a5a0d8adf29a59d11deca19298f40029cb8f14f53b401a5436219e3b94c60fbc07133cf39e6473ea0dc04f41c171262f9508332e8739af308987debed14ce6994bcb1a327875220fef07c71a6a970f608b0e0e064d0f0fe51c93856fb6bd81037ab853eda998d8309206108a8a80889f6eeb1d25e412419e20bd8dd25e19bdbe0ab220d461823e21ea518f7bdb797e88874b62b7ca737dac6c0b5499ac3965df32c385f3dce287ba958c3c2bd1fc8415a2db2d613eaf881a622ab2af77bb98967c9625ccbdfc3850ff573d94bee216017a762a4b3638d2376389705ee3a4e863e45db804d13ef8c61d41a089e7aae2d6f77dc856a1b9558c66bbca744645ad2e0204ae3f72d7c86b18405cafc02026b84e41a24fbb100c3392ca4ee302ee542061b95d80bb09ea0bbb9bbd6590cbb1bf14afc250c2d5c44004a986d7a1f257364bc3e5826a16794e81c461c256879a97505bbf718e5ffd2c0fb709d9907548459ce1000ccc991d314b9a7062952b166343539630bb02c7ecb396aa82225a5231ed9e2d2feb6c290638ac58972e0a77cac97ddb4c970343d5471542cacf91b3999097bfa958d5a70ccac23dff4f48192c65ab6995d95239ca256150059f46c7c62e4b590f0b5bd5cd4929689fcc01d769326c587ad76ad48754c749c5b0ac1757f877206fefaf961fb64e78578b1711a6618338c61a593ae2989480d280dc1f78e39b03c1e1ac12dbe8d6e733fc0bd06feda803e9de3e2e28518b7bbb00801058f76877172b73bc7320024a2d09dd92a8637482993e9a9cefb1f1e4ac168dbbbd5b7e1c7739259deaf5bc215dc171d985fefae17cfed8192f0de2a6e857ab43383b76888efa5fa8b1b7f73afe793a1ef4c8fc2069f1851f91785a95dd47acc5e2297aba46ce20fd8558500d2f515ae66e9a3091edea43913709b7bcf7a961e267ec18ccfba6488b1eb4c4e959578706f9a58fd8ee09999829c2444dc8644e0526d91b15cc1535ddaa6ded9a80021619070197fa9f6c08b3fbcd375df1b185ea358b6da935104646c739e0ff835427f85b9f5253c8cb7103b98a5b08cf897cd6062445e844ac02492a3aa371e3d3cba45d5cdc9843ca59d11a65897ca3fbc1cf97ae88df8f5215b58cdfa45ae1992aca6985d3ea712e92c89ce110ba19637f3a364a2863ea39fda748380d9b6afc7f4a0b549fe331d152228e436b671af40aff1eab7f055fd6ceeaa8904842ce1830e0a5e5cd999c094530e8eae52796e9717839fce6b58f1f45f1070baca94bc73e538b80634f028baed2a5ca56a7b11d80f31e1ca3b6860492a20b204fdeafe8b7118cf7558156b93b5fb0e093dad16dec812a9125c1ccf254feb76afbbbaf167c3268104ccd30f424c40914488a7ae9f4181f877c048805a9bb5f96474a24122122b61c1066e89d8afa1995a30760306d764ba8d74bd1041c163db24562d6ae963e93365d64da2e6bf1ef7bd0217a08a56577a0b122b887916e82e6c869280b095461218ea3ce9a04dfe6103ee5ccf3a1b2c8405808fd80c20b2351636862e43c25ae32d5d9c83b551ed902034138705e653c3d2cd6444b3a55a0368ad71d3dbe349161ec9f3653233957cccfbcd17f714a4a4cb11177b23b789fe4281820ce4b4aef651bed69e93116c744a8c242837ffb09f6a271997f3f8f54cbfa1310cb85f343d58b407359228351eb47ae8e4f6f8e0ec58040cbc7299c3cb7aa5086e4dc4108ce3139ae89c2702ccd5ba294c19113a0e076d8555a1abfee8b9c0b41bceedbabb5dd0be0131f34b7ecd2c692bf82a8f24a2c492cd480f0d186f63c5aa83cff68bf84151a091e3a8f07df20b0cb65f06e28ce6c8c118c6254006a986e71d17265c3268b710fd6e485a885eb840c02e451e3985e3ec148e9bc67e831e1042d81a9b48e6b84340e5127c7e2079953565d80bb2f40078b11f41ac47c538d3d77ede56ab34c5bb2e8e52617b5c813130320a5881470307ba80e085468ea2717d10ff20fcf69973a8c518385d3ecc51f7d2f603b60a1a3b261608c125ad1f61f723e0d17191e5ae38e3a31200288c72f3fe327bf22837a2a5f5991398f2cad318fb66a871dd793d6efde59471f284d45775707a2addd421f2253f87c494b891e714ec6c891c547ea8339621c082525993555abbfc534860c63496e1ac2aa7fec9c304462988a983d771b673cecfa0745ee5e21278a7ea1223a6c0d9b54123c8ce2635bb8417b04e022ded0ebfb391e3add7f8104e6777af59c2a544465d8f673f661b19d3c9975a8301b23b8b02f34ab8d2c12d4dab22c49385056c5ba9c456967878fe6a3fd2d42abcb061395425d6aecfd83beae2cca850da5f222872b62529c727d13ce20d108bce9a022303ecb2543721915511a0175ecd05f24e3718ae05e498d4d3b5685da68d23030d75a60f8db481cf5c909810c1492f53a85261a041d95e3e98cea7d50546610aa7d10b0c039a20ec9305f50b8d7c4aa46a008da8a241633995a29f115335fa8b224d2465352e7f34ebeea5c84ccd5ec608ba2973b719c00d0cc6a29fb95b757a05decf1afa4a35d46c0ade1a25fc3df2522254493e27d57b479b75babe1f6447ee87549a5e6f501e017295a692a780de8f16cf76b3c58521bd666288a58e7c5029c4f9db37474df5ff87a82243149c26e8ec330b581106a6a18814b15bee4d17a6a1e9b515a47bac084f88ccf27ccd9170b7f2e9f6380446f25e17642ede1f39a15664ccf332b0f15d84af6633b70a46586ea51de408cbc0242aa32cd4865624c3afe6c1f79f42ce4b40242d3fb12e065f5b03ecec6966aed9f61b7571b3671c69290e7e7b84fe2e98669713ca1392f5ed53417bdbd34d2ca437ac2b4b189e2841687ac313e77bc3ec5a7df639f313a80a296a9bfb9164b97ea13f74b00fe8dedebbf24c0698066c1aeecbfc975f8a493003879e5a7354a822b66711e58ab9b12e3e7f5617aa61b237e27e1d07444e0af303381edda70775dde22020072e90546ee56bfac224320acff1e94a647a327dd40913788db0725b917fbd18d923ca59a2ff6ed74d50de2d6d80c5fac4b364caca6bd351a7f09c784cffa9f8f429291d8b017920491d7314f1636e641b5372800b3ce3968a984c8c883698c038fce8a15ecbb22bba587b5760b1267e042436beb068642ac6dda7564bbdfaea96fdac725c5cb14be356156adc1c94c5e3098f5a75cd8d489d87986a78bb35163d6760ef868c0b1730ab1d85e54ab3c7590ecf315fbd683f827f08b4cb79ea69cc8973598846c7d40f76b24c04ef7727630de9116183dd0724ff3f763e8f11b330398f49283f781320782d132ad4ce10b6c577b3d48e970355eb4ccb3ac7749108df3f7ab48903890d322be6a6f03a14a34d3715abe7a62e4299316efba5be1a0dc809fa88d63ff05816dc58c31f70152e70b4275095cde2d52a443fd28493736da6e7f20f943fa69c827aa4d749780838425394c018d1fac4f5f69a91db067988fdc2a02a57c84a42e414ec1597683431b43efadb77369e31992ec6bc736377bcbc2460e53f2b5a4a01f0097cb1ee916a84b771a22128347688bf7f37fb50f87ed34b385d2d7e2784b837ac47d996393eb9908f82e400458fd45b7d35ca8e3d8b65bb6eb22910fe2b45aec34534c892e749326f460663e1888d30b4688260f6331e4628328116f182b033688f3b70b6515707afb691e3bcaf4f092fae638c8c93b7247beb9c045cbc577756218b1483c5cd014d2ce30ec854d0d33d03080306edff8b1283cc6d7d9081db5a2ba9584a60b8aad7f0e713276def27b65dc05ca9328e23a45be21537f12afccf1a5b942616b4428b8339f8e7c887dbb389574534881fee7a67981334af69c205484bc01677ad64f71e4fb69d3ce3013482c95c10977e4350b039e5e1f1f079976a2565ef0c4a4e03da3113c522b2910484d056f9b1f85098dd6b90ec7988c203e49e0780b1a7a8d7d656a9e9b5df36399a63cf616440e507fd03d098d278353e6b53fc1afe2513b1b21215944973d8471a7b1aa04dff848f2fc96cad1c79574f2a5241d928bd9a9633b9e432b2beed48b65cd05d1aab120e4ec7ea62268a750a7535816812f805381debac066d83f1c861d4d8547667a6608c6ee4fe5d181e30678b0da1343d3662a2493089a256a0fbe431f9f0d32211bf8401fe6e7a3f60e863c58a894ac90325e11ab926481505132a54ff73c069b179be8b6236bc6c3ea978416bc06348e53ac22d56d48d85b4d0140e93b7b024423d95e5a9bcf72004a5a5eea02fb4080d5e14c6ae7487006a7eb2736fd5f7ea6eaa0e94adf99ff6fb9da51454ae83c07fbae72567771108763aa4c37a5940e6b17fceab02bc4ff60b766a4a8587fed24f9b893a9c15fc7cd011bce38c439a2360037af81c79d0ed68184ca2faedd49f34a13c1a45c3deb20c1d5b2ae4aab48d38d4a03349ad13e06f7ad2186180974304105402128711dea068e1dbc0fd544c694082b31c8c0e04988af02fed1dde6645b064efe91d446466c3c8db1149512e88f867c7676c2c66c1caa7d93faf38874f0b4aed845bdd5704ff4c823fcee31cc92dba7c0c28e6b909991722812c6f0554aea33673618178fe8201ec729d44e85c1b951b4aaa769a126b2f61ece8a3b6664adc7c28517858e7fcc9396d30e64439aa482c164ccc88b6d5c2d57eec578dc659b5e8e31faf092cda3e6710bc0387a9b53ec9374a243d19d9316891545e46de6fb86adc101733b978968ce3e64cb4a05db89041ae12d51425193b77bebee2becf55bf20fcc902e0374d0478a3c9679e0e590d9f9edc7f03543e0484310990e1c068d47ffb8b24c61f756b1b104c90d451ca258779a6ce3ad1e3c2337e56421ba707c517da876c9eb32108574e7188a97aa395c9b497d97b397b2f1e5461a13c0f8af7edc174c1d897224de98914b20a3916457894b3a5a5ffdf99cc3250969722c36c08f2f41728b99053cf6972f5bfeabb50af145b555ce58028b7ae3f2f1ac21a14300a4ceee6b9042599b490cabae92bb8062401ae5a7a957ce22e0b92a74f7952f7d24caea4cc14ab0fe689e133812b2f281b1c561195973318eb37e8b8f263b15e534a298253f6c8873b01a42c7b9c82139cc3cf90b4acd82f8bed666f7ceea2f6db3b20368dacd983126350671c77867f75c82c30aa5f7efb9e58b748b1dd0998cafa92112da099d0155acd75c7aefd7acd7528cb86c0d88d596c99601731c1759f9531f6f487b6abf59653bb334e6721323d745c8d1b32e0dacdc3a8623b4a640e6a57566efa57879f49542bb9c4fac678f70bbb0ea044c023b286d35cf53f6e5ae78caa19051ae01cc8ee8d13860d0795782ea893841352fc89cdfc12b1bae0921d443c16c25c93b723148760ae4919e07c7da105a10604a78eacaa190bac33ca45a53f0f4bb3e0db18bb450010b2b8a55e384c5e150c828cda05022c54f0416db9a43213f528f3143ba979cf0d05d8d197d6c2bcba1905a9a1e35ea14f4b4098ac08487f2b009bcb7a0b7c49170ca7f96af4cdf55caea57870f85387a360403771e118310f9a8d94b58f446668db9eab69f3dfb488886426a0960924c8129a0174332314f482df6f56028a42e0458ab6c2d9547c497b9d64254195b2e358e0ac05945f36e6464c6d7492d46810143217d9de953d98a6c1e9e8ee622e24cec0914494d337346e9230269d4528b9421fad0b09bad502a7f26ca1eece3904795750cd7f3ff6e789e05faaf34ecc0e0bd534302159845af059abb906988c1d4fc7388905928825718262db775368dac171c58de7b6dd5c23e149e89a6bb0cc8f000f1d7fcd8d1da2b2abfe0ce6b804b773e52bfa0964107db6e9a9dbc342509c35dd48fd56d8fbf6c31f4f2ceff7865e90e9748c734802ed1b3175b064e77de92bfca694720d02817dc8725494df71dc9adc603f613f2c870ed7fa1f964e4327a39ec53f0db7f9d77871a4e6863d0adbe9b1cbdc778fc72500363edb5394bc63cf2d4710dcf86d39d07576d3ed2dd2a1b9181cd9eb649334b29e0d7f2d0f34f4af83d6db3fa0a8bf1d90394a3c1e512f06cc46ce84284f05d795824d06aa11fcda5a82db4ff2c6cda808e62fc52ca61c12ae596e1c5d4e490fb9373207b0ec6d12606ee9df5f766dfc4f1e427cae6bf87137c3544d3c0442aef9777c4b631fcda00ef16c2cdcaf4f9e8d6216258ef5f03445d2a3471df84072930d097a1810a00718713342fc2d8ba98188e2411ae0eec27492a581a602e3e75a711effda37a6472ffd49d2e55b4f3b33e4d3ac11cc69c9f7d7ea1aae1c02ed758d05acba9e8c603d5f5ce16c55db22cdb9d1df637b5080e394cf4a1addb47558a93a3e53fbff28a84b0969ebad34d69c9dbbf6fb1fb66e66626b366e07019bc795bef7e6450b8b2bffdf43fc6485061cbd16ac6a8085e4383d479320adc64c90d52133b52244fa377c719387885e8a11b107de80d4749f8879bf33cd20be3023ced67a9c47905965c4160a9d59d76da92e4290b004c1d7ba4e50e10f30c416680ac924fa5d35ec7c3482cab2822b9f9cfa40802144e83173bc9b39c88e0fe70638417874ac74218ed899a756703bc918f0c6cb4b4eed4f79909b8a0cfafe5168623a2e464287d6740a6ba119d8c189fa5b2cb555600aee9aab929011d5523fad06e0009784f90fef1dab8eed4a32b2c138030301388bb7a6f28aa25cf9fe8435daa062f497b689132398c4e8d009998d88495b7ab2536e691012fad8a622b6d4483355180bf20dbd3029d3a8c79ba0180281fea6e0123a07ca86bc0e8b49c555f46eec8d213cd513eb4bfc141e6bb5cc4c1f99303e5431574ead9f28e3732693323b5dd523bb189eb18a492605bf26d316e2ccc2007d158478925b7b3a31e0747c296a7e15a6e17787042e041f01b2815de9800171dcac686488f0d7953c56689c88232c15783edf4f0722f51d24df9c86e67a187f2a16e157c8a86bcf4ab36bd0be4741ede879cbce9c0601a5b66a4adee73401a0992658405e8fac686a3a440b85eff6148cff57fa508a9c5cf0a372c24f2561ff48aca315fd448af7765efac9ee089dac8c061c8ad4be927e4425474df56be80b4fa8f86d9fb2ef691b07dc39472e6379d2e1844b154750265f2b973c608f73c2dc8821d03c39a4e0707cc3a17332dd3e0a1678dae9857d891ace681501a5dc481e362c3b502341e9eeddd273c98b3cc26db599e031239cf805e9b691ae1988c8678f10158dc1fb1f1785f9fe1e4c9ffa70398ebbc8ade24cfb498cbc4231a67d22f1c48c26ceedc13bb3cbba0c059fbfd2a39011ad08c42438595afde459a9aa553677411d37df7eeb675bf6f6cb01ccda0f90c445db20e0eb46c61a99963428dc4cdc5d246b01a6f485ba3165e80f01489c44eb362da34bb054e891c1d98ee4a60dfb28f4f4debb4cf5e3032f69ca1c17de22feafeac06df49c8f66e7c68bb6fb682b478a308af9195c23af463277895942552f644037fa143586d3ed3caf4efe5b25ab1f893cf4f7e719250075a3e905e866fc39a60db46af3da8ac9a83c441291e84bb0bf9b4a9e57ee8f25d2ae57b3091e667debc6a5bfc16b27371be30d5223fafc5b9ba39f17c525ef014f36952cacdd0f1f2cb5081961f6fb49296bbc05ebcf3fcba2cd54a0629184b18f0a693a96bc80baacc1fcd3f7f11af368136e415ce8c114e117ee63037ae26f2fbb6f9a336d1155eb2313b6e9d3d165c9c028700d2f0b443eb2fb1a00454081ffb6e5893bc1a7b6cd60d2614f495b7ce5f1f89c153d3169d5eb01cf956b4ff47587e64e74dfeb7d12c36e915fda3c80c5d85aa6c645114888046a10a73eecfb93df8fe5597a7eb6630ad1e995bf34b257eaaccaf79b82070ba424afc6a80d62751fc87e79a7f8f18607338c099fc401ce2e8c0b8043c886e70b1707d6acf9a6fcb9e27cdcb32e6ec182b59901d03c502ef8c176f93a5f851ad826685c8ebd503b0c00eac56445722fd8a6cd615b719ee22ca883fd597302823f2b09a39f705aea87be3074ceaee4ab0f46b8987b7274c5086e219ee8764dcdf01603da48ee560e274163bbf4e1c184927a63d92bb2c602eace7d5bac8842e4ca6fbae24904996a099d0e6ad445b0f8efec9f151096d93084bbd421007b3143e1da808a082ea6c94a5034c84ef388a65204789770e1e881ba48665c0216c41af3a9e445470828271d10951bf96ae4a46f006bd85b03dc686979f773714b26479216b6380a7a25ec46758c110b1625caa0267fde8950f14891d7f8ff851fbf685e511b8bcab2af0ff7d0766c0eea038446eb040cdab07f3cae82762f51b704c328b5ad6129e6e04434298cfffe9b1f1802fb306006745a2a27c126f839cf8d1f8eba21652425b744f47abc4aeac2d094d77254f1cc79ec3397358251399a267a858616dacd053018477b54c624b853fb3cabad7a63b34fcd28f819c0792b8a9ca1fd78fa91136532c21798856bfcc976ad09cd02525f41c8fe2357502b619210aeef3656eb27d710d2e2e50a812d271e9d25aa1d535367f6846130a411428a1d1ac5c4604ea21740990d0acd8051317564204c538187c90bd3f0f5e55c19d6ef359d891c40721768e0fda29af0faa0b20348fe6a74812da73f4d56def620370990f0a99a4d7f32f472258e10dde116d65a9db89014706b6c3cd3bec6207dfcf6249c4878366f58610e39f7db2e87665a5e2c2df5d8ef06c1032b9d15bc77f3019b4334a46f506a5fa8b94d4fde7f592ba476d5ee98ab6c0838e87631001a216e447c9a75a83da8b85d0e555940a20f2ced0135c1417598c0f21efd998564c2d7743c8c790e321d69ab33a9ba427b82a2c62110f54feb35935c772064be802382a0cb0987ca21f215048a4ea0cc82366664df336f30acc4ba2c0b1ebb6b26a447d251905879d5bd4aad4446fa218ca758dc8cd40195f8815b8d019019f917d3263cf4552e894fc3f63123a197473ef58b47256e6d57a2dbfd5362cace1f7057aed7a77d9a6fcea6bb5e0f600f31a83ac140411ee920153edc7f30010e73d114fb65e9204910ebed95a8588b5627fbca88c20facaa13c05f886a8083865a1367f277b7aa469c3b0644db41d8751c5cb2d329f00df6680fc65cde1962bd8331d540caa663ffa3aa4aa94d26e468572c8032b58465c83440ef5ab3eaa38522b4497cd4777113e9940ccd201f4621d63fee188bac658d1368e77a44d8242a1602af5fc0fbfc3748fa8bcf35c6f8b4c11641bee3f35405cd216b8f70b55cb773c173b9ffd24402d6ca58386d4f93948e0a67797c81a1a94dd30528f264e71d82e1e876e8a8a46361c50d5959faac019503ca5b9936123ce0fa18f322fda5e0626e5cfa5550a185050ba6ef44eec3a6d2b2e0f1a6e039f7899e306994ca12961348959b7ecab591624f0cd7eb768d1933ccd0828bdb4c8b41defbeb4b096aa0f25b83fa4a052eac990dd8c5d538088b92dd00552f5ed2b2e72c90182eec20b3cd417598c0f617967424e6e5e0c836d68357d50a48fb63e325996d66dfa0d1b70e16203b1c2e251c3580607cfc28cc56343a21c8d55e3265841e7b10eaf086ae46ff6b36f30427e38498c25d7168f799c87f0034fed71ac90857ec0dd691516f64380511ea8f1aadb67d547650c707ba3a60355e2b86b9a58fae30a2595143815670f66600c0555d932f6b89ff5ac8d007f4a1ca415d645500fc7c65e6f3fc115fc5739462449b7ec72a7bdeadc5dd1ced91f44ffa034af4f3795f386536797d79575e7fbc8912e7af731d562ae21ed186ca55a92e52f538927225e9008aac2972ac102627bf6201a40c2721b28271f94aa8a983f14effde20f8edaaeceaa50c410a59f50a21014f410b0f9a67d371ecc0bce26adff0d34712a5a9494af115c4fdb2915b31c124118ea29703f98abe92a69147e41e150ce7519d44fd5094e9acc5e0040f19cd8c135b5075c63572086d6c483299d05aadd8aa09a830e1fab37341a02c7735446701762730176e34b2052ec997763565b2fa8e0ae4df344d7dc4af2014a2c5c2a003f4eb0a7f49368647843be1f64e7897a2b6741db79a2f7ef141903c49978c4742f7ae2e874ab7ad15a98f21bc6f37d87cd879ab52e9ffaaf5d0af8732bba559481f4dd102a61e5941d348d3b9ffbea406d440b6f60809be705832ab15d77016910886b6cbf869b405daf68df4509efd9bebd713541f4a00e7c0d8900baa1f669fbf333118a9ea709dd42420580e8c8e13576041eb61a12d58d428369d2ff73924a7f7a6c2a21cee3724a5f1dd4b6f63fdfb37048ec8f3e9cf78b438344052e9783956ac3239a6c46a93d19511c7d7ae7c86958229142b37016fb712c0e6437715654c4507cadd4dc00eaebb87f1216efdb186422e0b7ec10e44688c62cf97a9b8f326d4809a8b45173ca9ccc81ed2e0244defe75209c36ab0ce48fbe902488b57f73ecdfe2f09ea49e6def608247e3d82f88321bdcdf6f48c77740ac91460a376fbc653a15aa9d1c9a82ceed9031de4dd0620dbb309909594a4af804ae36feb1608905b1c0e2fa5c230376c660cb58edc4a0e052c21aae4b4aac76d380f525689d49a51cff5dffefe28ab45d7d71d24929138d2dbc27dca23324779319b29a4faafd334c19fc240cad297447b2e07662a268fca141143dc8ff9ad52704a2a45926bf5c216c5b26fac5ae898e2d038814c84ff5372d7b6cc9a61a26a01a5acd58de0628538f741bb34cc11a500c6bf25c18de8e0ad6df1d4e2288a7438eaa9ec971eb2bd716f23cd5d97d732f50a4137c9748102e55526bce55233cbc714a10d0de36e41fb5987debf164c814fb10dcc40fa0067eabeac6f23993ef6a14e6d28621ca706e2093ed53de8928b892622db3694f762124f6f246768a298c87171379c1f3a69a8b43c2e52425aa5eb97c721ff2ebac5dfc826243ff994b556bda97b216ffe5bd3d6a4c03775e434777fe3da7b6ae9fd13e67f40ff46788b0c404c7ae72c189c61dde35a836880943466f9fe5b369fbbeae7d04e143d10faa1537e08e4ddac747bd50d4836f13fd27fc5437d94db84e9548fa02c2ca0208a03c11b7138f710a4f7730dee2d7c615caa22bfe6a49053755abbc61ee8af5880c0d8270d5de40a218b17285f54e234b5ec9ca19836d15ea0fba200dc4f14a86d9c2771b0afb3bf0f175d935ac604e4ec7ae792740523c5fe941bd812610077e3a7e853d09184b5b40e1421788cedafd4b2d85456032488385945a26f574406c20ff59f9732e236826120831ce0e309de3ef42b2a4f6df7363dd467a4af83591c22a2891b435d96a38c1f40ad659f931d4a09101714e91ddfc7c8ea0c32699de3e87683e9617f3a3021e5dd9b21cb6064cc28d798e0cede66a257a07cb4bea84987e658ea917b0e7ce461f6877dc1b6fe972e73e96db4a6c445c91bdecb92280b3aec871106cb47189980a45c0fb31344dd988f656464643822ca0de350c4c3a614828625043af381fb0c32806b301216a3f3aa50617d004d5ec51527e55446ddd0b553bd78d69467d11a2aea64323a7ead19b01bf2350e2fc892630e0a5138003bd0ab5a1e0fd763c307b3bd7d1e9a3e8eaef7313bf41ab5696a3c7f1effe18d20d7c478b95f5aa5700fadc9b3db372afe90ec20b249f9e3c2d159cd4c7e7f6850290289e19e19b7d7285736ae48043604fcf20865236ba7909ed697918acc2d4bca5035dfdd2e0881b75e0d68bc2c1f1971ca832784b255ce8cf9a72a670019663c57c9a3d173a3b80e445fe75632ae1b549f8287b33c9819fdf63062117e0402482c54c305899accca720f894c1a5bd243af5741dc8b94cb85e6f8bc4894f80032d17e6f6354fc1c85d022afa633f1b704a126f91945c003ce2ec44e700e6d4fd0734b0f60db460f6cead3069a0be84ea4cc746d6e8cdf0852511a61134816824fb9f5496b4970ca7d55ab15d4bf671ce78d6712e7113e2b0c327536c7edd227156c29eb57983e0e9c060af807e444beb2ad72438b682f2b43b0f033b51850043c9fbdebf7ec6f91b25b43c7b5e58d6939589d356346fc76fe64e93b07c3a4b2ae139e0887bfc36aefd07ba430010f9a3196bf0764d047ca19032cbcd82d0045780bede7d6cbd0350a9ff5a04f4a0203d03fdac86712ca72b6bf5aaecfa39f32132bb0c176512eda521678c3721b1d044ead9613330fb21e7f7dfda6763ea981cf2c493db30d9248dc58e22e75b9676878c9ce5b9a2ba67e726acebf0c8b795c3c8953e25c50a2858b59cfc4a532624e75076c1be1cc919d691bcc7f9dffe4f238f505b0633c9b9ad608d92af53f4b7789d5f6e96aea1efff7a73edb38ffaf57158b45b724e842cfa0253325581b14742e54476aa3a47d780cccd5b290a507a5b1f10a97eefae8319e2216514915d328b6d2c49fd806cd642dda9af5c513de434062fcb3ca55ac2532cf9f70ccb2d6042f7db829f702d61588b491942565b69dd04b69840acd60fd25127048e50ae84df3be74a32fa03c464e5626b13f663e82c0512c73381b617d14fb9255a441b0bbde8043652df63f4daf97d6bdd6328ad84791b62b0e0d3414407f92c3c55a7755086e653b70357021d756a30a3395df4fae3e2cb1aafa1dd798e73a5d9f05d36ebccbe1d7d33b064a763dbc1bac64da68a261ece80383b86354ba87e88dec5a82e2f1dfe578df742e97a259941aa9b002aaa0855d3e2bf9c476a82a50963a806bdffa61a8ebcd4dfb56be5e04715a24250ea3cca5a90dc6e6ba3feb528ae666a254e4161586bf61669ba8e143cad9a0151cb9a131c84f444a91cab3d0b85719a51f0d218bf6533a2c87224b1e3cc48accd3a5f72cb2192113227f23579865035cff88f5b788ae53d8d4624b83410d7f6b80c4ec7064093cdd523ee6a5c591fe49445df2bfee2553417c41d10a347c887486bb35e047bee4b21488586ca0899c1f2cbfb8b14e95b79c350093988fd57f3050463434713458a6f68c954b51c434ceddbcaf5b84be21ba25688fc599a061a1bdd8fa511baec0d45ce0c8850d61a8c332d06df5289e3661603aa76813b77424d479160641bacfc419fb18619206f3a863764af1362ad0894c60d964bbc3824d838910ff0c27448117ea5d8875539420c00de01184c3aaeca8b12a9908ae21357d82bab6e5f755df7c5d12be13f4eb7f562e1de08053b2d5744c0ba3515099d3b5e3884c0f03d5bc56ccdcb8511a19e70da6c312023ac8456517f1c06411f29580a0cd502329ecd1a7308a316cff52fc920b1f50c2fcea82a21aa271a5dea8befbb6416ba3376ca2fa12bbe34136d9335b4e15cd26b78a61f2cf2292c3f6b8a2f0331705537f16723f4b4e2e83b1ea594a5032177926932d346a09dc6b32b5a91e919102e0d18f75b8a6b799a680c0e02d712099a2b4d624f4b935f364027678ab2de4dced236476961ac352fdec986e67018fc4de69c5ee363f35d25f7bf83b9ace77943c35bd5d6b0e32f552547452f1bbd4e29b69421dbc75159a57cc16a34902a1d53ead827a24a5c20c130c6b222b91e42b223b3541a310709da563183c3dcfc9c8f840cae29e4a155b18f7f48371d1bb3b5b768f6338f378f6c663b347d1137234f33b4a04502a43fe56f3664d6d86f8eeba156c0b9f6fd987baff62f305f783f4d05c5a626a72960973b11d420d7acc2ce491f0f7d50bc48fff50c386fd953ab1017a679e4ed0da5974e6c15addae85530bec2de92690c728515be9746edc82dbb92a7fe438e2f50c688525ca7520270b17d6951417e8a3a1765f51df93f4562eed022ad36618ea314926bd10832839b46f959c4de808f4316ef0c655cee518f5b2a665ce53e4f858a218c08a6e3e6e6be8e188f6cfff560480eaae6b143451ebb122a6dfa98bd438858a4a32a07f340bc42324fb5e9c87b650fd2e19f9fb8ecd92653a6ca0bf272d8b3cc4577314936dd3c5feece140e52655899428581d1235a3bcfb67cb93e447d5e6917b1faf00cbab18b44d385aeeca2192047fa463b8cd82c125d21e599c4c70764cedfc8b2400f8e3b9b64afa9dfbfbf8001977776c7b5ec116f6ae81a1bb2e05b03e1f75c79313d412e9e79a862f4cdea7ac2c855395eb334e5a00a02bce94fdd2a4f39211c924c051efe72a6151b6fb2ae52594dcea3c90d0c0f9a733bf1c4634ea9898c947c0ba6fc7481250c9dc1b71f90f89ca56a12eaea4bca1d046435d83133205504c036233468206467927b7967e8a57f33fdfa6e0dbfb6619e9702dfb20d6c41382b392963c53d1cd07ae3e3f5ec56414e105557248edc64ee785f658f5d3152fd7f8f589748c480bdc52b915ddf1eb2825980d213ac8bbab3dbd3abb52f78f4609286c0230f1a449a1712077558f3815f7a2854a211bbed700f3465666e1689f5f1d8793fcad02d26fcff82582624a9619a1b61c8a3cedaa317559075ae13596ae51ea1db25c3fd1e1a45bb4c0b6318ff928bb57c091e26faed108c235d8542c47fc13f8745a7a4ca1ef2798e4db3f78f8b449300b8bee186b977e723033b023dee63a0f858e685595df29e69f37c2de27b7fed69f67855a506584d2ccad613f3c7de1b649ecc3eda4af98927afc1f3d4b791e9e136c0e27565af161a21476dd38c06ac569fdd346e19f5680e03f7d9bf3c87ca6cce4bb5e4a9616b3551937e6af51b4f93061f43244877d03ed3113f7e4249c0e1a3778a76a916328f24ec4cbbf98488e369178e86a1d162c6b35e3b0c77107e7a761d147dfdd4877f13c2840b10a0ac6c496a6cfaf23f1ceb44de84d951a078c35e8ccf0c73de4a77fcdfd97de4d733c792866cd7710a750ec7586b57d3e86cb4310f7cd548237ed577d6241ce2817bf7bfe50e33a14b0b3c1c168dca4143e5fae1117a354d06c21b07d2e439207f191ac9ffcb218d83bcbbf70c876c54d9a18ddc2bf61e30ca04113321c9f3304d54913e093909474bf2914792b8b55224d290db0b31a0a5d7b3bf702c1626114e794e34f59a2c988a5debc8f4e8540cae869bf1e7fca4fafbc690e4711ff7e5b82eedf282700f60cd00891a9ae4024eb4b0f1ee4be18373efcaca07fabf3bb7e2c3ef6ace9fe80ab7c56b58b940bfead14e79f1515af00b942307866d82e89748deb01bf84dab9f237cc3a2829635b3fef1bf8735164915f9be45ad0a1ed657c904073c74cc0da1733b682b0994fb44f7b018f990cb497410ec95b83858f05f3ba7907c217e49f2eebe8b86493296d0765a76198590cd78a71664c9fff26a732b9455bb5d3b520091421f8f4a517d9b14ff7485eb8696fe820491d09014ec7114472ad4c1198ac4fa16a5208942f8504b668c641ad19e14b895b22f449ee19f8acfb011091a964ce0a8e880227f4774b3b1e0ba512a23ce44d55534bede3846515f91454761520c5c8062500da6d511b986b3a3178c4e9160d155924f9998b2b8f3aac3844b9c1f38fbb1cde4841075381f7369fe74fcbf2a71fbf4f080d93531cb33c52d30a0c498e47d6e2fa348e118a9f10d379525a5e231c0313894630f6ba6f7fc76756aed2e4fb92838ed78e8c3cd136aac03fe9a359024d299e58c1085b7210e747e170e4484f9283aa029d839ee46ef29881981d5601cf2fc5faf5a1db8b170b912531a159539d9218a8c938797218ee20fa6ec79b154206d940e0f6f81b2bfb7ed6f584494b4687e8c89a03910821d20ec5615c149292198060146f163e4cb89c677db8629337b96eade50046b8308596964c30d6bec96c3ed4096b863ec8ad6154001077ced372a5d460bb8068cc19ebe4d8901764c0c90c4ac6ae037a58c152c00396db2c34d17f3275bd03508c5dc9e37eb4c3acf454b72d61fd6f28323e4cc2cb16038cd9f180773e8d345479ab7c922bfe59237698e616d01b69a06920cc9ecddfe07db12de3ee32bd90007a4650414d39aa64be35b24a4194924163ba18c206e6901d148a68d2a86481095612149d65adc2a5f2190c24ae430cc196902b11d62993f720ad0ab19ba865e96a674045b57c75b2a5ed963d4e1a82bef834482b7b7164a7bd1bb0f21cb2f4cbb23395740c61f7b006268d79399be29ff8b6864149874b414777fbe368a36495e85c7f6cfc5e4bb5c573bdebd830e9df4494098771c3df400ee5b5f857434a1869c145723dcf0c66fb8b95de41edc10b5e8c4856997cc49fec25aeeb4f74b9ae7dcc887c199d26795dc940d1fde95324961ebd38e2b5619fd5ad392ad37e89a8655d54638202923e088d6b64790b5471d0ffda61aa2ae2747691c77259d1a4a5d74a18fa9e3acbc6072651a599a520553d7d7270634e83a9eba6b96a8724fc2f4c10d7fea381d3d62b223319b65efb540a4ce03df0ee8087bf04af25710c38e4aa1340570c146962e0f3ca8bb2a5081154dd5543228c10fba99dc72b37f434eee6ef8d0bb8a62bac06d9f500cf553523bde3666671e3688aac3ce38b33230f9c1f54df4bf502542f10f1113df84b117b9eb13afbf9568b23dd06d702975a880f2b870f12192dec6c8d56841d4492f24985eca4a5bed8313c693762824523a92a3d7a8c5b024aea16fcc013e0e05e9903f403989028bd993590681e10068fe52dcf60fd5b01a63307854d54cc57bc6f5b27d1c1b9701c8125c028e54333c11ca04dec042c16ac85a04ddb1a9b506c819b0679920c8f13fda042c1ad4c78a1e77fb8c98063815379286a485ed18c1221e14fa20f7599c4d9f3be9f5631cd94615559c00daa7759573b8551e30a64045b22d23a09827ca0262fb8af2f4a82fd1533184b0d153587e8160206c96bcd6b7b042a24f8c073eac86ac4b84a1f49ea4f4f10d5fa630df2a8fd5191941c5c506b55379137b1ea2937f973ec8aa3b67694f2642eaea0b929889ed9c0999841bbdff5f239326962d4b27f5b8d06959ccac29d367153a2abe3841b5bb0c564353e612e5565d15fd5da2fe09410455787c459d9fec92e3f302f0fca0802fdcd2cae81af41be336ebc1094cc1acebb75dfdffb6ac20fb5ff111e0af335236b81e5621ed45b1f065f66905ca8c077d635d1a3a7654f08fa7204fff6f9dc79903acdcf1d7c262ef34ae08aaabbeaaa5741f1f8860929e2bfb70a0de7a297782e19fb811acd54c9d72daa74f0c78210cb632264a07202100ef5900c352f2de4c03bb4c7e70f53689b0bedb29cb8440d2139bd880ea15d0752282696f15d9a3092d78b57f08c3df2ca4a6a05ac65a866b7ca41b23f21ae8508c2e693098a6049e383df2578916b21431b969614a30d82d08c71bab9e507bb779d45ce1451a04f8981ca0bc033f0bba2f6dd45cb8bab630b2702e839d05504c272d9ca3904118c00214696f47a98588b71a517b99787c3b253b46f08ca7da10a0bf092bb724c095107c15ca772e6d3a9c5f77e31d48584909218a1b1e80021d724f21ace72f911df9722c3c2294748b4345fd0b0c1798d980429014afef563c07c953570b14a8c1fdae0865ace4fdfae1cd666978ef243ea186e0a4907600e0eae91f1d18b374880de57c6e5d97af899b81d8b06070adab07da1923dc880558dbb60028cfd252e4e6cb12031835bfb1f457d3fbe207b7a74ab487fded86f11bbd0f729d62c2b7c5500aa0bdb30a406d4fc3d4659499bb8d61427923aa1ee0469c07962e3680af083484b06ba1fd1c96896bd0a6e13dfdc0848adb695ca77cb0c67e1ad26864546f8d9eb9c6dd4d6a4466ffa98c46fe4a5664f812eb57aa649ae411be1abec23b3aeee3a936ccdbd083cea2e7dd6b4759185f0a5c8c2a3634e987f44052230f2d4b2c601847ef47a4eaaf918d673b553360a00c205f8c1313b280ea76ee9690f0ef7edc5674ed8f821844fcf368e601836dc995726208b48c08d2a83b6c0dbca1445cc7a9e09cf2f46005e556a8aa02d12034a966407a7f07ee3fff087f07d518434208ac3d045d64ed568cd678c9d9781e72cef6d3d7b96e127e399e10e0d854f6d098429e3f5b774ecc4436a515b4ef4b386705888e862945d540919ab42cbc95cd4f00069233e3946b344e1f6acd929cd00a131267d4522ab315c26930f8a01c534203de3d416bb0100afcc30a1249785dbb2d0444b628aee20961f0fc3f4d8502f913b1799b1a4e6056f81478e1d5050e9579c2e56ab964f68d3a21238091e2a58d30cbedfc1edc744cf5e9de36ae6fe7f0e032fb9ecb4ba1a0218e7b963f178dec91e2d023b9522bf0d5bede8c87ff11dc3ec8baba3924be4141f891ddc7f6a11796a56892a37e2fdfbbe1bb7a05c40751f2a4696774d212e637de1c65bc142b4e82601c5de3c44cd65acfb15f7e9a2e993e560db8cde9a6185926b808f36a7341286e6d5393ae509c8e7609b9ffbee244af804ef71fcb66c53fdf6dd9eb59cf1a2cadc394e855443622bc0927475cbd7e2fbf6ba17c2712da1e6f9918575cc69816148e5c0cd4683d3ffed26eb98dc5036057422057004c0800de554d1d215e23abd22a5257829918ef7e8972ec265a00f78580ef6655db6e1da8743b9743632b8aebc483ed8ec0c109ca13b05263f151d5eceb6d2283bbd783f8f597a562262e70bc0bcc17d8d1c6a55c56de223b02d84736db8790b144a0471be800d2039a12df95de8bdf2402757ff70db91d74dbf8a5845a8bb13b50eb3eee017793fc2ba808ab9fb0aae42665bdc3c1172350d19004915eaa9045387c87967682ed04c4cc81b158ae0efc688453db34ce04e0101eee7d96fcb05e897ceab9966a11544f8d88e90e0992881b8ce7995175953b46fb33944ab8ad2ce04b7250014f247c641b78f819ac3c9312a21c186b23bf0d93b19c040518eefa41dc7279183826d1f6d16eae03f403a6760b68ddff2dc859b3bd84f6c4dba8d9155c3da9e9d5193bbc2456c1da58fab2ab36bc7b008213466e34cecae6371ee02fcdf498c1a57d62d82d82bc3b606085c5f86ef0e747185f41f5a1fe6057995b3d3139d0bc68d8cf8064ad09d0415ecc1ccd5224d2c564c79f896ca0eb051816bd0bb9589db9ad1247986978dd6818141763f40964b71a154ba7e3f1644684357f816d186a3e539dfac9b3404918220841831ddf22a9797d94fa497441b3e9f96602ee90d4c2f282b3a32bcdb438dbd3d4e3775917014bee14ccef425d0d0317074b26cb606d241d78dadc963907d9f51d0ff39ca6a073dbaa72f9fc8e34b1336d6e45d6eff64f67227916c6652ec75610b069d667f5bc646c3a8d6bc4d12ad69b1796417e7d91db88f4ee390eaad11cda231f6806af643224c60ab2334d51cf848af6acd59aa349196eee6d1a56308047fc6851971306ac3aef58a5e23d67e517e171b740c2490ea4637256b4d4df846bf0a09280d9e9c81ee772c147530d90f354985e4ef5feafa9ca0907ce2c158da9d9acaa50a6361665de31ca6e346efe6b69e48638535e6bc21a2a70c0f880ed23d6214da0a79e905a7fc52abcd86394543951c21d3cf3f652f85349df0e579d8d8b1b54840134df416d26bc306728f61a6d6a63e9923baeca7e031a70ef1c6265a562f24b9ed2b8b3e2f0127ff2ea8baf19c8f630cf3bedad4eb01a291d7af7678b0548a06755478884393c8eaa15543ce9d09d74462f358b8c828631ffe8252dcfef60e5adaee242d0c84243c4382c19cce3e4ed17e6e55ad906a6fc5e29123d9e4a2bd82a3ed221df2f5867eb0bdb526fd4e072b1bf4762e04b918708e1186b3a223723625bf837f7c41f6c7cbdaad844a0deaaa33fef2c74a3befb6566031da42b8ee5d63716f5336adedc53967809c385e07a9234751bb8000cea819fc2aed8c2a87ef853ec880d4cea7bfc19734c48adab738818c1987c38a6dd17c1c1934539620d562368c2c5f285e020588726348256f0a9c3cf2b84b1debae955a45d50af0b18ead1be91d228fade73180670887aeb66260d09ae9670902c4066f31b916b40cfaa52bd5d9274f77cf40d394ba7755befc586bb05aaba596447edf4e58ca99b54338484fa6e1761be09e19a4490c62c8885dd4095aa622372741d8767fe2b7b53e8018b09b49e4cc93b6c07faa8acdc27284a90ba7b2bb1162e7440190928d8248c23015e16b7600d56de7d3074a0cc2f2b4265faa91ba5d8eb0785914e8ab1e0b4b9c1c91e10d0426b2080e4628a2466ebe2b3890e14a6d0ecd9bb14c647bb6f70a09a1864c916a6e862b3f759267afb6f6a9639c1cb5981eb7770a646bd34d1c10616ecd6b1dd3420bdf2e5e07a05d7c15609488013a0335017669ef433b8f7ba556b9127cdf7e5ccae2b1ca8316f3e64d3c2116dfa649578080a51a7e915ff2aa06efa77fd0f4f00ec22cf8860c76a454bc16177a28fda735b3d3b9290beeba32fd663d043deae32c5ba8195c1c884d1f8700ddb1062e3d912a3d2ac8267d66c181c7e6fe665760b5142babf6c66026aa0592146022a21e1803a11b993541d74e98cf92cee85166946e5de2f4d8788da62094f881ba0d0721a9531988958557550529d979a5d3041a53d37a0d734a805532f7bd7ee190dff9cf361798e166a52cd1632fd06f2fb99369a96caa7d87e80d5917f36b9bde66ff458ae4bd7017fabdcf497aab457e9d9adfadd6140f518ee5e22ca634d597823a7547377f836356045886d0873834da805ba406a04706344b97ab5f5d4429e8e8a9ba8e101d8b2d1212447342badec09c8d12282daafcbef32b14c34af472158f96b35ddc60aa0e9e4436521b1bbcd6a4e9157cfc4aa9e32ca007224c8a8306a320b37c74e8e71babf156b5aa7145c438af1942ef4c1ecef4991dc78cc14a93b295a75abbbe4d394be4fa1543f71f9a7f0e2d4d98a036a4a0f54284541d96f28412151722207df04694d777dce93256b231d91de95e3ff562fc1cb8f0cae7af586a3e53dd1398aa8d51ad385d8900a684d4501aaf12ae3696b94100513cc46a5229f84a3f34b2e22fa2f7bdf51a8aa292b86a4dd1d91148baceefe7a9c02b7696052832b2e23912d8ff7457f9eeff6e5d17fc5c9df154ca0d2bc801e5a69573ccf61653c2fa111a07118ac14e0caa707cdb7416d944e59844d1c41199e4d46b02e09930dd5c0d9a7cb7b6488c816a8af1ac4076e11a9ebf82fc9e5d8fc1be1f723887f081c56aa508d996daa61c066f3465ae64130572b1ee9a7faa091b6b2ec2600c95a3a8c0c55b3892f1ef567d9fd8bce9cf753e35af6b64c9ffa12e9edb80af921cb56047087c7d61c19ccf1b7c763801cdbf9cac29c0bd6413f1189c446de317695b89f637ad13f6c8e369eac181099b3850afa2f07c854ede60df4a393c22833b9f1e34c094a6b8eeaba3a109fda7525632c3fda713fcf9d8e0e853e9d33b48e8fe64bb888a3d7f20c7c13019f5997f5f80be74e84f83538504570e7a78e74aa5f9f423eb8d70c93dcced447dc64eeb3d74ea94838ed384b6d37df5be9c5f3a58e8dc2f7e8a2bcbca9fbbd8ad9cb422d6f22194a3c928b0ae8fb2893b47848bf5e9330a037efb72109c65a08e65e8eea1962a2971f00d00fb41b1d185749f67f9548735797f9d5844101afe7960019414643dbd2ed946649de44f3d40c496fa9a5e2b57caf47442694b4cdf73df2a75b43bd4ce862eb7c39a48ee11b6d2b2c0675d1bd5444bdd8ad09b455052e2d840c0d52201e594d077568dab518de80654bf9d29b55e281e45a0ccbaea68caa4c97e90950cc6de5fc1458fa600c0dfb64be5bdef45dbaea1d72ad7317f90b3c323ebf6e851b10eea732504bb2f7eeb6e5de5bca9452d10ce60cce0cad4804f76ef17c8109911369224c25575dd4228ac20a3dd6798c780d5f2fe22cc92d8bac3f134d1487a6103aada089e42bda788ebf878169c8f6c1a18cc10cf6f64e13bd08d9db442db0fe4d7443734322eec75d54708cffe4be7b127843d26fa0a54da389d80737b9caf38d686302411063fc25830d12b9ac9482bd4dd454c4146d215cef010eac5f9f81f50ebcde024f81f5be038ef9db042b633d70183301dbb707cb2fc15b01db37037788eda883adb839f43f90f57f59d25489cfc974588c46084dca314c3e567f7890f597d00be0ef6d81decfe4bf84ed694107374b48a9d314fa2ef308f4a652ae2570449c30bd129fe3e2f9e5e9fcaeacd113df3473538ee37a87689691b0b4f6b3471fc751cc271c273a29382753fa384e4ff34f15d516f374e69baa8b4abd00cedc09bc944d7f99721ded276b64741a3e8868cb8f7a8e2bf590bf064f7f42797872d353afe1bffd9d87ce75a5d44337d54b632f9f4ea6d3e97491b05c3b0814c8ed03f75c959c404e028a3b71dc09c53daa8ee8739a4683c80cfbd30f59fe1f1bde7f25d6ff655297f99f5763fb539f409a8aaa2795d3ab5c69398e034192976364f9f36cb43c9d763edbeef73c9df6e73813c771dce94dd547895538eef426138b3fe138f7a71b84e54bcf72fbc79efef41cf7270ef461fad2f7cb06bf214290e0afff04066920aefae81e09cba813c7cfdd5e622ff7df2976cf414eff3df7b7f40ddefeb1df73aa4f7da3fefe6041813e4cb704a29e6bd58d6df07bee9e2b87e2bc747a06eb650106716b3a81aad2a3fec3c1dfcfa83f7d2b691afd27b0c54fdb9657f16c9cba2f9d502c5a80dc95f6e3388e053d714fe2be21cb994aa5cad66432994ca5ced44aec077eef52bd5755d2a7eacaab54d4b3909ab9559effb20ae8e3f4a6e76277dbaedcdc1f6c83f747c7a08fd3af7cff952b8fc335c0d45f026f5501591ef5df7f6c7ad40de22baa57492b757ad89f022f8dfdde8709bcbd7941749619bc2514eaa7a7833a619625b32c95ede974c2ec495a9695ff39bf93d034da4e1ab7f9f9fd63b9f6beff7eecf7241289e378749fea8ae9717c88ed206e57c04e42fbf0bd4a2dd52b735fecd77da5ffd9d07c3da0f139f0d264daf4fa31f025f430099b1668fc3b6d100b0f7fc2542a89f577496541a4e502f86f2fca1fb15855fdb24117fb292ad029b727687c7635bcd81b3dbe7084995df33ddbc1630db4a7edd7b18307b37cec390ed27a681a0740a08387058610b223a5575a5673e98d9e15e8e0b1e30bf4de4c09cabcb07cb1fecf35a914d5f1629999f6f7e8e6211d444b2ceb0ad40823d65f084f13c7c905eadf554834b98076c431c26b7a3aa1de3cce04e7b1bcda40449cc0de3be2888def4e3c9deb41defeb187405589cfe99743b1f2e77392eb6ddbb86de39c0479774d3713ae815eb6b9cb7d07369087fd6a17f7b75df17d7060bfc0088e6affe6037adbf5f27e35d8af2be5c4be9da0d877bfdaf58522ed84ae2c91ed8722c4defe2cf316208406148bfd5a35c24396d730c243af31031726647b674e178dace91191c5716935697518d0ae19509c12d83b94d4a99d5407b9fa8933d05011e79ea2891a8b37bce672511701a2e58aae6c3f05593991ae6c04595e94ae2cdbf84f57edeaa096edea66718e4a01d6e335572b5a02dbf11a1ecc08b6339f5fee28c83ab6a34d99ab3644a1572beaa915794ddbc68eb8cdf41a1e199171655eb422257627b44becc57666112d89db68453273ce24f6623baec4b23c0627b6e3a1633cd8121e7a74a01c4e61a71127f6623b5ad5a0685368431e46d1883421ad68aeb429d88e5644447fe45190c6c489f8b4ca8fa00c82b7bb47da0d050e7b7ee9d394134f2afc02914f790dc7d59449bb54ec4e3c317aec829d53ac7fc72e1a6965656f5da1066368ea0222b4796a6896bf651028f5281e72f1353f3ef19a1b5bdd4f845e51e0a1c809477106796314660882bdb1880846a4027be5ec96d7f412ec8d4b7aa24d9c31f630185734a03f76fced1de63a670f73ef30dba464b88cbd1cf4d2af659f8a124cfda57f5f1dc81ec329c9813c02d9b318145f2f29af2050e61aa7709bf88a31fe2ff6c65788812f300a7d815e0e8ad2fb52d0c4339d8b4107b17a7aa218e9a07ed25374500fbbac7fd4b4679025c15ea248f49848c463be22f4764fb3d735ccd814ec575e13d4414d2c0104ef2258f7eee119ff0e9a3d086a9e1ed1a67b7a7a847a7a80e8608fe33adad7e8235526912d0f95fc78e8355c42fa740f1070c0c36f200f4318d0cb41e10e0b449b8632a708a7bf8d57085bc9f1cc29ec67590a0bc5d8950320f0908540107b700004cddd91a3120f7f26ed58a8dbdd650079e8a1d7f437141c17ede612a87c0195ef537ab8805e1612d25f37281cdf6963639633ce324fbe16fd330c6430ebe8046e02cf2f9723424da0f6042a1127ba9fc00b7162e377cb969dc3854cb13d81aac4e74c1f2f808f457dac5c123b9ff3e9e3359e4a51da1deb9db1b37bb23cbc32d3c76b1a0c5b46a1d327de49637c17ccb3036fca4e1f39594678389fe3a64ffc79c4c3eee57331fe6475b588480410cd76e0f59e3e1023ac8feefb251b28111ed8bdfc0e0c122d055538a6ed7eda0e2c22da6e70bebf3c12c4c3f9d3a7fbdb2fc1c992d367b286f070fe690e74fa1c993e2c6f8e2f3c3351cfd52b1ff5eee96cdf4e5056fc98c46e7dc4437716d27311bb7d5cf906af8c29d878001b0b60e3cfb00dd67ae119d1c60f598667741f7d6c7caef4ecb14af5888d2f3f62121b1fb561ad89b53cacd5b18c3c6ca5c7f4f71c573c471bd5c71aca30cbafa877baee64b1c41e96aa22bdb42470f4bdf400e33b5a6f4c62298f0fc713593afa794ab7b7fa05f51cc733230f14f662ad9f6893cd49699091d710c714a09c05271cb130bf3d27254b51555510af62400e06bc4e031ec783a8381ef0fdaaaadaf154f5ece938e0d90352a3adea7582781ce7847eb81f8efb69c539299d3eb116c7c315e119673dfb021c87df70b1537b9a2c8f01788e3202f8907593094d6a5d52d665352d0b6a5978cab6a0b6c5b42db41629eb825a17d3feb3dffcb3a7eccfd54cb68aab07541f0f7808fc8e9a4388efe724b0e3ef940058c3ad0422f0b3f5136db82c3c618af59f49a61297d77016a040c4fa4f20b7f9d56ac5448eff64e235cce3fde713286e3381f797400476d407e461f5803cb82050afca7bff803a44fdf085a83e86a81fe363defb2f092abfffce205ef59713b2fea725e8f697fb69a2faa716d0ed75d4d114a3282307d4d1146ec511e176582b0b60e160adfc8d4c5bb1bc0d570d978e0b08f04ed22b00bc94f439422c6f572c8f03b27c02349726141f01ac038097fec0a201de94015c2d7f03ded9f23660cbd78042d3d59aab6833595e006fd1d010e06d8ba6e583b70200de3903de290300f05bb1872b607ecb82138aec002c67c1094a6c7b2a7054d423077a230fbfed17bf81cfa312c978a090033b81ba048ae5eac5b44004662fc7635fec9df56e44ee766403b2fe2cf56e538c88dcd1911190d0dd567763dded6e42a3d5a8aa72c4f4c78057e5ebb30dab2a878a8f065552e5d9d2dbfd8b8741a1580d3c78e204db35f82326b13d7c7b39580d3c78b2c476e00f19db03eaa6d2c850652f6d361ad5ba4d1635d16eaec8ca87fd78e898120f9d85c743ff76b056eb3f1550eea70585a79299c47fae0c8d0cdb2fbfb9b0b859a14409bae2afb7262bdac4391f74d136f2f0b448e2e2a1cb209e2596c5603908064c6c7b9f0455f9adced764d180def8a7bf58ebe37b355caaeabbed0d9751b9d81591f57c7dcc97574602a8fc58b9251f112aff723fd67f3897877ee7d39fac0d05b27a345992dee9537fdce8acf854f556253da5cf71a18794feedff5e05daa0555563f4de7bcf75df9503af8cedef643f4e8c3891a5a54a4b84b4a37a3d19cbf5805c917a85d8953f551f2670f46cbdf5d3fdcafcb6fda5ca4d1605a70fadf388873e5958eb875be235de93c0d8e3a125713fd1865d9ccb0363110fca6c75c7c9eaba5884ab9167f4913581eff7a6402fc763fdbd207a278be57d816e55269432b2a4ec9f40e0293259b3c5038ce09d3f76b22600f69c024714016f8092bf943ab1fea60f65c89024e562e43ed61f9ded5e3cfcfeca273d27a594db7f55957ddbef8504be44195ffb8458f921e96fff8b87de4fc289dd7d3bfb3d8ddfe3c4afcae73afa2f61fcd1d90e4c7968a21e7a330102bdcf92c6797400032b3be80674764fd3cda39d8189f59758cab3f81a68f2d0b128d35e2548848c3309d469220cb8cee1972b836c4bd1b42ccbc02efa619aa2699ac65ccafeca9524caa2c0235772a765fde5125e238b780d8b5dfe3289bffc914bdc336591a8c86b6e1c8a52e214afc9a4d080285e63ca9ce8c425d1884f296a9fc28984ba6824452351f439e2a189271ae9e8df2581244253ef71c8439597ab15273dc712c586ac0b751e7a0612a1fc52c1ba52855c0aebc625d63f32711bdf71e1f1155dd6a38f11eed7dea7c455f6ceddd823572e14893cc6df57b46001faa45cc09b52012f5d018302401ec617c7178cda1fc387a931ef432dc0c71831a674b95c8e19691ffc69c2f053726808a35fd6b5173f53b26a8c359330e83dbfe939ae9992ccc7c3561229e8cd7c3e92f63393348de9d33ef8e935f06247301fcedbe311e3654055bf10999ff900647fb51f2c89c71c993ef34e9f0872a61e7a67cbd44399d4a1a7007516c5986db525e1197fe9021f74812e702ef1f9e3a192a197f7c78c348dec877df07f7939f422875ee4d0cbcba197bff4e5efcc4edcd6e2196dfd25263189c9c75a3c23c98fc7f84f15d77e54b6a2680380f71fadbc6624e31d63a15028d4df9445fda5f639dac8005104a07300604a002073cc0800decacacaca4ad7751d17bbdf5a3ce314d4279079269ebc184f5da3754fc763f9aed152ce71cf06cbcb5ec598d3e94d2f4435f347cc7ce7c8cc54d27b4ed71ca47f000dc0b327448c9779163f656a936aef78333c59cb6b4ea00f158eef6d830cc6cf7cb224a36f90e38af40c5e8f044e9e19bd096ccacf5e0c7a794d04694817fbe02d5d55d8e629380a4b612800689e325bad16bb0c50d906001f5303f397837cf8cbaf2c00537302c7f8df15da4f8c7139d43ef8c3303d176b7c45a0f837ba705cee340d39b4235dc02b6054e6f0ca974be4b7666bb6666bb65cde65de5f7302db4817708cbf0c28e774c97e582f5ebc78f1dfa26a51b5a8541c57f93dd426c233a3f7a1ea8831a387a93c3c1c3d176154168a361698f2525251e848c8e431a3d173ed3c1c7dd7c9332317b9a4696cecc3e847e1c88e46a3d12fb1b2b238894142d1666b798c3feaefa434251477a24d4c613be1953b51caff407fb112a6c6e8784a96654273c8ca969616e619f952eb4c75daccebe71ff1e4d0aaf0021cb82c7fcd63b71a833cf41d21627c74c2eedf07c6e626f4624147301f2c894ff4e1dae2b9c6232daa8b97b5c462b688e88ab576aef4ef30163b01eb65272d5bcb642fc6c29c78175ffa1a5b4a5c5ed3a6d731bd49b6ecef69214001f037b67ca4fc213d2fc61df0ca3791ba3f1ef179cf7bae85ff225114bfe71373efa8b09527678ad1ee51f3519f8d7e45fb16f5f4ccaf612cac8529c192c8e76a7a12e91b547def7de00e4f3ef7931e27b6c4efdbc3219f2920f3315ee58191ff5319b160e6d14b093e8bd133e863a43df78e6510d45ee584630535515256547ce9a15072a21e43a12286ea0e05768f7528f0be4b0dd216d5a8c7502e8fa2ffc3fc7d1f3d1dfa1c479b186f7ace64da11e3c1eb811e0562bcf3c498d17bf53381b7776c5c79148801f24e8c89207d15067dd097f4631ce7c7f17ef6faf4527ed7ebedc41d1b4ddff271bf3cbdec97a4e79cf34e0443625499a21d32608c6f8f5ed3abdeab1789184710d9abf226d2ab90dad2d3633f7ac716d1f6f4286a55f50a19b22adf522f124556e5f45cd76d5ef7b4b6e54c2695bf186bf28ccae3b88e49e5f400781cf76af613638c1b29fbe119eeb65b5ec36d423d76848b1123468c18316464bc1af1e5af68f5cfe95554586ad7fe5d049e6184a6c126d4fb64208efb0af4f6c86b992dc95c199087d98f8fc592587f54650f6794d9aae16d31254d548c07ed83fff4c192602d0f7c51ceb9f1d051dd15a6d8b1d2a23c1c9208450880cad3f9b616cf48290910944409e6620c080bc2b8b796d7dc56b22de916cfc0ac9d2dafe12814e109379a6bc5af2db901edbfdacfa86a3fdb92ada5fd78c8da6aafecd68a36ddea56ab5bda12af69ccc346cce2995310bded2deb4abca6ff76bf861dc17c30568cbf184b6efe2189f11c030c634c2bcc3614788db0a83755afded3ce8eed180f0ae99c18182b46ed68aad99f48df55e547f56248ac3fa36a9068558244ae776cf79c9743930219886c37eda97b19808f5f32b98def2b7635131d835ec1096caf421a8ef17785ccdf92edbb05e07ba6cad418558b6c6aaedac7ca4012c095b8d1889b368c3600008f30418c57a273627c8cf7e74b73b3c309150e6e888df1ecf110322427c6d318335baceeefd923919ebd1a23ebbdf7dff799abe87b12a9664be4dfecc7facf97b29f8875ec1eca745a791594a99a466dbfca4576a55ecce766f6ce5610cbd2e5354d22b594400adecc5e8c65efd69a9699b962b6bd6f623e49d081b162cc090bf46e3fbd2a3d8c3646c55831c62bb6c4c36efbf19a3b5b5b6b6b1db1fe9b128c85f9604a30d6d6b23eb3b855cca7624afc31104be2e10ce89dadadb5fd6c4a6440efdc5ab3d5b2fc02896e48e845b021c888f57726af2028afcf5c960906037afb15242553edd4a7e766e2040d7a618205694c5e2ff6d1600765d9c53e081c792f7f798d877dbfd8fba4737a569dbeedc5ec8fce7a74c796beb68e1f8d788c7678d82fecafbf4eeffde022db75d27addc77df169d589db7b55e31ec749ff7d4f557ec70e0f1db38df3c2aebf06c00a82d2432d65d551ba08e37e6549dc49e6e9989e56d2ca62efd2f5fe9c94be562f66ee57bf883831029d499017c09fbdefcae25d826896056659d4b62e2dafe33dcf50b121a2f24acc9c1468555451458e13fcfe3a4c5f7aae3dee5ba6e54a558687de83f4b837551a19487ac0a12ddfc241a627bc9a128332babf9f20d9f99c17209217e08b491d846cc932933a30b1edd9708b3514eb25afadc00d05cf5c815e76790dc65f7aec6f10cdcab8a1186326acf4a6522643661986d22cf6282f8756451555d0b494bee571bcc5961ec75bea8d879685e5b91631adf72bf5f4a6eaf23652af7a2e7a36b4cf5850efe40294655986c3c2a5f693da4e3c0c6a26a57a8a0285f912101e3af65d4bcf31c06bb0d29f9e3e77aa0cc0a156a0272e76a65a7fa5feab5417dfb5997818e4a193d3bbb703e65f8042542cfec5770e8ce7ba4b7efa1bafb96d398a09fc1b6d0b175fbfbf9946bbda07ffd62cbf890694696e5eaea6d14060bbb0154f9c74508bda4c805ade5bbec1eb364681867ffb2584b4a5d2d30f85a85880395c5e0409b0fd4286e4bcf8235e804a38012401d6e53da77360c0f8233c07c61402e661d02f813e2c33c06b4e3840303d959e4fdf953ed614eb4aa769ddeb2fd5d3b7489b7d0b1d6c576a4bb53d21609ebd1c9aedb64544db9f651f245a6f04c48853cb1df23e9a0230cf3503efecd19f4e2edee3b86784855155d49788687bfbf5427dc852ffc5c31504680fdda313f659dfb61e8377f42f8cb08f13812071aa40da72dbf0dcab6d4f40d4c707b27fcb25af46026c3fd62fbe5f3c57242478f1e205095e7c83484c7004cc2391c39e0e18b086f7985dd1c19e8d6edbc3e33866d9cbbeb6e548956d376d7b36a2d00dafe9c08ff4d2ab31b214fcef2405daf5033ac75ffdea8aacbfa28d8e18e38f03c40d06bfe72864db45df03fd773ccf184dbbb59d93ab9c75f5f66befd76df69e902486e494e0c51f618217af44e7bc0085740e783bf32a9058451555e4c1f6771548dbd69e3bc2042faf44e7bc3c0789764e2f88cee309debe7c82029d7ffdb5793adb47afc6c836d856e01926eeaf7ff1bafd9a1693d63a13b79af6a276bf9e40ffa5aa74bcf817416d059ee917cf3c81627ffbf57ad2dd42af6eea65cf95baf674f831db1c767caebd1c91a37f58a7fe33067da44a1e8e7e0c746179d17eb672ce28e3e760d0c5c308245671532997980da93e0022701febdca6e562e75ad661d2725a97695b37b951b77935a203f1245830348f0a897cce899b9575d6efbe79c7412a823432d8ecd06b5a472a88d3116d6204609da370a3030c4b58ff1d21cd0f3274446f2fe499efd12b2858097613dde14e1a1a3010b1fe3276687a6acf53fb39b59d25786e3cec06657868997f7496a516e8a5e9349a6d0ef472d09006f6144a68b59746686a33ee43e101bd2da46257312803087395266b82f27ced479279821ea8710c4f0c8cb1fd44130ebeda78ac7f6f9b2645d0b659477c982672b6ba72c5fc594fb431b53808073fb6a6595992ec273b12594fd89bb53a1e2025a0d89b2db1fe5864a993adb4224d8a46349fc855b69a4fb0257cc5337cb07eb322b647dfdb4f29292dcaf795ed9d6823c18cc7c36ce56160b6040794ad6c0df6726544b46922ad475b42e3d18a78e8594f56245b225bc92f4cc956d94eb67ae9436fb68adc1dc55e93c9de8c87e50af4a15e83bd04f7ca5eb9923c1e7a878614dd783c27f048b1fe2fab9d224b6cafc47fcf65c0ceef7aabeddeb66d0389ecc4efd58f6abb573b5b6fab4dd35448660e8d31f17b7afb4dd1ed7bb571603589e62cd2b38aac243f7da4b5f51046bc824c8971080fb55987c84083dd57db1fe3e908b4b7ae570d829ff119037f543b27a8c20186a05a2d7301cb66200f8180f4fe3f2cc023da90e28eb74fd3df419d774ee0a2145436c85e1568bb7800050745e18228d6bfeb296d81a8bdf7dcf6838c68811ef507bfbcf95f127af949f7f09ad1065e597b58809f74a91e5e2363fc0db4400f7e02f6989ac64f6e78dc9b29acff0fced2341923502d04221472a331137b136de6bc91344f9ca56134e5a1494811e89dacfe8c67b0f58e4f788040824f780441e135e7a3353014eb2f439a1f42ecf9e5c62ae331fe3409eaccb3b30491293c65d82111a5917f439694416a4e27d6bf4bbdbb8c2e013f7a55e97ba9b24282b7a554d2302c46cccb30ccfb88bd8661d1bb1a96c2c0d46ba954c6d2d86b18cb635d05ba67d49348a8b971dd133fc618238e182be9bd9ae2672e815cf7445406fa407d87ea82605ff628d9c9fb96e445175b8b162c58b8b8a8542d2d2b56a4522c2c28d4e96432adaca8a8944a949248dfe7795dc771a3d166e3667b6e1a6a9b5f42c557f9152ab404de59996728b8c5c81c7610ac47116db3cf401f39beefba1853dfd5398f9f4529df4379dde8496010cc76a91fa150d462df6ba7ef4da35fa9b7873dd9985ca0f1bf20981d3df7d51aff0bc2c7f7547ed6a97c8f0f18a6e861253922535ef381b7f42a4f6a3065ca012dfdf7975a92574bdfaea282a98041305b7acccbe1227a3a2530dcbeabaaeddb6ee08b4f77ab5bc5e178aab6781716e06d16d5a57e47fa9e9a469d75c6de077a605855dcb7e5c097dfa1b77bda27f6c8fea9f9482989b2b0a4f3b07da46cf560610e71488bc3a0c1ce16245954baa40c5a09b14b06957898f0136c8892156553f030616f46b47a820d46b0379b62fde5ab8db8e6cf54325b5b4ff7b8ecd69341f11a0e8a2e9e21ddc68f31f38936ddd3994f16e461e68a319e31c97eb21f7eef4975f6b77b3297f4f19a9a2f7b654e32976451ede5352faf6112e43512036f2f61af745996873d1eb2e8f51e235dcffcb963af64613e4fa03745535b10e702d6136f78597e83e527dce0851b0be506e7f9e5facafae6dd0cf1bd7f8f685372027bee2717dd5ea2a7a727daf49c5a11cff80f99a4d022ca81cf2bda18200a415678d244e815f444e8e6464809fd1a8da847da7e8592bc4e629ecef6dcb671927bc98dc00e9ab699bc6eba89ce7073a372436282bab7837e89f49ce33d05a7d38fe4dddcf8f8ed09c1395f7873c3c11bcebb3870d374c3ec1fdd357f9f3395f2d740e9fefe19c8f2a3d7e9840469a616c6981823381d941f63f8994a333c41d4b2fcb2fcc41b9ed876b99c58ff06baa1038a93ef3b540ee8e5976a7bbe415fe5fd8d88364e68efdf3d5ed3b1767ce40fcff0ab7d78dc78b9a20d0e8ef16ff2f202199e585707f5931bafa0cfb2d247e24aa46fc47131d6694755b5fdb49bcbc5835f3756484cd0f676905ea5f49cf33d8954fa5e3c32d28b877fbcf1dde0f0f0085e16b25fbf5a880bc3cd0d13ebff4367dfefededd03e9bcf39d96be06cfa2959439a6e095e7e82938144d805051a5c4c8064dbee0e5535a2c5f1a673ca1865c2128d17861c188eda8997a1519121bd0c2558fadb1f9f7ee7705d696442f0364823c3367422fb586b448be988369cc34321cf788fd611432befdb1841d38a4ac97b9cd8757b1947230f73ac6082862370aaf9d34e70870e293792c404c56a0f9ed1c1430a41372dc32f1275fea980eef018d921bd8c3eab2dfd577b067b091e4dcbb26c9469d9f66c27a7655af6542431451aa8d446dc489b9dd6652095200d671630977409b1b32ee623a5ff441b95a0240c4405112057117bbd6b0151d1b2d76564ccc759b24716913c45988fb3309fa2255e237d739feb4a32cc77a20de613633c7acb59988f27f19efe67a5582e2c1f25acd8d262b5b0241303dda703a2975213e6dab23097ac78d2dc9b2762020d68c0a0c4facbc0b9e11f31f0c6e86f7c0d088e31375a027103e7d9e502c4b91810373c64577f749008696f489b4dfb227b6a3d674fad3107a20ef4861fcac4a9633259069a031003cd01c8c4a3818183797e81a9a82294f4cd2eaf71a029e8d8c183c83aa98e2c57206d494c57ac505179399003b93c4cd280c8f57b2378064644bbbce67b7d6c0410245696f4b1fbaaf69148aaa7cf1eda20629db3219ec1868f3e0d7711b11e49b53ffbea3e6e87fcd81f2f5693e245ee537a1dd1c6c431a5a6c17ff949e94b4f6bc761292c5d7fc26de9715cfb34161c07b98b6ae6df6ee52fb53289fbf8ac542ff2d0a5cc1dcee3fea4b54c514a29fd996aa52af34c831709ab7d29fe7561bfef35144662a916b0b7f43f5eac76a775f179d7a768efd65b5ea37d128ed56d5af1a17de44b956ada119a7622ca52f48791282d3d7b35481ce7d7fea4e8efc33e6e97872d1f5f4035da66f15faa48625ee3668d5a51cf55d263fd7a6119c6f357a6e12e86f1c245ed4baf06d2b08fb52ddb978a64e761be85ce00139b28c6ef8ff4bf8fd4b1b63809a2b4d496a5b66547d5fbd2f21155e3c32081014d1ef33d4bd5f99e622d44f4fdd742df77cf3105f2d0c5334e7978e833ee1c56165fb26de10cd433bf46bf54bdc8573da50bd40656877c49d370965e62fd431e3a3b3a0a498a9bbe3dd47f3c603c0c2844c56faa4e14c567a505e83e23f6219ef11317e8d0890bf472908eeff374e67f1ecbf7cbdbc031fe9ddbc4bcbc4947fbe0f4811a88f6dfee06fb9b2fde06b6e933b4508c691a4dc496fbef6bd1341049cc16e8ed226722b44917de7358172b6a476f2df1bed8f81cd6d18aa2f42fb55eb5f45d3cbfe018fade3b45757bb45cf4744a319573a267a3c51342888a5fc8901c983f02e63b2784c1de73b8e6c05e0409b01cfe119e130a01e3c307f29ae92e9ec1f2feeca9674f9d52cf4cc38fb40ffea7c7aa8ce7479a06057da8b4674bc1d2bb4cf95d37f6819f63fef0c8e419a635be67791418021aebe37b96f7ef291adbd23333bd3a2c46434bdf5e8d694be0edff34ecbfa7f5eab018f883c61302c6b793e696fe35d89c4bf1ef86f15c4f4ee8f5a166d9fb837ecddc2ed585827d847b9ce852597cac2b5ebb2eacf72eea4d590f0c3a55970f992ce82e162b9ebdee562bf1904baf6925fe1f0cb6b410a031da870a893630305231df43586154181d9687b09a56029bdba754af0e5b8a24540abc345663666606aff6dfe344ad969e3d1c1ac6c2791e97624161242d52138ed1c8d391ff91aa113ce3ef439a17715cf994b853242e117be211ebafed60284658773990d704c07a8b679a9a1bf7a83fb17cf6def3f7f4bfd75e5bf9ee97434345443e85fe57310d54915efb928af4f1e9d75f7ffdf5f737b40daa48e00e8e313aac0eabb9f0731a787fd0705aa755fa1f05603ccc7f34dc0daa4ae00e18200cf8da574b6f62f9c8f2fdfc2db0fe2ac6f2384eebfd1e0359b0403ff0074d8b672f08966fd007cb47d087fcfe1f341ff883c6b2802cdff4236fe504a63c8f6314876a2ef5bd46bfefd7b8140a45c19be26dfbd4b67da9e75295df05a75c3c6af2f7dad561491f23333f07f3421a4f177d596630c27c8f18d3a53a1a8a3630bec41e479bed61c4d0360560401ad307fa9893b432bfb932d4278f85c4278f8504de394fe0a5a99b62c1865c9eeb357de9fb569aebd5b1030608337afe3e980ae3bb5e1d3040fee2b3f88fc20c61d96bfa08fea0b1d474877cd445a576d6954fb55861617a977a75e038d995e7ba4ef3b827d5b6ef4425ed4ba5976e03e361fe9a6cc2bf2eb6f49ddbc480268f317de9b5bab10fa60fabe961aae961d4ce634c5cca4c2b311ec73f8e837986f9ae484800030303f30c030686f6bdf6a65771d10f1abbf226534b6d961124601beadf2bb0de313802c6c38c605413f4f0305589cee9e139959867f0fe78b12abf4205d49eeb010a30d3837d096960feae80f1b76479b38989a9cc2b5e0508f37f3c7a155eb16245a7752a9d272d60f9995f9a5f25abf18db0a4955aaaf7c50256fbaf5e1afbc9bcb0e8681aa587c1d912cc1f61029857a2736050df9bbe549b7d68b03f48724c771cd3cd32342d7d188a6a955aca7ec5fb53bd71f5bd58efb54aaa1d245a1ca7206c41089663ee35eebd37d56957b857e1defbef696828d59e3d1d0dbcfca3b321e8ec0d627d684ffa1bc492bcb3da6da6a5cfd369ca9e6f21085bf0812565f2332f876f21085b386249e08fee8bf9f0efbc142606745708c28001539188170dc59824d67fc710d194a1a0d136bbb8f2294ee4a1bfbb2675599742d32b2132a0f7238e9baef5c235e086977e140c683fb7c7517b833e680bb84ca65cb4acf336ea6187691a877d8cd94c1a8e3ff61d7829076211c3f11603a5363f7a39b4df469ba7b3cda9594cfb344cfbed231837f04535cdd3c9a6267f4e2bb1ce3325321adad9ec3b7b0cab92a5d730775623383fcb6208bec40ccc21b1db59fc8885a0b372c6295c8c16aa08f5b26eae5449dfbdecba5b09cbd0a149c9f891e2f8062cd6e973d2d3994aa612223bac5a1ebad780885925f3672ef19ae8d5c0563c114dab4eea2fe61386410f80c250ba85793630cf466f513025580f9ab69a601a71a349b096f623dfc4a1e9b9761c9a9ed6c9a1c9f4d188c9f437eac0fa33f38ce93b8ebd1caeec277ea49a13b59a4b5ba2fd683f134b82f96047bc084a1063f5d0295f7355f1b3a50d3981e51eb2b20c5ed3e3c49137e36b2eaf89da926fcf8616599c0a2bba8cc05b8b99993d7659ff9997f59709ca9e588f510589b1a24d730ce683b5d8663fd166ce49e96348d8666b29c13a0605ac0ad61f8bc23ad6853158ffad156dbe1853894f27d62713eb13c8fa121478ff04de3092b696ebc6bb68ffa98b774fe79f2b129a8f349857a37e8be7e2eba5a4a24c91320015406794269ac0181c73a3cbb5842514a108400042134d30c184bd93fb4e8f3b3cd3aff8c3c9e7482c2547ea26b9db681ce0946dd98f70f13954911d62d9d3c1214113a553e5efa39fdffbf91b9cfe00ce219284f6d927b1a984d03efb1d1ab8639bd1b381c9e699e699ceb297977f0c7b80f6d967de0e0de434cf01f27d441628684669e6d970950db60d0eb1dcf454d8fb90ef8f812c5050150ef9b26df4f34f0f478355d8e9f9739bb6f977152012728874cd095c0d693279d7512a49427031957271b1e1267bbbe5ff4b2ae5a167235ae7197ee9d9903a882491c4f46c6036f36c78b4914525f44a3b3d1628a87fcadbab31c45207a9e6d9983cdba3c4326dfb3c3288e1c0450b162eaa96152916d4c9a4296145a544499fd771a36d6a192665155218e1555d1cb368efc4fc4bc3f8ed4d63b3f1feb35f25e2040b16a87466e296c3baacba95dcc4aa8ca38f7b8eeb9ce89eeba23777d8273146c0ceccf1be3d2e36c7f8cd7b849da007d21853a7e5eaf49adb5438deca7f2b9d63fa472995169e8915d3bc9f158907728c8936abd172a36cc4588a679a677cb86ef90b35936d8fe34979c6ed57e7a893355aaee33a1e6ddf45c24e79e3f218eb65244c6acc3355b39c676650d5a00251c08048085520c31ba0d024453ba8032860831437d8a1831cd29005a5a26529785014a5e041513c02c728a02c05133b56cb83e526774862efe4267690228517e4302538024ec5df59cdaa18649e09c0b736316c072b8bf5cc76a0020cc3326c0733884dd08c678c9e3ae8200c2fa6649653d39cb32c458f1bec20650c196f19866118866513c3e260b14c03b39aca90749f7d073e1379e81a07421892c74117b691294529d0ca36b539e7fce9a636c114a54c8d9069dab6c2664f5399e7641906a62668a2291c34519aa3110e784aa3110e76e66884831460a3d10df0908d46379883361ac9b72cc50da4b02aaecd3b381079730778a09a0bb8ac27c37420290721da8cd22464137ca29382454796a5c881143760c126050f457ea64cb1fc78d8b10c0671cb3cc304e078d0fe54933b2cb9010ff110f98008393082eb0b5148ebee1be0d8b677f38c76ebb245645eb41e112d648be83e693b220b44b345a878dd574466fbfd493c83885e592009b0fdab360211e4bbd714e1c2769c0eaa72f883411abcfe6da7d75c7f9418a88f082ee00f40efb4de1ee03c8ca19dc7f8bfc7f4df21b6e500f4864dec002525050c7e4865c1fa4f22706d59d260d98ecd8a9c97100342c27db4e140299ab0026647af696c353959db326d4e2122a7a6fda6d1d41d3609c4dcdf9dd59adc010ea3b0c18642095368d8fc97d0c3fe18539a28852f1f53ff12de810b7664b9c91d98d8fb1e128e5f4e30c5b2eb044eec9dae13b02c7b3a07a0aed5ca5e494d5e335fbe946c5d06d675d7fe6deb6ddb5e621e8ed6de63b7d5fef6b0edbdb65f20acbfd7db3774f0e80102ebef3f2afaa183d0ac03d16c839d873133bd143896e074955b5987c4ce00c75f95581b6577ed6161c80ab4000625ae108510125e395c2af101e80da575b5004adb8c899d0d76965d2d606225c81e461a7031d46baa0137f8810bdce083852bbc008a09d0bcd7800c3a20021260e0441cb22b442dd069d96b26a3c14e217e9b667b57964945482b41e6c89cb3005c0a2e469ed1324c46af432837a18248ca5805ae7bd5449a4861d9cf72132932b0fd94bbddb3d1a6e626525a2a969b48710991e030840932a803152948831239608215e200850c2cc1083c6879a1880a2a92e470c500c796e5159ac4c1055b141b4c418a24a880e2c166413538031298a4400648b61005db410e5b948c8a2b3051833284a10d5096c85e709862368103176c66b9091c82b4761b40b18027c610851c90c0032f0c21a76dc0fd2073580c54f8a10191265268c24f4e56051e7450cdd95f60d1c40d59e880a829d5062184b10ab69f9e2c3789f2044dd3346d6693c5729328487cb2c950c8800d4d24610518fce0085f810a1e60544c61526124a362c976b2dc840a24b6b3dc840a9e0884199d354cb65e96bdb823084d30e101169c34014346852837f09a50c1d345a981ccb88969da37cbd9a426514e7062c3134b2d3761c34bb694f02da16236199ac2e6596e3294054bb22cc50d8ad026654872645a6e520623d47293322c91be020211ccb2cb070f4d2cc1821b5a2e1f3a044dcb2e22bcec0528bb88f063fda5e529088105ccfce2544801851344cf721332c8c17266b949195060638c51ca266558425a6e52861dcb1eaa72c4e8ce061212124df6cff9901f67e92f076cf6c366418cb0991004d0cf5ea5a6eae90cd43fea1df7a5ca34dc68a2e5408c046635eb1b6c37300896c3045554514590c53a8f69094e1acf651138a6a1a427cdb7991c45ea1249757ec44892f4bdfcd8fb984a3bc2deb11a39fab3d7b1071cc7943d94a66c66dce3be9094f5e9523663dfbb70d6710537375a36ca48fccd3348ef75a1964dece5a655faf1392d665996695486e34655c32ca972588bf6dd735ce7759ea3bd4eda518dd6abd2abd243ae7a1f35cdc56acf3c63859aa8065eee3b90aad05165c1021dbdca6b9e8ef6a3d19762569f67b257a959650f35ee3fefb9aeeb3c92f7246feb46b49a5248a05a8651abfdcc5ebea94e8fc97eb4bd67529376fbcccbb1659f695e9665d8675826ad49c5473620f2eca394534ac732af318af5e8efd2a7145d6039bbbb0fa95e7387f80fd15a0a81ebe717ee02949b88c147b3dc840c63b0777a3ca364b90919b260d9c396b60919d0609972ab80729331fc905cbc4695233ef6d39ff43149c6aac221a58d963d1c7465e5e3e8550d065aadac7c27020813ad5636888a1d7d0cd2b117c4105612012401d67906fb2099cd88c83e48663360e5e3f8a8027161e5671548026cf30c06a4abb052068b1e03864081db6215c732cb5c6fcf86bffcf8513ee7a04a75ae63dd5cbc6693afca01deec4d2f5f67e5bdb2fde2b7ffe839f9d73f931f6797793a2b5ee9bb780d4973f9937ba931c4c56b36efb1aa5a799567afa63f55558ef9a69f6f02552b608d21b6f4aa1c2aefbdca7befa132955a9a3ee2671f87d8f99c7c07ef94af551aaf8604b31afef225286944d036820cf667fb4d3e9fe0f8e552ee84fa13aae268940fd4cfc741551ce9a1ec5cbc66fbc6a13d57aad8bf780df6f45dbc66eed8ed5fe5effc8e79e674aaa87a83d87cecf6a86f32861e9b3df63af4b1fabd8bf7f39b79e6a25efe8fdebd20b620b2c7b8af7bf11ab6fd9f57638825bdcb89fb5355d12f3d5bf66c60bff238aef2a6ba525539b257f9ec5540157d558ed2735f7a4e470a3a67875900177b59aa31c492c0197d781c6847f5c6c39e1a182587814c04daad838367fa5ffce41815ba89187a9809495c5ac07e60e1d0989a7f03e588f5ef26471a7b5384de996a09ce2864309b706f4223d65f26b4618982728e29890c7298bb3b0cd48b5c16a788f507c2e5abb8b2f1bbbf651c5d81aa76c427e80f2917bd37484217fd618584a01e50a6e0a05586094179e233c69b304aeca51094f8e409189f708c116a300a41894f849e043179ad44a159511db221a62d0e7af244a8758301da4a5bc29f8b313611cfc498c391c7c6e727d166fbf871c76bb28f9127c678e3930d9c4531665b65ac9bb16ef489ac9e8c651d0b33d6ec994526cf2c02b39ecda75b653cddcac19dd9901d22728373930d5d6ab516db681f8128c9958ab19b5fd1155f720bf446d7166674613f9812acc53342a4a28df3674319d1909cfb5a9553f3b1fe9af6f277682fbf5fca9f200fc71821da8e96158199101972382703b327601614633c7b1263784626c4339e9345d74d74c59bece561ccc97a620c127a69ac6b2df799040858a80718a6587f0ed4a87464b2ea38036d9f23dc2c70b6cf9166f1479d289bd53ebdd3443c54426fb3c038b9478a0e4cec4dd939a9d0b7b41d70b4725c37041d425ee6ea3d45248ff4223cf2bdc7792a5683c8c933bbade3d436d06489c06c1069e7acb61b0d46f0421339fd640a0d117d9056314c0d46c841122cfeb85eb19569da11a044d1302cf64456f4893c98a69161093d435869142b5ac51d22e9062580c1091eed89d05050cc30ec0c45e849c2c2c0dba6eca9b7a2a7a40dbba10585095186f556855072d3d0e4356ca314e88d45d1796e1882418af597e1e939c2f3c2e34578eecf15e90b5c94da73a4cece0e8654d5e004698c899f8a31f19404c53e93cd84ff89623fb64fa6a0fcd94ff61a8d3da654a6e138113af2b16a35e6fb5ab59aa66973cea97590a6695aa6695af6ddcab22c6b1e4dd334229767dbb681b7c6250cc69f3bc114ddc0e88a4be24f6c459bd8d33faed8e3453d45ac227ff264f5c47fd87f5868c87b38c6bf27f6f4449b2e8a315e4433a2d410158a42692ac520cc105151147a7f2ecb322862b00632d81b7b9899b31ca0810cf67ad1f527d77f640fe88d3ffeb3c46bb2978c15459b58f4d323231ec69f9ff803f640551a187b222bc6c42441fb336fc9b2ac6b1b3b7ee6e9c897a68cdb3fe6996e70957241ec7a582f959a3303db08ab7bbaa733d2f375573d7008175b7c8bee61237847df2fb9c3381277650f8f015ef65f27374ab18d93a42cfb3454ea316cc5afa0dff225950fef33ce8b9f4af774923e92bd777b58c97dbfa7e2befb8c4422a938f00677ef792b91d4c5ecbd2e461965945176200b14f4bd6fafa34fa29fd5eb9d36af6ef4bddf40162c50cf0b82be047dd027813e545e76bd1ea812af59a894ac95b6492d99a21100000000e313000020100c074442d1784828d9f6ec1d14000c91ae4e7c5699c7499053c820630c8001000000000140100401000caf37e79be3edfdd6104017d7d66fee0f3b2619c0ff1e3cc263f0c6b155b950579e0bfda669ac320f708874c40e04102b036da75c6ca3e5e4c909eb3701c4d604fc4fa05b387eb311242710afcfa7e5fe5acb226df7267c41938722b83dc4a924db51882b3507f1580c5df0250145796e16b8c71138ff81e18f3704327abb59987f75c0d0d32636a950adabfcfd552056c0c26821e311690c050fcb317fce2836583d3aaba610d037e4eac9f5c6a4721c9a790079aea2bf188dbb817f987c6f47b1e5a5dd1dc46523bfa73b0ce23e712c212874b39dc51108ac4737e9e4b142c713142943fd55a3e2b07ee71af89aca368878310044f6bb1f54df60068c9ae41dbf82e1707a1ad38a76800ec624f196ed18938bc6719dbc9db9dc9efda99e9bb395b3e88824e4e15645ce52a0fece8e47b08e134ae6b08671ec4454d5892c7b24b954851448419360a2b7b731589fd79897087731e094ae91f310d301ebc32fa2efc39831891b883403ab59f0d94decc839bc4b2221eb4f1c79e824b3d4034b0369c6413823f50bf1c755b72572791389846d8c32498615dce6e895235829714d83746f3035f2bd485b660b5cc1a0465bc37339f74677cb9271f6141fec121a2081d8576e5f3e5720a8573aef23b8e02aefb39161b7883383dac441f814a70ff604b0d477d1c5207721a6c3165f7067e3dd6d13b592155bf14aafc4ca577a852ba6950fe4d9fd2886762384287bc6556f9a8815accc0aac604556b0222b588195accc4aac602556e4c9234fe4da1c997cdda9c4bbd3b75582e126c07b51900f0821d819d6745c3ec6f238411bc7e7bee6eb06277da04d4e94a70613471ab6168a5e91020b614f630665d26a46c88a6e1462b95668d487ca080f4bbada91ca24bb3c4c13553376deb7611b4214473d182e6932da34f14ce759110db7bdf80821d0001ee2f487e61159508ae7a5e796697d490a87c451985263438e71f7b31cda4906c4eeba5afbe682831ec8d98acde1605fcec4c338c7126281abc047a1b00a83b46bc89c30c81712bf73aa49d6bd2ad377892344ec74c626fec87fd6a0c6ff330f3464c491504c68921123d1aeeb2c917ff6645900c86222d14e896449d38d4ee8aa72ed29091288c5574920f9b1ae5802cf1b7f095a2d05633e57bb7bbc200e3acfbca2f89344bed445dcb891b8b84b9354f40017a9e37b3e9b29a8a74e32e6d00e234c5ceab6e9623b8267023f3d36ce6b9496b47cfec75d38a8ed2bd9bdff33fff43f44dc61463d8f0b401284b5668c1b0b22e0254f056e381a07f407cd570646a9a83a76a8636921eb11a4dab3a0a198e30208ac3113733a8ea209862088a5e1f1629acfe54e7279a65b4d8929d3697210a2d415f828612d44f6503ddbee19d3f49f47595c3cb9d4bc2917040ae5bd568ba1e584eac8fd7c4f7b122484f16466f1d1aaadc1e2cf606d5a11e7e8946a6a326fbe1209b82909aa2d8f524fe23dd7cbeb1d38f7f1c723228800a2456cf62f5911d5d31bf0f526c05b3068bfbefc75e7efab4a42c72d2268c2b2239f0acfaab603fa16235a5cc4bca60e0613d42c407f3532fbeaa9c975574f54970155184fb34bca4140a7df76749a080ef0e9b5a4771e72d88a8066c5d4276eddb77d632c114db96967b7dfe7f94329d96058b1d99bdb83377deb0f43479a12caa9cdb600074ee9e9a8d626e568060dd84c1dcae68c893e0f6174a513eb432e2fffcd10dc13c4f851b49ed16a6513b77ea127c59d4e35e1b15f0158ba2c1bc309fa065757c4ce48bbe2f6fced299a789fa7cae5c3183e05e4cda46e5d4e0f88bfdc59ac799bcb9dd59ab3bd9c59aff9dbcb99f59abfbd9c0effe060da81e403187ef451f8e6b3d276e9655e832e353a5699de9ab8e246f26f6f378abfbdbb51fe9db9b2f769f66dc85730f7239033523f3bc6a2ad37ef2725b7af6fbefa7df3a5c0ec51f5e41aa88049396298e40e04ba3b97fbb9b3099486a0b6e335844fc8cdf6f0880b10215b88650f37074def7b5fc18afdbc58546a506498fb86c86cbf19dfd0474c1db1024757cca076eeebd7559048bb501e5251dd54837e95a5d776a79569ec09953a2504840d24a4159b1de0c9adc7813773618a9c3bebdce88224779693e55d783c75d68563a1731883d0757a2aa9780073f3ba4bf403487da3e8d18b556526e5765c4397aa48a93a2532f4aca5a1296a73d0f09847199a59308072b24ed3176ec43c21d4badace3a42e87e0976732e73c1c6074a56cfca68997676fb6b65165568392bf07d94b36ff026242eee743ccc82012146733b191a105c22b15cb19d74dd1fb640027ad5fcd6448919b66836f0ca255abd807bb94d96402dcca633060da20e9bd5cea0f358790a580279b5be37eb605fee790faa68b27c31d4e899cf49a964a39293dc902e0fca333b0a99134302c9779c7280a9e8b6a13aa98eecd77785653ecdcc0553d58808c2c7dc05c607b031ca56746670ca37a6f5da3ae88f73ccf0f5a10f611f283363c72cd5a5f4419522e83e5a299545c4f97398580121df04cb83998eeea86cfa79df2fcd1ba7bfe52147b0c564bab67d1e405f182e85be7f90f84105503e008e6c3367e5979406f11cfb76e45973a79163839a5a509e8ea6a182e837a757131bab47eaf998c63d2e4b789c61a1ee56c0b01f8680100f25f2a2d39a26db14d03855ca475a293d7e35eef7633b9c396382f362c6bf43f3eb630c5482a2cfa83b4f7f68c6382568dff134a365a6bcff38a7f3f7ecae6df397440023c2a4ecc9b651d91b8b082b69bd492aae22bf6ca9ca6c5f225697640526c2c500073b686ec9ee9b42bd023319d83d1169dbdf32d319113dec2e022a9851b278253311e609067b4c042b4587a8659102d480cd56a6305bf7040e1aca20824924b6f9a8b2f716be866f0dd292a2447d6c4f2dd1f544df25d4ed94acae0a51d88161150a4aeac9e612f10fc5cdd737391d1e47339d98a3f4c7461f1f5e4cfeca977166abc006492771c9a25f92b4fa269297b686af6499c42960b80d38a0a881973e6a23099be6663ec79e9d6647cccfcc5997e93f1883eceb1a66dd2b890bf361e4b94a2f62d9af91d8566580343e6e541101d1b7d862bc18761b13e12d9bd426aca256e0b70de52cdfa2c68ad8217e4fad277f3688f465582dc32f90545fab350ac1109883d322eed505854bc2e6e6b941f9c77e3a22270226e6725293958514bc93586231c55ea575ee0fd95bb3c204e77d2fc2cf4652dde3e425accbedac3db6776bd9fa4ef7ec5f51ff7428a0aee19cc36db648700ff13f5668f52bf960159fa48fd004279cd49b9f12afebd5f3822ea3b3f8c8f497e9c487cad6a2d004776dac5a435d4dd0e559555a64b610d2a3361dfec349ac098c1e7ee67a0d84e802ccaf117c8ca61c96b6fac2ebfbf9eba4f76b1fee7ee9f07ea54e861da8774482050c08e543260c7089c346688f21c88df0dba09e5e18fc8b669c213635a38b85103a8cc70b5c93fad6e27417d46a6ee856b7754b74ebbba99f62438d01742c0641ecafa6b21db714e36fb07a440356fa9520a416d229568f3819ad1e9f9f5ee6ed2cdbab65a7077c30a4f9b1cb2bca03eba164bba4886554bca4310ba4aa58b6d979386f89d6a6cbb4cd05f78778465229b81683b4d23b27b6ad6928bee41af94b33d725d5ac29d7fd125ec49e649beec055972728349bfaf7b5cf408b1884b7f0fd0335260a73a4944364f623e238b294d55b5a17767dd21d66fafea669f562f8148bfaa8e68f6d479d7da37575a45acc6858467e61bbb071eb43655982cb6558dca7afb0c161c076709214f4314800b7c3494427bac438edd9d2a09d92c7aca70b93f9b8622bd4c3a073dd4bad27bd455e5d8588d7308f609c739cddbe231a0ae5e2d2b9cd4e654fc8cacffb59de8bbcdea14b380a8e3c77d6503f2dc29ddcc49e495cc4ddbd5c9e8b94606876ade8c3082be71523a44e0552eb40246c80fea70846e054a1ef37bb8ebe68745ff7d3f89ca6af45d7b5799468add8ff780739f821fe2f0c99bd621fc0d26783a11c479312af397ffcc793b56c80df6ddc3b30e986e65c5db1c848842ec7376c38d5f9d46ba28e9763c6f7e7095677ebbd0652b7b97e588fcc02a15a280c1c354f8e7676e698aabe385a83ac9cb69dd9cfec4a322b007443be9501d3824faadab9174baf2acd4ee38ef5e4b669999b5d74b4a22a205571d30f06078ec6b85f9ddaa7ab275e344e6318c62a9b7a695746579546023cb713c47843af55475003b7773980550ba074db86ff7b16f89f9f7f8f07a93bedfcaaff98e2c9a4ee01a8b2a7a1cf614140787f20c1e68b1f101035d612e77e0db3991ceb7ae5fd8a471b6c4e915379579453bae9e4fe1302064fa36f3241e760e4ef2c5e073fe8eaf88b31d95e29fe7e084793920f850203718ca343e578a058d5e07c12ca26300d18dcd3a12c410eee1d1e1a727aa62cf1b5f71ce5e1ccbda4a1c06489ada2ebe748eff84de204fa7da2d6882aa43bd4b91f69d4c0b7ba610657c1aeff48e4825d6661d8dd597076e676e442bb53a54f4013446b56fda8cbf432017ea97624ba1180fd1874682de08f6147c6730c8a333d88983f620ef9044347190a13145deb860119e6113f6a8530e828327f87318262a889d348b6346adeed10f2028a4306159fd6d6589d10de724276480554814ece9d7249ebb97ce1f6d148186fc39e243c8c01067146b7f728d0a87d63257ef59ba6511ee033efeda223365b3183be6398a4f2dd6f2003062dc9909ac9916c51ffea1d7fa58c6bab1a5eae73115fce7c61569d1294161294e6567aa77f152f2048dd1fded3720cc7610b3d3cd150a83d901f0e488f1868f8e2f0f623103acb9724d8cfddd5ef3e96372f53fe2e1130421427dda5b9fcf614fb7d394a3ee483f4c7f139aa46e68bd122999461a12b84674c033d5a8ccf5eb990bcfe6920a6abced944b184b8326f1a7dd54f34e140ef3f8aa4f65e9aac2e2bc8b21da80aa09482fb9621a603632efb102027ed7afc96c4ab7c621c17e77488affe00333cb73986b10fd43f5a78588760cdf4355f4d00407ad2763e040dd83be55770c71867b57c56b302606a4a2a075a8861751af131b4c078717557d06deda9569dd0c91e1289c44fd27453519e4462dd77e2def20cce97b1c94026b021ed2f9373069f11b6df72f32de0bb34cc74c08a578120a02b04748552564142e70a5506118ba025da9a873fdf7f02891cc2fdbf0e9dd4bc562da8ebbde7a899d95f781c6f1f4f01f69fea8c699020fee2ad3b41fab55ff4511321c3d22705daf4da74c3151b926202f96d74bb35cef29fbde0bca4631d222dd156943816c179fe363c55ae9f43a85600ed4b54721060abe4980d82bfed33ee5c01f2a7cb3c016a3412846804026159fd1720f49f0f43cdce30e84f282313858e052a61bb44bbe5852170756af98390ee8bf86b776521db47d2b81ea0a00f3d33a89039399bfe1a4da03807189ed8d305731b455ae4406b530f1858267c5c81e19702e83664b73347ffb293bc0151052155da24432e185b26de5f1153d20fd7d8dd6c96fde8fd86e35693a30e3a73942626f7a4f52b1b350619d19af09c4f52321938e6dfb22e30e7216c248b3990e2c4427928fd17b1a4ed14b85ab6255098fa9129ee75553e5d19e98d430749b89ea958f8aab49815e5edc6d841f47d977ab49fd8b91b705814847594fa0bf4fe06f17e55c676b4dbf4cc8d90a415a7cffba53994163b19ac11aeba81a5f4cd6c735a7696456f1bcee683ea9ee5c8d5dbbe8ff28d1ad926817940e1cbc4155393bd06a0cfeea56215c561834654211a3f086c6dbc30c4e248d2822e055e14d947e2fea44089f07636c6cd2ab8147f8b932b9e649eb2fb5202159579de778b4a4191f9110a1cddca435856a4bed71bb51d4e43b8cb0c53ee37abc5d340642716ababa14887e548234f7867517a0b39c4876abc5ef92cea85d2f233037e9a2ada5564e8ae91dbe951a0041626850b2f9c37b0e55454e142b6b791b926426da4d196df26ffb214bb2cfb075d2490a9121246b7a87ab4c87cca24a192513b5910022bdbbfaf20e838ee170fe2077a90504b8b5d36cfcefb3c2ebbf25b14fce526e33ac11a22f80e868ce1750b62fbe1ad5931208af95192877b63e497086a4d84e9f6a8d1cc9fd5a4ec0a2136cb39f1bc831434e18788a3709ec5517c8e8c79294475ce7805715c977037971c77665448174206c73693710ce26e829e8528716f0f947d20fc98dc34fb84caae8984d63a94fc2f543a1a5b50be78e1fafdc1d3bddd8883958bb66e6b6ddfda0aadb672c946102cefa946211f916a4899fe357aaf2290c243e1385c250122a1d918aed02e2617c7e79956da7b13d949b1ec925519603001af19488d11cdf6fb2e4f240533146302447d8168c2ad44e19da1d202e219a7906e74dd301a9b71d496e1f0fde7466242d41ff4589e7d0e27725e84563b3ebae79d7e5e6671614241154a226a8a0505809d08bc28fdd335492b1bb4d0fccbe7cdf7e1574d5c604f5d13e9c1ba52c64ae79bba6be0a543762b067288afa93d33230e10bd43132ec0483935380aaa700548cc24da2b5fa33842c94a51abe14ec16dd14d238647b38cb997d35e69bcd3db03acd4eb2a19a1980933715c474cd379deaf3fb416e2e44db3857d4da055118753913de5f5216eb6f40a7249aae276ebdfb62bc27bed21510675def24f435fc6423c24eab58336ba1638bd2b1a47119529777890bf85718acad9187e639457436bbae69ace31e50067d2e28840723ebdc1b2f7b38f3eed3d16b224c0d4a793c94df7307bdb1d0adc3f43258867c4d16d8ac02d27a6812894c4d8a354f89d482226c458d8739d655dcba19925e7732a5c00d6798025a40b928158098e3abb907619f77effa54a88b9f7b565208552a3a6158c5e7e9165465790f0d4376bbe35b7fd2c9b21ed6e3bfb2b24d4c8fc1c8ef0178724dd9ef771450490e7cb86ca5c026e430166daf316348ab1cf9da21e4c29a08ba084d48947f40c7ca6e7deac41ee194f799b0eb490bc9ead1fd2f9cbe4ce16342dc2c65698e856d817a963d6a34fa29896b8055481172b38f369a93dc5796a0988fda5d0d7a0969be56af40530a6dfa2112aa2b90bd465041465a5d7a59bfd722e5cc04e28483d64c09f6ef488b20683b32bb5eaba24060222912df231a7ab8d0c8f23d8326e565c30371716145aeef47629699d9220219d084f35b7db10c5f8347dffcb3e8d0482d1a9112bb8058dd1406788244980bcae304ae4ca84e89ddc8c6e1272be84078190f5c23647b1d615377e26700dcb3645c8fc4a30ea73cbadf26c4fe420e44e43a96c97204b5cedbcc1ee8589a434a1b259646d620997937ee8355e116df6987a06a838888e4bb278500b53b0e45acd55304c012f97d9cba896d02bc0dc5912a1b039615b7d5f869041466d63d7a8f50c658407d81854cd57e8584a651041d0637c98209885ff5f115b72414a7d8e7ac7128e11f7c390ed77dd110e5929641677f98ffde19710a8a6096eff61436079af8181068161caea8ff7327d39f94336c3f0e347f43779d14d019aadd811f1852ba41122f20ba54048d6c11742ea4206cb3792a3bc57e3e1136f784f79e65bc3aab4c2a0194285f914e81dec356eb867150534794bb3c98f8a11b72702ddb6dce4906c07ca37f2b7671ba4857aaaf75b81bc15d258e2c6679d24f44d3459dd7f1ba05bb007f6a243d98e740a2eac3c3136d71d18c29f78d5095f32c41e146874b432a5ac602bece6c4446aac0f64c2a057528e865334ac32360628b0a965416bdf1285c51933d7b8570366b9e1d2aeccec9ecc2b01bef86bb96ef23dea5f574c1b4d4358fda8c5a229d4adf6a5f881b52802af9f593b3ed03a6b9734fee2ca047ad7630f394153107af6446244e2365a4c86227404ca60bc61e9b5a448531668c375c729f09ac6293cca052d1bd6ba408e2a4368c77ceb571f7c78eabeb102b6a6663eb35949d3d8c4b1fe6c4692d98add74238234a970d360f393f8f872736f1f254998ece2f251b82e02d1120cd9baf87428d1ad232c8b9d326c0b0d7e2b20fe467336b7d3702299e3c721e8df34a2ebcd543fd126ca1bcb8a2b037954e98959374eceb08b6c642f6fee46a3996ceeef577f66d85a5355830c3a364107dc000816669f708f74f086774189eda5fe097cbb2902274f3be794cb03a6fd895e4adbcbf1a2853816ff130d84555a23417f700fc1faf0d84e2feba3040146b436df871d69900a245c851cc9347f7d236a0c9ce0862aa7c7c1153ab3d879e00ceba3ca4426ea15d581f72d632ac65f12b68f91081008123a4f78a7b9389dd62ee03570ec774828b9089d151b18ca4da8f89654d023c4901993e7d4843b4cc503c47e4347a3217144f39e4e09f45fe590d6e36590cde9e14cee8ffd39865c48b24eb6f8b47a3c3c98bb4c8636afba3830a1d92225e8035456262085269e9f8a7b1a507c4476a7b121bd75cda79c09aea885dcff0470a8f60cca3fa9727c10cbd0f55f785ed42dfa101d24d0f3f2096b3d94921aff8bef13f28620a371d2da1f25f97d0be3259f6f5f2d73ee944ccaf5bd81673b144ddc98b11a99e7c689229d601c9124cd97176b60d35cecc1b64308cc29454fcd124d8fcfa484c22ae7837737ab0fc0f6236282598f83892b8fc3324914ae639428ce17152526e6357a076951d257a16920c96097be0ffa78e8355c62b722f8ee7f4b1b8cc38e4dc562a9e1e3c7ab863d5e8ce45acf66a36ef4bfe3ed4704d27ae569e4244050730a165fd4b9394d55581e832bc74972640af9c22020f580a0e36b9b50d31fceab7e170ba078c338aefbfabd1d4ae1de011aaa67898bd33da47de1d8b84bd3547ca8fefe9860ac82f620331b3ff285fecb099ad447580ff4a32616927f927cf18c923d2efc48729d5596f9a8911b5ab141c7f8beb9f868956c1479306061ab91399ed5379ce1ea075b639fd732dcf78f879d3c4f580b411f7953ea1d804a322f1040ecef9c6cbc84e17d952995d4841419c85d35b20ef605d13b6a01d25d291bf4f96e84f2b23fa018ed08681d794e1700a9d6a32ee0b7188ac5e97c34fa7f62be37a0c4006cb3bfb6190c0110cf164a37629eac3b82693d02b3f597c1036f3b272325b8a2d83debacbb0185d6f91aac90b5b07763e486d539d8d6ce81469c36a5423abb6c459c90bb5d42449e52b0763d4f0daed8b7cf17a809366f81977b13991f0c0671e3cbc419345451088a17e9d2da6e8c6eccfd76a59a9b29e8edc85aea58d5cb4fcd3efdf2767c41dff9ff9c9c799961aeec9feb55ffff4354ace6bbfffd8cf7905e707d4d1dbddad71188f44a3c6f4e56b6014c08a8608e44b64e5bad8c6782da23a30c1214cda080d4e03e5d03666310b21b2d0f04fa0448b68d6fdd666c59d1d25c54cbfc2f75731556f1b024e1d3d1a9d205149922ff4990ab0fe9bf23a796c3031b44697ea28e9744b17747a26540043cb81b5977ba6da4d41cb8b34da1bde04014ecde8f1d60a119df84c4e8e6d07ce0d5f4fc0e1b2a604b29dbcf8e936c11ddaf7882d48cc202895142ad1f2a9596d22ead1f8b2fc99d30e53dac83c7a79a2aaa4866d7438263065e7c2388c8c5befcc3e1d38a52812c12b1679dc52a968628e4975a482224c40c5bb290fdbdf7fa840aab954bcd029950cc0e686354a9c6431f652b071de6e82d2df44e7af2473fdc27a5f42171b3c74c12caaef3c0eed357a27d65cc7f1d25948a599539ea30bef40241152ad10877754bbd1240ce909d304e93a47e9d935b8756a5c533c6543c76f0cc64cfd004461bd3dc2ac4d293e6a341e36014d825d8c36ae8de1337f6bccfd05e0406c2300631436c5c660d3041b098be4b0f615acd7546c30b54695735642aaa433e1bdb86611e100b8a42a2155b11612958df49172b2dc41adc5f1e05b9cacc5661cdbffc9591d4591ec8e5096c2c682d7088ed5f70a6556cfb1c363ce2bc7726310d9ef272c360cf2d1597e5278639ebe429301f0e5df667a8e0217346da8087bdf4941cc4730c0a8f1950036c87a9b970324d58bc79a06168b7c25dafa679ee3b68c3d03faaeb7bc7c7af528cdf5d8edf6bac3fa0caf6bf32c625664b89a633a8afd18d59412554d25a7623699e7857b6dd207652fd33ffd3f8c21c58bf2ae05e856bf52bcfa5e0b7e450e4ead221f48b01b4fce8de6337675a79b3e1a51d18b36c9cf350750e63a6dc4a001e990d9acbd9c77204e2c337e695ac229ee53ed80b4e12cfcd3ebb7e428e403ec6a56a859efb6d2a0dc7cc0b6b695fa31f6f8ee757906d4dd785877805192bed3d496c608e2670a123e9ac42b4d219b918042acd58cb24bb5b54f902963fa81c07006546397efa1674b3bb7a4ec1145a1b57cc8d488e23677774b8c45b6c7b40fba4ac551ab74b4e833b7a63669967c8a838e7ce4877f84faa16febdacf6ee9d3bdc6d780366eaa01b4fb5e6ec3cabd866ebe01d1f3a5f4da0e6ec2f6d46f3797d3ac53a7bbd158753314d41ff86bdde8a3005b02938f5a65606c5d4c613c3f49458337b2bf2589a86797403a722c452a9db91e88b6638cabff21d95a3386ebad35998cda583fdface86002514a0e588443e3383cb486d3ae9189bf3ddf87c4ebe37c700739f5a9bef0cb1a6739a086f674497a6e82dd0171fa79f81566afedfadfc3fbcceee625d870f1b01076ace36490af2af98a16630b8c4a28fb0c909902c70df6856be2dd34876ea2c0f11084dd0062ab8d8235649bffe5e9e596ce6b9d1d532165159cd9920d12c074b28c502628f9eedf695540fc1a892cac46aaedbfb3fef36e3f375bb91e8bdcc13d0cb4cd1a35312258c7e9ce20c615ff15d73d6a110fcba65fe4e922396f93c79ceade77bf29c5bcdffc9396c9ddf9373d832bf27ceb9c5fc4f9f63ebf93c39872df3797a8e5bcfffd439b5d541ca043419e4eea6696aa48499a2625a20759f7c16aa9bc508f655b1e6ec0ca46f6a2c626ccd1969303749e49f075ac15c081da58e82f6432108e1d4b0de621b256ce388606bce8e4c0cb3c2a4a09520537831de860b2d74e95a72bc5f5e7376511a08a23df948162be23d6e651323537366579a9300267ce288e09524b5e3cc5ce759b88f33b6246a7552dad49c891bd829ed386fc3da586e6c1cd252d124057bd327736746b0740d97509f6c16c6f34ecf91547a846a74d073f821228c21cd89bc8715ac12fb73dc4fc2d618f6ec2520e2d5400690f1595bd5afe49594267e4a31dcbdda358ec3beee7cfe827338b347361bb48665c914632162757210dee03b9669c074377f8e7328cb2cdd1e1fb1abd7bedd6534f2e5a1efbf78a46067edd39bd9dfbe158a941d0c65e2c7e9640faeaf0e83219e884892117a96da1ab15765b55207cc25912150e77bb00e443a1a1d96c0c031f8ebdf8fec7e3150605c6233fa29a66d5506d80f0db9195834dfa3bdeaec88cb72fd2b6853174a9c710f3c6478269e1195f8f7e846d373de987664a034b6b6e5756dcff223e601d227377fc0c936fa39361529cdf691fc696e3d890c2053325798a87874be20faa38651d88810bf753c55753b498bef68b16a57fef67996638165f433ab99da25a06baa0f1e5c886d1a1d1a671e2441501ab4b0828f47f23237202a789e982ace87cabb24a090f40ef38b5bf030fadc0f866130983ef900b666d69264683db865a7ac4a103ab0a36cdad20dfe2b8e419ed2082167344f3cf165d1e3710b2a7b43ea2ec1f9a05f07a81aa8e17f548c14133318060a5f8d1f0118f62a2cb6a862665d8c59f87fa0e2e6b80c961d9e86f314f6e4062f0dc6dd9be3629cc98cbf5416d004e0889de9315441e77aaf958ecacce3667e2cb2da42c365ee94c8d2ccdc2b2c7195e428cc1e409b4577724ce195600e4ca43e689783faa13d85381b9518531e214b3eb2ad9819bd8d106f48033fa98196f86b27666850be0d9a269a1ccd84c47a3415786d06475060850772f7d83c8bc187bc3cd00d98acbf202976f88cb6a20fbd43200a09ec896dad028032fe825983922201f80278df0e21be3204a6dca8bcbfbb8c329d10443bb28619b32b7e3247a40c12a30a36cdf12337add02b039c578ecb8c46a8998a1490b38139b8e0d132c98d1909765146d0226013c6fde440777cf09e46d0e1cdf5de1a41f84a6493294d27b3201152971f714fe5155ccc117c687cc78795260916ea82c558d4c7039ca738455da99a7fafab5fc486704e5703ac4c20deaa32a6b24f3d36b65253f208beae779d44b05dc68351172e79160da7c1e9ec33b02174a3ff32a5c1d2a0bdf46033dafe16f09a7f60c38a5765af73fd335cb773c568877a86c7e45e4b617caaa0581c91d68e9c88e6a2316e24d9f4b8a7c2e3f1690a96d7213ac424741873644fe8d21610f4c2b32a5d1fc8c3a46e2c6ff260745baf23fff14f203289a8a5efcf69b25a9f256e8a3c7d62fe981a0afa1f44bca7f41022eb75344bc274e49111a4fe1108837ce41a876cc64fbcc89737793897299575cc20f33f697f86701767cd8bd86aa62fc41e39fccf2e02fea329017a72051c7b84bb4ca7312078230a3f60a24fb097cd3648fc782722b04142097a10a248c04e23882b9b54d185f86e308e445f9b6a78c877ef2cc2cd4fc19b43ea640701606a2980f91e15eb347d7de3850eabafdf8fb43cd1d08136230192197dac655e4dff0af79276c3d99423a31d40a2aa20d6b23fbfe0cd25682e49be6eebbeb2b3a22c331e34162d63af3d66e7ae6e3569153816f1ad60c8b96fbff2da105e043e1a56e56779ab4e602c2db3b91865205fbc14683ee5534825d22890be346a1a07f183169114f31e16e33fef1626c897881a659056a6e6c14bd956670a7030c8d259348e722c158542aa324e037dd47a414517a475a5a62bd3b4c631451a7c4031587e733684e93b43f734de44b34d437ac1b3a7638ee691d560fd55f35fed1f694c4fcaf31e27f5cc0a5082935a59c0a1cf5d28c34db6b36baf5cf37e89a0c4c7796450405e432f5da34102da980e24aa00b78cd17942ddc5a979abf2d60a8ab1ff724aa99831d0fc520e89a3e612c8784e49810ab65eb77ac164910df2c01143f5576d09a3ab56f3138ccaa6815417e34ada20aa1f13ebce0411e45ad815c15cf49a50dea0d6a5759219454e09229561d96e45599197172e071683c5abed18298367579aba57d4175bcc473af12d378dfc8ac24dc13dc9b4f023b5a0b0a8e9a30a71ba9daf2ccd89610312798026559e7a181f01097f0049c67745934543c08e1b668c2e0049ead3a500ba9eb008ff76112805ce527a1164411ad686965fa77d2d99e0d8ecc6cc40d5db2e8ef1a44e049f16a392f0cbc0bcd0564e99c0802ccc81d3255148f1180e3380f2379e8c9179bb6e7c1c40f5d6d81d196f800f1b970301b52faa78519f1511b05e27118b1cd7a0a376189024010eacc3e806c29913bd8e9452cf16347960d356fa40b5b7afd46dc89dd46afb81fc5bb28ebc0545ffa7d4aa1a8d44d8368c8f93fa0f866888a03c251e00b92c348d5910b7e095b5b23bc391a436fc71b5f5d92a0860b4eded0813b5f5989a01a57805f0aee10484b570ebb42320a5258e58544845ba96b61aa804260b490aeab72aa07b64a0ce23d7a10517e06b066f30834b5ef5182df31d5636ed15ab1bd72ccdcbb33decbbf0b270a4be2588070daa74ee29ff3a45999b1c04f90b1eb78418aeb4e02f82a8bbeb9f3364bbb0db851836074d3967803688ca7ec9dc5109d7296c744016d40a9f69f671ddcd26c7c1b6d8f4ac20b8a1f2f22a5fd83d5668b92f665b8eeaf87eed9df8689541d9b3f573012965c24a903bf65ce5bcd4f8070944baad1cb132454f98e13bd78d2f04580f61159d53536e6a3b83b975fbcd30236f0351783f47394c4237393c08dcaf58e2f4a99cb65c7ac8cae86693979e1f366ba713d617f51f448a9ec84da8d38377ca2cf01b9b1e4b2fbb52182452014687db6d2fc2fa5df4a8f4627acef6b6397485ba0caa56ae76e157b9c4f788bf7e60dc20d495b9040ae6ab5e7d78117840b06bf580ed302d9454c17d3e31f624320bcd6e0e5fc189f3560a455aefa5a7b56f44fa326fb4cf27d40fed177fa7d45fcc8d4d3412b4e2f3094945a299826a91b81d90b66e161788f1a5fba2e9f369a3ea98c8847ddf9353542424365b0c5ec5e743ae6d1980d6dcf2656e7e7f3ab40351465dadf5050a8eed3c1e4be3ed125bab4ebfda5e34ddd2220b8e8c7000500bd4f338c70f565a44b63b3201a62bca9008abf65b005855dcf2a0424aed57dab2c343497740c6f1d3f28577193776942cdae3d4c92f54c4c88c7c51b1865a9875f19b5bc0394eb61b20f07a8f8b83518958c6c9bf1971e5ea1a3b7cd25d89bd4d025dc2504440a14a944461c8019fccdeea2fc007ea7f3d3d399d632c98ee8b7a9a15786e0a1322beb415280e051b7f7c0b3d742438315e47dca325747ba1e506293b536effb375e423153c21827453f3eec0b8fe7b5bcabcce4719868935fe3ad807ccd0353f8c6ced4f310520283c479fbdb36aa59e5224b105fc335d2fb7f0afee63757e2ed5ab7b9a400f20d8344efd9bd131073999ef7940cd70ad3a433ffe016e10fc3106162114b33e01f57cd50b4b5899b84e021efe6f9dbb23ec770b7bf841aecde351ae694fa82861e1ff12725bb8d5b25bddcef143f53cf65bc12d90594ea2b9dec8d1df5e595c548f5fcbd51bd56d5c17c705dbef341bdedde05fb993829094d495434a13fe3b2e0ac1b2656ae2d6884198fdc6e3706bb165bb2de2f2123498c75826c15016ca12cbf8fa43b8e7212930fb71e6766227c8b02fe61d34ccbab1c0196efbf9d5fe133fbfce4fa81e51bade4ab9d526a8f06a30ff57bd89ab5758cf78ea8208040224a5eb9bea9bab294f33053ea9f1c38eedbc796aad15237f2a57c4719e43de0f6977ff1e02bc7d43397ce8d680436e2c54bd79096d71873355fcf82acac8e2fad4caa011a67e23859f9a90831524289f772dc55b60e7266420b0e5c60dc4fa3c81816468471b9bcd0ca111d60902815ca2714c3c0660aa372dc6be00c7f6baca9a6cd82505c311cefb247ebb616e151aab403d20693de28dfac51562513f7287863276d903ce8f87fae119b8a3aaea32c4eb52577ace6d109b3c1bc3662c8699f6465b29228720faddeb1293222f3a61d2116d1910e0e1a509373f7781c062773d2547f10936215b8dd907e5a077f70d838b2e8fc3719ce2d56896f2cd2e7863a2266ae928ae579798587e592e27c62ef2b1e69457ba413a6e2618ac01bded21357de117c87a9324786c7bc1e87f81956d2a1cdb711667cc2e0667163b2cc92b1d3b27670bb33a26b37df31110abc44640c4cfa5a08da0e4fdff16bc1a10da6abd36ba0e5592b44af31e5d2250fd766530165987e5f7074bcb0036e6e117126e7dfd15ac2c6f3df275284ce248e0bec6f926111266b27d21c90d05fb5a39e85a5f17db0449c19dca825d0183936afc5856fe7049a949a293d915d31f548ee56f1e4397b29aab9a4393d1dc97cb78c6db3df1dcc77e76d771800ae87a70aabdf8a517a1413567e47ebf3f4d24b5bcbe0f169b5bf51b72f77c9df6663739227adddadac12bc22324094037c5e20e944a46ee214f428b941c5ff45627d4f20545bddd04a37d84cc188b8db70d4905d6686f7602226b4ea308945c209efff86e4520b731a0ad7aa9643be463971578b7e8c7fba26aec26ee0722a5336a91c862300bc56efb03521cfa8192d3a80b5ff68d68df6aa7b5a7a12dc3ba513453197aab4b6f3b39368a3c648f7fed203629720219a43f17d4687151d2a1d9a3d6149a0044cfc639e1f9672a9a1974ccec2864735b1070808923681ecbb7b55a274c309db2d47fcce8ead8b5de281702bcde2decb732b03582fa04a853335727b2154e4135519b2032a1b2f59517069bd4c78a6171be2a01ea715fa34d149e3e6eba5d1fa2d758e66b3eb1be6779f8b1b58d41d7a4fa159df1ddcb048197f6514891025b5ead44e9967389d3e7a8744a2ffeb433c89945f79d78145ae410b447554f966e4cf859ed29f8541991d00be530e5dc767e2062933f89ec52e3c1cee770d208a961f9f5859312f32c897e85d443a881d4760691a319b8419d657aca9448d0378b9b50851d035f8a4a6f765d0bbb35dbb9c85ec07b776261abe34c986c45ae8130028cf92577ed5b23f4a13fb54c8f4e7b3c432bec52137e89c3c62642fb4caeb42affe42b654885d506767b052f908999273d042e56c0a238c4b82b5cbec1ff6da522a9b0f17d565524b7b85ddaf8665cb3cb653d840c7a8eb5b3b3ba4e5e3568cabbf35d433a225971977b82bd061d0e6d101de66b5d3a0290bab961b191cbc48880781008cb1e248155d868e6e56b6f4f4e4da316bfebf8e2857a32365a3c4b6ad38d8dc669ba75ee5fdfa566806518d97483f580c9abdf613eb4c68ee96858eff655b9b063745a83599a55481fcf4aa3f62ee58d83966b7b1f98b3e4d52d6eeb967797568341634f8789f236679b3b90620e7663421a38738da19e4299438a47a9413d4a55808e8d5f62e61737541cb6b74726b2566a8b60cde91b6d46e07d7dcb2d255531b4e14868124fe4508cc91f5c788911172c06742c6a7c49cd9bfeac187c38bbb7e273462c6d8d337de5e28ff4a3d68fafbdff36c953a80f4e038182deaae4090104711d153807c55485c031f52fe732c2a88b9d8cb95a1fd0278342938c4df2af149068f5ccc0aa3b9d05003d0b65e46d73907c14fd353116384a963a5986c58b12a1f1d7790e1c136c9a0ca24f4fadcd08b3cf966004af350f498aa377264c6016151d31d4ff610b48d65b4b87f5fd2a2f04b3d9c761eba5224a5050f6de7e5e4c1ca6abc52f26f84e74af87385c54913a4ee88adb3cef6db214919b078250e10b1cffe44f4a41e102f4fe0f33030b8c78ce3154eea4055393b074fa4405272723086030c66b85c05e0d346c3f6f2e8de191bf97c56740d06cd7986282eda1d5e07ee8ec28a46e1c2b69d11604e90bc9573b345ad325c8e49acfd13b3239882aa6ce56da6ea64446d5fb83fb84a49a4be566ea2c66a6f86412ca00c804cc4ceb26aebfee31cdfe2678ebc0f4bd1b03f07c6bfe599661c0f8f194742fdc14eeda5b7365f66761d6797109f52fa622d5772cc0f034f47a1edc6c5795b2568c162907a4da88768fd5735c648e3cff89b6d2bc77e4398549893acdd667cfa14b62b620d32946de938e2022a3d450fef1ed61e0b8203d40f9af74a00fb395bf097f924c66f42ab65e723ca949b95080cd9b9995d97de630d185e27f548ee438b47e42090beb092595fbeb1f8760d34e92a9a1adb952ae53f71a1d0b017b6b8e1fd9d9f3e201e8ac544a25e5bcf5b3b99a0b8f06c84fa0b5ed56ba341c4ff82d1c283c2b44700513561d808b6a8cb6c82e917dd500484c909cc405a71609cf641d62908a0f857b7a0e2032546494792cfa81cabec9791f35fd89f5ed3406e86c130cc6976e89916c5133f4efbfc31b1817f4ac2530cf0e3faea93746ff5cb379e00f02289c7ab18f7bdd2dbaab70a84cd057838850c16485672e15c9d87865e419ac2d14c9e6e6fc2d7d80706ca1ee551962f1e21beb2e447b78653897e7d5736106325ba0273604262096471f922be1eea9292ae47c08130994f98e80354178102f34c405aed4c63af785b4643fee72b5f259a298702ed58b1faf1c06f749cc02fee77fdd57c2c11efcf8400a908d5c414e422b13e5c0b563085f0923b1cf299a39031e032504ad6db77a1e47a68d02d9f0b1423c8b1937b2671d24d2df821cb1631c6d8f191755064b2941836cc9e794caf380450565e26fac1a44c769a97817a8bc32df8a26067fd4ff20e735966f6442fb24214b5e7d26c5816fd61b465b89982e07baf2c037d5dfc500d683b2074491f57730b0b8962483582b8eec7ead2e88b938e8014f00a9e849c296da5e6e42f924e1ff7bcf907542568b5a6684adfc27f22d8d0838fb9eec9815b44e7b5203407c4c26df9e26a1b38745165860ae2ce5002709d7e45b53cd01b0072c81e43b6676319f608a7f0db90f4fa142af444cd373c9c7bdb9e110af0a1cdf17789f59cf4d89ab13fc27ed762320914ba7ab1fd69946d3c0d49f9e971130de3ee50f67cdac746b3551a1ed4db5ed61daaee4390b2368dd2a366d2a03ef8c53f7c132c6a4c2d6508c5772e2ac0e38c366a7ca45025210863a97b20fe3c3a80a26c8a8e6b7a537fd0b085adc6d891473193f7bd57ba0b3c72ef509c0559b8ff68a702831638d76eecd1abf22dcb780101733d5f76b335f784c69a23b877c249ef9082ed65b2e0c1bb122064d24fe8bbf99d180aa570c28c580d80a9731d6aebb79d30699a702dfab2cd0839820fc15164a084c67e645be2a68111be16c904b6bdbc342032d12a41bd25fa705f07e7d9c3d390077751e0cd75f0bb410562d3c1d9e816dc816807c2fd523a7d5822c57eeb3b7560b7b09f17e547b6292c0b9f3582db8a1053c41e3525e32d4baf16c7c7d560a456c1402f466e1b10f1c456054f403faa007977604279e01fddfd25c1f840f379f21a2a6b77e96dd45dd56fb24475a836867dd656187fbda17f622022a1a675aef0b931b8344b68089321bf59360741e9579251f032cb1132047c0ebc28bf838dac11b5b34c3cc557793ab878e055042ef230f24abcc3f7e1e9f7e89e5f452238e2a8adb0a213b9260b053f4cd61da0a3e3aa65ecedc2121d9bc3053ca979f9ecd3cfbc53d6221ca154a5600d423215f0ac4c8e4c36b782eb66682663237c1ee3924f2537be674ca4bfef52ebeb0b023cb5d135d83be3c396cc9c7852068a5112af9dfe15c4b51ba66bd962eb0d203239b31797420cd5d3e4e1b049032f835eade6aec530e9ab43d3fd70559df462a5a701f21c276197e8e81e53d226b66081d50078ece3845f85bbcf4054a78518000f436b8663b48f50bd3fde7cb4650b093a35d05de72317d0836369da82ac563dac47ca1e81702da9cce0282aae631eb593bd30f4f34f4dbbc84f78dd58cff6ccc7654444594ff496f93473c8540dc289088f43f35055690f2e85c162ac716596f907093e9f510ad2b043c1a7ba4aae92b9fc2a35282221d2516cdcdea2ea4df1f4095b8c17d4b6e54e34f7981f565d66e7683c12d0c8fe034d2be8d9147b58ffe5972ab09c2651120fe6afea82542e4c22b973bbee40e52cb1cd9fbc67e84610b9a318c9f83d9cdc6041138966569fe25e253d4586948b97c26cd967832cf08affdff19c6fb84fa3a33fc4864ef5f99f67cf2dbca378bd9f4708a7201f0b2ccd7bec592e1bc89fc5461c3462c8291114c2e54f2e569ad4ee553f77dd3deaa06327dc5c77c724c5f093651101d42ec646e81296c8c8cb34351037fcb330f0cf4903f09e5812dda00215db5c94db0ae767505de5e465ae56ba84c67a0a51dfed967cb48b05453feb6018cd27a78bab901866ae0b9bf880d86d359a664404afb59e0bd93c05d26650fd8661f6001165417d47ba9b260fe823058402bf5d49452484a8b05b87009c34f5ffae2ecab5e8f40bfb34b77df81ec1c9f055e85322a808944674d6cb5846e3e2f81188e7b0ecf05416c4b870aafe22a8db6287b25a914bf5525b3c7921dc07f3ac4af593214acef8aafe70004ee8b31da9806d6be1a39458f806afb1abc34694f0aaa970bd22289f91b1a35aa7fa2edb828ad245fb21817294d42341fbc26117e4544be295fb62a26dd24e570eb57ea4229e7e4635a3162f736e9e84fa970562334d63a409975e2f46e2fb6d79b2c2eca8f922b0352d9f77ac10c9e27514e60a772ec8263ab6b7d47bd2fe97057efd8db5cbfbf30f0e2287f61846c462bf53e7f7c45f3ffdaf32d51e979f260638df1d6e3ee3ffbc30cba0bf4258806b1ec8c98e9fb246fbaadb0a9ca1cd79bc69c4338532e6117e65bdcde8c528ac295e261c570d46a8ea7d9dae0bf1067407b999dd631f03e6fd34f23a7505eb20c22e03304847fbf0204620fc089fcc716cabed3a8cb33c3e949d30eb84b82ceca697c4b52213d79907543ab95ad45a058a1ed9b714b6e2d2fae114ad18e542edb501df6bbf5786f8a37673a2da5ec0c58c0cc61f01578342274d14f6408e115c12f815d24fb42262e900951b73e3c391ff645ad8d6dda24ec226b1dffce569ab98fb0c8e39e0e3bc012eb3b1c1bb40ab0e85e93481c0d492b3e6b4bc5a622820f4fb5d599d51d6e6ba0c34a7b9c65e852728285a1643cd6cdde8bee4cc0d11ef47703a87637445df1686b3d91a4c0e649ebe4826d3cf120fd2f55ea1e65f3aacc592aaa923f132c59109ca0f0537ad90e54b3598a2408f3f2c3c71de1958061c427d06c3f5a1aaf57cdedd32c74eda7905756ee91d3921bb8eece10056ae8e3cb1b5a649e7bbc8046d7b2645c7bb026a87fbb150b26d5897668055b0de02709ae8977ae628cc65901ee9af4c6780a8a0166232ff779d2e698b94cfb1613af28808d3eec0da193306cf3b601afe507bf27644a0e007da8f03e19f7a86c4a3f51817e7599e6c46b7e57d551fd758d83f9cfa60c81829eda3c373ce33c889bbfeed33e74ad2db065203cd900cac17b2b285fa220f3273589256a6884a69536a83691826adad2fb27e251aa34bd9a551a0d1a09bb6d9c71f5d34d42b106ffbf3ebf4b246ed402a13b7f9d11690c1fa9e4a26ee36a2e11155a07af66fb037cae25e37ee3ec21f12649f6ac36944b62d30fd5f32bc599b0840429c5142f9a269dba0ce4b75bb95d2ef5b9b764fcdd3e4f272ab80fde4efe2175b9fce3408c932134c8ab6618503baf7ab702a0095df89d469141fdcaf0ba15251b519a959960f383827afb318ba2eb75c86abd149241af43a2e8b120fd09d95051f035985457776d20853fdcbc2e68ebabd4dc1c3688762b3678a67a81c90856ecf51a5916deaa933340ccfff5af84b1d7b62f92f73c0aa08d43a02c67ba9090706082046dbf3001f2de3f7f6c9b757fdae0886636287d30d820964ab6ae80f63695d54093428b5cb030badd66220447c81b223b993348658b6552627b2b1691100fee5272c00a3aff2e6a575f7fdc30865ae1d193886a8555d9ad747dd1a6dcb18fc6cce4ca48984b4422f9448c346c0a584802b6db8cb88786c79662a781e20b316dc6cb9bc9a710ffaa96579bd49969941d5f53a3aaa97a1777aa4836f7f5d1010e2b9efb24c02d9f3651e1494f9fc8c4a5223710774328aa7a1c2dc434b8969db5071f062eeaf10db875819ad8824d1056585de53ac9039af6897ea514d02e2d99833eac7fc35581ea10a45a6ed73f89b7cdb6a93ef3706ea34f13bdf9e8882af8a2f74c468e575687a0c2edfd7ae4eb9dc96d6584b1887d9c70cad7f80ac94dee38c039c584ed86943dc9ad467f400d8b281fa3f648e8669bf8e2b32b624335a949a0e1453ac35b7b3b879e676118265e7d920bcc90500126ec3563941d260b8ce43a1b9314f034cfb3a60cb6d5e8593163de399355723c8af278d31bf11f5a2f5f26070e6024d9eef284534c4e0a92fd81027369ebb8d7a4dcee58aca2d405d1cb3ba82754b3d43e36034586bc80cdde153236fcb9313eaef200ce6314a7961264916069956071d2b57e68a97ad963d265fc6686db992f2dc00ffdd4713dc66cc90d6eaa498b56502d1c4559178787aab3a374a172de0b17656374c0b0523c3f9724cfc2308f20c94c57709c465fd2e8f755e555882715e958c8f043521d8b662644da2a2ec1039fb332d6efa3d0fa988460acaa9de1db45de82b34eb77a4156e12640b60d0d51dae7aad644d09a652f76786bf87bfef38f5be9ce3e902c0a261385ac912ad6a1c3024379c8eece18be70ab3f3cae04aadada61643ef97439b5cac8e63b7810eba20cb6b594db640f6d8aab6200be2ea6626e3d865be6a671e2485149babf07888bc6cbaa63e5cd8236f9057a99096d821937753e1635cc52c96cd8544be0d6e1c2af9d9b77e79219fc7b84597504887cefa6b0425657360d54b0d94f22c2fa006a3ebc13bebca97e6cd1323c270518090a1660f193ad5083fd037919aca9e536e7056d54a7cc1d4cbc676e88e531daecdc1f2fa191aa7e1a3dc0c6f48db5c6a86762339b9c09244003185da2d4a29413542ca67d1b6140c79fc5a26efaeab20faa16888fb33d095bea921e058731c55c204bb819f5978d7cf96fa0255a3cc816586dc5f22e152cf6a36018050b5a1de13e15d2561bc1dbd72cf4e08463481f23c2c835d2a9e9a3fb6bddabe54c60fc6cfa346214307a1944b6c6d93a5956b9efba786a8c3eba33abda97951ee78a520ee0471a75f7a20c704c30b56307a0518eaaa54b4502dae3cb5deec5eb435b334825cd6dfbef4080cba8c4a905d8d6356b391bf9ebc177c5c4efd8d56063a178d9271c17f4eb40e2cbc4356e0d2a0fc02d0e2f2a03842acc110319e5eaff2584080d4f6edace9f5c4bc2c08e0d563c411103b4e9b3da53291ecafe20a80bbee5c1c01618c517639608720748429d64468b54e79a154e9fd00ea7d1158fde25912a226311a5097b0aed609ba0e1d12d163af422ba20c94e80025e9a4a314a7be1c6b858fb07ee965224dee7eed506ac51db9caa6d8f3f36a99b1225542e0840f1144c3abf05284d39a87db5eabb1e4e4a82a95505b82be26389ce82526f3890c448e731b07414921a40d0c3d5b47271365f12b1a7052c14d9a0057561179b5e678a5d83af07ecaeba369efab47403f5396bd3d1edf1ecff8e9840af7ab9a8b0f2daadd17e1d87b64e61ca226a1da6bf27ce26eb3468bed9d99882aabb9b0112276b742320890ad1ac8902685df39a7ccff49f2a0df2f1606fcae428330b12a7afce03c9901eb0440eb603029cd77d6f0edf488616212e7f0449c17e754a87aa1333e9f0c654792ce3b9e80a27e6aae3a0d04a7ec74685fc30158236e9853c4608087db8b9516fec0f7eec703a4136702b9d9509fc6aca243f6c63c6318b643790fbef10c31cd7ab2c0f3765c944d2c8be8a4858d26e6a0cf13bada9fa85c0a94c5e76184ce9300d3de06b1746d9c80ea6d670a89872a004b99366b9372b490aa3e640f3e605f206ea4a876f4343903f55eb729361e8181e290d83be9e2f080ab5af82b0fdc45430c647ba4c238c1cfa3c8319da15a0c2e0667efd5f438c359c0484c1711d9490cc93cc533bea9fbd28f3d292fb83d51263084a95d13c49cd968415aadf38045210c14a2e20061435eb9f5b8ea1cd5fb30e60930ccc56196a744eebc2627197b2648db8bc41c7d121a3a9a7a42b9dbdc552ed0e3ca418c560aa30c07b9b6c0e41bfd3e6d843633423778659a79663bec749ec27da1025d4b8cb6fb81088c038620b799c492d5a107ebbce934586b6c230c0429ea8818f0564cd16045bb2270a243652599ead17b11d11ba7df8e28111e8347273e169211d25cbabe38bbc25f1361ea632e321f976525f2291f39d2d122a5b875daeb7de5decb1782b6bdc1cde8e654b090f89d741136bbd2d0e5d875e1af76546b6463cf53387f674ff01e7b534dbe9652c72b1791d1b84c7789e56902f02fb5b0408c1760f0cb18155e2d15e06319646d1935a43f15a8f69ba2c422ef61542f9c365c84abba2ce860c45ce9c867226e10b765cca77b1a13ef6aac068688850af3372667074599d02bd35521cb1c1e44cdf6e9fbcd2b0bef1d6d73de9fbc1f2f819375b354c908048d6e66dae9abd533c32d23e2768078db5c7687a9d54baa486376feb2d1e5765e66e7eaf5ca124424371fd4d8d7be28e6f585a63b3408b260799fb7177a5a66b971345a9f9fbc88aa848fec31d869a0cad92cbcc9da73829cd813b6c2250b9ec5e3a7ed4adfb3d0e70070405a39ca12ece8280f51835cffd7804bd359f4f235264f9dca018cf8c9a16b5f024445ef71709c01d22057672826e28f252f4fb91fe0251b6959784579c701dd8413a8aca82a322ea4f8c9aa6ebb15dfe70245c6628a6413c8cb27b31eeecea3a7d898a2304169a4d0f5a1b30ea5aef58f7b40d0cbf0429178386c16fbaa6462897ed21ea77b2d11a1711e83c6fa2b3ae40d58fa93c248861e7146bde743c8e8a900cac376ffe6fe40d58d93815fb0288c05e2a88dec044f8c60e2fe7a7d58c1f90d3ee4a7083a02e49fead2866e5f1f12e726eb403336544e9ef2fe21b72bd7bfcda1d24714afa127d4e897685f5d361701868906231be2f8446928039a38524c25e6c215b8d93ff465b9e23183876b8cd4a2e3aa7d998d6e676cc7b3af986e1eb128626dc98f8a6ef3ff230163de48ce2a8bd83e2c97ca0b0241baa3fd70b692d8c9b1bf92244c8004d489beb6c6163d48a87404ed541f7dbadf30f6e93f06915499b1bb9015b4dd32e01fca1ba7f5a5fdae62668f91a237eb0af9139c99faaf7da1baf3c903a80f89ed262ed576464af8f9dd9f7ff03afd4a1d0654a0680e9813509580120d800dca34f8fd92bf5493e171f418954eb55aa5a934c057e387405d47b8666488c6c301a25bca11ff72fea84405f25ec9e15a5f2ffa8527b9053f1dee2e6a5dcf6381794cecdcd79658d4afd3cf73c61dd63b3130c127b3b3599903644aae3659dc8c0ee816026c19aabe21f9ceea4723c531f07cf4946ab518fd34193ace648aadf0b5abcdb7839804043779206f7a6f4456c9e69b383658ca0474b2d419aaeb8f1c8b037c6254836e13aaa78bf131bbc529523d72c44b90287f6414f0f896878119d2ee1031182e613ab3f3e69c333ac15ac79fd318890cd8173e298a4783563736e5927c53ac3b42ce8633af0072ad31318ac8de9a2c1e66a49e46955fbee7cc1349c43391a58c10c9f97b8ed8771d106327eb9a9aa722e8e38558d0cdafcfe54799ae62420611c3a0718e2cbce4a16e10ff89f08344de1c0261f06c005dda3c06c5e197147f829ee470d86256442c6e7859c1d2ad69d366c3d23cf5f8f8e5501328be2ffa6d8306e4112868402404cb5ef40a1c51892a74f7be7c256c6e4d0ecdef9de665deb5826c2746a00b8cde7c565a57dfc5a9f9790ffcd271e5d9f7a56a4568c582783f16994f850c95644187f7a49d29a3ed430d580df74a017fafedc3e1580e340c0412a72f1aa606fe4e2ab1bb2ddd7318222601f506ee53348f3484ac9f9d6a261fad75a851907c8500aea94042cdfd664582fefc6c250b830633d0126f586244941cc86cb31a91ca2ec22e6c686011f1d5642f0d6eb62a2440b9903acc27c1fbf895fed3190b082d15ffc2a447cc14cd667def15eac8b9f8ed8d4782cb121b45920618591487ac4ef3f24ce5aba6e90011f2f418a2485522072bf7f1127342620590d9c4d9d031257b5f78b9efde08b04d1bbd99f4a6d0c4e1d0cc1b6161b123ef3b0d077b143a2a582bd0f90b3c3d571d0041ca5818f50e3e4dc330f883a72f618bb49aae585e43a42f70af10ee5ec50a78259a44d8c5de72340c47937a21f954acd3cde429901018327c0018a54a0f16596f88ceb9de2dd03dfd60af7e820e1e6c2c9fb2a2089d7f5b8ff0c7b7da18741e90b670cd39347b1abc9753c54a70da447a437006a12fcab9a03cd6a10e0b09a72c8d55e834eed1d1aa67faf77470f6536dde5346f355646dca66855c75c42321409518863eb981212c3e0f679477cec752c7a3fb318fab1f93620afd328aab95f09b63c98db4c82466152ed4eabe340843af95d967728abcae0ea4199e2b140f76330ddfd9383459a0367b0d2f691c0efb1ad1c89d0144065ca98662c3c70e20ea5e72ebf40b205140112e0dc581b01554054eea16c9de6b4a131633004689b75fe4a8a11906641b500a4e4992798ac1a7e5a2d0c21c933b6ac4adc797405bb4958f2ad0b7d8b4a7cf71813f4bd254dca1364abf66770b1977e2c5cb32ca9534e7f544c632a686cb135e521f8978cc2232803da9dc02c16a36f150a682239b9999fa1980183a1a64ba438e2dae2b119c6ffd492f4c273a8405e93173ba114ebe7bc7bbd42f687c7285a0e80b402203f0e5cafa85ae7321a4b231c29368413f39569432e60e8ac3612291c547a76ccb25d3db60683032280b6590071cb22fb5ff41374dbf8c9a2d6a85622a3c73080d1f2ac8177cb66166ae31f1e366076e7b5ac2a006fc0a9e8047dc8ed5a55230c6a7d8977c441c0f98c81cda835f98a17e877e8d1ccad5281919409c47c4a51d7b9023a348ff6a6822cb5f058813c29f97e5128240bb0e7bf9683f9717fed0f6cd8510283d53043d0a2cc3510755a14dbff854b38a35447f2e849a5e9496e0506d61e08e84cdb372b7abb2dbc1863e937081027069e029403440b9a074c14e2576695c9a7c5af482576f74d28fd60c9c220af449ce91b7be089962192da3c5a7aa4174d925d922fb247ccc2af05ee0cea8916c164fa6de82d89c490d4473e781d159751901e5d92e59df91e89d7eb49fa113408141a8e921da5e514fb180a7dd371baf4f4cf58649938eb7a8010de298f0260e58e54592dea718aa5c63616178cb44c93eba460dacd173281fa87f11a6fe9ab31b2e0e0cb40b624c3e51e1fc75ee79099439b591e00666d00e13f27ffa2a388da700dde1b5a10af3bde8b17641a6b4de6d754e53caa1073049ad3a9b825ce6e9d97ced4825f2d362c0d66eac60a556df4c0f5e988b61c154d83432f77b29ddbafdd2dc7c294f264da9519876f781936083e68c4f8016c03d754ad3a9c62f92a4a3cfea3c99d13d7fef94b9ccecf6c1f6812d2dbc902e9d4669d51efdb1b7e213be7028a511ab6717bdabb5c182e62a1c03247c5de92b1257530243a45983a2d4eb0afff5bccb215d08eb80a07f2a2ee8ec2a5aaabc26a957c12624eb4d851fad26042b9db8afad80ba8fb0c8bbad910150e9baed32b83676b470c55847378579d6035e2bebe4a07c05e359e9971c94d832c7ea42744b4787abcf412a4d5da69742cb469182efc7fc33c80ab2161f3920ee8049dc0ed8379b26ab554cc75d5fd7c183e573ff0247a4074422bbc2bbf599145fb46d1bb32a83fe80e10554b7cb86ffb7e9bff8c9d1f94aa8082991455629615e1b6122b5684d209f0aebc8f2ff2d0e939a96068377ecd5d7190a208b78585861266eaae875ca08371ab1d7bd70f63e0447b9cfe54418e80c5c7688372fce22d9f8392d09ffb79d6080cc480065a364b42d3ae2119c18ad4a588ec7e9df5177644146e952815cb60c1087f3838c3ea160eb87e0ada160715c41aec5c1c18e0d693ed50f74c01bf92e80708cea4885583aeac74713f00da1b256549907135a3f0bac6cd79baf10c29516a11f342a4392d267e51733d70551ec2829063f1a82154dacd79864e04edbe14206e805be516169bf63b16bb2e258673041a95179ea5ec58e361cd6f7451a4c575a70cd7b6746f8edcfb4f5bb4efe9ce1027be63bb9f73612e3d58ed1b193080462c00aee428a5020cea8db975fad7038f947fabe57a8188d27f3289b43dd4ca0769add751f167da02b96c01066851a96805c05f4f90acff12f64386ccd1cfd022db9cb065340e5093b5eb193391e1229bd1c75d2ab5cc9a470d1cacb943409a970d8aeb2230234386e0a4620350994562f400e8abc611277346616f18cb8d6ef8b364918069511b8660ada0f638d10cf013d0940391dea6f959d66b12ce1a95e230eff7f4a7c0553edb4235bfca7926d16a768e0c19ad897b409bcc4d53ff7f692b13fa21a8a7c7b25dcc8b0465210e066d94d1307c0daab7344becbb1943cf78a5b28fb3eb4546f8a2c4e60bb1e84445a4d301ac37fb59ede5f1bb06b4c2590604365676e7e1902a907d1465e9052c0c166893a3c3e03bcff0084b74e87939a57e9e8b127aaedb0a7b8d587729b21c0271ad415d1650636fa1f461900eda705a912225782efefefbf2d9cdb6bd38320c989659085dc0482a1bc916514a8efa4a16b310664eba701c1f6c5982c8027484fe597a177d37e06b6e7404f01dd7a3ca6e3ed570e6e320ceaac27c69dfac8c44724764f521a3ef89f05becc7bbcf1a41492055e3acbe04f1e3a26cb0f1e3cf94255ff5fa1991579d9351a95843c2e5f89534567cd47c8782b41bff74e436f46c4670c7c378f9868079aa0d2b6cef0e23dfcb4cd8058c1c77c87408006272dd26778a1fa65afb1b4551fd41b5fb7c846147df4f7b9cbbdee1618c98dccc6c1088179528f4e21c491b76393beee6d688aa7e8ba9e479034fee2854b8211ca4e63fb1d655b2f885851423d30873b5da11ed1ec30cd7b6091e3140a1fe5a4ff13083f78b662048614298510f5d22b42a08086a76614f9064907ae987bf8b4f15fca004fd36d7f06023feb2b83e3de7a637d3932cd3cce71101ba60aa3f4aa786213f328fea53e8209396322c19cfb21ad24e19e3b38658f895a632971614d040bf7ef0c8ac6f8b158b3d7013a6e6801cd0097051c199db5863754448dcc663bbb774a6cbd46dab0d0704fafd1e0bda4f2b4a9b90502555415a984fde2e9d43f1fb2b6ca8f852cf722be1bcf17396664bd725207e34f506a24e809a9d4ac94075b6ec4c96d7d3f93503008955675f5c6e6e8a79fbfb9e74cee73b3ba300b13bbb15c60541483cc3b54f0a1769ff2fa97fe3de9143d5c0404ff7b99348daabe45ae5ab34dd91a65b40c5b2a7becca65fa953e064d781814b3757324e95a79ce2e557ae1cd27ae34beaf7a55e35c437c56d2bc199f4a1b461b358eefd27a18fd77f9f67e84b86c70480f0115b257d480c542d2e3c66bbb59193dd482f0055f85825383f77a9758679ba6dcb961c82de7d8b1ff780ad98944e93057267c524473f14154164b50d18a552a42fb4fb4d073fd2acd85022367cbd5758498bc11e9dbf7b693d51a196323b181aa7f6a7be428f9df8667722a01a8ff4e7583595d725607f07ef348c5cc160f9b5dcaa551ac111e68cb22764f23cab84f3fb322b1e34fe9231eca3e6bf531ef9f93ebc8fab168224ddbe9b06d34bbed7a541f1db5d8aea014d6ddd75c18effa3fae061352e3101d54f2fbb34dab77d5a5024af18875084768d26e17e227761f1160cee36d7430be0cbdd2734952169b161794d91e195e1c5d2f5642a95884b16e9240c015a4a0b0dcac2c2f189425f9d2b0c64dc4b6a058c00272cd72853b8a429121922dafccbc66d5f7d1d223307fdc8b5c4511aa2e64723e4b0580d45689e73f6f9e05e24499c5107844696ecb94cdd1da2826a9e661ef8686cedd6a42741c4d4ffb79d6a95b068681c95ce69b55864bbfeb6b5996e8fea3d6570b0ee722a959143ed5dfe9e2a9257cf533e811c9049a924bacc906754a8c46377904dab6c4bdd22db7680cd2f8d5abe5f790e9982102e8fd51ddeaf28e1c0f2fcf8bca05c8228f1f58ea78f1b35ead2d22328fc3b69fee3224c931ec1d4dd62006a874f36eca873d4a6eed5f277ec5089de10ba361a50d8a880c9b0172da3a6fa05560623ad6ebebac5ffcaa82b6e44f7b97029786d26230261cdfd60604f35b8874e296e68fc89849124ff78dc69dfcb3f6cb8e3422f0715f19927dbc4d5bb6f7c10a8cf4bec1d210f23848a6679e43d6ca612e2ca1e4d43b5281405a5d5ac8a53a196300462df3dce4fbc7c425431826e1dd36d299dd44ee3aa4b1d37de1f4e1b6d14ff9469e1bcff24c88aa67efcb39fb646295a6342f427d5c85da0cd8600394d6a8761405207e739e2a782d29ec2fec0e2883c5888868bcc81db75d7680273ccd52e4887ba51a0f07f2132d134d2d951901ff821aafeb1bf1c672e4aec3d6697919e14c7e4bb7bbfb5f78cde1390ee4d755bc644d5993ecc763fddef64d2a248eff413a85d5eba280387e2d2de6027f0b108f714e2523b7dcec2284ce204bea7938848b1ca71c7b5ec3d56d4cde0dc4b3aed8d8e5922e3db255b8a92cc08c1547313eac037c6211bf9beb1a76b2bbca0d05abe9c5c1be867495257ac4ef3bab55d766477b96ed8b955682da131e05ef23179f1dfa33ec951bd2d2268c06fbee3556f2bcc9deaa54f6380d826535aed6355031b7424a2a10fc13120c76f864f45ad74c24e5997135b396b7e15b36c16ccdff4c91586b655c87982a3bd38604b8c1187a258e8249f529c0d30b20939939a34cfaf839ea90ddbe7dcb3942396ad1c263d37ecd1f4a3aea4d344b3abc071138e85ea706c20e3081fee55812a722588cf62f27e5ffd959992bf2b80583b3b4666e4fe4d0d3ddfa32f954c7265ec794463b6b99c0dfe338c188af65970ca620a284c9fc8f4f40fdaf812679b86d2e2566baf4eae5da34e1511c025a92a250ee028e5588cd3676d5544b67193822ee9a9c561cf76a78f3be0ba55aba9c8982c625448dea74b2d2af7ae5f7e1a4b94e84d47f67b2a1ac320cb81575562f417277c4bd3f28a0adafe38ce4a01a21691a1f5a9d4612896fb5a4c95cc6bd39acde920c2e2dc3fa1e559d83d64d58e046fd0aeb6b5d4ee8a741c91722444ed2d518401f05c21253bb36b1ce5533f43ce4c6ba3e44a9459b4329bc4e61328791cbbc95e7c9277acafef89f34a12ec6faa337cfb2e100f541fc12c5b25a2488712b9bc5b04828a4ad61d4b3bdb7a92b3159ab8d2ff67d481d506bb93d29bac6958c1d52872fdb36e6515c328cf3b943717e465877e252c756d56cddf412aa9b8a14d084c7012a46da6c6f04eeb1af807d7f18218796c43323becc433e0c99e38911cbd2eedbebc3778eb606eeb8de3da902117333511a4b5067f83c4942bf3a1c14e48e8d79cebc6c6a52a8012ed7534550f881b837f4921566049e6b9b4cf681fa74f7817960593fccb28a480f43962c603a5e1026aa98865c1a241000160d6e3284a3641fb6c3ec0445e79dd35821a5238c180c4f2fdb9f3318b7938f8542135ac80e01ef800d32cdfec4ebe35c4557887957f57a06be0e93b1eb62ea6100af220583177990031d0d2f57638ec2914ef23eefcc0804e5027ade12947cae22cbef83e3a1862b8919d02aef4ddf8efada17197a264c04a2d82fababd626e3e2e304c43153a00b5acead3179346267e40570d5dec50a3532fd8e844b2a81a97257b08baf5b6e3d1cfc1239c56babfdebfea6b120d6b0dc0b59114788f60d2f584fb30dddc7913577f13b413ba4b8186ef37a3f848d58c8599ea013353de3f77e9de9d240da355aceb3a3f5431b8c82b74315f7857e12d8955217a031df62a9be321a56d27dec6d37621da721ea5193f74a7392d3b15862f55128e04d1961924914a51cac241a28ed4392e122b66249698249e6a0444dc5356468c17d6011d7de2e786337cbe3c6e9f864c7372a19c2e65ca793631395e27b8bc2c99c6b3f88995912be0c0534a79fe2ae9c05b21a2e7001886e3a3f35838270804621d0dc7ad444e84682750d6b86b16a16d858f72678fde00df783967d8df3e972b30972be1dfee438659d157affe10585f419de95c5e23072e8be7c3ba98a2269f3acf5191bd55f0738842ce85da327bdc3677e2e4e157716493f2e06e1e460544e78fe1b3a7de4ec77a70ec98f89aa653a962b7f501f48922a029331590fbdad8abd9d1d702d76e8ff2c39dad4d594fcdd58a63c7d58698344b9d6ba8db4d239b631c019c4b7b6692ff3bbaafe5c3f46b1c418c17b6f9ab8be5f6bc5ddba4f1888f7a97263a588cb0b58d73abe16624c18a5abb33328400b7e1f28e0334601518e1d5fe2691e18019517830ebf16b1c0c7ef2b5cf2e5504990d4b6731603f2c56bbae6d4e9531509b90c6d8d2329546d41d0a88281d61c0608d3d2df38a1b323a8804a64e5981fce12e5215e4fd3f0cb536d9beab41ae347993a7a49a74d16210b04e8fe373b46e9e32233754a294ba236bdc7f393e421e099af86fd1bde2c67008dc3b55cdd14cf6cdee405445616c32a6399b1840b635575d5b0cf765d4f003096d1b1a1f3bfa41321d4247ebfa084b7251418d384ca95c54aa8a7d1690f2c98529413df6db4e607d5b13185cc1286198c6a6ccdbc54c8d8bec0607ed93a359adf0004f2c29ea24504733e2a7300273ce96a02dc8c3f062d200e687b4ee43ddbc247c5a6dfe1ac6bad316b204cc03aded9c5df8b54a201a66f940baa1029f5dee6d80d651c2125eeb229af7c762f610e3f714b5fef6033fbcc6f3de1878b88e28ff1183d29457355de7b81ff22bdd7277b945ceac73ce525876b9879bb9aa13c57bc9b098ed31ca5162e46de64a72ad1c66559b59e19b9e861f14b8bad6ed6090ebfdb885c3d39f98827e6c8bb2612de0b8094ebf01b299ab46f6016bae84c000db209bb61a110bdd75d58da03a7ca476947a3d7eefeae847c0e52a694217774fe6417721391816970bf6ad2e223cb02232f7c199b6d13d6482e65179bd6f0e2763f5c07af029d2ea1101316bb0fffed542d93414e64ee133e017dc4159c899bcdfcbe5c70499fd4f87c247d73d4e354ed316ef298ef31d5ee53b5caa00e869799cd3eeed50bb0796f4a35b245d932bf274ec701b2b19e0873958dd9b5b4b0de92fd89918630a8ac8d3ddddc3492869b158a5d2e54ce431dca2f125ec0e8154441282d3dda057de1df131bab8467b617e5ea4650d0749a616233c657440bd1b567897e0e427bc85984f3497c6691a399ea7fb834f3cde81e3490c341b40f3f68e66282447360f821abf12fef0a235a821938d41821c56538f4d147ddba480171edd8a86d52160902a732d1ab0aa5427677b906b0020abf45405bdd430cb49854648f9b678dc95bd487f4a514ab4b896544552fee0a2e239984de6a4e1851394f9626b1b070ceb5c49be16a80cf6f0861c059d4072db65992bdae58e933b4b179cfe18cfe886daefeec614e889f4a16535f4503ef4ea9d0291483769eee36cc34127e819c55093445032efe2b79375377b82456c99665718e9a6947ba8a101cbd57986beb7c0befecff51bca04dda19f0121cba444ee64adec1096a3f2ffbe484d27cbb736ccc841f34ed8a0931571d8fddfb1271ca2a8c679f8a8b3ad641e1ab4c81066c1338bf1022d50a7ac711dafc3232dbc93ebd0e8113657c247b4dcc5bc9bfd3faecf3e5e2b269f1f451baf4c205d75010ef647fce7ef486fc4783cb09e232ae27d58a180d70ad4874a308a779577925a5cc80d0b98d3a512c6290d0ca87a26012b467589facdba6d8780177b42816d541bd6443f5dc67684737d395dd410db8d4932bab0189f63c5373edb6feb15b23fb25696b81d2c50e2c54a3dda43d8e93eef90a9e2dc9142f0f6f10eb385b0486fe02d2bfe8d9aa030d0a6c8403b732e0fe33213bd42205a7449f147426b13784213ecd7c742a9fa1d6c6c2f32c3dbab27f1c471fb0dade088f67cb153df2d47350eda2da185d03ccf52dc39203bfabdffe14864c783aa619e70f4ebb394bb6d6782602c97fa7b5feecdaf70000bec5541886ba95668297d5976743ec65d4d596cfae5f49c111052effdd3bdc53aeed01885ac30904d5bb495050d1bb9d8a8480dcb4cd68b983e45af73fd148a412bb14ae13ebc0bd04e4c355ac77eab2cf30b01f3bf02292e0eea5828548bb130a28c4e91b768fcf6cd2bbb1112e8a31e101a2c4fa3e100ecff29bf1c92ba5add8a79a4bc9b886535cd9ac76be2d66ada81d2c929812edca9accda0d7bf11f69671f428699fa38f46ec577ad29796971416359bd464a3e644cfaf51a0439b4681a79835878dad6e891d871cb7afa04a9a73e48e89b2c753ff7389a9aefbd1de4dd39086b061dcb17069bd795df0309845e4bb7fa8a9fb8e307bdc8acfa8296ec92740101f32b4ef7a2774c21d240332fe05f53a57d4dfc1bb3ec2fb6b19ea54f16591ef44d471c307b12acbfd52c1ae3d99d240a6ee9d61dde92fab36bf17bcb601209b5b9eb3cded7baabf5296793344170abfc7c2b758944b5acc8c46f0ba10a2b9ce831ad0000baf861f2d4f5a6107997d85a3a8a1a73c01529ea88797f798ed5eaee9c8e5c40d215a106ff21170f60861ecb2527217ea8d0c8ee108e1cca4043c6861ff85903196c23853f7af43bf3647a5c75543a1a5d375c4b26c9c3ab032ede9512fca8ec29b60e79fa7e4ed103f8d8ae392ddf99f0dfc14759e6fd7e46dad3d5425121585c3bd3315a3177a824cfe93668e65080c8c3396822e05413828f2121d1263b4f0b1d6f84884f529f0a1cab6bd17350bb22b8ea145b78d163c0a3d6cb707a44a50c2dec00451896583ac7911808c199b04117d54aa59034a8f234113b317d8df9f37d31a041dc42d7ba03a2d9f1385b2ec73cc87ba39b8c08ff5285a7b4228dd491712148802888a91c3a2432566fed1543db4af5006bebaaf87cca93f56e63cfdfdf4993229040a161b103e5a38b2928b03a7bb8141eb599c7b7e25ea0eaa16ce387915acd7e96d5f99fd0dab5a5c01c8cc111baa9b25d33aa0b63c2700746456d6595c333ce50cf71e2f8c8c96cf0bb1a2ce7b1694cb30e838e4be8f6dfceda47c06f6c519d3d79d2c8a88f1631a3b87f1c289c2589e695c83a7b054b51ca683611e5f18eb122fd483a270dbf9776cae72204c8ca193e0b350b4482b61eb533d3a33e5abf0a401d0f613c169bca310bae1f9240b9bc7786c7c35d92e71b508f99fcf541b196e66ba75ad906fa2be9b1027c70ab54cab14b9addeb9f42b54ba02080965b7055e2cda15aed067ee32f09adfa1c7da86999c70030c67a84468d9e0249ebbe64fd69c9431bc273c49d01f43bb2ce7a28b7f5d787dc7fc54845b7b288a7f4ccd893c07c39d0e384f4efe44cb80ecf4f7c8e8d0a815181252787250a2806802c31b0501403b23712bbccfbb5bdd68a6ed64e289700b87f44dbd3320216d830447ab23e8288a29104dba9b84924488817325f726f254b18c5c6b831ceb07b631a27b45c738ed6d712ac03f27c0bcba083705525725a2b0eee2d971b0261ebadd3b06f0de7c2d3654d834d442fc9fdcb0adefacc5cba34fc6cbcbb15bf07e187e2bbbbdbb758ee066ed0f565c15b80aca416629635828d3c425f2c3eec15669962032152d919610a60acfb5a2af66bd212d23b214a50ccce084c68977e94b700a08b249851676955d029eac99df648cb8378c826236f7efee73ca55cc81a82dd4653c1c98dc8fbc45001105b50c04621878c9bf7527a19593ee82f48e071fc3d2b7883c9708292534e6a5e831b756045fe63e9b461866ca7a52766468a04b2948516cd55200bb3ad7b3216ccb90930c3e6725c7e1148ef15d788a9a89ff40c4cdc365bc22256f9ce3ffb1a19128c989614ece92441444d0385b2a683c537812840676654f3ea9966c66a66b0e33a0b6634d83b92eb14ae48a79c9db6bc82651cadbda74741dca06622dbc808bae112b1abec665cc2b391e6a46eecc8a63d1d1398f501020994ce5e8575acb81d3a759720188c44efdcc0dd8b5b0f8ec5b9bde233d2fa03269bdc41c66dc5537fbc56ae01dcae590a299aa037cb34633b63ee014ac79d06334ed6582583b9c1796e1b39e353671cc815b1b1b464c8c3822a34cf4c3a83b5c8a92408080ac22da3f37d68233bba7d1da80c1252aee945b61a68219fb199f0f8aaa5d2c29bd302511801de2b2e5716a6ebe0fc7c708c01525729048c3a23150d9834a41f6ac57559564c1da2a73084eb9fc546507ff9a9f994c4743583e4a510765e3ea7ece69018922316c2de42042e31011babe13f984165f58900286e22441f134d58a096b1f1939df6dd1340d2d61baf71fd9fae7bc3101e3b5759fe7f6d167c84a01828f5b22941cb577bd944c7ce4fa07daa0e385514d8a162cd3dc3d888b7d763d87d2e8d7a9811d9a144da530542cca36b13f9f22f8e07746fa808b2fc1614c8a0b25a0af80b39e86cd335310f294dfb4cbb1af0b8f7eb3c57d35592b98a441f40c1bb399b51f589ce1f5b62f5d2c7c41c9e1c239ff219bf64f324e2bf343adc3e1533be523eb0d7d7937d520b44be5b695bd6b86c11f42fdb8b32021bcefc9dba0147f3befe0bb4ea334eb71ae5464d119c1689b269a3bcbef66c96dbea31f713644b9d93210f3611196c0d82a56b8097fbfa2a493e1a728e878785d228ffdf03926d2864b69ea75e614421e18924a6650a3f056bc91702927a89c465084653da04ee8123c34f109d804fb3e1f6cc88aef2db977db25b82b7ddbc53ca2dd6dbf2e44100ac6d04836b330e43e1c6b6a72df938d7ef12109dc927707c08f83bede6866f78383ac541ae9a6401891d6c414c9b73d913d01ff7cfaec2b7ad91716b72bfb2ee3df39775c56006ea64575f2a3683d1ee04ad465a0f057f5522de8e0761174c534b90b33dc6dfa0358ebc1728dd96684b43778772a566fafbe9dd0cd752481a798668a6a2bd1321d00a6c949b11d92ed1971e82846d4b3d21243736818ea0acb915f0e62005c567bcd8dcfd931684580013f19e1f9d745f42341e024b728c172ed76eb7a33ca66d124362fd7136588872e307d839bf83358c186d629f4a4033b3501e969fa6ff5bf625a915acb7198ff795a4b0df5512cc1d63a118e0e79fbc0efb27f8a7efc450b7f2995364f151aa6d16be0f28c5e885bb79b3d3443835a3351868766e228864b1cf213c841b75e645d12c47b8620eb8ac28e4d9e616ec6312918154218565fdf9e1a7fdd03b3fd910c3373d994b1a6e23754cdeba552fb8abbabd237ab534377b75da5b0f3c35754071b2e9658dca35bff8fc623054127762e483cb4c24738de817c1f40f18a154cb6756eb56b4cac9c7b213366729e11a68dc062c92f5991a51a8fa5431b64b3573c525265fca8359b27d4b96b6612e56ee822a9f5098322710a9b03e6e779980aa4352bb6f41ea46d5c20c60899ad372288614400d2f2fd4ecd8e807e8adf85d83d6bd020390d66a4023149f13764e5c9fcbbcda52f26203e694070f6a0c3a53da7da654557b6ad158b1d82116c3f7948159c56583f3295356d3b05979e1adae79b14695ae29da5a570017de0fd49b774df2665d1d50e1c4f045d570d4c0fc9405d4403369b1d6ce2d96465210a6842af5a0cf32a36cf4f7007efec832a411401df65b01807a201109312ab37c3bd6a241cf8819a56a092ea2ce1c5c62b7288f973a9888005875184049d02e044809064a8cb7ac8319f5f8ff5d4d93354f289ec8ee781cf513d6c0f191fddc5c39e13d36c39c94c8d0b692b613ba0c5d70e37b87e33f9d0b6235042fa7823f1225eafa1b21a6696f13c3e9ecca171f66c8df9ada840d30a4b1c9825cc2cee39d12f81e5ac2d2c3665590a113f3490454a980411c03398a2b3aea823bdb9310727c5c66a68d8adb0b9daff1440824384040b3062fa83933f7afbcd77c4f7f17419bb7653338b2c3a6d192f2b9d7d46282c62b433ba05ac09ae6e702d604ae6f03ac7c6a514add6f2cc2f202a6daa7fe788cc74203273bf8f145befd8b9a08d83b69f3f3c6ba9a9fdab1829bdb4f0b7a04e80e928a019834ed0d14ea4799df8b1728fe63fd5c7b298b6a053df9b71900a02f3039fd108d5f63e4d4b90bff24c07a0178eca9d94e35f2b975f3db14837557517add5d8d48f03e3d468f621b1ff248d240f2b8f7936d08d8f396713a6d24e5d0d2c902143e38834ea6c92c023f382d5641bb632b4b85866cfbc155059b77f43062a06e94515ea919571340182b05ac3cfe9b47abfba399ef6801ea08832d20f3e276d694329597d52519a348b235cce764e217d465f1862647d17c0b302e0f4c6d04a1e88d7fb829fe8da8200e7f4e680aa49cfdaafe457bb2630cab8f7c64432c5a8b1929e341f309938e7ec05f16465631da31f9808650958b1681afdfcfa2db66014293044b49c7125a0ac8d95194e5d78899964cc99ee08d6c4a9261126e9ad253c6ba2ed12b5acd7992676aba4c29ced0753c437f338b763678ec52937eaa7fa7931b11ac79bb0dc36f9274d0ac01ce0a9af6e9e5b04ab3ed314b7d7ea93f35651f6f04977360cbb008ccf2991489c3adb9c69c73cf8935df4dd44edb4a18e870438acf53d1c2f278f21718cb4f40f1115477ecb8583d79f46a4555167b6a10dc93cbe402d884a08a1855e9830a2c1ea1968e17b74fafb4b6bc7e0092bb0dc09c4c1c7688bb8cadb717b7fbae2888202dbb03e02f09747a0cccd884f52d0965b95eb218c043b86151fc86d43a54b94470a61c36c6cd5ffa04de8e3bbeb81b67f2446c317a4b135ae67391e9e97cea032f8de2dc5be845e8ca1ae2950b0ce06bbb356dab2a06b66917b5c05b3b8a1606b36f718644263e298b6097c0ae42f44667bfcaa502ce0da0b202246c4cc52484923da6197dfa8c732c74237cc886c5c2e9f58e5b1397e460bb9d2337831354f5a64f71850b22d80e3de454a7c639e0e14a7b6aa0ff289a29509efdc604c85884b4a604102d234050419ecdd4610f9f9b32fa04b4f3922038d260b6de6fdd6e051a753b20ea140339e546df18f93eb4d485c2b1e9b6ee057fd46a2bcc1e2d481444b512026dd33258b3dcbeaf033c4e3cb7bae7bcf5745535244e6a1fb03cbc94ce5d617a7a8a996b28f05c11f51fca8a2eaa2307a0d8c1d7893c474e69b69758c77765ffe491f57f5b85c5e53f5b637ec291090c2b08d86317fc0b8ec1bda77369fcd8fd40c8d689499916fdc0033c6c56fa2335fa14ea0421fcf23fdf00a3143b1524e1e3b2745d81a002b222dfcefa29db95f0f829ab749da1a20d889902bec205ecdac8c6f214529d33761d6a8ec24a04dafc3d25ed89de4fdf351ad01c6e0e91ecee00b433be5bf823c163f31d91760e80b8d19902ffe5da031cdaafd025e91a4394cb750986be45c526263548e08eb926d1b5b638e5277327a788caebf07c8782b42f5eca0bc45014db0618ba0d8eab955e2d4d0cb7a5215b206c868bd438e947e7fb7221e37755da8d751caa04f220db54131e5cd76403b00a94c999779651b43bbc01c0c0e23a74a27551fb7c96f45a7cbbe994eea8bc2c9a0ae81ef3879360056fb5a43085355cb4b832c8abdf263f857049192c98cf3e1318270da30c5d9225d10c8761107801e68d3d9aa9e35877b8a5d76a06b341c81338b4f15ccfb0fcce01f37dd1e3747f4895c4a6ca2e89be3796ea4c2b00a9900a94ba50e4610073a2ab9b68463bd8763af7aee2671ffdef538eeb9c8b4746427f19a8a2365aee2028072bcf9daed0753a9240ae3bd2f4a09cd53b3e95fe6152d402bf285a8459cd86ccbca2e04914768615890d93368eb763cb935046e12c36125b0ba6e6ba2d3656562575a624d0b98eae0cd6fc4f7bc2c925ea4895551f6ab6090863788574306d47f28fecce88161721ac2fc133f29e7842d8268c2569f40f32107353eb68053ce5f3da75eef930a54ce09ae09e6f1879e4f7fb7fb87211a1a5fc93b5905d01fa6e8086d90980aa99e24bacdc314000ce595c820c567ef75540114a4ee0a53bcdee95048d156c37af05537d34a43d6358fc4dacb490a246bcc0ef4143ea7b5e5cec3bf1a4b4c4c3199e8e6e4d43ecbd6d90918ae69b34aa50ac157b3d1266f69d70904db86be994c4322fa6905d3b6c72458b99053566792b09379d25d46bde2569917429033668fa4bdecbefd1ae20adf245aaf28efa65fea5d1c43107d62459badc13848d86414104472b5aa0961d2c80a4e3eb2821c0e88a695096913fe209149372bf8b9372b18d9b1218c4620c48323103ad667851ced6a12af147dd2f476eff94c53e4b2c053bc15041eb12324691c6b94261c69132f26ae6245d276f32b2562875fc723ff8b5210ef9b48b653660fcb6f371747c0d09a480dd86217086376923e7f69de6bc1c2876e1a612408d1b47bd40f8ebb832468d13407f88732aacabdf5b7ebf047b5c47f51fd4135611906040579f176fff7d9b0c3beee700d3dccb398e3ae56ca264a5ac3b891f0588043ad514dae8ce75012fa3fb67eb4c781eea21a15acec5ccbf0d8bf1e8ba0cccc459218037d41e46614ef66ff904ffa6521c7d04b8e736646e1371ce0466d484308d475f021b68ba19cc8b79c318b66e7fcf4176a390133a248b157171f0d3dd6ae9397f86a6a7b9268b2a4d5dee465a968afa91ffa60327f8cc5419af97a1b529adb4bc51c0ef6595b974a732443129f34f4e8213ca024d63735ceb51eb92620b65a36b1282569cd90ef506f1853123efc9dcdf78125be37f8783bd70985f2df8b4f0fdfe83c8246d01253571925f4798c777e9a2e95a58e668be2a6567d6eca79f253f528f2e85a06902edbc60e75da4fdc633ea5000fa4c3b6798106bf99a464623b162bc5a16a9a6b9924a65296704b7a4fc24f14dcc4a485a81026db5b1ed7d1b6e9cfe2a1246a0d2a3db62cb90192481d1e2c6ec03f4def60a2937124100a59decd24ceac6f14f07c4eebd992689d765af5a5c8bc483be4bc435df2f70d52152d5ccf52497a51eeeddbc05cb12c0899fcb9149dcee730ed125bdb32b86a6978709f62489e99195c11235455d82c286f898fbdfc0e6481aac1d5ff17274a02a0f447c08cdf8c4e77ba4dcc87938f2f52592ec606e8a5ded05b96439d004d1eb26a74a053adff03a2d26b9f9fa8a20818e2fe5b1e861e32736d0e59ed7a353b3d9d0ecd48d5fa2f2fb78180c24e42d0624265e71a5cc3091774880baab5b90c19f79895235dc45176da570106e80cb24329f3d8aa136f4ab6ce3d5f1b38a085a973af59d3523ba86184ea9ca4843f3bddd16022ba0aa3bc4218ed8519713c8295470e0d4ed6a865e69e65b3fe51d4ca1c5a42513fdb9ad9c60b82a39eb5ba7e1834ca147bfe391ea24ad36eb00d4c01d374e20517fc1931b83f9caf4fc047656bdf44cf584f0f46601b43c72bb56d92b6385b1116555aca22ef86548483682011a7f9d9e8004453bcf6a01322810f68e710dfa560ce55fd8eb23f84223ac182939f0aeaf3643253b2ed8171e54d0ab621d6080ab52b045f71629a6dee8afbc25165aaba9e1626839a25c804531a276373e46bce0aca2d05da8670ca73fa49e79c499486e82b050c9a5aa62b66ee99d2d62ddc539a95b70d95d9b7c87f0cf56bfafb02e04d3c3f617bca5c90144e80082a9376fde6db44a037b7e1f9687352386b6f202c28dda95fb0dac78bd09af0a34ab26e533a4da7b819f511e9625a0df3ad6adb2c9026e2255bae17bd671f17128a4640bdf8498c99b886af32ee0fc6097100cb7b2d0e12024cf740b58bd6346f4e9969335c319b646141a77576bd8566d13c188744d5eb8415718a7150aaa18e0a202c6dced26450a82a409c9aadc90938e629e4d2f737cb1d257271e189c0b033216b3729d2d872f5b622c23055e0838f807542e95a97d9dfd6b9d616a07ab5672279d84a08de686352adc0a145888f28a95904a5284497be8575ab8add712e55e1a651285a9226cc7e3f2d5a53a510dcb4b320c09f72a55c4fd3ef13ca1a7c52ac6ab1d74f1fff99837a3a8e30cf522cb3f9f98e7f1e9d8eb3ed3b8d0f48fabe7d1ca1c5b0dd7038056b66ea1d4ba5b1afa449930398e241af8296cb3e570fa60184dbf267862f4b1d853727307d899d541688294a3df1c4da947012c099eb55966f659450c64524b507d4618aa78a450343cedb6e771aebc3b60fb6330295fe4281344028a53cf4ba86a73f5f60140bab24dc9790058ae2b1cb8388da58c51d5ec704d14f321212275e2748d886f13e580029a866f6680bb2d032c4989a86449d07c25c14057b06552221f447005f3c06b68085c7bc4a48a6eca9e92fc4472e771801010d3fce4f7092feabbd38560b6c8f36644e3aaa5a576a93a886057c78d49874c45f954ea076d33f61c8c2add4a81f5fa5292348c5262471bedb2054ad8760593228c3bfdb2d86f8009aede865a6c68b0ec6c9e0335112c9546e3a2624f792f08e05153c55e680bf02e70b0c121a21c10cb9f6e1092bd6ada39428508273ea86dde5a6e64a188d8b51ac02221f2a9222039a331c00fe92c332e0ef0918c0df77536599743bad0392137d9d8620942fb16db349a29b453d671eec323b93655ec6f5eb42125a74c59a55ad34935cb47658827d09ce65fec95daaaaf16d41517d191489da6cf65046cfbf8a825d4edf75fb0ab18f03a905f66b7375e517f44f0e437775ec0432bab09cf9b714e9054b141cf03b40612c9e4d4ebf58dc3de3d199e9e0eab1be37dc95be7e3a42801fd68434244a6bc543b9346588639bd429d387e9b0eb531e7d8a5750df0b8a516e684122d3fa9e85b14c34d7f0abf40fcf438c613b9c38bb80f01525b8b3371abead18bf858770a63261184c671b3aa63a6186bbec8ca2f684de22c7db34be8413fc44d3c614ee7a8f6b3d357c87108dddc66754fb69500cc3c8bc56df15cae4cfcd8c51c3836378ca408b625f9a13cb43c774c57ea5c7011822495e3714be70f53d8016fac465efa9ceb02721b8c9b7efb489e1f55c6f69bc48b21daeadd8ec5299ff427651e48217a01718189464f4b4878755b8b83815febd76dee6432489150e332168249df966d0ce3b38fff248130f248eed1f1618bccb8452e465c89d29921e6fae4848ed851d5705c6d186e781a72a2eb893350e6af1d892c8ff44c64963b5aa12c83d320829f90ce93db71f5ad44b135d1338005942925b1a966998d0d449b94f339cf710e42ad5b72c0c052e34456f1155106058b539e81214b4b16dc3e530acf13f436e7f7b1601240f3d6390853cfcbffd40d91b1d8994d495f5f48b59cb2526da5a7ddb40a05e4a209396749fd3144ff379edcb1de1ba81fcffffa73adecccccc7677ef14a1125d12ad0f3639363e6c706c7ad8f0b0d961736363635363f3a326a7c6470d4e4d8f1a1e353b6a6e6a6c6a6a6a6235dddfdd399a554a01be61ed2c69724df6d78a3f747b392503938211c285f003784a2675007777eff670b777bb3d27ddfdb5f7436980528fee5e35ab1453ba016ec15b3098b752323098b7b2ec49f7142c26d366f5ba67d99330306f619a430edd9ee9350be4c1182e83030e9ea98f6f24d6929aa015ed42b3c006b0c05a3baef98cb9e3fab4ec2d3c96a78db9cc7a3e6d3e7f6cf65ebbd3dd5db34023dd61686a1638001b1c60d2dd1e2488dbc0b878a9785db3ba632d91785d3937368fe9cef8597c138927d7592582c5eba2cd4e5bf2640b942d915959c94a2f5177b38015e50a2dcdfaaae86e98fb555673f9a34f16bf2886a4bb53dd5d45771335eb23d25df3ec69fcdab53292d69c880f121f34dd1da4bb9334cb7b028b97de843fc29a99b1da998c4b2b767b65dfb259e32991646b85f217c9e5675c7169c5d2e7da3c347e36cf7bed90f1f3b5a6790e650b847fb440f88fe81f192b498f4a9f6b7b64d6dea0f28b747b359e9fddffe96e547750b33a0ec42a5913f2086d666876dce488ff2336fef87183238a6f3353b362183b69b9ce6e37e33afb4b6367978a3424152d4973f14993af8dd16e8fecf68cbabda2eef6e9fe5a3eafbb859a1513a5767bb46e6fd6edc9babdeff6c66e4f3ce974abeece9534b1c3328581e046b3382fbadb46b3b8289dc37d5c56d0088e01f886a3add1887f64a3891b80e86e189ac519299ff420fe311fc9d3d2b0c738ae308ef46359fd8f6cedefcba436dcdd37dd9c92ee8ea159dc0cdd8d6f2896371cebf6ee6eec6e1ccd6a23e01be69a8c7637e7fdd0d7defb5e521fbfbc67fe9bcbaf3d69d6aae74a6ff6595973a6b56b654e9bcb4077cbd0ac26d2dd2bcd6adcdd2f34ab81189fac54e6f8f32de62eb35eda9aa9dfaead7d0ddfb0c1eeaed4dd3334ab71e01b8a7ff4b2d14b235e4c235a92a434b74b6fac92dd1eacdb7b757b40f4d7edfde08216d050f5164949aef65cd88210542a23d0bf22e00b4f4784c7e9a0ea0f244f4f8c28a2f3ee6b7129f8beef73313ab9c9898700d48780a3cec1ec390240cf95329d8cc017a393770e12e12aea9c333a21c0f57d9ee77ddef77d9fe7b573de0e7a40d51cc7795e747294772e4ec0066ffe8e3e1727385c465dbb522f4e10e0e25c27e74e2f4e10e052b9f7bd38e9eefcc47559a86e5041000286e8dcf32138ff1c0122203279c911f0048aef804428077d8893a7bc5f108084ef802f0818a2e4a91728bee339ea6588d30b14dfe11c74d3cb10a517f0c5f3f6214a5cb9e2ad542edcce8a1043747e7a4972e99dd5ca51a6d4e7a9eec92704cab90eb5e23b2b17225c9028c08ee729972750b81dcf9128c0cee7bd926387cf579cc85bb9caa5775c56563ca57228dc4eeac9ca5528ef272b5f71ce45889473a8172144409472ce855079e7b292a3c7e42523d30b15b7ce4b2f54dc3c2f40116b757a49f2fca47279a27228be93f253cab9959724cf39e75e8418c2f3d44b92e7294fbd3c81e23b2beeadf4e0f98a8b104378ae7a49f27c65078fc8f3ce050ab79372940b146e07e52a972748146027e550b81d95abba957b2b3c3976f87cc57bf09ea09610b1b3f22284088854ceb91029771142a542959cdbb9410396934ec3557a31a2e2d63915b7a0cec1951c3b7cde3991e73b2a6e25e8f35e09f25c48e72515a86ee00007eb4618bdc3b94081f2040a1227cf47e73b9d0b1222705200ce0589ef091411382980cbc891f85e44e0a4002ecf7b0b97e7dc12d58d1cb03a577ddea71b5f746e0318a4f33ccf5b013d67019dc5545a6161d191a2e3058bce0f5656ab9595afb0b0b0acaca44c2b2dbec2e22f45dc8ab7ac386b25652a81beea3e5f792caa95149d2f74bed0f942e78b8ea5333d31a5a5468d1aaee3450d9d1fb4d4a8615a7129d209a306a73345e70b9d2f582d2d3a5274bc6861b918b1d470a1a5c56bd45871560d67b5b4b4b09cb5e226969f4c2d5e943f1600a4d428aa616aa9e12cd64b116785149d2f74bed0f942e78b29353a93109870ad74a6e848d1f142478a8e173a3fd091a2e3854e183a535c252fd2995294bf9329b3b889e5dd4b9127450a6785ca592e2ad58ae5c54d255f597929e2ac70ad5e5e5e8a523a5fe87ca1f3858a89d3028a4cfe81be02c10ef46e653a994aa894a7565d27644a977216172395b78babe1aad52ae52c2b674975aa55c7b2624999bc04bab7d2a95629479d5e8a5c1d0b57c24207505cdc035c4d2507537081555cacf66681dfca8ac957564a2b2b1fca576a147d2ef08773a95c4827440c5ff15abcc6f7d5f8be156f713162a9e12eb8aa468d156fa9e12d2b2eb8140de132e290b0780d17d27d2d9e8bb81512ac52449a585e64fa5e8a586a780d67b9d47859f12fe526677111220647b3f26263a572a55e8a4a8ecad1f9c9f452025fc02a252ca8be315445de8ba95b9d3cefa67846ed72e2b9bad357c472118180214c454208f13a23748eea844ce970c2e08074fe15799e3bd7f715995e7257f2a2de628cce0854ac70a9bc1593e7208c1c84c0a5ea56a5931791609592cb50f222d2eb502e83eaa5c84bbd90601593a93bbd18b910313820a07ba6d20a7c519151ca4295299c5145f544c5c580555482b282b2825282b2825282b2825282f282159415940ea7c495564eac9e584571f25515ab2a562138a9844c1122869029689cb14a3a038d551297d4e114714f5220cac5e068522f28140c4a50ce78018b73412931a0c48413a5273a9c971fa8cef0dc539d512a39d1e194a094a094a0aca0aca0081103d55b84711232058a1031aab8c02a2eae4a9512142162acac50a1a16a1b8a546374381ff80350ca0af782c3e5b93ad58b0d162b95868a53b9ac4edccbead405ab08244315c58bf1fc7462f50d19b08c500eba8a5451541ea505aa2d5432e870545ea8a6b89c7c8c317e7052954edce742bde808f14adc8b2a041d8ce79f8baa0a9515aa2a542150a9ace8704c9c151dcec93d4fa5a10253ae9ae27ab9c105cbe4adaa42062cce059261840e07f4af091d0ee7e0143a9c335c459cab48e70b8e86d309c355722a604c2902c95049e9708a5455806480553a1cb08c1074382597e7aa281dce161e48860d55149d2f389a920be9389a221d2f5ce0a723a58301918020192e4fe70b0e08f75244c4e7427951fe5c27169715179004a5b8502f45980897c94b9c9f5c8aebf4f2524482525ca69793178164e87cc1d1802f9c8a8c54b77a010fc6e0c10c8a945c2e240999d22f42c668223c17d5185ea568c5045772cfa5b708c3e50999d2c17848a0b8c02a2eaf8888ce5fda13220647c379ae2d58453530e1ea7cc5c42a021d8e1335746b75a3052cce3fe77121099442d5aa5e7563b88aba56f58af3d58ba350dee22c7e04cb6b78b7926387166771a2961722968af3beee3b7920ab48bb56be529d4a2ed0573e2b2f525c2f2929b0522f4528ef4c7e4ab9108f04abb84c2f42c4e068ba22225ca0e7355cda8b6171a181cbf3213e22529d7703d509008d01557b9e8b0dcff3da0735acee54f2a070011492c8810a1830832dfc400a1b3c91802914e80114c4d8017de002bf530978e0eaaee0441251605ca70ea6bbbb9beb9f9ee98ec04c711b74c182a213152eb0608201468efc744d118f9c200ef305c9f1151763b88a6ccc60c309a04cf1a8c004a60a9819a8be66e2ea604c8711628b1394c1ca421715e8ba2eaae8228a0b092e290bac9e72b281572a71d185ab54f258a0725351131d580016927c60020cec94ba265c252a5c5cc14d26afbf131751e0a20c930c58a8ef6445941a971555b850dfa9046060419562c16a8b15704de08c60ad5c9cb34e1cc7751d0c9af079dc0b367ee02a5a159d6cbc0016e154c66705184c5979a6d3e9048220783a9d4ea7d309044110ecb0309d4a306842ca04b24a251378e26ca05e4c3190c1118ab0042a492461891e80a7d3e97412a9407184181258820919008500e3b9ea0827972a8a058c0882091757250a186330e10452b090421935e8380e064c445982e3b8ae8b6201cf0b1858e12afa7e6035151844e1eabc733515141c814a14118052a0703aa1744025064e5051c113ae1f3a1548804a1423c02da64094010d5c91851514b10221f0a08ad3ca6bee046350e138aef3c830f1e0fb3eb074c519575439ad4c2693e984a2820514d52a954aa5542a13948105074a2817d4944c272aa0eac5060e16ab9442994c27d3f7e140f90bb0e05a19c12a054f9e78d73085093680f2042750c1bd2dcce058a62dc8b040698c2324c105578491812b388004df0cdf4b4e099a40e30c26821085123bde0ea2ec0000319c4e2a950a9660c2c15281192ea46e9c58a5d24ea9640271ac20010080e1f4a252ad6002df0b2b1b1d00000a582ec880a585ca8a95aab18232502c4f6058b1c00b2b12b8a07a418dd49417502c38c2ca890551a8612a02554a4206708a962f869309c74ea9543a994ea713ab054828954ea6530d5753c922c93503146e4a9550518a009e4cbd45133d80028616be8872841851b0006bec80e00c38130b2c49c0058259004d25108c52860b6c960d1c2caea6128509ae229667a10241b00446096389284ba85051748106190ae0a2014680a0a48311ac44b1c0e98ba2012c9870e2c0125802c1d3e974024d5848e1740ac3753a4531c2755ad9399d4c2596290ba007aef8e22b954023984e544c20eb045ec103d3d73d7e70baa28a678385850e4c504aacd681c517a6d309bce2890f0b0ea0565c4d058b11b044a9c1b2b252a550275309fc3e0a9c50a6941659b850fa4ea7d40e5a3c168e324ea5ee03a980a016554c204b0b2bb8400f0df0d4c54a959a2cac7042d9d0c1709e451a2ca706984c1138954010b4c104e3cea202046d9440500b2b5c200882262ca2e83e3f35e881364a200bf4d309044110044f262d54f081ee36c05cb185abc86b562ee060e93484d209e45ea85039a83299b24882cb6432995427541650e0b83695582894c96432994c281c54b29882b76342b98a585eaa408d09a54aa1e007a8d349c532a15e5244b8e00665587182164849a289521849f8ba38028217a4000b63a011832a3930b94e4538401718d08b1c44c11452a912eb646ae203209800155198620c215c1185836009055b58994094d7c4690b96d3e9c4c271bae13a814b78a8d3e9f4f5e974844e0127181b403739e81d0c0bcc88220431b8820a1e5049c11650decee9642ab1a8a46009ae93aba9a48008378e50799ee7792fa6cf3b27c2f5e5f09c0857e905832f4552aeefc57b299272715af88a7cdd10dff77ddf0b98c3e4f29c83c1f7715cd77d9f0d6f012cef03bfef7b81018d1b504e371480e25029ef0aaacf3bffba8ec5e2b8af5b21fabacf6bcff33ccf3bf7709194cbf322a9afeb2ea04209951ce44c5f7fdff77d5c7762e99c3b9d7aa61dd5e2e2becf06c7b17aa6fdd4751cd733a592837ec4c94dfeade4d8a1e4a013954010e4b892275472d04d2b4425d0d4715c4ece69e5c6112cce8542ad74eea54ea654e742ba24557f278ff57583200d5c0db21411e1fafc5bb9ca8f4839ca39a215e7aa315ced44a929aef622454aaeafa7e472c2a551e4860d582a57c9bb222b57c9f3564097effb585c251004c11aae52a9542a954c2b4558ae929b4c2693c954a4c555f2325c1f135e142f0a19647056705614f518ae971b4f502baa549f587abc1753a9e42f397440b93c073997c9e7f4026ef1026ed133eda00b97860bf7b8e02a7911175c7095cae899064b60c9f5bd80527aa61d94d2332b0d705d45f70c14dfc90a208baba9649146c9d400d3290227d513282a5254b4b0c26432994e272ca270750793ea4eb5a752aa1547050b26b6308373a1a2850a5c20125cc8826bd941d79ed7545c9d7baea6a2051854b428a3bd6ecfe50756533901142daca045152dd070b5290bd516dd4a712ecf6bf7dabd76cf5302e7f2562b2a5719e016e00b9460f2a28f0932a0a8da57bee22997132e8d5e715674508a3a325c5e948f09d7a78407b838ef5c3e267aa67369e1bc7361795e5a752e3538cf4dabce85c5f315176ad5b9ac5c3230e1f23c57994e2ca8a22357f7f2cd805ba438a0529d76560ed2c0d52f70f50f57db14c5740cfd991c47b74ede7e52a9542e4f56ba951ed05502bbc7c9519e4bc905ba50b1e22617211c4de725971d4e894b0f17d3adbc341753d45fb896084106d4e7ee4ab98bebfbbcceb5724102c78e083e57994c3d9f6b06944b555a9956a08bc9a5e4025daad40a5c81a655ca468f1e452b17074239eda8be958b08b8cee592727da692ca6b71f50a08ba742ed58aeb6ef5b1b03a182ea57239793135340eae8ec6d5f9f076ba1def637149ed802a5309d59db4e04ea7efa53b9dbe178f09d5e7dc8a0dcf63b156abefe3844edf37c30c3870b058def781a00d36b873387014f18a742fdcf7c2812b45be1c397638b9c9894a0efae9a5bdd2cbe985085769a508e8f23e2ff299568a945c1e0c68a0568ab4eb73540ecf8d3affbcfbb8229e8fd711e1f25c856a5411ef850897d79952e055e9a048718457c59bc2599707e506aca2d3c773c3062cce61b8140658de1652704f4b4f8beb7326baf579501ed03ebc05740ce71d42dd1e1405d428c18fe9932f04e304a63627492a1269168c91ee22cdc2e10c4a73ea65ad7daefee4acacd85ddd3dd32c1cb6e8ee109f31160e4f6c39e2f0c221d5dd2149be0d5397999535e35b652eb33e1ede48f294b938d6d1f1e832ebd8357eedb34fedb30fa6e5bae449b366877c2e7d6862a63bb9fc2a962e1b25ddcd82dae76af3e91abf2ce9ceacac34f1b44ac61a7ba12c7ed10b89359b6f34348001743750b36e18a3bbc38c7f363bb167daacd6fccd5ba65efad3b2ccd372ed9c5d4acbfe6e7ba021db03654b0e9d4ea889642cab0edd0d8066dd804477ff34eb861f361ca1bbc31f9a644b6299b1ac463e3409f1d33025b17fa66225cd731cffc75cfed13bae34220fb325b1c7885556c537f1cc58562398b1a40e7b95b662fc18f6a649690e1bcb6a04f3f28fea4c66fdaf5b2fa9e3ea7f9f46f462f93219926cd6175f28cb806c6841777beb7e96511ba6e8f6d65f2bfbd80b1bd137bb3d05bc4c93b65a3f6c7af4b8b9b8d5fab292a57dd5eafd9cab8de867b4e6737f56d61e731644565ae3c9b60ac57e0949677fe4464913572223f9b5e796f18c923db9eee0f4b8f9bf34224a1bc2e971634445f175c0e971436943373b6c54c866878d0ad5ecb051a11f37362a947363a3423e6e6c5408e7c646857adcd8a8108f1b1b15da7163a3423737362a547363a3423f6c6c5428c7c646857cd8d8a8108e8d8d0af5b0b151211e36362ab4c3c646856e6c6c54c8c6c646857ed8a8508e8d0af9b051211c1b15ea61a3423c6c5468878d0addd8a8908d8d0ad5d8a8906aa8bb8fb48d160f740361bd54e9cff8cbd7fd5c5f357b652ff14d4c23fe114dcdf7f821d2f16b280f190f1ee34d4d8d8d8f188f9cd8cde843fcf1b1fff132ba23f63f68c48ccf4b6303021160bd44e9f0be24118e8f4f6ae6f2ef3d87645c8fdcf2e357770ba0592f3bdd1d8e5f49d3a45efec71c539ae7c77ea36e7ba0f16b277e21fc35d76b69f974d91ee8331deb58d2216692fb65790a0d655c563afb237b4dd375cbf5da22fa73df3c8746d2d2f05f5a7e7db647b5732cffbeec8590707af0d871836433be91688fd4a3d28aadd64da457b4b51f5ff949929aad4cfd66c7e9a277b74db35c6068178cff8e237523443c6eb3df5e07b192b133c879e8e1e1d9f17cff48c4f5e7bfc77c3c53b3e303749ae556747bc6a1c46f475c69d96962a5d95c86687c7c42f9fc877bbbcd8e679494f9f8b392d244d3fa9f65cda515dd661fbfdeeca7e5a111d0b41710352075df8435a1cd11cf0e1221a22118d75c151cbee1c7eccdb826bc99292b79bf8644b77744b7f7a4593508493a7149494524a592ba9392ba4b6a2fa91790d44a28d19d6a547743e94e22a95149494524252991d49d9494442719d15cf716ddbd43b36808c18c66aff886b9acd6b4097d84353336e2e31eba9b8766d120a4db46ef0e9bb066a6b4d91ba3614aa32186ee3eb27ecb55a42615dd69981a69b55e26ce22356b7648ab25fe68452b2b7d7ea477662611ca981ea9b9963e41549296b587e7469aa64b0753527cdd379168cd48b4648ca4d9e61712ade904296dcd2612245a132b2eebcd48ff7a4c63f78396e8dcec3883604cc921343153135722f7835a2d0e05398264f1efb5a2675be24c9bd5b7f9d76a2ecfebb2ea8eab3f8dc881c05ed7be46b29e31d8f8345ccb2af3fb2359cf1d7c439c6bad92b5cff826d39c970011d75aab85cb37b2b9d5c2f8cc340fbd585292eefccb5ef846cddbb5998e25fd21e97d1309496bd702e11b0d62c980a4c330c4213f2993e9df99670be421769252f214492a3a2d579bcfca6ab3a4ecfe589efe97fa2f69917ff4e4abb4358b1497f4e656730968ee86b361e1c0ee2e6a961386baf10d6998d268687edcd01c2ac6686c6e688d8f1d228f71c70e1e3935ef63e633bd19c74e4c83f3698dc4a78934b9ce6898d25a2dfcfa1abdb2187e3a5f4bc36e6da6614af3d6e3fb477f1d3f0f16a8db3382470c4cf96428231f7b0e417cacb56eaf64414ff9e4ab7cf2f5b99655f663e97384a4622d6d49c5d202fd8c1549b757c458ed5891ccca7a7fbc48f20fdd3f42727fa42ff4a3fd9951a28fd54ea0192522e99945daed25fde75bacb4d9d2a84c32a344b3b29695d6fe8e3f5af1479aa947448e2c27f993a44ababd214a5b73c5d6ecf684f85a25fa4c89cc686eefeebadb4669e4c6916ea41a9819250272f11c4182644788a7080f11908fcf4e11201f21a22127e2211a82e4c8912440423c3e3d3e44403c447c9c68088f0176901c71f10811e1217209f1fc2401e2c9e9214ac233048827c90e3c43443c4362bd5f3b81829e7c22a4cff6c71e2e9faf55a2214449be5689c60fa292f47ef9459e8c555c95ccca7af350d0cf0e0c4dbadb070742e243e41ae2732428c805434db70f3ec4a7c767084fd0d00c11131e2220244360780186d5f8593cef1fd55c6bf59a2f98c17aa10c18ffc107e7217229f1110aeaf6107000ef080239a21085477f4a4c18186274a24d3b2852052d8e729a4b804d51800454da5485287c0e10e66870024af820810c06cd7907ca4a010f745703420203dc601a9c8017831d03e8d1600f1f20e2841fef8e31e95082003add465ed420c91384d05c0c8860c204a5276d8a01045d48810692fe502f88c0eb05476d42420a134db09046977650d11ca4a4d16da25d6e0193ee9860245c92831fdd5af840d20f4296d05d941b231f1a34b4e908097420e90806da0405209ec86205ebd60107d0580207145dca81830158a2b0a23b213528b8a8a5d125cc801908b9d9da0383c8165e92507b4141473a801044972e10810198c00c1e1a749c2f8870451a6dfad185184510163498040dc0b82d629aab0206c80b6516edfdd400003c206da0db0ba29c5592e6d3dee891ae92046b53cdd45f7f39706d8a821bc116ced4353810068e853bdd7c3eda8bc0170053773a819fc7717da30bbb6b6e87af005c9b80805da3c435c77120c8a35375cd719cd719e13813d7719c570aa2e33aced4c120c47125ced41db7127a5da9049372eeebba8f09eee3b82ec551a1e3500d725fe73dc715751cd79d9274393aae2b7d1dc7848ee34a1db7037783e3bcee1403d033b17030701cc7753fba174e1e0705d771a58ee33aefc5755f0ac5a35b713a270eb4c1cb813375dd67e3a5ba8e8ba981c31de0b351f578415d7fdd7180fb3c980fec38af41097044e0ba6b168bd55c731fd7714fe04e9d0e8eebc0aef3386e0747c39db855d7755d69088743d77d1d57e385aa184e03e0565c90a1a300077631701fe771dd05759ee2beee6aa91dc635c06b9718702da48bcee34adc67e25638cf89ae3bb53c2ec7e3baeef36e8582e1408e33d57c3635d4705daa74ea388ee34c1cd7e2bace075e8943759f77c4bd7427c779331c4ad5712713d709e902d005a0a3c16bafb91a5ca9ebb8958fe57d5d0c5dd77125ee9371281b3815d87120c7e283e3388ecbd1f99854a88e8b9d56a68edb813b719cd7711f6784a3a1fbd1cdd0a93a5307721ed7711dd7e268e8549de9e33cd0e3381f9cc7c170286ec5711c102e005dca3371a78feb38aec57125183a1bdcd771e0c7fde8549cd70580f3bcaefbba8ffbd1759c0c5d8a4371a7afe338aec5d1d0a54c1ef79d3e8ee37c388743c72988470090f33814f7e1e050a896ca871c01e004f0715d57ea4ccfb15ea85119e1b88eeb388e9b69539bdd03115c151e9ed0ce8314654ce1c1c5084d5842893082244320a3895c7ad04352e0e08728182d24450ba01072b1487690a2a84a10e521e48814019082113a43cd0f2970d0fca02c20f03184151b7cb8a4389c21705ac081a581011cdf4287b02c046006564527434607ac8cd7e82040143250a801e6ab1afc860b1d05007e6818f880f62f01dd5e779386e98669162b02dddead7cf265f3cb3c5f39b29ca4db43c237a4998eafd293d40d364832a14ca88fe58463427934ac888a007a39c19452a79c6f5583fb56a5d767f356bc966f8c045820a9c4d299509fcc0a0d3923484a29598d9f0c4b111d8f1c60928f2b058141520e4788b424a0fb52df91182b2421c1081d538ae0c0564b0d428ae83e19bc199373d10109a083a452a986a0272fd4d839c22b5284029262402d59d958d908a2e705f3845355480a925145604db04c286f0534fa16c080224e1f4b8906aec68e2292a001940e319e9ccea0004ba70285b4987e7c3abc0f561801001026d5931a40a9c9a7c3f4c308154851c4880f2c0103abe6c98a7824091924a94ed90512b072538353328307c414034e1129d38f52eac4e2f9f029e2d190eaa94252cae4b33274329283a7278532b21a1a83a820e9c62783932ab500b0524aa9785e80e84052ea642400312592408f0572a51d4a2910484987ce8eea44e17032524a9962582182b2e10342ddb031c300648041c789003a080da088d42934ed58d9e1c327c8b4fa4c32802d0f07b5fa707021269429f5d1803a7c3942383087e702c250833a89de0f1e20384e2918503e8a1802a4e27182f96cf86c287d204907cb470424001800940ddf0c356c3c1a8c480a69384fe6cd7c1e7880172020a0852d493082295b5841820f4c91041142206123d98b30209af4c0444992a1a0230630d2cad90133801b04e05f175ca401852624a1003a37bcc81083298a1b7841450776e029408b861756aa920c5ab002115441c5141b90220a2892c0e040135ec002444369a03185580f5078820b5eb6a58925aa4c0748ca54c50398f081e2c1181ea8a2f503e7860d55ea649a2107165734f9110990017c7a7830e0800528c005327a644182117c8088254a7ce0e0b0f1e1608a1494e8e4808332954a80c40a4ca081094040890364000318580209900e101c565c163c2c74677c55fc095d195f12ba218064703de876d08981d2c12a8c0e071d185d0bba127824e88cbe22ce06ae86130de00c2b317437ba17381b2d00005de85a38d6c7d2a9c054873a9d3a9309ec3ecee3b852afd4f072785a247d0d48fa8e94743867a24211ac0e2481e0ca34801e14f14961f3dd584d0182521249df11140ca91970242009c5c3d7831700552ead4e3da79c52ca03822305da20e91425c9469322503e3c28a2b0124212984612b892418ca4557ed122098583a533010169c0084079411503058cf8189054c3a5868b37d34273c2d192861120014e39a6205e0d2fc8698a24efc786a6942a8520c9539564f86454361ef7ad3e99540f4800130f25194aa952d1cac6ca060a070a06130f9e168c28c9e05961042825e986a2afe6af1b68f85aab1aa5968ff366bc215fd0ea46a9332d31e53001812fb0702595077e2bcff33acfe49d3c546a86cf332531b9502328d5622a9938cff4f1f8683eee148397a308540d200892584250444be9cb712262c42704235e5ede696c21093c180307536820e59c0d3d80099e9d02e4e0c3965078020d0eac1a27930f3d20014ae38b30a8d4b0448d131410620121ec008c19b8000b125041130e6002675e025f2a9851e5073a08838b14103104104d7a608204a8484f0d01b801430b58400409463084102f1a66b0650d2c420882935a521a5bb042159af8700386961dcca08b17b8008b2b4ab0840316f00282872548807cc0f8a28b1b64e184111ff4008c1970e1022d3a3085124724c08c2a3bd0810bb46881099e24fde8c3d3b252e5084610020db860c10a50e0810734e0c717104d7c58e2c303a415d3b202c6173480e2020f78f2231006f0e9e101d26259f9fa084600e38b1a74c18215a0a0041e68c2014f7e30804f0e405a3e78d8c4b8d0f2751a473042106a40832eb860c10a4ae081261ee080063c21c2eb872605a009d1c8c2111d6ab00061062618a0049325351a688012372411a0d2f0b6d06901cc4287851308be0f741ee8a8e06e3a1baf860b55331e013c87a1866e062e8749062f060ec7778383010500175cf0585f8d150b6b4586550caa19522d28d3a964ea4a2510f4b8ee9661861b9a959af2648ce6b25e93e6472bd6f2a4a19b33a5a628352b75c44a95dd3d8066a58cc4388cfb8f1597d571f55c1dc8edd24b69a2d3ea291858315374374bb352a76e98cfcafa349bc7c0e410c4cb3afb186a8cee56350b75836e98cbace3eaf916fb210c431fc62e8935dda0920677babb8666a1688d6f58decf999a343713a059a81b50acb266fca3d3c44c6b9e6de9f8ede831302fded3e253144e3fe8b1fc4c1db39a756ac158fe4bb34e499c909c9667e5932eb3eed7ca2ecdd87f56d2dbdd387437ed6404dff0d2c4dad7685eac246e141201e8461161aad2dd8f492afbf3e6eef64eb66eefa8db3bb92374ffb0711dbff71475fcf891f3c3c70f9c1f3d7ef0f8b1e3c7cd0f9b1f353f7ee4e4e4f8c8c1c9e991c3236747ce4d8e4d4e4dce0f1f393e7cf8c0f1d1c3070f1f3b7cdcf8b0f151e3e3074e0e8e0f1c1c9c1e383c7076e0dce0d8e0d4e0fce891d3c3470f9c1e3d7af0e8b1a3c74d0f9b1e353d7ef0c8e1e183070e8f1e3c78f0d8c1e386870d8f1a1e3f76e4ecf0b10367478f1d3c76ecd871b3c36647cd8e1f3739373e6e706e7adcf0b8d971737363735373f323483c0be8c0029884d866af6eb38f25bdf569d9677f1d9f7e93559b8db00b4a155082a8976f443349ca8c5f9e27fe9729a0040a085200019018a3c79314cb5aaf952151041244ba3b84b9cc685b3098cfccfc69e5e9d77afea123ae38c287237a9e54e96e1f9af54402ac274a3cc979f27577a8e36b16ebf04c8194b6dec89b8e6c4b1d2e6ff11021012a6d2d6d7e5aaeb6acb01712ad0185d7fa8d9ce11aec69b6d215cab80c494bea098849c04b770f35cb08308c2041771b35cb08224610a0081a1481bb5b6c5611acee3640b392ba48d222298945440b8840ea0e1f539a784ff367081399997f99fb8d9a36977526fcf1f05fe64fcb36dfc45cfb5c6760373b605e52975977790b76bbb4fc18cc67c21b25ffc2d83089890943189920981b2630b19ab7ec245997789891be05cbf84798cfccca3a96d446ef28b326158d70bd9e29495699928effa5e3ea32ebb05786dda8699e2e03ab7daeaf7f194c6661183696f6464dffef09cb4a69363b49454bd62c7622b8216a3004144314695c47b7d9af75192b960ff399b0acb5d1e55ec6d0ea3f4398641819fda1d7f8351109bfc8cf63f9582726e774999cf3a6e4451333ad65fac235df1f1f97d6c47f6f237da1dbfd7387d07f86307192c62c59c43fdb9ab5a487b792baacbacccf68c68e710802531f1f9f63f9d8a9670abbd971c2887868b3a59151256d1ecaacd7dee638638ba9cbe07bdabfb466afac24499787d8f1696db634f2b7e123f7c7fa97e2a76599fd19c28488873124493d53c7b9baacba0d3e61e8cdb77a782b353d06563379fec07c7c19189759c7e971e3376f44c9dbebe02136e9cd9e1f63fa7556563b2b2dd28f7f3ac998465426e919cb4cd69e2763b44cf264acfa640b44e45a9a58d2171a82e9ce9191ee58a0a1c7d865b347b091688fdc4afa632dd150b6406379da9e6c817092d247022014b6dcdd3511e935968f6d4a6c4132decaf8c754a9a6a70af9b3907eb132cb5b3f4398d0c49a88447333f1945cc7bf220b37d14dd46a11d5ec956198be53bac35b4c26fb5b45775f2487fd7933cc653e365f217dcbb7bbc35c633ffadfb7b19c34a13b246ab5889c44e90e9d30e198da5c2c274c626e24496bbed484295de619dd1dcad08c63279629e949c58f391dcd281dc68cff3118c7f845f1c466d2486b62cdb466f349bd74993cba3b246b2e4f1faf2d5de35fa2f16d944634fe89b1cf2532d69d71ac3b2c7bc42d8642a152ef3ef8d3885028542a977fc4639984164787b994924b2a565939ab9896afb5597f1a51194587d4716595b42f6d99d3dd2135c9a7f95f9ad3acda19a1bd7dcc71f513cb34ab268390d26c7eadec2fad315113d23d2b2bfdebb4d9692f2d97d56649b736e3ea1887b1c66a38ba4f724a778738e3ea638d915574371049cb6ea334b2a6bbb475ac31f2d4dd1d7ea6a37ba69effe6d9eeb08c96e8ee46a150a9b0a250a8540c0d9ec13458b4e34c59698dc6d630c4a21d617ec03e78cd667c0e41a150291d92acb9aca793fb41b11bade910059121313a352eef19f3b1a45314fd14e9a8618424494b0b047397f97808fb9a1d82b9ccc75b3098cf84b792ba63eadd6d43b3ea1095d6dd4c9a5559342bd0a2e80e69b9c2dce6b2ca5ceb2f9ee30bd18c7478adccbc2ff3a3fa46f487d633197477081bcbb307d6825998cf84d8496acd6b65a7ec6d3c3321b31d0568966c0a320dc82c4b260024cdfa305e4a87314634c338ec071ff04c0b2984c16c69e337d2f6a5bf63d8e83234b2faf869d9818c3556567f9192410ffb1e2f43772f69d6188371033d138e35d69a09613018cc6576ac319f21c99ab1531f65c62f677568f41b693a75a10fa2de6455345f364acbb98a55f6e36b2c4fd95863638dbd5863a9c35bcc45d37349eba547fea51da213e33230f74b9b7d9b7dd15ea57dbd32a6a49168c91d4bb38d3eaeb1ee74770cdd5d92b0bb43121ed918f56ccb2aabf78f7eb0511a51586d3124fa13e2b19233a7fe31fc648c92951e51c725fd5ab5d952b1c68c682e7dc29c7fe636dfb759123bc5b9d2eedb5e96c913ff757988c7928efe47359fe2e3d28a5efedbf2c71c67b3ac3f2175b2fc5cd6ba53d69f90acb2996bdd48a43953af5113636bba2def89cbf7598d79c6f449cf34fb78689e2f9615bbf9f746e23ad698539192a68c96b5f698ee84a5354f1f6b2c07313e4952c7d85e91fa97b686abe98f69cc9f466465b52784c16c89a4c7a7c7e9acac7f6562f5f28f20d19fd0de0fe2c7c3fc3324bcc5fc4f921ee19a1f9715c88546d21a094b8be95f1f494baba34f5048c4c7737996b3faf78f2c769cabcfcaead7ca1ce350dafae3b55614a90cce26cd389fd66fe4ccffe87669ad760e79180383c71a83d5c03ef6a5755cd62faddf62ee321836da7a3f08e665f5318b7f14e2f18d446afa8d7c7ca989311547fad7924e873ca489f4f1c78ae9fe905051f34e3c7c919af82f7699f14dd39a9ef159d41d711221495a1bb296c865b347ac251aebcefdd286245ba0f16f359178b2051aeb8e0d929549c61fcbb387ccd95e1a51c62711fc4667ad66877c5077d7e8e660d0dd4a9a35244a774391c4075131494f27ef1f0ba2e2bf8eab873b44908c7f6dc6e579cd98b1a430f7cbb2ca602b96d6711d6d69c4c3181817faf9f19066ad900bfdfc78c69fe911bfb55a886b9faf75fc4794d2f00d6f8d09b7640a4b84d0edb73772cfe55f6aba636b7a2b3ff6d8289359b246b18c3ee9615965d6de91dedb1bbd6af5965f9bd14b336770691fd7717c551abeb5da0c49cd9a5fe5796da6f7145fb49a48ffbabdc6f233d2d332fdf1357ea6e25ff3c7d71f5592becc7f2392a4af5b9eaffc3857b2e6f335d6d85863e5599ea3599ee38fe59bf8c4af17129d292bcde5696b334f1add5babbd9248805969f87eacf6b527493b339295260281244a377e72a44fbacd8e738d7995c94eece36759a5616e4977d36615b981e4871edf8903a9d901c40d7ef25652c75fbb149fb61efd0dca8fef67192d5ff463f9d2a73dfe6c8f5e37b1fc5a264f2afbf1f54622bdf995319521fdcbe63ffa4c674ffe589ed834122d599e9fed51b6472f5c492391923192626bda6bd24c479abff6ca8f6fb27f7cc3d889e95fb3e6af59fc366ad6fcca22bdf9afedcb9759b359f3cb8e27b6e3895f988e9f1fd3c4d31ed52ac596146f7f64cbf367b456ff9ae559b1cd8bbe30bdf4358ef4f1a54f8af745be5852f17fac2f918ee457d92b3f9e8d67d1eb966becc4af71a4b1b38c9df895ebe9a4e6f2b41fa3b18fd158cbac0852e7b316f37113d6ccc4c699af37ef989979928a7846449aa1a9894834b82622f56ca0bb5dcdea89b17a7ce86e988b8e8f1c06f399128987313a74c0382669793f97d5f15f4a8a3fba2f11050a51588008b3235ab6af23fcfad9fdda51bd3fbe302549fac2f44513338d1dc10859187fac47199f352cb8ba6e6f01a8f71b49331d9f565627aa3169c6b59a6ff9ab68f3e39fddd3ac650bd772668893ee9adbd28f788208ff57765ff67af15ad907f17f65d41c4b7a67e39324cdf8f5d996dd9c0bdd1d6b962b0b2e326c20200aae351a11d71a52b35c4074e33f31ae3434f1f32dd74b4d9a6c3a90f1efcf66f5e67bfe51c5e5cb7e746ad6681e477aab48f69a9fe95ff1ef69e6f26be38be569cb92be6e48f69a33b57a93fdc7caf375544f27ffc23fa3e6cba44f7be5c7f8954f4bcbd596afcd18a9cafe9a2f92ac462f5aaeb697d1a5b5bf3a367407928880dfbce5570e4b40aa29ebac5e243950c1ca41033904f50f4d7c6852b357a6a35941a410e406419084342b484e37ccc7f7a7e5276314665f189f7e23497a96b4e6f73325fd635e523124e939d6a33a96d5cbfcb3f18c05610132a5bb7f6822e3323e34093fe624596d3e96d46fcd0e75370dcd02a281ee6e350b08ad7f68e2e3df7a3af9eb32e3d344fad731b58d25a5398d08481120387e68e23263751f9a845fb3623e6d8b072db37ee4a70f14416849d1e1cf10268ec57a747fa8e4b97f8464fc23fc834f4a43e249323e2e93f4208df5659ef6ce5e19e94b9d20e22bc98f6532fbfa6bc5dbcd25cfdde1870d37078d9c28dd1d7eb6473e2bebcc5ff369d931b5e53420270746c394f6fad18a300f7fb46269abf72809721aab57c4b113fbb53e7ef6fbb45c9f88e5a34a773776d3df6d767aa9e92e1f51b22d6d5fba8be503a9f1e9f29133d2a7e1680136569887f4d220a7a7bbf2a5794876b4836bfc6c8146fa46c8737c9a3834d237f2998e66921fed90b1ac3a94d5e8452f352fb531990c4969b34466657d52bc892fab47e8a541a3ce78bfb65a78c8f8f765b27327975fcd2afed5a1616a843eed253aa9e5f2b4e26b866b66ed1af9202a7ebdee8fe5e39fd1d7f8b59bf19f4e5e6848f92612b3768d98f4e7ff12ede00f1ab325f1eb6b358f65d56156561aa6e41066f108e2a1da7146df9f5d4aba238d75bcd4669e3ba2a87dae3dcdda210489d6fc69b9b4d93bf33fa2b43fff74e266edf4a7e5ee9f9699f1a68cee86f159959556f45b2cd7da7dd34b4acbd7d67268d68d13dd8d6b79c23866dd1ce0864977ebcc20bd97b6745a3e765c6f3a964d1930b5b3569168cdcebedcd12c9b087c1015bb1558b0d9b1f18671f2cbf133adb9ceec972f22bd8dba07fd0819f1a78de5e3eec669560d19dd358eeb2d9bb5dfe187480d16ac9a0af88d2c5f4e6aa3e7e0f86714e3afbdc64b6da5cd8eaff1317ed15ed3de0fc265d6afc5f5a88e4eef8f6fb367b3f639d33fba8f5f687c4cffc8f863c9731be95fd29565744808d72a25c556abb4b59a155f635975c8480f742979cefede8070643b62ae118787088d88a78819946449129a587bb84984ea27b9318196fcd8318443e484072636620c59cbb430cb28a631bad696bf0c431a9a163673a679eb885092f2b432ff98df680dc6c3208c441e80848a14595a912b239dafe47bf0e1a3f628e9a132312a12da41144490018cd06434fa63c4c3a4b683e35a3379d61ca7c7cd8ccbc8903fb6349be3da7d9bfdffcea8df627f9fe63ee593afdbcdf8c592bec6b75992a4b46cfef8125f48b4362beb8c66ac53fb1abd34e8da7c8a8fc4837f468390e80f49c53ab34790e8cf1fd54c818c449a8790e8cfacac3f46e4b99391786a982e111f8947761494cbafe51ff91b74daaf5522f36f90ec28e8c4d97c51a4f8af155fa58e8e79da5b4467f4d1197d88dcdee875bb7f64455c479dd167fcc7af9a1d4b7a755eac63595f7f54b348adacf4d15112447c25e22b19bfe6833f67d72d579d98bf67a6e5ac0e2971199820e22bc138ffd0d3869074fcb1b4e20fcdca6a24d29d5cc54a9a483c635975a82455924f135722f9da986ba44f73d922e5e3bf4137e317ca2792f16b95a87662ecfa6b87e88c3e43c6afe6298a48feda21f8ebcd7f6b95924346fa9796e9a541a6495fb9fc5a39ab1853d3a4af6b3325492bb65a3c8e5a2ddc6a9595d2447aa9f9ca76a446a435c51fed90276c1cc08bee069766c524c07308e2de82c13c636afa8b253d1a4b2aeae8e49c41c457329248c6d285f3cf2e25ba610bf4ff339a8766f5a7b415df5782efe373bc567ca1276375569e3d9f6ded03012803100bc08a862af7ccdf42c3005a68e8195a6678a2bb9774cb0c3c66b4e4c8418ea4961c322d395a5a64a022c3930ecb2a2383ebe333e3b3e8b437ff8bc3696f493c8c817d8d8e32ae8af4a4ec8f2ac698225999a5e1bf32a75edaa839d412431662300194c6659296183c1c311826975fc341b4dcb842086ebc5a6ebc00430f18d002834e0b0c31b4bc10839617ae6879616c7921c87d58900582f5d457467a98cf604a83f90cac0616e421a6e639abb11ac575b499a4947669f99e268c3a2e6b594797ebd0e1d2a1c35b45807c80845c4bc21b923d4d1fbfb4511363b05b6c40c1c613367eb011430b00a4d05abb21d91aecfe0dc95e6bf30bb500a00700a81617b67081d6e24290ee0e5fd4e6b718180c06df5ada9811a6a5258b96966f69796969b9d1d2a26a61cd84b88e25cd2245fa216fc1603e13caaccb484a7b4ad2bf41210c0623492ac29aabc0d7ec90e3592dfaeb406a5cc769f834400e0e0ce632b03006c706c6c78739252d8d96335fab390889fe8432eb31304e00bfd90173230abb368bb4a7fc7306067399cd2769facd8ef186f46638dede080623b31f44c530c7958e233dba328b636e6f04e323adc9fca523ed71b6404fc66899642c93c8c81fb2401d8c10a0ee7ebd5e3437931c6dedcd5b7ebd79232a6d257243b23788a47f49928a34978e8c8ecc50aba513649a2ec734154466f469b5885c468728c8b53d282674b74eb7a044d0823251e1d3b2dfcff688270626d3d85f93d61c66f3d79bcb1fe97d9aed4b18119f1711cfd08b07221f2124468892b85e433e433c403c45606e73ab25237f0826e3e3b8242d6cf4c93f34d62763f5becd71ae3a7410f1f1fcd8e5637eac850e1738bae5ab195bbc2db4784ee8f2bcd9f1d79bec7fa7bbafd0e235f1765a3c1e6d65a58f9595f5da7bff4546c3602ddd1626fdebea9ce8ee2e91b474b4263b23ed6ae95c30b58d2ff4245975001a6ae1ac68e198d8fb41b470ac0ec599923656b19e432ddd821a6de9574bdbd0dd21ecaf1d02a3224f4b771a56846998ddb43474d0b9bd0eb7d741e7f63a04115fc98f56dcc2175b80d2dd46e2d346cfa7dd42132d2c410b4f68e1ef298a6ff3db1bc54e7cbacd7e2375e8d0a123c4245975d0028feef048b3d0e0028d1074370c0936f4a315870c39017c88edd130bb433460ba43933ecd310ef6d6a358ed3176c57ec95016a6d0dd61aeb537ba4855f63728a7c7d050e8b9da18f5507c13df7fc9b4766d4f4e0f8c5fdc737a0c0df9f83fe290bf88c788846f648f449ae96869981ac9f847d2c2b8f96f5473dc1a807be8a5ad34182e5d563d06c61f93b4c74398673a9e97e86bb484fdb579c8f149cb6e4bb7b9acc262646060f8afcc7e7e99cce2eab3b2d6fb6425c5994c9b5552aca62bc85318774a7f3cccb8920ed3210a1296b6ac323b934feb76e6d9964876c7c30fa2e299b23aa54a6c10ae36fab7a4b5cf1e5a4c5297f95925027bd890c7601cb0496b308e3dc46fd29f7c9a31b8ac446ed2a7b5be4681c437877c2c111eff8190782c51cd0e292d1049d221570085a0614ab3404b30238c1970618609cce08019183043026624993184194298d6636e80f196d378cc0d5e73991bbc655a97b9c14b18f7960cf61f7cf8d18aadee528e1f0740c109559e30a3c70c1918da84ae0282a63f7a1520cef1af97d59378abceec91d6634a0b7a4c692616ab6933bef87eedc4a515652f8469a644acac7cd9fb41bc4a5b22e55aab45f46269cb570bcf94b6e227d8e8f696788ef69a7e736cef886f38d2bf19b75a4ee09a7046136c943c622c8cfbb7603f9ad4868d444b1a89967c8d231de9d39ae0f348b507df70fc4b69f855bb6f9ab5cfdd8d6409445802184b9041e31b2e218a6e6f612b2b7d9674733f1f687de0860fe058028fb7ca3aab3dd86649d2756997d66a75774e194c28630665a000df90e6551391fe5546ee6e39c6d43c4fb3368eadd60d31bdd41cad986d5fde3c5a717c7c96e7eb8dac293b325f3f96a7ecef1f9116e33ae63abe7d236b92247d7d3e63b596f54dfbd89298fcd2ac5ddaab7cd3dabeecee218ed0e30838f00def67938ef46584297d6dbdb956cbfa2aa908336b368213dd46a05d23e458239c8a3083ee0e5de31701c9cd9a8b60a4696c6ed64c849a2b119cb89597667c2218694a44841ac2598d39ae3a3e2e43c3943684da106e90b10519072063ec6ef94ce88f2d3944081010821142f011043282e044109a344c48665beeee61cb899c002e644b0762fbb208103600840b000109082e4060f981163f30fa010f1fc068981a69b58888f88c3b2cc6268c81655b9a358f323ee1acaca65945186cc6ac2c1f903ea0f101d80332ba7b28634b6257cdde1bfd19857ac0f1e0033c28e2818d168c61c5184c7a346b0c01ec60ca0e62b003720736c438438c29c440b299f9b03a499e3292baac56f75c61302fab59b3cdd23ee6720f5b2d2298cbac87b0b13ced0ecc6fb1f14df39c5d4a13654437129fe6f93e8c0806232212657656566cc9216625fa92d6f16bfe477566d6fc326b86f94c48c4c7ddac99344f3fa2614a7bec3022189d553c43440739d0810874c0044b074a7420240c2584b182306461b01a071c5c664b3ae31eca2c4c08068b11824102f399d0ac44b6078239ceb5c6139a355b9a0de633e111a1243339333d44499c7a0562d64cbb563613961506f356f82f738cc3fdb1fca35aa5241e6130219fc774c7ac4461bed694fdf760b3128566cdf8ed8ca46569b3a35989427cdf346bf6a3af34917a7dd3d2cfb79dfb414468a644c25bb666cdfeb45cda27abec9e326ffee8d8e8d21a4d2c7f07cb78887120dd3da49f4b7ae93993918f73f5db1bddaf9de5fbc3622ccde63230b01fff66d21f6c56222f6db6d4c1ac4463597bb2052adf444292350fd5a05b86eeae8694be3a8f2d29c2983563b39a95a87c1389ce485a3060dde158c93a92d67d7c9a98ab0dffd0e4be1d4fec431307c3a6db87261ebe91b5d9f5a525825d763c876eafc358c773e88b2afd450dccd3c8da23b62f91ec0e4952f18b22379842873750c00d6a3abcbd91edcb1898ed4b188c7b91042f7ac0f2820a2f0ed0dd3a34cb8b1a1b14a13b8cb18141e23337178000c2d7eb864f1992a4222c5b2b04cbe5d3f2e9c2f4f646aff1cbf365c713dbf1c4e1ed8ddc8e2786d9f11c321d0962839aee1ea30649d45503a03ca4a3d36a1105098264775a2da2d7ebf64634e08206960639a4c8e0e6e5531a693e26492afe84a585bd606e7369fd5ad14b4a064961220500ddcdd3ac197ca1c40c889841902eb2d0dd3bcdea4205dd1d569a78e218d8f8491e866f64693349561b2ddb98233d2da9a5e5bfb61e51dac770add1dc5eaf9292a60b89fee0af328b447ffc6b95288c81893ee3363018878930bf9fbf462f3571b624a6b1af47f566b1665cc98a3fc6b3e3da99d1fb47d4c3d148ac3766b1dbd1edac1c92312565be563bbcbd91cd2e835fac339bfd6bb65d3b737b23a7a5cb67654d8d4d8d794c45fa3098db184952d9696f3032e5c7863cbce5d3e21a96d64b4a71c5b95e5a6dd68887d83cfdcb4ae26a7463d66df6f191aaccb43797a4b526cdb62cabff120f614030b7990182f98d34719581fdabb4b0987c9af9b4de23a4c4330ea51dc72763b4c465bdf41cc9d3b4a67f6c24bfcaae95dd375d563d46e630b74baf356b4fe4e18d1ad9d9e7b2d21236049b6182640991ccfaacac25ac0676cffca5f5b7b90c120f6146888a00f11c791101f1fc14e1197a0121f1211a924488680808c99097100f11a024b05c7e6d36b3c4c38c2be92395c9eccc8ff4e69aff1221200fcb775c91de432cb3b3f1499b2d8d66aa1567a8d3c4133b7e6ccd7b9a97e2fb4723f5b27c6c6922b53d69d628d2fbb53d1ec6587f4c7ebedd3f7a18c7f52ff55969c9fb476fb33497c1a4156db6d774b1d24c7a67369bb72b969507d7cffdecf95a1a162b798b9da4acac7556563256a333bf5616732224404e3494e4e796eb3dc51f720178a84307fe32e35be3b88666a5e1dbeb8064487ba03d31ca0fa248e90e1de9bb2ba296272d531e3840dc384da42459a30809dd96339f2e8b4e8c5c1d4692d508f6360732a389d6e4e94e06e12dbf8c621aa657b4f1c0395d561dc897f68a65bd511b4979e0d0446bfe98f15934d299abc494d69a95b5bc7489970023a62b84342c5b72086649ccf3312add0d6b560a4c90820aa48001311a4b414d3853569aeab3b206fd10c965adbde8ccccd79b8f5aadd2d6da092ed0dd364a2cd1b75a2f7aa9f922495ada57492d39daec15675e2415ebb51957daccebe58d6048b34a80a333a6e4688517dded3a0ee333374a52c7d58a055871763775d2330ea5ed26963d56c83ced2d62eff760eff760eff780b325876c96366481ecfd1e3e888a7fb44346fa3424fa7364cd5a3d325e6ae4c80621d1b252da10facaae91fea51195944684f11ff9b951f2c717f6b951f2897c696ba64154fc41d42192e6d20651af3582447fba9b05b5b37cd54ea0f17970e963d6ae1124fa836f884ffa7a7db64afe06c98e825e369ff445da9b4b2bbe4c9bc5d763245a7be1bf337bcd108861747ba31030a0bb3d538ff9f3f64630fd1911821b345322237d23b5bf413fbbf488b5443fda21b607eaf6962012d4ed39c06b80d1a5b5fb992e316bd748b7c700b3768de41309ce96c4b737badd5cbedb12df10d3e45a8b9df826fec53fbe4afaa47834531391eebf6a2212be5fefa5310f20c1036378408a0748d0de7ac9780b97b65697f1d610a2f694689d20e2fd5186e4be50ab855f26c664a5f989e09fd5319f260d5323d9dafba2616a44e769f747fa465a2db1de2f7ff6e21223f1c5378770c55f7e91217bbf87d2020511fdec2211dd722569bef6a7e6e666878d0a8d3e483f96d4954f3b23bb47659d91dda31e2125344c8df40829b997c708098f50fea16e13ab0339dd6dd26b03d22c0e4ca1bd65d26b739b756a221324ad164e8f1b231c70c2811f5354c9e419f3e5b53118cf15dbb0744d7182299e90c9e5bba6a053f068db9736fb0690b001263610a443588ccb8c3e304a695e9eb273040223493a04e674033068a0092db33c1a88a201b27f6822332beb2d065613998ce50fc13ecb2c0cfeef91420b3f9a25850ca4c852ccd03f347119994c9e2379da284c1045139c6bed69d915e6d2d24e5a06a680c7f23310820cd40cd8687a3100020c2cc140ffd0c465a008018582f5840f9e60c113639324156df97a239a6146348ff409960b5c0003173022f3598cd92c2373e9053e0bf4c0024f30a579492dd06301182a20a5e6256d564799ad001315c8f9a189676c4597f1a14988f1e9d8b419fb1227a4e004069c30327ead665abed665687599fb475fdea887d46962a6b51d9c405160091488c00f4d5c86888f8cfbd0c466ea23a551a086023113c8c10492265023012048004a777519bf91311ab3d7745cfda8bc7f6467fee3e10d9ff6feaca4634c3eedcd66bfb65e73a47f61fc0cc7bf5f1b6fe4fdea37090cb12470838c0f4dc272687c4c83f07fcff849846e3b9095f610956f44891e0b7dbd8df4b1502e7fc80581a0eed048b4a4e7f171340b02304d8c11c65c13e96b380b1fa60926ba69a6ef6a8276e9c79a10d21d3ea0ca49cbf50128a0b407203dc0bb6332d2293629ed7e90875e568f093fac30fe98da1e6062c28aee9e95359ff6529bdbd2a90ca63616134cba3bc4941467fe0e61c23b7c1187662d51a543d91256dc97dd4a5a736b8996a055ff180cb604eb56960e2823740013ddfdb56bc74a4d07e484a51d71b5f92d8624298c97366ba4590d28231c3fff35c9188ca80124286bed7efe11e340a4a343927488ce107c1b724c9d28481024bba3a3130313a42632c9f8471d24bba353139930600706744a444189283afc5bf18fe3cf10267e2be9acb4a4db524809022441055612484822021de29f214c603e133e254f9192a4cd01a55aa824cf8c06ba9e844c2944233202000000f31200304020180c476452b96c1a34e3001480057ace5e7e4c9548c32488410a198408328400013200020202333509004f93c99bfdef05ff1b6fc5949293fe60656e69192fa18b52159308d8a42961e5d28be29c68ca03cdd3552ba7ffec9398182ab8dc959551f0ec827726ff78c454d23985dd3bf4329b9e3186348f01ba5e0207ede35aa9f38c95096b8d4ed0d5a1aad384b64dd458c9be5d3e3492058dd8b6469c49786408fc2fcf6e165591795e25bf9c9f262df81e48e1ea04fa1bd7da5738299423ed2fe53e3b94ab158439898a8af92a11c4c79b641e52a78b0200a187a6d28cf678a348a46609185adb9456a200c2f812b3565b71bdf3782c1b420bebe828d6e79a1506f8337677d2c461d5d957dd15d0af17026483b639ae4c278d296cb89186c78d2ac8a46c9718f93437b3775a09baaea229ad1afb9de7b543b1e99426fc4516b18e742587ecfb9760ecdcd9320ec02adb4e5a8aebc90d4d105dd50395d08060da1f85aa7e6dce12d1b8ca75e56c13a28b33dd9809cca7a7ee0a9361b58be6cf136d04516f6f34ed047e2967e2c514f7b1bf34fbe0119e9c8bc3baad1ead327cdfda9a721bad5d32cd67fde015afa80f4383cf156c3f41dc1f495e2fd7a76a31ff1e3cf398d944c6e5a022a210f4fd94bc23e21a654c813f666a711777a907a6877224c0eed034bab2b3a9146d0d7a0be4536db1d220814fef3042f236e85a393beb030f8f2cc339281fb21ca38038b9fb9368624f7944fc4e33ada172e8eaa225a285db028c8cd478b16c64878a1aa060298a37def82976befc51c87f40fd6ee0a0eece000eaca36673f578cc23b24634fef60aa0c3948624f03ca06d940e1f30d76354dbd748160536a5ad588316145d1aeb5204081abff894e124c49bedae89dd3eaa1ce8e3ce3bd7e3f88328fa4c655c717fdb61df9bcf8f25c25b98eeac2fe84804b05764048f6e189d86559622e36b73903d88cd1c4331034145bd567614bcc0628f44dc1ed773b9eff89ccad5e54bea21412afddf12550718e008a180672ee207754802891294fb974ca31dfe369ffde5f11b70c37d49010f6559777a77de3cd4e1dac1084b9996f24185dcdd1a247fe446c3c1c927c1a6d92dac25afc72178221ec6c3de8fa327eb70c13b5476d7781914a2a688b48cf66d32b94065f0a573be30c3ee8ed9950c3ab902b0e308904262ffbaf9fcddbca30982bc2090690d8eea6737687f5a5e5d1278e7e04a600b01486ed53c8fbbd26851598063c5e26f3e57c40a7c3eb03d21f0ccd5776e9514102d3cec4896f575c700ae266b012affca53c10c2cddfc0c2de64f0b58d4c17c94fdb87ba188956739c46f21feac34994e16868f1d18fecab1b34092ebb2de8e6b21c9b06ce202ef644bab0d237a4d6452a289c8927df8da4c9624236b0c873d52abc30d83a2b554924e75527f92943b2044877b88113256c8691c69fa9cac5801255c781086d289d208ff06f1cab3c2ea1ce297d48e22f21e5eeb606b11a16f2587836768527106124db24c2a991b2b673a805f15ab01bb127db82b9b8f81c93fbd1663e1e3bc88900d9d6c2afaa1b535fe85d3e74b91c989d140e4f14ed48d7544bbd1d150a3d8e52e0d162020e8f1a8ba0e83cfb73ab921093f1b6add3d33b22a1a4196daa88715ec9a458b561adbb5876a92123905b5ac132d743aa7e3be67649806dc9064737bb9f6e4086a83c84a04ede81b54d3990ad66ce1c967bacd18c2e1fdbc0a7d34db7e51a5e744af4f32eedfe06e4dac6d7a2b9ed9eabc87700b2b773ea8fa73d60b031dd0481e0c20f38474e2c2cfc9b8eaa18b629edfa884dea65bd029d667cb24c9608df995ed0e42133ddc0960516e007635484e0a2d4d1a313189af2d9093804f5cd80a3c75caef2223ff6788d11c84dadabbf08f5989c6e6a6326dbcb10f22c69aab5fb70e9ed21dd10108ab658d4703efb928cd01d57eb912b314b034313e1e71f54627d44ec63c32a43a93b33cb581ac8ac9b3a9ed58bde221ccee51aca21bd49af0b004c558795de140df74dabb3aa22c3e820a50a06af9c33e5e9979bd9d1ca02f41a9337346555c05151d64e0b568a0b4ff57b33c8555b8ca2d57478cea43858b4e094b12ab93ee682ce6c7cb31f73f47e553aa9d70fd1ce583cc53ea50c4d86d5731f3530319cc891826d84847d0cd94386d214caa64cb8ba50e250fc856998f3f2e01ad3dc480f7ace45dd13e08609fb49d1cbc095f718ed105dd48c519098a292bc96f49707a8e3ffb5a12d20dbead10369dec848263bd0dcbe15bbf3f4347ec36b372160d8ec7f0abecf1b4f90fee89cc47b42c4d53b319cd41b9666709febe4a188d0a54986fcb014bfea76180c25e0a53cdbdb7a145af3326daa8b2826f7a441e42dfeca8d9d032771206501ae730bd8366366be8865661d1e981c5e8daa81766a34944836230c73770cdab0614ae10645b25b42972cd79558502116506377a3204df38a5fc44c85f70c516856feae5e1397dc6bda3ac79dddf393c50bb507544ec18b3a22111b7645673a3140d2ab638f295c2048f45f31144d8723be6f19fc1ec6dafc24da55270979a6ed52d93d05a1e46317390b78ddde7982b028826e2ba4ed6841b88f90e4093bd51685b98b4359915a235fd88077fa7a5985e1261c725ee10432eadeb671d7c0892283cc0de1d05863aa560e0df19cc614f2203a0a3f2b24945fd020a815645fd328501677d7da7997cf6ccc296facb50c72184700febaa3f29379000ee74daae97835bb1704cc7c7aebd731f068c1302bdabd958d20587d08ddf2e3370891331cf349b13a12fe243bfea603c6d2130bee8f39f497aa4d0e9014832589a55b2606eafd64e74c45d63ac211c328c5544082d941aadb6a4e14408f3d210bec024d966db802e6b1a6e92a31711e8659025bfa861e91c47431eba1679a1b0c667bf5bbcc8eb94924f68a610258bdec139bb7194f5ef71847e5fb6fbfca391838cfdaee388456423c5fcfa0a0b48ad39c036391d15ad6053115e60313341209a595230dd024a01f88f03a67b086d59a4e66a1025d6e73574aa2a665d93f382b332d73f708fd3b786421a1f1c2130432dce54d7266c91bea10d82486b81fddcd81704b15b2c8caf66da6543e4e706e10f0a5bde1ad69c6d25cad03accafab0c01f5fa11428c5437ecfc8c2491813b5d415135f220f447eac78aede51b1760eef1e8ea1d225d77e0ca99952f4685ea5555441b7fe8cf1bc7a16717768451e021c9fb4103e5fad38a4e8f2305ca4e2f42210c24e40d199f418414de7c357e30900a6e03d083c570f386f65ce56c8c664da65534557ab08bc4dcd091f88ffb188430d84ab2dac5f6a26d4716b9a85f230b173034b6412f4caeaec08751061abb50e6598e8224dc006d5e33e7d6303974458437b54b317668eb8ae6ed9374530e48f91a7ddcd9d352d0084d2a751f75c83b17fc3df58cca4ab26eb0a6d87d4916329996fa1768d62ab8ec535a33a157147bf509b885a9492786f91d25e568943c0b5eec4b5be70a0e32844a508ef3ae862d5a877d0984c4f403ba0cd74aaf32f4087b56abf5b67befdcda921bddd5fe86bda1e95f361dd586e0408d777a151ef74941b8a22c282e8fe3d2bb825df0f4918ade91db90fef004830a1f11cc14a31d5ce3fcc20dc25ad56973d65bf37b0ad3b1b5e1f5825f2f2aadcd3380cac56b7a0c36cadab64c4cebe98f56d697865bf525314da7d3f859b8b2a03181ff4ae0c63ae98ad07608038dd6119cd7c68db84b581edeaaa1ee9a14aca5bd937fa01de9b64ed297a0583f96e266991305482a8795edfbed07934afbc9a6d21ac8c1827e2a099c6611a2d8e426a7ae4d63b05106014bd3b7cda41a5847ceeae8a228df082b689a4eecf2859c3660ea57994ea0222507aaa6654327da233671ba37b342473f626d5f80ad10da3f5632f725cc8eb60ece30ab6e663f0d0a333aba9e544ce7135c46a6ead89c57f28e6997bb0d8b15ec60d471bac4f0cb885bc4383f1e54b166bd940342ae71abdab6876480c835c83f40c6b34738fa29083ef0ba9d15c65b0a9de488e508e10869e09a5bae7a2fd6943bae4a757d9253ae6c1567ef9a780c4a916332df5b2904c68657c9064871717ba4a1172dc4b63b09e35b5885e4408fcf1649a37aec887a51a75e5d644197daa952f82bff34f6e2bc1d485872b953078a8b094c74d913c7d9e059ce192f40a3abb35573c53014efa2351598f9e45f5b57b903467478b6739d8b1e9e78f22d3746fe1c84e7d66681c6338e4dce5f5297a579d740495d90af11514854dcca137aa5d57f1a3f6ea66cffa1f679b9e709c06452a41ff488c1ea5a001413b2981029580691dd271c2fc2083947926a3869ce73b1171e1652f841d49ce1e8927b38ccf33d983762ad071b0d94354625dc0cc25718a1cf7e15ce18c16301883a25d8267922cb01140da25e9d922928f7936bf9dd4279653a26c3d356a9492c27e6cd0c119c555ae7e6865381012e6dd82009f19f5ba9ffc4f2673399a1d0e21432c6e4ae1be5e7377a5d338e6bc3ad972fde900f2e832f76f7e61de4a2fc00135087b18701b95e9af266516e6f9406587d6a3f81ae8af41a160925dccd01e42745ca21515b169e1754e96bbd76eb31199e62611fb6aa4b024a4958ea7206a62032577f55d7e2c43a581b3a2012a99381f2f91d4c365b2bd4cd8f0dc0047f909515fb5e980fc1c99415f4d7c8553107bcdd4c92e181ff609701ebc0e4f3e5ff4730b21f7a85e013c8c6b2352728aa559794bb223dbfb79f3365616115f09d7e0c8d8f6e4463a0bc02943aada8851655500acb6d30e10b15bd092c5945b34f1f90ab452cbcb0f98864690e7f0e5157ad9843cd2974349ad2a05a88c458e81959359da0d5158f1ae967423e5c75cc3a8f9b9053c3a36580b37eba0960ba1887ab6b365eed7312e4466407d0536fba8957fd5708e619de1688e2d37b7a6311deec91e5e23db2828943c5eb0ff4c03391516b8be19c01c969378add7c1b1188bd3d0fc3a3305fbeb467864c17f19974c24cc284c5e8cd02b1555a91834dd6fbb7489dadf6ba1fb94cc80f7b505f39a0301b787009a6acb447acfee1f7a0f44d8c06bc207dbe45524c3206963699dea3a5af4c00f7babf6c21657ac91d433f9e20a4352ec7c8a0ead9e45077b0e426df1c0243ba9c2a7bc8f94d05cabed5d1a0968bc322aeb58b1c65c5a894858180cd6f138edc281cc071625707b394bdee4581e9794b7f0d9191a3f753a4a5bdc6f9d663a4c5861925caca09504fd668c00e5a098d9399489966ecc3147dbc5f4b786a5e38e260b3e9c0948d718237daea837e95f0a51a649198efdfcdbfb90bd6024124bed7409663e41505eac67a9a89b89267b13706a1de8490ad112d5553685c02fff6eff162367058d3b46a83ba1a14a2cedd85fb1da5131d8c4fc842d49cff0c8cea0988a1f7a69a6b8bac70818ad0d2ac96f4333c64b836017f4cd1af59d4287307a2e5c78068b68106da9871db30d561c40e9457039f2a975183eeed2f11f4e4af2d653a6b5fbe11438490ff993337f73cfabe5975acce1e1cf8c7c8e4663ae72f6f5dd6574385734d00f33b00d5801a03fe2a4ec05c12b053fe390a8a73edfeaadcdf13ecf1e3cec30363ccff57bf38b2fdafc6d149c383b4a8d7810cd41fe7645c76b5fcbc371476546de25c4788df537d83bc1ec93e7b39abe949bed45bddf37a1b31271b383bc5e5fdfa5e1d87ca6c572c797801f8beab981a37382762be920f830900aea4f4db8e258c5740fbcf830ff1efecdbd397dfa5b6be53c07737ece9b1f69d4969e8cb8927916ad3b33e7ebdf9af0e4bcaccee2b4e28230006b6573de87035d0226ba8ff70532607212224f8360887f11e72c18b02fc4ee09e2cb255cea06cdf9666429fb8039b337594b3929208e001442a2c3c954905a6d6c4f35d780934333ec25e97951e8967232f0546aa38007473cf1a8fe77a7f11a5a7f6a906f087739fbbebd778ca78cff35ddce7bbabedac5eb3cf35e3eda45117b0ad1acd837dc18cff4202f420269369a555456862041976c9ce0357ebce91715fa04a5867c1682731c32030309780dc97998f67280237428a26d8daa1f90ffc8f66825b33e0f89d125a908f95527489b805ad598b898948357950e827c3eca2ef89c158d717073ac0777f4102e72f0f9d82ea8bdb863d0a3abb923849f2599dd63a587048d59c49009097930b753aca27b148aabf5174f40a008342ef31e2772f356312eb2e2669b674bf424994fb780899210a94e63a3c043bfa365dd2983a89bf9a6285cba0fdc07289ffc7eea048c131705ba94125c36cc18c9985727911010e3cb584054096f9de5dd21804fe1eb08414035c41e5424170e001ac9e5798963abe1485fa4a7e56767db4dc1a0c3da4f9c203e50841192c0da9870675a008eb39ae0957f63bd5bbf606ed5fe8f05a4cae73413e440079baa35d3bda33051c4d8ebf7fa52b0186b3c175e599ccd850984fa24f8dcb5f428ddcb1a24fc1eaa2603444fd866cbac1e33d70b228beeb8da8a73f652d842036c4be8f8e78f4b0ab0625a90e32cfee18432a9f497a26a326b0ad1acf960fd4dd39f50198755dd556f9fad330cc7598b69b563808f4465899f52ccc5b20480185f5bd3e8321cccd44974dd3c183152537aebef6d3180de715a01a175cd7782de5c6eaf94ab59ad7db032aff6a149dc01125cea49637a813a4923155ecd9fb2591f013a11759ab43cd4e7e20a0af53b70951cc970e67d8f907db00ab8e421713d3b7d4af15e02fbb44f4f3aa4ca9f421a13f9db6651781b51aa68f712d91dd38fd92d95d53f77f1f194f75a9e339c833b22c248b49e7c003d8f7e5983c247132e3472c3ff66893b4dae8b7bab99606db1a8d1264e2adba8a117477b8d9268f07f4bc5acb0ace9a8c788b30137eace00a9bde7ada13228e283c2705cc008a3f08521a5aba316c9fcc056181c4bc1ec65e12949fd552f36ef71a9fa60802a7d7cc73c5d41f66bb0cac0abc85a13fe0bf39d2f084152235d5d04c5fc07d37c57d6900676a068367cfd85121d7da39317728c41ee4c9aef1f1c8849b5b980f2097f99fd5d46a5315a869536e55c89ac6a8b055b542507be03fb92cb28b5cc06a79139bfef8d8bb07ebeb588f837e3c55ef4f2767244e99672995aa27109988d2b1c7b6231df4817f86713d756673127645b7e18ad80d83fe587595b1a49cd7888b09f6e5f870f68c543a023e4b811950a86a6e5a236c54c51429eb0856094800913c0fe13b88fb60d18ff3853402a43bc78265d93aa5c06c0ddbdffe3a1e814ff26b2873e9724870363c7d0f368617fe172636e412200542df07b002e8864150615e6b220f277f0cb8dce2d8e9ce53a86d2cf1006d2d3162c746990c5e4533a041828b664de24e3e93b11f6d7c6852f97c506c8817669e2ea87a5fe7852502b101c8ed996edaa032e9fbc7a56fabf7b234a1b20fa64842c827160b756dc976125ce80d508899de8bac1af92f84c75cf25e97baf33fc7f884ec94c2ced56fdf203ecd5dca8969f5a0356038fe2460b662dff0537467ff0fc813d987b3cb882ddd4620463a622b0fd739765edbbe5693da9a08ee1ce33b58ef287fcab110d7bb85f50561d200241080152a15f6b035b2a687d573c5c31899d8053a035b04c3aaa042f20cad4ca90572921106634824db9dfe8d2e505b8881089d49ad40624c26af536d4892be51045ad64d84a002ef271cdc55b1ae24998fae6eda01d61cd37b0a0190ab8b35686699d9d5a148314cfb274b045a1b0ed54418da8dfb49c612580218034a4b85e8a4fa1a29a82abc7e593dc6426ce612cd7c6da990499d24222d73ae3da7e017ba48b1b0c9a410202988c9af0480a6e4e4b44a304f8bc3d197e615352fcfc5f0f82f14f1d507aaf4dc612d38ee50bc478eae3f42249c52fd9aabde319325530b4025dad3302ad13af4f175f78aa86b3a83a8c82a75decc716971a0637c9b8415a76b80f7a3eea0af87c3d74843dd0c6bfbaa7b6636d748361d5bcc5371184267c9ecc2aa3cab23361a7950b147de8b2299c8f8634c1afd297bbe77fad3f0f976fdd53bb7f0b92b295a4a5fb946a441de0359a39293328044272e51906e1f9c8f52d566e1b6eef6c9d2f0f61aaa155145de0993161af92c0b700dee77351e2cbbffe9636789bc8fe81478b886a34154cffc79fb2f135ee702dc5c231fad6a06ae4f46eb637939dff9f7741c2c50ef3c8e7e53e494f68838395d15455f522b35d103c2fa475395602b9c3352f40c19f0a03c92faaff380546b0bcb112bc566e5e152796a095bff7e06f04f75788a31d076a71d0ab4b090d453816a4ea2a3dcc31319279f275f692c33cbaef159e20436141166bea8688be058d02ceb8aeac09bdd08ee29f95fac0d52796f1379f4bd1cf97533a942f4a57cf50e3944ffc32bab93fc9f43fcd93ddb0af939c9bea16e3e29a73381df825ff2987550a36e8a6004081ef9bbf75840c79fe08f412c98a525a9b547db48c0a79450add041ba2713458ec9f83a60a8550cb45ee9b11bcb414835ac0838634cad2e7d531eccf389199862710da73615345f811f7d62d93c07822289164b9106d1323df1ead542d0385305f1c81892806a8c91faf24bf359b2be7383df69ce99ce3f945d41d0c5c5101f9c04f2d629240e8ec1293ea5035c4a5223e777db34cabc70fa026457700ef2b454c8a696677c19001e7b584ad3f60b05ee0194e255c9a565d5fd1300361fb772e81bef49e3d73b055dd8fee1ba75cc2a31a05f34fafdabd5672bce705437a89bfc7c7aaaf1137df3e0e26ba4949bb3202e7932d24e9f230c8c39a958b7f327ee8c316d94da27496360b3b40b595f215c85836ad640b124ce50724a8717632930dbe6f0a0ae87ab1b034c76381d6d7c198a1b599a7520959556c79fbca0cc96ac9a9a2e232579307d36e32e4bac05a2871a4214fcad3d70f0f5dc6ac4a457bba4224db1d8d0141560d5b3378e80c51bf5b55a5874d811330a9be4061230aad87c11054d1ba15b4d8e63c7863222e231d45c370146d58c899e25a180279d812c2aa0fc70e3b548ab83bb09377eca5f46e01176edd9065dba19669a852074260412b974b295cb8ad34719fadef1ee475457b154d16e596fa7cfd242935e443bff8832f39608dc13dc53cb30f0350b92c4809423a8daec189b7a0d0b0b381f08d2fca74c006dd700e70f96ec986fd0813eccb12aee6b8753fbb8912a569577d125166902004ea7aacac1622e2efd743b667224fed70a625b1c5acdd141bb37510c32df95eb40f4f14302854f792208467a312566c90d87d987bd42b6047b2a2188bac7898f7e535e878196c9f7c0a0e4ec30442bf02a621d4212bb1d0c930092ea5c4200e8546463f77373d315968dfd5a1ffe3b1a4e1a033be808a9d4df32e8aecad0d8198d3f4f67df15794ab950c4d604fecab007ec3a37b8c9cbb93a367ed3f6b0a89ea130d8d404b440b010143472a98c970833b7daacdaed34241198041d6809eaf902b2adabd8b84854d620da434b9e08295df89c6702c541c2d2f17e0886afadc5552f97ace8021bba09c64c38e2e26abb0163fd583c40c8cee701a3670ca8875729a74cb153c788defcba6828b88845101aeea695fd13421f172b91fb4db0cab58dd89215ce8f406dedf580fcbb4bde8b2204368ad7889f8c533e28ad5eda066b2372e75e9bb48110b0d71dc486237da9182ad185f7bffc36dc0c1b51050f5844995a6f7205e734bdaebe550e1629e99e81022e23a3b8ecc35cd328406cf47b0cb71b313e13df8bf87c95f7611d46bcd9c2a77b43601110d7bd79fe6820ec8df78fa930b763d845d906430fec1cb7116d8d34fb434a146c1a3f8c61aa5628265d227a1c082ba7d7e162a9b20877435ebd602680febb1026ac913a62a23592ccf77e3ed50978f13b3edf1780ed233af1975c554d22ec9597457c46ae1e24fbc7e6413e384d2edef600c8bc5e4c73aca4bd5f8775da76e56258c5ff7fd9fac69e9cdfcb2dde67a7d605cd32788febaec34610e1557c6fbfc79bd3448df74bfbca9f449ef990145a7cf52e4425529274c4e384aa605d894e61ce59603a2ed82508f048fbb603f97b050b924febf2d92a389411941d32c0e8aa1e979fdba2f6358ee8a7a63cc4e191e5ed977bacd1e159e0b49ff4f6ad79a9f91f38abee9efcb3898a4aa39222f093f23e67f8f84648cc40cf7cbfb8959f59f12375999203c1a2ab3896ce8c9546eb9e309b99d3c0ad3f1423672a7c24568066337e7670cd472bf9b31998d02e74a1f1434aba638fcb849f93e18e44a6d48631833316f91da65f961c3e5a303c4fbc9a45fac61d9d130ae80fb5a68a7912a69ce8bbea39f207e0f6b9b6eb19b2a7ecf66daca34c13c7bde4366ccc51db4d1358e40bcdd9e1c632b8e1310a69fdad256daa9cc6d5edcd97251dc1b4f3f6c43567c37086464139448d79e3c3f492aa083eae93746bf0a438148950f3b4cbdc29a28f2be934e753de23111d8dd3376e74cde8f8e2f9acbbc97648fe6bb9bd8961005b9ed8f1748aea8552d4b89d942af6a85c7fe0387eaa44a6118922189a062da99dac01fa43d5424ed22fea9ae037baff5b544afd6125b706ca02e82aa18b16989c56d2c77d7ecde09a0648c8f30c670393883c166293ce382278b6155ad123a01af353ab023e5e2b62ca4b41886ef27be6c2cbdc8d8b26cccb57ab8c44c73ba576ae736bacc4cbcb8a2916e21eb0b3cf76a559db24ff5d0184f3913661c0ad50a710ce57e4a70f0ab16c3194afdd344e66b0fd909913fb516963cdebb86d2e6f6130373f8b0f383b2a494694e8943ba89ce521d4e74b0e667365394b73f7667b281096f1b19cf906f9e6768f5c9892aa9b6244beaf60d4f50e39d8571abb2af6a212596c7d87cbe5e77540e92aaafcbedb35e0b8ecc318367238554a82363c85011c2e8d2b722d956dd10b1e8afcec38f37f7212d54114d440cc40468b60ed2b7668635237eaf9f2c37deec4d5e963ba110ea77c4f625fd14b6321260307e2d6b3a6b3867a846bec0af289fd10aeda5db9023a48c48884d9d50cdfafeb7c7e2ffc75f6bd6e5c03ef39ce0b0debe1a6897c37d6281478c491d6ad26a5bb94b816d8a173d2d0e4f8a6f798bbc743831694eadb15dfb6c5fb828c5ee2156d2839c8ae5db532a3d8c4afe84adaf2a10d2c8ab05f0112951fcb6e2150f03191279e64b608bd14173e606c2dc412aa7c2a55ebe4099c5c605f5069e8101ce32d5f679858fe2d4fe78d8dd0cf901357cfbdce5d5f3c889f33886a78e3fa1aa7c51470984f3c98a911fdb20b5a9a04eab95b978ace541fc724b06ecdfdfd2a7f93979acbc746cd4c5b2383997c45819fe1a67a05ff4b2972d68078155745fa41ef082d37d0766a787e4df238b25d3a0a9cd5924924febf4552dee2276111591dcb1714f6df2e144cf839af6b9403bfedb42ef6ef9278c6c6f3619a22c649e0509d6e2740d219374d379cf058cc13566b6aee0f21fbcb0f3ed609b276d71b9fa2ed78a7606dce0bb83705142a5eec445566a8a53d02ec596c467575ac719ddfdc034f6d2b5e6a295f404e0a0e17602486334e296fcb8993141d36952d45c6609d002d8cb0781a7abbf46190d54928379f5bfded3fc04aac8287ebe861bb386a39ccac1b2091f0bc2928cb106e9d7acf967d3087aa73a011dd92cad1ab65dea35bcfe22cf05bc96d9e30cf40fd2afa2261aeca803fa0af69999fdf431c7aec6d63d5cfde04a2c69b2942232a45ad8780b24c313d7ff95ea7e3a17b654fa424221ca11053a953bdab8f26dde4015c069294743fe1117df1c5b9bfac446ca876a6e9b8bbc23ad1a91cbb6163f9b3aeeb92d62a864d40474d051102639bc5f275de769a8882d10ee98f9ddc8f902c92c46e4dd3f817a15785f644ba0224891583ba827fbc647309ef3745fe31f0ebfc3b3473eea6232cd26d695c587f3d42da0c635eb953be08cf1124c45b3c86ca0fa4acfabb58752ece2463e577c53941e19c9f8f6ff75f2a376ebcc74905e331669a36d77bf841677973c7d6c941f70452204b63c047b22f437211ee612f04b383bd985578999549d1bfda5e93755e3618bf29b7e8c6abb674c029aa964d0d12208a27ae1fde35743820972237794ce5a2c448b539334b237d3d941decbbd0070ec670453be23851ed0a95b201e41308456f5607725adcc4bc31132b42440f8cf5ef103923054b99f47d0797084e8ad7f88cdd7d5628e8dad1233b3e6da9bc4ac3ac52c499097de903fac785e07118238360cc64bbc38ba70da3cbd5dbf74dc07e8df5af639d10785d5a3d389c9a5e0c82e85c3bdbcba6378e683a8029ce329636da5106e09b6204471bbc674b0f459f157f4f2d664e15629a0646553dee3bc20b92a74103ea12a9eeff5cbcbbc5e168b7b859b5e2e3d0380a147d14d8bb649b60da12b96e9596444205c57d4aed6b27e08ff82532935332c9882d87b04123fe40d2cbed4d8b9a6b9f526fb33461f51b068fc17b7910908cff91741134ee9f7a13f4342ffca4293ceadab093d3c2ac793e103bab6c2007a43fa88bf307f8a9f41a03cd21c609a584d4b3b0bcc14f26c2af75da32443e95becefdb7e2a142997b7b05087666c3ea1efa609595f3031e9dba40c9ae49d307a190f30e40252649bf8622b7c9d486696d6a3fe3ac1f1921e6f9617aad6342c52da8ad23c30b54444b26b8eb6c77c90f76c87b554bf3e41585022b9ba7d138b0c981a6fcca2615b556a8355d65602cec65ef36080683c140f29a338aab3d7561519048dc9b77fb1defb46bfd298cc27bba7e6ca0eade695c5e6acef54498bf09fc6d296e8186103bebdb1d641c7e39da69a019c87ab0478e1927d00af0715cdc3a99e338c7638e7b09f2ac7770ba8508f65685ebcb104873eba598b7f9417581d8967fdf6ba0d3bdbaf9a2a6439cdc3520bc705ed7fe183a507593abdc3d16f1039879f0cdf338e609ada005ac5e32ded3719c40f22cd575b215ca5149042385f0c99ed937d2096125d0d31a11b3095cf64b1150b5b051ce92986342fa316d644bd7b61a7bc7092cba4dc3ade3ed861d7957abe008b439207af0f22410dc0f6205f5dd80405c549cce4c3233ded9d31944f1f8a5ac4c7d7f882538626424f3f2d70a102bf276ef3fc65bf9f577ae6c7afa753deaf4a1c8993846b116038be8845a4cc6bf5eb043c32061713b9b927ac93f7e9828673d50d446a0cf1355b2a9960cb6946f85467ac97b84c8986c7ad0fa136246b5be7ff4e8c41b937b94c2b28c1adad0fedc576e8a14fa151bf9cda70df18fe2faa3aadf1bfb7278cdcc65cc4451524717eca7b435c1d0fd2a2c594da746de102f8a9b87e3efbd42e8efe151b0285b60c853c9e585f4d583c3b48db24e922c5b77308430f904a4bf91c4b6c5827ee28decd638787c9d0a928ed016d0a7c6b58b4349773d341fb26b27134e020bb30bd2c6fc68f2f8e0ae0daf097acb0f6a22c6ce96b534cfedc69ebd28f26a36b4c7af50ef0ffd1dd2837f0cb2a115ed37c96a9851addef8ccce64a3f7c37d345bf059c1264e6c42d0928c3f917809154e64d1c46be943e41ecb9114f19e20831c37456468978c0a2e9670aeaf04c529e9f4b1144964513ae5a24d3311cb9cf71184db916db9b7ab575282d763fb1b88393ae5260f158a1ee8e78b0ee70171f8b1cbf22899b6c8307f19eaaf2362cc0632966215b7656fe01206f03463ba0573849eaaa9a573b8474dca3db9538d0a585cf470b6b9764b5c936aee4d2c9e97c23ad3ddc61b597d08cea78077bed5e3ba443c3d71ebedf49eefae4ec076dfc8dde592e7a4563e91f831e856d9b667e3f0addf65d9c008c257ee60791e8d39ceb8973e5dd910f5058447efbd4d4ce002449a05398e97a8834e05b373f314e8ce7de25ac5e24f331c3a0361657482eace3b834d5100cfb395835fb51fc020af323843e3f1c95c070ef1c17ab77d5f327fef00912d55e05b33cea4cb773de035cb5831d27af451f2124bab5f39206d0cebf958b3a70f623ca50dc693d7f083fecf23384d8c6745d8d5f5cf30d0f579a430dd1881c0f9c21dc73e114c30e9354dd4d808108ce79eb744af56b49b1e700cd2ca3fb5247ae845a5cd8b891ad23e705024cb5d1fa3e0da87e6ba1aedd097d014cefc3688ada702f9c26204057214120104a7586acfdfafd5b26aebcf1107bf685adaaac04b618dc3e266ea8d9f64bd507542390f980de3898e59b35dd48dc06663d63a4a75edbeccbdb4e8eddb307e39b97f182c7f590a744783bea2122052245a4cec699403e33d03bab856229e28852f528891030556c15a983b8fd423029815f1ee28e1913226aa72fa26f6a6b1723a9b9c4aeb9b0562526f21abc7794db6124e9df0e895873446abdc28a2010f84fd60c99e1cb89321f543d660164ccb4e4f7a906c9b7138405943b5fc6e2b6014f4bf4ca97823589f9ce07658443e80a36cd8324d4cd3366b35c4d5ae03bc8b3a3b0ddb6997c26359d52d40087173da0efabbac4918c9d0856b3d42f4d63c081b588cd533c018489b9cbe62ba1cf528ccbde4890f5774aada5085d80ffbdcbc07430ddde428414fddfe1362e8e2e7c75100b81f626bd196a9df1afd7a95643caf1c352dce1e2840176293a13f31e6b2b8473bf7645f39cb6c27ebe7ef7eda6da2bdf5099d1bfa33bd41f612e6a3d474f1c1f3f5a20a43556a4138087b75a15b900f2158cd15458376f92fd78bfd00e79f14094bd36985de40dbcc4104860882ea5268266c505239633bcec48469f6e1f20e26ac2b3bb2c1833b926ac1544dae5aa385b1b47663ac4be51e5d7bbeb0b9a3695962a7156234111fa064f8a8bf23815e36f3097cee3b2afd40f93dd0c27d7a86216534518b5c785b3a3b52e61a17468ae4a2607afaf89b351d85331320b029951a6f8dd8212f21f466e9ef7b1a41b7156c0679386138c2d6af9675a66bb87491b566584d542f2db9f86ae549a3f2fd4fbe1a9f4754e3558c4edf7ba7cf37a97932536233bb4052d100c9949e0094bdaf54b35ddf544bd305eb309bb44dcf6d7afbe5fbeb7bf7da05da030ecd70091abf1da322fd22c4811dcae65c2673f3d13abf20763f6ce0afb69ca0c78b02c1bc1c75a323d8d13acdce1f880070baa79100193bba0690ffe6953cd867dddcff9b9b871a0981ffee60e11a85a9011486ebf688227f7f0489298eefbae698cd6deae20c2e7ad8d9447c031ba1b7ab888e02748ff246425303466bb2958103b3715dabf70fc865283f241d46480cae90d129a1914a32729864189998d4b745efc28811ce21598ce26b2a4459a0ab1e8414649316166f0ad98ce56bb7660f4aa1d4e1065b711fcaf7ab00d9f8d8e88df7870e53fa3aa139a405fbafecee3fd6c336464f7cd7c7e8e5c70393727c4810738e764aadd6ac7751c17da7a73c67dd066745ec288e88a02eaf94cc6b1a3c9e977b2c1be9adf1fdd88dc1a3232eacee2608d6c6d32546439d6c8362c368f2d6a30156dacab458571747c3c37ab8ca6ca47df0579ff1062a6c288ef03cccc9feaa980a1fdc676b62d49cd0d493b9c0d2b60fe22481248a0e6e9af23371e8e863e44c4044b5d378e24590b11b9d5c6835481fd791c53ec88d6a8cd17206222a785f614b8ed158f6a12da1ce2e3e5e2ea1527678d9c2520907a158bdf9c603c8d1ecd36cb6dd4fbe96b8013eccc27d7262710924bd0749964f82a02d9e6b7ab586686733afdc4464d927f40e944f399cf51018c04a1ffdab3a9d056af7540b05f6c2c0c8b22f7cfe0eb593811db3f8863177ad72f57de23286599fbfdce9843a783cab87e4992aeca9428025713ff394f6bc1c7e906abcc15ba34bdece0a0a5aa09cd6ac18e2687d174106e21afffc01026054a825783db8b8dd6fbb371b1b17ec6948366dc004d8e818662a765574ac13afbcc4e242cede1bc9bcb19834c7eaf9d404301d0a0e927c9af1704d75d1221fe02ffd3c2d4ae7c74163490dbf2f17eb991db3f715bf74ec3badfdf1a703f06154a00c7a3519a14922ea7a65850bd9c45b085158190ba46ab55edc7e0f70e8f403256e3b7d3aae555e08ba6336611ff7ff24f422800aab05fc1247f7ed22789007c5fc120087902c9f978ed914a50dfa08b2f3df46b726ec561c00e15bb960847f0805989b84e6fe2a42e8d7b5a42bd40ffedbbbf1f0d58a236eb40d99982c85540bbb7fc5575ab568b5b2560dc5411cb4b6e00ca212a3587e28a25d53d2c738f19b1d3383c3ce106ca58396c81f56018b110188f8dbeef9b514642659fba30c59c365f10bd9d5b35ded85314c332c665e0f09db38a2598ed244b0fe369cb869bf48a911184c15e5fbbb0b509069762386ae603147f4af3d122f581f8714948720bdb1686a8881cd6c670c44c8d37352d48dec7e412b95800f0a488ff95f5d969079e01cbf79e632fc8648951172815a921f66a885e26df115ef2c24ea132238f900dab2391681921177846d9ceed42213b07f77fb9a842ae168e3bc71e1c50845ded410761388586ba0ab27f9f07cec354b118240ccc19b15dbd81e008820fa03cd500bce81c0042bc8e2bdea2d7cf160537722a889778cd00894c041a71cd338fdf2e46c32493a0cae8a19517e45b3b08d6f89d734abe268b313248e5facb539fa80822bd111dc79f681c313de3075f1d5f62be5193e4c9357a05b4026741ab240c593d608ad53546138eddcff3c9b6e8b30a364e51b4835c104cb9339e0f6cc34ad7f422260d78616b1bdb22bd97f74740cde56792589b69ca469cc62323d02c4aa03de9b73308e0e239d8d902e9b962c0c0de94a9c3acfcf88b5027c2b4cd46af420ee809cabb6e0565fbe59c801dc3dcd8159f923baa1827b5637a0a2b12eaa453410e99fe2846ba76aa8ab6e6e88cf3eb5d75a419e19cfdbf384fbe5a6126634871fd0d7e2a62c4f8a053dc753ed72ec5ea4929ef49a32bf3d91f5ab20d0ff845ca31dbdb9d3d4f4b27d741747d79a2e644e52c471b15dcd312ccf94ad419fd71ca9c6a8e15691610d2f7661a576864ac067584ff11676efcb80b6e351d6de62a631b4b093c780099ee06a18a921300fc25477b92031e7a9c4388e7c188ba2c805fac80d35fb90b973a1fa5ae016ac9b6ceab45e0012cc3e585ef8563602342837c96289b4db90c680022d24f2d9007e8abea95207ff9f5dbada28743145c12e57ef64abc4d2fe15642cfcf2dd4c5de187f7653d301218d354e5fcdaf6285cff647241f2d9617a2705a4575771c8a21ea3211b2a07f70c96246fb9ce34b6e10d5eaf578f84ef06027baf423aa49a3cd74d8c45c1f8f23b2d0031c9c4ab3f157c75a2c94582770f899f07085c8d6c31e85c9f58d6a46e7b3c5f0fb81d5a96b416dc1566616f3658eb5699bef2802d7eb065c40c8b7adb04b20de45c9cbdaaa70e5160b2782e15976e74bb1d32f52bd1ef7fdaf940bc56692228f4ec24b8a5ec8f86d6ac1a50698c68c60b78ba0209292d53a849eafea4a11ccdfc1e24dd4ab3773b29024c29ed944560d6514d8b6808e9e01619edee8cf474ef91862a048c61d27ca6196ba371c29b5c5ad9707ff210fa77b04a7882ac82daced188b1507689d763caa47fcd4ff239562c9b70e4f01405b7059a55b3abf6da8bc358e09c346ead91a18204c1273e148de6cd1715198eb8fdf43cb2fd1ebc333a9d15abe556dac82b2bb9223263caf36b7f8a8fcd5466fdd4a7f6fb04a91c76c812f2425ad6037e21c8d9829b43bc1386a89e18578a8e39326d28700d72a0c85d58080a780672ea160d4b71394c08e016e22c382bc618bdd9098b066570205ee344574a3f2a76fb8761a25d51ad6cd90570b49233e70b751ba127e351d1285f9e6a7d230dcf2f843bb40aadd3c7807ef74ecec4fa106cd55d0cf46c1ba873a97226817eb0c5a1e0882509e00256007600bcfc777888b36407df941814ece5cfa3c41a9a491a5014ddcfd22cd041edd875e7172e157516a8c8d5b3bc111a6964b919b085a2e8b5b439fb1ee9cd659df5fbc8a699597c204d1379ca91dcea3dd4dd8d89aba6d6c8dec1434db195c13986e98315916deba39629dd14e7c2a2d9713a0c1e590c0d9ca3caacf186e3a234e4b5655b448a71ba34630030cbf448d7eb35592076cbd4831cca600d861d47233b6331c3068b62d07f5bf1fbe68b59c0f5b54fe82ad9d35cb5ae751186a17217d31075079c3cadbe3d6ec1f526bf9006c0389d62e46f1cea2b5c498cd588053eb85ced3d0381394e5a30a4d2f8ebe551aa989491a1269dd15d6c338801ea8ee21c07a689454e60dafa8c6cc3fc5b44936f9095a19f43b4edb575d879d04dc1bdc20253074e4a8a61032831397b0d8f47b603321060451d958616b3d0a32a9d2b1582b0d8ba5f3a9240d4286912694055d75e075256d7f58c6be9fd5dd19e5bb32b67e8832ad5ffb6148a9ea0671331f9cd15ee28b7ca7d263d69015a522db205615e1024a8159dc2ca6c17d04ea01fd49b858b1385dbd23ad02da87d88f32d17d4a62b048867b8189072031cfc0642a8489a0968f35b84e20ba0a6925f2cfa8f95e252b3b550d8c2e927053803fad9c629ed17ff5565129e1bbb9ab0203241ed0802b131446aee9d5a0ab79bd49e037f3a49cae3c9b10e9c508f89452129069890922b5b8f30629db9afeaa33f52adfa664abab9d002228a8af49d22f1edf940b1bc4448c38337e95cd6a7711a370970a8b104057609e7780f4a8cc02eef0af3a7a540742f87829dde7c58fa8f5cf14a301df57c43592ec5a7f31bea3314a77bbb586237506b78afc0a9f0a56ebd193a2fb95941e3d9ae095985a266fecb576ea7d62d0e28a625e0618a40b65034b794600bc1ac530765c4861b2583eaaab3f4ad9ee18645289547d8511beec2371fdf3e5c9b10bcc2993d1987b8204afffaef58c3698f47812608d7381a05afc45ed645c95bb17e307ab4f898632c8e460846a7ddce3a31fed7d24e81f297ae939d5fbb632c741476cbd25764df20da120b2e0b4886d845421510a190fbee307cbc942eaa8b455488bbdbe0612b211c6b8140eb01be5ef7665700a1a24a59529c02e705fcaa28eb97e4a70476e1cad2c5b9284104ec2456be056cda7fa039f712c46b5122d236a5d3d3464cafbee5caac2861a93419dc3a859068bc47d05c141ea21d0403fb9b1c9feea955d2dca1b384f35f028a4f0da49708a68b12f3c754f9731f6bd776926c62138a1fa8daf9403f975d675504eacbab2c60bf1df5e9a15518e7ba0d472a8e4e9717198a4a8fb83a9993bc5cffce344e71c6cce821b51609c68b60dbf7950827b8ea2c1af2c53531d483c36bba16fc5e88799d09c25bc2abefcccf8fc287e0231b1644047df968ec5c24bb8115ed85968395e65b9a9b60a49edf34e8807743e2b55ccaae223f48a4d940a70f6d661a76a86afc3b483b3e8cdb16286280f769b6c5dae4979bfc110876754a8260a6668b36b597eb0b2effd001dcfc31ec3c15c712f83eb56b34db417289c25ab7c2d322c1a59906a7f64d483276cab2eb7f2ab2ee680b72c4e0dc7e4e592d51c777ee0510ad2a67a5ff725cf895cce86081639ec6c42eb8508cf97c2423ce11d1ddc68745e6e385ed4381c7829502bdc76490455d0148e823f3f4b421c53ef17085505d7a00922f173c43a730fd16890630027d2e9c60e1959251a0abbed86ef3dbc22e2c6b0e215d8264071050d3b10dafc7c83fb42a9797ec1cf6d12f63cc0b755d4c6854b271345f9b3525b49dd0f34dd0a962c50b7c324e3e649db670572b83bba1842951f8bf3560cb920f7cfda64d7b3d89cd1867eaad48ff08a46d0b3f8bd2f0ef183effc31c275f89eee564d50911dfd2dd8b9e4ab177450d47542322970eaa9e8b95ee3cb1776e809f6124568e68bb2809eb358157fe446d176141081d373f084882f2825f1071912d420747512b6fd4af84ecf14fecd2554022f7355f2466605463591a7573fd8d033563cad807fab358be7aa395e65931584cff3b3a069f88fbbb2bdcb93e5065b4fca4caed5ef12ae6893726ccf453d85eebd4e04bbd9ad44f97504c1ebcccbde4aa51f0e34905822ac9746a8c98b47cbeb0864bf14df0409dae999aac4c444c2dd04911baecd8789b66edfb0f4f7a72236d5b2ca079da1845caa67a0729690f33c62c91e333f134980b8486156e31fb8e57336d46d867e56817246d303e05a8229f147535c25f8113faebae882745544615d5d781cf1d57133989a299fd746cef678d41fd4dc13034e0f12125aca3e81b3aa0e59695012d3421eaff5716e6bf6745f63f84be785423c03ab8b23839eb0fc4cf187c0f9d31e2959eb7e5a83d686e0d64b980e0d20b6073488246083ac25476818fd8b37a72819fb399788b6eec17a6b7406472dd9175d513a86c2f454f58cc682f24590e48ec26437c3e63910d14feba6fcb03a222c03d36d89ad7f52876a2e10647d7d10c7c9a3a1453d7d1145080be39d7f0d83b03078159c8f8c595f26abf2d84b792746c1262031f2a6d64ecffb268ece86456fac857622f76db0edae5259bd7359ab0e1c15bd9ad8ddb7dd6965bd53b59c3b88d44eb570be7a9d3ceff7fdca5426a6f3382d16a4b64acd11b2eff1f6cfb939fb57645443f31a26c4806a749fc63265f49994775ec4b9d6d0038fda96429d425517f25f8257ef952f9c97cfdd81d5eb5626fa13424f1740b23de007f28e717f7644e13f834146288f913b9283d4f058d35ae86bc7f69b5ac685fe1a75d7482b99fd9788591f500afadf3d125c371511519a1da636bf71a5a70261bcfaef58c85f6a13e10c012cf4f65a35e6694635279378069f2d7b8d43d941d3313c37e92ff51ba529ff8053970cd561c88d6d94e7b6963f3a3c1c0be974a83c9f0a4abe69bb38eb961851482341824f4c16a73d3730ed43c825f881cde02a24274f103eb1fcab322bb83de5c0a9ae9827df2bab7bc320cc9d36883d204629ac4ffed5fa32c64b730d7464d33c853491fda0efcd9879f2d103442792172296a6cc15325ddfb028148b06a01555a6af9d84254ad574655bd4659f472d6c077370831015cd169e4ffeefd2e9eeee9585993dbfa0e25c9f28a81422fe9ec5f994d6185dbd1a312febc42aa1e05c9d482844963dc116e607f6210b1cf10da94442b20400a75bfbc8866bd8e72e2f915b8599ea11f718d8aa9c758f1240ddec00d325ca5d081693477aaffca638469de9cd860c889d110cb14cfdbc2b5c508d8d0d8852fea706f336ea669775e680f70579694e6fa1815a12806764968f432e1a5963d196cc25b263c7a82b59c026e4c91ee955a6c7c89873bd7ee285f63d84da4cd93a4fa21c33ce6794202390c53b0fed1f6fc25d1c00fa5fba40ce481808edabbd40f786211a99db5bea781389be5fe3a0fc0eb3e21999ea0a2aff760bd974a37b9dfc38f3863bc0861736f04e88d78339b7f58d5f86be5e34fb07a593724f71d8c2df76152d3ae9111f3942c38dd7f111657405c77297c6da4fe39bc60cdc755ed7093f92eeb178254addf09972707390b0397be7c4e1f1cb57a11e89b20dd02d51f0ad6d7850c527eec2372ada19cf7dfcc8d741a0c793b59ba8df6de0045ea6db20676bfca461ca928e5b9057bf94c3215a619abec1b1a8d5c36cb97d1c5614619c460fbcbe68f3d081a1f5f278c012dba051bf2064cd251a73393ffd0611d3c2dc3a04737621e8153d27b59405a5678ac2e7284d5194da01761268cfb68163cecd01bb497f7c2f65d46af7cedeebf27fedf2092a5e43979aa78cf3ddf19a863857ab1dd74ac81867544399129b6248490e32c9d1eb43625e7f91fba74e1b1f8648151a391b4b25d6f49706add2428affb8f8478464a2fc3ff6cc9d5a5bf4664daa7699fdad5a50753d0c42d84dc982bac60ecfeefeffaf32bbdbe3f0e3b063d39b449a5f19f7fb0f98b24b35e27e429f6fc3edc631f721d372c7fe1c4da58343fafb3d296b507190ae194e390710dce6553c1ac3fb2dd1aeb7195481b1fe99d0b2f75f57538f0d4c4820c1261247413e77f0693b17679e13f559f7fcc3c2f22325a3560cfddfcfe78f90293d1709eb913a36e25a7b42bd0f315ba330c07709268f3f7be8ae8eda17fbbfb2ade23221dd75ac1db9536cee4df370fc81b0c3c5eb4373f2033d4b94c967f7887c415a67e6cd61a27ed24866b0ecc6f0e36abc6557d9e282d574b962ba5f893a76ef88206809a198a7b30b6708436dae6721ddf13f72cb9015cf5441a414d2d931446eb707a51a74daab0993601f39b345415b48957dcebdca4a4137c5f577f2a8163b12980dda91722b10d7ccb8193e7d5e62150c0f0301613a3d6527bf4d3cdb4d2819f49af611d639202b3494ea2aa4190c2b78986f8c37d760a6c819520e80851518fe603301940c02de3904084c84c7230329d3de0d164f4791aae9de4c4a4dbe52ecb5952ab988f54e99b91c6a48cd8e779ad15bdd67867911e43b8ee2c245d6c9ce1f91131530f0117133f70df4c80d452115b96c419612e12b9d141de0b224d29cd2542e5c12c109ea0a35ffcb0c8a586989915cd3134de5fb34cf5e4bcf40888206468ba2e0910f577b1653fccecd56845e80117d29e68fd45cf682bd7313bed3e8ad108ba972473b3061fed5f56a2235bc56781a20859220c83264480f13d9aecd9a0e19271dca2361e0f17d2c4d36508fb097b890845e412fe4d3dc0ec051f4a8f39b0248eb67818e913a31884e374fd67075170d5491133399f9a04acf8d32074911f3a3178e9e620d8ef563fca74aabb574d5841549b8862b9802b972feda95643c3b23a07898d8310973e4f7861741cc636f6395da834f14daf03ab3b2d114b236bc58a21b4b38edb562ac83af8112dd09a6877e9e6659878c91711b40f07ddd250603f7ef38bc9c546619797fe8be28cbe65aa536787062b867865ce82df74dcd42f96fbea65c811b8fa9dbde9edfa3c56bf9c1bc990bd57dcb3585b9e860c7d6eaa8eb36e8899d1a82ba85c52f2f4ba2a57e92ad3d78a7ba88ba959871839b0bab15fe91924846dc12384fae2a274a13881ddc045600e50933660261064e7ad712f620f82460a8c0f6c869f74715c26f11e6c80614ee3e3ea8d347e783cc929cf610c628634556a548a47ba7586444ecefa78af902ecd249de402f3eea035ac9fd415b08cf2493ef9e472aaf17e797a8275b89b1cea7a4eab8ed9bf03580eec3c49928bca00dcfa5d9e2e2b0b8edc5250c8b21e71f203e1ee99d7b26108938a60f603534a650112d0e4633328bbd5f0f844f8c608182540f7416e1840c9b39d054e7ade4f908014535be6468f51e055409dab717ca7b25ac9779ee2320627cfc027da0e9583e0127ff8ad5b4dcc6ea2189695311c780c2c3b0e382dabee694d7d49310a2e8ab0a18994a1b1bad065f9b79a3d85eed7ec4dc8569fbb445bbcf4644bb301c036dd65df0bf4cc40ff943122d7dcbeb1b0a3adff4af05cfb4f50f8c022bed061d0fa9a85076971b31430eb3127964c832c2677910c8beecb078d2bd604819a286cc89b69b6c36a8bd337f3922e6dca2c5f79fc32fe850921875440672de64b28b1c20af2f1b4c55a8b19cbfe8ba6d1ba66065998e7368a4d59b58747d25ca5a336805aedac1b9c0feb0f2d205c2fd5874e8d2353b82ba1984781b4f19d81da4a1e65efdb8dbcc5a3c23cf796de305863679cd0741b9ee6b06bd644c5b5458ccc57b7557ddb0d8539eb5d0936318c0289c88554b86265b3ec516072f7ff73403275611a2fff46f139a3ca4380a1e82d9ea1a6f148611b2504bac182abe928154812acb00bdfc90df98eff59d830232fabcc7a070be38796020e0d9328a69ec5694876aa32ae23be37cf23596e8670214d96d86891d11ae90be6c9b26918e573e1136a29b62086a214969b9796d153bed58bc80603fda2a81487a18b744aef577f2bceb97ab04c9ec5953359e898769eb0494e1bb3e3fa82c91231f78199a4ad25db0374c926df6d16435064f03b574c77e0b9728d6dd95cc7785e360538b1bbfffa5522b5dcb5d69bd1d7bd9e52dbf7675e76fe69d2b3403839be81c02b2e6db468b35a1d23336cfff33ffc93c4561495472d7788d2e162527af8b8e2c14c9cbc68178e7e26bdaca396fb5719904d4f58f41e46aac22540ea795273d16a5802e00af5325adcb7724e95413edfed942169e5f8a730df79d45174245f383cc22b1523dc8691812a9f8f188a0badbfc40952ea7793f91c78fde204a92320c6d01933265d1828cbf740aab6e2ecd78ba3f3dc15e52931c941be1a0f1ed50c2b655864381b24901deb181d00e7e5dadce48dace8cc419cc66fdec75409f122d78de6dee1a4ded7f391532cbf4cdb59c5c9d46960934703364f935eb656adad4acf1c8e1388d6efef2fb5fb028144e865083effcbf32988f18dcbad15fda44a549671948a859d2bdb09ad1fb471e716544234f01a17f6701a7cf729dc765df49b4bb8b89f228cf40ae1dd8bbd0d7fa6cfe3cea3b8ea0a178004e583abdf0357cd1088784274273beda1a6d1350f013e0c28b806e2620295f906b0f4d05d6af3f6036b2cd713b4efaccf1588c5a6034414439bb7cc4a82b178ae533f126054b6dcb3e786a1e166faa1a8eac8759f01ef52b128879c5a9deb6e1b49a6e4fe899dd7f7bc355ca87500598429a8d4f1003ffeb3c98040ac04b9d0c037d2c6023116328908a2c5e167ad59c1dbeefbb90e6b2425f3d0eb6377d2168ed9d48184086f0de3006733e9ac06c67705d8c70c6e46d3147fc39210cc9c15f319147e2f780bcf34ab6043730446f7aa6e49942a8ddd0923140d2227ccc933f7e80e23f7e842fb1eedded264138232c9bac378efd1094942c58933971796093eaac9a8ca23451896eed9f34e6154823b4b3f1c21b876b809c94b344edd0a8a66f406f1e2bc06c159257d6b90961391eda14100a30dcb052a7ba086c57c022ed9e85651add1142251583d73620cbaae6514a21b7a9b6bea0c15c04e30157ccc428c4100fa4843985ed01c945c6fb198d8248b2d0f835c4d08f61455dc365c70a0781c858f5d974ae0fc61e877642253ec3cbcbdc5fb0bacddfa0299e3a10d3a8a1d62179afe4c81ada2439ebb7b7b3fd0fbd43c85ccbaa66e9b7f30d260a65f41aed223bc430987b5f7aac5e95e18a6b6e12d75ca447a4704ab9490f52ff89ba12b96dc29317c11d7d0a786b4544c8c0906121f09fbc4ffcb1cbeac91f08d5f63161291419619a5768ee0ca8598db4b6da39e36232d9609a97ccf25bfcb374ab0a4103d945567db431e5f60cec1e7ec44042ee0f5e70e246212b8b4aa8f80dcc15838e077b2e9fe1d42262546211ed964963afac1441b6971a532ba8b27d8bdff4f74ac2b8da240d40c5c58c53a6e185b5613eee5e6f5e334d949ab4453d5fa1e8c6311bf4640994957fb4a2095609ca6e2b3c0396cc68ee5516478fad0cd1e80c7b77d0990abac788b2983a3b0db2dec6d32e853b7f4e3f21071fb3265b4c26d672e66c58c2eb33494e8af75c4d42cad70417852d53408993b164d6f650b071dbdb096540ad0bdabf099388f3ec0c254a9d6557e5ad1628993258d8e4ad1d147c0e26b6a4b6d2a74afdd032acb74ec918fc0d7855a2815b42d0222c52266f3c6f732832ddab51c40fca745f7ffd8c58fd946a17503aaad4840a271f8b4a7140efa4af2ee9a6a39a2ce1a1eb03d87cf88bb5faa8cb9e42ce9087a2173edc101d2c09580fccdbb89dc8a98e4d5e82910aa2af24e13ee750598d7ebb38161da987df588585554e366695bb6e4c99a193131925f8e95cde1d6b190ba1e9b49483c1faf3009e96285a2da0780c70c6bc7c1154440e7b9efe33d55ecddfd5692b8bb57455eea17e4a465628694221b029d1ceb0ee0ca12a5623404b366fa4986d44fff3b44cce1a445f59ba9061f6a72d18d9c921e0e880dd37df93af42b8b0587e17765ab867152b306f1cca01bab7b1a18da85ff31cbfe1ddd070a17295e04d7b34b6e32cfd23fcc98def626831d8ba9b62a0c54c1e522f6040677fa1bb72b2e2232fc248ffe1173eba204d08e758962e1eecca5045172e06abd830bb74f57d69259749a6b69f222d5d8dc031cfffa0aba8ed7ee0f20e21f25a18c332e5b09a7475092e49c6030873469e0ffef8600637aa111d522a32ab4a9ea162223cdb1f50fa9ca1d6e209d0ad3449e9d20474c7f64cdae661bc9c8817dd01367d730725f4de8c6404f7050a447cb2166928a2d3e9d6c77d215464f43a31b3930e4717348e989907bb64ed68f4dfef801a0d2a82db3f1dd05a993fb84f14f8c7463456ed3dae8c30081fe45f6d2ca9a9cd70f07071226918108d52833b2b35282042406c56b3b7524e6339a5ada45f6285a31c615a679448f9120015c59072f52941be93799d35d2f6e7cfe2c2907c09c98d00367166e375292a90cb4429e6bcf2ea710b665153047818d48c5af3f5b80d8fa0f46a7603f706646d5ff643a002368f894b809a1540af05b91b492eeef00fa0da811a605ba8a2b59cc70275c45368e29a0d59fd3eb1ee1c0ef77086338d3b510dab209a6dd2cac8a067ea1ba0061eafbef52b8cd3e60c65b1ed1a42c1c560c3cb508c29cfc9e6342232ed009af379d885e777aab7b6cbaf7279e0744c8e5c635b2f6eb848177447c387b1797e58d1d2363f6befa51be104b43508cfaa818ad0aaa3e6507c8efbc171ca06f4e5ee798a004911b202188ffa6379c46494e9c1037b377411913327ff872282c29e320362668069be43e8a8cd15ea4182fbaa5c7fd7afb0fff7f08bd63b18a193849628d4807c446b4619f1c2a7408b0f5100be9ca21fc38e60f1cdc697a7a7ee1df9cb3a824e50a2ece6df2e3d8dbbc6fa16f421bddd7ddd9355cfa9f7e6d05b4f3a7d13029f656ed7192b563ad7230dc9302164f33fdd80cab0164ea93034b239b64ce725b1c669e8c0c8f5e14a46c79612b6124c090fc711436793512fcd1874b3ecbfc41626ee916f8934a2e70d603f4e787291f0ea9d2a4157cb73dcce356297186bd3d686afeda3623e58af7a410192c3a61df6d11132591e6ae8d5690a73a60a5851442e32b28bf2e2448604f5090edca999722fd87247fdae367b4d149666fd258da7c82f618bc5f92401098191a6b651fe99a9512504405ad21ee42bcb8b5e69a221287278a5106ba9a00d4e9b5506848f2ff2d6b4fc5bc524e155c03af07de9755db17f38d119d3d6c8aab952fce1a63353cf14d71d8033d61536d0cef3f565f168ee4dc2e4e3c44fe77af644af24f61e5683faaf490a3f270f6789fcf50287c0c18b1f772cc4e943fba0159e9e32f39d0693b650a4e389c15ee3b3ec2370c16dc50dea986374bde29043bb23af02cf13f466cce815cb2d6eb3fbcef8c9e28e8708c970a03a1dd18540e4b2fb9b033734a13a189fba0b3cb0b690fbab4997bc9df019adc8e8b5efc8c798f3b6e4680d61d2dfc7f0bea657681917227e3a69b31ad32c1260f6ea197f7f3826dc79499b61a9b911215784aa5b54b87b5516cc32fda2f82b967f60c4f7f9558ad9b1efd40ddf13beacd99c893fbe8f91430febe9770fbb7011525f0931e95b8b8c23f069b9b0888daa661dcf9caf4a414f88b354a8db44ded6918fbe8a094c3c38f7fcd88b3f2d330e49c6918efdb3dee55b2159e3de035d8a04212368af0dbd71a0e5a61c756a352b2d441033b1fa7746dc44846fc1e41382787ab3d7ddb6c9dfcf4abb77c7d397b0459f95a052105b8032bd433ddef6832c1aa0ff6ffcdb03ac9cf74a6d32b05cd5ae8231dc89fdf77784f57299b6fa9efb1844fac74e55adbf7fa95a22957b521d2e07f5d51df41990fd326d686b72c91dc5d3648883e40791495c46a3ee2ceea0f7700fb5c8038acb2ebafd9b7f8d2c1c10f804ff227d020a63798275605d74af70d55f83b617ab31fe00fba1fabb0c218fabc58c6c8e2f447d0ff4d77d24656f158453948ef2c671fee94f43a45ecccee0cbe607b3435bd652a0d8734714cebddaa46ccf5e2142f70583a04de7a299510a5c9cefd979d089856a5a04b7ed0bccac56ff009e11723304d321b81ffae87ffc2b1c8727e7f51187059ec9da8ad09520ba9c2006e6039ef86f4a06604832cbb0c3c7ff330eb05247c4a2ffb7a6b276b1babd44bf417bfcef2953b7ef602c5e50382e20e506d26cc79eb7ed5bd3c4e29b2539b04ab22cfc12d77bafe779c21f07331df47bf703916c71715f37584a959907cd1448980556c3901f25bf4f0ca306d1c7b747d806ed947e14b916b7eb581c8b2a2005c44f4de07ef3382e573bf912e9f7d1a6979e24b0d6c7ea5015dc6e5661ccbe67ee35d36fb34deb2199ff197cd7d8d73d9dcc378cbbe4f8db97ccbc91896cffd46ba2cf669bc65333ee3bf8c7778a9a5cd57f381d48081dec409a5084ec0b330fe077305b5f94ddb978297864381f3c2d0e4dc898b806583656909f69db3a5272ce1041d1731131f9da1512b2503ad69d4fced5ac575cf2521d42ad3fe63ba3bf78325fd6b1a9d3bacb3c4ef82c06b5878b10fb521f049c49605a9ce70af64908d6c4e58b4e152414313013bdebf0b6f0a3fba2e6b7d85e080e260860c0d07895d126325a4dfe44323dbeccbd02205a2d55fb27629dee6bfcbafec543e3034011406d11dcfa14aabb69209ed0452f8be7a7545b80fe303c5982ced80c3e0530eb58e00a0a34c983d568a8dd52b583db09b681bba187cf03bd0ccfad78cab6816af21727bb50bf80286f4402bd258a074bd44a2e183f65367caeb9a69b916696f2abfc2cf6e33b8cb874622ea6e3c0624fd74c5886e738a4a331d243b4a72bfb3eb924ab57dd10a54701fa853650fb593e1c499a0fc9fe19e17e84c316bb18ffa8b4575f8c154867a40655f001d17a2ebb970ee2302238a55685fd27844c1844a8adf54cd5053a6f48107cc28ae603530ac6f768bef4b1721402c597f8120e4ce4a52f18f02a740950ee02781b4b6c9ca6f120bcb1cb9d3018fa13c5467d900b16625191e439ac363f7a1129bf747661f0fb1e1affe4d98761b0da5a089d6e754d8964c676cfada775d2901578276b6bc7172c5c1159f6b5c8e31711873168e1348b09b63737c3ea5f6619fea137da64ff9043ee7d33ea9cffa4465aa47490b0a1ea0311ea21b32bd3e309c3475ab0893e8bcc28b66c25acc19191f056141f89b5406c0fff4a37f446056d2aefbc28c5e2dc7b342b5862329caefd27910fb7defae143420643f912703c146a7edd94e3d211b988a696d67854419688a642015a7b627118a99cacc3f206d8238bc63172afe3473d70ffa6dcc5c1d627aaa1b4206c9a157105de3c2ea25c4cd9ab9facac7f9014d99983d8e457e0fe35bf6ff1a2fcbde4f291aaf884f7217fa6e58666d2f756262126c5e84835e2ce6bd1590986ffd2000a498dccfdf214a8e7417fc843145bc11f169182062fb7569177288c255fe79fd822a290ddffc632da249ad80e8b92c20a865835d40f2109bff644db32eb8ef7a7e4eb520656bd22a8136df2c9e1c860cb405f81f487e6f88270e496107a7a513cfbe839066e75b482c7d99eed80c8b7dd92314be04e20c2d14cd2a54c1b7aec353f278e695a2cdc6d2dfc5bfcb0c74f00972766e5910f9be848b6c6885efb096f4a62d1d75ff8469dd4df3216aad6ed615e8005d1f97bd08211df8749110b4f245913f2ac234eff7a67d04d87dfdd8a9f8580703ed5373e17762b0f6174b6824670fa483afae75dba2af3e8f08ac087f2a6cd56f6d2ba7d493241b1187ca6975427c1eca8d6300ca89a43126e67292c462fd189f045e7ff043ddfa0e24442310a3b007dcfa9621666abc64f8380e0d52a152334e3c2ba66ae4e5ba91513c259a3f71db40a0b4331b1765908d066efd142e3610416629cc02f73f0184a60d13ca38bcd11cf58814619380eb85d64a1a82dbab43a4aba5f4caf68895a27fc8649cd329a5c909294173356adc6064298c1fa75b0ed13f435433f2d22484a5d1b7967b08aecab85dd9573950639ba234a15ce1a96f104cf23ba4c16de26a6c37e0e0e5d6e0365cd97d5fc0bdc53dbe07734508beec860d89415aae53093a260b61cc12bbd5a4e304d6b93999d9c110c1ad97728b98a9c771993026befae8eacae65923d1b2087ef7229201f91f3607e909f9d036964fdb53fc4e1ca7ca1ea2a7ec8e909818312515d81b69aa18d6a1054d909005704027fb7417b5061e688aafd02535a83404828ab5bc495b024eecb86a8b029b6f52b0d9af490a4b130eacf5c93506cfc4228a84836994a602e0bf04c0ce04bdef26572326600ef11b85c7b313cb5b6971564f18077b5ab9624f02aa8d9952c21eb457ddac806e334c4e26396748d31c45d2a01c503c04d26f80219c005fd92278ed9636e0a6ba97c66c48c5b15501e1848bf100cce698ea198282e733233ac329a6a59a0c743a4beacfacbd562ddaa36f09e5c3cd14cf955c0ecaaf6cd8d66fe05c9140c448610c24ca6cc7d66bdd882cd02edba61c26c03f12f869f294f5ad4f6dbae8d05049c006f3aeb44183fa4a382d027025dbea1abe76000461f1cd1485eb60710fe2477c611bbd1468850e752d4972a3459ffe1bc3795b63a5df9d9c56a5eb1fa2c3d328756afec6061b27be21cd93861b334e1718206531bac991368ea324e76f46ffe00c8ff5a40b76c048796947ea13c0d385196df061b86c631cddae4f85231b2f48f61f08467d8ccf8b0b3064519d55015a0e2081bfb6a03ba86328fe5efc11a8e80f024df30f75313be96ffbe85e86d19a96d03f123876952343bf81472c7da0c1fcecb33fc7f0721b8fc7b2843858e738dc020786ee4e246c09db51dc418825614a43b10fb71941c7cb7711c12fae5f033077164ff2825911511e65f39559c3b314d22736b19a8eb3fad77cb6a2d942cefcd787ed89546b826befdf2ab0124b0b56df0a6a2aae2f30a5a002655fedb819bd6bb25849ac42e292d5ad2166efd15b6653eaee84dd2e3ec19c84ecdd1836e5e460141be86d7a8559d5b4cc576c3062469b0e6193b35cd3898e12834156886d2180e9589ca66aaea0524912ff46a66153639969b84ddbaefefa0bdab89172ef74279847b7c83598951eda374219c07f292912ab2a02a2b2ab7103fc0497a34234552bba8b87cc30890ad66ff3c7f7ee51d45010c422944da7e2876a00083603730d9512b759576363c0e4b34539351310a584251fdbd0421d13dc7b5239e0fa17d9fbce749a2098bbeb72fbddaeac1a629ed616ac89d056d9cdd883dcb6fa9bd904aad35dde03b0e8383f448ee9075759c6c5e19da1447931e08a3b33a111390eced59c493e724ca3eb23ae2b5d80bae346953346be183851c0f1871cea4654059991dd225650d7bd199fdf44470027e05dff784fd71fdce7fe5f3e3ef81b3e1f2452f15453f3302e8f536f609341c85c243c2cf4954ba11a4148b87d42726196e483881e1cd653852aaee855405187c3cc7918c9738cef5983a7dfe19e9093be0b4b01a5bda19584c1a0da3068c0e8656f44b05271e2f7dd2f93e89613a2f55e94675f015c62f5d817008108f793f62df5954319d23e2e9e404e11c74fb22d4ed3381af632bdac59c11b238cf11fff038c967aeb54a5d11af76a47d55c6431a2cf18463428594e0536587a8b7e45f8e106f321d35b28824383997cb98d940c6cff770bf53341da8f197644a8beda0a5140048ac6859d0ad4c19bf88fe19a8b1adf29c40c7123b6e91db3d6a75edd72a10b853e8f1866f2af62b70cc1218681d67d3c6235a574e6513a35d8d0d9b49f092583fd4de139ef76c4bb75f31cfb92d38b74384bb1c4fb2b59451720663c0060599d5d67d1175f68b739a55060518beb388944305a9ae84d750812f2e247759b2c8d63b85258190ef03007ee01a077ca6c7320b96d487a50ab36d3d8511a657bc8b37fdcf161ae4efef3216e713d0d9399db386141a2a512ee4e598046a07a1c9ccd5e4a81b8be8200753988700b008443976ba388733af86454d87fbde1d2606198ac3b67319174f5b7bcb3a08471b1efff8a3ceab93bfbb236bd465138ea8e3b3677cef60aab63dd2ccad6c3978da2953a320f024d9579390c2010ea0f1b560aa6ae60cff3436ef8e4c9c5f29a619ccda13cfd698fecfe8265aa5e5d173b0cf7263c1b7b844e424f5bf8d498e17ace98ad93ffb4ac600b89818214366b7abbc588d74a58b9e820be2a66d77753a5c43ded03d4a65cddd067b65984bc014e2143031d8195a403c4b558f10163102adbbaf09d3748ef6f984b3c23e51eb60b57785b2d740d0ee52b8391025ddd44621f5fe2639f4a6434c6b59a9406b15c0f74bd2494b403bbdb6645a368fc290fe14394a7933aa128686f9113aca8166c01422bf9846951c2916f86e1eb4694074012360797b331c423df3453fa47142baf359ae25e27ec38cab499642fe052c49f1a9362fa1091d7062fa811bdbdbd8805c4a8246aeaa80c06d117bcea061d4fd193824c0efc066d02d99d3f847e4c55d59567c5dd4381ab2cbdae0c00c07c7733660fbb7da06a7d0111d07f1fbd848be98a4c5e6a2e4247ba372747bb87cceb6e3526613f5faa04d8f67e70e7d636e3eeaeaea275335d135f5e6fb900d7f24a766e275e635105515224d66ad83316f9c8a4d8d238b1f5c228c33b8ca09fb5bcaa868d62091301a05dedd90519859e510eaa91be526b8b448ae0641c638dd413d700ae1d7b29a72043421bfc7d264eb44acba21b3b2c139ef89dc28398d96555ce0bb734a54080da1101325c471a6d3e9b1f345bc3e254a80ee0b97e37bfd1460489a6b04396f04666365773e01068564c961cc8439142df451a6149547ff5196e79adb072e9823d847cdf077932bd3aa9eab49f7633d6bab7954bd58204da5e27a49d20b624cc943a4fa05ad493bd7646bb171ddfb7b2a2dba6766ddae9fa476857f604276dc282ed0ef2ed2353c1859aa5b3eeb7660322d994a722b144869d4501f4ab30083bb59a8e892e515b08a45605aa0eaba1521040ae461dbf887cb39883f91416f7b7292485a04555ff3b968c9b529aee67b33658e7ad91bfa564dc226924696467db2dd34d3ccc3ef2fb94fc3f3ed6aca8bdce7da8d0deca672c4606744cc1d0dde04801c9092c0ac809757069820b105c3a2e22240146125992c0924401224046046c045070f236dc121fe5f99227ce09e9e544da8caca47c383f7179ba8f5727ed4b1fab34767fe6448a14b7f9544f3fead959154b9ed3be664cbff9431306c52b595af68fddf781c0100478bafb0161881e30c503560ff0961c08d24cc50158440ed0c1010740020e24bc20b1457232ee7a1f54a98fe438e9f93aed572e5baef26c57b8367d728a667bf0f793c51f4c84668748acd2fb61acdaafaa62415bc0e846e1d3c915a5666ff0847dd01120101db18586b94a85016e30200aaf4e7b412ba3cd5e9667364f236c60841546e0608407458029224b112922f610115101226c20c20084488e73107c6fce4a1cf7a549abd34b2e977826c22e8539084ea11fce7148388fe7cde9743a39be937e2a49f291739c9fb2ad20587bdc8986a8221ae2c90260b080072c00ca0246d0f2012d5a24d789b8e4c4e60567719c934c9d887dac130cc379ddc336bb6847539df553b905e75f391babf5c4c7a17bff2d2d4814c0474b0540a0a5375f2ff916a7a300a2627622ee400318e579f42504979410ac996d09814277cb20f8e8ee20c27477105a8260757eccc395da9ced70258851771046ba3b4b1852967066c76ec49385004090d1dd97d6c86019082a80e8e96effe1901fbe744bef5259fe3eebd5e9392ac7359d7bb4fb21ec1fa674aa3eb6321cdcf29e8a0dcaf96c833c9547bb4ac5ee8c5c46d9c8337aed4cd7c6cc97d5c0645b6b5c24d8aad59e74cd4877e895aecc886861c24aeb4263d19ad815ed3195213ae4fd6bc3da9c894e883ba28c23674094833211dc05be828ddc302df3c4620e7ee2429a453b5a192df45269ec7c4633a8aa368b9dcdb6ca0f9cb21f3bb73e547b49106181038b115872c05280f004a113e18d3dd34dc28eb3c9b91f9ab2f14bb14a3d11847975c6ea04c319c5d43f951459cef6d85275a346517f2a0a21c42c88e34bfc26c539f668772d376b6266846816ce56005b008ad1248c83e34bbc5af76807068152c80fa12e84b83489341a8d13cf07aded3c554af9c0870f21f0010b1fbaf8e012f98000ca0735d385f27493582c59be14046dc6de7f95385397e121b3802c48e62466a64937a31f12a60f0a5d4b2b4dc7314e147be133e40b236b73e6faf9017ad9784865b5e953e9fd42f8325ecb9f3c403c30bc2fddfda078393749d0f47debfec3aa8589d793e5fc1786a95746044301ac03302360413010ba3a3a087437cc40261cb308d17cd24df2f125ee13b3a02f719f6b4dce999cb332da0dad978df9cca35de74f7321d8ec3ce6258f764ead0f7eedf779d21bda1b863ef326f79c632aab7bcf55c149a0bb456811778488bb11711cbcc810bdaa78bde8d5a4bb4923b7823dda3d38f21b37b993acf812bfb1329a7bb4f3e88d9f386cc3fb58fc3c7aad8f168f371fb4a8873c443dd4d143047a78d28309b25aff6a3d309cd1f93c1c77bf1b41b1d6546dfa481c89a78fc4cea42543eabaefe5b8ac0fab14bf10bd923496ae1df9ac96e6bc475bb16a6f15394e9ac7aabdb46c87b04fefbdbff8a9f43ed277e3f41939ca14e428933fd88936c771162d94ceef08baf4a8d795b0f73e82f4867854e355d15e4c459b7229dff368e75030ccbffb75e2b80ca9ec61d5c21c4cb96479f326db950fcbae3ccb52ddf7e84d77dfae3ad0810b9a34b1e9f0c7ea83e094c13c804138fb8fd6de0311788fc5a1cc3e677c2dcda148916223dfdeffe103052ce9fea0bdf76c2b2a8a57a9900c26daa04aa778f4a63be8c00f548e74cb19755c938728987f8a8b4caf5c61a46b8b5db9381714d9e2a2f56a9d8062009404d0490464e4b395ba0ccf8c9d7a7ead93ec9d3ec2359ea3f2ef5a3884c1a113e120452c43badb8616b13ec0128234c21e7d8d2f743a614e72249bd1cfccc2becb5872787c210e8f5a727ca125ce79aa0f47d7f8533821ee552de7387f4c06bbf3b18f7756dad1f085c617c235ffb88a4b8fcaae5505a5ec6afc291e1e7f8a5d71e0428e77fb8cddd24de3cdee9f8b58a0bb4805babb8322527453e0e9cddd45a0e82ef24477912edd459ce82ed2448b7abe887aa228c2447791253ae82213e8ee16f55869491a7dcf911cd5943c5aa6eece144c4553580d4e589da229479878fff7bba1cc0d1f70d5deab37b0a09a43f500950caa23ddfd5f53a1e8221e2c229e134f09dd2db9da7b221bb8d8f036dcb0f38768678f9d28ba772afd1fecfd4cd5d6f912e9cca11346e708918e8f28c7e2927fd44f1ce72692e9efe895ad05c257ec6674ac1ef8b21d51ce037264a21c118e19221c287070ba5b621a5a93ad7e729334fd1d414c6d8e94b952d9aeb25de5fa75ceeeb33a109c134437b56e59bea9a1adc56ef18d072932ba25c9fb210aa69048ed744bd21005472914aa86224435b46a685102b248409504348a0b54901443445234d02db3b5d7c7aefe481094c5a8c44efbfaf232fe8eb34efb8aad95c1ea77b14a63b1097e9ed79b346962634d3f13412b8b51997ff793e3beb33e633ee6c7a2575a9b3e2956ce2a056483bc36497e9c840452189dd96a610f7a75563a921fab3449f21238f2d3e7c73eb6dcb6ac759170e4a60b7efa589cac1fa23da82879be3cd46a6543770b22a2010c0d4bd05044e32b69b8c24486275fba5b067c25936a297e427a1200af52212f5918956e223608a0b8d26c9dd2d95a20da0402e795a21954f04af195e03c11e1a1453180931bc13afdb3a27f9e319af10f552adaf18a76f410420841049bb91042084184fbe3041d9c221866501ffc4ac1aa1a6133f63dd8fbd3ebb5fa51b58074825e3a36a4807e5cadd7ebd45d44025cbadb02222783889cc8f172e2019193251a09f56b339eb04ab31e0add3d52d227f4d022271d8c2ff40227cc76165628d111b011ea18a48db43181f374224202a9454d5410562a20be92a6aa6911933cbadba39305fed0f784d6f5dd2b63953209c5f766b0daccf8f1952fef69a5590fb41656eddfd7f7baaffcf8951f0b590bbe62955a7c6d6dce1e56a785bd32b6e18b6665f8656b7de5c7b2ec51daeb653059ce8ff1cb82a26767afef0ebdc609d6e6ec15cec4d7ab366795fe0f1463fb0a5fafda9cbdc299f8ca8f5f60ceaf58a5d90ee5c723ec85f10cc7ae7bc1ea88e72c3fae31d37e02fa0102d271244890d45021aa99a2668ba8464bbfeebf98f8c97b265804c32be257495473c5a54891d24d44881a23f73e91dadd4a5ae442095c00c3052faf4a5f3358ed749ac16a22174017a60b51fa054e3f95fc54e9bffe8ae1b52db8d182979699d2be5e51d482ace5086698a885510b46442cdcd13da63ccf4b791ece5f91256221ec160b1e7b900ed13b61f8278e48c919571226d787fd2d81a012991429a941a4c4c311253103d7548a9ac1463c9d5c323c794070e220e9800889456212391eeec5552237d22d39f0f1bce1a6ac364fcc855486aba514662748b9efaf98c5cfdf845758c00a36a2153a68f9511f3b0b82a2544c10611b8017fe5dffce453b72afcfbe94f80bce71bec4390ebfd0004a5b09876c25a4b195d0c55602d82d93244992c4821674d7cf0f904e6f347b6c341ca0b1344fba5b7ed664aa2e9c4d8a6debb6249bc80e51053691119b282545189e53848d1c571a6f4698bda183d255c55f70972f71d87495db0c9beecdcee78b2348a51c276d04a7b492f2399d66b011efcfc7f571a633d8888ee96c362587f1d31d973edeb7ab56b6ab6c57decf1b222f4c49e3c35e7d7a77803611c6fc26c297ba8950448bd0a465fed133dd422833532178e99ecd97b94208b7109e74b38ccc61abeb3322da40f8a34bde8390c40602d72d39aea5e3a372b90ed08f8faf7e3c47a7a72785e33a372d15cf08cade40e060fb6004db07446c1ff4c8cf3e786dbe1fce97c15c06ab0f72fea9360fe4d83c3862f30001d582f6e6179a7486e39ce1b14e6f5a3094fdb0ca7695a58f6e12ca090ce2cfe61572ec5d0ba3b9d24ac1efb3a758a5b14ab722bf15e9166335bd7130a6370ea2e8ee4ee1d07eb571f0a4e5b5ee04a7372266e846a48b5d11a961eb33537a6b2f9396da9adb7ad48790e93cd75428ee3ac48be81019edbf439eb4c4a4bf7636f2b14e43ce1862869c79a2a2140202212120240b4232212b0c728241881824ca2047ba256792f541534d071dea0f084e5fe2add10fc771b464a9d0cf8f4bce86f311a45e52dda0e7064b6e40820d3c6003236cd044da113455eb25416e20c815825040101e041905628340be049243202e0402c81840a400440648097f8cf107157fb46a60480dfaa8c11435a8520302f84186bfb0e43f0afac924cedcc6c64f3f4c546e92a456cc82a31f6ee49f75c1c119861326bd552ad51f374913959668c791535b55272ebfa89b38cc9538cec64ddccce347fd50a10f1af491823e20d0074ac4471e2d7174d061f4231f9c43144882736886f492468e5f2615ceb48aa4d1e8b34b3c06cee574ecb22bdaef58ebc24fafad2abba2d91e6b5d556ad3c76b10dc60a51b952bb5e1cb68d7a2706dfac428ae74ce6450c31e7cf41e6284f0dca3d6dd7b5849ed319a578f32dd9daf1e60baf508bb537ac83cccd039b3430fd489ad3cc63a5de251a6f11083c797ff1d3cb6c8ba1b0f9e6e3c8c786ec64c9b1923cd8431c3a55d96325383193773479996774021affd4418cca2469d8851a828357b83ea441c032f062ac460043bf2b0c3047670c08e1eec28810302f2255e63c597b895fcad8ff6352ce56fc14008062f18c05087993a26504768f240eb1c8b35fa21d1be8e1cd7e04ab9dafd8dc5a68f15d391023ab2d081a2830597989a438c39642dc13265c43254ca74f0022d5e70e5747271336eccb6de0f72c9715ee55c70870bc2b4cc51b9a0002de0a3bbe510f87886e76dc19516004024072172a8400e2d46d0542d16b3245d3b720914072158c461250e2870c4008e0ac071e1c8e96eca0367bfaadae1e4a128cb3973d2bef1c71b3178238937bc6ece3fdb89587622f6ff38cec74ec464c420a30519069009824c0b6ee4e1461426ef4e19d7e25abec4bdbf7f670a9cb8e6ce0771dca0c10d16dab8a38d10b4e1431b2c74cbeeff63c11616c05840031b3760438e6ece4d775ecf4bad408f15845941162b1842b40205ac008715e8acc1c71a195883893578d6b85143066a98d192f49e8599382b24efbd91896485e338eeff93a451382fad8a9234ca1f93a4113e996c167d98e1ff17fbf951ff2fa7a6abe1850817a793ab137177112f1eabb4549ad5a68fcb31e7bfe1b4f987896ae53247e5753abe1fca9ba3f21ad8fc3a114b18c5f3660280e3dc6669670e5258152d0c9cdfe1e931dae18b4b94a6bce29a9fcd9aa4137112d0743f143165420b1d3ee5a7d27c3f4c75622bdb95f7bfb31a856034b7ea0f511b3e763b2f7f34e7da9d464335826e2cdaaff65e1d11079aedf93c733c6b6d78b09b1e9dacff1d9497485ec2a828f6ab2afb559aaa4d1f5c9b3ed5d28ced575540ddd33c140f4d9c389427e20edf2b8c85209db3cf282f91669e395e9a797a9f2dbde08c3d38f3cc019fee9cc08c336690e97e583523ccca0c2dddb23383d59d9b5102949f4dd8df98804bf77f26b02b1374778b4a20477797c0012508bb5b7ac6a24ba64ac06a598251b7c435659ce996658c916510e1d4557baf8c26e3036464e996938643c60924c82997233033022e23a041047b888009114811d38798294462761013050bc16808ab1fa320f5fc452f4912af76ac730449ddc474ce32add1ec2c147d04639576d607af8a34973f44f3b59852a712823442904508b474b73c713a63dc314619636819e38e914277cf14089000410a042331f210430d31821043d65dfaff706c5619e7265952b9182398399d5cdcf4301c10462a8c145a56f14bd9ebd7e62902030c18428031e58b425a9e388fbe3837c1fea3f687702af5f1dabc92ab74fa7c681d4fd97fb1e995663a695266b1f331747c81de03a90c074f1e41bee8dcfd7f5eb5ddcdb52f7aaf3c5f59b4e3b579b26eb0f8fabf5f07bc65e7c5182fc0bc17b56ee9857777efbd77a639e0a59b031c079e7477e354177c48521763641716e882852d78b3684b59ecba68b20133366fa0cb68035624c91bf90662e8ee06a307982ee198a59d8191cdc034693002683969de7b95c21ee8c6fb5ca94f152fcff081b0edc958ccf19e66bdaaa301ae6f3430ea961c1765b800d3dd5c68e9961c17353817475a5a9bb760b205989b2d72ca03edfffd5eb4afa7934b0b3fb498420b1f2d485a8c90051ff58a321848413a1ff4af3272dbc40604e77f74d2b2e892458fc4b25cedcc61a85531dd3a2998ca6284c598ee96250ec3664d078b2b5820c9001addf231154792a3e34ae1e800b17472f0c4d462104a068ec8c095965cb6f6728ee9fd02c617ef8be88a30ae98c01530d115ad2b38b0220b2b5a1828040362b478f368bacd4e1a95f0943908729e4d2d2961f9bdf4b139d619fe0d4b423e6fe7a53c65f9f56037fdd25c1f035b3070a5a5ebe707483eac9b54aae0a30a0f5451812a78a412e9a79fd1dc020d344899100f3bfc6cb6a838830a0b50b103150198e20d792dc795a6ec3bc7b4e6de1d8eab4d1f59412bab4d9f5a2dc5ef15c9572b34343f9f37c77d6673b6372ec5fcb171ceb08b7654b96cd91cf7faa13d09617abdd26c9ea21d795c7affe2fc3f7bff07fac20882f3ef0b487e807474f0558ac7e5403aae940e900dae7323eb8736fc172a320712cf92c5bd772928cf92c549234ce5fffd5ce2d95cb914fa5b9a2d508e60b59c8bd8e65c39fcf8fbec7bf3feecc6392e07e738ce837047a1669e392c2fa1a2449951592b9c3e52dcdd8170f7076938b3305b398ed371259ef37b12675a451751a04604851cdd2d6b6afce4d157097f7fbdbb6d8ba078f9dfc462776bc9de5ca9e88939badb6f80c64c3d2a62a13f4eaf7e58d3d1999f833dd0f2e0b14e1f1d787ae89e79e6782a8c8560b64708667be6cd359dd3e90f226c74a981081a5d4660e5e0c418e9d1ae8a135c38c0c109568e4ad4040c9a6802e4e1ca0e57bca69ad89818434896bd173195a0c8048b32d1b0259e5882d5dd3256e9b5381ee6444bf804ca4c5a6a0236a8284a9c40093052022990c004441290c205102e01b89bfed9fbd9e2107cd9d8e16e22165842688926233ce44e848923580831819efe6c8346f04e1d6b5d78acd3a787a7bb79e8232c2ca899cd75ca58afa16d024e26d081127d48d2c84923cff2bbd9cd3bc3ee224d8e787184179e124b74b71230256c50228a12a56ee9253cbe908736bb7b4d5461013e9c077ce54b024de0941318726876853d7a83b10e1e7f8a87bdf7bc9475618c73ffbfd9c2deffaaaaec5755a9ef06650bb6aeddb94f05c72aade265e1c9ba3fbb3c21156b81fe9bb852c1e34ff94bf3035917c64f6b3fa397952d2bd77e956bbf82e1dcb0329e3d9e97ab686bd327e3a7e09d3af8afc549619bc5149e197f3f3ff86578f278aa7927ebff52e9c1189c58e71fe3f1a7b4649956a9a205cab55fe11c8cbf7e9e3d301beab0f053fca00884c79f821fd30944fbd58321bd2eeb52e1c99331edc119d39ecf36e81b62650bb654b55fd5ef01c1948ae504062ad6a5338359c9f567d6e77472d16c456284040a0d10d380dc80043480c9962d586ca1b2a586ee965c7efcba0f7aa5a713cde1fcb32397b091574bbd3a6ddc44aa3f78a4e2fc3b6eecba29c353167a691c41a61ba3a2a07144041a7bfe5d695e31e5d7ee38d8515c5fe85a1a0d5b99c46238fd851726ed6f1210a284f07409e1998de0d2dd75c28c08db0856771167bafb22bcf4f4eac7685fff7a1145542a449ce9ee861121a6674889e8d2445831552b122143f75c09e1e9420d61c6105e86a8756a082bdd728851778f2016ed6cac0b00a4f1cceedd677126aef39a5c7fc94c9cd107bb19c390e9a68a310c39cae4300c09e139678fcb6a5de5194f5655e1d855095da48f1aace86ed4cfe68aa24e2718fdd95c7de8d1170ae58af26028baa2c03e2808979ca71ab92c66647140a6b3d9ff586b0308a6b2f0c8f185565948dd2a208a00a20362861fcafcb046733a4c74a64c19fd702fc9b94e7df035720e8f3f859ba2e34b7cca0975338e32668ac150966b9f72c9a15c513c15878a723f0ce7adc271fed9e9f7f397e25ab9f62b0ea4f39b13e3877df539a5e7d1d9083a08ceef692921ebb8c63d21389863144310339480a115864ee8f6d3c8fde43cf86907262626b22ca6ea832ffce24189e02594979e88282f3d1185e657c1afe3a9ee3f6b057ee6babb57992727e9d7d0df101382c574f7165c2d3672c974775f2fd96fea8ebab198e90d8b19d2fb98a7b06ce9ce292c1c9651876760bf85645261975087fc2defbd6c57764bd7afd65ab1ab7ac66e954c6ff54b0dfb6b0d5deb084fd9cc4c63bacdcce8eef7e66cd6a5bb61332ddd3d63cd9a7477c72ac5332360990d0cb38135d00a78a4a577edf74d9750194261cb92f7140bf174bf504d7777100a85b29705821367a36dd02fd4b551106476c82220c341a642ac8e9803624fba2537e71077ed4e0832049bdd730cd2f999467004bf2f1f958fc9c3f1497c942128b4e4fddff78ef074f038807501e30136c2d6ddd149a0cb9d0a538fd9c436793ccfb6565a835f9673155fe1fccbb93319f998a9ad26f7d35f3ccae1bcd83829389e963093bfc67869e0e5bde4abbb9bc3970b22058d826cfe20ef837a1043e23b1fc4e961d6030d3c0cc2c317c9916c707e36318cd2b2f350802b28d8ae88b962afd8ec10c8b6831c5b768861dba1051dd8e896a4eb6eaa73caf2c83952f85d4d8d205792e129c33456a957eda792de0f3d3875c0b2e960ca410639886959c2adee0e406f3954d972b0b1f2022b18b062849518ba9b23d978a6bfa1ad927626d30fd52a68545162ab724495203aa408926d413c41456a7aa322474bce237123c7f531950550b9814a0aae31ddd25a110b9412471afd385f98da20570fae17b6561e2d32cdbd773aa15c514e2797e2211772402600ba40326c4034388800872d383861c9c1da8235c482c212fd0cf253c5f643c4cfea47002b3dd05861b1adaed8565bba5be2299baeafc6e8b59fa5bdf0c20f8176a8521fe7ac66c8de1fb226d3c9abf353556e82554a5c53332862935feb25d3e95349516f2b29dbca880f191f928d2bf9fef69ce939a347899e1e2553d69892659b024e51e1863cb61bbc9072d2efc4716ecadc73ee92f3e16ee8b9e1007ba8c868f9592097655aadbbbcbf34ccae6ab2f1ccc193828d270c4f8ca7890d6f6c3658d12dabb83f063a55919c17ab9e05ede72e49e57360f41fcf07bd4e18787fc87a9d9fc5947f9f05adc591a66be9dc91a68ce7e7b3ce58a55e925fe54cb44112a433d777fcf9e6affe5dacd2cf4afcd9f6486f82933482cdaa2367b5d77abdb876e07cd2c839ee63b3bb33e613a45f6b87a5f26b3d9c899eaf7e5a3738e65c3a258d26cdbd6b6138b49705e3dce4d73a141d3cabb8329e3d9c9bfc947f469b2f9b238873385e58c90e81600a3fa1858efb42757aed3d9d9d54ad5335391d9742b3aba2d7f9340bce2934ff9bd84bffcd16b6988a4bfff9b9c54e1ad16c4fac528ca9cfdfd8950c4f1ebbf2dee60f8a559ae9acf2d5aeae5d61af8a3b76a5aa76e57d1852f15e069b0f44b33d19530e3e48800a9d455baf98f1382bfe718e20385d2308cefcd90679f577ea8ffdc0996938611e930e4765c34f0feab30d1aa170b5b85a8a838a559a93617f690efe6c836ad3275669b6414230dbf3e31c67cd140c5bde9d5eb543927bbd38b719366192d4f252d028d3d9ccc2feb26478ca783edba1bf2c3033fcd1db0c6bc86d862e2ed49a41d633f46c338cda4f251fc5ee74c2b97e8d558aa9cc00e4e37367b34d0618b4f7322c860ee4e39346163264e9cf62a655ba9b059b0c2fc86044fac991544bff2686337ec2c9e24f55ed00057d376f887431845b0c3bf4bdaf170c62361836189edc1fb2d7f3944181e1484b2766743bf1d2727322eb6e127a73b2729282cabb3f6441d002e57ac558a59bcd173632f9b26c53436f362834d9a355f4d5644b1304302984c9164c74605292b37fef5fc8e4dd1d8eab5edd640c3609856475cba73e45d6662ae3bd09c9564ac15612bb1b84de4ab5845332c0b6448f255e5a8e935602a7ffcc03c5927c494b292e35fa7153e75ac26d4b6478e105d241e97dd4592fcbb85ef146d62b769825b1ff10f5daf4aabd9142b0d9a5fcbd5a73775c8e309b71b6ab92cf0a63e7b95efbcda83f986baa89f5aa7117c6b8c0c58527dd021f3d2d78d12dbdad851a7a48a70514ba657d217b3bc77463c14cb6950530b5396321ecee66a18992322f7329f1925262a5fb679b9291bdff439232ed3db65b122f8d3feb38894cf4fc491c89993a6148b2e851ccd8821b920178199b7771968bb0ad304692fcbbff96cb4eb5ad30c4b6c292ed00650e00c57600d6014a90a21dddc7cefb12fe6bbd3f8da095d192a8b0840a3d9b0a2cf496c217296049c10006b8c300670c6100ba190077330b4b92c4e756002e5b015c5b01986c04b86323801504e808308224914612a4f3abd639ce813614ac6c2878b09d30c809569cc0da4e706133818dcd042bba1b87de4c081e258d63f7e1ccc24a392a532762efaf7f873d7ae392f443e014b3380a27787fc8ced914edd799417146b105c3f7464e93421f297ca149c1459342025a7a6f39ff8e8e60b5ae6cc1d67d16ce166ce1cfba1229ce31718e7399e5b437738e2994268e69d8f256939ab0890dc9d48978e4349d9cc4ab496234574b4bf62fcbaec41f29b6e0a25b040274f7d6cd4102da4b0950562768e916cd09329a138ecc11aca2ad31a1ccd39810c6042e3426d098902447e5a00d4928afd229137b309d570946d0947085a60404d0d0044243c346d3d06c34db984d8a6dd26c354cdb5589556ac2ae9f9c5c298d88494dd3888cd01c2983e64812475e344748a011400b680440021a015421001d680440a209001fddeeeef5f59c9be4ec4ecf504823d28814ab23479ddc439d3eebbd38f9fa6a572fecfac9b13401b84213809d00884043c219249080041f4830d18c5007cd082a18618866041aba1b1545725ead9bfe86126731acd42b758c8a22b389f3799ff3d4a95acae970f8f3c42a97a51afdfeb2a4cd39aa1236fd655198e8dfb9cf44bbc2938766c12f5b5610167e74bf5ef3e6dad388f041081da00941d62d71cdbc5962b1d24ca309218ae46107cea3fd8ac6c8194b63240d4963a4a72506a7632f792a10c4a101e1053420904103c2100d082dd07c2047b7ac13068a9f8be68321683e18d90cd60f432e8bf6c565d8d76ab178c38f1c3bb7d98274d25adf0b4ddf61fa42fef1057fd8fcbcc7a4318723c777eeb8c414c4a47184eb4fb6ab79270b0922e3912c9c74b791a6e1c0868608cdf1140d112e4d43a4266988a866302ba7938d52b33763a6b019e2d84dcd3b59340d029a96d1f4d8d98fe3e1bc4e3f84cc215f0ea975f721a536e48eeecea13743226088ac5b7292fb1ffe8672de696a424477cf3b59a158e78338b97aef7d2167ba9030dddd93cb5688acbb0b79424899eec671d09910224612a2a509a92147b511e2ddf3ce709030dd128bd586b4ce99cfec1d64102b3d88ad2f73ddc0109563fa9e857916e7750302d8a08ecd0642d8408633809cc1e2cc0f67a2744bce6bca9938e726c9b94990320429424a102c09d2d3dd32903f02b92210afe5064813804000101d4064d8fe70e38f33b63f84b63f46a8c11735582247c5b9122512ffef30c14a94c81c15931b9738e54a94c81615971c13dad71a58f1230e3f18e00702fa28d307127d38e1c30f3ec4a0b412a9667c594e92c4c159edec7e36c5aa05bd4e18f6f1da3c4be19c39ee7229678a39d9e203870685d0400534e872678eca9b34696263ea44ec778e2a9f77b2aef44683146670831984a1d6028593e6b9cdd33feb0a5d2ec31656c5eb367b1c4996522397ded754b1f33c0b9bd8fbcfc9b65abb7acfe28493d6cab6d64ee28e2dec57bb39a0a9e3093d6ca0c718cf16ecd2ad47a7c71189f330930798ee967984328f267dade771a4f178b9f0f8c04c986ec97123783a99d172ad9926324f2236dca14677fbbc339c7e9f753f9438e3391d67312561c7996e3b5860c707a6bb7bd28259922ec53eef64ad1e6cd5a6cf054c6374df4a63dfbd50b3c3b95a1cfcb4fee0fb42b059a960dca2a3b6d1c1a203853b52decfc1859bc34af71c27486fba7dc1152fa02fa871010c5c00021700e182d3e682520bcc58d102af054a5a600039c8c8e1841c9c1c328e3de2d0228e1a0702e000048e312dbf5a771d4c65385f262f75afce2a0e470a6fd0e00d2e84de18bdf19121c10d3cdcd8c20d1fdce87143006e74d086196d7820b7b16a63041698d1dd5e6947bae0250ed312c7dd894dd7b2c0002c38c2061a6c20c1c68c0db9023e5680c689f36bd728640d35d610625b63688d19d638a2460cd4a0428d2d6aeca8e1c19834c62431a6966b1f942489cd3c70dc0e930edd49057c2f5d173615c4a1822854b0830a6648c38f3458b0441a39a48142b7bb80298ed7b72baf521c9982560a5c48810968b08186043ce80d8d07a0c1838608679839638bed0c2f67c0ce98a15b8e9c9b4c1214bf2449dc665a53feb29c2489d0b534d67f7447cadaf4b1d77ea0381b715c7ab62bfc148a23ac23dd1d6c0ce7cc7b338e74bb7bf3062542c94ba76a796aef8d37432c703ed0e9d4dd47a1807278a244817d500794c3732dceca4b3c51fe5a9cffbb732dceb5df0b63cf9b3ff3cc61618c7acfe2bc6761b4af18cb4420a1485ec2f95bde87f3c25a9ec50992e1297b554be7cb669edefdf0666befebaf88e7fd211b7aaa97fdaaea65f37c65d13e88fa6b7144fb7a85a20c4f1e184f946bafc5a8261dee399d4e27d80f65da657a831a3345f144c9310c9d4e42b00d74b7506f62c694f044b7f742f36932481bd9c484ab15c3851824a4f7fea18561afd4b33fb8135b33cf1c9ca7351c5217c63af97d5c40df0ffe7efe07da1a27f84018e3fa17e7fae1ecf2a430fe1e488627cf78f39ec5c1d7ee00e1bf2c3cfef7f3fd604cff77c6fb4314fc1c9cfb5ea582c349fb7ec49d16ad32d6ec65613cef6461fc2dfc18a7c2e983bdf93c38e7fbb15f558591a5bbc3d8610ba315460c337bbf3046e86e30fe00a34cfb090c1064d1be3630200046adbbfd54ea36811e2300a34976e18b177c01822fc034beb2d299bf68e20b24fce4273c71ee7f9e1796adbdd95a209f3b9b7d6b44953c95975051b20d42792a4f357ecb9b161c67e85117ec15e25c7f86a3b37d608bee961245743cf195b01f7a65da7dc0eb9e49835a1f287960906e3cfe94589d402dd47da52380e50263746145acce0bc5c64d2f284ebc7f79df4c74036a1d00b0b70ec8ee4a3fd321da54b409c0682b9acb02da0a0d1debaee916ea8d03621a5f4904895237912188408083194e1cd874f7d75b173730611b56f9431dfea1f9e0ec3b224a109162db40972c6bc84008de00107ee201f641efd915ea9bdf1305f6411b6809060ccd1b98d0d25c604656469b50bc0d8c06dca8f91967333107d35a588b06b89406569e37b938011710e0c28acde30b7161c2b6c5192fb58506b660628b1a24871fc839c738bf6fa14508b4e032b598a2c5a8bb679f8518592c91c5b7cc75e6da0fd9192b9cb496e43c6f725ec3496b495c827d907bef6a0aa4d16d2bfe118b2f58b8b0709281324d1a6520c4995a9c01d21733dd92c4e1897f1cb9cf073b920c4fd9e8cb966e285f6cf0bc2bce20a15780690e7ff68a70bbc2ca0c539f2b9e747b7f6d8d5d81425b41c6ad08d35670692b74ba5b8ee09d8f42a15451420c748046154b54a165aba24a151c50c10615425091372a4a539099828a299298828629885c00cc05b8702cda57e7569ccfca9738cb67f453e74c96290d56479c3f068adfdf09e3c69a923c703b38f81d6772251273391c959707ce28adfe372e6b4865359b972abc5c2f54362f46c06c16b8c2023f5b05ce54c0cb56812a15f0408a36a428629382c916851cddcd5d918bc1a54871d2e9f4d917e7cdbfdca4438ee35296634ba4d7795d024e11574bbb79ad57c79217c5dca2280005ce6c14f0830251e0da9cb158a31fe9bd20652987021400010a35a0006383820b14aee63816e7a613c73d71820e7a7ba28c27b03cb1c2d685902e62da677a27b65c7e639d3397ade3f4da45004eace1c4059cf0c109274e80d0841f4d4cd1c4029ac0e926714e5c0aca890d0bfbfc6792e5d80de78464c3f225eee34bfce65a12e7c4a3f8c8b1ac35b203a8a49496eb20756866000020005310000028405834209009c5a2019dde011400005eb048b46844972892d029848c31320220000000000400f24dae78414e04e71dbce5e52e05b8cb627250b3aff40a2224cba7eb1cefdbd7dad20307558912e05b413acd74c85d3158992d1fba2f01b7f28ac145c72c9f7b8120fd43e48f80e93b9b51a3138e97d1c40827c1db069af9c4e38351d19754798f0187f4450ded53ca0465ad003d8dae25b42223d5e041dfff4db0df531959001290a709a73d082bbd1ce628d8057b13a2d5c0b9eda6af915f8da7f4285809d5053ed11016d45bb155d2818c982233f2451bbd2a2947ab2efadc1c1294c549c932067e89c8e0a564517a391536e6ec6d45bba3c1fdd5389948d99b12842d91f562a3aaa228feaad1da624733f7b6d8f8ae300ac70174e2fbd85224564fc9022499d831bd457f95bb0e00288296974fab280285379f0819d9d374d59c2efb54b901bcff433e4e898707f8455dda0f1b76f7659a3271fbb5a06b534ecad4e2284961964082d22998faee1f526b80508707376d263fd634c4ce65cdc8cde40e75e22d772ea9480059fadfc607e4d6dac6c53722a3a6f4d0e64612b13dec58963b04ece72f7f1eb3163fc0ca05edd9a3c1185fa66603b7c16eeb66ff5ca042b79549c0614d5b23f4882f66eb3b045241f5c8e1bec0440e2e3d082c5fe79b84011ae4ca38ab4cfde3f7dcd80d9483247451377f4a76b71dc5816002109d19ac6a9e7004ba6210df718c0cd7a7ba343880d9870fdc838a73af14ce266c57a02b1a3d081097ad1f2ab6f73848274ff813e192e763017fb55c478d346c6ece4b4b778e81cb714edde03de3014d12b4c41ec53c6dc26ae72b69a817a96b5363236b7217feecbdc9c428be746333c57047b30d5bb972278828c9761c17a4794019c2f22feeb55f6411abedc985b29c61ea1e5fb7df71059ecc5c8ec5a609cc23f5cfec9a92876a89d94aba7364a05614b622de41197d9874b211f83154f4972860fcd54a7563285bcd20e16fc9621a475bd4704026117f83cb6bd2758d041723b4817e0c422d9ae42668d9885ccbf3f6aa5431f7c123baa3f8df763e9d2c03fa4b8daf237ef69a9a8b2768c29b26f280a9a57ea8884895bdac139b9fec5f298abe2e5c6f09a49f5d5a317ea7cb27aa104ecebe2d46e7088e99e75ffe5c1a3db7ac3e5f7d3d3c76c61f7e2d7903471b11a8f07222624685c007ca2cf76280f3ee3ab32669a1e8142b01d3524f4c5ae86bb676d027d20611e31f6554a1973beb118509f2fcc11ef81ba334f69dc12b344aac04f08e5938ae7e1bf574aee4817185aa30984afbd8d5f349fcd94973eee03d9e43b686c54d1c58db519f472716bed5fdbe8c19ef092b97941f90b52c91727aa23407e0aa4b8021ad29c45d6a792e383c8798e497001f0697d4edc37f36421bb12f03c72d147c99e83a820b9fa056c1470eeb18a2913403181af912bd6969794a29226cd845b8e31191c6772c3e0374259a9798731895ec522eec5ae43d77fc28a5a27213e317c2a95b8876fd0bf371e8d99d5e749767fb6d5c360130c03430828f9a6e08b2bc666f5c32a9e7bb2fcc7143c9546e33b69cd4738b0fac6af3260e085f1f75f36a5b3383d5ba991ce8818b076bfef8856fe03e369af3917df7eebfaff38481fae15635ab2369632314be98b9dea452af47c57f5a9e2e4ed6644400815323f51a8876a8496d7cde939f08ec54615ca32e154350683249a8857a5f110483e33ba93b784348f253674d46574fa49649f84f9531f079fc7873b730fb8e64878b943202cb01a07d043314f6e58d3c5bd40c48aefdc4bff2f1404c777b2d94860449fe3bbc93af1715ff9b23aae3622f478e278ddaeb441a770bc23aae0ca4c918adda712cad62a3acfdea7e65584886543088ca0d3ee43a89c69f534a645d1910fa8fdcc3129443f4b38f9aeea58b674a77d05a3909da743d3066ef94c278a149fc48e7698a1cc0c0e7384ce2d45c52c318177a25c1e16ecb6bf6fac49b370309d49fdadbac77b1abacfecd35e1656048ac10192c8a6bcd23214a341c01e5c491e47093c47884c12c502be2df4660dabba038e3886a4f21c22d695fc2c0be318a6f27111b90da01c85c010c6106d61dd7face4e9fb14367c7d9d4c99763e5500e786b8d4232bc00d1cb89b697fac5042bfbf3fe1c248e4296cab41cb7d65ed75c8deca6c25eb4c28e5954ab2e610b011ebef8ef47ae2bb4d7021bd82f0063764b5955f7ba20daec54492ed103f2463e9cabb177dad58ebe7d1058807e1f17d3a74487352fcd5ab23012006038827d74779358ada4125413fa0ee1abf94d97291eeb01f60dbedd54973d78a4d70fcc2374c3853c4899549b7c0f0037f29b3636efa4a23965d3265d3f823a516cc54b12a5516e6f0164a512bce1e676de685c08d328c8d65e520e46fce9c4ce62ae9422172fb13deb0a74b0757aa0afe9e6dbafb14cbbcca18c39858d4f1af65c7212ff9e8dff8a75650aa6232bc5a007fd0a08a8f6d6f0f8d7ca8cb1a5e637574db856f7ea2e59e678eaa595a7e77d8263e913707e9540d2eac97967c6892a8a531e0b75672cdb802aa7477f137faa00506e3441ac2abdcf4758718e88018315789ce7f485396842524a55385cd5576b723abe8cc67f2bd62580d055ed5ed63b02856b46c5f9fb4489fb48b8e48d9aec9a337c519d8a130dfec101cc0294845b4f890c4eb7f91944270c34d575c138cb53adb9ce1471ae07461555cef715fb7b768d61f18d360fc1fc3c78211595e1db86db7470a81adc4f79ca7c5db0618b38f0d100ce4aab54d6c432155ab7e4f03c7d59de3f641e95d77e7509b2a5fcec529ecd3642e0298298c4f356bae0fa0505ac8f08f2ce5bd9cd4ce9a643dec080763e1f8e58f4d95e4fc1daea988b86b62e7052f36e77d73d77af5b32f276d7761473c46f44ac93aea50d433af145e6059d065016b8c9523cda6156a39aeaaa2ce0015386c2f2f33bb7dd207fe4c5591e97091de81d1fca43c027e40b36f693ea4e7c003efa1eb9553df8115868d61e599aaa08f68fc12de18fc040bf116dd11fbd76345da250db11fae4f97fa967787cac2d5170688e23efb61140c16340e79676af54a236914725302b4ab51ff85f9d2e6c31aa412c35d0fc4b67018c2b9bd016a19286ef712774bf85085c1c66bce6277673078c8546774a325008e1b999ef485a534d8bb5e92d570147fc82ae74d5fad0e0f252d915c2ebdfe9c369e7eed479bca622e41d9876c040ecba8674842f44ae44c6c8f2669aae8de55ced3108a1f129f8e751ae7f35adee68d4d43f0f0fbd9433414ac266354a46055c4c8cfaca10df44d08a294c753a221ba7992525658eee5fbe1e852bdb0fc879e358c1a7507731087511164fa57a5865ae65a6d8f03790c60e15ee2d31075380fcf83c5fcc2de13be8de6e384c786563e24328e263821564569684817326084de8bb0f9def88d22ba40a8a979ff85ee3d7ea5238281f06452f9fe04b2c836693caf5fcad50dcd9ce32c71f927f498fa608a256f785a5a664a9d6c6ed7adc849411f05899cc3ced6a1dbfe7425964c6586e40edd00a1cd0ffdc609629e43b31c8f7324d51c6fb4395684799d408b6c463176b7a20b1798b49149afc011fdd7ffb0e20d7fb8fdf32df19432c03b50691aec6fca00dd2020441b95bb1ffb77700bf9a57725964a72163cac329b704d8eee7932686a63cc5181ccfd3a5f44e2b0908e003779896cd3881c0ea327e41484767cbf13ccd15c23f97315a7bc8e6246437e67e083c4f66f0818851e57a4f37f58f22a47a6c02f92bca4868e7f16af6699d78baddf4d13990b0b290ecad10c2123291b8e93c483306623032aea774f6f42f297b209d9d1998446d87ceb1cd41dd0c1e80b7a71813581d846fb70a9096ad01bf421c958319668c5922d3ea351dfdc916964c15cd43a7feb80a56d776f20a7abca0f312632b66523d03e386646d05ba94015a8ed7e35208b262060638fb111149d458c0edbba5ab6c3ef2e940b475f93d411cf3c98b9b77b5cf7965fcaba2c66516c0f1031bbb788b12c74801c7554938f24078e26bc98890dd85dd6b0487692871b2d7fc281e3dc6c52eaac22f43477d2ed1eafd1f4478c8f7d7e5e8f91f8e687e19ed94709d077b8ae3cda429c91b1d91310713c3d2c83460afa0e8df52f1420188e0e8606498fa61e5b329bcc95285afbcdab3614b3dd8e35bd9f5c89b87be427fc1c6598820d09b349fa26839821310133f96eff397138df029dc021fca09caf11543c7978b1fed2d19a73a022542aed5c755b46da0512e0c1bbe1b8728e49d65815d5cb938c73b6295bf361c6f470282afb70d602e5308103b3fa1e0bacafd876c938551bc6bdf1631e47ff13fb6a748bd069dd7bb5b960dd1d6067eae183ce58add9beae9c43a643dca66cd23f27949ab29372735eb4167bf57832bca23c38975797e2af6fa26347dc79236df1abba8d41f2b82363672121636a4365625b4ec528e6af1292c6e9e8bc2b26caa3ba3b9506a2ed85971a82662711162dc46bb1787451d16b08a317352460bc84b5b6f39133253c579332f72fb277be6772b539e781b0c137d3eac782d3abe08757cc829fb2103fa743c456f2853fec365fce5bd85ccfb7dc745b3fdda53d2f885f57da953622dfc9646dbfa90af78707e1d324bf86500be47482e3fd89f56f3bacbe6f12874487fa14e424b6cccc882da0eb286891ced309436629fb0dcb31c785a349fbcd0276207e9b97be9e7bca91507611ff305438dfdd622a46454f599a703956187d376ec6268e9fa2463604485ab37200d9404eb223e245aaccbbb4cea05f8045c5b3afe0cacc75e3503ae633404b2cdcaa922b4b74a338a5c573c091638e456513e0ea5f264f8060fa0790ab606ed40c5d0bafb6f92bf9c36d3241985c8665528687bc94bae9978512e457dae9f3cf0ae91c7afb354406af7cce73c8d8de38dc229c92abdecd2070c2b0ef5da2139791aa3eaa7ba250ab5a71daf6e3ed2c50fb7a287b9bb2a01fe7f4f041005be2a9537c19a1662f1cf191959522362486214b08cf3105f519ec80dfc927ee22fc92d5418456bf2082454223490d3ac1414200e1ae8bbc5c85eb4259ce03c2777f140ebe9fc21be8f08f6adf74ca0286a1905edb17fab0dc0d7ef22fd49360ae90df95f099c5e873293a599942c1ce79fbdffd126ffb3acf5bdc85574b593fb64b56e163db0fcc4fbf7d42cca42953786dc6de73c117231d14a47c4cf6b276932269806c861041edfb468bba531a0c6b92c6ec448d45310ecbb4f53d0f7bd3e9f8b278f0722302a31835c703ef729c3a2155dad9beee8897c598b59e1c0f88d614370b64b12914afc72f3d94e4c6b5469ca78c18cf6f9f0bfd01ba4f4866044da1c7ee7ce3231132c407d4af03040d78b8cec935a12da4d49298ff678bfc0d12a59f1c149f428a08a9fc7082d144f395df8933ff67d49b8d9febaddcf29fa5c93daf668a23360af40cbf1fc393e4077f881c47e188c4f8b546d94954eaccaa595eb103bf847cf0aadb904fc9feb46ad3541d64b7529316e8bd30706f889ac409b06b1a96888c58000507af10c08aca202d264180789b13dbfd2f79e7080251eba04a376b1c03c739060c036dce9bd08f000e4fd4c738be993fc3dfbce6ba08994de697349a26526d21e4bd34ea118f67fc12deb333f6b56e8a1969539478f2308269035ec85eb10636675edb42a43c66b639f0daa9bf833da0b68a534944d9c6f87420f2e5074f7c458a74286f8e1df4a295cc58554f272cc155b0f4e11a0ea221aef16439bd028514e35220403aba2f8c9c80984938d83c873c16d6dbf6d2ebfa4a7a313f23cf76683771ec870ecbfc2bb16070e4f089000884b3a1dbec1b6c4b98c1f8cb3a2d0fc86e75c9e1819ddaf107df5a1ed546be376530f42ede45e195330bf6b70de2d22dc2dd8dcdfb9948a140a041f2cc95ef8565741b089e6abd5ef1320b757f196663ea1ba028a43bb548b09da4882a17b14a8ce9832e11b9bb2e582592d8659bca67b1fd8a1a9b38143af8beffd706142eaad0b02029a413edbf06887be950c554829f43210f06aead842f2b3dbe66486c4812545f7d027325c0fbbd574dbb6a59ceaac72b5ee03c2e62ad4954a1b2dd4ce98a5c7f7edec623b2b9a5b59a6246bc35f13aecac069b05f06190d48d69e57169b0d42796599c9595fad4efb43337955969ba12d1f1678dd52e2e83376f62f7237da576450543500b318f1f4c282f4a958049cd40187e99df3126b1ce4261cc73ef0c61115a9b38e17bc318e36318ea1650a6d3db689376c5b3703c2895092f006b084d4ff3d5059c07176ac5136f879041cd4b2810d58018705fc515fe7bc65a5010e1561a905ff8682d31eaefd8d692f38c4d3c13ce86f6801812faf58b1dfd8b1df56d337b208af530d6d0cff52ab6f447d92e5231ea4fe147c6aec9c3b6d790dde90c6c71821cfdf8eb9a2796dccbdee52de2f630e84d41fefc24368ba3dcd130da66317ad2404dd56cfdda84b83865d1fff9b0f1c30f3bbf92cce665d72ce9d82fd8be51eae641a1f98537b41e1ba835e7b7bf94b0d0886557e22066f38829f5965f9a3818c57f230b8969c04111a3c7c68964a9243178ba275c203ef392eb8137d349efe415d40e8e85a3a152ac5019693bd16441ee2a58c9cbe6595d3f40a38e1fd72b5323136c3e364802baecbd39faa6831ddf7f19f1a7a4d9d36b1479a37b196aeff35cf5bcb17d750593689778d159dc25003225c4991614b6dee9a3e0d1b22fa87569dd0f919c24f1b40a547e4d0c1c3924e1dcc84da32cc9363b4b01f449b17c642a85a87d4bd5a4944684d65de55314e43df05dd7a800e03bd1230b1e1308209659392a29f64337f43eaa8ee798e94e177c34a64a8ed25e061cac2f681297a1f8239bd5154a96d38f1f15de1f7bef2aa17b132c12ff6294b89fde39e7828f08b92ae8eb44be5f8c30327178f73aa06c9b18ffc9ee3a44c52b0cd1925f8e3d0af749cb1c9cf5dfc5d22240197e76b2723ae72c190e3b15ae79462ef4ebd45bbff13e5085ba15601052614769f02f5ae0a47b982eb21f43b81ff2bef73c9b57f68052f5aa84ed9e8ff66e2cbceec45a7bb30b96893e9c4f77b48f523cf61d0d048326dd8985d85ac4b665b4d0eb33736594185eedbef358521bd6ba090762b0910f34ddba0aa55c3a27797ec575a8c68e6ac0772ce916d82e7f16987e3d0e0896f9483928afa18365ac11efe2ce856ad640633cc12ad174b4cf515b1c8091d32d5bdbf3aeba36535a19c1310615dc6315cd651764468feca8b43f0ed8a2f094a572aab43d65ae8af7b876f85c2d9cd84ea2ac29f80977a9da9c37a269238fab03197ea1091b83194d0149589a1c998359c1d57f5787ee0ed8f1bb5849bd695f6f9a9c6fa2327ee6cc723f660cb5a0d6790f166f3e6dec4326b624c75702d41c452470e82ee548f7851b14dd7e148139242a624ef3db4a6f44375c3704e6e10de2faa8d009626201f77d62e6a5a856603cd485790708a22ff29e2c54a1324aeb2f19f0927fec45516f6ac0de29fceb59603802fb33a5ecc7e9cabf33d443866f2f567aaf58fd379e20e2528aec81f49af833587a7124ccd44488e0aeacc48e98ab22365948d8dc2a6a6e8905f1407261995562d5fd7128792448e010eaed7aaaf0e17ef2e87bc68ba3a4b41a4b13559fde40e89bdf3609621615788e52ef89c2141e950344384be06779e30ede2670dadf6139468a5a6d2cc988340d26236feabac162b8ce09c4eba08293b124f13109f5fff68c3c8e6c370ad3cc50e086a9e88417d0e8b5a2426a2a08c98d032147852485f093606e3f7e87fd903e7739244fcb2b04bcc4db372153d08ac09e042910d499e40f7f338756642d3ce9bb449c7c562ea6e4225cf409e104a29545e4d75a026d414b4a8ab3788b40fbc085d2e5348cdda9bd7ae503c45f321f824d16c1dec8e2f38e552e01f1c5126d025eb90c1af25d5ffa70589e3a84f99f13f0f2ca5220217a552803f414f01da4fddc826323aab9f16a7e9c8bb02d2297b64f0b5377f3e73f725bab84e38d384698aa7a963aedcc8161ca98e661056ce4c838c874923372bd489f0f010104de0fce1374c785bc19d6dafb0f7e53c59813745da183d3ccac129599c3be017cfbd4cca851903d092aeb3948f4a70fe4fed28da9add99130354a13a8c0fc6b0737ffc31b481aabf75a6f93c36b98ff7b1ceeb2d3ba333481d08225bb1e0c5d5a57321b94e53e780862407aa09390d0eb9eda0e9e5684ed30c6818c895e332edf206067587d8511dee1cca99abe672ffbdbc9e7782e408e7eda2693676d93adc55334a5121eeda61523adf2ff008c1daf1a02864e19cd21cbd170b6a64961e7ad03637986e4697ba7eebf3fd3654bb404aa80f0675e6f49271bd37656101534ce74a2040adce9ecd505edec5f593f24e0d5f4ee45f019a9ddca4d76950b915dd23945049186126bd06a4cc941bd3ab44c3933079314ce17a223217993d273f78ecbc5b2a7e51c29d303de1ca5a4bdfc887f301d32072b612f1c410544044d7880b9b9480e8ea490f3f9ec19022454e905a82d654b98752301638973adf31dfd84dbecdf4d297251410b008fa29264623a63c420d692372396525ba842a057ae042ba8e121d6c38234f50948d2b0010b108fcc3532b0be23d99b06d6f1f1426c6da85f37574fb163be866636e1287af5be58dfaae0e025827925957af73e35a84450014b11a9aefa3b260728895b2b1200f6e35ba8042118d48fc41631014f7a36875a3b18f14ae6bfe1194fa6ed8258a4621f180f15f6a980cf71cbea1ed9213c660a82ead6d5755cfd9ade79b0e50783bcb23c0273727d5bdbd6ba6650ce35b4ff67d983cde7356aa77e81e4b5e154048480aebf1a45684a03ef32c0eac4c8811dc92efbcd757923ec5896f0f3aa9a7d2c8a20abf5258e5ae40b7f8a81b965c11a2ef8cccfa8ec6c74d1f4a0f4c1d295d735e395445934d6c1ae15f7a88c8b09bb11076d62ddf829ad2750964e851b8e6fc3a702710c67ebe44c9156f4de1a9b8b55b7cb0ba0df28dd1bcf19e2eb0074b7062ab50e8603bd7f5bc22f9a6e4f3ffff9f593663db9c7ecb58ac2082c37c0f918cd1d42e6aa92dd259be02acd65d9b103c64b45e33ee8a7f85918e66b2e6763410f9acb2bfe5c04bfafd165b382ed6a36688077a2139385b6658bd17e5c181437d5b4db8b26e198c16968dc86938c46f093a23fb257ab1f06914fb105036081a98a85aef1a77058e6d09fc4be4d6932b80b1a10c45c5ad6139b536e6a103087f3120dc438968a630843a97a2b0c67690348b786d7e375d71154ec862f0afeaeb3813348146c454629d044e05aad5ec6db9930eeb06b7f8b372f3c73fa1a92ab754043da9e262e0c23d4c16e434c24d3a991ea2c7a02496f9a9b8855bc8cd41326b40416c3e78de02773f68d4370fbe1f120e148d04edd0174031491a858a5268494636a45f3b73a30ebee03e726cc7e0793262b4e38ded0bef93858104872b9bb284b59b660189c00023478be707a7548ec943111cca2f7782d8b8068528a4961b698b15ebb9adb411b0c81cada23a8af130e2480e3cc142e338c53486563a138ece1f38702efc5b479dd75f13fbb1587033a15f19ffbba0e8ccd8d1929f656856d2ee6b0ffa16d188a2b467a5b337307459214ba4298a1970a4ae5d2d827fbbf5269a1cf3a56b670130b72babe7995ef729aa7f6ccf947c5ed2fa8881b894207531715324bf2f9220f58c79cabd9dca6d30a7a7329e3717e379b7a0a1e2dbdcb993a202cb1d002bce920f0b14a339cdc267186a6d984944c342df888c81aa2ad780fcc38d7367fa4757c5ca92a6239ef707d69730a4d5b324477ab1eada0500f02f9896df1d9c0191c96634e994d1d93be6f50c4688f839903a9d4baf2529aff0484406ac7cfd060e7e186df864255d46faf7ea0a02d07996de02d541031384dd02271bb44cfe1fd1e5293e58dbd2ba4d031855eef457f96a69d7fce1d826d00abd881bb7d7bd2501985c59e2819283c3e5e70c3d20f38c71c3c8f5571ef59c1ec88fc5656f4965b99d3ea77dfc5623e11d217c3c1a16280460e91aee3d7ade3199e0dc2ec23b753823b3704563703b5b715285e165335bf318b3d1e0e1ce6c7bf2f92ca9c61bc0bbfed172f2cc9c8fceef2129a214a177aeb81a79dc754588f9ee43bcd0489a76fa8ddfb1585ce60a99908165e4e6ed084e455420ad31b2b2cde3888c9682b6cc997700a69379810efdb420c733c83376974d75621114991bbbd53515b1acf9e14718ccab1d9b9a6d2de0fb35a01c13524649ddc9b33e4f48bf26168a75f7220eee4090d25608cd201e7703fb2d95fa131da35ef33bb52b12f95977c42361ce5f05b6a7dff05df36fd8af3361844471be78402bf4b547ff9d827647a34528820328bb8504c59c4770e8a41dc546e7bbc053d8dbc9d6c68ccd6320329111aa0c04d00e95a74fb831b8e8dc1e38fc84245a993ce78c03edc2a82a73214dd6da850d8ba8876f69743e4686c09680460a7e8a30dd83e5e84b908d11d04257a3fd30fcee39d5c6913284c2294c651ea34997a143dec28486a2714a0e95f0cb9f95ab2973bdf3c7af38f176b8ce2168696280ea9b15a24080f60218e40a4ac8c826993d7180e20989d19624dd157c612246a34ad765c2e641ebf04259807c736cea52feadb631de3460bebdd03aa97861b18a0849e8baa1dcd7979c798b55ed236b6037dce9bcf9bbe683b2ed577a41fd3cfd15298d00134a742ff3b04ce4a682cd786b9f13a76e66d79ea5b992fe73d2a12b2f6fc5fd089abefe60d9a102548404829495367989cec749dccb75fa4afd54f41d6b47188824f1e2f62a8f0234b28d34969e5b5e5f4316148cc4812c32304f4b068ae015d6c81f9a08eb27069ec1db007b47daf3f4686e82f08cb12217166de651d8f06cb574f590cfbee3cb83dce0877f504edbeedc7914195a0f96d6e073dee90a2d730905331be9a6f58475c743af8b3e0a8fdb7da547351927897c795af5793b7b2acb9c7f844ebfb0e69e69061640e66546b123b7234656c4a7b3e8003b92e5f745616dd366e4d6a56cf67a39c05d98882fe7000205094cd86d68a082c68a7814e0cdaf3a9cf83ae66c71101d70d7573b55f7a65cdc86dcbc3d4975974e89eb17a20f9e61684d289abc72802ce795870443ab5ec73ae7c1856f1813aeff9f0242fb77c15960849f111d8ae59be47769e95906da04580e5f82fc57f35c28cc726bb1738b7bdf5ddf16c5208441c9e3e428192bf62160575b7c7dd82345ba0f8a5ac8596be699379f14c7066384f6b9eeb2c6b8d46cb9831f21cd8f7b1b646a7d198f14b722f3f07b2afc7246fac21a64f1253400e9a3a5f4a8038c5250f339c66a6a0040783b328726252b47451208000ae04a5fc384a157d47ad91c4a2914cd380514e42cf99f0660c7b03b4803446ca43ae9fba2e0ee073c9e08ae62ee5fd0bc7115b53cdebf41bdbb0ef03b46369c90799307d243a9c58534d099078d8a1fd4951f57d7ee6991dc772252b4ebb9336af4f022ae95ce5dd4c6db46a7b7bedf2ca2a2da1c5e48d06a5b3ed35600c72c33bfb712b08ffac8703c3669cf9806faaf8a00a94489b104580aca5d6824ab8cc048351410184a4c4665951b9d14789e54e1326fc3e935e96b75a5718f534bda060d543013dc82432e27baa8759f3667f9cddf4bc6260cd3ef93a48c1903dfa1fabc9c8b27708cd1a0191a8ea42f33f58153a770edac0d665f214768bfbe8f065a4c57fcd49da42535eea85405033f32752564be8156973ae58e43308d05c0e6a0455e5b91b47c0754b111baa72ce493f84e3ca38f421c894de8a43bc648a6554b12838d5fadbde721162432788b7e014dd065fd895af9a93a2052fb810091169405940071d1155a4ccc2c2470ca98deab1030f5055c53c2c4354484cc8e61d6bb48732d10a19962b967b959013934b8d0b8a2ce155ee3833ecb52279607a32fa36049500b88a6e41e22d4addf119b457a75978dfef9f2fe23fbb484fcf91a606f7733024fdef001c35a59a4f422336bd0cf3cfb73f91c58a9c06fa0376d25b5063e56b079717f765174e670ce484217f66b9735b580314a95629262fa26b97113a17152c2754a1da7038f8a71fc047ed0b3bd97005a707c0be8b7d071e7ffecc7e32d9b79cf2cd1079ac3bfd9b6ce50d5a0fad72f0da1f86c710ca61bc917b3acbd53dea7948e0ef009a4b0f2cbfaffc93c0203b134bb81439d104b1bc9536d3a29dcf4a0b257d8695d24ee05131921cbd52e792bd11b516e081e1add9dad68c4af9f84d0c586b8902a869c5de89967de3b87a47facbd9f9c7b1f0eb744dafbcf27d42d1655499ebe87f34401295a637f369df80d84d2a06134d8830c73ef766b76c348eb8d33cd7edac3fccd380f005493b6b43338a01720f0c041606a91b2969ea8229d16e8c87058dc5574f387218e64cb81a9ab758735390962c36320f6d2357babb29540b4332c7b53ec99a35d34b6f7472ed683a9a042ac64fbc15956b21da4b5b0241e1dc32ed198c560374626618b5cc35e779b95a37a823414dfed814466cba0023e737b35dbc0d818fa3d768f3aa082303c1548c83faad482291dc18344a7434811aaf435d4556c771b6c4694a79c126d9a1248532a1104cec3a632dd95c221303b42fcd8edabbc0f2121246c64f2329c80e222762c67ab10a426ebbe7f6e125b19d8022d046656adc6ea970c3118930148ea43936874a4bb6a51c9aa6764a4b8e87c45481574fd13662cb4323d5a141f977dffa299ef70de8c30377154c91b9f878802855e39ce4367bb104cd1089e271d6617a86e02bb19bbf6479206b7bee5cdccd847b1a9bbb4cfd2371a11eb7d17c1222823dd1821c5e55295a2d6c1afc5602d336e40acb35cf21f1deddc4ee03ffe2338fbb47922c1ddbf8d275109a6350843392962278cf0517a7656dc469bd3cc4f55f1535f5a672713b6de4c34badb7cbd557d263fde1fa81176f97a3183a04a090260f3591e85f2b074b76432fdf95c160f82749c328859316e2c900cea4b9c96c69335458f80c3ac0ccf174ac2ad36f83169ae299869b3c1a77bfa34b528b21ab57ed8101a1d7a3e9c8e25a928cbea491e90d874e28550494d61d03ed6a0833b6a70d2d2832c6474ad9fb98428d9d2f92f4d96c5cc8f69de0dd2f78918ffa44dda4f247801cf89f06085d843e4b8c8bc9632ed0210092943229a2aa185b4c126a6a45c1d631371a8fc2a323ad5718389e37b097e8d2012b7cd9daa5f97d32b992cba0bb7821130ff04eb9bfbb5445a6c7ebdaa0e08e6cab8ea9e3a5561166d613ebba72093b358d1421537d128437de7d071565c79d2dc1b9b4b8d340d3cd92973355cadf0d51d693d230396f53caba2a1654347219d4801659aeb93ab62c63daccb300c6413a1ad9d0d5273d99aa004885e6b7a17e9cec95d396f30126fdccf00fd4dc4d7c8f94456c527d9e4cb2a07db0f2499c3807ef262975137408153d0e57c291c2c43165f8bdaa368c45a75680969fc6e3b245ca57cc4c8a880da528ed42d6fbc1c90073f680198b5f44a3514d6f009a861c0843ccd970d16dcf4a4be0f2d2b41b2af8d6aa743825187fc454b321c2b807837412d679515a371d22109eabfdf92270f986104d152826359f16ab4e6bfb466df976492a26923bb3729e4e0964dbeb711e03caef160cd8a1614aa285a878837ffdf389de7acb9a488ccfde9d19eddd451d35e8b7b64e253917022a436b0a9fa00af5dc01556cfba9eb3d704c3c8c3b03d7c8750ad60621c1de35dda21a681c645455c6e88c84af91050f65860c4581a34e75ccf33a0a87e4ca646687b55b89111049b91375cc9155ef94205e976e07f5559bea3198f03fed29d49d434bbd324b4ec896b1990a311117c41ec4844c961b0603c066a65d24b3a0c9b3402dc6d499c8f6846c1e49a1b96ee674ec21b48280c1d859005802ae29215c17369ed5973866d3a5220b79dad3dfd1401391864c0224e19c82b3fcfcdc6f85eb27c1e518024e90b50b251100cf542fcbd728674914c93163ac9ea458fc3fb0e98e6a61182e0369e00006c1463c45a620d9a371a018a1e85bece496851481550ecab3a21974a930fc37b26538eba58975634d51acef2ceb26a8c0245386c4087db8be082fd32572852e5470879536d44aefd4754fbff26175c228e951150960002a96ad5ec3478ec6bf13470550e87cb7d1b5f787926a11805baf2fb24b04487678463f8d9f2ac2022614f659e8d60188d346b2c52bef2ea4584427e8f7e434f8d4d1d689ca04a841840c79b0adb0440f7f50c8589d1887b04a93c1f3ac7cc3b96b3e2ba710b5792340a73218b191ca824c54b0c43841b85a054c1380c97a5b38688b9cf77aca8345718f43c7e3567ef72f421bf77a1d102b73ebc2b2a13de71aab382cf1b81887bda7c8b1de5b927f9ec99d29ee0424df41f0174af53da22e83d68206d870239dc0e209a447c04d4debb794b7e936f905bd4abd322fca18aaef4605a95d1ed29965de8c41facdb400e0f582db1062cab69fdfd1dc23b089922b8ffe18eea1b3f9741637c682e0b54edf3226edb237620b8cdb9af955fb445541637959a54cd46df7493d2fc58486c4ff2a3b529fc05dc9162e2fd91e789989fbce6bfbe9cfb8658761d651f01c691070ae59cc3e6df447c6eed8e0d7cb2051b08917ed4b0087aaa501aff22eecb492d1a5979317b81a6ad26105710e518cfd2d36ee5ceeb9caeadb73b3a6db6986d386f3986035458d21db727dae441012db9530022f10bcf1ffea4f184ed802fcff538d62a18e3fdacddecf71b8b3b27620be3930af1bd9c02cfe481163029d8c19453110c0c534e60fa73638728767907def17361ea521a978294f674cd21fdd4e14fc2f2a8c2ff51ea76a9bd88ecf7064030c12badfcab339211ab3ad641d92b7c75b4ffb3ece6f1215d7a3f0579526cd6f5f0a7ded51510a5ae68db9191261d040df1d2d9094383a765a7db4575eea558b1d7cac0af9e1fda0e372873a4cd32448978bc717549680c19fadaf2727531f1d886128fef12eb6421ae0b15fef4a9420439470b9abefe6c5f5a56643191c9b9e619a6fe741591d3b89c971647497eadc8f9a4558cd00103cbc7a951c9c2e8bc270b4ca4143806f2c3785a81ef76453dea181bcd1739b55d37baa2015e54635288fd68e30ba06356c8dedd4c7265040910135cca931865cc92a6ac538625a7c55133bec900c341ff6f576c87ab773ce865031c2db16725e9e4dc163a7a16b8e0c5a56c343815645528cb28e4cca78a90b2440927f2067bd5883c96b1c7f5dae0ee6de97f69c5985755fea4b1488d09f7d86f250e43bad18930dc95cdb206592b16ab9161c1f0329b0b47be95d4cfd809ae2c147e8041a83f912d5781fac244bb9cdfaf2b80c0963404d3972183d9ce9ab2a5446aaa0414ee8a9f699e7a27068763386a5ae54ba356384be7b77c2842e7f2c184610f6a6f60a6a3b31221044dc4783ccf5ad6cfc2d815c91ba0daed5dc80b920adfe17f8382f70fdaee2167fa1aa4c68d2bc3b57a4da0145b1374895fe6a57a6e1275f9ef824841a60dd5f800b431851cbabf82e369fd9696592429519fef4f9ca8b00d1e748b6b8f17002898b518a3c2a386dfb9dfd73c982fec102d01bb5c1a72a15c0a730cbcbe2ba26dbb6dd31df36d7ddffdb3e692e62a00f0792826134d32d56f3fe490e19fe0b230dc0ec07cf8d6f0a6be1bd65eb648f597742bb771ccc8286542cf0ff4a6d967703bda859ff0b053d7802acabd1181eabdd4b15e6cab79b40a22efd94f9cfb093119fcfb44e170db17cc35f7f8143c7fb6df27bcb4d4ff7905f66c7c6f5b6fdfb43d9fc8d505ad1d7197c33f822dc6be841c16e2acaf4f42f271a819c8363cad44025185c9359d8c8cdbeee40ff5b03f3f8ace12409d0cf2aef2164a7df8e67286185e449fce93139fa65e55b5c6f4875e41f8be59d19eaddccbf33432a702f19f9941f98e155204a857451f43aa9ce61830328960bed57536155366ecb079cfff58db1549daed679f6a9be9f0b06ef5270733db983782365dd6687225fb5583db9a59d2d59e69b98cec2e0fb66c86cad5f69f8ef2a99710801d65117833bb5b675beb32d44f2ccf0c4f07b3977bdd7d5e15708fc6e8da3128cf18469b28f45428173bebb88081fa7226bfe7150799e2290670112c329b596cfe6edcc1e474361afd9166f81ef900afb8b26c98b1405cc5eaafeb7716668f7786f8e00665a128e0f158528e99465ff7dbd844432b0cdb5f8a19a8eae786f2fd73ab238756d8bd8ddd5b6586362e77f19f489212640708c64314767ed0251f5178fcc7e7f8b34b5e742770970e23246b2f5f0a1a6f58c4cf2392e7af63a18fc20454470e0bd8e252ad03992ec2bbee7c1c5771c9b72a10a4e4fcb0611ff706a86db38ac99c12c1c198fada2ae958a70077a6106a01b38c781decfb72de18d82a2be11b3dd5135aa80e377600156de90d85c3326eef75cb81ddcca244148221759087a2d1827e90c9d016eae0854c99f85f2b79ca5ffb9015fd12430bcebb23f09a65b22bdbbccda5cfb75e6409039816c384b149fbf794b26e254bb42279733013e384bc31e10f1a25e700a31f2fb2e8494f52d3c07e3f6d673675d4a7f45ff0f41214ea8bba603c48a1b7f8cf4297e9d20f0121498b249ea4ad98667a1cb23b64824aeac6f490a900aa3ae755017d1c767e0973f4e203201984377f887b9ff6830f5f904ca213031c6d8286d52b800819348800165de4f3dbf3bd9f135075249e0339d003870eb9f7e803b71cacdbd62881bd5d4d4fd8d457acca93e321814a4801fbcf98989b6552b8a4093f071b66517ca821ae98a3f419165955f6da2d6c116803e4d9b7ff308a82d3fd9bac374247329830748335214fdc9e83d41e667356ceb2c681e6131ffa33883e8c892db67d6cfa5560999f601787f4d63cd34f469518b41a7f356d20ea9cad56f660ff9d04759c29c64b4a1578f4a4c09db22d2e0605f9e48225f229cd51777cee39b74a243cabbd51634b1116a9a8c9e70035776bcbfcb87910ae9bb8be66d028e708f361066fdb0d40fabbee746374bcbb03298c3a233cca248a52a71132de97a68f33d002b03e0050ff8311000f5151c13e7b8f1296c78e0deb91c9187e91bddee81c48589191df22be1d85afb58166fae2ae39550a6e6d2726421ca2d84128d32dc9bcc26c6c90fe6baedc297fe2770df5b67745bb567005d80e8f6d91b0029a94b58b1b81d7d4b8d7622e50c320b8a1c31acce5320da0eba0f8d38cce0143aff9d009a009850be8aa33b6055423f16ae246cdf1401e3c8c2065a3dcb9543578b6601542c94a26b4f3d0a10ed0a593b4dfb70008e0cbaefa20880a70ae69776fb37f08b4784d9d3ff7b1b313b1e07fbba4bf0e923e45c90437cb5f80c3bebffecdd8d50543e59a3329661bbe3e30a20eb4214925747d174f6149fc285946ffe90bbcf1a38e815a5ffc7d7d1a2050987a759d0e8120c9224f524d85d60f96629b3ead670afa0ba7a4772e61674c5676d13333eefdd2980b7bda6a9b2622b9c758648e146948b7b8472dc87165d4efb00fe6c46dac7fd1c5ab459ccac805f0ab386ddcfb5f2be1d87ce2c2ab7203d75508452962a259e2326f9ee5f872afd55ba59bb23e6706060d795bf7bd990f812944c8e9a4f27c44809b70724f8797fc3d2caaa9b1b5d5743532da05d091d4f68c6d87cb82d4a244bcf303761116404304db6b56629ad1d48d8b27bf83a64763c642f5cf2b856f4011263ca124d5c712b87cb5dec319e1dc28ae13d58e7d26b50764e1b1789bbad28dcf0964cd9b3d178678f5b30deea991829bf14b7ed0a0609f01b9a5789bdbb0c707bb8817765224d1ae71faf8098e5954c41efbc1f245c056f7c1ae8b09f0904940cdfe32f93d5f7b076fde73b96eb7f793105d8b31586eb69499050650fb628d201aedeec5038ac5d4799e01d8296803ead834527c573a53a7f09dd1eee175a389e3ad37ce53ca1b8de927c4b97dfcd2adfda3df72f8d6c2cd26296e9729379cea3a0465274e410aa307cf10ecf19476d56ee5afc0526ee56eb1a3d7914787518d269f99b47a1ccae14911103c3ebf49dfb5a1413844da3e32f084297b6b548d08aad8833bdaed04521a07afed27f3b9e3bb18cbb739d267dcbc60b3e199b7e4002aff89558437d4a8e349a8a9990a108391e434239ee244963d57d6bff41de2c65af4f90bb4e78a3dec0083c4895e778cfcf0c14df1933f9bfd6439fe9aed8d3cb174200c4866c688af4f80e0e24d0f365c7bf0b765803556379638ced02cf1adf791c21eeeab5aa14c1a6c1cd01fc0c3804b6fd40567bf7c2634ffbdb7d12df405bfe65afc6c99f988ccf47cd73033b3e15800429c5cbc62f10bce545e7bc0654dab56341da9e30ff616dcfc96fa8da05911bff39bb6d8a202c588b4284be1657223ceb4d9bfdf2fef04cdd68e8a9c1783fe48e6914810389faf41a5b07df6ecd231e6fbc424638635f088e0fa825a15bdc10d72443bf13e44a12f447293d12d9a6f34d7207dfee92fec28a3029ceb21ea41dcc370115f327c394311bf366b63153dbe3275e052e4de59daa53694bab934d19a3f22807a6eb2c2de81e9f12106e5806d6d74cb0f8f38e2edfeb1b8cb88fd52952f0e9a19b34dac3ca3e6b0b7264f8f44d1ac214c5d5d09a7e86dc8e44b04ba84721dd6021569ea63598da6e338267bc1c8352e84a8ea599bf267459afd53363272be7330b49880a37183962dc9eab5378bedb057265074ef36a9c3f9e2bb6024fadb526822bd047a6a46aa45813046739505ee446a17f2e6d0c26ffdb45d80102fc2409ef5a81f7dc0344f0e0cf38c16eef3fad6571b74fa78bcf153d7b931d0b1d032ce13f0c4d38ccf7161bc67b8f3ed58cb8f761fd1a8ccb52b6e761ae420f3038f91dc19bbd2b91e39535d4add580ed258760aa2899a190119672e47b947ec5708441382d63e0b119c9febfa3b436eadc455ae024e7765fcee963650536dd95e08e33ab46cd01ae4c38efc4ea56042bcaa064308f582c4098cf95a764e99f6b0b08ad5686df758ccadeb88efac1488e2ed0f3a56ed6277e6d7a838ac56e421ec4a764cae27426b6f5a251214eb9d42d52013b21a0ee2a2affea57b8080c4f9f5357dcd6f88ca589c48bce6083412752298ff92150614d0a1cad8552fedd83b8ba74930c0ea9f908923d8e1177b150d8814126a7511349493d8ac166483efe7f3edd6fba698186dbd71a75999bf00d02ac0da08f5a87d6543a897bbbec809fe366cd6c5c348ce0bf0f084dd1d127361ed38d19f0aaf52a99a462d5ecb1f81a98969f37d31096f77f508ef51d89b3661027d4ce5b871d00baf647d8946cd3eb26d62cc34bb5c6ca79e42c813dfc30ce15e73237e7fa027d6f9a95e3bd517187f39af01d40cdbd3777c8c54ecee2603e0287f967be9eb5e18ec3bd9c04e8cc6fc29b5f3ebaacc9c657d7c99e00c28f7bf45e05a22f0507082c8445354b90a1d94e9e47980d1802c7aa178d2f10467bcaa38ee715505205b86f6e911901399dacb264bc1f8076a7c9a0d3a451c7031c04842a6c629233ffa508ab64ddabbbf8938ab1fac60297a68caa70ca16ff870fde4a3eb4f882d8d8dfcd9699a257a045419da89726a36ca0063b990bfb8121cfef073c46b9e51e22d28f4c5dc358db2e7bc47fe1bba962945e4defe3ab7038825f7b523d29df7371971a58a6511780e59c9fa069cb9eacac8b291607c9b8a8823b200c3a7c14b15ed36558a5e21879616e31f8e2519316a7f484f9b1fdcc20381ad5570cb6facd9d03893b7cbe7eacb3aca3a3d73887b0834c6a4b9184e5bc65d0125a3de04f0a47064db3146dac639912918cd5e108df4f873244cae757fc7bd90844d390550a368112a91b7f6d308f916b320c7de412068b6e0844f90b449fcbd598422c36f31417b43eedbb12b4971008652f96ce1387b99f6e7e50b20273d0c0bae2b31595458256281000d60db05e10c604e9253ec4ee290e83222ed7104ebe28f1fd836a44a81b8d019382ef8fef1421bb597739b89c2b7e716d055e3b7ef90967c02876dba5132003d2cac555edbe9b147862cbd19412b409ae6c4626e8b866ce7c3b3547db00b7d743787a6081116163518061a27a40331a7e5443e4934173f2bb7b516eb2d04920ee474a175df302df04a34a85cf4c76da3cbb3a190ba96b017e240e7055035a59deae3110fdd8f80a1d97743eb8d829a5d44c499bea6404e50cf48337e43e046aa1f9ab40280157d5304e42932dbb2ae69d73c10e374bac19ef1d073d8eba1d9f044916532aadc1710811e8660513e5f553f34d8fe6746ec69bf46ddd0a4cc246a2612e7acef569aa60fc93a9350a10e0816d24eaca58846c8e728a379c764a719c3abe0a6f98dad1001165d3c2cb8e4d9f38da066f028dd31ac0a9a06d414205880c3b2ec8b28ba238e0904dbb5b0849a5149803832cc42e59e9cb3fa146107f9f014bcc0fdbf423cd4029dcd1a803e01dedbe191be492c5c6f565b36a5a2a30c394bf94683f26ff8b8c603c1ff0214830048e4f858a21ff680425015f2c10556c5dde595ad9ead571996a8b2c7ca5ab3167b106e4f38a550640993d59c9755c12b93cc3e0895a84130d61c8cf1d3581c362cd526327371c39c24a992c087be0a08a7b9cb405cfa047833fc1445f047226da8f187644bff8526987031c13b1462f7f8e370bcda577f105fcd38f939852bec4b6fa7c1e8f27046c6cc597a8588939bee48eea121bb153085a68b2fc3e8c67a21e9b72b48eecd8fdf68f3d2336266e76bccab7fa8bfb0b5fc22ce9525fb462745e48dbf2f8f2f106da08560c46dfe55ab2e6984637a636f9c3f9c0a53039431692d07d828b6d58f20bd0209b19d04991b45cded773f457493c8e6885a88f84aadd6a2d60a5cd0d70d669f7efc7eb3a014be90413ebf268781cdffc0d7859a64358c283255e2a04251d71c69a17fc96fe4aabaa05d418d01999a3824524afb356af3ce30c054b589b745f63f6eb8c2ac823b6364965179b0248cfb16536e5c514e2332b0b429efd946e349c832fd9ae94aa3185038ab2828969a609c69bc01d659b80d3a398a87a74f172a74ace2947b208a19f6e6eb5ce1e367b8d121fceedf90c43903ef7d038cccdfc03edeec2b6e877b29f3d48dccd5940e12dca458ae0042abaecd3129761300d5bf66d73502b55e408e7d0a83f18801aff075f5173c37da9f4e30c30d193a04af110daef91e0a86696c0848eeabbed8f98c6766a44478064d02b1bfad24ba8fae36d4ae962d4109364a8451d7f81d0c12ab2dc37ecbbdcfe18ddc5d5b3832ca22f4bc013551dab2f23c5e095202de9041a7dee2b5885b3e43153ca800a6a08fb102ce81aa171c5a384269060a844f7a5162e0e9e4dc6e5344f2d5cee83e4919874bdc12c413a30ba66e96e67caec6aa516540f4528973b73e00cf050ffccc0fab687ed3c26deda6084bd4b5b0b9178184d53668d00c15cf65ab78a2f7349a5b81a79f7dc8259acc11e7a850353d5b0ff0f65bb7b33327cd5d60065da6a8b5eb7e907de2a085a67132087c44d713d5f536c16cb7829ebe60a174ee0ecf78349197efd101fcf4162d548ee3133b171fdfa98072e87b3ff6ffebf3c8dc02167b220c97c1766c4fa5ba29b3e2984c3ea8302105e60062883dc786d37af812736220c91db67f903b32d64674631af231a543bd0abc10e96b43d0eebcaff55e802faeaf56379e7c55716e07b67b171edd434b1fb107bf0ba71512d76f9e570e56a0d781538e3888c30e89346238440d35a839e867177698241dcab668ee78c5dd1599b616512e66c615d9bfdee09386a3c468ceeb918ad9dccbf333ec79cebcf1f8175e216ee10a0a62f611212593e5db54d160c72a67ee47631c6ddccd2f0694fbfc9163f45f4a2fde973494472e1f71058dce769233bd8671850748a15feaf07c6eefa872621d2c4101dba4a783a9a49f74472dc17cb2f98b0d66c7605ae2b600fce3cb3ee44b3f04fd8d151261a2f2d53e66e3075cfd3ccd5fbfcbcfa35a83fbdad35608de1e4758fd649ec569ff5a72236320602cef494a5334df1bf99082a054d993a781867bae0307ac0c24832c3b3df0a815ad6a19f2d572f03cd3803f96903ac7c767a0ca0953510f1b5041e0d03d5aa0c542d83ba053e6547af571c61399f5dcde9ee8818a6d7a61cce431b0864705b58a2f179ede66c345b6b5fe495f1528c7ff42b48850617b5e25056391f1f00c713a58db4c1c9ffe6fc747709bdf4eedc71fad1e995c3f2f1b7606fa25082ba4c8e229be17e9f8ae83c2c4b599c436bb13f3a2ad7372f5349b111b9db8b623f3b88f452df48824b400afb531b979be379581522fe52f86168ada22b7a37da0342bdb755cff21b50f35522629f0168675ed0b772c47d75747b7107b0f4b6dbdc34e72394a76556ad822799a6497435db031c5d313ca1c9bbce6c8177273e6dffd3c1b203d2995e01e38f7fbcf368f2d37e95de21ed9ecedda050b00caf0b43339057f1f635b1f66a673ba9c81a0403f37d4fc0cedf65df1f8fdf9a828be5ce43b5db31518f6fb0c533eae01d1c1e2862d9b99d85f9a89ac60eb3fe00b1c08c092a8124d30c90f33b468b203931e8ffbf6b3a63ce29a6466662ee87ab8baa1ab1fdc0428047ee3cacb8b6fa636d81363b6fdadb23ed160a1041c0d6ab818b2aa91441576c99feaa7648f15142c0a8f5bb155a0807172c06ac89b2934d46838868d50ee9f05640e21169f9c10988faac7a4b00ae6b58b6679a78d45cdd0850184a66f8e0413e3b171a6bd5c15395310ab702be0c9a77894667ad6746fe6fb3a119e1a3c2a6548b17abb961cc97ea355845949a87909229d6125d0cb3255bbee43998b41708799558e9a4e85f4aaabed7d41012663b053f4e7f649231c834f2b7e0a6a478e0e13e35b2dbaf626eafecba6834a7b14e1356bcfb9419a615071d36925168630abea2493e05a32c2cf788248ea5f950cae87a31ea62ce9355ee7c62142d65f97f334a63d4f9f1032c6af4a2c1362ef251bf11c7d616dbc0925d3552d5e5a8014909fed5ce55a1d0501b00a3a88efc218229ef2424f7169ec322ae3b692e4294bd04d8fdb23bef6a36106c8a9f425124d07bf68a2ee5fa1b4e926f54613ec06db27dda9c0bb4e54b48cb2d30347488a176aabfa498000f68634f33889ee5f8c94cbd0e74dba7911aacdae32fbb166df46585bca38b030b242acbefc17a740b54d47b0e5c41263e09f2a7fa156f8a1151a8052c0caa8fe61942e45790bd7e2bc1895a235b5545e7f7994f1e938eb422379d0e28e58d24ab60324ad376f06e9cad03f5d1ec4e132760b38537ee2e76d1f46f6ebb942cede85716a07a6996fe0bf5515f08b266901716276da039e80598c52502c295c2a37b08541f8a47f38247680be20d82f1454305e590067f8d3779df2504e9d947c03119ba84ff0505cc41e7e507909bb5c9e0dfb81043858dc83bb2e3217707e6625b8dc4215547560e0cc6f68dc66eafa3c218e8c93e90f4aa169ee1568204f208fdd87c42f21eca5fad3925879029a83a6db80fc2ab067a7ea33f8bf60699b204ea284fea4e6def08375842f08543ee1026e481ce890eed94df83da584404ba75515018865461c659e8ff76cabe717a56f7620f16bacdd93f38097f85ef980911e411992c05167b3509a667ccf9b3ca9f49db2cf971afacbee7a8e7f0698ce14d6b39a6d86cf0267d5bcce981cbd805db8841fb6c3b2a465e3b06813a7b0b7080344b6f9df2141390422584867d276ce86c0f898d6beebc7eec3ccc40142be45c4718f506a25469b1186e3b457fbe20b57f948b9d70abb56305f04f0a41a27171272be376dba7844578c1b9be6e82c7bc03adf342dc1caefd7b82de0a3057c708001ca182d861d095311ea1ec7e7387cae6147a38cf78c6b4c91dea1c75ba55172282f99cc72c4c153fa879de0584003e4aa34f694f3e4583dcb13d2f563f8fe91155863edbab24f398fce3f36fb9b70ee29df78153e170c290ee9de1cda4b3e56bec830fd5e07a77f7d7e605e9362555eb7d30544f71d48da498bd7d556057966446d58310f3d180b95c2ad7b36243760b2a26f048622112f3c74ff46aeac8eff399f0700dd910799a50f8cf1bbc5fb8f835e2a31fc40c11e8e7ff455904132255b8cae0485cc8bc874a1a6ed2f548ce86409ad2ed6474cc8e8e04d3ff3517a8529064aa7129fb424bc92954cb3b20c71a66f5b142b89a53ee8dc5e1815e66e9ebd65dc0242f47384a11a5edd5652d56c83a70daed9159db8bec93f02736ede4cfae1acf1f49968fd7876ef0583fab7ffca83012b74ba7b4eea2f00ac8bbb3891252be9b238fd667ffc6e3e4d0adb003c93dc69edbc08098406c3825b9f4ca95c5164c9c8c33726f31f2f909de934983c1a122b0a22a9d2d8a1707a1a1e597ccda1342ce4d7b3b764eb42ca9a3b02c882a3dbf450a02ad073992fdcdba32bddbf64a214059219ef2d94402a3f8fda32bc5daafa0298a5a4a831c9a17511f01c940724552f02384b7d590666fa0f4055ebfc357a759c540b44de58984a231877b03e7895e00fadaa30d721f48301d9ed32cf7563a842fdd84b5ab277b8991b4a8379599d3d8a20e42c51d85b4f744922652b8175b32e6fed48b4958913437a8331d884604d45ca8836404b7c3730f606a8e52218b13f0aff50df912237e1b21fa7ff197c8283bedc531ef0faade805472fc99e7943dfd6b7c49a1f060f9d4042f05fe1913014a7c7123b720a85d0e2df8af9b0c5784b9dfb679aa2e406c24044f646527ca1930d8f091f9002360283fe539a8e4708a316ad0459bd5f2b56b83e31ea2332cb308a5c74022324310db406dc02e803a5d301103482acffa2a6e752bd6a05a732d58be8d29183d5f9401829e8e83e4444f451c49e922b708e2bcca2abb29672eec8b76f85dea6323f95a60f7915c732ad0a70227b41133767ea6392b91b56c9d06a5357fe5678fca1cf5c41f06d2fc0d202919d8aac1458d277b6b4ba347693b7789f3f81bd62a6c5e12c216e3a6130ab9a9513c189d56a13bae5395734e9541edf32d7a3211cf7190d528e3eeb19f10bde54e8205b9f8efb9285eefe5ffec1522b09575cc0674323fd98ff4af290e49ebfa08406b665d6b10181b78bc72bdbd66b6817517f4a8c9e7cea79852bef301ce96cfad131b7ccd69f6f2cc633f87dcfd5327b12f2fe0c0029148b0cd62fa081e05de8614271f7de78ee4fff948b01c86f5646af15d691b8828fd3c2ed47b9f127522989e899e38b889d9fa3ded932d15ecf1c9d2d8c54ed856a01d3c2db0728aca32aeaf63e900a1cafe35f716fc90f75e599a65b9dffaceeb0206aa0cc241a73ea068032cb12d7d28d4c7da3d05f4e544e8773f446df01fd50ec00d35045b81972a4d85bb65dc9fd068ed017a91ba8922d8ee02b03b86cd1acb86a27c59e6c97d68609351d7537116068ae3ee984677d1ddea27947c44ef74c55d2d94defa47a99a2810379c1bce08b03e01b512bb2b56b633b1d192a6eb5130342ff668567d7d8a97629d2405d67c78e2216adfcc898513b6879a641672e9ecf54d038149f71e04ac294293dae107297b09648fb67355d2b5844a455c2703e3bb91c923d619cd3cbc06231d1ffbe443494f8c2cb9c54a7f385704d7bae0652ae4e79a21534d46c4b9ac32a03bc9e5a12a34999f44a9e408f12cd9545345b62797ab6bdcccd3a86287bc029381616ac8faee8793a29e4fe3a0b5f0ee4b1b9d54e2fc4145cb9c78b443f7a22c3689adb4f9731d13c2df8b2e2d8cbb8efdfae9dadd5ed347c251b3551b8876acdd4525f66596fa30e33e86de04f9fedff154e9fd2f41e2a0296d94ab063d42bd945eba0c12ed61e3365ea574c8a9f0214942b81b39b8866c8f8c9fc723eda643daf4f7892ff6f6327c4be5073eadeb6d6ba1edefe6e7fb8bb9e28bf0141f54db8219161abad124695eef6b32e331380576b4545ba2aa9047b9ccc986d0ce13bc808e0cc57823d3742a5f36bae3350331ff04c851e1b61121918d5541f6c342681230885053cb034fca69713575b2a6d6085865d7fd0c146d016332937ebe6996adbad80f451232a667134e7592240f6f6526ec8399807005c1628f9e7e0b0052fc59c94d32da45ca99e06749b86127e78f0f233e5e57b9a20347dff131b682e4c67c88075c09b5bc5bae30f82026b39b1416ae67ae33bd2ca25a40a0774d449f77afc416f08f118b8ca003cc307ae93ead2749071a3a57cd8f63269da376571783b841152e85886cd53d108e38fd32987ba4e081ecece6af96ab14b77f3f8d232ad5279acdb129b6a33c9f693b3ade9e54e435f4948b5af577bfec153cc3cd06d439ef853b582f5119557f8aa4d484331376a0aed10d054aa1c6e30b0588a5f345339a73e96dce9f09c2da5d791bb20813f5acd496921375cb42ab3f1b790e7d5afbe972840b191e9e60ec39a342198e4c1ec4c271235d1060e1b9f7db0f6d316926e249b761552738eb7e33b14cedcc9822d35322a797848c32ca6c6a9bd8659f32017a9c6edcc44fef817a986bd77cff79c0c2b4f5d3c4a554931409f6bb142d59267fb37846dbe9f643a358f7f876bfcbdcd7c44b0998415753dea341207b8ccb427818d36fad50e09369237b6e53df55f44fc648e2abc8707b696b570a199620fbc281e3793657398744f2d61888796e7ffed48edac73ab9e710464c0f258120f0922df4bbbbcd62f9cd4703a5ce5c3faa2e4253fa776d7ec0cdd448041f3c2ae9d6d63b06fdf73c72dfc537d4e83698c2b994d40a376846631ee9c7791a2e5d4ac604ab38342e9d77f03476c24577188ba656c36e668b7f7c46eaa2236511ae2b18a294fa19d8f515a5bad16dc090e62615ca15a8deb459bc15fed4e1ba9f7feff6d7b99cf9521143f7e72ca2a61bcad5851f271b62fff2393b5662e576b6fe85bcf7bb4cd21d1334bfd0d257edee5cba0f8ed9af47198b3f9931bf0fc9b2c78456af682d3cebae1314e6cc09879541e7bc47cca4fbf1ead130ca74bb4d74d01a4f88795ffc1d7d4dcfe46f77b6edbabb7450526dfef4a1ab8c0e1e2ead50fb67c9777802082173134748dfac309fae6c3fff1d414d8b99c6cebf29f0a968bb02651ce730f347062d02f55727c1c85d389f848bb73f9a4f5bfec1e55165b1fd8941130e6df7d7fce2f1eaa849741dffe1882029e5f909691be7f58f13df20b13d55c3f252b60e48ed7fee9354bc0ce39bb31fb7f695adb72e3fe64696412eb323f2404b18290d39dfe46ddc00aa07af352e019f723a77722280ae021d1af78e4c2f77c489374478f4701849840d0905e669cf011edc2606be36ab3ec44cc1dab88a8afad1fe6e03095cfa21e370e8b1485b226546d3bbcfd6f1afe41470db55a607ac04edb9214a2001cc165707d16db67a1fab30c538026c2ca980dc9e582fc1c25735d4fef3493589052b7467577957b1e3ceb89cead8dfc447fcea6c0b7d153aec8653a8d27972a6098bc4099d6b9c95fb35c59422e20efff76604de17b1500c8c79dc9e624436e6e5fd33118a35771c86c5bdf5f11d4909de9318df3ad7cd44392ca4f27a18c89a587e36596bc61815a53451d56a6538025a9976e15e483e6ae41a61e37e532c47bfc5a7bfbec3d9f57e5f12fc600358472a316bd4ecc64afe58b62bd57d69b90e3a404df80472335199d77c94ddf9e69dbd57ae679fcebc5705f3e680b3d3b0a7f7dce9737ebd9bd568b149c27546950ede172547a633161a7201bd336a0cdf1942424ed19545919ea5abe23d2564886a5afc9496a6e05d11d24ba98e7b48775747c9b430a6d0630bf226e04b507ed1576dfc2e5847949bda9846c6a2b73e5cc24208960c3ff1f824bce0b1ae4320a1ea7622195e6d23ed324e5eb2759fbf40b3429040bf43c4bd17e144c189f29dd9e631916e76441740b178bfe80f12eb42ad5ba55336efe61f44f73404e5a60b02ceb03314e381f3b8cef396c73dbe2f3ab62918ea9e7cfa4622e87f3012e4c3b2fb60c67adbcf48ef3b3dc139779aa9e5d0a7889c78c13e1f0cc9ae531a75e2fc08865c3c1e9f826a3498eaab77d01b3610e83fc535ae416acc5e1d15032bbe58e2b56946ceceb5043121404c6f0bd6f46fcc1e2237a8e4faecef78b575e45c1311bc8ded8688facbbea8cbc67e05435a6e21e540b019b662b0a8b85fcb9a4c9ddba62827850b5858796c25ca293898c3eb9888ecd724e303526f9a1c8fe75d338b881c6d21dfadcebb063e9592f6de4be00fb9a49ccb488c1f7ced2f4db368f256b92677008c13ba612fd1c99bc0e0b13086ef012f45cba33c137bc40c43c60ffc6be8dff46382b8e5bfb4b4990b914a68d920e4e4276624eca106f6c9c283b84f5f3278390bfc5fcc1ff3e28d22c6fc9775ba6b327d1891a4695eb42e1b68a5b43dfe1f62a9be26de60abfa0323ac8e26e918f990f43f89f02ca587ef00caaa4bec567877783541eb3a3c9ceb22d8ca275c0e32857f2c890a38eca6024f44e2ffbaa33834ed22afb72d2cb3f413ee9c9b369f4809dbd9be8fa0a769e65ce20867761368e0a947f24a7188c6845179be563b13ca8e933bb4179a5dadb2df42e6fe11f67bff9c125e22ab4777e418ca7a40033fd9bf32c6ef68cfcf9ca50383274d8f300ae2e4687344a3f66ec2ff54a4f59d447bc96b9e0be248e632380bea687d80fbdd2d6c14bad4deb07625a22c297ee18bdc90017b6a7b7cdeb41f56978e52bb55024768bf9b3b0135841192c69683e3907782c6f4f534467e8dfc318a743ce4b44b4d1173b9289ee579e92918d327594c80ddbb01feee9af7e7c5252ed6e84c868e0951916d847523725daf7977eae34db6458c1628eedb7c8964869de5223029b6ac761158a8b1b15e5411ac3129f28aa4533ceea3431fbd468aa39981b49d8752e957b6988165aba00f184c33216e9370027632074d080f11b94af544da494a196b811b77477eddfb59de66011b8ae82c9dd958c1c33ec19a6fa8c320773ce2cdb1d911d539d6766737baed8648b34408bae19b1d415d588343e6873a640e4a60ff23fbd02aeda62f52b21a827b111f8cf9f3f0d2e0cabd7b92dd5550e8b2876b96129c79e3058171c5bfc80c96f22cf8fb37ffffa23072c603dfa32620478bb0988d369257db9638e94559bc1a2173e66d571310e3d6bcf0bc73945794da3a227cac9029c7a2ca121af82a6b3f19f27506719eb0c063077b69081ed9e886befe23c6f1c36173f060a101030980155971f3968d801063fb70c9678107a8ce469ce15807f13a7dcca837fd54e753172bdc9c260dcb7c68458846d9b62db5378acf4ff915cee8e6a593b55490c58092817823d1a7811c5025de46891a2b1ca66601ac67b3943e1b263acaedebd8d256ffddcc6f09e62f4764cf00162c4e2b79563c875c1da5e838c1a0fe28f1a106fc10efa50aec85e76427e6e71ed987cb6c6097405cea5d7ed7fe8f627ff2ef8664d2f071f1b7f10b1be01fe330186a9c55e191e44108d748513762dcaec9b4eb65e2e874797fefd3cece14c65d1f8c5961445ccc77ba697c1f5b0c34125a514a51439cd0b0cd3fd9835c552c51131b0eb5503950008eeffa217ac6dad9f8ada1671f38f57403023db52fdf975a5a5d80505b43a84a08f82008ed48ce9973ef6ec4d5dd29ec3eaa6a6a137c0b87dde5c1dc66f1cfeeeca2115de002260b20f48232121f75bfbc82a1950f8f8814993282094cc11bb3cd5ff3b72004027ef818109c6e5d1ad6f2c5aa4d4dcee55e5915cf4d6512be1d7093b9879b01249b0e9a40108d10190de52f4833fa6cb096c7f06e60537dbebdc1fa84677d6a7b01939e2778dda2ed67f43bfcebb3a2593b16fd20f2087e2c39cf779544548e366d18054f41c148f954e17e20c152762df888a84a31c951679735477043803c5bb40f883046b7532a8bf1afaf898fbaa70d20613d2ec80c81319a686204d460df92d78279f9ce4afe1d59bfcfaa82265f22ea864dfe40f976adacce3c966c95fdcaf2d29bed5dddfc6c43b683f1a838bef7818eb00b2f58d2d3831490382658877cbf05c7576f3c622d5866555f6b600dbf9e11f03f8efa7594c3867584d00406a6d4266c608806e163ecc8b17d000740e2ebb9befa42d61f89fbbf980700726de2471d3ae135de79cb92da6fa755804c4e9055a0d0b9d27a39d4a3d9e24861e37603bf241ed060780c2300a0d83f2a2495676682f910e60b47390316503a92edad4f27ade959411cf8d67ea97c0e4907836d00f630a88dd91179969ee1fdc375b4d3a26317989c85be0e5aebe61f5a2ae3fdb2613a73d5b017434e28bab5b3b4611e58e8168b80a1bc8868783fc82f3e885c58e3c9be04744efff2dea81d212bba63e16e9ff7d553672e8ff12231d60bbecab8be65724d4fdf01d23c0908a15dab9e29848fa5ccea51d8af7587807df28e10dbc4acb0469284653e244e047596abf0cce6ac24d7042569fc61a960739e17053458c11d5cf6f662475fcaeac4ab113b7ebb0fadd7175e81892a0948cfb7db670f3b45fc56c1e7dd03b56562c5c1a34906d0159c7ab9cbdde6ea1323f3205cc01c57b478cdd564bec7372b36e8411ff965e6de83b122c26546082e8753a27c00e6d63d27b7bd44215ebb2c78c6f49a69364667655f1a9a177acab3d45d3c7bf17209486e373c5526c3fcc3df2e672dad2720e4a407d1375b6dc3de66fd4dc108d36517a0b8237e13d4cf87ed10e41e5b05ee80cbeac39af4e5771c4439a53245b4b6749676b4b5dc61f932c1901fb3feb26bb3f859c85cb013870d023942a4fff45f39106065e7a259bcb80a0e8f1e717b299dcea8cbf0c83a97a89964527ff6e12d2824db7984a2eda31b09b07e29889c66350d779ac27c2ceeb7d2b2c0d38f5293b5a6a9f12520ed9941c5e23820460d405ebd234ef875803d84dbadaea2bf4a54ade418353a5c8bed62743ebe0983cb525371ca0578973737f89535ba12d8eb3c9b21a803e9518fa275a61abeb73eec0f0a7f65a4c50366733ba110ae66f94fbe0fd673dda27cfafb7f607cdb84cfb8c65cea1bd2bf39ce1377a6f3112209295c32921b6277b323225ee8fa81497e6063a64a6da24ecc9e73703b898b3d347c5059b9a930702a65738fcae2ee9cff56a42029430fb35b146487daa1d806c1ae79041df7d9d810ae1a681bb896bb240f2b7d50444e8e53664467d39967ef1919ece055d4b4d1499e398260eb6f06dbb75e6c193a0965eacae9693414ce74c05a20f631c3dbe20683cb2cfc3de0a8e0a78aa89d8a5842dcd7e391543f44a55b54a1f78146e17ee0c40c032dfdbdc7ffd746dce80350cbbca82910e289a9496da6c3c4ee2c8613d9ab4b5a8cc32878e08b7f6b5f312cb08c9a273605ed1cd6efe8666bb18e2ea632e9e44032fd0227ea6a208cdffa6fb87945d13a32f68cac387093bdc337290ea1f194ed2285a6e024f1cfc332d6e3a8637021abf627bc447dc082c0f8878dd15d1721887c27b0cf40602d7c679422a464e785c8e16da5a6f000f0f5f98cfa6ff68874111e9a2a83cee27270430c8a48323831dfdb16e419ec9f0be1b8fa05f553d7e9fcec13648908dc0dfdaeb793d938c0ee7b7ac6745bf78186930d3764ee9c30b3df24902f4a5eefb599d1e0c4eb392d8875f4c047fa0bda3e0ddde8be8ec12b33c7906f5c7d798b1b37b9ee750ffae4231e7eca88d186075fcbb43fd9c3c9a8d70ba582a5eec2c4d93e33e2fe3355a01fd7489e398f35f3812c59f4a784d00f8987da82c4a746c719c6ab40673dfdcfbb38e9b6c77e0f0015c807903aaffddf62bcef26955123a12b41d2a42c23121c7f6793ad50980503a9136670445bd7f39573852c5293ba1f979ed2ae28143a4fc5bd7f23ae46de4bc0ada9d8eb9418f58bca83681968e4490f2a5cffebc529fbe140620c186fe986853075e4271114d8a020f2dd8d21928e9a6c0291bcd5967c7e556f5b811472182274174f80d902610e5631d6d39f03f5ac5f5c7318bd4476f2f4211e225600e2c2ada290901e1eed3a3361737af2eb04a075d6badd0ceb6a963d52b7633d71d1810ec9d805f0b1fed80a65437c071a58991c110542671e5954ea569ee952e1b25d50a65af958b5db7e4bf6005db141e0808cd60483294c75058a6158d83a0c0f72332dcb3b8cb9d64a1ad111958799076b1232338e4208112c08828e81e9f501328b581393000e6306456f6e8c398041780483384c2eb77b4a3a709dbd9c616bf72a41e37aaf26778376481b84cf30ecd3c516057751688624769d71de389c5955a13204f1334e6fb35ca364e661e33f120c8721d03e7f1f53798755e04b43c4b409c08d030544ddcca84f4b44868631783d273d056b88692883e6cd780b84a905bbc6c1ec1dfa90aa17363a6429be288cb565cad16fe726f86468e9835b138621f7c26e62be9e325b7798568f100c7e7ce8615d3be7e2e03cd00f9254530f4b942a8fc683f94a589506bdfe203e909077781ad34e446f7884b87d98fc113e8681e63266fbc5e84b33347cd57f2e8e94982b5036c0cd7dea1b52e4d0c2992542c006d40189f87fc21617142c2997760988cd4d68756cdb50b54ffa6f9100621c8693485d4466928859c605e9f7bd409e4a92f7833517c6aa471900b89602413d141ad40442d922105b5c2aa33d9b6f2be5902550a7fb03556ddbf121dc2258bc065ae855e76b3af901319a5dcef315d1b38531cbd7a42666b6a8e9abaa041da69df04fd3977ebc8a271704d7f634ce8cbd3b76afaa56a75f53a022621c8a9e1d7f06b62152d0de54d39431d790a19b6c0dde500a13990401a68d322b267b8a8cf2a7aada4c81fb3f23441c3d91b8b675c5a41008e5522a07d16c4564f659328569ce9246d17f1274444284f799878ef456ca70ef19519c970a1b61fcd987130be6302e5521c4fb2df79f5c3f1022339be086a09358fb44e41936d5953dc437109b325c8821a27062c8ac3590fe2be6d41d580d8014e11483e652d83954e93eb210205cb9d8ae5cd9f6374d756a3fcd532f1436d9396eced49312505bbafc302f3ebb324be042b0cee2b0bc2ba3c38f5600c2cb3dc9665675f7d6614186d028984808254ce56d5d50c94149aa0d438bc3745f46271d9eb355b9323ff56361c357c3dd16a6888d3efafa6fb364b73d2ae6589ed33fed134ab3450bc3e22e13084e5611935df0e97fe35babbc5d7ed7e5d4f54d9523ffe79e21a7cb38c0003fc2f73f84ee6bdbc4fe22c90ceb52bde9493bd8bd0d048dfa3e2abe194f1a41527ccdcd34769339fba9a73dd8d9b7f9d43e8aec45194986aac6ba0630e5f317f25eb8e8df10f9e5ac0244894bb20e41b8075b8aa828947045630ee18732d62c763d518266974f35898dca6663545da334dcf85668102fd5f7d6f02360d6a4d364b4e4e54952c6be290feefca53627d70f06fd2e1e24bb7bd535153a258b628dac61a49cf86c1f2a6958adee468b9a5dd8eb99cac2ea6d7c93c22a68970d818305fc8809d7870e4f939711218ab0543f58f9af659853eebd844fa9c2f4bbd7f6840fcb3622645cb9f3afc688baf614d75f2900760d93f390e0a67ccc0ce20f372420f2925ee52e9ab391adec22266667e2b7d812473e7baf94b841f9ff6f15d1f58cd5a1ad25e40ec4d7ac5ec18cadfdd3a968a6c124f111b4c2bb010bad6ee2c943c3026de622633829fabdd8c6c6d22c5e2a335a2a255a36b49432cfc78e4927b2142a7d9ffa75de3a93e084ae3b01890b7ce63b319351ff28a2b46fd63da7bea1b61edcf044b25d23698845005009a2febf21d095da9743f725dbab98ba173a92084b8868a706f720f2a6b457ba23a2da06987b6e6cc7e5ff97c27542095c6c51f44a08f5a9d09dab3b29df7d3a877240725a261b60fe5bc79b1abef6362ceda008d31293f0e2c18fa9cb933a601b334a87c3b0ab89144c1f33c30e6d9e75ce18ac925ff7efa04cf234f63e8a6668759d8354f30ef575f3cea84540c8f30baa1457149cf5d6602259dbcb67ee37a41f486ac5c8593fd6bb04b0a7a215a38caa1ff23b0087bb1aad519552c1e0320d07bf62fdc2674b248b81788568433a745e892a086382e5471263dbd6b86f68797990d0e967cdf8c7ea0074f4fecd63fec5350a635d6054f9bb42267dda37d3d48f53f8f6b5faaf1e3f02b985b7edc36409ff02ad3ff0219e2cf6bf398661136076ce9237356b9b0145e20a90f624e7df414f39e21b6c8122ab02bc0012c616f058c37b2b31f2da9e3339f5d29917a01fd463ccf733e8916ef63f922523589e6093451e5aa80ec91a94f8a71590cac13ef6733bd300dd1e57b5b2aa85b8d8210f5ed86bb6ba75af8583b1957c23bf36e040902d3215feb313f05bd4ef8e3f2ff6beac3c98bae556e7dc7a2e6fb3d087d01fa2f36774b9ce8ad96de94597e6e44dd5a84cbe5e6dc30a6ad59cfe8a4af28bcd8f3ce835b701430282e8b6544c4267347546ee7b49f6fd30246ceb92196c504aeedd3fbe383e38d7db3b103141229bc2b80f19c381e009c5640f9fbf862a92c7ed1fff3d6831c2119d3d16bf9f64f27b2cf49c64063ed92a3164c86c10b88bf10ff32742121d41573897928937a4515236e4f3a2d28c725388a4a20320829aa9346e28a74116cfe8a357ce03d144f2f22a8a463b2d7e0d14bb74ade3d33d5d90bcc09c000fbddb723720f4263574b9d48512a4c151d8f0a541eb01425a8c2e84d24babb124cd9676462f9124c2049aa236c70662322135e6abf7d356177ee465f418380b0e19c47187c0cad09820914e821cbacc4cd1931dcc2c7218709e55538bfe6686e6d943aa3d018deb21753c88653cc283e1f83a8cedd91e93b1939f512968c8d147fcbb29f14a2cc73e413cb0085551a51d7a1922fd227e8dd0e500b0cc114caef86cd627f1127cd933dcfd35cc4b22d3e884e35584381c980fa3d8267d090917b30f41f5fdd53746c5963f606dd4e1f0d2c285106ecbc75798d140c5100e7088b3acf693ecd5be0a7c5bafc5531969065fd8afbbe88869247d88732f5f75785d7e8f93d8b78662ee2f002a6c0db2732735a0111c4a8bc6b549dc28847f3421c319071ecf549225f44ad1787ab86725b86a800f2c74540ab540abfb23844560b50a2e374a8fbd56e3746bd19fee11918fa4baf9c2f17b1c8e31299daffbcc06398962d5f62502c40428fe748586c289952d1fed921cdc50067c7ec255bdb630d9b74eadc52ec2094c449190e11a05e3c2a78825788926af99f73d5356d1b295759a10dfdc6409bb42fa0f305c102194096b7626a60dc0feef70dd9096efe7ac6e3ca89c2beb6a74c9b17d6d8c7bfb6418f61405bf87454628bac2922318b9eaa8bc01643049565b835bb3da106fbbe3f9538b2759d720f8ed3365d11a1ef71c6cd177df512299a74fbc402d3d8bcfdfbe8e47c80b2882b4d22085a94a11bc0bc9c543fba06706ca713a81fc3f02670b9310e1a23c47929cb51a66640cefac68d62785cc5d208a705d16262769b03a9d20c08f21b53ae305890f70cdc9c012b573d8c802385c4c7746e8670c1ddfb13242ce00e18967edc1d9a452f04d27d4651e781ccd7984d6832cc80ccd005f9f7daab041e8ca2f8cf8923875c7be325416237f1b3c09d0bee860da25952b94d280463785f8bb8758b60f245aec503b587b396e8f825998aea49fb499d735f8e5ff4deae86e30da0d72b30027d6370c5a2102bb0c848678b6564612069a3b46f73407834a61b0a83f39fcfd651f0f78d13cabf7672ed5e676e45c2aa9a7d31930fc9e9805de7ba14e00f2490b0e7ce3be29c6ff2a4384ae6fb4fb9036fe6774c54fe25e9a0dc2b1d664ce04b8518786c2ccc4dcee0717d8d85ea9569f069118888c9b3cdcb4719b33bc349221f256bf68e6001b300af50ccce09207cee7efe8b3294d9942eb81d02db77627e9aa92951e2b853f3ba44f6aa1ed2aeae68b6d90fc9ebf086829ef619ca04b104504a07eec33b2919849062bf2938353ddbf839023becfbcf9ef66ee9ffb34ca08143c7a1c22348cca9c8e2c04e437cd677c68d171d8304eca8b8c252e3ef182e5feb03620573bb153ec5f0970f4c07ac27eba140a0dcf035dd322374aa062863c30ed24384075328fa4d9b54977c48eb8c9e3288dca507eef371fbe8baff62f0edddcc81c909664f0f696ee40c8ed246f23df0d438009730f73984ae51068a51772b9f497c2b598fdf08c0e04c5b0a6d74d5943e65a35f8f134989fc23f287c6329e13d6333744234a85a78297483eb15db7078dbc0e74044b8c4573b15195ba3cf6a1bf325ce35123e713024836f66004a9750935036bc788a51e3ae8c9aa4223b576d6bf7149d26fd155b23ec9d7d783040cff7be1809dfa860cf6543829469aab2b6a2221634d3d01863771e410cc6b408c14f7c9741248181764aca57369d8b764924b66aedb334e232ba341ea173b819d1e511885a29765a571132107120d8e7b31f8fbdf9612450221363e01f520ea224b9297b198e287da113d9ae14b0af18387e705b0a1bcb9c9650fc823bf88b1e061e95a17073d6d24ee455e93537bb5b2d4c705e929e2c36b643c7c6d673cb115675772d81397b2dc4f58aac7c55c21301f540102b725a900b563214b3e93e3110b3850eed177134ff61579dc982f4780e09bed18760c1fcade920def678f9fa0b2401baa92b24ec6960ab35d7f474eb7a7f68bb13582a233bcbafbede6a2928b1d8ae072435190a560aa3e06380d4efc65f9dcd206c8c2129d04abe129232b12ccf11f109920705b4891b3f49d5a46a312d6d24ca011d54269afdfc588040ad9c80c43aac237b06aeb7f056db6974e3f19706ef2e8d7025a5ea371b897c1397eb413aebdf3ff64bc9fcadad2f75b7060acc70e3aee29e8b894f301cd5da54d2487325f2107b7974be3c3b754d11d8c5daa3492d41121d53b110692283695763b14e53857972c9fd1441370791cd47882abcd02ac48e7b1f23c80d03952c5d0e54105f52211c0ac8ace1ec600782986d7d4adead414186698f29ae8ff40dd064eb8a377612059d216ccc75513218fddc277424994648a471b3aa2f9818fde537a208ab7f9723617e34bd5404b85f15f993cf899a14be32fc2dc0509301c4eda856cc39219ec2a160a06cfd0d44e71873e55139ab86e1e9ca7c5318f38aa4a53f6541fa726c3e9ad03899d2c08edc9cc92e01a364ac75086bbd207507ab5a8c36cfce8cafec8c347ea83440874c41b92dfd26461b31866947037fe692094234aca448a6974837e4a20ef7638b57db246b83594d96b8ee543412bec5611d12950f2175671ac25929c615f24d4bf0736f87e2b7176d7b75572099681128073bb2cb057ab0e0947259281a134921dc55fafff29657ac12b68cd90b1e85792f954bba3bf92392e438096249a78e122a064f13559a793ae068b8b6825d010019170e8b451750b68e59754ad601b05c5e1b3e75cd24e30263bf6e5cea56ab3357ca062952e6f4a6c9fa95febf1d48afc8bcf72bfda0a752dcc6f772a86afd0d11ffa051fbc37de7d0d1b1350793a7366ab677df39d402231b8608de795fc81b2ac6127fab16f69ed3085d1db3680ca7be0c7297728bc3393704825fff4c0af6d1eedc176f89feee93d7f4e9decac2e3050c0f2a54233c6e89509b8ca28a696363008a92f65aea84d401b88ba66c8e247e79654a6b8dd2c019b84d42b0d8adfbd07863fed735811fcbe560c3f9104ca9df987b66806c8b9d04f54cd30cefd72c5c6bbeeb887c57d8a91d51a4a542b931a9e13cd33a0f2d97f539014978eb847aee9af51f644bb9005f7467620ad2a99641f01a8b9397e85ac9439a3cd7a035cece962040c34afd9315ad686350d727be987cc4f02140b020e1a7583b68146e91832d831d34b4ff6f098c373670b02326d861404833e26d941a729cfd2ccac12e525359edf6b6dfd915ecdc96e4e4c7aaabe649cc62604dbd678a713abe14d8e8b8f21552330c91e22a199008833a9ecf5815e0123a78fc3fc1bcd38bb0b178eeb2819c46f6ee46f5c75047603638ea6963a25808e12ce0adaca65a8d5b5007d9890ad33b5f7cc36bd222ef32d47822a13763ab2fb6945eb5dd8129a4f70b70d766203379c97c778a183dca33ba01f04f2fe25ab1ef6a003708cac8f4ac17290a587151af02975ec01e52a22900e81028082b6b21e97a105e136a7c684d585ec04168e20e82adba856fcdd2fd6bec05d094fa0b38ad1f27eaecdb0f88045accea0ef9be0eeacc62b01cb1d09648e0912e65d5c3bccbff1626b8d7ab67ba07ffa620eb81937abea693824c7154eabcb394d42e15856649c772158a3674e1c3a87182d6674a01d02e705496a44dbfaa5a839fbf7b718137259e566d5c7e20dedfce52065db565acefa1e165b199d5d110344b6f8b87ca5120e7de80322063d3160a48123c6870e6131a0a459b17aae1a0e9e37ab71809c8bd5d54e784e6506321e8ff0e235e102f85c69d51c3300a05078c2d70dd796d125776ef9f058e2c222b38765491d84f0cdcc9dcd79b81a8fc2a6c9f68839adc9185efcd066b67fd47178411712f1fd91957e968e7d54c1e088906742da23dd7e4660c2350217dab10433c5755d1a985c9d9ad64cfdaf643797be08ff20ab2e3141143f58a8981fc30818d79203feb50a60b03c7a516e18dca50c56335699ec55ebff3b73edf663e89c1e891bed75bae1762fe9d0b9ba5694c7d0767d26668767e6697f98063d1752b286884e92b5a87d1faf152d709e7f05b2ab33fd85cad1f5dbf1a763434f154f0e90e6c8618b3e9564219ed538ba73d6a12bb7a9ee93c024a3b9ffaa88d759d08a7d969a266496ab6a3843324312c729628606b53238cde37331a07912de257b370aa2f7922880ddf493a39a9ae34cc6cf823516c56cb300c576bab9feab485aa9c2c1820c0dfa88ad30b177e265df15d678022c09fd42bf046d11dc5fc3e6c858d9aff356dd9e987fa0c0da45bae76e550551906cf7aba007044daa7de1e78c6d4613a8b201bb84590fdba30b151c57b956a45777a24c2820b867df812fefc1d8e1bdda49ea7d48bf444e17e1c4e8869c7a61fa426d24e687309e8db7f29ea132c61cbe31ca82f45872f4e0c95eb6af687b5bdbc6b48b8f7b94cb2f671f6b8ef5c9878828fc0f86d6a04642f01a884e29d73b3e15a937d4c50fc4fb17c86a9e7f40f53c03b486bd2c3dbef36737ff0696cf3198cf12ae9ed72c0203df6be2c713dcccc38228f480928e6ac151068b9dfd99c07b6a7c5b6003d7160abae2efa342b275805ec21fe2f50fde0145184b517006609d4de7cfe3644608904266303cf051200f21f8e00ae698d6561f7e808d202b080d0ad0775a345ee32640251fdd79409b6516441c9314ef46ced8042452a2e062073bcbb56c1b2b81deaad5183c02a2727f18ba74d99d67c02b32685ed66a99cbef11a04fcd7c42018542baa16db51adb8e768aab9a58240888337a10f3317c0a0a8d4f9a8d39dd41ffcea1071f5ad85772b13f671424c8d13e6882d7c2ec28e495bd522893ee6df1f00997729dea790dc29c39b5f6b46103e1b75c95dcbce3e6f0b47642a0d083512302763755590955bb85640fb3cba4618e76c045b26d100c5c574bc3ab7ae063e4bc8074d19aea4e1983e73baf5040118ccc3fbb21731ec029ace746918ac581bc81a89e31050c461946f953d233d74d09b5b1ebbc7dd76c525646b4d80363c05a58042da678a707625739d3dacaa21dca20e4d334a738ece20f3b03b787ee2ace038f2f13a7ca6e7e57a78d18bdbb42fb9662ec1a865ecb03ffbadf853b0104879fcd621e5253309d2f480efb438cae7743e37948061772dd5949caf1195e482b9beac71071423a9a6fe96f8c7b955c6c75b93395b4120a3d7bab218646151877f4a3ef54b8d682d870d22af2c45f5254169b7c335fc76cb3e80e5c5c59dcf119f31d5b32ba04a3a7a2f3cad0dd2c84d03a4d35ed64328ff91a2259cd14cce032e69e876135f23faf86c704c839672c12a92f56c39f51993f1c39a3fedf97ab3e1c2d7ed717ff9a786b794730a3dc49f94466b06214a06dd674d1d69d427648c9467e2d369d2e310c6119a2ddebfa5dafddecdc7890bf3e5563dcf4eba69fa913711aa629e62980e6b286df06593c4f7c4ae2a620de84dedce1133ffcccfdbcc7f7104023ce3005f015ef4d80c859c4c4c839c0e36808eef48d2da465f40d99aab271613640e7bb68e1f41f847f2fcae703da25ecb0cd1e498125301beca1cbaf85e8fa1a9d5f82d011130c54977dd7c72897e12328b4de38ea55f76626b31c26385b5b31c1a55dc35676b9826bd07556569ad0d7fa3f211832be04e615a08bf2329d99e15a493d0b5d00d631943ca89c4ed08fe2685079904507fabca750ec903f33becc19e52d724d188600d78e3dda625aa150bd622843d22e308305ce0d6077375f7946ffe66012a2c18b1bcf72ff4afdde6ea323a386b44860c28be72b1c62b7a1fe269d5b91116e3543bc6daba8ede674adec9602052921f7ca07197b2f7514207287b8496b9e39af4ec463f39974d5cb96795277072ad8302dd799a0745db0f31ea42d0c9290c2c9c6c8385f908aca77cb939db2c629fe1280706b8d89aa3946c2cb25ddfbe9bdb692e297d2e834804c80e1decf1c1cf1baf16f6367ade547e5e9f10b8dadeeedd0c253bbe2c4d86cbaf001b1ff2ac85ec87a390946b057e6fab9ebc6fa005acad33aa6e987d599f2414800d61ff4b7df6080daef5bf0964b687f78d893de3e03caff2ffa5690a66a12d8e39eadade922e78f5de866cde41c4553577431279702e1c6942a6399db156496313c1c97615658818ccbe9607719d678ebc549f37163276e8f2b28001408dce261348653963ca36bbbe14aa845940cb7aebea51de290bb178af9e34b8b61699776b47b482a77a1b1b3c114c50ef6ce15b0a67aae1ddf0c9ebf396a5d74c6070fe654eb4f0808670978ece7d13e6a5cfdf4734780670cb92dd37d6de1767be83536c01e43069fd6f1e9c764a6d6a928e24181ff06f46089ac9b0de828f55e60dca0ee2f3a71d030ed3421e5965e93987373668c7e390a39322878f60f476e626f242de7ef2b8ee034b085fae664ca81b0a6aa06688ae6f7393005ff3313064160841d32e11dcac4fc4dae6a9c4b42fbef70dbb79ccf07fb729747dc8bc9b1d025f8b7600612118a47e689f050bd097bddeee947bf8819b6c6ce404d1dc348e4e43021e272b9dc46677932df34ca88a32f802f0df72cf03183e3baaff9dbe3334845472030e405be59b4b1bb644867daf85f3a7b5b576f007863e94db95398e9f49d0e77b28c4f21221061978cd1db2bbf59dbaed686dc3b2c550ab16138bf2807bef746abf027f816200c7a8cbfd1de262a966c0a684726ae911031f121daedb2e4a6e006946be26ed4c90fb92a01550a75abc51c66f314149837bd88fbf649ffff674fffa3d3ccdc50cc68f8640e95b294866c79f76a4630e5b6b84f64a1492f811691932f85fc8ea38ed6115325cc7d19171a907f2e62c52e2d1da3ae152b056a8caa186855ea731be1dfc7d2f0642c0ec18eb2fc207600593c479a2478088d29b8a656b740893d6307cf06d08e36ed21cb46b49e15adae45b264888d6495eadc83d5ee510febae65a3b6bd00bcf04ff7960f40b5dffecccb7d22ddb2272d72374926f78bfb52c94b5be0244f02396ec5701d10f9ebdb0d2c3222e72e10c6d7a10d80514e5811b7dc06d66947a0d1685c999d18100a7fe54f56e3527d1d1a829712826f3fe32bb19ef95a4694c8e60248a81baf8ccbb3a7295e549ed4816b6629394e06cc1252109a7204e4c6d329ec01c218caa6634525f0b808ca630e42a98f896df3fbd51ae909043a053d48a701317ae3a7515e2b4e900fdd36f40da0a5b41c559574f69fb81efd8a41c3342efd5194151095c5340a2a3d4aef3bb551f40e79353fd130492a82a004fcbaa729a8f9a07a9aa8d02db838291fca05c61948e926b7edf0ad4b5df83a7774d0c4c9a8ae52f685c96c4475e1191bdb23902b6a3546167f2449b3cb6c88fe11639240ff0b1620b5784e3a6be8a9c36a1ba823b7480105bf1d1ada953d339635ecba3f968ac27ed95b4f329cadf027b0664048c1304316fc7422bac4c38e09ab2ded02cadc00127c5d843726d7526ebf10c52e3f87240fe4d4ad87e32b23cbc05ecaa7b88ee7dd6c4027372807c44c124affb35cc122cf7451f52709c1828e985050ee96c267d7529c524ebca1afefe2ce56bc4d20d62918c2cac6b1364f593050fb371a8b83f382468e83be33369fe6ddc72453eabdd7ec4dde185ebf17a07e15688eec4eef1e00e498d4d0ff5bceb76cce825b861b52e84d847a88e8806ccf30b4ad424b0314f57caac24972d98f17b63688e22cc674ff4539cb860ac62b98bc6284829dfb8adfa7437f88bb0c3ff495a689129e1fa857c8f5870410f2658ef4f245d1d6a9f57e595ae13e167e7b3ad46779bee93376ca8307f00afb69b8fd7faf8ce15b30e11c427c01267e585e575d2c15101d97a55debebf7697dd42dae55b86424dd6ba02450607a11536f275d8dca6050bfb1a8d9fb55100945cc4a15593e58d91b79f1923ebba2bd3b5b6a2f42b4424f628c39a366b3d79db39e0989995f2042b23fdaa3d8aaee58e44036dc48b10f4b43275a354f7878c08f985581c2be504a56280e47d067017bcc31648b1cba3f72bec1de05ae79eba0b0668b06cd724f658f06492983d9de519fdb311506de798e14f1a0b2b39f960714535c36c564b4176e0e0c469e176941ba697da3f68c7ea49c6ce01681617b49612c0a5e76adc7e33316491e54057922894bd22ca0e8e8763f52d0154cb0f581dd4291bc1feb0ce0b4fbf2883808569d9d8d7b55118c1fbf332648f57bc39d55a1af1678bda7e05ec06b40b234e0d83d6a0db1c63b81479ffe54d8870ae69d2381bf1fa4e1dfaccf3317408008ee4ab238e9707744ff1cfe72cda6952a0c6c16a1d552c5855ca1b08769b0e0d3d7052b21e1174dc9f9f3c748bedb1e94a9c9bf04aa5b1fd4e021d7179e8527b49d4f07ff9bba9d89343d4263419dfa848d319c071b87a94e732434f0d1a58a50e056b049387db0255028307a033d79b7d966509a5b74ac8f25fc850709fe21d2acf4ec0a8c43e2ba5f5ca283f3377e4cfb85e89dd71b946b32f2703d7ef1bca5baf42159284e7157e49fdfe7b032e14e5b5764b309a187ff4f1ba727000389b8a3d23508bb7cc305960c3ffd9c94aff1bc847760f72255a311c6f65ae58ddd56046022085d45250a0f0e000fd5d7ac513cc79e95eb2fa48feb993d0488081def1fd8819ae4e3615c89fc31d4fd61b05b0aecf852e3cf07b26c10057529e8944312255c491c2554a8e40daccbb482b6c417539cbb4aa57e2982070050040e4d44bfa6ad5e59246a44ff1c4e081bc78c62e0583b003b9a0ba8afd68193725adc2b26b44fe8272cf05a3df3ffb55eeb9c3ae60fb295c454e1c28b0562dcd6644d3cd057eaa7d7e3b6647d76fe5563a2554e2a5ff58088d57e8ffa0409474d765e990b556be71f66a4adcbf889fc2021dada0f492f1c38a18e95d6ed16cd797c3aff47bca8d77ee5a726ff73a28a65c224332fc1ef3ae9e84d63c8a19271ff512a9ff233353c9e56feff00b68381dc2d4fd55d257ebd4ca96dff25ce803a3ef458803087a5cf21f2a9689f7c3f8896571e155de920e5b52e14da9de829bb4257441762dd2a30820807f230941ccd302cb8610100a44c1fb601e296a787448a17b3bab516d36d2481dc48c44f75629a17233161d02f3be0d5f84c6b736cdf2098d9395f50ed0bcf84ff00375dda667bddafedcb8bbff045f9f4caef6f28fe3e030e6a191140bc3c3fbe4c0080edd2d6c0fdc7e4cd1fffb4090d80d00d09378f15c05142f4f640d2434c5dee84dc3f468d5a9dbc67f9625ecb90fa4c94b35a40a912eab676d0b3bbfbf076a7f2f9d1ee64e41be759f15fd8bc75737fe8dbcc836d8f171ec99e98aca94a942e331ec495b32ae3ae024e495aa95033de6c0b3a02f887aa73d62e7fca6144eb8934fbc279968e4b057ca35e48bf761da4db7c049ce2f7b6006ecee604315bad257f6a3e6499ab02ec066529b848c4c4ad88be071d58f90006c9d786f23a46835ba83f5a084023df73e7d456b080e957e19dbbfeecfe50e4af8c5abd4f8a1beaf295f1d03bb9557f0d6afe6d1add80352c6f6ccd602f4fe8f2a2f2323700707b851fad1c69e8b35eff2f8e9e0850e2d43ecf31d5cfb9b99ecab328a36626e362519968ab016e5abf68b938be4df3a1a504be20677f9c35846ddd65cbf281b95800205ebbdc8389a853d92f8337535cfd8a239b21cb452f664dd08ef82bf66f5223aaaa6970a36bf4eab3a956e2a11f7abb61e19ede3313a2281851691edcff173833f47eb19683631442f1f6e5df175576a203bdc35b30947629b35de0fc4a71d2efaff9f0aa80454128e6ec05cc29f3834e42ee9bb6b08ca0e86e87589c10da8590bd0893d51850f1af73c50ff7835105f1071c14a3ff22a915beed7cb16c15788405462a118c737f1dd3f57ab45447b611768bd26e023fa1dbbb8a5f8a8b99f53f15b462832e59165353f7e0d66c9a6b5b12cf3856a3dbc6dd38905178d820c61bb4580abae24cddf93a0ba3a4e24cd21b55f5507948fba0f65fa92385983524141fe50b21335ad960e895dc590a456e8a7f42ce455fe92ab42109f7679cc0569083c69dee5896e225f0d220245e13671a2150f3190a44a17648804dd12c1289a96e2854951417c884bd06a8cb285869b8d8493f59b6ef84f726e7fc4d643aad264e1b4ced3195497e3c15f82e7e239738164a81890a40a48b4f4117461a6a2400cb9ff1ad508f497f4e64bb8be464850530cb0b6cd6d92e6719fb6cd19970938f5c7351db50bd327630cc6ac6a9ec42285fb64d9808eb7113a7e1dac3e5a23c919ccea8d99156119ea4405a46c4bfddf433312810908fd243758c6dd6077b2ead3b990984124c7c3c17b5957e1b5d16735b78fbbc462dcc53c12525223bae7b89e90031bd721097a52f9c6e5430a0abc05fd0ede0d0e4c90744c561a955e6443447298d12f17405649be6c1a23aacf7583686cff57e73e350827140b6cfd5d52253b048ede3f543049442f15a98dd2edefea4d863dcddfb6215ddc9ffa9f9cd9d93c0a71a72793247da337f081ad55954cf09dcaa7b7c9dcf0f751be4696efcb5dd39f8e887fbe38a4cd8fcb5aac22c576acd49b8ccf52ca2cca10cf0debe0c56609c21beabf7a38272f415920e0a350f2e76c3e6c38ca391598dd6e4d46ecdc2f1f6ef0fdd431747f4d261b6400c5ba069b3c7845a4c1a91edc52cc4544214d96279619751630f29853541f0d3acb8ea0b3694ccf49bbc55167d4c373e609083100838b2bf46b5d3648322b402ca7e21be477ab67377a01eecea858cb0631b6bc13b2941229503fcadb9101fd264fa54b8bb95bbdf0042fac45e942e3cf850fa59302e3ad7c437763841811e2270f55fa911200e42afef1a560c05a5e6fb840b4a225d50feb4e71956aef20dff7f07beef6a16549481ca2831057c89393ede21b9fc86c996c7efdce636e096ed6001a07dbea211caee62c7eed86d8f5b568e0f36771bc054f95b235ddff665a5d408db4d89d5556016322251a1aa0692410daf902970cee99c73d401106bb6ff366ae00bf2836c71cac4fb62b3270bd6cca657ec7676886f44f2f5907c07c3b542e3edf56ca6bddcf378cf708eab7c27be16405f9449ce476fb6cbed2f0d322208abfc4be997bb8e4774b0a381c39756ec12e3b99cf8cf7c8a52378876e1d107853010087cfb82ac6869a907b289d1da82e0a23d2c94f7d134c2d4a54fab5e1443289afa4e5490a273e1a04e6c60a7f32bfa8e5cae475383eac09453eba2f178410f564dc2996d0b90a129c17e15cd1924fad87c1d88bc79e2c67d1c47f915ff3d4c6192f9117e058a617703e2e30bb4083476d2320c785d7bae1868590e52f3065cfde2b491060807439ed3a7b8199e7e3f08aa56309b93c1de8fd49177cf1c6c12fbbef2f044bb4490ed9b0756e700135ba1262346ebc17785b5aa814afbaed5f6b7831c92dfb2451fa1e265614826f28c5116a2a6797b373eebaa7405314c94feb9c3f1e7671bf0b198e695c68d1dca9d6d03a64d3cf3839b404da222d8b1f2175e41a344fd7346687040813330518a1816afa97bd0c1e98469df5fa72c14694739bc8b90e6ad71aa1f924026e6c764d94dddbf1bdae6f5cb86c908126002b62361a53358a2047138eff76d5bb77b6c0c3de885868b3c2e16da3cbbe44f2d14cc2d3ba6d06cdf1b5a0742b5549a19ce68b4f21b7eceb1d08d1aab991dd392c281162de97174c04069fb47b1ca599700a19bd4d61a61f26df0fed058c7b1044090d0a24c1d6fc0b683ee66c444cc4fa8c1cc573e4e01edff670e8e1264e1b05d87a7823d1fd608053da3cf0c6c725300bbf4c9d98431abdd7dc4dbd577f2ef3274041bf60ef4a721f8fb13e5f7318b8b7e5903c6d39cbbd9ee611860d23b419b8a8f27f89718cbcd70f6528724b46bb2152ec33b02c4e6323b324c320d9f8d96c63d7c3070295b7042b8e0c1d122f27fc561f0d7a1dcfb2c44c2e9e017ddbd72ff1e72d10126d9ed9d9720487e5f0d5f2847ebe9a7c70fcd7fb8f116bb5f7250ee56c798d938e21c56098b595f56257544ab08fc98f8afac26a514573b254c83e4fd9b9283d0631e1565a88bcc3d83fde42c191a5900d81ff1670624272e4991d610426706c59b3619108129ff8bd79c7592f0475c5e058e3fc4120e541050aba83ac42f719c87ec126b8127867f60a81175b4c01dd0025e8215b7b3f9c768d80de82ded59490b660d11299288749e54a580f900eb69951580f9f4acdc723711290162eec45ad68d752b7e16d30311b329580e5a0e790e42fc7fad155d99aa1f20ccf08331febf166d129571d726be68b0ce0f64f0810f7ef0c14b0f54d083b107303ce0010f88b078e0c3ffd7121dc2e8c5d3d3d989f02e754ff710baeaa889f9d4ad793657e5a56f783064073ad8010376e0a5e6d65ad5b7e639dd22e6048d392a1a547c4dd1d8c146b885081c3458685cff5d073e781ab252394db968a89c501d37493b8aac26b9c2465867170da1b89357c528d9719f91c1a96d7473d50e06f9f46c15cda5750d1fbaf065aa52a71487a70b89cda54447675c44e28ba69f9944a19cbc5052fcb95215a741612aa71cb446e38d52a27399658957544e7dca557dae7a3a5d3cbdb9eaeefbe62a710ab4530e05a8074892e1b42171521cea9d0ee1dd553827c5618a431b9b9e237da7c8a010a3f8a70c2dfe6b2dc9545592a9aa8c98df41907d1371fe2d35a47b8889730b0d3eec7041937f1f5fb4200e14725a00821650f19f42512dd043429369480b3832e2a8ab14c5271960543288d06448b312c9d8810c1ab2c8e8660c32fe4f5468a69caeeaa3f718ded7317e5c6294c1c5a8220626c68faf160bd0f87f1664f1ff9b053fbf12af9c304c2b0c302a668581faff1e86ccff3fb6c2f8af9d04a38c1a04c695af609cfec1f8f12b3841d73a9a0c2d1590c052c1142a38800a62480196bf6acab91354c5573d574d81510a74f8228d2f96f8c2e68bcc0b3552680d5a7bcd75ea5e54f162077701832e8c387d17297041028b8b27b848b2c51b55733e7475b2f7212b5ceed3a9bcb94ea70b9f2e7cfa6c416ec1a1c00e14c060778e3b0a1060a1e0090afeeb1e2a3169aa2e2d4aa005154b8b1d3bac1388e004526ac7d7cc29ede44eef64e73cd70bdda98a73a3f4b23992379453c7a82897c9e4a45137318979ae5a637233ef6a924326d6e045f303d6d3cccf45a32373ba4e3aa7d34fcd65ead78c2873d57ecd6099abeeaa73d5ad4954ef2255a69326535f8d9d4c7127d2bbab70cd55b1aa73f2dae8cd49ef144a13ca9ca49c4e33e1452345e674758c3af59ec9a24b9b644a9af84ca53dc8490e47b7505f6123f389b94f9f2193a33310e1bfc700c4d3e9ea2a546a64c808d1dee7a9a7c29307b6f04068050cac20c38a20acc8a9028f2a58504512550c7df5b94ca7b4ab4e578de974ba6aea0aa7f6a9ce9c46bed17e9ac1283e656ad28ea67b680741029d3a2aadab131e796aaa52cccbb4a798f372a7174f4d2b14932579a4cd53dfa88c73aacf129d25681daae055f1137417f9c0f086cfd795a879ba6778649a9cae9a9aba4d945f28d3e9dae869668647a6c9458373d168bc5132a7cb942232c9f242650c5e3906e0e97d8b73d5646badc86432997a788b4c26f2c435e95b17f881f26c258551ff3fbc15d6143e684545ca334586e489a7c02e5397e28ece7ffe7bf44841c593384d77bfa4d87929844471c7ff35258a321e33a320e2df00517051c444f1e32f9acb84e4a2124eb1401916b8d22d0b24790b08a002586a11eeba024ffcd754755a1520ff6f708a954091e5eb6582b5eb5d545eb8ebfcdc0c19794f49a36eee9c8efaf4d4dc290b54e05170b1de47eaa3fb7826da7091a374e2e7df09eb840f2436d765ea5613693461c5914b46c8654a3b2ecd26524dc56a224a13492e2442a8340180ff9e92628844c8156a139327384c60f1ff4499973835bd46efdd6b4c16132e989cb49640fdd7ade8e269d94d8c2e11e4ff52620cbd77d625576288cba484f7ff427092b8238927922092040c1400c324319a561353e0a400f65fafdcf1e89527ae3441628eff9aaace94bc6890b8ae1a249070f93a012cd704365027a0800958a309fc904019507c7eae239c92c0139704bcff97408f0096bfae2b0267046a308f68c21156e0fea4a6e9063ae2e7bff6917723ee30e28a360243f775e2a54a739e254ea09cb8368244b315cb4a93d44a1093a3282b5fc58aa1ab4a37f7c9abc8fc4ef7956ea022def8da4db2882abadca5ea028b48928bb8ae2bed1c0258be5e1018e2ebce16047e8e70ea0177880fb042758e34d7039a100147aa3a8798354539c63b95d374776dea17671a31774c629a8eabd1eec9428438feb3b9ea373d8551fcd3555b05444eda7993ebaa45e426572724b59e2ed3c4465c9ba4114781ae4aee534f4d72c83679cd4aac19473e84a3e7a5f373234407847022840fb1972516c98cf2911c32f755fb367711cab12a677eadf01ed29ba7a7bca19cae9ba0ab5f1b9592279b1999d36892246a74a5d23d743acdc8a4bb9ffa0e824c91e9892e21d114d54bcec5d385531ba8933dca7584e5e88923d490499e75a3f8a8c9514c376ac3c888880bc9b5da44e1c9d390c628ff571eb483207b78f294a8e3209ba023274f738ab620ea5855747e4d2fd2fe3fe543404533a8cef87a3a199d66684e9eca9c5443e8a8724869905a49755214ac8ec67fa5725a6d1ed28e774c269217e18bdc4ea89c4e53b036f145e5749a52cd9b9ec511e6e91ae37429ddab3a6fa16b00d9d8041d21ea3888a8e3740741f67ef23404c209204c206238c3387fb04eef5f4566933c5595f755791eed93e9da624a5e2749442392e24ed3a3dd7136f9062c4ec4572aa7927393046668bea46290324a9534288728a7942b1095802813c9fc40831f9af801f5694aa2fb7475bd2a4f9dcac9e4e40ec34dd471d0357255e61a0795539cc23498dca8b4dc62bf6830cacf72a3d0343c851b3d9d883a0e4a71effb32f71eaf9a53ef55294393925b2c6f2e8d62a30a0442d109ea01737a74ae1e9cdc04813d3e3c974f4f3fa5393ff8f82797200960a1f0406df17548255e2b33f7192aa7d314990bddf57453b7c953e4b512795055765a9a7b67b57938c23c3645f289d660b2a8a6a666c824533c5732081215716a1a6154af4646467c34c925dca77197c944e55473997646ed7675f22ad2f8a219326bd05dc4576989cd7d5e25de68aa5f9ca769899b9cd212a36caec6595be4c865323789a69b48ce8f13224f5625c9338a14d113f3f4004d19c25db5da4420cf8d932557dd4579e45789b16856bd2f6eea6d5e3d7d17719e9a1cd54f6c767267b579e8da54611c8cf3030559d05c28f1087108f1fc8bc624eaebff55784b3c404fed725b220dcec1d79548b3f778a1324973baf61e6f6aef6779a6f03e9d2995780d71a0ab9e64ca7b896e12b58d2e23333b5c462e22d70e17273b92eb24d330dda59199934c6572897388e45aa5bb2c52e4a249bb0a3d9d4e579d39c954e6aa5995bd2635713e9d2e9cea5ca9498ea7d3a973ae4a51b228872b639f5379a664a94add5c7b8f61893b2ef71ec35dee3d86bb63d166ef253a7b0cf75ea283ef910317129ce03f4ca9cc94caf4e1880fd714224c19c19493350548c809421c10fae9a1093da0d1c3103d289142871436a45cf99ff1b94c333226d355735dbbe4e8b5512992ec3332544ea72925992281aeab6e94a75626be5440609aab93178de9ca2e293151dab0a2701105f57546a69326dea58951412b99ab4321038a032c283539b09e68e0c9ce931f61ce4c8e8c8c4f35ba3aae989f7d87ca69954da6b2c439a729a76a04698a6c54d0599637f5e6020a022d203b805c60016d012402e5c8e1040a27413889f9af33325ccb84dad43534bb97e0a542d38b733144f5b293178da942377a4a5523df06080dc082f5f3849f19fc24c0faf97cdab07c6ce003864fca27861e20f4544151920891209f1e22447474d041877a5d57da475e793af20b4a8f108b270b0f1a260f53bcbbcd8ccc91bca1d8f0b8f0a4b0d3cb92a3fcc23815f9c5d39df375764a3f8a2b1175c303161e88f8afa71447c719de63f180e2214845f9752a401b2879758cb20a208202081560051d13e8e4ff8a4a49237e3a5d692f37ba4d941c3acd50f1618a0f32297407dd5c151f6d7363a36d6abd8932c9430add4146bba7891a4da868d204b39a3029a3a298546172faaf2967c2e447dde912349658f14bae54b4c9d7d3e9c24bfe6b2751526ff4079cc1a33f1dad46bc24c99311475dab7277d2e8baea65aa50f2eae45553e80eaa5bf3143e2f93e4a60e3e37d1eee7de44a192ca536d729c19192e6a93e3643235f11039b4baf22af721dbe46793abe2938a446f66421a7e3eb9ea4cdab7887223998bc8c4e8a9aae99abcb94c3a57edbc67857f78d0131427ed2a1e1e9ce2948c92f2219374d2a3a825890b943790c080e408091835e836f9ee16922b902831e54282e45fefcb54a1e8d6256f92e20d147228a4292ef07f838e422ff1f1bf78eab78ed84753a9ad62353522511eeaa91487a9b9bb8dc9a4d31e9e7da33c1b39fd7fb58c605f8dfc5b2635b8653255f98a7253937fcc4b535f627d77dc7c5c7ce67f4d47aecf6e62ce83784a6a302d55bd892ecb1bbd9dfc186ded61f1aaec78522ccfead0f8ef86c8ac2ec97f0db2ba1fffbfc409941e4e8daf7b08c53cb52dee0af773556b4323dbb6f8af5b9537496b4b72ba6852bcf396f60639445e9a15965645c35637d91df5cab0d4a0ecdc560685a776cae6eac0ba51fc574ea676caba25fb84657f6c90ffd36947c1291a23251de537d816ff5f7110f625ee97556404569125aaa9023a9d3611ffb1ea18b58a5519500760d5f4e0ff8bbc5583855573819a9d1a0158346e583442ecd0d4f05fcdab0fa9a73e449baa9336b791f0daa8f41a798d91215c8e34444c9208462f1a93a3dcda014bd5a0b54313d60e04202284d73467cacb21129f299caf21935c6d1ef67922718aee8c4f3339685335e622ab33079188cc0d4a9a1be518856382a60e8a97701ea44df0c439e82ef2f1d1248ede5a9baa259df728e1412b8d796af38c28141a4a40c3dba0e4ee24464fac4dd5928dfea0bb68f77072c7017a0361af1dc8ebc8f5c3e9327202faf9d9b98e5ce4e9ff6d20057083ff6a448a9600a4f87f2a6f0920c95712c7bcf14f8566ca495b3159fc576dc508c5fcf8aa7779aa508d5540a029f973554b873574b8f25f35292eb174a8a9274e5da7531f3589d3f5ce018cff1cae04e5800ab272f8f99a03f62f648ed7961019fcff1f6d2d048a25c4ab35267999f7adeb015766e1c0060e18c0c10787ed8635ac1b5a60dd008475430e960d30b06c60810de7d74e8a1b95625c93aa4ade45bc51297932394f031a0f6d8551b409de0aa32813387bb31546d11bf167a5398ed659698e636373b323377be25dabf2541aa7a27233add37333d50f26d32d2ac0cdb4c6b52c61b589b0bbda3c94a5e993a2f8d424aa2a7f4844a50acc74b402f5f8e804e5f43c294028e58627fc6fb94309ff2d4968b1a38e0fb45431b3d06103947791c9d44dbe531c689bbc27288cd2133d74b4a61809ffff4f802270fe15f0551690c7ff05a6f88fa288ff07fc03509b34fb7f12c7c8bd047099bbc42e24422e73975ba9899da23a90bc081e0438505c41e2e7a110800999afe15fe84b4b7c518a224932821c3c207df1a4142c11a4a3756b6e7e0b11e62e2f2436d7897368b44d14c478d2465aa20486d96a6bf22e2a4b9cc2e2a307a524c6681151143c5da6c9b4531235d278a3b7283c7b12322491c2ffcc651af9651a372a9337944e9e379d3cf190599e29f2ec463ce799bc8de62689a62693c9e748de50c24da2295078f65569fa18f172e3984f74c99be4a4731ca1c4a0c9c915dee13d5440211da05009a8c427a7070c9df838710286e0ce13253e3ca1941b1e14ddb8eb0c02819c8b3bc543f8e4e8b953643384837e4a9cf98e0e10ef4137c6d11827a783a81425716e34c6294b9c1372dbe546414e7a8b1c24110ffa6f31c2cd7f4b1c3643bc44774ab5af9e9eaaed644927af1d044777efe82675dac9a319238e4f5387bc50294a8a17becc8e5157dd222eaf8e8df44eb1116d629c22fcb7c0f1a5227cc0e8c628b86ddbb66d9ba6699aa6699aa665599665599665d9bdf7de7befbdd65a6badb5d66217bbd8c52e76b18b5dec6217bbdff77ddff77ddfe7799ee7799ee7795dd7755dd7755dc7711cc7711cc771dbb66ddbb66ddba6699aa6699aa6695996655996655976efbdf7de7bafb5d65a6b2d86611886611886d9effbbeeffbbeeff33ccff33ccff3bcaeebbaaeebbaaee3388ee3388ee3b86ddbb66ddbb66dd3344dd3344dd3b42ccbb22ccbb22cbbf7de7befbdd75a6badb5d662f6f33a6ed3b26b79523a3d28e03e4677111db0c41b68a33fa99deab410e18d16d38dff9621fcb70801c734e2260f69df23de3ba8aefa397d3289ee94aa074da5c2b38f78efec52c42d6dfcb7b0f1dfb2c6ff8cccff0cfe9fe84b42ecd0cb33456a9e49ff42b2a214041e2f665c030589a654e6eea98e8d2e9e9638c5e30a13f1b4b439d2cf8e53ace4bf25086a0c99a4de284751b0c4a909858713f3689243195128230a65448b4ca6118562c34386e8de2715edb3db7635958da3926597114f3505779df746cf13679b191b4fa575648ee4fd83cafc04519c8a1867891328dabc49796933b34519324c79d9b78871ce13cf689ceaa2d138954cb650d2a3ddb3c40994254ea098242e7f8046b428e5653fdadaec1bfd59fd90cc4f91a9114ec900716e70ce139b4c67e7e8165ae1942519a2fbf4ae7df2438a523ff26f328567ef1df8ff50ef237224cd406a410975c0f13573ed460935c09f824e9769dedc886411a98404842a8a282a01b1939aa46a88143399eed47f4b1a258a82b90508d6ec373c3d57684e6a92fca7eb803e116704c6d279e1b3c82addeaade1a349fec0c9854a6f30b1eff8e8843c0a257814aae09e173e4ae612253335f577b49aaad3653af9d0b851a547d5a37b847a5a783ac0a319fdd0a1814e4a67a6491196d4b14408253f50a2034e17373f28dd547193a4643325e7c80f31d410a38a92e903a6ef13bd27785d78d64859fa8cd0d5a0239970038eca8683d28696349bbd70c52d4860654ad8aafed4bc51aa71408d108d10342ea51d6e88b080c81129d4ff17f2252242888cffef7da96cf97f1abe44f4c6d7547572d374f15475e2e824e1351a35844d62707a434991287c8a56e08408e670424d904eb771208e3080f8c289c9c4b50a6df204257b4e3288ec405bc43836344750bea42c71ce2e455c9638c7646241931c8ac91486e6d69a449ddd641acbdd73429b4b9a4364b7fdda5d64439e37f5d2f9b929921e6db3ee3d863c0df71ed3231579deec6cf29e1999cac913d77daed21d8c7007776e7280ae9337a6aad326127747a57aef4e9e37a79a22a9b9c9329fc8131fedd51631ce49a2c4941f6db3cee81d5610e706a7aeca71e4dac42893d428e7b9f7ddb9d97bca6d2ab7e6b5668b5593d766b2aab66665e2d45a2f9abb03ce456377c091b9b036370e36316a4c533c35639ef6becb700fe1159529a793498e6257413999a70b5f4e78784e33a60c9253ef4e7878d0548a3c6f7845b72e69545725af8d767c9d3419a66947711f3949a2ca5395fa5c75866b949c91b94e1255623ece9c4e12d5c3930c36d3ddc3ddafce9bd454e7e726ecd719f6b1e8ace9ee7d09949f6be457dfb5e4fcec171f6fda39ea1ac93034795d8961d86b8a9b570d8148e9cd240cc37a3aebe94484975c281fc3d30e73708a755d5ddac4e1497772a37d55929c4cc39ada1b5d7255945f1517edb287abd79311374f26bf8c362ae5e70aa5332f8bc8f3268a4f254f7c6d22941b85281fc73aa23b35f51e1ac2417b24c5d309dd45268a77c9f9c951e93e4a7baf45690d6bcacd0be557aaaa3ca7d329c5e175f554c5a99cfa69cab5fb13f25437ca732a1079e2ebb4519e53af5dafeae4e25a85a652e16adcbba7bceca4ea4c69b49326aa77ad02da241ac4c3b56ac47b074df1a4b2949c8e9f9c292518c53f284601758ce29f4ef674b2075d3de1f9d9a8bc83ca1c25688aa7df6c11e3fcb7f880073ef86fe9c17f0b0f76f0df82860efe5b7260031cfcb7dcc006bf3a6262f21e93931c1f27d70aff1c517204f311dd4190e5912322c639c2834c3157c747fa6af330ee2d925a85cda18e318a4f93a7c82d62d1c4e8100c3130c821480e29e4403a4df13d5992c40188fcbf0f2b32e0811fcb8b32baff27112089293e57ac48f1c5ff938e28020e33280a47aef87f120b5a16608302dc2008d4fff7284287d205d810801967fc7f8b1d46380009b020030a23fc7f0f2933a8411641d2c00105febf47162d1811448308e04092b2c980133d6844f0ff3d76400208e188214728e1ff5b6040028b1c4e3cf1450dfe3f850a307107e906a63c92fc7f8f36eca080107838c146f7ff3e2c7052010ad4193fa481d55b545312a2819210224a42aa907bed60ee7ec3464db78dd6b9a830da3dbd92694779472b1af2cc33479ff0ffef93d2f9ff1bb8e07f08e64abf65aef47f4b0dfedfc7b7d08007dd10c65fa6b4e31d1f242038080208297c50ba5247e90699afb99b2d584a36d451579c0799f1ff01f8920d59fcd72857bd527c956c9840c90622ae920dba648392ff8c6da8e1ff4b35dcd1c3c437c0f8c83223137652c80cfe5b64f043059f95a9f97f4b0cfe5b60804589062cb8898d76cf054a349c26597651a22148bdf161867f121aff2fc6970250c3af4c6cee8bac78255eff2d67fcb79851fa94364d26bd4d239fad71fe6f79c17f4b196492195cca22fe5ffe83beb44490dfa536cd6b9b6469921af3928eff2ca52041ffb9c5052d20638c55498625b8a6e93da0a46065b84a31e4f1ff297c29863bec9762f8e2ff7baf49497175f2fc420c52bea3b514034d29061c6290a114439037794a8a357943b1016905ffffe44b301c91272e92c629a854c2927791adc1e1094f7842298a1a317a4a8aff2d2c682135dea8ff963050adb14de948c948a9e4bdcd4573242571fe5bc058810a52f0c55ff1a20b2eb6684181165f81961398c0042d2520c108b238029ffc3fe9ff1f054fbc05441082161060714509e6c77f55e10644674dcaac19d1a29ed2cb112076ff80071e022e2940bd8ad56813a32d558a782facf8ff1fdf427e0f1b6020d9218397411affdff32d2effdff32d2dfc7fcf7f06febfa7a7a58a5495ea80f8dfc20173032d1af80b640003b9f40209ce543ec2a99477adea480f1fd21b2517def8944471917ef2920b60fc7fc9852bff9789041dadbd485694ca47a1cb975c98f9bf4c2636d2264994ca5250fe03dedd2453616892a912a7bb778c8629f943c7647993c9936fa0ad394fdf7b49ba81f04e794fba7752949f47a0f9c4448fec719fab34444d9d5d440ea59b289369ef3c15a6b81fe194f904e8e8bcd940402b154e9323702bd9654e8eb94f9f1ca3dd73a6d0267b17915b898dce91bca1dc229b23a92cc564ca8a74a8f790d20f1fbea35595e2d906b132fa1e38599e34841e458ae8fcdc6071ab4c628d118dc8f31e47152ae8aa3369c6a68cb88932c626e6d7554ff57411b9aecbd4478e53b3519e87ac4a524431785554c61bc3b60bc9856d17918b3c699363f64ab1a9f334e3f14a4d6c9229ae31cc5e34ab235293bb8baa9f53edff242bd613823c013a4d36577d051672b4894da73c60f0df4301df637f8f213d62c8e3481e33fcffa504cacf15e484329c50c5093f7fa272d19c2e3cee48c9b36f7de1b1051e28191c3c649a30c73faa09657c79e634818ada9b80525956135c7c98b005137ce02b9109364b40e3bfa2fc745a4216750955fe6b3fda4b48b204971a939b32d71d58ac3bee403d2ae88e26ff77b8584a80c27f94f0c4577ca3841f142b610049b8230958fe39cd4d1286f87f5227e1e7ab9984157ea6e6745f3434a20ccdcee40e8204eae58df904f501329fec8d2ec128fed1e91150ca7b501d37c129563264926936757a2779f06e82f21c345a9aa002123e40c717ff7454800e23e8e8e92619ea8df21cf6148773a0314795553947933982fcff11e6288ff00547e1ad23547184a16a53af53ed2867a32ef1ffa88e9b681d5d7212ef546519618e9fe2c3558d5002230c71a2d1e4141f4ea811ae38d488438a380ef0d524372a457549aac40be5a408737c11b2f8221c1521491152d509071a0f87155f513850b5f31e3890a43463795d3857ed654779bf094acd4d66539340403c7da7dc7ce2c30870fcff1022f0432ab19eface24c61c15af13475d2327c752355e3cbdfa90894f2679b571fe5fa6b1a80d9a17927672279bab6eb1f1c6ff8b37574d6136b0f8534544d73c870d1ffe473630141b3ffeff42f9b80618ff17aa8f6b54592389b586150430be07a14a107e3e08d71c5fd5d8e24b9c763eaa915a02e5478d243f8e69ccf1ffa88aa761833412f0352895f634ae7f202801085d0021e3366a63376a7ae7efbb494c506f99b8b538626eb31ba66ff86d3d42a1941488336eec72d6e3b839ec6e51d329c1fb69a3e6ba4e1cbf6dfb3411f87119ceb67c37f113b7c518d5d9cffe007258a76d5a968998e3b8ee5a5467353eb34a82d7db386ed49b78314fdbdd75200ae476f6ba0d133dbc8d79eb3654675334fc980c815ad69cf66d9df5440cb357e4948ca06833366eb1eb440e6bb1f3509d0def920d62f8669c1ef3b61a13edb8519d2d313aa4f1792dbad3255f9a1a3d0d7e1af661ace96dc4b651b322aab31aa70ad3d4d86550c336ecf3c62ed323c6619b519dd564b8cf55ba326f6a5d9938eb110a4111e4bceecb18b31a7f9cf6e98dea6c4c1093184f1513b41383ee54a7d68de6d4aa3779f25c6baf15dd2919ea8b59343d3392151cbe9c403d66ced3b66dc377c376974d1e9625cedfcea68fb984f3fac94d21a8e92de332c6711bbe16dfabe91c00c4d977efa6b5aedb3a0e6b9b66159a02d9235440cef3468ddb30ab33afbb78e37a84c21e7c00f7f6ac277219bb9ae7651e4675d6dc65b843ed6e3b9365df70a68058c65ba7617bb76f13b1eca13adb8540dbe12fbbdcb662b6c7bd31aab368eaf58cde683da358d3240fbf1ea150eb01d4dbe6b66f6f1d763d6ec31c9a76500a68b1bcb1f1e3460c6359773be86a3d4221932820d66519c75d51fb3666b7fd509ddd7679aa8230dbd1eda5a931330205dcb8adcbdc96b371e3bcbb65432a712ba9b556aeeb110ac927e0a7b711671ab6e971df0ff382c04d6356eb320dd3b09dc52da23adb89f03ec3740f7d394020be57dc1bd6f98abbe3c611d5d9bdd13434c930ecfcf42cb7874c8c862689c35024cadbed110a799c809fa6dd0f6fdccd442ed3acc50c00e2ec6519dbf6e37637ee8cb3fb036eaed356ec46317b59d6f6cdd75a1ff06a8d3151133591dbf91befe7f5801cb6b7de361167e3266a7b519dd5dcc403da116f3bebb80ebb1a7359d47c07c4aeb696cb63bedff6462eb3180f20b7b5f6b086c7ac472ddb3e5467b35b0010c376e689577f57d4f2feb86bad0ea8b99c69bdd96dccc42d6a1baab31b4d13f06ee3d51dced6cba2be5fce2c77998019bbdea8752397ed9c7587a13a7b725463df12f0b31ebefa72db1d452b661daab37aa318d53ddb8160b68d9bdbb6718bf8b3daa6797aaf112560b7e1ef661ab6655a67ef67519dd5210714b76e14b36c6fe2a87ddcd7a13a9b775188ea9de570402c63df1ebb4ef36e67edfd509ddd262f73588a38e5298e9ef69a6e404f7779cc9a976d5a1671f78d230fbf9d24e0a7613d6aa398e92b66ec759c0e01c0aec376d49dbd5ad77d9e1d519d0d336b2d67f32eca7c6c404ee70febcf6a6cb3163f0fd5d92d4d8dd90090809fe87197cb1ede466ce33cef0898470dbbdad3dc87b7a67d1caab3284665cc46310266baebc69c7dd9ce444f5b8cea2c9af6f08b096212b353128dd2719454958a59e224067b6202350cc39a97656edcdf15515d757276e703b14de38c61bc7d9c673dac519d35e2e85088eaa4498ef67ae0a87916dbe2b62dd6699e87a13a5b846e7bbb98202631373139314131413b31794331c24ebe1e3ad0e64dfcc6efd3da7a3b8f9936492353c5cdd0b3260edc98d630bb8d1afeacdebc2c268849cccd54281f57b8ac696aac31d855c594678a8c09da8909ef76a6c82ca532b3343566e2068a5ed78dd7e6ec76dca8651bd559cf761a98793b6fcc765b37ea0f6b23aab3696a0c874c92e8db28cf5a8f508865a0dda3b66d87f598bf31db465467c3ce765b8f50e8dd14e761a9d1305cc18601c0d0225b876957a161f8429da9b9678ae78e26003b0c11b1212f679891b1e12eda252f711882bbce3a0c4000029089d9bb8739e8c053ac430e3242ac90cbc6e0a04d1c6e54bb01675ecad8105e35048086cb391aea4d240037b444dc76cfbc67b03a04192283ae2186191886869468ac1bea00b3da4437bcf41a5c6c0e0020f2828c0b361cd202d10584dbeec582dda81a56185355989a247a86b993291b7ea8704372dc39a460c3dd674001c5bbcc210d3ebc6b43f16ad1b8f0881ba521ca861ea91b48364c8f760d2f030e6488811aa49dc2a60f1964d0c40f205f833cbeb84902879d2f71404a12205f0327e071f32524e6f812124ef8d21517be7425c897aedcf0a52b44be7485fbd2159c2f5de9f97f175a28a5dd97a6e85f4ac1152e147cb4f4f89b9215d597ac2cf1252b38f87f19dec80064f84a456cf1a52266f0a52a307ca9cacf97aaf02f5581e24b5556f0a52a40f852153bbe64a5862f5979f2ff25ed5db868e2c24511901f3858fe056707ef6294054e1b29bcf08cf12f3c31f8171e1bb8f06204f52f46b88b0a2f3f5e4c491ec6f403630a1fc6643e8c29010f637ac0c3989a781813150f6302c1c3985400639ac1c39874f030a6351ec694e5618cfcc31861e1618cc0f03046060063a400a89cffc779520e6ffd70e10546092c1e4689153c8c1235781825d6781825e0781825f0789825567818233d3c8c91ef5fa2704005d20a28905e5678e105484905cba6be654380b76c7c2c1bfc960d02deb2b1f2960d136fd974e02d1b2edeb219c3b2b1c15b366ebc6593e52d1b26fcff0b301fc0e30917171688788b0527de62a18ab75828c15b2c88f1160b36b0218517165ecca8e35fce60e15fce18f22f6714f99733b67f3923e75fce08fa9733f019e6bf9ca1807f392302ff728605fee50c0efccb1922f89733b838238cff5781051580ac00e58e7f81f2847f89b2c2bf44b1fe250a0eff12a5c8bf44f9fe254a927f89a2e45fa2f8fc4b9403fc4b94d4bf4441c0bf4471c0bf4441e25fa23cf12f5138f02f5142d0c20a302cb80024e86180f8f03040500f03a43f0c10211e0688110f038489870132c5c300b1e2618068f13040ca78182039781820693c0c10223c0c90253c4c0b290481c18af62f5674fec50afe172b3ffc8b9505fc8059c014300b38c1ff0359e105c8917f01c2e44b18b8e35f8038f9172053fe05c808a4e8851f16cc8b1c35ff22c7917f91c3e75fe4a0f202c4fc173950ff220702fe458e2bff224706fe458e12fc8b1c63fc8b1c36f8ff167ef850e3617c74e0617cc4f1303eea781814480f83820bff6fb9c0c8b4f03032383c8ccc36c30b761ee605a78779c1ca85172d8efc8b163a2f2730c1bf6841e55fb418fa172dfabf68c180172d28f02f5a48f1ff2b6041bd0b1620de054b10ef82c501ef824502ef82050a00acf083851f2bbc2094e45d847ade4588cabb088def22c4df454888771122e25d8428f02e4216701102c1bb0879f12e4263bc8b500dde45488dff878191c18d7fcb0d98b7dc10c05b6e686fb9b1e4ad2142b801c45b6e547109c00b005c5c28cde002c300e8c0e3ad2c32bc9565c85b5992bc9505e8ad2c446f6519e2ad2c54bc95a58bb7b29cf156961dbc95258eb7b238e15dae68e35daec862d511e4ad3a7678ab0eefad3aa4bc5547f9961b52deaa8388b7eaa0e2ad3ab278ab8e30deaa23076fd5b184b7ecc0e1612c27f278eb091dde7a627beb899eb79ec0ff2f030c961c10784b0e29de92e3046fc961c65b7200c125c891b782ecbc1544ca5b41c4b782f4b78210f15610265e0000c40520a520330ce1796b48f8d690f3ad2142bc3524026f0d99e2ad2120786b08176f0d79c1c3c4618535e4066f0d81e3ad2176bc25d3e34b53f4b76462784b66c85b32dc5b323d6fc9906fc934e04b4674e04b46f8e04b47b47ce9081bbe7404922f1d01e54b4748e088107cc90804fc3f17809f41080c3bb4d0420b2fa00003248b77313ac19732e0c2bb1885f12e463778172335dec5088e77314ac2bb1ca9f02e4730bccbd1f52e4744dee5a87b972325ef72e4e45d8ea2bccb117f972306bccb919577395a22880b174dde858ba277e1e2008f83101a6ea8018701e880c307b078eb035bbcf5011dbcf50124bc7505cc5b57d8b7aed879eb0ad45b5740e0ad2baa78eb0a31deba228db7aec8e32d2c02f0161649dec2e2006f61c180b7b088e22d2cbcf87f00c0008038acc883fb92141578983c940071c182e2c9bf4071fa17288cfe050a22fe058a26fe050a0ffc3f0b405c70f9165ee2381f268e201e260e073c4c1c13789836a088e38938ac78172c547898384cf02e421c789838c078983868e002232486172c33b0b7ccb879cb0c03bc65c6d05b66acde3283026f994182b7cc788165461a6f99618487898306ff0f038036621ea60d240fd30694876903f5306d183d4c1b463c4c1b503c4c1b1d7898364a0080162cb10e1658c8ff569ee1adacc35bd9be958d7849fe6bb8fe5f70f957e10789052d5801a0838a77a1038b77a1c38b77a14306ef424711de250b0a5f9a22045f9a62045f9aa28b2f4d61c6ffb7b80c49f22e98e95db025ef8201b5e0c28f4fe17df4b880172630a53a363a423a028b9db0c41dadfd86255c81e5031860a28b981e2cf4d8b9a20893b6b9cb178cb689c29404983ed0d020b14172cd1c6952261df78ec909ea938e7be7baaecbf40101d79126c3d4125e50060a5c1881c466dc250a56901cd9e13277d922822862f8f7e1430a3c48bbbe9020b932da7fb0cbc6071a5598e02a5531c4ff65324dc0087bd58ce5ae7b48ef1e092875608cef214827e7e6e726e73a721d69b207a6ea800edfd15ae4c4a9227ba3a958e4dfc70b3de6f0e1c6fb58e37dece00c94f7e740f7af9393f5cc64ba45766c20ff6726d32dba504ca6ac48eb6450fe7db890c993a7a88e51ff3e5a4865297c34756cfe7d0061818fa64e5fc1c6dc3b4798e7dfc78f201b73efec14eec13c7c34757ca8b053d82c4bd5929dc23dbb2c553c4a89b712de936e9e94f7f4bd971065bea337be404aa6c813a4e003051f3e3e5a7a907cfc7f8b1636475a9e8053ac5bf270021374139126e7c93ad9718850be6485a3cd9df61d85679e79144d861be5a88e734c92e794c4d13aa97ca449f389de363334372b4b554f2f553d931c4a7a93e2e6d6296e9a1815b451ce9392e613701791437ba7c46426b5aa00bb9b9b248356e60d4ee1aee2e11699240f7a9b4fca52b504e3f0a052c44d82208152949f1c359ff020bd4b12f31e90f3a013a341e6937da636ba9b5829574a264593b249e1a474523c29bd6f5d925174494629cb9bd1a72c6f744946b13155a3c97b744e9a6fa870d6a3a269f3c9d10e17edb57ea1b5b603410f0c805b779c3762a3e669fc5d0deb4105d8edac61d1d3d9f634cb79d85ba2c705c04fdc99f6468dcb324d13b1acf70885688f29c08b357cb96eefcc4a016e3adb30b7b51db9f1dabba300330ddf4cd430cc6537db30cf022077c79cc5bc3d9ce9eecb2a008a7b13bd0e6b9cc7fb699c8502dc1773e397339db72c7a1b7e02f42e1e3571db302ec3b04ddc4e80db3662e3b869df98719bf735016e77cbbc31e36ce4f4a7651e13e0dd5d676fd679da8a9cc5b82540fb598c456f1339eecb3adc29018af6f3eed572368ed966fb26018adc78f71dbf2cd3b4d6444b0150bcdd27ee8c615d8771fa8e57408d715c87655eb7477cf5b79100bdacfbb86fccbcec759ea7f50440cc8a1a8b1a87e5eee3b2cf4a00fc2ebed65a716b796b5f170150dc2287f3cd3026defb89fa0850d4585b6de3b80ee3ac683123400e1b37f665f7e2adfb382e5b01334dc374de2366adc759d15601b16e674f7f9887ad8879f82b02c45ae65d2c67e3c5ba6b3f08801bd76d57143b4eeb72e789d803c0cddb306cb39edd7afbecb64480dc8745dc8dd8f52ee665de760078b7763d4ecc324cfc34c7650d00359ce16deb3a6b77a6715b6600683d31cb448ec37ad438775d8f21c06ce33c5114396cf5c88ddbf60450ebb6e6b6cc66f66ebc6d9607b8610ddbae1e394e146dc69c13c04e771897618cedecbb22c6788059e6b2edf3f4a76f367e1c4eb192f43601dc5e763127e68d1335718fd8d6310114b30f5b6cb41be6b4b6e1b1d6ba04f08a765f0edbe2f5f4a78977d3ec15d21de078adc77d571cc58dd3aec66addee1324258099c7e171d4d613b1fce10d7fa1d56c12404f7f19c7ddab3f4ccb79cba691cfc7d9017e9ede30ad73f7693bdeddd5fa8516b3a4294875801d96e94f6f9be6b00ddb31a33a9be2f066aad0de24a42ca01eb5d65fb779581433a78dd90f243a406fc3348b3b2eebc611e72e4b39945a77ca8b6a459190007a98e5aec6f29669d9375ebc95a43940cc665914f7a82fde3e4cb34700efd563866d6fdc6cc6f4dd360a90e4003dafdbd91377de32ed719d566bad5e68b7be1901c4b2abed2b7ed867b911fbec8f9398989f9d18ae6f768b360e101bb56839ad356ef3f467b1ad08a0d661b7ebec376a160e507f57f4b8b1d39cc8619ca70561363d493463d6442202288ee2b72fce5bdc23b6a34675f60d306ff9629aee3e2ebba2b679deb540df16399a768eeb110a3d921ba0c689d96edbc5f6b8338d1bc3b04728aca421801af6c40edfec1bb5eddb6e568e9b10408ceb446e634c6759e78d1743757688975913521b60966de3c7d9adcb2e1ebb3dc4778686f8cec97b6a1de2a5c606e87999f865d8c398a6bb8d33aab318c6d971e37a84c218d21a20f672b669d9de4411672cf3509d0d0288899ea7bdab75a238da6ed3509dd59805da4a6aad6126d3932ccb7d53eb36c971c4b5d6ca6d97c84a415203bc99f5462ecbf0d623e7891bd5d98d6215109d5b727348698058de78d4f0366e3adb8c392080d6db3eabedd1bb19d5d91d04f97596bb47980dadc52cb75d22ed0720f6f697799bd5442cefcb89a8ce7e3e00b12dda0ddfdbe111c35d86cb122fb1d608a3d9d70330d35896f7988dde96efed2c50ad970720c6e1f1e6ab711ef77d9fa671df0ec04dfcc64db35b1cf588653c769e112434c0bbe96db3cd36e671f87ab90bed8aa4033073fb665c763bbcc50f7f370760c75d6c6f567b62b6c54dd41b12241c805a5f8b8d3b13c7318f76b43700f7bd98e6b44c671c1eb3e6509d253be9d95e92a90a09c906e0e65d0e8bdede5dc6ddd88db59a9c4c6b9077c6dc97bbed6e2f09120dc00deb8d7dd9d319d769e2276a1b11090b988dbad37a13c56d73a2edb20648330033317f9bdbe2e5b4a67ddaadb57aa1e5523bedab2b03d0fbb2ce469b7d1b13f786d91e31eb362c06e0e761fce53d5e7cb7e6b0a7b52eb40a20c100ecb4b7dd9cddbc35eeeaef03827406e8691ab77d1cb6f3367ea3d79901daadbd0fdb4d679c88ddfda9529c02d59a3b99aab556cc86367732a5711c08482f0047bc715b86c54e8bf766dfaeb57ed811a432c0cc13c711c376f6ba9d619d0b404d5b6cc332bc619be5b09cf1d1d4f19820b500ccf4a6bb2edb36517f4d90c800f1277e3bdbe2febc2e6f1b461a03bcdee636eed372b6d8c55029fed150293eb5557ac500bd9b8956fbba4ee4c6d1e3a3d957f8a7d65acf5590175a9204482c0073367e1fb775b8db3e6fdbcfda90c200b18fb35f67bb3d66ec13b30cd5d96b3d30402bdeec7e5af6655b96bd8f3b39aaa4d693a35aa358c56408d20ac00c1b31bc69dbc5c6bcb9bda900dc3713b34fc4326de3fd69390560d6bc2ee7717f59b76d98dd43d90ce90bf08ef87e633676f9eb36c76da8ce0ed95be22c88e4057837edc3d7769c68519d1d22c5cc5e6b6d17a0cdf9b3a3b875198f1ca7711d27c3b36f3d4221111217e0d87977e7cc6ae3b558bedd46b5982026a7a953eb16e0e879d9d31adbd88e7acb32cefd7a84c2204828003b8e13477c3b6f13bb6d314c0b50dcf9e6b1137797655a77c5138058db5a5b2fd3f2d69b134554673f9d989c98a0144797e47d02d51af4f50885a407904c006698b7e54de3b29b89d96e3647e38eb85190e7f5088545a412805e863fcd7979d470fe38ed61941613c42406adb57a3d42214a2201983b8bf1f86558db70a63d8bea6c68af97d911805fc6e5cb7d167319c66d8ba56c3d42a110290b10fbc64dfcacb839dd6d2b8a241180d713edfdf2bd23b6ed2dd3301b5a0f03a41080da9875d9e765dcb5196fbb1bb79334e38a45800402507b9fc5701ef368bdad7f6a45f9596bf86d687a52216101669e88b371b459ec3c2d8a17d5599e865bf36c82b5d630dcbe7009d215a0c87538d336ce6676e4446c247d00c462e7d9fb699dfe70cec48cea6c8aa3a3566bde457affd41a13b41393e2e8925aaf0d770aa3a3e6019207408ed3b277f586650fe372d6d55aeb104e6b45b7e6ac00bbed7dbacbf0f7615a632cab02dcbc8ed33c71c49d15eda6454d87d401d0e3c6edeb324ddf3de22e7b1c00c5ebdd3b627a7f7ae3bc9d6d00ecb2cfd332c7ed6c452d7a9e06c04f14bf9bc531e346cf5a4dcc00a86d1bd6c48be96dbb9df76d0c805ae674663b316b59db5987a900eda65dec6a797fdbcbece52e006a19b7b7c76d9c16f715ad87ea2c103b4cf31613c424060810d75a6bad5e8f50a8224d016a9ea7452cb3f6db468bf2225c8ee11059969bbb4e34cbd314fda40047bdbd2ebb168b1a1b39320c5314887e6d4c10938e34015214e0c6692d5b9ced311bf5ce2eaab3a52a95952a9e5a6bad55e354b5d65aab677b8442520d481600f5a8c7afb336636cfb3286519d25ba46fcdca4902a006e3a6b9a98e9dc7976fbf4c753cf6ea0a671aaacc424ba3ba7cd6e0a090a505fac8d19c39add57771a4675f6888b2151c6a5f8ed3215559deb110a65484f80f7c3ecf76d9dddb066f3b6a13a8b5d200ec525ce9d23da25d6bb085565cef608853c242740acd3c4adbbee6e6fb39ff6d55a2ba909b0cb3c4fdb32c6306cfb6cde9800bff1cbf2fe366cd344ac775e02cc59c656ef0dbbdc68b36ceb110a9d909400b576f1b765a3eeaeb6eddce1f8404a02c4aeceb22f8f16dbc47b450a801b6b4fe43c71eb9bb12c9347bb09ba8df8ce014857403c6edfb61b87e12cdbdabe1a4742021cc7b1cbf6ebb4b77dddd65954678db699a11b084d81acedd0b47fa40980e3d77d58b656bc9bdef4385a4c9200c8d96dfc3aef5e6dd45be761a9d0dc65675727cf9bd59b2a262846dc5431dfdda4088099bba3bd63b6a2c61bb73d8c3a02c4f2b55bec2eb66d18cb1a1613c424e648eb0c99d849adb5f693dbae4728d42423c0cbe9ceb356f334bd656c7f9b15f0669ccdd8a7b9aebb5967fc91aa801ad6a3cd189739dc65fa5a8ba69d540478bfeccbbe4ed3b48ccbb096a1bab093d77e240880ded8899c873f3d6217eb380dd5592edca98d3a313ab4d96bbb8df25c00d203400f735df76d1dbe18d6d9ebdded928800b34edbb0ac5d9d759bc657233900d4dcd865d8f8755a976f8737aab3611686432a716bee921a006e6bef883fac751eb7332da33acb53930c354e156a56233100cc1a8f1a877998b559b63beb5d9b9186003511639b77f1d6f076add6a13abba51bc8f316006a4fdc5da7699d368adb873f0580dbf8692b5e716b1d76bd0c4b00a87959be566f98dbb277b52804988d632766a3b7e9ad69b7c30800b5ad317cb54c7b3a7b9bdb518200b59779a3b7e18d6dddf669df8dc63fb57a5c8f5038b40247bcd92b6eccea2f7f59ee8e40ce6a4c77d9e33e6c14b1678d402d8aa3deb0b1d3aee8755944757685cb6c2b02bd2d8b7b6bb613c5ed6d91fb3015b85d6ecb9a1eb1cdb40e1bbdcca6a0e86119fb3a9c75cee266bf8ceb110a7de8e0eeb2cc66ddb6a3b8652b76b596e5ceb56e14b5b7829f1eb9eecb1bfe384fd4ee4ea9cc2c0402fc6eb7bd4ebc223676d9a7e91d04d99fd4cad11d84c9cd5a532a93eb110ac513b4e29761bbb9acb3df77f1b7e570d0cb63abcaa8b453a9853dc9143222000060d30000f31000303024188cc6e311995834a1c60f1400025b9a5eb6704497a85994530819430c01100000000000009360427b483ab5f902c31879a24f61bd0c72c9c9e09789d8ea29b55ec7c0eb9834a663388ea7e35d1803170bfd03ad702e4958c304abb68cab920e64b0bf638c9663c578f063d5a9520ce82e863df4d9f7f69af55698f74a58f5dc64d3db6bb2b7c2a057c2b0e762df4363d65b61de2b61d573b1e9a131d95b99416faf616f857daf8459cfc5bc87c6aab7329bde5e93bd1506bd12863d17fb1e1ab3de0af35ee9aa3d1723b087c6a8aa7a75b12eb184292097ad6b285092a274837eb9315757742034f0a8c1dd4c9f689b485dc61a587e27c0ff81ed321023dcb50113bfde780ee2a70279614c727342fc422c81072437e8d1025785fb7ed18bde1cf5c72971d85c22937d6286b469a4dc08224a1a7cc48f63b5983ef21f85077a110e9cee20aa02c0d89067ccb3c6ba0dfba46a241cbaf4be5d89996dce8576408ef0ffb216516bdbdbdc674e2f94df1ce7e3350d345a5999300a5a3f145fa4322f2144123358c2040dd60dd109e587177cc04849a38bb9525a076153e25d6e27b0bbf898ba362398badac386777f4afebbc0dfdc55ac7b3c4056070882f820f498cc749a05767b612b245b4263f2d82bed41228a1dc9130074cd30bcc0f791e9da3f9f94615fb169108f1f95c5b9f570e98cc3a0d1c57f9aafc63e05a03c86bc3f7114a5e3fc056890ef11e6f24a556219ac7a3afc1a6632e10b0fa560d4922c7af45dda3ae0a7005d6603deb42d6d7f22a877e316513bda4ca6381d2755155dc072990ca72e858d23aaf14cbcc53905f094ac7e690a874ebbbfa3cf64669d5362886593f626757ca2b3b5eabc9d9736e0364a023f1c93ee51167a1b026620996f912b57da7914fe700761c6497cd45de9eab057bddeb5d66f3d203d031886b541ed95800bf5c3b5fd024a3932c5cc488ea2a6531a00a66057ca0b9bf418e19bddffcc9b992472622dcba5bdf4502f1963cd1cc3451f58ecd539c39ae1d265f408d91d8999ededc5cba754380a8032c7ba98f565dfb0601de8c684b16b6229d5c540fbb969c2d77c03759291975af6839ae892d26b042e3ec342d85ffa91396cd5dbc6ef93c20d40038c3933c4b91baa42ca327243bd62442b4da4213a09557b37ed7ebf0dbdb48cd8c558b99f7e93317246f12bc969bf59812e20e5b3964af086de529d2e84794ada6e6082cfc25077bad2f5c66eda41a462bf5175bd1896eca61c8c7864bd3ce1c98614fca2614602ddb47b91c1995f7a17b35f2e837660a17a2aff715232493557327058f9c55c4d5c01b90f220b0dfe96174fb4832c61c8f7ff51b2958c9764ffe15f8287e06d9867bb4e3cf50f92710bc844f60469b060774969e27ce4c8d233c450d70943b31ffe8fe94c197d5d6a6b4c78c0cd1e61ca629b55ce6600cfb72002ac44ae98de7f4b4f1085c90b84a768614901096892195db45258acba971ad70a9d1be5449d9ac556765681752b7a2430af5c67423b2ac5627bd1a87e7a034bc2fbc9270af4393c7116b8134c4703c0267d686413ea5455d136fcc87612cef23326df42225e1d6c7121dec15f4a5d31122ef2f78fef5906eb14acc2ec30192e52f90193140444612d57f62698386944925af8e671098bb440d3bde4628a345c89fc5f745802314478777f31bca41537774b4575324908744f452ae90dfd55d2e93650b4aba76a8ae81683c9de3b0c4ab05303d2fae59eeb4936fc0b6525b8f44d6d0338701c60bdd700feab178e04ebf805aca3534d741dde16170f7fdba63d623dfb6ecf1b24840168cf6b52369a89c2450d5519d51257bc138acd4d9a4ce629f51af6fca11302f16307e1726f98bc0279924fdc2134c6de16fb041f09b1a5f68b206b47101a65cc117788cd2c55ab62e1d9fdbd5df5e413a4e984eb91120d7aedc7dc987f53174ed71b22ab797d37da94f0ec04ad8facc978e67e7c70bcc1677fc060c7841a43516d0ed24a346d22c21a00249cd9d3125e453e6bd3a05354b5f47eaf5e363ae2e72f835b56e5148e748bc3c0579388ce2e4a47989895a8f0e696cd054fabdf61702bb11b72d0206bc913e02f0afdb187dfa68c41341a557810fe595b8495ad02a72c40de20bffc3b8092374ac2a16316e6a2fdf6842383011a7dcaa649c58c1680bd9ee8faf32b2c123255f7c50680ae72c55540472ba2aff4d14b6ae8ae36151d7d8ac2111a8e8884147477f66a4523eb44c69d5097f04729d3b3a0055182ab20fdcf5f22ada6c5965ceb4fa536b8c1effacc6ca54591b47a73091e0a286f49a9b9a1192d843ea962fe4def275a7fc9cfd211561ee6c97040d22524b076fe9a74f32dec8e192be897ac0914ddbeec62f89cac5de80a3e267bc3b9a1c95c25c62f5d78abdfdf858e3d44c053a56a46315eb818b97addcd5bcab8da1c3afa0d70f4354b48dcc4790217992d2b162f5d44db9cad41a1bc540ff1e80a72d3a923609d8e9218ed2e70c821b5532188d8d12b3e66bd8bab698a526ff0e4e04542bfae0e728ab4b3e3faf1214ea4d82e4d9d095ac5b38fa25079a2deba11c84055fbaa0e3a88bd357ebb1c89ac4bfdd3e73729c9a71e05edeb62ca01e6988f1206968f5af4edb3c98678b82e98a2ab47a123e3f947d3841810742eb2b6e4605fe7283c4e337baa2f972f73345d1eb4ad182872e2b35864fa0bbd06727225727c7c7c48b7a22e2a41f519fa5e90539fff384f021265280f4da1c047216d64f477270c7bfde8392338fd2d1d3f2a2a918fed228bb6888c2aec05b919702da2f55b40f5496a11280d0340f9cf27598385cd9c2974913b8e4df500397d60547a7614bd142b2dda117e778861e601948558bd976cf1707a0446aa73ec37a5bf0108acee0a35aa48d3a9c73235049a402fd5a11d4d23ee3af263c8f78e26baf2d3e4c0d91011cdb52d93e02eac8ac737ee9f7c2e67ebfdcccdc216a6f45afa5d601258eca5c2aa9b3a44bbe48207deec4996c7fc808d597dec588c067e486c8d2aeade98e0591a2685565d465d654b9a6651741272c5375f1c53ad14fcbdc94d0313282294a58d5c06b4e059fe29870bfc27daad52dfeadd64d968039165e5c17efe7bea248dbfbec6de31419a42d892e9f5af5cddb70b7928bd4df1bf685fcab217cd52df403e767806d77bec8f0a727578050890ec86d16affc0acb441a9f18e28c082dd8b3b56e24f9351706452b8c03f9a470079376794f8d449017ba1ea9052a03cd79f66ed5deef8912269ec2698d4fe413a38791460bf27297103b0c450c635db5e37eed6efc01cb695e6900824c78f004ef57e11e74314b341ddce4944a3d19fc19a35990e17a25f52555f5a927d916134e5f154c0d7f5864d5fdee26c4b2729cbe2f4ef16bcdd120b45ed7112b400ffffe705abf5dab50e22c692d9a415ef9793b99f0eea86535f9fa112d868d37cca12ac0d845f160db3643e2fc51a4c10e5e49ac3a5d53fb05e34bdc83f78969ecabb1e8051d94aa9a73830455bb541cab808df4a37b20be70c15939cfc42bfb064a6a8fb078430d9012ee24d574f6db8ba3e8755aeaddc2e86aa8eb9065003a82ae290518240f02613e0ee3e58cd10239cd76f9c4177d38679a9fdf476580af84fafd34e4c95f326b086997b6e0d1e01d904ae916ce809bae2de19a71b47856d6da08dfc7e7ce7f8b64024a4bf2437aee6aead52f5ce59ed06293fd74c8a868fe0af118e23543fb79693a8df54bf06bbf01dacb713f8424b570919cbc07262ccfd894763889e39458eff31d2a41bde693a4071c6188ee13e8e12f01dc4cb5cb98fd11337ff60b4c25394014b64c49195979e33b5cc1470c81b96cd860b8468468bff47be850fe707804082163eae47dc481c4c0d3c12219a106f33366ea9ceccb23740017aa74957ca1fdcde196cf2845917582b6612d067a0d55066ec26346a43220ddbe7eb3591c41339e0c72416ea83b6b8120397b82a5388e652822d01504333cb4414b901093c6494511a33ac603d955c374301ca3a1701ff690f43da3aa76e717db08032ce97f129ff0d9788c93317a3c53104b211d7e02219cd7c0097f01c46c90404584f6044f27d88e840d63157eff3148b3a512124651a063bb08572e424610ca4afadb8bffb5a8083adfe3aa0aa3200bc8a289dbcdad406b92784635ad672c4c704f18e3d89154091648052ca7a39b909e0e60b97d61ba73311a8d8bcca26c2a90ffcab06e901d0a2b8d00978a3a1b7e728089dfccf210b401ebcda67185fd417fd602d95c2e22d1c43a605303466b290dfe015a5317de41d5d4f5b4bc5715122ed619cfb34d8fced23a3c005d1ff9340783809dc6feee2a164aeda0f39a37d7cf53e95a829206d7f7bc394e3482ad4bbb222bd88fdff8d717b53c769f4b76fd1bdc5355e8dd5bac33d018e9b5227cf12708c9fdc110323d3ca857614bffb15f8adf2771e69ec0f5820aedbf8aae73758261e81b784fb6e30fc291513deb32a96eae5f80d8e188c338cc067d257d7f077b4eaf05ddcb4dc98ea3c44a3ff058af592a01feea7e7096186f77e1962c2bacba52e57b6f430e0c4760f1d9effc4ab13c1cd1498ff65035a630648c245053e064dbd75f6597d62fc27cdcb14fff1f1ed5d7dc11fb83195f095bcde2f83c36017fff2c016ea8ce4255dff94b7fabbb6df5a32593c50ea3bc7a19fccb3939d64907f83fda9ff235e181ea5f5d8f2c6181875f74b696feafd624c03b6310c19a496f46b25e93f1a9dad7c2f5669beb52807747c8283f753bf7afca1303e89fadb4e8f4d37d887d127ba4ff1e0cd79f0df9fe0fc49abbdcebeebc7f64c052f9b3877fb26e337af1f762f43b92b79b2b464ac3da4e32f8add45b73a1a91cc0d71222f0c4e2a57d7e215e07f356c6be72d4caa4efff8f27fa9b9aca4b737b7895b3e78a1f73554f3b36e3d58c2c43d452a9be26506cec4bae3e78b221c3d8e7c8e3385562b727efa5fa3efcf05dbfda689d90601e4fba6f1e90533a2ae9ac3697644732d6ffe0fc01bac26b3b0fabfc6d92749c7f5e1726a3d6ecac3e4f75dd6f3260dcc7fbce425b7ff5fee8ae3dadefdcb74387aeaf72c79ff05ded1f954dbdd083c153d15d4973baee95d45014af3a5c3dd1fb59b9adf24f8a7298cf75771b8b00794a4b5f9c0b17843d9a10f83ef5c7ae82c8e7e3fc8a5cfc7587e37703955c10dbdbd04d1ce1d7ba201be8f20927ef11db87a2b126af8b34b2c8a0fd18bccb1fb157a619daf7a80337793af7f99185f95fa9f540f7639d6dec1cdd196f05cee81b5fcb2bbc4bec0fcbdbbe25bdee38bee9a977e8352a450b16f6c4c05842272983aa696ad8bae93de045c723bdd69cb15bb1a4f415c078637815e1bfab3ac35d2ad06023d6489c2671dd5ee3ac002efdad67e311ceea7951cf2f865d6c84c32ddfd44e0277149e0d7f8eee21413abdd3fc549119f0afe70f063f0f86fdf32efe1dbc498c8b6390182d107c412dfefa2285f48a8a1dec6519011d97091d957d42ea24c34a746f4191139352e6c65e5f290196777b7b380bf0d4db5937bfaf632b04b0f62d0dfda27c2a3408e648616975d8b437e30f825f28e0482fdef8c77c5a8b77743f0e7ac1c646007de5dbe4e790a004a6f2596fdc19ab84fe811f82487c3796de511fe24f886f9953858f7bbfaf82cb95f98d97ca359e4070f68cb2cebbc344677d11cb2307a8fcc8c93e32181261671ec6945699fb57d04ec0e91b0891045f655991f01fd2013ddf636834eccd4fdb50d114d2c443f3e935faf201266ff7864cfdc4611ff0cca17eef577c1cd175e9f3266abf96c8102153f1dabd59ed8f55f3f69fccd609e04dcbd184e92cdebe3d2b0a8cdc1b8ad4451c3413afc08ccb8ff49fa84fa5b1c897f7fea24915ec08a175f6cd6a020ca29d69f362537c84db285a7edfc79f4091073057045c8390e0f24c8ab8a45ef27f9a14e5a7865c43272e53e23d455eb615cac26384ce92c0e908c67e9088ffb55d6d4a46c38b5e2a33d0d3cb46f3b0460f80d392b6c6dd4db413dc2c1d7cd362780d9863e992f3efbf51e38b9ec319ef62a3f236b928ae4d8d692ba38358a2d24a3765d20117c0fbf42f382ac3aa0e794c51a4758fe16dbe2784ba1b5226591da39d89a04e8ce51c7e74e13e28abddb167de5a670051814cbcbab0210f52b627785eb222c86fca957f03fc3e8108e3dbc2cf4bec7440839465af06a02e8a4b2c0b22e2cb3bd45291b38a8d2db50cb17961fb0fce4380fce3a057d87fcb2438a0b3f4d411709a670355fd40e2565a35b80013a9a4e601d6f353e9c0a6796c2c764f8b990e98202cfefcf119857e1e31b38b4f5bfc9a8df376faf422dd919e15b78cdb3cf4387e7011249277d79568fc361157911074ca4dd9b68a05a5e503dbeb3775da0708a49599ef7c7d8c5dd165d0a880757b0044249e135ec8fc22264d341ce464da2f35e4356e4857e53debe5dbe4d225486052da4d51287a8fc63273b5a6bad8a878dd9d9561c0f6106c359083b8e64ccfc01c28d28072c0f4b857152ac3721683c3780f04fc2666c33edcb663deba4b00c1192fe8cfa1720aa95750e933baf158ebfb8db3bb4f17f8d2dad54c07d3f753b2fd3c619970c17d740f992271ac9ba274f1b3af474daaeb825286ec189ff491e0d100cead2e052a88add83e4f731129be6261afb467282ec3d5eaf574a6c4ef51594786f856da86be3ec3e599e272ea8cd8c001e0ed8c14ec84feb19987173aec2ab2519c21865c48ea857b8f73118ff15d3d05cfbedf4e567d8851a5c93949d2bb568b60b749c66c3192a722ddab737ba774efbc4c804e126d48ce483aa889d767e3764d25242330bc38da7b6817e707c56881cf40c619bbea781e1a56001c30e28f55f7015f28b91a92b93848c732b2f2c53c6820af94db83d38969743093053f2a576a30d837ae40dd6ca2edfb5b0ae6fa211d83a2f1d767608e49048486d620f21f2f922e68b000762654bd6a3b774597cbad79b62a3d69903c269b569ae138d8fe8cb0eaf650e53d546f73f070b4a3e8090198c0bb035c926e35bda4181af9ddabb9676f339802da57c2de70c0144a22e126082dfef1e91420373d261207f6f7414fcb5316a55cab1161c0482c6dd00f07a2d2b430c81f6ff912ffd9db81dc607a893c583c8ca2170b92a43e95a5f2e9771df8236fe820f3f48a5889923fec09b10c398079c98f8ab043bb8fc8d274761bd3c2c616089a7bb6cee20436deeb48d66c1cb06d813cc6efa8921b6c32f2910faa50cbd7a9808efe3e9238deab9653766ad29b9c7f89e8811259b56d2e7589d5a5cbbaa04ab8313a91293074f8dc23b58f46b2a6d6a576673ef3bf2e2445286f0b8fd36008e4ce724d1b90d647506c7ca249d4fe26f0f0aa3866f699b74e19558bce8e2f7c07640d1d34f3a91db72573790d2f37d08277ffb17b621c44acc63cf386059fd18e4e33d0ff48436ff0d8a4f68fca2b317c2cfa49efd48ae0f5e75494153cb816307fff847107bb197ad985deabe6b531292def44d0c3a977ee7537b44e31f4db31dc9df232058fb3741d6a7017b8ec643439e2229bf364d2402a1846fa3e6e5358da6805aee00f7659d3b4d43322dfe671ff81d51f11fa4a783b9b39889821815f15a2d3b2f512798e3be51eeecb7275b25137fcecdadeaa02d2c6c3349472d8e19560a25e7aa01107693c3748013fe94245dcb2e87572c02d5f608cb18b83213054353f6ffc1a8831f8236511107d4ade54e74de32f24a39a82d80c2991d7a7b9dc24266a41bdaee54a4316aa4208a01175e980e1f6b8e8274d67a2d10024ae1317cd0d97fbd214ab395d4aecae81028eacf9edd72bc374f24695d1c452319cfc3ffc232a9051f9e65d77b8952857b6abc6df29445f3797301131637fb0ac240bccda4778c7ed9aea8866a45847b387c292e9b1acdbb4bd8a16a4fa158a0183dfe6c4e6160b400ed493d428af089014686b46383615a529dd487676ef450d80ec3580e5c4a59985a4d697f0b7e18ed045b5843184a20698f1b90c432b9301a89d9885f2fc7b516ac21873292242d8131e788b8203856611b2fe3ed697fd2f4f25821eb9d889dcfe7a97e4ed024ecbd5e93416e81f7770bc7b3ce9d419bf1406388ea6dd5c9df5102823ba7c3539a24737a8f53f67616082c51dfd611a4588d3603455d84001661e6d027a4690173125e24bdca8ce12b081ec61c2bc9d4b2f5c0903cc0fe4ee63b97dbc332fbe662d77c3d19851e930a11607d41738e375770b543657b1a5bdc0bcb3bf0089d1c5dd7ec432f1e2cbddfd4c6c809e11ae64568f61895dfdcb8a74f692ea3adce6274d26173bdfbba0d0db8302f41890db0f7e4d2c633292c23d9c19947f7725c759dd90365e17855a1c22d4b14db3e71710c94d9fd5eaaed71d12d4dea8e5645144b000eef869c63e7cb4f4c2be34efa3b3a5f15b521140de6cf624a8c7b66dba89ff7b710fe99483dcfb5b8f1d21f452a884d4d93098b7f54a742d117f59209f7d73af983faacca7cdaf88e71f0f9374c8f0dfb43adb907b4ebce8bf0bdebf47e5561353020fad2898eb8ad0b91188db0244bd3e2148eed13ca18490de40691ed41bd4ce1c7388a4eb7e2c80828c23a7fd92e05ba2bcf8b519902477e51671a284d6707c249001f1d12a17b240618e03d3d0c380b6458be2d566ea295f39bacbb33c0dbf1d3dc75720cb733672399ab672c342ed00913af8b0f342efe9d9dd91199fe96920b240804e1a3061c1419505200101e31e8688101920088f40103470a0e2a0100240f1a75a06010090145f0c088834507900008c2478de41d058e810ca18fb23fd8ceef1ae7cb0704d1c7063b173850a200103c31d0690103120188e803034e0a1c2a0100441e1aeaa0c010090245e0c11087850e900008824f0d702864a04401207862a0d30206240210d107069c1438540200883c34d441812112048ac083210e0b1d200110049f1ae0740cbbecaa65056e73b689d116c06c66b13970adc4da20d544a21670c8b0faa2f9be95332309c21cd3770c7263e5d3a4042e5cfe6f9327d51a50da2161f3223b7d5f6f26328226e26f59e25509e7971b3c38fad0fa8eca32912c418eef3776f9b0f2e92402260cbf37c99f5acd29e790b0f390193daf361279c112ff9f2cf15681639769ca46aaa2284fa8ee9f7c4e9d341931b5b9241f2a0a34f6df2d7852e55469200d638f6b763d46d5e80638797d3060a0719d634efbe694042e74eef03041004c223e091ea1dfc6b44291ce461eb06a3d3d31003a1aff452dfe999b889611a62f3b7a12950d8910c7d1a62f8b630130bc8df04e5f1e502f3f023749ac7c561efc302915e98da3233f5f38898ba8ffcbe30283283c15826eee0f1079aa4e575efd0f8392ef5c11d8cb6cac58888693a18a103fff3c7f665e61c3f3c50960d2f65f310419bb3ef19da33423fdf427f7c759962d3f1726ae90d44899ba150ab9869bca363a7b9d8dcb718d8ef7aa68d04fe565003cd7b982859e9af3d643f6ffc2f7a19a77341d7a77ab0c0beda44a40f13bc8e0921305f2f3d03a5937c7cad41d27252b5832fc87b29875e472f72fb3b302c3f5986629553a8691eaa6fbbc5b879a8eaf0b07437159dfcba908561de40ec6569d48401527ee813c50add2033cc2265b7fbf1f229b1ef72f9925025dba36de48b9210408ff9bcf9560a212d1115405a2ac8a9486528ca0a91b5b2f6174f13ae72582200111b6b3c3b2d321df77199c0b3974ff62045287952b9bb792e17c0156cd94d0b396af46939ad3fae501fec238e29760a809dd0e9cb913195670adbb5ed15b86ee88dcd28267826f629f496f5c1f860cdf471001d7795514a5a58475c26bcdb5cd087b87544fd6e33ed28d1431e9fcb4bbe2b9c481a718a22e6282f0d70630f21b9e0b174bc1fd4ba1da9d1c96c16682f074764c5342ddce8502082625880f2626b835bf0687d3e1f946787b0b7a93f20af7d12d1694a361eaf7308f6d40e37b13eabcadf114e22f24e6b3b6ea10b5ebb5d49af79e5da6b945a70db2cfaf75ddd329f91d3c922d02ca1891ef6d8711509094386dba43f1d94c65d223660446b5278c24297256b37807cfb42e239d4d56046a84dba6753358d91f47042511dbc3bc6d5e1547d57b50984b8fae7bb1901b56bae4b91d85155c588f58ab683dd3dd80391d0777d6004d3b3d9866b03bde98a5967b8cb377320d58b6dfe87ffb9fad155375c3f79f503bb0d174c8304d2542f18332bec2a188c81607e3215f98bc7c45f74bd3be8b1217f1c0a83988b13c1d6ea577ee68324341e0869399a9e6372a90c7ab2048d5b751ed6fcdc4f8aeda35a828e72ab1810724314de9e4c29441ea0f15988bbcaff07e835c27e61a66f7592f2862e7f08619de797630cfa2231199ca89228ad173500b695bc21d8e44d3acc136ba2b4841c740e75ee97e5fa32d4128611926545be8f6c30d2dd9a232e78cc15d7872e2eb3e973cd739acc7123fd3fdf31eca8019a5a4980a31f6fb596b1e88f66d66ddf8b26d22d7b39da3394eee154215eac32f53c51d56436e1118742061a45b26cb4f7975bfefe009b7f5f8fd04f644bc005caec6613ba91ae1a9f158d2de426e55f57a62d3f2e5d5e30fa48903073be196f203b705244c41dff6fb6d2d9bb4fff2ee99da8fd5804d35fbf86ff67663b27438a5f45c7bb43fdad7f2dd2aa781dacae574cabf416674e16d57985cc6abbd07cc5105d9dd47fbfe13076f5f4e66cbd1d8b89540fb5ac7b8346aa1f535b179a87b7fcab9cfc1e1e7cca7eac5f2ff196a2d80c1f915e4766115998fecf51e83a7f611f58ad0e430e4002c69432bd1e4be5345c252a39169ce3180d9c4810b5b8bc56a72e8bfcd1af0bec0d1d30b294dd4a11e85682470e955846c225abdfb7c47089f053c2ee2a64050e30236ea045e53b477fd9f0e111b4dff1d8bb3dbf71aa7ce4df8550a84851e488e7befa2cbd6d3f1395a811e43a7e6b53aa11aae98f7c1ccd7c1f8b08bda74fb7b99e2296e4db7126fd6eeb5b111ec1135fa949fdf4136a1a4731918c2a7ccfc29e093355fd18816d317751d220ed36f1d172fc8eb944b10703ebcf543bc40c57027047cb7b5f3295ea328bb890ab7971c55a7808d3e9b4f1cfb5d8a3a799f4381abff4a4fbad043255a8b4201b678a5e5f37d89580f38cf41c0c96aad5c228a07ca17bcd9d870fc14b008158f8678f3c2b1f6450cd5157b43057be901dd81110fa5751212dfbcacb67b30d7ac9f565ddded36764a9294366c2d2b815af6616cd0a22001d230240960e9a7239086713000b442d5302e3ed363c8c2b0b3d5ff0eb7f68e436ecf6db74540e772252657ed2b714d284855295d98f5625b843485dc63edbf132a673531e2e58dd4d47b40484b1d0441e6c2965c30f084628ce1e85fd48650089bad0da1b0cc23787c7a5e27cfee50e90399a9f5710fcf17602dadf9b058c402d80cff7e12b4de394e90fbe5802d1feb8fcdf947602451fb7f8fad08f237f62849bd09f79664b055d0bc5550ee0a81ef1075ad773530293922899c7478d3914f8baa10e060481d8cdf2247430c4163ada350ee81f279ddce7042a520fcd837504c0a91162f927254750dc52664e063403f60583064b3512cca0e01f543cc52cc2d3c5332985111963f4766e396f2c882cb2d1435031c962f442ffe034c39a38ed0d02085cc8ad367515e3dfd8191bc0fb81231588ba0f78e6aef6dc3150e17ca91728874815fd29a6d349a37fecd774935029eed42ca814aee63b7b3dec989be1438268bb525eb6d682ae04c634aa20fbbaa70a2386e966c0b0ba25865ff6c4cce114ec4fa51aeeddd16410a6273cf2e0b3e6486782f15db75ce7016ee369cd0702165b61e6efb799e8970c994101701b94c9b1285c09d8f2ac061e09d963ba7e06bc5a0530929b71f78a00e7cf6a96b0d6d342b75deb87236c4de501c504ba1e73ef5eb957e88763029927d301bad6a4928d643cca44b6bbc2e179fcdbfd4fa774f0e1f203f92965b7ee03ae3494bad7e68a586eaf6f55e3212d57901fbb0d9d8fbcc18b3afa14bbc9e46c17f7778ba945871806c4011073f19463a88b74d2e7a62f8be8b66c852c7454f944b0e41402c563ad2838b1eaf73d3c494511d1f3e33c5b8e4830dc979214efab7ab5834509ae9814111c62a8ab8c84501eab79e0e322b751379b60b20b7c3b45a50fee36d7c244995a7a401bbcef67dec2f9929451247816c71ac0a4e982b3631b914036270bddda77135b53b690c30fad1ad1c8acac6a08188d719b217ad6cec94a1dbad2fb43f0ad9d5831511b4fa7eaf66f14af99d44b9d76bc66a05cbcd9e72db0fcb0b6e1a850532ebda5a4d1d2250bc4206b55d55b74f8220f55485d60c2e4327ec19ce9313263c250c8d3ae611aca00172a0fabbe126d80bcaedae168d5256f31683a17fe1932d278b5151c22381a35b748095b5947f6ffbf7e499b58ce6b620cca61de8a0fbd17d7df8fccc62c83ecd0f39d7516761e65b135496684838a6b6ca33a509d1ece2270c3a50ffdccf1995b522fb7d4542c1ec0cf12f10727e60c699959740f9bc772b63ab0823f51b86221f72c878b61c47cfd20260f84402441e0123e913d3c487a9cc69da83826b53b1ce0472b465f3f619303eb5d603594cf28e54c8bc362c6d6bd9386b32a5f915b622d20b514ed9c19e3c278c40441f84d8adb022eab7268e3518a5a167e792977256b296db38839339576d41e6899c49132414dfbc659019ad644a7effc371317c8233c987f4566170de0b83047c8be98c50afbebbedfdc1258ace437a7d1048b274cce308151a398be7b0c3ab8577262a841407283f63be73d8243d32c72cbd0b01fba3f77f65a535882d4ad8e202ddbacdb10fa4592aacefb6a6aae8f92ba1dcdd6e2988f43587b8bac1576fcf899034fba1a047133d0a7bf4069aba0e4a144ecdfa9dbcc6145b2d11480253f09b08686910885308a992831acf761eefed701fd11158878dae22570ea97d400eb3160f7047f92cddc92d13ea826001bc1bc72aaed57d8f1d0fe8e2daee8a1429d16167f97efbbdd21dd514e74120caab2a5b5a4c028b2052c3c6e0db24e548dc9bcf612b8e8f6eafd77065e5f2ba028f750307bfc95e169fcf50ae46532749eddd632817b1cff99535c3f56ecf9d395a0ca677f63ff5ea13c79550ff70ce508cbd94e41b58cc15d9c7b8a1c23c95fddb2d4239f9299f2d9a80b44a8fa376ed9cc3153658e9aef1dcea0bad8cb50927242d796439922ff6148f4b7b57cd826220b446efbb5fca84e270c3b79d3227ae7bf0848b71b3b1b96e06eaaca6987b34b39f671f747b6a3122e3dd5a20dd260f9991307dfe2fefd9ff88256065e3e8910284726570664f6e4a1a9c2c941e1d0831fd57ec48d700340b344229dbb06f9720c2f7bed6843f9f66a67610d93e8729c57f8d40e80ba921333d7af1469d0122ebb1029bed8d4cd4e76a1bc40975b3ce42668a4ebf25bce7a398a407dc6d192fdb44983f1c46ba6dd2e52fd7fff6dd3cd30e6be1cd10aac41d40726745b52e3a6d8a3910c6f382c5928e2b3e76c3e54fc3eb6a3aac0c562d8d386997b90e75234253aa23658d50be328f470c273f4d5fbfc570cf4ab379f50e2f724218039fd7e1f2680e0e9ca9bf4cd77c93598f66eafa302c7a5ca2ce2d1d4fb3928e0e9e0664b17d5c2e60db74d3a1c5971f644d3368d7e6af6c9cf8e28b067a01c78f7ade22f940e0638a7b507a282e2ba56f860a73b040ac595e05c94d0d383add515718bb7b7763d5b8ddc010a4fe706cb24f6b2f58148844b476e62ad9f4b7c369bcc78365c9bbb2f2eade525c8dfbe107ded95c8c48cd70fb2d7e2458d363994fa56f8648206ea8254109ee3e058b0a141346502fcfa0b436874e194b8b07de96ad8c11e7ab4017d9ad7536c188ed942e0ffbe11742c7792e7c0eb11fcc9a4efb7be91a08b9ea19bafbffe43b9e03777bb1bb6f5db99f24e97649907ee6ae033ec661b28ab1922d87bb80dbaf2c35ab198ad4ad9a994ce6b6338f1a2308bd0b4c71236624ee28e095bccb5a03af49fb8f494e788706c7e7844ac5d6ec1a15321e35efecc73c899d6b7919cee2cf922db0d682477217780c80911c129a4536861c076a315bbe2760bffb7488d9cd9800f3d1859c4f56fd9f221064bffeb774c0539a0ab56f2aa5662b6b85da74d26559501fdb8643f075e032e2a696df8fe7b62b6518b2c364cdb74767866de49cdae5ffcacf5dbf42a32cd1eb040a964b300293460dba895face4eb93e4fdf12328cb599e009ac0225677ad88273f8ac53f7e2735b4fad825f5bdb5bae4f016fa201c6869e1c85f878859f69fbc097e56352471b233364fe8549cbef3884959bc652c2a2390219bbc592a468e946053a8a9bb1dab642c0e81d774f21af95678b5b3811be8a69981a58c38ff4115188f6237022b9e35d6048ba01e934709a7782f351d8a68953a97dd880d62f0255af03449d5be8de5d85f0512944599002ca7c379049f40b5f547294378501be0c1393ea17499db8c353b4c1c3db917930e22f671de502df607e664a68950249cad3fdf1a33a762fe2ec8897ac8a25b864fa99507951ab6f8ec19728eda6aaf8ac7e28026aec6211625619d4f09f66c46a3998221a59f5b281581dc7566a789ebc87c4fa4834ac688b9b03bec21190c52e0bc433634a5b86ec383c1f972203902dfaef153d214768c65ca4c1d249dde5ea949067059c11f83952917b0f20d5f2f6a5d28182e8987062f8424c8bd38b4ff0357197bb915a3e17d357d9a407fbf567831a764a1295270ae9c37ea1204d8f6f9cf055be3d2a323ad8b3014ddfc5d6e2e6abed884a3b4ec7e730179055fee633fdce21e8846f12bf992a38101b7d20c185334793339165334bc370477620d46bf4f415d6ba6bf93b451383e90c34e3e8fe19e5a29f49f1b6ed0882a846cb217512d816a8b51ac2639add7725ae3d5c2b466d9988c69874949d9dd138825eb1845696acb095a894f163cef46f8f40425d13a598c7c2499c2180bc3ae131057f0067bc3630a077832e765dbc566f1fab0ba41f1f67bb0c17272125ff18abdd44ce305d5b36ddb841b05d60c0427302c608d00470063071da25eea5f5274bfc22ddd0862b889d3556267f0114e1b5f7f5856f232422052f2e29126ab467d0879b506558a197e633135911825590b12949251f409ac9595f6bef2a13c6e31d7dd94d207a32dacade45915e801b1128af4f9738a39d8cb4c7a4df8685bc13dd3667fb035372adbae80be173f875c5c3043c6298599269e930a0c1506360789da4e39465ef3e3cea2dbb827af7f472a758b7867b1c75c20c17e2067dab02b0c458d1be4282918d94ff53487eb91869d62c7a921b76dcdbab8875511253df3ebd5a7275fdc6846b50124f7ea690e6150e6673efd44a1d31354bccd8c0ad0178b145beb4766929122a5d04c8054f80c0bc3681ede5f12d2339f981f28a8c993ee8def9ebc8c6012a0827c1a76c508354440c1a8f49d62628ebc3ac16cd45bd3b83b817ad7b105ed9f8765cfe5ac06ebd611ed166194a23e392bf3ac63503ba54cef0924c330653dc0b60207ad3548d8bf38a163c763544d2470d16373230edce1874b18360b1c93b56c34c6069414510aa6aabee6439f47b13452f92475501002f8330afce1cb629bcc76e9d365d5b54393efc0a886dffd955550703c3d678ab27f0ea87774d7212a968fca2efdd1e5aeb061edb5016d7e1465ff26e0dc60d3e1250fed84e4bd22d06cf1a47d5e75ef177d9f170d22473180a39f38df9cad667ec7bbaece46383db1791d7f7eae3ffc4367ff7dbb7fe4cbdd992d54003613087ba221d8ea60f3c9508ad83429b90acc1425610696fce14bfa5aed5aabcbbeeb5599922156e7cac1975bdebf2663725acc3125d9778539633cee264a4b930649c1b17fa81698562273be3999290589c81cde2729eebb4e91f77dd7ac9d4dd36a6e6cbdd55ad5cea484120dd26d940ad47edab6c792c64e07e95b0b4068d05d1dc27e32b1200ec0226a696ccbd85e43a42508282dc05ad71e4657501c4a3789671739cf5cbbe509e9e22c51a6ccfb67a9ed23ad15b4e4f760a7a56a040ac6444d5b57f987982eda30d4e05b82fd93ec07a965826c3c3e14062b6f07e9c143b13bfcaa0d7aad6fba1d073339160339031a6d221f3d04131032e30d7778a77a6f70737dba6f0f80bb05242b08e55dc57258e5e302834fba76d2f3e189e441eac071857bc3ced5cd0bd92a85b830fa0efabdfc5e6e50775f02e58944b9caff1dbfede6956a3fff59eeecf32ea0c88967eaa7181f524d2cb6b7ea8f4b27ec1f431adea91cd9fdd7a934f4cf079d26a66a0058de0d33c26d02db694227c53b05eebff2716878ab4e8836efaa33abf91bebce9cc9e97255203bd099d96209f38491ef52c912e4a2ba8e6d261897cfdef676fab3045a6a573dfee7ead2230a8957461801fd755570fa6226d9af70ff7538af3b313ea3a025319d6a4ff873697685c9204bdc05794aebdf5621180c873851b13be1bc13b5edd2312fd23fea8c179b2986bb3640cf2a3e26e9185b5909a9ed03edd725dde28590c764bf310150c2575de6f0de2ba0ff9fc0409c2b607b0a662db8aa5b3c91b5ba261be0fc3c3823504deeca140b1ff737fe505f068d3e23a94c2b98b6f2089672e56b41dc1b1bbe6f8196f0553e278ef27e3b1d2f765ef84dbc994ecffe01502f4fa63735e6a7eac902f80ff5c5a27a3138883079934b318693748c6a131bbbc4669889065babee5edfdb17316ea037202e9d84b7080dc824cc5256bd10e8e1260736137e7414cb6cb7685d69ccc6520748870f33b0589e21d040514d90ba67642dde98ce791cf33d18d0ffd96060024dad62badc1d653629f4a7e8861e3f07186f1ed83f2c4f21c141b9fbdcf7d6c5e4f14921f2648a0c1c3cf10dddff6f846d806f53e61eec410b83fb7fffa3cbbb7ac4dc98c5a1eb25bac5635c25ba64a27ff86d0c4556136372f36f83cda5a22375954a2cd5e56d728ce38ce71a19cf3c894b4f9aa7c1ebc8db3b07ee91e290e8f502058422e6f1f2960d444d6403aa0417c876d8b3a039f8880f23a63b8e2ffec89487b18bfb24e13b8303c6b2b8850c78717517303c553197266fc53ada7a76f057537657893e7fb97b843897e870dcde5831f46946e1e336fc62e0ac0f97061a205931afb6ead36aad5b720b067ec79a74a905f50e987ac292147aeb26f873ee70d07fb7f01b2466c28fb9047cea01c15daea05f9c3464111d053fff93d6e00b8a628a4847908fcb3e09e3311091475db3534c3a6ef4b7546ea5a2432649960b2f69f23ed2d2fef6ab13045dd924a5df60d71d41a91feab29cf48d4317462fb1c86bc2a67bee5f59a479dd57cb6ef571339937fe43745246d9b30a723d3a8e1f5dc0b1137c310648ddd64930fc89e19e0c1aa644373f836c0687cf31764e57c99058e1768f3fd3c7a9ecf32d53e78ed9968f0f21e383f2fb249b7e2bfe7000460f57d2ba36f3e19ab6dd6360b9b7d48bc4cb2b07d2ae036a67b45b624681d6678900b465a7a41a8e3003414be663fdba9f3d62956e69cfa735f8562137432794005db389c0c363069eed29f897940fadc91ab86109f8634212d900f0ce23560704ecd289fe0c2b06a8aceeab2f08fbdd7464517543a3f283b3bc331c9411418c248987aaa8fa75b55abb1d9099716a5c1353659cf5decba933beb0bb898badd158d126578bff6452b718ece76e48c22d4136b8f820e202d3bb30bd20d58532849090aef3839d80b32c5e4db2dd56573e5f68e9783b533cca985450363e5412188e2b4061e11f7d484cf88791d10ef2aa6d8201c262e49c9b1abc95f099248a3a2158c86044e36b84a6d0e6d74d45452bc48650293b54dfef1b2f228e340312242ba47d8fced895157e0d60f0c808b5e3ebc97c1d70981472088abf48806250cf6216c8745ff4e9e002add36f0874d245bf14fb0583827eb6e2401c50cfa55428c1b57030da2f2e9f151dee1b9fe212722bda4b3a740535c45b13fc2f8b7e0b5e2fe02daec4f163a765526f15819f0d2f7c338df7bc25436c5e54107052745d7b73f94f43fb7ec213620f56fc3394d942429a2134ba0bf54f5c421f47a4862078bd2b73e6ab691cd3b56aceefa982739832c9b8bc2bc6bb6c6f41d50344242d0e0c0a7781a0741eb09093d0507ea4ce01e8245c9fbbc985c164d6bb303dbfcb7b90dd03e8bff439f76f0025ae641ef02af7d095c25d78ec4a43d8ed6f5107a780e4d5e6b7607ba4ce5699a74cd704dbd646a06345fb255568589bcf2a34ad515eea826a1d3f9fcf772a108c5bd7b604b96447781a5ae1b81a95d7618bc18d8099eb8b874c19ed59f29b5aaf6f7c013e23d9e8e17aae699b9d907c7925e983d286d46290b575c6360a58ddaa0a85b24d17e818e40a14013928b978ae1fa5e65e32f98d5d6cc24fab3353185ebe26ae1f907e6aba397c328f60efdc4f174f231e5a48e143d69bcc4f4f714c18b118f7c5752cd1b1d7aef7d37166da4ecdc7aa7e12c38bd9ca75582a63a09ecc9dd21a8e97cca6541e65a7b8c29cf34aa7e0c35a132b677d1f084dc6db398f5122cd855537b4c43842ec82ffad4b8e8141fb56c50d40e1fe34d9adbd33e01097f01052a574fb23060b38554eac4074d850105163bc39a223b668f7f03fa0d6d686a146142d81675eadcd6d656dd379d050d1d902c350a4e5b8ef74617f9730f0f474e7447c675808181ed4e19d9fbed9d3022323a7208f7c55d9284b1d30a21e223a501b5575b13f50eaa82cf1c7697543e6d71f26c98462a881c5b0bea7f4d6647d280e3911eac8e5558991faa1a513681dc29a9ceca16882f2a678ee206f2a43d545f9c98f5c8df930c79f216fa7b4ba4a42881a505f3cfc824e0ac68cbe3ed60b63c83ef1bc165a01019f270c1d8baebb0385200db231502af73b22f0e877a0b191538bb98757ff976230cde9550872f36d0eb6242e3551bbcd5d5d7a9936ebc51336684ed83d3707265d0e1a52552efba7b54794323131eda0e9ec64cb497134ed0b4b1d8823741edd9401ce8a3929e53daf4532f029ca389a88d33914782962112a9d066f85df0ff8c96f2e2363de5a0b358103fe95cc5dee35ded408ec2765e9ab7ce23ec69a0c8c29309099fd3c0ce1ef6dc3dbfb6b96109ea49f63b18643dd2b018829e1e4a26e3f1c31e1b4bf76267d8756c3d5af5bc26c22d06fcd9b8df10df082531355f9198c3b97d0e1db6d8cf07c54fc96ef64173bd25eeaf55d71d691eb4f2db2413761336e4e553335151cf12a2ee46b63b3a268f04573b2e1e24a87f857968131cde2f3451b3c6cae9c743fbb30331750d28e0ae090d5cdc024ecf3110df9a9b0147ffc4a13e2008c0778eb475e5363a69fa86f494ac4fadea5431e94d10321551b26106ee5aca388237c7edfd3328d2c57771092bbed6d25e8bf8789d7590ed0d1662070ab9ccdd16b02405f1d6aa406bf79e9a8d7f1f7b21f6541d708fc03d0c549b7b420b9582986818a6ec82f89f73945c73ab61c127836f4d9f7d114f7080e22249de4aaf24ab07b58a567d8e2bb071a015f29b0de34f07fa57c16351a8e5d56fe2cb06b256ab59ed744bb5b2f86abfba1ea49100e44846c5c7bbc381010743aa111cc48ebc20aaec8f46009eaa94aef1d1b0c1ae4eeff2c7ceefc42cfada83ed7eaaeb7b1142b289d7819a9db9441c3871741d5cefce4ea13c546927385038cd5839210aaf6abfc15c65723ada7185b12e822f72c40519e2c4d82c53535188064c0b976ecbbf02c55f8c19da6c7fccde517a84785fb8e77e70d38409230a28ce8db3da7f73deb6a559941c2a259076cc96cdcb2041257e3abf6b1adf3dfc5dc9927eeb9f576f2b52848c5ef159dd14300ee93737b1c594fcd726df78dd0dde2220c0632ef6f71e5aacb589ee8a62c95816f326e54f7fb61f053582d206d6441e8b9639ac79168501521492a85759808909d093a004e268c1fff958871291ecf41846945ff13a1a2172627bd5828b058e2cbd5052e109a317d427ac79557de33979dc295c2c49241b49c408593da2e3fd6149547e4faeef09fbf8d1a7ec7b2f50109b4d9e9115e2bd8ebf211e96b81d66c4c2727a3c47e85523b2708a10b2352e67ca427b2d63144034fd12608f22f84da8f36e1c395e0cc62a9aed48bc20ca403ae9e1a7eb1fae503f6cfa3ec7ac184a96701499e17103b4310f3ead3bd6208508d624211642c66af769ab95b633705401d71304b08427d5d85e6d27111b55bc9c65fe641d1678efc82ea58f29ec164dea632f676dbbd6027d4b1c4970ff4e6d47cc89cc65c36a7f51c2f3ccdd0e4214bc899e5bd7a7d92bac893bb80bcf06d7b455e89fe6a68b992f7d11493d6e61853c627388b66aae595e7b8398b524b39a6fcd0b8cccea5871cc8c4d3724839b3a792507e562c79a6ea12db7781bf0217d30524dcc5c0f6956e9c794b2e9637a20a7da550404b0a849e77ff62bcd9cda56fb8b8dc49866fda6f74919f06585bdd09e9b5564eee1e4ac9623f50a7c7c7f23bf0b1836680a9013d23ef69336513215cb2f96b5720fa36b908436d4898fcd8a6b8f227f62ef9996b403e229ef7399906dcc3802cc8c0e8ba70fcfdf93d6c535edc78fb31c650ee93ba78a2e70cc75d672b3c61b31593352ab35982d0594afa8d8ff547deee41beccfe9a931b6f1ca0cb2def0cda7aaa6e1185f3437fec13ee1d1801fbb4da074a48f8d05f98075b0cd6d17640fcc072bd1622eab9a1929a14ca7323dda8537b6aa2fd253be1368e30b819289f3eef535d718f1e2a1aa48a5212288010e8bdfcbcea01a3cfaad1a3474f08ffc6728593b96e7412121912f584d8b4848a771643d4e6ec76c167830436c49eda88db60c8a85052429a1d340c6cdd1aab25ae9c065e160fb650e61a8b3601d7036943aa717e703db6ce211d717a74cc3e5c5339ed9b3c28e59358a892251ef1c72002b91b098b2dabb747416503258ac1c1254af095a150b23912e0c3a2fa9f476a869cb952e74e3263243a3395d6aa493ef9dab75a489d597c9aff16ca5d51c25c97bac7237603ece25c437069e301bd8847bbb7ec217c2d95824e2b4fe7e9cb40823695d5154f9f4b926f1be3d6f723dfe2948dd654ea09f945c0941fda8d8efe4290995e2abe12c800fb2a4088be33fb8c1a833876cac17665de2b2197cf4a1a8fa4e37e3bdcd28a2069a5f7c9709879b54a612e62a4e7d7e3f09949395c0687ce28cac9644bbd70a4f6cab1349a7dbc9d167fc4372a83f41797344590804decb9825f4f1bbe5d3cfc7dc238773349c314bd5cefd9f9209b92d910acf3646ee07b3d2359541c4d0af2a4b0e29c0f50d54176cc9edaab81a5876ca44f365c2d8cec4287e5e7b46c97f02c194a0888da47cf21d39120b915f635424e10a215f82495661acbda7f8f96f3ad3f1c1e5eda6c2c95b24b069959cd2170512f0b4b805cd2c491505a744034d0a00205ce14be2def80c2a22b112829305cb8836d17a3117d0fd3135ede0cab78df857952d065190b47e510e8148f25a66e776b6eae02c31c4dd6d39ceb768d2d4e548307d05e8e9ba74434c10d82407aae6a67c060914e76e46b89e3c3465d18aec3e353c866a6d0d0d9d0776e61818d9f4e84b5edf5da95b7dcc7f6500c62ed1ab7e6ae2596d7ba33e174b848a48674402496691b63a4e3d820637dabe3e3ea621b0b0cb0b8c242d0adaf2d1b976d8bd8ed0bee7453acc84f78c05a5145c218f1b21d060ea4083918671c4070cef22a1132498e149f67261e5b5befae7f2daaa95c99d6b453800e03fa6b81e78b748a4829b7ce859131ddd0397780c9e74456b90e0545839d78546480878c8af74e9e529d9be50630d588a388be4955eba3eba2415a85b0e84f00f2f3e18fc3ad3d82c995e039dbbfa8f2d02c3e85c35df594fc185dd467f96ab830ea73a134a03a76bd29e1f20cbed4059af4345f995a93062553c7fa1e410ec9b95fd4d598af33222b2189cd00ed3e5b81613101a61b2a57943b348548bd07f6963bfbe7e260365589745c55674c7afc3fb3f1265dc9859248f14c79235d3d9261ff043df37354553f483db3dbdbd7df17849a19d7eec4af3a1eb64b985bd218437505612f4a12f48c5023ad955bb599b15b319c8ba30c40fead992859aa90f341f92f950a53adc65291614da44841c5521699fdccfdcd0eb142737089cfb7cbc6e14eac2b90bc27d9b477ab6437743c06aafd35c0f83fed69baab97c4b62fbeb8e51863650b380c127ac67b1f6bb6e16bdd017686c87e0769c52ebdddb1c62025a0cdff25504a8407f542a145e0106ebc08d00bc44c5affa21dc40a35c0daf1091729f04197c01596ff1386d16f6462016a79c07ed75ff26329d9796ab680630e86e38eda4b6af6dba7dcc71a0d4d3d0575d8104c6b1b54dc450081b64fab26053933b3dc3b4fbd4a3a5d005d57a3d9c7df02ab008a57fe873c1890016dabe8117850a46f9548e3821d376cdeee96232905bcb300fded9366c4eb99581b733017278b63f65a3cb44ad70e3626d59a95bca3e6cc592f1ab37fdf4a617b93baf46aa2ba51eb4b1499cfdf29f57ec460259c2bcaff0468b827fa33bb73c02335421a67549f7effcf997e5fd8e04b3f6b21ed32fea7a7f5b64fda298e81f390ee0f82b91b308beb278bc921759164876330239d0acffc4253397b6bbbe55ab070409d12d2eb09c5b300721e6417c81fda1eb2e6cf6e693bac8b54a09d6267b01b4c7bd9dd90350526b70a67c10fe3b0d7bbdcce2ae72b9ff81169f11708ef28ab1d246bc34139d65084019e11804464dc83c37416eaf22f1fd46444aecb013b47ab16129654e6dc4660b0b0ac466a012b4786522eec1f673fd04c24a9274c786e5b3eee410f73d5ec60497f03110067b3a6e101893522a5643ea33361301e42f99532eef8e071785d299d9b3dd61ad80d463fdc712122ed178e4f7f1dd83084918f0525c9648f8d6427230e734175083e8ac03f3e21ee49c40bb275e8b549f19045b0bfa1aaec7898888b7a89a1cab923e198d19f182eba428e9835aa732a8ec88b6dd0d73f310471474b7df4f614556e264365fe0f900348f9eeed2102863b8f7eb3b23ac036fe93bceb2ebee6e5840c7f7771de0c13bf87d47b332d19f342f43ceef983992dc5fd98808d5dc3aa90fff0990078e6b49a128fc59f95601c0e165e6853471cb976c6e478a0bb8c047b0a1fb69a90641819ca8cb24cbd4b77687158cbb914b51a243cb139e8cc7a47818d057576551825509234403d4a99b0d8b044cf45122ac367889825b4ec76fee0990cc71cf62aec07a46ae99144a31f8ff7e253f4f80a511c82a77786ecfa2d26ea0701b540b8c7239973a9c873a44752f5033003c709ac46bfaa7055ff82bb2dc1b1caed629245f0c0620bb35239a0db488ebe44c2270bb2e0cb7d1bd82222213a661d07787d5ccffc36d10a69c2cddf02e2f6529591ea039fe58abe8e42c0374a5dd75001952fc065ba432f78a19b1aad1fb67c4cb82387b6a9eaad57543f84f4ca399b8817315da6ae3e6387a044824714a062a50db8ae3bc8dbcc9905891c8dedeaf42ccce8b900a15f5956d36945a4d739243497587e15688adc4565e25d6bd37c8971db6b1d4eda3d4c47aff938a8281d7ebee9890598bc7ba146f275e26efb35324b7303c2316fa98483eaf08497eba5d8e1d1141981b89acc5f32f7c2b2fc277e74bb20b173f0353bf780cf09b882509728a7a6aaea2de58cf2aa7b4867719c44ef9712a731dac24c04f5b8aff48a0266c7e0704752a4432a87c3915aa363593a8e9b927bbff0933aae0d5a761620dac43afb018e2d3e99ce9c638d5fe73bdb29563582c1e246435a89f8d205e268885b2281c3dc4d4fdadc2eb880e6cd8ba732ab5a87250c74fe1dd78795b37930bf7096705b63c9529a8007d18122bc88022fb151ccfee6997988ba598091325cec019eb442a7956d966caafa0d3385fa4e04da98ecad30b23ec40f63d7b07477ac2eec10f3458913b6924e8c3f31dd31e5d10ebd7e1a36d9aaa2e483fd1a414a1465722cc15c5ad783008a24838cc88f7b311a2b3a6222694847091ee9c4958274eae89be4405282d73a16d4656ee7f67a206c9ae00b8037ee6b8ee78bc2ba4f13945c264ab2a2096c1d9d206b409b9fa4faeb58c6536e17ba260d0c54209677d489a84838a6528386a75b3e5185b0294aba8c63adbf09c9638547002404d832da5a87098df837fe2b14145a7b2441a87cd3955e7c42001a83438be93204664f06550d7e79a0cb9b876e4a18054f02a981581fa7c264e556bcd8265bf9fa39fb7798e242c209e26f2fed015dd413a7ad1df7c312e58f492a1d334ee4f6fad80c043cc1ffcaea33b9dfc21d0a0457c35ee3d62fc1edd1757ba41ca124b3b2a446a9884057731d22822a083371a089b580302200966526e28b8757c82a6ce030f6804f41adf42fc78a86bb4c8db5fdd520c64559c02bb398befea2a033b89a71e15be3923fb05f15bb5afe01b48f1c9aa39fd8bf0a67fb8cf786cf5248ae278f34c3110257c9a815a35aec9bbbb73fc863715d07a91ef4320347e5529d9b6153c84e5f0d857c374bc83af3f39d55a8bcac3f9da51b45fdabd1e5aa357e65c8e5130036163021289d4c0718290239613d13ce5ed3afd8f6931c46f4015f4ffd2d5e37ebc9c7ef7cdde19c8cd742f113a2bec830ead21227394e6244a76d43ee2f1af37d80f39dfadfb0cda37b63c68cb3881e7196533accf6cf3ddd72b760f66f8660c3f9bf92e0f56caaeefd20f9a12dc48933a395d33cbe9c0e0c9001f43e11367690ee22219b04ecaa946265894d9b0f4744e35bbb96732fa5e09533fc6b87f0cf5009ba9cbb4b817613e4312710f1d7ff215387401a0c439eaa398158d1ba341b1a9cc5543dc39f7fc7c0f2e0b26c8f2c5d174b1a16ffe314fb02f85cb1818b77695b968e60593052591783e918cd2f2f2c8f497aeecc31d5b8d2789ad013d46a0ceda0501db8467c0f29ce31490d1db0ab039762a0fa8018ef7b69cb8ea6b6a0bd7b33cd384a5d14a18664b0a52ab69be6def9bc9c0ee07f4547098c5f50daa62bd982c295be4b8eaaf0eca779bf7ccf35c4fc80f8b09328c123f6732c02d96bad0f90cd8b813963eb22c5e9625c7351efbd443674b3b243fad4bf3e6ef01039801dc764951a58e374c7bffa6aeda42db2137994923d850baba7c5179b0a75532cf11d4d7b2bd3309a060a435b5f4991392635c34d2e07ba0203db32b5e020836da3fefca6870c6a5107a2e849a35560f8f1ae2580ccec98df043ffb6e798504ee6364e1537ff2372902dd143244dc7fbcaa2800efd7bc50adcddf498ef432057b16c522c2559b9544f17d1d43d34857a197fc39a90be62d4862b24b34f970e105e996e33c8f69ee4239f8ef5c6c05a136fa57a95b04f4e6cc10bbf486ddd3d7878569c4c96733c981713c43588fcd0d6f937b9e2083ef25ecf89003cbe44fe23365a20cac84800592535e88c761ed7afea29eaf3e148110c687dca9a00ad878cda110ca67c452091c195402e8968470576fbb59063387bf3ac73bbecb0525e76f08e75d8ec49ee62032524345fe8b04d9dcc977e558e31c11fcaa4f77b8126152b1ad7be83aefc17e92fd803b77639ca0cd87013b5779967bd2a33bf11cd57f610a9b02cacde1bf5f7164b24418109b51412168744cd68e87bf6993baa3b30074add2a6f693fd92070b6a333a3d4ae5a4259487efe8e6da7124439cfcca127d4392275730be5a334d131225d08b1f676b636864fb2cdc75bb3096640cc54341f1c049decb977c32fa3d2aea1ac972abcf26659be373e9ef51ae38b3e8e9635652391fc75ebf77c3216ae68d67ea8151c90c93972a1764bec43b2a44789869e318c3ed3e55ac4475ef04157fadaa4b18ff1d9dab1bc09efe5d5d0c7e0ae0e99caea6453bd7db3bfeeb8a8b0ec9c9d33ca2ea82dcd1b1078beb044421e346def02f2d719978694e472239b870204a653bb5d5c6b87a0a5f66de9929c743e1dc3d0a694cd60d34ce0d00c57ef38c31659471397cc20e8ae7a8f1b910847fe1c47b4551dc2ebbeeb1f91624f0c09b521accb526707ad02b4e29022d6286d476c6453baa5b200027eb8993cda0628fdca0849747ed635b6bab3867fde33c83ff7e01534665cc0987edf506f332ffe05f542a12e8808689a219a5e4aa17b425821916bef6f42877173601f3ddee55827594911f3ed2bcd6d805ed99959d96293fc8d5c026b1422ac3816cf06df80248c483b3de0be162550568a3c04b0355847df1ee015e12e853a9d17583caf90a88c78ed175f751d8b5c3f65e6e17f09f7609c7946a23f4c6c43102c3c117877a7698bf2dfa9d33fcf163e126a9bd058b7b7748447d34cdac5f108dfbcd4b6f92265f77886f9315a8ceb83d5e6d105a049c2e43f12969d1d79d40f76b6eab8e414240b964234dc536d619f2b3503eea4e2a3a19afa1aaa857de12eca94af139b3da664b57620c435ffd8c95514f3c633ba5d494fd7181f0a169ac6745e1652b5a158b41d44b0b30891a9f4d153fe521361013e578347f52b5373262628c850004f22e7370c19203daba224032226b6b8022e1517d9f52079391e043bb49c36d853010d1a3dfffb95b51dff52454d1ec9bea6cfd9eb7eeb2ecf4a41fadf23887e192bdf44851021abb71018a69dfb29b47d6f952549450f01b23a6736c73a029840a6e7c8df00786155e04c83ef83ccb20881e9ae6eb794e9ad9e60aa3d2fd49510876ab9fe31d14b3c6a88f6634b2fb0822f232050ae9f7510ae1e87a903be24fe38fd6e676e3d115f4e5e0b1f43541a3b551bdd579bea5e822aacc980ae9239753bbe530acdc95c8da2014b67ca8ac08d8c4bc661bfe13403f6c566db236a05b0d9c063168a6f8d5b7c396186b3f1f50c581e82caaac7a1c44513ccc6f29fe013150165ed69066fff000bcf91874d509c10c25831f67d68727d807e8cb1be6cb30e2648b7b90cf55abc4439470ec48f00a659ced794a88743306840b1124209cb69ca0f106bfa8bc19bca6914047f59222da5271379e6f6587f4fe6db0cda83b8df120804789547d7a7fd8ec4c8dd911c86d08fb53f186458ac555f1e4b66dc4fdb2ffc8b60df356a0baa6d77029636016d46f3284d888b67bba249c24de7791a1a8243e5a1f9c33e27490a6d03ca2be5e709baad1b0dcb4054e63af40be0fbf552999f63fe80c9c511128751a88f971ce43c1f5e47b96de0949a94da7668844d99c6baaa3e929c4c19971f5123d79042212043d82576120f4762b74460f3bcb520d933126534401eb0601df78d2995a9b5eec56ebe85f2294cc71c1ca36c0a83b1d2e7625c3ae95c73208a4b69bef678248e1994a0997618e3f1adcef31173d57b78e9b0667a1b048632f1ad418af28186879833a5e1f993b6637e52f346b62eed1fcd9b6bfa02ec6610b9ad05a9bbcb2261853256e67e8aa97d7090a4d718271082faff3daff881edb135c5f953243f06beb118f380aa9566f970eb9155b84a5c5179297c0b2cb197d2445d5342cb2c26ba19d58a25f22d4b64545cccdb39d6588a46cb8670e895fad936005885a9ad9b8dde588103923c6920c57fa171782eb80dc87980f287fa8bed0438fd72b7f36349bbdd234f9a9020d9d3f9aad1671d0c19660a4c132e9210188503c5740bdeb541a3dc6a08bf19b8ee3866526f0fa699c9138898751531cf77f59b640df4f900fb59390b9883af7c6f14f5a75fb4ed57f095808e3f0865d7599a886ee6a77e286bfb3c26bc6079bc456755521d05a9940c0dc2845259444e18f15704e91c9a955861e4f38a1b3949aa21116a970ee11b951c628287553d62f91f050c94ce91f1d0fd390f406fa3f08da841f4b25d2d091915e561039e8f045ef9573e70158a26f3b63de0ad6a88faf06f8748738c7327f4f25239560129fed02d0dc24823e9da63eaf267fd2a63366d4d98115859cfcc31a7b9a98f5ea05ce5f0b082b02258b2c992268012055a573a2d54428bec8e89561fc194e3cc9e9e4da538b071b6052aae0e60053db1f823979ef24edbe27fd656dfdeae15866cc9f67722213578d1f8c0272f2c741e12f5ec5e50945ed19257945a58ac888246efa9ba352c1835dc04afbc14b500fd064d17ac14f153e5895c5a9a4255e902fb8ab057a297e943c3860a5c31aca6ee41de29a4a0a7490278fed3a0ea5a85226083b0008e784ff406e84980074a2c4f358101ea0eaac2ecd25fd888593811aceead44ab3467b87a73b76c361177cda5a2f7f2657c950f004b76971902ec81420b611f53bd22f351b3aa6200d02b03cf2ccfabc87eca4415fb82622d0314609684da16edd64758272f9148a47e80993d645325007059811f6ac0535f1844c767e9305a8e742c79d9c137cc367e4c73f54f7baac2388f5a2ac881a53f89ee213ff37c031c16bf4d335e33ef9efab8991066c1a6920ced2c141761088920730b6eb810790642743d925036247e18596f74b4a188a8bce8dc9b3068fda613837ae20b6a2943dd1314fef1c8e55d89a1aa23e7f1079fb6b9ab063e4abd3d927cac076087730367a524da08f8753df303a74dcd8846d13807a2fa8d4d8823d560c07d007bb389e307bff0f4b23af8e3c6574403285dcbe16eabcd74cff92d60d6b442ba7bf2e23622291d4548b06604d159b789b2a0bb0a6095dc7444aabcf165d63865e5bf015ae279f1f81d629b946203338ca4c1b124c928e5b2c275940ddeb201c6e9b09f44b6af858c19bee0661e905fb328e58291a58a5dfb59b042f1510532b32c88264611d2c2eef38d1f572933f6452c456cae6222b8c9b0b07bc17b1f33f68597c3bac32dc98855e25c7974d966d192cab6424ec0ed09b9c7de2be24a9d94d6c0ad64e890c9b364b63d77a63d3530ec138c16600237d9ecb381659a87056fe730c4315e8e27f4875f53d18166f8f937c1323ec2eaa0aaa2bc279c375e01b35ff98942b94a4b3c8f4a5962373648b876204bd89818a6c2a368edf796a94f8a390f0095c8c3db97ecc276077b5c8de39fc3fa0f1c8a0fb3a47b30ac277bba706fb44a4ec110b65d0a78fbaae22f67cef9f5204bb706b3c3c1e0ebc4a50e499143b7d8dda58caf25f9537bb9ab6b37b7c0d9541b13b848887a805471882ff1e4f8e2486c5a3506e2428d7a1e79edf54cad7be5ead59440e271278f141203763f8e6d6f9678a468a4d6e37d59b14ff3cc1cd111c064cb2f953d57e972f7142491e5ee4e8dc51cfa8530f8e052973c193dc709658e9cc0f57574220c0eb209c225a9c4e5cc3fba42215b63cadaf3d75909ac1cf0a1eedc8c65dbaa02d8cbc67f4e57fd0fecd05c03a8acaa187f81e0fb501f9bb0a2d8b117ce778793cf9803b8a0e91b6dfa7b91308ee7ca8efbfab83dd3c895dc0f9c3b744079664c99a1be4f61eb73bacbaba833fc5e8949f59ba3dfff875e7ea5d77179362c5b28017261e2648b6fc8b0d904f5dd7c01460a7d6fbc3f3bc05606db5ad3c9d53b791a56541688a66b187f65db9e62371986ee95879b12dea26fca693a22e88653209aa776c94c78995955bbbdd185f6abde064771d6de0b3f2cf2ff0e8298c907e7ca3325cffa16fddfc92aec9d53c08920c34403950da0a2126b2bc1309de6017f8c7c18acc267ff5f7dcf46ba32f9335fed858b782a750b7783f7bead0551d9a6495643a33416bae8de0fbd0d8b6afbadb98daef49f5f5df4e349ae8f9c024dec19ceb13de6aff10e664d6f7d17fec3a71379c2b6687f6807b1440564eb5fb774ae2bf533f990347f9feb667f2c334f978dd6c0ce647ec946ee8931493e143ba9d7289081566b12dcc5b142622361ca6faea32287d342750b10b6144911ccba3c3d208a6d24057acbdc6da72b54a7510f8a13707364eeaef36c707fd1070b08b0799f5907414431949d228d9909e9c462ea7e633932bdd4622d3fdb3a4f94ff39cdcf124e089d467eb864fec36bbffd032d8a36aa308dbd8c4b3a68ec8e284823e8547a40a9101aceb84ebe3a0fc753a33e6d7cc89142c701e8dbda37303836cf8bd8061506c3ef1bf956c711aa9bbf2115b989b733d70c106cb63df700f8bac68d4f69b3eaacfbf850dc64ac6766330bdd2cc191e8c1df1c17d82729cd719fbaa3bbb6024564a94a3acc0b5e378c15b9a38f4a56ed14ab7bb8cf5ba4a2140e0ca70a17a3866c8001fdfb03bc4de9f52727b2faf386e8847170819946ad9af9b9d8fc8da2cecefbf7a7515b53eae19b7f9e411d944d26af77079c68c35ebff79830ae4836ae7c9da7183054e73d6c174dfe3805c04e3bca9daf4c0c87a7224284b94bd54dae4d24f7d6bee5d23f3646d4ac7dce4fc389910d3769464e16dcc57899ec63b341f75053e5af5076fc04e6fafd34e1283ff7eaf1bb2c1a6c1dd48313a18c891e9dee2ed4dd15d3a2173960169157388cf841f4b40824e56203caa2a394dd7d030e68e504b2f9750c75adaa5acdd2c8e0c0ce366e467d7e216f5dad16789c154e0a3f3ba2435f1653593d194e180d1ba7e684364b8b10d9291b3ad295bb81f9b8239803c8b6d80ff050a563677d81b23d214fac13b29025b72a2e9f5b8b93e27e868ec9a91998ec1ab7d7c63eccd9f28e96f9c56bea7933395bfd5a4f64d4e3abb26443b815956715a79f0eed277737ddb286ffb4ec48da23f8afd86e26a4bc59055ce58a4f2df4805490853e65f6f80d4cb5fa679862b0b3d5c95fa6a81f5dcbe680157f8f3b3c210910063593934b2e6a901241056272d8c7d6be078474e73098ee651746e469ad1ca5ba73b00a565b6c23142f134e8a7e93cbd15a8fd37e28c829c01f1296958120c22976acd2f1aff4899ef16d62dddf90f7f27a4e943414eb707c67f00ec2e667feb0a114a6e934dd93ad9fb0e62319195c9d7b0fb7994ddb881a9f15ef96d3c6b387183075199f275f9107cd120aa883353ef2e38fa7ec9eaea50d9cf555318f956247bda9251d0e771ecd58af5cf74c8575e032cb581f6e9fd4b427e4d0516dfd1c2f5f7551fb35e3d411492da42546ae8ee3f9e0402bc313dbff0a8f6ed4e3f6f34626d9886fa9c4469a8ad658181bd010533a240123cf44fede58588d85c9d0fe0c6fd87d5b2594aa7318cf8e361795e3dfc7ad170becb63c25aedf3a3d34bc88effb62c180d214bce12dbfc146142050c76f6884529251c23f2ca286324227b7dfa090fce34ccf09ea1598bf6f907def0f62609b0410dd2ed009a0ae520b2e72189732b569613b15a59f0ebc909a138c306f098abcdd46ffec3bd7572be2ccb11e2adb16265f86936bc3237cdb63a55c9244d0bc0e4efd51e4c5925a1b0a980428fbbda2cd528482bfc8aaf32941a1b83854f015846b124f33da52a565954f1daa66aff9925a22ab94271e195f5e3c9272c85cb27538e58384256c1e5a2556ade35ce4d1dbc8f81ba39b832a9fe5fbd5847aa905a399aa15995cf267913aa49ab35d8cba80a2bf0aa82fedcad346ef2306a2510310e7cee9655c9e9e195f221bab2ffcf53a9184e2bf3ff3f44dd4a0fa25490162440ff6b46bc558377331e39d4015671d4f9facc962f02d7c0a304c50e0c7e03a18d734161ec1f95a24645e999d075ea40d836c31080c65ea21ba2309c70680348bca1bbf5160d083a562e06cf7e5e7133dd916641cb38184280b99ccbdadb22fafff66897eeb5e8b5d60f51e64e56f9219b4dfad20e990f5b148d24b55a67f7047bf07958e13f26efbd277f7b69da37440b1d1138a93be52876315aac127937272fa600a7fd280fe210251d99f773d804c6a5964ac2cc301875032a1f17ead66d36f83740b015d006ba8e94ffbd7a3e131453e8b700d968966a559bf7ba9bc0e2215877c19fc07b17170e3ccb64f612324020cb7b091b6e3b8acea7595a22345bd2d757091ce0a156cd9523e7984c55aa0df88535bfefccff58d6ce02871b62f5b723fd3eea1466fd4e7312d9823cf4770a9851b9f8aedafbad25eaa13448a4ed6c79f0233c0efd7e76012655b11bd34a039cbe5cab3dbd8546b6f07e6a336fba66d26285bd609ff178414936dc96d55f530d6a307ed57b5aceab339666013a5b05e00cf77e30b2e12ce12abb2f0f5760dad1a9bca6c5bc06e842227812ff496bdc77a53ee446563b3acd43fc32904966253a52d5196d520f9ed8fa67b49463f9c6cd598a81fb69f2b1e913e5dc52b238638fc7cbdd6bec744512a7e0307668b69e4cae0d342db93eb2bc81b33e3da7c9f82f96472d6ab73933071d0b3ae91ecf77be482d49b59bc38f0dcc70d7eaf6e9551b45ad02917556bdf4469b0a5974310d01ec307f7eff957ceb603845bb45cc91d7c70a328eefbc7c27d06a0e7385512e3926701c0cb8653b1faf15a417c772b492a5f1c479dedd0f9c179bf2a0489fe51fe9a84cdec49f9fb37f16b47fafcd99ead95586b4a9e34d69e5d8cb0f70aec0418aa29d027b754b72f55c33d61c1b89376de38238e2a1803a8acb25b7ed29d0aa52d13b07c8afb5e13efff3f58f44364fc507def0df6d7b64f4caf9dabf00193904aea742af23a9f6a90760e97bcd681bc1f15d77067b483484f235ceec89c773c33556bfd1e7179b7f31203ac85102fe04e1494b04993c75cbc6da2d06faa5d7c416ee7d16592e8606f96937caec6e3036d09affef6398cba7abfe1c63420cc8786bee2ce68dc31b4614ac2274090a06bd2aedaba44ff0777fd64322bdebae1659186c10007538d4f4fde546f9e261f725858a3bc1b94cbd9a090458d7f1a38d09d9d36c45f1c6e011373bc16fc748961c8850117b49f1b0cea4ccae274ecc5cc6de80424873c2cbd0695c9fe32bf578cd9b00e30a7b3b528ea6d682d5d14ababcf26885725ec2f1d82613245bc5099de4a80ec46a87f824df50c09c4042c6bd3560fd257f9c0f5364e7989340920525e83e029f4baea1d30a6de9aef3ed5cce271cf2537c641ca5ff8ad47faebff32faa5264f964a0c3db5b9165f663fd324b97232788aa4e2fa054aeb9b5bb2d22b345389e152eb18d5646c3862c75d3742460559471e22ed58aa0e57f2eb94ea507224a145bc1d1c10fb2e5fd2563abd2823d3b2bb78f9e949bd27b087aa7dade38f3133c6015831a6129de08a035050d33885477df6eae6026edc32a033b8b30422ee4ae5a20746833b2494bb3bc04a2b0cc53ac5e03a52f759602989d9d50d202cb1a5a253c2f68213a017fbbe239fbdfbd0e3029ead46a575fb7ca1b796123e1aff27685ce88d42370a7dd7d44377f6bbde367f8339de0dad4372234b7c5dcb6f1ef9c18be88b9277b7fa215362b0adc46c2bd68746d93fd1fd5bfbca1c59b05d834e98a16b3e3705856c3d6d9652a1d18e0c4ce3cee319b395bbf3e770128a90b03d25df1d204abab525d3720949ecdb7214e1c6bcecf2452c0e0d052e3cd8ccbc9dadaf2e634dd388ebfc65d22dda800c890a5391c9d56d8afd0b2d3ed3a7cce1c3f2bf6d03d95113cf9e6dafe25f57603a9c89be020f54c6ba97ced3c4a024dfc90199bcf08f7c757628423a82bba98344ab7ff43463d23eb346c704162f9d62e0ce056810a80012611032aeb9664addc6b00dede4cf6b4245586115382ae08444bf09a3a3e3a6d8bab43b9ab5085ece51d732371ee29208d800dabd1a3c45d7db9181497e9d870ad28c39915781b52cf792872a1365f81be8e719108c7d3ba8e271fcea542c80e299badbb7d0c720a4dae91080a6128861e22056b00a9bf5427d08ce92c34f1632d1c9015fc5ac4987bfd9a5f43f5ba431497ff54eb44b1c00df9e55cf68890a6c086c7b88b5618b3bb18c9fe1cff17d57cd147697c9d01c3ad15d5ddc47a5f2ff993b6ff16d858fdc1bf870fb47349f1d93f17a024802dcf4bfa262ad08c80e57b0e7839cebbccd0f8221f09838b9adcf23118c746b82a8c6fe6e37fe01d0da7dd3cc3feb6b3552c48dc098721aec87b1ce8bde0f817fb245667cbfaf019fe430ab2e3089562facd68bc189c91db8a528b553814acb57b6cf6973535774c160be1879174723489c6781ef6db3b9e51f8d47b3bb44169b3a2317f6412b9de6b13f865d34cd9e41f0bbdb657970da773c4d0299299efb32020c54c965986c33810872005a973b70d739e800f211aa929fcf5872c7b9940490db60f8ad539a58cca0ae394e7cf5b753661981ed7dfcc24832c81495ca80f9e89a4d089a872c898c0348adc522cd702031a06640fc1165ccc464c57b36a390d6a5b0d21f430bb0a6ef8a98cc2ea74011b07b78b06b2f2389abf3ae8c9b2459c08d884f0f715a3cb913312906b86b5ceb87a079a4d109368ccd12948316fda6d0d80c038a04037713853c19213bc5b8a9ef433a69a1b6cbe456344a2737c3e8861c2da45390c650e5af6db72c15462c7513a499c5b41de5f12dfd0ff1407361b762ddc6be0733eb51ed68afa519fda6d89f83e12d88e55b82bce1b4b6bb4c90ec6970d749720e2caa61220bfd94e4a8d9fcc82c49b41a2ca6a28174737ff38c84404f2cfadbfa2a0a68af2fa2f61e2a2a84589055c596b05462152e4f2b72d08fe55519d0175989eab0e9309d01085674b5d4dbe62cd80a6db6dd2198146e20bf1defbf7cbe124ba03f92135f272023f81f7f7b74fd0a89e9db40cbadcc6596151a5527291427f3ab37db8ddba0ad09ecdfa5e8dacc004c761a15a8a715f15def448eb321ae35759b91a4cdee26b5eb5d2b2c9a5212a72605e8b4167c0a51e515a296b06cb4f8f9701e29b71c3abbce67228c99d4911830a123cd781e80de1e6481195358c75a1db39847a5077a76b41db55bcf42202b3496f6edfb1b14e2900ff4abf60ff1939eee0f643101dd34ce92f5cecf46feb28eadc90f28d6d159a5a3b74990f9a15f4dd8cf4e3aa2cd0b34b1d99285d004a76b5b1850c91900701ee94533b5059a20c09778705e9f4451743f1d73755f59401cb4a247a6f4fc9bb2b16d7654e52b82279c9e744c6d528abf5f7884f42cbd0b492f6c71fd43611583cd23455931d83c22ac3a335b40ec96a1b2c3932be6dc1504b7223fb8afcc0a3a0c664c2743bf969710552cf4ac941126f403c1f54eca04dd6d895273e60112036d4487a5a39e5aab22363ce817824f91c044421327a5f10fc4494a8dc44bef925718c32e0f796105d50b978559935e4d8806c52ac28fd4a2ce863485b38bc15e8c068b2523233bcbb32e285d0f8cebabe380d3b4bda1f37f2f138dd5bcd0cbcb9723faf0e5072513cb4cf6e31a922f9b90466a53f1053774b3e76bcc93698d3547fcbf412ff44d55e1e6d5f5710f9bfca1827394657011e1079be9cf33c3c38481c6ac62197382522a1666404c2ba31b0001f775126f0df0f95092c8c03a7439777f8ff7e530d0072a9b946fa8c17199cf6e82d13fce979eb993a2fd91d2614cd403432c68532477433869502e7c7034970bf5eb4d1cb2396a52abbd8b4f55c6f6f82fdd764befd5687e55da1ef8b0d8798fb6c685a61f9a004186f4badc84242c82ede5352fdd8da5dda76a825fff213fd568a417b73850401e3633502dd9de17594dcbaf07f0f6c682a58732dc1b38ee0eec2cd23aea9f0ce1a81cdbc49df13423790d66d19ebfc4a646f0e93c1cb701f5539c65fe95b3f5456b6f28867c6f66524ce7cbeda80be6c9e6f375d6e43804abcab0d02402ae167e142d9571a6c168937bc6543bd1bf70bc0d697bd60eff77356710a980537f279baed9225db062cc7709eb175eb06e9b51dba4f72de4e1b6cfb0a5afe08483baa126145671d4e87b2e43968b5836119badd33e74a967bccfb5c87bdd9cb64eefc0769fb3598d725f977b9275d5ba89059b07fc291b92f342d3f2025cbbea42f44b013e618f525393083259c000e663ba3babf134ed0c1be1332d1f13a25a8a811a940476cb206c40523d70aa34baaa628abdbac35ac06fa16db6d2171614a8c08140e785ea0d015c08e970155243abe320baff9b301045f70bcefd769ef58b37336e9f7b951aa81e4d7ed23e0695eb082fff869f89fa9ec1f8c0b8184cf6dff3a9fe4808c73e17e8e8adc8f822f12e80c5924054c08ec4546a257053c650aea5cdae7d92b6289948977a03d268ebfb0b86b195f7becccc7bb26e0135100b0bbe8da1c8a6c2b3d6722a77877069fb647bcc5af6dbdcd4656493b580a68a1c3fe672f308fae5ee1eec66a5409e02c53e1079ac5c193fe486b348162b23aaf7612e542637167e493a7f4ef4d450806f5f75d0724137e788bd6748437127c6f21c50bcdd9d25beef2c2fdd700cfd69fe1d9b8ebba3082af2e413f7a3c3e24cece4bd770c3b3fdc2be210ed4b2b7760228c30b68ee37d8235e17d2cfb41c10525189f8b2abe601debe8a77ad68643ce2f4070670cdda58e941ad7bb5e365b9f7cf15714beb587b147bc039e5c225015ed3b991a6fb934289d169b30a39264bed63d4c7964aad45b0899e27a0906b79010b39a2d16b407808ac19f5047fae6dc5405024f36aa4386ba90f1e6f3d85dcc81950751523b943866a262799acc0fd81a3fe4e0f978704341b4f8bbfebeda8e492933ac7dadf5a20f03efb3fe29d8b0026c252dd9e5644a7b8c02ded053a04138d505feef8c8ed2aabb5dfae0e210c6d8a19ec6f2e6c538f55651f5cffcfd421948eebcec6bd18153017c8d026a654ee2d9878452cd8f7328968efc4b6cb0eb3b68f7dd229673c6cab0f3301d5ac7a4970a35d9785e7fb5aac5d552e9811b7581807b055f4bf6aba596d972c65a4f8ff70c33985428465e3ae64b808d8ed6ce5d0f2b5dc706be5f84daf755dedb3246b226a95b0e2646de79993a18d4bb47af34ffb301a895437f2e77625cec6835627f8df08905a1b8ad3c8af878371f5c52b2274b13cabdb448a732b0d8edd2fa9c77b3674ef73a445a95de0bb2923cdca5d5b8edc176b8a8c3d02fcd227a51920ba9aa57f8a34ef26bc98c8e64bf9a4d73a21e49f46535329267da1c74f98d2778f0532cf3c2af82144264d623664904069a785309f15f791f640729b5bedbdb1839934052e4390653cc984d8d1e8b6d1b2547e4e3638d78346d508b5cf0667b25315518a7984d255b8d25e01728b332e07967e0caf2fb1b04588ce2bc0078096c7b87b252555d704a86d6619616e316f797b012d464f71c404b7a7399e116ab78e110d1c9f65762242779799ea7b60dc2c33834e5d03943388b03c8272580ad83bfcddb3f0dd76885fda3f7c669ac88aae4bf234ada00a9b82b4568e7e5319e70b6be1f548b13da2412fe73715562c6733f2ca0b334b98dd01b420e526732d4c4fb957b042d41f789715734cd49316838ea784b213e1baf23ddd22474d375bcb282f4f17ccf13b6786fd94fe45bd5935254ea7e4647c8f84876c3ccd8cfbb997e0ed9d418aff5fce756a5d94c1f30bee8c8994b4f5e53e70eb42aa5f7d499dc78414cb0094c798a9b8ad8d82f716bfa89bbfb3e41688ebf203f9d335e34f9ababea081b2e0c13c46288e37eac3811a379dc2b959f5ab9c62a80d58ee98004afb8a725755b67ef0c56aab5e9c40c1783d5caf5ba4561d51016175b36d1650469e91ab01c22a688ccc0026fa7a32516f24a61cdc7f10aca59b13f93b2310e7aa8ceb13fc140fbbe73c07b32c7723c67bad16195ff9088b608e90e6e7042d5408432cd4e051ef5da64c77843604c9280fa4a8178eb2956c62fa234625ddad46f36b6a7151720044a9101cda30dbd6eac518f6a29cf9255b4151763a82a463c06e33eed902f4b044dc674cd7e502e12821d47e88d9cf0475989001cbc5130b3f9c9475c492da7f1626b18766b216c08ee33c8add723fab92a76667f58524aab2a343d938a049c47db6aa4684d824c402bbba2617c048fc47a6cbe1028001ceea632f526318d2f1f1c95f941a79f34f56a8d9c622523ca187c3d8049d47a5c079e4b636a502228a1650ea3ed94bbd024f436128ac9c4839d0a68403d39720a86e93f60dc8d0646ef5e5f2e268bb28d28d4ffba3a15845dc1714f482ac3c3be2cb117e08cebc00b25bd254e092687c40c79b40f6743ff55f7fa9589559b47fdd10abffcf1833271c3f1b9457ea88fb7c797b0e2801b0cbf066b0dba052477fcd0d9c53f6389513b7f1ad7602e1008f8da1e87387c7d98f88f597c2dbc4dacc96badef7e880a5d30af095e90b0a8537d1c09494946c3e67bcf10788c3ed3f2f03ea3189b27f30aa5d89b51bf0a187e79683815a6d69cc51c2a689ccc3e49ed668e1bff4df1719a191c8caa6a0b81004be52c94a5fbf18fa3bc7aa1a3bc0aa5b6f6fb5a0ff58a8e015826edc7b5556485c1977a9f3fc6daadf032e10c3918a43678971048ccce619fc1e09ea8e2e64984d3813f1ceed43423e200aa16a080c748ed05ecc3a2197e8bdac0dc8cd08a987ce2c1f286a0a0a3abe0e24a19964faad3bfd0bd69d8aba5d905f6074c7334b2a73ac72e245f545e74d16195cccb71bc09c4ceaafbf5524783d6242a29e4e3c1f905f95d44ee80277a2a612876e68e689edc937d6b89087fd141f669b3afff98b472efe3685d3fe51acf437d8d9c0c772d046852606a36073fe19c45f39bac383e2610bc110188e580c1d4145d0adb34c977b7c2ed617982d48951e607f6a7088c3d22a6035f8f79300656b5c424b533133c0247742952e8eee02f3db556de97d0f88278733b183c188a7100ed46f6ee54d5fb9ce9d91575ba6a5117743d83c206f6ee4f9cc6cd11e68ec90ecdec856c16321e0c9b625b71345ddd9d703626cddccd7a398d126a7905d6453f75d016e830d19996216cc75759e818d94cb49481fd7c3b1932d0aa9fd7e5331abb38bf880cddb0a5878c2fd4a9e9a991d763a907f9f89fa28d97f88d768345c49ad5ed9e849d2929112cba5573d1cc29011543ab357d235ed856e79f0f5ab1d4b27a6ee9d35db5faa5835895c8fbddceba2243166153f2adb413f0e96520bee756ff5b87cec372c25ed43b3dbace670f67837883503d559338236357b079033cbd4e565c7fb7ca79d5f59a7ddc9a0fb78f236d18863344cbd136d6fdc3313b2768aeb1b7f0c52a3b7c81347dad75922fe589943eed07bc042c9f1021e26fd3d91cea2b1bcda7c0cfd846241987676ae0953b34ea54add84ce450280cd7add28896c93cf10b45dd79938465db2a1709b90b130a108b032e0d1dac97e174fdffa009b18ffd0ce66752598a424eff7b439441e226c41a0bc6a38d57aeb2fa37dea5e229cd25a11c2452e6f3ccd2a82d0bc712928326d7b7b257ddf17c92f047766f6b9b01462fbc62351715422cb804566112dcc67a93e26a43edd9831aac4c554c38ba76c8f6e8c379218c9276860d87019deeacc1bd290ab91df5b911c47fe20ddb35a259672de1fa1d5e62a29187c662da05a2d8929e615d7021fd3e3965c01afdb235b9e729e9776857d95d93d1d0dc9ba4a493cdcea702d634b0f98cd76329f21af1eac91ffb6d7527c8c6cdb18464057062f418ac60c4aa4ac864a9817a0d1fb9a4505e090a6110d5813bd8f3e1fe4ce79fae619ef0ed9caeedff14febab644c39ae5813a8e1c5486d0d681702cd333df9df570177707193470efae77be3aa2af6667964997fd80c5b549f408810b66099ae53f15e42fc31af46f3f44819aee9c3e06ad52c3625a8ef292e9f80500a30ccf7ed451f6e015370e9f4ae804184205cda00084a62b8e5602a9bdf24537425ce00fa2b1db853efd438e5a45766aad89b6b3cae63132431550c84f34b52bad2a94fef8485ea5876837e90db3424b3e230efed1f057e6d141fc9fdca142fd74a9651f8bc3f8c4f1431d6b75cfd1cd786fccd454bc1107ab1f49a7c73dfd088eb0087f019f43dcec734e2e7d9fe83db114f0e3b6a0ebc080834de6e420610ffa7272e0b441870f598fe24d7483f4a25457e8624b959ec6c23df55e24adacdb4a7d69107edaac227f14224957d64dd7ecba21ef2bc46c997374d9ba98c8b6d4d995d761d8738e3601ba358839b01d7a85d080300a07cd2b4ecc63568cb140845de59e2be2312807df99c89dfb88f1abcb9b12f19cabcda45929ebe91383d9e12aedbc86ed2dc3a8e52dbb937feb09601531988e2b3c84765474b4d42830a8a3c83d3de1a5c095fc2eb403bcae21ac66f1349f4d47a3ae5de38bcb1ab9452af415f3086239be58e9fb1e1586a3b02f5afe24bf1713c4aeefc07b52cacf6aac3167c1ec98abbee4ed5d70b332de279cec4784f60959fb4e0b1f6a1251eb16e2b3fe366a53bfb9cd9e90b7117eaf62757921fe3164b662859f039c281cc78d9fbac7e444750ed274fd382ab70535d2466ada88ed2394c7b6c923a4370f33776b8875fee0606a1fd2d498116d0c11a7f87816cb18e624f0c4a50867be683feb08abc35a379ff31b1a87800f6131e21196697ea0936827612bd698cfce88c7c398ba5e8af193306c609a1322937998754971e2cc08f7197419e607b6e41a78c3888ea4e0084c5fcfdb9c642ba2f9afd6ef7192f49e6b9a71875324928f92f5222358ec59f8769bc518958a3fe3f74600817c15e6738597fff6b7d1138fdc043bcf96f01109627f55203abd9025520461db4b69956b217256ec63fd2b7eaeefd18d32a3b6a56f5a81fd734409b53890ede48c4f48d6597a4040631f03465796355be88324710375f0d2e870874d6006d8f76b8a1e14ddcf1bae2e48de132867909fa7ccdcc2a220ea795275d57a22260484fdd609467c92760facf4f408a4472546ebee2fb5002fc8a3a61ae5128382b3898c7727bdfec56cddf92ff5819b6f087094916fd1face8e28a295586c138b63de1b1ae5fb0f103d926c33a660471368a4ba79032ad08c8db261fe94e572bbb9b7ace4d6dc35ac028ca6d07976446cf59a84f9c54f0cecf5cf068c8860838915efc55abd212980dd74d560d08a7887b4df80e55b941c60807e8e9028bf9c4e61b7f6efd858dacdf1b42508e9a3335263ae7d41599e48cfd02578807a4012e9658dde87e838ae8072fd1a729c5e714e233aac760a92efd6261dd4dcab52bb0118efb3b91d35cafb3f49df6ba406f82603199efc4094c39ded7966ee9a5d1060402b19e7e2030d9e01c7d60b69f1daf9530ce72f3cd1907cb6cca2a86d05aa3a61887f2b3fd5db4aa2c586b282ebf07dd65737eb68a619c3a392bf6958e52267bcceed7b1df1e96a60e3a29f9e7da08da443d2027f7b230dbe445cc8ff006751eb3f577c908eede3ed3e4a4829a464f5db255dbd31981f7464490664b8d2ef19d3d52ea48c02ebeeaf2712180ba627d9977e43412294cc98832c563e337e3626e6e7abe1ef166f6778dd8fdf593a96463d9b3854d7d73109bc2f95695d7eab9d9717bdeba5f58feae34378f4cb8448dcd80b86f451e769f266b59e14db6c9fa6119529373e2b1135c23f255225cddaa28400cd6b6a50dc38fc9e2f03fa0ef9d1a0cc7aa49673daf268ba8a0b390488b74d22ee6cff8832399246ded8f6465960ec6a3155af9ac83bf7705e12d1dca673116e817c650b9fa4bc4731d200a232d4d51afebe97912289408037ee184b70c3b60b0a6d00130333333333333333333d3d051bff576b7272643269924d1489d20bf817ea794524a299227131f7e9136fc45daf017d9ad6d23d40c02e90cb10c6c0c332eb080ab0f1898c74d0e3d76973cd5191758404888c81e163e5e60100db358fbd0d5100e3e5c60f8522684a89304f5d9741a35dac61608ab15a6942cd8f76a0b782db2e8fc81072b4cf294f89c2532747a15e6cd92e4d26fa1ff2946c382872a4c22f7a13aa9136f6611394b85394ca6b5b68610e6175418d3cd24e9f96264ae50f03885b9d2941246e77ad29d34b22592a630496e23764d0e7af5ab529844b3944e494a429ae08f6c91c2142675a9fb4a427f49d928cc419838e2f47d9ef804250af3781e5f13d4c9febe1b9045167d45284c92a0da53deb7202c3e235b070a537837932294a0d2ff32b2f50953be51a229d3b9b4351dd9f284715c4ec53725670fa31fd9da287874c21ce26fb4af68d12ae1c8163ac183136615d5174b1a5d42747813e6d02ff994a47d4b50c9e286888ea3850e4d98ca72ca6bdf69d294fcc896d509b83261d0769f47bdd6c988cb0313a6ca742fbd245e984df3128613df4e8592dfbab025cc7f9287b464974dcc4d834725cc257405d149877f101d4a982e47f5b6e5889fefdee03109839e5eeaefd988e9970d1e9230cc5e2815e74c322d710d1e9130889079b2884942c2b46f267d4a79f682c723cca372b2b2c851db9aff77eca0b1c311c62b49e68dff8fe570656984d9a29712a6e65a1b2a173c1861ce7325a51e0d9953dbd6224cb13ac754be729ea56069c14311a6ed924facb798cb97b34498e4ec8b6f8d9362fe8f6c891403830722cc492efd27aa8fae94b591ada4bee0718857e7bce4932b3cb2f5040f43184db57ead3aeb8a8746b67ea5e05108f3c5279dc6830ac2846e64ab2a0b1afe26380f4218bd9496f24d2d1b4b8e6c69516a10e63495fed72fa795501ad9e213141384e94e5c8b274a3c69942682ad1dbf0096814720cca3525b35d5ba2ce9226c80305bd2d6f32b5f2acb39b23503ad16336ad018d11162821967b5985190031e7f309ada08ef20623cd65ad4e01d5a40c08602d2c30fa674422c6f9d9ad0347d0e2b1a9de3027d305a7df57fe814c5cb1fd9cae583515dbd93bc20ab32cc3d9882aa78628a58fd56c5c7000f3d18456ce866e7871a5d19d9cd0e78e4c1ac37aa924a351d1542235b9863078eb380071e4cd2899da1835810264cf8028f3b98539e3699bd7dbb201412a25ba47fae2178d8c170979e237fbd5e3aac6645f0a883517bb4cb35edeae4e44f9ffad367e960b67072acb83c0b42be621e7330adc916f9747363e02107b3a71b1dfbb407e5a2fc070060071e7130e78910cb6cd10b37ad120f3898c5c25552792267cd6487c88d1d36689c251bf07883f904792dbe7adac92d914f018d2c9e0439bec61d0178b8c160b6595beb41ab746b83f9ae83ed585eed09a21c3776f40d05ccb86246038c0de6397df59d24d1162eedb1065397ef7fe5a0f5f24845fc4d2092542ac0430d664bb256fccd6d27573dd260166925dc92547b56ba91ad2d9e04225974d7282b85a36b5c8e1b3b3a11f14083d9a493c372beecf2588f6c25e9018f3398356f54967c825f6def6106739968b9841023bfa337b2c51e65307afc10a15427bfac0ec0830ca61c3ae50b324bd43d68644b43d43cc6605e4f9278ba829ce81b126219f01083c90439a7f5f4f9a9130b814718cc3967f7d26a9e7b725a47043820723cc060d0c9d4c75cbf8bab21cba269ecc051c3dbe30b26594f3b58ec328fa31cd9621d3668f48ed416080911a9e128b8f282f92dcde77abffce33db2d5225c44f0e882a92f7c9a97b4787d251e5c30971c5db7f2d789dfecb105934cebbbb7751d31b696c1430be6aa2469dd2ce9ad4f5930bc96a5b6d48e9e6486a38616386a6871583029730f7fa376e1f4e90a065bcf0b13ea57b334327858c168a632b5b68309624d5530a54f7a74a93dd526ee556af0a082b19357589276d29e4242cce03105c388d59b9c25e8ac769282a973b8927356bd5a74ad0b1e5130a9caa7c7d2e532cf1a1621b9050f28983d9c2c17267842426854c1c1e309e67393943e538b361f9e8187138c9546c853b1aaa0ea6c8229e393b589f6bdbe242121386ae4180909292552386ae41841317830c1e49a39278917256b8561f05882f1b3eb62c733395899446a0c1e4a306e257d2db1a96ae19104839d24c82ab7d32989ae07128ca1d47849bb72a12b191282a36b8484848430c1e308061db494b04aea4cfe0bd6c1c308e62cd244fb76c7cdf6123d7814c1d4f72587ca999af3322444474895483103e00e1e4430bd9a9cea4f8ef4304a46b66e90a0776cbd16af05058a253a44e03104738a954c895bdaa4af85608a919d4d287527c3458f20184796b44aa7fa52ac3c021c10a9e1010483eeb19cef2f9caed846b66c7c1697ecb891858e520ef0f88169cec3e9985b25eb430f1f18d48d924a981c65ee1a57c1a307e65c6622bfc554f40d1d20e181c172d259452869bc4c424242423c7660ac64bac4674f2d295921215522d5060f1d9893a4826e78f27e91158f1c18afba4a8ea2742e256b640b053f22428386eb68911b3bacf42c021c10311e383097589fa137c7a47c7948085bc1e3060695a469f769ba5790d9c0203f982ebdfdbaf8f1a2c1a306c68d5f3735b1a0732e758e9e4048482991d25123cfe04103d3660861d153925bee3403e3f7452fd55141751ce1f0908149da7e119ddd7a3e8559dcb871320b8f1818744e268996e4edf6381d123c6060aabd247956742fcdd1e30546331bade4f9e434d2f3708141d547ce7b96d5fd4f2b0c277bf62ceeb93f05392bcc39c8d6c58a268896ca2acc256f3b67a4bcbc75199871c58c07ccb8001633125598c49d5bd89e9e8931990e17a9305e4a69bb6647a8db8c0af3a91ca1f1af751e4b4e619284c512677492564ebc62c615331030e38a19079831012c66e8162e4c61ce71b55cbe29ea92d845298aee57f1214fec2da00417a43088ac570a6ee36241a59448a1092c198549ac53f951e293a0a4de068d0744c18528cc9fa4b67b07a5e3d467a1304982c7cb61335ef32a5098d229b945ce422f471d9324b8f884e142dd5798b728c27a6e820b4f184dc97956b89242e7aa13e6f2b426e5b4624204179c30d7690bf7bfa2fc4c65082e3661cef17dcbf6f5ef15b761346110ba3c2fc5c9497c6b6bd0e82caec884d9ca2f769252f84f79a298309bcd7cc659d295aa06828b4b182c8525dbf24f6977548e0e2c42422c6150fd4bc29fa416724f24c05b0983f7e838d93d577c1e97e0821206a5ab931872be914998bb3f9b7a6d969ccc04b89084e1a2bc868e10aba7c6a18323611e759f24d572d550823bac2470c50c08ccb80016331270a60a09f3bf88be9bcfdfa636c62eb8788449437865b113939fa41928820b4798949b49919791a1e4bd1126b932e4edb5ea96bbc70853fa1816bdf45c4f0c255c70b108534e6a7dd6db93907fe2c0d122568922cc7a96eb8436ed9295b316709108f38792e3dde29e37430b5ca15501178830694b2d26dcfe479327235b2259681c707108739da0826a313127aa212121214e034d101272058035b83084b1c5abee93a0e4b46b268530c9381f6152ca294d0a17431358528430ef9645133125c9594a3a05178330c75a90cb9295bc3fca487021087349d59f3ee713113fb1145c04c234fe56c2f65b7cdc2c0b2e0061b6d491176fa1b58274a9e0e20fa64eb2c923459724fba59de0c20fc6934fa3e26bc2494a385df4c19c25d59f20943e41cd0d090909495cf0c1dc61a17384ced61c8b759462e3620f6651d952187552e7d44dd3181012b222a523f5601e9fd792e617cdb632a2a31910129288145a1e4c325457fc86f79ec95de0c124269424e9d8695136740753f67c99201e4348d1e120b8b083493a99aeafb7a3a4d8edd6c1a0e77fe1ca443f592f177430e55bf83339c7c598d6ca1cccc15c6eb332943a2978021772308771732f25bcd5564a0d47c1115cc4c194f7290962527055cbc1c154e2dc688efce9f7ce025cbcc16852b024878cce61dee40693e92408fd109393bd77d1069314b675cd547496ca6961c3051b4caa94fc94c4bda92ca3dc818b3598e3d4aa4b478cbca95da8c164c27377c97d726e4acc451accdae77d9565c2dfca2121ec031768302859162f5f8e6b25eb2ece609a15ad9115767fa785849c09aece0456c351704f706106c3bce96dfb3fd94eca6251c351506ae0a20ca60abaccbf3b3f070b228371b5e3de4f90cd8bd98484e0180cf361f262279364d18e052ec4603eadfddbb15386d2e5163bc260b6f924d6f52d44c9302444cd082ec060fad1514cfa4b1f479e898b2f98554f8db2a48414cbb1f38249d895125a253a494a740d0c2eba60923de8cdc6498286ce98062eb860127dfac2765f8cb2595fe0620b06f5a14ae6efcc8be7ac48adc085168c95edfa771e3d5f12bac882e14c8dea64927cd2e771644b07164c3274304b71c652df45b3868b2b98e4f5b8e988fe4e82c9031756309a78f5ed0e9b911fbba882496e3e7afaab09974a3a68d8a81bb8a082e14d8e4f3153d225318e00074440e0620aa6524175dd9892e2c92fc7c085144c225d66c4c52d7bf7525f701105a3aaa6eeedef8fef282444645de0020a06ad2863b9bf2c7bdc21212121496506c6baf293774da578fc4461aeca1fbdf39968c82e1406dda243c552bd55923618010e887ce400041446b7b4bfbf8e25844a3f61be1c3d5a98ba91b9cb13e6d461fc4eb2ff8ee7e9845943c3d2bd7f85dac609d386a58c9d20edcb4c9b30b9e5891f22f3c8961a00441386534287bddcc10e8064c224967fe549f67ae16a4c98e64dc92609aad40993f2e81246ffd915a115e4b486235b963099d7853493927c8543c46dd0b8aa8429e777a97e15dff379642b8bb3b5c31f870d01841226aff20ba1737e9eb54cc2582659e8b1ba37199f244cb1b4f50593a5feac33b285b2924818d4c7fd31d9c4bba4f3912d86802e6300041246cf66f63957f808638948bd1ceb3ff68c4e00718449185527aa261ad94a9000d20853f83429c6b37530b916381881d0a5751fd9a29163474f016411864bd949e97a675d00518449acbd7992fbd4d615080909b12d5c240b1c35685cb9300248220c6ead7d2585ee587f883089fc20d45d093ab66422208730ea5e67695ed878fc0d617cfffab87c13443d095208e39e50a2844fd2e9abe415400861d02c2598eaaeb6745a1b8330c9e596ce2e9ca0227c44c3042fa243c7fb1533665c600133424242427488e0d081c58c2b664c60c615332a608190903f18010e88784c02441086d176f17cb10361caad4a22b3d9fb5d2108208cf295bb6517a774fe3b6cbc09deb400f98341c7bd93a6655397627e305568b5587d57962a35b2452325916a8002145043479f2024648bb33d00e983a94db84ad6a3a12201081fcca1c396b6ce266f4992ca40f660d2a2726cdbc70929ba7123c7971100440fc64ded70da923c481e4ceff9c42549733c98ab4eaca399989c57bc83e1ee4fa45d8a922abb3bec60faac234577ca497cdaeb6012ca4ce970928a696ea183715e4449e2ebedf1ff1c0cb7d92a1b6ef2e4570ee66439bed769933e5c320e869383677a4e2384f613381854f2a40415bd3ee9d71bcca2a48abb5e6b5992e30683c7fab8b934a21e40da603acb93938af2a2b5c46c302841c5d95792afc1589d3dc85b92f3ee7cca0102440da652e25a76f3eb1cbc240d26f1563e662b275daa6830c955929cd75225cf66d939809cc194b9b9326f4a96683a5b98e1a897a74556e7f706903298a49968f5affe975a2b0e206430e82463214eac397d6b0c863d39355d52ab5472c560d03dc16cb5e42fc8923018f472122d96a58adf0f0ca6394930f14dbdcfce647600f982499c30677129df275f3868ec28388078c1647a562c9d7cb43f932e9864890b1d1bb7d1b1111d40b8600a4a5c10e9514798cc1701b205839e4b3772b6b2625a46b652471f102d182b2895a6afd2ae86980553493934d7475830575fea8be8baf03202b982d9523c8b66724e3ff1b282d1357c545ac9956bdd1902a40a06ab3115bb7f94a834e350840408158c1de33e496acce54fca2502640aa6bc5d824ee27552e2bdfd01440a0693d34dfcb50fef518a8271d7825fae37b9418040c13c4a92963aba52e98a6b0079822978ba143f6365729ed506102798e7d2d29c104abb69c608902698a28bd241c50b6fb13e8c08102698e3a794239496f956d295204096608ed7493ead1e75da593e8028c16825d7cf5fe429d3e7c8968d2dd01533905e124c7eb2c9ad7d72f224bdbe81b400418261bf6dd75cff2bab8d05c811cc16cdd5b2b4d82759ce0288114c36324a8f8fd2f549bdc51131b38181032982594d3a491a95c54b49f6c87e16a7738010c194e4dd3c4ef2408660f2b793cb2f554427d10c4408e6d9cd9155af77c9350b82499f6a8af6951ce4cf4408204030e9b111b22ddc058b510c407e60ced9740a4b2f9ec28fee6e00e203638fc7eae9f1987d9dbb1e98e4eae0b6a76169c7bfe381b90495938e2835d9436302c80ecc9d2dfda55715ddbe8d05203a30e7dc915f2d49a99c6a901c9883ab25fd52717ea605c18169dbf47594e81b62f31b18b573b09247fe2c546703d32731b17e336bd793bb1a9852ba9c642b2bd7537ac7ebd0d1a508203430ee491f4f6ef229799719989224aeb296928416f1dcb02102220363872b2df75b7229f766025302480c4ca2acce96ea54533fb30d101898e4d0325339e4de491622a86f6411125203e40506f37882d62fbdd83283b8c0a4e7a93d09ed72493cc78d11748d56184da727f173ea46b63e58615a5ffbf3ae114aeb7f4548887eacc224054f2797dcd2a1df872a0ca3d643eb9e96bf14f4910a839ba7adeab4977e59fa0ab8e0031546bbbe24fd4d3c0f61dae1e314e624a889274cae9cb4a9d5f0610ac357792ec1b45d2a39e902212122e5a5e4f0510ae38965b1e464f359cba323391358103e4861ac9c61b12fbdc4b3751406a1464d691151920e221d30f81085312e2de8b0203c58be84c29ce252125f46c997f61a8e8203857994bc161fb32adef71c7c7cc27cc24ec9baa104f94c3d61d88f7157f2783c1fd34727cc29bb25df907bb14709274c399d9ffca5f0d9478dc08c0b603183c5f0b109937c390932af4e96361930e30258cca8d28431ffb48b70cbca49331a59e8d841e370bdd3c8c2023b6820a024f091099316a1a38a9ee51c26c684f9f4c4d1ea58a5628b4242121a3af212e6b0a7ebeac2a9d2a5620993c5eca0c49c244d3e5b098389ef51fb775414cd6d0b1f943099c72c612d2d6aa8bf2661b80a9aaa1eab3f4fc97ef02109539c37a5317ad9717124ccc13d099674592061ca3b292931cd82e8ec15011f8f305d985e122d5ac972a2234c824a1969a7d408c386b6f49e7d49fecf39021c1031c107234ceb5b7b821899ee39297c2cc29cee2a5744283542c9330f3e14611cf1a322373d97a8d7858f4498d278c5d77ccb9ff31da22351337c20c29c73f090a34ffacc139b71012c66548914153e0e6112948ffdef6da98a920f4398f3dbad8b8992dcc14721ccdba17ad7e4c24efe5c3163c605b09821525674f82084e1cfd676dc4497be944198a3e912bb42a9a85c6548c87ee14310c692c5b3524fbe0e262724e423102625a217748efd274c70c6152275860f409854927b82a69cdc92362c3efe604a1922b489d4caae99f5871f4c9227abf4d7261c010e889ce0a30f66f354e2aee74ae7c1ba620258cc483ef8602a35259de9cc05711906665c008b193776d868c016392e707b308972bd4ee9693d98b43da76cb25a63fe6379307ea59c67be46db848707d39958ee9377caa4687207f3b98b12d4ce29df92640793e956f9e471dd6b74ea600e1dc4f8a5a44f996c1fd2c1a8f1bf9dfcda3998e52b2c5f50e27f65cac1ac25a992eeecbfb792713085c9d5ee97c644ec040773e5acc5f093477869df60322527ba737f9eea246e3089a5d266d6f59287b50d26596d1f4494684be944d960aed15f2da2fbe46a750d26f14ef683c7a758a25783a9dc5225b1ef656254d2601e217227555abdeb3c1a0cead1dc77b497accf3983f14c1c612674a9b020640673ce272e6f059555b3ca600a5bfe5fa643d7559c0c26a5c69379ae9373f63806c37c3493c4cbb56fb205c56072cf7d5245dc9a7c5d18cc9ee411519aa12ac5ed030ce69c4d3ce932a7b2ef178caa57a597f733edf68241aac5b3f2fcff31e647178ca2976ac4bae654be70c1a833734af04fd926945b30e5f1ddbcf89db3e45c011598514a0ba60c3956629512d23ab72c98c5ff4f5d494a2fe7688e1d380e7d60c1606172c5b7bbe2feb882416a585af6544a92046d8bf48f35860f2b98dff7ad4a883c3d7322838f2a986e3e3d7bb2b8134f122a18ffff4fd64eda4f3e2529c1c714cc973ac479b8f664ca968249c9bb378fb31cf3a591adccb103c747144c26b8fe8be5a4525f4a0d3ea0605282aed150e3a326c845e3e309a670d10ba7bea3ae3f57ccb0d322242459427c38c1b8faee61d9e2aa44130a6e202024043d0a6e9c6b82c16a46e77422e7d9e9912daec007138ca9fda33cd587e9f71f4b3085a6b529b12431eb45f6a104b388ab9226b2feb3b7249843bc8918d9cc2f930e09398d0007443ef08104b3bac831418eea947fd48f23184dc5931055a2840bc25523988493521c4b4959971491e0a308268d71932efcca92c6443089164e94479f1371e195103e866076b7a4ff2cd411e08088083e846052325c3346bf5bc9b68e2d725c20eb230886b7f47bb293b09fe4d308704044e40308c6d3e2faa544e5a4547e4437c70e1c67e3e307e673f34ba167527c4aa3068d85c08c2b665c81a7e7c307c68e9d776d5ddc4d441f3d304853720825a875b4b08e6ce5070f8c562b63a6adba93abe33dc78e2acef13b68e07eecc0a4b3f78dbb8f985215107ce8c0f42655a7ac1f3cf49a69e34616578484bc8d1b59f8064242ec3f726012a1aa4d14bd1cfba9d3d88203b386b79b5c66a26649f9e0e30626712c9d92ac54d833d9c8960e94c5d328a5840f1b184f2abdaeabf031217b1d1f353057e52e936e233e9faf113e68600e234bf83f29ec774c46b63e6660f82a295534992175f5912d4cc3870c4cd1d37dda98d896b6c471e30c0d1f3130093a29e955693a090626d18b25c751f969a9b209d3a52bbbf895bc93d79a30080bbd35257464673032617aef3311e7c9dbf48909937c89a9e43b324449d9c8a1c5493200e31226414932cd9354a3e2522c6138b94c46e570d94cfc54c29ca4b693a328f5d5498c126615e5daa5946e4f1b6b7500c6244ca5e496532aa534eda1244cd193369552b3c3aa2912a660f527beceedc9be46b6685c390006248c3ffa4413f34a1e61320fee267cb33c7e3bb2b51480e10873fef44af3fb37ca745580d108c389d739e9a41f72df64642b49174580c108c3d5a55c4a49934fbd83b108e39bfc185e23b6b99672188a30a52b6142bfb7497939235b22288b1b2388b2b8311212523d809108e35f4ebebe768292cb4384613c8e50662a6c8e7c0e6152e1ebc2d4bfc6f52f1735806108e3fe49292fa83025c855087328d5d9db44ab7ed908613879a993b86bb12d8d8330cea947f3b60d078d1d5b80210863256942bf45ef94150a84413b09a6e2ff0510660fb284ae7e90ee73fec1f462bae477acf420a291ad7443644447330017861f4c96c4ce5daacaa936c2e883f9e349bf234c54bd4a59030c3e184b92e3862593a24f987b30a89067e51a2709e242226507187a306927b71731b5a3a5240f5f12316b49b8850773c50bdab5caf27a9cee606c3113edac1f6d9f1bd912d9a2988ea75106c30e66534b3965af549218ab0e063bb14f2f2b87ddfb8e163ad65800830ec6b2acfd2ada39983d8f6cdd9c189fd5e560d231db23364e8a76671c4ca1c29e682197af626787489501061c0c27afbf7bab4d95d76f309ee6cdf598185bf285e106f38cd0694c3fbe09bdda6074ef6fd11ddc32949c0dc60ebe175ec44bdcadd6608ebfb323744ea228b5abc1a4af44abaef792f9c11d376c94c201230d0699d70ba6229fc2f4912d3418aca2cd888eab69aa3b83317450de1e4d49b5df8d4d3398736564c4bff3a28dca600c5913e2f49d44b4920c06d161b292f8122bfb8e2d8031067398e9f920bdea7b2f30c46050f15494f9594e965b184caa56ced365cb2b4c186030a5c929e6e464a54248bf601275a7c4d117bd6052297aca278eeebf70170ce273a6954dd4ea9f430b1c96050c2e983ff754c3838d585eb7601ab19e4cf2e8a72696b4601a11d26327e984eaca6164c158b1de4d85cc071deb1b884500030ba614b253b47f0bcf231b345229bb82c9cfb6d4f9d6e9df11d97811b4080e2d6cc0b08239b7baf3eda36628530530aa60baa89b272761254e5c6050c1a4acefc7432c43e9680ac6f81c25dea84ea9752998945c556a72dfcac875640bad6e01230aa6f3dcf1925cbf772b43c1f823ee9521de7aed3ec124b7eb16fb4568f1d00906751e645fb6aa244f7a64ab74c06882499ce7e841273541491e16309860f88ebf24c7ad870d952518b5530e236d4cd25a1f184a30f9891d7a166639b49e0473aebc56519f54250faf4a000309a6bbf6248a7aeff8b446b644fc51f07503c6118caa9d45283988af6d1700c308a63071494e75916fe24213c0288231949ce22d6fc7d96ea0cd11c02082712fa8e09f2d097db9c11882493a31615674289db42304739c878f564ffbef6a104c82db7879fa1308e6d9cff693cb4e984afa81c9e49c3549923227057f070c1f9824a9ae72b4f6f4233b8c1e18540a157b6d43dacc9c5f80c10353fef792c4e4faa0e4db814186149963b11fd91211d9a27198b500860e4cf16b3e7eaf9d7d6e0a307260cab19275ec458f0d1d07a6d47dd9133c07b12609e306a6b74ef356a7ef637c60d8c01c2c7810b57fc249827f4ae5805103d3bd971c74c649764a0b8306e6125ba2e5536974fc1dd982310383be8cea78d1fe93fb0060c8c03c2a42bfc7ce9dad253130968eea9d3a134f8406030626f5b7a46754a809599a551531c078813968899e6149acaacfc3708159f3eb2dff4b0ea7a4b4c2d84992f288cb7311ff6185f94c4eb1e33acdbdc939223bb4c0b1ba0a93f47726dff689eb41a80ab3967f720f5d3f973f15660fa3c2d4585f99585061d475955352df44c6750ad3ad76099e6cce3d87a6307e57a8143d4f4a17d352986e4fbcb417ab249d2e529864a5b4b373d27fb27b1426f197d382ce969ced89c2687ea6935e8ffe775e288cfba26f6b29ed964982c214469689b1d37177e5270c2756503379b45ecee409930ebd930bdf36679f4e982e3f9cdbcbb8f9473961f6da6d7f2fd39d7b7de1c5260caf2608f314ac179a309bd8eabf96e4e8d87d260c4acaf92965c5be9ae705264c7ad94c36396dda9cec12e62f59dabf4a5d57ec9630667a9fe8b592a5c4b912c64eeaf304dde2259b23250ceb63c2cd877253ca330973d847114af070525a52124653a6ee654f9235e645c25872a22bc8ec216190ed953f4b2ad245787e78f108c305cbfc51268d955f46b6ce11a6339d537c2fc586898d309f523ade5b6cdd90214698c3528e77a955ba3bbe1661ae9cb2995efa105a9265e485224c4a055d9f4d0e8e6c99800422a91f33f080d48fc515337668018190901c4f821c5de3d18d0884843cba61c3f43fc78e93552ef6f02211e6ccf6175d2f7d63d2e005228cbabfed512e7492537508837bfe8b1c71726b9586309ee9a728eaaebe2de48217853065be5805bddf33f111c2d86249ae3521b5c3c70661bc0b2f1f3bd382692c087389ecdca617a274a53a861781309e9276d9ade424af42409884b889b5cc7c6a1311d018c1e7a8fd8341988afee59f6669133f98a39c7a9ee58e7529fb60f813bcfc242ff136e383c133af2a67c993a4f81e0c9fa2e4589d548d09a51e4c277b75b9a232d4b53c98a389b1ecb7ea9e1e7f8107e3bc8c74d3252c6bc7b2681b437871075336f1745bbcf2c20e86b934e184f7529eef34b2553583177530854a255cfcd265b2ab912d0bc20b3a184c693319134ad4f9650ea66c3a7e94294bd2544a0e26ad2f7a823a495e483d0e0693e7ffe64b29fdcb8f6ce9a091c0c1144d4af93c3e4bca217d83c1e6b773aada2dbbfc0d13e40b379854104aaf4b259b4b6d1bcc67e1a4688b9f446cc80673b0f7a02ab98fe53bdd1c5eacc17c526bd592bc4fe2a406c37609a7e37859cd0973bd4883492713d34b5227683056124b8e269a78c9a8cf600a55526991f35529a7cd60f60edbbbf2f776f295c1986d9fbc4e6ac9605251aba324fb0a22f2184cfba1cefa47094ace1e3118b49f1ce553f59d594a188ca2c2ee97245d7fc7cbeb008371f352ed4d2f652e60f0e20ba65259a3c43d3163a34d890612795fbbda7ee105e3655eea69a8fc79ee911529b523c70d1d782fba6014d197b3340bed9d840ba6ec2db23765f4620b46cf3c6d662fa754571dbfe3460644ca0b2fb460d2d949b332de91ad1b28a917bcc882f1a42ab14f5ba3e438221b9d56831758308d47bb24e95ce55f2a8b052fae607613eb76f3a7f27b6c05d3782953722c9c88bdaa60d2e9d7e42d37252fa950c16c52ef9334413905538da5182f6a41e8f7699c1c3f8190902ebc908269e7ce24294fcb58f8f845140ce226bacb45116bb9823e780105d349499e242e67bd7af80453ca9c4e6392f23d15748249fe8f8a934776c9fe8c6c130cdaa27f22ec3e9f8a32c1a0ed64dd07a52e785a5f2cc16c52466bf5a41b4f4a94609cd3419e54929c491baf9831e30a2c91dac38b2418b67b5b849b892eaa4782b93b986a976a99d68e6032ad93a436253d76e718c174b12bd5e414e66aae2298c28efb9a14333c9d9e08c6134aae97971cd3f434b218b021012b1b5a88d8b871958ce0c5104ca7dbd767ade42449ee8510cc57f6bb9dc4f198167a1104b307bd36f3b1224f7a376e54e005108c16732a871071d1158e6c896c916347d6095efcc0ecc16eb4b709214358235b55e5082f7c6032b18eebf99fd34c02bf9185c88ed7c1588484d88b1e988212533aec29d1accb173c3027593edf5d2ec78637b285430b915783c18b1d985cc32ab7ef2769e2d681399fbcab99967f55d11c1867b479ea7052cb9c3830dc85bf9b855dced36e60d219f912ee4ed6a4f8850d4c762da6dfbc4c5eb52d72ec2875012c6688ccb8624603761c2024e4450d4c9b6127d52d3d7c13bca081d14f978c4c117b2dff0ccc7ea34e97871959cf65604a714b0af39d24716779110353bd89a524cd0e512fbd808141e98ddae925499aa0f3e205c60fd15d49eeba933a1ad9d2a1450d2dd0162f5c6032dd9d43bde959ce9e5698dabc72e4524fa509b2c270491895d1df49696947b6340020ab307afa1be1ae9efb2a3eb240005185297df5633defe73d646100498531445c10bbf5fa20c43a50d0109871c516ff80195714e3e81a870ab376dc51b2a8e9774a8d14c829cc9d3d9e668fc84fc9a1850e1bc62c00620ab3e7285a4f2cdd4ce7700220a53085f7f79d944c5a13f58c2b665c31e38a198902105298f47ccae9a37217ef62d3c2d1354aed0019453232617e0b5d161727a5ef0513464febeffeadfa57e9c896ab5dc2784ad81315394bd9c46458c2f026aae986baaba524235bba322a614e353a7b98b8ac57324a982495f42d4c344dc224875d8efacada62ab244c295e504ae713542c391a09b3d688df7dda748f1d240cda16aaa246cee432c9788441057f2b0b168432f97584e1843049a8c516f524fa383e8726e56f822b808c46184cf49a136fcaef4246984743495f7a4e3a2137198b30769f8ad4947bdb3eddb871382043118693a25bc97b9ded3dab4346224c5ffd6649874f37a1d52107198830075529e99c254fbbb48c4398a4b812cde3ac72c4a7c020c31026713cf43b2c410d54aa1026312fa9a4190d1d4e268439efe747ab3e7e50fe204c2687ad2ea16287b92a08b3a9891ea74bca2ea305c2a04387d1a684e8baf24616059f280310a62b25e89e72f3dc50ffc1a0e49c95ecc29d901ef58339e9cc4ed162eef5751f4cd27b9c4d11e3c8960e1a574690c1077316259bed29297b305c8ea73c95284a8b4590a10773b81234b4a9dc9f4e97910783f692aa3a6fe67a5df06036398a30f9fb17410b84848484c8b883c953d07fb18d5f1bd30ee6249cd81a7961944a2a75308736b14da8bd94f7ce0064d0c124ebe424191d4b2c133407534ab5a32a693df174918341e5925389276e58c627230ea694224387ca3813bde160d47a132ce8917bcf6b480896483542c61b4ca27ec9962c7c5d44ea06a3aa8ada3da543988e8e6ca5744384044e830432da60925495fe587e6183414931e1d4a78ea773720d2651629478a65c3f8e0804196a30beb60891a783943329196930e74a82bcd3505e5f6f0664a0c12046296befd3234c4e9fc194975e2d9dfb779e59fc88e1408619cc4156759692a3bf7c4946194c59572d8d1e1df219924106c3a9f7a896a4094a70750ca6346154104ba12d6b7d068484a0e0475a86184c29cc84580b6da5c4fc14d0b0401206934a66b1657d5d3272e9810c30989228e24943f6bd7929e30ba6943d57e74ebe958bc9f082712f956ac966a2d789766871c3068d3515c8e882e14c892d4995bcb424c40573953e1fb153a53594b105635e891b2a89fca5490b195a3088934db4eb3b32b26010323aaae74f113ac71d555830c72b3995ce5a23efce0b4840c615cc29899fb19c847ff924709061059305d3fd5f26e813e6546b9051057354d37f3541e77d0f7320830a465593a25c3ef55327412fc89882e14e52715297280e6448c1e8a24db8b5245fec7492110593bc58a145fee57269060563c910da84f7ca9bec4f30e72ef99ec54e34e1c9a2479002329c602c4949fe2b2635b40505329a600ebd24c9ea6adf361a0974f405cc6ac860823988c92bd1796174ce46b6b25c206309e6e4e67eb79d84fea097a1046358b470e9c204fb376524c17c2ab88aa570e13f7890601ea5d5c4b4e4b01c2a19473099d279bda412943429dd840c2398c4ee89fdad6dd2e84e4611cc3196946af7f82405a10c2258292190310473aa9e3f6d92c9c817f11132846036419aa7dd5d172113c172a103194130ad59a6e83395be54809087095593579e1f18ebc365cb558c2d65715d42860f0ca72449ccd239a89ad02220a307a6ec755deae1c3bb2789d8b841638bf4af11e08008481064f0c07c3f1ac24ebc6c15b7912d9e718105d8780b8840c60e0ca7575ab58412224d3db25556c337f0a518204307664f7229f9f9ad2d05253272601a9977ab73627fe974648b4364e0c0f06a596dc9b2bce76464cb72c8b8816145a7649a27e851aec9b0813969b8279d4d5cfd2757460d8c26aa66fb2957f4a9a89940060d4cd71e54ee7bab939546b66e204e1b3266607ced58794abc1d1dd432646016a1a63ce6639509b5951464c4c0d4a54a8815254e8a15c980c173da4686cee84990f102839234e57f464b18bb64b8c09ce4e896a18368b4c2d4f53bdf6d82760e2bcce33989f4d22623db2c68906057610ce99f3c46af2e891e111b3768682521862a8ca3ecf64ddbec78c5908d17317b428c54989320547efe683ae824458549e52bc9939af8e117911be8ee14e6d3f59be15d4a633d53982e5c9824ce64540921b2a145ca2b8579b64f7a53a286ec5fa4302725fe293996787972a3306f8f30d1264a47a83186280c5752fc3397f712ee8d110ad3aa650d9956a3944e29158418a03088145def334a8ed57c9f30a84f5f42b3add39e30aa6c2765392c9d307f97fb9c144d5cad3cb2a51582189c309e367da257b21222bfe3438c4d18d4294b1a3a8fc5124a3744121dfd5854d22086268c673d627f497c92bf202246268ce54143dce84afb1a156260c278d2d2a8ad7e9f13a34b182fe54e65111dcf54c812c6b40e7efa29a7f47456c25879c44a2bf46da973244709734afad653ca39a8b8fcc8168e3e810e111b37b64f60011b12a82b6694cf028716179831012c66c020c624cc23943c9113dfe15b0ac490844178fea49784eacae10ac48884b1ac4a89eec12e574e818441ae46d5e9245d86923112311e61107af2bdef9ce71c3bc2682147c7709392a79264640b87160f88d108e37ddc9937bf6ad349311861aeebf03f962de524c70d911b39ec0b311661b091bdab8e1f732b2b0a3114614e399fafcea74eddf7c816968e0accb86206db2146224c777de264bebdb288ad440a11e637ed16bb53123a96480436686c814addd861a3016938bac6e5210c6752d72555155d738f610893a5527e7372cd6c940a617a6daf789d4aef9c78642b06214c29c9a96a6cef932027ee448c419872ca53f391dd97c5b3001c5de30461ca9775afaca434dedec85655484802665c31a34a9d224620cce964de975e0810a6d696bf4bb2a51c3df40773d6f70a15f5673e913428c4f08341f8594ef1c24a7d6863f4c17c3a9c94845a4bc249925a88c107932ae93f7a55773ea67b30679cf4eac1a4f35cf4f021f2cdc479309994f44591eb5f42e7f060d84e72b96a874f16e26521c61dcc79548a0a91214c9c5e0411c30e26d35017eb2979fe76cd5048088e1ae8ea6050f7d09d824e67972b3a98e3573a5d5649922df639984bc85549952407731e19398ba73a6d491ccce7263eb8e88e69b2386ae4184124c480832975f44b2b5f4987140231de60bc112a9f567fdc602eab1b513bcdaa0d461125a8bd70e9ae1499718105e0a881811c3748608386056af806bc10830d06614a102972ea1a4cf9498aab9e5b949bae06638e8696ddcd1117578c34186e4c747953b5d8214583c124b96c8474ef0c26fd26e78fedea7dcedbb821526298c124e9caa227881caf128484885106935ca7d37edab7781294a1cfd1233a740431c8605af519933a4a478463307e5092141b6331bb64c56050279c902bba248b9f0e83b1d3fd72798ea1762a18cc39c9d6a3d45f347dd7c896b78de725c4f882e947b4d25c790ebe5f0c2f989387d0a34dd698289f2e98a498d10d652aed252f06174a69f9f31aea6dc1d47749566929e141e768c1b01e2766e50f9fd47d46b6ae8c10230b5ff070c90495392106168ce695924ea11deec7fd418c2b184d90a24f92af424ce7ac60b84ea3a40f23dfe66b8c2a98ff74c9a293b24ad91d3a1a071e2106150cf7c1fd47c9f5182629c6144cf94477f7cf27b1d3e7d85a25c49082412975bb0b2e9726638c2898b54c2cfda4aa6d26b743c78d098ceca0a181087040840531a0603639425828797c3bce2abe428c2798aa3ee9d4a6738cfdc909a6bc27b694f8ab277add0483bae834aa838e09a634fae14284c6054b2ec174a183cba74ffee526251854ec539d29394962d524982bccd9f5cb9bb648305f7bfc8bbafc1e361fc124c926dd83e9b0546d1bc174a2448c5925299657114c5f259fe641999cee840826a53e5d9fead1d1466508c618393b397384cc84601227e5ac94eb6a55828260aa6cf2878fbbf6783d108c273a76343d968609fec09cc3cce8672d396c5e3e305d0cff3a0b9d25e4a807a6b7e87d3ae979b290f3c014c498701ec75ff5b61d98c4702ffd73614bbc5107a6a0e4d5ca269ae4395e0e4c4aabc4a8279d4a570a0e4cf2e52c49124268d933ddc0144faae0ed5d3955593630d5e5c597d2b5a452a9060659823cd57596bd17d3c0f45a2749262539eb783983b6aea451e79d97813974fcbfeebaa45298c4c0a0e3397ef4fe2941f4183030e92ecb95f97bed271ce305069d2afa09d318157d0c17984bd4cf69b135c6d36a85b162ffe8b8155961180f6ef1fd9be9d65985e14d9264f6c4434baaa8c21c73563ec609536112ee84bcd26a9d0b27a83087974b418a5c07f9e15398e44fca9fb2cd564cce1486cf1861f16cb772bc1406a1754789c95732cd1ad912b1902b18a430b6a79b74be21c52f34b2b543871648a40e083046611297b755a93f09a7a328cc27947bd27265493a1518a130adc75c2f55b2f898090c509847e7b368eaf695adc3f8842999e5f9d874d7d41f86278cefe1fde9c4fcfc27c4008c4e9853cdaf4bb4b62c7a7222904ea824d265a3501c0a8481188401000084779b0063120000001016900824129150b4eeea0114000442483c6236341c221a188cc74491381c0c07828150201408622086c12888256912cb280f46bd70488be999e92802ad52cb9e516cc9a78cd85a3a0a844e4ec04b0ac599c2d139c9598a0938c25c5281cc3ac4a9b51eb40da2572d6b9a22ee8bcd42bb69b01e808a9f365491aa1d040e5beabd54dbb5182168d03e6bda35a6dbd02c099673a33db32655240e7eae6bb58c9c6e581f12bda31ac51f8f84268038ebf75fbdce8f352d89020dc912ff67635aabb561d4318f126e70d523ea5e4fa5afdfda4ad1325ac7c29770d8bb923c1117ec9c646689a80c3e843ea59d29e0b40800f872b0fc4327aa5ffd2bd09418bc1660a114f17baa36e1e1245206625bc1583286e037929a0d1804e0faa898cdf233e7c9dce318f62260156d2ce03aa64e97ba44c17a941336401751ace25b00e729ccb2efdbd33d41605a8ea9847b3a81cc8b35008a62cf620f72c4b7badcb3414a2d0dd3772089610eef166a30e463eaadd0017577e924f8c03b502d147087c32ed5e6353fc157321a5445595688f13f4ebe2d10638bd7cc491fbba67580a7890789a8c941054db65cb2725fc13e7f41380dc9e3310655d22c177626493aeb16dcaecbf77ff84b8d34e47e70edb49fb05fc6dcb8cc6f5b683689cf28f0f2bd71380fd624731be02b160a6d29a91560d218ac8dc26a0f00bf61cca8caed903bbe2206014b862dc2d6503113dd2475513ba3aeeaf1ceb2e02ce42da7d4eff1c779658672b021306f1a430868403152a83159e9b12ad1074f2124c611eaba535803730191b23c53af7fb18f5eeebfbb41f75e7039c163081c6466919e79808dd319d0e1eba996284c30719ccbaca3130445d97af8a6c95a323c30b433a7f04d9cad03ecef9cfe32feeb48d349d2ed66805680c7baff86a4a3c896426178f2123251371b59af9c79fd12e3404d0c0ef9e7267c7b52861aa15117d70d138c109ad86fb829ea207bf88a08e48803c7bd174b34f4494e1362da51e6009eb9cf269b003cf5046c84a99cb0792190f6dca09804d3f3be1d9e320ddcbe5950a0dd29511130718804e2bc1d23bb084ca63dc0401443b14804bd618d06103a4d53ab65d943427db0388de95705cbfc178659605226a86695d23b56e52c74004f34c893a832d7c0cd5863217979b74b6e71ee5abbed249e9b9adacf549715988f0335c65ae4e884e21c98f35d29be30490ea6a939b0fe7ee90a03c5530d60c8a2a167f22c4b1013c3ec1fef2f67710e932c7e2bd261cc36e16d241f4a1527037d62391dce0a0c505bc7a5707aa661615e6ac33015efe7e69e4e9e51662b7b2bfabfa4cd7ca9d033713748287ee9091f04eaec6274e025b96caf018fd52b78e31f892f2fa7cde8c67c9b4e1230f20f3ab9c4b4885d68ab12ddc052489ac0aa92fd4599814799e86583f0fb7c7bf43b3f07cce80638a4c33e4f61dc3029f3af3f61a1eca42969b750a8fc8046c5a6bd648255ed47c61ab9dc720ee641bcfce843cfc38ecd45dc8c4f05378d142a1d040661cd26b1f02d1013e3c072f93845a9433250774b9877ba8b43827674a235c4fce7fd01d4414dae8634b026d0b5b59cd823beb116d0f61eb7c9c1fc04537dd343d829ce36b2673df4c7c5ee3810db7e13356a58d265b8cff630a09de1f20fe2456f8773f3fe26d79d3882a2969f391013525fab744f229a3d0e7f39995c60ea9a849849ab2e7b30beaedfe635f91665cf4000f6a90431ec662a791184ac80f6a905e5a2e2102fc8c08be2c95afc12c8067bd972217c7c9939d26486e6ee5cda5e346593f0e5cf8b982357a868902746c5a807fd4057e863a9566ec89cb34dce27cddfb4b5425d81a62efab57bec3fb85aff6d02d325ec4498e88725504dac2dbd3fa135d4772c52b1386a26d212885f8f1e2c8ec0bee9102d31659281a1dace9cce6abef74d81a192970094c047861cedcd614dee86abbd40f25ac9fcbe9ad9cf9aed8f7853d7167e4c3aa863b94af2a042d61e27b92195bb8c032dc2262242f4077b1a3e60d2fbf93a806d410ad772e0051dc0837c6f9112ef14dcc49cd2cf17f07ab7bdfa65073c092e129cccba97de286142803c01971694880d1096481663284f6ecc42cf9648e52472552746cad41c76b101bb641d2b01cb399521ae25035cd4fcabd54f932e2306787665927fe30063e79cb8b1b7be968fe56a1408d781961632c172276665c53e054b667b67af40219b96bfc9fa6ed831b0d1ae9739026c0278fb0ea32c09f9ad8fe92063f082a32c2b60fbaf2491379d7fb4adc04642795ddc67a0a581462bf4e40e96d3f36bb3fb42db42eca905b0dce084e202910f866e97b799ba214ea0f6fd81e954ecf466a4b3c3ad9f0c30d364d4ead855836335f041e684c96b1549a0ef4d1d94a326663bb0cda6344f19f8e7f560e7576d6316ff4f0edf8faaeef764e1a89fb84c5de1dd4634755a6e973c7c15aa69939162e80266ac56cdfd350600d56b810ba6620b1177999b62aefaa3cef681ddbbcfd93de6922a4e97eecb571340a582cc9f8ce873df57c578f61e76db813e13ee0c86125f78daa7f871f4393f9d2d2de601c5f61c037880d09ce39a6b973e08d36441bcdeb1a1881dbdf9748e40fac227b4be3171ba704c9d3187bfe4b0e8b5e0da6a07c55cd2a12dbf75017905b2d38880b1c147f92e9d8100ab805ee025bfee3401e6e712dc57bca05887929b0f3f885c28db84be3fd5588574406fba9252b63516bb5dc58c150ebac529708e3db322b84cf6e958d101268571f5373e6c4000603eadc797828fd43800f5b81bff4655eef3f827d04c7a64067120f94093cd58114003e9e96e1c5110f467b082fb6b27ec9344840c408ca3735b6efc4d849153b4eacdb6399a48fae1b5b84c114c78613d0f0e39784254a5151a0860ece9e5928d9fc7ef16a3824587c553fd57a53905f0128fd6e9dc3accd0391701b94d4a6fdde4801fb67c0a29a34f052b981a6ae918de8dda1731970ce7a783601edd2d73640e85e5ed94712b1b5ec0d0c0767d2b5f801be1cb20c5ec5acc02e66b16e67990a82207405ceb4a85b3a997e8516cd44c9a5c16c4daf99e8613af8088218b2500227e84caa405bca7e3e544bf03afc1a01c88fc8a883feb5b90a3c72c9440055ec0e5f4b4e206508a5e76ce605b27c5c97b91998926a297cd993ac1c5d5f0346ed423199d9e5e7757c5ac380e46b35d8ead6630e6afd0f00117b0fb3ca95702425a0ce610cd88c2566165ddb1018731b87eb5f391c4c9f5f23c23b7c8be5133b79e801fe212293c83839ccbae3790f954f866b354046f91b263584bc09db89f47d6835ce017e06c68da46f80b3711953aa8ea6dce8c468fa79b15a534e6c70609b9e9660852c2f011dd278162ec8308ba84cebd61a31306667f124274503cc0913acd2c016823cd4824323b466d4274e970763bed2499eadaa3e629c57a8abdc886d19439c9c26c8d81c45ccaacf91852d327112794f944395800b0e29a1ed96fac8320742091fa213a47a7c89955200656c0ed0545050dc943fb86cf1225278011ef8889ab80a37d35a63ce51f97bfb59f7de0e84dfdf9b791c9177536c04dbd145db8a94a1a2e797f6d93bc2b42e2729f14dbecd28f8514f5d2d2aff241fad19c087f24af50ce08fd89756cac2ebf85be0b4dbc903921149351484253117297500e42455868b3466e2d94af50ba42e312b2452848422908ad43c8f74289146a52688d42fe09454728f8854adc35600d18a1c1097d25c872a01c8628fe864ac8980267a9d09a84fa51a1c8a424b367b208c127348b90d13514ca8b72ab95459fc553e5466346d2ae996671a1f58a26473d717b3fb83da497ff0817e8a51e93d3cabec2d9770c39a7a5f6b360825b2eb1b961b578aaaa486a0d590ffc5778cae3145f2df7a1c7e68ee42c9865f59112507748d345da5f268b2f008f9c9bc645c5aace160fdf8865da268a350824c0ac8d609d980011ca434677dded130cce70f84acbbf82aba2312168ef599bf554df7100edd2851062be5dbbf8a0349ffe0f016bca68901d367edd9411934758a05487e5e2d1a65c3220d292593b133c5e2b88c7d8b509f6c8d60da052ec906c8973901a4d827fe286301e1dd5fb14d8b2f160d833d19fd73ea5f67651bd45251d69dadfd3127ad92568c8b6c13541511d87364a73f3c7619fa782ec2ed40f4a103d7218b7aafcabbcd9411c931911e4e489ff8b5374a86b6d9371f1a4fd5b4e885ecd2cd32ade62faee850c76ecb37c94d72fd4d9285f107882e39f40659200a17ca0082cd274e031a5ce46cd1d502796c63a975b7bca12b64da7dbce22aeffb367a6e9ddf1e55c130d6da92c4946aa094b2e3885f2a9d80319c021ee470404d2242b1efd21fbc0b122996939b0dd6a4ecc12f836010a5910e9536dbd8fbd29949592b982b8f5da5048840dd654dc792a885209332454d38c245c6aef546b6a54e566b4495159ec3fde2c43b759d8e278a820c3bccaaaea46dd24d6a8da4951fdeff09921b4cf4451f8f381175d2ec1b1206025e163180b0da3f3341eb5dfec8542bbd355d4649d265e663974e3aee00de0238623ab48b806718bc9a17f0c6a258527a76803b576622618b30d3ae6c7e075ce811cc10437eb17215deefb950800cf426b30b157de2cd08ac509fbab55b4d154be869e200eb653a0c970a36f27e4cf2200107cd25725a068ed52924d40bca32852ff3e94a0e22304ef91036bdea78c081cebea9ffd06794f78db6c70679471cb89d938df9e38e0c3b78740f630fa3b57262114f227acdbedba937d32397a08e0cb7c3e53583007aaad02b3f9e96e7315c84c2944d5ab60e6777e300f9c86352c59d1c454d3c3cf462422d7ee1f18e94d75ea42a012e5f81810ac1aec2968ac28992a6bf4dc2afb16fe4370fe34b911f164b753e9e0e6ce79260e7136dd90121df59d6c65d627e8a0622ed0e99302a0578e7b51455948355c1426cb93eea392c0d0bf4fbdb3ea4e8c01b2578fead52cd5578e713df545658c7eb88a21760daa9387551a9bf16b8d6dd15736e0e7985a9a066816b45ce1df385725e4802a9ab6c7e1e888b56803d5ea643aab063c09a73870eec2dbcef4af74dec00b8bac6d2740f3f0d4f7b4e006492270009d2405a25099bed29e4993b954947655fe09f4d3cc54a23101547d300938b5eaf32a3e7ea9b478bdefb5a325f62231190fa33084c1eda806916ccc055e936b6358a0d0f730fa89c3d7c31e586d6d612902fca0d7ac00cdf5a6d9cacd08329219c630119f2a4473d0ee0d145b513189ec147a12abfbb12b069484c19f5dcc9d62a5a823d9446657fb1de107d9a253c91d5137883e0c556edcdd892fc8b5a8a1023c7e03d1b59b84d134a75102d856b239e376fe9c41e9bee899dfe08406da33873779027b056d586ba802c4c53e824e973d91cf5c9fee13e96780079ada670c706c08b02c10e0d83bf015174cd81dc4c1c1df80eb0570ce51a236fcafcf888fb1464a7084ff552eba2ed9850b8b70b2da91e7f235ee02bb9b6290a06ecd46970bad9fda6c35973281fa7e9d19519640a0b3946e6c251a4933845eae47b948f6a81f1567770c1823564fd7c30543bc90e2064adcae2d7747705257d3531869fbb1aa074b3b4384d6029b0409c38d2e115a83d1cc774036f478d47d1bda1c70d11c6f476e6a8997ece30ebe59a09074a90dd44b2a1893ce760d8a98ab15a9e9b71010a613ea79bccb2adcf545c96f06c868b707ed0c0859a837c6cdd48df329a85b922019aa2d8958de8267ed0f3c5d705ed4e80f2beb1ccbfedf52d0e77cf700382edb8823402264a1c46445c4abffa00dabc4efddefea7cda0d4ab40817cfcc609a5893cb2d82e676931612b329f1d6214655c0556b6106c11905dd7f8abcc5bc885e95bfa9c3114651b6d4c704091adb509e3bc77fb21aee9586ec45f8b6cb2ee79d912593a1979292f613805167ad93a9e818a3346456b15e56544ed8eacb318f22d24c02d90a4a7a6bbc6e43b63147969e3afbd53e0bdb014894146aefded190d40c8401308a04d352a002d63d1a149ce24369c705a648d89b610bd7d0d2df4c62ff8bd77cf5806b6fea2af8a12483a421782bbda0c5885202f9984b0405fe717834b52eec15267cd476fa0d977fddd86bec5b679a90f4e4316aa8a2bf4c4d471762bb059b8f84312300e0b654c5ebded00af316420a0d624dca1b4b7a5f286289ec56b1d904c49cedd26d7d1d96e325861360f705c08dbad84aa7820b82cce7d10046886b1fc76acd73efb021dbc4c41e925b86d704bce317344ab6e02478bf1d8b306abb6e391c260038e1247e5e222a0c031d3e6c72dda33c764a11096b7615009e000bec5941a73882bd72d6f80ff037ced73d9d104a0638281f53d05c34bc77902061cd8196e7ded3890aaaa2f9ba24094818750a9d201b125adad6835243c35269f8658b124f104e409fedde0766373ee55f73ed8a69e37ebac7e9e5bec4168c16ac265ba99db6b7b3660d73ecbf3c38659908cbd19bce36acc4a88f04a50ab6cc091569fa0f780438af1764ad70a3c226e5f0d125745bad21813f4da08d62dbe023c0dd611d23b18ee7464aaa6bce3ee2e1e2fb8c846a4d9ee346eb0b6903e2e5da114c584837167a5b798c9b742e17d9e4589880a0cdc7ae13c109528e5aeafe5a646450105fbbc4189c70d46df5aaecb9bd1f39e1ed23a5109d6606089567e830d35243f68d629d709e770ad1e4d32f515f9b5efa5903b51dff507e66e4e248ab2ed1f66d26d9687f2d021426bf1d28b2033756f24e0fedb912892ac82ebacbe266fec0d715a992c28a631a7dc70343e76bab2f7e2f8dce61724c039fc4bc632dfa51778a055e6f23952e1883a07a31d157f2490fda1dd980f34e900bb930c75f4c39c901988a5221f7a6a00e01607156721aeb132489d3d61d1b383ec9f800279bf27e6a01c3d1e3449d4d314e6e6f95d300966a02d59f080fe293651c933bd830e2451c3a66496caa9700c646b9adf2b14def24730ea80f36173ac5a29c0957a3f3ca4e1567302c5244b38f32c4e9febad3425106133072d423d1d5b37178f16fd934ff20750295795881e689711005ff73b51a913440fab5e82f3c0717232c073152e3cf906f5d069aceeb5ac0e24d790f0ef6a4aec7f20774d9c2e26ed3665933f42fb952f464ec94caf0c0d4cab77b78b013407ce3559ab810169315fed426c2623513c905937612057b6f8a7d2d15aad19a89146ff7de736629a2192567d6b1345263310d8d2fdf5c627ff7c200e3b5123a2c02475e8f1fa223110a334fc1ba67a76dbea75b898349eeebff38a91e40d4db73a5c5bb72eb629f99ef37736144c3db90f1fecee1ab6cd36a90ef5940750369cb6f36e40c4c9e3740bc603c56b8dfd62dbe9f147d6ebd297dabb30333181bfd16b8499fcf78416ca84a4e81c03ae2330b02ed142718510c0ac29f8129c20e6c505b3074a0c807da0087468be79151731d27f70be00c528df02100508382e20373375d7c8163aa8ed551e951c22965da1ce067a23264633fa93ed351001b032dbcc1e18731a15c9160162b03bc58daf27c538af470f735eeec7db071b8d0cf74cd2419470d63554ea9dc9c1b31bf10e043a831f47a0c941a33fdbe27ecd3f9701083ed824c988ec3ef929cb62d1a930956277cae7a19d5f52be88dd4633d4849459631aee3b66b9b399439e203fa11ad550829adf6ab0aa2b4d6602585b2eb4279ac2e0f02d730a508725a158f2e26b74784ff7b02290363172feadda7fce7047eb9036a1fa2c750884101e7df35a187c9ae5e9a6064e39d0e77244cee68d6eda6927582c36aaaa603efe8aa8006e493a83918fd84615c5ef22c4e4b89b78c3bb45eb9835483857e91f97e9b2cc94a0db7fe2e84d6d03264b3a29436de0702615a8289d6fdc31369a4dd201ecbdf765d62462a88aff07b3c086446ed6dd693591572631ba66199878591c2b424a847e22c74ca53db4f484027b12c909f04cb64a6583e9277d9063b398d2cfd6e792ff761e81bff80b90767a3338eb6b7ad23131167563414f7a7aab43fe8cd47ea80578a6526043e7caa7b68aa85bf047b6cc6f61afa6180850044800cbeea891e5f4da399f6fa401fccaa1bd1480bf51d08e7bfa1a4c0d44f8d1b35fdb8e0f6ae29411291b0f974f59ea21e88135f39228e594735a308d1db8e6665673e369231904823720b3f3978b1bef51c51ef3dba059453419032380b44520621f0da04d8463e914363121fd6f8ec768232834f47e2056e2252ef29728fbcbda800d10ba066393e6a95c37a3d3e74384b1923dcd2f554b5580452e0f7cd147170109108b647601a72729352775578b331fe29252ada560e2749066859e4868c5f29e0b683cf3d22534fec16f4d68bca4e14abb20127a47c4d310fe4bb97be688adb738a05bd88e0e2f3b335dce26a006409935782e0f6438140349827c7822bec495de4866b5f7a61709256a1a8769f4a3ca9a449fe480ad0549c7e28b1156cc7a8c5808eb0922ef229dd91dc8730f08fe7ead6e0392017298eaf746ff6298cec1901fe05c0381fbc2a86ba239781529434fe37f94800cbc250624901c78ee288172095b8c2ce4c9b245580d819b7493481fa255fae30ca2f2dd7e43e5040b2d84cb4e82f842869098ae8da4527c76f22547d59292426901e1ff28a3ae7c71cb898a8443d3cbb1d887c5cb37065227e5d3d9cda843725c9a54c2a3cafd913f7daa0373f5791de857cf082ecadee94562c96c489b896c25d36069d789323a44100053df89224f6540bf784c4f0347e85f981e2280a29b45b256627885b59656a245bb279a9e16211051292ef2614b17424e99ed10750da855de5c4ee286696a5888d8313562dfd4895045b930f944581e1dad912a46c7b244ba8152a08109f39af71102be92497e7a8f10d115371d4b143dbf75894b3c22c8ab127c657cf691d81a92865a061f5524b5898d4690796243a491d3826d52c6e1be663a1c8506c61f405259d8b6534a62e9ae368fcf02b081f5a14acd2859dd7a46fa74ee919e1e04dde20e29dad62ff69418511db226e99eb571b4132cc0bcf45199e40c9a973501ae3513f6a44fc1582f496fd3197f00ae678adddb7aa6193c9adcb373f6208f14e2d5c3c82e47481edc85e0a6a67f9c68b7a6e04a6e129027c875f2852b3458871c04d9a299e49546479635743ed33b9d1249aeefb81ea69d494a25f89631a49b48a6f5989ac86c71a36fff1b0ccebf232fffcd2f75950b71ecb3301cff561a129908b31b542cbbc559a80fa2c28326f0b8eba369429f8c7184c76bf3747529745721b31b91027c74238ee6e26e45442ac205843833d00f36ca9e985728f9ae01811cdbb69a95338dea8bc6960c400e7c109712545c8963623049718a10e1e399f2e63c320d9000b265f803c472a369b41b4a23b3f7cf5962eff0e991143c1ba4e03bfb13cf63444eba49c2a32dbc21f0d1b75400dd14266e082957d9833d6f1338395daee07f33e645a180c454c1d862bf933d292bd4e560ef40a40bb37ba7354f2991b470aaa5f55c4403b79ffb6ccf7c2bd32e3b61606b32c9f09fa9a816332a38d066486ab9c6c48027d3097e70e91b23536838eee720ccfb3982955d81e48a283670338b079ed883414d39705ceab5aca7f160301fa18a4f46936b56e8e35b7d641c04d7c28bac6cd331110cec5d13b5f7ec425240c88bfc76d01859691942e06d3be086f1d4cb9c3ebfeace89c0a758b2eb8e9312486e903b72e7557b9e78f03526c8bbc1d301cf17fb129ee01cd6380044b35c27744e45a8c8ebf5d25ba04e5b3bef13712f0784ea54cf9e81659f92a3792ab9bbf2e9b8cef9fd0232885b568511650022624a431842d4737a258982141440f1905268ada52c26f3f446f4fcd90084e555e11d9e2652833e2a740be1671999ee7d5ac2574352019861fc2cfb5a3d12ab9d50b5dbac11117f8f68e5a8542cb68fb1f68b4b1b3d6799264f18979ece51bc9c6e6f32fcff6fa2178fc0e68569fcd7a6c13c2937cc214f11eef092b7a5781b7028945605e3c11525716ad6edad9374152153b02b31bc2c35bc4da06228d1a41124ec34c74f83b749e2321fbaf589989a33e921515c5632d5b52b7efa566de123484b29e6e3dc7967ece13b0aa53e0c34b5f92ae766524a872208e9aa6f5533789ea8064bb41d4900f5940278d97a1aaaf3e28c5a57cdece2013b6aa2a180fd0497cb05e0c04e9ab6c8a46627ab82a7987f5856679e43a05d152045562c43859c21b6639b492dfacdd456f5873387a1cc12ebe55db6ef0ae22d6a1bd36c5f3959a70c74af6216f2a4252d103299c4a767c0d08b4f00c4ebf19a3ef99b0948c72ecac72aac5a7b4e333e622d51631ea9cb39f0d1141311ed22134e4b407a753cda799ac168409969a7c1176d9380140a377c54a2f3f377a62f4b6d3bc54060135b1a647c05250508080328a7a471275848fa4e0e752f30bc90dae772a4502d713a31ff221018f4209f4d83cdf345262eb2364564da03f850b791b467ae0ce5e5b7428291f72be7b0158b0daeea77928985a2d0ebbbceec76d38e8273a2fbb3b5d9e78686e0cc6f646cf25bbb5259ca34cb946a84d922256436f98ae59fc98d44d00500021cd1a072d6b0baab17256e0490bac6a66cb9f22ae88032ffee7af189ab17e017e1604101abf6ceaf51e3dd430f735aa7d2d0aea83b6e54eff3bca3d24d3e888f894d662f9e504f4a2f90828df0b489a1b4d2b813491e6a0cef14d8dd50c43e53322e0cebdbb32982ba5f8b1a6bc225ee35239a87f53d7704d0d3875bdbf02a5b2e73700afa2af8d54f4540435b9d30647949df7f50b0ac044ed10778f0b507590d96cd75af1c0b08b59afc2842c05e213134de421b99bedc3b28afc7427bf4ca8f17f7cd7dfb8a7ff4a9ba1d4d66a7c1f37cb8f831eca3c02abc0ca0c984c38e9af16525065ffebeb8797a21abb4c0f5d54f490c96381f341a970212c2553a6bc356eaf4c41e208efed8a2d513ec69b38f10b570970b3b1743314e7bdf0ad9d3ad2afad64600d474618d21c3bc7ede818079b9433961f1d9c5ab923c0975ad5e2447eeb323a59b2f8f3abfd3b91b8503992351466cc19f32e1cf4bff11770d697ae56ed962fbec6b96e28cd8577e16c7f95baf8b64178df93ae42f36b0b088d952555f1d4710f84789266b174ba4bb1e8848447664b2af011f162475c71dbf0e48c74260fc33e470ccbdbf59630162c3c7fc6a2f2519c0b1ca36afbb8fdf242027beaf559c88914e5275a20e8053d2ccda9250d28ea32822341f5f3b4f51a5965a1db3ca5485ad113cd9c5486356d4885c943b91540d21b001250b78626630cc3d35b2b86f9a1cce01ae5ada34cc41784d4da5284ca892cdb6645bf8d881eafae33479dfc983e13cbec226af65d80bfccbb097efe5cab07bf836c4e8ac297cd41733932cf15cf1e8243ab44b21aac70bcd3db52651f45f5eb44d909fc4ea97d97ad2e63934bc5aefc844699a64a756fedc89cbd7cc9df723eac1ae03a711417093653b3dcdb5f976234d308a79357b73827570eafefc42d0d3cccb3a945f4cdf55350f48d56f9b49072173316837d8be12aedc7f3c315002c868da267a011b5d8c6ed1e32cdfe2a9a4ee15080571ddb7e0aca992912a493942aabea14d4097c94885da9cd99c7433fa8381933f619eff0411cdce927ab502e6375962f700d481ab9558ad4fb3a8478a1d2d5b4ce68a2d27ab6fb2d9cc5ea5bfd2e0499ed1dda157b936d51d1e052644ed4efd143ac44e6d9857c97bdefa30fb341d1021b8364f37c3eba5e203ddb6be0504555f08eeebcbec540bb8a8c118c555af0521fcb17d8392cf45ae8b8d30a6cd8b5d0eb33e571a43833869725f637ac327d049f8dd7c6d4417227947a29d7395b11291c1bfb173795e17da162092c853580c3d32890e100be9a2fb3a7c8beec28607b600dead8ddbc6c3dad857a0c5a19fa794ebc41424ff9883d1e25b772643b84f15906e633978a107fa81a0ce4c79d4efc2f7361884ed33b298ca47443ee148de0a14e2db04660609a3eeaa74899663e22aed68fcb2b0a69dd165e44869dbee6a129c7881e56d4562bb1390cb333a8d98cba5115d2912b8ea2d9e7803c0f1a5817826c78a3076875ae3291126254830ad6521fa3f2fe5d98129baab00df4f67a70b5fa0d1996ece436a18a386a5284245ad4b4e991885893669b0d9400e107b4cd9f19a802b6f59106511daeccc711f970003234f876d4cc1ae6eea455e13a3c4252e4b17f9ce8ebc0012aa4624bef848947d86bcbefb4c5e4e8125888d849eb3ed1aa1646c5df76c917ef2b73f450e2858052a51794509ef3d6632c4096f0cf1f2b6c4396ef7c2421dcde0acf8dcff0d7f6b471042deadf6e1aa76ee54817d2d79afc3428c3f16b8f8b3b377720c1616dc5ec65cf92c4fe91a3c84fa446ceb551e71217bcb8134f4203e5807c78613f8d5bc0a2102bc9d5a7c3bf323778dd7004c2793ba0dcae67beb0202764e123c1d7250ba446e16163bab69778e0f1098874dfe46403c4307f307b89111c8266d6a2bc60478c11313635c81fe0a9fd130528e9ada75c5c02b45b1322ac29c3b532ad6dce88924d81ae069cdb0358a22e5ac4550c069434d9385266bdcf11c6b0a26aaaf2fd6d80f1a15c7598e1f4465d1cd0a6fe10dc5f305ea025aa0369570ed2660e597f45293cd31398b8617f1c8d9f37d02af328d8f9679ce068ccf0a75864942f3d211651c8c7ffa38f35398ab65de7e6db93e3c49395896096e0cc6964c2df200a24adcd8562d838e6950e786bcb7e9877f701b826c14f52e285585f483732e3033fc6222ac1c21fd4532ae9a90cf6f5f8063383a7cd6f4d49764d99762688835c9c7ef198a8b720c2ac2044f0cb040ccb22f13777809564d672c718992a8455fc30199d9815f1cd637151bcf7e06b0e3625121601bd633a68a80ec9d43ac8b5ea2e6b5c50a8c8b10441ac63c6031b36dc68b6e4e9cbe3338c9e2b84689f10e8d2dc76f09b8df27bb74da08e7c104d61fc38daa5dc8651e4db80a0e799395cbe89dc9305b5176a02877a1a700dc0910528a4816748ecc30076f1c9012561c5d8b8089a67412c7b400b16e3f3ba94e31d43fcc41bf81db2ee4f82c80387b99c7c9fd510ef214f486c32eb281a7a1c29a8c047e850df91253c6f468a60e03bc1db96d581515ac4f595dce93f2da5faa83d9c93768db209569a4ee5c36713571857b60bc4011d2b0162ea179928629d2401a0cf22f123121dc57f2bdc3d5a0846d5f8dc70dba7850313b065e5c7fa7e3e3885b4b053a237d40fbc111e9b730f40f3bd87b6a46eb94f174548a023036d2c4c77263ddcae7e0dde6567c757dfc2d0acf02ed4fb75ba5a2c46a1be81a41d18f6568fd4ef8078ce0817e9548399090fe80afaf821dccda76672d84d798a108aed87b41659064a64c41e858600002dd2cf1e3f2eff53d0ea5b2002f8a12f9890ceb1256f140236c339d5c47996c35230909be1000d8c3a3c2d8494a8cb9bcef46f78b1645628338247918ec240a31021ec839d7061af92108a2d09d92d130857452765a5985115593b5a3cecbfcb9402b6b360184b1fba1c8c96c6ab454908d1addfdf16719f9f4b8f9a44d873b35edd48e70fc37401a76ac746dc3a45559351480814854dc2ff4451224a54d406890b45ed019bbe0e6e5d98815cd9f50407dd765e6f6b8d1faa81deccad6cb3cf71475619a0e77c9a0f09620fb3ead8437d44086776e3e09c090600ac2f80c9900a7603eb0f626c3a523860538581a57c98db8767c11600288883b0be1f98482f432f2c178720fbd3c47a87608823d9965369e4138f50c80fe96e77ba9004f4633b6abf7b39d1b644f9bf3e3962ba220e10a5324ab1fbfc88c806e3ef1c37040d6990b3180d5eb0896751a619a00d637d9a9ddea159c86eca6ae683daecaacdad448cd0a3e7dfc5c866259052f13b9f36df6f0fb74d645701a503fc1eb6012ee6e79510fb9ca15995f482e5cd2258274f8b27fed564b61b116df546929cd7c5dcb4105464e4c65cf08d0e983836870fd9703bbc2d5d053d95da245a40f723aab01226902ccce5904f31be140d874d29a769a9b95d7ea47e8dc7548ef4cc59ca6594856894c9e02da6ae0aeaa8a072be5d7246017ae23c14ad1c2d5b16ffdea2639c9198f0e1c212656d34bd70d1a9c5305362c7bbf7f32eb0101a63e26ab6516adf163b95d9370bb71d9f49444be1bbc4664a8b2428459db8b3ebf952dcf7ad66d059759cc3524816ec4c2e6626f9e5a7daf66aa0046bbfd0bee4697ef52f9e4bb2243426a39b85812711683093fc704f2b1a927e2eccf44af025b928739788856648e93b6bc9622195d09c34f550d26221cfb28d3059cf614b7e2d07f8748c97171a8b650e00ba9e3b20dda81f836f8b5e4f7779196b155603be566d709b0e8199cdaab8ae5584399d97e8588019f54f6e5777da468dc3be2875b9e1dbd13694628f5ee735e1b26d57d286b040c64c1f64fad3aa4169f4f3ddb52d40977c0ca850ac1d62c43038693c146d22b7ee9949f40799725836dd12c665f7b6947762c7be71acc6d4535daf28767cd57d80c76bd3f00ec2deabdad529a04ed679282692b0941de30219478b756b07ae80202b6e1b2c868a967bfc43f48889f3328639ec7cdd459319f564ff2254e62f1774469da42cb32e8f98ffa1f3d3105bb2ec7c02278bcad0e6f363e167b86fb1ae4ce42ab31f36fe43a10a8759c8a236dbd070409415866cc142d1e851d13176685a47f78a822617c9422d9706d8402a918a755e14e891dc52dba36739a3e61ced7c66a58899058ad06691730ca7807f994dc708d04570e85ea8c733ef13e0e713016ecb10b58375629d7336080906ba1be516d283d31529204810dad4c974ee19f5b7ad55c474fad34b290fe19b41eb1867084e33d1100c86425afda74ab0835b86b57a1f84d7985f064f2cfb8e132dda36a8c7cf66eb174248a39a5d32465794927a29fd5cb6c8b0cec83da4cf2218daba2a1a972833ead4c433c4eb6c54a0644869ccc93567ca79077315a6413afdd898974fb520f6302ada643922c5906646224954c486cb9844101e8bbf44a7102f85179b13e2519232102d55b823aa818574fa2a9c05ace3dfc0259ad2ba40cead4697611458a3621900d74a72c9b4bdb5f017b6d5902a207cac344c0136975066ccdae5f057bccaa4aa6ce9a2b52631be136d346e9d32298b484a4a9b84cd69b96a9a62a6a416a928112d52c68a5d416529837eda38f613186280ee86e2b5a91e9a04df24402cb8125a2cc74677e75e815ef830034c92824d8c12f2821591bd4a203b7e27618a44cccacdb6941e3aea9ba6ceb04825f5c66518ef0ca9c16d82aa5f5d43927cea8d98e3c945617199891d93d214c814db3aa46173ea4bc901f19ce0416116510018c8f83efbe0e224ad730e2488db8cbbcd1754e48d8169563c13f858836691b216fc92d65d2c5c0ff418d32e162c75f223efd7a65b26d50589fd949cb0afcd4d96172c129a99c7d4b4d640513712e69698ce4562432cb090ac8acc87afb28dc5c585f12dda6bc1845835f814861a85fe1eaaec415acb0d4e418111127edd024433924021885cec27e00e853a67ea4969308b4d8e524d6df1c41dd36cb0ebc81d3601d985215080f067ae96d05f2c316b81f9c3cc821334a31f5e95b81e563dcf3006066f4fc185f6101dfc7794016c48c402ac30c5ae8d18b96bac62f720920e2d4738b3b9a782cf37f1e28e4d1800a341aae13e86f1e14e842b7bc5de28085d569734874820660d1dec0269b0b4bb0804d6269e80e8d72ce53adea446e843967c789cc21810bd88e2c9acb2dc37b4096ac54f106048e41664f765f66b912147396fcdbd9942167eb2a2faab9888df28b8a2cf94eb302c05c3c3456fa8b79f3000c6f684f1569ec5c5fb9f47ad24e116d247181479ec537f24e0d45ca420f0f014de9a040769c0a2d2d7cf2382aa5d5aa1716900ccc117921498a412d85418e8fb2885890e20202b2d144154339878f32573c78e8d48a07e28748a585595d857cbb8adaa3750b8f24d88b9766350acee185ce7fa5d19af07e93f42147f3e483905387fb1b2810e80ff9461c99d3952c1b25aaf9bfbd9f963498da742d9a719532afb87a242bb61a9c0abaf693dec6f37894f8af2f526a0347bc2f10e8ed2b4f03a68ec248911508155284da31eb0c873c3b85ea1f3f9e7a9b63ee13802e41712998bab31cf87d34e77a1d58fe85cc343c3069a7afcd3461fa18f831e51d7fcbf9d4c31686a9094b768ff81cb25010de4b6a5584c8f2049ce463bd12ffb526862122527d51efc9aab78824348a5387d33a615467b412865f2d50b415548294fb860de9c20c9f2b8c94dcb07316d9189b0c9423952733e82c13f8ca73309cf1dc076c629b7099b34ddbca2ad8d942e23bdaa58128ced2affb3cb0af0b7d498fd4dc414a16b63d5403c7e2c1178397c4289895b59d10c988af3a0154d9a4b3a444dfbe342efca4364ab089f563addc0d066bef771368ecb342321f4d9022e7dc4980b3950b2a4d001c33f3f3f3f3f3f3f3f1fcbb66dc1b606425b48494a2553053e2534882d534a2925d9de2a141405000000000000db0821a4b50ebaeb0b3b0ba30b8dcee10844f0910746d79f586327fa74691f78e004cf4ae63953edf2fdb803a393a67b3b296d3cfdc191c2d06107be8275bc8a57a56df71b3eeac056124f8aa64b5ea25bd93d7cd08191a1c67472f7bf98f6213ee6c0496a4c3479fa16dff227074ee9f0cb9562da907f89039f74ce37a1c4e8267e0a0776843a6dbd81d1ef9a576f3a664c133770ea4e3c53b9993f734a830e1f6de057c3f3850af7d8c0e75c495bfc14acc4c71ad8f4e5f9f364d50e1ed3c3871af84c4b5a169476a650c2c3471ad894b3c97427897d416f12f181063ee4982869a448ddb2d0e0c3c7193829ba7f8e15e3c5dea0728ff830031f6f3bcd4bd4695257233ecac09ae80ada59269df5460636c9ed947941c6cca4a4a6f03106bec4e05fb2b559b6139a317c888173ed0b322ce6d2da6a18f8b3eddfdfd251f704c1c0c9274f66cb1adcba4fbec08595cc29d8f88d8bde0bac97ea53db7d29b9ab97a30b9cb6a80b993babe8e87381f3db6c651d354c556a0b9c722de94397bcd9d44ed402bbb6418a127b6c43edbcc24716f8924da76cef8b1b9e62814b72febf9cf3e7a4a5b6c3c71518dfbbb2ca149e836f56e0cbbbb7c2db24f5a62ab06a329750254b501b2c6bf8a002ff6759ef92693b71548cb7600a5cd492245363a6cb7329b0a6c5732949b4f8163451e0bf3a589af69126e242811ba13ff9758ee942554fe04fce8dee9621cadbc28713d893344535fea70a1f4de054bab6ed6a360b1f8f25a14bd6345171c2c712d8347effdb7feae727287c28819354cc9b2d6990d9a42f09ec78050f6ab43306ed3e90c08789b1ed937c1c815b2d49529572c9d16cf26104ae4a52f14c32d57379be08e3068d625ff8280267fdd13a6b47ff5b53021e90a1830f2270426878a7a0da6da3dbc710381916945613477f73d28710f85ce7a7303240848f20b06515acef0415e5316f75820f20706b8290255f5968ceebe3076ca533b9f35ecc26d3fff001bb25b775ff8f3e7ac0691dd366fa2b0fb87e3571d35bd4120fee80efcd26aabebe433fe71f3ae073e7d74fb2d585bcadca8b8f1c70173d649fb76aa6cd7de080eb9c04abafd34b62a87cdc80d18fa52b287da504a1fcb0015f9b337e09bd68dfa183c60abc08e36425e61eb5e0e4d8f6611d7d9330495a706e32a5abced57881c1db30b330977ddd7d6993e700c32ce0210b3e69f9982498249874518dad1d3662c1d568e6fe561e16fcd99d78fbe7e8c9dd5770f9c67f6c4708d1b982f354826bc7a4723615d71282472b387947b8a69c15c253c50a6edd244b5f52e67e4fad8213a14d76e65c4b829faae0aee4f57eda9d7f9d6a6c81f105ba1c1b381378a482353f29ad55dccd24731ea8e0b3854e2f2a34bf543b052743c71cc345b87d61e8a071898729181fb916dd73523af659b6c37578c0a314dc6ee87965ceb1a4acf88e1e7890825319d447695afd50268f51f06329b3e53799b517051b9a395addecb483634709056b3ac5e41d33aa5dcad7d8ca91c36980d15f6ce2010a2e678b1e75bcc5d2a41ed871238c1a1f403672f80d9fc027d87c2e326dbdf7fb05c7dfb09132ba98808c0714cdcccccccc4444444444bcbbbbbbbb3333333333abaaaaaaaac4ac260ec0141e9ee0e386924dae0bbae38e1c8c0f642738b94b8963729a499a638d2d2b4e70e28d09a5616295d4688d2dd74df03928ed24c6f8a1b9b58726f8ed387acf2bfe891253632b05346ed8a8b1c3860b2e137c0735222b3b674f63a2030d137c5d5051d9b5b3635cf0b804fbe769928a293573665fd8682f90e9d0828725b8abdd0aca2d0733d3568231d3fc7f9ef4ac0fe3944a9d830b1932b8500f4ab02eaa2af483661d194a82c72418d5747a2a8e92e460558d2d0f49b05b82b2d67693d5087844828fe659a295cc77c1aa1b1b9831e3060e2c78408213799bef339a6cba73c375207b3c821d1d2154ede7ac5fa51bbee305ace7e108ae246599d53ce349313aca011e8de0929d124346d1d7d8bac262047fd9c94a64d9077bb5c6d68c19c90c3c16c1c949f6136c9449d253abb155b20b0f45b0a726d888494928a9991a5ba8018f44709762256d72ba984a518d2de385175d63870d11d0400f44b0f5594c89da2c9ec9c1e310bc6a564c9e2ba54f72acccb0031e86e053452fb6b5e513cfb114f02804bbfa39355a4c679d245d283c08c1f9fa7efa4ca26ea898e382c68c195c7031634649013cc163107c5fe95839a5a95f5682e04beaa4a3216dcb14dcb0e12df00287311e81e0bec41cfdd625c9692935b6ae5c0238ba100120d8ab2b5326a894aea78ef6a214033cfec0d9fa7532b9ee2ce9cc9d1f18932415266a56fd7612038f3eb03148db2edfd04ecbdec0830f6c4ed2e79d98cc72e5ebb1072e73d2f1da2b543ce93cf4c065794e2797d0b20c257960c52e956c7e92f89faf071ed88e599ffb25a5b649e271074ecacefba7949e8d0ccd98a1638783c1c30e6cc6283a28adcae95327ebc046df0e26a7acd726571578d081f520434b99f66082d6bd002347183a6820073ce6c06e4e1763872e537265450e6c87793cb9b2443113e41107f6cff54a492925e99ad10506de233063460e7f4f4965c2030e6c124bec159d29c92432bac0401a083cdec0e75d3f192c45cf6218c87364b981d5cab163a6b724eba7dac0ab9ed09d9a57a4e50c1b38e549e86ad096e356d20dbf0a78ac81fba04a4966a1d469550df050031b93cab1448b4e3963d092f44803df5d9db962d09d6f678dd51c3bc0f04003773af98f697af493598f33b027a9ad899697977f1e666075f7af723b6560949449f60ff692815342d9e6202f8e7ed5699c89404617189071e53106c692e8fd317bb0cd39f710031bb4f869134b9f345d26133cc2c0e9f2ac71fd045d933be6071e60e04d0c328fa8f5bcd3e81738b9a184e68a7b4973a45c7878813dbd9704ad9e4dc999336346173825d236ebafb276656b6c798e5205021e5ce024cf2193ffb961e83861e8581daa436d0bec6693d24c9e92a6ddaeb1650290030f2d3056972b6bd0db5fe2bba372780b9ae091054edacc25756b700b964dc0030b7cd2db6672cc5b4a1c67ccd8815a06173276e4f01a68878c2e3040231185c71518a54a9fff4931b9dde561052edae7182c6dca3a757a54814b8270ebd349cede830a5c9e1c3fe851d7630afc6b5af4202d58caab794881534f29c8ef4b531fd419333e470b3e470bce230a8c7fc96ff92cc98e1b8d3a04c6609063c70d4f1a1e50e0d63d9652a234e5a07722038f27f0ed1ffdd2c81a1319d7e1e1043e8fa8990a2665b494770f34818d15f34bf3955da9556e0b1e4c60b38752f2da523dd349f21b2ed8c02e818bbb39ea5be3b72596e50987064a3dc04309fc77ed5b2cf5993024e001195e782481f3bfceab27279d4b57e82140de82047920a1143b895d71dbbe8163c795271c1a404f386ea0f138026f298d3a19aa448f414863ad051e46e03cc524ae6a924451314911f84c62a73852e4497a2b2bf02002bf974dc6249d8a6ad2fa0e1840603d86c0269d4498320f790881ad1cca7733ff444965eef00802e71e439eaa4ae5619a0710f8d7eb28aac40e8cfe62870d08a8dbc8b123f1f801fb7da24f939c4d4ac1e2e1036e543765cf6eff8de9019b356d148dfd27cd44bdd091e30156e8060c7420023c78c0bb95dfe6eb33a5c6e18566c06307dc8feae74e99aafa4e1a6084416305387078613a20830b191890d1050664245f78e8801b5393e458d09126f546784302561e39608489b949877d92abb62b64c38b0f6860c68c1933aa3487070e382b61e974e692f53909251c1a484a29c0e3069c2463ea90513f95144d8d751b3976d0004387870dd8cb6157222c892965cb468e2ef0a4d5400968148000b560e4bf861ad1517b01c617be2e20002db84a9e82261d44e6bcd52cd868b7a2363fdfdee6b2e03fa635ad0b6eab27b1e0bfc4be7cf9d3a8936b1ab0e094550c93b71a02bc82159d21d4da6a5cc125dff26f53c972e88f0ebc56b09fbf32059943e64d61e017a8a1a329c0c52a2008c00aeeb2a5aca27e2559d6c36041dac8d1450a6e145b05777fb207539537538cd7d0d114a8a1a36b7021430217804004609003c74934609003c717fe852a1895b152b66cc994e0a754b0d943275ddb1c4fcda182534b5516f46ad24a5103014ec1c74a15938850569a5308600a4654de24f9bfc7bdce4ac1de49679268450a5e4c3439073f7f9336aaa3e094ac5efa2c73060288824bf27574a8b8516fb71a5b0178a6cd4912370843d6c0eae8bbca54fd18be87a881f3d2ddb234e2ea694c03ab255ec9aebbfc178342d0c06a3ab56d329afcced13370728ddc934bff870cf60b42ccc0e5d85630415fbb83959c1942cac07b12a11945f9d6889a0c5c07ff0fa53dd7a4260a2163e0bca29be0b1ee3f96548818f84f2afa89792a9ab4bcc656ad20240c6c8f92ec2e9b944b881f0206de73bfb65226c9f42505c95370c346da17183377f5efbf3f957e8817f84ef95209d6daf0c2461867cd8b902e307642e524ed8fd8dbc80546ad29c124f5d58c267323640b9c498b157b4c6953add1021b2b7b2c6152dc4c9faab128240b5c3229d6766aed2d41d740173842b0c0667cf193928bbde6ca15b8cd7942b5c656d110865881757bf7b198c14e4dab0297fa544c7e6aaf2b5f41ef402ab097d1244bb13c546a8ec37011320556533211a1e3c5b86f41428814d814a5fe326d4dcc921305feac93d508251502055e7533a7979d12a6926a6cdd6aa004346c843c810f0b5adde7efc14c12198438813551fd39b606b31c643aaeb2439ac0a7b191b5a29398d3c9d4d84aa57810c204ae6ec34e4b67743764097ccaa74f7eee99a4aa33811025b0d92779102594655a0dba312124096c78dd874c299f20c3d5a251a2084102aff7d7a2a4d06c32b532849023b0a76d152ce3567f072dc408dc8beba6713b2da6de22b0ddea71db4676fa1286108193d33ce7c83239ef9f589a154286c0a9c90b227b733529e92e2e44086cca0ef155b14b52fc840481f3147553abaab7df932004089c586b6d3a5fa94cf2d742c80fb85c7293d434a549346d213ee0e26bc9b9c163fabb6784901eb09f4c8fe8adbb3a291ac203f6c4d1b93e6985b45b4376c09d5ea59c19b5438f4f85101df06aeed6295a76707d4372c0953631a5352184923d592138e042dfe99dd87f9bc52284901b707656e95337748e895e13426cc0f525514157ea8d9d2a4200a905aba173de3b15e2a904a105efa75ecfd426492a5b60235d04126395ecb0718c150d1d581a0099051fd54ae55ded881e9d2c18992fd789ea68e5ae0189056b23ea5fdb2b4d3e91192c3849ea6e922599e8925266afe0fb639d12d7bd3c7f1cc415bcbb284bb14a1026d309d28aa41c2d4a678b19082bb84b61317f106d92524a20abe04d88570c0b6d723e1144155c3e49d25c39345f281d9054f029f809d2cb564c2629082af8b8be9bc5d2db9af47200720a56531042539f9c93b43177a6e06ec44a7b69fd5365ba52f07ebb655d4944e42901210567dafa5397f66c4b519051b0a1b671cc6c7f028828183599ae5395989224e9808482ad8f7a52e58a3156b44140c16b4aade9730c99e43c7d820bdd26675dfe5608254fb0e6c9b4c9c9f74e304a66137443e8a86c2a342a0e209c604b99c7ae6c727eb51064139c9b5e937292a2c578d2209a603b9deca263486d137c904c7052c5d2e5bc26a893e298e04b49db49dd4a3493722ec1e69c9430556a4d973c5a824fea9b695944e9497d005209c62421eaad047dba6d024209f64dab89799350d2e6249049b0a25ed3785a7bcf251806104970eba573eabc22c1e658c942939fb2561b129ca08492d3833c0d3a63401ec19f28f78feb2657b909e20836e62949beb13e79f683348253faa7c1fbb45d7d1223b8a424a59464a74f96de16c19e164b3d661acf6366042902104530423fa44813b4e6e7072411dc755f95b85a9ba4772088603d29419976462b793ac821f8dcfcd7a53e97e835410cc158652ce1278ed02654cb0152082ef44a5ab3db3095b4460021041b42e67cf12d08216b1d04173d87b4d89fc3648b0a82134c34f7b42b3922d225800482515bf28daba81c53a84100c10571bdb1a0d7e4d60fc81f5813939c63292dbf6c27103ff0fb2726c6f22ba9e424903ef0961a4deda3c7cd4a1203081f580db6753a28b94383670fec683a93d3a8a0e3efa6072e4969c2d54e54a8dd79e0d73494b49499af19eb01081e6c4bf93f56bf83dc81cf2c4aedc9a7eb76723b701e43e7bccc2ab1540aa40eac95b855922d2a6500a103232f9fd04ff7b7963b7360fc83f61d536953d30e220776c7adca2c084f96199038f067e126097e7afffa82c0818f592d66c1e46cc24b206fe0fc3d09d636a2373c0fe206d6726af3d09f03d206fe93d2d9ee7d04c206467b92ba83529631ef0eb2067e549fa0d4d5e78a9940d4c06bad987cff761655049206c6368569e71a65a9251034b09e4ad2a6d1be34451be40c7c69cd5cb174cb64e541ccc0b77bd98a080da40c5ccc186e79796f97191032b062b27753ac1434d7053206c636e756e99a206260ddcbc6d653f20d250f12062e65b013f4a5808081f18a9d1d6292bcbf22c8171821d2a489255b1ae926205e60444f47484fbd9be40fa40b9c5417355e327592583e08173839c5b8eb9f2b732c71902d705f2ae83b3167fdef18102df023fccfb4778fac1202c9022754788af9d5faa4a403c102ff655e320559feb93d2057e0d69448eb4ad12ac904b1027f92ca9dcbb24e8e390b5205365f851e4df993492907a1022b6eed21eb4fda6c15c814588d1b74d2a96a494a2e8814d892599434d1b5e3a6048902573ac8764dc14c73080205c6f3a40e1aef74d097833c810bbd297b5bcaf74989823881cd22a694a8379e4acc9afd024813f873d571337163ee8d099c103298ec24ff82f6ec122ef7bc4b429418102530f6a5ab64d2a99485079204b6c4e46241c5478fe72048603563c6b895e4b43311c811f8cd39bf9320db739d108811b898a497b8313d4faa0f5204fef33265979c0242044658fa9aec23646b5852ea7205902170d163c9d0fcabcd260e2204eef48856fcbbc6ce3825800481b54fdeae65d24060a3c89482850c2fe5c11fb0276e66cb1ccdec2fe903564de70ba53da8fa4a6103480ff832716da345936f9f048407bc26514c4a62c58d1ba21d301a94a57aaae9533bea808be6a66d994597c620176700c9011f544a9642c4fb52c959101c70da6326a6cd3a9af208e406dc9694f3b8799d60270b6203aefd34267559da2ade32f8a805234a10e9a3f4f5b8c78c166c4ce7af16840e2ae71fb3e0cb77838c7b425334593359307a82e897d669cf5f2d166c2a4188972c76d2e4202c781d9dce3b9495247ae7081faf60c33359b0afb0e4a5c415aca6d226fee6a9c656f264acb482d3dad9a72ee6574997159c54e25ddba9a89d4475155cdef4498a625256bd912af878723c2b35799398742a18d11b119a726dd589b1c1072a180f2528d1abb9e4bee829d8cd1443e80a953b53304a67362173a5d332d15d29b8926d5a941437a8e7e48c19f7410afef24e3c6976a3e0d2dec9eba3df53852b0aae4d2aeff60c77d53e3f42c18f3e9354e82d0a1fa060cf3bc8ad94c4ed4fd19ef0f109ee7ee32779738b14d33f3cc17a9e246e54fdfed47827d87c3e2686dec9a3ece5049f97f637985fc85653f0b109be343c76dc98e4694c6a82d78c19f2d49deadea44c70a759a16a19330926731f98e03f9a0af24e560abee9e4e3126c55096a3cdc37d7afe6c3126c9ebdc6246f8d4ab93300f8e0a3128cda67d666d2d9d9194a7022afe48975aa94a7a04970414b84d2ba174970e926876793a2f4581d094e0c256576b88a8f36f10312dc9fe8901b43c96b2aee81085040461718f8780467975ccf3b8f52f94a4770954e6bbccf39faa5d408ae37e8d86b991ad25746f027a3065daedfa7ea5f04a39b3f47d80837f13741f8500427ebe907a5d76bdff21f89e093a4bdf29ba67ad613307c20824f263b3fe84a82a82466061f876035b5a45c929834049be4ee0b96ba2ba89f588e8f42f0a3b96282ee1c4bce694270c2b22731e4497e92ee0c821d9d97a4b8c91204d79759212c8752a28e3e02c15eb4586f929794fe621f80604fa969922bb3cdcf22868f3fb0f7bb2926334fd228f7c30f9cf45ea6534ce54d42eb03a3679b466fea09bad37ce057b475082bb3eaeff3f0b107365f4a95194ff2e825f7830f3d303a676e34491d59e034ea9a5ed96ad23167c2081678eb4c72b33689662ea171c3bd28a3c0c815d858b6a284874ce9ab336205ae944c417f28ef8a7b5f1646aac0c50bfffebcf42626b19483112a7039d5ec4b92743c491c4561640afcc76c2b5a2c68496dd0a85a058c4881f33f13eff247cf396876e0f0e20333668c4481fd3f9992cc2def2479471881021f4398b292db3ecf46372a50e65fd8d8813a76dce81da68112d0e8c0c813b8644a459da76c4267939f3e67c4099c32d78e9ec44ab469780e3068b4292ea030d20446a9182dc95e2ae764a6328c3081ab582e3adea97c7de112785b913189f294db74a6047eddfde4ce1d1f4902a3ea92748d23bcbbf448e053ecd0187a97fca37704c6af94d66e5bff3b15b31123f06756f2d334d569499b8d148193a477a592493d5e49623642042e8a65bbffeb85109ed9c810b83241bda37dd28810d82093f29ce44682c06d926fd953c68b07647021a3744006073020c30b30beb0a145851120bc193f25f3ec6f02467ec09a96a9682a949b94f9111ff0499552db1e1644e97a708dce99fe3f4d4678c0684dba6f7145efc9cc0ef8ffab35cbed5d4dc9111d70b2f2df67878a99e33f9203b6cdc41c3589a3846b3e8203b6f289655e9f3bdd5f6ec029efd8495bac4bfda4111b302e3228b52dbd5d79ad05279dda51c124c1db829616ec778c3925d939665dd32c780b4a94249ec9d1f28964c1e94e25c913a54d9d9c24049158706a26c89cc4d3ea3e4adc20020b366c3fe6242919755b1779057f1e739257b307197a177105239e2c053f17a159b95670399fbaa924e9ca9a31ace0aa634952cc1f2aa8a462384260b60af63a2df5070f5aebb92a1879c12bba25994907110122a9e04453eab65a524c5ab11a5b5ee88e1b364090021b10d85d80082af83f9946ab2965a5367d0a474365cc41bf6e0a63d075d2c9418958e03aac8c0e1d38c0b841030c1dfb00915270abb9d2e4a47237291952b05e4a926ba546fda3e0a3aaf8e549c9b3884c4414bc89414bb60d9d164d0f05276f4cd371ac4a6f06147cec4e27d8096d7f79ff04df7d6d172b2f837bef097fcfc5d3dbb49d60f3b64ee54eb69f640a27f8dc67222c6aec937fb309367657109d43c9346e8968822dd995635a89f34024139c2551547437ad389e0383304e950e114c304ac65cb982f094626897e0bb723a2966ed7a96204bb077fab1724c2957a8d10b2295605dad2d475357955d94e0436da63a419320e37593e08436b1e26fa693992b4970e6567ad29f88dad691e0c41dcdab2994f4316d20c19f0c4afa95942b8eed568f6083ffe8346eba9fd28670786101114730aa63671daf522aa5228de08452edd59131956a160021883082ffdb582feaf75412fd4570624934699274667551041fdcc5f54d4a892422c9436b92a4972022386169a48775b6c6d60a74f40e1a45450ec1277d16a49572edb7918821f858c1ba0465c104ad9e4821f81c9e49b79e3163c68c19332cc70e302e007d1021045ffe61b6394c859a69106c8a274f4ac54c4a6cacb195dc101104dbb9b4d6d4da8d12992f2e4502c1859b594aff5f7b2602820fd17e5d1e7344fec0e80a255b2c4b7b7937113ff02777ddb665c907ce90b7a00a05227d6064aa79501e9354a6e303d72eda7a474577e8f019227be0d6a44a4aa724738432f5c056e570cd373efa494a1e18ed29dc6ac5deea4e2278604cd4983cf6df49314f022277e063e886cc9f992144c60e9c9061639a63a8e84a8bd481fb1dfd983c290b2ac845e8c0650efd9f46ded76d09132273e04dae5cf7627d394329072e3c597b5f92fe42261189037b7a92aa4ca9749efae0c0976c17615ded1bb8f3f5984b08792525ff460544dcc06a8ef9796bb00d9ca083090fde962688b081d179e2174b8a5ae8510ad6c0696e4e62e5abb07a7705226a602fa81835694f5f9b89a48157d11a2c8729713df52268e0840951a24d1693f47244cec007bdcd6b51bc1d889881b36c32bc564c7beadc8d0de840a40cb7b706b59a31546acb0422646073ae5017844c494c25141903d7f153ee1ead8841440c6c9049ded41bcd7a33b981c30b14062e488f49d23415113030d626ad680b152ffde80b5c7bcc3993bc1acf93b48817383942070d99bbd39325d205f66d93943175fc4efa225ce0949f49e2094a42640bdcadadd96776cb9f440bac962625fe685f240b6cea606a3fbefdc7d86281add0e5e935bd5e67cc1538d1374dba059d73fe242256e034544e1d258b55e02eff7258342dbf0a15b8ab116afd938752fba7c0494f627a4d8ff6779f14f8152d7da75496509e178902bfe9aed9943414180be939987c9b4cac7f027f821e0b955a9e42893a81f71fa5e43c3d7ab9729110690227e9942cfb459a9b740e06c38d20c2046e2bdefa89ee7a495c02274ae5d3b95371105102ab3957f867708bbe9504882481f1ecf92aaf8790c0577ac96e3a05dfa4d923f0f1545d94e9746ea3891881ab1226d355a7cc5a2a022b768225e9447e951a79181e46074a81f14518f701112270eab3d9999d14bfe47c087cb6563549fe10d59d881038f112d7b276563c516b6cd138eba29c0b4482c05ad0bbebd6767dd25b80c05b4abff9dd627ec0ee2753563af24c4ecd077ca859981c6c349ad5223de0477e120b255e72eb9b079cd8214aca41acf49e3876d0480e46183872a4c0ec0b223b60ab3d9b742533a8285a111d70ea82cce9724c911cb02eba259eca5504076c52214c87e51c3dcf44e4065cf00a4f9a2ec4c4924403344ac4065c50594b49da64599d59b5e0e2e5787e4ed26a0c1a5a7095f25ed72ad96f36cd823bdd4c31495452c932b2e0ce6f37849041a9b42a167ca724e7d1793998e91c2cf8cda86dde39f50aae04e1a35d22a36b8b5cc1a6cd93326bf41293c55bc165662fb71cd4892e26ace04be5b8f665929c2ca956c16f7fc88cbb2721aae0939c52704f96cd4ae808084905a7641b6d265f2abbf62d04159c1cede4fd20333b05bf59a25547df6edb68aca03dc7c10a3105e3267f7d0efad101467b0d53424ac189417ada5495b43b57d090828f5a5d6932ea08951c3876d83856551b90c1850ccbb1811d36ce8c193a4a0718380e0081081905a7bc44b1584ac995044244c1081d3b593e31640e35148cf8dbc96b5e5935594240c1a8cff94af4d8269fd8d02f423ec1e924c5a01b3a595896e000e38b0a2417e209366d642c13935452592aa413ec9e0eb24b8f9a98e9ab513e08e1049f332741fe7afa1a5d7283904df01b326d8ceb2928995417461817a2094e93ac0e32291bbd67828fff25e6f7ee9c4a1d078cce8174d0d8e13aea30c1d79ffc529d523e3d992d845c82713d4b7207ed362b395222c4129c6fc892bbc6b47bcc1a05cb105209f7643cdd1b7ba504d7250669974f921d4f7823089904571654122aac24092e074be26e09ad26191209b6e44923543bab5d8304a7ec3decf4d5e61b132fbce8b39047b02bdefd416dc67fb110e2083ec52de5eba714b4e41ac1fb78b624e3a6d1f91623b85ce155c9a40ffa2f93869045b0fadef6e9b2e296e4d801c6d52044115c3a1d3fc90c4f2278d379fbde3e8392564cee397e71f1108208aea3f86de6fcedaacae042466a1c5ec0a03920a30b0cc8f800081035e410ac95a929ad7c31dbe79ee34b8821f84fd2ff3f29e5ef9a2904272839c54bdf63183820901082dff7114ace7a41c5d4d4d81dfe811dae2364109ca4e47b129ec55bd35a632b69c9e862023770d8d091642144108cdcd0ab6e4af6b38c699d2024107cd226c9ff26650f1d5f40f09992ca9f324f897ba5903fb0f79e732d6e83c6ca22c40fbc9a88906e2973db86fac049f2f2e4377925f7753492076008217ce0bf55d77facac935f7be0ea64e8c5248dd6beb81ed8ca5d62ab984e481ed833dd49ceddfd55f27b80103cf0a295fdd43d446b2d373c05090b5cc7a51b9d033550021a0608b9039b3aa2af4aaeec4a991d3861235dcd644e265836a40edcf6a9f1f134d19e736aec0242e8c08f4c9517ddb3aa2e3b3ad148681132074e2631d6e7dbe89f240103478e1d373c0b04217260c5cfcc4e575d7d65438785c481afa44997059587c0817135d1494e4942dec07d901de4e8896a27ee216e60f307f5516b4f4e367a1b78f1562da56971e4496203db39145360d3049d6e7fe4c7cbbb14d8246f650c32776ab4ae0f5b44815dabcaa75492448bbe50e02e699998fbf33ab7f5c3164fe0c4b49cd378eea6d37c0bb18513f86cb2880ed31a628b2670ba26e969af249a87568db00513f8cff1e4c64ff26ee479842d96c0c818edd449aac3a4786fa1043696f86b9524e675bcb748022747f5698c1b7a19d343d802099c586e9fca63660dc263e4b0c511d8d3eca79292227ccb320217164bb492bbd4af74c91cb6280223a6f249525afecfb62c11785125c51b132bc7b43304465b3229bf338b6606e3b08510b80df23ebb8a12c43e8b6ad822085c504f9ab13707042e8f08333fc93ca6ded6b0c50ff898395f7849abee2cfe610b1f707f3a57e83599bc2cd603aeec3e6765cd1e4b5e7580d882077c6be924f80893cb4ca816b1c50e38d5e26e62d6897943c66ca1032eba656df4a8a92d72c0b8970cf97fc2019774a6d9252553ec24c9c31637e05c94d8b5a5dfc4949585c3163660a4464b4aecf42765df6ac1a8be961c933689430c5af0319430257e4153854a67c19b5dc59c041d2ab4081559f059d4effe831c33497f88110bd6bc32fbae67e41003165cb6d560ffbfd104ddce21c62b38ebcc9c2429590e26c96c2162b882319364e6145bef24b1c410315ac18ecc57e2c760d2f7d9a68718ac6054ca669a7c2fffd7b40a4efaa66ac998737b88a10abe3c4b8c667a49deb4993183061d62a482cb30793e42094a5019d541c4400597e4a524b3aadc53f0296a9518c54778ee874288610a2e28254f34287d65b22d051f474bb6fe280b26f7328418a4e03c7385d95f0ead76828418a3e0c7a3075d976a9d9715056ba27abab455ba54ea9424c4080527da85f6f3b4271662808251692cf5a849e525f39fe092943c6f66a9df8ab966218627b8a0b256e3e70c427fd7093e9bf04ed1cce604afab293fa54f6d824b2dd252d4a0793ab99ae0649f7c9332fb67af2499603397ec214d664d65594c70d29df6d839eabfc7cc253899e41425c9e2b1045bea312561e9a904ab1b83be4cd2465fac94127c6cd512e3a68b08bd4d82d315ee6f7267d125a548820fd6495487c893566422c1e9cd9a66213d4870da6e2a3b43f30876f304f5e9638e88751cc1ddc6dcce964d95fc7723f8d77437d2366d5aaf8c605cb77b7cc562c9a32e82d5689ed55ff406933645309642a96ca3a43c425689603ce9e7fd0b1d84ec1822b8d2e41af4072145457308f66469af50698469480f0dc197580c6da1aa4d9b2c13621482bd7ca1253da5c89c3342706b5d82c5efb73421c62058dd60da74e976da540a82d35ef53bb6c94070fa549a97decbb04e4936c40004df63799954e9119eba3f70428849fe5f39e6585b1b62f881735bb12ba1929439e37de03296bc5ea3ff652a1f58d1b016f51d4f674eee813b7f8fa6fcec522a193d70fac1a4b2984e348fb13c70a362d0e08113799a4a4b2a4950a68321c61d386db173bd8f6707f6d34493f288a6eb3fc510a30eacc831254b9eb9c7934c3ab029ef828e1633f5353607368a7ea59c3669b60a6e1562c881f36c71bcf289a6a33671e083953e55925a4f1a647060347efaa44caca43aff0646b85572f34eb566273770824aef53624cf1cca936f025ad754ee949105531fa84186c6093124c99d826091f8d5903a3564b7b727dcf93636a60b5ccbecddc536a12a5811bcdfdb5269e986e3368e0b4592e491093a63b3d32c43803f71d3c86d624b5eb5ece0c6c66ff8ca1d9c460ea2a0317cf04b13c42979c479864146290811f25e8b4b4e0c924d1354a883106de4b9f4c31de7f974e1203a33cada8a5b3d232d125c408031b2fd3e6d0dfa91362808137d9632e257ddeaa9c4a22c4f802fb21349e5decf3f15811627881f114f72c8358dab6246a84185de0db2fe5a0cdd3ea24192e7029b306f59f24a562564788b105fe6209da048d61c9e2470b8cdfe95c92f0dd174be2861859e04cd649e9b3aee3a6c71231b0c0dde5ccce1494da57a56a0c31aec047dd3f0d55fab34a97e38b2ff08b2f0e0e31acc0e88d973b7ffe50a53655e0372be8ffa67c21c5840adc9e24a87eaece14d8ba34554bd9848f47d510430a5cce9b26a975780cba87418c28b09d53cb62c7ff24e9090a8cf0befc62aae79ee24fe062a52456b5c61dd7248daa440c277052eca4049d4b970e4d4283184d604bc6606352b794abca0446c9d1bc595967aee925f0a5b1322679b2c8d1eb112246b9a3c450524e6d8c24702226bb954e71bbed83420c24303a736495bc279fe57b04cebfa4dbc624c84ce749a810c3089cd295634edff00e4aa7085c89f4a0844c4a35ab85089c5d4e3329497286c07959e79c4dc874492b04fe73bd067f4b0d425882c09dce6c31d5de66ee381058b73ed1774d2aa54ff6077c5dfab53c328d92bbfa80cb0dc2c4c27fab37c4e8017b5baf2a96b2e358464b183178c0969e1c7aa6b6bd5bc6d8012726afd419639745fd74c0db474b77693d093e1a40c4c801bf3eb25294a6d7984d38e03c49a9a62e9398ed2737e0929c9ef2e653d9de7362d80037d59a0b23b5e05c3f586a06a54d76148c115a704a5c3c9e49df66ea2c5d1899056ffaa26b769eca417e881159b07ff95f3499e82daa0ec4482c58d7b81756253b9ee48105b76923ab5a372b4bbc6e1123afe062992064501d74969faee04fe992a2741ef1b73c69051fb6a1a3944ae2fe28fd6084159c7532d3493f29f525368cac82db5b935b34b3f472aea882bbe4669ed34c525abd54b0266d9e9f66aa744907155c7b1e9316f4ef2a37740a4e94ead74e29e8949a02868d2e6e38181b983143071836762460d8d8610a2ec78c253d9f880c25c94ac12731a5e4cff6586e168d1a2105276fd4992ea5e42035350ade2afba9cb9952faef44c125eda2ff73b69e983214dc6d0521ec4b52c15240c18e4553c1db7457924974c461e4136c6e2b8f9f6952cad73cc1b557b7e6d4563f49a613fcc55e939ddfddc4d872825553d1314df946fde026d8f4a949c66825ea32090c34c1afe71da593800c2e66cc30c34826f8ec3f3185062fddf46282d113f24285aa2fc1e7d1dfd3d48f9bf1b20427de6927515335c4de4a7016bdb47ed4bf28958412fc5b9e3a359a31774e27c146df1d5d258fa853b6241853f935e88c2a3a8aa8e3059d01195cfc6124128cce3eb937afc91d5f4cf986d4dc5c31f80836bd8999289ef729551b5fe4700ecc98516a09238e60354dd59790d65e4a4e2318eff426beaf6104e79ed3e4887f7cb7ce8c457049e4c7ef6c42c957952258514a146dfab92e5d4a2218957414db3f3944b015af83ca943e876093d2a7436bfe7bcd49de0243f07aa3d3a98ca1f3a95821f824a8b5fc4127594dbb846033dcc22d637bf0dd07c1c8d896a2998a82604495ec2bca3bfb89760a6ed8b80b04236fdfdc2f37e3e6b407ec300208fe74991cf252a9c56effc0a9cb3eebb65a6bf3fdc0a5e0255f34c5f481bfb49644a754cd988174d8f8820f5cdd58b8c8b4d5a4973d70b14e4e963fef4ef5a5074ef8254f59642e3d7193c1c51446f2c009d9797bd96212d3950f8ce081cf3e0f153f4c77e0ee738992ee52748dcc0e7c7d7cd5ace9972aa97560548549aa953bbf9748074e79ec243737556d4be6c0c82026789e6831e5adc881dfd823b408a5262599140755476e301d627a61a3777804b68461040e9c187409763228dd26fb35f2063e257d1e84ffe5067ee3973ef724a90931dbc0897b66525be6d0983336702abcec4368e54a9359035feb99a48c6742299d040b236ae0045161993e4a4893fb481a788b498aa8051b0d9cd0961f2ea6b5febc1933fcf451c2c819f820ac343be91adfa40a63c40c7cf4d01ebd2e78688d96811be19794d21bbaa6fe1132b07d2a25aff78e1a46c6c06aa5784a5a08add1332206ae33fee6d5a04ffab8eb60240c9c9c94c8e8a52333693f63c68c199ae061040c5c3cf1627cdf324175a635f2052ee55119338b4683112fb0612294ac558d8e1a8c7481efe039c514752e706523831ea1acd3e9d60a235be05fc78408213c2db0166347cf708d0d46028fe8a8e4b2459240180a05024110c50000c7cf1b00f312080018281e0d88e3e1785415a80d140005472822543e3a1e2820161e2a0ec4025130180c8482e150401406a4208c82408e6599ce7c008726e16c49711ca6e9e4ef7d22f56cb5cc4e1e622e6881893ae7cccce38d137e292bfbbc89cc53f5a42510de8119e21ea6d9ec397e1271ae97aa2e6588c39530a533bdab909690bb061e4e9192677f0ed0bb90fa13fd106a70b4c0b22c59a8c1305363e20f43eaafda672234a41258a3a30938a9a625b2ee84c35302af2af0ab8ff7accdb608018d420c6eb20314591244934596bd21c08483c81f8af581eb94acae043218ebe0bd58ff03c65f7403c1374cd97a560e4ac7105ee98cf0d64198367cb61c7324271902eab87e0b3240d42dcd63c2facd9108a937069eacf85775b5e8268cce6e35d53532bb648bca737bd9a47ad7096fde8a8131b789ca4faa1fe128f1b63e4749526cd062144c33052db6622d2ad39d567dce95dccac5690b00733a8245b8bec6c8d5011ede93b4e83597c477f2a6d9aef0ccb66be47fd9c9ea964c36b8ba4f400a4589e57af3868db651e3bd6d381d44fbc3619cfbc734d4b7675a3184aced6a10ea7ec2b4141e2dc278740acba7cbf30928d308dca655cc650bd904f8f376521463b6878445523a4c14097abe641c9828867200837add8d2404b0e2c5990e0497a1109a084b23fa1b50957fb1e641c85b0c27ed41d72df2aa0315c8bfc2a99a07cd9053684329d0947122b36a21bd58b1e9da5d1a9ed51dc874a322f9182c4c0ebe45667329c297dc3afe0091c68d21684be8d1b4158dbd6c2ea61f613f601a3e243a405b7cdedd4791182d534700a703544155e8bbfb1f6636761243d0aae061bf36c2816246459348a4a936803908cec49ab0c99539708370c4fced993945bbfe285ffce2a2127013b7551815651833f90cd5e191495dfec67986a69ca618a0116896a21a6f619c2f95dbacdd90f7b7a4da699afa33b706ab2500adf3792743553bf1b4975692a460bc5827fe02944b8143983b8d67cef717cfa2a29d5bd9fbf75ef8a7e18348c45459ce840327a711a460409a5336e25c2a068b92997b7eb08a01798931905aa7f209c29b5e2260eef233381238e0b8581213df01e0c4b0982ffac022db9bef159087fd18e8345379402fe3de7a47c81d6269c02fcf2a256bf1e2830c7186e432263043f4b97da00afeb5eb222eb81b711a61105a01cdb9fe99734d29d8b33594fb8eea33040522ab81cd91f8dca3ac81d6d27b1155e0724676b8e0976b42a9a155f8dce60c4744f1288d7e0be4954ec7a86a540c9ef6fbb6524f2d3cdb8921cf4edc9819ca5ce52f9c0827b743e4f99057af12b10ca434e150fdd3f4c380a4fe042e1b5dd7a50c23c193237897f11da1466cd389653f3d20981d93690ca504928464401ee6362382a379e65721839873e1132d2ae78300748c954362a83b7079071a3fd44b7c7bbe8d05650ba5c76c029357391967256e882910beb60af25c1e5c311ba980384bb1bc0a9c3a6a98b78c3705ff499f5c26a041f0d23ffbcce78c1702249ac6397e531898e6960e2eccbbd88e979fbd1f06f9e7cb9ef76832d302074a343dd6dd365174bee138d3e64c63337f56332c6679850f1123a4669935559eb145e9e85a968002faec42a5627ffc0df162ff0d2c663eb25d0116c29e52cbe7c49ebc8800e0be2729bc639849a1cc2675dbd59df20efb69bab0aa5112c8081d156694326463d7b11bbc6c4f5905dac31f8cc76d4ef8a3570835788c5c6013ae63e654691218f9dcec1428c980e3b2b19df4282d5ea2d2107fe7e23c981859403d69712c8e4b352e01153bd1127751d168ab1c87c873c2c18c57a08bfb4fbee9eb2f5c339b253c70cbae54985892b0eb41fdc3f7acf0f6d5ad68732d940220447b7b310b0428a995fb6aa926024824131b791b2f2f9fa1de460ae6c98de3a56462c6086e6320511ad3935b779b5ff1006338e6ab5ccc732c1bc01e492abc86754c8f9297d0f2dc94d171e2c74a1d1b979acc54e747a818ecdbb1fabf3008940087932ccfc0feafd6bcc20c6e0a44b0c5931dac767e4890e02c050090fa16c20163e49a56ed8fc0ac11a203a5a93a25180914e31c7a4f5996411049630b429680667a30ca62baa7f962c95bc81ae2b35212939b17a4bcff987a98ce633dc13af195a137f0c65c9c93d6e2fe67688f3f6a504ab21647d37800904f197b90526d04e0454859c8c28e90114c099b1368c56fa542c2e5d8aea1ae3d20e24025d354e0981bba564ac44966098d769be14737fa9c5bd3829c1b0af22930b1abfc50f59c49180b41639903f8e88890b7178e97382310803a6148f2895ab2851122fe56110708aed51f4dd9c25376c97a0c2cd7294e412c4dc63c6e83fa9171a0436779f41561cbc3b9a39cbd9c0d7ceff33cf8974ead6c49b9952be696b0130ff9d32b2f745738dc16e9cfc72fc0f6bf164c476ab4690a5a3c94e3321669ac7d9be65ae02c639ee59b6823d5481db277b62de78c68eb281f5dbd58e1d5b22e60aff7e8854524547f6f58e51da8f69bd6d0f80ef40d414a300f350ff6bc836483e7ffea38d6c172c983d8e8e1f203a21f1c21c6cecc2714a086c94a21b64de0516c7686f6b28fa00f8a40c4db76b28d7eb19bc8b7b90140c72212f40513b9dc18e303758c0b16ba4bb1de60790752daad1bed3d0d895d1c3a882d37b6aee4f9b920c2353a0124a3510d5b07138799c73b38987ed3d2319ca02b1dcf10a82055a723f3dd1373bc9823cee2db9751642c7b6ffd279633804ec85277fb025a458dded2d0eff7c94b00ddbc95fbd1a09dea4f097ef09f1f6126342eacc77d5e047efe184a801aa2afb027e66d79e8be068d1b38a28110c303a6dea3905064ea61bfa044ba885ffb22fb44eb252ba7b6c5e20175d56c53b7d58236cea73cdec9ce76b1812cbdf1ff1c7236f04251406012837204c7b99543f2e24c85ec265db065b4e31ea3f3518ac8cef203efdf12623cace28507bd782749fe70660eb079183db8db859ce0be42011951bd490addfb5488a9c31666eff88d6378e701be08df48d288945c940929ccb5176216d0400cc30c63334a4c74523828266a78f5f127fe436f0225f3721d7e61203a0565dd59ea793d4818227271826572670c31b8bc47a620b4e71316ba88a8c6fe4cc6d45c65b4b32ea30d90fe6de9869b704d46dc0d12799b0ea4701938add58514417b30c47ede9262f27a8c778a84a69130d52093d6c3c6e012165847837218ffd1035f2fd3bdfff319b7f6e4857e418c64630f634f7c631baea21db8c6b08b7188d9fc988bfbe3e4f86190e3e4d103f12e29c6dd67462710156c3e83cea041bf4fa5352e0ecb7a0fda8539a5a462e5492b16165c1ccab21a4d9330267d1b544a890d02844524d308caae56430faf1489ac5aacb32f83d750153a3845e5a98bb40a731046a4b5e8db17eb71070d91d57fcace5cc5c0a2923d132a3b9f6d18409517e4fcdfc1fb5cf4558687a8ba9fb5462e8cebe3b1c84812478787ec19bdd8d3aec78f979ac0d59a3108683f73a5424388aeb8956ca3d69cfac73e1a263a39d6288026bf60c09c2ac6a756591ca16cd21eaad5269125e307e3dd89e04248f7981594983201da66b62f1e462be1aa9e9f03a7c8691a58544af3a095c8f818e030238dc1e933667cbe8c6802c1ec33eafec0cbbb7e4d307cd56a6c7b39406cede58aa4021ee8e88ecee255368dd347261dda2a260f8c55765861876c69da6ee644fcb7019b4909cd0d55f5a4a597c3ceafaa2fab77f59aa4a21e7595e6de0fb5f76223647c6ef34e8df26fb70fa811985299df7ce3c08d3d767a07f0eafd2dd4581d655f70b1a5d55d049871443e3fbf9f4f5cd872d3ae8b996bbd2edc829ae80c97117ab1b9e93ec252d063b1dd08d242600cd02e482c2a9ead8d34860df802aed7c7c8d821457dca2e816034c5463ba26634ca85c55875740b598a857553c5509ff630408a05ca0c1b56fbc17d1ad9a262a5fc313b3ebb47220e691b75e3bf04c5397812f4fbe0f5371b90dfa0c4b0927f7e376576a3c47c8ee7a1cd6704ec5f14bb1065e426cc3f9216946c04a2477513dd7cb279b138418f9cf7222b25553c7a47193fb2361855d39b40c6019d8c925c3d51a131436a7d4706711122d6e0a751063990859b36ed3378e32b6de39db8d54f9ae9b997f4e6ac59dc4e3ef687483552f5b4d3e486aea9d6cd2a78f2364ff0150f33556107343f20504a75016d99a52a30825f9bc07326128f5f6724253ec0c9e1ac6e14b04f11a4ca6fad3f5abb66a1f09925fedcb0b8e713d89686437dd1dcce35c67fc5b54efe03ce1c71d8f30e31ab6656d7d5cd80f6fd792e5d66638457a15f74c501d62d7390ffcae5bdc14d5296c25ce7188e6a40a52598c38b47a838f4aef0d06b908718d60779eec23087274d90a313934e30544ac06f5fb39e19addd8ee08c2b00bea0e1c2252d22b1cf141d999cba0707234d161eea024505b26960662d5408fc9a703d0dcca9d09448e58c6f26ade7c6f4f910f6c647a2bd6a8c90638a6408be1a840cbd6bdb3a86d146552b69030ffd51068b416995d01fd38a93ed51c3776465f35922c78950cc6d07a62032dc3b69727681536bb15ee9ecba3584bbd11a6ee337924cde56054fa4ea2ce4d1da87d73fa5a083dc79d66f447b31dc0c4e1debd821e8ae32e827f27005310502451536e67e429a972010289ecc45af514e2b6549a4d3e558ef26fd657b9bfd15942702c461e9fecb5a4466e182f009d7a12874bad1ce04f713366bd2ff22c96122335d97bc58fff186ac97dfdcc74f5a8608b0739fffa89b3a985dfd3b4b95f028c53240033357a3323e7e74cd3f841e8a04e86a86cb27cc79c3e36369f34ab3dce0b1f5a3b29afa3e9eb9891306132c5f8114a5c2b583168522576763a497fd0200c219574f2407c2ee8dd9764d16b252139620c4f3b5eac9778a1b9f9c6a6547844fe3f1787728c81495bc67ba5afdd94190d5202bcd13a12466233562e2dc00a1606b6f4cdcd8db3ee4f321488f7bd1d9e3d36bd585b40557b08a36364704542031bcf2877c7eb5d5e9ab0c255ed440ec1f969470235fd1382ec5a21a2a18846858609bbd9fdf8343a41f26c5f50891c4cb697c7fe4a7e625fad16ae49cfa5f1a2d4623120dd10c3adce3bce82cdc28756f9350d6d1bb689a895c24971fb7e406cd577445d39131d847a98793c9793bd1a36838750091f6d0416bafaf99184bcf11030f705ec62c6dbca1fd534cefbebc5951280b6033cf60c82bfef0b6af8017cb6642dd47a405de8c34d3c3ffdb71d3b22769ca01528d18e984d0666043e41c98a33aa21d9bae15db88de0fb3a1bb80a10c893b5313bc321f8d4bde171d04386bdeadb956353e3e6ad2543304ce1f4c01761a1efb3425145d90a7f71bdf19df762f5289dfad57d9d8bbaf34d8c36e2ff36a3a8125807e71adfe9ceb299b53a77b92da7b9729806bc167aad61ee40058eb1c5324e221954f1a2fb16ba8b0516fe3eba85ebb4a29df0437e28751da21ad30eb1131a869e04192c258137cff295dcc36135324425669ba187a9ea2963a9c0f1bd0f36fa2b6e9a690b7b1933c3cbae1043d0b4745b78cdb9e2c23c2d4ad2767a784ca3f766ec76e367e9f035a2fa40066a4d5afd87e82a94955176a6c8aa4719827c7ea86d8c9406dee6f86de0639e309c63602a9f48711bc77a5739c4fd2b6c8408f9a7a5e586bae4d2f0fb0cab6a6e53c42989464c7a1924e289e1a2d50b2d6331809dd746b171591588cad8c2fa79d27aa1556d1197deb7062833c82fe6c7d401ed76281fdce6d584213cf3b45d2c997955218880ea2744939a1497e75b3c4500c986f32e1d9e1e3954ff1d231d104dcb280f33d2253ff25817051a5970436a500e3e87f844464e913701da3a8302bd739123f830ace163f5025965ae625301b7354475fa007c417a2862425160e3e9dcd0da49e8873446e4307fc9407e5e2e648b7c745f79ace413d6f634515f704b2787f7a827d5be12e06448bbda142f7edfa20f1e95418001934904700cad6c47539ef8169a5222985f6f7c8d17b7d0bcd9695394d90fbd03806a4171af08384b83e7a51326011be84af7236caabb35dbd791f8f39678dc27e1044667e049e551121f3c71a8e4976249910066104c264f0305b93de21545b100f90eba43bc92763f7ae2bf0d2529060d5d58e8c682550bd89b95c9f9821c708e5ec824aa0c386808c2fda5dd9d7cb3aecacc2221f504f265f047989424f02a6670f1899af67e82608a5815c27cb1b176b5b560666c95ef24952be6d6ad52637ad9b9e1f09d73439d2d3d836705cdabf68932290ea0da83a8a864dd948d1e51f68a889919c9453e006c3f81ae1fe6cab77e6e1bb3aab83b93b3b1eaef5eb7e209c31c190ba8fcc35be44c66bd99733dd0a5c7ddcc056aaa97889b11f237f2264c673bdc2c8080bac66f354f166300ddc3d864ebee3835a4ca84fc02b6d950a6ea44a40296351e4a090e28d9100c219472fbe804092ad006544fbc9b3650685f485b3187540bd1bc94c5808dc84ce1cf01aa6e18140e4b14aa0fe4daa899c29b724441cf495a4f04f48dec5f8164ac009f16f9ccee9e544a183d9cd656f30f1aef7830e14d0fb24966c8ee700d49ba7b4ffb46b06cc447589d874de3864c957b6f4546c6de0ad5471e84b083cdacc91adeaac266dec6f2957196f4bf2f8ec85d01a7c8497dd2a5cd92d79f290a9c8e6942ea01ac0f8c04dd554cf4b6e2fb877226f5a2a6bf548b1aab1ae163bf819231d96071eebd2f58305bc2bc1c8ec2f689c9684e008775f1664a51cb4d68c26f17356a58e7f751bcd425b63d5f073df764bdcb36ee7dae1b5caae95567f39dd7899c21e37a9dbcd2a582efa20da08c5f78098671234113c2083ceada726da35e4604f197186b05f4bbfe5f2cbe94008066e9af73c32c0590c7f255a11e622a22d2ea7926a16ca8405cc563dccf11a637d5c5990a39796187220e5db64f1360c32ac448a1a1998a72213393e8b21a4a9a915427c07eb9d3aae7d4f9fe6198f3a8c53d5b709642abbef5a93adaaf08f2b74f88510fa66b666f4316bd8457c3e310d34255ac0d996c52a643d20b1df7eb3912fc0dcfc4ca71afd26dcc32a1a7fd0952ed9a86816aa9d376a459253351857640aee737a09ec3ee9e68f98782bc800bab475106f63c29f195f5f112c9d180bc4f886d57f03fd67a977fa1ef6d3c0c6d54c4ae28bf2ce503292822bd1be6c4a66987bc64e29ad6ccaf31c88bd68518f800282efb18c4b7df9b8faa68e97d6e1ae4855857759d33135db681002cafbf6461649a49e1963da242c70fc022d535da6ec9483358af9aa60cea549fe09486d086bae4335aaadf17ea6a6a51e3b62f06ba42f305e58c2d4b9bc2b8684b7eadbac7c32af594a9cbd9faae1a4f16035448d382326766ad4ccfede1b48d8689bfee9e2c26d9810e9f10bb29c296d047a11217189478f999ca0185c3df5981b6c25407b0915b205f10fc6a3d1d28a89e7f5ea482e3d0b24f577c67f5b5d044912cff5261bf754d1c83006330c507a585c68cefdfc1df9f4773b1d71cfd41d129165674806d0480d53eebeca6414f5f3e46e56dac39af6925f1f3bcccc2263ddac140a8446bde09a3f8296a993a4feadb5555d9f5520affa95e5138aa71a74ed0f1bcc11fee97a17541c407237c300571fc5c74d755ab7d1806464049df9e58fe3178d7cf9aeceb143d48616e4e68f9f8a232664be87134e73edaa310e531bf1e90fe8ded3c70b7f111d486c5734a53861348049101fe3fdd0121a145418eb46d982b739207d7c9ad9ba17a47d677a2875ce704a633e43ea6b0e5621e3961ca1f4e837bed9237eec762320230f2f41ab33b1db144607f8fe62b00e8ef5fd9bc529fe6e9ae53da788fc52da31d0b38f8387cc8ce7108aa59ea51c32e0a5656d9a4a090ec23fcc9b3824dbc95359e6cfb5050d987fd23ceaa020145a704f0313cc2a3b0dd4a20eb5788477c4e230a3fd0b011b8bfc786c83019a2ea7c2e37223b3a50d9825c8beeb5a1eae5ca54b2ed2e5b58ae346e652b08c8f774529f587e1f3326405b14194799003c9bd233dfa93a03c2453ff2ba3f20f5da0cd00aae5d21e785665c8c8fa3c6a3d7444fb4b11c7ce2120e72db102b2d93ad80283081a2948eb300e6333b1207cec25e4ea2a6d75f75aab4a6a4a9850babe0e3cfd7386f471c79e68fae89dcba25306d7151247e9c6698b2e760bdb15776a915cdeaa4c61d9f5868c105c7988f98e10a819458f27496d846ffcf7a88e451d2f237fce3535db0a6b51ef39624cf70c795acb6e7eb23366b280a044f4be4993cf2bcd6e8b182168372941ebfdd2de99c019b35d9753cc9fc63c198139f3f2a7cbb7420f291cd293208a138bb196d102fcf909b27fc025f856e5be737493fbf40c5c251caa9fcf5b021b5e28bf5e9ee47d976869df50d2255e6ec4ceb740e757e3ad010a6837df74292a773d83b9f35ac897ce363f395eff8af35a3986cd69807346001b89ec54fdec5cd781cb4d8a695ecfb53f5984b3bb2e6b3ede4cccfceae3974d2a10cd3b88a1947771882a233c36f19c0848198c68eac934ec8b2d03a3e78b018fb992b61acd64486517846496ea90c012b81af06451fdfaf41629a4006c10b4450123686d7e3ed251c56ecee5d1584c67fd2a3ed57dcc7f277d36aa571e7d488c7d242c7e1f41b2b003bc70ce8f3fc94bba00a64e0c3b6c3e75b4a470d22128cfbfb4e2914300155d78b63a9dc729a815398e5275bacf28ea9fc5f5027a0fe39506b32210936db174162269f9c0f4e4bddcf4080791da252c4ebf3016e084d21d4e649893010c2af0fa0a4fdd6a8270954b2f5cd99c82bc5031be29dd474ff4210c13bae2075fe32484cc7ee8c31ab360b2f2e71722a1188955163161e1cb01a01b8a2221abe1a23d3c3894bc58bbfc3153c3f84c304b313982d2f6c3c80228bb9ad600098a8c58491d403ce117e01bc04309d110d1a05ee7ff2412746e64771a1ee087a0303dcc43ce3f448c0aafe7155808e6d926e26afdec8f70f1402118628af6b6c340d0619bc715715f0ebfa0582bff939d96675a59551481c4f6d18aa20303cde3be14c89820ee7dbb66fb4f96548bb3311c4eac2b763795ddc6a0100bbc9420376c4c85c7a045fd0b8b0933e5674c5b6a6477cde82be8be4ef830a60425c03eedc3781d0a7cf0c93001f3085ea00ac66eb9199da91c47838a7a7af79ff08f9298118ebbc86af25f70045ca4be2c1d77c0fa12f4501c176c56bd8b24df35b4514c2e356d540708bbfa95f93342b5e9695b2fa5c1bdb7f0027387a5ef41aac16fb9b69c556cd5ff073dac1bcbbb2a05d3b90082aee25e01837c7f599e52e98324965c5cc8655e9082c9ea4dc04558a4c700fb69ee912b450cf14fe0489bf36b64864c34fbad2138d38aa456e6393f6b87155841499683b87058888fff16dee0da0f52b7dc7a6144e865497cf5d5de48e92e27e464b08f4aa8a9a0aa80462f7128c1476af27b989077c8cde877160314fd2237aec10c35e32204df2770195e06524de63c7172660ec0179855069934016105340e312f9ec2af3a59abb61ae44a16ee632cdfc095ef773e08bf3453f7cd283effdd52dc9f1423c6b0b1c506931717b15d407436ad96fea3c82333ca6b2eee32253a71b201cd27445333c9a27fbedcca20fd491676f8c5c3228f748cb0338194698994014d566e36285984db67a9d0df9c5b59ba0a932c42abccdc1e078f5ed3240b0bd1babb23a9b5289a045e5ce47e83fe93e83f16ff28fa08ef47e8be51e70f508e24fa31da8dde72e99ac2ae97501d491649e065d5bd51cb1a96db00685ff9cd2944113cee436df7f8cbca1903aa0891deeef3ab4e110c79426a4d711236ceb5c1cac91936fa3f22fb65902caeea481c528b902cdc9b20ec1848d09cdc6d940322c1fda4bafd09cf0e6454171204912e36742f2c603d95c279ac4629730525558992319c735d1917598118a261ffc778d15e01eff6d4cbc2645a3adcd4c59df9416f25d080bf394f6d24f664eb3e5ef8f94236d186f4926a5108326b114dfca01ab0f8f10b07f9e5023f0481af32026d24c930dac51567e808be96980f9ea270066f828b1678139bc2e2c7d4bf7d795d99363669e105232247b033d7b5faf8c375fb82bacb805d62757b04f64660f7196a8a4376b12ce0c7d0445f63f2e3d7d63ea2122a6f9aecbd3699ca62ada5c45cff9cc4127f81bfa499e20fe62a0674947100161622f99b4e93dd4704c72e4867d57374dc93546eb18e1ba025b136988119146ddc65a4b26220a2e6c764c2d4eb60fa3595402f4b2c8489e10d2c84df8cbbf24ed2e82753ae560429183fce119e4144665650f64a17a42596e6d10a6445b9dc0d4c28e306ca511a9317b0f464b855b3ab72cc989ff281e0d7f5c8207e89bc9652754cfdb32c5704152f8fb93f81118f7a27d47a5c279faa8334dcfa3a8e0b30d0cbf7b59ed88e79c2b2690a6266e2435252df66fbf1345612c4f143c2e2542071f5f1b898f3b7e61253b094c68ec8c6e8711861fefd5c1bb0ce5dc07a1e166011af12744cbaa9573572b9001a234be6e7edbeb8c20356e3214faea589380dbd5735d0cac7316a373934624d36470972987f6a45a6df3a3212938b361305ac108c99230fc8f498ef60e563a2f03358f7d58c257f0614173b9515792cdc5fa0e56a997e3b48ac5625618713fdf698ea5ebd6a7276cb9e2e98428eecc2b5c3b2e5563141001e632462cda6631bbaf0a439f8695b1515c6de52ac04ddc046c63e007f5ecafe926d31522147b804795251252085729fd2f1a7b304f4eb014414fbe71e6de0c7d8dfc41189d534e9bcf48bd9e8ed3e61d6c5dc301b89e482ae35b3296ca7e5c8f107a20e0dbab3dcc08cc3c740d865a97ef184c2390478198e0ac7f340f5d8db8570285097d3ae8e94aa51a02a977a2e3750dd285401bab01645e5e595e109f786901d2ae40c0840f424619e694e5408840a7ddf5078b4f2df442ce120225c7c248dc5323b31d67caf8433f9812077e1eb110b1d4c62769076ae996f57a62f8b25dbcc37eda76f7bd2bdf877f167180e526c1aaf10a4b7e6a858e3cacda5cd1839c1e1bcdf101173207132c99ebd520d84f48546e1c5e14b75dbfa4b22e3acdf7e4ede1c4dc7cc4c6eb230480630493db6653698b9f201ef42186b09cf6654d0395885b96e1fe1352afbbe90717bba164a9dffab907ec610d669192bd72dcc7b965ad86ecfa588bd2c64482601c3b8da90b089e155d9a6d3326b9900d88daabc3e76711a68a65ad374d183bf8485c619185fa0386f48c9e043136e98d400fdb9bcfe03c5bfb8d685bbcc07e9af66e74e2f9db52a75a3bcd88f3ef7947417158e7a7a51f33413727ef6eec4d9613ed1455026df62b47209a8a5c2f5d2a4b0d3c5dea99838e1531c29f62e7d9ae2440a47479715182d540d45524f9b0a49601b93c396903fe6fcc480df50c759f1ba8d5dcee10c8c9ac8d02ed0baa832758f7ec449022a632bd0c7b3afd444702bd35363d91c54bf891b00ee1156d91fe34259e08a1f9308d7014beca62f60da7395a56629c96b6f7e7f218f473a074cc0db546d6c4045b54b3a054d09942a02cb93cce5a498aeb31ae60383c20673986652092abee10099897d9b336854b77122c280ebb3263e03b1ed7b7d0a22db912cce60f0f8e117199b417ac86b3a6dd38255fb6102effe71b2b911286837fc13f80b61a890b1a869381724c005828448211a59959676c4333db60764fd43a47655d3a9ed7ef0459816100fe842d8f2e26a2ed0927f810b5fe0522982b4affcad0b01769ed45c31899868c92332065b62733d2feae55ac9e54d59e22668147578c15b1d750c2d76e7189224cda40799179e25e24dd83cba8cd7a1dca4c8edabef025031b67b5b015bd44c75472a9a43e084041cc22491d27a18904004f8702a46082597b1d8892770451a84fe580f905c01a467ad9e78ca9c972ac511dde1925be8896844586d389b04d96735a7a9ee2fab40b8063e4877fbc417bd37d842a58b38db27be6070834d3cbba4dd3045c4f66ea5de3f930a10b142650973ed94c6ddd3fe81d28331f672d4bac618e5741f9d5983199b7cb2ebefcc0f6672ac166d3f5011bb784c9e0c5d5b165220ce630a2d5975064b671cc21bba9da110b1546912e14e66442be8346fb62dd18962cdb601203e72132fbbf7c7db3866c1ed5d0069c9d50b49ce23e3201986edece210f359fc7b7543a7c770aa44683d9ec95527187d0deb75e6fe7c3f0d8c692deba189ec381025fe3f059bd9c535a753e7d341172898d3265c1403c1dae8bea9691a202398215ad7730e599aa656439631dfacf5649d19982d5a039f3de41c294b842829a9b3e9a17bf9d8e173ce9ff13488f2f9725d3b1d37cb47a5313822c2b3bc451966c6ae972ccfb3087fdd116b442eae2b8078fdd95fa9cc45880ce4dae03a6fd3a64b4aff71d2e4403dd20e0e105963d12938c763b9d39a1c69949e7a10d5bb9d94047cc1a4446813409e375887fb60b08b3b55a7a397776b8cc023893d59acfa139508500837de317dcd9a6b9ab0328094a0da8a0e7f32cd9d2e57031601aad69668a06eb9478e26c48c5e9f0fc4e71091037c1bd076e7f838f884fbe8e28e591af36eb0a86fef4d819534749514b77d94a9dc1fbabacb38976bda1c5e1d6afbda209ff58cfdef3a728bf03951dd8650b1893c865dbd131216ad7f85cca1fa09959db64022f99415fa55427d294c8ab2dca77113040935b6cafcf8a122233f63e3a1ea0945a2735273e13e0c80e1fc3d71fa4063b9a5210d422678898c5ed1d788103dad3e48e82c4b6e9316eab43ef80bd217feb45a898cd08c4f6716c098c97edc5872a6dc563a9f9eb41e3085cb152df60b920098f7a68714695325549dc59a634109772aca6e5bda998ac2ee1198e8101a216aa705007bab0bdd4b3ace9a57f1778c91d847e81c5b68a3af737ce72d9339d6670c4c234702b4735c1fd578eba9dc563f25a501340ae2c912ec8316a8aee37722dddf57b20c1a2e1d63ab0fb5dab6f23519e066fec41db098f0e945bfa74b975553a66814f5415ea3cdbe536e7c182df9a1ad0a8cd6e8b2a47f751fab4c2245cca8313f495aabf151b55526ea45eb087c0e703e9eefb89c6fc1b4caf659cd50fea61b9a52c69e138e34b7f0b57aa89abff994262d16b476055dca473164b992579370edc9035238449397945d2557611c99d4e25d257aacb4269c61b7c82c834a9a97f327ac9d56d16251d5497d403c464966db097440a999118743c8eba25f4dcaebd68ea19bfd3fac220f287206a6f66bb6914805559a495418037ccfa418f1e574a1eb53b9252cdb1b4a3bb120b698ff170463eb851264b3e8fdb9f2a2ad8c236e53a29e0d942ef51bb1e9b232990608ec8dba3fece2d21a25aa3426b59ed8c551a5ff121227919ccbe05c22437465e4b5eca211d86c49f2060d52e4b3a715605f9f254a244cfe0e5f2772de418013f1bb73249c902325541afaace076403e2415f6cb5c12894e3b7139eb99c9f0ed4eed40ffd2f0f0408f2bcce6da4ad0dad5e42cdf1ea498d04a6c768914e17eeb54e113274e77216797b185a9c6c6913d6685d9b6d72f8bbed5050b3a7ee770d624c45e6ab2e31b9f2d18b2552f43b565935ca610c26e1093e450bb85483df24dceceb80270aabb94946b6545e0376a2b801b34d6e4bc562c29ac1b9082b5d2edc0f00cb5628f4d2fc9b86790ad559239bbeb61b50fc8c3d7ab698f3c924181dccfcbef1cc9155f536b3d23b907f52ab96160f4ff93b0c6fe9ad927d9f14808f0fd3a7f1bc35c123259276417aed76e6d17e49b38c0e6d94eac16a3efddebf444ca461dd0de1d2b94e5202c45ed169540b71ec8ede09ba9ac0dcbea97814fe478587f7d9cefcf4b7ff55882d96302ef141d5e1b6c6341c83f2d089b6ad905a8e94176de202a01619f48884f5d443d7f842f651a9fc55e0755a5c18a6eee76d6ad4f428721fbb9cba9373aedc328c7197c77d309221a8ddf538032b2e664c54d8c9500659d92d67a864a9fd143ae1490d599c9f2ed5692dc8787a0a3d86405b5208a0ec797b03c54adb17efbd76cf4728ab018a6671f453eca4b78c81225f113397d1c2a0170885af5ada9b0ec3d6a9c0ced81e8dae6c906191b75861918b6f904210f5e0ec41de0bd4b378c5d924d86c917133694e51e64ed3783a4dd0201847183a636d656a99954c74eafef9f8d01133ba2fd17ce10ccf6329c2a05983c95661923fc86d5f0d30488575b90e40eb87438d8cdb41cc50199302075f65d58047245307252cbbebf507cddad13facf476b0a7456325c6f6140f5213ecc1bfa0c6cf531fe499cceb3496febb669af70cc02fb7d4d4e0c57d32caf6f9b996f721738b12c171c0c795972805b78675433d9bd6541a5db32c31de8607f577f8c646ea8e709f92a1f4ad64a28726f6cb4f9cbf665defdf0d85f130157b34856cc8d36e3546de1ece439160a6c8dcf486ccaa78f8bcd0fc37d6d8b961f26698e0bac8e2b46fb23a5c618437a81e7fb65eb7aa20a6f67dc69aceb60c511be0fd37bae1ef88e4ee0b75f47d3aba494452fa4475f504705a6167b41e1155c1178930c651802932061043512391a4d961a3cca4f5a620abb2239fea3470d42489444411c8abf66f5c0039428a54063980e1649a6ad79b336187b79755158832e52c61a688456b0b24caa915a4661f0d8228f549e61c329c44a387fc5b83099ec1f4e292069821f563a2295e4deebbf0274f9272bece07238fd82abc2d00788fe30b3d1093ce90dff2b8060299aa33393c9585c6c5b094782369edb67f5b673b00617085eb775c81ff0bd1ee640b44e687b259d2accf8f8e17b5f4f52cbd23c54facd6ec21f0fb2a3c79142393a351b5cb915eeac32873e83431921015b9ef33f709d5c36405b47f60d47798a789208f3d2f40590913829024bf3fc2931235a7b3ec4199dbaa0efa06f6135928e235da1648239a139206fa101b683d4a5fbdc23567f911300e4db338dd6a3011f005494c846d6d2ddf6ac1846311ba0dc3d4f7f80716fca6fb274380dc68e25b6a45bbb0ae112601b0273d5484b600516d106fc915f66134e4b058aff2dc7ffc53346189477c578390340f6d5bcfa1642eb72b887855bfe4f6a7f6fe4057d7c4d9a42307e4fedbb983a91180a6d9e731d742cc492d38076c68ba3065ff48aa71671e743c6692adb81bf0ff60ae25b834c6f988a8697d2f2df8ad672a72f49cbb6637d26d8d270f38d6969270a8ab11309e5e68a797e8460dd08bc623790231834c717208f1822d4cc4261bbe4655be41027b032684fb55b9c3949ee15197cd6b9da48727e4d64fdf1af653fa34f68ac0d0b7f3cce348546eeb51854c7a337f6059ef423d6d5f8dff6d9c8b753a1fd0747e46e78387e66ced14f68459e77cd723f5358cee3bc344e8996d061913fd48d52d1e5ae4d91564108a3a57d2bc34e31c3bd62c5b17d452c9c2ba8c98db829c5b424d115b0953e3152d53e1b26e9614515e67c2694ee7c878f05619c3673388bb98bfd0e00e290f36260496f49512aa7a9772668d0fa33e60b247b5b8b453e31d0db0601709051d07f1c89de7685a79d5d930a282b439cb4e4f94990ceda16c808731b1dcd6777a1bb84a19be6b3ef53e4005e84f62ebda976a9af62d7bbc1335e9489610841d098bf2be31098815f2fab344a35df2d062459a6359615a7ab06062cfb898b288f800acc042ffd40e7041fdc1435c78d4015b3b962e036416c39cb61841daecb842bb52464ab1263780c49b060b47e1aabf106cd6a3b223b2aeb1ddca5f3fe34959e9e2dd8dbd2cba6e5c2ecf352080cb1d1f107650d82ccd5ff953e94c45b6255ccaff7a4542f56ee17a236d00e4ab6eb041728d2a092a594bbc2314dc6f34ddf304c59a4b4a727455781f94a79236ae3fa5991cde818888da5c922cdad6376e300c6cac6288713a334d1837c61f9794569102d20653aa9824acaf404c0ca1507ec3ca4bf9f75e7b3059b4fb8325c70c530f263b399bd375fc6330f5aafed75025aa8f39b3430b024e900000000008013500cee57ffffd6bc6dd6fac6da2f939413baca50910f6f684a32c99452261fc507b48db4d6e0c76da053099a09bc09bacb4aa5506f10061059a0a55575d3cafc65c52716489ddf34d9cb592e4ef38f8215fc0104166839fe638e3b732a4dcb2bd061b59637baceaaf737ae40cb623cb56a33e9ff20b7021d7e9fb4ffe7bfcd9cc900c20a748c9c472f1dcfd7fe55a0b43656345d45b36c9400a20aa48cda262d34882a4f4a05ba3b69d86a314cb71c6201041568496376b77ea93db3740ae4c9df0b5aba8d038829d0aa63d8ba3cd18fd9c25f0029057a93b99c053d6d761e8390021de5aed2e9640baffe1f05f264dad46d3a538f8755200ac4fab897529afd3499e400120a743cf94feab7856d170705326bbd2d2bbbbc5b5f3200f9043aa67fe1c49709c413284ddb9452e90c7602a9aef339eca86e0e209c406d785b31f936c82650f231eeea702ab59c57ef014413a8b15702c9043aad9b7cb2172e2b575570638c1b29b83106ba31c68d138cc15400c104f2dec3ec4795abbc3d4124247ef239402e8116b64c4d672f251a4400b104bac4e5cebaafd356e7402a81cef07c1bd58a9440e7872957fb8e8d9b49a0e5ff8f73d9cde5aab0078824d0a55f65830b2f49d51a9048a085532ff132c9d200020994cebcead5158fdae511c8e8f905f9dca55ff0a8408038021d3b2edeaad3ca56dd8d40a68f31a3a997a3bfa46504529e3299c55cadb49d9728208b4087f9929e4fc6dad4a21481d6dab550fde29450cd2702f561774b6b197fb3ad10813c7395fda9f4e616b31c02b9ab43c3cf46dbc7630884cad62eacf0ba10e85c6a5abcec714ccf4508d49d744f4da7c5b0974220800c02a522abaf7369b8dea82090a7638da872d14020f325295bcb2ce6a8563a0101c4abbf512bd9f3df1f506a32698df97338d34a7e404aa97d5d4b2dc9d6fde9035ab97229ccfd4efce74480f001ad4dcc5f0b31a96bf33da0256d7eea39c85c00d10342ff3e86f9ce92d4922a0f88ad55fea26c1f0fe8b8ba19a6f58b7397bc03ba73da989aca4d95318a07103b203bb7184d2ae5aaaa3c12923aa054a7fafc8f1d1ac7a6035a7e92ee529b9ee7d3cc61755a56ab94789d1c501a75d6bf72f7ba336e3380c401a9a429f5247ffd3f7c38a0c4bb6c5fd89637a0634dfe7e30339f57ba01352ecb183dc55db9ccb50119958e4b57bd82b001a55d5477e9c5dd55bf025903626be3a59735cbd2e309440dc8a06b6a7bb36a789a520d206940aa952df8cb5aca581945035209d932bddd32ed2cf201e40c68414eebb4ddc50c28194eebd56fbd675599914c5c80069032a0a3eea8f5c66de9e47e6b203ddf45f56b19545d940c282d67b14b9ed45965b4550e13ac013206c48beef3ae51a59f98fa002206a4cca27aa5d46618102f5e9ec18094aedc94eed2a925ad817c01f939eaa4cff4c694f203f1027af33c8b068d7737a52ea0d4eb987b32cd5cc9cf05a479cce27195d2d9fe1690722ea76f0bb7f398d402eaf4c72cf69ef25fe96501f931968b71c13dd66db08054a9fee26be1f33cde2b20b5287d957d6c69c55cf006016205944ced1c57ad662d7d5605749c51575953dfba5c3180500125dc638e6a65e7a049d52e804c01ade35fc867bc8cf14f1940a480768dd5a8694ccbe1a3a290d03b335df24f5040afde950fbfca3fe7f5049452be496dd39ce7dce20464da6c2ac664d44c1766034813d0275ebd455fc5b32cd303081350faa29ecdb6e5da5c0bb204747a498b3fd3d123802801199bb56753f399b52c250179736642e5cbcc041024a03c8a077f559a4ff6097204d4d6ba4b2a37bb735e8a81946dd551cb4123063a6d7a0f2d9d3cb8781a06cae47e581d4ca3c776d1f0210c647059129e5e376c523918288fd9cdcf497fc0407b16333647f5a3f23627f8f805fa3f66ad6553bafe65d4872fd0e27d4c231b6deef4ffd10be446d594e9e92e4b2e8bc3072fd0a91fdbc663d22ed0925473b9b566597d9f3e7481da32176552c2930b7ee4021d4cfedde5b631712fca8f71638c1ba1f8c005e2b7b5baf3b4273798b740776bb9fcfac5b640eb16f5ca3b173f6a557dd4022d78cdcb827f0e123e6881b07539c6eb20ce0261beb9dc74763e6481d67bdf62bfd4d5ccea2316c89c7322f26a1ae5eb6a051fb040bd962edf3f26f10f1faf40bd96ee84be6426671a5720b6e49ab68bbcf04afdd10ab4c72e3bdd5c42c445b102ed253facd6bad778a755a0f5262d56dfc3b74b4a5520a5babce0af65f373cc173e52818c27cb45f59c420532d67c7709d339c5ebb933057a63cc8ee265295fa34c29d082b978962db7fcf352a440976c70a55eae49f81805f2fb45a55e9acdf910452f6b8ed31dae74638c50203e79d4a2ad8bcb9bb40f1fa0407d7a9fb9cfec9a767f0219f7d2656793c2d3ad9e40e67fe184b7aa76b05b091f9d70643eb7ea4d9713e8d25afce61834b5fa973c5cf8d8045ae86aefec1e4cfcabd6f0a10994b0d5d457a747d3e56402b9e2ab593cfe94961b317c6002ed9a3cd9c7bffc2965d2f07109b43ef1f2a877ec94a96409b4ccb67eb8ce628e25530964aa6919eb49cb6b1b52029d4b8dff66d527817ef152fdc77c75eec5e448029d5fd525efd73d9e5b2450f33f9b65ebda17540a12e8d3b25a7cf3fc39b9ec118897e5f2a9beb3159b3b0229736799a633beb15b2f7c34029df62bb30e8fdfe18311084dfaf5337df7ceea7c2c02f5b235eafb9c6d472545a05eee67d7b4d265594e22502eca174f9fcacc9e3f4420bc936a559f79e39f7b08a49eb86a31556d88944b71ef1a1f8540ffb8962fcbf24308848be3a583dc6d3c191d04326b7a878d060581fc77d7926ecbf9a4df8140880b269312aac5649f0204d2ced3b6ca3dd3623d7f409a89b854f262fadeec07e40b9b5f77f19316f36aa4e430ec0352d555d3c6b4f1071fd0fa37ead0fc3a677d3a72f8d803c2df576a516a66eb743ff480d0a4368b49c4a3471b9ff0910764dc797231d8ce6bfce0071e90af71523b5d76b6e9dcc7b841860b6c40427286e6e1e30e489d5bdef1d2cc25334de3c30ec8d0b56f315f96e97ffea8037a657554dfb24e258366c7071d50f3326b7f6a54724564e8f03107c48b5279b74b679fa585870f39205de373b6eff2d296310e28efce2a5be359e7df4f0707c49cbc971eaab324f51718467cbc015d27b5568717d5cb562928230df1e106a4ceaaf52defdd8cbbb60d68617596e46b31ed71657c94f860034a6bb17fd4e675e8fdb106b4d6728cfadbe93bb54d42424242427288f2766a40bd3cada5ea5eb949cb3fd2807c7dae05d59c8506748e2d87974b8cbd2b9d153ece8072b1a6f4ab7cf9e37bae0e1f66407df67bb59952b6ac95ca80509559e96cb264878f35d0b261bc65779e7efc020977318efe2acf5f7998e8956014226d40d97dd631297636a063107bd9ac83eaca95c81a501ef5a6d37277e15c520dc8f0b9efc1e578a931260d68cd2ba7a1a929df5d259f82031134a0050f9aaddb53ebb4e11950673aaa92d26e33205c980b0d3eae934e8d37a3a4a4c78e4f413cd9b143a40ce8f7ecac3e8b1a5bf49c84f120b206eab46cbb157f21034a9c78adc9d4bf46178a8c01a93beea3a866fbbb6c04226240ae18536dabb9353e87019d72d5acb03fd7ea491130a0555e567b4a3cc6cb38f9179090b88084e464871144be80d6b26bcfe0aab30b0de338b7e3757c49ca97a103dd20c3053770a41437010d5ef002c692931d3b3a897801a1bb1e7cc346e1df5a6cb135d97c543117d03126ad932f6b7bfc9c2d20655e2db987fa0bcd2fbe68011d746eef379cb2c077d0185d1efd44b080f8f35171a7e1b5ac8cd21103121283060949c919349087498e2686c815d0e2b76b99ff97a19702112ba0b5aa667c51fc85cdd1a17294f03051a708912a20b59c5ad2d2fff669aa44a880d4d9739a5426fdd5c429fc9a1e4ec7a45152408c8ad76def245eb4140564ec9995395fae44040aa8958ddeba46355c568b3c01193f5d2e2dbf7346bd3b01d96ab39c63f6b29d9301814813904aad4c9f25f6332b291126a046f45cf25eb9c81290724b87976a5d4735314a8a890e1dbe94fc89a18812d0f2e7903b8fb9fd62ef40240968513c8bfd69b31633f229e21041025add05f7dd7521265d709cdb1b64a4a08c123c8f18ec303941010acaf3d861a248487e49b386c811902d6af66f5da555761c520cb428cfcf952e13b69e0921063a7d47172dd39833a638ce711921c340ce66f5519efb38cea5f13cce1b428481ce57d3a6f465f559d6828130974aa588662daa7660a047a3b71a9f7535b20af9c5b28e39ca3cad7f5f20a338ed6a752b2d5d2ebd40c79551aeecf6cf09d70e9393650e478a8909f25056c79b717262c2034742311684f002195c9cdc24a754c995d9056a3378d4e9c6e5fbc6758196b4cebdf5d1e5b8e1940b74d2ab9bd962bc9a960d41082e507a5ae69b8e752b658689098e9217c2eb503910e310720bb41685e928ae6571f655445ba064a7eaa0424b6d5c2513520b9497a9b74e59ada5160ea1053ae55b6ae1a705d1dce69d59a0b3b398652566354b69f849c9ff5a59a04bcc8acd21a7954bd39ce10a89053a7e8e9b95f636618196c44d8ffec65f81f6933a777fce7c1a563a166744882b50da5e878ebca477fd3321ad40cc9ccc7d96ce64d2185620d5b3569f5bc6f4aeb19055a0a36bc7bef4abb5a8344415c820dfae7478b9c50e762ad05a4b5dff77abe1ae62210415e8cef4559a32bca437abaaaaaaaa66666666662222222222dedddddddd25600921a7409a5c599d349a78793338ced90f424c8192a6e6cf25fb7998308a19262638424a814c2d6ce6336d2ff8ea709c2b591e31180345878e12dc18e3c68d316e8c71038d1c6a676e0d21a440ea57a945ed2fb8787991411a4246812e13975ac577fe35cfe82284880299c485679bea719c437995030dc74b0c055ad5cbf712cfce11c57130aa490828d0a26eeba79631ef582242c82750f6ef7265661dc7b9209ce1259e40eca7c80b7f1b9336a413e80f57ea859fbaa8b4981c3a78987002693a6976f9d3f1b450b110b209d4cee7666cb1cd1abfd3045adf9a164ec54571d284e394f048c3848719252839f672109209644e4ab34d97d4ebda746b846002dd19734cdf736fd95f02bd1b9f3e46d3e8fa3e28845802a9cf646cb5615ebcbda908a90432336bf19a7c364bda47a6044a4f8ad362ce96cf5589e3b0a1184226812e71ca4f5e7f78e430918124d05add2af18fa752e697095276a040086aa4d1839048a0be3d7d3bee0b8184a21d1a635f687aa832870f421e815ce54a9fbdccbe9852218e40ceb7c9acd9329cc6e0a647231b813a61db52fabbe7ec2b8411880d66ae5b5b553c3c25c7a2789420d3a391850859045acfbc2ca8c9a708b48e59b3b9b02eba724d2290db1d4fc6ccdbaf5e2b0411281d35a9b815fee10d325270899043a06f3b6ee64bbdb4da771a620864cbd9335517cdfaab1c68841402e5fdfdff9230755dc2104220bffc4eb798f383402619f7c33dcba2a76a090299bfc24e79b00381d03c2dbecc722a9d6c40207d5f269d5d352242fe80f88eaa6587f9dc5f5ab80a217e40aa52daa3fda9536a1e3574e87032b60f485572ae4bf3ccaedef8b029dd4af5a536f780967e44e3aa978b8d590fe81d19d1b4ebbe661e503a9792771f5e3a71f3c4d821040f087b17b7c5d5f6e13f7a07a476193173b1b6034a68adf84c9eae035279ab0e9fc4bd0beea287103a20e59fccf8d0d41f3595c3e40625b723640ec876d5597e59922143881c90e2f25c0c5fed2de70cd5101207e49a6ed70fd39d524638a0f446d3d012cfd095a2c8e0c618bfc33711216f40e66ef1fd640ef9d3b8012de5dafecb283e87cfd521a40de8d7175d7b96e56fed900de838e7f9450f2bf3cd27216943c81a10de59302d8bd9598d66a90159a7f6b2d4a4c549fbc021240d08cf5aa2eac2bc6966d1803cd7eab5b49b5ad24a3c03ba736eec974cf766169a01e1b1334a25e6f4ebac2a0352b394fab5dfb91d7586869035501f54ccc5de6e98ff16114206c4cb7d58ed9c942b750c68ad5c7cb7af5a0c6825f794c9eeda102161406794bb99657819bffd430818d0ee2a3bc9d2f34d9714f205646ab96c5c890d7a9a3584102f203653e9b996a78dd576012936ef6d9272e5e4cf8574fc760cd902f2de940b3717d602527ce6bdfcd92ca03f0b4d7b596dab963f040be8e841f763b4ed0a0851b1ad5a7fee88cb1143ac80ae5b8f1a5b66885540786d9251e66367fd3262081510afb38717e5bf65195bb542c814d0a7b32b99b37dc3668b1642a480ceea5a56aea5cf98b40e31240ae8dfdc74d93f8c180285e550d1acc52c9e4d087902ba94163fd86ae795f58f10e20494bcd5d45a1871e51d0c6902e24c3db36b95727e5a4298806eefb42e99122fae96d44b085902ca85cf9f65ec4509214a40eb2c36868dbaedbfa1a2119204b43c2fcc6dc6cff257439080eea45afee41b3f7616c528841c01592ba772d59f20c540d6eba82f9cced9e386c440e7b7fc16f7f8f6176c02c830d0d1f5cbd1a34edec245106120958ea91d721f558b3ba281c1408beac22a51b5bb8fbf11408081967a3767fdc289ab8abf40c65cb3adbaa5dbd4f2be40671bd7a9dbb224fb49bd408ee7496f51492d9ff302e599a517af94eb6d39dd05423365232139ba4088fa78aba7ecb9fb2424b940baf428ff651d65d6318d0b74b6e793c1f4bbf8f66601e41668d793327cbaa837c99c2dd0dff32dcba76796b485af00520b94bc16b52895d42eb7faf4e8e1871628716b2f344ee7d763668132cdf02caa4871085452810cefd35acc9a57ded9bb811e1a2bd043234f7294f440d10a2a3e2aa740f889ead83a7ecce6208e941eaf4c51a99402e1eba566b45d7dccbb420a946cadf3dce516d725a11f2aa300a9880299be3bab94a5c1714e470e1e39fa72f4f0921e280b031d946425140aa8800229775b8ef9da27d0bae5b54f3275634eb10d6ec8c005154f207b4f44737cceb89975021d46b5eb74599b3565154e204c9ce7ca92b3d5f9c6714e97846414954da0955e4d42d4676e858b26505acbbdf2e2378b9fa74ca05bd4b52c223a269052b5d2e9ef05378f6ae51268a9e2e45eb697975f8e251c17d5aa2a8116b552f12ca3e9702d5202adc5d82e7cffebd7364a542681cc24f7e4a469fd26832a90843189ebbdbed4f9a7641f542281ee13cff2b7bb50709c9494e14bde0b68f08217189eecd8913ba84002a159b2cdd7515779045acade769d2f4a7576561c8150a532e95842e5e7cd541a81965ba67439ccbe75902b8c40ca69e9b5a89a259da3669545a0663788e9ffa4a1b953510462ecb4f813fbfd327a22907727cc5c66a5c15cba8208b4d4ca777c556a9f3f95c123c7490c3cc54f408317bc80846405631c3e540e81fad38246973d29f5ad560c81d896a964729b955abd0a819e5f57cfb1532a57ba129394924ca34208b4bc2a9a757c592fe6536510c856995d2afb94e5a3382bd2a0220894cbb25b899d6a19ebab040259b65149f1b93a315925ead5c9c154540081faff2cad2b6f51b9161da3f207b46ef23413aec5710e078aab80b187ef5841c50fe857dad293d83c3e1a3615f0092a7d40da46b7f96c59963d230624249fe3840c175c850f480dee1dbf94961a5c4e4efe04b550d903b2a4bacc4f8f755a46c3e4a4878941450f68c94fbf9cd3ee495f58c983cadd65bd2eca1f0f083de9f9f25aa7bfecaadc01ed29b3985239cdeb52153ba0cc356ab9853b2d2af3c642a50e689d3afeb494a7961633840a1d901a3d77eb378c380794fa89969d7c5f534a2e54e480fc5475e380f81c376679b66f734c2b7040a7d3ab59a6fa1c7bafbc012dc78ae6965e32bcaf1537a0b563e7d0a8f7dacb556903323f29ef16a3ebbabc28a1c206d4b61c55a78b2f564facac012d9e4b8bb2ea4736c4aca861a93ed6bb9534203649b9fae7455d63a982067407971e363de65bbe18a17206b4a0f265541d7c4cdbac980199e9d2efc9cffaaec44a19d0aea1ebf975ac4fd55fa1b206326a99d39458cf1d6427839baec59755275d650ce8df79615eee564aa6979b43450cc84eadd95fcd1d06849a529bbe1eb37a4c3a43050cc8f4203e2ee55af9025a7a4e2b3b262d8d497342c50b68e1847a9a1455099ba1d20584ae94ab2d6ba58cd955b8809497958e4ffd59947f7150d902d225a5b3dc2b17c5c98b09152d582e2b6f39dde9b38072496de6309eaf7db32a5840faedc62c69bd415dc654ae800c2f9eaa137aaedbca2354ac80ce31f5b4854bca055392f3f8924f2726ebaed7a85401199bc734790c535a56d1c0bd920a15109bd6948ef962cb5d17933e3654a680d2aa9f7dc636a78ff1491b2a5240ee69ae68d2dbbded49250a686d97ae637a0febb2498e921e281528a0848b5ae7a865b5ba3755a83c015d6336fa2e4b952e62132a4e4076d4f45a6fab3401d93efff91e75ec2cbd4c5278acc00a1526a03f4df8966cd9a5e52b393129e1f138524a140f3fc7631d469525203c3f6af16d5b592f6ca26ea92801254c8b99a4164e89936a2509e8a8fb622b53fa65521b630c46002a2a4840cb69daf7352e8b423d9523a0c3b3daf83193dba94da418a87bb55bd39d5c3b26065a561fb55588cf0bee28519161a094eb9cea5df8f2d4a24adc0ea504c2404b61fbb272551f5c96170cc4b876d9c2e6b6e87b0303b59af497c6a4b37097e51728e15f2b5eaad3ab853f87882fd272366e9cfda4222141e961d20bc49d8fbd2c77351b0d2fd04a657629af63a2ab05c7391e22bb400b93d14d9607859003f14e20a20bb43cd34e3f73aac2ce1288e402a5e5a43f69f184eb6c222e90f5db61e4c555633adf02294e6deaf8325e95f87520620bf46bbd2c98baaa55dad5029dd36a142f6fc9ac2dc3710e857920420ba4baa43f4b1d5f8b5bba5543641668b549b6f25099ed72c71688c802193ea7fed42d7fe92f16282d6867b9bd537674391688c00265ba2e4a993a7cbebc719cd3e1982af20ad46de9fc47392eb66ecf310c745042021157a0f3c9349b74b3fc24bb335a455a814c339d5cd6626efae0f8133d32d2701a1ca6e127ac40e6cfafec0722ab40991c17d37d7aad5fea1d37c848c10d55a0d427e93db7ba5dd4720e22a940c91efd9ce3d9bbb04205524bf35ae9942fddd6a7c3e49c0229c6637ea994d697e2c5889802d9e6726c155b27b394494a8b94021d655a9de5a031cb743aa440e7f72cc9b031b7954922a3408ec6bc65b6dda7a65122a2408b6aa347e1d14e86bc38cea90a444281f2605a7cb1e3f3a5efc4a4c4100622a04098f0175569cbb4515f4c49486e8c71e3860c5c70030534b8719810f904d29378964e6aa9c5f49a1a60caa37802dd592b5d1b9ec7c58c12e904bac5985b57eadfbd9892be070a8f1c251703114ea0b566f3d494a3f973882810d9044267f5cbc2eb281e6998a426d05a94a5e92529a5677de94c2077d76ba552ee51b9668709d46d4b53a9c4ba24c5be04da336b3ecb52e2e26e650283b62b885802b1d95d12f52c35dc9e38ce9d98a438e30a442a81788fcdd12835c9ae6d7911598eeff0a7942b39054719394e6c12e81b75792d2fb3a52b2d121249a0e5db3f6152b6c579293cbd8e04cab5d68dcaf47d9c749d94a17f82f437382c498f46cb40041248dda46c4d69662f9d7d047a34bdb98e26bf4d8d1a6f46aaf16694a8b19404c177d8893802995e8bbf8bf9d76adf7511441a81cc7c2fe7f29c5da31b23d071dfc48b408b1dd53fe9bb8f5f32452083ea9d703175d8f81a9144204cd3c7d6e5a6f7fd328c082210ff9249d339388eddc00577874096c92fddf65afa602e139ce0739c90416208e44bcdfdf14946a9451d834821d09e0531a5655debe81e1ce78e89082190bbae731a270e02fd3134bed79e6774714120f366512a2d3d2b452410c8d22ab574fbea9d258d0820509a2e977f4087ddd9ecddfdc9a7e4b814600b6e8c71e3fce45356c007113f205c9667737cac6b596ae9033aebd75ed54a7bc6d7f301a9ca76d4b3149fb4ac25b207744c25f231fbacd2fbd1035a566aadfecd0d325280d206913ca065574a9ff432cfdac47a227840ea92725bcc69517cd0ee80dc4d2eb8caa826971233528e1e76296207b476e5fa9a54fa2b77eb808cb227a597966f6e9f0ee878e15f67facb1c903fffa29b03113920b3f0d0b235a54ce6380ec8cfddfc97c35cccdd9281081cd05a8c795f18d5fcda1b1ce7520e1dcb193d44de8070396ab92ee77ba945358e732538128f335c874943c40de8041c38f881b40f241a52e0fb97e7f2bd010a20092fc94520a5a09c71528000a8b17c40010048413983060408c097e16794c1c37520400028270978010002a002062c400428397ab80202700800a0a02c24041080a7b8222940003cc595c909c9010030001b0938f9123392a7a094942c000001003900b2e46639be6bd0d2eaa30994d216713d9ec74c8b6702b5d91e9a2d356d676d60a25352ece9b8bbe377181b9778344c76ecf81d07b061892c41808d4a207cf39618d7a74d6c18c761bc33f076fc49091a395489ea4be191235178e44839791d397aec304933b04109357a4c2273a428931d6748a2c78e1489cc9172820345474949026c402273a4e8c081e2252509b0f1889447d9f13b0c60c3119923058d1cea8c929204d868045263d8d66c4a2d0b3a3202757eab6a850739ad5a16815631a9b3c713e2dfbb2250aa573fb91c6b1b89406bf4a46388c8bbd6923610814ceeee2eb8b668a67f1b87406e8cbf8c9baae7e46908645c9bd3ab1fd7d56ca310a88d9ae5de0c278310e8745246a96539d918046a47b5e8e7f81f654ae138771283efa10619ba091b8240f777ceac1b9bf329591794c0043170410a6c0402a1aacc834b59d2445d40a05d34a9a56bedc2c3be3fa03e8a7ff3ce0f8897c5a3d894ef79f6b2d107a4aa6d516b4dfabb4dca07e4c7a6ab8e9e9bc7b46cec012d7ea89b1e7539b352d9d0033ae7e48a5bb1d15d72d9c803e2652534e98ed2ec7578409ac9664e8dbafc5d7740aad49c37b868bf2b653ba05f9d6bcf2c5b0784e8e95c7dba2ddc63b34107647d7996e5a032c87c3b07d4cb5fdb92702944b38c1cd05a92a5b52b6de2b334e380ecce2b9ec67638a02529b396e3cb2ef30de854759eaf0575d7ad73035aa35cb9ef4adf06c4cbce2eabba8c4aa3870de8175d5eef0fb25b2a5e037a7596f5699bee63ead85003d2654cc66b71a56693d94803c255c9f1ce4ab36bae6da001291b362ad3a8b2ae25cf8050dd5a9516f3edd2d20c481db3ea19c734b82c995906f4cebea969bffdf83f730d6497ec589fb42603c2cbc36739b398cc3120c64d8b3dbb392ac32906a49f9a3ee57a4d9d92c90c035a8b0fb39ecf85041b604046b1cdb2fa559dd365d9f802ea5f8c592d6ac9a4ccb50d2fa0b376e1f3c32b116d7401bdb2f3e78ad755def756c1061710bfb57134f3c7bc5c2bd8d8024a4abd2eaa1dfded571b5a4069c699b695518a75251b5940ea76e19f25dbf3cf8c136c6001e539c7175c5c4f4fdf36ae8016b59812d33aad8052b29fe356fe2aa0eb5f683e2da8de6b6f830a087be955ffd6497731b525c7c3c6143a552ea20d29a0e567a56d9d0ea3a2411b51408f7bce3eb13a6f44b4010574776733e5edf2267d3594890972d87802baa3da181d369c801667f64fdbb65ec34bda680232dbdb7bfceb5913ab0d2620d565d3679bd3c612902ffafea2f2e7758eda5002f23c6df5a56a49024a9d660ff7b37bb53a12d0624da5fe7d59462d6fe30808d997a53f95a76d432b064ae7d6651bce63f46fa5f030395925e788817c9765bb0e0d318781965a6e5a32db36c240984ad74e6e2e1f3423033346828158ad4a9ce997a9334a0103d92545be736fed578ce31c0f131e252839cc99fd0299c5a86547bd746b19e30c467c81d4fb5a4c97efb4ae32477a81d2fb2557b7bb4b261e8ef0c2eeecff2ed0d2645dd692a32e50ab45ddef2d917b17cf05caa3d6182735a9fa1cc5716e6530820bb4abf9ef96659692ed8fdc02b9bbf2cb05cdd37bd316e8973ab34a2d69f52734b540c99decf0ba7af58697344cc6202149c3e4e4648416a817578b9942b59efd9659a0fba5d5ad49cbb296d52f0bb4fe8fab84cb2c75e934120bf4dde79cb4493b99c5e0082c502f371f75a38c71e133f20a47b6b5f3472f5d81fc98857b93e15dfe8f49465a818ef9b596534fcba4b4560823ac406af933cbb676f97db755a0740eae7fdb1e464ba70ad476ba54d5c94eeca85281ba5732ce366e74560915a897c57f7157d6e7ddf42990bae9a5550d1bd5be9629d01973bc18f7351c8c94025db2e4d59f6ee76c2205e2f4eeea9794314fb2915120378ba5e161fef57d140552e58ea6f012a249df9150a065e1c15b103b296fa5658c80029d31beb67369fc09b4b82f5df8e6562fa6968e2f393129e9e13bee4a30e209f48d8d7f6e9764ce5ea1f876ca8e35d209e49b14f7a8768f7002a9e50b72633acb1b73a294a4a098e028593c68641348f37c5a3227a9ce6ed6043257d7251734ed6f4e473281d44998b9adb447308196e3ced55cecd9d8d92590528a93fa499b2c8176b5d5e89aca4aa05f8eeb5a7c25340bdb1aa1045ac72badbb25cf24505a520b2ec6bf9240ebc7f8b2d33ca78b7f24d072c73eed63f7bcfe20817acd589f75ba6062ff9147a085ea7a59cb52c6116839ea2d219e9478a411a82de1c2b6beed6eea19812e5f4f2b54a75b8fd91a616411a84f9af3ed8b9cca091d45a537441851046ade93fa8d61b5fca4339208f4aace6ab351a8a89b2388409fd6c95f5e7b789e8784240a238740cbb9c4bb9215cdbec133460c81164c36eab1f1a464d06c0d2385408b2da979fa55526a99b6618410695966d6ba8d492b8c0c022d465d7a63d4eaf65f7bca302208c47bb6694cdd2f8e66212161c24820d06ee267c3e4e56c368d310208d4cbd8e2b87c196f637f40a90b2fedb3d8dec96e3fa04c8b4f9754b60c6a5a2e3d0a19237d4049f9b1fd5ed21a7506834f41791e255a18e183c96529ff73343ab207649c1d0f9ba496e2753b4e4c50b0e3c4648de80129fe2ddebcd47963ed913c20b32895b88eee377fb294113ca034cbb76fa65dd2b79e1446ee80d2ad633a2d37ca2ce7a5b80c484870a4a48cd801d992c9d997b743c27540fc9d7e318eaf4e9dbe931494a60352679fd7e2dcbee89a1a99c38d11394c60240e70e0c0c81b3430e206846c4caae146367e35d206352830c2864f3c4c2230b286098ca8012d06933ada69df9c96bdc78da401458d37a302236840f91c397a94a0022367302366b8315206909135909ac374cab7ffb8bb92610c0f1811434965240c1a1801038f7ca101235e2891c0481750505e470446b88038d339657e9999b6cfc816d0f2638f66dd98a6be1486112da053a650cd518b2e4fab47b2103282852b20b37bd417dce5c6eee90a2356a88c5421c5c4e46401235450e3cdc0c0c81476440a298f12859111288c8c3c01078ae3b0c088132e30d2841126406064094a1849c2081250768c1cc16439a0520c94141e8fc613c303956120366919b365a5ff5aee4b78ac921d289e46c9a7f8490a4aa6092ac288402518c0c840e51718a8f8c2535c95f030c9d14303955e20336759cb397cdbafec547881e214a8ec4202155da09c98a4a098a88001955c54a0820b94fdfd9dfecb9c3699e2af8c9fa0f493cfaedc02a93673eca8ec7447a5f43c722c7bb628e940a51628b440c992fa5eeab328d5bc59a095c798e5df13dfa465a2509105052ab17840051648f55837b631e2aa3e222aaf288140c515280ea8b4026ddaedae3dd3a5175d0d12920a2b5027567a382dce4bfbf238ce9d7c1eab71c227a8ac022dd635ec26f9e038b73da8048d6fa844d2452251200e87a2308862000423a70705631200001014120cc602f2704428d5d5f5011400054c3428524832242e20180b4b23a1401c108602a140208682208a622006c260a864155d006e55ade4417e41d101be68cb08ed4e2a341febc9f2540a5888956cad5172244b23f468f5708fdc5fa11e7529d04673bb0a074d5be6a5e3bbcffb8361ac6d394b5bdb6b1284c684d8f427d6f1bf910f10e88d779c5ef3232d1347503075eda15cff437c3d23a3fb44479675a9b74910537d0929a7a2481033403a1c541068751eaafe2778e8e2ecc855a472f192358ba5b310523d4143415a59133331e160b8daee59e429a994b71cc2d278f542a4c6ba1ac584bbc87111794c59e172ab57f459ab08d0ed0246a27b32d19b28326d4cf731d604d1fe0d0cb5295b531bc08171da508d9ba85f4640551373041a451d60a54f1b47a68732a8aef3a3a5e8a02d01cb0ffa5982944c7b11530e74ae79a0354aac968739047b1b52c2dc9067abd72f98ca5b7d236ce2623ddaa53a2c41b1a981d636b467a0b0abaa5f6a5ed333d5be05d758e3f0a31bfef598cd60ef2387500c5e1ba4938469d5072afe2433e0f84d1b5036d2f07e44c83e1ae762d62202f6a66f95f2c8c9463a2d626dbc822556f4f921cdbceb3d5a493cfaa3241f28ba884d60a110b0e4ce8c6ae2bfda3cdf4d7ca4d320983906c24b23e00a152c1e489605a3af0211b46662b2157b664fd1480bd9e58e3f00c58ee3aa50b05a4e8ba0f1a046b6b6e3ebba0cf4369077f95ec543267722ec3a32317cefeb4e2eb3d1252f4ab409b4dfa82b6ee1a734e4a2c70de43b8a6693d0eb8ace020aab36620aaecf452123547ca1cc13b4869bd4e6922c6aa65ff429f3c8df9e46ba18270a5cca75d3e60a8cbf9dfd86dc732351582248950de6cfd9b10149990835c33565c85c6310aadcf14cd3b52b919d0285554265c41af75d42586dde5e347f17dfb991e7106c626ed2ced717354800808a37c3a07130e22284013d7cd17a81f569b309532099e566b064fa706fde43cd646f068b2e9b643f123131e018b19f0587e68f88ff240a9a02ce63d0a835a26d02701d56e5547693d56ed25735e9d26572d40b3064ff2b7e2b2fd87112ebd7d57ca301598586e8e93c6dd76a8a8708190d60f393c770c4995e7c4bf96491b9e59ecb44e992d2d606cb87b9aca956c8937627c4bae36267be44b25f3c4d5985496db89231d2b8db92ea7dd06bba7a46b846336c4ad4187622b712a40b496e8843052cab6ab0b10dd206cb8484f4eb02bf20614c58a449994417a9547ce00099c9d2a64ef80ae6a07e26c154c715a7ff80996b206eb416bcbd01f542bb4cf6a1ba68a0535772bed7ec8bd34f3bdd9036645ea33490e8ed704f7ee52de9d5b6483605de86424a8c9b95f9c3b90ec317a437a9b32b12a4e8d88092b68f7b32db2fb3f9dbd77c5be3524c89efb2bbcc949ea19de8b5d5442c6f0fbffaedd5fd06dec5f5a91b1bc2a1456b1ad5a6d1b44c34f286999af3d9c23f8d68d4b55114b8f99af5f3169ea0b98c8642dd19e9bb528370b3f5100098f632ecfd64eaaae56296581a8c7a14bccddffb0aff519a197f3d224a116fcdbfdc5ec96f66b4b2fe985cca65e1742e380329ec95e966fc6604b4ec1b0ed3d66680fb55ac927022c572edd8fdb1b8d56801b0a3ad7d036c68d2eda2e3c6f06b0ab02a773dca9d0c3d03ece7f5749ba0e276ffeb69036ce1e3901fad9892ba73f870186cc30013e63b480dc9626515bf8313835777ed8434ecedf4ac0ce90fa00f439671897ea6f56c6d8efcdefb08607b03143c49c2f13bf5811723ecc8567eea54ad3c6c503db8c98fe11cfd810b4f64b43fe8e4f0c74cd4813095e17d8527b0ca505ddc9943dc1ac15e3bf8024011b6aa35c0cc3f4194b17773e741221e3c0b500899dd6febc15a94abc368d52ae15fbbd5b700b42713108ffeb9f1d22a1177f5de4acfbdd5eb98e9935bf1a3cbad614b4069798f86d8735f3ef7a1ed1cf73f9b7b846d645036ef929c2e46e01d99cbcd47e3ca3ec9cb589bb13984fdf9a1b409d4fada0c09927bcff4f2316bd3b060f35d432ade666e7881dc64b12677f35475f545b9ed3038cbf6b397cd422b04fabfe3393e56901d21108a8f9ba5edeb50d102f27515f3a3779b0537244f6b79f28d61768b3e67ede01d5c262f5e4bad414682bb0af7d0162f9bb7e9a2da0362f2e8e091825fe9da3fc8459048b21e7e92ecd33da4007b5c7ca08ff6aa08fbdcb4a4db5b5c54ac55d8fb7524716019d85c5b20a48098bd0c497f9a2538815e70926cc2d032220b8a9c1c952033c8b3008192a830e31d668434348e6f62974fd27cbc598ac8eb250cf4c152f89d709b086bc5eda68202769a544218f1ceb3d4dbf8aa31d4d851ef3cd8693f378d7ff9ae7823528a54416d5b58f0b871c802989c5ed407cab85aab17402875c116149c059442de321af6e8841ccc9f1aab46f86f368571130aa587c8af69bb7de7fd1ea682794309e32adf0be330e1cc5c617d1fe12434adb8ec68a98ab7bfe19fa57ff18bb5918e694ba0bf3d8a5cba0d82cefd96452526bf3a94bbb7f50db1939ccbdb0581b01a4d613e8a7d08519dcf5a890e71d58e99058c9e674b9310c0262d70825f582bb4ed40aa082c9d07f925cf9f5da122bf7d672e75e28b4e08b9053784f0b2f3cbeac0e020fe91161a73df72a4960cb7e70bf51ec10a6dd06c27656da5ed8d9c68fc7c82c85a2f1fcf128d769d313727158a5a933fd602bf5c850a4d13430be7f7254a39c37304f12224a29e968bcfea9c2b833e27579390652c5a1c1a2e4242bdf13be4982da430ed61667a239b2b60198b6fd3960e1543e4f7ed3c28e5fc1eb4bd25f56157748610a19cb04d44d236bfce13524d2056a235649b045176a187d892ec1497428cb0854141bc160c435485a45ebd19c719a26c41ad0b4144497b4848f5830b366c0e544d70e205b62809a986ac3cf7a431e1c02214e1b8859a02bdec90283a21a34266772f2c236aa8b054f64bbdae8812da0b3662d42c7e30c0912e49d1b0dd256f5be588bc2f9d8bcf1b34cccca159aae08c86e6d3908a7d25164d5afe809109a8357d056a61ad7cce4ec8c431d792326de5314aae16b1a8af298ec6a806c79a42344b7f3c59142404e40d5898ce3191bfc5dfaa49e59830158ef8442f6d1f45d43beeb4c61d259f3f1784fdb0920cd22407a1984253d0447c957e9097c28d9420a38f4bcf569cfb163ba8e47f190faefc6ffbc5a1b7b3e9018660e56b4fbc447a5e57b256c36a442c0f0fee12e14db4fabc63314194632729d32a5ad8aca32215c8ed48e7706d67cfcb93963328aa0c41b43efc7c431e4800177baaf540ced6e53ac9c309ad9a4925787b05ff37877f06704e78cca3c528f51b76a385fc03a50b53ef2dea6e4d23e1dbcbe90fc83247d34d79bbd70c2dd9a1e001c20e824514efee58286092fa682121854e9202e0df753434a748e8d75a7eca32fe7f47f093bb302bf6b74f55c94f3033d95fc25d2a5807c94e804b1d099a0f4209a0ba0250a09e6289ff1823cc64027cd959fc1aa764eeecea58f7388e78c7056938a45384c7b8481dc3f7946e98c5e2fa6cc98252e63343f324cb487b2ed495d912092a8e34aa8e2d5dc46b4902dd0999bde8e699089b0915f54327c89a2b054c5ca144f5edc58ac7b82152904390167bc06bbe6b5d5579d71975013545f00d11d29f219e7d70ebcc568904185f4a8f9c60b3fdbc846ad37ca549d4af0a42584ee9e0c159a95fde76026667d5db5ac4439a7eec677f7c94c5898e3b98bb4ff45d8c6b6e8a837af41511f49b8bca8b58d483e202ea537dd126f532fa17508121c255824e7d3103570b0b6e1b5b905ecbff12eb3a69ef3508791704e2d9ed5771d7498120028854f48b085780b765a9635bc02cc7c857048e8203ee3beeb24682e6cade59f1a516a8834f18726b8728b7ea94c641491e8ce4fd6ca27327d391daf537d39ab594402993fb3f48a215d62cab67aa00ae0f37da9f14891c85186ce0af2c43dc9c64d6efb298e1ffc309e668f610273905f6b2b4c6c66e5deb23121f266f3a041a5501cd87129113fdf26053cc003429bc13689f7c3ea49d55502b3cb60067b5f64691443f466ca2260a70795096bdc39363e91a70cad32ce14bbf8442069684f78c88ad3cea20c2019936e21f101bfc0060422351dc5b6cc8a98564b56e8e5c06281e0b12d4b074b981e422e4c42fa459f45555b297e70a199413d2f3850d4106710e8fb00757f13b924ada4a1b53b4ca8dd61952523bf9122c998007e2816bcf55f43073f94e9628f81c106047f72cf60008f3b6079b4330aa2a026ce2c6f90051769b426bde644d60d09b9dc3875c3bd2a7c1392ce6d94b97fb07238c19a4240964d84421d2b3e83a1996811d26c7e948722a4dc31861fe5111d6fa02c73d82f89f2c25bb5dc01b27708b5209e998b40f316bb6dc7a7f47f206b526ac3bd24ebedcf6b1132febdecb1102015df8ce0451483dae9e121522b5b4de55b5f17f3f32a70a842a7daf3e1c08b79e344f0749e6529ec67bbd96cca0f6124da5dce7c048703ea524ee8de595ad0926eb549f31316a075078591f8b2131785cbd85067d80d268b653a125d39448dac3650b1fe1b3fd15ba87bbebab1298ac1adeec17ffe7ce738b7d931d4f733b4a7dbc8151cf3da6a9fd52e0480969b8a1078237c4cfe46ab665759d5c5e3898a53a091b9be33d07a12c2f557f213d497f35bf25cc3fe787b6ed511333358ece0a6d1dba56b4f3691787a6833c51b28cb2ab807a736d475572eb776752424142afba480c94b381c0b3af3feb8eeb2048f83eea59844686390ef221c6a5fd7bbb2641063b801f3b462ad52f1eb9afdc08b2616c642859f53c9927edf25aa82beca5951439f29553758bd962d20466277851f7b44961148b7caf2c95479f965ce2abeff019272471222ef5d9d7a67c36e1bcbaa519e33b498c0ac3bac3015aeb63830dd489ae9d243a680bbf8043988f591b82be0ebaede1588115ffa917bf3f082ae04b6742fb9ab03de06406701f9083e20e7e86fc3d090f704035dbe3d04ce3374cffb9d13f97f9de563bb4571c435e34b5ced9fd60469f5a0ac53b3d0e3e4bc6f30657ca2c005c3d95ac15df3394ae28f310035fda92ab0be1cfe640665ad6b735a90da7e3c9f9508310cf34dc00d8231e70c230574bf2ed6a961e7ffe275380d555bfdbe76d765a3f9cd35a1dbb3f86fbc0aec8efe71b675feb0fd4a1cdc22f9d138f18fc9b1de9338d45cad54cf58b14c84a0b5be281e017afba8152cafc3ae0be8bb46a248d74cc7ca37082a1ad302d81d61240c5ba77c0903e36a0f2b4f736890f81febe841a7c78999fa2c03f343ac5badb4997181ed8e283c29e9335c8d9851d24741ddbc2e82716ec43a9dde99c0c238804fac81a0d91cf522312beeba078053f2e577627c18ce73b2a0164837729b02c11267399b203c96e54276289e28a912362c255419fe391e9fc65b2701c95538de10b1a6655e53400aa3329694da04fc561dae535493f016a8b4e64fe89320750b057757dd30cdb332a815fee349398f9bf0f20bd9c8750df367eadd2de628ac02f1a4635ffec925232a8dbc1454a850ad183c60a301af9ebbdc99f884f6a7d160bc43841577b9996821ab078327f81edede65aa37387f0032a0782a8bfbd30802feceaea32d703d8992a802a8707301d234a346fecf76601ef066f6f40714e4c9c9576da9047ca8344015eea17268240589b86e55269a5b87e7fcf2fa87064b0dac44551e789adee01aef7709d43e7a99459e4e8017c00ed086e5c8e897843e006c89232ec132c28bd42ee5e90c280e317a7e67a7bf9f88e5cd650038389f978d468542f52a213c86f74c279eb107364786e268ed9438a6e99f82ed44f5e955a73e50260fa5ae91f3cb746071aeaac06e714909164a6f7dccbb96d080568a37358f85ce24f6f1e94c8c5e92f30458899c6d5e4f093133af566b7677624434c74a2722b39f018a3aa9610595d72e2fbeec95ccc80b9d8729a4d459dcebab514041b0c234415b4e155b7e8c7da200234216e04d1da8ff6def00ab93205bfd1579ba88194bb387844b7349bd5adaaa4845d1b2ff7e548ba85158c18fb23c052e97c6fc2607d45aaca7da05f16b99063086708dbb66559644851479bba0c131ad2ae8c69f8f0369de1ef57141b0912eefc82d938f08a743e992baad0b1443174dca1346e0b2310405d17913bc898658b564ecb33b62f29919be24852f5d5b38ac95a617188528ca285399936af97957a6673e80cb3324191e0c8b28323da7678dd3965f66ed250904799eea3c6e9e351151dad907ed025004fdb2832a689e008e65b5878b6c11b02848fa49f1b46d39f0eacaf71d439a9d42646e3b4388dbb3ed0c18e7619ff305eb5186d3c37f4920069ccb8c979e641a09553f9f685de6539b56594c4178f32b8696d2b4a2e447db8131024f84b640a39f1051ea5a4eda5af495338b3ff2b040374725b6395f9631397d8e29575146d07940ab89a3a1cef42617d023841f83a60169e03225d96fb62f9b24ca1a4ddf3f452e7e6ea2b94070e851b5e1310979c43d50a5c569f8fc46a9a9adc580c05ea6e3b59da984121603f3e4d14378079301f04923f8126ed8df961e70e20664812ee6329699ef9f8b7ae42140688c75500214d889e0422d2340627bf3e0b7626ae0295f24613b5e0442162f5e79b9ebf8694bf16b46a8e7603405254bf06af40557e98f82ec13fddc62a704405b075edf9eaa8c44c08268f375698d01ed5b65b5533001555638ece725d4b0e0c20fd0336e7332d3a50755663cf0b99e66748aa740d580d52a5a72d5e8462b903ea70a0f7f76a437dbc016eb0dc7d9fa4a2d538a1da8b501be19417eec6734fc34f4d0f1fe8d0b53597dcb55ea494dc1401000154cf1c90e9735db8a61d79604713c6039574c53cc27963f8850664778822eab40128e575c7fe22d41439e69ba36c1888bc545dd815a230cfa0d40b84d05bfc67aa861a41c2eaf59b8488c1a69e5c1ec23143010684d55493fe0503cd0db2cc79e7cb299006f5bc0069deccd3a92aec98457e589b91680004ef5e06d0dfa42fec72c1a4ec3a7a48e9ecb129939d2b49a77d1796368ba21fe021065b769fc9978fa793efda463843a4bda1c2e8a1e9382e13b0d36b3f7d56496e9e4c89157262f7fc389f39e21a5de7d9f7021e103c3471afd4e17bd11bc30cdb60c80e97725c40d5635c0a4aa2ebfe53f2394be180cef29ad8b559759682d861ff5c41c0e7954913d889fe805337ca8676842c56c85fea794651ed532535e83935f0f75ff1271c52793788e86159a2e07c74fef4c40f350ee1cf8f942cb05f507a8e7767f8ffc44919c5f8f9ee1168441f4051c63093245f88a8fd563129a79a5dc7fa06fcb77b85061a355000cbe5c351a4cce9e34f3c2fd5ccea79e84e0fbb1161e6f4d8c8a1141514720f7c54c93dabc799816ffa079598515f91f5045f632c1c21da710ffc0098e00da53293242baeebe609a11c0e3abce1f82a4b3904d4bfce6ed43a5f3e173cf3afadeccc6ced295c201dc3c7bab45229a59469e7023703509c518558bcc8924ae6a9fcb2af2c4bd9e4e44e744b2f60a11ea5379f760dae7ac94887f36c8a19f1ed733c1db298633c03d26b2ff2b93b14111723a469ef82c9772ac8610d0a51a3497cf8593622534b906ae4120b9fd800434a3a30af418df01f31e6f3a3c366bf0a94f86ff5cc7191d9144d9f9fef52a2407171391bbcabd04260d3f8b7105bb6074704308559ef8aad2f39ebb4266b9ee1531812f246dbc312a2e52534386bd1ecb89b08c391ed7eab44c2d65d719f175d6ca1428295fa0d3476883872170450b99f9a35ba87c4693cdf47824611528de5466b7587f5437c63e886afba563cb41e08adcb09ea230adeb848838c8175602a48045b42d7df0f9cb652ced3e6d85d647a33c7842ee6bdc43a26080886f35f59c3c306cc221389490df00c82a01d059de097176f840c668cb74626e7b71bdeecb813eb5416db0b5c938642930f0b38e581b28d41741c1a60d68e945544415019b910984036bfcd014d346cac476f06819ce10cb48f879d728c19af7b68b939f0659576988c52982d9d2e8ab4a473e8bffc5b2883a5cf869da28c4623b973eb421372596fdafc010aef9dc84212b2289c11bf7fb6224175e6a96211ed56c6905427f00ef51e180f9b17f2222a22c2c07b8787c39b1b2b6812f423176fec51ed633d19e56bf34b45e1b1f2ef5b7ad2d4000f92d2e8d1473a3bc0a1c074363d5856db0c4aa4dfdb5e637ac12f48a03eca919dab25965028d77ad2cd01f511854802cf1c0f21d2bb081cff7f8e756a81cd20aa596e4335ba990aafdfff3eb1696b354a9b752904ec4aafb5c3587974cd501faef8e2a5195a76b59cc6b00cddb095c8d6d72d1b06dc8b601961e7a6d66575e885a03b0082da11caf578a3637bf4d61e10afc7b4e4b1b5375962efaa475311f266da9bacb177d1a3a90c7113ec4dc698bbefc1d487b8f976267fccddf7602af320a0cd833c3b0f62ff3c68197a9078f4205fd2836a480b4804a6415a5b78454faaed021ab21d82b9f0f8c6920ecc0e7a4e389bb9ce74344f0176c6ba50e926ccf5131de2e21f66bb0d1aa58d998d48d35e357b3a856e14f20c24082d51a5065a8534bd422101df82b854252972721d16d01315d68196a16394d5ad9843081d84e8744700482896a719776b99ea4afd89313896cfeffe34efe7d2e307969083a93b61c56c9cd139d34274a1a9b28cfca5c6e37dff6e013509b7d570d4d5e06aed440f938b7c83c349cc1b100374fc91542ba44f10fba9530eb0e701c70e30c51420316a534259cb6a87a19249b5a590682d7e502639e36f58a75133da6cd53f210b71f4807c19ca50c6c02aea103ab516929db7f0c3c262089bd471e4ef5cc18286977adea0766d569b7e81f959aed86d27c4825722cf98e255c14accf73f601ab7a4a6f0f3fe14ff26db90ae64ce8019484208eed4b58c767fc3eabca251bb1220e887efced8fb456968450370a55c94c20ebe0fc0f714ff68cbf849ef6d139804d1b4bedf655eff4e2abda5881e71388b4035ec7805c6f911cb476923ade0aa5c4e4dd8dc850aa046893f97e199e48b5e6840df9a746321f2889b2b8611608cfe923e3007f9dbf30aa1f9ffb991460e59504026350c6448cdccc4041a9ad3e4f5f25084fd278e8609ea437b43ccc1b37c665efe2092f34c0248727d6d2344a0a9d4357253092c0df339a3b157991384d88179070345a9e0d3ae0a939314274426e5350ba1adbe2709513029bab6b312749c6072a2a7602612975522a57d77db684b4c8d8ec9f1002558bcad6b653044d2979d498f40e014e1de1fccae17da24c58d17ce001c23d939df10e21ee06b0cba50e6a6e6ab2d878f8f54ba932875469b64ea50482a318668904969ef7ac3c9d8fa8dd881109af81cd50d45fbd0cfbe23be082991fad8b3148df92dd1f13274fd688610c62f6938dce7333a0f842cc901f30c2754a9e3913e8cf1a1d42f8303f1b9f734a0fad070a057d84adb6bdce777d065c4e070550b7b2af62fe75a318ae809ab2daa2a5832f51747deab914b702a6dc61f98f7805b99f58a02156d4a6f3b0338ea898c51dbae7edd2649b6e91d3ab6110af7febce7a0762092032bcc2ddb3e0a45cddfef60ccef1786ddec06701fa87be5fd24f8dbd9459a16033ab25f8b83ba8277378ef7ade7a05c9898ed4cbd98e0476d10da5746d19c63cd608807be4e160f7e361c71ede77735d06052f1bec6a67908eda259a6bee06b995e07cc080a8baa0339661d81431fbf7d6db24320f1bcf0154175d7918ecf2766cdb8bdb3a24d3cdf47ccc7cdd26926eac954c96cd333d92fa457628f4d5f831b71d0f0e976362e44b3f05a537643ee022858384a38b26a0f094da6a7dff3f0d7c095f7370823be58e7d98f3c555121037476f06dfb953a4e6ec52ffae1b98d2c905e2828b0a03f1138c9070e5f82e628b2489e5c11c07a383c3865a65014af67883754974120e9da67ffcd6b41014c00465e03c022c269e6e136643f4add6e74f4b3d9e2a9eed720beed544c39275ce600127d212e934afe80e61edd98a5b5566195863a818072d732ce4ef4df4b67857770af606a0a3de84efd48add9e7f9587360566d15a94d6ea3a4c34a557f9b66bcf2423e246b84aea72decf2557a09c5548a35ec4d98aaa436ebb59758911dcf04c4fcf4e3db0dfea89b22a9889d2fab5050b4d7d323097c248a13041491a466fb06e4ff2ce49b699309e08c4865ad18c068bc214a856a5506c52867fb0180d024480a381167909df685a7297e97424c127f896252549bfad90a8b9e1a16128957518a587df4d3b1c49bc41a64cbc85450b901234cb688e45f4cfd0af792021ba7f2017567a55d5c562ef9822e951c1759b7d1747c44f960f0fe00c97ca69f00bf50def2053f678ffd08be685e5cb9ac202448e350cab4c820c1f3e42b783f20c595ba7c97c82b03ac17811e26854d509e8854a9b0e51eca83bfad19d9d8c9838a39b01765891248a2f333791f50dd2bcaaf8ce23c290413e835c76447702f40d7f404037abc4d05559437848f616b0857fba81022c4653042f03936f70645ade805034dba2de7bf787981609a44340420f94c36d1eabe2609aa21f9a8362392998d65184e542301201f3acce932b09a878fa0d578ac918ee91cfe81aff66c87d89c3f21abf94703feb3d463c983a03a4da8af2ae27a2442acfb0bb7971f12f76e60abbb34c295e702551dbc7d2c66146919b4a344046301d30c2d1a550ae39145a3e75738ef93aa181c25b3016b69ab74095f3b540238471b50168b31b5a6b3c8d7d47745c3d83d54c8ba834b44150995ccd20e431693da14ed02ee9444769f45b11ce5a03cb3f2123a1667888c79482e849ea13d4759d626cab3cac88b468a04412dc907060016e45875640ceab77b81c8be1f8684afe9e76ce1fe79e3a64776d815090e64853243ed37ded7bff75279429c99fd1b4ac3579c95eaba757f908d274f7761d89dad1af789dbb0310dc2cc5410472fab8e9dca6955b37193e4cc39fbdec5b2a406e081215f32be64ac9d37d043304fd462d6d6e0f49b941530546be4982443cdf3df24c17cd6e2a03b7e38d895425e492aa9f6b8a3a4de5786bc9ba5bb9e3166f9ec42f2abfe1a3342581d8df21d1ea6e471b357b64e83cc93d91952f1fa3e41131cc4b37e21e8ff077454ebcf21ac4a81cbbb87914bb6e54cece7c4ee5cd9f06600f8906fb6319fba37a12911f1a216c37a85483d16e2f5eb1c6373bb96488dce44b8288999cf613e808aa0eb82091f1658ee19e52e233ce7bf72cdc00d86c06a867f8ac9ccff205c18a96644b6e7b87d409cba2e8b4596429e0ef3fe73e79540edc21b7d9db61bba9202d7d161940e15b1a132eae93b381665e8fb14dc656f9a0d12ccca7a78d310703266d9aefcdcd3f7a19bb56ab28f2f35946c005cac084bde42984cf03f17792fb160aec09b8be8083e7840d1b23849d15ec444d551bcfbd117ee6d788e69cc3d973e5a23fc1c403702ddd17fef4795b462be31d8373e4ac932982d171bd3b85d03e2d46a49ca8ca3fb016510139d0269cf5d302d65cd2712a5b01338338f9abaaefaaf472d2682fec6e1e440b4449e0c379d9b90b62738e22130bea202781e721c8f47ac59311942dbc4b907b87434d486a25e54b224bd1c2e798f5b628e6df219fdaa4fb32b41cc6e3c606bef40928f164e7c0999c9a8dcd07f04fe59fbd31823e48b9746b17dbaabdfc146b30cb0cdcb780133daa59e8d7445823235efa4d852391c36acc215edb9b9815a38af7b8bd921fe0896d6e049dd3d5ded15dca3ac45fda4a8aca83f4ec5bca5c5290840e79c2f599e366d65fd847bf7829fd56631a1b3adcc01ca2fad2f8d2da36c7aaf48bed2e49fa1fda2af308ac12d10191ceea57449fe3a309f5d60bbfe4fdd39a24ad8dd520e0631a56d40884d975ebe7faf0441b683c1a02db00a35317caac65c1e8c992199bffdfc510649a77299d76d2ae720a30c82c1091100cb40684ebc4c517e6b9047bbec196915ac0d8568a0172674b69f789cc33b09124b39d7c34e85240d3a015c4d9aadf73085a771c694a793c200bea7992eed0990de605facca0d92bb7d017a6c195ed17ca72c00ca7156d3a982f95d54db1592caf107d90eae495e6d8fb8c33ae8ecef2162a205d02700036f2ba5b1b877af31517c9d36d416e093ff6e14c7229221ace41426e5ff88cc1d2c51acce27460f1c0338479f9acf1031c8685b8cbae606a2acc42b9b73a8838c32b838e8b442f9248b834336a502f9e400faa2f404165bcc091a4b4d390e15f16520b436bb8337aa57c397a50f0e8f51072732ac788d8f4495ca7c7233ec4479798bd440a0742206a610817938972d4208c943e1ea5dcce11d037651b8ead50af5780ace0c548500734e5ce407ce8fb150762391cfe245020cd373bfc30e67cc7dcd37bd7e87f6f646e26b9e4eafcf8f62cc2eacf852bb04b115c86eb86f0f66603a41a98f5edd434e1383cdf78cc5cff7fc50239a048529df331bf78f61fce2c44fffc08b58d4b2d5051f6e9e1a1194ee655e011938880b5538706f3b3785d194021b4a9fe447f86d65ca87aff1b8d5f7c934c39e7d708184da438a5f0170904344aeac51d860d2c7cb969fa98fd6a2ffccb15a26ebac5ae90d09f14e7e84dab12fa065916e318ceedd7e10b0dadd2052ba3296c8073e6627e25f01484b026f0e5c9c4d100c1b0c02193a6b224617bf37614ae319aebe0f74972a13767137c0e59fe112d854825bb1a94934c17c3d909f76fec40cb818876d98fd484fd5f6fa9ed1b689a7f8ea45d1f8a0891ef62330c1774d2c7c8f5e842af7c29b387eff1a8d01d53a22f00e42e1386a98179813d7be0ebff3220a0dc233f13f5678c5ce4b08241627d6db428f48e0718ce86dac5e04388ee3aa93e1be9c9e80c8cbbfa565d89cff6a7d28bffc48b83e03679395703685bdeaf1442f2b6e78f138d3182055ae7b4de2c597bf6ae0b65a529ca88a05f71952d5978f796baf42f5f21b60ee39bb5d6cb08e994252da400f9906a31491a545e1de65ee83f2a9c2955a17558564f28842fc8e6dd77009a088ec844cdb7ae5c421285bd1b9f7d75cdb36fa8f9b90ffcb50b61ee03553e6953722e09bac856957b63c83f4836a443ff017cb5e8957edb02c2ae8018c9a2f116990bb1b761f6352d64223439f65200cfd29b1f038b04d378654371c219e8001f7f5728c9734870c7a9c0e1c23c14c4c3ecf178c01426ea4a75e2714545046a5a3d8d477c61295c014fce751f7cbc1898c01a38edde76f116499cd3cb6d36d1490a49473f5be223000bd3656eec498c39c65a56fc1afc74d7c22089c5a6111e532a63b6852d74d4cbca6e1cbc7cacd1700a62261ba64467666e053aa98b01d446aae2a1cd83182f528988032726a8ee7e22803a5a010e5ee31864cb4398c6b2ca45d76fcf543d18cab8fced7d423d809aef834da90eab4a21605dbdc611c10d8305cfc2eccd4beb6e45edbe1ac3bc9b22b8734cf1698386c68425c7ca58382010821e4fe8500da5d301b5fcaad406651fd3b59acc107962e4041419240e0a0b23fa9ed0ae53040596035764d941354ea4449ee89c12750d1518491c1802923fbeec8ab74fe9c8f61c2b7e6767cc4bbc04dbc12cb4b1acc5ddd8e4f882c1bdcf1d142908620e77c551ae62dc7fdf8018b369b604b0b85790e74a4313d7efdeb2c22b6c2faa8c1573f7145a17eb74cf32c0d2623027222bb0451a029d48a8191c8e5195d05d17a958993db5a72897c33c54cf2003010ff1996cc183a13fe8b047571f3c7558792e48c2d0519615be2baad92e25c61d028448f2d341ad995349c0d43791ba2cd39206bba97ceab96bc414a4ce69fa51418cf37d0d5014fe41d7f8a3d41924ede9430ff079cdef8c254fc9e82a8cd3362037fd046942cccd32c8511c32f00ccc206f2b5f5aa25418f908d49bd2419686ca63dee365a1e230a0bba1884057ac6b2e6982483bc6db5c5ed2e198343497cf3410f5ed1dd0eea0634a974bc9c2050f614ee0c74536269a080b5165aaba32e377f0bc8d658da2ac5d12f19056796ddf2b8df8c0516693c8e57483464015938ae24615bb2056eb207e70881ce177d4315073b056e59093f77596c998de751833306f76b4796914679b901a02054fcccf16d69b67e02", + "0x3a65787472696e7369635f696e646578": "0x00000000", + "0x3a6772616e6470615f617574686f726974696573": "0x010888dc3417d5058ec4b4503e0c12ea1a0a89be200fe98922423d4334014fa6b0ee0100000000000000d17c2d7823ebf260fd138f2d7e27d114c0145d968b5ff5006125f2414fadae690100000000000000", + "0x3d9cad2baf702e20b136f4c8900cd8024e7b9012096b41c4eb3aaf947f6ea429": "0x0100", + "0x3db7a24cfdc9de785974746c14a99df94e7b9012096b41c4eb3aaf947f6ea429": "0x0400", + "0x3f1467a096bcd71a5b6a0c8155e208104e7b9012096b41c4eb3aaf947f6ea429": "0x0000", + "0x3fba98689ebed1138735e0e7a5a790ab4e7b9012096b41c4eb3aaf947f6ea429": "0x0000", + "0x3fba98689ebed1138735e0e7a5a790abee99a84ccbfb4b82e714617e5e06f6f7": "0xd0070000", + "0x426e15054d267946093858132eb537f14e7b9012096b41c4eb3aaf947f6ea429": "0x0000", + "0x42b50b77ef717947e7043bb52127d6654e7b9012096b41c4eb3aaf947f6ea429": "0x0000", + "0x4da2c41eaffa8e1a791c5d65beeefd1f028685274e698e781f7f2766cba0cc8300000000": "0x080000000001000000abc3f086f5ac20eaab792c75933b2e196307835a61a955be82aa63bc0ff9617a0600000008d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d8eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48000000000000000000000000000000000000000100000000000000", + "0x4da2c41eaffa8e1a791c5d65beeefd1f4e5747352ae927817a9171156fb3da7f00000000": "0x00", + "0x4da2c41eaffa8e1a791c5d65beeefd1f4e7b9012096b41c4eb3aaf947f6ea429": "0x0100", + "0x4da2c41eaffa8e1a791c5d65beeefd1f5762b52ec4f696c1235b20491a567f8500000000": "0x00", + "0x4da2c41eaffa8e1a791c5d65beeefd1fff4a51b74593c3708682038efe5323b5": "0x00000000", + "0x50e709b04947c0cd2f04727ef76e88f64e7b9012096b41c4eb3aaf947f6ea429": "0x0000", + "0x5c0d1176a568c1f92944340dbfed9e9c4e7b9012096b41c4eb3aaf947f6ea429": "0x0000", + "0x5c0d1176a568c1f92944340dbfed9e9c530ebca703c85910e7164cb7d1c9e47b": "0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d", + "0x5f27b51b5ec208ee9cb25b55d8728243308ce9615de0775a82f8a94dc3d285a1": "0x01", + "0x5f27b51b5ec208ee9cb25b55d87282434e7b9012096b41c4eb3aaf947f6ea429": "0x0000", + "0x5f9cc45b7a00c5899361e1c6099678dc4e7b9012096b41c4eb3aaf947f6ea429": "0x0400", + "0x5f9cc45b7a00c5899361e1c6099678dc8a2d09463effcc78a22d75b9cb87dffc": "0x0000000000000000", + "0x5f9cc45b7a00c5899361e1c6099678dcd47cb8f5328af743ddfb361e7180e7fcbb1bdbcacd6ac9340000000000000000": "0x00000000", + "0x63f78c98723ddc9073523ef3beefda0c4e7b9012096b41c4eb3aaf947f6ea429": "0x0000", + "0x6786c4cec8d628b6598d7a70ace7acd44e7b9012096b41c4eb3aaf947f6ea429": "0x0000", + "0x6a0da05ca59913bc38a8630590f2627c2a351b6a99a5b21324516e668bb86a57": "0x00", + "0x6a0da05ca59913bc38a8630590f2627c4e7b9012096b41c4eb3aaf947f6ea429": "0x0000", + "0x6ac983d82528bf1595ab26438ae5b2cf4e7b9012096b41c4eb3aaf947f6ea429": "0x0000", + "0x6cf4040bbce30824850f1a4823d8c65f4e7b9012096b41c4eb3aaf947f6ea429": "0x0000", + "0x7474449cca95dc5d0c00e71735a6d17d4e7b9012096b41c4eb3aaf947f6ea429": "0x0100", + "0x89d139e01a5eb2256f222e5fc5dbe6b34e7b9012096b41c4eb3aaf947f6ea429": "0x0000", + "0x928fa8b8d92aa31f47ed74f188a43f704e7b9012096b41c4eb3aaf947f6ea429": "0x0000", + "0x94eadf0156a8ad5156507773d0471e4a16973e1142f5bd30d9464076794007db": "0x00", + "0x94eadf0156a8ad5156507773d0471e4a1e8de4295679f32032acb318db364135": "0x00", + "0x94eadf0156a8ad5156507773d0471e4a4e7b9012096b41c4eb3aaf947f6ea429": "0x0000", + "0x94eadf0156a8ad5156507773d0471e4a64fb6e378f53d72f7859ad0e6b6d8810": "0x0000000000", + "0x94eadf0156a8ad5156507773d0471e4a9ce0310edffce7a01a96c2039f92dd10": "0x01000000", + "0x94eadf0156a8ad5156507773d0471e4ab8ebad86f546c7e0b135a4212aace339": "0x00", + "0x9c5d795d0297be56027a4b2464e333974e7b9012096b41c4eb3aaf947f6ea429": "0x0000", + "0x9c5d795d0297be56027a4b2464e33397f43d6436dec51f09c3b71287a8fc9d48": "0x00000000000000000000000000000000", + "0xa2ce73642c549ae79c14f0a671cf45f94e7b9012096b41c4eb3aaf947f6ea429": "0x0000", + "0xa37f719efab16103103a0c8c2c784ce14e7b9012096b41c4eb3aaf947f6ea429": "0x0000", + "0xa8c65209d47ee80f56b0011e8fd91f504e7b9012096b41c4eb3aaf947f6ea429": "0x0000", + "0xaebd463ed9925c488c112434d61debc04e7b9012096b41c4eb3aaf947f6ea429": "0x0400", + "0xb341e3a63e58a188839b242d17f8c9f82586833f834350b4d435d5fd269ecc8b": "0x080000000001000000", + "0xb341e3a63e58a188839b242d17f8c9f84e7b9012096b41c4eb3aaf947f6ea429": "0x0000", + "0xb341e3a63e58a188839b242d17f8c9f87a50c904b368210021127f9238883a6e": "0x08d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d8eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48", + "0xb341e3a63e58a188839b242d17f8c9f8b5cab3380174032968897a4c3ce57c0a": "0x00000000", + "0xc2261276cc9d1f8598ea4b6a74b15c2f4e7b9012096b41c4eb3aaf947f6ea429": "0x0100", + "0xc2261276cc9d1f8598ea4b6a74b15c2f57c875e4cff74148e4628f264b974c80": "0x55a0acda6b9088a60000000000000000", + "0xca32a41f4b3ed515863dc0a38697f84e4e7b9012096b41c4eb3aaf947f6ea429": "0x0000", + "0xcd710b30bd2eab0352ddcc26417aa1940b76934f4cc08dee01012d059e1b83ee": "0x043a080000", + "0xcd710b30bd2eab0352ddcc26417aa1941b3c252fcb29d88eff4f3de5de4476c33cf5030be27db95e3a080000": "0x8901000000000000000000000000000000000000000000000000000000000000000000aa2e35d0b0008e199a82e949fea05248f39fd87e2d7d3b773c9f21b2fbe906e103170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c11131400", + "0xcd710b30bd2eab0352ddcc26417aa194281e0bfde17b36573208a06cb5cfba6b3cf5030be27db95e3a080000": "0x02", + "0xcd710b30bd2eab0352ddcc26417aa194383e6dcb39e0be0a2e6aeb8b94951ab6e2440b598d56f335b5f7155d9b03cef974a1a23824f49049675dd63800988661": "0x9a2d540052bc537646db8e0528b52ffd00587c8a053e4507031753105809291df0e50a2dbd8dbab06e5e90557b3cc06cafa2aa2f596e8cf0e5d212e561567462b405fa9965fb7751da6eff21e53c0ff4a602b3945e925bbaba6e7aebe55a5855b97ec36e42f696644bb9a59449a6d91958153716de04fd551d87bf9a721cde97f4a612ee4b3a095eef0b7a09aebaafa6eada7d4157798edba4398edb04fd5582ab6ed36b73785f2a7f35e9dc1774eb39f7557dfa0b7ad30bf6d157fe92f7a5baaf1c6f6ac7f197ca5f38fe6a6faa7ee3bea45b2fe1366df7b5f9abc93acb9da2afee6be5d349b8afedbe726e530d9fde94b98dfb9af755e3bea443df1ce7be56aef9aba9bbafbeafe9d059f7d56eefabfaeabe72bac56e9dbbafaaf96bbb2f7b75bac55e5d759ba86bf735bdded7d62d767a5fd97dcd5bbbc52e6f775f7de5e581ed406902fb245f3abb7c92b5875ed43a7b279ffaabc7fb92fed45b0fbd54fe249fe5ec39d953ff2af3a77ecdd9752cbd2fea15720e9d6e6e6575eaf1be9ee04f97ceced343afe8acdbc46f9c20810f2b8e5bd0fb32b7da55f7a5f2cd5ea9ba52bb4d1104538481c4bf2abd955bd0b35bb9d51eef2bfabc4d93882c88c8e25f53e0cbbb710b7abc1bb7dad9611c8c42588628e8582aa6e6f9cd7f3a9fb965453468ce9c2143464aaa5bcc6576811042870e85c8b22cf3ccb324babbbdbd9d3d8a79c5e853fae37d4d911f3d7a74f6e9452e5bb658b1126331f6e68d1b376bd6a8518306cd993364c8484989119344124208d1a50b172e5bb658b1d2b18ebd79e3c6cd9a356ad4a04173e60c1932525262c4249184104274e9c285cb962d56acc0188cd960c3d39313274b96c000c30b2f18c0004444458a78514cb7d8db8b49748b3df3a210dd62875eecd22df6e88413451401064cfc12bf0c19e2e3e3dedec752df2ebd8fc9bcf4e809e9b28fce6f827493ae79c8538c51dd7c9c268d87ce999a876ed9f206bde899071f42785f10424e83e68c9929ca64fdd97d656a9cb812fb57e653e46797bb95494e097bf1d9912243827e5aeff3d0797874747272ba6edb6a95727e53e4120ba3bfaf8e135c60fb12ce37f19b180962ff6a9f22bf2f77abbdefe70feff7d49f39bbcd3ce8d1fb32872eb9a2ec2261360fddc22d7a934bc2627ce69343b2e39be0671e338f1f7af5993b8ab16f276a21ddea3f1b3e3ac758ec7ed279faac5eefc767a8d3fb3199a117ecb95b99671ea4cbfca167f763a95699a087feb19987ce4d84dbc757e4a1cffb319a87f76b67278a2cf5d1d3f9fb750ffdf3670feaa043e73ba48c2eaa797ef6f6f8611496a0c6f2c4d9ba25bb057d3e4bc562cfdd82ce382cfb7cfed12d13a0b33c808e1d3a7345ec9033b221168bddf07cb95b5ffde8b63766678ebb159da8a127bb15fda7fbba8fd1ad4e0ff147b770eb7a88bbf5c9678f9ed343d0a3ebf410fce8cc15496fca8e7fc1eab7d7efbb93a45d7abbbc4ff0e1e56eb13387047adfaf1d3a511335fbc4abe4cf3c600da119cb3d049fddc28d7ba8a1b35b16f7103f3bf710f4af3ebbeca1e8ec167245d16df42cdca2d7ce1c74a2b6bd31e3bcb004986ef14fcf31e48c4efaf4e8912b8a9721ce0b4b24d12d7ee8d3e36e45b7bd458f21ce0b4b24d12d7ee8966edc43fc5f7d762bb7e8b5430e7a73f2ca6e458f5c51ed5674e656e0874ed4444dd4444dd4444dd4cc15b5133551c31ac2205806f240079d9d5543a8e8326fae500d911ac266081743901892c490160c514228cd100d0885211404a13384c0104243c80821371072239403211f084123a402a130423410f2426805425308b14048034237082121d4859014426820f401a11d843c215445088b900f42a6848c11da80d0152169848e10ea41080842b8103243e88d902e84e040480e84b2086911ca4188072155089942c81921658458218483504cc88a1033423a08b942e807212f10020321461042042133426d84d0086d31840721690895112246e807425c203486102d84643124cb900c0871420813428e20d401a11e085942480b214a0cc1228403a11a0851215486101941b2a03fa06604a92288144164106406419a08e2441016040113244b901d828420080882f010844b900d04d1d2b12023040121c84dd00f82741094260807413708e222c88a20334136081a1384445016203800b206c817406800640740ce00d102081840c2004206102980a001b205102e806401e40a2066805801a40a2035005206c8143f64001903c80c7e7c0084073f39009206089b1f2a80b400f900d403100f4059807600d200500680b000e90074052807a02480900002011017202b4055807000ba0128f633f573841f230001013402a013009900a8cb4f1a3f45f821c2cf107edefc08e1270840470019015404100b8056001406080c900a808800fac04f9b1f337e80f0f3839f327ed6fc7cf103c64f183f63fc40f123f55344c4e247cc4f077eb2fcfcf0e3819f2d3f4bfcecf0e3c34f0f3f5a7e78f831f523881f46f891c60f22fc78f3e3083f86f0a3083f47fc68e007891f237e5af093c48f123fccfc50e2470a7e88f9c1c48f257e9ce0870a7e0cf1e3cb0f227e78f921043c030a017af1c3871fb11f39fcb8e1042f4ee8c109629cd0c40963823011c40527c4e0043227441144cc09506c6ab82e72248143033d46f081c40d1ce0d8e107063d45e0c10437031c3aacdaf4686295825ba60b73a38b550e5b9a1e3282fc90e3881d53ac2adb0e70f4d0730637c59603136a90a30537b8f010dc507343073e8e983cacd8683dc831020e8bee051d0c723c714308378260c3f4402268054161585598400416153d623bacd85185094530210d138c10c4811b6104e940100e006008004813c403386eb08a81093ed8a10208041e39645b340b7a055b17ab3358587494d8bcc8c004d9d2034bcb052730e1679c200647143c6778b2c031c6cd7021ac8e30a18c1512269c8143ca87c02201ab4b0f12f4c8400f1f7af4d063043d3ad003053d84e811448f12f430418f13f4e8d263033d7ee891a507084c60a2c7077a68a007971e40f4e0408f10f4d062821326b8c084264c10d383871e5b7aecd0c3033d44c0e3081e48f030c2d358156135d56c5a8c0ea3c1e835fd45efa0bd6835ad83ce4177d1691a077d83e6a2d1f416ad4567d167da068dc5b56235c68f0e80f4c03be06387a00eec30b3830a138c30a1881d48f0088387183cc0e0c186c71a1e3de0c1831d36d8716607163bb2d871c50e2e76a0d9b1821d4cec10b3c3053ba2d891047cb3638821620861b3e30b8f2d38d0b8117678f1aa04e5a0670d4d226eb971c6a522c70a70e0e04160656015c60932e0c6f0b0e11123c70c72c8a0470b4f173c697870c073031e2ebc1d3c0df07821a4062c2b78bef8398367075c0db2333c28d0daf084e0060f70f0b042e3870b1c3900f162670c1c59785e6002105853e090c2841ff850e29ed94ee01b3041091d5a5c29b62e5d11565978b6e840b1238cbfd90186070b13c630a18d09649880060e19b0622b216420f8916225062b87150f56445805619506ab079606583eb0acacdeb0b4b076581d21084d1018d28b24421a218f606501d266070b74ba98e066f5831b39b8916645c68d1bac8cb071f1d303ef071e207496e081c1f6c58d3539c2ac8670d9781ff044307fc8b4e89912f2e6061a377c20648b1e1e0871316dc0999924e82e2c1d84d8e0061baf032b205c1e4c20fc071e2e38aaf40441c89a36c1ca8c959b480321489cd0438f226e7c214402aa84c7656ec1f1c48d363d6c846e2034041e1004f98007026f0beb8a10334ee82294c50d2f76b4e1aa10c2e246193958b0d3c6a9886184b6482e4376105204ce0a213bb801841b3db841067745c5a2a70cd772030cd9831702cf03377670c38d10318488e8107840cc11e07881902386f4e055080143c80a1c2f3829c0a1020705385ffc08f4890e0c79841e1f6459e0c880176107193dc0f48091034ce744f784c7014e2a870a56604417dc40b3e3073d58d083881e2ad851464f1837b4b8b1458f157051781bb891458e2f3dc258303d86c8314464c2aa20071133cb8d33ee86070d0e28582570344c3063e5825512ab25564aacaa5831b16ac14accea898c8b6c082133103a83c30a10317a1c914309160f37cc085a230408b2063f5ef48851af8835e0a09858e0e0c289c063031e2d78b6e04cb0a3080e055c0ab82e267cc149d13306a781d8044703d60d9c0c566b563e302108ab1e641a30414d86e5c61859067ea6c011ebb10407031c583832eec3aa0caecc7645cf0f565fdc10a387113d3da84bf848011703160e386e10cac08d1ffcd4408a00c7951e3fe8d1c66e61b3b057582b2c1178b4408680a3e287063f6a2a9afa82da447da24ad52c2a0c2a14754c25137fa851686c38363a70d091438f1b6e07ee072e0b4f06722cc1a3816e0ae70a4eecaae0b6e082e921828e2a3a6ee811420f10703280e3011c0d9cb0c3092038210bce07704480c3c5843326e4c0842cfc06c7e238f0149103091e237cfce063081f1ec8b1450e3139d07860bc25bc305707578caba6e7083a623d43e888e88ae854b04d713870317fc2a5f017ec58916dd9317365d06346cf9b1e34b821acac7044e021058f333c68b0a32647113b5ee8a4d109634b621ba383031d3174bad85ab041b129d1d34687959e34b62d5b09b61f7070b92eb831b84d74657444e87eb06960e3c0b6436745a7456766e708398cd899e27a9009c1f940a78c0e1a1d297848a023840e181d14fc9ca94ad416d02a6a1195057408d5088a05bd829aa91fa823a821a8602810ea11940c1a05254357404b40b7d01fa807680ef4065a25eb41e6838c8d1037999490263225b228322832277ef490a100880fb21db22c01a05682da4c23cc3333077307f38c19c624638231dbcc32a617d38cc9c5cc62f6606a317d30d1983f9862cc34738ca966ba9937986b269a0984c96676317930bf985b4c1c4c1dfce0616a6066405af133468221bb9069e41a69464621a19063a40ca4147206b28c9c42d2402e2195902d904900b1810c420e21bf4821e40a2412328ce4800481f4416e204323b5c80ec82c92879826f2209a8938883b88398863441dc42ea218118cc8266611bd8041885f4435710b084484412c13c704551163106510a5e20c6810918a38c50f0dfcc012c54424e21234055189f64147114dd02f8827a04dc41da810314bf3207a80be205a895522968843cca161009588b196010a439a06310411043d03b84497a12da028e8277acc8f2c415d349826a281e81334085a043f32d041fcd8a151d0256821e011601a9008d008300b7806da0016016201af80328053b00530086806440282018f80646014f005d009d8043c012c01ec0245004300498044c392d237c39318a030253969224305982ca180042600c3806e607040035660c00b0b50800b0868818524478d031c821122290cc127341f58f80c6d24a1c5188549d20c4848b6a313a6242424158f22184a0c4c4f909a2041898109c9d21294023c35495a5a8252801f3c5830c3930c4c494b2be0a4a41890a03c213dcd20c393a41a7cf008c3afa5274c9e929c202525c5d08307188612839426a42751fe892989060b3071c179a880098909d293289fd484090a029e98a44069d2e47b7810c1afa4274f4f9ca0ccf02485890d1e43301394274f4c9ca438417a82b2f4427a12e59938497912787cf17878e197059294905e48494ea034497282f4b240521226284f5eafa405ece09102aee14994774a527282e200251e0f143052929424290978c149920c323079e1070f21f8a5d42469862641f0eb8929c9296906a627cee3044c4f62d8e161026ef2e4c5f4c4e9c98624240b2c4589c204c929c9c9d213292ea52650965c3c3cba300d484c9e983861f294d4020e8f125ce0c91293274f4f989e90c08304529a24d9905483c708d8094a01b61e2538e9898993274b4ca6acaa0af8a5d404ca52058408393d35f12a119c5387600b2429213125213d25bd906a98010a13d22b89095214a3231e185d408ac2a4891021264f90a2181d7115085e7ac22406a427a7a4d78b0912125745c0484c4c9e38614a424a5a7a7a7ab2b4a37a80a902b66ee125293470809d386152a36e604811a10b3cbd9e3091507dc8a93db00c494c3c6461214816a800d294274e6ad41db802525e4834242d25210d29221485ab5133c04e9c307945313a2aa16261a7195e48b5eac02485a75ee1a7274b515e4828d400c509d3931a72d41c58881092902028203d35495a4ab251ad2ccd50a502525ef5064e6ac2040509a7c672e814333199e109e9f54a5a62d1233053d294242370056878b284d4d13478898994a6244b8bc0509c922e8094e4b4a244e028494e484e4d2f9dfa03273561b2140589e90992059c92688022c31313141a982ab043879043df70141aa2181da9a81038089cf4c4c449142936281afcf484e909120a4142412cb00425ca193c64480a921392132834204d617a82244312131253052a0eec040a0d484e9c30415a80ab05242c70740c76e284c992141a909abc7cc0af1ab4074932f4a03c60284f6c588624261c2a063f3d3d212d49a181041a06274d79f2c4448624a6d713a4a418742818fce4943485e90952520c6b929e984c79e21405a9c993a50a48890244bf6027494a2f263420357982e4c464890900e80e38a9891427494e484d5e39d48ba725293438315962d2e4d5436fc049343c7972623205e995f464810ad000c52906241b90a2181deda0673889e9490c3130412281da8093962a20058a131c8a053b71c2e40aa7a697197e62824203d292141a386a0527bd985400c906ad8297a4d080f4c4f4044a14a421148444595119f053d28bc6802d10a5090d493420b1b0800520a0c805252b86494b1560f2c4242506a4a726494e4f9c303d4142c2d1009c2fb4cd9a3362ce3cc32c4bc5620f61d2cbb431b4316014482591a9634e223a74e89873ced994c62863730d4a29a5109031e2e0a64cbb7b366ddadd92768c9199635366ca94366b507236a68de6a1b93d802bd318e594d15aca54464b63431882581bad0deed84d993b4a9e1542c896ca8e55b28d4969ad95994acaea4869c75aa5acb5326dca916354d5aa499d5a2d4bcaa6dd4cbb086577263bd362a459edccc618553636654a99e31065664d8b51cb24a47452382765967252ca5b6f316a5a6cad5bd3ba1b328490ce0ae190e8799e37b5a8c509e1a4904e4a994e66d95d29953d2c6b8b29a5519395630fc7d833d29e1da5569935baeaa831cbb6a17100689cee6e71b703203733502b76039a3245817d74773ebae3d87577dceca37d745d77ef745dec60d7cad311a8290fa5b1070f4f07b4d3a3e389103684b01b521825845c9b6bb5927543cada32ceee1aa54ed348bbb94ac9b556ad366dda911976377338b45b3d3dabd8dddcb065c4e19899656400939031c3ac9933fe819d71c63f9c317396c1ceb8994b602e812309cc2434f30f84902384cdcdb035be415f60a6515b00670ae8c1f194b56353cadd3bb03bd688353a46d9355068c831b7ec986394b1ca39a5bcf75e1d9dd8daa431d6e88e71520a99524a690d1376708db19b736acf6e21b2b96db7ec1d5c7747ae4da916234338594ed9554a9ecc3ce34a93526a1a73ad52b25892c5d2b4186bd5345665455963a59436e3e8285946ca94b904c41a2c9bd2489bba4029c71f38384a7afc8831c61fcc9123c7dd10c6a8c5dab2e39c31d65a2b646ed8cd08e8d8cc8a3a5c0bb1b204c2196dce5431daa051b3d1dd556ba14a6976a39987c4e698258ee6703ae270370e8e85c825e138aecac8314a5637eb00d132737353243272c76e4a01402900b8352963cb4969ec1825a5ddcd9167434a3b76e45a2184915ba19bbb699750239552ceee49257394514a66ae3bba46c7aed1354cd8b1234a137698c0b58c12f24ecb8e313237c481a3d61a3520acb5d6187b87ab1c73c71aa34ad513d927468a838383c3e1c458bbb626355942e4c83146cdc691acb2e2a810767794ddb19b76536ee60819d2d92a66ee48bb3bda8835cec81ce39c2d6365293b56aae5c8183b464be9b4b2d638279d93c6383b76741a73727258b26c8e30b68c578bb1e39c94bb5946664a99d2d8b23bca8e9152cab5d62aa38cb2bbe7a494323777addcddb165b36ca6cc2c5b870ec93176942d5bcaee6696b15bc696dc31f64823ad638c453724ede689b152aeb2a38c31468e4c65e4ca4d999969339592327777777377f4ba3b364b2a9b29a5dc9472c7964d69edd832ca8edd926bad4c210500cf9e323253eeeeee5a9956ad8532eeee1b2ca78c94ca49a5843046dadcb24a96ad52d3a95996c558bb69949aec8edc916f307364dacc94d2c9dc33c6ee8e513237addcb125773333c7d82da90128a534a7368570d202b83e2787a8ce6983523a2915a24290201a14a70d392ba591d54d23a5274c4a5904a851c61aa99c3152a6cd9429a534fa34776c0a296d8f314629638d14faf8b48c9aac7293348b526a324ad99169ecce5a4e1a9b328431726c1a650fa1628815b1046e0b3841a12189862c694ad212920d4c68d8b1c3416480b2842403d313196480b284436869e98952d0007a1c69a5d0e2f1c3a30790138c0495e064e9c90c4d909e96a4308921c9890fb721c909d31324a6274c666812430c502ea481394892530c484e509e983481b2b4c48447004e929c929c3841411a424148d213a7a7137a94f0c271020b8102c5298752132615585a82e274421126494e393c4909e9c98624261dfe9424038e1cafa7d7131b9278b2a7264c5e4c4c9c9e909e9ed0400394160f16f2248624a7289749d252939d123808535294284c90926460e204e5e9c53364a8c70628353ce95062d2a44992d2100a423c87902048429294982c55004906a62733bc98cc80f46443924f614a8ace416878f2c424c5e91689e1494a0f093624cd80f4c4f4c4290a5293d7131a78b22727264faf1e42786c1c24e98989531253920c4e007092f47a253945a1014a13222b16e29434054a93242724262f274d929082280da120244a93a4d78f6a86264f4c2a8034c3eb09d393185a53989262003808121394272fa7a429481688e18953d214240104410105214e9290a03c45b1805313a4271b92784c614a8a3f2b203a4645492a6b9484d12c4a15151515b925300883aca8a8a8a8d84ba2202c2a2aca251c1545e3128eb251112a2a0a16392a0a962d898a6a5854146c4645c1a828986a09c3a2a260148c8a8a8a8a82c5b80406a320ac2e6198b684a3a27a0947410a8b8a82c1e6128e82f51286c1e892a8a8a82818e4250ccb6073090cc260bd8479090cc2607209c360b0b88461b05e028330b88461704904a6112033431a5e4c3833d3bc882434b7bdcde99a5bb6bd5587dec741d7bc5a449a38db1928c2e68aa8470e49116aa250fa72ca5b19c88a16fb190bb47ce6d4212b51cf1c7247ed1672d077a04baf6ea165ce881948e54872c060c05fbbe6d0fbda25e4e0356aa7d4a56b1e996fb74ddd887ae6cc25a19e395d419bdfda930c145d7a734ae895624199ef9b414ec9f6f3560692976385f108cb6c24aa81dc11a301466f516e91336237d38b97ce9c11a3f1f236c1291ec897dc119bb1a67f72470c46cce46af5c1b850ee88cbe0ae154aae35561f2c044c231056b291b80233df1ee343679754a2ccdec232ac6459571fac876f8253fd913b622fb8231683be95dbe48ed88cb965dc117f613fe38e188c8c33e220a89e7247fc03ba55ee88dd685fb923fee29be094c61d719bfa1a77c4604c954aa592d9ea8369516d963be21d1c3118bfd94d15571f6ccb4b6ffec61d311a2f5de38cd88b97d77291e33839358e638ee32097715cdb70f2e839f9370341b72cc94664125843d9011bdd6ad3a985aed43e61cfe9d12c83aa2c7315f4bef8ed2acfa94985a7ece1e704b30c76069b3a734775b6a7dd6f7aa59ed2f4b6b7461fd1897af36d7a4cc33b48b46fd7be9d3b804fd9e974b5566f39a534a848509665cf5c5146147d445f21fa88319b733e73459b737701ecda6e11ff6752ca186377bf949c911295f4e24b331a1561d28499228c1360c8d02a0519f8f5c3d80ea1337700ff209a602d6aea23567304146133734d32162bc13fd52437bede157c2e7cf5e951b7d2fba82b4dcfe44f9756d64a6ba573523abd7a4eb456e97456e9d4fb2ef34ffb9c1e7409a3b03f1095a277676e2357d4d456aa893de58c80624f9be00fe18ccfb8ea969b46b8b3fabeaf774a7d1a392430f6d42d4321abaf86a7d5edf4beea4a9947f9994fef93464c26167b7a9d9ab84d2cf64f357eba53930acf0ca4393d6d3f5d73e6944479fac5cf5cf39c9a54f866a0cc9fb2affef5674e3da7ea4fd94f672e09d25327eae935ed6852c1c28d7a4d70ea83f432ff64d389a2cfafbd3d5af125cdff7896fac282b70cc5742ce585cc03e0592a054fbc65b1a6a3f28fc73f47e5e564d42757d4753353a93caa793c3272453a3a1fbd464a33afce2cf3364e0965428b2fb19fde5c510d1dbff556b7a2b717c4bd60432c168bc56e704141c56245a28fe8904bc70f46093aff17f49947f7e921aedd6a8f9e79d093d736e48e2b796b4f2a2cf42e504c1381265a9162a60ad8380483e5fbdb79a0c79eecd6106dbef52cf5658cb74cb3296343ba6206629730b09f947ee89f94fe25db826757829786cffbd897a2966f8fde520d1ab0e2fb7ef099a296576a87cf1c02582a26858345f8291da07e8d314a2865c757ffa87f137a8cf27ef0a57b4a9a92eac6cc6732462dba8c9967d56ba597068fdc6b85e89ff46fa9c9787977a07f4a4b514b539cfa15f8e3f5d27d613388980baa3d4cd301f8a32f805ded449dd110b5bcbc52b80cc613c8283df8b11d426861df6f296af9af5dca8e8f1c20f351cb4324fd83e9d2e3b7d353ca7c3ae492543756bc0c81968f1b78d8dbdea6f73519afa4e5e1fd600f9564d7035d94969a8c8797a9c978e9f2eeacc05f45c3888f5769a9a261c4f7a5a1a261c437191336082c942dbda3bc4ed29f6419aff44d892f6fbb644d4dc1fa86879edd0ff60f3e5ea5cca343ae85ec2a4d892fbdcbf87895daef0e92f8ed7d9be84b8ff76b82531f7d89bed3906f823f45de7ae589ba6111c621a6e7f4c43d74a02dfe8bf27d9d98813e96ea8096df5981bfa8e59b6b61c7d4d47f5d2cf650a29687b1852ee31b03967d3ed8e533b75f8fa4cffb6d3fdd4ed830d39c3dab9b64b7b633cea8bec61b8ee62b876edbfba2d333fcd5a3b783447e75f9d5a943ee00d63ff8540b988fae795763933da43903a125cb574fe3a3bbf9eab6046b636befd33c25cda35b4df376abda2067a479f4a80d0942a779bbecd6746d7a74bb6dac8db3b15536c2cfaee33ad26e31c6ee868a52b956ae6aca19c1afbef2da2dce56d94854fdfd5cf81c9b6c2261a2afb8a2179595b38b01ec5ab96d6f73e6a2a714bdbacd2161831ce7cc25b14ed4f12d092cb7acce57176ae5dd4ad5dd1a7d64de451f997ff53367a99a72d7287a75a2087fe5b16bf3beead4edb4389b92fecab0e3ea63c0f76506a25dbd3fddca5add6afd78bbda34affacaa35c51dfa68e3a7ced0eb94141273cf5606fe1563d1f4f3ded6d6fd56bbd8d5bf57abc955bf54c783bb7ea01e06db655cfe7a917dfd2ad7a3c9e56ef3ef5e05b6dab9ef756b555cfdfdaad7a3bde6e5bf574bce5b6eaf5bc5d6dd5e379cbdaaab7f3b6dbaa97e36d8fadb30c08e8841f55b42ded6906f83100111706ca21003f82fc7803d1f2a339742ba4813823cd6bd52ee4c240991335bcd245ef9f2d7a9ab7f7693ccd3f6da33cf55075e856a8ab3f45b1277047f0ed8f0d72464c86578fdf0a013510ec561fac04efe49ae7e40f190868a30eddfe048033a20eb7548f9ea685fe047145f51639d2adcca9742aa7fe15f92ccc18af7a6d8c8f0e6dd0d69e0bde0bddca3ccaccd090d0102c1dbf046040a3c167c8058806a25bac81ce49b7325fd2ad4c0d9121518aa0b0b5a7b9e654d908dcc240291411400a47a2441f99db30002b52dc267e8c470460046e30acdc1e1940c358f49139c4127d644ed9b860ecb3cfb28f3e808d9b889530d5afb82b4c3462646bafc22d3d94c2d65e75c81db5c32dddd2e265e596005bb52a6c958d68db0b5df4a016eda3f7c7225bf4e0966e65de1ee4d2adcc2357a4412c1dfcea9a0036cdfbe06b6e63751f5a75a2662268ce5c51bd4bddca66e856e66c3e73cbb023cb95e656001b97001d5470ad2e51f491f90ad147e643d0e838faf8586a05b17f8aafb90e2ab856beba904bf491654e3925aad7ae92ea3a69f0033f3090ccab0b802ba2176ae956e69a07b73050e6f0864e7bf8d53ff8ed1fd4f299dbea51583dfe21ee280096c896c256d94816e5cc669665144208adddb8152b67d504a77e27497ccd6dfc07f5dab500b89eefd0d1c3b3930387ce8d1248c8b1e15383070072569081a66b1e8eaf9ece53afdff668c8357acc1533d0f4c89c91f4e9d955825d6a5f1f2cfbc0296d94ac448a0b6ef8ef025dc46606648c9ac3d7fca3df6ee9f472b668a19c51061d6ac99a1fe2d0494e23b9a3003c3350743bb7f6d862692c59c36e9bd39d79393ad187ec49b9a2e9d1db9939fd75532787040622bdbd1b0c24bb6e498f40c7523e4cf19a4fffeacbf890336237efe49feadbb53166a05a7dcd63e59fd698422d46a2cf97543e3d3a750b37cd539a1e9de7dde98f4e5b68cde3cf18a83d9b31bacaa3b792fe783fd8ab8cd8f22a87af729efcd34ed4cd21e957f9f4e44fee08e82503b5ca893ad619e3d5aa47a95c50d4a3542eabf294541e5daaee8efce8ad7a2dd6fbb9f0cd40edf47e2e3c6420ad9943223f3afbc82808a3bdf2e2ccfc3287b105b98304fa0692789e67292d4ebc7c2b37e68eb2fbc1cf5cbacdbe3a67deaeaa6ee906399a51f662dddacd55174ae59b4adb2e471fd36bf43155aef2e956abf7cb1c4a8e5ea34ce5b14b6e2a8f5dd2e755ea66c7272cfb7cdce6a55bc946e612066a98a5eb3bef9248d4304bd76a3e080497b9493602a343e7b2d4ad251fef0c70872e3acfe9f14ace28cb820562812c0118b68a66c2580f65d5ce2d7247197499795eac4fcf89bd33441fb273baf6e8195714bdbd9d0875e88c3c4fb7a4eb38517faaeff4d4fdf4ccdb3f9d970eb9a3fa4fba19a20fe9d069e6253110e9d39381819abafefee86ea3a679bc3e9a53fffca5db4e765eac75eb41b1ccb8acefbc20c4058500e65e10e2b2d6835a8de1b26e9b61afbea857d2dc52afbad53c7ecbdc11eca3dbb8699ed2b4d9063995339724fae49074e4879c97cdede68579c17f2d80737ba1ac73be0076d93b9d3905e8a0828bbbade8437a50f4219da887a0d1b14be5d241059775eb5feba56f1ebb984ba2ddcf852f7ae69cea1a45ebb14bf3f8ab57a45b527e8cdef748f4e95f919744ed396120c91d65ceddeaccfbe077d1acd24527da69971f3f5e03c0baf68fa55e529f818d44a7d02174ea79b11e3df867be3d83cc3f44bd0132bf651efcf63ed8370c94324fd2df9e793b48fadbfbdbad0715a57259875c122d5ec83fb3bd2a70ca152673e694a8b2fbb9f0cc40f3aed02de9d18bffccf565a15b52b291cc8da65396f2c189a76ee306bbb091e9d02177449f426fef834f6df420c70275e690743cfa7966207a9714f575d22de9449d7971de191848ba952ede17ba25bdaf0bdd92feb19a970eeba2b7746ef3cc232ac268b3a62e140c09ecc246da9be0d4b74723faf1c22e0c84a50a4fbd715d892ee83d265684162bb12b2ee620401b4ac0d6e74804bad86b24023d01d06bf4a100e8e2e8839da819688b962d5ab260c98205c660ec05abb4b4d928edb63923e947f0a3c0971ed3f6f14608b7b0db90860d5136eb8282c1c03ec31833ac79f6256b96a4797618d2c070e6d95d38e3c214cfbec2142b2880c93c3b1191028e3c7b912345863c7bd090a09f676ffdb47c9edd7d5c87470702cc2d80db6d7bf53bd68e11fcfa5d7b5ea033d700d6d4d4d4940baa42276a081d60b9873e28fd06df0edd42ee0030183ce41fc81d2559c14e679f8fcd783da081366229a2e5db7d7e8acc1bb348911efa7456e8a1af3b42d40310df6e001674a24f13f1582c1673b5ff3411198bc562585ced43d848fc58df253cebe05bf29333e2343fdd665be48abec88d2631b72a956d5a0f535899c139b9e79c91c76a3a8b8d402861125dd4f1347e7af05b3dc4523cbcf9f69f1e6236f3cc0336612603cb90888ea57860f3f3598a072dcf35dc40e9442d6fbd510a2bc20774cc1d00f652de7a194203882900929b353132b737c702ec95f836453dfbd7cedd1359dc3c4b6539f35f7de93f9ea5b27c79990d71c39eec16732cc05e66b0cf6e6d6fc819d3ade48a66cc7c27bb46f033cf6e7de83ef22a753fd804283584de103710b291e507748cf3c21260229433f31eda316a8f1e95a24bcf32af3dd49f49597e40675912deea96a5a48bdede14f5922b60b959b5875cc228a3042cf750b36779009dfced2d8b7ba8a56b79e839c16f6f8f9e6c96ca02c4b71739e944cd523c5879081f7a7345707be68ce46d0f26218c81659f2cb1ffbadf3ea887be23de435feb480f498ffed343f575daf87cdc6aeb23912efa60a576197d4489c3dddafcab10ba61174bed30c5b343cea85d3a51b7374bb1b3cf0763df0cc5e8588a0b370f63cf6e9b8807cd744ad1f93f18fbef59ea06561e3e74c82981373cdf0fc6a4b337453ebbf492b09e3d7a1fec3fe93b48542f6f13ebd9798b0ffa8fa7fe8bdefcec71b73c8846071d3e370aec906bf2a6eee3d5e91674186b2a2cf7d057db8b2dbfe9d917bd3a6436c22f37ee2169a517dd3264b6b2bd1da3e8177247b2ddca29e5a45e3dd8db6c9bdece74f8fdd5db99d748f5908132877dd43377c43d75e68ce0c7ab243d3a51538f1928bb3b48a447ffa4b7f34f0fbead9b8a2b6a290da079e8b287de56ee887b66a0af5d7af4326fef8bfae856839a06e5ea9bf24d70eaa7db3652fdbccc405f76dbe39f1e339074c9c52b6d47dbabe8904b22e36d8fbb056114ca20ae94b95244f41863bc12fb18638c54d2e44026072cde43ad1efaa44e0f7dee53ad9c81defff17cfc6ffb7618b34c80aeddb2a2db6f83446af461adfbecf6cc6d67ed5ffd78a7f7c35cd1a7f33a9108471fd1a3c76723f51255210203f17f9c02bd4455de3010ceeee675f1db93f42bb5d7ae87fa7ed0338fd2bfcca7dbcc9bded6adc8ffd5166a0ff5f4e85de6f1dbe68a667be45880fdf4e033d7166ef2a75bd1a1e7d3adc82f3d4e5eef56846574d13fff88c6b28f6518838ea5aa807996aa62e5bfd6b70b3d4be160e6992beab6aedb7aa887a6b3dbe9f1470fbee50174f0b3b84d2f73c815c5cc996301f699851c92e9d9fda64fb7cd15c96e49672e09eb277c1bb7cc9b0e39eed697f3d0ad652ebb1fec338fde57a7c7e87d3273a2b6d1fb0cc0d1fbd9f0d463f4e97ddc2d1ba2ccb0e4a37fd1bfe8df74ea35c5a9a9a9373f3d7adf9197d2a7c7cf9c12fa31f39ae8cffbc18fb7094e4d4d4dfd07fbe8d2abdd82db430f7ae601cba0d4c1f20f08838ea57090aa3a589ea57010f3ec3c39cfce3e7c00cb2a74d0d959ebbe317a7b73451d21079d3979a59d9b8d5b7bf09b830e39f885e5ef76d87d611022b1d0a10793e8a46e68f39ffcf60abd568e44b87d74ffd56f973dc40ea19323547424eae8c96eb51fe9beeebbbba3774708bd3ebc3b49a04b87f17ef03b425803cbcf3e5ff7ed36c790333ae8dff62d800e7a84ae142f515be8f54bfd948c8bcf6d6cc409aaf929dbcaf6063df95b9b6fa23fa506b7ada6642c36e20463dfa4c2436f670e898cc51e22e9625b0ff1371b81fe4597ddfae047af48179d9db9239e7acfa7af52d73ab0dcf6630849b02c754311cf747a1f8cfd8440e870d19cde1a74a01615cce2af0c5aa130b66d9cb3e5fbbea46bfeb2b7069d575dedd6a0f3f2e6402cfea2b7069da757d6a093c61b9a8db1460de7b851a96e4ed78693950dcdb2ac861c2f6ba8c19366e5d175d0a89c669d99cd5fd93645e62fea759364347f715e5f2b99790ddd739c7346a5f2d766bb9c57996f7fd5d03dbd2fe9d45f5a96f1bc74cb621e9292eb94f755bbe321b9a9ea7dadfc093e747a5fd69fe06fd49fe0576fc8dcf997a3bd3896f7a7f3eccc43aff68ec5dd17e770755f51aa5bd0b9fb8a64ba055d762bbe62996e41afaf38c5f68a66ba053dbbaf7826a75f114db7a0f77dc534dd82fef13c7b906eb5f229f2572a954f91af62b17c8a7c96a6f914f95ae753e477383894fa14f9d4a3943e45bef4e8d3899aa787e41129fd9539478b7c67d45fd569965d9d6e45ed47d3fc457d53f96499bf542bfff697f4d7ca55aafb5271b722ce107f555fa95437a75bb10bfaaef5beaaabfc25399e6e457f69dbd6ade8aa5a6fd7adc86a7ddf6f3af497530d394fbd86ede97db5537f65525e7a9d6ad0f1ed4d7108691c01065f4309d1a307e9a213c5e9f1f3f4d08b473a8e479de99bc71cead623b73fc9ae875e5de635bbafac6afe247fd3ee4b7315cbdbb5cde77d4daf99e6d567e6d3a354ad3aa7f745551eb76e417f597f928fd3b156b7e396756ebbd2e6a8b47a2bd5f976795fd2b3292f73ebe3f9f6e82c98c3080ba1bf2094c0cf589be73730051d4bdd107bdbdc11fde8d0fb280c59f6c29c2e48c9c2cf1857f8793ff6a77e28a53377d41f9da8a5f7b57c49698097137ad3993b821fef4e127ef3d1e35582ce6f9e9fa8a7f7c1874d5057aadc20f54fd9477f35c17488c28b36ff243ffa2b7a930c670c218d7fe26e7d4fdda493e54a95b7a19dbb255d4225fc86b9242c848ff78bf2b008b31dd8ad875e2438ac0ea7bf9a6eb8e611de17f597f5570e6fe25ccefb6ad271e838feaafecabca97d55efab693acbabd3fb6aa2be79bcafa6cea5d7f01d9cfbaaf765efabc97af51c6fb281e32b7fa93cdea6e825f84e769b6a38cb9b32c7715facfbd21cfaeabee47d69be79f55713cbab93b0f212ee0b7abdaf1202936b017adfc9b5d02e3b59e6277b4aedd2334e89f4f6cc8b9f050dfeeb7e7e3c3faf529c5e7b28faf44d07dee80c53e87ed9437005f85406894a58ee21e90cc49fc9f2edd106697cfb0755ae79732c48e93ee855d1552a2fc8f6c1575279dc7cdbee173d3a515425698f5906812bd0559dca15e8ca32a7923985a13a950a4375ea442d610cc1181fdd42659c0dd27cf4e8c47bcf525880791b80799f67291b60c1e2cd749567380e2f8e673ebd28956b3ab311ead98d52b932eb96e50216cde7f4a04bf3c234a9c08245742abf423d8cf598ca355d3acbf9a30da6f098546f7df390a8de76e58ca0d7d8fcf39496ac6fce39dd3c26eb5c0def833dcee62c967755ea8582b9542c6c97a5b4f9caaf50872e6bbd1dcb712bce2dc7714ed43b76e5ed588ee3b8eb050b85d73ad1cf0b954da75a76a3e6adc2ca1c2aaa7a76b1b82b732ceed26e549dd3a7d3cc378f21102cda4edfb132aa427536b0d48ef5e957dc351dfa8e9db02e1fb9a2e8703a732ecc1a9575adc2321cd3b1d40bbefc57596a0b36b5bdfed72d49b7b28760479647c1e0ea9c73e61ac079548e8e6f4e85731d87dc0b3abe5d281cce39733070aec3795b561d062828178e77cedc0bedea1c025472f8e6543acfe1907b21876f9739183acf71451a1f1d7ad6420e022bdfe12c8fcaca596ec3835ab90def3c129ca87778502cafe19b07b5f24d05bff36c38e7502cd7c1e1245ca8ceb91a1e152828ce3bdff176e97854a0a03676b13ca81e87f21cca5d87dbf0a8784ec59d8a0e878aa2c2e3359c0487d271a8121c2ac73bc8bdb0721b0e39183ac771a1602e96e7f0a0a08b75a10781d5741b974ae738ce66b8f860e68b193166ca98416386cd0bb87ccfafa0932fcd6079bee2a15ff1c5cc9b2bc43c8e67a92bccbc9d1e930a89ea2716407c748845968f9e5d31868d8d3908e0701cdf3cce571e151cbe721b1c046ce05ca89593e0cc466c6c1904a036dfe1502bafe1ccbd60c3b90b85c3b795c7ae1a1e95cd6df80e8f8a0dc7e1247854a036c7e11a0e07c3e6362e15ce6d380ef7020e5fb98e07c5b98d1b45e586ef70ce330f02387c75a96ccef2e69444d7ae650e86ed56b1e19bb36e94ca85e39c17a5727546e6fd82de0b96956f374ae5dafc83de9e398ec7f2cee3a02bf3769244a7de710de8aeac3c4c769596a66b9e398e331bb1f70b7acd55f783de1e9922ac62c3712e147451d9b950391c6ac7a1709ce53bbc7ad437af8a0ddfe1373c281dbfe1760056a4e40ec2c43e73fad95b98f1d0e5b90a2d190f5d3ef3f9f26d6fd44ba27da6facc550f9fb2795e43d97ce6f1fb9943c26b3ea3ae7dfde69000d9028ad8670e392403b022f559155a56bee3424117947777740ee53b7474378ac739efb9513c585470e5007375de39098ec5c31d0f8bbb366779512c27c173dca8cd49c0b9512c6739e7363c28980bc7bdb2ba619a5478a58f21908fa56260e6a14bc7c3e25055a0b0b82b6a73ce6df80d0faa841bb56d4e824345d570122e1677ad3ce76271978d1b55e36271d776afe0dc2a2ab8707c73ee5661c5a0ccc3fb24f98a879786ae8affa697227e89cdbcc3ba7c6f9baf5c3a47220d5839cbbb48a40acb57170bce0d9339cc25b3e94507155c5dbb562ea3ba0a0563b1ce06968ac5eecef4955f71d7ca33ffa27c7677e6caa17f4b2211d6a5c2f9e6d22b4c015e1d0804366007129c8fdc0bdbb6ba1de7c25602ac360e0f96610f7cbecccc4f9518e65a88ae8ac1978faee2f2d1a1dca2ab5c722cd02ba5fb4fc662ffd43d75ab6ace08063db3912041dece0ff6b0850fbe127495abaaaa1d7e2a6f8f763250bc932bb26e33c8bd6a82539073cd396f33136ab3ced99b47ce36eb4195e3f0e82a301d4b9179f3aa1d2e06583e5a6ddb7cd354398cb8156b83b067478723e97674f470b0088eebe138af27e37a5ceb61753676767a1acdce4e8db9e325f84e87b34198b343c676ecec781c8edce1fc86736e396fe74b0fedf8748bc3156d6e739472b8ca833e8733cae12acfb824d1553e3924395ce5d6c6d6bdf5f0709c13924d876f9d236179f54dc7e65bb77965715ecf6d8afa9dcd83cfb3b3e344dde3f16f453b1e793cfefad3eef8dce15cc739b72c71781ffc1cce393c1c383c7e9d1bdeecd2ade92578f14db738cffba01ec7fba06a781fd4cafba0e0ecd24350c67e3a8c6f1a8d4a7577904457caa453676e854cfa971ee27cbae538ce9b73e8ad50c039193664d0902943460c992f6c2d1677f9e6aef20be576fbc9b9dd368ee3dc7254f3956bbe5af974bb5aad562a15abdb3627242a95f5ea2a95caebfdece6b16e53d4af1c7a99a7f2f8bbd5ca89fa59abd5eaee24e11c3a77e1976e4d77bfaaeb518972f7fc7accfddeebb10b56d5ceb3141074f0b6b70bc364ee44ade29448bd40cdfb7878b332dd9ade5c0bdaabee57c3abdc7213c0bf5ab445d9f0d0ddbbe22e28f728d725c0bd31bf56b85170aff793d6b3237cd0ab7ff34b849ee62a2fbaf53e1b5e73e65a68bda68a9e95e921cde737bffc74cd6b33dd9a73886e7a9be9a122262ce2e7e6ce3f1d7ef1e9b509e03e25f782e7ee917bc11deaba5fcf33333bdd22d31e7574789e40f331e7a302604ffd697a94504e53aa67f7697ae61fa7a4f55fd44b1b9a767c853da55eeac11c76e1e66ddaf1d07ba0809c510b881e5c4cd802002d3e597860b91f1d5af1fca343edf8e836e8f8e84f3d1f3d0acf475fdaf9e833e4f8e84e707cf4253a1f5d02373e3a0c257cf41748f8e82ee47c74166c7cf4156a7c7403e07c74a2eea31f617df422ab8f3e84fbe841db47ffb11fbd15dd47fbe85e3f3a0ffde83ad947cf991fbd931f7dab0dbf1d26957048fc21d4674431fbdaa3f794f970ea615d0111399ea580f0a505b7ae43870e1d51870e1d6ee5a643870e1e1e1e1e1e1e1e1e1e6b6d4686cb47cfa1927a99c3d92b4c817a4f146f3e7a0e68a360d34306cb47cfe17dfd3b4e3d3612f42ccf31a48c6ec783fe833b4ed4cc46827cbbddb61c43cae8320ffaafbffac621f9fa39df81cff7e304006bd8436fc7330ff62cefcbe1ed1aa724fa8edb8d53d29f79f5a3ecd60b7be87d500f9de59cb3e21b2d9b5c10309d43c0f46cb5b26e599bb54ed4d56a1a97d9e33d3d3d3db36787efe8f19e9e1d3d3d2a2e494b875bd761ada6c12f39bc0ffe8e471eb7ce73bb4cd0f3f8b7e3ed1967147d073e8f5b9e1e4db3f18db55a4f734a7cdcf01ebfe13d5ff7f4e8b0a1f5cc2e5a4f4f4f8fa7ad7abce7ee24d171cd755c73cbe339c9e7711d3b72b232d6371c6e1d875bd79cc7abaf22a1e7057b7b9ba2681bf83d5e137ccd999f2bd2208fc7afd27cc7cbe1443187c78fc3a36cbc4caa5bd26fa8bc0fea3fdae6835a791f54ebb5bb93a404b75ec2d5b45cd88584f81f6df3d2352db44d8e0787e8fa299b1e8259191b1e1ca2839f49f510cba5e7f86697363da452a95444adb2728b6d7a48a5f22ed3435dd7755dd6c5ed835fbe732bb7ae53e2e3bbdb65bad8a7fe243d5e73f6a06735144047f340cf52517c8982cb135163e6879ea5a0e0020596e71923cdf73c4b8d71620c98313ebcb5b151ef8376db98abf783faead0f33c2ceef236e85d28cfa3542e6e146a75bb6d9ec72ee849afd0729be6b1c629f1f19a33b7c2ccbc1de8fcb04f523df3a31adf64f07e500f1df6902b824e149f5a890feb2cb7ceba934bb7a475e9d63ef55bff342e497abce5a057879cc3fb39bc4ffddbca2d73acfb453dcb33efab9ce78484f3ea486a38773f2724d5711c49e7d5b91a97bbc539773f398473bf26f89cd7fb752c6fbb4d516f1d7a99c779fc2baf09be75cee3df3c7e7e8d4bd27a7b7792a85c73d58d6dba255d7395981ed25c7a8e4fe3f2d2350f76c90185e832174208213a78a9f3cb213aa5eadc6672c0213ae8b25e28a5fba7eeb3eb058bbba03a892e549820e68a926cc684000a17150b40c15c3eae4390eb4a902b0cf4c9a587e29b1e820fc4f33bc9ffe29b6f332fbdcff0886d78b49926008f2f2f1d82b95de6c22f4d80ebd2730c29a3835c9e5ff6d04ee639ef64f785cef37e4800cfa5434f0702813ebd1cfc037d7248705eb8ee79e45ef0dce742f170cf9b7381c7eda20fe89073e15ee65cf0ae4aaaa783c0d8e8ecf3c12e3da479bc43cee8609797ce16bae6f0aa1c7a566594457e95b7aa9b8aa56aafaace32b7d6552aabf2693de899475d95f9acdefaea56e5adaeca37ef835fdd7a9f34e25ce5d1b35ebdcd89a2ddf839ef7b6a96f7c1a7feb60c513039d7bc9d24f7b31e5dfbaabf600fa347a174bedf74eb05c7a337dd32b7dd0fea3795432fe27858dc85e3dc04c0b950519d73a3a072286e14a2e378f495ca63dfbcc7f1d8d57961365f791f0cbf83a4f5d65b6fdd3257b439f4b8bb5957799f8c9ecaad573fe944f1a97f4ecfbcefa95f898f216574b0cbf3378cebec892dac340fbade58ec3b6e7ae5048cd12e2c25b5f843e8a5eb6729186079ee687b9f842968bd651ba987c55d74a3f442518f02b2051431178d1472454db54b0f3597a4c7472f75de0ff6b33d2070f9d647793fa897de5ef5b0b8ab6e158bbb32cfee270910459d1b85965e139d9a9a4ae3257bf5d8d5f165dfa6483d6e143e967a81987f6a1fdde2a886cdce8060b9ade50d16737096b144e962b1d80d307aeb9bba0bda7c8f27b83c3fbfcd9e33a844ba149d7fd279a7269efaf627fa995bca2561fd94cc21a1fec5c91555242da0ffa4479f5c91bcb2760b32b53e12812ee8b2bd3da6d6c70bb9a2d6c75b51609fa59a1013c5b399e726b490113a734db4c99ea59a60d3040e60a4cf524ec49eb567292774f08ef89be09414172f78ee67292e60f0dc245f8781e0e51821c740bd79b04cc7524e74f94fb2941321f8afb2a77a967242cbf310578986e57ea2ccb3d413629e7b967ae2cb7b24f25324fd6b51679f228af4102b890e1d7a3bdc7a2fd20aea21966a42886f1fd243f079aaf7fde0d7ea0575abef4fb75ab6ba65824e5e27f9ed39f6c7fb60cb04ddd7fa867d57a562180b47d041df981bb60d2211c8ac04de10e392b03832dbe6205b98f9c8c4c3f63ed0715f588681a2bf3a966282cbb3940b80f80fbe9492fef38cbcb0886e25e1c567b9fa30f0f042310c14fb5f1d4b2d71e6594acc972fe2a3d748845dd1619719a2d810c3a2858b8eb7828a10ade0020c4b7ae80b1ba1662216dbce33880b741173b55fa08b18e45a982798fad91e150bfb09b9163e2f5061a257ffa0efc4db7400fe8c4a75305916d3f8608b177b6f9841c45cedd395f8d282229eb917fa42d51ba6e900fc71092925c44085810ed50eef0162c6aee87d5eea6b01edf542556f5f00bbea05b30315c49631621f1df6e5e8437a8d3ea40f41a363574ce3832ded7da1dac3645746f7b293b9caa968ee624e01edd65e2af586a1ae830a2ed5a5a2dd30ec6a0f0a8c941d9f3995eaedd1db5981bf04b457678e85e8d9555a62407bbd61e865caae1274e823254cf67c42cdb7dbdefedb8eb48f860d39ae8a740b03ddc769be9d47023de40980811aa6206fe0b85bed44d1473b1530d1d9f5e97ceb4422ada8f391c8f4f6562432ef91f6d1def07ef5bf5611066a875bba788b14b19ad8b104967d6a27a10609346f216743c74f653abb74dc67de16cc05bd63970d99b0dc44a27f3c86f48fdd4cff388dcc3f688556ffe016126c383b472239aef9c7694a70957f39d63f9ecd3f1fcebf9f957f4358fe1de9fc633238fe7113a901bbb0112fc1eb3c1b5e0d8fdb078ed779dc3e58471efa8adb2ccf435779dc3eb4340f9d04afd26c4a3763bc0f5847d9e8e884659f0fb6d924119de823c214e0334ca16fe01200055d2be79c39249a13757309585da8282e511cf183980b0a4ce654c0b48799ceb5053a793fff793fbb74e4ab76bfcd35cfe956f4ba3d3bbbf43ea8e63b00d7742bba170c14d530500fdd57e4a37f508d18279c1073e433b7b08824922822caf6050c982f99c7748489470b535f21f5f0b62017ee48c6a638f57605a319a114ce0bf24037b96994c24fa91e22d343746bce687ae6d083471e5e28d5ade864a21cf9e9f0870efa57645e2f3b0b6017cb590e358388b9581e3d684a37b9157e98d1c4cbeb85f3e62ed4ca7550c1c5ba54a2661031d78a73ce21f75ac0cab90bc5f9ead6e803fa02d8c55d30cc46701888361941d954342f0e03c5e944cd29802b9a1b4c00f4ac097e07399566376b5d6e9bbd3baa14bec2987d6ac326e1671fa55bd0610f1d74d846d52a225866231a8bfab7c4a3e5bfa5eddba32f1d79597d66ae79fdcd2589697cd081a99f578b697cb025f6d44be1217774e4a992234fef4e762196232fa11518db3ea66143b7be2f74c8463a0aacc29ec252b7d433ca3c865ee6ccde0e99a74bee884a66eaf173463da3f436a93095b57793b1ec533a27a3e945d27b85e8bd647e4cf49be2d4d47fd94bb7ed61e0a5f75de0a343bdf43e0c7c742a2fbd0fea63d44befa3f2d183bdec408c0367de665b335d45a1ff35d1871e3db677818749d85cac931175e846f461930a9fc1d02de8d5a7c359a44875c91d499fed2b70107734bdd52d68ab272f0db3a91785fe175dfaf4a4a8beaf9313f42755e6cdd9f7bbf2dff479914c789b580fbd5ef97999e84f24f2ee2089f4e36da22f85fb78026623d53abbed8e70f6909d415379f5ae9e4fb7a073eea97c7247d3abcfea4de7d1e18eaae774ebb34e5df3a668ff45a7378af1f136a930f596dfaa66f5aac96e49e9aa6fde1e230c5c916523aca9201be19f5cd6b4e3a7c88f53b4e7becd9f6217353f25fee69672472ca74ea91735cda9c7721557e464b472e9452a577190634ec51d653e9db922ea659e15d52a79745aa005fa48aec87d8a87ce81cefaf77394f9d690870ecc6781ff9268f34ffd2f69fd5ba21f3de3940c7d74ebc10d744d2a4cbd7673b8a2ae5bed4f103ae58ca80b47da5639a8a5b31a57047de8a07f3fdf4a4d2abcf9a7c85221e8f253e2438742530f9d9eb4aff0e14db27dbd08e0b79e7952b8b77773c9290142b359b7d625972473eb924bd265fc76977077866e41276acbf9763f96736eb9ae736b39d6ca372fe23a5f6d5eb472bbb965b9e536ef63b1582c975c11e776e5ccd9ce83cef29c5637a85bd0b95bc46b79dc6b05ebd9fda2db23293bde5e2f38ee058bbb706e14af718191dedc0afcb2fb99d3b6e69c8ca22b2df19ab73ebd48f3cc9b1eb923f84e46d2ed65e2353fbd4815b915f8a7572e097fc1ff45df41c232f8e8ab319e65e62587005e23b922ea4e2aed7ab720bdddbcdc2dc9d3ad1f5677392051e6773c4b21f105092e4708f196d541c077900237390881153f7041754674c0052ce0c18b105ccc97a38f1944cca5830a2e761f6801db5b5e3a74e993a5bf60df1fece59532b6bebae6c1879a073923e8c1b772835ebf9d1bf4e07375d8ab0f86af1e19c655e6edd3330f3a516c8f1fd66e6d14b60c2c1f61e5a3b3ac4d448623e0e7a69994984ddac033d6b49967ac21439e61149fd7f01775ab4da4e94dd61dcfa86de5ca4df71a06a3c6951b342c850d61952b37dd6440cec8bfa3924739162067d41ec9b0b61eda911e5d294e5f3a529d1f3e06669644d3b6eaf1773c3e3f73483249e5bb63e59268954ba2c17921ffc456b14a327714ef079f4302c380a1e09ba00ea01345160fd634c4d271842cbb69e0469c59f3c9872e3ff3fe8c72144d4867be09eae0619cd497542f7de948967d17f8f69a591684d59b0c04955dc93fd0332a4746beca1bf9073ae490c4a7d26336659c1b6f32fe8426ac3e980a5e5e996561d9077a125fbdbfba10d2db95fa7e4b3c5a345f523d75e8fccc9ef4968e44f96f4905631222b12a19ddda8d5392241e0049c60cc440dd5c513bf476faf6ddba251daa9bfec58754bebde39c4854da6d06829f0b4febfd60dfdef4da8c1bc6d5c780f899c755b0220c7634e228219e3a07ade85ff77d7728bd467d3f388554996fd7a05499d7da3017aff626478be93eb946b2e9a14f7b23d1f4d007a53e4d0fa979a3736489952f53c0365bc4749a981065e2185a64126ca43f888dc4296bed3a1d1df7d67f2d2d8d6eb59bd129f375ffb1541118a8fd1322a28ac5209c82360406d2cededa1b066a6f26ba6f7b58672c1261974ef44f8775eac7db750bfa156a9278be420768fe9368befdc7f3153a00f3d0396eaeb669e9d4d4141a5b1021ba9d26f8b189f5947ae69ff6e6dbb3297027c9cfab147d7a76eb7d82aa2e76b5c9363dd471b593a43f2a1f2f9ca25bd0576ab22e8199e910602c778c2c255fd9ad18e38a81b0cc73cb731b9662f310ca35cfb28b04228d3768ce245144d412b38cc1a60c1921ba4bc7d24883464c12700bd4d26689a758c1055d0b32641f0662177492f946ae288881584da6832eb923f87cd9ccb3db56b7786b32dde48e649471053dc26b61c6b1e95ced2481b24db7d871929840bce4da10f9e696ccbf9985fa37ad3cacfe49374da4a289b24d0f45879f66e51b88af6822910aa67db4cb34eafdaa1a2b6cb2b4995bfecdf71862342b1032b7be3883ef28f5ed9fe69303994814c33eda61134ca4728d22defaa55bedd28b62a0e8be28e61b4dc3331d83ae5b0ea324c22ee8b677f88d8f44987d7cac8f4428fb88916174f6210fb9211fbd21677432e38ae0953ea564ae4d7686cd3cbaadedb689ee93b0b922c90d63942b66a0ccad75e959cfbccfe733eefcd361ad9c39fffa37674e610902b1001117a28fe8198edb1ade2ee8b85b35ee07f563b038f15dc38eab1a4df16b5c66209cfbd9f0d45d8844ea124cc1070289ddfd7458f7eb9e5797bb5f1bc59f6e45cd230351798c9af69f4fbf852c7bf5457d8b81a237135d647bbfeda5b313fcaff5d56fc9672749f7d4bba7f376701e81009dec568cfcd4adda826e7a746e65ced9952deba4f7a993c02cbb3b48e69dd22fe398228a78ea8ec562b1a7eea288228e7cf423316e3986940139e84472d1f99b39e9908b2e71b09009e2e1d291c7c142e6040dbf0ce14a43022eba8c20cc1822d0028c0e0d96972eaaf53245192cac17ee798c0e2e1863458831559c18229b73d22c036952b0011064b1e24b9b2cac24f1ab9f63ac40f173cee905c674749ec7e870021db8fcd7391b1e73e5cbe7e0c4b70a3a1ea303961f7345cc181d62df9e33260732dfcef342c75cd43912c96864672ff44aefb3e1e59c9ed294f8ec369eaf170bc821193b4e4d750aafe4049fa57fecb25b554de7557a4ffd5e3267ae012ab8b2cbd14774494618d2bfca63aa80a9d16bed24fbcc2796fb4b0a825210c425073ef8c18a178c81860eb0b8c2f200bafa416f59459a9dd6eae9785db7b8643add82d0ab10f15f0b4eaf734c95217e7ace0cfa2e47c79fc754c9c0ab9ec7e030f55fe752d42ccb68067050250756baf83c06072fea9aceb22cbb12860f6cba1ef4dcc018ff79c78132b0b4e1a1ebe7313898f18e839bf6710f4285590b6806eadcc0941ec822103e3fe0204486031135c7f3181cc63ceb790c0e47502d26a514478ceea16301417b1e8343acc304e9743e3d34fda787e69535f3584b872386cff986088f4bfab43e7f6fedb0e5bfce75f8f29da5cb791e738313df3974389ec7dc60e6a55a3dc4eed3aacf636ee0c17f1e64061cc1b7e4b3c48dd511aad0e18e10868ecd4a0deb011c55c75e34eeaa12acfa3e3f74ad810ee7596a2a060ffdeb3a2d54999acf5c3e3f484dbd21c1e5f3030f39ae2ccbb2ee40579fc7c44cf091c810355c3e3f6c3c26d60411ebf2f981a54a781e13bbe2edf398980c82a055a6204d45835e35b97455a5d5cb14f434fbae3986b8e93297cce4f34ad16bb7ba6a3073e9df92cf6bae72ab79aa0f74d4f9dbe5b3a684c9e7b3ab247ddeee10e8f8c01763c83041143800c1150ee808c34f10bba4ab25211b01cbe33c4ba5518226410721749d6f29e8a9670e6f4eb7a08ed7758b49134caca1020931c078c0cc1943f3b3379f5d57966510769ccd3631cb2084b566af20c00882891b9a6041cc8acfbcd3c1673ca010c2ae5b393fae7439cf524708e2b567a9238460e660b9cc17e4fa8a441813479ca0082ede9c7106181757f1dbb31349c5628c043d06c518638cd023ec6e973107411febc74742021159a820a8b7745ff7dd2d7fc9e7a33ff523e1110384350f5d7a4b3ef2a14b98a6210c424bd928270d6a60332948c04a81cf39b339e79c73ce39e79c73ce39c970d1428b307e004110ae49c5cfa9c54fcd35e78c2c805290809502186950034b593085460faa4882881bac9142ca46d9a08c3158a459b3c5144f441438a5f783936694524a29a594d2ae5bd2678e4ec753665e348f44b4db451fd2ef579f524a29a5598ef48eafcb304d831a589ae3081da61083031d8600a206613a1430ac4a1a665cd1c5064170c10e34a881d5b2ba7d96f17ce699cbea99e7341196cadcd988eab3fb2df97ce699577fe8328750ca1e4881c5164c5c8185085ab832293ecbdc0824f8cc799a08cb95b94f0fc9cfbc1589b02bbbdf52d0cf5b3dd0f143e9153661a7208d2d69582982118a3084229c61069b2ede0c219edd3e4b9981458c6648d1411e102112dd62a9aecca7f742c75c99b3f7453def20815d7eca78bfa8173a57f6cd799b582faf978c9da86319f3d5e1e883bb15d104412db6c47e8f73be6730f27d05f0dfc6c542345da479e8bcb231c618a333072f47c8451920e4b394195d9ebb152ff70962e4c855e0942b0c03556121129d1964a20f06c05ced54a2e7106f5443b7524aeff19fd41368266c5e265e13f5fcc54f67affaf4a437a3116d5cf5c6b80a2d9f26bd1e6f217310e8f1ec1367b70d2cf3082ca4a2e31a7439b1e3f883bdbd26f8501006fb2d23b1fd58c8cc8c83813a879d75a4e858ca8c2cdfe16023fcac67292010e1b95b3db04df01b0c32bff9f4f65ef05bbb4ad0b5767aaadfc453469bab54ce77aabecca76b1ea340fa064612bfb9e656e3a2e69248df9c39241a75eb9b472e4975083fcdadf7b536a57e533c42ec097e7b19d0332ca878e999af49e333a72d1760f83224c6560fed64ee3ead2533ac115384c81873feb498b9165853cf1c57d86058d24393cbb0f02cf5c59a205966c87fbce667b33f65df3e3d34dda961a5defcc3f7cb9cb922abdae007a9b757ef07fb3ed8674a1f75f62f43422f95acdd2dec2431497693406f9d1ea23e9dc77e11fbcc9b37fc579d59ea09345d8e8ddc51f58fcad443877d43ac52efcbb21b1e7ac7361a175ba392f4e950c6ea444f9dbaac53c6ec7efdb2ba928a00a2afae7149a8675e3de61fe97ddc118c7d13947a66a01d24525a5cf1dfa4d98d517eb1df9167222ce754cefceceed3eaa1cc61aff238af1ecc5aeb44bd793bd535147479e91c98cc6d112f3ddb81d44bb7d2ad8541ad09aa29be7596c7aeaab49384fa94744593d015b55edd6a2ae7d754d7a8bae65a9b97ae72352f5d69ba76b7cc48a552a9aed2f44fbab6b952269dde2ff3ed6a4e14b53ab7ccfb64ec2bcc415c56587e853948e6d04514b7cc8bcef2d8e535c524da55e25c0e0942c779cc38b777c73af5c9dd1d7bab672aa74ab5d2249556d7ee97b9756bbd6ff31dcd7947bb46d3addbfbc11d9879e9d66d6f4aaa2ff3cd379f46d6ad7538a559b7fe19fc23cf2ef6baadd80817898230556f3fd81538fa578d68fe69aff2607cee1859c8b22c5aba7107d834af5fe5c19fedf4aa1040f4d6551eb46e559bca88e99ba2b61d5f3904c0babce58e605dbe69c95b3f00cc87b76eeda6714882b8cd5bb7dcc6b5d01febabc3b9faa2b43cf51cbadd3655c3d5ea8beaf2d4adc7fcf35987be714adaedcd3824edf4aebea887af35874436c557e2327aa311ece75582de04f55fdc49f25920db009ba8032e39589303326c280e3b44d3b17f1b7bf0b9957c9e52e39999d9a85760db2d0bb247ee76dee2833ea314477a8f8f4e9dbde9cd19679c41e70ca679e8b5532f9b6fe79a0e7a731966ccad3de8137ed141b79333e234196dade00dfae6db75abc747f8b00c462b2c6cd3350b9ea5d844f15d8267a9308400e30c92a72a6dfe8339f149d9800c9e1dc2365d84e2598a8c1e1e927996f2010dfee759aa076640ee4845859a6f5af26d48f04d51abff9e7690039d12fcf7f4a5047607ff3dedb083f9df8b8b16fc708199ff5e62cc7c8dc59e79ead99f7fb04df0a5196fde7befe59d6760f9b9c5c316a2f7fddc00f1d2e507db4932b778e9738bdf81ce45df0bf692a7a6a6b63c9c403cecb9c54b6f0a09f03eb5db3e82532f91408f7e043dde27fb6770f9a7fe79bff629f0a3c39ea889dafbe879df4ff6d96113b619533c64dd8f0e616c95b792135fbd1d36f5aa7975dbde577dc7bafc38adca6bb72b6f67e5fc1fec57be799f4a759b583fa5396f67e5f0595c12d654ffb4dedcd1ca398fe59bb7729517376edb3c46e3b9cde3223ce7f55bd990279519ab7df3d808cf4dd872b59384a3989afa604ec462df695ee5b5a772d67ccb82cf4aedd5bfea7c04bdd6dade8da4bdba5d792b8fcb6033dec66de5b11beb2bef457f4abf0c4ef0adcf1bdebacd38b8a6b3ce1cfca2b39c66460865673c56d6575ed0ab3c2613c3e1ade6cd1959ce72bea934dfb48d6a6e3da78d533951735ed38e57f9e6694e35d565fed12e7d768a732f07290d2c44d3451168baf92cd54512cf4000e0388ee3388ee39c7d3837d65a6badb5ce3e960c4dd3b4ead4354dd3bcb211f6d1ae5207c3f0b4e8c0739379ee160351a7dc04a7a05719887a7b508a4e8a4ebac6468adaa9cbca4674601942d17db2b3ac237e9f2cc62cc61833ea99b73110955d74f9e92dea4491a869e6947a467b04f6889fe5969999991b3a7bf021b3360662797bb04cb772ce37b70ecb742ad7bc3a7558a6cb58ac7616cbdb63a1b10c7fd0498fd327f5ec7e1baba4d157df9bd6a3a8de5e2655f7d7be0483f0f332a9545e554df055698af8f92a25d99c9153a9e6bc0d81649ff16bde5e432099db086517b16fe7b7334aa59152e1db89baa893b0d4f7fd88beddd66d3a4b3d4ba5917a1ef37d65a6799ffcafd28f4ebd6f69fbe9d99d5783130636ba8d1e0b49e659a679578f9a57d76c36057eadf1eb556aa16af783bd066d8d31c626a8efda5ad7aeedb07de39de8d08920f5e871757adafe29fb285f9d39244bbe56a3e9f1c86974eab66a2a8f51e5b5c6e89a4aa56997f9c76816d5eac1c95d8554caf2c489d3ed6c77590aa12833b3537ee835413d6c8af0b2f7c95a217b312a819c51efa33ea5fb2519bbe1bff6269ac60d533fa57e9a671e3d25c9b7bdad7d0a6d729a42ff05e3ccdb55b709a6f172074973459d4d3f80d1fd9aa05e3a7fb0a7d0da6e87dddd0e2bf4a6de2eaf524c2293408f5789bd19a6c1ca0127f00816caa0eb150ed270269d0c3a3602bd231482856e59996fcece41afb16af33224d6aa58e5ec9005dfaa5c7376c81545cde351596f0a7ce84d81afc91857f036c5df31baf0ada75da5ead625d7543f737b79e26c2e5d73c8c12dbae857bbf5abaea9ee077b1554d9fb41bd8ddf7700e89a13c526a88f9ac74df123d4a28bde7dec2609f43ca9b7036f13fcec4709b440339dd2f41effcd0bb3748b3fba855992d88853d07b618771180e9d6f76ad5c0172658ec5860bba7498a587725efad2c32cdd921ec46024805d5632874ed4b08aee8359c078e950ec5df48106104b94608922d4c462ae2e2655d04310389ce00997952b402ee8586cb8d8ad5c6917752c047041cf3c2c0470418579013a940bd187f49139549817a867178a28fa904e2f549817328717caa30fe9d90de2e8434a0afac76638083a48e1858c1b10e10516feb01fa6788204241883e688335cec62ff825ef058cc05b3f4500fa8a55b066159ded2a794fec5fb457d9c5fbcbc934aa79729f3a568449b9f37f32fc6245c850f9f5d2fd54effa27e0906c4674c03b022753f1b3e3271155a7efa778197d935f3e50540b68042e2600c1c54f15ea0d8a35853535340b8b458093930a20a0f62d2a197580f0f28d8d2c509005d585026f61485d7bc9718902da0884d198015291b625c851617fb77819fce9c0233908fa56e70e59fe07bc181d7b8b41be3352ebe50ec514c2430011737a4118bb9ea8d5989c55cec1f94c72f0abbf4a237d700205b8c9972b133d7001c2f7290822354999a72b1e77c7c819d6cc6851ea22efd0518a4db964f8b0a087d5a3f30057e19e430857eae9e74182010e92f744bba0b2e4422ce66beb0190fd3e1fcc77a59db834f9bd20b2c99218a0d309659b173f2381bb148a44bc845e6167611539cee83de14f81f9c026d33e496ab799be2abe055821e3dfad34bdf7e0709af799bed589f2fd9bcbd0c817cfd1336c7154320d3a5b7b4bdcc3cbbfc2c839e5df382de5519e4a283aef2a8432f73ada9be0e03b1578fc7730662e73b6fbddfc637a491c599b7acdae6a54f0f4ed17d55aa4af550bbf44aa68732975ecbf4d07459a778e9f60a58458c910a08bfba457ae5d243fdd22b103005ae5d5e562d3085eea7de664427ffab5aaa5732522c4cafb7968101a8529148d5127d4897522f55d04daf52554bb7200bba797790742cf6d1a362b157ba1f093f459a79e95fd5f2d22597848d00839f7769face0afcb3fafca7b7916147097f7afc2fea67e6c1cf620a2f58547069dedece02d8a5b954163578e67a7a0fd8c874e9d54c24625d7a4513894097f4aa261259b9f4ca06a6505dbaadde97f94ef51aa6f81a6af02b6fa73a74b5cb7a3bf526a0c6fc0a745977e89ade0bbe97cdabf7d540c5c7861ce5ea83fd8e0b2adfa12e3ffe4e0238dfa1d705ee56e1a9379acbef874fd49b5705baecddc96e136beabd6019e2d2bc0aeb08ae2bd0a5b9951a8ba96e15aa31810efd09e83583cda667d828a743486b36a747af5e376733a1d3ade9919b3178eed67409b979e1cbee33967d4618ab47cd23f59879742df39a458f99c7187dea742b73fe39e699e238f41db923a398f4ea742b93b23210b71896a74f36029fa75bd397789df8551974edd0753c1251f9f45624627d7a500f693cddaa3ebd081b7106aa5dfba8aef26afba8376a9ccec3e5a7df6023f0a7673addaa5c24f194294eb5f2d577e80ebd525c34f12cc50513dad5e9569d0cc4ce9c6420f68f4458ee219a83d847979c91bc9f077f4a6fe9344974e95552875c930d5670b821f64d5f0d4530c2d467fe827d765ff47ed27ba95ac1e10699a45e69943933d037e994d2a3cbdb04f55f94c2520bb9229e38dbc639b39195676e579e11ecbfcdeb4aa93afbe67df5598a8b227e3250d69c51b7735e759507bf5df334e718f2fd34d7bcf636b71ef3dddcf6668f54ef7673a2e6eacda0dbdcba0a49fded2a69de9f96a45d73a2c89f79d3634f768b37183d20fdd3f9598bf4d00c1a325d67ba7381e567d0cf9f9f3a3fbdcbf1e91b4bf960992133ac80658ab3752ba70b2dff55339270a1873e97ca19fa8fcf489f4eebf4a79e79113af4d5197ae82bf2d4a91fe9a1214fa92f59f33447329aad8750f82fe7bf22dd6a8fbe815b4c3d6d34373c75ea393d249d52a7ce3ef42a719b4803cb10069d0e0fd72db67cc306dad26d68bebdcbd161233ead8285683a1ccb2b0bd174b2842a838d5d628c43beab773e5bb7841400cb800d7070850656a8694119179f8023b908baecb628d3df7e6413f2ed5b6578e5b3d416625efa60194a75ed7533c1326462158516625e3dcc600b363400638917b878b3d0a107dfc20dca6e41e9b55bada4ad7fe695298eec16bcdf537c769d1eb2d4524dbb9fe62ad7a8a4903b0af2dbfd3657397d8aafb985cd30aee8ab348fbb158930037d3c0fef97d908a10a4ff3a10d9f3933531cee16b775ab15bdda2df84d30f39e62d7adbebd751e89c8e82d36125f05e707e227b52842674a88848418b0f2b987a6fb88f9fb2c95c596cfc2ca19357fc64cdc785c7245d2b98794bc3da53ca8f469140a74b1204641c7109aa19126012463146030382c148d4743224d96950f14800ca2b4525aa08af324c7611432c6184388310000006400606466d80058c7b76f9ae5f43fa19457415263f4dff7fff0c9a67e95f940dcb9dea60be3793610c043ce09f8d7f96980740824f1b4f43028af632f295f0eab3120eb62c747040d92a07caccb380d0053a366dca3f9dcca550c938fb2b84ca6fe81dd317f29869bed948ec1533f097507e3d02e087e292db7195103ebd7f588cb12e77baa04d1b9e8c8a039b0f04558081855fc5e12480a5703de2c6d89808870aabf28d698c9c0f61f503b3f415d3058d02364743b54d17e4b493ba8873fbe8ff884cea76101688b349355ec4e02b66ce3f55955a14f492e57292559de082cd2c15319497255eaea7526d256eddff971d8a92483b2f45354b66b454e5da0c064b5079a0fda4321c59ba1a0d5dbe93cd0ff0033a6ad5ce03009720e85d06d855454c18804e3ddc6c12aa4bcace55d5815be307d40a8af2ef3afde024036b45dffe4ff7ee99af40315eefa20d0948bb7814e09bde64a0ec3a38c026ddcbe9beccb198286f40fff3fe77b96d188ff474f7ab77cd2280885fcf23a926f13a08242a5745415f081a64c421f6e400b77430f77a03fc81468710f34e3163423b3d10fee43076e439371877f7dc496d9d0b5cc77f58d02b72bbc92d51ca67481f6ff608cae9e43dacf23199e8888ff3e95fa184235a298ce3087a2385e88915bd233ac2b198caae4bfe5a916041533a45fdef02ba9c7bb36cb23847cb74b0b14e644d09d15e288f0cbe1839fce496bb149504f471c8f0f7451a86cbaa7bd29889e5976bc404890d47c3a8576e04d01084bd893ecf9d6543f58f22906ed02466b0d6bbe5b5204ccae9def650f7ccca7ce89b6e194b2a8072ec568c26cc56aa6fa768ec5a13230cd99b15471170746a92a3b7f81ef09401798325d59dbe6afafb00c444ccbcf8753ab2b5c64371ffebac8f1fdf9d54e69ed66e04993f72e8b038a435a09e0111f00b9a9373ba1a9270c493da663b40ac08f969d40f08d3246cb256af1f239bcac4af872d7a105c466269c32a386d09ebc66f5d3a8a28ea311573fc7421768c9681006e6c63990aa58a216e0599702192e6800d739c28ae610dcfc15483a379988dc69cb43e5636e74c6a407e8ca8bbe69b1db12309a26edc1dd43e19f2cf80dedd303c8e65ae81ae08fb304d05b6e3b1333fbe5c2bee7d2dbe79ac766bb0d535747a472604a04c00450a617489c1292c1818ee29c6a98308aa6f64ada19630f911b3e695eebc7eb57da3574fecc9a8acd468b8a8a4a0920eea90b9d5499e0491587879095a14450720b9d0fc1283300841bbf810f31e4f4bca1f5e48ea6341ed8a31a90b40c6a910e00760f297a55c4bbd38517da97b42e893bf4607740be9af2d59fc43d19f87e532c0d1149a51702738d0f6847849b77c481cc4582f3451b2e9bf69e189de77799aae9c3b128c0d92f08d4e315b3cd29a3a56343c31265763e21a56bccaa28171e2dee41dea6b6d6666cbbf3a0201881eaca8f0428ee1c55efd335d3ec7cf2c88125a064625d64f90fb738a48d77b486c8c3fca9a2ed2387771e7b769e69a2f6394b053c7782167842834622d1e08ca1f24cb16d5a5c0912de2cf7752d6bceb60d180b324e370b8e56efaedb2fdcafed825536bfa2e763d796dea2a3f1d3e984824cfdb0d1a48c2e6c18a3cff6d0efc777ceb3edc71f099640628bdda7b6f32c0a199d694801465b473ab7e74bdda9a77610d3fbe610ab9020e670309a951322e87b3eb99b0f84a9395804c23e14facc5f2d2c595fe1489f4b4ea0d3e98526fb00bcaec8ef452aea9891a38ab95db264e8e718f974e6d6be38f63753be2b7370fb1e97c88b96598409dc9fed876f08ed2c4966504ac38c0cf52ce2a852f3101a11f63964fce7dd20221c880ef434ccf4b947b567afd12f4ccd69a34479bbd69885ce4205c56d5007b6b8298fbb94f6b7d9602b6d733426c96eddb838fb4404580a355388d219e3c88bfb31a71d3301b080127c1707bc4b360c11d121a8c5d48440a01f771bf8d2e8f04810bd0affcd62dbe0bb7ef7e1055b7f4416629b09472cbe6a0e1134afba5a80068396123065da8b651cfbf62e1ca3371d9293af12de6d8c9d4f3769d39b23d174326aaef54af01f319af9f6d2821fc0e738c0071726209d26fea1af31d7afc611628b9017a020b32d7e6d9484cac80f89369c70f48d2218dc08bb12d3b16c93242d72af5991dfe8e486c92d2b8f36f698a941bd9bea7975f474e643263287eff51f9d438c25029dd1d9bc6b9395ae8bde79ec86b169d41d591d73456302f65822418c703e290f32984c4c654c4fabf839daed13edd7b12277ee3eb73a8d5f1db36527063a2bdb9417caa50bfd93a9682698967b0666085b5c8dee0503e1dc418805865c47845fb6de15ef40cb2a5671152e9c70ccea1c60afcf7683daf49c9a3dac1e60401a30ec566c00a82a2284a968366b8c5d83ad1af9854f00868c0ef3aeefd114853d191db38963e1843d26a8d08edf6b884367b10dce2bf249e34ccb6ea010d1eedf34fe86ee2ba442defe6a1b745eadeba38b44fef1a3aa57824d8dc1b10620c07a8d4c0f63c376febbffb527c91605f83b315a650afa999cbbecd553a79540b3998f28d2cb84d4f553b0addae8877dc112bc927081ae1becf37caee8beb34578cc4509c89434b8bca9660f8b9f58e8b028eb6c6cbe0a58209b879b98b72331d7cf603ef84108bf316574928ff16a2fe498fe67e30e998a881a37727bfd666fba2c03610fe7c71ec2cb4ddea726551f388cddc530c3341bde649aff3f57baeeed81fa754a1ccd68c4d850b86ea669628d02e883fe761336a1da41d98f4a5ba0dec5330070fd219a3f48cb767f1506b7fea2f2be6b1324cffc8ce800de4f68f8ccb24d030f10b1ac43abdbd37c151e4a96a86bf7fb1c294505c6f0e749282adaab4b0152b994b49ae3b0f42f7149f138e7ebd23fab4c3015ff55653029bf6231328c276f5493b5e98ba50d9c8784502365e7009fe7d58f62cbe6da64c51a784ffefc804cdf7173a5cdc877b904c68d374cd07e8828d9f0a77df9012e5781a91bf0bad69aa1112c69b805e3034ceb7bafe296c76a33397cbb835e9cc273b73be7593980cf6a99a5a403e870d7ba141c4c015db92b428c894f48954dbeb8e6a5050c7b1f96c3cc90cde317672f6f2800c2d9b5a303c544893fdb3869b197a9bbdc014000fd6aa7610dbd1bc788c4f93fe60a605c1db73af926a593358501dc9ec9497fc639ac322280ec98ba09a3ca4dd37cac9b2eecec9a261978c634c5b8638f81754d7be83504467c50705ad74bf8cd0cabd08522bb2e10fb1d1530fccaa93024d2439f6722c930de0c454a5e773867de85a8a8f6d12e34bbbb727aeb05e2420be209ea6ad293a914dc6cb4a6f41f52d95811c9c411cffbc8d78ad145d23d001a1cad073560babc9278c3ca8e738f8e984cbd2ccdbacb2cac6786ed5e4b9b59ac37bb9711d51ca40f974209c7d5ca379e77ccb36b95c9e8403e734e0ce63c589da736bdd2ab163286c98446df35feb53b5b61161df4ab6e5aabd47a735b22e47d5567ca725c4782e7e36d7a723783cbbc0a2b09cc3a2889f88427bd0ab6cb41758fc2988167f5cea05c91e00d91f80f5b173b6f2ab509891b8d5ebb1907e36e3d8cf477f562dcb8abd7275f539ef7faa7baade056a61b8ddbae7372922a0f8727852e081689f0a03f388fb100e5cf3062afb5339e0bc810706f3aeef0571c7e3c3dc672a206094c8dfc8b55929e63f24ac40ab7cbe24311ab84fe6b2f926eb2d4f69d219884812437e4375aaf105e84307b1d06e2ca6f04b1da4f935fb42a6cd0424d60cf9107aed09b7c1905257b852514ed7ece022fe4e805c09bf5a43022ed7a5dc401acbabbde7a1da1341173cd669e6669288e65f11a8119b4eb5a36d4ff75429a4b4ea78e5641905140adb5171360337292dd605234392193b4a3bd30f5ba48b0f1b98e25a36f910561aa8f1dd5e3b5221de219924eba84b24f50cba53ef3328d5f3237d33c76de97a425265275097d95fed23b900856574d8e648bff82e2d84068f32f7d2b5673fe43499453506ef57307ec02ba2406abc6d004733328c22cbca945ccaa49040eb5adf7b2948e4d86f9354b2f80c1feed4c91c0dcdcba427b7b6e047a54959dad9e29b104624fa47a652da9828e4fa754405295da4872a84e6e1db7ed2387f8a92bbc626be51a8f75b36f043ad78f202b6f0525f77f99951f83d580cb4c1f47a9f4c4918d040b059b7068b9f931aba13bcdfe8b6362f18e5b26157f39b92ba59c1a05be30d43e1be261e5db6c6cfc127f9fa79415b9238e0f3021d5801347f5041a29f1913eeeff1a99b2b38233f73b14cbfc8b9ae968a2ca6d1d97694b1264e5a37ac19cb0aa661470fdc7e3ef1ced59a9baacb1939fe4dce6291b30d4f07d3c3af91567a7c15cc2724a3731d6f21e8a03fe00ea47b1c208390d9a518abbc97d65b92cf1fff96e600f8a943745255a8b2fcbff8651e5141795b04294ef063f9dd76bd37dac085973a49d37c1603927b612cb5d9456de9c653ca04ce5e6486c61d3345b4b817421057aebb366b17783ba57d7d2b0e6f377f459bcce8d420e12a6532abfae995308f7feb17d9ddc7faa67ea59b64690bb7555fcfb6bc5112ecdfd55f5a3c357714541a0b66af9926e13ba169b8a57a5e1a59aa67cf192f2089a7261262a3c4f62723ccbc579fafd978af3ae674337a79a345ca07f20e6b128f04717e246b99544e16495c1c3bfd15c8ec092f73fb4ee9b0263b97295f09109d56b27e80b261b6090a6e908e5375c06bb69eb980dd2df21d1397fdb0e300b5e9f121b85ba42c8cd1bcad0f470f352349a5249a5ce7be5891f611c8148406b1c3d7350922dd83ee4613030043a5f8b2711982a9646957fbe3fd31ff6c07ba460c6d1a087fa1b375b6d49c115f4d316c98899eb5a3ce7897ed0a7d7c2f394782f4d4dadefad54123b8e5462d17a7ae7c01f51961e4acc93aa013975c3210be430afb67b00591e815a878827428e8015f4e1427e35f7b48e92205855d80aaaeb8ed3a54e9c97ec02301693a30859726b2908bbac7412bc67f84977c7b2a822cc86ef258582a5764a398741514a9e8c9342167d90336198297e699a0c07ba4385b0c23e78cc878c00e760821bf2b207ca15f53c73316861e40ef4ffe055b96214d64a10621cae6047738ec4f1b71d3256d69b38121badbc1e2e0c350989f861324b2cdc26e6a1930326c73f82efd570b41a8918113ead45125107677eccf8239c3fe5d8562b7f9d2448660bad6392575964798af483f546a6aa87a2f0e3bec5a42f0f862a3ecc9428782386442133046cd1f2353106f2b541c000b5e2050ca87a5ba5528cd3e0da025d3cf9b49bd078b6fc477ca9a74f976c246bbe219e5d9b00866c2ba8be0f14ea5c38a2b307f1729ba3aa14b1a7f142b4a8c74d03dc914fbdcb9a7d196468c7a50ef0b594a5ef2eba74bde87009b0134c3b0c7b8c329cb46b9e483777e71375ebed7260572240ca3cefd2328abd7842863c2c27902c0f407c8c647e4764f3d8d344060787d5ff63d42a97c3298f667e8fadc4c6bdaf9d74f458cf88283393a7e709fd2182f61e536a90a5f645f3b3ca00c358cd4924265e8d5b53db5cc5ba32d4138d939572b5292580f595e582cca6ea7daac17dcd5772abe9e522cfdc02c9d8adec3cd8029b050e0c0afba63e523739a24774be19013ee633fdb6c2220dc03ae5264287246190064ca44983d7b060038785fa70c52758b23b387c44f1868ce5008155ab22a911a03ffca11dc7260a8032533e9b7a4df88b17e88f8e5f13efecaa56017c9c11dc88c1cbff167b18a5fc20fefbf013a26c18ec3937f6071b78dea532ba3107e49341ca58d3621b372afd98ce883bea8a4427547e9d6a2328b4a26bd88c528608c80ba40223c2764913add97e01e847c2171c61f4167cdbfe696ce3c4eab6c43314e77d7407216296d0751ff51f283a7cd166c9c65ea9b4c822a5c85992809dc8f6a263b48b9744a1e7ae23d051de42964087590bcd3dc715c9f544ab32d92a898fad51a0fe08dfe881dee21425866eb53ba262c6c969e72c112194c708c300004b2a5ad0bdb8bdf7e8650c49bf2a1df9bcb24bf701d2445c1e650243c5cda4c380afc756e207fb31bb9067ef28818e2c8c2ee73c436cc6cb8f665dd1a528653e1977883a963842607a1c398aff58441bd2239b1c20ac25ffd56cc03740b5595943222b51853d639f03cb1251596f41d919cfc65c0d8a539ac659fa9aae48ee976db1a68ac7b18e9f88a3a431de54a4a1abe4993fab128213ab90fbd12e0219d50cea25b7dc0b08d9bcf06d3ac36c9c2e671188e21be3c844645b09a1a55a5101bea1fb9d8752ffbda71b4cb6b9d01392be33e7df43ba4168191bac3b3a4b6ec2264f5b9b2daf709ddfe698f0e70b1039463138fcdd3f1c98a0ab7f6fdb1703dbd7d3ff7f43d1071af2090d323d03615b7d25d000811b8791be1f83447f0b9bdca761b8810e96787008f5780d94438211df3ea19740052aa51ce2180fd186843495b11de24d9010306a485dd8fa90315dd686437ceef8a05f282d2e89f69026711462b032c411b51f89cdc8ccf5b28fb3a25f1282b8582a027aa9fd9d9976ce265a92be4e0f91d4c930dc95e845aa6645d252dfb616494742732dff45402fd9419a791fb37e8c1dd4531c5e3ed068856a81c6eb013c96f4670aeb08bc0c93606e8527811617d6b53a9857331a2edc238f9e7e5e34c470ae2a69719b5b1aadbb8c78d6ecd3bba14d8f3f06a0382420138123bda7f97217e1fd9cbb6cb785af0832c9c9c1741d8ff3b633dce14cb69e9a54a07c7b9e6a02bc4730ccbc02b877f9af468854354ae719a31345481d9ae5af425e8030ea4edc4d768ffd039c7753d465095a688cb949723bf53f423a8d2521c0232473fd44a86dfa8873ad471f840021b306a0931404976623d2ddcc18aba76fed80425d5f0360b84f01a6c55335380d36f8266dbb075a5e7ca748aef8b464536fee9740a76273b3a7c59f310e46f2bf0bab0c26eb70bc8d4393f3e84c05f09a870efd18ed70e96976aa65872f14378d1c01ada302e4b3f093a51df6db75b283af3b05e5cb48192cec5d5b053882548c837079ef2d078c4be4d92ff6a9c7193fae763425e698891169c2073b37545b001db85047105861e02c0c477808c7c2596ac8954aaf47ce5d7f36d58ddb5247346db00aeda72f1d1a50c26150a86fbf115210444eca6f21916887182a559248e76f9920e1c2fa51346170e766e66b682d78318a5639a0c908fef089bf9bdcd3e69e2e039bd694a896ff1b74f3d0630cdcc55059e3b01f2a034eb753202441564ed363cdfa621e8c5dc4c83f9623adf8b4dd0a314b712167016d61e69b1d5edec8559360673d467dc5859c106dfd6f989607d962bfd110e1523c8d6b400a32a6c5d1b49d96e5e06a0c47feb80224d753441370c0db8b7f31f840b21259374baef3bd3834b4f99f5e6ea4f511fd00ca840dba44842f3fa83f0ad37a46dc4a5988722c8ea1f340e860274506906a2627cf2444123b107dcadbc3a748323f278028509b5f224bdfe3c2027a11e9bb1af73a2023e45bfd6ab7bb7d5caeb260df67fb8530b8ec8d36299e97ea50e3f0acd73fa5899b9a406cc28df7798f2b401bf5d39e086a58646953f4f64c398c52e3f9c18137c6ac3b8996e7da111ccf83ad467a02f3a01944bed52a808e84c1972d743923296253fe72893b536f394015b4f58a159581744d06638c104699b3d991332d159c302d1b5928e39eee10ccac50980c490c85e4153d118a7211777f482d77012aca14c72022ccf5c26af7cefbf50499e632eb4e8ab2d76b1d29c3ddacd0b5bc1409ead1467f1615dac21d27fdfdd1a150caffbb2ae2ace49754ecd08eb1721f03ed448895c1f4486fe8539da9f188e11d4b11acb3b46beac833616b4038dde18c95075c0041c73a079a2e30aff410a94552ad828e79c590e4b1cb54a201e2dda91fc328a8017163ab7687fe29d0ba5cd98efafcc15da16985683f8ffba42d782c6398997e77d4a09bb419cfc8352ca9721dce40689c7707c8c52347f18044813085ea552131657cc90b66111cff864318af67f4261a4a335ce204e6ee2251f812a80b70faecab4d0c0adccdc1dfaf370c411b0e6d8b6843287e5ae3d84dd99670d90bb2f2b1e9e327bc2e626b52e4d751ef2c52811de5d2e79e3e4683bb327c090b684dec8cf2065d474a27397cfa1a7c019888854f8c306654540f0f06bb7722ccd7c4065b015af83ab27474708ab368ce4c5ecf3eaa91ac9a58cf07f7fede2342eed11a37b0d12691e5a628cb602b94d7def6acb76b01dc2becd6b07c7c3fa731b6747cadfd449f8dc1661d05c6926afda8756698fcfc0136a65a04d9d20350719fa449fccc8cca2162eb02fb0f15187eacde4ebfc7d8e7cf79249eaf65d8a5b0a3d1ee1af4485b44d5540e41c41eaa86c3ccd0d035b939db3317df54791e2e91962c3a18e4310992a147d61cd670eaeddc3f2532c45779082ff25f6081bdab80cf15bc4bad84d776a5b4cfb1ee1fca09941a81c4736deee8562a77c695c5195d713988c55c3878b2865945ad5abd482da30caed992c202095c15b1190e778d786ff3598781e53fe6c14bd82b431ea7de4c7521d07cae6c2902f5fab83793a441b0295d41c77d0bba91a8ec6952bf0f8f13ea276006710fa9f3589b2a2028e1d2be58b501d517dbfbaeba8e106a61bde22d77aecfac16bc0af87cd2d9c6f3d8419f513d336d427337aeed32fe86e0747f9e78bdddae1ee8279bb09884b495e8595084be80c416fe822d40922f688d372f3e383cb39f6ea9d976a04cf5ebb32156c0177d387d0c8093068a6f9336c3d40825c12fe549b8f6cb6624f9566bed6abc94dcfe207af48ab13488c902f6f4692bd78dd83a0d332ff243bf7e3a6c3682f987be31acec29f3626c80cef1fedd4d79ce9fd16394700a6cd7a4824ba1fb53d4e00baf2373aa351d89d046145843019406ce9570cada115cdfd49172452fdf15e0bb70b06212b8345a2f5dabdd8f8a45a7b0dc762f7ff55ee203fd0c196cd4486bb60e8c4467af85d5f867d5a111fa3a543ada650fbb0130132df7ab81447341c96fae088bcbb4f27cdeac1c84b72282249459e70426ed39c6c765bca5b0175514f21897a2b2cae759bd9e7e1bbb14da2e0849d1c9bee2ca63d97d3a41a12bea422427e5f6b9a497d5c97e83e180131d6919a11eeef640216eeb56c0d3f601e4f38aa519bdfd54483e85edacdfb35d388512e92d03aa44c7a58138cbb7614f763d7c2ed112112c6b3517774858548346cfbee6eede6363c41c25401b3098971a6c750889d0b21b5895bcbb74c52f82342f6969f03350073d045721753d3f040f4b04a73e8a16562a8db0044f3486336b6354d659a6bdcf31925e12e2d1c3c01610c11a41c7cbf4ca153eb50de497fec4deb4d7c581fb7ca2367ed79ab1bf2b8a6b09cc758121a7267aff483eb6bb3f2a98670b98d585466967de1a699db56020cd7e693e118b6889a02631b5f6fc0a9926189176a11017154abd4fa6f442769680ad026e488d218ece50e015eb5a16a783cc36775cdb638b8135b194fa60282bf9c5a936416b9e82ce02029cec195aaebf967ac4cee09d41f10cca3344cf542dc057d9939d78347724ab437f5b1d9b3328cd80b7d1547b6e632b712217485638d324b31260760a3f9fa86432eca51890c77136b325660eae778cd47e4ba62e670d7634e6e287ca98875c86fa66009e636df04bcf142249a91498e3f2e5121d0c8655b1abb00ec0753c1e399801c375ff03f4e74cc82aa7280b35520d18aa2b4226d2c0d01565a3f16d765c781f3482031b6830160bbd73763bb91b27ef899846ee13e8f40cf3e4d1c23de8c43c7ad078f43f397364db8c0fbb46686268c6c0dc0c1846f3bfd0628b3b26aa45382b19d48c6b597e77854601b814fd51e8d4f152b318a3b7e5a083896f57d9d207a9b19050120e0e0cbaec18e85d131c5b23afefd82248292dd4084b384282f2c055c5be1b0fe557dd209d9a35c8be676db9b428d2ac9d1fab51206f79c95b711de4c8d0c5bde06373b43d1537b80a29178559df4c79c98a69666b81b06a0a2cc7a196190260bb9c81c14e41eb665581e85fa7fff749a5449b953d55c50e110d211bc69efa43a08f9305d98cbdb609c159779a12a63d627d0427bb493dede741366ae411a3c1b502c81d6f085525f958ef2835ef26511b2c2237079bf848fd002b94a24f890538b11ac3775701c73a51397c4f56ea3b3e5a7c54b71d8734f8619ce709008ced47e2112195dbb90758fbd7341f7ed4d71665564ff5b4cfa9780ab2da340be803c1945e9c321145661137f14980b261e415ed418308ad76f9c268cec61132ced09e8640acac29397fbe5dfe95fb98f8a878afa835308fb66c4d126ae075e00f027da9e7ead9d98249d514b852f4974a382e82d1f1534d4446a6b25a3f3b145774e089cbf19c805dbf7ee66a2ab43d1270a732abdea9b66e51a96c685a93ca28b170837c9128f42dca863cd6e74745c8ecf561d78a3133edb4c4cc0ca7cc68823e90cdbab636b7b8c80369380f881979db35b5822e4f50c404bb40219cbbb04778d88d2570ae023bfc647a5cba86db5746eeda98fe8a2ce28ad8935a7241f9ce05a577f2168d76da9c1937f3d540a1e0d182de40550c4749d4076917f2a3706b52e251ec9dcf6a6a311049bdcbd22f7a96c4ccba510ef3dc78c56399858f0bd6450dea515a4bfa6e21dd492aab6554ec2e40aea2a3381cfa799ef08f175d75289ac6170fd7d26d4aedefbbc0458efed590c0d13d96031d05eb87a67e99d16e64e7a68ad65732aa62c5a582ff9aec8b0bff965946d85784f2030eb2db858ed8b59d7d41cb8709b5e7288fb1ecaaa4315b8c1d05499ae6b6b4161bbe90a6fc36ef3feb1408cf8ecd8ed0c35c8e83518147aa7c3de09328f4f0a4df6a07cadf3ac35fff6874a0ed4a389d0254cb63721a194ec2956c5dfa42dc051f4debbe70372f0fa3910463da35f38e506aac8013aa349db71368c8fb0375076b23f5640390bb6fc869d1ca292dd5bc954f9fbb1c3c1d79c3406a87935fb09bc842eab9bc6e09b23c207e51ec15a418afb3e779c6c2d31a8db137a93579d315e7d61afae5841f7498832205b450664e63abb34240f227064a3dc902db280610f692ddd44ef9bb3b4c85748fb736c646c2b8621794ec95998df4f2f495f3e3d8db1f2c2f13a99e0171eefd8b8af38a33274631874fac24d5f3c62827a7ce78f9925b37d850ca146097fef33a94f366899729fc2e362516e809c40ab4ce43279ce7ae891cb1771a563e3f45817302c595554bb8b614277f5212ac81783d1fac7a93600825656618fd9a88c6e5073c794f55f91f3fa1be24dbe753f83d837b96d2cd3c07fcc7fadbb538f0c1ddee7b71e2a3dd91b221cee6709343a36b3e25a0891607df40d390a14b36932de04ecbe102e7e71fe2f1bd1a45aa27a16a4e304b5d991df0194ee51167032fd48125798089dc10ade81e1c1de1061ce2b9656b6ce73ce00a09b702423565ec0c03ef7f96ee06fc3ba54c242afbecd73e263df497c22ee1b0268d80a4d046d214727d11d94e34c125e758a647776208915a9e0ca29125b4414b046983863021d9520dd1b6a713127c3aa92c9607d31125948f60d6f1686aa8669d7c85bba8f530382508d2826e96dc5de43e997956d175ee52471cbcb33476b17e8f56e2f25207e5c4831505f0cd6e5edeab5a547d95af92f4d829f45720598d1a77fd754cc05c226bc784f28805166add562479a1ca56270b200645f1e4bda3b8d3e960bf8a85232270b4c9869b2b5c19530b00e14290b316a902ae80f2b22cbbb5420ae4f3ebceb503ac06adec7a3e2a73577cc8ce7c9e254abcd1abcdf8f1f1bb113316a7ebf651ac06c9ff21ad77cc353fbfa1c2c14ce3549ec562af5e3fffab56e73a8dafaf150469275e9d6abeb8ad06f0f3b2bec6935115e49c577e005422009ed03f47d02c6c89ae16fe88080fdae121dc88304014017a96e2ccdb8bd396bb544115a54a451176a7a597af826791aa94339f1946f5a6f80605e15835c70ebf3a78df2307cbf2a086ddc5202b03f82299eadae60e741428a576eea6b17d9201af0ef62c42fc21ccb89a1846ca6624dd275cc76600276e15c0be28710fc4986ab8b8bdcebde1de8e8bee7c86843b64dee718896c3d300f4b773d7645f09aa8e2e841baef3822c752ad4ecccee8e8f8fd6f88bbb6e1c1bef6f2bd94fdab1feba105d7be7b1ccfe1124aa4ccedab17f6c23500fee0cbcbd510a5e2d18c384d850bcae28e6a9cfb43c4271abda68283f1a2b4b605197cf06ad8404cf1f3229cb50165e7ca6a7db6fcd031c0a5fc312175a55e974b9f7905a709e57e78b96bc11e8246b6b9a70f5befc45492ddd2780fcb8a4c0255e7782235e72e29cf941be1f65a5a2c8f9a846c3a18e41f06d01819a89358ef68bcc801443d764e0d8c4e846d5bb898a00a4450a12f3468ff660a50f2998a463c8858326b79ed554506d748ca0d627072f2464e92ed1e8b5c7b4f41e27fe499a8c60d2f1543ac4c2e2118ea2da45d896ea746e5c28c24665a28602276660147fff1ce4b33031f2df7213dc49d6cce221a9feb63cdbd8015c7522275f667b500e48231399aedb69e5c1a7308470ce98a94c96aac059cf9bfff14b9e0ea8e2646256a573a9172db0eacd28aa88d912625a3c8de69adcf058442dc79632a9f6809598f6ad8ee97f3fa25bc0f1191bdeb3ca7a4043f2228de5547e27bba57ca14aede788d2b0d7ee5b2afe3948e99083609ce3c1063835850c1d3131b74be3d8cf46f262c9727332928a4ef5021bef079b62828062c87b54a8917ec1b2ad9464f4b7a670abef85d9507903bdf30310023c48e0cfc181903a50598b984188ab2593057ce177033302d248dc69b75107b0c13bc8eea356b53f451d91c020b83d8a323205a073195f0d38daf0d0def1f5e0f4e6c41e35c908304888fd2a84a4e3612828692a5cde7dcefa01cc6f76fe562160701721b72584549f642d9082e63bcca902bdb6bcb86f8a48d4702f6a153366f61948077a3c7d310c73cb190947b41efb7d98c6a0025d34ab7072089df75001cacfd586ad6451b0bc25c3e901ed8bfb97d175204167424145a208c721dedb57872fb0497c76a29595ae849a5278c0a13d8b8cc814f16fac4aae40669c08a4271c02779c794d86a44a26bc232179466d8549210870b4f05d71497876b8ffbe0261f8c9cb4d85f71701f684dd1195e8593b64b3da5ac55521cd41990ad174edf62ce113a443583431f138ee0654866807af8e1db3aaf6ce65c6b0a09a03816e26709967ef71385409280a904a7c4acea95af78685e053ea2383ee3230e4a6e8fc4fe07f803a56e12d676671461a81b794561394a22b198bea625963ba81a9799ead8cd0888feb65821662faa446d7c6fc3011f4e89fb4f30028a3aae8a5a552a5c5249ecae88a09faa5587848a7c5a5062c7534da8c213479811061702e80b24606e3bb920ada8174a5611f3174009401f75a130a7f42b867e95cd1223a39b00b21335accc1d56ac5db1af400e2270757d0dec4f999168e5ee1a9c1576b1aaf1bc726f2eecc2932cd07fdccb3dfef78df23586a52e2eb41017f03d9149da950172d101091899840ec95e2e6ccb37d55c933b90f2ebe7ba3fd21049b9e98a7d26c413b9192ad4edf40d1aedabcb896fbecafdf9e56ebbfa030cae8e3fdf2c96a2887a377649b173cae3bc4737f46e312b17f2fc5ac90ebb1410cf091a81f24f0eb33e27f921d453efb4a35a559eedecfbb499abf223cd2f126ffd4bb5fcc65266b1e41b2e70321447252be72ade795b4a1935fc263c880b36310d47f537bb72aa36cf0ee78f547a68505c9a8b3b0008310f041078b36bc6d684dbd59fa6b1a092cdf2a700118724503908b564f33da4ba94bbac2943a06b5489c309acd3d66c3c67506e643d9f3dce7271470513585e1d80ef6eb0830d6c8a58f8811f6c92aae2ee9eab4a506e266aa1f370341f57125e41091a2b041e9dd5c341bbd7d9cd952a0328e9e25a0fb280ebbbbc5bbbfd19b5a4ec50242635516e410dcebe7707f63dde80d15b16bf0778c64c16edb6fdbb1a5acb61f096fced497830f83d2f96882d1d6c806634399aeb8753e5b66d933e9c27bb7ed732e859c9c328511023442b651dbc91ed0a165c194bb312e78b1c25a32c8f1cd6f606927498ce65aaf35199eb9c335b46695c6dd868596f865428da2a018327d2609048e7ae78a45ea9941b07a0bb22b7f67f55ddc64b746ecf7add7a4ceab36b398a957d855024fb6fc339221adf2e6d8c465c22d8672584aae994b900a91b85be0c41a172860c428b91e9084b06c77cf2b74fee71c51b9e3be370dffce082573c74c6e1bef9c105af58d0fb96938c81946d6c0ecb41cb72c1d54d6cec2d52e54c7a3f85f5db65d7fabb68368f0712d28685ea4ef805b83d636dc1ff020e6131c0672054a931601c1412afb3e16761eb11cd5f65242b96c2789d83d95c7022fb96e00c6fa61e6c9256474f9fcad2133ee31c60e227643bac1bba275806290034ccc76fb8806e9e210fdd3260568cd91ebec672fb498f302ab94b6c4a00d1b57198b7f4d70574a97412acb9e34f6480079e6c106ccc1cfcf98ee8aaae5c886947e7d7aaf7f9f6ab0b5ba1a965face16cb68610c8426049030ef6cf13ef33a6b136d00d0d90c95b480041510e48d99db0b150bf2fd38977a5a7ba3da4a5a7ced344f18382a9df44eb91199dda3a28bd9008b612e2ee9982f9a36fb1ffe2ec5448b6a6b30f433ea0ea67beb45bd22888704a33da3989c6deed665b0a2b6ded7cb6ba95bfb519e3362682c60bf2584fb234309275a8b89be852c53f05ebca3685be7529924a0699529a2d2772d880f1249dcd61e9a785e14a1377704d97fb238bfb7d4613120c81a282d215ce3e6ab3c100e44ba1fa504826b651839c6eda181366d653e630e0c968bc897541daf4c1c520953bf0ea7b5aa86f6ca53fba0f592dad7919296be935e7dcc9c3a8ce3b917af48a0a142c3f0e7513a9fdd805a2808196d33c7765654b6b12b739d699755cca6935b7e81a88d9ad786c2b08eb442e00cd83f948763b05bad5e8f2d79e9126f7481077cac81fc5f92905208cf58ea4824118eb0e93723f05b7cf00431f59c2a3f22cc49b1468a336da9beaa8ba544336182292c510483e178d5f8f9437f7a01485f4941552fe360addde0447fb23008785679125c88826e898dc892a43cbcb8bf8b14879203e32e6854df586c45263d1fe800c25cbda04558100775276d6765e100f38b451be375b7bdc4247988ebc3b68251649ac90dc35105c83914d31d0e22b5484279c3df3f2e56f2431400074b633ea17e17a4ec5c84543271ed310ea0d518d355395b36f5015368a588ba2510939d02bbb15153370caec64ec32de9890db1d0644ec7a0eb8019df840958b1f8b95a6debf9c989ba1282d791a1c47cde6cd2e991ae77ebb6fb7c4bc3eda6dcc3b4753af854b2f30cdff1fe125184992e31e6a4715231220af6ec13568bc9dc6704fa84434141263018f889dc2a13d0d65b99419261f4585a800a47d81b4e92ad32d2fa0505f4ba9f76d21e31b4bd01515c24a593e7c50758c9f7b48db8d70724fb9f455f6864b2859322a54c68e158a1c6c79e047ff63a1c00a2a5ee346f4aecf13b50426c98e71d09831b146ff063dd6c89e3d5a88498ce1bab5b11b7065abc26d7362208a3a46f2accd46117c77e698b61a990bffa0c9820e14381955139c20174ac48f220d3f54dea53d3309c500eb126e9fd056d52a946415b96abab3d86e22a45e66cad1b9922687ced0a759f95e60fcc4fcdb03df6855cce9870bc0705531fe6fab1840b99ac7428261e00516f9ec3582dcc6c47a027b2c2f2a2d20c8800f75e3eaa02a45548188db969a100f8ff40d7af80972301efaac95425f18619334f6449a05ff3afaa2485e5f0eb059c62f9616d6ecc5803c2e487bbf892313d47fa1f325e926800d7cdba827d4c24ca87f258b348755957caea008099cbd5970ee32495b6cc25408eaab75a994093009e30ad6b2d5489ca445b9b2d2aadf46012569d42d10c43e961cf6a8525e164e40cbc5e7593eb5d3f85f63e7d5c9f119582f5c2379314166a6d6a98adbac1b648aec9000b0abb286cc2561dbdb4338c91c13d2d431ee614f58b78ab2382c8983eb6cb9a7dcc1a4f82624b23cab1f984beb65318854a9318093d4f087be47375d330ae38cf923fa6674db98e58de480f0904093c805d7e36720cb04dec4ce38fbe82ef69fe73556c61456b10d372120f4b90f567a9e1c8da2fb363c8a21fc0a8da1b49a87736e714d63e9c393eac7c4a1ee085baede061ba85cbf92224c304be24ee53becfdcde35117d316ec6b7138ba87351a1b7a043565e432809adf6f471a3182ade2fc0f8fc2a731f9d2dd0a269769da611089c21746a00760a176d2c9f0168b1611a817393dcaefdbba4f283b20c0d02d7aba9fa3952818600bb55cd11b3457f7cbed77eeea13de04137a0024da2adfb41b57a9ed40d05c90128a2d313b23e72212cad6fbfc1f62e591a0385981428dfe4e06b4c21181fd6c07ca44244357bfc104558629156bc8db522d373a18f84705306ab40aed49d649798de33391a01c9379e3b1e38913f510665f2a8d387858342d3890454b0b664c4b6e3406d4f021923c3fca9d9e96543c31322170a00d663b668dd33547c7b0811c0c87c7776f71e0abbc4820984618a7b4bfe30a4ac28112bb1dab4fd43fbc28f1fe779fc8006091765d43115d4db204bf90432d5963bfbf569260b9a02915ae022b8728b92132f01fc5ac80e338d36ad8c29e0409b9bbda781b7a86247630a1c7c35180e903d1a29a865864ec5373a8bda333abc70090feda7479a0d842e2d5d36411a200b5340b3ae3b46132cd3a0d7af1b2d07c31cd99855d186b0aa5e0315fa6504c2efeae0aaf81b5cfc0a25d20374d545cc947d55c4a702add29641bdc97a64acc8d441a00babffcd1f663ff6cb84451098987ee862fc9c7d746711d414e301ac4771e62d7b251c04f73d655248dab1c67b45ff2618b9f108ac4e8fb2f65807c9e7aadf3ec81c8214f24e44f5a531df963b2a9e0cc71c39f981f4d2a29497ca58b8172d1a4fa80b419f71a9e3588dd5bcc3a35643e3b221a2ae8b4f639235bea2863c98183ae73d1044d92e89e6dc60e4e008129ee0e91133a8c482861751d6efc18c39f41ae2b385a1e53dafc4f9e041826cdd89e36e3c0adcad0ef66bc6ebaed219c7eeb80b24213d4a6f6ab23073da0b81239489073251ede98a317738d48725ade6635758a7450579b4fdce6b8c7dac295b00dbc2a5a520cdffc3b5568e7d66112ecd18570e2904b285b339c6cbe2e685fca122158f90b0bb09b3c3c2c47e04f3119aa646ccf82619c6dbb162d0b2dfc89f35447dda833afded033df963856f82351fff19a8fcf138fd75a536a20cd5a08d4a3feff8e7109272d04ec9ca59a5028360c7a8dd32c50a3b5c04f9568176b29219bd1b8421f87f5151385368f5c43b4c8cdb4befb25eb1222b04d85c2046bd25e815df3ca89b88c8c6088287cf07112bff491103354bcca2a00c87154dd6bea9a5632e9307e26b804807454cbbb87eba173b185addf07c7038fcb884c175e42dfb527e12ac1991165e17876602622861a98275119bccb60a296dd9ed2758c924def83d68e2285f307cf4079cbb6e2c258492dce437a532838ffdd4824070f8fed8a14092bb70f1ada0ff5e4b8dc10c7e36a4c2b3e95c29b4178c7bbb065d3e6818acf4d85d6d29a80bfc28469052203d88a6ce7a39f99bc023620437a6aaf586635037220d7849370838386c8b2c69003dd05304a6199d3c1681ab4e73ccc5c5aef21d4d7da407357b6d24c0c6abf3193d115f65ca32e96708dcedda4aa3f924bf6b5b2f004af4b8d597ba3de3858053d394de9722a3bff2afa46f941868409ed08ee31d1cd58d8903f28307738824c84908a035f04b0136ff0fbd8aceef4ac645a665729802947bc87de6b6428a4ca98b0d370c6ec1a923c0da534d790e96a3f144cee13d9a598bc1cab7371102e663a1daf73d7904a787e8144d18e1f089758404e1fa956e2ad5e11c3f36ae7d22ebf6b43f3c824308494ebec9134feaea8d21408347c90fc7920150ffc34421ed926e309a6899071b2ab40d3d9ffacc4118c85829f86f27caee0cf430895f8fa3326b1ca572a612f74786b684e21adedd1c0110e30ed8d86dee260b09885177a304c7b663a1e920b480c7328d225e58d7d170ad551ac53ecdf9929562c4587c9a23ab068e69d2f5b738578a510d5d82452552953e59f44e73659f7feffcd91c7a9f670b06eae68950ff831e6fd197e27c241a2b029383143adbd76ab82524ecac10d107f6031a5727bea6c40be56b3959037ad25403f4cb1161133f3dc8514d3a1a46d08d3ec1eb0da79bfdfdef20152c8222f2e57488c937014fc15a1eac565709366026687aadbbd55958b9953265305de202dfc9483eb456e40551b1852045b70a3067ebdf5445a12dad6a63beeaeab4bc79dd1857263595ef440fafe8137175557824a95ba84ad71c285cf2c79d683fde26578f556b1e05b3034ce7d15e9bdaf4044724d2d986028ce52c9396d4e28ed0481bf86d47cb2fec0faa870d08f259dc23f5202048d6f1a700284447ae18404bb024678309de40bd202d26a7322eb9670770069db861bfe33b13955be23d53b81695a0327a1d79573d1b8764a9b0490a0c2787eea3037b29d6e2ac83477839f6b0a280225e8d341ccb708c18a161a22cd6cfa1db2814d0835df1d0545e9f92974fa564cf1f9662d7771cc592a24186b1198273fda943475a0da2439e2d20d256374fa7515c5328ff3614cea17f76cdf92d9c15f239698b87f7873ff1d29ab168a5e424d8b7f6471a99b3e5711db5bae93ed6afae6d231b18e089677164e1d9b1d2089c8ed0f4687f2bec0683481bb2b7c0540719983449a81b628a3fbdbc1152602299995388309ab4c1b97683f51910d1a0562aa5b204be0cfebbeacbdfefda7ac4673719bd2717f2768559d492e4e9983c5b9340a44a6bf5287420eae82502cd11a85b1590201f1264c82bbf9c1031342bb6190e2ec91429b704af37ff68f9eb647a4881833ba0fa1884be8633c8f8091d958ba0ffc2c65063d30175888e28c236e8a0a65a5d6f5e5adbec0271dbffdce13b3d56ad71000b5324cfc4db548c16ed469632b712e28002a9ce83e5921ecab02e4dee2f8734bf48947c7a0a3494e43a42681433d63df377811e87c5b81709b980c51a7811ce1523096a1f26d8be9b275bb4d9780390197751007b33cfaf194b36d4296bd8e50b08f7fe88b1ddeb7dd66c856024706d12bf2d707cd5390d163a7331ac1b5426c73e39d971ba998aa84e52fea08ea64b4401963d5506f8df04dd511747a454915a24b0dccec7d977304f28a5fc730876ce3b9489dc7829769fa129b100e89dfb01bd42ac1d2c798a3df5b936515e07b549a7ba8441b6f183d04af062da256db779fa49a8c04963a7a760887bca84bb9f1a961d334cfd11f3a012cdd2a0b4781f22778b7694f89ceef325eeb4226424da54cf993f7c05af4632afb459b3141c0a9a1e4cdc44a3b63a3cd7cc7a89e50838498c47b777cfc5e390d1600dafb08f853cd6969846a6fdd355ed82d982aa5450c81845ac1fc93a262e5f88880e8287f6f64783cbc440612c8522b54c062b01e44752a41d2a2c7ea301997d531bd4f40b9b31d7009ecd33778d62e9fe1ed2deeb4d9f8746c8384db26782087a20940d9299429d5efcfd07724bf9cd28eb6b4d2cdcec68424e24a54e7f86bb6c9efad5cea0421215300e7d0d536e9a5d068913800ea4060176bb5457c7df878e570a822a3e645f9c8b14d25476c6a930c12fdf6d2c0b814f90b6670de90f969a02f0ced8b22a59c515f9ddb22ec12b2b223c5c8151074411280ba800fea92b421230760e915d391034e583ac2a6e6654d989108116382fab60704e24aed63a47ad7f243442d2b71f6278850b0830ce777b0cb3ea91badd4c0c53a8d1ada3f6e44128e454443280676e4840d38f770d40b3a138840dc332c1412845ca12d9793105aa1247354d93a9b007b761df15f2dc65e74c0b32253a83d29f2e9888d3b45cc2521d1f84f681bd758ea6b38ad8e0e69fcd5fbaffc7deebf3257bb901b214d9c21397d0ab0c5566287d4f0452a59e5f98c263813aa8957faca0c2c0e1f619ec6b60dd3a8993d5db2b0803248b3f8fc02a7f5f7ccd55a17b8bd7a950a6369f59c9d5106d8b4c6c12eb71ab1ce58c1c8476c14ffb008f986dc44b54024526ac74d88325ccd78469159340bc7f77def16f1e78fc494e5162b7977ac7ec08d868bf6b1f1eee045801c5333bf714336daead98e76ff9a0e1c135c566dac2943afd26f4f1f93aa5715e4b1c234b31e85791fd008b99a0145d8ca267d5fb937df14fdf422b13f200aee39c14f5bc0d836c7acf6fa66e5547bd6152ac514629b75dafe107c73a260e2873870bb733bc5b57d829229a1107873b7b2cc2e02874fe374ef711c4296e0ad5c036b0f233da94392991cec6f397bf373ae0409d644f6319296b734f770251a58653fd7a30d62862e50cfb6a985f652cb0791b9b5327994f661206d11d3aa1e9f407a9fc928d2a527061dee4639c1bd5764843174ae440d50b43cebef441a5b9dd26a79ca171210ff28f2957d5c723073e73783413871b8328f71772608c82c49b6516ad8e38a1c986d6a554cdc501d72aa6249ad49f1a75fbed5ad259d7b5cf0553d4ae0f24f073d3f13249c5edfaaee6715149de0117732606e53be0e224269463e986e0f863169959bfe124b54824d870ca44434a67396c3c388186560df3a8af37da818afebc4012fdf6f36c5eb935c54b42de4c087800331cf20824649c5934cdc942133f624c104227870ebf3af5f6aacc1a02520e258b73212766adf33826f32cd6e654560ccd6ee7ca359c37606626e1f8ef818ff43f14f7ad6578e05cc167df9514530be33598c49d21b19e09bc952c4f650dbf7b2339f8040cab5cd5e2df925b94cea48b33e582495149d40ae030052b94522c6b0d96964f5952a2847d38701b3f63d1dade9e696043d6abd88a3650c634294b18102476ab5064937a8f136ba2c0b2366cd9b0904f3677b74209460ddc8fb8e611cd6e850c43702f3333642a443fc962d66a2ad51d36a19c0c9c2f14ebd33162fdd8c2a9a2fec932869e3840498ca4e80b9a1f9f05bd9359977bdbe27135c926e4db65f462395e090ab206506862c69a9919b1b6d13450e8ebba5aec76ea8187601064c27256ffc4782e17b06b482ff28c96e51affdbcc88bbbe0377856b20514f2a7b8e0292a1ab054c98b730fe9f820eb9bad61c4dad53b4a089e4bd62d70db9da1bcd0cbf6a067670dc3436596b1ff2014e98e1af13562d53a6f7620fc762f011602ffa7838873ff534c8c22ed68d920e68e11194136e97fe8670c1f2ae958b1cdca028e28a9e691bee291a12f82f992e8023aaa7a14d405a5e400ac71063441471c61c0157dea39fdcd51c73dc1ee67279aa902569b55329367d9bb6ae737aab4031693ae67831c83d62aeeb489c8fc0c4172b14a1038f79f56144ea8a47b97ed69f4127854e6cbcc8583700540913a402fc3881e78c7ef8dd73b09bf698ef1d9635022cf6a08c6d93b807b3f6eec9ad21225161c695ea7dfa5fee89d273ffffe5beff67f7634ab51c88c78c991ec866a68012b5be46027d1636ccd01dbb338e2c09d06bcfb6cf2dbff52e583bac1552c9a518cb2f059918c7515d1544584d338eeabd8965a7182ba559f99b0fc0a7ae7888ca09fe14b648956bcf1e75b903a2d0231b59c4d5f3383d0c2010a4f54ce53188a509a37877aa3a284c425336d0a6234bb6669d0b0ef3f681aa5dc33e8d6489d35f878e8a383a93e5e664a84d5f4af37aa27dd99f9c673590c038d625538114e74548020fa9521c95184b5dc9bbeafeff92c0636e927a5a361d3280b7ade82cd12add5a190c4f01ec627805e46423e03861f20bd6c92a9a481bd8a74a2a0987456118e2809ec8e02e9815dea57cb78198ba21b46d0e54f45fae73548c948d9f0f6b620c24b2e6cadd9f71dd6b9dcc7a281b791e9f7df97c44e73592a49ca049bd072a7df91987c77ba92b101d4aecc43641d29c55334b02ea864b926182981558ca4195e9221efdc15c0cea5222b37d38dde0b4e57008259896b636300f242e1886919d5e4ea1c96715d456362dfb522c6e6065ef9ea6d2a3b6ebc4e73d235f8c3721c174f2a5f37517611595b0a0817bd40b0af7371436a4f2d65437d1fdf421b5a50470b24af3b4e5243b7b305bf260badcfed6694e43180b1690f4deb230c6f6a6f0ccb6ec640f7eef46220661f1cedb66667cb794081c60edb4d873221c833b04e7c967cd7e417903c54a4138759a5e0b588e7baebe08b20f2c2408b932d12ef494803fe64bacab673664cfb998ec3f6a370478903e3d745a4e50194a80a7e39000a3cafc7d18c7aa1206e4b2824212fa569097b7104a409c076801ffb5c6b2b7963c3cddb7821c172698036887d99f4088419de8a547b8ed25dac2fa656a9397eb85e9af9352f358d69cb6546b9b79662812e3ac9845f561d8acdfba6e0786ddf6fdadd73d01cf16b806ebca182afbdc9230ebc9f47045149356b3ad97971c1f4dda0703523b2b59cab960b8db4b30299a796667a57d306749242d8231cdc2e9b743e9500648f3b2ae22d32888799775b38028526241c996999bc979a36844045b40ea4167a123df2c1eca9810092d449c24d91f935c570562018388e7a1af1fa75cc1f75accf39836b7a8e074369baacb4980eac022dcf3fec24bdd3cf666b73086827e6750b7daf69cd895b2aa95fe2c33b05e894aa01c06de1dce52bec46ffc814c5310c12f7e9c5b4d24080727940fae20b3496c3ea682af356f53c721a6f179d5cbdd7261d25eaaf4305e0c0f3eb18969617f95598ac8276a794baab7040ac8b2f9e74766cf0b6383a03f7a6fab12d5638de53ff03f57acd6037ed7f8b6609f65384a5fb21d178ec08871e37c68887f919b18de7842c5d604460fbf4a9c7a517fcaf075fa47a01f1f9d750105d448047a1d10da597a1a4f088f30497c97648b92c3016dae7e4941f9932b589de7b25637e460016815b14cb01bce4d7f10b1ca96b5a685e88bc21682bdd588104592a81a7260dab10117f562555713d6de414f18a72d3c4536044ac2081992b100c952df5d9102207a059a519024ae1558160ef7ea4036bc0dce31fff2cca804dd6857e52cf9a6cae10e110ce4ac317c0ef57f61707ba1ef4c0e9b078838784a27c3fbc7646329b6692bbd0bd8b76385cb9743ad54793856543f4ee4b9f77446cc6a186d021bdb434255cfea03c5520c1b74201d9fc30c524a5ec001b4b4a8827db3112fb8ff47e32c81ad15f55688219adc9c1bb333f8a99c60bf52ee08603c498b6c899736683993cbcbad890ba95c02c4942c721979195dacf9af81f6348d9bc814b71ec15ca05e734538b7839c449b88051a61170fcc1bf6a772089fc9131274cd6fb98c121b42fb3f767899829c1b5859896fdf764db7fd4308d6a7c7105c063eed4b72b1087c51cf05059667f07601d5720695c8f440d4b3cfaa5684995bfc6bf2d462a33604abf3a3031656745aee41f369d0aa63cb3ef6785e40e6aa4ea5a9bb915963a59eabf6715ffba6254282e1803d6827db8236ed262d8b2897ba944e381fbef0d1a9aa3e139a7d23ac24fe004911a00106e6277d441065043813d061ca72276434281caa9120d5c0ff34f253b778d92bb69d6b002f3d4bc5ba8863a3d1bf7b542249f9968b7508f11bb88b9f2d83f162d2e5122379a419c0e1920a11b260efc4d483acb1bdfba4453c455613c6a74213e14a27f041aaaff3da9d8215929f0496b7c19280664fedae217d1e8772d521a67cbeef0923f319416d6b2df43af0b8f264827fcc97c9aa350e592c409dc9a502b614633b1e77c5ccb84f0c01ee9680ca8ce9afe474215d9bfcd687a49f089454786faef617307e2e90f3872ebc4001482269b2ca5a00f2123a77cc85e050cafbb37579a61c776152897f641fc27901846fa464679ee75d9d8a61ac3748c07e126d81ad83adb8410dbd611d06c4cd45d4a5396e6a3e3dc1a42e814adae94aa531b39d83ee032ad6cfcb9256f4cd507f510209603c413685a28783d3624d9043825f7666731049a0ab2c74e1adfcb489aff305c55886d2f00c4dbd24e64b7cd0f134e0b10148bedfa1e4c5326e1178c5165ad8e79e2a0fb8394b4a4b43cc5b02e8d3f80777972b3f2b74abd8c74c1af8e41141ed2a0161b5fdccf99196d7abd015f1ad4b6b0a619b64bbc93d8ed17270c5a1d8979e4cefe30157d3cd51270df1208a7bd9d9a06f9ab863433118787e44d1e98f901b986a4507fda2ae7487251c0134fedb8a9ae98add3e7739aba3b01cd106dcb03bc28cbaa2c87b4ebc65c903c53f247826de7e1e19fdeae0f22c276fe8421d00e37185d517756d056335b14f141e0494c14767ffbbfd331be1cda519cfe9136ea6047cec64caf3e75ca644f8801b535b0ef17b6c79bd81d618607357190ccaa1362e24ea442945449396503cd11738f01a58202a900fe39e85ef66eb50a2f38aedda8f12ee3de8d6e882da84417bd0fbb0353faa7db1e91808d288d1453c89c94fd935b351147dd884f0d36808dd0ac532949c03852c50b44071ac51ce0dac2c734a439fb06170a1d27b2c338532ba651104c6ef1be80219d152845b9b81a0ab63ea464f6b8b446f84d25ca88523828446271fb5d03ca43870baffc4a6fd8cd807b783c9b0a2811a39bf972d78e8bfdc622f6d06c65921d1acc664ae5610cb9c891a1136c1394d0c9fbe0e7bce064f1c1ba636a65a5f8069ce17fb915befc9208573df2c0f637979239e4306290248f7047a7d7c081bc2aed2f2d7a34b8d30e835b3bfbf3e35dbc00248af11a12f56d1a911d8d1239d4f27668f816a59c5d876fbf3fe3a84f80390c80867dd40efd397e2a588c013be990abe2a378a86e22c37f23bc1b000f039997c4a777e800deb2c2029ee66c7ef439467b2dbcb903e1475fcace99ff87243d55be078b5c5fdb9faf4065b8515084a6c8b6d70183519380a5b8b4529e8ec2905c5b1f38c68412aa7cb84efda5400226125a52e97ab5021f045db8ae9b0a5b7ea83e6b6e55cc5fce3083f9bb001cba8100f544e9c8c3182e0fd9dec1bdae7863e14ba9a4591bc0aa0ba6fc72d9453f6e3ea30b55917c310b7ab4a71f764ba1f472d5c34ea277d9babf991bab50749ca1a097c58cf4430610a4d689a04346432fe3e1c5fbd3fd8bb5826d2dcc020d2b04c0a89349ce1c83931399f7c1ac3d131ca91ac3398cb82854f0147ba34b112db2a1974aaa4273c6acd212d6db234433a75c60f8842d8a0b70758f9b14d2836a31162914d0adc466f3080b91a646c4045e4e55acbb180443e580eb4c3844bea261d55169806ef88f8e42710e04c5dd1fd2c1accd00ef1617b8e36588e221e75ddd13e7c4056425a3920d4cd21006ed386affc302163d14712950389cb7b10bf850be17b4edbc37e702a4e3e3297778de5967ec3f4a23c2c38cfde54206fc11c2fb9f5302acb0aa43f893e85329191304645a5c227cf79517e5f18c7413950ff33e3035b9d905267bf50ae08cd34d732455e6650a1f7dfadd7d4f58059d29250fa20f50a1412b306229974d4686e0173b53a3fbfddd8c887c00fd65004a88795280d0ae6c8331651c1b531b4c2f191f997a9b7ac8d33153d84addfbd2f89f88ea3ead4c00c3fe7e594d0a906e5ed651caf29dc71a2f76f60397d637ac630eeb789c3a5d6396a0505c40eedb8d55c6a7d78a3fd0d868a4445cc163b22370e14b4ab0e1303c58531ef69cf01882deca26b8762324a1d4310b993a6e5a094de9072df41c7fbcf7bda8f6d8a0a0269450ea933f5d5d935a4ae28c9eecded770a06223743271154435141c88077162a02370d78d92df8b1f8f03b06173a05be2f44dac0d42bd5cc7510430f04e518b0a6a4073e18220223d2178a1ee63ca20c70959bd319bc1fa84160121b7dc359216a28285f5967083f0a8426a6f251b617b790e1494a92cc7e306dfb68762127c56ad3e2bfd691038e0c0597b1226f778518a9e00715fa70e8ae620aac20df852dd15a9eb3ad68a3c9d30c810b13b58127cd942b1fc7ae24c4011e0b2b3dc3f8a72c97920ae3a991052afb8b41ad892d4e8b8b6fd13a20cf0007fd421d0faeea81768001a395e22ea2575491183f02464a18540a02392872370a67b1a4b6cd9d31e21400423d23288071bdf7504c1629b63c97e29b431caee722429d56ffc14db85ae0729045dfe8cb02a71774d2e98c5d90e3716e177168a3c0cfd014d30a601b95e0c5232e9e32866cd98012483fa4c1fab942e90362f1eb4aaabfa6eed09910e529d92b200d5397e72c8c6f89b594c8cb5ebf7e05646a425f4fb5949dc11fe8effd37b3e176e64338710ac576116fb2ebddd538d5c1b10e11dd128d258c2e49826e1d8d96619f011592b68c32b32bad30fadd5cba1149bbcdf4563e1c49fec0a7cf51f8a4f08208943a9b189c7947b5b37f032aabe50244b539d6a8909231734d38d3975392292ab00fb6560a59f3481250fcd98f56a71a06138df6520712633231a8239ec2403bc997aa86b82a59ba40db468e620077dd9f1ebb3f470104903391f34761b695807290fd2c9b941080910dcd51e9a9ce7e23aa2e9aa5c40fc8b64cc649bee895256f0ab5453b01e5b695d9c59ccbbc364499bd4973cab43d94313d3fb40753501d7456e74341c924e151f3cf97c19e22166ba8a33c4f7329c547c42fdad7c57eb529a686c95ad71946737dcb48139d3c382615a77248736e4dd864ed2bc7fe3ce273563b190e60df2f8bf8a26d3f60c1a1d7a291974822e6a33dd78e6f7014b52b42ddd809559c587e102f577203c311832fafcb15774e369cae5eb0af2a829aa259d518835ff3ec63ef04f5d81ca2a9a4ea9b679f2db08aef6d38b6c561b4b252f600ac631afd3c1833b99327ec3fc569bacebc94554952aec39e12c3c660684239867ea866778626abb2825cb34e4a49138516fccfffca7798111172d01a2ed8544ca36de2f17bfbc194db7b356b3d3e77d1e720a8e5355d9e87aa26543d72ba99992c3240eb2261055ab82e911d73df1f49e3f19ad71e61162c028cc2f5ac8df655612052d6381bdac1f90d3987ddf6a85af830551ad47729941b58b2b027a7442886132ae15229d31da01c6da4fc1a13988ba1317018b8ba64976b24985598c0151f6a19ef53b07e8fd11b3d5c86a7d7d2b57724c41f9ae5c1d5504f8344879b7dbd16c581b1c8975350e64689a8dbb99ac7ae88a6d9397a3666be1cefe5b6aaff98d6f20f13af9e1d01bebc3db832cc6cf86b20c6aec23c5bf23f175f0b9cf5a761d3e753cfb84f4ed248b22dadb35f17ca8ce7fbc8965e465632573b2573b59167a92fddad7b2a70e056e0b80cc8c19469c9c4437cc16550175493ac93708d42c19c21e8b70a4c60882acc9dd9c9448b7d5f6aa5c43c62035f758008d8623d2b3280ff20e7920b52d7cca9c121613dff9a1002a32fd00e27318c9d1876f828d9700f153483b8398b1c87b1072114b81b913641e3d061ae4551742596474ea41ea2b82274b46434594c340d4fbad4090ae9a8153a1469060ac2c076fadc76b72467aff2dea34996aa73a2de2c240c2cf8c54cc04a4d1aa9e451da3164155c044a9bcb931f885a57c97b239299810616e626d68ae1c57462cdc45e47619d7037650ca0fb951850df3209ae5f1362224f6426cec189e457e80c49ca5c4240490874c24027408484c01528b2a2154a5a7c23662ac4a3de2f258bb1bf63b75c344615adb35ce730de6879b6f435eb64b8ee779288deddf40e8f24419f6a924b370669fdbb8cb4a135051ff8fc7f7d93a99799f4dbe7bc39bc24cce0878da267c24ff6b41a84d89fdbcdfffcd813aaa9db6a17155083c004da0b76462462027a87309f12a151f87947ee4e8fee7591473760663044428686409a1adec542583479d7a19838e0d9234628abcb499a84f3100ba3038b1da33e55600f78c2f5e3e6449653d3148a0034b75e2ba344c6896c0f314f29d565f91786df562387dadb47cd81794c803992c7a521f28f32e0c2a907589e2ea6790707eef02b0c1225ebbc5399a4247db6e4131aae0a38f5d044a327c73f3f84d8a9204945b583166bcd8f8fede80c970a54129d814a5584903aa23e23ddf4f1c18d153b6880faf391dbe42fcf2461ac5f9958cf5b6534768fade0588564deea072ad6a0cb68ce19188918a43f1ca4b6ca6eb754f2e6a68e6e8279c4aa0cf5ff547b846f87e0189748263bef4ae09b8a7cf3d4851f81dbc32ab25b2c49c209036088a16fab6d79430d4569638e0008adf5f07b65d0a291dee5f36c0aefc85848597a236185e3b97bfbe19f6199b5366f236772bf684f63ef472557b22f86e661792333c6dddc5060c4f885ba39783b87360be2bfc0cdb508b011431d01ce0c2586381745f90a2ccdedf1267bea0785055a72e38247366e715e7fcd2c8c8b117a87e2c477fbd431eac43277e5f476c3bbc08aa5a1e29c1440ff358fc542903aec700ce3a0bde0e25e08d2c5f2fd0f8e4bc3ac953e100095ec03bb0444f6b094a55db893ab70c149bbf1bf76fc50e10a952a713c42baa347686ba41614e9d49fdfcf8ec4d5496833490de1aaca848fb3c7e91c98d39f3ab26b343336f70184be163500ead74221e8567b92c80066e301124b1b1abcbf3aada61659d8fe301a3604e7a7fc906399c77787e82a94570f2e6804bf4aef2fe8091143cb7bcae8d5ff7d83a6c6edd990be25fda39dea205ff49b19f37b4a77f0e5388159cbfcba7497db4f250b7fb38d7d78c8ec6d75d6359e4723d4f12516b58df037a6b3065ae05db1bc0ed7d4d850e3f616e091d15e04cfbbb8a73654cdfb86f95b1fb32d73fe38330e9a94807f25ba2d2bf0ac3c313702f2a838fee0865d82a1206cef1f7122ff5183d40cc86dcb4ad1f07d7bef5b4baa278c9a03cc600818b8a28e5417df4c49b03934ddb98a649a83fb390e045eed4826bb148a2086d6567cb975416a24b5986c0118eff4b9300664082e520dc09aea1ed2c0941e42324a64ce07130f91281a79ab7a5fe1a9970cf5f00549460d0cb6fe0bca520bc6ec4d5f8c267bab9c0f205c998203f856259d622113e36f5209917867227be7ece89805ec26ae4b82886d904fbd7ca74b8658131296acf85c83c8ca5ad1db8aaa4efb5375e74aaaf1986ebb8c3eb75d28202090c87f0e1950398f420899a0ff3a8d6218c0f55862bb27197db3c603bc48bfacdc20e704b3e3eb2e15dd25ba154b7e55b9876cf63a6fe621cb50e2e6b90d64ea261dd14f41c4a4d1d36a74dccc7e9c10aced4023880831822ec63c263560ecca8d92f2a62b50d8df5f9ce4ad8e73816aac2ebd079ce96b4e225979064ce0d102a4b7d2b2b74faf98a254ba712ab68c4f3c23140449a8c0a2af8b8199cdcc704e3f03e6aad5237e6f5f66c44881c4f2ef92030e47b3d29ca21f65be8ab02b2ca7c98b09e47306bfb43b4cd04aea68524f3c67580a9d5442caeefb2aa4571abd2c95b4f6aae14ef5dc9e17a9f6984ed286ffdc40d27f28c68ce9205f84cb30ffc92761e2d42961eb3bd94859e3ba7c0a712924fc2b4c65527b84e6f2ab15799f946ec4ee37b558890c0cc1c448e7a91be3ac773c58551c5dc06c91248ef3fb84c55e2d741ff089d8c2a3287572f500961371427c6445f1a9b710c1e2135e64716fbde2967b5fe8d132d33cf868340a50276ab6445461fd230decdb3ab0362452c2dbff97b17267aaa2c7f8fb0a6c3fdd8a824d860a850171c8c98d5fee81119098f76a2fe2582e078d8dbcc55a8a7705294aa9a5bdc2ad180de97891620e62e2e14de8d59c6152631cd095398d69117060facd8c614d73d926480dd53f90cc9824274c2885a31d096f7c37b5da63b3611cd3b817608260115a579f94bdf8f49e47fb4ecd1021d8a62bb9ee7bff21b09d417e575e62c5b256678598734c7e1a560cf67277d91e3e2f14b34b68aa0d3e1d29efd9a7ec583878ccfb21cc1b60b3a1a71a765404e4501bf335980939fe550319be5d4d71391cdd904b3d7604cf841db469f47b8fa02d89ef4bcd3f1125b33326127abfcd05077505c7678bf77438879631b9503b2ae1456c1a27aa16feaed7fba66470547a039cc6d7321b0e103918e39f8c396cba094104dc2abf8893951427465c8ae6967e8acfbca762142e8755534bc15ce537cac80fb7167854f072fb3c93517d8e59a47ad19fb0f36b2e4b66c86937cd334d8c803f2cbd6e6fd195312139c02646036ea685dbe1a00c9b01eac20edceab2d1be2fb862a4ed033ebb44ae858185ca028600f5913dd005494da36f88b5d0a7c79ab33e05859b102f8f2fab4bee2e2b0453c1bd027c0a044a89ebb25720d23a4a07468e7f1fdedfdf73aba3d7f3580c2dfd1d383dcc3141b3504ebb092bdaa1a7ad7debe75d9107bd634d4e8418dd5961eae779d69a7b68e16a284616245d8b36276f3598b0686c966c42f6de64cb2da59449a68d0a1b0b590b1fe633689a06873ad730cc34bd9ce498a3d309769d5d02e110f519302ba5cc47af71ad566dabf16097fea8eb44173c8a39d4a198a7141a51a31dbaced96b7cbabcadd465ba059d7ae7355227b5986ed538f53eea56e7d4db4bb7524ebd95a20bc70d1e3e5a8ca7de649e46978ddfaac2e1198939d46b3cccc63025ba6ed89bd54a656dec956a3ce653381780bef39437e5b16e4a790cf53709ceb37ce0a7dc07f5b1c665a8b14be0a7ec85423a5be631ef817686fea86ba03fcaa1604477e5d1637e5949e3a843a79d36599d36d1d393363946ccbb4a57692bddc29c3af3adcc9c47cfc680f22e87795b4d9d9c5f52d0fc85464ffd76152331ba2c1d75eb7292972188d4ad0ba57495e8a221e6504ef3dba19cbaaaab3c753844437431477bbb485d865b3f86cc939e91d813886b56161adc569d79906ef56bce42b75c8841734dd3344d839ad72a25e8b9ccf3eb04525e831cb45af5ae1cf3d0fbf387f2a8bf3ba5f054bf8c491831c668adb2a654af1304fdd579cd2f1f69aed3ad5b7d74eb763fbad5ae7910e723bfabefa06ff6d68ad9db755ced5d69cd47af7907e94f83ab87b562ced659e816b5b0555d73cc35dfba556110c5228820c03c97f132c1d0f38673e3d2f7120d943ef3028ca0cf9c7360d90fe19fce97078e8e87656e1c238e611495d80595c8547b3bcaf160de5774502962e9afbd764ad37b8541a568951e2a916120d0072ec11efc0b9947cc9b0c03e12299c72c7a4bb8bf0db35547f6e7e3635cc2428b4eba6c95e3213344c105ddca9983d1a7bbad2ead4e0f4cb0f4267793a6b9099a20520e3efacc6fcaa5137332e85427724e3793df9549e34e6dfd55c73e731f2ab89079966559a6f9edb2f6bcbfcca1f7f597394e7f990769e8994fd769cf32aa79a66df6769f696eb27735c4df6472cd21347984cc495e42d2b8e5988931f788544e29e594610cf5dc62eca6981725a5534e294b10c1f0e42823476666e6c892291674ce49e99c53ca3921857042090642082184104208218410420895e4849027ced05f56a5b74b8bd14919cb61484e9363be654e25a50de39c3a62a4a458ad55f62755a82f98579f93d24923532c71464a79a6daa59473ca29a58c33ca18a38c3068d9734eed28c628659431c6ee1865c7eee6c8bd0dd5eab56b11f394c0a7948f7850e3631ff9e0e459626d7963999a5382a9b44eec48caa654469f53d249e99c52ce296593c77cd2fa43e59452c2096598325262b18403ccc6f589a1896118a65aa5be4aaeddd22237ebea231838e1aa899842a269dbb66d1ed42066656852ef28652a86feaae69857e9edd3e4db363d73ce39e7e1e6e44c5e8c2e63b7228d118c339c53a34051c68e5816888a0ea5f4e881007e046a986a18e34ff7d7da0c613764c8ccfcc391614386cccccccd700baedf954f069026877a039293fb03021a92c2909b4dfe76e51eede5f935a4e5e39095070339066c4012933f25d0f2fc0202cb475f3dbf8090f25a94fd0131730abeec4f5a9e6068d2a527e625f78811c6a0e3d70e48df9181301030a83cdb2dfc832215645145e889228ad0416bdc68a4c4e934dd45bdf4ebbf8a31461d8c629807698a751addf5c7b08e87e374aa159d54878d35bef454f5375d0a1942b792524a380694928dee762f57dd922ebd53c92ae79c6e05a45b7fd4993a1add5d3dfdba75eb4a87744abd3aa5ce9e0f3398bb00f450a762ccf104690cb33d9865f9acb5d65aabd75a6bad5996d596a2b5a9ea9cc9d3fda0bbfe13a75bd2a1e7c34cd714521d1d00e1e40920e68c1f909ec7f3eb07221e329be95ad0d4e84ad036c941808108ddad1fbb950534c691b2bf2981d0ddee67a79a38dda9ca7417f5dd3d6c0300da107e08fb4c079d51506d9d139da3106e950073bdd4c920cddd62972e5f8822c6e3bc86a223f830d3b188c869efc428ed227460a030a24da42a125fbc24d1f1cb07f6e88350b4d2f1eb8728cf3f3879e9aa95d14b1e76e8b3dbbb696dec0468af745aa5538fdc0b4de42452c3f468affce8851656223704a815235631d72a56abf589d432330083b1078da14f4c83e63b08728f86fc4d127c63de9226229550e61e904f98f336f98e1fa34bb9a43f724462c378c21eb33ef1e994dd8a96c2b642eb7835fd7e3a9ef9edae97735150dd1cd339dbe3a3f9adbe24fe15e9fca61ca23701da892ebd1144bf9b578f1c8f111de00ee658f41c9ad890c60a32d05883084548b313fd09d04eb44fa863d666db35f299bd329d7a36c09d1c38cd8e508e9d69a1449731baec38a7fd49b44d4c2b30028a215060850caaec487f12fd897cc29c635731073a10b561f64ca2cad7501c5d50a43f99727acca95fa7f370155d50307f42313a394a0b65b5f344fab450eace131b580c51119e801913a68d2c3b4fb2b44beb5cf497c7c354d75f7498dafa8b56cafe3ac5478c90bac582dece2f89f8f6fa370cf11c3142ea8f5f02c59663b0e8f4c8401a8329406d8b5b7f2d830e7af55b99814853a34a1852c257eb53c2571fb8f4d5072a7ddd6273749ea69b3c66a6159eb922d36f7f1cb2c257ebb3c2c60ca4db9881cc9f51ca1308fa97f0546c4e4b6fa08596a7ce2a427d3a7dc9001a2f4c83bd401d4eaf1eeaa995f0dbe310d44b0c422e1a3799170f679e5f3c047df7fc82b2f430486b451ebacb4b9ffda0a15bd133ffe996f4cc99fc68cf1c49b738cf5c866e4dcf7cb5ea3afef159c66332d7a6b779b23fce6472a6dee698378771ae71b780bacf34678ec7c4c2bc764bf3ccb7cc335f75cbe49967aed3adf6cc5e1d9f79b7a66ff6fa67389ff520f497c767fc30483ea1716b3d576cd0d9c9721df372c0bcbabd34f42c897f650498f3cf26403b98b711cc4a7b2bc71c1af4d38344fa00dec13c3ae6e5001474546548c8090e3704ed3c01da899e65da9d440dfeae1ef677912b47dc4007658c204ac10e0ca301521c71c5111a5ab680b203dd9f39ff2334c6b97269e3b293b3c32fddc29eb50d052730253ff5a5fbc0341f0f1da8d42d93478763ba45a65b9a478765bad57974b8145d351eaf0a298ffea35b28cc93af49ae887494bdfe9ca7e06f5347ca4622fec9ad56317ae48a48ae1e7d7b9db5524e08f6986f5e75e92da95fadfc8d5fd0442d5e2cf2a251172f1ef5173de5452ffd45477911a9bfd83d67a577b797d910ff93cb97942b12addc93659dbcdacd371b894eb62ef1413de7288f455d90c0289589679c0c1141a4e5e8cb986ef547d76a3c27594e527ae45cda6b9f7ae7c1f6d30b8ad29fdcc4158956fa3bd9cee337715d527344940ce1cfbcf3fa4d1c0fca329f70e9c9992b520351b74e1efd646f3ff5c915e16cb47297c0374149fa66eeb179ed261e2d1279d105dc2366d6074622c990a19c27291df3e2d31a84cc973616718ff8a5bbb14ad1478f55a2956e11758be55256a469577bb6520a113281aefb4bc0e985a22b3b1373da9d6855a59bf243b5769d47ed47b7a6b70a3f023667dce4d1fce8d24bd217316094a4181fc98cf9688f32a4e85ac59c5e654819525c6548da8f55ad314ef767e8838e5f425f3ebaff911329cf47399039caa1cb7b01468c978eb9966d623822393f83fa8b5e86c6949dc1389ef611ba4b7757ab69b333441c99c6086149d2d498d265537242f4855b3a496120bdf5517757dfdbe6c34c27979e4f4631a7bd4a349d936c4abb32a498d35eab7444aba2ef0cc9e83b5b3afa3e19c55abbee64744f46dfae4931f28c1423c598ce4457f5768ea9235144e9cfeb624e3b0a5aba38adecf084e8170a411ee009d0a7f7af153879139e5f54cebcd64c88601f5d8be283c5fe1c7a7f6c020d87ba3685d45a6bad59e63ea625391ee5577a96993289927ec39fe0f0272a88c34d0e39ef1a798d6e9da3bc6be4512ebd4ea66abcd6ae5badfc6bbeafe1ba349f724d7e56dde4c5affd955a530f93adce0c44bac9bb99a39218c93c23693ee3a4330331d92539324f12a9ef331d043d9977de93494e561be76c6a75cea5f49ab9b4c99ccbac8fc95e8192c39fd8d8e4c8e13636396edc66b5f98dcd716caef227b3c6bb49741e0440df39e79bd739ffc9b9b3d2397e94c7f9cac3e1ddf09edca84ede35f21c754e831be7973ae7d435de5c4d9c701b69766c3c07216ce709d08e8de598539dcba413a12e6f7d813a56b76e795b7f9bb34f8efae6f5446711a96ff224d89b32cfc7199dc9619abf996b0e391e8d48e6d55e93cdec151b8fdc159d9d2cd235595f3e0cd020a181c194251cb840ef01ecab037d73444e5fed4ffcea53bf4aaff6c2c718c022527f7a12ec97c4a7d2060c28d5352fad3a77add56b9598bbcff4cbe4ab5d92e3a9df18638cd1fad011e20a3a1ff858b5f256eb33fd6223804666f56efd5abdfa9039e762d687da2bd0659046bd1ca863cc14a3545aca4ce95667432168ecde02f8d92f84411a5a1f76c81e3333841032744984a36f8f4a743016d145bf70080ec5222dddaade5dba055fcb3c7a30a8bff6cd6312739a7978c3f968af913769f1878786373520b3b7c99bac0cfd358f11235c74170ec1a1e8d28939edd5646f97c1a16f1ea6dc1093b347be3acfa3b9e6f91042c79eb9893d1f662ab78d55ba5babfd81cfc3deecfc355ab6120c47e1570ac63c7b6f118f9e0140d7e03845015a9ca2691d3509bf3d08a7c0a70fb776ed932dc0b7d7c83bedf1817e3b737e9943f526403bd5336f04f562b63dd36aadfe0468a7da2726d72c73ce6deb03bd9d0619796abd2bd54dd542a99ed5ea19998f39d19f54a5879ef993ea4fb2a587fec49e118a31fa6c9a4614e2cb9796b49ab65357a3daa0076ff09ae2e49f5f42acf110420861c71b56a49493e2e082611856b31b5e689bc96432699b8907a78de338ee84a240486d5dd775a99a9ae7d79435549b8d8d8d8deae60405c776e3c68d1b3856528811b61c3972e418819552c18e4d07c7a343870e6e085471246cd16367ee3545ca6b082c256cf035041459dd4e6dc303bf5200e635441933a82881b23a5ab8084360bc40082c4230d07206116a507162b57091c5156bcce00447547ee0450e334c5a80b2544181182b7030030538942142cb46c4514a8b019e5f425cf1379e5f4260a142cc38849fb9c7ed2084104268821344045981e2076ba4c16698f1a28284105848b1414cc340648cbe719325a4e14f4f487f74cd8725044eef87fdd453f5d743bc7ec84d1b859873ce39adea88856e5d1f467e04f1d1c2d539d22d1f3e3a76c53032006306415974b0c54efb8a5d4052926e8064822d4f70f962a7ddd905a4822286d006181d706041113bed1fbb20c0431758a2dcc0065cd88055584972e9c89c535feec41622ca4387f3d965cba86a57a7a35d2bce89ce5f4c61497de8ab877eb167e78dbf5899993f085fe8fe26e9b687d6a709b431c618a53fbf828854147ddff8d65b733c4aa4a973761e5f7fad011952383678d2e426391e253c3e201acad91ba670d2e6e6a35d32c49c7615ae0e176f9edbaf0ed717a537ce64574d39733c38ae9c61860d2a9d3430830c336c50092ac5266a2cdd3a594f712befa7bfc699e3a9f1208dc373259dffd457b90cd1c53374cb051d7f8d37b7d92b7f731caea3d39f0ebf3f587e5118c16fcec71c7ebd12fcce935f4a426b87dfcde59e835d3f620e4b0682f2e82b0672e3d15e1efde93cd145bf1f37e4d3893e4ae009ed24783ffdb5eff098f4d7ee5e93ce69e93aec2d8165ef6a841f396cdf58e8847bb4a33c1a7c40c12e28af87fa8bd282ee42a215a23822a9056cb8e0b5050141666680254b0a8cc0d8699741032be73c48dc9e7c3b0eefa76f784a7eba3fb912947f3cb61b676ef39be86db7f9ec90470bd5a8b2a9f1664875db26b150234a1842f04112184070a51e7e88f2c5071ea0d869971203dca3fde465009ed01e3d0dc8c03ddae30fdd854452a95b3dd451faa341a70b9432b484d941500acc60342ee8f24510133f2419311082c0b20508a231675061242c5e04a161a28ba0279b6b264ff3246f568910f93e4d7e7322f2373b3d8885076281443dd45120d14fb7ee0783a050b72e2bd1f03169029d744be9fb7448638d21965480e61504a01398400637f02028a94ad111208250a68823c840828d0400018619a2216c60e6a531248a39edd22f8edbd589e32f24c2d19428ba78071ab5f82fb4e2db6b563dcc8b927b488744d1355b8715372f9b7b29437fd8b3f390f3057f29513a4a7fed42ed3c437fedd813dd6da16fef28dd9ad2ad0b89aa74eb7e42ddba43dd82ddba10a989e8d6ad56fe36d1b73751b788d805347406104db0c0cb1367e860a71d16b16bfbc1146ba031c410ac98d9698746ec02a29203335e51ae50d1c6163bedf0885d1b280289305a0c31e185153bedb1ca7711094d8210a0632c4abd7a90e3914aaa63ae514f55bd8e7b4cc73c1bee313dc5274cef283ad9dfec2eba5bb7950a674a281ae35c56f958f5b801d8b1a4a3eeec37136b712b334529a54b8f1ee413a4e41ce93e4ae8b10ac04bbfdd0e16a2bb52c540fa2547d757c22de167f49654239cfdbe9f9c74f3d09388f8df9e8f6d55dc037ac71b5796dc6ddff2dbb29d47fa9b10428ed01ee96f1ae90f06ddf48f104b81c6ad8179f6d7104acff6a7bf00a8e91a733c3a5c93540af1530a71ce74288b640fec62728297958e20b7f6d249cba4bf291d3a730d4d9bd436b8492b559c090369283d485759248b20b442a057d75c33b9ba09adc9eba24b1ac9a4d54a16c9a21dba1cd1c94f8f41fd4ddf9cba9822ced9c1d9efd8b1c327136c63d22dcde4d0733894a2f2d9aacb43056f27e5a01c8f4f117f93dde198b3e669cc991c7ad24dde10e8d26d75aaa9bcbbfd8e1d1ea4b58c61164fcc3d767810932650bacda9df4eaa72f9cc0e4b67aabb8de6670ecf61ab58119a9d546bd7755227d54ed2494209f539d43687be6990e590e3d1e148600ad4a74f8081489f4e016e693e49f05b5d25f8ed80d83843b771cd8bfc9d00bd7ad04bf0a093e0c1cdf361a6abdf74cdab4e74fcd54d74487578b322935191960ba7fc74264d56199cd22dc967e0d084b08a11235a0ff7b7434b912cb245dc098591809d1a56aff6a739852e9c84faeb3639f4530ac59ce9f186eec66f380e5f79f492d46ed4ad954f9747d28b4cc2e177fb2b8b7ea2fc4aa49ff28bab04bf12cc4f8aea64912cea96166914357b936c39fcf299ead22e810f6d8fb4d5bad0df0edb7345c87748f01ff85748706851a0d25d59e5a76f0e9d40a1284c76b8b4d22e127cbaac5282d7483167bac65147814a771949e87b8cf437fd07be0bfd4da7b64746118aae7826e64c29f4d3b5d3c6dd6a1225a54d82d75d3a6712fde6b793601428e4e44c74318939738766cf8c406d7bc9a283cef21bbfe14ca20bee4c8741d0498ddf9af2dbbd4ae5cc2a678ee7862cf2a4517f93724ca20b49cc995e590ccb4a2dfd4dc7e12bbfb2e80626dd3ac117500e3d724550cea45b279fde04063110ae08caa15c025fdacbb9c983c42b24f8cac3e14dbfe1717f99df78d355de8551cefc741b4f098664d6d85b4d9eb2b763ea9d989fde4274916027d24f479d36db69263a3db3f7fbdb557b75e4528e1e400d34c6b9bdf4d4654dd7df4c39e7d2bb0a03895043a1a8f320dd5968143dd939f4a0518c5648f4ce3b1b318fd0a85b1816ea2b2ddee5a997a7ce180631e73c4e75d1a51373a8d71a314ff6474374ddf8a6e5b8f120e74457a53eba8dc79c73336cf28d4dad36f6eaac3293e9880e0e45cba303104278bf8f5e129d20d121741578a2c3662f3ffaebe8ed0156fa9eb6b6856797de5da3839ee4c733b31531081df41887441edde5a5c7e851081df49884bdbc9431a68941a2941ebbaf4840e71a4a850fc24090700fe8dc55e17ce6fa24fcae5e71e86ef7d164b58afa78e8442d094e9111845922ccd027d171e1d4c51c68821e7cce33a188eefef8e8ea3c7a90cee3980337134797aa73babbdf47fecda3ebfc50218898e82c74ab7af416569cbd3a36cdc61f6ff2c815690203135829fa242ce64d12622a484ee29a4691c1a28ec75f9c6f21e64cd78f9833dd042a9dc49298404467c2105db7fd81cfd37588886e557b25fa7458a5d1549f2e437475acc44a56c98422bae92d206120d4a7cb1c32ac4217ec65303f31fb23bf75700fcf8422ba76f9a4bbac24f4d365d0404d42a348572148cd1c26612f454890c41764943e092b3de6c9a7d375f48c3e1d16512ee49d734e8e94995d87aa63cc6f8c3162acc303c7376d4e1957d007f7e0098420dc835dc72a069c3349707eaaa0eacee8a494778b68a05b0a84c8f676778b677885143af5a6b672128f870e75a4d1b1bdab879d998eeddd60778c52ce492956399ecbe4833aa845a7e5864dd5e49a6593e3f68357aa4b55fdf953cb3e2b745b4b09799e24f768ef5efdc8e0fc42f3d15fb3978fa1090d57c7b39704e7d9fbc7376b3f787c98ca67921facc3c3fbeb24ec45d6688221744ee6e9dc73a58e9594524e7b65884b1d74f9337f4ecbfd49e9b2674a26d2a2651f61fa65a72fb0f750343c7a908e6874d0af0ebe6774d0ef0d1d4e4332e4738c3136374bd12217518f923e7b68fcf837abf9ab7d8c4d047b6989c038973b833133c9d4263d3331900a04f36d53a974e8c0c179299d3d451d73ce07a6f181697c609abaa453a264497de84a7c7eea43ff593d9c36456d4c750db4435010f4092dc31bfe480d0da318e6177b56a974e8c0c1e1c1833a7cad37d92d1f98a637acd65a55aac66a90133441417f9b04e5f0cc11896d04fdb5210887a0f7010afa086f78a884b907e63f750837a4bfdaba79d3f38120000a7ab9550692013df9a0970bd8faeb2985c66da446991f2c4108bbb744d92244b71c6d21da4204e42d65b694f1cc263160642b5148f90b9fa1fc163459b784e9c445a348269349d3a200130517518c89e28c571442e88c868c7a30dd5065c362c3509c812208cc4690e7867bb4cafbf277fb06b3a5c808e9553746553cb78c6e6034c6c609ad95feca6f28c43c44eaf80505d2dffa82e2f582a24b8ff9e8b0a17f3c1c875fa0d598710a2cc0133a7ef4f859802930f7e820f084de313d7b94f4d959802948210c04da130f1e031840095fc2ad386e453d3bc62e14bb5ce81cd711a48a54912a920b9105988203f8847635be323e86c5689ec10bb287d608f768c18cae19084c217afb0e0391f6c43d600ad16ef0845a838eb9870bfdf547db427f0d860a515b8b956f57c11f9e0341389eb94707b19627d06850cbd03317417b70a3ba737ef44bfb0664d433d70290157085200f7dfca129b3a94975a813b76915a353c686cf319012543637353737a99b9b9b9b9b9beca6623737289c2ed0fbc034257ccf2034ca9c42fbcdb467679802f4bb3d9f4e2c040ef1816984f048d764928f984b6c495dd2bdb43e30cdc3341d45834e2098970bd05c0cfaf0cd2f17147d148c81c44c8ae4a84cd412149302cb8eea09061907c6cb89312f27cc6c3188ab399c7a409950d0c915a45248d4482d369b91cae4e5868be71baf27c2dcb851d9e0e8aa8416c5b0338e96ee329919ba9584866ef1eb8931f1fbf3a1020b2d44973398010c8081c81efeea50125dc992faec3efe4bb4e7a30fdaf123ac1ec76bd826bd1bafd54d7a37af659bf454af9936e9d9bca66dd2ab796ddba487c26bdc263d9dd74e9bf4b6d7509bf44caf759bf4b2d7529bf4e86b359bf4e66b369a6abbb9a1b2b9a94975a813b7ddc0614f60e7a3dfa40e5aa40103611691f648376fc8bd4044fab45dadcf2ac269d2f4d787dc0bb569a0499628c8406aac3cd1b2ecb807742e45418faaaf49af3210e83c243aad906380ec2f8b2e6dddb8077408466bc82b5ef1eaaa5c38cd40ea0e5641e823815510d2d9c1bc5d87c72964dfa7761c98c2f40640c7cd75a473da63e89c761e3c707074e8b8ab6deb7e7aac22b34736c700e9d36e1df75881e9e4d6a9da5752da3bb9176010fd298974509cf60ae6415a7afd921b923d668f1819d35d28f43d8581446997ec9cf696028439da2ab406dd14521ef21002ed26d9defb6bd7d15fdbc8457755f7fbfe62ed1cbe31b4948e44464f75c3192c5db290799de75796281e0b16265690f4dbdf38ed570ba6bc019e5f4dbc9a28faeff9d584d0bf9a387a0d8e790d559dbf6a1a657b577ea3bdf0c415313de5b8213534f2479710723cb03de678a8d5a857e39a46ed95d1bbdd4788a47f7af37a546ec353efc68f367ee543dfa26f3648a4b06d36486f7cb3b75fe537f6f67370ccc30e452d54514b3957f9dc2eb4577ef714036a62038db7867f7ae1d25fccbd9ecd6d78189fa348a85f48e6af4ffc0b83b4e45eb8fd9b0dd63ffd9c47b7178e79cc7ffa6174cea3c7c8d91e78598ccd9b3240059d73ea41cb5279a7a8437b895088a45b0d5380bef90f1c33e6db6bbc0bbfc651dc901b87b607fae6a71befc26ff779e31da4d16f348d9873dc10ea3ddc0bdb53d789376e2c85de1ac7a349798d9bf4551e3f07a143f99cf750c50da15e937294438fe10918e6369ee638bcd5d778351e92fe301c3e53f6d6c7613de64c3f75f6d64759d8d0333fc1b63d9953873980295c8845e731bf592cc9f69adf24db4df2135fb33dd4db370e6ece05e99f88b970383cfdc4cffc6459d537c7dca34bc7a9633e820f335d92eda1739bf561a6fb890ffdfec4f7d54f7c6e08f49eb69b4fee85ede1b41ce6b7427b37d71c09cc014c815f73c9f16863de34e957117cd6a74b82cfe66744b46f0b73004fc0707874d6f44d09b8442a504c40594108a1101d21899450110d61444268da5fd5cf2f4bb4f1ab25caf89ae7d71260a416655e4b04cdb9041637b8420736c217466362d00316a05185100bbcd880915301316972d8c14a12521401eec082292916b0804585075ab0450c2ca84883832ea00e4469b02087a7373b94524aa973f7c2d245176198e9811636e013a22f28221be0a02200cfaf258a58020a0a648cf1932e638fb4b53f2f5d94b2611990dead311a041350518510be2869814ebcd6178491459bb083125414017308e30056f4d08330c278628b2d1d10e2c116635471e58627200eaf2b452f25b48857601856896ed8887c881956064c8e1fa856b7fb8e2976643303a88339c4320c6239226a82888a1043ec60f086c7ae9cf1187665088fd51d0cc368a4822ad1a58c1253acac3c8ee797123e6025d0e46bccadf61b218cdf8aada43f36a720bb3bcd77bbf46efde9b88377d70a6175d95fad257c4fb517e7bbda2b5bd56f74d9d13bdada5fdf55b54a9d3f737de9a50a561a934451115bcc103981415398f9a20d3286e0c5132e69b840d2a50b1923d018dcd03056b47456bc502b5d0ce214bf58c12165e504118583fa441b674c41881dcf40454bd00e720026684c1b4898a12111843884126cb411c40faca8828a2284c1952179f8208b52115bb4bc784083c4170e092cb224647044d402b4841017a3233344455f8880041424862000a38104191faabcc00a218cc1c61167e61145d85a704499a7f4e911693ca594c616dc6c993b24c182d71162bc8c3013a148a24ab6539444111d8b9278f2dbf3cbca10a21843709dc1c3183ca8628330bc704174c28433889862881e7850c2ca199d269a884de8602f23885e558e221395478d58baeef965840ede881b4c23bc3c7d7e195145f40146a2305e4618d1c882b844bc8213afe040af1d724b59c5dba3de0ea33cecf2415a935008b2c7f26f128e87d220dd4d69d39eecf20241a7cc4c1dba0f842f271364c420215131bac28b956f6701b6fa9d701a44558a5620e535d495cf30462cc6786d7849afd63e2d07fef5275d7ed15d4e4272c36f9c7a97c9d32337a89bfcc64e266f72ea79d3a7c993ceba9c844dcb829e794c52f6d6cede8ab227695b6ef64ca53e9d078bda16be4f6a0ee098633279d4bbd3a1f74f64f22cef3219a2b9669d9abcfa1196c9d2d01fd6535eba91e8824b31477a9564742656754ae7527fb287bee8ea2992e865d14b87b28daebf24420797e41098a143f759e794a67ac3afdc38666f58b8b41497e292457a291d22c12f37ec480a97a606391ff8cc3da6b3661fa5fa46d094cff1fc02531486cc1767be7a18a2cfc218bd34b2d96e239b65b54bcb6a8f56c8e49b9c6874d3bb9283e65be69bc731273ee6f027b2aaf70468470793cde2b3c2b703ed3047847a6659b54e8f596dcf3c00f4daf47aae888063ce750fb4f3d153cb8a724c18a1330e21f4b85b96e5034dd1e4d92b29d6bc82726872cddb39e6547e81491252a577eb65f25890886147509ed21cf3219a631e312328cda75f96740889683e2d4bda93c934e7c9f3813f894cd79c359db39bd5d488d3a577eff46c5298b24dea9cd08499784c26320e2bd7b3b9d33c59969d96d53618f3af1a78f96803313e4214cae39823797a32ff89dc04509ef2f66e7d269fb2dcf3136f6604e51aca7393a76c13944b7bdb6a5bff74aef3765861a7db61851d546751b6862c476a3ce529effc646ba8b129db04d5692e3d934fae761eef4c8f1f55592c99793ff1ab651161496b59d36e4da390d1850c2230a43c009ecc4f37bdc088a9b5ebd8ef4f7cac4eaffd297513e827c733ed854358d3dbab65d6644d97df5edb5f36ecc1fc274e00e59c7374a1ecc56c11193922269fb68caec7e4d22f6bb28ac8c7dce4d2b226e7657900ef689ac9b4e300a01dae3269027738cb3d3ff14d2e35232714e7d98679c7794db21ce1bcf32c4750ce3541d926598ea0bcf326598e54dbd92628db847329bdcca7471de39df67c6cf81dcce3e78640c8a3b126ab3ae612b35e443ee344536739d09899dd640a528ff868c579ed5d26cde49bf374586187ebb657066e0621b8c3e9b0c2cec9357b69e05c08ee9cb420918b5ae63bd5f3899fd986928caefdf6653233981c660e9d86e84a02e175c811996ffaa1631575ac567c14a4856a7293b77311a73ff66aaf777475aa7eea6ab5b70689fd39948185fefab2fca5e696d56eb2574e96d5b688bdc2396659709dec0c3107fa6ad5759c657b7db503db9281435b6f3208236606565a0c96bf52cc1531559ec5246dd1ddeffd8bae08708e743274ee0f5ee3e599252f928cc8205f5e2049311e06c51ce9be060c0a8241324c1723248a44b123c0ae4a46c783151a2f2faf013feec111993f5d6ed13d3b748ae4d9cbf2811246c7ec15132bda22f24ae6d4422c9028ba4c76b5ea3a7f180483a24bee487f5611f9d3a77530bae8ff718f98a5f982cc43cf5c43d5da75ecf163205f7fd1a1f420cb07fe0398c9dfea3fd1649905ed08aceab7b2a46b12075d4fd69001d2b2a4539f9625ad65555bc4d6fe5c079dce91cb238b5544ba4c427a815cb65023890a2e92ba24119164826e523aa5e8828dbffe5374d186e4d265cfafa41b1ce74be2c18b0d280e303258176864d1c50b621530303dbfbaf0228b28279982d845955a451744b48a2e9aa85574b185061f1082073118c38a298490420a2e70e822872dc67c41e38507083f042d7126a98c2e465bb051a9d8f1fce2a20c2ec638b2a223125775c1e9a2d3a50b9c67b8a8820b325c84b112c51428a421841a446c2104251b6c7181e90a9e09184388881f68d08315404194d9d0835218389041121a222d25e85e3ee7a473ce39a7aca29bf30923ba3859c14490953476e0831d88009de082879f2f2ebccc29a9f0f2a5cc73984fa9fa637574565b21fd18adabe8ea3a877d3ebfc9ef8f9f9dd3de5ebd9587d198047df02c356ed861a158c623934674d2078e61483c788c716698327ee5381f7d7e2129fd759d08e60347689860638834889660962c8ec8b26022870e152ee306439851010e3818830ac492c596051036483188448058e69c589753ab56b3d38154f47307ca23bad3f30be988edf98514c4cfe71752096ed0ee1519ad0d59d8b3f42449c2de3634106c215aed5657e80c215043c805a6812f7c18e3873464600609c8c40a42c90456c1c894342c92281634801069e8575a0ce1bbe797163df86205b2caa494ce9c1f7210c40f9c74a1020c221a90e16d9195806261d2628c296aa54e64272a402e2802134510530061460dae781182f362e544258c971c4e5e4a40b9a053342daa60717445182604708426cb135dc648410fa01258f8206271c68da4f2d2828b162de081c63857267dbb4ca2bb4df4ad145d940c5ca23029e6d02031f48c92101c624224a4135d984bbf3fa6867970477a1e7330c76c0d34697a2c18a44f9fb686ea72877734b861461c0077309fd2316b0375e935c902033c038a1804ed5497dec406ea98576b03f51a6cc0a4cbe9d2db0041678858304ca73e93583048a72e9db64bafedad2f93ba312174a2ab77d83514d1c31ae69034c1bca329ae861ae79c77a886b9e6bc93aac19452641e3a5dbac1e13c576ea4688d73986b9c6b9c6659d34f1d94049dcbce3cf4da425da5877a8a92e89c86798dd7d81a528e39ef708e8405438ddbb88dad817a8df38ee643f8a5ca6d52aeb211d2861e3a07a73c7495c792ae52d20e02f83e4a7c90a0bc3a12939f9ce74ae63e3034d17c7394c360720d7248528e39e49050af71234e30afd91cf31acb9a8e0312318939d0535e106b5a2337b648e571ccb1f158d21a317ae8f0c8ebbc55cc813e2080efe3f300dea9711f242c184c8e7294ad417393f30ee6485830a06ae01ce5bc53e34338e5d4b514f5aff9c16ac71c68478bbce3c4e4288f30686ef2e690708ef288647393455956f45392c71ce89b57630e74cd63456b24b362308fd5d608d08e0d3540b26b178d9bf217fe9245509445482a4610a143040e1144d039274de28328c84093c68715c00022c145098c7b7e5d7174c516635c5174c5115dc552ada28c04c0f3ab0a1854d105ab020b0a660ea164c9cf168bd12ff51a1f0440423277ea57c6db8fc187d05e76e99a07894cbdb25f6a721000bd74593dd95f0f44a83b73b147baa9277ae62dd9f3b8621815495d96ba90c1eca5b6a70773c845c7a4531c481e24148df993cea2ceaf2f527eba11557f2c6a85bc6440f4d28f2089ae7814a4852988bedd85d71447df9e84c9d0cee531ef440625fde52527db52505050d04e167e4db1f497d11c31fae23d008b92f7002c63bad550c847b7e011df46fc55e18851527ffc6c71ae60b6d3a1467f7ebbda2d761f8a42e38627c00284314550e412fb021205178935b458b94248872360115c5250b91c2177f07245182788c07c01c41448858b10171fb81dc24881860b0e72072e6af8206b25ad0694cb16528c1465a4702283e092a5b9b4204a212e5b5e3ebfb838e1058ed44147eaa05384eed6e9c34cc75efeae9e8daefa6525196243313e30fe65a582cb47e74cc76aedbad5ea7b9d2a85da2b59e5ced182611886615812cc032ce67b30af987759ccb3981fcf3f4c6ebde1d0de199efdbaf07c8dfc11242abf31b0069edd634e9bb49b1a8fae1b9ad778affac3bcfdc6bbe179e760ae795f7f588d7bb7a04d8d266b7f98db785b7f98d778294fa73fcc3bcf477f98a33c16fac3fce4b5d01fe69ce7427f986f9e11eef1a37330c7dca459ee0ff391e487aaa7180db3f7fbdbfd7c9337a1888eab27ef8b3927efc67c73c61c730df39307391eced6b8417bb7bb6ddd5370f6ea88f9622fe7cc25d1790fe87ccfe6a6ab13ef66311bbf4c1cd638db9be453333cf4ce53a1bf761bcf4774d5d8b6dcdfad2614d1659ef23ce67038ab13c779175d2994b7a73c8e39287bb79377b7bfabeb7f93e0bcecc1bafed856896ad984d498199a818a44e8d84f5cdca4364d346366c810c2facccc32faadfdf173674a819451c32085dc63ca26d23729e3dce2191a16030e1092e0bc740ab5bac9e04b537aa5e1651b3f325e0cc3b018b52ad0abcd83c612bad05f1bb93a1fa345a8842cf5a551cc3ae6cc8800400000006314002030140c898563d1703853173f14000a98b050604493479324486114840c318018428c210000638c1918aaa90ac6ac4cea287ae0f8abe449dc757ccf8d31e4de0d0000431c0d8c198c4a027c2710a563423b08e5542885e638286f334dd83ed7a2e3b7a6c614174c6bf81299b3a01ddbd4c071d477dd45608ff78d50861fc1021970a4571f26446d555946c806fd7d054f33dd14aa2538a5284fa6e8242a208489afc4480165c0e8e04e01a89ca802b1da3d1eac0f8edf856c3b5b29508c6a74a711a21fee161c2c82186c4a0e9a1707573581927d90aeaf424031c8064f6f6fc8800016ca4083dd839d663d82286f1d4912e16c2731b185c8a99a00e8353d06b24adad97cbbe63a26645e8a92a83443b3f5b9713896bc76a5cb9f85cccedf120356342973bafacd34cf12626c65374e4bc8261acad615669f95a71c70f678f62732126960e2016753ac5ab835ea0c7c53ec88ca8c0ec42d9bc755ff3508d754d4544d028bb20154b46039adb69e801bd6d9d4b6244719c6bb58131c7675d43cb00747a64583b1324ae7c8df5326bd6b8c5394267de84bcaa7598941848d14a8cafe542db200a37f7d09a5e2f7f5855fd1829dad66ccaea9b814e1179e59886a6371dc061f5487c5af6f69b6ae1fb858dd9c53c3ff54640a90103c89e0980d035524f9050697d5b3e0c8ae25ef96f80728171c3d77a84715c4050cce93101824332717d2a1d388e54971a0f9f4c3b633bf5fa286a29d0760b931bfc9f7fefef758e233708ebee76046f895e826702c5c00ce807040a26b503c7dd1ee63ca824c75a2e3ec9f9662321ec966a30b8845cb6c09f153c66873570d2011d2098d236791887a362ea2175b122f645c071c474bf83de35580fdc5c9235265160ce7f268c665eb84dc004034a3f58ccfba6b40cb2d6ad83c8082de066d49dc8b5c490587c82495a3bbad96a1c7482defbe32c12cfd578288e5ed63d6f0b0f0ef43b77a1e3c3f2225c402d4d5c90d322163d11d3e9304728ef0b7b8122add16916c39bfcf68a7af5071e2c8b08ae33605503d176ddb42ca86bac7577af2f1b762f27a6fe40200cf1aa204e3e15bf1940435124b4590842163abee93227a90aadd9f00082d5ac1b47ce62790e5e44e9965de73399110c16b9d379957c4e2899fc70050c702d08c94bc5b76b81037a873710f37a40e4d9e516e6893fe672c58c21a0e1fb8c9eae318a07fe89cbf370978a675c3807d70ee1e8df5bd5f7462f642fd7224a22f23a24609359e1870c8c96994308cb1608e0d58c359e51b925ef2679de39e3ecc3eb606d10d24f910ddf7d2e344891690fbb4ac1b0e89a382da6afe36b192c469603ef09bb0011ce485164e981ee8a54faf0017e8839c343747325e4b374010012349a5e0f128f797227031b0215897e3071a0c8189fc9e66b80ec1ac6d1f56cd313aebe387506d673de11c994ac23760ef800e3270bf383c0990b245f114ca19f966d1ca87635e35ca1c0a7c68686d480ae99b400901b94d6e356c9a451148cdfd3c404655f79f21606587260f8c76839527b0844aa713c0885a5480b887e1580090df5c1d3a8833124a9688ca5a0abfe0b7f144883eac4b8d450956c7c01d3060be49ecc8180370415f1a1fe34337ad0d2e4edde0877ef02880c634c147b0cb47ded6123a2ad3ecfdcdcd9ba2271db77652c241197d5e39af48d62ee36f4fa546e42a38608077a6e095223f118b526be2f4bf6a45d1b1edc5f54c1ecd1478335728a95fa6500608aa31f4a7b87a5a07f127b975f671750200784b12f46ecf76c1735fb9e620f0073213b40e7502058d79fd01a3d1f641f91e1093d52e43f4406ccd664d6890ae6f6d2cce848156fa88976c0e9b54f83f08411f2eb8a6d65812ddfb4b5261676603a16f091fb552804aeda63e963359eb952e1dd4d1b91366132177b40cb8a43c1e00a679d88d4b0b66ba042202e7b8e5253812e82b19660106ac848a657d7f6fcecfe1410639949a730a2b9c9d3a92e40073addde5f1d1bc9f9534edf15d8d470e90577612f56922581b72c5517d16c6a22f2c8feaa97a241200ccb9d5d1ffa8894103ca9a5e20aa668e5723ba1bb066a08fc0720532624c9afef2c90c2235f6ea17b89fcc380efb5303621e2e6646c49e443f14657ebe25336806f9af5517f4424550d64dd5c426ea8facd16ddd9460d42691955e2771c450f89a3ccb71c740c2d6ebd6e9e2119bc1fa476a2110b70500e6db406835f8e5b0937a088a61b49bf996d870666b6d276dbffd7c732d363ef0b7d0c74ab4f2af40581e8f5efa3689e73ed5f987386560732bc16f66fba5ca7d7823d64b6377c464fb8f2e1a9dd9ce736b8e77eac574642a0e073c73a82a67fb902da23de55687a1b6ffa40a24fd0dcd434718b55321c6dd04e5058a1766cbd3d8fce80c0407f8c7603e852286dd9a2c3956b22256f4ce99ae9e67ecf642738e96c1423c3a5b217134f25a5e24fc71d7e472d2e1bdf1f51f8ac814153a60c10291b04e8fcc91c6d278ac6cd3e5307f5cfbf54a4086db5c0040ba73747f4804397b0304a06400f560c10a611d08554417f4f06af06c283db05a5dc783207156b137e2b6039f06cb8a8b2c060939c47c6a6f1f7b78b909d9434115b3d4ad2602b9883a8d3631684476d26e86c782a11c1e87a8893fc21f015b92b796b019e0508b98470d0b1bb528c55cf0af9679f4269f91d06b043f970967df1ff947d024c659af24ac51efb31fe603bca5a84ffee92c72365781c9a4039b0b1a7c99665275fa756284aec80f6db95208d327bae380884007cd58c6e040eabe6780d82f4dfd012dc59f151e2512c78ad056f07123e8b4d51adbd768889e31d76da06a36878d64c9848f6f7c76eda4dd2ab6b118148082722bb1a10182f563e13d2a20bb821c40c809fcaf54200a529d2e0e8d6445d9e77ee3727384880f583d24d252e703f5d687d8335a2d1eaa5e1532ee7f370aeead89a9f7c2c461d80172422fd8b595a9c7971a620d676fe7ab3d4a8eb87bea77045aaf41827ab4300c8e86c4e6610bfadd329b4f5f7e88236d5a024e90cd9e9aac349fbc62faf06dee4f198de1883c48120af87edd7b7a12f1ee56f78582827ab63960d48add1c1730d7bba2e0ae3e9c3f16470c468b9b49533cbad92435bfad8627a0d3d73ba72d420b604f7d3ba75b6432fb6f73468257a6dbcc726fbf418ab568fd63f1dd17007d812241c290a5bd3065209f25ce45fd4de1c7bfbd9304fd7a9a3b6bb6f263c7a3699e766633a6cb381be826b0411b2a905f0acbe5a811fc82fd7cecd973bb206a2e2dd8c119036958d92e580cacfdfed483a0249a4fe8015da0c5a4ce6e7eae660aeaad9ec706f84eb7dd6601ee90c16e210fd457b13c0abc656e87f4fa6bfad81185e464a9a57e92702bf3578cd4f16c01197e18616dc3ddf7adce6c426cabb9a9a62f28809b7461c5d6952b43c7d9e490cafbe0316b4ad46503fcbffeaf29e534f1ef7de835dffee7093ec31ac25e7d0a6b2ac4e627947e8bc3a2186b0ddba7f4fbf83a5e2ccd46bb8b914ba271f25440c7e9ecb1e67f8486604541d34b5173167903c6f6c8524d2b13539fc1066cd7bfba5cffa8d158d7c3c47aaf467fee7260aa6b78437feb72522f151adfd41a3d812eabde72571e13636a8f4445c1bbe8509f4524780064b132c7362636d48b431f5c78da0e0002c80b08c303802423acdd4437505f31e9378c7914b540506cc30d7b6bde5e2e9425840985a9f46e87455f1386949299896fe787b3ae87f18576368656010e8871c22282cb0645781fb599c2f04fb3fe8ec53d4890fb9a26e0ae9c05e566d6574262f05a07c56cebbc967c2821ee190cb93ff04217ed95a8898ef32980d0659dba022f4312ce98bd71bf7de990d4ad61718c7a396e57160288038af1bca213d49a39ce6d50b5726cdf31b8b2b252015e1665ded85dae321c959f49fc9ceee0c2e48ac3cd9880422bbf57df04e770c16e8fc49c520594580340aea4e89a940ff4a08d075892bd6744f6e085ce029febb4d308323e98bec0c81379f4a984d21132db6a50e935285023069cad5185b1b32156d5b01d010d7d970c2317fe89cc5fb3a31a1b83d2a07925d0d94ad9ee47ca6ad0ffdbde3357dcc0fefae142ac8c5c95b31d8640288aaaec39553fdb52ac22f03f5e4ad94693783c818525851269309b47f61a126dda8b5b7a74da9b9a6f775d0f658071cc23bf50fba0d3b1156e595bdb2f8dca195805b6d097551d33168648c232564cd0a655d6b623c9cdb1e961f01b3d7a0e7f27a8b80eae266cd8a3ea352d1db3260cf184445d192c2da03287a4b459a17119874505077211c4b7467034cc79071ea7bcad7de41dc85d8e5c0f747c788f5da27c49c3babfdedab934c30f45a027c19fb9ffd03721d0a7278c584decfb3248aef90d3251801345713b03fefc616ae57ce472084f070776b4d4abd98a09ee9b8e9dfc9e1ad5c4477640597a8f71dffcd1921668ff6b3ce9c1fbad58c43f257f45f1fb9112b7a974f14502cf42fe38ede8ec5fc484ebc2a228f14c941f222584109ef242655ac00588f68ee0e8da085373267c69fa4f05f5e12bdfad851652d0e58ea997fc9f7fe6551371aaa04c7764c841d3c529e422b008442ad9024f795cc87348b5ab011a0bb2c527536da4d65f94cb286ec1a0977e0eca0cd6c0daa33ebbbf3548ee82d8c975785092a79b6c6f99202b0c422f770d56af47cf46729d7fbd74bf678272b8d7c1264aac1e01b4d4d9a8f0d06d0473738ff0edb51c9d77c6b609c83a6361b124ceb2d4e2761e312c67d102e0bb063e7e11d50b2214923cff1d68a60eb9387043be5e7a29382db134b84327c03454b8f7d1cea92cdad64ebd1702d04c59fdc01fdaee9cced8a7ad10823e2d0a9053e7f244e557c4912f42fb729d2024ca0cf56bea500fc6ac11bf03e318d0559beab199c72af2b08545498ed21886fdac021a8b59d1cdd8896cb9e04dc5e0986c280b2172d718c5c71ae75d7acc4caacfe77b23621ffebb71e69e07b0dccf5f8467a87426715f02b642a02b2ac7bd59fe6ca8e85e9646276e7eeed71eec5d2606688440283be3d8abacf39fa0d400e430816a5eb375f64d83bdee7a900020c154dbb7586fc666c3a056608cdcb662242b7955047dcb13da37dc6ed6153b9f76c9bad43e0f4a99f144dd750d5287d86f8e28b8deb6d2e79a8e5e171e28afdd9a7d5033d5bd91316b96207615feb394eac3b36ad39bd7310125b978cb2ca19bd4ec9c15073b81eb2929452f93b343a61777f930fe5a6ee0d4bafc9455a1e16deda137d06bf736ac7b905ed902ad3e8524dd58f6dac1c7571894d0d7a38750a03ecb7a208d332c5d83703229156e65a0746c429847df001ce47a440b4cd6a92f21c27008a05332fafdd929b10bf3f684159e442f21db24cff3845bcd75ba3f83583f7ed027946c1cac173ace3d9b73dc842eb6536145e8767d0f57f133d0ac30ec9350e0398e4dd4314036df855887cedc27977b28b2a33cd7f3b8b12df974ba89ae33618a87daf6f24ec99017069297f4506e994fe043b815eb581bb9cce6e85afe95a6e015d1e3edcbd84963d16db18b09df60858f7b33395dba3f8d8345776593cbe2238a7a4dbb09b85e96031d0430717119d992efe029166d74ed08e416ed8a0ebbe49f2ff4f8edfc6419f286210fef43946f34e0c782f9daf8b2aee36f2186ab1b2f8b86cfb78bb651285a6ecf45a086846e263fe82004a52476bf2d13aebd4d4840d435cebacab184a0376c5e4a307b7dffc15e42d39bc1104d160dee41e4a1f4168268625a352e9953a61f95fc020f47df08c7985c79f3fb538453045aab263cc3b9a8d6d9b670a173be7954b34bb84a2f79eec84e14f160b4d6d43aea8713eca1da8a84ed82ba23302c2a3454642dc6247dc4657aaa6f22e9d28095fc9dc0114cc253d6211232b250fc2eaf1171328776cd2ddd84429730d216a1b01f0c71436c7a3265a09cdc1c4d49450ad942354733bd46b0cb0e8b688ad4cd1c8d868a0e9635c1c081464a113a4ce7df1a299356cb6cac88af7a177b988f184061f63cc021f85a40e699e3ea82183c5ba4549c8f112020779f36213619f9eef84d67a68d2a18da72c2bee33c66d1ddedbd9e2dd25cba5c2c6aaaac678b10d85d105b2be6261285e8ff34f1067c753fb815a3476cf0c4199f4002e9ecbbac0f129e7ccaf2889e75baf89a2456c31d7c1c2fcfc65a9f96a59524febfbe8e7205bfd5b95364e956aa4797dffa672c7dd0014e711c14fd4c525fc8ea8982c76e7234fe70d6674f9fb418c8bccfc2024e4c331a203726d6fc190def65e3beb10a5753bb5635dba90a5b7a3ce84f1aaeec17f42256b175773caf74f5e80ae89872361e4f66c06c479299e39b2c6ea855a0df0ec76238cf651ccd1321f470dddc99f67ac794eebbdea43de271b94a2b08d6f8626539a4058aea5dc6ac1450b1964cb9b1ad0806bab3565706baed62290c7c54c6d00d145e0371e8d6ce66df5f0731cf0ce0b96dfb44ea63b1c6fb592d5b45538392b76ca267ceee14b0460574df94c1cc673bc3c42e63ba923c9114d31a0a92f41c2cf4e0c82dbcb3d67fa2d1768e0afefce74cf49667274e90f8179fef486700ad346a1ec2280fb4ec322f58870183d2a3c8c603a20ffa5b0a832a961402836558d0b78e58d83052478aafbe280d5913f9ff309ea2f74388c787e9962eda0be02524697854a86d21a3410682b5672e330ef97cfbab276c72cc3c244c98841f7e9a301f56681b326913d4752434c1ca0b2e147ba58695cd91c90851bf1f8001a26247d8540b20bec78633204b028b5c6d3805e6494059b091502ef6eac665192443ccf078f3a23125ae6ce6e849cecd262b206f63e5cad787170f8f91e6dc71ef49e577956a74587651af1a8aaf92f1f0d855144e0f429a1d2934fda1ef9948e4de61413f56b03b2bb09963fe88f05970bee8afa0061b5e491fb87169c4f858a9cee560b05f76a36f4e76d0752f098425024de47044d421d6e4d08c2c75b28f070ef7d4f749a6ba552a50501b41be97c62f51a1b9e349f3d8f7a51e07094e2a496319260a8186616572204662195a58d336e5c722c35a0653ec5b004639da8b4f0fe0e8c2c62235cd972c987751e944b911aeff4dde1078605377c1bddee08122504e37f9f18f0a24c36db305f018879464266ed6213427c4c19da2038e197de0ced111ee041de09c183d1182e08ac2231dde2e102c51dbc4ffba4f45f2746e5054681eae8857c5019c40401ec37be21b5a58963e53b3f9fd10c1c689a10a44a32e36cf21835b831f45d02a6fd0f2eb245eec399d5d02c04c4052e6c775fba6fda18d72016ffc0a709c80cd13604b0f703fc9a8d66555b3f01abf6640840cea590f286de619e2ac7452b8f9cf90948f09ac139905f665fe77c124c83b8a7d79403f83a91c71a8d67488555c8d8ba020213e0e74365074971a1953e03319ac636840f6832903832a58673182484e944662241456f011b0778ea876c81f6dea69134687b37f8d6186e3ac832e713242a9912079eba75097e656eaf1be7837d781e952b7892ccc2e67701a687b34c63857b529c661517ca263778f3f1367c4c771150613444e6af0821bdd26111a685f3a07a20ca2bbc6e8ed12a3f4f95dce1b6f5a3fffecdab13783e88fa571e0ea5aab1a7286b3ffe0287754c45a93f4b815d7b4cc2b1be14e05b008a8d8c33831baf842d2dc1e01e9fbe8df46a3083bb5b275e965f13932e0c49ac0e0b556b586760569cd0de99d09c57e7b01bd30a52e57eafe4e3d087fea2a5f2ef410ffa7ba76441323bbe84556b4c3924f3ac20c26c88f7fb20d4d5c74703921c815d9a3461f1610ba3441fcfa74e992676f48a6e7726ec14ee40f18470ac5193a1c1a88e8190c7033a5c30a74e8bb81d38bad32c4bf24c02aee2326ab4e2b56a23fa12c0bd808676e239ac2a0f0f638d23c77ce262675cecda3f36c2518066c5558f17fe3f7e37727a1d0e96caef18f17bd3ecd5f9fc8bbdf7aa6d03e3e5df4a72e8350a257a92ed4a7950f805651d08a3f6a9554007dc2f9db6683bae2f454fb2a1a2bb38a7313edd41114d913b1ec0516ebe66e7475a8f4550871a8fef25a19f6bbfea7bad511a73ce962eb6d36469bfc36df2e170034be9d344d013a3f4f9395226c64f08fcaf7e3d98fa060ba7f32ae0ca8cb0f260e560c2b9e9165ef2895efd6ea145843fc38364445c5820b627d83154fcb8339a437a5d0cfb0c21958d07c6f92561e84dea778cc7b47f5047c06e9ee30078088843372bc0b7f4b650cd6995225e1760d7ea18a519482ba5c96919e00be75cf64c26cee9d2862b2d33a4027484f11a971785214d3dd316d388d560e61c064ec26e8be19a1e3af94a7a3fc4e059093f3150e2bc0fb1e3ef71abc4f75808af9db47c40671f45c908445797b43c85d341e5479a98d3efd26aecfcc513fa8976bc9d38b6da25556ff9ab51b5fdeaed0d33382bf3f1fb42511ec33a50fa4ec6f74e87c100ecb4fa5f0e4fa081a849667f586d3a556a9dde9938f1147d8aa8f65997d210d36f4a08324367cc52f17f5c19b98013c8f5a308feeb4faa3495d308de70aefad3be10458a099de9bcf34209d0ee74e5915a64d14e8e6fafd1fac5e448b7766a98b51c4a1ed139188955f78000d24f25e0f590d5c94ac2f1132359e3afc2471543ddbdd8f91ba64b26d9e9b54742fc6a1d4f70b48c47104f9a5514dfbaf4e71f9ec6173cc340fa3418356e37f7a5ffeca4b69d96c9dd0f17f40abaeb087255836c1e72fa6e2eeb56a17c0d4aa834bd8e06da5ab8bf6f8933ac01f9dad53f248898830ddc9b77be29231f288a4b0580009908b89c91e64be0cbf4550a3894302ff155ce3c28873952685433647cad812762beec69356e619798cba70ccafae1ffc3fd650fa71440e713106839f6e1d882ee0d293f848d7ca3f82d0ddc9089849c4c25a202e110829c657f4b205fd82241e88ff7f0cdf8cdd3f6af507559f50d021e67104bdc0d2d99224b23e252e15fab251bd05aa3e98445f00e9c839f21397daea53561da8f985e4afb54186573657c45ce039e853a643ab3f34285a54540bd52ff4cec259dae0aa58978d0532addf7165287e6388c27339e5580eeb42754e2c94e856ca08c366814ad255d383a9ca5b77fb5b9e47390fb9d2034a244f52852bc89e1181e0732e822d7f9aac4e5ef683b0c4df4fa3ebdaa8ffce283f660a565a5dc3263ea1d33756d9fd41f9242b7ac65948b4c432a04c133543882569643863b9ec852b6b7fe448aff28103c2253b0042b7814a3f746c7b1098977058eeaf6bbdd89c7ab82d3a1d739fbf14fd88911bcad82c1b58c88158403b305e9d7c8e28eef262270d7c09b851ace69cc2bc9760ed40f7abb650025086669f66577175343bba7481480f996cbb9e6d9949f025bd48abb79d345fb519b8f3fe1ea69c7df5d31cb98f1107d9ed8abc9b14118ea20be952c10e914fc87f7db1d33cd219977053b5655f8e1a9b6cd8afaef4b7ce3568da4d940810a2cb407819fa611014f06e9d5ffce04a0ec9599d553f478d777c3e8f4361585a2a5cfce682d2a5bdf8d8feac5db5f3560dfe8504cd5b6c062853d159da9862d0cc79c5e9028d3078452f49d6d5a556992a4e92ac395bd7fe955e63ef7f190a028ed72d438bafa9f7e4c4c496d28d4e32fac643d0b480c1451b6f5092e04d66a8b3a374fae523da9092f3ea5c3905d35d11a29eb88ec352392dd51246f837c654046ef582ee0b458db9689aee0b10261329845bed7980207ef30a02bff02c6de47781ad2acdc004c0cc9b20f6f4d2d983b3b772678cdc3e2b254bd4adb7d6619392d6ccbccfedcb53c1af9cc5c828fc69148eb241ef8bf4f80667be75d445ce305247116ea5d86f956195de7811171d5c3260bbea6e117fc81cf258bc8064e5d72630cb6f525f885ebdea74427d09042565c74e4d462f53e0be855427a4f7a98b4f4051816e1c6c616fb66d8542d2734c8252910fbd8f12713ac160c02b620683085c1d6b31a7a6803347e3cd2cd3f5db86e7bc74e436181874eb3aafeaac6de862a0f38780012bfdfa3f4b490f246080488a4b168b41f432d86da29cc134bb407e6562a270045491bbda757f09b51ec67126dd9741ba3ee0438cede40dca9cad94a6200475f107149dd3c1fe16fdaa6018cb959640d66ec3a9be52a0d44f075aef29b8780ac62d9b9315de691694312acf6648c3adc165a531ba47499e1897577ca8246fcea5c457791cdd44b362636af819e09a33472e588c7b80312885c1e82ee6ae684798932e62a0a4c3953516c724ae74dbd9eca44bf40a28367eaba7e0854553cfd0ab77dde809b0b85a2359b144d209e7a90daed2aad86ba68fefb2a3268572229772fb5aa73cc921ee98489c9d2e4f4ffc7884912a7981a21ad6b1c1d21980b94b6178882b21db72619071c224aa861465e9ec94b09412859fff39a3afee56f3d52bd9b29034587735b5b1c4b0817b9ac25f8e950a7334a3b47d941cf4606308d69daff36a387c0dae43c3c8e951d7ec2212539398c01fd47e4934608fa8d4f1f2dd9c4df7fec8a7f5bf7931229ade6cb6a4ab03884637371323f90e97908208ca120245ed623740937611fe52418b8ec720c8406507530211d23566db7d80cefbeff4c93123664b400ad4dce80c8009016c11ec77334d7db1d7cb3468969f6778890aba03d477b1e875186ce7e8b5e9580a52d29075a1a116cdd74f65c3db7042212c998f14fe8cd8187b184e30609b13bc30e2bbd9884b3a9c0d45be10d5c439e98daa062a90c6c08030c82855a0e86eb082025f99c4266b4bb830cca9a308ca5f5d75fcbc538b0990fc229abb1d858dea943fbc9470512bb98a33eaeb6cce6ce1a0653a175e520765ff7e89f0030b3a50052757b06228eb666036c5b9a1342842174c8a8073deab1dfb6427824e3354d3c5fe4ad8f05d28ee80d2f1e014330ad062cd0c98dfa0e03aa59c726a1f56b899e2624613c4838f9257dc3352395049b18c422085205bef0afef065ef008ddc1494fa5b59173b9f436e03869e51fb4fe6eb8903db7a60e6a03b20a13103a30418c995d4060b3863872e2af22a0312b99ec4cc787981b606f9b35f3ee4866a0e205eee27e281209d2b3e49bb2724236112a124f2f5e2e66231d148f544c17c172d29371e1f885d9001ebc643cd991ff1bf32407195033ed565a5863df97c0f84f2f0e17a3830b9e028deef1f1907e48cbbcf01cf4e5a67321b61453a044c2d93e9f822363b4999b6f547264f8b4a2e12b1b5561ca6073361634ebd637b017a4ffa5a969c5975f986bddb602b4f9fec35952911a38acb18a3e4b002772cd783635ddd344de8b34b503cd4b406e49d8478a75c8dccce7b6d3af4ab3ed9b4a21e758c403cf36cd60c7f55acb8af1d8f4389c30441e176f751ad30dc0fb6b178a74925c798b2a4713dbd9880bb8896353ac403e26a5aebe88805283823a16823b8dd2a50f00f60d21efde02ff81d1feae3de49e66ac02d7906ba53faf5c72ef29dfc817794ebf95b82ac309879c458363622432d5ac02fb756324aa0e13f281ab2d9ec0b60fee3660121125a3800404ef1e1400854e3a25a3acdac7765c24c29ae909ef0b8e1cb2a7834bd80ab3c4fffe0858a20b92a8aa5dfdbc486ef6382adb9dad77086bc3b831ce87f25c2cf356eac0c10b66b9656007f2347d9dcfa1a41f98f02e85f8868793ffbd61adb8c8470a0fb75c298d0ce73b76563fa6e8c2b1503d426f14d5efd49d38ae05188dd501836149f0ea89bcce3604070e9e619d694e5b1c7b2b1f92c6660f8bd1d14981decb0fe768c917d297ee8d887a3fd5a82d100e5700cf8aa5b352d5c38ab3d10e96aebca1a03f0b5c3d2bf12e7510eb584f5ae6d05a3c9d12e8c6041610c356090b90ecaf79956e4c1ddd4e6accbe52ad38757694bc08cbedba4987f9d01bce0b1442a4484a43cc5cfc17ac468404f5d14e066e130b3e2448ba8fb3544582eea2f080383ad38ed3f1011723cd472e2999f39328370ed987955ef64e7207e1d4cf50238ec42c03aad7dd6ab6eb68d6698f8701b9f9c96073e40d456b360ab936fa6df5427fda751c00f3f05457e5bc6af6235903914d870271e69be18c03202dcfbaa439a81799bb1e011501b735237310689ebc8eb8a5a7032080b06ee68e0667b5c32e4f0d46c4e86f22fc2626b7fc3b2f0fad0522c2886c58f8ee7cda7cf433a03017d77f440f2da24b14fc5a6048e432a99c2eb64c7f80830ee970a3d48171e064f7f7042cbd5f90dea6957ad83c7691cf70945931185c5f3a9c43e4ce110ceefb6cf09ea75d1575ebb186e00291934c2d1feca11a4ed573a647a581caf6aee832c821d63154cebb45824deece0c56b1ef2418c6c92027407ae37d0f5c0840af00b23430476619e9e903f02ea51f34679dbcfe5fe970c8f20513f1e884fd80d048dcde1aa6084e5aa51c9148e64e1fd13884156621b3b89b2a2cf246c2662fdeae770f69e5bbbec0ef1170242fbed327a1493de792f31f9c750780bde1579be9d75255de2c1ab0c694aae9823ec74e7dcc514f53ad81a58f691c695455d5f65d0528cd3a641a162e3a61751225a0f27644d93ad52c722bc0a6397ec920d9c814bd43cd96ca882a9a081da5ca79ac7e9a04ba05db0f70545a55215626730a2092bf7ab1d3051e62ba99479a8ff10b23ddcfb1f23758298018a43aae512fa378625317a834e8727cf992618346cbc67742d6bf878b0f0a7d8d8aadcad504e3106b080317cfb9f187645b3c333fee57201fd890ccb5328138e52b62585a7457c0e43d1d4e1b567685b7fec6517d7f98f709056c9f8a6899d591a1ad0f35405996537e19dccc24c1d72032dfd1846b7b413ea0cd8cf3a34bfc2e0e466bc3e44dee01a18249976c1793cd7bb93b6f689236e6cb0431e950db3a0169d7f9c4547b7620e4b867d452fb31f70d4e4f0a812c2c6385a9aa7f6e84c9c8a19037530e08dd5f7cf37a276d84a91c41d2d23af303556121053af4ad5a49f3ac7bf47df318daaaef0151711114dcadd9b86c21c00ce0f8001b96e335bfae36c7e055666ae1d6172d2ae68abcb12d1cff08490ff9d6ca5e74317f66a3b6202456ae1b77006fd8a5aff0ac5a7aadca17398359ffdb0b6743b32b566beacf911f9f2aa79dcf72ed8f136f140a9b0e1ae0993d2c93f867c0a5dcca506f0cd656f1167518da4e3a0f5853961539fa7895dd75137b788989166c3300f42db16c5a2e57e6cc97c5bba6f5ee85edd1a5a770221efbf723b00c6c849acc33d1294ba87d6f8d2d42cb02026f5f969182b0c5cff49cfa0f9bf0ddf1ca9a6ed41fbea3c2f1f205b2838e0ad93cf8f61d41a24681b224a1869632868ec81010a3e92ea89c7dad43986db8f1b0026a45d8ed90a97fe52a1def3b7874dd3be21572b93122f819e6753ebbc68612d18c12f796aae1ad7a8000cabd90d02043a377ac7aa04de160ecdade8f512671e8207dc8ae232023b39f96f34e55df5afe3f0ad87181341b0b527c8a704284614e1eb5fe53626fa5fd25cfaf34d47f9a66e4b3a37a0141174a444fc9529b318f7e0fa958afac347c619300e67a4b3892afb46b85d23dab1b4576dd99dc7523284f5e8291c76dad8ad5956418c0209d4f3fc034a82b7bd9a6644ca16aa4118220bc9ef04304ec89e5b721b5c8bf05dc35115f849a414aa2db132b780818ccf1fc285a68153b6dc4707ed2ad181d2d07542524fd35b4df353577adcdcc9683a0a7796479459a88e542299a9129fef4acde5403cbe50050827180e9a19ce442c4b045ca203da904c8153d911c432d8f12d9c1bb46f962ee43240bfbe1c1c9e0d50f147adda756b28336e0d9c4ee47d209b8b7ccafe246d9114b2367b48ae4591d4c9f0cfdef878d92191ee733641bc9df84c92b2ce755f14bd32ec028dd60f2ae5a68ff45a0bc9c27e23775ea6fe5386a170f4e559259305183168b421aa23d5829acb0115bd45f594051bdc3fbd96a4832b1ae08fc486bfa684173e7cffc9c4d61ce3c83523f766efb1afdcd64d3669c2302b302ece62ded708e20792198aff31ee82a1b0cb6e6e15c5ad33a236ea96db30e64151891bbf6093167b742332bc7715dfed13db796990fa6efc43e07445ce3ea4760f68e0efdc12567bff462f4bfc030f196eceac6f4ad691dae0f97f381545cb22df1557f9858dcb87cfbee24bb30a554cd935aa902fc7985ed915ef71e068ec3a7118ab975d009f521f619edf7e545e1b728378c05ec97c5b8412c2d60c0f0d95f3645217b90ec8e95bfcb99758f7b4d79fc48e7bfad6fd9636a8cae2b1f47a6ddc07e09ed85cd59faaf5fc1ba45ee8baed463deb5ff61832d74be40a9be7db3f8524726d1fa0b12a3222747cad9d376e5e4506942eec0366f9da85445d570d2615444c84c510ff3c1fdf969bec6c4eea49a2a60f277ac0695a14e6a49b5f199f6be7df7e4719946dbb3aaa865dd969d598b3b2c337f50236fea468ad4ecb5bae6b0e76a4b669436dd14a38720450338665065c783f4b6c34342ed0deedca146878750cca2e47361b1310ccca0045d659cbdeb863e7d133f7f428ca52524242f5727858ea980f1be414d71b28a314105dce3239f2f265394035810a725cd543725ab842ddcb8758b970c7f849fc881e13d5b58ba553021bb5c433cb16ad75de85425880490a467059a6ebfada32ae06d2d9d5a43deb5c011c3437b8ecb0ab614f4b15a53013846c593e6b7a832021d0b6143275f505a6b65105f3aa2cc05e307f16f4a698662e98f7c98fc21f534605f8f72261881b2e3bc674d0dbc2fdcc3a04409df507b2d364624d6b43daaca0d420d427bf66c2603ed4e96097f0bd2ea15baabee21e75c523d93729478e75c7201433226afd36db5d0a8710ce24946aa6502aca022016b5844e98e302aa70baa3d7acd843ed04dc7646e5197a6d270fcab14b471f91f240fddec4b8bc6bb5bbd1140797afcace155b9a862c88ec367d893f283af9c05c53ac563c50cda54bd423d72833ff48c2359f4c8b05fa868f0f0293ab7b69b8777a0f7113f48a9a88b85c60f2dede33ef1789afe113bda7f11e669a65b518120f44f89a886e67fe9aa62fcdd491d1dae8b3cad6d8e1644c4cf9e9a6c7584daa12408e01c8dcfbf462b18cc334196953625f6b81a1be8aeddd05f12cfff5f1fc78af892050a86eeabf27499cc41a6ef4694dee70162d20cc1c20e6302a848c8e80ff40ddfec28fbccc52a3050dea98d3441033f2d8901f09b3e1d9340a1d4c57bd55bcb7a457b4ce404f05ff6230b12e1f6ecedea9bae6523abe331a4220146cc87edff7e116b6caf0050111094ee6e07a322680614c80084b8a106f53df2f9a73a704430e7619d2610fd1a4a801896409ee6e6672264d1a29b614833f11b9cddefc611f854a9783325905820a923f6740d78ff7d18c8cb9917e28e010e3f8c9aeb91669abdf873b7184f4dde0e6d64574a2b767312a3165d2b60f51328b8aeb65f11adba09d33ba5d0579ddc923a7c1781be897991c0429472ac953a05182be0456a9d3aba3da14d967fda605f5de21dd3e6025734fe3b79cc5ed7bf323e4bd38670b1e458c80016be287e7224bcff622a0dd963686f525108ded8fa7a4b7896e338fd66190b4f1fe0725a71ee1e7c1b2274c8c581fed573c8d9b58e6402e2710fd752df5a03126c3a1b7d20db8961069206758e23344f761ff631d804a7e0b962c60db0d3c7bebedab43743075c84f84cd320c94bdc22a3c805c2d70e2238054dfdcc0c225953e1149f6003f3fd5dd86526a5c90d65594eb9e621e9c2fa87d427a0d742902147b010aa6c2c3dd627eb1bbd8be6b103cbb3a049c67ec12ee614aa5337a128df61d94a3fb8848924434051b6c44d3644d33b9272711a2a3663055e3c3a9de5ca16fb215224a83de055106c34b1cfb8c6a1ef7d177c6697c405996c9a2cc1490fbb623c2944980bf503ffac2169f7c73e51bdfba71e11061746646a6cc8f8864f1764a87db2b09ec9c29cbfd389aa858ce227da2c38e630a5119d363e3d06f1ff784a047fbff6f93e75e48a386d11b790b843f6286e28edd73ac1e4b1bca6f861e1244bb96ec160c2b520590456077fd3c6e5b2b9b861284e6936c6d65cacb948bef228cdc053ba773d60cbc7ae7ea332fee5d701bb7ba5ec6ce6ecc3684226ac4951c40d65353f01d12765a81bf35110232bd0e17916838d8e808928f7051509227664275cb4908ede32f34acdd1c890fe25e632a3c96d6033ff9f12f0d9eb2e8371dc058d1e9337fe5019329bd543022dd770c025fe3621c37313574dcabbb16375dfabc89e17ca63ccd799e5098cd633d2bacdec62872e179b5e2f932f13ad082ee9c56639fc207a6dfcd4fc8836b2b14182fc7c9d29c9ada20a937b4c93d7daaac8448b2f7a70143593c576d6ff5e2cbb65db63219ec69faafcd28faa3385ef3b593dd5424acc15e39c9f31be3afbd0fe5463e1e8cf42a646050944360e6dd4571d3b6c3d9bda5ee6be7010317feae0db6d6a55baf0302df1bf78f52c2e9536accdf40d42c936eefb30d77708f38bf740766757b184d172d7b3a64d12bf52b06a14cb2db8f9a1727051e3595e54d724da525bb8b47eee837fae93b928aef8e4d2e417b1565dbaaa7caebc313d8a2e8230eee23e1c11e97b900badf8c62e29306bac4c3912c73ca5806ee0dbb607327d0a3cccfaf771b6b46b3244723372b8d3acfd481fdb4f00d59f4cef54412de461281d6ea74dc083e5c91e53f9aa69d33d3aee03eaacfa1a5506818bde4beded321080384cf132fcfc89f96e506ad39ec757f97241ec966add97d4ad6fc20c1777c736e3f33708ed0caa24880e9e965ce4d43c0648c6290fc1f26a11bda6b2dbaae8fe7d6a455836d05a2f118a22797f53bc50af2812f65b0be77242e60bc53936221f524e1b51acf421c416baf285e2a6ab4ecbcd7d93d410d5db13c575fd5814a321a615cac6c39fe40723195047d2dbf5aab1a054b1454f091bc315b7eaa5887d1985f9ccc0fc2507be2cb695fe7f706de95cde511e9cb97ae9b929b99f28bc1615556c02dc79714c7954908eb895b199326a3ff625047dfcaafc3153d9265d41353caafaef12d2ba268b7b9bc32f2425673bb763b3a4dc3d7be62bb340327ab8c6b8b3799d68b38d07295e0d430e684021ee427cb08684b209b7122e0888c4b4e1487a21efc85a1095c966e46382d13eac483a6a3dad1f4754be4147264daa79b4414a37dd0174b984453cee5a2d50e2c92bbdc3c04adfd3c5348bc6a37190e54a9fbcaa458537c102235e1705a6cf2e337752ff0fae964d8bbcfee8a5ed909c45cf99613d2288acbd975f1a971cb158630b3f24091da9a7f5d7eb346f88e048a750d7f9155b0203e83a724550f1d5d583ea22b1b1fa1a32a886249ccf7f78c5eb8dfd575015fe3ff4e087320096761e1a0921b372c0ccee792bdd992faac2fda1d1147f5cbe6ca6c60bb90b39d9c90323d4bc4541b3ea8246a0e4c3267e377d98628eadb8b8d43fa20aaad6a46ba3990f39e9d16e6db561f6a3a9bbd873cfaf6c5754b547039610964ad0b1b03491f6259f9b0b088b218c2128c7f49d38dc341d95e098a670345ffc6dff31a44ee07ed72a9a5ebb3b3b3730520d7c3524fc1ca53348c755c55e0351bdcbbc8d6128621203426b883c9aadf47665888b72fcc360ce8fab3d1d06d05d07f7bfb15930ae2f114a1e81b15bfbeb012b1ef5daf63cf889e3a80cb3176f107350d7961652df2225ecaaa7133cb1b75f45c5e58075cdfb84686d8b7f9ea3360a918c7b637acb06452b602bceed1d4227d91fc0c615fff6151b8703057a27c52e5e44371aaa9e7926ac4b212c9599712d7a1e594d4ce40565a2ec4ff60f03e12365527301d72030c45bfdc6bc8e517b9bb6fd6da037585d3c26af40706a0c4b3f310a799dfb392509111b8803b70893b70352e39ee1671fdcfb16c34bca0811c5800bdb9cf6a6e7b52b8791edc78af860e15ad5aebb71fcb674e1430a93f512ab57dfbbd7ce646137e6ea966757b971fcbc3dc478472bd16173fcb7fee4174ad9a762ebff7c75c8f689a2a2dee3f73f9b08bac83258a1c77e17e6215a10527ba246ee7f5141445033f823eeec6b1a791671150fe9339148a50c11801f14b3df6c1d6d08a74d442c9e76087699f7ef4e31839eb2fc987a8181011be6b9d576f6b885610ca93fd0fcebcf639909b1156a195aa14cc09cb71a9a1aea83726a4896fd29f1e80032a154973d05bb98431087f2b4e86d1bbd8b6aa939342cd41813c90c4aaccc43900dc0af6d4728ad27f0ba8d1b52dfbbbb41340fff30445ee1b4929c1da3c6ff602bb6691079193809e64b0d8836ca4023c3faa20f3106308c64807877ec4b881b8cc8f4dc21a075f3325ebd5d288b65582ce5bf3489bc6a9645989ae91edfc51f5f24a758e225144b7e7adeb3fb7513a456798e2c87b46f5e72e63d8be6f626ab82a8834a3e7deee48346d014d6b67a419869b67258c6223c83266489e7ff69088bec1ec185bc1d387de4f84504a39e715a6a6a7af1a0ce1883c35adda840d117d580954982bb444135d1482796461c7f43632e9c02384d69399d7c8bc79ac30f1ea855fa1eaa42e1e4aab0e752d07abb13f84f11e3347a98bc489e46ac4296c3fe20929135ac0542c20febe6a21935d264caf8190dbe0a74effebac8a962011a88a38ef3ece089cdfb9cc334d91e8e3e9c5b0bb35cb322a60f5101a103355304930458049f1263c2c09551b6e869a5077a2de4134156d6e4e7d38505e20fa2e96ec40074d58e1e84611e295062853fea19da939d301a4e81d740b9deebd4df5a223eebe1f8668d9e1bc6b063335e956755076baa614c489c8e7a228aae3306093e7b1fcf5d9e24169c066efed83dedcbd54bf2e0959c70c6342f0613a9cdeddc066c6c49e2772b1b8bc48c2b1c8b9185ef383a6c47f86f9165161aaeab4f442ae89b7cd038d0490439badc9df916a7ad12309ebf63fa431fdca25c14cd2042c607a57c938d8840210d6abb472943f8ca27911cf01d6116e27a8b6841f41d1c557eaf213413953909363339989082875a8391932aaad10b25a2d9784a4ad9a5de528c30641dea5651c8757e2411e1fabce55d52687fc69f4ffdfd6d3a1bfb32e8dfcb85469cde495235a0ceaefc672c423c9c1a5ae12a8451e01b5dc3e6d1f5c8ec6ea21962cb95b58e28dc711df0770a16966a69fc5b355bd82bb190ec9ac93676ab4597d69ef37e6aebccc0c90418414eb4e012cb140803a6b78459e2f5bd0db1f1fa039e975988b4e37f58faae41413d93f09b06226c2706a33a43e9c89c2795fcecb52f382ca1b708287de8ba1d2096d84e6767d8062d0b205a4c61b53021aa342060a7fec97b145bb18a01b2039c99e897534fe38ca49828f71ba8d0d269ffad4da6641aa806ac5bf5afe5fe82dcf5e494e76c7e33e4f34ca66faab311ae07fc08d39ba14119eb15774ae5261e257cad5b330b7ad25b8b7ba8e23544977b0efc74f9568146248cca35fdb13146a6b250ff2f308f6dae31a7c007534eef0ef96d4ed9e4ffa86d5a27fe0775d44cc470a142766ed34165def6b1858ca8a93a001f203d0158c81286196e411f723f9e18d816b94e693b155d507ffb128ac6ddc0cdb1bb7ac7dc76d95c7984156bc8e84c88a1c41e021b3528d306ec6b862bc46bfbf746ecea2374ba54cab11e941afddeaeb6acdc1f48bc374d70827118a84644193ef9bc01844dc51bc3d757eb708dfff3adc97940b91592de5bda811f6fc0f27272144d52f7c854f92374293642cb90e918e8fbbe080e43b9c06a3cf0c3f1ee2ed17a6c0a8d5d166d4f0767af962167cad7d8b666e8fc1c46c5c1fee75702ea475fbee07f10228c094838ed2f0f8e42c92dde475f02dda5c7ee7143ce3372d7b3379784632fb04872fdf2110f7cc9df76c0be0bd0f18ac4214b4d88702ec77d94c9694c4ff7f0019e6ef9b194d9c3799d2c13171a37b5dfa5293a19ff0b304c6d63dfe7ad729efaac0414cacbbac2c141bc96692cebffaa3704eeecfe0d9a182dd3f589fb9c6bc4fe7ff41ac6d641f96230c260e54828dc666fd3426a8f7870a015d7cb0a0b7c89e80caca698cf10c130140a90e1d6b279d8ea0cbc1ca106ebd7efac3114a9fddad5e6165cb93a1f56ec9fb1a4dce395eecf7b31968cfb6ac2fb70666187ddcfd625ad918ceeb9085e9eba41b55a0ede85139dab7aa7dbd9ae0d353a84448d0896a5881b7d1b0b160401a7eb7a903c23d44e827f322915f846895fd4c17189810c7336a9662a48fdadc6269247b7c10e3744e01868a014a24b06db37a5b24c7e3fc345c231650ea8e6194946ab177853b4b8b8780aa53d5644e7158fa659626b1e3d6bf99c742a50d58c9ed87d01fb8c8463e4e2f046c1ad721229f9f3a7f1c391da8c207a10f355a1e01c998fdfc7ba9718e620d1b62ce28879c4812eb7f4351a99e529c151e995fa0f9a26c482383f777ba78fda3ac607adb58ac33878ea282e9ca8d5e69cd13c43036c503d09d36bbc9ad84e485ae1865070f892674a0432796dc3f720628207e7923657190601c7ad2f39a1bcf2e725dbd73fd81e04fb774412d3b22c172223763fc147e8f0711df1613e0df05932e68612177cba9b8a41bfc4ac6fce14a69399ac08257b083644ca549ba47928b938fc6343422db359e57b917cb25dcdd28f0a430fc99687d2bb09727740905acbbe0e4c4a7812948baf2cc8781e0a0755864a3aac514f38f844e2038213ab0d8e18447a0722a0b56b42abf576eac355413668ef0c705a1dbe6a7e378d064471ffab116311871244d3f775c67be1640c71a8343c58be30bc6d331a2ae178dee03a7a319eb979b354c5187f77ba30c206df233d06c42d80276036ee108cfbbec3615b708166f05c3cfa0be487a5e53c22a865937e53b733c590b872a7abe45acbd921f9ae55ea9754928a661ac11e2a489a26b2a80d6c63e126159df6785f534a0b3186ccbc93e997bd0559bffd3bb161c27cdc513cd202fc2bd8aa8e170c6a25dc8bab8438162893af906492eec5696e9a1f22a9a569d84da88dabc6800b8cea7b929c28a701c713966d0e067a751e5a58a9b259f7d702cad33cdb6e1236f9ebf3aa8f96c05603e7cad3fbe4869f492b87c0c279c6d8b4f0ae2c8f800991827bd59c2d9c90aa1bb5303c23b9eb8f76a7a6033103092dc97074c8e329036a639a62d603bcb03d56928ee8e112532558175a48b77a9fa281e28d39103eafcf6f92b2d57fb604b4e6e28e0208a3473747e020b0377982e512f961ea26647ded5d551923be3d2b862787d35a9f06b7d3e8a691d7b3a7be7b34ae07e9e8c6dfbfd4fccfaf40eb5a38061391845971ec007fd9d3a76c4af60fb72ffd40de8ad2f81e9b1a2a7deeb94d82b32659acbd452672a5fd688e7e7705223ff18e625750707bee1875f97b5cb78e3a9c313f6e1796b6419beea4538fda6d0f71a8e9215091f2c1c611e0314881b22314760445439035cd51be87082a94a0851a631f0935453afba640ee034c6243b0156f65dc7d0fe393544ac9e59e75f74e39abc904c36af0594bab6d000da24717c0581bb2da3048cdcdbcfa1cb9b13321a96b9f5a91b27520562801d4de84d68510b616867ac08012773ff73e62544875992e40229cff80919d9f440489d37f03c4149d5baacb4c3c56400490d2fd56ac0f82fd4901a2cc25d5ca3c00f77dda0f34a2e08d0397a9cdbff8cbb362670ddfb1e00d4b5390dc8e45060bb00fe035b11052ce9126fa205d997b4664d3bfcd9b557357bc991abd73e7f66418a18dd8b141bf9db2950aec399eb61f9e32862ee86b711d4c4a7bb6f1fb03861c2f2ea05f9a5b19200dc060505859e8635e7076984572305c524a0d9766dcbb46853655d8333458eb6e3ec41f91570255e7df45ad7c55a845b7927f5c417b46851b619360ce0efd9d6b8275e8c54eb14e4b68ed75db089ee87dd06edb91f056d8a79fc9925c3b7170a20854b0dfaa9966c5b5948840caae835003f22b1ca43420d9e10c706ff3393b21b9dc9a88fd483b95d6c7ec13adaff7e91c9a37b86791909f93b623e2a13255ce5027cae106457a0aeb6568749c72053a1188e295c381e88415a9ef4aa097508b7f52058b6db9b06140c2875d42adba1e4db427293659a87c8eef31ea7b09a60ed483e6dce821864ca327ff769be32bea4212a200f52d0c359b17d4b597b88a19298e6399441440c73e4844b1d26a3bbd1aaa44cc5404eaa12fd45c95a9467afeee34fa7d8ab3a2a68324757f4929cbbfecaf44e1f6ea14c6943dcd95e489b51a35b728b61a52e824a83b84073b1ab77138cd82a3f3c40e52a98236612669f54fc797ee69302e0b94841e205977097c061eefb42389260b638b50e976e083a5c6b835d527a5ab8eb3ae6328958c37c803fd666ddbcbebb81b2b275b5ebc1c0c8c6395df02d5bc58ac5d2b1ecabb495cdf87171dccc01c36d40c90d6e53fb0618c7625d7e247af58c55ff63ca0455f681736a639a4fba21cfa537f49a42c00f49278631df0f0e9f4e83c03e662846bdaca07911c38885a384820157f33262e0fffa2d90ea836064ae3f616f34a4c496b1bfdc4f4687ffe859be0d9fabf3ba6b2a757d12cb905e8abe5a8fa7fc9934e5545a7e42337fa043a2d93fd480ca6b077d985e4e7913c510f4a5bda920419cee4091f427e1fc76c80017d2b4ecc955f24f0297f3cbd267e999cbe5a0dc7767fa42e45eff861b120d6ef5bb6223897cfc32423ece5d421d57a9bc0d0fa25448b750cfc7aaeeabf917051e6b19dd30e152f4e44dc0444a72ac3eaf5f15c4c75639af54cc2939b95e5b6edd3bcbbc73d7f262c78c3956c32d7e318dd1ec9255a21ad97c500c0cdeac755c3204d9aced61814c3e3f8ea564e5fa4afd6af3528e8e9689317cb01116e5d830facdc39099d147316241b8f8cf25b954a67f81b32593e73dabce9d24511f98ae144a51eb2234a30381028f70ca759dcdce9a0e61655a76277caba0feeef0a76055f99d11c03ca126c34d66f7aeb417ac0aa76ca7b7b6541c7fbc4fa7c48f2e1b3b000643cadf2137cd33e8ad3d8e645c3cc6c603fbe3c32630204acfcb5d8f69c2eac6370a3e57dcdb5ac9029d48dd4e4f52104e58936050ed38c3c57dbd27392a34dd941ba0549a14ab0e5144e8737cef0c75755d9ab704d01dbbc0380a4733ed0b5771b29b14403cfe9ea194a4a6d885504d475aee656c976439cca9c3ee665c6af37003f4d62b206df05be7400341e82d10cde6823843d11bbbf2debb355224ebf5e7349255274fc80c3985a8f4df940610102e84e4dfc94fa5ef71142d2b1b5dbf68f9f10d2225d9ac9139276d17765847c13d00528a6329271a396e6e465d7c88803453e89300b4318d0fdc0fc6409e6fe41b0ca316fd10e950a72f8811e50181190e0cd0201af26d8f04026f6c52575267f889891bca8474e6660a08f0fa92f8ee7049fc6f9c600d83f209364b585e22a336f9705300c05656beb626014f8e492ae31d40fb3182f94f02ec086db7ee972d355c21951640ac82c43741e369ed510b8ee195cf53ef16487941501e27d0fc1beb2694172e1d30f0f1ca8b23b0050b02148621f766e57255c3b23859506a6499c1bdad3001d2fa916e4e9b75290ec3808e9227c4317fa13d3d5195407c2a9e746f8ed0f5413c952944b00b0e480017b89307e94728bbcecfc623324a127029ef91183baa07189dd3bb69600e881b5372d4703e024918892e46602de09d2c463cc788a70b7df7f161c6f29f9dcc32c0f42ed58971996e2ca19a24e4f6f4b4992d4e8cc70edd12a42eba26d78b1fb8b3cf073b03695006014232e6865bf2c619857276c6caf5148129ca0a15adc1d262b956993fd653945a40172e1905fb80e60db103372641858538c1dd6e576ea12abb6dff273d4c6f27efcfc2a5cae361dbfe12a00b11dd4c65fadab48e4c708fd4f4f1c1539f5fb578a94114eb1f6dcaf834fe3154ad37597358f554ce8ac5c01ee178405d3d27852f6147d306a401b45774663de43f055fcc6afab216cde1e458f5f435c5896169bf373917b87dc9b2209036be7616f44b3e6e0c88a5fc7514ab5f27ad770b84878765a9e12df044a382d30ed091c3bb4d4bac259f988f6ddd081d8e51837e7bae58f3c08f6f64099233b78083e702877653205324cb66acbe2e24f831d8409a3424209c70efde7dfcab41032e19aa88fd0af13840158f92cef5a1dc8a9b9b877382cb26336289e33a694fd2dbc905698c791b9d96e9cd605f69718eb082c41adfc6cbfa6f8a788dde7b7e9d5d9c1b5980dd090b7ebb0faaf99677789c6997129a1a5a6f6d4548bc98b1a65d1d360ebc8dedd14202821d28ce3e3980554c725975b5ef818901ca23625cfa6aa7ce5d636ea7bb95e370b1c58bad634453544bc82ede5c547b2c513122c81d5982877b3b2d82f2b49db7977d3502c452774cc1a066ddc5bea498b4ee69b61c19483ae317824a8c25e86a2318bb883a64ee1a8b5caab2aea9400f54a90dc34cb063e24e8357fbfd6a067d7a23d05c80a780d5cd58bd59479f6292d5d8bfc029d1b2e311a6e6b6b0a3c7f94d0d0ee735a2edd06824dcd136a0b4064be632809bac9db256ff58bc2d792c23d11c8c4b26e385af1a408b8b4db6625e68970bd7fe972d349997fbcef63e02f2544a7e701c95000aa5870494813d2ae911cb86d4708ab823c84c8991815b217d80973b8554078a3657774134c023558c47cedeaf583e4f331b9940df664a1ebbc1dcf40c49c8cf5b6bfe8f17fe9698f39cf098199de2404666201052c64554a9a4631a75f46e49286105402f258c5a89b99b48c5da32416f97ee6915a9bb49ec2398fafce2ea24f911beae4c303bce868da5dcd539cc478d26510a237a6b218b4724ff3ae408a926ab035112a63681c2b5b8e83a002475222fdad754b4e58ecfea1dde316010fd657fa174148f2bbcce4f5d51ff3483114349d502a6d560373b52c7b522946b3aab73ba484de49ee24f847f7fb09678991464acc3636cceb4dbdf38e7ffaaa197383007a54b13cfd81890ea1b1109f36e0b27df19150bcc3e4548b962666fafe81ea0905f5358e6b1e77cdf876ae559102deebceccb196c1b33a2dd6fcd4252d1dea20cc6e5abafdd1e1154efca02e92856aa200a64e5092ba9168479bfc05a0059725c14b74d2b44b4d63ddb1b23e29b9c486ae3ae088c453073f3364ffe4f61abacfe64c96eab1b6bc19cf97c353010212f450c07987d46ef1db9ce3a01755bc0fbc3a225c590b990e736152630a0109edde38b5bfe0b1d31977141c713328f53d9bebb1def9d0dde115a77382bedc9a4736f3c4c5b2dad6c49b5564589ddee2649a8666e7c6738a9277a02bb8707f2efdfc05f370ec1644c00984b9455ab9e94cecebaf13a8f2386d3cd4a5f7674ed350d6aa335a7e22485e289372b78b69441fe6877d6509a4a2e761712076e0fc9839cec7b2934a78dc339fe74185c7c5ca1302e1dd6d2f59f8daaaee00a3598e543a89b5a215adf1ee521a660ed4027f794c1fd62efae801de0eef4658fd192e57ae4d63bb37ba44ddea5a16d7c44850901c961c28287192809858faf5c86b11f7ca604c83164eb80cc10a9d02010f01684329e9ccb916aaf1b01962589c9920e09a85ba3c666fe4a0a3065d3661d61677719885fe1782d7ea1bf9df1e32efb4547aabd78b0c389e421dbbd5143f91977b9e73e731a6eb46a623d80300235df9ebc1ae60fb4b47a07a5b7228ca03e57e34d069c069916035166aa6b104db4bf7516bb328ea10ed0fe097d0794a67c9b21564d84b53891e028044f453e072aafa94e0e999ad231dd8eb6a819172824834ff66f8bf44d9d30b81f8ca09b6c58ffa4352da4f5cc00f923f9f7fad0a0b6050104d1a1527f031f3b4f2493a7c374b351d01ef97b6e37db22b553afe19f8294cf9e06f7e11970f06e398635803635c11684fd4e7b84c16a1913f7613d1cd9691504616fcae36af02bf1bb740da0cb623ec692309f9d18bf33ea8415d71c49f5034501236ab6b71d1d2d7fd1a9ea8df45f0472cb736a989cacb0df8726b6a7adb6564ac435f698f798514a81c9cb3e5dc8cc370f2ee321bd8a714af01b8534faf406e8faa5f27eea5be93cb48a0abe621a157292620a07c8c61c91a729a4b43a481dd23ba4f82d4630035472c4f83651d881dec8c0449a27c1c7b0f242708cfb51dcf6f6b100c48ce25b2513f6180e51edaeaa91c98a2f26cf7e79cee3d2a2c80bbedb34616a02633bc29900ca36231b4b1a91ab2657d52c4c2e0d6528d68a5fdc6b82cdebd46ccccc528d6f1f5cd4f59eb8f5531fb16e1d8b6b7f8d36a21b9deb325b0b2c061196ecf0e12897c8de5abc369bcf862550ab64e4a9b8485b763fd9cc9bd2df044cc2a3fc697b4a67e29d8353fca43deb7b433eec8cf15d26bdc92df3f71c3fbab99ef514d19dae024a801bc2ab1a7abfe904b5dc9a2616c84dbcd46493351f11f25a8c29e0056c0557a1724b5f3e418455bb05b9d8efd7275634ed4d9a0abcabc5bf2a3692b1aa8507f4a5ca72db1dbeda500a3ef028d8093aa713e209e5fd7c695675454a68ab0d5b1e5869d500db412562922f1c8474fd3428eaffbe179fb66b78b886f3e6590c914b13860b5ebe1016827007271bc6cae5bcdd729736af01edbb3fb0aa8ca4dd63a3acce03c05d367b0137e774f47320ed4853e4731137f00d9b387f11ab60a68c76627bf348ef3adcb21e4550dfe276c143a7a89706d9e4a06dc94b9e0ca7af62cb4ba9711b01b7a4149c43fcf30db18339e024466ca0af5e89150da5afa32c06c61835285e0fb0173092e02fc23c9b603ff4e0c29cf0f1eeac929e6ac7d8689e2ec80df3de9d83693b31163148f7c3f951699ef7a60899d5e0241fe67d43950ab4010c1cc8aab0df8e802a8f5a3e9ffd1a4965272b3d3a34f90cef57f00a813283e75934b77304e3963ae79e59aabc09b06ebdcfc26df12c125db093854583d27dc44c5a6e65efaca7c99e0ab384e4b193b5530caf50cbed0bab51c72ac8eaa7ed09365d860673b31610441ae999e088dcef8d69bf1932c3982fc8d52b056df5717df080e5cac7799f37c2680bab493b327d151afc5d43fa4e0ca3444fedbb11b2acb2218aa35c2275a710c4ca8319930a1b896ccac0862d918a6dedbc1cd39179fc4d6b5bd0d3c8054e1c422d19ccce50c947069c1a0d3f9569fc4452e9a18e899b568f8a0bac6cb2d118d8b8fd75363ffdd243aa72898eebbed1b5872ed3d4170d469f533542dbc5f5dd7882421951e8a802bc0bf9e4437d1292127205ae1c53e327ccf06efb5207c7fafed9273b01b13e1006e05cf629396b8129d0ec2e522110cda6c515d2df3a14ad33aad535fb1723bcd56d3cfeaa3d94581258321f48c9e1a081ff3716c55007fd56438c4c7e1912ea8150a08b78234833d9571e644462834cce9f10341f5563affa38511ac6ab10c481600a07b7ab2af29be3b30902e4a0966ae0b24e2c1ced9f4ef9cf40119909798293d73c80d9d850d5ea7a8943a88abb94470324013e06064cf31bfe44e816e86a987ca298b922a921e78c487c46d26367cb6e565b2c1cd77382e58b6af690e5ba7d8925eff6fea4e73ce92cbb1d11b82eab96b732bb19bb95bc61029f4c95a8c82b97373a328cdc3ba661407c22668fefd8830e862b666b4f0f3cd63933504985914b03f55bbfc143036f62797a79ce738a93dfffc34c83412d5041cfb739acb8c883bdf01cb6348d4e37f033bf8d82559f3eaf9189740536f01a4fa3c0205aaf19e893cd0eb45c7cb69b6793539592663a22371c9baf26ed0c36e8ad8766e67cbb0c64263c41a3aaeceb47d5d7b916e241c8930be4d2740ef51b450a44b5611a2afe304440dd61f6d44c0f9193bf0aaa437351ae0d8092117676a7083fb78a938094c0074bcf90f07b1d24550c3593b5f2e3646ff1c0e67277aadbe9975a0338792ed93573321bc7aee4cb7d0a60f05cfc770caa580b5f4817cbcd1df0bebc53dbf2303f9ce4160ac7891c1e97385b8fce8e9da57be1dfcab0be677682ff5f0c0e7b966eae835f6b22a9888b745bdede0c6c7c97c2915273cf305ed3584d948a0fa0380d78f0c90be144ba234979a73e53b2307a9c2a645181e4a5404c991be02d7cd6e8ff80bd8d2673d4276c6933d0f531c3305c5d8946ec18b14456390880b8892f1ef9d2343b8dbbf50284b75584a3fb087b853ba09f572958b680ffb849e19c744ae7e7772f85303a4c4310f3da60d5d1ccf3feec964762edd34f4bfcac776aa6da3e219c3e826331c3a8eeca0e82f31cf3de5b44a4a771eff91f4f636a145187af76738be4438cd4713be370e65e3f95b2a168159c5062d510537efebaec25f10f0b1c71205a59f03dca48f0f44b87cd3cab898075de0d99039a7972e158c5449d0cbbf71eb248da2bcf9e2b45155bf71950c882f8abb9fd504ecfb789c7108526089c3b6911d9199d19f7cdd16d5aa6a6b8bd5be8cf2bed03c6f0b2d038184a41372df8732b584ba623a3e4864bc1ddb7e3cca1ab20541de411f9612787b8bbda70963c1251f7a1a874f0684aacf56fbe2bd467891676098cff20eb46d043e00346861280a542b3df38b986979eb19906ce44bb2ba27ac141be0484f2f114066c03aeef3e4ed01f32f0753b231d43134659c743c164e10fb781513326226f4102dea169f6bc972730f502357b2ed038b437d6b997469aada906d8861b7548d5828d17c2e2dde106d8fd41d6fb339c90ec8c2d92b2d25485b58eb53227d7021cbe53c938b212abe0ceb4b0386d576dde95fc9b029fb2edbe78c2bb47eb41f4a03aa9ee45fb95f746ecc2e25d4990ffb72b53058be40d65c31616cf9d960dfeb90e33ec5fb7e7dbd85ceaebd26e5fdb2102d084bb6d06b41615f10e243f02cc351cbf122071bef8ef74566a093d67591848175af8fdf4a923b3342431733cb9f8c78a72d011c61c852d738de3b05043701024b48e9b7a3e19d31a3b57d142a76888a26d7b08ad61b9bb4488ca37ef4e908483c5a961326f769ef368539d5fbf154d89c38618ad798f06e2d578fbf021400539aa3c0a14c8c99ed51862220728d110922012655580f9437ad229f40b8137be5e223d04dd6340dc89fe53b856298f7bf1a0d55e34a03770aa65142731095f1b2763011c0b99f134640dac608b27eeb4ceea0ce2188167132323a75054df653cb992a596f6f1381a79f9f727b525efa4911c9f11d20d3373ebd760aa7dd9d78fdffec5e5f4d20e928fe16e109afd5a9435d8f814ab3c5367a3143178e079b14429194a7f528d8bda4e7100e7b469c03de74fe3d62fc4266a0a7261328941468aae162176ce5f891032d83c3af573eda3ad66f962e908012eba3a795d0ce9491a179c52073e414cd0432083c5a9359ac9c5057813cc32d3ed0ace714ea0498c7213ea95643278db2173a38083ef19725ab409287da76da06563ee049179ecf995f85cbc262a9a47daaf2129baccf8c2a3c2d8a36a24e1cf50bc7beea10e0e9192857807674677885b3acc29d822da40920f7cb26d31124b03980b66871f5dd4f7b0e886d22d0743f6c0a957ae2096028e0376d24545728ae06e141d047836405ef4341798cf9fc137c10c18edcdc63b0c392225d4f619e713a582a1644b932960982c57711ec93a305302908e02514a8a239cda8e01613455e9dfbcf7ef98c25f067aa8dcdc20c6e0b4bfbd2a2c47ba9754a223ce1e0dcee3fe8c2e26c911f0e41ef46adefe5d1d0303592402bbbd8f0502e4ff95a49865ee3413cc9f911ba72141ac6a134b8ff3ae27086e98634d6906146758c9f8c044e6dc16d53c40851298e02a5e2bf2b9be35a75232887923003bf7e63a5b424b208c9d06260e06793e11656e5b3dcb82c852ad13331e88f4b499e0bea169435860fc64e2d72910ae4089db869d74c141ff9190d700ca02ee653972bd047f5c34e7115af3543cae9dd78fce1460968902687a62187a98f6cf91d0a418d3cbd441cb384a97c6c427fb9669a3fca13966cf6896b4f46517a8fc9e426c29a0e04bebb2767e274b7175c8f935ba05757e601f880405a4bfd27e57741ff770ebce24ef77f38466d1f089692432bc0cd58ede15e62feaadf9c70060e42f295eae6c7897930e791eb4f892087ecb28791b753d200760f286c6e3125690fc100e1d2adabe88e271c261fc733f1a66fdfe629c8382ba7c03c7ec54aa560e0a03defce019f0f4fa650c4acfe7e4a5d769c3f9ff60c234e3347b78a732397061ca62c18f3250e6bcd49e626e4439a9112263e84b52c83024f8bcf7adf932701f264c90fe4356f10a9f31098efc035ea4df333c5f17431d7e0180c2f65f543667c1c733e2933ba8e30cfd15020cc3030a26eb9d57309c15a5c5b7d5ed106530e131e6bccce2b6f273338ddfafee955966e3684c1176ce552b6ab54ec4f377129eabe0bcb7c7194352513419cdefa2d4981867a3dc2707cf1fb782432372e381ff6d3742082112b9b4b27b0754095909bf0a95930a68d6a8e8fa5301554015500554067b7a8aa23fdbfea35036ac80ea4f0584dd6bb51b15ec2936ee2b2cfb570d5dd8b3ba830566b5fa7aaca2b39a1b0fb96dfeea0ceec598621189b6b576f40aa8d5de5b7baf1622fe409bf8e8736f3c65da6a9f2994881967ffc5d3e95e8c492458eb4976987665c76e662f6b2f7b4df7ac642492141448ca90f1b2d75a6b2d0a756fafcd326b7ffe5dfc7d3f5e3b76e52a549bc07eb96f8a65f54773576bfafabdaf4dc88ebe27e53d2baf3fb366458ff4d473e529377f3f6e56444fd1dfa608cbf850c3a11d739ba637ed1a76a74092051e9af9dc6fa250f79ba89dfd6aee72770631213b4a4d50ae6355662f7b3f9998413e3ef5046d86664dfd9933f4f7620efb95690ebbaefeaef9b0034bf5a70ac9cec7c7c7c7c7c76706d15b9ba8424c5c33c8c787deeb3763114e7be9295406284356015654fdd96107992449fda93f523e99a87b312691fe899a286a42e1affe7c55f4429e6447a94976f4ab3f9b6eec9a706ef75ca5552d7976a00d570fb710b4e1aadc90f3f1913388091feedff499414cd4b89cbb3e51b2cbd7a1ec2efd71d7bf6914386e977f137551d38422bb298e6cb8a18d1c2d67c92f276596af64d261b45c25a7dc25af9ccb2c6fc94082a4bce52a27651c180fb2f296bf641cd283b0bc45e7a45ce5a40c61e4e8ad64e86132e332f45c72f46c8e5b25af3ce52a79e529b9042b3ae52aaf31a79623e59a8ae570d05dadc66ace9bd3341c110a29a048e18518a048b1643bd9f597895d7f29b1e3be6240b2e1be8edd8c42c15c0f73d7efaaf530b77c024b5af2c012fd858255fef2967332c80c78fe9b281fd3a63fbd1cc322cb61ee92554eca2d4fc9a4afe494c36420a4a71c46c6e11ea4e5300eb51b168df3f2202a877192061224e530744eca57bed2236e7bab49007a29e732e92d19c65fb2cb5532cb6b4c961c3d970c3d1b3d181248f98ad6617911951c2945547e6bf505a202514ffa39d1bf08f49180d07ce044d85972b705ceb48e9e94c39fbde9ec2a79080d2f458b6045eb4c731990ec826c7b692ebb21b7d51cca09ca679a64d0a6f7020a26a67082551b2b311cb13756f666328968d3b2d1636ad6c82458b469594ccd197aecbab59b35d510a66d22fc8a46a0941c4f7386aa5cfd91aaa1965bacbfaea53bcb492b24ac82339d92af785d4040a79305514e825079ca6bfe71a3728f69362c87d1c7d3f50b746938ae5f9ac37c907037a29cc088c1b9d9d7aab91bf5f63e546d75fc81257a217b0896e865928b6f4d520ddd5b0da5be6a285563cac6d4a6a75bc0f109b4997b0808080868d39edd039ad386883fd0063b7d3cc5533cc513167dbb02b0e6449b0e624625042cd10f01511a44f5f01997feeec5557f2492d5df5f0ded199b9eda29a0487b6fd645d3e91630ac66e4fc988076367d3ded6a68ced01ea480220c48ea0996e8691970fd570d6dfaa8dd43cd9ecace6a0eca8a09d964105a601db49118d2d9c93fce7c4aa5d53d56cf7d15239d5508c391289440e10fc3cad25a29ad6865754fcae3e855af9048f330c68a524aa925a9bcee2545c71b66619a156cf54a2557aad17b528e674d8a9e1a6bd2a5b37f9995f2d14d8af6d1d46cd8ef47865d9ab3af9abbac5bb6a230bd0296558cd51570fcac2a57c9aa3a46ab48a58c1db4a1bf17cfd813c66a46a53b5892ef6049089f3e0e07ddf295aef40765dfb021133038b9d59cb594528a0406253627a53f76bc502401299d5c885a477ddc2e66e5eb178b5af6ebde5bf697961dcb6ebd925b867286026db8a13c00ddb5aad66ffd77a69bb3b5d65a6bbdf76a4d77b5d5fc07e6e3c57507ab5a87e8d5b23276ab4149e3167f5dd3dbad8c719be6a216a1901751ec6c4dcbd7f5ed35eb10bd7e4276b438eb40c843d41f0e90203a10f2506474fc1a13e786e83564ccd57186de280fa1e1417980799b79cc2d12bd861469ee868d2d73f15acc3217ef31fdd1cc4519638c52bb616fe9b034673d9eea787d805b8707e8e3eba3fe003dad6e8637794d9690685dcbbaf75a362c21f1d6a53db86e6130fe52467581e1b421133098b6003664f20528f6154202062f3636b3177aa8d1bba746ab86e37abd6c6a7453042580b051a244e1625b1be30aec66560f52cadb5b59bb51d94c5fbd20f5bf7acc66eb424a2776fd62b7d9aab799c3ae6bce7bac667bcc4220ec2bb4b4cd9c8491833b6a372a10571731b70e79ae7e434b5227dcd73933843c62ac87b7740f56afcfaaaaae6a0bcee22c8d83de6336d743fa9b635481eda10dcbfa98fb46ccc989f534f75cbfb9073b9c3598eeae97185560b8e90fe40b363d13287430119491d69c37c6b905a157077fd861d6fa757b870edeee76d569aa2ac6aeb66db1fb98d8e3766b375d7dcc0fcbb11ddb32ce76abbfaa7dcc2d6d6896b5dbb669204a6e46171d47c94d1d6991c6d95e6bcea445b7fbeb77fe9b8fffacb58af731f7e4748f88ab3ddba5a6dd9ca94eaa2aaa6b5555d583e8341f228f08b30feb5c3d1870fc175fc12dfa36b51b913dfd66abd570c0d79038e8ad69511cda0f21dbced72c94b2028c524a29d57ee5efeeeb5acedf0f1df53ee6572fb58b8e651c21970e1f19629717691ced97fe300dedc51bbbbe652334bccd080d4fdbb40813691c0dfecaf237c37d33dc9ad5dc8d69c939051796c04435574a6bf7c3fc3aaebaf4c17e6aaed2300aac63daeb4e76520664b28527b6fc8dfce1b45a2b69855353ab93f2dda69eb4babb1ddc90b3ffba6d350efac30eb293b65a4bef63ee6ae3ae66cfd540ee0ff14a5c46e665fca951487634343443324a947422812450cf269dc80e68d66c5a02d1d0dc48a5c03cb3867a53c620a08d4c62cb3d4f336b24cf49140bf85e8cab80e1fe2ca03d63c86ec62ad6fb98f16a1ad9cd68750c2ee07af818b29be7a8eed1deb39d66d66cfa6292b55dbbd9b4bda65f59ebf5305737fb989bd21b567396aee7e0fcbd189348ffba38244fd0660650c6957247be2062216bf08c43524675644fa903a10c0c2291f2270ac9aea2b30bda899a0f735fee4621d9cd47142ccdefc86efaec2903c28901d8cd1c373208589aaf32cdac89e18434a702f6fcac1162cecca3ee109ef3940a1cf7471f77049a35347366fe624c7afcd9d3669a86d2c426a41cba648acf4f1676f61787648e94411f535930491dfa0c8b16fdadf5d7abae4054bb51ed0e7655657da40c025135a7f294575cbc32a7a271d09d825579478e1fc7df2eb31a927e0163213bfa1e969e96b7e81f73863e3b366bb4dfbb4377b326f2e0ee07a0888a3cb366455ffabb2afac3dba6e88fb4adae78e817b00edd48bbd7bdee6874698aa63c107fecb55d5be6c15537f7c08c3ef24276f5a94e0beca36eeddf7d722fc6b0d11d613c225701c9ae621845cd1a9b4a9166f5a92a95b5eb68958215959a4f48ccce1136e9a842919d95158a4976f57502c98aaa2aa96fcaa6bedb1d58aaffee93542a954ad1cc1834bb5ecaeddab6eb7afdfde898fd4dc269acb2ae532f64b75527d9d514ce150f2cdd2416e83eb9494649aeadf44db2dd78ab3bc2acc4ec29654f2999c9cfa62cca3ab140a99b64df24b3867af577497691a85e4fab4f129b52209b82f9cb0dcc8b9695957256d87d427648eccde669965cec7aab45223b49ed0f2c559fea537daacf2b9f5d6f29d02948ce2ae8ab28496765e5317cd26e543675929dca312a68c76b28a0d3bebebd0ca67d5d43a536f60d9564e7b02113540ecae7c915aabf41778a5da1d8f5e5658a6e065e0e23446ed6251ba1e1b91cc6080d0f888b86d1384094dc70877139104ebbe09798b96c364623cdddb8aef24be5f65a6b7d6457b50dc7b961b729ccbae82cffee93598f2f09e840f5f74917b0b6f2d108e31ba3510d89c1cb4a093f33766a4729fa13b247bf328f3c351ba3c33829a518768f240abc1d7a181d8db01136ca5f8523bec2b0975779ead0e163e294e39691cbb42e76e2cf9c7239f2420a8a21d99279e00c9f92b50eedf11a8e782d5a1f8b644e7b9a23eb6391c8aedad316587416fdade8afd2e72427b7d3bcdd9ea48c89c4fa4819394615b83ab4412b6bb3487a5e3e730fcced69d6c0e8fb045770d3a11dbbe886a68b881bc370166448f45e0e7353f45e8ad0f05e6e8a1e4c8db9637f221e731e1b652fa2d3acb240a389adedba4155923baa3e179330adaffd0164c67c8c2c5ef40f73a6c6400386def45e0ea3e19ca9d302592716283567eaefc5d6962f16f8ab92dc27a97a31e9b69a767d35592774565535a7ee799174565900a5eeacae8a92fabb17e3a93f12a9a282b834506f59236c34c2b0db5f417784d98b9e6e8645244c4f348b21ae85286a054eb995795e08cdc6ac1f14b231af666392e6615c6a52e6e6bffba4cadcbc7d45d2dc3cdd302e61dc27445098efc2cc976c03e986bfdc44c3b3e19c0bc65172c3fde538d033d1f05c7e832e123d1b34cecb395d247a2e1ac264e8510993a1f7422f690f0c8cb6402dfabb2cda5a15fd7d03018db00b3567eaef7731c9daaa208a84fac8ee243bfa0945a2e80f2cd11d0b64514fee9015f8b3a9af4a629d5894ec2c90eceaef134f64b7316c0896eacb6b487bbad6daa92d904c722d9e95cfb5f046ba7e7d681af0674fbbfe3ea9bf92ea6edbd4ac99d7d2dfc5bf36354d5fb73f9bdaf53425a1902919e4844e1d5140553673761c82252b70f5429e52afee81194db21b42767594e51e8d606450f361fb1de52feed1310cc2689c97db5b5a0fd531d1a196e3e51897a1f7925d8ec3b9681ca8bf0ad25b9755fef04bc65172f3a2e406e62f9f33f52f1a0746e328b981b90dc7c15172f3729843cf068d03a3715e5eb94cafb2b80c3d320ced984d33dc2f197a51f321eeeb3a46cfe1a26bc8aae1881fbdc6b4197e94e1c69a28e72db7c848e5dc240f2cd55de9b8034b32890f3d5d81bf789a26940cdab5d6d3215c3f736450268364900cba32c8fa259fc42d936417c3eee8f7d23efa75c9934a5923edd72d0d88ebd9e3101010101086ddf8134ff75691e8c6a6bfedf8d8e30eb4e1b8fa2166cd7d7271ad8f995239d2f789ec6a7587f47d4276f537b4ebd88e8936cdddd08e65fa03b7fe0e55796357c5d91b95b454643ce20bd8bd1893483ffcec9833f2f752716467d766961dcbf28eec437652a39a0d4dd3ae69dad47c70da3f3884658ed34e37fe8677e450b94a36b17c45537991966b2a197a2d59c97696ac84078dfc69e7f077e8d0b4286722e8fee0907643bb8e3e6c6c1adb214fa7d3b6690ebffe07d949edd0db8e65b76d7a45086fdf32cde12dfa6c190258cc76dc3b147fa871af99e90fa2b6ca658a95fd98fe4818c37852c970ce3c66526a9ba6e10d6b4ebb48f7ac603a2239cd9a155d434aa987b6dcf1e36724b7175ceb5a5146a9a3badcd2decab2aaca56f656d60cec6abd1159af341bf5566b69bdf66af49895458d56dfcc969b12ae8023ddb40cdb327d5994ab959cf33aaa6301cb8ee65b2b3f65ede69c73ce39ab7b3becd7ed0d76557a6bb5b6b2d2b24194f69bb66971661db4d171289a35233d03d348ef2591b07f336650ed66cbae5999b5aaec63e2b899b3acd78a6a5575c9ac0913de0afcb84376f337dfc86e524b297c62e9e9f6ab45fac79c992791b6ae4b492a638c514a29a515f8ebf68f27f007534feec538ea1c73ce099f88ac6fd7b296b59fd984d10afc759dd4328c5e017ff049eac725f56ce76467e9ef5e4ce9b108699c5ba5238fa686317821062fac106da22dc62a4a2be8135846d16605d60515ced0b93819c3129d087b8c31c618a3fc84104248c980e92b2ca59452caecca7e6597bcae4bce39e79c7366bfb22bcbe6e5a7756ea329a3143d92d6a594f6dc684be1467a9b96d394524a29a534464ab36b5a1633ddc15285dd7d3776e70cf60ac3b6675bb63d3bb755d831ad8bbb833658cb5dbd833622cd5d97bbe69edb24a594721b166d58d35dd56f9aca0e0a898a20b4ad6318bc2085198410c24bd34c57fae8132316af48638cb15e19fcbd97e6aee883699abb4658b4dd4aef28eba0971b422cdaae8e3e97cc22d528a5f4906a2669920253cf925492e46396496467bde6ec57765d5aa669eeba9626d959bfb6577d4476d67b56dec372699a352c7a8445f85ff461f9cad46e58b6af5c36b69b2f91e8dca5dcbdae28046d745c972bdaa7d64aa310b4f1b9a64cb48934b7fdd210962ea86bedae2f602c73d885fdbab00ed3164e6b0fadad21a5e9624c6bd9b1532eab34173f2f7b989df68c84e10b5eddaee085e1f8e8336b562eca22bc54748a1ee98f84f5a6e1ac28b5feedb0e967acd37778ce58a7940e3167acdfef624d7f38d3d6b1eb169cd1753f8984311d72ff18df2b97c09205846d7d8859234d73c6fabd185b264bfa5014ee6009fe93a66d5dfacc9a28147de68c752be729d21046499f7b312691be5ba76ac0f1d0929894a99d152b382308d951934c3265904c9992c8a8ae801dad864cb0e1859835f4a2f01009a6363ced68eaba9f44c23875ef0cfc43023ac17812921dad86a40c3a24bb2ba00c7a05ec68dda9864eb386a6e815f5f4743ae9a8a8fd934818df8b8225fa9abf5a864d4f53a9542ab5e90e10cf2e5540b3a69e2a1e9f2f2125c13c154fc553f15457d0612ff7477f9ec05f3c65d590dc8915aa72520155403d2a980e461c91441cc3175a7c51450f3028236945d305923dda9009174b6ca851013be0874340ca985aa693dd6b38e0872f82be7862fb40617f344ac0d68f10be38c21230b621932f7e80ab26f0002f910320f028518321c4e0072c38c2111e7c6164075f9420076b60426ac9154ea842076578c2143d000312b8d0040b3e7882832818c10944c015932470c544133e415822c99222289184244c24a1848709929ed3ae7ed6f082fd7d3470ceb9869d3de79c0e80f089858435e4cc3fc14e4420e90423f697f78d09804d18314fafe198afaa4f1d1fe3c660dd202cc5cbd4bdf7de7ba961092f76ba78a20b2773ca39b718751505ed06bd0d0b966a7583d2dbfb6a891468689cd000c90055404040342a48c001155f3481841d308881658a7c55810b23e0200c4260f8c213522001230726bc30221405118c208430e01baa607204164888c1132aa2980f6802062a6431841b6cc1074271093338f92491451315f08041cb60a17e200c32e04292296e40862f7c81a782c111575081123c39e0818f179018dd3861e40c4610c30e7e10032878381de480480c524a2083145ae882c6851cb0c063e1138828d1f3852730a18228b690054106378822083a3c98422a08091b8e78826405413b489e98420b487c0728bcd00523b6f8c1132fc8420c16ac2770e840144cc4c008330445b9c1155a60b68084284e40848b256ab0020f4c0d967082d38e125cc8c112aa8084a80535d002111748d104912c3c41826e4c8c50049e9e2a6cc1870a37e0d04511d0a08525967003294c2105fefc20b18209162831540429bc2ce00a63f0b1424808573471e272052bac4085263840411986100524ee01b830d540075218b1c1129c90354988e0831f90210a1f04416185460ba84051f18411ca8003201e9290223f47fc4028e7082ba878021258b58012281081c7065c28018913a0c053abad55adb5d6ea04ae15a276bc7802055468f1059326400109242a1b543690490da54c37e022874a1e2e7468e4e1c2542b1e2e8ee04205f5d2005f1b32d9e28b196ca1c516555c99ff32dd165ad8c209244e37a834a8b668c1dde204778b125c2dbab85a6841613664a20517b478f2846422d2c2c7aa56c00212c905a4aa05352a19e00fef386b62ac6250d9aaaa5690050fb2d001165a24c9e2e794c569dbc9426765676865078b275b6302290058e0411648342a50810a68b040820e1642b83a58f0c0d2c12b242c90c42b8ea421890a05151629a84c5865432657745119b9820a960d995c81852b9c604224328109d6e600e2152630c10281c510aa60841954c0459326964077606da583ad8d4c60828d4d8670656107d914ae40b2adb5b61a52f5542590a94a4013854691b1020b2b8eac210d48cc341c4173d2408359e58836649206146cbb219334e854465ca8d9a821a95529ad5476908487bcd8d5e9c528a593524a6f5ff5ca29476ffdd2d36d5f6d8eeda6eca2bbbd8876d1a6a43ecbf2f49c3dd64135ee81de62d7be5ecdd91a05a687de3763cf5aa58caa8a247cdce159732fc6959db2883a2f233028f3cd9f3d9fe3743a9de4cfa9b2eabdb556b5b2eabd17eb32cddf0f1ddee52231ef84e8741862d398eb7093cc3bdddd24731d74bd325949fdede663f2101a1e901c0ebd4e4e1f24b29b3c684c93ece634cd2372684e1f12dd4176d8d5c4cf4f133f5597e922eac658beb2ab2779a2a77a4d124aada8aa56a87ab584829a35323a888bbad08042c3112ff6f50bc596a740680842039221d3de3664828614bcf52cd35fb7a1ec89f9cd367f3bc43c26cf9d6b21ed02c339334f9666e3da4a33cc341bd7a222949cd9b242ba5d762d2b5372c80b89454c4c8673467b968198cbc8681c2192bb216f5d6ad98b4b978dd0f0bacb18a1e101e9b44c8c06a2e44687cb7407a283eeb2c764e8b99cbba13fecd73be892b9c8498dded257c4b018296334aca49523e6584cd641bb8cc6d15bb631b9bb921b99c7c4681c199977319739f46aa77164344e4c8c761d74f008b2adef4c8718eb2e9947e4e8bf08241f84f52dd38892ddbc8efbebda8dfb4bcf6b4076b30a285bfe5efb2f0ec99e18193d4f325697a3362d02cd733036dc80ba246ad6c893fe968fc3afcf1b6c70913e525a526afdddac3f7c793a0efab4ddc8e8188e47dc56661d51fba08f5ac7bd3c17bb799ab9287764372f654fcc7b6422d0bd417fd706fde1ece274ec0203e091e78af088f4e2f271f56a37e8e5f78f94d144246916189aa545b3e4c89979162de4e32e4b2682ee954c049dc7b20e9a65f1be86fc8123c4d480ca4cd1a7592387e6cc9c3c3367cfa3a0cc23b29b7f89510596b7b7caf75093f7f76a3820862dec5e6b22b97494414d04694656d59c8cd5add6d65ad5ea563bdab4ebe7475a53bb5b077dd41c00f2254f2363c88e46522f30d63d396811c44091325031d9d26c58328fb9918999d66b45abdbdb6cc68650a43f12d49a9652fecc9a1a254aa3e804a2571d88047ff08c9f79fa993e13c93ccdd344324ff3344f529e24cf9542b28918e54f8d55fec89cc6bcd2b209f9336b64b44491244afec4e89f3de769cfcfd3aca19edc53a22c9c3f970da002833219247d9fa771875a3b5b6dd7a351f9a87790ddd43496ba8a24b6cb864caaf8d93f8068d56364a1497346d2d71a33ab34877c0d595992a2a0cad93b6738c3926d5f67cea6bf1d4d8e207ee4c88ee60a76bbfa84cf5f574d1d75a2508eece8ac73d699ab7b49742477e449f22481e7ae945bf5a6fca668eeba9ab3b880b16bbf9eb1a47ce531257f3fb666e57a5d5ccd32770f6f6b54b9d77a8d592bc4c7a266c945a8c702b5ecb2a65c62ad2b45df1a81aa7b4c0af0586e75341d678bbebd86c4d92c587f42f6a6f1a5e8524a11e47050953a5251812a106a186b14e2a28e532c59b26489f594c7a768bbc4ca3763514769127d1ee8b01c3520a2ca8d425128a2b2dc9b96f988b4cdc72788091f1f26644747d867f38931eacf03ddae8f3ab2a3a62a70a539d1b464d6c49d14aebef2f98f66c725f1057127eec417ec9076e20e95578e9481377dd491324c2b39084ef456bef22038d15b79109c20deca71a2c7a283b09c45e308f156aa9c0d83368de77e680006c1200d04b104062d81414b826050c511758cd3cc1a1a1a5392282484420dc5548e3461d2477654066db944765426a1d6d26baf491e119a33f4f70a0909090951fa6bfffd1eca4e2e914bc88e7e1405ae879eb59a0a617baa3f22e2aeba88baaf279132201342b3e65e8c492421edc3ee6a098de88afa93419b3ee6a0d6d2144bc7a099352d5a2e21d14bd3912bc65787de77f5ebab33e44081028a930d37dc59ee6131994c264a973c911d954173865ee8a2f0d0a634b5e9e5920854e77a58e89239437faf5c72a9a5e5921c43a2c7cd2904cb032051ab431c74437b688653b78310317eb8a99fc1848ad4aeb4cec898ec6fa5ea00b56d0e82367611d0c6ae99c167636648b2b18ba030512b144bec0a056ad75a4fb7f6df1f3f443bb6fd356f6b4c8d07cec6da8da9cdcb860f249a2684251ba1e1e90c69b9ca87e8b4682242bc96ab9c0587e540545af4eded2fcdc6559d85c3aeebfaa0f631b7d59c3dfc2fcd59284a9821b5a3064475abb92b6a36a76425561371c37218bf51794bca55cec261578b80e85673184bcb615c96afe0c06861b9251d7a157aa41cc4e62f3b84f873b254a263af5a047256c938384a6e58de7292ca611cce1a181aa745e3b0a8dcae5c765be1f095b9d1a30aa6b91bd8ab9116017c43a4bfeada31cd6d974e813b0aacc34229e38ac065690ebbb48f28bb7b592bcf1983a6db010e6552e30283329f95b3eb291045c9510669c15aa19a02fd698204d504494e2d528d60bb6193238cb0f11068c46f72c40fea2fd3e1b061932376f6b66193234ab0bfd31ca925688224755523ea10970d9bd06068d74068e30d9bd4606857c7d0467e9e88d4573d11219ecc337355e7d0a980108f089d5947bbe832eb5819478817354ebcd41c119c04f0e53390f2794e02dbe56fb6cbed55df609f1a671e3bd43809e06fcf00d69b06825334c4e23fa395ddcad18a315a8fbfb11ead1835901a34f11f8da573fc5807b2e15b17651c211e8e929bd1487355f491b5dd7a06f04796657da471e62da87112d89e3d03dbe819c05a883953892ed2393167ce548f8186eb4044cf3ed240b65f59c651829f69aee25ce73c2de368e7aa26829380e8d733b01d9f9340f6eb37d92f8da3a41e473e7bd537d7b1c699bf1ec4132201d1b3df8874a6810491d79efd66d37167ce549ace91cf0ebdf92feee490c7b21c9fe42894238f50d6893f57d6f9e1c1fec52556f5185b60ab79c0285b473dfce2935d3d461a6625a7e6eae781cc434f041480b386cc80442242bc7b2b47cfca40e42376a17601219e111a9e9cf202aaaea4bee62270d89f90ddc34d007af138f0c713011121de7611444d448897b7478d02d093d89661dea896430703d09bdecfa61a05a0378408fda6712e4dc289b76e455df1a85e896025554463bce2f6789a1a5b8c3922147a22b5633f521ba1e1c5c77ff04976e85d15f62b67a7f93a90ebd0ab596e2be3440fbb968dd0f02800bdf9f9ebf3d0135284a1277272b2f4e6aff94b87887523343c7922963642c39b971a6708173d219e111ade1022f2d68908f188d05b9f1a27ee54374243fed238910787ea5bddd2384a6eac4b8db363ce54b7f43cfdb533b5111a9e67fd8b3c70681e7a968e4b620ef42a111c3d68050f8ef85912af4b2e913b9247eec81db944f200c151621d7a5706821d7a58c4b48e92fa2251c744c3bb2f123deb32673745ef7acc5cd51588de75f9ecd238113567aacbf822d1ab303d2416895ed41168ce005df1d08bff62d0ae6a6ca8e5d021123dd98406506c016c0c484fea2a3567a40996aa4a247ad0fb626a5716889ed4384a6eb0478da3538486276f8a5e3ca687442fde143df92bdf5b1947c9cdf5ab71a277dd82de6565407af55cd539e473c4d79044a207bd18e9e7af1775e4e3e51532e576a4e6c8d49c5b23e00f6fd9e398d65aeb57aeb5f63e48db9e243b79efbd0fd2be1ac20e1e064a29040cca7c7767c393640d6e328326366c328325f6774d4d74b8d850a34864a705fea869d3d324b3461ae151934e09f6773735491947a48c797aba2365c026337882be60d3575be08f26d9940049ee0e11a13d3f0425766943264b28b131296395c558a3b5b5a2536ea83f2979fcd8f635240f6bc37e1e6eb821dcd006c21fd0865e7c6bacebe6cc9979edde0c638c44ba7fcefd62ce0f68236f83fd412e20171bc2d48c29580a0016669259b3a33c913370d70791848eea8668f6374f3b4aea8997932367e0fe66d04c624b1974c3ff788d960116032e0698ee5d98e6d7b639ead44f4d6a8abf152843b43f12fc0f6843a768d34326517e36d47c10edaa66bbe7bee6a8638a2f9033f35636ddbb3a1e913313899c995762cf272175cc893ab233cd99f9b8137364373f852aa9f960a2672b30327b0751f6a04e66c6078302a005fc20660dfe0cd1f6ee8241586b605ece64a4231f69cf8f4493c2f415a60962ce4cb942a2f4da510353cc9822ee96455c1b9e8350c6558130a00c1feae611a3649ff7320ba1010e0ce1811db2f381451d3c6dc40caf10e1daf2904914226c9aaf59054c33698820a060791e2b2d25363d60dc1e3e429b1ea46f8797d0a687cbaf1e2fb70eb9633d609e1dbe429b1e365c3bbc85363d6eb8e81087639b1effe8f017b4e9919f62d3435fe530e62b87d7a04d0f99b31ce6f09643112cc513407ff0d573c81b2cc5cb640d96e26372064bf13a63b0149ff3054bf1c7215f588abf215b588ab72157588a87c9152cc5732f79c252bc4b26651859fba0fb8b169615959411166919665d9b8dfa87cb5fcfc29c45187df8f6995fff62008efd930278f66fee70ed1f2d5df4af1ac0f1bf4a808ffe599aa7fcbb3c5ce59f5580affcbb0c70967f588cb7fccb0e7018ff341927fddb6aeef24f34e32fff3002cefd1bd91ce65f4a026ec33f1505fc867f2b0b380eff5818f0ff6ba1f1fc0f468deb7fa4fd987f2ede65febd34e039fce31c7000fc83b1711d7af4f0eedf0d1bd2c061c3fb907bb861c7dbb061c73b20bf01dc8ef75e76fcae4183012d3b7e012c3b5e010950d9f136293b1e01336a443b5ec6b6e30fa0edf81806c0767c01ae1dcf83b5e36932842502e41d3f80bce34b19c2d20e19c292007200663284a52e330096e475c80b802579006405c0927c0e3901b0242f936d60493e46e719b0249f730d2cc93fcb8025791cf2016049fe861c0396e46dc806c8058025792ef3004bf22f9926130096e4497900b0240f2397f20eb024cf9205004bf22b3900790696e453f228eb9001004bf2a29c032cc96b592626eb9c0f4bf20680d9f0acf9e1fe90b79cd12b6568dbb6dd07696ffabb2eafe54b6527657c725f1a578fb9deca45643c620f52d322058564cde78cbc8c33b5a38e71059e42fbf60898884e110478d9758a30c0cb3e44484e8e8e8986a7bd48f474748a5caf5ea708f6ec758a90bc7b9d22f7aceb14e9bceb3a982e32c3db5e84c6c35e5d66da64bd4d1ff2205f247a9ad6d1d131cdf0b20f995fe478a6cecbae33c47a9193e399485ef621a2d4f5b25f2f237959e7652f32c3cb743767e4e5b19c210ff257d69007792bc7401ee46f96813cc8db9c03e441be6600401ee4abac03e441de00125f42a69c44c0228ccfcf2aa57ccbe7abaaf2790babaa7acae7adf9eb98a5419b1e45dc7d6dd0a64711788ba04d8f2248fbd2441071afeb3e48f310daf4a8ba08d29677e9017511a45d9de5f317daf4b07411a4f90cdaf4b8ba0852862f2d61bce7754c8d8f4453d4a94e1fc4acd1d1d11982c310e6bd7c080d21ce7bb9ce1018a58800bc97174980f7f221337272723c53e5bd6825f37446c11f1ce2b16357af978768472982ee98355348cec4a74c433b4ed4d015f8eef0f1fb1cf2e3b143e6aa0bfcc1211c29e323fd90328aa03b7c5cbc7fbf1d76641eb0440f2313014bf42db9072cd1b3641fb044bf9241004bf42ab90858a24fc9218025fa51fe014bf4388b0096e8457904b044bf6512c012bd9671600996e8b11c0496e86d16024bf42498cbc81abc8301f0079fe4b809420352c6bd1014a22ea4b093bf19c2ce3ac539e302cfc31d7b1e5f7c5b240684c3666117f84ac4025323e9b6481b545628a7a5d81baef9328231e506324805fb831c1efc20d91e45061576228a0be87522cacea44e444141259d88a263e30afe620b2b0ba418ab29d4da85125a85428e0e9a40a16428a2eca8140dd655414b99522300000000000315000030140e07c6c3e1709ea7a2f60114800b80a650745c9708c32089511432c610638801000000c010100021aaaa00001fd0e53dba07f6d3f22eb2502636eefd13fd6939ba98f8def398e8a77d4549a2088fc86281c639610bf21630642883034ccc1cba1622daebb741766f1a6e253feadafd0c0ea4ac8292fff36bc232071840b4148d2d0e3870012d8d0b33ef549142311c28e95cb89df50d922531164f72734dbfb70a7d1dc29b483f63836698da9f172e4ca96122ad9cb830fdc2fd1cc34f4d8e23525180c632c7ce7a0763e78e8a9ed08f2a32503888bf092f47761d893fdefd34b4a0e166b05778e9f724e4ffd0f9b9ba67af4843b149da9a4629cb36abaeac27b961b86b2a9aa59e5196616af0645b85af598fe476c9a7ec0436d3da3c30a69cbf567b04d6f60a4377fe3acb48dc6b9a9edde6e80d3d25773d116be8d2ff0ce4ae282055993411d8a8caf0c2fd0f92ae308c16f74cc08c598275b3b6be30a62656ed2b8e70736235fba9b66324c3537e41d842d7eb80c4cbe972b9e8f84f78e86060003d3b209bb3309cb57f3f9e7f46f8da7c10690bf7fa7f071766aab433e8a7a1a5c42b4b8f0cdc4bcb84c0793bef88a86a2fbcd0f238863afed021a351b8933c7b91bc8281d572cb9d88518b137400872647dcf3edd6ac94c59e0b4443c9fac1aa486d1dd6439404e0439abed91f53793ea81a0c6f4c5a3a338ba224a4186be5a2b98ff6c164a8d2e7d6098b9d5e3df6890974c8eb01d0dbe7822e1bf6c244d9d6d2d64e8efe443fde1f245c4d0e92f142875336d693c487763595367b3ac7458c0821c8c878e299897aeec9f4b08810e4cd5509fd385920579c0b9ecbc73360484d3382883fce768b90ff022dcada0dc5ebf782cad4bca7d017d270d3093393bdebe9baaf7eab9419ffd5efb0cb8a76fca60fcd2d213cb8a564fae2340a41e215c9c4569800b302036bbce61e1c0003378ff86f7aa13958a5b45300117092e2366cdb728a98aac53f38785ff10d847c62d58d5c3a5283101b64c198ccf5af280c16dcc4b241454a730b2b803e429bf8cc1d41f2ba28baf9e666a9a8a9254ba9919900bb09b2ca11554220761893e88f69974cd195a744dc7010ff8de4fe00bdbf4a0259136ae22893cc4b9d1353da41eed5e142fb3bb5157d9984fd7521d474557ada2726544820a18f326cab86d94c7b29d2e3f646b14633db0cee8aff8fc08e04b95f0195d85a8ec87f5f20c12976a8d862be3c4f61f269ad363d7b12a6c1d7ed1e6e75cc20a7db92bde3a0ae3d2249dff951366d5035dac1d8ddb04f33a66c73b0ac48f41a6651bdc1f06c9aa8eefebe4d780514871f3e51d6f412a812d421ec9f465a64b26470c913a118ede82584711d1dbeac2aa1e8b0e8681a4581dff25f56227105db0c52037abe36cd41a57338a53a95037845aed01dccbdfc611c77e9604c1e978f3ee16894b13e0f7b68c43e4fd51169a250b67040dca9503563fd56c7a9c028fffff5d2f4950648d38354d5ef25f02d2af9d99b22902c1cc0f142fef3e17dfe9de70ad341551143196383b680ec129c641a834d31fa36e531ca40ec14472a39b0b87fe8977462f46a242d7b2f23edb810975ca06c04d54bdb5511c14746d996e7ef9f00971f5cd28b859de33b65a90cc49631ea1735dbc193fca2755b4eb94286d1792eea443725474ab25018637c57a9651fec893308114bf543b11d1925f729990a8560aee469cacaca5b3703ddd4b0488c0dbea09aec8b5a310419c89795323bcc174160312706128bab60e4c6649a5e66a3ac8674aec7d49187471ddba2face0595f58a22501a07f5b6ca6c9f11143465f62caab4566e2e417cc25d2b8dcde56ec8076d9985b143ac31eb5e493362bf6b4ebe778c40554b04e2fab08ef46684823fd60dae036970e00d980807adebf25b8adde46c6ee9b28060a95a79f6d92ed526add08f4a21e2a5ed8c5f3ad9fb6613b00718b460a767055de0a28f5e50891a1a56980e67df6af38f28e1525bd097c4b6b24b81932eefb8be799642098aa21b303dc38cd1fc9f1d8c4adddb9d4d1528cb61d8e87518e41e1840237ff185b2bc383e9f89d25a9465e5e40d8342f92e5b13977fe4977e96997973f4a74b3d7f3a7a337fba90f2a73984e14cada4fb030da5bf024ad49f50456187fcc8932d59eb59b7795c40a14b3e862d5967bfc680088697a287323ef35b1bddefb088651e687e942f205ade8d1c8f0f37c197d58d2e3e3628faff7194618aba2f650a824fcb85614f552cbc9a771695e9ee8faacd88ff2c1a133be5d20fcfd9bbbecc36f368d19f2a8b8bce2c5fcb4d0b327122d9cf359c86767e00d7adb1d5e09276802323850b76e94e7b76d39ee08cc15ac35605376dd934077701e099e46f8e41f58af2a65545e23b488c0ce3d85e43c2924896b69a9ca22e384c307c4a389764dc394a5f71af4c4321ed90e1a592b670d2737ffcc4f48877a4595011ec1d1c4a969ab0dc766816301f7fc66b51a486ac9566008b21b1fb8a7544a9524e78e8c7ea5831807e595c3df7388f7f1f55dfb6017dcf50081c4d98abb0f2a7d9d84f0011a8a825e366b7e76f872b76d735df5aa2b1f80d870598d5e599226793ea94186e33113239d1465d36b16068f7597e27e82d4d1a548345632e42385a93488dfabfb1d0fbe8743ce68463f45cb29d6b2fdca4c50c372b4c5aa52dc326fd1c212ed49c906ca216bee3994fbc59cff76a968105371289a6997e5c4a96fdb922da08b0a85b854cf4d51123ed3b8d71bafc46cb96930c4869328370848e4f002f4bafaa17d235ceb866d012ebbe1a0061288e0d1cfa7b9857b0a3154b7a3a21e00e9fbc7fbea9a4bd2927a614794b417ee2cd0e6b76c820edbae64e1ae08ed5e5a180debb9a1e1864bbacd1a903b7a3753c2c20f74605dd5e7d9e76ca4b3022ed88c827144e45452d5d7cd239932c2d3b6267d47af2946c0a710dd2e6acf54555f096970b089b36ab37a29507c408c8a20a2e931d4c18a07a62fc8c88b1fdc4a42297ce778b88488423b843c834be3b4a8da3db685fdf8ff2b4f5ad78acfb7575c4f67be418ed833732e88b868434af11bf866510eba4d27e2d51c15297f60d289a6b1b7ef743ba990a632a2d0863329ce0154475a2c54698f001c046d6c61975e456235ad1605acafcd30287987ce6555a962bb004870a04193d26244c8a08782c8220a3c4996846e70288261ef1d447dd44319c7949090e937e206d2be242bbd0f858159530c4952d3b19fa480d3acb429176516494cfa634ad2903a55e6bd99c7333ad8e49e5d32e777287188e657efbd191907ebebc41c69921ce2344c820c1d960ef5a91fb1de0a82ac22dc66cbdbc8c296e47e5aaa69659c2ea68c12a864646cc0f922e1b9f065b4492689db95c29cff39b7db05d4c2009893710895d80f722be205bc499cdf34a4623d58722815673bffe1e51aef9a5b7a9ecdc549b8aa0ddf6a7b2b585db3224151a1c953de7abccd1cb08527463b529aff0b1ca106633977efd3a12f7fcdffb3390eecadd1ff04c688ad8d436a1e45f91179d151bfaa7404370474b79f2d54abd69a08c2e6a1db5a360fb47797f5491b7f868eadae870711568de6bad35cfc40bf7ba440b80155a4755a29fef549490db1d65fb6591876138a4a630a949ccfbd06ce422f0a9733de6d8ad0703903e8fd3f8ca0902ce0b07791986287f5fa73e5e091bf79b8a4239cf7d4c2bb81403c6110be46f5eb52bec593f2ba3cd66603ce0cb1047e394eac90d14dc181d30939e86ac0a974a712cf112a324c151dc643e14f4eab68d0e5ee333a1a3a01bbf6e3660ebce88c529be0b41720565a38ca6aa942d98603a64bad36e46b8635adca738f402d71656ee38be89d7d22d0f9dfddbb111c5632533fcabd5856e1c3db01341bc8d8c2bcbc571e5dc2c178e8b7361b938ee9c8be5c671e75c2c778e9b7361b9386e9c9be5ca7171ae2c37c7857367b9386e9c9be5c6819b31ff889167907ac29a162ef5dffb8186a279f8896f8c9fbed00785d70e7611c79f90de46798107103bb97d8cf0ffbb6bdff367dcce67e70dd6439a25a26205bc86ab037cd82f923935602ba297f53ba037cca67e27d0eae6903892257f1fb4a3b7f9370e7a3c82f7895f89e5c307dc97d69d76f923552a618bba7564b11a3ef8806a9076ccc00d403ca06eb986a4eb6b4af455fedb905ca560561051e94de4b151e33e4335f0dddee3e94435e31a017afaa7aa0a7f72f2009edd9f5288a628877c50565ec74550cd18e05e8ff9a404865f4c228738a023fd1cf48ac8c6f55ba506e0eef40421ab5992e69637d7002470bf96b4347f1f067d51fa7b54146690964d03384660824b3123ebf0b061cb285d48ab6edba41643ef7d867031af3a950fdff306a3a25eb5981dbbf41b1c93e9e7b66d756976e8de37088b76aae36c389c760f769cea8d6dcc45cdcd9b55501e029807c7e822289d3b93d9df65059e1c700b4d93d5c2591c75eb3436cfc2f1a2d239c518fd7b0956209bf5dcf661f965765e09e02a6764b98130d5117d4160341779b5894931d257398491598f8a0b710d9b31daa93224a8a8182d79e848d1284e2262544e7a252dbfc120125ed6753daf2081e43a4b5daf47f53d108819716f47fa5623bfed1030ddd78b24d4a46a9c2f8885a727e38a1c9e305145e4e05b89f0d5a7e772e24ab2b0834ebb8513b434efb2b0c3b7c3984330a9c3fae68f5a2307d4bd850ad055bad484db691b500ef8c2213c08e158c939a05dc1b58f9aa3e1a660b17cc6609d03542b48549da3a219fff42644e1d410730ede30be92c958d05d5a160e2ed55721fb88022d3e0972bed3812a38ddc1d511dc99c48b90d3610f50f97deee04d34dd14ba05b7284d22ee12b803bde081fb59812d2d16149f48ec6c00fd8586514fadd6bcf109dcdd24adeb2d2ae663eb9338488e9c4c73b3572a45322112d200113a6774104531b6ca09a737f4a8dea2c156198b7297948ca488e98cee2085d88c5b2a2d8956ac139d5bb4621357494907cd49b12a5a7c35a78aa5b1e4e319172f63c558693f9e22314956642cf17cc6c4482bcf727a76d20b3e8d870f24c139f4055be80f4c9cb4d244bee74ed2a3d684fb2916937e4556683d9e7131f2ca939f9e9df5fe10ddf080319ce991ca327bd4269c6f4bde35e99c1b97257626d10f92b99f35d938897e96ee361647b613f10f995bc69d93ce6e5cee9c7476e3e6d649673714774e3ae3c66db4774ca20f12f79336279ddf3eac3fe91cb72a4bf44e629f24b9d968427f32fe90de4d255ea70634ed92277493eb88ef99bdfb049afe5597b45d1ab650b0a8170c83415f327ffcef7b1b1c154eb4657274579078c2433f968e73c059f0efb18f286ee5edcfc4df63201b2b6def065036a9a34112959dc8782b7a483a40e407c04a82f04bf8e00f414f4bf9fbed590839f567a0ab31f3087fb31f3440df1524ce8acfc5e346452008a8a67b0534b65941aadf6b4212a8acfff282a11e2c6e360e95aee33f8f8ab32998e304402a6093f9b8ebae70f0ff8f3482d0e85713d699811107f8a734568c49a3015a89b89c8ba4dd264cb3595ac68c9a5060a28841b7bc0b5d18b6f38eb6d2476115e1d3204bd41394f86c5fa58754d2d2906b2a26c359d975058af0377bfa4577d6a7a86e12039ad08815b1bf9e81980f0e2cef36e7406562a983445cda838ea74d408882b12bccca156efbc3e819f3521ded08def13c63d1e46e8e10a4e335bcc28188761faf4f66bbf6abc86704d7b66ce614d108f33c0cdf670adb4eef0ab630c7e532d06cf325d24c286783cb618119accd16c8f036c707de77af38f7cfeab1dfedea86645ce618277685c8ff8c7f42818a9464d3a19bcc555f5b7a15a1ec9b15aa5ed2c5fd7d500b0c2e1047dd4c035b596e4ea7c887ff8f86813f81c45e51844a3a65c6f57f0ef5111d9c987fb743d79215c1cf2c8720089732cfc83c2d02e3f0254c9c1a2c878b8aee4dde4f27c09692e893b132ab36bdffabac3a870967a7713d72a9d3c281cb36249ea8adea8125cf1a1ccff1d44f252bec5579a5442f356c57d7676346b068cd6ee6150252447c96f46be39e0165f2c1e37d4f4a0b9f81d26f8023b93f2a02373b8368f32efb2ac043edbf7a15b340513d495ddcec66b60abdc06091136e3bfbd83e7d56063e9c7950775077523dfcb0c965452fc3a17fdcbe9d88a2222b93cb1e67288bf3c2b1e9b312426ee6833e2814de994cfeb11ed23c54ce96ceb1e4febacf7af34907e7acb54eccd8fd514449c93a3509ad5e8982395616f55ba43e6d57dd089ba9eff105d989dee49f83fc481405bb1e55403888a2b83346831a358f446dbbc15f3fa646d403480919da511f4035a32733f07f546a9eb2fb60eb7ed92eaf2076bfc218d281a8bed008d89f1685c64e1d010ae6ab772dd0bb569c7bc549143640c55f1d2308f6e8860286c628c61c4ba1e4b160cc80a48892013568ab618e7586b4c1f0e339320481b8fed1cc8632e8fd32fab71d150ea4909edf41ae79835e2bb941d4a05b151017e2b6c210b79d05e1ba0554c69d015ed35c24a12d77ab46efa8f78d020d25da3503d1ad1d42b1091032316cb59d868accd021ae3fdc1a1e25bc9e438efb4d24cc6acb62381e52ef8bb1b4a19e9b24b1bdd2adfd73de5ef140bd6ec59e185558acf62ec679b051416934c2ad87eeb4d5e98ed3e41242324c10dd90f43abc069f5576725cd3ab405e24f75af52ad94b4f5a384a2bbc44c4ad16236c31bd940b97f6ace2df621fef6596a18d8d6cb369a22eb353917e56365e4f8f0be85e9e9223702ffde2d6abef1cbd3ab29997c0229645acc294a49c722d34055ead17ba45b0eeb4901e9847ed35b3fda5d3e1fb9b5a6bb702613400e0c7737d216cde2e996085fba101801609bce6c81fe835123f95ae18e6ac30da7145a8f00aae36a74d97f16dd04266272eb2ed5c1d6f38663a8b48add9c1b5fffbce5b08a34f34bb70f77d994fe309d29e3fe241b58b57d3550b1d95665ec2d67fdd8a2aaec8be74b5210fa10726ef279288f50528706a45c87123497bc5ecf65fdbdbf13388649bb011438e1d10666fa362a6ebaaeb164a9a3c64da4d950359cda45b2495dbb1f2d3f171ec439773f70df218377f9e248103259dd50d6763ce2339f938df5d864aeb00700f8a992c000fcc7533b1134bb7e04ab26073712dd86ae335f2f8b394a78f1ff9344b9ba14eb835b2d42ca16104cd34221327ac3313facffbbd5aae710620520371c4e163e2135f7d9e71a36bd1afdba37a85a874c0baaa56c983221e94329206b3e6bf578a08cc07f156dca0b8886a223b9e1bdbbd189acb0bcac57c98ec20079374bd20a527724a9cc0f383a01b384e132644b386175f6a67d48d4672e85d2bcc62a7464a5aa8fe398f3e27e89207ba02e7562fedf7853e0d993dcb310d30fc429702561759694a89a31846d45315e0d9589315c7ec0d78d48c81ccb047de40c21228ab976c22267fb4b40b9efdd572ce05cf63a9a7fab18c79a26087eae0a40c402c2aeee3e474d1747d3954fd83af1de9eaa343e0175eb8de87e14647f341f8622d160e36e8053a7349289847898b6ea28ab634221132229597d300771149c4d6d0b87446daba3897d848d284b5a1b691f13057be2d3551aee871144c3b1d60a034edf9d80aa43122e420da3fb994d8e7cf1505368e5134849c2380c3deecf7b6d28d1d95b09d2077c39c15e8e89a58484cf519f4124d3470dfc2e8ff99d5b6e18273d34414c284fad3bde0b853db0f137ef931d1ed1041c784e592ec3e08ce48606119a95f2e51801b75be9972d6a3af3308488dae2385f7df0e0cf4b1934ab512f1112a15c65ce55a111ceac8d2a817ff8420655b6af47802a29236b21d2e999c138487038b365e3666d61a4b467651c60392d91d7ce5ff87041eded92427e5f8dff5c2be12bbad6dffb5ca45d92d9b185c5c4fb8a6a5b23628f878a06ab562664d9a31c71edc6d1d4dc9fd9d34a386d71367d18886fea452a7df281cf9ef41b4635462f18b86b83193ebced0618ab0c892dac294be7c94ab342b882d1a761056d2aeba5d9429395767152601e54c24ca2413c28d3407b17b16cffb12a281110d6274b95a75d67c8790ee8258b59581fa24ee267e05ff328e4ddb5451c01da390e878a11758b2857ee93d1326a0cfef01a2b88c2ebea894158cb812e51bc86bddb250bde7835f1c468d9b9ddcdf986db9f828c17da4a0f16c908695f27d1cc5769c926257e0566ff41dd3bc740dee3aecd3698134b74086578459613f1dc9ca5f186c7a79a21fc0538633a4642652a27a184466164480de55552c18f8cb8d0ccf50d0150754461a08701f724a874d97c11bc0840cd54b183ff233752a3fe1237aa38dcef5e396436cdf9d6cd5a9e580107b923853269a420a06c9a4a624119dc7e4d9eb9c0a6885279d01639e34b4faf2da559d3c0c085741411cc7b9cedc1314318d4b84665fc95d07b828509d395656251166a8a2a84a2227308afb1a898a94955b452d9d6a38b74f9456a2b8471a8b8b7b1adb57e967b7d23336f4ddb6ba753ae4dd200cf48bef46db6bf22f5be6705cef521463186835ae212d3481e902e6e60b65829c208e65213f4d6222e053af20c2beaa63a10dec04a4e0070b676f5111e71a0ef9f20b1f2c8f62d92a6beba3a49d332db0d9f3889a5f3b4bab4143d0b7e526d51372131292804192aa736a10adf148b9f48bf441dbeb7aeb44b2f01c72519b851c26ca2598bc2ddd91b6e0b7612ac0c8788e8c012eec849547e614a6a89414fed2a95bf6bc13264cc5cad3f0c9a5874197f4b859d83e07fdefd7b44e04efffb89d33637c201d3a9ffaf6927a7a73613260dea5f809c71cfd6cd4c969e10a29c31568c8eded2535368a2f897fe4a399938214d0e4060b86205936979f4e0b0262cabcd1893a9029e39a0bb6ba4654a09174bd93a131461b78c41da9ec6fc389f39d4b8116846603647428816d6b1b7421b615e01850e007e29215189ca3303c8a3e78374bcfca7da5851694a13e94c60ae82235c469dd7f3c77224cccadce182bf6157d7db8f7a02e85551c44a50b0eda6108eb2add6e8eff6cd7c4bb51098b182aa2f639dc9f781456c8757ad716bd45fd3b7f324ca5cb1455b3e831ff582a21132106e06d71daa98e56dcdc7b381ed643f91be77c0699456e651190b0f3e1049f2475623debc6ebbf035566aa9d025c6b57dbd417645270ed7713030cc4436d60b3904867d8449ae1c537c0066faf0fae951052ed2a7315057ca88d79881ff6185fc090c70ae3f068c0a9b20fda3e6de4e17b39d58d1b3269393ae604f4a3be05a7268d34b0a1da57e12daf42c63abb310aa2fd90268065479c98d92e0f5b60b73b805e0e5538d4395ea2e9ad308403219a4e0792080b5281157d9b05a93b950358d243b01932e0c25be8a80ec70550e32fd0eaa0868a8c1d42d7dca8f26695b0a6ba4cd7c05fa460e6a3167e4611db468d5a3f1a822c3bcab76848f667848de900fbf95a1840f5531779604e46fb51cae3b9db5a50a993941881d508649b8917845f379c857f47f182c5d945ce38cb8b71c074459222e31758e2c2ab5f5c2399e2ecd09e5ae44e7d9af682e1b8d83d07c04297d87a3c215ca0bb274cb8f5324d07c0ee76a579638340308ca9829811c379f5b0d404300201247be056d7828b161c40d68d7c7743fbdae91b27f1cd90e985dd37d48bed6b4e1423b5513c3b46ec6af869b7013526d4057901252bcb5419c1674507eddaff2bca410d8d095018c45ef169c671f24c53b95e88b6e6a22c44063cfa2762529d77139b05d75adb0dc5fd8eff58b0deec2261b56235d368f7fddc1208796f91d72b953cb0e234b234b53a094a33d80db9e3c11b0c71ca81c4be3ec13b0c37ddfded9702ebd627f44a7a783db645c349c85bb9dcac6d50625b60489619ae22424137a16027c528710f9a10bc99ab4bd0d5e401eecc3f22d5cf953ccd04efd20ef59feb3401074d7e87847b909ebf8c13baf2177326efd70dfbe556fe8b858d40adc26ed4eb4ab49a6b57c338cd42792ce760388ab5afc12d10dc05d80f8e6eae92b0bcc82305abffb0ea7837d0d3605dc5b3ea334772061ee40cdea66b04836ee9d1c06c380f028ed46aba4d5089dd25244cc8de2ff8cc120835e54ac1f28c6f4d80aed0bcb2d862584d44c55d65feb15f8830f9be6950f6f6cc69108a42f51890a787b961f4623b90b04cdba18063f560c6e407fce6b8895a1852240a2bc8a7c6816640b8dcbb7b7ba04a4ccd9fb674bf9619a89561f6bae0e402602f5b36f1833f65609e74ab45950994c71dd2b8e86efe9fdce68ad908fdf691bbf0dc06142899838e0504772f59ca1a4df6f94f72983d2781581e18130fe28a5af71905a114444707c2c580a50efb3c6823e83af5364abd67a16e7a992e8837688b6ddc29dfc77306225f089d9d0f6157d341df28984860fe89f031768b8116a0e2910bd92352ed8b846a9fb2da935887c437256507749f95662d553a337c5764422eba1919b69242fa84572b50880aa57a85a834a2d925b0a950419d3b56245c7e118f3327047ade0120b0d1cc095354ba547809d4471ceaf78ffffda8ce4148cf100651832a4c74704466d180dd16316f02b8602379e8a7a69b214b444e9903fc5d97d73e0254f8219c0a526653566ab008f9dbb1765dc30333f8dcfb8c84e281ce78050212d9709f8816d060238e5d4771c395134b2915bd85504b85f7c97d6c39b87d22c21bbcf85de7450c6c0cb07c1455386dd08c6088744afb560310a613fea83cf158e3be88c2b91afb5abd6a3a580101a6f65c62cbd920cf69bc27122d305c37c53b3eae8b6f9fd83e14471f6c6edc33bda4557c4dfa22e34804193d2fb3f313270602fdd1a452f46c7f2335138791c32996c486e60e96b4c03d196f19b09fd8670e79354ee1f09491a4d13110853cb40f64d4bde9b11037fa49c41f5cccded3be0d09b72e90f749b7f7715541c7cc458dd0cca353b1400467cf056891400ced36071e904f6ef7fe9e4c044e6ec04b80b19e2fadedba2f8a120d347ad42c26d9cb0458f278f9d01705ebe1c4d8d3ae7bffabfd90ef88f55523a87df8c1dfd70736c39051879aa7f446d05c8e97611c09419f205ffc469a8f47738da3bc2ffe7279facddbec95a7cbd2af2090754df3b3b1c23bead465dbbee257baf75b21b13c56057ef305714a7ff9402a87744c0872984683989175242ce94819a156d4ee4161a0b995564354a8095b0ec50257edd9952ab146a77ed136b7d9387d1f5c4c6061efa6c2fe3f4739cc15c086bfe3e916d2c3ab34ae643650bac1d68b104b9e3cbc302325cd7cd098617835f1754fd1de68042f4b80840f30a76c674296183401ff33d1c01882119fb4c22bb3b0eb366ef89aba48c7ce82426a6e421f3f3900b2059cc560bd7389e2cc1aa8b7eeb3a8e15f754289dd7b656b3719dade0eaba004e846c390baaca1ed7c2fdd70d2ff9f0320b16269b32a47a9c99719f2ce41fe31666a780f123dc0d42056550c292374b1e86a37ff3220c4dc69d9d3d9f9aca9f8004e0f88ba5df8ee163ca5be9a88ddd25a7154ec253b0c91eee3810fac25331433d518007f652370538c423500e17d22f3679af0a9577a692e45df71fb80a903d213ea030fd94c9a3a9a976a5076130b5d3687e3e70689ad4297094ea26cdc2ba17aaf84abc6da9dcd4864bd84ec9eced08eec4116534bcf59b646ea8f7a57dd656ab6269644f3973957bc6d1c8b508a85cfcf97168c1c6ecdc56d497fd79fc79f800dc17bd5363974aaee507d980a2167fda963ba4b047d7bd93792cc99b0902d69692c2ce931c2f8e07e938303db248b6d92aa801072afc71d40e53d7fde68486a9b54f4831c2a3d1fb7623a684242ef5d16f56c11922e2f1e89750afc2028065fc49f7dbfd71d59ca4c718a94bbe512e09cd12a0f7cf01ff81f80095ab5cf7ecd3ce842060ea975c14d57f28b1101ed98a9c70d53a599189b58ddab1dde2313b7f66ed7f1d903bc8c29284cdf027dded4e21f9a3d601122a988ff8a0291b07ffb6e4d49affddd6040211817f860948558007f3db9654b1144152fd614b9d7c05e5d2d5f03320cb8fcd7b3803304c2c082520d71ecd711c318b55c27e92e6a1c03bb3a4b0190f14e663a383d139a58b52f80b324ff0d98d39dfe0f2ebd198cea26b27107eabe7631b8802022bd196deb347091c1456e561c952c0886b89d6140991a1d034798985349cd6f4d57bfceaea5bc8823106b7425afb66cc145c305843c5a530bdfdb0cb7135746c5ff00c927a9c4a224edf6d83dc2c7255ef21d52b5351aeff5da96fbcac58ccbaf8b9f9f1e36afe27c6d6013800257839a6fd8d90eba94544a76462f32a035a44ffb69ab4b6c056c8197be6b54d3a6d5af1d5e48c12802afe644554012d8bacedb2006e7ddb625e08e6413aefc41b6cb71e7e0340446e8786833ec8c174557fa6d0f7d26a34cdf48299f43e1de392e5dfdab20a6b4a96216f98d0ae8ced2297de9c6990297568e7a0aa4d5bf0496527e8d86e8cf014ba353a2a33340fda89b4b2d7fc9a59408712927a21094ce4d7112c512a5e02f2c3949789c8be24abd7547bf0888488bff029f8a1709e5fc87431b053a6edc2bbb7c0b5c8094c9996b3d1b569fccfa0e192d85ac001fd84d80180ba5a30b1cf6363abe4a99ed6ef3bc3de7b6343613947e79c2e67c7f48d41f004582cfeb8d07f1f7fb1e7dd0b4b7b708a32f25362d87c4cfc97fb7bad7bbd0c8581d072a98e84710508973c872f914fa7a75a9a2621403d99c1e66da09e7d27e90c37f133e6319120f3cf0645445308a082da7e6a00e40ea2ceae39172b9626c3fbe41654e141321a446b151999d23ae9a422f6777c4e388b6a4cc5333416cc490669934917746323d1de651a4e866088a14e2029b8988a454041fec967b129e4a474c0674da10665125e11bb7301904fee8ca8eaf5c3c6dd84dd536aa34cea2a7769246c5f523bfff7cc9c9e56c6d5229176f5d054b47aa43c192ffb7680684aff45ba93a50e6b2c5d600088b6eba8653d33fccc45008085311ca1d30524105a3fbc976f49fa01a39997bab6edb649e4f2f57099ad20b1f7fff7bad710b43dc9d77e1f7efe055b71df9fcd25207ffb6f0100d141b862e6f2024274842db8c4c41084015e56143bf1def9d6bb373b32aa60cac3c9bbdaf6e3c20da3c7f961f6f0cdb3b744920b94febad441335fdfe7fd44fd9a1f77d354915796b4e2a0eab33616f8bbe2b356932c88acd4e564c4fa151ece53b4a9f027b881f2553dc87be7ed4fad522901098bd2e495057ad7fd6110e45af3d7cd51488461a5925b76a5bc26336a58d4381d4ecd55c008ebbbccc737f4c387fa1d1de1ed54ac0029e4c1b74b1ac3d022efb4e2bcd20d3a973e81e3a956a7c35a79f8607dc523d7dd67203303d1f9d800d648a5d7497c6f04996b25cc991fdd76ecef885f13815ea34ed8b310a5a455ab7ff91208ac6c2127811dc51484eec33d05f51e18a1ede806d2815cbe6b4d6963117f0200f184a36b30cefa02f980ecddfe1fbe93f0e834d7a405242370000d19086a2938b161f44d382fc9d4e3764c3de842ffeb7a64e28725fcf9042144176987cf1eaaeaf3edacd9b063e2e92e5bdbf9f5ab1126f4e05455134bcd6c32eb70cf4c952f0ea12a0822a40ce1fec3bc608359fa394f647efcc9c715f3dfc26a6e2beca75e0638688aacb381b2fb59ab56e57d12b675f0bf22a5690287d1781a027fa69f97ad65a77d0042328f08cc3dade9453203bb8333da0240e57d5d4fc7bad114b822c0090130cec914983adaad640bee1225548e0a41580622023eeb9e425a5756826e2b8c4257a5500d5d14379d6b00eac76c251f498639dafdc52b04d0731d86f3b96b0c068c366e63c4c39edc01847b90bc0c58b6e333a3832b08b27b06164f938f0930c8f6d74759fd8af0bc3338979559fc018bfc11e24cb2973ac941075e700f66c818a764d2c381a4ce96a67d48e7d400f3281515f6a19014823a8c5b5e9c70f2f686db4ed4308cc76fee9f73bf91b0c701090cc3e095072de76d4d92d939004638cd4133bdb7b3e2a242d39e174b80f0545cd2259447125f9f93a0ff392844224217681be5b10f0587677fcf716a3c470b9e51ff729f82ead9456db2398700e6cdaa8b607954e422f678a899c8282d4b40daeeb2ac16239503d2a2545cbace629c2d0ada00d3136ceb6c6d8b099fa3223781aba6d9da32d897fc987f1fdf04f5224c28bff0797f096496de154a2a31ab3f56628dcd02710330a1e958857a552eaf04abb8e8a3c86194c9ff959a6f337b9863de39b1200fcfb990d7c2a9e1e78266eaf45483805f37c5f664f46bc5e5524dc549c894b5f7b32072b8884c4a65b7bed75045a80616018ab940bac565f5df35eb03c57cf6cb0db763191efc972697627e06710fd558289fd70d997067860c7b4232d3b6f3fe8677d3bd4feb7d9c58ddade3a8b7ec8cacbc6c1acfb1e03367230ebb93a124ddaf83296919c0bd8a10e68629618fe45e43fcf2ec03a2abcfb497b36edbca8703a7803374f10f5f56a8078fbf224985018ac19bf34668077d09164e1402ee2171ba96152688a255cf15e86a4d0203229ecda2d5a28e0e00baf8fb7e7c290ea23a9f539865605cbcd39e1c9bd70c5f2ec2b1f7509c149a361ef2b156fde56a75595426367ad2697afc06a5f8779dab06352ee1170a792db30f8835ce347ade0cfeef6af083dc865672aff496b273984d06e5b91ce007a8dcb0a2b2b5e2c4a1f9a7521921cab34923e50555c2306247d977293e282cd58a3fd54f14fc46d3ecb51175dca963fa356fe1206345b4fe1e31a263d61330e10d6fb2ec47cb6f63008fdb4c70f22a79a9a03a34dd7743427590ba6a91b5a079aa34b984eebca7bca1ef0e7b4d24832947e6f07931fd77eec241227479488be371a4029470560cffa882841290f41db2c0626a2a96f1245f2e39dab7d8acb6b263aab46da4c1922890a8cadad8916fffbab2b95e7a82c2bbab1aa6b59ca5934c14fb3c4f36030de1e5e967c8e93427c41f0ed51e564fa38c9810a2792c3c6302a21eed88ed7a2955d9cc0df485f92745910f4c8b26a0ec6a30d65dd9c634730112bbe664407fe615ca77be86da8d8d46771a41311ccc98a2693a940e05a7993c716192316a83f8634768f30bf3f6dc60e2ef4931f898e577ec29b9d24fb08cbe8a0f700fb28431cc0ec6e064356a6b637216123bf480c3eab2c4dcf3b3fb7a3889d1177110df79b8c264867d3a0bf78e301fd654e8e108ad845070b792644431626e22d0323dd57a975854d72038404a00a5df33e478a24527ee955e514983448eb01e746d4d33ea1c40246a43b79ce49ad334eaac8f3a4421a27f52c79642772f1f0516d1954f446e44b91b35b087a832f17341399ee0daa29c5ca2967be973d2cf82b053b0057c612e9b4c047b7bb0d7df103651c02a225017e3f4e2fc491d36a9069c9b6d3513bcab75f21b58719ab75b285ae95c14112cf68c973c40f9f447bd05a00226267216bde84ead8907ed6f06efc46410eeb41808fbb67e9a3499cb91da78482dc7782b7a0c1833a18055d7611be34174e438351172aad13b845881224943e0034d260f1ba14363140975e239c20b25c35154bc413e8da1058df327503d55297685d91edf337df77b6022f093b9d19b2046ce082ae03560c5339dd4ed6a4f9ec5609486904b433341b47d957fc4ff725b01b6eb0a353f6a2cc42dc91a6029711d225b80c7029e516cb49658925337df29c1fa0fd7f2d49daaa1c79ea5e3537e85e20b7a91dc4bd1da498415406c5004bff4bc74c88b368369968f1e1abf9ae8bb8e1f6f36dbcc582ddc8bd44fd984a3d9da52376a8fc9cdc20e1c078249a7dae98c03256da4cb0cb873a318fe0b30b382e6dce4bc33b8d0f430189410471a1f12dbbc5860fa2ba5a63e7e8859e53b973bb4a50f618646b924ce6a4b2a4267847807d2ed09d4298b5866469d3b346f3b5b5e05f750e8f2f841fca881ea2a3e8a072eedb7cc3b0348f9b5ab6b213f547d3e56709f6ad2abc960767f8bb35350f4bda51be8bba9a8718a839c19d63a4e190d3b2e6463141a80481f5818a2d48d13c2f0447072068cff158ac333be36c2999f2920be63096373afed0e1ba144da10a96829e63ee38fc8db5ff821712bda2850f642974d2b604a76acdc9ad49467763db1c9bfbc08a3be064548a40bd9f144b15a3b8c49bcb62e9faf90f0a18cac264d5f744814689ba6ba41a4a1904ba21ffb53f5915084f882c55860834f4e827e222b897c04a20a4c45cd43005d9e10c2f1f0878363d95d83404962070a892da0431b0227dc02d8ae6bb89f1e1a8408472569963d5cf85244c267a14723c47242bf24a215ddbc3af4d813dca31808cdf4dbd593f93e9dfa436d88a3508ced791d59654d2d02fcfb6cc960d7e2558b24bac7b1eb388b380a88b2e838fa49af4281052b9c6829062f1166245a818686ad190cdaddca19e09d713a58ced5eddc71c67a5e2ec43268851234e07a94dff2cb6f6330a7a68cc4806bd516b7d8f3298746aad99788ee868c3ee1d392b9475649651e7c81a58dd5e26a460f54a0403941fdb7bf1a1a37a54683ea16123370c1b47ae46eda1e1720a1287c9dfc53eb7229620f79e40672d0dd9cf16cb515b678a677ee6d82319f72950cdcaa23c63650831784a9634c1ae7c5929ab0de74570f79abfc7b951f119f881227f96a1e26edd4806b6e621279073723bda0cfb75dc37196c725b5498a304d37a318ec3ee49df6fdb215291e842c507ca80ba18edb7c39da46e0f59f41514494d2ea19c8ed96cf38d9bd62215d4fe9adf73f08dda04b8759ec4ddb771e426e71f8653980883a48a0cdbdf68da6b3729784911273e6762f4fe5e464ae08dbcb1c9420fe36f75d5372e196803e8a877d0b87a029b77c35b8698a28344510cd998889823573b93f082c3941ca9ced0a2d58811c1741345054d0aa18b50bf4adb2929d8fc5c6cab2b33c5327b9b3a129413c52a2c41e2020f7d1cd465c017c73cf96167a05e1634ef210f00e84e0fd8dfee5ec15079c27741625fa7dc93f7f3d23f1baa709290c63b017e600406812bb03400041fca8725a13b51768040ef8141baa65138f354e664367af3421cf849f1107803b07da0eb8f772c13f9874999e8b2ff3e8ec76a5d06329cc5a98e594a709ca4d494e8529c4402d44d2558fca41ed413ec1bd169cba43ed706e243f2fd00baff90fda4a1601a0c5ce1d979a1f6c0607ddc231e572dc9ab8dd0c9cddb38b522db93c5af6c611a3592f6e27dc0ab1d4035953047d5bea9026117edf8efb4e167b1165f10056afc2de307aa08c289d632c5c4a3aa84a4ca3830025cb69f2ccaf2c7ed9d98ad3636828444eed78910923f682af01c9574cfeda3b0c20dfcee81b2dab28a7408ba57f52be12b93c42919158ead446ff9b9d1690689d73a4d328a2b2ee182329a6df86dec8b6cac517d5367f36a421ab4fba7369088865aee90394b6460c16b091cd8e1e66a5732991feb3b8a93932e2d622b7ce1738d5244404b5b2508d6311ef3f232c00b018f7126428c93a4314e8ac9002ba23a2dbd3701d10b0e74dfca2aa162412ccee33e3aeb544a60eeb694381254751031e73a79eb78c40a46129a87d26369bc38c358baa291c18dc4d000e8ee826d517080149263f83d15fc9244ec9cf81c6b853338155cb316d609fad0f0f253e738c8c01ddb122fc1005a1731f327b2b3d5baa78b21536fe6bf6353f6e6ad910d8103247187356f18d8573d36b30fbed761801d455aa41fdc3c4c20d0630152de7b616bfc1dcfd1d009f36ddfa2c4fb249c3e75865af7e2d78f38b362a6dab25d522b9315fd65c16485abef7a3179ba88a3f099060d76e27c8fc316862f6349aca1f67b86f2ed5b228cfa22062f74ee58c5aef3582b72a2b678245055be5376505c587ce0928cf54a132316798bf3cb68bdc2a4bfdd06c74212adfb6f27cf3627b878c7e566fea8034be45bb3710744798933ad3b55739a77a82edb89c774bfc4b3de819c7bb7ea84cc2dd0e88c1d0d85408e520b650df7ef0c793d52a180613bb8138ee5e517ffc57da0b90e2fcfa2bc2c83aec7c90370490b974136e1eb080055cd24348813146c41fd991525cde4763ada96e979bd648f0795db5c13e61edd9f558fcb573ad7c93321bc69038a4a5679d51572a0109d804fddaa50230559e8d5d97064d95990a62c7cc7ecc186aabd6bc6d42db8a4240d9624151918c2d1cfdc32e0937734f677609c6ec8e959368a9cc46c8d6ba3d1548f9002eb0228c427bab740752f1e23f6b59704f9d4c32f0e3afdbf58852a0cf6f5ba80b268ff1a62495b78e5960c8724427fbd3213c0692c5436c66f0ce345de625e21891fff033772d9388a1405bc26127fa5f8ac583900ad6ebc312210b06454bc82a487d8f77f292ae332e3cef83ad34d725c663f7f176bb17f8bbbbd0a7ee574f3cac5960fa0a38e8008832deb35d95aa83ef283f04dfac61e78ce9286a404ca2fa0a08fdfdcb35478807b3c9341bea8133fc142a4908d519afe88fd5cbce581e04de5d588d5ac4ca0ce3c16fa22a224615bd9c4e2819b0a6e5b1c8a9dc95a74f232508d92ea385995c5e2e319e1775df48c57acd47940bd930560050c8ec2631a0badee3524595b0d3c111e47f0cd3cb852eacc6f3c7b95a40aa9bd987c855da64e4989c777e84e537c3821fa318f452066eecaff3126201f11f8153d76032eae111e163348febda9537cac59b2ffb3a65c36967edb0637466e916da61e53b22bd676584f1f48bd23dba4032c72be855292fc03bbc5f67e4a59a388d786a4c224c81a0306b5d561babe984e2b77f2953db4b6383a5d5eab7e94062f08abd3541822269400980c2f0f7e280072afbfa372d5426049af49d29e7360cce6af6f29784821ad985d6888e942a9c0388f3bab3551298c9d3f6ac452abda7a3788bf3213306f0b91ed91b905d06b52ae32ab1e2643696c0363e301be7f1ea0f178509fb19ce592c970f52c861001cace3c230d451f29f7b7a16ea0d65279299491624f05a1a7210badd8983b02ce3d748e6f11fa49e6f547f6fea9d35d53e58cb282ea0b9c3bf248b971167ed6d3d80bd96843890f308fa168a2236f9225dc744f3253dc5dc606060d3ef8f302a6df3edd822e426d70ba0ffb7568323cf4d1841d68582698c698b388ac25e765c2082df63d5dfeac1fcf26928e2fa89c39cffdacdd772d3ff6258f1d6cee65cf20dec6847f49d44d76a43b392397b2ab19a65781273a2d7f9d314f3c63dd48b0676a16d7a5b80bd98ce1462f691e97081190e7044385332622cbdbb72cb475b1b92485967a3f4ba752876073e636f7b374573e1be4fadbf3a001229188c1729b831161e476eee231d7952919ea9bda00e6f03755a17b4288c8ca553f366b9bf0f410140eb42e68a0c82813169059265c3fa6325349435fd597333cb819e209c4f0503d749978098bfade7417f0702ce4a6ed96a6513a8de6a6999ff3757aca30489e904587896dba01a9ee4f21136717b4c8e1d47a4e931b34898e305023c9d6249f2f7c59955d3769a7e78cf5c46c9853b7b6e3bdd06ae407343dc228251e885fd0d0ac70d55b2e49fd9bd5144f85716fa17c9c711deea17fa11bca8a8011744ea57c1601a1fb160f00a62ade91183a4ade0b164307febad02d30801229cd5b8f242c37954d6b6108c36c5da1705bf85f57cf00f3b232d24a209c4ab7697b02f8ca870018c743251d51a4bb4a6deda4e2954d7805ff5c5a96884511424ff437380dd95f237f620b1c0f8a36f3cf158eae145f4cd883f6caa71a249835c9dea581bf953aa097b8d54d00d72048844592f61c191607647d5889324d10311ee3395d6bfa94df959c9038711e7ca3a10a936e5767546da0af6ae8e9df531508f78efb22aa2bee089281d473124374450401f0fa1da29f85063579ea84b4bbf3fb4de3d7b7780b37e5652357697e370365cc6ab1447ea0d21e2292351c9ffb262638708c7c7a6a75ec6af77a7aba978843ec8a640a6d74b9573cc90fcd18d7c2bbb650df1e75d3a78e3f054b96915482dd5f254bdb3f8d76d096eb9ebd409706e533005e0b316c05a872d54d1813bb58f1a8920592fa0d7fdfeccea3dd039e2dc1e07ea6a43b47ea40d90e70e7a17796ae40dd1ccfe554a0fe7faafde579f9e8a1d99e2f3d588cab0b172f02eae7b9e2cad7b08b86795507bab777abe420fe4820a9470c6384cba891af81fe6e0336c056d1bf2970b70ebf4fe5b3029e3e3b3356752f6eb0537cdd0922300baf2929b343b19f9e65b5a38a07e399b1e5e3e41c7f66994a83ed39d002e225980454686effdc506a85ad3e4ff4a8a81332d0df491feaa7c06f9c06b67cd350e3cd73258e83105576ac3776fe911a6febc551c4da3ac2e175c712abb0e83793b4e8ba23d79e16536dd29e0e4e04be7eb6423fbc7f7d93e7d3b06d8e2fb1e7a07d331bedffe2ec2c32f94dd683351407aa4a27b9fa64c394bafe3c94f22c3a41ad13b8c424754064bf1c5a3929af24c343994a5f23c962ad8a33b8293c29db54cbbf17bd6de2df094a27c0bd4093957d7e9cc60fef798ee8f3300b90449eecaaa321d632e20841075d900238b86bab22175ab1fd917a7b3c060e70b925cc6fd6c68b3bef7f44481a098144b06663d07a1b5451c83d8205df0f4019bcf6837095a89f5b4f3b05ad0eb73dc1d35918aedfe694e87cc1b1fefe88401097265789e0100bc1fbb125664d51b4e50950368be071022866f4cdae2e0be925ffe74a412bcc60f936d30e043688ca82f2caafbaaa139878e22a4435cdcb7c4141b6baf9b9073394c028f646bfe2c487b0fdce424ef1ffa2c920cd06f1b217b3024239e5f0e2cae89bce47b87d7d02d1ae52caecd923bce0a238f448b8d38ec91e1e24c8323607cf530e235f576a1343cb484aacd2347b3ce14c4b15d435e27a2fd4fe3b30b7e88d655711c623aa1ed408e76a92c7e9863a96a5f86afb1dfcebb40b85a384c7e59a9601e2e2e462e61487f8c7ca91339d6f01160262187f2b72c681fd6c70efb676543a17444706fabe4e5c5f97f65075fbbcbae9e0c29f62f7006c0cf50c505a7f1098f633610921af0793f8d588401f861f85f919ac73cc99e181142005185992d6d4bd43e16f4e4ab94cf467c87ce3e325f656c21deff45731752a4646d75b2f191cecfef874191c70c5a0812d7cfe60b4ba153e417c117434100543f2fe3df55421fb8c4ee80073c1241396ccaf3247f096ae99b89428fb7efca22e32f7a1064354f194cf4afea9118c1af490b90626d51318c0ecc9d277756f341d0b269e0c38a7121321f1783429095a9e00339001f26bf46f3f6c953fa7b8ddbe1fd645e4a6839ea9e194f91459583e46c4383eb878767fb18903b8ceb27930630cf3fab1b02725eb42ea1a828d404d76380b553a5b907b3d93dc268d9a198398fb3b978987121ba5631a382671f0d07eb9a94bd56e8da74e1c216f94bc0fcef7043865278df6956cec6b85394df7cb9c7956cf1ee408452e9757b82b261058df3b54e40d54d8750b5bcfb9b910b6a1b7e76c0b20303022636acf156a2cf215022e8dc4af9e6e08b4bc3378ee7ba04da1decfd99ae0146ee617eaaa4ae4505fff8466fe369e9e3a22162d98635365aa590f8a224365b740516b167ef4a1fec3059310473a2316f7a54506cf47593e8c56a3ab97506945a67be488098600a6fb4ba6514773ea954104c4458cf623adb1ed72fbf7480e2b768d80daa993579f513ba61ca45558530d5a90067d46312eb80b272b92d82f928d225d7f1e82fd8063ad849de4486e884b7e41c46291005ac9191a5a2cd381f63cc13623f2bd9cf070ea2bb934134414f0909341953f3f748ca8f0eb33916f4ff5e32aa83a866519c7d5fdd83e060cb9731d3e1a8647f3814e44dc84b2787ba963a1a6cd8e160e35b4b42e551dccbcc10090d785fb8adcbf807774267ba6a9a71341db2aca392a5b1bcdde4e3d2d078dcc6381b8b4c8f7af4a07f62d7fb433a5ad6fff4726bc5dfca5c70feed5cb6c03e6e91d6691cb5c8270c8721b141171c32d18922a61fa45efdf4effad96cfd0f2117fb8e11b5ec406bbb5b485a01dffc4af7c9f997e9c451c07215ec121e29c2a57f7079ec217f9421be6b67c2b7ee0f484b34077ead5538951e8cb4f2d4fd37292fdb108be9d2fc1eb728e9d54ddcba7731b5cd77d2d442a6621aca448e20d76bb09eec23a3adbeca648938d86e759c54fbe312cdf2c5f809e9b98472481f400f2e93e533d94d9768f0fd7f200c543b4c9023ad9a93976047812c995b13561d507860c6569d1c49ffc4ce24825f5c27eb0460d2b880721216cc760dbaa9506c28b84671be511c59d8c3c14ac5c37f64ad8bbce117ce312f253f1fa356b8a99ff8e0f2d66b0129b32cc998e42aa79e8ab3c007aea6bc8e6a1b2c6a68cecf0d33655cc28c06d99f6891d5e127dfe25e8649fe7e15f077c95a7e0160250176162e6c28209e4eef916a80875182fe963a432c7531f6e2e0ef8949bf55e9123549ae067c335518bf72b1fd91ee6c67519a457e66e131fb9a155bc76d24304731d0de790d1b6274a68cda662da540a349ebe584671bf763195f7f1355a33cd92cf7c815c8786cde852236776ef5c523e9a24e97eaffb073a411b68c1fd6467bdd50eb8632291326c18517361bbad855404b8c9d10323a49a7c09b7c172a0cf3f9644c16ff4602f9ecc1922d6469079842eaa8bdbec94e6394a661a8fccf222f082e882e3d17ad26f886ee19dda8db58ac3bb61110b436964489c1e2dcb9d4426ab00d34c0fdad4f3e2d90a30493f10683a75d98319d6411ae0e9451d297fd981f72249d4b67393c18904b747fb4b1299f579e8e2ae908a1e7760231f797c2f1f04242d3421464d1d8d78451e9c1f229e9ecd280ff9032936794dbf114f07ec72132ddfa540e0c47e55c1b603c9af082d7e6f6c912bf3ac112b646e280e894930c028a5264a6b003bdd1ffc6170187aafdd786d603cbcd412291da4f0c09247ef2674913d041246d42205a45968abaf6e4e5e675fc75a61d81bf27d58fbdbeddb76cf42aecbc033d232ea5253b5af17a18c1711ce69eebd739b542cc094218e46f0262d0cac4c7da81e5a1d2b8c0fda737e4b1ff58cf90ecff8c7a2bdb4c16c0b71879244bc0274bb7251be46a3bfd2d29426ec1e15c904ec359af22fe864ed2fe542e042a520a7e15f08d067cc2e93972caf3f0d9fabf4f2e14d9867008dc6694db8864c119bc5caad545c4bb21d9c0fa78da81efdc3f9a6115ab6dcc9d7a62943c39e1dcbda242fadd953f0d762a29c38588e858daec53ff6d40721e4d13665d7005f5a5ef044179eff415a622fd4a1a53afb0e0dc37be7259ccd3494df6172d4a5491ee84f5f7d848a737e1c35f656054d6312d507f8622ac9bf1a205ca8a721f3ca60e55506c87f096830be9509f2401c85b3f4c1f0d1fae71cfaba276121487e691e87f58ec884548c20d66cba0a1924060b28358512239776f40b32778261098bceeea65f529aae74d0459e9198fe49bb113ff5a7822194172d66d64a58c2f7863f502955f7d48e3cb36623c1aec3d483d0db14f0fc38c2bcb781625d69dcba2dbc5beb98708c034b5431e6f8154af7adae20c3059b6787935dff169c7c624d88678b63e0310c9cceaadecd2492b9f48284735badafb0067ecda02df8e3c4d62f4e83f95840945a9454fb03f0a657bdb7436e733bd840d71409482b5b79d67f92ab5ab9c6093d056f6c81639f974be378c78df45dc1f923a16db01a7e9fdbcbd0461429268a28de7347974818a39c6602ca81069f4a9bb5e9783fbfb01afe63a64010d26c3999a6c033303e7e1cc2bd3c60d9fb607a6204f09b8e04392148554cc836ed21ff4a2cc0af8fb0b0e4c242d0f5c29071b8c2c447e4cea0f11ec7b1810061f403a01adc4c70505ccdce6702a79182d9cd874358ad9cfc1e22d1c3642c3e598ba2b2ff6f52e39ce948542ac0724864daefa7fbaf412014c1634ae86cfdd72059f1df2931057f5f284821bb797c0451a16ec39e863cbef984543b266f99e84871e1776bc3332343bb7146f1a7aba794b8f06e671042e5e4ffc26b1837c3e07ac479fd6cfc00ed221675542aa0fa2ad3a67e5c8049dff89357d5e5895d754f1d0fc8f2d87210a2a6389a69b0d595a213e8db46a4b050b240fce94e7574f66134d407bc44f436d7c01fec82aad42168840b731cb03cb8bc9ec8e3b41946d38751feee4f70b061e986398c4206bdbc030bba21965393119ec77a8f39064f0e2caa36b07d69588694bebe32eec3f2ef7cca67629e7d32328c8eba357840acd9901fb20aa0c0c8962e5c9a0b44479dd70e07a342583103f75bd25af75ebe2ebd42b2bbb6ace7dc40e0d96a7d85ec9632a51ef27141d15afdd27805cf679afd23f8275f8139cc50c9af703d05263364484ff4127409b7b02e01ee76c9ab481d1efdba8738021df1f3983edce8f551601dc18086006228a7c064db8c91ad4b3a4330f627e36360d06c6657c0af430dfb72dbd1393fa630bb64a9f7e087958b234ee4bd6b32f552fe379eebc926df040a9643f5df404a5ee1da08336e60e73d7cf77473ca15af66a4aa49cda99d718f1bf65af493f2fe2d8708b82295d863e8847f8f9ee30c3eef0a50c73f93a7f6cb9c36053fa05de8096d451f1e7b8d017a5a976a77dd311b4a0be48f0153aab108261d48b323f50cd56d886af34143973e70c1cc2f02a0fc42f59f7cb6224fe9588698a44ade8ae735ce0d96509ad30983d4d078cd352b30bba2ceb1a3016ae3066fc2d87e19a153683af92503951e7da566b86230b5df726a95ed9ea9d833fe90a4a7e9d29a3732985e8b427c7a9a94375a0204e58eb578e5686c20a56f0a609daa8732f5374502fc04ec57250f64fba7419cb488a128883a914b7333496e258a1beb57646a05466d4247e837d7e51caf72044ac55da0f2f2366cde278219c6ef7a5e73c77be1d272969c7fa9d6925a535ba040ef235b10cfb7a24185ac42cd350022dac4256be154b16af319b186b6a2c9b558d01dc26a9e5eecb3d64070101313e91a51af79f72a3e223706f6cabb9b40dc88aaa542ef0017d024a2e72880ef6e1b827894205e45c375a0aed832e1dcb091ea20a91ba0fd2cff4c44d75f609506649b52876d7ea6bbe1b7c1439176ef3ce7f5deca68c724065c503b5fdc67eeac0e3a920315fb72d422800122741cb2773bddde0742a313440810891e678d366a5f41c1c2bcba51a0b6f5c06a45d875f6c1b5a0866de03141ceb29b1072ed7ebb1e84d22f332cc7061eefaa1e3c26e65e160116b2223a4a1aa127f0faef07174ce1505590d3573b629e667938eca523ce34980acd65041e549436fcc00933a2502eb06f6a7836722a1f4b7d8e2fcf83b1801a40f7f9bd011d7286005577c4cd23502a7049075ace07f427687c4c48a408aa2b433b6d62615b9af7480da306e49dd5f3dbafa2d44c8fd41e323a85b511407829aac141694d4a5332ccbc75819cbae1157b304a90b29b9e65a28132612df19772c8717d04a0fb09f73d4c4b0211b6402b0c964344343e68fc00a03928075eea591e7ff14347a62212dc9f41f41fc83680e41220453ff4765d870a80b06014c05509285f100a4a005aa85cbc88568ab07050f56bfe1d3b10b3d30bef485a8ab6b4d8da6110f0ee9046d9dc1a058409313ff3144720f502576e96b983b107369cf20c9f4dc975188ea64a995211483c558bf0c4d540798b2a6eb232a776af9b883a9d04608163f5e286eefb82f370e5bff3dc36c8775b9ab689e16ec88d1a245ac1af30d145e8181e529b64eb06e568dc552e0ee3ed0aeddb16b846f6e49b7f66ee31355ec3e1c826d804d4d8e8d2c083551592eda359631e004ecf55609a974f2bc32ae8589ade47757bfba05311d16cd793bfe7aa84d166595f64a80c99e9492371ae522b987c0a25e16a55a2c6cd8658d9d99cd13563a8c9a02d4aa5d7a5f10aac8d9e29e87c45631227bd10ba4c60ab2da956dd01e6819e018195301a83192dc360a89d466ee73dbb929eeb359c741e295a9e52baf740675fb60c4d5f5fbaeb3d932c865c1c12391000012c8ed83e18c05644c3b4611c89ad6911c985560c117d931c6e9649771de9a780213898e5c7d864c28909fd5e402bfc490816874cc1d492b29b7fb92b761257fef20531761ef025f0d6b74fd4b5e2307f8a4f5473421435c245134be4004b56808e1f399a29f2394113f3904968cd328698d19591fd14738a9a89b38c18c64dfa2e5672e8a560a5e2db07f82ff59c6c6cc20c622b490c87cff9101eddf3f825ae2840b306a440a74c34010dd5941ebb1252b82181d5215a8635cc8d1eb466a0ca4fde1c9c51c8484a2cec1b40a3fd5c963805ec153f743e6a2e09286e9566449b0109280133f08ec3dab2188191db055430952d28db868b424ea7b2ec68b9edb848a0944c1f748d238c5a13d138685c4ecdb7352ee1e7a340133509388e89ec8efaa31a07d06d4279e3327a733d2932f4853d0360d2a140535cd395b92272af16e5b0763ca3c52d38d939fdbef8185ee1a230678c1ebde71201705e6d57ebf864d282a6045dfdf03519a3355940d0accdc4b131229090e9d649e41c3ac4f16aee9a4e87a36be57a08beaefc253c69c3eec8f8fb3cd06687de23dcf4f7e04e2a19813287843b8abadf8824ddda673caa57c5b0d3764f988a9fb882d147e63029611c672c06cf77d0068d44ca15bd80e4a19753b5e88b748445f8f9ca0e6852313f35a7c2f16826a78f6522f1bcee690c88f5b733b4f1ab9b323d0c1d6333d69b01242f843f0b052034983f2226629e2b6e18ec59f6c76d84717392867b7103af648152663fe63566a1cbccf1042806752b91d7e373b366941656b17282ccf7b1b0e9f1c9bc78acd7d8b3602f698d4e00c5411f180f88c431608042b6ea230c6dd94eb80630e66d4dd62189768cca6f4d3a83634168abe353c5af3fb6b094cee4e7574041ca0cabe84daa23f728a840a26ad9478818d34ae8c27c407bed290b55eb5d108b95c913bd5c03a78845fff71c50e4798daa9d319ee588bcb80883434220bb460b474161f03444dfd73662f7d6f154568e78f77115764edd1d1d4e682941166d05b09d43d91967df7f2841793c1f176277ccc80ba040dfe6d1d94837b2a4d879d1c6e4204608f65c17887338a49c97eb4ed78b36eeffc274bcabc6ee26ffe462bfd2c78744fbf4632c2979baa72b3336bb6f67d5a8ccdef2e33d197041ae89b55a26e70a2f37cb1ecf6ef67f1e9de4468b78a0296f0dcb95077cfb6c7c77f27bc42bed09d508c144e57c664bc81acdd485e32b870516b045c2fd8c0808c59b6ba70a12b2a03e4bd35878f27e96fe948faa2a9334aa89d169bc222ce718ef9df4634a0cd82a9b38312f67023793e8a84a84e2f17c038ab6b25a776a7b13fdcc2aa8dd2a256f00d458729ff65341aa326927506da81a44d40a4172697bceaa0fdd4addde54213d51ff043a697372597745e8b77095dc7f68474ae6fbedf6385471003182a04e295558ec656bd5b3500fd67675c684c172cf878cd1f7e3839476bb2080cc35714b001245168109578657a22f79ffaf3c61c063121072891417f2f2e855ab6cb1c0a6a249056a82bc4d7d37b59ebbdc009c699834403fb7f88ea309f399fa7431cd7d774996a5d06132690fa4fe48fb49ac35d9bfef0832bb05a3100059e80ca218c75363e33346c93b37813751448eefae89e426b7b3f7c24e5a3f1e4fe4a94b5afb854ce07495f4a663d558ad8f62e8409e96837a9b3246a0b366feb4f88e6cb2862f9729c8c6fab20c97c6736333987351ff4e7a64f2496111f8a4b4e16f6f18d9b0ef3cb5de6c0d19686149a5f34d065b0fa416ee347da33ae428e6fe9f5c30dc63179a441daa3a373c59c4b3fc2f4a3470961402bcef3526273f713f14ed1ee2fafc57fa451f4ecbbb33a2979c5d459abf736dc595791fac27fbfac852517a86c7214e3245d6b0a2a177514a9c017bbbb5e5646f690389ce90b84bfbfd5b6948fb064b3f93074f85efa7f3876e1379b20c0c193388812dc0724839302e66e0cbf235f181424e69e050baf9740d43579c69c03a83289b7a2bad651439ec38111e6f007e393c828c6d894a3a2b7d99754a9c1b374ef0197d9891fcd9083673d643c73f741172f0d2dfef42371f13680fdb38b3e62b1485544b9b58a33700ce0f6ba9997717212e01cf3958acc7fdb2e925ed2b428eb69fc9f3a48fb781b763c2c68f45bf798fd6c868972ba63c09ab617f81813af39f215b1ca1b200e1eb2fe318c9fb23a6757ca68e04111d73b061fb44003a22c42023a1f7312ad8278768c94f55b5571fab412f358ca2310c3ef37adcf1af462d19c1b6837aec761cedeff827584a0addc157b7b569eaeb4eba2f11210171bd05fca2f782e4fa50ca1bdc430154bb7e350fda63fc65b043cad0c201f86f3f564e7bf805a1f5dd051bda62312146a540dde60d8b1a6e578014212c6f76696e8b3ef9dfbdf992e606ac78ed3fc72540e997ae7f3300eb032d0046eb62a9b054f7ebe9f8d84050cd036eb6add8208c03b10c1b86c0e881dd24dcd6860024c6681447b03f1ad471a336dbf017bf50f7903973b1863c5a99a2467c688eb809e7488fe6a96ee28d221d9ac642587777a7327d82f48fe164ff42f4d5d7e397fa57b75092ca3ac748f648c729ae8b4d24d1e12670ce205d4674837055ace193dacb53e81de960b25acb7fcef01f26dee7d2ff816f4f7b8262c9bf31233e8a4e4894b92d11d4c258ea42ec90eb77640273ae7cde2ffabc7bf6b2594bc3ddf8aad076e921645a05dbb892c1a5e75fb81c795d671499d1d55937e42ca5c8986fac60a3e0877cf66228b8ae39f1d8e4a95468eec3010415c484e176f3470cd13363af1cd27281f9293802bffd39bde5ed0badb3860ba3e432c3fe2d33a9464687faf3815ac9c372f32fdf20b4c2030a627bab5a3098554d3ae536bfdf39bfede6b73bc7ce9ff66187950203763775178845576ffbb78de8fcefe263ffed236c873dcc5afa17607f08d053d0df6125eb56de1f2b357b70412562dd0c98db88c96e6f8d6c238410b2c9267bcbbd03ab0a870a890a75f647ba57c5d2ac22e952be6c2471dc6e2a6d78f42abe5eaf579d39dea57cc9f1f0b8dd74121e37572c93b64c2a6d9f24acf2e11efe9a65c2970a612d7df44e4d2f892a132edd3573a9f412c6f1308e115475e38e0dd6934455c53e6cef93ee9a99847136ec8a65d58d7efdab5d74c992fcf2fedafeaa27fdd5c3ccf6e0787292922f9a76142945be688735caa6225fb47b2af9a25d13c1073a9045d646f7c431c758f3769238d24c3a28bec0bb6686ddfc0aff2afd556fea5cb7c36a36bd6613ac73e9e3cca44b59f3d2b1b9b47d7449a1b96486431e5d3a64d8cdae512e3192eb71ea6dc8a30b96431e7bc8f5a36bd49183a13ceaf840ae778d35723d066e76e1d44ba18aa57ce94cfa0481e8eccd9344fa9188a3d379bbcc20e8619c0e1b51b12b96fb060e9a370cebdc16bbe847733482fca5ba85436f3f7da0b7d847aedeb5df729c6b7a1e3ee15315e6185a30088dbbf7d16efffe611cee5b876f70df388c63a737411eb89013c32a2009691ebfed63c8dd879a37095e59430550f6ce7d823c58fcb21f6116d1b5c39347f76c152c92f076073f726f8c83e62f739fa0c52a1f54372c4e5681f8c6bdfd78b1ca87ed02347bf8625887a761b7ee276635cb7ebe593d84f334ad40b3bd67ef477b4540246f406c41d46c39acf2613bf70de3dcd37318c77ebbfd46bf1259720fab66cdbf6ab366f5a89051d193efabf8c9979e4258314efd7de3b1bee7bd5acb9ad95c08edeb1b67bb3d4eadb5e2142eca35cb709024b7573fee32b27ccf2359fe246f380ccb3e70d7f0c8d22c1c34c33a6b8775c641b38b660de368e3178496b96b9cf7f1bbf16da26b6616f9523fc15721a459fb88a39d7bf7f179246b643838926bb6130c82e278b7991ec4f1bc7fb2e6e397ebabc538de6bbe51b38771b86b0782bbcb9c21731d5d3256b9ec7779f87d77efd27222ab59da377166efb234ab7aa2a649f0ac6f135916b3f410ce9eb5562bc44241d374644f0381984bf2acfdcd19dea67db60961cd33b7266bee35fb8dded840b63ed48c63afc13a5f1f6abed7c499bd49af0da9149e942dadd66bb8af6c55297b464bd952ca2683f65aebbd2acaecd52a3f2bade00dedf514f4819ebe41aa6109ce2c56f9d22af0e4a401bd95dd8028db57296fd05beb43d82c793acaa4e8824c8a2a849ab5da90f0662993e2093f90a209364b9914480862a9b042855aeb83f094a54c8a1f2978a04411c51850a238c9521605922b5821ab20cc680f2c0c1443d00009103ef063095c10210c4e683640c14031c4063e4c546ba13065298bc20859254b5914427a789265d466b96fb308e525ed41815020ea83f6a03fa80fe5b10517444a920c6da124c9912155ab416bd5346bb75befa53def1dd5902f7dcdda6dbb973b42bef4b77b39aeebbcaf7e1fedf9715de779df07168dea68447b8eee6826e93eeffb4070f46344ead7f8b600b9c8fd11d188d40fb70895e47e2989a99a4cb4a7e98efa887ce9f78f2b843450ffe8293a48fb28e91dcdd3451191922e8a92cc298a10192254a7a843725f13ca334817b3c7e43179ba9849cc9e23fa48534944ac216737a5b56ab65a4b7bda3bbab329ad55d3ec56b78df6dcaa66edb6ddcb75b5eb68cf6ebb1cd7759ef78120ed0976def781e068440a6b18d29e21382291c2b0543299541313dad3c464723a9d9ca05028a99a4ad19ea9d247c557357d5434b9c9e9f451f1e43bf9a888026dccec49948a82427ba2dcd1952ffd934b29a63ce44bbf12d91d84e3ad44b2a6cb7d8d88acd1662f3ed070344a69a548d449ad16554aabc5ac5a2d01376f6fb4a5a4b2524a395b03af6a76bbdce5ee6667b4a76a76bb1b8d249a4043ed635635bb591a49348186da47d5ac46238926d050d52a8d249a4095d28c92a8df238d1553de0ce4c6b447bec85321f9728d70d7026193524a29a594524a29e5d6f7ced4df4c3f330ebdb4459e52cac9eeed0c9e6419c3cccdda947e570badd22a422ecf2a425b45b8e52a426bab08b52ac29a671521cd538bf164ab083b4f22e1fc58caf2b68a70665b4528f30ce58b3ca5944a293bcbaad9f06432a90542383f7ed9a395d6fa5a6b78bf32042d4bf9522fc7751d2a0102989e14eb2e2c5884521605501e5351f8c8e3952a21ec651ea2796eb8877466b3bfe20e24686eec7bee0dc7e15b8352230490a5c43faa6aaf81adb62aed2f802e59d233a47cbd942a8985d85eb102e4cd06f30319143d8200591d84520645910c0a20191444b2204164012417520099681e326c01480b27aa48620b60380289892ff84491021cfc30b204211f2eb4607221b38114400b85943333555e652f77f4dc9b7bee1b1234379b66b110db651e22bcb9d66af8e7f2e42b6ea2388940b1b8c13c4e0ec2befc38e51592d98087ac063f960adb03590d66508318d828e61764358081ac063e8ee0d91c5cd484e4cbc41ec912219437e59635897cc181ac063db2a0225b84d99552ca7a5a44e22b3f1b04ed66f991524aa77ca9a7303c99d099b29f0582945286db776f18ca53ecd1498d10ced75396f7b35a4829ebe5b81eaf6a76bbdc9547c619a47b86a890ca238966b7bb8df2c80cd23d3d4485541e9addec16a47b86a810ab8df24890ee19aa5ad582744fa535488ba33c628510cecbee6e929452decd72dc08cb8d6b9279659e9435b30960a79002264890203041412c4149809ce109205dd4000819ba06a32c654094004162032020469ec0821338983f4f6061ed8fec092064269860e979b725422a854fd8504821961682684fd80046f644134234d8e247176a98b98c2167eb863cab9dc1c6c520fcb2943df1020b83275080c33f8104484fa9304c0109a1219df9c32da49a85f5b392f4e7267362286f5b98fa09425b64b656066198a5cc8999134434ad092d9a18b241f182a905cd6aad699aa6316184892d424dd3344dd3b4ae439235eda92b644dd334ba44ea8841cf0a66c0052514010a21e082065480996c095a20021021255b6822886d0207a32dee9c5589267a38ae0531f821410f27dc800754985a604289c64417401738a105b60530b21f53c86600049b022ef40a643faac0d915c87e14c9374bd98f21560556052c3e64c0e3e3239360469b2c4fa486f604f7decda220ecb294cd40680642688bbcb2257090b52c654b40d14508b3474ab5b5d6f208adede91699b9cb9eb9598247b77061f6b1040dbe1264c104242001097c7ab294c560481eab8f4c2fb3c85216039e0c831710f9545953b7bbb14a08fb1f6b6f718c014452daed47d68db1f2c874629510db7f36ac12c203319e1bfa188e4d1aeea33cb2d51edd4a12d371e35ddedc8fb2280bfd4c21d3870f21403eba0e074d7c816691d7e0cf249ab34c3f6793680ecdd93d12f8e6e2a00e427f1a684768f18e1b9b373b822ed03d405ca08fe942286f2e700320f0f0f0c0b8b14702df581cd4d85ec331edd6bbbd03c06f1fa2bbc531fbce7b7707783847cf8400710bf5500ff5cc7b0eeedd1563f7aaf6b87b7740f7ed4368f770cc36118f77213adc44355a23d22ea63c78badfe7e07274bf1f298f1c0bf2ae5deef70ee8ee5d9500edf74368bfda1b0f71efe1d8f67beb009f1c34086da1ffee800e539fbb9dbb66354c8582d8e7081ac2bbf61c5d0eefdabffea65dd5ddb53bc0fba77d08ee1a8e05f5637608ed1f8e6db2c3b31c3b437898ce680bbdd6611e7b6ea43321ec39910ed116fa4da44462b522114fe5c9f43162085d7289bc9937315e08fb9428d3c3000644f98af3666bfca39a3c371ab038e8a6723aba4943f064cb5ea005ab699ad5344dfba9355296b2173c2152c6830bc5160592942784854a68099e9012b888250a28454e7080a24dfc30d12676b00270073de8d6848c0753f02008de12644478f0231f268b24b9cfca62282677df236d42c2510ad5d8c100ff0624ac97da65a14276d528bd1b15e17cd3296c4f6c414e6c4dd04d8a509ec6a55b309f315fb3beb0de1c86423bd881050b3628b62058a4000b136c4e60c143868508805880608080369f255b1214d915b3d4d6822b760002da3a905dd123d301914c07486c32681e19163cdbc6021859caae88c1152ba0354f29bf178452d3c65a6bfd266a17c797e7646d30a8524a2965e39e092525c3a6c4e6821fa250b31f354dd3b69fb0e9bc1fe7c7eeb0c26c3e58361f3061b06288cc0a215618915961054a69ad561459f185253cd91e0cd1bdb9efc5d0645abbb55d7ea719f224ed5a6316967c49358b5e31c6a6c60eddf2c3bdf7621cdd426774ba85dec565b5a2912ff473460ef48d614610fedc8f291899d63d7d0ccd00606ce68cfe8c4cbf5d8c83022f5656b266febf978b3314d149f39c93369dd32ea13306a02dfd7bc330952202c384f0876b00318426d87824911578b4a701cc206dc89796f207b96fa3035aa594523a2ba5f454d6d42c65be9dabacb1b02dbb260f7863b607b2d75f4bf0003ab2a59fd57a345ba33db5a694524a29a594522089b682a96db359bc9eb3dad98d4755cf877466074abf7b72016fcc37eb6a2c96d5364dcb82e7a7d46b3ca55667f938d6479bf93125b7ccd03eca8442c8177a7108063c8088222880c3089dc962fdb0b047b9d9b3767505316f8f475c79a8e120c843df64bbc965dec23ca656e1e883dd90e5ccc9474904d9846c52436fb7644d21e9f22cdd1a813031b2a6bb3c8d4dcfb0502e6f806ebdb8fc0fb266a5bafc10dd122fcf0059f3cb3fa05b2b322e5f84aca181a545cac819dae58190334e52ae72f906c819a7d4615c5e027286097ee984193f0635c172f3be164bdf44d3af08bbf7dac951af263f99ee7d5fcfcc430df7ba6f6e58880ffc1250a790e92320b990e92d2073a03f348b82fd99b51c1e1adb9079be866e0b0619348852beb0d4c7c0a2942f53fc4a85910ac38b9528e58b4a2525b5b14414cdb60d83d79d439d88da0f52be7c2731013287170e8ff20899be7628924493f843fd014b233636105831255fe843717516112646bed073224b9cf429f5864cdf2273a0d76632bd8ccc81fea2c817fa139903ed1fe85d5c585856324f7c922ff49b68ca332441c83a8a9c0942ce193fcc1ce8e951b20601f285dec5a5861a56565050249131ec812e219cf9a7e7372cfc43b7d0373640b3e8684e3cd64f03411fb437dec49bad28adc5c13c3434ca13886c7321e9f22959f379adee29aa2c7f1b732cda3c90a4b6088d14c9b2f10edda7cac2323195cebd90b01513cc1a6f18e29195bae2cc616e5175a3cf9d03c2bef110cda20cb02f9db07dcc21a9b0c835126e8184070b640ef4a138799ab563f64c1eb3c7f4215f7c9af583083a3381688b1d12827bf4f4993fc63088f829fef4b06e4a9f3cba753f795cae609953ac5c5ac8906ea11f5793878fe9821cc6c9824c671249843fa5cf14489b1e960a4aa79f3eaa38ca930513062ee82bba8572b985348bf20847494448a60742ce80dd20640dec075933dfb7625f13470d86600b01cb6c6a6badb5fecc786f7dcd126bb7348bf5a7ba69adb5e22a4e2c9108a7f7da5f952708e7ed0feec3d453620c8d4d0d3a14debca3031ec872c6cc2397afc671f738f5e3c5b02d8f9da78d39ce5bee9e8af357b421e5cbb89d204f100152bad84bdb23edbd235b3106df0c0313d3333892c024814902930426090c052afef13ee3e2c2c2b24aa2d32d7d79cd4a49cfc919334b0fe3a080cf95303d718d3612f66fb3ba7ea74c7b28034d17617f629ac6443f3c5a05590e9498737603e56006390742344dd3ac95e560882c0758a86ed031566de0c926eaee9ed9a15bfa344dd334928bf0a77e5eabe7e40c2ef728f7ef472bb6a9d134269834accdcc81868686864607d9d297cd651bf94243698e10de6649220d0a6f5b81ed6ddbb6ed72b709f3ce39ef762fc7ed9ec295cb90b0de7befadf7823666de4eed66cbc0aad2e5521a532435241c2fab0c236be81261f2507b4a856118ae4ea966751886a1b5d65a92b59b952452ee53cffcf09dc6300c3319c299491b162ca5dd6aadbbbbe99535dcdc91a7e8832ce2e1e1c9e3113c3c3cdad4e6265fdae29c3ae7040fa0a3e24dbef4a6d5a0ba20055e257de1ec371efb8d7168bd316dd87a1b5a9532d87eefe9cc56ecec6d5fadb5d6d36a43f3b459e766ebedb479b3ecd69535579c6f0bfa70cf7d7e629ceddca5a4a774dae0b0bc8eecddcf87ed9748c886b6dea3dff6cf8e219c79dc72ff5ad58d2ddbf969af8d0dcbebc8d66a376f423ab02ca7afb6265f5c9ad52e303134cdb2e916232f9292590134c11e66d66ecd9a586fc59b7d50ddb0afb79fd774e41a0d041840e00a629eaae86158ac77dfdc5b07c2f9054fb28cf3ebd63ccc0c2d820238423ae3ddc3ac700e115144cf78a740ee14e115a921f7477bf4dbc4ce9aa5b1016fd49686b78ffef66d9a554304617fa4a1c1353aae1a80d24984882f843fdea90426e09dbe0859d3a7af809cc1653aa280ac19657a1c73469f6621d36b3d70f8a7e737de6b349d3ec4ad0421a5524998330dadd1ad7a6db578b4b66edb666fa36fb1adf9a6a0aa6e609cdc33bc2197a7e8323b37a7cddccbaf66b6cb1427c2d0161a9b6ed9c100daad5dabe8c27205d19f9759087ae46bd6c4acad27a41308593f8190746a3dd8b851af5dc3383af2506deb03590e92c831b29455b1237bfd75cbbe7e44e1b8816c3f6ab4d29e365ef28dda3f854ac27af0869cddf0f27db96c3cdbdbe0660f2fd9e22264d75cf2e53b4220db2b205b2ce50b85c165a56fd006d81cf064b768ef548dcec9812dd0ed6a5f17c2e6f2d878cc809409294396201037f7fcd818e7b3f1b8813cafc572bce8c0aa9e798a3352e86ef245035bd4f2dd7ae29526a6422f84fdd193522684284f0c7c8ada5b54f5651e756872520f8c0943e8e57929abe2e71a0fb4eda3bd9ff6bae75ed6b5c3b389b0306b38a65930b4a5c6348b368b6ab626d73af303ac148e84342f2b00f9420f0099037d4c58a7ac81dd3c67c0c25c4fe94ff4230c65692bda90d96e9806260aa114ca36cda2a76916bd26c66821d47abc298570be4a94a792276530ab2416120115320e54ca9313955161848a2064294db294512184a620a9a92c65549841bb29b0f6059b36830b241322a42b6529134284e338aef33e2aca2913322413b2842c5b0b8227dbca1a15cc66927cd17e4f806c3f2f1ec917f054d61020dbeef32338721fc1ac5de25430881cd9a323f07ea3be60df8f7a6257c50ee370db862f40b34e8f80f366155ff539f2e572e2786f2a6d1dd7711dd7e1f17278bc77e32e773f56ce0a5d77cfebba779d77cf89aa8bb9bb26c6a95ef7d7e53670c471f776df94a477e2982377e36bbbdce5c2b181e8dccd73223d89e3a1c33820368266ef7a783c0e9a390ceb7c715cddb97bf55e3cdee3d864d7cc1da6b2cc1d87dbc917dbe46e129066ff81b03a7ab96c3afb71a4eeeea7e4c6de77f023b7853087e6ef328fdf476ec3630e9aa74d86d93cfad82f174cd6a9f91e563369ce111e691e65167974511a5d20401e5df30602c8a3cb66d8cd38f629d96258bfcc4a5f451c572c7397791b378cf361236827ba68e62ef3bd00cd1bd6e9dcd41ed1023393c4b9248fc4f1a0384aa10f24924244b95e650479e4fa52f72885461c72a848387e423e5b37bfa10cf2803e99e25167284f399447985964ce8c18e7111d3b799c4956cd9a494d2242750649754bd7da2dfd0d657969adb24a794733529f8c78789443249122331d4676b2d6b8468d6609658a47297416960b4c0c8d8d8d4d4c0c0c8c8b0b8bc5c27270bb5cf7fe29b5eafedaebaeb9be2dca7af9b1e6ae315b08e55096b97578b33ec1932c63dd82106aafefee9f52a66fb75aad45dfbdbb01ba35dffd07218660c003ba65c2e32ac424ee233c9e40ee1ff6b84bc97dc3f7c57d9442a35feff327f013f579fa57ba47ba04bd5f91b664eb6b8d5a61cbd43a79771b141e5779fcc9099bee4b783c857774bf2bdf99bc746ffbc0f0d224e528279d7c643a18febb9bc9bf16d822b54aadd3bbd4bbaf54db53f0b84aa160d4e994bb9f4c780c73f7d2f7e5eea411fef0abe6ee2afbed9ed8c557b880f142c92a0692211b9a18181716cbbbf0b8f894804858582e303134362dd3a9de32dd41fa518f0ed9d078312b30305c9a86ea05ab69a858de34301ed1212dd3c91b5aa465ba96f9a811ba45cb7423bc85e8ddc8ca07a3c80b70356424d432ddaa5b238c334a8d4ee1d7346e95a32bc4295680bc0869bd5f784aada84fcb749f14a41fa5d427d5d1e6a13c9487f2509edcddebe2d55cbc5ac9ab91f450b3babf4efe3afd85facbf417ca5fa5bf529eba047930d122ec2ebaf5bdb95801df4a9a86ea851cbd91340d8ce7152dd34d212dd3cd295aa69b415aa69b405aa69b402dd3cd1f2dd30d092f6fba88bc6923bdc5f4e91e0a87eee54d88c7abbd7de88cbcb93edd53f08feadd7b47b752f827460b05ffacdebd7b740b857f5ebc3bc138de7f6262f3e01f182f6241de53f0cf0b1c8ba52ebb55c23fab185e1018340a2205854125251f175e17b12053d029e8e4730849cbb40cea28293ca9e641c13c72689c1385c7dbbdbc7ff7a6103a930a426742203a73a78f3695e8168857239cc2a710874974ab843f13be275c4fb0ec7eea6e12674fb3ba97c49944b3ba87e2e4d1acee2471f66856f791387d34ab3b284e259a553f4e1f4e54a95457ada8543054aa17315631700c4cbb00291723aaa465ba1509e788512472256fe48dbc91374116e7a0432dd3bdfbdca25b3f31fc9edffcdde791a6f158907df769a469ace0ee73d63460e09e17691a2f70f749a469a81e53bdfb1cd234563816539d460c1c536195c538472c962376448e98ce0ace113322470cc70b9c23468196e972c48a68994e358448919991232db345cb743807112dd37d0a755a84dcb56f3f08cf9d0ed1197943c2e31d610ae2a1dc7da59b1e9e7413f1957295a78e72d44f7eba49d7755dd7755dd7751d11dd5077959494789bc51d45fc9ac571dc4f62aa59dc4dc455b3b89bc49228deaf59da4762781253ab66695dd7755dd775975dd775972c1dc6a9a56e49c1939fe7c72944440221fc4624ec6f5a84dac703211ca78f1c1af2199a43524868484e1e211f9e4d8bd09e3ed62d9ced3fb1532c687b771d53c93b0e7bd934401c8b81ff5e44d318e118787b229ac6098e8158b59d708ed8ca643bce113b95ee635fcbd8c764cb70230b524a29a514e7902d636fbffd20ac1f1f6ab79f43434343424242423e3e3e3c93e7c3e3f56a58a19b1b7278bc17a778b6be55f0563fb12e150beaff7429a614d38a6331eae118c5aac60a90371e5821ca115be588a572c44e3962618ed897237673d4fb85a7d4ea2687e426e5c0683b292c5ddef4fca67b7753890b499f47abdc38add6969952defb7d61783aa5562dd3e1a442d47adf46ef4aff489737a887240dfcbacd5279236f64a3e8c8eb3aadc278b14a39a1a8a870787169a12165c30d3503a09189a9a13583a2230f85bac935a8e7116064c3a231d2a184a25db22394e78db812a7695a7753dac3a6f1607b0754693412bdd0abb80028aa69dd4795b8d1ada352b775b86add303407146a2b9146e0a84d6e8c92a5a8d2664b288e725cdd6cacd48f99cec900c0fd6aa3fa1a3de14efa1abe00f8385a7a8c7ec4dd3b6bc66b10c05338c63a0a8ea57ed218857750473d76b2b2f569e9a8c63ba59700f058005e1f93f17ecc0493034b0c136e7454e9a3d147a731f0393c06f3188fb1dce4b11e78d8a10031efa8d2bdd13defdef65877f131fcf0b1ef3dbfb9c9357498718f2afd9ec3201efd7abff7f62b8ffde063dc7b7e5333009a1900600160eda8c70280774ad79e038ec1e0d1b56fb8f3aed97bcdc6b6778fd958c52c8c7a4c06de29bd3e068eb1e09dd1eb451cc378c77bfd0a5eb91bd65e6f861bfa58fdf658e314eea3622778a784ab098e99f0ce08df96c1240f7f20fef0cec561cb4c0eef68f8d432d3e29edf687d0fecf45b7e8787c942054fd67aaff6711fd108699468a8e6ed69a82616c2e4f2e63d3731edd8e1b989e9b8e9f94d09dc7278602eb9c961040f0f0f07ead5b86e04765d373a81262612380a4b28d48b952a8542495181018306961887b1226219325e5c6e60c9a8a185b3c1eb4ebc8dfb380d070f87da75323102f0340d2607003c1600aeb394fb4eb45bbfd6d6c2d55602dce633b68fa6354307706bb4cf8bd1dbc762f5b17bfbfa187dcce28a29ae9f57e33ad07c6fb4027c87f3e071b1eff43eb6c5eae9b7c7bec7680f8fc562b1582c56dff39b135a2da5d6528dda4bf14eb57807f7fca607bc233f1e7628c04dae4183860e3468d0a041a312c06646cd00685aad9956abd56a5d9918010400003038e090030e38e080030edf8bcb0d36b4b064c8a841860c1932648434b0c4c0e261c058810103060c18a793f7fce6c54aa59292c23194cfeb38d4b6a14eb6d4f69edf9c4c4ca5908463e0e8c3f2033d5cbdafc3b7f338fc719d86c39dfa8b4f2dd3dff04ebdc5ab96e9ef54bc6a99798a532dd397dfd961d690852725ca93ddf535a8a7d9b69d1b8fb5c672bbe8b4c2939779943edfb2d801cc0e7ae0334488ac3dd08320574836e404b966291b32050d9e279e3ddd01700890213cea674e78db157d65cb3ccb3887f28a6644d3344df30edbb27d4e8e3d6ce61c8b736a35526bad15e7e49c5efac973727272c2d1bbd6ebace4fa1c6badb53627c7e4a6a360336b46344dd3b49c1cd2bf73da737260336bcfb938a73b78ed1236b3919cb9050acf2327781ab138e78473ec4df014da70ce9c358bde84734a780e9944745256b2f61c1d1859c33961bdf6099b791a9973ce89e715233ca70071ce87a70f9e3f343c73605bae7f4e3d6ce68aa78f4e9c40824c22b9e297d5fa38b6dfbfaed58e637bff958363be9f83a3fb7d0e0eeef638b66bcfc131e7b50ebbea1226e81992b5e7e0e0b0ab4dd0336409d71143963041cfbcaed933640913640d5795982d84924896b947b772ea7974129c1138ba55714ea540b7349ca37d3e873ba2569d948e96b3fd9e7ef2d0c7b40710515b39ff61b3d9b66ddbe8bdf7de8b398ee3388ec31cc75d2795b953fcd299b90f9b9dfb2eca8222559022c33a377ee9d4dccdea564e77cfc33938e7fe0befaa5b398d6fbde2779a274bd47a6fdb344dbbe3f6bb6d9be679976e74dbf078dfef1ad465ef689fa323f7b8ddbe7ebbdad5b4eddb66bfddbbddfab1d6b0539a13a42b08fad6ea274e5f0c423bd55a0b42e5033dfd973dfa519c8953e7d551678f618342d364434290354dd39c306529e381188e4828d8a0074338c3073c8083263407b2a8e26691c597850dba2c98e0b250419845cf48a88bcf2407a26cd6fd26dadae2c4305eac6851116bf51777818949b15ce52a1aae7a0d385c060de257a953f8ddca92aaabfc292914d4c989061935b05a6cb8c1e5058717971b6c6861d5208306961858fc0a8c172b954a4a0a0575723ac2a4c854542a0a8598cd662c164bbaccb003189632ca235d58ec22c1541ed0ac2334dcad442ac6858f945112f550d151c283054c42c3d12c1d7a56b4d1dcc1616dc3234c25379eb88866d15a3285f6db0d777978557f7e7569fa8bcb6ec1b83cfd1215c3e5068c8f22fe70721257a28d788af9ee6645396d105b44d92c19220d22cb5442b41d99df8eb0524fb9cac3abf0e8a27ae92b3cc2ac6efa0b3cc6bcb8c961e09106868d148ff218d88663f12b305e88a1f8ddca922847fde4a79bdcf492188a97af38c6c959504e43ca65a85ec38bb35a64b36cc02ccd62d520830616f1bb55b260bc58a9e0141e6d50f884c7980cc300981b9ec7864942829c1fefe8c9cbf99dab5a173b62ce15d78809a9e330c947ac90f0612a241a0e53c995e545871558ca8a4afe379056483015529571984a8f2cbf72f9ecd1acd661a51e96b27257f229152e7491c01a0e53c927a794cf249ac5ddb5f2e2210e87a564f0f212a6926129f9c3234c85759d996d384c258fb0cecc2d1fe78e2cffb948e2612ad9c3e30f4bc95dea2b9f3bf0278dd8796b82b5a19fe8f00d75144a94718cb3a456f008fe3bbeecd6572ebb25e2d1e4a3ffb25b38e091bb76f1b25b29783cf949c5058f28475dc5e5b25b2f7864c13fc4c0371c45dc6165738af95caa77356dca4b93633cba8c7efa0a1e61567ef2e331e6475dc4234d96c74f3d05c778ca5530cb55ee826fc036884334abdf220ad1ac3e4bac419421e2a081458c21aeb09812c5d3c57045fc6e95305e882bef2aa26c568a984241d1c86699cc69c2e32de1bebdbdccd00742f2288b8ab8e0828848899224499020191a9a42346bbebbf7effdd1053cfd08337afd18430a6f3fdae850faf6510aad98fc7e94437438673a999442d208fce67fc54d13ab2847fad3a8fde4f21fea921bc1a78ca4ab5c96ae1a4dbeba6435eb2b91a5596f9698124fcd9a471151e28978eb7c098fa614b2a18981d1a19ad6c7b3972c63fb6c971f65110bcbbf5aa5522b2795f086f7bb29b9e2e0e8b06409137a806d7945beccbb669e459b128aaee091a576b2d6c45a9555c2defae0ba733d3cf0e3778f0788c7d1c12448b8f4313ca9844f3e9a5e3a3999603ca65ce523ca531f4f8efa68f2130f735604231cc1081292a084b9042634610b273c010a5190c2149050a10a56902ff4f30a58c882122d6c810bf2a59510c252baa8b388aa94b0bf3eb8773dbc7f3cc04e42a53a0ee9e1fbdda3521da7d43b545aa54cc8382af8a6e0c993c21f0a9e3b50389c3d277cc23309933879a4668fa984c79a3f2c0f8f3c22910004349b4d21cf8a6640b359d1ac0868cec639e7049a33a0a2a2a2a2a2d96c369b0101010149987ce4c81198dc87e169d68e247afcf0a359fdc154b26b05874986a564174a1f63d17ac952eb755eb5cb95a61d47b3b4eea78ec3a30e29f9e27165c99233e411a6922d1e7558b264099901cdea3fa059fd229ad59746b022491ee5119eed42746b1ad902c9cd2895e46f4908e7373c79ba19d0f7c891f6c932860e95d902039f2372369bcd66b3d96c369bcd66b3d96c369bcd66b3d96c369bcd66b3d96c369bcd66b323720a1909b3a2a2a2a2a2a222393b12f637241c515454d417a267ac66b146d64f8eacba290aad94c6f889c9f538fa1dd331bd8978418f53f98e6a3512b79b944827d0e3beef8c52e752606829934a25e53bdfe9050c4f4399c2d177bfd39dbe78f1d88e868356c0549b542a5f4aea3bf7f4c50aa5e2d88e89ca4ba49bd25058beb33a3d3179eceb0e7a8fed682b1abe6322a9585462fc043eb69322dec3f8f6d88e3d4a7f670785831a7f5fcb340df8e2da3293055712bea3189805c4e187f13d7cea44bc4adde3145e59ccd232f3da0adea930f0095fc7dd51f56581b73ae5791dbb226b5c72498699f28beff230be2e85946127b9af5355640dacaa640dec6b0e8592e775284ac3c0afe6e59a1996cade75669eb02dcf1a18c9db4ab206764db20616ca1a9849aef1ec3f5897670dcc04be5c2b197692e775b4dc309a1be6bd5c5b86a1724f1898271e6129b93fba5640acf296bc5c34c35279c246b9f10853c9f3a3cabbcc128fae95ab3c0ca4e48ebb9bd52ac5231129b9f168040f0f07328e6b2ec9381850c9138f44f0f0a020cb7abff0945a9d25af2c59a2852cafe39b36882769bd2bc5c3c393fbf57ae98cf276d708952fd7ddb5f28269d9fbeba5e365f02ed2100f4fd631c9305e2f9d9b497fe98439bceba672293573e92f9d2d9bfed2216593bb5628f9f482d17cfa4b47cb277fe98019751789878727eb9c649417ac6694bf746a4efda5f3e594bb56847878b2ce29ab5cc26c56f94ba7b3eac5754cab978e299374bafc82d90c03eb74065f8830565eac542a29f2651e259e8828f265fe24a2e4cbbc8978225fe64d624934912ff3a1682289a59118829fd77177b35aa562eb7831ab12ae1595c3525ca49f1e951b93bb4829ae150facec98dcf4a4dc985c9ec564e68df41def61974ca9c77682b687df219dd47291543ecd7bc984f29defa9cba7bc7a9392e9f4d80e0a0eea77df39394acb455201e9773ab9f79df0e05d2b23d5633b9f0dd2e93c5f323db6f39de020eda3ef80f75ca4254b96e41f9514951b148eed98a0782741386464fa1dd2518feda48437e120eeb19dd477144662dea0be333ae9b11dd34d1edb293d0507c5765238681e0523316fc2c77648f71edb018faadff97e82919837a3c7764e137f58b68c0907e9cccce15bc24117d770c3241c64716c67848370c8c81a067150c53b1f0ea2f8849198371d0ec261921bbf59261db7b52c6c45c29619e54b5d47a63fa55ce53253ade2d7eb757294e9a517f8d1bf7b77275b9514f124a2a04e4429de2f0c49e2aa59dd07c5b3441711861363686c9a95a2a9d965f0b620842bde56440acdf112076f23b2fd60f6744bf711ddd246e0685617d12d72878e699866f5b38e712706791e4892fc72dd9d212274f8d09e9e9949ba65660e75cb113d338f74cbcc9ce1e8d62cd2ac9e99431ed033f38a39c50f3d338174cfcc1eddd293c7cc4208a511a600ca2fd78e10a783e7c5b96ad6e90ce3b06bcb77ac0143777c3671bc85e121855a76b79c486641b297a58c084746b35c931c199a1de996fa197056c46648cc15dd52c129baa502e9960afee8963a032ad18347b348f74251663049cf8c880cf5cc48a85b8ef4cc4848b718e9d6688a66cdba350ad2ac0ad433a39e20e014a010f00a50081c0212018b748bfaf4cc88c747cf8045ddc2a36740a26ea9afdebf8f20d10848b72856d19b8e33ff934365c32afaed3f2638160b9ab736a569281dfe3131e1b08a9efb8fc9e93193fb9f93c9eb4714bb662ebdffa3c23113ac9a5801f24605c7824c78042465c323a094c5a31f281a1ef9a03a3c5222472c88c3231fcdaa41178f7a34ab1ee7086a3c9237f51bca8d4741a6107285d0102245bab5c516478e6c468cd8d94c2b52a42342841b32c4fba87ed463e463a4c4c867f4a35b40dd32bd7e04c4c6c64443b3c5c4581818cdc5a563b138963c3fb2e41124fa0e72516bd1bd6017dfc713863b4ea79e546a94c4b8ca2011fd1cc1d13533c52fd7a8c355c23814c3b41c1df2c4aff93b45d7924cc22f57671d12e945afd3d935e71932e97349a6a2a437ebd01bd30cfd9a778559a72ec9d3c6ec2293a6e87ad6d132ccb5650aa399ce3264d249e2a883072334d283108e3e823cc2500ca2a0a8e48a5a6a7b983a45230020002000e315003030181009c482d1284ce238d90714800d8ea64660521888c324865118658c210a0002880100c0108099995255a1ddb2039b943e0405eea5f44434f1fd11e015228979692bab40c017a25ae0cb7fa0c8001a1ee234f8f26a20c735409aae0df3d557432e32b92793ca73058aa72c21ae36fcc20edcfcb732c4412d2a9b6b1d60f9e2a60fa0bafd4a6c4a4bda9082407a0a224f29d0965230dfd67cb2fff5995c732b1b5c62f0b2c199b156ebc40223e8ecdfc58e4e4d30c5362a700cf0ac216760680eba60cbca93f70087fc6c58e4fc4e457f16ea077cbd75da136e233fad461aa7f819971f8ebf642479e18020d1e298116ef473305438a228af2e75cae48b017c57019159fa77c2de9063047128a04fc88718738e2a8a7e0b46d3d6972f8a403808f8f1bdfb4f6440ee3a6ad2eb8c28041478fb8d369b771bc6e67dcb3a578852ef3bc5d1b33ad2fd12456f3c5853c7dfcd470effa8c175882b5d3c1509fdcb4685f50c55a277dd1f1dbe060fa6884139f66d7952e8da0716e177b52a527a81c00a8a84a32dfc0f8077acd4ab15c1c2497bf46aae55731e0bac191b2804700aea303088e2940ad5219efffd77c6ccd310c75d3bae952a6676a55c87bd64d426c8ebfabe078fbdf2a7884bbd18d62746b0eaca3be9a74eeda269e18488aa992121ad1deca8883fea51b3e7c72c6b1b3a2c1e97383e7ddaa05e6788093725f2d132383a081c4b66fb6bae338e8d80b2a3fcb03e99f8b4aaec3e191167dedf1071ce5b88c4fefec057e41b49bb49838c88f252c022f870a637c74aa77ed949e8ab89f88cee53eccf67604508fa35c48cc29d20e1f5bb0d20ff0980ccbf6253662b6afe83bd7cea5047b693d8cac3d94ed08a683b79bff86eee59a289a82deeb98c20c9122359e4f5291cf3c3c4bef2b74fd03e79e500109e325b28b6605620c659562871847d695be70c256d47698384fbc459b1a49e201222396545d510b63ab0b68f97668c37d0c66b2a42ab1f678384e01f391f344a43ef6503d8f87f8fc9db203d9b88355d26ba155a1846347911ca5f41268d46cb2ea2d7a128fb7aef9b4bc0d59f66f5fb626f6041bc54cf340ebe05170fca87a414a23ababd0466b0fe01737b037a6c2d36c425bf62652e433995bdc57226e5856b3331be8fab0890070bb019c99a4ca13113c3c8cdc394a860651092e6d4e9d517f3a5ca147532fe9db2621f5faa58f0ed117527f83dacb03417c4095039016690679fbeb66cc0def1c3855b9ee12f94e8236f0a2e7ba1efd19c59ed99508359c8d9a1b2c46f53c6e27e47e9732cdf914f8b3fbac5f13db1548ee825d8047dc13cb51660709306ac566aac2e3232de161355a737d96561951d38c4c9ec7d1b4d7d99e03da086c43c4364700bc19b461766e76309c49efc4acba9472228927a085df0eb8aa822d63a2fe4b1f43f26948c76d73f4f640c10ba0ab6ea98bee58c20a510a16a5dbc050d03615afc934c01a817d331374f3d9a746668c33b7238b7990b545970f0b029e392931c099eb1d078297320b375aad63967efe11267a9c06aae63a80f0d72b79c5ed63c95f0dcb36860d8f022c2eab847106d685f946b308e361effb9e9ef2a42f9d4c4dcfb1560dcf7fd9b8223b9e31d7afcece764a27a44086aca13113ea580e9a02b695997c3d9d0496862b154945c6b8adcc44dfc8ae1782883b15da1aa902b3c4f8750792b8e8a41b5224174561c4a35a18a15d3374e5ce7559c310d44a18c542b136b33f8a50a05ead5775e1789dac369eea5bade939312ca0d3ec56c09672121be24564245b8442788ea0ef08588d823877cb339a6f443c33dba743bcb161f8ab4d0852401ac3a3131da16b79d01495a189b25328283c3ac8ead6b00ad729f402d86a353d3db4f0519259ac9410bee464f5d0e9cc70ba19d857d9e03e44daa7528dedb3ef04034a979465cc66f718020e0d7db32660dae91d5444b0117158cfdcda16d4761dad6851992eeae4f498b6c56586d04703f0c289788211c843586de53623e78457a3d9fcfa661839fddd6a60be1986915dc5e6f50df9165bd9e2ecd64ee05ea1ab1881b218c10156ea7064e8cd8c04266ca614506584ae9b3e7fcb44105267b4fd0c6e0dea02a88d4b0ff941954d5aecae6b0820f73fbfd919f926a920eaf6ee96e8e208693ace00abcaee4830043a8c6409dad9122628fca9f4d0dd0d82ddc5343cd508cff4e175e6c759a2d325a0b9d878c6d026dd88194945eb9022b0acccc9b823c492d30c4842f1ebd33233735f683525a67b2faca46424e4bc51e41eb93201c0228637dd23032e0797993d6a999fe6a31e370c82fcca833915b68adc5a6df3b424d67b5cc38d0bd631dc36205b89ffc4739fa1226b4d562ac628de21f1ed6d11f3dcf74f3d5bc8329d146a9f93522264a232bbdeb7f46679025a0891faf876a113d1d9c029e0e2f76bd6a59574d6e61b5c105428bea17ae9b365bd5be6c4b811557ecc552d574a93a2016e719a7134bc55173c816b3e9b2a2806f8ab918c54c646338a81373828d30c74fe97d8a12f3b82198eee6fa56ac05fb89e1d95595abc4781d5669f723a5d8b2154452475c6eac369410a4cac788773c48915f73f9ccd06f600e9b0dc287377d77f7e0bb450182311b08ce990237a1c8a6022e2f87506a1a350979497e7a48f87ac2e622edc9800396fb45932416ece75531d868e5ee939482482d64d2a30aa8893f206c6ad81c2eb533997c0d6a6681d2c1cd8e313be08ade140cca85fdc96a7cb0e62fa324f410e0fcbca975ea54adc758f7691e8aa21db6556d588d6592bc0e460e86c35a23f9d747242258b1f0b5d1dd7f45bdb8262d5c9ff48f3e3660ce4a7ec6965694bba36bdf583a62c9e071dd6513468c9ff63dd6345e70fa79a5fa465391e23b9be833fbca49e7cfd6db3714da28e06da650767317879075b5926e26bd7bc6248f7197b124f0647d8ca93a91a217e0824645be6e09f5ec65b49943b119f2e1845a4bbc248322208b7e86b8c70b1c75f80995b31cf8712f053576f8b4760256bdb99f7e6424eb83e28957e71164948ac0f591c41d5daed2ecb92c7103816a094a8e835a5b7c57a0ce3fef839cb3b2ed976987334f22a8440a91db19b4918067e6d0a6a80bacdbb333e861b1fccc037e898dad56dfb6f021dc5019efe8655259cb86b630d5ac25086ca239d2189506a2d39f7dcb0a914ffe65be7c95f8e661d8da159ac595b4b8cda5becdc8efffc76f4719dfdf6de90ecbc4eb29ba015b8e4fb3c3f0ba8533c85340d328882eecb984927d467a98c358a586331d1f8293b066550ecdf53f9b58b2226f41f8c446306db6d8a5c0f93194d1c8a456491e1c8025af2a74782bc84fc42b5be20bfa411dda260ee8bdc4db5bc8f710cd43a86837da9c17cdc7625e4b8ea3e46f1cd030689358a82b1c7844d8f5e104cb60cf7c1a5230f486a650040655e5d28b0e0c2239432c1a8e3c0efc5b9f183ebed8eecb6c18deac16cb70250b7d480c96197cefa183258f70243c96396082812047775057d17de457c1f764f88dc1697cdf7637530618f95ff2e403703e3a5318b382f8c907db2f0c6cab8aff1c324b7ca39280b44d822b56765ec878f619322ee653bc656cab8bbcc93000c09c726de57ceaef44315a2a25264bdc8a861d76248b9bce9c6a73e37978265cdcfd4cd55d2f3a31034c6c6285f44ea6f9116692f1e8390233f4ef53ed42cfa3bd0ff5cf1c8440d7301a02d7b64b625974800ef5707266bf369f3ceffcaa58c214bf1d7ec95f70f2b6dd37da2be7479cd16422701a4c8578f0038260f92f9f75790e50eb8daa60db50956161a9361f08ee1a8aeedaa393a6d54405398de0ef7e975b00535ecb593fc3732c88c0459926f38ce07cfb8299ad5224f60267c84f6df8d2a043dc85b10611a9fb4af6aafba9da1629f8bac6e87e72ba0e75cf68b92a4dcb2fd4f26dc90dd647c96ff90c7aa833c8273b0951d3468d701defe41a2fb094dbb2fb65fc951f2575030aab606f2b8a451286bed9bafa1b322d6410b171d2355d3122d4d058e7e0664bd1cf474b790b8e38346cbc032eef8913b765716bccb38808071596891a006230056ca014ebd8bde8842b70605d93903b35ea5378a69d9d928f9036e74e7fa96971c996895ee857844a168eff8ea53c4a436f66709efb118ede59e0cf6a6d287e03274f6379134433330e3be4fe72092674c986c20b13124651faaf15e911cd331de82a9bb313bbabbea4f9e1dcf03a968da126651f0f40ddd9fa9ccf392ffdde0068deaa7725ec785a4159d586a8535dba730fd0674fcfab444b8d5e1f029cd72f0067affb4d2a0f11d2802e054418e1f1b0ac012a56745aa4de57bb52f3003ce6f1745ffa2b8f2006daa64bf301b505e525ef952dc29599e4ff75d603718b3e41239cbfd93cd05348cc2eeb7178f3fff7069c77811f3cbe93f28db4a6ae12acc71294878a14ff4d91db8a6ba05f4bff9fc7c61e3970c6ebe14bcc6d60f8ac9754627c85b34a41ca04406c56d1d304e98f3fd2df21ce939b482105e16635428b8c8c859415293b7ad9e517cd3f913682129e4b42d3167b4a11b3a5e9a8a559c4917d58094d34c0e6940bea0d502643078258ff0d1067b407f6c42673915bfeef4193dd487a587b47a9c253f7841fc3718ebe5f96a8c0ce79300f1056fbb94d810a148537b1259703bef33f7faa9d6ae9119e2864f875ba0a080b7cf3c9d630290ced3361cdd2447035281aba146987709259c7e194f0d502f8239acde675f8b9e691ec081b74913d701fc1d2f6a4148b2677f6e23ed7e3f5a865c095ab11f152dd67f614aa1ec39211119f6a515816811570f6568d587aeb794f3ea649baf4c73ac4ae5e11d996d1a392f357c30c50634559e7477168e775038fccfebeb2532e878dd742cf304d2b6c1029ab85f6b090c7106eb45550b1c9403da07eff03c0c094b1ab55c8a356673c04cef8d4b5a74ca51235a366159c0b56a6c933c015a691b32438b5c41c7a7e06654bd6417dd71a22bc9bd4ffc067d97ce8e30031942d571bf153676cf1fb7c8ff67b0b687c4a0b504f4c6575d8744a4d8f83a689dc11bd646dd2fb5dbc22507db39bb95504d8ead3f97e867d6b821355a9743188eceb5b6af75c22f3c6b6caf5aebc0d1def30f59cf9cd1a2e8c306e047435fce4fb9bd7b2856b7bc524b4d7c5eb4a6d286e4a6bc12c542b5c0eeffe4d0411f08dd8edd0b91f6667f14f5cada14d944067e923d2da84bc06f71dbc9cfc9f1e727f4691d28becbe8821d0bb2534f31c2d8c4773e200340b77f4745ec19a1c5779ef009d8b3de3941f8f38db5a081bc3d65516cb5758f70334f29bf4432816406295c249094a5e387da5fe38172028aefffea4fd4f5b8af0bf09e3499413d60a0f3cee9ddf9e4bc4a60244dbeff17f25961105071027330d942db92887d0011eaa6887c03240402c29790a4c62a0b9dfda4f2f194fe9341a5ca673061cee50b6c6cb2559f01189087fe8959fe1d8310ccb1b126163818d64386500828b63d48302fadc9341eca6d4b1e26b69a802985c99dd5c6cbc76f7c5122eba243acecfe865c7e076ea50ff0bb409886ee6d3294f4301dd1718c354c622e9d7af20550baf7b0794a433e562e079e48018354031b9b54322c5c3119a8af9886ffc3ba92c688a58e07aee3884d9e13157225a73282de714e1a0383c0983b8727686d5c997228d4a37230232c728a2aec94026808cb842fff9e3ec306973ebe70fec47bd23b8f4e8f8482481f900bd3cfb40460a42a46d9fd10a9d3587ab038764c37a9aabfa0542ce6493d30670290ac74173adaedec52236860ea75b04f19ff7de9fdbf67b6c40d3fcee5fc506009e45bbd16ea59bf02bb240c77c4dc5926900187901626a2e9b825579e02a6b20040b1d7cd67606d3a12f64c6ae90b4cb32d1918032133e83bc79da1fe0c910afb950ceef42c4a44d3ad0da166059282cb743ac5e9dde6c2e3bf3ae8f187e526b3559752c2f59506b6584dbd24051867464289034c6d464ac2f696fc35607cd1277386e3b926e859ce91b43a07c210c66f887db2900e2c2023d70b25601b91b1a4272592475dcb8dadeddea4c0e7bf30641e8ab4180efe7d1e6abbab62c571ce1a760c9e7d1298b60f340c107f008b0e6f0b50bb9d4e4c2d0362eb56376ed7d618435718a28340d87baec7337144884c103aa1689780d0c0b05ba74e93082db8aeaaee2ff652bda99c166c7401b69d0c6077565cf405a14cd1368673dd2a23bceac6ef19c4eaec694965e2f4d7a05adb95f41fa329c8b23b4e69832e9ddf7810c3511444cdd5a049d531c82cd50e17fa63d501a5e500610a5696fa7e6310733929be91bb80047f45a540f055baf6be907485d85d9a5d989862cab4b201cb4d8463a66ab44839501e663b0a5097c3513bc0b83f28a035be4bf288a22ea34d2deefff5d10ee42c0bd5f1fa5de5e75abd547847b54e771f1d994e5b2426c9aff11ef32352580db5af90d7df80983bcad2acba8865ab22af8dd04e6f610657a88370febc796f465aae4bbb726af98943e49693bb8fef1012ca20963987a45c024b8fa042af8ad82835addd184ad51624c4142e8a7948b326dbe170e09c523ccfd412e8f4e80318c5fb1258328c520a20eae99a51001a6bf889811e9a19c105756cd49d491be4ed304fa4ce4a64fc4e61a45f84c08c2e0954329788983344c950777b90e67f5a36ecd36d03575151408882e0294144b77c8aac843d5f1987b1ebd12ccf7b8f00bef76c50340de801a50757ae630356d142a04644361244a85ea830dedf697990aa74b8cd977059b3e56dfc0b39746f3a220cd8870a30a033a8b688eba0b33bd419f4fcc7f6316fa7842c61e8f2ed185b90247d7620b31549fef29bb28c2d41c924d4488331ae8f1cb4f82c660330d62f0776566fd155c554e01dda60e091a6558ce84f4661a46f7ce19e0a394d0a3b8949aad7062c5dede26c5c2c1e454085463fc978ab80ac17c54be43440b8d5b0736a426ef78342d535da4110504c6bc64c5dfa7486c6fa4cf5a548650335a3a0e4a3a2f21baf4ae42185b14cd0c8016b29ce63b9d2a2b5b2b6a21778c1625639e22f83cec65b324ac9c8251d0399c690d8d8f121562ca35494087aefc0366d12c59faa470904bb10cacd198db8e5d0c590949e5a602b136e3fe3a2db7959dec40181f63fed4231c151c8eefd2d81fb87db84d413d4b7e405ef79de1c716f311ae0dcfa33c3094fa037aa2be200a96791632b579e0e828e19f9f232604755ab8e88e9f07e81c9b3a663ba70a572295d026f6ad27603a2347f404d420994a63dd4cf20c7e97bb210453b3c0f5b4569a5150e0fa891c306c8c5aff31226121bb0b3e0c28b3eaabe5f5d8801465f9eed30d12292f9889e34d96b3f4cd6ead425322ea55f728eabbeae7495bfbfb2efcb8cafb648544b82eaae2bf8b4d7551fc773fed5c74a320638630bb39d4e30ee3010a270b3795572cc534a195a9ed4bb04b012d0fd87945ab41064c8af45b4b5b133a7cfb95d1338d0176b897355a5de286ec19b2113612bb1c0c673b1fd43aa345a573f906ce6a33bc804dc84e2afa241a14b8bd451443ec03f148a87021b32daf5a692c55e0164889e0351e0c8539245733a3dbf312654ad59fffc6eca78eb97dca327c2df7cc4cf4bb906e92b246af7a937b1d8094896c8b1313a5789884410605c3c52daf571d52c1e3116f25de1ddc6b8f3dc75c2ed502ab24628f7192952801ea0617be8e9548b6dd7327a624c77c106e59a19bdf6186a0770cea25d26d4d03be3f6229e919221823ec61a76ecb86b3c1ec608ce0b9c32cb609046b8597991101aff0f36c6c820587a89820f122cdf989a9d42f12d62ba25f3ba03ac833f3bafee1bac40ea9648fcab5d7c727d26ad1f6c67c9ebd46d99c77ddacdc9715391506afbc5025561d56bf483c7f8bad2d030b77f27204f2c5b9b244269e03ac97cfb3704374c548feb4bf4aeb9b52262442b282139bc55c30fe39874104f11b2b902aba74eb4430088b1c2ece2ad0bcd751a3849ac0f4ac0f7a9b26a7503e5e0069152e36590c401d18a70c7b330b90536eda54a17a769e1e8100c5efd00cabdf536b122e499e248d1d5a8f3464cc1431aa8c9fb455a7d3cdfdea5633cabaec16faa23fdcf5c13423cd3f0861210bc5ce038a321200e41f187a10c80c1547b2f089444485a5da02fea7d2a1224383fb63afe5cfbb9c90f4dba1a71586922e4ecbe1ec4ecbec850d648c6f94c9efbe10ea9b1844d23e1aec43ce4ddae84fa32392aac9f49eb5bbdc55922f93b3e3341453797f8cc0a60ed553932fd048324f4434006e1233f2a7ea76607b74f0702acd6fb93f238ce461b2f92b4850e3023b8b07cefc374c37f1de1315ad72cabbd99489ef3babd02a6732a7f4389dced7711969d270e4c13c278a0c033218879e9e1a2448ea40cd107f3c2178c913bce12d109b2c3742a05140feb4b19490ab74af5669284437e0639b92837fb946e4676ff0bc75f8a181a258dc513aa411a073ce5260bc9089cbf36879fdde426f69c7c6d923c570d9691065928be54d6996415facf95e11504db83d514f423bb56bad173268af40999e2b213406401c17ebae42f868dece78d0d76052b08c6323e23ddb9a169cc8b0e1596f15a4f1894e74ba5da3320feb60a2d10161cdf0bc5db3ec439eb2d75b538a6d578dc725b1a8611dde73a8c40fdf9a3e663d2356c2262a3eaa343a2a125420e868443dbcd6d78ae633bf38426567148fd1b375177ba0594b3cf4742c1078ddaef167fade811be000b2ffaea72589f11c9434db71aba03a80b97bf884d7837addae7c46a9594c8c40b94b1ca6bcfdb8d1623403c2c2acf7009554091477e9f4c19c4c8df594e0c9307e90d49f4c1943363891f1003957ab2fe02443d25bd6b8330e793840ba1a2ecab5c43dab100b295510c7960e91400225ac73a0d4e003474a64d4b58ccd1493e9657931d7e1fbaf10ae3e9354de89782523d0355fd7c2732b46bcfb887a2724bd43ccf31193c3974089a9fd7723aae4c8b43f226f59cc907274c636ab83453ac90206d08e041a8d09de408769883384541fbe3e527a5f098fb0cb6bf9e0d5fa9d01afd34153f51fa1333d745d004d15f8fda88a23450a7a1db38d0956704bcb76a2398e26600aa3637088504e752aa8f7544118c2528292e89b90bc2f9960b1660294cba4f2ff8c0caa3398f7ddf1a09f3f0d7c90a64a554ad55da8c76c9e8596dcfd212996c9f61f13776b0ec71b90514a1b37cef78c8eb33d87835b64ac4a8c3dae7d8fc66f9193c36d6494928f1bfffda3e369a227c5d1a243b0f0437b2978a1c3293560fcd6989ca9cff565514e40bbc0c5ce4173476c6fbd71fcec522211626bc99b197b7d014b0805fa638b9181e64956f438a708c4c7e6dda82d00b79ed1d2d1e1ce37d2e274267f95de4777ab4197da17531147af23d22469a446f1f481c1077dff8598ed898f073a4e693de65abade292a6a06ea8134e3bba0f3b9c2798473dcde034724488df3c6fd95be783f08241f6884d9af62132eaaf528b5a49a840612ab21cc2c3605c13d9dfd9a69b406049b846ba4a1c3c65067914909c5d299bb28046ec7154d2195051182a5593164b0497537c2a8ea13337e15fec568ce36fe2a08e94684067213ba414bcee102aeb13fcb6d61e862368717073379e4b01761c6acabc0f2ad41dab9d5719e4bf2bba01d7a7a4b1f6d04a1901a58dabf99603474d09b24e23d52804bcbbb0bef9602fb4847b8772af0b4f126c11cdec0070984eea50696d6df26384919f22789f89e34e0d20a5f449ed113b0e5d67e3b63b00044b4fc0a302ef8e91c0e483237ff1d6b490d70316b06968ba69584c4cfcd1c8d3946d6d09423612bfb703cd05b8b62a415c0f18d551a8dff84b5e8e22949626561997a10072de339dee505dd2135c40af20cd2b871b3486ded1422b1ac1d43f3fa3142d21e951ad98d942165ffc99b173d0a2ee78dc5f2e793678b0e080611bdc385e48d50882027e7cf7f7a0559ff5204bf422002ddb98d42d5307f9f3bdb20355764a2cfc1729ab80328ef0cf9cd042ab11f9624eebbcaa82c2514f43445ac5d7d30f066e931391bbea14c4bf85e6d4efae53d03a5ee81e0656abc5ebe9000846b0e70550052cf0fe717767d625a43f2428a285db48a2c7eaebe00a93f160af6c792bfdf3e87555c7f54156220897f611740784109dee83297fc0b09082824604630ff00cefa837e15d6f0775d59986007fab8483373b052f71fef7ef9153c1fdda0ee4c1fa9160f9e204477ae8401a55b92c3f5e15f7c0328df4560859dc4b34c651d939825ae8d9c6d5da291aef894f5f12b553466d40d488339a1147d9ae3a2e13d9718d2a5fbf1f23daa56e280b10fd9bae4087ce2dba3bca84e320ceabc5b8a27342f1b1eb04507d0465ecf56162dc77b112be9bf660fda9e80fee2e4f49beb176db89914a5a6f3224ac05505f319c97a955ac599076965a84d1d13e6031b02bbb45a8ade1d034844ec65c0c3e31bece89452b397de41dd02e3f85e092a70967a65c8abcaf5ec438f36c13ea73bb7b6e92c32a07584580a65e72f117379a9aa46abf80976c1f610b79236c129132df1c1449159230f188a64a6890151fb788e61da6d689e83e54f808bba51150a981e6de492525502ade0d23d2e0ede7562dd26dacce3a96446ffec923ab04595f6b3b14112ff1f489511eec9e840d582c861b9d0b3d728c3d9079220e512639cbadb862eec4acbb4855c619425e159745dca95a3bac11bd70cf0f97ace54a1d52467bf3b7aeaa160ed59ac46f66d35c85999598f321421f2a1a26814ce6956103574ea08e79b2f1df0fa996e1742b7af5fd6235ea305864c0fbde462073d37b809a1c84cd2ad065866f1176919f925c8bc6293eb241917f8abde1f2a0fc57a3fa275a874dc3ff88f1618205e6657e45f927d3a5060e7476c927cfa13c6b85d60f2509285385f01e2b88c19071ac719bdffd6ff507ea507f4a9355a34a066a7fd2f02e34433ed498000235217c825a7ab43ec37461e62c47509375bfcf251d8675d6cdac845dc2c242a1b46cb0ad223b5fc13e9aac2509449ee50f685868a61fe2b961c2352a3a3510449488b9226ca6ea4f978114b0cca80c24341d1f775e4614fb9446e194bd0df26b5d1b5cdc7edd733c68b87919c5190e545b1651bf49a5120de1c8a2586facc38305c3c856ab74ed5b6e4650ef8587d74a599c897d1cfc22b084069822996c0156f26f2bbe2fca273cc5e8aa86af9347bd6e976331bb209ba0d9d7fa43488ceec0aa65e14b4451844614d5193523a7401b0474b870d9dba51a34891dec7b2a8f595bb03301f87edb23c67a1a7f0aa6d27fe0fa70db89f8fe4f81e5fd9cd5c30240118b42682aedb824f061efbe8080f1a7cde0ef6f4390d3057d2fb9f01e0912a7b17f521c8be51eff5219dac1eff391cfd87acbd440e82197cb82564a061e72ff3ffd836043a14ac16cb418554c87cd65eef432a0e35f8a210299cea52f98704dcfbcbbd7f53e28fde851ea284c6a4de222dc978aef3f79bec5356c040c69cdd5f7250dafbde6388213ab73cc40a205f760069fc50e85ed4ab324023a48c8146e0902f926962b3c88e300dc441b2648a88edd5687f660b65357e8f5b678b51c6bcc0d604d37985add60d6a95311c34756a66994ae69c6079573357a5a417c3a4cb18f67fc0c8fc6df62a5c31f1bc5fe822dcd735fe6e3ae60ee1557b4d2537d904e4672517c94104c7524bb6a50ed724d473703d707a9309f660558d9226d5f25b11b1d2315efa3a14e99a7d2cd3859ac605a33ac6a124ee1894b7fd28c3804f1900986e10a8832ffb71993ff22896d9f185d6db17d63b9b039c9bb100dc0f8e1eef71afc1cd4cc86bca40479083d1b6f680b6f17cb4a176fa1ed49d4cc48807d598b15e77548b708de16e0ade450d6a79264db5e69b35b17d549f240906a192000566ffe361b5c0f9b3fedeae4a116961d75e60be0014f6e638d9b1bf90f2d333008819008318e66160ee10f37af19ecbd33ab1670660d8f8dc8c7ee534bc66d500719dc38dd8d509a3610ee744c0c62ef2e6e8fa5944c33aa6241333f1ad29ee65fac670caac5820416ba8470b6f181819dfabe1ea754fa1dcb3ce692f8289f6f109e2eae3b31ed89f9b00233d5f51e2f4cabe50cdcdfec9561f7895b9bdbc4e7737f51ba01cfa8ccae0998fa2cd0600827d9d4642f96ea48ac9eed2f51c544208c607f49d11de0ab59dde0a2ebdd94b688c734bbb64c4719f22afa3483b8d5f42d7365a6ec2a94d1cb015e71cb83a102428358fa36b3e908e6cb8913ae3803b061d9498787fa86598e3a6df4083ff6c78e9cf3af715e86cfbec256af0bc47d83b343b2fee7e067459c0bf6d20cd646fd7f036a88418b0e424dd27d98a2c4383d942425ae00b16cff087217aed227a9983edd26bedaed96750388e7a8f6fdd2a08b8e650b1b72f0be3f5f9da6f825e52fa64bcaebb8d08e8ade1eb1c550298e216a78cabe3816a673818eda94a94c6117c8634c7ffb131d9315309100c8be617423f7e5dbddb6bb5a5fa64a0ba967c41c29827d5da21f5824edd398861b132fed212b2a158ba873a363ec74fd22c16e8ea46d98fd5065246d2359efc30b1cd8a1b3db9c3e27599a70f8daf7103576e42562bebb1fb39a5ed24ad1eccf7d1e01deb62b3c685c02fa3c5dda77097f0f996efcf181b961b9cba14a57e29e78ee58e78491cc5ffa13b518409eabae12861559e912ba7602376660048abe714e57d0527cc9d1eb2513ed342ad0f16f6dae26f129e8820a514304222e7dfbd2fb9dc51802568308b927efe79cf359d611644a0cb2c215f268d2d6b21e3c116bdf941343c95c6f60156fb6e8bafaa47fc14bc7f135329ade6af1387752aa4d16056d24729873143ea9400bdaa8e65601d3ebffdf7dac7ab6d541c89858d32c0a674d9c8275070d738087825672023552606d0bdd50a542b2bb6d30e4e3c00642223a7f4cea15a202b954c2ae9acef88fad81c909b188f53ab000649a5bfff50373ba5c5f27cd8b4049237ad401a5b20303181d130901d0375e4b53fd13610e337c9588c4ed51feac7f4130c27c2eb5c0f7a034b17119e10c56847dc274ac61e5e33fd7aed41ef16f9bdba29874f4bcb197eff62ba2f85cb57de781df5ecd3caa67647e4b39f99173a2bd4ce2b00e95b569e66ef619d560b12bbcb72489b6042f785b014e89e08f85428399f640c38c00482c91cd399fb344c3db6030fda3b1af1a95579675b7c90791ff1ca23d5d7dfbf990664e8a669d61f7a6b7dd7c5d9a80a9d024abbbb5e60f84976544faccb12eb132d625cd253ebdd366edbd8c184f4f65b2c875abc8e20feb3fc73523b000e32f2d04ccd19bb23e281eeab49e1893b209d812897c6ecd8bf903c88e72a1385a90b4730d2093dac58d4ddea832d4c423c655c4c68f976e9802d8f93860f81287d378de9c40986a8500729a44b9e018455101314a82566802eb1af828da56e01bd81abc5a0ecf91f0204840a1d091c097702ef7a9a7479f0ee0f13cb919b784992628ceb15324110b1e90165eac48b75997a0dcccc4f09a948213af1597d932d059e8601131dbe76bd7489d289ef8a43a41f10d16db7e640fef1fd298a468c978170f8a203a74614f9554383337f2a64434314951c736fb6062df0aa4a5678f64045cfc12cd12a84632733ca8d3822f4f69cc4c5adfb2337c37c287afcb30bd099310101a473a875d67705270a98cf8b901571b91ad6a15f0a0ed4a51660cd4cd29e8fade19e74ad1717610e173be9051dbe6498c488f9fd54ca7453de839d6c486030f0c5a619553a3ab9eef77e998296500962c8537e6c6d259b53a8386f2e3871c9ddffc1757d0e03fbf761509bb119e14c61d2f5243204badaf6cec3212156114353a0905f1f3e6a64b78f83d339bcc720f30e65dd836c0ff6a524949fac3b76cf22b00634149af808677122468fb7b9d497156605a2a9c1007c3cecbe91c59f4ecd957305e3113bf0466788530addc62b1ed15deb97046f13de46c28f385025a62247723f5881e81f9890f67bde7942c0562829cfc8a925f662755cc20efc8db2d6cd13085ba0a01d8389decdbd949fde871ee9afb75762deb978fd533044820c2295fb8359323ff4257ab47a07f601d3b5af43a1c844389c84e01e8f660f02c8694b40c72d149ddd9efb25e9d20d7c03559c4bbab374d0112753737586ddb03c0561b0b7b738763822d57a70aeecf8aa5e29acfb3fd972690f5a9070ca830880f43d7ed61d6e1a4a62024d8249685a294c7b138a936b5025c66fdff0219d07e9dfeb152cc690d0343b72933d3650fec43fb322f8015f437db5f1b7a3c1ef7825abaff22cfc288ea3e744220c7373679c79a2d28c4f63e0f1fe384e305266b87a0e41b7b2f3cad0b0a4063aca6450a391939f8368894a2024f6181e9c0833135abf1bdffb0da540f979e40a817a2fbbb83dc26f7f5bec5153b500437d33dfffcd42e895fd508233b3c07896ee85f1d8ce810afcf7cba7e7545ea59433f3c94fa840a9a0507450e334ce4ef12f6dc7b67d4f76bed26919242207e360c7e1e267bd01bf89f55d1e3384e2b00323523bb6342d6a940e03fcf16e8ed6aa0669578d31e3c7102efa713c365a6c1d120a823213342d8d98f5e96c2d33df87b653850977e16f6c3617ec0c73a440e05123c5f643a38b0d66ea88865c1fb5cbb2833d825df63d756ef51b3c7f111191e15a33aabcc0d5b7f625b0f8e6fcb444b3dc01c17f3e2f0244f02e3b14a4f12f7af6f68cdb5382241bb2ee118995d0c9c4d575e389726f6fe44c65b01cb6683b22fc034b09ef3163de2a163f6eaf181a744a3d8d2797ac02ae07e2bd3cf74d4e7f9225155b0ac009846bdbb1ba3383fbbba05804abfa352c7ac1ce947f481b79feadf4bf5b95f124c6f3f1e40d549eaa6449597c1bdb35678c54fc62f270a86b780af93a443c675d5bac1fb2be9cd178522dd3abb094aaa085453f50e5b94f5f9cc49249f6629670f25fa5ee30add19d7a20013f9b9b9b9f3cec0061170d0cc19c007306572ec782d414f9f81b96485f48d6dbe44f25140c70d677e12e4133f23b7686b8e66e697ccfabe62cff54c966cff614006b08e38f122f45f7b81687510106b7517c1d5b5425d071314eb510aec451f484f559d95023db5d67e25a04415509e4b5e7a7f9bc29af1ada16d024c115e7d3244adeb7731912f38edcf81c28d2dc6d0277d4196fdcfe1f5b7457c167eb6b15b175b0539b773a4b0bf10aa62e7c3404a280f1064b04c55b375de6689e08053d307110a2ca3cb6a300db3d77d5a69cc3e9b739e84a1df83e6bcfccc1bba5195d96debeb0f347f0c308418704e0f5b92db9e576e26b7448d72964da81d22230ace63af4073795e462e49faeaf24053be4e8e85bb67cf3d042fdb3b3b916b586ae3731db9f4fc2d891d2f763cc83bd40af678371271a4b9013273a14f748462d6c91dd8fcffa1efefc6976663748e3fd90e90db59ea39d7d00d7ce4a70138d313e4bad4495f5fe58f95dd47890757fcc5f5ba84709d25e501287730a8820ce096c4dd5ae46c27a314b2aa2ac911d5688f09070fd0f1115c872d67929b906fd962ee7b42fcde05d6929975b367e7ba0c235cb62a1c0d53313a1cc8267be5ee36796307deb05b51ca205780eff767436dc10add0c3b0fe81e5d42002e83fefd818a215fe1a77acc9f0015a37c9a902df88959976ebb16d645982cd3f68dee4bd819288c92190d5ec7feb76499ea4286ef9cb5d5e09719f329f4c2315969518807fae28f90315b751c0ddc43f149476e68e3d65ed4a7f643a2b956f203aa06030bdaa9d821cbd423c829c8beca1424f5e986c6c98c9ef9bbe4eac9609fd75325997b3760a85a65ea7b3e747672a413b707f18f423eae5099fc6319b1bdb57bb7b7c7679730d0d6b86dd494b481120598fd729aad5391f31b5d566a9ca0d7643e169bed5a450adea21ec132a1a936e56074f5286906d4806f2a99081d4b24a6629b2d71ee4d839a6c7d196e190341e6bc640b6d073b82e314d88a7490e64c28527aacaa4750fd6de473feb89a067c54044ca31764d9060dca33ea8c785a5e5311472c026bfd26c0de636bf8ad31fc2e8577c0fbae40990216d89d1409cbf1bf5ed71f8d9e55566e723dfe8d448051c11b796d09003e4c3e093a033417314bb9529dc80b1a14ea17ac9b28196106b19c43d1a4ede94bed2e41c24262a3f1ef1d03a53504c5198600aeadb3b19b4409b27d3374ed708047a0047b02f15ef8aba7563036674fc8a43fca68dfe24bcdedfcda13738c3c330890142d2591913e6aea009d8b80483c33ea3b2be8bfeb8f93b9135ab9a9453229a9451eeb544f407c0c1d9d1f003787a36b240a3b5740777f5715f6959c401726184f63f571998e17a7de22ab0b30b93080a6b74ceef0e7fc7ab542ded09ab46e29b95d8c214cea5bb960cbb788c7a036f75bfd5035887560e1904f9ff28557ad61ae8b11236c4a888ba20b13979e1221702ad271674422ce6e9d9268be13a226880ba78215dd64f6801b355ad1442f8353017609d18846214c9574f7294372fb360606df435521ca37ffbfa490e176f2c394f9615260c6515147689c217797205db50921cf97186d6c4c2afd2ab594cc739893d84f193abda372700c1db3901d56f8a1e155e2b13a3a8adb16ce8a81c8c81dbcc62bbf1d69f0c46dbc7004b8caf06964b32ecfaef43f80c51a7dfc12b8057ace9f7e4ed53ef081a662e70bb8906434c41970dc370764c8e1191cf8d9899f50dfa4436efbf8fe22ef3d82881fca87098d721c7b46d720ee74102dcdc744a2428d74e8469f0639e8f2a41cb2d658ff99c75863422ee98a7f6ed1fd583d7a8414e72825bb3b2105cfa4713ce6788e017e0589ca8c5f9b7cb79ee200ab747296171ed7e3d4200cfb9aec0e70332ec7bf52838f27a55003c5e828db8e937b8f1ebaa67517da9fd8637f58184777dbf5f494e56c01722348ec90a25ffa84366284c3729e2e0460e55e48d26f11fdd2818c18d09f5c15a8524ef718468d080f1d0bbbe3634587e94173dd16501fb08e5446b62166196cb20777ee482884349301f6e88087a99825d0bc1c8aeaa5ea4ccda962371b329dc163921ea9e2f61aafe02f2def2d7170c0d991010a9a30fba6d558f790e2ebe6ecae251d22ff2bef9b874523354bf3d5fe4545a804d80305618b9c878adada9b71ebf248f2fbf1a8ccc6aa1a631c77f4538d6ab9ac35215af699f1fcc25caec58241fdd408b3446029069e54963b728c1811393e5468ed1db295e5556eb0d9ecad293582e21e3b88f8b0f8eb08e5ad7ddff6f2c8fa66c50c73276a759d8b82082f813530e1f3f50209644a09bb5a148c95c51b37a0b7b942e243bfab82131270674e7a34a5b3ff59758f8d6fca9473d0fd3950189d4841ddf063234f0453d9ab2ec9245409a3e98197da141ed89cf91bd3d17f9492f1e96ae414f28fe42c1b289ce09b6808031ea50fc18b655296f5cf6b1625cf538438c62df101aa73aebc5b32ad790a5dc972b8f0da39e717179e89dd737dd5be02d2bda8d18edeb29b2d14a64b9e922f09ab070ade31d8ebeab39cc8f5c2624c12500d518033acddf976ceb080d8a0a745c4be989e2c6e53b163a18d628e22685f8d1059292387a6255f35e7817ceac0a3a5e4cce9fc1ecc49aa8d24f4269339fc5476a61c1b6a55d97bc6d9612dfd034c1daf5696e8b19cade192be23328255d8208d5942d6774966289622cbc1401cf4e41fae02c94472c03ee1421bc0bdc19426e00596f1e257144c0a45a73cc51826fcd9d56aa26653ee4de92136e2c0ff96e37b003f5b4d437fa61e3b4ebef3a400aebea19f4224059875d4207758a1446f71c45c56183ce19c17aa8321c2dd44b6ea961aba91698ddbcb06968be795815b6783b4a432e57e815da1651a982fe11ed19fbb0127a38cb83aa959f843acc798f80a98ea6aebfb78cb0907f1058ea2d371ff6485f525885bf6afe15b52029ef736b69721d33cf6f000539529901ed216d6f2350ef866352d53ad424a89f4774a8054e174c99a7973f232f19cf317da68f46fa3a83ff9cf1f0efbcdb5edaeca29776de189f6eb107dfcfe5355ff21da34bce5ed80a90b20cf6cb3112f8962150e1e614778337430da7f88dee0d7225e36fe0d5568fc482a9a6bbdd14a208c189fa930465770175acfaf14d5b9fcacd3cd281a7536266130cca97b262bdf5af482297d360c9b48b6df9cb50bd70fc03f83210f3a099190d2696558b9f2ef7fd1e8b01e18104b0bbc30f5c3a868d0e063d05a88dc15cc22f4f48071da97c9206eb20e2f8dab05ba823a92ba5e2af3df6542dd167a32c45688925bf6cccb850f29f04e1847eb1a8efa08754be6144fee91a70cc428f9c174f4445abe6ecbacfcc7d96309268f7c6f9a269c3c30c983cd6338c435961d01382d982242c419e5aedb33a543268b1737249a09409c130cf60072fbaa18dd6d1dc4b5cf3b44a0b3da5f19fcd6c61a733c80cc70bbe10041b40486d9066a3a9d1d669d5f836253db13b33d6527497efdaad277b65adf02edc91fe82b26135409a5fe4869310a5b4a2bb4a712dca3a2f0e0f2adeba4cd8b493b08dcafc1663d2b6d436162acd2c6a8529a0bb8eacb86a18ebe3a5c9abc07bee907cf3dd35ae88823be9234e8681aec7f0fbb942a9cdb9aed61c74fb330ecc35b1e631d65d6fc187983cc8a36042b3411e4e0734062b1849d31e630c90e95f0650ad3b83a8806e42fe05aa236ee8b0f83963a5c729a3efd3f40cea935aa67fa5c0f618d3dd18a54e835a3b4107e5493eb6d1da30fcb4d427cfbe9e013bcb80953d75991aa0fb6e2ef3ad3b4fb0dcb1245021b4f39e7a79d898363f2f604fd141045f86581e19d21f469d755757344460068c0c7a312e827fd6de5597a2b11c78d58d1f36e9a643609d12db63472202e6dd39c7618be173d6b3d37f4f624173eab3d7d0b26c1c118b315379a20701be81a8543a55493365a126845d395b2e15c76457d04d1d8d56cd99a5e8976dd1d091977f1ac6f995a48a64ca2ed07d495df2bd1468a7c0034dc42d1ecf4994f4e8d1f4266353ff67b17aec2eb9ffee1f09f2f50d6a1e290990fc1383369605634791d7642d7841ac186ed0745cc127899176c36e01c4f1e39c132115f36d0a976ffaf2e0873a9df18046e7b2b3437b91b9412c0272e8bb33633d57c2e52536e9e1e3a21483324c2db07b47eb67c6751c3e883a340ab644e8a34fbc44f870a7a93dda29e229d84a8f9ebc0a6aaf4f37051ec2b17aeb03cf901c92e82e171884944019d7a10e998da45b4e2fa78a0674243e36b68064eb85021c3f3c62ef0d0c4b55e71f1eb34b5abd67c38ce892825e2d96468ae398fb2042002615cb0cffbbded05c89f0c11f597639e499590e3e326d9115c8459b0e45ef6e10b2f7fbc7b4e34599a0b5fac8e31b81fef328e8bfb46e5480ffa6a0e55ad65b2348d5b23ef6ce881e7966bda0a0cc8582b06b250f90d87444a052c1a7c354ba522ccba749956116695368cec657428a56cacd918c5e5f9f86ffd6cb6bfdb83e23bc7d3bd54538ca8af9bc6771f948224c25177082ff2cd39f852528c24c0e4c84344503139407601895c71e2fecf96944499f53a76113ca7ca064e01f7942ec04048d39a1e028905ff47c79848f63acb34e6be1fe79f953108d1ad0dedb334fd4fbb5be046e2a57f4f7965b85403e8aee4811d5609e8a2af2c2c8b00c2c7d168caa29a4eb25d72958b87d96d8ce504bd580609876166806bca63be5fe01de4d3822a32ce00b561bff8e86fe006c479618eb7875ec46a3ddb1a49ec8b4e1b3575639c80d108003b5bb6a58b892c467405c464b3df14b4c65668177623e513b8d25a2ce42b3b1ca3256c55069eaff13c15bc1f3ea260563ac777495b350c5c915282336c2334f5fd622abc863791bea822ea650919bad84781d7cb8e58dc95ddc8210aa5520d133b954694be13d7794c58a95dad678f4bb3a242219657ffffdb8ca2108ecfd0888f4e5443731b5f8d4c5d7d7afd6185faea9ef29b6c66429d3f2285c1d9bc354f1c600fa9a341f76db499bf4d28a0fddd0bfee5528530ff0b8634000afcd624491320e223f4ae7644cfcc7cc1aa17d4cfdea10c01595bb6ab1a3bbe8b98c394a8552a495cfbaf93f8a57bae770423ecc78ed9cd94abb6361459405abfe2a2791109e877bc6c0488b2820969aed61100e65d098507d71d954e87f128f9193b406907340492277b6213a23b25e2885508610338684e3b3fab9c82edcf2fa4409c2ef55021e92ec05769fb4283c5707eed2b2379c3b731d475e748c35f572fc545e58c925324dca3c48015c00dffd6082c906b636775ed412b9e2def08dd469f084365d489dcd96c7e59fee60e85b99a0ac65a851d91ac30e0f661f65537754369dff1ff060857ddacee0e1e5f2972b916699017b60ad89b14d85be7d97a2116c09ceefa9aac731c92b1ac71ccc4803682d2d57785e494c71e9229531c4c37cf68971dca30cb857a02bf1f691b89006c8ab24310535dcca5549d935d20edceca53d95b81cf8852014d5c67eb06c6e48bfd82a0ea67edea9b898189d3171c187fe6124173044cce59fdcd9ef3ca2d821295df527967c0ce97b23d79c0541e4ed9bba72e45bc5faf9c01eb072b0221c872286b2e92403c412d2c4b6e013ac5971d6f5cbced6de491ed59162964f0e75bfec366795e53cae6f47bc5452d87487d8f2f5d372d6d54523f47a55e3de96f38ec5acd1a2b3813050a19962d9ea51da828d767fcf6379d8cab295ef8605daca564cdd28a50f879f80f666cbc25002bb7e8b4bccc287979e3d7c1f3a6ba63d1a5531ea063c297e4554d76e40aaf82589e2883d685e43200307ff249d317a6f5bd0d448263a7c99a288dfa8c43ae7e7736d62fc201ed37cb2360515eaada352aca7beaf2127d11d8a3dd709ee080ccf8696feaaa2071047e4d8350192f9b7b1404e42b0ca35837d13abe8343ccb74e12ed08eddc0606ba17578faf3d517df222f47a223eb7586e47a075cf9dc4646b809f992842bd50e6dfc919f3c827e6d3451c99ee07ed770842ba76473c758878f25b75a1a2907ac297045ab5979f7557fa05f9ce71acc4fa5e525e3e3fd64b6ef1b73ea8c68ded6401ec0bf1de4c8494aee76f85548957d4e9894dc0e8247d2232ae337b6fcacf6e67d23232c8a125958071e00fdc0048835775f7a26ec80aff0207c1a992734088f999dd1d98d5f7964efa091122fe727e41a1bff689af27fc61cbd3bf478f10fe2c6b359af0c9bc368a08f1aefa491cf843ea5cca87eb95691ceaff6782df4118dd668b858a0df0c25223bece8c3d8bc0b9066b5614d1ced33c24289c6f2002cec88967eaf84829deffef87bced87801a31925f6883744404dd59722869779f01a9ca1792e4f3f5e1d9b23b657aec7d22d41524efb17cf9a353aca3772f7f899d6b7efb4523109bd684ead4b55e65ac656f3fc9f8be09f2beaa8b7d4bd3667a6d045cad2c30cd2dc8d3a1efa053660cd78c5363a13f936123e0f0be5514b451365e54f2890d9e22cb269292a3fa91e84e34487019aab49e16dec1995c4afcfbd4124a529449d319264f350313056f31b3ed5067c0e787b7ac0417f5a83b8308b285dfe9ea388e63f38ae03438f8f3e0721cbdfbc48d96951af4dc0f66d733de7ae79a6b59c7f9e20ccae060a49c060693980f54d223d93881e6f98c8533070dc7faca84678bb9fa3fa578f59a65fe039c27a9c0741683c11adb2048106744c3e1f16ca1d5fb31c9fe852ac4094b82f4a2f242fbbf845e72410306c86152b92ed581a4aa299bef093fa9d6d301c0cdce06c803f8e80ca19d55f3d86152410d88cc0394345ac7e9afc8aa49181b5c1baed5ca91e11cc90341683624edea960980e08b669c387cb865c81fcb063916ba4a4a508068257648bff0ea3ea103022c3363e88eabddd007528bca6053272748983151086796aa052cbea2e5b05cac80a8d6b12db213b7cc44505ae67d95891dca3d406ad36321d20b47e0d56e1c952f7124641059c35a01401617929b952da2c3320336d101c2fe88a0f44d45be824a62961d8261e853b7092206a098d0170640c15857e17b9deb20115a6568b1495b27fac3598a8dad8782407f2f71454bb6cb94ad0198747cced315230395a89ff2f5bd0b4b4c5a783e70e7817673ec6061e14becc18db6adc64e2ed5e2a47e859b68521fcbfd0b1fbd7c15487060f1728df74ed5fdef9a26f82130a25052ced68ae968d6a4277f9277efb7aa66ae1be1cfc161abc21ec4cff69c078afac9b4ee1a226512479ec8333f4a003d9a50d01351d14335de61a559339179c43a3af625a769c99d03a4aaa633a3d8c69a13fbdd6e5794f8bc50bf82955c039989ebedd3de0008cc470e2da3368401945903efecafa867c72ed0c1c7bcb07920db3e0682c7cc961385eeb7776cca7cc925f6ef85edd42e5c71c4d372f60c0f26a23eef78d4811183a38239bc0d6b747b57fa5d9240dbc6bbe4a171b7b87d8636e42dd0b1fad91748ce5f1df85c7b26b2076ce3ec462d26119409916682c8ad8d61cfcc028919d00f7c52a218247c7e8e919e959cbff1d46e73b8786e516037ce3d426e081b9398e10070fb7446fe0d96854df3bcb260aa9a06435ba3a87f875c300398b14dd1ea0a0ee09e41baf1ae4042a0b2a6c78f375e8147444121342eed444bc2bd6ee284f9a78a1b123c3d85d521ccda09eb13fdaf464103a7790a6a3cb2b5127d9e4918e0ad43014c26d378e2c9aab428e3f0b61c13de79b5d1595ec708015c8e5aaa92a6a2cab28c56705d25dad990bd70229687ba9115d7f956e15351b6ac4ad8d05fc5d8eebff1dfa7c7cd9a298eb0058fd9fbf4fbaae8b93adafed9d693c85c95cc7e66fa080496c84aef42927c3dab99f5e73d592a591e9a0b129c530dc98d50b27b4c7b591b3b4d381499a926e80878c960917b35604fb3e9deb48f92fc2c84015b617903035bb1108fc55bd942669a9dac7c65254529d5ad0589f92518ed39056ab2b71d3b147132323c0ddd023908d3d44f98f698603526e360f98ca25223973b41e60d326e59f9bfb434f7ece8e7ced446c1769cb84a14c4b3bcadd530568d8872356192b7462862862c5620b8845d2968ee1659398714105ed831f94fb74e37c9e98db8354909e61f3ac918939916a58829b4e21c2c1f0d9c8b83771441c18f926eb76d8b229b9c239e79402ed337c243b4e41f8c4fe31deea147088085281f09e2ef620bb486359ec7be0580dd280253783f8538f1600d80e2f5f285dbd3c974b9276ec20a42d5391982bd86d8d2739ba802afb13fa8a8b600eea203cf61fa96c2047a4e0c95d01c83f2d0338a80efcae7f5bb17174cdf722281feff71c3c07c6ee1cd9ed8cb8a266971339e5f69caa6de7534a09b169207e794846bf3ba5c25f189de1a846c1f61c0dbffef6c70a20f7d30752a3bbf059d8a0f7ec64c2918200284260cd3c1c2bc316b72e67cf14a11dea109368b099e6e252b05719abfcda9de63a011f8f269730e461aa8fc92f3641b707fc93262bb1a5f504d824c18882a1cc799457d5d1ec1f82a950f52946516d4e908ad38efc436e5ad0b4aa31187ec58a273ded43998414604d24d0e2d274bc50800f2385e27c364c6b0cc052561944b170cd10e698b4ad4bf4f1fe43d21bbe51d73dc472708c06a42035c6f3c9dbf5610e1a9692539b7ffd06ec43837305a5e284a59a31004942ca49f8de79fef059b01f0d4ed3d4673e2e07fb20c304f95474f7a8fb9cee9530d13bdab95aacc7a8d4dc8cf0fe16ac1622da2f34c43115e4968cea0efd3dbaea912f602a509252caaef00f96b67f261f58ccbc80ed3bb437e490a429e6fcd7102b5a3265cb28b19f796d52545f3b8c075d1d15ba2193528761dafc95fb1445eeefd20665b05e949c31b104b592c1482a1e0127cc3b5f396e554b01d72bb9d042418bec61f6078ca6b4cd0ac957dee05dd0d2bdc1a64836effecd5fd200400c3d49be9e9406d53381491cd79b4344bd2252eaf107a25ee8eab5cd265f7fde6ff6de9dcad71e059756292dd8991226967f0bed319f4aabff7d2bff3d040f590171408804cf8478784a4a7ecc7439a2964d26581fb084966c299458b1138bc78dd5c41b06f69c54ceb5867fbd61ce1679acd7f1b80aaf1e95052055be977c1acc4662ac7d22986890aa52cdfc2c917d043ce39726bc03e3ee56db549eb223b59fe8df4d130b4da0a70a5590794d0bf80747d7266d16525689c83f1c97d118d62e1455bb2b27ae6a1bf29ebf7c5635455f1f93a9701c5761e2959e34353134d68bc90710238f29ff1c210d8b61e954228a0436701018c55f3261e5ebff80171b15592db634df01e77cb9b54c40882489bbbad05cf09bfb8af58a4b5d9f78e9b08d3bde8eef3e8bcda9677b1614a0158c41138a369f494efc51544eb45893403bce022ab80429e93823e0f9ef1f3c735e1334a28356dfa20eecbe71d3b75410765f553f48a9b0a986d9c1cb50d966684d06cc2ee612c3ab1104812c379eb4ae58eb4e5170276c546d9a69cdc45bbd6fa5a27843dba32d310c30f4d23499aa04093b7db51c1570fa464757816ec383e9fd226ef767dbe491581c9d05881fa565d3a41886e95f50ae77ef1de847c9062b4dba3ab660a3d1192545072e43c7324c05b71886128e59989396d7ab2534b84721aa6b332b3c4d4861aaa6dad2f0c94e727d831f7f5c4c83d25449c1f5ec8117b46a6ba5207198fc0f80f92d432a74d95a47518f67c78b0007c24a8bbf566aebfda76e75d52fd681d20cfaf576c0569ad0758684ca16ef719e004515c3ee992af5442bd3b5200d7ea67b46dec1ca2cd12b92f1e2451e8a715048c1703672b375f474532535400afaac18515d5d80acc3e2a6e300dd48a0ec1320cacee170fe7a0cc9ff61879a46f1dca9820caebd024ea23d719790cdd26ea901847364cc95df42c245b20aa279df897f0c37d2a3682080e8cc2812cc824bf4e98ceda3e39be702b1397ec396a40bf1bcc7f6c15e5536152c59718b3d767197abea3e1f6cfa4c09d459bb18cf6aa9b1acaec91363c70a66c5aae4e62d56489b8c8d9a2a20b79ab028d99b159d6e27bfacdbf09dfd1f81a7d295aca26f08379806efab0fc3edf81d8efe1143c97f5880c15e0b283ee7d8a0b392a433249af899e112a7f03797eebdf1ca6ccfa2ac882ddbaf980f707a58e9828e19a967f9dbc363ed78b278966ed1bdc3d97af2a51a2b70ef2cad2b827b2c22dc7f79f50c5048f5465fece720902fbbd7e69679676ef9e576000e7596668f48367f48d1de288a0a59e9263879836e721e65a4632aca2120239585a14829af43d760573965eb77f51364eecd0183c328f91fac12d9d929366a4ba0a362204fcf151b7c5ab93649387da878c242a3c49e41b4bb54c6ef8fd5ddbf42c57043d220da62e80dd1e7fea06bb395a49e9a3b32d12a9c02e81707a106154fe0a4256b0efe3b831e311d35d04439061fbfaae2cbdd24a326185a05b05ea9433c4448a4c565ff8760213547ca91cd5ae469129090659fc220c6c1f8708d0d388e5f9c10e0b83a66a6a4bb1bb710a4b1d4d8fd90659cf99c7339e9a02effee6b015a2415b9eeb5f3c25c03d61dd0811ad48206d126f7520ddf35ade2d9211cf5330c75cbf95e1c9ec3ff56437609a853f40132fc9ee3da49e07498298cf910cf8351f93c8b0946d7abb9cbc0de13e700c714ff8cb6524fb0a77675155081c60012d17082232eac90aff11e040aa1f03ad36a1a8a6c8ae8acd2309ee3fdff03f138551c0ff723c0932631623e71c4d444743bf1b8061d89fa74fd4cfb8065be93791c4d569f22a5616c50c06090d7a47a937bed66092c66038a484b322892c9c7c367a8a3b70de23a57c4320120b7b9822a2d0f2675459aecf8f201a7d2bee83daa69707785b67691a0ed56b2105f902ac6769e680b1ad5df5924720b1a6ccc0c211140b7b1e38d9f804057e59d87387b90497b53081e87780b02ba920962dc98835bf538a4c1aadcf30ec642a937371888ddbda2729333df1f01b66d2efd5b0b776f36ae951f73b154868efe8584fada38d91aabee831bbd36ea2f46ae754a99b1dde3b9b9406fb582760a3c3516b033a5da216331059f0b7bf5d03ad12072b7e7077711a39f28bb82548ff2a6065cd5cade7b6c19695f759fcbbbd09d451d8ca9008c6a3ed1615f8c5958d547cf05372ed31570415c0e322c617a17a7b3393ed382eeadd63f5c53b2ca914c51148ecc8139c20c4eb20121bc77e0d6349ce1088cc78f849397e3c61f50b2eee957dfe5188bb62b5275fa89c6ec2dbd7caefdf9a5d3dda1509f081460d04534a776f8fb8613d105e2d8d3e1c062a12ebab4c0e91d4f917141af4c3e93bb0cd39476d7c9a025d1680688031c58a7fa79d63c4c9b6489648bb516cde27cdc6dcab390e7d3c75d245a176be04df26484390cb14f1fc53d04b8a4ea6626744d094ab2a30c9a56a0808cdd042714335a6274402a59e327bc5d370ed90c8ede2e8cc0661f22afc43fdf478847ff9e59a84fc0824a3afd5febf74c034171eebaf20ab293392b827a73098a2da38b04568cdf3c9727d592aec18bfca147087b900ac85776b40110042983c4bee49c77c3efc1d870e1333a0161c7c8acdf63901d567336798d8037bc8dc0f0abf51df3e262505e3fcf2053f28f75a529c2b4db856d49c71513b11d5613abe3e3fa02d007df28318cdb9caa7f74e81233981ea509d24197f95b5de80167bb34071bd79f46bbb971ac85fc1c501fc74f0b7bb6e93e2cb7b2485f75b8c59e2a73c91e46974c65687fa2fe8aa323eed25d168ec9822b82920430074b589034ef62bef53760ea22970ea991f6a5cc23ee296afaf3bbb032ba4def1cfdcffe5d840c1aced52f38890903d9710158938deb082eb82f7618fc6acda6e5a7bc6890dfacd22824dd831096e0d0fa06daecb296f110f9b95e5f7d38c62832a3c3152f746856a4ac86bb123aa8f9570824d9700e165166badc95013fc81b0eeefb4a7391428488e4c68a4dc640c598f0d224df21768b7c91d237fde6189f89eb8636d31368fd72af07df66a8842804930f5b282e87ab8aee21c09ab22a60d56350614302281e3963fe510a701f7ac8d88d5889f6b103ded52b8cac73c835fb8ece569992f832ec26d46f3b1ad949b78b0fe8e23c43ed56be17a480f53e8055ce05857c1dd1201dd423528299ed953dbe7599b37c22c45a6f4719c5fc534f48d500e45c8480a14286d1fb5f71aeb9a1e147e50909341168eed76c761e5b68f713e39eb84531a9213c0694d7e0e53d48c88b8a5292356db3dc09fa0573c85cf0e7252493c5dafc33d9dc61860f70b48336169bfa917f9cd9fea172c332f6a9bf20d77684037b4c6abd07eaf6c011c8a7b87acfda672a632ae0aefd489fab3ff6bd5958cd1d55571809cc1fa4899ee42e14349bdd177fbaac6c808d70c1f0ae2995b6bf2844447cc2772d29810d28ce9b39b2e32c881d21eeeebf66404a3fe61f01113cb5a7ab85d3a977425db11cd3271081bbfd02c48aee925f819a0fee7b446dab7081535c62e5a5faa991faa1ff51b98c2183823c6bf6ab159eb58c7e9754f35f68868f2dd7dd59e5bb9b82be81cb60e34aea84c56505bc47d50012d0d8bac73f562bd670e7feff0f2bb2cb29cd9c834d067261e1b6425509045712b916c279d46b440dbbab2b29f41bc376c6cdc2e8a04045919680dc58924ee999ed434544bea7412e6e2ca7df7805c43104fafb53cb5c4016956d3a3971aa07a75cef40ad77a0d663d987eaa7346c9d42d921d6d15e3683b8d6a1009bc0201114f1fb111fd0e820fb12f017ec2ea633fdc2c41a6fd52121e267add671b198dada1d4ff9480f9afd7fbf75935113217bcbbd03c40c120ce40cf84472dd2d919cbc26f5d66d2a6cc875b74472f29ad35bb7a9584181dd86b16d85b5c7c1760615d8864b280b7b1b8bb6b0a690eb6e89e4e435a40b9fd216f5a329e4ba5b2239719dd2166d5b51f195e7b06627b0159fe128d8063bca7358b31533a858c1b61ad2ab016f52a14caf013fa648a1428da6db6ac09f94d876729202dbe8cd5662156a3485dd6bc07327f1225833142ae6097c8c23073d72a4fc5f29266225b0adc68433b918b7458da690eb6ea9c5b5ae0bb72d29398e09e63ad4680ab9ee9784e4382dcc75a5db5a246e7b611b8e1cf6c8ebaee7b066e56128787c0d78540d78d5c909099cc39abd5cb8e6bbea27d896d3c2b61a96c7024bb0f7a14e37855c57f24a2009f6bed58a55eb55ad4a1d6755eb5158855f28d7e974540a9f288b5a3fa2f089c9d8a75a6f1a710965d167d1162d9e455bd48738c7ce56a1cac39e58eb391ce21465d128ae619445fdea2fbea5eed780f8abc7f16a7d87eb89b2e8e3dceed3d7c0d412300861d4c50cbd65da0d196624c74e5550be03a099bb38b6aef2424981fd4489cd1231142b295094a722a7a49391d311e40d89f392cc8195a40e9492d47995a4112693158ba44414eaf1a1423d3959c435a89114295034813ca9d08fa25c831a094d43a79b76394b58252a848e689793a484c4284834d22ee70a979414b5798bf0285338493b5e28908cc0471ce9a0a430d2d12ea7c96a7511a38ab4797360b0db30c9abaffcde4474c26997d304af62242598a6661317310aa9cddb77e18039e24b74dcc032819d6eb06693104b24ab93e934b1ea0456a986a878a85446a87e543a543f54382a1ed54d4a993251a686dabc8f9529a3142e5345dabc2fcbd4116ddedb949b4c4e7c55c23c4949db8ca95c34f19787a1c0fe0a3a534327e24f549178d4454ce3de98784a4ef283f5958fc94d4d22d5bd66f88a1296897585e7eba773053ecd804f435ee5e9549e6e27a3539036ef53e5a9a83c0139119d4894a7a1f2e47312ead38ff264529e784e44dabc6795a71e6dde9394a792f2b4d3e63daa48053ebf157c9229f0d942812ae251c1e767e2933c81cf560a4fbe57dd98c0e717c32759029f2dacbac9f7a921fb4267253ebfe39384e1b385921acad723452790678dba936dd44cab65c8e2cf2b725884d11e11497f9a2cd5a12673f8aca9c9e239129b2c965c1c63909470652d4316cb7a24b782563eb2f502c154aa54e28af20d4395eac4233d2790e745a180e47b6f8844fd746f88ac3f4d3744641124242323222221a1ee144ebfc48ee89757917e5921f58b68d42f1755d42e312d2da8a27cef3181ec9ff7c6c464626ab5c2b0e23831b0ee1d0389b5ad56ab656a91b8a9d56ab5acc945029f2e530b9fa3099f5c49593349d99955dabc2a6f3629b95ccbd36424dfb36f6c798a4527b9637cab2c29cf9a4b4e529e3593b0be3a11458e1345eeab7a82cfca619a0e9f67170616c78981e4de3194587b84adf5b7d567678e0cd485eb2602a847b2886bc5a77893588a37798f326859c434c49f9c8e32c8ecc2e709a674c5e422a6a9591431a52b159fe3ef6b194c7a2cc7c3b0632e293b939436b3ca9b57259755e5c9ede4fb54799676f23daa3c4df2b4739aa69bcce1b3cf7ad62c9e52175de63e62eef5e2d9dd4ef0e60c6f270deac81b79db39ede46bbac9b77493e9fdc9c52d5a20fb26ab826ab042e825c1d6dab5d67befbdf7de7befbdd7761d42e80dd16aa64f02596bdde1cb1d6bb3be5aa5ae56fd22b65813d0bda37700794a206b92eaa922f6f576371f4e98239ac8c3fa1548f57e2512d42ee7156a97b30eb5cbf955a2707c9fa67ad42e275991dae564e1fe0af767dc30f5c7b2a423f7c1afc3a937bda3777850a83be68d03f2c9f65e12c893255b4f09e4797372ae8e76b937e2ee6897d3ed2f8fbb737b5c9efba35daaf81b6188694a2f09018258885b9b1eae11248820800001c4cf0f3fb469da5b5fbbd887364d7bdc038f8c4c8f19337676d881870c193b70c0c108183074626274c0c0e4b474ad4fab98c6779a6b8def0dd99b681ac9dbd34ba9385652b6252f2c97954cd5926a81c2341800484c3bb110310d366216fb3afa58711b2759f431c36ba8b28f1c93d98bf89c9399cbf81c9399ccf49c93590bf91c93590bd4734e6600483dc764c642f59c93190bb6ad9e63325b310366bdc68b8190594fc9452c8e7834618ec44230540a7b4fa9b06a55fa8a85c3b34a30ae4247186933a86f861aa712754e51eb306a9da33602a97724350fa00beb3c21f0a5f022cc74c3aa913aa98bb4cbe9f511ed7296ec4dbb9c224ebb9ca69c53a5d32e27cb8876394b702562639515e8461d42536f4204a901e40788b2fafc50d61f3e549e23d85b0de239b97d1379ddbe83dae52c1de5f62dd42e67f8dfbe87b0cb493e76fb2e6a9733f594dbb751bb9cab9b47ed72921cc5d97a8adbdb3d5c3fbbfed12ee7a97ddae514fba7c4ed1b8889db779013b727ab87d49b891dd22e278cbbbd05ea88c06c90783b84223a7155918a350a6277b4cb3df0e70da59007db1fa44f8afd31bf4271129714b896e22a6e716de52a56b0ad12016a1714b886e22954704de52954f00d14b8020d691713d7ccab9cc0b51357c1b4fada094c93826b293f6102d74cfc84092c440aaeb718aec56ea204ae95b88912b8460cd72018d7f04b94b856be448983c0b802f96997e3da5fc2700df612868138ae3f3eed82826b2887ddfe877621816b240e23817f40c12e2f5c7b9d840bd75c27e1c23ee0fae304d74eee32c13593bb4c700f27b8f2f4689716aeb56e52826b253729c132b8f668d392e01ac94b58b8c67a090bcf20c17567856babb354b8a63a4b8577c095874de15aea2a14aea1ae42611924ae91479970cd749409e380ab1176c4b5f12611d7c49b440c63c421ae999e237ebc0571adf4f0846ba793271cd3e15af7b1c33035a725c4b4fa1a875b2a0e0b886915d3a8d53eba98a5dec0b0b50cb9ee584b5f3cedf2a3f2549eca5379a80e1cdb43cd74668786c4958704d21e7d1f49daa3dbed76bbd91d7687dd91949494946481be96bdb5d65afb5d9f148d8b10be3c122836260735b3dc49bb1adb72d0225825362627a445b04862707252b31c3489083beb984e8cc9e1661d9333ce3a7c11acd369968396a19bd9989c9ed9989cd2cc760c4ece6a9683c6e478b3eec0126a96831ab9b32e26e7ce684c8e38ebbac6e0e4986639e81122bc59c7e4d459c7e480b3ee2e4763707254b31cb4e8e666d627a267dd6937ebfa8bc1c9019be590b3ee4470b38ec9b1b38ec90967dd793139dfac8be9b02d07ed4c23b68921b6e1c86153046b56c245b08a60b577fbfb7916db70286d2172b7ed7731bced3b8e87b98eb2a0174b9e077ed8fbeef7c645b0665cd7bd5f046b867a05ebc5367a13c312f82b7ab8148a6109bc0ddbba3edd76ff795d7b230a47c292c7a97834d593b05226d1e46258022bc95961eaa617c19a99601bbd615b11f7bbd7ddb084fd7ab78dc709312ed195c0da7ac971e4b0096f2b611c396cae025f8f238777e4c8919b9b9b99d82ac1b6be2d87352361e1d251243e919405bd5d95704a4559d0db87b781d846bef42258b3950adb8a60cd52266cbbdf6d4f1971cc84776fcbb13315109f30bfdbaae9230adbe80dc4b68aeb0c2a280bfa22583312db7040bc4259d0a3a02de86b1040821cb38b73ec0d2fc013f1cd6ca02ce871cc4ea5db8a60cd4c23b6e5b06622b6d1dbcdcd2cc45ddbe3b0680bfa1cf4889b9b1911e42cbcd7f56ddc350971498bb2a0b72f615b8d39a481d9d78138a686cfc56b093b665efd300d1ecc892f5461d65d0fbfb874b29a00e830c2acbd190e11ad59875b280bdaa24fc437030065416fe3f0ebe2131765415ff3ad8008338b73d023478ecc727a864304396bcc82b2a0c7a9780565414fc43763798d4965f9a84797f388c8d30e212119191111c9fc204264c8ed668fe89758917e7921f5cbcaa85f44a27eb9ad3244a91d3a5bf26987562e4eee16c08b5cbd21f2fbf7f0de10d9fda4404d20cf2e2a22295d392bf81c9625233b6ace8c1b3a5017a77d2319110911c994d221312d2b6f9194de90417c960c78d5da0c78955ec23468352933a0952d089634dbdbd9b966ea8276ca257c5a8f0219c9270532f3598fce7a64a48b8c64da3f392910d9ba99cf0f26f72dbfc07b02d943bb987ec3103e69271b2730a12245c6242424f108667443110d7cda30c9267c564af456a16fb50ab5e7671ffbcc36e9a7031e4f884f970320dced767100646f10d4d9f49316c106434f206b359b300d9a9a695d842045b9e21ade2dd7d3245a448728113a24a665455cbdc819f485ceea0b9d513284b45d6a94be48525246423a3a3232ca4545444443433366b4494f840810d09021313130302d2d2ca669c662b1ffafd7abd56aad562b92244551fcbeefbe466b5cb3d8cbb1c3a9eebdb6aeab3c4af028b2e345938c8819e1791d890ea5a3abb8eaf0bc0ea54b795e6772f8a2a8b8e29cb8ef20eca7a697a7f72d9313d7099a1d525e52d6c00188181fda6c91599961a25029a9682256be625f3bd85e326eb470a059c110828ca921c204d16f0122864be01f4c379d9e9e9e9e9e72a7f73fa05ca8d47bbaf7a8deb37a0feb3d24ef29794feb3d27ef31790f89a3a04e4d4c7e22f1c2b4cd1376996ec267d57162d232611197882126115925bc2a61d54791baee34357f3885c23fb4494f5373872906efbdf7de7befbdf7de7befbdf7deef45b9f6ca8a69c662ffebd56aad56248945f17e17e5b7f3bc8b9905e56441c13555c74a8e892b4eacdedcf6bad1a2590941e21a62eecec14a8c6b82f8381bae01a265f528e7dec1700d0aa62debf0693d96932517754556cc24338614fbd15f46af56516b45b42287485148fc823e1494e3e8a1752818470f6d00363e8a24211d1915110d09e5a83394f770eff9dee3bda7f41ef03de27bc2f798de33bee7f41ef228b887e6f6743a79c23435d62ee3681a8342d18640e06986785eb5ef7717962f66a9d9e21f8a8a8a8a58ec0b9d7d640b65f3ea21c210b6c0c4d01bc95ddd075e1c4da7170914d84b5c2266e2f4e68953fa1f52373ad99e2c5d6d9e347f4fa27499277154e96af3a873a5ab6f9e3b4ae96af3284f95ae365d7df3dd61a5abcdc3ae2a5d7df3aa7ba5ab6fdefb4b57dffcbf2a5d6d7ef5af74b5f9ef65e9325f9e55bada3ceb60e96af3e0712b9bc727295d6d9ee42523d97ce9254a57df7c899794ae365ff2b074990f1f331f7bcb7ceba279f126cc9bb88979938fe6c7a798d97cca4f4a57dffcc94da5ab6fdef413a5ab57b2f9137795aebe79d74fa5abcd9ffe2a5d263e2d0c7ba2a439a5a4d94449732ce392e6b2a4f925cdb092669492661234bb686ed14c52d2cc2a695e9534ab32cd27315b9b94fad1c0c7c8ca8a69c662ffebd56aad5624298a345bce5115bb66666666c4872fd9a04a999f222da3992c575a566f9a49b118d27ff47a19b55a45ab1511490e89a2d0f7b5acca683e615b119f9d8ee3b6acca28f671c2387a46197dcc5c296f7d599bb16f118a3818f0641128b73277916565255fd3cc3716cbf7b774efbdf7de6bcfdda2ec6d20fc26b0d22e679136a94d326348b11ffd65f46a15b556442b72881485c42fe8bb97f921d226cdb6db326aeba135f621f303d426cd5f5959314d33168bfd7fbd5ead566bb55a9124298ae2f7c9eaecb6acda9aae5c0ac295d33b7ddc159333635decde5fdf69fd57cb9ed620787af2543aad45efc8912347c2d3fae129added6239ed6f7e369f53e4ed8d6339ed2dad498567d9cb0edeb3151d3a909df71c49f188a582c85982c9d96f00a3c885bdfeb5d8c0696ed4a9bf5d5666cee47e883bbcdc3366cc335b7a71f9e68cdad37422fa4c1b28d7a7a5a0a676cf4e969b04c43a3af0aefc392ebacf1fa8b3d30c467e7f0dfe947978873b0ff2dfd96306ca9acef162d905dd34e36a55ab51062908ee371f4d0be876009470f0dfc875d03b0c9f736792cbd4ba55229865f18bee72b896159fa404c69cb28b501cbde670396c5d3d47cde3ce39da66611970ec3d27bf6b73c6d4db5019beb000dc4a5e77d14c57fa2ad8706621adf430fc461f7f55411044be0e5aa8d57d37d251086b45fd0f6baee387a6827533579387a68fd11cfd0f0d18d6f71f46eeb43cf84cfcea69f46517ccf28a3f9249663638a3d0c8ae2c3eef465d3fb4587fb379bf0884f4f0ccf9a7c69357ff7399f71d8d6604d37778512675fdbda5289b3a5d271f4d0387cda72dbce7609e3e8a1dd972ca6690b72b760f7cf7a1d7731ed4aabf7ce71ef6e77ef69936d6e572b9c68dcd31cde7eb56dad7dcf3d6d190ccbd5f4ad36c616c2d326d3282d095d39645797e7bdddb97f23b72df72967c3bd6b72dbd3263c310096695008b987fdda98a673e6ec975d39d0ecca81b6d9302cbd4dee4a5a4d6e5a6d7ac25a6b6dcbd55b6d321deb0bc2f0e2aeabf5d55a91d67ab7f5f4235b3759ba1a7e80de7278fa364052a19f5bfe3215fad9c964beff32fd0beffcebd56aad5624198a62e9eb6cdf6bbc1720b6e11a0fd396d1d37e64eb26cbbdb79c6b389bdb9c9090568fe4b6b6b3b7bdceeb3c7cdeee7e954228d217a72f8fb791caf6a32f4ea429dbdb10eb2f7d41a26eeb99a159e57b1b5de64ebe4061db0e2da3ef99e9d3c84e256d996928533c43f3de1dcfd0c0f769a57717cfd0eefbb4f0dd2d9ea171ef463c436bdc9dd617f169936dc072e373e6879b9b9bdcd98b69b0123e417c923f7c72d9c3270d5683cb2d2c6daec46811b24fc5b62a084319dd694f5f3d5b43bba001e6d6eb9276ca7daf0849314d88dcaf476432d73194e11521c97cc26492860ceef4dcebf129c3621af464a658469bd6f60829dd81be9054a5d6b035b8c634d89132e4c833345d6e8b69b0230f3892676cac729f8606bb1d3992676c98b23d4d2adf1a5cee8e69371c39926d7c2d2b1deb173a93816930f279c3b56dc3d59a8552e922c029f763ed42be06573a7d4b892ca158442c9e502b394e474e662b6a0a5f73325724b6d5a0beaa29a91ebe66bc785b8d0af7744fe18bc23ddf49dc6a19edf16ec2af9651ee21ae29e11ef0227ecb68b7ccb6ccb669e3cb8d5bda745133527737659acfeef7bb05025126339943dab64d27cd445d984c63fe4a531ea98b7114f3578e59a42e4431cc5f29e690ba08c352feca3097a88b5229f7579632485d80fd9560fea88beff3f2e779b9efe58ebae8badcef32475d70dccd5fc9e54b5ddc6bf357de6ca90b6b73fe4a9b9bba68aaa2fe5de74a5d7c2ca6194ee9447cd6e39dcc707ac236e969b09cd50c27c49796f04765d5c697bd96f2a4c162e52944eed3f100332e0548810757d8020598f033646602a9800a219801145240831925bd0653107689839383de727ad6bf2dbb8ec3b61cf6dc73ea2c02f61cce417f318e1c756661585bd65baee16c6ad708f90152a654050b09c8f36be9c09249aac2aedab43f64fbf0a3c70feb5033592a6d20bcf76a0e92c54ccf238b46d8915532155204a45c041d59ccb781886431d71edc3215d2039f1e40201b01288bf9e3414ea6b77c870094eb4d38c6f8be0f02247d733b204c8ccf04a4fdc9ed88e35702f2f4782c152204247b3c1e8fc75364e76672412d6dda7ab32adebf8f245bad7a3badcf37f230668a6b52d24dba4937e926dda4ec9ddeec8bf7a3553c8fe70b420e6911c99ee7095dfa5bea4033c52c204feb63a2ea116dd28b55a7e84627d3c6306707d91bcfb337f6c6a26e077941de6ff9a16e9ba3776fccc1265b7b1bb4d7bb2d6d3258d26cf9be4b9aed461ec6a45c93be8f249392fae1b9b69fc7f391640b7ba6e95d1cbd24b29ee6918731575c937c80dc8082c0d2fbe1f9b4e9bd547a3fa30e9cd0500c8bb9202ea85db87be784da65a85de8e9f17843f6c5fa783cf685dbb12adecda107dd7c60be8f245b2d1e8fe7eb21cf7abbd8fad897ee86dbb12f4366d0815af4e663be2516e5999b4ba3c733829b746f37e916f958da543df5f36bdde382ac8af714fe3e14c6277cde334d4f0be4f70f7ccd2e01dc12a6691e1ec6fc9d1b2a3a4ae28cd4a436413cf24073902f86d1a677d42605ca272dc27407f919b9f780fcfdc6fb57ca6873289f5c104ff6fe79c0dbf174b2077493693eb9a0ecbd0bfa86c8a2d6d1937e7646f2e9dd7cf8f472b2771af3bc7eb520fc3e119054880f82649a494f874bdb04cb93e682e557ba66666632474b5a154b9b4c9634dbfffac5874b1f58c40d33226033d471f4d0c8d336f169cba5ee050ae3e8a1954e62d4b9873ec05bf03e043ff0b39ccf7a4e5b060fc396b49a5cffd55cd270f49430a52de30e9635d73146f7fb51882777ff4e3795a77fe5cd632980d24fe2bff2acd964d34b77cc01c427cb19f0f4345f26c1323c792acf9a4d6d2a691e05d0dd05fe96f0a903cd20a6d95c6fa36bfe07819036d8755d17821d08a6badb751deade0ebc240882a60eecbaee045e10bc6307de7b41b1bb20085eaf03ef05b9ee822078bfee5e8c8b60cdc2308572711a6e3a891e077697bbe04f77bcf74efce861db1d6d8deb276fcac29e9ab4cee18fa8db3e5c046b560a6bf877d54a55fec4752427af3179eb1e0a90c3de572239794dc95b57b9dc77dbfd0a0ce52400701bcb6d38c54bd28423870d886f4bf1f236f3275e046b1672dfc596840a359a42aefb2d919cbc067c0b86f2c76e2b81f2db5e29246ee2e5b61638c54b98b7bc06179714afa106d96d3560db0afc5ae1428d26aebba593d7786fddb6024379fd45b0662e687071394c4bcb4b0b6c2b82c56d2a00c0825550d85b2239790debaddb588ea3824753774b2427af59bdd5e23600c0566e9be1368ce22a295edee622c32d33b4000066a1e22896209ef9f07d85b75f956e696aee7c88efdbf0d55dcffa18cf811ef621fe76631a079b1302cd2957bb35cf46e9c322f78ec32b8b6b17b76c9025f1251b9fe89d23c50c9ea6954b33b47a2473a7d932dc90b9846ba58ba5db107309d76aa58ba592982bae7d0fbfdba87d2f7d9f2dc34d06bbeeeb6ea33369d5c3340b85243173b856e3de615ae7f30022b9c6dd46f7912d9b52e57e00c9227dd34a29a51ce52103618c962f90345dcf93c5dc660b0540d8f672a794aedc73f7fb216bd7dc22a98afe21b9da3ec25a761d0f4da98a2ad2b1bb622d3bef97ae78b81bb95beb143aa22ce6a6f9a47692bd11b1545475385c753c5c753edce18a39aee34c65cd34be7702e8b81f8a8a8a8a4ec5b0d4a7f5966f23bef54ccd5e876fa654450781271042841d9a0aadb5f7d485b679da31c69da9f92e20a4f4deef1345925cad5a2dfc6a2320b9dee43b049e2000e5143c74102122929477e47bee0443c8c935a85f83da8e04a837553c4d772c812fbddee374e877bf35b897f002b837a6f112882b5029c47d7f1c63dc7734ba9b7d1165c28bd8d6033ec4b74c3f4e87fbd22faec11dc40bf8c6181c96d1e6872b509bf5de48807a937f6970b80661faafb91184b4fe001a3a329253642a24083cecbb73f4fb48b2d5fa4df39769d3cac80d82200882e089809981f81c0be065fb6bc70380cf01eb51e63b886d3df71ffeacca0cd2aaf4d8d3190cab52bbeede3b21088127db5f21ecc833642a2408474118cae73327a266b4d979f76eefddb10037b23d8d1d5e09607f5fed62ef61196dc6b8b6b1dd3da0a4a511bef0e4db0079de2c3e7c782a718de91f58d610b76881a4c9de4be1771a03fc3c8ee6eb3e42e83dac1577dc572ae1f366fa9ddeee5c49abe96a36f9c334ecc18725add65aeb38dab1f48dbfefb12fe1b3528fb3b5ac99f68b8b4f9ae66805a8ef3ea303cdf6e069f1e9633c5831f7d2fb647bb5348f3d35bcdbbe475375c81c9190c6ced42ddf1799a6e61355714f73d50049bb6105183206487a6ac3e6fa1754c53d3dc9a47cd2db1916ed74b7f82c05557c9e744c372778f376b89b24fbc6e7e7a35393f2fd9701f2c4c08e7d315bc55e7b7b5bc5fe04a9432a91b3f208715fa35d5680e89758abc8ec80038cfb5ab66881249332cd2fa80b1b2d1ba80b1b640c7561a306eaa2057d89a5a02faf12f465e5a22fa28abedc3e51971ba80b9aba9920a4b12f036410a23bf42394b9a01f9d3d8b4e07d4a34d3b84567fab3c624eab87c9d6b4a7554cc39f05c89325cfea8e5c772acfa7439eb49aef6915d3a8bf21d32eee5b7cbb13f83040d6d3a336ed2d6a93e88821234245829288b4692f509bf677489bb736ed2f9036edfd69d35e9f36edfdd1a6bd3c6ddadba34d7b77dae411b303c68836af4e9b48edb2fabdafc34eff5d2cbd23c7b38e4fbf329da4757ac963a77f916fddc4e98fbac9534e1f4bfde4274e6faaeebae912ef0aef9dc457da2ccdd85fad15297eb7cdfe3d02c0cf9a63c4e267c52962f9596f8856fca4470ccdf0931a1152f19316095af9499388a4f849918050fca4474354aa18c4fc4989809cf849877e527e52211f133f69d00f223c257e52a01ef8271db253fea4371eff19b3035651aa58911a9f2b3a8e00804f33c788053e6338452cf83cd10a7cbe8e189a019f2d23422af0b92a12b4824f3289480a7c8a484028f0f91d0d51c133f7762b0a62e2738508c8097c9a433f29f88c09f998c0e7837ec4f0f922c253029f2da01e189fab213b253e491ec7a718b30386cf0fc608143c733bfc7975ec49b84ab38cb5ca576b458aaff296b4458b162d5ab468d1a2458bab13c48720407a00f223f3e333c3e7c70e3f7864f0f4c0a1c70e8c1d1e313c76c0dc1d2d2c3a46745787e3388ee3388ee3388ee3388ee3388ee3ae4e8762e97c7e8004f1d1e2aad2870d4f953e628e2a7dd470b2f4e1e2a7d2070d37953e603e963e5e5e2a7db81c2c7dc8fe953e5a4ede2037489b164812901fa41f9f239f1f463f788a787a10f5d819dae121c46347d08e17f7c58bdffe06e9172ff0e9c3f6c286152036a46c88317f62503135c47c6a206b70f11f2e4e2e6878f1d060a201a6d50366847959edbc945e5c481e2ea08b4cdc71182f60601c6fc1385abcc0386c5747cbeccdb938f7c6c511341881b12f492e48b2a316a31bde73fab0c1bca4b0cc4fd28b0b0acbfc20b9c8482cf373246b3961991fa3161b4c58e6a7c8869811cbfc10c5d450c2323f4335b800b1cc8f900b1a3eece117a7fd14c1386c51cbec61605e5e5c5c641807c661b361478c1135e8b8d081c366736c16e70748905bcbacccca6432993d87c3e705cccb71f4bc7871390e9e1efdc245761c32fb42b6c383c78e1d4618a1a3a343474ecb71c8ec8b9616c761715a665fb4b8dc5fbcc57b506f79cfe9b2f798eef29ef12fef291de63de06978cf7717eff15ec37bbac7bc27751bdea33af717a44a6583e56997145661b394f9496a19cdb6470ac76a90d1eca294f9396a19cd3494323f462da319a694f9296a19cd2f329a5d6434cb6434b7942d4aa095365124a639ed72baa66f144be48e7601575feb7ae7388ee3388ee3388ee3388ee3388ee3b8ee072082a82104cd0d5bbda93835a7eae84e5d57c4711cc7711cc7711cc7711cc7711cc7719dbdb13836c7eab03ad608bbc3f2b03bb687e5b13f3a93e7755dd7755dd7755dd7755dd7755dd7751de7dddb1d72812e911b7485eed025ba45d7e81e5d246ff4bc9baeebbaaeebbaaeebbaaeebbaaeebbaaef3c47beb9deed13cfda37dfaa7817490bef590066a22a1f5e9a016eaa1262a323a424a2a62e455d25c0a5b64d169310266470c0f183b38f490c1b3c38f193e323f3df830ce8417e90f17882f08b10629c48aa6d5a6fd0ddb6f626d5a4b840810d09021b75b90204080fcfcf8f8fcf8c1c3d3a3c70e111d2b2db37fd162b6ccbe6889ddfa45cb83d85e406eb47e68563e42903f6a883c417c2db33d80b0bfdddddddddd6dbd9515d38cc5fed7abd55aad48f245143f590bdaf511b78f68d31a49325204a948d251129211d251d191119151d150119110d150d0508bdb422db3b72d6ecb11417c3002a487223f32493e33907eec70c423c3a8070e453b308878c40ced8069997dd18271d86a8e3ac3515b4a2c2d3031307090b1c30c991e7ce0401d2376f0d8e9c1f3c3e7074890cbd2dd860011a94155a80e55a25a548dea51456a99bdd56901b34283e92256c3635e36b45eac6e205f60882d9e652d3e0b4000ca9ad432fb59598bb4cc3e97d548cbec6194f58896d9df50f64dcbec5f948dd3327b1bcace69997d4cd93a5a665f43d93a2db37751b6112db3a7a1ec1d2db387299b47cbecfb566badb5d65a6bedeaebbbf8c2e7cdafd37ed1e26469816baa8e951cf3a5e2c4eacd6daf1b2d9a9510e44b0dd17379c135415c99d7226b71c13540b4b87765b705d7b478c9fadf61d88f4411c7126365f293bb3e3333431ef5540cf0df4b37dd73ef4ec2a46c9590fca04aa1c89369144b3f7835e776bbdd6eb7ab7375aeced5b93a4545454545d6c7fa581f7b7b63adb5d65adb3b494949494949b7dbed76bbe9e8e8e8e8586badb51f8b6dd95b6b9358bad6e00534491491c2f0a84441f0f4fb4e3def94e34eef3db5f6b43bcbb832e293128974288c85f8a442a597f04983c0d74781bce6e8edc6588b595a467bc58cfdd55a91e277695da92b6dc6fe6aad48f143a92815065b8199b018ecb017ac055bc1489808a3b7c2601506ab305885c12a0c5661b00a835518acc2601506ab282815f69519564c15666c25f6147fa178b5545aab132bd224c514f1fb7d772f66da75d5da6a6db5b65a5badadd6566babb5d5da6a6db5b6d6ee274b77d7672855aca440a172c24c31112b51afc2fd8477137c4a7813e363a797401dab5eb2fe971c761c3db47a6252c252fdffffabfc44bd69bfa77ca59b28898f89a6973091c764ea656af5af4e5333c96124a7a92647c13d333660b9f56e8ce13a3129657e8a94664952c6647e90caa7ca97a95cc9fc1095a4cccf5029cafc0895df2d6dc7f9e0430f3dc8c8cc98b1c30e3264e080030c18313130302d2d2c274e6557b957c127b0cd8796f5c99f78ce67a6896d3d9c6e3ee7b394146c93313dc504b6cd186fe2399fc562d8b683f8d8fb3264842ff13e0e38948e61c050015fc6c4a87c57818169597b4701bbed29501800cbdd492cf353e484657e924c58e60769c4323f472296f9310ab1cc4f5109cbfc10c9fc0cc9fc08c9fc04992bf84f8182a24505a68cc1304ae010936162879419a64ccbfab0639c1cd80c867b68594f877dc0394e2898e564f161a507532636a365bd43cb5a46cb1a8796358c96754ccb1aa665ddd2b2bedf0448f2e4495b75742839493938483847f5c666bb7183864608216ad408c21644cb1aa503a265fd430fadc33eae0e1d2b3939260e4eac65b5dedc667bddb8d1a2a15909210459a3861844105fcbea0b18c66103a2c463f7c1871e7a9091993163871d64c8c001071830626260605ab8a7bccf3243c30735719896f5635ad6c7a1657d192debdf443fa56c69599f2b7de81718dbaa8e7e0f35c76c597d5fa6e2c45a56fb33eacd035f252949b56811b235a1b79724b354b74ce5f0c476a5d7a5445431414b3c293211cb1d9c882739fe945c223983973816f19110cf031411665f1fda946c22df94c814afe07ccb1326c234702f9a6e4ab14410165d55f84a882da31b13c5209fd14d11c5202744142a98a2c84345c43940219260f85288e205564472095785f8c299411c93be15624b88ac95451c7fc86ef9903585052ea85dea6d775b5b2b4eaeb46cf102c905f53f214fe091bbb91086d4eaa83d327defb4b53a5687e591e98e4c7384908e8c8a86848c8a82ae1097eb3cda79a0105405fd0786a5708cb91c0ca5221d4f30a2d08894e94d47a653d16928d393426d946951a64154057df3e81f9fde691efda3797a87d111468e8c8a2415d51f7548a6ef5b5b20d627d3df1f3748a6e780e4ca438b541d39b748c5b91122a6dbc2d46e6befe5686d6befe5b8ae76de077a1f08964a6128d62a8ea6533d551295a2b43cef8b96e78a92d092f3d65255cb73a543cde4f9d59284b2be5a5782f0f180340969edfba240e407966288f5a4474056fc52ad158bc51ac718b4b66ddb223915d9c2b2d271accbb22c56b328ab8e279292e418034551a831c6b70352f5dd6f07e40a25212121a161492d292929a9b11d90b58584c492909034090949154da996eab482c1e247d2f50ac086e620d377fec09248cb1898d829a5e5c9f2a2afd7eb45495412244890a8288d828282d2300b83c160b6339d35ff6f673a6b322dcdd7ab541a59638c8a2949b762b0461dbcfc917c548549bb5c2e97abba4091962dd204759272d1f27551244bab462bdb775c58cb8e66b3edb06da9c4d48a5c89aa950db24472ed32cdcb8d2d1055519f4355542f734054056bcc8124114b28263992144d50c55309ee15499224494b730b6f3ec2dbbd11e4f99cc0f3e97b2f29b6be3ac6b8d70ae479335e952410597f4455d412a0cb35c6a8e6eb0433228764daa40fbbac34f7bb2425222104b29ea2c0ba5a122450505631aa08437fb12c498c4b6881ac18e9c80868c8ad47ae3b9547bd39e2860c4c0bcb8aaa385581ac78956253525252ba52138ad8828926630e21f9faf004e63a2d4f919628614b94e812f5fbcb129728118b993091522286718912319615b15352c4181d9aa74dbeb618291769191b7568b23431ead038a5c66aad5d0a2e458a9b22450adb35458a1494c4a289947ae204bdb11413274c95afcd30e5c409d31469a9a282028548cb1429445a9ea418c3a42a545450a04891a215638554a1628619605a5858b0b05d4114638cd8ab159e5a0850737d0a152b6a7c6a50ae3fa580ac35b8ba825a9666a99ce9b4c997aaa02ac61864abcb1b96a79831cdae1863d0299015b3b000408b31464bf54ca74dfe4eab1833f4803cc5dca22a4e32536b3a6d70b962c58ad58a15aa152baa0a0f44b5765bcb75b43cbf22e9077a1dc85db071424ae98d9076d80f4f9656896e728f3c984eaf37373bb21d7920c915df0684dda803984d270e4a6f9bd68e33d9c3e853cddd68dfa237c6f02a679f833dad7663570eaa4c5599e24b55506b6fb51d08e9adb562b6b6fc84b8b854057ddfd6143415abcb8c0e367f7545bd0ea8bc6ab3561f61cdf4a6f080a49f91a3ce7272d423b39e7a7acbb9d109d2c08c8e3ca0c8b43a0bbf20643df56abdf5a8efd671923d68889289019136e90cfbf27d24d96ad13246cb17c8ef94f9867d310055b157c20d14b2b5d40a65a62a646210a44ddaf6bbe525425a7a951b9096fe9b81bd79442828a847460f18bd30406445140e13b00b96801203b2de0e4189810e3c119501b29e0ac9a7b5d6a2d8400ef24929a516b543d6db5b0a136eb8a1781d2f44f125031b4651a5478c493c79c2cb492c75e0428a780a32944802693112010095f81da8f856a2eb082858222c03289744343de05522962082ab25ba8e4e3e13b12505937b228a36687d2eb1258592fb12451b90901051aac0421145108c30110b092f925f287da528ea74582499c0dd12e22b0237268e5cb026c49611c87a9b228e30b8f484d87201596f290dab7922c544ac042d2161ada82a854231667b9ccf996cb18918c27a1a0bab8b0779212cc103f93c8f3669ae14d36071801142780d8140081b80810584fc98a03580041a2a7401081a18c208862a40bd7c7ee57cae740723f0d9810876703282480a3e54189002065859908204564290c28d2a89ecc440020492c488e406246b0847d001c913483153215190814f144e60822870005585286060a58128e44809214323aa1f64d785940c480f0b2916909f1492c892127600052194c4000a3b28f1011460b07a01144cc01222c74c854041074b0ce4890c2c219028a42a141da56e45452e205f990a291a821a0399ca5448d10b542c2051990a2922c190a20fa8b4508481214512200922bda41bf23bd251c40a223926ac50407e4650e1901e11161009ea8024022498a99027d0405502b2cb54c8137e62a610268cc10a3df93ccb97145e1a54005cdbeb9d87199a2f37a62afab3b95fbdd778afe30e1cf7cb5d1d609906cb67e5e1b31570e590effd217d58028f6cc275d66bcb81dd95405bb97b39aee3bab9ae032f67ebb51ce6c07bf1596f5c0e03d9e1b383ba243190f496cf9bc4eddc6bbadd6eb7dbed067e644b47270ca4edeeee1e2a3a4a32e263717777dfa406cadd407237cf4d3aed4d52e7b44eeff0babbfba6de806a501d2a0a43d5a93a7547dda93c3e40c01f928cd49cbe6581a14034c8130359737ffd6e716120a9102520e5fa93e33ef266bf83565c08bd2190f5a806f282480f88a4f526534a29ed9ddef9ba5bdd49f5d6fd35d9b7eeeeae3ab4a8bbbb4f96eeee66c9dddddd9d1754df414db65616087f64eed63ea4f50791cc3d4816c54ccf5507f58ed73ba6e7b53ccfab4949499ee7798db2b81af1cc16d79df33ccff33c4cd36d3dcff3bc3be660933baeb334b6ecacb59df7aeb4c9dfb5b957b678813c69dad2d41a36df53db5530094908ca627ea9834de9caa186b4529aab4dbeb98300593f08588aea5e398ee3385487ab913629e5388eeb6a7f60c312e8b95cf1f50cdf7aa93c4b27f8d34dbe7affe42ef225a5e924e5e9acd2e4aab29f2a4f8e2a5d5f95adf25ce1f3f6a750914cfeac0de19de4fe10acdc3f692e9cfa893aed04abde78f5738666f2d369a6cf9860929f70c96b4394b2e9b52150b2e943a8b209b70ec3b64a2729c1b3caefabd2bbaaec9e2ab9a3ca7bcb267c2acf9a0d9bfbb5214c727f08536e7c9e7ed2366b364a997c6d8853263fc4789a626260605a5a585856564c3316fb5faf566bb52249f1a366fda53f196f1acbb39660f97da55892abb2f56ad3a48248b8652e559e9d5334ba93f82473288ae2f77da6679052d384cff0f42188cf902cbbef04dd3f1ef25f0fb23b6dd1ddb12f74b6b3b393bddb23dae5ac16a95d52a9d4695a39756f66c6462b87e1695a39c41629c9beaceead30a52af7deef0d35c37fa4179e9ff775a99f5f267f92390c55a914189247d54c624acf550ecf570e437c76f768066bd2ad8b414863df09c8d316fde321bf1e642dcadced51e6ac91b100dd3d7c4fe4c17f37fd64325d71146fc35ce5dab4f6cfebd5247b9369099bb1b616c27b1a3b6f7a89d2d728c5b51279b27c5fea6c19c795ea278c68a39567681ccfcdcd4dd0cdcdcd4a9542911c582be8d5ea75b57661adb76c0241d479af3dd519ebb8fa5ac771acd54f33e4382e5471c2a7e97dd64a954291254a4b1fa5df48e928522ade1e863509113a6a5197918e2fea2252f2743c5d1c4de75c4a5474f9c8ef7b51938aa752a965fabed5485293beebbeca8595e3c0ae725e377a9ee7dd86983dec1df4bc12c7791c573f53eeb1e338ee350ed76896fbbed249536bed2a8ae3790304c1d7c0d37c19c4359acd366e0e5f036f329d4e9b876b34adecbd464366ef35ef3433364eb2775abd651ba9ece19996038ea08223a820d3d45cf36ea3cb211622d485dc9dfe5492ab4f4401696fb5e0aa15dededac8b43c5f2ed4c5c39486b84623ced868d1888d69780f74a998e21aa5b721668a6b35fa4a2916c3d2474dfa19f0bbd4a4b5fa4ecc15d76af55cbd8d2e574ca949dfa5dcafa30e7d9355958584d05a6badb5270d97ebe9b30543db8ab6d9e36d27c4a98617448d0322dbb778d3c5eef4daa933dd917b4d144baf953a8f0c3defb5eea56fd526cdfd5efb5e35ee1d4d97b9569b3ec8fe8702b26d5e7bbd5aadd58a14c5af769bb17e1e085faf566bb5224951fcbe3b049969f601b7229f5c3f33c497693622723ce0d6d241448e5c3f442bd36891cf0e1dd912095be0aa46ab2779e35a786bf6a70fd71ad74e5ea3a16a3493f74dafd14ace9d3c4dbd468e5fdd554bbd66c23510d76860edc3b4efdceb275cf330adf53eed542be1dac534d559af9930cdf4970bd74e702dc4b4f0de53b8464bbd74167e9f04d7566f5c2b9de6e15aa946f293d768dec59398467e856bdc09a63557a399bc755feb12ae71b572f7de3e5771ad7fab09d7c27f97fc5ed7e6556f0dc2eefb5aff36eefe3e1bad4c5d40f07b0dfc17a7a2a8d4a95b697335ab189a0100000000d31600203020100985a22049a23c917b0714801184a65c62489649e41888518810a3082100000000008c00489d0800210ee800a2b8be23a083d82da9808de0459848441bf284c38d49a73b9fc282d4698245050e8708c73a98e3ee157c357d99e877f6aa5af80e7262066836b99995059957a1e185bd1e7550c5e568b084d251f93ede1e878b432b959db8d637445d3d2dc2846d01369fe39304aef28a833d5b25d4af1b7762e69c6606b4a77996eaee5cbb908ff5a1bee58bc06ec28f80eeeffd08d7509f971efa1e699812c97447fd268086eb73a0f12c7ab061d59ca5791983f42937c6acdce6d41531c2a2fc7ab6654dc5d132d9d0a500bb429837bd309803c9721bc27d01c0303a5e88e30b97b86e8ec313feccd3aa95ef16901c831a451c415640f7f535c7f17429691d3db4727f538d5361cc1f1d1243ad4f99999bcc9f086917471e546554a18c4351c80fb2a036b4097d5de4932b7c0bd49075378df0eac12554811040939f0ec2afc7da57f0c08653d87433b776751760d9c5546d2d58bd289e16b953c40637361debdb55d8e03bb5705b56b99bbc37d66367c1b8b4464ccc48164d9ad0c8577c34c3e9c9be39732b2a4efd6edb7716bd8ff86e96f711c5699e049142ee9e635d73d56bb33397592bbb916e5f06a12bdc95a1bfd86d08dee12d83f5800d56f7e6e55e86a97a67ea9ff105a8500f3d91a8271578549f9e973150fbf0ae8591f203de0e8a7fe22a28f7800faa5d73e8f836c8e2672eef4059f3a0b5e34748175e8544767d33330bd060ef145b55de47b63c57d9c8abf0a34257c47c650f1151025d90e2e13455b2e949e557024b5bff496596f44470bb3273183c5b59b68882e7866a7216cfddb5cb36eabe5363214f3ecff8fe4073075cda2d214531db1e34f7f55b64881cf58a046df5e8c90aa0824aa02bbc9a136193e03b98cf2301411446e3291dcdb5c3f6110b795195aa854da6cfc61d5210b51636f9785dae34371e98e49b2efb603e939eaf57d034375d0f8b42ec22b62cdad58b5c8437e432852c94dad1a41b6d8350b79882649b0e451726d35119cb61c499f0bba7e6fa3ab6e047a01b8adac23b1863332e8e7074f3b19a1ba8e2f4503ab52189ca14b8ab726eb28f9aa81ef1d8be925d9920d73feeab2cbc7cbb56759f8246cc9a5b83fe20456498d46f7ecfefd62ef79361969fc27ff2e22ab5025698a34d26b3df53a0c52e469d6c3ca6cc288e5ba48d9ea7bc2a6dffe370a59ddad6ec9d06078b200fc7b5b1f5690ff106718d9a5f99a738979d998294cd6e7828d866f2960d8232fbcfb1b9996116958ccea5e29c1254c674f05fee1c3a62e32832b13904c4e3844bf841421022011672801e1b9aa61e0d3d1f8b7f7ab6a04db6fe8f175ed93aa79e3966179dc2d851b8e87b00e7b111d7d54a7fb9b09e98f03706678220aff8aa89e7366c0a167254dbece461ca43bec54c98caa051eb964e4d8f61057f808df2174b68ec35e18a17e2f2d2bea7317cc31a0b1069db9923f3e3320c9d46238aa7606cbacbe3634e9dff1e7c2685a65bc824ed0eaa5217fc99f576dc68a06f2b78bfe31b011917795d4751b9f941d53f0c9344a05a7f34ce51043dfd5aa0a588a59dfa6922fed8131b5eec2e7f5bb2f99664610c84fbbab8da2f8a36ae81988598e088125294ef1bf2a2344d6d605f9b275e3f570010ed02c4520aec0c75bbcceec8a4acea93ebfe1c9dcb7e30651d2fdb566496750018c5cd30432f0de1b66f9c8aeb408e5e01c7245b3b8afb0ff1b19d3c8fed59f71a174c9a3dacd17f58a16369d6bafa4be467dbdd936ca0ecabe3c4b18ad18289a28c13540941a3cab9433deab7e5765ca5c9e97cf003b833d13ac7a892086c22db583fbf21dad8e49a9f00e5ba72ebe6021639e73b1fd4792f99827536518e65689a982b85d29c65d9d9d943ce6ee9f5bb3bbfdc1392803721c465a61a257d3546ebe56b85894a53c6e6d3193ea70842b0e240b8fb4c3d51154b6519b94baf4c3e9d065b104917c18e237048690e54f22fce712ae0ef5b710b0d0838580e1c7710a7e7eec0ad56679879021d7e3583185c4f1fce2cb61090e217c8b946bb0d7ce5f70d070fa5a8b0d2f59442d7336d4f0396b70b272f97c211829e5c35a39815e70365a7d6fc58f2502dcd8cbc1c78d5b83cbed89328328a7a08865ef2173c76f1999b641eab77a6a7b6fb86784703264fff2d2272e1af5ac31bd1716b7cec5800266f0b988833a3eb60c95e2c909f94a54b66857f4ff9a6302b97b46dd9ae7e38feccf9d747620854cbbd2e2242a17fdcdfdd4ff6ea1b6b9cee1dd453eef62981fecc64566f7a3f06cb3680132924d0d512baafbd88943ad44443828ffe63cdc7c437baca202e4241d745fc297dcb0fb6b80940e372cf5b0367f4ae3bd0c075aec9499aa7ed36cdbdff38c2a74333423080718dafcfdd93c168e0600789c5ab0d4819554c4754efa23765fb15f66b1c6432414c3fd04b8e769fca0f421435e8bc51abe6b5df290ba5b909382a02b331a95c3a0469f8f94fd5ed009b5e7ae3e41445712c5af24de00c5a30775703e8344d00301395fbd20de098c976502965cb6ec04183d04a98140148ac23b580e2c43c8f7a986fc5a5913cc2c878ba98978550dd60a05d999801f6d3bb1534b053953c60e08caa5ec44f025f83110f880bf625f968769599b4b018f73470e56e63c5a65bc161984b45662fbf8485ded3428701e9d6bde0aec9d0dfd4f99f74cff6762091e5703894047ac939d5a69a6ee9eeef3320bf02f7302b0b037407df73729f037f7ce74c27263927152b8df98d495ab06f32b261dd1cd5e19f8b22461c18da87b07440748a9ced5442ec2e66a84ba2e318aa1bcc9b0cc9007b8e3739e720c05a315c22746d02948f0f0255f473c1d648f375bffa4d3c6f36f2cb43439c0581f527578dbc26f1dc1f530710c305714532095755a479230a9e2988e294161c716fca16f3e0dfca708c2f399435602b8df9947a73e938bd88351a874f14fb2b42c745156757bf5de5e524bcb0a21e83695ed08f91e08172fe45026060f4c1a7d8e11e16cacb4414afa5cd90fd6f54907ffd04861139f8b24546e2a8abb9c94af59db610c1be641f879ac3b8ce1e7b464b559e408a332135506457c8b3610a9fd523717a470ec5627ffb82aec65190b54ad67f78573243ae10408b2487635a1092e1617352d714bee330e9d3e8276e7c39e81bed6d7662a7e058452b6a6b2c752f03b276d615948350eaeab5fa2e8e0545b44c6503876416408412db6d22ca60164f2c8246a2df907e91fc36f7ce52f17faf6290f91cb0e49633ec9165c04cafa2c9fe600187347c9fe5f42389e4dc790608fd17a5a62872935d3b94e3e8c39e6d9b2b5a09a533c242563458aa1c4017dadadf96e5bf6a78c987ba539f3f2e5038cd53440350cad335f140f653bbf8a7c1451c8a5e44deb2d94f7d0f89ae154518cab914cce4228ec38c8992774905313a6140f97612d79d1bd2a805db348cf720bfabbaf5fe09137dccb035f55ad36f4a03a81b6eed26ae893441f5065a68b05de3574b9e5d5e2655c993be0bb505a1ce35977d508294b8db14543ac1026434d53c9513a176231c13bd8bf2743f7ad22d96c9db2745dd2342eaf72b8d5ac1a63230b430c4d407193b4fd7738d294dc0f188c65c03722437b76daaf52f7a212260ec9f218c1cfa6ce0db8a8fb7f367794634c270000959051dbfa65723d9ca8f26213898f6025d48ef2cabaeeeeedfe2ddcf2f93a1adbfcea277bf7d8ab46121c15df5764162e22a354e03d35631c5818a580757b015363722ddcc23497dfa979ae6588af56356fc4546a5af5620909eeaa7b07af1482215507855fa826e33f34c5bd5f4544d2428368a9a8b0425390772e54170e97eb32610202425401396b9fd3205279bd98dcee7345bf730515fa2fcea22afce56d55c8ef5f9f40b7a70c987cde64103528b02583fef13cd934374e0de476fca914be6446805ebfc928e2aa030d8c8dcb11a6e88a4eab91a6931c5900ab1d61bc76e20714d4abdd1e37cae8798fcb7b5b4bab6445c1bbcb689e1791c5c4c1005c482e44ffaf16c6351def7cf331c483c83ba805a4321e3adf80a4c3463400b244b31216d8ac26572c8afbd3845250c4e9df37b4b60f2c7976a8f0a62a3994bab78ce486a64b3915d72a265ba92e995d6c40bc6cb99a8b62af72dfc2b31914a18b4d6ec5e3978142587e0615841c01749356618b6231aeeb4ead9592977db7b1af51425619af71dc8c576336dee9f0bb446d40c2b7379b601edc77d8cc7fc86eca34ee86211dd5d0070077a74714308c5eb14869b3f0f94c0904f429a532d85b916e34a074a82526ad31a7d91bdeb3cc7b7daea36708c26daab1bbc2896e9e3325f06e03699a35b641cdd900574ab8cd06d32003765c50853770f27ebe81699378979b2846e947943cc9561e0b6ec829b32edd0e6c9b439cd23d3e7305fa69dd33c1980db650edc9671705316a0db326d16f36504dc2ed3c69ae3650108372fe3a2c5bbc91b3d5182235ffa5ba8df759330e9ce229f3ad0a20c88fb1aa6450c26a8432fcf66cb4dcaa06940a2d0a773bf6be4b6139e95e59a06cbff5d5b23b7a2205ffd1b1fc09c031cf063212a45d1ec54947fb266862c63c63f21535917c0759a286e8a047342854b8b2c5362e546a58b7814dddba2104ff04ba52657d9fac5f4f2f1204ee7a25ab433ab217f1bc6dfb14ba485c1eb99b1b3587c47e76f7b87e66c2dea6bcecefec9ff8068d1785a57269cbab9a6a725a245892695a4b6c1781887e64ccbe96f9cdcbf49ffd67bee0cf9e18fa6a17be051ed2bdd1fd1f6e5cfe83a22e8fc25b872166e93627727d7b4950bdaf473e97129e7e95f78829e832f9d43b828f463d2b96eeb6cfe2e267df6950fc0972a8d2c9818ab42cf867462c417d483e306ef58165e12627383e030e0174305865c0b9474e01bab0aa4967bea90837fa35678a6c51f385cd7d5463df9cdb39a7b22b468364a7926c4a062d1d0ed4a1568f191185ffc6843ad7880cb5c16c7758d5524fdc7a71ad781ba6ca517bfe92711cefe7de9aaedce17316eed61ae5e41ba36726484c81d45b94f6004ad1050796e93e6fa89051c2001b0ef275da63fce4b29ca03fb3ca335bc304d2370682f29b4d89d28ddabb165fd4fb6ac0dd14f5cfc1db710161e5226bbf2ecc3061ea0518029f7327739d081deaad20b9fb07666d68cd73a52b1d5527961201ec528681bb7d8a92df98d6855d89274c7378dff2f5ef8ebe4d9db1156f8ebd94af835af750ff95701ab7a5c6e4f76b4f05092b2b2059ff0b2d685df17ae62641ff1508cc63fca62ada99fdd06a04db0a7d22e01f69ca884c2309115c389d393745554784639f9c0221377b71a112c66d407516ea45d21e11ecf4775592b127e60ce9eab03d379b5b794204fee4b5f3d4a3e1e7ea787b024e5b49831f4005d676a05ba58b6e80178ddcb972e9ca7120df8ecbd58907daf457364569236782990ff0e6eb1684e14834cc3764457913c30057a9bb927fa1192f3c4d738c777d6282c5d246a10c0048711db906049e366bded454efc3da48efbf2b0ade07b87120e29803cc18860620488742e1a8e9e7cd1818594d82fc9af076b3c896504e23a7e8ee2d04d5c5b7a9d41f5056835f00f72b000eac3df81950b236b12642a6bbe624425460431e9b4cdd694626c1de368972e534085bb7b39886ec75dd15f352ba49b6f3864bc8efbb082fc99a350633d2009e9b61389285a00b14de145a2eaa3d878563819d1e97a18c5f0ed5fe18cf48b4a1a6c622061b646ce842418cf41f3a15373e152f2df8a687546a74bab6cc91153f08cc20c42ee2e968e29b29984b26069e6da268824d828647c09dee4ed70b9529d44427b11af0789f18cbeb6f7f6b5af42e02a777a4104ad897e66b302b68868b5e91bef392c4380c9df32d11e4371e9a93e83727c563b48fbb130caf208d075cd0a11e39c3d5487137f7b8a76cb0c62a2bc5132f9d7a44b6a85561451ee8ab2937c761a369d83cc5b0877ac10ed3ea55484d11665e7789048444da25ef3ffacb943b03682a44c4476eef7647da50d3c868243a6f5fb61df2a4a37aae021de09c2b339c787364aefb9b1baf36306b50e54cf23371a6669405eecf7e4de1cf73b38d50a470660e785d4d616e7e70095c954fce5c71bd36edd944faf0049ef8eb144cc9f0cb7732e0646ac71c2cbd4b97e47bec79f3f0866c6eb481a005f9a2badca7f0a751c4a7c9c07569b720133f4b6178d2b2cf8fb555c4bd13ca9b572081473e056513671d1ad1efe40cc8bdecc7658b6f61589d510452716c08c2d0d75308bb7d19dd5460cbee44edd63b54ed543c1b9b9c69b1f395f0501b38ab3994ac567452c7fbe62f9ccd985aa5c4b2527a644d0ee93009748ebecc9f1c412954802b3626359361329aec9f561d3d1143644643cb14347452e6db6763188f15eb16c1855ed8bef2874ce5beaaebcaab4568bbf1d91c869bed4093727d00d1006cf1b9badc69701917a7d93a11fc0c59b1134cb44c4d508773677abcc12de2c7917ef5cef85d01664c10bb025c51f1cc6c0d3981f8058dd5cb3b3f26559a7445f3871093d17afd4c45f0bcb0f8a773297fbdb3a88c25b04e2f14a60368ff7a363ce6fd4094ba25d499e3eee788043644a900b5896cc70830b7cdb08187884b6672a4b841302d19b88b3f8a5d043a3ef3e3fc4131e6b2e91480c25a6f126c800d0ea6bab8cc03be7923ee482ff8706e32d88b32dc7e8232f249772a330154e22fb39d39f1a798e6e133aaeaaa2f4667ece5e150ccf130a48b50d53c0110dea1468b6a859adce1129770525db4dc4a5dd72ed6fb52a08561ab2de8ca581ce4f434decab0ffe9856091717702fc01cd7ab27b127d04bab570abf82d375946a5aa0ff72035e3daea8ab7c5ca9b7f2f8507ff1d1a13ef9715a5df2b176a8efa5010d84e5d7dcc95d4cd0979e9f26ca2f3790bfab7b6cc60dd04f3b262d90cc878a63c629218010f43f9e421f54debee9d043075203b680ba0677bb9549d60057e11e951faa282bb151dd91aeb8c956859626e145d111047404d8d93b70433c161cfe44c4f4fc55b0903c49f9f54bf9cd3e0147ca694bf386050646c5f64006be1aae7e64cca0cca709ad44346a2e4b2898ff4b31592fe1d782c19f17f7618525c92d3a6cf8f47a9baca2c672f918211586320198637265c4f906470c22bb06b1e4a2040c2b256385a10866d6a2c439da9cf3c34f7e7772ec8893596001388d3f5f838845813f2a60403db0928b72b2708d09b2a3b3757148875a1e1bf8cb5248c4e85c738a337c407a49fbaab1d329f7f288b8732ba6fab970bba2565b920ab61e82531408e23814db262cb289911beff6a23bee88d6e87f86c97157259171ef71885f318e63664120e8cdb19d8fe57c11065a3513acd22b76b3865bf0086ae72c439c48fed85358c8ed533f8d396977594a417dfc54a2e49cc8c72ff5f4472d8ea8ebef65ff8a1028fd21d701661af2b32bdf67046560f1809b7e776b4dee45b0d28c5519943c78d117f7758e8189395931a61d9dfe92bc6c4077899f258d1492e5f9c6cfec348826afe95eff0310db2d65ee90bb180a2d71c9543c9266e3ca4775f2b8bf1ff6dda5323757055307c1ba053f9b35e4052845abd20bad138bf25db1732e2133156b02bbc4110fb9db3aa7ea6c348f7b7201f34d4dd37e5d27c773e283d3b5caf4b75a29e4ac2f992aeaf1dabf2373d8f75481b82fc765027a98b7e39931bc51ff4cce6d7dbce14f063beaf1724fdace5fbf72822d45efa7d8f59283efe5e8e7ce24737eed36a5b93989cc22bad4872b44556e9eadbea5737691b1af85f7a278760a5a71876c789673d7fd9f11db6c506c8dc2fe1fc819f81c91b15870df45cf283b4d4634f6314db245dd1edc347948434d0210a911c3776841894c407314628729fdc8649a0286e60dceead45e8a31772f2781d8215885cde12624c05178ee3660a99f3cb3508318392022e86892bb81fbccea5081c1d939b8cb1c6ac423c515223dfb31699b50cadb7fd8a6b0c24aa9085b0090aac55fe057f2b883606ffd7a3e7365931e79f551d4c08cd3d66b65a99aab92d40c468ef5d950d525f30a64d9b169375c5a717bfd2324652be4b8aa905ff60531150c45003627c9fcede2c0918942cf6276dfe74c107c7aaba7490bebeab7300b0a8c4098d50f95c5feaa27f2de312e1ff637ed7c35c5cc4af59e984cbb51523b76cafed1f27d1fefdde1a8a0e303c1d67a47487c8c61eff77aee305383bcb20851e080a693f0e21464ec244e3e47168b9340f1a0e1e17ff1c8448cecb05fcdd24970b70973cafec58832dda58e926903a5c7e9ab92d15862f28f58c6c98459c6facb7be0b68c085b991eb73e0b8c5598acc784166e4085b3bceb0ca59c4961803cd1ad7d570fbb81de690715753a5fc488ae2f2654e185ea78e85f084c5549ed6b47ae842b61c5e3ed6ecbd22cc75b9906eb5ad1860ddf794ec6bd315d19246b60cea4912edfd50914ac3fd45f23af88ae45036ad7ad051f0a466d90a7f5d064d9e0a4c9b2e168930537c05192676a40a946fc6376fa867f4807503961286b7d043488b4de9a871e77929cf29573f41a0ad2dfb95165d1d2bf035e33dd340ea3e4fadff152045d12243afd8f3fefbfc95dbe8f8646ae3ce8fd7aefd00f77069638d4673f55a42b431c0bcf33820f92a01d5eedb7c34fb80ab8674b6ebcba7fd89dd181a4e33333b55d2967756018321a364367ad912791dd9a1bcbe2e02b8428aba9f7a26967d7b8838be125162d182d6edbc7a5e82da4c88d1b0f6446755368ed0b150556bf5b18954a15a3654e57d596e32e06b1508bf4cc918abdd386c64ef438b8229cccac435e36558cf3c814b52b2ce1d92924ec7fe34d50796f64b982904864b7c5aa505f8c183e79ffd20b974d3379cc968cce25490b9d350e287036384a4ce173d938097e799c4d51a38649f0074b299b30ed1c4b4e7fb010a1b5b4faf7a1f1819b890d57525073b1572ba8eb2fc2f437d04dad46fd6d9f7891dc725c569c788ca5953a7299e829becc007ca6e0c206931df025fc016d448810263b7bfe1e2d3c8efee009b12730c71d310e0e302efab6b07ecd306f99db72faec1428da0be0fc25760d844f911b25dcfd0e521a1030712fea49726a1086bb54ce33748be9fc25eeea2c44d80f9e66ac9bc0f9a9bcdb161cd096b858d02ba093fff14ea006eaca3be8fe77b089e86864569c628fb793980c01aa354d90f0ff17a388c6fd1c929f184554974a641c24d668c9ac39a0f9395e161d020c9ba447a5d751108423526e82480ce306d9a108dcd3772c08fa0b1ca361876a15571135dd0197d88f30a9d67417a8b76bec46391b37b6340528933569523f253bff81bddb44c22a239c0d2770728d8d81e90be187dedb57b8c6e03d0f3f467135aa9f0939d87c8da00273f2333ed4f4286554aab029fcf71fc95c7432143ef0dc5d9ba1b588500a8cea1bce887be1de50a8a192a6d515e796d5ff67389e716f3dc9b21c15bc0ac6b50c1e48891e42f12344940f67014311b10a8620f9703a21ca76c7c45dd160994842972d3eeeb724ef6abeb9212b12179032be6368dfc4503df8c65209e314c01743bdefd1d6ff4f6e160ba1bb4acd0a761c2d007d99d0c844bc9f0842066908834d056fc07cd74f2847ff71c205220c35653b2840c16b311131a986d329eac1a4fb2a87825510d145774f6379b4bac46955d589ba427a1c75e399189dc5476ea10e68c1252226ce04b03e69350c9b141951f74010f07bb5580f846aac8e6cb0d28c2d99ec55d18fc424fb2144832366816d7a1a398f90fd2c92336220fcb419ec0d90cc2d4925c6025699c60623e654766cb81b8bcac3f2d01bb269ee91b681e01605ce6897f597c4c5b7c445327f3a8d8a298d5493bf0cb4a3eb5289760b452f0e424c326b9d028927f6cc8df6cbf806d4d1fa1cf639652844d5d9265f219d19b6b3421f3adccb9bdd763d50cfd57859c0d3d3c32f333c49626f18557840bf5e88dfb3416bd719d67cdfabf67f4df7e028225f2d988f6f1c2a86699b93d1baf8aa5569eb22f12507656feaedada993203477af6b18b254559e198af621b1341aba440fed15c5a8339229937afadffa74378c68c86d0a91944ce6c569329330194392151280846f550df251de1c90471b3341a555ca5148a6b550be2fa55eeaf141fdc5a3a3fa257cfc611f221549207fc09075a5f878c25c9f82114e6266c198c30efb7248e0419b4cd5ef2075438c89780103403d01d79c025387bb63ad5621cb8302253198a9f05804a036ad66b09385c837ddbc54996811df791441377bb857c06a17579004f3a4c6e263151c08939e91d04d93f45d308b8c606d64d617fb92081e76eb1c3ee156937319ea983a2f8724100a2735bbc251f009813d45c52622a7e67a4624ad18b2b2d3905d764c46c9104b43d87649411eb3e5816d8973fa0df6dac1ad41695342ab5c61746ec3afeed438018657059e99d54c459a2bb309526342ea7359aca3edca85ef7d078a66c662eca81b34d694718478825a8ba3dbc30e512b38ad92f9804701927a6794befb80016f1de3674243a31c34fa2a7c64b431cf7627351c690d582493d3f590530fcff6f1cec51d5b224c38510ea1fd9b424a7b77b93640769aa5d40ba8f2e1df2ca5aa192eb50d6cfe503821435c126e8da7736045e5476c420a940cfd70ab8f59b03949365f0cd1b94765fea401570643ab2382931fc62a1c111322c856254cf3a76d26b8463b42d356e15eba8dce7662602bc3e5d698cd6d70800aa5c93b924222527c0cb7542fd8383f11d43bc7154d955b05eea062357ed218581b1ebb43f36dbff234f6e98cd9c856838919c5360785fa0acec9c4c9299ed00e659d88ef0c38e536e51dc104b50726e99c1a5830d1ce285768c7485ee3cbc98e637688e87a52bfe1f66f27ccc4b485f0d89e0ee84eb5792a15a0de2e6b51526b22fdd97018b6cdf35030aad2d9263eb4ccf8037da12ba2ec5d517063c11f7c3cc120d929b1ca539085231e9cf4f82b3423879bb8b232ee31e5874ac10476837c2f4b1d295db2ac75f2a7a5dd9ae6a3a6c1975f18b99478e0850f557b1346cadeadf3c0392745b5e45c0436d4de083cf9148ae5b541058cf448e69c3c3f7acf95d576b3a5c7746513ca06b040ad9d4d0b90cadf2f8607de8415e314b643c2e6159db1eb74e4d7842438f3272e3fceeed52b632596896d3e8dd64fb9fecc8bfddefcb7906586c0af727c5f4ee2db0f1ce21f46a735903bc11991ede29cbe04921544275365d13995517936cb3524b9d4298011e1014504ef95b44b82a2eb26d9f49c20a252a3d03e6406cd259e95b45d9bd4ad5f6068daf0cab91ffd2b8930e884d255ec4154ba09ac26407aa92e8d0751c724db72654b66739142b99742df34a5850b5da1ceedc9a0eae50ed35061d018406c34ca0b983cec552be21d4388fc1790e935399d106c0b35f572eae870233d54002990e5a05c01f47954127dc2b713f79e067752780166834c76c58e428f21760b29820641d4237a4de9d9660a170aa3daf92569f9f2fd35ec046cd829b0619b60c3fe60c3563c07a344cdeccf75d6e96aa9442cbb8081e404d887971fcdb44ba46f4d0f66ec77934b95ccc91c43f6557b29d54ae3ea95915639a2803d935c7ea918b89a6e0cbacb6730b90c1386cfcb16e9642d052f3e4054e46a1bae0bb2fc737af05cd42d1aa37fee9bb19035c6ef2d5a383dc8a2ed8b2566628854e2e7492989b66274f44e4ac8c67508b316b58abdcfa29c4d2a97aa4afa2b55498ba04e8c39c1a912c151ccc9e6a2ee6a4c90bb0dac6318c3a04387a8d49b12af27d7fbab5a56ef83ebc659e739774a548b5bf4cc793f2b019db0bc00c37828ee44e28c263814db9f1bd80ba427ffc810aaba4422fc389f36a37e8f17155e9331e661ca8af1359298f6071e46f4f5c284a5441888a482a9905716517ccc10a566c747b3b906115b52d34d3b8ae9d0a130c879cc1189b043c56f294e8ab1c1895856706cfb1344c7883bafac1bea4a5307f0a9cc514c50b0e417455f7839d269a2e1ee592b998260de2d57677957f71e54fa83785574a9e104cc6b3d434c11fe2913fda364b05a0eefe90c3235bd0525651dd727ce5d3e93babe699b56972025d48f02a624ae550da707d51ad9093338bf3c6480cdc285bc087186a15767237561a473be2a92e0fbd0d4038c36855e215eb40d8e42c2c79ce4d08b9f94cd711e3ec203490f3ea6f4224b5762591e95acc13f4a3b1663d4662610f7257cc3dca99297a77bb985ae4f3c1d4af6bc583cc1de3d656b3c41b65c896fc27102fd34c25be0f7d52e14935a31f8a458f81d832f9592d339ba29adb92ed12365c176197f98e2518ad168c4b6186a5eac66e67120bb4d5052a67f2fe5ca123a4327aaaa56b001b243c84adc2d613326f6be7e588893fc61b4d4f09d510cfcf6b86431db56666c316b4b676d3523cb59623d2bcb59b5382bab5937527ae71d3f16747e515af1e863686f46e64806fb40a58b56b2d2eb6ef997179633f31fa1cf082d6786d829e1bd80c637fedc2846d4867c24a6d6464e16215b636e0e31724179dd82380280e2ac98762b2a093686efa5299e4792235a3c66cf77ba76856f04176df51bb1b5511fc370edaad7006e7de537827da33cc6e8de15d708dedaea199e33266b98e62f10c69a1c84e8d006789c4e42199ce9580ae4696a878defa54624efdafb3bb697270227c5dcca43decc9e3e886c1141b215ac7680e94de110642bd5c3cec218b8bc02a37318dbb6991a33ab7b554e2582e92c9ea942b0f91b646accacee5841ce7d57bc90ad52720a42a8cacffeacaaf1bcadb1d4deb4c0b92cb5aaa3b4eab900893069763c2e4d6385d5f97e70a833170e2890109ea91a60a4cb4e2bc03f768fe7d09f9953b3eb3cbd65d177620267a145872481338fc0798ce0fb2302370f85d85b3abcc03c204220e5104559f92c2e463524c464a84926128ea5332b1636c03c7280e6d11f827e489b1b7228182efa9127a74779833df8605644fb3198d6020a56dc4a8abccd0a72ac099641ee77c1522942a28e3430a9832637969c03b6672007ba61e4f8c6c38d0117314b80af8e3f348edcacb053d4635f98aef66402499709586b264026d781b631185733d359db800b6ceb7b7c6ac04b58190dcca1c79c817186088129d77f706b751f0bdaf840a846df500b42087a74f01d7a19caa4953ff9fccd2f5ff9f5cda7dff9f4c1e72f7cfdc5ef8f7c8ec630adc695b624a619a0e483b69c6fcb596e39a85b763937fa6735d2fda3c3c76d6b676c352bcb99623923cb196a3d23ab195b336bab195b9dedc618901be83de245e909461f881cd4d6ff0676892c666dc9acad666c7196ad6665392b1667653da316676435fbc6e8b552cdfd8b6514469fe8ac79ad44c2ff21ecb9653dabd6b36431632bb3b6326bab33b63623cb19b19e29ebd97da31a9f42f699a7131bff3cf48ef798b93eef06368ee0f4b4c517514021687d4b17a847dfb9869ef0e11c66e9536b2521a15126e0013e284a689fc97c4e47bbcbface8aef8bce53bd586d1df28b33e0822659c63ebc43f47f2c9381ae6f56565d2d7d8b4339df8db21f22d8180220d9b5fb54994cb4af37fc27184c933c0d73e952b22a86d103209ecc3e05bf9261c671015d37e3308c07e82a2387e37820ae1a701e55bceaec3695b156a4068253d018ec16a05659a867f51f1070a0aa6db74810316ec1077d99b3f981f4caebff26f876f06073c1b2dc11c37deffedc2cf68ae73463f8aad8f7c079e34dec09f5c6dbd02be88db7414fd44fe546c7ccddcdcb1bfd1e79135a24181096f6665746c4c45768576e3827fe3b9647f6dff9d8372ead015c1200b948990db70725b670cc5d644f1520fcc71251567401216cb1f71e10abf60782a02093022945d07cf7e6c922b26ccc0521a16e644341aab43372d7911bed5977ac0691880872d3029ebaed9e88f9441f18036b71708b87142ca4e3c02d1656b0808e05b758a0090c6c6b77a9adb02b3d771773e8a971ed8d55174ad157c9f9661fc307af9bc7dd05bc4bf42ee8bbfc7759c00b042f115e787839f1a28a3f74c5479cd80cc36be21eed988aaac88a01165bbc580cc12be21dbf15530f604c7a97715e284c6e8c1a68543f4f46d2d941399b046793e26c529d4d0a9d9543d29ca939e049d69b0cf48bd22b9b1b7baa62155d96ddc65602dd3f8a19fa8179f2b6ec957ae24dd01bf50cb7b137d46337b084ea78ba6925e85c24418d5f3cc2cae46681a9b9a5f8f77460fa62d0a96a6fa7244bd4301ea833a551e04806841d00398628b77362b7b43e02f7dee85b8c2061921630d780c42d48f3007561cf77ccb47272ff555e5436c78c52a1810abbe5a4dfef57eaa420c620452c50a75efab36647b28976b4315101a8c7946bf3322ef626bd646f0792634cd1b428ad0ff1d8d4f64149f31c5b8250dcdf9e168036cf00dd11f7a52bef43d5ef3bd6c0056af2ebf165f8bdb8f8b95fe4d764cb4fc3a91503c299b97a6bbfea8272be50fd81ccc5e5a33beab82384323a807a3ea30fc356df69cfe456c16cd03219455e956881be8ae881921bf31988154c38f10f72caded39fcc20121c87ea1abd7124cba754c3ab6ec016025cc301191f151fb6eb6e53a0fa20118f40fe2cdfed66fa07ce5de3148f4474d4da11a6d17738456d0031cd576552fff8a109b3369ab287c37b00855eec3bf682810056e9e760dca57be7216561675cee2b2d6ec0027160ce6e436be691fddf9cde2209372f1a1131c09260ac37620ec6bb4cade59945131a013b4aa94ea180f68270687f1f28d4dc0a0ad85e080d9daf0385a65ba5800d606d31e9aff623fe208d06d979a629959cb7109fd2502e499abc7e8f14943f9eec914168f247fc90898d157744324b1f3cb860c660588d8cd4951b60c64f746a48ae4bb81313f099d1228b222db368ffcac792f951ed3a17bd701b7a877ae36de8097ae3ada037ea933bfd334044fa8ba175e1aa58db5cf9e84c1ca33fa28cecb2acd15df91ecf1e007ca419b3c34aa5703a27c4ceabb1c31bcc04e515585e0603db33e2906fd9e7d01facd193dba1f4169c05a3fd000826ee84ebc93d5a1643e9a6f23757a6835be0b2e777cd7015a27b892338a853520b710da74929e4b09de042f8d776c25461bee59c29853cdb58d30194c0916728bcaa35d38b88dc07bb4a961b5fbdd60286749576be0aae92f840ee093b0ca3ccc67343c8f0d4b38d54a5d110ae3f6637f88dad2f00210f209ff4d2c4925c5b54b96aabe3de528bb5419d5bab3aee0df5581b54b935abe3de50c5b645450db5237909346e020dcb8a58ccbadcc23e9259d9ba20485f439093846e76d53b4f11dcd478e216b3a320554878e418023673135c5a751808b4e6e05ff33cfd9f6a63688718252c8e1e2447c23d4e6315e6285506b16ae46961053e0bae90268125ce85aaa89e8f8fda6846ee9e6844f0b5eafb8137d9c6f4c4a6818795d758d1dd3c5e3fbf820d768b42f9d34188b16b7c090e21a9bac607d40d0bc7e7d66d036902627ad8d18d79edf94c8a482643460074d13140fc1e01b012877d66f9844637ce190e04b40b7422557f4555eb8e28b29e194debbba349fd45762429005db048082485f4386b35f9c29fe0b4c83c1f74998e5d8ab63f00379c8a5e1e318a54b0a268c3444b6a6d9d46dd7bea9005686508de71a3c9be8fe2f269e13c1a9611ac9c5de435f9c84ea2f296dd1ccff2ed0e7d03963b39eedb9d6b59f11a1bc4c1c681276f161cdb64f1de4e5e851f6f7ff718531e152d2fedb286716129fa56c0bb1f986cd06f005d53c34cbb9999f1140967461c26211982549a9c8c15a648c2b1bb9eccdfa6d5f0d5766dbbb5d9edecf666bb3bdab84d1c5c23284f9a915a8e499f102f1f48b686bfa35ae7f528d600ed6f2f429ef802fd646fb4cb1537d2e995d31346af1cbdecf4d8e89c8e9e6b6836004f061df88d7569d01f25f08706f74ad6cca3f7f44e8cc1a6be61b92b701af9005c8816fc2944c854d9e3c89ee293813914fc8f408e2d9b53c2a820078ecc480861851abc22dd2f327c51c46330c80885f3f3094b127c1fb93499d26311d822db2202d6b937573b710b4bf86d64f8c90006608d49dbd3c9bd9e1145d43ba348dd4354a9738d6a588bcce3fcec1e47f463311dc71e4dd13902f7cdcd243e9ccef8f016f2e160813d4a5a55b9b048d2d17fe1c4d3291c0e0efd934d78c7c63384a907ef47f711e6cd5add8e299048d8916e8f3f71af4132b56dc3eeac0a6efa99b057e79541af6de8ee7e44f7f9826ce6e547fe11c381648349acd079e097d5cdce495400aac632ba761bb37e6867be62d45ab60cd69365667afbf037db75ea2036c7280924517e6b459dffe2d260b7272d7165312ef3d09dba9d0c53d4d0a91af0ca5681a45a71dafa92d0831075a6b856bcc4f22df0fd89390287bef60c90004afc2f77c4d10b705c46cc54b02961fcd9e010d78eb64f354103e21c38c93c7969d7a262ccb6c952b12ddd8e814ea6940aaa0b738dd5d215e1d26d1eb1dbc32a5cb8cf62ccad5881dbb01f150f0ff57299f6318c8f59ddb57e58ca14a46442c507bf0b70bd1fffadf5e07be78fdd352c6fc0f70a241280b72280afa863deb8d5f2c95756f5e939dedc91a1f7abe9910cdfc30ad4fa659e2fb219818c0102bcd03a3fd4c15d3b78232c5adb5a3c92d254a3409014885702790c632ee7c4ef6a7d58ecbdd19918418025d72e00804952c6109e800c095fe6c9ce0dba111d35e5b51e7728aca4293c549df9c11376a81c8fab4cff22fc71f22abc2121a729d1b17a40b211f516bde41d80a5a89472273a0032511d2e9137e3511ba3fe0cb7324aba330ed118f266de6a63445c50330e49be061ef024030d7fbb172e5a83c06f8371af48b683c4ebd06a91790f61157202e2c9da590ccff3527b004292ff126185337187d8602bbc8db55c914a91ac3c9bdf093908294bb89f301d627f9f15cd9205995f8f1440a2be2cb7829b70b5732a3ec9cc5d33c8e0b415dbe8c11b3f4049e04d5177c341ab3bccf2006744f27e54731d16f00c678d559c1d75378b024eaac2d6b05ca78ceb287c9de04b2a7edb37409ac9f23b7723aec34878a43986296f344cc8bfc3d47fd13031e68549356f8d3d05a198a18845f92c8cc70f00e229f0e76d4cea72fe79c9247868ede01d2021635a124f282a5e3cf9e281cb708aa0f1fb054320f91370260995aa0186f681ea02e114235f4a38f5145a6cf323f70529ce61c521fef6d55f87020ea9c97d76a8719043cdfd618101c526473d6fce2364f8928db4a56f3039f2b98317157a73d0de27737f4bec63c67c275709308e2b352cc40c235e90d7f069e8f9959c97b2db87b757225f1fa56952eba766246a8d455f470f434fe3e4a28ad78297c690e4be8bb47e32505212e0c13315c9c0235cb0b9196e9f70e292e899f728dd570302027adc7dbaee0ff7d82632b737b787c7d24fecb9d1c2a3e7b247ffa9ff40cfd0d9c37a04fbf91b83fbc2f871ff7a8e088df716375946ed0df5f7433f0182391b28a4a776c9f50bec42b7942d36b743ae19c95b4831ac626fddc364709fdba8d2d2dfd1b886f599fc16e75efea42be5d0bd6f4d4b9b73b99292af583f33366180ad4fe5510ed3baf1f5523c08caf1090ec25497b33fe6f88316d05006af6e295363bfa5d21d2a73416b73a7506f995af90ef1b0b95218d7e0a29a577dccd32e2aff30be1ca54a6457634cd15bd0483fb8ffc5e265b6e7e234dfbaaa4395e08ded05c61add67937e075d0b5f155b3dea8db7624fd41bdc78adc2e8654f9bd3371f90f177f2d5b1c47dd74ed2d106001ffb07465d57d3cf72e65703c0baf0272eae278074e05fdc5d0e0475829f4ab9f0e92981f67752d73976cd96824d7851168ddaf988dc107a2002c96a9f843768d99e721dc304f6341bb1a04862a39a88cdb111cbb8c1a0b5389b38d483092e1802cbd168236a7c202a1e1691784402f0c1e58a08d5d3b81cdf10f324e8ba3307500ec90519b820d26d9652875772de4793b319e6f483190b1de00b3c89eb50f1e73ce43a5374fef24ef5749773bf51e513adb64bbd460519d1d076d425e340a70ddab125bd6d7d3cdb0f7a397a92525eb0e014da9c54ce9960acda1c6e4aca7344f3501add7d925c397c1ec02e418501bd6a0a6bea4fca58d06a68248b98892bc1fb2ad9480890e4269e611d8ad21fb757ebe9679c26df7d7698749bdd2af14e60b3eb0da28acaf947d977052bc4c274a7f29b33591b21e6fcbcb3aca827483d83b0698d58f39cf29d33768de812cb6cf318f6aa4aed4ef4d8677afc1893bbfbec17d91e21f307b30e67234f453abcb8e26d744e31a3afa86ba95d88dbddd49269f185bdfe47af9259a78c84af908636d989f79a9efa0a2b63a1609b8f840f909497d54a6e3a5bbb09929b188aab86a2140a1ace4a51209a40ab8f1b5ad6cf951a97cb27d187824cefd4089f5d6a87b53489154c2b4305b6d0b3078bb3b86977cc035ff009810ee38d71f9b0972ac13a9b1388ce75961cec1490b6ba4f2a9c3ce55ce794c8bb13e9491704cd856888f2636e7cb54fd7db2e1d27352b66f1d699bbd48e5281baa90c80270d6db5f4f13a353a4906782ddcccb39c0b1f57edce1b276ee2d55b5dfe1aef98f6507de8c04fc240148a5c2621e0ade209c27b1602bfffb88060e5877b56137820a6f5e6b503c3596816c7210d55441786af5ca2dd838927cb4c3206b3de0d7ad343c0c76ea61fb813207e5d7c6d5f0777192a2043974a30c339108de8bb2bef7638a409d27c02d64dc6d77d1085fed63ebe20067d1c3485c82102e55340938601379c433e05aae875cfc431dd4a98471be91dfe80e2d6aabcb5b5be568b2745672945257f78134d76e4d4ed0a14f4b71ae5c4be05dbf1fb98f0d2e2fef5859ca8129145711ab5853e76a3c1ce8a494061b91ab8991d15d464846c30bc36897c0da08be3aeb417dfae82f6ee64bd7345bcebec002fa6168bf14cb853128324998dd8dff878f943bdb6f4d903376ba6775ae239f5324e00d2c760068a92467efffe348652dc27b457a48536f7f28b817f05ffdcb4b89c03204d0a97ba2cf42086cacf8970e4c07aaf0fa529dfca5a6944acb594daa344d508b4d082322bf9161a127d5d9f33732db314d580ed8e7ed03a59ce9cad380d5fea341cca42b8e0148840c92b926fadb08d4ba358e7dc45454a0c06df3cc0c3b738409e84d5eee501639076d750a1d543a63d716a863ef24881d7d78e978561269cf8795b9bdb35dc95bf01716476206a643813f0e267496672aeb54d0b74df5dda2056ef5d6a8b831bb0913cbd726f52be6871665ad03655d151487e6a6b3756430b17198a94c8c84f1f5780054ca2a2e3643aa45c3be2d7906d84f453bfd8ad4807d7084f50bfa9c5a9245fe5c2d233c04d3dbfdc6d454c6181db84858f982014e3810d09f9046e47a6dfe80fd7f0e4fd7e2fcd8e4b4a21d8dbf37a51f232b46ec18d264f048e89e9eb3164e33880d35c65a6886f598a2d32dc384811c3d0ac4d28af0e6aec7686e88de8934d4244ca119985832e08a484d5d8942c1b7141d4736a6f7605414e60355b067f1c592fa884ce5878a692ef31b71dfb95171c79e45481ca6e26a8e34c760153ea87ba82213c1f0c799219af52b440926b96a98051c41fe9425cd8e46d2e02d1b89927503ef800e5034fa037fa04ca6340d4f3319b37b57c42a921f7748b18c5e8b0d5cf5e3b987504cb62c5e8e84b4012ccd6278fb957f2d9176745ee43bded38d0a1e06bc9c48c63ebd7abce4717a0eb6a3fa4409f0a05fbad5d952307b7e69ff13722d5d029a05ff686373a6220ec120076058cc486d746b2bd196f106788ded2bf3fd5645f1843bfffe6654ae3c89779d6a9d7d3b7e8ee4cfe41b330e9e1e17da49f3c2963344a56d1eede3b3a1779a346d66d075722ed3bb399d80ec5ab0fa1bbd442676318100aaf320504d95103afd24311570d5d678fd087ca4e290d9b7d775e40baa0fb47c79535618de101d2236d8fd6d4f0c9057fcba02135d1a8ea051dffe0bfe5e774fa1357c17ac4182d9bfd805bce340bd2494558279341a3e32c8de3f34034436cd91c5c7929906de83d8160eff12fadb45240676fcb1a0676e52e49e590faa60d4549c0902ade1ec8d57739721dbe71fbf8cde5b6e3947930ccffd6fd2776dcf4fb2b7eea808ab9e6fe440e3c86286a299ee45a13a019a6783a43ec6ca0821d06618dd92ece297880ac8f44fd18b3565f04ea2b6f5f8d86fd1a458edfb4aa7e538e7b5a257c7334c25490d397312d7658837eb3e3974391379742fdba3b26bfe3ce94c5d43d44d0249e4f0afbc07a7ccdffd82159c4b13ed91acf4b1198de5cb70e45918b1653923775e3b1de2d8a9fc1f2b2c0dfd2dde758e9cf136f0a705ed92396cd7a0f8ccc53402fe28c90ac22870525648e204d2de20dfabe330370030830a0674b7edabf32ec318485a255d7d9d63216a4d9531d2fcd89162bb294755fa69eee0a0f588f2ec823a55a85c0b145677663b0770305474d20a136641bee4c8eb0fcef7513075675ee01970c7a9aafdf0a7092976ad6e934171457d14b9ad530105fe26e9531699b32cb4487f8590089adea3283ac1f33bde494f3855e02b73267f65160fce8a0bfdf28399b66ad6bec6651782004ed5b70d73454b0433a4a69bdb90d10e7ba40c3797c8b269fd5b30bce3c9ef144ac5b72ab72201b06c9ee34bed4f96719199a55ed172b7c942cc7d889ce7f64d1b7a5fb38fcd5d8de3808e24c6e7671d675abe596675b7adbbf6dfb2cee7141d5ddcc5243765151008c698c4d69b268eccd95d3ec48ab9f37452f83e4aa636def10d096af51fb53d4a689fce04283237c7b6c26b9c09dce40f9d1ac5c96e1d6656a8885ce4df1354477405ca83103cba5c6277ac7052152c511b46bb02ee2e3df082f384d860412d13bfe6333185fb71b345bcaa3a2d70d6cf24afa3be31eb4e9f0cdfa5742db7795671d420a2d5f6c81db2a6ad3d2f853b4b847dc0d703e9db2f173b0d13b5c0af2d5fe95cc1723b062e8307d291bf1a873e1cc29a96b9c5c66e41fab77905977914bd711966e1e85fa63e7f7b58b92f6d0a576d16328cea88bda02494fb5b8ee39442c693e1f94390fcc8194404ba185602dfcff7aa487735af8e09c63760022c1b2bae2956001bf7adfce6c745a5056ac5b0e443f49258c6d08562d999aae164e3cbe3b657e8092840a59eaa8cf2aa2f546ddea2af3466761c28b799dba6f7b776e2db79f3d0898ef8bc1e5e708c00bf733e71c7417d5af1f7581a790b74150905a00e40345fe5041fc035e73a13a3e97c6f9b868dd5dbdf1bb96be0103352638e06716a91687d0a3ea773d8ef18f433afec08027a4a219784e245279b14c0069dda89b6f5f551939e90b50567653e493a7846ed7df3b1282b45a6ef35654b15fa7956878b290ff71779628038f22fff4d5aa7541458528205271e867e217c1b1a31bc39ef40b1fd565cf4afc76d2244925f66cf77bf814d31a73c7380e1895a844d64acfdeebe0840bcfa86b89dbc04bdf1a209ac970538855d1ecb012a058c5e855cc337b636c93286feee689cbc91a0497c8f4bff408bf8386505f4f8509c667050ed805b700c0eebb73a3f5ca10100c17b3cdfdcc164c6838f1bf0468954683a4cb69f54f67bc0c9ee859627d697a837dd9f9a0861b729054c717ede7e9e7a88be838a64d2c853486147b5915869564a9a0aef094695772f058d06382a58c7b04434e669cace186131b9788f9d77a6b262fecdf0e4437ce44a6f1a879feea57ba1d06d6fa05af4293f455cb7f5d66cdf8a21eca3c47dcdf167e7e41d2672c889eaf3e261bae4db4e1c3fa8a64ec97d15e4b13757204419d47442f1c0d70f33aa1d116177f3b8708512295afa5e48b8fde19592aeef9adb886e061a4d7ea57d0014cad5c6f46ec1a07869b85059f0bc96c8ae558374198ccc30e52518242ddbbf07d94ed5bb8b23aedfcc8d548e4331c6c247ae4a18521fecfbdfd55016f4aac554dc39f2e9b19eea4ce600e198444a14dcdedad3c91d72d15a2121051ea88483e3f64522773a82c6462445cd2685774cc6c2a1061bbc12b1015f480e5b33d7e13ddd6e8a5d23a5b6f403f6f05d4da2ce4865db4c2413d2dc2f6df1e8782695a267a1243e04e668d460bcfb9c720c680bfd5208dbf47631d3ed262279acbc2c76f3631ac9861ec5a906990ee386fe29465053e1acba8bbd4e15bc7a2985ccac3bc906c29c4e2721f06c1bee8d3efac6b17e0b8b71223a65c908adb5e8f5bf9318fb9a04327826e767f93e4bb1c6d09dcead1c44b9aaddde1dfdde0d111796fcb808384a9819660fb724aa3a089f2963a52b6e59e1538d2d818d12ac01b651039a91510b0ab036dcc1571e8fbb3c1a410a41f40b6d736efa69cd7894ce640478de6f62fa32e86aa20cc956a999bb21a93a23605c3ad67ac82943ea87b2862e921fad3bde85c9eed541256696963acd05f42e2645b368595e67d2671a13c3cd5079b5cd3ecf406bb1f0aa3e1b4184be06d665e146669564b586a02c83ded478e44ac0064b804377cf590e83aa118d44f25cda3a2273b35a33ae0c452d4ddc071c496c225abb2949348c91af1b947299fe4128cf2923343a3845b89d862a1cbfda3c5ba2cf2b9e4b1d1672d2389ae224b3c57766486cd8d5decbcf6f53f8b0798e4e0ea21009e3b33b4dca11c1ec39818aab0e37cef5501f4da316a07e00c4d1a1775938d216c782065519105aba05f64e78637a40734da7b4fda86cd5ed2bb15b86205ef6a8d9495f06e252aad9a2588d34b7d8366fa223038a1b16120383ae66549bb6addfeb062faf5b070891a17be457cee4550aa8c769206e5236557109c65d8b6eb46c392ce424b53184140993a2db9497f143de3469c39a7cb8ce4be09e1369128121b9a6e1d94d25b0c6d238ea8490e72d4e2899f2526e2031ebea73800fdca0dbd8f9bf8a5e659e560e2c3c990e51ab209208b045955c0f1748047cb044416c2afe3a70f983a2c10ef6571447e13adee40a82c340c5e66b842ca8e39e41b20ca203e89c1091303e503ee067e388466146935b735218852f630beb870cdda2a35b86ca7cc81b88182eff008bcb3874727b3cc46545a3f6275d8bd8bb88fc27e8c848f1b379df18037240ac38361cc85561661abe8a138079a32a2039e2e603fe81c12fcf85924f61e826bb81e937f5b5f7a54d4348f4a8b2af067abd1b4e1f2ecbe13823b796c4212295b60507ff863634515acbae04e10cddd9fe0235a26856ad3b6c64ef1ea1ee194d49ee1c37b2b09459ca60da303e692220fd364b8b4375f331bf1585336d79e25919b38119d8a4293086184b4d25bf1423b223c74bff2dd0ae81e57a0780c909345594bc5807699efe6f854427bcc509743f4b00f40717457e438b0ccbac3093ebbc503368e5e7d134d163f20fb4ec0ed0e7391bb5b0f50ceafcb4d04c4b22a193143133a900ef8eaa99a0dac7dc43aec4700933b9296f4b816573d08f9cc35088e6b6890e534d85f710a323c66224e3498ea8b82b865d0d1cda0857bac5f0a2a4bfcfaefc48c2e8f86d6a56157069299f3a5e2f98602e0267a2ff363e7fcb746ed500e350a9aa95217ecf579cc4fc8100dcda343668f2799ecabca5db9338d60c2184082e3bc55538f1fda0bc0d0039a3c27233ae681766e042ce0aeb3c3852da9ba0a30981d38053921e60bcb6e9140dbf02f10f506cd6a18f10bbf67c7c5a23a02951a88a8e62aee01768ae3aecf5d9bf2f66057822bfd3aa7ee65ae681e734d18bb9f7c08500be4df8b5808ca60111e676d352a28741b1117e7d1777a40c2b9184170644ed465af40f127ced809866e0a8974a260744d45d25fe2ae72f64354caef4ad6f8d176a4f511fa30b03099a9ce1f4d9cd8ce69dfc928add2a92fd0e854ba91f6ff7f6f573eb70bee6ead546a35bdd86b0dc79038d7e310f333a58e59a1c7b1903a7dd39749ea3849cb2caee368da081cbc8e0dfcd377dc680730018af2d75c3658afe632c3fd15c7d9f56e1a199e674431c5221dcc93c95914e6f7019ac98a7b57f02f66bc7fcc01a3897d27be901fca7268974539c22e0b7268f1ac420b4ae8a7e5a1d364602839afaa0e4abd58e135138694b803e420cfc70cf968dd6920375c3ab30cb9bb6d074cda631a283c4faed39075c6433da97a248b0c2683295f941176061b929ca97e039f154ec8ea9e99877596fd6a5399fe91ac7f98a0fda9d9b0ea21ccc0bfa5083275ba0d4530b63ba2edd9757430b16e44299938795530c53f2df333cc75460a8d6788aeb21796d2d4e1a2e886eacba88a87054bf8adf01a2c607fff19b30bdd82b51fc040b78406fb953679472a1a82d1fbab6816f93c19fab7eaabcc600d6983d25dc0f1aec9a01ab073fc0d32f1e12ce1de83b6219660eba2daa22dddead924ff0380647c04868fcec76bd0712d967c5e0fdf36600344bd0dbc0a30ec17f0eac9586818a7cfbbf546dc6affb7312936f7091401abbb8604868dbe8007309a7eebe27b90468dcc62438028b77b030d2f2267d9af7da1c9f10e7d3bbf832deaafa616c1568c2e7c2ed38aa6d886a0699247752d691ee6563719c9c9145427df1f29a8d7f3bf2250c12287f9c05cedf83d3e9efcc05c1b3e2e43fb1e92096350ba47581a31d8b5073c1ddc21f6f0b14f43051461b744054f11890607f48a043890bf2df2de3d388f374e36134eef87f7eba1da7eb0548e3aec87242002a09a4698171a201a576fb0188c0c919e17588714bb000574ee3c5156da6067f3e0043dd8cda007805e9f64e08b543b8dccdfff0615d639268cfc33b9ff7fdd65e902119694622d0e7efee20cb5f1004c5fc671cfea1b2cae8d0ca2058f521a00f6c06f1f08c768830b8c561520c660a213aa086dfe44eb545459e66083a776974b80bf266e9cbb76dc38bd6ec89ceaba2da3aac45dbb3f01370fd74f42e60938f3b8788dfe1cc9f286a1e7321831729030acb1552001287d6d8da3f54dc268ebf768a3fda48e0b3419239e72aadab22bcfa2d62314ed064e28554f146bdf4d4357dd06351e7296ca5a9e289a2e2456add644423d2a999b263a49749119bd69d014d3a5c953fc377c10cef533ba4b7c3bd60793395973a34473cbeb36e161ea91b802b9832451b23a181f73b816ecc491fa084dc0680d19dd48eb94ac8d87f6fda97a001905c3e144ca2fae9ccd88d6e2185599633dbf1883e92fd2b730abcab6dddfc2c332b3ed4cefa0bdb685f51ad4ebb4f05e827ab98fc7c15f6fe2667f88c050a61a7d8a22af2aea0eee236ab50647c599c450f01062ee0d3ed58d3aee191c16185ae91700b7100968170815ee6c806e5efaed29d6231efb5632a37347bfd911dd56234d8ea8bf3d51e47fcc60d88230ce1f1147a347799cfdc0676905fad2f6ef0d0fb38231cd33ba71685733901b8676378bde7828973047495db2fd9f2d14666c83d243cc1f90430c9c500501ab0104be3a93f930d6a965951e9a1dd0e515313f40126cbf32042ca6fe44f5370cd7e37f7df4c52e0c93ac5148e69eb62fe759528c9addfcc30a624e8c4c9ac143e79b7815644e7fd51c480b6f94fb19b8be67e031ceee69eca74bc31f7c2d7f8819017011474d668926fe41e6030b08756fee7202931911ba31b9d5813128a14fa036bab39afb1313707e85b5af451c78985d871c48278dd3492872b46022cae26a5637a2e80586549610316ddef98fd6d4bcb3752941d98c844dbcd15f75bb25404d9382d299e38b4f49297d2a8bd8b9e5bf09390bf4a71a8afcd390c55c894ce546049e603e36b47a1fe28fbe033fcd044b2473217d5d9aa2294d0fea0192ac6fa30d17f437cce5deac5d0586804ddc59b2d7dc69008b4828264835425f1185161a8ff013d78d923803119962e989a43947df87c049df425946dc355131075d8609952553d313653a13d8b988a825609330e09b2861a64d97e51d9560045406208a3d51bd0bfab2dfe3660591c63dc8c195569357e7e39286a92cb24a9ab36a303fdb9bf402d27d8c114b2ca09e73c5430e0e4f5252d6bb2044c693275f25355d4facc3a8a07089365f61d6eeb0266faca3788356fb379fb1bec6bbac41dd9101daf782b54d825a1517334c4d8ebefba2670ea59ac0bc017f4a4412c4e481fb6d9e62bc28faefc3cbe575f5b5bb6e1f1f67a78ba94dd56d398981f101a5855387b9535329ee1baee7a9f6d413317673b3e42c925c36dce24eed12d53ba1bc14e2f32beb0a716de11beff8bdf0c562581f0fed78521a9524df8e5e5446678c025750bcea8ac2a35ef2130e3e63894b8ee8f964775b8d25e82ac79e8d49b47bc6eb91f5657ee69f63b84d644dc2567e47e5c818359dd250837299244b0fb8d4901936d76500787623ddd2a04320666c2076331a7f0d132f8160370a03641565e6889c34f9052d2c84e3b497d2e577c4fd15542cf758903dbac7825eec1e0501e9bb8be60ae6d185cb5cc01bda8ae6a33b804c878677f36b0236017a1ade22b3b9acee34705296f571568971f24d958e707ccf2347998de92aa95e066b68a7c698cae288e320094788b557c36d8b834243a58365ce86084b041796e8bf1c976eda3f5fec15b3d29499eee8dfa1752293aaaa0ca8f17263cf594c3fdeb92a54bf61b1fdec07828aaaeb02dea021b6d56785125fd905918faa296f24ddfc2adcceee8e48d2036e309d130df8c1b9ac7a27e4dcfe4c6f0985a35ea0fceede13af8abf6ee879238d6ed94b435b6e2f9f86a838d53f5ae1494a952d0f03d8d6784d5c85be4eda29990847eb897fb75c6fcea1662f2fe53021a068f4e07a449d4d7674835fb3d3d70ce867a2cbd78c5bb4689a155b2f5a742b3ef460b4e8712c76857f574ac5672495de460c6e5378d016a09b361732d8236cef8482c735efac0266d0b65269485b8a088bfc5dc51b411c008f7c8d205f934bd2aebb64887c1c7fcf30c6f7a8605f7cac63ee05568a680bb4a16954562a581edeb8f864b9b87f6aedbf635821f318e1e3db208e929d9e7daaa19d178a4d53533cb96c92cfa486ed87e81f81aa6737949117400458fcdb789ffeefc3a4c8bd53953024e524a404f457efd5292786152d20b2cf581580c38c0c645b434a364316ae8914f7299696a4f8b2159205236eb8a40d465ad4597c756d0cd5b7d51c29b4c287afdf4f978bf9b466fcca13a816e8c8f2404d3c24df4077b49e20b9487d980bcb6a09709e48ebcb3d046cc96ab3633cd9afca7b6f1157100d1ed7438ee5e7d6faaa49b69f41669c50396dda9707118ecce0e43468eae137ad0560b581eed7b6e2ffe438bf046f5606a06c0d613eb9c555208803e8d95f51ab905d1b3215e15efe84fbb37983387a98ed1c1382287e36fa132a453e1fc396e2db2fa17eb72acd3a9e106b1ecd00378594cb458b9747b1bf08aad173bb32ebd25a8190f13b4da404c00bb48205773b9fd91198e333d3bf08047d10163452a65a031333f605e85a82f6ac65df9c0b0d1425444e892ad4bd4063827d187b9539c576d8170550b6d489cb03ea5283d27cc3c6b3d740ef1a085b83527293dd8c17e46765850589f7a9dbe2cc3de415b4b0f8598bd280ca7d3d15eb33e5466fefd7f4d1a9a44d9b00d19becb0f9a2f230f18229ce5736067accb484f131a9a93c55e50eaa2313241c59861f8814dc8788881d002e20308f8c4704eccb1515ba82e9f5010f1f02d1578b0001830b2202f7af11f09c1ff10f08ba4240763efa924190cb67f240404adc557d7c509cb62c80390b1839a05854ad25a374ed81cf1b1652a57fd2f1e0c353d59fc4f8949cda0af9ff0a05176c495af1e6d4a2696e62a927ac41ab6d443678459a6893c3ece6e3ac403b2c60da1d3894f82e2e1d70b9ff2ef68bb1651375144169d1d24ecbbceddcf898c511b16b8140450bf81279567dbcf683a4393dd30a890d0a2eac3dec57a200a6f14002024088a4df03180e341b8a6e6aadbee8557e885a7d94b9fc63ca9ccbfc66eb199508d8b1faec49d7ea7b041f1e35c1e90fadfa67420b082bf718f59970ca94bcc298309eca64d0fa706a3b2f3206083dc2b3ceed5fc20a6e67d07fed538887a8a1b30108305a2bd29985114410a5ea01462fb7422476663031a4124185470fa2f4484df4c4b555106eddb6d229aff949e59781937faaddcbbe7592b140ca42ab11d88912fb664829646bb62909a9a922762160ed5cedd679024dddd6bf5e246146878ae2fa8da0de45f6f847be57d1eb1f814eb48781010c1eea404f8ad52ef6784087458a642e988e010d8419135bb8b9528ac79bcc8cd6f81967f8dfc399259c9cab7349e7920ada5595c5b82000f7d7599e93231559416d6f2951c6840c5a4d5bce227c142c33a91ba413cab000082b23e7b3c192d1f50c98beefff3816bf58c8dd0755cd28642c0ffece6ba5809a895451e2b1d1c8681a4f4adeeab79885f95c01260add501233a16a9893b70836a518092c0e019c4e515abca3821906d45cb5fa760202c23aad08d9117495d96dba502f39c5a9361c43f65a21b4dc81c2d2523f0dab86979eab57416bdf8cc9e131b91cb8b6557e10a29cb5f3e0274097d3827e0e8ba02196876b64ae553627cb81e82a526780a9e28a37f9f6460087022bd281b629f8e88f315b224a05fbe922a7404b0f8ba5d078aa2007a930ff408b059f6df63d15d8094c4c68ee89d9ae13fd28bdb8f2c453701ca23073eda08bd31fcde3903b02bd4260c2ee6effd0adcf61965b5c2b31f46668bd58fdb8d70a3eb3dabce0b0d71e77e5bc1f2c7dbd7e8b754710748a9c759a70156b185fd7af91fbecd744e3ff8163b23d6cf7ecf2fab89cdd202715c81e3816ecbb247bd2933bf8c6fcb7fc23ba19cba06b487ff48cdfc1eb58d09c8a845c43d17525dcbb8517b2de7ac585f74e2404c06202a591c3d8a6d15c6c3b05a84b36013a562221ef3b668a3a861c3bed98f3a0581abb73cfebeaa764f7e8638a85976a935dfb4fd3bef216eb5d06ca95fe2956da4e1f8a2b6eadff140f77e812825acb70e655f240e6c16a8119dc92df3469f12ba9fc9bc8b3a7160d209c0041cea85de8a06700cdcd031a389150aa9d8c8bf06dc11484b9b7774d20e7aeee1e5d7a161a3405b8068ff2a6c0b10a398a36a38b1f11088b281fc7d4e40df9b2234820268ba77f089b9af95993befc0b1399e761f70ce8035679a8b89428ce69f8421da45fb9545debc1d31699af8bb6038ae4ad2b23290cbdb12e3739af8c46d8d936efb19f01a06f11c6ccd241f7fba01922bdd8a70c3855e229649f22db9f82bd26f089b1901406afce1858206dea11265d78c6cb4db49aaa6b97d5df3001068e61359837224071badbaf8697ac273abc6585728ec8590833b771c28096d99ecbcca78cae26433c2ccc869363a38614389dadc6193b54fae5bf2eb160a6fea4b49198ffd7d6ff136a0b31efd1e663da1ed534e6b744266ad56f8e90e8d8aad8e63fdaf62f565b25c0d121418e4c166914121464511838f2f1d16fdaa770a74701deba3be0a5534441bc52db0ef2b47ffb61a23cf1933ba9456312b72bd0552a8c1b4396233962bc57f422202a175b515a591d647f9b16d32e543ebae33d40d5c2ed269ed950c713fa23a7e1e92ea6870590a67f9cfdf779fe0cba0004f37d3c6f02f6cd1a64a0adccf80b324cdd358fcee310000ff40f52c02509676e8589e88b43589bcd8c4f94983f1cae803306509940e757823be800987fff032ecfc7ae18d1cc180ee0f15e010956228090f6a046348084352bc420d67ccdefcb5b89fa92ab6eafdde9c2a0b7fc4e03baf472a05d30d0514e07f4bcf45964ac440730fcb0af8e88d090920c0cbd3f8f34d34d91e32c933d5c20cd2007898e9a18a8520158e6a8612b73d4a83017e46056a995c05deaa288a4a9f2556767ba57c0df107c43ff437edb7befbdb794524a2903010a6e0a030ab8d43bdc4e864b9e12973b3ba3343bef89d15f5c8e695c68a07289cb9c25354921971d68666884e41297198d0c2fb9c465aae90c945ce2523c7314954b5cea285c14132ebd28a4a8a3fdd465082733de96392fe28cb9c4a518c594f38319991919b9c4e566c24619d55310a0cb29d30b619e32bd60e66d0974c3ff5edc197389cb9b32327451b9c4258e2e894d2e7189c97821c3b4c291919191914b5c06e5129739b9c425ce18a83136a0ef32789b4b5c7a63666374a0b8b1440d2a97b8fca072504db9c4a507458342c273503ac4b0f9e88a5ce2f283d2924b5c663148627289cb4f8c4bd76bf0f6c514632e71e9352d891c3c5142881236fe9a27e41297fa2f5418a6bfe609d6830e28cf8e4a87b2b4c625f8b7a44c3158795bde7f91eb9e894359c4d9ee18c5920aa50b6c2725850d7aecfe25ed8e1f85d2eef885ed4191ddbf4d731266f627dcd2c6cf101541a0c06103d805cc19284006edbce67752fed9c4234362802aa766603f6c6785e1849419508f0ba70a266808fbb6142083765b5ece3e1529ae37292dbb7f1e10f911d223e6c945e98b4650e820ca76ff36f0b1fbb775904576c738555020ed54969b1e22f66dd12c6372303a85603829df1501f667d8d6da17d57a3d5a50e5d4885ea2dc80c1fd7c3902078c0be2979b2e3a6c2f32a4a88449d0e8f9c2464cc229a70b101b0c0f631239f8e48c18fa3226e5c5859b2464588129c2e3e50b4e97a8118c0f32b7c3061363ec822505668d2a09312b1a373bc42f3f6e90fc7871dd74a161fc321bf272658391d2939b72f3854aca0b1a1c20632e09f9d4e5e37223e37ee03c01b7e4bea7241e172a3b381fde162b1f9721395bb2645c0e7751e1dbc2e4717932e26e804f36482e6b34ee869ca79d8873e2660b927eea11eabc2d4cc0a723780beeebe20263a4b8e8308af19e8610bb14c13815be272674971b3c41bc27a7100785c365c7cdd30f200e4ad09634395cbcf0e0709f65b19f72aa33bbb4192e35d232adc66e4cc7bed835e2e437ab1f4da4519ca6e9992b55679bb455b0d2ae2bdb2e2ebbb4cd5edd67e4e98a489bc5cdc4d890d6518f466db7e5e128a7a97aefbdd75a5e6f4b9ffcde3598da4b53741d7bcb454a2bd3d32ce5e9496999a794521bbd750ac4d314ef0c787a00109e6e8d0225d2599e327b96e171bce59fa97b50bdc27f5fd7479553cababc8298d75014390995a8f3f0bcc6972ccb9edc4fbd2e91e5a3ec12594ed23e6eb935c2d9fc24bf6ecbf22cbb291e9ef135bede92a43db3ecb672ed12d12c8b8ccb4f288bdc85b22ccf3599e596d65a2bd5a9221b03f9bce11dec389d282cf359ca571c4ad485b2a034e32c0b90b22a2f77ad5da26f934057e8b2169970d6476d0ea255007e91da5aebad506f293982997dada5e35b7cf93736e19a6d758d58b70e6d51202456083112287cf78834a2152994e8e4883037858802a5814f9d1c81d3ba9b1c436ac861e48588da19fb020d780acc0610c2305974288ab095be032c0b6b21400173dce068637e39106de14b65f7167fbfffdef219084077d64000ba13739b05f7d44916243f80a74e8cd8fdeab62050497b01cb827e51122c0910302c2122eabc97e8ded8b6da3b43ac3f81f07b0bfea32bbe8b2fbe17df8a2fc5f85edc41aad3e05f88b7ac35c8c6c2ce6c67b693b433db99edcc7666620fdbaa623f3fe8e874743a3b1d9d8e4e47a7a3bbe60e8e835d8d0977bbe16e6bbc5fd247892abffd0379df3cb0cfd499e9cc7466586756c6729292feeac831ca31ca81e5c464b3bf2fe0e47072383a9c5d8e2be7b581d8d6b661dfe8410e37b79bdb0deee67673bbb9dddc6e6e37e0b8a56c8b6bbf0196942c254bcd52497f798a268e4365c81c992375648ecc91393247e6c8dcdf2fe48d347a0f9046dc881b73236ec48db81e743adddf19449928fbbebd39cd5da2be837b9ed725caddd6cee6c9f1e49ec7f5a2b983eb80062c080aecb6443ef2cb796877c3c25db8135de12edc85bb70272e85b7f016e2c25b78d319879e088d6aa1916afc7902e2401c980375e0ce15be84a46cab0574fde522cf486ad916f6b78967fb6c7fa578469e9107f38c3c23cfc833f28c3ca3bf33744dd77e465149bff44b1be9977ee9977ee9d75f199816348a4cb22bbbf22bbbb22bbbb22bbbb2eb6f0e1aad46a3d168349ad0282661fc5a6dbe62f122567d0d8de58f6bb48bb2edf7a368c3b6dcbeea6db2adb8c1f80365db9b655b0ad09b6bdf91ab58414529fed6dac158044227c08e8eaeb89c07561180cd9d32f483cbaf99bfbcf3f8f89ddcefe03cb027e5e4efe0e88acb45b01cc476dfc1fde54134cba2f324fde59727f797f324ddd677450fc61e36dbf2afe220db063191a6e8de2ccaae1663fc62b581115b7fe74f85d8bddef2edede5d5cc36cbb274853dbd99b521d214bda752dee3ea71f5b87a5c3dae1e97d08f6a6fcd41777453aad18e8ee47131e5aa996aa69aa966aa996a16d402ce2a5c01747060de6e1d1c8cac099093cbc99936686f00341a8d46f33eca7360daf3726039b01c580e4c08870fb47d8daec071010c3f78caf7abcd07df776dbff66bbff66bbff66bbfdeeef450712314ab0b02789ada4da936523b9c2371cb8af2d42d8b157dcbb75b07584632004f790a9682a56029580a9682a56029185f814c6d01c053927623694148a91bca49922449d2882876b3d3103d1d63baf147cbc6a1c212a988b7928693a302e3c1532ed26e4b9bdb76892c57a52143abd1def25dbb44a6971c1d5511074fb968a4bd0f0445a34f34f244232d1a65d168e3a0e23ac5531eea6e4b67ed79a14e87ba1cea62ecf06c10ca421987c2d3b34383e5a3c2a97094a88bf99483bbcd64776afc4e0c55132a332a315fd3e769d9dacb5b9ea1c05d14b8db35cb02b2b26b3db58a2b9f2dfc29089ba205840d19f9fc90197afacda8e466e4133f405484bc1c152fb70115a020144fb927f3649ecc9379320fc84b108a208dd338144294eb988ee9988ee9988ee9988e29090d4da1f936a5966f6f7764acb80c71ca332cc3322cc3322cc3322cc394780904e5f88643a34d1a3260b688e22dbc81b7ef76bbb5c037a12e2515ca71ecb6729b3464c0f47cdf352c2106710cc7700cc7461fe6066de895edaeccf461831460a8ade16c6d9b490186ab9e665385bb4496b3b85db258f1f46a6c81830eace8d8a66c2c1d783062c979caa9bce5b69d23cb0a82e1010be7292f81ced50fc8312ca2dda64511082c225eae7ca6d056e6b609331eef5bccc7fbee02f2beb37cc8fbb6127e1fb8f7b75a79bc88555444570841f4dd56268b8860837ea858d5706a6f7907776d53a1add56d695385cbbcef2d6f39a52dcdfbc6a2bf6caa70ab24bbf2aec2bde522000040c4f2a0030e526c60967c4808850a152a54a850a142058f0a153b2a543a2a54842ac04f850a15d695524152ccef357b66d736608cc5fd84fc987b7f79380a0d217d5423cc8b5ae0efa3975a16ddbc61d71b1c7114499d9b7d83b3c3b379cdb1383b4745f55faee2a12258ccd3a3716eecca7346153b74469c1f5535766004de0981c7477fbe3d2b9f9ffb37abdb6dc5745b35e55649b9152d577bcb57aedbf27ee4c8520546114a2c9d60beaf5e37a617647cf14125ccd95746497c5fc102f084114c5f8c680922e9ecabd897ef2b595fcd5648e08f1e35e00f36df7b763228591498d47303937a706052ee2def89dd167d42040e1c526e38bc7cf1f2bdc76b33c416031730325e67efe9f2bd27294997254ffc8014040d67efa171f9de53eb3d36fdbda7e953d3d3e353d373c4e27b0f0c74f5d870e9008d78d880463d32de721eda6dd12e2d3c79e2098c935dece93b4f4d8905178a8861c2c30c67e7b1e1bef3dc569025178bc185232f0471761edc96ef3cb9cea3e38972e25172e259e241c283f49d2709c703c3f1c478646ff90eeeb6fee50447132750392c7122f17d27c7040828b5d80f2ba4a0e4ec3bba23beefec844cc9b1c49822602073761e9796ef3cafce63c4a3a3c98e53931d2d3b4c3b4d6ffbceedab59a2cafbced257db81f296efb86eeb0061665052228d10251bb27cdf118ae164c398282b3d9c39fb8e11df777050a2c86d08162e5f9ccebe1373fabe2373b267df41faa1e6071ba8a8b75db593a96e32d52753a962b7f5828853ce09236a924459e1f65d15654b122f37a2986101c9d955332cdf554906c881863132dad0c8b2c2d955b422beab6a5d6513bfab9a3e18aa1e1f0cd591cac65b1ddf55b0efa5f3bd54df4ba543bb2d13072d548e581265061bae7cd7b951732591516107133d9c5da7e9bb8e935ad40cb819b9990a67d7c159f9ae93eb3a3a9da82a3a4a5596beeb24dd90dc90723ab09c4eccf21cdc6dbd3882658b10516a80899a7112f13d870332a526970b3e5ca1e1ec3955bee7ec2c00cbf2041133440d5172761ddb779dd75bde758cf6771d1d4a729c94e468c9616afa9e93748992726849b5172c47f696f79c590e9277438d77830d54d4db8eb3f36038375c4e96547bcb3b8e0da7a90c4e8f323847383670747cc781ed763b1cd7eef5966fda6d51a71a538eb020f1c30c5c4e2adf776d09269488c19059516ae2ecdb36c4f77d6381181c465cc0d2a3093167df3821beef5cdfba1d55652b55d94b1b09d2dbbe936e97287693e576bbeff0fbd64a375ae9e686a9e96dbfa1ddd034cd755b2f84d05a80e1c40a3bbc50e364fa7ef382ddc866486f79bf4922bfdf2ce91e2935ba478a4d0a2a15f5b6a776b1d42d868be5def254ecb65c689105519271048b12e794ef29998b261c3a7c7002a3870e674fcd82f89e4acac095a520617e08a384cdd9533429df53b59eb2dd7c4f358549f50873f4b6a760ba940d5d4a8776edb42be5d2aed75b4ed26e2b03438c722884c1e2c3e9ac7d276b3bcecc8ca6b499bdb0c4d94920be934dc060ab22040c57d2bc70761217e53b99eba48e8c5222959496be93493412098d44b291301b19b391630c371441e4c66397e6851fbe8f2c8658c271e4e5864ecbd94728df470ac68a13311f5cb1265dce4e3ef94ebe3a69d4491d5985d129aba0e56d1f6fd96864326a8a8d49b131c7c6d1755b3a41c06a54e19105470d27dfc710c49c62500304983340ce3e36f93ec2722c0183ab0c0cd90e671f63b4efa3ac8fb311298ca8268cc8468412a37cbe8b3b9d78d389389d28d2f094e589325dca0cb1840fdf4522ba15686c96d8f868727671d6c37731a90422b4293a583862063467176962ad8bb6a0ef629314b18714f148b421eaf82ec26ce1ce65135f6f7948bbad19087123470e331c35118687ef610d474a8c21499270b11275f6d0b6f43dbc7126197078a1c6cdcc8db387b830d7435d1865245432122e854842a4ef61d22c84cdc21888bbad174b5a58a384d6c4030e1dce1dbe83b9118c0fa3305b864839727650c7e43bb803c08c068ea82b4f517e9c3d74297d0f5f3d34c2f91eeac02a804e5805500bc80436bdede00d1b81494620cd755b3f43c990a43040880192f41d4ce1346627a5851f51709c1dd4e13b0803818c1a1bc6cc2084114dce0ee6f01d04412427354e6cdef66f8783c245e9be9b0ea7fb726ff917bb2d0a041246ec30723283cdd392ef1f16345556c8c2a346aec9d9bf19d2f72fa9842a29242942e3468685b37f341cbe7fb5fed9bea66be4eb718d7c47e4f70f36fb6ccc3e1db41ded73d168b7f582c98ca62c2ec418b3a371c3778f0440741082cd111a477c39bba7e4bb4744ed082f29c89e78a2cad9bdd977af7b5e941a4f498db7347ef792ae0b890be92dbf445eec1abdce01404853921966a0e1717476adb3e1bbde79afb7bc7b4639df3d1d52b493142d6ff5cda6996cba09a793709a8673dd161d0326491351d2c4d0440f49beebd70260455c01220683471067d7465fc3773d440f67c2c43852c30d4a9c5dc7907cd7b2ae67de778dd4434d0f366ff3cec632948de5283bcb375ceeed8b1b708822c40a3d7c90d274d2302605588da81d5c64ce9e8f7ccf2c307214a60928356650397b36f23dd77ab6e5260b23f7b0308e7ab69175bc7d65d7078c78b2c68923686028917dc7092042081a475a620822cdd97191ef388514147ce8d0c40c5b82383b26f21de774511def309b2a58a9cad25b9c74bb44486e4835876131fb020720416829824c0c060d43bedfdc073b578ec78e898e2767bf3a21dfefce65a486518d314b6db49c1dbb827cc7af8e8df277acc3c87532a2e56d9d31cd9adef24b73dd96016ab627646c2411720390eff7a50026ae300112a3855c0c67bf463fbe5fd88b241c5e4e6c5051220a9bb3dfd8c7be5fd90cc94abf4b6f6fa8f91b6ca0deeaecaec22c51b55edebec8e1048b528ed998570ce70cdf2d14354bb0ec589022e489b3dbd9cbf0dd26c1008976238249861c3bce6e6931746bf3ce6e9b4240599577db833e1dbde51656026be36d4ec7cebe6c0561e941a04a6f55e0c487991cb21a3cac398fbed7da015c388ad57648521b72f66a83e17bbd3d093b54d9c530e508c7ecec15e7e37bcdf5aa8b7a8bd402c9f75af906288bfabdea78d1ddf7f84e732f963c31b5a981089026949cf6dbd6720dd010e85b27579a82f8383a63e3b4b0b7695e5470c81802852688d3f278b143131258d0a4a1b1c6c66939cbb2b03b58e8b75c4886dd49da3fe96108156b15b4e331ff3c72844cb2b0836cec3eeabef2a01abb93aeaf7cbce5f1f6841336b386dd47a11b761f8594ec2ed6d85dbc7de52a58d85d4cfaca717cec2ebebe729c1ebb8bb0afbc8322760f735f399fb17b98f4957319bb87b5af3c0887ddc3d7571e74c3ee21ec2b278a6177f0f69513c17607735ff98f11bb83b2affcc7697730e92b2f95ec0eba9e76ff90ecfec9be7212c6eedfeb2be7b4dd3deec3ee9ed2ee5ed257fed365770ff6950355d95defbe729cd7eefaf6956bda6d91b44ac3e7e7f474082e287ce605a871664e01cbd2341a9bbe97c75c57d7508ddd75ec2b27d9ec9e755f39d9c4eedaf5956fc0b47ba67de51b4cd93ddbbe72a02ebb67a3af1c884be52b2476c73aec8e6d5ff96acbee3869776cf4950b71a95ce8698f3c76bfb3af7cdc51b90f8fddafeb2bf7d9b1fb35faca4d1e2a37972adf4c54be75bb5bfbaa9c080d5923faf2e40694149f79de4454beabec20d7ee75f6958c91b19188ddc9d8d7ca491a0985ac310d918683cf1c933232765b751ff1f7e6382f0fba4f8ac0e1557ca62ce89523951ce1ae9876a7b9af7c15c40e8aeda019f64ab622b2fbeaab35694fe2469005e312af89ad31c2258f1a2fd87651235303bb257dc206f6b6e4012017cb4fe4ab3540e60ac8e497e8f2f0e321074d4b5a809e9f49d4a4af562aae1cb9b27a137611dee91172ce36abca15d0bd572bac5a91d95706983dcf14753647fcd1400d9071ce5bb5b227e016e0c79655f30b6366dde42d5228228cbde2ac14b58d666f2196225056e614f8a80d4afdbebd694b734b699fbfefa3506e683c79a2501e9b3555f50bbbb3b16409f971e62f72ce3a7845d6f21434046d5db0962829eb9b014957e4cc2bae9c3fe6225c5b5db03ef34a96e0c394040e1805acc726a6a17b8cfe7291de04d91863ddc6a20faf7917ab34a0e8b3c9cb887075c982fa7d6bd3854896409d66d4320a44da9bd0637461225dc0f6b878f37d3ae791755b24cffcb6449e39cd66c7a2577e5eb64702e58012653eaef8cc770e4d9a0d30de09d053b463251fb01f73b1ac670aba2273f079bfe6949582d73c050effbc430d7075d94b78cc29bffcb32c287d8f5bfd376ddab4d159176132224d61599506b0c7fcc6c8b69c96dde6def2dbdb26cbb2496f4dca5d58bb138165553368456bad58f594e214a52b544f79e6a2ee9fbea32e3ba6d55e9c52d9129b34b7824b29148a2276fffef2cb59a21d4bdeb9e545f889203b5c4061868464e4c20c4e2a2cf971040f66971c2135bb72ef03c310fc3c9d83f63ced7d9fa76738d1ba6aef03c1cfd315a8a9c70462577ea3cd105a6bef0343711cc510fc3cfde5496bed7d60288ea318829fa7993c69adbd0f0cc5711443f0f33413adb5f781a1388e62087e9efe52bd0f0c4531043f4fc36867b4aedafb3e4f571bb718daf3b4e76928adb5f781a12886e0e7e92a5a03d19ea73d4fd770af00565c1313e17d6018829fa785c0bc0f0c43f0f3340b3192685db5f77d9eae4bb4aedafb3e4fd72536b4d6de0786e2388a21f8793a870c5a57ed79badeb4d6de0786e2388a21f879ba460ede078621f8791a081249daf3b4e769934b8e8eaac8fbc030043f4feba03d4f7bdfe769194fb4aedafb40f0f37425c2052784d05a7b1f188ae32886e0e7e924705a6bef0343711cc510fc3cbd034e6bed7d60288ea318829fa777d05a7b1f188ae32886e0e7692f55ebea7d60288a21f879ba470f515a57ed7d9fa72b0b4e2868cfd39ea7c968adbd0f0c4531043f4f53d13a88f63ced79da868c6d03aaf4d4367eea248c91cf317224486df7f0081384c78d89558b65a52c8cf9bd59e35a9564fc558c535b7ba3b76f6ba444285e3556cc6f05bb0b1e73caaa9e0c1ef39bbfcadaded5bc6fbdcbc7fc7ee02bbf19bff85abf1ada449aa28baeb75cb435c09c621d034cab4d79a6ce351a42e615ebe82dac352ce9191ac97dce573394d1159677f065d31597067f79bd95da54a52b32c619a7b0411e458006ea076099292b735c82949579a6dd164935f071fbf399f72c44e61fbd69caca610bfe5acaca587f8e81e6e205bf5b6903692bd32e91c5b4d58a664d0ffce5afeb4d61b3d215998b60b5d96bf097d72cba461bf08b8c7bcbc59d4f2cc4e6bb3f7d7f05ecb92fd1be01679c476bad5094f6464a37b5ad4d57ac98883a637db5f5b4d6ba1a20a5f90e4172846cf69a717a8628e4440172b9f621d07bef5d099de159edb02bbfb406d5622222d0f7b98330fb691d090803f5b445ac492f51ad3d54e13bb0277e3841040a45a6b0510a13444f902dee76725b33d1c3647b627a58d85f971e1976e8a4bab1c521787c6cf0071d1c7b2f51c5b617a4099d18393da890725cd89121678a2a49a58667090f3b274d4e10dbd3f5d490d3e9b23f1c9b9db33cedcf4a0cdb63da49e1498db1861651a808098397201c5a66ecca290e4640012d8ef5b1d59add5a7bef139c1c4e54f0d895531c20bb72da811606701a0b084a5200d19004fc3cb5ca252ccc240c20b4a6009b0901c8d70038102b287f15433a845228046d40c4ae1c0828cc8fcf8ad39eb1071ea1dcce1803e9d363349f887b178e37f4b6928352c064d4bd625747a88ab2de729eef19786b6e175d41399012358c8c2bdff726ed49dcd7246a5409628993f2ab665f17fe850e2ad08a30d103111d9438e98b22383464c6cc78e264775bf8ca492d34045b5f69ae01d67fd796d974c1facb3359b3ac6c925048dad22663a410cbc2f2ca4999652180afa492a9442a994b261213a9b6f96e26d14c18cd8c99b2b7bcc4dd167572a68997126c7e784a7359f85ee6663491f1220416c6c6d94b1bdfcb9d0c98c8acfc808b814494b39baeaff1dd7c75d3c8d441f6289dc81e5a984a5bd9f4b6bcc5caa45849c6cad2755b1e70097245499a1e8c90ee0adf4b1f3a5e58b244951d4ece5e5e15be974238e1848d1a3ba0a0f972f6f2bebe97bd2c91c2703561d8bce5bbb73aa8511745ba2e11e9cabde53c765b115833660b142d449c8c5c1adf39151a94546842039a1b33cece679fc2779e64822640a4fc8852e668c6d939ed677ce7b5b7bc731b6faac27b54e147dc06d7f196c36edcf57acb8768b7a58232b4353ec468e28aba32be0f6569c24a0d2686a032c40c671fb27d8cef43b7324ac784871dd6ec40e4ec43b847e1fb504e17d58776436c940c2929195a1a423284f476681c1a87c621d95b2e84bb2d0e188901c99230b720455c18df857238603043e4a8890697b30b5dd777a15d949a1a1b696239a439fb90abcdf7a1571f321ad231de10721a6f08691162126a7a2b741b6142234c68840909b96eeb0434663f045143120c294f7c17da81e99543932c46aec438bb909113df8560d40832493416cef478ed7076a19890ac0bcd78be0b21955153860d54d45b14bb1d8adb0eb7cbbde52862b74501da0fb42c3bbca8d972b2f98e421681303ba20441dbc143767614b326bea3484212454a2d49172e282c9d1d056dcd7714352adf51d876bea368aa82a247151447286ca0d0f116054cbc05893714e20d4510edb634c086071b45c090715341cdf7a025272cc8d0830a6896cc387b906df73de8d6429329638478ddc21c9d3d0897e67b50ae07e9a24425414aa292a0a520246f91de06252505c19282623d48f69603e16e0bc770d8d4dce0c21926d07c07caada9a103861cb4cc705a3a3b90eecf7c07da356961a67404486ecdd9835c51df835e3dc868fc1ea4438401e424c2d0f216e826be80985e4d220c28498401d1441850ed2d0772dd16e5724649131b98c81dd960e63bd0cb8c131f28e8f8e1880d9ab30331f11d08089b2734209e7690393b50accc7720199721df81664048e1d38f9af0e987cd0fd44fd4db9f5d98fb09733f61eee7a7c9134e40c19c9eece0a1fbfe83a2489a2168a6204133e4ec3f64beffe4bc2c2d19b30346161f67ff19f3fda7fffc3429f9e9a1e4e8ed0f2c4cfab11126fde8086b3ebbb0f6e30a6b3fafb7dc87765b2f8c6a483e1c1184c9191996f8ee535b80982f4f357081d1c375761f1bd4779fdbcc8a1424498eacf083d2d97d7062befbe4ba8fce272a84e1a314c2587aeb9314be7c90842f1fa410e6030b613eb1ee237bcb57b8db7a113bc20c911c56f84206e954e2fb2a27812b379ea0863853a3c8d957ba0ff37db51342e409277e5022052150ceeee3ca7df779751fa3d4771f1d55564e55b4bc0d7dffbdf7de6a39c615ddca55219714f7de7befadf6e2e84dacc2047643a2a8e8ea5e3f665c1d13b96483a24c5a5240b9a1f1840b14246cce42d550f29553abe556d73da2da309a1c4e365a4b1d2531416b48ac5c942ecaa1183a1f9cb22e09911b59f7f29e3c957921916d3587194ed986c4f8975f198f689123444a8e162a02f46002a33a216b2791469d664811694df82fa5e12302d00324ca860068b12c6fb602140fdeacea30901b2a541d12f62fb74714b9d0b20a0486325a86848b958a2b478a58e59ab9cbe57262855c4ed07fb9dd2e97eb042d024f674a4489aa99827deab29e79bf09d75e5b8554a0faf4eb6f5af9dde6bfb8d505b795352572c1d33397f5a4e404beba024b0618db1b5a1150e907fd726b390dfe727c2760df846b5fa69a7b2fa739f39bc71b75b382fa960fd11594bf781441403f3eab1e9e1d954e0ecebe4991a318829fa733be74055d4157505ee47211ecf7ed6bd6a0beb0d67a11294580b5b57e40f98bd6f779b5922052cac2564a02ee9bb330e6322ccb7213f0bd97f36b7d548c712e9074645914538c31c678c43ae7aea516f3d89dbfe594a7b0d6567395dbd5de6b93b0b6d2106cb50d68011229feab1c344dd03ce32afb332fe55f36ebb5409010298b4e29a5566b6e35b9859a2fc0e509f86b9632f51ad5dac5596badb5ce69f467130469b41eb747c35ed110b4e779deca8712e5d56715e49d5ff065ed69cfcb3709a6813d1ecc36f72211bfacb5d6596bad2d40a21937b62c1e78d65a6b8d4b33df8284d04b62d65a638d31d638e77c75fe9cbae96aad96b17a92672652a58c90c750814b14c552e753b4a358e253bca358de53c4a358daf324cbb114e9831f17c17e1cf39fcafb2ec0980d54c28d0999efa726d003f67f9cd6cf4bd117eb5702a621d0ca7109d80413e8019f39fe4ec8d5f596e7d7676dc61863d385cd8dfbfbb0ad5d974dbaad9063f3da9cebbaeebd36e9fb4a56817b86a6b5a5b1379bb35035669fcd655c86712dbe62ced98428d5f57d4d948932e5caf475cc9e873d0a250105e829c83100ac1621287a176092d1e2021a679b7ddf98a9164f8e6253dd9635011e5e0dfc90f9f40d33914b36314cae9bfad1a041430931c8a7066bb16a953d2fe7ac69c023378207d8376e9c4b128399782364e35cb6f929cc638e73ba667b8cd16c8cf5ade97c36f18eaeb89cc8071c26db729871cb3671767fa0ed1a5435aed65461fc599b7a537c5566f86d15dd02c0b03f9b98aec038633c03ba55ab5a6bd82b8faa566bf65e79e5c616638c31c658634c79a6a68ae672b42ca2d9ae5bb5fab0cd30985230c2845a9025707ca28ee65c7e7a9c9d7295c73c4ba12dedba443553e770a773d659679d2fcfb5ef5bf6579b39283be5acab49881865dd8b3aec12f593fda65429a2fbf626796f41f4b8fc7c686bb5a22178ba254202c418df5e0d8da29941da67575c6e1ab1290bd325128013f046788c4875ce6403827c8a641d45c6dcca6f599544fae99c8378e43b06e39b9ab3ce3af337015badb3d639e77cc6d4bc7a5af33701e30c05055163ad39c510c0a2dab6d65a6badd5e65aadcd55ebfdad3e50b5c25a8f25dc3cce44365cac5a7d7c0713679c71c6d8666eb5277ad6b39ef56c57bdb51ee8426586c5baf99befac9c72c25945801e4c49a83e3ba1b5fae4a012440ceddbad228ac1ac2c4b7b18638cf1ca1cf70bbb7ee35ed1b0914b693d4381ced4524749656abaaccf684e35a544fa7bc1e7e5acb5a7b76e367e18a7c0189be3a6501e27e071011e0760ab1ef7117f29de2faf14011da81f5c5a6ba2031ebfaf7d6fae96afbefa2a34313902a8ebcbccae5f598206e8d72608e88acb81ccecca3bc58d98d65abce52d6653b2c733c73404cdb3999fd839db155ab3b49e01d61ef5b2a6f7cb606c61b83830c53c9738e79c4fb0d6c4142cbf2f7bf8a31f50e620d7a60f8e5d29fe6cad3a624f389d33bfb174b0d95a9e2db797c7b7c99b54f839670ed2107451985286c863a8c025de943b29149f39e00059e691dc3b26e8540bbc0f79fa635e3d8ec907ec0739264bd0af4333d31531c895dad46762ba22f3aa359e012efa6c6ea1cb6b8f8f2dc2a2a28df7fdbebec2406d7392260894281f808492e8f307c204f6eb0f3c7e00a7d59ed4b2f8f4e7d98cf4dd7b8b6e8ba822104628e220e02d728448c1d1a20806cfcb5cbbd025a63ae79cf3f7dabcb77287eb8433119b35d725c6ef005adb94b0826be50b79ce7c73cb42b3bee8149b82e5576e15ec6fdfa594ee06c8bebc7b4dbc19946783d724c8078837ab2b402d79b394ce82c198e6b2b7e033af5ae49a7f34848f6b0ed21042fc691929149d941200e432449e023fc79a7925806769f0d93e186230ff470d80b9251bf0e23396c1e38ac7c726c647b56e4f6badf5e779fade6bab976faa0b9d73ae59d78a73ce799539ff3cf201996b911ce1d39f35219bdbc456c6822856ad371e41f3cfec2ec6d75c6559ab337baf4c28bd7102985b96c69c8ee0618cc907e04f23f93259c256adb28bf1f19523578e8c3688ba62aa29f53cb36b2d86746b7d4d5b02c61ff63ccb750bf2d7bf49dc19c6bd3e559b1395ca6bdeebd3834c689cab0da3c971fbaaedce76785ece1f0d415317a59a10fc4aa05ecacf31743d7cd61905a51122ad433af7c08febb283e0b538921e07c12456d9343db2045cc2073e73fb811ee8791f68b620bf364dc8f8324171187f2bae72006e711d70bfafa601d6637cc263153ceb710acbe24eacac3566e11dd671dd3eda46dbd75ab50c06b7af3068fa0a03db9fe0fad1f599dbb2e6dbd7dcf435dbc80a7867d9b5eccdd162d17edff6b4ec733bf69af75505bcd333c7db25ba3c2886dbdf14f54aefac79844f636cbad0b2cf15080cbacf3a6bd9ebb8b0cd42686df613f267ee25b1b3d6fae320e0f9f590f674465237ab88a461191dce2a2a6ad162f3d1cca1c06de9983926f881df87416cb3b556fc82b4798b971a79e637654996f41689380c33969c12652e96452ad88f8b768e5c39f2153d36717ef1d9ab46d49977b14a11bbe90a323937d558d00c5ef062e945d293505f203d362994c731c798d315148a87710ef9011e83f098a8a4ad7d390d01e4b80586b15bdc96063cb3af5226698a430f9a2f004ab32bd7c0c51e3633dd3d806b8c29946f86ae7e54a4e32547b84fd7e95679ccaf14dac2ae4b54bbbcbbb83a7186ebea95e61e76fdbdb5ef5be68d9424416b9e31ae617c2364e3fb7a6c76cdab8b4bc2f7d9bcb7d249bf4e237cfaeaeceb878cab7b6c599e2e578431c62e56abc755048bcb6ae21554cdc3329e3ba864cad7f3929c9911812900021400131700002014080744426198e66916cb0714800e6b9a444e48481488037218464210062114cb20600800c00000409129a2ea00261719f6457f11ff845c882bf8177b9ca0540df7fdf14db0731bf8ad33c5663b7bc7989b18a81aa0a67c0394638f116ea2579b3aba4224e3922142491d4f7be39998ed2bf76538e4c324e7fe8f64840fefc06629cf8453cef69a847239fa09063d1465f1d02b7b45c9f98c287b5fecf9c2a3b5ea2f21fecdf78af5e2e18466fc25375ca521138338b7f8c0f20ae63bae0ab5f1b702d28c497a3ee0aa520f287a32ed239d010abb393fa46312199c77812b980b2d488cf0e8411f15a1644ad5982958281197125ef99374a98c2179bac98dd59e253cdfb0c2769a0b1743f3105a6ec3f8abc80f6e9b1d7bc47fef8979c8550a3fb5f2d059b6685232945c627fa79bc6452a9567308bb5f41d482272cdd45754de11770763414b7787aea8c26f40d3e8aff74536fda1b6a218bfe1d0062643b0833c68d32eebcf1e658337ad04ba75bc15ffb09f5732c8b6a52a642f1e0d54f69f8a4131410d0d3b8c435df9f4fa77e6bd5f9134b1f9ab6adf010ee85dac1d50552388bd98869ee318393c989ae697c8d149d8da64401af1071b146981f9e430961864e7041116f32e1c83606352793d4d9c341a7de86bef7c0a408610481e496154bbf789579ef789636660251f0eeb257bf5d9810237b14538ab92143b0f1f8125ef3f47940881fe3ace1f79136b8a41130961ce6f5e8317328c1d44efbd4ff4b227b2a88dcb074c519c14b2630ca00636538523fe619de599d0cedaa8d606ef31e8c04a8dbb0396eb475651a278c348c25b5828f096e58c186f0612c9934e317448999d91ccac6f559c49a962577364cb9040367374c02404d49141ed72437455e452f39c9aa701af9635002a7dde4791eb6489e6fe071985ab04c940e142c14d6f04116fa068dd6421d64281a0b21c54264f7f23fbe37d3e9ac0eda39fa2f0f502f38ba2e1642e82215e9ca56d8b12c369d5a50d27dc819d093a6c229b7c0a1bcda078b4a8504d550ad0860ac1f79bc655272cebc037e4da345625377458ec5cca5d87d0ff68ec58ce5c874168e4274af35f143bb041de8c9a172f0841483420aff203a3a4180ef2d320d8364c728e6b1b40399fd1ecbb40477af03f329e3d2feb9fb9414a360cf9a69b60e44cb4d9ae2c74c12328660637cf48d13ada2187234e5a932c4c5097213a251bac2d3ecd4d0ced5ff550b6f880e2a114bb1d42ceece5d35f5dc990f1f1e02b9b767c3e5eb0810c1960ae5c5d0d07603373fc5633f8d2da430189faf7190185745dd5e9133c1881fe3fbd2fec02675667da79cb7b964bfcaabbe3c89fb2058a3b208afc8ac9b6d656cd6e24d92fb421dd9c3df745931d39abcc640e78ecdd76773c460a14de2093e453ef81d66b8d220ee5584911bcce017e6f9caa00c3ce26f7c5d83f9ab9b799c5eb086c34e083e36496d182129c6592a6503de9a08ccae0ace54e90c0a1c2a30b05c56915878a59029f60daf9fa190b1da7ce171217ddb1be1d1ed83727b06d134a9525ba07d006cbb0e9e280e10d51260609e28068c90548a953a17ef9f7a1af1328b57dd2c4ab7d7b3a5e9b65dac031f3cd1b23e253145703c7e69bdfa800ece04a5e2fe545b68cbcff1f747daf93cbe5bcf78d4244563a98075a27bbcbbe54b0b809bd31d84ee45f850e11b983259529d2e4ad7ccb8995c13d01e0288ba8ab0c27caa186bd257421fca6525189992e94602f11caa30f24a4cc7663625dc70195a215a6831e35450abca8a9f581029ee8254856e32620bc02bc9db2856fdd99e425f714a21574605ef4f34675fbae3a5f0693f7a4d2d7928c5068c0da6ed68f68f03dbbb903f22745e8e29b8483cc877adf5286f5a23c6919a01239966f8110739678bd0e041f5da5d16d7d587bca7c97fff7a2dfe08ce611f46229ffdf7b494ee7a83ef527ffec63e8fd643b6a8ff79bee40b72383d9e4c3d9cddaf747a88f85c57ae7d89b9f99f4ee9ff8481673033834cde911c6d3d0e34c2366d26377040c6a74ff07628d4b4deb4a530dbbcdf95457c3a4e1a0717f007984db8fb269ce08f9340b1feefa7a9d5afe8bc963243b2c2b28091c61a8c6e1aaad139a562fe71799195f35ad3651fc57ea4f7af265cd6cd1e244533720678b95916a083676902596fea31210e8c0c746769804678f260cf8443c92dcf7ddcc1e1672e629d2c7e011a44dfcf8478f456c26fc9dcd9c1762c634e03e60919c809cb445b5777df2d5843b425f6f3db1466e8ab7b5ca7bf8349f7a6affb46e94615728dc011ec723eef348f35411113fdaa962c781e2e201b189af082b31ccafa49ba47c16d27fe216493c92776eaa6c0c9217fd76c2b247035c64accc811aba50bef57767ae0dec03342da617762f687d82772b651b7deae36cbfa1cdc3a9be3f5c4a849a33f02dbe0a1297450b07ae07b748533dea5059071a96c28449558c7014b7a483d757568788d23a8409c2a4f61b392bad889ecaf89e54d80023c5a2ffe730dad1a5e23033e08be0ce2616ba9ec04e8533dd6124a0c2953a569a4b878e321f1a75796a899f30bb935cea2b520356c19e5d3a111f2750620c3f36529b60ff3c0e88c9679c7f0061c4b885617aa573e1d83e3d57c2f1110acc15c148e2ca45d5e1a45468f0f17a2f1a74b1cd91e18bc0577af868d9af2b67ec0fdf081216bdaef6aa70bbedc5680058549c595ae8ee55d714e957b131295e43e7c1d270b6ca010f6a2abc2e1ee18911264c470a998f51421eca53ac282a3c26f0c9fe013f9d95c00ba957a121d276c7f8b2668672ee7603f8f8c881d26387d9b14e85b86ebf8b02b06fc728e10fe3bfe33a4d48919abe33179bfbccf627407754b99926d6b7dc1ae8ff961b0993cd8cf8c08fa1d315a13e4e5e0cd4d582e4d5b2f9af7680cd7587180d29d48d4092aa5bebe0cda609a2df842e49729f35831301623575cb30629d53d35e36331aad9d099b2e50d08fc9c20c82a465d0cbf0646dd4fe62d4ab4bfdc145b94cc4d3ff634a897fccac470e8dc71c7e2a1800ffd2c1e570d8e97f9ba0b7ea41ddb8a07176908c6e7970f9bad740e93341e5d99be0a8732bd0e391edc942ca2b597043208d469520c8acf565aa243484a57cdf2ac3e6a51c875f36c4b251600bfb3191353269f603f32a105c4366294afb61cd82204e5612223df0ad59fd4de1df64f37bdc198f6bff326fbed62f0c82e92047190d097d88beb7aa838fa9346136876cb248ce9d228d12e3c59bf348a928b253cf937e4b94461573c040d4fb7ede8e7a002c4331d9c6dcb6373ae651a6a1835a7aeede040de973f6897b6375274000be1d800aa3db73df3f60b1705dca8e42a96cecdce833a3d3f4d70e105afb49722407f607a9c7824dfc3176e74f956a735372ee44a02b5a4fa8adb7f53a55b47117b97574b51abdff11ee8dfd20fb391741a320290d7b58b42a54e3741a43a0718a0514e83d8ddd9b73ee0c67b8df92eb0890debc3387fd3696b0af05e4906b9f85b0c3194564b1413a407f17b4de60396223a3606e71bc5752391812b146dcdd29f7f9a8cac391d6b1f3bafb89f6ad9ba3b078ebb13eec7b2056ebc8a94ccfcdab19ad9230043fc529031d1d47f3ad0cdc8786886f10056538d6833f6ecc81bc98fb4284774a0402d4b3441a8e08be6371933f320aa787c9c3978f1bcbe3ac144f2bf12a5eb623069323c8042ac0b228cbe37192a3c9e114c1ad128257ee64942e8e3c56c3b9aaf98a2a9e00a305744739d3b74e250525732b810ca7ff6700daa22dfc9474a931c3524fdfcc6f9e5a188347fb00da07f6403dc4a5a00ab8f22195a20b053a278fad923aff462a04e6e379e7f1f23b56aedd3d5cd31d93d3f74af6284561477ff0742b11367c072f0cb6311f0685568f8fcb84bb4b750b836f511a401176ee4dd90250b037d732cfdb572ad981253fb36560df36b74da03becc6de0e2ca0ab67843aad05e9483c7f80218a06e8c05faf10cbdbdedf4224702b7aa0abbadc6c8ba08a2e61c8bd684d1aa0acce059ad000ace9fce670bc4fd590526007f7ad9602958415fc93e2735e3dd16d528a6b3a2c76c092f58f42cda4f28237b6a95587285bc6670a1542872d2bbf40519a1061f11d7206cf504c527487056c457990a356dd21267f710d46998d3bc71f0df15f660dfcfbb6e6b451a7be56952e51f71483ffd001fca55cb978454194f2e22f0fa8dce2377fc4807982bc07404661499fe8eba5c9777db8f76c5552b337087ddd59e51b874dd072ef03563abc39797328299cbf815582f8dff8b287aa6257890556c140d778d57070d3e4689cfa84288d0898dc74521a3baeb6da76698dae12286b04cfea59b3d716e35611db31530238344b2b19d3f9aa0a54810aabdc835c758511e12766703ec14e5faa199962304a69574ddf6b4c3da72c5052c24c9d70bc7c21f08a02df41a8c41a35cb6ba19c35252d685a51e185447605e40047dd7f6e706760632a157943766681eae57999064c4f15ca72e9749055e2df87260c3647b2e4b8c12ba4250b995cb2bbd47a17f5cfed92513f0255639b3a0129ee8756babb55898efd66fc05adf7da19302406f3d80cae69c67a8664f8c5b6139997cb8ab92cc3237c3ae9a98c2a3cf0d4674afe8fff6d9e59f99d03ae8f5df5398e4c4cb22df500c0c1f71ebde26bca5285282b35e516dc0c00efc28545eccdb88429ae4b81f1b22a13972a31f7b1eb8931469831f681048fc5729eac0892c83a66a0a7e759f6a750e6f68179c94fe800c6997d6e2ea5aa6829593f431c2148b29188ef49578991f8bafacf1c6551a313ca562a0d007b5cab88eb72928e1b0b137338b3df26a3ffc45392e892934594bdf1c6be9ecf8e4bab1c8f07e569f3242e7961caec9d88c86e691da4d30bccb7e5e52ead52380676c2ae9fe61c5ef58adc12f7e49eeba571e53fa27d0b750c2bde7df847b86df30db11de36d49b8cb64eecbd0c11a578bc8860fd37033fbea24d5329a5406f75a0b2f555dbd356ee5d2e1c8789f63d5f4fe6ea5aff611b4156ec7b4bacf67be90f775da3c82f3d9456746ee3ce1ae474d6032d766e6c50db858e1a9882306c626abc5ac32b56fa540166dfb670cfdfc66e89bdc7ac3bff6f6de1c13310e2a109b40b36d20872ee58147e7947f8adb9291b26a6d45267f22863e9a08f5da14e026d0fcace79d66a3afc2388a5262a87c084d9795a0ff178bd7e4b30a5e38bc4051bcc37c6bb7b2603230a99ccbd549b7481238e1327cee34a991f988300f07a0d0a1e21c431647c245131a4c68d78a6b0928f4dda6b16ee67f0051d12a7ea18b09154b32691d9a191449b25d68167346c81ea243b96f588c181f396e2010e4c3b7fb14db3e5e7c1808c9318b343d809cf0577182031ad2be5a2a380ebf91e13b3788c4b475412dac035dc9da7c93bdd6881dbc3f2edff53569e497bea0788d5f311b5914a4e89dd6df42eeb2d1a4435740a1d76820948ac9c6d2f074883278bba7cdb34e19b961d9bcf6517332f4a470a7ce370c82d6bb4de1a8a1c10934766b90c74f1d91c76e76ed8fafc81e3109653248987eac6b95c28cef61506053b2921ac8c4238780879c9e853eec68733e15a481da270e7493ee53e0f4ca50a15b1f500b738346dc49d7d81061e4b38a0a4baceda651c2d02138d522cc8c97512240a4ed4eb5bf0dcf73d6d981a652313142223373369774338e9809cf89a20b16181f138798fda90a3765303282d88655962bae0737d892b9323b1411d13b85fe4d2f0585143545dea69150dbaec4863f43880a9bf25fe67da4b7c8b9eadf92595ff23b178da44710a843f92f09ee81ed484144f5ec3dfe11992e5c9fde6f609665bd6fe4a65a369b6530ac45b217aaaa4c24547bcbf359ee5d96dccce87ada3842aca1a30fb5019697d239c08db79fc2102cd014eb5715c972c5a2dd23a8fd65b37e0bba0f99fddaca81bbd6d8d454e75b59cfa737f98fb29f70a3d5157533104ace001c5b2a797ee08460453f0d1a8bb5bf02a8c606910ee440588ac2f945038542b74775d83393d39e4b6cad6ab002d4c8f6932eed55e57e20145eafbc5293e3ed147122c6036e484aa7644a0014ecc029771d9fa35e3c75c3e68de5b2beea2227e7be352ead373cddf59c59fe4d98088420bfbfbf76610d0c77e91aa34123ffc26b5d537c01ea36bbb8d9c393769ec2050d771be9f0ad95409ad87559abfccb7abc82d67625f9ddf96214199b1b24cc9d35c703dbc58fe607be860a746f67b127381169cd3f8c4b8007c5cb40084d06498864c002ed4884aedb228911fe0481406026a8754ea8e07abbc3026919f51ca820234471b463c737190a21979ba1364f8c69748f9ee9486be7472bddcaa102018527167c1438f4514f0c91f78e672a92118bf42a784a1152a58a7016d3a8b9512ae147cddb8abc6ef1103b38e254dbbd806ae9ba22340244fbabb6dd6e8c00e1f95a5c5884f92e711701bb280799eb1609c0201910738d874ec7336903cd2dbc2257964ae3fe0c69b0f1a4d3ddec167d5fd4c42bae496920bc7a1ee81d16ffd5a4b886b77246f84cc45b24785f27c4f06c4eebdee60de106b696db540e89683e53574b4434f313d00e21ba2a334fdefcca4271a4ac5ec6e9cf8e9479f3f20e4483be6f5008141808645e6d1ddba05babb2b98e3824ae72369a6299c715c17b036c120993835bac686b4afb9947f9c2c53193746f47f21c0d1d8ecfedadf5d4261dee0c91ba1c67ff2a52d444f4a967714110bd15e578c3a27f0a65a816d3cc9a964ccbdc981d72e56f6db0376a691cf83d3f4e382d3dc95bc63902ec406788b7e177a849008e750091a816fe56386fe55d7caa61ab91b943bf643e7ec40be4ded40f522aead6929ddee2765c91b0782acdb72cc737f85e627a1fa29651343db72d540e722783f82b2f5d637e23bcce292c464741278583f9a9a62d25c75d852174a4b5841515c3409ce2532b6ab992742ccbabb127a694d9e63899e1977565ffeb164104194188f4a29da9ed924a29e354d361787cd2714afd8c84d3481e6141fa98fd836060b8dbd07604a065e7f0a2bdb46cb4638da2492400777c8348b152307b77dba68d90e22d558d42d910d5d7f4d23d2867edae3e5547ca6eb610cdc3f804c998dccf7de5eedc304206e754a7cc393d6d881cd33586a8c41818c816adfecaeac46f6a51e825c1c57eb65ab05dd87c45b15f7e10ec7216795cab43758dd711cc43d8260821af2d9c599b87da3b3d4428638acc17091e550d296a8d36fb0453a38e5aae03a7425b883f33f599849658bccc2a0a1701de09f6f5da5b8a246a87bc2271312bc791d7230cadc9ee9c239aa232c49021c4de6c7aba563d7e0c3fae8cc5dff2736612fcb455aecd8901f84de196ab9f654eba0d43b1e937b754259c14c2181ebadb98b8ba669a5a678acc4c007bda276cf7911919dcdb44e46918ffd364cd8193fbdecadad9132d195029d9418aa6d807675c093557e6f2b12df2458554ce74fb99cb304aa7cbd43d11ee7e6a0e22bdd448a39ae72a03d1a49f8824ea51b7101664544e2989c6837aef3dbf0ba4a70e49afd36c26d5a992b1383ab4aa04a768545a1dbff5284bfa4c0b9954b781d60476b11c4d1604959b81b4bfa3919b754bcb1caf7b4adbd13b24c5dec30465384ee4e46fabb936f3404f083c09e3871c39dcc12100842cbe2c0a35e91c0ed9c81f820ba04544276e1f2f5b4443260b59f20fff5b09e60c7ed2a40e786815088dc02fdaa21ab54d2ca5ea2150ca661e2f20450cf38332c8b3143147ee9ed65e97788ce5ca1e86f256ee6133eae45876ae34f110a8472afb375256030793b1a05c1712958c6fb7e9309024756c385152f308724b970d11b42a043a584d5647471e033c408c7b92d1a288cb4feec5d20edee573b31916635c536501fb08e1e3b08fb143bce488fa55c39d0594a5f9f2a02386dc17a4207874b173baf4d173040c8f938eb0bcfb7da3487cf75e290eed654350e70981c70a3ad04722330a9bced19117740b2ea68c6bb6ef3c2c3d8c3ccf4e368009fe1ba8e065cc806260e62483865b21e462fac6ba91d32a50be78ba981f2357ee0a68f4377b448459d00a262b4648fd350ed4fe958bef2dc17e7a90e34ebfbad2d45dbced03d0b24e67d756c8f403dde5b780d5f426121db00dd4f9ad5f230515d39a9ab40ba24f2817323633e064c22a8c393dddbb5072e7e3179701da5e0d7d01004704b780b033d3cdf36e20240bb39d83b20152f4a84b3304f421e57d503ce87c09d90847511af204879d7d8d26d313c42644c9afdf1180d63694a5d8030a1271ac16bb81c766e400d900d075e556e2f9b2665c5f4b772d3a3e0ea415d9402c0cbf7987c0e67e30fe06e48e8469a0efd3bbc39c64e1199a21d7f873a8f2ee05cc3dce46ae14bb7bdd59670b6334c689cd2334fd3b9b1e1c72b66b2204e95df12503ef32b1d9db05241debe495517319d08f0b48c83a3ecaf6c457b3cbb087f0c322cf48c6c5cbb203514896726492888a934b42083180f727ada7179d061ddf38c6826c2d8411fe8d6ddb4c7647253d0a590c02e6dee4666edbf249249e74c41ad98f5cc7aef7de94015b1370f6f554508af2660e9285f0beb2d848c82fa802e1d786483694b3c3c4f97960087bd4fd60c09f43eacea5a50c313668ce0322ffdf4384ec64bf2f9838982ffb459b0f82363cc8cc04f403d02a06cf847de2351e9059a2c3ef5f38f5e639b366d043dffa24030d136ff6cd794f1673e3e81a50e732090da12c83959d224cabb0da0d1e78029ff00a48b032319cb09af87fecc5894baf4be7cb5d80909ba3ea24811f5601ed024a44d51a9587aec5858228588aead7abf6bfdd78fdbdbcb20337de95850b18507dc7eab96b93b2669f41bcfbbe0c77873a341a4fa73780047042c1c6d0690d3e2bd34575391345df3dc2f03bd6491372a6045ca9ec8cb66c6fe05721b2b842c65ee6196c6dc4b4a099689f4d1979e51ce994243b39af85d60210697c6503c351651f35aac673dabe5dbca5917162301703a5419a827ff58e4f3dc578ab2fc9436a6a7818e73811ca399865cdc04c20270a8bbb59ab27211c82f07ff04bbf955ac88f53c63db77d69ce84470bdc53abe7f82edfa7552a8c934218406a6093e70c2a29c18c22abf395329630c4a493d68bf0721e8b7d84d515bfcf38af1f750b46539f24b5d9508b29fdf9b4b4b459ce7d1689d2bba66896b0cfc22cf5aeeaf373ab67c9c0912f23e652253d7532efe5f36b4645a36bbc5dab59343ab48bd7628c27286f089ab7e8454d4f3d43ded1104b2116430d3b957c05884bbe7a48ce491cd0be762e6374e9db94a14325edf1fdb73519aa7c78bec02b1f349ebff65ccdc0ff95aaa4af2447fbbed8adfa535490a193c15f79206ce71a43f7cce120160fc88048d7f2b043e9d791dd1e731644dbe505ef87363e19177d54e8f9779d1cd2ea1d69cbdd5df3c5da9064c893d3d7c44109cbe93eef9f7d1088ec88f8731ddb51a01fd7e869c89bcb504d493771a2f89062d46a0249467871b61fb0ad26b8d3dee8ba89323fa5f8dae318ef7f962f982a89f5d7a8f65328f500138dfde51f60dae372fd2ad4ba8df48601fe903c2ed1ef73989c4469f3fad168962f9d38de521012d33d007c975eecbaa875290f9ea4b047a8abbcba7a5a43f88bd7c39a733c124cde5a5c887bd120c20ada1f44ca6f5c272fd8e41c92d4bb202f5941fbcffb2c3537cc55312d8c50c9a13c71a068a5ab982b157d41c48f7154bc5ce3eedaeeb4462936cab82e0ba8f2b45a6497db3829778100ad96029ef533fdd24b5f60249169e84cdf5b0bb09580b1d72f423a528213b2cf2890814818f8bb1ddc97aa13800df76037b0f1d0cfa7080726a5e35fbc1a9da22f6d2de81feb55bc16394ebbba03bf5ddaeb188d7f4671f2b40f7b460928963147d6bf6fe93a8b1480be87a874a831d9d1e730436572c00d0299e06fef18050a72074233652c5f7d737ecf4f84d1c7da080cad84bd321ae64e000e51f06a34306b98be6b007559d9b334ef68c94df4d5fef74b0ce8b2ce35d155253778f47d24291d0e5c25650a52e65aa70b15fcbb66f54536f7e693d23532c6ebd0e735a53ce22dc74ee67594f2adb694f0e27c50e5ff27aa537083f4524c11a4c2d43a9f3efc905b6f9817f6db069e9556402402ebf77228ecba62a09b0e1671100e688147434b8800dcbc7bb6dc50d84197be85cc5853784c7b8f0c5f762ddf7c89ac24df37254241e00533f23b28804a8081cd45a63baa74475ace8c94a900bf03dadf688148a52d55804b56558dbf790411c5c8d8051cf76cdb4ec6736e7322c10b1fe46943e43879a2326a3d45a55186cb2a9c3cb3e014e21f5b1a3fafcb1bd5715e86d48eaf4e18d918487916f1ff631a80ae8e70efff402c2bebcb6541937a5ab5ffafebbb35804a97b06d54b99c907e1152b96fe882f3621f1ceea1cf626383ae0be0e87115b3dca041924df254642ba6055357280b6fbedcb29f5e3c0e02674a5e5c3fa2fefec4d1f15c6917c2e380b91085813a60bccd53be100dc071a2696025105acf87631276d7d2dd60a5b7fd97da8958948a6d86707bd8bed03119a1ab0ee5bc4ea726c773348e9a1613230052cf0a4c31115145d76019ebb9c8257ec99f8f6a4c1df74abd5c17b9e42824eca0342b4c9996cd670a4431041acacf373287829d713c81cb64455bff2dd1d1a156b5b2cadd136e506d9e855b0d7dcd123412a9ced812808db8d84a2f0413a7d58d387c9eb47bfd03f622edc43ce6ce2a5cf7146601b1e5c4595e6ea6d1709de1b3217c486fadc8d458f4d019ae2b7a27e24f94945c5b90172b3b75cf8723c18cf2a9bbc1697b3e314d3ba40a25e247459eff379f52850deab0e1490ddf2064eb086c5cf48573431519ec2892fb6f900688902489fe740c6c610ee6656f0633c4bfdf5018683b3a6e565f0c42a5abce79b1be96816ad5205c3dc43b33e233268b9fb0c00538b3620f4f4702c7038d876a8f206c3ad5a11550dc9da9a74fde596d8eb379fd935e923aea4a33bdb3dc6afe5d2ca7b391a58a561d17859917f9c14018682f3847e1b28e33d452814c7d01497cd1ebe22981c9938407a8eee2f9eefa27ae3ee57186105e33a51e5cc4c37ca7d48e53c23aa5385224650b47ddab000e611e485271684e38dd49161edadc9a54e7fb231105a3d437801b8c9c9baaf9fe64eb3900509a277807f30ac2d981096fb06d4baead40d408683e53a198b34fd0d3540c7232cf2c5cc0763e1071279ad858004cd704baa60b1e1e080a5aa1831e0959e6c8449124a7a81712e36ae0fa8f5733623039fb97a70826d9555c0e2a53c99d311608c5536d58f11371fdaf91623a6f481884d48b2847f4c4bd4b455d6813d1e39ceacc7f9be6e38fd2750b25fb0ec6aa8b894b3b718a6065987d2726b816230db81840f528fc7d640769a6b1a2803fe45e49515371356a951053a64475460f5a193838aa5f068648cee246126e12a04a44cfd39d91fe37d09b2c3adaa8cfae4eb0ff0d1539b2f31238cefe7c9218437dc38ae72be98f978a1a0ebde22ba7c69ab1497c9181dc903d811755687006130d9264e5ae05fea219e0ebb643918f886103662ddf7a4748ca8a894be7886adce8127d080fc15421e2b3582f7a34dcde574d37f082ae7f9b5000d443586b0ab3de891406381fd1383768055acfcb88089f61a5263299ecdb8fdadc8e9ec4ec0d9116c520089f764143e2fc9273541015a72ffa0b92fface613491e26433febb71e6837176d7880ca52e2baa0ccd5ec35fee3c38b358f2ab14c4d11c7579287aed87c5719f1a6d6eb1393e1f6202be6e80588751fa3ec8da257de67b5d7c9f8163baa9eeec3dcde3e93834f409df1f2c66f20a637516372aae40fcb89efde2799b4ace86fd9ac0edc9c8bc4b72b1ce594d67d1cbc0b810e284fcfb4316f3680d7bc5b6e472afb9d44cdec7f765c9533320784f5bbd30496cabf968b7f9106102f8eb50e118694fd3e41b458f0bf5c24acc0ca6258ea88682699cf13a4c5a5df8b45c01ab9113f2618fe974e5ea4f073a9fcebb4f92f727489cf8421687c6f5aea076179f1cfb2585ce6eef32d463919df9b2a84cf5e69dd0758d6410ec11efefd7769abe8384375e1f24e205b6cd55a4b2de22d16c159ab1cc1dfce955a34fe2914bca999e7f265e3a227f022cf6e24b0235ae463358881eebff855e61f1aefba80102e96fc2a0d118fe95fd6479808fbef974db050febb1c2bd00af7e929233da6df492bc8b1bff447a8bf14681c07d77c3eb16a7b9131322742dcb4679d39e5e0d80ae5b37dbd8fc501b64bbeab9f65b256668c1b91c6ef4b252d2efe5856fa555aff19db2766eb2d3d197dd50342b250fe6b5aeec3e3282ee7e1ec94b3e58bbabc6a6031078f57d80536ccaa1a041a039a2d2c73b0522267b48eb344e69cb75f4b4abf4c9de5202d62303f3293032c2ed3609c95149066b2296fdbe08d4dcf8ca9b3ad160854fc5c473e3b2e9729ef2b229898f70cdffd6f71f99785a2b300abc565a3849299b478ce1196167f2c2b9a25b05a4c162a2a4c6993ef8864b1f0cf82a259236fe41988c6fb66122d16fc2f17f92dadff141829d5793606777aba6210a5e79ce571d99b86ff74dcaf25137b24d85eb684f9cce23280d00485983c526de08b75d5d9d74618fe9f4aeca413279e3e1d6f52511c5be809eee55ddd427e308c96ea74c3708dfc8950758aeee2bd1819a827c8ad4727f057c43a728da560398ac51a31f50c28cf9bff9a3a5d41fc6ed1fb3c9d0ba8e4b3e5907ba4666be22a5ab126d9ff1dd8c3e30e829112861f4be95ec1c3e33bff736677a36957d2081b854948785830fb5f14c69341f0c38c850f23b93dabfac81f8d35d1f575838fa42c0d1823d96073c9cb316d3ccb53d787344a962093908cc10bd3939550e76b7985670b93345ab2303750d00cdb5999af7b38976cad95bbabd7b8d3b6d39899c7ef1bc8765ff33ada86c547c94bdb86e28f22811cd0f0be4be5769b140f08322ebd11b25b6aab6b0d2917dd7cd99bb383c85637e529d73417929fc47bd6a6d90ca447d6bbed2819d26c36c6549bc17c903b71c02944933289f0b86a7736f5f35f4406121d08d15366a17dff7ecd38c53cedf71c20c83f69e3413ac684ce36e9341093179dddaecce0f91288dffa79ee5ac4469bc0c4dedc399ad8f246174405d923a5fef7341b620f79ceaa6c2feaac89a230847ce635af0e04c945a1013d9db84fe9cd53c4f3cd678c40f34c5bb3081a97e554f43142e2bb8b97a634cd4f6ad41384213ccb6868eb92beba603a05dc2feb916d35fa111597d6ec0020df2037062c2099144238e0c1f0b0bd36323032759b09ea476e3b931322009c5ecc564b6f908c085386441d28d5860a53c7c20780d7ab3f421ee54088a63e89b33959c21374f951a6cc2c3ea89daf7751afc9441fd75a30af9578b9345c435cf6fdc6448b751f7af2d8ab70d54cf636128d9e236e83ab5e780415ae320cd4d5f5ca8e383c6090d8d0e90278604c92e4e6fcb56c49980a2666fb0a8ddacb9596097dd194a28ff954b1f50ecc12aee91e10fe5604a348a7d5f0390ac49bd0a3b1c63e67abafe0830ad5b63d41b408402029004034ea1f5594cc62e1c5ea0154ec04ccd601025413b9ba87e1bb4975f4ac2dbe933b0daf607fd134abdaf848de03ed62d1ea660d528b8275a28df3d42b1a3f038d712d5012ba2ce7ff14b6fbf8fe9583d6d973445453f21ec4ce3718b53207463d3d15b4ef0a559b31d9d97bf2fc3705ddeb81763cd03189475bd7604cb107b432afe17f0241ba720c1c60f687e1967d79067e692cadfee3b3e6d04092df5af9307de4ba8df0620cd3c3e06df8fe5a834b8b9ed20988e4185d7c291340b2f0b11e3280075535fb131a6a18468c30613371bbd2a1d0ac25e12d80ff757a8559013df2352fd98629902c0949d7a629999ca8a57dfa4a4b46d8c74c341a89a646a807f85c5b6181523e7b5c3504783aff870ac345a0699501ca2ea57cb9a529516a79e557cf2c5775003d592923f8473f469b80e0b1610c7383f7a0628625e974501936d38a0f91428adf549954e974f75226e281c43bc7d111cd29d3124f9de6be6ca532158d40a863b0cf53d5733bb120bd3b360a9322f36e1e746b81aacc7f73745866265dfb90de935e329872eda37a97148ddc18d196714b2516a3c5db328e52490630f1486ac92a318d9d3256d29903910d0f911dac74c819cfc851c8bc74c3322c2fbf2385a1448a86b67561e0a1c0bf2d239336a5c2788f5474a675c7f25f02ffdcc0f67c74d29fbba5df934e323351cd877e87d492c984ea1ff03b524936b3aaf9c86f919aec8e4908ee8669a0e9d2817601078f213495fb337d9c1fe7bb3b8c00c3a03c92776d87547faa1bbb6cf3948d22c18e5c3875a9c880d2be98f27a343657a0767487e099fb21e26349465c854d6b9c04611c7c7f4b19c3d78e10b5a4a37cccfafdb00981583fd14fb556194e4431c6893a50a8712ac71717017b1fe49edcb8e50b88a2a72e9dcd7acd3131d647dc838c27fb2457c452b629121e6850936909d1beced7d118615b80d927a781751f334d8039f25807ef75b64288fefefb7b3e182ebed008533e8a9941c9ef905c8031855e39ddb4e4e27372b209770c518b51e016b1e6c2a52f30f6934f73e8a82351b0f20b88abcbb72b5304a18c6f5538aed6fda185e788bb383cbd40733e7a443abdc74337e535f8a03cf8d13e8c2efe2755c1fe274eb7e505a90b40dffeef5f4b3cafff21fe6f391e2460405704f8e23e36e67e940fba4bbfca10095eb263f88a037993914c13d68cf2efc31a7e1e2472051dc53c7b19561424f8f17dc53bb74891a8338a7816f055ff34a0263f3201e1f4240b25634a0a1881e0ea3f5d0f7c3768cb6e740e3f5f6107e87bd7b0026394a468f13e3ab74df66332c175789077b0927274bd84314bca0f06ebb790281acf853a6a2218dc54a8cef0808fbc87829058cbf6b070b2fb8dde1babc86d14e7fa5e0aed07d10602e6e7c964f50a320bc257eea376c4f531ed5b45f239e0eecfc4533e6bde838edc3fbcdaa1a7dccf87bbaa9b6e26b38bbeda0a28b95ef48eb64c9ae368eb3b594cf47e65b3bbc7b9297e93f28a2985e2837606fc2c52a9eab05af313a6651d3cd54630a6a4d816babf9bfc1d662fe4687055d4f5c9820e1dd45d504249d363b6021e6b09de9d7cf015f71a99f34d503cd6e28340a03d4358ee233cf870a5afc9673c5e214157c85287d9d4012621c51add3e6d8494305521049a81b9ab66ef9db20c6196256f113f0b3c3c6d03e3ace173f737e42b7513dd00f60303c129ec014c02f8f271121bdd353e7507ab11e3f4359d7ce9ad09e82f9b7f30daaff1804bc2387cc39a37cbb160b4de4ca74c1cc79a7710d307f217aecff2a35e96643449f7c7724924b640c03a7683861f07ed2a64054b9f76b01ad3c197d294bc705ea67f801cc6a5ca9ec61287b1ca62411178769eabd6251f71d0c5458377377bd5ebc5f99644d1a6c2260690f6b4473b044a1fde8792b313c0e88d40d07ef19afc2d8034372205a708fe98d67d290d953ca992a13f21729aec007678cb81b980457ec91d60b42a00825de54a0ee0114931734e9e192bdc1c8ec16b5807aba21fb2933e103671296a0191cdc5010dbe8eedf6fe3fb0d26fbbb88731fe17e3034f025d8d6e578d645a20d267478c88314e02633a1884f7b31f76db2f8dd6e2b80656223cdc40d76eb7e08ef22eef13176011f210569d2b5664180d78ec47da36abbd35c46066c8ac18781feeef1d4d095b586e75ded396eeb2a04f91a5deba1ed00d8054f9645216446d3c65d3c0a8132d7ba365b4954428ab3cf50fe7d224474eb719fb5973f19b7e5af81712734a4500edb27fab693b1dacb9e6e2b347c5023128f598e119c54f904af683f4f71b92ed75ac72a694d0d887d50b79ecbfa56a9dfc08e00598b269a61396091e9d84b7c323b9cc4f3d9d1327392f41aa90d9925b4d7d926b4aa698cca009f81d8091edcb32c205164e00fea45f08b0b11cd01135d29180395240bbd5c166fe6e728ea7e62030de8e3c5a36df766411e0da6e0001a2cdc5499f7b33db9f20907632755256d5bed0b723c9e1c6a10b3f173b3a4bf353e1c619ca668f3bef6ac7af2add7e28b3860478dcdf36a2f9c9a4567404d7215e010c21b3f2924ffc5e64bd257c9a50020dcd2d7fc1c64095bc2761abfb3ee9a8382d9a823acb9a4e0e20c38fc8a0ca503103bca21c3ae7a87a5a5bbb8a3b103830e8837500263ceca1b4c718f1cdec152c4e9ba71a313d33ec63c8d8ae1378a622f5fa4acc841dc1674dd805662f8f1da4100f7305818febbbe2dd012ee0dd69d4dfc17b2a190946e21565b93500577572904f262608b29b6e8d8f3cbdc182b48314c391d91c5ee6d36c463e161c60644e1087204853e985ac6030bac461c5992f7491f71ba22b9fde183e03af810d454140d28de6e4eec288fc93e16b8c792bd4c25d71409e70bab45e12c86a4b76b8f84dc574a9e605e146066e2501532985574f067475440b15f51b8060cea038e0fff133ca1f9860dc971d405c467aac64909176e1f131098cbee436e2f4bbe5db61772cfca58da77c982f5db212d11c0d658480e7171621528702de34f45350896b7dac40bb93ec117f7dff3a4330ba8992505d0871c1599254da6103ad6eab7621bec079ccf08897738a00552a1f3956a4c9a11094ee4ce9275edee57de26c430050c9e74d2277650212fc3945727213470ba6897a758fb0535c05dc10ff44022d93e916259f5cc3d288ba377d81487bd799c9038052bebf8ffb0e1d868d6096c365ea03efb385101a4fa58f01f5df0d731dc7828a0626e1bd3776f487e7c68eac0b009ac2c253417dafb51ba839c6b4fcd36a3da7c5de8a391edbbe610e8ed8a6cc3ca8df7e6ed4bc4523ecdfa864f847375f28075d87de475fbc022ffde2f86bdc9102de5e62da075dcafe421aa500fa17af4a829f74866f8d3604a1d1bf9a6d87775577436bcda06111313900e64807bee8bcb432e97496826e9f925bc8941f874b5dabad7202b6ef4211c72246cd69ed310d58184ac3b1da8b46775642578e90ec356b599b4b5364db21ab2aaefbe87839b65289f52a5cacb37a9389097efd74b103409558706bd511d479e32563b50fc7f15277e74cc0acbfd8e6b30a29721668ead318ccf3031ac0fd86077a487b45abb2b733bfa2acf9413097909d83ab536a053402886c4aff9f9b6592b8cb5a35886e85f5e13fafb4a87062e099c405f276944aabaa264891461b50765e8c78451071bbb673b53b1e0aded059e07e0f1f82a19afa2f1e321d2c0176a79be9ac23534f669600b461a9c37c44cca2a95f7575d80b27698b23ee7b1d28b9453c01149ee716e1f50e0cc951029b7b1f3563f747628a92fc63a1d503987627acc1b67f6cae85bb5fbda57b5f4e0382140903e07b9601c333f02ff649a30d6ed7877f2502fff50d9934f1d70674b44ce1daab342e622f9a907235c18d74c51e8495e7392e8082d6135dd9a50f7b971996a4ad7d223321c819af8a36ec6015bd817ba152acf476ca181fd880c726d0ec8f289fe7d09f2732d045bd4b820e5a1d7ec41048f960335298e6e1460a7b1563393e3366e8fe9ba9ee84284bcc3853f417b7348be081ee5cfdf246146d16815897356068e1da44b7b7e61137f115cf0780177e044c8323af325772b9c388e02db701c180d13fa95aef910776130242301472a42d8d41a6e79e231ac7d9ab6406383be0337ee53e8a920c66361801edf272334116aecb73e13d8db86039139841ef27ca60a1ce0c0f4447f0ed0ba03b680cd029e805f3180c7b29894fc6f3cf777f2a74497ebf61d8f38c560013c9bbbcfe8300316476007a62984e28ac2765b4a013f60689f7c2c7a8f56c024d69f8f61904dfc474bf29b5d83b15c4db09ee3ae5927d77e5f83c834bb08e65969d12a7416c87382e4f78b9c2e833d31ceff3bd7fff360643ad41533a7235fe4ece64f606b71ae4ff5aaea2c98de2e2356112c1ea4bf0e00ef28c8b2e61527bd73e90f7fbfb43e892c95a6020b5d5c4cc7cc31030ddd1c520e44b976ef97f6c38230c3025d6069100a3f3ab24feef332d147f114489ff0cdef79f8f67c784ae895004fb07b84604c809f0e0290a76887515c168be1a6d338930121a7ab850f05bcf841a4247c44562f732a847f7601c19119821308194dae28990578445419e68e4e9e029934a1f1e1985996c6ff141055922602803732681a9ca74dbc63aabc6da5a7e60a143811038148466efa5b277eeaa3f59db2c0bf51e489fbe8e3c762a229b325f2285bc783913417206d205a9cc62be0c2b06d01617ed0cb7bc24e16c0cb1704b87e2725a8423aa5088d64a2fc788aa242a81c5ff6550cfa071e45fb81338869fa3dacfb4292c487c0034607be2968cc70944d0dab796dadc836d21cf252de8c9a12cf4597ab69c5ee8f605af314c12182aae5a3471f1b0ae56af744503b591c343a555f9db9b1d6409f16d3bfa60d46b04d32a34ef3978cb7863e08fffeb0f0a64e108f66a8d8735c5e7068f6eee410e2dbe808de67b050d5d28f86008016ca608dac0020307e610c4660d600d26107861850146b6f1f41ce476d10e8191bf69ae62298716df4a806f44ec34ae377c7484203a7db3a88674df21946510833b932a94351b41194335d433144279b311983192a11d2364a5727e614b37080de935db7da85a7a5692ef09353afcfb18a9f289e18e7911c81baec0dcb09d4d2fd85c6d9b0a0e810dd4093eee447e703f5b6577be6e7f28253c8eed3973800fd813a60438fe56339af8139c259fffed399e7c421487f23d370c2ed6339efd03ca5dce50110e2b055ecedd705e8ddce237e796674bd08f51301748c143693692db52481db50d1a938a546411e8b4e9b410fef7d92f5d81c6651c1d65ef8f9111ee387963bf6f78a74f175eca81e8f0b1669a37e32bb44f59c0148bc5fc8e67b8274db33ba21142dbbc7d9cb1e4471ac8f1d6b89a659466f1296698d08230ebf9bb5c7e7933bc22e1e5305876e9be06d2c96b241804990cf4a1dfab1d3d3d93519583b1f485b229ac8ff986d9ebe259d066fa673f7884bdf68e117a43d87be659e03eaec1f40a650bbce05e305af28bb140e5df72c4d46ad1b5c70b1ed97a919013a99509599528d5c85a0a5a121b918d21f14ecae23578a89878f5ce48f2daccbf6eb803a4531dc5d0ecc466e129e4486c3544309370c296a68cf918ae92e1dcba0b7baf2858590cf4073b460cc63b5040576124b7208411113a87d0958200838bdc9ca66d1baed92b99c84ca8ac30c461d64b1041107a65494098f53c77cfb9af8d7d16733159adf68568764ed38fd239187a6877caf773dfa31d53326cc8b81f77a564b5f5cb801b16910fcdeeb908be1a9e206ed29bacad15d0e5642d3a1eade810ec661fb57b42816262890c10e211e3044172097683db61c273adb6ec46921dafa4d3d6252dd07bf808018624935d5869d57ae30ab66b9325792192aa2f6b10841e8caaf3ce0e2b7f87b334ae12e9e18f85b5e1eb88c16e59c1e2021bfcd788c7e5cc061e2789f9c659660336e57c93a395dd8cb696d778019fb04cbf50bd253e90f985c6ede2c77ea0db609f72a8436a0a880166200d2124ee58e5d2527c9b82570165143834ee865c519b913153ca3a304a67e3bab44b148f02520621f48850d911af1885c823e80c6de688ef26a1e6e9ba1dd130e502f28cb3d8f1f810ed65c3d88ed07b23315c4fd8fd4b1041564b0e72d2b0b57c9bfd73e73a3b68d57fdc166b0fd0ced85713a538a8ed861e68ea8768d17c50d9f426be3ac001026e06fa318818c803b613b0ebbe7168fc036c12d6a8bfe076868abc8ddc26b4722579c8522a3782b3cfdc7a23e1464eb425fa2d6ded34ee2dc8d1d06c07957656bbf7877511beba3d2baf482ea2aa9703b0ccc5461717f0d41d12c03e445ea415d2b0de21d827c7df49934ee8b49eba707ead10265501e2a57306abe7c20951fcd096a67112fded2a5bf20b968413ee3d357fc15ba0ce517ec50c37898b0a5af1e79c8283e94411a4358e634411a1ea8c7a2961e2d1f6258e1b403f62571dfe19da9edb8599fe04741e1879ac5b6de497ddd14d4d516491850e7dfda21b102c0ed3f3b7076b47ae5b370eaab339f43ecb41d0e294f3fd1b24ffc47a63a84b0403c9e218995aa35ab22880a397113beb2088c86ebbccc17cca86f8dd0997c6c2f91f680d48089d8ed3d9d4ce240be15540b802ea8040b481fba09452cf80d1d91e562d397e2cb3432ef57fe1beb4815f82b00bc6638b7d614ec78039368c1b63c9ba51b3c309e93565b9efc38b9ef3ba90157a6b29a4d43a2533b440e8fb4e518c28768c5b24ba57195b6f35580fb9f5d4810a9d15e7b9138062cb59bdf2d64a2e462c88cf877151b16682f4257d7e34617e55ae92327f1466330b26adce6165019195a64455c2589aac9039126c95a813438e5234c9890f43edf37a0233cd6edc2843b98e15863204453e03a6f5617643ae9b600fabf8199edc060ccebf8995046b38d31952a0e42827691d9d34c819045afea27bd17b374bf4b2ae42e96fb8082de730028219dc35e30994676ddc74af68a74b502cb6c2c9752446d3307f0f7cc2f67b0a58de038f445c9d13feec8d8fdd5ec0bfa2d8d8cb72209aa42a43ccf77820cc4b1b5b4cb1c407f11872f2c41533bda98f8acd5efe4cee63b3112629e6008bd004e0cc1b880c55057469a68b46a62d3b19e39ce412fe72af17a1fc52e625ae2ae8d302f45d3cfd0929b523d4bff75c24420903eeb8ec89d2b023ad60380887399ae3814e1e244b15a4eae6ec05c588286d8fd6d533ef3d528629a4eb7dd599b714f0c091d70c019507abc1da7772c3a0db8c02a34f668e49aa521b10ceca7aab674a332e9cb3c8fabc8e949f490b5f762e7e11a4e5b4a9eb0a65f1416566fd55b352d2998d5e903d7c9501bd60d47ff8de12b3a1ad956e6a162224624da5a994d694312c06a0763933f21c1d7677f0c4598c3811ea74a0c3429169eba5a1e16a1075cfb8ee822beebbeb515eeb0d5aabe0589c6da895e8a79d064724eb80a97c28af9a069316e14cc2e90dae878e3d77cd52c5285e5cf14f3ca2fa810ca21c5a4874de4537dc415175a2da9d45ada13d8d6502ae375887430d745654095214aaca9f28bb873a586b8d8998f8573bb56f90575114c41f56a086b3df2f007c6212f909b13426364f7cc73db2e045b3f110bac5dad69dde1056f2e578ec362e1fe8e430c982a93e5be43c2953f6869a483c7307ed8bcb2d86568d58acf963a0f279bf9d8445c050fc6f6b0f40e0ec8a5114d158d2594cc1835358788433831b7e76f3bebb7f1c42cf97ef8428570946160792c2784873a47cfc42aea1cc63758af78cee1132c5ec4f7a59c90c0f207bb22318763489570bc81047fd490fbc18a179845ef291bf28d87f0e58ce39fb2eefc8993ecdfc6f2c34258b520bae71bbd72973b415fab27f6a8237e6a69abfddb8b56ddc7d1a3fc076c8cd51b1db95dfd4d7d81dfb909009770be290d89a678e262e1728bf0d4d99a32496154118cb2c00094eea96f353cfc97159b5b0c6bcbaff00d33ee1246c9c6eb5529dd8b9e7939628d4b600f3444c2ee2da1b81e72bc4f577b9ac06b5d5045473b6ea157953d30ebdea71f84e0183586acfb57bf90030e3b94372b8a29e7a406d9890a2cf1675090898ba878a8da63455952978445f9da569f1ddf9d74840f816bff79218f1812708178b37bb9fe5537cd9572ae8606b9d8e66c0389c63ca317750a93f2c09f507420ffeb0951cfe06b331124e1d3f9f8f805e28e153d8f839affbeb900f26ee31e1f51880b008f5894f769227cde9bfa22b7a3935dcc668b015e918a710ca56e23b8b87f1a414369a40d7a8a28392543c170f62c734912017e540df4149dedd15ef87ec0ea7c24816168e301d7df7346d513af5d5a57e754f3d3c517732390b0b3783182a8170a3839a1ef83590d9a1770ed03f2f5f6de80c9293f54d746a979e3d482c718626a232e5af96d9894300f689801a0464072d37765fde3e43ee8043161ab2538985049f78e54169c80b7b12ecf81447b3fd852570bc043f40867632ac4598ae7dd5b4a4ee5cf2b6ca01017618142ab4e54e1f9a0a8f1d0b40f822fbd1e4cda4b673ddd488eb6a65467ff2712d58236839060b846f4b813e7588584ef46c2a57082b0bb41c18a03c55be8a49ec14c8842762a9875fb97e08bd358dc59c6298ed1baec17d62707459e6f185139dc50304a03e1a32fbcc73d2c5e8cded3af0f185d48edb1236c23b5f46a99a3b690b8afe08b12cae8d9129ba7c4f122372a3fad161a4cbea014ec7acba6ceb2a17821dd5dcb9816135ce5a367ca6ae25a9af5ab3d4d02abb0d0c1d426d5dd7f76f4f88a241eccf0064f68104c91de6e6d655e01c5e70801fde0af382992c9e93984647994e4d106352becc0a271f0af3447182587f72d3654570830fbce0eef0b006f83c1a6411f885e4b796a0fd081e9f9458867073b7df2dd955815c6bcd85469826b4346840a7513156596987bc16a067e133e27ff2c2260ffe6c12a4c08915f0abd8dc0cc6c245cb336506d3c73c69fc09df0420c18b4b45d552433c413cb3d4f0ad34f466a9b5b72c850ca3b05188be7245e17657ca5e330fdb3f8be85e38961814e7935102c466b41629bb0efa1ba371c6924d9ccb835d352e3b204ef74e8fb37295640c0f0c857558ea0fb3a5def73a2cd447de7bf989f9e4fec061e10308c69a05250c7c28185e768ecaf6898325e28626aef09f814de5cb974a188ec2303bcee87a8cd8d164f912820d92668f1c48889d741e84a8d6b0955475a1c904aa1b40d84875a9255eef74e103d7f438ae6da3775d62a8155ed200d4b24b181b279f08a29c911c53e43466d1d4aec37e142bb549c7ed0e0b6798bdcab1d29a4cc22af48cdb938b4651b1f68775e48cb51e1cb38f549d22c2dc5211e8532e0e630289c6f1783b3029b7f0b343d4d3ed6dd659cec02a9a7b179edb78e3a16443009b5ba851173707205050c6b3a55b7125a231535310df3da186e35336039c222ba7e0a6f01e30a37f9c50eb987ff6f3c670dc882311f47c7ed093689e4f6fc2ac64b5189706ec06d5390fcd213507cb2855d1ff19fd1ff32a59832261f9abe868de61e4d6a0f01e8290a6e5f43e16f0d664fd8cb2e999a0a4285602fe245cb6a2d57485307c0dfae22ba77875cb11aa1fbb8725b28e5a6150200a91560c2fe537e0e3afcc1178d1911f811741ce17a54409ccaf3366d48e492c9c62f1658b74069c31659b9eecbca9773a23e980091937f19417a70475a8c9773287bd0a27c7e4b7428b64bf7a52e219e4927bf6ea9811e3b7f56db5e8e2c2b8f6c8e43763bf4a77aab605c939327632250331e81eaeed5b1b3b12260e82f02dc5a066ca20c9e2e1c91436dcfc724557a5ded87ecd58ec192c647bcd657c1ec3f408e90c1fb46199ca90944ca603baf5f2925a40d815a703e6fa6af3d476d48acd493696812b04074a7133f589c833481cc09c8853bce21398a374769823f701da456305866128322ed4becc43538352ef0e1a70921e8918d1a1292f535596fc447665db7befbde59652a69464830880092a0994daaf7bf9dc4348af508ce7d40f3fc9a021bb62ad8a9d41e3ebab3cf634bcfa33ea8beacba81666b1a72fbbae721e8e2bd4ee3f900a273fdececa54dbc9fa335a21fd655648dfea44b332f5bbcec264a49c1a65d0c334f385179671af71b4aea8f6ec59cfa9af65be964acd1a380de4412f52ad368999dffddd889c50ab4099993f2dc8b2a66531f7fcdc755d1777434b7123bd6a29edc2a0bf3c50afba0be69662f56ad55db4143772b95796d55dcc97bf65dc5d58bde214b4e19e6d97b48935eea9fe82afb4532efd5eb513db529a445b8ac4aca4d77ff0abd07e5cf7fef2b54f7b197a68bfbaf218f62b74e5e187203c85a0fd4417c33ee4ad782a1e7ceb411ee83b0fc212663ff920eb31ce0a91b7675b990d3266bf7ec2b2bb98df5db00e6865b2a76f599afd68b2d952aea4b6bbe01b525e212b731afaee3faaf25fbd34e4ad782a5ee759f3fa41996dd88652b6d1bc3bfffac922dadedede24a6973eb52da5bbd0e17a6506322726e1385d84d9c6329126c9f9f16b1b25fb53fa306a7f7df4b4eb312cbee65dda430fc7152ab541b44b5f83d6c74bad4c6661bcac4c3f8500c5ec47d356c6aa9a8cd647cd7aedca58da1225121982c8104486b868e47c6bda1b3e1af9d092d27a1877efe20c5a6c13257bd03a6d314afb2d34a2d8c943f08df871cac83991c10cb6cb333bc06f88e6a3914ee45bf6868f864e27ed421fc67ddb117acb0bf9602664705e78e50e59e4d2e8dd8c31e50e697d3449feb4d4931f06913b800bab00c349183b61247133d7e49428c57f1a0a5f6ae7fb68979565274d9adb7fecc47afa6df3eb573fc5787f57a1d47eda3775d17f18cbd317791096a85d79150f366925f4b04f322c6c1695b760c85b51f995d76c10ed6aa05fc171858a59217e351b342b03b2f3baa4dc5e5ea96265b69f6f7d6f109856673f9aedbab54e2e6526f00dfa304d6b96411be8cf97defc1a520609dd6d07fdac3edc76c8a7bed5505ffbe9b17831543e6b8dc58bf170eb1ea6e59603cbc778b9eda8a5fa98479b547ff3bed0ad5feb6f9e566193543a0ffb181ecb8354bceb3366d8dcfc6c6a4ddabef36893b68fe155ef0bdded411e6f35eca89066a12ed5f826b548cf5ad26302df902f7fda48a3d2752734b59b6c753350a5945d898ccdbf6d366cdc30e3225bb54b3bdc3ecb387797d120c89de39ccbb8601d0e9adce4b2d56d7766cb6e65a4462d9a99b6786650a6ff0f972737e716ac633ecd9c705bf42d6e66ab6b7d7f5b9eddfc41b48c351b4b42805a2b7ce325a9f54febb9edcfb6f88474b6853c44bba8c3b35fc68c417fdb6c98a1294347c660b17286b61d54bbb919c7719cc7acf9fc4de53b27dbe2f65bd6833cfa303eb357f13eed761ebcb473b8392df6754ececa60cfcf56c6c5a67d37b771da6f9f31c76973623feb633fbd2fde6a47d7d3b76c5a7324d291700fa2dc6fff45f9c5fd82c02fee7c4b3ee7702f8368191719177cc37afa907ec605a5d92ae342c60b3a9e8248e4aceeeef99627b365dd96353339ad9f1f6522775a19ced8e6632232dab61f8336086057f2739b0ded22b9e5c321886cdb0ede3cd824097ad86534333fb0cd668530cecd3c194dd6cf24641bd6213fbbc9beb76a65b2d7567808d6b15529432bf6ebdb9dfde88d5bf61abfd69fb51d696ffdab48c936bd6d4498c8b6d9d03d5b19feedb5cefbf85a2b2cfb57b2cd0689c9b862257f776d3b2c9ee26699a679f06659d69b03b2bbd1cd06f9a09f1e7f7bf3ab673d8c4b6c08d631b72d88b6651be8e3b3d8f7527cee9b3399ebe567d733c7d9d16f51fea49bfdd8326d1f7fd37808f9d910ac03eeb0885ccc93974a78afebba2e6a591e826fccae5598b0245e2f2241d8c3cf34ed61bb68efd225f70971ca13dec93e7738e5c9ed3433d4a9573867affce68577da5ee7a8eb8f362f72fd3fbed57db47d756bf9cf393de77ed60b6999fe1fae6bd6537e6afdb3a65683d2f8affe7cfb79916bfde6d2e5d4988695f9aaa5747e6f561b55ffedd9fb5eb042fa6e4fdd8eea7baffc8675f84fdbeedfbff59f17b974be5b19ff9e74bea5749b5406c002c04e7feb5fb0fe345b72dd937373cfbddd6ffca7677d0d4ffb91c765bd6ad20cfb5191fd2a0b0c88ed8a9592d952ec4120a656c67e46d06ff7acfef6d657ab55ed37fbf1ad0dc29e822cf9524a49df7a8de96fffb593ab3de74d27d7fa49ed26a9a4d27e42e447af1bb1bdf6bd6a1778b577235807bcdac76d8756e4669e9c188661d845ad1bc137ac1a2c6ac20bcf843fe24cad660f3fdbb8dfac57ab4864f1b6d940e3b987ed62c16b7d8c3738dab6a3399bd1f82cbb9a9fb3387ece7a18b784f4e5c9d4f81f2e7b9f5f6bd47f597f3537b2300db71baefe84f427a4ef0b375cf6eb5be35fb05f5f50c4b9cd6c9ffbb8bb394a33f383f5f970fb2dfb4523f7a3cf7932d7ff709b41f1d2e7f8b924ee474137f053cb7e11e752cbfacff2e9d327c8ca345bd1a7cf79712bff89ee7b6993408d7ecb7efc0991a31acf3dcc0c918c7ee6defa588475f45b57e3b842151271aca7dcd3f03ebe341eb4d9f0c25fcf6d37681f5f2e4648a5ad7fcee2def3a0ff66d98fb519000b006b3ffa2fd88cc9cd40f2d698a06e90d720af6f3f3f8d19a25f91f12cffc522fdeed98f9e3762ad6dbc69126df93943248097613f514b15b1d84fe4167a296457ac8aed66bd32ae5e56267bfe84c8acb57804ebf8b8ff7af5f61312331a38a46cfda06f295588bc9b95e1fe7a0bc40fb21f5fced2ac354aadec6bb523ec414f4f3fbc345f2452594f9f468c97fb0b24e5e5ac07bd047acf03d94f48ecd5a52fc35d3fb81789b8e728db8f0334d7fadf3edeb40bbcdbc7235807bc1bced53c9965d9671976d97804dfa0d69a568653a3a6e1a40b4aee5f5805179e18b9a60babf842cae582cf2dc085556ca149156010a9020c2daa0023892aba00a58a2e2ca9a20b5f384b2e9c2f238cf8e0f6cf8ae45cb8bbbb732b21b6bbbbbbbb7323c1dddd9d1b09eeeeeecebd12b9bbbbf33b3717eeeeeefccead047777f70eb74d5507e640c0ed7ff98e40d478647e08189564243f66326a14df076b14ed485a1cf8e7c7c0b7de07fef93e24711b6359ea03d72daa49003aa8a60bbd902289284794c081157e509688fa996af8e1c3e7ef6e7a0a9a9324c75a725989ce4204b4f02270fc14014b4a9f485de287b243916841734cd6172f35d7fdad1e1ebac46ffddc1ad6136b752d9f3b25c536d1c7c7877d72487e6226ec139b7394f8d8c747ce1d7ec0b044cfceaa468b0c3fba675a34c06841b2280e531853b4cb57554b2c1d6be7d68025fe161970d42ecd004bfca625b4c9e54a71784062888d0aac6003a75c36d0466ce9a25a3aedf2718e9276611f7a615260d6641d68c37f08eb68cb5058967378065bb89e6393714e12f5631ff6f1f1c1ae8caa60d821414a082708418f1f4158f111b861a841bfc0e450f90c6a4f0f1f1e5bbe88120624e4bca91f5c7d2f2fd38aa1a6c2743de04a1514c6a07e704557abd58f1fabd5eac76ab5826108b547fe7c7f1f555eaa4e492aa5c5cd0544164c70050c47c000440c4bb4206921c28a01053b53a89658ef6fa59e647ab126c3a003beba1623a6504959b292d22ef1fd34db45f42493979cc6a08445e4ba4504e65041c8d0468c2d36a81f5c7d73ca14734abb444d5a31c54ebbc49fabd56afe989ef526ba22ad4c3f2aad8d82a18bfac1d55cd22e1f5431993b7e227989ffc95cf9dc1e93ea465405130c02b8c7c40dc312da5b82e0d48499620c49fc9bc42458a2a20288a4a806f583aa89d32e9f2989ee69a4e7133d95dc9629deffc55f7a242fa9309f2f78769adc1917f2ecacb08072736b5c8885145e7033d0ec3bea4183825fa35b487414ffb19fa1af7d0e10259a4f837a9397feced7fefa1c20eab2339ae9aba0ff4c120551da4fcc1bc5efe1a5d9430e10c5c3cec078697e46837aec6950d48e62b29495240372d476a4037dec63aedf6692b48da18fd9194651d9c3b2a31ed68f62b2b73e7beb19e5db8ef8bde10051d967d1cb1842764ea7b62a95baed849e18a46ee611c00af5631b22e603f193f6f379f013a3e6fff013e8e70ff113dfe0b04d93e6f554fbd8a6474d4df6dbd760cffd283ee869509aa77d4ca681ec0c67d9c64bf3b19fd932cccb3cd528bef6342826a3684738648f7d4cb431d86b7666ce4cc6f1d2645ba18df8978d6f59e93adc74061977a97ef63a40ef06ac30c048894a502fbca249915b73608e035cf9dfc34fd7941b16aaf6db5b991db91db9ff8c3f6767febdbe59e68de0733e23f8dcea423bc201fbec63b0cf6692401b933d676566f292e4b701de1e447f3db6799a07330f7aa318edb3d76c66316f149361965512be97e0530f7a7d2d6bf212ec52dd120699f559aa3fa8a2ef278c519857bd64fde559d6d7245478473d6afaf9bbcb77247f467bece9f53428df76f4a8a9c15eb335d767967ac9facbc33ceb2f3b929f3d0d6a6624ed5f2fffb2d76776c69ab11eb3d04b34281ad4d543d4a81927a8d586f492fc16cba3b8a00a42a4b080a20b224cf8a94b2f8625541ec58754342972bd63bc7478f00831e5f2e5af40bbf8659e9a944bca944aa58e407d104a4dbcc1c97a92409e21a4b835b08ebefcd1bd1c9e5879393ce1a449df9bdae563c883cb9e73f969601dfd382eb7e07e33d090529f592ebc22ca17f7833e5d4c0d92e07afb7ebb8cfa214f1057dc1eb515dd1a37f51341b1d959020abab04517a6a082a30981f41386810aee1cb4e900773e8cde0beb687b0178c3a7ede1a51cd7553d5aba50fd6189ffeaae8b1c429740bce4f34d9044219c167aa9513120513ff864aab4d9d37de940c4130223171ae1421e10f8e06620d812b56a85a6a7d12aea47efc582da5ba89f88a5889817e0a4e709502c9102155001359d0577f2000547b459798a80c253032baee8421e10c8200516c57902940f7cd1832941f80a7c408322361f4051247421cf9111cc0f98ba41265812c6dc410e082c8b074418913b6801938b9704713f19aefc2680800644ac5050021b78122e58e2ca2b5f241fc2344c07e0429e267470e3853c2e6041c442651d7c19708510520ce049e207d55edc02358ae9f7f7b6d54bd01d5edc8d225491faa19981e80ac391275081fa810508549208af8842e3600aa8e9cd349126523440fd008311a8247de37cebe77c4bcab7e6cbc93a5980c20e4a7a90083940496f4401f9d64b3be3508c80fa41a2e45b76c689d802158246c9e79f764401ebe75b7686b500052f8240fd40c140c99f7686a17044118e40fd000019a0a4a54165519bde2866529f9171051336a81f3a2da0e6d3a0a4378a910f0014a0a4ad5eeaa7415d4e2a6dd20c0e1c2b5452503fc415f84009d47ce9cd4055103740fd30830c50d3b67402784a8610dad8220445c841498f85f841b5b477ac4106797e2ecf12bf1c024725a9a91a2052281e937bd2cfa81dd9002fb538b25029cdb5e8b4c1a2b9d132139c46326b6155eadcfb4f96651977c34f4e663f9a9b3d895060fc6917af9f79358a7bfcb13c3e8950e2931825fec89cebf18965c5287eeae80aed9f4be94b1e5e9a1fa358f189e4e12720263f857e6a136427953551a6fc8b9ec297ad942b3f3e6917286ce34ffce1ece7a27e6279b61ffc4a41937f86877de8077b168b81ec27ba73cb3219d9f6343c084b99c8db3ec66641f6ab37b3fc218f7a29fb191ef4cc7e41443588e842ee41366bfbd653ff78a195e1ace80b22bada67f46314fa310aebd8ac8cf6525a9a9571a73646e11bcc57e7cd98f1fc8d9af17e8ac1a2eb697833bcf792976478d04b313ce8a5d82ef4278b257989feb434e435eac64f2bf6d9c64fddcf07325f54ddf28643a33aea31f37fa4eb1f5fae7b4ef6de759ec94b4d7af272e7b3177f6214c668b85ee102a55f102d0ace7e33977be9ed44d12b3b51701cb783935da712afe9aae0b82af60ba27551ecf093ae834a60143b2bdf792bdcc3287638a80446b1c34f20c74531a19226773e54321f2a990f952899e2ce874a58079cf53fdeb9df56776488850b71fca97c4729e8a9f69cf77262b1ddf6335dcd7e4134f6561e7a38ae502f1b44bbd78afd4cd7faec3b0fc715aaca7f1b779795e1aecc7ea6fb55dbd92f7214ac43bb2c47016a2e0ade8942621953a6944ac9492a25e76d006a94f3f83abca2e01bf2ab7784e541de914cf3b2bf382f8657bd147a7f6843f6dac7f042cf7d1653593cfad99c730aa196f5d4db00b4e148e88fb03c6dd2fc90c7692c5ee82def0a794c699334ad86ec35edd9ab306a355cbef2ef44b11345d72a3ce83a8ed175b4ebaaca579597af626f58a2f2d5ab95d2fa942e89f12a5e0cfbd1dcaed6e76d47ed2aa595769d1b7182590939b9f2dd08dabd9f64d890fdeaaf88ec57af0cfb7d0e9548a211cfe924a4f422d9e745522a34b693d2a96e7ea4112430c70f3f855e3e101efc04eafee577c6e28d78c51b717f4cdb99246c6342cfd1a04425a86cb392ff03e6a0573e103f712b904a4e710ce56f9707b4215f003da8920446bda6c57dfd9a7e508c5ff99818bf6247d8af3c0d2a46c6b358ff958ff15fb13349b09fa9ef8fd998d0affc8a9d017de86950429a24e58c7c19de0f2fc98fe1491602da909d8a4616b56382d96e095cf167216f847d08b3231cb8f7a7407fc85a5406bbc37ea47da7c2bc505f0dfb217e12fd685244912b3f8890764925418471a408501fd7b80e13f7e31b2da7891139b81f2771e56b19d6a9da053631a2c895df2d6917778d07cc91bd7c07c0d305ae2c6a21cf87900f2cbff270db31c2c19f7b1d422c5e929890ed5ff17c709bd91fd0867c22542f5d96963490477af1eaa13a0fa2aa0751dbc3340ab579955695146dd00a8a9f1bad385f9a14e9fc4f662f233ff999cda426e56b518b5ad464165fb35ff6da6799261fbba4a67d26b14bdae8c9305f82d4db1fbf879ffc51507768971ff181b4cbf741e44b29a5a4604419653ca2feccbeb9f24b3da8d64f39ab3f7c13cc111ffe01e00cdac3ca8198401b92d62a12f5443f45cbaa264914f7f889d25a45224ef5f45c0a737cdcadae6420c0124471bff635d96fef1ea3781be1d03de8755079eedd8328274d92bc6228f255e47712e505b421396f149f7b1a54a79a34c2a11ff431fda019edfbe3f6d9d3c8a2b68ded9a26499215eac73a57ca672670067ff9ac5a92d91eacf34f226db54ade09899ad4036d481a5ad48f53cf5cd32e9289f04d9330cc46a83529663d442229457e82289fd5939f2ba75ce922f768fca05ab63649fedca2faf7cd6c8c093494a8d08a423e9ad0c0489326aae8eeeeeeeed8dedd111b42dd2ee4318273bfd7e213f5a3371221832d9fa92b8944a29714ff23f995af44652354e726b44b435294e2078a274eac94f0a1355a3461e40a2480a81c9fc01c2b1732f1137d4aef0fccd12fad972f8310ab309db0e2caf722e0c9eaf1121398835fbedf84a19a22c50f144f9cb8d25a2961f53812202f8270e591fb7140b8f2bfe904d7036dc89f1e6412061553a4f881e289132b57c2a70695db163425062758dc568f9f38246049be123e4eaca07822c58f5331e54a8e491857dadc2fbbb1e9eeb41c0eb4213f00d9cd95cf5e076db0ca757658a10dfe3470b3fac3bd03d4e34d85a861c4e3dbdd40bcc0c924c928afeeeeeea69436ed8eeddd1d4d32947850fbdddd71f03411024aa314a265ecf93d5fa6bbbbbbbb637b774f1957fcdddc42a89f36d3f3c127463cb6d7788430c6c8d3e31b396b287081081318155a32e92f1b7e2f17da8f5e7e1869e0e127ecaa9d00f9596b34b40bbcf179bba15eb7523e7653fb25e06184d14192fb4b991b5fde1053a90edef087fe32c88d2f67bf6f0ee8d4dd80f7a0f265e0c6971de80a35e0f5c6f80db9dd859a34f21eb9ada1afc77f3f7137f2891a9defe54a2aa85072a50c57ea5041450fe47b6c9e2df8c116bef881155eb0048f912646e04b9e28b24488235c26aec4855f03e6809787656526a8fc96c5a35d2cdbb45ad2e3e1d100d3a4fe71f9dbb708d0c0b48ba36450d1e0f2e1b83cf899d8c2fd44b73f24aa0c620a8783bfb181e9cb8bddfc317e16e163188659f8d01fb3d404f52f8440006efc884514b43c5e9a444393fcdf7fc88cf511d3243b848e28a842da85877a87ccc48f3c466870e3092a17196c9194fe29c2484393a2298b3a5ffe679a2ffb047374a02600eab03e3e0e9843fbf82fed927dfc19da65fbf83034f0f013e8e3e661cff1a25edf962154fa9fa81ff3b6cf3cbe2d43a820be229863bb91468ba3499ffd670a03e4d5803e8ba6207e10314a41f511d3a462361e7165b8df9e7ad8859b0338db83b65d376bad650875de4f742377798b8fe3c59b0186068f8797620f42ea3d411bf113006fc41f9da04e5bafa834eb094416655b625b625b625b228b9245096d4c6c4cc0964f259543a3b4875085c6852f2a41ed72600e035c7f56029e2a8cf62349f150b0257151f9ad8ef97e4e04b547115e99bcc4d785662f62e23e8c32f9a94767ecc4f5ffb6132b216f7bfc9ad728938b44d4d61f54ccce24997981044d14c949a1b49c24fcdef78b3bbc37f9a9474fed113544f9d65fe4d8dc91ed7ba300a3363bf3034ab38cc44b2bee611d2ff933e9e9a18cc3459a448241fde00f0f94d6ea3f9d8a6fd991a52aa90c046c45e5cfe07f327460ffb15839e87fa12bab0982c340651f028ad26c4428ed5f58076679d0c03aa48d814bdc3e00dae8170f43691d03b4d1ffa95cd10a94015d2cdac237fa631603cc215ffb18bed1af591efe9ef7657babc1b211a1b2d73c1e7e02c225d6c129be4129104490f36d9035b8669100dae8cfae08f9baaebe2ec738eca325026df427711b4703f2f10aee656d3c005da26522dc8228dc189454be362bb8fd161227b80d05a481409c5970fb9b858090491fbb808bb8cd3a6c9331a9d047bbf0bd15e81389244397fae391eca17f66a9bbad52d48fdeeb04aec33dac45c6b06fdc764c6d66717b60d8376e6eaf2a788e1b6997691d4993fa9d7ba0a8ecc35a74cee5772d7a246cee884501465976e60714fb78a99fdd91b89126b9751dd9a4e7f206befec01c06b8fc3cc01c2c12823f00bd80cc384cf7257a3b006912333feb0cf1937cfe18c965d28bd89abcc4cf6c599e42786812d35c12bf48c4577a6c624a9945fc4c62a9d324bef24a3b845f7034899fc44485ff99ba9e9945a7b35df8196c543f0f300730c0ed375971fba9b8fd0a70130e24353eefe86e3a24469ac489a07e5d4e87a4cbe967af2be275383cb4cb17e793fa0547934cfed084a3493128a9b3ff0989f426474dfbd2e58c92d40e4993fadd76469ad44f62a2f27f5dced5a1465ce0022eb88007874909a65c88850b79487073797856f3b3f9b08ba981bc108b2d88b856a4f3392b2cfbc11e2d52518dd6485aa89fe9c29e7a42e4b5469a27f246daf3d56c8d2154d785581c8109f79a158a0a037fec5f2c91c87aebb18fdb0eeb337f4b88bc8ea35db09fdf98471f6eee26dffcbbb37e745191755dd6c7b44bdff93efc04b9f0331f86870550eefc08b48bdff93fda05f2b4a0e6ce0f32c404a8be69010a261051ee77514bf4d3053a71e13b5f86989d9e4d02d0c90dad82460ae99c735ea31aacbffe7a28332a6ac89b5e9552cade26002fcf97dea88617b54b4f2de49ea88bea3146da764acc06e88df8e1a88aa0caea6e6e7f660aee5e658cd1a7b47c69bb44cbeeee30423a44d6cf573783e3128eeeccccf0074be98ee4892825e3e83ee7f42c70fdf98817441b408eee178da219f4a2d606010b7837ca77d8c1103c59df967dafd112a537c739e9e600f9fe961646d47ae617d5b0d124117aac22572c42ce5c01f5223c91b489edbaae2af259c52a03edbaaeebe165290f9f1c2fc193057370afebfab75f9016ca4398e2252832410d898c506535a2970f7017b1aeeba256088caa72214f8ac94a166abd9027758415302ae8429e54147e50b70b79525e34c0881d2fc13be7b790786a8e28e2891372ba37e619a72b8bd12dcb7abac5eb611a0e8007d2a75dacef0fc7f51742effcfe1a7dca6cbc14126532b44d536b654f6fb0c66dcc9ba8243940d4f5d3eb003572a5139b88798eca6cfc94cdec066defb6741b2d8536aecbe660d992cacd3128a97e21fb10f83384bd1d80f490bd107a7bb850974d77c338f1035d0ae63000ccd1d71989eb5cc4f517a26d6a13a8c29185fa9cea4ff5a7fa5ff5aa57c5a0a4466e77ee88f6bd51a051da478f5598c779acf3017823889ca79a2531a1ea56b40752ca28230ea0b86fda472fdb764c7a65da74e95a865dd49a5182a165d845ad1965bb0e645721e3a8dd4dbe7bdab6c3a2cc9031ae8644970cf029adf196d7429261ab41bbd1d21c54adb6cbe6dc327ac724b20fbaf76d0f829c884caba9fc5fe4231c6fad791631794d4afd6393e8bc2416a1b66931c6d8eef123df1823e70eba82c864f4660d88cadf5ff422383b1ff10267e7235e00722268299782dba39c16bdfc890bcbb48d63674752dd9fe04015d48e840c0c30c000038cf61c7020a8651646af8b6299a5d18f6a1a6c972d720e0a5551e3471b372455eb60bb80b84dcb402adddbb0e4e851b69c3c2ded04411736e98b79e167d39ad81585ece5fac6be5ffaf869652189d4243923656812a5db11510cea47224999336502219530821754c0134d4d51d118fc502450a0394ba03846a03740a0292b765eaa131308d0078c004a319912832a2059028e6aa722f94c5765c241537ee2ac8025f9403002bd5902c58102cda902453285c640b5130016d4cf7455261ca697faf30243038f08ecc0838f2da45cf91e49325c503c2142df0f128102acc308126e7c7e4cb5d6fa82c3c781681113c407884f8d8f8f950b799a38023e810826373378f1328317476eb018c20d1657c0e066207ed8f2b7422c8cb0733fa8b2d74e853518be04800bf5ab17bae0feed87a9542a9583822f03cc01bffaf76bb9f0a36c62684db0047b3e2082cb76a77e14c62338fc61827187eefe3f1c4208e13bacb0c20a2b74a7f2c70edd51556bdcddd4d313c4ddbdbdbd2d9c0cb6f003b861ace7a7168659561661e699679e31866517e52cc3f8a2cc568471772458064be033a9e52d4bfaef7bac7ff49e5aa791d218194266869099b904f7333d71e4b328b8d584139cd0f6524de8016a11eb6751607a88288d3624a20ebf8ae2bb156b7c18af8f1fe347514854433e2ccb8386989eea4d9ac0a777a58232c6478f5b9fd107a594fa88e9d124f7e117ed1103ad081d428c0a13080308a2c26778858cd2c626511958795cf9f0b52eaa3f0cf272a53b3c414beb9d1eadad6248a9d7a4f2c3239a6647321a4ad4eee1165b1bebdb7a997eb699cccffeff90fe6553c3a97669b73e78d010d3a4940d901d7e6a5c4e71cd0f910f4e619b1f1ffafad5fe1bab67172bd20b33333fc6cdcccccc922333c3740cb31126cccc3d311560d2e3c50713263ce2085613062968b2a2595c219585156c322baa3f0c3cf580a5f89449a5a61713c7faf0648acf2b8e429a14e1cf90214d8adfcfcf43bbd01b7f88901d7c7bf030818518656ca246164419148931c618638c33ca1863af6a4d77f76a8776e90112df638c31461e234f5c9dfad196510c2a6d42ede71d70e4cd54eba2c2171ecd76070f48937a2503ff07101a38aef031bb0c036917b64d6915c192056407e8fd80ef42dffab103ec013343049ad4ff3bf8fc85f02184107633b91ff4f9d12eddb08644752621d571ed2b211d242a954ac52a24acf213a5b58a4452b2aaa7078853f9d0ebc0f22bcf69d1c35bf08a555e8242e78180515c28c43fa18ff10fd5ff151a59549ec2525825bf913cd12e11e638c2d9e080fe26a74693629402e8419daca36d7a7ac01cdb95f4e1caeb10fa153be267791a940e2bcff231fe2c762609b38de96779163b0382e91e360001befc394014cbf7b0837e0f16202e69f45c03d8a2f6c0019e30f0a40703026dc8ffcc593e26f42c76443fc6d3a062567e44ed0807968ff149b49f61d13e067d9a4d9b19a2795cb3ad78407e421e44ad14016dc8d758c54c78097c72d1a77f65231c563ef4312b1f0afd8abd6c0ccbc7b0332bcf426df47c584942df87d07be8fd6342d69fda98957eef4d304e7a61e29c88a3577348600d6d2096e67c07a4d3d3d3d3d303ead10179cc03ad5d0ffce97ae00f48c6d7b07c8cdf40efaf437dee37272b283fd5eb7a403e9b17d086dcdc7fb8cb6079cecec47896a7914505b243a773c11c4736968ef12a2ffd25e3d426c51f24d90f0f30c7bcf287b0bc54652e653c5bce730ffad0e0130feca2df5cd40faeba1e6f03d0867c1e7eea814bac03f28d8f81805bb8f22fb53c401bf207e0a47e5dcf950fbd848d70e0429ff106fad057ee63405c65f1a027c30b7990c58328191e44753d7e02d9117f773e7ee22c08549ffb994e42144a877e7f1d583ea4d5a488dcb0783cf41424a00d497b7c3a2d9a84fdd7f5b8d6241cfafd63fabd6d8c7fc8ce447a33aeaa80ba158e2ad12a1c26f831c2780987a765d8949f2675aa53a94efd74ca4f94d62a12fdebe0300ee3f0f6351a63af437d2c2bd2379d44e774f5ba9d8036e4633afed8c7f863dbbbf6999d01bdb6a3a453f2f9a75da44c81398eac407688f622f6619b1e91fc18c2c91807e6d846fcda882de869f8ad4ef19cfccc847576788a253d5b3cd16205e5ca9f1677aa6b463864ef9f841f6467409f3d6fbf79206ff28e9fb49f367bcdc33e631cd6d13657fe16e33320b723fa30463bb23d44690fd33a9be63d0d2c2aefb0920128a10aa00775de8f7104d0836a5dd65e077f4d07ed9734899b34a98775bc8d006dc8a7b453910ef9b9e1e12529f9a66130989726c9c7a132a964572ae44b5869e57a0b39cb0a922da75375aa4ed5a9b64e95b3798cea547ea2b45691e8bf534114f4af5f137ad0f70887ed575e87ee59be3b2dba9e6e8b2675aa8ec9951d14a00df92060d4f6f1674a0ca18aa8540c5895490c15a211080000003315002030100c088542d16834cef34cf30114000f87a250684e15c8c324c85118658c318400000000000018003344844d001c06bdb14274db1c07489a5bb307b00ce9fb24a2392b2aa3f1477e452030c00ca57288e3982ace1cf6306b9c76f03e3f7c19403418d6074372274b96f820e7943066cb51e3c72022b287638a4e76564984baed0527e47408e779ea9bfcb020849342da3c3392bd745dcee565382a2acf9e29d92668d863abcf6260cc48d1bae6214da402b9abac80c83584aae540c9eae7448d00bae5cb8d12bbdec245e0ad3cb44e6c9742012667e05aad89052074075481b0c12ac6a44be1d6e16b7714bb34868e11fd53a7e9a64e5a4fe767b819c20383c00c1170edc0a913356e11c0dacd32fe015cf301b3a73beb4317fe0eb47a90d060586de4eda2bb53906b1c8ea5efee03ceba9d2a8046666a659d26642c2616497e3fbf7e2bf9d0dba96d46b4d0f8cfd51cfc0a10a6ca795ec31270acd59f4fe322ec42c0537fc67089dc30ae83d33a81c9f4f518aabf368084172d9c5e2a770b6f81d4f3e3eff02f381146e907d3870ae004514429de22ad5bdceb65451d5d91beb9b50375ea7082866d5edd2334f45c5fa2e2d428fe5f1e3eb90686739440d212a39fc5d91ad6da67d55d008a6d075377a2818a56e7ea9ad222d5d216a960955892b585ab798bfff6fde969e6663886e90b2d927d44587dd0ecce8003c59c247705cb55fecaadcec022d8be52dc8c92759adb128f37a3986ade2340b7fd44f0bcc4ffe7c0335ebf83c419d5e5e740cfcc69121caa6b2dc1bb914a5c723a3355916b71847c628b7758a4150b69f192c4f33e9475a5f741ca99cfbbca88fdf5445a675a9c6192a311905b16cb374a5695b0af5cbaae752dab170bf56203bb2d7768cc958eadddf8544552acfd6cbc4f6b555b0369dd0f89cf8a6da4b2f083ca133d03cfcb1ad112a61410361086096eece32eb1c2edd214c5343ebdf6d5851c40c976e2d933dbae0bba772fd96b8c2ffd2efdc0d5d0e3d768f93081ce944e8f1a8c98bed6d0466505fc73325c6bb6e8d85deadbc417557ca2aa80180da6b88a96471dbaac777ae0beb3c82134b0a829ed4e81e61a61548231e068a8d3889bba94cd7a824a8fd89f2f4e91777a0243c83137c6755c4e35ab24e4e35de28c432a74c18564fa7bf22215427a040a02dba9881e7c19cae0c511a9be65485526f70bd5953b995931876a7269b4e8d50d5e8ac32d0bf15478538c011b85abdcbcd7a5a6c084598a4800d4c0182d38a93ce1190b140966d37907d76e56ca2d620fab846156c827ee0868e0bba3f1e29bfbf481ac4bf78c55aa56370fe1ef266ba0b79f86d73875fcb68df18e5c3eb3f295762b582363850c0c8bf26e044b90536184a10df3aca7d272e876770ca319f4c9e09d52c9ec3710916d7447d7e9a8471ffce734a7563f5b9b3d375a5c839683929ed7ea5f6cb6cee97a33adae543c29c705674df4b8e2aac96b2ffbc9e3e9e65f5041364b7f0a9a0cfa6ca5ab9e1b49d8e62f272f384108765807384ad9ef113cbdfdce191bf74a8d64cc907bbe13850ac79678cb54d72571c449dab78a2719ff8c1e609291dbd420cf10f4a6c554528f207ed084d3eddc918de42a4a17b982cc48c2944b021bb78d1ecab2499e5347ab26f10b67b761f5d45cd8f7ae21edf651e30cf6dd624baa70b65f02523d1d2df596176de69457d32ec4f0b50b92b6ab1906e0cff9a19b58281f558a1ae34640bd1e261722e219a7c744ae036bf822cd6c5c15e3696a40309e3497e3daad7f2d7d4f86f4a45cb7956b8c3f8922bcaf6711dd8e8705a2b16f9213419bd7d80bf728a64cfde6b9a98fe1dafbdac1760a875b9f0cf1558813aa242fcbfc613a1a23fe8a55fac08c94b1eddf7d5fcb1c73d7f17b1f373fb0d2f6ede5b7fadf287079b82161eea238ea829785cb0d73ff69fb619f920ecbf5c68c6ff45b3fe83cd83bacb1acb5a214f6535658890715f1121045133054196151521bce40de21de56d2d309f57c4ca1ae813e0231cb1a15c405cf93de769e08037c2f18d88162c3449146e1e877602c9e8d822bf5511555c89eca61d5564bfed2c250cc4cf3613d3801d003042944462f938c0b1905896ed12ea3432182b465f15a076514b9e04fbb41f2b561798e87d8d9a39435f749d4359726e756ba7bc9611ddb241ecb94d2f40e6ec209ec7c5a5cf504f422908e247d29d01b24587a0f68ff55254906ae29796607b5ddf1915c6a1dc456c535287bc2ba9621693ef22868897f4705d25c8e276f991bffd8dc2680c32f01fcf4708d196abb1f5b0d604221301a134141b01b0679b8d0348432712e397bde5f183d808666d254be06280583d500ce4688bbb10f2957da02cfb3c75d27e8ec935284f291ba386f5ff5cede3a7e4a89cdb284ae07a228659be44166050e4a5ec5bc28fb74f11b885048da76594347c12527c3c144cfd9760ebf8d77ae0d59fadaf7fbfa109340bd2fb8a604cbcf8925782b0234de40b13bc22b7980369c4939495027fd8f1da20bad1cd8ac32e4431f1892227c4b6cc9143feda425c0f6067e5886c2193479a3258212d3a366d6d7db17ac464a0f4a2e1394041920543ac9873643fb5bbc05d308308ff3a80582470274d13d1110ccbf46a38e133d359a1be5a9c0174aaf1b18359cd0b686740cc41f10c5f1cd91f7d5db8dee68e34ac29834b18679edb34ad68aadde2ca44228ce805c1f3de1f0d7a957dcf55963e70f8205146d335752484dede162b7e492302afae4779c0c4a5b0e94a428eb474ca9b02d2d78fbfceef7fdbf2b19ad8321d38c7f234f942a7c3c0d3f27f62e29baebe11582b77102c3cdafb4f21ef22884b023538c39b2f9f50a6898803aa83208d8de00f3fff7c741de0a429b8062b0608ce38d863a800d4439b2cadd8f26680de940d75c01f6e7688009dd1f99e4b273413ec964b6623302aec71aa1ee790ef3fda50a3c35cc95cab59f873974bb3a70642f813ab47e7d9201d54087c52003820aeba9b1a7aed13d3bbf20a2ad02acec93b2685c5fa73d7cb1291e19d4bc826443219a2f6e412377f8d5aafa5476860499c28a6fadf13372587381d9542b360590ec5847451c3a766af300293ecc1f40e3dc6206a6e6989947aa5612f327a1200780dd807a814d03b2981ae522a6f561100ab6e028a6b8040a00b13e2802e32d8213f827b02340228f9788a74081c858c3f4c42ad665793f81492844b9ebf28a6962556d7fc58c44a573ac5d46b8f3441bbc5a3b309f00d294798160028e32d2c9266ed3cbb84bb98467aac6fc5a1efef8b083e6d41c702fcf5c37d13f050eef77f10e2941e09b60e15004f1ce744ea83180db39ce59bb472df3e0c1ffc55a5e3010f48d001875250ccc097bc4ac72096795d98e091ae48d30e819807e99c7b2cd7dfe37842c9e250bf2a0684148a74c4cddfb078695c6e8e50bc45256d959da52e9f4b17be1471837abbc2b71d124ae2036f26fe31f5575fc48af7763b0302a310009bfeb9c47adfb7f51f55787a9e98bfca4786707ee4d20df6d2901dfa1890fc634693f02da87cc08aa9d7c534b0f0decfee0c024fcb1cec2ed146c0dcc294292dea21baab8388aee03e9f46caed2039483cb3740620a6351e0e10045cf8d517214cb5fa2a5097e3f6799f214416aa5139bbe22bcd96c4f676d07140837bb57b6cac41598ed46e33c12fddf1f942668f5199e0913ec4de8d36e9bc517512c9f5532ec621fa50c21fea2ed23c5f4375287d5600c4c10366c60c26444f7e172e3c1d3bfca828325687bf670dec46ddc5d5bd72e06262ab3139cf9074a3ec2159fd8ddb4a5046295ce34cb300cebbd92352cdd792a4976d359403bfb66146337fe66dd814c833836e12545e3841e2800582249384347d223f4cbdc5bdcb59b11178ffc6b97aa6deffa5b48e9c9ba398daebcdf725bfe602b358fb9bfe8f3b7f5c85f7f8c9e08650bcffc80264fcac5ec3471c550476e40f3b41f94233d4f99e3b99843b5705373e76e868d3b4d03f2c8437b103200d34dc3b716ceca98c2317d17a8642132a0d2f233c94d8bedc874381b7f3ce2ed5dad6cc3ea59f8912cb8a9e6ecc9810e0080331651b58a7b0112de8794146fc1d9d28761cc7f52b3ba7f856e49839b832945a3816634f62440d9faf80872bb144b746970384bdd6d25a30f7e9c8a64933a0c93339b585d4ef2d517f08593b90d840ec4c7cec5ce8db4525571e0bb77c1022de6a398dc99ce7fc46500c626b683deab277f0a98e40f0e3aa92205a4cd01a5adea897d8128602cf0288ea576dd5b7f11d781fddfe9e552e4c5496d72f2d343d741548fba06aa96106370be2b1f8f6cbf1957a20745be51fc753a4c35bcd2cefb451fe730329fe37fcb0f67bd8ec97e5e777121b1c1ae17e3a1593232cf89078689c7486dcce1f2849d29e6884e6ab1ec750961c41815dc64491b14200ffba3a1f75f7e3705c60f90ce78a41a443acac847faf8f342a68860ff5c3f8a5e614656a987aa46278b136d847d3554bd72bc1ef364a12f63a067e8a7c77be10fd3f410ad54844ef077171427baad00c44274cae66fb4fcb27688246eafcca62244f4ef832bbf94769a10b372e7a4009257cc27917729f5d7a742cb28fb6d4272c15346f57a0b657e23a08bbca6c451f3ab09f23629fd6a8e71b3c6c4cabe4f028dc948f31fdec4834147b35fe965961cc79969b939a570fcc1e34868d30dbf2ad37503ddd5df1f967ea50a7ec574f918aff6997911a4fe40fd5f9d0a2fc62bb1eade61b2aaa84bd96bf5835e11977d5e5300feee0f79d2b22ea12b476e34e15a97687ededcc8a3fca578b3a8d4eb8f304a41586a9d5cffa95b2d9b54a7fc4e1bb2bf710853914c3e311d05d79871933945781da62c70525e83e32ad233b48ae7aba30a6526896b89471333c47b05826d3a143b380d7ca6e36826cb94d4f933a7e2be28e39c29df73188bb14b079e147496335d03ae47c1c700f76a60fc8647f49e0672a19282d14edfb6f0e921f9e2de7f148ef032bfb70aa0621a6aa637fddb3d9c04c24a75a3943e2e01ef08b544fd1a672466538162336dd17f2c54694017654d9b9d3e6912692311b48e4d2de93ec2202a049e49df637dd296d59057fd6c36533d3e648917cb1db15210066c668dd45123c87daf4d3251595bf72b010873c7a7183cf725f8d311650e075a8ed099fa4f938497c383d71179973c9edff816891758c874eb782887556f874884b4f6ece3f85e28aababff650911653e9dde3a8ff59011905b44848b2366ca294e28d96ff3d58f7ad9495262f7ede2aa28d13d8fae0695eee2c197e838be0762b796db77717f3d9f8971a95e02ef36c40201bc36797d3540e5ef1219b233ddac14adae5475355e81fb4d0dcdbbfb2ef1061b8994dfdd05404a89941461c1836d4f57b016329a55e8d5717d1987c0d24ccc52abdeec04761b5e2d190ccd811ca40f6ec56b87060d13cb8942db856fbfe71527b9a050cacec34ccfb20304502f867997c049e24e6c042d48d6a7251dc96252a02bf160e2a9ebdfed8517f4fa8822656c04bb9dc1dee9f8e0fb0a396f6a58847ff6f05216f779b04e487b6fd3eaf2337cc4fb3700fe728571317491d158cf992bab9a58b0862f23859a803c8b341a3f11b11bb7f849f232908b35a3fb493a8cff721f04451a6c025a71f917780006ea0e39a79ab45a268382c0b687a0e674dd946e05cf6616e628215fb3e590d5883c1d5003d378fddaa8f4cef6b5aeba4fb7648c335fb4541c01065d3b4101ca68429cfe19cf7c7c89eac4ae7296b0ba6c5bf6aad4a5a36ccb06de74525a90bd3a7c91a45bcf11fba84ab1fd1690b08fd997e492481d016f0542f4f219c79545775a07e715041f0461d3171d3dca274a2f03f38cb95670d8a5214f02f058805f2e9a52a3556d8524381b6235877861ea0b7d1545130445de6fd4895920ad92550603f29a1da80680136c79398d5809e12b256b4185482564c4106f82070bc22709368a375475bb963f95f85020f1ed41020759f87902c5c472ab19d1754c6ca72b0bcb35eac37736f1599f3fecf8dcc7c63390f9f46254834ab376883016ea382debf93aaa2f7c521bdffb583db9250fab6a9bd1838c608bba271008066172b67b474b5d70d7ef82a28edcb58e55055654772ea64d00c75f1e38856a70c23ba094b8eb41ec2a1552aa888b44555e9f5be033a3b2891e83782ab1d246bcc0b89377f78a4c561f22aa51180a3d6d682dfc289812dafaa5363c0198588703dc460b1e1be552904573c88a80736ef33cf9a868e2d3b962b202ee220b6b080f1b363fbf4a3a6f3831321e7dfda18892ade529578f16aae54048761200c42fb21476859e322e7cae0b811545bf6db9005021285f083421622cccee6abfc7570475544c3c24eb84f594cbe8e24c4049b3382198cf15eefc638beb0469ae1d379043313c591d3fcbc944ec543925d3c5c7bb8f3ce08b011667c211ccdf3b6575808847c487cb02c9ee9871792cbcf1641647d2f5eee3554576dec717cadf70b66afb0b5e0a1d870029f0559f33b2e2ca73f8843e13f6e0c0a335abfd28d52c3c096874aefb050eae55de739e1b7b23f3d32e3b51a1f2cf508a4392a66a7053ab1c97c90c1e29fdf132c1249a1f39ea1151e0a529514aa91333710a6a4f9b1bc47fa12029123d68d061ea1cb43139230946ce05982f61c039b9c502cd01c24abc31e677cfaa9aa0168aeb05fb1df7171e7d868960dc8d7f77f80625dba6dd705686b32b68dbc672972d7adbfd61f3d3228d4fffd45b19591ef085f18868025a6cd0b85d72794cd8c594bfcacd951c603ed4ecd4d5cd3c271299dde688b91cd97979b9e87119a08d297254c060450a7d0541ef7f40342e3a500581a172ef34077f39cb6e1d5952b5e7d65fa22c4ff8b20c06dcfc52b8d8ebf9cf31818325d8948628cb6d33e5ad64a30e563eba27d0ab0060dc0c40c5da48a8b85c47f22df807d55415ba67fdfdfaf738b35a1e51dda888468f3992054742d3fe28aa8ed7e7f9c7d4c8bd088d24f90d5c5ad9392a8d144a7734d41fe421d9717c6dc6f6e93f393b9838956322f1478fd73756d959582bac298973366f44afcc3876ccb3a258b82fbc88cf777e05eb37129368936a97fb2c46b0bdc3f48441953ae93beacb982c1165ed93619e7c4761b104a645816e700621fdf62e9d44ad0ef8346784caf23b650cf3f7e2bf3f22a6c3dc6e1b5b9b94cf08b688ab8b70d5711c574fd643fa01b360cf6995701469179fd06a50e8c06a5b713680a79aa98e1b200b2c274842a0f763b13f3ea4e7ba92a79466ea98ae43614e7e4d3bbd97e8ce84dae87aecede898c08af30c1d45d36c2974ef2883205707b091d6ac52a6f236500e55d8aa0df51a36a4a867912e78ab190a5dc72d337d3641724c45c00cf9fc34d296d9a232570aa2d8263d08b8e9605d4dbd1104551008d65169894f2453d1a0a7c0a3eabbe46a0134af1663e1595cd9acf0ada4159f7de89eb59c16818827f4c767b0f7d5431499747a0d3bc94bff7f18111687a723bd6ff72a682f94fd5653e562ceb948129a1e1d911208f917e5bb29ec4f334356a7d0464a59fdb31abcd80a19418dfda0e0134364474826fca2848045030005f77b79a7276494675a32c7120d3a0552383883d0d8d8ce4c39c725d9ab9622f69ba462e857e3a8c609ebb7fbc07684313168d0cdb133188394c232aa1ce3a526f2fbf4bcc070931ce146e40e23a85017036b50de73a7fb7c3ef131c67459475b3d6e911549ee8379c6c93fc0d9b3ac544dbd59195d3170e230727fff5f8c16f3616e79b28dbf39764e0128c2abbdefcb153f3c11b83adcfed51170ef8adddaf6ecc3bc03f62f2f593b55a86cf862185f019761fba9dea3a63cb517faf5c0c90099435da8e420d545c556169f89d692013a072c0742e986a989e7126187c70739b5c1a721bc24324647cc21093f98fd77011e063b24c78d5c89dcde5c385b4b874b89c9aee175a1c12f3223c7abb1d9ec2840fac7bad49e235c7830d18fb485e3df4d22038e81ebc3fb60747c7448a3001555425467dfcf614793c3b7a79de6439a9796740016e4bb1bb34e7e988432fc0cb5259976bce29e48cb420b72d47e93c8e9fabafd1269d03cdbe650de7577cb2445e59dfb28624a1ff031b4bdadb2afd55b00ac2d7c50f56dd23e7ec30e365c28b3146a8688d5866b0a4042e1f129857d401792f34f01c10a5d443502cf9d017963c060e1bfc5cb24bce7276c9e337ff8736154f27938fa3ae409813bf0b0ad4582a2a545908889c6bba04358fd1b2e1dadd992697082de90ac52428428d71c22ff63eab776ddf9505e0429dc46c0fd1b0a04d17f4ab1605049e5f5324fca343b591d36e0f6c244eaea5ac7a0c87d2fb4e1f0baf67008fda44378d6994eeb9ca0fec647cec686788ef82a83694afc3705db4a5963f63a1519fc5d765e4613f7666dfe5dbe08188efc034f641a6c99c2781bceeadaf459d1047c4dcf2518d4ef7b0f1398a9ca7b31d13dce7e7957d71f578d2a3339712986a36ff990ec2f84ea6c811bf4e7f8ec2bfc0808358506a1454bf9c6c392541f3a40c2ed04b00c9a6c0788454219c6dae8171afceccf7084d47b18c716df335fe84bf6a7b850c83e043b57562cbd902c6ec34557fc0c56633718b015646026b4a85116f37e77c9955cc12b2180429e8f0d18e75a80761466ffee1e49c01b7f6b2793abd2d4536c8f18ff2786fd967bbfc26db7c595e9d9819bdca7d18dafd6251b010596d59ec7fc36e02979e30856897371a69c0e0c9eb0fee77490f679f8d9e6733d46807d895441eaea253b006dcd8fcaacc911f6be0ec71045b14b11567c0a8bca65b3637dc751d6e680f17baee8254a5a200a3010f1ec5520866736cae95c0df3c880c3241617b99d8527036c0d2b091932088927674824d73283b37b4a3f3c208b49f922cc46c1f1ba4a1e494735d6fa749cc6821ea86272e154eb23b17948f8902a6ac6ce360f7f8952ed431199f4399b51293d3c4ab2be71c5edc031ae777b8727f15434d1eec8a15a6e72113945f10490625ce285733cc0bc71346cad7cb3ba411c4b0a82c8a237901f1d22d1cd1026de502f7d8553486c9fbcf9927951f74818575bb9afe73b6ff7a1c6c900ab553fde760d6150e5ff4192d380d85f143f8b064696b63df6abbc515a4858dd91ea968575780f78f03620f8e818dbb7380cf38fca2c35342ec7a12a30a4abd8b9b7f70033ec7f8c9bf66ca8cd04289a228014e7a1a08400ff3a395532faf8cd53685e804aae6eb7b3deae1b535c9153f4984aec4c8d5d92501bfaa72fc414fdd26260fdbe0c8154870e704a629c5403f49abce92c23ee703c690c38085f0874d2f219f0a8b3aa0533b6cd5ee888f7c1da123349b2e9c32751415c649005c7d5e61678bd72d9fb834837a9dd9df71004c37967a558c9303f4210211ab438e7a22e3d36ca20d2c1770c491140192caf766aa75e19bf9d1ee6f4d0f3c9340bdf06b2d0c34f10503a9f31e39883f8455955bcfb4633e967711bee1a945602f67b975dc69ed34f4e9cbf569223964994cc201a41846b478062924516514f91ca634d20506a192bbf6a3ce1a9e9be9a40aad8ed74f22418bed46b5acfb332d93355a0829a6aa633b0b3813512558e9549df85609b2764a1216ad65c1b00683b81c476d917aa24c729ee8e129b1998b9174ba661d5a51f24eda4a22035af00a8057e30e3ed82fa77a0674aa00760a5825ccafec1fde22e71f96721e79f39ffbbd0c8466b13511b2c0b8c5877f883d6674a75c395ee8cd2ecb0c964e5ba194ef8eb8f491abe2dc96eb16e412a0324c42de2cbb24e2073603e3ed21e8ca709cb94c8c00966b42cda0941a85bd3949c1993e8e04f3f448feae548c89ed852c6167ac93f31950a4d17f0e8f25669ee439e1c2c08c7387ed06a00e2bcca2f39a1cbe084dfd97d548acb42aacf5295a78a490263ffc4304bd8205c8bc3aabcdf6f123db00c26b54ed48f7425d1cb867748a1ea42329e0e123fd1b2b1a974dd22bbb016e35017ced5cd1d024e3954004cc7ff5464c2add8be056f6e2609856cf936a0e2cb9e55728a009ef086a39a3fff735e135a3df630c9ac825502c1af9ca703a0a191472990e3ece87c14071c1fecba6f9e9cebad10c2e48bcbb8190e9f1050f73bea5cc870df87204843471aa658d8e13e91399641221bdf1737b3c6cfc444b271a800354d01e87fa620fed0120ecb8d1530459032aa21407be7a57c373d2db711c2f7449db87bf25ab7445bc3d9b0c83b09bda91f3d1a0116902776fc6afbf2fa49f080c51bd33c2602a3d8c31801269c64ccfd67ddf93b03f1cba067bed0734252146c169a0fcef1aeca8528f100f996cec1f9a51d1a31a5121b14f77fb545e639713cb9cfadcb042519c1df3b523a61cebd2762ff073369d881f886c76c89a4da245494586e92c89e79d5fc20ea2d021e1457d8f049accc99d70390a0942c7004b8183b8bfe4a417409196fdd95252bd8124dc7dab617c97883e02a794059f8650dc5ee194c9243397314a31586b55fb093c486773978af0c8499bc89b2b132c5e8d15b515847fbe9ba4d3188d63c728fc194b998347e98d406e4af89dcad20b4244c9aa718aa82018aa6d54fc1c19449675ca97c727a8d8f0a1356ffba611f46c223561c51a6e7029ff8e20aeea50c22ce9ea32e5f793e61b160e2c7caf7c0d4bc5afccf6ad61773b983b8201f304144d1c7928d778ab7e12e2d93d41c10463da697424a676e1c7a09bd13a10e21bea67f403f922dc4f5d77d9b0662fb2eb338dbfceff42479d066d915ac79ca08817cc2debd327c7234a27c24847309fe4038ec1580f27f01e36c72efab3214b3b4cfa5ed21e6e409f9b36b58360857cb0e034a4ba3d08ef0d3d696fed217d2fda89834de0b355ceb554423e1d177f7125aef54f7a67ce450e507d83443c5e8f35246a09d193ba83c85bb0a5569712828d51b42aab47ac34a613c729d525cb35f8154d198a95b36ee8e6810dd023f851012255ad43443334b52887c331c3286815cb240ae9329d290c61255f98ccb8b372aecb5b3834369bfcaada9de2f75cf83176e6e32e5c84982ba8aac4c2249bba8615c5c83f46cdb0fc5c803a3957258477e3923bb30a979ff2c8376747fd3bd309eb8ec8b56675e19cf34a48a90d49bce4de0d9fb9078914b7a216b9f8a5b8d3efdb7de0295617610222600ad7a1a5d674b1853ca7a30855b4245ffb50b0c1db90d38bc7fe2c9179fc941f6d16e7038652fc073a3f4c68e4d30ec452736b6adb281c85104dd15d5f79502eb12f9d56a87f6803c3c9ca7eda7ca3a92bd8ee638b633a868fe908178f8ab4ec30868d572a086d1f93c29777e5f6fb03f222488e65e14ff955600fceb5230c616bd0e171179cf41cc7782dd37605a645c7057bb3a1f8b25612ac4cf7ff150b6e8c3a2e0878544dcc17906a9d8e307361711670915cc5c51e98801776ee932081754fdee8122d9caf6360053565678b3b14f9904cc56fe03f04b00181a7a4d020e2a5d39fbcf28a51636d11598ddffc25f8ea952a45c8f2ee7b70ce9caaf0a83e4ae2dc3cb87e26be62002a13b9670b6d1f9cb319cfd6adf21af9dd8449a701224719808fc58dd1257f74644027037640d690e86a32ee51ba054f75df579791ae726bd0358a6ad57fff4d3b360954ec45813588694b7e084a2dcac5795c882eef1eeaeea73abcb0994b28adc126d3e3cf7fd9c9a3bc665609e1744d99ecf80f6770d3a36bc9e769bfc7c78bb8a738667a54d2582d066105987c3c6df88e9abf9a4617c26d92d0d08e611b8ca9fcfcec9977e26562fc50cb9f928fa5fb917b22cfe6f7ea1576c3855cbdea485f92811e5a2306251514bffe1eb0beda3e2779187f9476de1142d32f07a534b8f54072fa277a63c3ef2d54d1836bc165dc15b4ca89182c6e5aa889e365bdadc37298afcb169c8b9718982fb99c2cc8ba0d853bc4f139a278de0dc01d4e908cbc939a188c929f1e698afd56662266e8be8b5c9a316d8a754a6a76f789abc29ed30380eac27a63d743645b16ba3701df9580d926d9e337d5463d875ca508c20111a6222f80be45289af51be735b0164bf7d5f52d8c6c5329df355c96240a0da64dd8562743d3147e5dbb84d9baa7d64bfce2a55f0ee7f77c1e2fdb31c879f5b91d172fef6f7ce65639772ab5a54ce6c3a8e99dec45fbc2932c285d2743fea9dbe76c421021b5b0de57ce10f6b6d299a39f06065088f4603f995b65fe61974231e44388f3a7eb0d2eb1454d6f16f4366062fbfe1902dac49ffcff203280a8376939b66d9f37288daa7adc5d1718cb3d8eb03c1b1958c63b4c7d808701b4bcd3970c1d613e0f7ab7ccf692b556c5b7277d072f4b51f2d25c8a45776eed8da914fd9ae6c1009a322d1cf4c7c918d0c5bc40ef12f0d8826300b57a8cf2b19d08b3b09b15ba782288b1ddfb0b8352d10d140897c704b21aa2600d2fbd266091f40d6e314683cba3b4126ba0a76089cf925d7f81dff423c0fe0825e9dbe4232b5fd1e83c9da70b3a5efbd4f871961e9105f128244858dd13286215c598a63d7574ca7cca3a9e472d495d0b2e76ba6066f3a9173d204a34135464daf35ab4a679fc945053f33b402ecac3c093dc7196841d88a51e6ac83000c67b0ec2d073e003b54416a9476a5644e4182ac1accd89d05501b16cafa0fa7c0dbff1361e411a9d79c7e6a1d8fbc217303343e8de9e1323c3a2c6da9d390620438fade3fd2743fa75c80409aae4f06e2f05a0d4f9035f09c041be02b2aa2e830adf80feb95dec8efa2448316a75c73f0f96d48203b9cdedbc4967b179d52e7abe96ed866f0787a7aa9ecab23275e740c17f79a0236807235968105f75747a23d92799fb754d52c81f2015dc7b29d7329f6528cce3cac8d1ce92a909168e587edbc2c9211412d1b75c733f5bac6c29284cddc50fd6c95de53d9b6b383a8ae85eff4cb692fc08d5a20fb005440bb4e5db8ec42950352413997a260989d3798f27a2b51b26688a49ffb684af5bd128b11ba74f6f8adbe6c665ce9635c23126c9146b2d48ec42bf2fa3197ddc63be6cad20fa370cb77b8749e0bad47ac5224061af8c8b6fc2c0beb775ee910e1b153a338e15082472e1b66b7a69cecec0da303a2c8ce5acc05f2d9969ede9c0285b0ba3a9e81c9034630e7276f4ee8ae2690254b9fa1cd86bad340516e9878108e93dbddaf8c0a963b9a7b9a191de2875230aff6f148b600cb9c04a96e4c5f41b2c73631f90e1e306c5edf32a11c16130a9bead71a1b17fa85e8caedec28c6d35626b962de39bdd0d20926fb084c0fe349102dbd14306358070fa94235c49f37d81c61148dcfe65f895862d5a11e506d5f64c98fb48a7cb6a84148cd48d8ba69d2a1ea272f5b875dda5f8ce743bc01ce3fd8acca917cd69d391bcaca8eaa3785ec51a49c34bd5941125c2cb3aaa67d9c18f3676dea4a04cd79833fff69b5fe85fe49293ce1d71186efd29b1114bb995289824dc6c33fa110e503474f690652cbed85ca04401bf1793b56b8a6d0d4767931b01d71d4f8f165693cdc39cf48ae34b2a6b390a532242dea12ed934f92055e42a8d95ee8cae282aeb17c107985435dc578768ed4fcdc5bde2f4623705589207ba0cecc7f1845b75f60df7ff4ab825e885aae0e7a2b32ad3c84140aa54d08bbe1285f8835672571f20993e3c7d53cdecee927027e54932890de0490effda166d9577ea81a6a6a16562063a28041b63534e44f80d434537777f848b2e94ed6b42bcfb7e0e3c7224ee084948752a307866b101310de2d7c4d1e7d1d34cf8b624cdd2a0cc1607bb9daeab2b81fad993489473b94da8302c73d9075d83995c33a0e7e0987a3344e6a3fa9f55d5379a02f36b4feee8de6254fa2257e9fc1c8ea639cf9622a8f605d6ae9840379ea33b0e46cc20a0183b9fc998ed673be86cd698df3ef86184049be703ee4dfa2fd1492a7f4b8f6f44bb801fea4eadc80a5cbaddbd482b914a278c5bd9388eb477d20f630bbc04cdd3eadeff340874016ec99cb9d639d9866d3694032a97c15dcbfc7789cfcae87139ddc0f44dfaa736f16fba8d7878bc71c7881abd03a2684ed00ac8883f08e57f2e213b21f2245856e2c0402c4447d86b9f78c70a9cf1ec1038d4443adccef1362e7eda28eac61193ed7653d6d8ee4f78fac5968ef904d017614488f4c003da381cb5dc51e317a1642a0202eaff513532a8fa10f74394b4f472f09e123f11c4310df6d0a5d90d553a6d842c5463216e3523e01f591edceb49952824f8a03434ad6414bac2047dd17764a6d7a5d52e8e42cfe0c5b47e89e81ad3c7b2a352bc075a85afee09d1f0769dfbdee58099019da5518c196fabe103cbbec97814cafcd90dc466137df00010f95ea4e5e3e2007a72743140ff9c480277c0cb131591a8c606d9c624889205f941b998f40ae51efd02f1932c3c504cfcecc1284b0f55d341001fa336394dbb78248e686041e45f80918d40d06a59af386eac2bdc0a941b7795f2c181bfb89deccab4eebd1c0ddb98f63edb79f222c66d41ec518ffd4e4524c2e66f63f9813687546b7d57dadb938b1586f25d52673860dc81e3e43a7ec215d1fcfc4bb469c5be5f8715dbe1a7e2e9fcc07931f7a95f31edb596bb1516c4922d0702162698ed02f510138898223c84ae76ec0adbf163387a13227a168216585f128023c76311cf71cde8d7a6d49a2bf1e0d326137b36c89c5c218baaff794e42147029ecd95abc0acb7089eee48056120f3460ccb91a65cd457340e01b498e8f9827b51e563ec4cdf16c305110b81def99d247a252c98bc0442e57a90031c0fa5bcdbb4811fd7a29ae7569ec6b2f5a34d37f672249deefd0b0ca0c248593d21b2ec5c655a6eea38c6c0c470b2753156490757838a95112c3c1ff2a8327951f180dad55664928194c4d1698f62fcb484fb53e0111b73f4dbf48602a37e89e0610a1ebf1529882e7e2d892606d0e0fc189280fef58b62f77f6459f789a50b215b9609a100d8ad4460433f9957eb350833824a3803cb8b49600fc9ad4866cc53b5a832772d7206e4b2bbfdc3121ef8a9107de51a7b4353eb539db238b50df4fe156bd3a92360fc3e0664dd44821740f5b613855f4dca7e7fdd658fd4916a610874496a8bf08af14ebe564294ad8bc41c0002d2fe323c22d11d4f3cb964841a76ab7b3847720aa70318228e6c18aeb5e5b5875680c7487085c71f2912fca95b3d402d85b982eaf95664fa099a99031873632705fb4535f880310eeac2967f742364c138c8f85762ddb06b2313791b5092af3cb35e2f596e1f83f26cab57cd61fd9c0154e0ce70f56d66ba4e5fd0769ce2c3e172623d608455b8370fd4e5713a92cad44212579045cc65127412b95ba096d0b0a29aba4b76f21b2f6352a5c25acf51bc0526d798902a2a14e143520ca68aa34e89fe95bed8849f60c8c4e528dbe2a2c9e19e9b65fa1f2e5ae35f4f1928e4ab05fc24b64def4a4712e799b34ba7459960f132544694289c5273b2fbac2f466b77883843f822aae0beb2af3295e70300232ff7350bc34de7f3e8fdaf857009a0d0b6952ea79ab757aea7f62c1413334ae4deaba1179b646e0a3b6be5941442953259ffa7e896fe1d7572c6d2dd61bac5b2c238b45460e46caa0dea5362538cff6bf99562240514b10cc7649c2d15dd0425ec4883c4baea4381789d8166350de32aa58067064730897b11808c9bd9c69d55bde7939a56ef56f832d985cc7edf9d243519d386ab864248f29a4ec4d2ebfe398047671e917bd0f8ee27d894d7c436c25d85ec128371c3e6248f0fb138f902ba9853b0f26c6bbd13c6117f544b174ff3c9fd16b226a80e012ddba351ea816172befb25bc78292e5318b29e94a6dfb3031baa9e93a18280a161f25130dea9f8604faf7980b767240fd05a2b015433d06417279b615e4768556ed3ba3caf721a779b12a9f9d87a41b1d28d8075cc5edf75e7ae4771e59cd589a6b48a8f75ac81096ae8e6630c1c3d4fd63ca690a0846d50e7093399e1b083d58f5d36c511a64aa507374fc46d98164e04ae29224529b2478b1557cb3f1e9b03043b5ad9d6392c757cd6945effa9f9102a3f1865c7deaf12c861a817219adbf055710d0ac5311c4c422132b0607680e0151cd54ab164d9708cddb0a886e8e7fb92045876d16f7a2b9547e24693bf7da63d153edb010e1d5669924793be29900f93888872a65df9c3dd38b0f645f6cdef0520c0bd6e3141aff374bf5c455cc413d5611555eace896915431909354b5f387c012652bbbb912bb93218f39824535f508de380eae71c237821d386c63c2dd4c55c979643957eb0f12a1b009de00388009ac3594719515d0c6db498035fa274d482049c226883f536e64747bd31416c69bbceeda4b1c101dd75e3b6e027525d71b1f355ea8b6f3bc23023c26f697d1d2899981a97ad709c72c269efe8c3386bee4d8d2a461158ea2f7864eec83ed8da02f31fa80e2e7805e4743affaf7fa27bd1cde5ef0ac170fef756cdc2b6a473359a0e2514a60de90346e5d5ede0135d492141948053f518c9a3b02d3ee56d7e840c327238fc03c2d673a1c63663217fa6c402ba3f23997dbe042090b095e8b9db8a471b898223b94c1dc5762c95cf0b77b8d1ba533ebf56abf2a52430593975401e7b585b9dc2d1be7d4868efd26b5c235915e778c82499b6b6e72aebd611cef6c59c94c13039ea4c0f216e9361662a2a6cc6bff7b7dd35f1177c543050dde1bddc7c62a8fbe5fc17d33769f55747030b8e49c3f4082ffbca840ddbca0f976c52e2a2d5d58b8d6508ffb830183ddabafbc6cf8c26cb01b45f7b9e2fbaf04763c99de15b740585a7213f9ac10cacfd486324ecd1c8bb21048f59fd5da0cbc223e1cf485f38a340466af848927935b038f6d130d9b1d3cf4ab986be5bef6515097db693591f090cab936079c4066b4b2e6bb4ce179c621aa37ede9c46316a5c385429405b800f3388d6a20c3f740f9bb6df02aacd71871c7c0370add2c0eaca18c6241038b0778d581e254d1901bf038454dae90fec65c2563c26209cfdd380792ec7af365f10cb29f2cfe64e8c802612df717d3ff2403363e19f6bb6954204dea01ff924a223cc89c86ecbe1b8dbdb00c85a2cc02499954f816ea0c62420c31dcba6c0ba34e7ee5c7cc21d42ff667084e73297ea81a6d910ccc9c3fb45aa84f6260360988b25a890acd354429d67c5b1b128b5970bfc530f0f28abca046968352d907733172b8fbe3d24cef739341a012c0ae4569cf038f88d5be4a472d594fe389ecf729ec39608e7293ba377a057737b8c92e88188f24b5ebf530525932baf8bc87842724796218a0c9a94b5a3cebdb9b8b4b51c5b25a28eec36d1ed4b4e88e11ddeda62a40fbb64d48b39ffe4d020da3fd5e1ab6f7e7c98aefd3c2af7b8b82bf70295871081ec5b47566b30b0ca09cc85fbb530e11d35fa7bf57bd70fe5b196a19d5cf0e14148b28ec173eab41d260767d060ff12f6ab05defb9f448b94259c359c18a799409a6ccaa776d7bb1f987fb6889a673a634796646432a30022012e99fe456518cf58f9ebb57a2bf175081f8d62c54900d8f81846dd72a971852b0b70abae78d45da3cc93d688251b85e3f27fed9b93c3431c42f148c7788335378715cdc160da821bcee6ba7413b52079076303d6f00d79dc3b00c16c2e4e63f772728e104f02d4a2ffb73904abce429db60223a3650860436ff43d983584e5657433faab93b83794d0f0b98c5cc11657e45225b0e75d95bc061e2df66487467829242315a461b8e8d6bda7aea248b25d81c9cc958342a3b2f637c8828d7102e1a8a7c11dff60761420ead0b75635a3ea88e39d523bd13a530cee315eb0e1d4aad79d8819f74cfd51fae1850a3e9b36e72713cab388a14e5a8c0f9c551094aaca4b1c97fa79bf0a328b0d255e5ac21f35462e3912fdd475fc0bca7fa4beb6789178437edd0dddf7b3a3cf6edb7e85bf0eb6c8131beba5f413a701ac5152072eec7271056e1543fe396feb10ac5df6d07f672941da0f11280e6213f609fec13ed74334397ee71899d89f0e6a7065ff9adf7bd2f6fecb7acfa7a568c5e3eb6fbce393607fe2d939f2ebf2c1bdefcba13b9cca40080145339c5f10b6c097109ab0200d217bb083918955631872f5b9cf159fb54afb3f3d0ec98a18e5efbe3316d4a5c383d68d646080b0100c45365c7a871eaba2334ff1ff45813af1a836f4ed91c2e718bfb3fa2d4c9995564675b5a775f38f7328b19b76b74947ae5eab93c27b2a0416022699d8afde7b16758605be33ff4edd640fd8c7e16faaa630eb069bee8391595d41929a7b38afe9e15a7173ec63ed6f5937b87314118cf4b0823ae980a6725913b92fd7f906c2286cd8750ef410cb43027e606cc31d8bded83c0b41b70aed4ba7573f5ef220cccd266d482752e0797748081c424a6deeb719cb349cdd38b0f8fc2840602265799428e01f4e632656d885b849357e5c690fd7981d7b687493054aae8593dc303302a9d6b856badc59f244663da817d29264fdbaebd91ede60acaa262d7acabd88ab2c656242d871a700bef61950a6aa033a5085f993328973889b6629471a4e80ba18696b1cb24e2c877334b0e0d18b9005d36aed8629ebb7804d47f8f269fec70b15b29a9f33c5196bc249e7e89d509eb6044235dd87ac950dc630bb813932e94d0f63ad26c80f57d1edaa90c481d57512bfc1f2adf794725fa29034a5709b3eb4cd3bf2ea113256cb20fc50e053046a615c980a2618ad21b3c4beddf4c788c6398d774cf652a801e8a7bc1b8ea3e552ef4d2982ad2c7cb5f9ce45fd52cbb8630287a370c8dcda903c5111b2b4eff90fe57e73a2a63308609edf9a528ad7c723eb1be48ac7140480ceb2e8c918423a17a490f9b0789a8de0ea5b35184eb0faafd2ce934a180ac8d78c0642981fff80d53aa3d3262e210aa91a570a177c39414b10b60e8f9dcafbebb95dca6e01684e9a0da1bbf79c5800ab69845bed6b94a919cf1132e643b6c8772ec4aad3a11e27859b7e862a3758bf62d15611f8484364f4c6795714d46681bdc58169d4bdacfd3803e08255ec6c9648b48e84a6ab1a08669aab9d3ecc09ab2aa0a2997c76353bc04580c35d869e05b1b521d2dd95ccd841f6db41a292807c22e8102bc17ea03f07fc0bed6e810434255f15fbdee6e10686042b805a57ed476f69f07aff6358e53537e2fdab69ad290273049bb511d208309d87a17e20a9f51eb39c22d6b99b884e0f0a8c118e4b8183d547c8bbd562e67c65d69bcef0aa70acf039cfcbf7277fd73a96176034fdf2931f96dc724190ff422cd8c96ffc43d494ff711e7280f685a93c54e4b6980d004b1bffc51686c4527e2417b300e74b20d9b1f7f63cd72cebd085bdebe4d26428a3297b0461a7d5e439172dbb2b325560195ca471f3197355b292277d63c87997125a8e252b9f857b7c95a17c630b39eb0efe9f13e4637dd92a05be945d0ca030b80998fca9615d9a897afee815c9b43b27557dd591a070101a90d6622e88a01bba5891114bb67560f85f1ceac570913281733d6d816eda46b17da2542308031cbccc2bd3739fe3816b54aec917002f72563adb040b8a46724e70a0707cab975ea06d8944c5f15d6e3d1cc4ef5dcb293933f0c96b1a81eec665328e4067a340efbb4384d676af5ae28eee2e644419b67161698eafbcf3b7861ff445e46ed208c86ba04c4318a1d6923611239f2324b0fa7b2541728985616c30b441fe7e780b9ab3a2456a17ec961029e1b6c0f6ea3a837153620cb8aa5e39c671945119f57220f41cc3090819ce991b9d616060c15620d0a1e0d7faf8704aac11d374ea77ef442a038502383d00135a05965e408de227c8769e1af62e5b8091ccbd4b4fb20fbc1692c94142e593e26269178c178a872b6900f33aa67919e877ffdc1a8ca8c107d61d4f5bfa12b42837cc3c49e81daf340191622895f37f168e1a5c59839868bfc2fad58b96ca4c8f5c83ec5c81439c35f5cb55520928caace7ab4651f1e1106f5524c330effd10e58cbc213ca6f4ce5442bd5e78916124a720578f576253ac0d744e49fb90ebe5d383323cdea8260965df13b425869ab63eccb150725047b16108a714c38727f665cf209d7df0ce22ec24cbbce342cfab8bf26eb7f9c03e96f64aaa6ed3d074887b99a052e5369e5e4eead605d5098589172f12ac1977b0b7ba89fb9cde5c07f17f75695a930b46d76456846060a312e42790f445280f853c8899662d833530207e62bccc497a89706d07b2873c02d308f2a18e311c8c073a2b9f4ee9c649f3c193d81bdccc9b65522e1fe4b98eb6a80b24d6c0ef6124b57c3fbf3aee284492284b4d7110ad46d50f23c6d26350e02b5c58e3c7ef57b23c33a49bd2a76e4006c748551cf96f11219b13c9b55ac82b5be1a362f8fc174bba5132332dc3abec321752829bb678f4a52b2bedd2b386cab6b4bcb83dec907e88413a6488e0bd8b3693d6ce2b6ae386d3dbe09f0db59e744c3aa19bec7479159ddaba75be255a5e8e38da1fcbd8be65fbb393627877d7e382a54be6266f11adbe93bd06a68a8ef33577a3ccac0f2a6a45aced9614b684ed955c2d2188cde2d851905af9e9126dfbd026e5e8925f2480cf36a528f940f42297fe4416368fbe09ca8f83473dd5f724b1d804074cf17a2bce96edc0acc4de717d81cd45a2b7f2de5e65101c32d8f66b13193319e6e90567e4122248da0f1a41f16c16494f63f3d9437a14b2700749b6371d0f31b4eec4200fe6b72caf198ee396fde0e1cd5ca5ea220a2c9a1ac9d77a52402c60bec5601d4ccb1b7a2cb4046f29a7c4876ff5c21cf48443389971d4de74df949f50bf871d2080609d61761966024c99b31c38cdba31d51943180e80fe64ec151dd9174108053716285617a1a090bb3cb1049c4752ecf319072e805b18ae2a44986d36d0de5329808f4e187e25f2715b7fe6165866ca5000480057ba51863c02003d10d58b564c6e1158b68228b225eed16fc15173ea94a250af41c5e11c26848d8d63068775c08ba15d5161e10f4bc2801294e57100b90300dc913d5ff7ecbe6754b606925dfa0bfffe901efe0b771dde3968a54a73931a0ea1ad2203aa6c23d20cf5a2e7cec2d971b7a9fa815ddb220194f4d80240032d676605c00aa68656b09760742c1d0d5ee07dba50c68798955beb4f823e69586503ff9e865af03e536e28605509f006eb0c5d0c820ba204614a113ffdc6da2b41488a1ada1b266c4728ea6c917b3861f7cd6c795a6a2efbd0e607ba2a648d437205d116a48fed9c75ff9c140150aa9530c9860f54493d40f83a809d4a9a124822029408be1e0349992905ee4064b2dbbfbd534aa4c3b1620ebf73f0449fd0d725d8a1450afcc11912f100af89b826c039cef7df1d0b8798f9858b16fa78a91902442898985b69928b05b209424fb7b391113ea9473b72ced6cec5f6ba12375730f11cefb9220b654f4b303e48d07e6b38894d8264fceff5a0c70fb6cfa83e2e00e341a1dda23f86a5f117ab85e7c417bfc111ee4a69b93250dde0075195a4876519f18ec815940e5048a9f16e11cfba918b41326c5ab1172924a41bfe6c4889ff4c549be8bf83945ec5e003724483d05e0ea4bd7921c0a5213a5d1add62c9bd2135bd695aaf191b1c19bc7179be29e6ab4939845a9d8203a4890c42c97d1131c2b182ee775cfbcbf5b3ecb9f842d4e816ff1b938511e74e8e00295c5368484270c32963bed8e9b63198c83bf750fc30129c4ec7454afb809021dd9da6567e41c78c383d3bc1b249813d997658a51760e6a7c84cfbee03e948c87367bb2664320ab3fb265159a03d66041f68f6835d016f2d86a255022763b79b8c97a0008984ce7c52049c8d1ff10aebe950716350d1f68f62e458c0f7dc7b2429db947c27b34f0dbab599ba2d8d5254e131a060041589f01fabcbf0f81686fd178a7c652fa2af9ef661648d588bea0ad17fe9a6a89eddd9d92fc4c673841b0be6979920d9f3e5d2af4ac83be2a1001f3737eeb0b6999454ef1be4e9ff7a4e1cc3828fccff79d6a212967352773ae69a98e17f25d6ff2850a6c49835f41ee732bca501b5327b47a9f7d8ef555f15ab9773ac5904181c26050f7e5eab9505292be22e99fc048503179d22a0d8e839ac79898847d244f777c4cf8ab87a35bdd37ee0e93a4425a94e713a84efdffac8ba721ca98ae7c0d6388a3cc6dd4e4aeae6f098006ea774bf09e407aab68822bcb76ea003d7a2fb72a4070c69ad99af33d115839b00ad7ded0be78d60271bd1420f00b875ce9112da9f676a9a794e31125f14ebd469b0e306c3c4301ce2a16e9a4406cabd71104eae05a2d4db34e1016f91261a441c10f0213aa75a65bc00ece6e00715af7dc097f05c5ca074f128db73ee101bfc657beddddfaa3714c8dc114ed59838a33a479507b044dc5bb7b1f0b41e30de7fd2988cf4fa15a7b3a8c5957cfe9bfbb3f62c298766a215b14b1f9ab4a0d6b835e7ca6b51ef0bc176b0ddcd93ca652ea4676a6c3cd47c2a187dc1469dd32952c2ce3d9850049e8325536a9665d6943fc5c1df21f8f898e37f6ca15e8276c74fa401bda0c8f2201560ce0be7804a129d9f2b463de42565aecaf4b03df9bf6f46627869f405422ed5e1323e4e0b07ae24012fdebd28962ccdbbfdf9c80a9c12360a03be5703b2fca7c5a3a14e6a17adeb3eef0f51a8826ea2199d100678f1124fbd44e18e4276a4db13963f207620609cd73bb42b80809f083d912104770c1ad99ab33f0dfd0488bb2acd0c3a88d940df9e6d067d1d2335ee9ffed5065fb2f1a2de17f8bd1c85bc4b75a4afe6ef13cc8d73d399ab26dfb66a2c56f961bee17044b1703ecb1ac0cbbc6b695dec02dee084d4e92c87ccc1fd04efb52c0e3644afc23fff1d797ee6d0ef978c7db42ff72feca0288a521479e6da98ea6cc6790fcf2744627457bf5bf530b4b46705713590e24d65def1fb514c1e9d76f7c24c430da8ed52882749d2292607b0109756fd4767da7a7f19f1a285ed1b53d386f0bf643d8c2569644c79daa6562426bee82d121412665e6337f823920870de81f0df8812d5133fa4e043931fb1715ada49e672ce6a505837e735c16ce44add7a937075cf87b9c2c28732b915eb27396083e30b979d106c56464ae9a833c384d6c1f8b1dcf9e27d67ed66a2f62ff17c7badbcff6803cdbda11632cb6f5cacc5a5bce322e2b822a0fbc168fb78a3c7936d5efc0e2e719979e01d9556b683bdfc9bcd978e2bf72c0305ef39c3d155d8bfe26a27558e3fb47113dd50b016f00ca3fa2c78f6d9257f7c145310baa3d42681cb694815c19b851ed0e648380697a29614e8dd90b49ae7b2511474c92734f57e59538f6520666abcd702a4fa6ca059f0f835ab7daaf2d76f92e8d8663a69c91bb73ea45d54b88d975095a0d2e4d591033c46e3ef8625b8065c4671dfac5a3c205e0f7da6688614c5c475b3947f1de12cddfac9f67199c1d26d85ebc454323235de11700b9415a77155aea90ef27cb78822922982c35ba6fa1a12a9df704bd7caf0f782d3623bcd333e4cae6c1b3618a2d60790ec81ccb24704ccdc021f05b55dd4ad2fe6c84fa9b95b6dacb59e05066384a20d909f68295033bbbd1269295c7e5777080d4b625d0d107489fdce25870e4eba09b46a2f0064787007f6980d8aef001153ea59f5f6bcfe71914849e5566abcc2bdab499525d886f14a97c4a2cf7bc88353dde20b63fea0835e1812a9f8fbbf842d2a0270797e0d03c37fc199844611c4c28fc85349bdc56d5dfaa006bc4243f1719c4d7af630b08a4a8f66a13190b45e044c1ccd3202c9146c259973c8c8acaca5d6d1992cd3386f6ab5cba673c48d6b2184c156958df2033b5997adca95079c9bd5c736320f8975aad4232f4c092c0068d7987a2e5ec92c48307a1f1b8b48634b7dbd84729b7f728a1da9cc802a72d2458bc944668f2088c3e8929894becbbf34307f30077671d1abbc516f581f93c8c09fa46b4f63477959c24fd3246e39513a2882984fe5655783a80694415a5c0d99e5e9d3bb58fb680921623ad97f442d3bc3c6958075b11d93e4c6a05d7da35a135c32048b8343e807c7a9f97c164f44ed251d0f639355345c2ca1b48028522a9237ecc371a4d927de6bf249d395b7671e277f86612766600c8d0b18ea2d095f7b63a685fad81bac8eadd95508e3bc804088a79dd4ada2aa40e20d2986703f1982be9b2b74d0bce93080e3580d553a3b21a943e0bcf6e105a687eeb39e7494a15eb8617444847754693c863124f82fad47be96305995f46b6b17629fe80330c01e339fc4613dd44dcb5541a517f1503dc68888d84b5daf0d37c4625337c1391f8405476588254ee705e00162570ea3e7839bbc271bb6e6eab828a84cc26ad7e7932d5954462458bc6a65e3819546b14e8a87282907b5be0d33508e00d1071cc25e96f800189d06b52a43e192dd5277061fd1958ebe138d98c3cb13e52c5e025593cd432d1acb8cb89088acf04ef604e2245676feab6f21a1612c73fb7edebc8d6333fed6a2fd2b7d28a84b61413022c36e49378b335d32e310f8e4aa8414165fe2a5aa945785a4b642adf61a3759a6fac6cc5575285a0851cc14bea24eb98cf2e75ba3692084a82fe496aa97aceb258510c0c7f1538768521751226a340086ce5de751f8751976626741238192a6867ff010267225ac1e9c482255fb5d640c1c3afb197965a3d4ffb5d45e3da00cab44a0c65435ff5f63482ba9805ad12e348ac0ad8942d3262e08da0a30100fb96d8660021b7bc4b62d357926c7fe4843de48959192405db05f02e1f61d31b0b1a51b5a984cbd6cdcf1b827c6957b722ec496aa0cc02e047bcb4061c678f2893ba331c8d514ee89359afb21c88d95b245b0b1201e7273fed83a11f4eb2bce54c3496e1523931f359c88340fe1e9ad5956b071e3b9bd0295cbcd8ffbcf6367cfe85397a97253ddc789d77cb05c2143954620cd74f38e95067fe624c4c155e37381b68169ef9603264a287613b4e93f8f29e4e5068ebf5c6980d9a849e53c6290b8fa789e0e5664a8ac3bf505781a0a8584ef9c54520def2564accaa72ad91666463497add7b3b61a7db531df0bc990b8011b0474032eb0efa6cda8589dda28c366d57cc450b6607ff468aa6ba5b4eb40c9c54ee210cfab83a0536720b609537d9a4e0b158b395975af327cfa6991f5dc13972a67d7a53595aed8a12753ebd3fd906f79c782ca802009ec87a754c7a6469907ee496fa96489c2d0ad40c01231e63ead6d3647db0a66aa988c167b3704af18a31a78f27b4f0fff62fcc9ffaf39c77a2c46555f8ec7b048b9bacd0b3fe4c63481c8dac386613b8ccffa084c4214a588d2235fecaeb7fcd904b23794cf7448b600a08913c39809da376898b8e75d2aea81a8be55b1fc9c8cbbd577a9d43ce31680b58574279ac052a98e8fd381a8792c6541d44d14cb4047c2ee79434e1aef64ed72fe238bebf91e5ecac3e2236f6e12b417d0574c64cdd4edb44451ab34bebefa2b13451d86d414f291f0218c983fed7194728f013387f25578684eeb08515aba92131955d615547ca29b2f78e0ca8b0c8c591be1f4d6c11092a57bf5c1cc98512a4266181cb6ccc6407a94f82700b54da2bf49ba19ebd71f886010a097790fc162dfc4897120c7589d4d81c72ada2bfe879a1659f8389ca3a8e9c18957e688ea3b1e4888402ce51741cd70cb34769be989a20119975379d4d1a983a29159ae987a498793502a822ea08e18b0a90729a71f9567001643d10ed3afd5f76f3c69af51f06f0c96b4a744cf46330f291484bb9205e90c0f78b778b5cc0b32ffc6a541d2381d95ba64c8f6adbd80449d851c42607fdfe8e0b37a38c64dfa5f74a759898ded7e141472a80b1e7089e9eb00a2225876dff2274e5a1465cd0967e184c5e56039f533299b4d1509fba96e1f2d939473e761cfca7e1630761fae09b83135843c49dbbef84ba679cf06150fe6e0ca4e853b2bb75ec5f51503d9eee46ed0e8d8cf6b472dbb9034b5e80c627dcaea2b40f404a6db7b8859e170c7856dcb972548c4f74fe8da13e0f6ce30be557aea1ce210788ea6d465f56d6d15bc79dcb4b6231cf8b05de9a6b9e21bbbb4128137ca3317efd92e3403b8988a92940b38eec3116e8d5b0865beeeebbe45709451c4b103b3d2414e17d1c50b3937521a1c871b38b805a7b1d43d95b67001d91127534ece3da48138a8853cae25188d6c08bfb70184bccdc9c44deb9917dc85b7834c431facaff1dad14124e23afc7e6bb4ca81182ad935ff3e926b69aed8dfc9a0fcecf551b6836e1cd7d1cc8eb4e35b28083d390b79364ddc8109da21cf44656120fba81dcaa54a8f7d4494b77856661ca33cd684f2669ac8cd5d7349271e1a88c552e4d589f53a6530035be24a27393433ac4b552be9bc9fc0d6f129d9c6d83317b76247fbd22d7a386dac8662c0d42383572c0210a82e70f659a2e5870a10881a5ac40fc7c6b017738609feaa1ca242aa418e3924b9a2874b5cc94144568bed8281fc1d3e876002679cc5dae2ba923b30ee5ac0925d380c1cfb071a7f642a60915ef3a65410362740265995ec35b563f86b94cb7fcdaca63124542f71a7ea77708fdab08cb1ea1c2691e65f95e2c1807ecdaa6337ebab204ee01da1b340e3807149b987f5edb441e4f8137b98c706fe7436c2bf2ce384e36cdf8f8c7927fc1e9b3693f6723b532cd309832f95faaae99f3f86bba1ee044411ff21f59f39e896911293d18915acbac0d6e90e4dc39970759c42049e1ec97ccb27ff3981a74a5332632ca2af3b6c3340c8d4902be5252292aa5e5c54bd3d4477e7ce64c3dac1b9621c6bea5fb449ff8f4ce39c8176b8f83e0472422c8abae10afba4969821e339ec085faea29c91a8cc591959ac11151ed8ec248ddc018d1e0ad5a2daea4b61308a7982bd8d0b4ac0116c382ea599f0ad9b145ec64fd0f0cd5c9166057539dc176b48d1446a3ea725e990d5440aec4426c0f8d994c7dbff3f40dc9795a201fc2c576f1b07073a56367e5baa1b02f07d962a8188aafbe10e170f67f281752245cb9b545b1123a1b9418028936109d6711901a2848d91e6e6735067ddebb2a961822ea2c84a97e84778b76425aa509f2459c5672b030458ebdc5f6ce3a58436c5721d37722744b05cf2f088eaa581dbe35508101089e03a0589f91dcf1d4c055f3d81e6987bc01cf2406773acc0c0c429b0b1a1d678e896512c360a9119126defcbc3f9a8b91873258197d298904be4f76ad4357d0d0f9dd6ac115b4cdf620da192740286d90e96f7ce808f172277d1393a374131b7c57b239dd3e31c9baf4abc79970eb4c351711adedaf3f54a0d883dc704560fefaed97c27dc567bef8066c5fe22ff26d96658f2e53619c59e3798b2a1ae7f961104a394a2731fd0e7da7d413abd99c1be17b9b85fe17047b1636e6d8eabdf094cba95d903298b369abafa870bc4e8859eff712cea9933299bbb8bc85103108983bf8f0b12e881eb3f527f4f55f81751c2bb380c1642be1164f72b31fada3a95cb6cd06cc488cb41ca3889b5974a39c7e8c245609ebd1b32b04c682b839e2aea4bb7ff44b9c8de3d6dab8582b45004cec9dc174977e21c1da676bc594aa2ef6978e342c4969e197710464bd1e889752a6afec281325a7d1ca557779577c7bc10f1374269cb720bc5325d93f9c758f56f7174d3ed24a824fe87783bd58d868e7ffa59e5f0797f12feb8eb0ac4f352a08575924f920a5ea4994cacb72107a9f5e18e1067d78336538aaf138c0329c0684f44ed25af8bbae7db712829441b4c8c86c69bade07b1e9f229d941b7cb6d01f7a218775ed8cc67cb1064f03cb630976c9c5a155a60f09b1af3f9cd519bda7022e2a9eaad60591c020c165d0e99b82948737ca2bb58c65b06e52687db002aacf2fed9f3b26b7b0510dd13e43f948c37a62b1145e84a687c20bf1f029693eac704fd42dda7c2e3ce3dbb4d6f7494020cd99b20cb63ff21137db20f89a228245b388fd3f7eb8ddfb57ee46d566fad8f2678056e924d767290189c56f1b03305a2053a2b51652fc35830d98df9e1195db348654bebac0f2ae72782a8b1f351be2d7b66115954a0ba12a1bcba75fca0879d58b70a912e56057a10503dcd792279fc3b75ddc04c796f429cb4f3a6183edf7ca3caf44542465c55667c4086231aa04c52b8373c0315146dc4c0af57bc4ab28579bcc81b19e7632a163825cbdbd98bce9fff4fd5f4c7819c2fc5e41c1768ba40f026321a4516305b0efb0672016b0791bb270aa69a0734d2af54ab2fa034d7a368dc3cc101b1fee36bb56d4f4f2f7c876ca45b4df5638b7decc6b70a22ade82180d00e9d104a6b516b2b2c5c02481ec23c04e4fdb691a28025d596475d20d6a0e3d6e16f0510c945feff330891927ad521c4d38c8ff0a5e78cc1d5331f526ec7ed5593a5f928e788d2cf8a44b06f02edb73e5e781d2df8b01e6491abf38f1bfc729741ba5144c9676144055ecf3f7c3eca699c76661a166483c6604acb692c99c09ecc1b2f71915e2941adde1e0fb44e08dc6ff6fdaa20bbd3364617b805ace61c8ba9d2c770d0f313d1d45807e6764a23a2554f2b11ff2d4c4aa6dc96982bceed283d321d5718aafe5be69bebf225561e3e7c691dad9ac830f6fc4433efe059056e45b20d6f1573e48e476823b05ca87a0e0958b0d5d23b0352e4d4c758ee10435eedc67ee576cfe8602d946f240c08f455040ac7efc3592052a34a63dae9ca47060d8ca811785eb526cefe0ce51311c185fe91f289564eac413aef36511d7140143308f06c800154aa4bb491a8ba9e55f8ee7cb42a1aac4450bb70f143f9a5a6050bf5372209d97b932db794524a2903870c110c120c39b4ec0fe1b05d7bc6f5e4b0b7d75ab7161ceeb71f326c99ddb5bae2a05d0ec10445298c1fb01186d2d0de620b4eb6760d73b18361c71b72225e0ddfa20b391e399963934080cc8fda1e649c17ac0632bffa1a2e3b06c80fb9dc39ecc51521cbbdc59aae0b72ba3d0d5e8c86c32e831793e13bdf389bbaed725edf24d7c26397e392e3e6aa7054b6793a2373b7431c9559657e77e83ab9cd115110dbdee62ea801950db3a30bce08da6c3899b22dc7f94c57ea673b7533683b75cebb4f795a97b3c1de03ee782cd8ce6ff80d3ab6f31e70931cd724d3146f0eb06b1e405f37d05704361fd4c868f595d21cf3a355eed0fc8ec8b7e83a99df0725734c94462b916377821c39e4983826fa8ac0371fb7b1397d043c8d24db3cf515be6d5dce0a309d027a1620b38227b7d605b1b7d1ac20f636b7d138c868ee2748c683dd323f0af35830d823f008e8d8f6469311087b0f18b3831819dce5d8e8d55459964dea1d93b5b1b13f34281e3589b2e93b20fa8a4a46311e1189b1e596db0890be4362a873426f93b21cd374857768b3315dd4c9a69f7788beb8a11b6ea81b62c36f78ec7688fc0197dd4e037ec365b7c3803f407337781c144a43bf492ae50d9b1be2e8c83c3bb7e13cb013391ddaf4dc12fae280e865f7c2dc1c0a4be490e38036e7b3e94bfaa43ccee79eb53364c8236883c7daa9a18647703b6db1b39afb999fb59aa35244b6d65ed2cd5dc6146a6c05fba98154ac9947b6fd0a41681d327edc391f0e86ba57487da39cf53a30772a5294cd6d7406e84ee9186bb8e3cc9fe95a41873d9ccf7471db89e37ce8b99f8ee30ef322b8c999bacf74b1707aeec7c6c5bb431e2b5fee7cce63657d9d6cab6f911c99b3d11c95f96d55b20f1d535e8d3556c7f9bde8b0eed7b715ae7aa1dcf12208f32268e7d7820eb9ddfde5857577df86ccc7745e838e1139ec43bc9dc76e473e36c377746ce73e1038cfce25ccf381c079887cde7642220881c76e06ed75939d9079221fe2c9d7e07de75d063620b7bd2ac57129eee31ebbd4e374ad18cd8f0ac940aec949def19bdf21fa829dc2b40e2a499e3be49ab8a67813374765ba3a1de6d0b251cf66d05c981fadef66386ddcc166386b47d270f908e20ea673d6ce3cec30cd23030eddf12248e4c60bf1de2b2fec86363d04bc9804857cd34e1c0d5e0465f022383bab81d4af783562407b3dcbef2d07a6ed5ed0be725453cbe96bcb3b24884c1982840c5394cc8f2ab1a12ba30625d31596315d55a782981f0db26109912ea9866ec8eba9100d4ba62b14922169ba42a19d5f9d0242294d5728047bd5a920ae0986d37354809c9eabf2e3f4dc1c2ff8b4f0c302908f206e4edf3199ae9084ab70fa8e89e90a4738014ec3d6534c9c4c5798c2534ccc8f16e53c71014a02a280a7ef8c56387d27c5e6f41dd2ebf49d18ddd27485351fc0e93b35a62b14c0799cbe6342e1f41d1b34a7ef9af6e93b2a38a7efaa20e0f4dd1c07f049fda080ba20b8d313fe9d02e001189a7162c2e98ed3a39e4c57e872fa727a5494e90a57a7ae6fa706b83dedf17b5a00d4d274851e4a8de90a4b40314d57c842b11113aba0034e8f6a6a69b90faf050afce5ad2081775e2a02bfdee619c91e701626408485a7406485ab40c4070c44801049b1a04320f74144052229bc2640e4379e916c0b5180051b5638016c68b57ee8d0c75978e1a665830dadff10f9d0210132203a7ce12d6d04aba0c31626a20201ee83880f1f3a6ce137447cdcfc87e8051d0a11b90a36b4883c051b5a29fc8788003af4f11f2de8f0e62f9c8509acf0970d36bc5ab081051b5a60e13f442be850c886bf2660c3045420400b87818503b94d912134a1cd07a08de0213f4439435c18925a61888d0e73fe1a42e342aac8906709d8d4a07f88c2019c873682c3d45140e1751b30f3380ada48ce35fc87e8a5c3013c6b23d92b27e028682338478728e021e000fe1af27ae97085e721affc1fa204e85068c8c11a5018721a6d24a340f37a0256d0613e789b223c743880bb5043ea9d36826be0d1ad50834d0d2bd8fc8768003a14aae13c8aa46a785764003c56788ecd5d38cabb32e81fa23086d0847fda089621f51fa2cde1e8f0a2ba4f06137418e4296d24cb60020e0a029d0ce72280a241ff10853b0c00fe10a0c3ee286d843b00f7692339003afc3e1380ff10753a3c4016c367b4111c4487335806041ce09d0c5da7c3d439193aee3f4431e850488623808619196e823692674cf80fd10174d81d01291d723fc05110d8c7a1e1c334e06c4fd180a22185fa0fd1d6a1100dc781c047c30300812f00ff21da7498fad621ea38b737c062b4118c63d0f6c2b6ab00ad8d64d80262d8b491ecc25e3d23d9167a80ddd13f446190f097d146b096b1ab5af575a82fa38de49d5f1dbe640af80a16f305682318b67af985dd5b61b7fe8748013a14825d662706f6d58e4ccc7f885e7478ff52bfbad546b22d74834b10bc857634de8961c75d76361dbadc6a23dcd6487e88b61fa2203a14da790c37681d0a011ddcf9b591bc85800edea091fc10e9ff8768870eb7ef70d1a1bdcb71280c407ebc90e34202c08d838003b4e0b9ce826780fbf07afcc62bc057f05cb7f10cf097d7e3d92bc0539eeb28cf00efbc1ee7bc027cf35c1a55c5001a35c7fc74caa7003a6583b773221eec35783b1fe2c14e83b7a3533278309d52c123e104f04678cb633d050fe603f06a78780290a0038e82c73a8d07f3cf3b21001e0026e880cf78ac9be0c15c7bdebd1262147480fe212241a796cc8f8ea05348cc8f5ec6636921d8633c182d047410a6532dde69afbc6bc60e6050d92f5e1606500da6d82e1e3562072420ec1dde4dc245930e5a34aa89c573216e202a2f03ddb77acffd98bb7bd521c680e4800e9bc6eeaedff538b4eab0b56c6bc771a18e7b207157da059175a09aa60b55e59e6ea74ffd4c1777fa14502a8854d074a54e9f52925a425f114c31d95c1b917b237e71c422c46e87d82189dd0ff1a3cf5e0782f8d126a6316ea03473b525f20c1e5785d2d0eb789d10af036280d72da134f40df03a265dd1fc1ae0551f1f90015e04c3288d201f508837411d2f82337817044cb82696cf1de29ab61dc79832c70e2f141e5f500ebf4d6fd11d9a1fbd4e64f02218f3461c038da65d7bbcc55241fe0eb9a64d3f061a4f76d561e7c302d76433824b4f90f942161ba5dc1206d8a27d2cea00098cb57610471168354bbe7ec0a8088c4924557ca1041ec92800c1184d13a0d54452c6b045fa8ab9e5d26402a095237247841d4c7246459503365c56902d0f56964883064928bd5091e41247c63b1e2581d4032b69bdf4d24deb2fbef44e2ece8499ad3e64640ab3b5e56a87b86e7aea72ac662fe564ec969f91c9f6acd1a2eab7457b7ab26d71bac2f9bce79c7335a79e13cb6c5e6a6bb574cee97d639c73a439c6d58ed4beeaa596f411539af8ea6539e7ac73a26ee04d5a25a6f5d5ee3a6b2837bbc3cbd4b3a80e4af865d58dad4a3a677745940e8b2c1f723b464a07a54eaed5e25a2a287542a9936bb5b8960a5beba04d68b5b662612b9dc2de26376b92615bb1b0d54e816d9563b3d6059cacb684be2fc374e633caacbe5612a7b4c43403c46e203159642feb843a294ef6e2acc93eb1aab8aaf64cda5b2a4e5796edf888e5331a5bbe455e66bae8eb726ef9968d115aec301af94849da724a0f2062b083219440630b16d0263b8c4c4c76101522c050fa84124806c9252590c17652a43d9450a26c19bbd8810c1bbc21842796d0823eb143897404133b94493f524ed9524a2679d9445f2c5fe040a9088d2b7a70833ab14359e50820489f9f2d653883b69c4bb64462cb4f26f2319c434908118300c3f964cb28f447ca87538c2d393276d8b25370ec54173bb503d04e21a1c54e1dd5e5a450efba1c546dc1ee8e18daddb92ea7e3be75395cdd96f6f65397b3695dce4997808aad1d77399a0a3533628c50dbf751c6576dc10f3c18818f0f7855bb4e578cc19235b67d7dd5e348bb9c1aa5ec4a8f9618b12909a46ceaa23d24ed3965d24ec94d4926c193d6bdda85e99236f4d58384174b548e7e40c6133b002f1ddad70629d81a8f2dcfe35108fb00bb0649294b55a68f8f8f4f121c6d66a1882b76a50142fecc7754c4927d2f0bfb3edefb7cd318c2be2000af920faeb86d9d2e9a5d83b0eb2a538fc324c821ce54905b9936022158ea1a48778ee0042e93561cf19249137776269326ee10e7115c91d7681a81173f7e50340232647ef88069ae92303af120001e66a6f15819226a31e3270a951f2e569afcc000889fa5244ab079b47a785249b0b1e6efe3d4ac9d49e5e88c17d401d2efd8d7efd05f1de349128589221f90be6a1e22d8a4727446920f48356b5acd9a5ac73ecaafe5c5246509244f9822bf6f4e99064b939ced78a4648b1d3e4ad6763c224249cb0fb2ddf1480914254522302a23524a29b691c618a33743395f40e5035f39114c45c412823acb61a8b3a0a0c0504b3485a2d243948929a44b38cd4304ebce0df1749a05cba9739ab5939f7ad63122960e77064490d33bb74a113e482209241f1f9022511afa18d004bb1fe19ed2aced28cdd2491df5088614caa6efd146a6345489d250fa1e6fe408d22849aa18630c353acd73c467fba6593adcb777470108f98280c9a63ba44c7788d2d0a3bc5b4469e859442cdda11a64b1c3dbb4299de32ed12ada1239a455367de755ce434adaf428b8917d6a100fa41c41b06b229a41165a04f9f880118c60587db2969e3a5d88e69c53ca39e79c72ce2f64cd1e75d8d272ea38f3a4618c57ab5af1950ae8d9566ba0ee25b6cd815a6b95b156b963144196e78935b1585384494709a7356daa9552ea30bff8fca29fafb54eefc89c19508cb1d66a6b7d0844bc3db5d1fbfc6296d57a6f5edde3f8d2bc3855b0c548638c3ab416676a5e2bd26cb3365545ac345315b0e0849625f9ee78b484156864d4908b144c82586204494b80e02703ad24b120458212d215d429c961dd335e460439c43922a952cf5be4224ae5a534b6e96c5a9cdebe63bdaa05b02aac56bbd2d41935567babdd191713af529271cb068525aa2572580380067dc98739d3ad7557323e3899c27ca8fddb31cf6c5f8fd3bcbb92a295ca5c5b338f66ded46e3d214d6f199709594f08eb150138e923446154d813e38d005a4a5fd2915636f4d3b8dc72bad7ab736ba72f2bb592bebcd2628d4b97535b3a05f4ecebc97dd230cd108aa629e68cd4e75991b9137214dc6966db3639abbd274fd3b4a8a1c29e5d594c403a129d2bca43531daeba9cfa22a596a7b5ca6dc7a79410440eab4b094ca80fbc9060021939c42b560f60646258ac18a4950e725865b8158cb0fabfafd5b2b18924ac4102ce79b5fabf2f9e3341092e55b494ef58c271e4107b5c955465b3fc0e6fcf11b67c48b373bc917b3e55460e2b4b2e2387d5042ec69b952de3c34ce746e566cb27d39ab1e161d423cf208735001c9698be726c92e79d3545f393fb624e78264f9ae7963fd19598f97dad968dcd33aba960e4fde52ad2448931e52a5735a38ce7b765b7936748b9748bd828a5b4de4929cd42d639e78cb5524aafad73ce796dcd26a514c79a38e79c73ca39e99c73ce39796473d239e7d4e19c7386dc9cf345c976d2b693f67b6b566dbdb6ab029fb478d2a2adb7765784f9de7b354c2dbd9452ca5d31717705c622534aa9ad2e7b4a676282b8b65a7b0e5839a3a434d52464c9ed6d9aadba27f86bd91c739a0a466ad4564a5fa9b7edbfd6ea9eb85389ebbdaf77db8d9b188ccc7539f576d36f14756d364f49e8a528da714d3aee0474c31025264c9830c937ab28d7843b4541b52658b5622d6e72ef856185d2dc84a585b6719bb050da429be036585a5caeb6e113c59b76ab772f8d8c8ca43c5549519035d9915340ab76da50a9959755dd4e43dba905881b58ba214a4c983061a2ca2b312baa18c3aaa7a1532eaaa9a18e43b164d2c8f2dcd049db3699982e67b58d4082fc22d7b764adcba9d2c80d122e7f617654b56a17d1c8f2131bc5f81849242d04da5009272d17a12eed295dd5de0c6b432d2836996402d3e93c89e4e5e890f0c30d4394983061c2244529a59716017ad09e3baf628f560b87d2cce3ce060a05cc0f88cfcd513ebe8ad0532a6ff77db3d24db55ad13967e6f7ce49963468b3c8a42d3b9ab48dc2c8f2f393a767d9e10a63669c37dbe33f1ead93a441f338cb20a3d3e7c948bb78d3f34a23294ab2ae73d282afcdea924a490a895150c52231650824a0bd8eb5d65e69060a90b0d65a0b0024bab8a20a1b2c514114501891553bc6ae635c6badb5d65a6badb5f6deba7282284a2718a226c7fa404ed905d8d65a6badb5918e2648daf8400c88c00515d0126d5b031c6c6badb59609945d53701a0137c4a2c9c1b469c182e7083a8d913322246936c0b7084cb0123b580952a24a07431c4c4c909c60906388c91029188800c4c4042a284ca2d0609843e9598d1d497ea02223b3ec78f4e3460990209123d71d8f908c800a238640c2640588bced7884440866c72320137491fa316b3cd5146766def558f572d7b3aa6e6121913f1f62231c38e184500f28903003a8470f29847a40e104126600f5e82185192d49fb7e8b5bb6c45e7b56cf82d1af7c45c7a8514cf6e00a140c01c68ea842a00370e547301d207d0f583d16ac561d8b31e8028c1d9148e08a8e1db120254abd07e48672289b26877a54592fcebc751c956d44d9146fec65934a37713159c60c42f005183bc2c9810270e54726157580f4d58bf5f8016347e4137045131d995d805413a526672d376746717606eeacf9b83b2fdcce9a3a03f39dc621e4be4def47dc59f5e9793de0e8bcb04897bdf338603747e340da5dfd4169cf1dc364d4d4e99026d5eeacfb981ddc967b1f5ff431d2a3f8a29a529934f757c74913d239c2d857ff9051ab8ec91a1401083d80b1232b239002d21f21610ab07ee53d20ab45c7a2176280b1239209481feb61829528759a340d70cfe251244a73bfe251a3a11c7e734f3da4464d4dcf9d359a06b8f7e2eff785b2b3a66d449afbab19d117eca658738f3339a25cff2de3ea0ebf237dc5640ba688a3098c1de9886803a43f328fce006b4c004e80b1233208a49a48fec8fc01ab264a3d5c5d2bc9216da2b234bfcba4e9f7435ebacf4d4d6d441ac3fac3be75877defa911cd3ac41645e7b867698a37ae7d4f9be2cdddf794ca745599aeed281dae94581de620c2fa3303eaac20a9eda9c72dbb1950e73e531e459ab469df9bca997a85f22895f9dd771ead527fbc1a34bf7bda34bf4be7a8d8ab41ccef569ff9ddec52a4fb8f4a4b123761923861468f96136648b14550c564dbac65468b6c59989fbd2c41b6e80be39cbf574264fb1be62b46165a04883775bbfd8a4a6423aa11cb88625cbd5dbd61bce999e95ac03dbe8c0cc6186b322bed61cbb65c0433fde9dbcc0ff3beab7defbdca93992eaa17703ae5fe7ddbe67d333bc8dbb167b9eb61dca1eca643ecd91d1609bf25f5b20c20a08e3aeae0b6ca454dcbfca0c775afa62bbbbdcc7cb930b5f82240a4b1ad58636f6570ae2ae80359b544a5647ef3a12a88c9696e5138e184134e0001cd843469dbfb45d624ddd9bf77ea65956e875e3685bf176fe6185b03736b60eef0b28d58636553acb1d488f544a64854cafca85190f94c53c1a0fccc2faee667edf7034d0a5242e507579346229b11f3d2fc6466d2598df9c97f404b91d2951059fac49b1e5bc36ca9da52cb277061294a4129d0420b179c30c70d9c40a1f73828def4d8516cbc89bb7e55c6b6624c19b47a622313db7eabc0fc2c8c96f0812c81be2ea8ce74b1f0d0d20ee5d0d2e6804c57d52cd8c477c7316e60c4a64be48f8c4c2dc62273c0d3a1ea23b2e6ad64e6671fb383fc31d218c2aefad7a4c8d98c1379ce38914f5204b1c63ea45b461f928898827d7cb5f75e90c3af3e9399963f3e648c73fe96cccf5a8c85bd5acaa0a6931a4aa8fce0aa816b265c196d7b16d561d173efcea25ac804b99346c20c7a8396e8ab647ef61f9096539e6db24c7689d254a13a88afaec69b1a0474e5c38ccab6d90fb6fd0da2af4e674b335bdaa91dde205b6589be6c1c172808dbeec069ab4469ec0ddaf6d88c1cb77da6c674cddb674cd325b3259a31a991ebb3a56db31bd8bf2cc59b1edb3e5b8a37338e6d7598dbd856676bac8c92f430430a279cf87c6009daf434ec81c39995cc2c9a34f4f5519ad8eaf1f1f88ccc5e0991578ae28d0b6956115fa7d3cfa2785337fd7c126fe65bf8b361cbdc62d317a1af939e45995eb23a4c7940620d0c9166ae00069bd28fd2745bdb41c635984629c8f49b3ced30e3192df2dc61deb148cc54b02bd838618e1cc6258c8b9ecc2f8827180b28d355f4aa671118399c45bb882508c7d1b4e7b16542e354c1aca002c68e474aa4ec6d729a874cbfcd4833cda2f530ed208b9ee774aa59550bc9ae1d965d3b3d0f113d4f76ed3c4452c3a60e73a7c3dc998e94066b2094663e467de8c1174f10c009987dab7a882c97d4ccd811b9821cf0d004b43f22c330020c25c0fbcc8b1d69610ad06a22edc311167e005e4d44bd2a2d254872c97445f047bc89123f82f33632bbfdce3d96996649693db9846a890115c0218026b7122207a982e28d0a72e87b087ddddb53cd611264fd93431974af7bc8a10ca23268822c1009d6acaa33b8d22c7abf639fb1c09dab5954eb64bf3163e4ef201e3268caa0e9139bdffc0953721895649052139d5b1b5b9c094748a24186c74b4e6639ecdb82430e2d7b7be0081e8ecc6a63e156381597398b7a76fbec282f6e9754f6d89d5028ee855b71305c0c979d1503b37a4175f728ef749a718f9de54ef6845b2e5f8f166ff3c0995be5897db0c599707bc2c98993f166c3b8dee26a7fab6669afef01bbbfb034987dd53122ed31ab61d6de0dc88d3a6d3fe1edf4f9e17f52f2c478dbb64d6e72db30ce7bdb62a7618e8d1c62b9c41eaf74271de88bb51de611c4aae34db384dc0ba375a8bf0f5b7b7b954b5629bd697caa85ec75c0cfba4a14d95d814738c618638c639350cca9be1cebb0b557eef2ed14e6efd349f0581e8ca7f224f8e2b1b4eab1b4d5ea3b2fb79ac7fee52bfb97f3ac46f058da598fa08cb73acc77568761c168b9b4023ffac2196f32ca749d8e776c2d1bcb96dae2cabb6fdd71b752372f8756776c6bc5bbe3acc812ca746110db5babc69406e32ec51de31fe30bb4f2379df258dae54e7df5c7fa97efd8af34cfbdfd8b3d4ff6964db5727ab52cbdd22414fac238eb70b57d07de70e8e675b9cb5ef7d4b6fd7482b1f565b59dde1dc65b6d7fd95eeda65af1b89fbcb8555cf7ad3b3d76dac96a96e3668cc835e39da21d4a67e087dccf400e4bc8cbed612fb79ad5c15667759a25c4be7ec7d6c31c46f35cce1382798c17411c6f249458838ff14f5f305a26512dbe241691061f67bcb114637ef8db92f9612618e39fbcd8ea4536a566cc11dcb9d4b329436a5cee334664e943ca7cebf7362c4cd7e9abbffca652de4a04a38eadfa8a3777ca8bbb087dc15c3e05e3e948ed8766450eafdd6e6b6d95c6413b0af54c872d56ea727797790461ee923a4ba5594262cefa0ecc65344f3dcc599a8708560f731efb984730e62dcff20a0b095acbe8486956c2550f38f2c53967dfd92f8b0ebf1d5e7ba769cfbcb0b5b3abbcb0b547782acc3bf570b5530fbf9d7a4ce95075ed2378321ecb8b9426c68b14c65bb9ec5e503de3af78dc555edcd9a35a967aecb2149771dc37c9a13cbc3b4edb782d16e677bff2fee2693918d71b9354132b6df81bc6da65e6873fbb1f9ac6dfb8fbc1cd8fe658838f7fc0c41a5cadb5d3da1fa76b5dce067260620ddeb458831fbb0dbcd06d4daf620dfe0bdd3ee9186bf071266ecad9392e08ad168e38e2d8e91c676e48509a6609b1efbe539f9a31225b94a74369e43b25ac718849756c51245747e8e4316df1b215f9f9d8885cc28ec79ba5c343049bcfceb3615b144bb8a062e403f2cc67c7dfa1c77a673ed3172241a32a30ce79b5aa95525ae99c73ceef8bc1a1be95807c5f7fffecdb96e43e6e47c2bd6be1486b1893c20ec86c760ba0d78e3d5ac7ae27cd6209e9be1d863af70e094a9f3a207bb6e65dea619cf36af5e7d0baa735f2bdfd762434d339b4f68db4a20eeb8eda346c8b71faba07d4a666a43a1296af7c38c8186356107b7cac75989ffca3e41d6739102424a41d7f391296bbecd02cfb1d2f9885e53b0e63f90e1616cce2a2691eb69aa6c9586c2fd4e4b3f58e474262bc316567cfb4a05db3e39190127bbb9cf5ce460e231290eaf21a9be666b5dfef783dbefc86bd93f693372313ce0eed73686d7ca9733a7539d9678cc85609d4919df61d2c1ecb57dfd9f116cde3f21d5f691e2298cb779ce7c57a3da8e41c5a5bb377f1fe61fc0db95e0576b0785817995fbde2d4bd20374fac61697f790459eef29d1d7fd13c31df719798efd018e62c3aebb4d4cb4cd7b597f12ed0da38dc638c31fe36feca7bf15cbc486950dd498231301e520f38ac02a60b5fd3e16a656f5b382f87d67dec328b35966f6bbf5f79f1c525df2e67bbec5ec03f1d87e2cc2d87d6cebe5d4fd370fd9c19ceb410cb414c5f40f046c22c48f886f9d57f2d1e482baa6ee61434c59b1636bd5c42a9dd743b459d461b269b8a41b9192332093b3e4ae51e05034d74c688fcdde56080729d4d4bc3bfa659423a4ef3f09cdee96fcb779a673ba70f4aab8ba42c405fdc51dfe9baed9d66559ed3855011b4280fe79831d2d062d7a69a24870fbfcd2a52012b9a6e80831d4aab25c9d55bcd4f665552b68320766bc723276af00412dbb5e391134cec2df549c9b3b5c413a5174572686daa435fd16a17e6579574221029bbd6ab2ad3526592c41d65a9544692cf4a881ce34d0bfba543e552bc61d9f59289beb24f265f52cc3c0c509a7a9928f95072287d92383742bcc4c4fceaa120ca614c1223e367118c01c874492f76bd6609d138cd93fd94fda45bf81ad36a69db83a194354530aa6caba554b1efd9364aa42d94c9252a3e12e8bb22cf87d2c78a8dfb5890b94d87e9d2011f676e8f92b59f5e04e3a91d7524a76f2c8bb239694dc74efaf25b2cded8673c9818d8610ead4d23d22b82f2e3d820cab1e7d6e029426924132b9b70f060d74cb3849cbe7d473bd63c3c44307c4d674a53cfa3fda4c1cbb45ada160ea56d8f9bb69d7054d956d7a3a1327601763c1a62b2b7c9e11732a62d849fe9ab08a5a9c7b5e6645610f94b224b9f6c28c3dae5d6885bce1923f2cc0ef18ed9f177322d8fbfb3e92254f324b84dce8652dce29872d8dab54531ce996a393cb146e26787591d7eb0abdfc596e6b43d6c78baeeb5624da59f3aac74ce1974174e5f276da339ae705c00325df7b10663fb4883bfe122274ff35c9818037b7eb38746c76a45dfd8363931c0011d62f1863e9e27ded89fbae3d057ea3af145628c2bee8c2c1fe299854cb04569e661a864f6762fd04d750db23c8be74274a2f27a641b25e5cd44fbda43019bb6d0991b36fd677338e59d84a78d6325a51447a44e77b5ca811715479bc53c14c50b7a9086102fe062082dd8bc18a1b529c1b192b2e2f8c428ebe20d22322d6c59b17481448417488ab0c47434c6145ddc271f483d09c129ba01041c3c247942e40229a4203113b36663b6a298406e4aa58e04c24a663c7a58e3881f274bd288821e6dc1841aa81e12341182cf162150430a272c68c110906454f04043450a55040d2690fc6007212884a05c34e1a6b80235451725e4e0988a2c642a8e598341c50c3a3732ad1f5035e9ac5849398511570a106040a748819502031b6cd9144a644f9cb62886085200440c56529600067514914419674801c2480a34589aa418424b06c614495059b66a020e4bc646f7dcd793f193d6a37b9b9c95915294a572f6b0b160d851c7b027457db04216a4c87bef8db78935f6bd6f99f7de7bafcb947cdaf1a889346c1336d8ab26a4c881093d940106164c00c1861b2b68c2091c65064df490adb5d65a6baddde10422f0c1a20e2abe58022d55c1b674b8f0b67aa6b239e7c4d16a3cf389e2e0b10a183e289002b40514556c31843a9a14418409b070324494386cca8a3c310f5bd42aebbf5a817099808a2806136104d524a21941ec1084358278d04393163d4ca2a4800a23aee0428930b260c2c90f41960e2e9ae8411319654ca1582001616903e3891a355ec0600635cb3b1ea580083e47f2430f2728aa420935a09830458e347c08420b4a80744513d95be6b7aa7a95c32c335d71cfaf665e5128b12c5ca0060e887882043bb06249b7f1fc6617b3da50da53c41155dcb0819212440455717b00c5142558430a326a409fd43da38fcac3a67416f5ece0032150e9e28a376c3044c5ae6520595a2282133f208132851c4a2a1213f4109186cf075870832448554891ca01164080220437ea78428bde403277987b4bc55a755ca869ccc1831b4cf1220643b000ac51ecfad77ff52d1eec2a04586badf566c7e8e3846453399348614c639c31c618a31230c6c7a8b100f65c22ca9e938629cb17618b72053926c121c674c598f406129bfe164d574c8263e846b94f361090c87c3615823a7756fdf6ae3b77d4d67573ca773a16ebd10169880594802031452518f74e75ee56c3622cefded3758ff3dc77e43bcdd35d5eb32a0fab82369905c78860a9ab746c4569282c3fa5635fb6c11a7ff311e438eedd77b8779a8708c6f2ee3caa73dfe958de3d82a10d91fc148bc7b22aef761e3ee7652b12ca09480e2d813204745a72872e94bbe25da3958772c9cbea31ef01611ec1eca184a25d3e4604ebae7a8c084604c3e71e290d8ce59a8e492298ea2c3a2695381d93489a43e2943ac9f25056b950bcc9aa7a07a559f53de089b5b35deafc64c7ef01b52f9de1840a1c4c7c7c40d45b4e045bf9f66d3beab0eda821d8f6161d9b407a0e2dd91e4ea06d88023155a1404cf430de85426968bd1cd3acd23d82dd430ae4f2b9f218116cc7372004802d30d45d74cce5a8afe818116ce5281d73d17345293677e81e24d8a291548fa0eae184a2d22cfb1e70355934cb6a9d9f1ef0425162ed4870bb04b7b3042f160e220228272d92b4644142b0a469a1c40817096b1125db204300655a88f1128488242d7290a0202d8420130404485186c8740c4551424547d26a0545979963f5e24392225a90554ca490c22509172b51248101193c602923091c4b0481442584ecb2e351104a76fc04f1c41a416471c28e474128b5b1cd4cd79430cc3d5da747ceca8774f79029d8c7c7160b93c69e02a0460e31ce5cd11ed2c70a31057b4d87323bb4d161cbbe3adef8883536ecb1eda7b6d166e44bef9557d28839e963832450e62187b926fad08929cccf31f63c8f7fc660cf8729ec19cebcb0d68933c968b35d4e46b33a84d22c26654372ce79c8fc7492e88758099315365d6134da436ef83192524a5cc55da2d6e3d7c5d9c6817e94c6f6a8ad4a29b5b8041eb27c95f79115e4844d2f773864c77f404e2c69b5f6669c7c327db06199654a69b578ba22a594564ae9945d1555509b29d572d1c665181765455c87ca302eca8a50a90ce3a2ac28956f0a955516d5a9563cb0edae2b2c2d3b328c81f8e5b62e88110d06bc71d8a1715bd6c4cdb2286e1437cba2b851dc2c8be24671efcd6cfcece365ad37cb8068acbd34b2e9e51653d301526448acb8f57d383636178a09c5bd37b3b16e59773c712b0c501a0b501a127e608a1506bc4f9a8f9d63b5c30757b8e08a26427045112c43c8da8e475780e08c2b3eb082841575b0c08a2a4c488c333e6eed6905d30eb2c78814c84147113f58810ab6884540e389105215ad20c1aecf5d4ec54033ce40c91060cadbb51ec3510512bb1e9595745dceadf51c0dea182e3b94d9968a216ccbc5b6f6f909946dbfaaa2876dbffd45945c9044173bf8f1620a174c99637b1417044c40094e50be0895b74004c38f8a2976ad3fbdd1ea61430510dfb6d7b00a8e88e0d8828b25592c118389335a72ee9ce28c14767d7677b5f5d65a6b6dc114444bd041833ae87002ac61ec5a5776adb5d65ac60eb9996d371ddbd2601f4521832227b63d2aaa63c7232964b0ed14466cdbba3d5414418e39866882031f4c0163dbff8b268a60494d91c3968dbc13caaeafa732495690851b499688d2066891c640a349d56a1d0a11002036ed7882573b48a23252439228072b32e21c20519a8889deb831a8014444841870b004850f5c0c39685a8960a5c960b58374f1e9210c97255966c7a31ed858d1417e0142810f4ad4610592bcdaf1c8873058a2c82d3b1ef990839716e41d3b1ef93084972af2ca8e474041b4acbc1d8f8058f245d0be66c4d75545f1e600fbca36f6956bec7b6ff79b9dfe6ebf9749f475fabd54fafd2a67bd6511c639cfede4690bd8dae9254e4b1f4a73e9fdf66deb59c0fb368d34f7276f8b34f7d8638935f7d23361671e0a9b7a1a907bca145a26cd95292a32bffb1298c8f6f5614c7a325d4118df7bef755c98df3d4ee68120cb227ab3383f7a5914c6a538868f2c8a474eca8832e55e23eee37cdd6b389341452a305dd40b4af345a62b411a10523d8151fccc27470e4bd8f3466e99e1446bbd6f863ebc2bee9d699e78af970337a36de6d7b2ff7ab462122d21dec8cfd7232c5e22d753d5b35f2f5b7dfb8639b4ececa96fa9f9a57e5359eaaa94cc2af36c5a3d5a90a73e23679740db050f48958ce2beddbe89d2be5ff926395de7b7f22de5453a72ea757eaaa734b7e28575ab74c862739c79bf7145c87167ef7272ac69794b264497b35def90c36814351929ea5ecdba1767729b773d7a3aae39dec496cf4608d9d678d35d75d56797a3da36d5531e0ef7aa6f77e535a5f256529a1524f5ec3f523aceaf45872c3a8796bda2c39b7a7ea6f252bf3de697d236f393ddf64d8b525254a763acc9e8c9f358f7b18d3dd6d53a73cfdfcfcfb67ad8c82062deb03129ced82c3726a298b24dd8710c28d8a83f8156e3fc093b641ce8a546350edba5c661fb45853970606fbf35d4b0c6999c8703fe955e38391c650a51a6107a400331d6d09e4db5adfd4c97dcb76f5baa63a5f40b73a7f2755c404d7fb2e779b4e2ebf30a68f97c2a773054e9e34a1fd247dc39bf4e17cb737ef64e41c8f9f1dd33f55859bf107758b7ac2b18cfb0a273fecc7a667e1167e6af49463d7ced72582e3b18f2bbaf78ac95cbbd72168fb5f2b85958bcecb156e4c89f9ec9f4f419a075d49153b9841f322acc1af66287638dec5ec81ee7a7bdc5e32cb77971ab8af2a69fae99b124c599cc6090bfb7ba65afeaae5ee621c699b93253b669bae68e74670f39a12b5f59b44c9e55637ef4d22ecd8f3e6b91439b14daa54d6f93a6ab8cf9ca244b6652eb648fdb00f326f9f8f8f000c67af963dbf511a9aeb14653bca953367eddd3955d3f69e4ca96af5e133da20922ecc845136f6c6ddf1d5f2d2f1e60cfcb26e2abc563cf4b26b6a8624f1b2239918acc8ffe27c8af38287b45a457010bcc6f4a195446964b661c39fb913e75028960e2200f030202fab99977650a18389dca3869f993ca22dbc3421b634dd029c847498c1c59d33a649a035b1c790155a6209fe92b5390414e90d82aec78d484696f93931598dfb480f42195c8fa4df32c707a23e31f384849c8811d66f2f5a7ad48052c305d9a964045a8fc61f190bfb2e318669060b7047df39b1c30da8c8436a399f9cd2ccb212b9a210f984eb780ab65f490f9950094e969c2c8e169a4d44983aa428c942665db69449bd8f898cc22f9efb3b149c520df87d328a39402d1170bd7c35e75ad9a856315f78015631ded511ece1c9e99cef499b816e490fa50a0e98a940dda343f261ff9951d4aa61549139ea67cc91e481afb287902914a9dce0f924ea78e84d372c9354fae2199628d65a22fca4469ac3d1365caa80fdd21d2d857592d2d838df9d9dbee47a6a952f78352f9b1146becab6cfb8d7259e570ed72369043d7883596c220d6d8d36e032f30c51a4b39cabd91bf5d32514ca78fce55ef8e64e5a8c72ed32c21214d92435442a134b668fbf8509f6d9fa7a63eb1c63e9c3ed127fa74cf6eaf65de048a359d9e3e94c63ea33e4932a53ff3fb8432f541b1b2ae3beaa82ec3f8b17a0e6b4ec7e837dd039ebec54e3bf64e3a6ce1675ea843332f87d6960762918e718ce1577d5adc88d2b2e3593a18e45979b7cc6fced9a253b26013438baf1d69ec2d40b351bc6961dbe300a12f7afb21d6e6dab45819d6993ee918bdf6ddda6cb4d3b39f748c28d3f427cdca1e35cdcab4d0d6039ee2bcfad5f7dbf66a9c5863ebe9ebb5c3eab5471046cfba5a67c3a134363d8ce6c3d63dc2a8132705232121e52c333f9c354d2221d1971cfaea2f18e74c578f399297c31c67b2b4afde03e6c7e417cdd25e563af60293b38c92372d8d9050b807dc7498376623cba1632de63b307fd13c2f8779390c3e0fcc573a82db59ab55ce55347ef849a3e9d2347e828dfced1be6aea6855e2412a5c10ff190ed729220e12f31abc3ac34b67f19e1d4e508c9e46ff925e71c93f3595e4cf717194f8224783de0081e6b5b1df6f2558c6883d1b289d2e01ef0ebc4d8b1692d9bc6b269dbca51d72e91a60b758c92f122a821a19e554a252a82dbc6e1ae3ba134cdbb40eb9aee3cd676b9bbd55d1e5939e7fbd563d95f5ab495fc97d5107d598d35143304933724244d43d290b286a42169489a877a17a250ef4e9a97f3cbb6da60b6984dd3613eeaac18cde6d3f386daf263b7e55a4fdf50789f4e3beee53b2bcdda76585b8c687b2c83d5bffc45c7eeabd0cb91b463b9f40512929c323fac0d15cd0f5fd3d2c9fc30c6d307c604f7de7befbddacdeecdeebdf75eed6a17e36757cbb49be955acb97fa1db58c7eb837bef6d2387ad7defbdf7f4d8b1b2efd86fdfa9efce80089ef40f924c0bb1df3ea4bebbef384f2776ba6e3c21c60401cc6fccafcc5918cbdc1e09eb231c67b25297790fa8ba55b134eb3287b1528fc19c95d230d6652ea36331678d30e1c85658a9c7a4344bc8cb610e7b39cc5387d131a29486ad1ea363f5abc7ec5fde03a674d8daa9b364aa72d911e3c17872c778ac96b3de03c278ac16cd1202f398c3601ef396c7e818518b86c59ca563f5313a660fa37bc0889fe93075ed2d5dc8a29338e500753a187f7aec344b3b7da7fb49f39c679b27eea76c7a27add3b49c3d94770a75b6a6c33bb3b0e73853152587ad6fe6337b12c4d9877c9a436bcfd7e9615a6b93d34fdcad134a6a765a7d3c5a3d56f4b57a39f7ed1bc7136fb84bd4376f6e8ee3329b65dbca63812f1e8bd32c212d2d3b46f88e11bee33c326fb98b86d23864dfbeb5b66ddb369617e3c1acf25f3a174f06a54da8d4ab974a8b9a658ccd08000000002315002028140e87c5629158248b945def0114800e87a6446e561789b3204861983286106300000010204000608686680338914762be71e50111a9bec614e215b2e050e215145f71e0f8563e05ca7e350352bebc9f878f2e0934f015785c4798211137aed4bbee53e77cc7f2f968dc597d22414b3e78546daf014ef2cf63c5b3460c50b623a95df5243d18f29fd56d542a71b65de142d6a37a8fb226e71d54f577050837f51ace927d9f9b7c025d1b512b69bbd2c2312a6705bc82c4aeec404676094a07cc5c757405b224e343334e242609d71b084b6523adc9c18b212296a101edbd4805841ff35963c2855e11234c2c9d146d3f76e245350e76efb57844a002e6f5d174fe14f0410b80df2e2405cdc0450cbb9478b16237c627735000a0ee22dbef5ead9632541e9bceef65b775379025d833333516e97b87a35e3afe32b669dd629c4a0aa479ba8e1993d82a48d33f18425960f41581f08907c34815dcec9cc507c360e00b9b843f9975d80243bb718e707c6f4a65f4d90e6e2c1866ac8647ae72ff7add759874a35c5da48ba9015d397eaa0fe3559289ab4cb3d63a768e1e5835c7d81d32e38cf60d1dde6fe2bc1bd76148fe738112614437cd9ce7836799c799db06e30b0fff9f6afcd58e3c381362eae2ffe415edc679fde5f945e481999b4759d8f826c4dce08e91ce05c0220113621abe5dd48da17bbb2b498489a44dc11290418597b542d571c1e091997d581d480e66f2586196e56984c7fe8f5d43cd7015aa058cd098789b92ad61686b47848aa432b9b951c47bb763ec8fc08608d47e09c10a480c54ce1d164f560f28e2ce8062795bc367d19043c08ccea326d360225f7f184ae33dccff9a8220e98dacba0d71acc09dba68429001a8038203ab277acfa0dff3164692c6077b6211a2867ba7efadaebcaefd11f515c5d5babe8809a919ee1ce93637d680193bf8df9f83401c9988127388aceb658b14a21d0b5d90036efeab33bfbb831559dcc304fe6e32454a6ac22cccadf332ecf06de460ec0d4520dbd3eec79455a88cba6886fe5feb86423e945858830983acc8bd97e90be5bc991ced8d11cc985778286b381291e6409912c6f0121523ea458108d5318ec72c3cb7f349ec1b1253177ce380f4b247843dfbef20fa77ef0bca02771bc1b21405ec6b8a04c128f8ea0d03d477a3ff7b77ac1dc7fa7849b80b7e17669d569788dd2c923e32abc56b3443a97d50394da3d92b7f290d698e23fb5fe609edb58674ee02243ee882b0ad700d5e560accb636e898852f6437c17a5726efc2ae3e8e6a32e744d6fcd4c7e2fe174c6e915f77c0b5f7f6ecf9863040fc88b2aec22dfca44f69990896cb25af3ce4215a707f7fcdcb7f7741d3b1e1ef1abfebcee4df83c749d6bfa8226819e4bed5c1097ceb8682598b607904e01558e263a0b3f79fb00004928f7fa59c79ac83b3d8b91139ac9080801f17d0984dccbce4212fc6ef30093e292ca6275dc6033df9db1fff62f59ca50f558f56b8c605c0770bc818ef722813fce952f30f452a891b44d5dda848093cead08d6a2ae13d00472246888651f14d46462d7c84721327e5909250872d271a96dd7aa4dc275f40673d0606b44047c4de11da0eb62f8dfbffbb833c0dad2d012d1099e0a8e746410febbb2daf8711178add2bc322a78b3cccd9f260848de8acb0938e68e40f1de62ad2514d2b2b8a4b91a41f07879978e122b18d625978cae76829f13dd1565bf815d3870e7c18f2ce384fed63e09d08d8c1adff70c0cabc69c1a5bd8ccf9cad669296031fbd26890531fd329189901f69e68a80cc8157fcf4dd0e0dbe58f2a752e6716079d6c19b8739b7463b31b2c703d649b7c3a27a3c15b6c07d87b76f6ebf83a66ea74a0252fac18b741aa28ec42a9efe921d89c0b423d911e526f6cb9039ac22172d3990c360db298a5ac0775a329eb2cd478165d63ab431963d50f028d060b7aa90b7055b8550f71d05e5cad9dca2759e3ba73882e9e546f4e46e468aad32771a1d7a34682689ac843f2f8aeb44887e3ff2d03219df495b0b97ccfa204ecef0f811d716b84ad5f28e063fe1cdfe4f98f89ac82ba2ead8258d93dee0e99bf2f0a1c4173d0e1646ea4e4b40b161f1a6722c58a6bf29299b7a34c2c470d8b8ae7105c3e98884d5dc70f788d0a4dbf3c8b07a55a059154d098dce3abc2304157e92d90709d69897e80857d3f478cf62e9a97c9988b0082ac33f1c761c8a8c0de1e5d2b6c2c879caf4d3e1fc667c33a5243ce389edbde0065da1486ccd2b92b0ec24064b0b69c22448203e91898764613434c533219f8f8ae818e7996c16b4e68d33f25865faeb27679dd8181535147649ea8639d8203048f0b128c608799d5554685003957ece2d3ded4a448e58c367cfc595d63b3022d28b5e5087c4909611d54da1128253bfec71158942a2e1edbaa762b86aa67cb0191558f6dbc80469a48b749a0a1f788f438f3ea48e355d2dd4a37741d76df938c5c606085ead12b54185f0e7c36b858d12a3a037e3cc8e8a95815c85b0d0d88130ef244a8f7b7c7759f12b032ddf41aab695c06a21f229ee819a2227104322b4d2fc17f42f440ead117a5cbdd62b8ae3c956ae32240ce78d7898c75919127bc8e8d99c15b7679e4577b56df09a8307b052e79c8933bb255e03c110934ce1af8d1186cc89d829c498bf4f8b60494acc24f7e481cc47924e66784a7e13cf870f9d6ad4c4983371cd36a97473eafe00796bd10cf3af6ed01d0fe687fcc6bda275d98a3c0ee15f6608a8651d9c96f497745a9a66cd7d57f222ab0ec1600d382aefdbb6a522269f55a361356f2c3a0fa042b547620a0face689402be4fa212e1aa7cc952637a845eef32b0f77edf226aea9618d88590e76f5a62c0eeabdf0857543fff9be72dd9f6069b0cfbaea7cbfbb3330ad5261d483e7258c578f47b67212851cc8737af22f5115e7413a9144d2d450d9ae73c7ad68973b31fdef517b898300ce08eea1ff1dde9aba8c827871719a3ade003e977c5327af2979300575734c7412d4da900073c0c093805b95846b7adb757ae254c879fdb25d89677c2d6619596aaa258931f489369e2a5e339a7b7c5dc9b67253334e035b22fa09f7cb73b42bc85b83915a5f720be4a8b8cd28e51adc3fbc1ee1e51da5eca36d99c256528ea4a0a47d43dd7292c7e0045b7cacfa85709a2a4e0d51ef5d1bbbcc02f89445108fabca36652a8bfa379b8cde91e59836a0a7a6f0f6ea0ab3fceba39526b6a999b909c6fd1f9e9a12e4529da99b68c0d687e9e52fd5ba0719e84dcb77c9b0f5565af01030afd863fcfe3d0a1f69fa3ec86a70477b1fa3fbea13fa9748285b09b80a62d195e252b4598eb5dd2a0681241e0dfb064017954007a2a25e0236343128858376ab70440a97e93c4bc2142018c5291b761daaec49696f06d0c8e0d06eeb5f46151263c35c92b36fea83d0ad256c6abfef93084ea051b417e5945a181521c160f6ddd79bf697f1934f2659b886e0eb3973463a36e334648306ba3409a91de44a5daabb66711c379e15eaa3875e1f3bd689f95b45df1d3472f30413e709bc04e0308652a348e2a58281e13539d447ab9a57bd7d360fb295b1237725f0fbd6b882b576ad939a8fc86abe8bac74b890bb8b4cbb2f3b850e7650cc189aad19f7e004534a824dee89a2284913594d3a0e5a283a149382c4c4a0f851ab8eca64ca3f6e1846222d01ef7e6c6d76a7085089f832eda8bee86b68b83459e6cbf2a84d034f045fe8e2a081c2afee5de62f73c3289f0a8dea20dce94b4e8978dfc6f642a9adfce3381dbd7d40591696dbd49c41a2c9878c7ab5b00c5a1d32de3a9ddd15aff9c2d5491868749f6b688688aeb7e3ee940b10fef1ab2441d5b4950f92e56214f35997a638eb22222de47925a75abd512d25ce33f2e9612e7e1097c7c6eee7cabde2b93532177704564ac0aa2096edb45a59761668d96d33adb6568a67dd44a1b23cfd2525db2287f5c24039260715c0bccaa30334e5fc5705fc71212098537956cc3af8b41bf6ba93dd51c13eab7975f5760afb016deff36a2aaf0bd97dd46d51d615b56ac1283823c9cd0015fff68d5198c7b423f9a48bb414f76f3db94e2e882c736c4f0722653f961fb88126e2370963a900d18972fd7bf09bcb74b57c2a0494e9e3e9ba8262b16eed3d524f7d6e3bd8d30dbf0009a51b3f25e5d2c5644b091ab23430d0ade0902d175c2a2866a30e4f8de4dc74d3bfe62827b12b4800c9e37d551e749f592ecec4627b26312e7c24a04b8fe0785f37c015970ff4ff54f1ba61b716d74ceb26ec885e5a74923964dadeaf2ee60f2f7b210cdff4121853854c4eaa641ec19c757a100db719da08ac0b7dc02a74269ceef884de7ed3081b6a1430e3e245766f04bbb1ba98427c4af0311eb8750388638ab723ba8992051cc7322d60f304654e9d32e0a3d262efa7f9a98ae8af8d6020256e78f7ea2f5c392cbb43827ba7291cdadf591a8f8bfd8eddbef93da4813bebeff97ec0c7f80fda49c14ca278cd4c4d44fe0bae651b7bc1d36551c03e02b2e33cf050b0c9f54b237227ac2143149bb73df875eff949862cac31b30d3aad7aa4b4e80cd1c42b87bf14f58d294de8c67336ff17475b7156764b05df16c02eebbf7ba489622aafd2896b5bec5887945e3e92edaefc9be39486e26e7406a58ac4ea749135fe61af229541ff1dd87aa1d7b663c39ae81adabda4470d905a0683725c9bfed0d4742bcb30eb1eb06a52a509ac1f8cfc9f42d61f0ae6676fa8c28746ee276f2e4e3df9c24b3b9ea87955ab8918f67deed05c903fe7fcfd4c8f36c786bd16109fec0dd3bb02b6545373107978c2ed0f1604557b83d970daa50d9bea03addb2568441e80ee3ebd4f81583ee7170cd402c555845e2296bd796d8960761b603ff38ddff14917bf169837afb46085180a25ab6c04e2af873fc2d2ba463eb83be7c328ebb21d4ae4b609942795b98f2ce5d10b3a6f6aed227af6e732b48b1847ab55907caea75f63bdd29f7882a4d30834fa354fe70033e706e5314aa09ca81e8d4e3732a56504747a1f13da2bd94e451dc0dd23f052e636014130619a81733304a8804296627a04fbd8831e807f341d363d7a9410a2877e07477dfabf88caaec7890b0f4eba94b967338077e9f027bb43e9d76c1f9c9d5ba8a9e6840d001e4e68cd04651123b17e95e98d2ef2076005c2a6a245a4dd05fa6f5db6aaa528c412870eccc2e625463246c3b05a92c73492d468395dfbe632ff4498cbc4e122a79d13ec829531b0d0459159161700a13f5d684f93f2606727ddc093c3476332917230739f6ea308db5e432e5fb74c508c9e303852368076d538ae2697e89ae31768aeb746a1cfe9210a998dd3987448d25811865e2592a677e9fa67c69b9cb4bfd51a4bd0069ed149a959669ea93d747f82d1838de3f972853bb70fe05ec1121b5ff97c99b93b32a056ad9e3bb7c785370b3ac5874aa9a2bb5e6b96e282a34bccdbdfb2a6335ed0afe23dd05a3475c41b36b60dd69521f13600e91010e81772b1c1034e866c2108a7041dfb5ebde5e90fa465ccadc693c1576ce03564f66cc1466b3f8447531eebb5526847abfed3f2994d6c1342e8654d131913be0b43a80e795f3c41b673f0b3f4d0e5c3070d64ffc56e469f13d13bd9693f33188fa502c64264d4b9aa91428e0db587bfe1ae3df25daeb42422642238a9fbedee8f923565642a24af5a6d827ec7721983be88b2622eec4d78123855150aba7e2fd84986bcafe0194031872236f6180545c824c63c5b596d7d1ceabf5ae0e13bcabd70b4d21e6b49fab85a11d27607d82742b72a02a8bf7c13e1cafe5022575cc7aad774c1adef4b02a6fdca85a8b73ea23f9b6ff426181b66d4d970bef455fcde6ce04fca48b50818e1e4d2cb8ebd7b27764a808815b9bc32021808e7ab80305a97ccf6cf2f6e409c882e48101412968e913c6efd25aa2d3bb9468736b1426cd98b3de80603ed0b8a651a5184966f5024472ee55a7c5b8d64537c7c30007bc7872cd971250e9e629c563dbecba59a21d54805f80d61227cd2cb4458b328fca29736d40ae880128bc802b1517e7e6bd0d270bb2a21da9ecc45a9e34e7eac929ff266c4d75d3b278ded98e5fcd43192d58fde5ace0e79120517de5f40508c8c70ad6e70654d4be8ce4bd1e4b845fee57d3deb32e28ba19dbcc5bcf0f6060a5017dc7ed97897bd5278bf3659994b321e663126a3a3f6fe4aa6f2af32357a452fb731d26b707f8694e0efbd45eba0bc80548d09ea26f909d7bf2eef4421b40905988601babdc7a99419384ed9cd69833534e6695baac384396c4a4b26eae158e09b235d2e6715050bd39c9932885b276144d3a6be9b371f3532d49d381a0a4ab60b764d8e7f238cf81b3b5a38a1dfb0fa0beabfe3718a6a24fda7435dcd309686c2f1739e186c1d3e9493484667e01588020de35e5f456bc074603f500a7b7248be629ab2ca9322b35f085ec6db65b47f16a728992f7bc95181c4fc4a730396823e91029653feeba9ccfca96a390bf8d89cb5bd08a20f8911b43a464ab2db1dbb1031ef6100bed8f60d596aa7236290a379d3e20d5d6fd14ade9e876a36f2a886c92bdb928aacaa29531c936dc9232b8ba5c1b24f763a1b571d0d75a551f80be5554476b626551e96b5a0f202a38ac5b74d13b71d916f11a629ab4d0c405543708a91a0be84b283e6f5f27987659a4f6390618715775ea885771a5762d2a374d90d5b352e48b5dc1721f86bc22317cdc943527a8939c530814118abb39091505181278986d05b81aa03eac5f55be2599671de1b54cce4e79c0083425e21e908c2e89d8df12345e77d9c7e0d073d36a121bad23306010cc39bd13ee35be0df3522835c8c68f08376ac5be10817d806d7bf0267aedaa146694d5e83955d040e36e5dc8a4a42a587a64349d4607bb044104b15f63d0d1a387eb0a95809df81a506b1c7a2446c916e2f087dc6be2b64c8292b85c915c8ccfcc08aff124c5bb38922baf779b3dc264369f47cb0f827509a3e8d87586c7625847917b180775792ba975fdbfc007adbfdfd461803a87752162826c29dcaa2de92c1765ee2cbd15325d16be206a858348e09d6b165f4f4e661b0aba09f98a8fd73ae65fe4347fa6d8d424de4aa721373f44b4be781242bedfb609bb17909917baaba433892a483379243e19590f48276d07dd6dc7293a8b3daa414374648bff90e53eb39d70615e20034adf484f9dcab6adbd015aa84c8a38d44dc5638d84f70b6d2b0fdaf68c09c8cd2e58f492765b21a8fc4dc984bdde9dd462cb0db4acbe246b0d6c97ad4020163ccc2f035833bb1eab22619a883f986356a21a25f2f8b8d1bd02a8b881b650001966fa4d614c040a862d2334c79fb6d78a7613f8bea17cc752548cf622da60f8496ebb85cebf2cef65673aac541f1ab3a197940679de54dcbdb29a29f475568e572db7be66189698bd95323b2284f2cd89397e538c5852a675649bcfb6400061ea4ac92031937638ab6b15c3add49d19eea232adf6805122fc65a6b17b5e36463deb256c5a9fd9eab32d75ca2c5ac255fde7e934bcae44e98985868bbc6418acd1ea24ae322fdecdc7cbff3c119dbb165ef69085327b1f35ce366787fd48cf5fa7e405f692c91eb16b62485719c975d60f5fe05d677a0a57285750c6c3c10e7f4fe8b5f06eab5b4a17c64808dec7723d0962948257c62c8715bc97238596e92d5b919ef82468635801a8d16aba2dfe75af63daec166f9783dc2a989d7625f0a704a13c69872504908c65ec74821480491d7c878978dc3cf569ebb84b6f07524a39be180d45c0a535d54f6e5fbd1c08a4c2dfbf2d748a10389f33e460a4c73eac43d67dfaf8fc0ea410874c4be1d1268f0911316fb53f9e3758c3762c6480092f3db57800c7d5b2de844f37ef73c5ab213131f30bb5fadc00623e8f461f8e417cd6fe61adff9decb2fa96bb138c16e8c0772a4b40121e0b40ead1051dbdcb32f03429874b9837f041c096ca817604c1126f0021407acadf739d21ccf03b001f13ce07a8500db8288cc482040520aa751afc90b81c09f3d8a2515bb5553de9e300fa1dd68874070a66786c45dc96ef042e901d666fa442fe4b1ec47426bf02da5207ef460f7975ee4f4ef50165f6dbee7f174489b7d7c38e55940c91fbeec0aa6004e987e83a39d6201f1d5ab2575a45a02df2f715f912bcc6fe4d9423811c369546186a190fd9a2c4c8993d86514df2ca8e084b3699730240b46ba7ea1b892dfd377af95f69fc4718c20490d6b1623c6e5fb1a46c788a97dc74ce7a9d5541d869a711e8d36ce800be169fe5fa78a626c60c3a9c8133ff775e0a4ec867733f09fc240e8e3a528aa7dd358ba2e710bec6cba710770b0d62950cd8477e9eda1b98e1497b5f496d4f567e1de5c9ecc8549609492caadb8b252951810cefd643275346984aac4a2e3eea3eea0f21474e0128340ef422badb12fb361747ecb853d3406f4e386debf0b3d8b908d8a4d139d164a191f3d4728002c4e7a8a2d29b2acf774085cf661230ffdce37b177cbe49d3693ba2faa60c76e9356d221219fb90bddbe05000b77a4e412555dbecc0e198516ff13e6be4a539b234900a6f0869cbcf62f65eae3d322cb972679a04271a4158b8d9c52972be8af7862435ee9b39393fb46d6a4ccd1170655b054001a83704628c650bf0393e512c107fa20b4f1b41d4845207ad9a1de36e6c398f51d29e497165d70cc800815de9d2cd6043136c837f4f884643a890149322542d6d978de65a38454abf4e65694568307793fd211d284412f12648e39e9bf84c60747a844ab88712f3d09ce347fd3589388d057f3c21853a1446d935d04fa548556654cfc41a01a5e940825280fa9ce7b6823f3ae7f629470058aac3ac68a2244fe4c6a1c49af822d2aec53f54b9488dfd138883a283d250068573efeaede4c85bfa24ca7c8c913fac23726fde0f23926c31d6ff7ae4ee3ef4a53bbccee1e7756115976e6562496d34f51c4b7c342617f19a291c3f4a9e27ae0bb08df1da93ce3c1f0b7e6826768b0261652f46554a2a769ea1921f8ee6cf488eb2a1c131b05a54fe4c7faa7478965e5c45df35c65205d716c9fd67ba77c6b78b4c9ea306d85bb8e8c88619b5692586edfa1e3aa534b43ce834c22beaf16241e559435bb536e1b498d7e2724a38009582a8ee2b5be6757b03e8e10e426c7e9f7a78e220af060a73f1f5259700918a9b1de109b5c338908a3dd78abfe995c5dc967ceca279c0005151dc4340ff66ef4eaff0700319c960e94240e028877a41ed287ebd54748473696dc5e94f2ef9673aae81fd7d990993c3e0b7c2833a01026ae8ae42895e4dfb0fbc2439355c227148bfa1a91319d470fa86e0c305d7256b51eb594a60b20d0529adc34d7ac4d34c772d8baf98bc3e69c75ccb1734fbfbe2cfe61894c3b90efa26663d8cf72df01b22bf7f310297dc194d07d1bd06ec206d8c63b5714ec434ff9732b3096631d6a00be36f324063468912a91b5b45adc8f2c3ea26ba42255f10213d4fca4a28b7724e980826f81655334778ba950aa4b3cb29798286aedc1f33ce125ce42e37f540669519f89aeb6872ac2b6660d4eafe153a7f4c13e647e3444ac6cee7c724f4fd50f5e5dd52404ef77f35a767148191b9a54163e69963ecc432c69899eaeed38428d61263aa7dd0dd402dd3e76624c232f1a0e262e7f358cf5f27e405f29990815128d203e775ca6e0a55a7a3fad19b9a291602d00631c3163a7d9579ac5e4111e30d6f2d4e06023730830882ab691e06c3406675191dcbcf43a7a4a4905437ffab2fc00c8afe6daa861e498f77a72ac8ce7ede7b0cd6e54be1b4a5f7a4a191e895bc4499ec8027bbd8b53ca39fdf144e3358e03a8ed81c9cd266bfa89a985936283a1257b05d3ac7cd101ad60ec57b192f92e7f81c557c99840768698d7dacf61a6d4c469b5424135b77aa5bf88ac5d3164464a10e2061c28a404ca04e462892f14e1feb29f336f5c9242a8aa960ca8878a23a9baf8f0856453042f5a4e26c67fb737552e0082ba47d91f825b51b9e67e6aa6c4b19e164780ae4c730035140d3d746fbbe2ff1e6556cb2589faf356ac26324545e07bfe528d0bb475fc98eab6871a29d1a64e6e7aad425d2082564ee805b34d99a82fb0507e83891f0c249d90d67a162aee7d4d9ee4b103915ac3f78c65ed70f8450cf6f1d93771f83598d8f7b8f50ac0e1a3497c92ccfb8f4eef0a2c07ee449fafa8fc56ef0fda4a49ced06aae1c82ce3043080a8d06ab10399ec3592207327d6877b271dbf9f49b287d360a26acad2f720e1444815111a7f9b285a91ca7e8108773de367b395d616508e00fb0fea2a2af73ab1615c8435833e2d980d5b282568e62c1ea026678a3168741afde56dd65952979b0b57495754c2174a5494e3c44e1559c411b5325e948fb85a50658d4b2eec36d49a4b152fc5861b777e7c63c689f5aef0313f6e2df084af6e0186a23f27a8b4a9ca59ae0855808b72aaaef0ffe12e76b1af24102e0a2a6c1224a2d77831169214a0d98506ee797d2cff475b119c714726cb85dea9b58e770b6697ed27c9566a07db8fffc34587f2ca1adc5e308793cb32d11efaec825e8663951478fcb03242344d74671d630a593a09d5af4cc86fe0e4e3c472c3d457f496bd76f8de8b0a8fe89b60fb9d77de18fe9838eb13e9fbb4b13f534fa56430ba10d35fe1d4e19f2cc7b51f3e64f7f516f95707bb4f93a1c6efa7f84e7dbdbcbd74323fd16da13607bb60975e6de24ea03e525f50edf6188c9f96e541e7a2de62680d18c1a86885c1d16d61ea53dcf3959b1f183378d6c54535ae80262bb1e8a0c9cac95feef179d3bab984aa6507daf99f272cc3994e363396054b92efede45aeacb023ecca15f17be01c710a154047e54a037bb47079deeb0ee8a9ee36f51118e423a074f76558b917837f792f579c0da446715ddcb4331b3e8fbd0204f6029f3902d514f73134fdbf9f78c3503a3025afe683f20af9df710a8a78dcdbe32d896113339219a182b2cee82f434934914d81e2237e38ad0d5f78af2aa786f785964bf709d4ad859434b8ab9240bce11ff0b56ab451b4bdc92ccb6af82db6f44937560d7b57a7d77aee2cc0482355935056a51407f76bb3e7bee1542768ea657a66506eed30a39421a5f9d7b27e2a9bb68dcf5170b805a641276db5b25ebf3376d71a36e865af7d846858d0c98b01b2be594446f9e75c282538a317e17be334b2512d1a7ac327fe77f4121ee0cc4d2e2974d71ace5a44665bfa328153727bff3a285e50d35faec6d43e04d9fc9bc1c6addbdc2f8191615aab0ae6947dfbd06379587cc725f755f3871e50228cd7696c9de6592653cb63bdcb706bede5a14d2cd58b4b149a486c45c03e05d997a31de668312f8e2cfe741e17c76688cde6c8c4bbec1e07e41192ab319d68d62eb43939f24ade57da3365d44ff4b1031a02d47623381e3bec59b79c1cea747cb4d14ffe72ed7a4dc700490821098e5fb0989b8ef3fec1e9a822e00887ea726647003f248a797dd0820aacbf525897c10a6bf2df4394300aa208fbb251c0bd7817fb7b010daca79da20cfd52bf9100386cf06b03d79e34b3a533083bd51f9c6202618029c43476b875184b34931d07e004ed51ea65bdcd23bdcadaba9c4b9be503dacdb4dcc91c0751d0cc8840e49175789178e1bd75e9aaaa40fa9d80c29a61c48f2a609e86be912d4e7ea89a67e422c043973147f71be0eed4b0e945c5b3c97e44d3109aff81a0176afe6047e85221dc007c35c95dc868c2b3c74e3f789fa24ac1b29f50b7efaf2c490b86579b08fc58e0d3ee3565348c3348e075d5921d02940c67d7c154ed64ef2366d0f36999579282b4c7acd6c41136860b7843037c02751f55a81f071e901d0f84f808bd9242bde82109c324d6f31888d93129c2fcd6e4165576d1f5c067fe5ca88354f18805716709731aecd02b36c28de621ffa9f6146abe99c66781abd5e59120342a6a9ff38610d37e78a9fe9ceddb3bef06b25a0edb5d79546c57f53f3050650ff66e4ea993eae34675ce4d152358f8c6aac6df6b44c95cd028dff78ce485f9e0f9f85c2a9a9fc431b253bdd2f92eb28d8d040aa414ff29f53d800d1320b4da8520d46363598c38a17b0447c75ead05f98dc85b3b965708a9506580b0628a6e4b5ea135ae1ad2575d8f90f9b5a6bef5ec9a63c80fa169feeaee01c9f4616ac50abf0363a93422f279390d2c078aee8c70f9ad69bde578f0a565e3ab267e0fbf1a9029a91addf755d0235b1948997c59582c3c4d2fd0b818b2f76cd8fceb4e7a33209e79cd4fcaab222f554a798d4813ac353b63c905a67a1499e9030ae73e9ae94faadd68721a5c10410a4ae6146c48f0ba8fbab4b3ef138a6d0239aa0ea5a6793843e5ffebf66371cc6b2b8a97bb10829851c87a8bc23b6cdfa72551541531cb9177a571af68375e54640b3c6a6d46bc9267c7c009ecc2d2e5f7e7f4899655eb752d5deaca5f80367f59c35d213d49f403b0ab2db2ce207695aab53c4df7bc3c281bdd2253d4e83628bf95958b2b2fdb2300a81dd18fcd142e6932fdfb2b21378d786e2a2ec452317112a04018a3b46779af628198999b97ad3d1b61f867b368fc096073eb38b1a0195cfc2fae4f3020c52ec81d886e217d9ab47da0639f0caa2831027fa806e46afe2c0f6e36405d4ab927e8db8e5ed93f3e2c6afa871e10af854fb18123ba9e4d0aeef452c9996b8e545132686cd000a43dabf2fb9a1304dcf5b4834aaca47e6897c01364037e058206bfb14daaf4edd93821c9b199684e5405c9c31a6970a75116ad544067b9508c7c4c4ab7d8b37c413a2f836f65869a0f92095b8e19761d505f31bd2708500741424e1e95601c260ebf7827b962f5ebe43429fa27914db61474ff08cd98326f79fbafca230c274c4b149a82aa3d5df429a28a5a7f9c6611f6a1d3e0fbfab1a74ccee5c4aa98c8ccc0e1aad093f693d728b5576ed54f43373f031bcbf97eb5b114d0d3241b0df62efabb91c469c89a0b8d756cacc5ce0c51566d6cfc8b0bad303195d4595d7275c11c16061a81d46b68f948d84ca8202f27f848ec8380589652cee0a3220f9c8db4af44cd4f8c77a119a9c563ecb30435d9dbcda3e28b1e1c3f5c40cb676b62b15ea20e8e27ab8cb3f3c7f97c67260a8c18b0eb271e93de9a3f5313e51099160cd7c1bc5acfe434da460ef974eec7868d87994b591a97d42d56211556aedc1b509822a934f9af052d7f9649fbff348c7f81ff6fc7a07b5c316c6946873743d20aa26a3ef475e5b03c0884ab612d91f6cc7c4855dc2721d29aa28ac7f8bcf3d7833611e323131dd5e3c284ecf9d4d46178ca7c97a0693ece9da077a1dece2781929f57197003ca95e744ac3c2ebea3536e1097615f0c4e9f0c02d0a058075bfd796d3e0cf4eafce271b4d57aaf8fd3f067c2daf6cd0e98a965770f136255e75bca99a2e791ef761e4d392797fecaed63f0e34f574f0229a6c43351f3844825ed03b8e27a6fb2ee21b1497dc3d8ae11dfb3b6ae98c33acf9ae6b016963af20f20b58aa40581a64e3c8b181f4bb0010f246f1fc06643fd7bebb0e0f20539028c07108391a86e1ff00ee01a7dc7428f0d79e5bbe4ea55f788fdab0aad2e5e0edd2f734bf13649a26479dc42d9accd2087efdacd7a8ddd67a4fff2a1b1d6a59a3003148fe0c2b29fc99181ae46a47e39b2832b5fe635fae62c4a46d48945a9d40f8ed002ce70d611e9e3461eb7a2419c5bc0bc20388b940c29a2a09887fb326e1bb9ba880e626d1dd7f70421144db37729623fe195550c5da006ed3c00346cf8c7d2362c0d0806e444420e6447100e984b0f78559b0ae8edfb1dc39c9524554d35c4cc62b52d12570653da665dda6ee4159e5f1b0dbf63d7d064ebe851a409ce202858d45d3a0be97334183e1d9268630de5a24126f780bb4cfd926feacc378c6886de0b37bdcec33cb5c57e2dfda840ec2ef29f7d85dbb2a324a3a7b834b35f761432c36469b8fdbb773e4e87f06f7cf2e262799938cb1828ab11357202cc83ceaaa2a5e42b9b4b0601dc0db060fa1ca4c2988393ec1d6b67b8af48bf7510a4c200a7b14850b8152c77e8a1c2a087a1e64122862e464d4f13b1d6fd59c5866da29fae99defcaed0d1e65dc77fdc4a3bfabf1f7c54624057f9b820b6c499be1756abc02162b92eec24109a58f79b495dab5272ff1dd69433f99ebe44eb4aed6f8c4015a9c0431e0499066eb2239aaf6c338eca122aca35bacdb7bedbb008f182291adde0992269dba11e0d011a4700984a3354df803eab4276bdad2e3fd4b14009def788a230a8d8c1f0aba40b2c6611e5b6b4a52064dac91480fe0bf4bf2d9cf6ade3a87b97a1210860b87a1771ebc1422c5a5ca9cf01142713c5d1e30a057facd00ab78d499f8fa78da43dd3cc5078d8d93788a6eae4a914c3661be3f700a574fb76fc23d01bc8183cb41c07d3a6facc3a25493699f6df216e7ba0c600da9b43b5c0dcd652be763b8c8e40a00b7b6c54050d1ef4791e569e028f2009e5c3948631d77ca5b847a2b290d80806af4a92af7a83b9f85e3ba6aaf73aad62bd6e63264fff1fcf9be71770399de25fa5d3ba3291e4d49f68e7e2e495cdc3eec55b848c2a49c4c321a0d01122b17da0e49711ee75a2247a8c5ae6c06a4683584032df972af5631db2acf7c02d7c39e8562e928feca524bc7e2dc83eb6cee630d7be96e7e2b3ffffc2c08d321387ec4117f0dd82e5131bd73b96ef557a81f68bc3d211e96c6232515a7dbce1e56b06c959d26e6547145d15599370c55db085d5bb30075b3a8424ef9b19c9501500f46cb8e2a402c51081f0a014b2c6bb945ac4f3d78c8bf798dbecd0680216c398f8dc2516fb528cc31cbb59216281cd357a077f6407e2d55b1ab5ceff7443046ef38fae4f87ad897e8fb8f590de64414ffaf32b38ad9584e2ca710bc5f0656e2a8eaaa55a5364240b1145abad2ad3bfefd775bb068db531b62b2c1859385160a2a4ca7de8341a0fda0bab3646d602be20057828e62821ee25b6898dd38808915e1d2473591feddf05c2e5994006b854bb152cf022ef1ad5b98413490eaf30477c5a82755d778f5bfe2e00ce5ef4c1cf241f323bc4205730dc63bacd0f655019f0998d0c349c0eaabe708ded31811e6bc90f0cc739416109792dd9ddc47561aabc41e050b5f6a2d02d39273e72d602193a4ad552722444d414ca7ed72fa2fb8fc5f69489295c0bb9b12c2eee4a03ec2355747bb68c3f971a8235d10440ceee2dffbe2ddcdfcb576f08e9eb43f0c8f8c2e0b015014453d323e6d0ca28ab71b50019039f03bf393b10e1849e5123d51f9ace41cbcbee0aee047cfdbf94795d3418949854ba53369042f468f77a46d17caec59e368b7d1b0c064a2694c4039af2e308ba8487056b7a984b401a33bbc56176a89c0eda1c2617816abe46ab5e75efbe915fd2bf8be408879de4af6a4ac275b1b6832982aa7244e0c105b03e3758889b46b9507b45cc9f9459dc4549dc3abffed0e26a06b15de47ad8a8aae2e5949eb950a60a511194a389cbd6881bbcd1f6c5e59cb7a7f35c2aef30f2ba80714ace5484ed2823c96580645ebede1d9a191cdddf21f4e83374c5b46a3cffcc039fd3e5359866a33905031556ea815bc89ecb8ce556c90a4fad015b9848c51dc93d7584e394a4fc18adfb2da1c829169744e1f746a9e98ea939f6f8f4608f09c65b57a3a038f26ed3eb79ce12f6c6f9fedad83d8549333a727dc07ae4ed68080eae38a4a773ee8fb4885de48c2114a70f5a4b2f39b8d271a04dd3bef83f0b065bed2321855122517dcba99a43acf53354441144709fbc3f5c0a114f1b0e45a5be2e2115c5b790c36bf9c753b28b8e6bc2aea36f3ee57bec480eb033ee85ff36e0a74ff5cc829a85fae9a8661378baf236b55a723b38ac54301fb3bd76147e624e0ed05495cab637f1c730ba1fc0e864e09a41e7804de371a20002d8974eb12b02e46139b7ed415796d6645acdedad58a8141d7d42208daf7aab00ac187237de3f268203cb388b9ca203d7151eb6f20eb23a78b84055f842829bba831b3c58e56325bac0018a17ee87fa428320fc322eb2ac58a845deaee786299461a5196ce3ecd4fe8a3c9748dc5e7e2d2b6aba826268025c18326fc9f344dc435cc0bf64ca798f7a5ff340e5fbc19cc739fecd1156e2d9059d83b6c18de544f4af6b3df5bee705e0a9cdc04c5f502fde150023e81c68a63c69aa9a1e69e0aa5056776bafaafc1281fbd57213a1d651499b70bf50619eca6e3b979391a5e33265ec8c497fef48a99be97bf84b1e51ebcf4ac2d675cd83f7da3bff4c9f9e877e7a46e08f386bfc156c02f6a0e6166832a5409c8b36d4b1e7dfb431ac2d2fbf90a691962989713c00f934d247ee76a85b3a9427ba4c4762816259442f0afa9f14136694889b640bbba4cc520ff7b321192e41c399c128620464f0ff0746a8783d6483d7b1a1e19b6b4cfb17b71d89e88ac41111d34fd9038bf8d1d1a5c011997e56199da02c86adac1c7e40640983cbf25452e4b786be2d8377b21f1453603960fbdb0937c5bdb367bd3e9b8f637e10203d49b1b982d1a794924961936bcca0be7cfa744b155b3d268b52e59f45a0f04699be4810ee5a346b4f12c695aa4ea7dcc47e9f82b16efbb99b14959ebdef1a28133e24692cdb5b1dc1070c490d88fb6e962729cfe105a6614f313dc92c09bc210b3dc789f88bfa3c629402821374ae71f0d88967a60948906662e5cfce4ce0b79588de59be046ee2228f736b290200e09ccca9d546264ee22b529ce315a8c6f1ca501ac3c70cc5a94cf29d945fa1b650fa087c03a44bf8b56c30fdd12be225472f2215711286c762af8b4195c15c8af2db3bc74f345a58fb1d218e4dfedf03737867c15b9a20870e04a9880c986e3ba4164e616593b83f684454cbd40c8b980414c36ca7b056332917531c6de2e6a46382c579dc7c35bcd7d60540c18c145a069265f096fa4e6b0cae304c1d9062ae0661e7d0359f28aab45a8a707726065e56006c0cbfef8ff280418616f6a3ccd60a599e671dfbf2fe90f4eba0811f0e87de0d3b4f3360b51204df5ba063363997f14c3bdc5692fd3e4b93f74fb6943e76ccbdc577069e7f9dfd9643ca63e094ad2acee0397067befa0e88db334d89ce28c27ae6809c69eefeee5d6b701b1b8242db213eb63deb5aed4a5d39f92e991350b7194c2fdc99aaf43f3a67218238436f70c6530d3da86f2af5fcee1a7a275649de25faf24c68bdc416c84f4efab28ce1915ca1679880825dfb3bb8154a7828f94456f0a137d16080954efb6cef148c81333b7cc7aa0515c658297b303dcfc633a2027e18a20b260299cf149dc44ada823a094dfbed7b8f62f71c5e89c71a354b6ef9f86d58e2070a39819efb353aad6a430f1c73cbf05f2cf8b5e9e34db574ae0dac04616c8d4951ed25841c79bee84f5acc93c6dfb168fc56103ae73b269e94d7b8b21beec0441193055f1a54b81c7555dfa1ef9c28beecd11a568472e454549ebdb2db84f1600ceeaa4fb0e520cde9e7f7fdb2287c93d01282f68e3ff861871842d3f901e6419f4a60d8b097ad377b36173c2ecae56c46b3d7356c645bc3787c72190a8ac75b7978bb657224c38c9b382cf60c1feae279b207bd51ed2e54d72ad4e2483ae4ba5eb1f421fa579089e76b322d60f15f831e5799804573f8c55471ff83594d99a2dab47c3db8c91740a9209ae4143fe781a3072105c4718afee3f2b05f4c6b9f95d55ffad9cc0f19de52a6b280aae9036eeb7ad16ee175e7358a1ebf6817a2c3f454688087fd0dd34208b0553ba1203b36c8f62943046dc958f57a92a7346453afe17df4508ab34c7945842755a0343cd6d6f4c0ae567e568597d0e68d830b24bc7022a802097b7a296627440c73c0ca2985575ad99dacec753afaf4ac2346648237cf9fa2f979701fc91a1de973482eeb82cb6da3b0490583775df4e5c285e6dda381fdaa0c2e40bad957004e5d9c5e470b87373124b0229d5410a8a4d1fb3f3dc82655d0941cd8b1be361078e52088d7660b72f7432c272cdc64a21be385e64798f9d08c05e1d0e30713525623ca18336eda6cf2de1c7a45000d3ed2c106e8ae752c202e2fb02d01ea72b2a2719fc4fcdfb0adf871d34dbc20962c65f004e7a988de62bbd95e36c3a1aa8bf48afefd9d9a4316c9d58bbf591d9e3ee402f8ca541762e57d63e81cdb2e058441ef358082d893f8605ea27565c6624f290fa176ba6a6e44fa2718ea8afbfc4a36e2eaf5d0945d7956cb6fdd0b505b92960b719d1b86f5c17bbd8a875f5a1e62843267c063e722646888332c316c1e4bfcb1fa9071cb63070bdc8c7c89dfaa719772c520a98cd5669682b04d12c76b44f4ab94c62c2c513ccc67f545e89b29421361d72a73afa5d0459c532dad2d3b82bb993b281b2e982d9a75e2d1289454970e98bc5246b279f7cafe46493c08c0a856a69eb731a41da6d271035f115f51b6d294fd4ff0c3e6d54cc5a9cfae8cc390614bc1afd135a288f637759af7a488682b36077a21cf261fcc60b2b3d753f20cb41a7ebb9536903bfeef5a68b405df05092306ab605c70a3500e2cd75dfb5bc85674b23cb2a97ae16ba899416c5aba24aa69956f9a2e7d83a02792e7605e330a71cba5c6b6d18891a243a9ba3e3dac5b56aef839884d295a1f637685a50d5215768eb2a693ab015e5dc94fe86bc51068dcf68f331b4536e8135656cfff71f02c32d497a91981514ec23a11c30a5929fae1a5301a91e632f05c024d4120ef6c0890d41e6810099cc330e9072ef28cbe14580575163f9ba850a2b3e30d1a2b805dba5e5f9045ba96a38d54efef866e1306e78b3c7aa4c7f45c70bbe7cd06d6a3bf99ba6a340303c05d3142f92ba0c0e7128cd41d93fe81a3ccbe6ce36a40b1fe705ac63330db5ed8cc276b92d5aa33cefd28a6288256d419e57ba91f9b263caf2166fe0b2f429cfc26d3e20278bc1aa7cc1e0c0a8c1d270157b6f4df2a1de2dd7a67611761d100393f83885181106732302880fb00dac5fa94ae872703f227c9cece287956bdd1ec785e2c61128369b4511af82a356b4127c7c17b9cfc4c9cd66ffd771df3cb86e83e9086ef0309734cb2dee1d58633a3cff734375b6620e544c53d9825d6267437ef16ea4eeacc2b5ae50459abcfd05f286a43d8859ce8a3afe3fb88f150755372a297f34dbf9ab06ee3b4e0eff6eb5d96cdf9d5c23faa57272bef3a55464db02d17da484a13d9fb4994071d6b0a829c879c245ef971ebdd9194b5648ce036d25871c8d885490b682dc3b1f61f30135839c475766dccc3ac4fc9cf95edccd508a9329a73ac2498a4cf0bb4925845e1bf69abadccd821bb34f70fcd5162656506756d251d86b9fa909cbad72b0267b737fff7ec371215dc6fba69462a22b0d72853a5000bcaa793f1e378c879dcd57084df873b14b187bdb4f04e5ffa338072dc7b746bbe3ed6506e82eebbe2af53ca91e9a3e161351255ccdc9639709baf604b4be293a3d5b33ab12768190b07aef069d204074dd7a96e5d2bab958863e2a522ea809a7d09f7bc84068ad36b7c2a7d7b5b28e4532b5e9ba832482521467079caacc7a03915d3c420b0d5821def9f5791668f403f662ada6aaf09727613ece2108b3a3cef543f1ce802a282d137064751ca974d9c72c37c50235cfe7e67bdf3fe5597fad9f388ce63fa4b618f09b64b8da54781aee65a6fc9dbe3950e030ebaad5a420b2183c3790af5f4a0c2f6a478c20f6ea110f9e1f15fa3f83e335fa5a2f016f432e65da806c2fef6a3d58ad4de617838d259c96d0cc41fb0d699376540cac2e193ea51c65252eba3c0a9206d05b291f5b3253c1ea7e32cca03908a504c67c36808325fa5e9c28fab332f3109bb383cfba34b39a0b61ffdafc5cab9ac33b3f0d8bbb64c347f2a0b884ea07c1d789d8e1cf756b54ed17217b8f358c5b36aaa48f0ad3645e094d98f266b7f22f9681e6fd4093fdeb28d8a6006629390ac817d1290a08a7bb55445a3996a890c7c24118387daabe94855ab95cdfe34952c5d9b8c9254116e2c7a60277555d5e265b34ff5fc8831c27bfea7a7eb6f7ef41623f86ded6dfadf5ec237fc206c0c56a042605d0feece8bec4d29e1ff2c5d2221d6cf5012a755d820e142cd6c5c44e0766476e3d8ec5b68082bbe1da038eaaacd8ff40b0f9d42e6e0eaafd2ad373303be948e8b18e9edbdb299f99ab2079688fda08df9d1fdc3953717fd694d425e827565a18a7fbf8b37c3330c3ee92d057af7c90e4e850c4b2b74f90c51745e86e035670f70198a5633fe1b9f2687084da778e3438234d02136cd212dab191239c0196ab0b45308fc7de272bbdc237dbed3b82d31502f85642f17b7f3a349521f9a52e66911e459fe65d7b05a93b483549d4e949d5a53567f6bf5c5bad35be54c588c1fc98a45541f2382f00ccd82c2e5c88e055c0ab56d915df42363b148f6b08929e7a85391742ec00b9533e4d4eaf637c7db6a993ae912ce3faa190d46f5496e358b5deda07d96baf6622b597bdc5aaa3da74645cfaca779e55b2758005894c6d0b0c14f2cfa3ef81881721da6923d4f90f006324ede7c85bef5c3571061f79d396c3f1e1bf44f09061996e213d58c0fcbe8b69e71395cad8041e9a5abda2fb01ea09b3ba8719ba85c6008c5a964100299ac9b6b965b3cedb01b40f7a1909430225f8e61689b7ce050c51d5e2abb10364c802e4e0c9d5600d6758db62fb8116cf64ad414c1846e76c8480dfc413f1e1e30c1de91f1c6b760d60c914e9ebe4a9edfea64c05dae081c92c189e0ab27e5f6a20bf1153d3245cd0136f8ef1a8018ffb0113b6263d63a836b782ca4d0424df16a6c7e384d2199e90f17c6b0566866e25264ae80ece9332883e4ac5045ef30a0e7015609a5a73330a9c87c5ae155eb285d86187ed992e8eefff799bb6105115c61b915447c583943b1045026d287a4516971c5f3fdef651f553b0e6608d74360383cd0bcf78ed33057000b572e63a62a78b18cc7b8f54500af32694b5e1768c79e94a951ff4e58af1c7fa5eeac8aad1487febf1b61d94fe97e271125843b23a854a731d406602d78003e85dc870c486b3211509d18771700cc43004a6e0470081b7f173125e066e00b78d260a7ac0a2485ddeca399487382868db28fe042f846d4fb002595b862ce2eb8aa2bfc08adda708a392cc2f95840c32726d5469b111ccb546905db5f88b08e95f89e475bc1e9838b16201a88ede2ad2b730e41cc2128bd0ab5ea803c2d128ab5ae6af69086da0d86629120182411b0c0ed53b652a3ad626e9f9c0811ee82ae82c4a0af2aa4ef664a0527d692d96287558c815aefa04c85a253348b21e1b3c1e2cdbd8f8be4e720a34bfcfffa2cd18d4ac808f6dc4e66860ddebf66d5a9a3f77a18f194df5022e7bba58c48e0eda42c08d3fef4482ed84857bef56bd2592f4b4f387198c6eb4fa645be7b2f11ff4f1e1e48b16524a5cd5886034cc74212b178a84e59f87538823802769a886ce18c4f00ad1b3c55c6ed5aae05b6a1e89f8c7356e46dc5445f0bcb5b8c9f0b88887bcb1905744261688923e2d81757672231c815a0431935d85e773959821e3dcb40d2f2e89a1d8144f930636996abd4131caef539f24438664a9ae22dfd9f0faa29ac222cd36b7bd83fd84088dc9f25e86f7f035cf1c934d85749a82be2954acfd61bcbb2c5e0382df1b804bacfb3f7d51babb43879e5fea9dc7a264f1fcefe79b751dc25420a00e84f1338415a01e8ed8761b68a2fa901c47023da4b03ad1436367a699d1b43e0d6d1289f0f428253c919da4313b19b05cb19f148674533e19f330e1b0c6b15eb8e14dee556eca438a51cb195a0146f8613f0173c03e2d5c105943ee559e2f986dea6d10ee70f000aad7fa0023c860cef59972eac15c10d8415bbf848d512c40f15c841dfa40c69f5caf42840392f1b023ca52ddaa158fa2db951676463ea8721cab526aa4757ecc725edd4bc35f22c6796451ff8ef0a293e06f9718680585f0d1799d65eeeec02d4e6f10de24b00a12fcca0e21a4e32bd82cad6e57cf5377365073b3904d5459128288785ed72b5f2e19a1c35cec195a3f230506788b3640553ba0984783921f41fe194feb2d2d82dbf00a987d4da2bf7537f8fcb5a43fef5af649fdf4b45dd004211619581bd923db446c36d15a2e103c60bb9fa80cbc2665a80493e4912d0cd1a5346a197fbffe1d2102f6f584dc57f629e4660067aa0677e1b68b2907582162842f6b0749f3403b13dd9b16640e8fbed82e38ea0e2385040d82e44a8706d82175e81543b9bd033eaac83a2cc16f8942122b082c5a3d95304cff260e043240a0e11b6a84e05334398005b08a48474791157248e3b604725709fe4639ab3f2d5038fd61f2f8f632e2073cc0d7b4a88683768321d166ef00b90154a52804bfaa901f1cbf89178507423848dc0e33f3b15b2e363cc0fbd190f80a5bb2cf19f4a130328b14a8a31d0fa07a8822ee0834177be1cd428c4fc23df024ac4f8cff6a733408bd8a40a87d59fa28545bfcba46bfd80deb8c229e581aa6bfd122fd082505cd9cd830d4691c1ec86cc4b5a6428e6071658053f0614d63af65dbd1fdec51db14f9cedaeeea7cef44ee62f1a3aec77939e586fcda1f33e0efaa3af2d12995cd6d891085d224a967eb0b0120bbcf9819b72138dce8d66eea915aecfa4582a62336b78216cfaddf0201ec871706d71218242f967ca936ab86b06bc2b344e9133d04de9db20af1a01e81dfb6d74540e7311f352548a4c86e221b07eb7556ecd0063659a0a50287270e24d0cfe50f288253b2066065a5f7665b8cb8df35eebf11b53e8487594b994171ef96862dba0fe495f9ddeeaa37db03e206fa8e8d5cbfa53ad27a02faf570283e8d7ccc31df26665af32bd556a2f4886259a25fdf9bd2b8b079578ed90192b948c4950442388f70fcbd9d6f93b0309ba038e71705b6575094f1358fa2436302b1db1fba0cac3355063a416e737e0b5b0ae5b972b00c17df26294b79486a047de14b8d778b048209108e6acc6b782b308a682672a2b1c74d028e300713add0d36ee7af906c1bcc5e6d3b91d081f27185bb9d61d905a97e7d28b336a2fd17430f4b025395e03d10a39e47b34a5ec96bd19b95914b042ad64b08aca5bd17f66d77e7fa312b812386a4174f460bf87e4ae49842e75db50363053f01fa5f10371e99171a83e0a47d31b9c569b7717da75f25c494fd6c11a3f339a04b6024ab74a1a784592873aa9ce6564307f22b30547ef74ad4051144b12cb930e448d7392850c8c59a58d4a6f2647f5cfdfa34af70c668172bc0efb2cfff13e38fda90a926190c4daeb42dbfe3f5bc5b8da2f28fb03dcb96396ef43f084146be64482eed9409dd088105b237af1ca1d7ea21f50ad4a5def20a3d2c361b6e1927cc0f7ca02be4107e9d1c55949211adeeb2159ebcd12890541defaca02950989f3d4cf1924ea6c19d9f1f2b02f606c8fced0eb1485fcccdf71abf9b47841f2c554b68df1a75c9c75da597035790c5d8674668293a6e58b3c3e9be22a49858d004294ebb444d838077db510989d73f0c97e303ee72176798d9da0d088af90fbd8ef9c8b56d508cfb333f103904204e747dc446307d2770e0a7e8f4f099b19f40a26a7999fa593c5f3c6db1939fe97a8034119322db2ec845f33d2ee4aa7fcb8434bcc331efd060a718e6d06e03081c45185562565d9d8173edf84e510b6c486395203b915b176e35a5ca9bba2f9ea2563bb2a94b617421a7f1cd468c3dd3765f58f6764b07dfb63f724ba871a5444efd353fb0dd99646d4674dab0fff52fa3cd603b419619d58fcb5e6331cac53744eee84a2796846639d5a79b0c60437f8c737646976096092a37c46d88b35a48d887109729346923419203b87754c6e3eff8439f0710bb40bd2af3a6e42dbfcfd5682be86a093e9c35ad3bff630fe9ab0faf6b80c02c51289a8390336665f037b01b4d6ab58e41ed9bab23028db2d272a50b4d303451a488f4549c0f311493df91ccf0d7a84d482d85ba54971920386a458511adcf6140c61e252c38d5e8bf8be4edf4ffab80af8ce31a0aeaec513016d96951360b4c494eabd94ec8ca98060f58ca05140e5cb7a1660fd894234581179276596f75f89758ba9136321ebf2905c4d09a276a41392fd93383446d4ad04c33225c21c5caad818dc3611c0fd02c98dde04f535fdc738592d53199c3c5ef7ca80f9d46c5e5c31506fa2229048528ec4a9a0e9418322777e9b1f027581318c93b26600d3694f84a658718c72f915de3821aae0b633d1326fa9316283876a5f00508b8490f7375459e009f055a0c78615d3fe38296c90971d635485b2a95dab85c5366ef9e21717eb57722a60a4a6fb2b947bf51f9689d83ba9185bd53733eab25d4a6a87d10b824eea291d172009fca1034d3941bf85b60d5969932c111a321c8f03ea8872f128344491029479f55c462f95e083f393224dc52631e0786cacf26324e96506ff38cdd88acc220a98fc1a4bac3c4ac4e128dd21a5b80f9861fc7aac20bd2f220d576ba02915277b5d40a43932304f0958bdde2cd009e019a21be7816991d9702a2e74d0093cf139cb894b148326344003d96d082ccbb28d392f29fe8456237b4970b34102f02a59a22c7265860349d6dec468f76e425c3529da34800404b0dcbbfb805183e61c662b51d1a963417f0b243a97bfc1656c018a875aa14f6ecd35f75c38527f2317b3c95d3717920bd3b1c6bd57cec94fb05c088905ea37e0d1a68bdd24b36ef07c62d7652ffc6cffe980b87557edc6b66efdf9804e8b461ea532fa859fe5e643dbb18ca5eac7b72d81c8334fc7c2ed24f43fb0981b2ac8b0fdc418b1084c06efe918e5c3b0a5f8762f67c1a96afebad23e4dbaeef8251779887886cf964f5a82dcbd531a216810a66a1960bd828803ccf5bdc9ebf6bd4806c2e47dca6745d080e01a3c0cc4ea533c39f2495ccf172947b6c7060ca3381e621d99aa5dc4fffcac8ffa123958287d26f4216238667b3677e2d33b93cbdb9c6477a1d96afdf3a2226b8848042944448f3c79f7702d72d5816d409e3a4576213d565109ceccd81ed9725b868095cf088c5efcd589c410dac3fcd3229bc2153169fa8e8ec1979ac23db48623d9c5d7b9148b0b1f89d8f16a27c9956f11b78729fb92c275c1ab0fe407d1a714a3e2ec53990e680584a096d141ddf46413a1362160e0bf6f01f25f2c5271570906678549873e8106632fc605f4560419019969b67ed92b59f9095edea50e5c363c23d90b34834c37965737bfe019cfbd45c1e402d8c3c0c58aa8130f3dc44359bb0e79445c46c2172e51928c958867ea2e9fb86ee6cb1d778312eba3b90104d1ae6355fe1aaf2cfd96c37cf428b58b17a3c0d5a5c1fcdc0b119ab6495a52a93c42ef3fd7052bbfaeab2305f1751e3a1ea30c839b215de1c296b263968f215d3f07b96a281611470e95b713c23ca2cf5821beb12ad3108c65c9fb39116f2bad605cae740b57da82fd648ae7bd4f4c2ff2c28b37589028013320fa7b1e9123fddea01059251b10e6707cfc6374dec8f29eb17cfa1ae32347899fda3cdcf6020269fa51ad8dc7dcf0ca93b3c3d125dc898ae419cb1ca291d3e79b22b5052fe5f7651dbfe861f9b34db28699740a811c86faa8cc851c02d1af3c5a9fcbf58dd0a7f1324be326edc7dadbdf41a893a7c7b2a9efb536c4320ce1f8d2a68382a1017b415db80c3017d465f8fea996390061f4a93282eb53b61c0587db114816b4e729aa2452568e53e337ee261ad683ee846de25957890673aee6507926273987be2f33e34ca224eacc348419c66cff2dcfbb3578ca79d201a4a7437141a7cf8c5ee05b38cf18964c03ef35f635d844f1cebbaffefe6f4602aebd7322171bd9c29873b47eca821d319ec9200f8c0a4c6642e6600e6548a1c4711bbc8a7c5cfd41db9107b6340177beca69191dd8fadc60bc67002884309fcb94466c29d5c4478f0f615f481c0e25b70a9ba419cb48e648a74f5a6544dddb7484cce7d8e1a91ef052e74787f159722a6ce5a9bb29a340275012ade2e48c44734df3c521e6cad38d21eecef99165caafeb8ca9c5bcd4cd29540b69338bd3368a7245ac8260e72fff2e1fdb2a0972739bda006c2ded49b29e1005e75c4b0e4d56cda12638c9fcb1d756b039b3484b51175aecaca0a3c14014fa3b3000f8187a15de52a37321e2f51f7f9f43c1fdd4de2d48bb3891e83c6ee242f58581f5b68d613dc00ae52320cecf3819ac5d130a073e1504e333624f983c1b313e9993c6671befc4288950407bd9030063c629337b1566ebec50c8d2ed6adc35924f44baebcfd8b31a01be8af4d999fc8051e3951e1436d684a8d72ccd14400c183d11c1773bd4b2e48f3514db84f201aacd2bf09b053ab06180007f0f48694064053cecbab09132034870a8a81af914bc4f5ed94d6b7dd6d86af62dbd81e617d0185bfe642923dd80f4672a97cd68e32a3c8dcf6dbcb8032e85f4ef868b840f61e355c002299d1a20ddfd4c0f6dd7d944455fcc14d287026bae859a09f42eacbdafe2ed683468526748a7c248a93f7d53768a949fbb4017e665a490566aa19ad99a4eadc711d7842a8dd0b8924245571805cb5459d30535c6719f73377609de49b48b4e4909e06fc38876cba60ca7582911c603f52379e076499337808700007c9eb6044946f72d5759265584e2ab04350cc15802348e56e9059f40db812873e03604e50b22ba87b6e3d1b6dc9cfe3b2378a33c11f991eb106a06a552ed9112d93780adff31dc82547a43fd20f24a1b4183c803d1048e11fea05492592ad26418445933e890a2161aa06140dbc7a9e86fc645ac579d338f5c2afc07af410fd5c9af2774d2a754079657e270f2122b442afbc6db4f37cf06e80246dadf40c258d0161d5e2e9f8c639d991bcbea3ccfb736c6fe8dcd652a864359d19d220d9968b48005163daf92b4b4df7c72751b78f367e0544ea4dde521e7160881ccb9052315681909265f83557cae4796c618f8a711eb4347c1c966cae38e134b4377b0d77cd7f6e233b99cbb179697da0ace294737258107467eebc0f46de20d1b39bb4f067250a08fcb28ae49e776931cbb28facd72b83006797973d7e7c641546c0a87a03e8c09de9d3a95f67231a1533020638994bfd137ad9d39f31b4d314b4f5121a7db997886c30b7c709b511cd3673e7298de712dc1ab3d34782ce4cca622e19a4a2130db6040537ce5670cc104958c8eb5318848b11a1a6959617ec35ab4be574f60a816955547081e5c1d1a0f95c69f32f9134d1e65465073328e0218b9e12f6075fef1a8f219132c8acd71da1dc32fa85c53a76e22b6377be326bdcfdc9e46a9f494d64d58a9b08ea84ac243e1c7c942a84afb5ec752dcebfbd00f9227e5ae9d6421e045b35867975f88889a3e8005c01ced967896d44f9088f863f34811311825b15946190a1f60a0ac2c2170b44edc4b536eec5cb4a751e21fe3f2d9f2b482bde30a7e1fe79d8466e7455f4bfa53f57b83d258f0ddf422a669167b1122b9d8936327545f4a607421304a45fc4eccaa43f8130081f548e9be1e95e69fb25be533f5d1581ca6f08e7284b4d8181208f9d9af416c58b953dfcbbc70238c6ea0e0f4ca082da9bcb6d05fb83921dcf3b73f546522a8d6232e6bbac0c901150cb305c348c334f35451ca7fb733351cc7d78b5308b650fd89b2e8ee74c9b28cb427ceba8287bfad080ec0efc922222fae7c7648eb2302d6d1125deb4c12fcd1651cac791cab2658e2b6bf3c1504aef737478efd380d8b26fb4b476a465ad03984165a15b152d81b5d37d629fa8857ba5750e3664f621f65a812221c9589148c05b3a7fe27cfe7c0bd75cf77b104694f0196658ab5b98e3d9b211d5115fc9a11c0ca355685f3efe8c0fe516afeb1bdfcac77b0f37c23733254d08dc8bde35058b2025a632eb6095cc20ff7e994e378317749c405b88f19834f6282435a36e91f8f03fdd6739b4a43833b8c7dbc947d471e88442923116b88845c4dd6b77cee7bb87745a5a63f5b7e78af8639416bdf99803fb50c5723f03d812d52d70a848d2d3de71bce417ac08d3edc26a4308e32b83d73c60f8283b746f73e3173bf64dc254df0f7eb6855ec4480cd7e86e2ff7f19819faea01cb1cded087d74852b45c101bc1f04f40c71fe015a63f6f365a46a00d8072a7cef5310f48aaee7e181ba3fa0d1eb5c543b15d9c7c6055a4f4129a78ec94b8e384d339ebb7a9e0c06230d197ff9aafc860cef967ee34b25f6b9107de6343f95c282dd17b8a57f9bd6574a2c540a1cfd53cc8512eb7a24c9ba5a490cfd436d4b847bbd3c84ca481ed63df19020c7bfc9998d076821542aa1c9bb66bdcabe993ccffa9d53e5f9061ae5efa97b28986503722e322c2fb88c6df3a7965a2de8cc96540c347a3d4c9f25db50c7440dcb60dcf6f5a7fc69613c15b3ec69fdaadd80b0447ab76d260dbbe83d17a9630c006cbb6d13876d6e42b989bb4b0474b14245bae4b6fcea0f045e937724aa4a0b7c021d722ac25035c3691bca08b3ff548149fbfc10e362186723ae570fe0034cb67ded2f400dbccff13495e1c734657ce76c821f7b9a5a6ae84abb2e8bd84c0a3883d2b259f49c0c09c9f64668541350854877dc63e88972af7f220c48a8deb604fbf5da26144104ce73988872e0848547b14f0924b0c4580cfd46f640768c4a00077d5def5d18e8d3216244302fdd459d465703dc3bc3214034e0aae87ff9d43651211fd6dbe682371a3cf0c2e243ae1d9d9f46a31067e4e685bd4129edb4345c42b1b90ad531da3f8b51f66a4eb65a9a51b01855e8cbb3fb33751459ec30aa28e1d0bdc8b7eaeaef92c3fca017c298384944933a93b4e4e5fd0711b36db499540a49af3bf840774f82c6298faf65e4eb112d60418836f72098a1b06b6640bbd0e7cbe43f4017ca4066d589de6eaa990d21bc9d74a5a3f84b714dd99e7602e10dc468c8de2613c4c9f9a10aed170e37a6860b19daa046083a84d62589b58541e67a2accf439e11ff92a521b3451e20928498978f3d9962ecc157064c2c8270128c1172b16cbee1f080b4bc6391b18959aae73a44a6c4bd358e983982a71e7e5e9baf529ea1901f4a269a274269b74e741a64332287c3db941aff66f7ac809ffba95b244a5f4fcd686fde985246933ae2bce4473e85bb88cb7da3f6f13a6a272800ec3ff98551cb03c730fdb1f85e666fb15bc4f20fdfe3f5bccdedd168ebbc3852f94e7c270f517729326054b689e3f94714f7dc285f08a20a7250697fcf2746e1dea25645e8c6a98f5983d0e83c3dc92e9f747bb1ce8c6e7b986b1e00ebc2494c4f97c70b4af630fa6cb87bd9acba550bf2041d6c6c4288c5826a42a5b560b49ac78ee96322ac269abe2018b0d0ba327ad30f9f300951c5c1c54fc35b55e7528315d318f9215ce93569b3a5608e2ed6272392b77639df5d1ad13b6cd5bcd0e6de1fe1d61e73d0b0a2bf6daa7d3338c24818a08e78651fea6acb037548f7e77498d9e91573126331d4ea1d218be752ca162378a02e71d56f1f4b37711ea5445bed5964e2590b1f4ddfa8064cce21e0decbe450e7cbed4941e022114acfa9109ac6a29b64e658f7c9f8b5e5e844f854e1216ee2d5cfa446251f26437f8daf384791674a3edf71cf05af75e52d5a70f203c12831af002db671e63c24a43a4c4975866efbb82eb512adf9e578996169e8f8039512cc9d935400fee012c6282d5c61755c592482304acc0a525ffe66ecf8f30b434a72691171a6eb1855d9960cb9ab4dec8a7394b19f42d28bd81e6f4329e257df6a9a36a8f994340c6d174405f8c660f75bb3f11df4ac2dd0d7fcff016682c3e8d0d0e2b4a4f967164905193aac840bfacc7f512f8397fd21d9d8ec1ad59f8926c096ca93e10d468380031718ff5d127deea3884da0a8871b24b2ab5dc35a2b49464fdf266643a405b2fd5b563a0506b6509c8d8b5f4455ced5c8f6db238c0d0371b122541a4c839729a492792aa694cdb324788ce8f385bf852a60a63c146ab8e2fa391e363efe1cdbd32b0d5ec0da306115c1c4891ad135615275463cfa19dee1039e87bdb7ad502806a0573f03da0f24a58c043bdcb32d092244a268c92227af9c36461e5238512d2a51bdda54338f157a0a8a59f261f15b6405b2d752c74c784e95e0ca7aad5d740fd79287f58e1024cc665a268bd81cfaafea19caf3f667f7a08765bac125621d660d0def046e58f68d3bb92f16a7162b73385c6b7b57c5c0c6e116489a7e08f2e08fb6470f005c0956b52ba2cf0fec240a91b119d5abffe3bbd81537c1b21f67c697d72f351604f7a76a5c7487f7f5c7c832e41dfc9e4fb03cef495953a148b08452dd4beddc68fe0045cfbd5708b504286af33f8dd40a85c9a40d14eae2200a1dba6ed7770de49cdaa077e651058a3883a9241a8bc378b49bb443f303e890b6498d09e93afab3c550f36447724454ee4ff7168c5e3a1e781495753b57cdf806c20979c04062bc1f6b7106ab29f1feda090a7ad0976430594efc17f1eacda36d84db69ddcc205fb8d49aff501b7dbe0ea3f890663869367c0070d08d3066638c18a28e9233439286e5490b705370e1d976a9e432b8c9e2a23ac165375b946d83c4e42075bb8f60dfb899df850237f10e33d4b3f143731a47166d60e316f71b6ef04a739ad2a0e344b3ccb246709bb3427df747103dd87f9c98672491b6a9657ecd6ae2fbc68c795728c9e28939930a3cdb9c38d623281cfe88d0d27e2690fc36ba0e199303e782e689c32f1beaea4062f346549914ff96e3b745819af00766245cb9278e346a028f235d178d0241cc594d11df41ad40cad9f4386b7f5a39f3980dfd839c36a67e12e25e2001ae1785ac2cd9a525a6a9223aad27eb20a006a2128e0a5832a64cabde278301a338c547e283712d2dcfd0c274d4a8f4496fe16f17dcc9516b8d4da48142b8043d2648d4421af41357da657f242b16c50628427a51f943e4b8e5935ef99a937f017d5e1715395487aa0e03efdc4f3b87d3f250ee148e1131f6db716c359153b24c2d1dceb204463021322fcb020e625a751aa57379218fc12adcbcde1e2f6cd0bae10dbce5bd768ca2be75b3ccb383d2b64e9348d5fd8243270f2827e92b45e8b95977c91fe691a44ba88475afa76e800d0bceb1ee90e205da3012f3d8525a37631c5cf76997d455fc4d9f084c135cfd1424ca86e685f6442cfb068acd75693a749db49154c9b94362447317a51bbb01606c238ee26adba430c2e224f2bbc5ee8d761c2f259521102cf8a4dd5a6a85d9bc271e5668cf56eefd4af68ecc494cfa51c3f0613bfc5f89ceca91c540b2306464da4ecf01a0b3517302634014dc99d42902318c77f60208b1b9747d716a139aac91012cb8f9f8aefe7eecade24c3f80fee9a26b550a7d9bbcc6e1b1cd91540fecee65cf70e9d2e5ee260c8d06cecabc6884387942b79174024df26572398cd0e4e6969e813991c1307fecc2c72e714812659b422725375b9928fc7fc3fcac0f0c0809b31da5321d35bdc4521aca9422b74e98e9e38e84881ef755c4c71da91eef51a73633ad9889ab5497059a8193fade6d6c1ab3ef9fb87a693b75c421310b00d022cf25f6e3b01fc1593bbb47042530015e6684981a332e199a2f2cce32f1b28bab3505edd9dfd841d47e733aad6af91418cdc4f7948af32e96fea0a599cd747c9974acd447d52d7590e0a8377be57cdade2b889b5e2cc06deea9d49c2e3667ce57ae48c187eaa07f255533aa3ebc57d7688704ec74a74ad8ee87183042ca6e32e831823e1e0cc506e60530109a1f912c6c4044d311f100ee9420539d8f83d49deebb758f823dc16da1cbeefef50fc6d89354a54010571f2ef41b48fb0cb10e9b38a3b0f3938a600ed4e3137e3d63953b6a6039cfe13a98eb7f1736663c28e5d5dfa50fcf8c35206461c9bacc719035df36ca5eec94750a69e74fc35a0aac6308e0908bad470eef70aa05d40ea31ed28dc5cba646410ef88412341c3cd07c0e2edd7964fce05adbcb65c5e605d19874b864e81e1aec16adefd42d100a56a4fc50edf0542fe1bb7aec822fa58bec35531587d651adaa250319f3baa0d7aa83e28a06b9128192b7d4d13c1b211c604a46b8160cdfdd991b62de9bd4e57c15387e51a7f5e080fc1a2fcc787c6a92cb75f221fc45a67c2aafb99ad00e1d97430251744920346c06583bfd66b1ffc8001dd1439030a35d6725a3090ba4a074b998cabb74e54b1b2c2fd3a0d157492f973f605f292cd6712e1be36a3ad8499cc465dbdc8e14b89f9f78627c6702bc3b9a228cbe2cba41c43ce6fb05ba9bb045022b10fed3143ed6f2911d97b932db794292599021907160705074129ef9bdc862468cf64599665d950d1d190d0d013a22029464eb0d09c594b941d41b7c9e44c508534bce8078782a0d030f48488861b6651aab3acf948ba07320b498d5f0291aed8c3a1e63c5ecdd389006bca0ec22166e5ac888048282860136bc73bf26047986707f7c0ffb1da41353d05bc8570fec2f9db2dd99905fd6010f3c05a999815e1eb89970e936d130ac120e8a408f8ea800afac117dc3205855b2abf10dcb2408e98c5cf9321121e98a0a622f76e4f75438e37eaee51f3e88ef241ddbdfb831c28fc49a3d7eec3dd7db35077c7b029b3c8b9c6f5c631075334386634cd636f1ca57ffebcbb657c9b9c7763c9cc2beff66367665473d5b627ea3a91c44de8ecf09133b7db384ad3f45a6f3e51308b3e757cd1f145c7170a5fbedc25971ddb27263dcaee5e9d59757bed4e42dd9cac67dc89c989499a710651db641e6f17954d8d7168712965098890252062e3522897d2e7e4382c4555b267f40ceb8275f129bb383939d1504c4a33524a554d64125d25258e32a41926b060524a196d6e54bdeae82a33d2637653836bd8b051d5c8773263a3b48e455262177174dbb814ca27768aa6b1383389f29c9c9c9c9ce37cb6a7aac6e294286de3529ce2364d3eca4b36a3d75e9c9c9c9c682846a9aa2319b1c928ca6a6822cd993335353637353af2102c03cd804e3982a013b39e601932e8d00e719b1b9a484306afda5b653735b8860d1a4a696c689d16768eaa9bff4e23da74e8e0a8e77da083d2d181071f703e1d7540c83828a8c86accdca13f9058589683d3c1071bcd7fa0130200787c737e759667a2987ffbcd7e5334f4956c0f7ba147958b509a14b77190c75ca4a30a3e62248c580ab3a0308b79887f8b98a5a30a272727a71c3870400801cb81238410381f7f5f9ec8d3fc3a433d3cc44f5645454545366adc00002b328143d06988c99933373635581b8bf3f117006c82586c8b1fccf624e977824e5387ee78c2b3723c94238621266216f39333b8876df103318770e21654864e3cb43cf84521ff10ae51d9fcc043cb27d81ed5f36a7f748fca834e4270199a33285c35afda6bf7288d2a0002604a23801d5b8fead7a6a349ed40655a8a631d11d464c1c4145e50aa848d0c688da21a1c30d1438d2b9890010a4a33831b28f4a68b1a5b509b2d45d0d50b8e904e200609884a1859b058a14a03cb13366268aa6e1296a3c804842e63bb8ced194ac676bfb1adbcd0a56fc72a92b039dbdc1a0e6dd5373a07ea86dbf01a7ee338cf6265af9342a1e64d9ca9944d4c61353153452f60c0ec17d99e22db820fe44796ba4a4c0b264b653d45a0f7ed92e7d45447f3a9d7549c4f2acb20877aeeb3d728e793a150a82658b947d1703e28c91549713e92a394ab336716be92ed51d241e4389f58c4bb7a95ddfae8c9d99607319b9cf47a43411278b5713eeec1a71e7fa0a5608e922654e1f3bbbfbc0faad09d97ba4cfb54a404892a16d4bd331cc4ac757787ecdd2d811e0b35f14f0098e87e13877106d7f942fdf7f7a9f600a56e133dec3027a5abd5ef34214399ba4dc800a509a01ad4d93dbcc4ad7e2f14cc6acc97a9cd66d4fe11d0c92aa8fb71833014d8a37f9fbb86028370dba39f6679f47f5c3f8632039005e5a2a2be527b0a2630f5e32cb57fce3973f81083ae96baf5fba16e2dd12cead62a800ba36eed5395d91c425a1efd110d6ac343dd266440a37eacc42f568adeb7e31d2bc51b503753b7899fa0fab1529317232cfbe89bce17aad525ce070ae6c3bf0c3be5dcd217aa62ce4788bb737375db855c7927f30bb581ce9ddabae676793077423c00152c58004514415b5c71cd2ae50ab5c2be0ed45869f5bff962595bbfe649c0125d2c6b7d30f8a8224d68ea7c5851de95c02cad046e7545b895802a248906b6e52f24a42e0f7f0dac96ea824346db1240fcafaafe70ddc381de56559dbd3c42b86588b38b0f7fb9bbf9423f5a57317b5f65dea4d517a375878a57f52c2909a86e521345b5a76e12134f55eb4de70b8535558b9bce174aebfa9801bda91f73756781c01d44d81e48826df9bba360c80281352c0f1496892a3530c2cc0ac0a8fe4154ff6fb9a8fe265075aabaab43f55572c1c7d5de9647efc0ac2dc22cc7b09f18e6526a0bd03e05f9507a5f8ebabd5f9959b6b5f5a3095862697b6c4dc012486c6babf4b4cda19311d01c753922382afc8d5bdb73d40f7bcd33c22c2f720685750ae69bc40493d01051f7382c1a6284793ae88459bec3174ab36d0ff7d009736ec3f27058c3f6f0df879c095c851e8703f50ff2056ccbb1a0e551c3f2f05f400ed56108208e099628ff2be3cc06ccbe0414f7e8eeeefba2a2072e6ea8e206199e70819284bb3b5cd1807e3b8f29b1a34689b9476f72022b50e4604490103f20f1ea2d5094a02b0228e14418a88409aa3f37b173bd51bfed8a51172562a01899b9fa400d2735424e3728b8a1ca41c806091515c1508d13353442462a2a57d448e1f044a9945971379ca1015a6d23084a3dc9d144f0e28e74a07430daaa589123fbd1aa3c717352962e3da8fdd14ba1ffbff67050a8d063cfebf73accd3d28b1aaa28a37633d30a422f36d4d58eba495dc4bcae2c35f921880721c6b8828b981ae018481ce0c5182078517942e9861eb3330b0458ddbfb373c58bfab1ba2b106609a533ac7491c6103b3b5772d0c505622044860b0aa0c8206697b434518153125586e852060d225c908b0a9feed293a6263124484a62488c27a0c450436f510419242f65c4a0882e4f44682153c51632a6742185abc320693013281282881184808a2028828000a042e13784bed01dfecf962390f0855c15ea5a3712b7d134c448ff910824e9ee06aaed3f98e7dbf1d1596ac377187f347f6dc59a91618c10870aa26e2a8e82880c735e478bfaed9839a1d04238d49f8fea38eaf7a3ba5015b49f55dd91ba9baa82aac1ad4ab581a26abd412e4f84ea72394116953b1ce8f5a83c55f38d3b3a821b42544dc2959d5ad2b5571576fba24195aac58d8992ca40aa4bb0ba01afddd56451356ce36e2b536b7c3853b56c831d4efce5f2430870e2df6cdca17ca89ab6c12efeb65c8a045c85dd72f9a1a8462116f36cd54225d3026125dd7a8a61c154ff6196bb4ba70a8534066caffd91ed35cf3bc2793e8c906098670cf3ace062aafc2fd6a0fac7330b04be33550cf53e94bdcd3bc157d2312c0fb46159fe3e7da0ba6daaf0b5401be25285efd1a9c2ffe090c69e37c4c38132e91ec8d130bf7d0e0cd81ea88393d0f2f0d751042d2234bbe54320d12b8750d2184f9e4031baa28404d2921125244b47c00c29a293f3d80fc6aa1a92c0c83046b8429ae2688a5764c8dab1b34942e042fbf97d70cbbf07201c35abacea8180b692eea16032f0c10f34d960b15832b824d151042dc169d52d771affa3b113123119312cae8cccc06444cac284c50b296187b503aba22177f36b89a97be909082b4d495288f1b1f3c37fbff59245fd164c167f7e56cdea7e942b372a95755a1e516979f05b801b723777f0b4c508a42d46412568f241688bd19586dc44010bb0ea72552809acea67d23588922879557f165c601eae9e2446d10e0e9d547fdde03f5c5650e3b763aaff474211e6692caa33f95b8004ff9d2792429525abe213ec26d64e154695df070943aa38aafc4748e0fa7609690aaea90a33d51bea30cff74f66304f5f51d98575f1d52df84b66647972058d2eaad63ed169c798fa8105127f3667d6f27b37e3277fe2132da21f35417226d4d425d03b77e29a28526b81b457fe28b440b4ca1f9d7298c540f45b55f6a2d2f29042318da96528cfe6a3e6074d9716a3681eea6797bd904665d8bacb38bf03198f7bf3bf7f96498e50e098826e9296a3242d45384632d463b303c23e68ba50aa3a3feb827eb8e6a33aa019a66b7ed00f57f61a93fa58b72e6cc9aab696a15fc6ea0668760956db4b81f6bbb048ae0ec8ef80ff033a8d34f8fba56704fbf61ab02ecc7b00025c929dbb0cded5767797bd9e41c31106f50a1f4e4e7a41d3956158e751326fbe909e9d27a5b4a93ceecd417a02e9dd28734af63070444137494b925292968d296c925211144e2a27291155661ccf0457f4827ef04eb3bc6ed0ca155fe3d86d1075c5f55ae86417345df1e30b61ef34d2e0f842986799b5ddc59b483f376d6e70d3166318a04a03716eddba6677c4e18e103dd021e1366dc907b115019ad0645da8ee5b558e30d47e9772d3b018637fc3ea3fb5961dbbdb398e6f6567e3b26d833df827c320af03c2d64d698115b0831b827afd76bc0e08dcc61df111b86e5ddbb6dbd234a04281424e0193a63905501c06a49e7b2429ef91ecfba0015db267d6a936713571f1d6016d4f3b20ee7d904197ec19578aa3dbb75271440a503787cccd6c07d3415b9d297ec447f0406feece0118b736a973f20683649ab6c1b84030cfb4d7b40e4813e18b2f2547a47f466ddb1acb382236157b4ddba6641042544c655e0b5c31c73cb8f125a46df74cc1b2233e421f81705b1907666b5937c5fd9d1f4e895c0fe747123465c98f9a020b5de7b36a1357f6da722878d601653fc394253f2a0b2d4293139a5497c3509d884d95af611be416d0b51fcbba292d30d6dd33a6a6d702fb7b4e026f394bc7d89ec32be62d300afef3537d564cfa28a32bf65db1972bc0ba409a1500d3a8d193b0077f5c5380ff55e87d11c2e89db002ac9fac552e10d8b5c0ddc1dad38bf23d05ef84f5d2e086e086e81ebef900131922970637eef605e5072397c61b772e2c0ed2287a72c19023846b79846fabb0d737042b98a2c805038418d0b6ce6eaf360a8d30dab2cb778e487c7fee5290ece10cd9ca7fc256f67ccce08bdf026c52f9b73abf09b4501ccbda7ad081180a5f8b8f755fbfd6599d727ef439dfa7e7c528a4b3f62cab737632f3badfbf58e3fb482298170f9498f3b7fb623f23a036471ab4d5e9800a7e08218c72215602a5468e5076818de88bbee88bbea811a00eb4a010fe306116bb0004f5950291908c9a2061d942bf3d03b154177eb02c106c9b5266111193d799d79e794109435f404829c85a7c9931093c389fec7770459ad45dcf864a6124f80aed6a689013a11d869aa85baa0e1ad11c1a3a154706fd26d53a252c708b593f42dcc127dce24f75100a8f00c42da6a95c37bbd5a52ad645d99eeb9430f1cd5b114151dc134644aa2f6bec9fbda3fa91cfd913dd7f638edb95aece66ec58d49d75deb1db158bba67bbb9bf63c78ecd952b83fa33ec0161a5e9827e5e2152160495ee76864ea54c7bf333843d1652f95e12687346c11c452603e81e0585adc96db9f53e188ceabe6aff8c82c2ed54802fce67ffc34101b6114514c1663c4a299788908df53423c5c0a6944b444ccfd6ccf6c8504b98cc8a6277bbc4301648778f521a49892ddd9d8978cb6c0c4c4a2329180cb2ebcffe3d3369447d379495149614520a298594424a614961b949319162627b6161d00983c85f61eee37266a858f79130dd50180406f1b9b1128af3f1579d49ba150685dad6757fc856f71906f1ffa03c4ab23d5e681623096cc11e0cf3e4115c32e491bc32432a9bdb0fd0ea0373ce6cce6945943ae79c273c1962ba42c9730001520d24a408238b153e64e1428b2c646eced05837290b0dae408a42072b6470a19abafb71851d8be13f8b7924941e4ba7e97b5afb9f796a6af70fdbda9a002b78d8d656afd96130eeb2b5582183371856d490b593153a449a251814d9604608271e62f02507180e2f61ca48f1b34505462a2c3571118229ae9061c4aa9bf4c58a5a5337e94b96fa51953655da10d49e683da09850a190960713aa6a44f44c9205b2f145cd98d40ced414587342327ada85baa9f2806f3381365b18aa85f8bb220c700cc35bb25836450f7c4497b5fd3918162f56361d2089347120966f103e00c85de0ab07e511a55fe8d329bba67c626189b3a3655ee6e89e46505137c7cc226fa4df8f2e337b309cbac139ac62773e74e98de5c1eeb7f0216bd2898b79e6c2f8af4ba05365e3c9da5c28f4c2ccf462477f250d5dd495beab43ce20b615a8682b12c9a03155a1e5a9146d42dd8f48959eceeee6e4389fb824e2be8b74d145820ab1155ee76797c3690aa8d2cd5061335c0a8fc5fa6fa69c0bc827e342a55a667bac5df9a426dbc240ab83915052a59c8ddb6f85b225436000d94fe3febe70b528daffdbe680799b6385fc7150c43318a7558a1fbc4fcd2e4c731dc7f37395eb815ffdb366655e8c117b3ae50ffeea0978d6f2a7cbd98159f5382faf3c3d99550040cd665157a8160f863d538a683a72d41ee5b88d88945ccf39100a5d4f811f330e9c157085da87f0b9137754e9b3a678783c90e07d36447ebbc51a7b6aa53ca9f527b4dca6eab53763575ce0e07857ad9e1a0fea666b343bdecb2d7541bd60dc1861608f6113b324a5a568c48580f35c6a8bd5e98a44ff34728f62ed03cf58ea89e3ef55ca0aff2567a289aa73c50a2f69fa452e3cba305223f66a98fa89fcf7d94d85307a39396074ab1acf8112a31ab7aa93e37662949213fca974f837951697948cf0243e2beb82dc55c0a7bad4375d04b3721273baed22ea810cc010a412115b82cd91e58056cc5c7513ff85a61de07bb90de07b3e06012664d2aff83afd92434a7cc11625a02f3141fa21114a11935b2931a7f62f28bb14c8d1f9920941adf02497e908021ddf06177d75bf739b78dd29b9bd52a6773842c90feecbbbb593baaeca84261dd9eece12f67c28fbae407eab3b801045457b9b0ce8505f1806668d7f4a6f8cf90b9306f852c0ff850088d5fe32e3505f5f1a0a0c8f9d03839a5a6a09f0bd53eeaa3a6260e4a4d41e1afc466aa6a345b9733a13d29856d00b9bd7f53c23c18d002910f9f09bb307be08ae9c70f6bce154b29a592432498a50c6c59f10c1b5c09f330644e616670a84d8127214a44b44d4d88562b4a5bc86af52feca8c97d71f08346864f199ecc88019310443ca80006490e058eec898a2d9ea8a208a0a5fe62054636643027ccc8ec081c3adb324e34492760e02f1afc78e5a04cfdf6c5a586fa2dd3827989b1137fc8cb8b17182d05daea7c98902660083f90c170e2767ad2ab24382619249f20b440a291f3048439a9bd483bd4c69eb84e0d2216639ac69431030d0ca862dfafc469c8b6e0bfba690729041fb0a96302a49ec9740cafcaf09bc142a3ce18b22784a040f88279c0241132c43522bae98cb135712024f133e1cfcffc59b17e660827a01ffc914cdd4dedd44f8d1131f398c1a8f66b2f1803e82188000ada35bc2b7ee0afd7cb8891d7eb65e4f57a7941bf7d1509814118f680debbc30449771b81cc1c41488376c31ef0a5116d5a5a5acaa24356c34bca962e5a8870a2df0a9a9102ef08a5b4b7e47c3c092f3ecb1199406da4667fec972750fd5b7a11fd26d24426f031d09250c0024998a71f42cf88119311d34ef740253f564fd58b13f0058da011141212125a254f4f4fdba4850aa920e87eab7053e142fe76a528047686cd772fcb7eb329e3cfdedd3a9d67b3df6c998364bfd976963db6db14f82c9bdedc19bdedf9824905eee328517e28015adbb703ee3e99f987bb632be6e89399997b325ce8de7bd0cdcc3578a0e2be3df3e7ce39dd71a0a0f0e5e7b84251565014d0ae30b5cb69dab6bdbdae71bb2d2386b9bb7777f46ca76e866277389d6a39ae601c0d8df48edd282b5660158a89c2156065611b6edfeca2b67062b81b4709ded8558adb3454467383b4ddb73cfbfcbd0a9ba56e7b94d8cce272a1fed980fc5fc7aaf5e7d5c8f299a1b4ed61776b4d9505aeededc01a31c60f6ed277175543bbe1b6ed628cdc51a4e17c9626a5d1885383fe76976a37356c2c8f6d8fd2b09ca1344df38de3dacfe86d732eb5b59fd15e854b694c3afdea1e5e40546698c3b6180a250171c6e836c2bd2a712ba271da022fa22aafe25c91ca6b5ae0453536a9b5f19b1678d14d0d1b2a28b271a35dd56ec68d5595558daa5f0037b612dd230da25b89ee9106d1ad58f118c388561c936284142b53ca1152e011523234a4b4eca07e15e7d3d2bd1e9a81159a1a56b4d581de3225a5c42687c5c7e666988f1d2d96918eac5088068f50c8931e959969a8baf343695ba995bac56d44b641da08f6e0df9ed473bb2dec398a61dc095cfb9723e241c5324f49b7c4781ada41a9db08068139f02b41a9cccced4d0e06691a926ef17760445548b27352ba5afd3c6264c37eec703b3b4586ecaeba2894ee60168b6668833b68a1dbdc1c2a7cae617bdae839a89568daa87b3a87fa41a13eaa3c543f28d4582a07b5527b3d8463c666888d84a0500e2ad486d2dc3c51a72b3a2951d5689679ea42315cf08f106c3a72d245520e42ed050f22b88234c6052378fee20a9007f5db2a37464be5deb99f5fa0e0a6fea8aefdcc811729a09ed4859731f3db2a56bf9b8a3df633898b19346559e9a8224c52961f97a4528809039e310651d108b5c548a93a5424a183d28f8b99f38144351bc3a22b314fbc38298179fccb7021930408b2bc804c11648670776705a07edb4d14f5cb09e3a5cb1651b6e052636b4b8c154251bf9bea393a60c40c20cc0dd57ff5cdaa2d323aacf5a2c5114c606c6875a11fed0a5fc777ea77938595e95ac4b0d2817e734752b9c972946ca87c08b261daa2030ac4991aa61b4c9a209a5431c8149110ad21c5fde044c3836a03e22855c469444c5c121cca07a7ad892dfb2148a382ce1f90505ba430a10c8b32347288103f138b1ba08230ca4206d40f59e080227acaa2874964940510d387a22c86a819e283124e1436454e84b971822f6e44e1c418589ca8818d2328f76303aabaa1061345f9604387a29a2e28e6821a55d278428a1a219aaa9bf404989a304f9039a25bdda427c820e2891c7ce12405086296f87dbd8065205f7c293529e574aa3cee0d617c975bb73f420e056cce2897b1eef3fee0e3a00021a4a2b596f8c08c0a3fc715caf02150f35185cc4e554e895896faee54945f0a3ea7e744a98e06a56ddca49486db345486c5b98209d9b5d1c320e44e289a462f26861e52f73633f596a04bdd875c3608dc413ee44ee00a5fe3c2a0cd99101f87889782336b32abf26b8160cfbf028444740e0d41247ef2c11dba14137d70885f4f60105e823df8f909644e45a1791acf05185c292f063151f744a32f5a0d556697f2f22287c22ca22518c4817021bc8ff97388a0f03f27c2f8a87bdad5ec62ee04af4b368ddaddc6ac278db11b682bf00faa7a2098fd28ce0b0d0bf59fefe1405f3082a47bfc852947a687a3bdfcec718ec8cf5e7a38fbac6ea19e6583272e677021840c9a70659f69de91fef9ede1acb7c2917e7fd4331457c880030b42e00318d7fc897a1f63d075ed18977b2e4c6f35fb5f881ecebefcf993e55a57e6bd8079380c903f1f67bd23f227ce91f8edea6e5d5a6f1e0ea86fae01d085e1ecb3002bcec63dacb3c3d97f618af62f648ffd0b5338ef88fffc173a9cf57036ef48f69887b3efd2bc23f3fd5f700f673d23cc423d926ea128171447c3d1b07f40f698f7c29423fdd93f60bed08bc2fe47f7608f7ad48f7d72260dee72f32e33333b179186b907680af67585efcba33d84d9c3dfb1f3a37b520f5f48f7d43cfc2146ba677bf848ba873e840f37880ab007c3d7b6ebd1f1030f1a23f878ac8b42bd5501980022285920ddbd82d725cb35b88358b56dc3ba2836df3ec1a07e41a4a31a9a27433b0801318b49c742a76479f0ab00832cd90d2c0f7ed50eb4470086e8370760b364e3855bfc667c99ca2a21e8e71d8f10c2d0cf7754ae03523dd0f6da546daa8f8fb9505b7fb75637118b392b961ddd63ab3a76a93ae86a158da2f23c6786b92bc2a715e0cb30197d0ac0e635cda6f37671ecd299a99b6e6dd4a6832e541765fb19a62b5b11f673e4e0b8f12e00ada2560e2d589d0be83701107d5361ab0e848d165163db4ea7625d14d5a3ba28db7b17a55bd3a0eca26cde2a4adacdf0aee511e2cb2e8a6adbf6ba0f5e6976fddb799aa683f3c972ba31ef6fb270ebc683540c3ab60fbad06f6ed7010e19facd1c9c2ec7d6e1d8b0ac361d60d06f7637b6cd87ce069397857e5367dbae860dd24d07956c6e9eeb80a6eccff0ae29d96bdd0ad86b308ba8dd0d9ef4a8844db825b5543433000008024315400028100c87c402814824cf945dd50114800b6e9c426e5a301588434110a330086218638c318418020842862052a6ca3800f8bde78943c4442b92bb5bebf424cba8accf0b91da796eaf98062e6cabb340647b0be7f24cdca6489faa30f9eeaab8af9fb01443e1164ab0e0e5053c2c638c0a273c5afa36d7c5a13e09ecb3386396e9f69cc98bb7a84ace6e629024686c302b19dc205e47da530e24825d1cf183643821f53d25d4d4a8878f413045fb70d95fad7e7fed1707645295426efe037d3bafdf009bf1632bc5730df215e6b071706a80c511c5b663f4adc1d97625cc42ffd1c3858faf06b4c2d1461031162cd39501c440f6db593189d7de9b653614bcffaa5261e29f739eaadf2484695e80ea2b451e3adac1b35a3fd1c641f37b8607eeef6526e6fa71fff630b6227f23e385af80528747543e6ccc5ac57404a5db02c072dc36f55fc957aefd7df1fb16da19b49b2518d9b596c121310c0918b7d5f1e12c48a4d3cfba441c00631ef0d06fd70e0817ada5a99c3c01317b1bc4c500b05265fc55c329c31954eabc32b9bc8022f66f749622a4a2184d86f231d06ffc0e46e163d060e6bf01e3170e4bc6f399b87a0ed28dca82910922155cd250f5314272cea61a9c7dcda9b41a4a62c940773378cde7540da7ea5b7ca60e11fa1f395f8e1c40ea8bb10c356831a70987b2b00569486c416be472d38f89b5e162058c206375ff2d64c0f29db0745488044e603a2c8cc10df7ec4b7201ef2fffe275fb54509b61649b9bc05621c4b3a0ac603d3f83c470491f6af2d67f1c614a8aacf73a493f069d87e9fd0bd825354afced7283b1782184e8f0af8fa813c15699e976f9db20f25a84241a01add101738317633cc27bc5576a132d9b99546665ae581906e7d610749bbcaffd643d1fbf7a1e92f9c54fb31d1170a4e6b10ce1eefacfe8046e515db2c9a15090db3d89546720b485eeeeb88f0ad46dab0c25f8bd90b5c5c705d76a10bf62a37771dcc241f919ba422a00ff0c4fe9ab2a287a61fb7bfed3a062d2f7f81b9152ec254279ac14a10fb122ef9b9fcbf92e8592360f8b4686c67822944868f23abd1ced068c616b1d1db9a06ab5185e3b9947b1d514c8f88b0395768d9d78002a8c3bdc1ddbc7f9dfc3dcc5b72ec7f3624da3cd36abda4e1cd0246f8a66c5eaf17cca87da62c8f21ae525e52d05ce0155922793283c02102995144227d928f60183ef321d644619e12a7a685f50b2764b5e1a21fd6f3ee458908f786bf32deb7e25e815fb71d5f92386ddbd70cc771ca2f556c6f96a3e2cba30db1f2d75bb31c5b2723a1002d894753c7c9157a6fd52c87a9b9e38e79e6d69e9301e9fc1a6f858b5a99c462b353e57b745514881e37743590885012e0d562bc0f85b00f5ac2e979215052534d32e9215afb5916ae491f786d311af95afe33fd48feb3c49fea9a049735cb2e5c7bfb2e8799279712cb1e9f7ed3d9e5fd8d0bd24be0594e31772a886e3e122f8e2d40b232ce1b48ddd2c7fc2b5b8d301a1bcead33dd0706d883ccefa3c550d0b380934b34f35c9cc297dae72e8448e20dea44ef6e05e4e309a87abcc2ab0e843058332b187a9f9a9474f3c7f1d80e8feb824744dd67de8a409468e097d2438dc608f65351d757f08cf0b5d6ba3a92ce927382212f48e6b3f300b41a8ba914a66d53a6509583b14d90bcb06d9de585f0e8a64fa722c1b1461c1a66defbefce4709d4aab97394a2242eb5e5455b9b0c8faaafc44ab7c5d18aa4886b80283ea121d3b98b96e893918da223a798723a3cb3215aaa821dddf349d0a6aa621f52237177c20e6ff798a2f937f27506425256fe0101934a152c907c1ac2511826f5b3ef4a25753b39eee0881d5a9488b96b356260b8a05c359ea8702a07de596d8e39ce76e2800bd476e8bbf9656f96fec81d8be7a184889c9d711555b752f065a39be0b99e901f928d0063888dcddacb3b2dff6c943b0ec455652b36835765668a21b22540cf765c4166718508af50ab430cb8b96980b6e69464a19018995a794041aee3269e8e44df47b0a5e041fa3b9b0e79767a34eb31c8dedbbaa9c5e032de0ba1a1f31806126f73a4d49aa5f325e707917a2e56fd060e845278f1dc9bd8b0dd5e059e004002f1157a32d96153e20e7002bd6ff0e865a473ccf26bb859972c5f2c000fefab55ad9f1b771b368738abf2665c37f2c3dcbeb8f7e112ad7effac71e6410a6efde59d4a2a985700638a13ca12e310cdbb30a2ab0a714f9ab85b58a0c246b7137735d8707ed25c4fe6eaf1316e993ca0c2aec10585c27614397c663a260f23070367711d54493182c5cf110481af5bd3e85e4b7f4ff7e2f5c37d62814622b4efb86e618d160d37f8ff849738172d3d0cc0803848aaabb0ab094f045f6a33a76920da5972e9a0a3a1194d0e8fd090744c07cbff665e3a3f5cb020aa464f3339f22a4baa248441fedf403753ab9f66e8e1707c8ab7e1f1d71989af4f595e737db018d5ab2a1134052050960412781d4859357731144cae6e826fc82668c916d8c5c47c282e41037c86d2c70a64afecb9eec50bda8f740b4728ebed4e821a6027dcf6dd4dab570d0aa6600aac82a7010d81470a28cc19617fd5f2f96e0fbe305c7e2de2f86273f1181c7c2f2ca44ae3db2ca5d6a4c215c301eb6bee8f42036c12a13b5e5d9f0d31485a6b06fa5f537d4c2bc89350e2949eeb4d1cafd0bf08347a4d1363a1f9a893a4a88315ec508b80b047a81e43ce778990e7ee482cbc342898e885c7cec01235e10ef4e3b917fcb09072301279b4261dc88202f8b2c48b282c903add9801ad176fc5a5221d40e97322a0bfa00e493f69b9d66bc3d6893a0bb4c921d63cb3ac71bfa5df662213e8eef14066c590632cabddcf0f0b9eb6f9f77f249740e80b2de56c8dd7b30c6dae420a33c3859624aee4ce1f6724064e3fcec0de1b53290001ff59ceb88c948d6053dc87aa276cabc87d3e59af05a7dddf67155bb438095a0ae71df9385fd95d2b9e9c929e135d34fd7df74ab4d23a77e60c25ae1751d47648188320ea026cc890c39ccce0f5678cd4ffd3dfb7543a4b6dcc90a5fc2bc43c5afcbfc12ddf9f5caf6c370c108055f60bd7e6dd17d6d5daa0f96fb3af48b665e8609f77543fbbd0e15c1eca128ecf89a3d28977498ad21c2b57f55b2a7bfb0c6d74889443508a7d181150bb7305ff3a528d9ff172b2f920f1c1847ae417a2631df5fb52fc5d76a20c2ed84959d44d4045e5ac7c9b3b2cc8cd3b3611e09cf3dd4b357df06a73795f7c6af13e99ddbbdaf5ceeb17ed5e2a6c7ab3c85eb0c2e53b71eb15d102e18ca5936d4f3f640a31bf3f99f903cfdb0059b4387af289a3a9861f5477986bad36e16847ab740bd23d69564fa00ba460b7c9af6494e43d2b406caa174ac10d673c85d9d65aeb44737abe9ab7a92784bbfd186dce8e7c5fb0f7cfb7dfbda2888d3dd20d1cb6ddad728f8b9b485a0acbe87d0f7e2fd2b85aaf43445f360be5a9fe8e680e5bcb33224c01daa92e83a033121ef590f29f8a12a16ad2b8884bc773dc460875459b4ce2092e5fdf521821d5015f175829894f7d6860cf6501589d60d42d2f1005480830065fc97b8e0f7f3ac3222536f23fe95e000147886404dcc53c0084379a404ad44081af0a1c095be62b2053b180ac7b16ecba86597c4b364a912d0786a8282a6fd0b207e9372d07808e0c966f9de7f491972d2a29d12cf1667058ccc21ff9252d865bcb9c6e5cc04dfba67b4d0e07903c55391994a628741860d7fb51c7a0bf6dec24b76d8e958d86f6cb921c6cdf3d60b8905bfce811d6642acb88ef3a5019f4eee8a2b58b0d80ce1dd48fb40324bedfa6de35c2b783bfae47ef27e5c7859ad5e5a177df81161ea0aae5163e07170d233d14f0c14bf17a47f2eb10e9f17e8038eccc705c3928a73baf8a160bb3a59d757ff4837e7bff2e2d55705e47a4ebb136bdbe54f74e862bef5836387405d3926bcfa7ff0703bab37569c5a6d8b22dedf26ddb5d39e5eb13378d4e82c2e6cc65abe02c3f8656550bf62f66021c94b382e7cc47abf957d9d3670abeec689333bce3188ddb70240d3a56f357e2be4f09ff98d53c00c66f9526c6ac50e9b13aecb77be15fef2c7023e4ff18ef1a25238533901dbcd0c081bde62e5457a0d1a697bbbcecdf3836f8a0b124a7a39797d8100772075796caeb99378d6be0bf61495ce53b06617e82c28920f1cae219b5792b1e2423bdc1ca8373b30f81fb0c62256bc0766cfdcf180bbb511a6cbfd0db00437c612dc8bcfda7d5c5c7372837454d678cbf973c50d38184804331d1da0f223ad0800b2374b1cf2db0b0b5f0453b58f0b88f415961d4cfa8e69c77e77956e104d6d85c0964a776ab8d33e3cbfaa9aabd27d95860d7388b7565320decd494cdf0eaa90d5c879c5d2371b0fe78aef3c7589b55253b790feccf48feda8e7c40f363c37281cb9e42bda0b141b00591a9a3a95162e625cb7ed385d2e5b03683b5a01cf1f176d48c75b7860ae3902a6e01880b90df9135b7e6c0fcb810384bc3899b5fceb1f038ba059fb960dcb0ea8bb8a94208303733cbab26c2a843852b2c92e5008174a65aa1bc5259ccb26a8fe7af8d04dca143c45d4d4ca9d2c8474231b98e0fc9ede412d0c9b52885aec908ab03660ad212819b496b6fb6adc1eb796abfd34639cfa3a5225465c7e35b2f5d2aeda91a04ffa980401a7e3d5657ac7bdcdcc4e9ef50f23112c6d1fbe86008e8e8c1aeffaa6e0746edce9c2d5a5604bdcf03b8790e27c8ccb05e810924003bcdd3981037509b7c5eb3dad734520d043cb4581185286140ab987980ff2622d64739c4766fa07fb019ac718d9f773cbe11fb6d3d5561411c2fe5a6d60650672b7244578b09ef0d406f0396b24ed3384f045b0a11b5f266fe8da8b4230c4f8fa554bbd53de01a8ba240e714d73835bd17def54b46c2943675843c41f91dbfb224b07f470c233d2116cbabfec4b7a988d475af891040684c7370705c1d34cdb1c3dc3f635306204cabdeba0fa4b92c292985c9d3501ec0bc15363d5f3a4967ef236631b62c510ef8b8f0c43f1fd8402a34e277328e08a9c17e9271f7a9443b795481d793432c6a88e81f796f8d0a4323514c850584ee70724d9c6d962ff9a2ef34b7c0f9b422be336fc325970c9b9031d982f976d2b96a6ad622f43782129228d2d7951f36336b1b970d6e25120bb972092b2c29aeb55f6eeae9e9bdfea1c2d5bdc68c53635653fe248bdfeaf185c624ef2c9a0d1b8802af3d990302faa8e933606fb48a0f4b6c32404f4ae88ed90c4533afc733712d3861f205d7047788e3237eff164216f73171d87214cadb0cfd0be7085a5f40379c42e2d13424cc4a25954aad86ce58b849254d2cf4ac655c93758359c22a9528bfd5227a0784b418b695099b76c6bbbad66cc0c4e7c13b098741a50646eae4fdaff07c7f9a12e001553bc9038d36e0a1d78d99425564c5d18a4fcc15b02e30ede8a2045ad819bd2baf366712412d70849c6756d16b5017a129b7bb7bb7255d1a99d066f6b4c98a8070f7dc1e3680797374016cba1d36a92283b594e3fb8273cdca458546ba143de7c613629f8d2ee6d2458faf130800e33cce7a5d3ff3245e499f038b6867e55459366ab195a4ed5a9a6ca85a0901360c59076ea81ff14ff0ce2670f37df24bdad620798a9f94ea2fec7796146926c9983ed232f621047850d8e3b44386651d2dab3c28e19217a43a6a771fef2ff568acff0e6396a92bce5f6bd3bd02f80ba1da007bebf80c34976d6509374881403d488c1a6d6cb2c3c4cdb26ccd6b377ccbea93f924eacef38c6aa9b508fc48afda0c8a638cf5a4ec9256edf164104755e4eee989762e17f15e472ab135a21341e14386b1ed865a08be3989dc8b5cb5757e6e3455921d651144c2895e344c4482550553531a93eaab515214c222b9f1b1d88689b5a0fceb62c5e66d5d1250d0c010f644571d51b866389a162da7a0a19ea155ef6f81c5ab6bb3b0e209d03d163302acd881c46b9b1e78871cb1df566f28c24ad1492ed1091927da349c5c85455f4447c47ebbd3caf59389c12dfce60d13db8a82226a942475c9b961774b435ec632303f60c328cf26e2436cb48726d5de0ada743fb74008cb194d1f86b4c2f21324a56f8cbb9e7688266892dd6dc5ba675c9b7ce0e7705a4eb43f20318062c128d1f8cc2006d2eaf525d8a030a468f39394ad84649fd53d68b0131f2bd0506d0d5ead66250ccf85c72362370a18935e20dc077cefcd668e3c083d1fc5cd2b6d9fbec17a4c3ee31fabd9182be7139cf46c5a429064e1cda12e26cc3527dff82580d39fdc4fbf0f9d5713536384462c42550cd1b0044e8ab80bf7d870979d7c5147c64088cff00f4cfe656000eed0e8648f8788df38c36d756346226c11bccea5969c33c3802ffd26ea928ef03e456f3c389fd8076bb788b2d53f28800bafcbe55fc62439b4f105b79eb22ccce296d0be3bbe0e67794993c56d677a6456b615873e6fd858f5da925cd0a5929b02ac1e20c25c6d129ca27bf86e04cf0b0293bcab382ba6d28f5c6470962053c9d149d921d1109caae9ed72d247d2c8e9379699bc3f19f5954e9e547a9a0e176da59ad806e1648bbcbc01024bcc25a86a9afcf80b740590fbb084ed3a92ee8e29a3dcf03cef94543267fd46a3cbdd35a4a89aea3f52da4a5a893c097579688672ea4b69d6a0e3961aed4792903e6cacd5031e1e7932d0368bd13e0131f288ba5748df4d3b7757f22235b68e22269dfe6c0fa0ee3f32f948dbbaa2f5a4244fafa1c75bfacf0e425e14648440cff16bd9c035856cd774eca1220af4f12b79feb34db39e84c52eea8cc00758829c6e715e1bce864d046636d9600d82fe3f7d20a6a1e2330cc2268a3cf3e174c6d9d5e490e1e22b0f1a62cb075bf9e3134e6456f67e2949177a84eab8a99d32627460503d09b84a9f73a7c9093f20a009df25b4894a22eb3209004a8119b238ada758c9aa2247361ded8b724c39db2f59741b2cf209f50d7e0ff77fbcd7b63cc55f7e44e59ed5e03b350735cea318971b5c2ad87987bc8278fe365c6c0a0bc5c64a4d292046b1aa14bf6e12c2d2e0e940eb397b79bddaa51cc72403edce26eb62a0f9632d8a02c4bf8f44a3965ce9e7572833cc5184e54a9025fff3ea45cc23ba1d73c0633a20ad91eaf68ec4d7864a989bbbbc67e79aac2ccf65bfe26c751416190b9c340a05856aeebc30aeb82af3f7efdeb254f64cf1fddcac40dee9c85bda1aeb9745898af10de2ab328ab234de5128134446f979cf050dd839d8222e3011dd094ce49cbceab9bc8729b464ed1f17799691e53c8f1404830a23064e7aac253ff3ce015503fe07099fea75ec827fd7468a5ac20bf1a03e22fb42f7bd46ab6478e93500a40aed2075e717caf4ebf4e5bb4c87fc6300382aadd0702e6085f220ac098d2e24160a6dfd51f52885cf7c71301e4574c9a7182e5b2c770841ae7973e15d8aeecd5549d700b28fe142479c69e428fa9c40986c5b1ebf683733824842740d17834d5643f18a2acd0aaccf905d479722adb1c5403aa462280a4ebe48160b4c59262b21de6102c678837045e1238f8f58a0c82aaea6382e10c646943ea29ecc49623ee405374b78f5a75626b29c04973e986724ab4563b9a04a2a0e5085619159168731f3a43beeae325973df8349b76598b90b6fdc9e1e4b3ccda57aafbb59d173b5bd9da28ee5af8e906d27a7478e962a48a469d95e74766ed69361297401b40a6edf866b38c897dbc332796661f7d8abaa08a6bb6660223ff1b50a369a4b48a02e1c6ef4a25329f1777e66f6ed4caa320564542467da232c4821fae8b40b28463b772b4da623f8879a369cc20211b3d0436436eb83e8c07514c7f849809333eb8bb474537cb621b702b1bdae1dde6bf0cdc83b000e35dd252eca776b94ba3fac6bd73e13d436024e46065e0d8ff3091d81c12e29c7bde435d8632dcc93c5c7b1f371bb2a3573ded81d1c1d95f2f898cef6e74d748fe46a5d0b6648684f8f64600901c973170e73caf5ed7f7c6f70c125c02650eba01c58ec53b2219498dfb7adf59d8d44565e54813b382199af6269761a9049388922bfad4ee47add819b521bccd658ae01214e393009adf572ad1aa44ecb640d3bd35ba98bd9fd2c0616239f59a46926509381350dcf62fe969b52c17eea9c3b4cce4d938055f5c689817658345da7cdbece5238e3433f45518bbcfcc56bccfa44f9725524f9d0c17561217c77fa8a195612ac6763393d0601efa2f51b56664d9aacb36ec815c988770996142d8b8401fa19f48e3bdd63e1fcc18b47d987b81d2003bc96c1b8a845b02e4faa69155707fac0cdc3a2698373fee8c874aa5d9ccb790b68d65493f2f0c8d17ba4288c2bac7e48e394d3adce858888614ab46708a2a45d9186ef529c0a2b6e4564fbdd1e116a20bb46ad8bd4c217dd3aaae43a700707b702f2bb8f0edc0d53bdbb3d5ab815fd5d42e547dd79004ebac82420208a5038752efa29baa719ff5ba9c2a28dce746d7547e618423cd9e772f8cdd0a82aa0d9d6f3f84904df71cf8e6e61a64e8fc2d249af8d0cb525e6073096965e1ac4bdc9f6ce9d60ccadd079a801f96edab2f71547d957c5f316b99574f8e8d64d9fe0977b3886baeda3cef2050323c3aed2d1da724fcacc5f93806f271635def59498ade023731bad642c142d0a565c4ababd708d74a4c0230bc6b8643a2d47434b2cad32151f1c661cbb774b6ff6eb92533c372a7b5ae704189d14a902cad4b4a43d2afdcec188cbcc9f305e4a922503832c4be341919005bf34c4e9a4037bf482d04463ac893cd58f6c54c8694fb12ceb3b1a1514830adc51b4daa208f6fa955aac037fd8d005207389603ecf0ad12e0ca204f028610fe69eb17d3864e2fcf71c99b90a6ed9359018f572f1273ed3f6287bcc0c7c9215e75594a5c9b197208e1ee339c13265836790193f91fe719f2867fe82b60ba165901bb5abcebad586ecd8fa7daea27035c32c01e643bcdf6806fc4c87bfadf623a8e51c64bdebfc36c8be356f96bb38accc08fc15b7a91044e8f7dbbadd009dde9a1c5d11b8792d24486a32f885385dcef1e09fc541c64f6407ae2bf33dc7f5b63c4c4616e062ed630362654024b72505f5054d4483c02fe0a50d57a60e1154deaebdae23c93e3b98d8f8c190a3ea67c54be8dbe1eddce3f8b8d0e7b0fb95d475793203db9ab0c2ba13eb00dba1ad62407e1291340bb6283cbe99dd45eb013d8dd6f1771c50924c0550d2f73c33e1197244b208ba008691b5b39b3320976fbb38a71e45d6b1b777d3668635b3ec8b39ce0fcab7099bd8ae68790a0afb235c652f3b7ec897c037047e965938238d6d7cfceed8d8b35398c778834f194dcd3c107d53c5831d8f6802e4b60a047923b8f0e37daefb879a888f365069f413450c7eeeb47b658c858a8415767655aad3a089ad1eb7789ad53aeaee4be528a61dae67dd64aee3232c3c199b9d2c4e3a1bf33ced1bd1e31bf49c9426b7272ad9f2add612dfba9f843d4eab7211c5331d8dd4723388d204fa1d7eab28f11d2ca5197a1c94045b186edff6d6ba9e3c232c00ff0f5764ee0893ee95f6e0a70149cb91227aced19f1b8d9ddd3e594bb16f6b82fffed7aaa6acb14f44b7596764a60f2d4a76de97ecc36afddb92c11f207f043d0ba4a464d04d74b8e667fecd99a56894494be2b9d14d2d810f5e121954b052c2c15be0d3b9f7f5c38b1c048970ac60cfd51b24a265e2a5e676450d8801762304155032632b92225872b488cc3c1f17bc25d203215b53421a125af19289861c1a362c29de2a0b0a29ace647ce8f8ad0fff15ccb93e8103080c99b70f9716d836ceb4fe9d497a3560a654ed27e70c7f52d4249ef3fa89feaa7a67d685dd434cd8e393cf35c62742a6435211d093b932a763a49b27382b70b9cf6226ea3bdac49fa63d5385dd12d366e3dce280b006332e1e8c88366060baf0100f1f504c1290a074fb767bccb2cf190e8d9384a60bd5ad1fa23872ca806048377a53114fbb70fcb4c2096f1473efb78da1de6a00d43cb665847b4f119743e93772cd75c8fcda7c23e39d5d60c90d5de3b9ee0a1c8069f7bba70d73f030b8307f4c4804743a6683f835e02cc2e4c0655d916f627d5872385b845c7bd70c56458ee94c9b9dd7cf93679adb522dbc4732db0632bb8c5221f898bc6ed476a6c16727ec981d51729c0af1fe02083c833462e9b8418c26ebbf75dcd3cbfd98d5d9c516376464adaa3825c28787f242eb02296c9f3e56803e86dacae0a8ff5869f9e94aadd2f2bef0e2691555d21f2b2198aa94e8159d925a2878c1af525ef294081173e40b2975cc40f30a593abf1a3717a55ffd0715c3b85fcd07665eb95ce35728e738363433af94d2720faf1acfede763c1facce0de37796ff1165144ff9d31ede6d5008419e64f3cd316aa9857c80fce82eca3323e52f1bec84cf9e8570fea51c29f8a243470adf24a78e7963274aba381457e358d285a6e151630a4efc3723fcb12416e4edd4aa41ccdd57b6d5d44a4849f718d1e842d52ec34ba0dad7a7b563a2e1dbba34f573927f02fd94244402ecd6bb9699e07bd205878d5da7deecd45887c8dc4aae2604f9c0dcbb068eb64902c4afde504a7b148045cbce00eacd4e19cce2bbb610dbc63124b836dc87873ad0e120b56c156f52574683d301800c073f14e936d4de20ebcc70f082a4f198ac49cdf2e65a056294e9dd39abd72ec2155de68f3e8f24f242e8e75ef7ef7663c5bd1cc6b0c3c96d7dd9ddbec094b5836f4d0629ed9d71943653226e989d9fc8bd5f9ebb903efea38b1d712d809655aa456a38be64b41b4020859cf0c558117f77398e6e5793bf6ea2683dda630b60def79082f376e434d66f48fb1ceda7823425e6069c0a06f108602d03d2ab17fcc158f3f164e4857cb49b4fc121956e3a29d103415e364d583534a2c5e567160e29c12a25278759708c6b87f0b1128058d7fb40841d19d3c18e763fc5db189857eeeabcd3aea561a00ebe4a3ea22d0e9cfeff1a1ed74fcabbe655a5386656efcd9b215f84091b333889ff87e9ed5fc84b37bb4a2a0d8ec7be4d30fd42a9f68f26e1afc2be5ff3d98418dbd6666f6f35b62524a040c1aeb94ea11414d09f39644fdab56f9d27defac2d1b25654709ba9618230c368e1f440dd5353eca3b72a8cf2b907e7c0008900361ecc7a05301d6c99079e7e9bb5eaab08ac44a409d2665f6765d0dc5d6762d78aac361cbf3a8d5caafbe2a07d3d22fe14bb380747d9f290621c8c179919484793138d326f2435d9949054139fac2f8de68d85b511822dc86aab7e26df3a911c6bd1cca897a6ef36251004a26d4de0f9425f15c3bd3e1bf922b2953104aa74b7826a4d5a61c5553bbaba624d7fe121a20f1496dc3c52ef981cbd31ae1d4bdaeaf31d8bcc68f91abe2584cd9fe98004f0aeeccda04cf23948619bd54a3a524a1c5379f343a661efdc269ebde74398ab620b3a1d0e06d99164ca5d4590357abd8dc9b315305b79f73542226438a4a38202f4cf2d55c4d4eda144665f71338a0eab07e8adca6fc4f351eac75c0bc5a723ad5214a7a0b142779b2a2cc3435bb13f4177e59b82f9cdc7ebd8ab79d480df72be7219798704c98fd101264f95c423320483c1502493598ffca5ea0e96d7767f058cbb4aa7b6538c695a044131899bb958ccb1cdb85f134fef5047faf9613f43014e8d7290d88d37714df0694092795ee54f54e8dbb5a068bbffe3645b11269e1c5b23ac6f2819670ab85fb6624258140a3b84a5c6431f7a3fa9da3bf7f710cb8c20b5d5ff197cbd28aa78fdbe42fcd5a25196b6a750b89727e1d818e54fc32086c99e9ab5de8ca8e5118776a9275ca40f8e5c1a39646a484ac0f9a89769bfe5f158e8e78a01e2ba18b8e307b81c7db61c326952d96f9b62cb8500b561d455422b7120a288f0303d2a10684c6ef1cea76484d43601c2667bf7033c812a908aed05018ed21fd131448ee892b6c7e3c2d474dc4392940e49d66d6a5bdaa6a8835ba80908ca59509057b0336536307d6a83c6654c44323cc3edbb2adc1ee437aec509ed6471f5c0c1368175f6c8442a396d65bce07d66733f735fb5ff2f3ee638b53daeb0a9cff1744f071cd9d708da10926727021b7352a09ab56f494390858c90783c9e1ed8a5e42366d975b1eac6f26fd9d5a2949b26eba5e306441c1388cb688c1b4c46f8adf2db23ea285826b99bd22c63c2890a11ffe9a50554ba9dbcfeb5357cad7f195eb2fa10056f6cd9ca043410e641923a902f87659bd814f19deabe9c2f568043cdd2aeb8200e12daa077152d93a2e62fd848c7b7ed0eaaab0523c70011fba6c70b5bccc7003942d57c7ec57b64ba1d3fe1def16de0babee2d2a01667f0126f2d25f39ee0e2f53983c62ee5aa4ea17063844fc7a21ddf7d6d6ec25e9345f3182f415f8863541e823b10f69d83a87ee84c13b11019129c4a882b9be912cc7a569e45d08aa1e0d75916196e054a1345f49aa83f503a31f450cba3fcb5c2b038bb9dada7e68ad781adc61f7640ab851a133b63c20f56b2c51c5ace6450541af207d9ab74c69e0fe15efd06a4a1696f5cfd75d1a584250f55e9189b47a5d685c730da4ad030d37ab066d20846887e606a8545fcdcd1c1042e8af437bef5f7c53e72739543eb0bf24c3ef0040658e608f641067c5b559cf48b7110e184b514bac753ea36cef8ae84c2d84df0697a080508a6e70ffe6fcb42e1f275bdab71ec66b4896a73c56afef56ada7f352ab5215898456380bce36cba40618aca7fb0c14d040493cf2b629510c99f7c277a3727da85707efb859ad5d4b26c4a270a2620a39e577fe09205a2ffe82932b5c483533384267526f3ef469e4d82a2d82642f7b90c3fad74feb0bddd1b162a1f9696af939308501f13a89282a8c52e610c28a71e2d8287fe0c7c6605cab52287c08ccc026af5e0c1574e48dab382cc777aa6670c7f8750bd3b7fddc1437116d558c80811043c8dee31909d85bb2131022b5e6249a858d01286e7d44ae7d2dd24fa0e09eff7521df51578cf15057826cb4c05264a694934d5ffc1df0ebb9de7cd68296c14d824c6752135d43c255f10123b6c18fdf248572a66b3f85afbd168e85a2749647c15f11c16e1af864771406a0571b128865b84411b84048b154d8acc5bd90c0860ee57035640835f26372d2c0ba3d3a1443d5070cabdfd8b5129fff1a7e73732f6912d947ca1c1b1ddab096fa1f26d90f58c9fa3b1f159c72762a142b6a8f0edd694020c33eb04c1e158aff1303367816739741a8b506ce79d215fc254bde2a06785a3945512f4021c7ba44508e18602f7bf64761695477bc4bc40cdf0db2cca700327e3f8e2fcda1102e4b10cce7280466b44f399560da8b44355f26cb212dc175d1dde05cb25af653658c0e3864ee45751f788eedef03f183028edb53a862bfe527a928922d9ce65d529eb3dc9fce28f75d2292fb13d21a099119260107b686bd1d4457c8eb08ba26d0f7f3c710769f901a3f6c5c20e4ec97a7343a328d7d9602277a3c3683d978bdbe6397c8a648f9cbd29302a4da63a85fb58e65c724fa23ff144358cee24a24f98e84cc66f9a32ef9d5a873bb2583261df099ce4d3db3a1f8806840924ebd0352c879b38cab96522122f9ab07d3a638f732640c5c763a8484194d772af524bd7b46c4cdb530a0012e0d57e96c7cf270c3e6aeab3171b31358e32599af6e02da741f4aa76be19f0bcb920d2a5f01811751ba0778fae509870dc774f4d2ce22dcec2a1cb43706624303b1ee1106a74bb7d53483a9eb13149497b0057163a2610522ca123c99f2d519677c64e2b08367545c9f712eb28b03ffa0aaf05a19d0c9d8c352d571bc5a95f7a05b40f95ba0947636cf89d515adc947cefcdd64b06c5e0671a03a1cd3aa485acff5a65c9d01622c25bf65133e98aada16e5aa8eac9dfcbae17936835e2b2d48bcc1a018cb0d3fcf771d5b0a5ce535c07f3f30b8a491df450c49f186cfd342b7c1098293c003d2d67ff3fcfed71c5dbd97f4b439891525e40302e4e0986027819213e828106659bea58212df3387fdb7793899260a854ee88fdc47e8fcbdb1ec87eba504ca6de3f29239da68b937941e3f7063957b0f4fcd34e8bd623a7cf4493fea060e1432b19450e6668d2a36a0c349fa4672f0f6ce879c383cea2b85ac2ffe89121c8fe86baa62f1a2513b0ca236bb73c31ec7266b9f20f374c059d9a55cb57b2af2fe68639b141721fe93517b52d578fd3fe053b0e6fc9e39492902c2dad10e31c42c38f9d3c9aa6f27080c3c2896f0a5a7cc2602c8fab95160f2efa92ba6590a34269bd3b3947a764b550031f9bb3e77167052a6034a0d50663d5dd36b3034968ffeb24843c050203620b15e3936f7561bf88b88c0f3050eb1202222d883590652c44454b21bf8ddfc285b2b2909f20d42366a9dd548500857002b8590c93580f3fe40626f2bafa667122ca372a7efd387210e2695249aeda02890906ec7af9a85bec28676abd189178214ff9d1ce62e3d57aac95ea7a6b7cb8c1a5319fb2fdee98fb6dc6cdb59160b22595f204dc2a135b2f72ba64b77213b4fc004f7852384aa6382086acaac242e6c5078adba803c9eb4b3bf9716b71272f8ae69228fab09f6c41e28990b564b83645f6770ff348494e977d30788edc36fc76f03cfe6d9ca41e7ed4f68315741e1cdd07396393501ec31aefc2d3309759ce95a8129c17bfb1d165a530d8ac948bdbe1b59f6cbd55ccdcfea502a104c69d902610abc3b76f8481c77d1110d1ef66c2f49c169af7adad94cb28dd27087431532bda4a4cc0f77cfef83aedcec62ee8d7fc238342ae9eb5ac6982802161c1c4513a60f8eb692598c4f090db692dd8f5916196c0e0cadeadeef4fc1a3b275deb6296dbcdc26f34229cf20461c88be6dcea1feb58ce6f54c61a3abcb52e0a9b65a72003a725f38a380b1fa36bb28ada0b59ea62d464345874c25b6d6933784baaaa9db9a98884019690d04335f9dd340f97c121e4933e32b314b078413ab9f00f310e4f58bc3a710d3f0355c9c088870ab1f2b361227fdcb516c21895c71d8b77c33f12849bf531b19fd30648b7cf67fd70dfa9362a2aed39baf792467c1346bb6d4f8148a882abf88e9335720be5945d6957fa1b5fa4be33ec5a35325f1c4db973eb8873f9e14cea1229b3cef36d97d6b1fadbad350462ede4258aed93730810f46d8e08e8f9e6e0f4986219fc0a9c9273e590265dfcf99b1ca8975ac1241c35c973cd2d4a5d65d2ff2f5c5d9f5be248150c03f59bc3b4f8c964ac1f0368fde5ec391cdc43a8346d7d870db3259800d618956180912a043bf9e846f205fd2b468c66c046598af4836cdf99c05ce758083f5cd50db3a3a15afcee24447b6d488e31b8585c4e38e6ab8cface1e21738d96911e45df5575368e15acab03fcda7f080a8893a7bf19232729d5e01bcb3b3e258c168dd0052283140811afe388c6c0ecd5698b3cebdad3646a713484e541e35c12281ff1ab5daa0177b1814292f9c608232bb439a383144a2e5f0798d42d68e2caec1016d91ecd3a2c93a18ae8ed64bdd1b859b02af14a376eb217b2746530881398d56ff90bc9d0e35891310442fb1ba9a0f7abe54b717542b02c34ea90327f95a9e619936459ba82a3af1b8fa014091471d3f0c91e60129346b22864ba2ccd29f33fc922fb1defb786cfb7915c3b967da43ae6dd9b767aaa7de2475c2aa108c69c739449c3f70d0efbf66ff64045b96f0b058be18ad8d94a7895512f3e24b4e8e652d51159c5a1774a192f0d63af95dedbb86202a0ef4ae4880bd3a5539f167c5bf9c9407d1d29a4c406c7f71b937d12b8273ac1bd6bc9cb67f039ec459defeeec97084d139b7b127b97a32104fab8e8ddd083c67000d56a3a8180997cfa23601a1bae53b9916ab25dba2e275fb3736b407a24e826897f45566bef8df969aa66fd1a3c4a062727b7f9117d8611e9573ed1e65bc5705b13f1c8718ac7ebe22098be6017f8d6563fb23c82693c0c04a2a6d41c44c64d0315a101775bc4c1cd75b6c1a780de77c22a8b2906282b72cbdd68cdf4a01ab2d52aab240e13b64e37ec3eb6860792e63778189aab2e935dcd7497f7af2d8d26254684411122bfa1c103a758810d28f8f0853f4c700270d2098909e360e6363a9806855107fcbd09e08d1fd08e5e64d084532fe04adaea91d675c94e07ea6a34046477f97bc165a009fe1999e62dbf0f146254d459286fc4c5462c85e2a43ceb6382c3ae83e223222e567e246400d29baefe43d3bf3c31b5e335d1d445a781b7e459833752006808803a4ef766fca755567b52e73af1cb57fb05440838f123156a638d2d35baecb4bee18aa1608d1290ab52d4173da13742f221e39f68bec66e3b50e523676cbdce0b5008aca494a205ff5cb5fa8069d8dfdf80bfd2a71eb7da9bf00be7da8fff9ac5b7ee9600036258ca94cbd90268dda552898c6b438f8388d327e481c8072f6fd0571721f2f26e66d352e9a41ffccc1984239363ff5a6e783594038ab674b3a3058f66f389814df0de7d7af491f4aa4334351a4b7f3cbf61bc4b7ad76c7c577eefb92f92d02f12a95682d99085754e28599c4424e6358ec05df1b6821817b870cf004035e5c510b057935acc4ff2f91bc8a59490c8190cd551a7f30314504a71cbfb942669ec674987671e1b8c97039c8bd2f0271eb481cc880a4e86bd70016d5b447f2abc62e00f525ba6f7258937787946839c857620e90e64b846b483d232d0f4b6beda67d24f830859b69532aa509aa12b909d3e8c36613f7b797ef5bd4495dd40430bd574df6dacc3300b8d21e0ede88ad048fc2a4c8c25e7ee16b7b9c57a20b79ecc2051bdf74daaa6a457e416444a9122c1e2c005c8cfc79c7991f6b61b81849fe2a5eb8067993c4e89f78062ba49aa4d57af86d4fcaec164394f3ddffdf2e20483326b9441b709b6d2c93c0622bbce6599a627f7ed9bfebcf49d2050a6ff36164dc25f3133600a6046369bf21652a188cd23bcb0d2e59a01606ee6c736c84e12b1c657949a84866ea9e63f883445626991611bf8949fbb072d0c9fbff9d0653153494f924bdcb8bb5aa54040679c764eda5f4b4c84750452373ba6e89cb55297eb928e71f933c2a5d28c770c67fd8bf6721660b2f7b8e19b0b3e73bc2756e7fd9d1099052e81d3c9deb456c461c6d71a5d222af4877340aeb6e79692c1bb72f40e4f94b8ddb97e641f07217fb12ffb7312849b6f8785ecaf7a63c0286a548fc5c72f13219b03e0a50e1157f9ba891aa80e7427baa80eb80d51030fc98e49b8095639b9508416f983f817607e45c10fc3cf87cf56843f00369912d714ad126762d064dd8120d97663bf2fbfb34ec48a0893a043012245ca4ce280af67cc6587aac1643c6329a5fbef225bdd7ad28fcf6b1835256c87c758d97be3d7ee8fde70fc9e6f5775983fdd85b0ae62d8b17d47a531a91eecf5b2bc0d376d622d2cc1ba4abcab5aa6504b6bddf79eae2abc925158b9c07be023c5b7dccd3b3db773f69313bd45a631ca38b03ede2f3bea46c4f9c10fecbc808579ad9ba8b73024fbb0adedb4121fc6f32fa11122f2d347c8e2c015931b6a1f13d612d1d2bf6fe4869b16294d84d840eb6057508b4d5c4dc5ba80c5f6f21c7fc3f2e4009e11e9c70ebf5511376105ed8fa22055fe29d40570528f3492e5f1147b0507e045bf2483ed8593239fb64014f7f7e6c98c372189e8ea09aa79631d0a379fdf959bdd30923aa85379f9fbc6b8a4509a8d4aa5d248e272ad0798cdc2bccfaeaaccbd3d0cebefaf3dd43dc64463815152574cf3f3bdb98c4eb33f22ce4129e59f8fcdc6c417719a309374633b55ae73d6ff10bb03d3a065dbb48d14d466bcdb465ac22c98549c67d59811a6b1c4976bba62fbfc7ab24e622112548bea6e2b9a54941614408c2cbd694c6b01c08fefa47d690527290b94f08c34261f2fbfbd7fdb7328592038ff191c4f7a6302ff5c76f30830a61556cc052394e1b42e033412d8946b7dc16a9722c22288344eb4cface6f99948ccf38309e2f089741d475e7ca5aea098dd2982ebc8f677e15c0ebf01c8b78fc7c6f6f1dbeba91b5cbc6671c318ebd3f895a86668ee24c236094554460fb9fae386fb32f17512f5385f3056da14a2f49e45c53d0215c4f3e9d03baca0d0d96864f9fc127ca5aa9df0577aab04fbc2e55e6f61dbc2ebaec7b63355f75026f9f8b16aa4b689abd3f4e8b6423b78c88c414c12e6fe1d1d26d48a4e9e26c8d5431e5ffa4b366d9bd11060dcc009f4ccea14bd0609b0af406d13b59320213bbff99a0ce09a9129f1f43f0be8f28dae95326c32a7b62d29576abb68f05d201a3b9855a5885d45103c9ed6d5ecb0ce4fae2b329aed04fb54597bbb2700c20c0bb5c1cb67226083cfd3790d6ab8fd8b501848dfdee9bc2356d5601391eff4b10b85890350039c38e6f3a9942a7518084528951f78bcf4c1df1e561f86bf6b04e0c7c6948c8b8bda01df79a6fddb25b12a813823e6bbe7e5eb7070f22c11c672c2f820da7b564b1e22468ea56bd17f75cfbad18d40d036ab2aa21b15e247153f784b2cfa3c20670a143409333f4523ec3e40e06b2214d3762a17d8fea50a427333d77cd0e33536c83c437ce081c19a0c7d0fe4e7432ba72ae7d4fc8ec74178378ed1e8769305255983cf4eff87962e62282c4377a125c73aa959c4122eed79fa4e887dbf43f22ef36cf23876ab9c2bf87c2d2af816f52c2fb40b88abd570701072df03491813187452477e5c161b56756dd4ef3eb33cde464389f270bb55a838b89eb297e128c8e6952237d4b2e938b1aa975dffb515a8d192e48280ab90195c8de6fc4a4b80d8eb7c61c970b216d2fcecf429d389f5759e08a934ea65fe62b955a3802029c821ab0be0aecff12624c8ba8d4d38a75468fa1eab7f7c001ad301f74e81ea2e4a633d544161580133d9310a0d5a7f381ea040a4ed152819f51eed7e9bf0bfc9f63063dd80a6383b27769c04fd4be9cbca4252551fa7749b4afe832c4f0a6cfd34e2ca68618c47558f06d3814c2d5c846b94e98a7938356c0b393595db9e5da5753d935cf93d4dca98fd12f38bc7a2387b92c64080f1e84100da2318f8c08bf1a96b27d9866b086998ad9d8118ff93b62ea868d1eeb261726fc92c851fc8820d18afd4a5fa2c2bde9db7929bd998aa5379c265352c7a418e77a7c0e79fb119ea195a84af8192258da3e6287c19bfdcf39c8b3bff1851b7259a15b31a0d7a0529e3164d754ea68ddf97355cf68783f265ace58766bfff9a5e91958ec4680d28ec6abccc8249a6b0515c3bb5c6212198ae2164692172daf0ec10da80560908a127524c885f801087b8bb94a91b937098ca5933a738f2b60d56a0e27cb13f19ebc2e169bd89ad80c1d5d5fdf93d31e25835649e538aab51a4282f5e257161502ef2fae2762e4b4d94c744fd29830599e58d3aa7ac85a4ac7f28c5a1ca74630a858430a7465cb8a21c6ced2460096b27aa4f8720c55013cc3d1e4f7e44af58c3cc569e1adb88d6340351410cc074879ad7b3ba56d05e11ffd80569e888fa1c662cf7ee7a3c62d48f40fdf9900e0978970d3ad9238c72767430e1d420273dd71840447f2291052aeb99c2d75482e8ece1b0732969551d0c9cb9d85658bbec9900b8df636181f2fe6dc1a0da33ad76b3550b8dacfd40e10d693d3a2695eed3e5f2dad76cdb1bb969632a95dd2918ceb131c07858ce7d4d707ec50ac63707f56e9a92088b435faab5836112c33588b32a8651cc10d00e971dc29f6a5d931142cef4ce73ba6cb9c385ed785f53cfd189e3824d048b8d9e50299d8291b7170c51df3d8030da3d63d9c44ac26d724a3ca770aaa754c21872cab63984275ca97c1f87ca812dec17e3dd5c75da7f123112723cae5474cb28a362716b7a8680c184f56adbc7f5dd348c67acd50ce496b98b216076c5001d1f8cd23c51fe36b5d9802ee2722af35f7a7a4e5e255d13fa537c08e1716ef0342823066f9de935fd69605584c01e4f1eed4ca01775de6c4c72ed3d521364714fb009b5955c1be42387bc7da12e9cfde62c98f07b58d6f9e834da1c4ee19388c9bd21574efaf199e75b4b1ec1a2dee00de0bc27ee82f053bb046d2f98ac037b46d5053fd96497d0bdfaba12cfc00420c0985d23a41bd493377209b52d648711745c6aa505d9d3687c46e437c0ad9bd64f826bbb91c1003fd46da111f7a5cdfa519cb883f96589bc366d3844c02890f0b69b4df02c40ea474fe7ba5bb56943f737923fed760dd7bb499171150686fc051c9a8bd41074106ecab4ffbe5eb4e1f44a3b5a4afbfbbeaccf70e87c2d552f2bb50c48e5aa43fc23b227b6cde2627b477eee5708ffe4286a1e5b8e4b4ee4bb3444841e93124986cd2330c1914ff876b3c926c65bc0987222a300b75ad8cfbd73f0243728df0ea68c0d6d0c0e7538748cddc7690a60098e7c35ec2c26865e73794b8892a938aa6452b0a3fc88e49017f22714915303e3acbeeb8b887555c8853ea528e92de8f28321dcc4fdf514646d6070f424161548218a1d4f010c0ef0afef78ba4a23951544fcae40960372a5cb8499995ea31ae1bc525188717a96aa933682d84bd2b75ae9b6d36b840292b4ca73ce42eaadd0bfbc40a4c623f2f75ee1f5cb9b7942c2b08d2c9bd6dab2eaef30201061d4304553b6b07c7001a546f387eca82c4f928e3d107bb408272338ed92dadacfc108ea653a8304fdc3f06e5f75e9cf0c695875efa9856af8789a336d21b5f23206ee5f1af7e8b7a4d26624598bb6f0388d96b2ca911d882435cf36f5489bd527b673f68e1e50c058e44e987a13296ba1c72cd7f952f002f530e6c87580aadc421959f5cf583fed492be506b309055b33d4a289dc6b160e0764be60b5ae94f017261d8c34f11304f14eb95aef90064fd9f67675e1a04456c07c1da83b70784e0a1262fa5313c0fc192d8266f0cc78550bb586278348f6ba9add7147b895260128ffd1dc7c333879001835ea8e9df61761ef5eca866ab34f083dffc132fd73fa48c92900f019ed0a9668a51fcd4bd4117afa9f8a0df78b504292cf61c833003e4d30d8d94bfe4be5b3f53b76c6804a421f02516a4e692753eb80a23c64cc487ac36b3cc8a08309937978f0e1a0db6987b8dfe7f1763efc0b192340348c8885d4512b073c94ed660a25b01b400a1a62dd7ce54f300751070b3564fb318a9ffc6727f2b3f160fb8fa6a2f9d86114eeb2a32fb80914020d2d40435012f9baece51b5356b44da2ce4700e3e1c3d66a4f76cb61d5d4e5389034a804b7699ab127cc2613a92cbdd45b3560f870a46967046bb3a6385d5828d81b755fdf8fa3f265184a8f1026435c036974802b4dc8ce7a0de0d2bcb170cfe0317d276ef1e9d41dd8e01011574a1dc03a1245fe4109a8f0bd7a04f3c3bdec6b72206ed6f66a8ec0fd112827dde2619625b39bfc37597278ee2892dd075ce49c3d806309642a128f94ffaf86199a50c38a7f2b21940ced401f4161f9c0087e90c5b3dc1fd160051583ea8300b038014d238cc6be12b6d3c02421ca038e579497e0356c29634762adbc3cd46576bdc59938b60b210652ecd6ea44951100fcfa7ef4d11e2b918439cf8d198049ec7e9693ccaaf9a1aae55e259d428c1bc03f5aa8366804e86fff10934d364cf8d95e7f699349cd3f9d4c5761735af8c9e7471e78f2ec9662d8677da0f9377760fa600f382789dfd15ed710249330e8ec373efe05f4baf1fd3501ef7e083849b1a58fd9ca5208c0679ae1e75d0205066eb43c150b1f82a6c874d9b941a01e1d9ded979940e246c22fbcf04f9a6b96238ca8db7cdf9ec0951081f02a4020bceef404eaa55337c1d10b5bd3877e477481551dc3e809cc6c43373b694bb3cfcb50fa99fbb2d451434353fc17d26cd0fa3c5ccc396903783b600a4e3f9d3427b0aead88714c0e3e54d8d3d5171fa211a00b2b401e4cbc69ec406da3b135ee2cb69b5bf8cfea0ccdbd440ff21811b0c62a276806d932fc7014ca916cd46d3fff438382290ffbc92271c0f5307cbf36fdf25fa2f31958c3b66ff3ed5a25437c3e13e44505a4eb5e85e1d43f6345c322ef95976a0c22340e8278258a2d6c094e9593bf4d4b1127e7168cbdf7744f413e1c6901f4f167c42c4ea0d5de8f49e4b1a088646134402f3662ad3606431e34049266ae816c12fe4f82927a1333fbad92a390e1697a13dc5382dd8c8d757b6fd706783f115a0f4e9bab74735aac14131d769f52f7de0d79ae8e0f694335434ce3e1aaba5ae0b80ebf95b3d9e8d24af5c84f48078ca64c1ea21f36775edf0ed882d19f939b49d2f332a45a265d9043e61784e24381876b82f26c001abb3034b1252c98608f39310e281f3d95f8408612434a20657c7c85f06a0c06eaeb404e4a80dc3e63d12c55dcd2c85a61bcacf3b253044b1b2793d2904faa55d6abb99842db30c5e92af944485f4918f0c3b6ae87da801440f315a94fc7132d90d4f05b66e1bd8afd67dae57fc611bfcd176531509e229a385f24f0e1456f43c1be38b29054b512680de9ec8dab59291ef8d21843a61ef497a34859a55d3a9ea8ea47debb8b6b8f3da73aee78e25c53182ae274090562050f469b7d880116d465b173d40e1c4c34308700b5782d6de6c2f725c27145c4b9e46f1aba14d3c73f8fb879d957783b0ebe0ff0e6cc71749dd920456e5c7160ef9a8f0970eb650ff35c4f796c3def371b80d290c03a7e977a6f90f7b2874acfa6bdc92c1a89ee1eadd42e7d4d67d8776686bbae91e5801dd88a822d1b78dc52d37b15a1bace7b67a8249cbb69fd03f5b290bdbabb43616d46be563a4dc36bedd5f23f115637ccbdf102544d53d202eaa0c358ea3eda8d2e558862b3d9ed11caf72a6bf2f6c31cdb0c22b1b0687e63fee5a50b0f9c41020913422ccea27f0e85665a0c4cd51196cf688d034c416613ec22702f37bf1222d230515e3f1baaaee1190cbfeae93d6956db1812729f23a75b8bb5b602bb5e289a8215d0b38a7088a4d12bc6e7bdabdc4e1da06774c1cc28a12bc108413847a5b64a4b768d0a35455e4005169f117b4e8d058b67f27f66877c6acab2846eac36a553495728808d83490bc9100c8f4c137b5b184e7798b18b04b004fad25a992ea1873189f395257c5b5b1b7c52f312c90c938a28566824a294670165ed28235e3d68a99b00e09bacf5e46e8f749d88d1dfaa75abe47bc200887526b68578069500299ff1e6c6aa01b7b7413870e9d01475f72707a5a2c9b841ff488b4edb26087bf8667cf9ee601aa04d436b2ccb1e313cfe313bc09ce285a3d630a5bd861494a9f5e68bd819bb983f688242b481cbd52f0eebf22b001a665ca0dac4e7e915298e524b9e92c27c94d673949eee6c66745a1ff43c18c88632b5617bb1a451e10af3addebafba138a8b7e1ecdc44cf04001e2f73b2cf59342a6f00a2583f28fb1494647793dad804b2474e3c4c3868ace76e60c346be9d7b2480531351d2904f1e5db85e4c36fa6a8ac23922b04b0cca0c2e2151685305b155598e258a34d85ec0f960cce2abd6bb51bac134cab210f67aac2de30a33947eec294290523b83f83b1583d09e4e56f0a314bda11c19495552f55457a4f268fd07fce422e87920a450218a2caab63e0759c5d7e19f68bcff394fc3a345732031d781059067cc3271817f93f353111fd6f46943b1ba2bba32baac821e4c56dde46d9d6a90867c5ae1fec81e4d4433ad3498aa28a2538ae443afd054ed07b6e2a91542b1c0d930b5a3d0d83b2dfcf4b6508cc6d09127025fb91e38cb157124d98673de63de54f453cabe5ab73b495cef49af532d9668e7b4a8fd8ee2cc36cbf53b2b11e7b00d81dce57dcd4fa0c87b5a0946d192b112bd6447e3d3edf2035b7a361ba3c8c923770e7a2dd3116d834708b06bd33ca379d1212af446b79ddffdd25b1477b29b036b4a5ca60afb531335a921d111b0d4320a26561d464ecec3988f89f68318892d19cd812c6f531d1d70e0476701436d1c845adcc0ec265bd72827444856861c62ca051e03bb353eed058696666d9745f36b5a8dcc58263b172279379d17582e39dcfd88b63a78c4f28fee7cd4c2e3accb0982e19953b189f21d6e310bdd55656a75aa87b3f9f6be63a38cb67e3007c8ac80f0018c0687b8171b6f235a9354fb2f234c6af76a56c1dc47775f6d0aec2e771d5d9ae8e5aff7e885aed57e719d1610c5dd10d969372972a943859edd664fc83ce475e8d00fbe0c91aacebf1933959ee173fc66de3b182b53216a22d9cf45779bd49ec791a9e080a751494994cd31be0f235ce71758d33c20386cb5d19d73e7d4f68926ac35bd727dc2f464ab1010603c8d874a07aebbeb9750f757310d81101806d14dc93db9532544c134b57041fa25b16afb4ea6ccbaf45c78ebebb246300f67110c239b51519431e8c8605f3f9a0e94e50912e980d4ee35a4480f7b029dcd7827cc65d50de6adecb73feffd7ba9a97f5e7d8768d04e9cf6ebe1371e94cb5e9a1e1c1dc570830ff6a0c777aa31497b7cd6df36e0889acce209f3ea68c861be9d2654de1acb255c87bd0b4b401f661d5844399f68a9daac6963f661bded80dc0fda2d87e6aaa47900faa85fdfe8e01b5ffe1ff614ef0268b69d21f19695d97f9479c5fbae4c04a232c65020ddf95914b4cffa8a82dc20f0ef2a251360e8b70d10da3187f6734daef515375de1eae3ca87b5d278cc579dd626ebcf88225797c53dfd959a10383d680a12bc4d425c675e0d04ed7c989d01ac08ebbf7fb958c3b521b231d5f6f1770a25534ea41d189def92d9f87fff182d196d8f7010c7334da22ae56c7da80af11becb1985d408cd5749f95af385872c9ca318743a08cb83d8a1158fe4771acc7523830e99d91194864d68c6237d828db1a6cfa31c764bf3543acc60905f2eb71fa32b13469ea6aeadcd0b3d5b594608e727f56c8b41181c8ff887fab8e9197e0d682af8a65d47b42d1480a344a45750f2e16070d0343fb5a184795ea23119b1f413a18b80d2ddf7b838eebecd9ce0eb1ec3df96419f31391c9e464e5acffa4d59dd66389b8d5375af1c7e066a8c49be6b947dc6dcf93ee895500a178284daf1ee6a9f401b97c66af6f21e7bdf2f9f452ac41dc795cd2433446766f464c6931c6aab36c661d1ef5ee687941e4da6b18cecb5fa9cd4b95af9d0875cb97b3abefb65a8301a74df93e5a77810bea847a87d75b2460f181c30a1d6253567708330b922b13ae33128b8847c4042a0d8e4bf322e5abb6731d6eb0bbeda0f1a179dccc2c56926eee02fe995dcc72f6ccde00f89c010e92a3d7b9e0f90405f782f301221480184914042740955791586d40ae5a3ad29e1185ea12f6ac6c95ad31df6a0e7bf15d2da2bfc30fc169763eb9d6561bc0af93088e6c35877fd0ad3a44a0a5901cca7dad89a768a44c6ca81f420c5a31339d243d0fcd0b72e130fef0948a775a47520a10f7e0b450869821a7533006efb2da9795fc64001be28a794796eeac6a1ecb26051016336e80d451ea166a265aee987493417e1d79739dbbd563f3d6d85fc8899159ad21f1ab8001ee7c1cb9301c1cf36938e033169274250347c475fd1930157e0d104cbc441d29b02a9387ee521bea40da7acc98a8264477b593471f9d69aeaeda50c313c9d7217e573fe4e778f84650fe1521d46e46d1e922bb5ffa2519774d6c699c597f144a667709238d1fdf2e98989aebbc0adfa0bd4afc2aa37880089dbd0423c452fba12aa515ea02d31002d2ff237035bc3a407173e4f9671e39f7fa97b04ba6b744dc7f4ffef1cdce9f68055fe01277b6d2823b9a118879d58006bdffefe0235867d6abc1e3dcbbcc1c3a5d68e3af91bcf853f0a0e84fcfdd7750cb19d162326b698aed6168112438656f1111aeb4c985d8116f9809d5ec3a02c97c68ac212c84b39fec809ecc78fec18cdc5b5166df8d928d59ca8dfeb5592d5bd902e4216595a8e79a730de3e1a7cb022a4f6e2b9af9a20ee89039a6f9f82daf2b6c76a9fe3cdae5c68e97fea6d0b8981b9a984008fb352aae6cbbf035ee0e8d20f499ef3e20a98d6507b48a9244b023cfe7c844872455fd1f36a5ea5ac4d582ea5a99886be790e4b07b37b65f1a013d122f2c87cea5521e5dd7a37ad7777f416d636eed9228ad9e4e3714a4c167787d0baa68e3b936403931f06e0f1c7d9fcb407e51e3b487c018a215d68df69cfb5e13f9c6e95077c2a8f882eaac90500e3054b332a6db5b752a51bd0d74d0e5dd31dbe280a987982d3b237b7c3e22b42047d5ecd8788d5dc3d92c62e07f356c4ed9285ed4effb808bf47da6ab470f7a1baa5b5345d48fa0413b97b5b42b16534b7181c2941d98e48808ab1c1917097cacdec81ac54dcfcaa725a1f27418051f7f1e05d6bad2751a0c6a809eeca8ec1dace01c1e0411144d157b37aba75951a4026a76b7ab96dcd596cd884850f347b42e59d9863a1a4a43172148c6ffafbeecbb7f1ca611010c7ca286362cef83a8c67c4ecfdeb002b4b1054225d1f876e93ce767f53a19c33786c274f16334746ef2bb81e62d0b6bbe0170eb601261fdf7ef6b574d2dd999729392807a92dc9aebf5d8afb7cebdff7e3315675767919caba464f14f62cf393b422a9166a8045a5265858fd499be8dc89b953ec9d67d53a06d53e13bf4bc265601b0b5021b105427c86ab2245779c10f2f63690c163b04ad2e8064788bc7b0b443c0cab4a9a8e3821f3c62d10e2335c1529ba830372e101543c478003006f3efc1f035a006a66593092b24a07179b065b930eb8c2d118e12680ae8d711ae52601b8380e8ff7cd1520e6078a99c979c55a551534e737e601c3dc1104b139fe574f1b73d6f7af0a0a1e5c90299708fb30e0c1f58f404d12b2f7de5b6e29654a290569062b06c906a81c32339e0cd743958a991386d2178f7a1c14bbeb2fa869d2bd1d337d3e15fe4e16bd5f1cf7ec9983828238e8e47d35d4ecf94d9d914efd643d4570e8d4914e01f1108ea3d49dc8d4f20ac73caf10e124e98a15423c81866c815c1ac6126ca203b85a30e9e1c2824909aea51e16481c41063f5a9534d048638bcc81bb400a16278a2a0b75b1386154a18030ea6840f49ec8e7be9f2b0d931fe8006e12eadd08a2f80e2038185ceaa752827e736d66dd4e4921ae981146e587df1d8429e04ec6ef97447a89f2fbecd4eec26622642bde8d712e43132a11387703832e4312a420840cd5dc5cafda0871a7077f17fec2da83eae2823bd7bba4fc6b462bc6e8ddbbcdb651dca27f13386e4e23d2888431d851d9fd238a53e0efffdc632f0e85b1396e4ee979906a3baa43873baa1f015eef4782a8e684f4a475d735af2bf30c5ed373ce0dea7ffd5c1ded2feff27dad83d9fb9c59d765d9cff73ccb20840ba15b5bb4a0710a5cc34af7ee9e60d06e4ba642cf48acee351116dc8f9e7b0ba743f9d3e34f2b2e8f9360dd872cce3e5c08dd7d7bc48f91ab82fa16d9b72f2374e750dfbf3391967f4b29a565414b4aef06c81f0318bf87d0a3737612894e1caaff800d55534a2925959223b337b78727ed2eb99df42a49f5a4efe9957ce7c2695fc475a6159d1eb407986e98ae2f3e30850ce9c7af6148357d7c1ad4e3f4f163904148af4efcf129d02b1afe5595806e1d037197c58a16fc0c851f080606c67b519180d293f7ed15a6b5c2450caee0e5428a2c5cc4804a8d1b230cd1854e452d84f46ab3d41eda1aa05ee6b12b7e8cf1a21b326a7c8e32389447cf80525ba85ba50c372a1353119437f8bcc4931cc51ab2184c44d08fa1575e0c9df28f571344d58a5b468c5fc30a5d28f6977cade341fb2d46edb7320e3e9f0c9aa77dec620e3f95b3df2d02cba35daf7559f7cd7a59c18ab0583fbb330d0aa34412d4ab25bd924c7a25d4aba15ed164bf157bebaf8ff25aea6e07eb886214560bdf5f7d9c6fc8685eb0bcb9b345236e017a338853c8c1fa606f9a60711ca8fafca953091efdfc731ca5412a078a01fd3a49081eb9cefccf813e079a4146d57f1209651a91eb6453dcc69f4823d288be0b29c84abd01568de842e216b230a609d6471684c5f10cc9660afa654444ee0ea1f77dcaff324307b5cbeab096b5616e81b9d814ced8551abb8a5f4612ffd76f544783f2b352b656d48fd7b03a365a9c2caa6e9e4d68f240004b02105a1f59f5258c285b41551b9243eb8389d5913fac8dff105028a9ee5289eaffc92a6ae4ec06cb8b468bc3d2fb2eff083b7a14955c47c7cf11d2d0162e71e9485084032889249250a414a3285edbfb221758eabe0695a01b6a54a4bafd5fd6c26e0aedddc05a687c964bd168714e31292ef5ea8b470d614c504c8a4a6868a9fe718d0887049249a4904422974827f1a857fe9da296b8e514850e51f5d9aed1c01ca59c25d7e1947290729292b054ff1c2e396ba8f093a4a5faab8044852545f07c2a1c813f4969d44f8520a13286a89f0a4caa3fe4eea6f4aaa3d2d124d12445c0e2f1818cd09409821e1d557f1310b43f0bba09ca2260f1dc0069a1fe5bbf1ba068e52608888ed0e278ddad866e4a67a5571f8f9fcec875648aba295dd11947d5bfbba2c3d21d755b3aa54e4b97d4adc1e3870750afbe45e2718407929595f5c12f876a8857aa0b200502e8a618b98e0586cb9ca357a37e3740aaa5c5b901aadd0d90db780e520e524e18ab73bde79451bf1c35aa7f8e1bd57f0049ae73793993e37206902473900690c4e36775a5fac76365a50422fadd0005e93a2916e706a8fad3c49b25bdfa7290aabfc77823e43a51e80628282809939ba15e6d953392aaff8d949ba21b2848671ca17e375382b830a9dfcd15d53f42ce419a92d4abaf9322674baf9c4bf533ea97c3a53a77eddf49b13efa5d87c8fb5444c6b941b97704e1eebdd3293a3d57c51e4eebfa1859dcd9c568675c5d32c3e841114067aef3ce5b9bf8180a35fe7f2a38c0abc0f21575c8a1bb0580a1faf354c5f8390fb0c089c816c917a8ba93c839a7942425505f242551fd09a9a41ec858aadfabb290e142c6185950982c3128a0f48a99a128b0f4e00739dc2043053b9011740419239059638c2e4863248d81248612129be0c2defc04ae86a2549aaa612a326cbfe2adda91840ab2c03e6fe6bc96bf7358a82295493af7c805a84a515506d9b5eba5fb540cf9e4c5b64217da42f553d19c61da7e780d6457ad8f56a9d607e72c0b5b451b951045965d34eecf92e3a44b7777e8f5951d1889269440420dcd0e1ddc8c4c0e540ccc0b3d99362dc32e2b2873b76484de8c05dd2a4a54ea14c8cc6850f81a7c38beaff11f0e618c525ad68cde61d8160466de6d28ba6d30ae96cabf478bc3de9d608d468be31ddd7e709da21bed14c7d8931575cb30305b5ca3531ce3c608475caadea1221c4b6bc8c8b04c34d1c090aaf0bb7e34d4a854390685ca2133936366660615033333f3426766664e33a66d66668647569415654564d4a133776b9ea5f23b7c37d234186394cb32c6694dba250949cb16a423cdaa71210e55c3d1c599db8f49392e4a495bb824215d12c98f388b6bf123f83b6d8357c8996840356d630821b466f7261ad0ec74da7e9c7073da82d4544a5f5e208c65bd9cd3729898171a738a898989d161b2882a7bfbf55844957f7d2ceeb0d8d0b0a92b7c326c61a4cad0bbeb51f151b6ad85142cf5632b104b972c15be1652aea8504b857cd2ac1a54d3a2b17eabccb2eb6334d22968a46ab59f041cd0fe1df7ae47bb01764c248569da83216afd4853f00e0b752f2cf3a46c4ef7de6d7875a6b70fad97756dfcaf17b8b338ce3b92fc39f504ed0e3a916d2b05d5fd21eba31f09e9e86853efbbf94ec3ae3b1dd8a7bb8980f0ba2e081fc5d5b83b841d9c1a45719d2af20314d4ddddedadd085128d201be2fd1ca5bd0ec8da0f8b6cd8a96d43026a7fb6ccf36eb3f134647d7cfd10bef7478f08dca29af4cd6f4006ff874c0e62fc359aa6bd11aea653fb578775a86b3b6deefe296e9fba23f44f96b4b6ed647a7a3a9d4e262f4a6fedede26c90affd49dc8d7070572b4d4af94638baab5dedaa6657bb7190db6cc53eeb6a3a0ec86d16353d0574f9719bd52c050c61c96db6fe90eeeeeebe8981e9f42693a699b63f994c26d3a6f126612d9dc8be2ecc54b8a2421696f50484d0870d0d1976492965747f63eeee46096384bbd277678c10c2382d2bc618239c1e34e1a517bd0dd8ee0e638cd0b29cd961b37b847257eeceb676b73abcb453137ad553133aeba909b5eaa90995f5d484c67a6a4261c576008f6e60786a428d7485de873a3509e3d484723d3599d6ae84d02184106e53c4dd6708210a15c3ce652622deddddf56d082185d04444f923338410dbc10ddd0b21dc192f58f6bc306d43c1c49665f99c13c6ab2f5e798c715e168661bcb0535695d0aa5f0edb940cf59c6f52326e87515a3e0750e103a0c2e7183dba38ec0ea31c40f5ee030006bdf8b5e90619b7c3189d80515ab3afd4d3986158b62b108a8e6199b6994c9b966151a29c47b0df2a916437830c46141072b4809d22170cd0034a0f8815d92d80cf18ad091f32c4ba14f6ff82e7df4cf3972d6221c7a6aba81e141f1d691b8c18758246c8431b8450f552bb29f79847a1cc8dd50b9b2db3027959539beb36448e3d945ed0af1ff5c03529f662da5ee2126b0596f53e358312836aa0066aa0b5196275aeef56729dcb93a29fe827b5bf95a8fdb5926d4e8dd28ce3b0ff54aa8b8a7248879e6328c790cb0cc90cf9ccd0cc90e48674480d2c4e3f6ab381eb901c18d98a5cfd329bf482c2fa35f4962706062533c3ccd6cb88c3e5d85eb01e7a9f67bd6f2f58ef1f63713aa0d0b143e3f51103b383c687f5571cb5975850621dabc34735a80d062228543d3ae2233ee2a318189a9cba3675bbba3a5ed64717f5100ff1a0f005ab407c1a488d152554364b3d3e50420368ecf722b7e99f93528efb7840d840ac4d3f11568e304a01111940b06a790db438fda62628bfb43aac9e4c24943054c2a609e9e0c2b91d6a18b73a5b2f719dcdd3382ef396bcb1a9fe4f5bf552a7fa03bc3d29a2848204aaf762f3eaae375e7653567c775ecc04a39c0e7f6614107294811a90e00c3218a0478f05ecaca05245937b0e7de078a2f40ce92d40cc66f3366692de8fa9713b38bba4d4de0514e3f5c19b69da130728004e0048a8fb399887d5e9269640a20821503da8b6d25634b75c3adc1e954efeb19264124c8a499ec43f9b4953a56cbee374d017fef96175b6c7134f6ab312ab8487e0299372fff1142059ed256f9cb4c532ecc7ea1c44197028374884a85801839fca54883e1e82d26d851426b59f8384503f4dc78a535e6cb14f4e25dff297d929239dea1ff20dd860b0c00d0c22a810562243969108f9f102f5f7a7d12302238aca2fe8c4810b31c83083100ad49081213a330ff34203a8df60094850ffbe38d4db50a4ceb72e8bd6cbfb8ad4e911b12c9969b353f22dfeac270b908c80220d2b4eb478920495681a927e80040a78d89244139884cb4048130c80b1841115416812842b9848c186111b4cc470620d248400f1c30f49c8c0082455f400a280034656506182a48a173e1cb15c8424c087329a0042182be0d2c592951453b4e0063e98a20d1228a1a14f20e488244c1c218927547c88021a21640fe06408255c840832011727a0810a254a48280902154a92d0e08382259450e1811247803184225640858a234164e1228d2513085931983882951ec0a0c8054840228c28811069bc200b29b49c20484808beb8a2882094a44811c7103db898f1060cc4f8228917c012d0e030f021e288113801c3065a6c300409d68c234b5c2cfd18610b25480410051180a08549105b8821040deb861855780843491a4baa04e1038510823072620848984802e2075ab43cf94113406d4020217ea58ba0000c88a83082941f24e9e2071a14a0e58a22aaf841891668f8e0248c2cc61072038b10b0e841488e13252e58a208662019e3080c80e08511526c4982063be04188290926ac6cd10650145b4670811ed810838d2e9ab0d205dc81060ba4b1c6135ff8c0881fa8c01fa22e461881134320e9e2893884c098e10334803801104578720447a2a1afac68fcb3eee0185f79b71e6224b2f93dbdf90be713b11ec95f907de0e7e767874ae4890e6bb46d3f80c4cf3edbb2bf280a4533ce7ecba2f6946a262de63f1fa26ad2b22ccb36ea43547703c271d40bbec9a499506f4299502614b05098e798cff43d3e44557b98eeeb59a393e6c137bde94fdde743544d2693c98442994c7183db8f6c7e6f2f5c3fbd0ff3bef904f5bde9b0465920c102091643ff036a5d98c090de137ef893e910c2223103274b78320e628ae5c1cf1b423c996bddb11449d418e2c9a0d65d6a8b2d929278b2a875c72d40c114209e4c5291258927b364f00489279b5a775b032a4b4a3cd97584058987a734e1c50f0f0f366ef013c493695a7738f070838b1308f1e8908038cc38ea8e9f8881258927339d4c8b832f7820e2d181b977c0e84bc72d4effd545ab0747538cb24081511ed103a46959db46510fb8f8a08d6869584783802e2650e2b9bc09e795ede27095a507c4610996887870c05e07df020a1b3c51e0fbf064578775bbfd981f75a8564733c375611de6d1641e0eeb36d28767c76517df068e238e388e703d80abd2860d70557adf90ca9fe940c44696656da16ce4793d5c85cfb19bdaac38b8b04cdbb80cdb8d5e934dd08a69f909422b862855c2d1188d9829777636a209307c406e87bb351cb7cd284a77e510b2369d53cf27c0ddb9d07b77f952c521329afdadad4d33e807b50dc2fc24cae80e61949635e71251c66b892ccaa8699b69fb01a38c27ea5c92eacbf6831a71ff1d97f23dca0823e5bbbbbbbb7b8cd11d85ca914346ebfe1d87595125d21efb48ded4c8dca736f36c33582f3d1d98477a401a8ff5409007ce00792ccf071e4e3cf29ba781f8349093f43eb60ab28c8fae1d3fcb651f8ebafbbc6575a67553539deaa8b6c42955f68bafd18eb4ed7074c3772eb0692cda2923b79157d4cfd7a852ebdca8bd6f4a47a2eed15897e7be05cb3c47ea94fc1bb8d6b441e75faba3fa3ae9c9cf38e95272d771596ee4479d7224b791cf21a9dce1d4326b33de7eccedd4e579964ec95ff8e27ffde746973b12b770bd7c07c2fa08c23a19ab737a799aa926d4f99f09f573246b6de6639d6f2a85f9a66efed6cdf7aece6e4a78796f3ebb15ba508f5b0c40be5e97273d22716b92ed0973fef535de151a80427a75d0a7f267d923de7ed04c3a9b799957a8bb454f8bff71ce7da7187a962ba46cb12744b80ba1e57dbb5d5bf1ad8825763206be5eba862d6281851c1b165a25af5b1dae62bf7fdc3b6807a7606d3c28aa7f7b1f074d51fdd963a11a36be1eadca70e48fc215fa7d0bc9295da9bf05bef771e6284986e0a46e1535a0545ab78a1a4c5eb2f89d05b8003fa5eab112ae842b6f4cffad50a1013ad8a9f8a96eb34eeba096cd2abbef84785ddfd74551f583db298b467abb463bc8e0132d84736a1aa52814c7d5d460dd58ef1fc91ec3e6c4aecf300cc32e2fcace8d0efd33ef80c04e6d3d7ab45f17e4384a23a573660e5f5ee23fc7498ea3b4b720fd832bffc741b0ca3a3a05010f622d841042ee69f2f5b8c5e11c08dc8240198ef4d0c3dc82c4da417871f883481396b905497d2f7535de80f4e753e9acdd11b8de21b005b1b8a769ce2dc855fb3153ff4e7b7b971240b881b833936c4ff8a651f5cf948e3ac51c7fa7a7b84e521759b1626474c44895bd29de53b20d0d7a94051a2d8e3bacb0973ad549f58b493fd19b425f2b55579a464e036d42e6f8cdb8fbd1db6e7e3d1a0d4df4b679083bbdd33b3dd9602a4545281723d088a6a547bb01c36124dee0a75bf5964fbf3c73cd373779cd4d12ca35723a3d549af7a532effb79d32b203e72c3477ae5365faab9fe9fd863588f8afd54d82b20d6a67b4ca18222750411537ba6827e6cd4937246ee71b3d2d6170e58a866a7fe4ef592fe66357557e765b33b6108ca157ea7da85cdd3bc3dc23c2ee297f4d88345d5bb1b6095b280e9dfd3b9d62932856a118f6e117b42a4542a134a370935a035563e6eadad2facc88208566441844ca36e23ff8240e651b7e9a30da4a4f7a5eaf452bdc2e2cb6b9b677a1c68b68ff9e54169da9bbc1972d06c312f01fa315e0e5166403dcce710f3f42500f3322fe3e5807a985f9e1c9e0f8fe66da7ae98a72f04e5c1fc6e37cc80fa180f87f5d66964383d4d0496e7442301e679798e89f1a2d0c040247b6e794eb353dac34e693f517f42a7e44b47bb1adaa9fdad6114394459568484b32be8062ca22ae897196546eba3c622caa9fc1691aab25742d110e88742094515859fda99914594199550944384d3241455f959e6610f49d0506bb696eb4542cc0efbb30afdaca2a28f24549effc5ec10634d656f0711e703fd3a24a2da21d5b68a16a78b8aea0ea2da6f7953c3118a6f64b3571d8858ec7657594d8d3f75ec6a3e751dd3c7e7d6c7f571b5ab6353f2bba3914f5ffbaba36908d0d79e467a12a0dee9b73f79df1b10afd973eba3e31667ae0df53aac5e3c3bd565647bc2e715d57e5315ba81aca8ee9baad0f9d6cf494215da9fcd4e5567fcb2a2c742bf999f3ae7eff8667e80a8ea2ecef456e8421b7a9a57f403637352ca71524a2271c220fe2e6ccdb2ae571563c056f95f8f6aae7b1699940f218c0f25b718d9ecafc7874a85d8f33376b9e60e5fa08181c85a709df7e20e8292656957e6990cc228864dba3d3637aa8566270ec32e6cce180f9b260cbb4c461a5719c3b08c2b01eda10eea24319fa452a53ea69bd18b8f03443dcac321c687878862a1eb36fde3360d610e51e2e780fa98b760fee5ade7186f3d7a33c078ace4366dcd77c16d3a8b83f6924ed2a9140f34ebdf71ece32518a553634c4e314e38b909a184ded7d353e34b965f0fca22c24f1738d660d27d2c54668bd9b22ccbdac5014195bf559a208bb0fb8818e91a7f43f50589c0f7d8f1f4a0cd0ef4a31caaa657f1afddda5d407f865008cad579069902605a9096f5d49a939e60eabe331cebdefc62dded07dc3ee2bebbbbebbeebeebebbbb50b0771f27b793fb3fada2a7695996e57dfe2678fef5f87acbee28608c31c61d87be11c208b94f10638c31c228658c321ae90a1907bbbcbb93fdca843ce82ed1619cd082bfd1dd6165235b239f56a3437777778f38cc1e6ddfddb5bade164f365f814564c5ddb2dcdd1d721c990e441f1bb1d1044e4c9c9c9c864e43a7a1d3109448e9290514456914fa510d0a3d39a10068666666f61ac2ee7e6fc80c2184104208e1f880963d9aa1c70a2a4835666666786a41134db4a00902687035ef144e2d80210e5ededde55dde5ddee55ddedde5dddddddddde5dddd75dedde5dde5ddee6ee7dde50ea6bbbbbbbb97777977bb973b14773218972c3b31337b4b64d98932378cf0c402fad10a4fa7937682b0c722aa10fec909d5e80b84ef317a8f738c0e4ed9699fa0683b8cd29a4bd01f4160c5b25d6d777d77f74d272e49dc7af612b3eecfcccccc3da9ca71a9bb98de47eda336470ecec11c833ae590c9212323838a81919179a13232322719d3262323c3437323a3ccbbbbcc5d8cdaa44756c7219d9cd0130be8e7461857d709d5769999ffe4049ee052faf2b27099999919c2dd5e6f724c9685ee4b787b77bd440d24468a2aff62d9cebdedd416d9ae8f3e80648efc51c697525a9617bd49dc76fecf1dbe3ba451a331b22bf175f7ce3b0b08219cf3087a84705acfb1658430423884eb7a0b7e8414fa67fdfeb5c120fffab9bd505f700f5adb5a2b74a16b117123193b2f468eccf303b399888dead5cf777ef85da815df627e668bd9832e57c2e8459101e1654298aad0adf02792e81181449a83d07ab5b4535aa7acd59a356d6a9dd2fe8a103a84fe9de2b73a6a592f3d78059e93a8340eb814356468480000020a0315000020140a8744229138241c14a6513e14000e7492407e589b4a434910e4300a828c4186186400000018620cc94c4105008ad182d181edee2e2dd3951f3bf4454cc271643f3c40972cd965ea66b66760fcbc988141e1b781f113e2c03cac2c4921ce1ba18de22e60c78801539405e2b57d6b16230c9d9b65743ca926824d1adaecc05c5c3b984b26bf4e8017efbc865b3a42f5ce5cdf3ddb4260e34cbd638b4679d91ef77a42473a652aff32d44b1f952fadc455ee896a6a9f5fbbb6504bcb58374c8e4de4a1b4bc08f825b51f4056cec801d86f316c7effdc06cbcc03199d28a3cbc865a5450d11bc3742ff4a88521528b710b05c90281f3ea2941179d2c8421f7c070547a0da5a0dc11ab52a08a1ed118c01f5f23a16d763ed0ff460191d0d59b84897f5530a5022bd7290e4819f5a9ea18288463d31b813b62e94d84a4a7727cd449b94dd5f8a49003afb565f0cf83bc49d90abf94b2fe19bc11bda17bb636c88b80f70add6ed67a875dbde373ef42c9d419ae635b4b42dc963756b40864e38fdf4885b94adb326d2fe4aee04139c2a9a64e98472d292e381200d96c1c8359ff68a0e2b3da6da1c47dca39471b677061b122e7b06666cfaa2bf5a06801e3a47118d57e68c5da6b4a17e93348335cb3cf14488efc96d66d6e26f8eacc4217ca4398731fced0c9a564d4000dccee85bb9647833b382e3b10d2a6ce789c5a6b59abc478e482da6a963f877ed654398b0c57c9352e401093a3858fb35febdef3fa1364bd6458ca569e7342183b237e2904f263a0928fc1639bb4ac2a60726fa2e8dbd9dd2fe07d520218cc39d270f44886d02000804c3a306cd1a9603de69709af9c97b873babb868303c0afec4792975cc93fe91fbccb08ca8b5d837e4961d90613d92f2e260e840e489e956f0aef035c2a877306b631bdf2d8942ddf4cf14e63446f44832519108ba15574555738c36057be2155d604e7dc4390f4b034557f9b2509446037f1f4da53c6beec3a6d064ebf142bf44677b442048d77a7d0c280819271091e699781ec65c19d68436aad2bfc2852a0a5558ad78781a9953cc8a03c4aef758d5f4ac50e0e5aa232f4ab53c789ab2174aac53b1ab360452ddc00be5678de7965e3af453731bf871b21e602cfcf3eb790e41b87b87f632fe478e2d4b2af66fc63ea6472fe2da9eb6ba328b36a44f837bd8ba6911a9d6698672ddb8b9b0c4b1df8fd9deaa132081a6077f3d57387a03b0905c70c45150f9ccef30fe93becfc241f9ae279544ecaf467051846614e9ae51c90af5c46079fc5d08e39af54ae5f7c608aef7a7ccbf0f422246ed44bf17382bc984919fc9c21cb4ffe130d5c3c3938df47a3c6b13822061c1ce4e1e2add91719d587315301a7ce879d1daa8c5642871d1e2d2e17ed70acf62eab3543fc659950d697b4d3fb79e817848e28db61037e32e2dda1df5047421d56a0393fac786d4921e3af3e272016c991f922832b9587bbc3d790201b06962ecbbbce08b1c89155ecb2a9ff94c2159ef6925b914cd49d87a6a6892004c85c0cd2c7e054111a16133fa5b005b42bf811a314701d4b2f9d5116e68bf74ab9e788955e42370d1f2e8830092f75bb83c60e56c18f80f5e6e978526387ab96330cf53021f01570a4bc83967cf42998049eb7667281e1f5f04c6603b4eb04545bd6e8162791d9f13a0d87b19c2fba25b54b0946b55b4fca6581b0eccca530a7ae7c2a504514e4185b721ca2d7730ff087b1f9c9968c93c7e6f6e5627a0e1eb62607632eda69bfb14a4232a8a1cc29d753194adab8b8592c0a7c21d2504bd3bcb47c579adf1350d66a80a4faf84664e73c918e42b84a6ff50d01e50916acd3cd2c687d8f7e025b3c44d8defcfe667836e43768c564cb2cf6f19ac07aea6bb146895bac9937047f2620e516c66ed3b57ee903944e746f04cb8248c29fd98cc6a7ad2954cfbb3da2ff632a57850c807f3a24f19981cb0b8bb394fd5a3fa007c20886c8f966c57a50845dbe8e82257b704db32e00fd6bfe6ffee49755b472042c6dd1b9a0208996e78b556e8852b29763f13df539d6c3cb2025568bef09d958b3182aa0eaa2d94bc7bcbdd6def42d57b7ac4a1aa71dc012f799ad1e9c4e10a957b52f6593a5d09e4c430d32a76c42c9d89f21909ea47ac69b5c1259d7e6639c0831f5e11115a8623f81044be3d9fc895b998792a3d68e7d18d6ab6d14f022804a0cce90c07cc3c8687d184ae1e450df34b36df279f6ced6d20e8b7c10f13081963e02e643a19ee53730025018fc14101865057df44eb9d9fb6b00005fde24869bb31a61cd6bafee89919ad5ef6d65d6af1daaecc85a440a6145fd344dd2bb24fa6e60a9dc0e2f06c40a384d68264c6434be977f3644ad5b0efcb373a93f4a4fd5de22747cc3e06dc87515735c55bfce1d1d2ec6376f01abea914235bd250437dac42465399d42e68e4643a171388b83c56d0b308b09b3f8b2b555ca12b3a25671ff725677068d66d9d2c65ffc71ef5d0939b4f6beb87479c3acc047859f425897206989b907881729b3d011491a1991523b96f4cf322e1a43ba3394e4ee7ee54cfa523f20c9b1d61d8dd787eace2e974a1850b76486084ea60f1471e89da360f1823254f33624627762807a2be605695c5013a06572b94cf02193e25020d9c17a7a916b8b6755a661908829d4389a5f7e4aa8d63c6ed3a457de8331306ba749e899c130235e1025adb5a1e12f598aa0b0946842836d7c0609d96ebf308b6be3378335497cbfc4658e34151f1bb42219de5ef413f29d71b5ecc385ac5ce267af787eeef056dd3d8c3dae933f9f83986f6588a911aae490b645a2e64602e8708487e0828c7117505d80ff00e960fee27acbda12a241c437310e33ce88b0c681b6cdd460cb5933941a57da008580ff53b1e28ccee5dc38186c0f07028a9601310658fd5f9f87f1ed271d5d14764a3da3acbd296a2648d43df24f2b5bc20362e364324d329ce8893fefab210a698b35aefc77bc015349618578f8623bb95bb63d11be4c1a01c4d80f517546d5c523715ae0ae94f176ef2f4747a0a78ff244fa2f6bbce0c322ef0d806641b441b73f40f00859cfeb986daaad4215c09b4cec45110bf1e035e956209462c5e6392fc65af0d82ca0fb65d2b8cabddb2c6837cbb51e6299f42cab1239b1a0dabc46deed8eee90d2a5481c7006ba80732a2ca245b7ba3c93dfc826ddc3353100e4e6e238721d5c65e947902075778b78fdad8f37e4587af97306f107a2a2567a045aa3e7bc32656b04d37e93f081953c485d738fc2a38d96d64a95ba04a5b6ac3dbbf0a57848237374787e7abceced1ecee958b1457b8fdc1c66905c232d4670565108b96616086d948f2c70cdf7e8a56f5fe9275b077290bd64e653591f822cbefc7f733cc630ed637579a5a79494f97249bb99ac55134a4cc1ec378a2237b9b4ddfc0851c361827c0c8c563aea85cc3140a6bdae02f7d0e7538127b4720488ca3cb5ad21bf92791c9c074c4096dcafefa4e205d29a1644e98f89f2b8216e19ffa4cf2de71bbdcc69100ee38ebfd406143a4d12c00ec7a9cb40329cca9dd0cef9ba1afa9d83c68ea458e32c0dcfce6cd30ff49ccf6864adfa06868313d4f328a06d6544b4aa617e13464bc4ca0f9e0c1183c7373df31026552fb9a64dc9fd4990750e0e3da49e75835c55337e0a56444c6a77f7fddd3256a92498b14416550cd10a83c6ee169b97fc8f02354986280957434d079369ec04810b99be4a1323421c9dee16dc89a7b202a93343c023dcbfe438fa9862dc5485d4ff096a6bd5a3705afc806b9a704ec7136620282165598a355a050252985bfec1c107644fa247cfe5fe54043f3c06777666de446147ce1990b178f85c2260c564d6528a12cbe0906ac2217fb3876a547e9de672a0015ed970f210df2b3fdef192aa3e5082793982353862bc98531dbc9e5000c56a0f3bc21afb1a2aa04288904b7c055f8a3f38388e1ea4d57eff53e60ec60990d0a80ae5a79ccb5c971274334c2c43958994eb1bc505a2e558ea2957e006904124ec5abd3fa699978ccf1fab77e0e12fb48a4abaee46c58f570badbed7b5253341b3bc3ad8fc28489910cd06e913bcf2130d3418858612756b06053bad323946cced513642476512be3b79ac675c5f2fa894de9502b881ff85d0968a133013893436a34a37412f7ccdfd6b57d186229878af94b78537d8aab4ba1ea61c19ce850f3cfc4a378844ebeb0d44113470469a4cb4855f13617e0dff9a97c017ec6b0fc5f2d8ea67caa3142ef5745a85427bf53525e12e1d0e4c9d2ef1884f7414b15fcbdea7af906a706fde4a14c074191dbb4363fa5ea6d4903cb882485aeceba4ac0b468fea67fcd66b34d5e89a075c8f64df5142641dff3cebe2e4084c3f2fc9eb94b89f22075cbbc5787acebe34043f51b10cc2eb84dee01c0bddc1d5590cb45db47e5083e02fb62fe8226d97dbeea9d4cc7219cddde2876dac4de1f93f151d2f262b6898c0ec494fb60914fa7094823f35581488d5fd2f127682c777306342167aca46cb2ee96b9d35a03510ae43334887f8585187127dcd7050a015c3508acae0808dde29654afde864afa1e2700f7dfa7a0003e2ff0d969909739bb5b1466225be1ae0f3e9509f9c09a4d1ef081c86e7272faf13d023628f069b3040918773a38c9612f29216dec0b3ec95368ec2c8de5630bd71bca7d8b81eee32637d280ccd26e9def9645316ec8243928067e08495f4ee0833b06d97400461dedd5e189ba35ef906f44502982c3d4aabdacab63d1faf5de24c72f68ca9c9f7b4916decb2306e78571144e736a0cf3fd247775212310d51461e1213c8b0fda06b1f3162c4037b9237b1b2affa3e9d75dd384636584a1892ac9635dca371bab13491e8e4bb063194338494271241b0cef24c1df3eca04fa1582cccf8c2e1289958e78840a5d1701bc205db47888178984b152781053e83913645d6f66c4706ec398d655f366d117a5ec3a1ed745397ea1cfb531f093101e13c19cbece5aa16ef66343c1196844a78a389394b98b34df0fb852c4dd1339e605f0327e5ac7bd31d14d132230be76b44a9c4fc439880bfe95ae8c73ea251c62f01be6c5c23bd7529bf7e19b99984f796f8c104abe06d5983cb02d81ee865863198f6923e14400835b76170b1a798b86abef687e466f59bf4d405d1393b9590e8e3fcd823cbe0f163c11cd9440e02e68fa283f839253a7fc3b1c4152fd5669e0ba9921693c1636d48414268ce49105176a25442310ee47b94c8eb6082101cfe0ae5e5505a0edb62da237019ac1730af0c0b08f832b6ff516c6b781c36970b11f6f0f87069b481d31b7591c43cf653d8f5ebe5c0717d58902b2651d9292da7c9cdf625179604a3eb095598ff6d5e5c452d96f5bab8b4ded9fe8a26be766bd59a48455750d8e5d869d86e484ce283a9af54c5e786aea81093b7738d85e2f31bf7c1bf8e120980644f147d299b7cc44663da5b7589338c747f6f14ba736b08b96cc7a0417f8f86031d958060cb15f25d1c76f9bcc7a0d49d0885e3d2ca46422d4490cb2337569dab28c14412db02f0225fa8524fd611bfd35cbd350125580d8191899375f4767750b17403b8e591ea4d471ddb99291c1a0808564a4d495027ff435fd4ec91c14bf4c594e2875383201c6c9e0ea93c1a4fa8432554499da28dfb53ee50aa2a9453c71e6b3206c267ee9f9c1795c808611062bed8bd54e2f4b36acf1fc90f58199c8399fb5a18c33e1bb82c6ad194099ba990aa833e10d9f48e9604baa77ef903179d27d2cad3b73eab6a88e04c80d4b66feb8a242176e49e20cefb6c36350f438860f4c6647f43532009a16661b152b4dc20f54d644cb5a56b09e51d41844703165437884ccb1ac253eca6d3699726e63184f065673a5e2a2768494ac9a503d0984466f4feacd5ce0dd3396677ce03e88b16d41c0299a10c1505a2b791afcb2dab1b0c881b8b12138e587a275b25d5e3eaf4407b57d53f2696b2ba72154372feeb696d87b88dd9a554e2d45b6a0a8cd9263115dbefaa3244e0405a9abd68b7bd2aeecb04a0e1ef29b3ece76067de36082c784b518e72088b27e6bd599b0d23d02d71e1f6c0d1bd8f9becd8fa1b307467c043f08df085ca173b276c34d9a6f793cb814b2bc911789275a39011b917373b9e37ed3772e10516a8a722010710f51a7caf368d02664cb77bfe815adc9f83ba989a5c10c893a158b65663c26fe6ace34158b06d0efe391906fc283a7064f06bfebe5ae7e65181051620b02b2bff646068a016a0255407da004c89e9a5714d1ce0942c655132fad6b6058af31caa592dedb2f5ed53083ed68846b0a0a2973027ed3fd5d1955c24e7a03cca92dbe66f1b42c24c97b1b8e5a31bd92df3f5857671a8a7302435d456c29e8d23be26ab450c7a54e05982353406efabadc3891600bdfd5a40520ae66c4793c51b463038d1a20682d0fcc219df1a9a51f31ddd983e7f3670398137634a88039573f93caef8b3ba05b8d405b8e62d4da6c7cab57d426cc6b797df62bd1f003451e7bde4fb6b25b2dc3110f64a245c678a643f46b37895dc6c7b3a04007ae1357ac65e8444558ed73cd94f804aebf3cd5ece330813882f0a0136daf34549b94a336b2f0011fb4b735a82032382674c3d8632b447668c771279fe811636ed22193eb086b7c4a4d15e5872cb227e0b1352a9e088f0e5f3079952dc55cbf364cf58f57b79314c1a8b783e821938b64fddf0ac5c431d011d79715f8e58fea817bf6321b3a786b422e141dd1380b9550a5e63706518274641dd8a8fc40162260810926b4be265953467a4188fcbb85bc39e460cd4c8ccca607b3c1648217f287a3719c92eaafbf8b7cbfce126246f8f3535e8fe078ac99d590a6fe3a81221ae66943622c69c4c2cb2dad7dc936a405b71a963df02166c960567f7a0e426bb0c4571c681bfdd6d454bfa75153f8ad0aa523b1ae86603476dcb1e8983cced6715d059893170edaa0a99142c186266f32b7306b9701e381c6224615249ff23192e0273ba6d1645c387c5063c32a238913ea1ee0d048208641d69b902d0dc64a122f5630c8e0d6bc3d5f6a30fa28cc82f1d60fdb2889c1dfb696246937049e23a9eae52ad10a4c66a9b5f5cad7a05a1ed8135c5bda9af056d1c2f1cc900d04e21c7f3b8b62d4a4d56798c558663a2a3f469cd14cdbb667d33b0ece602a13edf10e045f5c8f8095cc9a3e5a849903b4c1e6c874c5496e7cbde8ac1cc138b76f78e9d0b5a0f28c5100e36b94006fa8a664d9324640ad1da77b8816eed475f2ab7196af676fa9f12a64980485c5957b943259feb53e41a429b44b88877f72ab4e77c4521f8adb3109fb012a3c6371b47cce50db6907920ea5e5c3fb189fb768dc5fadf3847c65f7e6fbc463573909971250547ec6d016f2889b6bba47ee1d96c9baa8e575f53a3c5f4d9b99d424fde5a257325858893873920cf732792dd4e926064ee467c6f509ba666a573cdd4acf720fd0eb99ea6be9bce9e2e1c965a2e05c0e5a53fcfdd7110ced3b1284882eefb30879ae0f346762a8f07dd428473ee065460fa5a074277a7b496f57501090d35a02ffb336a0dab849faa26f2d5fbc983cb3ca57015dbd26d4d1db2568f424f287e6e39efb878342f28674fb7e3406613f0b257fcb7f86a96e05ab6ab5ec936339d99fbf604045063f437a0f46dfd54d14b38bf51a789bab4bedef1b185ded9bdfe1377c1696f3ce71a21a13bb6c3110d38a159fafaf2d1def2a8ba050caef9011a4ad75c5cd8e6ee6cd907784ae6618e19a2b8e3d2ae64ce806517a1355738688eada081691e9e5902791a63bb37a14444db2909d5e852d23dbc6526e6ca2fd2eff651b131562d45eb878dd6078ac8b62cd9db95dc7e082d1376003d5ccb68b5ea29b6c5bcd74f916db2d9f072c65a2e438f91553de895ff6266ef7a34235442fca257c5b7fd1c68a759a968ff95c54438faf558f893e77ae9ef325cc6e21339d479e6e0668a829a9ca60704e9ff7bed2b9d61f1a2cf2a6cecbcb530e379ed840628e185f6c12f17debadab6d19c8d510fb41bf7dc4ad54c35e8ca9ba80345c27eeef8a83e3498beb738d09583871858dd099f7ef32428e4d78f4b65025e3da4d36ab717d5f623fd09bf2235d6875bf7cf49df7f7d814d36da7edbdcfc1da5a27311fa2524bc6ca4316542db07a5f028c1356c1471bd44995d68ea57433795f5a3dbaa4556bf3296bfbdc5441ae3288934cfba4065d2a6d8e6cfebe07f1a3b0f042ea5ef4d690267d489352835efa69eda77749933bf4812b652082f308eb004dd307b3f5f84152a47880eacb479a859a34ad3d9a76eb4563d507d68ddfa4a917d9ae34d236aa47b74eb3a69af8fe8888b2a7d1fa1bd8464d60ddf84d346eadbb854d93a7d3884e785aecbb5667a01b026805ffcd9582a5fa463157a77e337c02ef6b5d4dc0eb985555bde621a987a1e88e30d156fe619b2e7efcf79a0544bfd24a97318897af11d0d541d04ee362420f451a88fd93e1d3c6fd1fc2a918d1b88dfefa3930762f1efe7bd0dcce067d4fa6ee079803b38e864825a0e7ed7d46721abbebff742c31c63867d06319947cb84e81988c1f155d0168ed264cbda11d1d595692f1e83e3c83aeb8c203a7cea0d716aed1322c828e7db8d0e06e16c1e8b1c7386aef8aa30d266639601eb1ee7e4683abe91c401e94b51cde885278cb190d4a0fd2b78ab14f3c45b92ebf633ddee6ac4e92067d72cce9634b7ca07a4721283fb39059ad70aedf1f7dda2269d0e68a93768ffeffe7bd72446a3e0d5eeb336cced95b22e63ce78c88abb4673bc19cc6ac286a70f637ee1b1792ce74363f712a3fa5e7d6b17b3dcf524cd147e21d5183a7ab0694b4d12e2681d09f6cb89fd8bd96c19443f06cd64f103b843818dc8878b035eb0a0697202633f1f97ae5ee123586ce8b6591a4469b457aa9849812b348660f985bfbeb3ead2fba2c99dba9301a7b483ba00ba7c4fea84e244ef4e1bc01e03e15bc9552d3e891b2a5d8033a240f6d43417f1a61c9feceb39efb10f23030ed4848e372e92d1b19b04cae3df78840959fa2f5a8f6db77d6238b28d4c85fa843e381b1e19512aa1025cfc073b433c9f5b4d597ae7d00a2651bdccc2238847a29b5c4588e3bbf4b4be0a261f0137e3e2d1912162e80789fa969b856b43623f98d9bae13f0045e66e9cdbeb5693e4108c52dd21fdda6b032a39c46173f9f55d4076d4a0ebba2d70b1fed21bd37de07d223daf7a6738e6dac09ccda400ce04caae2e454bc37355fc4f2a98129ce418289c1dba4556eaf9445d8cb16d602f2e6fb4f174eaa2a0162af9955607521a95e557bbcd98d4804f7787dd5979714b132132934a42ffb6fa0dc8e30ab14441a4cd43e64a8ee7aec34e4a996488769301a7e24482690fa5aee429aac08c9d5c844a14b6ea1c5fed789bf8dd947e58c7c040991a3f16252ba0cd80ffd1cc4377c59ae544ca3e4f090e96621a01be4b41cf608490ccf39ae33ffad6d81b316a3e00cfce7604c41ae166da6f95cb56bec1b457ea79653508eb25960241d003f4fa058e6ff9444438ad100ae1b0a0ad332d0f591824d00881ff19049b35a8389cfe3212d8f3f93ea38c60879580188efe8513b00cbef33c79597fee92cd08ede6ec75172ac1a5fa22b0cf8b23b448aae5527ec3523e9475c3ba0264bf619065366130c7b9d5660d7271146cd600dca426453a2560a6ac80a132794fac1f1d3bcccb695dccf5308b3af7e817a3c312a9cfb29db03d8dc125b3b3ce1bced9eaf461fe5108adc3c4d6e3b5a11bec6c39a1bf9378f18c0d5cf9e41d3da0808094d92868270de04fedd8a3672d90377a7e79477753b082e7f37d22b0043aa09e03b991d4ed5dd3138dc240642b07268c00bbc75074064db595f3c58c2420c26e9f46edaec6e928d459d5f076d33a7d0101ec115300f39d058365d7e9aecf3a7c5c93e2dd31d21bfa1eda57016af26e7701df302509563447cb5151e116fe528b5f95d4b7cc87eb0847321fb40d03ad1ddd5c4ab904125229e1580e4bac44505800037676df85957f0518724c8b0a60d4d717d241378ecb0bec0b52d97d13ac2d4d186e9924e0272e44570df3cefced5f430e5e3f4bdc77ff450e638810816ef26b400aa17bf6db1893862f040cfabca950d2c958385956a4eb893844f2d82fddaf97fbdf623a3d90874e2363090c1546071f1daf971fcc7ab8ea9f42dea4db44a14800f8ee6d6f5c083d2878c8abfb4675ab450b7419370d10190e75912ac44d095465d692abcb5f626cf7513fece33f8ba51a7b5d113c1ac804d5b847ed6c01ea9bbab1b5685048ae9cce350ead3457ae18e6f2d92d689a8f48ddddc7e581a1dc75d6578343bb3a0a8f6379e5cd63ce74088d075860b11648d278edc131ca9c1408d5dacd1a0e310387a49e923a085461e6e95c0b3f51f47dd668f4ff639bd392ead3a02a12a32624bb9593a56b34569d00f70a49484a509894d52e44767e3498053309e379c50b4493cd9d282746184479d24ed716d773d1d54c9366bbd83a037c6d2a50678da522e63b7898722f2b15f6f3aa4464b652ebae08354b41e1ba45aaf66c78624b15d89d5506d4d009cbefae30219c0f9f7d78cfe90d53558d2fc700f94204673e0078712fa1dd65babcfc68ee93558a6dc896fe824eb99fa60d7b6b39d6b3017ef26c34f4984b34244d1349867d0d00d4f6029181342e19e64dc97027628f0be5fc1e425e69280a3fd06af328285b806d0fa054eabfb120184bf4df457c8ff87b77e3a8702f20c7801e3444fdc28db40d8366f54862141193add828a752ee29177107bc302fb8dcfd90d54ec36a0c75f6acbc4df56a306f51cdcd971becbdb69bd1efcb065648ebfe033dac5e1939c1ea25b3fc7bebdfed9fb7d1170e9b4d68c6c9325413690f20e9b93c9971c80ec59fe2004b5de19890e5ea59682cfbf5346f80f3340833d7754c672bf45dfed19f0dd4adbcd982aa33fa8103f4f0a5f4f74b9d3e619ccedd61dc75be68e81040cbbbd452d0284717c08579e8969e1655197282f400c7a5fecb20a0242353d88bc420d80992cfa8f9c127f4b5d20f806274f66931270eca82b2af51b57c71d155776d0c0fdee0a5cd266b675e30d0d6e4ec3ca5927499e68db4a4ad6614e032d483f4dbfee532befdc41f3a1bd4643347990e8dd2b4a16ee03a3b69ef1a47310b3e8429084cff33058c7aaf930e5985a721bc8af69b4e7cabace4e0a8f54f9e94193471f35e294a7b8c7dbe32ae74055a09a7304d9596bda4a02563f7852b10c540361b1f69a9ab45f62e7bbc834502d501e142e63ab8cd4d7d7a8f641b515092ddc5133b2a4eb5489f7ec79e3131d9552afc8c872a82fe915662de0c55cbe41c9df8bbc6838a3d7898949f1c507dda57a056686f3460ff265267b8e4f13b1606f66f6876e47cd4987fd695fd868ef7a28ac0eeaac1fb5cd1f7ab62817763ddab9680a9ca8eba04a71fde2d43a1d2f137b61cb5a82e8e0e3ce6b12c0440378ec9fc72a9a9c831e76ec8428230099149b61f9305b636db67a759c3b08566ac55c1a6c6913c015c963384925351c92f9ec97045e7f6c892a4bc15b2dd692a512d82e377c2ab594366f1728ec51c8a35cde9adc713b397c0ca3a76f70303162231f5d5faa482e25d1b8479c0ef9b07851dabf5e6d0c5a86b1df891c149a32926a12077f9efc0d4ddf2974ea77433d5562a28f78c8b422e62b7b49c841f036c570903077a404c3a3e70ca75530952255fca0af5ddfc35e1045cddab901bbd22647a8095e0ad63365b71a756bbbff11c6e1ee92137fa5456b0512e23eefa2d61936ce82f09cdbbae7c979067196b92baa6e6ba0b2342e9498ff19cba01f45d332552d926aa28a282b8a886186451f283aa4c8a0a20115095374838f8b8e480eb04341a92d70f9c221c82ff0041c44b0f53b0f028e51fb7cdeb029579323aa22b2557a4ec0edd05abe1a2c5cd2fa9bd763d57f89be99905171713d13b15f479a2e3d7892628a7309c69940dee6490b515e43553301dc13b3c76772cc48eef89069b85725415dd327bfdb99257196dcad0cc4b1ee341031200565d75bab200043300c343ab533d8f961e52d4cea035751fe4f2f071de894749cf89a6e7dc0c7f31475c0c918a0024b55a223389d9de66210673b89edb95c119d5c0323549294c50303ee42f368aecc6b729ea1b0a927c97c40ff7138d70388455aa0321624dd51fe19c23c006e15efb669b89f8c3887c7ad988797e09d6661b61018a1bf9c08cd8d84febad149e7e5cf8592fb9ca3d599a0ac13b278612371b0e451c1fd24f38823072e335159d65abf38a0d91d633a08201a3907ce0936f39662832ee2c0d7fff15f81c3e61fb814933f0f99216487368258829b1a9ccaadb6628a87bdd31bfd0016cf509c3bc701afc6fd858d8b5340ed4a547e81013b283ab93891a658499c1d3cdf66619afe730ee5948df8afeae8047fa48259ad5549df73439f080d6b8730e2de2c94598e351c55e4396d567bc1c8c2c1d38c245e8bd37300db2798bb2d7619f1296a46ab253ddc22829abcda146fba95800a0eb57af92b5fd8ec747e252e89de17b1959e698851c7e19fa195fbac3c8cfd8720e7ac2aed52dc613a9dc19e22bc0a172cb3a10aa900a34f61e1ff42ac907d230cd015001c5442898a59160b3c650ef5c0bb039c30a86833a0eb04c66131440919a44a1fd8c800ac25baaeebf12c8bdd29639e8ae2b09942707c69a57b2eb825ed5bc87ba302ebdce37046c900ad9dbfa44716ae6ff664792b5ebf298b419ca7ec9e855b8a46119aa7389cc4287c6209902d8739c3905a4f7138f3f1415935dc91845b2d233053a83df486b6e9a917e4a417decd2b72f2a9250cade6068c8d385d5a665526e3d3537a2d0aaf4bb1eb297a3d8ad74ad1b529bc16857cb244b4360a945c8352bbc65e2cc0874277801e99947cec315cd3ae49e0ecb293d562f2a38ae2352984d719989e018a8108d435b764bee7826df841270cd8bc2d749f85f151f700b046aa6d94e192edf9b9a5df94e223f9c879013436e7ab718223cf7a1394a0eb2f5248d0c8cc5ccc3879145dab8ad8fb4a5d63e9db52e0d750814ac5002daa489004705ed3689480c9867ea20ca9d66410f0e8ab4f7d82b1ca43cd6a4d71d3d2d33c92ed6de1e03206a02b757291674df38a37ab5750532fb1315bc4258991c37a328b2a4936f0b2f352805eaeee8abac767dfb601e30c1188b7470e0f552d68dd6edaa570153066d55b543d3d0a1639686c33c057738e8702009c7bdf9be3d22cd4eec2945dcbec8cd1b5b590d82372850089430238bcf6252d34f2610abbaf471b9ed29525ee27244424319606b2d4cdcd0d5437fde7d5fcbfd097fbd16b2048d700c0b281218c44790d0cd1d4219afc0c8cf3865f104672ba41d4a4afcb436a6fb73eb2eb8fa6f650caa0539d3213cf8ffb4a34af37338352d126898b57dd62d0de14b229b8c264f09f0800dc04422e5acffd4413b8719f544055b5b57c975bd3ad519e6eed4846ebb83fd24f5342461c0e027e48a947ab59cdd224b9c00ad4d81d442bf07efa6eaaa03edda115d11931194a4c94498aa916d3b430e6d3cc6a936870b1791bfc8227fcb4245e742971e944950db041c00d01e6260c0474ebd836ee89ed4d6f6cfd34b2f3abc754348d9dce14561905e56d9f258d1105cc3106e326e56702027b7bdc425c2d938c821409232b7a2e015812476e4d2c207670dffa238784e487a273f9b70a035b8412fdc1defad5d0b09df7cb08c64a3a0f9178eed485c2f52eae25b1e3c6ab0aaa406b10cc20d79a7ac305d3ec9a971f76e8a96e54e4d09d9a0f0a5260954e161c0fa6d975f7a523337c7cc5c7fd2e21aa1bbcb479deea0025d637252fe508fd8854de5e3ed76b08c85a96fbeebdb73e3329871812adb417e80b8d3120bf26730289eac6a50a97d3d619a1b423d3392c5781bf0754ac9d7f8855422bb4d20153a730499a01c466f67d174a622f2431a211fa2b4e3ad2e536d60dc4937ebce93a1ba2665b092502d79cef20faafa2e73211759589fe4511157989a4fe5098d0bc717c637e1e3bef49a900a6593b5163fc89efd04aedc57d9e22a48d8a2e3e1c0fdf978a3b216acf74ee23989f8e0e110d60faa913d5bbf310b3be4e09d5b4593d5b348289f0c06d654b4ccf907a119f0a175d7bc989d304669bc604e9299ccc1fb7f51292717156174a688b7b05aafcae0f66caf5233b4b0cab0809159cb68fab39ecb0cd8d3ee2bf73639fc8c2d3beb9dfc89c7691e73b64faaf53c2cc19374d31d8b61fa4f69e13d9495dae9efab5c196e6da1cddf226c70808b36258b900d5f582b0adeb294b0b265031cb16d3300d994d9c3c6b703ebcda1368dfc1696928eac8bc5359c7d870bdbc9db435527249e83d7f3b4a517da7547cf9025ccd7c6bcd4d30ccf0474428b8f787171efece3173b597d0a7cca4e6ed2a30f4c0438e4e64d8ebd9231a9c044b9a61626912cb38dae0ba3a0958047326ff2912bfddb5cb668b05af4a615cd7232abed9d44830a27dbdcba6cb006a6b65531b22921178b3c921fd425571a8d97b06c7c4f078c4ff096ddda38bf07aa45d5f89ba1c4c745f9f4781a0791dd072723264d99cc391271770f57e8cbbe53afbe870d20e6ee908ec27a799521cf188f644601abf0c354f3142fa082c1788782c64cf0da0e5d41e1c81fd4b895c31e50fe404fa2186b07d9b95dbeae32b2dec559d5497d9a9dd9752f896c296f4a41f54eeae925992b095f9fa3df0e834eea023c97c9e5f0e4db1b1e0713fb3c173e2b403393be8064b4d99abc122cb0cc283143e0d0ae2dceece0cbd8faabc95b3125b03238d20d39c55155d4a07957876e1c989431313bd5c902ceb9bf25625a1c96c9fc4c789470812a96368e705f8e5396267df3e584c83894b4fe1d05ab4cde675848c10f78eac7d25345860b029ad32570ab868e74804262ed83b2edacb6cee95c83562d373d84866c86a6ebf01e60515178c1426c991ba86b947267585363b3f4268bb4de418c979e50d6928c00774c60d449eac9c502bdd5d85cf84308a8399cf265ecd88a17342b2bee61b2039cad99a0cf9dacc18c423f5cbc14be024e079235e486ee4720b0811a79fd38207b5b48e06542b3e809442a3dc19e618e0541de1ab9a2b42e1eaf8c86a5885ca02742c5a355ac4fbbc3acca2848d22497920ca524caab274e25de10d2054b12b05931160017dd35b63d56d2b4a287af698df5e9c48b6e1c2377d9ef0c38e7ff1192a9624941db93d3ae733fc219276897c36fb04289f6162cc01389bb3fc6aeb76f5d81cd99ad476c56578ae9ee2e0197297e227bec505606f56cba9ae75cc2462dea125ffc2f13db1e86402ddcbe6ef91c92538f23a7a0d78715a8c5d879e35f812a232e38273d144e111e492046e521c145d9c6488ef582c331981d48e92c0112319ccecdd3212e77f762167e4fc1dd387ec20407267f24b26bc7c7f77b2043bf6fde4b972006b41dab6394326c746fc04727b147b525ec1206cb858f2ae94be85636d8a8320457ea012d6a613cded57e5311cc1be9aa0bfd9ecaa85245380ee8fa10347da0caa7271c0fe02b6629b35875769c1acd47e58cb80ba1221770688cea10f9d47e0b8b3eab87e80d1ca95147180208f54e8e7d33349720b994e0c97f6f51730cf7c4da61310adff11d26a2859e96ae32b1cdbd3e42a03f21aa296fa5e944c3d0a6a5db78fefd3c135efe3b40f851645e299e994231f256f98b51161da353e71b5c1fca222bebdfa7a796bd0b8c35d509b12e764d125ee3ef20ddbc36bcf2373ba9c3ce596d783c464e23cf67445217cffa4d3c87cae0a09d68f8962a1b0e79a6b7f70f3bdaec7a850aa1da51ed65a4ab81945d45de509bc045803586f3e576eb6f97771fc29d4fce9e14d5ac3fe7c7a7fb20128fd46d124c05d0808fa75d0ca9d867ac6ede4ed2c5a08e6795208d5c4a0d4a563d02994f219638466b41087dc8757f45c88438b48df0f35e37068a9eff866d1a1d5c43e322ecdc5e91177ee82f7d4966e30eb51f1ab92d14ce25061fa0f1ab5e770faafb421e091c5ee6b1b5e995c41d6b5f98e3cb48c957240307f3c034648410ad6496c15fc4ea547b94d166a87173b85c5727af04cea79040617a385eba39c2085aa92a623845483002b7f441918e40db6ce4165143001e8a6db8c680cf257315de0ffcd630184f4b2cef1379dbdede7e2d017ba0960542b64ee8dbb0845ed2a91445ce76e74952be58b73271787b4c84f70b5678f067fe33ea8669b9097fcabab60acf929e1bffa08fa69c77b2ad76b2f071b1cc46344f841cb80d238860465d502518b5d22557422d196875c05c6e70c765c1ab4cfebe21ccd1ae939df45a6af7402467ac2aa78672b15cd0b727c8410cece2a0268eed955f5aa547975a43bcf0b2f52782a9a70d5354be98328e16771358426bec41cbcb45a31d5c14b9ab87dae02c01129aaa815d796264f451cf24966a7724e9f05dbb2a5feaed51a3aaf3238bc7637115a4a6993ff04c54a9ef7dd8eeb636e2669ad19e867056905e17988100cf30811aac0ca5d1a33dd11cf088ab83b8610721f9a20505607ee77f736d255335445c40dca8997212533fe047b465c47b10bb33b18ebae47bd4cf6731f8d0ac88cdcd689001dcf39ab1842cc27f955a7ce0ade539e962bb3068f4c832d264c2cb925b94ff6adf5fc1faa1da5c0a8598116d80ac0f3a39d237108acd5394758c0be0522149533bdd14538131120d348cbcfa7a6e50608a32f40cd6e67d825cda34ee9387a13e1638f5d0a1c94244cedc9e484b933d206aef878386c96dfc5e16ffd7c4b1ceede9a83e7c78b111867da2ffbb600b5d9a7c2bc9620d1dc83762a24fcbd3ee3d57a05299019a183c311d3db81289087f4374ad0449b0ec3896587459a2266439aa8044e4dbcf502c69d25a677f549818c9936756ca8c669a8b11a07bcdc8851055a7e58760c4a7ebc812dd9a9dbc6af3e5c1e5c6b8bdfaed7ee3513af240db09319562fd7d06dc7333eb761f1004b253b88bb687b86db16f0c1f14bc5b4674767dba5821543db3e16bb2cc670b4b44a60b5bb23d38145ecfedd3834abbe508bdf055bcdb51bcff66556163e6ca7a7ef745637572076b79a43900db6e6d2d82ac73c918adac9185b5a96285379898aa750e3d06df60562d129e67c41ea30fc66cb66199a00c37b8d444ce0a1e6dccc7cc781b8c30272b13dcd64ebe0c09bc63e6979f08843fb6bd0bb831ef6e7a19b73750f175c3f07ad3b477e36c99a65b9ef3c65b225f19bb4f78ee63bf5be3a2b21c72c09272f0630a82ac740136a6bca21e1895eb5bb1b94411a86ca8b298d83f8b4cc4e2b630b4bb99d8816fac4e9899603a73ca5acba4669589a5c49ff49305bf8c067f9d61ae3d4f5b8b16034cb8bb6977dcf669342e734f83ce9c039441fc714c4e89a716418a833cf6a0800b149bca83a7a6140d19100ed72a06d06c747b9945d59894a08e24d8bfbc2dbde5c017735969b64bc6f521c700bc669665f95221766d81b7dd4425a1b27e55bcd5a01b1aa872f3b4688f609f1aa9cb3491c1adcdf9dea3ec416ab23f5422a7c903eb2f4f6863602f5164523a39dd1278ba7cd48ab7d0ac848a4ce3d2f15559c7350c0730e7f01cd2d0c9636628ba79a2c5d4648eab01053aadeb6fac84c2080ee96fbe3b177a9f3becff2d43584b9145b53453f7d37d30b998bbcd6e63ce0b1fa64976e6f2a954ef64b209f707b57b3c868b08d5f134029ffc8f475c2ba05b322693502badb856602f6192ceae9f5d7391a2042a2f156da08a05d3ccc18ae9e807667ae1b7df5416a3ca5bf9476a3764157911536c3d1454b5c8df5c787a6028a50a8e09a640f86a766fcc41319d2ce5cf663edd74155eb65c5c27efb26c72ccb9546285f8c9c8a70690962416e013859525bc6c2647c238772fdbc00f282a8d62001b32e7d9ee7abb28f6b68de4ec6dea82b084c3b9de111b9dcbf77d0c148b25786c77b1ad91f09bc669ea66a2282eecf7ae645ee98aab7145fa24604e9fc1538f807b63eb9d1b598acd4cd1adf7ab8c7397d283cf124b82ac1232a2e58c8513f86c80ad1394bfc0a4c3946f00ecdc0027df8a6eae86e4b7bb09a74a5a400911e2d8458be57d19b85a8745bb512a570849a2106c4e056d2daf808aa2573b0821de97a5912890506c2152a9a1ccb13745b0b29b796ebd6da7bbfb10c1c855de4bc63508af19d90456432978e15e2b5834d92dc8d282a24073cf5cb8673cc30215d8125f2af9213dc454076463dc6638466e5a36a81edf9a022e2202a6c61148bc6ea0b2ba944b3ea86b6bff0a3cae8f3f03ae4bb7d62ee5fa843cc001e76ce6c8a476e927f619fbdf6479edd70467867442f00842d32bd6a1b4958adae5d63ce298e84f22b9f032dc219b9e250dca5d0e64ac607b94d30a0fcbd8c44434ad171723adc01766e2cd99899ac4b47f99a6903029b420a069147942873df33faeafc50da8ec411d843e94f10eaca4ea6ca653cb82f0df6dab48ab3311f418c3ff02d3b78efa4279584767bbec2355e81ef2f318d0b35a47642320934ff9654adf4b1b828684c0aaefaa0d939e6d865f7a6c3f5ae656bcd946421b72d2c4832dac116cfd9362f83d76fd1c63df75485891786a8f1ea564035d666712f5b2463f5198a62337c3c0899ddfb828491f6f0d9ad2c95dd24a73b76ed08aa05da7cb058711bbb6c7a56a5b8db75b11e160759dba1b5213288ab8ae7372936cc6a9a268ac474877c944e880f1c74af37643be85e4a6ba836ee38a15df682e282bfbe03ee1c3ee8c85eb08d3c0fd38682d23d42b33dc688fc161f6e16f9728748fe19de4fc3a0be1f4a535cbfc72dc3780951ccb2cdb65633361781e9954102f03b42b8a86eb99c7b7cab8963b4a757b3dc8ede50f5afa4666c9272da34422b257cbedcf1307531a1142ad5e06dfdd757f655be405dce58401bc3eac8567b72710e1622d91b88b1c8e3252b9997ca62a4c79aff613e24fd2f2515c26bdc37f7fa78aee26bba19c0aaa0d8e25118566ced9126ebccbc24f541fc015a022d0400dea8a4f107fb81534b219f9c24d0753667106a64b9a84a4862d818875d57240757c04835e7916515125b54f87291f411eef73da17645817f45ed521dd95a6c89b9016aee3e194953cded56a7de7ea876833188f26116a6700fd1fc94658d4be5b1d12f492d00940966496a110a64497b6745028f12f95aa0fc8e9800bd953a390d48849aff826db51cf0c8a550dfa8c6a5704f80d86c24c0b9c8cb1e98b7e249f99ce6b2ecd7b76c68aaad1abe5ff74137a89bd2dc2a0bece4de43e454d9c84d9190690fddc10b3f5b7a4dfde21b2dfa2840ef418c08c153589509fdae339a61e4d6eada4b4518a7abe0a50e0e5c209a3f00e06b6833b020e14b0ee1909a8108f7d5c491b2bfcb8ccbd9514c3a41de40e35762a92e8ed2c992db9db4f6e24fd68862b79a0f252386cd458491c4683ec68c9c6d1e60dcf0e2ffca4f8e63fd70e0f98a26b660c3d1c2ca563cea0fb1adb3e56b2c087e4dc9be6f4e64ae805a821de95d2b891abf601ae52e80759397891412565263d81e3d0d09c4d8a62d7bd0ffeeaaf1ebfb3cd904d7bb80b461f6b796d2d16bf8ecd082348a9c951c952aec592cd0cb8858c38e8408c808f185da066f846ec351a90f18c8d9903cb1d6671baafbf80f79d6988e22bea664538fc4928909e7c55c1a88c734d35d43800d195b020fbe5a6b03530a7c5e7a40681d974a019a1bd2e1b5951fcbfda65502c772808923bcffd59f487b3bed8b1c8dcc6dd8ef2bec9c61dd21db6711a5d5001e199124b7073e4ccff57ed02191fed05d9f71edd0170c6157124ca15695a72a8dcbf1e0db5117cd69e0a6ae3714cba01c3447b3ad44169dfbdf43a4e0896c9fc313c8275be0577ecc3d634f5fe403ab3ba9e5dff9a057505d6219397ed084743936bfb056abf9609eb070c54481c0f495019602a084f69d6cf4b0655e634097e9b00d5faab2f95f3814b136733cc18b0d07901c1fa39fe562152a84f397f40849474b88dd752279c75a968ffceba79755822fba81c4b2b3fa557f19e9c6e801533661789d81e7722e5800a554d04b3197609c102e57d2ba110e163c35674292723145ea2201cebd5d99433fe4107ae96116c3c6aaa67f104383a7a66ae0c94e37e19aff0d01157e4b3c120c0e8f21417ef911940d14832fa52b862c158b09f3c0d91907d27fc5e81d9d750cb4292c95ac95110f0c72034ad71aea1bb96624b934107ecc4ee8c15294a00d9710b8e9bc118150fadf6cb94d913344c68e86e8ab2b42f55ca8889291d6996e99ea72f0b34e086844e2d8d48be56bbd2da9846316ebbddc8b26b65be040894cef9391fb4ba3a6901480b621b6ddd71f45e5535868c01a8e4aaf94231d4244915c0f9b22e0a6fb8bae3bfe12291849e08fa891925eeb9b1672520d4931dc89f43044df0240508cf5bd7e03c62cd847d9d2c9839caadaf02f3ea52db535b11057a89875f2f44db775165e358796786e646957cbcc133a47db777d9f5c37c18f52a8838bd84f4670b80321cea3948c5ff967c667ed899076484be64c64b2386d6a09b1bf02168933d6c014733886f250955046d52586eed53b0a9b05b04131405c1d513ea2a1651588b8b79ed3936b41b060d728227592a496fa0d2d5cdf28619adb69905e888996e1e30dc710ab201110ed35b7d0a06ba6ef27bb83c8f902a981a05cb552616ec8886aa4c18d074eb8dc13428eabd0dd33033f55c92df9f37f4679c093e3bc87ce46169172c8cdb3204dd4a445be613a6142155324e56c3fcdb7444b846bda146be77e3aa94dcaff9693cea22e8e72b36a6e102db8a9d9c56301b6997d31fc3372da20c60d887d2c78996ce02843065f0a95a392e609384ecc20f7e65e1213650cd43bb992d55cea151ea11a22ce849213013ea286c6fd0e4063361970c2e4a58c4d6f2c0ee7d3e15d942f496faa9dc3762ed302e984e56526cee4d4db2482c629cdf85db89311e9ef96747553a2d6a023f9de6c5c33d04f5d5103c3d18a3edee6398818496ba7a094dfcda7de3f1b19a93f90bcb7ea36791a076f683f77acf46eaf7f4edfeca70c04449f27fc55749151672788177d5294b0af77a4a1c10ec3e3ac83c5c4cd454d2f5be1a99ff47ccb5d91440b2370ac2edb81170ae946d2f43506b410aaa57f2c50acdadacfb21fe949c84d6643ed0c35b4fb1a0b090b8a7f2a226975ae233ac8552a5f5a8d559fca9f2f40770600cc27bb614efd19240d57cc1c805de6b52a769f9809112b2f29339b25d793ee6f21623dee3a95bb8b9e1e9dd87d07e640b66d3db683722c3fa4924d52cb09e15a14e518f339ed202a0f405e33c251c69147d9e296c605ff121b47922b838c807de58223210803cacf4f63ed6bc250c160ca8b0c829ac44f8ec3d46f7b49dbe7c3549954eabbcaf1bd09ea327b194231b3bb86e786d9252c2266cba36e0f3c9603fb26424f20a92606af85afd91807df12e5638460c0e32d7a14cbd803ee508c4bd8bacd98cbbacb1782b9746da1928e2beb1be9924682d97364b924198554107f416e51056ce0aaf68587d5e3299406c95943622b45838f6dbd83ee8ca2c5ff4e1590f6004df4894de68f4d925b586716bd0a883bc84fc5023766835a971719ac5f01332dc70b996df2b7452cc8bc005b5e7120ecdb3fad4b00c1011c62fbb8130b49b4d62b536826668eb0027f964ab0494062297bfa24c7416d8dff27ddac834973395df5c83e869b9d854d329c6b95c5e182fee2c0aa0160f99ba9462181342489a3002dc329bff9cb93dcdb52e8200638ef182284e52a27f8badab838f672f86406f3d570270924d30dad28950a5cc820a9f69d9d7358c8530e9641a847a9e24e1af304c5dba78e934707533497a290185c62cdd590488cec9f5b738095464f5280b78479dd9f700a35786f5f947c206ab38040060d3f5e32ce7aae9979ccc7103cda4ae7427a9290a93f924036df7237414619dba30fda24158b7d9eaf6c9d80bf5cc227de00f2b6f33a954ff662d2fcabe5a280c79393a84590ee517ce6cb8c71480d6b661303eeb7a3fc8cd8d535804ac104fcb278af55bc16a78a68a249df1dfbdbeae72f2f64ed89d3084d57f1d2314a8fbd882c4767e46793db05846b1062b4b6cad34602bd3684b80c95adc90e03403c6107c9da5800ba7755b669f6df84582a5d1d0e3eeb6b3939b800e6e7dc13183da185c1b6bbcbbf1b7540f8c287aa6218e3da4a02472cb4c753fa47422124ab067afc0c4c97af92f306d26cd1935bf01913b45c4ef8c811537283b0f6fdf46e6683419d194723a013f4bb8812342627ec84e6bf2d8bde46cdc598b3645d3b39f20be70b6d980ee0243265ee46e45cd7507396647fa8f4f4b078bb3ad098c409d9f844ea54dd3feac9a4c08132231894b94d84eb0f50988946998be46b0c1df81e0c711aeaa6d5f8e18ee153375928d1d61af449d5cde51c7eb4ba9a4da3b432fc4c9970cb81b6759f09f2c510fd18e766744bd2ee2201a24cc8752305f6e6f8dd81f0c4bcd06aa0933f98f1d3c7bc74049f07389d2c0ea9d4ec6a00e1f3eb85997862409b67682deaf6be268afed76d45e65e039b46a9e55a6e499889589a98c1d54fabda8cccd309e9b8c618ac454553714d2f6314a3e4e1f98cda1c52bd8e86ad9626a5146d0c99df4e93af485b106d808cc0419a27c3884c88dcde1271a10fb25a539357f12fb8b358eeb36ce11149192c2f27e5210f6c2da48dc66c0517ecc6d88be01a83913652af7808d9032748ae3f39336d382deafecd369867fef9d12914cc515d6f19d8c9fc2d985a9c49790a0415f3991da90ef4f6a59bde8825f9a86fbd85169f8f63b813673802b9b682347d5c441230b05990c2805c4be808fbe44574149f528433f9c765b72a11b522addfe8601f06bb31052d7a426950975026b90339bf1712876d35addd9d9a757f36368844bf6d30a287640e52bc299b8e12ee80c8fb7e0ad443298715534ee2368da5cd300dd0c91557d9fbd80e9ee90265d6f0ff3f18a7e18beaa49c06c8419f09f84848246a40a304554a8ef57cf455a06b8ef27035d811114f408d7d23083e0d5cf201416d809910ec02b909ec4dcaa2e36fb242980a0d66cc883a8c290da16fde8492797bf2e3d5859fde0ee264bcaae1a5f660455ab2dafb897f63069f240500db4b0f3641dcb19e4be9e16abf66e8d40c272d90707605cb647f8c8f9cb367b9ce5bfc451fc152f304ceb59dbbfac029009493460bb529ddd64312abf0e80b62a9c02657add86e53a10bc28faba79d465a52f95bcf2c84c1986134efe4c8def989c4cddcd3331cd517a9ac7daebfba26446d2ad7404b520db43f495e6d1e2bb134087b26501a735111eddac6eda5e311a37b1176a3000f2316f20f1bcdb466c285ff9d802c88452b260cc202d1c302822dc1c3018b5e61a0b542a15d6bc80f88c34f44e4af2e69471a571aa8a188393bbec2adaa01fca82959acf4a7bc79d77b4f2a70f12e85098c81020d4a4f7292d4afb9637b1a186d50a321747c5e43c2ca86fc5a354d7937df44ab6c7c5b311f2f9d325836be2698dc2c61b4448f3630221221cc150669fb1336e498e19bc75481b48bf1c010e59028aa7f18bda6503092ca8900aecd9f33416f24673289240abc068a93b41622798902212e14f347e7aab016379fed817ee6ec47836dc77b966299769668a93081901b678ac7c752655643780988eb9bbeb58ea5b2a9f57a44eb3e782c5f47387eadc1b305f8649c001310a068cda5b85e3d42a3b3a2057d732b6ec6f70201288909fdb904b7a6cd26cf7d3f19662a725adac0b6a885d31a4d07c4f04c3e21fc37de6a0f025cd7d67dd35e992fc45d8de9c39b647478bbbd2ccce5ac1f2f3eea89cbc0abc156d1980dd13e9b3a4bfd63375470b2c06586d4e83f3bb6c915c71a7e2b135c523c0ea1b199b0273b7a68f64638db81fe0f4fdad49410212d9946ba1ed13d188702d96dec41157055273c86cf7a638d8f3652d1fcb3a8bbcf468eac8460ee2e02a96d8af81ea07b39e4abd12e7541ab94ada3d6038f51c8c5a02378e9b02cc81093d2811f215534f60cc001009c7029017cbdf644802ffb18514ba7fde37650bb9c2867d9784815290626aed4fb3da6309eae9c9f05389a6d77c951e2f2afa90f437e7432d87a4c547a84f44bbb6d6e41f4e4021cca122023577930c5720be83334b8cef5106c98d05ca5048ff82a00a179686208a019e3c09715cafb3efa06880a218ec528ba999a3c987783b647fd49c24e3f92de33512821c844f653fea0e41f05666159d8d1c6e6be8c62b0af1759f2d59b3d051b4e331ba638e59ed81e84140d4e54c758ce24b6f8f9c4c043b891f9d53c0630742bd7b16d0d1d4b28849f92c193df6158b6c20f05d0b6f7f916785b33311988c8b13bd841a8ae47ed96f7381a97d4c115592407cbebe8718b2f1fd10eb5199e4a9f2b29f3630f85553b87c5cd9403b35bd556be29eb15eee596308995dbac1c700eed3b9019ba57278580d2ac0cd7d4d933712ae57f9f50fdf7cc9acff55338a4f9d7e692bbeb5b31fc5a3f4ff14af7f4a76581a5a4d81a6089b9321508b3c11d0c68815b5ef9a550049ea0eb5764b8eb5a18f19a20bd01d0df3c3cf31995e00b607e6f3f0c781f4c5c347cba5b1aa218df8f63704c0d78ae927e6ce25c0fcabd71c372e671c15010650780f15fa6165caeb4298882229365f21461d4a12042492688d2aa513435c124556d228bf380cb38cdefdf2cd76eca2fd7ea88b4eb7b83f066dc219340900103049486cb629fa6fc4b52aac615cdeab43dea128e287d83d79676471cef2dabca57e6d8c54f4fff3a40cb5d71ee87ee75311641d5658ae6401bcfba809ada21a947fac6d741bcd67ababce379503bbded614b4e5829d95cfaae7a667dddf4e840bb23abda50c529af1c507a21e031e14f1338a7fe29da19762042b0d383d8187bde1b7830db3abefd0413cfc7105152f848e7d9795b12a0dc9074ea9c4f76d0204938fd56d9f6eb3361579e962a8c5712e35d85c906a40e5200a5e44c705bebe694d82e2bc623af5b9287b3b9ccf9d8f99440a4a1a92b34fb13678790747ca82d95c1f1e7228fbc5b74c32a03fb143935fe538ed5064a0a790ec1ac95713a27098c1b33bb36b15f8cca3d398f7737d83e261bf2e81e52e2a99e8548ec5789b39f93780fe4f82dc916fd21bd285fc96005bf8cc1c0c6e262862354c7a7a2bea157cc1f20e0a83780dc172b7a43ba4683add0627004f9bafceec7d844b899af437dc0d9a390bed3c1653f42f4e38d029ad174c00214aeb79e9af18d64ea10afd03bddee1246115d4a16f6a84845d5ae8bdfee89640bc9eb988d09f751c1071d4fcd7a888257311159a56ad06f2378b1af325be2d8e28ea9e56c331d269a923eed55431ffca5eb4ea55b0be8ad4dbf63971a929ce5c0197dd3ec52f99c08d168b3f6aa03d300d8ec4943221ed80ca04cd3350d9314c08e95af9cc4c537b88e6257d8bbb4bf51cd622b6ee3a7c94bf1fbe84d2ccc306903b06eb510e80dc00209d161694384b5f8b0edea2374b880c6b9c62e8e0bc0cd182edc0184d6d717c81700b40258f88d5d3ba9ec7709652e570158758af6b47e1d3d4508b30afac98916495a94f64219dff302e8bc6bd40003ec7683d4200698f9608c482b678907209863959d80ffd8a5bba9521eeeb1c47dfa2ef0122533445f2a515333b8c005cc7227c34a9d6eb4c56518ff37688287b2dcbe2870c830fa37249080668f8efdc11dec255e61477b70c59c7c5e7d47595cf797a881033473d81e7b2d20d260b92042b2b9be066c7425a7b1a008c1b47e402153f52148ee5d9ad8ef3f2e4a11ee98622ca140e05c11ebe21004305fddeb78896bc8268169d9df760d38316a25f9ce36d408bfd02faed17e689020490e624516f7b032f812844833ceaa89104501f038cd0a9dd287d8aa85c3bdd1aae170bb0a4f6f160388a8418384d0557555079048f320ec7f353c0c08432a3c0fcabc3e794c5f16212a3e0882ddd63248335918ca4d22909408494436861c838005f9c857f3c75126abdb189cb89a0c7610335a6df99158b123870c26b65fb80604fd2429c17eb6821a755012d488c6cc2178fa62f065de993efcf229ddc47bf325267cb7e1e74c2e9c610e72f72c2c2634c760c89822b671b7263208db68840b180f82b975644ba5c01da7568566b21cfdc5d6f3a673109330608cf1eebcf638281af273dfdd82d81c60627d9d4eeaef9159259b21bd9b8f272f5aa3015d601068743bf5e186f7204be06194126093278d30a70b42cf7e6fe64c8056bfc64f0d9b78e906e5d9a8b9464adcbbab5ab015e3c03816969f13c9e495b1fac23390348f5c5e60a296b497f6a9a061e27bae8d1b4e884236a500d400817e40531e04a0420744a6ed5d7ead77e08e78813b4d1205c667cda20f5663db40e94abfefd9818d5e01f4e57dfd6429100a505ff7603e28c0e7194a92f1705a40407021298d3dc629a5c0296d59d5463ff5904075b15b5a94e2b1133fa8d63b896aaa56e08ebf6d3f14a047f3bb7b5abcf3cf600e861a27d10c3abcecb8a285a2524c952dcf831ee1f3731a5fa91ff5505cac795d34046291f39a4755b779f25cd19c99e442926d80147e248cc000d0f9173d5880ecb7039aadda8a5d3054aa9a0e39eae8db1c58faedb4c9a2944dd88bba7c339cec2a0bdd39357adab535cd3475c50858c67fe121be8ceefa67f4c101200cc1a030931f8f94673f85ad65e2ccf4fc99d55fb7522e8d26a3264256f626bbdb965b4a29a594016c085e089f0849808ef8501e2a0e41633407295494302845435cd49ad082924c2586c861caa484c185d0bcd921c3f22cad441e076ac8b4f46ede4dab9c42d4ab326fbdda49bf9b1a327dbd6aaf864c5b0fefa4dff551b9b0f60b6d2c04dd9c2ea5945206117fc2204339a594724a94adb6da6a2b6ada8c826e4e29ad95524a198e732221a79c524a29a594524a2967cca1105151ce2ae26dcb991b8d8868b36d86dd9d379b0a9434caf0d96aeb4d2965ce92e3388e931c2747a3914b131de9799e27f137d2f005a0a2cb7b251f6d2bfdbeeffbe6f749ef1ba1b4e7e27492a4fd5a56987efd860078dc755d87bdcdf33c6f2365128944ca1ff77ddfc79546a552a934f2485f5792a88c1a2fc079df94f493927ee3055eb29ea4e594f51b67f8ce4927a4350882a0c9743aa198dc202a968e68932daabd741549e732515121e9b85051666bb7bc8da20ac9bb378888d276afd83da2585a5a66cbca0a49a7935151ce39a7ed783a222fbd636161b12c2c95b24c16a9027f3af8a30b3f1d1c7160064190821304a5e91b479586c9960c6718e9ba4e863248100d809f873ba48d2833837a41d918f9e8f29392a6cc0cbbd1beb6be2ed9a06cfcf4e92f76d48d66e697645ceedba7f5bbea7d5b4a525ec9ac56ab6a3b6f7f9f7b4e228dbecf2379d94af932c87e43007d4152c2e51226978a8f96c6c70c6a550a2553f3f251ce5c3a7c94351c1fa5d00340ca702c6d1c6eda328eda307eda339eda25b86a93e0369b00aec27e790abbc6bf2df3347b87c67736e0394bb47c0339c7866dca9429394bc47887c34fbe79df7e7ddbf56d1da056a550279b528e6fdbbc6aa736ea6473f3ed9a24dfa62179dfce91526990a694436ffcb66ad27ce9c97dbffb3cd34692a373ea390080a3c3f5aab139a1522a0dd2a87c9e530f24a2bf5d02a85529d4c9a6e655caf16d1294501a6532f2714547df6ed1809a66671b981902dcc8e060e98dc35f5b05afd92938cdde726066760571b87619191cae82430607cdc697665b9a5d6936cdd1342a1ecd9e39ba047023b10949d84868c296cc9652c411d3c1883099667fb863030db09cf71c8eb3731c85adc37d6c97a3b6e8a7fde2a96dc355fb86dbec01b8ceaef113f6cbbf8de34d1b098d973a1d1b05776d1f5eb375fcb54ff02ec7b639a0a6c9b16b0ecdb961437c19400da8695e2e1d393bc79e393736121bb7b17fefecd8509a22a5862939cfbd3439e81d8aa403b234a84d343663fe6fc7a4bc6fc36c51c5fbf6cbeb1e0e6e243d425991e45879dfb6016a550a75b229e5a0d9020877960805e0e0aee17abbf8b75ddeb49104c0551b090f2f6d4f6d245d00022000010880c66b6c243401e0b16de1b76b805a95429d6c6a5eae168f66ef7095bd1ddcee7ad370d59ee1df0e4d30c13b193b159e9cb54f27d78ef24e85a4833ab99f50a770efd892c2f8de266c4961a40c3f6d96a3b4c8f2beed34a056a550279b9a974b074e29c7b769805a95429d6c6a5e2e1d380028e5f8f60c50ab52a8934dcdcb55caf16d19a056a550279b9a5729c7b759deb75b42efdb2c3b3389ebdb2ba056a550279b9a5729c7b757a056a550279b9a5729c7b75540ad4aa14e3635a51cdf56d16fa740ad4aa14e36352f970e1c009472885e6aaf5cef16576d16ff36ea4d1bc98d976e9c66ef2c2155360c268f21ff8a7713dc528a2d5bca9bcdb2a51457561b0609d000fb15d8dd20e9e8190d9a42295b30deb74f47a81234898ebd3395e870dde4db2650ab52a8934dcdcba50387f76d10d4a51c32deb7b5caa6d931d019b42a45c466cf214a396af64e4dcbfb76e969764782f7edef4d1b490ea7017529c7f785b93a0906a1d9e4a97341668ddeed56c7b7b20829819a1086dde30e705cf9481eeae77cd7aeddf38fabbf9de638aeba5d09b283da5a6d155ad46dff6e9eb3cd167b9306b49bed9d6ed6cd24161a08ea66d939aee8ed1d3a49515391ce5bb30943dfa0e77ce452a4a274e19022f5156925e220fa481d97f7f55b748b4620025947ad1137e8572b087c75ec5bd0df95c5944ae1de80af9b84913286ab82c770694c993245534b29120f8e428e73172df3b3066b7f3ebafef6b5f5c12da5a8b794a24c0d16fdce7aa50d3ae825d7da3952018480a12eed70e41c7f2e5b965a3df2edfa6857e7c6199246296985d20d506ca1679ec10fa62e43eda7af64a1afd3ea7307d97ee8ac3f7403230f35ea261539efb85dbf93ae917bde71241d2f8fbc119727e568a62e52371aedf9a4f99d97391f8d4252018478e17c4eca96fd4cd2c9d52d6a56bfd756bf75e6cd8b45cba3bc933cb69add6325fa39b4e2630daa351fab5000a2e011f39cd077c4667242077dacb49f3bd589958f15a865d623583e562364f8588dccf0b1f2f0b30ef994cf13cac78c698463ce33c2316b19e1a859e1e82da30cc7127ed47b6709165fb5b885d597856dfce1dec02a6789161b30748baf9c85a5c5b7169696705f2ba3442bdbca1cb53ecb0ef7ce069c8a9f558a9fbea21f6e29758c358a953dbf6537596d09d0007b16bc7dab9595bdfddeb2c2f816fab952d928576d10e52a3f9d508e512794caa65073ce5ec2671f4ba05276ac6c5bd4b63caabdf1c816f5524d9f7ce4da55bbf4a59af65cb5bf21d5264d1fd5f64aaedadd976a5abb6a8fbe54d31c0ae5dca7f60c7c542865eb1492744c0fee71de30de8cb268fa0cfd686523e5f9d1ca68ed472b1b6bec472bab437eb4b23a670d52eb569b41c124e6ccd58eecc8ea6cd46b0c76ba24d51983ed424afafa48d5abeef22498e95dd7715cf5387bbb3d7fb451a2b8c2a40b13d41f549f42e87461b3dca8d6d1b601438fae25e9546b7325e9e4cd574fafb5732564346b13d4e9f53a33f33fb2e67c64a9d71d64e6299db55297d433a5e10ab1945a5185c81e8f6f6e6626b76f66c4eb9b5b15340c06fbea37065c22615a5170efbd9925933d94c554a3561b49c7decb5ab95ce67799a463f1bd2e33cf6bb94c65cc408f284df2465c584b9e8f39b5e7750130894303665940d4f539901d20b12ef4085e8ce44716900fbe884091c431c928627a5106f62508888a99355342c5ac8700ca6ef70b93971a155f82a609b40609cc294fea661bcb0f6a5a083d5b31d9cad7c8671f6598f8ec323f12a7e4b97ef1d9471c433e3b8e9720120aa7b71e1793fd823e9f1d8ce5ac3518fbfc2371ac676fe5273fbe047df61a0122d9ca5ee301cd02fa5cba3c9fddd6a2cf4e825975405b002671509fe593d8670702ab2f2f94808ff9a35094adec3e64be0b91685fad3210580b120d240664878ad9b9503481a63eca27b0cf62f8fef93969edd2d0bb57caef748dba7413eac2ae8542c985269aab0e68af491c196f35ec4719a46b2b14155360f2ae9958f758bad039fc1116808a560c41aed5a868bd078d61811e75ed0691909016a2a2686b7756d3422950d7885ad528d130d8b7a9811e75ed758dba681321ea1ae282481751574b76a9c3d051b414eada8981398044a8ab858619861ba2f6cf36844eba8c3885062c199a6104a530a90bf428879c00d5d775eb154f5a6dfc54166c6061306d8f27ee172c7417bbf870f510be21004ae147f641e678605948c10623171df4d050ea88230c21c508b21614e8080c660323394a942980a8e8a14921449b22f6338ca1e6a8398aae3edaa774e6da4393a1e2a4da872972d0c57b5018617ae090184463c468cf1845f48cf1e3639a309f7246a240312265dbb65a5d8e76b312e38ab79c3d7b994b42898c849579f1001e97b79e33cd73c88caca3ecf23cdc4d78b3baf11b1716d0173af0424fdfd1037d23e56fea0d911fe5d0037886acec0575f630bc69cac712506ef269adb556c8cfce23a950f8198ed86d107afe7516aaa71c159a1c0c479db32679dde8ce23beee7146c1954adff77d9f4be944b87d2eeb27fe37f39f0340befc46e254ffbe70f65e5f330a2923a2620b2c461f8dd3891fa72c0b49212934655268a6863348b6642cd14e61283ab281f43cc6808b481996b33cfbbdf7e6ed426166643cc8ab11b39c4519dede8d47868a332ea27d7c2bbe5ba6529af66e4030f29efee87276fad09edbebd60b65877177bdb3ded5ce8679f331a33eefea522349113ae9327a3f4ff7a82720451b8e407eda10023f9d65bc40cfcf70bc1e0f99013eea4d8b8ffa9bafa8b8838a79344389e626f0027555ce473cdbd1ade8b8aa9eacf6dc1e777843deeb797a6b7dad1c50fd46215d0da0e20df23cdc36be2eeb75795b54a8d2a757172f267bead5e9cc93f13c750748570e4f9df65418eade10cfc7865eac03babacc192bd01385d3773e41e8e9fdf4208ff2cadd3956400a9a6c216a4f96313691057ab43e730bd427ce2eebd66ed800b36505ea5269189848936618d124a7422c781cc0618b0a9be32d9c91b1a102a8483db3f0420c32cc707d445d3988a2906ecbb0e70ea506e04299192ad217a888fa18a8489d148e36eea2383343579ef7824f5cdd862de3fc1670b8fa4aa46b8c0af4663da7eed239e7f9396fbbcc360a572e5b6419d1351c5939079bcbe86877e1a83f7fd9bd1e744b76219fa77b0f8a2190b59e1175fe1b11e6c2b9712a38ddb0531cb6ac601fbb7d210f012ad650afc857100a537b5498ea7327871419c6571ff7575fad665a82f2a5ab8336f46446ccd94ca6250d4e70eb5d9a2187839ecf717a055acfd5b1cb9ce7d7dfe6266eeef5f5f9b6cdfedbbabee8a8d63993bdee1c664c49928a75b31dbd5b0c75a1002032b5b6ce79b37a206ad7d61bdeeab476c1841e678c02a187c2a89446167ad4f9a6ded470bc32bd235759ce5acf9b5178c3d53c476fbb995144d76b6b18561b6445230b3d5154a47a643da5395018ea44b2124f3ba7e18f4ce90e0394e891c25ed6a0501814d99a5184164db913e622cecc69a79d734e3b67486f72a66e67c0328a65818a52ca0d15690bab65868a54868aa897249de9a3c698e27b696d0015a594dae251b1453e05ecb7c0b2b5d65af1756d7138bef0d78632f464d88045455ae2c17b817705e8814456981b9b1f6666f2df51ce7adcd8af7723a101454f1fbd6a217361ad347539cb586353d27eb5aa95cabe9b1e03688ca169bd4263cf9c5b89d3013d3f67ec37fba87be7abe7892d252560cb919788e7a33dbafcc833ad7586afe13892baab7872158bef6556ce39cb5e57e9717a0b4706702bd0f83cdae76e92eb5d49c6165a5b9bb714c6958f151569dddb66593fb79747515cb13c7bf7da6b9ddab0c5ba90b7e138df3b3a49d85a0fb27aec780bcc8191bfba4d72f32ba5dba90e6ca58f7c039ee339e7d9e366ef6da73aa8e72d52d2a60129a58e6ddb36dbc3b9f5550c3f6598e1e7a88a266a2fa57c87514574cb74213fc33a5da6e0c2ea5b18f9ecb69d5d4439a707597dc676b6e07085fbd8712843683991f54e27751f8d46239d11e79264395b6bd8b2c2d7b0a5ba90afbbbab0fa165cc84f928e6871d5a910f8b17aae2bdcbf5e656ca16b580303b6b926756e7bd0f32729d4ee7d4eb5cb3a371fd7b1b51686692dec57a4cc01d3003dafe3ddfd788c85e0961f9f2740e67ce1023a12f03811860ba604f9f1d5ed0ba1f428a6a244bd950c8f6778cca1787c68ec1dced8cacd51ef69cb71d9b7916fde71dce4726873761ac85aeebc6e3df30c6f5d661b8ed5e3809e3f6da8088476f96eb750dd664f7b3eaa3db76fa898431b20f4669f747663a75b5a5cfa89c2e6a30f7abea5347b78d21d89e34350f22b2fa11842edbb5257bdce07ddb2b9105761f39c47a10bd93939a704e8b7f8a0bff9f46da3203fe750029bf7a0dce69c67e7421736cfb3fe863d061bf4f3a5d002e8e5cbff36dcc216b6a890e557922771240ebd3985861a1efb06db300e7d8cf11666d9c2610bf6eb38f441bfe57bd02a849bb8882092b84189277c72f039228969b30a73ce39a712407829549084b6231bb447451f2aa5a4924a29670f6aed62bfdbbdb549257ae9ddd04b973f498ef8549e1aab39449102a5c8c950adc98c169356c3163f82b5b73f3f824ede3abe43d4356a276f475006ca6ccf8f1acadbda5d617dec8c7c916cd9aee8c149bb59978306916821b4a4d550647a3b3d84714574d2659453fc98bca3b45a15d89300fbae7ad776b7bb1dce495a3f54dcbc95a405c4b58e5071738ea4d3eaa1e2e65206913580b43540ad55cb578f56d35da411029d7295a75ce5636ba612e337cf019238d955846af5a58524cce659cfeaabf5536136f7d96fee22d0928a33fcf9cd5baad4e6d1fa69fdb492b480a86b3e178ffd6e215d1d913b2471a6e33be4b1df18dee2b1d7218c316ef5d0c7d85723c7ad1e10044150eb52a98be22f86dd172b9e48d74b8d8a5dd05fbf4412e7e457e5f75ecff2a5e2d7b57cadf8f5957cadfcba4b1c945fbf2ab0ef56f6aaebbc1a407ac32a7be6745aa804027dbd47c53b887642c5cdf5d0cae621b4e231f48347adc26c5e030b3d6a212da49d50d7f5cdfe06a640cc014c220ef9eba328fb2b12017d14637f9530f1d7c7979fbf261f7ef3f1c690bf37627f4f2a88e2af8cd8df564d060ccadfd68cf5e4af8733894322f91806fdf5914534b28afeb2a2fc1d5fb0300207e5a34acf4ce28cfeba0a4ce29c66cea8127b15d95f1e57fce6f2c5a3266136bfcec30af90a613c6ef05bab8704d8b76af5c5a316c2a8b88536f0a8d5d7cbacc2c0a8eba516da205d2f569c12407354c21a253dd465f2cd7934a12ece37e721445d9f6faeda353d15667b99d557cd4f85a951578d11f962c5cb2c063fbe60f19ba34e610d4f137af6236b36001e8973f22d843d5108ab303f3790e22624a130f29b84a2e7b7148f1026a46f707dbb3e86b1df54d753a71bb6ac70fd73f9e3f52f07dab455626cde715ef53c8fa403c3c96400fa5fd83aed96a9d5aa4296c085ad16c7b578d4b891470d4c02a6005462f2e1a482dfbcd3fbabb556b082fb734daa25926f3e4bbb72bb1b225d1d9198c499be1591e2e6e3a57542d827a31f89d379170427b898c4f11c86b98d8850576b46bb22d2d582428a9b6f4242b0ba208424239be4de9ede9a51d775428ad4376f41417bea1b756246a24f3421f49b133cfce6236bf632d9826186b0df7cb47974610e508b478d6bd57ef3564de28cba70d7d99ebff1a8fd9603245b3c6a728a1fa775d2655481bdf43ce79c73727189a848ef50e945dc13e223d7478c3b2228d455d423716e3c75bb710cc3a848f10e9611a12e9e39573daff34a05164a7b99ccf8ae7a757b4ffaeed23be5b577fb4adf594f9481b63708ec895d26a20934f6f18e37c862f008e8a3225241e99138369efa2dba44170a15e98dd213450a75c16ced41c31fb4246d6f3b2b34f5fa6108bb2de8a4cbc8c97ef38efaacd3bbce5a29dd1b8dba20b5a823d500d2a31a407a540388a3f7e691d700d2f5e515a2e2e63d68b7f968c31083fe6b856c6d7eab90256cb7091537ef6e6dab5981cedbacf5d624cee6c3f4351ed02ef8713ebdb5df9cdbf36f4de2c8d016c9d6e63da8177a7232166c339ef45df5b6fdbda42e4ba79576fb64e9bba96486bab69d5fd5b1a7f0a3bea8636781baea638c633807ea925117e7d8e5b18bee420389199b9b6d731b45e2987ef32b7487eacbfa567ff35b445d323fcbdb77299c40450cf6542374d265ce404faf08d8d3a3544a4aadddf38180248ec8427d65f1e666f6d8417dee21defa103b7a5071862d6e6d8f1d54b49eb3a651d1ea1915ad9e6dd4b1a6bdd54aa8781363023ddedc20d2e34d8f1e3da8687dc78df41bea926ebd9b5ee8ab84bae4df5498a0b75e43a4af8f3748b2e7f086ded0104167a0b71aa8be727e4a42e1024d49bf52169afa0d7b2cf5b028759a0859d2444ca0972496b59675efbc5ead9df3de39e7b41205d657180f741ea5b53ed14468e95d2973a30e44a1509e09852fcaa22a0a455112f59534a803a88309d4019592a9542aa59a2a954a05ea904ad5542a4553a914683aa15029d309a5e3e22a920ecacb2a2b928ece0a11baa58543a550a8546af5a994567a056431b578dae48126944a1311b2b0b4c898c162c9903163060d1aee7b872e2e366c541b366cd85099e1ad684c1a2b335868b4b0c2b086210d69d070df6158a3868b8b8db0c6de6158c3c5c5868d1b375e50da85a463a386f6668d39278eb93131362626a6d219131323b5e762e3c6bc71a3860d971b365e441b376ebcbc88220c4c4c0c8e97175184818989c1814346a6d59a9981918991a1b447a53bc8ac1d51022d4146a64542093339686a5a2df00812482001450209271248985a7475c5921b8599e2574cc2e33af17c9ca9abf5d24b34d0a3f778f33c54cc4b2f65a147ef615ede29710e3506093d9d5249a9b593526adfe210938279ca3129d0d3e7cbf1d6ec147009b8045c022e0197804bc025e0127009b8045c022e7119a518439fbb4e13a1e56868c6334273dec92a27b51daa1b57282ae691f579a583b276daaef31169ce21e6688fe0109f9d823c20112ae66d9b1b28a36257bdd89095e94214d2d592b910d4f2e1074c5a41b4be8012c5670f1224713a6fa19bbade2d3344725d3bf6c9499cd2c85d3fdb055461720c66ab4761864290c4e1748fb6ae3da081c0ea4b839e1d880c084f7d61cf0ea407880f9023244ec9553ebb7ea88eec738faec7aed967770db988240e97009a7343974f17a3cbe7330bc84628df40b38066ce02b0832e490bb8ae4320b00a93379018177ab41182d9d1b426a653e320d0238dd0a869846886240ee7d969b6a021a2117a4d13e573ac0646c525406012877e76203b4062f53573563e9f9ff47c06651f5be1a0877e94423d2ccc20d02371529f5d17a1473026d4f3d99bb3256bf9d00aa2f545093c9fbdeb76553d91a20a8a8a07d41315916ce5eaa14a862292ad4c841e411f950c0be952155940480586149da8c610a386b7ae520511b0f8ec15105a450983677a1ec3211a520f07b5561fc3211cfcc802226921f49db586c8916797632b87b736429dab8aa8cbe5e32a30a4cb9584146b62aa3146952a3e5c45d99f777be42e1ffa852b09e992327b36120e15491f3cf9ec634dec2514273efb6823f4d9bb1d64265be1d067a79d8faa0b411608975eaac46c369bcd463660dd0d2078a86b3639d09bcd66b3991f33b45eb1881ee76c3667e39cd55be78c48c6660729d3bc00f663cb406de2a0fab6511cf094af2c5a123c65a7ded0c0fc615d82f4286b3e4afcd40a546735a8767ddb3715e6ced46ab51f3f6ab5da8f5aad6623067a94b57183299164836d318965a8278808430748d43004255524d991c970f0811fc05c644044de41b762814568162145e2c85098e94ca2485ad10ebd7271522d68b531449430798583aeb25ddd206235f3b2d453425134ca62e2d244bc2e5acce06b500d0be1a14780c449c034410117dbb8218975055cbc31d16dd9c60f9973b9a2ba9593cb5b8ffc399c81e2ab8fa3afdbcc6846073dce24a1af4c61a60b499c4bb512baa25167223699b2254730961d6ab1da10ad8826efbda40991440f312f694514e1bf9734218858cd59f2016fdba684154f7801a5053b28b047922cb1c52049124c8bf848e004de36ea811f8024b020a02d5104a8512bda123b2cb123842488604aa9ecb408228a10302256312dd02d2ad4bf5efffa4b5297d94e7e10f2e8d159733ed193e4abcbd8d06a50f295851a821ce9e4abe33b89a86b643d1416754dec54ec428b3674e9ba58612250159da94a51b69eaead99587ab8526aa15aed05b1aed56ba591814f4a5949416e5d415494d6f33237adb56eb3b5b57a9d1c9138961ef4749c377c65b994e5a6b3c4a413e413c0887e6be5642bbf1fd1d3e5a8a2f26b94b77b3b95177e83a88bbddfa09776ce28829eae4aa154be5a71ec30a77857d65a6bb7cd5a6badb5d6da6db3d65a6b375aadb5379e24f1deda1d74b389adb5d65a5b023dbd5a6cadb5a1ddb69ced0564d5594b6ed1a433c8360c6a11d55e1e49ef62e47532d456926c3f241de9d3e58d277a7a35424f0f298a051de75ae498146cb55abc12434faf6f6f10e9e9d686d9621d536bdd6ab5f55bb026d0d3b537637c6252a0a71c8d70d0d5eebdf7deadd67aef95b5eed3dcc8fb54463737371955024f2bd807cb5cb0ac5e4c64fae0237888eae3444fc73f2ea752c9db6e42aff0055658eebdb3daf4e9aec0322c1b45f15864ad850424f8516bf78115cb8caa93681934ae0dadac0607f4bca34e46ad7546b5d3e7d22082e90db10c89de4dc8ae6602e3c75a5b6bb5d6d65aadb5b5d6206b6dad15ab489f6619c566ac002904e995d2ca744ab1e68e8422a104b1f505fada7c0b27eca3d4664f1627f4d882522d2c2d9935e56479e1cdca1732fc5e0c56c7b5ee16e819443448ab199128e813410b6b5794d632b64ea26984b67ab947073d3dac413896645b6bc3a01a33a8bee691da53a7b3270444417af610cd9e201c8b49a2a7d71f96111e6aadb549b40995f248a595110ba3142aad3e15d084a2e38e71077ee52c6b412fdc40dcf0e441b1cc3b4b2b2cd95a1d595b3cd6ddec66a9abce3bbbe2e62b8a36ee0a71dc09f488817e46b65992468081bc7ab305416669f1caf25975123d83628c5fa881839e343c4ab2f34ef7a4f796be369e0a134e124f7dd151166d3d4f638ee8224bb4f16c3c4f6d7885648b7a0c0af448c23611a529f1b5dbf542cf6ba7b51b90ccb1453788685aa21b5d4c496b2f32aa2882f8a921081f140e7af59216844cf501ad1a43a5862e4e33fdbda419114ad960040a941346904049a1512f694680d842ab4cc141a778a032a24959a828a14935930e3c4d20e139e2084f911df4e9258d67277584d62f6945c230d9a0f34b5a1128a92134e925ad080e4e5068d34b5a11295241d0f625ad48142a30cdbda4159915010222086f917fde04ea5975895a3b279e78de694bb84a6bb5c0a244d2b1762b7da47c6d8d173a3bf51a229d7ddbb6c69b639cf3e69174b0776f474b5c68ec5b69486387e162eb94c887c607dafa68899efa6671688946249d5bc3fca3da81aa5e2754a4524a2efe0ed5cac55b5aabb5d75dfc550d22a93073562578154ff40cc7eb040516e9001d4f8509a2abaee7a9d7201adff50ca1a78f34fc942d6a492898fefa9d628aa73e6b9d5a48e260a7ae876a78ea1a2671ae834d60f1d43f23e4cb3424f4f5481c7bdaa1168be20473224a13454c3c35117d479c783a6ab704dac18828a71b5a22d39b86eaab0ea93c98aa115335c2548f3855264e15e874b2618dd99b5d3a952670528ab512a1af63120aa6af1dcf5f0d93adeba415eac310437e2a5bd8b98a81b78e69e8e89743bcf1f840fdf51523cc24cee64dfcbdf7c4f3f77a1d225f7aa8c2dc98c4c17e77008a3101c28e88624411d1df1b7ac744134fb9213c5c6c8727516a38faa1b2657a3d545fb90a09431d0ba22d74d1932f60358b117bcac176789a6b348ab05556d9ba6eebbc2e554f0a05336fd84485be2f693ef0fc30e4071f32c0a40722fcaa7b49eb01ca0856da730f4e62767a3872f3d83f960f0f44243dbb19174a8ca10329b0c0c17e20075dc85e7870e2ed09a364f2980256c8a005444a04f520075b231e67f1c4e3d4638c317652e347d40e4fb0903df1968722defa88a4633d2928b5f1a3f798e8b193c73bd074b07705ad03481e7b56e8d083c78e7dab81623c85931f3c96d425a9f8d1a3e930440eb4b77e8160b1cde247d4631c36c0f2128a28441ebbee798c83111ec6075fa462f80630784d4cd2b9d972808a0f07adb58a75c316f74494baa10bcf24460d7543104620cfe90629273d849929b683572202181362f48151a443403a418c588909d03b41cacff7c4d70d9168ada323bd2a825011863c7d831117c6acdb410e026c140b02691b43c6c5a67c589675b89708b3ad8795fd42084f244cb3ca1c46940a335d49a62744b1b48e4e0e8c1cc020a2296d08151d1da230f23721105118f963d640cc346a755fd27e88c10ca1958c0a133ffcbcaba6d0345ed27ee00145d3fe9246e40b0fe8192f6944ac503142afbca4115141101a7c49237284ca0bf4f69246e403261d689597342238a8683e4881424739c187229a0f468c51c4db97341f88b0eed2445e4c0ce611d0e7fa084889ad2f3da4da42baba1ea468ddbebc75d51051d1dbee072ede8eaa216f5d159338d46d5774a4a794851ef510066354d4445b874145ebdcd651a8683d6f2d6583b00dee58d7439a0b2a5a900815ad9d13e40189c404e91194813250f67604c11fea1a3508545f930445600f75491fda5b0795a02e4abba109135008a4bd0da2faa8540d9755390a99a11100000014004315000020100c080543c15096258aaed90314800b76904c745a9c4ac3518ce3308aa21431c6106208210018446466868825013824cd887d3a488ce1d8aa9a05ef48260268019a05632603e8cbfe1872aba73e1d9457ec2903174da4f1dfea75ddd595e045f47008ba639b2870b30d4bcb179572e2cbeacad3695cf6219b58c5061caf25e8a5a4f2753568b455e45a9751d2ceaa224a12205747a39bc435735e0ac7793aa065d1c91fe7cd6da324da72a824943ee5dc0229071346821a4c483e1acbb91073d738313a28b72fbab0afa0852f8a392238448097a346b85d994db43526d4468f891bd698449668265141cdab1226752f5edca1cb9454de0f77323c902d3cd2a8906e180746e306e3bc96bc5f974857185e89bb45d10ca0fd03585c552f9d51efbf2722dce6c8cec469e83678ffc13a649bb537da0ff0a0a76d65f61369ee0da8c4fe04c216ae60a74db00e2637bdafec4247925eb4c8e585505c51734c7332a62132f5e434c9b87b578936976f23aaaecafc0d2c642943de99a5068f799e73e5bceecc1ce1a7616e886c1981a1f15b74483cb575e3ffd72986e5bc2ba8f850c2543237ac2f025df979055d98c5f45f08f6874f498b5ce8bd8eb40dfdd27caa2cf84cb461f64e1945854a8e0e60e389c13d8cf766e35507e2d2ac772dd4844fed77194ca6ce27942e1ea7aa9bd36e2c034ce0fc812853f546817736108f0de26042c196bdc6b574a5ab34588f6512c1cdfbb0dc762c0f25b4eb9f0520faaeaa579543fd749204d3ba2fe8db9f239bf0a032b83b95cd1b16ed5913944c577a20ea66c3aeaaeaae5d69bada6a5c884e5703eef3352c82a258e8c67b33f414dc9adb63a991cefbc05ccfb10af63ce9bc8521a4b2a734a039e8209f4d5cfa884473f694e14c3296e36e5c46d4f6fca3eeebcfe8d0cf1ec65459b00f49d85b3c2d50990bde83a70ddf86f601dcea1932db7e78b81a86902c47ca70a045e45ccb6ba2264c7a413b6af9218fa2b0b96ad0e98765aefab1904134201ab2fb0cdc0a7618dfb12de5affc2666889dd32f432f93e1b81b17583c4a5b70506843b7c27e505c73c323c35b602f412fc337012be82d98f0c8296f9f13e4a56c8fcf4081604571ee54bd23b3110034b65193ff6be0c9068c4ff75e495bd18eb9712f801acc9895eb780dfb67bb42f1d3490ed677791cd66298f3ed0f0ff1bf7f6e900c55f4f66a6798a3554f6b6694c7c173205720f0026fabafb279efb93cee194bc9f30165377c18964fa50d7bf709aa289a5a579c297ce3c0831e461bf240fdc04f0a1f755aac80d7506fccd7312bc549a18a0ea53059a81d70ef8a0c58ce3b7a3e80c854bf1afbc62847e3ea2220e5f6b08d7f8bff597c38c567e99c390d9cf74795d1d42803324d3c0261fd512e68a0ed0f399c60b7f09a6836aa6dd64be274a494ac0e7dfcbabb74685987997ab1056460d0ad6b49237f9c2ff21566e83e955f8e2aa0a4f4d956dc87187c5380e2652ba3c71388aa33fc3c304cd525fa958f13256bf8c7e8f1adef37004b2861b401be602f5c884027913655c42c09239c12273026366c03bc6f282e836ed4df60eb7d0145fac3bf8cc7940d4b9af4ad679bbdf703c9c770b36ef0aa84d1ce7d73684874f127af9c36e41b82320a8ac0669625c726ad42bb630124482211b5b951bc7af1607f5c876a78fb81316933fc60c384fa6cd708287911ea8d4e1541d209d954837868289a2208e6fb4970bcc13a5912d16fa34e1e3de292e175f30f2483c7ed0eeeca24dbf758e9c42f134030697a203ecadc552c2603f91b8d87eb40e9df15164024989164b6b409e125ecdf15e544523f7d4e044b15b252fb69254172b4957cbe9edf298ce9b66c0ce74a58923a7745adf951a08b1192ccd0c2be97cafc56ea0b91e84196423b209be0e716659b901b086175455b8ec4adfbbe2e8471d5e602cf5280d4fb2c67af5a9d6f22ead438830f7873d13503d9b58997e39a383ef6f524452dde549a97016947f5269fd29a8a563b3700850a3f5d8cd9987a0ebee3c94a21a4ef25a7655b601a1b951af45ffd6cffdec4f9571e28e04b5966ae1602cc448452e4fd7fea82f72f29ae42ccc03fff2a71a51c2f1183a9ec4f8ed3d5c6d36dc26c95ef3af884dea22ae758f6beed0b0593a8a05c97ef3ca19600047b71795e88a81d59e8ef52e4306e9acc04d5cbb8024bc1eab3c677ee20b0202b9e4e1bd6c73ae4639535ea72e6ceb7a947a348f2aeb36ab0d52382744d19198d4cdba874785c478463f5ac403e05d995a974f9844de0e4ffc9dfe13157d2add2442696d5c0d04a1375b966d951f1f7031fa783acbbd840773e843a0ff778401a0055d52af60e24511fd3b0af8bf478d2bdd82862595e2a83c3bc95e3233b814a9dfb5855150f4e24a8ddb60b5282134ff82ed4119c3c253a33ebeae42de8c30313319572a77afd58c346175461c48a417ffb6e09e3ca8571a7aa234317e2eaf7bdd972413ad2c76b64ca5bd8cf91e5a6b16f2291526bbfb211d2d870a00b888d7d17ba3102c0f4981b920e7021b408b3a6b290cc8a9cd468f885efa604c3a9050fc8cd8c5126dc5f11034ddb121492a19f8bb88ae2dc2d96571de348082a9604ac3cc76e1019f6b9d43c588bc7b01dd1cd15819ffe000bcf1631f9df3a7676f325ed2ac8fe85ee410b4c946f861faacda34828640adce391e6136d81d06f88f8b08064bd062c54552ccd7c6fde6ea1902c81150bf21c89d6e222a145fbe3f468a66f4c4e94d343ca609aae4519780221f1ce493953a8fd862a89f10b1bccac2ddfbecdffe1969a7652fe508285fb522637a49bef198ebf8eb66d2b211321c6620ecff184d54dd29fdb2131e14e66a2e4828fa59cab6ab95c7be80a0e28336d51e91f102168c0a27ba52e13c27c21ab7ec4ba75abee8d0e20ca6f481bb9a6c95ae0db66578653686a1d0183891b691aa4f3a36ede69278fdd596c11ce9d8cd494e01e47e198e789c689bd669f6016ff65d651098ce07693e1a7cd7e833cb6b09f91d6a68f2e6dc0f5be80211efcb6a2f645b2536d8c6cb7064410a980536796ba9cdf97f06ed8b28b2cdb8bf7db2a7e9a11112e7f3eb5e457a5b40a6ce66b634e38c1a46e35cb28409679cfe5a380186b9aa0b5869b28ee1c0b875d791366d3a3fa69512ae328c772f85293da41a41e393458287b5c68bc3f4a9aa929fa8334e19f3bc185567fed911491eeea0f0cfe663f55d58e5c52758ccfcff69959ac896589923114b87bda7dc6135b185edc87e46493d80cd0118be0f0038a0fe9934e047199ee5ab548c0e6159c882579281e33d9d10dd6452b166aaaee693a9eec4a527b69348dd1de1ef11c2e80679a07cfa722486a7a1f5e73a88a769c3107caebc1fc1087e16be94ffe5861ab8a9778cf3e1fab8f24dda207b6ab0f81fe1d1a79715355268b8ad79d32578a29a56b66c407b0f69985ccf6eef1d882a88759201673ce0af2023b33d45ef3f6131fa20bf18ce671082015752f82c4904980f8b36127067c4a7cffafd93cceb1a73a49632ca4bf11530da43f439a3162f9b079a90e0ce4839728a02bc85c80b3f1b70391ad44e9ac9484cef129480e0f7188d9dc9c233e1e72f7d2b6b739f23a2bfdb8345aa380177555d1268592f4dc6c3c267962eaaf219525503a0d53b70f155ed7c9068b5abff8a69ac66e8b45efb24135aa81e00416bda4abbf2342b7b7deaff147f4c702705c3ef0b96a5637eebb34fcc19da2e2335f99fbc8e92fb76c146b3bde7f51bae9bf19d0e222f8f13f6afbd65dee2790d94eee76f84ef9aee94fc59d955709c07d05b177f9eb412c5d3b99c83d2866efac02a277a3f8091377d5a13f25eefc6493b02710e69725bba1863f449a58969e31eda7dfac34a11481676f1825bc0470870849a67ac3f18bc45fc937c7e29f18023c82baed6401408f0f1588300ebd82fbdc15c94f18bd937425070ba7c0a3328281d2f020bfeb33015e7f414ff516e2a757202cc86a8a621602696c721774dedfdc945ebc0138918bc6b9fd5e5b8bfef1ca44fdc2d6420e1520aa2b9133cf340c9b9fe8a9d023961ead4666a662fd9f118ba81d5d7214bcf4c2224b7b32bd5941da1f46405efc84db0ebdf95af20b67be6cf5d448351375a5f6e30791b9b7e0317ca1e8fa11f2ac3040d399be5920a13b6e4f4c21d836d78f236921e8a2f4d8696c9f9f4099cf310fa694704f1ad78bb8abd31c01126490f10e7022f50c32e53e104931644f83582e33e4ac94c83ad3b2ad9862b4886526224838c80b906013818a2592c1c00735d62cb7a37b4c9630831b4b17274d64962bd1250a61fd0cb44eba6125c925cf5d6e79cb3b8915b47f14b91c73c576fbb38b626f147e58e7bf90500c9f5b5cab1c31ade839363c0596f603b32318d55ae88e31c3d4ea7c10796552a26b2fcb47e482012bb33575e3149fe7fe7082e2eec46cd338181b6f5ec557c705ddbaa65ca535d974ea8751f4e3a9fd3527a1f4e67172de2f9a2fc242c39698fe6a71e8f8d575c65a88bfbd0bdba39a48a978204dc496442dfc8910bbe3c2c39452a6b25a35eb1247ab1e9e2b94f1fee746c31df94ab0d6d2117986a2b833ab710855e55557735816b205ac77e5491fcd7ea6c02d75f56331f0b508c0af534df0ad542a9731e79d61efd1abece0ef8acae47669ba8b69a7faf684c3d737814a54219f1b44403001778d08877549b2b8028baf18f7878cf1fdec056b88049c6765c15b8d5418dc6ba600970358b4063a30dfbcd07c63591720af58f0a3b726c5ee3a0664cda590e7d2840d769e2b5372c97f7bee4a037947ee17e798aa3c72e04725464a6ff3ac8022e780cb08a20bef830babd669c94ef8f299e1e07019256366bf6b06413902ba0c0a25800538bbb1027687e9e3413a7ec347d30dd4ef207e82c3b7b593578312248beaabb99078f39ce14b07dcbe04f607533d4bf1bf807644e4a16ce1920873a67f71952af7f849c072e43092c3bf175d6192f19f1d5a2748e6c70e62e6b265a167f2272890a9476c0d194d0cfa4e809848b870164d9f2df0a7ae974d74b57f2b55a087eac569df4e81429345f9a299d92fb0d3b6968af57039d94ff2d3f8f1730abda0433c88f084accc56e739ac44c69f189f27160e653827546902279574540d831c8bd02873d20a950d20a1475bd06bf4c7fb802b88f573265047a9644f22a34c70dc52cc271fee2f5b30afabea8e025b48f7e01241c69be698871c2402b0186f8fe3f5cd733876efd9df7428bc4d0639f642063412c8a627ba37e61f8d3413b1ba233a04cb67b36db5f4e40813a18610e05bc7d4f03bdbd1cc100369e8a92a3a37dc93189bea806d46b5512c8291d41dd0ab6aaf5838e5509bae0a72e410f424de15a5febd4ecdfad4c2c7467a7adb8167d42cd0bfca47dbb75b47fe284f8e98d530f1509185fb49cae76a29640936242ddb1fc770bf2f264ebf475e75013b27555ed29c5193e5aa9f289394e9336a93e5be456f5c63289e1af4ca063a5de4be0a6dd91118a717ac1b8b4761d2170d600d3911d3619c8216729e503564d2d7ea17791896f46cd222576a379e0ec42aee2bddadc0ff9952e63867b60935567f4570d935fd84507e2e0825cde7e8dff4bf7df6c94097fe6a65f6ac3592357173520f05ea279f4509f62aeee64b008bbccdb30a7c47bafd2f95807e92de8799f8873d592fa664df8069c60e5d60e5712a8901f10db4d8cd9e63a6fa333af4deb15abde018f2fc21c6f33acdf8833c81bcef20839a1273bde82205fab7a3e4dca6ddf031824d73f7f01585fb891ecad443b7aa1b77f90e1d70a0ae365cfab4945e1171000005dcd78ad768de5539d3cb455625347828db0e6dc1f98614400e1196f3ec7cdae044687e80eb86b2a675c57563bcb3ac55dd6582648cbaa977015d3a078fa75546b9c2d92fbc04ae63cb0652d4dd8dc9b8245e12fa3cfdba31f475682e7e38c6a4c415e7cc9d3740649dc3de0ee63ce0511644f29da36cfb7031c852dd051f584283cf6f8b049612743bbac202cdc6d4c9e5000fb732ab8016f914a1154c1f4aaed248db69c5fc3e9404070bb4e32417879cc12a03e75558ac29ffbe2177f4d0bdb4b08b293a7f6c6ed962943178db2417975599bce10ac8cf442a2a9b7b3ed7265072f5402fcbd6a6de2dfc2337a0139f6ca761baaf57a8a94be9cb75c9dd89513fd9cf546f43f6109130ab928d29c048e5c16839e8351398f1bd86d12c31618947ae1cd9a40b939b05308d72de7d118a37e5d2791a92679b6d9081d825015ee4bf8cba0799c007f68444fcd11e744c2fa161442edaa49c59f4b8c2933332a99fd38c9660d309e04a276f238c9493dcd6770277633a900ad15d2042c13dcc42c7320b6556c6b30e88b7f7ee8cca84386de85413c88be640f94775f21d56027b36177b5b6169df0100235f790c8ee810d618137d2aea7fc6179a6a725d7ca12d3db01ba34bb29e177b50e8567a50f61af3ebca23ca87b95d2f285a18fa3c02515a2c30336a4149d07a7b8de84989f100751d3155f360601b1c25109cf38bf5b6a4a021abb0034f6af08043019865d82c0ef7cf56a5db4f9cf74a6b77cf1a7dfe76b70f162b082e491d820e5425d2141a222a20ed60e9aece2c2d3584547e71d186cb1bf21cff50af8ba5f3dd8b42fe7226cb0276b801125f25ce999ae3a38491228f5b99f79540bb011052ffee982ba792652eb482bc4dd9f0d80e857de39620da56d1d54234819e0cb3e3f6bea4f4c10daecf9d12e4740566859e5555173d20f2fdbb19988ac6413f129856b41200628bd67cca02a469c0c900a1035be2372644918b5999afaea6910aa6229990c96a91e6a856d5c53d6a3f3120373fe215aacb6414a6ef40227860cf1fddb0ae3896892aea3ed1a79480f64116e3b7b25645bf68dba8f41592d08c95db78b7a426f0b0f2cf7f3402a810d5130f5ba1310b9dfb0afd8a7ac86535670377718ccc367b82c8d580915c89e0a0772983df00dc6c804eecfcbebdd9e39640a617a108c49c2902f4fad0f29d0846d871ae98d594f600b2b7d2469ea36625e4968aa87022752134b52e7460b302c03d827af869a5036615c435262585442956a56615a410650c2e99332f9c5cec248961cacf4a37127894080ccb723fa138194130325512db5e1600139abda768568a5bd0a65a3b008e12c80435010484fe97b39c84da686105d1107b664d81dc50a3a03e2abd09f68eb4d8a4a77dc723c527fdb9f647c3d57e51e279597e1b306e3967a19464cfbb6a1b01bac404a2590614d7879a184f26c60a95f471a7c6f7f2fea9bfce08f93396b2f13585fb0502b235d257bdd95cbf3ed281013eb51e220d5f5a4743b6a953c422dcfce8682d39f9622355f47131be1acf51c634f4c1e25c750c5213317392fc0e71ed6538a9fd49af8d414a4d26f21a10750f42bddd1e74f0df8c4504adf7b883ba79ade285240db0d4026f3aa880b15a226acc08b7d109af1e81e73caf4d15fe8bea7abdce4bd5439233d34f69d1dc60245acf4031ec8aece4e00482e5083a860b90b01c81c6e02204cb09744c172471390685d9c5d5bf024094b45eee3546f0f50150fa2233de38753ac0aa211d99f260b48a08c53e9323f4dc93b7a0c42ff580aaf4f173d96c6417d0a9aaf5726e565e0972fc86131f9886b35c896d041029afa5699d06177fb30796236ca62f32aa5d8829d702318d9162fab34a25a865281b573008926ac145b257b20e76aa8c67c1f1d50d50ab952a356480d51662c5d80bc394dbc010f24f110cc43a7f3eaac94109bc42fa0695e5853d14e45e6260bc2f5d09f5d1a81a984167a9b3ed1a226894c9aa4c3124bfb0041e5527a8c662526580ea3cb38b9541ff0469b53bf25bc79f508e163114268f63e146067d27cfbb42efe65d69e259778fa1337cf40724039d57c9e8f13f8bb84ea3b49394d5f1849a549be894737df6fa8a9663b6812c13920cb7415e2974c72ae3ff81502a37c3c184d078e629cf8c001bb0e788c60365403713b8fd6bc98e71203e6e7ab2bb89e1a4286c5508eae757922482f1fa170b58a90fcf564b87e85b51ee1467ccfea595404280ff3d1e4e51869803d914164caa2fd66ecb29087257df7d1ea4c4d75d07d2a337338bfeb333e835c91f5a242179e12206bffc0dfe701a48fbe77568f4e7e36d94ae96db5011ccef54a130609d764ac501438d4bfc2bd1c62ed953764c6c0ce14bd3b7fc4e896b88b25ecdb3d5585edfc1c8eaef6395daf31c092292fcc306daf577ec9a5b2ee6ce1d1fa7462fbb7ee73b5a953eeb2e1775600c1112cb8c6d3e234e43c211e3bbac275979feb28cb6791e7136a694e0c697a2deecb1ec7301e26d222d3fa9c531a60539e61671d5b7f6838cfae22ec16a1b077bc207e0acecfab9212ba2a20bc435a0afe470a735ffcb24419cea202d904e0ff2a93f64eab59bdfca8f25ee1ac12761bbb525f500d0fbb2ad80c5f7f92b8f797dbd33ba7cd924c9de54dca174d389e80e0599492d82e968547ba7ee636d7c58a9a90f147ddda211dacd11033489ff0e0187f035816ea4f5f9c0a0bae4f8438195d395841e2183e5e667b6960d65543c221becd1c714a1dc8462b2e20b32569a9a2dcd57197d024c7187692ba606786008573c91fbb136bc318727599552990c83d187e91747820790bdae2a45987de783f9a16c800171fe8d7745989230efe4a0ceaebf30d7e38e285c8e1a4e305721be263af3d4e73ca7bcd498136fe5c8b8c75c99f07fa72c5c9bbb81ec8ef0ce6e2937e1856f1002b5a6594bf35fc3a693ccb560c51b696269433e1b117343143723f0258a55e4770b57541aa38ad2dba622804e0636518201e24776847d234163178da6eedc3763c66e67120915fba95e94f1655dec3744a2174bae3723b9ab7522c5ac64fe4a763770c92c273bcddd2f9dfd8acfc1286a70f798233ebc7f9b1554bdc1a7aeb41e78802576a81f41766f149896224e4d2209d404a5d07a568691e38dffcd2790e48798df488dee417a912438856eaacc2d448909365bb95084ba78a3264bf69056686427c490b67be0ffef9d7a4410b6bb8546da872a54ec3db823563886ad2870b1121c480c0b7850667dae4baa10ea88cbe5564958757104fb846bb1d1e9eaf77ab36fcaa4c522693882a9b0e73833932d3fc427b81cca021d4364e453604cd8f57e1dc5e98e8f95eb3795e67773ac77e23cc5d8e8f370aa46a490b0621861b2ffe940ed29000934b4c67366edba908448904d29c6b2db2d61e9d8f88d142d0cf40862146884fc0dc086187e3197104c89b0d6e2c6935d085c14566575d752dec1c1355231be0158388a97163d2a197b9c360b07a408d3722abbb9b5c44ccdf045f7892b5544ad93595d3321b5b6ef025bff16748968a676f5fbea0d57f125435d2d46689262e9d9b0e98ae1f34f97ca587145c5a4bf55dc0a8dfaa59d7d4262deaa45e15e9e3ed12140f1cc80db3f2ecd978bce982bebd3284ef52de150fce0136a0c9e393e4b9740502fe92703a32435451bfd9dfb75864742505ac9712656b94289df8d9651fff83bd2bf04332276b71905e0a6fd09ae1042767cd0a37ea8cadc915de814ce7dcbfa7a4ddf122be65bb212f3820f264d5d7d40b3125ccae2c551e21d5c8e28c55bd5db8b9d1a0ca206640bf03e5360c10998e02d20a1d2cfb26975faf78856381d029043199041ef3ce0c852557639300e0e3c764580f9d9d2495423e3975c7c0b0b42a006a511c7336176cc9d5ad00664075d8abd068474a19733e88daf8f2f1c96786e93028354c610bb5d06be669b48bdfac400c6b04272cf4705b765b8b7ef93957aa4702f418a412c93a06c39b15e0270f606a49332449f3391ac72e6628b84ae404d1ca6caa1c1dc70a1763c2195be47071217891263f6d19edcf8b5051e667817d493a92b9ca297cb23e6fb2184d3314129d430bfa9d86b09a567bf348656d0ecfd86bae211a7327626d3f6702a60828f7c0971b83d8e10ea2b310113a21ed19990ee8e3e2a624c302af2fd6f7cc56cf44efc8bcf0ad0c8d790bd2504b94616cc16ea06ad1e3efcee426a5d25274f8e6e81f06bbfc0d2a63673e18925d7fa81ac12222c340286e283f9ba3fa86065ce2b0500bf64cefbaf1f9baabe0b08215f7742525ff0a4d402634ea5f2b1dd8e2cc5124c96eb7056e9841279e298b0314c2fd638b7a52f274c88792f1ddc5331863c98701dc2841c388c8352128d45b90fcbcd67d6032a9f4faaf9a9ab1a094bcc8b74f20c5f7b21d922721c4519d56a1f895a89dd924f036ba810c20cba4c236d085bbf5f6d4bb844f4a8534b5db8f8ce4afaae03a4c9706e43c6245caf1b1e3d4701d6142bcd76ba2042ded8632e8f9afaaa2f413669b57629759e9260705dbaa0bf46627793de21a8af31812816fc3f7328adfc31f09d36635e786bf38f7f4bbf0f66d1b2e6710479f8572c8a323c57169da333ba2466f69b5df214abe46785fd1231390f978a4e2c87440dedb1862cf6eebe2814598a24061175cc13abb68795720d251f0f6be94d8e5cd833627bb524a97d60fd75a1408c5145773293c351437a8a5d6df59670301dfcce1a40c2c59f4c26d205e7622398ef0714d7522ae2489383d08298856348291b4bc949e27543907847ad1ba219364626990e919f57110f03bba99aa228376e288858d29a6724c0940540446b6605d940030681ffc31db2737f28d477abe0ba6628711815c4692187270ca2eaa994144652b578c914f18f673deeb76c97596739be7ff0ab65e96af0fb93500d6eb0a1271adaffb62b69c454e131c8e2875bea876745734d0b752734c78920ed15f2751103d167f18a59f4d5714718c7924d90338a290488a9b001a45e2c1cdd24ea01aa3db15f7209617ffc8103aa91b49db7005c96b179259c13f5f8ec629f7457fcecddd4ae40c715f11dc077f4d800e207aa2da01ff1a99725862bcf7880bc8f0c9c8e08a2a69b50dd58cbe400aecd63ae1ea4248cf88fd3b8c8864cc13552c2b555e02611eebcbc289efcbc1e57e7e11ef4b6dc22696531e6ac755416aafc049df63b35b0eea02ed133a1e099b6088251551f11b6c600527345ab5ca63e172e709de81e3c8ec4638b610fde84caa71973d540ebb492d120c31a991946d5ae02593cc996a6bf8a83b490bfb22453b9cedb0e14e4765b4ab7ab72b7bbceda82ee3ca7100c4b4779c079590992a22260bcb0f9e92e545915fb75594b7240a3bdfee17db6555f52a78a7cf3b895e3bb8d91135c6b29f58a86c90688ea78b95a065645dc6cc0ea80aebf4ea962b1967fde245d0e64e1f7172b80aa0a64aff09293dbe751205af7b477bad891ac02c27747b40a4ac35953249ff5de9747203536c2be1d032dbbcef7b993231bffd208e9e2a10b355fafc01c94772659d60bc9589445d8dcfb0cc0f2941a0b00434c2d59cdd3681f4cfca9201f30b4252e8fd296468541a7442bfc922ddeb9908b87d408b6d3ce2cead6430ea9d7178ac973c577d55a5376d11eab396e82854821e68b6600bb990686ecc0738fd53c57e1668e8bdc890ae981763d08ac47713ce158d67d8d0cf149a3c5f4031c9e134affdc0f2beb4645931bc5970000071ab8f13f8bd1ce75b6ce14451e408b31d381b382b5611d565c78f781089affcb6db60877e96d98b15e0878e25b106ad3c92aea498c8cc1c701dc3f94107e5ec5ccadc02d9dcc897d851e87e82d0aec2323d4451d467ddba793e0873dd08151783a1a54b5c64bca1cfc74e6e85e9fecb33ff039af99ffa3dabb7dc1e835e067d48146f481f204d3e3cbedd78f995c7ca41f96ca9250620ad4eb4149b3ec8e72525be81697f48f4aecbf4d83104a757c07377ad2dd9bbc6692cd0b34b40e0fb4c9fd376879bba779c594b8001a13b4ba3760e9899f88aa308d87940f1208e4b7494b7a6e4bac0a8dea3ddd420b8cc887476d260e1a07ba7acc6a0b7df3bbda6b8e92faf35d317305bb6439254f56e6e081463d9e8c35da51d34a39c7c9c90018f1d7a190a176e05f23ec66bdc2f1c4d8a053598d7fbc753a820187d9ea7412c2e1f389b140ab7a35f679cb7470011e773d99c507d0d64ee1f0d0a4de167144664fc9631b348e9d5811fefbc026af335c19cdb281c6fd9970427669ba88e891d31ee21e731e117f4d0c7ce4706aa97da03004b4f8138187c15fdc8cbbc1288296fbc08d03224de71a058bd59787b1c195547ec9714a8e59f2b98a6eb6f7bf4835a206f4dca676c072e125adcb9df871574d2bdbf35375af01f522730cee385eb9b8091d3452fa9c4ec443ddbd1297cc3a8bc1ea4aa14868026a0224663717a6c48d7f7c3a03cd280f196b9824f722ee4cb80998d5ad173c3d595bbb69e181e6bc4431a67805eb614c7e58182d90f50910fd56dc503a07429fdaced088a45aa3bbf9826e5bad7ab2ee9d5aa9c830c46b5f5621a8fb4c8ead9b1151da8d5530e23338e95c5c0fbecddad42a81a37287a53365a042cfbe52450adc09c44d5716c50dc2c40990af7f90818829e392042ec2b1a3f5328e27d4ffeeb71c47acc272d5a25fbd646354ecec45ee0f069525e0722967e2ae655820bf5615333e0812969a4c1ff2a98e572232395745efe73ba488108c336f328b1888c38cb430d30a11bfac5b451e8b4d12593a8fa240b5ac378be3c11c47a31af0c99ee3c4f22c63ed95d072a90b1a4d3e780774049dda26ccaf23557d962c5e44cbbfca849b55d48022879dab12c0b97916b2b4f548f9091ce4dc8f4cd4b0594409e14a26b1dcc2370a2f39c141f558a76d0ff2a8e7972707075cfd723383bb899cc072dcbf2b1da5f3ff9bb89441d05bb97407791220510a887d32264601a9ca9271b927080f4f7f2aa7b52a9355e0b5ec494e7472fe91d51c9e7656e15c4ba978b0e6e1bd0efe77e6fa2f8ad992a2c0e0d6852b99ddb40684117a24bc9b8485ecc39759a655ab7a5e81fd63daf29735fb23829205d76f45816ebc0fd7bf8929f44d9c1ca7b17b73c088d965564fb5f73839ce109d3f65a6d2c7f0fdcb4995223f8cbf64fe4fd23c0140a7d5163046cb83b2cf1edfbfddfc51a4a70d1beab44c107366f7eb0700daa2c5a1170de4339e31ee1a07d5c72e02ec80ff58e325a3ea7dc6d2bb743546e5f4a6171db79409908bc8fb8a8fd12d0e59798b563790ae1afa0b4ca7ea604d6b4b8b8ea1642641f0e06b8193bffc9bea1c2f0086a886e185e50dec8f9b1046b8940884570e4eb4f2cf00d03ac4049650882daa7a45de3e57acf0aa02808593335807db56180c3d484069d6b5ce027cbb75fc3588f80262543702ae4611587e12b05d435638dcac0dbf0d85848cc45081f8770e982e51d73a07d7b5308e3aaad86b2164f4f54e76784769eeb4acbcf136563bfcd3ffbd8decf0980d11ef083a1ce393d56a1c81703b819062c1284368c063d8d7378532f5ada88e00e2873010ec8d9fbdcd2ad37b215f79dbe005b57b78d60463b6279a0f66e283d5941808c1508bb3e078b24c314084ff59f086248dbf60ba1a3938a95574e69fdaad07a6535d0afde7b44dd5bf1abb4c81797f5189b1540f44b2e6957b968c7f5c55e25edb4a1eff1fef5995035196e786a99e720ac3a710bc3aab2ae444d08999006c89e9c466703ef7fde75cb981b7ca899660bebad881bb4eb3cbdedb7b4e1607e3675b234157751843298b93f3d7a52066f845633b89000c0d281dba52773427bbd10e0049625403d01310759919c6a9e57dc4d7244e932849155ed8642fc7c3f2f02c235708ad1d1824c32508910822826297bea11a64a932b24b75e64c91ad9560e252b2f7ccb86b46171a29dab05af0a8e2c534aa564018dae6b8742d96fb6d04b9fdf09dc42b90ff4beb09136df17345f373f3e954b2f1a636e46dd7fcc462d60e46f643eae9424a96d3b5acf57089f001ab580a8e64f4851ce6a990d4806f453231ce32b9e2be12edcb8a907118ff3a530e544a0e0d51454d20361618a8d2ffbeebb90d35406f797b86be02cdf966e8c210abdab1f7ec61771643ff31c2a6c392721fd8cf9a4caedea889a7ac0f88152d1b0d8ac955a6554513ac537d268370058f237ee58b2aa83e82133ac04356398dc64ed0548e239f2c8a28538ad93f30446651a20302eeae162ec2cc89931132f7619d6a577443e9f7ffbd248fbcaa041584dfdc877e1bf7ff2b6d64305c4f050b49eea2fe66c0c92e8ee3bdd1fe70f07afa9d91a39bf844b44d53c4f57fcb7800e144f88eebfc13fd230d4cf255822e0fee4338cfd6592164a4ff5ea4a706e7e0866e5a013130e30841fc705ee28334d6628f5e1768612b0b66e546dd5a1ea6da6852ecd17272d88de3483b5746dd292ac28796bfc0b3cbe39d86bae95daa47edb75a499e8930cf1b646b4968a2ecc298539568d581ad45aff5656d47096b750020a6498d2c401b933e0059ade4165a1ae18439c475958b714acdbe4c7b989ae5e179c2a62f2e3d42948cc35359e4bc5c3feaace86b5a2bce523c7e57b77e1b8a047c863e5bec00561c9e6cfa12e449e16aa51077a3e16e0122af82f9e62f095636768e168fe2f15e8092d1dab66befa31d0374864b474c4b6fa1ec64cba5e526f5e6222ea0fa68bf532da85f106bf6947d609c985991976c2837d2f031689fc47898eacbba86eab6fe8ccf84e98d664016fca696a81e7e5d5f46ffb30145ba30117b82a0b0aff4ca53cc0bd936fafd99a28ea1ffab005472881b852aee6475cfbaa69a9e0c5eaab80e94a1e380849d3993c12c39403d6ed63bb452c577b826fc562674307227d7376babdefde6cbc25eec37402990e5810edcdefd7040e01e17403775e1fe5d665d193665f9b3fb188bf0e0821b61f05eb7198615eeb21cf2b642b6f97cefbc1fc731a5bcbce91e2258f2d815f5d3a4ddc0971eadac28451c0247f5af320b0fac0de05b53c0484f135cc18683b729cf77b887bd86bb7d3accde0615c70204e5d37797b40187763340cc4c2f65afdac640fa6cb5faeb3da0069f19d955fd42cf5b991f030e1ad9bfd446ad543e905a08a1e543e81abe4c60ebc326b1a4ff6cb8ff9cbe3c78d0e2c9a78a6d9a9ee58571f69fc79a2b638104a9c379f7092a01fe785f970163029edfd2b01d549367ffff0371c79b648818c445941edc7c8ce26e87ce870f418ee4873e24cd48e638c6c6ade0649c2733ec480b201f0e4a25cbe846a99c62477b76f568e0d41771ae7870cfa3049cfe8e2695273a12344e2432296bcab77553110fae3a3baa1ef865d428afca18cbab3d9077423a5a504d80ff3d6add1053817aeb4ca455763aaa292b8f829f4abaa31dfdf46b418177fea2ba5b1bcd598d67b9026aa51f57e0f24e450ca7c615cc6ad2bd3caec0e5ddcc1af534850da76674495f053c1d8e547c4c3c3dc06acc68f19d5fb9c9cbbc4c9de245a9a9225b3bb0acd8751c1b34deb03f76d1daa31651e5c0da69d3d9688426174de54f0dad156066c58eb6666a3b95adf8dcc39648569b2745232634b434ceaba8514e2de9614bebd9b6869ccd05eb47ba425900dc4f207699159367904830bb2519e213d2d39e7d7b711d8d2ca0261dbbacda182f3c26982b94f17329da4ec4d777135fc058b17178a62e6247b79a0292987bcfc344307cc90dee5015557499874042b77525d31ee7540dcb7af895836d1e9ce6274f61b170713e4a5ef02658df9da0888654299a8f0d98b8f309b1635d11937eda385f61c5c4d33f3bb03e7379fbd285f2cdfdccff48b3266d59cd44674566bb70fa3730759f431e47849acfdb10bce5bc9bc6bc69604fefc2259a5914276830ededed172a0ef8cd5aae536842f46050fc43109efdf3f53c0798d98e21e4ac54d9ba36bcf48ca5a5c52ca255685c81c5f74b914a5a1a2ce1b129dd670a6f08d31edf3d52ca97a31ed58ed8e538a7af305f240fa7133fb48d9f721d69fdcd92f7f61ea424ca916f86fff172e68651fbad8fe59e47eac6750673b3351dd8010eca5bfa1541a5a5bd178e063d9229b553a164a840380fa35aa473cce71fa1e13047a91adab6ae43a48851b550235835efd01ea69e5ace4cf950b8cfbf0aa41fbcb28def5051a24c7049a86568c52d48cb4cf9464c259b691cc091f0ad01dc7e7463899f74c092ac2be50586223ca0dc77863d59b0e6dada709ca4573ce1e4d9de6a3dad427c7bbe7e59fbfa17937371e89b2b0c6c1213799f880eb95207cba6d61a07a9022e29fedf635b2992ab7e505a105e80dc27a0fec13747005be44aa2d161141f59ba4b68dce3c7da9555afe4e64d5b255a05ed375c46b68ae5dfe8c85e24a53e87a684e675a8b85019e8238be0a8ba2511efad911d47f512feadb36c5759a2edec55ec8f49a8e73a38d1e26a73716360d57fa44d8a8c8db7126ed53e6a8a95bacbc0d71650039af6f3aaecf0294f836d53d311d50387814dd2be81faf7652eabeaa04e4286084548e47fe5b1eab9ffa0ba66fe32a26649c5dbae48570a0642b6038410b60f66cc867b72484c32869228a6544aa21049b0d18596c2c3e2357e1aa5de944a137405b0f25765451cdf72c98495846884a3e1a4d8888078bb94daf333c6e9600210aaae5ba6f45eb9076ce7f4c93b8ba5188b7c368f230885be71ec95813a34b0fc6e1f79c5cacc0aeada2fb65e031709941e1b3df90bbe34dea1a2890cf0a760dbc7d92b361a70d2bfbd342f116fdb62c3f1fbd1c7071a393778c45d75ea92b278514c0b8c30af3c1399d7ab2c991b7f067b1a4b2d8ab57ad77a13820c8a59493ac877ff1bce95d5a9e7d49bf0b4e10ec61c67b4d0ab4acfa0ff347e9101de907cb23ba8c18bc8565cb1c914f9c44e35e8da2534226dd00b74a183326850403348132f88dde019b6253a623dc93b609222e6a4035aac9588f94f7a426acda425841266a94eeccc3cc58f3f9b3d438a2967adf4717020ce9b2c44608a530d0aa43e223d6683396a2cee54818b247c5e6c6c6080d131291654962a09b1e7d1f344deee4e3d16269e741dc80890bc0db3cee47f793cf85a87a7a8ea3c9832921547d60e5aac08a9de25880834fef62d0b854b2a23d6608a784bf4687ff10dc4fe281496519344b622538a19b8b1cfe48aec935f2604c1a0f057b284c16570f6753b19dae040e6bf34fc7fa7578cccee94107c09b3c22a9a083e9e670466b4d75f1c1644b6a31f7a7adbdec6a5528ce4f2ece89bb40c6d5a1692f058162b26311ecb73a2429c4ace72497c32a70eb5aee62034270fb2f47427b98ce925dc145c4a03271f29723d63d7f16c91bde029af86a4e9245d0488dc1b35f019b54d72d9998133967398fce682d333395dde680cc03b7f0026ef0d2b70eb3d30240f249b6a953b62931e80f56272a4a260865b1e1d8716ed4a2edc2256e7e906f777bd1c47a46cbd5a9bf973fb599c6c138747a4ae9d83d300d55d86cccc17a626aa45a4840591a0f589c249a8ff7ff459207c60c8e2ff67b26878f0a3f119e58e3979b305cf58e03880a4e0a427412713008b883a0b70ad4e1c07c15a65880b470f36feb57270db751cabc3545baeb7cb0a0b2dab24a22837f142ec12765a6ef8dc0cce062e6fd6b60eee612b368b25fecea071dc312716db327372702ebc73caea2a4e5bfa40a7123544539b23a2c41bbbcfd2059eada5f11221a0b01a5ab0390a205c08eea6f660bd05722604762ca20405470df0bc38ff43f206657a6d4265c249e7adbcf7caa0876fea413e40caece753f56ee67f7815b2afc1e2bb428c977b1bdd7361b30b032f0c4cdbcec2f63b001af6fd392cf464302f3efbc5f723579b1cbb86ca8b35a0129e876c08fee68ef03a6ea5666eb8993748610f4896ae3b73126ac7e7c293af490bf3341df880504da1b7cfe92810551c40e4bcc452d092c294ad01e4479379357a634344087a7824ad180803ecfefa57ee4ccf8b531cac7aa4c41de71cda659051b3cfca1e1a2acac9625521b09e2fe26c93d1cf3c48a48cfa8eb8e510b7675ae51d48d69b77265e396c2bfc2f97b4a98af578e6c17636892a3230222175aa9d483cfd6882a8a6e638fdbd4b480c9e78d6324fed0d268c1b785fe935788bd1b37669db2577e072ac13e5cc30fad9da3e7d690847ff6e48c1a18c0344d692dfc7d8df76c859ee63851e3c3d97ed861767dc16e89808b615e3d13760af29d1970b51e500ba9602d88a0938eb8e0ddca8ff6bb8d3456855a414badb80aa9564fac52be7f8379af419989423f6a9e4e948017507e1c0f5fdfe97ea7c5642d3e03a5c8745d4863c1ee00ed18d297a09f5ebe341b4264c6494aedea0b2c5349fcc6b61059df61b7f36b88c143c058f8baed19f648d64ea461b044a993b274913b7082445c1a6da2faef7c289600efc6c4d4ee7d2c2670d47c89a7b1362d94a1308b4c8403e28f902843f490ba547b3bbc376cf952193e231d120ad92cdded04161719b3aa1869bd22c4c3755e97c856911632d009d9c61ca0f04bc72982c31e5f6285dbc10e5971b43cef069b946190a8044fafbfe944044e01caae2ee7a4a2f8478e183d20f738d4929eccc22145b802e47f8e4b2ef866db64fc53feb05341fed9c18d666609bb5be730b8a72c28bc9d4ac91a58f2b55829b92819b7659b624a69d8ef4da16623220f5e695a64df258c413356a7f4c8c12563d4cfbf78946274001bd7c2444b6870fd7c3d3caecbd6305d83157eb43d7ae6328aba63ec4b9cf839e222144819b05710859997b37351370a813ef61025bb55f2b1799f8c7bb9753fa0161621f81e4ed4544ae0ccf3b52201728ee9961049adfc32d0296d8cc4d47af29ea9311a005a0ed9e5d39292811034a6172570eaf49d24a635d34032b38809e36096227eb60043676b50e08bfe2d342a7083613685582401cd57aa659f91f35ed7b524d262d548612552659ad8c38d6ca9c1481066e42cf8297261686553fcfce9ac7e1191719d618b23412cbd7b2755a58cdd74411e2649a1b64c39eccd649e23738b7ad5dc3908d2de96aa8264303c83549b58096b80f12ae595d0a89503267d15366d13a1b6474d2d7d26b0aeeb713c5aa1e2992c563e0789f385a3c3d7832be7b9035bd670f6f105c8c259ae6eafb27cccb760c3b512241b09072f50f02de56aeaca1d6e1efd4cac2292af17fcc2c7dffc0afc3fdfb57a98cd5384bd1e0eb60a60236db2729a8fc37ad3044e150cc1277a87327a4ea66a1810ff5a1db52505913fdae08a9026cec84b889b19a937995d33c4a167b77b8eda3a36f4150396d2cb65e5803b47b194a0bb2ffddcef220046f84a2a707c0d6e7a81d8b62c232d8a22b15e8ad1981a98ebd11fbcca3c3144fc90d66280814cc3c4e71093697035429cff647ee956c2a612890bff09edf64b92d93c713e8ec935031f1f7c3e4a31767bd70f25fcae41d5c5ee6638fb858ca88f59a23bb9f7fab04c14cb8933b8d8424e14013facd35d86632a7cc6494193d1e73657f4c3dd1c45236b33ca885c03b8071bc65ea6bff8faca0c358544f56f449cd02b3dc1de0b3505b5a3ac93adc898edea06b3b74918bd2aa9fbf045e836f4b286882c0aa135c6ab8384611b937531bc2a181289a873151cecbd4f36b5cff86126e79c008077f07138af9a28608e3dc44afaeabcf5e582145f5ea03a75a871368ae6e38611ca5749ca7c56efa0e9b323c013e0386c8588512a368b36797c67aa4d1543cac5d6dff9a85958eb14dc10852ab63896ed3b76ceba9bddb43f6b14feeb633a77f3f48aff1a99efc6c4bc50e6cc5d96e1adb76c4e087bcc1354593478760212fff688555085b07431d1d98ed6ccb994827c3a3bf7a11ccc0c7916df7a01c644437b339d0446b85defa82ab354356f4a49b52ce8df30ce223783244cc70950ce14150d6257b1002503c82078a71f9ec2bfb2f57025e82693e1c02460bd52b63239ae2baf156d92c23d601e9577c3da82a98f35b8c9c13a0264084b99f98914eb72d730c5be384809bbc8276674fde5552b04f948cd40ba0e1156dcdde0920596e96f9584188f5b2d0fda9f7dd8481dedacd72698e6196d76852895d16f54619af684c58f0ca7a3bf013d2689f8c332510c3e2dc7d19c4b40c671d7964d2061c67c6f96bc1a2527e3938623b181ac90c64a34a2bc3e116868b3e68cdb6e9ec7cfda1ad4f636c102a17ed25fc2825efd4394260b8231ac7a61d3750d784420c9ab889c269c4593f6a446294b6089d4d412dd830e5abb3d959047a04e9c88f3583e4b14696ab4c1597360c4ce590cc4f3b0404c5017a7574c32495053f02615aea866044a6203477af087d48878fca325ddf181154f53b526433fe7364e290fa5ad50941b358c7b769a49e6cd8f8bf6fe201fc75f62c198e45cfa239e187351cf4e5e1c64b079da78115c70c9cf77761ddcbc91c25c811f7727bec2dd3b31f2445dd28a25bbf69165fb20ab9af0269e639680b770d5fb997dc0ad7a34e3240271d12ede4790124f01858450dfd1128fb931fd6c4057f15f8b4e852677276689fd05ac2de8dc1e65e1aafa770e8a1898ac3aefd3a481130007cd7b732c761a88da87b62bf4ab69cdc390c323ad0c96e605e65c73159f8f3176ca96db233a06a70ac5a23e6e14021ae15b36ecbe17ac25b0cef019c655d87575dcf45ef6e00720b24840dd51876cd885771f827b01a303e2c543e71a08a727c7ff53fec4a51d0df6a45ac8e8117a800d57e6f3a47a380236ff4d02cc4a70db2b2170833c93ce0f35a00c9e2bacc3405b1c3fe4a03bfae6952285982ed61b0447740e305bf9b1a37cf4ae57d186b21857708d80e9350aa1b13952d6ce62bf52106462c9b9348ad254671c8d4d2ab419de0242b7d15360c1f9dcb2e4b61f603320876c74097def958c5167d03a524e01283588ebe799250123df9becbf0b106a7cd4bb89bd1012143efe50b32630eff173c0a1bdbc5456493358e7a17b66e6c45cb2ee14a2c91cce2f0d9681209f4cbc1aabab0bfb16a1277f52ea3c11043199fc5cf10e58c83335db9f8ff8ab198920f4c3a163e764bf3792b8a456386b1c260c8d5cd0cbfc1c5f599321cc4f4145ef1dda05f736dd5c73f082aa9ac03cd94f92ca47c12a438b64df5b80064d0c30e0524e00b63570ea4d32ad5d731305f287850268982f32af1f1d580b76a70b7ca1bc304aac52b63fd5b115e0f332a4bbc4c72b836f835474d9d3ee62c6e75b57cd8ce409b6819f6aa1d8aa72653b3062295d732a8d12ff7d5eeb234d8926e8dbb773f44f2b4906890507f9714ccbd31249401d30a6a1d5fbb33af8a66f92c7ad0ef71a247eac854bad05020578a7f109d5db38205c7b5e139c01fc5b7062462e520b5870ac4c5476dd59e31eb6a21484c513fc7be35c2f40dd220da1c1addbda0412c985828bcab2ce72ae8d03294b49f7ea4315f771d61769110b52761b8961b8905dd77919f61a7048aad67d7dcbaf7b51c68c706e501fd47c277827d35650b796138401d717b1787f4226f3c8092a5173baa1f0db353168ae08f894b64d12b6b23be567c3aeca06512f4389d3e08a8db662b6bb4c4a2cc407a81bea19e1bd37e44be156f23fe64d7d0101750cda517eeb15053588a8fcfadad8faff65570b2192dada52019280afd2c3693f814700d5393670b98ee980302f506ea9c660e6b5e675636c89bda6ca7dff3326f522b72e408416c5541ebb13021a641dbefe9616f33ec7a9870ff33060c64f38453ba470cb70181e49a0d75ad8a71db3f160903f410668f9e019c18541ee47c20002f6b7187e3f852075f1b65ceab9ab020cd27b275b997c140aee9330bc750b1aa48a4c166475b80adf109f547802e98384f32719f79c30a88ebeec27ab0a12cb549fa8a7731570d756692e97f665d8483e2e587cc102def0fe4e910e19c85885d26f3049b4b4d0f8646bfeca4b6487c922af310387cf0358601d863a5cb782272d864932dcd552768c64894a229975fa3b0af0ec655ef0b5ae65fdc5f7f84482e2ffede79e3078c23db30cc442da9548231fecf051c7a0659a3cea83dfbb0d8d7bf858b6e35187f2a74032e241b883adb1a3c04e6e5c67ab79caaa5d94f0a3948098458db087dc68eb950285ed08f2f4e54bc71c5ea74015449b19591d62d71665539281aba8e1a84bbd289c5477408d1122a9bb84cb36363d091512efa5956e35bc63bc5df43cf22404958d90aa2c2fea36f1e6ef0cdc82128eaf07ca79029dc0585719319cf77b8ac31fb823d233a4e07a9fd0521053ab78181ad4b786ae4c59f062c10497b28e5d83a3bf45bc8cf3c63dee70f1679bf88d543fd24ba8b015cb12532f146b488d93958b66b327740924aaaecf18eeed13b14853e0eabcf347dc8b4c07e43e3413c0ad7b7fefb484a69c195964933865fd6f485be71f209734f35b4d237ba2049aef2291a3b1f73e2a3956a77b6570abdbf1a85371dcac455086b35fe3062a5a0aa7a0a0fe36495462650455853f3b4afae57673e308f80ac82d60bc9aa84fd25145cedc1bf49d8c1d1e96a6496777d590380b3f1c1b24a3d7ccd21a02538d87014cb0c15acd5960bb69f5fb4289da56ab04d2e68107427511f73ff66e646acbe4f083291c75a4c1021aabc4fe0b9ee0decf2c24e26a227b5e96fe948a358c79137debe4072277d12f184afe48a0b73970a37fff79bb156a9c42082261d84154dfff41f6b00bccb7d9f70f0b90c8d30d5c91fa30021d8646d5b435fa40b150905424e50181b3caf1f94f7f0fd7e05a3329c2ed5ed093502ada249fc220f32d202f7d4a8daa0b75658c6a2ab42a591b984e3ea24fd4f52e5e2dc3ffece347d39c1e90e842f4f96951c922e9bec7aa719eb926a21738a007e6b00fa2d68df93bf6320fc2a92b5487a679e34bcf2cd8c46deaad6064c1022f1b451a56b9924c8c68cfa7f9057ae530892254169cc8e384a866c4ea3de60e4a4538c3e0cd6eaca0c66f145eb51b45099e1f50b38ed2273f20867e18dd075eff22f9d95c15f82434dcb0f01f6887a26ba816b1398fd7dc24f980bfb7318f7e73da2400fbf86270d6de08b1d7767878ff9284e3cab50b8859c423006feee1fc18c1eb7f0ba7f22c58d41601cbf2b86db2c9dd6cb0651ae8e2ca1dd98661a9986a347c38360d3e900a9977fda4835cd6b39839ff69a9c60a57e254f3028f765250a1ca3129c4598fa0961b4110145f56a5ec153be969f82912885862ada136f257b346b6a1e26561f46569384bb6ae6d022d5e90dc0b0e56011cdf05bf968c3301c7a7e11126c6ba20dfbe42526e441b4348fcb1076f101707554f63648fb240b7bcafa2cc7c38a40fb552a195be7da2c84a303af81d9b397f1b2b3f79257eeeb5b5db030c364b75fc01fad08beb08ad17eb0580b125f3c6c18ed40d2ca2c9e8b53a935ced0a357317543837f3012c24a85ae8185c112ac2902f79c906ecb83c4f21a8849c73e0cb7ab2351832191451f350b183bb4ebd3b9498d8afadda402a5450d6fd85546580be8a026874d8fb9757ecfd677a2ab11de0a9427221d08b5822951b8b2061d03a2525789d4ccbc55b9239924b70b0546527f583193b1462c5297e921713db5a2bf2624a02fd556de6b1a9814431a803f9e0221138207bb80f8607d6cdfb08de419803cff01a7461f3cc4b18c4891a1cc486d03e8a7d430c14560e70c794175a377b3410b61f40953207236ef353f09f730a5d60485dc55bf1efa94e9adc81682dacd954561f10c3d5d4608f535f9eec10a20b826051da22bf24dc231c9f877d9eb194d474937151622889352e332ea5b8707ab930ac9f2964515a1283a53662580ec30145deb735c246c719268b3e7ce2770de71da617b36fee062433d8f2acc106917f01516f55f1d5d039ffcd6a16722b2caf55a36f64edd01a1c656af7dd7bdfa596dd0d226083fc0da5b164a5f52c46b4c90237142104fef6497fe86acfab8338626d26ab18a2e17561760fd5723451d0b025005cee148025f863d9a6e717c7bbad4a81f4b3515f3fe14023070b139cfdb9be783d85074063e80492567fa8ad91b102140fa089986fdbf01739421ff6dbc83dc69e4501dbcbee780822c793b63a532172f7308306a6672c5f962c3743239e67a2ff740695b429c2ea09655252353118aca60ddbcf3abb7d5324fa495350a89e1fb4780fb7c67534cf18bc04c0d100c8059138d6434b7a61e138fed792264b65f2c1d617129a1ea577f6dc3533147d11ba6c7873279854c6824153537a9ce552a43c647a052c1f566d9fe03c601133bf387a15b960c1e4c964c1c2c55c4ba08bcb14d91a79b13652a590f04efe30b9fd2319166561d894437d13121316fdcd866bf5b4e0b84c22d975b5359aeeef1e5e52b788b7145502cbd68c65f7ca7dfc008706f056a213cdd88627803477bd9ca65d3a2ec500ba2ce346dff1b447a01de6efaa2bf58b27d86ce48bc197198850c2e8af6ed2eca56f70807b2a8bfa9ea94d8d6c0f4bb5c26f4611a785ac600fed436ba7ac9d4a12b3f338890e6e7a4f1d2425e44488118246b33bfa5edcc0f07b76e744fb672c03892ed9ec3c0a0715264c493dce20c972c6f5992faa3a2cf07dcea885aec3e2c12e6588a7fd2b551294a39e27a9a56f81bf4fb496e62228ba33a4ab3d9fd455ae65cc7000e30db1e363a60200db430fc5eb6cb0bc035315bce034f4b135dc94bf51140cf65ba995b9bde215227b5d27015f59be4fdf81cf9b86302c389e819eebbdbeedf4d0c7c42144b9659336c2400b111dbd80cb7ba1145d21206d9cb807696f49b1504014babdd46bee6508a8826b1f7494f92fd77f4c288698c23d26e5fb78d9cd9a6dd9790bb11aed3cd3eb3c7f444216eb0845b8a40408708080d45bfbffa9153074b06dc2bc26d658cd63971e28b4f690603f373c7340e681751f0a06f4667ac0a186250bc735b2ca013a19f13b3caa30b6c18a0f22e816f89d135087116e2a272986029c6fc3af8e2e22672c526b9d67ba2b9ea53b405ca8646965f8d755c31bfeba29d7663d59020cc22ab8bae9a93b20ac5f825a3b352e428f6eeee48ef46993ff1f76f08a20ca928132db2f6fcef00140478b5adafbee0f536484e4151545154fa94d829e1a285a0449e1a4b1724c321f9aa8c9c94bb7e0bef1463ba4f6ca615aaf8dc23a9fa4489a2ed319db3e07967f68aa93c1bfc0a5af3a984c0703fb53f0a3e01eb930d7d784db81b921e80f8e06d84ae364a9733ab9799c32e955abc1413ea0872239c314669f2a84b282742962f15030dd9068b6526921119abf60b5bc397ea8c2ead4a4dabf681ee16114dd8fd656c9100183df9c134d643ddf1cd62d1e387174a3a58e114ca405d38bdd8b681135ea3049bd23a0e46f405eaa831d5b1fa1cc6b1c7f4327ecc735a18469bcb54cd2f39a011aaf74c5589a44b2cb11e51215dd8054d75e0d125199a4ad122d97d4f93ba4442d3fa8ef8fc1aa55f7e0e29bbea7d20592aef01118e4c5391796a48b9658346702060ae917904accab3efcdfa586c920753be10c94053852bbac6dde80531cfb2764c8ca199ef7bfd6d5e5f4322ea62814283e2b56061c9e5342aa5a9f8c622d4bec3af760e2e2a4df5fb27bc08fb62f34d23a32dd9668873a1102b9a15c7f5a181bde932fa4741a1af5a277d4415e3b47c6c28ac3a68b4cf660a68ce3c4078afa9a2910dc2f52b22f189bc892f04c25bdf86aaa77b6ba8ad7d96df593a235fa6d5a91047530d462d2f90866a401ea1a4d707bf29f7ab57e7a71914e4549cce8cd66faa0fe4be2bf3beb33c2d28bf7e4e6cb60355612a389fbc4160e987d86746844f2080ebd3c1d2c454b1db8ab7557b277b39cf6c3fbd7e6bab1ac135de4fbec4e2f9c3e5d3e9d46a70f0a5ea0d42e7bc79af7ff10a8956f8acc5b9974ab98b199e9475e700b66725f9be549d64f28ae28bc98325e7be544247a34e9dacbc70df4671cf65ee74f1f1ce6d1883dda3682330eab8d04b454a4cb1ca2fb30446ef35839d4b08d6832c1c2f1e571c54096ac7bc02a3dd2f0e90fc17f72abf0e6a4cd37153904b75c66958e5ee8b22c13b7743514d475ea86f81b04cef782ed5d1b0817d9b0a43b9fb3f9e61dd3b7ceb6d687c1165c10ab25495b75bde17caa0490480f2338fffdd601dcb92e1fa851d5371177f54dd44a69aaee082d2f0915e884f847821884af5c90064a8d9475c514e414422ff051028f927e2f7a85451eb902a92011b727c88aaac3b4cac057854aa2e5add55c90beec8cd1528f32eb0a01e45a5e2ac2fa9721a40fd7d300ac741755932aca8a1d14a2ba9e42b3aec49b5b32855dd0f373ac0b981476afb82d51a42758684ab5206ded33667b68dc008db3adf934a1554a35093bc7c31c64d509e06f281b827d5e06966e50b5de128823083d0bbde4a49bc6381b85f3200944a493bc9ead2bf756dde4662c6151ad2796ed820054ad59a75d4a0bb1825263751f7201e14b7203d36acf1de8ea7702ce77d51816537a86994d15694ed74a251cdbc875457f9dde6ae6f52a90678b58f5473dfb23668253c28ae2fdd53c91c8e494984e426a9722ce2a7f69f611387d7aca563c7245269d20edc0595d1de462c914acf43d0e1097778965231ccd465a29df3261c98e22941dbd0394d55bac7586827750fa4ca85800e6f8454bec50bdf1efa7eb725cc171605a994a03c5d09e96c7be2b85ea7ed375112bfbfc2df47db0ee9746fc9f0750edfde1dcb9b85f4f3d573a3b0ec3c3be54439fa0841fdddab26f8f0500a3ab4ea36a10848597d9aa0bd8daf013d5c648c49da05f4618dad04d387fb75a3f25e750415efe29910e46775fd3207c10b67a950e320d48e93d6a49f7590f393ce3cc48692ac539df25bcbc77d9e3e2dfedfb0d3e47bb0c829472c85f34fb9f3979237a89c5c68f3e5a172697f82204cf9a6f10882f09d829f6b01d2f0433bcf03e6b2bf574a5dba1cbb2495681908610d82c4c6e34e47f9b79219641b5d355c8c124eccda6ba6379f3aa0f68b26d686aaf9d7a119a37ac57c10c6eaa1cb49864512ed63f1e18888390af7727c2efd1c716ef1e1e0133c11962e6511cb1761def06bcf2b9099d18d4392c10db0ee2964f40f93cf3eab70cb2eca0cf850fb4c632c7f44bd6a6f62ebfea06dd0aeab52c6acf348ed4fbb4ed480a061ac1304ceddbcf8a1583d9ebce8695ba44e2286e5dd310b6facd97b78c5f7ea4e44b210c60830e91ce06c7d7f02cf7a50b7fc211aaab2c0f94798073c08fa49664edfb817192bd7a1050de2d112403e950b4ff5d461ba2f6798f9ca7633704d6de214a664de1831d270b7efcd618703d41734f68aea253d7fea825316559ac3f16b511db7e9cf7d98c9d8241d8dd026b7fda9e41e60f180f32793bae38a9bd4284732b56291960c76b102b066dc9201c6d8abe4f6d4e0685d4523589ef1b4c3161b361db043d65d9124e9d6c2b6ef78b7688f0148c2ebd297f478aa7e74f04fe09c3e7ec14f43a3540dd8c1d2a506be43801d2703a12820535dccbc8e3b2f27d431ab2b6be5329767ad3c3531390e2cc044c63fc6a98ae037e0c884383d1110515ef7f2d252721194e49622d1dc8716398b8802b5219c84d91500ef8a90ed71084facdb025faca14d3b1b78f1f2a17a27425def4be7a08766a3d39c502e763ea4aef56e39faeadad1ed689e39a28266c3b893dfa5bef751fa81ce8be1dfd18d83dbb73bd947597d7b1aa266926ed80511f994db2f0431d54e21f772536da2810678175c6e8a4dae284230493a0ceaaaf81252830a95646b36e63e65b9b99f9ddaf8bf45303f630f9eb22aa375fa4084ef81dd9ca03a0fc4d8596aff3072e7ef23a116f0aa06033607451fd441ebb65b74dd7d14969522c520f4cd9836200a50c43d733c61437132ee674f06a429f8d68bf160ba680e4c40ed55216987f10832157ca427ffbbeb185e931b761ba45026e7e90bd94242cc7e79ddc6a8dac1bc7aac23c7ee2fe5243b76e555c14c5aeb85e48c2c50f02efa3c1890bc799030d9f055b83760507686033e713c48e2b7792345161798306d33675a584fa48ddb27b98fc030a280e6f8d416f10eb650da69d1129d1c88045cebd37c1baddeda554309d2780186814550aba76f4bb6e88532ef7c1ae677cae1da9b11536fb87dd33f02ed7002dbdb2542c53e72c45631eecea58e0f171dd125b5ebc5af392f26dcefea5bfe451ce57847e25e1e81d0398266e8c1c3a139fa22a2717e810519250a184024312ba77e2f0d15451b6ca7128be04011a19203cf3e7cacdb86058e3c523f71f7f00f07c866c260580eee6fae79f774a596b9e1073e48bc33d6db0922d3c2091e729a111f47e677994bd93c3ad80334ae03c99e51c16c61fbcae5c8b37fb71e229a974caebce3c04ca2d8bead6639f6af8e21607165dd813a9efc6c8b5c8f82e7cb5e41a72d0f735d5412e269ece67fbae62f44c677fcc7b9a8840ac5c47abaf34bd347fe409ab4ffae8a165b9a376258469c3411794c26d40d258f8cbc93acd116c7019bb90260a0f4d297b352cfd00f2cd8f19a1bdef5d0932248ba44a6906bcbfe355f2fa35f0947b3626ac4081f09999c4ca359ff1ac45334e24e7d31687ee3760c68ec21fec98d01d9603e0ed54f3d74b4856fd07218ff4b1fb4d8074485eb139181c9423f14c5e1b1bb3853a2eab2f82f41f797764fa9b0bff17c461d291e288a00aa94b1de77ee5830c08e65046cda67e96a9064aeb96e5416d6ea3c2719923dfbfb7bd2c345acefe77be2ea2120ea5a8b697cf93bb66277e67591d52a538a5a38342e269ca81a70869a8895d62a5c68e07bcb45cb5c5b95ba610f3f746ced01525cf6e632bdb78a492b3acec7aaadbd991aa370c51f8b329e8b6451fed908683d60fd24b2334f3ea14ee9fa68a379ebace8beff862fb4d0e9d05402741f1a55fff7d405e6fd57395bbe8f71912a69e18a7735e91ccf2a25242bf48d4745f75ba9e65156bf79814fe019eb9010e8303f465d242d8fc51611ac0e362608deaf579b621519e5e9ae21c54bb604b8ef04e06b8d095c47a192d6d3c3f512cff0822eae18172ae0fa7049ac5479c562f7aadc8a74f168bb99c29a38fd595999379bb79a6e9ae3d35fb459e93cf311abf6fd78256c841868bfa43e849ccca3eb31e8ee691ff9971a5c74e9894ce3c6446c2639703fec01a72a47c52dd3d4e4b9773ff191393ede27a12a9512d3f58399cb0ea92aa3c5f59308930a949f7014ed3fbd447ae8977c9f7ff68b185a5444ea1ee50969a3b5095cbd60a26743853bc5e6e7b45c6e4a9e663d4836b47282bcc6448263b04028f340fd175a08fe8df226bf6a30e816c866b646a256a2cc904e661d228747cb2fe7f79ea5cf0d243e57a86d32f14a5fbc48ef4e2f6a6799fee6dbf5d86c60c91115e28881d772490a8e5dc15e47d5e8d130f25e6cb45e26dc434fdefbab81d4c1f17b796362a3841fdb97103b9e50e04ef20ad3b159ef08fd458e8d05804f3a3c9124cdc6ee6143e467b30dd1eea7a016fe9ab2e31613034037ceb94f9a854e24003f6fbd22a208a02252f829b43a728632169614d1c51c5d2117b2e222b52b7c868b2e19db6d9171943fc6132dc1e48732de7d0c33408ba5eb3db651f813c77e96394ff624bfbe5e42d42085b807528fb3998b3f12940f32f74eafdb3cc0adf2b706b4677a071250a4c8a19f72270ab34e450b8cdea3d77d6087132a08674b9cf5b6813e48301587e86576e7b13d9c03d0b8209903d9203a6c0e86a1169451e61532df2342e73348e9993c408b4553c90ce7fba5923c4060ff215e6736e1e5ff411471f32af11c4b1a24cc3e30643a733250dc3f8784119ad96e39423340690f7e82986d87d28942d3acd12679d5de301f0e1a57de70cc14aef330bae114d83dd91c7feb682ee324b9e427005b24bc274d82fa00c7627892d545df3e3a1ded3d02a87347184564008c74b7304856a68c84dde73e31ff6607233241d36ca6ac623a3acc07c8f670a29dfb587a52823e45afacda8574d78c3bdb05736fd8d186d61c80cd4b6b851aa6f688db7c1be71844439a190dbe97f7e6f864d3e64abc28f24ea68021b710ae7c31136d8e2129d5c59989f4d83de4e41fea20c8774303af1901e5034472d5e2d0c83dc1bc06650426804c9cefdf272d77fca564bfa7d385361aebebf435fd72522f4a36b1a1b2c8f60a0087aaa35fab1c4395cea33308945d6dbc9075be4ff8ef5398656178f8d0355c8f9751580d8422ca59cf6f2735049f76f62703ec742b8a2d09a7dddbc4903a3e3182f15a80e17bfd96187699c65c247281f19f2aa893f5ae9b2eebe293c6e7c5df51c863c8322e929d24fe046fd41433bc2b2a094860fbeb06df79e8300cac82031aff96a0561040cba83a55b3f60885c93f0c0eed7728144479357d5ea524c76b1f189cfc7767c80656640a67c85c2ffc016ffc507cc7788dc335b63e91a590743ed40d799bc7babebfed448728d650603a16617dfb7bef2d659232cb09b7093a0aa6d35c32bf54475760deccea9634d121b33aca533e6bd2f469594d4fe957485695a5a3545398b80ac447be4e56206630df989fb9ddd88d89398fa03293bb31133883fa2b4c1b69d623a42fe2ad38f071c9d76b54f588014955d8a5a305508142430750dcd248e7da33a16802c31b358cc2e4eb3a6a68a992affbccaef3c03e2330b2ed275f35b45c916d2631348366904bbe36f9baf9a5d3bbcb5d1a1121b7cd532655ed11ba4d55df24451fad93df2e4a0973bb0d7118ce9accb56cef956ed4d005267627a488bd9e38e07762031337399da061888393464397393295529b94308b454e501216c14ee61007270430939c270c9936acadf0b66180d3a843edb220c79d159889f101295075776d72b42740919dd6daf3e3a869ca542a1689ee4e014a74d475314c4735d076beb70ee6b6d6c6b88ccf5ae65a995b7b3165636fde95e16b6dcdbbe16923bb5cc1d24c171dffac67c645773106e7232e8942b258b9a8d034f3b4c1cef50d298b569a278a9e124547159126d4cc5b5af32a2d893985d94857e634bce6b591288a33d6f733e711546816e9c644a51b133d7c7bd4a8e8326f813726baabb2306dcdeb2c9d1a756ac3d9d2a9cd1e35af53dbee8303ecd72b4e0512e2c8918d3a0393a89338628b4312638c313ea14ea63bb6f8c3c2b455a5264e7068e16ecc81d151af32cc2e7ba582e8d79784bef2fe950ad751d751ab25ed296f4fa1bc3fb51a62573de4ce35cffa64ddb4b2a85fd19a9cfa939037368ea393e3382ef50350b5559e2b15488ff125e3e831d6cb292b7b7acc39e588052c29cf29a3c778ccb9b253488ff1d295c478e9d6cbd24de711282ffd8894c738155aa5551ae94226f74148f4242697f14a237f6543f1f1753bfa92181f4b9fb2b27e7272247d65cf252727574b4ca3971e3669f49a8f4a994ee3451ac91c9fe904075817d32ee1c6bef1f4c2b491d97432994ce1189e629c42710ceb8be1189ec2303499c8314452c22449f813519556bda29c88166772515cb22651144511259e7cd6a9476f4c3c893f3ae42719555288e26a874e6d39513a15dd89288a4eae722a10ec3d918a6d5c83aeb49b1ac5167d1c451b8ea2b5d65a1339bbb124e26f0bd356954827b687a5c06fe391ab75b2c750c4573cf10dc3300c2120866118866118de300cc35b6b1886e10dc3300cafb592b3250cc3b09a35b0b1f8a7aded431e7def45f18dedb75d8cb1d96feb7edbd97eaf779871631c862a8c71ca92b5d62ae3ab2161ee6cb3ed6edcb8a63bb4d97c92c9917814c910e39014a71895204552d4824352f4c138144d61188a238947528b88b138aa522754883a85618847524b2862d28728866e7d14458c7b31682143d18ad5c76d8c2f2a954a6941f5687f42516549129bbc9ab498ee9dc274dada83f4daa9b5236922ad965f795b3181aa2d6bc971249d8a7932351371042385f41f2533a1cf9444da9bc4a65194d23f4bde8688b062c40c0d0d0d0e530d0e1c386a489b9a9a52e87a8dcd08e4e7748641ba2d51189d749af2480d367f6246d0261c49a0121026f707bb933842b03eda5137b614eab199316d6e526d8358af9e637db4db94a72ea6b58d31e511234423d8a63c82c53235044775c39a1c393939a669cae4e810d8fab9222a67b52a85aeaf72788ee4e8a4c79442e4352398235aa0121026f747a7140a5d07f713620e1a98b7a11f1b8488ae928df819c28ce04a2c533bb277d640d5963d9d7c7ca87c94581f3c2a1013f641dd945f549bbcb4a71c27ccf147c98f9b4e26b5477b4e04b0caa782c9adf2c138144d61188a2329a65cc4a4d731570fd12a2b3de5a9b73fa39b50579935e50d4d8e732d8fd86cc2e388c9f0da11859bc3f17451a9540ad5d8ea84aa712ccbf222a93d30bea7564ea8b23eda636262eec9aa625a47d91249984fa735dd30d74ec7fb4d7eae0c07950df242f5d10ee64b0cb547ab9894f5a6c33391a31a662ad7a3041449c03ce57a94802f9a480016383060a2723d4a00145e20c08d1b868b906caa54686e6c2fda83a2b11ee80f104818c1023cb0bdb5da4a9a9abc2d9d9a5a55280e4b9bb0b4d921c35a8e40011e3f3a35a912b5016167848b9a285a5610765ca9b6412eeaed8da226084e31144563288aa2288ac65014454f3b4328149338456ff7bdf7767fdb0ed2b6ad0f20b7bbfbec768c316e615b6bad75076eba4962d4c3c8e130d2b0c2175a39000da0e81581a1054680972d72b896a54e2ebd3e20975e966ec62097ae42000572e9a952a84c991ec8b69a8c729b4e463946a1c4b04046156991513938991d383ac017a3d7df987a163d2c8544ac864d87846c6be5300c0de0258757c8c8e151184f1c19c001686d830d9f955c2b068ef2bd0520cab7005df2fdf98e02a290410f55844d0220c55a607a0b3d224017310f605b6aa704b9fb80c900d34676196e9e74c070006a343281d143894824181a488543d4c08d6088c0848d4430945077080772211831207b08971c06630dd2f66eac92160c1d8c76c806743756c91218015326573470f0021c0fc041f0868b89238a9b304cf28b1a2f0e60330336c648820d33da6003a90b3692682c6086b9a2c18609c20cf12a901ef9bae8802ac3b502b15ec533ae0c9f22eff2b24cb6893af1567b884988b97cdd264e205ff109a51b233f60b66a0f914746ad402ca945a440be5eab88019c5cb38171d70a842369245a0ab1c9e40a240e29730f62981c656ffbf5244c8e6859cd102e62b755251caba8f55baa5069a2fb9c585f1226378b6bc7887163a3685f67d62a2e4c5bf5615e9882de9dd25316a0a41d35ba0db3b5b836b932945fc76eabb4ac06e764882b2375ac645c97c8216e05e223636fe217ad6d329d4750a1f98de19f1bc31ebececffe22a972a64d2763a70d0d997cf4a13209aa89931bc34b35e833d116ac8b697be8f69de9dd16bf9089f9c2b4b9f7f5108c3072b822532b31a705a699ab069220906da459d368e86648147aa852e510d71e1315480b96b12d8798eb75d520d8fa78a1c63026bdc54281796d1057f5611d33a93db093de33561e95dbccd3c99347efd3c6936d3d19db3bbe0f368b222e87843e3afe8d67abf630b9f83ba0590ccf95d73cf68ca70c3537d9c20cb1c34660dec61d8c37108357777317776f9987cf4f0fc9675b5abad5e54a00498676cc3a962ce3513e21c90beee9e9e96112e2766119afa0e36ed4e5ee0fae8773e2237f4ae34b099d160f9f9b298ee2cbca28ae61f200fad4245c35794f0fae07e7c331f9e9c1f5e04ce7ac692e1a38a9c1d07472c900672249d38904a2586f98368bc3e1aed5e150be1d2ef8a248690c920dd2b501df98d4325b5b0f26c797192ff99abaf0e0d23d4119bc7cb1ae25b28a97117849dc256ff95625f426b13d9267b4ebed90725677b3bb5bd12d4a50c9de942c4ee9f5c475e57018032f4a27e8d8608faa4b12b9438d590f3374bbdd5a1b10d5185117981b91e8a6ca5131a56a140a9268dcf57c54974c996a4fb3f2c2d3744c9ee6c2d3963cad85a729791a0b4f5be1692a3c2dc9d3903c2d85a7a1f0b4139e76e469263ccdc8d38a3c8dc8d3863c4de869c0129ef6a5f6b425dad3c0e4a705674f0b13f4b51bd0d78648f81a4ec8d7aa04f95a0ec8d7ac8cf035a29fafed645fbb927eade8c7d77cbe26c2d7b2d440f85acfd77c7ced83aff5f81a8faf79f0b5a4affd6a5dd0af297dcdcbd7805ffb82f2da16d5074d669d355dedd13e3a1fdd9501e1ed3ebb2b0bc2db7d8aae4c086ff7e15dd910deee6374654478bb4fefca8af0761fa42b33c2db7d7c577684b7fbfcae6c8ab7fb285d1912deee03bc322adeeeb37465f6e6ed3ec12bb34978fb8fdb955925bcfd07eecaec12defe23776576c8db7fe8aecc32e1ed3f7657669bf0f61f4557669df0f61fbc2bb3386fff617465f6096fffd1bb320b85b7ff40ba321b85b7fff05d99ade2ed3f7e5766a5f0f61f4a5766a7f0f61fc02bb35478fb8fa52bb3396fff11bc325b85b7a7b72bb356787b8abb327b85b7a7b92bb356bc3dd55d99c5c2dbd3dd95d92cbc3d2dba32ab85b7a7bc2bb33a6f4f8daecc6ee1ed69efca2c17de9e225d99edc2db53df9559226f4f7f5706c5db53a52be3c1db5360ba74653d787b1abc32eb85b7cb6eb22119aed3186f975591e53a35bd5d66a5d3196f97e93aa5f1761951a738bc5db6ebb4c6db65573ab5f1765951a737de2ec3d2298eb7cb789daabc5d96a5d31cde2e33ea34c7db655b3a5d79bbacd7a98eb7cb8e3addf1761952a73abc5dc6a5531e6f97f93a756f972575fa7eb24e18ef4fa4d377fe4ea513782e9d41d68d8563e5583ad68e55c4e2b18c583d1612cbc7fab1945840d6122bd8bab570ad5c4bd7dab58a5abc9651abd7426af95abf96520bd85a6a055d3717ce9573e95cbb1b7315bd8be7cae232726d71f55c472e24171797cf95e4fab9bab8945c5e5c40d717d7920b8c2be80af3bafdbfce7fe11aedcf5f1a6df7cfc0cf5e3e2b35dabef359e7f3ef7352f67de6f219e9f351eee52dd908c7e72c349f79194b2eca57f22e13659d179f7bf81ce5330f3f83f2b325a29f01bbf89912173ffb6df1339fee67485afcac97c5cf8cb0f819cfcacf8aaef8d9ce8a9fe9aaf8592ef7331c153fbb4df14141293e68a9ca0701a3f82025283ee8f7c407f9701f84e4c407f59af82023263e8837f441454b7cd04e890fd225f141b9db0751f9a0db8db523f140c11b6b9ff2404b473c90110f54c403fd6eac9d88071ae28184f8201ec8e8c6da817820de8dd94ea417aef6689894d7f9e1757c789d251d9c132937ea6d158d2e6cf5a84a6e5ddd0019b91d974370649d1b1ba60dc5d1a1583a15d12cb97919c592516a9837dbd0275f69b60cadbd3df927a8696c31c9b4644271dbcc0d6504e56bc11b43198563925971df1ea2f000a5872824699a3696cb1dab121b2a8562371876f027e74ac91387e250ce239e38151a0a2503f3ba2dcc3ebaa5dc23dc4258c3bcba5ab0d17ea2e4441b408d2768c66e5716c579701b0925768bdd723b8eeecaa29c403c902494b3de188eeec9891302b3661b10ef64eb8db9fee42b6d005f6f6c87bf9d6840bd1b6bdf6103d306c4d3f17208cef7547da5e5b0617ab60101f18078b9bd7220972b0b091f2a02688b85892d2280c32202b71b1398630e6a5e60d2b800278b0968b4004102ccd0c00e8d0c9811019c2cccc8f2060e53a11d5362dfd478917aa8caa3c7e601497a2b469a44277d7e5a3121f9761efd3a2a1586e7e96f88b66248b97b3c7889a493385f2c8aa4188aa493e469b30e797fac9bd0d345491425d1134aa2e809754249143d89cf45f7ed6edbb7bb7beceebef7e2bedd1de2ee16bbbb556278efbde7bdf7dedbdd8d31c67def256d775b7bd67b2f3633c656d58d529181326bad350c7dc2100dc3300cc330bcf8e2b36badd5bc169746b66bad8d313e4d6da046b1d61bab2e62aff5dedb395b6aad18bd5db5e0f0a7d452c530c27a5d1cc791c4a16872d3353d11c3dd0d9b419a4237e1130a87a2bde478c5d04f1895c2373c99c8513c99c8082f398ad88cf144a2ca187cc393491cc993898c511c45d28cf08e223623856f7832a5502994c760324e2632c28bcd2885ae97384606dff0642247f1642223bce42862336edbb16bac8c178ba38f6288b58c23b6a3967114435cc62886584b88c511876219210eb1a8650cb196712ca38c51cb388a212e631443ac8586ecbe58aca66a8a924d6edd92d6a656091b8661188a23dedda23801de420f49d34d527f3252887944e4c12d5ba2d16f3a266224a9e18e68b76bb7e34d779e36cbe5a61bfb87573e7a499390183efb2149d274b2e895a1ea58df7c31c8de9646fba8636d83582d36a93d02a1bd19895509c71226266dee5e2b4cabc504386f338ab2ad2e5589420b0bf218828c841c6a3980d10bb2898f8cb2602514d96918f6fcd45aabd7dbb5d65a2f5965a16991e86ea0ed994657d6b06dc4762c21a620b044fe00026464d114552574aa324d222a0550430104288095161c608886c3c8d8b7441b198f19638cb159834a23cdd0d6e8b478d826b2cd4748168faaad2675c9a2ad7a11c56cab6176b2cd0ed92a59244aca367ba504a2cdb2858c34b2e8a293a6cad11e0d64d17f66459234e0974567d20497457712c58a2cfa10658071cbe205ae0359749bebb41e3520298b6e75bb2c66144dd1693d72c00b8e1ed000133891ab00194319fb3dc11652982fde09b29408e851a2c7e822031c2306420d18030738483c2984b2f87859d00839e0c72bc24144034bbc08d810e1c2e3f96288a8d113d3448f125da3c50d2e380a3053b9a2e14609b0b8e10218b8d1460cdec0d96c79e30ad2cd68008f9e2e5cc0008c8a29af4c244fe3e9644f23ca628c718953e5a7ce23a8d0d0540ff949c4d08a946d6c74cba257201a8f898ebaaa5c356a57e3363e6b9b1a2e2db33aa44e431b1ab7755216ddd63c1c8e4275893dc6975cbf1e737d4accaa8db298a47737263a2dc727ba151d26fe8a16f3ab3e572a602f975ca739a7c4f8f5f29cb20025312739c5e4b29371d37b7765a6cbb8e8d674d124b31b5da765a58bbfdb04e8225bef804aa813a97772f289d41e459c5c9befdc8d895ef33afbbb16c76981b74645a779bb7463e250c7c4de89bb5def76bbdd99a4f49dd16e577465342e8ae24e9cf9de95464537df22dd984a0bb3a691b1f0aeecaec4f4fc0c21721bbb1c03555b49c2eadd4bb6edd0124a7765abd04fd694f192f1744e69d2a75c6b79289b1b9dbc32d26772a55bd28d2caf3c4fd569734515880fabc3b8c88de1176ded9e3111d2248abd8d2a9d69ad589d904e6d9a04f5b499cddd988e57a4845ea5f55d226380b4d4c668bac07c62721185aaf57c2225cca67285d3f904bb58b30a28af3586cd4c9a4227737857e189c946f38a00a60a1df2c6c175940e6e632489a1036126304d1e5e9fd9d2e9c9af8f7e3283b67eed82cffacbe219ac391f73d7ef7099cfc15feff2d3e6b37b1fa246db47d768db14103fb814b7440f848f1fe3f759445d70b185ce6d165858b9e2ad952bdc5691a3620a29aa4401c51338279a606268092592b8bd4dc2a9bcbd39124fc5a73c127ec44f7123fe082fe28d7022be081fe28970217e080fe28570ebc50711e57b407d0e3e3c147ffdcde70fbf80d1cf979f2e42516c2886934173507888d283f52208218620a208238e988204955b124a2c31c444134ee09e80228a2a524c4145ae0a2baeb08245165ae8ec16960bdb85250282157383a3ca91b3d2d9d1c1e36fced0e0a8b139e1d02a5337d8d0a4061a66902106185e60e2c2921694b0b0820a4990a480c209474c305284c810a1126ab43c0b02d281042141808cf0234b7ff8881002083d3e3ee8c1c3831d31179a43ada03a191919191919195c0eb937055e05f2b0eba31bfdba2d76eb9468e701d3762249f9c107202eb62472f3e9305ea73a9c3e4821b30ede8ee23a75a14ea4d377fe4ea513782e9d41d68d8563e5583ad68e55c4e2b18c583d1612cbc7fab1945840d6122bd8bab570ad5c4bd7dab58a5abc9651abd7426af95abf96520bd85a6a055d3717ce9573e95c3b57918be7cae232726d71f55c472e24171797cf95e4fab9bab8945c5e5c40d717d7920b8c2be80af3babd865eb8579557aed396b7bfacbc742fa2d7ee75e555f4c2f2e2bdb2bc8c5e5b5ebdd7d10be9c5e5e57b25bd7eaf2e2fa5979717f0f5e5b5f402f30abec2c06eb021180e560596835981e96044b01dec0aac08860596056604db02ebc18e6048302e301f2c09f683758129c1bcc080b02fb025181858101606bd75ba03add2690ede8e3abdcb73f8f3e8dc721a9d594ede89e52c3aaf9cbb93e8d49d56cedc59e5c49d43e7edc37cf0c1fcd27f792faff45dfef749ef7b2e8ff447dffb2d6ff4599ef758bee8affcee895ef7563ef7551ef7437ff3301e7430bee45f1ce85e5cc9bbf8cf93dce75c1cc98f1a6dd479f68220b38ccba13c100fc808a80784c48ab9c151e5c859e9ece8e0f137676870d4d89c706895a91b6c6852030d33c810030c2f307161490b4a5858418524485240e184232618294264885009355a9e05019120240890117e64e90f1f114200a1c7c7073d7878b023a60329038587283d582f82106208228a30e288294850b925a1c412434c34e104ee0928a2a822c51454e4aab0e20a2b5864a185ce6e61b9b05d58222058313738aa1c392b9d1d1d3cfebd23242ebe2494ccf9507ee7b683dbc9ede876763b453bbc1da39dde0ed28e6fe7b7a3b403dc59da09eab8e9c0e9c8e9d0e9d8e928d2c1d361a4a3a70349874fc74f87920ea08e251d419e1b0f8e27c7a3e3d9f114f1f0788c787a3c483c3e9e1f8f120f90e70bcf120f189e204f18bff990e3bc8ae7dc8aeb9cc877eeeeeebea5519b1a1c3433e63b8f8e1d9d554e0e15ce4d0c2be7322edf824b40a59f0fa967c42bdacd74b3dc0c37bb0597804a3f1f52cf8857b40bd205e5827041b7e01250e9e7450f517880b27373bdf71e78be4e50270c1ba6ed26884392a679f3bb01a38689baede6877ecd24ec9d08200022afd12b8d36bac317cd929b883f79d51426e929f02a9096df04637cf8010a0f517ab832ebc51d75c8e10647952367a5b3a383c7ffbcc1862635d030830c31c0f002131796b4a08485155448822405144e38628291224486089550a3e559101009428200495d29c2c2cb62b4a57784c4c597f4eba2e405f865094cb016a6d3d2db4bb85d99fdc2db4bc075eac445d8b9e5d6655bec7613bcb29b5fcc4df071f0201e0817e283f0215e0827e287f0229e0837e28bf023de089ff24738123fc5a93c126e6f4fc56d126f6f6e95789b84db25de2ae176e8ed126e99783be4b689b74cb875e26d136e716f9d70fbc45b9c5b28de3ee1368ab750b8adf2360ab752bcade2768ab752b8a5e2ed146e736fa9705bc5db9c5b2bde56e1f68ab756b8b5f2f60ab758bcb5e2368bb758b8d5e26d166e756fb570bbc55b9dcfbc8c9b1fe3968bb75b388e9f719a37dd76f1960bb7791c5ef3346e89de76e13a7c8de7f036fec35b226fbd67fbc50ffd100047fdf03a68289bfae1533454a77ef89286ba29279f8307e075f01f3e8656fa0f2f436beddc7670ad736768e7a6c3fb10f9ec7c78209cf537bf9ee5aec7c1d17f39ec5dbee3518f3dcc79fc0ef7e063fec1f3f01eef81f7fc07eee37b7808dfe320bc0ff7f9105c8407c1d3f7f11f2f82ff7ceab2ffe1a9fff1115ee6413ee5407e0427e183b89007e2414f8203bd10cf1fe4b307f2da67a7fdcc85bee6253ccd89bc900ff912dcc813f1223fc48fbc1137e18b380a7fc44f78131cc9a3e029fc09aec223f1249f82b3f02af80a9fc45b78165cc9afe02e7c0bbee495f80bef8233f9251ec3bfe0303c139fe16370191e06afe167701a5e06b7e16bf0264f839f6f83dff04ddcfff4ff1b5cc7bbf3fcbbf5c20797e23aafc3779ec77b78eb858f2fe3f7633ce7757cf53b1ee57b70d5e7788e5f390f1fc56f5ee5389fc3a13c0faec3df780e8fe33f3c146fbd8e2ce51770dd875fc0e82dafa5d04db0d1cec15b6ef3c1e5761f5ca7b69d5beb6f72789cdb1aa60d8867bb09e6f69ddb9549f1f61ddc95fde0ed3bb92bf3c1db77749ddeec63f4c5fb6ce998cf961b201e9011500f0809c807f403520202022d0105836e41b8a05c902e68175414c40b320aea052105f9827e414a41c0a0a5a0e0ec36c3cd7233dd6c372b9af16646b3de0c69e69bfd664a33e06c6916ccb78ccbb9accb447997afe4a28c25f372966c94b7e45e3eca48994bf6e5a4fccb5db252f69281f94ba7efed79a9d3d3db33984e6ff0f61cecd4066fcf613a6de2edb45ba735783b6da8531abc9d86eb74066fa755e954066fa7e53a8dc1db69563a85c1db69ba4e5ff0761a51a74cbc9db6ebd4056fa75de97489b7d38a3a6dc1db69583a55e2ed345ea72c783b2d4ba72b783bcda85315bc9db6a5d324de4eeb758ac4db69479da6e0ed34a44e51f0761a974e4ff0769aafd323de4e4bead4046fa7fd3a35e2edb42e9d16f1769a52a744bc9de6a5d321de4e03762ae4edb42f9d96e0edb4a54e6bde4e03d329cddb69c14eb3b7d3c2743af3f6daadd3206faf0d750ae4ed355ca724787bad4aa742bcbd96eb3488b7d7ac740ac4db6bba4e53a70f299742e696b7d7883a1dc1db6bbb4e7fbcbd76a55399b7d78a3a4dbdbd86a5d31fde5ee375eae3edb52c9d8ae0ed35a34e43f0f6da964e41f0f65aafd31e6faf1d75eac3db6b489d7ee0ed352e9df6f0f69aaf531ede5e4bead4036faffd3adde1edb52e9dc6bcbda6d429eaed352f9dc2bcbd06ecf4e5edb52f9dbabcbdb6d429ebf4410a9901e0ed35309de28074c3a55396b7dff89ae583b358529cf583b3582cc7a510eb3a14a74243995e2879429353a7a71c85c3a355d021f4060b030bc2c0c096605f604098179812ac0bec074b82f9605c6048b023580fb6056604cb02c3022b825d81ed6044301dcc0a2c07ab02c3c18660b7579857f005e6b5f4faf202bebcbc945e5d5ebf57d2cbf7e2f2427a1dbd7aaf2d2fa3579617ef85e555f4baf2dabd885eba979557ee55250832b31c008f02f140bcfc252fddf0198c0d9f834d3e87a9e169371a9e3634c3d370323cad4a0c4fcbc1102d1e3e3a29d38c9551f54ceb3eb51ef1284ba1dbe50caf8793fa970f76774020100804026160491b98dd864a09bf5000c75be4e58b0c8ede9e9e32635d8a095cd1e92cdc0d062b856e88d1d80e1e6314e190bca2490155d6bfdb00232323a3d6e97011c6dd58bbcff7f329555f0d8c3a07b993c8ddc0beb83bd4e8adc38069b41bd8bf0e7ac0c8c8c8a881fd821a6bef1a90f8b4750e4edb4da2752f07605c3b49e25a0d3c9f15dbe1c189757a909a91c204028140d3f589ad83256e14454545a48f29247864023353c3ec5031eee5009f78efc537bcff448db557416e6112a0dd4becb3c16030a8638787470ff287baff7ebf9fce6aa7c707a391ca34323232cac9b1fac0474a774fa713985667752a9c1c3e7c9442b807877788601008fc02042ee17c0906833635373d20609b1a1042b835384210a14f3868aa083e40201008bc54c4a0ca92ac91757097b851f4e07b8471388cc3388cc3380998d66d1897db7b4c193c83f23165706fc7ef34cae0e54b05834f6313781cc751748c4913198a360cad8874c5d026e57276290cc3dd6eb74385384e1af8400986ac69aa5413488561e80bc3b0c686e4f1783c5e2eac28390469471165f1bd38b4c10db10deebd27550e9c23e7e6acda5a7bb1782770c55bde1d5550a86aafbdf75e8c719d91c23e218569bbbfbe384ccd4c617690043d1e4033e0b5022a206608e48e5cfdb4b2eed9587bad80955df264d2a8725a053b6c08599563d25c19bc7c31dd325f60ca89f3f73b69489d8e92b9333435d7897b134d783c79ad7e97a8b2e6dd28aaac7339abdb755d0a2edddfaeee9478d6c8f690c2300cc3367d277597fe71e1f57c9deb5ce77ab31cbab54bf7daa5fabbb22649d34ce5eedd1d0ac7a9063c238589f67abd9ee9ee461caabc985d6e49f7e613e2ab32ebdba182a96186503b72b7bbbbbbcbede5bd5d95ca346f149840cafaac38d6d8903c1e8fc7b3b9196dcee66c0e554541c55c20a3884be292b884c249e19442a12a4c4359925eefa81b09550addb38f6a90e4ca54aaea3ba972e01c39b744a5ca142a67d5252a55a650b6caba5763eda4c99c51e56817a05165686b20777f207797600532b2d6a34b9af7a7ba682adf5fa36798d649922c756252a5c7e01c6c07a404ba842a306da6ab321986e10aa6c8e1151687a7901c3ad2081a10866118e2d8926933ddde1260dac8059c748c624cd5349d910629c6c94d7e3acf18c1cd08c692e90c1ad88838724826541aaf48e1215f2c8960ccdc5b2801de4cd7a84c60fcb0042870da49400332267cd1936181caf22093b0a6f1e4e3783221e00d187c79038c698e6fb8219ba18d37da09a5044d1426ce14384060d68481630db3d432930253260d1b9c190302dc0abcc840b7031cdc8c81c60e767081db133ab91e11ed4e5684e28ca22c2a7d69c2e638a30ad9822a090063add8a8ee711447711447517cb1cee4daee99244fa7cd34d954e4e983cdd8c684b1434d1ecf55e8351769d4b1c53f6bd4fa2a0b0986b20dcdf6de528834e5a831eb1568ba55ea15c0b4994a638fc70dd2961bcc600b0acec018638cdba95c7bb5705be4c6663756fdde7b6fa501699a8991314fa85439d3a649923f3d68358d782431eedd2494b7aff7839a33671153a59231cdb2534908a0c6da6d1e8ea5d0cb01b1af3566339d501002848c918447848865fc64f46b22c79a1375285b91aacf732d63647e2a5a512a552f1c23df588d85150424f97e8d856e4b23b15bc5afa13ea94a616306380ed6d962c583e09609b8910ff0c20adc58208c4e952b1a6f604100aab670ae1bc8d86da8b23aab406cc6b8be6004b503185891d5ad752657868337ab47110093b19fa06487216e5b863276acf4c61176b25a6fe103641b8f5cc7f04c32afcf3c453aea3367575651e7793a499e6a20e5f207b91e5d4029440ab9746a72f174f26757fc4cbae83632e48284147d3cc3598736294ad9567d87d097dbd76080e1408ee5b5147a39aa08de6539caa6be04a60d88c703cad229eb098ed78c82f2950d2e5870b319e7b4d98ce3e3a3d9477700d306c4ab2d552039bc97a868fbcecd76def8caf35205725de533b7a6c0cc128da3cbf1bd7c5539aba5dae3c64777e3b32e87e0c837e73d6da3b366bdf3b69b754e5bb87adba540cedbf00b681ce79fd0b8cd285bd2b861da4ce32c1ac772250d2f376543e33117f0e5181fca1ee47a9486d1116bb3ed072a3632e378af7972e3a3df388ea36edec6697c4ca3288ffebaa33470d906c403eab50319755a8fbee0027404b4c5888edf1c24a3df20c9e12abf719c9cd3488e53755ebff1eb382ad761392e4fd8f11cc7e3db6e5c75faac61de388edb382a4ce1fc7514aa9647747cf49c1cb7250a387ecf550eff550e57f9e839bfca71deb8ca55a7ad085e1efde6b415e1b39bf3b61c2ea3f25a16b179c767ad73faac618ee70ea1cfc66b8964c755e7931dcf399fbcef7077cedaa8e938e73bcb6bde86b3fb2d8fd0f8e85d1af913376a9ecee3e369c371e246fda2a0c3575e4b1474f8cadf86445e5d5b1ab979551eb1ddf8e8b5515b938c73b12d51b05dbf719b949b759cb629646af5bdf259df9c38a78dc7a5dcbc72db3da5dcd539e33c3eeb2e8d749ef1d5cf78ed74f4ebf7b4a178fe3a8fdf5f398f5f3f5f8acd2b2938afbc96444e5f996e98ab23396ecf95111a1f9dc6c7d376ca2a3fba402ff3c8f5e802569ea83cc6515d1a3921a1a92a8ff159d378cc91058239c65538a78d4ac61947bfb101f16e3ec7c7b7ed10fa703e085b1e31723de6b4a9fcda12499df58d799bcaafa3eee3380ac7c7cfe13737dea591d1739cb5d19bce376fbb71174e974690728e8f3938e71395d3bced4675c638cb6777f535c798d9f5361398592ef3b6227899e56429c4534b219b1d425f0ec2661ab7c934a7cfeef535b39ecc5082a85146af96acd38768a5b3c936a0dee83620de2fedec0c752aee54e914e38c421d7d9bcda8e3e070866ec234da289bbab53eb0f6689b0ac029001f9c1396dbc8ecc407283c44e9c17a1184104310518411474c4182ca2d0925961862a20927704f4011451529a6a0225785155758c1220b2d745b70d1852502e20647952367a5b3a383c7df9ca1c1516373c2a155a66eb0a1490d34cc20430c30bcc0c485252d28616105159220490185138e9860a40891214225d468791604a4030942820019e14796fef0112104107a7c7cd08387073b622ed44bc684ee4428ba3211884420caed2c1fdcc7f8cdb33cc7e3b8ea6f7cf5393ce755bef32bd7f91ce7f91dd7f13afecfe3fe3a7ce6dfcd771cdec64f5fe3e5e3e0ad3ff90d2d6ff237b80d9f721abe89d7f036b80c4f83cff035380c2f83c7f033389387c15ff8187cc9337117fe0557f24bbc8577c1577825cec2b7e0497e0557e159f0143e89237915fc844fc15178246ec29fe0471e052ff226b8913fe243be881379235ec20f71a127e2b42fc16b2fe4b3a779fe9a03fdcc833e3b090fe43a7c900779125cc8ebe0237c1007f2425cf623f8cf03f11f2ff3f47f5c84ffe13e9f3a082f8287f03eeee341f09e0fc17bbc0fffe07bdc83efe13cfe038fbd07bee379382aa0eba884cbd9ef814ea1190100020004200000e3160020200c0c068462591604719aa8f614800c59ae766c5898caa34910c4280c42c610638c010410008831608664883a0af8c533dda34588252028f4701dfd7f46fe33cd62e46fbb006eb15648ed2320748ebad76665ca8e0032e64b58e4d1e776e2af84324622a6f6a95c3a508c9c7831c4fa27f6d35e19abbdcfbfa6bf44611df52618109bb8691e3a5eb726d997b2acfadf19dfdc890f5a4556ceadeb45a878a858924d4aa530146828d394d96002b329a69c80bd66b467a6b6b0f26455ca4a40415f2d1f0551854e558e3b1df9eae8aa6699c8878e7fe6867770a9b90a5671031082bfba0fce3404cd68bf27f63f82ed055b46b74d6aa68615416c227e88b4e78673952548dcdd375d2e3389f1815d2e6b40b4b977f94369578121146652226ed52ab008d74ee334c71d96fe08f75820b43bfc20c209d6350e4376733b623e30e86bc49dfb61bc3d9f17f76ce21ed234008ab9376c8f889ab3c26749b377f625307a9fdd759100dfb0e058c7f4101ca30eab2247a534508b7d96a87dac465eeb270fd19e5b7c8a152ab61755307ed82338f1b8f41d69476025951b89315dcd0f1bd9b45f36f9ea50fc6f98dc2c114da1ba328bc62c52f34ed841a2e29e091f440687c2da04a64f50e51872330c0b853cf9e6674f279cac165f7b3a15dc0d2bcbac6cb4d27e8b129320611d411bf8efeaeba9e83353ab0b318e0e878d93fa9cd3ec603f59f81dee810a7a23daf565b6aec5b090da4e57dbb64b2c1144ff3ea1467bc8ac83f2e437df87b105d39b8edeed524461f680d3702a6265037ed6e8787d5abd761136eb6e16c0a93682a1921151be19e6189840c4eaf9d3e1e2b3cd9ac56b1435b72e414055dfe4d883c50e0325e7014cb12d738cfca779a61a007aba22dc6394d2b38c79c3e1fc6eb139203a2358e6f97a51c8fd90b7268a5d4b98e14f012a01a72cd700cedfcfce1bbe47fc420e7777df814d057737939ec8a5eb056603971d8f565830d0f8d08e5c03efe4df40e41bd34f349bcabbe7fcb2824506bb7510152d776de7fa0cdfb28f8d854bc1507121def452e3b83793878d08585ffbcfd7f40c6be01e966c08295e31e953da5d864e6d6c4d8100444caee3ccda26c4fbfda2fdba8c138bd16eb79c26939b9c725bcc7c7bc74c33c0b8300420b812e8162c581553484c71713d5b5d9bbdc47d5fb44571385cabb44798eff6d17b8ca9d916a68f0897e7d5a48c48b3a908a1ff8fac9f57301584bed1a01943c7f58f5eeb6c27f82ea6da12332052031324a6f1ff4e5dd9e1d535115658dc60ef6a22fe2cb56d6f73f8c79eb2cc57a2ff638718a75fafa92f73c1045e20c25447350c00a23a5b0079ecc8cc6032400a99d8b662f0bd87ba35d45e272d16b59dc79fb47bd00d51d50b3a1395c99588121b2bcaacb017a92df865639d12c5a34edb7fe248da6e785d56394ee11c47b90d47fb03a318fd11bafa3f624127b8b6534347a33baeffd7fa9f481ed5d1e219402adb697a114bb443359a013c239dfd1de14658476377cc34982ac8234f6750f408316073421b62358eccac67cc67701bfa24e5961df2ec69a6227bac59af9a5b29480c84bc7be682cb58442bc6c37a7999aad99e2077493015c2aacc5c79ae54563146550ea3df4fb9066539cc6cba3bb4a520fc6d0b375fd94b1f33e652e6196e041ef62f740f868c68512357a734c3aa35e24de245b6aee5af0d240d01faffcd7ac0bb490146e872d3550e914ffd6206dcd5c32ac4227b643def5af84d5bf277e3c118256ecb0d26c32f26c05d05ac429c62a55c2742fa44d9e7bf984452fdcfa7994a9a9d848f92e7d5401e7c57b241f3ccd7ebb0cd1bbf255c0e30e712c9ad00720189578b8779edc66a0f8bbda9dc26c21eec39530155862f11c504eecf42b5f58b5462d89934cb5322a52f82b3f4f1d4a391bf6041a5ffd6729375a200629508e81ca75aac78c6152b552dc41ed065b79084f5b4e768cae762b39c180f35a65b4ae23b76993e76a91e9d392535a99525d35c3ebbf8590cd84cbf69f56bf10235019cdcd7a40fce6bab58687e6b79b890cfd6016bfec9f575f0c0b616f93381c70cdb138d5a5e604f8390c27c318780eb4546b9d5c5a6c9f5d57db3d6bab7827257efa2e3debfbe692453e7485b0a83da8ccbd42d44c6836a7b09cabac88497fffefded47e04c7464812d61fac55412f6a8e394c3c51131a4fc29ece4b33a4a473ec809893a955ca655dbc8cfe48353717b251892a2e918048762261a318f86064b588e47e13ab936a535826a8b406a5e22075db72a87fb8f581f454c7723f75a5ea160f30f430416b67c7edece8208d4a1116a25c0c2442bf40b81399e60416e4e400273b4d716fe5e269168a0dbf5072c7a0718037b721c49f4942c82334e9381630f1e90b0153aa2cffcae445511c5bd098ec6f32556bbfcfe7ef5073874103b7ad325fc7406fc219d62cbb754383fdca4e74662ac06b90d2ce1333c093ed09cba08f77e42d474ae164f7734631e44ddd78c5229e25aaf870931553b78b2d52a6f788f73bba3973803af307c1d5068200c942d5ad65831b25a80b115657f4647a214f2d64b490f818824a2451c562493885b1bf03a96aac9a386fd0fba3a8fea1afd8d7fab265134f9417464ed2e1ec59ad1cfd276458371305bc3fe5c691366d0495724e03db7f61daf4c68731074cb6850bff7e2bd0b3bc1390e1ed66aae5043903f7962323c452f1ce63c0a4d8026878ab16d056f282a955bd578be9de434773f166276925b662a7d62daf0bc6134a63049382b074adeab0059bba20ae1348bac0a5753f0a436148be6e1c63d205a07111636e72bc5df53816d86803f6588306a514cffe14e095d7352e32681b161c2c0b6c6c462dab253bdd1f3f77c0be2946672fa5ac431f674e6922383ebb6a69c9c833584830cf12c88bec88112edee8a0624762590312655cc0fc3435117ac76e27d51123904779639be9b8f568821803d6cbba173dd3a249751add3fdb1d92d5668eb3eaf15b707e1022d4050f288698232136c85144bffbc9eb1004a83a0918449731b8a90fd60e4127c10a40f5de5904f0dfe88fede855fd74d63f39456392f87dd6cbbfddce843cdda6aed4095bd7545310107b2a78a4deea38f721ec3efc5fe8d03d20412e7a4fa8976d02082f6d97f5c608374ecf79b413cf39f6cc64a737b417ecc49e7b19bb1ee45ab5cbacdc877ed172d4890af276eb68ebb52bbd5167def5e6bb30164e6c030dfc9a29c157b373f8802205518d043e919938e01e9892493117d87b4b9f770091c7771ba365c29a3196bb535a2628f363de9b369126b07b5c2a96a9305103eb1633fc4ac73c5836df6920d51c725ce917e56a5f4d2a5cd43b4255fc2766d4ba335cbfba4f05cb2e29f6a09ff6bf3dac357c5830f058c8942ea382479ea1bb63a670b0e1eb950f59fdd60f609985cbb3557515ea8125ed1c8f95c91b6de42f80e55a2257bb2de4ce55ab267ce966c127cfb0af1b7703b605df1ad8b50f5f6c62f7e64846aa2af068a6eeeabd30a3cfd86ce86ddf0815125a6a42b429521846241fbe354135a6182746334b1a25b314f9396bba245d79f3a97e5a8afa2172f1a03d425e9d4badcdaa28c6cdf9c1d8ad790336064addac17c8426c5b5edf882daa71d32e10be9254560b6c9c5cde2d76a82fe15339b4bab4204291861b8c62dcc503ea93dd4dc2a4bf6a0841e8c776715eba5acc5369bf3f5e9f8775095419df8f0e2992036e5ed3f1eec49733038547319f52600d9b213e31e270115e1335079e4a01911ac1d2bfe0137b5a30f01c0379623eb44a08fb4143f80ada097fad928cfc28eac51802a4cb75e5dfab4902645d1a431597372ac38a7697ab2fbb1160f254945a27f3daaeecbf0b9d031204b314929a4bfa5ab7b44664f4286e81e5d7423ff27b106ae9e8c0092a93e22d71fd12826bac083deee4841bc7f455907757c47e7fc9b1a642d18a7bba4897c99df0995b7f600db4ed0c3aac3fe903d46a7981e81a19e8d089e4084cde9cc1db45d81af63e84f5acb32f9157448501338bd18b32cfe13208813ecb50563cebdc35e9822990d54ce2f4699961267df8566e8d0c239dc8e1ba61a67be68eb6689387f2de93d762aa0774750cee1db790657d56986af8c11a755c316bae44491949b72c2e7d4cce589b3aa91460f7b8285fe982bf103fa7d36eeb40c4c24cba8e1e147965b8678f0a34ff1d9b983f8e9d4d52f5775611e3bc301b7243d65884fff54a780d18e2c6f6e0f34519bfa064fac98322f276ceb62e7ac2d468044ef947faeeb92acecc3a4032813eac183c89a391b2c5e15361b347ec7b21dabb61444c215dd48a3a0ffa4967bc3ec03c68d834950e39ffb254dac3dcfbd2663e241c0706777211e8e986fcbd50f19070a1188c6aba52aa4b7f54224a2c5ecf7df8d6bd222bc82a332fb8a4878b91f9c285860a8a6c88a876a36884a70b32c89fe8ec45faa6a480ac005166fd5bfaa929cf88f36e2581ed4458452a2a440f2ace19488ae4868f1487be91cd7068c05d82915a81198cfd9860e0183025a06674f45f9d303d6fbe455095bd039df1bd2746583d5500023cd4cad00da0528af7ccc57ecf89892fc4e8e5ebea8d39c17403e049d9f3ea05f4c9d5202a09e96117ee17bc9418765dc1d1ff3c56042edd20bcfbf90486ad78423a3a0bfbc36eb3256d0226d4eeb7e5fa5b498c35f84836273555cf2cb588523fb744b25e7235858f39c9769b1cee5a055c1aeff6f1b77c6e83aca3c9ab835658736577a0ee264dea3c14d445e38474d9e146a4f4af0448238d996cf762d0e491e39b857fef315a728a1517b9916ecd0df03560e11f25fcfd84d65fa8e621802d46492809367105ed6ec90380c8cda4ad7f616c9d923d911639456feb551a213d4d45417410a023a4790fb7cca23fdefe574583168742d33fa975be095b7161deea2acd2abcc5119beb5282b07998c85e961216868126ed6dc2e94f4e7dd2a8ded6c7cc3a5db833a5ac447b611581c6d77eff5c39d54cbfee8190209a72c5c3419594719262f156b164588b0d7c7651202a69768b09b34588a32a9eccbe40d20dffc7c209b586b78619b536063146dc61239b69dc39e19b8a83d8e3c1f82b13fabf78210803ffd1a23592a1b6fabc5bb5411f2fbc6227985113c653ece97c93a8b6970f2a2d18b68478f8a46731439a79b5e2ba0a380090295fb8deda593056a554f2915bc32e2c5ca7b2fa88ea3f90ef1fd05b78c1ee5476ef677f632f7c2c48cc50b1b81190343afbc040aab88057fd79dfc58138f1a99909542f7699da788f858716880a996aae432a685f4c3857f78503051330b25f2b767601031e6d677eff8ab8aef271c2862fa92115979c5c02efdf4f9653dff4c7d9961e0e308bcbccae9758ea3ebcdaf09b76b05a3475579cb0600d2e3fc859f3ee9ba3c576af3f6822e812abdb012583b7629bf77f5128be2e03192f8ea6e680523865c11f634544269168fcd1cc39e09e003ec9001609335656a84e1b5633efb7532a766d6a73649f14f20fb1e6b7cf482cd759bde412fde50335add4623fd1629de45005ffa7e3a7b27d919faa8db39060b2c3d90bebdbfa2e29944311a0cfc36e34fbab17712575d5c7812b6f0869074fed006e53d149d12e57e77174d4ce9f66a712ec3171eb4854451417a4c98cfb9f7e2ee4d9c7798392cdc3416042f403a528ead350cd6b80d54aa152264591eb49cb697e3e64ca379d900f43feea10a97dfc7c1c9ecde08421b410b390407323ecb68a61f87be787e1b96ae45a1eedc5622d79c7e1277f449bf42abb9bb6d0e1472849d9ceb2b1bbf17d0669fd30d16dcc8a2a30ce090b00e11f9628798dcd7d398a6e7d77d5b49a6ad58076319eaa6507e3e1b9a02ea6a1b58a652373ca30748bedd8597acf7f198895b68e22a4b6a793258487a32fa1b019d51ca0f834e73343cbf472dda36b366d812c3e27647ccfa75b28c82901431c70951d0edab67bc817c1e44d660331ddb8544c8ef4b7c63cc8c2ff753b87748f8de1f430c00e5627babe7dac254a72c779cb6a85f089adbd4467da7ac861d099e10a4d9b7790a718d64bf7534dc71a6eadb217450492d4ee431ad099d0428ea6106e84c8476ff04031f47aef1113487f675896edfbf4f89a00173ef8aea1858c3782b5a9b96955a89dd9715a4c9a2f883ffcb16dad875d6cfb68d1f66930541e599c41b1eea1c0459074e7abede80a08158b984086e458c82849892f3f18f4c0db8cbe2934e3a75c24db8270451edace1ce538123167c86cf1c3fa078d07e226e0046fcff60f363f8b09a6379fb64ee2fc0e42d12c0e896dc9a124fa97fc28a1cf0e304bd8e60e2d6f179094aeb3169879ee39e849468501ccb15a64dcabe8ee1948bb63afa73560e57084640e6aa334db11e82fb404c67878fd0acb96c859c7a9e2a696d1b3fb845cc9888f0516094874f704346cd64800aae6710d91517389fd8327aaf24e8ed537bfb67eaedb9b0245a0265668e7f41ac73e8d5e13fb483a97b956e0ab5e4134459a41ab892e9050ceb7ee31e9f8a2eba32f24238701403ce7930a3a7400f5560ed9c9d0d8f7c6e811ba94d8f68d3b1711381b15da8852bd8cd57815b37f7e5f73ed072f2dba8d8b38e42a66134017a72e8ac1e4abb7b74ffa6a21d60c22cfea2cc703bd2fa848f3a6c42fdffc2f8666ee1950f16d45a5f8649f61b7c9cf402f792eb5d3c3350e29b055829264f347272f110b8ff1022b91a9704f0a35432aeab3f11daf8b814c23d63c58bac0fe28e818005a95b72198222eff7f3a5acd1b8440fe9a84745299925076c747fbaad71e3bd0ad8efa88138368f68453c5466145f658fce07afa737c0e704049a8f5cfc50fbfb2537e638a345ae0e6434e0ed1a06f3fba06ac47a2ab5934629459ecba22be07bf70dbdf43bbabf189c30bfd9546f7329a829b3ceed4851012e842b15ef4ed5d1efa65ca12dfe04bf76efff71083e179c04789fd930d332746ff4e224fff882dcb9be65e6887de3ef1928585811fe76e63a81063d5db02a1f2ce07e4b4ddafe5dfc31a71084921331b8fcc185e99061ea5f9b46a69db48124fa8712ad7c0b10541402f4458c424fea2c0641a3e0f66b211ad1d6e428fad92de1641705702530c285e096fdc16fcb6c59292a07769530a807bb0591d417b88a0cb583eca20ad4c7ba4ae4e2c15c290deac06e2504fd44ae2053e5015f29827651ab50a1fa30578b9938c06f3c9290fa7ae5963ed33f04aab3a0efa03605115e4385be7f5fc4446fb3431a0ee395229a51ad650ec719080d6106e5223a06e410e1881f344707d3b941a4d9a1c1113168f0b8a058f694001a111ce4032de1c06c3210020b40cb04ce8140231a300f0584cd01a04280e304a021fe9bd93f19f833970bf51bd442a259b4c4f4ac9708758b0950f152e2040eeaabcb65b3032436f65f6dabae37ebfb2e6f169bebbd3ac3555f7d1ae7d489b2fe90cb1fa7132deac4547622bc3b01bd3cab227d10fca6bdcd206ee252102e224b48f2c4ca788e4b3c1d0b4fece0394ad7093982815b50497f91a9c9507bc02eaa407dd42854aa3ec0d4ca241e6a165ad057e00a3ad51eb2b522681fb48a687612aa8719a54ad407985a99c443cd42cbe8137d7cc9299828a61bb362a73058f972a268b7f4bd89258a86b39ba4fe07c37c95a01397ce4abfc3f41e5071384df8f44600614666755dae902cb1000f1e2f43a2d3bb240d6dc75d908cfd64367b96e959edea281c56fc517a77bf150f40bdcb04e04819163d620f23ec836c39d51df765634a157d614e569e21c9077969e088081f710f1f5317236cc32cae85f1afb308a54ce54c9316b415ab96c5628b8c34eb76072c0d43a5842890fcc32e07d480b46f95e3b630d275b4c29450ce69d2202b01c6322ce21a1c53ff1f9b05f0059c7f99f5a81a9465caaafdc1dd24022d717fbe4b237c24aa9042ae04da8cbe2cc99b1675bd11070b6d2a228d1f6576212c27ba26405637544144942268e24392dd29ca85a089d3d335391050a3686278d062675272a764a284744d07e46428960ade44d891865c9130410aba250032fa81242f1775b211e748db43a471475912c284a2cb83ac5fa8e2445402344943923945cf10c49f9e5cc8914e8d6162bea08531294950229b10ef747c053218adadbdec0783189129d6588ba95dd48ad9b0e8cecac5a8e29914a583f29d535463a2704ace871475461411911b84e2e01f6aecf1483bb12387a26d7c204d34c9501930ee6e89305728578a3b9c446d12ea29e25220d1c083026f38c38c68baa01a2adc2d112521a89183033044de09d479e0ba0aa2f54d6cc5d32465e394d394b2d3b4c14c93e7eae04881779b69e4a431ddb846c199edb4a56c7a65d8d360993eb85232cd365939685c338f2931b63bac28bac69750badb7114eb1a0e9edbed863513626d30d609c9da6b211a2d901d605301111ab531056bc980719dcada21b2c6c0580f47acbd8635021eaec6e840bd98aba466b1a690fe34e30e81360fb34ea6230789f10729841662063194f1ef592fb585574aa90db1240604f1569404145740479d22aff88319ca0563ba175c7d4ff3ed15581ff96b956504a08da19a0c67914e836bb247ccbc4aabab8cd1665bc4e45e9688302cdb6d8d96d2267c19b3291b75c3c73324fda1d7f082fca2630597599b50a7fd1339b22ee9a05305111ad7d132d0dad74dfa4a1601533d11e2658fc1451eb6095cf69b59a02968294664b3c65bfeb59e577ba86afff4f6d128d835edfe430ad6a948722842d26f5d0d0545ff8522d22775f39bff8af70a3dfa9a535acd6c379fd069516629c283ae58b5c210cf3a3b6444b6de0a155e59e8e59fa0d9f36a7ff2c64368691ba1948dd541a69b85469bff506dd8049f7c97ef75722f0301751ae98434ee8174f973ce2151525d4326fbf143165326c3495314d826a3147a2bd96ca1243526a798ce4a6d54c425aa8609bc5399048b5600889c4a07c5437c5125e2624d2545f540aeae26f141b3a6827c22a3d2a970905b5541e413bfa353600718014d4d64e94146ad66ea416f41b944ecf25d1063a5b961ef74156a6f84b99512fc50f7cc69ce203007374b56058bfd1aac50a27c66d7646c572b3aae803af11a95ca562084dbe527a0326ca0096edd3ba0a12114a0fc0bf929c7f4897deab524c6630775e80b69d91de273a5bcf627916517a4130ff21ab86f30237097e2f29154f3a6d78df4e1cc4bedb92b2db44a548501413d8b2419e525c051224cd43d70cebab280ec08eb6bd57c5658a462a676a4097b4a71162860012990bc0777f1c2dba2f8cb8a0602ea19a1f7ea777ad0b787b759945510037ffb318caeb5e9bc5eabac2224aaf0887d2042b75df8f094b20886f11c104504e1e400ec021f9cc053033a4e80b309b61c80361bc8fa030613b854078b63a8ac002adb30cd01a4ce10c11c2075e1e1191cdba1c92830b386a521289005899a80f00a876d6064108a5901d10c064882a01604bc01600bfc07810f05744980130a360fd07e818c3b6089c0253d5826503d0f146f9872004932440600fa1a1ee6e0240b8d6c60bcc3f215148621c91210a1e03009c65f41422c0d7917cc753426ec9a7c6996ae966c5d902c5d72d534557733a5a14435e7e96e34e968a526887441469a00519b83eec41fedeae9889ddb1847036d7a16cd75c868d92fed6cb9905634474a7b9b5c4d126d24d20220d7b843036e34a78cebb8d0da146d28718520b48743c32fdcfe049d3f68dc0b2e7a40e706f4f76f43fbf9753f4bf33dbdc3d4baf29d73376e45dff9da9e7dd7bd4d43ddb3ba2d33ebd86ec359f73b61bb4dba85d22cc07455e500130580b79fdb005efbc97b8f7ba1200cf9aa2efb98d416eeeab2895a405f5c30470bc45f7aa15331c1777f7bc06b3f79ef712f7ae649effde2058fd2e26085201a9e150747c9c9ba302e5e1144db956009133d3b30ecc12fa2390e7e19fe1a654aea3c3b09fba611a914b25c380b896d216fd57ee54f10163dcf930bf83427f572a0704f6f19d878a0151d61ebb19f7527462b524024841a64e02282c525c88d0093cb27b4781ed2fd1c1c335ecbb833d117f39bd7c367f15f55ba43093b26871fbdaa213ef749341df9aeb159ccb366e12c94141f91ab0f636bfc93055b4724a3064946b014c13bfe07d29efeedeb241b3cee505013c7bcb488c6b91b7a7ee3f3ad0c94d1186d1235b99d85210dc664a79919cf008741c537449c2d5a4c0b595cc010155b402657583f3144bcb51cf3b83d5ca7abd18d4ee2ee9fa2ab5be42053afcf78870988b05c9a235c3fb2e0d57f6f323ad26c00abc85c1aa6849365ed0f8fb96778fdaae4256511afff1272876bc3bd9ff8873c683b081a8f2c2c0906dddfbfbff1f6ceedad5b6d6ed8dcbd75c3d6d69dadb7376eefdd6a73cb60f3dc0bdbe4a83a59ab79dab2ffcf5a057f165cb92ee798a76416c1676d2b1b1018f501e555b51dac505e6b03532a77d9905878e8f84f7fb090904c62d85799963527ae3f07ad82b92b2a674ad8c3cdf54fcd5725f21637564631e3664bf8db383141fc017f75c5a794fe72cb48fa0f6c13bea241c727cb2666b834d1052e39b64c755e1495f46cd116ca172167ed03f166e40fda9eb12303643ae527de33dd54967724660019541e1f0e9a04248970aadc60fdc672d1d4b8d0f562d8af10e3bbeb481d2164f38d28d57630d237069f3174375c0fb3f1378a3b6cdf722676b7c6a1712499d9bbc8fc5f9b567d9088dc75ff7a941553302e1add2898e1da6430285a1a3138187cc79e0b3c9b28082d096e48e3f9eb17d2a55e812d88e90365232dd35100f22ca008b303dc67e448602d839e86d4b34155c06fc5a90a853426626e46e7b64e51f34b14a937a61fe198a40b6ba364fb1dbb2563c47d14a190dab318a252071c1aeee6733113ef879911ba26529c87aff14490db6542b3dd1b4a5432812b47c8af978395ac92122a40057afe2757d67f857183ce91dc10cce4239249600116e10ffa5e60890b9a630342d03f065f0195128b22137b597aef57d8b6a293d6569c3f75477fb18ef9466f77f43552f8fc6fef020baa7ff1b4b61a32356076dd495ae48ca46114d1fe7e043cd2b716bd4ebc7b1ddbb98ddf9ee8dd340309cfc4c5cda78b773bc8c68d04f78052bc8827a88b73d36db32eaf409f92f1c2bea30d16e2331a31a9ed85b1eeaca3f5351bd69433e444602f1b5e4398ce7e68a520f0492dc4a7f51acec0de2bb7fdd57c5b0c8ab08542c0af5cbd63f63965487710fed9c16736b345a9f49f3476c7f40c519d73414b13333cd03b66600d031e3f813556ba45dde6a09f8d7eb785d0957c0bf08b21f9a9c8b80db4218e2eeeb6a27f62425117ad6574b971e4948ee63c623c29f1f7e367be0d9d4718aea324831dcfbe7a3494b1e3829cdb07bef22d1d44d8873234d5da2c80b5132b3a01aa3772d3f19ed4178f5eaca2c202575fd34c7ce472eb99e1721495ae80be874a454a2482504284e040ac81c490e1eef640f7fa855c93389023a2a3145e60d4eca128068025ea315d4feebdce80b6d933a6bdb8e28e23c9c965931d0831c8ce165846b05f57f1e72b448753c25fa08baa6b518a9fec91eca62277ee405c07631f750397ae499f822e5fb7627d11e0ae56ed5e15406b488440a20388092e13beb05b5d4823f79a86f1865b44a3879c023ad1ee845445f02657a509353ccd888e44894ab7062fc87f3276f4a3fa3c3787fe9fd0088411414b131f5c8f085ac8a9a5c8c76274158164f55f1b68b48a7bf9bfbeb7ece620f5d9351c3ae52fb5c4dfae3db33409210df62e52611b2a68d48b2845c2759183ca8fdf9c8044a0112f2329ee8501770fdf8e9cb9680e501924a9941bc7e0d647d2434c39c5219659b58a73f5dd722364349b937d8fa09682e4d492daea4011b63642f6f25091b38b94ab99b6de0ae22cdbbe245d4668b32795cea3b8ce60dd878da283281af52917773414d057d7f3bcd159c7d3fe7af0a5bde2119000c0e6cf62f65af7d7c095ed596da37b93b22b396429ccc0871b5f82fc6991490225dc74532fb874cba102e4528cd22b600756ad9625efab3a600f23073d5355e3dc1a1cd39d183d47d8cf22e1ff387622a976cb6f38ebdfacd5525e229c932742d6e0a36463c8418108e7619c1837d9644251627a6e24e7c68b704adab6f395dbecb5d25aff3dcec20d94a40518bda6c701ca10ba3c8060ce27409fc68cfbde211de594b954f09b33a1f56f61d5007161c516e6701d96178939e86bd0155e2b98e9cdf7d4dddad166ad7fcceb86120630ee9c01d056bb7d4fc19f134a2918d339503a38105acd75225a1d5f98d4085cc0370c2114a5274a5da886873ea8682af507fda575d92d7bba6a6349f191c702ad0a3af4faff1513acb150d8eaa91e82048f63b44f3608415f56b4d3c781babd71f811c2ea3dd0d61d5fb5e53d9be1b12c806c231d20f8a461c9f374e10036a036093ba816d3c4a19a55526ccbcb25adb06332f368ef3e9dbc6cc65b126cffc2f29bc6a68416680b30bb6145c8a09cc1e157bb78347e74be5a713f876941b1f818e2fd8931dfdc48ab2a62a23ababb0d6345b735d16fec688ce9a90a222731ca3e3df051a1de0c57958ef96a52e67a14524da8bc40ec1f35dc55ecd99477b7ae66c72183c0e05ba2469b694b0f80d436311e9372db0180a73774b26125e4772529d6a214af658cb6b531174a70069306547e575aa818d9a02802137eb78c0213b306ea395e21e3d0eddf24f8da0b86973e042d16951773d4a0ca6147905da023a6090ee5c26cc53282a26a9be8c5168099bc8026347d2a3aed78d605953abfc479f478343c93953e77d8204abf8b7cdc5724e2a027844004de6d9caa06928720239934c33693c8dc7db3c4786412b08df4cf24b66bc04d7b5c091405a65f64a441a3013e16d50d4d0e26764eba99be204cb354fb897c2cf248ed88d148e6425898975b4f8e3b347748b0e077b3f3571b78aaefe615c0ee566b92136aa44668e1f8c7b18aeb96492b4370ec625b2dd6ebdfd485ba9879a509f1a6d14058b090e1a026ce21cac340599bfd90fc74ef376b201ae61d87af4004618c48f893aa40508f25776429161607bad40ed683430c70251f0bb69f98e4c8016c446416dcfd3c32b71ee91ca2c69f95b43fe4fa43a4ca17b05e90f1cf0e53246d00bd4a55892470397cc506b835c1d61b5c6b8b1abd5ea467d6fe2dfdd4b5169408cf0244df55fbcbf430a17c6a3a52bd998298dc029e1dce645848284a7e80815f07b4915acd043efa201e1c681c0dbb0b72f59523ec7cebcbc3c061a9e5b6c43cf38cf4866a64a22fc26027c696e49aaba230768439abfd8443348a75919c6d0f8bd3d5cb058d2c2a9276a017dbe4647b4eb07ac8b95f0946de6bebaf9376f4e325b164bd84ba4c89fe2c95eeb9ecb14c51502a934f3e512e56090b7f8cc6a0f16b28715c74ab274c73c415e508c32e5fc0cff7042a03c91a233a59d7159cb062ad05f22fa918d8720c2a847d0a535eb950fbf21004b986f264db021def6d3046644f08954e649a336ea465928e2437b333b4c8ce9c11f750c8e5f99519006dfe6a8bcc0924fa60b24c91fe6fe3b87c5a08870cc713c3493407cab483516de188da2900be01e672da2f058c1d11abe0e3f8cad7d44e3000976d38a6140c4bbaf33520c3c0e393be06783392b20fb6d7e7d94e5579aeddd216f26f4b0c4811a9c339b8977cc21f3e928bb74841b40638153a7acccc48c2a8ec5100564ec3f6ac83a8faa113230bac6c31066b1ca1bc9cfd99482857607acbdbbfec5c93615ea33bd64fed3ff4abf31892019a7bff79d30f2c451afa94fadc2d7f4e3e8671f498188f0d4821c50cf466ea686bfd1dad111741c4e7d8455b24ab8061a6c9ab86a269ae8d920f8124b8dd8d89106eb7478d3abec16e2443a9dc6f4a8bf0ce7771973bc2462f1e0aad72268141947054036691dc284bd206e1e4b9a9259f3c31d1d81bb96b079ebd21735b49953b99307d552fa5d42262c4615d825f54190aa37a68d281fe5586c75ae492419b496584e0e330f0aef1a3c8d57e856ae88e64f1576cd9d8db7f60e25e4ec24bfbd7e2acd89aaaabb06d20b19176bc2d92cd2e18691a57628e4a5f209550a9571a140bbe37c1260ea944197b77bf27288468938aac0cb7cb9be43525af2b4e8f99573fbc91700b5d4e4244f453b4f4b730cd49a5f4e8ae07bc361a72e0db0edc7783c49b3e3e2e64b28793ecabeaf9b9a650b2ec21710cb6b859cadd782a495cdb6212415e4f848122788e819129820a5d390e13719cfdb62c921abcf9f731e3c13d7b58ee18bdfda984cb360bf51a3fc46233856ec4d5165f090f7736d65cae44a2133c33b2dc04ee39f2d304c38c30d5a829327d4087b4a6a2bdcd88dda2c63f556afe3a71f112a2acbc20cbf748f6da826cc50f59f77fc7635dc1d99a3232d105737c13531c9d728119ac4ee9d7cd683a89d5e428d1c89e1e19bd8e9aeb321c74c033aac247807834b7b4a40e27fe5f4c1c12febe03914e22b9984ff17edb236cec6aaa5f4e549fa4ee2b0737168d89e9587f3c00ad5de7108142c017b6abf058ee95958da3b7e36721c1e355b40e2fe9b2e8596d41d67dcaa53790ebbf78de66288328b2f3159f70a280c279a79ca573e15c129cd353b210bff2b0e141bccd94d5fb741183ccd461f4946a6ea74ff7ef38d5b36dacb3d6b93bc0ecd21889fdfec90ff4986df7e4a6d5b77cac0d391994657a857e99b7270fce3d2c25273a46a1d9d756b2b959aad0dcf0ed9868f29b9ec9d30a8c6808bb846cf9413d1600c41506b935aedde0bcb6cb1871463f4369d978fca18585a3a72a3a90e2ab60674e2dd353e05057babb6e9933f1ad625c6408eacdff554ded35e579dbde9a5e0b495ca70d344c46913a644eebd6d383d4ceb50c98e1c2be7e13319217961496b50a726353a7186d7b7dbfcaa9e526af1de878b99f41029c89b80d43b7f0d679d142a3ff39b7100810636d288cb750a425a7d64b1f2db8fa0728dfbb05b21e74514c636a4f6173eb436f645d004c578295abba4f60611d6b8ccd9305b4fe11e791c65562646f3896f35c9d4a1c055bcc24a25e297f1f7b514fb6b4936639cf376e2974a9e58a02e17392739ad97beed76289bf3767f8d9d3f333a46b090f8f941e0ae9543e1355e4d93edcb64fb802609c3789f24c198492dae7bc436d14d048175717cf98f21c320a0d39de6de6b87ed160113ca05d1e7f1ca9d0228a5ecfe3fc02166fcc8aa4e2fbd36758379631019410cfa581cf68e327b756099551bfeca6d9c4ce4843f2800448c3aec58873a573437cc89ba1269c534af995ac0186da331bb0581ae498a91f59c565c85299fd40a5a2b7c213e9307a320a51fe192455d5376a4c90c579ea62b849e68f688430b41af712cce30852fb7d060f3122cd83c38d04d9ce27ca8603474a86c7774928d2a96d22c8a6849339e7df0328fa12212ae2ec27dbb49bfdf3cd7aac0173a1ef3c250837da39a53de66aa5c6fb6ad00f5f612caf37b8a195452e67fd03fa37a76eefbb4599e2d77331668d0e35540890b2be78302de16068e5241e07d1e33fbfe39965e4f53e72e863d848e31dce7ceaf7a26853475ad13a170f1417090ecbc4152b912720bf5d32a823186dd618f5303074e2f40e7ac59c5832337afe20b2ef46d8633420624ae7b363d741d8870011905051093fa68614a2464c7098cf4a8111cc7d8330c7a1b423ca539861fd389fb9dcd4adb57b800f090b0c592eb085552a69a22f9465437c06ff6ef7c0f9266d4993aa5f38d9de8a2cbe2513f8d51400d501fa19532901e8ab082e2cc4c99b57884dc40007b2e7e6ab2b8a18ad2307e70bae09d8240412be8af4b4dcab72302338247d915c8e00f4a5762a0a06a63057a50f5d8558b01aa55fbb76115679b71061133c6a35e101d22554e0c0d444e434dd6375e84536b13cba52fb972f91bc6c8bca5a443fcd378154fee325351f429827c584923fb58e19e24c9bdb5e23f11913a627d7f8dd0dd745fa821487f2aaee861bff3d53f4b31a3de2b4d3996c4de98611cf6cf34c7943e3068192e4546090b365ad2e2b725f4b8ac05216410d180d0eedcb5a1218d424c4d92b04a6b15c842df4494976874c89dfd2db4cdc7a22942e70a9f8b9713893b23904ced07bc240b8b873521f6eb26ce3e1e210627dba353f2000beb976c180678771a6609395478da7ed6313eaf8e8360dbd823ddc5186e3f690399d0610fe4b6055faa0cba1e2018c5b8833e2812c17120069eada3827f903f1eebc08e4c763c439a63cf4fd800a654bfb4cd5fe40318687ee738b44d3955493282e8149dd80eafc7277f020026020b4d231f87e8567001a71663d2f23ce2d8b5e15ff96ef73c4c2fa8788ef0b940751411aaa43662cb94f27fefa9c6b602d7732211a8d9d4eb416a413d640328d5777cd241dad2e9996e204529546164510b1207f22b23534652e489ff6facbb10fac92f840c44bb7284be98652fb0a2a5fd9a109e9bd18d900f58c68eda36dae645c9f0be0be4bf3859ef64550ac6d072c3fa0ff35dcc33250e85b74e5526eaa7741f386a0354e9f2b94139fdbfe1ae7533849761f3baf263c52d802de1eb44059a4c7cf5f69fd8c524aabe1622f5b5042b22544ea14dc36f8528bd9253610c87bdefef3d99338d44a3cf68cb5fc5aa06c01ffd60b4e75dc06d3293c2a6dd8158d4da31542d90ca683139dad1a0dbbbb736d3947633dfe93c0930ccbcd800ded024854f04b0a782d1d755fe133c79951771b0c7052acfe1b8b90971c0b0bc1ac6cda3011bd4f72cf80ac575b7c6028408763735a201918611143204286380742791345ad19b6c078905acc90615587024dad1939c1e0da905a115b09ed841868980585aefb096688fd47afb3424a125afd0c3b1c2b769b358fcd4a7ae6b4e43893572f557a67e290ca09116cbade1a04a0f52105477cf5e53b3921050aabc7aaa79a84c1762d55072ede7ed51114684d9555e2d649a062f7408b4ba978482f32892effc24921100fd2aff3d7c0707221552e8ba0ab72e6451945c39ee467952e5dd8bffbe0df33d70774bfb94691304adb8b1d91d149a3d867482311e88f7639103362467cdffdc277a7c55d5c1376c6f515687ab552463c37de7290f36f246dbc7b77689fd2860088eb83e8cab4fece7d878b693470240c79ff45473214ed3590929a9931f104836215b47a3f8d1959254d13a78cf72abcb0428b141d0deed4004b3cc71859604dc0ee7b3a56817c23860e7126bfc71d1a1bd3f1c33793b62993283e0aba47b44cc8579388a4866d20200665ce9b60026935d150a8b287ea975df276a19621739e8c4f03053c59d8991743642ecae272eab2a5310b8a52ff7700695e34875727e0e495dad3ca5a2a7e93afd3ca70b00f5bbf3f87083c1eb03c878b677f4debd421fb0e83cf76b48ddc910e70c5519745ca6cc6accc6b89ecf0d9c6ca83f566b6a112b0c66a2d5f72ffa1b43375b7ad0f263b88edfadc848f84f2db505259784ca4cde6735dc03fc88b0359608cda697ab4072b52111b20018bd94a62ab1b490a1419bbdf42a6e099d8977f6fe9ed98ec98a464a00e547d9c6a371319a41b538051fd1875175d598f4154bb9560c6d99249926fdfd4f23c80c11fbc1ee8dd1f36a4784d33386a405b1ff43dadb54efb5400b32615819284e4aad6097cdcc4086f981b5e7449b25ba055faf00b8aeb8d3b03391b273f1c18a7c6fd689ab9417c8698ada61389e5f2d3ba8e67e6236ac5899d10bd02e6393594e21ea8995699b06ed6956745a2103e03f407b1c65acfe17b468ac9b071bdc007a3bfb0e6a11b439a45adacc1f5206d642fe57d8900912c40fc9063ab1834bc32bb3960e0c59d21c303764d44e3e2fefde563e4c9e90833d725d795313cb434aee3988a7f261b430b43626db807eea8fbde06b74cc9b1a28c71e6d7351ca8d1df888dbcead0f30d12599edfc32a88fc9617f63c3af436605a83822c224e8f1617b6a59388a9cd216504103f69f293ba3a8e4158625189596fa573b0f0db8a2e924340b0d49ab21df196197ab462d3ace340355fc73fd661af5f7341019a13f22ee91212399d9a16249971c323e9f2f4a0e9836706b1850ba467cbba1eebdfd654564482cbb875b8cc4929f6d77747ce9be48371047c34aa5c134dbaa0d3779159de43c876eaa3ab7018081deeea8ec02fbd56fc453fd1e2b707aa1f53f9d6cf6de17c4857abb25249eec4a0e788d0bb6e845b8871e3e8c70d6c6d1b20b11547273af0b36f14c7fc071da6576e35a5369e1e47404897fc4dd2cb502f0c11309d94d07c99613cf5b7a4e45310907018c4d65b342a1e1257453231f21a388b82381329d0034abcce6f1e61ae06252f3b90e3916eda6fa5a85b4885026a5010cf7316a961ef404fb988620467a1424670f84b624206018403ac6cdf62e3817595205ba6cc55662be65b0dfe32e851e439a49564ab8d44c4c8cdba16187aa15b1b69be120114c65c7bc1762be265df548988a9071747544df3186cb541bc6e1688e88b2a1141d20bee962f3e907879e4d7b401b9d20d6260035422167ffe50bab7ae126aad83fe8fa5083075844ce187d51c25e232d15f4dde7d04bed9714a8057ef2ef4859aa569843754f812b45137e17e0f8656857a28b45648157911a43e08aeb8437c01fb04b587883d25407f0b37f8375549bbbf5849660352962acd01dd345448a00fc4b44b8a1d68d76560e932f84ee3c17d19acb445d9010490a8454c81570785f735031d80ee1b0fac54079d8f4e73d0e880fa5307f1f34233d1b083887640e690c3797dd9df24bea8e72325622bb75be381f95f4eed8bcc969ec610e671205432a9704d003c5f03771713bd71d9d1cd5d4e10d8857450232bd4749a1cdd3432368a61a8ab9dcc03f8a6279fd00532c667e0a490616840937789e83ab6bfbbee43aeca11e991495491e17abb572375b8e98d2092e3c41340b6f44432a816d42e1f7303ede4817f042d3dcfd05382f4a8e75f060466c3f96ad7d77543fe71a774f9354439f1d5ee100cc9a98dda7867e028eed614d687b5489662ea7773e0247e2e556f15b501e1a38c2c8b419bccc358aa541393c29f2c2edf42a5a40488dc0c64c227509e2667ae1028a5193f30d3ec0833ab45e43ce7412e926b6584a005d1d21dedeaf1c3d413b75e9a7137185be258362e55ca5048881c9f3a7683e11b924133cf468925cdc0c28e7a7c4f4d090e46f7a4e3e256acd689f959c146cb99ef5831f72fc4ae8e25c5e1aa4db12f7b2130450552eac44a9e0c0093fdde2182d6445f380dd3ac1a7231da04d4b1816c987a9ab820277703476348da53dd08e0887319f711dc552caff8b8f3f060c055a402e407607ed03606e7bf461c6b570a60bf40948ba4bb7a44449d955b041f9340c3717e5d7d5d7ea2b12af16268e11b5e6a5ad51db6cc5f2a61acfd9065ea1f0264b6935d30c6b69722f8fb93109737f83242524f725c05b0513ed3eb4b4d1efe3081e426d274b62e5cea37cc164e2ec46fa62cd9b2f84e64c5ff1fef4dbb5dc35a27c35a39bb87c186a89ec0c42e47350e9dbdcde049cf3db8fae93289cbb56200c847d0e791cd5908a2d06d9fafe7d7ae1cefd3d54c3ffd17ea91371b67f378591df6d1b8abcf54cceb92f7b41df59266f4f919bf2143f876bdefc34fc78e66b39c934fe00ccc7ab1ae9404713f7aba840ece240eed159fa64cedb76213e3ef5edf65e35de512f61c746d05a8005b3eb61d333c196686d26c82337fd63033f4dcde2d0c710ed6e4a625829f295749d35e3c23d8dcb0c77b35ba6dd0ffa202f5317ab97f0a1b5df0a2226fbc399aa9a0bf46b95f9dc06403f511ab176f9ce4889de3461aa702a2d19f2489798fadc4ebaef01a6d488b4986bdc74bd7fda124d2bb0963fea47a460fd0dd4a58b772768fb2dcec032ebf8ef93dbed160e9b35834efaedb0f9a6aa4d1bea58cc5ef659087b33a68d223056c0e84f9a17fd56e996c7e87889c936020c80239ab86ae9447cae6aa9688ace516325e84dead915b98a8f15b357a8cad20e72279eb005af26562b8a027535d97d1bf013b5d4af552f667586e4344d355f76380a028acd08f51fad1995c71e7882c71ac01df744fc4b702428119dcd09db906caa3d9adf02a324bb6b0b63e99d4271ec5980bfba68867065eba32ae06241323afd217811a774ada887b9b822700916e1530df53626bfe84a8ad41b7e6c3ff40eb16b2bf8fb4ceca00fee9deb35343643bc21fe71fe8fe7dc8431284cad82dba817665b6d35c2c33bde8247609b0322dcdaae8e6b1d804c7b12b6a8f841e65dfc1d9ab046073c9953a6b97ed32ec1db415ad86797207e9b93c979c02aaacba2a3bbab249dbc1800e355a1e99dafcc439d38e235ee95b5aba3035aae5aa56b7b065f8821fb2c870379378e2914580ba60a28b84c7570d036c682643d32d0c92e1550e40a54529bbc55f6b04dc468cee2f20d9b40c40e02fccdd90328eade4dee64de4a99e0ea2deb8d6294ce0d490423fa0af32ed7ed7f4a2f68b7bb2962783e30ec67ff73e334160b812e65a1a7e4d611150b690b8b08ecd14f3ccb602d73c0156f2bcf619f0fed018df011215d416b202f838da6687b74445a8371d3b4d287b98f0b00a7a2a728d0294d2d2510b06d37bdce879963b4131e0f393721a72438d7b9cf0708d016944c35a5ecfc5482ef51100e3c14f000aea92a4f2c181d4e97f0ae9924054bafbbce4f0a350cead08e36348619126a6cc2b1247a4fdf84c9acd0f281bf38133607667f9dddc10327d62d898719c2731212ff53f93200d8a936b5fc3a2820088b7cef8471e99bd00e0e006a51217d04652cf25961c31f1915968ae88aef44ce160b9313bd990f11009904e9efe1b1d48893e46b6766e1b1b4980fa0e80cd40c5fc01dad9f7b0a215c94078464f69a23e0f39a493cb62156767d79bb55aaf38488ce49358a2f518465756cd700ea3039481cf4053bbb762cbab09b2a202e9efd3ae8039c759a33b726df5363d63f760c39b856ccb70171d439393e177f400b0c9afe1110e6e263bdfdf36e0285ebd63d5d16d38afa0e527fb425b5d36d38915a9ce0aed1f6376229b3830cdc1bd5bb07e43ca5af82b4b32bd46ba79066cbb022ad6a4d17cc3d51f16eb75a25daed55f0154d4d037a4fa0aa748d95d31343bfce71318a933fd8cd6834c48ca3a9527130ac205093ffdc3e86b04562e743f0f8b2f1d24a823f8913602f1393620baf51aeb2de3134fecc46a8ecd3ee067ac4fe6e04c4f9396e5c72ccb162cd45978d04fb7344462bab4d70da2e1e6b224d94f65bfc0b2ad403c6994738c43112da60c9ee15c16012bd4c10891cc05325381d7accf3f001a4425d79afd298907af24b005ead6f994f7ebc2b57409c5e15dba2ae58537239896f31710f0ca62ee2974a20fbc82e6c42d98fa92dc318b0558a4079487d3df067ac7625289c12455a7aa97f35e4c1e8b7c5721b3edd4548b2af079e1f1b50680aa322de550203ee4087fda5159e829108080aff8cb065928e97de2c13a00aaddf75812046aec819e3a2c7f2844c723e9544c88498ce2556ca6c4f0ec279f986ec4bb05e8715ef6b43d3f4058a5a26b09f811f2ed2f6004b4b98cf3c43e4a9c1d15ab27b5841aa6cf4e8def68a36210903b91a887a8d8b78c1b8b94475cdcf46acdcbc94f7cd7dc54cceed44e5d9a3d45a62b7ee983db16baa8ad2c4b4f1711d282c7848da815874bd08082ef849ebe17763f468b166147695d162bd05287a9e33a44b8cc29222125349c05fc57a2d326e0476bbba250315e655b08f0011d0c383614d1dbac4cb7be9350550c2462c1dbdb0ba6aaf0135655203dab8aa3fa8da93171028f84266d23a5697abd5005a09f19bc07839a0745c5b42e1b0bc1f0dbaddf49e37f6febefb4440ba2bdd69f7d4c0d45ac64c4647fcb04f6e7bd85d7bde2ca00a8ac1446da25087534224514f489d71485f98b2950a894c1c6bae7362e6904c8ea286bbdc853f5b75ce244bbad7cd417063bc7ed9fc4a8c80dda188aa27c4d695a473f287ef0fa9b4efaae486abb087eff2c2e257fbaa7afb16bfd401377e8f9523563e33d1d5caac071ce0157bd661b8422a3b7dad4d9040c299d1703d5e92ff0c3baffef04c03fc2b757181baa73bd3981681d00d4a4bf350c2e35ea275ab348b53c8175f8ce769c26e0b537f64539411ea47f79338abbacd386fc2a492d8644053dfae08e3af8aa0dad7cb211ac31f578d7c6b095d5b9f2a43513ab57321f1174f2bd2154d41004b58e8027ec23d0ab0a6b8d9f371d4d62c014e412957094c70dda95dfb3fcac82819da86530c177b8c93e420f7d636b13fe417b5dc1ee4ef72a8b2db2acbb5a429127240988041cb2e7b3870cf6d390308a74f2358901df4a70cd23b6a27c8a7b4a98882700cb330d12069d6b1be75ff598c3ec1bad30307e721c6486bb41e3dab09fbd43257b7564b4c1b1900ef992403bc409c42660cc6138fcef090109a00dd4896468265c5cd7f210770064dc4302c1e219cfafe3dca232d12630284c8854870bc316b45962348b5496b122aa0d865ff31148cde174e15c27e6b962ab090c1ce7a24d3e2ff81fcee6a42c7402fc0f1b7a040245938b64c1641d8114d26671334721ffc694c8d1a120725c4f14c8bc6daa4590d91dc67440d60de6bbb2f793ab570c0c807bb332e10d7429ccc080a8592b0dc5024972e679590b885fd0e7515b40f046f81ba9e076e5ac5ccb288158f3d96c17e6c42fb0a5d13fc8dc226e2d5cd3a754c14890bc372bd4b46593b6c6c0c0519579559401a4b3e040042123e804b52ee179a0803b5ebf01270223ec0284017380aa31b56657a62c4e955a6725e5feae7b6dd8c6698561f295b3e6325b13a477508e9b6db84b25528bf5fc6fbf9b4aee1280ed9137198c28f1ec6e97b1bf9495e15a1ef0377003cfe767c99ee512a5c9396d45b522e11b3782e7a1208f0155cc4f88420858597c200f85780cea623f210442c8caf022a22d8152969ffe66adac5a40f5e5d1cd775f1a237d6aa107bc7769e859513803d59a350ed6d85e5b3a2c0cadfe82c495a972084403e5a3dbfa80878cc0eadf650c44ebfd03d2a4c0a18308a78cac874a2893b04c42d2e47c9cef9b08c1a9b6f6ea44305886062ac220415f07a287e1491962d3b11049513acd83346d67717f6418e3fbadbc32b6d58c199a19e9b2ae170a38e73514a525ea0354a726050182481f1a8c7d2b35c411c0af4fbcdc74c8bc362480136cfed73a097ae86c356bff56428ca888ea9cdc1064792e7ea78201efa60a6543c8775ba1c80e27885c5e9074030e0575e10f83c985146315f79b55873a8ba05fdba78c08ea624331fbf9d296ae24aa1ff97f5f47093dd011014233ddf5c8fe8452c141311d2817648584cde558e67198247abb3686bcc0d1195e6a95377969833f4008003b07ab7dd67b06a3d27b0c22af38f7bd5184276227a396f910fff87e8bf2511638d381dc47119111441380800ecc54b1b8b293e1c0e98302c1f76ec752b378417c2576b8c1005615c87a8469fe5ad6ccc589ccb37656c4cf3b3fe6d6416b1ed466ab6283e9a12679c57ac8fdfce0c2c80d91b3c03a9d8f67723ed8e3958096d987081999d11a8001a973efed348ed914801048096e74d119c393fa280229de1ca35e6081eb8bc8c24b5b83e09728c58cad80251b4fb3b29ec3be16d8749d4a52980f637029432c9783e74dc976256523b039f6705116b388247cfb40eb07569ef48553c83df51f37ccf9b84f540b87d28880b77156970a19a490ac9adf38165d25f488d218f14c02d77a3bc3cb2910ddbb4dce317de04a0fd8270404202ce4d2820f8058cb2a7f427b230406499fef63285e84a4167d9bcbcf41f9d418cf453377c862dc0dfb90e8305635bd366c7a5de9c41f6b69c6f0128fdaf2f9c472c38c404928d90bdfde9e4ed7b4a522af57976f1862ceec8500c78a936b374e237b9e1ebb63b3bb5ef78459ce5b01b6c7a9af6b6f8b08a0aa4cf38dc18c4db137722d03ac9846c673e91e724203baf80aa3a8088d209f63e79ad2005c9e2d207958059e26d2406ac7324d0d31f245136fb583227c051e8394f0fe4885c974b47fd2779a5f5d6532a2d3c37a890d0e2e9b5cc425e75823e006a4245cc0f45b7fd1fa2fe69b605df52657c70d5f878c4cb8e0ba98e5fb37a85b03e80673867b7d0a9d748a43dc3b8f53bad7b212a0882ed925fd1ec5d18f4b71149e7438de403d8f2ca515c8056f31b3cd249eafd99ab3d1dac343e8d02ae4bf307588a7427b9c7320582b6d065735d07ab71288d2927d7645a8e0a7f1fe64da35be3af262e46fab4d28a5b9a5eb019fd3f087eed55a8a2826f25a9cb53229a6727c45d635dd72ca3ce24436ba80e4f0e054a864b92c8ca894750f327dbbd9c4aef741d65b01afae26caa6278447d452a705f334533fa6260857f71f5d676413e9ba7ea9cea27760426cd89aa2e28cea6cbaa6a41304413565fb506ae0d84dac030a25a0d70b2c5183113ae1059d1b89ff11708a801d18e3ebc6e1e1b6e04bf958ef853b397b8582d49334749e2208d7d44e27d01b46af09424f8025f4ee50d8b9dece83a166f72fb9f32dca7bba3a3180302dd16442253290ea56f8f9fb0aad48fbb8fa96f5bb8fe51131f3372450b812bbbbb1ca60b23c8d5161573485322b267129bb24717da221a4970707780a98709fbd81d42d6962f7924d641948f2e8b3b88d18589f6262f6f567b37fabe252f571a7f1d044f4005f64b413e1a86c31682ca7a462cc0586291c7abd47cc897753787b6737a95f397b645e7ee949288044cb90e8c90b08f43a4644357f528bc0dd7f4db4204347f410138181a30f93b1a18f47b3c714e7927e760c17f1032ee0782d716f5d17ffcbf8de92431208542ed503d25d7d6d9bcbb6142f055778f33e42dc3496306b460354f2f7248c6c517f9be48f349103dd44b0282655d9f1f5cd4926129710274fe72466492a0a6e60b1d5838b0530aa183f826e7a7b4bc6374e423865f6c489f83a284de3289aafb6761421973e74eaf5ef09975b8251a1b3c3b5516a213426efa949273d5e3c75a6b7c70a4dc40e620fc97016327f9cd823b18927daf0c3306abaf8a2272ede746128967ca2a134daa7bb326b92e192d5024897728af28a682bbd8f564ce62a31a67a35bba698323045af03c47f0cc979b452d60b9396bc35da4e21673bb2bb66095b9088adff676d2b052f58fcb5c81eb01c288f213a72e4049964a0d62ca4480e16da8d8362189b03fe4722791ad08b268516d013237590b747302163369a042ab48486423099dc0b74f01b44a61dce422316b7c3fa6caf9438c0c6dcba4a26bf4a6500b4a9296eb01bac46356ae2904e79e580448715a0ae024b328d21de5ed7caaad632c897f0d75118f40d0b5f15eb0f92e65486f9b76c34529de4a72d62a748a682aa426f82d506b6248e608fcee061c6722607b5eaac444483567b351f67e1dd9023c35f961e7f6afa1dc283a9fcc1e843c9206d1dab20d59e159f1cb1d16394b1c64f227928d866eba26d109e5350ba4df88e9891e135b7393ddd0706ae72fdd6e464d5051f68e3f842eb180f65bc97fbedbfde3564194361c9329fb6982807f9cd319152075fe7639fe1a88ea0b076eaaba0e23ff33353cfa1db34a8e7600cdceb7a69a59fd2b811fe26069920242761b234f853f6005c5231e8b2e1ef262fadc6f5379102493e89a34e89839108c0b6ddf734cbb0164f0a94f9bfabb9771365b2cf8a04d9d42c3ad1b268ccad26aef2e1faaed74ac4ff508bcf66a1850237b6f0a40a40570e4c0e7cf1023a64127859405c11b5c5099e61cbdb628ca874ee3b2f9d0021804e75ab41e7188dbfa44e74e25ab48a5959d1b07185f9cef80834ceb84ae09e802629e09fa816481bfb6354a122b1703a664bf0bfb5d65a6bd64d22dd44c8a8496477f70ead07ec06f906dbdc4a27398e928693a4e3debdd3df8d8dcfe9efc6d6be7ddced86f377efd12faeb857dbf87cd32d9f77ba45f4cd25656fd7f277b54bca1e1d131d3ecb1fdda1cf2c877891a6d234d2afdff4779d4a53087bb540b74016666dd7ae6561dfae81ac57cbc2be5dfd552b6ac73492a549afa45b99a4bfb82dec9aa63fed9af57aed1d4bb32ccc834bca21eeed716fc774f6a84935e2b1c76317965bae575b155f5dafe2abead7b58ce5efc6c630d1431fefdd39d2e15c21f9e86eec21ec1f8f34d25fb5b58b421aa4bfbba736bfb577fafb9e264d3b8ca9f510f7f6ed31cb21d6d85ee9effab665ed51071d608683dcb2dcdf964972c94bd9e458fe52367699912240f292e3207989c68ea374130d270a2637963fec94f68d148192931c4789ce4ea2e1cc8e23cb34dd727d987649d997ae0eefb6be78ba5169caee21ee78cf14c9cbc49d019416072e213365208a8c35660601ae449b24aa13a670da168e54a936bc68c719ad3d03eefa3a455cb82faeb8d166dfe0886fca2021572acc942a9694a1d99fb7bf1a53616a4ced316f2055a8ea43a2c8d71b0cd9d4b6748d296171a39e3fa449c64c991a53636acc4462cad4212a0db67cf5516362aa8f3a84cc72b02c15860b134103448a4ea4d589556ba2ad93da3a6977cd29278c89222f95c9415823e42c34ca3957e00c84f3a29d6ad98aa2208410da0025ad539f4813cb4d292c9f8e877ab4a31c05595cc535541d718991d2caea50d475ea17ce6450f6ea74aeed5876b3b6d2ac14521021420da968444a315bb54c46d5d49c9632419448222931b90490036cd320cc3039a594534a2925b5a494726a5a99e89c734e59e79c524a29a59496ce59e98c998c525e4ab95d0d00479861812816086e7cac4564add5ce7f544a29ad7862c38b92452184d7e29260abad2c96076e7cd531cbd359c44e9b3f6aaa15d658b4d65a6bada65a2b8410c239af33c1ce1aa94e763dd0a8c549cc0103188ac415598491235b3e5a788899385313675866ea67ae34cc9ca2cc7090bbc589004c1d9392072000998c590560b266e20c49a9240001c8646454250094015801863a6d94a9286c9379802462e488dcb40cab7414d2b148a392c994c99895a20c000c60a0959ab6aac20457644a0f204e9822ce54d6468a20333351c81344a111ca007af418a2c74c9c89343d7af4e8310002f070e261c890210420800d2e0a600518aa802b37ca703ac9534a4a4a0a4d0c2224ce8080c632c8d394075239618a539cd184a4a4a4a470b873a1849926e0cab53f4571e27137eca200f2628ec3f76e053040bc98e3f0dd346880165a460011504b2dcb4cc7619b85ada9a9e95c96966998eb4c8a5aab8a93a2156a5985598a555ba65de862e448c7e1bb6919564181da49516b2b4a591de63a0e5b15452d1460606060acb5c25a1163792e806f6eac155d61ada0585870a5f807986c856487b98ec32151ec30d771b885490d959471c239e794b3c25a6ba59585d65a0b2d6d028c120b713f294f29910c910c11453e1a89457c910c2a509a8af8221924cb4c8d1059c4773b356ad0353030b1c60250cb34cc75eec59cd5b9379381fd3a0c893b8fd6cb6ab2885944fc01e362e4088faaaaaaeaf19b26ab0cbb880c91429a6c3a5c2443a55445c9222ccc65d9900614026de69cf1860a2271881432da48984ed779313145c4c49a1824d6442131484c4c4c8ce7b94084b9c0cdcd8dc7f30185ce408632c0951c6a98b5a6a68685852547102318186992b1a6a6a686e5038a4d8835300ab8722f6735af9630110a5b6a18f943559d878342923bfc676dcce11b67145d2d34a8c9019ce153058d1328286957b81e1a8074617fbf02cd13441bd2d014e143a303cf0c0d0c3c40a031c11a9ac8a169820a277c40d3840b689a18014d12ce70d34f4c4f50bac9cdc4901d53c023095fd81f9ce1d183092b76cd99093151b3271cb2a709e865e247ca02688c189052210c9bfe05a59452ba51869c986698c0040d7e70bf0a08da831925543c4320e2238810acf0e9818f2a3e23f0a10614aca0065e16688400028d103334424841882ee80d6964c0c30a595114655534333ea86c531445519e11cc8ce023733b235d918bb7e099e26e5208b999123c47dcedc7678aabed00dbc8600417db90660915705358a204f7074b78a0082460f1e102128adc5014a28d945e934e1b63b596c22aeca4945927d65a4a279d934e4a77bc3a95856952432b488d3336ff4f6436e5949d8a08dc01db34e64a8e9923470ea982cd8b76aa652b8aca9123478e1cd026478e1c73259e76902c5acc24362fdaa996ad28aab256edd0783a4995910cee678aa71366c1a5ffa0cdf70252b123e4e608c69a2813a3c5bc1035679ea121868881b1870eb8a2c3c6e6064489bf66c7051ae14184081554402968686a65a950c856d576acadf50135ee69d10e8659703fba5f2cc006881233cf0f2aa9f24108e185109bf37a413b2795ca4ae5e88739a7ac1565294a4a295368bda31f7eb89146dd639352421c29a594724e26200c423529a10d1aca6942789339b10f5c9109087f30d9271b4608a1561285d8e32694e26095524a2985705a55052184b06282524a6b654355293be7b47eebfca413a3b4d65a2bca96b04a2184b02329dd590c3171e32bbc1056940ed95073060390832803e53f29e5254f05c6e3caef85ac7993b5c61e30a73a45181d1005cb1616c56c1e16d9a19968034ae8a68b12bae9424929c54c01f5587f224da549c3affa8bfb0381cf3b9f0eee58590e9ff7bb75f0bddf8ffe38b03baf1d7c6febe01beae8100dbd93431d8c753a577e8932ee75bcc425c5dd1d6bed143f1e6338b760b73acbbae5d1df8eedf9963f6fbb6c2f4369ba17a4bfcfbd7327c9587fd937782fdb7ff2e7e2edeed93ddd61675d6635ba5b5a6636f025842161c8ceca1ff6ee5797b7eb2feece3b973dc7f9f336fe35b31adc8c7bef30a4274369baf76897bd7aa7e15f4f9ab4cbac06d6740bf6f84cbb781bd3d6e1dd9d0cb765fa6c70f19e8694ea866e82372cfc695dff53a20e94d0b45b79584a4a4a55dd1b0afd26d38daaba3714fa4da61b37b6a6699af64dd39428955252525252526ea488e4d68394ac410c1eda67ebca326de92a23c125a76072a22109eff89ee792354f7f2ef9e62fdf7b37ed9e6701ce73bc6d9bf7f1dc73ee16b0804b76c92ed92527912df0833cff785c72cefbde9cb305f2ee21928185bb14655934ac65b12675651ba6b87b37d6b1ec2b8ac6b667e9c172255d43114a249a7651e896bc8dfbc682e58fa5aaee0d857e93e94bd9d837ed9db669f9a3b1b56dd3344dd36e77eedabbfcd1d8f85cfe686c4dd33496ad7d636121d134fd958ac04283f411c9a8141a7d42de87d35fcac64a9aa4bfeade1d0a792a534a09cbc52ef6ab3f968d612c2c2c3458760f91246f1014457514555514455114754e07fc946a5e1645519cd501eb4a7f378850425282c384e4961c47a984eb38229494e85092494a8ec344974870542bd55751940fbbc2909444407d957b40593aa7151742e7891eca30fc0bcb2eb71db3a1fd3ac6e91a9ac6d73df9d3b8edf2f8b0b94cd27e91345d03bb0f9f0ffb9efbb4ebdb367d2fddf239a75bb26fd73bce324f140a81402010feb6813076b77befbd5708dbc58e5b5ee6ee9e7d3b962974b1e94cee7bb9b97bf850aa60fdbd6cfc6dd31fb6756c2c4d9e50487f3e7836b0b1feb443fd611c06a8ee5a7e99bbea740f71df6983e330ce32ab81e163194317d3f32167bf48cdc7b5d50a16f755ef85523b6fb15ebd63d17a5b790012040cdcdd0389fba6834a930e1d2ff485bed0205c1d2b25d7b4920c25ca0bbd974ad3c9486a39b817666de8d8f49d0a9357a61245c7b65407953240e83cd041a37fee095d7469f73e64ba0d27a46ffa7bb9cd6cdc6b36b8e36b58a66b701a4a93b61d9f34fa757af3a71d6b1be93ab6f648babe1dff66d275eef7abb6a64997ae214ddc39fde9d8f758e3d161c84b7aa11b7f1b1deb96d12fdd12fa7da1fb7ecb9fa65fe81e69284da063a1c38b3c3704f25e7ff5f7f178b6cdf3bcedd82fccbbc7b4edf798b7fd6ad837acebba5bb9db8e6118866140d8b6c76fdbddb1b52d7f3af6c61dca95d2374e7fd5def4576d6c3bf652861205cba876efbd31b371efbdf858feeec6b6e37b377da589eac0d92f5324312287946541485114f568bf5bd082d0da6b66148c973a8df80f30d1ad5fa1771f91b66fa4d02d79a15bf23cd7b84d7f18f8ee61b435b06373dff7f5ae77bd7fa17dbd6ff7e4cf0b9d3bddf4bd201ef6764d933ed7ee1d67d2e7dc7155ddebd1a48ff6ce9dbbf7ed9c973f1eb6e685f0413af44db784bcfc52b17ea93ba42f6944ba44dd682412894458842f8661b732f683cdcbdfb7779c3f1e36d634fd9978aefe4c4a4a48484a251269341289422110e8f3f1783cafeb380ee37bb74dd3b20cc3aeabd3b1b666ed0b0269cf3f1942171e6a6b271dc21b3cffeabe87f006d04324fdd9ad5df45186d085487f76df7ff20de98f8b8ffee8d6eed91e95eef8d774f587dd3b8ce965789ced3becdcbd19ffdebbbd30c3fdcefefda5f280012a8b2cb218b25fa8287a485c17fcb03db353d65f76a5e6abaa3e236198f54b4369eae8faaa3f178c5e00db7145e9841e789ed043a483fe1971c738ce08514cc8741b4ebadfedf736b3819debc1646b60c7dece5d9b26696fb9be5ddbee3df77bee5dfe36d2af534ee3539c2ff62b7f2ffb7acc20807fcf1dcb24eddbb1aed3244d676fe9ae3debaebde3ae696efb76eed7b7fcbd6cecdcb771a40fc334e99c6e21fdd22da2732ed8e67e49587f2ed8e8c3853cafe7f407fa7ceef5783cf7f817f670c798e79ec32ef63cef56f630c618e31edcfbf87b394c7f3bf6cddfcbbedda15c21d9b044b9c712051fc6c439fbcd9f0b86711cc7c5cc013b38ee1797354e7f71cbdd6fc68ef3876dfced2df7d8b77becf7d8f64ee3c3985c961b7334e02671e7f40b335c520d7c69ba1a4a53f6ed627fc1e6486a4afcc2b6aaee85d332edaaca5f0a353b94d5425d86dc75e8b46957e7349c28f63a60fd941d43ec0fde25851a317f611e485ae32bd22dd0add1479f5f0f899edde3eb661abf6d17c5a854de9ed3bbd65dbbcd6ce05f12771d4a27b90e262ff9ddb00ddbb66a63a44e93381d8152e9e230d1251a4e947bed98973fee019f77a7dbb1d3ace5e039bea649deb57bef8eefdd6636bb7e948a927f212aa48af77a187393644f9a4c5e926d58402c21dd695a4369a44a3dfda1e90f9b908dcdd6b0624c9a4c3e2f65c5579a8cd8953a11fa27196594b19e524c320e8644b9626db8d1af2b961e8a0ab0af1fc11be2eb4950a5e4f5def039842b1444a1ffbc244f68a2b754a66f41afe963de948ef28b2bb06a0b17eef8afdaf59e7b432c928754a176098b3bcadfe8f631ff44f6ff7d69b60ad054ebc962c1625163ec186a0feb850a636d2c15accd9cf11d273d3dd1933455cda4f2a8a77a32d1f424552ad7596b6dceb726269d8c31d3921293d3d33c12c5904d4fd1dc42ffc3fb44a582009aea89ae238028f5b5ce40480b17ec7a0d0454403d4503d4fa01e8a2fea3a79ceb29ff947f9af1fdf9e75bcf534ff554795498121206e28eef816eea18d83645f2cfdad053ba87b8a3fea8164a533d8f4893896e21e2256e22f4a33e801017744bc4de48155a8412912bfaf57488543179bdcef18844a9cf59c23ccb1f386de6b4d0d33c224df52f712f409aea690c1575d208ab46ca416e7bba3f0e6c7b931c73a4a916b143ff648f07d0c80d88992b2c25313850dbd29354a15e874c94ca79ef4e87785e2d1db22be92479e64853bd287f718bb4b539e9983465d7628c7a3b44aa9088e07fd521f44ab9c65c61a4a9de66d6a622e9ca439aeaafffab279b852196f56863a9b043aceaa38fe00ee52f04ca3619a07606e8676d76e57206e8feeaa9ded09e3933c76443ca0b698a99fdabb98344e270020c8466094758021273881f368c30c60a5cddae8ea954f15edd57d52fbce1da5e65adaa30d6247c0b5d74b71a4217f53bf0ed67e05b9b71973fbaad4c46f65b5ce798d5d15fe71077b48bb7b7c353df0e2c2aa0631d4303d85bddb65ea637631993a68bc4e1cfe8748e35842e766c4ecfe83467659c3febf79dfc59df7e516c66d9ad4dcb740debd82dcc5ed7c0a52f74616f551d4daa619dfa0c974fdb938b96082550d43bd43b5455955e3239e92392977870f6ee7d8e2986b37798d5f0787b46cc0286d43c4f93aec601eb743a59d699d1fdbacc0e338ec3ba46f7ebc2f81a96b5c3ec0126bf8730a44723f1dc6610f08e35493bfe754f2669cfeef97c3449d3387cf4e7b23fbf6e9e91ffc34cffe69885cc388eeb50195bd632a6758dfc3f5f7fb65d039be7da0636d6b6e73b360c0963da8c46ec4ceee9b0c935dd62f2ab5b48aefd93e171fe4c3494a6d23d92c3979094489a56892a4d545556a55555a5dd4adbaa2a87b6ceb76adbeab75bd55659af947049baa5433b5a6ee99cc21475eaa0fc791bb4afb669282dfee15a68fabb4019fe667b2e7fd73d8ca953faeb1c77b25f33c3c1623393715d3867d9f1b5ccfdaad90c4dd3b44c46770dd4e91af7da2fe8da76af81ab2f74b15dd317ba007d3b36be76ee33b40d1f93977135e99e54c373d0677834842e3c0769085d7cbee31ef419f7a0efd8386f199461fe644f5663eeec986639c89d1d77d8bdfcc5cd715a93348035f64d5fe802fb0e528dedda676c9af6a409fb8e9d5ddac5db1d4d1d5e17eff2d384cbdb15867d07ecbbb53694edb083cb09139c105db79e8d8e91b48bf340c79fe3dbcc8676ce8667cbdfc9deee76b7bbdded7a74b7dd83f2c77557c3df0efb624dfa685a5571dff7257d740d284d9d477f3becb0f1efd50ed257b784bcdf934fd32e273ba43f9793ed1d9e8479d935c2b0ebba2e8c2f8c4522d1ad2cc218638c9de8ba73f93bd9dcb5fcedb035cfb7adb443a1cfdb5b086f2f6dd2f4d19e8cbd6bf05ab6271d8731779cbf938d398c4fa4e904d6ec70a285e1d757e95069cad6c34c874afbb027cad431e50e2aa3144d78b8870eca8e7dcbb28f3c9c1dd381e42512d638f486ef71d74e33bc6ddd7dd8d8a66599a4691c242f1d9f440192974e52d29f0f3b3bf6795d86b16ee1aee996d1b3c3905ec64d50361281409f4ef62bfb743ad9f60ccb7e338fc7f34ef664b1892c661b3ef796ef65669986f527377ef72d67f9d3b1b3ecde4b79f3aa9dc189a265f97b991dc74d4b7fd8ef75d8b652267996bf0a4729cb361c255d4d949779753c2be24a4b559eb43405a91c2edeb160e29add2dd145a167a393f0b70b8f3c6f6b9ee669f857f338ea69daf5cd0502daaf2679b64cfa7cfedd8d499e0a63ef1086bc3c6fc46d5844ca46a22e94655dd7751d0804ba95414c78f2dd9af67b3f1ffd55dbe3d15fb5bdcaabbc7d6fe5799e8bf7cc08f2f4aaa475482f0bd35fece4cf65776e595696edb0b35777d9d96dfe72ec4c7f9d4ea6c7ea61c88eb56ead199d8e86d2f4b964e94d21be84651db38eddfa05af1a7ae7f30e76d1b552f75f5da6bfbc7c6ff799d9d8deddcb9fb7bd636fc5fb85f1bef75dfebcec1e66333cef6ef700ec9e477cef189f846dd9732fdf5f57cc72c8eef9e6b2f1c5ddbfdb65ee9ebcfd66ee57cc6c74d9f34b625dc601f4ee73a901daf7ddbfeef6b56634e2c69ed9c03cbacb2edee6910e5fd230e9f3f59e54b19410832f7892a8b5561caa3899613ee10222b04ea70847d440668a9c2bae30023261880fea892136c8acb516aa010b3c0032040b42a018a2082eb0f1aaadb5d65a0db06badb55a237c14c10458b8e00920e88f285ca00436050f03ae80c40984c0852c9250820862c8c1c6c0e3b232325666a603850c14d6450426625114f5841980a89c40d5586b6d1533530083a946234af0c11019bcd6072c9861c21245a400033a842744300510a78eadd65a6b251434c081a20627ef0757a560ae4130285028d4b003cbb256a0004411225042073ea4a042a811e20315152c8aaa4da834c220636baab0b959f8c2166ba870045c6ba60843c707b6d65a6bad750342553110814a82add65a6badb5b6b5d65a21331305cab02c144b10622971c2a8b8e00a9ca9b5d65a6b707cec7aafd65a2dab02a1835dab5d6badb589d75a6dadb1d65a6badd501a79b4a91d8f589278860d7ea04cd15bbd65a6badb5d65a270ee584185e30ab509493da3645511445f3435a15ad81f921d20a563545ece01104115080530513b620031a04206e0084084fd8d44b278841452f1492265a0348952a904a71738aa22a65a98ca2288aa2a01344e46c8abad95306360821e8743a4720711db144a733bd20062c50278e08d282a2e13671822a18010866e80210bc708414530648a060902be0800640d8c00b37580105821554912c8b2c7410862bd46c610c4a50199a310011451034974651a5f0441451108288cb0bdd0a8510339ba29ec82267535b0c8aa22cab0c29a028abbd4b4f817c40497c20081e8842103378c20f702ca9126368d3b9124ff4e403f107980479061a21a01544b4b86850441a6080051e4960e183285aa0068c036b6da863adb5d65a082427886dad053204246c9b852394d442c904333e54007345112250d01e38210320aeaa2b7aa2320795462aeca00a4a4029ac400a2105554c122401041431684e0010312e1a7d1051862b62d00ca5b082185705724418ae8871d920552c4182181755038511a0887155d8124a50022fc4b82aec095ea0a9418caaab89224978c4a8fa42d881416cd03082183493f088214f70b684592665a48c49caec2923553e9344c2a43571e1ae7696134f5d4e9226ee355353e6fc32914c862365a08b8bd25353bb5c335bd3707262b00f4ae14af5acca3687b6ed6632ae17ca70329cccc8bd3bc6dbc7d7990578433dcdfe44a50c8b0c07a2c88b90d8f2d9157005a661cb0b6355de11e382b0c3322332321c69929911699239d22445335b8a7e4c14290118432463e51d31aabc23468b285cf9288d90583443a9a866ae509cd3e9e4811812fe38c211684442a40a6c020968b6bc888a1b212229b694324dd89f68c896571348a085fd898a6c793aa15491446c19b31152e587901ca96224c369018350394ec18e78479a2bc8c6313b1ef7d891085b24035176bca908fbfed8316e29d85b8f1de51504284a424684190e1916639c5526e1a874754d382dc5e0753319f156de11e3aabcd74c99802de265fd679232dcbe2456f2822dad389570a08ba94b62321cd1a435673822995db379452f886468d59fe80715553a69bed264e51d31ac8cea78aa320aee2792d92299792a45322219918c549993be6e22992de3cc9534551a0a8542f044ea96139c173ef855515a6f2805015cd1515113ecea66a2d47f15566f28d5f58666fa82dd469a6ee00d1507e254958e97ea34ebb8aeeb78912a9d15593351ea85d42336bb5e0ed97576b2aca98f3d42b246eb087291a8aa1b60494949c9bf90acf586c22e935b1ef5724bfb43576fba7fd647bda947e8c9a4a4a42b2929a937b58834d563265cec56c84d09f67929619c1a35b989b6a1e206a594d2d336518a6ddb5675eacd858d48bf218109dccb5ee579553e46af0c3bb6d241ed1b1995fd75d1134661e889f2a84760769521cbc24895aaded893e5b17fa041439a6a89ced0d35c993854d2d82e36b9c9adea0d8d0648157ab10e797139bbea982815dfe0be38e8a18f0631040f0a437bd020542c3d7dd447fe476f80e9899e280f0a53aaaaaaaa375555691a0df8ab0d9cf1bc1aa147e6cac4a954c895bf9a7c662bc1191a0d9838b108ce0b692a49192424cae79fac893ce26903d2543f71e68a0e9c8973845a559bebaa369d4eb5199d24c3a874bd19bdf47a5371aa11a912cfdd7ba3ea1452a6f466ae5477d69b91a6a07ff526f48f562b70b6edf1a616912a71c3a034559ffc85b697334075eacd953340f78dbb3253555555551549a2a00107a181c2080d143034408cb4e8711d9e5cb6094ad90ac4aef50451aacc645410c0159669822d55a8153d3ec289cdc0cf86251b7e72ff9828f59a3fe6b4992b5a573f6e333d3837d88ed8a6260537bce8fc11aabf72761c86b439f68854197d45dbb0cc15ad674ebca5a89116b788d670a2d45f9262a1d46966a14e718f9965015265e4b139fba34e3367527ca5c9645a1b6b05b8327326ca1450c5f31e6580a962576ab9c03d9311694c28e6c65c1846a54acc9465ae9c1cf4d0e1ec7e925b649d674e282794734393523008ed71df913de64bf477dfe914688aa743e6f7a2447f304808d274a01457a706369a0ab9b0cb86bae757a7ea6c34357408b5a142367a4389cc6c1aa5280f758fee81a236d4469a8448958fde73ee9745290ba3317345f69828f5554547b164c6581247d6a6478cdc47aff7646a049ae243393bbe56fd8560763c554f3b9e3e60c7fe28ea2070a4e96e10ba88fa733919bd07ba3dc7c0b63ddc698d34551b9e73ba87b847faa3a78a6c2ac4a3691069aacf0e4083fbd1991d8f6beeb56191d268a2815623e510bf0e6caa298e3479367e55c9212c39cdd44473bd0a931cd22c21c8476964101ffdb1eb47039c1fa8542bdb297b1822a21100000083160000200c0a068422d16096a6699674071480106c94465e58281488235112833808c21808320619420001c618820c423765037c90fd8947b8433f93f13c16c914f061c6d59377aba9945632e809821fc9d762c3c08ae08fdbbb58184b299feccd4c525c35cb8db6e365b572c54ad22a1f1ef6eb5c4b2a2b88d84bbcb2be958c288d6ccd56e1de6f2d62324004f5093e97a9c0bb1d788f5845909a75faf864c8444c2e7d5620e154361dc499b96c532897456c6c921113633fe6ac153c6fa5069c33c16248ba7c41a10eafdf0fe8385aca7570c172b79061d1b9f76d8803dd5d474efb7002144aacdcb322f3e36f756c1239a5632c8fa1b03f6f7fa414fab6e4b92545738c6fa653c62fec35c994e805c286e566a92ee1d4b4a1d1a3faa3b97b56ce84484686e2298650a7b78d3e900b0b069385bd77843cd5105399dde70764e698eee20328a9b6c0cf1304fec897d8a7cee758d4e07e45499ab4b9e54a7e01c8da0c99c10a184bfa8e175b2f55e97bbb4fdb347528c9c7678bfd7eea48586679715ef545c12940718420cf90a3d3b52d3d374f8c9986a7689c8350488f3a736bb9e12e255e11ca2535e7d7963e196fd311545e321694d7e1df967ad2f2bc946a322a5bc6c5246d532042f6a4aca6e1ecd7c74b0330798614ed245010dd2388d846bd350806d7f502204db46e1d340502e1ab6b8c111a58410520ea3ac27c33ef4b00e2891b2bd946d3c8d2d878ff35d5b8bfa63d061324b9bf43a07848625f595facbe8bd6bef68932022f02645de15414fb19dee4116d2d42a895805301912dae3f7dd87e8d2bc0c09d513dde0dfe4e4a62a0f2c95121f53aedc828753c9987ec3417a8ed2949eb599682d97fb91a4ada83b1c1d79a23fc2edc2d95ad389cd269d3aa9ceb23eec3cfb0e8da8b4586b802a26f450c6c2060a7d21eb9d7b0af8bf4b38f759d8b1d976f58ea727666285265f2d50378086d6bf89ee9fa49de6f1acf4a12fdcdd5ccd411fa4c0a1b5c3b2987ef5d8d710562cadb639b58cd7a6a133906fbe6e87db0833aa414a04fdb1cd440519a21632ec7d47a1335256595a18858013386aa967f1beb845df74cb49b903e1b3b6753c627f7943605b94129ed2c975a0d88090319e8014a362c611cfc0ae671fc04db72954cdc0008eec11dd0cc4f18cd4d94106fd0040110accf4fbd0c7f7a2341ab6e495906e91e02883f794860b76e29a8e06cbc716e15b92fdd8c0ed05bb020c7d9b198a1b49354f05bab9081bbef44424bb23ebffcb92ca1d082773e727bdffffbc743f098cd112abe9b79dca11216f1629a773bbc3d80915b117d758542e907c4d40c69efc170d6eb8bdcd17d4460491e00b7b854578d6c9030a12323d2ec5856ed088edb80a6bdd55fd559af7d4dc9a2443d1c6f740ddda86cc55d4ba5468925783a22b09a9de57a749030b152dc74008858a14e30dd3fba6ab83b44d90a895fdb8dca549bb289b36c3107fb188d605674845a10232bb18499225c9bebd088b0ceb09b23ee247b397dac9228a5d7f22a096fb142b1a883146c92083328f7a651b8d214a8e4f3b4224a1b248490bc5c563a4be99d89a6271cf05b7a47dacfd4254680c2429c8adaab0956d21fe8907fdb6cb626461cdd2d17c23c5753f5aaf151c19bee056b22f371033dde2031685dc5ff23eaaf0fd5b9822f3aafb254ad542bbf83b6d1be3f29f42a55d1bb5b130a1049630ac8d837f4b5fb818f02c405d375f6e558990dd9700d044c8745dc89f5028d9cbf1aaf07c5484e154e849886b694f16c92c0a2e6eb0bc52c4de1db1547496b081c115dbc744400227cca950c83b65d638e245065c995b79da8f4f0d2d3e3bcb43c2b83b079441256d6d29b135e647892bb9b340faee72573521e6cc5ff35cc0f811e20aaf24b8ffd663a529ab1debc4acaf0a4669146218125ed6741f9404ba2ca6aa82f3b2f693e5133a796d6632d8d207c3e416efe038cab12b92c15e7c0a4c1c1180a4ceb2440a5a1a1dcb020aaeb422a825f9f6e5d8f84ba243b9e91e9e06d8c6fec02e07affcb117263c7b6f5f6fb5e98bb96d6ac69433502f54d1d5933e46b47a5f6a2da643a8ea24d136a06198aa5e83683903fe6b46e0629b5b387d4a5496f865b450e7a93c664836313106041c9eb0c28e9dd9d643412f1fc083c7d8a2d7eb620f167fdc95bf9ea5dadabf0a62ad3d8ff3811e7df8369276ae1f32d9f152f4a9cae402d301a7d5fab71f081eb7732132867e8d3295ce47dedaf4ca1bbb55a988114bef568497dd666090bfb156dc7fabd639c2f1002c8c055adc1e60640d4a743b1e33783de3acd9a3f207b91b78385a8ac4cc3031a98b9f73fd05103533d29684e40fee98fcfac9e0167a627618f34f2083ca8c0838429ee72fc516d11214f1d92f46e4c1ca3aa7ea8c2cdf0543b6c11dc4c07b49255df233e0a8a2e72ce4cf18f7096798c91e17b4112e3c7bec3782f5097e44255d35c45df7e1c6e9b569c12e3e177e9110cc422e09f732dc5c03d7d052c8d92ab14cf7cb4b8f62c33edf635e5aa8c91b2a9700f68828ba5be3dfe8e7e8dac08140209664a318a99aaa79cc9edc2504fe3aad41579540363cfb40ab030245b40e8e1d9756e934127202afdefe99a48d5ec95eb062c6b79f4a494c840a81ac284bb163571c582389112f0c44829ed8b5348bf68e1ce251e0c1f243b0f88f0085aaf502d91fac24a2c7e77de1841d2b3c548a22b2ea148c199401d20d57184d07b91283b063a88b973c92387793198402e8aa8721d8efa268ea09e2b100170df23916e10d0f1179077ea032308e6a14380328460231e0add915d227aa6507b745b9fbdf4016c553be1210712b35bf092433b30b2bf63b06e5487b396180b716c41426ebac639f662a7fce5943e4b133efed1c922817f0724161a4e21a2769e6c7538f2b70ec45da7cbf0fcf46ee0741bd69ab2bfc14d39ecafca5abeb0449893b2726c7c5722002860a689ef4afa27e2c303b2c844d1d5fc8fa02904738810b98670aefd3de7bcf741218e7f51dae42755ecdbdece71c9d91d724246c470f2de0bfd8dff83f8ab780b8a098e3b0d1c0ed4647742e5c9cd59058d5e860d02880ae5ceb5c63441d3d437c7449516979d4676d7cc6864c72ae92069c5d00227cb37017264fcd16de6449a11a8fa71560c0211207761aa821985bb8b40cabcf172acbf0d31a682a6eac4fde42dfbc7f594e3569cc124e7771953b5e16bb2684a7a7a4952c66b7191dd8ad055448527b3cb69bde7c3acc3cd9c5590caa03a97121a34a2215c71a430b628b31b52fc8f0e21fce90c12f0114c71dd2146614b7ff8c989525a7ca6442cffb9160504c875b24dae8ff9559807e7cecbe2e831ad7265f31c875b4652b122a96aaabfa569dece2e9ff2ad255c3431d5f57c824616b6d90ea0b4a37ed48a2d14008f80743cd1df0e1cca6e935852f9c444cd4ea56a17ade5f5bfb3f19286008c16858c80cc7dcfc1b60072f7782f243ed2c8efd0037eca0934f9ae2178255ad2003feab7e7de1455939d4226cba877cf6d41003a95ec4b4115e6367989d900bf9682a21fe6ccc70be9575bf53525ff903a0bfc7514dccf7f5440c51f1370669130b95fc0927f60828acbe51963cb504ed2c4c86bbae71020829bec29ed589c6b4a0623fa2360679f84a8f4801e0326665bd3afc5a094d49d831fa1041f3510b0254cd0406c33ec53c9b09edf804df4a2b61f061c65560689742f2273dba6da32db379741e6d0f0580494b2020acd987cd7d56af790e605417aef86d46258d5eb14655b0d2cab676a56537f54d6bfea62b7430f36037b1b002e726031ae727c1278495ca9cda701d2067710d83570cbae441d7ddcedc531080509f7c7419b01b79204511e9aa67f88a4c56d6a85e99336ded6c4a29b03827ec77b42223236455e465e6e3b36f08437894671375324bb71f43fc071123686d874531e3b29f5b945b70a498c02c84f37fd5c960ae3f6af149db2a258b6a7d80f5bb5ca2051b12f6a51124fcaf258e15c5bc777662666a8c085b170f38456195b9b8a2ac02a6eb229f67e985d79502c1112c8b58ac52a7489de1b909fb88af54c762a172ffce3bc2041b3e1baee377fd7b28be2073d2d0aa08718f649f1b07b17a2fa720b8bf74421e50aebbc7022846ae7d3ec203203f5399fb0bbbd6ba414aebcdb1964c2275536ca2a1f6a7f0e92b041af244fd8676ca1619d901069db09eb66f3764a82a51a77eb30b0ccdcc84677c9c6d3c1622b890642be6a491d59545d07f6afd78a3a524b31becc9ad472a13c73d128bb82e9c4f59926d304d6ed1586d43bbcd1267c640ed403f60a3535d49280880d88417cdac8356d8452fb80ad0f965668f25c210e7eb2dad898ac665482d1166137abfea1fb0d7c0ddfb6df425cd79ef7b86e6d87f3b5b72855d6577d40393624c745734f4e2772685ee45671decd21ae774e1033887421b8c4fa592a611abda522baf497ee1ebd0b4797c3ea66a1da6d21627e812c4c38ddafc6998fd8c63efa54bdc7f54597ad04b058042dfef22518c845f1adbf038a6a69a4785ab3c1dc07342ea331e92e91a340209d5c530e834973985146c880a702c9e67ca9deff172d663f31f28e0914873705ce7e08c28b6fcd4ebae793680d604eb66603babb4a8341b84a0f2e5525610656d62725ae172716213b5a873bd38d2ddbde04f4cdfd3a705da8b53821a78e8b4b04b2cab88144aa5fd5ea6bab02b841f174a37033d05fe43c6780e810416f631010d44f2d65696d6edab7cc32d2608e868369be1a26356b20abf8803ad91d54892b8184da32e87c211d2af3b3d8b22647e095e1515efc93a67edb5ec2a62d1ac8aaf1f3a46a796df16c9e480b8f2b33fc268711361a6b12fd615bf5da791592b4ca3bc47c8054bdefc104aebcb7b643e85ee846435bfd619948848077298e4bb6a5af9e2019b737cd556aab81b707e75b1ac45526bfb5854be327c20de4737ba3d13fd916e5154c442dd6a137b5ae505e30a52d524523fc15ab6f08f19819629c1bdd15872f47a295f8974fb1f720cba5eeb3f7f757c284ba7464381a9996214a20acbae805d267a986c7622a9a43132a674349beb1b2f527264d8681653f4c7aa907cd70201ad8b3afd17b68b66a525058a7e66367abd1afcefb0493db89ad98e62b7ce4d2b0da075573a126aebf6dbb93e0f2005fa274b688496b849b2dc980e7796bfd9c4af672152b2c29d7241d8de1573d38296e47ab5b2966bd7e6abd892b39cfd4146444989f85fa11f749968342a51fd7d83b03a5d4506defce55a507018993f92f6e43e36b12d5c7b50178b76a5f4956bec36b5b4af397b4408433cd8b7831529c6ef75ad14ff7bba7409288bed3901c29225c05c7d9216fb5184be3828944531f9afd8f3d247f7689eb14b6f24104e49871ee598bc921cae637b2cf3439a05eb63fc0b9c10ac5352086a65fc3f6febb5c6eba6c67cf74411fd58f3460ee180d6c98f0159435fb7040f401b23b700a98c5168767217d67c6a1c7b3a30265b8ee35d40c16eb55e3ed1344aea8fa30eb8e0f01aef66bafc3dd16c246e94baab885a8a5dd7710fdbe13293c181af05b8c6aacbf39eb224174f9d22571e9dff3b4ae57e8c2d58faa8415507e4943fd3bb41ed5cfb85e1ae8995a467176160161225d26dafc1cc61331ec3e797a5a01bc11b221407d9d4761bf4ddda1f3e26d40b3bea26270a032ff4e2cd86e1ab359cf91781c8216a0064747be610ffb8946de621d153883017588d5cf88cf06bd49abdee3b262bb8684482f44ac00141d59c991bda3322fe0177b02369272cc60805c4c2f2a1671f4df7554e68f4ab64fe16bef057a731d56624a067522c81f81703dd76da00369c497be56cb26a80e843c2d3f0e58c0bd38c062769b73c01cb47917ce4a0f9a54fe2efa8b8756070ca6ac19c1dfc17bbef2af7ab9b2a788497f92915ac1ddcf4bbac0ec254d21ef9226f5e6028f0538af4ca3624afb158d562813302d6708e9e71ba5447df9b6ec15c05e7502edf45612ee0976078824e14c5de474a5253a9c37fd81c4e4e8a371a1d60b518509454fc0f73e61c507c2e295f1a10c2657fb15051e00bdd7c4a329b06a68fb3ddb099d34cb6bc6e91c46cbde47e5b838251e150fb58bbc0cfeb380580cb5b965f3ef416dc033dc7453482a1fd3fadf0de0197d24a30beac24c18555e53e1e8070d7b7f2c1d419dc0050e550195310d956dd1002067515893e5c1b458217b46f4ef9f86c8918e67883f67b2491e2a8990d6673c4aae3463daf355f524e3711b48a5066c9db49a9264115ecdbbb886a7d83bb3c48232d10c6a24be4d2913caaa198d1feca7a056e9aeb277d1b959b70664a492abe39cdc6f9881028ed85ccfd54194bc25384c9e86817a54d0a454f17b8d3f5437fae819be146b2b26be1098ccbe643f22315dbccac8ee7472251f9b2bf54830ea82502417d064ce662a1104531a9ff27e2237425822e0bcfe0e28ddb7e1f0f3f9ed1eca0649daa523253b75d3374a4e636f9f18e1c24fccf47d4e11b04dd90aa5b40ff5b8ca409c729df4ddda6838910656c122e8e365dbe9cc72fa6abd6499356a6db7f28e148f67b3bf49184f8dc96da21341cb5efe501dece976c932e5b27e11855ec829bb342b45a656fd66b3081aeaa1ac1fe988765bc8c67dbc92b010b73daeb135efdfd52db61576d74018f3e880832c6d9a3fab045479ba0b00d379a2a3db461d4e0150d4a88e16376480cf244d090996acdda822a1611234c54425b2428552670b001020f2809fc25fa927292f0bc95795fb86d5c8d05fc4f1bad2e725167eb84d38ab7c0088cf7ad8e5a72b531b26ee27a7655844eb50edddb7d0bc58ab7abd3a809b6be33826a13914c4947d0fe692a8c61be5d8a51b15144f0274246abddb2edd2ea14bbbe32ee71098ba040647612d9cef97659d0de9c359e8aa93fc232af5efc4d7270a797bdc4c560dfb19a77485f153a0d062df46db1a88292cd3424a4a0f95257ea2566917aaa4d3baae0b673ef4b90a078a6467a7035d113b4669745e2d92604fb11410853d937bd0d8dab1439baa9f4d44da0508a19d48ea8020366e8cd458f6670cb6733d2c5565acbd09414c3e0a37a658b6b24c483c8502f69fe077d26f1dc48b88ed5d5273e33f1c4e0cd6b0e1ac36a07f344f222c42cdbf9e3eae647b4b7e71bf727da7cd2504abd0c6c0202814e5665e501d407939a95a2f0435e721dd7432f50709a38674bb5e319624e61d2eada984c8376cca42baa99070182d5171053dfccc8033e305f59cc1052d827de34a48200d7d40c53e23407dce6595d845c3661fa76ded90ca4c4a1934cf3cecf8283539d2e524bfe1783379ad8766655658ee35275591066bc7647a31e725f59f10a77d09624958d059271940005c3c7572106fe92672ebe034fda7f7aa99885e9ddadb358f251d9ba9453d9fd0a4e4ab1490aa8709a639e8edb67583cc3e664abd1d12992f4b22099b843fd658df75ccc8180dc8d04c9adf297e881b49defecbb0fe70c2a2ff3eb1ebe6a8bef68740f06a01b96671a7b588a79a9d7ae753492d3298ddd43f079026e967591e188922550b9a2d4f0ec5bbed936591533c6b2351579ce778846b9e806dedcc8b083abbefdc89bb5969f557dac47848c16a2d58413b0609990cea2a03d2efc633fdb44508735518a2a740fdbec8469d3644fffe935ff221e62cdba5bf76ff40c591a78915ce9a542bd732ff537ce5e81cb7e1e4eaa66196027ca311e756ad179e00f6271c2facddad2ce9880d5d97b33d978539ef9597df84c90bacad7184b12a66f00125354da5f2dc32f701401d3a41ad261d1f2b54f781c14091c67032b4409c5a5e5601854c4c560dd5f474849ee48bb8af5704226a960d6210f42bb822da1aa50f4a0f719a42182621f2983ef4135339f1fe20f81d7b22240a7f26297e17cf7eaba8214fd2e73dc21819ed0be142693a4bd52fdc481e17041da1424dad90865b5aadcf4211f80278440b27fde00c55c56516109aba3f2841f52f8d26a904f5cd987540cd8afdad2644bb1bff0a63392311bbfbe6301089088e04ef1218f389721b4561399e9440f1f6127f89fb6c8517883933318bfc7576e8ae327d182268e3b14477a1e50ce6da322d0f348191ee9a9cafcbde08666fc41284adfb8e721b0094b24d55830515bd112e7b65f23a31de994f5b180da9597e93daf941cb7c232c0877bfb7a35680d10c2f3ffbb8e8c8cbeb8310d64fe09716011d3a070458d0a3741d34e38407512350c1a0a6d5bbcdefa465bf55d612f98deca5c38a736f575f68c9396ea143745bd0ecb1b9ffcd1472b38fe58b98c7df067e7f64d6429e950a898c6514abf0899ad1a798cdd069d0e67dfe68d5a732abf388cc590abd9360089aa8f6c9df9d64c935d3a25752a59b88b5c3386f1e9a625a3d822a78ed9f265e5c2bc74b188f0996f8d0eb340e3266901da533e1fd382c5b544f06156be724b9988b8c8e08ac316054d811e1233536416bea3662990eeb9186bad20b3d5636207956ada5ea560b12ed4a682475ed671eee73a35cbdfd1ad06babd82f343c39d505d804d9750714e57060b01e0ca5c931148b7d3ddef52cd0f63da9ed3ecf61ee88ea729cb7eb3c40178d41a0fa2967a78ee1cac608e01c1e8b8df242abb67e746288821197ad33455760011a69d58b7407bc04c5849d3a0d66aa47ea5080260ab7783841c187da37b94ae331d120aef2e52022ce7298ebcf6165903a2e680143f6f596aa363a826aba6ab62b1c4e6f508d1e8f9732297f98a996fcaf092ae64fa505e0b8ff00587c2a8da38a5d0303c047ce864e359818defcecaf5349cb5cc7d70c68a763e742821e60bfa05f79e9468b88e72dcfc6807e9561792768e5007da221b827a2b2a8695c7d02a9aa6225f0bedd93b944f7d21292184b87dfc9bde3d02a284bb28cd92cfab3c4beac6840e7666480d2e1c1ee71ecb76536ea5a402eae2588209642d71a63df8519d87f9b244607594ff7dcafc4208a5347e1f926d3b20e8e59d062b1d9a9b38afda3f8b0c5dbc3c460505f2ac2c3cb7e07245afef1a32255ea48e789b32a521f8ebdc26fda3cfdb63500ee2bca2504c75d3499a02259c43c85c1e05dc21a5c8d2347c64a4f7521d0bd6a035f08583d9e62e4a69ec8630ca56f7dc4f67652e92a43ddfc7220b4ec95b913acba001314f9091cec097a951322f2aac2ba9768a78675ae6bca039a20cdb908dc4654f7e5333d15d0d1f3eb9c507ca8c7b6272c2740ffe181afc3343a8bf8193a61477de50174285571aa5fa9bb3fe941d18f10e47a33ad3711bcf33ea98f03dfe5e0c74471517e682699ccf94441404a1c4d0411ebaee0cbc65a02d4448ced9c23093bfbe8cde50552b41723df72e11e52b85445a9b40dac61462c6b062e338a8437119f00d3152e82a08c0043475056897608eeabceb98c983f2bd6850ef381951f06d15b024202ffed639de06a4ed5e6248d2193b39610a6601455a2705a950017b184129a759a52a6380181b19b1351ab7b15d400392ea0c50fd12545c010138b91a90f7f81ce6d15a79181b859ea51562b31c9ce25a6148cb4c529e26bd847ac00bfc125e03648c114527193f27a1f56280d844863cc377d1e1c34581573783c909695bf3b35a8820f64e6d721b44d1c2054411a3d93c6b9f4e7608ed0157de20cba086c2d1a3cf615e18cb5036545016dd2304f6e7c26bb3833cb8083cc9e7643bcf0f155d16eae4d5157549c1eea296d900782850fbe710a958363ad209ac4eed59425c5605438871b546d349394dfe69e2cc759fb0470c50655fa6e00bc2f6b8900f09780a8a00b0bb9524c76a92519e6f5a22c2a294f82afcb19d72e3893c1a40fe63ebeb121bbf8b161f37b1bb976d61002a526e60c460b2416ad198641ebca090107a100db594095a25854e8e2b16773bb811c4f5ad074188802d679c13c897b317049cc54711d32190e04c3cc615f89c94ce07015e5a1a86b4f670275a662c26f3528907c69b6e9895932461db5060fedd3010ca2cea2caf8079c0543fc47c252d49d899c27469dac54156361a86342e1321aec856b743500de5fff0559c2108533cf325fccd6ec664d8a9bd83a38f3c7c466c6d6de8b1f9401a439980e022f3a0e794dbfdb05d2a2836f3909e898ca6ed39cd08ab0a49d9761868774a7356e02ab00594d14305b91bdf83f3d1a19226da1b46a4d9e428cd2cfe45f1033254f48aeba10d7ae3f4655d4c9ce970a51fa063156874e5e6d0213b4dfaeb0a2e704e99e8534b5f950f3b0143d7bad1523f2b258916b27d46e4a3288f4e7dc44e7caf3da7a91d48000c4d151c836943bf6fd93ce93b8b404b51085bdd2e1affdab559b3020c660f9244217659c4f1065d15442c60b079f6d3ce4687866ba94993351a1b1ba978ed2f800e114e6e63e2668b8793177b998218a830ead987ae63b4684fe1cdf7cf66d7e1b72a9d2546c80670a6d71920098149c9ae8a9d97082cb40250f4df591c0a84aaec5f55931c1a8ce4b87eadfc515e68edf5cd8609d7a59d1281777ef214ca9555a449d0db98b3b312759ddcabb1f205f5b1f98003892d3415bd486562b76277d24893dc8d802173fcec3fff7658a7e7977a1710629c34268ec17690236bbfc80dbbc83add9483a711ec02d3c14ac3446d42ea55ae244686815735751cb9a5c577ef5364c9949e097ac2d92fc86ac60b5ba37b1fb0fd79388013e0cfdcda6cdcf38f5effa85d37f667871d874e36728fe399851c52e22dd2d378649b1955f663d0da161ad5039ea5fd344bc5d7ac113574d660190efd44b3584e41c26f36bb4070db8fbeede596f996ba735866d06190b617530d5c79e0137400e4841d7293b9261563dedbe0720f36626352f9082542556f4423674a09d7281b0e6ccba1684e9d71567dc34353f34d5fe32fe71c0705fb95d9e2c73e79adbd508444aab7c91d386259b3329e388293f46e8dae9cd17c55a2c7ac47ccf6ac12ecdd6706b5513235cd005b69cf61a2983b3e3c3d39639f229068c1993f0baf3a1b59d1c79dee954532d43efcd08992333781ac4a6e5bc52ad2b078a2b1231df4a79c90803342d57d18e9bf314afb507abff5376842690edc4aed190684c1e0f31f7d084e681eada4044007b4ad7cf29bf247c9c04c1981d9ffcd38c4cb8125286ae448f4fdb6e1f041d0ef49c5ccf2d9c55868b8e93aff4209486832624a2772629c1c44fe3e43e87802589afc700198672c011c4927338ad23e2a071fa31e99a7c2c64fba18f61510a8592eba4e02554de3fc15a3f5fcba8413ebd33e2025ae82458aa3556c87be12b517210d504fe194cf1c4c2eebd02ed7d77c0dac09886d08e993470dfd8406e392e28584e80ff849c582204f1c7a3f6fcc3105f08693bb32fff78d454fc7f52589fabbf9473259e14785f8d1b4b25ffe8c7a6a9cfdcabc126c45b80e8c59b1665463db00280aa82c2f1988a76b187b70d15bea98e52990ab010eb62736a4820a6c48aa10176968202b800a2d88e0c072d2b05f53bde30212afe459202f1537c789e620b94f1429bfbe24f0b0b503017f7ad36969cc414f48c40b4b0c8867a2a9317eab2fefd085bd97682e02d4bd5c41fad825b011237037edd0b00b41594d49d00341b4119e7fb526eaa41652950e3fc62be0055408503370b426d67d84f19fc80a28a3eccfb59b018399946185bca420abb02be58bea607c2eba5f0d86a5d41769ed1387ae640259607ca560ef02536c37b13f8fed30425881bd76660ee798fa23d068c2e81fa291dc4e64a20604a77d2ec280100367b7847434f441d1f8ab6f38c82ecfde69c889780837ba4d38017588d3bf76f1cd8be40f97d73c7cbc6ee4f507a3cbfad359a0c06cfe052792ec1058c781298fece7c20fb47d56e9abb008ce9ab670ed06190b564706571aa47f004b7b66a3036dc50fa9388deabeee68bc125a436f410f71bfc762788abb1c0e3195c3f884bf4a10b5cdf53ec9e7365fb23a4a51ec55c8ab50657da42b8f52979bd32b82486b85eed5b6c1d2e59f3d0a90783cb0a13290089efbee6e18038e08e6851ec1250d7815ccaba2937db27ee2451941042a92d6414e5821219065352a5640bd1f1fbdfe65ad08ea81bbdd0fbfc2c203b078acea13a41347413671b23ec4c3850d402411bc141f0342378928ab5e941c4001390e6c26725b904dda62095d507ed890639ee4880129c4a97cb0125c76f8a02bce6ac9de7c9958cf93126d03c41610de46616930e4aed5cdd1316d9e758c3d5c9ba878894259c64a06057171ec44b60a14257470a8e7c5ec38b03e95a8d0974fac6862731f8266b5aa117a2a49104d176256c1c5645f586943735a9ab630170beff80449970162e6f941010ee410f896009071e7f65569a2ea4fbecd2ba0458d01fdfe8cec1b29789b0feda6c9a1bedb3c6378e46718b56afb424885791415ed2577085fec5a09fbb84c7f5fbb8bc1e82c179272e245cc7dd5615c70c5056e8a131e453de11d612d3b381b445c4e480363420f91c478853b48a4213c802c0b9da20b457c706e5f4442f014935248ce2fd054820cb89739c640985140e6364a666e57727407c261bf19eb6364391d4bd2f75643d747ffd8591e9726c4fbf9bb9185264851b62b50bac7ccfa72ffbf6c092e0df8b144ea164f4d8ea661434a8f06f120515187557c0119f4a79ab11d5567fb52e4e4f819d26fa3b84ec5890a4f36dd71888c15a1577a50c98580bbe891a0c61af6bb3ba2b01421b7443f5db0be300f13f876246b8e0200d9e2e956760e73e703712f0dff28ddd5c92175ec5a2ef48b990de6a385ed02ebaeab1d617b8883268e3706231f2e598d2d61bd9664e2797733d67e253a412515c102366e09d6c223a9331ba71068e3b1655d011edf3698fffe306179867e725b2fabe78263ec417521ea71ac4d8bc65a517c3a08305dbe1f1e4026a0d6f748a2d2240d8f12d9fe9673ac02440850aad4e490293eb84a94302815caf5cf4b8bb13ecca747a432c6369078e692dcecbf2416d107d134d6885fc0ebaf569ba3b2b5f80f25fe3dabc627aa8ef46394932142436bf5bcd480243d3d2cea49938710179b119dc00199e646f5165c42aa3666ded4bda742fb11583ccbf91e1130b74efd2319306a5f7c12d77ee05556402bc53d74840e0fc739a20f721303dd11a0606289b4592a14ca1bbfcdefd2b3b6821b39830d7b53c7cb0655ffa8e21104dd3d0e7983c1a3449a6402a79702c4c3c4d9bf3110e8b0026e22d6150152e12c6edc478a39ca4aa48c6895db542131f080322dfbf25e4e1c9d96121fd7ba23932c698df6363fbc4780f08ebb33fad1183bdbcf2a8b8406924ed8a14c143e642181c15a3251df4632b6982c77f4325f0456c2b3ef52e6af9346447dd1c2eca3111600465651cf4214bfe6c299f9a5a9ec232f3a9b28881d6f536264754b3eebe63be6b334ef08560079ed2be661eabef6f7cdad54a149693b38d9111a462ee99728fe566d934d7c48c336ad67f6a5ae249762a32882cc30709bbabd95fecd4f2d8eda08f12c172bda397ce1ceeaacde6221524dc957d74ffb11a77b5a5098c3bfeb0d00537e1ae807e3f65c2dbdf2669255362a497c933d24b2173c59e77575f5b08007500331caf099428f81d31293da052a16cdea7bae839a255973cac7858f670e961cd8395c7951e171e163c5b7ab8f46ce1c9cad345cf2b8f563cad3dc3c58396189800b97f95701117cb33aaa63c5da4b653f5471e34cc5e8483b144b011a23b7214704a3511f25e24a4fb95ae7d08fcc79190f48032bb71b8d248c50ad48fa8e01aad67e9495ce8e33d74c85c4812826ad8ebf021cbe297501404e3122c77fd366241cd1a9194ec627d101236de47b6bac0e2b0c1b6d5f9c605c96d358a4d6c979006a8d4f7f3082d17518172383d2b9365e5bf6b9510856dd440187d08d683430f13a04f2578f0fc932398c95bd76c969488de17206ee0915ca865cf4fbc53706c474199282d25070da852c1417a10f6b2d8e42f82deb0d180025c60ee58095db854f347a500607902ddde4ae13e8d3e8ffaa3ad9609aeb5a1e7b81a0da496cdcae384de07827d25c03fbd5d53f122de668e3cea2d69a60be6e870a0cc661c853f1e943ace7fd58c488abf549b6d6a0a2554d250debc1f88fd0589a89d3fe22ea87fc81243466c96d25107eb0a492c49d53cf846a563e11fede4d9c762a0a91da78ee584ba280a9397355f3f77a5c897ca8eaa1e10d5d120411527fb3766f74a48c18ce188cb0cfd8e1223d7b51b4b4e918e3d75c3b621f06c9bc26912c9925ce74acaed9d38f6c27c10a2081f80a5916037058542fdd60809c227bb3c0767a3eaf620e94029260af8994bc809a1db0dcd6bb73f2c6fdd9f9a958461e172bfdd6952fc0ff9674e8e95895188ec71f9627312fcd21a7402b030a94c3c607c3452c747807eaf5977991427f4d75eeefd6fe8d480685e0fd4bc9b6cb37d9c73d2ddd1a3530625488ac66759665b9dfa3b3392e3021b66a20336a93410237764eb881ca8a570adf16841d2152a4aa88c8e306ba6921de2af040afff8b22168b2083cab958189e20bb821d2bb23c74a810a8fbd52ea34962e99b717bf8c45229a0c0e65d26a1b6d681c5099bf79e76bf3a4dd159d2e9b84787845cae0059bdbcd90a5e2dcc2358af035d7a8baea1a4d1e8c526e44980b9d6ba421a3b796f283a5c8712f6b6ee72a42d7a88584c8e342884d5b2b51126808d573178244945432d7e943d69474e4aa208f1d82dda5090aa34a8a48dde9c6e1945722aba4e947a9e9cd77d658637e50a284b781e226a9508807ca74a022819485cbe66e7522a951a4116c1f1bf7618a535103d30d1e8df0feebde3602c461dc9b89e3006231b00b3749f42a3923371e1760a0cd024d39386cb3599685048f21250ae5f0cc428c65cc72a46d59dc488da6cc816260ddc322d3bbc8233b8b6c27c313f2214d8bbf16c13944a8f9f10dfd51f3653f9604cf024fcffebeccd167337011eb9858c0d21a4c569b870a90c042014492b29740a91e8afa3b01a76a76222aeb193413a569f79815818048a24699818cf3013f502085bb13352525e74f06443acafc42ca17f95f6e43cc32340017352092e0ac2044a1f3cd8d0d88543b8968569a4532cc471388247651308fa9cb329465655e8d379852dc2aaa34143584953267d6aea0d64f888a2c0a1d2a65b629ab2c77f8de6eafd212cab0f591a3d3d53bb1ccb90915988e68ecc68a7bbd991f6e8ba56f08ea08bfbeac4372cb5a56caa831c1750ac9696dde6ca445134a4c6bc8d895133d26501721d70552a00d509ff5867d91e53d547b0225677b4721315106cb058a8ca869a38d4da0cbf293869a4183b226108ae874876cc62e2878ce387661f312220a5e0f6a5cec489fba5781ef7002cdd61748b4c4db0e6d8c191c55413d51583dceaf4554c84c5b860224601f4ccd25dcacb03710dc48db93531f4438c10066e51afb90cc2ad456830d9d763f56b3d67feb6e3e15339a830e68e333e347f1d819c9dff720783db1cfc82d5771b47176dae254d8c59a69e136c7f05222839c8bf0e9bebdfda5fc0808d5b06501fcf1d79130d2b2fd4cf71beb601e3e4d70f2419f830b23d67a7d898156b1a073473033d7f7e1c046e1fc5c914405f6c1f0813ba45710e8c2483e39d7b5857b97d630669a8305db0ad0552828c398dd0b7e9944acb4bd21b8e4f32d8c59179430f3e00188f649136f07d2eac6ee911298cc6d8432311f837a61d2ab330963b6cb34b34d228acba683d0d25cfd60328f42209d2529bf7793a277aeda892bbd50fb2660cdd3d5344096d2094895455f211f73b023399e66920412d528337843357d9f9e00ecd5a678e573602c4b021f16144c9040e227a18a6594ec600b12173cc9d8d68b933de3513155506a2c6f7bc43bdf2c3c89d616ec6da0b7c1d4b3dcb070430fd998a6e13e423f196003cbd1313c6e9969d89a86d16e58dd2c741abbc3e272846afd78b9b506ba0ee6881a5a80d0a6e9825589a182df8f99d8cec7eabc943b1e3876a3bc768ff9f683a0bac17e396225477007c5f4d742b85dd56d172c2a9756cf01e181bb12eaf25e25ed5e9c006829975938626d1df80d4f7b2b904021868ab9218dcce22088198d46d030b312d0a323c8ed4b39ca2fd7bfd48628c2e299909a8f71163076650cc8d5ecee7e65d8ce0410406a48bddea4f6ae046845ddbe364c0d9de9864f954a93b0f5beb8b558a8c9eb75f5d48201db0c3c130469be0a3b4c312d6fbd62072456a4672212b5114ed758cd7f88dbab802b67a5ac6498336b47e021dab971b7f7f31da629462f5179fe5611f1f07e97df6abe3281206d66d1ff2adf961db1dda6b00d51c2758900ad2b4356abad1c492f0bfaef8455d4012cb97af93ab06b59cdb08243389d884d52ff9b12157160fac7bebc0f3b5148911da29b97601a0c44d0206aa95c91e1d9d63e437f6644a6a9d49e3ac38b6b9356e823c38e48f9be4028c5442460692eae35bd392c52fc50a3ead1611a2c20c2052a5654eb090f8e53de741d23a320c0f6d6e8a743add5583213d69c3e81bd138c5e10ce091e0ddb21360be0f6381ac6e1a88c25975dba2c9987aca3caa13e4c8c35f3b1bd1e60ddcff3fd2c4044a8aab070a97935726ad0931a376911db5e0573fa894711e6d87f6ba4898aebfb255bd7f777053a04351836e3dded174194c2037d43acd996074174bf1380c0a454bb1d8af2155456c58cea4283357b530a3c7de7817f6b6003593b819bf209d7e0dbea5d0551a0f89a808d3fd6f71304bf9fb0773cce52108f87fb036d3d9fc980843b5892937c2d8e1583efbe72f55530bd84af02a8efed061e7062ed5520aa2cfcf94326ef6d19499d06e4c3c90f3bd49cc3cb5a241c86de51023e2c42ce80573543bf304c125282d80af57fdbab2c77b9ee9a45f79060999362556a4a194dbf9036c6f9bf0eaee765ef05bab27a3e39f2af712d7da883649550cc47629c2684f015e0e7accc4548e182c2cc6fc1a7c3c14edd6012c6f70ff8c7386b00048c9eef376e544035277c8a946ed749db6d27c8571c8df192ca90accc417fb74128bffaf970011b2f782bc51786dc99e766c739afdb2a8d6c27356c26d3454cd534724d74adbf5dfa9785d7a85e93fc994d67295ff9761a91f3231debc8a52bc2c73d4d8ee43bba0ba07e574d373211b46b63e48c84f8f318245aae4e2920e38e5a1e50eda587cf6e4848a76b917b527bc2b0e690522b9c7e93844202b212fea6234466a5d65c8fa777b26c63d4d43442cb8c9b8c3e3800d77d8071a463ec400e39424e97201635d98d80a92d3fa976344a83ce530dcdaa233c5082fcc88650e0ef0d5cdb31bd308ee4c144d409f7cd2efc48e1d8cfc6f8f1af62d7ab3de8092c31cd0ba84ee7a87826a8fe23bc6067817728fe6132c027a74380280dc9c638ad7bb342da3f455608149e1681fd8818935d4814761162eeade419c7bf4e535472bcadac5b34248e39a783b93f1c889131915bed8dea997b9825c91f28a678eddc6131808eee37d13d25e5da8a9d026769267e0e8147076de0540cd218eaa3083a299ab18a3f15814a341b1943c841a69aa0431a25c8443b9bea529695ec89a8cd43b3e1a1cfdc2f2a2ea9f845cd2b35ce8f21b051fcee03604a9d33190542f5247438fa7273852c46246bccce090b3ed9d9123898d734c2542dc7a6fdf6ed635a7ece7b9a08901568af0eee93a667516f06d0e1fa80509794006629be9fd3441038d86676553731ac9b066b9c6de9ae591baf9ac1392216cdc55663b2b6ba493fe945f65978926a1cd791633c718fc3e8d17cd392ae8b7e3ec193fed8caec5760deff158023608142d570a392581b8c9ba1164e490c1680ab01f6494fc7ac579b5a82e393865d68f2c267637b2c6513c1432455180ea88aa552b9617d6f4569255a25d6c850fe3b843caea8aa7e11c689ab5a033478ea1235c3a5932b99a9b73980e0d637459c95c6ee970e564ce14c55f796a52aa0fe49c5169dc1e2100ea66746023ddf01b14d28e86ba7b68a35952c13b8a2f7f11abc2f5daa9635c2e02fd7ce37867c9026b50580682ba2e3094ea2c34243bf1f5321fbe5d69d406598a787030d5cdded9b92a0cb695b036b1f015b27859c15ebb92703388c8c969f40024aa11caf6c23389dce45e52b69b4bca4b877135b3e128251ea1e869f6f3631d12256297aefc96cd26a53c38a66da5c2c175c6f42572e64bc6d510d3157b155e183b48a3944a57b455fab07af064275c2b765a4666e817e98b4554e4e44f1a1ae769f0a5e5fb72fe0416bb98c086b9121be075106ae9d3bd490ff4f91cc91c4ac2d7a4119c2d2a2e0f4d243a72779e956660836c000cfa87f48d22dd3384047c7f6d62e6e179fa0cdbed2d75a317e466c8df100a3b314358c0d4521e81b6699e5021cc406ac5c659668df006c3f9923ac5953e52b1253023ef7b80b4b1c6f8860ae0d9630a62a2c02f80521fd9c9a2b7ee50a75dc9af0dabb6026e187aa328d8e5ab22525c9b026509204d937a9d680c45f1a3ce28ad18681708f01efe0116b4f6578db617886f5988efc7f0eadac51e019a20348f67160c7b9c83a2010485ea1de9d18d3ca2837c40ac6d9273171ccc5a81089c68526d9f90507b267b1dc5755d995e36590ad07b57f1d57b829fe0e6d4ebed22dfb177142d8b13084442a8950d3086256c3040d346c6acee5b6d46b35479c83432f19745df1475ffe2394d73193f28f2097fdea0902d56498220c164e8500d142a5d9c2ca075ceb6bc638a76d29d14bf2119c383fc187bc40ff89ffdedb9534c87351c01c2ea544dae76a85a270d89dddc0b80643d30a920d86347f1853a1a7583b8d90d147f36d325a4057c2b43c90969caa3b17e49b09be88af6f0214c91609392c74b4e8f5274fe8f1e3c816142f9d4621d69a9e00c55c0f05fc08f3c97eec4f92981c84afa7e29e00d898dc9f17e5783e0a0ce64d289e30101a9c441a36535ff84c69d78a955fa8556cb6a068e71134973c2aa952f9aa16e8f3a8565ac530695519c4108cd2eed574feeec6fd2e20f674520c61ff3b8dc2436d0fe2763c8621b8f2575f06ac51f4480c599d7b4ffa2fe7fbfc32b34147d4781c3c178465168e9606eaeb10ca0427b2c50791c07077403e1239a0f3b039746f9c77384a0cd802ed1324fb1b587f7bba8bec47fdc0db8b41b5c403c65fb56a91abf6926814b7e03309eb650af4ca8a25c03673716a42ca2a4d6c6080831c11d3c61109a014508ec6074043422cb69f41a6dbbd35bd30bee0072482487f8e47be5c59792576e2def6a475a8d7530ef4da8b4e89ba8a1eec340eb32f000195b00ae4c01e1eba8961e05fe17403bf1224c223fe8de23261462393f202b2e7ea189c308a4cdb7c6960f3fe72c8e3f0e93049057642336171e9ed9f815e891114981b4f22fcf54e31b746a968501088aeca261ec16ee5dea80cde0486cc5a27e39315b64de4b5b866bda216898ede07020566bb2b2827aa44645f6e4d5ab387c0c33a1c453c96142c59641985562d88e2d35e8add8944e77180806a9cafedb35671c700681ac90366c155fee9c7dacd984090b17696bf97076de23c032685125d05036ea002ba31ec0e5d2a002440843390004dcb2a8367632f7555055d2edc0dba24f3c814451c24cd550688f5d64b1927047a12182da4fb6f2e0e8a0b7e288655455c410a7c1576fc1270800068adf8e5c5a7c66381e66963c0e50e56fa01dc07bb18c62c286c4705b19454208edb0e4304f889c87f48c906a53b6555a8013542ef1f6d5a039013540810060dbc8b7e9d217fdfb73bcd3f296d3eba0c3408fc876caed952b5f25e7d599936c19875c104c845033b3dbd22f544c5d28eace860586008795d90a81035ed66c671dd4ce5113595d914b9196d6ae2a3299c16c429c1fb4de0f8d2d08a50917ed3b4922face40552627813c47d1b2daf0bae1c9ccf948ac1132ad3d2c95fcc2cdc3223cc8a0d0a03e4196e5cdaca3545d50321af1e0a84d256cd699f0104a136a0036eee3f58625fdc0cf8ce03c256a7a493eb017357985aa94f00f2d1530d07451e5d5d94deaf500cc803c9b96c9dc697d17d1429dc4645353dd68d33a103ad22098817f66e47616f9cfaec83f388f61a857789dd14ba26ecb39479007afa647dcfa5fd28cf9bf6127766186b528c2bec9b79c7312d086183e82b6f9220dc2a9ebbe092e80740b9056aa937618d28fdf3f04ec0139d0f463c6b8646d73c0a9f1ee1e3dc0041a165b05fc3c5449eb7694471efaa8249e6dc87e25417f4ca58dcdfdd1f095b8e545c297e923184869c26748ab53e4f68067237ca9e787a7c3252d1a15f9dc0c773c9d5e84472c0e10ccf947ae416403c7a9b11729d7a487ea7ddc208f25914405f40a0c473841f5fab99e0f3952849cf054be2d097a01fe661ae11e34befc5100ca5c0d5288687f241f89cbd031942706bf5d7c638f1203c52bbbb21eb979488e685b8e56b15b575376ae755202f6a215e0704640c38006369ee86f201f72016a67a05c4f470c4e27679993dc7c65988340b13605ba0164e44dfd7632c25588bfa9b5b5f5fefb3ec244c9fe77cf9d59883845f389f6647422a82a6c46b1427c1b9e356724c1133091d1209f7382050d22121e4cc009ae0b4604471c5807d81410a0399a48de7f02043ec2f12a78a752e98c40f60d9a3d757edf60f32538c0d61329150c7ad78ff4ce5e5844286f27f40498038845a2eb5691bdba66be9fad7d6388bf731ef6fbd5ff7bee65b19cbfbd6f4135efc8b42dca7b6d190a985cc9ff7f8ea2b96e43e94abb84213b8cd8c740ede041b1978ea0825f3dc802514d50a0ec780d7d924aa50ce93b2606ce937cc3a02aad5122029a5e390554bab2932a53eaef6e4d2bb29d446a73ae8e86fb2146b4f36ac16bd9bda8cda191eafb0f69fcdd7ca44d896f3d3b3da131a33c0f6a17a613f8652e2fbf49f040dd388708eb0df2fb0730e64600ad787b30b88f1e067cb8c412b8a69e3fe6d77761c9998d6f313aad94462ded0056bab7f27b0d91abc6c6fa7590a1918f004e89f9982c4f0201cdc4214863fa47335c02682885bd040bf5fd3cb33e6f31650aece983a8f133aa10218aebeb1da459fe0801f9f060e3e44b9649f48d45783014bd700446b7a845e4c52a0b99c7110223c53d203e1ffd2795e88085e6e410c187013ae5037501a5a4241c9b9702b887d9da298b0cd41607e3c41b553945cfea4f5726e9ed4c4a09435ca9ae762b7cda757d829448a3c88a52d449f0cc21d01886850b5d21e0346279afee6fafa6570bcbc82e63b6bfd87c695d8a9367605cbc59b79f1bb01b6b71df3525b003c9861144773246c47c206de23f4e29e9e7032ace13dee71ca0b17d8ca1ba8505b004aaef36079dc9ac94db01c29be4813106d47a466b6fb98fda13020b09e831216d73716d3e42397f49be71e3484cbb9fe2f405915acff400980abdc84d07035ba04d0236d8ee290bfb4db65e60db2de85489d15ad4ba76e20469172b51dbd456367c32c382c7eaf3c0acdd5e0fb809d314b47a807b252d1dc5d82878526c5f9b6ffe441f9948944e4778274483ae54965dde15142af7cd7ef008095f2a10dab12033991b7a0b86b2783fae0e82a9a24f827c866e96a3f79bcc5fd752b2ff43004ac78630f1e44dd105657b891b0328b0dd6869dac7897e409d64cf115c5f4141f3dc3acdeee88a71a515ce9c637cee13af46d47ee1591530ebd244a15afb0866eaee5c59486f9611b88f8602ffc11e5e6246433caaa95c0ffacdeeb52ddefccdbcf77eb6a54c843a566ba1ca34ec4a0526b4365ff7cc06c12875a01b172ac470c110eacf199c6e5845ce566422937682e8b3a0c9c4b4062ccabb4808d7201a05a2e1acc8fb3523c3125cd5e8e85b32a065d39179f8b097a595c34dab3c1822baddc5b83c474efe0065e8893fbd34e95c868065b7fcb3e5b41f53cdc9655d511190ed720525a286345f09becab3d7894095b4252214cce11be29a7f7e17a18810275a752bb4a8dd5d883f4902a7d5fc9147d448c292c5ee0f0f318f78a3fdcf7ac099037ff8a0277a08ae078c4a7b286c04ba1fc47ca5d1750e58312c226d5cdaea2dbb69c2e357f279b73711d843c4da2d1a934f9580cdc15b6b39f6080ed4038aa135687e67513560a33327ea58594b4a4348bae73a460311f15cece232f7515624107171429aa529cca99ac9958bfec5604ed3cf0a603ae07a6e7c2482d63e77b42a5a5816ccd6ca53b50ad26a4f17a7ebf058a4ab066581b10e5118e244194619729570fb5e7cb585eac51a168ba978e86d827ddb89845da8e9b83590ebd0b0eeb9119e898e0a1272a0d84d4ea515cc6ece97905be6a99d226e6197203ac2d915c6865eef54fe9608d5e6b67aa7a561733291d0a0f84993c329a98ff5848ac583b03852aa3f71565be1cda33403c9c1011a2d76ebea21eb4be711f5e82dae1f703aafc334dc18942f3a99de833b22b2b34c389628c8adf6590ff3052a2c378aba895f50021544f9360c9640b8042348d615d4664705e7f00e29827f648e697ebba1c15011053be5f4ee352346cc5fcf5db80849914e4258e621e4241fe205d282a0302518e46d440176128f6c39104a7f4691cb98828e6eefacc704356056990118a64a87342c4b4fa71746c685d6700da712a5f34a87b7fccb97dafcc7b2d3e083064ba1a6884dfac20d7eda28508c89f199ab6288540f001f284f2940b3aa29a1fae9b91608dd566439a8b4bfd4098a2065d1bd6e3464af1a40f0c3679634823fc921491f7308877d9784818b603e188ec3a3010b20489ba4fb7576d7335625b822de4ced7933614565ea9e0ea4b4738b21b624a30e4c661aa3bf9f915a3c8b9c1c0811c2b451593880b43eb352818b250eb4ddc3a27325e5e7862ac49b3b6bc97cd9af209a12bde26f218895f4cd82d76c15517fa39b066050fd84b54b8c04a9e2c523c6624a2a35b1e1aa30961cd883fe5ff60c979c44237282e6083c4ef77e9d503846c015a07fd355c708aa4a374eb06c858190d9c5b0c9402757b7b85befca1ddd200ea9458a4e13b81134ca0617a80712ed4adb95bcaf7488ea80906cb7224476a749adcc8fe690a107431ba3a292bfee51bd52cd9f4ece27f5fff97fcbd899469935812630349033d0333489ca6850cddcd56146e415aa87e484581b5d49435cadc212f689b4021406e569f25de6777777777f7f1e8c874f4718c3a561dafcc59d350eda865958e1ac040502e608708ce122217234158ef656c23196c809e16970e26285c8daae4f314167477777777d726dddddd583aa68d3c773ed0ee19d6962cc6a46a5509b7aa4c3283991e9fae1e17477235894b4404ae9e0d1e7362fd52f2d025aa7fbeff8fd51521e2ffffffd1fa5305079110c0c05af27302ab229918224300b0b2d8e06c7276027bcbb6adb56dadb53378a58dd4f1fd8041d63083c8cccc5c0322350c893fbbbb2b209dc21c0f224811694184b303aaab1e09af644c342e747747c97a19ab0364e90628986410b70b4ab8b14b2201522b8b99192583f6ff1f4c49a49a5ffa07fff7ff1855ad2cbd5fad1f285fafa2df20b50f98924202535258c447da2a2405e5791c1676ef112ea3a20b1a4a645654a3e09190646a42ae1f587785f28ab1558b5eec202439e99abde071d0ff7fe3e1fde891fe475941e9ff3bf992d0962e68e9ee06d2f9ef0c11261abb972844cba0fc3f3168dac8f3ffffa0ce944cc9859f9999cb476923a3aaaeec8d4beb82a93bf92f17df6f2ebf9f562b2f044bd8bd0d4cbb85417a6977f7bdbde46254efedeeee6eb4752a3fb976777788a8d246565dad84d0625beab8e14abbccd0dd374c0d6354812326929680266c744a284316321ae082cfccccccccbc52e4c748465a080b8e4e06958357a33ce59bbbbbdb360b226b67a4dd4dd26a05c1b066884dd2649a1a96b64a2193ce9942d4537432410a9bfdecb6cdcc2cb455dac8165c4ec76b161b3a18520a4a1be3362764e7799ea7f5299263e76148949f0accf15d1c6a24c7a8c849ed3b68659962c4b337231dda928e9613495dc920440b8c2da2d550c5a1a2ea2c6f38b68ab44cd4263181527be944886092411c343aefa49c145605f0bcf7c91763547292f9e9a9378e68d8e0d10d09f79a3282465a0e92708874df4b76198976f8947677f30693058d83f216256bd833a6c0071c0670299e642e18ea21ac444b564ed025231c66310d4944a61a411cf6fcffffffaf848007062f48104b87476b486b2bc6a403cacccc2f2c263a19131719bc26e0536c54011c3b9bffff312fa58d9c396968bb945e69e3989dd246a61bb89032dbb3da90a94846222a7477dfb6512323ca0b144c564e1542614c03bc1e4d846496546cf1928aaeeeae65c9642933b355da2a7260c491c4d5d0081404e426a6de84904045728b63cd77fecbff10d2ffff0f676fbf1ccd76c1ceff7fd9fb1f82c8a57fa7982633f34b94d246bedc3accd894da93ff3fcb8a166bffffff519356abc5d25adbdddd6d518e62666666d304e299c2242c5256a9f5713e12740fbaefedeebe4e4c8aa45c236965d9dddd35d345438375ac5199b229aafc35f0c286881f40386ce839f140711ef168e1e0d57370fe655fdddd44a069234f2df47cbd1eec68316de4096566939a344003500a0d51644900077681053024a029014d5a6d86967210425ef07741bc6829c69f45a4f498a8890561ffffffbfe57ff6e6eeeeeeeefe80e26929a783898dcd8f4a04c1da1900606b1720e4e2088383c106403e86ba13301332772909e85861070c27a8e1111715207a0c57d07a6a39b59299997d67bf6d9724aa4a1b79a5750d24a2bccc5c43099aff3c9e90d1034734e2e7a1f210aa5012babbfb393bab430818b9a1953513c2fc0ea435bbf7af455034832821c4d18c135431844b7ab569427974c334e1b4d65a6b81f84a1bf90306894523b300393233194d25592e76feffff41faffb7c04dd1a846854f8e0c329c98feff7f6b65847090629ab5a1a8d24656fd36749562ded01811a36946efed464f73f2bbbbbb59466cfd43de9db27b7347efed69eb002aa2ab1cdd9b1b4277b72e25917a7669b72e55726bb5a042abd957111e356630071198b53a52dcfc000a259a27333b0d98ea0e240c3aa8c3854279fb213564419b0afa656666c66d9536b20597d3590d1f78d6c63081b5c18d0a164a3ab2549c40435a0e8cc92a44a451e4d904e1a83978e60d89c50ba3221a0b943095d8a0c6dd00a9211fd659a3c866cce4a118989999a97aa58ddcf9193ab2155031591bd3395f2ff367dac893678247a29a280324f0104c6265638510a33a1ce26045d0cccc1c9cda4a998f1c3cee6243b666ff7f32d8b593fe5be96b9cd0491f800cffffcae4ff95621ca5bf950924fd2cbda945005bf23089483104d7b352225af275f5526ea6ffdff2ffffb8e2ff4f2bbbbb3b08f7a01cad435117d4cd930e1d4455d8631831be33255aa3a2ddddb1b6f97f962b9fb546df6f4601cf9fcccc1c6357dac8dececfd011d34a0c1f13a4dd40aefbff0fcc0c7b40d58d0f397c66666666e60a82f85a88d2909023119725304122c47b8f449523127957a6c4848648ba38360ad4dca2596bc684624cbabb293063fcedd9c559df8b41edbeb7bbbbfb1a903a1743242f4beafcff65af9c9c6923cf9247fdad6518c9d2a46359d48c49ff3ea94aebee4e5a02a6ddcccc5c7b72bebb3b87f89f5d4b61d6e1d51d8e142d2b70816bf3558728597a10c1ed465690ffe8859ffc7777d3f84a1bf90306998586c86cd1b2bbbbbbfb3de7049a72ff7f8ffebf8622a3b567676068171484a2ca048c0caf54e96d56d13febee9e8012e2dfe8bd38eebeb7fbb004944d29962e5499314221943fd13ced9e7a4f3b4f3f484d55b5999999744c3cd38c40c33171cc4ddae88c14fe1fc9e927fd5fbb979b99d9c93a5927eb649d2eec8c297a0014e7eb12ef43edff7ff3e8559c3021656666268539c0e28caa9b605d6b9dc8b86daa7841828292910a4614258d29a964c4291dc1c1fe7b9586b9cf6aad4636835e4a1b3943b3eb5596a09d5acb102e66f040f239f66670688044d0a68996720a38159c224e15a78c53c7a9aca9adcbb551983d6d3700285071b5bc4061b5e3a91a6b70349cf2778003bcca5f4a06857a2905e599c5c3ddf73ea025466ec6d08c1ea1a90e339a019820c816dc42076566ce9918b29aea4005e545955a013bffffff7f0ba88913a7ac1f256084fcd65a2dde0fd1d41007981a5513a55e52028e50ae1c19f9e8288b7ad690a10c06ffbd4c925c4f1af0b078572d764005955c61800024374bdba22f2edad8ffff3fadbebcbcccbcd0bcec5e7a35074cd676acbb9b2641dadddd37b8d246e6cedb8d8e9682567b6fadf7d67b2d3333372ae375c1ebc662ebf684d7e793cf5823bb371edc09badbbcf1951b2b38781826f8ff0adddd6dfec2e633333333330b69145366e6aa522b33339260692389457b4362b496d98c290b004522490d8b1e5d2df5a9433b99e169a1d1ca96943c3a1a2928cf1bc9ac629eec8810eaa9da90a183a4cd4a6a24dc3be10238554b1d7a41b476d462d5995084c1b89892419897f42ffe26ca0fee86323e379fcccccccc42b25ac8564bb5b414aea5722da56b295e4be974dba82d14feff4cb5e83233b38e2123398c9caf17a9a3336de4b943a32a33f32c56394459d214a883f32ffbeaeecef1336de4994378369de8bd12eecd110425408b99696d089869e3d3d6b6b5a610955a3d449536b2eaeae6414b652986d70e3e948c565ed0be1a357370339949c260c10d43bfde15591906e6d70f5d6923793a3f7c293f7e2a3f801730f42b0238a0a04e0b51cfc7fce1a18bdddaee6e18066666e69e636923b3ac869ead169cd5e093b3f6b4ddddc223c6b49b56bba0eb63f776570df8f5e31f358b3395cacccc3d684a1bb9ebd90a7aeca8d4fe7f2517a6f4f7006c732a094f55f280d4efee6e24163ed2ee77dfd8bd95c982056ca1e5ffff1f66edacbc4f1f640e7cba7db4277383120724e7ffff3f21fdffdf8e8cfffffff7fe68041a3cb82439e65f1aa1d59ba6601536314db8a810171fba7ab462e46a6010b4600e394b00cfee6ed408446142992a23333305704426995fca32392298b62720fd101d39cc0ecc0fcc90c94202c8cc6ca34c9373ae70dee7ffffffff49eb29cacb0c0b14cdd9ddddff4e2d570c4ff45478f98c9036a43592511e18ac6bffff1e59ffffffff6f9637ab1c33f34cd6dd4da45d960db2fade5a8d4db7099425872e346492ae1f56504c414e43ea919d5a2442d923d2ee59eca54446ca2e4f623ce7abb5166d6205feffffffb31b126e5041b4c9185c4c2e46777677c3acedee9e41a8017461c0ee6e09ddb3e361594d48c47c0881871bdcf145d3469ebd996c879ebd1c4a5329ff7f3853dac821cd496ba295e56b57f6684dc69a69ce5434e6ff4b046d09a22d51b45600162ce16155d4940286111b9a7397febf07a0701d1d77258466ac967431966c804000c164ad317b8f1401f0e36972f5feffffff6d82a58d24168d2b3647bef0ffefeeeeffbfee81ee678a07494757070e4050b50810efc2f8ffbfc9718ae7bbbb5d8e4a1bc9e4236ac5a5ea6c2011fefff7de1b1b01eb000c902769c3918e4f9530828cac3faed6326a4b242daf62b5f0336de4f9b6166d618aa8cb6a7088c9ee8d55d37766e699cf3c9eff9fb4734c7fa21dd2fcff5f436935b3870f74104c5a2c46f350b9f9004e79a81180316842779b26cebc974a46752376ed0e4b6b052bcacb4a9299fe7002435044c3890ef1e5d5b1b49159f576b5d5526f58b80b1b04c0866f4893666666a5aa999403928aa8344cf807c70014231a58040004611c8af34066600314000815daacdcac401a8bc3615130180e030381501810008081c12000c3500c80d1204836491f709e65abdfdc288489dcbe7d003a896a4b760d92cd0b885298e5954d7083f682485a120483783d47c82044f95e0e11f6ab9517db7a5d786f22911a289c89044067cdce2d4334db0ffe6f5d06d177548eda6f918c6a046f2f921bc2a2543d42cb55b6c421ec3eb877b74513fc91d94724d4fe23b2bc02df7c67fec3ce250dc854646c6f589b06013b26820d727a13de591292ceb597ae8c42a92b735bcb6ed239a37c125d5e8b7c7f64750113b49399de5440f4ffd480ce20603e4e29712bc80f36702fcb965a5b30eb61225f1f3bed86740478ef85a4775b7581016eb308602e20c320219bae1edc5ff1eaa35c5b80438163bf0f6bb2430e2d554318103714bef6b3dce2298587bc9aecf109624ed4f0677db751935222498044b406d1583ad4c0b0b3ab45279d928375065229e1b88c6e8d3b4cd0d8be975792d25b10bb6fd75316a06b9805c8cec6f9b4d11d800da40614ff1e3012df4a4e81928ccb9371002cd14411c83d17e9d1b60697423608a9c3aa92ff0e76303f3aa411ee346b8d5533887a000b0389b76f428d292f7fab5337e657ac21a084f8654c4666eb9e4a6f895b50363a7fd7cf9608ecb81dfcdff5cb41a36ee136e4c43b482b208fc52507b1b8d556d5080ad0001ec3431923dc1d1e605eeb1db7cf66637d618d9660f8789e027738c414f64f6d233c572844a1ec0c5b010cea0771e40f44ae2312afc9ec028affda73c01f270fc84399ef8d9a0eebfb43ab1872c0dbb6ca0057390390f35bdcc0100c5c04eafc51b649030d539b1e31424b3361e6c08accd32804adbb60dc769f38f054efeba04fdfaa12cb8fa026d63a0c960ebe89878625de9906f4d4a4a71419aab0262f8ae92b70b01ddc62a1d25cc5f8399ace806d887c02c4469a8796ac278ae9456f8860056158224fd216866d0f2c048a6869f580a003b43c75b09c48fd73fccd0e21849b6509d09165073996efe2f6890a1d797358c7549d228eeaa04911eb5c1b20f74e7c6216ced37f8ecf2813af0069abd2411fe4c5978d1cadf695c2d39197d5279ed16616ac0096ec9f87b0160b606b004df429b4dd62d4b8dca7264cdb11ab391f026ec206e247b991114e852413a8c54827a956fb053a23b7c3c1b127527b09cdd42e02a1ee81a681ac3c9955fbc506af6f5fcc34ba2cd9f90c426e86550bad6fd2c66700c73f99166e66166fa22f3515dbea11ae62ed3d1cb601e8bb36ae4b0fd5087d3d32d8e83a9f98c42a922d5306c651a822733d86974a00fc1aa408f8dbf437f28058aaca73380bd039b80519afacb27b0dee9988ba873f298da7254da6687269c51a95ab6b43e35b1af6404a46fcb72acd758ed7d8cd93e6325d8bdb42aec9e281ee22de93eb5896a6772c0d7d11ff60c0ed68480f740a7ab2f345f2c13e95b414d703d98f647d10f4d35df96ac5ff74652dcc30715ee9ec747190ed0f5ec9941658c5d95179afb324ae86c4003813ba7c6d0230f6436640f1349d8ee0e435b51ff8d078a620296a6f9effbb85c19008ac96d93168a0ff395bb0d1df3a939921f237824a8583301c00cfaa018f7d5e1c284c1eb17cb9212b40c6c24acd8ec5746e0632198a9e71254132dc27f6858388f76c4c8603c0975c7b8e3cf0fa95131fe8ac1575b204d0c98084cfc986da314acc7f8f0f25d111fd9f782d783d0ae022a34e5ca058d29a834b8956c157ebf4c4d86a1ec4c02515807161b2f578ca6068542051fe8a1596188d3328c62557ef78e6ddc77cda202fd7b56aae17793db2d7415063a98184fd7299fd1e42d4421c6af4753e3b60c874d2cb503234228cd34db9e5c009c00ae49a2e358611082e7301b9df7feecf12f7daec17f2302eafb2958f08c30d084c09818142a948326751042ccd210e5dcfb5c595b1527e13939f2104fc2482a49f22bc629ca501d52c67ba7162a08503433ec603a032bbbbcd8ca9111bcb4d2de6d48c1c67143036fdb31d0d84fa5fcca8e82c08595d094a2acb16bbbda46c2689028dec572ac34c9f60070fc75b3e691a07c01dff2cac4499674c5b07f4c161651b4c3557d8c6c2723cf88f49b449586ec012d1224f346cfe82eda26ba6c20bc0920adede6006d020048d24c316ebc76395f7a1473e904f3936b5899ed735c01121c0b701dc4e769ad6c3f5051e0504fdf11f2b82c4812c3aa5618c0757fb2567516e38cf363bf658a6881d75df546e0e17d2be1c3d74cf6a0b9d7d68435be7665f6e4ade12e4541c32c24c8994543c00b2528f0da325dd7ae304497cf44d0b0065e625900ff39fd277334749fbbcf14359ead9bd4a2ad64824f1b7a3e93206003d22f233f0f68c395c454d380091515e3e219c2eae660de2254c7cfc3cdc68690d325889064f3d6086df728c889cf452adf2622a43847cbe169b7d4f11c50ae1b6dde0c6646a317f28dbf56602984dee72660aea99049cac28f2f061f67295624cef91ee65a244570ebf319a7ad7d26cfe9b9a410552ef552027dde3df731caa9cd7341f0d9e28b3778be05989fcacab2b3ffcb5962337d5d7d8336935965ae78db9af0d626cdf1b895c230013efa510653240e6d21b430e6618025b1ef0d0b09e8fe4ab91a979a357b29950b1ff84941d7b2190dfb88c3c6cf8a2f6fb823b05880494a9886df38c64c58135d822f3db06050998866ced55a527bada21e2ad2d088a0bc412a105b89c8d9368f3c78e3154c436e407710a70f7c2328a050ad06518be20c86d21a230ba5d5080a68360fa9b594c756814c4519b2de7aa42f79382e6e5000deccb6669cf1e4e1bf865e2dd1a181b238eabd55342ed02e2535c827d8746b0d7f19643731650008387b9b04d6a54296d13ac79459752d34e5a54c656b49ccb539bc22a0cf8055fc3de246f9fb3d1a65f6a03647237851f9cf357893fd450d1880b9c643d42a7b82b8d370a01922bc643e35e588110ba7fba29935c77ce3750f01c13c1b5c4e42885a5916f58e235d430254ad9d48df02aa214daa8dade837cba0853b826fa99934fa9791be222bb30aa71c8b5d78be5211fb085ccb3cb874778eb6a00fe60835b45fd6f12a60b3e1ab25d42419cc2c41eb15e31054dfd523547117aefc302e3fe41862ef70822f5d557207f068d643b22e9eaedb571ed58fd46cdd16cbd7693cd57da719c9104e8bdb301035e50745662eb3fb9f3bc5c334502abd12656f5f3bed4b51019718636f1d6c06a713251cae4e80da211902542cb546370b2038bf816fd2882f835ac2ae9bd205752905355be88e180bc49a9dd20f5e9e83a8147d5bec1930361bbeed50f0cd25b3981fb4e3ada36e3a4377cdc93004dc18ba2d621389a4476a956fd44508ce60c6d4aa97ca229055338e1db5ddbff6d2ed02fbb8e44f1c03e679908d78891fb22c96cecb1c3828ca43e053a934737145c2b758077043cf4c1859f8521edaafb847ee37de103f8740633a68f48c503aea1b2bc0fc24f2aa4ba1e91361bb33261ee98a4b03142ae9f6b1235e88e372c043b0a4e57e0caf3d87180ad4eb7947e0d20fa6a01a69b6b5cfea8e29f56481990dafe1b56dc4a4228ec314e54f30a6302ce15a186d1fc26abbc9ace436b5ccef42edde5fe5999a054eadaa1cb586ceb2e0168b46582228b85b0086662b461ae25bdce8f44161669f99038d924cd2cbed00889635e5c02fc18a8674409e9ad419539616bc9b411b92ebde20e22dde3a7312efc79428a00586ef0462f635a78b1beb7966479a0c6ca9b7cf8b79d3c1454e51730291aca67a9cd9357cb29c905f0e45afdf436ab7c6f11822f527a5fb7679c939a37a2155d45f30bdd5a3f563d6d06bb96693dc14f8e8930e6f680d28fc1e8ecbeed56bb1e42c9dd67c09db842b78c93cd148ec9265bd9421a2323804b42e8e3b817f4d0137e11f54a998ed9e3a4e2eaf5f0585ecebab5100a71c2489d819ff61b5a813fb03312f354435dd764f81fd055df049ed366733299010817241c37d20223723d2636d6ef86dd65699500fcd00714a7402051d353b938c462e89369e75ff714b1de606a074a06894e3e4bb141f876701a7c805d8c974294cb8450b08883d9046f5f655d57e95174713f6a20c0c9445c9b54f6b2cb72adb335b5472f72845c78bf87e73f4a3c23092856b5c8417a87549aeb794b6f85594504467f3d84fefe4eedaa0df199fad87aab0604fb2ea147a444edbf7a60070a9f2d07e0db0a129e9ecb96c287d38640dc7f32dd6afe1f8783f30636fa47792b3f32b9250aa4ce1c04c084c286498515b7e0f721a118f68ee8e0822fe58365d5ae0daa648631c5e0de0b60c55e053a0d480d4a690c2cf54aa1bede6bc97c9dd8ec40998a03ee8fd548d8cbfc5ab4c34903d29a7d9d654ca29b619290b5e4fe23f3db805341eaa4b5fdb8d39a8dcaf91248fdf7296e36ef45204742f52bd337bc107f24bacbcf8e1fa7d6055191c138fd32ac2540e9ee4f7567021e7b77cf43aa7980f9a01bf9a0ef44380b41899fb25f7b39d2ee3d4bb6fbf72028dc727a2386c38eb767a19b679de8f7e6d7b741e0bf27d4b4c692a11d28349ff0760e3ff5aca5bd335f210565a13d95d63d3ff9c7cf5032be24d83185a69030cf215e70cb700913fb01695f9e448f67b9e36a5545d760576686219be6a79467be9c70019127f842a9086b3c376ddac1c1ae720f4626a21c8faa937bb40753bc8154e406dcdb6ef58aa4b2ac975cf4644f9058853455e2103341fded1ca889da8c6d889656a1c44ca5c04ec99b2f343cd2947a178ba8a8cd736725a06fcbdf07e8d6bab1390a781390dfdf9a7fcd58997f92811ab1af2b50389f3a9fdd9b6898a5c58d3e7b59dded3ce2a6ed26736a2687feeac17b07b5bd8333c04adfb4b38fa9199658c4bd274291a4892210782cd37338099e3d15b4cff4eace78980582134b84ba4a054f59ad0cb617a0edaceb9ae90962ec403eb1cc50c5e5ff0d4a9b0f5b868a71d329e04b9da9e222c95875a28223f8efb33d708c07064de80cbe24a40f3beb2499955b6acea68f174d2ed067892f60ed132402389ddb5ea0a35683e2b9f7293a38190a65ce371d6ab8d69e9ed1fa8a0286058b1c9caaf9975b51255d85119b8e4e91d384f769a393a587a56f6868f0fe802c216c6536591544a22a232c5066cfc6854d6404a09f6a988def85dca18ec6516f490053c1c81e6ee925745f666cab0b11b3d6203e9aec699b0008498709132181e99dd8f4a85faf20503caf20823108eacd55e251d292e54d4a970d49e5fa455168eb9be00a00ed774594930dff33021c80e3b41ec0d9652d101a40d74fbf52f8ab226ed52c4f6a43245f15e96a09503afebfe293588cdadfec432892eaab7934a246d40aa3c0a095d1d387ae4dce567686364cd6cd06fd27537064f273fe6200a000a03364b240be04b2ce07d5f71a15197c1625b5615cd5ced3f4f21aada64d03a09ebec97f94771c950192d3c4906c04692454465da07528019eeade26bd689a1a7d3937b58c03c06135ccc9b883f7c08ddf8c68470a610b3a62a499eaad6067868e95433c08c3c2eb1123697f7b6a63d5a23cd8640bc3c1d82242fa81563a0d6fb8d489f0d8eef403fbe09995b782a224f853e131eb1a498184aca46e417aeb0832ee84d6e90d0885cf44f30661abb9026d14f95c933b334e0780e0d3f407463fdacc92529461a782af5cdf2cae11b05425eb9f283eed8dc2ced0991e40b196ced92885ee643305dcd3495d772a6640169323aff4dd1f4297ec2d97fc1f07d528539332886c5b0f5041b3f837c772debd0ea53fd8bf2b14166abb63f0b219372ad59cc54dfd921b29bd702c6ce50b316c362a2690427267428e988a5fbdfe4d318fcef35d90c44799c621b39dfcf888d2aec3e49a42c203ca4d831a478cf4e9782e4da5607da92c5c2901097a4c80145573180ee7f849082a2c8c3eaafc6583f50a0da3193f21e5f675fd70624d8d1ee415919ed84bc36b1e024baf800c9a94782c08d4eb3285415b2cc800513434162d8db6c7549cbbc8121dbe2e888f50d9896a471333df4c981c849b12c209784f5e078d795f8aace9e2ded0846bb5b3170c608d01d0650077134252a303b050a52c4a0d1a462682431eaef5594ad0f6a7e8f37d7efb8154cb24740b7e280487d0b7302e097b69f403b4fd17cb4371c2a404c688bda509476d8c1d12a0520b8d01e19209c6cc1caf08d258a9b97bcc4fec39c2622f7e03a34f3f457729dfd95bd6dee0c39efb99ce2c6b4ba7a0d4f30ef5756447db9d6efb5f8d8aac8ab2530de595946fba57f7202bb8352ba795ec260bc619714a53e9bfa0c7010643be03c5f5d7a569183522ca52ca1e323fb49f9ea7c8fffd286077a47424462382c422290bd7d27ce03cc389d527bc86aeb670af3a63c958225eb1165525f5465ee00d4c8ca68b747309b4ea0b977a29aa216a52287b917440163e7dbcb6c71073f11c53d90f30a00c83a64c5cb7c2454d283b9848823afd8b7aa8c35db1c871771d4c3cb7257f91a93798a494dd80ea333f676a5be1f44e38ba7c8a59fdc4eb99ac8c0e5c5ba1a8ae3c76edc640abea8928d7023788aa3a28db7f592cc4490a006c273347fe13ceea6faf10120c89825be7e23600f078d87760b4c051625324824954003413290283fc1c10f8505562db0d3adebf575c3ad8fbb8a15e2e614cdcab5de03462c3b77ef8299cc9d7f018b281b6b01d979a342326893045596b4253c70e7026e9cd8a0d0c6c354cc0903f2ee7ce0c653a38fcd9536752e32778618494ff9a89e5eba7cf1606fa68ac6d00bd691bbf5cd1c7fe9d63d326f1eaa0c5aef60ba51b0a1ea11627d46fbaf67c2f536e9f2a95aa90616e6ea453f704bd3350cb58baedc4e8524df28c24484af65a8525f753e3d268fefbf0dc30c0a989babfd346345e2360d5a40e1ec4063d6fe59459c48cf5f693ca0a219881e6cf9d82220619a2a70565ba0bdbcf36784bf3007eaedcca8004c1426501f332f8e500b8498d1829d28b31fbb500e3298149ba7d189129943399253d4d73c16989f97be05d3954789bd824b3095932d0d372d13b80c7bae077963ae3f410f04a26c200c7c2828b53d3b949e8e012b1f5c02f062aca83c02f39054005cf419901fca667a738320d8de5b40df0b256a94cafa4c8e70742c7691897403e8ee14ebeaf0d6e8ae3d85227c5f83bfeccf3bda76a08462351c9387acb726d352808ac65b13d8adc8ca2c8e122d20a893227e30570911a98c4e454fe6133faa5c2c631ce7e4bc64177b99721c445f972eaaf31a6594b1c22474cd8a5da649604b149352961396106f9c5ccc5a7d48c54698171030726909af58eb2078f42713143e3e212e80132e95810f54cb82f458ce61ef09fd7b2130a8978dac6ad62ca021d6723799d4154aab7105c3fbcc6977ab3d60e11910285be865dc4da8a52232aa5012b42b032f460fe35183d17ca6236521af3365229f1c0b1e8193841cfe2402848599163782352bcbc82da809b3d9dcbb8073c400c104d69c3500d9997ef8e0d6197a343b5b50851ab67bd0a644dd413698eb8624aa82a41445929488f0d59132dafa0d2d6d737fdfd48bcea934892e770f781087a8f6e521fa320093a429220801fc5559885bc0644cdd1ccda66c377ca3b054e2236d021ac6d32c06bf08b067ff89b8d880fbce7430137a3cfcb5074e7b537e0789c4203282b5b91246d6c6d8195ba8bcef25cafdab54c432bf7b1c4c62bab1403267797662d98a86f6d7f765c902a498dae8e3582391f9990130549ca4c800259d38b78214a5d1996d21a61b8b5ef45887b43ed39064dcf04944b1974aa356aea28403afee8affa5dc66966d8388c153ee972c9cd6a1e9b0b0f167d02e1ee48c445cdacd50148b38a6226a52493d30d77279aca904628396b70e04a5e0c8d8dcf30bea32e49f8926fc183c6b47d2d2c23188f1eb094df3f4ea38a63da04d8afdc6415a34647084d3676e13c06c9b863467d913d1245315ab326dad6a0efe2432bc44da5366faf10dd1f2deb025227b4a9aba3b88b7a2f4b99b9272e11ab312fdaa16025e1f5419d1f9adf9d0c18362a9e38531d2e83aff4bf9d3a29d5575e14cfe1fe07cae722606ef543bfab562648e52b6f3c577380f3627500ac9ee36568994513cf2ec37c6283964928be9a94ba1e08666d710fd374f66e8202864f42493bff8962978b44bda146b83fd9351447b69f311345dec285ceed5f37f1af1ea4956781a39992c151a02ad8924da32b8cb46390cbd0230801bface01583507f2c59a5ddb801a267187e62809ed387a0af9b193830c5283422c0209287ed46e2dacb6d13fd30f9720a5126c37c316a58bef9d0ddd9c04257d0d369f2180de9c81eb14814406dce6d660b1b413be90f1c11a90e88f54a2832a5b108850cf14bf8aaf24bd38fbe852692e50d26274f6d445d8a4e194e724d087100fe104ff02aa0886c88a200e89ed80966bc0f2183d6f36584a059ab714a76b723180d603df27569bed2fd90de7af205ad9dcdcbb9e7cc688329fc60163fe9b78b4a61a680d7b2a992072c0b28655fd8681ff6692ea8d5ab8009faec32da426160bb3952616ca181cc1d810b5693ff70a33a2d876faad90a06c93239e2cdfac39a18772e8d91a9daa8f884671da474a7fffe999ab6e00c5c1af7e3bb9d998574c5d623856e77babc47bdfad6013e9d28fc0ec91b07a6b65f6c4f76145060f36de70c0d7775a4211c3a4b59b94e8a6a13d0111d508e84b8d3dc0ca43fdc626cee847162e45df392dfc107b2d1cb1e3016b92c1422dd32726e4fea3866c224102e9a4a161a871350f14c9898a4656b457dbc3f2a39958510f00dacd144d2e918d9aa6adfe12bdc928c2568c6b0029aa92014b9a2637bc56a7a8fb33485181459d3c3ec21a599da9e5efd365113bae657e5ba4778aefa2afe9e3b301e6b3c8fd5013a632bfb6f13083d73afe9ca221ae0f8aecf7db464055352b4b21c8486af322956c047e87a5b3b11b23157e830c6554634d8501a4e2357adbfb0180cd9ffd49ffe5eedd9e8d743b4ac7c13bf0fdde51e0970e0265884529065a005010eea4271224d9dc319e6b84bf388addcff9a04d00c20298304e564cd14f28e2495920673d42583ecb13b1c388883166093023b3bb99eee48f62c8c92a8653d3726e062db453fad503d3733fea2f8b84301445923152afb5f242417fc24b9cb736c875bb9081d3a9d8d769a776ea4ef1a8a988dc327d673894ca836ca9e9661e04987b1bc8f626ba11a35bbcadcf357e1ca10240aa263740083e73126d16c249f52833cd631d7ada8e3a774367694c74c02406a8a075469dd76d5e72b5a0929f19ff7ec61fd851097221ca565d151fcf3bd47fe34c852890a88feb37835a84bb83d604301b4008970c523484193bfa7fc7c05af756698f25d8e6e1ce58c30609950bfca0809202b9a504389dd25b01fa964c467a7a45d2884258e33e394c0f4f141e35d61072e5751b4c51f271660a4ddbdc053204150a75c2f38d09d9aa25682a3b92284c11aadddc80af77c819c190f2be0cc72279f0c3fd12d5866a917c993348528d3e484400719f6b4c456d09ff8a2518e0c11250ae7b74831002b7f48d161ec8024f0eceed0e7013e15387d5eb67fcebf68523626996bb67964bf94d6a6b365bb8d07f3c4b8889291696523710b5e9467f4d936452cb3060b4626b0e5360a84055c6d7c12b74e27f31ea4174dc3a685720d0bd0d6b3df27c323cf5f407936e19a331393c808b45d9f05282e61a268cf49a8909619062980b2f431f383e511a78a4328e493443a4e1d0145715a00552a262374069b5c01a99ece20e05b05536965794a27d665e427512ad98d44dd731af796c22769e622bc44f580619b38ac090826a6521de339e5c5441594e0e7849b68b49429dff7d2f8c995da544cdce15fee56ddef83068c4cce1c7f2bbdba3b132748c5dc728fb88367ba3c48da3323c1e526cc627e9adebb0fff2e47670467119281b56ebf5fc6b369dc4c99d582e68f2c6611e3dc814c4c3f04b4aee03e48b5724955380652445e997a056414442cb2ca4ae14502daf36cb61acfe1d47597ce5b11227818cd2a11bd293e7f7b12dbda506e7c05f27102240522119c527967df8af65e4103647cf9704935f1b920ffa034ae91bf1b9f26a26dea3178809c382a5b2b532d34894eee37ceecef332116fc1062da5a555fa431031820a30926781406559a12ecffedcc2caa35525308ccb94cd11560c29fb1f72b3c00ba9943949a9725514bd360567162c60010ff061a5cf9d8e9a251840405364e0de6498dc30f6e85d000cc2ae10de02fb4309caa78379dc481a76392eefdb977c408c83be076c2feebc243d3549d3e105220c37422971c6223e93b062d8ccdafc390e01bf87426f3df26fc885b01a56806dfdfc76a57dbe818c2bd337c706fb7229b11d78b6b1e6d51f873d00468a2cf328d25454dc1855033b84d49cad59cfaee83fd507d97754f5e406406fae5483c509aead95632fca230ba8e8fc65884cbbaa3b226760372c782844c6454fbcf9b31fb04c214ca96581d89361249a1836faffebf0fb092609c0a0918c1d8ec7f5f264cfc692e3d38601a661c9d2c15ff49960c693b1f79eeeab2c5e49e721eb31fe6d1b3ee5323cd4a961e8be2f13d07b8fa6b62861bc36045cd405061999359516cdee1f37e008886f91d003dd6564342408b89203d3067d513feaccac14f808787f81b920f430274dd84f9c8c8f617d3d72891bb2ebd2b4b4785a4fa918484ba6508bcba7b14925304b8a41785556c03b0dcbbf73e083935ccc9cbe67f7553e467103233731d0ce04e15af7437c4993e6471835773ff3739135808245c761ee00bce0210b121158385c48e660811aaeb5298de41cbdf83273772e11950424649cac99821ec1db144aa8b7855a570bb7c66514f8f47689d66ae45780bf891975831a8a9b927ddec31e59ba5781ff95ce3f5a751a7fb458b0f5867c64b88f5a5ef5643eec473dc12c42c52f361c413ed610c6186280110ab756092de551697b94222c95ca4d7c8d7026a8a694f724c6352d57142276dc845cdd091aea4cf74d01b4719a2ab249f4060f9b131448feac08d5de3d08f776838580d9b72245f33e0186d011381184b50fd4f8ba3d41db5a99361d22da5d47d790c480bf0af0cd6d9f4bf22039a619764012128dae543916fcb5573b60300dd4ec59d1d25b96dfab0b01140af3a2debe98afebf82bb56c739f5d4ac51845946d578ee28276cd6848831cbf2ef30b1ae14149697f318366a1cf65b08fe51558b71308623cd531fc3c855c71fa04a5cfd01eeea4dfc0ee9526e5a916e238d2107ceabcd8b6a6e435a0a37adac802caae2a76b40545cb135e7e039ca92ef0c874a8c505b25e2d1cd8c132433a27e810f002d9424036318fde1177345cb643290b157eb948bb93e21e8970475551cb9c6f5afcd2a892472bc5a2e2b0d544a011ad0ec295580d4d9340631841485da51184ed31f8c63938c71702ed1bd31219a1bbb9e077e4185fdfbb6c37ad2836524bc0aa5da2ee7749fc330dde7304cf7062fcca999e2864a66e12d1a5fbf3723a9096db2e54e29ed6dbb0396026d028c021fffffff7f1d2730f6e93c8d3aba974e950b4cd2c82aa10c72d3ce9a504985d5b381949e240d7c397e84c8e2240992a2a12a5359685ee664ddccd051c21225840d71875bd5a6a26021f4d0592285051e4f9e50a10243a9006d6062022227454d7e1891e38938f5b384266328468691cb2f66ca4d68db4d3d32fb0810b310889d49816ddb4d7ac0d807244444fba049cd533d288e735b9e52860951931facb2c989b06412cf8e560b466c5b1a3d30f6e9d08c3a362f9d1c1798f6ffdf1291d584076d6b6c3b061018fb64624cdbe317b302afe34f923fa963e5129cfd7feb4459f34a42f4892d72ce92a3d05ddbb66dd7e811773ed850c2ffffffffe912866d4b439a34a549bbb91466c2c78e0d1cf8ff73468dc921bd6e3b49923f0895ac27061035f53b02c0a31a3a5e3e164ab5f1c8482b213042f4e20408848791161708b4eddfb66ddbba6d2faec212d964ffe7f49c22404de59480e40710241e5c4af6d1c68db16d574cd5562d492aadbe5a0c1a1bf6cf39e7cc1318fb74552d667a34362d5ce43805397dbc94e2083543cc906263679343e3c1459dec3ee69c87b5ed5f761c7188706838351c269c262525c6711c479678438624faffffbfb28d9fa8c09c3722bb18c57aa9c288d6fa003f663f7a202862a347287324c7840792840072947f0980cc10de2c91a39f21b270e65649b224c922b0155a1d2b243017c6beb10487829831be00c09c38724e1b1049b4e612ae254b2a4e82570357ab8b20a440149698737a8e73ce71ce39a17060eccbedbc028a37537333a3cd552d567203700a9027aa1f7ade5b002a79614766db5631e566ce20981c6152828548d40b0f2c46c92c4edd30b6ad0e48d6be2ddbf2762f95c17273e201fc24f9ff2eb02b03d1e0036ca662d6956d9b75a52d8e7a6cdb0540cd3567026d4b46093b087a318494941f5148c42296e60fb0396d4200e048f1301d2d8aff9f45098c7d37a70fb23cf5ff4f84841fd95f1fb5bf094511a10b49ce5ce07092d1a38690290f6e45f69ad0c4e5c598140453dbb66d68db56cad9a5efcfd8a53873b59db375d9b66d5f08dc99f560feffc64d18fbc69224ffcf169ad30b85260ac6db6e5b1572c0d8c7f31334b442052353f089adc9bfbc0a82ff4f0357191ab9974d0092fc92ff3f49b3ba6bdbb66d1e3710594a810610db8d86a0206d5bbb846168a4078c7d4093851121975f99816166407f6830e118db76b62dacf589ac398fa2c257892116606e0208e0bb917d4932985ea0f810351b02440a3e62d58ed1ced18b6bdbb66ddb361d3f32fbd53253b6e6dbd9b69d9524c953825f924d524e10193ca072f038923144b5c464498a00a00e022693df054b8a8ea87c312f10d93091a7dcf1d5d8776ddbb65d043525c8920e9e928e1f47dbe681098c7d4db8dc6e050fbc99153dd4fcffffffc581e19cad6823432b8c187de22c0093a4d8f232e73fc20e524940d924e98031850825f28739ff396790b7c8f8e474909d849124e8dab66ddbb60a5d8d4776b710b27319d09c6daf1ac2d4a2185ee181b16fa6e6c6306d5bb17479069136a7e738e71ce79c73071218fb946e4e4fbaaa163b7aae972433a5eddeb66ddb86d30d779075690ad61a0204aa8832bb2bfc6ddbff415c4e0bb0d7b6a19cc0d8f7a4ab2a0ba81e8d4d59e472da55fbff770501ee08914a0420a984f3818e6effdfca1018fb8c909462acdc7888fc93a4ad851bb0634223714fcaff490f6469a58a6c312427b6adce4d18fb461424e9030819e268a38d04655cf4d8f6417f4948933435d57f8984e506140c5ab2d8fcc020730cc53143d494702ca0d6238622fa54ebe803d46fdbae2b0aee51a0fedf36dc3361db1d59f189c234b482c9a835d9b665b90279807ee62cd2b6513d1d8dce4697334e2d85ffff181cd4f258d0a4c3911d8b470d3b39beb7486004871828b88004d14ebcd25486668d33c5f87e7e45b32b0b1ade4ccdcdac2c4ae849f189759235890a1631c499e1f4d85a4a04204ba404a64ffc5190e411e3092113263e21d99764741322616fdbb66ddb0e591a92b5b8d992e45b6301a8c50148c5c7050770b88461dbfeece60f6fe29871695798734e202730f63de9aa2c03d4a3b1b18c0c3976052e706c2df44861851d11091968a20c48aea404be21478848cd2ce158e2730496a9b1425673aee69c9f493ab7deffffffff6f636224fbffff24f9ff2f243957bdffffffffbf6bcef29f588a73d66ddbb6edac6dbbeaf8975580aa085521aa42ab52abc254a5e9297a0ea0904041d93949da89bca432c9ffbd44b14c0500012ac12157762fd8cab68d2234f9dfa6315334d155ba34a265dcf8e3c8db03edffd7f8a9115463a886510d243fd0b635f8dbb6ffdf8596234263931cac2449dcad24c9974140de8d141668e0733ef54acc990312308a9454b1e5808411bacfa09a2dbb030e005b76b2af3634d3b2234d921f5b80b022ebd8b62407bba3a3aa14ff9c73063102631f92d2cde94945105db884841e306631a5c975d7d3b66ddf82c0d8771b1a6f46af1b920b0c0a17d088670707a10d1a3c25429b9ccdce86076346941a3f731d7770c145923b14ad4892e429592e1484258a7ec0d8175434f472c1b56d7b6ac0d87733eb69d10314a20043d5046ddb9b323734afb60da35cdbb62390d9b6ed1f44a11db0d3784a5653dbe63081b1af49260737e545440a2706309f06e0ece9e54928d5538eba26b049ed77fd7f05e0cd06113197305ce52881b1ef96e3f472e98b1a576024a9638922ef544d5438aa1cd58e8ae730c9a766851a62186ba821063bac6d674c61ec1b89c81d2900c8ef1387f82a660388d2ce4e91214f5c1c29e2c50b0b14167233cca023a486ce0c098024e980e9e398c8b5feffff8fe281366c1a02639f1192524cd3ad08eb33744d615b2f10fcffa25a551431fd3f19b2441d9d4e9548bab66ddbf68d9ecc86ddb56ddb360f986bdbb66dcb2cd99f6ddf76db429901635fcdcdac870514a011f6ff6f756809a2c93e0338543aa89c14f5f0f1216699c124b34892f3258d1c38e4b86b3d1b8dcdc69613da760e3d7e89184f317431aa462bbb296385375333658ab89973bc1dd278a0b5ed5c0f8c7d34363953460acf9ca193093ec80cc6b8c03445d1b673c0d8c7f313340fe0c1860913f480038ff84373b5c2dacc58b75528f46aa9296144d1b6734e60ec7bd24d15b92a98cf39e7931118fb90946e4e4f2c9e74ac5795587efd3f0ca4c2502a8c5b3b47f12c92d4fd460c20e384937295361a84cab67db5bce815d95e30a248149a247cfaff2772834ef63724c91209a7f0849a9394c8bb3dc40e0a47acab6d8be0c2d8373ae151966ecd29ce29cec9530265006507054932f158e42f86a1d015182ae47a3de078580ef244d615db16a23485dce6b4cb2892acd3d36d056bdb95eb04714e1d47acc4d7ac019525962d2db64d14c6beb1fc77843cdb9e210c1e90a4a4989d9e9f737ece399ff4c0d8476393c3f3b34288207be5c36584f682b5489224e727ceb99a73ce79d891b64dea05c95a23498cd0e9b09225484feceda4927654ad1639864428c510711b894e90a493b29544fc7c6a7c6e5eff719420c9c35e947cdc1091a3324866368c659122a8b4cddea6a6000c00131a680400034118c9e238b70e0614000613ca94e4b83c301a8983c2703824048542813020000003434100100c0e83404090259b261f85118b88c4dc9b1a38f506443975d953c75687b874e860078b11c0d4c3e627e8bf1e101b2d236374e9fde983dafe2199fe8a352b09ca34fcbd5d9d96abd4b6bda5d8c178d9e19d900d408f01e7a67edc7dadc12145933f8507ff8a2bc4a4b9b52bda2a800a5d52d2716c8b27ecf9e5d010e22ac031991d8d11a56e6554ff0dad9f400145ae9302b7bc45651dc2722cdbd4904031e2b179e3709ab9bea2d144555b2567920088aec13c1b885e29529704b049e3c3e07e89e12c9990448e017f2fb24d0a82a1efd0c45731ef4d50d0e9a665ac83f7d03a0be9ccc4c561a9012786b10742d046d5df4f456261054ce709f9169badc6678266beb3018e513fc5837ca856ed51f64f7607c3edd1c989a76dfddbc145d381685d5ed13767623ea711c191391d14e6c945a7627e0a366d0b425289b9027c11e05605b8effe8a147e15b9f11771e8d093c8dd19eeab05c05db5825876d53b10eb8ead725c82953ae7737224d9e1b8a6757ed2f9aa93d053bf92b721489e5676f9ee3ccaae5d761d4074c3a8b584d41932919bd0c15f980104bddb026ade1474c4ca89274282a1edb98308aec3c34b41b30e587f080965d029fd1f26dd1822197d621a2ac331e1c682a16786a3d580e268f62921dc5a5fd1d154ddb4547ee631b5d8d0b3809e85c5255a80f521136ccc33490d2981b9f3662da62e9aeecac08516e0202c366a1666dd56fb995a24b397458209085220df7e5d766e67ef27775a0ee229be9f07496006a147e740ff1bd0eb1a65e5fd7753a45a996922f2215ed7d7f0fdbd07e250b493cca41b8e77fb3eec263b4f95d4eddd90e52acef76c9e3e983e6d2d3ed7f7131ddadf04f49830d52b3f9c9aae21b258ca0dd44bc5d44905d482bbe183b3a5c5d8ada047eae23df0504c5604ad6a674fbf1d714a102da93a1946b22d86b0dbdcbfec987dfa3f0bdd041a938e5a104cba23c79541d48e583665876d4fe511fbca508cd729ec59abffe15c1d4e56564af3afcc5462f9689b625df524c11ca56313f994bdd9f1a02f7ec7641f2a801bd3b424cfe9c4e4780f1079ecf917e8c59ee81769ee4b5211ecfd0e5083de72e78e9527232398c64fba64b021a9095f0903a459dc7fb2a788dd73523d710c134f1405768bc606a2b4124dcb08c59d9490296fc4cce892eb6f483e402345f37712801abee46b75bc837453b939a2e2b8fabc210d0274bac1890629938473ba01a74560d9316e1e5bf79a320db6927168704edf0fa651e433f98951998c333553129a6081c51bae6a8c30ca035c3929197186ae3a0bf81bb68712faa886ec5e221f4acbd71cc0acad5beb436fcd79a5eaf1afb0565c74d15103890bcf1280dc20e885690046abc0965f417d41518347ff31ee8490b785fc410e14441a875ba2aa65d4c4f51cc3a960ae0d82ba1d3266d916eb82098769a92a1a4092cc4eaf1ff3ed924288542b6b9a083e449595d09c69b3f1c8dd457a9a8cad2f25dadcb0d938c8e7a342ede5cf248d0e32c6d0fbfe5b5fe40ad515a0271b78d205318ed9d4632ffda47c3f8112cabb62624dbc4dc06d35e1f120701d17a21fb65d8fc461c24b292876176602e0692894f6d656c982ca41d77dbf346204945502860daaf69dbd33120a3d0bface3c243f01e67a6621c49881888dd17a13ac9916e3ab026c5dcf515d7df47569fbc8c51c01c2c7b4ff98ec772ba6d80b291a87f6f3289e49ef05559ef24a4af4648c3535d4c0d19a2fb7e045b758a7491183ea9ae78179fa3e7ab582141f5165150832a00b79b47741b751cbb732afa0703ff8c2141a214dd9e474caa86094df0b24468c52f8f5962f69400ba6850ce775635f527c50724d0a12f8f04a76d8330c10754a7160391b0603985cd185879bd966c23de9ff2b084ea91af00601f4f7cfa39b3c01635ca27352b6249e3f3ae0918e71ac5a351f67e9154a352ad4a799ef8cc1cc09808f936fec571f60a85184221982905a205a3582a0958410fdd72995bb7df1c5b1ccbd24efd1d243fb0079626430173d320eacfc39bc0c1d473823a7e71e5f5d60e8ba02d2185e042e6e65e1b545e63cd0f849a0ae1280c0e6c1552ce057dc79184e7cfcd16c7ce69abc9ad4051d17b064158d2a5b6aedcf6d9e273b807df1e79164fa53cfa68a6f72c8871907487146d4f8ef84cb2f799ae4f3226cdf5eae8670007273c44a82648875f7668c5f51efeb746cfe634db28a1c23b1cf2551f17e91f698fe0c95fa4d20078d350ab12b913440d2a16e2704614b0d5c347461a852798da1b4217a6cd48e910e5ecbaf289dcf553d42b7bea298f743b55ba40c28e8f54c206e60584a7180e6556d1c57568824911ed7d35de7275e0ac7ed7c09593ab7f9deb352aae248c2f3b86d5d835927277d4018ea114abf468d94ce78c5a52077ad15b541551867d0acdfb226c997364d2b0b6e75f0381537d728c5029c0b0dca69aa06a7d751d329d08e3e1774c91aea1f1ddd6506a3e579334a31dbddc73d592324f892cc327d6b10dde6a40082beee347a608555253b4f2cdfc25549a54f42084597f826e98792058b51f03d129a5449d4b75c00e4fa3fcf401a2f125efa218ad7c65dad23bf809a5727084f87f3af282e1be4733218a5b1c97851db378c162dfe7e40b5d0b1f38838cb3acb5a0248ee412b812002367e449b905c8e11e4a8a1765233c548d2d4a29fb0736b62d5a4384b0e62ed20832bd5c9aecdb30c173f413af92e90852d664d885f471a7c53488a608d67d403dc4f91740333af7cca2e005398256d0dd091bc88b26104c556911db5aa71aa0d42010908c5b0caa613d0533e2f61d2523c3c09dd14dcc31d3f24abb4cf2b1e5bee535026622a4f56a3b8559cdc210f159e707274182cd2be40955ebe02ad7960a3f505801273799929666015989290f041bda2305fdf33eaf96a029b1f2a595479d15966c434603c76e72dcc33f1a9a168121211f18fc25e0c5b18a4e47bdf95f345516b19274440d52fbf004772c73532ef6201e6e25b69508d918e9227c201ca5d327fe1a75bbfd0006be4f54892a2689cf79253bf2bd1ff8bd83e548dc6a77e313b59b9324a023364625a7e8dbe5759549b06010e06cebe15c3a1c569e2959a031fc4e6fa76c9c8fee9930bd00b23a782022c6eb0e4ea230ce2447a399fe840e2b996fee4cad6ca1cd8e398beb8b1bedc9e314e18eb1a30f9de91208665041ef9d31d658a0bc066c2ae1255f0e7d5f09fd66c8838b1fc5a31e68b7989626f61b570610bb2e6922b74e06bba52499696f4c8bd0dc96b556f3da080dfe2d2cf4741443abf523c566f8be33981b56038ac98c2a18a14f422a2f204bf82481597246db7f3de0d00912717e888c6ab6c087a7caa96ddb8e0d18d05955fd261f4e3f2687ccdae60a98c7458b6699f6458fb5522d0a672907d17af718320fa944d510800ce6a9beee1f59fc1ef59bb4caa9d187ac6c199c14369ac2654fc5bc6685f7d96f11d52141f2065d2a52b53faf3f85c210888e33fd1af52ce22ad42561eafc8fe58de2c4772af1e573f73ae6800d374347adb7baa450f070744754b3dcfdc26cee505a015e17b313171e6e168146066d409e9e53322f2aa1d849cd9566f0bf3165376b010d4c69d15929041271e115afc8be1ba69628a0898f88e043971d15331477927dada39c3ae8e26bfa8d9ae888617407fb8e6e657bccc0d0c07bfc975f15b27a889315de18f06f035f13e5c9f61d39d8a2c5ca49a4d52b49cfd2b5d17c9265580627fc05e61b3b05cf7d762e78e2dcab9e8f107d02fd78876d4328507a44f3396155ca40a4a25ceb27e31f21e4843688b58c603d65b2133005405d63819ff231ca496ba1c4946be17f8145c6c84a727d1cf62869be8856a0891382f61b5d52fabe45f5a882e49ee7cd24aa4e96c0996f06f196be263504547719d3fbb1a13291968a14eeab24ab36ed8786189afb6a80027af2e0390735bf1ee7a1795f1013ff0b4d14944d87775623c88cd63d5078c09244010d7f17ce8ec5b2e5f668ee96bd40ba5c90537812c90d9a88731dde94e30e99e58013b80b18bb718111a7b6c21b4a1dd2765e4ec7920f8be11272eca8689619779c2a6d114344ed97a17de02ea9dc00ff74ea4b7335527bd9001c6812e67981747629cb81ac68364703ab211829575986ca002c9ad669f8572cccc1d417da610582ec638df25454215fc4dde0aff56dcd5663b09fa06af6c959e90d0b4bbb1ab5d30cc45d94a0c2ebb9fc440d18034bcc3c66fff0c7fadc3011ad180f7c051a366019787959bc5c2746828cc2b3ba5d619881438f696dfed0258cea256b21c739c2df8412655b00cccf35b4a84dc8f776dd9b8a2fdd31f98db85f6ad4c644b914d2ec0ad20da14c9a6055b7e8ef803a2e3dd8b53646a579b63c45e18e01e99a5fb883ded3939ca983061ad6c1475bac6b6150773a5a80d78803d767a3275ed0aa814448e8f73cbda8896e50b82d86cf000fe5708d008eac932d9448688216607b6092b798db7b66289022edd65d3a395ec7c3083099d58f3fa3f88b8ca083039487e5c9ba5e4488a06cd09a829de5dc09838b57f7a40e384c0fbfd082d871cfda1524bf5f771e8e3e12ab181e16c34a46404a816626196370b00d8b0586fc8fe6140bf664008f36305e5241a77540d5ffa554b54d8d76f3d3a9ff16300fdc29222c1c43f5a606f34099316d0d29e4fe34bd27057e53101df0e21b36b2ca8ecc244ab616fa843b0c3831b83c0ff998d16579e4cee9f4aa414708b228d3efcd85617976847ba69c4aeff04e80cb0a427bf65c583c6740ad1737242172dcb4b7fe574ab4a2895a9919f37512f1ca4cb9984d4b3b582097b83aae6f17d0483831294d819f3e5b4c44594174cd049e85f908827afdb3955922173e1e8dc9ce95ccf1547901025a2a49b60a1949d6b9fe5495c6d90c32a280074dc2150a7893811f45bd2093215c84c17b1695760d9c55bf356a4a5a78ff771f39e704ff83473ea01a050365813e2b7e31780594959c203639b101eac90ba806ea18e5d05529572fd97b108bc5392491b0d50e08241eb8a7d749421555631f83730060ba58c4721a82429f73b95578db0725901d554bd299ac7e123e3f91860eef3a1b016b380a9251f197b75fa88870dd7843e58b2f1fd7400ed86246d2409098133902ac1de8f0934c26d33b81c9cec6490581082c2b4bb54fe1d4661d759105a2a4fea0a9c7685ef9f5b0d885c5c86651d348b53be3e64b83288d9d51e69b8bf1cefe219ea0b27d24dd46d1f385eaf1d0b15739742fd913d4de2aeee7a863a7baaad1d046ea0934d7c249b4a5d6f98eae206cf8c8cdf65d4624e8276d4667ebce5b4a817111f9535dd19b526cad0028a13637e412e7d977be3c841295103c0ada4f264fac6929e5cfa8d32a8d14dcf43436dea37a861d720b0e45533655a772533d7b849e85c37e0a50170efc64221dfd2861c8339216c2a3c01a0de31ab304565db5e5423642c6a46389d6694ee0b584d561650dbef022543359985950ecfc6d88b68ae5d76002cbbd9d47172837025a514cd6fa7f4e49c4c38fa043d689d0e56e4e899d9f058da29ad12aaa5e89aa7d9f49b0fedb5545fb59dba6041e5dd141eca7b9b8ab5880574dba1d086f4a0aa646709da2abca320d1349e8c8afe2027531f60b0b9d3d21199f306db8141823956d6ca2ef1e148ce414e1eaee19f7f3eee6080a41068f1c0f511be81408500d9846b6f8225a80a43d1308159a3c0df63793dc636afcf458b97f380b8b2b0cf38361d09880987c9c4716e4bee138279c9b23aead9eb6807f4c4b921485161c8498444bab4b07ef126315629a88f8c8f8cab8f2c89552905062bee151887d121dde85aefa529accc530fe8b838fee766530b12af8413c6f447e044b56476bbaac93b8c64dc7cdf63f6bbd22ae8b961f6a8c93e210dc8a145278438fc8f20c1a5c693d50080eef8293db2708558e5128f7ab09b4e2cccd3376616d73360af7a6495fcab9747886fd9019617cbd41c762e4c4e36a227290b2d263dcbfb2fb90ed7fe9b0385a020bcdeaaa6a34200a193704135aa4222c06011346a960ab303d0ea3952888ba904d4515c1f9ac7eabd2c66a8d2fb5444aea4b325d5c9394b40cde9add7379c435f839a4ce45e45356304baf107929f485d33cb08ac2fbc38ebdab089e292778da7b6d190120f441f50265642dae5f0cf179cbcf40901e7c151acf74be6a5cb64c531af18b6e99271b81ba290b6c809d9826140b75009aff034a4ff3c4e7364a13f869facbf372189d9c24893b6890668b93084669ef85443f40907c5ea0753cd888ae1bba7680fa73e9f3165db565e3b96a60557e71d2ebb2c838201cca958c12ba87e44246d325bca9a694b56e919100e7274039369865534c6f295ca84370f8c4ccc456c70573e0a06d415a6c7d384e8e46baef1df782aa780b8013e94e7e460a1bd0eae65bc41412564fb793108747a0c56b98077bcfc347844cd2c72d5b0aab5e99a4a367f99d61624367db91a076a3a9aa0cb5ab2d9e6bb243a742e9b1f29f7cd0745a85fcd4c3676c60280a30a9d524ba1d2699d5ad9702b3b5ec99495893b6e2c210f70836c3520aab0d8548353e1bb26cbfa16c320775912d0c1e75f05382508493390ea15eec1f8bb2100a94e3476ad3e11033d04b6502e01a6a0690939398e2cb005db3785c87854a24c89971714e034b38d7f7f35f1c92b374c3b3a6d59ac96c49709ffa956c377c11d5d7528e28c704d7b751809912b1915ec4c5be9494ddbe64338e750cb93de88a9da7ca0b7c699c0ad004d1b91794c74ac19dfcda5900a20bb54531a9086d844c23e0d819c115ef5f13c1a26532a38661ed45e0abfb838005d54582601b601f4a12f48ad9380832ad7d219244f9f0b979503d7010c5530c9678dd63c5f733094f80976f9f0d685e304777e41698f7487c4bd2ea674554d7de49845d77d954abb4255cbcc13932f817ab257beac802ff7f3e1f1a438a268598c08bcc200eac912c4f5100ed4ca3da1c9d91dfc7431709a6f81940f193400b622cb8fae2739f80906c4ac4124531ce2c9b8548072f3b78b8d68c1b194416e26bb8de67e3997056fac1050ec28a46c9f917ba7de2bceeb70959ba38c6f6fd7d44c90498462d63017c68b26085d8ffc1bb0c9cf03f725d7e375760cc23d6bc9e3120ca58c297b0b606d43de78a5078729d62e8a84b6cdb03094961ef078b98ad187b810c509faab8a70be177acd69b0114c67433b907e390007157c5b2d844ea7658a2055cabe801112f941ebcccec71ea3db81cfc27201ef531bc62b2a8f2c4b5492bc36b5bf6dd95d940168cfa6cbfc36e491341a374f126c4a6c35d33f4aa5ea18a7b5a19e476eeeed9d9c300dea2933ab08fee46242ad231dd8480febeb9563fd64fd5fc10e2dd0033202382e804e43fa8a3547d6420904143597049f83cffc33f0a40c3a549980cf140d1d3092cac94e10932741e5922689eb0a02dfee6eb05c938d7403c69eaad00ff55efa566722debc14379ec1e08f3710f562cd19525b4f929486cde2af7be74c194e39b297ce2389f6f6eb5b3c85d58f9e11555e8e4989024d130cf64a7dd80e7fd3240e20854e3a2d16daa20362a9a43e3d1106e79aba601245144fef203df0b9fa698d5f5cc107220830e2e5303d020904a59c59f2396c146e13c251927d05370adb1da3dfc932aaf13aed68a66746cab0b7d7aa20de01807667eb3d6f05fd96394fc6194232227822122e597b32197d129f96cce055703618335b22a0b102b49727a018fe686ba980c18ccff3f3eb477a910050ec1d72188c03ad777778b47417885419a903c08b569c63b778241a4f123f68e34eb815f9a0dcc9e5877106397830588d6e89aa96698af80a43d6b65ccd27a740c580150f25926575e8b8ca906dc171ee150b6c44ffca541ba04ef1aeebc7a9bd9c4251013343df906d85006243029b0e96bd624c441669f9cc63614d1826a8506f7628d440a59a4197680ba1ba0be41d32af7401d04d17733931e13b1ba82e3d36329fab3daac8b21077dea4ed68511c3ce1b033a817a7754f970e94bd7f83a31dbc6c1ab4558779f91aaca36a8972604d261971f0200a40b719b58a3f08133a4d1f46597324e5592259137307407b5c8133b1c5763a53b98b5a0f216ae1d7185da5dedce036a05354a3436ea36cb4a92c995075b0923c098b202ffac23f75a39b854c7571ce828128b71f05eadca04071101c40cb371248bf2f86dec897ef6a72fe17d001a408b5070e7cad0d6e7b87b4a6c1f23192d25a603d4762a340cc6f8f9ef2fad5a6865c66ad69dd272cfa2e61bff43d3cf04b96648f0d6dbe4e327906fc8d2f7d38fd55cd81935384d2b8476bccd5f6661c4c75420cc331538f2ca6cb201ca29eb1435500975475c0b1bc1ae5ae7d8d783fdfb378fe0a6650efca09b4088160488573b6e1835d3c52bae84a517272877d167c5d5d045eee284663bc13fb2a69b6000f322b90550f64def3bf8d21159787c47d1c4098485d715984160a850532a7b0243be54cbe1ca898a0a52ccb0d6de2bae2cf9983092dee93e0e7ba9f2dbace6c3c1092b1986d0ee34c9b50e103161ef6f212328e0844a6c36e9ebb7cddabaaafa2412770a0e4b1fe3af65c631805a57950fc610f5834eff145ba32e1f588179cacda024168d42ccd01692d485022a70488e6671db3bec605af6e37872f6069359937eb427eaedb2644a578c83dcce150295bf5db8fef14e32da33ed6dbd5b715dfa315b1a78c42bd00f1b1d1f31c66cf033b361eef055be2ee27991262f8a1aa6223bc9e9fbc32d5b2637d45f313eca413f1e0d898a0d0e7c5b7f9c0c3fa3115f7778d3f67679ee3037074589b1b49219f40d2892592f29970f9cdc18e489908ace1ba64e93982320396008abff829a4de7c722795a1f896a64cd2c09c8969226ad7d043c13915b85bfa8de544268a5a00d81568acace382300fa5e1d0dd087802f4c3b702e949988cef86df2c8d5877dc74ce3128a9d4965143195400a03d5bbef3fcbbe75a869915fb2a687e1ebc2fc5cee12800ee3f76995981306f14952b429012675e773a36d154e6c73b03e128a8f47510f2b03bf52c872ea8e4050f9fc8f1a7ccbb629a94824c04783fe31d2dade5150b81cc4543bff4c725b3f1a3cb1d0d6f970b9e2901d82ca7f49668c63ee71a10e42a0671003e4d056444b076554db115cdff7f3c36aaa42c437f6675a25695ff33bbc816900103ce65de18a900b054113de134ef5225a4645be2ef44c005ee0caaae2e128204a0d761ee81228a972fcc713ad261e936594d06a0a32e18466c3b5f664b16ef13cd2225f68c6c405200ccb95f645f8b05dfc0470e9b99f26b8b5a3416a88c230d1470ebe41c757f2b7db1777b2e93fa8e71bb14b28b55e2aa8423e5269d780ae5303d1b4486d003c9afd254c812449a9a4e940f6fec40ed89c43c2701aee338b8408fe5c56b4585ab2ad8767ea184636c52eb6492c772fb593a06165c4b0eaacc18c48f6fdd23fa3e25f810607ce06f8aabccf41458a0bf27f44ce39a04fb0e58677bb3ce464d337c3367ed23aea1d5816f915a6ec037687010db548078b301030f9e1fbb6e2d4e7a11dcae8f12cbab6b1d2b3de7e1b9aa8a3c0b793468840b6c36e2576c3464f5a682e3841893b9855a5b32316ede0acec335805a54470fae065bd88f5005832ca9e962eb1196107c88532a1c40e98ace8239d5a823feaad46e09412e69353cf48d1f6a6b414f271573c6f41d0518b1a21fa3394ee80e539802499459f1922a4b5478b9ff47314a66889f81c2ad0847ee1b2d9d7e495724275569758376d5698f55635c16b991dbe83a557ccb5bd4a2010a19754270a121ebf5c75a2c763c71031d2f723192a89fa4945e653f1c9d266b419d5c0d57acbc87aa9e47772e966d9386fdfffca72c7e5a256664213e49ad4820fd66a0d0536283511a67265cd1a40b28944f48fccea43611299b029815f32a6175f601cc058633151c52d832167a20e9b5fdd6d519386dbe08266627037007d8a08623294f31b0cbe501ae282dcfd2db9b31f63828f664e94514fa345bfe8085cd6d73a47917c15e7014fb16c01ece549d98da21bf5b91014dcf7e3551cab25549d20779422c16da11ce641da186d8cfb4404683750f8ce97ff6c1dd88efd8cbdaa7d2f7454aae294ba2ab92e29621716dbd5573aed1d676fdcbc88760aee929b65e507ad64ad4ec156aac0954897168417f890a888b204b00baa2c862935ecb5a0a582e869dd828c0909bb6545bc045312cf209fa792c7d5e1feab835416b44b75c422ebf011e6ea049e3c41bfcf0fd5d95a886bc2138cd3fa5007407bd9217ea9a53871401011c6da126fcaccec262932e1100d4129ae46ef0292041513d711dc30ab5f206410975eb6849632527609ea63a8eac64560e50444ce795ef3bfa5d072c05827237c768c4d518eb07a3f9e9fb04ca2031c8d53d46f970218500e475dc68b911f44bc657aff064a708e58ba4268cef0ccd8f8b47c4addbd671cac95a64e39b814880ef9cf20eaa5074f704a758eb6472d5c730be57185ed470f1f3054ad8339592f7a519fc08bf0a61c70a126fa72770c0cccd4100f761d394620c8e8509d2743f51a79bcd52274ec4410c29e0945d4f4a8dfdd2b02b146b4025b0290e409cb535afb22dc51956726981dad7c609fe979636b9e38dbfe08c2f0a6212b3147022fb89795e88fe6a4cc5f89e9736ae09e9083d614e074c34359582fee1edb2f2325bb53027a5db007e2509126b428fc46146d63b42597f99292849b7e66957978d2eac507db310f97288350ec0ad639bb61a678600158807c6692b366986cce45a8986aac9a88a5a46dec6cf9a5c3f40a618b42883eca5958e534afbbf971bc7e281bc855c268227ffd810485603802456b95c91ba00505197a508b3b837a9b4db108b03bc076ca242ae3e272a9c9b72de1189ff3cc3f83a9005a4a1010a3075415e408a59451d8ae46e75253793177a0fb0e60eaa0e3b61fd8fbf69ceafd3316b6d147a51d6c132060eb1c5b41fc3d609b21459e186fb67d8fa67c03c51532cbc1b0905d7a7158ca3e44f30038b0713d4ff8d2981244fb8db965ba6b4b79432e003fc032204f75ed5bdf7ffffefbdf7fa8efbfeffffffff3fe567dbff58e54cb99ece47dcbd185f8c6dca4bbedf7bef4f9451f2de7b57586c6edee14c4c10265a0d1d3e3486c985d1ddb12ccb7bffff9f36adbcc4c8fbeeeeee5b725646756452deb936d8c2d3b11a6e794b16706494913135833663c855ee3e9ae012ffff7f666465f408af9821b9aa1c69e580c95b870c89cc88d48e86a6bbbb0e2b3cd1e338f228d3018f295a07280cbd1621821c43a4210e23445e03851e42dc6ceef7de7bcb0fb59b1b5cdb94e7a3b6ef93d40c1fbe334d5fa4b8093f8afcd089b8f7de17faff8f1afeb35675ca0c201dba39e446f08690ac3b7737c727373a0677d0f0b3f1c4057845072fa103bb95bbbb0ee39c8d3b8fed6e43869211aaa0fc4699dfff7fb6c92d8c552d263c64c762084fccc5bdfeffcd243127ddefbd17ca131428285da0444129f331bfd74b92244972fc5602a27820f1655094d17befbde2cac94b62126ba159191d222a323a42ba1b687972af6f999120499224cd1b281e212537e523f9efee6e925961cc83b2b180ba9133b4caf2a6fcb2aaf1a4c6528d5e8d27a9f2de7bafbbbb97008c7246e9a8c8eaefc5f83136f1e5a009e7eeee6e5225593054ad27fc82eeeee27330e6e7aa771b7777cc5322daeeeeee13b8dfbc8c2e32a2649431a3dca2e0a2e456620b04435cab55e236e50d751958d2af598269f915ddff7f4d9451f2df54b5802449d4e8b473777777f71c72a94b2fb74cd5ffff8f7852e5dc7b6f8e1e47ea34b3325ab361164e37fd3c2dbc6b04cab744011a3a29559024c1a062d5c8502b42f19010369ecd67fbd5116333094dfaffc7efffffffffffff1d30011ef5d821861c40c0f4c20e41efb5fd4d35166d81854725cb6cdfd1171367b8970a96a10d799dc464149c95d19c2e69c7f3f98a283f77771a54feeeeeeeee2e7483e1c99a192cb810e44e63fb65020263cff99274dddddd6dea8a303ba22d42d129353cb288929a6163a7a4dce8c14cc21380956224fce556007a18b708734b08cb7c6c8500ad0de34419d621a21e195cd4184132450489cf9892038c718bece71fcad0cae8ac66bbe1153bdccfffff04452ec65ab4686192a4cb962a4e82dc656c1fa53c30ae94a4a0c304ac1780258f87ad453e297a62e4eebe8627caa8bbbbbbfbf5fbf7de7befbdf7de7baf59ef04185ff387bc8fdfdd9d89cfcae80f181472c06448de7bef7577529768e8b1463ca972722c7861c2982366bc0835d9418546038e6dd1c391f7de3b418c75efbde4bdf7aee179076b7cf9279a6b6828efbdf79a94478a2dfc6cfedaf0f8a79419babbb7441b222e8aa68c6f8c9a1c5572c8e242437cec3ee8d0e948d2b1ab5f6656466bb61b2ec7c117ddbfca1403d401678e9ace20e99ace5429854d66724d66d6d89a1d42924f5b13810bf2a4f35164231acaa7b5dd8a4ec8a7bd599c35b238d7393df99a72c81dbd904f9b0321da6a40acce2229c9a7d549603b733b83eba5a1ed7a3b3cf5cc243d31924f9b7433030987dd120af9b4bb1ddd88c33233815882f07a37f2697938c05913941ab009ca145c130c3d3479e0c9f7b4423ead6fc44cb8e403cc0fcafe4a25a1a1126da644e3a1538251b340db05483e2dd0c429a599529aa2cd94863668a35ac8a70d662bd4a12b5a6285b68c2e9f56886765a68039704a55723c3bb4532ce4d30e5b3e265f528f684663924f716633ebf510673ddc975d8f28d8bbd58670f9146b5bcced5ac59d88c2051473f604d515213da14c568c76d5e2933d41eb4eecedba73b24ff1b7ab8ac94ad33ec52ebb8a274ef1b6abae5a34aae38da92716d913391626da44221bab5ab489c2d182f043456f3d1dbc518a1a23524803b8421315a53437d741034629038d1ada4e4192e4ee2e1bc9ff6f85a0b7231e69a3c2e2ab21ca66c9361d69c601520dc9669a2172a28c921240728403529aa899790e1b4cc0b1a188848966655e1aeeee3423da110d89f6e4b5fbbdf7de968fc5922465c64380a1a1c3cf890b471f701c44682c11197de4bdf74e5096ac2a062726274677dddd7d690c6fbb97ee119885e1528313af27b45da81f9e0d532037de15821befbdf762104bf275c7eeee3e13659474d1dd9de541801817b9e9822f0af98ac0fa136594fc559698bffbbdf742d1ac8c0e1115fd065046ff66129641c9e8d76ab9fec9134015d60cc11863dbcfca2830286c611bce5ae0a8d934d9d9dd6b626c8656320680b90075a5062632a890440b07702042ab0885367e73b10283db260763b25cf20255ab2d00b1bfbbbbbbbbbbbbbb5f53c9adf0feff6f7924851a13fcff13d130d1102622c2f8ffaff0babbbbbbbbfb942949dbbd1cffff7f8aefdfa468cc601b8c6518da58d9605cde8bf13503f5feffffffff4f24f7cfbaeeeeeeeeeeb7a7c254ca9aa41b159731470565f54efebdf7aa39b2328af4644903353dcb83ed5d0cbee05ed04153a6033453b4a10e8644e2ff7f30c9cae88ee7d320f87be1d08df0074e0684940cb141a50329bc70c27dffffffff7f31c90516042a3081993308e9580ae1b8bb7bcddddddddd7d8531c642495646773cdf0fc84228f843de7ffceeeec0232ba348e493bce4ea690d804fb11f1c42b01d87c42dfb7f2908b818a4848637a6ece0378c3ca0a32bafbb7b1877fcbb10f66877a3a2a2ca444d8da1bd979b4d120c6226ca28499a6569416d8621a9315690ceb80d2ebe1b2e37505077d8b069561966653992ff5bdc55830a1f881189b9db126e56467125e472093a5709493a86446cb90945b67bcbc97befa50d591925a215659a918b76a4630118ebf275bef0d50adc00fc1a37a527aaeade8bafc518c348d86863972c5760db82d41576df015b025f0e01041b7b0aa0b2a53bef2da82e40eb6e7b7de52c80eaabed1637d575a1b5c8a220eb4dbb76e1fad1df8ffee893132033e9cada15d33fb193fe5cdb4997b85db19f14bb2017a2cc6b5245b231f7aadb41a92cd5a25845b83a7ba98f8d94bbad082aab772e5541c79f1d1506297a72a44851c2c6442dee20adc3483071b974ada2a63b3090794ce33b419367c6cf54b756abd58223883c921764a1e2192256f285124c8d63034417c705d0dd111a951d4777f1f5d5e3aa85b8e25f8499b9917c7f775d5d8fb031cfb60833abcee2aaf506e9e2d994294b9453131be5a26375f56ccaf48463ab3665723aaa614090f1d6d387232e156246ab033fc66471a90f358c09c22015a2059a8b1802e248d1981a8ea3c5a9e4561492540820881c6344c8c0e1c106a956935de591c20764d061061d30b8dc6684e0f243889811d074c0018520cec36eaa338889579c6c61c149044c3c2d427ef2db6bef63c00a13e091932d46ce778019f34cc33425465afda123a937651ad2b0cb4d99864e3d4c48e9a0cea0c043cd0d4e24e28a88183eccea99f3ff341a4e4e2b0465a0e471d39e909097cb4d7b425fa0caa0ff7f9ca9ac72b2916d62c8424c562d9ca11124a11f1f72c879d39e908d9b2d59c499a2bc0ad3ea61061068b2b9692f46152659b5692f06940f56622cd935f76214f9ffbf1941c6d9b4176307ce0cf9c3a6bd18313e10c92336edc10803024c2637edc1b861486e6dda836105c8ce0b0c17707ee4109bf660fcc82183d8b407a3e694579bf6666954e4cccb76cf2dd7ddb437b361ab36edcd84fbccb80b8e1277554aaf383669551c0226f666eb3c14d92e261e4ed81f36651a4e0119c0ae4bf54b88c0e5715326a79cd1be7aa43bd5dd49c8763139fd18a3a23ba7285461edb0abdd2cf5c3723c781248fdfa45d08ba0174194053cf382f00c15d2bce5932477a370e8f7355ede91cfec33dc91d1878be22271944fd791d677090c3c62258ae433f673818d7cfe88baa232ba14182cc9678add52110e979481067427eeae8491da8105037ce493f21e0784f6331f4d1ce041927c529f69e341ca7d3dd87011011cf9a43f73f685c788f3723401109ae4930245a09021df01f1852042513e6970b4f5ae8079f25d012366d45df9e2bb026685113030249f540802d8c389e9eb61450324f0c8271d621d102747335a0af9acb35dab365156f52b483e6b0de7a404a6b915e9c867bd6d5cd539473e2beebe6ad2927c565de9b3e26568e5cb6c9c5991b2e1402b6088ac7869da2dd5c867ddb9f088102a95577b2ee4b3f2ae70490a52aaaf3ea990cfeaf3d901814ce176a4a9bf0a4594cffa1b7d3a7c4bb3a30aac5d82e4b302adb086d50eca0e3558a372f9acc15df5bfaab00e4559d5004092cf6aea844c3174538666b41cf9b433162e2fa0998d593d82c4aa3be2bc17c0b4d92e1a598295c3748ac85c4c55f8f8a5b63d2c9868a1c708053271a4ca30a08e910e4ea7e8a802e9f4d0f1417dac89a36d35099ddb0532746ef566d7d1bfd456972fa01ad06cb5e26140341bb3da02345907674f9c22b870bff6b148c7a88465ea33fe8bc40730c5176bdbbc8a84d0225e3d3851c6d2f7d573a33e2cfde1253442082d2af514f5f4285f3c41eac3d2e48b07487d585af5e2f9511f9616792c2da6e9c273c328c403b5599ac5b385c6581450a0354f18de6601f7e962b17488170c28ca581abf60c1a088021665652ccd8295d92c1ddc2cd8053b6431b7cf1e1f88574febd5b313653d467a9434d9560360b581b84d584f8efa584d42a87333e102508c6d49134f4c28a14040b35a81a52aaed6f5e4562b4658cfd11a133a13482692788254c58aaa30b5d53c61280a99122ab31a078e1e3d5658c18811254a4e18b0b6add6596d70b35759af5a58f2625dbe469f8effa84f8da95e24d4161a7a7a562baeeed13b2b0e6e760993e9a88fd50650924f133db96d4de8b6d5aa9e558bd7b85d6760abebdcc6d77d550d34ab40945670bad3aedaea2cbb02cdb6d52a20537c610c4cf145aa10608aa38d91660626a52a48641b16ceca5495d845def7b1848f02445b6f0850c14f010c6001095690f82a3790ed5fdcd80acc7a8a7872f0d4f0c173a547051e22e44ff953975cd5f2b0e20e1171dc9142da46df31e1c8c2ce1d7f9ea17717795d0198cae74f4d4441c5bfe1b6f8b9fd771c613bd4a76a9f0d1695a8eb5b7336069d7ad3acb2ab0f3ea041d1e5634e8bd7565b588ee82a7a1f5f94fad89d18446537dd39339a5cf5033004aefe0d604d6abf186b52e3fbcaf1e0f5d54f49187d18b9e3d5d61aaa0b98b3fdda6a324fa36b88576de2285aad45d8c823c937ebca85fed50758ffce3636f24a5899d5549f64b6252c8af176616709879d3bfb8c9d310c60e705268c840a4645d9b9032bb14fea13b259b366cd1a0bb888b9702ec69f28b33a29675cc1c69b28b31958555d7d403f5069ba72c04a8bb21c0f4c96365f04a94c6dc24830350b46ae3c6069158c04951e93b61d73db8a7abcad2050834a4d570fa8412b98f9caf180a4e28b20d52bc703ac4b55a9a2aff36f8ff3ddb6bcf235d217299264ce2e97d6b7dc3eeb2e28a2187da2d0c5738dbca01583db064514344814e6a09127ca7064bd479bf7b85ac0a8aba8735ab8aeda6139aefd624bf025eb8d4396cddbd1e7b8c26a2159dcf4ad4d2dc5082a847527c62f933f1764b53d365c883b412abe19f14316206b0b4a9d47dd93824e11fc3d91f9855001172e2aabfac737661cdf911a35e9e465d18256206a310565fa14b57ca6e07dcff7644f8c215015ad6aa3349a26ad403fdb3688c6f2b61a5b8d2db62a8d4992c4bae2913ca894ecdaec418a440a00082800e318000086201086711c48a224a8c07c1480062ec49cdcac401a0fc62151301c0c83c280301010004120084000846220060661aaa765035dcaef41911cd866e3f7b65662434bd9da4a1c08a3eec9beb15b442d71d6d0279ad114dbf4e4714f4328aef2f27f838196fd7584598910a60b7664596f47266a320edf80d82dc6ea4eeb783f16a9dea06fa1237f27a412b3465b449b62cf65cb09e6b8ddc8d2f95b6c6381711bd83965a9d230bdfd322a5409d249a054cf38d6bd3ec73278b6747c229b3722084c202791166fd79c10d8f573901d1c00728248fc9d6484a3a0233c0207b1f115b7101553c57b42f395dee96baf115ea2eaa35305836c7c479df160bcfc7511b15ce363a28cb8f64b0982383173dc6311065c9e16d9768e6ccf496cefd179180308337d3897eddd56675322dfcf63b897fe7d1413db1e28374fc4e2c464f978b48d02e00cfe1b0063db250520be23ad83a89aadd1fcac762e2d65ad91e7220a50ac719823726bfa992ccaa07ed914dbea5931edfde2999c2b430c121982eb26deef0410688cae482c07dd5014eb0610dcb766930cdf58dba7bf2e46945168aaaa8b3f6a19a065282685612c076484dba95ace8426b896e5c2575a672837461d2bb43ea8092b7a59bf70d9f5f3abc8473fc763eac9b98eeec20525a3d7b78d72bfd7cbbfca49728d0e03ce46175c5150909f9171e8b3dd095a2b67ff8e5a90cdc88f06c35afdc85172565d85fa62bccb041fcd4cfe6602598d46448fe891a1eb490c1aefa205fa0e5ade4dec86a362678344a8156a2a773f3c8516bc78705bcaa9eb7e71702337fd419fbc8e3bcd1271fa9566dfc86ac5588bb4c4b84c73af62e955d733d1496cbe4175ff928d0a207a2c5ecc202b5c60a524e40657c405a55330bb422b8184c8ed8dc579e12174f1a22eb0396d0f6810da817ab1ab1dcbd2a9f18f2ec2cd27dfdb7fa38faecde79493c2d2449fe928af099569d413fb01ce805ee46ca5328dd3cb6b6a6f8e92bc3ae6322836e19293b390aa67339fa9f10dffdcb691e01e7c77bdb0ff109b8b70cc4fb606fc9267caa4235eee74b55ed2df4a315af228b0ee33a264bb9813a7b681e218ce2d56b4fa1020090bb8dac519e41416625d946e85ccebc0b6a2d06885840b3ea70c030f3c801004586f0a8a880476ba5db675252efc2664c2dd1884352593585f8089d4c45cf27f01254b1b9050ed4d5e11d1ed56ab3d9705b83e00505b8c018b86de542c45341d738a9e11422b3842227a708fdbe61e037eaaa6bdba1fbd679c264bb308f9b44b1a4d8ca786d21e24ffb7379c01eb1fe447eef7224311277cd3d052133f355356069cb53fa4ae0c5fbf5f3da7d765abbffd9e5d6d5c1e9f90a093c17145d66761038d1fba75a668606070d03df3c32365337bf258833e67c2f771a5a0c1873d3644c186c23ed25c91535146d9240925ceaaccc0ec5fcb9f486cd221553157026a8296edbf914a911c0d76c56a277bbd5dd9342f965a9f1282accc6e2e9c09f5dae0328bad453880d64da2febe60d953a6750a7de78c19214cb65ad690b4a27138ea28a512a2e66d7c2b748ee56939b2343951910230523cb2bc2be0ed3fa4294c59898cb1a73a61373b661212a9702fa73b5a9c448fa975fdb5c8500f9075968ce88f90352dda0ebb3ce1a4666335d8ac9ab3a65190c75a5e2c4128a9e5db03b10f3abfee704b9acceabf7468d08a7f601b83e4b4cdd11bb138a120e1470baf71cbc31cc025e9bd4e97a157e7b7649e51ea25501a95997b617650e7713324cdeed271cc242412a17cb0d92e541bf31d72c73378484a02c9711ca7a31d728b81ed17aaf278980e4279f3271603964be4f55ade1649e852315348edf19fd9e45035098643d9980583c8fa500b1dc24173b8f0c98fcee3a6dfdc229db3bd8f9680338ccdfac74406a4f052fe39db90dbfe3d3ce54e7fb1cc53949aa7db42a8fe864329ee8b3f5f1747dba6f535d0f4e5fa519710dac4122d4c5f810ac25607047c9970ca4f07a149b1e9c0371846f221d9adf7a5eafad68022379561b4faf505a2abed96c271599b819eccbb10a480945ce1e3c280c74f1cf321c43a3cd39415fc9d80a51fabee0f65301ad797d8a46c4aed15e983c281a5cb9dc825d99e05cc44ac88222b15db22437251b08ca40f326aab7bc46beaf1f919d610d0cec4ceb5135315c8a269f900842ac41a0edfa097720170628b7073a192b0ae58b7000092cb7b1d540737ebbc2b25a1ee21be805daf0f56470a5535437d222bf39b5adf61820b207303b19d79d8734ca11a6ec59b1a11080521878cf22f141a64ed3d965050456b1e42ba5bed21c65c2169e50676a067797ae570b075961f1785d3852fc911260a87acde46449d098af16a4c911ca0288e8b12b621c07f78442a4c80654762e860144b131f4df8ae167370616803508358816416d5769e239a1973d0348891d0e880867f2f8474cb70f050d2ea054733218c6cd7cc9e43b3f04dee51dd3521b221373c3cf248bcdd7c507e0b24cd067bf2d8062160db7c3a85001cc612ab69525221568a404f32b398bc1f7bb16c2a95e8bf15c6092c855c9aa2438235ca83758e664d8ea98814eb7fef6e64ae453202ea7b20863a6a9914f9436003ae067f9b77a8f2a8ab9885173c7366104d28e6c8c8fd831b251a3f72449ea6265d5fc3bfe15249cbd3a8d204bf6af6edcc0b1a09e92cddc0b093e92d43540ac84a49a9c9022ebab632df0d07de6cf2dc8ad720a63a2c0dc574fdc8b81a2421ebca585171c66102ce3bbd8b304b3cd576e69308c08f630b8701541464c68d3ba43676d84e19347883f85aa4713d065015c1832ddf14255a13221cd49f54e52379cf288fc46382a8aa0e39ca0c39ab07fbb8650cd3b98cf1dfd127ba414622c8e4ec446f2846e12797e15a7e41089cfe9ff038d4fc867cee8b17325d51ae7497af257941202d926c40fc50c5bdc470a0e82e8012450b2ece9f07b25640cb28f9c724283c1399120413873c7b933bd5b3da01000574fb65f8edb16a5125d91cd95063bcee6d2035934bef252161bdd7aa9d33522c88bb901ce4913357033019fa4763c196db5666210e9bd44ede9820c9df363832a317629cd823e21c52f13e2427b3f47d200d912c0965969853268ad84427012daf9865bde04c8374b38f834dabacd9fcc31f4414b41f0f3697c3ebb3fecd08cefa623253a973b95a1e92ccaec406c2a137463bc5ca01b2d5b861f3b1ad32953832f21b1f59a2d3dd7ef45e7fec01dd63e7667c7b067530a050ddb3b80ff95acd383060c8ebfb6a302b6c289ffd7f340766bcdcb6b37c0c816564123be407468e0e90254d0644203cf291ff8c7eaf2e44e4f863ad998bd7a10cfd6a1a23707b3f39ab73ae53c7607745be1f635643ac2b4361828e93a2d503682050c85b73a52540f28342e8439a450f0a4f6d500c7666556f47f24b54d92fd5169209bcfdec976a23ad1b60199c99c2f40c31d1071f6dc9d5d7b6aec491c8123574761c4dd0b75b536a9a7db40d85a46fcc360a9931eee6733a1205cb401357fa4204ddba11f3f34ac9f56b9daecf5026ba41ce16873d43dc516f8de67ce19082ec2cb4cb3ae057435a1e36441b3c385469d02ef31d2682d55bcd6882c972b3bafbe582b379cf85b5994d4bf8023e7f35bbbc4c3363fbf66a00abab904c41e04a2cc1aa164d811bb200023f72e49a579b876e0a1872e0ce2b8a5040c5dce73916322cc4748446e85526e5d18dff5da8faf6fc053d5e94fa22907eaa1734c032de85aa49f8b3da76e0aab630168a44c65f7ac79b1d4b1af420b39835acf8049a0ba9830b1c9114e18bcc1fcc905fce2348e6a359d02e0fd20db8cd78bbc62ed72906e14add5e660e81af97b9ebb6d3a0c0876a8886190bcf92a0237c798d83cc97ec929fc4e29f87d957a4477c60e4cc88ac7c108ca997468cd1c42edd1d4ef1b30317a9446aa1b4406fca5b022ed8187d9ae7d45c430fc649bde2c94a0739047693b0160e4e25437b0c0b074fb87b5911d006d24071e8590f5309c861cd5b2552b2e0cd44a2f904fb2afc0c3a6fdfe8cb256ec397f5613d07f5418966f69f561ade10c06694fb33ffa110164604f2be979fb8caa240a799bbffc8bb025d0ba8831b9c429ff9d0159a0e9c41e0579b3ef26bb2064e813698219ff988ae79d28540faaff6273410d8dfd0b87dbe34236f2698417f3e9747f3ed6692fb23ef3e690d9c0f5670f2830806d7b10267dc3e3fd45d719669b4ddf1f8b38084a59e2b062bc342873b4b30077963c6e0fd7dc4cf7c296e520e2883d517fa63d0c9cef59861281ff992ab5c890b6af9ce1f3ae121a277336eff99afd27125b7df82fcfcafc5475a65fd7c37308c67b16772572930fb24f995b0af000461a6b71a1132e1eba710d74fb1138754252c3143473e54fa0872e5b6875730e34ae386ef305113fd87e80017fe05afc40fded7972997cb7011db7d96afaaf85cb48c240d1c21216c5c0861e29f35ecd7f73704d2d4cd8efd17a17fb6510d1e4970837c0c73a6951aac982ea9738ca0a094490a085dee605e34b0734442087c302fc3d481caa4a80038d1301b0de0c1c1168f8cad175655e7090fa387166349dc9f3c3aba8fae2f773ac3273e3cb6abc9a09f77a8b2fe9aa1a9d3ddef039790bf9aeb21d27fe2d50b0da4d15f0442347dc8ef5106867dea37bd64ecf027efbaedcb13d72dcf73c9c79250eed8708459550496dcc356312092ab1eb140198d22842e4386cbf040f883d7c9ecc02ae29ce06a5602c75e173d4b08d6113e64d8fbfc436f026212c0998a2e64b0e13c554a61fe2854864abf82f5351a0050e2714d88d7bce94dcf7beabd1e89e64588f3e0d4593ef48a950582d88d14a26db1e187901bf946c1b5adbbc114e931ac708afa75e78801befdc31e05631e9ab032597aded3ebdff94d7e0814c50aeacb90c0045e19d972ef79e65695bb3a7c460dc08544ded09a82f05a2ba21059a3984c44f189dcaafa296374c1836e063656c3a58b83827724b9987b60e45ef958d24ce479adf051c2085e57390867af7e606e8987459ef422cbd70a0f7c24d42faf5410d4f65b1d6220d97afc9fce741ab969c2d9df67ec6cac5b7de9514ad8591e1d1adb0b3f46aba7cd92bbc777293fd5fbf798eef4ec39ee2c2d38d1891de39427e6c8ee4bbd539e1360f8c1d5130bced59ef9cf828548050386cccd24e03490151be3502bbf33842c49cd1bb2b2fbb1e1e5dfbd87b435b24be61f405f5965fb5931492f850b3664f10a2e4f346ae6ba5ae4c2be86a71150ba31374ede981d8f6205ac63cf3bf6b1b4d21ba465737159c2e7fde5fada3348af348e023b2e42f1b711f9e8342e01559b75880c60b6c4234cba9f5f6598a1008aac3b2614bdd751af0208c0ba9f5e402f912d46926f684e8a6cfaf6a0322ad9d9a49f3b90a7988d7b4b0205a619995957149f6f6797f4245e5e0df89ab53ca6a2cf62d3eac7c5c559228a9d05ad1902630fa60c1306f9e183c1285fadcedaad9d6a15978eeb56e1c11eb31d3b6147417b99a7abcba82c88eb98823549aa5192b9a78132c50571cf1d5d258cb147dc410e5b10d8547b5665117d4bcc15ad664c138c7b671988ca82a2713bdcb7f57c53651a4eaf527a717144a77831b62865a106c10dd0a35ce27a69ae015ddc9105f1e517b104856fc9887a8a9d888096b959929b7606d39b14974131a285d6bbf44bab7162384ad8008636532ff148ce1dd2f5d5969714c0c47199993b05d52e63f12f96d3aac69822fd24a7bb5473ace810f70998b579c51debd1f587679a86298fa84ad15ac22a630f12da4ed9c986a9b75fb27c5def2c0be592eecf35240168e268ffc6bceb0ade694de6e7f56f3ced94f3637d426fd65ef542693a4e4d886357ff92b75cbeffde2b55d069d34820f4e92dcb024cd53724a33050fa232ee7746b6a8d4694fbe1c1540a8a3a3adb3412a4667d15c2837657085dde29f614d451032a5ace750633701ca6cfb0a36fc16a5d3054a1234fa0d5c827ddb6bbd4b26c2da7ae29469e64c5eb404be57aaa55bf86d75c016ed8f72d07d2219cb584ad3983d851fb20bc75c1a012b9d27dc3cfbc25456a273d9ecee32aa5536e4002311f8614bf4aca250b9bac9398a59fea92947d405cdac42a2caefb243fa95fecca2ab84af150e42170139bafd17ca55c744ed421dfee09a9aa4c6900ede48a73a77d5ae6a509e715f7d5f13c76b7e40ee93cc23a87969846a1d7d901b98bd6ea2c9cca7e85fbb612ff881ca57d7af06c18efbad585d7cb915d21e35758a28484dc0552a9c1324c3a0905d9954c32fa3326cd49d0294060012e72ce8d0e16cdd425c3a4e77a855167a3429ee141ca30694b0a6e1e66141053340f264840aaa069ecc57ee3dc157a813bcf53886098e28c6b4b98f68d56986b090a34881b2453e77e1f0611a36da4b03bc6d7c0582d59606d98fde0cbb5fe1d5b268b43c830d5483f74581866b0bd1834aef89427e9a3a3ed909e31107840836e252077f6c34f9d08d09acac6059005b700850044b9171334a278aef02e13c18491299b31b92440ab2f063dfb86c71860f56e26a6959fac8d1f757009744716ab4264aba3061e2880a98c9f680eca3b3729f82e54ba15004a9c3be65b26002a11843482c07cfbae2c94f6119fc065108610b0a2c81031d4718a30c5a9ac9e12bb1e0ee019ee7f5450aa5b3e32dc0988d5b180e2811c87a66bf4ffcdf7acb4116b23e8d75131ac94b3cc297a3a31503a8b02a05b93cf5bbee87d85b953aa302dd74899c9678b016b46236999a4c5e216cc59ca8299d54a2418972329997ca53a783f7eb97670b734800fa9d0c311a9e55ca077ef057be69d755f0a51ffd0ef00e54d98be913609d9ae7e194f2110d884bf6946f4b80e8bb3abb033356f324b4a9f8e17bfbcb10b525368183ee35e8810431cfc9c139c39d4d53bfe98d829c82dbeeb99bd07d94a0730dfb438f602bee19b33f4db8088fdc1bb710310be3f208f99bcab20568e05342cb6e7210ae9a36a69895296c344e9d131818b03636677985b0af03042f81d3bac0b0ce89d9202fc626e8a24ca8d6e610e01d5b5bd987a60bfc3f70ab51802e044976de6b09808234e9a0c82685c7d673af1a2249c8a4b515528266bd5296675021c310a4ecf73a04b7c78ff01ff20403e42a1a631bf061589fde19a56b6fcf58f06747c8408ca85c7c94dbb589442b1c708d0cc73439286a11b7e7f9740412332b112a76f168399eb7919916cff84b89e71cf97fb94b0695980eb7cd03867205e3999f2f87f83dbb63cd8617e3b877180503262a06324c909982406cab9fc6e37536a7afcba7edcc5947a625ab3a43865ab2705ee0bc59cc18bcd94763c02329e0b0a286901ec17e6e3a708106dfecd885756043fdec4e1db5802b956000715f58161e6a123ef54bc668dfb15cc10ed4f76133f94f05698dd955d40c3a821169d64252aa032310c6eac00847890e9c1e84ebd0c3b22a1a34040cb4419db11717c1f296313bfd76490b17bdf8c5606fa900b5f0511105d37270916c004f00df41c82d6b99f837ccec71cf89494aba8c603a0b40747e83719eb8ceaef2e17b6ffc3af5cec38ac9241ebc9435e37d0761bf90b54b956542cd253d7081ab0b11f126dc885d0114db905337f57320b56f61d927a6858c72d5488fe2b110b8d37da07fc90dcf68f069ee7ebcc31a8e3b7ae0abb27adff6c9597c7e9b7f932106718f05357deb22a16d78270f37c73b38487843d509aeb0c8d8dde96e2d18bf615d2bcf1869dff3aa824faa621c33bad8260c1cf1fe5311cdc66304a945640037c098741580b6405805067afd27743a957f3cf3e9567348de97e7453ac79f9a68490cd6447e35600a5f838778fe286a08446ed62f36babae4d6617e2633cef833ad9fee7ee7b229adfd939ac29a2320d2ec0b0d3f054069ed9ce2b03b456d75838dff67112ec3b4fdd736eec4e4808125a32a1b4a0568ba353f58de455c5abadfeaa74ca0ea9980a349119627db4ac393120051c15f236f7bee14626aa7e7cde61d6b3b592b98ed287a1a378ab82ceb82afdc440ea25d57c17888cc7eeee9a22a2c6d35ccc5c2541d411e2a913591c208c0cc0bdcca8eab7b088cbcb5c3866d9e73f1e54e55fee21bed5cd0892cd9466bce47a6ac5841a93ea916c1cc9d5d81da9aa210becadd325775481326350e4a93117447578207a84b8d444fe676054019cc199281b03d44a35fa6958a80908c96adf5272c973d094309153333503ffdb4b08c0c42e4e3f0f7505b6a98f456c0c5e85e9ca965ab2b0ca00c8086552aab371530d787a7c5e09c1f053c44cf5f125dc0138c89c86e6dfa9bfc9b00c860a227869f2fbca3306de64098bed71dc15b6be18cf125fe41334423b2903ac26e5c31892cb64d32e7a88f474448e28236f74df2bacefbd585a06d41389abbc541ec54c1745fd9d4cd5fc6c4561f048377055de56340bd5af104ce331c126cb6a05e394faa4d91a3b26596f5739f406ae129e7e271b84bd74f30bf4fa74bd1d04f3d167960b47668142232cbb9569f30d60942b99cddc1b906c37c8bc883c0b37f0480589aa22ec4e381727360e819a36b5943804ecbd6d6648dd14ae908e10556ac4d5a7e71922f1bdac47753edaddf1c3aa9d0f66152a3ec60d89361fce0fce12ee94f59e6edae1b3b399b101d0eda0a4e5298f29cb94fa2cc665e2db8b5ed78251167e42a4ceeb27fedc22ec390f9c80c3fbf838d61bacbcff2bb03a06a9c17cad4bd87cd500f2e3013b450535f95e90e521ef174c7571bddb1ad2d47bc9adf2cc09da90b49d83620c1d6e4a3fa421f8fc9689527a503ded912de684f26001ba970f590f85e8f9c007224069bc2d6a692ee5ac6a162360ba818287ee85cbc4a7620dca72a288f8a883b81232a294deda21873bd210860b4a55c0ff168ae901ec24bc957bb97a091c56cbffe26d6bd02b9f56e99951a55f019739632ed6df467fc7e5d8ee34e253e383df569436983b05c148762d64713726202813a74a63a282b7474cc42b6bc9a3a5abe6874d38155115abb4fd7dca8215843f6e508e90a71a959ee308b6571dc47c36c1389023f56dd97fbb0700ddc1a3f3e5d3aff3a8a15e62e97c1016a060429d79304bbced7ba80542e652089f73d1e4d190244eba33c7800222013dc6348b4758b09220e6adb7fff3ac291a464dd5352118e3110e4ae3a294ac5b8b58e7f2cbfe1bcff865f95b421a63d764e1d4edf08e04bc24fc3a83478ce01628729307ebcedfc56fbece3d62fb9cbe952bcb5ebfcc08a3063865b601f047b18dbed042ba200505c1875639891b3145355b28fdcf93aa4ab71018486ffdcf6c4a967a780436b4d0f08ba907866bfcc44b1a618f131dbede4cf21bf023d437b72b88b3889b12784335628901f174117659a075b2bc04850a6dc8beac8910a02670d0a913e21313cd00164a249f3a676d7c9fa34678ea4f0bd0c175a8f6e8cd5d1e70004e8c27c56f7d26ced41160f8241b5881921734f5a9c3cf2f0115b37fdbfa38caf760080008e91ebd008db8009644f70eb5f59612487232ee621059801696cdbefb0126652794c02b640e2627de0b88c2c0a609ff3a23693567c4877b44b9dbb1f50c311802209569eb9a0ad236a6c2c49af8a8a91a04934f66609c4ab66271998888edf01b9621d78b176a068e70e1286925a2d0adaa9b9a7e125c209fb0c3c0117f2b0e8230e759608a50fb4a6fc7cc2ad5ec283a994234c1498ce4f62d180d4db116e27030f98580316191b29bd920baf42f2599f49df2213d462a63970a07a5196a5977bb204c4d6751f49e7c107c9728343b4085d6693ad470a35b2f529e0c6e67c0cfb263820d15ee50ea29364f3e1b0f700ae1c75bafae4440774e850ca5c7afadb38d652a48bbd9a6ba17bc8b01711be063ae1ee84469153e65ab149645e634ffe9711c0fe8bcecc80b556989de96ce04d1018a03060c1cddd06cbcac002c60d308d36c46dc5f2cc24bc1b29092ba283189c2b621c6d9bee715d33671a1bd61808a9eed32579725a08db5394cc8eb6a1580077a794c21cacb174bde2ab2b897c1854949d69b077f3c1b2ea265a51d4ccd3ad6833749014026fe92ae18189ffa48ed8e4d52ce983370c99e48069e86f3771d17d5d1223b70b93ef5b59c3277a8df58a79e442f5a9da5867580cdebd76bb6cc9e8e6fbca06d08f87a71c004449187a466055e254d89f1b4747d392883eee99f22319cc56229e22fc9814ff0be88f4a1a1eee88f57417869718189605e2b945735eb274e42ad15708403b0091e5bac93dfff545365f7c6fee56ac2d3587f9bd79c39e8726ffe6799e08541731d4c856bf08f62248806947cc4a4aa953db27c6572af45a854ef374fb1afffd630bd881b2a099d25177b682d9ca12ee62e847143c83dc467b75b1d5c3047db034a8f5970d79259ab05cf26edd8f394de89b6129c2ca2a5095756c3674991264df4d6bd0a20b046632f098691a2ae6ac39d74b958767e17bd853495aed6fec17f1327bf002730ff1bbb0da0160fa2f9cfde1ca068cc70dd9b9908f0d330667a8fb538c802d8ddec8bcd342ce11827c8d43723617764296fbee61353f77d5a9da5419a15710bf820a50856dfdda49d082743142ad9f8d881a0f76d42578cfcbd58752f2e8a327edf6ed16fac59024f14c37c3dc80427261447ae2850ab45121feb91ee8399d5835d9145a90ff081f1c2f07a5382e4399fd144ede122baf4c68650c74c21748c2352a22e2299a6458be912f3f1c10a81e4a20c913c6e4f5654f393afc026189004497436fcbeb66095a6118d003831e58e00f10d6b5842bd2ebc736224113d9bc6a494a6571be6a89a67d01bb3a5c478e4fd533913146690860ec2869a84ea29199a0d288558a9dc8867988445bad6da28386eba43662717e174b8e9575aabcbec8ec9dfe1acedb4f4b200de5559dba7be27ac5b1c5cd0ae014efe5d19526592c09fd3b2a3e8310339493a7ced27d494b2dc1633d36de6aeff35f32794f800bba3fd4b87a9612986d9837315330decff9ad169970be87aebb4d94352f626dffda9d936bb4d9fe7083e41dde0d5f9980b3930aeaee584475c3b90ad44e3bb5aa895b5f6ddf289ec8a3dc75cb405f03dbcff82f590635ead3c84fe00b63ba77165b1fa41b0259d0a0ba9c5f1e76c71fa5509b06b8bd5ccac04bd20cd2d3d5233513393da03cf253fc5ca3d510f5c51250fbaf29eb2ee9cf9bcd4584a45997fe4dc4ac791650b4ff49ef0a4163964a3d13a709665876fbf0422e0baa85e39c10b2a84b2109fba88cffa6bc07a125a6b52b04ac68596af2099e84f119a2e2ca0cd0dbcb52da455965b12e325ea50131e295617cefc671e152780c3a8cc96bdf607b2c6f5184eea003445d013fd2cd6886f7dbb552a36bd37e3e8d5dc0fdb13f0fd1eafaa6c0b37611cab8a9cc4eb1076fe8ee594243123266e6eec3709e81c6f07c245c09ba572d5072d16d98394addc09c85d09f18b4902c47c8728bed90f8c4c41772e7d13505f2102496c0c43166f0e8c90c87c044652b75e9ced6f558ec1662258090be57b18fa10c716ca4e6654d9d5c88e21a7a272b1481c2f6d64576d06a8a3297676845b89ea895a8e691e562fd22989e74c723972b0888ca1bbceffff7c19137f943a28f8241b68c99db2a723c494c00fd7b3fa6eb029c725a4918039e32a89235e2ee5ea5813293ebe98be91ee97dd8bfeef4c66041028b114e6578b9c058c9d1328ea4b4aaa16e0d3018e0da263cf348d8b0580a86910bc2d3289012108b6bfba3252d02d6dbf00f4b552d044a743054c2ba6113f835ca1b7fe149e1618a4894114c5bfb518a86d9f00859dfbaf685f88d10955d673572bdb824fa204b47cb31e0895ffc0dc5e42f892a5f49019378b941824d07f1099835cbf1da09daf4932aa3099fd5ca1d6aea52af7c5c09202322a81fa4bfc87611bed546bbfa67522ceeae5023f22af2a923149aa5ade0d5adbc365bb16e13b534d7151bd1c869241e5fab4c111df0a3a3fbbab8a8a7ad35cc35e53b4935f8a3292b43cd384c586d133b2ca7818c228ed04b433af5b0feaee785a5e5aadd540fb142e785518f9f5cd5cdd0ee3165aafccaed106f0fb187262d2a96c8e572dc45a790a45aeac3c9ecc876f6658986f9977d7f8a0856ef5d8fdcc2ce85a49eecb6032a21ba655edb0230681e7274e6bffdfd0a99bfc7b0e9b819959187c62a5c6bbad72386172e0d1a3c01ca024a19b9197bd045512ec297c343e505e3465a9445ce5c149469ea6097b5c5d23d19a7a94b19e561856244c05f61cedd2cf9c1642b0bef9d2a089039a6c54b2aa95e1c481e7057bfa114074b001bad110d90057ba64559f2e1395b69c902d7c932c0b6f07d33f7fb7399a9bc72cb89696e3311282c39c76796e3ac1cc42c92c22fcb8c8d8878829f400d0aaac36bf84bc614281f7cfd6616884d174eeae97c503d2d2bf8e4e5954bc962866b6896389c6632b5a4197e984f1dc82fd739f03267b10bbd5d756f7e084da5aa2e9076c93fb3525bd6ebd6178331f434238ccda3161f5677c3896591aeff45cf4d0712a485eceea53cc1401ad7b3127efa8890c3dbd58a487da74e816d606030300aa3138f8b349af15c273ce5358a343a86693cf91dfcf467a1c14ae25df7ab5b0888be7ae3ea82b72fa273edf5767f0b45e7ef5da6fa05b5e7da4de77e0485bf9ab7fb3efddb783c414dd22530854895495909f9b2f115bb4428015df85b1089e14711aa071cd16817d058e1391aeb06388d313b3fdf6887aea6acc9c993d1e358193bf30d349e55239e4dd94b5f080611ec07db1e388c81e547fff912a645e03ba9d26855b301a12a7037d80cc12b952f777b4f6005764d25bb7b8c90b4b32c30969fcecb471787784242c19008d92a243175d9f7b01101ef478e1201ed781820daa21fc03cffe2a22d1067fb16fb27b4a346a2224a4edbdf796524a9992940134080108980836ae0ac2c2c969b9563e602ee8d6c630d8e66f3a1a9c4ee4f9d289397f077f41f939e79c27f3ce6c9264ce86bdd25feeb3ee49a13779a23ac2a499f97366fee4396958c0cfa05c357fce393fd4e49c7eafa37cce594923d4e9b5bf29fdf6fda5ea37439a6fe34d0f6435e7b7f8cbe827e969b4277d3fe9ab49d2a5dfbee6f4da0359c178a9feadbf6f5b9fc7cbda9e73ce39e79c73bead1d95a860489e4f3349af3d0de9b5af26497ff6d5989e94fdf6d58cfede2433f84fde8f243f4c5faaff4bde8fd197ba81f4dba7faa349d1d16b9fa219bdf6a3d44afb6dce39e79c73dec913b4459550ce4819e3e1038c67c70e367d8ee1168a67ffc4bb7ff2b4377999c8dbbee4859ee47528272fae4ca41d3b3c403b8078f4a783fc68623a480c81bb9be9118bf9e8c123f6ffffee233549a31efda2d7d130dadbbfc9fe9246ef2f83bf8cbe54e327d91f3d8dfdd1777f34f77e8d16c69e9a2434a3bf5f8dfdd1d7dc277dd892dd5f6e92f403715749e6c7dc9ecdb24bcd984ca7af5fcde84ddffdd2d3dc2f697f9f7e34f64b5ffa6ab2b7f56b485f5ad194be66f4a5d575d5cd2c50813fbb1288641b1285c4cc0de99b718545dfcd4df6f67dc858383921e9e201aac45eceee50e0cafe50e0e27e154349e55031c0fd5bdc2e073e81c3916be43f4242be57060efa74b2ffa7d32ef567f4bf9dcc28270658e6be30577f239c764931c0b3ff286754241c1d19c5efdf6827d3bf75ed5ae54fd912066583b5450eed4e86fec8e5231efff9e1c895bda5416ff95c350723147640abfcdb93239e179280474ab2ff4849bb8477e52e1a5ce51fca568843d4a3c0649467fa93edb1a73d8ad73dc9e3bee489fea6e6ea04c58b2b921757a58d0677ff95fb0e57f937eaf94650e800d3ec63e6151d60cf3e66fe86c0f3b76f081cfeccc75820b2b0106117902a9f5ed8e29d0522cb0ce0102c9f05b00996f7628c42fd83608ef7461fa979b31efd3efae987435ce16f971e38c4d5cdcdf6a6bfd1fef4fda5e63773b3f707fb4f6054ee97ea2f7583e9519ec6f4281f82a6d3bbfbcdee2d20ac1d1063fafd1f105f2c1055fe1ec1e872631836fde96364a9f667838df238c415ca9fd4d464bf7dcc3417c5ab4942b53f7d3f487fbf667bd3f72309fd1fa5cfde7a377b9ad297c51f89bcb81a79127f3737a2bfe9fe66fbec6f427fc3eda0794136222fae7660aec117b818bd688b30f82877f724fca594536c29f93177cbcf31764048306e4c810a1255c21858b9ff37299b9e00fba49d0c366db3da9f6c5ff7de2ccb3a99ed374ddbb6ad9309fdc6715c37c3cc5c27d3fdd67534c45d91a89311fd8639adcb7e1bc58e3e2389567b338db4c92e24c2a31a9ecc5bddae27f3b679326feec9bc759eccdb860a02cbdf70d763fb01ac49ee21beccb1b301a544ac058617f1c55b41c0c28ae8e23c36fe72faf8fe135f503ebec3fc3546eef84fc4ff894518892fdee32aaf421122d1c5834810c1fed087e4f84e44749936393146fbf88e136358316683b5a0fce52689e84b2f55c6188cbd7872ca5d88c35c89db4edc14794850dfd5faa11354adb5d6aff56badb5d6596bfd5aeb11b87a32c7486bc7b92769e84e4fe6cc93f97a32c72ce2dcf32cf290a07ce72139a17c0770b9ea004e1c008a00e4ec3bc04e8345c035c8e5571b5650c7b20ccafd1ba5eecdfc84c5d13ef3e2cd4460e0f08335cd28debf5c65bdef892cfdde32a2bf5fc94bf138cffa204fe48978211fc4f378632318a7c8911557832b3ad76e1911445270b89f0fd62e7549bb50cdc30d5aee87736fcbaec8d23a42a78808f62481139e48e1a15e0a4e4eca91065d4838b15d13c7659187c4f4d6fb576469d363f15644b01f871559da4811224388e8796289238a40a5e0b82a2527e5488a8ef67dceb581e2c1b2e63273b2732128b2687f3d17629145fb4d73610a51a5bd5646d65e8b4204b5d77e9240bbda4a4ed6342259fbf0354dc35a0b41b2a6fd89f7c55ca57de67d410d6a1ff23e260d6adf693fbd6f4983da53ed4ba355da6b2ddc644dc3c9e10aece7e5aa959d15d7ca122b45ace844f09f5869d93bb56ca5853fd807b3bf698f845252ac41d7d9389ddc1365144f15530145963ea9986415183bae566469d5122a245447a8745445a8605af45891a5503db1d25a71b9aaa5d3e04e834e4091d3200ae58fb32f9192d2c9681ff2621679325311121c5f874715ce7aff13592c17af85fdeb7d4e64b1d6ab60df83ee17be91dc6feddb6bb115d911c95afb27d65a6b6d4e0e577e5e3d2bad1557645939225c69adb446797a1f5083b006bfaf93b1ff7533cc8a0a82c30f66a39b010a4edbd9b2ed53b90a70448ccac882b96c8be107fae39449b6b95ee0dc2b699e8ac753ed984c27aa27544ea896f05ceb17aa8ec8fd1dfa18b743fff195d70a142b4a4ebc959d159e15241a5cd14941f15272525288443008d125a548988293c2adb0602f66557d1118385c69ddb021f2909c5ef3bee53d4e64e9d3ff91dcdf6f2482fdfd45727f3f9108bec690e29ff05079899fdc47f49fbc941c2f05c74b6935d8293a2948e4ee97f7fb1c1c40b9dba5d2899352c40068581c402cd443727aec49d40c89bc0170eea5f28683738f85dc79484e4882fceaf4e116cebd1ad93d94bc595bb5149c06bb56510df0fceaf1605d29395927b3d2120981a75d260d69cc5d7370ee99f2e6b2a2d3c9acb45e38035061d47533dc6cbf149c34fc05078fabfa7bee0bffa070c0542ed511f1e58da4e0acb452708c182962fb565a292bad149c2572b8d2729e1caeb452705c3a069032fdde0055c0e1015c26efba4ac632fdc20fca1d1a9130ca4fc9e4a820987edf12fb3931867effffc498edfbdf487c71018c0f46848891d117ba9122445fe845f811394cc149c1f960a78e01a34c3f1780ee4e4a2bbb28a0ecd6ec06ef3de20b0c8f6f7581f34404911b6604b9633f0462e8228bdc601072b7f8e47e8f8710264a20bc78f8b024f7d7dc4856bb441f2cca90ad500ec9cd630412f44f8f9fc2a696a15da80b7213c9618422f70378d824a7801b45ee2a72d3910f54f5eb2a97cd93bb7164712fc6bc68bf7a299a3bc31e3cbb7f37f48a7e51a52710ef0c678bb33d7ab48aeccdb48d83c9f136a2080887332463f4281767f449b9e6388ee324c7452d1402b9c1a974608d287038a7b748241289a44814b95027133fd387bb50cbd0ed62d7755d160a8542a04824f270c418e30d638cb778ba27addb4222aec3200871d10b678ea4de7e46245249498e7f8a27289d0c55d2205843a24e80e36fa24e66633512a9a3b754766da5a9d44ca5bc53299296912e89446a9224915a9e9821860e175028725f46557c7947344a00c9f265430427ef953166342023cb2f6cb1f111157998d8a24a0b5b609752c618d365df9d8cb689b6c0f363143dd9fef41ae708042e569053fd72069c53fd22e9f9985fbf451eca06e7a9802d0dc22cc033f570b38f1e7046892cfea788a33fec0181c3f8731b741ea411617e0513213ab1a5a7edda747a393cf0071c02c9314629bbbdf8c993eb1b32626afc4d1b12856a5109017f0e5bc0f9a9b47ce73a05cfbdf7deeb82699dc04830130cc6c2c92179f74b788e304ccbc503c3b303762fc628d43f08ca7b3146a1fe41b0f14847db8a47a39208bfb55b4bebd1c0006fd2a76eb09fbd0ef5473fbb99fb239ad8e06cb0bb991bef07fefa76f436cbe6d78c68ee93be1afca91b466f9f668479b8299ca08c4a279c73ffc4b36ff2b41f79d99f36ec752858de3bbf1fc0b7000c760118ef29d32355e7df92e8fd55447844123dcd7dd1f78bece31a2d6cc9d77ee439bdf54c5fc292256d44f74f4f73ff24fafbf5a3b1d4e380ccf3b76b5333a298bf991b7b336de3ba101544a352a896e82dc947f588c57cf8e8667f539f34baef6fe3fe083dfed17d1afbf7fb6ffdd25743fa7e84fe7efd9aecbb3f92d0841eff8fd28f42a9fed0df4fd184be547fa4cf3e84b1a3547f8a26f43990bef4fd48723ff435f6b3cf21f4a42755dca39087a9d4526062c5a8efe04c1b1c0ff298c3fce7b6e7b88be6e484de5deef21de7f11e11ceb4f1ce01ea1d9c1c7705951193990d2ce8878707c68f7097bb5c07ef47b8cb5d2d030cc86d2f71ee45792e775bef47bbd0973b274b58b7fcc7b57d992757eef217978ba777bc7b7678329999ecdde53d2597bb7cc75fb0c3fc853bc8551d7395bf07e93c67b9e7c4c28e0dc1a1bbda89767128da256c26d97dc7795c9a9badea9730a098bf6c5d1096309bc3de79dff197ff38cc63ee0255dcf526d6254d21b9f60b265ffdd3b8258be5f4db3acff4cd62b16ee3e4e46e752f67f9eba759f3eb207dd3acee59fe127219720f23cc65638f8e26a259cd6a157413d1ac662520c360f6ce47aab91ef47dd02fd5fff317e0c2a3877e691b57f96b5fba614c83067fd9be739427fa1bed4d2c7f912eff66b82fd5cf3d9015f734d973a22ffbb4cf3e99e32a7fed932c57f90359b58dbf34ebf3eae148f24ced598bc46a568cc1f117ce5d9afcf18ff225815ce5dffe2114113d24a75dc216d2acc611d22efdc5eadd06b7b9922cedb7f7972ec9d3923b2bc9f297b8c2c969b97678b2ecc12ffad077dc6f1ad8389dd3ad7635abe546b3401207a436e907d23aa055f27452328d48a1fa274f54f2ae16f2381b6a29edf7039672b6fb7ffd9bfba2917d7f8b55da258a3e34aa6f9fe6ade8f157735ff435d9d7eaee363baa05837836e800194307b15f9fc67ec5f5455f4d68e3b4ec6ffd5bedcdb48debba1db0d166c6e661a061a20ee904ca6be6e434329170f628de3de97ee4718f3dd193bc908e3e99482dd70e1a16d0cda02c00835d0085fa07c1961618180bf4b7c3dddd1d266e5f6b45655ffa9bfbdab6997c7b9a6c337d35daf783f4a5ef47921fa5df3e73984c7ad3cf493d0cc8183a884cea869393d29f7c4d7a53ca7ee9b72779a9fa299b22d5ef86d26fafc3f6251db427452e763b264cf274566c2d3aaf191d787274e0bc462f9417f79241248bf428aff4289ee947dee94fbadf3cfc5a67231d38393d3a7a66ea0793e3d5326f78bd708891c5e73713593cd6bf2fbb1ef3ef8743d7a37ea9d6486ffa9bd29f7e7ea9fe66b46c8b9d3d0de9b3efcf4abf7d35a72f7d8de9493897bc548bbcee39fb45107960f097aabfbda67daa6acf7df69bac1ff252f7b70f7de7a56ed83ef4a9fbe5b07de839eebb1eb27eedc5e9f5884d9a34b9420f99ebd7a3e7899784fe69fbb8e2e8671f57242f45bf1bfc37a28f3ab8ca5f84232c76219b99972b1483538c491b96c421ddd08967ffe4656f1279da87bcee6f8aeae8fb7a548f58cc470f1e31169c86eacf39ede3bfc97ef4fda5e83713fa9881ac5afca5fe0d859ec67ee8fb43a4af66f4c51afc4d9128f43737f7ebdb9b719dabf2b8d3fb0ec1077f912bd4ab6786a7461029e824082568245d353ced515ef6271ef7246ffb91172a79f84f9e4847d7f0e20a85729ae1e9f999f9f141870c527e20b23808a4caefc51885fa07c10f4416f721b2380f0d0dde8b310af50f8227d3d7f7fa5d3f1ce26af4cfbde6af72b36f31bdff562ac90d66e6100646c6d0413c8499210c0e7175fa526dfa52ad75b6594e76a999d39bde763d6c90b93e0e7155b2dd4ce9e4994cdf6fca1ee5abd93efb1a6ea634a1c8dea3034ddca6ff8a0e70e71bb4377d0ed9973e7633a7df7638954c2cbc300f1e82ec871168a6664e6f7a9ad39ba2d39cbce94d5f0d7655bdfe72faaa79da5b943f3d0dca9fbe9a2416659a5e7b1a9356ca3eae48a3efe6066b2f032db4a0a2e2820b2b2da87c5f0b2da8b8e0c2caca0b2f80a617e40b2fa8acb8f0c20aa85a79e1051054a96080410002b801822a150c30084000376eb0b00c60000420000c2c0260c151a3a7468f9693e76ff25e8c51a87f20f9a97670d839332701d15561e3e4c9ca01bab873624c97a78c0105e12012c855f3bfc0a1c772ee117098056553d04610b520b246c4eb68e97596f36774682451357f0757cdaf2247f103d444b58cc13f02c918fcf398c411468ca19f931159266a07587e8c3174e0664a190000207038f3e790d7ab1ea81160ff6e24f145eee420cf5622cffe4114797e8c5504b96afe9dd89b2d57cd17793bf32738479f7d3b3b248c472814fe9f2fbf99e3aaf92a25b2a019b3207f91afa8920f82934effb95f88b3a03c652ccbd772b2e6b2d8a28a5b2ae5c493ab3de4f9218df172f929dd414404153ffa9c4e3bc617fbd24a4ae7f6826d8bedb243b6b36b9d3de4f81dbdd0c403ca7efd707eaa866963635383ac61a2b20eb75e48bf739d1fbd90b3f6a7fdbcde0097e9c7039763e5c210dbe9b472d7bd9066ff9a85598e1be71e17ef45c2de3ba91137f39ff3a9b5d66d0edb19a16d3e3062e39c78ae9b761ad1c5d0e47e9b775223f0a51f3711be5c0d6e04d68488d727757b39d734ad9dbaeb7455fa5baf5f75ae93a9b4e6d0e9424174422219bc88e3ac0d1d7c4df273f9cd06fdbb9bc7ae069dd2964575794f94ca401d26ce8f76d607d4b78fd2d91082706ac0fda4b3a13efd5357833ff55396c33fdce2b306816f8091ea584083fd1a12acd260ffd33a4da5926603b555eba4d16833e1e881ec5e3aa77d5167837ffd5057c3ecac06e887efcdece5b64e0801f8bd576be2038511c07097a30f933272f83a58cbd18749189995d7874917f9de7b3f150ffcfb8141ae1ac5b028471f262f921018e7e8c384e7c11d1f262c7a0339e59453727e31973b19ff9ef3eb4254844be7bc9dccac33bb54073fe79cd3dd7dce39dddddda7bbcb3967cf39e79c73ced931aac06f81093ae79c3572fca2ec24a2e6452cf2c81de99238b1514be025b094ddb2c5007bcaef066292fb652c94414ff821876d933bec1b2161b31aa791b81fca1d27a0d882093b20920407645481d22087b2078c17e450be2416b95fae922dbb6710cbc8dd5d6389110ca115860e84b033831c4a1c2032e4911ce5fbfb0b9022c408e2ea990117341062d54680503a021a3f000da1e70541abcec9ed0421b99b0a1b3672a802c60c60004349182e08e38b1860c85a460151c1c5cbd9d74e269301461a8143540442128ae410e52fa817902bdfbfffe17c1bd3fbf9edf2a18d8c72c214d95a2ba9c0739d800343ce010efb0543d9d8d8fcc033bdeb2f0d837df19373642f02870d6b01bb2470d8b07eb54b88026a17984de774ac3b43f6c401c3e1cc12c716389caea385b858c27cd1836f540284ce0ca02081094c000595c11639424416be2f8e64fa35eeb715b46082236be67cbe5041139ac8f4513a198aad00bb61813c29c212a04c2f6a01333126a200d0032904210518558861831874e143ba1165941e02514896ac20d39fa64e865e2dd349354a29c5f43113204760106362843544092d56f4c176a13078d9104129a55d17b4d4c9d018d3d58569235441400e6fe49021cf5884f95d782105ec064a86c0aaf082065e9491e7b7c02c21499eafc3c687094590992fd809a40b9e5dec20d3177d2f6b73e4d046a892c31b5901408079fec538c8330966e4f9df2ef3c1227c9450469e1f8201819860490c709e604209a610062d82e30a1c8259ce49844c9f3e77051738b091e76f375e100182c3f7e20a042430c9f4332af8200106795631554e406325cfb74c2802abc6d71648327dfaf96c51822fcf9fb8c69e3c9550818416d7a0bcd83b993a804cb3c85415051c5e99a58f163088c17702e19b6519125c8c47244386ab8a92cc1838be8414c7a8584eac2513c3289f2c9ab09065592685205260f96d9f1f226d7ac944e107a39804f17902d0c6d336bb61fa028f72f4f149721a820f72f82ccce5e8e323c54914f096a38f8f114e6660941c7d7c60251de09ba38f0f1a274ff8f83459819214d8f004d8ccd1e70942e68ec81f097d24b19f6b1da404da66153f9bf93107d964453f9bf9a57290abf97235bf9a2438c4d50f11c425abf9f2e7671397ace48c7c1d2dcff0c9e2488e3e590cc9e1f693e5dfc8d1e708401996e54cf5648242617cf1ebe38b167ba130d7115f6e8fab821a8cb916bb5f88e947b33324c83f119420cf0f3b48a69167125804e11338fda24bca5d2fe52f73dda6d3f03ae8076f5244957c2bb27cf941307f892ba058d0ed6101c8512adf2008b6f427034c83292883e336d696d32ea1ecd95afe226de0da5838ed127d8e6093e56f45daa5cbf2b723ede292bf39d12e3d9247656365f9d3658fcecbf583046c092026624dc820276cda256c34821ca15d08c9f2e58d2247116394c850f6482e96a8e450f6c832641a32e450f6081992e50b72d845b21422877d44d36e4f4cfe2c60d321a45d2eebe2b02eebb22eebb22ece65b55c7747f63840eb64faa3413eedc2dad8201406a3e9fe66e89176a12deaa22ddaa22dda5ab976787ae88b02ae43a311635034c0a9d82090d58cf61b0c64789ad75f486318b03bc2e6c9af1e540f2aa87964f764d93f59364f960d94e5ed7195e4a1ee00d4048f1e6a7c8841597e3311633610999037e044a6f02fb524b3206d84cc2041b2fc5e22c6f86fa087376992e9f7f02669641ee2923c95b0b0c851891058c0725432042cdf9e76894a583c59fe55d22ea32cff6649ae91a39212d864d93da07f03feb3b34136c9f4db807f5f5c92fdfbfddb40c74c9764eac92192d520ab484b1c1c24728ec8d6912dd972b99048c99d2c9d6850beec2fc45942d1a0ecc952bef40dd6c208c4e022fa94313e0a85845676cebd236e245bfca812a51370e4d1a28c2c6d5ee40b6bc0e50872fca2d781698328c7772f041213ce4fd5a0e5f9f510e5f8318bdc92c3d82487ee456906962f73ec037cc6d93f544fd1af12c2941246061eed22bfc6b118a3cafd32c75f02f4094d343144674e5b6913d356da44134d58269af34999a095896a55d0b2fe76de6c3abdb63241fdda3a99b8191399c684e6ee844d25c66ced5af499514e25c6dc7b6fc41a63cad755ade2f7460e15d972a3c11cad6a15883f01a880d55616960055688e7f3146bd806064e9075562ccb5a1979537091e483484b4c8a0848b215c750613f2fc7ef101164b204308364f4c81b6e08c2372016ecb6c023d2305a106a0e08c1764b0338e740d38410f2aa725bf5541cb0f9dc5eb0b9c21812406d696984af0120345c8ab0a5a5801841578053e6814f1b1020b208831c4106230f1a080232063f422463072c728e408349d07b87d06d924f7904dea47f933c42cbf1c67e01e68ae5fe8df0109244fcf871c45557f7bb93ff7c79f8c0738bcd2864a37e30a1f3382aa30238c1214b028471f339030c40c2b8030438a520ece72f43183c78c9dead4453e41903a2a0b6cff3668b9ae2fd836aa321f6c30be777bf7f53e7747396580e9eeee48626d9bb79207906b0ec92ab68dba7b0ebbbbbba7bb7bbb7b4bd9dbcc9893a5255ca7fbe7bcfdb43d1bda861064f5bbda10823cbfce6ffadd52526b6dca0697f336604b95393c6ab080aa612325c523c6420d1b29264a472878c789a97402400038ef03f02f773a9391eecce89b7ec9853c5f46faa4918d0f7a11475b837dff908d264983c0fd5c64b1aec8aef6d5ec4a176649b9d55aab37a25ab665dab671d9368a24af0293ba1054ca17965e04a90be1046aadd35a21aa945a04433e32af4ead0393d21054dafd6c914670ce7e294390fba5ec50bc41843d0fd85377b4743bb8adc5bb858af0886ad99669dbc669d9e8dbc5f41f29904c65665e9d67a8c0fecd193bda2b3f4af9ee734e539537d32ea519fd4b6bc86e8c209d757eb68a9a7875e7f83065c420bfc096021172f790ee2c328d22d3f70bfacb05a560932311b263144c0e528c248870df7e4dfdfbd988a0ade004ab7e36f5ebd72f4a4474afc778e79c73ce9f5faabf98b37cc69311fb269d14f5938a6a4251940f0e5b5a6614a64800192820c38b3c555a482a6354c8f4afa4942e6922d32122aa4113a03097040e6fa663dc7b6d663ddc2012946709528e0f0a15364bb853f4f8c4c2c05400a1ccc8b98112041548a2686294061552e4107f11541801e5092a9840041560bc7652b0459530e565abfdb820af5f875794c09d235324cfef6e0699b9185706176423166360c8f3dd430d01b7abc1f93b5f45a2c1f9e00a3017a322cf3f0217a4041bee8b3c3fec82e43945649950607f2e274f8e08871359e68736eacb5f2a4eedf197fa135571fca5bae61492431b39e4625cd0e562ae1beeaa7e5cec052638ac3d5cec85d32e292f3ac5e6eeeed4ddbf071b7f5a1d8c78e5bbc7d9e4b9a591e71694a706b6ffc04f762fdc1ea07de16fdef6851ff0a8170291a9af79e1077e72f685fd77a6728a098cfa4c2f4001ab484a44c7566badb5def55afb5bd7b6f6adb5d65aebf6abfdb6f6adfd6badb5ed5598b56dbf2631dfda6b6dfca5da6aabfd18d69cfbf27e3344b7d7deedd65baba9ad0df7fbbd543f90dcf75a6badb59dfd81f676151f250466c51818b2ff060e016b2f9f3af52fac40e47e100c2c1d75b7dfb6ede3d578989a77eb7bc4c1aeb8d73c2d6f99f694524a35fa012c32fdc02bd31e6c32e56cec476b3f7a616db9aa6b4bebee06bba25a2d40aedfa5d85f708cc365a498c028138602963fbd5a82c8d236360537c66364b9771471dc8fafd3dc8a12586a2fedcbf6d1b99038bccaa455f7371ad30901c3eedf5b61d9cfd065edabb0c872df7ad2ab4bb89031542f228efb970991e5be7f615542beff92e19434787b22cbb55e5dd2e0aa06b9eabe8e8602fbd7564d22c6c87ce9dfaa936f75e55b6d3e078573bb06b93ec043a022df8ff2c3ca837c81f4b041e6fe66885963c0ccbc78e3c5f9c64df3c29b6d28b3b5efdd0c5df61525b0e710dba0bdbff6aec974eade1acb97fbb0c2b4abbd8eaeb00681ea9206efbf10052cef4795fb69a0cbc1c2dd7d6a9df9ad5c8cd165e853b7d5ceeb998a3bf5d9da94eeee1e5ac256b37b83fe32c6183bc6d831c6ee6e4f66dadd928b5c2836186b185c6fd2a5b774a44b6fe94897aed54047baf4968e74e92d1de9d25b3a9352a1a533694b47baf4960e778472759b5eed9dad9bcd56a66d736a27c073b6366eb6b82e345b21d19cb3150a8946a4e9530042cbbd1de66ce1d19cad1149141263a31cf5a93980861e9af1d05badcdd030c2de9aa3a5856af34683a0b6f9cbdcdf381bfd9271f7e39bb26fc795c14015f08e2aeb8777701b28142777d881817bb96ed3b2cbc53415cc215e34cc7740bb8cf2fc4d443faad8f88b800448fcbd9349cd4457651adcdffd7e1ce2aabf1cfc43b9aafefd5233f55338c455fd6a92d0d4bf6f5faeeedf97ab7bf32309cdfdfe1f3feed72833ec07e3aaf939c6c071b5f26f7ff939f447e7e209436c7c07db165bca96b9bb5b4623883e3aa3286eed327ac87e9e8154d92cd86e8c313611b6a8b28afe42eb8dfdf71fa6857a34e8d061c6552d575d0eb06c19d4252363503106114c381be3892c479f3176e68f87aa3a994c629357d4a05e6184c43e6318c938479f3188a049bce56fed75a06b9836365b64f1cf220eb7c9f3f351bf879bb3c8323d99feb2083a951df564626eaf039deb6fb63b084cdad243f3ebe1b97e37b24c4f265503cdf3a994a139bcd9b9dc576c5165c331057e4924ba4490fe266d247d19440ac18931b67f071d19885f477ffbc21b37b22816a3aff96b9aa6b956230f5c9e3372b35b02c0042819c3fc78481cf4f311599ae3e19e1c12a4419690eb2e8b642211a44f631227b250151378aa7a503f56fa6940e65c1ba082d488a24614a820a820ff9ef7059f17a8848c785541eb18a21100000000c315002028100c870382d16014864980423f14800c6f944a6c5a4295c6a320876118c520630c328410400021c6101a1a1a0e089da9041ef4f0b11c378a2eba35e8a898251c3387f9a0d07894f8585cde44c5b1be07af24067f6ce8160385cc199e2b92f045a2eea1d788a571472de67038f2e244516cb0ca1a8c0075ef7fa121af0f4686461978883f334ec869c4ce40ba22f401891c11316f1de8cde3481d38b010a7410b1486fa2704cd6196445c3c911f8e4e8cff3067a33e2178360ee3450bb68c1b8727903c0f99262f9390a02ec42dbc327a6e55ec74264e9edbcc9db2c4a45d2d83534c59e3843076fb2b2d6f7720dc2d63fc8da0f4994afa1c4a7ba2d6d08f0212e5112e5c5240df66fec702e6ec603c27f04cd10218ee85fba7567f8e026880ddf55e21734ea8779e102f12d394177b66aa73293b9b9700dbf5882703f2f78155716fa40a776da20d5b1e964849e1ab198b1d4517c5ed7273b65f8e0baae20275d1505bf7af636e25c793c3852e2f42e2e54851a62a597860b3d72d0c7912f8a9f1beddb81d6516cb184d0afd8fe47fffc2c59a18bf153fd00b019b7dffc175e40e62f13767c48cab2330827a911eb8d31814a6409bf7813b7a3f139f31398cbdb7f30bdee053c6186f4200c11d55a86b9a0565b54190b8d2c5088deb1993a0a5b08692ff78cc854c999f996446c132b684cce061d43e59b5491389f1c7c78b476485eb0f4c0db619d238f406d1a3821c81fff40f207478738bf73fcad83554cb5bdd83d28ba4dec86e6939169c836ec0cd8e6036071e1e5eea37851724a68332441c7584579ca627da682eafe79088004eb68d5bec6502f5af0fd9555284ba8a449a00a45b4550197a56afbb0b7e6575c2f25cb1892b5a04bd0e593764b9c3e7909d63c2295f2c40d27a03699104fb1e4b14b3d7f7985f9d10e6c0912b98f3e4c1e670c35ae8980f9eb0a3871942d32cd0682a59c2100b174129d80229106ee91a07db508ac07a94159bb951eb0ae932a29c0b4cb0ba533a5bba363ab30cbddce518d56a3ef9e7e77eea491958fb6095f9380c118733687f4ffab536a2c37a8768aae265e74e8d5421a49d0dfee4a524cb8038cfc23b723e62f8b9a0329dcebed36743d48f81b8672b3254c3e504457327f199e3476fd3314dd6fcca7032262729704974998a82e84837621c8534a2a6fe8bc06f4bd8e206bbcddf8bdab6a3b1d3a3b1d7e70e42dae8c5175d732325e40d265469f242d1c8edf34472e70cc278f9882c8ed8c62c335d092f270abeb6d5355cbb7229b021e84f4b577f87eb7e67c8c85ed0fc938122ae1e0265929d077466ab9e04831ebf953fe3b744feb9f4808d298a65cc04fdc92fed08a0f1e1d2c28d75d6679bf361a9db44459a452982e49310010f890438049ae8ea17dafcf2c85371f8c38b1838fcd48b66832f3858cf24e51614caae0e3204bc0f407604e8bea90ba34a17728c062412b66384464dc43d094655764127228ff2f86995c6d3f269b066f129c688012092a366c4fa0892ab321291bc1d99322a648337fd80db081c2e30de314c9b89f58093d0f676f9034f2286e9832149aa91c053192be6625b650aed1e8934452787538114331b568184d6de30a7796b98fd9ee71293494210ddbb471030301197cae9ca59c91982b999f157705c125bfa66922bff9b85e8cf89bc0e66462a36941aceca474f3c131d86fcf8d855e315764c114264b65e135cef488ef16b8e4e014ebd024529c8577c55b1fa4db94be3d39291ea91140d65c34e817349a6c65d7bc70f247c9751a1f8c529db6d06b2df2b5fa0dbb0db69b013b7e135239336adaeee97d98e099c14767481b76f9bf5bfe5c21ab8359d6e6dfd73cf6a341e4030bda34d05e734d24965dd57e1fe0e17278f98e0d9feb2088364d15207d00d3d709a28fec0c60b105a347e9ceff83dfcc83466f14c617db964bb7889450abfb41742bf4d3b479aa7a08718676a05ea2fdd9a49aa0b6c866974aeb922c220121b3b20ff2bdae0ef6c512cc20bdae1c7f49dd488c1cd1b1acf4c3843550cc503f739df9bc7709ab3d017477c92543bb4743e262da49064b9f53fb069a373dde459428e5f92444f1859109e489fe2f7de61525272663aaf94e96fc21bcd094a25ea25c2a8b8e41ead722a1a1089d7519724821b2439fcb266c11bac063a2a4560c06e0bdcac83a78947cf1c7e3b4fc671f32d33ccd8a3f4e4608f9213bf6f55c642060512d2edb0859f40c29c8f74e202b18b52aa62099466005c339069d3a9b00ca7572471ef4f63b5e7f4593e091658b5d2306f07fd8183360d63b6e1aab7e4ddc1b06e25d950e0d3e0104b08cbdd2db6845c28d78751778c70f7844ab178f9141ba7fc8d3c1fd51feaa2c55bec2547f8d8171868fc4b60a03140974ffa38868ce2a380126a02f107108414fdeb81fcc562674260a9af9f0c11792f6688347132b0309e7a4418d59240d776630cd10b93a0c92e0d32c463ad63951ef6db0432397483e1c1278d46537c92129eb5cddf9ba1e1d23a278646eaa4e86a33564ed3c6d448e48ed5f8fb176e50fff872a7c2bbbbcf630c01a8c4ad209536ac957b7114b4eee78ba30f4b4c6efdfbf90142242c9d13d0c6bf8f468b93790766bdd38c99b37ad40e8dd74617fca4098dada6832d288f2509ba935f5aa809cd482461b6e673d40ad09c4463df96338193f2c68ff60eb0eaf8399db5be120674b5b4306f665fd0ac4c6cf023c5523e18a0125f1bbc36d195b8e298c0105f2fa61ef719091b3f2495ac6440350270c078568b8da7069a263a4d8df446dcf54dac9fc73328f9a2ed805d3bb7e8913cd6fb0a320b85d52c4526e8faeb940090f4c68856021eb113fbb3759c8312b35a770d771e447d9cf587ac27cbda1038ae5677e4618942294ffc80d5b4002aa08e9474787d8b4cbe05f3d76068f9276a3996d98d927c98af16117bc5be108102b4026022348787d7357b1e71989f2a781fe72b42590280b95e64ff95fe1083ae765698b1fd0a653708ee6b124f1d42f27faa1ed033ba9c6d949a6acbb93e280dc48e1841a07cc2eae74ff9eed0634e0fabd354f78e64b242f316b832625dedef8d0a0edd258c7596a3b3c3dbe91d2566008f02e11d0f085104526e793315b0e38d4fb1fa4aaf2369e66795b558ee3b37b67112361a502fa5a58dba178b2a25dd84c366b1ae51e73339986e21a0e6ec2d24c1e98c813745bc9c0e6bcd641d7f32003b2fed6693dce51205e0b003376c5b2b7d3e558bfeb2115c9be88cb08aa98df22baf49321cc1f8425611a662b811f609da247d37945c99e12c25850429575617dfc82fcba03e7e0639b95e5b7566cfb4ebb794b9323b537bcaabc80b693083a683f59f3f23f8d67a44d100c661513fceb43148d14922e180148366696049dd66a32d05523ee6511a07cb544143c33d5c2d2aecc7a14b21cc600af41d9e708e070011276ab4fb063a8a8628198760110269d52ca7a60f45482a59cffd7176816fee2a08c12fbb1ebba949d06dd3522fb3181a3c60947bd7f20748240bf3fe859183f931d71dbafb43b60316c9af05ccbcba94ee00a492d36c3991e8142d2818335bddb0c14349dd9cf47b2e7f7fd4458e0ffeee60c568febaef4f46fc374181473102d15f49462f81c85f39b558b74e945841a349c8188d7243e9d1d7a6a54391db6ff25e3dcd0be8a5b36889f91db4ec9d99622ca1a7b930f4a5d0bbeecc5450269e0672a5b0874fbab9e31cce7f9b2e9e1482acb20d42f6f447228f55e2f3357eeadf21a615d1741c5595109c393645411e6ce39473eb3c9aee4b01dfb09d2f31693d452ee7d1f84b65fb5751749026d29ab26316363c5d4a724c5ab399fbc25b6e4f1968a1481fdf5a0b7ff436b537d61aaec2dd8689a7163716b15e89b80c55a75aecec97aba070c31b5499f3ad802a559b1f4065953f91d5b5c34d19ca553c392ad5b1ad24ead5a7b817da86a48df6804145f1d4f4cee1248403528a62e13e097c0b5e46dc823770ba57b407dc8808af8e5f854b1de4d249e20b057f60d6152789f09abf239ae8f52c788725574e3de420d0f8397c7bbfdc7823f08c229897a9ab0f5af4e08a4ff4ebd3becbf08f2326bc55107e0181d427d65f73f4946700e8bc5addd54f5292eab1d1eb2b0040b2f94aede97855d4ca27e46aacad632baeb61edd52c3d96d1ea222c7890a0ead58554b3694a4cca8a08f6769a5011237b4260971e7a9ec8bcf287194db9834baa2899024d14167912e9538b164fb32029908026e400c418cdaae8d2e91bc5936c6c304604a5aaf24395145e1ffa49a2e1367dbf734347a2934ac6911ba8b4f13638ce130ce35b92b4d4ed34b80fee7d0326985d9ebf95e7ee52319e1c4216e1c73b8f6ca237108118ed764001976c3fba972f6592d2b5920603fbe93eba0ea9795304ccca5766ab1db4f829a9100b80fb23d8d9b37230ab66dd6b6bc2f05dc89f4b0ffc6854542d624c973e55a6a755a5ce73344969a0244c16d2eca67702017608f5e2671d7bf4b699fa6cd0aae9e4e9bb4b558f60a96f8f111b4f15a6b47a950f74b827abf3062fa544a3068b83092e07ef9fbd0a3a842cf9f18dc730b69cbd19060a9a965575554a988f997b2bc14a646510b200c70342cf6a7dca9e7fef81b2acb8e15e15c1f4fa0c783be3d88229a266530d78052bb1bf463c894cb75fb8e6c1e633e8d61924ac6a73d6521514595ba9a20a07714bad6c915ca5506740dd821fefc484e100d44d05d74b6aeb06f7ed7bd22c68d4cc3cf86b49f9b845d713c22e4e842b78d25645a0fb231c7cd8b5f7cd8127a7edfaa4f7c53049e4a4f5e50bff9dd57dcb62b809fd19945b0a59b26e04f4b6e126b1fd8e8f8b4261be4a503ddc47ff4cede3701225b687d4eb5c24bf34549d40c0d08d3cec7fb7ca80f1feeb2deffd0ad47404cddab88dc2b57d166fe091d9bee02be11a5e44155e94a269057ee844c1f2e5fe1cd2b809be16e0373839b6cbd9f040e11b2a5f8a3190b01cb1d55a08f2b0b01051ca7118310cfa249b7f8309fe566b8937f54768b392eb18479d00ad1dce146aa35862bc146fbeecf1945448df253102d7589c343f1cca74c9f553a41cc054aa6ad5d677d1782a84552e14cb383a9d17782f28dd31129d342e4ba60eebc88f8943364375fa2b2489a803608cf6f1fdda644cbd0bd88b979231e481c8680640e856b039de7b0ff2249caeed5ee0e676858568a4a9784ca5963b108d84680c83c433d6a42811aa6295bbaab2b930d2ba3a40cc8f7fb8a9bb0e69dd4f2abb3c4d21f1e83d4098338ddbab0ca37aba89dbfae3492956a10942b076d7c9f06c4ca834a330e41e1d1edb5887268b1646e256633b776edb009e974aaf663d60b33d5ad49695abaf24056192192cdb24396c41f6a4d9d44b9f5f8b3d60878c873e4abbe1f92d692067c348b8289ff44cc37614dd1ef362154bbc7ab3021042a1b519fb2a0304357baf02dc67aaa3acba45f0dc521dd743760f430e76e077f8c56c5ca3521357e06849ac58932c9cc598f593f5e63bbe59e459545abd004e804e1430c81902790f088709392a3204ac54b12a949debc04a50bc6767146466086559f41742fd9634719fdbda8b3cee71d2c1434e77864100a2a9e84778e37c01648031ace131d82893cd346c4791aa6a13a76e09c424d970ace2ad0212e7137996e85c5c53564268b1564929cd047a062179713f460a0c79a7d2eef958e23d0a6e0ed543c1e0232c70cc9ed39be036c334fc2288acc535a702bae717a8abec87f0112d23f4fb12d14a877b526be2150d49e4e09d73b4f1f03bc31902bb34600405d6db2c22c258033953d8381d2e4bc656002fae6d0cba800d9305b86266ac0ee419471d0d269e9744ef04bac18766b4b2d1781bfaac8e92ca4aff2a1e384de8485d10eb07916b5be409b034df714400b526fd27ff76eed7fcc66bd9039cfcac6a104e6bc2bf37023b1861f9944fe076b08551bb88e14eb63a9f2e5928ab8d250944743f2f322b97d15a9e849a63fc17b0e2f15ad175f97c5b746cdb39164c812ef6240a602edba2387afffb8c3009568d0375d6b2c68766f0c592b5682611b8c50eaee35e5a43a40a770ad6bee8d3508280bc948e886b8c9dac93e9656cd80dab46d0efc2d458a21dc5f9b966d68f4c362e273f91660209b54ee8a65003e32d2f3155e1268b8da5395bcb43b0bd17dba0c3cb3da1d36ccb70d3e125f2d462744c9cf12416506e4c676f99b4f3a06efef16498962b5f486350600a4cd2a062b95c072dac6b32120efe5e3638055dfbb5cd3e8f2e2f7fff39839a2bdd7b062d2cbe8f77e39ec14a2df892b9d8952bf6f7e6a36e83a77b3321344cdfb1485d403deed6e2035f5b9dc7345203050370bbc9e7126bdc66e38603edbc57fd1590d47633c11ab466e8d192af259a313839253b0f08500aaa965b8c46df54fbb81ce6164e5daacaedd3053716a5407cc8123770ba6e415ecc90f94268afedf6fd6b574ce58cc6196babf0d9d6d74aef7785e08d9605eb794ab15c143e8bdb2602b4dd9fbf4de450974148d6e378e4aafd0f64ecc0fcea23a3d13937687a17364777fae2e870e033302ebb2a5278898a74fc9e2e4e29598381acd98e57311a3aa56350394c2a881194d0d43cce2c376fbdfc046175dcca98a018c5bf62a19a5e80ff63f36854b649873a7464c3763da9fb860026b89bd0db5e16a60e30ce83819a4a5aab43ae53bdf4d0273d5f9f4e6cfcbaf9e722137b9ea9287f020b36c0f2563700c9f4b82bedec2238b2aea0681ecd4584170895f4c8cd67a05cfcbafaf7e50576bef2004e3ecaa08cf12397c611806b4b139fdde225c129de369cbc3e72228cdc89d3829004f0d06c7c9138b84df496c40e9f6d910c654c9ab464661b19cc807bff09b0ea2e5f986ab06d8924a075358ea9791d5897ef2045857f9234bd4ad5e36d35132e51ac61d4757bebd54d8263848b24eeb02efaecbfbff72cfcaf80c7c3f2852e5f1fb6acfa93526d39bf0c0310deeaafc49e50eb36db714ec1a1886e70a331417106b18a8405b8fb82b2a1fa0dbc369caca8934b41eefc3dfee01c2a827bde2a3e9120a21d38ce39af42fb38b1a331e01e29dfab3006d03100716a69cdfc3ef0afbeb70e5d94970aa8f0b876ab487dab83d22387e762aaa091f125bc4a2b89c7753553d41cc281559a447c3c4715397044c560035f277402eb425b748f2c85eee310aac9e604db7cea08bd4b3f73ee426bcb0608994bf069dcd83da7f8a3a2395eb11bfef7b6d138b1f8a798eae0cfb75ed43e01c6adde41f7a0be6bf135bc11b704f9a1ffa948e6ed4144ce8a66a4d843b1334f2fbab9af63dff7d855d2b2d7861602d9320259da865163ec675bde9202395961524dc1dd18fe90a53e2683bb74e07f5c3b557f1958ab2b4454e906446f4047fcad0fb80f0b8050ad312f4bad16b80698eb097f8a019d8f49337f89fc46b1337b4853bf668f1e36c8059b131c143c9ee6759040df5890c259e5a477a5c1b83e7f28f8cc8970757da6ebb1216b7a681793ce6e2d2fa6e760e428f8b27faed2895d427a9f162cea3dc0dfaff481ed7f323c250a06ecc861a33eb34000512c03c95b447269161995475ea9064149f25466d189ae0fe53d203dacec4ef5158f72c922ccc84a66af5127db30874dafc6d7f7a4b557aadace77808519db1a2f1520fc7f4499db4c5cc923ef3c6d9c0f5a7053fafeb074fa75f485b2160b49cf930515c7c00947b441ce1c8d32878f1d087b40748788cf32bd8221470eb9e4205c09285b18b49f223f10f7a8ac3a44c331fdd591c01d21aa28d1be1052698a84714b701f093d81e18744538b64c34dd335be27b520242e5e38bafbe4b7f62533c595adbd35fec3927386745a6b1788dca53f5ca64b206d77e252a3147bfaaa962cb349b1ac9c3d165613c656179216db8860c17d295f8731febe316ae58e71f4e4b5ee88396bb45dc8713b2560d4553ef917311c49726e13dafc2b2960a5624410d2911b7b7a597a58f5ad2774d771fec7f639c2c52634c920d61e01036f076739ddd8d078d548ed87a68ab741f9e53e517773f4de821516477369f32ae2876432fde88e2d7083dda3cb08462578c99a7f2a46b0e2d2970c063f9f7a334e9e106a43c406c0a8115afef6c51b5db3327ef756fdd54c7ea900e298a141e64cfeff24ccf6752d21f9ebc9dc619a3690e8f1494b05e40c3fd07b7d08af6319358695c14f62cf450328610c73eecf72860fe08b102757f70c73e75bd59a4b701bb31aa060cf964f2341c8c4f20ed4d5ac4feda2191a151ddcbad56a199fca0c8523da5a74b373bbb465451c49c61266d423309ae5ae78e60983ea3470b2f081b33cc843e3427e65a230382f94b7828fab481e4993bab2cd2cd6e0f3e921bfe56e27534623b38bcaee77e7b33e7c51b92670d6686663f11f749a64f727e82f34dc926ebefab5a7f189ba06b0eb227f549c953e643b1a7d25d6932bc032a8b4d69293afe12020017b2f6ee8401efe6dffbb7d4bdae39a9f7e95ee5756831bbcb037c58d2ff69af1325bd2ec0b0a99454ac243361e824bd92f7b36f090fc5a1ffa739bd418361194134f869585eef780b4e142d58b78b0c4186a0c57ad32d74fac9cba35adcabe0e3133d5f6fc640308e268c6264b091afae7220a51ff57139acec8964c105872855e6024f2fa36eaf41c19c853f2adcf2ceb9142c1967f21b7fc3f4316e42040029e27220569307c0633522cd372ceafd1cfd04f2014979e60183f81c4d0ab75c94952f4ba4b98215ae0864e1ba134db8f3daa074a788f6ce23fea4fc4b434e26f691622d48371937322ca9756ced6d746f7ef179f5a6030654e0d36f6c8f614e528edc68cc383645e513494361a798fe88f912b795490886670f9bc039ddadee0b231bd8069163d8a0ba810c948cde316277e80aa8c590d37f33bcb612795735e81cc66093110be62ac07643d37ed2b153b01bbfd59343867c58db253bb7dbf320b79d8eb333280752be3be0e8127d5c7bf34f61b9271d218a2095ff9aa6ad6bb135817a51acf69c0e352dae4f7271ddc974c90491b31a82d13ecf4ecf35b299898ed291f9af45e57ff25631398e8de5b8d38280fda25874b6cb55d0be224fd655694f40b6656378ae54b17668f10786c1ebb5e53c56f3731dabe9fbdbf297ac492c347316a764386e16e7e37ba2651c6cb93c810c2c3c1c3639ccc05f44dad9920297be32d686e0b346eef8ad1f858b891b1547ac5e69d3bf95f83f354f76886122551bee4d93e6de782ad190398e516a9daaf4bb52c4a7f95771f9fc05c72cea445588182970a5a5d0120c2e11a457cbe60f4235806a561575ed0084a0391d7a904274fb6f9b3d9de4456470a19a637d7ff47a2d221843544a538c395cf00628bf703504fef7096135ae0a22fcdb03c9496063fec5be03d5c3d885ec32af7f0825baf9cb2696b1005194ef1d786f51884fb03d7ab7078c36136045451d167246bdc406b35c1f29a14ae052e42c925a3083a2b1edc41d6bdb598ead0c2affbb16e61fbec844ecfe509d4e07cc313b434355479574e28660b432748146128d5dfa8fcd4500e4fc860e723d83d3efad806788c30d10a9229006b985d936920784806db2f89a03b0bde20782ed49257896a919629d8e9cca7570edbb3b01792f303035e124a6d5533b3d36ce925b33034b28b38a5ec373813c7ab2777d5f5c4ee39106ddbff221b69ada283625c029f9acea285c1d8696886941398805e34724e39032c813580763a921f64b51075b7a0e7cc8476b1fcc9d437e6baeaf5d213b57509fcc0882766318970f75174b99d26642ec2ec28b1c0e11fe9f3316bdde194ee12fbc72726325a1a76c70220730c9fc487c9b1b56df410ea5fa82647c24664dabc854ae69198f95f25c899f0826511251034b1ea4f886ccf317a8736553c4b8b0b0c4c5c069158f81e1739f6403d97ec029669c4119739b7e542407417ed6406140ea913684ba02922472c1645b3f08b82e380dbda77293a21e353aef67bfbf40b0298951eede4010314d31c5177151ae14a7c774c29dedc5ce41ab78ef91bb705aa1cf1380c05efdcd91752b599c5a3dc51e65984f649366f217d494d9a15d9e768245e7bc874aa7c3a184ae3a4caa11086c0a4e79bd41f96fa3bfb5e93b38314a3e6566157c17b0fd64208b02e32bbd0972d1aca2f2d334c163bb4b2f83a52b6950396ca9f27d36069d1e05c639b6aba73e7f2b155700af1cba73a7c400fb205c23690614d53fa818ffe435cda30489f64054a1835cc330699269d8b40182d1fe66de7e89476515a92b0ebe47bede836fd0e0013f4a9e709251fd141b33e2bb498e8f4792437d14b33b0272768f835eaf8c31488ea17b7b040dfcc483c72d28938c48597a7c393b2de90c070c1d871d08ef4c7b68438cb652550d4ed55a0949553943d8e0f8e0ae51559ed7b3f754d28729606812ed739da85e08ba3950fdc64d741f486703a5b06599e87023e5726b6ed80658b75a29665a103c4afcfe57b222637bb1f10f36a331f282b8dc9f3357828e45e3a3b4feb389a6e834ba487b348e5c2439198349a5fc1504c0aeabf4079d6ed2642be611dd1397aff84b6575fff2bb4584fab9e25549c6e3bc217fa2073a27ed342053bb84f36c02c776d501cd8d76d3e827260a547af6aeb4ddcecc03bfb7e16a6bf6252753447757ea44e08368ec90720dacf685ab335eb6875f64c8cffd392e0c2f7542e005ce50f40957fac43667f9bbe4fdc6368a68a86612a5473ab4bb1c78b586359fc297a40828681209c1c13a6ae8a18bda3a79f389066fbb5402ed027cb5336b937d6c4a174774ed4052b94254df859e42dfc9b1d7147533fd5c3a18245bcd539253458f48be05149ffe7a394d0ce6ea20cc9360427196f60b523e3cdd1f86fd50216c03a6c3511468558cd5375d089ab53191145a82584af0250cd643ea5a786c12581928ecc5191b1889210c75c82445b61644f549f9a82bc1c0a846390d62ecd31fd59cd1c9d6d7d74a4eec47c2e19168027c5d3740c80b9af648bd269770a24f33ae0b208cd8e32c054c42fb7d1efad27cc7804512a2054a3b56ea1763bf840bbfa1b1c6ee2f4a9adf1ce96228d9734ffce18fcca96fa62c229a9fff26b015fbcda589b437126d3ab324a6d023198b4a55fcd6546c6a3a7d0a56cfe8e79b7b1d2920a47947c0912e1c62665ffbe07856a9bb83b1fc057bf11ca8a4808300fb03c72406a2c72715dfe850e0d39b84f054b831a770b2f334a81aa3a308807f19b1497a819532d0ac1f2c01e28e3c959b4c2aa8c513e898bab069cccebcb51a631a45714c52a638eab5d894a52da290a784ed4d20943a7c1745d440ce42696a10f57e7664699d17e61c81ba4992531793638587b93ed58e8d3b3b0cad3bbc8c31feb2d0b3066e63547ed042e440007a10ae07144aa0e2460331941bd60ea6c06258e99030db27eec35caad4177950e761ceb062d9684869c9bc51a931ab0fdc0c5d4cef18a9ab58759bd31ab9e5a3f304f1ff3ea122c86920fb88660f6fd20fdc5d11ba986173f904b78acd7010703e80269dddc576347c4e25c6190512c84403cafb52518703ba2307a15d1230b5c9e9837cbb52f99944cb3a26ceab649813021a48d60b23b5fc4d7e18cee11e008fe3f485d9d3cc0d8e871541382829f7e6733b064ad07b5da4ff8f11f43b46f4f8d5ba895ef26127c05358a037060516f1e0124b99b3028bd8e40e0f066a62d9246850f0a74395dddaa9dad769848fb04e41c2ce94f759800156a34d29fe73f3e1013e18b1da3848f3c64c9710de305e6341b735e450a74b9ea8d840681fec408e83e1c43fec99a9b64cbd244929cdeefe1bd9f884fd76f2b6da8636e150207be0a86742f19b8a3daf198913052c7ad6365490495b990678951f3f269d68c7b4b152c43864748f118763706f578bc31e56548a31e69d31aa4c89975fce79bca05a79e3477a73898ae475dffc503852f0c19f9e1c83505ef900948290b343b27c0779ef11d608df20e3577c380fe9a865dc72e08389698655357df490509a8cc184f5caa493abe039afb57c35e82030838b417f56abf4932fe1250027800407184da5229d65cfe617a27544af41145491c288f8f15f437d0b5c6a16276640ba84b505c705a4599a915e2468a78eab760664e5986008c49a7954bc341f219d02de98ceaeb2710a1004e7b877b88d2a0d8d614a30696e8e8753498bf1aa763ca3478d9941d94b860a95a408a3f244481a70f526a89b0787891444ecf6dee0c5ea1392282008107f116b8aba8a4a8f5099f0649376b46349831a5ab9fd813c3ef8ca27d47302db4da6094ed7e1107f6f4afb2724e1c424347916b0e93a357359bfbf6411e8eec81295a47c21198e3d319b4e43a97ad5e6033cdf667d0558aa1772b0f57b915f38a531a8e59b010526103461b15f6e8826073a30dc3c8e1c9a3634188104bb40724645ac125d88fef091080a91dfd67c46a6efa6c10743d8ff22104da195f8b96a7a66c8c87f854592271c90a729c92dda5d07c70211346c329cf7293304f03b7ddb9ea9dd94025a33dc59a67298ef05a4eccbe73da2af544404788612efca1c8c78ac11d32e6212be4470b4b96e193ce90756c29108a8b739456c4a82f83640331ad4f9daacde31c884815cd0be88115fe5c5da25b2f2e4b01d36f351644f2038916654c4474651c025bfc4b7d4962098091bcd64cbd52e394cfd6e5c32c34879df39538808266aaf0de8559ec0362d47383c4003ceca68c9730f9773aabd7a5a7b365a273566689c441c92fd0757befb09e80be057132bd1af0884d1765c8a262aa603a158849a3d88546387733391a36a19cc892ad0f962dae290bf970e74f7a31dc3ec9ac0f8ccb5928e904ea86449f5b67d3e098f8b1bff741734937916a6252de992205cc3717896ba67362e604613a58a03c935e82f87b04f7ff07722a84ff29c8d8eb61e7f7443385940980e0d683bbe097880047cac981bc0619889a6a2d5add62112a4e739b02aad14477046e870b09ecafb7b7b96a9132408cf9741f7ad8b95aebab8199a37a33f1482d6bcf02bdd0841acbc79b3e9be5d04c5650ecb50276a8f3a34c787166a022b6327bc4f76c4a87a7c10d7ccdcd292cab63366262941e70fe719673c6a2e0499300b2c9c9f519c3aaa56966cab0c0e53b0491329cfb21a23d965a81ae20023e1394466cc5ec6c14ab38897068ca89b3d6027388dc57f216c2644dd1c14275c49b28a02e7482a8e9e14500ffb60cb7d4ba802a0f24b7b5e451444d4bc95ec332e8812daf699bae6d6c0f531d5a204c42aee95c66d5ed62445d370a9c9f4a704d2d410a2e487ca8afd345219408550018c60a3c0a9e2118bced5feeedbf958d7ff674ac479ecefffedaf2a63dcbf2194c480ddf8d73cabcb0b8175368bf26300e08ceb223927e70951868ef1cf2cf7b67be3d9aed6222d7302a89089d19153307c72340e9bec6649f01f7b655536a1448e834438d347d399b3bd63afc0ac184e556591612a1662b7f7026d15a92692d2d1ef2bcdd198de13a50450be52f9ae3131b3a44052457b35cac0778020e4bb6fbec0277930de5e3bdfbee1d1d16437734879e4bdf2f7ee0d63d67a5faec62049fa17daa6e1eb2f83ef410280eee61a8b4414b8df636347cd8b6a0d28b7a163ee1dd601d24d2aa5d1588532a876ecde0c9efc52610acb197e5786351ce14c3117d8ec3e04a6e24bc91ea47d7241a7ae4ba4fb7a520988944ef2b628372bd52550913d6c016e12896766c3216b991945dba0737e0e29e0b8ef0ad25804928e6dd0cb6baa97b4ee1c35a8ad620a236a50db6ecc1491e3f1b7b3ccbb7ad38de70fbb9a35549667e19d13e4053f27f352cdf562435a7f8122a27f0a398d0467288f092e04b991b645525ad3c9f4bce3c2d3098689fe657c7a03050c3d8d3a3ce913356437313e3c47a5804460665120e5ce7a737812af0b5228b55fdb09272feaa2672b3aecde0fa24dd2796781bb51787d8dc28b508a436c56365cde8f26479c6746e69d2ccae69210604660f70d4dc39ac375b91b0c43a5e9832ce5bec7c59eea51b75131a20ee26792b959017563586f5725f2b1fe9b032e15939c1db83852d7ef7d17e939b71251942fa620978a75746f310d263c24c7924514072550fab25237b0c250d86ffd0dc064329dbc09d3c09bb896a0a4b85119b7cb9fb93fedacff5c6c402627643a2ff36562a1569363a7953ea5d3fffefd5f9775c56904e2a6a2fa08be84e3a0f82c1e263c2ce5a7e29b6ad16b939f7208ffd3819d26a7db1b8c60e36c9d6ddcc43e920b1065f062646e07fd59587759cafc7d644b42ab69d6993a24d858a02801d07741ec5435108e9cd3eb0f3a6e2ac633fd7181cfc08d036482c2d5dc835e431aedf2555773972459ead947b2f245c2e138514e3f41d8aa6619c00214a04dc7c1726e8d919c265f12e7541b0eb5f83460931f71aa6f70f9b83c8db467cb409d5b8715ba658d6a7c11fa7005f7f23c10439ec18e394b792c4a3b0d150e1ddb0b2d44eea0c0d91fe97d2e410268c39aef7a7f31d4d4b41b4233105bdff45b6f97d2fade2f8033e5fe263d5651898d656cdc1f6f729dbf5b912787444acfe10b1d8d88049ad68382fb97da08daccea79a488be49f6ff95595fab8c248556fdf000d6c03fc732fd9a2ffc658b4937238370f56b36098d3723d3bd636d040ec31e6524f45524e0f020c2aef211f68305ac637febd04841961a60e0e035472ca522b963881b17db0faecb554673047eed31d668afd105333cded3f88a6a2af86eb7f8d7312a9992d923c72c2ff331cc9e4201ee4edf9222932c206819ead6811051a9a346ac10bf7bf04ef8072afb128d069e5c37d71f1e994e7fe59d83c4c7c420cc775f6f18bed1a299985d5cddf20a5e81ad59f3248e466aef4baae16909f60e1d2f958e2f10b7dfae187cd02bb0a2bfd5230b007c76a283a3500309889ee3df3150711083f7bcee501dfe291308224b3ceb1b1d8cd3313d0b66f1a4a01c98f2974318e680ae75b93ad6faeb16b0423d4b3604e145fb48ab9f1c01a7a210a54e758adb5ff2a5381aeeb16f9c238e8bcc92769861d2833532a3292161a4d99e008eab9d9dc2106e39c98ac27f80c341d5b293947f2edcca2bccf169c96f2e713812684874a16c32a21b84d9d7412f48d72c848ad66473e2d897e9d1a79a350f667193fc7f3127f63fc4d85750c6be3ba7b5b54535c1f765ad2603987436f66591f4e54089e59e35a2072ed44c4cd2bab8a3cba19a6df2d80f8a68e414c289a8e5fc9b9f4261d4983f9a8a5962e874cafead89d1f0478911c2baef1bd3ec6dc4e2e03387079537f2e382367733d9210b963abd50ffd27eab206b536f9300ecc4fb73c656b210cc4f0450e8d260baaa741d7e1e28dedde594431f5da8873919ead0c259d1f15d7c19652b7c9dc1e6eb2f1b015a38aee53ef3159518f94b240dc571a11bb36fe18a75201b1b4ea05cceab58b6d12c30709a14db6741c10b1ae003a33be1ec3da0e661c00901edf2706dd2c322bf42e821230e905a250c414e469d6f55ecc5f5783c3a18b3ca211ff421fd31162d8c60441eb3b0207a8a5e77031c55bcb0de79182f41d95d6b6400d400fc9dd60b3384ec8c12eda34c8c9398e77103547558bf41c416142371a71163331e2c3c3593503d17935e44580a1634da91e476d80c09195c021fa3113d773918ba0702239e146383967984dde4071d1af012639a8302e86f49c6722fd3b9aab4c6f990c867198d44ceffcdaaad3a49d7b4baaf6d2af02a7f8fec352ea7fe2cd31f2b2f732993983b26c69a7fd03d069231cbfee0eadc464fce983bc50a463c00770423bb15c5fbd8233fe9c26643376a788a111980f99f54b53e58c9df8b7ddd8c18c1e405511c0fe0d420c6b790bb6529fbcc081b4ee1468ca3568d9d8d18a5ffb71f9730365961ebfaa3914050e693b12f46b346cfac90df8c02115cb038c6dd789f47ece15a731d89cdfff20028065ae6647d90a5286ab9b7caa18d401ce39abf8f7f1991c1e84e05b2ee3b565be456ea0666b740a94d26835e35269a40f8cfcb902bdbf697283f3e6b22a37c3abd9e65ec8f3f6eb6d05acd050740eedfe225d0977cdea2946948cd0cb1cc70b34a615249184cb4b92a80e4b913180fa2bda189d0c5246700ef9e191eda54d5b5b314eb712f46c19e9e814631323f124b426b0c4de08a2d57a3b60cd8cf1b61366f2c7a16ea71f96f4390f3f6644882c25ddc6a9e118106ec21df209ec293824da6ad793ce6aee2c4cf4334d9a3f520dc406c72f98132e1d541dfb478dc0d9d604bf53573eba9b383c80d12f85a63059ed1798b022af919d2d8023826e71d912d963ba5cca42c22f870409f78372901298baca1a264bd88a768379edf3643379c8aea1a8390bff55a361ca88c17c2388916265e6f01f4df6b02556906f357a0e3ae0b4490b108f8389c9cf505022efb954d0da3e254f5950f1396b2f1aa5c89cdad36e7ca42d23cdede0c3ed1bbd19284cb6a33474b89a7278453c4f4f3a1b6073d26ade3ea08a00eae0939bb9ac04168bde1c1ee1e8010504b7cabfe8ae4fa77a70258c4343009010316d13da369b8e4b2b238439a8ad735558524b1eb0490593cf6bee68c8bdd9bb98e81feb0800f2048f5e513636b8a31ff4ebac889b20cf33a730d86473ec0cfb50f2dc3052396d206fc268a759d0d2597e52ef493fe26133872e8b6d5b00e8387d535ac46f5deb03224c7fd473c7cf13a9c7aa78b30410c0fa52d89155301afd1022eca4a321517a56e8c237b57b5c1af495f316dbce19e3a8a47780204774545459fca08a2e57ea0847b2e9791a16c9058afd2d3191f09cce2fb51ac5b766f0f61468393a6e5cb93cecc69734a8c189a6a58030d468760c1e5f1bea878006e22054bc03c82698790dc18257fe3c674246b3bf585e03f0d9e7e82768ce0c1268fad46e09b0b16aea4d3335d960aa813eb3b6e2b48906fa20f07fdd408c467d03ddd4debf838a4c5d06f7fd0fdbf755042fdcc5a31fa52a4acbd6feb99604a5e4201f3962a8dfeb6752e391f2d2ba8e462ad244dba0294a6c28aa06c3cd91a87ba43b20ee4c04a339fd257d2dbe00bea8c181cf69f478bf26ad702c3f6d3fca8a41711bda64eaefb902b563260a86579be435bc32e2ea535eab0f1c7a4a33d9c4f555a46f1d6f1c63dbc9d4f58995e5315b4b22678d03ba7ee0d1b2ddfd7a350e471662f9f8dd7a594733b22ec036fb45216194017f8f751ea551760d4fbd12d1caf37b76c0309e054aa94d035706e8e982248abfd70b56529f4babb08fa9249b1e3f132c635032ec2c1d7d9e24c7d574210d148c5ba32a4f48b8904c517b6cc0f8124e432771ef3c40860accddb796f10f97d468e18125dcbe7f3ecba9e76282ed1586d0982f4ede78cd0ab83e1338193df32aa9a333dfb54249b64c35b0b39afcc6ffdb505925100783729efa1dac0b5e903d4b7a59cca00bd55001c95a4afc36245f6e92d861b39def13d0030ca032ead10eec4bfaac815fcc94aeb44537ef50cd5f795009ac4fdd3cee521f666e936ee5168a781065efa9bea30e88d561ddbffeff1ee24d4571b2605f00d2ecb86a113602129f51a62a425ad7dfdc577d295bab27aa324bd105e16d0bc5d7558c2aae7dab2ab7a39c13857b78aa986ec9fe0c38894ec6c179ab844c135677f93d9b8b4b73105116168d74312ba0c3d1144c1bcdd44e00545bf1e3312a5ae6ad220d9a49f373c04e19e81bf3c0359442182c99319a9a787ec831e651a609a0238999b6460bd639588ae9f0e76f0d64a74e037a5b24d9f3485243055651897b09652eefd4ff19a16fc627022f5eac252cd8b572c153127df7637053e5f356d0a36419afb7775996b8a17f2fcc4993b755d07413aea42dae61dd0187794215e86d1957a63a174c93b6a4acf54207b0556e1d9579a3d1c409e1097664352500240a270de9445dad7cb34ba99a998400055844f1afbb113139cd96b2f0339a639a5576897ad564f92ca46b297b38d82f44d817ae884ab7124ecb1b80b3259416299907c4272cd80b2fde86ae41fe4456a8ed1748bc160dbc3efd4f61847d773b8d742417916e507b5f8ac4744b6f4b35dc1e9f1ac83dceffd0cf1c4ca350914690a2000c9ad370a2ed808b3dcae83b0391013f743004ea88439bdec91ce010e630a93b3d5a9a336e7da4981559c2bf413c3acaa66f2e27812e8ef4bfb8f10b2b83dccd6f37e1f92812cd8bd79c611d7bef41b9c2b9facb3dd58ef5218d46aae2e5ec73f453bd7792f43e686ca6e3291c5f9bf9d18f36c93ec40a449010079f84ec2e73768c12e326b1da0f5a6c351d2229b248c8a2cc8b562ab6dad8ce1cea8d8ba38381ff0c834c87a193fb0305cb260ba81c633e42a7d2c5fb2260071be43a8192c9ed3f4e10be73072c6367cc3fe885dfc320161af37fe1065862f2096f548b8b679c82865eec6abbb54a287d307acf6f503be36c31290bc3acb655687bcf0a8918623ca52b515d0a6467fc5063d739d6579155d3ae858c8947dd96ad78ce315b78c215b42deac2e732c4be07c56cc8cae7c00f370b8c7ceef83caec8ce6027440c905425bd1ab8a2d207e5719b484dce8c2b44c8677a0538a6004d0e908140cd7a47cdc8f8d9a91f5f75d6682c81b9adfb3469ca80e72720b3a1d6322dcdb51071d6752f2195de74ce06ce94827858081dce6be6c64e3ccc310f7e32f49a678c01d8d226b3e525a6d569ea90ca056645a1c8878fa52ce9b4c0122e2bdd6c8c38171a2c051b652f27b7c4d65963a25bcdb9234d068bef87d16ae7f68f6cc813826cdd44be891f033f216926db4ad5ceb3633c38dd9b4a57cb45b3635a5807fa352e698471f79650768bae049d4bdd3f8b1296d0bdbec2237c28f534157a586c864655e6248e1ce9cd8d060bb6317a7a3a1ded7f543532d3c457cf400e99ac0f3b5e5e166fc4069c2d5649f65ef9337e83b8f1591a8b036209bba92884513a84cc023af3c11eeda13c98435be8bf1857a7122e4bc8cb0ec1534f1e9816b2c0ef8e3711d04b9b085b283c4ac11780eb4ef6cfaca2cd391d9d9be45f83164391c1e6da6cfdef34dbdf945ac27dea4f10b687d87f097162b01ede586b3ff2bcbf93d68e620955ebac1a500e394492a62ddd96aa16e9a1d701de31dbf956c3a233cfb25c2380bae40e7e0d4704ac497cfe7225e7ef884958ac8a0d9ba609bdf341255c18f2b840b636c23afc3d2f19e6d0fcbd3e464b43590af6b5d6ee94bf41ff2edccdf69f22e692b4fc885e0fc0a254237000a8cb4f8d92b447ae4b8baf2f4b1b80fbc985698f581a6b6ae491f5d2d797cf273e5375330a1ce3477be79a7df3181f9392c1064350d72ba350a02bbd21a59d3d43f018a70eee7dd78703cc45d306367e3dc9425fef38d5abc025f147643879eac46331362a3b9e6a36297f1526949aa02495333f75423fde89407b60c17aed57088fdc29a875ba76c61887fc9791af39c4d18f4469bb002014b5d5180f41751bfd886a53a1977cb1b40a26f29c87928bf4cd8c988465e3a8e8a515ec4db7a5dd08a5b9bc6a3ead499e48341343ae28d42b9d7bf3cf5513f9da6695348913eff7d3516afc3661563a4a24fe8323d95ede896001b0dbdbfc2fa7112d099dab7b8549ca1c2450e05785a314c756537f312c655ec3f1d575bb69e9ba9844c2ee30ceb1b724265a6892c19e47c13899336a52456457f8d4dad69d7cdc5b5ada9906be07a3413dca0447fbb6493c136196d65dbdf30b19f5d40764504399d8f54bb347617bce72836905e58fa2981f730b550a211fa9ce1e3dd8eb47efcc73bd436454e381c6fa097f43101e39fcd92b91b39b49910d2d207652c3420142870a82c10d6ce5a127dac7261ae54027a441887a0075e96f82cfbace1163821df8e8b5eaa3e7266f5299b09821952e4570e4577c286269b38753d9244d95fd40e64c47a6172b0fb6511cee9116b51eb4aca7563160737f8563d56591c8c1f91629868d92c45dde476bb96e60d8add6c7c9cd15df670dc47558866dd46133855eba7bb99d90ff3f7776173e6280ffd8f88ffebc50715aa90730b3039c8a99c89ca3dee05dab8b48cf86e0bd89b30d18fe3dd6358396c5640088ae9128d0797ab8ccc7854725d46369c153d6bbcc146f8a0679a333335bb2e1cce19b4aeb0edebf711d3a9dbc05a09fb599b9562bece478de097eecd14e568b11c70b3f1a6595b724fc95ecb3d4b7005335ba2b067545601a24b81a6b7b541357f9387f4531a2238bd29f98c1614be86e86d1662624c6ee9f9c7673f3ceb4d87146dbdf91d4c5e2db31e98c0b20d57b0669904368adcaf62cebc2438741d89a1ecc9950fd99dd791d86bcbf28557f815b548a6ab8e7fc95820a5b554988b402e528a692aaaa2dd6f6049fe114731e1cadff0716295affccfe5bc8c18524bd515e53992781804b4ecd661d7304f4655af54d7930366526e5d30ea08d924c8100c1df40d911c04fc68b7b520772ba491169caa1f9609b1beabb3d98dc4126b616ed51007fcdfbe363177d96f756ec6b27a83539ca5d6049709365847d42629e72ee60b7a4ccae7b553e76725240c9d4a5d769b1ea727eaae94d96d83a7a3f9b77d465abc21d04b03325a65823aa2cc7856664517dd515cbd72853606a1649e56ce98e09ac648b91ad72e61acf10e5871090fa70f9021cb77724b30d3e8bc91e4c344973e1ef44ef1ae2a4fb65e9a5f19adb0add50eb4f9e254e759b1f578eb15a04a28cfda74b98c2593d49a7d1675a90d60e9bae756004b7687780509c2e63588d33eb3abcc25697c4a6a08399067a4039f2226a6df633543ca290b4bc202d10f7624ee5717c9a59f14f89075f421c8129576f545f85101de9aa524ce730c88750d4e54182b14dfd4d4394554208c60089d21b746f02b41378aa3f4933f2aadf5b9daf8b60ac10fae00942e686b9fce2bb00940ee7f169fa3901c5882e99bb1a7a62c5321606b22d06ba925f718c7ebae05c9c606c20a95fda4535ea0aa30a6f600445718ce10be9a1ee1d8889d2d864266398ed39d5c65cfb9e038bdb8923ef541c95694481af959d184d10d1483124b40fc9adab5a5288b8862aee63273222734134de05cb6905558dd9d74a394df74422be362c096d8250987ce374aaf177357f2f017d6ca5f3898f980a834a4d31bee386a1f9548fefec8ccbb19f0d704422a5bc9bd60381c640a151c34442ca6cc58a110147db112605a359b4319480e9df5110c5beb3bf4b138c53e1c6a120713fc689b453fbb0308a66d0afeb5b6b60b10cb1246990151e8ca0b6b96faae4eb41e70b198b0ba312277f45879ffd51c8ac6ef2d0c8b9fb032139c3b2b270444327969df16d78d7b24ccc5f650c9b1d2cdf42234a938d76295781a22e3ab768ea94e415cf27d798e3af991aa1e245f6185b94d4e80060fe354955ea5ff77bd77b1436b38f31a15f2c6272ddcefaf71f4bafe961c1c788bb7bbb34875c1775b9ae8e69cc2a19ff4662fae178a73465c273078e850b50f8e369c717088ab46a25117bb693944fa17128e1a5aed369350418bc93bb974e950ef1f014a77e0c3ff503a5886e27641004d27c542e377c9a7413dbaefc3aeec962f4f54800f511429babd13b31b22e6c1a2c83d2f910aefd5df179b7888350de9c58d226e237cc242f81e1aa3c11817fee35df6e19bb361169ae5ed7c49c806915afc21ac1a7172ef034569391f7016e636021614c3e9facb7b0c3f21726b2cb0b74a508d11787ddc722c425c5298a425859dbdbc23ab115466a3ac7a0afb42a0c446c35eed15614565b7229257f0155ead30ae131a47e5158e002eaaebfa0a029b0dda8d71deb0066902440fcbb6b2932660ff4da6287f912ad2904384fae22e49c445fbc6fd6655752a711a735be46062171c20be66dea5f994cd1b508d857a99f8dcc4d17e36bf790de6d8709f3c1e6f89286e827e2952ebc29b6222b007e82ef684de6023c94a21e23695f0286aeab7c4c01b670de896fe163c381a5b887558c8af2fe00ba400847867386130124000d882327eb76311a3e246231fd9a81b40fa8e5cd16eb888fb22a622bb904c5560c8c3efb1a9895a7969b2bebf9c3f9c6ee2b177408fff7141c860025b4862e8d3057d16092ad3a2e45fe03773bb36f5d1af5844619a5e4cc216ab37352923c922563d657527813698e485fe4437b206a4af7679bbf8683183a8457b46123cc422a92f8ca726200f501f91b272f24171eab29ca786f6389b012c2a97e1f76cabc566cfc93ce93543a73c2b964ff594aa879b948a21f1914cf130e68950be724475beb044c1d175445c437b6f4358e47fffb7aed7bb0fb4bbe8fcd009cff13bac21f04e4285d718fa96d025ac0ffda03eced6a6142ed9e8e3ebde0a5eb39046174348fcaff2abfa5c2e3baf5935a6bb246bce39d73d0e5ea60eff2a05c950e1dc0653cd443ed030c38842a70106448241881f3fdcb68cb8f66c1736acad101f3154075a768860bd3e80e16b8ecab0a1f3bf16f6ba305237833012123943f212f71061a6e21a4e4b64aaadbb2769f707f0d814cc148aeae2a675d3eeb0a770878761b678c6d84dfa3918458d42bae5600456b6286cc52ad3d6fda5c37318ed4c79c2a59958e01162195693eb11437993d1f68f40cbec0bfbdfd41c32109a98f4cc8f3f8c0b569e81004fba41f13f8c43a6edcd08279811994c20c6ccc2b225310983262303bd72bbd91b3325f67c99a836fd6b04d19b30812bdc460c81c8e4d09d4428e0f26deac4ed6dbc4608ee82fb54d8ae0300dcff5a0b2d17510c949e5635db2ac70678fb0d3e1cd9eeada85eac96107a8548c941a1328860ca17865dcba235be17e57325d379de6ab3ca8c7c7e1346cd2b2601a442f3624c056ed1cd0c9d546459ec10f1f7a77be18c57d4a3fee194d29d015b64a482ff30b3f46e63feae5f3b888e6e06e38072295ef4d78cfb143b170253a5cd3cb9b2dbcf5837a6bf9fe34eb5c122be5f475f3e7b1d6c1bf80869b1a8eef1ee8c668fd5bfc898755597da184cdb1500d4253b4a14bd9355f14db5109365cf72aaa0e4531bb1524fa3eaa5700b6b4d9c49aea640a9d036657b4e19f04e1e8278790ad0ad8e705052c6f67f6b79789d7206152ec1eabb05f26487ca211e0d7b86c94e43a82b25fee06a40796ddb27fd82b5964d1525dda5d781666bc9c4931f361707f72000089dbaf449317b718fe1ed007ae18d3fde70e095848c1d9d1577264a7a477de0a124a93a27ee1d1b87f50cf577f985e18482ccbb076d958517bd3a7d7e54419d41ec76b263751007d1195367d508dfd1ff938ab47d0d7c8d03bd598d992da41ae6bba5b3b8cfcd75338ee0b48fe1733739c32ec1acda35f27c60ef78eda46f0e7dad8642dad48bf382b644bdd5f9c16f4c7eaf79bfa43a8555e0ae9bbf4b8252bc25b011ded2fcf2c1c3a8042349675cbc4a39ca44653c72d2c1087a92ae6006d9a92699aca5249965b2f62dbc0220b24527fcfeeabdbb109d8be8540ce4cd18efba5cd895731ec2ed4ed382a29191150314005e74fb78960ac70beaebc11541ceee63fe1e51c4343216d9efc3bdd5a76a64867c78d6f6670e98c7ca951d81c7db4419cb6367eb9067a6180376e178ba107267ffb2b9a143ec27750ad1012d53d4a9a508bce113b26c0eb9ffba174359be1bddd7d6a6b64cd9a8326734530898766fcf7d68895a28acc43dff330664e5dd1d97d9949b728f23a1f25bcaf595bdd0e128c29becde7cfce32a71c5e9b52c5ad9fbdd300526533f4ed39ef3ebdad3ba0e1c5b72f59f9bed0888fe3ec56e859bb333e7dfd33169f8d2e9d5c75d1bf3608851966771fa1f51b6e5e4ed5377c66af00b792909720ddf6376e4ba020179997a2037edf6bbf653c3765baf861664b8e94d5384a8ee43ff79ab350f231ccba63d5b390795f79c64c5a949dc9b9037c7b86d8bc8763642efe8f05e12e5d0ab5f7d51c3e1087ccded00d5bd15feed1e02e403d686f4fe0cad64bfeda97808d112cf656c23c5f83dead09860fcd6fb8006fe3a463438aa730adbbf68f55f645d318f649bba8f1428ab5db26be321e399aa4c37f7cb5279ecd94083d07c899ac27161fbe4a2b7c4a87d9bc44747eedb185bcd9379140f6594a4b32f890cabdb536170096ef777aa95ab9f94ac203cc95940414dd74585bf91cac2bb2fd42d748434c59bd199ec20a7b8ebf7ff61c47d899dab68bf7a5175bf0576eba37dadec663c768c0b048ad133f454df0304ecf16d9330fc1d75a09d77636dd08f3efacaa09c9fc7185a789d034990273c16dc3084184be9a69eb811cc4c20ee7050715ff805f3c776577a0fec8414d37a753b916757b5f1ee407e41b5f05837402b2854d95e96e6fed7094ec6c4ee6f86b26683e95742c767de469cf8ede0e17d281b93916e6ed2aec540763726ddb01fde656a203789726bf8603be63845a2997ac54832a58af8a01fc44f43c21cc2b386db919aec78820498fb98db41de0f8b562dfd475fd95e68c6f0bbac9d2c12b4aadb77628b210d614e4b0597f753e5fdd8cca8af31fc001f0379a70d61c7c8fca60b80e63eb27a50fa2294a0632ccbcec42682361875c4583f4b65c7e5e22d7476b956dc5b044a041167b224d6b8ce002e9bf6cd1f24ba8b98af274d07cbf3ce493fab7716351e930687227e9a17dc5f33803d0025787567b6a3520a790ba90d0741912052e4400e30e3a1ac6855f3c01204f5fac95e0aba22ac50eb2954a0ad4248e5f5f159a89675d78891416302daffc05d54895365889d8e74124952c71002f8a77360fac6e21e0d21cf0bd618628a190f715e3d8d882bc068c8986165f84105f35e2a298649b564dc0c0ad269ba38c7430cbfb536d28a9b1811859071a05a22be344bd0d8ebc22791f0c350a264219bf2fa13c34858b2640ff016222de6bc17be88026de7f06fc9671f19f2fec9a393b10af110c14d2d10574170da6d3f418e8284e07a55ab20d0ac3f1cc750503bdb6cb35ba20c82826e9d9f59a42e54a8b74319c571d301b6f010e026d606c320bbd47d4fb3dcc760af0cee314451377d037f2c7c1eb798304fc441ad19b8e1524ed93578aa966ffb81801141b11fe9f6cabd3785b4669df936c7ec13cb5b360e848f3a06518aedd9d59c0e5ea4c7ab18f95b412bd17f6825750db904d7f2b4efce7341d2b7d01fd345bf486b5fa1a01fc9748198f8ecf81026c35dffc8a98489d7856a7ed326054e913d57bfaf07a91c0ec29c66d58898d6f338490c6307071c718f62ac26567853b41bd242a8a3a6134840d16548040064344e7ab4b7a3265fc74e6c7b00c36162f2620773e00d310ac87f0081cec714d0f40604a2e29f18a2ff8b75a8ad7816d738b2986d1344c93758fd8999e95c2137ae30ae2b7b667c3240d636aa48136a4cf76c00d5fe00eeb96ac19c7c0411bdcd64a3c2ede577069b5eb2070bbf330117cee305c9e422ec45e8e12f14c41bf7cd89cce91ac5c316b5c00769694cd96a352bfe37f858d7abe4b766a014770b665eac59c9df487075827b51df49a86acc269c847206edc63f3476704dc59831f94069382b0baed52f6e6440853a38db85fc0177ed438876054f7c553fac5c57b72e2f17043b5138635ece2fd9d1a901894719ef013afc8685d647665191462727081ea38d9e939d7348415bf1a3e59e8268f8bbd07d0bd92d4b2eb1390f7b2628f5007a07e3765948906620219ea24780743046b5b67673d3f608c55bceeac031c2cbe26722eada9662b63ccac2549534beac0ca33b9d35d0f57f45de70ec84f86fc88399395eab1d11b13959c6ed1c5fa5c59dcfeaf42cc35c5312b7266bf9aca76912edaa76aeafcfcb00a994ee50ad828a900cf13b43e0e3d60111a4586654256c9a87538fc761c53901c12850ae605b4ec7a7d42064fb1151279927b5d27325d87a2528ae6ea952fdf98232688c19f5b07d32479a0ca4807ac647337090384a7f16004007699183784ff61ea3e0bb5547b085ba382aa28c35c585de0959a4a020b083249edd8f311be06478e213ecb12a814415be8f8979337e06012019c800e720890cf91ac2c79ffe447d0909173e5e8f3de1e8ad8c4bb9416eaefb6b1eca381744e6beae23a92587e8d65aa8256bf1ff76838e73a32874f13e260eab3ef3d64d38779c01470a8218f977c44233fdf5ca3565a6f54abe3278eb634413dc77fcd7b10ff01acce0b7814f70733c721c7577c916449804a63f4d6a08a1ec87d93a3cd650f24da47bd5813d0b24c62852648b0efdf211abfa463c2ddc892affa9bfcb103e24217a180e317081d1afe2b9cc315a954abd7cc3316a55bb4fa00a08395078a80fb57c4d79b9542d766d9df3ffb45db61004184b5d3521f0290aacf87459256184fd42b8f411251a1cddeaeb40cba622723db394b63180f431673f4f361a7b166ffa20358fa980426801ba7bfbb84f8fddbf005170addceb364bcf5bc581d9631e001f7ff8926e8670fa34f16dc61e08a2f405336ba1cdbc4c330cf6ffb154145c9fa060851dc0d7db7bb44b4835668ab5a8b725c353ef40bdb1dd1baf820c933dca1ff3f3856255962aa9faa83258e4127972b0c1028dd9c831b9a7c6e56fb6009abfbff3d8dca4a317acb0d19de36ce50245d208b1f6bfd9dfff026b965c5319c06ac1ff5fa86e28027bedb41ccb08b97701c0c39d9b29443d844b7852e436f00351d6d9981f7e10abe7d9688029372108d4e6029a13e26a5f50d0596d0e569c311c39bbf2cedd40ce551ab32d77c5bf03bb73a7487194449621e55daf0fc471919049fe6ca41a1f1664f51912d4d1ef7610870000339180dcc6413341eae32f2fee011a6cf066b08085a7f79f6de9a525a3255bca94640ac906d1065206f672a48e86a5cb75dfe5ba8e86dee5bc8e86dde5be8e86dce54a1d0d49dbe54c1d0db5ec722b3a1a629763e968582f87ea68482fd7d2d1d02fe7d2819ceae5e5a322c631ea57095c6f06c0cbe55e39cce5ef2c0b4bafc69fd17aa592c140c0f10c896298760a02b1d846e23aef2b59d30966050c8ceaa57f52ede324e8a54b754ff3bcbca860c00eb2b3a3728969e91fcd8a618162920e76be9a73582ea78e58d26b611ec5253797d7ca3071ba523bccf292a622eda2c21180e2a9c869e6d0504b0be5259946d3e845d5c204033363a7d12d2710ebe9c06b314d7b4df0cd66e43d717b33f29bcdd59baba9f488830cc6f3e10befe876abceadecb137d746a585c2ee85a9889f4c274e8afc6e2ef105eebce8b270facc1e54909764fecc9f7105b3c807b76576e0c66dfe6005d971e14d1e9e1168af7a44e08500175e50008f1efb693c07605bb9551941871672809e0a7e5d0461782da24b6e2e8c8769fa5b546e3f7603df34111690bb14853515b118354aa87ba857a8211414134ac824c564b4c28d12ba12bc1af54b4e58195d12b79fd44c454cd32618f00d4a08254483a1dbc91811ea5515319e1ea1a0867a85f56042309eea9eabc7f65a4702f05a34647429239634155d981acd92e3351505612af29bcde534fddacb566eae544d8d4dc380a08d099305e60476e695e7f25ade0c192cb9b93cd746652b7b6532eab1bfa8c7965283a9e86adc091d4c0ccc872a9a9142c502fd4a5d54b1e05877adc9e860493bb313e4b2129789ac10b92a167af00a50c0038be41edcf90c98482c39d638cd7c2a4661c91a97279860e9b057e3a50a1247f4e0ca25d906485c1a482cc9423ee0445baa711ae65ec202f38765c4112f606942dc59c462b12c80baf359fabbeb0e037718d767a070bde42413b570e723b771eaec9ec425a790ebb3c8f5cfff08299e5c7feaaf59b1e1fa5bd08a91ebff56caeb3f4e01c4f5af615d7f1c1a4b5c3fe28a0fae7f0b2ed870fd1590e4fa114378e2fa47a0c88ecf752aaa5c3fa28a237ac5442c1eae371d82144002e06a429412e050430fac08a1884ead21b835886f1c6744cb47f440032cc880055c2538524150835b7f0607a6ddc00da590ea7335cefacdd4d1f1702e878564fb5c8d9c4357d34680c2762117aab0f7a1430a559898e387d63e745e40ccd71ec690651dd2bfd3680f040b4d127b58b1c57ecd0882659d6ed65161624d8fdae3388df62f48d89f52831b1bd05ed39e9bddd7ea633615e2a6d16d274ea36a4cec41fafa3d36f0b5b048d53dd869eab3a0d5dfc41e55ece143c7870e8fa921969a7458c7abd3e4588e318fac1b31b589cd39bbc3b0aa516cf6a0699ac69aa7829661b31379acf488ab3a4c8465079ca6e9e8a75fe9f7d3e76cb0f352cadb3cba140a97404f0f625832c59223288610c2a9d061a6a088e50a02941b7210d4811cbe882386308a12850c920882954313408a62c06148088810614237a003152e242e22a080c10f20a8067420e189097c50d0b2c10d2a00a23c3abc943c31030e76406589202cd981884c153fa8a1881834c182223f104141c90e0f21986283264f9414d1840a70706da086a09f1e420406296a30031139c400073824a141872ec9eb060b8cc0074536507da0472e1151b460062aa07243901e0eb0040f452368c24813508abcc8b2a7c8872952fc005291501bea1386520443a142e7a4623f4f9ea5d9820f07cb1f5aee776f85b9b538a390f656f74dcbb25a297d99ea2d61999aae0be14090b14969e52aaa5c9cb75e191a63e6ad6bff99b3e9ec9e33098e9999ce593a0cc700a5b0fcf3c197e56f7628649d14fbea74d65aa9b7426d1c685ad6cd23b4f95aff0b1496bfbb2790bda924b388d5165e94c0f23b539fec3d9de0381a2a2bb6bffe24b5dbddb49b07d6ded26e302d63a7e96c104add3dc35a785102eb357c61ec1c6cbb7059172edbef94369d1d03ed28ad9492a2f0d33aa90fdf3f318c39cbb2ccdd356650a32d036ea36269785dfe1728ec7c77c77e700cfe972017b8fc93b3596562581531ec5db859ad3d6a5e318f210809e7349217188c3614d6929e2fb73d8dd63edb5efbd2f527597bb7b777631628d6b2fc60e77710a9db054c299d31a899de24649b96a15eb65e3ee24544124f40a2252682ce6908aaf3f5f3cd99f1ef8f1a10a2f65f44bc39807ff170334f43f9e36ba7d26892135a4b4224acb7ac44033ba1a0305e127df1a08b507fcaa8992102ce0bfa99e7d520514aa2353d8383c20b1758d55edcb0aabda6897eeb6b615f0f6738c6c4b0ad56c7b47fd0b962240ce76bc019cea998c6b15cf7fa5cd7859d9d2ce341e7971370dc14b18a651aa92b96691b57a39f76b786d2b61a52c75e3f8deee87318d5364e64f176d78fb1ac63f06b3a60b35217dcdd9f597376779f71f7ce5d9c09a5163c763ef56ccc2bf2d882c7d6ffe63b3731f6ceea9c222d4d4d386691a43eb4c8959791942641cee341a8b886a020699f665d9962e4a4c9143279ca1798e8462a05967b9c49819d3cfd9b9f29615d7e22213c97451e2770a5cb443c47a92be3d57a34c2cde7995006375cee91aba98372b9478ed1a19d21388db04c74812997ec529cc39cf3c3df3b5070ce1a9028728265840f11200c01ced9243812c4142340011538d426496234bf4cc4a2413fe1b4bb2f57e2019ddecc4c359fb4d21a962c59b264c9923997f8f7f420ce811cc8811cc8811cc81d68083a63d6d4b4cff83f8cf187d63a35ad62d5378d096666666666666666666666f688d05aa3736366c698703c43d664d4b9a971a40e7bc658fcf04c72f7204d9a803170dcacb7332fd1ac96b04cdb485ce77d256b3aad6041b5b8801d92598764f38beaeba7dd4dbb9b8a80ab1bd7c4cea7a7d30a4e816085d784a4accbdf2af09a3033339d9599a9b85a55c6035d4bc7792ea5cfd2ccd57297bb7b3530bf9e611876d462f0645af13e30a04da1585a68ad152c5d2515173fe69462efdacdea6dcd8e323f3fa7eabc2653c60376ae260b19a694763d924e3577161dfd98a65e93b013bd1afc220d9962b5babb7badeed5eb57af492a0476bed7c4858b172fc65005763e1dddbf1b47198410828d701cb2bb978cd85483eed2724949d8f9252316c5b2e274a7c996ee3462bfae64c47a2523b62b19b1dc9dcfd9ae64c4924e2b58502d2e1dd8a5ba97d4e75fe79c3cbbbe5ca7945228cd32ddf9e5faf7251370b3273866e61766eb0d91a29d0692cccc586dc982c8829e1da5f58a99d91b62b28c58f6177577ea0d5133a321e60924bdc5914c1d57ddddadbbf7ecf4f3acbb3b35fa403a44844805f586606676238eb4794490cccc1e11cccc1d7dd2dde751c55c8468a1f5ab4b27f3013bdf9d7a49692ac8cea7ef0dc1ccac39f7926ad5cb8481f20cd3e248997ac1b24c158405a960302c080626860525423b10c34206c3e64422f31836279217d50c966541574022984b104c8c08732221e27285858c8b39911071b922828b393be07225145bd0502444e88fcb951633349408fd71b932d2605916e442046b09a219a1c80824381d7f7cfca1e30f8c1873fec4704ac28f93f04349f8294106c57668c102254a680009ad700368a89258fde3c811a08a55ac32611d19385a022021cc390f5317bc2ed4b3e9eeeeeeeeeeeeeeeeeea9ce290068bfdce9d3a74fdfa600ca66285b5cc08a6129269549eaa556262f2f2a183fe243625a5aad1816a82254510a8885cc570cab4b5ac2138029b16218132b2d472a8ac98baa85bb9223282b303133ee4a8ea0acb498711f82b222f3e10b5772c481505642f1851f71209415172f2a8631411da92c4c5e8c3e230d751740d40590bb001a8104772012a8d300511a20a7018211c36b919a6202fa0f3062c8a8517264480925c8a8f1233e44464dc5a8634ca8bffcd414931a9b5add87d89850abfb10134ea8d57dc809302d8660b35bc73d1bd3c99cf3faf0f98011fc9419c65a0644cdc2d14b023a0dc9067666d909c68663f4cf1a147070328cdea021006eb980805ead5ae830070b43b62bfad1b2324312d46307b55aad5609a65ea64b355b41b3355fb32c5530d3a8080626860518c342a645e651747b6d574a55b60f4bf155563124e48350eb47aca2f5d252cdb4ca1f9f209fd64bbc023a71f192cca01904132382c9e572b190710184b519b55eafe9bdaebc4468b988a2dc86a6680df9cdf67a852cb1058d57529657a5c5da5edb158c75bb484f4f8b191ada9a42787e785ee21570c7d2741170800b91d74e8b9764b282583423bc84aa6809b98ab446206133400b21025c68bd307a0a8011230717c3338a020e8e0068ac408277e367a80419747b6d2f2235e3482fedc1cee74af04a1936266c2f20aced8a0c7cd341411a68b58e90985ae56d1697a9155453e3953626e8a0d504df78a5e98997c722e2957eb3bdbcf24a076c5a26386d592d486bf9cdf6f2168561f160fb31950927b48fcf0933260fcf0c006c556caf6d0abec130d1d422c9704d2dd351075a0080916151241ab9f85e0d1d96d4cc18cab22ccb9717150cd83f483ca41d52909e8f45daa9c14959962faa16a6d7ebb5b98c5ce507e4637d327c1a2849413ed6f7a324f1dc26ed908294a49db22c493ba41aca57d9ba246907e792763e1669e7639182709b4ca62a290f94e5ab6cb98eca96a98ae9d58aa20402dfa05aad29483b1e4febc855fddbf958df8f8f5596a5df9076483b2569a724f19076ca2ae5b7f3b1be1fa49d8f75fb493ba420249e5e995e6595b21401098e63f621666e00adadc3cd4ec53aadd3fd31c7701daf00c735b30d983b93e0a64c67344c5df0ba5c2dcc4a3bb0968bba5a98314d2dedd058ee8acb651d0d4fa1e9725b47c33d9fb85d8b5c5a85dc5983dc597f5cb9f36995bec95893962417b919cb6f307ae5923363fdc878825c72b6b29e5b85643eb79fca7d00bded22d6c281edbaebe98af48d57763dbdf2daf5905dcf9d474dd3efe26cf5cf39e7537e9712df644ce3cc32fca7875e8d493f961604c7dff77ddf77fabed3f77da7ff4eff9dfe5bf1df77fabe53e9fbbeeffbbe2f6479f00be735994ca6effbbeeffbbed3f79dbeeff47d9ffd4ea7ef4f2751b5e2fbd34954ad389dbe5f21aa4ea73f9dec77fabeef7bceeb68c7629d9f25449d4e618ed2f77ddff77ddff79ca9337ddff77ddfe9fb4edff77d3adfe7a7ef4d7f12c9ef4fdf9b9efb4e9f29a47f0aabe9e9f72cd21ebf678bedd43001e78310c6186318e6363fb6fbfb27e738fdbaa374b1a759386f7d77fffa343aa358e5771b2476b6ba6bfdb01820e61011902977e632111027f7e7f2e59bc5d86049f03ac730b13a78cc146ad81cb1a4a6691ca91bafbbffd8ab98202c096a8fc1d4eab50ed2f398f785f166e3a671d9fb7359b8a374b7d7b22c7bec92886098d7bd7e2cd4918dbdf287d12b1da49a199cb3bd3f0038a7fe8e924780fad8479141d1c54861a8c1306f267a355ad53ce3d90f389eb9323df31bcddbc5d92251b16119fd0f368c19c52c2710f86646a330c5edef9a234bceb24aafe6a522cc6cf51892e36cb9c63dd997d4a39f4c19fda45238b349e562df937d7f3fd9bec5ed39f149cee8de28e0d62e499ce591255ba8dce62c2b393d154a978ab3d5e39c356405aefbfc6f6e2bc8d8f4a7d0f4dce9f9f434da743a997efe3c85a629b28c7e434a8ffe26530f413ef8f05cfb2725822ecb9f8880f45cadd398ddb19deb7c534f61ad524b8ee19f6a59dbeab1c854cb546972e7f19abe1a79053889758a49ac45363e581d94d5a33f8f79ddc607abc3f43ce63dbd29ac42f5498f363d749867a33e7df0f4a727ece90696fce94eeb773a89154a8fa44be9f124922fccf29e9ea55727310462abab477f2bd6a3ec8f3217e798fe664e984495b51e014e6f32892a9bb57aa532954ca637994ee20a4cd8d393b56c953707e798de9f3bcd1b02b12bfe6b955e9ddebfbe38c7ce5ba5e09c1db3bccc31dc8a2a96cf23c0e9ad15552c2b957df247c7717a1651654515c66bdf8a37deabf4e87f0a6198d78a2bf4e8d74f7f0aeb0f3846d9b24440762edfd3735d9732ddd39f4e3fd9abd1f77b2fc5fe4eb58aebcf3066eee9f42c936f6ac934fea7d373b4fb42d4d3b0f4d33bbd97154aaf4cef5f87fca6e5f976f6fd5349589fcba3afc9f464fd5ab68443d77b1ba24272deef0404bec9e134ce758aebd935895da4477f1b10905e7ad92b969bacb502d33ecb5ace22d6326b6d2bc4d6f58789c29a441da737bd15c9d3db37bd3d994a22d95dea71514856290f9877ab240bcb253d7c00bda497d7f90698952b1a2543abc50292302e20cb0726a9e41cd57c4981b4b62881a194c8fce537fe624a596ee4a5cbd563939ef0a1cc27fcb95990d3905cbdca7278825759111efb3b7382dd9214fb007a95f000134aae1342dc7625320f6439d02c872877663e7ed3ee95c732e14cd4fa53baea5115bde54224d30c2ebf1b293195f0b9dec2a61875489caebf69883a0559b40fc46e70f9bde54cd46f8a391318f653bab0238c0449cd1bf2219edfef454f7a945b7f4e0e894b663d3e94ed70a360459c63bafd251fa2df9f9a92f55cfa2c9837d9f417dc7629b5dbc0ac47339d30cb393c8f5c6cdff8d033975a96b43fbf9404e792f5908c52532c699d825e547ff3a1194f42fa8d94f5643d43604ffbbcb0b83584b9a5242c3933349b9d52f16aa1e634f3b954bfcccc874b495832eb21b90facc3245c8a0696f41d5b54fabc8e23715234b0bec3395bf77c6a84812244301084ca108d9cde255c8e351853863f7dd23592488297866f21a9699b48f6b89bcfec993c93f5ba52bae6aa0eb1100e59336180a24679559f9276478f3bdfef9c22e9a3bd1a949643d3e77569d18e086497acc08eec62e274188dd559b4bd88b890167af467a14711dcc192204f76f7a396db300330a790dba17bf6eeee2e64237d5cf76a90486fa33ee97ddc0e494af6084921f7bc33e4d15713dd8629a38fb869f89d7907ca4c293333a594524a29a53578f2a208ebcf0c85871b482492486e9b6fef9ba8815e8599293353caccd5293f531f9792c4882c8888e8c91320209e2620892e5044f3d666ea0238193004cc55c8e5e79f9385660d7a7459a847fe394b336a38468d9138975fd3b46d6a35ecf69aa6699567d4cca03fc31a6ed65ab5eb4fe6b8e4e370359cd12316d6d72a7dccbbc1778a3ab2d744b2e662f4d65083808fbbcdc7b82cace9117b2da4218e5723cbb41b35a81f62f0c39ddb7b4d8f367c78385c84808f3b7f7baefee4481ef3eaa83524ab8b4f7a2f85f9cdfe2471468fd877a86313716e468363609fda81ad338460fd79064eaf3631023d622f80a6c1beeb5858606066662e86f1e811fb1e31a1d905a9dff77da22ac725bbaedbb6edbb19a45c6ec165a2197e5c6e7a36e8e51eb7a73f9df6f5fb5adfabdfd5efbcefbeaff5bdfade0c47d7deba52f1cdb22c237d5c98540b8a85e5643275dea7be5aeac21da5efbdb0d4755dd795baaf863abcefabc7bd74dff7799ef779def542ad476f10c6eaf0c0947dcf6a9aa7f1f53cd1865aa8c3fb707862ad9ee751805251eb42be29607707d6b7af0a87dfee5538fc9213b89da85defc95e43bf34d4583c0c70e66ecf240ccbddbe23fdb6711bdd1edb8ebaee3faf4607f6e85fd4527a356f2bd17d7dafa2cafb4980ee6b17f58a3b0f47f7de78eb5771ac30cc5b4518507a457a5f7ad7e1bd50afbaf7e7489e0af3eb7721dfcdc3e1755fb9f6f1ed5177bbdb8b7059745ed8b7f354f86ef570946ed5de6b8de318dbdb20b13d58afabef792a9442b2bb5d065a979fb84c344395cbb1e86c7cb06451f79d4d0fdf3d8f7975743d390cebb76ddefd692249014dab21ed0cabb5725c4fe6e857eafeebde1335a7d15c48824797046f8e4b6a2246bb345958e17886d4ca5b27063439f630da63594cd449d73daa7bd40a14ed01fb0ca8e766dffd70312e8f4ab9b87c0bf65a14269c5cedb7204097a35c26ca40793917efa5707aeec5382386e18a4fa150dfc9782accae63e1e1407d978dd04dce992d0fb6bc80dff212ce2b534217feb3888979a137cb7e6659968529d04be1f4df732374b4c741d05ab055c4694eb840af00f4b377696947bd72b9ac78919c974cfd8ad7a4f48aec9ef4f535a35ee9e8b4a25ea154985198f841857c593c1c9d0bed11f59c16e437d315e437aca3d9cee4a5d0d705057e0bf864f62f5f1f0b72f9fad80fe7a8be3ea68473505f9f43a1fee5b3909c1765f208807a179747a19e69b40a25aa60a017fc1da50b3e0af520f83e39674e1b24b67449ecc766074b623da8e76a6c8c30d613a4c8a50f7e7b38e883220cf3eac868b44fafb217914ca54a9f872325a242be2d21eadb7b09f9bab763de9696a73ca93fa1be7a3674b43c8f795d3e25da18b124d673eb633ebd6a117b7a058a644b915eb9883a5adee53d0f478b8b4d373927051da7671b2396a4d84f0ab38acb8325e90e16947ddd1ea8573abccec3b189d96b22c7b988a4868599a8f588ba98082c221983ba99cbbbd967d9779cd37d567a2e0b390cd8cc468d48a3310cfbae57a4c7f89ec81917e74e52a301a33c748706e915ed9d0fb5201ca37eeff88d4603d3d4efe15623b70eb9b572e20fd0ad4f0a31a01eeb4f8f35c88956b52641f5a913bf611dcdc25065aa4c5461bce3a539aeb63dbd59d6f2c1588f5af842cdcd70aecb148d50b9acdb710e110c28b79f9c81b94e9bdc50a0a6e99a193853ae752a97753b51fba4d879c916ba4365d3f0bd43af1ef9f6df201e9ee6199b758ba0e078a686d9dd9dc3176a68ccd0346b41f071346fd21934a8a6590b82ff22066ce0f44873dc176aae7fd3b8417bd29eb427ed497b522a52f7afb5bbdb51e8b1e6523a03c7983b1c837e6a071ab69aac8e7ed7b1b0c0c0ccccc02061f4e8913e8d4e393179362a8a20ca810ebe5bd61dff1fd0c7f6f0689ab520f8cfe180de518752446424a535e5fae63aba2ecebb0df98da6590b825ce3809ae62ea6d0f5ff12ed04b9fe7f857e08b92c24834b48862757ca944b3b231c34b7b27a4c41b1e4f612c118232c09825504b7571121d2d10e501157a5e749d7faf1c339449cd39f10cee914146d06102c2d2f7f9afdb1bdb69ebed9341ffb0306f536e4e4f626f439714db3f673e2c488be7ac5d4881ad9f897df68df1fda34b14eebf3cdc414fa0a4da1ad64cfc5edd563cc092c3dea1509ba7a456eaf6bd4ab6e6d2f1005cee9fec139cd39449cd3429cf414169221a7c2439b704edf1acef1677a59d3ac058dc6ed4a8ffd45db6b9be284cb8fd33724960d0760938265b48ba9234b7697ea80cea0b78d8fd26a7239ca1246245c8eb204d0f52addd1e392dc751b84eb6e83c43ae62a156e1575f8578dc7bc241fbf611d5a3aedc9f35b2d527c3d7d707bf69c73ce96cf26029bf9a8a4ec596a620ad58c0040000000f315000020140807c442814814a5a922a13d14800d7388446c623695c7a21cc8811005310619420c00c018638c31cad4cc1001508209d9025c4c5698bc193121fba57cdd2c8c82d0a064948c33526d6e914b03a00d0c461b52b30fa9aa9efb6c0c76b92aa861d2d14744e35deb3e4e142a8abd14b9595eca9bf938e33313393c8d2e6ea22bfa5342fb14f5f14cca73a8a8260dcf366d3df30cf71ad4602ac46d5af8757b32c3912a0de47eaabd87a4c6f66ed34a1102999e835f4d11a91497311cc94ffbddb11ffc14e4d2e7c299e9c001bc049beb090736612e4e9307cf0d5d9b36025ae33160f572cadc4bdf85226f1381021e154b2aef5dd4cf6629abbb0a6fbb19e804de7fe73bc7ac7a00f68fc884cbb186a390e56b6c747ba2dea9b75f3bc0b3205133456f5d0cbc06aa6a3a2f7ca10922b9d32e91ace469d40bef612f316cb3d29982a5ea56bf210b77ae3a44ee47d368876dc371b262cb130d6fe61f644c9dbf5422fc850ba0860633542392192c58e56f97b51d1eadec7ea2105bb05abede55aca0e3b3b4c8666c4bd8093740b79f9765d956e827ebe8309afa8a1619c9757b793a52ac8466ea82cd9fe41354a6ebbd6f8a5725cf9a769ab08ed48dc75536eddbccc9d493b173fcbf2656361e00d410aebb00561eff334dc038c63191b40eeb214c4a241b2861193d8a2360d0e4f331ba42985e6ef7990f01e3d8e510ebbc9fd341131777005bc1f15ee4fcfbb7eb5923186a8ba5dd04020d7d86428d45c7743fbfd26857f5a012df7b1868b368826041e1ca55d5da18673e02c4f7ace32092afc7cc694b01529f1813af893342304ec6921c9f2025e595dfb56f767a2fab5e3183458df4e5b18c241714d3204aa1ca9bbc8a64a5b9befa229b6b6dcbdabd2cf73828aa668a1cef9804da0aeabe967ba7adf49153db5674808d16f413c1d9026d7652733388ecb021fed9d7ed12fb2b374bea5db2740404d4f21ed2139df3f039fb92a23112418b3968e6394200e6bc4f101b85d536843312dd4fab54d375e41956a342ee665ae11c0dd7241d3ef42b86482dbd508f6f240550991936fac5aa6381133caf0368b5c43dc8d6dbb9be0cae8bb7c952e3c5904cf18bece405ede463fcef77a34d145edfcf76d68849b85861de981d78d83a9b32e091e54fa527850d62a10129d1702b2387a40bfc882cdf142dd14fe964053822e2eed57fca503bcdff8d2112f9140e5e9b65811485b039aeb582819a21e002cc0f46ad826ca062ec45a0aa58fc3b527c02d4048061cdd85104ae83142b775c4fb72f729e4f1a5034ba5b20c83daafa3047523c6546c0ac5667d3054659e2377298b27d98f50d8e227fa446115cd6eff6eaf56845c541f9b27dc01a3ea64a9752c2ef4b7fd7055a04f06290a486aa66b14f3153f0467b8dd9c3b5de4cebe7f4396ec19e67e077eb74363201ada92c64b5313b972f20aef2d4408df13d05cb37768a2e5204a11cf7b58f42c9cf0470dc841cd29d462a5da291df5f4950eb042909985f0e63a2a6d7196abc5eb081530f595b31278239cc90bb375957734f70ba687ea04bd1387b07ccbae13bcfbd595f57b296f7d0731881abceeeffe67178604d2358ae0109d84803662093e3c4dbe34c420c3ca1c6aadcb928bde51afc18776b3b0269a68c79f021b3af2347f5d3ca8ebf8123a96752ed4374479ede6efd252270eb97a4ed57cf38fc82c859ae4adac0addf26dcfc58ee2cfc30d0c92d5cb3cb29f9b719e05899960b1343f0d5953f074364c5bcd936b29b7696266d83bdeb2446c4f82723ccc06256db1b3e1daac59c7085ddc406c9ca81cc17f4b5d7d1c3500d89fc872a8e235a7aaf296cbb304ada7fecacf481936f9ef7c734f0956460e353497e6d7dcd44c04507d46a3cfbd8d2155e92e4fdcf68c98698624938f2713e359349b0bc04cc387f3c133c12d082e8a56b193e61581a1d70c802d31db9ce5d5cd66a6ed27c5b217561b97e6bf68fc9ab5d64d3a265650d4caf719a69763838999fef033694e72048334c563ee01a8f0952f99ff3a7c7793827b03b59fa295c836e9dba6a19e4d6c3af946f180a31e960c8fcfbadd58d4444584afba3164a130458570d3f8008abff676f9506a62048aac68d06b2606b6ca7ae71d091cdf2f636255d9d41653ddb6c5f5690f44c530826738d319df2d5257c74dd1e953b72169e935546922cd142b355f1657e2c500daaa809b04aaf04133b2e6e12f6c59f58282dca0df89fd0859f0ad7bd5013a74df96e1049057e96f8e1fce2195cae95ccf94d8222369e8c5c7e8354184e86b120de6018e9de6a1507235aaba807a7c0190da540d7296eef982cf23ea018f18774ad7f88c4f266c43f44e6b385c61507464c22b01e28984e593201a70a0ed4a6dc5711be08fbdfcb8a504cff3055fcc116b5f8b67b01f04476879ffa3488ba2d007256117411f36762bf02aeaa3bff2e2dcf19a7fbd188dcc223680cae48ff04acb853de24f1bda9c1ff3e5bad4d34f62295916429942943dda452ed3e457daddb22d4b230a9232265f11cec758df2900cc70eddf9acd0e2fb336522e118298b053c22ea5e076cc8dd2881e1214706852dd78d40594b2f0a8c292953112238745b59e93c4cc4b527f6acb526c7909e0721efb8b194b30c8e13d8d5f02920a9eeb59c3f4a46a9562d36051f5db4aba3f6138e50048c7ba58618412d1ab725d529a76f49fd7edded3b5d89418f52c66a34751bd238479e2e6b941b04f7cf2bb68f3442d832559380ae00baf29f7f233417b8286e0522961dd76bb38041442ab877134ebd1687ce9d9159528925f1f519ff6dd654e9270782f00d8444af3a46f481aefc2c04b5df27464b41eee3596063407f823dfdc38e8b337a8983c08b43c8c9b94b1ceb1486f44776ccd30fb25e804adce7cf0464648ed8c6bf2c98059629c20bdcbee7ba74ee840dd980ffa4bd74ff3d88214cca1708733becaa5521b31368b6f266cda49b4b7d73687fbd652f724d45d3d8d448711e9c9f1ec486837cf61cf2cb514e71e47850ce3b153929bdc519e2753c894a1525a34ddb733662237636fa9e11a24fed1365f03fda89de0874a735858e653a286bf180e189b48323931f63e409e7a9dd8d71379a2d2477ac318df113fc2681b6c47d237b444663c311c9ec49a16d12fa54babb8405b343b3a74ba9c2e1e96b65c492197ae666b995d093370431c4f873f0946ec813c82104dea1d7a5c37d9fa394315e9f842fa7bcefd4af8331b0b2ab789e932d29bbe9e96da97e9918a174550f76b585471be759d6afdc42e05b2a9b6a7e6f86738d97c70dcdfac47c033d10ee82930b4376c5b9ac292511776c653871784545330aeb66e54ba3c3fc57e911178bbd931a18b18f2aaae27205938c16d33f6bf94fb4664305b068a9de1f1e482ecfc112dc5c089c28c5b3118034cef6ffde90944a72dd9d36d7788e0e11b670991a4eabcb512f8851a65f129c59b5603738a134f675a2761b2fbae599637fef991fbe4063fe2ed4805589987577f16cf81369ea8a88b0f669e7c70513e9f99b872da1c8e118786bfbda2051f29f16bfe4f620eac1c8422721664710e967345b336da01d667c3e825d2bbbec5af0e048a61e3ed9a5db5da43be9b5d1180c869853699ae5a286f69ca047a4f63bbe1b3caf291efb3f7747d282dc82df41244daf9ac417e601599bfd8bdf4f32fc8ff0f4bbf17a35c68c1dcaa596892a9c26e54dbf18c05980c67dd487d7441b5f3f23e43bd34dba7e015afbedc39ac7585fa1398805444a65ae6b14e8e882b899abc5e9314660ed1879adc3767ff7e38b511ec1ebe03a83ab97523daafae1185a3b6862114ad6ec0d8d9c0c414b68c91bcd40bb068e429447ed58ecb22ce0afc0de637c34ed454e9e7caf02456673be78aa820f386e7a92aeb4995268b57b2ec26524a38f4c1b9cc6e89cc8aeb6b8c21ffc865fde9ea58fac31f3eba98616da7d4dfc656b8a9fcc3b0187cd4b63470973719a97ac96239227ab6a7bd9ff4d1b9809d875639141619e1a9e1f527809b3af6a4661306c72ff836f004ddc290cc6311c3f1378e5f029beb1ff8ac7a24f7ca1617ffe36d6efb58df84f7a629506e32929cdef4e52da24a311dc68b38e817f287d3aa5c2b48eda2279619c87947dd3169416cf2a19b677be61d84249e1330f7e5565c61fb201b2b78882c5f916894be61604fc389c9a4dd7089aad466cf75c77d94a3a66ce74e3472da3198698c622ce3e88182ce30041a6c2728a4fe8247222f29b74a8075338804c6ad9c85410e3a1a460e22de7ee42fe4bc7f5f6de4a52b756f89111c538e6a81abaafe5cb7d96c99db5a5618a5ecfc1b84794eecb2ab879def07784f6ce8dc25e05adfa2a5051df167831ea2477d630ec931a1cf3cb286a9557cc9cd3b9a204f10059920ef58f7a48be58e3205d0ad41e06d4387ea176b5ecf770fa5e66c44d091e82fefeb104141e506028cf2698b17c7493482971834b94e84a137442006785c5b5bc97b219ea8f06412addf7fca972e891f1b25574778142c2f616763742e61df600a08a35285f66841c1edfc74c9fd0e19fb61ea2dbe59dfeff0127f40df742aba9278155f6260e83114df06397fca9cf0fac06d19978daa5cb38f09f3aa946727f125b22343f91162980aaee8bae90a6907f8cccca98276482717b5cf05128c8e0516966c135954832b821f78f614633204277e833db60bcd185632544c78f6cd1d71b1c3990628535122a4801a8f100a7412e1fd5a1725ec85921402908da368ca2f4d2e538879e4a6cd3f670afb77e26a3746c43d405dcc3564d22cc7f8ef4f02e41cbc61b6995853c800049a01916599d4b440a1cac0df2804848aafb676af76a4847f033c3dbb2604cb12cd40f78c151f6cab27d221fa59794e6441f1e945c0ca84d142206653f3da50a3b6dc70bb408ddbb43c265b73b68cb062b98c5621bd1a0b8f45b42c25c379f8f2a22fa1c44da9254c7ff1e55841dadd451c2206683ff15258b10e9180a64e4db9fb81a116af398d3aeddd95109908c9742c1dbabb0b9f692d40849adcca7218790ec9c5a380b708a5ba490bda5d1e0ca041c12afd4e607455c1095b7978742619fa3bba10c25b5272dbd9ae43f0872824ae97eaf44a68d21ecc63000fb19cde2e64ae4f5fb5336460553c359be2026b76e3e25620579fea81654419643eebbea2a2bd08f21ff2fb575795f931fcbde138a4e57a81874179a90a54f600a83946710fa745a092f319a7cc4c0f76570ab96e40d6886b3103c60863c9d8e10e8f8f674e65fb0bd41a2da2165cd120b595fa94e5a34174e8a39cade89cf01dedb8029e2bf0abe683c94561c46a8e2cda0096cee283d21456764d0483a1d5a3be4d3e360be005bddb020fde14ad02cab1a748361199c921440e951e7371ed66bbd0f4b1106c2bd9e3d66ff23e59ebf679ec29d6bd4f840dc2fa27e72d9ba8039cad2a4e5eddb1f4c7c44542d5605a56addf84ee65a04cd4015a3757829cba240517033051c3c4e662cd8b9e193c3ec176a8738ed2aa7c87e127826ae25ac69f2aff7a7ca8f5f50d0093ba4645425708e7e32e4ee9a7fd245d06ab58551802ad894a245c327197e619623d73872a79f58adadeebc7b5d5bcf78b617e6579ceeb5fbb75b67386362d15c6a5d721b37128d2050326d42bca078ae89a06b016428282acdec6f75705915715ebcf268fd2ab72e4a576f2c2076d9957768659522d61ab686d01d605045067dce7b7485456596eb7af39ff31fdbba03e000389ed27696e1a3bb2c77a824f8f7768901cbafa23958cf38cea71c87defb93a7d041cf152c5bb97890a72b0529d86bf1f95295a64ad0dcf7b42fab835442fda19c42445ed2a59e32a2d1233cf073ecff305b9ad13908d9cddf352d781a49366f2bf0be2970b2442598ae94783e6fe229e123b9e6e61f26f7b0319a2b2637c53b5bd4483b41420c9ab01e3c1e5171c967bbc6643a9a2a2eacf4ae2123160f979704cb7a1b1e7193ddd2d14780640ce1dce9ff229faa7d2ea07d845b4284165d539990395eb75525a4c5933bb410b0a7c751f0ccf18c132fdafcf5f6a37db9eff12038b6ea88a277b82b932ef6220646115ac8cc703dc08dd92d094d6fa478b162e8fbe67d07dc2a8be8b1073ebc6a2aac32011cf6d5192c402c7378f46bcab46d7708289218b80872bab1014c873f797112b448e775aac7d07c92272ffac9e237461e8eb5b9136bd73ff36d542eca654e9277c3186c90ebb81c1eeaa1b3d67a6086da77ba7ad174ec33899c5e76cd85bb42ccd787f60703ad576f88099e8895c76d81e244a4d69111ea5212d2aa17e8127904f8df8eb12441bebbe2989cc78bb5d16a6aa3a7366b54547ebbd1904c6114f89a4622cf7e845546d4cea91dee0b520664e8114e8e2f688f102d6e4532ef77e08727feae41d945714e43968437238b4318f270686f9debb00cdbbe7cde61841ca604a52b84c8bdc2d34dec367f0114db72f009bd398dd26de2489f7974dc3e1fe5aff269e050c4c326762439f0ab109bfecf53d1b3c3d2889eec3ff547058436248db994ff98f33eb1cbcdd92ad2d103143fac089ed104619ed3ba0bea80b87717dd1cf0057fc582e0d4341648f3c720ab8a1d92eed5a9657de3cf2656b76ff57d06d91558f38424d78ef7887dc6b20ec8f5b22c88e3e442bf643b745320f81930f853df9ba3a74d99555855c1ca182c6bfee7d82d6040f9e7453e7f444dcaf8f9d829b86e9ed09d48b7f87a9b4322373e2bee92c2f3a3282cd6c268dd3bd4d934bc17eec0c61f65f7a04ce21d4a0f90a68d3a603f47534a8beefae20c785b05f39bcc52e3fcf1ee3843bc92ae6e50336ab891f036082a274ea2a3b5ee2c3485df7d18591c00e5859b5cda238bf097309c42c25d758744800f6f02a7b109c56788514f99cbf4ab47db906925ff638a2525bbf5c72a3e861e2e0624e9f7b938c19c9a043e261d194b748c685c57bed28ca995b05524c3111a7bd8ce9ec6aadc36dad9041d3b54fbf4871aa2a6893281d62ab99158483b6e3d178c9c8f8917488f2595a5dcbd6152ae8aeaaacdc627e27e0fd9e0c16fc94cb6e089cf682e242d3c4625e31952995018253e416bcfe4245eb4297f2508a2ab14138a7bc980235c0c6f3fe9a53257d26771911223c362a9ba0db9eb923e9fc6382e971a5d9026c5b38b6ae3f40d7daab97fb5a99ca1feb275d0f594cdfc15b74a4c9a87ad81481d5af101e412aa356740faea982f96574d77141d17d4831c5651e30aaa7ee99addbe319251da8c55c44a941f7fdee151cb73025b6de97462216bfe6b610d272b3f36376a515b207b521d60f2f38fbe5676540e967f70719f326da19768897673a13723e39698717fe34f1d12525799e7d3333ba00f3f35e081fb209271f299ef985047dd4199bf369a929537e042d29daf3ef846e2d5efed50f7f31f61b6265d249b185a49103c2361ddafa0c0055f991d21870da6c9ee93ebcf6661f508eb519c207f4135ae3b7fd84322cdacf742b8ddf3368469eb7655ea61cb67eea9128793ce6ed51a734162665f6c2418a9f923424ef3eae3efdc6d3727515720f75a94a5e8d7f01ad6fd1e37702a0dfd7db5bd79dd9f07f6023989fa2fa82240f2861a1ff1afb5cc85540ede15973b9ffa3544e3ec019fd97962eee446293387d417952a109c5077025e08a1faa40366c926515a07503656eca611e2f7b63d82b3a82eb28a4c143857bf94611010e08da37b8156a1bc586735229c25725836f0652b7576559cf62a24aea7f84a4d65bd1a0942bb0759e69df030fb4ebdf72d58e7a240706512f578c5af38848f79122dee85dbcf20545c565c46d9778446dc15b23bae2f81d21eff886002b5c06ae0188bc8a2ac1e4ae6ec770a9ddac2861259107b16f24a39b9a42ac4c5e9b044535dabd0969dc80a675041bb2182083827054638645281a7b7c2904c63c17c5217c11938d819b26e18a2be85022563070d4964f4a7dbd6debc1d46a8d6a662a914f2f5b9de01502e61dfa59e1fcfdabdf55d472f14f14e2662a5a004209aae45e920f7aa475927f54586145e7b89883090068020a35826268755f7668b9008a34c9ec9d9e5dbce140bc82e36b8e873d837495f004f5bfef69c76bc35b97a9890f44d331dcadcbf4e57213f5366f6e9704c1f0f73d9182919afb801df882be97adf78f085d89208f3dc5e526adab2dac9279ebfeb3eb5c5260a93f2a22f537c828f67c12d190feaba0a8c157a1f105b89e607ea1c03b498cf6c92f97538e0ea1ad8f4d61906f6b924e67520d4c68da4fa8aa81765b56a1e35ea5c1805f7d077b38ebd23f3fad7890f72af959a09f64e6db28fd85f6ed8d95e0497c4108a071999d8566ce052af344ca3d5b252e23fe5bad38f3a4793bf6680ee4c70d1712682a374404cdbc240fc97516967f364a089f525636d8740774f2a3205399de3fe93488940f44f6c135a37a07d4b9db62c663361ba3b4a46a2496ba896a0b4b2fdeab94c56beff142d3aebe638dcd334d23f3b7f8a51594404ec5c38c29632eedbbfe942297edb2c89d8b8727e02472e2003ab89b542c5036165055f8576d4909eea09b8fe0c6a09b8be580a49d8a4e4c806f1e828a37a660e0a46d165d9b2812eae83d92f046e572d7034d38bef5955a1d6ec9d03bb117869801ccab2f54229ce952cfa289c5dc51454876c7c46012cd09ba7267bd7e75422612a035ba2430ab24cfb52c03f3266db072af440186a6edba896496b82e083c615ca8f13e3cf6898685e44db9238248f03c39f0ac93a732e59d5e92824194e357122b8b1e6ba3f4e2a38e5cb8a49a195541ce415efc1284a004506e8b47bcfe2549ffd0491133297d4c768d180be428eda78204559710fcfca2de482e534426033f82541b3269e05024434125fe901c684a2126d0bcb3a4a483865f374c556ad472bf0e0e6adb49f325f1d6dc8ccd428fa97f51caa171bf0d45bd36659304d0422c0e1d3fb4234f23c5f63198add59b93722fb6acc13fa5252e813a98b7546c41c4a260f69ab418436a42383765356e6515eb3d9e7afca5960b44392e07ab2fd112ad5daacf358225243196989d9b1ac0c443f21f8723f0839d33787707fd522c0785900df801d855a98d2d40105f9b3ccf12b327d2937b589d2c387dec7c8d67aa48e15f259f1b064f9e0fca48a0e2a89778e56d37ddf725c4c946e5dbb67771d931231f645aca0d46cfaeee9512b584f720811db193cfe294248f5c0828bf47b40fe272ef56cdb437ea59ff3768e958bd03a2cf90881d962348fa08d67b3e28f5c417efef628a169fb13c500fdd34fabc36fedf44d636f88c8745ce69a2b1acf54403f5c294de9ad1a63dd941b1e2fd68a7c51a8682561f2ca65c70d407a6c7cd596b5a9fa57db1de5803db3723982561b903b86b512ce628c2be29e0b4a7a8a593388ab28a4853d8aaf003650469053555c000c013b42704781444447c88953502708d5035a2cc6163a5bec15f8e5904caba380602694d53074a30e0818c69ac5075bca34289e26141064bf80561c4dc357cac3ab6eb33885609eae658becde2d96ab5780a6bf6466a57540235928e835280782dec1f8f2543f92784ef54ec009ca4e514a24b03799c964184df1230cac048ff969442e0aa77f44e025938a48b66d18d9fd224fa3a06c002bbc1bef1325033ee1a032d4e57fb108720a09680189d4453ed0f19221cc08e864d96065b03bfc38bf04e1b0deddae2e15695f8f4db2f10c6ef61a038addf55d5181d8fda97bd8ca81b178b6a91afdb2135cbe7c33362491728233a05350c2bacfea541005a4c55a71c3ad6b79a56660e53d4dc8e8f39581d5ad6f2919b8308e68c5a1e72a525b50afc818fcc1004a30502ef626d95193cbba12d0e0cbba8215cfc256e3951df9e2918c1d03d42e9911a4627a94563a47ecc33b2f135f09cefa3b1c39b162c344694ead9503c8d5a314637d31b30f9de991ac59974798a5997e5d356217e6127b12c83845e04aace6b8e8331bae661b7121872e44aab692d1ef942300c55777c3ba0ef5806eb1edaa5a6e6d94fd444d0275a2d09035b199d288f23a8b2b3a1602a117cc047787b47a205ecab058fe6d0801ac9d5282a93f3e7b785e14d78d77f2c2add082abb815dc6c4a5e54979d88263f4edb87e29b752106bb675501c3a2653a19918ee6a3d0fef167837dfba853376862e6f46b745b66faf10db849f0ee3dc02f54c3743ed8b337a0933789e390819c9646952828dc07164322ad70a355c786dfb3b55641cdf7b700c28e4d0c561f3bfa3f744a22b765db51474fce12c6f928717206440f04a89045862f3c9f26f390f6f2e925b3e9b6579cb8ecdd763623ba7706d744b0171bcd18436f248c411516c644ac872a585bc310653461841375298265faa5aae40d2f4e6a572578bf1e5888d3fa69dab4e00807d563a6a69be523904ff3f536fcb3cad9ed175e0541b65cadcf29ec478fc76976458cedbf646fbbf4d4a5ddf6ed1fecd61784801741a4b667c8ff7e739afc40b6e22788d0fbb7f6e1ac7eaf94c53c0420da13a462576e5c2901c13dc0586f4911977616212f5bf7a73bddcbba684e1fbc5055d0469368eb590830a9f8334d181a06275aa0300e05acb90ee30f0242908190df7f6596c5b04c44d60ccd99ef238bf4f6fb2b4ed6d7afe1446c6922837a0d3bcda454319904e1567fe2e4baa6e9912c36025da0a752d943e5018d82c2c0a720a224a8447918d5956c6296f27f6f9c954ebc2dd6a0ed20ec6f649f70368a0f61cb59b01f02a4d75952eab65e2e2878abc5912704f790775f3f34a7494c336498efbeb7114bb5b6f0784b75df659abca7b387b97309abb81892e721c0b47606c6637252294b35d50ef902927d56a8a1c910a77a97a3dcd16535411e7f3102fd5b1ad7acc79dfd71678dae69d1f8671dd7d9c6570bef7ad6c79dc5f8c0ac7ceab2d8968d87b4a4eb3a6df3317b15eadf455cb26ede4588756488c714036ef0e11207db5c0f82f496277d13aed9a12008e3eeebc023ca3fb786192182229b75f3be885da94798fa3f9f772fe183b711d5387547442ae6c0d34f813d0adc888992d797c2f09ab44ed8a6cb303c5451256dbdea20bf987564311121b28c6965276796e5d3eb973026fb847f00213611c08dddb887e6b27c9f6c5e162fc65cdcd83a0ec39755f70a2e5128355281444e25254844a5597a1d446499fdcfaddcdff295d347ce082efb7d0a73adbde756ee4bb0cbe399eed3c3aa504888f66fc786e96eec0ebd1b7d3bbb7d037bfee229e4985e1a03a11d1b34bb5e45049e6d9cae0986730f456314ee12b0d0bf3c36424d5977778aa52add53b2cb472a6af92548aa02377e828e159540ec42318b01db136ff89330324d0ebe67410b6c0599e4bf0accf2f5e3b91dd4f4ef1f07deca4c201c70ed752015f8033edf4acb85522e073fb0e43fae4ed95aa8cbe4a726a25f196b3625801a937f0e7bfdbb7d59e8f0c3ff295c4f62fdc9df495ed69bc0467638e4937c9380fbe1a3d5a46b30522fe628677e67c520135f42b0fdac9cbf77ab3b0784a667b8017d05742dc723396b2198e170faf36d535bbfa360068f1390e3e0171519cf7d3692d1cd47d868e3b688ef6bc52467ab151486a4ff9faa08051e2bd683477fdf4d0ee02cbfa788051c1b69a68be03e0296c871e6303c740f800a2138d17e5cbde2df58071b61c6f131df604543a41f8b37bf09cd13ad240ddac0c446613009010c069729839201c81dc7ace2917f91510c9385de3c1e9ce5a6fb671ec204169437f238f0b32b0a15a7c1c3bd7de706c2e1ac8c4a643d96cdc969d3aadc1f1e8bddd825f4539ed101eb2f4a1fcb5e7c8622df7d17aaa65729eb980a0666f8b3ed5c58a7fcd41621401573de1f1b810553017017bad57ebc88b045a5c207250281580fafc6348156677bdee47e42be213d7fece7572f00d94b1cc1bbd9a5582be2a6bdf8dbd983ff859a09f73cded1cc301c63266cf3782100d693beec511d19182497645abd85a804ee5feb2303352cc82277b74625b3d395a19e6786fc16163afe48d1e73db6d978d2ab35a603c7bab041733394aba536c0d0a86a9524e7553ede63e26c38a7cdab6fe30928a74b96e0daad3b635d9d6f4e3b89f086c4ace98d110240984e1de3bf10262b2e0c10eeaa586c7a13f85dfaa22bcfaeac7fb151ddafe28dd150c7ef6e4c8bf37776004ad50f68a5d68b6f7091451c0165197f537c9f8d6a4f2e990bad009b3219c59468831e1904888ba885fc23faa5e0b4be5df7b894ba3610d19b293971facfbeb6d2f942fc3cbb91e7d84127e5a54c334c350fb519c4e3c8d4755c428e7986cf04dcab25570bb20ce3c934a728dbd283ab8ad6dd739013c2d0b1ffc070beeba833d22a01e470bd55cb20cc7ef893cdce22ca60f303a260ff781b83a70750537ada57a1085da2f2dd5a3f059413022e05c65165c2626035cd54db691ed654c40c5e734ebeebda3ca7c889d24edc5341fd16ef86fccc682e43606a5f5367d44ff89bc5de23c7405128e588dbe7bacd6c97435b1b50fa372389f5aecd3a2904190ee4165bfcd74509def0f8e53a7c161f35242a96e4a262af031b78e866b643c88a2664d9b85a23eded4c17c5cd553eb03cb086da0b07406590263e0039092dc087d3045f9e535533d6c0230bdf413f0f100d0a8cb2bb03966c9163831e70168f9e9ebe359241b5d0ce0fdd9eac73f5c482595602e10e4915db45f63bc1d6137e71d74d03e86efc2ff1132419b5bb236339c79c0eb68a739459f4c288f55353709686bc21dfa91f11828c83beb169e5175787fe44d114e64d904dd364273005350feade79b1617b87625af7f60ac71eb03718301e66856659e65560e4ce60c4d981bb023b01ae260ded66e75ad1e4f3f6e59a0e43d57e9bec7407003e7b1d684c29b99cd2dff7629e84b0f993c2a648e18b1029942b3f567d75063d040dac96407c0aaeeff38098ac2fd3f5e66647f40f6b718c837c49d59c610c8eea404c56d652eeb29ef700a31eac782bbdf7ba10f9badbb0bcefc9d8ccce1132ec99aaf29da9b61f2a2cc1d597268b02584020a68574ee4dfb39373027b185dc87d0372acb63999f103f153b93a329b2b2b6074154a828946124cae892e14e0aa9e40ee5d87a50f05dce3034cf5bc0ad926eb5c387383042f116440bee4b782da895365c102b6ec3f71baa89c06f582a2e5350eb06760b951822ffd6cb160884702ba8d2720ba204dd027e1b0760f5cc0066dc6511ee239bb190a790b3ef33bb17b1f1218540c0fdb6169d06d2b992960d772c2c17b87084fc11b65765c3f41d47c84bf53947431a6d6e3a79ca0fb5b951d8c20f05529571d2b888fc9c6f8a35d28f0ec6c985f478879a2363434e5dee47ca075d791a753387df850e6944dd39858127a15c635004aa3645afc056f05f11350f31bb2534276bee9aaca2fb72d4c3f6518a260dc6b4524fba79a826df7758dc4685f0e1d36a8cb7b02b2c5fceaaa41da703879a18a9818064fb799e565d67dd07fc8e1ae55819a1e46b59e987d1a53bff77f4c31ed7fe72488655af39717854941dc4b56f01446b1a53fa180b4385ca79000108bb888b55a50ff7f8e77d11c49f7641baf862d3c4d85bf3f0f1c0cc041f5a8104d9d061337f48c9afb0acb4b224dadf1d7724700c406d071fd98df60a196717fedcd2f2dcde95e0d6873b74c22700ad9b40435e232a22d7022ec58d311f9f82c151055f28167180cc8c38821ddb33c1cfa459af750537ae48db7c9efecb2bde274635cb9881292edba2ce971392f8d9d0ffc20f01fba7f1d2f82a112e318eb2a32f297014e012635d28069e651bd21111c4c66c12696b362fbbbe037c0e3d41a9cfd746a016ded1455b9ac2f805869fc272a7ee4093080b343e143dc34c751af394cd6aa64d43508d1cb5b2725c2aafaee6ed11a7df28a3a099bad448e80ec6768247b2453241b3f98048d44503dc2529b7bc6c6acdf0e0f92d319097c18ecda824f06a2c0cdd8069a48ebfd5e14681cacd5a50d60eced8cba3c475344b8d70788f5685998f58ed1b5eb05298f7cd75f8a5167e8b168c9a7849a12a07fd9689e020d648502a68c64e28a6a96b959978316a106e09a8f192edd08bbff74f8cb0f49c798183343cbe27a6bfbd0ecb065fa53d36897413da0079bd7edc4bdf028e25e7c372b20fdb0d55b16a54e84b5ccfb672cadeebeeda191c481db73f669900c11e43c40ff5bcdc4e4a75e47a39e2b4022b999ce6d338684af995078bf8e97898aeff6023cfd3af3d6392397e5e8b2289f1baefb93ac6203c1369f1d8490ca79f2eafb09911e2b042fc7e371d93b1ca56b7b4df4887a911fc3f2b36e9845bf4773324e6368f8fddcceba7c9e664418642ec1fac797ed62d3872b6c1c55bb6d174fe4f747854fec37f6ec4dfeb6d0121a1f720db3a1b3144749ea28f748cf9e28e12c974f9c3fbfb751309faed0c1847a23ff974a2ae57cf0160cd68f973cb42499fcc9ab7f47524f6a64acfa935c3b79303237c6d804748d4890bd3dffa069e181b8d1dd34b44a8de2f7d17b5b66538ac9c34ef20f9bae2f8709b2f05dcbe8390adca0d015850b6d707ee0a1d0730ae5b1f69b20257283f0c9bea1978ffa317a18af1834552fc670d0a7074f77dffdb9e2563790277df62e04d8fd6dc3189f4b2286ccb91ffc6e153b4022498793a4eb0032b18543c7586c830b940cc50e6c79ec0a0289cb6b5b47da2716f02404025d6520040bce595e428f231c7ff54188afe498b875c9323aed566bd090e0d2738ce010c6d570a7cc411ec4d9cfebbd660613dc814ee633a7b9d3dfbaee1e6573371e2dff550a37935a89a786febdacba34d8263021187d5c47536e9d10a9b292d162b88e5f4d3329b566145cbbbedb4090581fef162179ea405773f4da3dcc4f0f04dbd4d3a6c4af6a428883ae1b2d36559a2237b7b8cb0a25ba9e0de54b74bcd27f8fb4abc8cdeb451026c03b7a9392a987e7b1d001e19643dcb28993d345e077726df4b1a4cfdc0d35a6cbd1a85d316c8981b4e927b694eba2b0b02f8d379985bcf305e66e7e1447dc34d566a1d760d231cb812d55a89a00a6b5b7f97d873687cbea538c081210d4a25a6160195d676f57c9f2d18646bf67d3dca577349a4156710c92039ed653d8b662bc147454fbfe005ec9e7796e1e0b9df9688c5b8713d29a122e20b38659bea54ab51005fca173b2c9893ff3e765f8576b8feb894efa7cae98ebb4ef3b693689a4dfdad176ef9cf9bda1013073a58d9a6a58c87eef9c1af76b202b7dfb4acb41d715563a4453c2680baad2b3ed0de2a966c1439f1b6b94f7075eabf607ee9b27bb400a6324023b7a105715adc0c142a9db2a085da3bea318a544e1a3e48bf6dea35d044ac269086a28f788777fa10a45010e8cb25da38e53ead8e13130ed8d73fe307ce244bfb6cd23bad6981b3dbc22925da5ee5db64d151c428adeaa234a11b2f8e387a620747f381119f0a48b993457125a6c2bfd1490a6c1f6443e9f92848087dca2637f32af6018677a7c15d7302548778941465966dd6653a4d73171046fb8187b621c47f1291e81cbb37d207b536cfe102200211f68ffbca31f4c2e9c0fca07a3a06b6b3302afe7055eabab53043ca47aa6bd5507ac559ded51c7d126bca9fb3a9a329d93424ddb5ec9a897fb81f922319c76a2a2d1b467c271f00f83763b0699079443c8fc0951a4799c35292862459533f65549a4e56fdf0e6c4ac9eac1b8b2b69e980aae7af4e3a39dfb24372f1aa1b0cda15f9dd716bb4a0bc3663b67a25295338e73c267943f2e53631846a92f4a30f9e35059dbd101a6095636317032188a43994344180304e4f2a09d2cd48bc5e9c0c3aeb70ea87221178fb367da1053a953b03d784425e23c7e0a3fed84cd9c95334295b092f91cfd6bbfeb409d554a8b055a86bfcdc5199d4016b8724c8861abd36754a0c88e507bf871cd8d06707222326098eb0b2875e895a5b382a10784898be57ccb53bb8cc0602e2f8981e7800574c1a07ae65c030839cccaeff259f0f6249f3defe312a6fa04e2901d75d5e1ad164465f6ab1856fd34d949bbe08830d17e461d96f512ba5c0a14a4666c460867708c6a3471c6538e217d9e1756442b4c44b53622b144d0a01b32d13e64b2f7834e4b9aeeda17a66fc334c0a5760c6bdb65220208630c2269c8608850d1ee953b91c7ec60e2d946da2d3f5060ef4e25534b877f1206d0082ab4e11f1e36b371e2cfe7200a2aaa311f6d5c8e5c597574d31bedc78412735c33fb6faa539e62faa3d085f6177949cef3074fadac5358716ed1c3f0710f5af177abed93cdffc136a5833c1f50b1bf74d3c53ebd81984ca4a172d2deb4a8378cfd18b2b8f7d13ebbbf4c19ef5b0c44d8b9520ad340924b12bf1563dd811d0828239ad6ba0cf2732c024a583fa5b79944f050ccd9b61c839b9e584d686539674cfe877b396f7746ac389790ea3484efbea64cda6a816bfa3853f3ee1573f0c08fd2848a4bee377129a2a3f296ccc2f408995fca8773e83472d3b61317694c5fb97892df9b6ec38704f08e349322da4350250f6db5cec58d372f3d0d5ea3eeb08778251e2a9f185dce7dd833f1788f14d2408a73f1d517761e2fe167aacc8c8613bb27dc53310e2527e2231ccb4344ac7fef1a41166bb6b895466db8c57d40a873d535dcaa0771d4564aa000d574b377a377bdeb926f5a59619f68215fa0bb6b1dce4072f43d559885677945dcc524f044db944a448d7fae81e29505997cec33edcd7642e65b9ba4162693fc856b83ecebf065f9863f432725e65bfdef58c40c0bd21dc2b88cb765978e5c04d1eda15ae0f96c543972bf15498212ae10a05f02a600eb2319c33cb7807a7015f8ac2e2cebea9641862024b4072a74b633fda39ae150abca13e8d0d9b75ebe70828994ac68a89ef1cc8f0828b67906d2039578a17726f4e5e0e66e842a8901efb4742649df65b1fe648ba09e2eda96323072c3fc662a85e8f2306f4ed13071bd0c6b17c75b7684e4929685c5220bd9b1ec9557f8a11421685200f0195d28bdc72d34f9e2d62dcfe86170f49833ee9fdb7d7461afe14e8462eda91f833c34ed7d5fd651dc5a6e54c80271dcac260193342d8452e031cd831a39cc80fecd804499b8e5221d9100ba2c331e179a21babc77b0b177584584d1d56fdfc2abbeaa97e186b36fe109677cf5faabe3e1269101118a8f31dbcef562c150d6af53608e8ed0db7c9b749170b4c11df94dc002430c0e6594fbd07743615cac42d1769ca51ed6b8a2dfd069c58240abdb106836fc56ff860fecf80139406d9260212e630564013ff73dc34fc77f4660a138f67d5e5d467e8b3a48afb21798283849b244b67ce814217dd3db093ec8c7afde582eac6e7c2d4826bac75659c9bed2369435bce314dbc9356f49633a26d36145cfcb1c96a9e885fc0b90cc5f9b73519fa1bff1afe85da2417c024039dd55a49f2bcc833fe2868a8af31db2a8188297df6e1d52a6b93896ea2e419d2db4c28ae68122c751bab947ffd6c042c0a9f64b897d180b77d4311280ddcceb7beb73f25489222bb29011fa06c2221a5ad944e53519c402ef0bc818ffe434196a37787d645e5a57428e468de33bf72f3a461b7b62d272a73190e741da4f3ca2cf963138e16e4116d24b477c0888bb74cc74bb2ea40b4046a7fc1c10677389f41726d6d755bc5fa9405dd438ce6909f14c3d8da7a7db14e09633b3804b422080f901e2560e43ddb6d70031f0e1f0e8261ccbd2d23ebf4bba10148e46a62ea26af66acc100788769586b016375fd27795234b4aba2e70aff8917c10f91546feb5c6741479dc49a6d5385945e5801f9f4ecdaf67f811b26eb4cc1c1a1fd04d958f4730ed0d1deaa05acaafaf6021d1b5b18db2bddcf0ecdb682f9b49e50c5938b08a89f2c954cf1ea3b2ce7a442e53308eb0c0d3b1a2a82fa24e4541bf8f9c45684f3d4fde638b214b69c3c840fd465189e2ad2ca1138eb78e2146225efc1d8b8c07b4b0021f82d70a2e09147301d66821089749417785e10575e780d04329680c4c5978ececec8a3e500ee47d89727fc27dc35f81d3edcad67954105640b86aea0310d18cd878efe0b3d5ad933a3b050e3519e40b482f06d6f07e9ca968a6049985c061e81c54bc9fbd6c08f7b7627a4eda6e6d03091b61c119420fbd99e0ec415bf223f4580073ad76413ede89f27d9054446c560fea1de4a4b924afbdf384df32270d0dedde8c5e7fc03666ccf5777a4937b1ed2072f51f39ae9384509b71f73f4a454551af5310b9d6c29a271ec25bf3a07ca374b0aca5ec9e89cdea154849b4cae77fe1687efd24ec8fbe5a9b2545ed74baf0b9b203fde32df4dbb65703acd297998b67a4dea9f2de1aeec6151dbbb80845441365803a14a008e9ec59ea75f10b4f9dba6fdc924c61b4e2be57872cd17e1336ba90461100ca1cdad0d429248a81af7c5d484110078a27bfa5148229cfd560e72435ffabab9aada1591e0fc59e9944870c5c9d34ab7fb292ae4d2a2eb72462bc140c1b96221f4d5494846451f07410573d1bad355f11a42a36a379c3ce17a28c720d13d8275f63ae438295fdcdcbdc863a879158b25f49418f2cbae986d8decaf8c6046cdba51a3c7527a3471ddd8065857b822d50df545537abaebc58296f554e4d180b6dc3bdf7327586ec580f65b6abace08f5a14308abd461d20dc6cd636a28d68e063d669c1fdca0d1ddd2cbbb4e2bec0feb405119de424b911e7e1abe12f5e0181a00479f16d8deb8c1cb0e419a1b428641f169c5840d477c97b40187538d132412a888ada2cdd8b0e12ca8961d0e946551afb0c61ff31b2ade835b083559d79762e30632769a3946077321bff867bdf7464ec72cd14dec2a0231876e686e1103eef2c01e2dde2e6a04f2815b2ea43bd6b558def3fd91fb1e11829b67dc371b72a32c0269b4343cc4c637ff6f6ac4da4ab68ad6a16fee515530631f0c682b669272e3227a5557b36c0ff5fe646c06e77235f1aff5d7d16ddc3c2203941c34164dbbdec0b49d19cdeb57ae8687b06599b2e722469b30b29d90f25f218b767a7b0887d146c65e57f24ec38ecd1acbf806e9d6e1d386e603ed37255c960a783dc745865e776d0c331aa551575d8e36a25b11e9923afc72b41194eaefcd4f7d75dea3d99edb82d37e13f6bfa8fcc9d272bed36ca89f68113a3b5864d39db8c00e5e50891e98ea40b2251e9cb688802b13ccdf32eeed201eb030d731ef9610c85c42e334f09bf54adb10fda05d6211f05755d3350ee2c334660963d294d3d947a8a623b6f64d07d4ec313141a170f527df04235405c6dc8243b555627e5f8877a2c4666c2d7374b9b2c3fc6619e6a9248ddf71c959a42135091796b29802d00587a83d5c35325973c16773cd53f3a0b45f1a5dfc95aaaada7068100c826aba8630755274355ee45ac31150b44cdfe036975eaa9458bee4722c01076215bce1ab3b54f98a8f4490c65d2f815bd33997e9c158a23c942a6623fe8c3fc1e27796c0eac5afde7fe990d392b306af98635e44c431fb689f417c0d40062bdc7b3e3bf25498105da50231b8c80b64e0c63173667625c44c0c2e02e717079258630de0e9f6a82e631ff6bec98eda69532bf09b170b52943554eb14fee6865daa75226d1a84a0987525ab09b5490db6e59b08f0c17c4528f55d35cfb4fb01abb9c45c57266972a907eca09e1e9a542b0829b6610ffbb6120ca83ff4b2aef68e6d547007570aac31396bdc00568113ac1b263623b9a8361122f9bc5f060047d5f99c30e2ed6df63d69dc0d748ec260ccf26acb74282528d12680b6c6690cd21f7f0b787e69c210258b0443eb850aad11cc29d4145856fb261dea94b3a394ccecb5cf46a26a8bff883ed0c37089aa557e7c4729f93ec182dc3ed54764f23f144313015c9861488fc0538445f66e345e4c09d9c8df8827400bb1746fb6325e2603a71df5259f07da82660afdebb3094f433b44a8c9d116a5b907f57643b8f4f654a32260307676e6f6047e178715943828ccf556fb8d273970e03cfb72e0f0366acc96ccb79af81b9fefcae8cc9ba67f9814078c31ec01fbdd270d2b2e7f0ee6530fe44bfbdde341fe89ffed5ae6c6db25e923f8087bcf282712e26363b1ba0b7f10b2bc772b152b379cc26d6a9388644126815c977fe4ff7067c39e70a92954eb5e46206f670b6267a39f811d20f54322037b1ac5495d04a2f361f8499bd7a09f893c9f694051440087ae64d38aa948e72b34e067d3af101e53b271c56a748d670d37b49d824b1c5dbcb2e701781448030826c1a045010e3996dd956bd19cdda501418d3ecf6f3d2137a26b8caef1d68043e7a8b7cec7866e2572a6014f89d3bb964f92805c62acdc66712466fb738e868f57cfd12408b777de3e1bdb57ae45efd6809f4d47b2f7cec7866e25722d149efac5ee0a129a758e0e237a697ce5b4a0b1e92b59d9b2e02adf24adacd22fb4e2b6c7d98b819bb4a89f237f82fe22fa131a8a2a6eb7da0be1b64c3bba5d2a111ae5e3216aa5f0676a4a458b4049dd6f0252c5567f79aed3118ca14407bb24c59f9d9035288efff570b35b48fdee074b334d2bb1e6cf74c42a7e407c340e4a84fd84d028142deb20bed0a558fb122abe8c4c41912407a8db2209ea1f385ed0055b818e02f8c68c72aa9ea2a424a14bf51b21acb373f6dd67255550a845077a8f5a8b174273e077f3ac43eba2c39d23ea3082f34d96f7d7e6701e1c1423f4894b12900f4ee57813ce3a30cbcd84bda3a0a8bd00bd0a4046659d8645de69ce33e7b3721a818ff491cd8b34ba0b1a99b43445447da7c092a37866ae75ec41166da19bb05d7312b6b72b02ce0ff935bdcca34656300615ad1c7580e3c987c0a5f052cb7a278bfe174622aafa236e3b8dd50c4ccfd8199247e19ba6558ae8dcab1b2fda41d6c95f8d27ffbee93a2381228b56855ee497bc50a6f19cecce8275d5582a0ef18857de1c3aa7d1d7568c900a6c805412905a2101e2c3e039e34383e62d0939e9208980b6847408278560a54c98943633688b94743f0d391a2b3db723f29a5464bb6edc4f33cc6fe2db240dc7ebff91ff75a7b11d88ff947164b84ed1806d27fb909ac2c2110d18d370f3dac1d12dfc1b21e26657d98e832d3bd6f82481c43c898636c680c0af6c98728d73e521d4d76ca72834e2f2d97cf209f13596e92736cd3b9bbe7edec0b844fb0237cd9d2346d986ec402081cc171e3aac678d16cee43b512a2963ec732a4c55769c3516c034f91b262f57b4ff11b21d9f042c39fa262c730074e879ed83cc3fe7380cdfeed3b730f4d9efc1cdb47f585b84065c9626726529276afd0e8be5810382e0a8d23ec8232e1c8f8a9c1283381d803aea5f850533530e2994fc3d69173a55e59bdf16c2218a8f1199f8b9c94d3e8e5992a04c4161ffaa80783ffd8e47a700a65586530d445864558e25f81c34eb303d25d21ca99aee91cbae21937bbbed72117ef8b9a612c6458fcc0603c28aa9da51a15eae11a158eca4b8ccef52208c4c2710caf54a9d64b3285299001376dd668f811766a6d669ed13a5c4f37c7e403a7684be8e8d0394df045c4e0f2c1be501911102b4180e097ec19c372dd2473b2b373cb52589fc6b5c1aeddd55c49413315333e493623840c90470984ec31ce9ce800c85c2f2c13d5588510360daad7c394876f11cafa245b51f76f998b7c92c91d1c1fe4e8567ce45efcf777cf294b82a5d841a9c53cc42e365d896c088c9ca56c0a681aa5c934fb2d48801847605a7d11d450545d29af49eed4bea9531ced2b1c9c4895d3229b3199f3321517bf2899eb4efdb12a61aacf8a27e1ff4341bca2fed094071fec450a2b526d27ea8ee3a291ab425024bb64019a3d19c4c90fd0a8598c7a977461d7a05b5ba508e1c9a18f6bf3a8aeb6e800238a0d3133d88855bed8763d9e035f34a0e6cf4fd7b80cc2b28c2a1aca7a31ea73f84c8e98350bff8487e52762d7313f510caf2f24481c1d9e2d2ce3232432c27b151b417a5b5221ae53b5cae4a1ccaac7c67aa34af97c495537368ebfb52d24427018701eaebaea355818d1f6506353d45689ba4a22d42d6371a739792b000e45a47f62837c2c848763131728673ca6db8b492573174ed3fa159c4b469acc203548d115a7886297362b6446c88207fda653430394cfdd31b3519ee5685c7d54bf7b392448f623a8babe3878bbea00100f463cc152d27284777a5adaf94d0813470af7f2963645f289742ad20ccc925f16e504e76ce61582546457f9115ab4e837d4ead8332ce6b199cb2f06e0ed17f2e910662266ae957716f795786056cfaee284f65250dee81b192f4e6e0642c9c91475bcd1871725bd4d136c92d191a38c9c811007c1372f770055da7c57179e488add301518f806f8c944e5f4df539fa345265ec29c29d52458066044d5add20003d88c8b3a9305c7c9460ccf6dc423c76bb9c588b1a269ba636894f5c565da2bcd50d88b218fa49c47cc2737746ac3326d2a95595ca3b7b08407b48bafd83f107519d06ea6dd472e5f591219abfaeceb23a4177c656cd1e21140cafb59b3cca9bba5435ba3a9f8241fb48cc9300f1b822909d41ba2c18f9e7a69e923ecdeae1789e49519f25b86499649243db84b888b1af2febc5e59a0eecc99a15009f7b74e05ea11567d3b9592be80534292e4ac1e0a928520f3cb2d77c9642b93b9467fb83a6156211adc7794a13cda3139f01299aca735a80d2154175c542d610ae96cabede82a159c151b1bfec0b044851241dd311389860fe338f1a82a948e49926f300699a259322bc02c40ffde72e1dd3763e6605041c0364fb36f60b004f1c98779a999bc07fe666b2d204f05711624f3d3d3741cda437e9b052265b71b3a48653cc3f53fa45319add308c0e00fd1a25a77526ecf2ca561be2314f72bdc7319759350ef7a066bce665660626a15c94ca202870ce8db66cddec8d30aed6319b08393eb7ccd76cc0ebc12f6d2c973b28407e5dd198840a14dfe414d20a8e78bd13188ea99e0d6c27872bcb58145d035150e33fdb287e686bebd7d46a47906141c4650b0f09c559c2b6f1815e0729cfdd3c583f9944fa3c98fc015f4b0073978fb92d5b06cc602a430249864ac2ed047b883ca0c47b4203972dd27cca9c89e237cbb07703a21bd64193384a398ba9d51e1b9b667c9b92448d45a68f986ace783ef6e8f1b7af34ed64b96ef55a4dacf21a257e5e4e8a8a8274e185a4321481fc7e1552ef25fca2be31de2ba80d989786cb13e418750017687ff963940474d6fdf5414eab240e50f11cbd1163fc67ab0d0384e90f9a1f87a5362e7fb4678b90a8101238628d07b54645149d6d362725294d835203f303cc8b3ffbca959b84fa49bcf2ab47377701902fa72bd0b50aecdf19209ae6b5e2f01d1846627a7fdcf15f044396797d06de1c2b5707e28e902972c0edf1179b589b8f74b47806a4d36df6af257fae79e77c42691126731a1df86ca112ab041607740163810b09032dec6ec1eeda687b2f45aac27d8ca5261010ac608861a957483e0aae52cb308b1b885ad183dd820b22c276f1171bdf95b971465932fb6712b9717e291b6092c159d018a0c47eebeedabc9280a68538a4cab5fa69c77bd38f2d7d113181959c52421cd53c447d59c15ddca3c00dd352cdebe190c4e687be9c920715e0246f848781a1b95bcc34dea884aca8cd753cd0471b22391cbe8b510b0601ef4906801e4b8d73ec2003ca4fee775a20d0ba4a07d56730c0295a541a78d2dffaf992f0f858021a96c9ccf1b1d563edefb7bfae26568582da180a85e400db8c030a14152c81ecc2f97eb2fd8bb21ad0ceb896c83216d2e656d6383f0c37fb9290bdf7de524a2965923258070f08150740fa860afa86d10c7278539453474bdb1f47913f70ba31f2570c3d5e06bc751ee8fd6fa2dc1cf90b85f79c6378051556f888807c37462a7c442ca1fd2abc0a1f51d077b33fd6108701b17ec8dde37b498594269874810e48b026309f0f6f8a7a1e059dc2eb68023c9076cfebd19382c6048871767103690be36807a4b1b81061fb75f40c78f7a8b2b7efa1ef1807fd734cd3d10378204d07d0e9e8131e484f588e4d9d9ba2d84d514c5f14348ef5d0729fc0fa5b46e4e17f53147adb6f8aa68c3db46fce566a67eaf6d071ef9f3b64b2adeceffa68568fdf3dbe1888c01ee889fcf8fd40ff73b43f2269e43d8d1173fc1fcc87d2a829e5fdf0dde37b27ee890c801e3d400823af78bec7bd31228f4ecd87fffa7025800ff35ef9f810efd547a92357ef3df9ab84f7f7b6f88b84f7f7983c59e4e931c2989c0f573b3ecc5b25c2475785f0d17fe64dd01ffc859a3a9b08ec55f8e8454fe8e755f8887e3e7a3e54f20fb94b78a0b87974de84dff9509aa049d071f77813f4009ec8f68e965ba7be6c9a3a3603b2554ff861d7afe161d77f7de14acaae2f802fcc36875ddfc75782ae24e8eac5c1fa3d746d8a39f55d3a3ac8e30babd3ae954cd1d4a960bc8a3ca172893cea085f88778ddaf573be702566d7dfd1c5ae2f42fd10aab4be1027dd0ec717ca8de3a7dedfe3716e1dff2fbd166e5ec7177fe4f8894323d1f172f74c10e741d052d664e7d038efa359f581dee77f34ab7e31a420851360c0887c9e49ec82c4171896f9fb7f7e264b0e6f1e27e4f1b4fdb3931cde14dd14f92b00dfcd43b931fa74dc5ab3e6e3f8e8fddc14bd66cdc77bfe8d66cd2f4fc9484749e41b1cdf0d0836c8f6c39b2222b0df3f3d223f1ee8a727f4f3fb237227b080fdfcf4847c1ee8238a617628e202f3f99e7943c76da39b6c960eef0eb67f8d0edf47ffe88903980d1dda1a563af4c8d8fe00d0a127dbfe1f5ca8f0860fa127e668fbcfd0a1ad614687954bbe50a1370b6f86a84e3bfcc0a972d9e1073745e10eed426d0f6f8aa41744fe94591cf41ba9a4dae1cd4dd176b9e4a0bfd0c4010ca602ecf7fffce8088bde0b03a0811549b01f1fd0fff879a0efc7cfcfff7c373e3ac2b65601f6c5f6ef2fce567883b4fda688476e92828fd00317716cac6431d1f30fe3c8418eafcb649b1f7274c9a2595942dc7befd14eb384baf7dea3de4c74103f8bc86411710fa96c470f083f27830719818b9de3afd203c263d7c79a0564845d7f845d916c2dd4d74219bcbef6f591dc67fd88331ca26650b4cca068d9568fb0ab1e1a21bb175ca0ba1471d9324553d2145550b139d58d309c12352a68421be130c2a1435e01084664a6003c71f3458d142024d5fca039a0ade0e84096924319e35270c3839a296aace450c66a9870228732a67918228732e6c12000b21a261a9df7835340e3a0fcb28379ffac62395c6551e1a43e0539fc1d0eca0f44814b4c0e5d5c113838c011c1a1e0a0fc769cc8e18e8f8352c6c24f1016238791498f206fe186c83be450c66a64399431ef4bd6b49083425e90c3d8b4805ac4881c462707e032f543182efd7b63f493454dc45beb17c2b0daf439237abfcb3038288fa82087f149866f88c8411c441f26c0b3e52ec17037344c707fe1be38049d2b3cdda5bb1bc1b9aeb2c8c56da53ee79cd6ab53970e8626d3d0903e271929e5087c62f71070bf315ead7cce29e58e313a148e46ed318756393dcf618294d2e952d2a0c9be9f5e22cb3293d259eb153a9bf83011a51336f5df2014d8f6ab0eb55d91d8874d1d6130987d6a6ba530f905a5955a5bb5d44042837b985768937dedcf79ef4dcafea22fe586e264cca1f4e38c545280ab818426040cd0ef361005c1c5a87d19bf48132c25118104c4919445f2e70d51c7a76c16459efaf2f3a50d88ed9a932f5a2ce630c51cff38c60461247981a4c5d117a3c9a5885a8f79d11737d2c28fc2f0243cc64d20ab1f66a2414313b34ac898536598fa3182af13a8f65add6ba9fdb8cdb0e9cbabc596fd1376f0bbded686a5b77e72dbf66dc86d1975c24d1c3d904d31dacc74f583d098f6d2d8f46942fab180d06cfb34db7631c7df77f4d78cfbeb7684c2518aa30c572328eb279d7c4bba770eee5896ef0fb65ad60bf2920c77026ee5af991a48b6bfa4339b4a60bb64229b4c9732ea2f3a299d744e9f5346ea2f4e16799ea8175eec38c39f6462b8bb47d083b86fffac945b20a941e3d2734069ddf16df6970ce23f9af89e76732abbb928bdee5c29b5bb4995b28b2c6adbff8db7c7dbe38dbb553b92273938bd4a1726c741da4f5ba3715652ca3d7d2a5ff829fd4ebef00fc5d4fbb938c9d0c6ba40f06f1febdebff2c3f57328de9a56bab7dd53a52c4b4a44b81fcd169d44441e7c97f6f6d7afbc5b15b2f86e784a2cebb828ad7aeed3fbf43efd41b6752b0f486bf73838a3a4f8bbe8fd580bc4359d64a800f42fab7eb802e7df1e07e7db38883f1fecfdf04d3fc95f48ec570de3d730c658f32287e2460e26e5d091bc8abfc28ae454220ffd591f2751ed3abd0250baaba6f40669168438e845a96ecace692a6ce251a283d4c75f3b1ca41f047e8d986c3f646df6636d5f1070e3a76f3f8c4cda074e1b35c8feae4404171f1196fb6d9f7a22ee553fac21f5f3bf503f7facfb1196ff05faacfb5999f1113623911cb4331acf96ada122cb2459e541c822fb0f89b027f5e91f993af2ed0f4d1d7ffbdc9194b5bfd9e7b4d7d4753ac2906a589087609060b2bf7cda3195972a5962b12f4568359051a54a1553a28e88f0242b0e0e687d7a9271f5d473647ec673a544119f39849834c7183ad80b185aa154ab63087b755809a3972d2b2770c7355bb7bb16c4adfbad44d8ecca09e7c8225e1bdd622d4c0ee3936c764c458cc81c351a50f840e609281a06fc3583dd487470d15ffe313a18e260e0c1a9f3120a0a6ac805656428cf1d27a81d27398c503b3638dd0aca678e134c5bb1ad1fe592c308b5d3b4736cc9df5941714f5cc429e1412331673e9627d0af0142b8c072074d384a06ba7ab0fed9f22179c8e7a48e2a39944550514d63c870794beecc204fa0d7c68982ec83240f10270a287f8571cc9efeca1eb5125344c9d479700cd63b240fd095718ea61ccaa230568cbf28a64d36fd524c7011875bf5d44499a4814cee641356e09e1fce7030c716d92ef5ccffa14c88018334860f5b94b8b2031fb25ca184c35089b5208a16f71a05dd0e48312c54d215f72caec5b7cca02cb6af693a68079c2d293d0c1dd05b524c94d92e2c983d5d4f4684303131050531313105313131e15c617464a1ac18374671b41845998d3c12aa090b557338c96164b248b12afe0aafd1926c33ede93756647474ddf3172b29afb557bcb832a50c2ec8e04204b50534903233cdaab5e34c690c1519ec30ff9c33c618e9a454ce38e76a85f1b437703430d0e0ea73d63a67d2956a639501455283a6fa9c1a6e22a9dacd0b426b144fad3ee7acd46da4c8baadadf4082d43a0a04ab64a3424c85c0966d8c0c30734f8800886c801cb1035cc38ca790c1a50e4ad06337cc833bee0004b152a80a246174ce880e5881c6051024112150a2956d8808b1557886145d38c125b5811441065b8dcc780a95145d6769c51e952459e3bcea8343591eb8e332a5348917dc7199528c0a0a24437a332858a110d737271426bd0f7de7ba30ebc2043839325ac7892d5a6307ed8a008432985293b7680d8714bb7e36c662485e9e79cc1e28b1438f8e204155f528077a22c6e997d5172d52f1bd8a91d675f7ca0b1195f84a161860eb2108363c71909a0d8a08abd4734903a60bb16bc8c29c24b0e88e80109d875242152ab19165b36de718685162f1ab621cfec38ebe2c5125f6a9091f38eb32e5114d165099a159207e6938b06874113345c4c91c5035668ae646fc7d91421c0618a22251d8091533bcea41003b280256926450d5c331fbcccae2c5126562f11ecbd345f1c418307447c0025db1d67450821dd034104b17a1c7056c406f6dd7156c4931dbe6b0a41b5a0549461730463ab33d0688e57685d361a1f66b315dc7c675380d9da8eb39916ec2504e794fff2a3275d5a26180dac64bd54de9757fbe4cfb668c19eb1e36c0b1993cb5d5a9a957462022eb04cd1728321bcd42a88c86293b0a1daa670e181c6a4e5d9ec86396546258b2b67c7191737ecbce38c8b2b365ec9644e3d681a889af1a0341bc10b8cb090b2450ec28012c368ea4c6fc20b17495ec3126520c15cc7261bc05c071c288112cc75944115586ce2a18c0ce61adc01c6512745642089060fb8400673ddb20116653928e104734d0306c6ddcef58a07d8d444520b324a14c198d0a5a89101824b12cc35eb0a18139712065cc491524e298fc2e0f95197184b59dd9d20529f7efd228dea220a2ee280619409a153168bc59cc0bcecf92cf86bee392b42cc9e0f83bf629eb322c8ec30427550b32c537618c9f86b52b127951da200c33ac6965bb9ff53e77ed7e688a8c904c7224224bf5082d5a72f83dc2fb0e48f0005231a010ab6230eaea1927fee4805164e88c8123d8994c3d5f6d60e5e36b8e36c872b7b87293bce768092b3e34cca15db5f471dd7d2d1105088c0881644c1fca517e4c62e366725c7991417380bea8c8e30ae6a224d160412302634669e04158331412188255200ab4f3551fc02c6243e01ab1f166e46e941128c898b0627bea03b3cb10463e28ac284122cba00c2aeea15910441164e3026948b1671ca0657684982513dc1804d2db7cb28a534a45acc89b24ccc899f0e4fb6c401c9284aa378db718a315c9c2776b1a74b200c481d647e5322c1a16966849759099ad84f78400931000b4082603eeff311fdf09950386004f3f9160a10640515f6fffccf4704f4fb6309fdfcfef91da9d8428ace7109720b3a9331802e80fe11e4a33ca5668bfcfbe668ba8ac82ce89d20bae7034074d06cf9afa08554f12287f968eadcdc105bfe3a208120e9868ad2f6205dc4c8189806d23870f0432bd13256254379f9413d99f66d342b88cdcfb7f9b8a707c4b7cd5bcdfa9e3e0b88a5af03f0fffff36fbeea24f2e67b7c4ed08b6cf5cdb31037f8d1fb40901e8ed6571d1a098e8f9be351ebd61776438772df784e7a2e4c015565dfbc0ecef5d1fb21a1c7a743b9bf2118b64df8ad2fd46c794c3fde161dcfe9d03a3ece764a0eda5c71506e1bba43709130e34d98e1d92475343efcc069c88565a52d9905447e8f97df647b5025bccb5b396e4beef1e14d519633e5c9628effcc4fefc673ab2272983abaa234b797d9253c473bef2988dc257c1e948362805639dcc86eb6f84bc7fbf3288a3c216cff9b2b91a7c7fbdf60893c25441ed7f930efd4ce8778a76c7c0836de65e349b0f1267c21de9c8de73e4a1dd5d36cf98fd426810416090fe483fccf03bdcfbb5c3f3f71eff7f91e07d22c123e2b401ff42bbcea6947f5b4755441b40a0fa483fc0a1ae87be81b25e81b5462cefbc7586305adc207d1378eb4b7837c376201485c13ea5b076ca26ca26ca26ca26ca26ca26ca26ca26ca26ca26ca26ca2ec1539bd9a2f68cd17957a40f567ad355b1aededaca7694c5c09777f2fb86860cab6b123170dc436dd623bea568fed6f23b6fc71a61fbd55cd530e72d05712a421536da57ef4eab78486faf6892e9125f7cb1f96f9114675933d350b774322ac7e58480469f62cf32118f7b5f75e6b05639bb899f80fcb2262467a76727c216373e6a8410e650c6a9389c58694ec4c9d9dd8922f6bdac1b6066520f6db996206a63b51399431277f8538ccd38338d20d06dab431e9fc6ee3987f4bf9411e676fae60a5f4e4aa656665346185073ce06207d58b1639a8b5d65aed4f4cf34a4e6cfa518904ab954480ac04318879c1841307ba642186dbb1e547a52216072ab595d24a6d0d7270f6f89c20d75a638ebb17c4e280b4eb3783effa5ebf18aa940fce197cd7f002d4a79c29fb49e6aee1a435061c9702bdd50ae3ff9b7777ef1e74e5158e8f2f37e7dc7634ecee776746197d4e4a69a574ce49a7fbea6ba5945297ee5fe82bfb34523ae7b51edd5529119e585acad65a6badb553d6903eaade95524a7d66ce39e79c732e654a29a594d29d2b96da2aad903ac31886d2ea4e69a49f9cf3a35422f11fa504672bfed571b6e20ea515ef5029addce675aa942a7502af3b81578a04b7799dbd5e77ed8ea6699af6d16b91881dcd093eadb5fe578ac4e5b69b638e953f786853fad18b04addce6755e57e966adfd68a54854ec3492a4e4de6ed453a5663e36cd644c842a450487b724b88e4e4f9552a5ee7778c7b3bf712f7f4b6dcf6dcfd9e7acfdf247b53be5224dc153f32698fa548a4a227212a92ef2c89752aa542aa09924549256db7932552a672a89e8e60c8e269127be9bd768b2b5765efe18b32e325bde34e43f4e919062d2e9a4dd1b79ba5aeca867ce4e736c656767dbb6cf6e6fb78f3a68efb5b8ded8d19c298f3af5d9c9ee2d102a672757fb7a1a634edf2f5e6a2b520c2956198646175a412e7e54a5bc8ee3aadc6989b053ef4a6923b325dfeb34c7596b6db5f8716c2ef539af946ff1b472b313c4e0066210dc408c6373e9ac9adff0a269cba28749198408a4a4526e404e499d367562533a690b5c190859e704c40e9bfe0bacdd3285f8c40e71765881412eda7416e569d35912149bce80c0a17381471183d7a656746865911f079cfd70040e9692437c82cf2ced6a3671cba578d3be2e180ba85995327296d80d357e8c30e2010045b31218f1930569754529d3ac8458f252802404161a5142f4a0450828335090bb1d6742c460e0c39420c6cc82f82106008a3c7794ee4fa47e4bb0e05f525f7b7f22737aac21f5b517aaaf3dfe0cd3340b7f4222ac8605323bdd97a494524a2929a5320b230ec058064abb56b96125b989fb95d1d4267d6a634e7dd76cd5971a48cca9cfd5d734aef5ddce6fc585c947fc551f865cdf7e334a6462944b47124a3ecd392b76bd9a2d8c37acb9660b1b8939f85d58fbc21436f662632c53ddd28c117e691479e2c65347f5aba68d31d65e7bed356ee33e591473f090bc21e6e0576923b3853fa595cc167e4fe3c7ef3a68b6f05bad0817034c71888ffc85795461dab2f1e3f9f8e5149f200ddbafdec6bfe21179eee3c7536706ea8ac155dd751c273fc238effd89a45e7e4be4a7debf255884b68fb0d42fd19e88bfb6691f6b2ee9de3fd6942f243f222cf31392af7d44dacb27dadebf092cc2aa0fbde3607d4fc376cca9b3a68a89690ca98fe107bf90d46bd67c6fde6af5136b883ff7449c7bf94bbaf72722e5d7345d5bbdd6ea3ac2e46ab6aa924f0607abfc1aa35e5db0c9ea165cc98b377ead67b6667c0a6315f356eede2b5593dedadd7be5e6f7effdab618de28edb54b74ac78200e10a4ce1caeac1a943dfda27400a740e51fdf62f74cf7da725d28f9e209f261f117d15fe0d7f422ad6557dacfb09e19ac038aafafc58b427aaafca4f443f7f2cfc5999f908cb7b26ab84789d44ea7258814c42feea22e89f7f67eaf404b120c45f3882fe11f40f87b6c49b7ea4dd0d70e8c71146c038e755186521c85728c1f93d1f0462cefc283904f7fcac5cff6c1cc478d58a3cbe6928d634cfd4a71531aea64e06679451cea4c2a19d6468cbcf748afdf9218dd559edfb31fefd86628efd957d1b03c1becc9b64428a3cd1896d677e15263b591b25cf9f60993c7fbe9431098298637f460fc9222b5464b6ec3d325b57e4d09524bbd202a52e599c96bcc82a4245ee173475543aa9b7efda71e1005c4ab3eefd88b020ddbb829ae910e54a16299b4927bb655b251258a40e2c615fc3b70351b67d18ecfde836ec8f08cbad7f3fa2ede9739b0ddb8b3657bbabf1e66c7735b6617397569cc2777358dfe7a4c71ae2bdea5ff05ef52dc1a2fd92faaa7fa1fb25f4537f75ddaa17aaaf7aed13a29f4ae24284e5e809c98fb5dd5822d9d7744d537e9b999ffb17667e7bacef965aa44c4b247b778c22e6d85fd55491df06142387f1c913aa9f1f2fa1bf3da79760c19f105db2bd90eab7bfbf05d391a217558a433f72281e4556e1fad1c2c8a1c73ce64f701c69064b20bd7df9b149337235ed6af8f6f8cc704b29873b56b69fdf0e07e7f6ad5620ce2ad374e1c2704c1c93bfb8267f859c1337e3bcecb063903b0f91434ec6c9b82d930b3365e0ee3f32e6f86c620738716cc99749946cbf9d15b4525a6912a2ed7e9dc8a169c85f4b4b32262d5b8664701d39c55bf3c98420d491831e16e090bfbc8946014209e78d441e07778e50e8015d3e82848ccc9cba38f21752d2942a461a105ff28608ce07bf10dc1fcba134028da218893c4e2550dc3656ba8f8016255f562a6b95954a772bd6dda70f5a195a29ad146b390a3290a8d4564a2bb5b5565bad0f73ce4a71b0716a2bb596da4ae9779d8e2e74b095da5a6da596fedc3c40c3644fefc7525db7d517d8b54e4701b5955a4b6da5b28923891a61a1825a5d413daba54c8f9094937a6e97eed25d1eb7874d248d33253f2bf7ce6d94c50e7087bfa2533d522b0c43458c3840c913a348a6a8621ac48297e7bc7b7f55eae375e78c0efec8982ef73d77ebeee5b8efb9dbbdf78ba1e37ebecfdd6ee7fdf6be2473771ff7f5f834d95788833e98052c99c9bf1579ec10dab215734220b2652b82fe39e101b604638eb712b0254e04bdc8961f415fc02c2257abef49bd4cedf057ec9038dfc0c892929496ae640163c720b72be6bc0872289190aac828ae14638a2bc558f750a97532486d9bc1a7e64d604e4a29fdb046818d956cff0976fe8a49e0a9033a8dad452de4bda347eb01289d5a1e9a9696644c5ab6c4fbb966abeb22875249290bcef5a6f99484d20e7027f2f893127f853b44fef22343334a28f2c8561c9d50d8b21379b4889f53fd912fdc91527e2eadc9d6461c9c3e1c9c4516e094635a00767d1d79e02c604fed65c05bc79cfaaefbdb0cb5cb112a60dfed2bf7f14b32b7f6bddebe9001fbfe3ce2aada93cbc1a1cfc71107270c525c4f34e6f2e1f2e1f2e1f2e1ea7ebe0f9c6e27f278a7f906452db596daa2683fd0ba9d63b2fddfd6a974a3a8d56bd36c6437ad6f3a2bad7bd334e2d845b03eaef6abb5d93446829fbed4be7a40f053ac6f945847ea7e4220e17c93117f852e071c11526401434445513226a1d4393fce383f6c99b0a38e6beaa83324da6d3f960d39045dbf7a8a9445471e1ae4638e7bf744b603ecf157b75d3d3e41ae1d14842c207a89616ca549526966a1df451760c07899edd0357397cb5dee7297bbdce5e33a32786bbeabdbf41b4a59c9a144429255706eb7652a88d4566a2db595baffe32023d3106c40c927cc50930c4a8c1c9150e4917c228d6ca54592842218acb167827ce70c2353100bfe02c11d1f8fa35406dcf15718c7a0d003ba7c0409199939d94a95f88b483e0141100441d74b91c308352403055304837347486c7d74d2d9d1bed085bf10bc5fb8f2d8fafd23366d1a0ad9f2e39764684b8eb323c821d7ea3e67a595d62c9e488ec65fb1da5aabbdd5e29e201f320d12bbf099983323022ea9ff4ce4e14f03c39cc1377dae76354224f52ba55f9e91c0d631c618e629df3f2b57de57b43dd86aadad34ae936d1cc75f1f41f932846153ea2e3b7a450ad5eecdbe92da4bada5f6520e83e08e9fdf0e9f5a03469e3576edbdd77a4026981a4471b2fd8b1194fb097bb1bdd75e6c2bbe73df19461ed602db7f5afbd4ce98436be7f69b11947f2bb0bd05baed0c3e3d4eec3147fe0eff195dc60dfacb9da6342d8c5686ad4bb97a059865cac808ca97bbcea90537a78ed1dddddddddddddd6710b9e387f37d98e3c647e4c8abc732c638271494524a3f5b6fc5b5627729719c734edb0395abcf4e3de79cf1bd54ba7cd0a4c900fd1e9018d09732ca29675294934bb63ea79c3b2e1f2e6336ac66350322a52e270838aa5dfbdabe0f32b27d0cc4d1f88b629b9d69fcb5bdf4f0471d94d4570e4a7cebdb2f49ae3f344d36e95d80605cd97106c6942dc28eb31b406ddc41c5f6ef380323cce6bcfafd8aefb7763540dcfed5fbe1405a9b6559407cfbcff080b049dc3dde824562c15dbfb904184d7b66c719185af687376aea60a42c7a358bbe7d16c534e6783fa4f61cd5f7dfe9e3a758b3f047af85fbdda71f7e70d31d59f8031f3ba824168b39d936c8486612273196aae75e68e6f3cb40cc079a366b48eabd2792fa88e4da71afe9d44fddfda6f3e3ed3d8d9f13b284fb7a5263709f9f0b336424f5ddfb7b8fbfd3dca774e74284cd788e939e0b4bb0d4df7e6a4eab3ccd3dd64b3c214f2f899e9019df93fc797409f63146de3e45dfc718f8b3ad017f35e46fe6fbd9dabc0f7f77cfbdf6f3b76ffbd487a3e6b87bcef512edfd37d5e30dbf6a9b7a091621edf35fc2aa2aed23c2dbfc9eb9e908c3b1a2e95f81199bef5cf458d7d3450ef33ea59f64800030ef8b1c96faab85786fb50b11e67dd544262cf59a5ea27aed3b4d8445283ff7113dc9400ab0ee8b248cfbfcb12a51918475cfaa7a091621d5c7aaaf5ac2aa1f6b48d68452af7aa2eebd9e298d668bbee7438c9c24f6604fa0c9b6c27221c236ed2bb049a3fd64fb649cbba8b40c19aa72d02945030000000401c3150000201008060422a150200e14558d3e14800d66963e72522e9807034114c3280a8220886118648c21c618640c420a95a01d51849649122bb982f0a6cbfbc2fed9fac3d3c417bfe4543cecda8b843639bd02352156ce20c40b70d27543d45da3c57d4d74f348c09af6f4259b3f8da7b636b1516555e5ab36ef2b614ef18ed637fa0fb374c1f03469d6d82af49436e6d64abc6fa2911a39c54a4742568d5158941d2d2d044323b0dc39bb7ba738277fa1a290b634eaf5fcd65fc0c2c0d61b12665d5866b55dc65af96553a0a9542338e8b201b117e1a0652bb22a6dbb501552d8fa93d84f075d8cd70d7cd85e1a373cdaf6224d64249bc5706444d4843a29374db7fbd5c28ad03dfda13bc425de76fcaebd68ea2fe9ce23f78757e74361c5bee656e603582aad03f2a5f419eb86957986b9804ce729aaa7ceb6665e878ca8a2aa596f5ffb7f1195be1e22e83cebf8fc0fba53d7cfd306e43a232ada03c37a40d353d5f0f23d82a431b5390767f055a2a9bbdcf39129c9195bc227b2f77d945f78f2db38b0f9ffaf1e230a685ab85bca963441cc37133fd65bc91faa438a95d3a2b0161aa5a2ca0df10e0a38da5ab7ec4c6148ba7bdd029840f85dcb35a5b288a7e5bdc89a9d25330ff04b284bb39006220b01346aeca82c45d01ae0e38e8db6bbca6edaacbb7b1c755aec1232ec5150841ecac2179bb35bdca266e66cd9401d47adc0edfc345fd14da1086ab2da244b67cad42de4d43f98fe95424473ffc19d8c0d832213b1e764d5eaf5d7ea54c2d75fc06d96f30b9ac4d7cb52fe391bb35ad095b860a3f384221d14016ecec61046228a3049dc39f179b79e47736ece043d8f25c6d55ba9d0fd0753c6eb219567e9943821ed78576a05f011ac743f35e935ca89de82daab38f4769fdea7af617657fcea6075f60ed56bc0c382b06dcb05d01428df9aa87e3be1021a07355067c43c64c6ab347cc1ed4f1c705af8f643816f2c535fe0d371a6de1ed5389b1790e3a7a9b7cf34e902af3b01d6fbeba3908660e2e9e5f136599c5eaf3e6a5799ee8409d0da1a32b596510fc5d586f7f5282841c1f1b790efc9f96c996fa70dca326a3ecdf1d29542e71ba5c2f5c8e23f29fcb5a8a15afc22bb83c94a7534429c38a750621f8a0a5613a291684379b871d59485e5def477160b3e3e595b68b25fa13106618df46875c83e3b3a346168410dbd8a8cb66f968d359027ebeb52a0b92786a5251c5c91982622fbae146d175f5cc75d76d88dd05814f9fedfcda65151ccef11dfdfb548ca25dcefdfdb6b9a5118fc0549b57ffbfc26c45103db3c5adb8aaef6e59ef2fb8675152ef31b7eccf52ebbc2aad3b31997ae0982b8245cbfba160a9c754172f8f5c81707da8ad5872e8d3b4c5ceb747783a2955e8f935741f42527e2baad5f7c5d273ad900ceddcc89479d8648309d28445c89842e05949bec09d4b314ec9adfd9ee0474ddd640cc1b3bf99311142bd35745497162884122f49852cd71d1bef39db70c938636b375644c1121c816944d7b7039c43eb13a4aaa1974ff4131769841674794da9c495f91b3b354191b18a3cbd6069a8640d1dca6fb0419ce1f84e5f83869ecd021af9ee5244a8bc50efa656fa6698d96d99c642261a114c1584cc2106351ee1412eca0b0a4301b63681b289b373eed33add7693fc6386fe8a92a7d6a37a318a1628c45ba3a3a0cff9e493038d600633b955000c19b4b503500f8aaae4e2279437c6e79c4a6a60bd9454635f16ea5a57d4614ecae8027354fc1fe6cf32ab128c2bea170362cd111b455a4ad0d329e087e7261cd4a65199330d8208cf2688e6cd5008c631e281652a34a12860a3576d679716a8a63b3c4ab3880a77bfd3e0a689291c131b89fcf35b13566cb14fbdab4933e1c216c23e5182a5d8bb846b6f53466a8fa09a1b5c57a2d4d03f6aa394c69aecc576948f69fa220c78837d1c2d760297738008c63648bbd56c81a20868119daa74f125caa7bf6364e2ddcc6bcb1950a0d71fbedd5f5a1ebb301c4c43501761fa3e0b879b6f8d351c83e138476672b8e16528bb426012984f16874045a2b164648460f3591b859d69903475d78a0ce635f6d6eca7285119f3feb2c6e21bea5114f8762f3cc36f51bd251293553d278167250c222b01709454e3214d4a3582ffe6e581a83deefedcd7102c38bcc5cea2506074244071472acd43b95125b9f10c7d115146808f0281515093ff71d1ef318c024ed2592bfb674184e4fad4bd751e0c9ed9c201e2dcbf76b77a49464d33af2c3dd6dcc066e75ec6cf610bc133ffd0fa295e0ca1fad4f67f65e12fbca1070c73d49ae65ce226aabf1c9d3fd3bd9a9469242dde0d40a77a4b4d4569e7902fa7366f7ba96e34edceb84df7a9894b274c9043be164a27d239739c499a57c93ae1838b1ba532046be863c4397b235a6be4e7f57c9620aba1eb288110e822ee0cb406616ab80136f701487126d211b472d66d26a2f22213821a010d7b4f917526a545a1f22e2bbac7087cae46970002ae4f7c3b636949a7b2c7033a519718e594b3d774f0958e8ff34f0c939c17297f7858000838dccf3f121891d94cd0d43750eb1f57eb7a4a8546331bebf28b30babbdaf24ff6660efd5f3af4e45a293dadac2ae2d4572b92e035716a3fc7b05f76fa407c32bff272e2c7b08fd74af6e3799634ca3e7fdfc3d6a968c49e8af2c07e6f708ebcfeab5c895acd475fc91614d25cf24c8f306c567e6e55cda5157901f3acd87c93be3bb28c80cf5f82e6d5ed5302991e101c013e5bec2f4ba5eda07659d3390f3d9dba259a9e218acc6458c2b616d3066827c85e8dc6093f673145dcd491d245405510bc5917643992ac6f57946a8e0877198366ebaa15518f8f80588f226ffa24e5edc00006fca955ae669b832c7ff5a419ad0a4321513fdc2d12214685045a40f918262f468128915749030b93ddc82a7119acb8444fc13fe9971f312d03f51ac15ca73b3a9204d175dd20aef0af215b82f4a9ced665937fc25a285ccc2cb128d52828e25e83d57155a86f77b96a5181abde4ea9d34b384018871faa794ecc3c2c7b88bc5f9ea07edbe8ce3ea86f85e2a33bf2f95c23dd2fb71e1592ad991357ed5067fa840c4f428e68e5669986297a2bd1ecb6f0452a8983d3d26958b232cec74eea2ca0b5522d1fea9d860208e19470b068fb8aedbb51d31a19d86fa7ce84367a440c4dd3f6c5829d1f188f3bd2ec8022dd138838ed0444340d226c6191579ed962e7beaf2a2959f960bea7ba6f03db3ac7410870f15a39375dde383331000d58c52a9d19af29a8bd128e5e8e4017bfb9b116c13d200fb32cb50abd929affc1868d2a815b6f4500cb7e80de0274300b28d6b122c591858f51c2704ec86ce08401a62b2c39efc897f6a471516bfdfa7666fdb5670c0ce7ec5d2f0869a4ccfa733929289adaf90922291b995e1e80bb7dfd47a1e8bda7315bd7c3f7c3ba31a90d5a6f28ca8e0ae1050222079852ceeeb9c8f3515b4cb8b0b4dcb439da602103ea7aa1d7ab029c286117b11ebfd3b9fa7af8c1d13a513af551d4342eefef84d03b54c632046dc17b2ac9773b454983f1fe14a758a1a95d30abb78796f206a497ae8430598b31b22c340a73d84766e28319f7456b9c04802f8e0ba0d65fd07e56e61e3baa8b88cc008ff6f28dc560c5f4c5734977b47dcd9f176a16e12d990816647c3940665ff4a526489ebb827772f99f57ef516290e1b502ca31a832b637c5260c101e10670b2ea21422645bc9a8700032fee6be9489e6ac0a8e90832ea02ef3f11673a7500a1778189ccb68d3237f70de7df210b024d87541a3321c63af6b5b7415da2a3c0851d2d81fce162ce43d01781ddca3eb1363d6c2bf25e60f1c0dac3c4815749a5655a71bd69bc220b90021b86bab4cf7a3fc946b29b5e8ac4aae036886865e67386af0947dd734e2b67bfac410b871dcdf94bf3b412d586f99d1979040eca0e87c135d0a88fc3f75112515209090731a2a1ec5c8a2c61381c1c803054a469eaf55803bee18801de6f9ad9f32149ce5890cd99cfc4d46e005ced8bb432232f5381ee33dddfff3c627caed6ab449fdf2a2a2b875b790928d6ee19a161846ee236324017adb89be34056a515033f6ef53784247bc68181032e66d06c4e1926a59900bc2d594a93e56d7b1aa5cac9e21e9477b9e622c82b113ab142212a5d4d224ddf5bb858823c240768f943ab3aa768dbf25ffbe51e1e8862c72b2f200c257cdef042ab790a3dd29aa01f61d69db524feea4e1fdfee0c019ec9959704ddbfd8b22ae1d3ab828d228c3a19c2cfb784edae74b2e695762d8a48535d815e8f924a372a72623e3d9192d8ebff6eb487e07fb24fa2ab21374b7c127ff3c737c4263de5405e2eddd117a8b17863bb35faab31a58b86ef2f00a44ff5720796a7cc2abfc4fc0f7c0d8775927dfac9eb59a8abb5abeb5dc5539f1cb88cc7a8af951832dca34116eb4879602d1d322b3227d563cdbe4d45562ddce6f9c9799a88b44c09df5a7a6fac4233893c1f5c89242fd61cc4242ed896b8c92509eb99ca4956df89bea55c4fca671b97a9e30f8cdb2154a1e1f75e5e12e45e5b76ef92d75fa40221fe716996f55efea9e047c9379404adfd96d731526c2ac6ee672f5db8fe6315280be87d2ffd2efaa626bf6bbbb0bc9d4b938ee2624118176f1ffbfb94cf7c87b538fa5f64a1e7afb48b12030a1411028efc73021654088a48dca2db914f1c126909fcd1abeae259a746cb9ad6086922a2e350533becb54846bf4739343af04cf6f6d11cecc11a3afd18f73e0b429457325c9017084537e04211764f2758513bd1f152eff6e2c308f52f9dcfed0fcfa26acb2b0d3b9e3f6cba6704cc83fb98db007c6e3951b34b956ad83c3d376bc603e8c406892e915166d82f9df428e2f035e10364665026c45fd8706c350c3866d53594d9bfcd2b1e5d9f3b08a4ded4b3c20ea024bbc03692d11c81d46f05ff0e3c7c7de162511b2e51a64ff6f0eeabf020d636d24b7463e58df79101dc25c978048c3640303211d01d4afe485847e269630de60dd9ffb90050b241d766339b9b9db996701d0d642d37c35a312119da20753154c1087d6b524a99676aecd0a909aaa386bf06d9ec7443918c72e53197c639c8e8b2c962a01d8a5080884f9abf8d44f5f10bfc2a5130bf10fb0ab9dc4446a82c4bc2f94ca9b2ace815f3ee83d97a8af9bcdae7b9922843b50727504f2f7bffdbc322657c94a06032544db5ac86682f0f71f36565d778b2183ef7be71990747df1a5c78ab33738aa137883f2afd22cb367e4323961ed68d34be8a58ea60f68ee2bcfad49561311eb8ddaaa0d9f1d7cc1d98cd112f4ddf7408ac04372a9ea956a4d3e701c20150beb4f18c6934d5478f2f35b0e7f71794f2ce9e460cd849c1edc4c41be0d28dd5e6bdf16d455cb42a6d624c5e1fa802aa59ee405c8a35993839b57945dfb148e5b32a6ea4ac1c8a1e1106d618b5e0dbf73c3dab299dffe558cf6aa2d1785490738b7a3a85b7fd2fd29bfa85d86d180c1116f1dc7d8d7df9382631a3444523db4aad781871fbe1ffb67edc88ff1f8e6bfd77bbc91f26a0286fd7188b041c9344f1ec1d63b504ce54e4f1e7f6bb0423f587ed66077f279a7ec7a5bb1b29c797871017bc74b53fd3095fd40f6976b3d8eaa4356aa2ddb7eafdc173fafe5c5616d45d2613d3c61288e4440bab52480d5a24e3a5d511b1710c74124e1ad6781297a972123b53b6e4c62527f423f24a494969b5ff4bb6a28853044a878422de62093005dbdd934211d0d24d869125d47ae1ab2b890016b87d7f0600cc9d59e34350125bf95d8b8951421de477299bdcb8c5a48b21066a9321bf5719dec3e61ee3924e51402520bbf1ae62a876b5f74264a9d52f1d1e74823858d99a2b69518b76f8b5b4e048a8eb094b77098b30402986dc3c62f913bbc2f3b4bc2fe0b5cc621a42e7585cde2b5b6fc2c41ba02c6fd23436984b17a966a35edf6a2e3ebe0298d68829c023f9f38e4b9d84ac1ce2ad2746b71242c49192a4f1e1f0b779632fa0b6c6948a91a3b34b256d08d73bb77443930988592d39ad1196fc71688f77e9ced8550ea32537877016ac9fd74ed1490ebbc8b617bcd8a2063ee04108b2b312759ae27db35df104bad97c0689b6cd55a923fcf07bb23df2357e399caf49468c7b4023ac0c918f18c6aa4d91e15298a8b0446ac3ee855d9e53f6300b149d94b0e09d944898679ee949cc7f3bbd731dee05e9c5a8fc970ece0dcbe23d4db1a747fe4d3105d702f6882bce88a9a921055464893a4ffd042f584da745ef374cb7a020933baac16bd1c410ae920021cd0d3f5f51bf7181703b6803b6b866dc0577ba21f11168699ef25a96df95e22d0e52adbb40cc1c94e3ccb3dd001c01a34e11327872db2069c130574cbb18b46689070228f57fa082a1408a348811e00753a6c931db643f35c4732e74fc2a1a329f93b5e64b74e70cdc9e68e69bcb55e2988436fa8889e0b7e8a0743e9940d3093649d979273143691600ca436d098cc968bafc1ccbdd7adffd46dbd27ff6147db6ab2a6d4d36c70ac6bc84648b77c7edddea48d022bddea2c4367718eac6e29a66c325423d4fe9ef7969447d4cad0131546b0c53cef29e50b0512c35d8d61ba35224cbd0346e7407938760d8f217c0b7577a86fe5c1f183cc00077016b6902effc18e633a447c51dda5300c59d95a9a685941d832c593e002c0cd31eb4241bc8b9b6232846482c4e8025f86a5fed3a444da5bf4dbe414ab502d833e1782a3b1e5f4e54decdaf47f023f171a45ae83952001f740eea71fb493c7c97039ec2250077ccf942d4853f940c23832218a3dc6cf9a3d2114009ad73b8be77ee0134925e63b8a300a5f0c95ba5ebc365442e5a1c5e051b23b232dba520f221531c696a3dbfb6f909dffe405e68f1a94a90360739bb109bee46419374349bceb24e6f7f3d52735fb19052ebe4139a2008a212e85b201ef120e28691c7e2f53739b6ccba46187b8d5d75aa247a16c2280ff0e129ac6f1dad14ba749d49f5e94c0a112bc245d88e4c0d738a87fb64055b645610ae3bcc22e35610686bfcc05a957251947439bc41142d39b1d843699b1412e0b473c36640e0b952684354a08414a50a49726db031366f249026ad9b9b61c7d729042cbe204430b00d5aeff3dffecb067175eaf54c712eac252eacfb861bbc60f574d77987005058fa6eeaa307c3c55cdd91f6fa3ecac4f0e031de8599a9ba7cf101d8170229075c67d02a60f559e8d0e7c6c020e4673e5b9787a6c6a35a5162d8c88a7901ded1844e3cdc73a630e6df1f0f1b30e6c7fcb323f081af316b3f7b809767177710df5a2130c02fe2eb10dae596a3324546b2ae4b952a0c77e6bd53390bc2c31e9bffcdc0a10409d008d9551f48dc9266b4680908c8e9bca79c0c20eaaa147f6711816121b333913abf67dbabe8294502a47ab825eafd12ee9b0ccdaf051c2ca7f3a2ef3c67208623a4ef675bc9feeb7cfb5b0c8dd4a45b93d7006780557961555f00cbff85f54f52c9bda863e8c5dc4e92dccc028b9c10b56207ecc3159e569e0a2dd5455e7e240947839b48f1459570e644173d55d55ebd0871d993a158c0939c54af8810abf0cad938e102faa09c8b9fc2e7a81ee9f8b4c532b8130723a113a4b563a743e8c220ef24733b87229b16b3f1c592d69d8a4b947f410ed8e24d951ea4d208e24c42c33db745284c20a4a7d31e733182d4e91cf2fa892b38de9695d6ba4a4b8082c95012e51c0eb37682c7c4e3c4f359e6e6f1fb71471ab9b2ddc1011ca053b10eb2a274ff97c0a08439250fac34e25ce7098965bc8ce8a3127d1d18db474d51944fb7f8a4b0a6a8a93b913628b66e7c9dc20f4f2460a92c0f9eb19587d3ec95f97a9e8c71a7d0dc138912fc86e2046b8365ccb38fdf1fb9770ccbafc1e972640953c3fcc0e2c7f8aa1458af68a1d03d58ff0760240c81be8631c5c96ae14e4e6b3f12c0e2c5caf56d2f14fd9c284c0395828a031dc5909437775b71468571999003e4a735367dfe2b33b0e1896fb360882b675c0893b93d56817188e5b7ad6ade2d1d3706ffbcae3e72da0231c902ac0c03c9b58c2001b5e6b1625346f7f2ddb5c5ccb402b84f10b2c20423ccb78385f9f6c1011ec74686ecf989bfe705857ff260f36e372139755d751169dad01d3f474d60bfe0d006bae3b232e919ad97877f1288534d96012032be306a82f814513f18fc81836129a42b7db8c9a3180fc2f7a032dc48df7bae000d308fffb6184a6aa11faad3a3e1340da3f4473294250729cfa69e43dd115e6851cfb07c607694e6c353783c9f67f59b916489624af380c928657f7c534382a17a214565fbac284af416c1c583e158084acde6453ef13e82766253276a4446688fe615618cc3b748471b6d3bd3bc8882cd5639e98e8b814ad748e162fefbf5b1b655ade304d89022d78e8532388bbb192f76c80a2022c575596894e98edd573d7a79001f783118b1460362a9cb32fee1a31b26d9f3a83d832ea1a6584bf05e0f1d82276a754821217ac5ba9c9d17b2e8615345ec7ba00e01f1025962d14576f2c5233c593965824fa9d64a2e752f39b7f9350037933b0046ddb0423aca1d666621b714d2678533f222cd19fa9a4158f10a24006ce667972ce9804d3421e289e9112c2c2c4517cad25070dd7ef17d64e01b55aba2020b6da66453b546408b3fc87db840beaa03d8124cbcef56fc74be183d24955fa3efbd0f51b2fd593d65ea89508ce1a6d29d3f7ea96e739d2c208b545ba7a45fc085d0380756c441399e232cfe047649bf9bb033e3bf41d2f6897017048348b3e510b04a747a932735aa9e94477f6a6c79bf83062fb53a08cc5581824b498847ae24d23e4a072c9b956af0f6171016671b52a58e61749ac3d499c0986970d9b3827982b8669c3dfb91b00298317bf172faf6a62248d5b71e8c18c6643e5f36643c9cf60f9fd01d19046274931cc21eb6af73c30c1318660dd46c30bf2c7cc0657530d136a0fb1b93640400047f67412a8e6add5899d61b10adf2436bd80976a80e66b9e5f018db1d4684b02ebf9808bf8855f28c43172206604f236c659a7cdcea9d9bac1f226e81e81e98acdf46b050846683f682872e6e3492e62cb39035627f0034793915409e5488636afaa6e58f88af8c48b9163261f08d60721565480f2ece7801474eb4cd252442080391659e965ee9e9936377d09d4814f05c8da756f7a401aba995892ae073b753caad43a6b4c26ea14db35e8e44701591ad1047e2b9b65fa1423d802d266e9833c4c6155258739721673668ba3d3675954dab56054a50ff147e7a045160a51eea7a34110557406923231f2625b83aa5a594abc8e72b0b381311f0d76a1919230343c11e3c2484dd56cf66c130555317d21dd14bbcc055d9e60f8a0015e1ca39293f47bc8ec6c0c0ba77b42c2ad6a4519a7e205be67c29478f322493c8d2074585982c9c6be4d036bd63593ad06701a7a3ef854cefb7b5ccfe98fbd4f6e6a62e4b7d9116db086fa188e44548b1c1fa2c7a65598fb0c022013801ea456d5ad44c33f24013594eece71b75505e489e90488cbd54cc9ddbc75f423699ee3fa442fb252c513dc1396e7394dec4402e9b5b49a7d4655184b0c11b1752c91608cefb8f97142aa82cd7a993452c4845492a7b0256e885e194e2db093929aa3fff8fc6bf6633c96821990f91b2857d9002d16b015199dbc1d0a0f21caade5ffd402a74081bfc80d14c0170fda471f9b710f74c743e22de594bd9e74dd4257770e63e07811dc930f48a05ce807cf60eaacbdecb1265d6e9a069961c943492b7e79e0782e1fb07037dfb358144ddf9ab3cee2d2e35c22ba6c1c6fdcd39999ffd35c6b92428d0b908afaadde4cc0bcd39fc2b7739bc13b335697fc2c3258856e86fca427255feb56dbeea933d240f42d10cf93794c4057c1898abeefdd413f516c20a81c1da423638b85eee8032784d5dcebb1f2780b0470582192b1c9502138621ac56ff04514e8a7411bb8314d063089f1186bcb2f8511b9c96ae483a80fea0284b705c76836d6d64083358594bab0cb22bd288473338bbef6737b84c92d57d3b89675d58d4675189f6d736f53576b58c0ad2837792012c11437ff513d86294ab2c1d847a2858f88c15ae08eebd2c185c6205435f6e984e7cc8d9ac8ae041df963b4bf8a12cf40d520b41dfa4ecfd7d4c14cfecfb7f9afa9a190c79b56cbe0667b1c1bcc513dc335c0642ee54f61f0e0d68f0563daa06e85a9a199951ed455e1c367e40f305c35c7f01670bc695d6c14b3913293ceb60e36d4b4db0f767431e859d208161d7616768af7b15ae050de66ed36cdbf3dab09fb9aa2c50c8e9b6b711c677d64f643ebc8d4362c5ce2e98f76db8e592259093ff194c950d75040e9095602ba633504f94172d70ca5d4bb189fbf5d09da5f85ef02ff82436eb7b2c935803caeae8d24e65ef215829fd522df7d7d06d7f11496fb87b3ce6856e01d6d9da0cf2011a1243b74c2d5e437d6334747d8ad3b8ba4ab656959cdd0387d06858e7732582204c2dd93dedbf0a6a13c0cc260cb94726265d8fa56e7869907aa391af98e4ce726ebbf26b5ce2d376bb53dc97e33ae722762c57e867bd5a929443dbdd681b39d8c632454e6689c05ce6e9967c2f192c30f75889c0ad9b51dcfd338695a71ead44e9110ba945ab0769cbf282ffbd6bab2e7a813b97ce7db68f08fb6bd1646c3021670539a72c37fb22d0d6ae701e452f9f133fc8336b8c6a501c6087bb66dc22391bc56ab1abb30000b2d47fe0b0a1a95ffcb6a14267e50b954192ca59dc5f96a504a24ae29ba3d2120ff6587ebad14c941ac74bc33430bc2e615da78e6b172b215ee0921c9a270c912c73e43b975fd5e6293806ab06a88b7d815af1a44bc30e825c3776264fc36e8a94d0de944b4a344c1635f0b08e0eed209758db07225a695b3d6f9405bf96c057d949dc131419f6913b8495d7e2438006d302f18fe5b39f1c6a2be0698ea65163a14928f3f53a10fa17f674d6bc434a7588f20e075923062a5c734596b70ac88ea4b798462dee5723da373ebc6efbdeda8782b9c15ce606db43745a2fad06a281925d9eea8114a23bb4b45a1565861b98d246731c54ea9f9dc505c16527c3655551196e6088450b325fc75971abf4a0cd645809b7e702e2bc4334de8ac9e1aa7f9204d01ee60366300024ce30872a6d33d0fdb8bd7e71d5d8e9a00cbdf408d47e1c765911d6e2f2391e6d92d443f4b81767b1662b758d0520a02d5ded5aa4007178741d7f4f958da72102ca1b8d9b8ed65d4057cb76f621083d5d56f090f1fa8cf67adb07b024dd27491bd8023080e698353b33100fd9c661831466db2d7e35d920094549554e0ab54da1244d834a2ddfb5cd876bd030b65cdc6d21c10247335f4a13c556140dee1fdad48bf21f55d0be3203bc03f78a09f0ebbddd4822f43f612d1035024ae5a001155a4625b7b16eac33545da1f49b40396ea50700c4465eb46b873f3fda0e02d79765b1625fa64c862b321c013752cd7c782c252b6f843d303d6e2ab2f99cea3b1f777f56505476c13c05f443eadc5aa976e70cce32c0bcb5e4436e1abbbd469a522e26864411f5c6a46aeb800f111693ae85c083db23d94da041ee3d7ecb05ca8f79a4c0b60f832346020d0cd706b453ed3c9751a12e0279f0f7cbe66a32ad606f9ae68f653ab97066f149e19b838433543925b54be09e10e0b4d282c2561825aa4871986a6ddea15a212a9cd6cbabdb1fcda2051bdf3d28c5aa29d96906993c49ef1c598df066e904fbe61e1394f03065787429698d5f8cd2a8983662dc984c735529620a517540e29e0ce0231f64e1888325e7dad545f83baf70bbe2a8443319feede9e9a23a3855c90be74839101d8053ff4f4c4fd854bbc3745b89d3aaeb074da4204423523b5f485114c1d0cd4d6af4f99c3b69406ee3c758a37456338a76562cd5a189ac8b42c1c86673f722101134619a9868847996176e33129da99da2e81c34cddf91a6530edb029c41b03a79d16e1d106bcbe5b75b3402060434255bd4712f378081ab0f918819e5d963f871621cb7f92d02a3628bf84f0471751bf1de4a0b1ed7f5834354008eb95b8d2098009d916a341a1ce459192104f2a957cefb8eba30573cf711e6342aa6ad8df09377e0676004615c90917513843552844d7209cc3a60f6e69fab31645f51765117f59814acd667587ba7d96ec75e8e378fab14053b54b72bf6357034d01c260b56f965caee5f366744163ff671ed791ef458b0f99490f8a0aa025156e549f4fcf5481bc6facdf0f0dcc1c3744b298d9b15c5aafe6114bfb04e6dfda461a70c18e6a51fd40c054d6f1a87a9ea5de23cc943b1da2e7aa66a484a22e6a6657a0065a101b30118e5606b34c2b74c47f3c8b75b5309af2e1b133f60e58b1171579c31f3a6fd48ec8b144d2d1bbcd1ffbde768bb7e1dba51a069a75856b596ece4c9eda407a8aadf0b4d06ea302ae1a9d4edab900a57050b8a51a6194611f702d61d3fef8701f18a8d5162ee9ce4114112cbe40eaa5a6107efd204d264de9ccd15c4f8d979cf1415f570371d59c7aea5757a441651338feb1a16ab3a0a460c06be9c3e8625b7c44f42754d9cf2c13221286793dd5ac40c12301ae7edb4ea89c3e475e43408a2e6f0afdb3c8061b2f7f30c13084d032070c29889490848c5e299bd7e9fe00d2cdc5cd26e4302d5233434093f5a6c5248c12f46ab92d8a899692432aae5f215142fac40368e2a6a31eaa277f122e0fa45b463136f66ce16c0ed8260ca3060682ebc1850160ca150b520209009bace91cc2730ef8428b5ec0a637a2b6ae5c77fab836850255a6b09512a35f0e7b6640d26fd22c03b3faa5a8a867a691527270e9ee8ed9a1602c28833531d3fa029cfa7e2f642ae4e2e12122c3fe79fef7b824f98dfc89f13aca3370e0bf3e62d3af066708e1652fea2eec13e78d7f1ef8809b2a7a956f3e5d2f7f093c815ba2077aaac5406fad390a7f82e65d2ca4e2665f3996a1b781bbbbdc71f023795fed97193abf6203f9643d3b6afd099bef22e448f8ad327532a0b211ebff9b02b7d5edbc1cf4e7c2f0a20fc44fdbc375b935290fc0592259ecf7feda369317371430c826c3d571698c163fa6c5bc35740e2030fef24a16cd8e4a83b11413f8869e862d7c9aa2f8919eb5b03cad4f811fef42327c7aad5cf8502229bf136100a61e300aabc2dd51bcd9b1a1be80605df1a1f45505aee97da95c2736ee358049ee475c21888873df29deb7bbe5672bd6ed979e09ef54525bd7bd037face6073329a28114cfb83fbc91bd74a3899606f70e09945fbfbf4eb18b770e17ee86954a6abff8246800f3a52010c133c1c475cbf7aaa040bc4b8bb76c985640bd577c8d5ef4269ee1d9e73c58b10b062cc743601bf0367bfa1676d01af92224907c6ce12290b8aa77871709ce1807c859b3e3cb1efc81620b22a7a40e1d581a07328e825300e16549e234d7c8baffa6e79849bca852988929f87884400330509e5e4e92682165359818cfe6d8992c70e7073bbde1ceefec5dd4a6fcc7347a0433248f469c08cf874773add1542ea21ba3e9e2902a9a0d8565d00d0a4235304d6b5d15d47ef6c0259aea556f280977cf453a24bda528c5c21a4652d1eebaf9d7b45c0277313d7a209f6dc82040edd77db0925a404cef493da27599ce5ca87f10a13b3851ca157c3fa6b040f5775dcbdc3a92f6b664c101922a5a85f99f5a58f56f0705e0b9fbbb27fd7c1c11cd977b00f3086701fd5a7140a413aa20f11cfcc04ee37ac9d3502ed5efc4bd11858c905650bc22a932f1a2890fb89a481d95044a8e6660ade2ed11dc51f600c18500e3b913ddd3a3bfa217c561ac7f97991424861caf976a694c3910a8a961227149b55541853edf22fb3ee0f0050f296bb406c8035830ec932786e052a63a22d88cbdbb85117900623a10b314d8f546e8fbc02d16069d053f44fb885019fbc1e05944ad55b22523a269105c51197077b07648b2d53cb8dc21ece92fe3904041659b7a73195da2f9ebaf2b1a876c54e35eacdfbd6b6dc69706391d00775fbd0f6b5b1ff87da95eb969241e5b4ebe18e8e08977af772c2baae10aa849f3ea224c4a7ffd05baab397cfc37e4c11474868fafb6d97bec99e083b7a81d258301df520ae2350bba78057697f2b6c8f09878aad2084c10a0c874bb0e38227f60b0077e3d9867a7c6718ea2f64dacf8dd564155efe736cff8036bf33596019d09d107d5cd7103de138190f00e95b10de95b0d024b4311ab98956c917e791aff49a0d704a3cd07f091e51c482116bb1c095f27ce78604fa71c74a2922138f320ee4a7b50fe4c698c973a01b42d8c44c68b7c1422be0252cdfe99ee38cc0b04ce3fa9b4b5730c3cc686ce20e86594407f14c8402048acc06418d14b474d4d00761df816fbcdca0bf25cafc1df5f4f9eaa61a5b0b69fbc2f3e648260639c8aeed59389fc425e390a394048555c72f9e5b2ef86c6479af5d0e388da6c4ce6717402980ea5f50ab835f0266f22ff7957a5674ae31ade2961573710b75278a5e792729e81be5ebd10570d305b770f6af19f31889b10fb95b15576c1282ff7c72759b8eb7d42c1967d3452878e93ba02851db93c271146bee10f5c3f743ab8d8b94f680b9a875ecb0c895839064db72b813b18aa3d06cbc49a707a51d17193d0bae71d5f3b382e8859c023863b7d1c5b4f387de68229bbba5594507d82cdbede66d0ec81350f9becd96f20b147c0138cfae2f366f621fd1e3f550572cb97ff7a1c055f91b25606038bcb94875c7dce46a5977859120d29075d48282ed3f20e6c2ceb3c7c0718dea1b7be1c90fabaa0ad3cbbec6fc093d2e386b522393631453b89f22106c45bdeab146c5af3fa8cfb44e20da29eae95d0494c32d66b881fb3d8d56fec8650601881dd9cd7462bc800ebd35957859c67d68a0e62507702d1bd8bc0b1eb6cee2693c5340a7dc10e3cf0ffb48a7402322a3da7e0238bebb1f29e98a608cd2a90e474baf1f164bf9b1a652146235fe2701f05ab03e4d6f9937104a1a8c7f9443ab2ff10e17cdcfe2235dbce7f29702fc33f82958e74ae651fcd9e815176edccbded0ae1042aefb1f84c26fccbbe384baf325198c18c2c9e9aa38b8ff77ef8ee717863f3f9987efce405c9849c3d27377f9330c3cb87361e0d67fa44a2b9b98019c1996d3400704952fc1ce0565320199e873d08382e91f022bbc56c75832b7a36f776496b6df692e608ebe7346a2b2c81851a86f1b4afeae66529c6767daaa1eb176a7938ef3aaa325c5525d0d8e40261f931160ac53add06c35b2d1413c3ee0fe60f66fce1cc5e48ba855fbaa076bd16ed82c5e6b9190d44b0aae81af47a13ff59ad34ce9af81c122e94fde5f62620c2aeac4b72a2bd609be7f2e993678d495685ada8ee79be24c1b2422d336f31517b59c9c18202df64146bda277aa421c70c201bbb0ecf506ffcccd13b0e53b49ecb03e1ef08508ea4dc00dd71243e48c7dff3a65df993f56acc53e6d42894ad1cf2182a8019db2b91e46117ba8a0d3604a0a2176e10024acdc0a8d09544464d5acbb15363910a9340e6dc56fde4247d8876623ae6e2f5ccedd1221a79de46f175972ddbcb4b0b07ea6938435d191e0b683e7548dd6b3ca21a165e680714800284458bd84b4562bc11398de06101a6610e06502e17561aef547e3c5ea15f2087fd1459d7e9523aa3ece8f1e6d5bb4312766bc4531d8a60956afe37b18e73a1d722d0730135ae6b16376f32aeaebbf0879d5b0983fac4692f1086dffcc83c13532d659eb527e904a565c5449bcf027bb892b49705d1868bb87ce6e31aa7b4a0812a0d202ca935c22dca9709667337c2e6113f9ba9de5ac3586d0d1d6213e2986d6e9f16ca95d884fc3f54b3f78c682141c45b79b416a3611ba0e6776103a9c6f4dcbcb1c313f1dfbc48554e604c490a1b695211368b7eb5a91c99506579e84fdb5e7d61811ad4c4be4703e9d64e3e3f5a6457fb6f0164c552359d710387f5fecc32288f5f9ae7f54357d52b363f5565ddc81650b2fb57aa0b07cd836c6806980942b08a8a846f8a88ccded450168f5a8a090095168bbc9b7901c7dea1e5863450a797b6b72d5fafe6fdf77cc7ca25c2744e4dabf7a66fd6009c8c15388181bdd48268260c3338c9fe802c8740657bc664a04f7687c40f8574dbcde1133bc05339655eeb910a15b5e2e60f966f2207a156ee4edf0d47f9187502c67292921a472cd7f73e4d5485a73081681fc4ae76e429e32d189e75c0bb48028e45290b3735173a9a56e04c603654cf2fce060b815cd7952330281c74f83ebd57e8211c4f91642a53bb8a0dd168e4e46f20fb60b29a598f9faa41117d0ec6d0a0f3e485e53477fa1151520fb4b748fa141e8f3b5a394d6e08e9c74635f44d0ba08553c9696855f43c32c8d09528cb7624d5b61a11173b3c51173fd4fd7988cf4f0903408d9dd929934f2885adf8db7cc18a3ff3192e126508de67420b7d513fa1c79fcea43cb6f405f48ee930dc0f80ba8670df6f4a8744e9e9587421d3c7d1003a68f1e39c74e3944e6e20b4d5a28d1876f9c309d8cb297783886520e34b4eaac1328451957bc6ca65ea0e5c8c9b733322cfe229c35633ed69156bc5102e0b3330e55128d8ea1e7a65fb6d761ed18aa4a7f55563c738d960f3c7a1f669e6da08e6708133506fb6a7b2cf66cb669571761be9af4b900d43f25ab6a173acb5aa6498d6a4e9ab0325073983eda9e3a15950ed82963f650c51a2374d12413e15bdc06837ff90261b677909a288264e17c26e524420eaa20f8ec3314a9f5aeef55a30c76ebe8a387919cae579beee42590702e58d9fbe2adea6d87f61cdb3fbc4ad160990e8567875744bd051eb28dea97840a5a692dd51c6a11a53bab7e9a4f0c12be2cfbde340baa818bbc5c3f4c311abe94ea43181424386c4cacc94ba78ac669715170917e797f293258cb5382eba6d442a3c2b1b6c5bb034679121ee7e6ec5ae82cce9055f58a46a753cf169f715542c93f744bb563e4255c165f6a66c12912227283abc50d0c36343fe249db20acce81ed99f58f81cc3f694c135ce3367b8b8098cc0de9b196c1e08b98c8848547991d3e0a8d1088e2430b919df65cdba4ea21ff09631a2a77bd886220a6f6e8959ea4df3d42ae511982464bbb2557ebd253298403151e66d66000ab88ddfe254d9980f99fe917b2061955cdae91345ff90caec5fe0a80a50d25aab11bf239512446088c2fb5f0138f49ec246b08ca349ad5e463d03e183e488ea621639ea260797a82130263f88f0e440a6a8d8ab576b7f18398292d7a9060f615c7047d27466f536e71f9a045321b23cfceb4eb00b58f82c6e4c13c514a263b68876461561a7101337821215d39f602a5c770ab408a2b64d01526d5b8e9f1cf7261b11ca3003d29eabd7c90809e14f622027b855afed059bc4b149e279b288591ff3270bc26de46d5e0733ff39f2ea9641c9c4687038c7f248bed577a0c0f56795868751de0fe64f7a43942e3536e769cc875e9a233621c4ee964987841b983f846079f73f1eaa9f3facfea74ebdeaa9cf8ea8040cab6254d5ede9272cdc01515ea3ebb7783e3ad13cbd4697cd01c6b8453e42c821f1f3f2d137d3bea0c0648cd686cb946f293069bac368d24c9c2931c2d6a32ddb82ae193e8bbe0bb361e69fad50c09ccab6619fe1acf9ea1fc356c64e9c273b50a0997820c5694383d60f9222377a32b95da09d95c4ce5976364e401fd7cbf39583d8d6a8f37c9c8ef6abb47ffeebe034ca287cd993577a52d91190044c0f931e488ebc433621d2fb99d04e55bc211ae41e5cca4d33fe80ebc64fff6503ee02b6a21b18f0f3439fd6e8fa8c4e329f5d74ed666bf99858c0d999dd48aabfa94a5a743ebca01f2047afd8bf575ff9f707aff7de2f557e1af5e47dc468edaf5c3c41ad0460315452dd6a4082f4ecdd9d0f73ad452a0fb8f08895e8082c114828138043bb538785998754d29c956b73fab6da6872fd67ddc7f157ceff009466f646b5b40fa8fbf9a60ab0e42ea918d5da9f77ebc5c38633e052c7024659e698f05cfe18376c06a1386a27422745345a8cfeb03247ac43af36e761b44136bfe17bc408e186c09dc0c54ae037d0996635a2532e9f9eb66eac85150330dc1e9f805333c946d4cb6800ebdc30540bc839059d28e40cd633e184474c5c13d805a93391c4971e4e19875548748d47a541264b65c1ba3c312349ed3725b6cd1440b4d6c9c8ade7f3ce01c2156d467691a41457b503ed2eff51e1276de5077f4acf11e5b2fb39820a1ff6e8069da65ddf82276d07784ae8386b468a1c4e04346aeb1f498444b48e64712baa16e6ec88c05f9ab6d3feca3f8b0f7341b2a1a3a65f85ef2680fb91de216a80a790c87e1a5a43bed7518410e2475619ce91a026a7a932f67b6dc82001fef64279cddf48e8830d449e626bc06de8abf6923d07ba1d71916873f260a6995aea0ff7413a136f3b105d1ab31455ea8f400275b514f7f82961dc56227fd8af4f967d7783c81122abb794a7767dea2858d25ee55f6ea4b91f124cfe5ecce270dfa0bdcc447121ebb4b8768683d153f569e1e81f773aaa3b24ed55f9fc124e3f6143c926fedb05eeb144f17a4465bdb8b9deed684b08e3c9f5a7572e5abc4fe98f30fe9e5c477872ca274eb4338a5178b791e8b61f80a921021ad1af1c2300c3aad98d10c5ce18cc0431e2129a66ddb8d6badb5d8dc053a40367c83da37e219a584dde9ae40e20fd687495dec48d82079fabddceafcfe130a7bfffb2b83b70db3da1ddd568b1e304e2e6a7f6185b5e7183783f5ef35d32fa04d0f40764f34082e2a1906a43fbee9e8c01c91bfa1d8884113eac463c1570a7454ffde1b8c26b92c4b125efa8eee32bb65fddfe8be7a4cd9cb8a4da1a287afbeed2034c9971cea43748db73d2bf41e85285f71cf79072dffa5e2a2301c09c0b987e37560c691115a947b1549a22eb27c41211567447a6ab62fbac4f74a747e9be8a924e628724dac1eaffe2f33634424f8866f428281b9d338fa15449d6b56da2b41f241ed8d186b55cfbe949a866fb9049ad244f6bc82e4822bc701d6292f4c4205e52779f1fd3ea8575f72f7857e63a1f9c1f62b2272b035cb136e6fbbfa8254e491cddd3327273b93d2ba94bdd8ca3617d546e4afff8156b7e84608c48a5b6940774768fd1c370164512d20cf00a810de139bf0251848d5418278ba5763e0100dba8a06f996e3f723f7c016180aa5e61376957b0fdd9315e92cd504e3bddc51911e9831a1a817e736e5ec87c1bf2b0afe8dfbaa4897f6160877cac631af59ea7b5e54b47607d11f5ae2a05d48e33edec68d76e2a572cecbe7a233379de56d6a1710bacbe6da4060e09d0a0b05050754588ba94fe69164f9163c2157df3f48604f71e4808be9eb6f74752d982def3061ec139b89fb16d7940a42a6f4199c14d96d362060b561c54281de8c7f8e5daa5297afa2ffd1c1b02c50d6b59588fb987831182cc7e26293397c77bb83bd930f32fc6d8bcea98d00e0255c1b09440404429dc165c844fd71ec460386996fe7f96654f3589b5b4389898ba79de0f452c4729fdf4cf246de6e405bc642fb4e05cfd34cd2feed393832a10bfaf618e2c1d5cb5d561cf265043c6724acf5676f160590fe4968c2b612d3dd7dfeb56d00babfea4f7ac5a7fc8b0a0c8c9e0f1db6cb1c1ced93afa1fa9d8a18043e38849ded45492112c530183f7822bd33b720d5de5042ef1ff2b22663dfe70e0188d132da84533dee0e2c7ead8fc60d921e8f30e40f82fff6b5a06728de8a09dfa3fb8441e0ffc8e5cae7877889fc69a09f716d62d42555cc0d6f5d9d1a5b656ed1821cf676c82da4c020bbc1d9768ba5dfe55b273f9da6ac394cb8cc3ebc84226e64fe1cfd8c10142ee80a41ac3f5465067e324b107d81c7a5152d79b1f4fddb09efb068ebe6046a2b303c7dd0e7924c8d2230d0d774a38e06dc650d0ca6a8721df40b1cee77e1564d750e6bdaec8f4aabf3ef00ecc8a457214cea33c4a1b7cee0812ce3b2a842b030b7ef83b562e19bdb226efc37bd126f9800b42340dd7be09f50b2061f68c271a304e6d1ff9d6b718f07e6a624a18d2053258a93a045a4d215a0db03c199fdaba9d7f4155fb47eb9f36a3bdec28ecb270e758cf5ace1b6c51dc7ae7886bcced1d30f0179a27734a93346ff325512211ff4177229b8acbbaf8380a6fe4faccd3c611bbc8c5e52edd3c092de978299f63b9b8ad3e4d9cce27c5ca1fa1391a200ee8f4b577bdf16312bd89f7ae915be6480ef4d9d56d07c8688e7f217676a93b6306744fb52164e8466c5b361622384e0eb5ff0ce7dcb89f1350b319f8836e3ee608d3f6a896efaa4491f2ed0c3659f14fb620a0ef2530e2e1c439000876d647106e8b441aa7728e6cdb2388172d4c1082b92f6b39695f904f53feb9df6e4f19e94c8edcce964a6e0f029ac6436d2aeff96d64d3c3ecfe673f378b1b154af04fa39832361c78740b04ae9ed945ed637a0f382763fe0e0d84007ace72fda58ccd29c2cc3fdea9fd46c06f0ac6e0f15134a3b042cc1474bc83262514b4111d837077bffb61ed4730fd933a6f670d211071998e3af12c57a177ca32f7d78d871aa786c1d9746a6e6f1980ffd62286c3bd07168a5fd1f76bd72e3bda71eec0f0c748b85fd6aa1be3713a0c40a4a867c60e8fff3f9d0e10bcd1951eb959e5ff9d9368cff13ef55d7babd7c39637b214e697f19fc2d58627852ca4d6a5caf7e45e0936749b57288f5a621a08cf83aca0c031212b3b0ddbee364090435dd97dad7ea587780566397491a1498915c5941dc0290d1b444ecbb02c80caf35e2b07713d3f5bedfcaf8f44ef24a086781aec81919b8d66bdb61e541ee9a0b81d608ec00fd0114be82c295c6d5df4402bd5d922e3179daf0f015f91a558056a888d255353ad2596c1c3d7a68a8ee9f49579f66159b700446832fb76c1c2a3b505c9002257697c479ce2cb85e1aa66008a67a49f9074ed496cc632d9f6ddde9bdedf45d4e9f5dadbc4a58eeaf492e22efccdd3fbdaddd4abfb8bca7b989bc3377fde0b27629f94eee397f06933d7fbc5a774d697228735878e2d7c42cc8f2f4a50b3793f364f25bcc4be666aea80e334ca8082cebb3e314f3b49cda85932478040211509191b28651b936ddfa607c33291ad09bbe95ffc42c3b15d6c652924d20e88969883c9978897dc9d890d5e03d37841b3f4a6efb3bf059dba911cb3e15fef73b34be985779ccb3d597f2eecc99bfa1b9c9efdd3f193a0557cf850681e73b05a8a8c8b8848661764eb5e1e2787c113c4d851c9be187e6365643508281260612d250000eafad78264d628e1ae0ccdafd8bea7a35da3caa9dacdebbfb3de3337d9494a4caba9d7eeeff59d4496585299027a88d6560ec24d659608b85a594f0656e2aa5ac308aeb7b426931f1cee6f00ecf0d1576b5eb83d500589a6720027909c0bf0094c30f2fef37e4f373c742f219e4659180305d2633ac67612b55846f155d98ccaa0aa89f08991d5f025d240f63989a8cf3d1fe6cc4d5b26d2dc9faebc1bafec14bf35e283e35f078968d98c5e69dba30522d4db602a898438146290995dd5b6b27ba179473b9e9d93025e425777919d9347a3a668522ec60565ff58d190fe67a46f17d9f6a5d07a1c566a8d13e07bdbd39fda63ea40d203b0480c943de305dc78246858c2873ca0fac5b8879bebcc2a3f389ac8a8767f9c8edff7385eeb664af256486a3cc96fb82c213ca75662e94defcaf7891ec3594187001677436bb36841950f3088c0c76b5581f753003dbd2d4442acdf217c7959a50dcd02488e2fa100a13e60b21f231c83ec1d204ff559405c7594d0061e5f8e3fc29ea8fa1a60cad0bfa7269226b91316cfca8e1f060159ceebbcaccd1181502fb504888f720ff8f2572cdda0fed33f5114ded705e2c81d00f59a9a7dd16385860220ea95870cf29f336641dffac553eeddd6ba6b69d20b97f1347692926cb165eaa592ba3aef6e92aa4296736af65a7418696265ab008e6abbfe0fbd8479735418191f05745dc4bfcae61ee75f2b01df091871dbf0f447180f768c22bafd8c460064de319627d8e13ced97e20f56753d2de2a4b354cd6673d9b645a04207cfd9f7efe7cd91fc0b1b48062904cc40ebd33d0de2d0ad2f4cd40c38cb14d765752dd9d8c76a768d59b40063a757d70a9eaf1f9657df2c7b3b0037f7dab525e7ecc6d608351bdad158de0ca248449bc09bba7c463ffb42b887afc71dc893dda0d3939b01cfe17be1331f9505075c687bbc954189bc4c9125b132572cd57c0dbf736c586951a2106234cf6e4a8f8ed092cc296db6bae5c3aa7759a3b62875de8f330f49b4e5544bd852a0807183a0615542f34830b58744a6ae5b1bb380bb925c7676346effd536571610008118955284bcb7ff38c45a1b95e4b5595e7ea15c7a728945f1ff2db8ad7f73d790d78a70a3b862a45fc4d3f8a051a9efac14023a257ddc0ea789a349f4c3b2c6e1dfb7ad2397029ea4fe28e6c76801086fbbef32792bcec723f92941fb12ab14f01efbde56ce42580cb7caf94c6f65e9625883ae30fd6e2200ddc008c2ecb61d0a95eb44b050f1ca95b4190495b8fc218d54400c869013ce905a1f2d759e3c84b192020d895f3005276d89499bf9643eb6a0fb03fd36b622ca6d098d3ab8bb81b217c499b2a315583618283df4474c2c81a82981dda9bb6f5e6e562d78829d90e9d69ec9f1b1a8aeb4f7f027a9617309850f42392a0f9e78469aa21ce173568bd1b63fbee8f3e2d4ea38ad507a3c633bf6fc9e40bb0df9797bc25b03f703041c8cb187301e7a4606597e53a0a701424bf9304bc6b53beea2a46d166ac6042f968704edb4a9a4016081fa03b5aee872aa0b8ba25fd1f8da4356d4bb3f68a1fed16cb335f8492033862a391913ad51a8dbf05accd33fdd2e52eb8a83b090eeb456d8c1f2787d35b4544e0b066fb9ca7ff8c73649f424c2a56aebc941dbb7dce98231b8c4637e2beaa7537ae6a7331c0a04fbe83371b8bb2a99616520233abd97f12adaab5a92a05a09f9eebeb094ee5c7915049546dec62c84041204ac9a148a911ed532c53369a7b4762d9708dbc3b0e14aa5f0fdeeaa095a9d16faed2e584670aefe05b5efa482d0ba1cd1b66062f7c04dd580dcdb0fdeeb958bd90cf7ff879d3b10b66de162cccedb591573c1c532c1e95a6c4b93965826b8989a4a17caf7cb7b68203b21add69fdd0578cf7f1aa5a3ea4a7049fd541a33418255d22f1d57911b4c710c4c29b7c5dc3b95a73bf0223c58355d42b782b0950c5ecc2d5b25f2119f834c196a74c023de3f512f5abe715bd622d5777a887b954cd43127de2caf428289b3ffb453f5cf57fadfeae263357f3b5b1c7986ec1364c1d6b457c76d0bab181d39465c70a0c15fdde4a3d64ca0bd1a426610d4f74b34883c8875dafd7d56d4b5d66be0a933c323e15ed9589fdc335653e59459350a152f32864573c1ab04ff011c7c5877e35ad9baf4df438d14f92be1c178fc0c107ac29870a15717c78eac9a7dec62ba7947f059b518fa0343ad29715ef5db95961765b5972e05ed6a9ea75e49f8d5eca17bb61a216d5da82294fc0d5f66bb6efa10caf387d894be538b42d9c06581943a9983d8803f50e71020a25c80d478b97de13f634e418f389c319d75674f5e5d3eb0021e8884ba950594a2eb9b51d690ce867a05b3c6c6055fe39ccf3481a2f311122f946c598fae0f71c534e07aa148408c4bd9df3b4444de7dfe8910d370c137401ee4a7a2920d1f67229f1ba8c872108a0cf520d314558945487a632164812043008c8d4bcc2e42872965c5f1d1e986d45278bee430e8986bfd61594c84e99fb6836bb58fb037ebc18ddea90c4fcea5aea5a7bfc3aceb02aa95ebb9a15649b9e87c418ad64634b59b965d85a32b0430babfe5dc603a0601c97af56772549707a909ff58549e742f75590f55c35d622d5fb1bfb1aa303a8aa48a362e3eda8e16b9ede20beb01783a63733406766d0a2cccf8e2aff8562d2002b3ed5b6c469cddb55fd000a48a79662519e96c08e11b0be44d79c65bc86c143b57eb8a7c5075b4a416778c4100355c959c81255a38c0e74190b6a42bf238058cd9a6c317c6ae0be172fc02c08073ce4997acfc8b023a6ab95633ee45168f768257a39585066911ea59a017e323c2a52979dec2b960eeb4bbfcfb97eb531244693799fd63d2216739810099de83f952eaf56844229e58bc7901ed6dc0fc6fc645aecdbce2cd69ad62a4dd62539cc5e981d18d9f54f04c370690e340050cb3782a801aa46d6ded4603215c616c6375cf86106d0f03964428393ddbb949ac08a1f3bee0938490bff07bd2fb4876d7ec0a84c9a22d3fd0f3f196d2d4b1f9324fc4bf0b45285f6f3525e583893768021c15bbd4f170e6e92eed52ee1a1c0690d92dfa6aaaf79ce29ae2ac35c4cd22bd406679f92f52da22766055d416d9ab93050dddbfac1dbf8cc494f39510bb8664bbfab02e17b467c27973fc12bd6789c6d40e5785bcfe081eafd573fe10f425c1af984ac12c23c83f3b6aad93e52fb58086eac902572d8d63408fce47bc06412b0acdec165dab2222b9488c5276282a6599dcb0fd402e2a8a3314ada0d4573ec0ca98d4c4a70023b8bf9b209537e2d4afc6d7f48a19efcf7cb69cc7656cb60bcb66a4c876500112d5bea0f2b5fd17972d9119317c28ae82222be376899604071efd5b55cdfb19cf57f6c76d3b75c95bdfdc465573d946300b1f69e0a2a714dd713a0966fe3ca38a66b4768176e126445165c4d9285cc6a742b52ad10f5b6a65b6a618aaaec7cabd4596424c001e8570f0208e40800bfb5fe111493551bbbeb922466f68864ac556b696ce82840ca8121a1f2e557bb1b87d51a99ab79bb9364c9427da2dc8462d42a9c622cfa6b6af18ba218cd041a05fa980ab10ced2a316f7082a0d3703e80e968ad6a95e88c9de0a260139b7117c4110aa15848ac379f818f37735307e3d8b78205cc09e0061c8d4390c1e0fd0292ecd120ea907be83502e9697f0fc06a409c1d584239a04b35cdb764e54ff0750569161405ab009865f9d5c5a8f8425593de84c0249259703aacf5d5b861c7a32511bc915447eab1c1538ece539bdbc749969543ecbb6f169dd7a9f4bc9d0a6423036a135a6b5a3054b24a0795b6ac745ada4e0696bee6fd9a7763755bc5fd0027d25dc080f49f08a1c7a29e94bfa4367570e91015fb727b00084bde0d88f1346dd3a677141bec5b9df89b6978f97d9fe6411311bf0fd9c8de7b6f29a59432a5148c06b40696063b58ce2e2e75c30a3b54c43da155920efea188e7f4c321cfb1b7994ad26d7f499fa55851c1854fdfbbb887025349ba10c8b5b8e74fee3511f663ee67bb1fe7079be2c166190b37e39cf954e6caeff1b969edecf8ec18c3d2a712b22073fd21c322ea580cfabd1e02837bede45ee7d1dda3cbdc983577ede45e3fed2c493825d1a4c4122592300c9028595097a910ea72ad125694a83274bf061a1262d516f6834e01208175e1057ba11965f04dff57952c2b21e1743fc8c549cbede78b4490e77411199230ba1fe412855a2989a258240631d36eaad1ae87b70308963e7d661bb689373db0b0fb58be8f4327cff1865a3c47a65ac0180c90285ad8ec533ed8187660fd6307a107dca9fbb0afee1403d18da80bb9b04dbf8ac94224a8a3b94b970064699d23c1953bf60c61278463c19d9e84b8c7ef5ce50903248a52cbcafd1aa81ba8853c87955a551a09e49241ee8b81e842a7eb34720cea6be132dbb804fc47861bb5b0e04e97dd835c66e0557f0da92339dcee679882706b2020d8c5bd964195451c92b9c21c63f4628c31c618bd8b49ab14a318e3ac325e935609af4a2794464edc21b3c3d7d1b974b09ace07d6ae4535e03cfd4a875c542fb6a581161abce0caff915ccce08c005cf9582a255ff603d1051031c6f84204fc686a8c30ba524a2392ae9c010bae9c410eae4ca55c061f68f0e10ad214579a98c82b6e2044ddb99f86e4c314482929a39452084d37b06125850cb8c0e0c6972929a39452ca2dccb8b248cc21832231b86205b6634746d9c1084836216ed02b4a0c88a2c860f6105a8a82c46614e5891a80a274a1f5a821297504516a86e6b28230686c59c1183d74a95901d97e1f3f5470cff9e9bee028fc8a751cd02b7fdfc27b5580eb41d828a18fd80de95e70f7cb85e05a09416c20003610f22a56ac5c38bbcf87bc13c282530eeb5c9d1749c27361c7befa1c4910d673b8f0a58f287f3a5cfd784fe924f78a5a4b8a8a5a469eb3815ad4b9d0976d6091917b4b260a9c10a38b0bbd95d453dcf382b05fbd492ea060effce84255983aa9a7b850edafdeafdea6ec0766a7ed943a6ddf81f088a594d249299d74d25aa78cf14865f8353edbe7f4d93e6b9d4376c250f93054ca48ab651bf9f203979c72c6c8e48a570d0d3d5dc745c4ea7f1886613d17fb88e1440cd6b8e717c33862d8cb8eb14e4e1abbda718c5132e15164ccecad9921dbdc49b870157f18a14452c58925cb9879a68cccd0995bf64bb5b28bde3133d3e8439285efef459c918a8a85954208a323391457ca20842e650fb9c336fe3b52a9393bc8524a873588dd33b38ecb2fa5f4991f587feeaf9ed3eeb1920f4d29699c5838a564cc39cc36de53be67e54359e305dc73f715d8867fe60731887bfc38386c239f5049b1f03d03d9ac5fe3d39f4fdfc79b63b6a9b5a652f3651763a4b0729f7ce6f8317e8d2c703742140c014b5f1f2a02361cf20bc0d68f2a300b970e723804893ce7c3814860123f621d9c77212f62af8175b07725435007eb7c077c755b2e7c2884a20b6110131f419a3c4b2a0cfbc122b048ec985017621ebf1a3c8a4ccc3963a4efe329789ade0e538f8f87b3c30790159498b030794e9393152c2b50b91f77d1c55c41b15f2f2d55994f70cb0c06e038699c334e1a29e723d906ca3a645e2098518aa0d67a021ae68173ce197f849608cc03037c03ff026cb36242290df3c01883c070e434c173ea5fd9d61ba7f5d599c09ecf94daf5b0d72ddaedf4cc6e077b1dbdde81632d865197376889fa60f0712c8e7098273ad521b1d65865acdc446710ce912b304ff6fc04fb20221e6b7b22cfa2a1cf603da9414229d6f6443c16ea9995722e8ce961e61cbaa36f6068c08b71ded36cd3c3e4e569700078f9180e7b1427e4b150bf714144522cd40b79ac97dfe9a93e7047f358a16b58112c80495e618fe234adfb3a806197086e7d883dbcd7fb160178b39d6ec7bddaf5086101eabce02b340f0ef00d2c12d4a503ecc5850f37c036f0677a60bf1df98920eef4ec6c0fbf67c3619e88397624e39431ca38e50f56629973ce89434b7ef38dd401a994b1367bf2258434d2eb7dfc6af664c3115c8f73ca0ec3a8192ce39431ca3865431c11986c0b899085f55430a185988779071c1c085a69414fa432521aa98c383b3d3e0f75b0f7987d76787f027a4ca830013c27540534a046fa7427013dae3fdcf187298e95e906ae97ba7df5780edf585bd026784ef7105111242fb8a77d61bf06c2010aaa31a108568883e379a91ddae1a08840568c5a34f55052d212935295a13ec2396d442369243d84544292fdbad59ad2439106086b7bfd2d08b10159ccf0f234647bc045c22046cb4530b2eda6938cd0ca0f547a208478830e438cb10409a9046260f1148327a41a0c8a1f40b1a4b140f536fe5197a4485a90ba349207e5f8af9d46f8afb3a8feeb27a52fc0b8fc8d8579707c512f795133799108fc5f27b5129425a03071f9bbc53c33cf42355cf61c2ebf0b318f8c10274f5098839a07fe4ec23c359e997a28863b88b39871f987308ff69ec5325b69ca02085f91f41da0a700971f08f36c9ffdb763e74a1c4b636552fc1af3441c9cc4c14530a4c0c1c19bd4a505861439b8113815d7485a94bef0a0a42e170c1c3938d5ab3ec78f30824aa57a1a81eb8b83eb9b230b16b6e9e7e40c1739783b8a081c8d8d2e5a82d24b1c31b55133e13f230267c3c6ab9ee6336dfba1b161a3fbce707d5549ad994c86ebdb4250a786dbed9ec315629be66484b7895ce7fa6fc07042fc3ba8ff88db50b8b412ff1a9c5f1898b7f1376efcdc5430ba5cdf1a5c5f1bdc924e5283e32bc3c9a871f03699c1831814178485329ac8a9879accc8e217158342757d1b68082723072f6361050b10bee2f66bc9e23657f17bfd4c766d3f2f136505c8d538191de7000bd8217bb8d55380dbcf4bd70f70fb3f97dff7dac1c92227bd26f532a9add171fbe5f6c7cad19f9194529a9a288d6dfaef0b0e3a47af8ee8186d751b61750a67563dffac53147e170e5cdd14cd4553b31cf16736a195b1598e2abda662c7b6da1659c69325849d4786eeeeee32d66861bbe7b0fb0dcc31c61861d33899e3cc113260668e51c2cd889923a4cb186334e2aa4ca29551327394daa4f5c2a494936accccb55da6b294325e1aac106e48f51a820f9a7437e96e624493ee26dd4d8630a24977131f0c71ed3069dc12a511ad57b7d185751b61599c41ac4699d6bda46d51051fdb16512fb0d229a310b2d21967003123d44bb7d18bdd920961b52d052832ae91d70b42f889561636e0442bd5c00a3c898888882e1084e9c224901f4b581655f07155c6c9ee10b8f28b793492bef1e770e0ca1fe3987817d7454b3a0722273b202122f269313f375127c9aeab28652b4c85f90a8fae6bca0d47a69441d4dddd8493bea1bb858a0cd5000c2278741ba98f6835a142c59126508e1c49eaa2e5494acee40414f7f3a61b589f63f12cfee45cbadc7e08d450e809a66e4124b73f98e4360e34ba7d3fe8e4f6d378994be3d90697c6d3a0f1d689332e8d8fd97e68a4b80574631e66fb898119e3c2bcdd7e60acfd97edc7be2435715f1eb5fdbca0be6edb0fca6e54bcb89bd6d9f319377b6cfbc9b0c7be59c7c615216808e3ba6adc785d3508ba570daa6822899c1c528a6e553571e4e5a8e9ce97dbcf642ca6fc70a5ec02e846c874746934ea0a2692a0d19d5e9c71e7cb9d73cec9040a78dcb8e2a20301cc20258a3b7f3eecf93be69c734e1c293c1499472aced61ac28621692890b98a322557ed118613e65cc550ea214695cb2e5104a683d6124a684b4081ea914568092d7600b44418da0f0e8096d8a2ede048ca0c343a70fa1817e090c06bd8a0e486272f58c11035bc509204174fdc388112a61e9438f9a0840c121495008c228a904d9e03d3c43c3b57bec7033b73ea129626f7a41396eff76cb05f7b50c7b693e77057e19aa9889defb55090213ea00e74ba5246cfebe6c7ec27eb98083b2f7fdf6ed2b60e06116c700192222096d6f5635cca3d297fc716cb2c663df196945fc47e7f651f9162c41745402cf8251061e7f5bd954004fd19ae7735fa37dfdc9816755a021a2068b0d060a1c142838506081a2002e0cd961180cd006c6ebea0f9e23abaf1a51f350fd9c5221f827960175be07ef96354576c0a8a85ffcdd65c629bf8f67a178a57378d6edcb858ff967b514a396badb5ca39c5bdf87326a576b0df8c3f5b916f5471fcb874e36cd5eb88ee9045666666e618619451461923c72e424f0ceb4576ba1deef58685e5ff70ba17260ba564fc2a2dac8abb533ed81ab2a4fa8b2e5a056672b0fc195786fdbc057520f310d9f8b18b215e31c8bfeac74e0524ce8fb0db8248fab053018157e7e39e4f951cb322c72ce84bdee40e8d5c0daf2798077643dceedc919a07eca2517711066ce3efb0998705ba9cc5d2f599b4b4742dbd6c37a5c47e33e9aaf53a4aba5a6c23019f593c275a714f0bd6b996e0ca5bcde34aea9b55fc0fe7098c8b496ce37f3d712d419de88433c13a9108be929a473cea1b7fc7b9c1f5d5fda2d1b5944ad1b81d8d86b0f0bfeb287561b15f2aca993497a692878455f97c479a40404242435fea1a7da9ebd168769308aedc063ba39193e5723dd526b4c0a2db3bb0830ebd9919d248238d94be8fd3aec7bdf669829922f74321ae0c1fd75ff5abf603ead44e05a47e565f06d6f632b0faa1002c5cf58c0e7605f702fd343ef40e401d7dc30f2134424a18e39c11c2cd0bcd3d5869dce3bfee0b72be0a3e7757556b08e7c78fdef8f369a4f4c29f55c66cfbc9324ce30dc2aec73d7e290429b6d5dae3393568c8d40827e5ab5e9f37e2e3238626664ba5ec0bcc0d1b37522ad4163f95b20ee535eb7602cdb2b4eeab5947bb18182b63376bb56c4b518a638606b5d108af5951db0948a8c1f6ad9c099c11ebdf7cfaf467c21b6e3ef93306e8b703f25511d2fcc0c278038cde99bfbc4046196bad15d3a217e49251ab1a6734a95476cd28378a097976cdcebeb3cfae7b6919cd361be79c51522cd384483062fb334cb2775df3d9bbbeaf8975cc36578cb20552c66e9fd88226db10d07b52a99a1d1fd9c33ebb2676711c7db847934a5d3deff9681ef02f88b363a7c7c7840ba32bfc9532d6464c7bd5151b3fd36874340ff82c6ba6fde6e3478e1a3a128ad8fe2c93ec61cfbda110bb0b7b9fb9dd78d426943d9f1fc9503e5058df52883e4ce01ecf99b04973549394c5e92108a9500205dc34ab7082561cdd8f9f8c54b1e5522c325528a1e2099dc89ec3b56a74fce0c2b7704905172e597121154a94a6488223c5b034512cd93627845ea210e2456b620815458b46e604574ca3b0027514451799511459aa5147a1a536d72696e08a6b145d68f87082498a14d4f041858b144b62928ea48802e3e3092729a8c0f8a80193144c2f3ea02892020ceb2389c986d0961dc8a8e182244462ccb0f5b252121c9892f4001f72d6d27cf71119d77ca9a25b9f256fdd83af658fdbcfcb67bc3446521640542ca8403965d3681659ed39c676288d698b72298379b047daa50251336e7d95106c8dd0a136a5c6cf66d5e05440e6d7f81a1d0cbc84136b762af8365e22c1557d1958945301a9a1a26fa393477055bf4607431bb9c117519e644d78c07a023518d8091964518505c308628cb09ec0fc082e2725603db96c9060bddcc73e7a6aa8d6cf7a60b1e85028a39aea8aa5dafd5e75c56e936356dc7e7ea868c894115b81601d6a74a3c53c3a6efd5ae439dad7af4b6aad48b756216e954cd408ead09677469348728175166553e8d6ff3ca64cd6a55bffa353dceac4ad343a590457f52b16f6934545d207206cf759216ecd3a236e5db24a161a41212d1546fa3409ae680baeeac325b8c43c978663c8d2f80fb6986462bacf56d595ec8bef318fe950791785ac6b019e0151546c7fec926efdcf9b726bcbbdfa00a0c266db09a823b40e89cb6e16b577e2d6ff5697e9d2ad74095ed5ffb86b83def9b88dc2d20e86271d0c235c61440c202016edfa3fda623274f8820678c6192760b737762fd62eeed5974cee55d9d4d5cf7080531ff5319c0b7d85fc803a7009aeea5754f7d50e8663b804759a57f22fa65b65ad7c9f79b61a2c3aa4155f552e78482df8a6fec74179bf8ff77bbe00a0c2f6a52dda621bc90457f553296b5f70afc27443dcabff827bd508fbf1537d2155c6edc776cc36b2c5abfa290d95c4b2521424b8f52593b422b1340ffffa2f9cb4e25e7d54dd3ac9c436f55566d80f2edd5a9fb630dabaf5e1525d4a8171702fbf2dc054d1e639baf4d6f3e7c7973102800adbcf27d48e5e1cd60d81be3b80302f6f2a34f7d5c738f9337eb1639c10ce54cad6cadd43efc185d886bf6f0d2efc8264fbbda111f3673172e652ceae26ca08f99faa84f40832c8980922830c32c820030a2775a31c7ca15c8481b938ca197b2fbceaee980b058a42fd0ec8872f32ed51d2fa0054265325a068d7dab2e569cb962d5bb6f460f49caa34dfedeeab7f4d7aa950982f7fc2cf3cca0807c0016012d8bbe195ff5f1d38021de17f7e9425a0ba6b698c31709431c618638c31461218f81057f88c5db3d2ccbe68a80d468646cccfe0a8f1ed71564c43390fcc63e34dc9cc28902017f01cfb30cf0f83e76ccfa88f79a6f12cf3fcddea299e83e3f93bc973669ebf95fc46aa97601e8da56ffc6dfcd74ce8f4111f0d21b182cbdf46ae33c403f368277de3ef24c8756a918be4f287807974912eb282eb38f153200b25771d2515fac6df4be9f0ba9d30ef0c8e242c4937ba4eb2d17d4e6bf411d46927a73e3ac1efcc0c4f34b8ce3204755a8b93e6d1610415790fc918aeb3b496224fef1f61eccb0f16505bf77517a8558aa3c2ebc0b37ee2b47887e141b78b0ed8c6bb9dd8c65f6502db4eee79969685efe44397499001475b271cf7d86507730c14a4f4fa747499a1cec951964f5636b5c9495646b5c9455656b5c9415676699373568669936b56a53005ff00cc857f45da1549c918ea4cca51d66449566441562635c939ab59946b5ec59fd151a0238032406f2aa96e2bf409073e66682ae28a185e3c3591014896958498b2044add5abbb4e6344d732242511048d73d88a4eb6ec3511057e8d0843614e3d7f680694391f65973d9fb1681ece1c7ed04d87dfddafb40be71fbc93e721dd45d0b7531425d4c509cacc4fa5b21cb4a3ca8d2466c5111f3f434f3c0d760add76380504aac908c7d1102756280600cd09310286c0f797f736fddf7c2bcd85721ccd3832fecdbef25a1f154eafa6b37d8cf63803c4776355fc41428432c290289d4e4f6d35d4cd00f5d00a1a3bdac6ba1bf87dfee5044f38a153b1a07e77afca6d61c1397a5a7242748f4fc909b1f5b60c0196774b9197c8d6b01deac6b6104ac7be1078b1172cf638054f4fbd22e26c83d57edd03d3b48ecb7a34aa23b137c62806eb3146e24e4a435a4c434a5294ad1f58fb063803cc73f26c873e416d77f082d295cc073543e5428dac20c20459fc4f6fb78cc908a862c4a1983802c175e26a5f3c8f6ec25f5498f6681a06261031eae5003f5d3746b321fcd165a2e845fb9a072e1db1e2e54b2b2e5421d023cb17cfb3952b7c0f2737631c59d35b44d1137c62b33d05073e3915ab9a8324d58785989072bae52510e6abe3974bde592ac22992417d9c573b4ef9f409eb37dff0c9a25601efaad4566b1e23a0bb0e2f64b2a98474fdf10619d6a0487dbb387dbdd8f7cb8f590709b0065f9f0a0e3b737c4a20f13dc53c1577eb1ec5861af010b809dcf64a8633938b59e40e02225fd4a5bf3069be538250b2a080090223e89314218a1c1e005f1486a713f5e62923089bc6493d216407105f974afcb4a5a80711d91f552ad955bdb346d7bda59faf3b1afd8d72e5e98c7f004c60ec8f559e7b0a670ba0e7e0cf569fdf940eacf0ec8f5b4b370c5f163988fbdfc873a31d0cf5412988f3d90f958e701a19f750f57d9c5a9fa1faebc3b1726c0ac148401eb18ae64607d8f754ffa9935ffb33b7a609985b1266fdd35db54dee413a9ee2928c582c6cab67bda226ae145151096000921e44043910c864881640a424241659452ba515a939e98544a332daaa8e20b4a25d502884ae6b1db996de0acf9940e6fd6ce10a2bc6b615cb6e5a995b106ffbaaeebaab5c2bfb816209313a624383eacc484e43a4fe9f9895c92f5e7ac58ec790bc25d6131ec7a11c3da1edb097d02fc7a75f063e1c2a732d73baf7b15948f5b9388ae4d5b529710c218a54be85d8c526a1c690c62437798926908a1162b841036cde060fbe73f84104aae910fa53b7c7b196ab142082f29aa1f0f57fcd7eddb1edd3dba7b8cd148538411465abd6c679380b3b20e87088e093e538589651b8cb4fe080244cad28f2040a42c19fda09ea66d8e9259b21baabb2be438887bd89642066e8c3f8048f1c69e1839317262e4a4e69d3cd4e1791896b991132389035e829059cae78a71cddab8e615cd3e83dcd76b593fc6f9ecc0c1813d3b3b15d6895dd7a7f040f7ea68b69a873a3c0fc3328f38646f658c38c8a56b8aaa1359590405ed64a1c3fdb8c5c449f17760b154b12a150b338620458ad7a6e8be02881bab131ac07a7dad971541b0f40437a60f2a79442a56c10163657b71adb2835bebcbb8cba4ba4990aab5562e86bcd62b74b8b5d64a6997ad2035431fe1c186ab030f3e2ce121063fe0810918786d6a23d9f7fff00175504322e7f077bbcee314e99b2ccb28a793f3eddc0d09026854b023ce944cd21020aa51ee00502867004ca35c017ac80720fa48e7e0031099363926f6eb27cbe484048fe06a89e41ac990237cb3a482365235cadd08808800ab259ec557fe9f7729677325295a42391d17e3825e3e287b22cf7a4287b2ca8299c6c1a72cca49ce6e3335b69fa9820c5dca2794314a9871cc7ae19cd52c9a2a4056071089e0fd1e6a22a873759211d4615a5a4afab8c5fcf5d011fbfe52c55a16c06a860b8f8b62bf1aa3512e0030664cae0e003608cad5d020e4e5b32c6bbf2e395f38220f25c7e4a5bbae6943a31c099fd46d5943e17a89b7135fc19a238da88b8caef7587ce52b5f591c1ae546c84139115462d0cc689453516e0601341ae570684a502e95230ccaddd07ae834cad9782e4f246894ab7127c7c47ee69b2dc37e9572328f71414fe61379ce059ab5cc3886f5e282883c8bb9005fcde5873a06306947c38a23c01fc52df129bef28f61824b70e5444986409d6ed198c07eb5048d72303fb05fb577724cb26747e2498ab6c83119e2393de5e5625c852bcaa1eee4985c8f713d045744ee258957d7453dd4443d012ed8e1793bbe2795b2b6b9b0cef9e81b48e3395e73bd4b33b97fe1c2c21ca711b2ee4e4696c1b93939843da7f49feeb15bc121849d4ad5faee7fa1b3bfdfcf85ebdd06d8861f6688ee6ed8e1e8801042088bd8d9d1e3a36fbc081a23369e02a8c44d1825b5646a48020004058315000018100e8604227138200d345d15fa14000d6c94406c6034960863418ca3288a6218630c00c61862883104208354d15100cf6d212c741c9762cd2af6710da9a047220ba34a2a266b870434a88864d82015e63d5ec866a7a81e0732b49520a06dd85b492f7dfc4fb81cada71f7910579e36ca0d019e26ae24cb596810517a1fcc1d32a2e72627a8f4274fe0a8604aee7b3e6da7a2104b78aa2079b4c9f15580e60f842085cb633d2d709ca0f017a8510b4ca65224f225d4d13f66b52a2b8df981fe78fc79ae399a8b2994e90345ed488f23c32f2980aaae9e73c554b74a4dbda8972df2d5a616c3c6cc0e9215081ee71a3d31728b3e365da296c39ffb25175a3d8cd54021a3f860cba248b30c95a9c569bd0004211643330639fb978de2847e41518d76c48624de52d7af9c64b9a21233f2a3ab15c6b87a8990086e4c525a7a3697640153766f1088416200401bb7bb1ed40c4f68e6e7360898a62571777013318dfd77fcb2db2856f2ee0db54c4fcdd5429acedc02096603c4ed45cfec9781077e8c5d1765495622c8b486f39e86c1f0a70fdc7d02d7d98314f1949c345f8eade16092b2d2e021d54ee44e9064e3df7120db8652f3a4d383a98fba6a3992d1729cd0beb8b2536774178f7eb8592a3564339105c1d400eae2e0652936ae717bd3f20ff6a3d7349c0955b40678e2c60e51343f5b7cfbc9a15d9405c805c91d5e1bdd94e546b5771b1e4715d3e3efacc6f5c8bcd070ae2e8a1666464a6db08d93a8d76b2abe5af07a744fe630058801d916d9237e3e4caa0bb0ec1c6cc671c27f7e67ece190a8f473c8213b507c52fdf84d27e95e961a0c47b3f3790b5a07519b1d25893cf322dc364ed60fe170fc70b0ecf4237a0ea2a7d4207d0dcec034f3ec8c6bc8eaf1444a6e4ea2daef13d4a4696048b12fde22a0c2ff1d6582eb294c888320841b59e21cc5c1c8af6e20ee2cea07ef1006e2171c2b00df10723a50c093da32de32c79f7cacfdc38b88ae90349540268994efce5e9acf7e0bfabfbbba652663dce0abed22b6226b168e284a68dc24a14962d41f9367e8563ee5154a9101abba1adfa32c19f4ab11d5f524fed4c11e9c6001153ed0c507d8c781f9616eb0e37d5eb9185589c17e64b3d3507289f8915060a2def8c51848f44ee421afbb49fc26c0ebeac682885a49da702fbd9597ed2b285d66c7e9e5cfeed3a97ff89921732aeca9a76ade3f85995b99cd30a456110154f9b137bf97053a0e40492140301a0138d2f396b2688d262591609aea69d489f794eb4fba46cb6df23eee4b2a0bd19a391cc1649de293329ea62ec6be0b5e79673727b7c6dccf3b70986fa36ecd11546d5dd6ee3555f6a80862c94155bda3a11e93e26c90eb1b21437588e7e1d9586948806ca9ac7965bf84576877bcb3758e28446813b0c442ee2d40be8012b978c2e8aeb05bb3438c01188d703831e6d160fcf9c954d48f0b5c4859b2a7643117003115cb3633dca25d556f7284d13247618d64994b321ca202b875426704d1c59ac573e6ef7b7f7860187cac070f457caa2f7debf79ed89fe5ab2ed1d2b4fa1c7d00a0429dfad5d459f607b3dc30964d91504cac406b86940bd2ae7215041dbade70e73225552836b298290a6074010ab4b68de6d7117c0923a0006405ed235b862064f4f5c91052ddcdac073e64768c2af66e41d882a04d98a15ade024fa77fa738c07ceb3eb63a958fb8822266756d5fdec53d59d3878b48895486926c9cf2e0f6e98f01f507ce994025221d61fc58a30bc45933e8268f3803658536fa649cc02975ead46412ba41824566f46b8bc9fc4fefb9d85b92812799ed68a37dd5f7a84b78fb4ba0f619084023bb93e17ab46ddc82b07373de6cdf69eb0661b2050e84d390f162c285b3cbfd87f19000748661bcfa12fb9c927f1118ec1e6b7be016e952b827cb563d6f9834a7e480b5e25928db1844b4f06fc60962ab56b1a9024c2943923f61d8d4a4da0d6b194c523d6f6d0e65c471dbba7578235d9bbc91861c76e5194fbd1c777e72909b633b76e133284e60c743df1dcac530f4b01dd9510cfa916b2b431bf32abe17eb420d09e6e40d3fda3faa7384e14299221bf07405bc385c9ee13b17ba673c4d07875fe0cc9246964edc0ff759240622ea97002d9e8230d42d280802161a9b64a4d3db0f925c7a4315a64cda588218484cbf9020933badc965545a4f38bf7d9b33c9db5dd0737530fdc722079b1a19ba51d815c965052c32a26ef606f327ba8a82d2a7b81b03deaf12a0f21f5937039a88f10a998af99eaae17d09bd483ffba9851eee0393ead4abddaf7ce3a4b42d6342fe4139633d07ec2dd6738881e29853904a4990b3b9d4cff659eba43f400fadabfa7085d8a7cb37edcad7bc4f15b34a2a1f4098a4fcc6d2d39838a5bc1b34c7e470d0a4b77629131770329859fef5ff461ccb0ea2523b851e3a69e5a824a629330595070dea89916f13505794619ab8d6f38f3e5655a8e0a09209ebb43f044209bc0ca30a983f9e185c23c852aa009ecf722b9fa7d6b544876504e2b36a17d369cafd91052df18dd6e7277ababe51c63941561bc7d826f33b8398422eeaebb93d95403181bf8a565bafc282c5f8c6e61c0674b5be4ce5711bbda28b6b6889b08e8d0db36abc5cbae371a6ffdee1abfc9ac61c35e9a73ccd54e61514baafb1a53e2586e2094d745672fe584c9ce040c6f081790b5b8a3284459e7a51b15ed971db254d56c71a262b69f0f3fcedbf93390546645ba76a4ea12757ff6ce43ceb313fb929d14807a83ff9e94b239dce37ff5398a17e5823ba0fb30f93b76c8aa103960750f9b8d7c0c22ec949f3542210b540e14af344dd25ae0e8e0385fda11fda5aa270c6a4dcbceb8fb99cec33a5ac765cee72462d7be468f3596ef22b2330c644242d410693d553c656325ec91b85c15e0bb875e457816e0300446b4cbcc55d00bbbd22ef6330350802ff090c130086c0e217f35706f2bae3ea816047d24ddb59e0f3c76237503afeb7fd599ad12668043de3d5b77692554fb1ab82374b913eeb1678691d7b2ab6b19209dfcbefec7c9e40644b8448f6219afe645377b10c6972f225e68c2f6e93e7b8aadbbe29f40eaef477fc7656caf9961cf0b2de61b24bbee42c9919c61433aa0a094fe7439a0546d68c45099d20842cd0d761a548bea3c545931b1060be5f7a5a13ae65f849036639a2c0478cb45ea4c04c0f80790c0a90be4a089110844a995bcd036abe1bea060ba339086da5e6e2067a62a8f8fccc81e6f6375cb0c69a838f532864ea2763dcd3a03651d7bf3ac84c55d60de16f0a6930aae7667285dfe4814b47e6c10a337deba6f99ff923f682d8265a324b841f7283631a376ed282df3c087bff6c4c7a84ff8bd5c7825fc85179b17f156af734ad67c97919417805cee242f205d0b270e2acd09929492e5359caeb1f5e8007cda7a82467e18fd719de6abf7661b92bf3239ea664d18d9e359b8be09b5b810f1ec53e49f645cfc1adc02450131fe257b792213902753a96a4661b34499cf032fbfa1d841e78b32c2f6ce9e5dabc189098e4499feeddd5d665a5f2c9c1a7a7500f6e546489a659e373e183bed1c9280c58195be8d5a677052b5f490fa9d4f18e510d7232be23995c71482e947e045a3ea3580659916c0aa7b2b1eb093903503fc3600f282684f7682c2cd80a91a971f51bc64bbdb3515ba870cc45794d24df967a80a1d9800b73b28b97cd62bcb94531f8cc2839e6e4d70082074c9ee9e044aa8f55523c95c8700a24542582f253e10638b1b95763d632307fcee006b377a0e0b2f3e4acdef43a8a97ff8907405de31b6f6e00a5d1cc14f6d37ed2048f22e76332395bf8554a1c84af09df5d4247b0f5af3a06fedca401134e86c6275f58c236aa28f49a9f7b329a6e7316746754421e54ac04e7631bef27a5bae0ba7c810b25e8b816c9bf0fd9dea3f0d6e20dc7719ccc35202a0a0a9fec8a541be38721b1e48543c2c5ea963ee48a377ed25ea5339d397814501e17339f3e7c09233426c7e8ab0c82d768e8c3d5b5cbd4d8b7a89ccdd39172df7aed44f2fbd9e7f99f549b25ffc17e905abf45301be893b7de0daa959536aad466b7abfb84a59e1589aef38593a9dbc2d5a6008fbc4f77566a439aba00960b7a45b2f29746a2d19a1e51042dedf488627cffe5eee11dd94b1cbca173f0ee70c72021ce4910fb754a1e220d58f696c406f18d7be1a28d9bbc4b8e81ba0a00930d2aef7d9043bb541fc3684a8edc3f5e909eb8045a70910cc9acf03139c6d46e7c54ddaf6700dbd06d5d1848d770e6c05e07ddcb7626bd89e46b2db180a37f8c3cf8b64120cd5088220b8ea147c73e1892f05ff622c86f05ba9a93fdf89902bda9b5c6ed485e3710fbc89293656c6ea2aadf22bf0b5dbdfdc8f05b65e2a1cf0c45b8b3a515c412b983a66a84b3ec7d6736fa676b22f66968be2273b9004b3134ae0ed2ac2a07229658dffff9115f6d27da1d8da6ab3197fd00a56c4ff4e0a98d492cebb7a68c90464ab51b73a9d168d999cb2106ae14abc9403348f699cb2554970a1eebbf5de525ca79fdcb0502504fd4e4cfb66916e95b73c140b8102a48abcb7b806fd8449bdbd911f9b4bd03bbca4797ae69b12a6dca17e8b50a386e4133fffe50979ea635eed5064d0e7bdd4c4899c25720d71be8536cdb128c9cf77b709c50510f6b9812c34254be0139bddf73af6bd7368722f845306b5937571925393f5b374fc39d23b8a7d2db1db2c29874cc1967c380741a0644b4d282f0ca19cc4ae0c9018367b2090b4f71f454f6dc1453dacceed45375d77f468c4acd72fc96831899356897838251464be7e5a1928f829e562c810e58321eda8d572cbf9b0c4f7478a370507293c6b828be83d9a74099d60d6ef5ff0cc6abc9c9e8d875c23da133fb06170f760df160be6f7fbe9de2ee4fb017b69b21ea1c2521ae88180ab6c036e21d4c86f04b9cf5db88062e674faa204132cbc60298650083a8308b5516975d0af48423ad9bc89e84528c6ccf6b131ea38d4a09f0b6177346e774258de6197be8c579c075e4e9b0c90cc68f4a263615b597e2a97d835dee306d725967886a0f760a8defa8580d9b509372b4b684bd66d7312e06748276e1c18ad3f19f1056323c743c2b3cd88edb92e541b4273cd805fe6cb03e6657d17bccc3223bcee7d929b8987873ac61051eac2ef5087bba5597612a0bb24b3bcd64e082bc2b785522434e5c90dccf227fdd883e05403c169024e0c9958dad6da792c88d30e7928dc61ca2e0a8e85ff8251f9c424b0026a984957510f35440d6f5580693df6a31501ea541e791496940dab62d7fecfc38f056d978a0b5f15cb4b36019622795996facb2d12b72e14324681a1c1718b5352d78187abbdd559d63a9ed7319e58004ff0d7927d1dc1e52a3012e2de768d9726a009eee2f1968fc611a4748935b5cd7848feaa1d2b6cdfe489a78a409f5e62db5856f1fc4dc14166179abefd2c3450927d5e18d380fd8a88d5d94041a5559a304736393b602ffac860d1d47cc96eff83e58c0800743d8b5f87274484e0849cef47b4092d46e8680e4a0123b80a5f7c19c15a673094c7f465c4ac0274a821b81094342b24ed3b44b4e2dd0d595c064b80c179a745edf1ece05e075599affb68af0fd883dfcb3c2d95252a06089eebf51f73b8ee99b485dea7e70b6dde3f47066131cf5d35da76c82b13ddd33938fc9ade782ccf0ee70cc4df54e3055dbf27049153bda9ac2daf912f2a2a208c779ee6783f35f3b3a051d39614ea7aa4f369572293677acfb12cec122df20d01821cd4e36f9d27bb8255811224afee4c4978f7e9c1e246fb26083c94985a3e000742b6d00e18319339d14b1e7ceb280c0ec0489edf2f9e58a6a1fbe644cfa208318ea6dacaac7cf6199416d1b5483a215b8d5e3b10de017e651ae779c30f095888d830c21c2a2320d8ac30444a8dcc8240b37fa05061ffd2935b43d5cee535b984d0466b9b629df22ac0fc9add865f74e6220d7f155be5e45cb1eda5fea6d523b14c5ce326049d38b1bfedeb104764f32bcbc320c67c030466a5f1ecd520133b1e7802ced36944d03b42ff18710f2ffcf50d0048314fe6473df804af84a510cbee83ed974a8668c9033a1bafb41c91db9060019be45b9c8c17bc42b04b49350369b6a1fa18f58ef2d9afdfbc4fe3d22795d90a53d70858012495ccffe27a809d90cb31882976251a1b5f831a65fcc89bd6f4aee938d0e7cf3fc6741438f7335bb2e343998e35f734eb0b0cbb2a9cf54965191e07083df7f8d2e6c42fec4429b6875b31ac0099b23978f249b979ed7327dc6cdf47258c55089ca8ee46e9d6167c5fc1aae281b4a06225fdeab50c1c216ec87033b3f6eb75abe540e32ab252ac1df4215c5a4752b58f1811818db17653da4f7c5d508b66bdd035b74706471303ab048b78437bcb91b8c2f8dceecb329c1f716ccea21539064c01f1a06d82b38b873b108fc031f1e2e76ecbc677ec617d270f1dfc8c6818745f7e77c7be229418151fb6aea6edc0025611968a44551cc114880c01f4c6fb9f342bf7879d03c8c8057ca661786b7288abf0ddc8eaacfb4810ff06cfc65ed847266ecb7942fb2fb2d56b638ea9087556b5df94426b1437eebaaea9948f616283429feb54f2137fd964e3f21a297a4b8327ac94c23d0420df3983ed523a42539baa50106146d86313876b6c92916b931bbbc6ed3e9f63d1a978304c776eb043049ba389bdd9f7551e3d8289e575d92a781b27ac3d2e52b557470629b11063fd1d172def6288d631933bc5eaaf9146470084ab1721fe14a75b6d0292412bb64204ded719f58e725449046a3cb2997bf4ce14ae4e20b8c52e50723c2aa5fe24e4b7e80be434136653d8e61333ab402893406292a64b1ac275641a4f97c920c3d071044e9dfefbf471bfec77d8e2b853817ddf5bb547755d450e881cf6a7c07aa60a26445fb072b4fee9b6f63328d1f59b5e0fe60c445b6133169b786d6e4b6fe545785d4b9108ed8b95a514c7338e41218efea00823d656c096b9003a40bfd746b588a31544063c0fa23df7d34b512f54c16c8cfbcd50f55060f404220439648cd2572e987c7980c200fc4f2a04a8766a605f635958d40cb331b15803acc0124d1c54a78d7f0e81489fb23454554a4f1dc81ed3e40097fc3138139392be645a7ff9dfe0a22fe30ab5f209a647464c53754f730200dfb304266416199428a346b7a248b26af5b27b0f82c23e1da3cdc93291b3f290010377038e078532fe6e8bf7067a14482bda3a519a726c5bb76771910fc5bc8bac4115525b42fc58001b393508977462ac7ed70fc0e912fe65d50a91bdf56de87e44be40f750903c25d0b756c10004b6a1f24d4eb32688e88c9546613e18cfd91c4b1c31efb47c93ac6eb6118f2d1f607c10dedbe8999a41b19341cfb2b7090d5bb02ebe4af23177483308a385cd9e12dbc63f12e56051c43a26936e01d6ec966470c06c839452485721c11287b94401ba3ad04d5ac128791143a7b145fc7ab9d28ff56b7816610364df2df509f1aa8bd3dcb0dcba5d1ef38983d88012ef8dcf5d560898e517a7c398966607874476ead4d0bcfd09b8b0ca4a121187aecc09f3138c520d57ebd66c1f595d99905624f4618b07aaee2256766946adade6989aedc0dceb4aea10ac93ccbfb89345db65f27f9495b18889040d653a0c1c0e0f4a65fc35539211c0f8fefd176fd03a829a07e455a713058b5c622d61229343265156a1ab1b8b088a310ef0a7be2a78a92bbe7f5f14d71698ecbc08b71f4ae1d3995ed95d17532b64074eb529e72094cb9039023219371c75035dc67eddcf0da246e41eeba8b21c26d6e560bb07e63073bc61f10544152d9ce28d4a20a9ed33ac952d68ffbdb610935ad065083cc5ea47dfab7c0d5114b1e4202d641e0d2fcd45bbe82abc02d7874b38172293e676ea2397eaebd64b310ca632fcfb8e2bf90cf19d2dd9e754396ccfb8cc690361b92fe37172ea23aaacb9737cdba4fb2b07880d0da410d342025a768df6053a2e5577c46c7a9177980e8028a682e30705c61572a91a1cebe09a1c8cc58a1118a0b9a88ed256a50b37e1d5f473424268d50ed1a587cb41240ffcd4fdaa7359b194b95271190863b96c10f7ffd7988d89c56ccf8ceec91f1afb51af4b4726d712b2605a545b109dd63dcd694e0e8355c3baf0c23c695a50cdca08e952bc22ed83db8cb57e541711ca3b5d9e8209ea08bb64b4c7ab378c53c5f1e4f571a9b0aa934f6fe49696c5b6b5d2130757bd5b611d960ada6e9132e8de03234dcbcb1a4039255cbe0a5f789b190bbe06d5c4a3246b6b23ebf40a2dfbbf396c12448dc882b31996abbe89fa2432ae604c0a4b6c2f4b4b22a9f5450acaa601a75d81227450b21a1573b6c01ca3bf0753f7c5708aafad5800a043245bfbcd565ec351d8cb028469a0235ef88eaf71a32c522ca9d532de7befa5422b3259be8bf657918042aa733e88b5298ab2001bd42926a26df3ba6e5f569d06a4bcca592340e6010d6f148383c0282c81c31f4ff281fdca00411863ea034226134ef5004bb978a5e4291305013b26e172cbfff24755397d88cff05021b5f82180da7214dbb4c523e444f22bf4558dc8cf3103fc4581d1688b94c877e9b10f0dc3e74211a1807a460f81fb8a477ea049c7d5959819c5ac5df48c730972929417104303ee5050b82adde3897a70bb4bb8119a00084288476227c746d73295047d561d8fc2d85a7791052b6e298670ea848bdb883e0e9e873b8b5fdaad4e030b35e0b47abb8f62634443dc6f67cad0fa33eea3bee20327a4a7b6b9470259b9808e4e0652e055951e06fd9ab662de9eb87555497d471638095c2721de0e603c6d5a8bc1aa8ac7ef778c6bb8a5628490869a0793a2589684a9e622e3d7d318ac77e5eb1780c57f264963cb99ea46b010b042ca16fa71c1b1b07f6566d1b78225b65472a49fa3a9a86bc44f42a78d897d377c2770c343e0b2b31bda94ab5961fbaa09e4544fdc7427f5a8d05efab2268071d6fb325d4f279cbc3bfe249be83b1a2a5852cc2a166c788d71bc57c94fa873634229a12f70a7ff52811cfe4090115d76bbc2068076074a459c675c1cccd4fb81f2f2005b9bd602bffb3c625493361b6c5a776bc0aed5bdc4828c45bf25d1c6f90261bf97b3466d2708258c7c1cff0d540ab4fdb64b67729132c2f0f12627519263ef2e02a02e70997364e3981c3ef461c9dec7d32921a04f4f32c789ce90ca62af7057cd3e37a3395e6e51ab0de94a0e567ce0bcd087a548d3943c5402d8c82e2841ab34be661066905a55129711cf3587ce0700d0d9448d3133ed5f9fb4039af6c7a20fedee9052ad081f676ccf2ce8b935101d32ac29293a46056d7c208427151a50791a4962590d90fd72482f83d99af01284d6bf708747307dd014727b8752fdd0036f57076b859774740723e496273f55d5a4716a2ff210e59d04c8c33aa68dd815abc3baa3255823b75f903e15c5da68110a76ecef9d027c7eae026efbdc5409ad3ea9ade720486ebddb639899b9d68eb76778372e5181660e908a22b1c9683ce27611fd8397165f2f1e3f8db1b9d6a203bd1b4cfe93cdc135a5ebeee48089f4ed0d2edc30d097b9c770b905954de742fcd7dfc7fa042f4404d6fdda0c6c13ff7aa47acdcac7b13a5b45e9e829a2506ffef0c3526295dd295c1f8d7db17bce1a450ec3116215e4b5b13b19cce8fd83382a82ca66f2cbcf89067a307b9e1520d3bfcf43f4d8fd62db5e567d57a2ea4f41330844536dd22371da9e7082e484a6de144da05d107e98d1fa14de75f4b8b192c4c1b12cd3902dd1cec97c30fb425dba506d7b0eca643d7b1995dfd7c58b5f0b68a10756e8d3056834722b607680c2d4a871a449701eef5db60366535fbaed88aba51a920ebccafff24fb4ddb03ecfad695b245f2eb61ac1a7b0f572f8301ece160f016e92928a6cdba1f200c9bcedcd7217f3157a39d1b9f81f7bc7f4d2e5593644d7c448b7d32ee71603f0f8cfec05c23d8a8f05b135d618fe6d388df83a6fbdd0d8e12f1a398c9c8d6e31e10a93dd7ee6b9e4bdf48ea16b9f43473ee9fc12148585ebbd641eedcc7940b59d7a57273c7615f5233ecf9bdde30c7e1fedc50467237971977b52d6d7eb47ceb62e033c3e018b91521f63a6232f07499ba4e24ec9dfa7cb3567b61b662d92c45774954916b84d794a60b8e3645c7e24b929541e88a0b7f5a1853755fcdbaf48b1dde695784974b6ed5217fb82cc605ee343e9b2b72ba84037ed25a48ff2b5a052a2500e83646766e49ddaca05f34ca15b3ddfc1d626e67cab0c7446069e6470ae4bd88958077c2ae27567eb89019ea0a0f243327ab3761ab2026d6c42d29d2d49802649738f11a558213db3038b459ee2e749e1f6b1d7ca80adb5b059e81e63dec17be2ada9f6d7ccfd8d1d4b3be7dfaced0e79f53fbe066c689efa178dd51757d4e3e4dcd30e8fde325e3fb01fa1b89d032df1384d11d5d456857a45b4337fc760d014dabcc4ee5cf8e82b36211f0f730d56fca141710bccebb8a2d41eb4fdebb67f231132ce2ea19027c5669582d406dc2ec65d6c8c02d939ef5f5466384ecc6b29c558297a16aa4f47446c96baf91da2e9f5f4d73bc9582de5aebde77e3494c4b814bf1e248b597e1937b1cdd48997392c73e994d46ef5e66ef415e04d2b69f352215d6894a516589675a6b1f12a6a159c233a5ae33d8b9421954ce3754e0d0d0660336f959ab75adc1cbfd2ad98f93fbdf05eaf2274cdf8dd79cf9885f783873ba845805ab4db2325d2e2e4259dc79b5a3629a318e9de32935b703edaf6e92f58ac429743d8616034e1e79cc438d4aa496e5b3dc584b12ad427c0ce692fb0f2bc03bfb2d08eb3739427c7ef3c5070d31b7b86927242a31930ab13a09a5bbd65a5bd7fac6af6a2f6d41ced85b1ea80c8d1cc0f86cebcceacddd4631d38847c4c0d2960a3ad2c607d8e95b9f578b7ebab70669e91f4d82ae4904444cae0114e9d822e84cff02dd1f7d2ba422a5c64867d089a93b14615bf4ed57f8080e46d7037b88dabc0be6bba631932bd36b4c30dfc220dae37c151d7a79624b095ea4be7d14d9e7e4481def907c2ecbdde4a4bcedd2d4e0bc4c88d167d515173a27b887d1b6752016731dad641b5adfaa0456ccdea9a62a516449d00edd6cc3bbd62ef8368b889a6508a01bfd033eb5d95a3e101cbf929fca475ff2979d939fa30780132e2043b0c0582a717062f86231d116a324f59f98c61219cfbbbbdf8d28071b1884f0f14cc92f63af2a4d8a8220774c83b503b6d9e379fb1950f76e97114b371a606d97cf2fec038b570785db494584431d85af6384be8ead4c55dbf4beb3106b64d5ea7d30e12f826ac87841f4dceffff414352f78bfc51c4c47ee36b56196ec9c47b213655628afeb8baf597b0da1ff9ed0dc3c914509ac458e93797672dc901a3901808310674ce12441d430c243b8af25c4bfdbed13385904fa0c362b7f4ce6777699cd867d20fe8ebfee60ffda60344958be6d5b4360f0a637e2c13ca5eb513417e3b35a729b10edc3c368879e86b5db5a7c72ca8e7f76321fe34d5c79709daf13659e518e315a4164ded3b1aa1874c4791e735e16a1af9fb755fb865c0fe5fbbb96343b8f3a4ac09b37e51098def7efd594a6f18ec81a58bfece9a1547bf199207fdec6cfc1255e82630f36b0df0573d7b874cbbc2951e79945426ed9d9c97dfcade279b765c4742855742ce9c29ed24161deeb95d8375531af325d2c5bbec7024875c04bdb280f56e4a5382e757ca72791c249c0a6231eea3bcc20de2a5d017e2411c7a9482eb24c8aa0c7cd526e91b3f8e9406b83c3c7d008158b6187f6ae3e93302ae485ddc0c4ec69ec4518e564b871470c76115858cd5c6dbd834baa54bcef0e7435ccc924a5d000a2163ba4c50f917bad39cd63a222f6791d1541708a92d682c9e49896ec20b8c408e179b4abcf57dbaa4c43aecd217685015b4248de217c735f548906959c7a07ac894480a1f15398f7bd527eb38a7996ebb1ccf23b16417a02fd347daaa333655f35247788b23229d1d6cee16a5eb1176bd871144326404c42193615dcf673c2588b3dc88ddeccc9f2f60fbb4b05b6b641aba330a23cceb15a9a0f4028b10d000552533736b80d8f94adc98e29546fda618fccce6ff34f1e550475ea367396a4112465e93d9e37469041ce179fcc9a4c438a646281a046664efde3b5ad7fb41ea45d47a0f695f86ba8bbe6b865777c0962bfeaaade1977460b7e69b05943ccdee0a92cbb5f4163f1df6ed690105a8baf48248c0a99503ee6fd9f06f0a8e14a1028f632443f3e871a2a68737a24f745cb42b97813a63d5e896d6315fb2ed76259e55b6c82f606b421937e1684db84fd8dab4deeaef7c6092c4fbad240dbb978460e23f3d014a73c79b8c31558e144d1eaceec96f861649ee3b511ef1c15a0631870d3077bb68f3f4540814ea3e10608f36058c3045f009f07198d5e61bc2e73de833fae0bc87113aefee46b1c1fc74494b9ca1bb285b859c8b3f8b69f27f4158445f354e33aaa794f918ec0542d0b7275afd38eb4b299abd9da95aa4e19ba5265f72160f7a57bc1b1534dac21c206555ab79d14ee5c3bce98e12a0938352b4468cb52d1ad5879c0c360238ad68e3ac4e4cb3ec996e1d1ee0bca6d703f61e49b86797da89d7bbec410f78bfb451ec4de2c1548c358764e0e8ea1d593577ec0213c6b97f247968f2c57218cc609ebab4416238848dfb666820ab980ae2cd7c1cadd07f05f1981c227897db51440f6099e1e8d2be958e1383a8dfbe69a7a0230f7a34fb5294ddcc6083e34e361582d55733dd50938906ae9dc91eeebdb6523e13c6f17c12c689d12bb5b69892ec10ef0044332f86e614e40e1e31d87896add1e4487228a601339131da32a092b036f0ca99ec18ed611d0f73b83479a1a3963a330ee29f15aaf78b42f97a39c0a2b1e17f35689be66bb7b404c59e6636eb764c6965d19dc924a3de913dcfb1a3f1b9f00ed2fdde5553613ef39889882d86eb361f76d5062906b667a002f9ca03c2682024a4b9685b6bbed4a2b2a9f570897a53b94499f6e6d21dd61eca6445f549a096761d3dacee2d67ed851762cbbb81a6ef82904da65b5da50033a329d62652eb4679e0f8dc18ea7c5a50404574319ef9f87a79a67f25f881302cf6c520e4c26f6e45292e3121c24e79b5b40176d3daf63e0a4c15c5ff49a4cbb22739e0ae86a9616d3cf851bc90ed928941a433215ca09fcd092367428e9e3b5c4daec9915a5185fd1f88578936f86d294772a7f5551fd3b39e3b9017f3571f6d2619b03261a77710591a3d0c77607533e66ba5d26b709aae481fbc92a05e4af1c841273f04def50377ac8a925f7f405595cd23d3ad2893fa6a2141b9fae0636447f2754a1be329b32ce607a758a0367564643e9c617fe453331e36abfba59fede9978e4a90f6e29c633f8854001101bce20083cc3807f3caeca63714db9541ee99ef1ff0c336909209acd2ed0f232dc29f78f7764bb491b84c53d3455a1da37a97cbdf7166fbcc73b829302be1f9bf234481339cf833cfc8e994c39510a637e626f1b72b8f8b5cf313e95be5d10300901e1feb09206e51faa94227bea497913e15a8fdd018fc2582f07e2878c4d24e29b9ecd72097dc4cd574328aca1bd5201ae4ceb25b972c10e3d6ad9714d5690c20c03c2ce204de3ab2b949f2ffbbf7e5811d21b597d4278e87c2f671ed3b15ecef9f63bf7b2c32c2eb4d129189b964afac06d557886406d364f9224f6252a3562b60b960b437af4a3fbdece3e9919d748a35890081d8f7c359e7985522790bc2e8fbd6081560d37c69e9dec93258e434de1c0262c7e4e41de2151cf2ba2b7af765b8065db15f5d6c0bd3ccbad46a9efb13d06a97334c5a7d262309e8096f1b0d882d5cc8cf64d3e1d0e84308c872a407f3c617e2e96c5f0e6cb8944f51fb8c3380ef6a1d2732a3f5c595f2f86e594ecab7f502479624f79b300f878a82e4de557713f53b69f8225aed45836b46cbbe410fec329910690eb5c3b75d8747281bac443c7dae474ac18bc25fd36c2591dc51f8c7d185555ce7dfa77757f96b9eed06c967669491784d11f4c710e5918433342d06acabf617fb861196947c0f3002d5d039d15910456b16752e388f258168b44c0331996a7ab9c7f737df9e3f250f3b7ea095fa827c606b0ba46ea1a6dfab96a10db8e00249b91ec76087d0319e738f0241816e053e98974111621cc785217fdb1d167c4a164fa3cd3b2d2d7fc81096bcfab24978b3ec6b9be8381a2fb8fb76c0ca860960157bcaa442208e4b9d8892e50d66e94dc18bb64ba1e20ac1256de5e8ce44f2f173997c60e96094df086030cb445a8e4b99eba757285548e42af772a930eaf6abd7111379a2c2846c451143072de2a14d1035400385c477f38ab6da8689adddf966de5a9409df7abc293845fac56f570819c043950691c97bbde06a1c6e95c15d8531276c20c5c795f2265623bd25a80e0e439c116294539d80669058fdf6a57843ee874624b5a461ce0cc77c2859e19a201b5c2e147ee496e7ae474f1186004881ad88d6914aed9b60052be310a1d0061d7a462872f7218f5c25c1296a93b60c35cfc09e2df6e02a30c81900456e8fb9672c2661e03422db14bcdb0ac182ccc9d28aa7a9003c5af4c61df340299b348745b3860d08e462215d29e24d5d219663184f58b64182e0512802e324c2c508eb14bd5735d3ca44fc542df8a08abe2ece29cb269142fc20ad33ebda3aefdba484357ba095650b30d28e8caa673a0b46256361d9aa922bd78e8ab2cd62fbdff9492c1e967b2a14810b6d44a24f76030bbb73ef327ed9478b243af939c091881d44ca283f892051ddda5ecf10ca0598f425efc068d0f1f330b8190368888aec5edc69970f824e7bcf24926cb309dddaa5dfdae70e607b41f5d4c21cd84e5d2b5d3a3e6ffb6ea1a41db07730170f810158e2a51ddfe8a43750433c48a7638ff1021ea825095afe23ddd368e86b51215830bedf1e0461b073bf18288df60a6b24605db162f434b9d9f92ded6f69d1443ee41bcc04df4fbb85e019221923aefa352420494481805f230b3a8d81630c5e9911d4a8cf270ea312bee388242bb822e5016f2debfd895d4a0bdba686e83ebc98232fb904f600404ac350d49c24396501dfbec5d16d4b91329ad0489d7635ee7f031aa8197629cac67ee5183e66bc2dbb0afc2ae46eceb5f695724168b91dfcdaddc9d72e4df13cffc444be3413c0048174635d68621b22924b1a7d4635a83dc874c070273607b8b81cedf72429a5aec84aec9f9a344209f1050daf71a89f96e3ad64ff8140705ea6c994b6e029263a999359e16b5647b0269be3e6540f9c9925ef05c3aee9f9511eb21727f19dc48298363e0fa93d6d8074c01c86b73d7f1318a1012c3ec25093305b6e1e69f01f0276d70bcb67eef9aaf73f98e6bfdf6f70fa0a9f0d59254c2bae83b21c7af2bedc7c936c779412efb2a3453a4bd4d7231cf5af93d58e84f22e5f1cde58ed8b3f6bdc730bc9e97cfda8bc348a5fffffad125063d25f946b6dd4a480fd34bee1bb6a6bd3fe1ffb8d4fda10e0a7e4073fda4d615f55bf336ae82600c2fd3be1d66ddd014f43f8ac7393d5aaf424fb743363d68b2985533254752eb836c2492b1840442dbccce87b7fd128eaac5c59c002d03032e5348257cf27a3a7505becb2f6398f5142fc0ee6a5582cb5533d31d4f06a46136688ddacdc387ab9c92cd75e0c824e00ae68683c60c8bb1e6e6a101bd34358fdf30bce5043995d08e3597c7554946ae3dc3245bafff848eb8a5c97762afb21c4c8b2f17f7551923c742e8cf45bb327f635f1dedf5a636355ec161bdd4391e57f1d3f10a84ea05bcc116a7e32b88993a1ada1234180e70557bbf953d592734e5882c3c6591feed67aa3b74ce78077901ab8d23b701f580afadff24a019e4b66af37f6a3e2d9c0520291f5d9c8736c191469c45321556ff788b6e4d3e9fe1815027a72c9bd54329c53cc12c1fb98abcecf6893690467d8269d9a33c06762f6d2d530898c1147972262b055904cac1477a6088b09dccd8674ecf64edaba1ebce01bc8e3c0f1d9bb54db42ed6cacfb29fe2f867716d85afbe39fd26be51f5f12e0b1e7f177947cf59d583a8742dd44c0ed099f42c84326868a18c2c2f4c457ad70ce2581f9b6707b88dea581a88cc8cf4736a665465ceb00beab21bbdd8e989f3ac3f11f9728ace30ed3ddc69fcfacf3a734ad735b43929cb686213fe0856d480cd496ac91a15d273d716a8135369b36e09fc4b12cc0d118fdb5e90e20f85a9a5f721966aaf98819a4cd1728e765e5f8f690e1ba4dfccec852525359ad8c9006fc2472a060a1b259155f448e4365682d7cfb1f715cc29b56d28d251a610576f5865f69a97b880b0fc58da3a6603dfc823cd70b68eafd2d5cf4c7ca675690387db2a5a54c1f928b432190a0f9fa6255d47bab9a0ea9fe188b7fea5d434e6bd913dfefd837341245b557353fc8b4aa6f5a38b46717c64088b84276f157217c26c63b4c104952ffa52d25830baebdcf77182de59b42831c7595baedb5511b760b7f08193f1a66b485c30a33e63c8bfc54f047025ebc0f116aded89f72d72c35857ce4188c0f1a5160e46f655679cad619d9d96275b14a77ab75df83dd92265c005e19ba1daf5edaa8eb788d6b4077cf70987b5b367ec44cc2d86b06c6d21412d8650c03e56e9d94ee9977295617d626ad2b54500d6f5d614d77190012bd2574951c9e57581ec0ce44d5492c9e4143c2863379bb37d891ff1ad81505015af1e75b7fe672e75b531a757b696b60e2185b5570835b0031e235650a5e4752f70013f63d453c83536e28aa2fa868f93604ed700457de85cf21c167a2b843491735b8488f26f37ea43e3390ef0655dabbe534567c79af9ed0d298080ea36d84d03f5616b6339b741e4d4ced952730b4b560843515f0d6161355341fda31f2509ccb65744cef6a60200128cd8f3ac3aeb9ed6b0ebfb0e4ef3ccabbf3087fccaa24ee19ff97550eace56b267164c56e131427457504827004c7d2d7282765d278d27c62f4aaf2735c1335f2c5f28db0a3dc101e04df874c9a503a1c12c20c66b169582ab4320a8ff996d300da75885128beedab12192e402cdbd73001d3c3578a056bfd913770815c6bc82ed58b815c4bc1e771a0c9e8a296ebc14e8ced4663e9473b51a891b91e0430bc866302d429834aa8793645a504d44c80cf601fc7c85ad55dcddc94555a7ac9fecc65e13a134df7284dc90e481cafc3a916682c67bef851ce722dd11098abd9c40e51abf4aa7f8d7f50db4fb94551fe0a4057e89715395b752843b5dd526473e9347469d8b7168946d422e3900973236db063323d97c8ae324cc8482302ee572ee8d9509c3d1c8571d1293230e7c5110128dacda0c09ec7f8f23dc1d21797244e78b332f5f203126aeaac911328b9085f640e43510d03dde52c9c886513100139cbafb92342c5a37124ab585a2c06694efccb9a2a6f1bde8243c94b17b1c97e2645bd62b76e1e9fcfb6d2d5d482ade7f74e3fc74e4be15d10dae18731f51cbb4af6865dfbc1e219db225edf05455223928dd8ab174b21b9914a9be14942b78d15777551d254e09f48f829515ff75c498d0866ad1ede5619125fe74bad8465aa1cbb7be9251fc21c52a5e2f60313af9c63a4aa472c0da4806891b8b63eb92999cfe2ac4c542231a2a01b8fae3e0e8f78694b0a1b1879bb0e2cda575d4e2c8369ac5d32d4307c6256e0dddcf658fcc471afd79026b68d773e8ee04805274b118c37114245668c91ae619ac9262b0475ad4369916d4fcacd2e8f77d4676f2415271190e54c548260e685d3c8331d828248dc537fd067abbeb5319b6ccdbad92e3d2d3146a5f590c937d5f2f84de2be76e31fde1cc56a4a19216b8d303a3d8bb4afb309841f1f947081f98a6c17545a8df6603ad01433f02597267faadda3bd81b60704f5aae3447ba776954b975235cd8c97b8809b5591938ec19a602075249ebba544d5c45df192a8ff046fb4bf21226bd335a9db9cf0dd02df302f60ed86c690e5ed5da4525adb1a890cec13e719ca499f76f1dc344f7d6075f33a9dc087239f218a1ccce7091fe75c9cdcfd820b5483e74c40050f3eb3d55604fdb5c252dfe921a0cd0283a9b0141781152faddd45ad8e2e3f1e8f9349f863f95e217a0a340a11e2d3d49f538fbce15a366df79b4fde42c98b248f6dccdc520e652c0fa0fa6f5b96c2053f79cfc2aa2d38cee04f8e6ccad801edd291dc8f29bef0998032cd1c07b027892ae41e486e422e250b34e02f5256c9483f8124a8b2e4953a398c7d202b3069457ae31ec635c81fcf024b666555679071ba79a4f5fcf42df24791ec26ff9aab06e7d5359873764d243048962c1e364f42691632492b740aac65337e87c1bdb9fe1fea05e4b7b8ac8439ebf15a39934f1f22f283777f8aca70f996c18c951cddfd51be2473eec4bd48fa4a732f2e8276018c31059aeebb2164dc3a9aec42d8154aea1fefaafbe7a583c258b95c8732394452fbc93b73ec7b59c63653863b15350a8fb049dd3aa68688ecfd5a7c27fc01c69611e5cb895adce0d375e26bd039d677b7aa054fe18f9e45185e93bbb4c0536999a4a21744d8fb13f316bded31696730afc55e5c98cff29b4cc68f3082d8e38cdefda347e07e2acf88726cbb436c6052d828340d3b7872b5b8102023750ba83413cb947c34b288c0a61f94117cc713d1cb2781a3933b4c5028deb200d8f0b0b605e4ae523c8d1c2ac3644e63ba0a68d2892b7dd2c4abb25ce38cc28d6b6a5fbadeef95b94235e324506d349bf5efac2150a979c9671f348420d861583a9ff31fa436dc3a2141a734827d1d64116a3ea42a3150f61aa89bbb58ee1f4cb6da250777d6bdd674d4f7e30ccf5d0299ab2cee7bb6db69c2c898849c420a9c009761681dff518ab32f6e2d64ad6f7d3c242cd7ff358f448d4cd3a1f8e6d254d46e58d3571d2314b2f0af97ae148609889ef8859976a9d12660af65ac550d520e97cceb166787c3e7b442a8b9825e339794ca06999fba317bee5314e263987ca42e312db1a28b4823f48f38b58e65b682274d4bdaabf6a85da15910959c8e86074c382b6e30f1b355553016a3adb77f05cfaf2cf9232bf16c56f31046e22cb6eb78029cd289a1cf9258bd75948f26d914adc574ea85b433775db4c62a4746ea8fc5e5c76e584bf39cc6c80d81c488f99a97c7c5f8aab21f1d2097c81290cc504d4a2f55f6189e8502920b7b2a2ab60c08c1531940e087495b0ef8aa02f8fd5206e5132401742355c8fb4f8487da320e89dc8568e6410c26bf0b1c0c595350edafb2c1836c9a63499aa2634509ef596b2f08aa625847809814cee05d6472493a14956cc1be03eac6a9ff553e18d4d6e53e662de2db05c869486a5ba74227c61bda889e8c1fb9e731af34dbc93edfc00ed4aeba9143fb703239f93ce117928fddcd755306a5853e944d3532d98d358bfd9a7f74ff751902047e126d4e4e8c7d2565d4509c14283d6ffe76577a1cb8a56c364ee0932af8d3617ed166a014bf77e417069a180d884f53871ce2b4ced4b8614f00745cea925cc7fb03117badbbfbdc4cc8f00519219bdabc12f5261bbef76fa3d56e486499b1f84b5be92fd0e3a2e32ea026ec387057402ceb0ad6193911cb6b785485db1c3f6b854877bab67fc15b1480b0f3d6e682ef20cab351c417d207aa6503047a576af542762a97009afd58fd1ba5389dbaf25e5e93df9a2f0d3b3527e5e634de03a42592905e92287a6306a4c8a15565a6ca6860cf6c62f58aedf5b575920d5aa3d79bfb4bc8f3e3bc02ca254ef2c25f2babaf09d44b7cfb4a320c102f4472c70612f0892430c3782d303b50cc12304632e324409143c543bbb6b764eef42bff5d7980d6950ba035441bd13d1798a4b4a1ce8c802667bb9bf3521a0ddfaed2f9f7a55ba912e21694dc0529dae3405c0883429d8e161e5a82507abb7d205ed2d4cf007ec47576ec9584add448cd30834d4f4c9dd5fc30fa503bde9234512d0764b840998c723101c4dc34a07071d4dc84542b97aff5935aa2c110f9116a8a9680d6ae53843f4cb109612159c02e335e60201fcca643f249f6d62e7fb03e8c621beb6264e38da93c1dd1606c428b6cd7d4ee03c49455fa0ddd1741c93b16ca1b8dfcf0e64495630156d84079bd07a27bfb1062cf04e99664960c374fd79371191edcc739adb38cc5b10ecc91c0f8c5fda056602c56aaa1ae4a6b8528e071ea8f164caa3ade3ec71f60f97bc05e2dcb00a2939cb89aa694869d51d0cb63c9936b80f20864ae14e5d6b84201c51ce805e9b67961254c3886c24bbb708fb8bd22f5f8dabe19035fc0712c8b92e72277116af69d621583e019ebab6ed405f5ba032c55ff1a1ef4d70f28e5b1c0806624e010a2201d33bad5e483a8e7568ad78a5af43a27f324bde78a46d099cb862260ef725a188083ed897b84fb2fe3841d3bf48548b028c5679fb2f0b02b56d281322c4ddb62557e3b00dc0977b5d1f0aa8891bd759b57a26bc0b1ba811e927fb632653761012117e35fbd91bf0498a214785df1e2b7bb008223b6f632f54e862c402dabb91634618f876f1e791fecec8407d369a687c7c77a5bb7c1ab7a48abe59e75bfb8dfade31e95a684b0c860705a5f088c6cbd0f86e57a7cf881c02195471e518f29b06b841631729d94c09994fd4f9fc1536c1ad1bd5bd3a95829642d9e6fe7702c4c66f0eeded75af7248b92e0841057242cd3be9f37eaa49a5259b78c8202598fdc66b88b778752a3f9c0b30d98fc602853fae349c1562221bef3cfa999926002cff9e522194ee57e625c25114d60f8ab25b51d46f8cfda39caafedad683d998f456b32a0e0237510b741554c8ae4ff5f096f5f5ca30f2028bbd48b310fae55485fa136c0636abb57a67ef8552c055421257e50487eaad5633490fdcefb5076535fe97c5ffe28a9edf409bbda3b90a50104e3ccfbafdb8fa4f4df37500d7422db75c1153ddf6a7e5a2d9e8bd00e112339eb768c61f8f024340fc43aea90f014b3bc8e599016215b8ea541ef859206b17d8520698eb0353ce827874b1821952efb0b6080538a944abaa8a8b3da3c0709a04ad0a6623699f32406a6977683cc9f22d278755d05d5dfd90d5b423088f362c6ffa88c37e9ed22c60dd154c430e4b14bbebd09007e051fa247aac7f1fbddc420134f86b78d8bd2b876028a2c8c6a74de9cec85c689588bb497a786aaccc73568a06c65b537c41458d243ae2b04a234f9d0a86164b784b0ac28b1ceec05ad6f67e5a568e9b07369507769bb30c1ef11e8a1d3ee2deca22c4d1acada9a6b059e37b6c435858bc20ca066693e388d71832312e2d6853109090be3a03e1d719f3e584e58b7c0d745538474ba761545d01f6f34ba08dda0a7d23aa7af9b97dafbee1dbd67da071b7f96cb510bd4797ab7b3130ca3646ecb1b1c91fb6c007b9c7550afa7f3f94bd36ab177a73b377f20102f1b93fa86a5aa59e75e7e5ecb7836d0d7f05bced9b0c366dc36aec2f6cb35802cf386c4bbfb191a614d8957409e98daa11db7c3a775fcc8e630c3bbe880c98cc78d54620f4e0fd9bacfd114f9b9076f0a1688efc3fac5bfcd647869fe9602ab7db18f95e9bf6614a6a58574f0d53aca826be59e60144ef46b53fcbdcc7d7bf7e3f12412b06506fbf5315a14abca76e1f87826eee07fc94efc7492052059ee3d662531d8af5a9a0cdc50e932e98b0c051859d79b1191125358d81202e3dcb1140db9bf0f1c303a6574c6f2e39094ff8c9468802a629243ff76a410482cd9940977c3c59f400f78c6fe5231a6466719156abe50c09fb01d4409a40c69b812b8d9a0aaf9c0fed499ab1b59929c1919a48856f7d682cea55528d824d22f4d8906048612478dce5a42eaee527a5d3896bc88d7558e58b74d2b47ac6113379ed910e6931c06855c0a3020ee8a0e2b566a58349cff32643128fc92647c8c5f0fb8878cf4d141d38492c494db9a51db82f2408650d7832b21f47718ffd60f8cd6d63ea094b35aeb904a7cfa8e2386849fe3afccff87d062dd8a4ab13a426dd232eda7a6d9438bd1575515f07654e58e0791e20773b8624c3f96c84c7b6b07fad10c84d767431ed667fb119d6c41aab4ef171753f16d115a84e49699bb767e98f6e95d9a32a4e1e7676c46ca64cb94bce994a19b54dd57d3e4e76a6631938f9a1c628731ad5b86cb076e99144b2470c19eddd8873444b20fd8c0d3310a702c2517b59de72014c8e4a15767aeea223e0617f672dd99cd91bee65651cb2978ac3eb6ac71cc327d599c1fa5511ad6d5121b2ed0478e5b8f50dd2b48721ef71821cb1f0728272803a07b04b8d479efa1e944d1112361a98944193c4137e879edea7d17739e591e3a7e9eca4c87542ac7e1cc67f9e8cc8c66486aaf3accbd3622ece5c3e4b377a76fdbc622f3d16d630ce356c1359ce488b151127df26e9708d700598adece7176e7625c271b8569e9b3b93caa7bb91382381ab0ca73e5bfd4914d76d1f22ed4fc43089fd26d1d630c32c82d5bedab185700d64c75a7c7547643e89087a148ffd27c889b279b2716b3d6a82ed48ac03e8a5056bab174b27d261b263b55f4016fe171de7460a6b43248b77c2b2a793a8f7542a1c076d93673c36ebe7638248dfcd69e7fb51166c0ca0894c9584b89ac63eb5d3bdea7e271a3bf5bfce0e9dc435c61e83aa3122c81d765795e1febb02a16717585f9f9cd61b8c96c09871e1a41ba9de29911bb1c4f4590f58af46fed6288bdc9cb919115916f7d5dfab91b481ae912d9fb8f4e257be884706809c9606a0caf85aad20e3584bad61f47761af30ac329ae468ec9482e65078be10fa4c024533b58c652f94fff73625755626dd2d20dcac14d665c9527b9f4cfa839727d9f61de3d740bb6a84191f8d31193b4ba53b2dbd922dc607e9e382051f5c08c58b5a10f626f3d6b675a1a7f25d3c358e1a0164384e127d288004e8e823f9b187fe551210a7da5af89ba12fe471774a82e211d58ca1eada6fc99b9dc6e81c446604a21dd5077ed811e6e8e07159cc5805c09c224fcf114a36485391bdaf20ac454fe40d591486c796d205ff8bcbe04bf758c6a5ec372c38fbe4220d64ccf497403088755eca3e2a393226dc58a6637638a81f19e3812101385d1fc294cab1c15e7ba508f8ff1aa76774ba0fd09d4b9dc9f8b116ab5247898d23c2cf508327c100a07e2e0f4fe57fdc0f3eb9f5ca2d8385597b322514e95d7f290936ce0f5b6f0bf8435a1cc87c7ca2048f8d304356fd41d2448ce52fd9d0142074492454cddca8ba20547b0722348edaaff46c04d0217083e235f4862df7b4043d1035c083b61ec044c372d81d352e7f88328640067a33a6028775211be46d620832cae8bf4ffb6aa91f0d044aa658291134cd5d4e3d78f0d9430074f408c0d1a419c8560cabae86b050735637fef79b86cda7587e467af8e4426d4bc25940f3d94297fa088af15b16f06a559bf074e3bc68d20ec7cfa6cc577ad35b90d2ac007d6c6fcf86aaf41ea8880f1da17c6a5a469fbbac3963809753c05b61a5078e7f54199e9cd38b5a744a6268007f3927d6080336b3696ec30299c54476b1876a3123d0c7e7f7cef7084898607ce1e4c1b75cc63b07ed904f1c50fec07a6280bdd30821ab16f8ffd72ec20eb04ed256b49a490965cbf64608aa65a6c5630e6821fce3d3ce5fac8f92e8c638550bf07a052e4a0e4d944a380d0e68da285380a08d1e97528cc7c77fa25169808c2d332105769c0d5963520f98d637d5f13e1fb90d3878ab5613d53abe6eebead158166044d61871603f9499f5bfbde7f71683098d0142df4f7fc8252f414d52c8b615775b7a092b76bed446f01a28ed0312d3df1550a278fb20da2f4e80c8665c007f63ff00647149528084465e22ee314ee2ac053d36ec21ddcb387a7259ca6158a92fe3cd342e7c7ce5006436649fe04023b1d3af5c735740b57f00acf5da354053a56d1088549897bfbd9a26b5decdc98e8fca2459ab7f4fc649ac59bd44191c22fcb547d0145d4f4246d7921fb31ae0a7ad15b803a342fd07d4b5f499f05465d6f9b5c2f352a9c935cc74e45e431bad8afac200b5310a63be3532a8566735f24546e8f7364501d053f77328a5b1f8c28e91017852b7fa7fb51e6b697970d10a4e5960d7f93bbb24acb894d2307a0473000ae658c2aa78caa5fd855e8db51a1e0dd9348713d42dadd394bcef5dbdf7f8257125134d17745a8bdd7760fc1b31563b166d7efe3fcd6d445fed59abda9c3c1fece7638682e62c96a1f65dd27613b11085afb4d472fa1fa46f6c95f036721e8d2897a47bb6c8114bc38c414ea110fa30546636084b1ea94b8d1d0a724b9c05533c034ab5f41d3cb05253b3d7738e43bf659ca32fbf678eeb769086c78a8ccfe505c600150e9febf0362249e783ce6ef5a1f1ea203528a5f351747728197df7130a3591ff4b2992d6f75a4a601d0325bd1d6fd07be04bcf59f0dd8943361c76a431696211de445fb1f5f2b2fdf7958e99662f422e06f7c7af628a5c8b6761181e6696c288b075fb21271cda0249dc901631702a71d22c99d16a786078df2fbc80298a6574bf7b6455f7258f198f24017b4bbfa7a447fe14cc401082ef04d88bdc0ea071bd979600c85ac5f8293c7061bd4c78583ee58dad82d6ebbdf5ef1b19d15ec11f25de95032ae4b0065a31aa88afc338c95b74858ff5848814616f0c5a5c8a6936f516702acd089444b743d05b48320e926eaa9254f4a2d92d49fdbd2bad72963575eaf83d01886d307327b350fb242a5d5cf026392d82fa485524dcba26727834be78d809d31f3f537b4ab676c06ecb4b96917825374e702456e1588fcfbf1ad70505314f99941da5eb24b179370948aba864d4bfe789d5ed25ed4510e4445a4744ac86672b30a82aa7b21028cdea8d461834ee2a160533144dbe6cc7b8c31f34a1801096e9f5e8ce741c434212c0fbc91a7f5b29df742c98e3f617e289563ccbdeeb37f96f3814cf6af82b97008e2725f64d28b12525765924568c8c3a5196513d574e55c635fa0956a6c9cad3104ecc9551c24fc6f22cf56515e2f31fa4092033542551b78d11cb7cef4f2a3370d6fe86b63999a0b4fd65f59d2259620b93a06f0f1f66d965848b4064bc5409e60ccf568e9d05497166647e46976a45dec829bf87625f794972e1b89fbd700eed5db584d09cc3f149749c81e3fc669f48f9e1940f643d7b770a88448824753238ced3edc866c665ae1d370deaf23cff4149526e9d100d39682e1e2c81125b4c8e819b65eabae35c433b98d22eca3e85426965b75a9c95626f37870370148895ad66d466c048fe0eb7c434b6e3a22f1112fa8c1ea06b774b8fb7a1cfac8d282b865f4fdf23525f544365f99acf496b7b16080649d702151675061dcdcc271edc20eef8ad67d18785eca0b95a61857b1b6e76c783d887e5f3f92bd7d7decac6cf8d180d4bde532594e1cb2446571f84adecb53d15a40ab6872f625e2fce2b84c3d42197f3240fb6872f28431e8289cfd2c04f1fdb62df276b8a6756c8ea2f3e3034e64dc76d6100dd7fba6193e6b6cb742cf39faa3d0d8210e96095b2179d785ea0fe60564d7d634c3edce2518b991efc865ae2426d4a95bbccc4618015c3090e5d150757c6386cdc453b38bbe666003db1ddfd13cb93693f354ddfe3dfaa52e3166107060550d77073458ffe84c0280565b312c106c78ddc64be7ad369b14c89dda05e121a35e422ddcf7be50d7dc4640147e4040ed5bd7a36a40c885808633a63c2b3e8ea0daa5e5337cd70ffe144456f8b9a3badb0fb631acb6080354f2311ad24f83790eea6b122d7cd232fd1a1af0d8351a3776da017703b1b0aa81514c9c9001c1b894082daf94d04863614a091a9beb4466b24cec750052889ecacae4ff83b11503ef1d1e86a18478a802efa724048f6767cea55f7c0688702d05024587c8daaa5cca0e6a1946875aad3b6c7a026af3deb956a8f58609ef478836a725490e83dd47aa6424d3e9b871da6d01e3e1869e7fb3f3ed3f21ec4e0c2878b3f49ed48a3d2170b8e7a43898d43e9e9f5245f7bfe92dd6121a0d4eeb90684c3116b7d65ab7d242b43707208e714232305a9df460edc4705cbcedaf8b5f90a4c6f32fc28a85fd3d75b3f798433b033d88f072760bafecd86933d0266c6d50d1754cdbf19928f5208bea9d22eb053b68cef6bace70aff58ec9745eda50271d638c8d0dca1d7cbb1aeb1f7ed1161b57019e910da92e9358eb5a665339bccc5515874a8395024355063cd8fc7a5ea2adcd19bc300b86a09f8dbcff355ca5868d158eec275307f9db2cd01b7c65b2d5b36ba481bab052c88f9df8f41fba68ea26f7d224e78c0585f8c28035a6b367a59305c554d074bc7280b4c942c30a37cb82611ecf8bd9e6aa2a9b4cee55f51ecf855aab947a7fdcb74120040601881a9eb1142c31003a03a056555934073d16a3a606d3ceab3fdb55c5d536349266c15edde7b6fb9b74c3249199e07a807bf0723164caa049ef379549cfd2bdeb0fc8ab39088fb2ec1b385d582ac7273e36c9298f2a64bf1ae25e574e95dbd6bed01a9cedbdc56e9cdf49f148aeca3cf51aa3af1324fabbfa55c3fdd17369b24bcf34237d4c17ee6a90bea827e82e6a947cc33dab74bda0afb322bd88af34c44c1da34d361775f8827ada3a2fb8ef81dbce7d767f6e1a0db8dd366286d0755461e726605d395cb121eedac083f9146eb1feaa260b83df1e96b9e3a162889d85e888ab211e251364258943c41a47143bfbc6902f477ac7992e958f3d431e104ee145c3fa7742d3a6fa60a076ee6a9230c876fdad431a4df0f0249c40a703fa7f1a06e55fb6ef8b0f132d4fc6287f465c0206f7e54b0bc9924d29c48b464d7ee78ed6ac4c5ae82ddcb7a66cfbcf407a461c993ae7b7e37a74bdc33465c626977f4e60fa49493462923a64a8830f16bd5e69c26aa8418c6f739e79cd415e90721c61823bdf4a79b73d200b32d1c3c40a81308b6dbdddda953f993aae03929757f971f2bdfe577237e744e882ccbb296a448a83b0ea44482e360ce9f1309d4a79c72ca297780039fa22391ac95ad098595fd44d7f249df12b9cc4b59962807098b822c96c7c25eb2603948582e698c0e5922225b946a53d7d361c7ea8e2081c5e39212e12bb41569a89665d40993854bd29719ddc0c8301cf58e47891a4f1c2bd82e612975cf529488de40049b473744b87f7433c219a9dad4fd74ad0ec90fba169eb259b868107c66d3a7ec02494aafd105477a02c94fd53296193ce183b35d6184277e80f35bd2bf845aa802e777e14c12e14c2e0123f566500f8258a17e18e2a915a05a7e88afa00b28a7419400f5c3109904d5f243e41228bf496c2358a43100ce91b048c302672f97449a988b8cf5719e5afce77d2806dbdb673cdcaf7cf69d334f2b3ef36e6e15ceba9b5b2885f30c0695d8d2bb7c0b28594d80ecbb500912d6bdcb102cfd2c6155fab4a9fbec46470455025bbef43cb47ce9bf2fdd1f92f82e0fa577b93f94eccf2f7deff21155bab5642f0e8953debff4954a2e3704a49f5f22b168b960146c676f9b205b5a6ee9fb96effa70f9d24794ec7129b5b4aef4913dd2d561f62e4049cabe050b304e98286c96b03cd303eb9b799a5fd795ba8fd87b14980766dfd20425f481e7dd679fc34c2cc664a32b6113a6ebb2b9712f2cb02d5e586059bcb0c07638bf0ae8bf02ce670123aac69e09937d36f2b159e507672fb1f651d3fee769bef6f4bba149d87761de856db08fb34924bc791ace2f5b3ee111b67f72601f6916d83c392b6049fb952782520147aff23c8c54545ee5f6cd0ffea31b124191e68944ca6870c2662f7b64add6baecc1190b673effc60fb00e3319934333389330ffd1f3e03fba25ed471f513ccc2f69d7c7caab7c44e5d0332b443968b70621db9f675c5daf98429765dbe49eabd98f6cd2928e88e9e78898de1a63b040402112635acaae37a6b77693d007367e03755d8c9af69ae6ee9a77bbf69996d51c59f6f389607feaefde4ef8a328a1e2c607352423c20950f687021c41fd30242241d99b04f743a216502319ec0e900390a7182d4b26d2c4c0fe3422cd7c9214560bd10a4bf08f92063b8a566ad9995b03c565b6ff8ff1b47df7833ef7db67106fdc53ee39fa28dfa9c04a4c3d20a0f6dc671077f1bbd1691e05b9ff1843efa370dfe74ac2ddf61af883fef61dd552b494cf1171caad3106fb19088835cc3de5eabfb0c052f9718f6267759ff4e42c2d4d421fd84ca9073af423ec8fc01a7b3f3061dc07f73009db9f2d87052db0fc522a85a14e086796267076c101e797570a6678f564a108f6ff2c8421ec4114ba396badd333d9ed630b53ca6e4a63b5b2561289524a29d53229a34f31dddddd1d06d3a759f6d65a3a279d54051186be068e3a60b325d460ba534a04771b4acae7c5143bfa3c3bf254ac4c66059979a936e2d1011ad8adb5b6e354be1bfe926befbba1dd2c714caf017660645736d6748f72769d89f14453ec8cd6ba8c34d1a5897a0692a665d9b16e3d60b519bc7482c78d7894fc506646099c634b05d1e5041346b84c71e109268e40851c8a9a45224cd4a946224cc4a82678224cecf984133a32124915809a8815492842892260d0ba401e13ac4e97a14537f1aab309984a3741869174a2042859144c6430c516667013c58a29ccc048b78cef53ec191de94df0e008840521ec5fc211080b45c013085c6b873d022a6577d38fdf0e1d7da0b87f76115d7cc9be826c5bc6bb6976b7c4b25bc6882ec653d5dcbd6a7e3bc6f8ec2b741ed580d77d1fdf031f9827cfa6e438830b0b96c13daeb1bf09a0bc778794202051de4b94776f3c14cadf38cac67b212a4a461ada7fa044f5c783a350ae10352928ef1b159dfbccbb31d2d034ee06a704e67e09224425647f3b624bc73c75739f653a72cd452e7271fb4cfbece7b7237a77b31bbe06eba494de5f8e260aa906e6e9262ef1e2c5382377b8ede577ea953d53a8408c21e0904387336390d184d9b1707fadad301801c54b05354968420f8a0a6122475400841096e00008503041d12b60fa3237c0d4aba494fb41c26652c746c91cc0344553916605f7cf6fcc12c30e9080527c9be6f793e63cd9cb22e3c5402e11c3d9e2974f826129250f945c22d8ed095150e17e949e9637a46ac49262a558f10814300c36cb95943288b21f850636aba4c0276c962a99d326794b3b3213acb07c942b5313a66555a7a6523555753c0d05c5f3501a6b2fada8d35e99f67a617ab5224c53b2ea36782a37d227ad3561e8879f9da775a4e513e3fdfd05d1862654c3678f01f6779d4843c3fb7baa4f9aeac6559e53d4a619aa8836341e8da70c4491e6df7f0af5298bc5a692d890ff0c6a138cf79f5388363426b0ff4c1269ee9f3297abe5fa71b98eb409dc41b4910d0df58015695cde7f16e953c6624d1d9611160ff6d2fb4f13441b1910d02402fb4f9c480380589f3215916aa6e6cd509b5e2c8936321e1e2ec0220d09a84f34164b12138a29c1dee2fdfb08d1468693e17412b07f2389342defdf3b7da22e96ab7bda489b5cbc7fcb20daa0434334c0cef2fe6dd327ca62350eab8bb074dab4d224daa040404f8a220d8b579fa84a0553c58884dab4a20ad106e5e1b94250a451f1e993c7624862406edf5ffa20daa03872060502f6974722cde8fd654e9fdce5922bd78e4c01f69745441b3e2467f4c95945405fc0fe1b88361c08e5fd3dd0a6fafe4022cd84b98f3eb96ac250ff1dd186f3c819f42392180e323aa5df730d1867ba260c7df721396386ef86b7700cada509b55a1fde1a2e0d2933682a8d4753bd68aa189a8afecba3c0886938b1988683e9c7b81f98b9b2a1ccf5990b46e6ca8630fdebe295325606c462b180307d1000dd8b4cc593a95c325529e3c1f49fc4b58865383152ac450c46cbe6c235e422b95ab886307d00b0d415ca02a22c16ca5aa12c204cff050b6d0555511ea72a16aa5aa12a1795cc7a8ce2782c4c63b118c5c1f44b232a5d432492bdae214cbf05c5abb31ce83acb59ce72204cdf0519ecc45963792a1ed23b4f8a8b9654a2a4c0c633e638247b638ef3ad4859566ffe98641f930e5df354577348daa83e72062591567408d3ef3cd02bb29a272fa7fa481b5e1171067dca22797585a9a7dac1d44b418ca1d50747e3ee7aaa1843dfa50adb9fd29aa7ef4b6979afeed5b83f98d6431b6b472648fa3e267d9aaaf90df509e68b30fd2e7cc1f3593e2af2079b131661e84b6d861485bb01a05f77b0766d87f461409686a12e9d2da6f4e3027d9abf29843aa44f83075e913e75afe9a9bcd7077b61fa0d350cfd8fc9f7c1708aeba533f092a163ca65deb2a7c4df0ef2b39bbf9ff6c7c385a32452d83eb8dd79bacf806242b833d96a93966dae3ea17cbc9dbc597ab8733caedf0e2f1d567fee861dd62484f49082e57b592662191c74f050810fd8a874768eb480821adb24d15cdf7c71d7edf092596e6893b0f346901c11d7cf21b1378e7146cee4c7a379840067b3bbb971f63cb8fbd2a11089b51810eed7b41de46b5b4823c64cedf62071e626ad674f4951fc33b04687133ba582cd325d6f3988d13cc2f133253828d061053aa4dbc8c586a2c377434787b46ffe2e0373cc06229afce9e8733dd98ff100292f5f0dd375f7eaeed52fcc7d37501cec234f7415b840e7d9cb11010ab468ebe6fe566e56ae41240706a1b8823ed0f8398a0e1dd28fc03cc50a78e01056760fa63fe79c73a210c1e2e8282b760f22f5bcef730f616b1f6da21d7dedea90813ea0b0d99743878fa628f7deb669dc391dd2edfba66fb83b67cbdcccdb365c916e558794b6c0f3e3b7a3056e9c0e69df7c6010cf9dc282f5cffdcd8bc24414ae10fb37f50a4003a66e14949f77601f6918fa3e983e7773df20c1f4b79b2d10a62f84e9673787b86f2be990fe045d2cb13906a522a0810f44e183f30b7d1d3ebc4f2a4f0f30fafc6227d847e649a58e9e6449f4bf667548df8513967ecf8e71bd4204ddc7979750c618196372f4fc1ba7ec28b84cf181143b4fa40923b3af1346d28f37c4cf88e01c3f1220e61f708ecfc3e2bed903b83f82dc6b5bfd1ca6060ed10215c4900fe207ed397777777f2166507e8704410495dd20b61ee1a637461afd3c24ee2fcd213168a7491049944cc14912a81ffc83181253842d20b1c417a030832014fd2ccbb22ccb5e881954768710398209119001072eb801105140d950fa36355a512a85ba21a1e8d7a410a55229d44d45d1af284a4251fa42cca0e80dc26f127d4bf3f218a211e9fe98d0752d35a6b03ec88f299589cd3ecc2b7798f7c7fdd12f7f871ff37acd496125112a654e6c3ac127909cb1b1eac6636402491b9b0c361a4c20dc2fe5dd56bded74b8eab0372354d83c5daea029d426e9452f0bdd94b181b0b449569c1b7c6cd798c2d2188de1f8c5700e6d01f91d677dfd038618c2c11168894dbbbb74c146a0252f1c819604e1fea45469c152469a2dc238f58f3f35c6f8bfb8b13211a8416fae3860a7ff5a752e52d8fe88e5e7d2b9bbc796b7a44f644ae9836e90caffe1024547f739a54ea909eba293b27b4e774a336de36cbaeb92dcf0d15946bb33d04390c274cef76e1970a0eb62a86c04f34b8e8981ae4b9133a6c824d3bf1ca1d710f22f87fc70c8c864a3c83bf39a3f5dad249286bf0510c1fe4d644a394414425208e1b8048e4052e4e0ce050aab9a27e9aa2cdccfd9344cbf1779918d0dcea52e50d8ecb27bcebe54d5219772b1059b670fb5a18e7b25815ca7c7e5d3a7b9d3d326a73daab9334fb4888a1669987e1ddc5f0e0dfba52aaae2582e56b0d9c31dbaaa58c10d4eb8c1093182513881111ca370821cfcb20bdd0d504882951f5326919e50d84c4fc56b4c61690b36a30e5ab0eb5bc0c11148c90ad3c011e8892ee0160e8f689022d6018183228d7c0ecbec7307c42827c6cc568ce96ec8b1f55904e530eb28d60505df0d226f78d785046406c7fb1dd20f7dec80c132f5c2c73e7d3984c4d19e667904d3c63298847d883dc4c03ec8fb12e7d0f208e8319b36f1d0210dff49a496215b3f976e69bb3c42dcfd9364644ec1b227cea04f036406cb77e9903e2175345836cb1e4c89c81ee9d3217dd9f3c98be33a0e225882b2e726082ccdaf2fbf7d74485f4687b48261877d131b463e0bb8024a0d49d47e6a607626b4880c4dd3344dd3ba6ccace3ccbb40ffda9bbcb2051d09b1f8196c42240e9a4112ccd8f38e23932411144782fbd9745accc3aebacb3ceb2cfe368564279f9db9750ee97655e165ee9b1ab3f9f93d13470764bdd3bc8f7babbfb1df2bd5bea2e8f1077df75dd95d1615f30bc4e03094bdf9ff21441c408ba9fddcfeea7f65d112b5f87d6536bada736356f44c306367bf92f4e60e97f9747d81fce937773ad7782a1cb3a7ae9b06abfc968d37ced6522cd7cee330dac7dd8a61de6775c89fbf9dd2d71dc7353060d245eb42168966519754a9f669452fa2f82b094524a334ab38cce4004353535353535353535353535353535353535353535353535353535353535353522883159672cd5457fe9c213e6c21108f683bbf664d46d89aee2609190805e25b4d5a0a20c2d2658fe7c4271e608c6f0e9407368915887d95b325c7287e3b3b88d2a67ccea49884c88a1742458fa13228c1412039ece842301cb6f014abcf582789a79c067af81033e7b120df8ec3ef0f1d9fb6715f154811e9f1d08067cf62176f8ec45e8f0d97370af4c219ee40d8fcf130b0bf83cb7b0e3f3ec828eb63b8827c9caf1790601c7e7a9c48dcf53090a187dff34413cc9a0047c9e46a03ecf17e0cfb3063934ca9278ea14023e37180ef0b9ab30c0e709040e9d728478ea1d1b9fbb09349f7b0a05f8dc5898e96f242d83786ad7e97323d13be820d4e8af493c35d10d9f3b88017c6e13d0f8dc46c8bc2c9255983fe3b3cc82003ecb25319f2518b08cefc2cf3209cc67d984007c9647903e982f9f254b2241c36729831a5e16114f3356bfb7189f25cefd2c83884da21870ff06e2c97326cc74f91c612f621560f4ef88276f01d11169b42fbd010810c3f2d10566f179847bc3fd33c493bf449ad83d334ff501375707dc06ccf898d95a3d6eae0cb8d9ee7075b81906de7278dc5c1770b3ddb1e5e0f93a6e86816b2cc7cd15c7cdf6062b86e72be06618b8fe24e0e68abad9cec7324806e1595708b8b91ee0666b80d47c1c521a918d9b2bcdcdb6003b4478fecccd30a6e63add5c4d375b02b86a10cd93b63361e6d71b6eae96c69d2fd344786aa919375701dc6c6356326e8681b3a08c3561e6db70730dc0cd16e666521684e787f3a7d67073b534dc6c67b82f37c3c86ebc354ff415e36618f7661298f339306eae00b8d9bef0968bb7f07cefd960f3444b37c320b5dc4cb23d783ec96b8b9bab6571b35d713355e1f92c9b4a0d4fb2aee33a3146b69c0872fd1011ad808d55c0c69ddd7280c0dad9564992c41819db88d86eb614118b156364630b36ee50ea4f8da2be6a50754d9c89535745e861edc06031a6318a4754575055f5a6a61a4923f95c5f80bd827ac5693b5a12b496d6a3b18a8a628c96d262a0a9b49ba020b0311744450cf63a7264633de1a795f5c418896b76931d91ad32d5109018a3bd9e10c560f147478c918db31e265c3fadfc825f628c0437588c99db920833b91b1d7040ec5481e77c30e039ff0510b6dfc1c6a70de6356e75776bdad85a72c66c529b48d9bbbb5b2ac17e7b7877ccb2dffd45caf6cf0db6b52697c2737e8ce1b9844c8ce9152f708c30f25bca4ec24ace85630c220d9014a04293a2264f9e3c79f2e4c993274f9e3c79f2a44993264e9c3871e2c48913274e9c3871e2a44993264451c0b09d15c774b9482499d94df0ef68c0ae7d75ffd95ec79f31a4f185bed39417afbd700437a94d2429a9b05266cf5d9ab0d971df0ca447dfd8616947fdbe35b609cf2884dde90d5d88b2ca9bf6d73dbf5ba519d1c5979ce2c294fb7ab26146883650e3305f4e73d5d369a6d58debbc0f25c57a0b772a2b2c2b58b420b96829b9bc00000cefbd6fa843fae0b70306a364e017fb603388f48a88333e263d4945b20aebd5d5ea5e2f03bd9e0ee9db007aaca92ad2303c3d4630d5d9e994f429004fbf7bf16c00bd0ef4541f6cce191c141b4c5f2b6aa181cdb305d39f8f80f9fe60f366942298fe6ccd16a6dfd140836703e865a077d3bd56f3d4296918eaa9264c57446262bba155add69248ff61d742039bebaaae8cf4c906af7b459a89557d809b4705e0e9d3b881dd3e1f1180df3e88fb60fa5243d76ab55a3474424260b75aad56dff9f8c4e852a9dbe9bce05eafd7cb852b2a82c1b55aad160038212117dc6ab55a91381f9f12974ab5703a2bb6d7ebf562d98a8a5a6cad56abc56213125ad956abd5b61a6d3e7206f551d952a9de74eaebf57a15d522dbc956ab555b13860a55a1542a5553d9e7bd5e455507457ba56845f5fd57bc68da87b72534710dd753b994c1a6d0d0126acdd07a690961fa2b20ca77abce67d5adbe5b753e98be4a8cef76a94ea74b815deabb54a783e98f5e782eafa2d7cbe55584e95b181d005a42ad172d979610a69fe28223712bce67b55af960fa28a5ad854b713a9c0b8ec471df8acab2bdb6a2d7eb5584e97b2d586cad4d686badd85a2c5b6b13c2f4bb95328cb6d5e6b3ad46db6aa55286de529b4e6fa9d196da529b0ea6bf59efeaab16f57dbdeaab1661fa5596c1ce56156aad5ab55585b2fab9a702d592388e7bcfe3c2240f44e21cc67de45e469f9c0b31f798fbd8957b8ef3607c3d388ff3fef36e0be5bff73efb90e7f2edf8ae1089512ee7ad18a3bd073a920e35ff91365c8938e34522e52c863523fcf06eab70babbbbbbbbbbdbc577a33bb06f5a481f8efadd77366c60c4b3bb7fceeed9f2f5e8d93dfba66a2eacbd83d990276ff8af80192c8b75a84d269a4cf8f2b3bea9a46f87bcad9ae12d23b25463ed339bedb5cf76daa47dad46483a59910ca7fbfa39e3c992f44d87da93be1d9d87e3476d150e78d3a5adb46dbf6d2a77d53c85ef4262b15eabceb47e5cd28f60ed3bfa910eb518afab68b80aa4a0e7386bc2f474e8298831da7b117186eb348cf6cee346b00b16353c094e7ca32a02dfb4695e128eaac5c783cb605a770e5de5aa064d9ee7f8ca77bc47c67309442006c5a0181483b0f62dc4717f0f29b8bfc1d883fb7aabca55dd0006f0ed80c1eee3f2b25cb33ad47e05ec9d567588d33760101f2cee12c418ed7b8838a38b744822699a466fc356be1df376ac87baeb4d9214900c5cab4ae82689960222ca62192c858ab5665f3fabb566302efb79b321ad08ce2a178470f7f53b0278b5fe0a18513db1671cb7e1bccd6d0b127225f9016a61ed250e27c96abb451b1177785bb16ddbc66a93f7f3f3f659b2b4e7c09f57e5dbe15d21127f377b2c5f8fedbb2b44e24c2bd2a1562b0d9ded7afc0946bcdd0ce405978438cebe87149c7dfd4e071d2acb0b901f1da8b0f3b98fdc0d5f1f4472d919ed678d97417ab12e323561b4f92e4d70a3af47fc9efbef721707eec60e5f7400511d0992452b240dc3612599448d33d07e3deaeda1dcdfb114cd69530fe13f892453a9ccfda4399922c1da4fedbf6f47bdd93379138cf8c50ab4cf5a914662eda3f7b995c0285f8feedb7bad1569787442e667b553ecab8023b063608ddee1f46019ac4d3d48dcbd1686ff24cbfd771be6ddac15d9d15788c4dd73df55d0450c36d31cac7ddfd01c1dedbbccf3b457614dd334ad15bfd270419ef148b3a118a3fd0433980a64165e91a6bef62e5c8c46dacffecabd10c7f57b48c1b5c35c6fbd4224e6be1df5fb47cd51ef8feeb60f1273b7871a86b58705712f526a1facbdf61d6b93ab1aa6df56927dd2f70dd65c85036e24168894e443edbb0178158cd841fa3309ff0cec41e2fa3ed430da33c1da67456f83350d076b9f65b0f6346e60f37c2e83614d2b82b5dfc088fddb31af1089fb3a2871a428d56b0d3c810437522cb991a24da529a50c7a7fb4cb36e59614c4ae295558f9f1613061e37b956694deb62ae8e24ba62cec35982fbf08cb7769c206719cc3149f0ebb0dbf28819dad4ed2a7ce69266d4a79ff266a13f7a421ab447b940eec56fb744853347565b6077239143aeb9f3695e837a593bed4efd0e3a97fa2cb3ecefdd3ad2e5a399974e845b07f17e9d063fdf2f2908de9165d3591e0f96d8356bfecae8201073f28a4e21ea69314ee6490eee76fa00f126f2fc1fc82b7597fd69ff3764fed01e2fa344572d16a71f119069e2df04cc1f36734d59f8d67123923b6b4802d2df7b17fcbf730f174210f8a31fece7a7f4fb2f2eebd8b9b49b7c55d79163749bfc42c1e345948449a565151f9c91acda19f0e3d0fc1f5238e5f37996160951b84f60a18447a60ab4df95b543e05767bd963fb1ff2bbe773627befa494ad5691eda4d76095ddeaee26d2f2f6e9d0a3fc70f4d7a760b73af448333189241b880a83099bbb47da903df3649fb01167c742642682bbff31df07b9f2b4f3cacd32f7fbaa43f76e0f12cf1722b1efb80a7844e93b90a6606213cf98af46d78db4a9de3b5b1f63526483432af23ad879709e31961f699309473963930bb68463e21ee4137c44a974676c28d3146eb589aa6eda148162469cd5a61ea72916cfbec23b91c626285b7f1a31b0d957be9abef32205d66152a66e549ccfa10e3d886369d36153231d3a4dc518ff1728b03ffa83e6c95941d87fc88fb589beff6c1269b6f7adbb59ce0a4aecdf0ef22998e54fd6b7437eff9cfe2e4336cf1decee9f9dd5a692fc205e92d27fb63ab4e9536c9a7a6a043bd5695a043bc5c1de30fe4e5453f686a4c2fe3307fb7bdd6a93c43d6df269939473a74df965f2b4c9a505e51130056c14b0c106ead0bf73fc3bc7bfe3660b499bf2f6ddbbf7fe53894823dfb7af9d047b48e97e03b394f2ebe3adb47d2e6df54acf217eb54b5687cea44ddc95d13ff3345be13f89d4b2fe2d43767e2e6ddf4f7fc6d90aefcbd7ddfdd9fd0ebf430fe2acf006cb1dfaa7fc1fa51d137714cca14330d85c03d778a1ac161d8385ceda5a47d0a5a8e853ab3d29d234cede25c6ab43877750072dd18be3bac41407114c7dea6893bf74cbe81aadb583efd795605a64cbd1253b8b5986b26deeeeee9e7d1db174b87d049242479bb2ec4974031d2c69d63fdbb6dfb6eaae4d2184ee6a472cf3abd7d1e8d26f048210a4b0790965dce677a3fbae931d6e22b83390193c9f0333f807f7de7753079e2f7d64231069b4a72a1f47366505968f1261e47fefcd9f20f72a60ae017f3f02f36352ae389c8aa8448d15564550aa19120000001000f314000030140e88442291502c8c5351d63d14000c78984a765e1f0ac33808829431c6200508000001000000010001510007131e162ebc46ecfd76ae778dc01a3fbf3751f47778dcaa5589f54100951aa95ef4fac7887dd8c4a2f2651a356b58d37f8119ebf3922c0cb2a555d1a406d42c07a050f707d4600d0726a1304041cd03e9b1d8881a8ff2d95d48af19513d2bd4352159c43825f683c86dcb88dd6cccb01f7e710ec638e609b8e01252e5e13d2dbd5203c4616527d6d9df59d87315a8578c4cff07133f13b6908a976ebda584c00ce3543ed2708b4ef08111bdf9c2a7b466f3a3e63337b32cc5b2ded0d8b0cc0d9b336ed6958ab33e1ab45e943f271ee1e9ae9f7b909494937a1110fd528a314082131d9a76bdf718486563c9ffa49eafdacfb2e9755074829c25f1d0e9c7b8ba563668bf46b6bf293460b9f90a8656d9494741f3942fb5c707a724efdd306303ac9b546d949c7879ad4d107ab378d0a962c9725e996825e7cc033a26263b1e4b25c6fde747bcd5e436474f1efdd5aad10531a8aaa880abadbd02a35e509b69c5887ec21d6ee7a8f652f100fd64eb3e791e14688f70b14c8106a2eac5469c85cfa2797742614e9c4b1f092904db215f26308cac62473357a18c32d07d4167d5985f79a93f575a671a62128487bbdcfcbc7b104d68ec2f0c17959e42b19bf705d7ddd94861a3bfd6fcab1c2807eb713b5c00e5dd5d903055f1af0cf1c7ac5f75b57b888d6ca83eae56e496ab715f68121b7feab1dfc07c153e1785df985f5fd9a9c9533b441d2b1148290df16bc1433105779bf215d62dc47b123f270175e51e89d1cbccaed7997d56eddbacde8f4a39298a49ce74929f86b0b48467e0dec11066b9c969bbb14c4b7605bfca0f8399e3e409d6e17e48ff0cc08aeb0d808d0974758b92e082ebc890eb09189b218699e9421472205450e591a3ffe91c745c78625bed1d6a683f0dab80a356e040e8521c0f379a8cbae94e752cb280945ae02df90ed39afe62620b421fc55d6023a26d0189f7325d39f23365ee6077d4dab3ce415c112a23c187b901bf5040d4f250b6d1b2b08f43b7225906aee00038f8adfc41930a1cd3ed2d1d0739b7b4e97744ee9f258dc00bda05bb6f7580dc0614420d661a2aee9747398f3ea2efc4e58a8077836aa93aee5371b81cd892c575586a617621578f2313eb4b64b8f57f2b734e4ba0f99280899373729140cf5f645c72adc1379ade1c923a283a5dbbe73ea0aa98f54aeb62b6bcf6cfddbb5c4ccd79a350d47badcc97062942c8a81c3c369735853a43525c3dfb6483bfd6ca85614674913166fc6b626299e9c7be68fd9a7133809bc1d1d6b812a2b9e266a20c1c31a53d4e1b085ec74e9da08f4b98d20dd07ba25bd1747c8ac30ac77c427c279cf5a84c063de77c12ce183cf353f7dea94b20a8af1d0e307d5e94c9162b250650f2fdd7e85ed72553c35c8dcb8821834c7234e0dd2c4650468282d04910d63a188e8e8db08dec06f1103b1b5df140640e0659f07cf87bc71d7c7e806497dc1c12f80a0b98437a71f2cc996950e3f86f316aefb5e0b537527a70a7f08027af1e8af54896f2bd69664d3328fbbe6d88de73694e1d4eaa97515d7104c87070fd2aa0d8a69c127c1f1018173b1876bafc88aaf9477f36af1edcea857762f5683bc83ecd69dfa0d0236841b4428faf9a3d4eecc37364c6c11db51a026a3a63f22411667fac2068de81cae1d86b21797d0e805624ee0fae0eac3511e24ee3228bfc4509f44d0f972888fda0f71b6c319761799a528c981240d91978c5d15547a7cbcdd0c59d2c88bb2d5bb2672d6d29c9815b6236d6acf560d19a4675fe69f94b9acc8b8a80eb348a9b9e143c8243d29d3f7666c72e75de053d9d136c4df712b0e463e27a97d6c3d22aa13cf3ca7d20ab8f59f85323e653fdee30e0d75eb84b22815ecb266186b6511446eb495a6c7c1b594ae8bf15fd4f69c507974fbc109d882aa5ddb3aa84ab0d96d2330da69944c2b1a869301e11db2a9f85e02664b9911f4e3fea185fe82f7be0a4524760939692613504973dd2cbd0a8ba0a0ff3892734c1e9dde991b140a9ef23791fafc10f33dd89c153d286e6019a1c85582f2506c41d65e6a8712894916c844cf08f3c8d911431ccc26420a44d029503c79664a071aa021e5a37537a1fd8ffde6f05a980cc5f5df7563349a4b69987d65cc8aa021a83b2a39b809f35ba4abed57dd018454f0af91a579b5799f66af8cd538aa6d3f8ebf8bc63302c2ce395c8b4f4e65e65ce89e9f1725f62df52fc3065bf03fcae2d2dfd7ebc031552caa22220d24da54871b8fc0669957899ca077b9cd282e755acf1a0fb31e66a78c6985a970c85bbee6f1fc551e230e056dc0fc4e59e026a7a3703b48e7c774f5d2f2eee9195c583311c2091e1712ed5db6eb85dfdf3b69f2ffe560a12642f4ac01a4f9686acbf498b5208ac16b6b4749b63d45222013a3fb45926815a293ef0aca2403f3ad82b69dca4b3bc595fff59306ff20ebfe71b1f1043ebcb7ae9a3e157a96e5188d347a2a82deffc79751b49ea2f81a446f7086998c4161c9c35fcd30e1c8ecc4b2b848b1b231c3bc4fc31e9402f414776c2de4b7388a286c9ca817d12061a0d12c06d0306eeb0cb70def72172cd7ee3d4365ddcb877af4a0986b66df88ee5aa171db95f07eea5b797287bcde6de37a34ef19d5c7623d21920bdef70fd2ed719f259703209972dce640265c3884fd4d8918932f1f3e872b7f19c67f2cf95c7cdf4cfc6b5f0392f6ed9131186640c4f2406cc8f10d5cf6d7d313c5a4ad9bbe9ff491a5d9d87fd86a64209c9fb781352123d53b581b13859fac2194d92e25b7878d980edbfb27d7e8b5f6469211e2801aae77bb7195884311b4bef4277bd816ae1d602c4b2d27408831af3a040c384fb3cfb4c679be2d962334cbf52561492c900816f0714452421dca08bc43fa38d0c261c1b12083f2cbab632873d532d3ffebeb3961ed6021472a15a2aecaa838f5ee82d741aec297998ddc11eaec3c750e93459505c002d2b04c45181a6630c32e8ce7cc4cbf15eff8f90620b1345660c156cce4cf88863d27b051f747afdeecfc7cd4c6ab667c74c41e87ed59ca73baa4e5f76570b334fbb11eb4d30932bdf2e62e646ed8be00907f98dbc40ffc484b82e62ea3491672cd3416e45fb666bd22953c48bc64e2c3e1829b020729309c39ccecb9c7969ba79a75eee4427e8755e0d32378d6a72b04f43028aa742f4404ab09f2b682fe8b31375abd6bc2082082d5398bdaaac9dd4684d40d1fb579c2801872657468c1b87268b45fc8f0624a1ae7c5ff098d7e9e96a3892df2d1104b1661f0be40dc31839700df8d6bfe12339094a81b43cd5cde838c03749465007e5bd0f44695c2308d985c9262be3b2733b1d60a05bb86bd634f13133eca82437a1081023da4282d36940d200402a22fb1593839fc8526f145b1873862b5cc52f0b5c5a30959029baa3c651403a56bf7bed6b2d67d17b1332e179960caf0f5b2c52ad205788065565cfdabaf6e4080090f8ce22c0879d8b35705d2a7a51d85435c7a82601699ef71ca826f4aa65a9bec42744990fed4956b2bb056c16f4282588ed93fff462db4b3caa7eca69088456562446925aa8b5e10320889ea955ce66a581928540419499fe019d540c6974b8587d865e654c0b965880893b510b0955be690a92a0a29cd20325361b81ba70d96fc379007d50f62fc9da6169da0dbcff601887c32b6c88726474c6fd76c752484cb7d2b3b882d221b17b2ec37639818930f124575cf264e19f1d7ced71d8566b8cb81a997bb8bcad4e615bc38c7c0ce9f9333c160979aa3cd07eb2b582032bc0f89b4dc06ccefaee0d13ea8d0f2a861584158b2b55d4be747308fb827af16780d3210460250a57fa78fa476892dcd1dccd05ae23d087b65cd83b21ca5a9ae70bc20fe6e3357084b25f28c7f76f3b0609bc34c726fffd49167a405a006a6b791c373e780c813810233202f41a357370739d790018338bfc6448fcd324314dcbe70477d05ff647f67c17b99e294e1448130fbb6596c0198102a9975f74ff3ef87c8127c379b4728f77277b05947aa5332b996f454c04278e6324002babbb2939f0a90a7f3c6152ccd2c30015eb00e8822308173586d90d9df08b8f36b90867fcd0f482cff29cac9b10e625581fcb89782550e20b2179baf39e4aa8e80de23de6df8ef8eab8708bd23917548cb78cd512935b1646b0cc2863a597cc488a036a419ffb71c914ae776c60229e1b867ce24ac52e71100f96a2f5255239e0a81a91e189ac359eec77991e660631a58028774606336009f1a66fb30bd4108b446804bc7a080be80aad446986dafcd91a60ffb9b26b9f0c46ce444d7520d2b4195f874b0dec6211531c8268509a99ca049b44429f47d0cc7a69b07a2b5a5acecfd5d35c85728e3f6484de11e52679468328b39f27da71e1f7bb9fec356a4e2499e7d288adc6a506a081f0231c7ca84ff62b618c46cb8622362151cc1c154bb6c8650db7359d04c4b50ccf0bf1daa9a41e7dd7fe0c10490b283a806264618dcf4fae3a491ad7350cb115f06b0a59c1f14a97d95d0440845b62ed9a6f604b7d9529676c6ee3741f407241f710f994cc87c341cfa0ac344120e80ead9f0a95fd52b294c0daec59bc24acd3c86a45cd07173d075e4747bfb54131eef9740ce5c39d39c389f64eb27a8afcb1dca3a4f19101cc2e08c19e3f106146553d5a37e9868165e0a0da6c6777d343039fa586a361e1d40817b58e49cb42da61d367127b6e086dc4077415a147ed8306282b6b5dd7a10987bc19292a8e4f42bac01747de553098c9526b8ccc055aa3907c0b2e3a93b226fb255443449c443bbb33a56e8a8ea8efbeaad15166747def67006188edf277c5d7d230706f882b92a8e660d1359e9432912197f33f8f1b9b73407f72ef776815c256ced8a30812c8a78d71e5aaa1ef22ec538b8c53061d6f43591b703312e7ffd05ca25796e436180d78371b730d89994a4ba407d0db6e816d1057f4f8bff090f0b52e18363cfe93b9d028ccc1e0357d2135a3ea09746520df6a8cc38b896f35960fd7d3b775427378588032efa1c47bbf624763d4478ec28cbec600b9bcc4afa0a5f3b78646ce8b5cb1e5edf4193b8c609d9931099de9c4276005ec820fa5dba4b0287dd1ab5de9f1ba2adc8b80ddef73ef20649aac23faaa17f355b689c943d466c2e1327d963308dc5cac734a6b5540b152ff3dea7b72d5dcd3782c24cd720cb33b6e4842cdca79e843e2f6952ede7b80ee523dfb581edc43b4ca727acd821de7d15ca7d262e812e33700e457af396fdb808af10692cef0c7c95a4c6d6b2b2fd6fc88c1c17b87b5e226d7159102eef4297051aa56b796e9aaca57488cb044d968846c78a166e2304b8cfe22cb05a506a1410caad4daeb866784676630351128246c012678c09a50a7105cfe22e6d27319f4bad41e1577c441afdf9712465bc9561a37e97a58fdc938088b4694f4026484dbce640dd934c155338c564b32f1c0966889512c10e3b6db9e9d01823bd2e43c7e766642ed9b51042417d149f9ff1b5913dafaaf8a8f15ba9a00d1c4a1babdda522b883d3c86ed5a293a1aee7a3386de37e5c17e139b8363410f2d4138719d530f9735bb14445de679688af75a377e6a441beff5c0d67ebc4f989be5023852d8f5d4ed477870b401d54c4af296b7cecd449a2769aa04dfc89939598d90bb280294c0bcc667878a2fcbf3923c0f2de0fae2a14fbf6b99fc53cc10b3ccb920288992dee330e22e4d12f344386716f0aedd58d79167e02155c66396f07d9607a0ca22f48ed8799dc8125d912db0b2beb4254cf6063c337568ce54fd2ed034e114293ccf562ea4cd0219905c9de74505fe0985e67f3ceaa260c84003509138d522985bdd11e43204c0d130a3221f9a0ad70c9339df585c0632816bc75e62d4ce0d5be6c152822602af4873750caeca0abfdc3d76058dba1686df11027295ea88073efc91d3e4ed9dcf805ccd6eaa6b8596129c09c99991b415d31f7afb298ac961dae38db948cbb2e723b79caca33de16d41ee7080058780533e1b514ac2aa753e261ba04bbc1da88b490e99a170698c9bc0004f66cb54135da05c28d3252c4633e040e3229209dc451cb79cb51c5c9f8f7d3462ce20193f15597a6826ebfe804900bb5a0b4564cc08381afff0ffd9be6111de6fd07641e299be12b9e5228caf2c1d67e07065d350568870e46dc8a9887be4818562db26ce74f1ed169f4a1d5a4bd9a8a892e8c79b2538ccf0b3284d70c83af316f75681aa580ebd1170ebae87884b457267675be453e442538f2056134693a74de8003745040afc0182ecc655237ac8159d0ff0eff5ac319bd8a69a9e63041d805bf4c9229729ba02d9a7200cde8fcd9f4900bea5ae26a4c5607d3584b8e73b805dcbac088c8986e00a630060ad06a66846d5de2c1b9406d0bc611905bbedafd2f931b7eb8e0709f3ba54588f2c3bba8db9191b87b0d6dc60d726af42c696954b445deb60f81354da53993943e5d00bf4b71b005585244c1ae4aff2da446fc18545903ce558466be1b9cd42d21de098050e08dc2b44a1e0d4e857b672532e99b66dee00010b060747cc5e1249acfc8d632158c4aafcd531e2c624d6df5a69ed6dcd567106e149e7ab27ac658e22f59044b095c952063422ee54f36e9d7c7b361773ef88a319cabb7701d11f7033e1ffe4bb2ec1f3587fb7adff26a085b7eef976a40cc39c51a887851ade541af6298b309bc78a417540a81b1d56ff7f9020a22c9bcaee885addf167e0c6b3b1e8e4dc2dc0dd5897069ec8bb690adde5b2bbeb0bb73a2e1932dbdb642b922ba0b073637ef885896bcb4ef7a4b648fc925ff5b0eaa378a3b1f5305c0679d8d4c6640306a13acd98f7462b2b2f72eb5ee65f95ebf3b3dce4a059d8b62bcbba53bedfc978a90d62dee9d91a1e19dd67f8261a19963e1274e6247950223f76f7f9eca3bdec15ce0425f55d59c6ef9e5626abc010d0bc554dd95392843586429412c572f65f27846cf0bc31f9f830895fa4785cd29825f729bdf89f9d472bbf24643c2a6fd4a5df13c8f08600b8da0cb0ee043ff35f6c18509640dd1230285f96df59eba61238df3e63ffba9a0df363dc61350b8954588f1486b638054ef53e00ff8d720b055150b3417f2ade2c9d7cfa7d8e8b7cc1439645fe5b94b5ecc121814b6fe50d2ec1697de87dffd315d4cec1125998b2b2b3b01607841920a08e174e3c0192fa0a7d015326de9b5a136ab3f066c086cdecc2a8f3b3fc2ce9678f5c18740db05d39e8174dc929536b8ecd4413266f8c4d9e1f2385034236704cfbb3a27b87a7ca6fefaa8cd09c698f1d0bb22eb7d5e323434ee546dfbbc1346aa3562abf24f9de22d5f860b8ffdbb37e11099027b65803bf22c4b3ee9f6dafdbd93e6ac866d9922b9cf5bc8fb8175dd3dee5eeb3f2eaee5f7175ff5d71bbfbae7475ff57baba7d57b6ddbc2b55dd74daedafeebe2b6ef7df155777ff4a57f7ef4ab7db77e5abdbbf92d59d7765eda67ed78b61f7cbbdcbace213704a08980cef696aa7183dfbb4d003d9e73fadf1b06cd7b87da1c2b82661b94232dd246633c11f081e7731854ccf71f08a7f7a75c532a777da20f174e2c26a27b41a4ea58e1aad66bc5beae445ad5ba7452c418b5da6a847a056df5578900356eaeb932be1bd081625bd7414aa3207a664cf4e86b54b0af93c227b2629868dff78069e95fd1f4c3fdd0105820e8b4f6a1d76d9b0f0837cc78b0267523e740713776e2639d1735164d162d6d3ed9343b983e04d1aab2cff955fe2e2bea54a2894831e82a468f27cb8d494af41e0902d989bda8325b12b97e1997d3bcd4b9b6e83c25f86d0475297b385046ab10c3e51a1d0681ca05f199d541b5ce36784f0c6724c2b2ac3f345c2ef89b85ca4268bd06d9b509a56c830a3b4238bedad563a4b388bcbc93e011236de7715d3e30fa399b214e8628de30f3e1a3d1a49af95dfe09d2b3b3cce66d3963a983ea8284180fca11999aec6d38d980977d166fc13199f5e0fa9816a68820e35201e2fa0d4604e6450a04ed197c59c45b9157392f120b0eae181753b3d0cdf2cd989c749af2494e5f7642611b8d07fbe9525c15036d38a3be775784d4b1ebf335cc3de3a78cb39756309388b1239595d46ed88e4603e9ae3e6290242a5ddc290cd7577d546da1acedf9087472a57c45c372c952e3e558e379530a4f76234d9b736fe9be6a0c1593095245db2c059308e5a674b2ab9146fba6aa5eacd3675be25420e5308f4b3ad650409b31ade7d9355e074ccd013f4334f288e2102772bdfee3d10c174abc3aaadbedbd9517fdaf17e6d4674babce9c0d5605408b2d4dae71ff7be0bde4ebbadd938421dd355c25a1f4281ecc31ba2aa6c8339ec6bbdbdcbd426931f64717e157fcae5032af1087e71157a1c1baeeccda469f78a0e5f74cd59730f40e4823bb70fba8217ed36108cfa2e9e288ad39e16c58555397285a6d1d2dac6dcc4c959c7a982376598348a99004202fa130d5cbf47e3ebee8d30362fec15e1720a161aceee6938db95a3721d0d63f52e8bdb766200dc13c72b950d5ee56e27de36796e97edf082fea537b52354b3cce15468736c5cb197491f98908a78d12e206f66c1a1ac87e1af09905e442e0392bc0c6c628923ce54850ba4e0833a20457ead1055effeface2c913cc12eb605eda9c070a0c4637324eaee356de4a47020b38168d1bf50b38244d536d0aefab3bea492d7cd988efb86180ac272829f94ec08089cd980fe398ba7aef9d51484be89b2b7d523e8f05f0f8666f5607463d920e8fbb8f5b87977027e45dc6b4eea7de42676bfe1b9758a9aa1b6d5268642df381154a764f5cb3ed9388f0bac365b0088f644fd06701a3b058c0d45b17eba705b885e0f99750b2b58af1654690ff4d618d078dab19851d8d0a3e04be486b126533d97485716cd455123a3277150c61a4b6ce816fec2b2ca41007eea52fcc520949a6bdbc140b012fa1866e8d63c09d386e3886b394be52f0a80b54c0b4065a8e16041566444877b4c9a1e5e5456ba17496aa4131f0aff9366618922337eeb11a6775e9b67d4a9ab30054db88444a5eed3e5173c5a701d7525b0e19da1f9ba15e5dbb33e22ee7aba9648c3e202be9d373778dea8170c2d54a05c09a099f97719ce4b6b11b62480819830bac3d71a376deb5047f77f6d6c06f1b16087ba876efec0e7fea1e51cdb6cfd506cb00e62187832150a7e8271f3a0d549778502706401025a2b1476c22dc0ee82000f6bc085a841a23c3b47d50779bbdabf2e55003dcb70de2dbc6a07f08affeeeb4623ca39c040882e7c3533a49e102e0205817a00ef691f8f0b3b11b46b950977617adaf49d0a6053d30c91fa0560e30dff3532bfc71633b84643a2897e35f20c9c0527181963589e8fc39b8577ba33a800275028225ddf716a7d025f034c0b07dace09fd6a30eb3bd86277aa3aa2fc96ed6b7e1cdbc3bcfc34b0b1a554911de819ea81c6fc3afa2bd3c5ee281cf5443ebd931203a00516d06ba95ec1fe9ef2b89fc0da8f7cab803e921e856f22e815d213f96601bd487a0bdf88a09ba437807bb9d3cbcd7ae593db47dc28441759af829b48740beb15715b884e643d05b722d14dd633ef4684f51ab97ae1aa99ffc9852129d62855975086c7210a926a1e8f5575d0c7a0e3537c5d379e4c8fa28d8c12628b819b5c937ae7ad501b591e3a2f54529334a86cf837e8593ad1064ec1688849bfc1f9fe1bcf5024209d6f2beab20e19539084e80a1fa95c443f05aef8939d761616f3d71865ab892dd93d6c8fe5d464195f379b7569a2b4f60293455284b3010b0d8c4c7fe4d509a97f947c53879d297d85194d9d67a47a2f615fc52a179a49b3fb4cc23f9d794cc059611d5411848a4350b538fd8da67f5a1e9ed4808d1838021ad88636850e8aa20355027be0c5c98ae86c2ee699b8cf6cae0354c3f5fa423590bea300918146361fd82442e00b93a758fb0ad69465733183228ea964ead9c4d8a13a283db1d3eba7929d103144997394fc0a721a2a6edeebc2b288e6aa1539a2d8f6429dac95bb38b77968e6834a286040d42e3f618c1bca98c3adb2d69e28dc4e9dc1badb4296f189f691d0be56c694979b22b3c230c9f897fb20e31377d85703a50ec85a9d9149ca822c73491cc10811e7358fbaf07eb6a154d490d38604dd1ba2eb2e7a1865646c512303b1f0305152fe4a41ab467fae0abc0aa1744cb29d1de03328f0e4751f9d47b26974a39cc1de5d4935adc7da1c459ab3ffbe61ebf518dbd8684efa41b9828b9c68d6e5e83af8cf85aaa086391305b03ace5891b8ee3cadca9b87c1b41deb485bb596f55658656d2bacb2b6352b592daba2def98b6e582632cc28e3993295714619cb3c13c984d5cc839086fb9c11463d9cb6375f9afd97ae3f7c71b540974ab5c117f125beacc4265a93bf7c02041253606336547a9a54b4cd70f50a4e2178d1251c510baba164f1418470b3971873a439c2f8a5867ead0baaea13bd05dc6d45989737c1e19852f3a9844e95ec1ffb6189c5022f36ced8ecd1abe4447ffaacfa0fe15458e032bdf057694631fe94910f9fa339f22861c893b040d0ff6bebf736c51ba4bda8b5c62e97f1caea34d604d6a4419bf037d9c1b2196e854ca28899a6e286c1b03e507026d256396c472497136d3c738702fb33f70b4d62dba134b6d95b75185da8ab25ec0f91e8c86aec966c7c17b870c2f583304dfae429b2403fb059bce4c3dfca47972bf231f1174cf5ced3b4895988b5ef42f75dabf62584017fe0747e76b67e9e27534241c04f73b8251470fffc94fd7af2fdaa13594241e6a73d33436c2f4e2a23029e818adf8f19b3f2ffeb22690905223f3e9f9f3ca39fe4214a2860fd734f5c0905999f3cc11f9eb4dfddd99750b0f2ebcf430905af5f9ecddf9d85dff3c8945020fe51777cf859b9cc934e1774807541775fde20972019564ac85bfdf622fc8d9dfde9b75042b5ebefb5d24bc80bfeaa02fcc1a6ffddeebe84eab5dfae3e4ac87bfd4669feddb15ce02c218c7336ecfe9d1c1bf5f5b8ac884c440fa5a2a451b4c2bd957d45ff49e18ef3e0e0c339306304675342efb2e567ab65a780c58a4ac8c3033edbd743879afcde21a881f5d920d8fd466876ae1a7edab57fb1f04290428d36175a50c554cdd4b55e554a2c21915c8596b74e9ac8e225ae5ce0dedc0ed271542f9cee7f42d869edab194ce196c4cac89e2211debb24f94169ddeeaba4731f92577e209cfd73b13e52892d40472c0d158b45066e461730f9d1e487b20a2c582163590684228fee87ac271823028a342e2a714d266242a0a60e3f22235ca0302c03b456433af4a1eb79b4809dc32674ef6f516faf4a917920bb931931adade54c096d3c086394a448fe095593eab6c37774e92544981fc70f6d4df82a5d1507c37c4bfc544608217409a80397ca1f2134c791a901731b6a39fcdd337a1054c83ad97be8b04a24bf983ff0fda93aec1d0aed35d8eb410cb2c7b6c211424c2910b99dc7b097b45c30017307c5b36901348c7ff15cceb14212c01d582b84f547fe4be28448664b9a63d14a5850a344bc0e39ecb5a190107a37945088ac11a510d1c664aeff0f8a929986fbd690f45d83eb0ffcb8a371e3fa14e449bde841a241dad3f5b70e59f30e46de40840179a3d6505d31c7ed5dd5db7f42f3a584c078f8e647ca285353fd5105593b48790dffb8fddb2eac1ccb47a9fa4f5d9958a7b8e4c15d896b2115cc60ba11e4739e43d90c019fdc642064c5af93fc2f9bdd4d2fe3bd366329d3379bb4a4089c783b641acfddfdd82e68342d891523ddf956c6af11c4c38aa824620cf21fcd0864326047a63183ede239354ffa8fe1bc56578ab8552adcd75619a325f1fe4c8eb37c04ff12e60071f40a6512f5c765ce68fd30520eab78949fb26adba11e92c0be70b39ce217f760a3e8de40d87f8e45c79fbe289190038ffc0c82ab30d71cf44431aabc8afa32a8c1dd6ea9241f5ac7a37d81dbd5a14713ad43e7d7311ce55a2ecf013db806c0928401344c5348a63a5edf5c767e009ff19e516d8c2b0ea3cdd3bdfe75b6e28a3d1528df817fe184c9185ddb7ddc6ceff64891f796ccc834a02eeb84197f3281e056257396e2e2fc6ddf7a49416ec0fc886f8af6fa5e501119deb9ac2172df70cde43eb1aec6b39bc587418567679c2068e24442b82078318542f74669d7b08a259539aa63d55be5424f13a5476a956b080d708350924764b5034ab70555e55d9b92fc53b6b35f92563624c8760ba9b2ab46d86066f991cf3b17fd9b05e7c68cccbfc2ee9dc238c510fe79d6f426cd9fc1674e3cd790ba0adfb1a439550b57f19f4bf0e43a561a33e4bc28bba6766939ec79b96e5d98e43f89ee3a5d26676782de95b6aa9056af8f00b55add6546d6e065f711847478577a475555cca5a1462527daf69dd86a116f4b3eb8fe9a18355870602502f25d194dcf063110b583edc081f4f3d1d9c175e4e537d7a210c6f93659fdb24a25368d33e476d985a740a55eff3e6505c30519fc861ff0697193436cdd7fa8fa8f0c18f2af2b608de141f65b01d4198f0da6d61439bbc6cea73a108746a2a6ac7685a16bd3c181db6bcac5579b98c808546dab4cc90fdfbb2c445d6d8bf182c8141401d098b02c47e62b53f97bd9fe541c571c06f22db58c0c68b5602b110d660d9810740289896c17bccf920df37e1fec3553a68a0c57d69c8ccf34461fc4bc91960a945e0e50ab29f5cc34392c3908668cf2949ad690b793610d41471a00be632c817c8900bf6aea7d6d57ad3d0333377b281d805f17cb9ebba1ccc93e48f00b12787bcad954599b14b5fe8b72fe54ec9d9614b4175e44d530673f972ca17b009db380b382bc26e25371ce7ad553b8943fddf1cda9613eee4ea92e45a7911b8df23b3afeb4a27755c0f76f409903ba1495bb14125394c4bbcde68fa29481e0d619ddf29aed6520869550841b0c596104aa809d0ed701a52baf14296a1420b1669ce01a571a1e4282c8f039c5d46ef9cab468d1fe9f4ab483cf73f1c7002c5ee5300b9d967c9623ec1e2233d79bc2fe17d0f73268f7b2efe8c39497b22c55c41a71ccdbcd87bb1fef1505d50781f95966ecbe5f9f26e895b6d952f0925a9ffa9c968e1d4edc8994388bd6a8f5731c339eb44e29d985e127764345952e985e23a6f374352a2fd7134faa96cd541a1a508fa6b023b78b9e056aedca5f46320a913112980471de7e0338d3148a0262ae7a7a29015c6b7fe947f4ab2a0a2476c2bd9310fe812de304af77a1f67b1be288bd0bba127288fa2bbcd3cc7536ebb290588000235f5e9ae61dd2da4836355c0980717c79a5bbebe188ca5e546f5c43f350499f5dab40f2681ea086a50de91240d2a29e9cb02b8be510057c8ef57fd42a97a7e56ac98f6e06fb1904ae32ee815b1551090f40658d6c432bed57546a19e38182fceb653a13aa7582a2730e287d94dea4f9288327a3a0a1c12ed4f4138054f51bbcdeb950d4d4d270f1477ea3d412b375c01c53f8616e88671476c363ea461c7cfb499a13766420c129e2a85ad5bc705f1be190b7b6f6b48cf74a2ca8bdd879cf4035fdb470835b4e70e1225dd9e879b7e399d51da32003ce81d0b00a2cc0d1602ef110eab711867eff73f41006d15534a037a5442232c87f5e11c8572c59b6f35fa5bb39b1d7148ce71f84677e4776c3b2106db591e951143ec2cad498282e8e74de54162aefccdf038a69c4fbd18dcbe38d58f15a0de06b84eb2da31cb7671c1c6034a4ecc7e04d4ac23f33b0910781531a9428cd44ef091f21e1fa72d3d4b62fd9ed9e6efaa09884fdf4e6a84721bb9b4ea33b6aa3693115659c33751decdbff545515ae67c05f4669fcaf25b920ad32bf3baca712e9d1906ddd41871e7092e040c54ccb6684e6f00b2b890b560eb4b9e3eda0e362e8bd8d8a87a88333f03b9f63c7d66190a38b6cc6508eae2c9fd8ef9d640762f8f24b3647eb1fac1f5a628feebcab59190767acbec9b34322ec37f325ee1279229a4584877d4704d967a8b897a210aa9a38cbe89993998aca7b31eab6929b361a8d3083686cd8267a89c8b5189250bd578b7d99a23f7a9f97551c19f175183bf349e42809999937a9a1bde3edc67fc88534b31dad837a1dd5d1f3265c21b3ef3366b8b68294f55db5462d64becc065caf4c385d1b9bc856f6789be68d7d2d40c7155620ed40d57629a8716ece260b08875c7fcb90f14038298f5e9a743eb69b730c6d1d648107293a6a32e43d5103ec040135a367b74a76287d284e439e4f17fc3924bb9f2f745bcfa1f27741c07de4e926905215966429eafb5b3de44aafd3917afd04e971697f16d3a6dc19cc0cf98d21ae00320c9139299287a37955afa7d060e273d8dedabffc04d83c2879fce0229d0a6a28bc809051da198118d26558d7821c2af465550429a1dbc75f899ea0e0cc9cd714a73fbc86c8d3527c7894e14ee1c34bf6bdb6be9b281aa8fee1a6adb29a8e002d97ac84fce063f90cdc084d99e3cebc18d3ec37705f9dc738d05c36b4074f8146ccafe48eb661a31d61079e32c9876fea271d93cc12bec6b2a9fd5f1172706cc66d24ba0f6ac9ad4484a1f3862eb91c2036edac8855f845348309a356dbd1d6e65ba77334c764dcef54ef2307ba6e1e7dcca1175865528c21813134cbfbf3e58b9608e7ed810fec92ed96075cef555defd07b3c199b900686df425d32614ee03aeb8bcd976c78f638f259024a3bdeb96026a33dec93c17a30efd78787d3dc62783010a4ac43f4eddfd3a7ee58fbcbe60b0c55344ac8298bf148ab5cd06ae82672902529ceb0b4e2c6997649331d92705c0be368c08396a54eb2b6e62b2c46aa9694964db751fd1a4fd2172624a7cc5e117f76c32fa1a62faa25a550b953a7e67df57a9b4f65809b21457012a6a8ed6eb89125ef47da878135f2a1b1f3ac6691665728e158dd94230b31b7f118250ae235f871ed7f8868188e37629c8a8f93034d91abf26d5788fc8a22c91dc0e2ab829d800b0915da43bfb512956bed8cb34191acfa4d68c2ef7543a6ab19beef1082fd606924a58f16a2a9f0106c39c903e1bf4c521f85aad9e6af7f0749514a7da18729a52694ffdf391da3594d61dd1979a25616bc3b24e9a64a95954ecc03ac8a66f00e1279cd29970061c66b99bbcc449b1694c32d45f7e32d1dceb8d7f520445a1c25e28ec577ff83ef0c99871cc18d948b1789bf534012fd1a27458ae0892b1c8cb2ae06abe28e94f74e133585947c57abc25072173e7990612151ca123d854fd42cd3e0719491371cb5255396805a83079dc41dbc280e1c3080ed8f886fcb323c0c3befa15227142a24c466e458085f5a97328fd89a3bf70b2f0795d57bde9cba34cc5ccbd4aa31181b862842627c6cf9eb3e22b8b6f99584517e1a0912de8b2013adc46aee57483f5b85cfdd5931aac32240378eca54fd29951031c46dc3fb84f4778d5f2e06c0fae481b2ebdf9e82d710cbf9f11c35153dfde31317aaa07af4b7a677d0c6f6508c01ad907612c8df81d21fc74989726a13acc24f0019bb412f81d15bf8dddf17d58f8371a2a32ec60fa10055b9f7f943b63398d08459da2070294770b328efbe2ff0035b0b36c84b176c54f7a7fa333a17349ddba2e28ba5be27d29569d9c3c22b599873939a193891f59ce45d632e820ed9be51c97af46d8b8134b7f3979b87f448abb981e56e3ea187d69556a4e58780bb30c435c01b2b2286f7a0d7008b7f3854fc587459a9ea3806b394e194bee3fc4223893cbd8a328d79845aeadedb4cfec415c6a682c1f6e07c7e94fed20f396414544e2c0a6aa9d41552d1d9b3920b9ab41ffae4e17a97a8010989a3149c67bd2cdf55428ae8d135efb49e7350d1381a4fe65a6998efd4f0af86e49e3b7fbf178582c1e8c8fc480ee630850944aee2c0021d12829d0830970b9a95a7f2c2aa616db962dc75f0ef0dbe8f8a8ff5bfb929d5f443f5624afdc0b945ebb1038c1a8c71f1ede7ec009f5cb54e3b7c52b4ed25530b436c71a95e86c3a5207ab3b0f2af3c1bcf8670ec29b6bae89dc5e4d6a97edca3e1dd8b06acaf0aece863cb426cffc41cbf02dcd16960ae97a6a50174aee4ecc5387b097cd739ee37062f3558d1433a9d3c4876096435c26e79f5ad1eb4b0c827a9c152956a80a3b0d1468ae63d503d069e5259ff799789dc285bef19c24d3e6ab0506584be0ac9846a87913acc21e023b3346a2419787f14fad1b400bc9c7742031000291f9a0d6dc8acbd0653bbdb6b16616466e88fe1de0070179dd852ffc9cf4a0e95837c3354a898148ac20a3d650ae9db1a0a59c2cdafdcb583c19e038abafd5308cb26fd58af42801b21bbba0862028aa2497a670a693eeaae5f3eb85e2ad81f5abe110fea073a255735ad4cf5fabc880e6c5ca8e99ab7730661ed0930cff057db39bee3b3579ad62ba72991010f07781b9c7c6a517e7426257b4caa2982a2ab9199ff5068fc48060d45eb27f40c3438d543c3ace01fa041287a18a619819d31a356b3d5d6195b5d01fe615902eb421d1bb1c71676e01712d8833aae320a0d8823c0d7d661c60297b64501e6a1275de9f2680fe77e223f5cbe609bdc019f826012da4bfd6b05bb2a131c63b883bfec81cbe23c6bbc853238bcdf77a6c4b018cc849cb4241c40aae2c439fa31e819834a7c56e733c087d279c9ce9c83baef9d518b32cea75e2f457efe81bf9fe02e372d45aab35e80f6f17e52d70577f7d35d749f74962110eb01cbfbbab444f0d7836524cc609fcc022f1a301e995e44031d4f195b84ebe6faef584cb9bad61a85cdfeb5253aa3930856bba5fc27eceb5658880a93cc35f81727e740aa128971771ccc64bd8071cfe65025a05121432b4c6060ad7034b61f1be3cc1acca3529b15275103eb33cb4dc99c8db3a86babd56a5e9ee0b9f4543dfc8e42b1207a2873e06d5d125154091aa595b6a0732cea38469c28d2423c73e8ad2c9c0b740aa0259009bb8387ba9417b0e5e49b29c4c6105596e1d2ddb2e37775686666d09cf630057eb1a8fd2ee80cd91c47d85c772915a86e0c6cb1969e3f2ce4455afc8a2ef8c2506916e8b888919bffbf9288d5b45e746134093098069663278622b1e42f17f98a063b5d0b8a1b5f205e4a7628666c07214937f0af9e0d9a86a98c113fe8583d9878b6247dd31f72c889f77a61a64393ae9f56398a667cb958e64ba59e190f901bf102fd79693367d8caceeb7238e4fe57e4f88508b67268750c856ae53c1202b0992e526b83423fb88a25707e729f604f8fda3cec651c4bbef4f6674b2754b6280913ee0d8ea26d4e79a331ec73d88912253fe7324bb77c59259ce7865b6d11c503291944b405d9233e9f6c57c2d7aeab6b4df9bf48d8628541120eff36c246894da0be3a3cd0ea00ff58910b49ca715c97e0cbbb131ba718bc6fc6e8149a1bd8886f048a41d61039b94526104d1e2bca32d0f2e4095b2de1695b4f9b4ea1a221ff80794f8f7c64e3ad420c44ad527a2bfc072bcc83168ac6416f2c5a7d4f3d11bb644bdde523e54feabee3688683c1be9c2333be8711e6136608a2f1e4c2e5c5b1c2cc80b3b0d111fc1921d828a196fd2df2d0b8c2c5a2e272e7b074f20c4a6015ab8000f8cf5e5e5285842dd001eb7c9132e4ae10f7b81fdc62eab2c731c3610e3ed29601531c58aaff8f85fd71df491970805b2723a36a966a047c27e1df10ec820700c48766eb4555408da69009bb946a98e44422024e8696f856e4d8aab374ea65f9ad3e82e00e3d5b549cc5993992f8788117abcf9a433f7601f97a0dac4b3440b90574b9c8de9365b77e7d3478c34edb81d6b4eb34b90907a31428415d932c5df717dc6905e3456680e8adcc1e8cb012320b210ce589692be72db18e24fb16dd7f4dc649352b2da79118392f5e2df25cb8a9046b803cc96c3145b38ccb784e4aa6f1a82805d0df2bf2af94447c12a6585e04c695efa21e2581d24e0d98bee684d314f2e06c3636e98fd90758e69bf852b550ca39d7bf8d4997238b6c022db6453507f00f0d92cae5059dcf301b4a8dbc8e4ce31b08bd63e0539010d2e5d1c55a34bfd252f9c83de6dfe823546b8be01be6e4ace2a8875da6107074e58e522c3e2f8d16c556aa1b6cf2b80757e44c1003dd6fea80eb13c98ebfe3c4f55ead7839ee8b1d0e683a133e8f52c70fe25b0be600f54a094a81601049f1b3b1f316cc42b5e9f6e82cdace0956e8ff9b08eac14d88e46e02e96cab0b2cb21fb8572d77748e9f35cab2c6b1151c797335090e9f56dc43a9827e148ad4c0d5b45bbdac023d027141fc10fafd864a9b62b424ea1cb7cc1b668759cee599b9b43ebdf48723cda1b55a85a3706a4f291313cf22b9c38f6488016e8eeaf7889f2caff51d86a029c7bb5287fe2306d2e02b4ac3b6169dd303d767720f658e93e72089db5c971d58fa2e27b661f5c091456cb90481bc8a3922734bf7eed769a8e1a25d916fb55c434cebf1a4c59924425b33c0bfa310bcdb987f9788473fec1c4b04aa865728b931b69222073824a14c100ed89c28364ca635941bc5a5bdd8a20d3387e631c4ae30d99d0c4c2715eb3510d03078572d6b9fc9d39249c83fa7ed4f3404997cddb4d3fc01b45d05d4ab88772dd0b5a2fc20b69838515fa09900f6f905a788c7f70c54d1fdebebcec163eb3ac9848150b003c340a2016a62c83375bd855bd6a234384db59480b07109a9e492219695400ed02fa319d98eee8e5944dfb438f25e1728f08b896a52276ba92d1ab897450db0bd342a65df5e936c434e19684246e64dd30a49bf503d90f895a53218dc99b66520637f32ca1e81741d864ffd837b55a0fc4b0081a43433be1f86edc676ad70844026130d766a5c41c94f7b5a763f3fed4440bec61a031eadc125fc44f19a728c6b246ddaa6812309183a54827f6619210229ef73ee8ec1e3e43a644ccbdc219ad4fce0e577830311b5d64e16ba2df96089f6e4f5b1957d829cd90432558b20ad538b03bf1232b426443da65da61f9e943e95f7719dfc674dc9529a8b4eda0a8d15a95f4e5929922084d8a64f0e76e790fbd85dfcc9d8c3276bb60ed9435b52f5be9334b060d23fcd55ccf111cee78868d6fc3327d891f13c34e69b408b9ee4489a1d11cfdbb709280277a12d5bddad8e7e1d744120c47d0b3dac9b20bb237e869ed35df5fade30beb61fba29dd43679d78eb79aa6832b10a9f0ff37ca76b62f862ad3f202cdcf61bd8aa9429af8aefb7f9b33f27a07cc0023b673e163e87ab894c81f9382cdbbb27d5504702e413531e526c6030260e13a45389fb083b8b3322a933beae339b28136ca6a818658b1c408175924706d5ad47ba3d72a9cd775fade5855af91063ce482d41bb5000a4df9f3805ab8b32bce9e96c237f9952851ce0139f46167925cd119bc9dac716c43e5d401c8ad8facbc5b896e11e0d2b27ec9c0c8832e211083bd8c359e574cb830430bfdf510ba0aadb3b88351a1a96f758103f019c432fc55beb883b44da7a80aa63fbbb95fd5959779707451ddba06852a14945469a86eca8dc82e00be451777a2128e0acbf19f087b93cfe68451ef041512562a35d0b2d0f9b4fb62d223d94272150689610039c320f64eff4b4c60d3376a5d6cf77e7e3d91553c198075893eb8133d44375077497363f14bf8cd1c09b98f1888ce654235bdcac830b03ddc57f560344eb3c802130fcc70a18b9da61b727ee31bfb379257fa1cfd51eb878e0d54e3aabed595f4261712ec460dffcc56238185a686f95062758b621c4085a923f7518f1e49d508de6113e5c37898230db1100a948b905253cb07706d0fb6ddd4061a40cc60b69ee01cddd2952f04d0b97dc24ee20d1467d32dd20b4863e3283a66c80c8a4ee0df07606429914801836d36daa145009519798ae5de4ea109886016a4b16f45cb997cbc306bda313752f66dfc4d3dd6ac8cd5b799a2ae8f87d4912cf02c3da68187f9752e5d3b3277e3c12a75ed65b34da5afcf8dba7e2a1b8c75f282568842a79bbd2ea410f977cf7e32a48c04a77755b2e1f0fab75d8aa8a20bc25e434b80dacabc4e141627083b02fa183b6c09061bce41ce95e6ec27d1628bf0c490b2cc3a50f2009b12a46531d0277d545b4fa8fb7183a6997d3b9867f040b2d20da3b7a5deb80e686119e203e39a5e2190bb9ceea9a7b53340994c93f9ed743785ed1d494efbc9744b9409cc02a3f1f5ed1f016046080b6d06d1a80641cea62609755140e00b23e18ea61b43cc30429d6ba80bf170c2e345f97824225846f51186fc785affc0e2f754a6c34d660e406e0171cedd786a9f070ac9832fe969b459f5e8c2f7b8f11c315a1a049e3cafd51a7ef19e6d96212b6048e59799ca900b29e204643eb185d9cfc5c86a085473dec63c7db524414656eec6f4445de78a032e6a28b6bca1ac3c7f563a4addf966c34d4602faacbd6167cb6fad1ead3c212801ba6c169c541b8eb05a8aee2631ab11c6aca5bc8729287b9367bf0b979feaf76e4824e3e268a19295765af9beda50b4a3f9cfac87c26a153788f64d0117c2b2120e4eddf567071438218485c4c968a40c31f740563ded7c86b6221f3463ff69a268ae5e8832d8537fd2279cf1676e9a79c1df8dea8a29a679795a9e18f7ce4467b52469b545d276c4555977fc7910cc3f96215c595ed27de3fb1ffb929124a5612b0150ffb911c2a2d59a87ecd7af4d5dbbd63fb0897b9c107b82847d23f7653ecb38b54717444344e874f752805803ed43016d3ac6c9505986f6d39fbd392e0009158b69b3ec0a1bf20b7611fb8a42b2efb53a8d6c04169e5846a082be4d8cbe2024ef24db998ee0c923df1f5e8b712970f0bd108ad5a7ebd1ea757c301f760d94ab83e99975f793d3b89e09c6e9024d36752520dff8a04ad0954a3e2929fabb52596d9a3cc6b837ce0859a1f67f43420dc22a99843288fffd7c20cb20e2df83e0e709cd9bf9338c0e703e8cd4a5f7a400f59d072a85b810bc8e161fa30b054e3d86ed18bddb0fb26e6248ffcf31b520627b56344557c81cb9fdd85ca19a85fe8da47623e30965d1ec61faf7968df8d9ed7ed1d2d5718d99cd52738c60a52f06f6b21d1018034ffe5d111f04266f08be1d1c3559e818edd76ae855fb5a516e28c95a23764df4456676cd45e2f00b041fadf1eb1257ef97f2bfc147908fb2ce1849e58fedb60877394301defa14b90e3c9f32ec47d2f718ac1ebaa3d1fe241eb4e6f29eb9b74fe9d0e95119580082906851e4fd085a957f42ba365a20e8ecc2c623fb614a2b51cc2efe6e15cf8afd6fedb396e8fc012e7c2e4102afdbfbeb6e737fec0c97ba5e38a9e5889d2f106a04f8e4db4d6a004df15f25410006c19665e0d004a9776373d39799799be3621eda1188d84cb0a64b96bda01578e89d27899d1278c273aeea961de0e0c954600ea4203509edb65843afbe8f2b44d501779942b7cfe92292b20875b9648e3d7f070435fa7687bc8fc12c3577bf5bd4b49d6fb6f1b7a5787aa136239f6d8e690b12f6cc7b5122bebd81778ef044b507ba1c4bafbe81dea8246dd378b831933477a3821ec32030239ec5b025203371777274d2fec9d1a874b1371be02975f2abe745ef43c183b958154a00fbd55ec25e0799c68aec1f2b0dbd10520594e45545cca10e78c49deb689e79aefcaaed2c0ef3fb7e20e465d79a481d516f721dce63828c49cfb7c6921231e60f4385d63bd826e05257d19470ad7ccb528ec34b40ea23a8cfaee9063cf3c17a366bdb4a0351ef6e0ae174411cb88f95cbd4b4fde120da60af6d925f4fe5c3d8579ba604834654c2030adc2c959a4ffce2bb75077845828982b13408ecbff8640c695dad50607f92f5a0ee437c1a350d1e7bf21319f03c1351c070dbc433fe4f1b125bc5299d0e11f9412e6654e16efced0a13e008d721cf8c179ae3584cad401bcf01bd31f622303d84f9d019ef17c0300108b645d7df9ceaf7b69eaef274a890e770f1e0f094d6efe8f6c701375b40e16946c1d9819d7fe8115aebeea28b2d3b6b92a5df216df6af713f0387c763ec5066344ecd2056ae13366b1c7cd5880473aa5465d1349eb511fb9311516af31f034f990d44d78749cd291fe30fd0a4d9c8defbfc90b89e5c02875073a08054dac1979412a8d81ddf87fa6b6ffe8a9bca206fe47c12d2bfef8240c81ffe18c79eec2b63be1d032b2e463891b0948052cf99dd2301548f43a844e363ea304442216d2a5755f5d44cf2f6c405aaede6402236f1849f864b02a5c34e34b5533910748ccb02c45b6df8a5e1b1df661f7ebd11a7b0e3976e5b0d1718364bab483095e09c7a75a39207920f8b731569bf3faa8edcf27c33f82d1f78d7f88ba01321301d7e4b9df6a020db483a927464efbd507167a1ca5c5b18a45f82082afef46a39b54dc303b84c5dae04388e29c987a5198a1380034b8b97b0c2c5ff61fa0d7422055799cf97bc86479a11530ded45de412e1501f586c79b66b4336c1fd9225f4654cc3f3e56f58827568c1a0a1a10537a167b1bfba15be1faa113da569f444d381bdb04d12a1ada1ebd9c4466f5e28670244062742b7da674e5851d42498e0a8b0d8ede709118ae3f51807ab4ce2e6331149144c8ade919234cffe9805b5ef2145fc2cf1eccfd4fc73a6517f2eca3cad8b9f5120d387c5ae1fe6b86fb4aab2153ab461e6f6fa8a0ed787b9433cc05b90e353ca737a31cd23cce1546b273606f3c49c00c503d81d91ea11d5e3a34fc8d7b1a4848b98f25091068f000dc2e2907fd5e77c06b6e6db715dc2498c72d77ad288a2412c458b97b37cbb3e3212177595f2ce0f2e40176e6a02b7b1dc830a940d136406cfdac8715d4be2d634a156e75df4d1bebb53983aca2144733ba57a427415c2570b38a0f8ae1d6fd7be4cb1b8345cbc5e6d215b229f169f66f17abde4820bd3ebc1e88dfcfe9dd84caf1ba010269d3f7b936e49387f6048e6374b371dd0f9c5182302e04097911e3190dc5a304196033a57cba231e2aba392a68fbf126d9f0810559d95c26cd40b11b290fa2357f94fa7121b58059349848cc8d52953ae33e3896f050fa061f6a3f6ac7a1e43b422d547695951326cf4cb86a78cc4d34d3f62dbeedce8dd7501a75fd15895c83b603abce832cad2860beb6d1e9d184fb131856c7fcc898a24d548136dc4de858a2b16ce3932978224f937dafa8fada5fb48e3d9aa31b0ca76979cfd9dfc406732e982adc412b5d359a7aecfa731ca676b00ced9545331ea112652062078a45a38b839ee0e853ded2cee97b5ee78d517375d6171c11c1906143dc952d20854acd50a9791269ac83ddd2dc635e00eeaaee7d141ffc825801be563c1dccc403a3acd89698650aaefc13c356a328a73462eefae96463515df5122e43eab1a996d668bcbccf6b1639991a50e4d9bbd6c73bf3bf08523b925cc0b0d25f7d066e627b0b621fcd3c62451d66403cebc5c6dbca1de056f8539b5811d95125cad9ca3449a910909cba5d48cd371fb479ea7fff3b93ea5bcd560c11537743f5bad597896f20c11bdab130755bf801badb3c382d4a2a8c3671ae4d855d12cd7bf6134a99eaef3e50dddb65ea8d37eed5028b1ec46f29c3200dd10e67ae8d3adedb841d8d4c740429c77dc92efc8e71d4ccd073de843e8be861d5d2fa147fef563a6765cfa385ca8bf3f3e1f2164a661b771c68e680d18bef4b6ef1e92f2d9bb91d0976e43ca9aedb2004ae7801139f5f152484edcae4523cf1c1c8ce92843ae7f96c4f70deaed26593463152e2d5ad12118d32a5b6a475456e352bc3c8b44e693e9bb253d2ccecf3d4cb1ce60483511119887149358a4a7bec9bb2de08a4ce652b63d820673ecc1cf98ef5d628b4edf8aafdb4fad7b9ba4b03a914ef1e9fd90645a4d3e890a96c2995d01da175d4a1da8b80842d2ca931e257d8392ecfe591615f3dde1968d3d01c3d06f2e0873a072d058fffe4494a88fd1f70a98c94edfe5122238645b574c594f2c1f8d88e85baf14a7f6a711010b5f685560e10a30005ebbf481903a1efe3f552558897478ef1354c9085d335070504b4e66d2c1a4bf38073be72d6fb2e428f4a8df60879d1bda5edd78b89c26fbdf08cf02d0fc35b0a5a236839e8e9527f123f992575ed364befdc76062493c1caa5c4e0fe1c280e00bd6e1fa799874463834b8c038896bab91250847c4d9ad36e70d442c7492a4181152ecf805f60259db84380602f71d03947b7f2c21ea272d9afdb3028d7b125b8a691488ca2540b5d45b7fbde5f03b570474f89d7b52fd460eae48abd451cb6f759c88ef457a5120e725e61fd6f3208ce4441ab680d1e47250ea4eb3bf210fa486e227598d7fe3be338a9423f47c55baa326b052c71ee21ae828b7f9f8baa1f01c6171bb0fc42504ac9c0dc23a0074d095a1ba2f18d50191acf9e77e1e1baa1cc641bfd3bccff8b3f449f83fd975e0843e9f24e23abe8bb2fbf1c6aa7eff6beab79c284e06ce0d53baeb30c6a1dcfd26a42f92d098f2aded751cd072b1023f5f9c9eb6e7ccfaba941098ee8acd48e991d1420508619297290f8c7576107e9b9093ace3ffa50a3bb4d292e3ac34722db535e0385a9ad462d680b35d42deb68ce1b869b3d982317f0292d4d4362759284a0d9a1c043e3142e2980784edbfa340e85bffe84850aa7cf2be0a60dc20398119fae38353e0a7c5eec67b49110a7e8b87c53d0c5bc82614409edfe4242ca2c870f7293f582d355b62505cb96199d6c7b1d77f84d912e415490e32261b7eb6e1a892ef717cb5fc4f289165ae56ffe9dee8f36d1214502e5c96bbb1658fd8f884f3d0d811a14857e2120ab39aa3b68390fd059bb0edcbf7a01b9f084291ba3e961d55cd20fb421bdec242316a9ec7c041c46e85c678731bb424a0efb514f4b764cc91e8fbc67296949df7d1a3957dedd352b0212a08d10cc6dd7a44abb8c5b089c87888a1da58b697c52c98175c68ce30687fbc7e7f9e9d91692e245e2ea8188cbaba8be43fefef561257dfd484c6dd9d24c7b9427cbbbb83ad1eefd922d8eaff057f6cef3e29a02be442fab43e85c6f1b0340284e0329a863606567de6931eb923cce907cc74b4bee190a9f1676d13c94d02d694cac3e6b4ea1a8f77e4a451a752c96e4e12c0ffc6a1159a5074f584945a9d16dddd4b6f2a826397452527860646bc6a81cce465625870db8ab111b3852b603502d76589e164036dffd306033df4ae64eed04de8c1aee4a79aa81c09fad769509f46447d1d002945001968cc64b073c8eacd0e2bc10f22b8275651f5d6359e1398f605a0ef1b1b897ce4020a0c4e665b409a19a5034d59dd6458527f4240037f4ed679117702530b59e1e8b635366b2bcb59b932ec3a046f0b0f14d099636ca57f00340a56056306e451d70528068cd838258e817330feabed18e8993154f2892464efbda5dc324999920cf4054906720695e7d4f3409ed3a8275ea451eee4fa3f0d17d40e82e082e0d920bdbff3748a4b429dc2debf9ff44cdcb4f7937be5ba19593c95a78b9e13052617759f4f1488dcecf57b1c479dcd2df190ebb003d7bf8358d0a5af8a4e44b587503b53497541cac747ddaca565d30173b187428d7222d74bffde49642696c52b246ae93b1872acc73041ed9a95e3acfafecdd339882190e296e0cd401e11bc54e9fd630edf805178867fd00b80925c8f2728954a3b4a25f9504a19ad4bfcea421f3e6d5dff242f1eb6a050cfbc788f444edfc5212e1c4e69f12f385e41c89dfe5d9c4e2d957b368090fec70e77e53b9667b1cc047edd704087d605ae227cd4353d8b89e3a00b24527f3191ebea5f41e2253d6c75eabd5a7f6e35f1eb8ef8f5fa4e87ed83f075a941c128f1dd6f84a49fdf62a301fe0b3067ce5a4fa717aefcee85d2475bbf64bbf8f379cb11856ee57cbcdc78499674391e7931f34997644745a34bb21b94ed92acb6ca201192c586b04bb2f409bd243b7b675e92bdaa5c97646590bc24eb4cfc926ce49c17334916fa7831f3695a01f09246dccb8b9924cbef3e18a60c1d0c371239cef5a2eb71da8ebe78128e3a21d7816a3320a8e8879b1b3febeeeedbb07bf4cc0ef1f9a608861415720d371eb061ef504f537b33c80ef2e1778f283e221ea29a448af091f8d446f7eff19112749f8f14d6edb8c8478a1217770e6a546c54648e7153bba4354afef53df8c778ba6c2e7cc85299a3c492c7df214ade9c7b57e9d4a8bfc1a0a0a363026fc928c426c339a94308b31688cdc813d3c12686611886d12ca39eb5406c46d6c9e8a418866118866118866134cbf846d7b1bee3a461aecffc3b17fee89c0b474a1d7a7ce8303eecb2c7300cc330182ddde86f19a57446ead4dd9dd277ff4c669aa6654c336ccee9590bc426ebcc39e79c93fec428a594523ae9a4934e4a297d4da394524a29a593524a29e528a594528a61d0764b36278c11ce19638c10e280df924df6f8943a16194e233a73ce39b1efe86318c5303ae79c139bdc92511c9c172d3814677bcddddd378d528a19c128c530b7af8527b35377d82ce83a104277994e3d1beefed3dd25cda8a4f0a785d78730e8eeeeeefffc9fbbbbbbbbbb3333b34ca77809eb65f07c6676eaee4ea5a5dc5bd99ef2f0971c0f7c15b1cd6a142f41fdd73a31ea5c9c4be6a4f4a19c2c2f52ce39e79c73ce39e73f29b597afc9292784104208218410420821a434dbb894c6d69b65fa956dd3b44d63693122d5d2b760d14cd64df062ae5fb16ee4cdb83eb3ced3629de55aa992469953d799b66f5b37e24e3ad5f98e63462846b50c8bd675e2b7bc2ae6740c574d8d291263171df6fa93ba0245703df9ebcfda7277bfc7652e14e0a7c6b7816f4c9ee11389eea94627135131c617a30fb24b3e84307e3f9473bea2c890878432c89f1c0c174a79737d07f54c174198eb6fba757d0ed1bd747ace5a7da8003fb58bb108cec4d3a95618f49df3e05ed7fb8f1d2e7ddf786035d84318a3e41e0fa69f28422de280b048e75e2c7bfce1b7b73a0581c41b2fad3f5e3d3bfae39d5c37617853a8f4a3bb00726a37efc5dc933dd2e788dac5a27b3d5fcf4573d6a29bf99d73e0c6a24e4db8f198efb18adfb8cf6bb555915d9fe5d0faa0ebaaa8372f1e6a8d9ea932de8c8906c25c3fbfe3cd5e4308b3cf1e914d07cc6d268dba7a9baf8de6a45946a11218a5975cd79487551a1587dcebe10a063deaf4f574fd9b8f5db153dd5af67c7a26e634ccf51135e5a59c846a947be540c1fefaa96dff8374b7ef9f73d639e79c1315e5a19c7c6a17cd229939e79c754e1e738e5efbd19cdaec22d2e8b5efe66b5d0491dcebb7ed35ae87361d238e07be24aee36b8b18cfe93a5546f2770e73ad7d13815bcc69cb43d4c9be8b46eec6637ee7742afb94ceb3f16a26f64d29a5947e67acf8d763d86b9b149d5b80fb7ca020e5469161d8a49fd1a7afc1c766867d470174636830b61c3db996827143f4350e482422a56b9cc66956b3582fcd9221d330fd3570b2026898bd7cae23579186b99ee9145924ab482af77a69856be7ba813d289e679d564a646c39fa8ec0755cc78ff8ce4f0a2ffdd933fc6eb80ecfb89e3ecdfe07e966df5a17269616ff665ab81e0f6652eec5be379fc5be37df64a137bb8f38e7b28ffe9c3fe9b6eda02fe7d3ebe5f5b386a59913861974c38b992e3eaecb03bcf32167713b665a92d1a8ecb908c5553a25a3511c783618f062f8f9fbe6d9c0508dca5eb319f7d22848c43358fbaeafdff06c60cf4c04795648c437501ad735fbe4c43759206cb8f45f0f977234cd621b7b9a3659204cef838dcaf4d1a2f8c68e37833e0b01b335d8ac6ee7e3015d1d78803749064cffae0d26cef4d4d237d9693b0ddcdc294d6d72dba917eddc411574ee7b4e548327092592484289249248428925963882895cd7724889af473de26354ebbda2ea435f79a9faefab7f56228de0bf775f96456dbe9b8d6caf1aa883e0cda4563fd68ff5e368347af8a487107e56aad0a704a7700f0365dff1102eb6f1a81f9ff674caa75340cfc6aba9a52f719d15cf060ff536e1dd80df43ddea94d0b331fad34d8bd5e22a8dbac9361e190b4b8b51513f1b0f12d59b13ce8aed555f120ff38ea240e10cc6481a71dc53b22d841f27ddab1c7c4b5c0e0de33d238e83d1aa55a664f6075f0bd8dcd11327d1050db1e8a4c9e0c5f8370cde0c7f1a9f2797931a4c9620e9d17a7ae06844da788c1e8e46d0057835cb51c2d1cccab331aa902b71ffa2041ffe0fd285dc23c11ead55166fec14c985665be8c5555cc199de0182458f3ad5d364d1328ba33e0a753aadde1d8d3e6ba1ad581eaa9689b251bc1c8417e3cf3f78337c9a85a254086368a4cf602ca15ed988d42d4863a77671d5f29fb3f6c4d588ebe6aae7c5c0d034cbb75a9843b22dd4432fc61f3614ae7f3b01166918afddea56b7bae539fc96b86e1da9cfb928de11acd2333d65a84f4e3e314a50219093be8343b824aeb4f1203dec89af86c445d2cca16785fa3f9d48248e7be6acf574facf2c5f2d87465514843d5e8c731178b3ab678f3a21b772d0e7c5f8471be304fdbdc358bc999567a37e577af8d9af587e30a379a3ff8bd1c8ebe8eb88877847ff8374475cbc71e39171d5a10e73c4e90081a00f0d24aaf70089cda4513e10a853bd6a540f9ce90161fceb3cd5560ff7709186f13fe2bf72b2615f4befabeee473d67a3a954ad5c29e2dc7f53490a82e9ffec5e9503f089c7fb94aa734ce45fbec5db4294022f4a91cec59b1249bc3838213aeff68e5ef9ce38f4df19daaa407f6f470c3d7e223ad2f3f7936302e07e582f075a11523cfd6395070a98028052da80222f997fceb1b42785d8df39119621b8f0b5e3fafebc2998139443a4a70e6ac15faf78b387db318479be5cb03e49d44e2fa0efee5f3fa6de3316be6ec29a7f63a65a3948657c311943cefcaa45f128e60248a5286762a8c92e52f0ed4a38bae366d3be475c938d4364a71a03874fd19c77182dc8f70813ac543fe0504a553d7252f79f525af4b5e3b2848e288248e2069da43ad519ce630a4a8fd1947fa9006d7674986273e5060805947618aa5c17538e9f32b8adc19f7f944e1c99df3c97881c1c2abae51cae954ca4536ab59dc6ae5399ed3ac2874fd631ca97c3be7098272f2b9ce4eae738b899e572eb4f39c8bcb2971bc1a7dc75ab8df71d1139d8650f5742a7d27bff4956312739e541f28ff357a3aa8864e7531c6af357a8f9e6956ec624e8cb1c61aebc3ca755c3fd63867adab6f168444a56a732711d18a6805677aac5e110ff7e4f01a55a5e69587556d3bf9d2bb8e916763f4fe1c03a601cbe0f18a85c03e6027aed7d48f75c6382f97d2cf2fbdb42ea5ac645d485f7a2844428dbe34fad2e84b2f638ebb4ba16115547af991d5a937b23f769072db51fa916f3a4a3f922f390e62229d8cba8967a3f42efdb352e9474f2da9f4b2b552e9dfa6a3442ac11ceb52a281a4f210ef0f26ba948692faee0c8219ed8d074b4e963e22b9ef8eae182265e89652d0caa656b2a7f7928b96162f4e25928b96162f4a3f4877f43f76b872351b87949c36a575912ef2495f928fbad963322b914af4bd9812d7456af98e46a552e9e35f5b4de963e9e3c71f8d1e48844572e407e11fd9cee646cec5ffdae24b3b2f1b214fbff3f44387fefcb716f7c518c08d1793e61b58e22ad7fd7de1767ca3c538529b05e3d9a8ef7f8a11396888573c74005d4c17c34bfd57573458c040fc4731c61823498b31c61829b5236a376a356a336a316a29b593da8b5a49ad53ea83ae68320670dfc768e1af4b5b8ecca4994cd98b574686273e50a2387922c3131f28ec45361d308f3a7dfb4cb36a04f5f9705b536e6d6e385a795ee17ab8f26df0c1375e2ad79d8032f89a95d128f8823da4fde28f1755681708532b7dbcb8d4d47b7dbd5784957d0b3054a1c22bf3713b7f1fa77ba19cd3040082ca4f03a9505404afc722d3e21fd7f9a8f1c23e080361b477615b6cc696f4d994db05e96a3b9b5bf9d9f499c9f434bc6be24cdfbd273d6f39deaf3c0d6c2bee0b5205cf203d0dc4b8d8282cebeecebefbeb6920666ba3de531969b3d211882c768a5fcc230095dacddb0f8483781513ef9fbd9e9d5cf7e23607e46aea855f85dcdc20b6f3f17261b4dd04ee6cd4cbf9a16228422142125aaad703233ea0040545c512842ae3250881c552bd298a30c2c34714a1e22364a08affa0b0019222d583d2841f0ca9daba448ea1509db050bd34154b3481a56acb5258a28a2f78e28996aa6dafa05065700452081189c06941410520f84cc1042b5499944214ab4b8396462bc80652a8da9688f8a8b2a9417b802738a10211a8da969280a37a58b07670546d4d2dd50fa028e951b57d3c40a2ca320dda4e41950fb0546d61f44095695944c1d934686954a9c233d2a07d403e54e051b5a5f14495552df280c91538aab632eca8b2aa41cb508298028eaaeda362a5ca4a1ab42f8a245000a46a2be307aacc6432f11344aad051b5e5265350d9b090ee68640a43f7f9fc1421c07d3e5338723392fcf7d2f12a7bdb1d24ce588b9e8f4631777777bff71e510d1068147f9146e9740cfcd712b56324fc1f84cacf05e1238deae722aca476fc7a8ae8c0cf726eb4409887c8916b1fcf10532eb48f87089ffb36fe9510d90bba4597b920f0d29036e6062ae8c30322ca41162a21b38505d5eb183a99981ba824f7b2a70a3920422584de14a172215081c5119510fa022454cebd8ec14695b5262f1c98c85a70850b0ed2ffe2e49c10460cdd09da53853037b8733e3c1e0c9962a5127205a1f2b751bdbc5b54c7d03f9ba8cc690d3bba207bab1b04dea722000e90e4b066abb9c08d2f754c9b28849b85c81e9c6102080e9c85aa3f421df3422e3e954d0be15e408c8fb18c0daec33690716e817810befdd95f4f2f19ccd579aad7757d76d1eb9a7c71965ffc4ecdd9f5cf397598d376fc5d3f7ff78c173f38baba311ab0a7e9b62fbbcccd819e7c83af9414ce4bc699b2a4c4538c31c61863fc1a32a90b5b0f3579b8043d746a32a5efff2edebce67abfe28e2b8b2cb2a872bbb5c0d7f7d029f93054a1fa90d73fbbb4882309ceabb06f9b04e3849c544ccc975b8ef9d7bf4d87bcd3a5c6afcbe9d7dfaf733d9800062de8c192ae385870f02fbc448918e343c93833bf26744f09447caa08badd1b8a30f80d8d8a50e6c5c47e9cc3044e5077f0a1030028f06ec0e8716a4ee65f1e8c08801b9d6511249040e295ffe4cb95cf921ff57f3abdf737dcf0626c6894fc1846aa7cff299fe533ce032600676420e08077a3069e215f7e0324cbd420f99f9437c439ff05cd6b5eee5e0511420811841042c8a772c6a7f1a9fc39ffc27e1524d4a817853b5f13ee7c4ab8f36f7851dcf92d2c8b8d3144ed9a4872d1bc6a3c3d0bf5d0a39c0d2f23f328d7443634ea79bec97597e47a086e351bc8a40cc2d77fda8c5aa7b487b0a7b435371e16cec4d669a8532bdf05e0521797be14d6f50d1fc233f8e95f6f26b6200c7f0bf51043ee07bc47628bdf87bce715ae3b95b82b37e4cae74b72c2b321038045769c112c824494cea773235920ee3a3a439d1241c57ef2c05e87f9ddda96c0e373cea12af5b25dbc7a8852fa367c5ddf428de2abf5344d27fdf897eda12da31f3f3b9d78b2e4160fdfe016bfd6e12f2e026d3be847fa114807cd38ea5a0c8262ff6a7ca3127c3120a0e993031a7191630967e24edc893b7167e7c812264ee24e2bae5a4271272ae1b81363488544494c4470c6c43537f7749eaba4535d04ba0ce43dfc114aa7523bec3871c771b63f7d3d1111350c3b0e914e25313dbfe7f40c2ccfc2c19c1d252b169ca203e6c6238d021219497c32e3ce8b611d2863cfef477ca7534fe4734fa77c9e8d9f67437b7ecd6df7b88eb71df365363fb6b26881308645248de2211b851a8501e9dbc51d2596e019e7f1c8821883cbff38d6e0f6cd0667dc8812977fae00069d07b9ce8be18fd1813afff13073175b77c89f3ce11e9fcbf3b76f75ca651249ce65c623979f29078976903033d46918fe9dcb4aeaeac4facb33d4ad9e74729c13743dd39f3490d429e5b6f1882f391ed8a5e652ceb9c8457e1751d445d2bf2c5ffeec09b32e33cf0d3f27a53ddee349ffc190a2528ebe89524a5bdec49cf366024310419313ea8bfb7ea0c02102117df91a22563218cb20c8fcd0a613d495fb7e866025a9f5be9f2194a086ac64c8f02441660b75def7d364ca4f932b6eea75df4f132b6ef795e97d3f4d9ef84c0e6032b882e8a14e94644d103913284a0c21767e6c80850b354000b50864d75307ae0eb4ba3a31c2523364e58409538d1044bf517131e9cf4debd4281c3b083aed00827559aed0046645185d4888538cb22044e13d4349b6eca789144d7e9a5439028588915abaefe7064911eae9be9f9b199882aae9be9f9b9f9f0eb4229d3f38442b3c3f9c72a82067c7103b3f1e58c272fdbe1f204a70bd65d241d5eef3a1b2c3022a4b9250b1c14a0ea83c310541258a95105069b530525beef3a152c513a8546981a2ce205c34514b1f58a9a26e2730d5a0624b58a8d45393962bea8b276260c5128aa8aceca046214c59c08208222c8cd8f1c3d0cf0f3a5918f2f34311598213b30c2264c1c10920d01942931538d981131941c53d5596d38f1150eebcefc7081f262cb2ce285010f2bf8ccc0d5e3f8124faa0dfd79780bcae4b8eb21dba02794991fde418e127c70637bbef27677583824bc8b48cc02a0b247870108509ace052384129b2d0441658d79fe524441656b7abffd3c5e62b46d93931eb77eef10cf86c9bc8e5eefe00cfe0f77f8f3ba7510c6d3a27c2eef7de0d41903803d00c706ee7e355b9f2639c314e8f9eb53c8bd252f08c8cf92767ad46b547661af860610a137426158d75f3bb49ef94f25949e94beadcf33bad5f1a8875d83f9b510c7b8a4d9f925e382f74f7c97537ab1f6cee32823de137a67cca97b92c5613264d5856d40fb056d50824446978b9b3fcf2bf6c3fb47e3db32e0f4926177e3ba469ffaefe78107ef775b1dc2fbfdcfd62f9e5b289bce405e1e53e9360a520486cc25a6de19be0d77258e4c22730e7be6e4977e93146180258c4611197ec1c80455a485e5a3004459e04d59b560d32d950da0640c8e3baded03694cf42b78b78ebc2bf1ad028d81b733e361cf0bb877bb564a1ebba5a08c2776602cf80ef300a11b35077c36f94cd643985507c5e1ba544ed60fc0b8a45860c8ccac24ce01b4237dac753536ce3c442edfe9b00b28951845a43019d8a7dfb9f0c9953a39a7f7311238a0a43bf8c8b67e3dd8e409097df81de0c36a57a4fe7c37beef5419815f987865aadeb3d70c67b200c73d7dff982f8f140a101a229024d104d50ec5e5ef8dddda5fb0c40b70bf2349df10c7fb633f85c9633f4ccf004cfe0bfdec61f25dc5c03dcf79304a19bb52667f8725d0f6e330350a368e08f8b2777fc18391708b91cd08166632bd677cfddb9c9753eb42bdfe7a473da4ec87dd73f8e2fb9c733e6bb8d3fede3217886672fbef7314e26f2fc5d1046e843ca0211b636f7f1eb7763dcc18d926b80fb7480051ffeb6f29f75e967229d45c6b9ef25ec2b371c4f4a1b1af8e3bab21372fb89dc2ec8103ce37dcc9a3febe1f6b32502dfa6e3baf26d2e9146d9fcb86e3f7fb4ce77b68089dc8cf46eeaf462612c51653ac52f43f08d47e4463b97d4eef57011b543a1ba575530773c1951e3d920fd93e1d14ce0a556fe7d0e3301f441d1bebb310323460468bf82a397ef76f4d9bf8d06865b8e15ae470214d0a8d830f16550a8ffd3a9d69eb3d62ccbfe75b6814b7a9aee61ce5a4fa77f92a57931f1b3a1195426e278fb17a0d4943f77d30289b79b2f075dec5e91941bfff29dfb046043e28b05fe5a9d99ff547c1a323f8857d58e21b218e1e92f1972b5756447872e1b0ec9b938e73136ecee281f76d3050839990d75dd857559f9d33f558b6df9178f838b3fb9f8171cb78116aed616fb542eec53b1fc83332e2b9ccb025adec5dfd0f22e381f9858791f5ab87943cbbb78179c0fdc9b5d0fb7bab03640181f452253677349cf1b0ed267b0458b164fc3bb2ddee6b2d8ce7613b82bf54db6e36bfa1696a5f46f5ba169163b7a93b58957f08cd1d7d1d340920c9c991a9771a8dbc9d096540189d2c89525abd83fdc74d0a891c1ac3fadc1e6cafbf852991bb3e7eb326e386810fb78461753fcbce1c076b894934f03697a72b5515c27e5e8247b2fda65c8c2b69e1a15e3cb28b9d928f9129334337377777737337337337377676db76d8bdaf320aded7b120df1d95ab7daa897e4b1b45d61666666eed7eff57b8ff9f57bfd5ebfe7e285113f735698628850c61d5d483e962d9f5a151a6ab5a2045d304e2cefb59314a2a121a1d67b0188419530882194fb8026009678af7e00625049a45a5a79c19c0b1ec4e089e1440c27e4bf972c8bc123a59452b3325acb3ece2ab7effa460d03d786520c27029b09a8c4adf68439ea14cd0000000000f314000028140a870342d168308e5359121f14800c83924a6c549c8ab3208951144719630c41c0104080012300032333540188e931ea869d68e4e4eb6a1e8035a90ff560a5bf1a2cde0231a78a85f6e8f8dc5e5a3df4906e97c6600278c9cf76eb4ea57d70c331f1fcbe08bdf6bf6f4e07084d97c2f6666e4302e64b740d1b42a5d15f8351373a0b0aeae718f1ec8f38cc8777a925ddc1e0f503583ba82c4f05bf40531a46f2eae6fe0a4078a99e1c15c163d8a28e2875a5811a686fd2e2b7c780350d85231bc66c8e9207098db025ed6d12f313e1ee839429709fc820a11ef4addc06055bb00e41989b64a350ed7b5183d5139427b66a3fd87508c564d87abf2099e40984a1cb761614c619e381f0b718b0b869939fafd9389664481a40d4be5361c779e604ad1f64ad6c5d2e3f48487e974e0c2c9835f61bb85f881aeada007dcc710413549b3ac7acd9579240e51704bc1341e460cad6715c5e461245d0d6ab78a86a5910650f45404272fbe6142d821f0b8754f69622c59a54606eea00878ab49a80717ac39de066a368f0523fdc2e7e963cc84a950388d43a01a36d1f0e308f063b451e8d37849adb8aed5a07df6cfd1d245aacc31f10e21c9ce531840a1eca1c84d753d44d6c62b57c7ee37304f82de7adcee473de08384a4fb8a4dcf5457ea941df7517613b6ed38a2a5b77e1d54dcbbff1dd1e8e02d69343aaec1ea5a14761620b93c89e6fda4804dc19360c26f0bb2b9331e7bc64c5de28a02c8a276593b84be673fd023ce1e7e9682d4916f76b3dd7efc04fea6efa5c7750d5db697e3fc4e22c7508e97247b18dbfdeee5da330e7bd9d39bb4f227186eff03b0593d2473a7906c919402b0b071f826f044576900ad254b632d67c1c71f0de3ba4a28e79458e87d4d8c1ded71a30d65c0743d038c8d44033a4c48df684d5ca69e7c8279d2def8a7d767302290a0609a334add61ae655d1b5ffc8a1f324c3c22c97192b966fb18de1f69d391b700b208c07a37044639df72a38f7f07e8e69e6ce6dfba1e0cf46caa1e573ce5e0a5bf1f2d1e13c6d81c0c19448375e82ea653f22d74a3ecb839fdf99d85b5509883fef65f7d8141becd71af1d0fe62146b628917cd16ba1672a413eb5877e766ea202e02dd9984e50050ba7af10147f683c323d4bae929bddcb3eefffbd7d4b89372eb7deed8df1df6afc072badf42bb574fbffecf8ca854faeb55cacc892da4efb22475fb4c18ee0fd8fec3b04349d4675dc0cc396ab0e23903ed829fd1d15ae8c11ac1226e789160063de7f5e45be7bd5bc8dc5044228344770073b1056dd27779de7a48e3c0facb979d5db45485584e41b60e743af1dce856bb113bb3ad01f12191cd9af0b5ba74fd7966cd83ed7d4526d75f4b57f65a8e07558682564260b7d9f01e5f306671b717e2a1248a9fa1c4798e36698c1b8aaeda2a261b50a3484b3dd7b894c170983bf7dfd8684250be4b1a76575cd660d8f280bbc01805fef0c4007565bd990e6255f84f489e281c709a83fd20950693d0ec216c182f6b93fc3d701b02bc6a6bd004021e88a280a62584596ade2d1ee8ee0c28d7caf9686eebe6b21ba83f7c71dcd779c941029a86b7970dd6529dc9b61545ed528f5a04b58e48cc039c328fc25f141adc218f2eb7431488d8b4da523978cfd4ee29a5c64bd7d7650aabb1c3711ced29dcd49ec7d21799c786d5efaee28e1de8ed8a53fdc7c3b610f2c0c06be7368199d3e9c6533be51e87676b910a4483d730dfbd5d9b4e4c7d83aa53c95232002eff4cba69dc176e75b04555b81da4e51cbe0a045d6a6dc8af4bae3967949cda374d4f1e370226a45a477835567ca55aac771bb1e2f3664769ed045cc58abd25d78977578435fbb61b5f359d75efbef1bf96b591884dd9b306ab8064801daa150c017b1dd6f82ceac12d3a2d138f6d178f76bb62c8b0d7b4e2a0388a720bcfbf42af9664b6358289a27c60fff7c229d6647fc3c4c34605d16ca82ab26ea2422b220438c1df43d4a42b48352e621890cb747f0968ab705a39b0044f2679569c64b69c84c47060f6b98f981cec6a5d55552c27ba4263c0cc7065313569eee3ffca89556eab6955dc59635ff48f80ab625fc0f696f2add54dd56fd604bba13971a3a0971ebceaf4e084524798139394f5acf53a4d9dff7d25ed57428a51674d86deb9b73be2b41a249b69e98eac28bd7b6abe875477296286401c62944190325455359b4452b44b6bf1de7f4b7f7183de4ccc02648c70c56a50443e3103032b72891d9539ad9c904f2c7aad35ea368e6d34115acd211ac3020ccd94132fb860f394ec4ecc120eb900654738d48f41e98641bd64e154e7bf393160c88c42cd33003a4ca49b1fc68abeff3cdc22237724f722e774cbf544921db8a7bbd5165529ce6fb4e8f9c122c277a1c130fc418ff7ffe4c992baf9b91322048cedf1b2b9b49b4914b0fd876226aa6625ce2ba1fd432e216c8eb3f8fed178bddad9f9dc96018b82fc291a1da48ea1ced451cc1adbef978b45948ec912ca2e9214d22750bae1963b8a721819c49ed72645fad23b2b41958c5dc080e31d1b436a202f030f2a140ea23d3016394db45faa4c21b03845a01a3d76719a9759383c42cf02a150dc1951f567d42f30fdfb53a9d73d5f6434458ebc1c6a2f0208a849581feb38840860b5458c61e1ac241f8a645c9e53f4c5446971be747099e669b737d38950233861ac61895142e7e84d8c3ac6d0e438713f4d75a1152936905de6d866da0bfa7ae94e21a28609e6525ef65121a48196e3b49bb628f1d01f14fbf7003469d0a060b7d9eda01315cd6e70c7080985c90c94fd7a7d8cf430141cb8daff3e6c9bbd9928760184c9d7191367ffdc9ff9a69fde7cfdbbd93510eeb7ccd7166f1ad217f13db6a6e6338b2c221e9426ad5b7b015ab3df931b0ab09582cc53bc6af35755e7a3f4bdd85c9b736988a95ec003b4abb692e6d8c601522c7e4ec755fccdc93afd1c81b95d60d47bb24da327cb316920a2c301a9325588c0d25ccf52f4324987c2fa2ea236ba6b148d3ad1c8383a0d5ba4e9ada51b4dab882b57af46ca8b314121acf23729441b3346491fa164971f2cf925962bb408165f1f64a13915d470e8b6ad5c2b26012f1a58f0c96b6ab6d7a8b27aff5c80eee490e47a747af3f27e2b0f9722a3dd177e35beee8255d26f256646145a036cb24056fe8c720e4f9d253d3f5eb6b6f8f08fd8473443692468708d77d5e4d58e52907b8144313e53a4599f6b39962db4e0e482fb375783114285979765b14f991eee4e13d975ad636334b7e6c8dd930ab97a29f750ea82a1d606643612a27a7fc831412c901237e89f1bbf2d5cedab721d631ac656f232262bf42c46563d03fd8067861ef9a9d1b0e7c4590e89e73d83cc37c86546ffd2c0530c2d7fa72294c45ca1a14a19fad137067aaf387b45211268a37e4fbfa0a88cb3a1e275b219ff45296d829d3cb95848c13b40cc5d9e843c6553edcd9cd1d2262b59d0c4757f08a75fbc662fb03f968e3e8233fefb704316f65f85c3c08a2eccd71ad34da0018f9f2d4b99d2aea11402d54be48b460d0465e2ab8820f035f2d15d6ebe0cb1d2d2c6285fd8f5d22f76b63a35ed154d58a0647d4c01124136f24ab8dc546886538260a75154455a0519d8a2812212411419881a02d57bd4acbff716180a8954d80c3c350953f08606cdc778d4d1bf978e1dae3a0155a708f8003eedb826d62dc9aacce9e5383739610ee6acedc39e3305e16e0d0d3bc87753780d5e9ae4e6256f19cd394d6c1bdff76c7e811ec17b65565ddb4bea954cfa774c764f3054388d0511fb49925ac1b86d5b9606ac6487d8955ed630e1eef5547ccd1144aaa4a0f83a1bcaa629a210b496cf859615349a70923d3484e8897b4c43fc316190e65daf29329ff5ab143a6be38435c02af7c5c4555872a1231688ee186040190781cc99eeebb218017a1efc71153774f7c483f0134c7f45a11cb1a0b9189fe1737bc40236e2271f1d270b35408db4c792edec99da5f0431ba9011f126322bd661c54600756c06f5cf2419c938a3f5443248c3a8debe6df0b04b3f249a0e3040f45237abc3d091904d049223f394eb8235cd7001779fa718fb558c14ca0e43b678895e6872f4b7a3db8b290ca4951787fbce1ec7966b29a170f1f6495e7812832c1fe4565ad759b951b35ec06a626fafb0035864bf647bb5262d33aa8b6beff6a9ea06edecb80b3051616c25e988bf5cb5d7e0f88602b34f8bd78f55e667282eda99aecb2a4269a13dbc58853d8fdbb0831b35f32972309e84d598ac1acb59a5cbbe88a54b8ea5e5b48f37331fd7a0524e125463729a317701effb71c07eb402ccf3c78dc2e81f647d491e1d13b686d751184a80801c84b757e31028100279485ac4de3e1cb2548e5739f5a527a5b11e0c09387e7be174a8366635d8079e588649bb23e22d65c2a10eef301ca73d7734a405be5732db480bc1f823fdafcebd4c47ef94793364240a994af808447ccfed0172f6b23a8b72b8bf59cd591092c2df2efe8deef2e243a4fab5e7e6f253a592c3597529f76d6a1b9e86eca2b754512bf60642ce5e1c4e20c28abd4795197e126e205cc6f42cb9377c8db4bee7ac86e701e712c2e46d441c3a354d473dae6485f37137d8004e4622408722cb3b11c0614da922f5adf3275e5f2f133e0d9a17cebc22ed1ad38ce229b71df733821db95677ca3d891be934f9c8e1bcaa2331edd54d0cced21086a39091b61904c447089245d56bee25e0de5e4825a9df35b1c2b55ad94034609d8818fc4b962891ce8ed5a0c8b472457d1b9470157c9f4dcf195147e9f3d6bdf914e4d33d77bea5d6645940cacc6c10a754becad4cc03ee8261b0db667b84fb0b07113f23b244460f25bfe3fe04ce5c464aaa887952b5ebe0c879e2c6f518f9fa7f2156f2c33c79cc525cc5087c83391a1631a47e967238bde541fe65b51b304f1ff682966c3de0919649adf7112d4522df576d596ea86b843cd89f59dd27e9f67202ab956014ff1fd51ff384f15f5496d3bb9a539ea408d915f1ecde80a35f0cba74a50725100ced8053da45615f727da082d480db65ac65ac2ceb092ac2e0520f4212bb147b98d96d39f3625ffd7ea9e94b99a52558f9da3b57c15a59b887d54b886d3c1a0ac6e6589c64ecdb6891495f12c2c315a3f11466bd844f79507ebda8904ac1edd3e90e5cffcc4da8b312673f03d07e2b3cfdd7223c4168848a36318dcfad86dd652495fd25825f958333ef3d1144b575613815bfbca316f2f2851df143406d096c63a2356761bae10a97087fe7e7609b42cd7b112a62f5b49870cdd24b2e5de277e61ad4614d3881dae3a3ca3883e9442740085990bbe3d1d5b313dfe5536d38617ffd24956938c91f2484b5a2d4f414683ddfaf1123333a073bbd724bb8332ab9b5fc17adf22d6bb59e1bfbb92dbd75f9ed9b6bcebf607c750725f153bfd68a3660d31dd8990fa4c4cf122cd76c228f1b59b3f47f22e6918c3f6c1ff2c78960f7c000d71025cc599a795cea9db2e9faacdcedf91f5bef6b23a3c6e76ee3e50184001483700cc39ab5433564aaf7df60979b88bac229ed1b147f1f44be3e44324e27b2744875d2b35c81814c74d9d780753bb97ffd34f42f53feaabfc76aab7c925e1c27dcc9acd5693ad72a727b04987f00f0ebd9a21bdc1fb50de085a67afd1002f3b98de38bf3c3611267afdcc69b5a6fc5155beb46b71e3335ed8962b7960e87d3f75bf64d7d45e76cd75ab116cfacdc5ba05ea1aff0e9ba4398411dd76977cdef3ee4a4a019b6903ebd106309ad3beb79647870f741ac5bfe973830c5575ec30dcd546ae2357070a82b5299e84db16c0e6962d2ebaab19fbae4a60bacaf445d9a0c2e01314f7f502b1ace2d322391671aaa4a1dd4242339df4c58f1e3642ab4e2aa5151f2fc0669ebf87d8991adf5ab2cce0980d5f3fd226b3f7b75013d111eb8f4a0c0554e6d5f5f2e7060bd4012052ed0b76e8cdb9864f28d0251ff99577f985dd0e2a0fb6b9673aef9d38e98f3012962dd91ffb640e2393d51d7f3f04a9abf2f731ed9bd0ec9ec1a1701a9d2c14a4ea5dd686275ca46c0011a8fa9954b94894db4e5b8a64348cd17c6e0cb675348944ca3f9b6501f06c7fdf37e940a7c84df8de3c85866c434cf55b7a2b74cb74d4db000d0a4183a13cc9aa5539771502d8eb411411bb0b1c41af4edf39c8d07bea1be5ba2efe7a3116849f43686eb36771b376d919d532fc491ab67a141fe3e40bf5d7b640768d266436eb6feef4b6b0f4a8a0506ef10dc94f19883a0240bdeded9b7cb60e80ca26e4544f3366cf9f6159762c46f8fa527b2f0c32b3a761efcc6540f9f1e4cd91bafd8d098be048aa8e2a7131dd24409ff0f9fdd2d197c4e53a058ed2b6d81cf8a6f690e1ceb7c4e2b50acec234d81674df8f2d31e7856defe7b56752bb82d0f01d3a5ca9326983f37b74c4b39abd5a9922c0ac97453004adccfaab9eba52c2bd00ea04df2d432c3028035ed037165f6e398c4d2bee5652edb517d64852eb711150ef108ae4bbeb40f10409425c6be2b8ba91bbb99c711f5ed96781bb4ee4248bcf897a811a71c580bc1e9d51d0da142cdfaad7c0b702f6d9e768d87c79adae98490e9e207b9f250b146ed354f3625f0bf48c9c3806710591729777d68aba49dc1d97f8bc906221ad535c0b62fc2427a8ffebfd550b27b8b5569c030a16c2ee5afeba61f62b924813165b8024c94c0b6c1ae7a561fd30c851099461f6404421efe6d2181b48b486ad54cedc0a7326d83cdfe6163bbb45ae1d9e43723d330209a840b9b640c1abb24d147806a9f6794cde2629c5f53fb1ed131209502c99e4ff77783e07e2acf6c043634e00de7ba89131ea1bba006350ca4f3144d33686bf740c3cff7e9d4a3bc016c1c47edb98a040b0cc11cd72552f6de1190e2ad529f17fb0363a7f8e65880aa45048a4586d8b600f0d68b8c418d14fc8b4257b457d26dfc6abaeb3960220838f2ce15d8bb4ef01b88b7b70a0b90961b918aafac21be85bbfa3b0c2f8632978cbef205e83d66f9ec6a431a212c986be9658457bb88e71396090a86dac67f0ec7ce7125403e82846572298bec8d079052f28939be0b3c6591cfe7e732578faa8cce673debc5012b29e1e7b40ddd94d3526893b3d8caf6f5271bb378c29a33f2aa95e0d0119297580bf8004a5ed7a2ee70d340993c34e4710ee9abfbc1def8b202147bc31b1b18f8f9750f6aab45faa7c6b6536613bdb767bb6ddc885b3b06f22ca126abea6f99ab27a9e8a1126f8129e0d089807bebe130050b9256dec545a1a87c3e2d869c6e749be4fda0d76a23af7bc531182558ff271d8ce7f18de3dc2017c487aeeac21dfc03bdf5d4d53bfa03b75d15d76199a8012d55249f02c55aa400bbea27e2444868f503d61c67ab0b80f44e8c9d542f6573a3a92006de0fbfca86abbaab4b57cbae1ebcff2a71045f9bb0c7f37259fada0b337cf6a2a7585ac88a3ec1227affb3cea0597fcf4225f60d446bf23784f24cfb5ba3b34891ea902a4d0b7c7b59ea5b0d3b3faff04267435a48f74632dca775a4ce4028238411a06cf3482c8b5b5a1292841692756407bb8419dc8e4d80b526f9cbab7b2b5cd9053d80de06434d9cf47c4c131e553dcfb476bc0a43e963711c5d6e0874aa64bdcd01d629d55318bf64bce3054a3290b384daca772e55bcd67a5a1e488ddd3ebee84cff76cf7e7b55bffdc2e51d60c6b58e4f83f6f922f8e2c38afc6e3a1282a6bf086a0ad570488bd51e8a5aeef112db582ca1e3dc96448d8a6830f45903f59943ec94ea0a605ba74e64343388e2192b39d9a29fd625047b9a1daea4ce4951516953cae1e1a15525485cdfb5d0877ab2f7e60c5f3282582549ac5a73a9b4debd0fcdae885073bdc90b88c624f2fc1fa8f60fa6f925f906bb7504780648a3a3a90dd2a82c660eaed5791a181ec14f21de52fcbb830cf91e01bdc347304db30353ce0e8c1f745e94ff23ed2069df8386b3a3427857f06a3a3010bb42b607891f5f02141df40d07abad9388e0a773831d6cbd6997d2c5db3b74b5c12e2bdb1ea10de65c5fae7e536477c75064afe6734da0fc4d2b8c72c661becbff162d00126a7b0bf2246dac89a7742c7a535ec9c06c0a86186fc1c21b2a99afe717a599169a04a703aeb499a05d0a5c0b9d21a7e77d9003da593764617e8f62d06cb7ede8270c537c7fcd8a412f15bcd2e0969a625b6799fb2f47602e194b5abfd06eea1e953c627a5612cfd9cf6690f49cd579ee0f68414d3ada59d86b170bca3ad128d0073b09fc17f1ddba6719823081cab3bb205056c619fa829e91bcaf6a0f2fd357ce87f54e49999a8f8b5d7f65b3e4ad6e8381afbe0101b9df8475a7b95624a7e517f5ebc5ca92a8d5d81c232ad1371720a3810b88a1a21995bccd0992c912a03e4b1acf1e667b6402456fdab1f29090c5b57700cd936618fd01cb82c488b5bc4112324762cda6bc2ef3113966b16f3024a0fdce6ebc5c7e8910dfa513b14cb02d87b8f3d29a6f2de60bf7a5391311365f72cef24e4dc7bb7cfe2d3767a9c7302feb4389c9bf7775d25703d322856a9f401424018e9cfe7a94808f49af2f88be1139c459ddedbb6a7ac795b176ef71923108afcd5bf1bc3592611fc8eac80135bb2b2521f55dc5b83122c8d9a95d44e1b033372d4b6b423b958b8c61fc4c5329334b3253ecb4251ca49bf56928a474dd048a8a911977dd13df2c09f6c952726e5ed716546e53159e5aef6f14e986d76806cdd180879e1e5797bcab4209da92da58b350554ad2f7c7baa28bdb47e8d09e580aecfdaa8aade747aa4ab06d9787049a07a1272eb76a62cec496f9335fe7424e494aa73be0e6f05eb11a25bf1cd8ddb1cc7c6f1b3b6e705d3dcea6ab7806f948d53c04808b6c3e96c099cefb539088e80d0e0710d36039b5405d1bec7f03e89cb07ed041b0bda7c0b2a2744d1c2b77437557e7d4ca2b2415ea0c32495665cf4d65f062087772f99070071dc2ecca4c40ba619914d37a8201c547a738b78b81e900c4e394f4c67716db908d8f935099599bf0d11b9c3f693b6af315d1e7cb80be13d3a1591ee3204887f3770320e2fc7bd59128fd586f0bb03fe16707da9e4311fac984f12eb347ce4163b5813deeffe83695a5234564735c433231ed67247229ab3dfe942831cabf72cd0a8bb50901d0fc141b9cc65396a88a8f234ee514a399b8dd14edac4c642a5278a3490795127d702cdaa4ea1e3cfaf2fc52534e8f098fac0e1c958e5871c738f562ba223cb009a3c9892831b614c0a652a93862a06cd8133c0184a534daa51c89e6bffa9c244a6a492053da8e987788434b752cf646f3ddb7c1679705c718b5902995d4e5340a0123be504a2980e2b245ca778780ea2c1a2354141b33861753e45ea325991ad08e58ac6ac16247f0169bfeff7ad87522ebe21dca8717b027379eafc34e6c16c7b23e003bf6579ea3588ec711f4ab02e47d06fc43bf420f2b473d20ba89cd3e895af57050a265b9998448c671eee7f554a54dee0f7151fe92336c706f648563527b34d1ae3453bb2af805fff38aae233fb17bd68f23b759afb2b4410476452318dd89418d51f30ed655f2221dac5a9eb1ae794be10ed4f9ad9dd1d035d2960d16a562634a9ca634762caad70fc39997dd2a2604e346f4d16036fe69babd2ab6085fd6e9b40a5306e83059709a72ca9a875eeadb119c20052214374634be1ada52396425bf30a2b27be5366027f596d47e11cd0933facade34b39eae1a74bb950cca5e80f17e44b97f4cf8ebb997cb8a1f678a38ac8690418239edab4fdbbcf6d7f6ec22f4520e979d27003b535cbd78a93041adbb1d3913f89ace4c31f4da9f7a5561d6c02b7275ae2c60256e436b4cea9f0dbd2db344d71bc1f97563862df02bd091e837572cc880edab337d4cc8e70cd6a0a0dafecb185ef4643267b0615d3eab273480f325b5937fc59b887ebc9d1d7f164b46e9c47e266e3fae5404d5e9ae5c614ec3bf0437aa098f0c930788c0f59f972ab60350afdc194d9c240af66abd494b0c142503918d803fd774d96862d891fc9d5885e6c3285264b1acc6107a9d5006fa110b84214eae437b8bd4f4892a5eabe1560a79465061116b89c36c0ceef46797935a32714407fd1be3bf417c2b46520a84ce59602e0ca9f3fb5e0b0f152d0da4e9860f3fa09a2fa62f352945692c851a07b2d055604b79d0dd2897464503e5cb9e5a527a97a72cfab06b1339d1fea5ecfd4300b756cdabff36b33698864a8a04aec80268beaf56e12b297d11300a7e456b4e4f2ecbb1106ee7e454e74e8ff9170bddaebc013acc370e11c48667fd0116dc4e2f4843a3a28d94c34a6b39be6d86a8dbfc74a879fe898a76518e1c150d4c5fcf38878ab67e5fcfa0a95f5d7cfa04b96ca506381c49c318c570eb234225ebd0aaf6bf5697c2c3518ad6fe611df96f38986820106da1e2600d5aa6bcd1eafa7a8aa61c742293730abef56621f73b9ac637c673ef6a3b754182c5856b8eb0b51113ed2b95534b8f334ff704e938b55775b90b5308f37c51dd1dbb0d342a22c52c662fc3e899d0cfed8aff3143841b87bc3cd208c532ee0fd3a2d089263044bbd7616d94ba398322dbfd807442814f947833322768a3ed96cf23292b47cee2d25211b788a36e10c6af25f4247f4d3636cddbd4fe828a15dd0bd7c82c128b3eb995fe5da6f9ec23910a92c7e668ee44fb2241f720599fb4872f8c4eb4780f212ef5f95b16923834ae5f15c2155326301764b225953e91a0499d6808c30b199e2fb94a0785cfcca0713422beda0a2d55c26b9b70bda209a56539be8552a4745f4d32b8698f3a0bad4dd1421233b73f6174aa8ce814bc760eae4af7187e06931a930f5a47f9fb06b644df044a13e53c921357eabc57d748c3694bdc222fb309283162f42c3e8e816d675af364fd8339b7d9f6d327229476dc9e40ec603fcc652a0605504b354b55de1c1c886a16fffe243cf7f821c72a372d6197d05036fc85160eb2a46b67561ff6547556bc836251f25faf141622e2af3c301ecfc05bea4c8ee2248b351b31fb462d084a785f5f4966f97864d7e580ca588874a8549be0292808a6cbf2fb601d3b30556792f9e874bf19e21ba254f8adcf13f73c695c4752ccc65a097820356349800fa9e64b01a6ea8ca3b30209a201b62acfd55abb087afb2679576dea89bb38b2f5cc416d466d5514c1edbbc3bd74460ffeab217b3754c3c015e9ebf37327ac3da4239fd8c453f23439ab17101cf2fa226bb7930d7f9ed87b20ef9102f6f3350a8b64f04ce5ad726d1885029c9edd7ed6f77a0bad75dbdb590447ff5fe88fec418e190658da7856570b5385ca93eef7594a96141ccaf385405cb26656e0e59b7146349878fd93974c32dbc7f4af60b94fef9d714d7f9b651af8d4a8e9a742f7f52c272159b9ee65d8aa95941acc4fdf67fd6c113cf4e9a58f4f8b8e8d897e7b0282439a800e5beee7daac01a5677e29082836bf0cfa93427ef54f54b7a4658c75e4aa909bca20634c78aacad22cf92671a6f109e05bd96f601eecab1f19975556b63a6426900275845f62fa556059c7d2cdbe376acbb5c896137c49a338a4d519c3a6c7ac66402f1139b08996b9409a3df85e8abea5dc8c7c2ff57adb1a3fdba7e1c563ad3b632d61e9c7313c58bb2e5792902cbbdba80d794fbbc17a221e2ded42e6892039da358627e295fe15ed2490b951a0cb6423226253f294f81706c7171b4e008f304da091ed322fb06c3b89c46cc275ed0cb5c3206c72d71843cc521cfe566c1cd0fe5301c3efa7cd3ab19db9b085d9f982cf948a9da7844908e5069633a97b416418f14f9a3f30288492686665ade51f2be45caf449c8f95b96fcef891a202707ff99920c941575802b6c99b6b6645623e96420bf6ee87af92d2c8b1b7f2b9b1a5ded0248f3c09dcca821f9e5b8f83cf7fcfc262cff49118393ade3c4bb5947552b10e7122c06b18069721a11cd92a6ed092cb4c4df33492206c55263a1eb33495afc1e8c0840570e5c7241fb79007c98aa156896ca365208bb2c63fb5a08d5b8a43b4fd10710b21bd52acc9b388903583ba40941e9406938bbacf13d728ba669ff7b418e2fe166ebc9805c9a4afec45ae400f72dcde954d8ebba85282ef4a571cfd001349f6b0d518db8500e943b7f9100dc78ef2ed71218032a34c0cece0f6f94680468a4ea0c23d4dd35f21612a6e8d8c1757597eee472d4bb0adb069d080f74e2dfde7d8a253068a4a2c4b7712d5c76389337adda6482316460a07c3e27b34e9f1bf8414f95ccb0d2f2778c8e5a611377dbc64ce53cb20f2f3b5050586ae2f41072bba48c42904c93f5851c021343e14b1b70f3fd9843242580a7ce4d88e7fda91152e9159d4a13138d51219ab2877de12590c28d774895c4a95125e7ff614fd4af02b193c9818857fb03d22a8de2293a0c8edadb6affdf26a4f9100f05c2d191508db2b8c25374b156a7132f5be5fb1a10cb3e3c7a78e0e59a8a0fde3bcc715e8eb2e23aada3f3d0f4968204f7fefda0c46078a447213108b95e17aea59c9b7c632603a75d49f040e1134d966d529f2072d005b632d21f5282af9afdd07d51a75bcb2ac82bf71f0896f485e373f3ef07abe0fcd4bd63ddaec0662b484ce82d2595da19745d91740d9f75db35705dc3749f897de4b99f0a7acfb0e1b7f8af00ba3ece7ddc8a2bdc636adac9cfb6a8f0579f90cb3bc08fb67ded1d1725f254aef1a346740dc368592b60f89401dae66bc04bd7a304ff7a637c827d5b69cbfdb36e6380a6d30d39ca15e1a6dc80bea695a3bfe66868c170a1a6b4311499d107b6cd90588a7a7f3989890ed3247f1a141897136f4ca0823c594a9c0686e777da4f06e20e559c5d22cd4f0866eb939e26579180dbea224b0e4bf30cbc9208b4c292702a7f98df102a3894e2c1354415165c2111076d8161d67355e36f7017261ff1f3282ddc8a89e2548b02c36862620bac24e920596b98fc6bcc5eb11da66817ed6c4b25d07699682fd5aa11afd25649b25b971b47943a2d70d893812e06cacffa0f55a2b60d229633426412dd53cef6aa40ebb2ff75f38ee88c82255a9452a8dc3c35fb5b3d1e095238b8b9779b21238fdfc01a5f84031f4b9073e67e4d0379f973015fd8611d0620ae5e396bb3f78bc36afab0eed303befeb9ffca86e992c4b8cc9b995d36c5769f4c0dae4510a299dcf7de345c3adf25aa13a526508c435abb62c613c945bd00996310d072c174bb6f611ad2b1c0f198bca788fd9d62a843210d503ecf5234983af47ad92e7547114cb4341d019004859265614af4cd798e5dfcaa948798964ab97bbbcc679ea6a792c97d7519bdd351c644478c4dd08d3501e9c4a47a133bdc6e20052afb0d3928df1dd4388d0f27a8df4ef1a62709e635259e845e618cf65d2a34c6672fc62003956c11e8d23cb5df4fb394b08e8cb3a1d6191e4518ae81901c507999ab1300e1587bf7bc83a78a8c828b388bf61444f0155235322637a0a9240740f10de6a5ff9a4906d84db0d18f3675ce93a50e996a36cef3431fedaa648f54cbfdc4ec1f8ebe1aa8db76c5de9988bc2a7799cf0549482234f5aa446c8902dcf5224f5986015753837c6aa44011b0d812779b7d569b3fa3681c5695394166b2f23b1735a969be85f74ba5a76aa799601d14d4c2f5866d26c1b6b82632f7b0cd977aa148f8c039a75cd69dd447259bf00422d5065ee3f04111327c9c318000bea99c17d27c229601b3ce110aa082e4221b962b4e9cfa3ce852a4272bb16706177bbb29a910c7824e1b6dd28fcb8903619606460afde95a4b27ee307ac05710ed077b4f5a45c5280655179fedc049a3532f419e516f9bbb79818a3939d7c0bcb1904aeb95247aff557e1edfb9b18ab0d1fc7400da64f874722442c15c8f42947e65f261dda6c47fed1d05bcd7cc09027bf1a41e373eb455dfe203d5289afcc8f3f6ff9da79774a9ac1ee19a2dbe6676f339b84463be5a113075ab5f722a3c3b07dddd26008aa8cff95b4bc6be5cdde4d2d1348b0c5a21d7021423f26210743a911a89ec70b82de727b83e0caf63b1c747d58dcbb381fa03930646ae9e2f481a48017ef93a9ce7a065e0dd4059e3e1666c011d84ae1e1b97c74003c4dd43397401ff8671204792d5ae517972ea6ec4b02b8239ca27f182bb53b764bd1b5db8c3c5a02a2f51377849493ccf324e37854f8ec6c63173ed831a8a8dcdce843f29cf38c98e0f4404c9f0aa3df058603a6697caefa10c7d04388b20e51c29c27cbe63df16b75316b82cce048238e5a0e292a0bb3cc98d0df7c458a3878b0596481000b563b8cb22f8ceb42c91bbaa0216a9b88cd89ec6baa2d36e9980be06e2a8592c581877ecaedaf249b174781e3977dbc60c2e5a8583747db501a9d4ee9434952a6a27f00a9426fe1c38fbbb694445ecdd63b37cb0679b06ea7f71550c82a5dc9ca1ae457a53b455303fd4337807802b2eba342493812f447f82d78abba97426509fdf8375646b9f8488261763826b19b57fc3859b726e0e60f08448c06c087f5f142fa6a45fc4c5c5e9ed8ccf90f6fb08c47fe8df0c0ec0d1704a2ef2561ce548b5750091697215422db8dbd6b9c276237dbab2248b92b07935493d3a2dfde9aabff942f30465583327e6018d78529212e646f9b0bedc183c1b33c9fa16286d104afe7bc8818f570cfb14af44a97e9de1b8a0c466024c6dd14ba390f50f834f9736b6308e1e35064a582831d9a5709f494d9599a093da5c8703ac20645feb3ee08c9a1145d5a42d9669081cf1d0f6056098f02d358839714752e625c1bc397b9440ecfb3e83ba59b4dd896f1b1d990d1efe819de0c8018269766aed6c9b6aadfe0fc32fba05995200e5f75241891ac5c2edfeddd17d2a7e3101fc64cb739e4e92e89187c9ee4cb23f0ba62bc2743c5ff8f032db6feed263d3af1b224f56f291064f9d27d28b17323f56dedef85e8f95a05f7845114977e758414161b24c2472a489edb09f365f75b0496c1ec64e54f21146141755e56256043b0fd52cc31da306f55be07418b323f3f81bcac7ffab05a1969a485ea544820f3871c879369b0790cd766a94ebaf09d6236ce215d5c5528c5549525819c862f4a4b7227a3e582c6dc8153febba01efcf59b8eaba04b440a548a03702078c046d68a4c5482ca150ab21a351846c2a3a4ee9786154a2f4969616219892b6f7e02160a5a2acfdb6ac5a7a21e31885e9e8753e99852355bafc85c37ef2ec2cf1942d96153f63a671899aff395b1b9197a7508bcb796bedf3224b669b2750f3ed9d80aaf41ea801a141c619d154ca19065f4d63282ac0230f4dc1a1b3aa488a64371a36af0173af037e815b2b8941256c8e8c6ec8879d9b4ed5fdfb6f1577303f3e47a876ce37a9acd885e88b29824db07b004c90f2be662e733caf5221877016d0b8a41dbec3cc5e819a5cc188dbaaa86f498f6af838598640d0e1abe29a68194511b17064e46c1bd8cb2ccd4101b3b818826ca629858e9f0ea1f1b0cb45fb38115f047cba8737aa84cc73d618aa4e8719368d21064e4fbc6ed4c2b55c615a506f015d077ba1c7e9a5fcf528720cbab5ec3ba4e7c9612073fd7244ad5cf71158a8d6daaf3623712f8d40a1b3c88107a1af9babc6822c4d330af910a005042980508002de5b57e3fc57aeb3b17b7e40701a4a4188927b97b288ce72cf158b20ccd2764d6a015a3166d27cda788a8d47bc84b425aeda3da8a0cd1328ac915e047efbd851d00fefde036cddfe146a0a06c48df7a2ba5ac251fda2e3f44373ca3580230e4703ac08292b034bcde614f6891772896d022d42b853dd02e4a27301a1024ee412bcd2c2ff5562045b1dfb8f6e81e8052eead4f2d2cf0dffcdfb46031059b222b851da30a011df208a11d99c47ae1915f97d021addd0c85fc758e9cc70c1506a4ff7d38e71cec42a7284db68ada6770c802ea4c7c0006116d228aa36fddeea050f30c1ec3cfd5ca7eeb94a4824ee0e09d165fd9fd9834a55182f5e9c2b33aa6ac98f4566386c7f5be62c0bea86c3fd8a97df3efadbc23d9d7a5fbebe757673d0f1dbe7df585f20a93a50cf897d8d7ee55264286c8be21eb413fa4b0044e63feb5a77f45ac102b30793c002dee86b7cd2dceccbb7806620e899aa0e7ca38ac66edb779eb6c876a067aeaf53cbc9a3f96adcdac313aa148ec2a0d0263dc73b7b5eab20ced3019fd9798fc1ec79ba63b486ba2dd527375e72be64117cd05a3f9103e548cc258c3d586d06a732cd16a139643c6601e1945a02c0de83c71a1831a1cdc1483ea3dabe2fbe80ca63d4edb3e3d9d24184e6b9839e3ad1ddfa58619c44722a00b1d03cfeb27b9d9c095dc0e5152646a54fa93c31bde53e4d7dc4c496e70ed35ebb6a2d5e40384d57abccffb9955ee25c3b5dc9c6596e7a8646caa6209396783caaaa547043ef5a73b59c1138869344b2c4bb1dcf253c78b3a573161eb024dd1b014152909a02b843e7ddaad17b1ebaa8a9ef19b372c6c25906098e10149dcce30b255f16b7a839793a694d86cd73c604b369e33c4a2cba63e80cec7d68ded68ac9da782572515e7f16049feb44741655de98e6f4d958f19bcfd84643b73060d825b2219c9aefa94d5680a3ac8dadd87d73c5fd6dd9d142ec2dd720a8d628853908066c0b87c575c657ae9abfb21220b0bd7b04c7ba5104f1005a50984451ff29333ebdf7a2b3dbef5a4d3af0c5989514626dc7c70850b41aa613cc2c4e54e467583cbf34b959454213886acdff891f36a16009d18e0f6a2fe38782960f7f8b0b770ecaee0a28093d1684d3a306aca01da703511a8b603d26f7c74881d58e65bd7daad7dd02420948f363b6335bda44cccb58f6993e46efdb8eb2b2d3501469cbdb04fcf055b8490f19ba1b576864d76c54d8edd1072572b4f1972bd58b765883fc21b38628482867a89742ed708641a4e130bb02e36a6695db1b7ab8a1b835108e6480cfe4037d5872e84fb9a5ed044d6eb91eaeb1412c93a02f65e27ce40ad556f47deda3c7ea1ce237ad039acc2b8122c9494980c7180a159f4cc5166ff55973763214875bb952309c67508c14120b301fca33c28ccd70f63711461c44bc14fddec17d13e23cb11860585e0ad5086b71c712cceaf6a9748c67a754283c5cde87941040a8fb919eff85dfd32b58d598dafd5cc09aed6a535299964bad4c75429d35a3eb03844893f6ebe1fbfe761ca53d96c890b818628cb6dcc6f66d02f28dd2313af9d4a606ca8ac8b338f096dc35cad4ae0678861a8ed3b3c682782b7cb1115d819e43df31d29ca7d3b8ea1f6c9a657676769840c15b9d12fb0063ff9100ff5f6657c39a264bd22a168f1a5f8a4424ec2c8a0ff3b43255a2628d11880ade64ad74eaed6d2c2277c02e9f00cfaac3ec7fc7a1acd62d3c2403e7a640fd44b6757649cf912d628200175e9de12dd448c6658f29410c6e15442f15f60d73a796171fc39cc0de84f10fb656bae30490d238b88a3057949d9113820f359da38f457b0cb22598519b13f1744cfa60a675a91b95c23e7a5684f16e6f613709ae10ecbc214edd2208f39359c1966b6af3e16e6a6f4f56ac9dce36f6a020138c1c23445b15a8ea7851071eaff936b4ec5e1b082f1fc9073e7203a70b89e0cf5c438e56f68c773e3c71097cf912b608bb933f376202668b6a2276430c436eac5659e66c823ce188d9f87636c92d4bdda638db373f9ec8b94daa672390caa915c6bc3e3d2d8f2af95b5ec8ab1ca3b666226d824e58345881ead41cf82e9161a5455897bcbbb67baa84375c36eb82249e914b50ddbc3fda30c3d204b010c86ae6a0406334405d1a12ddf3f966a203a2c270ae805f5fd3a3f41f63aadaf00b8782350d7b304035031206f9c83711768f201478fe301f630ac7d01fc975f5ae9375e45123619dd1a6fa9f743796341dd9d5e602e2bc8e06557cd2301e7519a7687553c4cce66f72d7f3d8eff8436ae255c066c5e0e64769adbfff546c0dd86ae423e900433daf42cb6deb8e0b12ec97027e0b9cf9c50cf485ea1145ee5a6e3b1645d2aee5372ec12a8e79102632157ddc6198a4ce24e56553ff84b7df0fa7d7e5bc369694468b2ff79aa3de3d7d23c548a111eba20726e9bc4ac80079c71c952afbf2d54e40ac19469020068e9f1311d7cf90e615837f914cc13ca383171dfb119d90e128d6078439615450729b1822b9f9637f98ba84fe68b3a2b7aafc5820e6f0d1d2794f0446deea48415a4753e669c51c29afcb4e1f59a267f53eefde249441e5b6c4d5e2972906160de45c4534cb327043d53db08e6ed625c2b05d0aa75f9e024c4e693760e989c0bdff68fa86a7a2e7c5b67a73353eb74a87ea77655ebbe175697d499ab1b9a03ac011cbdac1bda97d672eddcd6a7e61ed751c7d5f5e8b75d05affb37f475b853172bce6b616f48ece833eb314d33cd3dd046b9ab482eaef31563939e6c8c0cac2a43476c0c795c92b24729b4082e093a596854413dc59be4738ca611aecf3ae3c007ed380c3e24759b5ce1af675b7c0f26341d5994f5c83775c4fbc89c61558b4767a390302df00b5cb0c0052ea8374aa31474505df09e81526b3c0ecc6b23f916452da80c5362e5c19bb2e9e78345f2af3248f20cd67b4caccf47e7c6579eb306179c810c46f0f79ef250a5913ac7b065a61bc2d52a942ecbc69e14eea42ad229fbf3b66237dcd97d8cac6453169c3e2abf288e3bd95ae3ca17cdad1057c67a15105a0ebc1bb57a76f7f65032e64e856a25751d82c9c70848853190e76cb6ed01ecc2be86488d167d95ef7865330490ffb1d7db7f0b6b62116ae1932d3a54df5167b7a2f5d860c96caa02846e8cd6eb674aeae71985f40e6d02131a3dd289fe9e85ba6ccd96ac6b3818c91b9625a52a2720e41f223afde8e9fbe5b485208713ab43a866923d7e8d1523208774632a7a54587903fabba39888fbf905b5967df61cfa07b833ceb0e3b7b6c897a87812eab8d37c1364d0511feb9abc35c6cf44b86a694bcd17041111960e9f2e149d5017deabb070992f04d4f713b20958db8e90780757833f09db25b4222dda08dd9dd8d8579ed63eb960aa1a64d4dc70b10305ebbc0b1d47932a386f6bbbc9b4a7296bde916596f09bcc30cd3b42b493a16c762cbc8f952976861647c32ae95d0c6617b82eabcd4eb6564df7e915a89ca8db07638fcdcdf0f719307e9ec4358ed3d7a18e1984498b881ecd48b035cbc1aa46db03aba5c8908c3b1f820140caa6a570828fa9c6d05ee16324df2fc2df285cfa58859ac37c5841541be49fde694c162b612d7a213e336165b8aa2062cf40b99751e1c56157320a69f12716fb697ef3b576188872f3a23ed969ed86c1a890d18d6f5f275cc31d3b81fa9021fe26c38bac4686649975f2283ead3e99e0c81bf369d39862c37505e08859967a98b45087ea40d7c503777543226d59362ea83591ea95223588a75724a42b22fbd5593fdca555e8a3b48a64420f1d05affe4641791518a82d27c26d36054fe1e479555560d98c68b81ec7e9dc188a393714f5f895568cc54acb510a02108df81c64a1b0d00d662674a7f13d137617c98465c1252dd553eb6c9fdc1bcafcb06e7ce9478775fa9dd102d50df7e0e13334a8c01c91baa5ae8d4d734d9635b4d8175150cfcb80f0970b8e5c94bd80a93faad2e25fd8f47d01c95e78ba589853da8befab70556c62dc3a452361ed74b113ddfbd420184fa29f91a7371246dc31e8e6ec098aabba4342a57c1eb298f945dded189e91b3c75d8f481eecdc8718a36b80962281e20bf8a1d65e6ec1a5ed451309e74a7a164cf7b9042926d3ba75039cf2cacbf2303adbfd9cf474e99ac4dacc7f05c863ca84ab39d70b06e15847d69d74b12a381242b879e74fc3aa0c4e5783178693ee54a4cad10c5f4849c242ecb5873447790ac1508611844f68836d02a24404609942ce29d0f2cda87a867d6c7d781ca1f0370f615dec39399eab919cbd7c743eb55793e66e9b656537c36e735327252491fbebe8f7a2c8e532b8be583215ba4bc1549ad674ff56d27eae49ad3ab99b29efdfce743dd440b2ce31dacec72d96c1e9aaa57454c1431ddf97dd40dda43c7c56d3299232fdd8599021dacaccae87d168d463b4818445a17054f134baacd1b50bfa72be3ec67d64055aee3ec8c822e28762052b70ff41ac2a0cb8c4862bac675d562d80b45411c1d566936e1c749a9ae4cefa4f7804fddce9a50845d4feee357b1c9491664440f19f4ea5430631c55914a674ece593ef2b273d1ded14eae04318762a7fe7fda2c6d04b30b708a962d302975a0a8b1b2cc21b17fe925b47cc0bfe556cd4ea95e55e235ce75934b799f1eee7ce35c8f09f9d71e4ef47814aee0daa33c59723ec3570c0a2279eff46865ed23d5ea1d7f575a84a78db7cf09c15adb94cacb5b486f23ea002a2d323a1d22208e6b998453a9d060f195cd7dc37f4d1a643978a3a8db4b1a2d8455ef923cd83c89b3c02ad7b4816feaa4dff0ca506d6d2dc49216335e35f81248f12657fb65646d6a6cc04fd51accafdcd95d5e44e3ef7b75886bca08de66f9b0f6e1b5e3170c64f627750c68210810a6d15c8d8fb95a0af0f6132f423d9dc82a1d3ddf577548cb45864a58aa204a82f6ef8c5b69e73fd127ff00775eaba9ae00e6d569eb6889f22a490a3740d33b5e96e4cf5847404fa7d6d7fd5f9a1e93ea3b7cfc45fee3d2cffde987394a49c8005b5342fac1d7f8af286b2a0bdcf319f35113b3f49566e0ca8168b5c9c7bf53baf707636bdae01bfdf94ca42cb512fab01717f61b372701f6a01895e2665b13f7bff2388914e8813897bc41bdf8fbee1c47a4ea4da127bffa5845e19766ab758137397219ca434c77d899ff3313ab3f7f5aa072df7c0fc76fbcefa54d36d88b990ed03adac1225cea0b109748ae4aebad56acc83168a2365ef97aa36844bb8bbe2ec0ef0d6519604afab83b2f7e19a882e9dbefe93d30d2b231f4383f2990947c159b01cc16f36a955fdf0d2511aff0ba038f6ee9db8a5a83a137687c28348a0691bb2b4e8fbac450b8e025faeb03f2b5c4f7f6131cb01dd9ee4512ffe1585ef2628bf2b7b1911a5e30a8338add4f04602bce6949db257dc6efe7ba11887aa2b321b3c355b35b8dbc954322e25f3b87a2ea5ee8ee8a13077f662a14505ae6f707ea0bd08962fb8065f7003298ef5b3b0f0080d2bc515a6cf7ed47948c61cfda85fff4d3bf4f9baf3f04c8fcba03d6f01049481e81e049cf6816b97052165a90d42750e5a6ff2d8f3221963744e7f95b281acbbbcbcaf2db0ca1716c08e4a43f338d3d61248901574cfcd37dde0f8cb17d3daf638a8cf0419a0dae251d70af90eac2eca9b4eadba6bd58d5793129ff305bc491e41085be47aedcdc01623497e72b967fd3d35a9c7b5e267e4fc488fda1f986ee5ec29eff5d9c804594af82ff3cf900046c06fe099ce8ff1bf9fd48019154bd79c3c4cc88650475bb76c85b94733d2015e43e1b3e14898a7d7202d6f047d1d9ea3592b12044df3a160a2abb7a6a5336fc6ef4be79383e082095c11ce3f83983ebc846e738573d5cee53d1bc905647aded8ed4ec38384e70d71bf1950be84abb6378aff14ce38cb6baae4bd8770e494f71e829143cb879901173b0aaf18180093524c6e88b07153c2c72a72a56624754ba33d270f204a3b19c67c1395365931038fa8915f282529b671fb40942a5c3b66508222a89c48ade79e5052dcbcf72ba6cf5e68af6aa76725f7e007409c2a7fd0c766decff13db474cfd3743356fa67453f41510f9935eaba64d2727b7bb6f3c699c156ba45df4f1485d1153ac49f5d130df31ab82608e8b07af0a647924a36f88249010a35c921709c9cbdd9e8d992b96e8d161ebd1c9920a7b0832a00cf26578a6a8c926b6976f97a289dd9adbf05ee0d496e8b177984554c2b4b0115087d69227966587c086b5178bedbf9b055001429ab80fbd17b00d40a2044a9040416bb065b868cab16ea3929655a61a0c6669990cdbec401a88f35647813eb9b2ff7fa488680936008344f0b8cc2dc14bde9cd26c4e6fedb4741bb8e637ce28d679b19f232dbe35b757cfaaa4982d13a03b51947e19d7cce1da778cb71b759173f0f74fcd4a18a0b84549dcf6329d131bd7cf84fb8a559e6e203807eeb680058dc3c8ec600b19d122605168929cd63f59ecab7b90af3f78c42a2bbf965afe9eec6eab0f856149d9d756443552363a326832d97c05e6f5ee80188f5f8c64637f822ea0f19b4b977d62f22db6959b7f98dbfc16d9559adc67c4e2df1993ee2e031d17b6f05f2bfc1ea6c8ac1e184528112316ecce59508c4f2c61911df06162c76d64eb66182f500e91f2df3941c18b52a4d645578ad6356478ad41dd7594bbaab73d5a0e3e8719e29b8df2c5759abc6b18bfaa3f91646983ea4822f86640abb2ac22022943b2837f7135b6d4c0d6794c96547fbf52573f2497f0d6f6285f2510c46a9f47baff5875d092f51727e7722a07d06040921d813b28c791a336b65100442583a1a0cb4e57dcbc2c9ed2061a3aacc251c1e324df52c8e357a986400c736f871d91c335a03dd336c2b77ebb9782e96fe4ba5491ae81fbd3f698302844b179a1ff984f46c00c99caf3ae9aef84c7c1ec54159bae578c989cf9e7d5dc610f0a97bd6819bf3284981f21c378a81a27994690cc67fff019be1417d5fa451a7a3075a980c94d612930303b145c2be66466d6bed4d75f0480ef5e9a15c9165bd3b4ef1d9382d65f3563315c6b4d77984531398d276619d43a61d88f0a0839b0fbb90ea4bf72638d31665659e03e46ba765645a893f204f0632f421376e37b2403e2ab1777141ee832759326ebb7704d89581ebaff79759c45f8afee0215fb9a90942816225f04b54e056e1b98542872e79b2522e2362b06aae888128d8b796e2bf9017b7919dd3f4e2f6dbbd1632b601c6fff06d74db2ba99d687376904331908e61f7d4cf59b8a48d5e844913bdce6b6c0f64718c32df5e6d9411c005a0f010596e6754a1e1a83acb23f2c578a8130089d5684cb94cf0c2c01db7195ea1a3213528f9f15947f791b18ca999e5634a1c81324b63f1a0d3b26817a4278118e39e7a6b66875803ba2a564e1224b921cb0cda181f643117028d8f98ca6797b9a86786ab099baffd5d06479c6e9996eba125c6500b6f4693d8a0488518b586558448e4df067840d902a85467e963b8dee44e4f8a1654a845cb7c5464c996a2f9357f0911b3db4dbee59997f52637b2645467e7eb4e1169ec84623a9f1e53abb51116d763e68c37ec4a309362973185d19d7c1c7d89147713bbd6b0f767d284a499bacdc01ccc42c5d898241836d5489ac90273e12e99f1b658ee4898028d098d4561a3adce816352dd95b9e438ba2b58240079897f138b1c2abcbc48887df935e6dc51174f675fcac87068141bb80197b7b810125a8a8939c64bae0cd1d1360f54510c2413d0c2fa2805e6ee78d9e3b8cd0bf4756e70941de742111ff194618f0858ba5a7a3cdf1ce3f958d5ce848b8e6df7962d8b52d658b721b26527cb6d4b8f24eed8b34f072aee97d766e2e9f8e824dc86353108d9b480802e18d48ed9c0dc64c5a9af8d5c3245d184ed0e18991a110c1ed082fd817773d921a62cea898e91dbe54605bd96f819f960f74bd46b081edb9f61f8a371befbeaaa9488e0a1beef96b427e3066c449af573d1c149407b3957d57980d35c2da1e7222cae4df0d554d3781d6b9ed91e9d6e61e7974b149b0e37b2e51b61d099620d9f2c02bad8bfb442449186583ad1afc0505314699f50d678613d30459301ec058a270cc556eaae885b5b691555755546b51f089cc36f79fa3addb115b749109f45a046bb1a324298b6a00209583995028940d4c3077801607433958d654b1036f0c6902e1a62d6b9f85fe78f7515786f7a1837754b70b722f9eec283685a2856da9e42ba473b12d0625acde91595e039450141e9f1edbf4513998c8ed9fae32384a951bf276140b459219e9d02b2e2094991c4f7ed4b96c85dcb8d67cab33dd28430e93a60a49eae9a7a9e766fd1f84216cb0df544e49103ba7dbe825e3090325207a6a24652417fcd0bdca9bec93430bda6fcad498a95c43dcbbc0a0fd89e74733c9d5cb22f15c6c6982ac67a72d300a000142e1735488958b40211c06825e041a65262ebb63aa97ba91166e007d96682d0de25646f29a54c52064c081108d8077b5c99c63feda6b48ef4237d69244f10767d5c49b1f1c3a036f706d4c4306c7f10c7b0b5d4a0e2f01fb263b69fb67cb11d1fb9bd3097974482240f6a529b4a7b7e57b93c571a8b51653407db200483c0b158412860f5cfd3a63cf02ef5a03615046ad63f1de786dad4a736758cbc7128c9048e50e8f3c6f667a1def0d8183bdcf72975a9329ae3670dd7cea175872d4d28a20a35e92e4d28424771d4bce9e8e3eea88d75db2d080bae3238e8fae16c845af481dbaebb7e0322d082c7288c5eb9bca20fe8f6497b62e0b608758775b3d6bfa904a83bfc75ecaac33e79b0b4e08c5238fd445e5c79adaed8a0a4264442a9e5604267ab89ff05fb1b7f029ce0cfe3160de9f065ec419ed8fe29918470dff2ddf4d50c8fbe2bda45187aad6f7fa4945aafd4ab0d63c9b52c27babe0f31445d4285506b2db6d66f89abdb8bb383f7bec0debf165f9bb35cbb04e76fc9672d687fc80292ea679be50816f3fdaac520b697c907929890ee2d7d2068fb6ca55aeb83a34e25754114d25aedbd388b3380d0f4431024914aa53014c5eabb4d5f87b3179f5629d5b55e55aad2bd943c456b71a8f32ad43a60e6ebbc91b1eaaaac4ae52aaaaae38ba65a6b133551eb7276c0641a75660ca14f133563087d0386c2c0c0c0d030a6c6c4c4c4d4d710fac2c058181818878181a9a2cb0964fb6985d271c34cdda854ee30ee241a850725cf94088e2eab1479c266e8cccccc0c955165c89021a3badce572b97c869d3163c60cfbf7ffff6697b3037b66a6541aa96ad4a115c66fa85ae9a8461f1f8c18b3929161f9cb8a45b6c8197a4d335ee260f6cbf7cbab9446a9c494bbb5a5c5511b7f77ff36c6511bd52802f5188d67445194e11281309ea1f56b4d6aecff8202ed7e31d662b97293fa4dcd0042fb7b097e9906beadd6a8d33275648832a4d02b33f4bdf56a65ddc1ab2f91cb05d2195eaf0c19325c2ed78c193344d8a6ff224992ba2c4b1a33d05e9ee27677777777777777771f2f5a682fff9f24c9b2a44183c6ebf5a2a1a1a941966559d21069d000af9b26b5a1ef618d1a35461fce81e86e6e1a2f7dc3aca9a9b161c3067843dbd8d88036c4b083d7cc4a87eda0031b1b1c38ac55a1e66ed8cc2042530b7358c536a2cda81302407477778b2fc6e5b538448a85f61206f3c0830f3ec89163d4d1513f9713c8c601136710a14f7106113870e048e1c081c281a3d6b8d703e042fabaf9d20bfb1078e41e945a9c989ad93d7a7ca26b076d41cff7566bb38335901e842b509cbc57a038d8afb5575ce1650acd8205e80a14a76efab2c7d08648491791e756f29b19ec87e9c5d67e26596c2fb6a10bb4f65e4b7ad0da7b2d75d1b40de92dc1a0c610e471ce39e79cad2cb1b3077272ce3967725f18746016fb36d9fe05a843636cd954894d89c608628775ac3fc293ca43d5a1f793a54ad95e81e041099595deff8795795d4223a043969f2d665650d96eeb96318711fcde4a2291de07dda407b241f2044f1776fdc00d3e251a43c90ebddaff4820bb922dd89d4bd2d2107a0b56d4fd383ab272f4e3c84a787361dbc12a04115784186765d4967ecb1dc541854014022e84dc1e004f08b810725a84a7bbfbf8cc67db6f3ec3e23e2b10bce5a9c24ad4798f78245a118fc4a33d16f11ef1483cea85baa07d9f0a3580e238a906d24842241e484224a14daa02d2484224a12d5b2c5fae93d76d5865fbe77bedcd38b48e6dc5d65a7cafbbfd4bdaf71beab638db3dfcdeebd7babbf5fb5b803183decd06af28427d73baa934a8fe6e6b60efcbe8621a61e499987f6e3209f479737343733621c0154a26c855f2551dc829148b24d3d0ded708a65439bab22f7ef180b30cfaa43c5cee13f2f17c783cde0a2bf078bc15783ccaa38992898c743bde1e81e2dc374352a906084ae12b0495640a451a1d51eecaee416beaa766ec0b8b2394d1e50584cb0b182298e299e979fd8b7ead404740023f4c3f78d046b113b4a6117e50268c4e344dcedcdbf67b27f1cbb9f7e51a641087aa21a44fca03792bbc7ea6f6f07837b0d30d19c4187a010d6100218613274e98cc006ed9228444122d608f9f9081b60657bbd85efb5fce47b6ffc4b65fcb5353d9f63f2bb6f5c7b6acf78215db0fafadb5da1e4617d7ea98bc98de8c367dd2b373a18f3a18e7efe13d8cdcc4375faf0f03671a046b78e0c87d1bf4b706594bb3b53d73bbdd7af4b865ac833ee94d54c110438020d86c3ef8005ad95de9ea10f8a221bd221e2e76f8425f21b5a2bfcdc28d1de5e8d57516aafb5f6da2b21fa4dda9b7b5a2417d437114406decdb0781ca16506bacd12a06262bdbdefcd8e9b74de89ad81ba4a9b5d5bfd2f010210b94da501cf57d5ffcdd7bedfdcf664a29a5f4fb9efa83abfa325d21d0f4e9574102bd5842a74b9b160531028c20434f90c092141530619a42bf34a9a2439b298bd634220dfea09ad098062854d0a353410c4e74b869910d8c15cc000b2c5222d0a44d8b6c556488a288cd09120816d99e8020088260945dea0b5b939b2d88cf67a5c56c070fc81045ab362d8a414b119af72fd3c8100cb722b078a1c74d8b8ab0925ab1983c014448089cc0010a1323447cd1c5c5810950b36ad841c70cf1c8d400c40b4c13deaa86279f6ac92ca606dc4b6ac9104c0d2f784135c9a96ac8023cd15235ccc03484aa618c926692238189d149cb30be18b133d9607219c26924a393dccb902822f1e312050c91301a894a4e78a20d2f20dd76a10dbb11ecb125d0062f4a240ced6c18233412c1cd4809502434b119f1c144c2113dd508122f55af8ca0d91a0a1a69e28504247a46a800493062c89fc616983b131e488193a01e0d8844c9c938cbce5ac8200f4581d16c5a34a4c376d9b468688814580c8e7a4214c68f8f8eb1f184b144aa041a65c5a9091da3a50623805d25ab9b4d4f1e38d7ac4d896cc06475bb10e3a4050b235014edb4c94911142768d5342eb67515a18b68db9a76e3116f7ff461ee5bb2744db40c28763efca1101efb4a24316f7f67c863f8f54602f3f677a2784cc411796c8ad14e959d238fbd94ad5c2251bd69cbb6262da62ba69d86d27353205dc22807a567db3f9d4e32466474d8aa950c1214cac7ddd547476decb3743413cf6336b67d931697fd6cb64fd34e8f40e7ee2ea5c56322500f684b108f893d1e43f90415f158ebbabc7d14c9ba42b2766e6692a5c3892daebcfd1d4fbd7cfe4bb2aeb84b79a6b68e9cdea1edd8766eb40ada4ecd63635964db11f2187e9dda2dd4ad43ab70922acf479527ad22cab6b40a229d9b47be03aa0d519cf05f6e7eee86a9230b16b8312db29d7458494223090df3aa87a9ca560a2b0ec4c43c909c160aaa1760ca560a3039aa0792533face30fd5c33c1d538829612b185245a2523d46f09f9f23457ae07682dcb49f1a7576686edaaf752768a7564375c20f2b53fdbd2a84b7a05d51b55d1f45dbf57768e09f50beada928c4fcea57e50b314072bc3ccd5d8d807427b8401f99766eb2748eb15f9e1327648832029d157c751e3b4d3bd691dd77876669152a11f498b9ebc3a0626274453d6bd479793cbe0e2bdac5013d4a651fa5b2d4532a437d0f1b92e70c914c9127b83315dbb67f479b0a98a7e32f6405cae91daec7c4542b99ac8362fede181246755b5826b35aa206d2e737dbef7f8eb85d7b76f51608d1366d010f5b726cda02255cec96cb895777779ffcd547977d8e761728670434a526f9a93b41be43a338778badd6a85381726ec2ec2b3490d18c0c17a35422bc5dfd0e9161ba600e50457363fc7ad4d1f185c69f7ff481ff8e08b82302549f69beb9e69cb3cfb89c19d8f791f8f5814bd0e59a31ea549fa34a6be92efe30a2d7cac2dda68e2fb48f5b0aed0a642351fd2d479a9bf57a8def66cca8a26b059aa50382018bb869bf1c757ee6a67dcbdabdecd3b483c2f3b2edafc0b34290157a3c56b75de99e9599edac4c66666b8cac2ce6fdb1ceca60de63b0248ced7f7b56f5eee16db3745cfcd4da92182cd9b7acb521d79096f9f198cdb62f73c4653e576482f4fbf06c8daaac3e47acddf6f24909f4b665ab1779ac1dc9523d65e9dcdddd64ed606aec67152659476eda5b56a0dc0b133fdbf675fe6e569f231f9db93d86d4b666f5332bbbff32ab950ccda883eae12558a08eb131a0b7e9471f16b0638ce152471f2ee37f8fdf5317144da97d5fbb99ff561f9f23232239a3497124dde555c5d0ce6300d8f659575c5681722c2ddb7ee82c13e8730c725e298e636dd731688fb497e8b16fd7d187eba64fea05affa1c79ac05d3e126c5a1b00aa4dbf6665b4abd78d1d4802107438ea686b57687666531a5e6c0b54427f9a138f78774b6c6c6053db24dbb9ae4869a8496a4c685ffcecb33bc61fbdb325f9c0bc1cfb67fc99fb08612a23895daf89be208c3aea30cbb8e43760d43ecedfa1efb0e745c48e821385d8ec7c04d6d9ee65a9dc45fef0a8b3ee917b896082708f4501bfb4e923b4709f4597d74748b0c43a46cfb75088ee2a09e6ed9f58e5c566118b235f6fd537f561f2d5b7c172b300c09b1eb5b27bb7e856168db28bb7eaa3c2b0cb86d5fbc4186dc3e3fba65f7d9dcaca832ef4c6f5fe000e0291713fd73e4a99fed22151a55c962ca92025551953ebd231f9d9b51b4ea61fea43a05f0e814b0ab3e3a2a3cdb7a0c45a4a6e348d37d56a0dccc0cf449a19881b6068ad9a61e336531262c541653eed46c8d7d180d4659056d8cbd43731d51056ddbaf40398a53daf6593a2bb32cddc9d26d7b7eb65d7535d8a8036e0f461d5005f31468074356209dadb1af222b9091ad09758875f4714bd2ebb0a20d300eb9597f8ce272c273cf9efd753c8fa11e488722e97607ca798ca43b65e4b17ce4b1d42e4556a02915a84a053272b3021db909b4ab40392374287ecc9b5ebf3ca53bf2bb602cdb7ffc2c83ed8fb7d8fe2bd23f86f4579152b67feec9318af06d5c7a79defffe449a484dbe90e7bf6a6cb13cb1947dd21b797eb35dbf449ea34d05186edd5284d3cfae7f7eb60fe70f24956e28da132aa5828959c9b05a33325c3ee3c992c6abd2d4e0c0acb1d1c10d1b00e0a03097eaa3e379ecac40b9ead3b3329c1c0f0f0f0c393a8f519f1def8ac77cb478acf2788c16f9f47c66f8c9d519826c5b99d8679d61761b4114fbac331c01ca55a0291ec334d836c9adeed083db1e39cfb847ae87d12d9321e042c0b90bee1fc618e310723433095d4e1c6377d1ddd5449fe0adb55a960e2bf468dbf541f7b18416ea46cdca121cda758cb2ab639142eb3ff104152a565881719887b5948ca2e06f7b89711f2851caaf6714073fede5f2d443ea8cdad8c721c647251cc509c1a31d8643614df3c208e9ebec80f7a5be32ac798dfd1ad6852ecad8f69411d65ccf20659ffa4a6ddb9f8135748f54b92bdb3e26551f28a17d66877514e1b46970d4c6fe074968fc1dcc284efd2a6ed867abb76d07b31c3768fff375dbbeee8f8e6870a72ab7ed5f5ca35663a8466d9f76073c2342facae16404fa5cadcc5babfd99bf01bbe9418013506800dd3a9cd8429f58f7bd153f92cb7f9f49f19263a923a74facd3f1324f12fac4ba7de4b173b5f3d889ab605dfeb03c53fbc4f74be589b76c5beac0f2cc41b6bd4fb3cfaee2b1bc9aa147fbbe0db77d5616faad9518569754d3a7ded80aa694527aadb5368f3a3f56617f83e06a754b6a2d058f7c5fad3b28c1f6fb6add41c957bf9c960f2495beaf5622b552582285e2f7d54a44a463257fcc35067b7b14b9d8922f2ac325cc7564f15bc96890447172988619643842a44ffdb9e62a4042ced5ae2420f409427112f8f47b509cefe97300236548f84fbb71f9043f89026e6144a5ecd8f403fa6d4bfffdd2bb607affd6014e9ffa1450af7a973f6badd6ac4c55ba606bfc05f5e189a4392892e684d44dba65229d3ed326937ea70909e1fe1ec5df8982581b9091c7288dc811dbdf44d24ea4c8f6f7223a2dfd29fda8079243a2b9e93d5880d91aff5379636b9ee6b8cdd69c4aaf7900fc698e07f9ac65446b5304fa96a4b3e2ced53e6bed0422c476e114a24aa7d1d2850843e3a7a412ac3f2a50a29dcb96ad5585dcf4afb9e9df22a27fbb0e689f8e829f404aa24f9a43f168474511d2d7699aedfce1ab47bff46854fed37a4071e4a77f002aa3d403aa6d1427c7ce0fa338dfce5bec6c4596429fec0c820e180758e8aa4d8f9d2f2f8ff9b77250b8dfb2e50924d88dadc9ff91a69bf96df982ed5c29ceca34ab6ebf08a995511dd2d7295231fc7b2ffda1046b4235212374064171832dec1509e2b641890d4a7c28c424fda19d795def58c20536e94be4296ed204483a0545bb0945838e25a4b5572a8160f84273e8695eb7d8332ebdf657fa1cbe25bf27e5b7af4915d8df7f4fbf1c20b903d79d0a2c802001cf56adb5466efaea4d0a8651e821fa869d4f907bac0c2c29ada9df43734f8e9babdc137ea41697d0b5d481e0bfce02f65cf9675bf630f36cbfb55ef086a05b6b85f6796357938308f8724029f4898d76a5426bfcadd05be02c8e04bf91956110d47a6574710e0137079799c7e7f236486fbd29c8a59b8dbf9473d2dbdfdd0cea0eba2f6f9b86f4a94baf3d76a341ed02d32fa4cb0dcbb735a5c73aa5af2adc94a00122415278360645b86fa94862206f5c4e80de1ec2eb24d7421281f4296eb7a4ff4ccda2eea0bb6ad92626fad4f63589a400b9bf3fbf92247e6f2959cbf3fb48ba417b4378effdb1a31ad421e076efbd9706489fd4685b5dad43b3baa3967509c561df96b5d684c8b665fdf15aa321aab56a493bbf3563af3f75472d25406fc581a6cf7afb7eecedc24c2bab3ce2036ccd7d0daef4fd616b2e127dd69bf81db9ac005e73ff0a4db9b2effd6c56763fda0f9937186edf7b8df6fd74fbdef26e7a795084a16b075da76c9af320ac958ae605c2d0e5449fafdd44535ae3729212ddf4ead45a7a03d7cd7573dd5c37d7cd7573dd5c37d7cd7573dd5cb75a6badd5d64a29a594d22db0b5d65a6b79b8895ff6cdc620d01a7c436d30286abb9a7159e9f1bf3cf672932491da9ae48d9a73ced9b1cdb95cb98979dcc42d58ab4278cb3d41dcc49927f3f06c8ccbb3bb8290de5b5f98980185a443e88aa26de88f97b4802dbd14e1b4ef4e8490bece1dba9ddf52faf7de7befa5f75a6badb556948562898dc2325b71df7baf8cb6f39f62ecc80b89648add406b72ecc7c6121a3605666465e1e787e960472e133f3fec8ac76057dccc9f5f2461470e33b2301e4c8b9bd9ddddc28cdca4f77bf88b97309d9b39079b4213c5cd7b2f0d8e268a0d9c3e69686e345168701eab3b976ef75e7ac5bf7ffff64a7fef2892d4d6dc0fcfd26de79df3b3c2d83983ac25370c550e1b5959ebc76bf267ddfad91983276bc9ce5fa545fa73c60d6cd4a84da6b955a1b9b999ff0325f41780216a93ff8324740732ece0a138fef93bd8edfca5f2bc5bc8b0f3d9c1cecb1d3cdf9fb0dcce0fcbc1a61cedd2e70fc010c509dd468de2903e3fcd6de70773ceb1dacea53f633f3b3fa9a64f706752499ef647eed0b9d4245fca479d93b5a3cec9ea6c636d3a9260238b46bdb88ce127863d4f9de088fa10f51fea4554b699743da5dc7e58ddb5027d350e1ae6635a5bf5f8ed8ec446fe3b34f7ac22c19bf3a8137e7e9713adbbcfc318638ceff75fc7ffc8f39ba98079df726c42909b26d0dcb4e3f89574d1a7a70a6d89d51369e1cbe8f2e358ed98e3891669a8f2dcc06ca3dee544f34ecc73cf99971245318bd9e78acf4e4b6fac3e5674f8a748bb2a609e094126d45e483dbad0b67d138a6aae1d4c3b6a639d6c3bb4833e65662e9cfe175a29ac1ee6614a0eb4fc572fa38279a195828a032d2f91b05ef531af7a9a03132343561f5600ec48cb912d122a4fab84cab3ebf64d8389d620a857abbf30d712da59e44ecd03605f06019e0312d93ce642780cb37431774b2e05985795d567676b5250fd4a668689d8dc2422849b7687a6f397d3a3f18ce2d8f699b209c9cca2f85cb93243ac90294263d5e7889ad6b44b1b27d0a76977ff44e1b6adba7dae76aa4a714e3bdf6d6efa334d80bbf25c4ae893a533ed4c57bcc65691e6af446a14e712a1819a7686db35ad847e1a646617d50ac2d2b1742c1d4b7753e4897395c8d0d90ab22d912495c86ddbcf97b563f13c76595a58bd168ffd5690564fcba755c463a9d64feb482bc863ad0b34c528572357a3e745eba4300a65f2a026a630c6d5839a139d3d7b8c7bbe37ef644f619407b50e8cb67d2b1af515a84671dc666530f5e680cb419777ed3b9d469d70d314119bf8397b2944a7a2ecd03c669becd0eae803b5eb101c0e27ce199db48a28588aeec4ba7dd61c74dbfaad5e6f6da5b0a71c3b908eee29a870d433d38ec76ddc322e2bd07467fba8f70f51a4cc8f4c111f7ddf6566324e43cfe104ef78a9ef85413c36f6f814f1d828ce70a4ce10e4b116b62f923b42e10e6d0b21f1ad7e115d523f86a7173f45ee0851374deebb02f14e1eb76dab780cf5faa53c531be5529e15e8ca589e1f966705d2b22deac5f2ac405b76683a8fe1a73976a7e6260a45ea94ae55a01c2ebf7c79dc62bc1dc3736269c1c2c20223f5a851c725f595ece1ae24b4c8da91992d61e4b2edcbccec0b11975478dbe3a7bec8ec963e5a6c5bdaeea3a33e57509909342f0a2609f6d65a4b223d1541f08a9f982deee25ad15a2bfe0d631194d2b1883a2e6175a1eb5f4ae9856daa0a816f5adaf4b429fd7b161dd1760b5e37def553332f11db9b022fc662fe28a55483a452fe446b2dd5f7de7b29a525916492a9e24dcdbc4471d4b1a538d6b3e5dbb431c6263b0ec15834d028d4ad621436a1eb62124f17e78c743be76961c686132aa542046abb940a673b83c003dccc329b59933ea954aa0b133313f6ac4f1d7fe07030312f2753cc0aa7050e8763c1aec7c5155340d1dbf576bd5deded7a4c7a2b1956bed8f6f008d95e47b83d749904559c8705d68709ae35c3e3a6763323a3148a25ec908f33aae0bd6196a830758c302a1ce7b89309e59ae1eeee331e870587c3e15890693d2eae98028a1ead47ebd17ab45e96de93382c381c0ec702177a5c5c310514bd5eafd7ebf57abd2c3db2bcaad42d69dc1c0e87f3b7e16b4fe335e3e6eaf51a75f0bf2e4d8d8b2d09fc72cffa806455812672d3eb14eb537754291487ff51af8af3b0c00ac165c1d1a06054b61942c4009d9af87e16ebae5589c537e7312ece17831fbe994422914afc138a2fb52ec9f87edff75d9c67172fa95549ce39bf2a0d35714d02b625a9896918e09273ce58b060b93f4a6a557231be24f0cb405c4c02bf8cc51583e501bfa7914c43325e646c923e74ecb482d605dca41301dcecb19b796d93ced6b80c18aeb33a5bea74b92496461f4ef57612f62a206ef2138a2ff7852b8e45bc0f954251f4a1b0e4b8c9e822be8438f86b3561fa65e0aac260bbc93496f0b2337611e238afa24d251d3098e9f494b44d6248e280db67a85949b83f3fff807d7fa778b5d69a52adc0e3f178aa4a65f50709f3c995cc4f0946b0b25259714d6a105549051a419cf342181a53a9b5d6fa1bd1a6d15c89322f33eadc9761b5eabd31715ea5e2700d82e09120f72a7547bdc1c96ae76060cbfac363a54e28175bf2cc48023e785715d40f9ae00b15374522080e810f92273e478624a98190d9597b4aa8d842ac500a6ae881061f94e8b959a15ddfdaecd00f43f6696f3e39a725b239d59fd6c856b1bb1f8ef66979560bcc9f760bcfaeb7c767d7bfb3fb6343c13e2fed06ed7a6dbbfe7987ae931fb06c19995f8d3a32ab8f197556313fe4b0631e66d4898179d5a803a37adac4567d6ad451a502804a027563a3503d106d940f306c540f347a5424d4e4eee0c2dce21e537bfc3bf240c51e950c51c4434f2d2a4ad283a6425bf0da2412922c9b54630249d103a008090df9f1a893414841131b833665b36d5017db16a1e0886d534064dba743a60c10998a5202567fa56f502d9739e713740e62e7ff2bb918ac288981a5282915fbbcb18307f6dde1887d5f03fdecfb2b5a04c464dfa22023fbbe1e756e4d13b5169d60c9cef95f469d6c83c7459a92293b3f38c6ceef32ea647d7327dca4d061071bfca04382022fa4f0417c6ab3d2f2620d6b9f33263042071af62dd261b72f6dc8be3ffee78c23d65214260822072af6fdf0899b5338fb9cf162e7bff908d1ceaf8b7200ca363e40a194000436250822afdeabc430836cdf079dc00104fbfea7a5100125ba81c9be354536b6cfd4ce57ecfc9906538a6e08b273cd39d32e827a18e20a1229441ec8c95a76ce39e79c4fd03f3becfb64df209a0a233bbf8e1abb023082059844550be9ebb4bc7d29ed41da2fb2d4295596b4573b6b0de751fce6de13aad9845a506a96c74dbd7516da77cbfff42dfba60792d3f24f7dcb5a5ba2907a54a557d8aa10116183219838caf1717bc9810bf459bfd63c768a4236213c565b0748fde95348952d7cfa145ab83c41f5a8a739a9ff6a2ad267a489f4590b7fea5bf951f84fdfca65eb00a7d39b3ee712f5a97fc1f4a70792c3cae96aab42291245ae48176c0ff3655359a5425db0b25aa34fa49c7a97c25383a0d6ab1eee51b9350995599bfeb03ca9ae549e940aa93ce913607952295f79d227b93c41c0e56992a67dd69a267d466deefb136bb3321f4229d5bd94a74542c5a53ccd27a4ac2c08a5929aa4f2b42f205fc667a0977ed3592fed919bf73998a2dd2d6f7497293ed2a90225a2a34e09044190047e89f414a0447b02e067cb83c7a9e3f59a9949a5ec0d2abb215299486b6cac7eacf4f4edae64b616342905a969bf528b6db9ba7ff72d530fbbe16aadb5d65a6badd569a55ea97984aeef454cf19283299a7e85e930cd92a83dba4475944af8277d824aa14fc03f41d8d4b4260fa8ac46c0ca3ca0356e75d58819d25dc97720d4256876d7126654a7703025a713ebc5e1bfbc9a85e26831f1ae6d5fa17d6bd4e6f6dcbc5fb5f02a8fd6a35b73754a3562dd3fe17f95737feb5af9ea802598e4235397777179ea7b7f750a6236bb623bd9b687db3e31c563f67ba88ddfa6e4a0e89aab46358a9bb87a9381ca60b63a44717a288e13f4041476c3109e5fddea2d9f35f7e59acbb99c29477172d41faa4d9bb8e2886dcbb3eab6bfa88d3fcccaea13b4c6ff660beac4f69a0b43fbb06f98e6c90656e1dac6c35f64f7493a85126d37b9834768ff13f6a6997bdd622544a3e0af6f1427c7be4f00978132d267bdaf066d7d7f5ab250f7b9da970023b8a957d4e65af308ad539746c46c467368289eed5f7fb6a5449652fc97b4807df5e850f451b70e5d54b47ddfe1d75d77585b7555dcf47a6b6e9ade82a26911ff99a2ed5723d2fb579dc7783cd622a1fe07bb3e90edef413c26b3fdbde747a592e35bb4b8d1151ca6a8b95fd57ce631d1548260ca4d56165a0a116cfb33bf4aa257429c4671824e348a93633bca96a7dbb6dfab89f4e97ced42edb1b686f6c22dbd664b0fa2bdf0491880eff8fda3d9da4aeb4b89f6579e404012cdca44afb1f6dddaf0f16842f8b9f4211dc7f20422c41ec956a16aa8644df74539eb188900004010003315002028140c078482d1683049e33c997b14800c74923e7a5a361546931cc7711c0421638c21861843083088c80c0d1151100010d037a6ac0e00ce389c80d8af25de48408dd6d93cca2448dc2f1af12387edc5ef618981a2d6c2ae7dfeea3b32496cb4635c554306c80819734bc9114c4aadcc3a6c24c1008e25b40785d895674c135a1c721d41311a4623f008f6fc4155bf74663de7436d0a91e398501378dd30a857cebd422cb5631338cd198812e6326737afbbd611a9ea2266258209893be30815bb9b2569d87e03236a9508254824964f4092a4aa9bb83aaac4bace1fc8855338374392035617ad1c125d1be2fb6a62b956ab668b0285e43602dcd45e557030620fcdc0b7cc86402dee2d2fc7d92f0f92698929aedcd96cdaea79de14311d3a88e1d0db86160e560a6492882bda1bf0fb6e2880b8a14e754c84d4a3ba5bfcc83984c3e64224be8009c3b865d14b18c6a75c03c0e851f811597cf4e2f387d6cede61d3c97c656ed5c92dfb65da67b56ced785ae4f49ef60f9195ddbb09626bce2c44047f613c544c83f9227b9202e8ed3eef8d9b84464786aa458372b90c44a8749d7a70463f4f5918e04b839d6a7fca8f214315c001ab8c5d47928fe090049ab9e32977f11244b097da229e629f930342bfe6aab6b87c591205b8ecfa5b8b1954865a52a66c907ebc0430c3fa2fe4f21e9ac0428f0d66604f2bc6880162e3cdbff6d3de962db99ccf8af4de40ff5899a1d35f1ff0d022abfe780ff99b23bc748d46ffccfb99d27345debe6811cc2c65de1022ff995bb509233e5904692f1cf7863bdbb5bddd703c75196cd3c89e132b15938a90b1b2029b32b5315f8cf196c5547da0cd25671b860a220fe5e7e725a79c681b3fdfba832669f61b15f3b7a4f2d089f52d62dbc9bc78707727456e0393b71cca52620d77b5a8e4eabc7dec75481ce3afc88568f7c965dd6b1ad5496bfe3d5d06b93bc425a2cbb3a939bb965f38d0bca3d113f8c76bed7b5015fedd5e5f25955520a749e58a7c92410205f961f8c4e588fb32e530dbc3958533cee19d8440e77c6c0ae7cecb9a72618040ca0daa5b1aa0966066ec981b229a0ccefc1447e7a2be327abf7c1f3c06e0ae223be7162d2c4c9c00a27c2c5a41e73669c6df74a14be2c0e8f054a35b0ced6c8c7430db7524290ae7e6181d4b2544109219b8bac805bc91e180630f47744983b36c2e22b7af12a68802451675175cd30be47c11284c21fe8270e9e4682b9ebe373d30b872ec1777ee09e497fe4d11344e658444a33365b9a95cee3783fd6e39b7e80507192d6c975c7139b347a3a519c72ceb9a62da3edbe35843c0a0b96158b495b1e30e52b5457d5593a120d2fbee612a4606226b8dc7d4b511cc9894bdc51359a15bf5c55ab71d29b51bc90f2270d7722ccec8158797d4af5e267a00d08b894465caa8ce236d718b2c32dc6e65e78302bc7ac7e3302e5ad813ae34e55d7a816b95e2820942a9178e7d50d66f648c2c2ca34cdf259aa7067820b27f008812b2f2a90313da47c35cd576a77e52bcd52d6be80f0e8e59dfe4250d714f1e3c5b65333ef842b5884379d9c5837bced99a2db8e404436e11338cb6fa5edc1291b272cc38d7de4241461db4e3b8eb1365c5b404093de955ec78c064d25ab6f19d7dc061d3c8931cf7c08cc62ded67d2967bfdf9f3045cd49c7cdaaee063bd9d8e71b61de80077e11bb615a7bd7b5ed74ee9b43386b2aa739d73097e1f1a3e576358e962996fe3a0a6c8bba58ebd1f326b0a7a13b8fec19b4d9957e6557f082aa66ff1eca1b15e1dc2153f83650fced798a7909e4cc9facbea05e10abfebe400bec413ccc8c80e9e43825486472433f8ea263ed66cf4b2a75e7ab057cc3f0dcb5db360763b817acce92c7dd3426270872f04b0f3cf1b8ca5117dad0e4e1c4420aac73dee668574cd24acd7008f0b0a7087e6fa389ef5e190ebd2aea9c3a6de2669b35908f6266420cb215bb09e93c035e13b0306b63d796a9ab6d2f469760dee09eb369f75783ecca669b8470270f2f18101fa928905957abb426bd50eee187f7e09966b066d92ee144a2be71813ab5017b0e2040b97942cb9d92de224e71a862f320f5f4b3e65e882815b0588d58232ea226598bac54fc93938e3bb52cffb6250069e4b69adc1181a31125b6af522db12f94baeb3aee75cb20860b29d96bdf4d006931bc02a77312449230d8fdc4254fbfe9050e9aa4412d62b477f2e2fdadf79b821b90041c6250af362f82654e7c54f97475665e4a1aa6ff82fc314ea34ec9a10b814b125a445a0dc7645b16dbe36ba443c67b90637217ac5d488ae721b0c1a0e351a8c561ca701a97f936111614c5357e4cc0479e8d11f33fbf107666eec7ad63dfbc4ca611aa3c46e8be2f58bb2bef6fa63db3618225cd57a443c4225dc7b3b7dfe1eb494ed6d9bc892ff659174d8caa7ba42d9a649093bc1a76c4f6affffc2bd0c0f08664ceb057ce3331d5776b47d06f95682cfe3b8828510865d18ffefeff5766c19f0ef31808efef1d69a3bff0991f416aaadd8b8118a64b48038af5e5dd0550c6d493456b905091252d7dba3d350dcf8574a1fb068578e106f054690e92c127417162e50c9e554b1c9b55161c9afafd195d549b74b38ee72ad0bb46a72b43855d374ed4e5520492f20fa7234d44768429f2c94a8311accae148b8e9fd766d08745880a65265616dc41b14c341223aad687361f5f8fc17aaf86304e7807ac7d4c40bff94d3ef0685f77e9122b13bffbe5af2344c48c84e8cf4d668fb6c9c234343706be9754a407ecd9688b8d17d751a3a283e59b98cd5daf7f165546daa782c1e1d19641cbb95136833613431e33d0fc935814b5387c29efec15fe716da82736622efd9993cadfb0074333f28de6681adcdf557ed848a9b3d6546f4174f8df82ed90c1272211f589d3b95b4059ceb4e8b90184aa78bbb46b045f36db0300e676726959688ba66c05ea2b099b110ddf58590c4ab3c46e2324d91853ce4ec62d9b438f09470b0b6a502d40d6ae1b68346463daec9853ad54e3c2648374c4795af419db1c4ab2bd25a18eaa8464ad87f8a08443a21956caca5fe29e7122b308404802c9d1894a02adbd99baed4b9372ddcbe35c2da4fbf502b12602f6b8911476917a06de620af90970b9dbdfa38f374f100d64980c04dac4238e57bfeb0a270ee9565c15a09d5b2704b32c27b6cd3c1825669eda2f53c47a14d9344dee4e10ca2bb654089870d8159ad029f7964a428bbeba3d54fc423749864d3c977b884932e8f06f957b01018584ffdacab36f4e721073ef90b953dcad569ded1ee3d35ed856e8adb35b774c22b66d941c99ee80a46d4dc87f22aadceb7197079872efa3e9bd2d0b63ea575e5903a008186e41c8301ff79a11a7ce0d3f59871f8dfa832865d496b012bd56cb5aad80d88d82cf6aa848d1afc1e570cb2b7672a93dd5db0ec383f58d909ff6bb9622a6a2314a7130e24c57f825fff479f2fb688518a15a710d7d5b7a8174b0309c2f71eabdb5befc7301d6aece70fd2824f5c60b3a699e3e4bea2d1d37d3878442760a61ea1d560a2bf4d45b039b1804056cfa9bb4727424c79b669cf91ca4a8b7c00897a95c3c8320102455ea4504fccc9d7a634bebdd33f1e5a1a9775457baa8f9b5e3931fa6a12a364dbd07ab064472f85e9b7ad983ae23cd1e927b264adeea247f6e3618ed0d294cf8587266e5957eedcd66cc6b9de6d7957fa02aa2de90eb51f552706c211b2db861380986f12f5b07c9f7b1dc4aedfa22f5cc52db43e1765d2012301769286660d121565633830f859e46e9236b893ba33c38ed3757a9c0d133486e6db94fc569398825655b95e5357a014c6f31060c496a085631f25515c313f8749464478ed01f3d9910b5c6fde6659ddea8f802f77558f0346d12a43820cb03558dd240dde74bb542c14824b571206f58e93fc5ae32553e0eb13cb7fda62ebc54adecabbbc6ca76be5a387a4d109f250403056e615dd37a261d01af8c75b89e3c75f29bbcb84e720ea7676085a74fd893afe3debca9c8001d7ee7d298c64ccd1ab025fc5f090921d346e184f3cd94846412325a6adaa81767d305a81eb21448565a43ad97fd6021457db65f0e67d6016af7803c66cbd29a7bdc60db0bb2c87be0fe43f773a23debc5d2c920b3e9a2a2662f9c50c57acd48773ab6709582376cb29414cb2b8001164359d92d4ed28870bbeca4889046c95868763902b9dd4183f85833e67432e9e78ed044a995b52cc896d676c75244f24cf5cb06b4f92f271e8996f1db9b059017dd5d1ddda74da1864d67a17c400eee201b16e71bc6db76ac9ecbfaab5f9fa1356a35ee92710ebfd96aa51244435f002116a3860fc53a3beb339cb167fad2fdfb217fad647c54d3b5aac8d4b2bd3738e94852052d190046f3b5f094adcd61d32d2179e1049c1750f1427fd1787b9adeddfa94b9dfe1336be44788ac58b7a976c38b4ec0f5afd540acc55c84e51c77dc314f9e96809d6182ac7be7c0201696f0670e291c317d60df321b027e299591c7f590428887f85d7be7645a1116d480be7cb8edfa4aac5417c896cc54737e52d6d913574acc2a2359d1269e848fd298b639184e5ab319d6c67e7864e17acbb735ec15618e6a906d4195c00b477f51a1bc9229f8b59c36b454e29d84e76cae2dec6249710d00299b594b05b4d1677cbdb79164ffb9c3e24f888e465c4e7e62916b9d1efdd66ddd14c4f0ac5787e1bd7eeea8060693e39b716d2e6bc2812619acc763a94ed33d9a3107ffdf847e8ac58eab3a8343e460b2a54a6d5df95f6c4ca02e457e719829d238042d954b9d1d1247bcbf3e2beec99603521f73ca0aea7044bdd202722a7a65032830ad778c043aee467ddfe3b765eef871027994aea99b669d81211f0eadbea0c2400810d43d8fd57c4ad63360f7c62db28746c63b8288f091d18c76cd6ab85b0304f96e81171a6bdd6817977b3db48b2c810264c230dd8f30fb9d7ad0e731a7bbe7617a04f626656743a2b3d283c196a5df70f978521a1d72596fe2ee2e4143ade15e14967aef70a89e81cce482b1aee93ec6bca3c4cbb4fe8303a7191440f706a011c59042dd3072f34ab81b8a17ad9e40bb7d172c4a8478b87014c6efacafbef5cb19684381c689b60e8173222c0facd4ce259ae1cb416398360117c0e2f1449f86e0e30b60f64707ea35d580c7237d52bf79a0ea420f4240b75a3aa6843ad5eeec18f8fce043a6b253b1292094e208d9ebe6ec5889290aec4f284c360a1481afa25c38c58d02ffe191ade37c8aea6a83508506e92d9c043911cfdf898b63200348d9e34baae168a824e0fe9788f31236d2967e230e49b9a2218c98862e527291f70ffd1995aa1ae76661147c53864383eaab46385368c22a4469b81e304ec7155fb9c6f1c93f404d8eba3175c7885ef8832e81fe8ac27a8d2d791f72b3a8cf020d2d7e8198b1e0c77a5c6193aaf48fa68393b156f279f90289c5ae367bc350a0e936218fe5a90eb99646301e0d71afba7fe92dc6d1066e5054dcaaa48a79a6eacfd09d50c43154dddcd9d035374a06c91e7813f4b4da2deaa604c2d1170df6b8921206136bf6c16de81442beb668b0fd68625a97f37e24ab12a7f2a1af300e6c67a74620221020c95ba203efef5e68567e44bdcad23c4af504027c150033b9340bac1499346c9b847bbc61ee967b536c21701e239d296cc74dbede856d4e0f052d8bad18cdc2a83d1cffc326d1467bcb2d64c7b81e37b66c47d52f5261795f8aa9389279f514fde1ffaeb7f20fa06c72f293e5e1438ce088f9254fd104517eb448dbc22a4d73e1e2ab1405d386a941e82100f2a23ead060ec09dc44721df2ebd6c040818c65154e9c909197e00f6967b90a5f3f732990ba2d6952a4da27ba7c8a38bafcd0a914a721ea80dd33c07a128c2de5d4137633d4833ab927bd65fcaa9701eb420395f44b196886e5a9f4c408674c93854cc0fd2fa8ade5f27d501aaeb5c0e5a328dd30d199a820935e624a03a1fd38d72954a4c8573d7bd10818c54b9429b778bc1ee5ba634e26e04d7da1015cdc4e1da57e7eb7e06a3835d62df48359465f927c02083e6e422d369a29457ab2ae5fdf0efbfeb7e95024b18729f5e006c43c84d76a1710746fe8b75b28dc44c0793b288cb1b3e81e577801260b51f9edcd937ac073c85cbb87fa158791c038fa2f39720fd914f7e87414ed151272760f9e523c1171c0dfc50737dff0777369e3e4f77561f90ca97132cb7777c30198514fcd734018e8cf7442f012591803baad182770530ddd3bf1d0f9a2acd006323da393837524a5e02cf5ad952236cc825c5f458096ca8e6a6c2cf87990422dad39fa11fc1c76d205a293c8b064aa3e987668a3ac8c47069be50982741ce6f6a2683dba550c5e0b1886a11099f82c8cde1d3a4a17d080b401cb224334ae64f11bd0199c27806ab52d62d51de2f0cedac8863d1cd406c1a6f6a82fa10f64846dbec71117cc4513d0ce0c78c1a45bcd0b93b788355b030b9b56bbcb82b69041f73b9000151afa625f1902ffeb7e2e23274c1c4d2295c328d56e589536b54802e629026bb3b499df2e6fe958ab4e4ac012660c11225ef031b7f40befe3b13d5479aec02cf863d56182a182c7345e50803b05e840dcf03b8d135469f43c7b7014000083aa7de9ea236135fd9c46930953017cfcdc44efd1948ec1ea7741ca50cff6ac3384a16236a1af41527f26a3ae7631b44eab84b0191e14c8b49e8f34f15b8b828de7a097d567b98a602082cbacc22fd90a0619d46ddabbe33fc59da01a02eb12a0ae102e0a20ba993905c8444049e6ddd2d1e6c8d147e35d8f8e33ed87489b5b5ed280732a139b3cb7932bc32e07dcf8306383af8cf1747c55db0a90575d34b14325f8099220b2a9e43e11464230dc8fbb079730a35160b7b82e4199e158f6c09e27f82685e52788256c3e67bd2be185e56c60c83195dcd180620c5a7b7c94e521d2907e8fed840ccb695512dee894ce49f7bebaac2dece3e08ae80420205655bcc62fe5c68620c438b7225bba9b284b769180565a93c7389140257b5f7658338f17e85bfeb0805313c86a76c0023edfeb5874752834f04c022e188dfdc2604d76ca164b518eb4a09be17af9025a998190c37326b363c76d14902472515536b0d70b2bfa58832bb496dadb97b7f6c991d0e2ae049bfe52b37e3a4dc0ac8cd17b93eab5ddc65b1fcc092845bc8d41ccc59168aa03eaff56fa2e5e2b90cb488e9f8bed64b85225996242929c4d8b02fc515b69c776d2062049447d7c42cc9f0f3b28c46c6120d4c18a21945f2a7b21f9291802aa535a9b314715d0b189151a02353ee2bc78dd13a09a803d71bb2b6c1fbb0c422f4bdec3ace652709f4b52f6c2d804fe9934ec4caea0b88222ac1d1d9349a6ffa2b11a9c7ee92d5ed10a3f508317f335d58391a4827b13c475c87a91ff1004820d3b759d8f776de43c72e66899fd8919f9fdc0ac3e64fac13cf611b8c611d08051a74517b33649189af3bcb86884e0d20eee99e4fc78fa0b13c9e1db90e611cdf9dd99fa0281dc2a8a42cc248fe2a6c81c7b7830fb175c4ec004bd86b04719e3e28a7c651a870b975266c04156052aa78a8768d5d91dff5a3056f0eeb4e76a84e12bc729368c3793c924c99e7c422d59ae6f657a36671d41bb13a1e1c5dbb973e431afbd33a67932aa086b699f25ed4f3d2960586353e16dcde82caacb4ab2bb122dc1056c04ad9fa9afd6100b54a2a70799fd1ef5541679453115427d98e2e4151260c0d4f8f8b78e3971b61c8df8705c4a96ca57c329ed79878cfe21a8d2e78094d7c7e904b18dd6a0ec7dcec2972ff00b5117590c6d8fd1b6503e03208149397326fa0945127b7ed08412eb47926a75f40919650c1396464a0d833028ff4a73cc7b831a03dc6cf15b7872acde609284b88105b0f4ff732aa5b2997936e70fe37887139d9f94969a5afa865f12a26ddea14790f6c553cee62bcef16820dc0b08492b828c5f8d70db4a924a82922a4a902f0d3ecc6aa76634993d6bc900bb7081bd182d30250bdaec8314f5b489cc2c03372413d5ce9c1156299be30440795a25bd01873af6b72c2cb418ed29e2b9a62d2d1818dbaa2fb54346a074056d7b9aa3138f4acae5f199461e6bc2b1852168759fc408c206a99391aad25b4a0d1d89f0b884c9075a3ae44de0dee09cb5ef73755d67ba58b0e28564ee529cf2fcccae9ca84ea7ab5ba2d25d0f55c1e570f19b58ae2922e139713549a6f4b12091340905b69d603f515a3331855faf770e306ad31b456814bc4aa2fb7fc86f3fdc63590d334f3678cf45cd7dbff02ed842b38941f851525aa99713c4139b313850860cb96c29e60f5e253cf8080c019b0af96a16daaa8ccae962b566e1fb6506589c11edc4c440defb45d8c50a9506c46a61dbf3b000cbf9fe528d62d1fa2cb35d6845fc394406436066240afc735698fc1f27804ad041eae32a5f68e1ce7be0bac91d197b8179a87a354eb927ede33a8f1fb1ae93108cf203fd1d75e43e3983a96000a4e6d12cda967f14cf84138569f3fcdbdfb810d00e252054d368eb379afb51e670d3c0861c6fb53288384f0013da5156d1644ca3e4caf76e4d9fd27f44724128fd510dd771aed377b8cd24076d797d6977d7069f490c62a4fe283507dfe7e60ef47caa000fd9745af63f978490445353ac96ebbbad35e914d5c470ef61e1574730d5f0738808215ff48792735735527aee428ed9110bccdb9241831cd7180f7fa3d26cf3f58e4a3114e0e04ffc4ec8fac616e1582c99681795969f856a9605d632d2aceae08de95b446ad59acd1d0462968a1996c4849bc0244d9bd237f22792529d738cdb442c3d2bdc9033e7d397669225680d06a5c2e159358e7a3e5ac0dc10f6c3136d4af970fadb216bd620b9053a51365f9bc41fc1a96ca3ea37a67e36bd641c334c11c1384fbab00bbd0f120b8d64c629a203157922eb556ed753a4bc928d90c07579c1777b6ed1ff476fda84703d6151e64cb12e0908987376b29a6a36c59e9ee88d7dbf387ccf61c189929362c425a39663b9938044077648f8e8704e26e3ec3d82301dd964c3a072fbbee894108f97af6fb50c4aa923be449930bbc59aa044e5d6b8495ea36d8bca57a38197cf673b520559a5b55a1ae2fc6486c3105371c418a1311f092531b6a937f2ab26758a0359493c80642159e7e0576f64722d26d404ced0583e05939f026b15f5a32c5eab22078318b0af4695f46d6887994e31e340dd04beec9b3bacda4826135460e251aa2c3c49d592419a21f540e4922b273d3b0c4f803e6aec24a1fc3627cf6a8e286077bb5e8b4d6ed25b051009f4a21118796880f44c37ea364453a674473621bf9e4f6857ba044cf10c135a9da9e5b432983b791f7c43f6062ddc6e897c3d650f05028ccaa2a2107559e97317e55b4024f351e6ab555c3ece381ea3fcaef3f5637f77f90e54e6e8f6d93a17c3d79696a353a37d10bc4c4b0b9b08bc75ed142cceebbdd521ee1e9aea446fe27f6d62084f326aca89915727c40f931a91b5e49b54e070b50274f4e53725b69bd45486eaad11c93247642bf692bfc46ea164ecb3d23ecea38a529e5fbb7bfc8ad39b4111466a20304eb19c281e4be3e4bdc1bb7eb3f21e9d162cc1281954a48478d6ad61c5a20d3cdfa4f82f29de474eb07c82f446aee9c7ebe9bd9e5d2c57403d6228a0d5061e017202af5ff3f095e6d669d7bb875270426c2547a7369e70a20464eacb3749fdde8f06b8f079c4d64b23cff407d7f7dc3ff586f8bdd1dfd9922a1e400b297ef4ff607fb9f73a2ddf3e73714908add0c1dc4ee499776f95796aa374ccd5cdaaf070166510b9f958cb67b47fd20516ae95c23bd1e9fc52720094193abce9a663b3da97230d9f33289680e894fbc3d2751d4cac9f9a9cab52b4fd46f060d1fd248193c8c8e7f26ab96470370b7229b2d1b18ba765803dc19d765d86487a1c3003661cb17934d741bab1cef40832c8753b2547c4734c54ceed936060a6524a7c17e9202b4de48827b69c97c9a88901587853e725bd2392dcf4e2e8721e9e2e6d0df7199f4b829fe84ed0bdc0fc795c8b6dea5c98c9af43f774e5459218e7d8202e7f17bb83f5a3cfbdd01843c0a25756c3a3a5ab57d96c9812919f41ddda118a8d4beeed19142194bcaa87718b5582f4aed01dd00dc5c5c56c6f5fcca3cd27c7c1849d26e0279d975a8ddb2531ab8e315dec10543b3b8f8fa279ea545a45f38195ec399ef5d0530877279c917cc545411faad101641b8ce2bc391f6c0813122673a638b5684631c75f3f76daa12608f7dfb849df4a577ac1c6ea8d79f3aac83e9bb34c3b32273a3f7f8981fb773915b8288e2c448eab506f99299daa60054f3a9365e35ff0a37019021c7f57ed06a772671c1236b5cfae8ff4fe5338f24403a6ba844e6ec283ddb65d32eca7e9684d8d7aa522c7280c079380e6979b44272b3d28239795d07c07609fd0b03acc1e2a7d48903b8a19057de59957d3288ab8535646d72f7303c68f31da44ae6ed11a7bb348800a93e9dd72b34231a9df56059db0971bd44fa596709660e5b105f20c8bb5469cb48c6693319e4946bd9d3800bb585288b2da760fc6f913e8d36b22883c05ca5ac4988e089e56f2096e6fd5144905ee5802b3fdbeb45169052b93e95c01d30652f12fa0e2213c32bbde7cb96238e806dd8042e0d73a628389e807380ee4ae88d053341df2f5ee08bb13e23d5cf7311b7e254147dd0eec4200cf5e8d821d38b5100da8fabd0a2883f0f1ed69f9c54bbc358c93691b17f7828db86a47f9361bb10188f0a4b6688119b6f182e619d90dd608d3cc0656ae4911da7afff72d6c4f436d1e8445d839222efbfa99952e6ad2cab7c8a14a63f2e9b574f8795d103df16bfbf9ac979780c107ee956a075c7d700b143cb988916b53941a40b34c9a985876bc086cbdfaf2b14f670be0f0a53b01da7517b28831a86c4a844cca4cd5342dc1ad83399800bfeeb953c58d86f9b81e7f1ddd7b60b184176efc80dbff3f2202ee322db26032189238eead7c109a69793500768fb25d5d215e01800bed0a2e84b5f2bf4730452309b950464af5c039c77bf0f47e4ea01cb5c1f425acdb3e7df81b623bcd3ffd11425d85a9ab5ea6bd8ee16b3a046b9a2771bd01d730af7c567df57a4826493c84a20dd0f8c60f0a0d718e049bc066440095f5a20c4af7bb63d69b10d0299c382872254b5a9c600510850e0febc49c64336e8adbbbbca7fe845128ae8531cc911f19baf1e6bb23c762603a4bc2c4118e62d77c19cd03ce16de80d6c1883deb6340d6882db232f73b7bb2a9481487b8145f8709cecd0ae3ddffbdb4071a459b61b7dbe6f49f2d0805c583c11d696bff0758f0fe657dec7b09fd4e9a749e72f00826ce5dba309295e484bd99dc9442ba9a004f744f0bc321d3ca0901c917fa92e44f71e1ec1db3617920ec929aa49b716a8c951f43e3f1b6e2677eaec0927d702af1c898ec84b470921f0bc238dd5c61e88fd123a22355bec4afb3999314e8eba8ac5e21059f6ef3dd4d21ee87322b94d18be1a048302d59f9de5e490c0063b742b8f5e6e358fe106077efad85f07ff9dece0c8124f06e0086162f843a7b8e26a38acc6fb7f55477587355871174792b32c2101a5b83f441abb011eb0f5b6fd5156981123e91b979847e2396403b93186cddcc7f76fdade62c172ab9af09d38c1c4eb1487082a1e83234557a1a4433739efd3dc5fc2ac8648c8818435fcef26ffab9125e53305222f1216730aaf2dad5ffc16188ba6f0d418660f7ca24217ac6c45216d70fbe20aaab0ec64139d64afaaf1a0cbb629db610bc2e149bd57fb87ae2956ae737dcf1409b8c71e631cb6c8893f03a6403064c04f309b1436d75ae2932124d8c89b1496656acf03a9bcd7bd70c143c732adedcd87b1818e0f267cb04fe0c08d361b0bdf2a1f57c488fd21ee15394c2d76e9f08521b25600a32d69107fa579ec10476ad9e243c971a9325b23074bc9b5f2d5102c12563540458dfed40571c6d78d8b133f3ace04410bd2f641389c0942b890c616acf95f5336a96349e2a8e078e1dbe7be2bb6cba9c089abc044cb7d14b9e63748b3aa1ab6e91c834ce98d3b20c26fa557b4264cb046f0ffe76a1286f27c53ef5c664158cf02d0f2268487c224b250a6a4c58973dff16e64a404708dd6fe5cc06e21ae6495631cd4af389868c866e85cee848e04119011e9bbfd99ebe73554475d016368d3da67cef1bb1b5bb2cbaa9be4f8377d8cc236a1b5ea107eb990be70ea0d59c7def9ec84a8234a2a25cfcd90c4c36512bf8f748f5f3bd5dbbdb0a5a9945e087a133009fc0affa1233795773396866d0265dcb1606c7d4e42be3eb4e07df5d3a85b3ad6cb8efa68d8ed8ebbb31e105e5c428d0f342a719b080dee305a424b03b9cb9a244f371a2a0161ed1268b90dd24753a1095f70e9625c37737f4a3c03d02036633237e4ce3613cbf9d4797b5388a6e66f57323b6c0060bb963ae97264801d4cc35b411da9a7cb9a7a116b4ee2313c7386dc1c0d1e04f7bc14b3fe8522d7cdf797e678e5e5c97f72ab54b8c97a94d6f75c006e5eccc823ab6ccd2b8f4af211b2f586d56f6cac23ad47aa29b5e9b08f63b4535b1b377f568c612987fdea1a903ee4aba892a1b84aaa6b959401e56262a6b00bb3520404ab4a99f61337ba87744b5e4443ca76896c6180a7af9fede99101005d2017e420f341f11e61b462ef6c65fda1d1eecce3f0974ae57b3968ecd3cfe84b0857a8f84dae16af48b9057e506853fba7aa1fd98c66edae9ecf15fa6e5c88c13884374064b9e0e27ce68c0c35776cdf1382d43bceab37721fc846217910d6a2f4d1aa8f26171104590cfdd1c95d58c0ad652f73a02caf408ca33233156d9b49648a211167a55cba1f31d7374d551ce4ed56077fc0c51c5397ba89255741e2b143a618187989d47721ed99dd8178a9bb8faf1212260a706e3527029714824f451b42dd1625d3968e4794a7002808e3a67088f89a41980fcd7d7359724099cedfb2041fecdd45821083761c40db1a952dfbc92faba7287570e1e1c75df5641475054b15831df6e76eff74b509f74e04bb3a0a44fd61123047a275b34408c47ab8a977dbec524aa52a13d396ed5f6b2122f4ac5e592652b17883f543ea85b28deaa8b983ab5f77ce8b702c83226f8ff847653e00da4eddc03b935982b2c3690076c14f8e2dc086af2e6450080a80afbcb86b152bacd50702d2671684b45cdc442d5346105dde075558570efee1568a8ca6c39e72a62a8221e15ecf6257f357df51da5b83760b527b62db679968412b9902cf06830c697ce264c70e703a58bc34a08d8256b0808b90583b35c8d9e151b8a68169fb5f56de332117f2a8316e42d72aeb337d541294252c404ed039fe056eb904aff1260c01838c92e43ef5690012a0de8741d11973761809e8603f506b55d492abfa1071d4c0dea998d48e495841dc2bfa7854373053ece00a8fa780385cf69e07cba348dd835522206765fe2f8ea96c80367a0a27da7171990efb325b96984525f1d5ebc49aaccba347ebc5276d56b3955c780c3fe71a8d19a30c138d2f3de6f2be0db027d1a644af1d7952d4ee4ea270be3c20640300bc43154e303ba30df8fe60bc62f7f896ef69b5e364ad347346557cfced9dbae56c11d28edd67f49a557c99d8cf5ced7459e1c9bc805f07b1c722b3fd0284d30de49331120d9bd8ba857d4c5c6510476f672be32fd7e0198fdc2591041618e6220996924233bb54f9725eff8e4716ee8a3483829b9331e13ac6685c5587ed84e86c5107532a75693d0e1b60f3f1efbf1d88718722edc41039b09804512acc14aade699b874bad683e13d6dd9e8ffb9452020d3632d19742017bb6ba53c60144716ced0f487165ef1a2e97714f564f974e60c504ba8487d826be1caa2b853913b307bde83b31276a32bfa0438ad91b53bf6d89fc086c63ccc19599250f5bad9d65b838f71bc02725dc8b49c1331f87fe427e1321d96efe12ba28cc554da25c620cff19b48b712606847203433a141aeb15fe8ea1480481bbbe995ae81e3e6cf823f3b3190502b429902d5f8c619073a7c4e1cac71a0b3812984c6863175cdeac518e4c802b49939724cdd0e4b14c92d85571de24d76a35f1d49c54157589fb91c731d5125a8aa266aa5604464d363aff4bb3dcc03ada0eb38ed21ff60a15dadf01108d71469f51d987ce70a6667676724e20ebcafbc845a477b2c31b15dc102f615341d35d626b2f4d5a24d85f89f0df513c7492231939ed80a34264b335deb8a71997896395deb44d6d93feb9283e9260b2ec5d9ffedf76cac58d2633e9ee91bcfac793ca490ab129ab147ad244013f79f365daf410b096d35d5dac774a9b5aef832bd685c7e622b9d0251498c0366145cb692788d02615f7a01ab02492945dff2440451ad8385c08e33ec203b266677791b2317abfb4d2c4058f784d29d53a03c93a859b33809e453d888d907d10601432063a72d7c985f687518e8508cc2d55f67282db973d36c9f12082b3e0c80bfae1222768ed2a74f7e345e82e088400c917ad89a47322294e25de2f0066992a5e019954a55140ef6a622879a3916abe9b0746e5ed6a5c26e97fde25f5839b8063c0577990574d884718f3b214a03be692c147d748fe24831d509db26d41aeab244904d8da6a3ff8440df432e44bb2920465e0b5db645307e505005712ae492d5d76e8e7aeb7338684413e48df45449634970a0df47a081609f03385fa824a37e5b122db11bffa8ad08ed2faf42b566e8e356241dd24b7125236a435f893100e2fc066b3bb8da93511783b88c31a1437cc8c9f5e668f1c78b1eb1cf1d53889d15e450280a902c762626d8b4aa632f96d97d47bfe3e7929b346dc5cd5a3aac43a97be618b08c97801698bc9f018230a8dbd57a2211adedf465488c5116137551367b213ef3233a2eaca7bcc187aec439eb9448c9b3111f28a008769a6e722ea1773cc11e76c0f7e54550456a371d43a78768425a4459356ae4684c2be0441a99dc6ee30e0b9723ee68bf897d14d5eda2cc114b462ac9b8741aabd59ebcf0414fbcdedc94a5850328bf704854068f2cd9dba5b3329363e0bcb85ed2ad67677ea43d0a1c3bd241769595dbccf060a83f3b1f515d3d7c6e1e25459267537cac6b55cc775cba92e7aadac3f072593ae45edcbece9e0c63cf68b8ee150f96573c2af8ffffac8c5eb104aeabab64842d384fb95b38dae2b04e6c9a3107d19db06bc9220fbbff184eb657efc1eff379d43c4a3708d8260455e518e68fc9d0857454fecd162ed284460715ca9e590c9627ed23641497f63c82ae506500d4fd486000e28a507966f06f5d985da858e3863930d7ce8e73b0fb9e79789967f57b16917ee23da526c2e70dfefa69aee321b03c212586baa62130b849bb4ca38a81449859453390df5f92ecd6773524e26253862a0242262ace9243d4ada7449e7e1a1cf18a9f26cc5de3d8268a6cb58b559de77c9aa9e46311bbc6be679ce51d481051c6f0c0aa58e3b15815154c0cc3b49b93f68d5a6c0969af80e5c4479275228a97e1c5cc2faf3ec994d831ba99edbb071ad54ac39346f99dfc59b04cc97fe82eeb042ba744463a8db9e5d462a02dd61fe700384987bea0ea0922510094f7d2307c5a689dd876765279a572ab58273d25dc1a237c447142cbfb01551af5166d711b503509be46c46de6b94bea343507d338b35b39edeab7b8b6f21a055b1bf37c9b233cd44c76baf83c20b50168ce1011f784050413f64b34eb616d042ee217e40475f61605774565668d87f67fa105e92b0164c3e7085d9b4e48209ce3228f05f47910581bd9fa7b0f426f37afa8ad74df725ef6b4f87d89f36fe57c878394c0892c5eb2fa601996da653c4a008a9093180810af86f22cc10b827fa222041f139b510580a3156a1e9ab3c1b1b7271a0d8480ac9d4d0a65db9ee1fdf37661cdeb254fe2bbaf72d60ac65fe2f30370933c54352f7094ebb4cfb13ddea5ba152d6c37c411a4f730b9ef046211647cf17137ef9c1073a8f74d25581b18016497c3d6f1032be1b875b8f0524c0b098c004133d141958086799aa268a74582fb841bee43a0e5353975c885ded95bd88c7dfbc085c74264012a1b48f5ec0dd7490c2f5615f1a6f16ab229dce19da67132cdeec0c745a9e485a7cc35c1c8181e105875a818fc3c2329ea53099d09a2662b4bcb67f5f63e2951c5aa55d080652945f41f19fa51f3f588d0346bc0b89d782ff1c62eeec54cd4511cac8c2a2384db4d9d628ee1291d5b168e0820e239edd1f1a7dbe6001b318c380e497d1d1e2629922154cf9b250ded8386eb87622b0400d7a0fa08735fed450302bc7d8674790387b6e8b7dd00eca1809d92719dc1118256f7e80cf817e964989619ad55f0fc522861b07b4a3f23c28749e6b8bb892768a847991d401696170145a320a630d581ab72f941dee5cd48541a175411669eacfce6718c033269aa4e7eb16b2b4999864cfba1c0cd080f088cc1492841354308a8301254cc713d3b93e132be78f2037c451de7c81071a3f058eb8b02eeac4d632eb27348a7f08a3d37376172d6180c05fa0dc14e7be00ca844cc16bd92e25e722596fd21522aa2d2e86dab00ea875e48bddeba71b81619ef1dc2ba0c1b7cde2c852e77a13ae32422e632baba4f534af475dd5041994d76ec59fb44c82557678b546f0a3ad1f2ff462a9a34c6350b3fd7fc3e4a64aadfbb9478dd65c51b3c27e790db601c527ea28ec9d3bb8b9c7ba48bf1cb32e8eb08c5c5701855cd0edb5f65a68613b0a6b56bac8cce7018323ecedc9e98f33e69fa63c50a538659dfc975cb1cd69bdc9f8b6123501f1f3aa22cb1c600bac5383ed76f9b20cf8358a373e8c256607fd2c4ddb68d216792ecddae4285cfb5ca679918bddfeb6fa1493cfb66a8f82c231da0a30fc2ecb0c3fec5ac6df142545f4f55d9c6099df0516db6427791b4f5fdbbde60ab64c857a2e665707e976b3e8ccea5afcdafaf19ca524fa171dd4981904632cec4f4a934afe9c0429ebd43810031c69e18419158f82035d33b0b8b866df413a60750e36ecf351268948cb5369fe4a442553bb7f1c1ec162ea827272e824f25ffa9b1bdba4d4334030d0a78526b0275c9caa4daed40c2609700ce149b2f3b802e00a4aa63aae702702fe467be59fe0d8154cc6310d834de88157602cdaa051c245c59d401e583be6cf87c863c335a2abff43979cc88abfc3fc2ca5808157b623f502b4c5bc94f383001a7156458d560987625230350c158a1ff21470abef168a8e4918057723c1e8b87c563dd253032f5345ef2e614e9653cb849a66346952980dae17b152a42e62430c007cb34c5a5b06da66c0fcdd334806664f1bf08bbe910d7caf869a81ee4674d8e817062f6b89219968f9a00a5e070b8018bc163ca4d3a545ff203cf6cfda32c3f032b056a44c18a9424cc93c6946a581abde9066a5c4ded284b78bd564e13119867f996886714c8fe852240577066e76cd2718244b7187a98ca1d098fe2bcc66f0b9b53690716e58ac5f3172f41385f985d60ed868b597ef64edac924819d0e5c1251561965fe1c2fbfb241c8eda51043b310060f8ae2038affdbbbd63f78168d1f13a13041e8018c0a944b27bee5cbbdc29c617617adf8c5bf70846cd205f0b0f84bc10682c90d08f9ccb2db11535838377cea78ea0cfce3f75b22cbfe3ae490d584649c74f25a891c817b282be2e5cf567932415b982b2c37177bf7b3022869eb2e385d18a14293d5a4dc400d90560ac1be4b916aec2bde5077f0c60d04049e5bdf84c6b5a19b5034d23b66de0c5b2d5b66bddbd40548f3ea8659582f0288bfaa9e96cb91343188856ce29b2dba1682612a4cd198d5faeb8926c54d90b2ae84b78d86d520567aede7d0cda6b853b9a52abf2e7b21632952b1f669eaa8899bb0f2bce553710d8862d4d12132872fa15515b77c582826e4e80833dd38fef5ce4a1d6edee992ba973ac7da2ec57ed207eabe04e2c1fbcbc8d4620e522a97a829788fa7a3fb31f156fdd08e637915539d5e964c6f01d2701285701e84a2978a95979561f7cd8fc01262ff3a79dac992cd454d10a346827a72e5804fdb9a4f3c31abb961a4093f106ee6286e0ce88b0a30b9e5276af6b0d83e9a1e9f3d3f45e2f814b4e553730969f93867dcb14771acb32b5efcb0f71dc6083d215ebc2c5d1c8ac7d841a09d91b29d7592a075b05bbf3a0c851139209aa78ea8be2ee70135f95fc22bd13c11e19fe6f9d16cc3a7aa4c9e3ea48fda6e180c8f32ee065677639652a4914ccc31b7b33175121ac7a2ddd9b3315a40377f665b6737f91ed2dccb7325be3b6802c15dc6dc21fba49407068fee94c404dbc8d689dc697441d05627bc77d577787b4d9d0d8d8b9bd6eb47afdb12dd0b0696e1612d3080ee2b39fb66ac63bc7aa686805028ad9aaa158105175304b25167107958eaca96e31d6968ff2c89828e8639404d43fa49cf312c579299b984b2f859ec1cfa6bf40146b574d82034f830ba0933171bc48b18711315881288f7cd7715abdb352693c1216bdcc897055a8dc13152d4976c5de708d00c4960b348287aac807cc397711e9b8955206a90b5c3465885e18867c16e6dd629eca45f6ea13bdf6c667ccc823da54721e54a5d0b35fab9e354c0774f7b294f95873b5e22c0aec0a4bd328dfcacfa2801cdcccabcf6b9a9627d5085b6a81598ab0eb29ca94285f140f98bc8b51f0ad921021447d0616f90cd7e3a9d4a584b3e9408173bca5f987aa5b9c470e02709b5c462753f61d8ad7f76f20aa41660ff96a91681da68c22c77adf62d259160de286583a4ad5f12c3e53340ac96449091b356f5f33bffe8ebee028cd206cba365463d687be9b7255713845a9c190c842142a5da14634e2680359283029954b0abfbcb70e7aaf20a241cbb954ca4d9a0b389a5d36a9235405462e8956b56559a60ff4d38e98164dc0a9abdc3a0eb2937ce72275b810e99b289bde270e4374aee9946e8f3fd5d25f7237e46540e69e90fe9a2f6532f889d8f6bd2f416f3e05dfb86303f38c95013717aeee39a0bb54e37a4ead8e32e85a7bb5d14d4b2b893b9d6e15cfa6a7151beceeba0c6e0da8dccbb5ea8289f31cb1c33c712a2842d9ee64a6738d19c1f5607d23595d751e64873da754199d32f8a03276aeb00702b94a651c4766bfcfab73f9a8f56b3a21cf529ee4fc74c5d741ac856cd76cc8ee23b88385e1c2c3be4cc8fa9b10602b1f8f7d11cc0a4a498d2495bebb6d1cddb36ce2a3d90834481ca6542c9c888e74ded6550dd97aaf4db0c25b8f4f5ed80b701c5f777301239bc8aa1487eccf28392d8d5ea656d8b94d616bd0d87b6cd620cf03ea059504b1c3693c952a2fcb13339f73a69bf57fc8e6e67e9ed464831d7834c832e57390fafca28b336f46198c7233401753ebd7d147484e9255014e6e0b0d59df348926b67f1135d2190d482d8a6da0bf75b297c6602c1c2e18577b63226b4511298642a820b4a9aaeb0bd8af105ddd614358bfc36e0f78d66bc3ca28942052ae6608c9f4842df9deeb28b084cfb30670ee240bb99c56a9c8a4281d275ec5b3e636759c04f330db911ac15d43b8268d77fa396322396a6951064620bdb6774646f6c2d148b6e105c8c12fae432dfea290c31b5754a0371baef69d1fb0a1a179f801f232e67789e67965cd13aa590f44608d7c5b026d2cfe4fc2e33fb841060bf1de10432518c883343bdc256215e1ee02850a191621d8977bfbb57d5400f0d1de80d54330209e0b4cafbdd2da57c365ab2e98a7d1d97d39aa599b180f25e6010a131be53131f6fc706225f1a849e0fc3bd174615b94fbf0161d640be5ca351d0f2f94b44622075276d090c8fe7bd74764035d6f6d2cc9b480da52c2c4a5a5ebc34924619e59bb16530e3c28c0824fc7d740044c10dce255e0d9ac93b7a0fda1b4fd0730bc0ab04baca02af6db62eaefc7f858cb9ead4c018f3e45ba1cd11858795d676ce20544cc32f29b645cbe5bdc48b1561d7e22a6263a90ff94123dc6923ec2054d0846d934c8b15e5cf0524106647cd193dab797cfbabb8e2837f2b22198c6f73021e15bfa5b0ad0eae1c34aa6f33c2509ca5deaba5acbcb924a22dad7b893daf674b17fbb12ba9e595c412d5564e31ab8cd527a8ff893f082b48cca289ba53e606bed66382a4745a18fa1bc4b1118e2635344251179b10e9613264a8c19f45ecbad0d7d34203a2d5ee66a3b6801a97f22d01e253a8629960987e952f3669a666546cfa69a2822b82b2e6663705a90cc1fc0a1cb533724e90c6c388286410fb81c4a5e45e2d702f12c4f2342cb33fe3d9dea08403cde6d51da68044d9b0dda937287f611569d9012f4fca6218029a696ef1231bba668785f02ca00fd3885ff26338ffb8d0c2d99f5d362fba7652fea528a3c4ab91d4b873563cc68a37a034804fdca7fa44d8becae7e0d4c4625d9286ea561670e2043913a2b0f28cb1750bcab412e555a369bdd157c4503ba16ce2f5d009427c496e558c3a2d5e6e1d0fd489094518bc849055f4c295706efe1a84626eacba30adadaf30ddbb10178987ad742e7322a69e5acfa867bf8fef2aa7fbc6f71618e56558656413a6c93e771083279f0a9dda78c2110844833e3c8ed02d5d0ce3d93a4021f50f193857871512cd163540a12781114cced56ee3da179978a3365abf48013f3bf340e4e1b408c5c826dc1a4d359289931b47303499eae96062fa5a575e4129a37b0ff4aab43311b80d585b42e8d94d60800d226977322c51fd9a53da0314e726ce2068658c12d720ddd6892dec6c18ee7604973da54ecea4504572d72c105c7eb43204143253684aa831204bd1abc1d4cef47f0eb78279a4fde9e56d66e973febfd58b98e4c46a64a80646480e3552a0a21c5c1014fbed605620fc91a64f2ec8754ebdd82d4a093dc122d3a4a53ed9632efc467dff3ef32b264f26411f22b0909242eb352daf6a30cc630dde6573f42d4a991b7cf90a76ef0653590947e47fea4a2b04810cfcb07102e4a449326f4540b6e59643041ea5e7100130ad9aff8ca072a0e543a99c1ac08fb6e26681f6bc028c01161764519197172ce9a5e196bcb9e0af77401305c1fb55b6e5b74abe148801d020a8ab9958e6987d84612417fe655e61c4d9f6c04f24e063f1912d5c0230ee52a80df1038700239249deecdfbac879932038dbbd241a96a41217b4f202bbd2e700ebd77a840397ba91c7c573b1c10c6b0790c47e212c19ae3e0ecb17af9a075d2cd0590514b4c02bbd0629231ca50d45988407a8bd68a932158d749cf4c673c01093db5617dd2afced9ee58d81882adf4e513cf10336ca649e72bff5575d6f046895703113d984567c02e75185cca6e3bc503a16b6174668bdcfe3568ac4b0ae9397313a1920e6dc99e75cec9f20a491cc890c6404124efea49ba22744c6ccf4e51a7546ce54af33703411f4843be6045b2bcc2e64e7a86df96af5c8f7c994de24261d6222ac8539143d362257e28eedab6e08abef35ab1a263ced76a1adb876e9b06e0a7df9888e9aaf385e351c8a2c7823d8cd000ee65c618cfe12b2d59f8f06c3eac78f0091539e377e21d434594c258a562c1dd925824ef1de055f316d86a4bf3d8376a919809a9b401ff79479839e8fa8688dab95123c66f908fc892e6138ad8208ece36819c9902c7d85237cb67034e0486ff5612bb136514432b2c6d8a195a2c4df4c3a084936c05b88f126476dae7e903a4c6c08b5a09bac13fc6bc3757dda0b7e006d3b314a19a6b984389f04afc66d4b16889af5def11d921124b24a1a0efae012f138b5574ad9b6c705ddf497b4596fc8ad284080f8b300d1305cfd218c6f5611ceeee06324fc3fa65cc0762911c9912f340acaab8f8a5338f39fe1e50d618dc532ec2f668180b4905427c84eb942de4a5e6727ea313e2485d087c1c0e04c807cc0a7fe6abb25d8a6e4dee4997f313ba3603e42138c9d8ec06c934a419fd2cd86073b0c34b38afc166f94a6771e46813b5618faca44f51bafe00044b8232a1da2969eae191703518174078c06fb2044728834b8af887292e6eb2457b3df8c23ce5c677f511996cc429a464004801f243d0700094cb07e36c17222a33d1ee0d18978a65f1f95471fe94a3d9794e834b68af589109f87eaefe18352052453c0f80548a7154383a97b51a40977d584c1f62aaf4200d4d12425b7535e7c38dc05e434a38a083b5bcd93ac4e802c870f7c489aecee45dac98f02df5a00a1f13361aae376de32691a06720415431977943eca2d6874bf5a082f1b0d3e53d87f60ddfc3ad6d95345642c26d415ad3923001847135e855b28aa860d4b23ea0cae42e98769519b02a64a1d9a694fa1ac5aa7aa1eb87b8324182a0f2f582670e23d1fd8774473f42c577abd000f680e878195c1d53f84f1aeeaa608fb3529f6c675de30df2fda5c690b8288a4c2b44d98d10fd856bc82081dab489950364d4d63907b30f4af70f6058372f8ee272d4cc685bc989cec3f672c563d3d3cf6881c01cd4304972573bda15f835e5fb20d0f062994881e7b86da93ed45d5624ab9fbae09868642338a02281701323111c4a014769054286d0c1e2b314b11d1337968cee3ea247b1ec968897c970f9918efa491a9d2aa03f00d02ec471f8709f3ece0c8ff22bd2c9b84ea17806fd62404deee0243a30c506a1259da16d7c17c5af6199e20b23ecc316df39d8935c54167df1ef8efef66f163565e00c666a1ef774b5d77014e584127cd38b35617d0599d7732d3fcab41d062643ae35ebc7ac4a82dc774c22ba9c52e6e0690d7b60b7855a73970520818a24c1f66cd062c65fdeccd3e0320995518136e21147898bd9df4414581bf3ed39c78e2b8c8a5cdd7ded5f1fd42dc18079f6b95d9651d8a43aa56572a19508baf50327504f08f3f13fd3486c803010e3a67bc35aeed449025412a4d2f1e6f703d912c7ca4a4a3cfd9f56e58fc69b38cd4062d58f7f61f58de5fa4017848a9d174348a09f909ea07797eeb7bf6b2d36c1c148503cb1bbde01e381cbd3c4ca167da02f1f6704ba2c3d39a068161305dd10c8460ca703fdcb8b2412df484669025ecc79a1793b692f4e73d5355199cb595db9c6c4d23d5bff0ce5221af6e5674d26393292c378b9301a0dfa60fd5a6e7201eb74020be793cf308512a230c9e8af20c856beee1496190227a721ab7807e0e7960191cb20e929af9e991c96b59024eb502b1c255e571e91ab5c26e7a0460bfa2dae7862e510f9939f459566d6717cb8e42e92108ff802ffba91324283808112425b3f909ad27a4e7489a7fd054eb32f02379080588df8f8b20855054b820ab54ee8c1351ce104c137f159fab498a2942065b608350c6ede141e557d89481143b07b8387d5d04451783073ee667f217ad2dc4ef74a7b0301e48e80ce3374dad30e402f5169ffa301e604ed447ba0ab80de780bd441b294813a131c5284bd49087987bfb09a5c49a5ad415e3b53d337574f47a0216668d3672f3c94c045f66b3211f4a96ce94a4dbb6b9236274b2b2e7ceefc267c9ea8c9fa74e3ecc291a8bacd025a283a4554a22b0643d1a349a7f719bc1c4827c8c68beac99841353b621d3f32316ab2750fdfc245f61b194ce2869dd8025cee7a6e30525613ac6c74860e50eda16c29a707563c90c16ef9437d88e70c29c029e94244e5ce4f058a7ad36a4c8795bfb0b24177fac6fc8df09e81ec0438b379c45150493a9aa8e984c6433234026345edea322e492fb930ef026a5da2cab09d0271e2d6a42398a62509700cada3acd7a7c7c3a04272513fc04bef2023018e0f54ab8c0eb59c0608b224b56a4e95828b664aac458023f29a8f84593c09e78900d7ce0766c6d66704a0dbcc40a14a20c8134b0584d04ce47bc275cab8f0ba99bfec3ff1a188716162ac58d49233794387492166cacea258fec2d67842bff219bdebb86318ac3e14629db6912cf29a7e5d4a9678e53aa53b8fad206868c0cdaf25ad5d01a746258a004da63945a007054727ebd225229f391f43e445eec5203f5c58f850da432a9a57ccdd123d4905e71cd12b72e30b1e4edc246d50b937bd7bee33b93716ed5b2f648ae86ee64a1f7b93aef7ea1c77e8ac83627849f38dd7a87d6d8553c555e1c70c266b575aa06f457f2f23794ab688f720314e5d0de17a426941ce10b2fe3bb0d06bda90d0aa61a2cd08d8e6efcd1c2ac4f49cba6647189be3011c445db79607d8bab40c24baa4f505c84f15e684286e8b90ea72f18e7df8ae42bf96c4e2d29afa72e6e199a6a57eee5ebccb5d3762dc6bf82fab978e027be9948046f3e95b234fae02999f0cb296eb52682d143ad0c6257d09822a85c98ed0d087791123148afa1409c219e2119527033116240b6056817218aa74dfa085656459f2f9671d12afb845139b3d24eec5ad0e4d8a70cee6ed9c93cd81c9093a3d705713ef0e67941959c65e6d0c0e146fe814a3c2224cc69e4d3992f5da104b7210dcc833536f9f7e8381bdfeb318e1b4fd04a7c45cbcf160ac83c507b7791e8e4c7935644af6e20f83c9cc57237ac5c78ade58a93baff5faa7bc83cfc1930a75a78c930b6c1447cac203acebf1bbe6777fe67a07032ca0561a50995e21a9ae2373813d974b8f3cce4d8963b33f07153c0f0dd88edf14587e378d103a9179e9f961bf414590ee97c0b3d05db7df968a6ab5e34798b59049cfe32bfbbe7cc8320dc72c43aaeac93889b3ecb3ef4123cb48cbed96c9f89c05e94883f4d29762b2fe73b7054205641d64999fc9106120894d52481d8593aeb78f4d6b252920c8329e838df2e3f1166b6ce5482ad75ea7a131d8aa9af90ca55a58334c94ca0fddbc9db8e5179f8aad20042aad9917a5f203d72625f9a6318ded4d1cc074aff937ac3a065371e95e295817851b99de213e0ad356c4ab3863e6e1519f03a26c28dc8747d2b65c54acc6436b184cc23605777c6133c15790dad22e0d275c80a7730879278eae9d5164d8567599ae933a6c73636e37a04a0ca66f3f39566d8e90bafc9afcc5d48bea1d93016a0e08a03a7e84a8c7f43d26cec9385622e2db9288802f1688b4e1cab76713314a36d021ded9dba0fb83441cc07e1606a58c27bb107d172d7014bf1e092d47811bb4ecfbfe80523a97f8eafe4240c9ee9a9574768d4e5e88794ef24cb4690e16ff0cf6d5032be47b6c68bcbe24b542db7b7f25fbaae571ffcfc69824e8c5851439a7def005a047990459b7f990d3a73f8b5f63a308ee7f6e8e45b9da4d981382b935a51eb9c892a91708e5220776686b24089afdff1901d8e1241cf3cd42a97773fe7a5939287763e3a82666d93da59a99e7c0d029ccc6a4cb5d54dad99d8183b4faa60505ce956a8f51437f580e4d1d2d86e13785ee192104e1bd8c6214a7b462fd49b943ad6fa619e470d5033ff3402f801685921975605f290e3a97ae44ce0daaa3d1ea59deda43539c455a5620b444593b750d9676859e50a0c44f80a65fa8eef391b4f12bbec4b1cbcac57e6feb976694f64b299c2d131baea0745bbc8b3cb08ade2d595775d412cd2707b74498b02e25e23178c4f65c500507f384549a7e48098c8373c3113fcdc0dfbd92c79511a33b7cdae74766815e049a707f81d07719d82b99b949b110d8590c06cbc0dd80c2eb5117416fd20cb90b3c6219c58247bb5070ca906daa369f8a39f05083ed09174052787fa0d44b4621c449dc20af140f4a1115ecdc9c12fb093db15bb248c0828a661adda3c6d2c95ef15fe9cd3a470931bc2d6eb1ab03c7fc7de418e885e00ef307c4d9c76256770b21b69bf0a548156fec0a680ce83f2a5a1a23b7e781aa7fa0c9057bbf4c35b50fb92f5df0d0e14acae136cd2482b68e7c5cd8d7edfed09e73f762a5b71cdd6efcf74681be173d8a057ecbb32dde80b983fea34e4babdc9ea47f89fbe430bd2ea4c70c1f51fdead807005db848fe4de08b049091de44729484281b1e7d2e1cc0e761925aa6e6869d65e838b684b1299568204e6c5ddff626dddf4fe8aff234e50c637de6695c2bde20e29b75ececb6a38d379c0477bd740c0078f2da24729cddb0c9953e1b0b7a2547f4722ba366804b08b6faf76c8d54c627b006a69d605ea96b2e435eedc2957190cb3a2ccd867ab26c83741611ebda338c63430e35b535b196c5332c8b467e4679f2909ced1996a85ec43a8e9e016d00a8a8abd5fbc8ed11fdb17a27dcabd8f462e406de6da81b7ce9fe1b9ba7d67ba71176a1d1159607a2c7bb0de3827a5fbf9414be212363ee95be0ad0077f547f71da29a6d077d877434c4ba11472e39318ec5262b0b35c16cd217517279e9c8dc76c64a5624ffc05bfcc4eb4c00e38f5d00053e7fee404d62603c43cb9e322537c11d465175eafeef52832c9f5fb304dc13fc2a58d678a0fea8864fff1d0ec90dea9032b6908100bbd8ca9ab86b17a0ad7c8f5580d2a4ed1eae876d4df11f9c4fb69de9112b960f2f8c0e1db99ac143895baf0c87296298891cbcab66cd2533ed4035717fe5172f0b7ab630abda706df54155fe518b8fe940be99706fce1e8159eeb7a479f2749832d2ae9539bc6c5a5027db3d597992f5742a860c7c0889b9c474c1241d711be491e0ea86b7cfb16957fda1eba9561399a61898961f4051e1699688d98dab25d33f0d6a6001e1f8fc52f0c8c338ce8503e5dd534841ddc40c98c7c6c54a8b75af1289324daf2e125488876ecb82d9be2a100156e4749d524caed8323e1b38e9e6e6c09a329c73a06265aa46290ff274de865d133bc54db5ca87855a11011ef5ea7e692876e9211ea76480fd53b98d2dd21faede9faa204403fc301d53080a27c28c80c0ed2c377a0b16ad9726332cce43a067f546dbc872cee691a284dff404d8d57ac114d3685ddc686ef8ae6e59050787ed4e4b55aa8ad5d76818dd2d5007016e569c9bd63d13e2f8c26b0a51d8b81ac6300af1c923ed77d0a3c0b5386ac1e623adce4b7e76b89adf0fc5f6fdfc6dd160de4ae64f9aa2284e57f42dea1a4b2919da27f4ede2b29806f1a17f2917618b64e0c29c8c74022ca695c82dd55385df21d7f6fff9bec5a5972ddca4264e83586e3d50c8f89c4fdab7070f63c3672bcbeea8d1a96e6b539fb2faf6ecb27a130911b8f21b070d873255a61c26dbe40e32fe49a8105544c1379d8f80060d7e8b303bf8cb02122fa1e012edc8bdd284fa156424e11ded89980d2b0d1d2bc2c281db22c2fbeabd5b096f8692c8760536032e0531537008dbc7747d3abecbd0cd01c65f95cb49fb62cd9eac3bd7f58510e5b6abe4115336b6768617a7ae96dcc6f1e3673752f6b08c1e8e3f0fdcfa4bf00a1d6d1bf66c7036d24e92e33343d49a0cde8ced0949e526b0fef90483c22014b25b256014f0678fb914cdddc19a102c4f31c990bcdf5eb3233408b73dd267a3e3e5a4ea19999ede77f3b99ab9e0689051a26d7daa29c7ae97c47b99a6a32d0f756270778b242346539408e12351c13950fcf56b202ff4145a8e18e5c9e9c72ea2547cd147e9a124cd4d68f17010ce79714240da70f99ca15ebcddec894953380a401d5bc0f4fd9e90a57bdf89f1f1678f6306825ca1c6e3161d2736bf3e69efb821cf786061092468ff9419d477d5ac2f8b87be35f71fd7ca77f05e14b15876230d6ae02e344fe075987f34d76bd1ee5b51be370d7aa4b61a4a1cd6e5fdbf03097770c5b03b83af981e25b161533ef4d0cc4d49f3a04aa8cf226727d2c43f96d96f8742f13e3165149491d63eaa7ba301268c2010e2ab804373d546d8e2b74f4c563759922b5a0afd55b8de29afa1d72c04b55e6c665e86d36d1eb647db6b2928957fea192428908ad4ce5a47503a061b8a1b66ae70c02cbd85c97a8ba464f348b05f66489e4111c57c7e6fad1ded7a3499080951535c10389c1a3346282c1bb50e04cc636af09acea77efb0e9ee23c25d0d13d0ada90c6c258b8520c9ad4b689d9e86689de9435418e759971813aebfc4f56e16a3718a1002647a737d5f230095b58fa4e9e5e4485e03fc6c965a659a31cef392caaaebec1769777d2569e33b2adb4ce9b473af0881b1fd697c5584c0b0e8973fb0eda6ec793f29b656ba279e992e16d1d1d0217cf3de6da1434c809c7b5a3f304bf29e82dd4d1b2447415147df7647528023408943b8e1d960fd6b6265725265f6f02512fa1ad8cf0e01cbf5b06cdea7f1126a0507eaf27b2b1da4d3325ae3a1f71cdc537362cfff98d7ddac0f0ef001c309df45363759034632cdd43e895ae20819293e6ffd9abca5ea7492e59d792ff791bf8d63bd27d828cadb13eb1fcd688419b7981fb86683232c7dda84c1690fea5dbdb47bc58f975efb15c13b8c74bbbee2420214c3e61a8ebe8f8185604dac1b915b9b9359500f0442a74e39e67c9944746702b2f0415006e1684fabf7073855cb9eeb4515cd39e8cccc8ed559c5600bba447c44c34380d3ec80738f3941aea05bc871e4e2e88435bbeac66b1e84e81d1916e1afc6df7cb8fe5ed54875434d92c05e70240867c33210e6daa2ab012cf3820598cb34ff8dbd568740da6fa77bebc276609c2170763aa425994d4e5951602e8fede8ceef815bf8008ec5f3364074724418a948fb05d3a93945443d7f9b56a1ccf4d77799e33ec6d0e9e326a21648aebdbcf7e4918b86f4bfec62a4f5690808fb05a8a1b185a446dc7261d07345db22d097798b90927bc7597637ba681e59c14dceb9ca286312dae9cc53e5fcca52a02ed06aac527bbbc66949da0f503d81dd7f68dda3d3c6de0356842d28e23c60c09750f66e16eebefe22e09ac2e5df7f77370f6ebffe07b946b8b479835174c70012f10538fff5783dbec819e39332bd0bf9b439aefefe27e09ab8046f1d751fea8916a2c4bc10e725949bcdc392bd5baae303316ef6df6640ed6bff5c270b48d76b8cbcba5db2e4add8ba5326e0aa8922938de414571b5037ec807ce94dec34bf24b75e1c0a6c610b1b396180a8ebbc635c8295263eacf9fec0cdb2e62da81ad4426fefd5637c4ce4b3afb4e6bdc1791a6afa70ae991d5a8d7d6c2c683e4f33bb9fe867282a48b630c48a2ad330123b2d4861869cdcf9e0d9b9501ce86b4be5147814d4b8db5dbd584e96ed5dd4c2e56e262b0b332b7f01bf9bfa589ad8cca29196f141c54ba95e00dc7d3f67273a88e98062a8bcb13e35c4f1231d2ff46ea78087ffb425b44dbb247b3115a0626f532479eb2b60dac73a35e9fb8a78a7c6dff76ca69bdcd0a3d88089347ffd3df79887bab261e321c737a8f4ab98a9b413cd820c7aea22324ff5df314c2c4e032a6c3a7b5c40d6554d0711fcc346bdc4713b161159e7a6b8a5fa598445e4161dc45fd859e20ca8ca8ad371b66a0bcfc5c6b51924f3e17697cc9f70157f5db9f4210a9c53d880a8a843710286fcf55e4e8d6e7258c69290b6b7dc5bee2d654a52067207d007b4075877365885099279f508a3758d6daed678db34dece169e05c33a252e36e36df6bdadde5bcddf6e2b6fad8cb75c8cb79dcadb51ea2d09f5f69ede964e60bc758112448f1aeaf78b14176f619cbc3595de9eee5b546af456a57b1b837b2bc3be5dd9debaf6d6ab6fbfeced0cec2d0b7ddbc27c4ba3dfd6e0aa176b5a5a6099f179be2223864a0d101cf56743a70f55c9ca4d8c71e566ce39e70c829571852b7dd66a32757777c71863ec4e39806bd8f9c30bbc12fc79b7cc1bb0bdac621df2bbdf0274581f38a289ce8b08ff70030806ae9a16b453e7b29a850d0cb2cc998f5d227040859a4cce8407df2e4c10bc6204df9f8d7e79397d8c820912df38664c1c1a42c4ce6b32010a4358d56800013430c8ae0db9dd0e721a3162675543c3611c92acaa451142457a7472806680e4a3049ac19197472411381f20a2d32ae295f33c4318943b95996bd739eb17f698a6265cff6f16818956756b316f8f99bf90ef63618fd7811dab1ef6782cbc35ecefc7fccca7fc640f77859baac1ceefb2f7318a2b52907d383794ad50eaf8b0ca4812a9a4474baff55e93c941f0e545b6a4a78690291fa3586203c92231f7fe1c07d9c32dd28d5ce1fa5721f42e0cc94a0d980116554cf1a174d9787989628915cf383a26e625cac7288c3085e72f94ae97927396703df6e6198a49c5f44d1424ae8991e0f666ed417635501fba8d60f667c9d2d4dd3cb99b99b9ab2042a25a9dde3d23297609d022e68c912eab66ac613af7121b59421742323c8647ff42706378ee32bc159f5ef700240788102038dfb2f53c2211ed6ea29e40247a1dda8986106aaebd144ff9c248e4a249eda38eb3dc578e3b17edd33ddd8a2e2f220c829c7222528f93f02bce60ce2d9711067da20b53027c04d2217a49f4c40d99e739860fd9e387fc22629c17cfc9899ff889334ff7aa61b886dd0681e12607f229aee25c8aab788a7bf31b274cf10ee2d520dde436c56b1c0639c553bc570ce2b02ae50beb370e0c0e867398d2213fc5e5a7c0e09e711a26d6a4beb0a2be9ad3279958286e8adb140f25e5260fdc5ec599f9ec1dc4c52ace1400c584eb9ec23cd6acf8f555c3489cfac28479eea1a2e0172aa69e9bf26c6471613eac41e238e6a82faca7cfc430523e9c17de4aba422039cf2312bde6d3f3314f3c9c50d2e0d9af471ffb62b825cb9cf4852f59f7caec16a7f6c99cea491c21435c9c15ab82ec60551494104514353f744f68420819022d764417f630be64b87b31ba2a64102723e84a5ec9a8e24a0f7b85b1ac783e44209f1918a9f9a173021357d4acb87b3e6448a8f901258b9a95af053d08f03a3e1d280258d55f0ab4d1ab9797985e35f38a4176195ec7f0d8011085eb4228c52f8050244816ecf26ca2533a27952e0633a2181dc3b2f8ac0786cb2ba66e515e8a682f3e37e416ab324beb6c346db3611d06b31c065f64a079d5e6f74bcff590b58fbb0c623bc830437c0ec260e6d24b7d8cc399cf28724399b3da22ce48cf5c6241dea0ee99534f5a41be90b9123e9439b20a34a0b899470f658e4a9c89d46d56b3ea9ad65266f6c57a9a7d59966519ed1cef5a69dce04e6f2256853c4c8f79165d4489bc332f1b6d9efc1c588539b5d686f262d66d12aeb5425885b9f858080e83b4f3182d87f285a6b71ea365211ca457d94a931bca9d971c5c2bb4b3135da874f185f5e42be23e1a4fdce9493e73e93df02a88c46155a9e4617e3dcc2d4dc6651fe7596fde6d372ffce1edc88bdf1a91916799c7ceba676d3bf745f902e699d73c94c5605683b602f942e69cb59e659846c45aa761cb4d197bb47110ae82d49b7ec30e56c9288a143d7500ece0869eb13a2330f11de2a7cd98418c31c658a34bfbe0f2cb0e1b5610e4c398444a89850c923ce923508f928f273108224929a369123ddfc04c240dd285e3c5063fbb4945d2e7af072e7e2976e9b4bf503a05410c8a7a703e36f908f4022ba4902785393ce6a5d8f9a87e9d86bfeac99f0c92dc9ebcb4ee0c2732500f49fe83ffe43bf94292f330fd896324acb339f9522492934895fbc2ea9541ac7e5c0c225792bcd4f513275da75f9d8b453fdf665e09a569a552e9d3ee17190c7330015d21f411a80843fff211a8083eafb99d5fbf30870fabf330a5ee97baceddf5ea695eaa7aaa7ac94bd52f32f82f349ab82f6e3d32684b3d30687d32683d16bd759217ceb7d5eb4783096e187f5cb7d6174cbee6d2eb749257e56bb1e3b8b7118383559d634e9383062bf496b9b9ebc5cf2407e68f0f35e7c1a5342ae5119075b157631e7b7c3ce668581549384fe29ee493ed1279433e8924f4b253b9288eb98a631867b9ebdc77de9d4de7a552c967885ffaaa9f7c36b4b8a91abeead681bcf624bf5e28fffa8917ced7b491c78e743d204ff278703ffaec12f902c7394d77dcb7c9fa95a070548cdd125dd4ed9ea0e4274f98036f9ddae96595cd4dada49dea248d380eb453769ce19eda26a5e458b8acc3469c09857226eaa1b6d5e832bd2e9d8026eea5f9b96aa59327dd2424f2641466668e99b9995544c0cccccc551f418cf6a5bbb7a9628f71ce3999f9d36a77fb0a337b77f7e77577c6dd188d7132778c51d62cbbcccccdcc5c1ac928f2812b8213968fb264aac2954ebd62d987359d31a28c90e6a8c338cbd5ba7d32210f94bf4e7208581a1a8607c3c41c5230b8e1a55efda5d4c4bd4e7289c3aa50065d8f0647901b4a1cc9d36255c55c4758b5fdb00ae3161d1bb8853a2b88bff36292a28f493e022519f20a9045e40b9b635ef50d8b5d44be80611886d5ce26f32dbe0e4f87ea9bdb51167e64bf940eeb9dcf60475f589d07f9d6a5770e84dd7adc59dfba4e8e6aa5e91db2efc21f6cba8fe37cb39d5beb9bd7b9ddbcd66edbdcbaa675da56adc76d5836855018c612a5d7774c28571c3df5e046a0243a2f7b080999dc8e6eefa161366f97cdfa6e4abd7ea1c9b483622877f34cde2ded5e1237f55aad6a52f4db617df39622c914475635612492ab1eacfaf1236e1e4d0a888b7d2ed0eeee116726519cb9b179b146dbd1303b00f1edb4bba687152978fad9a02f5c7a691d88e1fcf881221a57dcfae1ec06c16e11d2125d220c00644b7b83a6996f027c8343de4e8404d2c8535df48bb2f97ccc7abbc0303b76340c4deda8b83207ca0ab354ba248f66e4e5405981d33a148df330be388b6d2915682c58a5d1e2155f2f365e3a26234189c615b73dbaceaa55856e883342d2b9a728d83604faa9d01cac9a3a70f8fae9c7ee0606d925145f2ceef2451017ba1de4cf9982eb1f46a22c12e1108a8971654b08893136edd9b47b369ddddd4d9b677737266b90e5ce04916f40ea396786d1994d6cd239e79c73f69c33c6922d8a2bbf18527c4bae9c734e4c04a42c93d2099e0c8b4ef01c4199c680d26e1e224d69370f91124c2ce46cb57e10358661584f9517d11461b2ecebf163c62a3e7c217b1824c1954ec5cb5056e4760b8f2ef4ac53807df991a8b85be95e6feb6a9122b548d7917cf3a694914fae5b9745e48dd2471deb746c7f3f5944be706511dad94867f140cc4954dc39fae1e737a7e92e7c09e74b288df8c8223d457c863c70a58f8fcf0bd6b291a509939ef78f4e5c61e89dd862c8bf7c74a249162f8d3c928db3dc8f3cfa6455e7dbb6792994bfd9dfbe6edbb65169e4d11ab8af7aa1fcb0faf5b98d4a23d7bc76de756e4b5f28bf73eab5d3b17df7490ec8173acfdc8e46596733ba0cb6293aa9f3d1486e4ec3cd79f169ced6d9480ec817d8abc4913738206f4837f2992785b85288ec223684f8b2d1352312134bb651b947b7b0e76c31df8e36e9304cac59f1c0cdfc32282529942693119434a7924d4c564d2b9d4e326bb922c4cd7c32485d3b4ca68f7a74c6c99bac2fd395f75693c9f42263e48b8c91720aa13abf39e79cd3f473ce39e754c5cf8114afa75318f1d43d938c424c94e28c14483c75af4c363082152a5e489eba8c49e7f43b953cf1d3883813430aa0be4ae0031d3c7595eb7c450a4e90c231a9571f74200a183c75d49572c9145e0021e174e9ece9ea3999f073ce39e7ec8914888900983a1bfa49d13780808898d3617436f38a110891022259c2537fd1d9d0976682446783c51b0440b2c416d434e79c32a0f859020ea2a8a20a426a26b5c2cf2ba8f8797fce39678ca0bb9201985843690f58f0748aa794523fe96ce817c59c53658b9f5e2f0f6af0d34d3d28e2a797bc8717fcf05c71032c24f143ab5085d007eef47a4d0eee20063f9df44294b1bc980429819120b0d084162db1410828a57484a2c2e2828d1d9ce0a75f93832f3f3f3fbd8b11c226b04411254fd8200b45f081cc001186885c153f08c0872e0c20074fd0010f7e48f0d3630e9af8e9f61221a9001036504412176cf18226a8b0c48a4b29a55b504aa58ad086154f34399204e8c813a0e801500e52f084097ec6cc698413fc1c41cdc4829e7a76e534c21474648c132c1b7aa76a461c10f1810f84200525f458a166522d7ece58e777b11e7cc8a1a86c3cf5faf3d4af13453cf5a8f3d44469ac4203251593162a32547eb2fcbc01133fa75717113ffd9a5cad9fee38d8c0cf792fc5c29863479c91341448e20849d00008269658ed20c80b120caec9231113220e8cb87e12e1a70d4cd0c4104d58e1c55f48a20822f618a32bcedc78f61a09e39146dee00c988670a7909507cf8e2161303e090637bc4ba6f091ddc42adb3ca3bc3181a81e8dabb2b0506a57e2a241c8b337c00676083410133a39e898a06666dd25406291412c01210f1c3f9d7a3af4e44102f9f9f25383e64fa4383c2df78e4d6f5abfd40cd2eb87e3e9174ee74102791aa63e3b26070270a486b851881b4244051b59427ef5949f8c52c628a394198d599665998cd1492ab8d23329a5945fc6838772c821071c72e0d1e3870f72655d7e42da06ee8c4292c91397913078844166c23f5dd095af206c84e18e742efb94524ad9dd7252395b474a29a5f464a473d2d943e8eeb6f173cec80db149113f6f2fcc7c6642318b3176e5c145983b85eb5efc11084266f2e10ffe41350d88b6452d522c3a0d5baa39e651d7bcb0731ef38835114e69eb304831ed33af6258584db531297f3e0f969f1f05c16c4a69467d524a9d524a290a8db3490d4923c6163e8c31469619f4c3bccceb8a26638b6155b854878a913b7131c678638c296177b70b1414172f4e524a30ae89741aa1ba14a762636c32b495ea99877d74c664e91698868cb106575915638c2f96486e539d14cbaab659ae1b912e2d9d742e505ea4c0309d502995183256dcfb66b0b44083d6a0b10638a2489a6259d54c179c9d12def2cd72dd88744b272e505ea4c03055179d12f1844aa9c490b1e2de3783a5051a3540fab60500017001a4e1028ee68779e6933ec59a5f329daacdad0516df96d09640a95e103d686ca1dd530a646e5fb4d06f69d4e03459a35946101c519701603de96c64580cd61f214989ab394d6f1e0feb9219c26075199ee802853bd936d7344dd334ffcde301be16831006abbbe8620882728bc2a5743631e09c3ca5b38921088315060c0943d3be18560cd6172f525260c8ec30581d466723a3637a613299505c9c984ca56b329948a6516732994632a7201f66d0e9d5309967df09480d119608b2aaa1a5540c1547e5a462c4480180e58120527a40480c9594cdca2608ab9ac857140e2aa75b2a6a06106ee7216a353d19db52762c8dc20afc96e3c52a205f3b1d39861a26c7ab5baa57ed3b322403f8339a7063121f22df82ab851f974d9c915f4f420c5697974c4e9cd9bcbafcb8fc30585f7efb6274d1dcc58875bdf6b15717d711171f979f9310ab402ed954db54cab6202404923985c0e2aba386304c7cb58c544fb53df1892ed55f787c9a851d56c13882c5aad210191e5699bcba0c1156d12b2480069417c680f3d54f5e188390af6ef2c2e882e1859ee2851851d89d5e3e642793139a3e94c9f1314f30161192382384b9fad4c3aac8028bf80836f4b5263cf9c47c88b14a5ff8e26267a8faa955dd858b55b1614cab868935b59a563e2d1ed64e4e673899ebabbb502b4ef2d58550e862e863c3d458d731edf4b9401a207afaa14b0f0a6708b5c3aa3042b142ad5041305604ca000f0a8bfb10b542ad5047c8d037bad48f32368f34ed73f1d9b46d4bad705e9ba68531e8ab46ddbaa961a6dbd900fa758bec18206b6ab758b732ca185dec170a60353fd7e76a18abe8b2853056bfc9b88d421edebaa2cbe69b735dad34f03fece69dd83b2561b00a0179c06539674fb317c03cf30b509f8e7d323bdd523dfb6a0eeac9e4748bddaca5443a7322d9a247081c702b245bd8cdc5e7f46a613e2f2160618b0f31235fb71567cfc527c76b3bbd4e49647264765c7a826c5639867260e1f26a9815afee12d43032bc721de79ad6302ba189e5a32380c1ea9ab783370d63f1b6f1690544444f3750075a466c1ac7209eea3506ab1891af58cf571a10e03b58a579f59886c1bc7a7553ada6e92b1e3b075097e1415a6037efbcc8a08d754ddb5c5342068d8f1e3bee9bb5ba0cacf5d56578950d80b1baa5fa0c205c8d89cb8b4b9a87a8d5574fd9cd5132399ab59aa3761a6612a156384274502c22289f8a1af215d5fa8a32f2d5eda6c9e4b02a7479c9e854cd637779b18aa57e3a4428725258c7ca4696d0ba1ef31514dc58e3ccea5aef8d96e5552e494f55cb92f273614e83581585769860c1aa7ecc6911ab2290105a8f3916845539b4c9632e6c7b0109c1071f623a8f79cd24cbb6588539e67608ab1a8bc7dcf2d0261f5a228f5de143db93807efa9a4571c63e26ab750d5936715f6c6258b3c4aad4b1558bcc1c134622c923c43bfc6a1c2cab59181389248f10eff06b522cc332c923c43b14a31891e4110a632291e4991d89983423882b993932616704b9d1a3478f1e7d46902b3d0eb9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b9b999455861754fac6edc68c57bae66af66af66af66af66af66af66af4e961bdd1314f756b357b357b357b357b357b357a5139414937b3d57b357b357b357b357b35729304e29f756b357b357b357b357a8540cf77aae66af66af66af62c8f0d5ecd5ecba5af19eabd975e5deca7b80925e2941b34b4959469ebd7d26e579764a87d09e67c7682b9b59d62cb33aa2acee3944833c3ba52bac6862319b3c7b9d45dad4b466a9d51186cd169267af3f9a6b9b3dd6c54d8e6b965c1dcdd6b6b17333a79bab671f3599429e9d3471eebcb759de3aea221247f25c4a9ebd14c427affe7976174718945ed8499e1de5155fcc172f9ae58b3a6a5717b5e6102b891bd2a09413c52ab771a3eba15cfce22016e221a2a21d168bc562b158ad56abd56ab5bac8d5382e97cbe5ea9cde6956f3742b6bb55aad56cbe572b95c2e17d68db81394941997c5d3629f17fe119aad2ee25751511107b1d0105111465bad56abd56a75511775511775910b142ec5842209c921a2225e310f8bc562b158ac39d4e29d56abd56ab598c53cdc621f76318bc562b158ad56abd56ab54c33463c2de9e3923ff2258beeca84e3392c168bc562b1e650b7f0d0d0d01051d18a71b8592c164bcea139343487e6d01c5259e1be195d8f9c1d1a1414c4ea167e7901417793e95ed9923e2fc92c168bc562ad7031ae9f57500e0deaf1f20282ee26d3bdb5de950907cbc1723c07fbc17e82328c06d19e346825896b430ab7719e736298ebcf86e5340cf6f385f53af8f2f25b2783f6d84f74619f01c495df666aede30c2066689ab6b24148374e9c2975af1cd15430e208ab9ada0a4a92c4b5ac587b5e3a7751a83012c3aac82c2fa910920f5f5e76395458e19b3f242e459d3cc66cb186e0d75a49a44bba298c56ea3182ee4a90faa1dc1ca8171902849e6ff90804041c182ebf10c7e3b4576b6a0ef4c50908378c4c9e0ed9cd4b194953361a8d3ccb3239e2348d1b657284034da778a13ce2a9c3f0421e389e5da23c53b7503f714d6eaafafdfaede8d12d94e4a51410a88f512879e24d9f0b201d2af90bef272eab36afb5f60e2e78e29b57bd131577b4d5140c6f4f71cc4bc170cce5dbcd73e1560a41f1eac99742341d6b25a7715e08e4b9ce6df7a56ae8dcfa0cdd1799c9776e3f205fbd70be6f9ec963374305f2f507bfe96b22e40b1ae7d9c0e00eab464e2180f22387e1f9b0c15c477bcaf782e498c4092511ace4055ec8dfae6d317cec74d01962f8faed10c357b7a43b99f69c230af0f3807ded1440bd75d0af2ed166881f37cd6a289e0b71dd59c096e81f15368b73d9679c71466666ae19465f5e90a1464bae74ed069a86a93d42904ed93e7c04400f6e185d327e93c1cceb57b35a6bf6cd38fb8729e769e04ef7a8c519cca975ce721c67bf19b5e842a5163ded547167015be20c8d53faf6d5c852f08e9f0b71db2f8ae91467a6b7f48804762fd292471a6abe7d9be6ccdcd96cccf2b50f036d9bb3d3650de2c8ceb76fded35d886b4da738437d7636b20b35cf3cdcdc7eb586cdbbb3b1d2862eedd48b2c5328892450a0c4e676f350db3c2cc5399934f2a87df1934a18dcae17c4f5d29cd7e35f67bedff5e961745ef7eb450f07831b8e6df31c70e06de33cc6d64d2c18dc987d73698455da27b1602b5370abbbc9d4981c8a2e9bc7e0b9da90f5f67c4892e76352cfe7070f83db907539c4aa9077e6b639290b77733944bdd66ba29bd3dcb065db6603ab56ac0aaf0cf2b279cce63836c7619320f84d0af19bc4c06f4b8a3e8c4a7edbc298c56fb1c96fb7b75aef8ddfb67964d93e1d98350222892450a044751bfb0bef77e6567ae6913e1e65252f88929f747f251a3ef17c0052532a7d256f4ffbc26a81d54fade4691c8395cbbe8a753634c6060d394858dccd630cb9d5889ccca32ccbbc7ed208833205d75deb64989f7d3206cf959ef9dcaf5aa79e0f49f2707cc81f7921cb871227fcd10383d54b30b8a1f491edc995e7c316378c455f5dfa745f9377f5fb422bcb4bafaf2186beba8d18a315bc83083f1fba8063ab6eb529893a2374d0f398a77474754d0bf9a57718b5af5300e6d2695a92b0af9224904cca1a7848a9531a63acb5b29452bae0959bb0914552aa03f5385907f66fbee1e307a5b19b61fef0213d1525a9e886fed2317721ce54c7dc06ab76f8c159c09638b339e62e7146e3c7dc6a9efcd11d3dfbe8d957de4a9af83ad494f6e980e1d97d0059c1f0ec303c3b901b2ce179ec629815461e731556a9a480e4314c36f7c81584658f2c45b8f2b321853b833ffb8c65b7ecc920b9e711ed721f58c5517189ace57f79c84c7eeb15e7d968b76ddb6c6224195af18b8318949c6432f86a23ddc3afa1f621eac1d5158103ab78f4f8c1fc6952323333cb1a63cc01476baf9e2c62b0331965267d62d8c42636b139e7f40cfb64163ab81dc622250c7613e1047541b8612c22eac10716aa43eccc91c71a1c24b8f386ee4ad3305ff8126bb8da1ede516c6f723e399f219037e473ed3bef0d3372ea37b6b05f1c31b161a673ce713ef236c7dcee605dd7f90cf1bbcf8616d7813cb779e1fdadf342ceb1cab9c601f9cde3d76bde0ffaf59b21902f604ed319b6faa994528af90f264cae10b2e10a269c0429520f63a4cf4c29cfa904d2343118e3fdf6d9320b31c638638c31c619638c33c6202cf3170f50270eb6882b25bfabfbce87147a1eb8d17c8ee877c89e87938e1bf180bd7476529cf12157bf430c5fc35dbde462f74b8f919958b122d1903ac75cbb999be3ecf8c5193d4e6f6fb207e40bb38799d3ec1debb7126420a1f312070543598c59943aabef26df1e89621673884990927e217179f374f423186c97395287c18ef1631c3b51e6979a9e654dbf30353f1df419a72807e5bb9916395015449e6b045ea4d84193e6e7d82f063e44f91799015b800db4c8e04af78fdd123fba2871f14697241faa005571e443930aab4a71463e73973f60a35771e3143c3d8f7d9c8287c8c729788e78ede3143c391fa7e059d18f53285185ef3e4ea104162f2510e38d08937d3cf89312866a1ed698760d0ab57ea69e9612984f0f837d03046c6857c9be986ee91af361cdc08f86560b73f5c8a0cb1f8186309282074bd0e9ed9252a64c9952dbdea418c528a594524a29a518a54e2da5946e4fed10a088b1051a18ac8e801d3578bed618f235580c0e610de171d971d1d9f91aba1cf1d58891777d95916955999c5ac38741191d5669ceae7d355a3243be7a28c3f3b546cfc73e05819aa6bd200489f60ad2444e2fd48ac1edd36e45e130586d34b7d3bb770437f472c2940c27bf79d6faeea73ecbe4ec6c1ecae4b47519d6d6bdb90c4fc3b808c9e4b02ae6fcfcea3243645a3246647e647a645c3248be7adbcd258855a19723c4aab0864b125661417cbdf9d045890b931aadf7e18015d48ac71aeaa51c2003c5d32dd56578aca9e1734399d7cf5797f16f089720978f03377479b9c49ae9d4e994e1a1d6c6153794c9a9d152c00ff92e393e5f6b1cf9ea05d8892ed5674071a7d3eaa816fd520ec02e9039e6b12643f9f830bf9403a6bbfb77811aea80ec43b5baa53af6a158dd828a6985a855113d383118104508a18d45932b681bffa41a907d98ab81d44c0f1bea964a3d4ce8d4a379dec987c17a32d227576fdec97584c1eaa71f065352dcf2e6d9530fc3c8d5c908abe2a9c73bf91861994ca3939313172ed83b15b95e2eece714d42dd5e987fdc860555c44243162d3f884ad4654dcd0c5e7abdb225659af7e7ac596a7578ea16ea9cc4a74ab3b1b192271d22328866559ad9ab66d49b06c648eb0323b1cd775a3910c8fcc1019567421ed903a1b199d9d23602082018b38145d2a0c433630dc6e86f93008953819485c142f7536323c334d668a389f63a8144d782541ea10cd8c000000a315002028100a87842281301246a226fa0e14000c78984a6c529f0a64491224290c33881844082180000000901291191900a02ab68c34f051546ae191d4ac74ca3ecd8520a365f6a62b7d137999282253049c7ee8ddfba6396d7e7016a4a76075b875cde1bcb431e4156674ae0c44c7455f25e1c284cc5b2545f96d2cf9894f0eedb95cefe7cb8c945b3181d0de9f1c9e2f1dd52ec8a1c2a39b4664ae2eb5a21255f37ee59daab9a9436a74a00a1bfbe9a6bde8abf62a6dbd6d8f88ff81cb00fe60dfb2a5502dac0d349c2d5238b82ed47dd775c55897ab15a78b0dadac3d2d11eb30832a497f31b55d6ff4896dca4b6958a28d92e732153d1b367471ad0e91c40a6987e0264acf61fe2fc56caff0b53b5141f7d3ecbd0696639696e22046a00f2b700017833a8e62a819600165ef05b961cd37c1aa1ac9394d44a3813b43a2461783871c990517e0a1ded749bc40810b736814cf37c1c0c05afa5e7174398304554ac5f20a51345afe8793018ec98ec1f13e9b6b276a56113c23ccd463117694805e52a0b36f6a47bc1e74494ed2135bb61d58bce607094a9c63b5ed9439c4c2a9120162cf554d5c3019aa27686a6f0fee4ec6bd897903e0b788a30b1555669cf49a23189f1ed987cb717bd429dd30d019112d9b80228b5f12b9eebd66e9ffaeeb36b40e2b29b5acc6d8cbc8c4adef042b9264955c9673720eba326ed54d57c137b0e846177733b2be5d2591cba7456fec94ddc24b71f31d6138e35d00f50fdfb9509ebac78053a769ae4891bdcfac21cfb300810b117b7fba34d1cac924e0794f3e345af73d3eb9140ad7306642330c8867f8041757d010b78c0bcfda81c622e7732cb223e2ad0d25783d307a9b1406494396795c7eaee29529374998ab76f40d44636730f3c4d67d68147460bfc053f835554ac209e006479593f82b6b5a0b5eb03ad2ef58c6975adfd5b2492c3f4db33d5d53802363e49a78425019840f93902ede148be7b2a495ebf02c88dbc3d0d061ca2ca5c8db11f0ff33d7a447d64ce9c43b63ff40c8320deb37e90114a5862087d79505c12f1d3ec21c81907f371f9daa0764081f1a5c572f20c86fcf033f4578b6e0a4ffa36885fe208842b741acc0c8a419217019742ee656fe9dbbbe619d1441560b4fd7ca78766ae8737ce446508118da11cca7dc23b5ab50f82e1232d9674fecd24f426d02ab01b2a50035ecdd0eeba70caf884e82dce01983a1eaa777aa3d743d93110cb46b4d0d71359b43d1dd5e12e7fbc4864b3b5ba86d7e7fb3cb2d05d9b3e0b36fd9b0de36c0302a8a79f6677974718de505ebedd49449a2cf4a1c31b0c14a023accc0867d96c507c5d4a153aacfd6c4300cf7562a9e95811f5917055029d3281f52b8b7af1677876885d83d5ada05e5a8d620858bf96ca1a328a6bada37fa39012a050bc1593212fdd94d5e89f8c9a875824534ce3aac620cde669307ba8ff023354c87909a702c4696a8c1c8b6252483ae586162208d90a8f693c498233576c46a5e82afb3459759661f6ba7b4268c27afda0be3fa5b46516d39dc7552755fb306012ae07e4af8c6ea4ca13ac68bc635e2231a7d458dcaeb03f0b35811d01499b9bddc4020686f88eb512c7646260788a95f66466d1111db53081a200008b1ef30f5836fe48b0d1cfa73c240d4e2af6b085bc4c5c1d3f59a0d098843b1baf70ea60309d2009436e088e224a088fbf38c7793c01558162216372b9e5dacb7db97a8a3875b75351c97808afbe3af78bae042ae1c9bc5f83707b6bdea65786fcd39e5838d128851ebfec72297c58e1c215716264ff29fa0879fdf2c78e4aa45e7955d67075882df348544534742410df717ce299d1bff487885d219fe8d3d3ecd63f1a059552c6479cd6f9b01760745514e03a4ae4e58044586355334a69164a71fc29c4fca5a4dcec168d2b56a3b2c48a0abc29d044b11c8702bde87ded7e722dbb09bdb344413f61635e0fbc8c7964ca67cf00396398383973123f3d2198c10ec12071488cb8b06a00cb62a20f07db3886ac3b2f81981c03d2705485ed3f17859b6bb22f305d56e72a3c22afdadc5105fa516b17fd0f749db599d10541628841cc6ce126b2b14d42ea19c9cd3007f0eae54e1c52669b1300c77041d52a7f15479a5f106cf21b132bbf424e7b86d8294d318beb44ad6f9008bbf1592df9ee6fd6c6da292b8a1bc2ed7d4a325b7eeb446313fc88e9abd42c81b093c27e73edc52d45caf0d758f578962544550bd7088e9a92e85ad43a02053822e8f19b392bb46305318c890100a78e996fbb89c0740302c4b40825bac576339f393f2ea2b85a070c89dd1f37c4804a4fd8b3641ddd59c3cc8abeaf7b39c832ac7b86185654bb848d2e875cd636a0149df08dd33091463df823db92e1eb5160e0455db54f0ca0dacdc182cbd79d2cd5e589ee609bf470b65c46a9ed0820d45d51773efc1bbb76bec52d8c4639ac5f96ed22f878833ad1ce8154c6d6fc234b4bd05a0bace7412ce27c511bd90439474963520a94b291149a89a5ea78099f8a7978b0126562ad5b14aea2362e05ae9c57eb480b7cc6cd3bda482efd45b4d52141008a1b2d0bbcf46a1ca36a8f4b0ec78191cc2ea5d10b85b99bbe91bb33d1025b5cf741f40ea1bc6fcbad87aa3e2954f61c8ac0c3acb56193443d37d0bc4a32688f42ea6d95fba2b040f2a902c7fc3919eec351d53c6ea4a7f55a3c61f50d4a59bc34433b8ab705eed2cbd8eabc68a52645ea88f23720506341c8416f76f59d83e67279b246b44c5562326569922d183da3f8d145639c34101b264ac5c475232037845a301a34ec14e128518f2926a29a741c1930f5adc6e3b7bd5c40b6b1ac92d69d3f2cc4ba57676c2976ec140f6bf45057272a771911fcf132f7aa7dadf67282a37820b592b76bb6f2f2bf42b58d296a908b0c5808665521a78a952b0dbfd9a6aedd162a0cf18a8d613353f944b8f4d8fe7f5cd70798d7d8a026b00bd559bf3c0b71681dc40b66bb499a4fc3e298cc673cc24dec01bf929985dae750d7feb9ae5cb733d69a6804dcf20b2cc79884201e9b4cff033d2db0173748df05e0b507724dd2a2029c4af7a349339a83bf4c62e5a546c995f888676f0f1fff5c223f666403e6fc60c5d5d43b3ca37ee0ba0888af01b3315542c890198a2d0194903fb98b95c37aa9e93001ce0f902f24466bbc494f285fcd52813b704a47b812665cf52964f422387146627c8ba3bf0aa26f630edeaf54065bb428f730277556f969c3b71795478d298e363c64e72066ed26f093e4f43dc967d2d1c38d075e975b71e5b1cdacf52c19e226cbe0448801ed1f5eac69cc5948ed482c4ecd48c8a045e66d640af3d967bdbd9762830b276321f510aa1842f507d09a6a1fbd81c4b5e1186e285c3f0b3c6bee7ff00c56667ce04a3eb545eef0054f481de27c475eed38ad1112f041cd08d658af266b19a04ceada1207813c81549c8c0d6dd32de2cf732a859ee55fee41fabc4418144686e054e5d3f1f805c1be1064a9f29bf42ad911e140b039539f9ba61bcd7c1980a6f528055a0717ef89b7b89edcd36566f5a44ca051ca02e7ee85a01ef9eebaf4ea8932ff5dbfe1342296820144278a2f660ab9072b89e535e0dab4a048f61a339c48bfd71bab9f462872fc48e8d3ce07557e52950f5e9c800ccf174ba06010bfc2b3e00fec0c7c7816c72725f1278e61d7adc09b11a64c300595383ba28574a5c548d77cfa5857c0c7ad9799966035e19c56fafc6960845000f24da4f43842a30957ae0902de087707a2ad0c6597944ae1f63f727386c6f58781bee83da8e3abb798f06863d0695f1ab8bd5235dbbe2b26eeb0952b35c5d53f4d3acee4fb3e8f67aa52d0b52e7091f192ef3266b5c7ed9e2ae689b1ba89d76ad29a7604151ccd0d15d3d5004c898d24dbcfa306de73b41c511cf1a9f142d58d68da0ea983819a8584d7d9d0d2f1904a50a4fc049bb289974717bb45056960f9b4bfcaeb4ba86017f382e9bbbbedaa6b26b256e66141533cdfedcedb4b6fbeb582b959595868524aebf593d9d24b7446cc327976ee720809e91321ca4244cd809c60a9962153cbd729f248e00999324c03007ee9b25332281636935e366fbe743cdadfa14c672ed7d6ce5a93ff131e30d20b9ea1c98b7478ba553c0e6d8c12bf308516cf98fd16415fcf80accd3b775467cffe0a413c1902ecaff809a97e509b48751fb8cf8835f8f58f1ecc5e0b212a81ff62f5f0eeb6b7b700ab3ec412879c75e890c1fe9517f7f8715b345c0dd57ed988ce3f99597890dab9ca188788246a1e2c846aaa7a99543a0270bf10ea391d82217a720af000e4daee166e077a2a9519e94fe96c0891d09b51388b782ed378a4227a1c1edcefc7666517e06513ccafc0c7d5bc1a8d12218d397fb31c420c968da717fec86e42490f4c7e346249ea3eb2276d33c293713fd361af50ff784ec4e271bc83899834db37056da7e193fb29da4a2c9810198966645a1470e4a2f8340cc12a8965514dea0b149730df3b61950a8d722220dc431b8af150e0d5270387b82c4121521e1d57523c62bf692e7849a2f0b70e438df0ec981bb5fdf7f249b0245fb80e4db5ddf2c0b816fadbca72b293cca5b03498e91046039e7c00e6bcd91baa27b17cf2e15d7ba247fbfec7f069d1184d223133f11b86d9e1258f0d38167fcf87a29ec46803c1b843f51276052c05ecb0cf8ec1253c31e8a662b3202b1f5a9fd74d237214f96294bedf7f0ffadc51349e3a1c58a0e1f7f3c90fa94f2262037ae329a00670a0bb5fd3cecb12c5ae37b96c9061697ae469c51329ae29d02a7e352c2198e009c6c8c0dbd4a891ffc17c4fd38bcd84072fcf684b3ee41582535e1e60c1ace5879dd47339844f98a300fe389f38c7912976c464f62f12757ee1036432e7c9b94a450b3cc0ff467cc6c7b49fccdc0584d2836564ec0ca5ee636c40f08b3e57e333ab319fa30732a8bce0366a8d6376b5761955b16b29b697803d976e32d9048b3d16abb52de7d694e2af773f3ea4d0db4db3afdd503ffe1cead5250be5229ae68f98f8d44fff31268bc72eace5cc970f0eb2d7312f6ad8817dd68f477334a35f104016f7b64550ecc77a05ea5bdf8de39177544c5265c8a5660b0f03182c7bb2285d7de42d5f240faf6a4b4b8ae95f23897030348d45d0c6eec3dc5a9f2dea2b0a7112a8a0991b0048f890b91d807c0a4cc0d6bf478904f55852534f98c7e5e46ce19e5490e89f033045f36b2b7efa4796ba624da3b3d0d9ea7748487c5e8aa19ef1ece077b616b54e8b023ac52c380c04284fdcc1a179abd5624371e43625dc229c9edb135f68e6a28ceab31e5ea334971b96502cf54c3eddfca26af813906e81aa65174979f45454d7552a11fe599984bb6c2db77d40d34c401e70969f264db7eda4a27e4cd276b1d6c65f0a4e09e653d34bea0dfe743c729690a4a4a02dcc94d18d9401951b9e78aface00aa3922c77b092e0e8c3476c07652120c5160a315410c4391686273afcd755421db70edb9392aa303eed8bcb25b1b64184ec8cc54c37a54b0f4b1a6bae109722b148fe54697b1acc47ca528fa7a84878824c1ce8e92a9b22e286b83ec670c117a662627369e424cabf484b009bc7087bc3b12ffb1d3c007130f3b99c0dc10fa04b94af287b2e92fec7cb63aca49e90baae29436c6d2462852ff47f2d0fc1445538e2d5c2970c9c5c34ed179508f5054460895752eec34ce3be86beaa3fe471b41018ad7204605f24b2e6a68d2e4d2cbc48ef4ed3bed4d39386ae45aaa79bdc019b458ff472ee4e0090e82840c5e90d44f00114667e6e8c21d405638c9ae88dbccc138465f0de479a12a47bc893ca1def00bf22300e52f28aaf1c271d35831090a0b2a07383316675856cdd5c9a1ac7460982d3f05a88a6fceb2cb5c671335e62c30eec0fedfa03a856c9564f1551c216a18cfaf0162af7425cd606b1931b61c540642bec39ab89de170434523d8bfbe914db2a212a95a9c515dc99a357c69f208e22a5583cfab1dd6a1f731369342f1f1ce0f35b59f6a2ba96bfeca4fba53e8b2723569f2f0a31810f4fb7ce071ec410281a7bb462fa3ec036a54e2580f39709cb7cd3c98d1f9adbcb5c2b3f7e31f4b37c34eb19fcfa17e3141c0355abbb6b2ea03f70721c4f9c8a41f7a46c8fccae640d7e598eb622f31d3affcaf40690949f684483187dca59c786c77b63105c6001eb2f5b6c6598c8e7af4a1b253b377c3dc2af29313aecb80d8eb9efeb8900f1331440c42259fef29991c177c2bd5b498915940e399df8555c7826368867c600b1c071ea1c8aedc9fa164c0f22ab404d66be7ebedcf8c9b1734dbb555e3400748afd29d2691788bca989f66b711b3e28a834e60dfdc3a60ff921a8fd7dae8516f19c1a09cced1438524a537a138843d5a5a9b536d9b05084c13693b55a0d9def9e62750b49645607fc2ce3c6333a881029dd65c68d423ce9d291411e03442aef2db6517c059a71efc452383e21e1c27d0b8ede31e50895dc927ffa9cfedafef1db758014250befc62c009b7cb26100e14777f45500673f73b27e09ad7d0ed4defba1c36e02b7a6cc29b527eea12f436cf7e7ad6b92d8374dec5e1c737e81e320f5dc429550695f5d37a0155fff2604fe0851abd0bea2a80bbe88e482e5576977c42653f588cd45b147fb40a8c6d8ee36419d1c868ab6137856e76c77b533cb2c2c26181872a2d206f5bef4ed9b94e582d91ba7789ec1265483e2d4ec9606e3027b085fea5984e159bf8977b965e026cfd1dc5a80b89854e6769c1680a568e1812c3df4eceb6a337d1b82a2dd30ab2c1f490280cde47fa0980d7fd211ecdd20fc894eb27224325e6f6068390163a21b7fce587e85d2624eb3c97495a9d12d465444dc1e2f8091f1bc682b6463529befe197750740142ac01f2e0ffc87d26578887ff9e7ca0608e43b7bf00b65285c7a72b842446f58214545aa94d5ab9e8554ee35e9bd449ed8980301fbcc2b608e02bd8063f2626242adda5582a06b7fc72944af3df4f50cd70c48919eb7417d32d228d02b50a5d8a44f65efa03a13337aab7eaf8879a7f57e3735718bdaf86b66edbbf73859cec474e0778f63202b0d5fe2b29da7077b1c90421d82713cbc1b76fa12562005fbd361669532cb57bbd5a4aea1963d99cdf92228ab71c496d2905d87be9a5eaa0de2c405b6acf982915c6fe2aa6f1c77247ec8c5f1bbc60ddfd45d00a2f6dd6d0eea939fdcdceeba9d1fdbf2a9171ab1a61366fe08599343ac2799c66442ceb4ac1161f3892e6f7f6af3d5020c07f896fbcae068acaafee5732b80db325160a2868b5bfa6822b9450d17353612bca3480197874b657da52565ec06852975a7edb43e63fa90ade386eb1cd154d416cc5b74a1ed62ef5d7cb198e7d7af79cad2828e30c15ac8c09cb6c08430b2e7110ff95e620d211ca7051dca54e1561984dd98998eee98a5e4bf79aee8d228d10ec2d6f6fba93662943c92729342121d60e8b1d00175837a9408292bf17c2c0519ae3f288d606880598277653655f1b666a5035654ca7b03a5e5c98ec5ab3b8fdf2b61ca7b0b2c114d51368d15b0179bed4b2196e60fcb67efe80c174d963bcdfbbbf08d1b0d8385b6d93a0000466925fe60f55b50fcb51b13410362326fceb163cced4c3792ba59ead0f436a4faf24acff650a3d3edefb391718253a7caf98ece0f3c659c4ad897264b69148b848cc34fefab6bd6a238c8ce1d623f018b911422e88477155457b8a629c111e07bba3019d0b10e507034d118a7d09d68d1796340a49afbc61569be1d5a889c1bae696b56b3092dda91121b5d126c4488518b344e3c4c83a63a77406de7869b3aa5326e71ffbdabea3722c389a449f7c045fa128f01c94ccefc8f9b4607351fdcc0506d623ec3dda6f2c9752a5767b6437c0af1b16ead053647964cabbfa5cfdc052125485bfeb9139c3e749f477fbd42b81ecea1261f13e6fa5bcd8be0a9e5e0a99726bb82c9463f38b080a7d1fecd3d157faedcda800f26f405a7277ad2a324a321d8209df5f58657c2945153a05e9f8535f610f14bbfe2723f9b8592c86809c46ec32b112f993e01b3f0e4c24f7e08ee2990dba846b5f9407b33ed4553d119860c042f2d9f947040bb9bf2164c88d901fc71358643eefddafa0d4aa4aceedfa2711f3b2fdf4efea48cd2dba0836b740bd6ff448812cfa4a79a5e952432049e84b7ab6e74fa0faa07861b6a94f2f31ae165010605b42f1b1036a2bdc8b145feb8d0075e8504d76c5763629f5e49e77f6aa301770bdcbbb15549dfc25a8d68face7e8094f928b5fe56682a1418ed3eef083ec0dbf809a35f009d4d02994a020d947fb379f9104017cfc781c109bc0243b45254bc19f2ea43e6959c38b35acc718458e3c509f84e004f618c329ae542029bb6085b143548e68bd6ea3583a1180a3bbdd47a2006785b95ce528bec3cae19f40b1380891e33b109395e3f719b425863ac0f68127a8fedd8c6080799e9de3e834db296e972788e0552e791a4a4c1fe0bfe1b9d0fe1d05b7a671bebea9e86eae05b849e36dccab19248534aa48fca4a06d1d7abc303b423d9c725d6f6c8b581f371b1e46e9cf83eaeca82eb311afaa9749e1d5e914f6c94b9cc51b6054b4d67efa007789ca93abadf387a5cdc99d20ab2ed02dce3f1279d351464b5a65229b10222c7bf47dedde058599efce02b5e7d9ee9c52a704ba8a7ebb3e52eca39efc45f4cc819d3f5637f7ec208c3798cb963724004b40b5577e81c20ceebb538b7cfd8c095c6875ab8bda08cb713aa79b6db61833161e1283954beef93b5e4a0ce08f1b3cc8da8a254bdc2e3ef7335428565b3630ca10b2c2adf99b46a7b95bcb48a798582b51d08d906964d3eaa3dca448627fe6e3c8e4282e55e5f2d0fe8ec7c2371deb168a54598b99f0e808b9749e9c08c7223f410e54777e56342594c96457d6988819792ba658d8efb751526e61df36acd9a805398eb1ac67a82290d7719c31738479d44dd825e91de36ba7dddc2cb5d53f74bd843ab6cf86b0a8cbc0e6a96114891963deb156514c5c14ee177e3e698702f5c6f4046e74f508f4d6bd13d057eec510d811d2d77127d4d7d183f08644ef4fdf1ba127bcd1a147d8dbc88d0edf13a0a37b23a09fb8d712dc1bd3217013d67b36f888f43a6ee6f58cf49ebc1bd918bf7bc158826fe5869fbe521ad34c79a454852a85674c6238f41f1cd520f5f03006df1c83ec227880e2919e46e237b73b036e3c7e8f60d28edba018f4cc1907bc894c0f32eb1f630aa8873a1fccac3f8a09502f75664639003e260e412fb7befe3e833613e380b791f981ccea63cc01f552c70798f5c73103ea499d2d8057de87dba764d38d7bb82b48a2ef0ea81c0de6e301dc962907f89ac79b01e8b90e6cc0d42fe7c5ddc3de67d066621cf036323f90597d8c39a05eeaa8623fcfefe24ee9261af80b9268bb019aa387f958003765467e16f470afe0e7e861f25e003765e1cf6446106848fae992862433f589727b4310fb18147581acecc7cb41adf279a733d9a38d4c0dcff38d643993487ddeca96a75e13fe3dcd3bf38a0394ef17b6269c40f0cb5b0f4e6c438f47caf2b24ad9ff059c6ed0ee868fe438679dd5748e0e20f16e103adcc992ba47732f4df339ae78ddf7a4551beec64dd9d1c147b6cc5d49a03cfbb2fc3121949b50ea75ab3a41e9969abcfe4602057f4324a8f43552de5bd4a743d86cf7c2190ddf7eebf00fa6205efd22f625c674629f5705f08412d3cd6dd66718c306b98341b7e2abad6b744600f1c76c8bc3cb4e2bcaf03149262027599c73588c59151c795143580e444e857caf278e2dcb5d78ba3f4012bd46254675aba42bf24667a352e8381226d411acad468f10e1eaabc2a540b59c444789a308cafa2bce07559cd159712e4e662be5808521a1b2143e4cf3ce5fd74f02089f193ff7071aa5fca48a290d04408a19714a0cd79e024519dcbe99712005eae5befaa33e19d425834b12866931cd4775fcac8b21f6078a88f51e78feacf0591e8391dd87ffd797c9ba32503d0beaa77f22a3cd606401cd8e6ac897a4efe5c9aeb4e176545712f99a49d0175dc2c984dc2c5248713dcc813d6af12a2a4445380de1a1ca465b739b9e4aa496a82918e7eefc1cafb5faa3c0b644dbda57c5ebc8082614122df3ce0e01f5f815f0d5a74f439c26b3a0331a0c805c3bc00a23bcb71e5abb643919d7c08d6c1b5e6c0dfe4427ce108c3b5b6408ce9463c6e51e6e4fb1dfdb1375fe6d3897382f85b68c4bd873eb660cd03ca19b6ad1d3bea43292892400c6d372ac5d721c33360a567ee83bf8beef8dde749509cb22aeaac9e800a7df2aa1fc0b7ea3d4aed5120b497ce3a06479dcbca1a22ebe0a7e356be924563d7a4a1da34031456aa3354be818f4357a151bb1acf1505165969ba7864088effeab407ef4dba4c20ac3b40e9ba2cdea650cd89b1f2134a97bc066e86d9ffc575706eaca809794a11a4bb322b67f0ae322feb323a642e3ec77fc63c277a4f6cdfff5cbb4ae0ca8d69ad2166c353599fa2968da65386253d948f2445725ce891878c70c19f80410fac046f939e1c809d61f8d42394c15aaad7bdd834682a0a4288c1d73ecf30cc355a45c431596283a119d28d9498ec6c59f97920811bb59bb5a4d06d1a8d1004cc52e585eb5e3d06109491828ece1b76874a5315edcc2bd7cbee72567919c40eb3d7f8b968019931e46d0a849a16e6b176e685fe9d5d888b8f5e46905b0cfd0e2d6f5c63241ed49921ed9ace540185945b1ea36034b54a62c09e43338808b7581366ba9e948c401274e14394cb5ffcb890b97b4fcd82ce6c49d5cc8585d24b35252422069f7a790e76b015ac794f0958f2c3e49eaeabed0fa6d16b68b553236111805e9a94c14f1e303c1fe3cef18298a73b8e89bf00f7df127f91cfd14513db5aed4f1c6f1d30de60c25c8b3c880784c41448306b4b7e987f072841e5b77724b0cbf30605eeb501d8d2e73d6fb569c2f0dff974cb5461dffaf2bc3ba4f86cc45fa6885f37488ad6175aa143f7eab8c2efc98c4e7c83e21db1618c67ba4b6076b367d525d9fceb351afc55ec565956f8090a9090d4d152c41ec3b6ed8321bd788e3b6ab075003740a043f124ff118527430cf0539aa229255e51cb8fb2fb68cc88f7ee7d99f7d92674c60d7219f39a87cc0c9b50612e0294a940c7b5054f78c70cfb4e426db918176010a006556d70d75677adc0b74cf0b9451285f5d66d7cd50c060e7073f66176e079e898380ab50782d6f6fa720bbf19137b01eb06ce4532985a06e20f9dc294bceaafe0c4fd9cb6e9553359444944b0926297d0c61c5ee9a28ec03ca6fd6f9240cfd82aa1f48004d0e583c4d6ea12c379124a01ef5d564d6743fe5c9e664379f2dbbc64a50aef67ba19f38ffa93d2b52153927ded45970fef7295c1c448e817645e60000c1c2084b11ff636d83e8fae08bd40da260448bb9ca6cbe5cb62d9045254330d4a082a811489220034b04a41545064e7182d31abfe2364da80e31c606304683b4853c3c5b860686e26e6df509e00e313092e78090efa12c73a0f95772bebb6099c4afe1aa4dbcce82c933a5c584a457b4bc5dd10cb98c4007a535b17e504ad6d724a68f171407bdc55848d0e8a1fe8e8a14a527e0b22ab091bee35d64e9e86931e70c585a5d238418f7a085387f2792d4c1519ac7192acf8f474b063d1e0d004835ac3f0f7e806dfc6855d263399246f52686100e93d00f155f851890a6d6b5e5a85a0ae11ba27e83f197717fed9a09d7073bdcfe006d1625d0b331125eac04d3a1cf9e1a250594e382834ede15cbb0ca3fb98e3f0bbe4ffce48ba10130437920e964054535b5d0c3d6230dc8b944854b887278b3e529a0510dd17842c65fde963060dd22095eb77d3f20c90098f7fe4340d5977fa11accd78105b9aea5945ba4549d135bd82b7b0c41d4909b465d0986697f05510a8428941bc1eb5795d78182d76e1f31d30eebeaba92e3c971830b055596a832713a84522bc2ae886ab62e2a3eed5a575876fdac3e7078d3115282037f35fd878202fbe6add0e2532eccb61a033e8b3db914524565cab5705ff1eda7ac2e23c4c3aa224ea1f9c4a47944d954c072011e41b41d58c823c5d6f0efb07cc0436444cd08da6865e5e1ce63a0bd22cfac8d81c603f5f8d22fc6b2a5411d6bd161f2c04410e42d7a3852f3f0bdd21fa63102cd3cd1ce22268a081a629fdc4cfab9392d675f4c19eb1b4e32b0e51035ed471548454374a06747c962dfa66a26d0fdad6708c72db3e500933b15f1d85badda750a3cbfb9f7e4d6b2ba8f6b2b6dd037de1e6cf1b23f00d3ff15c9d18c457684dec6a22dcbb18e91d278ba17723632779d87b68a98faf4d7adc5ab6abd6aa52960b8810dce184c6428c9fa7e6d5efac402c958c517c5466b33e8558b6f7978e5ec1bbc2040e19a3a61f25ba16d4e618293a8d8ea48cb3046fddec41cffbadf148614db1c96f50f24a62c5e1079c6848297d7c6dca1cb234475e40ed4627e6765004fdeca9f0ad487d792a03a15a6972f03eaedfbe7570cacda5d24a60749668a081efd65e4dc38157e2b5f3dc2c93b3d2727ea0c0df722fde204950451abe3d0c6df508d87fc62a124436f55590412d4754339015a95444001a9f6965fd2f51f43dd6308057abac751ae261e0b0d1ea60b7557b47bbab10f0e85d2a27485cc5bc19c93048268272c96d82ac177fb72be601ab5b67a914d9020e13d5e55f84c87c77a59ffe47c28324e155e319fdefa9e402c3de15a044468299e541564b70160332813212faf6778aa3afb7e96ab632272224991f70ea62f4106fd815052420a891967987a022e368c70f4bc478eb92ccf46f518489f5dfd5297cf62417048e9e42b99f85b4308cd7df446207ddd22501494d83c4590f6c422dd41a114dab53a382fcaf02a03a69893217e48ae612f9984a511b4bcf0987c6d36a54002c17e49782362ea71a731705b4d7054a1cfc89a21c2abb98eb26512a89d702a6c391a0f6700da08c9ef2b885b84b4d331c544f00654c86305284e2474a07e69b9dc5514aa98d66672cf9e3f9fed19c479cacd0e3c4516ec68a90ba496a5d612b09a0a1b3134e15654df49528cbb2030454949159a26ab6070b1eec627e7daf469ee262c072d0efa0128312890d2dad16b264b4a715c1485db2fcf41b676b072bf961a0b99f761050efcef75b9b8d4038ee31b411875b7ffe7e3c91b0a8d5453eff15f4e8a6daefb45ecaa1c2c645cd324c621827a343000c1709e0afe1d41036e5039421270994f18167bf2faae6c8bfbb4b2cf35fdb6a880451e467a4327f8858253c700dd69273b7b87948ba3d38838377e676db9248fb541535c3c8c892fa5746af716a4f1d294740b6078c25b26849e593a62c8de4ed32221096e566be0a77a1b8d0d679b458b3d0e2d1ad0d648794d5202c1f2480072f562910dc0aa81a25a0ac75c222172a941275826d0aa534a02e38efd52104572202f6cf760e1bafc102d13d53b2da1f2d98730381d955255d3fe1e33c9ea9d9d54d78c37d56703d5317beb1ba8010f4859e010d5395137eab349fe2ad63362ac8d3be3c4379d65c4960ef9662f6b499bfa38ef9db88c7a6e659c522ab41a28b814a4c32f4076929bde014090a93b7088237315add7567052c69a83372a24b19855431ed214a2f6e588b9e74b9610e8a2668e9781db29ca5a866d886b8f07a4ff9f84eac2730e67e5ca22b35ef237d37c891ca25d133c8d3ab828efdf921505e8eaad03dcda97e5003443135d960c4a8897eaaba8960d6036aa1393ba040b51a66ffbc0e915ce2c67117bd5c8589145345be93efc3a172c15c78e5b0cea83e76f61e246e29b2541b4a8d7a904f57e10f63d6a43f74e363540f3b45d8d1ddbd46307e3fdc4b2b1736c8d9468e34083d8156458a1578351279d472c25d834bc1e99a7b9a27de19a9e36e6a929e6e46d69faf147c23232f5ed47362fa6e12c54c3720b5fbfa32337a8575736fa04874d03a8fe28ddaf76bf85f9c5821fd19ac663beae487eeded11cea8a5887547c06b2abb5ffc79abd9c4e3e7cf80aee549bff034940f9c7ea6096954f24700bfffed9d1364befa7485a085c6c5c2cd3486dfc6fa652c2c7fa14d61aa0cfad64c73a32c9dbda72e8d775361f3b4682cc566c7e3d77187c3d11990530c3edcac28dd82d19b4ee3b765ece5c17c5422612ab8cc40c8e6c272e21488da3c9a497abf15b1e6eb26fa1df191b7dcd1dc9a2a92b8dfbd2ec935bedbcbaa2245ef5a09394842863cb3402c64540a856c0dcf444baf52850504884e02be5b075bf72dd586a017cf62196b1b6e40bcf037782e14f3327a6b5414ab48c61b54977169fa54ef82b244d3ca02ff93fe3818f9730234f6edcab36d8c87cbda2e3f620fd658bb8f8941067df6077ad9696c0b203300184f011be2388b5699f0ee8983011c95488b3af7ed85a521211713d2520b04acdc9c24e27a14109f16491831bf24b537f0dbafc56f90b220e725317dd4bed2046b3605025619a7152d524b082475877a002150cb88d73a7194ee7ccd8fd70ee3205e6ed9d5b12db943f2573a3ebde88d0f5f68a1c6b08a8f9941f3dd810f30bcffcd6c7b87911d4cacfc2907221e258e1cac079df6408f38e7f1f4c70d640dbba159d685bbed319a007581a74080f342e262629bc4d407c9b07f1ad9039f250e3b3a7caff7420d1ca365410d4474b53f282bcc957fe17df2c889dcc15f97e1877ccbcfc30a8ec656fd182b6a5bdab34dc2f6ad033a7e40894541c2ef1cb901f4498be03598b6dc4506660eb7a3468e5d1915c1c6051180bc1bbb988722b6c28364bc15a416eb0d7f315e4ff1482826dc5383d47cac656ad366c40b773ed5a7d1add6f2310830926c2ad6489927a8ac35085942eca4b5369d7400d72b6e8eab7652872643423a68ad466cad66566acf65a1da7052240d49577bc1c83501b8af838d26f43e01bd5be3876139fc030a4c7270715c6a89fe9e51b56a106c7e50a3b5a4faa2a707225399aab3b6638beef0921ca68232a80fe551e124eda5c394fbcfaf41050c2908d9b604dae9a5ffd24de1e9a6137ba9b07d7eae76df041ca0c01cbed2bf8e8331a540cca03d9e1d51bc9eb715be3f7de584b68c78549e16bd398420a68e20e1e7e3157eb7cc8a7a53952ba69d6dab9a28429709b272d77d1ff2b3a283f04d79456c8c554256daaf1d86c8d7dba4f791aedc4a521cdfd1461d7cef51a56d2c0ded5aa19f14c77ca248405fae9fdb4ea5e0e48b58df1997affdfd4ce0a14fdf055302bc60fdf9e6e93357174a90a4f9d5eb2a29743296d022381e597edff5b66f21ae117602f0a53a943212c89d7104d3a8bd97a8743fe7a6e76b259a18459b3f1cbcc7a1c71848c774a9a87c4c8e54af68435d84ba94465d021a61fd305b988a8e3c0091d7cf15f0bd1bdd0b6a91d2777ce22213f404de3183b0135121baa8265998d383762c54c57e4d24d2da96e9aa778bc41b648cf79e5ee8005569b7820e05362ca8976d531b8342f048e4a29913a94e8c711b9fcc8165b049c0627f2cc4945c0125f4ceb75693e3fdce0d56d1b4389851110978bd15edcf3611e6a09a9ef40d2579def28513f19cdbed1464d26b819c66b517404cc1956114be8989f19fb461b40bcf8034ab21bf6a743550f3d06b976dc177d42701178cf0fd49144150b747c297da677dddc3a34446280da3d904839f82cba2c7b014f25a63421afdcd86ac812932c10d36479f74bb3a01c3ad121d629d16386909e2c051279f0c14482ce7aaab6ae46683df64b547fecc026bd2643628aacfb5b758c479e39eba1d9a409ae8166100b4f53d13710296865b5bc6b11e34cc5c71daeff22bd9c07ecca20a744f6574103b7bb92392b2938f14299e330a16c3a1910bb52321160f96e1534954ab018b51807cd860c6b81d6f5303ecdd152550715e18788a40effe4e6e76610c96a1cfcb5c924ace0e8b1ce8ed7a3a06b0fa7ba07081c489758489b078e317cf1e7b95517fab6cfe5262bd3aca7636ae3b205739b7ee808ea71398f663dbda3e72b5262e93b6373e268984db9de77bfacac9700e31e093c0dc522c3b284f028004ff4f45ff63c5cbfb4cd4b2803a2f635f7fbd7fa5c0375c589683503a435eb3c585b4e4d69014e545a7876dbf900297e177f4a573b895c614fc02d7fd21fec683075fa7026a5fad333130351e077e59ab06a3b5553402babc1dacf00de5f0bf31161ec06fb496f5a5ccaf1496e62f3b06ea879a822285d16851cc8044306af9e21deeb663d3203d395329927e151d11d7b168e5d940f7a247b49c833810a57052ea5e81144f0e7d42b36092bf50ef154169e314ef5072fe4d33ae4da98dad290bd1e924596e4aa215e563663473c4240b70c209f776ed4348fe050f0f2b32f92213ab02fefc600401c0d881d8f1a4dd58a8ba79cc4a8395a8fb0a0cee3c2862e10f4398a18c577a79386d83cbfa221922f3d6c94d71f60ea6e1bf14ddc8a3b07d6b3a4cea92054ffa2c98b6dada072d020e3d0991f00a64437bbdd05a3f56b049a88da1f31bef1a4a1de18d8690efb053e247381c5cb50b76c5ddbe0f506ab5c0ac6910c61d222db47c60d63569e3a77bbdbef4ddebd4afd916ada6f85bf082400254a78454c97b05939a0db68ef0cdc2320552df468b4db3a98c1b805747b4405592f1212b0818ddd82d584c9566edf6b46dba602680bc18d07c14644c2bb274a00410f773635d16ca7e308042901a944aa9b3438fff707720d3f84b34cb2a239930c695368989b827814070b1c83e0a0d012e36fe0aea734f672719d7307866eb3cde91525aa8b89088a721b586d93a10baeeca2b503b4aa9afa753976e7c4a2d4a63c92c67d867eb25b461505b0c5e34ba7b9ce08646c0e3de5845e3207b8fb8f10b2253eb7687166afb8e24dc7725003d6518493f695d5ae553903e847ac8b3ed84cf09f5f764089a740e86db5b2c45dc1638c9022bb1d70e79a1b15486cc97d127a9a05af2c9cf9b938daa25237d56dd10945d9f8809dfca6f898ae086c34d130654c6e2fe4a2786dc79abc9c5cf2365cf6a3101b8cc07c2facee84af121af0842cafdbab316b35ee169a1641b39d79d084eb2989116741e0fc7c49607c76453be314de7f594cc38de136ccd293325098debc61c3ecdec93b6181267feff5eff1b22e150c3f2b75dcf8ed99099ac011ede4e135934c45ae73253a98aa4a109ec092e0e84574c92217f2d9e6d7593065f1a32b643f4df7310fb11e70006e008d4a16727701e718b99d82d3925e82997ac7bea4986d7f82718615818b0a171862ffb488d1e4cf3018c05ae7979eefd9031c3f23422958c0f902ffda4271010039978a5962f554b2807e0902b409af9ba7c0d1a997a19dd7a4176d8deec6f73f066253a87121c902f5d7dcb9177e42b3ea66fed0dc073a649eddc83cc6fe7aa9a83766ccdbaa35d79329f208d4455c80c4a74bf5be85f216386c5ec56c8c468c32708d45332a8e8d5124dbf73105c628b84b8403b07b994f49b682d0fea9005ad91147f9622aaf5f929ab2eb88028056aa1dd6f91f4f5547998b33cad5ea8d2c829d19b94c5edcd78cd76cdf2a733e833360be1d6d4d7f95824a492e49255d1209e679126633142048927287e3ede7f4d934df54f492a5cff0251e0cf9a8d0d3fb864c4b7d8e60149980adc89dc5ff2c86d6fec4c43435b8addefdd0824637b81c9e5693c9bbc95bf7aa160361fdbd9ed0166756e25d5d133cb0f629d11eb74b91d1d0362dfc8c74bd6d9962551032ed6c03e014d7a7e78a25cd048371b6950ec64ea94b966b63a0775c3fdecf04c5f199a5704b8cf855008e442818eafc2bb25698bd6f39a6bd34f74c195a5a2f7e9fcb712860d250a279393564de2be7e7ab48af5daed2d2ba7c4b27319994ced4be98a23101fabd10aaa0109cc0b85b2849ed09dac4c023856b4ea3f3dffed681dadd6898d3150fd6486f5f40726686c96309102d3d10b7c11b0120805960ecd72c71384c852c1b83b7f2c8f2763c4afc30fc6a741c070ec0ccc8ac4fcb29d09cd3389b005e7c2c4422d27f06876942c34beef9c71d78ee388ebac411d0d19ae27a47ea12b1901017ed9001bfa2c8c6d03658b10b22426f357f275386a7559911630f2c4324966987d3886da7c9873acfc6b7583d07749f387ccf23f579bd9259fd9b7626ea6975b6dc7d83271366b1e8d747c41af227384d62355f1b6ef19788a7b5ccf82a22db6314f148dedd43bf614030259d211221d34d619e4fe9283743a52cd0a1a3b34fd04aa01108ea3aff5c0da0757a7e293334163b32a212d0a68e4c85b132924f9a96794288d53a1aabe90ae44725b8061686f5c09e1aa2f1e5ede616db5fb614c900dcc701b4cca2a0e4456878c16f68831a465f01a676f08690806d1dc468ae446811d9a19ce802d307ff33fed9a91a88eb65c995497e56e783c8b4ea7f753348a8e06de4fec885861c4ef990a3b854ce07d2cb51fbcda373fac1363d56cee50f216627539adcae54b28b79f40d5bcf9d36518181ae135c3e0585e48e0737e7a2a20332414b85a31251231b972a127e827d7324033be7bdffd409246540f3609b9e34930cec9e3aa0a149a15554ce0fb0d012e882b14ebad95dffce7eaf6ab1762b5b5898c31b02dc701999eb4d35b69d5e7796517334baebbaf009426c929765f890def634799b5d82cf7b5c9e4995b84c1bbd396ad7b345c1054f355343d2629e1ddaa2790ac0a08bcbc40f24b449625f53e5855c1aa4b0ef0ce44a7ef7db02a19061e0f9014052d588536981f2e8c202e4798084225b0e0d35e2036776f90232cc446bde23f192e55b9fe469a8a989e854b22aace8f386dbf0938d533c681edd300a95cb17d21b966a43d539dac267a22bac4bfa536b2954791803c9335ce93a2eb84c1997ac1db82821aa2137911674b1f54c5ecaa94485160c4c9c4b9ec5aa78d6cdd6b19b812cd73538caece124c7d6e8ae4b8acbe81efa25982ce8c1ce8b20494c56b302befd2d27ba0e441bca040c3abfa6d5c7e1b6843bd094a9d5011960068b4c072e8d2fb357d6bd66def86e0c555ad0d6da4b9cd34db90469bd36c330d6da4b9cd34db9046dd03cafaa546a03262048ad59252a0adff77a08d7cc410a525f4beadc73220221a6cc5ce309c4dd49f9f946399d6e13b02432c55791f88474a1b8d4e3f7e1b9b28991b782d14af42e05508bc0bc14ba1782b14af42e05d28bc0bc14ba1782b14af42e05d28bc0bc14ba1782b14af42e05d28bc0ba13cc2c6b843e117e0389b12720808280f66a8cda021befdfdf2d5aed4926b27d89b2a54c22d055f434b02eede1b33bd564c323ae8ad43919af508a186575085843316a1d5d0d7d1d5d0ead1ebd06ae8ebe85ead0b8ddbfc6ebb7a01b9c06fcf17d97dd5676c30ddcead0a13270ecb8ece7dcc8accfeacf8e229f0400bd2ab07f0406e6a9983cc7713b7886720cd09445e4e879a63560846b097f35cce061d5fe9efc4831d54d4f5e02cb003ca9818733cc89f4bf58982212cb479b2b156d50dff8e6788b1327f5aa8371a48938f2bccabe0f45d756dd99a19faff0c9ce1317786941f81dd8243e0bc64e69b4fc6bc1ef44ac02ba12e9ae23e3b41b9bc3e88675864216b318d89685cc98ad39278d9aa9c28428b2fb70b57e29dadf580dbba22f48431f6283cb16708679cf09d024822cb309e38e51b8d1144d46cd5f834c2dbed0d3579142695fd9814553a8fa31aa2510bd003ee4f74a43f69f0ebc933c8049444c108c718ece809fbfb1fdee443a95f06fece22a5a07293e1930231410744b2d62315471eb1a6903ed440200424741f9deeded4abb5d7eea9a2f068ecfa5f211ac5e991001adfb9ce59e615a18feef4eb36b93974844b059447068a7de85c41ab7c4be0a7821d3a548a9a70efee927504951fc9cb163f1239f1b9eb8028f1a1f4b5eb3bd2d4c2faeaa8d7e5c5cd0bed8804cb13bd7acdea44aa9c6fbdfc33c0925da78260e88a1b7f529d2d2af9239b95e0e6432bdf556ae2e1391deb2c0aada7f85f49740a7b3c3b3f47b8a69f778c2c503a58e8e8326bd779b91bd2dcba0b44cb4844e5ce7941d6658ff6318456283881ed53c77abed86dcf7229b38dcbf373d804d351a5561a693bfc3b7b7aeb405eb5e1abe3049ddb12017bd4849d9c4fea297cb2e746470e1340ca0f2531179f15eb0b638679303acb65aca912b42e5cba87cf255650100b7a42adf92ad268c5fb2bd06e06d9b87919bc5466d9cae21b4278f4ddd667442357dbc7a9fe648ab222ee0f1dc05dd8d5670d5ba4d223880305ffa2e4322e29b4463c2f00c485f82ec06f50718866b3b27c36e1a56fdc4d902497bc5038993e2d6948e794109541f3664a43042af643abe100ce2d236b454a131beeba492c8f77052c26e71ca94b0e820c986ec5af9612548ab91b8fa488ae50e2e565c22c28967bd7d71d034990888d391fb139850989cf6c0812eaee9ede1f28a9ee655784ae7cab4a95e7f7bf86a3d778e96f649e25be68fed9a96cd299457b5e56664c8c6560a1651957282befcd751a307ca53a9b034d0aa65ccfcd56d08e6d040258e03ea25ca7cc95f0d84b203cbc6aac8d3508f94b9c3cf905cf602f75627efeb66c11c61e795a1f3c40116a71ba18d328188b1525f816af930100115942820dbe14e44d45114e6808518eeb9459cef6932b1adc3917ca85b533532668ee0073ce4a5e954012880053fd77bf062c6fb66c49cf30bbe76c1bcca4be23e967199a898db7fffd8f0667c3b73337d825a9993a42d9274d7df083f60a778d63e9d5996b2f4b429b6c6049af189b29dc1998bc515c9d968a57d7445d5e0fc32a9fa50561dcf8163cdfe839aceb3a85e185b2d69de7712f82e58b8c9472c2d92a932b7226096888bc6587d0df41f93986645f981d1f981c307c0cf3eaaeb2d738d6536a2abf5d2fef582a77ac1a60e635fc162031672c9942be78ea7ce519d3f4a46e3374d2773f809b582786ecf6fcf06cc12bd0ce048030c959b2f9830e4c8673f76a9f969feb9c649c9e83852ff064ffe63f6589baa6a28ff150b92727b3f387f3a96b3be7cce9beec68b05645598dc3451ea06201bd7ff9ef84286eacebcc577cff0a2c152f4375e7bc51d253bcab90f045435c9da3e80cc3b996fe82822ac959c623453e71ca3352f303485f2d1d3aa5f0574f3e882be8072eced7b3160662399555ab5f10544ee31c6a7fe3b30f5a0aeb8ddb7938bb5bdbc93776e1d8dfbe41a96008ea2268d6564f338484f19113b15d26810f21ffef21f305f75e61b36470089fd4c75a551668849245548de0cdc93f88af28e8b7e060b816dc5d44688dabf98ebd46fce2bc413b4b0564a0b846e8fadb635038e81f97255795830fbd643b1b18af927b96e6382117bbfdbb653d01b93d32e74586cefaffe9fbe635f35dd70e03e4558205115ec93ae1033724dfe2d7e5393c43c800cdc18e20ce0946aa3676d8a4a8938802cefca41bd4c2d5f5f4c9a3bc52c93419ef254b8c5cd09dbda75ac6dda2b28c9850d57f52a81efbcd111c95361a7304563e9ae92a0366cc2555818e6c9a3ed003f5eee3cec341f050e3923dd90739311df92a6f929585b4c7b3c43c2f57ae516aaf6e2ea09bfd20bce08a42487780274d6f37bb22aed59c77f9c91c59ea6829a0cac126c42c358a102137aae97ad09982d9b456476a20550131821e9345c784f03c9fa8b34d8fa1b60f6bae096279c9f3a308c26768b4ccf5cf6fb7e7876a37f7b90143283fcc869abe12fc8aecfeb3b414b699aca45947947b0c32330b661b0767e1d941bc82a421af08563c64e0412d65a9bd1c347a305ffb5244ea305f64e67af2e6cab886a4c09a5e8dccc769f47889cf3171a3a71eeff546f541e6296e468e14ea5214e1ada44092c046d1cb7b17c1ffbe1058147aba8239a6537c28dcb07b193d0b3ecca35be6886dda6d0222d4abfcb610e2b984aa9e6910897b49d33a23dfcc56fcdac3030ffa7f3635051ad7868f835c8814ab1517a7286425e15f6ba8e552b5d12528149333019cb0d4f4d08608b105eded8c0839597c77b6a7af4cb052d970ca4aefd02812340126f336e04fd5db44d233e47a79c5ca4528ad21649d6fa73066e0544c5ba14d79467cd5d24434c6fbfc706639ac847dc54413e6ac955f6284fd04494302f12cbbccb41cec829f220568847cb27b62fe342d7200e336a4c0edbfa9ea0e9738aefce37d6a26b923657433321a8b21fe84f9792a26111fa7424ae713ea5ad106e87a46441f58fec640abfbd18b7df0c1f5f10032a0531f89e1032a53052ea98455d0ea901bac35b23b0957d5bf1cf814af6cc3c076fb2430a4391d35223961784bf71d0f523c54452f3083eb29baaff8b89dbaa803e29abbe668e4643dd8fcb8c8f5d7bf00a2a7dad7a2814b3df0087b7d129e8da5bd07c19e4a6265e257785806604b1b3d67f1940d4b62108cb25e92eb16cd1455c636626a23942215d6d394d512a21fb34477a054111993f4bbe050f85db058077a0dea8b956d330e5968004b75ce527770a9cb0a137afd56bae7d9031a05e55616a41b08ff5fde29c2a5aa5d415fe6749964b8d5db7e9ee363730ebb3bd7d56d9ec5669043e1a9a0b80ee079320c8e69b2403cb152f808196281aff8179eaa9daed92910d82f826f5e629853af0b2075203aa8f0c1920cdad08c526716957a4c5c4805ee733b7c725138835bd28c6614e1187302ad7664f9811b3abd3d385b81159d692d695c7e439616dec04a39bf3809e9864718e3be0b650aae57c04cc113eea2757d4c910beae2c65ce4a6757fb731a568c6a0dc067287435acc5733ab5628e5b9da83731b7f35c814b2877f699a05fe51e1fcc2989979cb0a1364b3a491512a2d82f28918e035f80c7f2647259e247df5cc252e333570fd920559a3980743419cb841b91c6a815e01c5f82c91b8075b53267e39f273946894a38b468406ba2011821e4a2c41ee42e88b89e792d1970c3cacc9e5206885a3762ee3d0a643aaac675426464b08f2376f06d45cd07cf09e121115a9dd92176254cd1ba46042bf5b131630460a930774e292e5bd5cac7d2ca83590291fae32700f0367a5076ca3214ce328fa99059cf7d281a0ea86a124281092210eae7ddd416059c8770455fad9d70759ca7559cbbb9dcc21b84395075e06367ca3d0bccc9a5003297018eb394bf16aeb96f910ed68c1c2ec314f529c3916c67f0f7c2026595d327db4acc01bdc1fa63042353de807c0ba533f9bc67f72a92cf867a196085c97c17304d2a8f010d3243cc0c3e7dcefffb7bdba959015efb6ac52ff1383f907b5d4857170b6bc82a415b7460df1180c1c7ac21c224d8a84ab3f60cf1dd9ee982c1be0dbbb2f352c0c71e99879056550bd882409696d2430c45eb48a566d32d2dd80e25becbef5ed1e712f76e477371830cc4365174c7d9f1ce5d1894c9da3446cfaa3e34b3598e362fe845d91d17150a6004c21c1ccd136626097006d4f8c58632ee2707b8370df420f404136898b8bf3829d3a15590609a7a02dcc0312a06343eefc6cedca6df040b07c9d1ff14f59e27c84c3d6584ab2626cb40b86a0d8f573619beec9b9ecf926b39d830793b69b4aa2841e0c02ae75b7d6a9d77a36d9c6f7f1c2e35926839d46f6e7a58fd85058dc760d7faafbb541197146e1f8f44a8b42ef1fc6a5a96545f1d387c72776c5e53d1df7fc24829c543ab8070982c2cfb55201c2838dcf2a843031a2000a5629ba884da7289897037a77b20c0a60ad95a2e0562fc2916710da767411b1688ed2bd97fd40fa07fdf9dd7252228f316ab54ee606de5bcc0996932e8d540b58f7c8e824173032c853681e45b506ce6bdd47bdf46bbc303d5734895698f487ffd90faee54eb870ca551a7fbb665165350216c387eb8be38a1931c94de3bfb3a3af9d462dab19270ddf4f293f49ae239afaeccdfaf66bb392d454f74282965a63e027f2f09c006a50abdba135041a1478758a77bf93fab3b1d1715b2c88da512e7993de07e5ae5c8f52925906fc9c2a66a7527669951ec08728e914862a00acecb4a74462c1e26b46c3f7cc89b5d75dd287b91906fa9bab83615bf2967c67bc3326e0625253f0fad52672586b7460e0614f1969bafb875b02fc488b1a9a4af06821d0a7c4836569f7ebba8c84068f8545fd366bfaed659fc0c0618ebd73df14eb0256c86b9a07d615bbd4b0c3053a8e6adbdf3da4bd1115ed9d54fcbedfe179f82c3a9e49df11587c3cba4c4de8c5dea644b4de0b81573887ba626805e5f53a3bffe6989dc26b60403f3cae4aaa8eb89bb63358c5b492d8fe4cc4b802cc96338c3bd5d7b25a01498ff023743737a7e0aed96ff6454e05c71de29f632cc9b1e3bedc4522932ec3f065139d007dd303e3dc4f6b57ea1543da812f0d4fc70353e552268fd1f5d8168b30b2098580c54d0ecbd316cc192837918ecbcf8d5ca74ffbeeffb8002312d74b31d5510326d86ebf05613b67e196f66571616dac28701bc5a6595d34bc2988e0692d9f0302606c5250a0dbe41d81716f59fe15f1ef9c7e508f8827d2b78a48c02192983801123df532694bd15280a24bad11f125f916cf72c250f9de6b8a72180eab7d175d3b992e4c766df65c1d692067a199c1bad94e80b0cc047881ad250025477065016c2a029c4012b29418a61d2266c4db64a926c0cbfb7beb997f771d28c44a460c422356cc1be1caee45c75149c2de7e37afa9af75cad523f09eda555eefe306ba1bba3b5afd8639e13cb5785ca24c095300cb8d44ce86edf70a9d25654b5acd4862552cbb357f4b657b47d11fc1a69713220fe4e33f7922796d1da9035630198fff0f8b481f8c559d26c6b41dc05abaedd268dbfb48eecfcd5be8108d997c348ac0cee5ea01b3681853270987ffce9d63a22e8dc32a46e91a51a761215512dcfc2a66f6e61b1ca3a2b93152c42fc9420b1fb43bd3e22e17ce30caa2ef16e980cf586111332e9451db943c4e0b4ca6be331511d4bbed4424b849605ea40f6bd277d2fc2abe738c85a670956c8e06dd3260f7e6ac1a2104759c7406b4f7a005f7828279a531f691f1750fbb3439d5ae05cc3d685c3acd1e77483c5ac433d4c604624a126f8d14bbcd8c623458da7a8d06b44a3805e4ad8a4767318630f33b5fc8b7b1278e7457f3aac0e15a98de384a7bcac29ec080aa82f54b56c14f292995c1787c39571fe6f8136a1e3baf2cb95254eec0819d50e1f26aae24f18d7e56327a5767f32450e69f55e84c4918a47e829c2b4c241d5591d9e164ed94c5ad5df4a8cbd8e638c5db635adc489b63996e57d52a546eff848b60c4f2f209a5e00c004083cd63aee427fdaac72907e4adbbcd5553646e33a08a3981aecda72cca8ab09c242f84c0b0ac5407411b753352f592561d8fa66f3e90033ea05acbf9c96fd22126ccaa326da1a46260fef69846b12c3fb269f0bb1275f67ad95b9a4ee49ce560691225126f10b81e7c37cb10dcbdb38418480701370028cbf9d3f3539da51462d599641c197583a80a66492dbfd90a7ce88b0da4d99fc775a5d4aba304ec2a4506928ca2832822c8b66da4c7733746ee71be829746d040e7c447da48f5202ba8fe1e13f3c1525b6501d281fc1ff349dfc238f4a3b05557ce5a44fad74bfb508af5f8f621ca8694811227ef7ccfa96a041e88a509e41be55d224878f986daae1fcea8816c1236c3db2516e12c998a1a8a049717300390804b2664e554b3ff828fce8c0a55749065f7c7a9915952feb6679a8e43606fa45986b1bbe70f4b9594d0a7c94d16b04dda83cfeb352864653ed657f3039a63814fa2e34f2d61abd62f1a79708937baa453a5016831aaeb9106de1eeff673bb3ecf7988be82235d7a60ff7d40c3e32f5e16b7a806174a4bbd11b914520fbd71681838c9ddc0634171de08939306d6ce3e2dbef7e8aafc7db286d225d0f0d23ed830222125d981c7feb01706423729d06cc75bd839c0f1504c8fb20cf87d5854b260c45fb174222ca056d5782216a8a0f02b22b7aa32ab1195dcb353738d86415b46e6ed349c71cf27f1f9306c3d69cbe41b94e76bde659a55e6d1d18a980b5a10264b286cf1dfd02f0fa8ee7c4f72d89e761c7402c848f2f9b8bcbfe7835a97caa24ad5e53ef2c80f5499540f9e8abe89ed7b872ed53de87bd18fcbd86da992c11795fa74df6cf0e9a30648bb9b2f4b6dd5a12ca7aa9ca7c6a7f60e4373b6c8400376948508f2d11ca210f833bf912c7f2af027338e33c27f70e2dda11648d2aa1ca147d3598d57dd44cbc89ca2ae329e5176d356bd94970357cdd0ea5e9f88d3133d888e8921244a7b666a7fdd4327f23d0d1938a572fb52238e821b0a21bb5159ed28151218766888727094290af00ea8b509155e80639186776c58fce36da8c27354bdd2324bfaea27274c70890de349de0bcfdde41f795488cbe24e07c61eace6a434f72b002249469aa43a60affe18b522819fa2c5e3ce0782bbcf7b72af6035a7870c1b3fde2a9e27e2e26567454e1aa7b00a47cf4729dc8004e14a01749fb8de1b8a50edb2305bd3189f6ce5ac0a51142b7cbf7f657dba11a1cc607bcad9e67e256750a755f345d289124c78b1d2addccad99d24568a414c880d4dcbd5e1a495120f11b449803d6d9ed6ca1b9d077b331c4ec8be734a4359f53a98e82add50b5710854838083427614c74ac4d5674080b6f709a3e0d4b6082885fb991cf74212ec2d5d736d4aeffb365b59fec1a1e779cba30b6348afa3e7ec40933ec7ac20865494795e8d1a3386b38f0a2d94651a820aad2159b0c419cff855c9f4e2c906f2979e232c6495acba4d7a103295661dd8200743ece1e34323f9974b50911f0cdf48550e3699e03b175087107584e2adfd0f157d2462f7fffd69fb2d3f0f6e1e6a378d1e12fc903da48cf902149403dab65e915e3050b2a20e5664526d51adccade55c2b1319e7f0893857117715777d46c307fb75de6d7166cff9ba6119f7d3f0b8c51a62c8905ccceb0028481582d2625da9c35642ce826692bf041fed3cd62d619486fc4ab68590b45d42f696524a29654d099409b108ae1abb971a3b971abb568d1dabc66e5563471324fb579936d8e0273bf1945e76794b477120d83ff711427d0b6f3eec6542a5f711aa2aacb0bbe9af8d211b24b04164230c1bbf9c9f9c175c2f2e39b71347a7b3a10a52e56c69554c608e5262fe1d099ce061e26683e8d2788ed05918bf9c17a064c9f9b13939b0d052d7edbbc893d64f1b442f36886c10b56c109d368836f82ad206d1ceb9759c125ecbdd19175bbc61c34f3ca9af55cc248fed867daa72ad9e2a0713443b58a283240e2dda756bbaba12af29b165ce964c782d68c806eed26a3e40c13db181b3f9a5c46cf31b6557f6d9ea3dc7369b79b9aaa338d07fe62aa43ee66f54e121d19a9aedcea874fb96270a90f3e0680dcf0f8f8dd6f024a1b7cee3029df9741e22b4dc652009227e42ec76aee7b5a01a8ad792500eec8bbca6a496e33526e4d853640d5744ab478d20d2ed9f37aae8faf91f10f5da500d57b35d5a4d499193cda4dbafa44dd535c963bbb9c125e3fbceeae59538124c76ca240f27648c322ef64993d8d99c32d9b232338aa278c79103bdc4d3eb82a0aea268429d7878ecc4a21c320f241e4e9c52478043e0e8c148e90d1b5c2b9902388a9c76d4aa8f1c08f69903c5fe04fb17f779cd7c8c2779e86c99a3d01c1e5168997797a6cacd4069384bd0997d1cdd9de56c8e0d9c2d750e34c7060d349b77b9767997c46e86b7b2a01dd88fc15b31a037f649deb282dab0cfb9cb0f6ff9862ead75c5ceecdb566f08345f64ab473bb07ff3038da77767f62d2d7ad2ed9fb408876b34d8af25a11f84e05339a037f2db7fce23e33cbb3bb32fc379743c3ca218018587cee6f010414b9bc3974395bb341e2274b6c40f47776939b4a03668a050ac746b737258414b2388683d74fb28f2b469b2a47f12d7916d840bddaa72dd82248fed06887db67a1d17e3f77767f561d896394f8f4a083e97895edf5e715d2bbda648237add36d1eb112d7490123d48dda46c8c284e478e6db67eb9ee9903bd5ed46513fbdc45dd1675dea5a96e7786d4cf5d4444afdbdf452f994c260435eb433046cb4a8c134fab479e7854b9564f95d37a830d66d0a031ab1979d49c7878ec6c699fe6c4d3ba49da272dc225b1ebf66b4136e76cf53aaea6c4e6e46cce09e4fa3aae3169f5e88d172c26237b4e7e50c61ce5c41e977d40119b6d9ea10289ca5f1d57b8e3d2f4d71d5624fa89cd8152b5940e7e8e1d36c735b3c53d8267ec9067acd04eec93f2887af078bc1f3f7edc6c8bf649793f2ead96782d3ccba3a1e6b96ca83a0c41ddc2dbb9d329603001c40e3b9d02461260cee28a9e9f4e0183046004a9885832ac4050b5d657f0c00219a4a0c483ce54830115921d16b564d8e20fac2d78086221d9a84e8f78f840cb0b78e8c00f0f2db4422084c5e547e80a212856332d4e6c9611ab853d06c11a7212c366e15ab010da8017424458495bf4a22505bb14831094a26b95a9f5ab6badb516819328436cdce9911324946c53a7474e4eb04312985ea07012f47264a73a3d7292c48991136bb584139bca04fbc4450cf6a6a2c5c57e91d2aa32c46a053b385165b1c74e8f76c8fd6cb1d3a31d62580db1c3cf3ed2a10633e57f79a40316473a201de93084ea881d767aa44310ab2c9bd5e9910e39f02083900e2e5cd92e9d1e35e14285c56e757ad4a4055aec53a7474d9828f1142f847ea63c6a324493235252700a7238515314e9e9ed941e13d3ab64532af5b8341fcbebf12a11dbf776dd3e0d4e0efb052881019636befd52ce39698f5797e4f184fc34c3680d1d4b2f8a2f9ac8d267ccc1a08833ec63af390be9c3bd27345072ad08238a0f2630628a5503453e9f79f9cdcf14ad144a8088a03c618a378928769706a1dd8f7979ddc104a69855c0015d75a1071c7ecccb6f80302b100f5408e1c4bc9c42e1421366453274c39997df2062622233f0e0635edee2c1608aa611f35b832b547ce6e52c1e0c4c511c31a7489c00cacebcdc3502531c47cc2d0d4f7420c8bc9c364103533c8d985315cc00c6cfbc9ceb4cebc2079af099975323b030c5d48879cdc0932a38f372d28916949882c8bc3c0610a6d8d2d2c2020b54a698434c23e8d13832875017d0b89425e6220c3e493ee0cccb73ce033098e26ab5aa1e0022d28539a41482256e64c01c526198f967b158170344507c30879c6e22a833109943701043b0800a98cbd56ab584e80106e6908c448710b0f6767139f1d42398b001c91c92bf78c2c47f7910b088d9423631f9aa248ea9636dd87f29d95fe586fe72e2a9a517f6cb88793d32849420f3721823537441316241cebc1c048129c23041451343e6e52924a618f343aee835624e8d28e261c8bc1cac628ab011737a451630d899976f254c312663841760e8cccb4322a688812930f099f2021d5410040bbcf8e2c9163bd4f48b0779b2ba25bb26779039caa14d5fb4b27bbe96c52afbdc2f9b8e0344cd9d1e557141cf242dbdb0cf906e7b6ba034db1b58c4fed89feb638d6820ae316974c198246e80de7bf1d5faefbd1483af391057bf14882defeb1f3a0977fd3e76dcae05608363cb19178cde9308b96b92daf2a76b0c669167d242c604b115e01ef6f59cc35670cfe79301f6f9f00de33ad66124f88665c0388c8b3d4129fdb969239dbefe1981b83870cb48d82bfd32b149f68a7d81bd62af5cae2fd63cccdd8b43ad31c6d98728f2fd3bdce28b3aac467a7dd26907c1f075883558d2213e3de694625c2a954a295dd2214ad4e187a1118db5d618c573224371e42790b1638c492a7bc13ec3aeb54b7fc84b8fb9c62188bf34c2dea4c326f204824326fd86a10e35c518c40f6270c418c43804b5c6d85acc73c6d7d61513d9570a07604ba5c230fcbc7314b68439655323df39dad1ed1ced1c95f889b3ae8f799b9e5e9aea53a9d487a9177fe7a87eb0531fa6c89da3ca4198dad1ed1ca5322f27d9f2e61e15550ba777fcda3dd521cccf1d2776763d7cf0c4b37354e23bdcd1ed48d9d1d99ca3f077766138005b07793852d93bbb9dddce2efb50562b713f98328222f37e8f49f1bdb7c5757998b4b1c581881fb0d613026a4fa470c308a3d76a6b36ac3d218a63f67513aa0424fbfae951baf644aeed6a4f9cc43a9eb8b6e99f15689bcf3e155a84547b625773a2b6ab3d514322e26705bb86544f19890b6a73e8d39568eff70c71317fe557a1d6eff7f4572645d839e15e9997e9f6650680a9ac8b54a463ceb786d12d3f8710e9f6a9e5b1f4a2f2d3146a18affbbab4a8531287d1453cd257fe5b3fb044ea0755cc633d62876fb22999ac87640ab21ec2fe9e42e5f5f0da93cea8911a20bfe92f2fbd29f50b406fd06c6d5cfdde1d0670e896c4b43e3e25a0c7dc7756974801443f7710fb74f518b494b2c882427de0b735f0724af24b2d618d34a07e6889b8dc498916930d44a34f0a98d2078a44df15563803cff4c30271bc921295aea128e421dbf00312f1c2364d65df106ab0e5295ac46c084a76d805976a69212409ba331a6e71c3e8facde0e7a50444aa0c494e84d8ab205a599450c1b077a75392a4a862b7743a25098b1a2465e940151c6021b14b9d4ea962c90c6c36a7f6e09af20219bc102212e94cb5b54b3b7dc9243e7d1f2530e04703e88d9a7a940eb5b4920638ea77045d7fb5640168cd9d4282ce77d0528acea1232af11a2da1f43c69e1365b07d3a25a8a3fa774466f8faebfbe0defa51ff2f8ae5922ecdacbb949887148770d6200b7c051b492502ca2246a40839bde32c824977cf8e1449fb047748009ed433fdf099d2afda4452745a2d273165ae4fc6116473de79e077080620520302ada99f96d76fca0bfb1d3295914d14d9d4ec98228050ef5fb62135b67f54daa983a23066b332682e8d6b7997510803b53032e012fcb6842cf5401ce0841c8a434930422b139679de1870975067aa3d29ad09402f0e6baa20c3046a3f034530525a388d48c942d038a1619455451ac6680800584092d242e4db8c0858399f9c5d020be4a29f65971158783e966c0bc180e57713d70976653711557d6b0cf8a2b713b2c65c0a105f4b208dabde0eba1e22ca8bee551d0985352c5b556fd7d1505c57c023f06d582ad5ff53f4ee38b6f2d4f7502b101ffcf1994f8a9d7bf5f4c71d4264f143aea00b4a7481aa4a3481b5bda04509346946dbf64378bafb8fe919734b6d4333d544f59507d901e53f520a852bde65485f1d7aee62adef2f43402355b9e96427eca65d5d1e9b5da1251288ea2b85930cac2ef1e359d2f69707214a004066c16cdccef0ddbe51f199ab139d60194278e7467124593b525d89cb306f5f0c1001a53586fb60afc3001880f05e2801f26fca03c072411e90c8e4d17c73789a2c9dad1447f333425bb430fec9c33fcd163878d8e0072f8608009404aa61c8e024091212bd4b1b1c1a9361d86322ffb76375bfe655eee652bf98a8f119c12a4a09d135476bdcccbbc9c9479bc6c25f3f490de8dda76669f1ed2398dd336fda38d68249a8976a289f493fcb339a7d6655fbe12fab44da7fc70b3603438b51cdaa67d5863a86dda88b6edf034ea1d0e220e8be29813c5caa35ee46c361b912119243d81529da854ac58da68aabf9a63b24406437d04c1134fce75ebb2e59f60faf14f536ec95f876c9e5e19b2d96c44cc5cb73fb26668682753e60970929479e33dc1684dfd717cf04b7c2481506f32e54ce23a048e234986f464b168c39b941b197b5ef6e0d395a3b8611863b9a24591103d345992c4151363b6180bb19fd812315d0c2926458cf7c2440ed6d3b1d3a1134f327e3268b0faed20f6908e221d46e2c9030ff8ce6d478913263b38df9b7c3edfcf0b3728763c2a44b1675b6529217941fc116f2214e24ea442e4dd6eb7db11f1762322dec45ebf81ab9f083fab9f89b36c4b5e411b8a0d8a6de440a489fc1c2554dd40f23d54fa580a89bd93cbe6ef86a1958fd6209104b7d3953e68c807284f56bf17dd1e32994693698cb110b3c57e624bc474312962482fb11f97d84f2bf6c38afdac623faad84fec27c6db297a61c29583f5603d584f04dccdcdcd88f260e7e6c1ceedd26e70c464d040c6efb7faed2054ab9fb8faddd5efb4faad7eabdfea87514aac0d32e8e6860c1ac5d96ed6c40c89c60d3470348268ec00e37a7169b1563486664dcc7633241a37d0c0d1d8814610cc0c698634439a21cd90f66a86446348f6af1267d866d8c69103c93ce73e422397f9176f6e6e6e6e7070703cb8b9b9d9447b68fbb0734b9970e86e8ca4dc0cd91c1c49e0f8317d37449786c3851b23dbcdefd24c2c38455cc1f9b139a6164645374437443744374437443744dd8573eb37243bb83bdb59fd4c269369347f7b68f58bf11722230f70dc68cd8eae5bf116ed20b125ce964a76724137b84bdb71f2a4dbbfc1f970b37303c0cf0480d58f8f1c888f5c278a000c21e1d881f03372020713386e386ce60fc711a31f1c448ac8626231d21911612484510f463bb91d18768e500eec9bf80e921ddc8e125b06ddd9cead8822b04401eedc86ba7d92ef04ed80f0bbb41d243b4c40f8ed2801e167fe7ef5d3210509dd2acb7832a14ca0d6a249870e48c74e8794532a0913a77d3c712019d9a36464fcccc7d051a4c3680f79e0c1cdcd78da43434348e864f05518337c5583187c8585e42c1ccbc6f259fd56bfd58f86837767f6777cd8b9eddc3ade81c1f4f6778ed00f7064a91c708ee3390e1d8e221c443a8c8c9ee828b2393884307b266f0f5d9a89c583227c1ee82ecdb4e2a688a41b9ccd31ab180ded21a326ddfeb8878c9674fba73d6494e488cb856e7fc888c850d8776e7766fe563b37990c0e1e8e2c463c6a0486c9349a6264486e994cb8cab2faeda1d56f0fe93da437d860060d1a331d5274e856bf9d1b12ba6e7f276773ced56fe7b6836407b7a364f5937273590754218a2919173687231f3a7db1079a63a2e5504b149dbe09896a9f4eb3d0f2d09d45a1a5a59f93a0395967cb9f4be34f3fef284de6a9ece967dea5fdd3cfbd4b7b3dc52d4f75068a84f8f5f04d3aed2dd949fa914e3fbb40697947d333d099fd3363a1347dcbd139d0d2fe89af74fa580b9aa3739f297deca337f6531df4a88f795ac5f124d6310b161d1142f4d0c4d5317669e9d71847e12192058b8e08217ae82d49b253a10cb795c7ce9697a35e56929191f9c9869011c964349bf25db21d0c11313719241e48a329d5c718dec29baf0d7c1b70d1eaa98054391e3a1e5154a63b729c1d8eee7453bad4127255bffcf617afe1ee8c890f4e38e898ace53ce0edd3f433fd2ecd9a7ea6df29f572e249bd8b7813611071e2142292d813b1a0d9946fdaed441f8ab77cad5ecb4a49e38741bc8938710a1149c42227871544224ec489381127e28e88381127fa0c70a31dd84ff156afe5b325c86baf30624771a0d76b97041142f4d0e4b58ff839e2c7358e280ec4f9e74cd4439325207ff17d67b483d728e362c38c979f64dc47a824934921b185f06518ce96b1d88927f5b1ddeaa9722d1ead4162490e6957920d113d9102a5d583d96518aca48239da325cc8f8647eb2216444b22832dd8bcccf45e6d792f9b1647e2b999f4ae627f393edea2984221822626e3248324832484606c885e376c56cc44e3c36703670a74ce248f9a9e1c2cedb808b0d7c375baba70252b57aa656efb67a63ab576af55abd560f9f98581b33391b386b63cfe4646464546faaa1ab11a5c68e66069a1b4d8e260718d78b4b8bb5a209aa11a586aec68e66069a1b4d0e3439981abb4f3e96fda979fdfe6e167aa3f6cd93917b479242e1f397fd5991bae0a48cb48f9385ec637f569e6b8d68fbb3fa53f374ee16754b94806a6adc9dd97fedb071ab8e1fc6a9f9859420748b17a61c79813924e65f3c0875c28a2dcc2043681256cc185228f543f41353686b2b3627f5b47e0c16be7ecdbbb4578f9a31af44e76c89ffd4387be316676f5398a05f27da0619c1f361a8f4827d5cb3fcaaec13e3facb8beff22cee12f3addfbdd56addfa8c4e8f8ef4562ad5d7138feac51b7e4fd7fca2f45fcd5717cb5039583d6a8571fcfcce22b112dc0dc3bd47f27475d6e358bcf42dbe42eeb917ae9528b14f88c4f0ea174a13a1505a473484cb31b11a8ade692750a0c64598083fc150c0d7fcc5639f7e7f4f8fbdbec784c13ee67dc062c82042f7d5638a5a6cf0c7e69cdefabc7e5146e66bbdc6a16443ec987ffda97938bc32851c740206e5ac0dd0d6f2324eef8c359224c8c496fa66cb3f413ff8a77efd436a9b3662cbd2b684da77c3f047af803ea0111ca8c4d2ec87faaa3e276b24b4c66a2be0af3e048a797d498d5b6926e08f911f1f5bda0ba23e2435cf96200efce9b69cc5962bcdd33edd7e875d52276923dd3e50cc2f0c7f47fbcc484a6c8c53338b9447e1462aa8e8a7f651b14896f5ab8721e8c803523a4da7471ec8650901459edf516f7a590bb6ed380cc3184cf4d2dfd3f56ffe027ff53d3dc65ff7c9ef3163df633eb1a52502398ffdabbffcd57a97675db1f55f8dbb3d186c4ca4ffd264debe0ebab4d77d5d921422fbd7c34821423e64ff7a21fc74c54c20eaff3da12dbfdf85b7f808b08f91418458a48fd8936490d7c73e48ccc3f48b9aaf584f4fabaf591e3a06520051a5b35e3ceda07d4502d11141c7400a20789db5fa9a9551e207019bce224fb8bf7addc32095f2867d62a22ea3629f190923dd997dce91c2bee236e988adffea2b3647a549fdd3be2bb6cc3f235bdb72961ab6fe33ff30efca48d9a7e6d99c7305ddc1bf3a495bb139f755affb212fe96583aac9d62426b2258804deeeac8ce1f63482355f2f00ed4b54bb304ecd18a7e6e69477b3681c6f858c6d48f67991a06cccc3a7b661eb3fb1cde6bc6caf5b2bb6bcb498b7afed6bdfa5c15efff6f7132351e9a19fb867af6024ebb33e0cec33ffba7d187fdd187f5df235c2eb634fc2eb63a410d8c77c8c1422e403f6312f24a65d78f40608dde278f4064cb7b0b7f6d262248cc44831fe7a188ff95d650711f201fbd8c7c8202cd4304ca1f3be081e9010a049f72f090448c8fdf9fb30d2fe344612baa4267ad89ff6d7edf3dd3e35ae0b187971f7872699af8ff9f3e2b8e66531f2c51d633868e3daf7d2bf6e635ee67dbc3e3642ccc39e84d7cb9edc629f184933d14e90b8ee813fbc1b88cbe5609c9a324e4d194e4d8dbb346aeadcd5bc18a7e62b081c6f0a1cfa25714e7037e806757bc518fe0a3fe6a9f9e2afb08e1746dea117bf4477663f86d33b8b39da2179ed974fb67eded5d9528aee913ac996e5d0d6e439a4e3efe92f0e2e61c6f0141348884c7a4240265ff7595d9ff0ba5fbbced952e3ba56624bab79b86eb5efbe9c7a5c76041e4404bcecb3fafd135ef62b77c1f6eff1093dd9fd9bdeb045505a9f84540b8aec0b7afe800da5ed3b4b002df7133aa0b84967f94f5c099c021efaf580cef28b377ace3d28e8f7c90ec20e1050e2d1d27304364d0f71ce0274fc3374163e1533a5e3d39f6140e79bcec21739f8b4c4c110d434867dc12f300e41cdea6d53a753c0e02289ad3b9d02460c68d197345a886054115e01ea29301331b439344a29cdb69ef8335581d29a15c0ae83da4eeb0d828188b10b3f78f553d509816ebfd219be0ff6fb345f3da4db6aad68ddd35dd79236027c47a0637a63026007ffc60becb8da08a8fa7daabf6332051a4607c90cea53083df6569bb18db5a20d184f5491d2c2c32e5359f659761a9b5e576044bf23d8a2c33ecb977dfab21f76fbe55b0e1b62ff254f1d2ce88cfd241b18b9295538a1bbd253898463d9e7bf6051c5665a53079f5f31ae2ec8d500a9000eb0256ca05b9fcc43d24f7aa5dbc7b7becd3961274eb7337a493f69ba8eeef4a84a129d9baba8353371b5c82a858191e0619c652041e9490cbab1944a9b6e238cb802046bd01458174485cb15e02e0b17fda4483d9f948a142db224f5b0d32959a88056723ec3fa38ccb5aaa05e4b4ff544804a9e3dc013884dd7e409294ce07620d3d39e59287d901e0b94ce90ecd14235c71f4b2c041912c610536431031ad4200cb3f4457acc125944fc912453a8b57bf6e820072abdc887545b51eef6e3830122260b340cf307c62c912e94be88e94d25d2059759a4f426d285d02c52a448890c62ba61c90f496218224ace347d91d217319145481a5e6bffb3d5f7d63074b972cef973ce600eee37df4b69ced55eab6d98f1b5610529a873381ab9a62cf2199de5121806a0e7af3afafdaa7fcf14d06f2d55162d7535a1e3afa6f08a9b96fab106229a3089af0c3b801a0c7358c225d315f158c3d0c8a46393ef8b90ea15bb5c76e312a718ffb8592e5db5016e0f5dd66a5083610e4bb864ba6158813ad631bc4920587ad165a3ff815c369982af1f93b38e592b30b439f5f3d3310cf36b1dbaa84e2244a0e707b9cb89c7ee36b6b42c9717ddb25f5c79a75c3038858289b9a853684fe349040a94c217ac8e22ac249a443090b06cf162c46b1559a2c8a7040b5850c002272e25c0f281d56fa33a9d82c54816586cbfdfef278910e30a7eccbd976e7d33c6f9deabf5bdb7569c73c618638c31c694524a2b0a075fb72fba6250d9985a7a44dff7edd72394566d746675b74435033deecc3ac05a79a1dbafb88aa48462f7b8b32d65d7760a34a702b6b4f7eda3406fe49c0bd0242d2e5055a85d85dacf7da335f66bb6daaa8fd6e43626eb0f597d6cb94195edaba1d65b4317494688e878a1a49fb4880a85e2eb39ef5ed405931bac7a5d08bb4062c5d7b59e55b9d2442cd4fa9601ac499b1b05098ae8fac992e1e2ca0b5ce45c41642bbb0d6cfaf5bf30f2c5db529f46a077764dfdf6f3d70f648874fa7885dbefb714b12f5992332cecd3c6e67366fd9acdb9dfebefb0393ad703e46b04d6c33c09ac97777921ad673d092e1ff331a490176a9eb8a9d3d3ab8710211ff7615e08fe1821f761fec4c54e4faf11f0c77c09f863c812eec39028f4133775f104e62e7ecdba4e277eea1f5fc459417713a963cbfc3f6caecdd5c926f06ad09de51fb426ff0baf2ef95b9cd5003acb9f73cef96b3b72f08a5a8a461a8874e654d55a7945d55ac54ae61051dd5ab12d3c7a03845a7aebd36de9dbf8636fbf56a1b46d6f44be165994785bbe66c5bf5c3c81d074d48b2f3e15519f0a41fcfb280e019a7e82f8973c5d5ef5a2c84f9a7e45f2f4d1697845a8b7a7cbbb3c5e8abf2def8c2dafea45eef2f4c4a32273d480d0f44beeb0a5e98dbaa022fefd62bfaa7691771fb52f109a2e7e8e1ef3c55f5714f90e196cd1ee18e1f5b0f7f17a98ccbffe923e602f2383c81ef695776928b4b49c7829d2260cffefbfcebde45991d852f5a20bafb8a4edf23aea0da616ddd273d957db23c6cc53f345924f02ec674821ffb027ff612f84575c4f77797bff847ad4734eefec511f83d33b8341bd88fa9ab32ef20c519f3abd783ff5b57b5d3ec52bae1615dd6a2fc99627f5f162bc6d9167c8bfc7a5c520c93024557f67aa97e1b50b8edfc2cf31459e3d3d6563d3514f2f8d7c99ffd3c5ff2cc913f5e3939c3e97e1a83f7ded02b1e9a6f18e5c7c7aba624b0715ecb083f64b02b1e9a6afa6cf271e130914fb127ff108613d245fb5a8a757deee23af667f478c5bcd6d8ec7ed8ddb2a7466ed0fcd12792cddfe5956265757a432f5c0d89724f1626a41d863ea7da84e281218b5d5c707fe7dd5df4f81d2b6fe17a6e1ea11225830f91a617fcbfbd8dff218933e5a5a3e08ebf7f7983d7e5743a1964417def7b459e9d89cd4e315740f77e448dae1eba8bd788c0feb23f9c25ffbf83d1d85eb43912eeaf3d1c396d72792f8f165ad380abddae4dc4b5fb325d58b96935d14dff4a51cba87e40e5bde47c196b5dda555db0e1f2f1b760556b0a5af120da1406bee4d01473b523e961e25f8f0895ab4a4f002426f5522a7dbb2534f2fad75bff4ed9366d6df1f81d2e8ed416fe817ea619e9a97522dfaa556f44ba3e81745be4650bdeb49583d0c29c4e557ef228508f970f9d50b699d3abd644bddbe8fa3138621892befe77f0cce957dd6fa09f8c37fe1f4ce5cc2af27fce3d7ae89f6d3c85ff8c38e5f3485266ec35f98c4e93ab6bc3e6c79bf6cb22beece6e0f5a736d77767ffa0874767f1b68f156b8aaf41b45d6b1e5fdfb3643291b7a21863687525aebb539579a3319d2b7328894525abf874dc98a54beab524a29ad94524a2ba594528a84989f925be3a73595f2c4d0e6d02320b07409d89e5a0f40774a6beaca61eedd9b750f8aa90629c6a4c6187ffd5bd21f525af89a3cf5d35c0a7b7c6e531b5ceb0fc618e31aadc902b0657d94129bead812638c31c6c118638c6d6c5969ce5f59bdd28c290d290dc4efb57c97b53ab6a46fafb5381893a10d168c41f0c41dd30feb83245de176fa18ef5a2b10561316cb035bc6c8ae7f66a49a7777469f030a809a4ee9a5a93568684a29bd3add2cdc8194527a75ba32dc85ba0d4ca531440dedfa7906a622901103df7b0a22083a33ba5898bc176bdbdb18df7cefbdb6c374206cc17f6f4c0c324a2fa594ae5431d60ac67afdf0c3bdf7de7dfa01e605bb5c2f94c6c0b8bc80624e3cf469abdffb62512a632406d3ad1e8684d52038e45385329996976d929f78e8d37befc53bd446ba3024f2bd79f743d67a469441e98c52df20a4b41c4f4164308bb3f3de4bffefcdbac65317a6b426d7b83a3cde10d360fa36d7d77ffaa1e61e006a2c07f4e978439ba7e30da90d0700a8a1a94163566e30c306752303183fd0bef4c463efa5a40af86903684da5f407ade951005b564a29a53b6c699329a59f29a5f45e4a3b7dcd6b7756750bd7855936a494d2ebc22c3bda3253f22ce1a1283bfd8aefbdf7de9818767d9be9d39bc12ca6fe76c6648737dca32dede69d61587bfd4d6baa290691d20f6888f1dfcac107a4ed39db4ae2ca01c538ecc9d556c92bf44aff71d8f8e90319f18f58e7acf3ae4f6cbcfbb5bbf273df5ba235a64e33b63f854867ce3a9364d7ce33fe7ae41d975671396c4ef8465d85da55a83d684dae486aeec5c3ae41646562cb526857199dbe78e2e9f1a7f0ac75b0764de42bfc7005dd4baff92bccaf1ebe6cd825903eca26dbdebb6388de00a1dfbf36f486abdf4bd23babe4ae62bfe5568d443a73be14c5fceb5f6410d8c77c8ff98a91416274e89636d427bb23187cb483b7077d4025dd7ea82f0f1be3d48471b10b5f9129d29dcdc3a2268bd70ee341ea16474d6ea6ec633c48fd91c184b99e9e60be66657c083d22890c6830633c8c0f7975c08cf1e2dbb04fcd8b7d18de9167adea33af2ee9168fae17592fced05c45a41147448f8e48e9b548f3bace41e7d0350ef4e8880fdd3e4ea2b9e8d2725078ea3988d6d8ff1b76ec614839e8e5e9a59954d9e5138ba15e0745a11e4502792021ae3bb3e1fe191ffb339c5196b187bdcad5ad4af5337dced970f927dbaaecd8c3304886e42533d2b75ac814198b910ffb18a903837d4ce7529012c1f8e63a1d884e87f9b7617f6cc6c3c820423e663ef6f4ce2e8c0c0223492125c47e86dc41bef05cc81829e47ab2655ef6327ee6f9ff9f54f7a4097796053549f23ff624bc901924ece99d3d09b1279f2485c06030d8c3c82142c8873d272bf0339eff497f33487a3959717796c5937f565c87218162fcf320ff3366f0e742e0c7e0e08fb561dfc5c119ae793238bdb39f0c4ecd194e4d1917e8634b1b721fb28f91b618394448257ad8cbc81a1465631e89a99cf8c4483052e87e50d555dd9d759c2cfe6562706a8a9703d98420701fbf1004eeebaf2711f05f1202af3bc65ddac5b8f0225d1aa662ad74fba88b84af74fb20c63f181bc11823612a78c74a31126f8c7f7c4c7cb3d812fb74fb9c0711f2c19f2483089d40b18fbdec39596de41021b517a046a814cdd5273d29119140000000288315000020100a06c482c16824cd0261ef1d14800b7298406e4a369648433916042908828c31c818020c3004194368686aa84100c4d8acf42f9546577efab151c12dba7a9595314b88a3456add2127ddd3fedc814158a428819b68e59b39e4d8d283d9fa6dec0a6f5795e6b08bfa55fc3e524b1ba48e21aa5a6b0c501f13a3ec451054096ff22201ac994f17dcf854a5a0ff1543978d88f6315f8ce51edf1c4d045b251e351c36c0269d61c4e036e81f9bce6e16d961a373c91027ab34c6af1d6172631645d2f4632d72518298958cdbb345061a5060eb506bc8014dcbcfa17a1b95a1cf7774ed259a90ad4a62251daf4db6048993d29a92b46781300782a8e74cf3340ad33ab255d9350222174d20563cb74628c524abc9ea8051b4deaf67b1d3e2a2e4f10b1b8cf3d5b8bdf225243b2eb6e2989d218aa50b5ed2c40676198001d0229c2fe3ab99fac6238381a13863ae5a63115171bc85d6d93f6ae12c5dc360151fbcb318417d8e4b193ce4043097ca12c066bbe6156ea0404e580ee0b1ecb463b8c9e092a098612aec14b57b294aa9d3f63275ced834c8373e498e390f9052e8f99af19f98c533b93600d244d0ecfe9804bca3e08ad4ae0110b151c9cb06a8a3f9bcade3d4ed3e1c192e404a0745d785f3d2af90e6e860b88e08d485651c53229299e66ca8464c0029ed94e97d3831f95c481e6ad477f76a389c1563a5702aa6a6a79b32108ed127e3605a7921bdffe179afae7d93566656ddf04391f35f2e766e411258548dd90e98d38af942d1ec5902057bf4649aa9a6f7a8f74454a49791bd75adec28994477ae1079766a208f8362dcc41b972ab76b6745b42aa152872c00e3b923c630c4b51207d44a2933bf754c4a6c8c394a7b2d15ed54fe434e2c81dce39881baf28de5f01fd89bf394c12823d99baf8d770cf903b7c13fb061b7d61f52d2428913ddcde1b55b56a0f0d960c002ef0f34f924931f14f041c4147d454cfa4d73f465e9410cf928c3a0d0009ff3d326d7841792e17ee91ce5c5b51fb079888636f33f6e0e89a19e812e2f7045f00d7072c5c4e3edad87e94b65a61b2366718547c94f4a9e9175fea9287e6ad1ff31e7b197eb0419636c3e32798fec457298538a40e01f1b3fa245c5b2014cab0ffc86a8589722aa308f543d899bc80411ce57cfabf8b97b4013da89cbd2cfaa47208c7d1eea334542be9085f24fce97a70d8d400f4f72928fb97a15102cb5448444f9b8597a96b37feb76389b4c405422c879b7310c97de13b125f1c63db13c55b1f6d7c7c64013ad31687cf14be3787aab896a97293fc24d23c65e63382b721da13329d0a463ee483e4a5580524ff2a1f4b169b1f53f967479cc2f4583de8f8d5c420b2d9d481bade0066522dd11cdd907df6d33301a9b5ea5da521e2f5737ee64275baceef3ff997ddbfc021fd9a7f7e14528e029dbf1ea8a34bd6d3c1b590162255cf5ca312f13a4c4fbf7f1694bf9ef8c13c4228835e5064ac358197a0f492cfc03d02693391cc9bedc64c8ae5e8a5cf7bd2bc5ff21dcca1f0f1c2e3816c4aa479420569987d81095c32be595299a31bb47b2214eeb4de71ee569198e6324ee1d0a61263290a11ec09d53e95a01ba88e19b77c87ca4af9c7ab79b34129754a73f21d95bf27b49f9092f68e4006652a51bd17a70eb2e782616a4c7b68b21ca51b733cc83aba8c008e2e3e76a0a5930d3b06737f198f7e35c649cd3a808f6b5c46c221a972ff8bae73dff587e2e4c7bffd294fce7c7c7a1d393dbfac1208a2da43bac3b693929209adacb052130ed0571031a2daa7c49320c15cb2369a109b188b002bfbc685b28f23252f0c7c8e78772c64ae4f431a1744f260fe77143566a3b28b19d58229b88207e1cd6807c4b532e3afddc871604f4634d1aa8a34c56987facef8f0542b009e809d1cc3b1183ab7901901a2d243ad1a2e99ae3510be3e1f9e18ee350a71efd5d0188a27981935568dab49d8052bd9897f1250b3c00a06e5297e6110a8fa4ee4f5125cd984f89e88cbfc56596d4356f0dde74b53b47821867ffb2eb40f5c08ed3ea13a93c67c38a353593ad266b62fa30459e2af4bee5110a9c52513688429ba0311130d54146b896755768765f298d12527243b56e7b93f2892a14c3b7acefa08dcae079337bb942716afa804418bcecbd7da80e7df72827c21f80f5e12d1e7889ab58dce64a619b2b2fcc43316c28080766a9077a1c06679dba388d0f40bf6178a51383857884c345be6b76cae76d96695cec6271c4ba2eefb70cbb087b630776e1e6377bb7fce16eb74a725ce4dce4d345fcf6819a4d95877ba831e551e22655f06893c9cf3e6c70c4dd8503b752bf4b0d382c48957e012cdc4d4842b1b60e87f849bd343b81376506d09a428792b505e16a143f735dc1c41525d65d815517507021d177dab3d071dd606983ff5279a6c535d097bd5c9a04f3387341e1acface2eb8e14ec5e09484ccfc619114ef13aa34782a869868f26910a5409a8e4599c8d51eb95a9829c749cb0acbeffec372d96efb3fe6e9bcc4a3d1fe934c5bb1cc9ba29412b4c7d74212aadc7d22293ebd9d9a29bf436b29f4a0f909e827ab27dea4c2e96ac84c693d124c7ad2a06e7f1574146e03b25ebbcd16977414a0d6c9f776bffe9ef55388332c68ec52501cd8cbe43168681adab60271d8ff5dbb2143a9e9c3151310922cbadec2763a2d4ba728e036443d3e09d34ec25559c8222d62ad4c7953bcea2714541db0282dbe7a517f5b4448c819281cb349fa247f626d06325b1ba4968c6ef7e25cf728a7f0e8ccf3d7ce85a0b3905ca652b2d47d7bcb88a4708dc9e999861bb9105f2a21b7db7ae45be48a5d6a5ce2d529002f86ad4acf60b005a1edf19bdf3810344898bb0d2f778d0d28e1ad83c2a567482f8d34f449c3b1f7f77f9c7cece69d9d2835feb328c76b653e2dbf3591b7a345fe20d08939c44e35814c315c126589f4d9af5799224508f398b948471a28964759b21711304383250caa0599f6eded1306c9f796bbde4d2762113acfb509f6309d9a993066937aa40d454d3b50aa554fcf7d5f06eea7f3f38f3604e57a5af50391d70efc77d7820ed9a2daa32f784f5f1a042aef8ca3eec91978c71564527c0c476c7800eb37015e54c86e250c6067010ab900a807b4e53082120444c921a303f88fff58d81799d06806f70b8d701ad48f540a1a15b355114e445a9016eaa5f5f44aa4e72350976bacf73d9bad4dff0bb7eaee1d10f6048900dc170cafd3a6aa86113388dce252692de91e2ceb87f0bbcd89745faf8a841bafbc4bcf4d7e4fe6a9584b6e38c61eff3cdc7960bab9c76bf7f80c99ee7a01c4ed4a7a281b94ea4cd15de36bb5537c0bd95939e8312723ae140345afffb9a0010e3947724eed2b73de3d7387bbb9aa6c0242757b05c86a28907db40f6f248896caa189cdc9f8fca08b4838f62eccd42985b6f756d6a07036588ea2ac5f74351b62217d271a56b13223aa9dee9dd0aab65c13671581bfed8be412c01967ef430614f48d2bce5ab556e1fea9b791d4a00f181a883340c8d69c345bbfe2e5df739361d3ed19a5644b41192a26edc2bf414e39e3efef9f2f667cef7041c23b65c05be1036c65d540ed750afa63ef0e743edf1d8e5432f4cb3678dcf5e2ddf02031d740b11bb8d1ef840280c281966f73a07384f6bb040a214ce517063502f450cda6d23577a0579b36857521c6929c07adda577ee5b419cfbba5bd916b6fdcd9ab8cdc5bc20606570cd621ee0ddd5b6149e8e059b5d0122ef65af24b960059e6e33ef1e5a449748769f37520d35182526e7b27773839ee796db9ef18516a2f2f73fb83bced84a4eeadb8dec82644229c70ffcc36c8430f7aa03c0af5e7d15ebcc5f117f72c2475f5c7633f0a35e1c62d0001443a71d988569b736deb9586a651bdf5524c0a723ce82b390dd117d569605891e97a69fbb7adb411c39ef0587bdb4c7141f428a8c5b0903610fae8426d5519df1805d676882ecd6dc7d8f70108b52025d141085962cd2e3064535dbdb92021d0c806702e94d473bbb9f25f9a14ba68a8bfe0b29c58ed572905072274d4b4ac0b3cd6073ea655c23920d87aab321697cbc238996c14830262318050bf7cebbfe369ddc4ac5febe9c5b30103df4dda35e182469ced96ea05a8599f4bef21c82eefbc21e9038f9b31c45aff77b8a1c6df1d0a7c990e2b8f99fe4c626c8e87b98163a5df172ae906d6fa07547a07244fc837b0f5be861050cc0421bb7e24c192218621e8464d622a02aca5d3ca307524f938210c0e1d990408b100f4e7207c076db46f00c3f05c555f857d1c80be2d100d9152a7898cb0c60d171250312ce10c91fc6af1dea34b4f474d71157169470bcc13034d1e1905244acea926ae5c96df2cc97bb3712be994597480ba8715507afa9a595b7d4547f274bbae436ca13336cd99709fea3bfcb148e8e935cf7db6e2c9a2d4728c7c69b14fe8355ba57ba5a5b9122a59d7d6c248ddae10fab1a580ac75c94c23ec41cb17a2711d1ac328de7cebe6322664dc5b3e20355a4026aff461c0c93ca162bb42c16f85ca8d753fae9fb3f610e686f3b2ef9369a421bbd586ecdc1c6584a11b5ba026ef3d56a0b5442ba3e438b924e78c7b6c16fbad3143c4a036922d139ce5f7ea899f352049d7aaf61c290ddc6e922dbd6eeff8df24337a6c5cc25ea0f86d9615512e80aa2e9eeb0401bf5a6d5acdfb828b1ae6039315a829a3f255114ffa9f66445086b67cefca5171a90be4d5a36cbfac7d16a7cc77483064ab7a71e1b6c28505514561164e583c9ebb61e4fa9c34126269871f39216bf2a600296c57b4314a3eda5c5f73ce37c25a7aa78cad16ee1841b24a88bf7611358d41f72943e14ce4b27126cf0cd4fefdda530546b13da96066dfefe6b76d83555f586100abb7509a724813eb854283247f6e8be3b24636f201f22d54bf31697212f2ddefc36f598da8734840195158f455c7fdddc7b0a61d87373a61f9d919eb6ce4592a7fcc1e5221b5b0240eba510fb601a8c4447300564000a3589ae18118a4f4c8084e480df4b7bf036ef43c30ba88d3ca2806b332f480144fba241516d4c8bfbdd243d1c22e01f567815754041bd587037c5b3a307574836b751de4f43b030184bf340ba3a1099763b1a8e35721f5ba9756c12b1f4df66a1b275ee934b6729567ad008bd93123f05d9cc55c69779cc934e1e313831ba78b4ce01c4dbb8fd82f710900a1c98b66b1d8fa85c9d10a87f7d892ba683d2e6c94672c1eeed84d20143c2cd9fe434311c6774eb49869c75b93024989fbfb10148c5afb8cf24cdeca25e21ec33118e347608a38158a104e3261a32e4b70f724222f981dd38fd9f231f99537618d08d4fccaf8d0ad03f4b01fa9aa31c09446aced4b5d1be9ebae2171998d83accb3700ba8c3698c19966698087917abe5628a33e3357b5e07b9ea97f58980261b1efa36f62df257778bdde035fdbe8eee37f0fd4aa0e3c9d81037de8e56b49ddaee1427868a8bb5c849ed0bcf394839f0423508c60c5e0b0d0b2362be3bd06b65bfd3900d99bef5bdc6496d78d2ff072098ec66a664629420172669558ef4b075a680ba805a08e52ede9dda4d50d260e870eb1ac3433a26af158bc511f0a648f0e8e571180213d87266a5b70d820cec0267c937a7a3b3af515a575c4a1533b2985894a5e091e4b68024735dc820629cb40b4dba834bac47990de18b7a03d5a5d548e9abab3eadbfb0908802c0ce366b5b4a7b2a9a770192d29f64ba5f5a9cad9d8104b3353afa2144d17a2cc00ac6d657c866a675c3ec0e34d12a67fd9e360ce9ac91d75a73a90b79775271150c9717489664b1e5306943b311f2038bde865a7934c229f0d301b382d11e143f71141cb98b9ac71938a1a5bbd6c98e073d1f613674a41206bf49017a76183d980364140acd3e81d770b971782762707a0039c13ef8f2a5d8ac8e1c187db596c7981eab0a60c23ca4fcee9212c984ec09324d046eb9f5719749f48910887fc2a1c502afc38ad23a924d206f3f93067704d58349b67dca85ea3a0645b4b5c8644ddce37717fabb1b84af9b02e852b12326e92f4a668118248d874f04b373c648c577dd9c8176fb19c7ed7d32e26bc698d6ae04b488831ca01eeaddb880daa75d831d2f0925781bece3692a6cfa01d2ce3656364a131a3f17578a4c06ab5092e489162cc7c9d0c2b0e7affc917a5823a77b9250818367c21944a484269e90024143950dacb993dee27a12ad43c4ddc06824bbe56e833755743c7c0ce7a92139a1c16b02f38ca8c808f00bb10f8bc687ca465e3c6978176353d9c1dea2ff74b5e938a42c57055c8d8530c5fa25c865b505a215e7033c6267b86fc9d025254f94d88cecee6f8f242d15eb43a89f3325bf3ba5d20ee21b7bc1c14940bc6c5e82db2e526b98156ad5e05a6555d73b209fd80840add2a140a706927957818c23d2871d6e7ddb8067a8d2fdd8d01cd051f797a11343575a6e5932ac61a31a27698d94a46b45c435561f419e73f9d26786c880044493bb8f222b17fb2ad6780a910d6a1129ae5beb150491c55b6adab285d042155e1375263478ff0cec03812cf74833f873b9729a093bef595fff81a785166aa92656abee23ce186aba8452d1375651632d543d2e6e054a757a91d20ccd569e82c054a995ec1f9d309ece72e59a4187ca6ac3dcb6c47d989f28c659842215bc30018f261e6ed14716d18b94b74aebe507feed8f14c9a7994e9af02a2eca36420a5eecdfa4848bdbe36c06709182c9ff146ff326f645d33d196a5fa0fbfe2a140ad8e9c620337b66db9cb2e9b1abc1a59f5ec68b46e666a4a5745b831daccfafa7d9c4e5c0f7277e545b412c0e6915012c9ccada4da157cbc4e8826884f18a2b2eb3ff86652d32ab34ac399c11e365903d1dc734772fb6b18dc91d670b70c49fb3651f3e7eaab36280d4f086d9bb3ff2b717df002f2408d56c4d21291515ad3e314b255d536121c35a928af171273cbd5ff0a12d27b78b539a2f60c69321e19c2bb6d8bf7089be4bb39b758bfbf4702951337a2af1d45c929771996b1b9dcc621541fffbdf90033bfc86eceed4b46cd9a78d31a9c088303172008937aa8471021827081053f8656fff33b4a377c863a721b57c303b491e666288705532f7cbaed8dd644ba487bf45447f9a535f150ff78d5ccb0a45bbc2386ce70391d91cfb7f3e97288adf0ac404caf1ae627d880a9c624774326486457ab897b9ad6927c2c2961408ae9a30100687442f2d4cfaf09fe430599e556cb44aa3c0c771f5e968cba1ac4d553079941ebc11502d843bc06ac43e063718884dd8a9ce6f9d40ee087a822851227e0b857693497c433ae9d409b18a93e96808b8d6a8191e5293d1952cc37e0a9ecc40a093618a277c0a378b527f2762bb352a71504191bdea4f44bfa3b897d4956610c8bb59c83284400e851223ce60b68569b8ad1e83718f6d2cde0465282fcf346324ebe80796320f14b101c5cba79d8d73fb94f95d36b3da6a4a3cfa85e917422bb6c3173cf0ac9543f104ddc67d3a0326f1a90076de8102e4e658af89c550c4b8add691ecb04a732c0412908dec7cbfd848a101d1d229f0191831fa6d3edb330b4540e8ec60825ed43dabfd9c3bc2c9babb057b664e3a00ae306cc50aa4075995833331bfcc0d9160756345e1c62460dc59ec97c6544b4170c900e868c76186ba870048b360463a922f59e49cc3a7fd190732d365c8762076fc223c2892063720c14e0c6cdbec265ed05e08644a5e85a43c509a368aae733afb8aae68752b91985a291dd248557f1464146390215dab77ad21ee8089d117a6ba5e9e81922d9d2f81c65db12297373f43ebd7559b30e2d734363afc1442e301a87c838fa1d084ceeb471ba357c2b2e38346c3e9420ea18f68ff6470f66cb9c8345a02ac58ba34fc0aa09d548de014e4633bf77a9d9fcd81b1e2f0965a6882782aa35a2c5cc30bf85e3b6b39856b753071479ab86c5daaa60e6ea5aaa775ea35824deb9b6cd76c027b2ed89df9545b219cd79531577f77fe98007b2a2161419d805b431d7aa69e97807c495a9ffdf486e00082f1a99246c87255ee3149f26c4e2c81f1090646e328ee7035e211f34715814649a7405214ba5d92278aeda159cca751e228bea3d2c7759fffe19868c8ebdfb2a9ce91bf32ac19d1040cab1d8dbbfbad12deab7d87015919a31399f29516642b2de76a85450fc1d91242b0f6564bd691ca57988aa787ea7b8c78b7bebc561b40f91a129179979516315d9f8d6bcc1b4d5c709a9d37893ced037978e7bd39a663056ebdf941d78b63f040f57c3deaa2077bc15706abc967f9412af350607db02ea7dfc2262d5cb7f6a002dfff4b3a79180c81006238d5b391414e11621096884dd291e24d597f82b44f095a699dcf1825348278da04529516df60f9dbe1c1903d9b2f18cf764c57646419825302c17978fec68ab50c422302b870a7a411804b2bfb40109095ef0e78b6fd6a866004e3322f6d9a8807991284040ef1ed3104732bdd86ee34d45cabce1baca9622887c30d13f3e5894d9101e13cfca10bc2540997f1567c518e004987e64152dbcd3961ffd06690d22715b11358053dce38e32e622b5b913dcf3f6534388a19d18747f8ef006ec9aca2b754c59bbfec5042abdb607b6666f83793372df67d53ea2fb57898e41296c2eb4d4dc9de0a72bb1c06552e886a4fa5fba480bbe17cae6e9707ed52b6151ccbbc310bc5e8e80925121e32c4e13755b6260ba44c227b8a88cd8a207e3649f210533ba17357db55fbaa8c3b88e99c6c0098b77b6a52f0fe9558971969a50279e44bec34c7ad28ce6b81682243a62316796a10842a3ec054853b72ee04b1e9b0effcf960563e7539d0e29fb7ac5392abf51c4eaac56c46d5bdb70bf7151a93769dcb812434c686f4a5d4b6a64081ab5a6aa61094a08716f3dd6d4001766567415828b41b6afc46cb94c231136b263e03751ea43937881e56aa28d143cf8e0dc65a0dfc915843d0fa42b2eb6daabae8363bd70d7747deb008bcd56de107c105675dbf28ddb530499442c84ceac40826818bce3882463c39979b5bf01e65d31b0439b0d31be3d5b9d112b54ce30f880ad5fd288598e460e7b8fc62df876af8de7f06eac9defcaecbe681dd52369313267eb6ee1a987bbd2aaba9bbf9f399bb353d49deaf292c4df297616aa342ad78a26cee176b296ba4c5bab4c92edeac26cbf745b9586004c248f55e9999c0965146ae7fcae8ee3fc0163321d46212bc2b1bfd2c6f32731c86a4b3f5e34f762e4c0a37f00622e9b81af524be4dc672a0eaa0792386e50ab66e5a1aed4ef211c17bb0ebdd3988ea8ec8b05031df5d4c65d21206a0507b42165a0e147658ae17f5a7722525c020c621a6fb877de5579379e656b452284764530c446e032f35b905fb9f6fcd1856e2de2630ab8d968a1ec28be7492a2dae28cb724de4d0dac37228543deb570c78f4ac1aaec143ecee27ef85c74b394c97ac605ef8b24344853d4caa133b8e79c1214b3df5fa0361b654e74cfee4691ef4e74117c01448fed076ffaa1d5e45e269dc90853bb24724dce02b080b263187212126210c616844cd6ec5d794b435f43237c6049caaf915f5e6e8fe23c767aca733c2d78c79ed123601435c0b8c5f68fc78f85d24e78f483f111bcdca874523a096a03e88c1042389ce6d5b02351bd73781776393a708017533355b9447b5072e8154df16ad1266e2fa83a046c49f62af85c41a9fdc90b89e5bc89b71fdacd654ae46cf9cae8d58000b0edbbc723f7a8222bbce33478e3ef0da2e414e7baec45564df80921e2a85a9e045422df10aaa0c31d1950040bf6d85f15562559a1dee440e01e1f69c42142c966a44863ea0836a554a3daa541ee357e365ab0c29372cdc3041b0299edf003ba6ffb8118dd608ff157d36d7bb4634267cd7af6a74a677eded4cbaf26e8fc1ff80c54b20d39dd4c1faca6454c83e49d438a872062972892cf02f20b5f4512bd67a1d44b1a8895bc60442a0e61312a722c5790e4f89b4216390055091d1d116d7963869162c1d852c14338e3e19adf855107180eac2dbf24360f4747431c8116c0623f17f8790871ec71aa911e5e7f8352c8e193a76b34b686e7f3d5ea7aa6582040947b6fb84d7959a1fedc4590a60f0500d61581a4132e87e0837147d0d9187e39da23057730d9a41a1650116d7310e64b73d0ee878a210aafffed2bb9585b669a56cc5a44ece08caa4443f826e822d2c7dea38aef89ca8ee2b00b50b76f7917936e0b09fc908eab406a4fd69e4e93005e98de52f266f3d3a5329931aa3abb87035c4293e3dc4752b4c0b100c95f4654837a5d7debc2f2e42e96c85a3da9c77c8f6cc6f1b68a7afddd550b7c6cd80da8cabefe04dbc270d7eb6f6aa0a8d768e79fb1d73c04e33fb2d016881dbdc2fe60c1738e36cf28556e6741dd30de5fd474ea5753c80ace298467691e9de6f43dc4186d1cc3827fd90248aaa79804fa5c444c2869cc03ea7d4fa75fe5f774027ddbe0f0f8bbab5e29d24bf734c66ea6981609ec86fd467359176a021c0c65800152d3a092c77eb9a83c8ac2fc30ec3fc20ded9a1a9e6d2479a5f6efb1243bf7af510d702c0322cf7a59080fb85f4a7c015530963aa099275464a8728c295ad25252f9db9366334b4217114d67341ec9857b3cb4a73397ad4cc6ea3182c617b00071d439259bfd5d1788035aa645b8d13ae0d4be81dd42941b70a4c91d89660249342b4934e1749324214e38857d509ec2a232949cd853a87418094c6fe858d670e2b6230387f3c1feb8b51dcf06a47ec23256e8e6fda49c77096df3bfc85a8bfb0b6789ca65b85c04a7364eeb2d0fbb56bf02605e0c7562414890188bbfc3232e64253359b204a36d142d15af7a4a6cc3bb895620285a820afd11e0ac471012aba16ea670903e55510bd37b4c2909803909120f5b35bc53dbac584b0c7bec6ddcd21727f8f04a5583fc392f23c4a99d9ced8a746d5e0a6d5b98f91b74748eb1d59d0c3b978ffa7ac9a69e5a2677c4325c22fff18dd170ad5d84e6a70395d29d889c44c98d5a218cc303ac4b024f1ed659ddfb81b1d8a3d283a5a878bb45d82a5a5bd885345d961644147db21bbddd00d789d36aa6fafbf20609dbec76dbca458cd246a616bd4b12063f5422bcd10a0bf3bb4a4fbc0e0f6dc47846740a2c627b52afab408f2d5beeff3822ff793caf5110234d5561c47667e52936dc2bcec3400d33fb7cd20b3f6cb9ac37d17ff5cc8de5c94d17acbef488fa3752c24dcd778c05c9cc0310ad7c9157b741cc7e56038c5096c9e117e26b40a33b6849f8feb5a4daba80813c1507acacae7e264893fdd00bf6982f961adc38f700b47ad6564b8fe8ea8b633322dfffcbf6efd1f0608d8d588f079a9439a284a44aec1b36ff9346c95b7cab9a52da9a329fa19ad04cbb7b40387d9915317ba0d4613ac664d82f3917e369da0852505d70bab36c24771908fe6f0bdf9753fff5ba75852499558cc7448b0fa5073396553bca5a815654fb9086462676a40d886f642e3b2802f760e6e2c824d71941b6efa8c9c4df4ae8268c8996d04a84c8c8b4a5ab9ced081647f4e932c4bb80391ec0724b9ff74c5001213de7aa064bdca90700c5b4f1c149044f76aa95da84b36ff83a2988515e3409ebdb511c1e3380a72b23abb92b62176525ebf2b8878a63a18f332a4b7614cb87be4f188c2c3c6d3cf1ef793c7ed61508f759750a61c6c17e020f6f64705cadb71a7d00f1b6ccbaa5f6c7e8e3109d5ebbd04c0538734632d3ecace32a949d293b8fe36692428f3e837029292ec67c9917a6e0e6cbbcc9c9aa55361295797bdcc51c3b37d5bda704a51b4d300085d8ff3942777ca9c88d5776293eef4911acf5db72e084cdbcfdfc527026f37e635b2f9f7f222c8c8b24df4100c9f06ee103a2b67784f3dcc3abfc9d89e6abc7843c735002b668537907a298115c0f24bee9e056b89a1c295a823d8cd478cb625c78ffcbdc30a12889c8ac64b3712005b777260695d49536aef739576cca2a15ee577ad245c1d2ca1ac79e245bc37c17f537d4ff8162100915e53a3dd6cee8d92e016e362960dfc03fc7cd1366a3b53e51b10b568af5be3a4c4ed5096a1d56ada53d2b432aa93d0862faa4bfb61db3e14718cbffc21737530bb0c9fa3b3e699915ac92c42f0a3c1bcab0751b843bd2b4d5b8a93c24882860dfbcb05182d2d41b5191032096ac10b9b06fea905ef74f6a5238433a09e11749c34fdbe7055b47acf25d4bc0632f7ef6bdb454201ba17e900d8164d6bb41780eddf6e62c8459a3bd4184b93c6aa163996194398807cb9901a7666d483c8305d0e81056f1c0633a0a9c670373e33a800b4705bc0bf0d67f0e26bb29b188c020ce1e6555b58bc1e5e7ac9e4f9211607009df6f9c5d5f1e437c709c54e49321527c349edeaa6dcb782adf8e5dd92f9d6636bacef11e3c9cafa431e2bb6d694fd78e3e93dd7a1e0851b8539514510384bbee2da79986d2a1e22e28203120f65c11aee85fa8d1873bb19b593fcd0a027b7a457dde59092347550e44e2330b4b7ae5bd7c2d5b538ed7786df9dc0b32a982b55d2dd3c3a384af83b51025914c8c4233964ed4bbb8dd06333e5cb7530824e9571999223d6b13b8bd0811b5022d61c5cace6cf953a2cbc43115d61868b0c67d55698415796a016376e6347c596c7ef8e9bcca89b766c0229bedc5e1fd6821cdd78784902f3adbfbf82589bcda7bf2b5f7ace5685b1944c41a4d494a09a64fe469db2850175cc24aa01f326ccb8fe1ff19dac27df20838c95b1940c5baa309f0cc498b5f8580fb0273249e4af015897d38d591698e41888d3d6b2209060fb1979b2de3e05a9790f274e3c1f778fb7bf06a73875e86c9f1900d97795ef2b39a10ef1ea3c71aeb006885973b6d06acb83785494184bd04255707d7bf80b2bafe33e59d2139324f15cacec9994457b0d19da85f620c122da72fc4b692a7bb9a791f3a4522d4d8539be865d38985c5853d0bf8206b782b5401b72835ec13358ae5a7dc7c8ef76c08400662ac4f48bcdcc0fd3c50fb866b58754cd31d5c609cf49f0e9deee2887413f5882230ec11aced0e3b90a5ee99438f78222a53c7b5e548acd3183f25d6f16ce2470e13d3a78f8532645cfa5b09f4ff196d36e9fa0cadac0d4ba8e8447a023784cbbee9a09c395a70b66ac57a0938765509938e76c6f809ba607feb96592c1a686efb4837597f355c6d5af55997246a06976e013e6207b8ebf5dd8b49ccb1cbd6eee7df6606c524876a200538a0fe7e8a1c011e1f545f2f96ecb8e214fe57efdd46ee70c0ec1797d4428aa17fd0ec6a338a7e45115f49d9f4cb82a186e721bf0caa4cfadc53782400b6ef89062989aa9b1fbeba070af7e4f336b4c28ea209840d86d9ecf2e48f814d5f0262256abeacc626882c6111c6ac2d2736a224908a976c010b6ec11b895be086e216b8211dd73c42cc1510bbf863db08b2c6a7c7dea3efe9bb6bf78b42c9c25c421f4b2b2d530903a903f6badaee7cc7c8625e0b15332590067c7fb219b862af4f715e92b01f5157b096e2666c68078ef94090fdefe2e858cb7bd22674a8a408f1d63044513852057f17c66fe722fafc2c2055e5854b49b5b8120b1b15f38e175a6ec80063ad5a955df6560e8e92603d085bf4e795a57304ae993a367e1b6507d675d42b64233d6e1a7298ece807f1668bf32e6cd64e5ff396fd30232422ee16b36582119d6650d38db611042afbf8103f1f02e9ae04b503369ce16c578aa21513734359952005d5a483ef5353b6c0400d66443de006ea0eb3083212b3c29e49256a247dabc8b0d2189fbcdb8813ebec13ccfcbed01056541746537a55d42c5531342be268f549f760900f67338615d6f54a9e2e4debf32fa5e4bda44c6f2ef5feccf99d88abb2473fe8363732837f420b560f798f4279966fb4d7117f37f50e778a1185b6ca3dcc83e93cbcbfef400c6660005a1e7d370fa522256aaa88c9a23b3a6ffa95c674431c87027f97799d91b4f51d485ce18e343c1e7fb85a7ded7d129f5792b4489774ef8c59b8135cd1dc28c4a49687956bf8b5e628846e15a0d7f95c735c6c304cec2a5810c812f6cb42bf31413e4c7c030077f25da5614908969584e9737f4ea25d2a3db0fecb14531c76c06dab8f21b4c14d14ecaa3586432f1bf1ff167436c635883481a2ddfa1561640d37a3754808ae7fb3acec8508a05f4eeb7b79ceb6d1da4118913403abc1951b415ed8b66b6b2674649adf8441bc0aa4ecfab21f42480d0b26fa064187cad6758aba1172461dc7d374bf0f854d3fb6996a8a8166404304f47be74700cc9d116a330c5eec2295e9841121a26f8584a52912880674103122b6b833a453dcaecfb7696966069c2415a22d68ff4308393fe041b6f2ec31a50bb70c5b886234f810e19c803e70b68099046106b6a96332264027f832cbc23dca1afb104dd722cf07ffdb0f77535473aff06bbc35d7d84710511c16cdf5d118e4751186353cefa84328168d43fc42207c8eb2c63cda73e17ac2ba426b9ba854fc52293d6e3f76bdd5186b50824fa5dd4d8b081a66608f82277e7d4fecb0a2bed0f67b50b3d8ac99c6d45260660cf6dd20a2ef64c127f8f7434a30ad4fd3280a2b2f811676d28ed71bf0d6ce901cc3b1d18caf39b5ce74fa42266583df5e40af01d218b4f13db45cb993196ce8ace465c44258f41d2e9e7d6bfd5b03bf8412e7d32a06b9bfdf7bfa568b9ce6ed8fd0eff44fab30da2b457d7faf186979f4d5bcc33d32d5b5c0ae1ca61b787cb62d64223e981037c852f3c9c369e3421e81e00ac787fb3bd61aafbc660b4734c56dfccb02787779ee6d885abc639a5c206db8a3c11ae5764ba5a16d7476a91d5154898b9e88e8fd193a111493e0f7bee3518dd4e29b6ea48e6513570c1bba0ae92da1179bf8d7e5c4e90345701f315eb9a5f8c5cd21cf63ece55849b74c2b7857925d374ddf931e07abd2b45ed335e8da30b4213d2ef33074b3d3a663e0234cd7a2403e03a129fd79dec686595b8046ecfccdb6d8f09d83a5e7ae29bdd1c880a32019744a4137608e97c61aa2440a322b10edf02b49ee84812dddb9a4db20ea386b466d51fae5ef489a6a5eb85b052ae746d2d8b2f9191213d5646c59e153a3ca7a9112eeaa85b8907a1c560b957d66e1ac5a982ba9c765bd10b27d29386b16f65a6ac1b5beb0b2be18ae9585b8907a1cd60b23db7929a0ecfc17f843ee08d20e2a833223f108042ade7601eacbf9b22f7959165f3cc41051bd0e4b9beaa0d9f0362ebac29e9d35d3f574155cd08a490f85eac1bcd40a39a1d66c5eeafe088a6d11a553c4a2b2362f8020f4a08c791b65764f74f86d03e3db4d3adc9ed35fe4e146f9b1b4d4885f2a1d8733a8a3fa520931c66e0b9714628914a8365bf710a831b42d5817c4030b909ec31e6a8d6fc1cdce6d6f0fa441ddf9b12a95cc1d1635cc637b12e4f598205a9f7c17380203009622d2aaabf6c2e355182b6798b35033a78ba4dc313895e71da8684353eebb36b8fbb39d438f0d0544f4977a74bafcd6fad2cb5e119f62163cfa0b0ff68a1d2c009c87560fc9fc89d4dca8f6a8e032cbeb0e54dd06254a00eb0967ec1eba8cc5210095485e37d233f7af504d9124b09b5102e71ac42832a4def21e1e3c46fb57e986b222842c293aa085adad5048ba071c33c5edd6abb3ee4a0f69d18cf0d94eaa84979b326ee699c97f09f0a0b51a27e4a982d36dc6336149be246c7490e4fb8fff1339c34cb1efc42995b3e03f189c2c595017899358f45073cb6cfa02a65d25a7d7b470ca78afc11f564046d647f3ad940ad5cdbf21195091576cb33f2a57396d72b990aff4df2423ad688c1f12dc7c62a3940c985a81230b337d06294b1526c60f59892f8dab86cd0b85451e0936f548705d291eef230310071e70bd391444f037b0021be8491bb577da60d128f7205ce2f9e2928dc7a92c8c45518c59a80d68be9bffab20afb88908ee57a1de08d3d5bd6037d77d7431fd32a8e8747fac6526f30a13ea745158aa1e954805b24efed1a9270e3e73948a44f4643449387cd94429ba17a5ac3b83b39884d5d375ec74ff9a1a32274819b5c4b50e23c7ccfe7361e068c2f74e418962d5284a6e40e7f39430ffd41309604f64cffe9d10024a60af05b1ed59c23d2b09afcd234fc7802fc1f57b3aeb6ace0b9af421aa87438efd45a2f86357b75ca79de0ea1552fa8642e9e9634b937a7523692ab60c54a4588d2f811e496c5f86decf442961e9d71c3032dff9e6ee8e9a36dc6f0626251dc0849e3535aa09486f0d5ced83768b9d5bd812749975c4afe70874e376e42fb03acfd7cda47ed0a0aca1ff53c9c4886e6bc2137dcc714057745193b583cb194258e08cf745f48ed7e5e31e00442f03afc22604641de23e7e3f2bd3808f04feeed115da40854d6371a87444088efdc5ea853db9f582bda0034afff27b50718dfbe5f480d02ee85ea097673a54f01ee9881bab7a8d7483124c029fb0a5ad86ded146431fcb3e2d9ca4f6b00ec3f5fc7911ff6a5ad9d8211449c54985d723f9194b01f52c1a9f96b7030e436f3f0873af3bf84bef554dd63fa9e007b37b5f0eea43ad53aed56fa39fa44f0e4f7f099b0d7684ae3d0863ff33d6b78eced436707f0e38666ce8ca1559a6facd49110c385ffd70fa9600ba013a3a5ad9546a170bfacd087406112e33f00b218e7d456da6c9381948eb7ea14cdc2f3c555d8ff4a95969e6b53085b3e3aaa18a0a259e4155c0fdeb1814b17f0312964668bee5b52bf3049b8a073a8209d2414f5bd869500837ecb572fa98c9e731243b84269d491696ecb4ee8195e5a84453f6cccd494000b79c364e706962baecfe18c550c1297fbd0e8485679bb2a889c5fda3b39bcef2fe9102a731e6ac48203f59f3cfc71b24a75f5a3f7d6e2b40e809313f3c1dfe012d31de556b5014532e3e4f0d8a8e050bf618cf08d73fb2335d8af203530938538369f90b40d6e82d6868566dbc70098b0f5a4a219bb9a607813f71011842d1260a09a3585fc8666b84ace44d8c1f2528e8a84621924e0d4d90a7301eb942eb285326835b5d57a8f794c4b75cf705759bbd49fc8331c31a3f3c55494eb547a50264b6f0d1b9412d629a6283fe6f1bf3cb043f1e5c541f0b6d18f425d59c3bdb7edae877c99306c21971512a5331b9419951b2358cde25af6117b1647bc15525566b9e4941352ac9b8349d56821e01b77d506f94a8245ee70a21e805f6a0d03acbebf8fb4485e1f55b1fb08a411c67153e0a36ae43b5c780b0f280e77a5ce5b5b353c52bb5de85a70db836c85365deb155610cb917e7dbae97446ac59e04cfa396841771edeff76082b0d9d762b99687c0b6acaf2f0780ab7666d20d30a003c0c78a1d524dbaf1d8595cd84b34956f94588a3a9c72b048d18443164ae0096c45ff3083b148d2d76c2f0fdf4f67b8410f3000c11a6637da338d7cd0244fa6ddedf9c3112ae93c80d265666f993f118dbceebdfed4877952e520ca51d0334b263b4e5825a481f4647d40e83c2bc357ed564cbbcbf3b6017a0072ea601ba322f4daf41ba26a6d9541c2064e0deaf2eaf5e1a854d0a787374ad4c6cde2ffd7911a62a6ee5e2938c473dfb51e2cabd40e76ff60f8fb3bc693514e658cd562a9fe6ae01fe6ba94b80c5b87686df9f828fd0a670cad106894b533627a7c305c5b7394ba658f6b84655c892db0726419334c5708ccd718e3b10b5f2fa2eb7e1aa5185e6377f16c9f84c611e2cbab9e01b1fd22994c19ac0fee771df7c4fba8853d9491a2cbcab09c7e44cf4ccf217b066b20205aba01c53cc5e0103668e2228c3942166ca38f54e5e7532f038d96c880f28c8889701291f26de9e32a9d3eb56685e3051a3548a1e73a050e0c341a0cc23871bc949869b5afc16b887e5da59bbc1c781e0aeb20a6972b0016e4c0f8be96cb93df0d72ab5b4a8ec9b29d5d1d8b98f4911c0330df20144e7ad23c0523b11bfc51ba23f23a9cf92607425d01a1baca13ee7df606a229bb23ead2403c542d10890b6725176d7d5c582fdeb349aaab5b85046d51714d1fbfc1d12a2150303a78fa7a309ef0420fd767209a7fbd3402213c4dab3d767142ba465b5ce07ab98b7287b30664833e8585c3413af436fdfdc2bd41000333b1864205784a7d0668c49afd2da160c3cf733cfa1123dfafe21ba6fdf334fb25719e070865bb1e7733cee739dd9e474e91272e82c5b255454b08a571e98bc495d43cefe6e1533acf4f9c376e403878fd29e2b3180d546278cca8960867b5a1fdee0dce086107def211447479200da5de78f9faac793b41b94f1d0a746d4c68fb30451e952abf2a9ef041afa0b033385032e5391cdd3c71c24b1ba9317e8e4af3622b6a8e2400245eb5cfd1252b74840926c28ceeba386939e65fa99f8ad53e17301f25ef737efc9fbc1bbd64e03aeffaf01c2829b5e567d5b5450b204a5661448423e1187d26c6b077ece24cb91dd6e120544909d87d5d387dd930354bfd6f51b606e44670d425bbf75cce1cd1cb0b6886c6a309bfc7cbcb7b32e77c5c148eb10a116d509dba6bc369a3bd29019fa07ca867fc7c72de0951d1251fd16fba8df66c9a5696a2ebe4c11cda610ec46315e6f98d2fe850cd064100e30554eda64e76d64162c4d9439d2c457c4e60c4dc0eafc0008f2ebd58c05d8c2baa2ff7189881e23175025cfdcac0ea82463bb1d2cef9629a13ac9b011637bffa039996744e42221a46d282cac5c628578d6f2f005dd7f8c2739c13df3fc831efa2cb1e1eb140ba08789370c713c585b7cc8344b2067d3489caf9b8632ef4374979d75a256082e6088c8ead392c2bee3658a973da906bf3666c298b03e764a4968680b7e56a9fc56706e8e44d5e446ead3bd70fbbd18809178fbecbc31b90fb5ff13eb18e4ed842f095d1002b8030da6fb1c70b5f5550b54b01c095d484a5327097bf125622044da3cee761ac96c9e6da0582ee4c562ae984b85fb3219d6c607aa3d2891f39bb964e30d60bd0017b3bcd2f9d2cffcb03481b493c3acbc79eb5c23c42ad64320a9bd41433e5e34fe840a18be4c40a3c922cf26c5985be25d4fbcb8831399b7baa967ff7e77d760e140d2c9e24b6c227f8b9aec3c9964f37bab4469bbe773b9ca4dc3288be9f26ed13f1f795111e194ef86da4c7fae8b6d93093fb65155edee7a6191920dba9d3dfd9853fd06ca7cf2858d75c7c6ab99c002cbe4df00407663c39331338230cb24ecf292310ae5836d60c9d9c60ea34267774d8391f02481d76e12d366f13ff03360df59d3bebb5fdfce643242ad3be4ef637b049dfa8dccfd33586a3931649b14951969f847fb800926c22f3cb932cad2bbcb3925f2ae0569928699502784486246d922a94efa50a77a729b49055cbda24b0bf6a45c69b5a23456f6d12dac21837b053ab92f373117da7c21d717bc50f4fa12c4af78c026b09ab949681f891af89118b79d2b000001d288ac33437c015bfb4414cbf9b4dfcc53771387bc5144f86fe5aee7e30101a7ab6aa37419b20cedd566a130941770bdd77ce35440dbc6fb2c66a0ff1e5b66623be579f393b7d8c4a40a159e8ba88cfa6d9b43d6d84ad22b6c16cc61e1f089b349ae19ba0a2da0d2d0b293ddf4222f4500dbc484025c6efca20af84dd88e67704dc1b256c22ecf553e324f8de6b1bcdb50e72d3a7f2f140f33a752d2f685476825ba4b6dd2fdbb74e4efb7236eaf84d7bcc0e1b5d339f10f07a52ba34635479e8ba52fe071d6602aa3c8f78446e0b852ae1bd3721d73857d8f86b93e305dfa5996a6bdd4d8b31d8f47d4d98fd95ae8a0ab48de85c08c0d730b8aa8e7e889787e762411e1c3661557f69c22644197f4eb0c90e098d84b00979c44f006cb2cbf76d20854d7c8df6e688e8a4232c35ff73fd4f8990dd13bc65c854acd9b2d4441615b7f34ee691d23e81b36d2876493521836a75853f69758b5ee65a5d92e94fa418ad2664102827cdec579327c4440e09646c1e41fb2ce1d59af4dbea5d153448fed226849e1b46aa1dce3b53cf512b4b7d4bbf7ba9ca499954b7a9c2d175275c131cb25a93f3a84624d6ea9b6393e73690e7c0a2ade4262ba686269f249a80c88afad0e5beb8c726bfa6653d72e25201a3cb3da26513d2553c53a2b991ff29b57c568223668166c90e26c2cd486593f8496d9bd18bfed14d6d926eae82f5eb07b671854289e88a78f01525eb61f205ae9d7d7cb60935a3f056f573e29954a650b7a6db246e42c13fd5c80738b139300237510b5a3c743ffa2e9adfeb9b3d27584a6d79bf8df1b650fe1702bee978489f46b0879c3588bffcbf3c868c3f1a6c3fa3824f53cb4d30b50182d088958ff13cd86ec2b8e64de2af9dda0c81de043f5ed8db9b04427152c3630e2fbf893bb2fb42411ba935e92dd0e6bbccdb64fb73f9bcde84b725e76baec7dea6fcfb94c2cb00c92504ec1b20769d7b30a7d9844b643ff55a0b894021a0144a9bfc2d148ab0336e1f84e2de5ca96489b3b27dda84236e12daa5a8cd26293214b788145b3091bfcda3c63ef28fe527b0d61f0a5fd3d89db5131b30018449937e621adaea3132eedbe3be5022ebc91e5b9ad54798d7c3d045a7571d88f54eb596e94f94833aa0f95d9dd875e99f545ba61ef060b5f7cf2c5b6a73cf921e4d88537e3748cac49da708f419e087879bfbb73d8ef4426ca37ecfc11cbe984c8aff03fbe09ad6feb47b7dc07427b791a0bf28a6496c1e171c88829b4eea2a5c3c883c1f6529ecba9dbe8822b6b98d1f9abe982dc7650fd324649792b998dec355fffe356d4997ea898be81be3080150c263ce1ecf9a64f9473a1545d178de451bc572f60ecf400dce58e879b9972cedf8e852855e29f360ed73a5488349f4ab048f47ef8b3a61467c3d8ea66a4ecff06987134b9bd3328f923fd2068eb1856397a32f3e60385786bc59dbda42e13c12a3ed43a80e216d445924b4825f5cd4983ddee18c6225c9831fc004eb095a7000479608ff1e1d5cb62692015677c1ea21b7d05e5bda411d79e2026914677b00d0dbe5897d267fb17d3818a8c2052ee38e12bba64110f3310c45e0882362b872e522fb8646aee8038d381ad609486e8f916e497738d1096a54096926aeab72b315e97b8f170266733cadba871a01bd6de19f48f7412d79d175fbac70787b44bcc0cd8d43268f018ddabbd9caf017c10d43e8689e4772fb8a7e61326d97098629fe97c9f62f6979b0ed7f5305ff5a51af01444a2e800896416818a045710b64643df4ae37a27ddd1077f0d163bc914d36d52f4c2d2e5c33ebc490441cda9b4e18415a8d79738e656b3d64589d3c7f18f06c1674f9728e514bc510c14350940852ea65ba9600ba957e88cfee6512c7b09d6a3addfa2ef5a22c7b4481e4ac5c8edaaf9d67a0fa58ed7643f9a667454df6148f8c3a7f2e11314f3c19617934bd84fa5669a2a6bd8c29c5b94511e08829ea8152fa37b03a420974d4e272e67691aae7913dc05d1c6a364f1253cf937a49e749388884f03c6520688cefdd2497cd271afaae01b20c276412aca9ebdc02ba308d6d819c59625b837bc0eb67d6f035facc57b7ad668f6b19db6da294ddbc7a8bbf005da635d03db064061b39a74b6dff59dd91fd6cc056b940fb401f63292c3aad3b141521e4c9f6bf709a13a5210ed3f5323fa3abbfe853ad66368a0585c53b8b65d5d17510a83f7ed46aee4ea4629a0fff6b7b345dbe22cb633bbfec960e4ce1fcec2864615b98066f9035eed1520daab8032600b2e1afd821d15c0bbf323a31fc9840bc618e601274ba063b0aa49c4f78d031956a1c26747420395b73d99bca00a8f3a7fb4a55a712821f11c24e228b792a12fc74319d95a08b48c0d69c21aea155fa23f2680a302d55c1a1b835a4be9e93b7044b67a4c74313143eb38b779640fcf81b5c32ff271f1f47774f0ee607d7fc3e15cd741e5f2b70588d35ae721bafc4ef1f8757e47c2329331f2319cb1a6d8bcb99ab687742ec0cb5d57e1f0a24a23d6d11500b3072c89af622bf44daa902b024272abd5c3cf891cb5f2c7d293b7e85b379ad3320d4ec63481ccc449de642e961c40ba5f6fb72f6993202708f2889e9494740cb139bf00e4e9ba3b64f4bd7070e61cde0c2d03326aae0a100e3100a8d2bb82ce58195190c3af3957f1f7e9c6080da58aa750bb435fab3b230b77b9a05f53fff31761f01e3f76562539a4c41529350d59652f9dc50a91230271051ec449b2129fafc9f6527539f9424aad5f6db5959046b3d17f6db4a23a75606eff5576c3cd75e929a6b161a915d708629ab6575b7a08df687bf5059b20ec9a6618485068aeb16cc7b5562e06e1d9960116dbd1319559f1ef68c3670a4dedaa5c8c9da0d65339154b86e6d948e83503ed6349c689330561dcea7082de56d1a859660675ecdcfed0f65b0393db6a46943cccbc963104ce6cb001822014100909411a90a4f3f6ec6b2d80285cc1729334488ee740c7b5739494d312a40627a4e1c16825b42e0762e8f9ae1992e2d8382cbe5f5fa5b1ce988ebf0201f3cde0df8ecc5edc76606c6ad7a7b4b272ed4673be3f64f6a8a1948fbfd7d84a1be4ffb15068356dbad7aa8ea69cf8e3dd5598def36795749db05391d7ed4fd13efaa27c70054c201e3d332066e32f75861ab18da27ff4d8f7032b7fc80c6ca0af4c2320d0595e2d87255cd953f82453afb6326965fa20f7e0c5168d18d51d31f1590f98219509e33244db27cc32546b5796e6edae0292894acc39f8f44eff0c90965df14304668559b37e8f5859a994d04673e63611af205ce0d2534ce4bf7b64682865ce9bb271b87c54ed2f7f54dfb525e3292ba8677c0521ccc79e014f40b722b096b5f05204f045c2bdde5b7825cc0901bc60223b316c28d12cf179978d6650bb5486b9345a7ca6b38f28bae9847ecf45a310cbc414f845a8e0fbb338fb518da3afcc3d1d68e4376649c16aa64547b7d8927496560eb7cab24c40e1117114958732252b06ea106f4c2674988b0455e7d82b922b9f868227cd2a4602ac2cca332799ba1439d7fc7b4e12b310d3aef9bd9b11d25ef7adeb726dfc9db1855f70c1ccf0ba65734868019c05a5f357e412f87f006979e96eb6d54a77d607f73395b79857a21aae424c2a90ec200528fe75e278efbd0c1da0abcb04a45ef4e508a975d4025e32d8fe0070407d86539b694e052e3f98ff950506a5e6462dad15c633af7062443a720ec69f6812981ba486a2f457be5d594ad9b0e41f0f83d47c0ed9b8bf8737da07e4179f35e669624fb5be049834ed3e7deffa30a13b68e7962d79beeb87cf7dad27c2c4ef1e92d64ce8be418013587dada99d03c3fcb4590e9e65d790894fbad2bb9ab410071211ca2545c6658e87fdd6981b696acb1b0903186953af1f1e4c01f74988e53114ce4e27ae5e3949bd3d9d6ed63c25d90e3ae88cb3b504d77207aaba517c73be69e1af572eb6f3400eaeedc83a9dd24f62e90c24de3e4ea5b063d0923524b4f393cd71eb0c75e0b88ed49443e7d7f866cbb68afb2393fe90fc7b4b00a7bc5d48f8b26a68c864dd5a1b3f3936ded29078add292af578716200a294c59d98fc174b9860e9e7e283b9067aa6c9eac319ad211c80b3500efc4d4e3b83531160c7cb2a8e36cf10f594314d46e0153b8332f7442f76966c76502ba2c3c29bd02658ceddd418939774a51a8d173b83abe106d317abb3fe933e8f95b8915ff6072cf519892a2d4a82654b4bed432019a263f486f52f134f46f613b6a2ac14704d9c489144f86817ca8a0fe3aa5779f1458e09de5acd3139fd8baaffd077eb389ce9ea306f2e0a4465f54b3207ba21abe6661d3caa61b6b1b518ebb571af980fb447ba339065bbef73f82bc6853edc47580fb1e916dec4224ab64b866f26a787a0b157632b120a043d25e18348ad53810324ac47fdb554f42f9d6d947c15b4be95012f67d6006406d6fd2184adf581b90bb881469e8f6e52a3bec3a46ec7c791641cf44e43c3773f93269612263c4ab3a69576ba7580bbc3bf821921196f85770939a95e62dd84c61cb52be9f59b841e22a871ba5b95006328b49583f763442b984ef5611089486adc4bfd7206653e995e65f4f925949e2371fee12b105cf27d4c69a7825e5762653d53ba4a7a4c692aeb9d2931cb2a371fbbb553041f0c3226426a0d64ac884c78866c5011d907de8bed9c5d7e1eae9e5b3442599233c3a06a7f80b7cc85ca404654744a2fcb40365ad5622a634b0d544a61cb40d23fb8f21e8fd41f042405418eb8f5b63194cacfc0102d6afae8ffca838e9076624c541a53902468f58162db8247672fe151ac030955ea2ca8a39163131f384d0bf6d683d89536fb83d7ff2875bc8da15df6cafb0d620223a07bcdde3e3efa41c281a965f7272d95c8271aada0fb1f887e75dd218c948790c06c10927e72dd322ce4603f6884b76a3423f9701c22c2243fd1cd70a0107976efbf44a24439fd37315f945aaf48fe7f527fee6d1a0a4ab237bb7f1612e7085f95cbbb23217acebdd3dfb90ade699c9e5cb7509c7f709362569dada839f94c07c81bf21166cccdcc67ea219f6d1d89e70a405a4dd148831b2ee3b93b53e12ab965b8ce3ca6fbaa714dc2b19a7dddcef08506545cba8848210ea2f85b4cce486ebfa340b8bcbb2b3fbf746a3b614c6132b6f1f0cde3738bd3320631c1cd241bedae3f955499c39fbf234ea69695acc544a0135ef0290e2023e105e27a20dc7d21bc907c14b7095defbb087cf0e39d863b261ddb8220f804e18099906779d6a991c00bfa955dedada414a40dc82a7b30f8a44b1233ce338505a1a51edeb9e820ae2ffcb3cdb1a6a95ec408010f072722412684d6bb041047901e896576a30cd0a046538a7ceca1813fe1e0d911acc519a45d70ddd196a708bb059faeb757726faadca98b4dec44d73794f7b29b8bf8150f4ffafa0a83ed26566ab60906d45e226c9d210e82aa130dc2e668f4b16060a015d799a4b612246d4dacc568b51bc6734e1bffd176584b3c7b0f9c60168ac3b6e8b5aa80a386fecdaa2f3e10922eec657e3818b4dc0f6738f080f43aaaf642597fddea63bd0004f2fdcc05cf6176f4e28a7119fb93cf0f42bba540ceadf730166e6b62718e4626b9dd7b73aa731886e04c569f65bb811b479b85458d0462f460f24ef8266970340fec3b63fcbe0a71e50eb6e97b912dd903339ce77fa470eafe3dc1a5fd7768823bd31f21b842f75da531c67ff9fdb89516ba88a252edeadbc12257472c9e20248c754d85b07829bda15a10e8ea6d9e6f9c552273287d2952b6eb94ee6f7c8adc3593d479024b1ddc37a9a0ef645e71dfa695581084cc25a3cfe8c034a495bf449e69293e185c2ca5fc3d7ea1f65f7ba1dfb409b351aad879df61e678a2f5592546c59cbdbfca05bd3e6491b51166c7abf9b4f1e164b6dffdc30a63d3ed37053d0b19597bf3c3de32caaefca583cef4205ba96848626b444f54372b11d85b7d3722264a5f7e4b756a82134aa003035c055663e2479091be677f333db48103ed850e007be221c4dfdc2773f0b7818c7ecfacf76d12bd1e8a7fd68a069676f4ac413f4b334e2b0c5f806aeb44f1e6e61e7b01593dd9c35d3a30a2be53b795e88481c91d2db28f55a3a0be2f678df83e3a8f6a063430fa4a3bc6db11be7a3d7665ca6114225fbe6d327f94f4837460ef2e5e5f01226e94945054eb3ac2325c35606fe78797c40a96715d8b50b07792f55a2ee202ed6e67c8e1b4ba38532cdd03ac972e5c6344263bf22ade864cac784a910fef5f1be6ea3827be8146948b70474862db3b513704c0d5582d32815dddbcb6b47880b370e0d46ece38da3a8369f8c58d57265ae86165c9b75e36825b1760bb4488240792252ba56e5e97dd85503df374b0344f3b43dcefd84946c068dfae84ffd81493c77e94df775573cfc340d329bb430bd4423b2cba0f94047727e78d80d4721e048f14fa72366ba96219a886c7f34ab7bfc12e0397db83d6792f5888ff0217a634d137215a3a334af13425b631293027646cb81e8a16c5510302048a57bc3ba3186fc4e9743a8ca6647b40d1db8dcd43cd9d017e2ad8c1a61f2728feb516b160ee8cde3d3227884c6d6638fd31dfc29b88483ee74d3b13b59cfe4d5df445f1125be8323e145ce51588140a1a4dbaabcb3be492718c3d0bfeca0cd135e396d90a91c43dd96447216bd2ead4aaeb24de2c8ab7e84e5f67d9bb7232c18d63508777dc0a68aa9bfb0cabd03dfebf3c522c988b9cc13ebe6a1a6f73bf9734905d5a66ad2d4c81bdcf6346e69266b200219b15c654548210441b1d805a0277117226c2b820deaabca2f995cc17adb96a4b91a5f2136dbcf57810a74371cb224af2426293a54221df5bd5acc8a19d89dbc15b54854fe702fa19d7415ddf211368d4ac38ffc17463f5e789b301ac389cefbab170f1b5a3d74fb54723aecbd1508f65323f7a6ebe73ade7b3bcf486bb0c426aa60e15ee79c5591cc37b1732d0f256edd0fd7e66ea0c3ac154b28a2f2b1cefba7d0ba0dbc1b42f7d76aec00ba09a1bb67129b81208394433334444c5be959c55adc352d9429f5fc252f6514fc16082ccb94fac6a0bb335f52709c4c760d44bb54a0b96f4fe98eb40cc957e8b8fb1c7bf6481cfa85283c14329ebcba8dcd71929286fd8d6b09ddc19440d699ff4ad0aae0f6641ed81407a51da5877369896deb40d79c187223ec675325df222d3c7b775c9dbb658ccf41d9c02614e2bb770e4967c867d81ccb173ef1e7727443b126f73ec15ff7da3680aa853307aac76fd6b369021e4ac3351e1acad70652c80f37df61c765ea96b3c4b0c535cc18e57a7643627116f7ccf203db3fb5b04c24fa4fc22807c9342816c2efc476506a278578551d9298695e0002bf29a0a5d6f8de2be77f8e648fc1290c487d74f82fbc5643100cc481cbcd6fa04ab646087e449586551c64cac953ea75dc4070a08045bd3492e6f52f8e3bd517fa9f87fcb932c60aaf72c930171242a8c7779d8fcfd525aba4d7767872f922c4a0626dc8af7bb5d42e672cd22148468b8acf18f9a7fedaf2b798e0b6fa5ec6af6c6f2a56438c39b60c611694152b713e3989dbca233ed0f9d8ba484e23c06f9abca1070c670d774574a6a092bdd40fd6dec194e3b65858580208b9015823a0b670c3c64da483b5d8ef3e59941e19740291caa24ec8b8cd76e5a95e6038c9e94624396e6262e5cbe8446d4808745cc40a50f8a4c797066facbdef5891e5c8669a82b3882d0d778c7cb0fd78d9446169ffbcd967c4fc3792ac95ac448cb340dc415a5e662b82cf5be24be628fcc9b07519b504cb066a563ece2490d61bfbf7a9a262e95137bb365f0242e89300ea5a2e66831d7940c05a66a1840201dd06bed5fab80a8b4e4809c43934ab1441a5807a4ebcad2139aa7e118482f738e298c3c3ca8e042aa40cb613fc568543092b3b9e93b0ea39d5d2f1daa4590536c08302f427b408f600cbcec7031aaf2629d33963df4ab5c058ae6a119c5962d01ea32752a1dde3bb3ce1ce58da8d1c0dfd0dc2c7fcc4543dbe10449a160dc4996d5f32f7327f7a9b36298f4b50137c94884c550867fb71de61298e9a9cc9ec50cc5a3ff6f16736f87e2f3f8bd49f95f56358cd7a8940dc11aae327f8462baf8b61e848b71072e3648d998c5707ed86e18352b6204486e1a330ddd05367db3861933d6b5c6b756817a801d1b63b61cf487b8878f75c8a7ce87cb9146206fba0731c90d944140803a68df2d132b5aa5c11e2e7945ce6d99854d78e79158353671593a03add9e1a95d6e343a0936ecee4947661e8632eeef0445d81744bd0ca1a25937741c1e071fc1265916d3ac5195f81f099a4b9fdce199acd1c1b3c66bd1136b1df854ecb29dbb303b7708a559bf29c29ef4ff4f665343304931922a96fed792be1e1418c3b27e708065c0d4974d54201a051317c433de4306033577920e0a117e28931542ef7e7409b4efd3935c832617f116bb86948cfd53032fe8c00337c8c7652bd0e014254656a8276cde7452e9f077305ca2db601569e9d6bd499ff5709385e75db001922083eca87faf375c7c024ac745615f304ebaa20e85de0bc83478002d8e49d7269f3a0e12bc913e269f913ed7e1717bcdc7565ddc9a799ca2756a130d6010ea7c9fc690700890e1751eefc757faff1687a1bc5a6a00140e1ee307f27b793c09d8aa64ab58b27793bdb79452262903b105e705ef0541b07460082c493881658a1821b05021244bd08f2c457ac84244cc922c4ac092d0aa4da1647182892c52c44065f98284162018d0e2434c07f46c53285a9850d1428216b45411fb41c73685b2a5855706b6048961419b9b42d992a4b5023db329942d4e314f34b929942dbd146ce9f29b42a10203df9616dc5104373f519541db0f4b194cbb80a23e08ca64a20c05db3e23d0434542d9000f55e679c1c7dfdfef9fdaa736bfb5a60106e03522ae796a90f2ae20f2afd749f0cf8fcb06b87ff44f15f0feccd35f02f85de6b50a9b11a986785d3282346c151c1f40aee896a6174cf558a02e2144c5123d32154a0b3d16a05b96f48076c76477fefe607977f8b60c436b2d498e96fc91b44f5af3d40fdad0d45f63d2bb915ced76abd19a67f8e0f3589356a21063db12e422b573dbda07f0ecfc20251f409776689e3c3b9b0d003f04433287a64eb9a5d7d3983cb8d21f6bac3bf0695e7bf04f992c84eff54a85bccf08f4d8e087b0879900c2626060313130fce4941312da1172cae57cf0f1bdc005db3f060696abb948266242ad39ab73020cec049ae3b4a7f95af50aa6e660660856c7e65d349954a6b53a36a69bd4525ba3b16c230dd74b85bcedcb5a96f4115f7f2eb5f69ab3ec67c3b3b6676f4f1adbeeacc09d7d50979f59e62e34f5a6a4092a0b82e569c90755c87b7cf27579dac66795acbd2a67961473336b561f35a82aa1605395e0119907ebeeab3b7f3c559f62515c72413e76b9b0078cc79ad40550d87632547d4d4adf0550fc95b280a2805ea943e238aa5e2c55a24a14c5185bf56118be18aac227c557813fbe18c6d8aa07e9122f47087efb1e0445f3548d260dafa110638baa92eeefbfd187f5aadff19b93a0f885bf637c1a63b933baff68eeecd00e9aa44967a41896678f99fd98d7c75ec7eb63b08fc19e47ec5f4f7b666870d1630ccf1ecd93678f6fcbefc5936787cfe3e4839bfc1d4b33f20406f0a854da415f3dab3c57e21833c646d928338ee629feea676464b11895f8a1aafc5efc5e5c8de3f7f47bd600c6b72faa90b76d87a438b68c6831b596cc1c2d1ad2f03e581e817998b2ee58c08bedeefe14ac3c21e4a03ee8a796b7a644f0b32e22dffcb6d58baf63f5e2f82b5307c9437cd2b4f5781e4b117c31ccb3fce02ceb6ccae883eeb8a9e906076d235721680e7e976a7bd5a943541cb2b65c87631b7fed599d29ab133ec678f7343e515acaf884aa34cbf8eb12f8aad711be68f2b01fbeca0ccdd9f3b80faa9ef6804f7bde82d6299b2f83d64d38e3e7f1918bbe95e7d8318f2797b5c7b3381957265e3ba2e45a026f10e9cdf912daf645afd57d5810876dffc4b17f96ad4db2348e0bdadf7e8d4983d96f678fbd0a45976b5fbcc46399da0c9fea24d68a0c475c85684c462b2c0b2658750ff03261e60c1fa065ceb0396bb5fe65ea68fdeb5f2d738778c7a736c83fcbed44e80781615edfb976deb3cee440501badb7d6a59ce7511bfbee699f7409d4d785b675211088dff26759a3885765153d5bc13c0cf63c5e3a603c5a0f3365b26d9d069a63bffa4805ec61c2ebbbd7b73ec677424a34c7c698beb338f6791840cc1780f6c47cec797c87d58999b33bbb2e57ec5d3173470cbef869cf7df11b61a68ed6c3a81e97a1a92a0780bbd54790d76c0ab1a73db08f791d301f3379b41ee6634c1e3efcb41ec6e4f17a98d973cd934e6dfba95ecc63ab7cb95ab32aa4fa1992f6a56ded8b570c792c2ee9fe32e8bbd91daa42aee44b84a62cce7d6b1f02754773b854a13a04c4772fa195c75e58daf81b31c9a3363c98c0b87afc27bcad85c9af49e9a2efb1ecf12f80eea036c0c7313fcb22c62d13e663ff03f3b1cfd9fc89fd8c5901fbb1afc07d98efd1c3d3fa1a93b6b5ccfa3247316bf1b4edfc35ab633ff7ac3eab9055e54e49a38a56fd69db18bf6a2642fed5afcc93b6b339cb5ff7ea7bec1d2df304b5796aca324f590e1e24fda4993fe3fc6375884a869a7021e28a9e99d721f33393870f332f63ceb20e159eac804086a55ccf8c39cb013332b2180cccca284efd97aba5592b167d9105da10fc32be22a5a911778f5ac71088e28de9d65ad3dd4b9a1deddb50f79a8de6765de635987ba5d9a84e73aa0d9f596bed4cb5d6cac8ac75777777678ad57c84e26de8d3a6d67eaed9189bb596b604c30473f7d7bdd7f5656b6dcbda18f75e3db2dc57d6da7b2f2903f5bd7794895fb636747777771fab053f77cfee8eadbdd67ed9cabefce56bedb5eeeefee52fd79ab5eeee5e9dbab75821e087531293ad826f4ab3a949734491c65a4bbbf7de599db1b6ca582b73f7588cbbc3506aad09b316eb5b6b7dc9ac7551dad2ee2cf71549e948a9e86e434569d5eed8417777cf14bbfbb5eeee260a2aa56e4ae9fafe35373158a7f6d27cf9e26450e377601b3ccb74e6fb4099dff1a02c54c56c085e9d8209aaf0e62fdcc9f777fc6bc572fd8e67e9964e41eb96d6296898f177bc8dc942990cf83b5e66e6b37646c3b6c6aac05015821804adadc28260a812c751548560160c66b7f1526b54ae1d17814ab1ab59d21c9c00a7f6d2d05a9b9638f7de2644e04f15821f9ee53cf37da00c280b5531558c08b3a44f9b2a039aa34100b6fd9a33108009a408a36d672c4b9c9d8100c8fb3b3b3b3b2f96ab54c0b3744bb774cbf582c18ca21893853219907e33b36a565ac3f8d27035696a2cd93a6572ce20d51145130026169b0fc5f714aa79da6abf9df5a766697025d3e4cbc69a94b9e571e8349e15a2a1aa86ce6cfade44548daa52e04843bf862d994d7132d8b40c7bd994225733a6a5a525d58a3553775557752a9696d1b2962b1603d3ab30d4a0155985789a82ba4e402a05291d6a0f09107bca615e3131574cd6da116500999087459fa419b5ad667178361f7e0996e677f3268b3cc301194c5790e610e96ac3b0e543328e03cd593db9b00252a13a61683a91933ee4352d2f46aa436d359c2f6532ba5579b45aa13ae1fb87d53c7d86ed2f5cb1822a869e9e7ce869c8f4217ff221930a6d5353bed0e7341e7680dae2c856d035f3b6cbb59dd8f5611548901a72406ab8620393251b9ef65981d4a91b98ecd37344370c65d180921a70b02287204f8a8282dca5f33271606a9ff7e9bc5266febc5378b33f6fef6ad9f5afd479a7884640a4e7c43e687fe21fbb9e5888e64f3c8489767d5c84753920b14fbcc34b76c54c3053138e1212649f9887abfc9f580b962affc453f84b2e4888957d66a1330331ffcc44452cfeccbafa7997958628ed339fd9889b3f73536ef167ce538470d92d5afc0d896b7173f32c48dccd8dcd420892cde24d12c7c234bf2471669943d42eff495cf9ff3624ee6dba6c9baf2171363a35354f43e26a688868d8344f237134b49f9138da8c0344f6ec6748dc8cee99972171333253e8380599a13239e160c4d7d360bf5c50b7eb5b24ceb5e33414846ffd2c12a79370ba018a46da5065933f9238727c91c48da2ea4312a75ac2a90620e07f240e84da1f1025fba369c12c4055e6ed1675e608ed2434450ab4368a212a5a8c19b6bc7012227177943203122c76fe191c16cc70819dffe69721715926ebf1c3112710ecd0eb028407f20e50106195517a8606159a326dba3340c5be7f7198c8c0518d9d3f865325033be89d3f667c92626718129775ad16830a589061890f508030c2e9092a240c0345fb3ac15dadf152ced90590ba748c1f5cf6fd96d639e75ccbb59c3315172edf1f1fd0c129c18f0decfcf957242ec37841cb8b9d9f247159d76a16a7be25a226c02148882553485094816ce469051a6e33358b4afbde5791b86b850c2d70b0f387384bc4d0030823286a672576fe6f043014ed64138918362a1eec4c9b4ae0040317469010e0528f205057d8908314278c88c12e01b1f3d3a8a306417dbb578052325d1c0c69e1134c8b9c14b19bdc970d582829cd159e5a942b7499bdd0dbec6e6a589032a361a18a1934211bcc5a8072cdb4404503991a5a321e58b12399181f4e0fe3838a18cc8517d1cba5a4f524a65d7882e50297d7ea851829841c8d56a2102e55123021ef053a5d20053041ac1b583c90418c44cce82636083ecceb05a9767a2105e3d4d79c1cf554f0c39517aa287add7065882a579868b1e0ca151db0b4d084254832a35cda766854f3867c6b7118a9dffce36b7d0751a4aa3fc53fbf3fc13fc33feb9ff94fab12c7f1c5d154e17d9de27d7d7f785fcf75f3585c9e28e0eabd42556d13a2f8edbc4596fff84ce8fa15dbaca0df45eceed85a96bb4dba3a2bab57f7e5cf22e5d65b3fa0efd55155f8ddefdae46a3b046fbdf5d65b9174f9cbaab0085b6db5c1c8565b6d30b24f8750c2565b6f30c214c8f90a5b6db5d556208c84a8ae61dada2ad3309db69a3e1133646cfa4ccee3b5275ddde684c0938385255b63eceb3c16a7049fb2bd56f3825bdb3076b53b361ad57ea53d91e51997570259adb423acac20c48620a4200181acd61e4345400085032c6409a2973f60c3119d989efc377ebb5b66377542c2c472c05c9a819faa0ca61817c3c8385fed097c21155299ac058d1a59f068aecd9237bed6ff36ad1a26f1459bc964333232a6d892b8c42a429f3131c86f270ab9988f1f7eabd85e07884bbb01f757456807884b6f9fa608ed2fe6a7196371e99bf4cc19cb6dfb4efad836a539d6acefd89a30fd920279352d1bad75a9b579e3e2c5e83527f619cbc9a23c09b687b6ac3030665261dea6258e022996dab86773648ce38cd15c82096aba41465c2046d03675daa1862dd2ea4453271e7a9b3aedb0649fe1a64e3c48d9508660026588255da6ecdfb4898b121ee435c71663d1628b71b55f6fcd35d75c83b6f51f58e8de9bffeb8f1db49d4743d3a3d172b31992d0cc4c4f46e6484a26432a8ac58e783131433030484130d8d1d4eb95d473b9845a2d9dd64a3916eb69b54ae291a4d2d0384689a2944a953415864544fb472968ff28f9d8946ad127c8c4b4db2d5162224a9db42d9bd959fe7157134b3da0621b28a4e427156ca0d0f7792cc6d8cc4d56be1f9fd07e02f7bc86795ec3554411e7dcf62f2a6c4be3a4c72fdbad35f194d7fc53fa983e1dfe927cba6fe7b7acc464bb9b99c9f765fb94d76cbee6cb16fe4bf34ce19f96ff39bff98fcb6a7e69bf46cac6ec6dc7d5981f17af65d12728e54869834a7e3bc1a5ed4bfc767ad1ce1f5cf2db0932193165fb834c7e3b715193dfce9b039ffc767eba2da576c02588da28a236a86ea764979ea0e49eebd01e4abf2d8eabd0dc0473d99e996cff1fa4297ecb4c36dd34e50fd2141e0fa98adfb20736ddb4f207a94aaf77f4c56f79884df7acfc39fa92cb21fdf05b1662d33d53fe20fd40124212aae2b7acb4e996297f8eaaf47a475afc969336ddb2f2e748cb91d491141291df32d2a63b56fe2011211521151d4df15b3eda74c7943f47538e78473c207ecb4b36dd30e50f1290a121241f7ecb416cba61e50f920fa420a4a0232e7ecb1dd874bfca9f232e475347534955fc9681d874bbca9fa42a49bda4de0fbfe5dda6bb55fe28fd10125232e2b7ac64d3adcb1f25233add17bfe51f36ddacf227e98b524e29d7e4b7ecc3a67b55fe24353d3d254df15b4eb2e926cb9fa42949bc249e1210bf65a34df758fe2801511a521a92e2b7dcc3a65b2c7f92a4444569f15b46b2e956953f495aa4a492b8f82deb36dd61f993c425692a698ac86ff9c8a61b2c7f94888a8a7e947cf82df3b0e9feca1f251f4a41d406f9a3144473e8e6f19bb33a18bc39bbb43dca90d43e6fd135cdcf9ae3cdf9c10f084f0b94be6691433d2ea216cc391d01b2a9ce6fd4e9c80fbc647b1227244976cea64eba2f5b14790c6d7b499fba7f539a63edbb1df2e13592097dd6a2dcd4e9455e8138112e2a22a33edda7a3b745bd06fb74413b07dd1f3767f382ce591ddbcecd6dafbd7bf854e3db09b1babd58ccbf03804d6db8560b02414b1e2195685ac3d85e5ac3b9de25ecb6033125a71d64f080667dd9c108952c469a5e4118f100cc041a665327233c4c3162c3124658700d29a2020de89a4d9d8a44c1bae8d8a64e459abc94288204064b111d5050448658124556102262450a112897155a6fea44a489ab49b7367522b283c140a408ec039a66532722178029818e917a8140bf9e30810e48c472d0b34d9d74501283a203912974086a41a163ace8e99829311c215574340222311ed0af4d9d8a66800dd1339b3a0de912c4102b303a2ddbd4694894100c1101c802b166535aff746d3ae314a73e0dad460d997216385381cad849c6385fa88caf132c5260236c6454ab1136c24646419c4e70028b83e7daa76b8bc0c1d3e3d953ec9e6b6f24b93792d81b493ec8616d921cd7ee247727b13b09cec70eb1e25a7bedb5d75e9b8da6c65e7b614fd4d87c942f4d6c817856c7a45ea4bc4cb160711345a6e9a6451499a6162ea2c834b9781145a6e945add62864acc88c6a383de0c0c0e00a06f67e20a8d3815decd7654617230689b339f65eb13324ee76c9912145c60c15ccb0cdb860cba056241968502b120d36a011c3ef6870b0e3800312676ff646b1486e3a3bb546b153a3d6286ad8e8a0de5b9f68d1d401009ab4b84283831b38ec8d228abd4d6e3a3878ec8d228abd4d7676481c588367839f4b88bd3e600f89bd4d6c74b07bec8d228abd4d7878eeeeb1378abd4d76cf959e0fac7c90c35e1e9de5d15d1e1dcea7569dcf07d37df00108b61046f7d203d222c416c38cbb830f082390606f14512c121144207176047b71148b6d24ee2211618412665cb8315cdb0866ec48280149092620312100480260b31b68d004ce38e38c33c65ff014a81c1bdbc7804a022a09a824a092a8958a144020c192f1c5d7c8e8a200a3201b619cb1e08c0225a6bed46a54ab519012251867289c8d6aad526b956a6d9d9284132c385381cad809ce54a03276722fced7286327385381cad849c6385fa88caf132c5260236c6454ab1136c24646390411813315289c8d30ce50381b7d09825252ab51ad46b51ad98ca837ecb4687befc518e79cbf8f04010c55e248ae58bae57ac1606262329999196d060dbd4ac3ad34f42a0d4f2048034900eff129728236d6c8f811f423a8c6c6f63148712447f16d2506d584512fb054734ff5024bb92793054e97a12a745d86aad0b1b8a95de15191bac2a32275d3e28509744c26d06d978a52dafeb1162e9e1c018b501d03e88cb61740c9e2f8833225985e5633804eb781aa9c60892ad1dbfeb1022881a0d632d97f8d2aa1b4fd63481fd506e2f9e0e20585028a1705c5dbfe3eab243738569a72b91e8eeaca6a36dc09bd14ac00652a30812918303028793c19cb0a0c462f55e8d04748cc223e11f229f29a2db44275c6779c94d5194d9f229bed6505d44b1524083a712285b37d74325e72642ce996742404d11c192b64cca0199a61e3095a0ab2cd32b0693003d483a1dc51431e31006875c4720021306db0010d99e5e016333575d3c1d1c3d1834227f429f2394275703c99f449d213253578389e703c6d07e2599c7742aa06efdb35a78352c306095c348464ec6845f064ecb63f0b5e4f830d00e0414b46512d4a46918ca25a140d0e3cb8a16b4c2c7235a61a138b5c8d89db782371dfebd86ed870b06abd7df97411b568072ea23ac39d1480ef6a529a038220500f079a403cafb98bc82564a7c658c4454471fc5d43a88e2965a9ebc8761a9d1155a6f09870a2892853caea00f14ca9ed40556874376e90b8fb373e4a8cf7e4888b68caa68fa5e0a78fa1680735297586dbb01fe3512f5a88b694da01501474860351a139fed93c6b4c00f16845e0e0b1322af146a5a2eff1ec118b204f5959ca2ea6d8634f48c3b67383e4f9c09623462dc7a8354db69388389fb1f26440bcd18bd4f69701434e0edc28c2d844ab3b2f55f6139d4f918f9113b83609414f3e453e3a1f232090385b08f7da1e4c4f403ca09ed770d604aa42d3030821d84610c9f17d74524f945ebb0793156409d41b2d10af06069f22ab03c4d3da0b4f06e9336303f5a278c9114518c18b8a4620a10a099130526ac35602f56205884781a8501d918aa64f91a55eb26c1f233de8126c19d86e087df79428512285aee51017df0fcc16dc7dbb6c776ead381691de9c620ee7a2a80d9bc10a9bdea75fae599c573581a5aea9723185b8b3ee4458b1e2c214537c0c5835aea6606910ca1a195c5cf156758de56b74184c0c88849689aab1baccdddd1d464873e8db1f66344a478bcf7bef95619a255f3b4f5b738dcd78f58ff7daace053db2eaee87ada7dbf82704d93050b72890b1c1c18f4a580512383468276848eea798e59b2b81965b4b87151abbdc0a11d5131186d313070ede20aed084d2ed175c915ed1b8c2eaed0e0e0a6c3018ddb4d6a67ac5163c7868b2b16db185d5cc11d8c2eae5000b8a6365db224ea97d0f5c9251e7870e3060e1a1238706020c312d50f46a10b92a87a08bbe88a8e74bdf75a37227fdf2eef32ae545c8c955c25f503193bfd10e874ba10e842a0d325499244974497244986c1c0317cf052afb9dfe8a6385075c39defeb67d2bc1698dda8d46b9c4b52c76406000400f316000020100c084422599224692027f71400105a8a3e666c2c1dc802410e232906622886812084186388410619649462ec0c00e80a9d4c5d7393b66f9d243fa9ed11979069361d90e289cf09e1c16ddcd98491ba0a9b22aa9b2ef640aecb510853fc7dae7b909ed2e70b6c7aea3e38ee872b6f1c0025bf87c8cbc05770fa8eefba052a69eecd44d2d5c178d7e876ae59bbec2766926fc6d1cdab51cf60ba9b79286f14fd2a6f107d19153c383d7289dc5824e851c8734f48338241976be37a049eaa560664a91507225916b608c0660d1661f0a35b4a4a76f6b3c7499f68379d57cb621c4c27c226f4d5884432079a2c794c654dcd951b050642567eb1360c1fe615ec7140727304f191a21aab93a52bca493d59baaa1cd490a52bea492db332bd41a362b9b2a5ad1d201f477e6831bdd34d9545692d02eb11bc302688145de835b1fa38b77814063c3bb5a215b04cb0bc18a4f0057c2559f609e639e31fe49f17a76a956f5c119f9ee86c221df0bd2ad722c8ea42b0d5e06fca9303ca83679dc3fce2c529acf8cb4724e26a9b34674217d2d3430edca21cdae07685587567d651220a0e6917748b428c7707ab28881ae799150b23ed4286553329f483ac6e2970d2eea9b9099c29648430ba020243167cbb0faae409362a8b42ac770b5651108574de0a3c354262fdb628bd96709b3f3a0e40e9df21e64a702bb8aee077ed824992f94f8972f56854346abbb9b702bbe3e79244375bb6135c2068209ac35f871d29d4e5f5790a3d98034b4a4117d795a13b465f554bccbb969b6f5a39d16155d9f9d82b9339ca40df986b158ae3cf70d368230f0935c6290aa1860755d5d0be90e80b086e0d450502b7d3808f4c98960f86f95edc0669f99ec91a31281bc0e12d3e45dfe14da5003d7ec5b3a8165e081539728c2a197483e532aa05b64b01fd734bf0dfef75082cb844da701c08445830c1324d2d1d0e9b724c95290f22bd1499443f45f5b3d874f515ddadad48575b998e1e68424f3c4043e86674c82d150a69ff86e20e26db6ef1267bc8bb94128f3179f59a33e875f067b86208d0040247f4fc031da66181653189c49ea8a70b0282e0c0270a1f5be39977674a07a0979b281f9fa2077ad79ca5e7fd035579b89d1285e3a4b9cffba1905049878d90929bf47d7fa42a2eb750527798f417493f2d6d888b98a99b1b906284cf0934e06db9dbcc445525364555b4af14d746f5bdb0f5111a3ea1416f50eac15caa4ef328fdd19e8f094cdbed4f98ef012fc2416001d7a1eff06ba8f0945308e293f72d709f5dc2ad8e23716187d367b68e8a9d6e8a840539133f2d900052dc7d33432b2747f6143dc5ed397c2e5d69ab02df972c4ea5d15d44aecde9289a6e34ccd627bbb04f183760e2bb58b7c82a4a0ec1a1fee942b61deb4910c233be42d7c264eace640598f5ae65f06b0751e40c444f06e565f0fce868406e61df3c842fcb0775016f9cc6db8eff602d0dac70e68fdde09a3b758a777880c365d46457e8bf818a55bf4dfbe0cff3e23092ab07a8cad94076aca4daa03bd3a59601c26c43157218a92e1f6a3360ac76714879cd1036ab31843b2ec73c1a0dea497aba8c595eb0bb32c2c102318226a8e67c19a7804d43e3e30a347083816e4271850a1fcd628c0d44b12277071714a3b87927a19ab28dfece4e530050b1892603fab9f567dc1b60312ae12bc0d251bcd3e2bc441d0b7b68d68f1132420a7e618c95276cff57cfab6fc94424948948c89f9350d4b2a1245775005ae32ec7eee64d4a76b8536c7928649838e41209a2f7ce2d5669e830425790cc4523fa8d8e85b0e677b985599a44bd1d074fe4ccfd33320024d810e62761b170682c7b7b09b482ea7528db3cb0b2b0e164686e778cbeba80ffb3e658efe5329527b818daf2092fef595bf7c2063e3ee29fd0f3e62ae56275e77fb60a168cdb40427ca033fc0204e0376edd31974ea67484298764894243eb2f6ef0b2a520af5f4735f03211d6347b3a4b0f63fe0f56e7a422add7f398885c993061ed2cbe820983d2116bfbf9c5aeef2bf62c60e7603c038083ea8dd0dd62be34c44609456253e275ead6fc3cccf4ffe724b776de4b8d084e932c222062ff52d425107ec5cc90701f74c283c72c88e21b236c2cfc380962c3252e488938ac951d4a9e7986ef83a7e1ee381c5c7d6c823de980d5d9943a48f28e00380d4a7a96e834e7b0950be15b3a77d1b0a947aedc2b09657a600d25dbe4d79d951008a19d12593151a0eda43d463660eeb75f47a3ec5525c08b5d29475fcc013a601547878b26c1558711f9c2a6f18573594305b9b4deceb9367e6331abb7b615bfe8c80e105978e4c319235261ce42b133007b479df3760b4d56995980cb170a658745164ffc1203d2e2c37be579747cc77a53758a78cc05c1e8bc8060cf6deb489085ae85600108b6321051016406bab21163bee8a6ad0c910290a7f605b28155d1c096dea99979ca426d68958542cd0003da7d3df43a8196bcac305326dcbf990570eadce6f427bd3dace8d8ecd453fe3ced03a436f90eaa95a6651a64ad46f1b4f501711bbd839fad6c5e1e37c01c2b0038662301caedb322cb3e2180462a24b2df737bee0813a3db9ac2d03dd0231c949f149bbc3ed7dafc16f24eef32035a68e066b963bba979a670e6099d63f02a7b58fb11ad5705e03811a7c154730d55a4090e28502c73b88825ea71ce14e27e7d75846e6814a793254b08451ae96faf7a21b9aaa953dd39d626b7380d397c15749991a6c98e1fdb654e23c42a6d2f6cf66883bb8c258c0c6515ba009e652e9e6cc8fa04095be71749ef2040138611dbf7b4b3141d2867742e75856dca5f0634183b9c18a12c17e3bcde5214228e2746ff1808ed3f2615f2c29d9e30e3c70768c13c0366d3c4cdffd872eb01d742cd2c35b8c496b824626d5ccb4aec62c1c3275cc089ad7f0dc166874a1312af172578d5d60e720c46e098436c6e4263eaa619f339a2dbed55a0c741bb7d8c3920b868a9be798f426e70115d56e1fa61fba6a49117ab5dcee656fe7048d4f45781abc1e8dc3d9c3cb1895a9a997dea9d9d05ced46d55a52764ee41e8ca5ea06d759d8b2ed02b5f652466e7c24cab85d3bf0c0ffcbe6c632c94b6a885c8b9d3d5b3f7b9be0c34f0dac7d3253576301cbd2bbb10e73fea36a212f10c6c3ac3261613e375d483b615c7e4b21712b9059fd9494fe1520a6bad1b7c2b9cc9458b36a4a75f2ca3dfc4bb0309e4f8347dd435c1d3490ebd2a885e4eaf82fa8c03324379e235345673d81fdc92e31a3d2a0f891131735dfaa446a7c7099841d701f00444239fb0c99262a6ab946ac7344ee34f97dff388c7aa4b7d6f1ecd824e1843dcda6411ad051b651a6fda8448edac28c4e66dcf0c607edb6a433007ad4843e6e67b5666f8de4c838feb45e4cfa4ef4b90f1e27909659075c3496fdd375cf9310e5550aa67b0294410bcd5342bd3bd2f4076358d318fc94d2ffaad1e04314f146a1f8b23d322c37cf653adddcca16a576f3897b786912fe6b976601dd4f634f19939ab59e977fb0d084fe1007d776b20c0aa60225c9856af05157e5838a1b767c215a0b9d6c9e7305e1c0c364c1c233867f31423c233bba271aa890c44fcc9a1dd1a9835daa3d41501ab7d0c543b36bc06d821e7fe17d0ec2ebe2d171c0be4e2f593b499669d4ac5986c0a20aef2e24574a933d30d88e43950b32b8b88876bbf8505701de84a34f75f27c47a826a8f68bcb61cb3aed97afee882afdbb9d723129965ef35536940b06bf317143db7614b29fcd424d4d1ee0be682212f58af56ca2afa565f82796fd462b894fb7b4f7c044e4f8d8ff5fa430d64ed287914a965ce0f9820d5ad7e160081908e65b9a06e48e4dbcd381ccf8ed6a0dc2c1c7be701275eb2a4611f5403ea9a48db5828a35d786cf07ca958e099b0c9403e8d5259e924985056e2188e4d0b758b0975ed396a87a6086b5c8f276eb2ce6d25134d69ee8d6a6337ed3366941412b3b11c3dca4061707b413225523d4e5cd6c2b0a9626209d0356e2e341886214a0dbe36cb60cddf9164f1e338f662c367cf50684105c5159cbaca7ed8e80efd03cf29a49ade1438095bc3408ec0d5a6fc07f1a7d25935282ef4a7785236112d8c95ad288490b3c1f76b6eaa8acdccbc902eea5f041e94ae8a96f6e389770a00631c4bb09f410e7f2e6b8abda6532e93bae66cbc690aecbd1c2c70131fc4549eccaa3a021cfebc5adf4efb3e2d9dc6f73673c44e11f50e3a0dc336cd4b3fdacae6efe64c2d715a42b21d8b50051ca0360e2cf861bd4507d08bf060ced288d2ce70bdc838c228ab049c0597b51e790a5a610cc637d6e8cc6b9e6dc37761eae4ed45c6e7740d845135483aa1ab68dcf37fcb032a9bb7e46967db97030466531dd543110d82b1789e1f4ec474965b84375c6926f585bb8f69ef498ddad83d5153689d36e843d81986f4cdd502600e0a5341cbab30d1f2343ef61cbe1253c001a13868c265199fb1f361c0fcbdcc9a8cacd62b1b01ba158f7664eef600647c0bc711f2e9e18c972c33243e85f211652abba016da861aafc22ee1eb9169dca8326d33f6e3ee76733de0ceeeef27dbaf6527545841304cbc22aa2ce5e87a81935ba51e409dd222ec3365eec4c93387557dea9b45dabc2ab9d5b52062b91a9017a2c91753de685f23c17cb897069c455f2f15411807f7aae60597a6118d0f5d70d04504b438f71f072ceb619d8a79264d909dc4c301f41930b539b314ccdfeaec4d837baf7d0fa5fdb046d2e39af8c534aaeca6c18538bf8f72f0211d4f0e9aec0cce4c6badd07cc548306ed9dac3937ea83a2eb972654c8f493e195a4f9e2ce5e1570e3d8f9db03a2ed2c02b4042927ece35ddc861a5f1d09d7f1c6ae34e34c98e9eda26b8e411528d05018ef8b821e9d86ae19727d79935ba611ab49e704e20e5dd7e9e8288ca8c1a5798d56ef951050a079937acada4aeaf3b353a6369d7b5b3cdd92c64364373f35c77992d67664fa699f51cf93778e2c4037ce1bb78eb2d8d547469e62b0badb807399df26e6e646e0991d587489ca8299a0bdbf8ae009e34634b54b6709712a7cc766a84ad02e551e907ac9541adcd74d37fa41e95e6622205bc22d538293e53df7eb5282c37107c231058f6ae35095923ece458be1427079fa8b4fd3e28ae4dda78c9e8e88ce11432937d200bfe26a7688babc42c4d1b079cfe7b36338641525da40987dd0f232d69665e4e093d2e1aab418ede0ed2743054859f265d92a9d4eb44f0a9fb6ad4aa1d141c8fc528ae21449d4998a3bc74a04241b224dfa55463ebc0565287c0e59ceffa84fa2e3ab425b837055971249e86b82854d1c3518dce420b1f79676b40369005d15e47967401d131e09051019c9f5ab04307464848baa309422b3467b0f14cbaee2d69c6f141a79b434b412909c05f0969a747e7f35bad5342b51b15d89d1cef4bc006569364c81cf0dc9414ec61abe4868f76c3a830e3edde400a76fc3a4a74ebc8d83e2c7a27cf7423b10947c8deefc717bb00f45be567897c0574a39f201f2355b97bdabc19a697572b233cb7c45c596f8c65f06018c40d1d63228f8a6cbf6636d3dcbe3ca227d77e2a5316211566aeb4e1b1068331ea7395d647509763587b19503be1cd31a766e0a52e002a306bd6f970aa9c3165243f1f93941d0530d1d969052ba5ce8150c3c6d839125499dd2a124362087c63d75176d40f26b0569a632f1cd7e456d487180d1744c680f6473f3997c2d9926a33c3468373131af1f398dd6c71fa468683cdfa6b1bc209fb57da903c980d516eb8d48ab4f56ac149426225f485869be5fc5f91ed4d848110096869ae9a75c1c5fb5f430ef46b41aae28cdefac4cd78dd30143687f36e076f78b221c43071dccb8060dd34b266720e68bb51789bbc2c965818da85735e24a7af759322a35291c8bd0a109b9c6dbcb27a2692bf6fd5e9592110e7770f34fd3469c431b139ff98977b6bbe130991cad5c9ec463172aa1ee329d692f4d6d1763ecc912d4bcef5c840c75ca5c1eeccf20fd64008c70240b81a1d76b0a29826466ede93148b2793fae035903082bdbc3aa7d7b34e70a11d49f79e14b1f225ce36b9c12e9eb1a2a7b0e1ef9f9e348dfbd4412318dde7a32e941a06540e9564738d752a0f82e841fa851d3972234dd45ec86617b2194b4674a404735c3b857d00a4a36a013a87b156d97416ad9e1acef6cd0d3473c218ecf3451e0e3052e4b58b2e90bd0dae83a90690452987257a6421481965f147cfa1ba2b93908dfc0ef643d0bc9e059c207b2650af013db97cbc077b0d485bfe378dd91fd76c684fc3bb1ad01bb89aca5458cd443f2acf31989ad59602e890f45808822e0ef214228dd3a593cea34d1837097b43b091005c780f8ba66af182b18851d923e96f93f8f2f9cae31b0ae392c062b6ac2aaee6c429f678728676b1998f2ce62a18fca4e8dba39ee1abfb8da0d1a5729507cbe1edff76a7fd9bec06b1cdf85486728405c3208c211b06c12bddb0985c9f8e32e7303b1a28797a128fecc81cd60241279c8085968ed3845f9785aa7f8172ad545139c412f0e3a0f24709717d430014f705be38a27c8a0caad117a48a196d8e60ad4d66f62778c5afd6417945285869e600e0334c014505e4fc6f3500d363526d29310960751f1e3feade778ba7b771dbfa05051458ac993abb3a8d3bcef8f84cd7c528567c3fbc06a32fe168d86f4bcf4ecfe366313639118b1dd4c133908487c9a354da435d47b35e78ec3c0283a43c454c6ab390a9c2d6b335362db04a1df758ffbaa69bd22887753effb0282e008c3fd789ea2a8039c69e780409cba6f651c3bae383697d3b90663555248637ac1141a5235687a2dbb2a85ed49e36f2a5259221240a5f0d1c1b54d696600093a1fc84ee203e6e8b1fede3d73975ee4463f58d1f275f257a934f7c310dd97b405d21356da0021a9fd1e29cd00eceaf597c2312adc969fda52b9cd69419d801521ddd4155338d2367bca06fc89d24a23daa597236ab939e502c8d61ad6ebdc768b0cf7665a1ea9d0c1f13ca34b2bf798087a7560316b0a838a01adca626b7d7d442f091d2773b3cbc1ad17bdc356f96c600771f318f5f0a9525add56b321bf9c7b73f620e15409d7eafaaa762b811a554f3c6cd018f58d0e4a5cb03f29938634f49f85423efa4d0833fa70f74df29e466f5239a2d974fec261e1fd6f62e22cfed859b3380d27f2b0e686c7906a3d1342596a944983c3fe25e836c9c7e062845fc8a75308ce4187f30765641e6f77e05c4810e929790f1ffe4f011afb6cbfad7522cdda15196b2adcb006531e8ef19448ee0af5c665d95c879dded8d6b6b592f6894b43042aa571da6d345b8f3a1480160891cf1f340f1c47db0e41d37c5a6cd284ac205453ac2578f5d4239828fc26b17a9c75ff62e21dd3159e6d189e66a9de1fa39fa44ae9dad81e3020c053b18f948e6c059a244824ce8dd0f5d1a3aa5d16c81a5ecc13f65175edcfde882a4eabd63758c5f84cd39032ffc9512855bf634226680d4af30063efc5c1f7f9b840e930b65b45aa689a71f6806a8f8949d13a24c27a107144a24cd65f802b50d434d71f5d0960eaf0b7350af6c1ae7fe8c6d92fc8cb92f58a8e99dd1c4ba0227e11b0c9bccf94f3581a3e3d69f2be126d637aba8c2f107a287e1e78e75fe6346e9eb7de799fafe35445c3b7bd61e260a71bba6ae1394ec066cfcd6420a2ac1eb7daf585d1c67133373e5f9273ff4c906af0797b1ef69034ed8999a388562926ab3da12c250f0b859ab20c06d5eae74f563835fde0686cd47c22f0d12eb411285b1616d1d26022147d5a3544a84c868e5acffd40d9f0189d18f5eaac2de35012d053ffdb48df0421dd6123b7694a38465a55b02e34c98571da61800206b80213df7011000184e28794bcdab0b226d4aed6791babcc48ea3c4192ab2034da4634ad71c0727be91c9b4ebc2e67ada27eb697d8924ed78306aa21256cff99700559e1f5e6872a1d41f1a0689c82cf2cdaddab29fca015982bb982b1b77618bb1ebad5d75606a90ebd2a3cf75770a73475e5cbfcceb7758cc701625fb98f5b1e4fd38f9c2f9a4f7839a9618440b0a490fdd9aebfdb99f3b1890e0b895c9289a0dca1ff299449ebd41d7a46b4b40c6ec28f477ba82039078d5c573a07f805701e60751f51a59150b55a6afb601febb952f9add88c134099f04c49518a5e09c2458f91b754061cd6f1d9c0beea17f530a58edb9f57dfe2f4ea690c30a9934e5dfc2826062f2a701e74e0fc707cca27dfad07d11c17b44645beada2956f73d8da206aab868f5fea250a3a7286b3512754cd4a22eea2ceab5bd44417faf28e7022e9a2dd65d0699de13262fa2bdaea2d8d550d493f14503445cb47a7f518cedd02235dbe31d392915ca1f3e3c3361827f5582faa0232e563dadd926a87e0a8bc0773ef428a5c9a2d1949f3fe688baa0afac6763a71e311a237f25bfbef0135625f04e5dc9234fcb653cbfd0cc6b432d4e397a7205c614407068b077680b112d84ed390ffe01abcb8b8d56a92ba56f0f3850ff852702955e674b26f7a9fafe79189b84e26ae611785a82b60d6c588de54950191902c5ab94edc31cdfd1ca4683504ea7f1c06ad855460ed00c0049d0775102cb8da76a23cad14a3da899d1069e420af8f93337a0886cb69a9e93b7e0fe1b8c25c2809984b48ac4af8e138be917ea7f1b88330cb0ebb22d93165fb444f042b8ba666d86f7c850c68ccb23e9d02c54b6653762938795e8384519590513dc2775ae0f8817b64f0d5f846411cbd58e415ad054e75abd13d30b9d230fbc037da77332e19c2f893cfc374bbbabde73af1099cab26066dcdb3373d12d0134d4fba5a10b2656166ef9a93c9d5d1c72a039d1320276c3af85edf1ce14517b78327d97575d236409cacbbc259143bc5e6977934a801b96199a72f91fbf323d170f29b89a48c970252bc909a0b9d8a1945b1c346f38e6754a425efa0162cde7940f93e43251e9d4138e899aff6833abed2992fb5afcb30daba8892721c3920ba5bfac3dd7be430e5cf390435b77f6ff393a7cf531999c3da6867a364ec072719b5f5b0b3020db6cb1f0b2fb2471deb7cdc53e396e41f6ac55ecf9f4221ab04a668e50318c1fe3ac7bac53176c9d3228e63899162cfd12bdc7115e0dd946ba7c4422cd6858650ae30bdbb4c8c4e82bc06eddc47a28bf98a2e69dd5e49e3b9fe197760f6beafaa3cf446e4ce9650e25e3ebb6397113aafb2641a23abd7d01a42c8c3f6644a7ff1f4546941c60b9cc5f9d0e49e8e95bc61b7076d819cd7447a0ee3d761adc628bb44f9c001269339052a78fea3d8e59f24ce1cae6c46f6ca4b54f5c7d420cb889179534062024dbcfb2e6c32b392061641e92ab033199026162cfd152c469d6b3d3221156b6baff91da4080974398ccb49283fd642e19ac0174a47d47e6558b46ebf3dfc5f588b6aaaf34d773b8f998502802b452114cd4517ca1a1b58af7f96c879e8bbad42afca2d45320e7fa862702cb255c0b035c157959820388e4c3180dd4309d0bc8925a6616900841708d96ab958ddf7089eb1490ec11c84559e9916bcb75860809b8765eb20c33936c5f13711d6baa37d89096852559fa036f309d38ab659beec32472eb052d696d27928dcc852153002bb7d02c2dc561e303a2228dcba888a89a3fa3faaa3fa759484a0d7bf4291c11f697a54b22edfba63d63a240fb56c914617f14bf76f97c6c0d241ddef82c6f4609218fc3d2cf780b5af2b0fabda7c88bcab43250fac8fd68f8cce78b3e6973057137f9de2bf3cbdb7fe686bcdd309dc77d237fa74d95311ce23c206d3745fb271f17c32c8796669c1c30e1f4351de3502756bb0ee5eb7663fc27c77212b349d44b90f13d7b81ee088e093aef84c41f283c9a432ba5f38bf20fadfd72140a831fd098811c71c18de419e9a22d35e38a73aae52a9fd21ff7e052e9edb2e5985951ecb5a45de73b0a5fd3532a00254ac7e9e3798162b64b84837ef0e6be28cecc2825716158a1210c3f3675e81649e2fb7b9f6af39b42d3255bf0a14a17d4d439c6abaf662883da564c945cc5e058489fda17fa54d928f70907150b2e0cc31c542fe846042126185c81403acf4d938d83bdf955dcef179d157d4ccfe604e467e353f8ff3d49bc5ef4e350a7e8f41a166459336c117b9b896482a1f9074c64c936c21f1b16a226f6ad77f31ad40f1fce5920937b863571accf0b0331c70cc6f9c3edc9ea09e73a0bdb39ea7b17bbff6082dec17041c474fba2a82797d778090aeb4cdad8c12d45f3ef21f3f4a6b8d853c9fc50fc3c1c3540f22b877f19cf2b07e36fe4ce0e11b3d13c24180979a352653767b8f557ad6f8c753ccd4cfc392b87bb03385fddf169c1bf2c751d7f0bf8f9be1a1a1f896a10738238a8c1cde8f5893a28f1c71417b6eef0537cfa636b9980d71bbba7321bda6656fb57de4dd0f12415ef9826c50ad716eebfdbae49228fd00b5fe63fdbc80e1ffb2e0669763a0a31c5370975f926abf6580dc9ffe619a0a771ea8d3b7b5f64188b44fa7c1caceff8aa1349ea5f922a8df4eb43b8c5fc262cb04818f349ac212f50b4d3f2ce617e3854ce6af7135bf5c81cc623f80022f9a07a4228f433919d9616e1ef02012516d48496b33106dc0cb009e3e23f541ba9457a3352aacb81dddcf0aa8cad7d313ab6858f5d2fc5812e42781e5280fa07bb0664446bc3c76feb8d31e06680f5a9a0562852e2ab610bb40efc9edcc4ab017d3df7d2d66e164452d4141835f46811c576eb00eef90b053d1a213f64572d541e965751c314e9ab36d55425fea7327ca16c5241ee25e87d90fa625ef5c897b729cc2cc5c7ab480d747591c6d946e72661d1f67516afb816bb9bf351e27e7d070b62eeb0bed9454216864101a1b12e53277c17359be8c63dac04fc07301b657d9bba88bcc0be8d5f2adabbc45c2b41559ddd4b3502d9105114113a9930117ba890900afccca891dda1e7368799b95ac3dc77012394356d25ca2662ecc78f01c5a9d7911c70f10f4ce4bf77e752761b4d87f9ae7d60e0dca69c5d864b354e88fe3f6d9844f70b8d8d29dd766a703db69b09ec01c904b83e2c88b18ad238f51b66cd3ab29a5267016d49418562ad865c718ed0fbb9db3085613ec23451f250eb28db7674d78ab660527ab822ce092772048bc68ca5a86e3353fa0f74ccee949eb297c1cb2c7649eae827fe3470bec168130120fef1b84d82676160b411084ebab2fd6b1fe96a51f68c950ebe20fb421c5150ec24a0fd26b6798af33dc305f06c4b31a168224051f44fe1443397faf79cd44d1b6a1ac5e5d2c6e1bcd6297263fc0ba3ba07073d877cf2280f76b0d618fa41b287e80e83c94ff406bdfd8df3bcbbe157447004553018b6dc7d3c2ea02adcf2586961993d77d5304fb2844143fcfc8d010893a530008b672c3852a14399dd1e7c798e84cccda61a1147a062e50d3af918db1ac203160654646658741c07f3a175c42fae12bdf85ce3b95ba6bbd88ab12cdcb8da4ac0ca59745883235fb477d5b78c5c2672309aa8ac3274a54bdd75e15cb4b9d2e84fc78f2484ebf9e9a25e4b99dd459dee6b5171f45558c9ad5ba9c361c24f6b31ecfad04c6e9644e5340612f1a9f3fd6772ecbed23e97e4f0de99aba83fe8fbb75102a07dea708f36c49e67a5dc07e7543538cd5fce7da5d6d6fce95059c67216810df34bf06d9bb046afc581f171ecc83d7c5acd63d054c6f0c2020aeef8e0cd857042e03f1675480a126984244d8a8ad22997ae1d2181332fdb6f50044afea67add110c2865c004c56b4cf51d0c9938eebcfa2647c986846301f3f67595d41c574bb4e614daefcfca03cef4c729aad64f921d074a76b8c12002af65df1f4f1ca52f57da33f619558b0316e5ffd22d7247368537e4c05217150e0a5fcfc4596f3dd5ee879ce9e080cd5061819a04bc929e508658db256cff99c7a88032404b45d9cc849952830467c6d5a0f78e375ded639ace1847c61599bec927fa58aa0a953d00c7e817417f8323a7f7fa81b0f1a9e425b05960b1730fc0d85bcbbee80c8fa8e1f658ca63af4a46f8d066e62b73bcb8c036582af50805f6deb658816718ea22b0fa614daa0d59c2b3df01289b5d2af46c0a64345dc7d9fe9822a28ade4291c485b0804e660f0eea275282cfbb476de71b182fec6f85cda6c5a3aaca3b808cb3afd36d01cee5b540ad80f4f4088d3130d7582262cf352136df591669d5faadc1fd0208fc554bd553b4e9ea295b080a8121d8be18595c2aa13abd805cbb8a904d1af6a00dc717bc45a0a72f88980250895f70b4d9e60c5542c372b65376cecdd66b8301606edbd29bc959e606b13d860f760ada227b82f0b9c5ad7261c860c5f564e0559cd6c3229a88c1b96290165dec6e245c706c4cd216d7e62e0777f2b462b52f647a3beeee4980049f12d979003e85d6c4664df73feac5e89de8e7a4122ccff6e58d6d5fd0b2f62e73f8d3833db9914154ec16880431f06506121e126e7472f7f61521a356cd88b765c9b652cfe1e5910c1460cd62c48a12e889e2398021863383b081340d901d49159f77c6acd6a6cc05ba4516ba2f2a18544d5bbae4bc2e7e623350195199b594b185d8a43355e7df216fa48205d088f94125b65c2149be3df9978b1e768ebd6f80d1229893d5726e1f874423fb9ed184184d7c74615bdbb19a786454767a5d860fffb28278742578fce0de6a6f47085e5f8bd5986e81cd94c9ce9298bb58ff50cd22467b6575397fb042a25c5238acc4a4f883c0549152deda938c295de3957db3ae4abe44c778aa82d7aaf933b47417592badd298b9d4f0bdc971385ff08a44c597e85812c816d32c7ab00d44aa57b86eb307f2f2d8824aafcabf303ec62dbc922a146b61170a9bc0ae7263d7f21a6bb3d8f46b8f96d1710378840ae0fdc4450d3a1862834bdc32822ec51047d4e31108bc7aceecb758e151320454df8d044ea56dd8157cecea47e0bc797eec781079d1927ed2f2843c08fc2eab27fdbf23fd101952c4505fdde57067e4a94d0a58ffa02245841996313f8a1219c683b5b4f839c28805cd1443a00081052176788d182e3a581d865df3717e04c2eea583bedb28e29ba1bb617a59c27ee2f9de884f73ff6dfffd865ffb5ee04b3cb08da790e0840029fabbefb43f1acbe06001600b3a115263a4497fc20972f78a6f62c58e96fa8c8eae44b017d69a8761141ed63d91c45c93e37cf94c20c210efbb2ef467b7dec62d529c12141273ef746c8177c6fc00d4ddeb60eeb25a744d01b8070436413726bf266ffc34b1256a99ba1f6ad514adcf69ab3068e0f6c659a36b42d17562e55f9190dcfc01e88f06aea6e30785fbc0555bfa08268d94a545550bf49438cb6535f20c13023c9b324aa28ef7d50480b63a8771becc59abf7bf4c7d6b36914caf49192d245d9d5ed11b9283be7d0ec981be08496bf32151bddc2bdba9d1c40e410e5d42c47eb1d51a45dadb739d09b9c36fcd36a25e13b85d80a236a04d56a043147b3872efef9a4de468af49591a0938e6e1ea66cf20e6e3721e2f4493ba05b0b28a7885fbe1053cb3d24c5aa72c6528ba51e3a033382b702254637d83e02ca12d49d31f55e352adc409e666065135cbb7153b4f6ff5dadf29d75bdff36965c11618c10db1087801a0ce1cb452774c0f39d9c841357d9b868c4f28c7ac48d1a6885780faf98b37dc3499026141984707de8190935b4b4b05868174969c70a35a225d8edba5f4d66f2c68a696e07d7f0211ae42d97e9b5d6c393f6054a8e69e9d16bc20276f2818300f5764d9cf29724bcef62c7c0e88536e899c9ded6b4cc7616ec999dd7a37307289075ee8f0a472c0924b3e1b7687ff25263c482e2133d18bd3d6d11df9e5ccb1e818370508f7be35da2e2f9117c9cf1afa9590ff95932c4f8e12a144869ce34000acfb737abe7acf59adddb242ecc4800ebabb505231e52cfa255555750d14dbdfb62081b3392281871f5c14d572c47e696470033708887de8333e85b03df929e5a0484851cbc4bb84fc20202333a1d084f2599c6478d67073eabed0d4e21413c5aec246fd683218f403855ba5494f1d2305a4a9f508d0eea8a4277ffb590c64ec9b192976133478abccb3fd119e6a76d5b9e36e8b87434a973e14b705bcb3b4c13d267f51199f00b9309d23a410501f705c5c1b049a2521e8907d91f2d161a99b90a36f96863c0c9cb51165a862046031620f782cab6152559168d0d84092534e3e6e856a3d249a7c40584abed906e3a415381bb94e41962bc9451558ceae7ea20fe1af12399b17f180d430875151b85f37cc9b9d1b9670f02ce2fe18d3580a4c89a6581c26df960926166c9018559f9034082121beb07922c1fe5f08c90c7e44aa504535407b9cdb6257165262e748b4251c8ca2b222c6c020313a3716a4e8287d4f06ef9dd7f8f207748293c2b4d56546dac8897c1a894dfd4c1da31e025351f8a652590b873846502b88fd014e2ef4d73e8e066349d7d68f6e5ca981bc79c120b62ee2da1fe993d340afc0f53552a26e952c25f511019724af90ebcdcfc16383677309104609fd37b4f38188ef10058f24f9d6ef28781e7b7f700179c32f16ad141717a7502b12bbc25572d5008853c7bebe2aa7cca447ef9bfd28093906f5b86bd32c13388ae1fcc21457452ae2f112d39e08527dd88173d891f4e0d7008fd2200818d62f71378a548fc1cf8e2d5168f1df0fc9e147c9c703896d4f4c4a1d485c7b4248a90346aced107a40aa54d76e35cd702948971a9e13e9b00abe593d057a4dc1f3033ab9a6685657815c23c5a51eca25d56c7bafd468549e991434f20e9a5951bb0fd14d47ae8c68ada8d761174bd7eeb14d546ce93eaf84b24307de5ed29735101e9fe8e5965f3fbd17cc7f895f2114966ec4a9434da8ba93701050f483851ee05bf57423ebe9eb3e7790b2b87d9c73d9605b3f22c12033e1f7106de9c60dd3b406f04c31b25de06f54ed42fc8dca4632bf9e8a0bb0a19fcfee3b2e10c38b0c61c898a68f6eee892dceb94aca32df9dfc49011f99574e45780497d3c441fbcf612fcedd5dd2d36368c1339818088fab8089c3acef97bafc45c802b868e0cddc4d0280fe0ce216a77e81ea18803dcbf2b9e45fb23d9c8f7ac61c13b2faca5fb8c7dcc44080bd3f11f256988ea72e646fb187acaa835a96e9426ce3defa3ceff8e18bb0722a81c3d0bacaaff4d5f87eaf2c9a370ff5b70f626d49d7e69b6600fa4cbd0841a95ace8cbb734bb1e996245e9da4fad2cf2029e359a24147c8227b47e869cbe7ec0cf43ee2a8de8f3842751707f5c3679a100ba866e0aa5396a3ffc293d82bebc2c2826df7d88582b23503a62d4361f483f7d1abec09fe5031aa75e857b79c31a61cf27d3eec387cfa336c9dbc75498cc9ddab6797300110b89c7a31b8d0012fc0ee14d813491f0089bb9aefe96c816bc241f4e7dfb1138e8947c96e88d420bb984c273d1c9a559fef39fb36d96d93c81df867e0dc126f8a4318c9a293f1280c422fb18936a9e4ee0402226405ec895cffce8d2d0409b73e1edca7fd8e118128cf72318a2927de71a477f5343cec1834fe91f6920e3d45c8d238026b78c242c382e0d7ad914041d69d2d9c5eabe978eea3472a549d568b7ad994aafcef1b88d4cfdb31e78162ae2e123b817f60aeafd39b694a355865e0825d6d4b50c6cab954f24209dde3691d2ecba45988aadc1e3dce338fce751e968f2597f95f35e4daed6d8f98f601fe037cf14e618f153107165901afab610bfd76c6339779ab2c5eceb8618d192f18c62e60ddb73649cb181a46bd0eecd5cecfb5a5804bef79c311eda4f7e0bcbb5a5701d8299c40be21988f317f988858d42019716274d7a475a7700251c7da6c989ad63dac284d5f2543066a8daab87ae4e24196a2d8a63ecc4cb1d6cac748c7f9602bb88a867c862196c524999fa120b2b826b5884cba251dc4d1c4249d24647322c4a55d8a0154005db032b15d24d63005a1c45ae1f3ab226deff795fbcb7a10d91edbd7b5cc24bb138ab9951f8c1ab66845fa58e2ccef253a54ea8a748e188fac90417d6e66a248d38a5650ae6c1cd3c4d08184401c831190ce3f78f2127ad4babb86f747a17beb3619eb985c90898e32a802e35efbe9ebdc05710ba74be152d8da5689f2ee7274cfa4ab8c5aae812e4124706814b44820f6580ac825c1c3baebaa928753ae8802523e8820158e125a09b9932aa1521d98738f0f617d9d6c7d401cc619ca852cbfe8fb6d7fcf5824e6e67f2047289f139220898e282905b5ed263223979de7b3e46883674f4877318cc922b1e49a92c7e9cb09e05b4ba9fa38c4051c5b0f668224f982882f1bba102ffd4ba15cf0b6b8bc94b73d96724f0ae4a7cd9dd8e669a31462b1cde9a252390cd7a139c7f54599bd9fc36869d20449b9786f2ae4f34ed5bcdb012b0179f7974c7975141013ffc9312a6abc4cfadb777b43a9b365ffd130cd5884df16beef330e44b6d7f877b6ccf92c0989b8ca42521cc2e1aa8b82910706d99d1cb22f1b95e955cd73462ebc2a708d87b208786ba8469f179bd8be6a63536cf773220411138c32dd48e7f9e49e824db974459bdc909e688fe6a3044ca2462145394fc681e7417f1a9fa55bc1b0627b858969b54f21af424f8574b48142f28f7d1a08fe58da523854ce182c358215126dcbfa3ad639465ff66568c3a42c2393b07f74902949d5a392f82d965968acb5109660d04b8101846de7d2ec2666f1e6b259a59580d9d56a05de2af525f77303fc6079306a1a4e8c04869e0c47a3758ee9f2559c61ee703aa095f7862615303df19ac822303b64db11601b32933c47b16071b2bf2dc45e0d2de1f61c128ab7320fc462def4acc6283426f50cc8c6e4f6de145703d500289c625c206943714143f42bd8b0cf3494a478b9dec60f31e2ce937df8d06b363d4f8964ccb93fd959bc472c6a11786acd2e820c8f5610d66bced6668cc1aea3244871e277e564120e80a3530fc459d3dd4b57196c48ad0d4ab65e23bd99c27bbc410fbeb3f5fe3018543ba1be6ab138ac25ce38a81fa98392fa1340350ff6113f513221011ccd9587009d952b91c433f2d3ceeb5f03ddf30b879847c91231fa1b6d36df6eb224a641cf826c17419a355ed72bdfd658ed43151e7eb5137a72ad970f8f5eb6dd7b9c4bee6fa2c3b59098a047929eff3fb4ca3ecf3199eb1724ea501d870c6e6c70d3c61a1bdcf46d646960370ba142fea5abe2b94021ef48c4e47474d7d641647e5bbe6201d3a2dea692971d5c55224fc85f6ebfe7389e9fff21c13213fcd984f660ae113f6eeafc62396e33c45262e27c04873ed8fe1a814930573490ebe359ea9670752cbc0a7e0bcabad382286fcea65be03cede99665c8b203c34d854f20226ea5ffabc1a383b6ea90bc2bf7c0f18dd8dfcc7c0495521e4f6819c95c2aa70c26f5ce42192b10d70099c958230f2fc9a406f860ac3b823f629f360c506a112846597746adf8a4af269784d9807e08ab4046a34bbb71fa973c01ea0daf5c70b22a16412e56ee07f2231da6dd118150be21be1a7309bc00b2c97418e9389f5aa1ea0443350a0e32838308e1b0bf5855244c76401a2e8ddc8ac47fa7676dee5e2d0105e0e271c7b69b8ea406e4b21ec2971e0d8398d78e98579616c57cc6590a17243e67543e1cc4e61562c9440a0819b80382c8886351369551ba5b2833634c4c0ecf42ca3e02102f6be79ff4d12200c55028f4b447a085af6bc4cab5f1987f43fa150ea7a3516f05b95a4e718f048bea7c13668e88552fb9775e4237227cc55325e5cb9e4c5f6f1afd72f4e0e976008fad620907999501b4f4448f0a26efe19bbaf1781489019b0e89619622fd2b3aa543c687836f0a8f471315a38b4df176e99276e125672ee6df35933e08d49f8c2b55f61d14657d53a54f262467cf6cf7e7178cb71877b3f40be96464599575e8a8cf6d4d8e7adb038a7174c2f8eb25be115922f4bed3886fd349b2f0f9946f6dfd1f81607d7129972477001878e8d6c0fe5a469a6894f00607e344fea53aca44e61da7da27f24d58f89c40aa8487c80e5607d7323e5ba6b409f8074b7c86c1358707f08bd1413f3495519444eed89bdbafce794a43448cd8ae97f1acb6454dd4749b3ec1612058c86802271681af9169f73d01f7ae001efce11b99ac550db45d7b34ece0a17399ca2723833001b8950707511b0a7492c237b94544142588c1b2b2abcd5334bac46ebc2e70693ec7f8d58dd5fcdfcee96acb1348033f2698fb90eb71692d71c127d8bd788bc9417cf17aa7b1732f1a04a7c47829e36baaf79c907b2f90270d22074688fc271e8feac17c0fd00556ed4dcf683eb427845232e6470d9057852cc26cbaf32671785547d93961394dc5ab3d6c55eaa5301a061454d1d3fd40eeda9a2aea6765c44bdbc2f410b255e08887cd6ff519662906a6f5c382116bf989964364868c2498bae45718ca5f655fe8cf8f08990f8468b3b389cd4af28926f52dd8747e06f5f12a4e1a73eea871d634f0c607ca9e677ca7257dee1b5ecb46bf3af6cde1231f64abc223c6e6d5d86263fd280e1b79cd256e6c764ea686fb8f1dca2eaa2907726c7e71beb31b0482659af68e32b365c94ec022087ead0035e1eba95d50ac003637c7859da5ef370d9c3fc2c2a2a1fb7cfe372218047e0c7dc5fdf26d7e9accd2cfd334c44d2def8981e34e7536f927c6ec7e380e532d5f10a6cf5109348403064ddd00773946c805e6e87161fa0faa5d368942a165527321cc4f69c7ddb0ebb2b6a578147cb6896ff3b34ba94da6fe0e72110c0c7d56b6d9f84ba1e45623c37ed0782c3bec056daf7f67ae8146c6bb61156d5b9415f485abc676cb79540ea3a87360e1743a7d4dee7241da04376af536fb3164ce3e1dce9202b56cc3552d555ce9dcc9d5bc287a954f1ccc65b3d9e8dc951280ce95afb8bff120ffccc7e13f9f7ceb3f6e88a52f523ebc8cb13016156270f3361c3bbe8df617e9d8bf83b262c54d42770ff032cb3c55d6641207dd95a5e7c21539131f0a8a1fe89c890115794b561f56abca77f8de7b0fa751a742fa8afa9156c42c240f1e80884071497feac6e564281688e7437f6d9fd0094dce765529128a0b01dfc415fc757426b7bcb88328285ba689344ed9c22d9fbce078b21aff4182e3bef5dc2c58a0dc0cc37254b2f4fe8b18859ef4f2f1d5c4948a07c0e9fc0991cb242795233e5e907b57571d61521d2402d5034e8f2cf25cf51148e3c19991650673f0c69c797c8a1e022406c4a78a181caa3547338195553c9869a8a44fa612014aaf9a41e78042574f6aae96e675d433ee9962e767214e0ea89564218def113df2256f3c01e3682643b7a1af75ef176ef9b7a41f8ce8766a0820cf4dbbb76295e85bfaac3495c64cd905cb5a23c28ad9d2945605372a1f347a4b789ac80b5c0c9393ce21bbec3522c5f24cb470fb6c4f199db0af83fe4cd2bd028833320c49e116c6bf743492e48f7635b6ff3d84505eb5002c85b4f872de22d3d4c519a862fb3fedcd4d61d32f2fb26de423e914af0b922b45cd0d6fc72d1aa6169274cf4fb90b954268b7637987cc2e728ff425886969bd7918a00a1b0a5fc6754a0ff99ab6e1e411e85da2ea362ae5a571f45d5868e3b03b951dd8eb38e109db608d176841d4e9a72534dd824e1149ec5b766727d2af12f70f5b718b3676a4b2b16f997ddc32ea671bc5e1c8f709910a5e01bc356cf224a64b1670f9dea094e41db9cfc58b495b3af2a5d40c0a96cce12ddb6f8d17ef00f07196c24c3efd4955ac1ab750400afb07bce102fa262a705d30145a4d079a8c88e83637831b07f3672b657b24443126477cb9b98fa65ae68766230b77e56851166564904700066a7cba6e8ec1afefeeeb104dd3d87140481344141606b8a05665701eed55d061d370586b216d6fb9a5dc524a29650a4707b4061407f22b3884fd39e90b32152d38c35dc18c97a90732af5cd9f68911937c99e892dcac02444cb476ec21be5c41d148eb67871168472660f1e9d4896e65c78f3ec30b5267c61df952b64f418320f89114d2210ecf0a423acc113d22a81870220e8d2e70ae4e882a42491d0900218aecb4351f7346abc994ab2e2a0072a2dc8689c661226513f944429192f28833294e121d7a114e90102c262ba23c77e33813dc45551c22706a777ff6fc5cebab404a54fc62c66309344c308180aecfae312b56a3def6e092a91ab8567aeb62bba2cfc6245f492b007ceeebd22e11f9da7eda8fc155f167b4da666998ab1cae8a2f43c56834ec84c78eecc7420e148e4ec538947e49116556a44e28891c499d30d6680aa796a376dda3cc1dc86de64759dc916044e2377303e32b26b9c19e60ad8baf1045434887f2b5d5a40e9d39f6ec66ac4087f2e54929254e84c9d7fc1985647cc940bbba902b4de5ed41ae5257c89edbd19e97c88cd45e9739d2bd7124a728d20042eadc1973b0c08ac99f11a4432f7a4d532f85b64c1a4634ceab394d695021c56ef5ef96830596c7ea0c22dcc8315716fc1cfb4874e8452fd3f5a750110b3e2ab524188d469b006151542445105c94a2942c45d0733bd11239c0b440cbed444bb480b0c377726587291b414ce00a811059e420ca0e7688591039f9e267a4ec762227473bfc0dcb32552e1247385e502309aed55062050717354db4bf6f33cae4818ca848153edcc0071d8cc462b119ad5612435c232e889c0811c176e0e3840870078830c490104d781091506d47f08679237f3be8f839bf0f5abefc98fd09e0bbbeade00f20fe61c4eff7dbc07d1c82ecb88f3f0bdc70cbf7ded721c88e0beac07d064120fef1ad05b90bee705f078cef7dec3a5cbfaf834f950ed7b77b13f54d7a844c3fdf48bfcaa694d2b7d17a068816f45183063a74188fb6d47acd0aeaf7fafd5c9a0518f5ebe7fa180cef9db57e4f095c68fa52f666639d4bd8d294749b89bb6443e29420dd26477a71902ec89d71d8e1fd04041941900684008226888062073bdc55f9ef1776e17dce74b7e9aba1db1a4c7124d01d2967efa39eca9f27b507c815d8d73d95b9f78cc3cf00c1bf2956211819c59f331e08b22de90c3923e3ce80f606672d6e4d763157a353792952975ff92703dd2c948372916c647b95e5a05c241bd9f16505a78f9ef967cb4aa7e94473b7197abf7e66f17aea9728b5f6292d792f04d91beba327afa7ea39e9bd2468a1c5aded180335130343660645450c125e7420c34507ffb16a2e1f4965e72155e68d5f6547d7d1deb4d26295e94aab32dd6194cd3e994867c15b8b26576b34a6199a46e94db2c5f4a8ad45d38aa64c31b3bfc92953d066534ca1cdee1417ac45f6abe9aa945a94e58c7147d971fb4eaaaa940d5699dbc46dbff0ee57d508800d1b01588aa255a99f03e0f5d4af11e3d472957d7c505f65463ad412277623fb1461fba579519ded2ce387d92773df97830e2b6d479971c89c489dee1bd926716cd1c5cf89d277fa9c999d6ef9d8bd10246edbd295a0d05d890a1d76fbd2296b0fa9474d9f73fa9c734ea794bafff6f22375af9452bacd3969add3b70d0cfdedf449a9bbd30a527ac5cc7741e937a508f4e88476266a506acd0109b63fc92e35a6b1882a370241e3b8a216e50bdaf6285f146dff6e7b942fa06c8ff245936db747f90289cd6d8ff245921d2110e58b56142fac6c8fe285d1de1ec58b29b647f102ca0e511ec50b27dbb43d8a174148c8664ff27311e5a4d56e1773b9f348a5f8e16048369d4c272640272fc6786219ca376059416cbb4cb57894d21617292e2f2e2f46198917981718fbf280605030a8129044808a41c5582156f08118183130962059d2721918325296c41cb64468c912dd755d2733b3e4e846961c944aa51824b82e1324c82041861151fc641bdc99edcf8406fdd497cb78196f0413239e50972916161696ff8c38a22d2f171717970f3cc2957d8081818101696e4c4c4c0ccd8ccc858c8c8ccc0c1a2f8a81a0448a5d03801a1698a6810c193264d4a4822e9d414a9552fd405b231a3f25476c97291a1a1a9a1a01c8403468d0a011001bd369b454242ae9c146003602087a05f57097b88ea8bd006e0470e332828a27841b9c1b1c2a445b817303e7c6e682d94e9404ca0d1c377004d5b610d021947e40e3c8c19173684e093939d78acc65eae6e6e6a684128c70dd1b376edc18c0009648b9317bb1cab15a61216b04921316394cc891036f276222c4526402cb0413ba289d76728df86162448c12ac1d9607245e899fbf7bd56d3eea36481041e207294c8e98d0a8d8f2bbb86f0b764ed8d959429bdb8996185121df22c409289c70c2931d764ec4a4042f6b4441b03dc2a6c420caedb0294a6c8f28a0e0f554b7911f3fea36414cb6ed444834718414ae4911124a9038120bbadb898e00bad559aea3dbd9d9d9d1a1e3450828a080020a29a49082d7e39e827f0a29783d3ecac3f35db7213ae2b5b1b3aebf3094715881a38ad98cee1d93da6052277b07951d2af840851526e5019a3c409407a887478c403c26550168aa00445500eac1021d810dacb08226b155061feef5f0e0b6bd11e436d4468e115de381a739cb7efe9916a592675a7b3eb511b311dbb3c6037bfa6087b18a3dbfe6cd7d54d6c75fdc97dbb97a94247adab97ed25af9f4ab301c332e88ec33429bd9b65baec255f63dd3b65aaaa844d2315aa9a2b9ca339b96b37c896d4b60989ad1f86cfb34adb932c9402aae63828134b036572e6f695c4c5439a2cde62a1f1dc15814ca249bab18ada982d9b76f62c275b2159eb224b0757708f38ad1cab36c450cd706e699dbd8e7915f90f65dedc768996047dbda9f6939eb641f8cc1fc6cfb2148dbf63555b3271ccab63299b21f8243db82b26dc1a26d33cc4b2687f61350f6fc10e6c7656e608d95a8d0d2be9e9984a206b6fd7cc4d148a1e37629342e49a1596e8914a345fae2de481fb7b76dfb68db3ff54a60eb4ba24397f5207df44aa0f7e1663f6f5f85edec7d71e7166d7b1fb7ad11fb7296fbceade94dafa7f4a4e79173db487303c3d875b5966777da5f121dc690711fbd1e20cc6dec038957f6294710e6acc86dfbb9144388d4b11fa3f5d19c95b77d10567ae9f59474696b1e27ef3b6dfde58935f73e60903a2c6fbf0a398b7bfbd6c759a7b79f4f9fe9b92f6f968fca94feaca5d7a39ffbb87dfae2ced3a32499befb1c232679de3695bcd269e7e9f500e171da1308b2f5f715a14b3f3f7a3e8494beca76e963cc6d4aa08c0ba4dfbe44fa6d9e3697c1d3766f1372d669dbc781c5e22e49fad2cbd325fd491f4797a40b56d806dacc5a64506b3b9790689b8be03a15e85aceb27bfb7ce4aceeb7ef5c73359f52c93fdbe6e32cefb7df80d8f26f6f5f9084ef582656c859f7b7cf69a2ad90fccd752ee0a9edab93ede5d7589d94e62cfc1107516cefe533a01a4530b42cd8dbd3e83b9649bcd9ee4b59db3fef7dd213234db64fd9ce44173cd850acd4aed268a4d0272018d861901d83bb4d9512a434ebf188bb3ea9c2dca6fa10427f7e05a40e4aa6b6dffe02ae23e3a9ad03bab2b730e2606fbfb7ed2d93b87343bcd97edb2c93bd7d9e5f61fe64cbdf36a0bd3dfe288dfeb0438f62cbedbd2f0606b88dfc1be46f5cecaddb9d0ce684e8edf1b69d5a7bdb3609a44f3e780a3a032120f8f8ecf084ed2f3329c542da7f66bb4730b4b13d469739d8cf381e9b725bf9b67bfb11887b8bdf5e6db3f7e18f9ff7751fbffc99c61c8790ef7dbe237ebea3fb689812981588ade89a2a1e33360d32652538c354d9e7913252e033a7f681b3d9ff7ca03c1b8fa56ead76957debdb22d1416cab8b6cfb38b12444ad21c36aa041a6ec4bafa774024d3fd2cf063a83d4a96fdf0172158984dd0e7db6ad8f4cd9af21840e71b68d2d5a93123fc9d274fa7cb3f47a6cbf43dadbe1e73ecc71bf398ec31cae25ee2f7703ddd9c8ce8f89aee861cb8e87851572ec13a4ce0ffcf939fc3da5207d697d1efdf787fefcf5b395c0f6fef4e170fa8b83e9f554d5c73e3e1468ee6516204d320b88183855aa9f67f2481ec97df7f527e302f7a304badbd0e7f6be2173ef32dcd3cddd2ac361289a850baea084b6cf33bbda495b0383367dbfdbd75b6bddfe6e1b4a0b1a29cf54d1fc42ccd3bf34c618b7fa77bbf7e3ad5b84c9146d2253d4242b424730a5848e015f90292a34573e8436cd31c61823aedbf615a7e0aceee9f3e41fdbdb87a2a54367da6d5b8e2186fb2d1f76bbbabc7c8df9fa39e68b81cb42c7f4880163e87a5efefb70883bbe2fa29bbe6946f33ccf3315c914952253f467288940d3003a40a6e8a792d0a6d854a54043e1d34dafa7660b1d9a6273f599a4489d97a76f2a923af7e99b4c3253d15c91f0f44db3b99af134c6d33751148a448a9e0d2d6cb4dd73658ad2fcccc7007e8ce79130fcd3781a200eff4176c0b8628ad02eb57cedc87626d92773963bd954b7f68cfe7dd3fb903a3028fa303ee6eb17836a89e981f18537d00de363debd1e9998f7981818312f03038c41a6680c08038a05df15bc816e98ef3c1752b872e5ca8679f70ac0f2f87924eaa31be69371017ffd0afe60c95bf71f0eff5186838c8f455315631f0a74cbdfa73f039459c094410228b30089810f630c6f20f1caeefe6532a143930b38c4ccd337c968c9e7906e013b99aa7f5fd7bf3205b27cbe4ddf2c3459094d479bbef785349f4cfd99a7add60e90848ff1347e8a88b576548fc79782dbd0ff3e1ecf3e6088811e60bb72e58a16fbbe8541eaf80b32453f19f8a300dd17fcb181fb3ba2c314367d12be18dfcc178ba68abe8c064c331b3c731565be83c6d8545114e8df94075c6c93ac04936c531cfa2938cbc120948c0902870c1021dfbeece6bd990bdda2e56621eec41914a61945221728715a951d826843e87ea8bc64d1ac76d5eb9109903b5898aaf80e90a9e821a16f90d1b0c37e6cb57648503e0cf32b41083a3a68cf4705610626d8a63d67b42dd75cdde46089d68ef8f16dab892f5c0040d3616ac768e38498cae1ac1f67e51dbf1e599f697fea151f6a1b7bd9d61a2e6aacc41bfc55bc9e9a591242fbf3ccf9d55491295c53a39142571a29b44bf1218a612251d064a822573a5e53069ad491df85d4f1c27acb4f865aaed1eb24c9404381d66f7a3dd4026ca26a68cd550dad8626436daab00cb4a9c26f818c36fe3c3f1d2f699a2f876073d29a3369626352ec0c5b281bdba28dadd1c672b600933a3a7488166a0d4dea843534f929d0f4654d15a9231f7f4d4dead4d0b2fcea4bdad570d1914cbe430bf433de0697c2b9eb704ac039e1e6c841ea3e2637575b63e5c7518d15b9f511142f3505b45e687b3e1424500009a8b48145d103197a700511f40144507a29256dfa8413d1c9219329fca10988dd997c76d7799d09411b7728c08a76f7c48e0e22f1067f98a3ec2ecc5276d7752623bbc36208dd8f2174b2bbdcbd57c7eb96ee8fa33bef8f2eeebda4bfb7e648c7ebc751098ba38d9ff4a38b0962d1c5c6764617d0064657112d882e25b6f599e38a45367e3b6d9138735c76f2ac007be1c6369ea669b2c222434dea303d7e198ea40efdf865e842eac028940532e42a6cd28fdfc2e6ea743f4a91294154b1b116b48d6d8876a886168f6d5b10880dacc769c70ec4aab4a20f3eceb21f7d00c2bd38e2a20f3e36b01c663107a3d88198b3b20ffbc12081e812da3885dfc68077e8efcead52af470ae1400a3bf4bbe28ed38755e63cecb6ef3b5c7187feb016f90e20311deb5a80b5f044ae74e8435036e63a4eaef4fb53ff166073a541cfd9bd3002068ee20db6b9731dfa2618b1b19b50f30612aff4c8ab9adbe0c71668e7b468ce8a1b7332f984094128c0367e1d44e28e3d125d07918d3fc7508e580e282b2d36fe552d6796e3b3f1e7f490c343ce0e39ae9922fdb9bcf13b429b10f48020138298d8c1c091df3cd933c7f6fc3043d953ef09c2b2ec48681ac18e027efc067f682ab2a5e9b5e503826a8e6c62354799669ae3ca6196e3d22d3357069a0c55e4ca024d15f628ac6c6c03db605a36b0dc753534f9713fbd1edeb479225336b0cf2a69b2f1538e49d0c68f81a3b8337f8296082f8e360669a4d0dbb68166afaba1e59a2e640a1fc9148632b3658e2bc7e52a2c7de8c9c69fc383af6c60dac39c211b87261f13111b6427bb7abb6ebb7ef51d05fccc5d3fface0382e20d7efdf5b5af4c5f9f3a8bfb5ac19ff9a55a32851f684fd3a73f1b3455f815f013772c114558287eac12b7c1ff8020bf22685b24be02527315febb64639bc4c6130c5144d81ebf057216cbd5e2cac6e0161dd8f83b20e647293225882a906cdc056dfc7668e3e73258338e26e6abd0721bfc3864a075bcf253a008036530742ea6e430db1868e38f1428721bfc394574e85574bc367e1df87518913a2ab43e631857e8c7be456b63fcf4814a54e8d006b671866d204e5c67060904e62caad3004fe10f5d8b271b53a94980e62cef23ac4ad1c6555a1b7f0d42a44e7efc356cc0a6606bc077ec911a5aceaa8fbfe6a8e66863207377ff63c3b643f067638bdf1e893b406af1c8c66f4a62e30f615c1bc7c299a24c731bfc0df02a1b3ffe19a44ea6e219082ad9c76df0d6da180fc136ee409390dbe007721bfc1903a9c51d8bc46ff0639bc46df073ae456de3ff54a06b6881367e181e056de38f3ed414d0448c3b9778b8a77a9410e0ae1aea31f5ac4375a847ada430880f21453aa8e6db4de3f3c8d1bf24d29bc00483cc287b907f36bedf551830609c5a736585a60a3fc618bfcf55c52d2c27530e4c773bb84e053afc9dcb59a4c7dfbde66a3ec6ef02865d0f1bb78061f7833fcc4b36fe1ce4acfcf84f5fb89d60e3d2e3df827056f7f84d9f85626920877cc732b1316771d8466f5abb6ddbb66ddbe6f91062bfbe15fa0bb88e7d81a7f0638c31c68f31ce0f7b8115c2f833fe5287dfe3307ebaf3d76dd217b7f7c9e477a3ceeb11a23f2d5318639f8df1e3e7306a630cfe38fd64135cadb50b7ea284e5a4511e90b5dc274ac498622c4f8a340f47a727462e259789e849115e482efd01ce6b958a6c9d46c148f2476e9c37c618bfdf1d663bd03c0d038ee341c64351a76780c22b68519477d05d578cc3a2b4f1f021868964600492fdc1088f1f8e4895eff06ad7a98797084e2b583952f275e0a806d9033e452e3dc0889a0082c9f583728268e8270692eb02832484a22401c5e5073db39d28092317225cd082f941b36c27720110302970c111030cbd889428c1a6db89624f7ca0194233846608cd109a2134436886d00ca1194233846608cd101c19886dbfc6b8a0ece32cf9d686ed436ec9b61fd6a16dc1d8c94fe64ba243d48e3bcf48e5ce3ece9a9bf4de877793402e066a1a29f49cd6f706e270ddf837829c55bf036dc49c155690d2665a16ac45dffc192152e769932baaad2136e732654f2ee62273d6fc962367c99f1f94962270310e8acb59f8a70d3c4e5bfe4c0b8a8d98107b7e969f0d675a5b7ea79d73b05def174c3c2672529111848e4f63a561d7f7696d0da82fb494d63829a594d64a6d37e3c4e6d7091d7f36b1fdd7c446e7479a6f139f52ecbd28148db4ba748f7368fbbcab39e4aabb4d3a873ce51fa3f4928853e6f341f7396339ce39698d324ea0e34f986f915f07355aa0e37ba76b1ca12ba5d469d8f3e9a76242c739a7a6b37633b118a7533a736c4f299533b1f9bd7dafb5de946a09cd554c5b6dad758b8d368f361aa5c9a7b51e3141b96d5b653cc2759526a573d66081f68f4e7dce39e79cd3e99cee74565aaba74f94d2165b27a594548a95e230b99ae9123de77cd9269df7e79ca6d3ddb66dabf408a7e484a2937a3db52675e8dbed524a7be85dc186b91cf3bd945297171899198f72b8cb9e472279b3cb54da225e28a53030c598e370ac5c6581576aeba535a078092e72db44514a6360ccc4c894c339775d96c2898ecf614a29788ba001cb3e7548fe0481a27f7c9f13e4d68cfe138c2fe3760739201f68ffb0c2a6efdc727941db4629a594524ab78d524a29a5944e3a299d75d64a29a5342aa1b5ae45e665ce19834e1718940d994a7154e8bab95c73158d6c3e3228460ca554069d2d77935e01b6bfef7263fc89af888da065baafc947e90f507cd5eab22d266fe736ef9c26af67ce2e8b8f71674480a7181ff63c12c9d3dda7a70a45027832e93927e8460ec5a1bc205572855f4a0ac617feb0c58b627c51115f9dacba3caf67c657278b2f17f855d0b698544a6957b425ed64f369279b2b1ba593c557378baf8ed66531413b2342c7a019aff8922a295779a318dc5ae291ce85935d9beb5342470c825287e4b91001dde3755e1028257b8c52c618638c3f48a178b7c79c258b606c6f4f780aca5c6db039e43a9b4ca6e496c546842db7a2a97ac275362c3c25933a1bad286f59f8bcb2d1e66a1eb9ca67ae8ee0ab0bded654499f2d6f6b035b0a914573453fe034045b1679a944bd169eb66d1badd2ea4b8e0234a923ad05e89685afeecb8d08d71b0285371295bbde19e7d1d6721bb00847f7e707b6e3c7bac48e763ad9e6922da59c451c882d7feee0ab0d3661d3057afcb02ee1538aecf81b6caee4bd3ad428d46330fc3075b381e1cd0e3798148a9f4b54484ea690602e54c41220243f41bc8af84c205cb14403400fec69cbd65c917670557c205c457c827821f9994b80762409edf8a12c62c787214192cb6de2cb2881f60f73cb410ddba4649f119e3ccecf73ce18e79c9f0bf49c36ba47f7e81edde3a45fb72040e6a6dbf4362e56d39d9f6c4569ceeba99d476dadb5d2d7546dafb9ea6437c3358c98f376fa5125bda56647eb8c5aa06f92af89ce94bed04ddbb2ab7533cab22d688ad540a2bead5bbd15d708346b2c0285dd2c0285dd2c0aed2dcec0e57437054f40459c6a8b4b0c0cd2cc9c47c35c9148a5128d44a7f769575115f7c916282594508254c9152739b09b7957e957b076b317964d4153ac0612d7d65ed7d6e62adeab2d18a264ec30b66af284c455f297b8923839897533a06d57f054bf6d7733201e77ebef05b3e9931406d9d105bac2a0dc8fba99ec66dd4c7646b2825bf761cb0ebb99ecaaa05edbeb4b42c75a6badaa201dff24a3f941091abc360d7c889cf8994862b15a2d66bba7343be79d776eb3f37a2c8d3bc707bae6d074fd1035bd1e3abf2b6ddd365b67690a1d5e19bbcddebbf5d86ed62ae6324ee5e06098ca791fc71034a51fad291c4a0351790712c79cb5d10fad6bc2dc866e5e4fa5291893568b35925c65db69ad35d4daaea06f51f2214adfa2bb59ed26c41542f7f4a05ceebc1e3a49240ee8f8a5e82db3646269617169697171892e2c2d2517af87beb8bcbcbcb4b09c5e5e4cfae5e5a5f442f25e5e5e6a66ec8a907d46886a6deb20cebd28773c3f9c69a4d0fa43a2ebc3cc4e545cc7d264cac2788b859baac4d82cb6bdbf3591c376297d9692c459fe1d12dfe98ec41bdb01c1cce62a4778edbd30be3b55dcc77c3e559666b1b0596c4dd8ef8e7447e6bd2ea5161cda2bb6edb6cb4777cb27734bf6ea1698dab6335ba25097a67a3cf25f3007a63b2067a1de7ea744eab8bc7dafe52c98b7ef69c0592d6fdfe4e32cfcf64d3467bdbc7d53cd5976db371dcd55cc9fde5dc7054fd96731751ea9f4ee3b5648bcb15f7af77c08890179240b52c7baa40bae6379f0947d7b7ad960db0e2805db5a1f2671c71ac51bfbd6484885f1605df3ede90533bf654efb2e1ffdac51b4d808f5f98679f9e276319af1a9cf864c5918abe7cfe8e1d8be3f59be70ee13189aa884a756a8ed973e1ba24761515c784117e66f9f434a4aefa59352548b459e44f0f667c797383b6c7f227d0a144a0e71996d4d557c1d57eacc0f9a4fa8d4ec17363d0a11d160000048007315002028100c08c562a14816e560b4eb1d14000d7290466e503897489320076218c5186288510419020031041965680a9b00b0e30920ead46a4fc1bd10d979d7a81b6111e9aa6f9276cb4de45906adcee10aea430bfe8e784f774cdc9bb1c3b33019c09bea1f0f9f72f6ae6aeea51bba295f0e84ba10fb0c8bfb61d01d94a79369ce89b0a60637c7e911827e9086884670cbdc13ff1c808e5de11fd6bc8eacf2e303fe70559e7063526cc3194b300f58f238327a06919bf4732d6c4ce80e4e0fa0f24a216b65ece2b6eb01b34a56f8899f8ed4eb4902d29a63a065b99b4ecd7b2bb22c26ec11c95e18500157a418b4d0b9d112739041d55c0f7b5053440bd2d562e2664be9aeb3a899e9e26e1591c6fc8d1fadd43d65627d8e6d81b44566aac8d1ae620a48d1071ee4eba5964c4c6b57ec3dc3f027be5a70c79c720abf7b1c2c74582dcdf088c95d10d96358500b2ee4f5c06400794a9760a36577b266fe5d9aa9bfa59f2d287c9d6eda5f46f80c25d294dc49ba7044db838d5c28480f9505841126695df130b40b36fd363f7313b048261081946aa4e7852887fcbac057fbe319ff9bbf8ae038214cb1e0e235a46f3876e95b101a554c59f2b8d603cd30148f17a4ebe9166be0a804a8e61b0879ea1c0330f9be94df0cdae58a01dd24a4fe2e4dfeb80e8c03bdf640271a51f46d9ff2157e241a0fc663d1249d896db0b909b8c6175d9bf616d6cb0b47cb341134f85f0aa72054bb9511d07fcbb111f682b80bf16e67a840134889a5d63ac2f1de9349e20634eb710edf1fc8dc28079bed2254f42bb037ee8cde755d2bbb5c912752c7ae4fe30d151c555f1bd0492fbab901e2358691c1451c902a65f728bc48624169e4bc9a0a85aea5afedeecd0bbf44d0af24a5de460441e1880a494e38911aa762ee81873b7fd5a0ec980d2df235035192cbb04bcc7bd880b6f82cca22f466edc78eea42b287e0a93339f0998d6b17933965e32e2208189feda0d61b0f1d46c40a49a528cc9521ae57f7dea2925e45f4a440cf298a082ab966a18d602d432b2dbd4e95b9830947fb458d2b2d0ac09b7ef222a1c28dd24883050541036db1c6dd0e351413b1825c4d1e14ac50f4d91cc916929e43e74f09c34c79e1a7635cbe07e5da3124c0e6c8a19802f119c6c2d0db40d0a36dc2b90a3ebb9b2fffdf0c649e57670c3ddf6edbf9baa8139a67a96efde84c77c22ec3bc6fef8fa85ffd994ed65287cccac5c3f2eb37cef97ed99bd8582831619d262a9dfaaa9fbe956a8a767f6b7ef56a95ca708ab61d9b5c77aa4ed18d4ddfc1125ee60a2cee4bdceac4d1e4c2b60929294108cc5d2ba48eeaf0e4238c47342b740df21d8df7351772836369dbfdc28a4e44132cb56929edc79446147eed57819c1e0897d92cdadf70c0b17c42f60338d64a8f085f4538656918f1539be89a20a2126a94a4f4c4dca48dfc44183278e63e4b00860184edefa7b983c1efcc11c20c526b831524814cf9d90d4260b288ec9bbcf311b9a3725502bf0fa54a51a1118a91fe5880d71532c748b97823b35333004b3d226851ab6caf3f56f41e1f5803f7d6105b882341a58c8180eff351cdfc76f36f686e91bb94071f26e8087e62fde841eabb85a53492efd8c38b1b080ea9c6881f8904fcedf328348435c12c26ec6640026651e07435494ad7d106b6913d36000bf25c83a16a526a8afd622b0ef5a4946579bc122065bd936b7b69e708a76fded6b661ae9a490407b67493cb9afb921be40648d57f1f4c151ee9e8e26a8cd20ef80cbeccb549dea5919cb51d1b6aa02d1ba0345398241205d3abc2f079eddf5f4f416f70169c350693083c252d443ba9fa80fb62a3338531fbf3092f8020fe263460af7add2f94352381c855771205668f195736ba844aeaae95b7419e3043c65c44a7cbd56a0e90df059b0c8c834b0fc20db8f00e8b8f75f698379b5df1ec65a813a1ddd18788b4e88db55c8cab2b76c15ad828ec983d862470171eef6d2af999da5bbd210b721379b7014d78a8172ef806bee95a999233eb6baf021b7bce3ce5ac50880ea0e59054595f48eb56fe28f604eb0b1e4de8bea42e9ff9c64dae4b7a00024d79d1d6970ac550877117367330a1df1e6203affdbd87f077f7aa6a4c38fa309b77ec23d2010cabc17350165a3dd45c7b8d00f86184474e37d8397d015f390f8a15a161598fa9c79e5b6f902e60d57c0d8f60819cae1abef6b304aad6737285205755cfabc63ef3eab44e4829495d66b792e1dafc4438526a91819012198a8c08c18b1ca6b66f03c69d82084932c8082c13862740bbb1a0348b5f0ffab93b2355638944cd6297433fee66b08408fb9a342aad83a70b77520648c18d688b8a6482013fb00fb95a060c60abca70190106874b0801255d74ba84139834f5c03ae8a543d9905cfa2fd6f00980feeffd8a41809f28e7ad26ba0ff28bd8513ae7cf457b8f57d0a8331024e5e1f82f6ffa2f53fa75eb187a062ff3224a6dc294dcab181040e6ad62271e009e2f8180590ee113b184cc5b9097cedafb16a0d04e3bb8aba4b8268d7be7d2be6a4c2aedf9fb1191c56f4b7c558238f4bdf97f1511ad5f076bf908653c84a646b3dfb7dd55bf65f35100d64f3cd5535ab4c6b7e1e78501e94f33cc24c0bed2f521bc593fb48cc3a08a479521a2b9f594c71e1875ad02aec5d04ee0bedbf3da233a3fbddff0fc1ef78e51fa6fa6b81c1c5348e20fe8d83d26c3109f43211619ba836b3da19fe1753e27279e74734e5bf022de85f77fbf948a0833f195dbd73ed902814d4eef8b2dac1b9d727d969cf6d6688d96a58f171baf51de716569101645bff42e707f4886728b2b42103bf97668e1b9361246e4b2b48bf4044bdadab58eae408ef756cc9ae76140df054b0c0774aa457c4eb4397e3fb907775689eea47c8d875edf337ce6759005d77a05addf1b24334dcb619dee6c451dc0d513b39491e2fa66369e3ff9fa3cc0f034c5568d39fbe24b87253d696093a553dda91fa6559abbfc866319ebea494a23d60d90e3a4c3f04f8adf555adeffa486aed2757e9246cd3249850069f9dcb980c895f6e9e71f2d68b9f775a7e02dd42acea0577bd4537687d58e10d7b6ff1aad61caecea8369afcf908922d6ca9c28793db8983600c2b2258845cf9cc9c10dc80617ea328a530ff61ebabb03f236a0f30804c379b46c2a28aeda70a9973e24a87d327add42ca5215eb7998d41f74af81d646d01f28f88948ea9df08320a267155ae2058d4a0394e4436643ca8e96ceb7a03d1d20fd0ddc461f169fca26b05ea6ea158e042c7a479cc03e1ca83f0daaab74d86908465ee4492aad09e3a7329d6726c54083621862fba0903bc97ac5cd4d899d82727c7d3a0cc845f36fe9c06e182d94582b7956127c86c49ea4d3468da05feff6541921fbe033003324a4dedcb024876e2040dfcb0d6b23c71d743d4761a35c48762f158ceec283a8756a4e7a3799870c0a1127380067ea4521b14497469e58d5aecca547ad9163b29e12b18b33248b0113c03c31083040ae9104325f928574e976822b3928de659b46c640bb638596e9c24ef0d7a445a636231682c77711e745a64e8b3b1568d12f5b51c2e231774d9a683c07f702fdfe381ca7eb3cf3089d0861032b4e3920cade81fa8ea3884864ff93c24aa57a58df384296deafa96ad4d6cd0644d94d6df0d6343a97133cfe63b8600b231523534b659baa5ad8092f24b8d3793f1b5b4909c6ad54ab2c73f807e9ce6965cd9d5271328c8e7c0e3c89eb6a0ef3fcd23f5b699e8c07f250b522a501aebe0fb2ccaeaf416b5165f057fda5c7f0e87679e0e9318e4e750142f42ee7acfbafae5e645f00437246013effde999bcb9271819083a2635c9a64dc542246d85b69f73567c991275debd7a888bd5f005040f28a928947aad8aedbe6b523c9a8a4e4f957c5d1f734bf857795e9ab3a66a98d11d54d470578b0af8be296c9ce49e77d1491cc24c720950d34df3cda03444c4e9b7fcfd362722610198a2fbb882af3798ce5f02873d6355b6f126eb1460d19da781d22f0aee0a72a627466e46781c1b1b2dfa76d4900e8df54eb859e799f1508c88bd427860fc6e94a68071a9dea94b15367cf7908674ea02803470f3d112cf409beb9ad5097a488f1a2a3e8ca83745048401e81c3832f4c5d467c8911f1f60155ea83ccb3bb8932195f182be668c93c1ada6f6b6687bde739de7528e80b1efa5ecf5a6d44b63ce5358119384a003172d21aea235299696971526376ea9ea97941b320dc56a26e240b8aa2a138c228fc2c5ddbbbe174f05a589854681e9dc57f51cfef743b6ffae078df97c69c1fa9e7ffc2bcdda5acd009efc65afc63057a6a7d3e47966166880a8c78ff9dffb490100bdd5ae8402001868708db3d16990f7f350a349a5ac3a5e16ceedfbe5df11a24ca65d04803fe33a3f4078f93ba4ba7952c5b67577268ec626e6c44d6efac38881343d6f78050f7e5c8ec4cc90f87fc9eb72083e04fcc8f75bf826df32c36cdec618a4e47e70ff781907e880437681132793e92cf3a56b45039e8f7ef15fff0f80a9591f7bd44b12e4dd6571a6f401b85576ad2ddfa492b8939b42d7051e61299a6bf0060210f44937a958d24644c6ebb4fc648abbca85b1d124a6f103a557597733b202fb2e4798e02ab97603d74540756bf2c820b0354afdba3a45a6a2b751c292bf7efd94972de934d5683778aeddd632313458ba9fdbdafe155fe8a7748c2b49052411fc95f2c8ce7919c48bcd2b2ae1d7538047bb912b45cbef2fc3988b976da5f20406ea912e1ed4c04ad5b470bae4c15707ed067dea1da92a18cb5c3511f4fd8b1c8ab434165e0cf102cc60fe696dcea4f7ce188328608fab61c23b71a7a3adcd62f75e89b3c0ae38abc469ba03310e71de8c5a96d4bf7fca5eca177b620d25089fce433c54460086b1e00985f95570976868ac44122524dde8212a29274d766a7cc78c2b82b1957dc15b4978c68865dfba9ee9c421ed8599046b06568ce25a25129cbcfe3cb4657793d4ec9f847778c3359011939e43dc8c44abf973f77aa0c9fb61abd2652246a2b5927873bb81dc96750bb526886080c6fe8799bb7c0d59a6db92fe5eb01066bd041b5dff1fcbb7a8e95c56f1cf3c6274091a30dac9d18e18fbf1bb619df6a6e886d4ae923875dd9206d39904cc82b8454380f2f372173b1c8b53ea3847a0712505fb46de88500d639aac0dea8150ad3839e351ee36f49678890fb41f0002f642e4d3262304699fc52710000211f09686b40397a620aa12f53938a4e27041eeec5f60ade6416c1d64bd1c1cf70e3a1e9541c680386fb30fd735e874e03d7e4615a9feeca5eed20f0f419c8c242e78b4eecb3cd872ffa4313a9e48878ef473604ec30a930ee4403cf4495100b573d3b115efe3dcbaf5d07e54cdbe5417547931969348c606a3a4811f8a59a3d1e44b938752af022f0910ce4e4347db32223f9d06675eb723a07b73dba905e3b16dee9f0acd83622a0d0539bae5e012413c2b08788302d58b6c0aaa32f1b1681da1cf629c38ed23346feca9e7e706dd50068792822777edb094c19c131ed621bf54620e16e4836e1cd7e7507228edc5e66c28ced37d186edcef1ea2657fcdc51f0761a21e053f8c9d37a9645ad2563d9bc3a62e47285f3de95dd6930827574d35e70f2e086668e212ad5b7f85b63387ea62cb79c73d47d2e8558ff7affdebc2831fd8d6cc69f30f214f7c662776401ba46f32379ca16ec550287998ae490e57f262618363b6479237f6d67462d361e87c04d17f66182fa8a09cc5d2661f4dda2c8b2c18e2c4f3315c5edc1ad029cd1dc46fe4a9d5c34ef3ef9a472ed27bd8e6f9d753c73a8e426cd6bbc71184ae12ff9f2150249ad443572dfc85031c35fa49794fbbc9ef518eb5f4ced129254bd051f605bc0e72c5cb204d5d2f3c55b88dac16c36fb588fb070585dd233b463de36ddf8265c0034aac653412b53fbca4aef8d433e106bb211e2ae19dd599a976f968c3681cd3fd58a00ce345d5a3c1a7fdb8b332eb816a44ff99ea47da0910c4cd10ac471fca6f2c2ff0f04db013e15815738d193142f6353b60489ef1c08711c4d4f46926337cca5bd27942d68159efc55eed31e93819ada225e8bc0bdcb28b6f9325359a0becfa1d56bdbf7bc48db9cc054a0efd03ed40945b8134a2af0eb6319c12bb39a83da3e666363e6e6ff3f5434c39bfa7087d3328881d7673ee988bc558289fe36392351d0ff702c94f3d705798f5a1ff5317691a5269a4c6ab40b3eec7d519da6e725f74f6c4d7d2d9ff189d6c7b21660c932f66e14a543de11b3830423583af10ec5ed0b1e0b79cb7df5b59df9a3b0571b5df49926a7603d86cafcf26b8834c86c513d1a369b6ce32ecc47046636c5507cef0f99789ebd36bdad72bda98a4508b91bd5f709558d57c0669a2e43082f4b2435f4b99de7f473a31678adfd1e813ff14cf80b07707ef5db97579b388cd60f9a58dec891d8a33bf1532938b3cb54d1fc24a35d33cb17725db11fa78de04020a379e76bbaf110b8e58c3032738a5c057ef71883b8ddb0ec82a1dda826ea762e61574ce53d8e157fa90d7ade4a60de1cce188309cedd550cfa84fa74aab3ee10c14b6f3eb7d50a6315e16ce339b0f2aa5644801c48a9564758438ad67942ab1a255685f4f340799d42690abc5451b8c387a6ca833b89844157c15e85d508a5c80a8cb200d7a9d830f48fb3dded7edb33400736eb9107e7e1cc690b3ee1e871d1b32e4cc69e6de71103ad6738855ff07b69c0145407f628186a51c3ccf9938afe6bd56efc93a9d3e0c7445f6ac1a78143cc7ed58c9a33f716e34bbe803918be3b5c0c952408cb0db7e5eb7e1f9c0ea80cf4eafa22139cd7cc3a1c260bec2b4a72ff3c165cca7847944abc5b0965eb903b41ebfc687f9003ff792965a18e02d79e07e040b30ff402bd24bf7286af767600c57e928bb379cc14a09d4f6624e5b96efa093996e2b6038b09bf3c8d7ee6c10d32c75226ea014049dd53da8bceacc8f30e94d28ca6035de9d2c1cacd36bd423e58f95c27cf3bead7e3d1ab1129ff2ccc2dc7f67e9620ee6251172b6f76cfb86e8dab5656fc1169b0a19c9bda8a3c53aada03d05cda8f4b0546bad1607de6e85ffe07bbfc11086c515f0e36e724d15fc6f4ed6b9c222458c538e3f9996009e4bbd9dfeb299067d846c2f62f66020c91595e06e180b6da1990e30721fc7de1c227ca9e649cb7a17b3fb2a49e7f4228a118623a71c9cde7342fad7e689604cbb83138903ac0a4e65454de2d9d41151cc08144f71ee96da3c4338f14c74765070057cb5672559ecc6c24033365d6a899b531ba22140952a97b74dfc35fdd0022bc8094277898d502cf56264d7088bea391afd293c587b14c4e356bfcf78485ce3494ad246355e07995549aff49b47d6ce9cd5a3986f60429550e927a79a31d15bf1b52512cbd477eca7621bc9a71e9246710a9557ca8c4fd79a545d79819fbdcf9ef6a66633eae02c0b2af4aa0653de00064ecee1883cc27aaaa0286ddc2e780870216ccc6c8ff40d1f28f9d3700d94966e779fe88722971811ce4ade4da2edfac898a486b0874ef7347d7e331e89a4123988cff4d323ade34455aa905803cb0ee6b2df05cda4dfcce2be317422e80dd819d6e9b0a8e94ac434d639f7b49078216945f6df8b28f2540e008e4ee68b12ea15f26f54f5a60e32c93b6c1a237991670f1b4fcd492760727642ca8daae0b31db1ece190140296b2c0c2cfa77cbdae9a1ac3a02f4503b1999b799ae9a1707877049d6291fda3f848593c67ad10b53863940d2aaaffcd4a1bba450c1e7eaae5b0ab0d94a5514dc11681758dadba9c10ef5a1f3c62ade31707d01606e7ff64bde50b80499db1fcdff5f29ab81e5361e6262f6c098d93335987d3727fc4b307347499392395214e9cfd4a0d27b568a17db43dba67a59c952942ef66386af0d10a8430f7823c84f8c34008d3669cb8540071e85711ae4b21a735719d1654b9788b0b7c81d353340c4bf06bd550a3c85d3951b01642afe4482554fb1b8d11264df68277a1fa5e26dfec175858c0839188f2b0d7458a866b6d2f4b4a2012e458d9570772d75d5085695c9ca76a2fc1bd5d84dd1ab600fd7f531c8412b5581504064a8292c6f2dbb95934faee0228395d203d1beb4e6186da4346228a2b3afaa8ffd5cbf106a714569c80f74ee2e442f7cb09bf643ea285be6cc36b7c798f376dbc4c96fa188e5fb3ed19870cd067729200efe8ab622a681e0a4957c02d24e10d82055dd6d0899bf958bd436f601e5dc3ec86f53e906b3e6271e1122a28b374761f0a25a661b3db35ae6b7786f32fb59972989b5f247faae71709127d2ce781083c7a0947a3f78d0068d7ff24a704fb94b9204ec0845d007c95c4558be372f1793f99ce43e47aa71e3bb14208313056a5d1295ff0be680283347b42e307f45ab0e4538a97e1e12de536d04649b7c1ed8b02edf95109b0c787efef2678b478a16d734a1d9aee5d75c43e25b811084ac187ed26b5c9a02f845bb308f84ff16b0d4805065f8afc9425be446ece71515be4de6b682442210efa9677ff8973720fc5e717aec5c06981e1e58840172d5743692b545f6cd61d75390b8e719baf501b1b5b6daef62225ca3ac5e2520060ee435bdf743f67607a2345d51af85b69a527ad4446a49e931a6de11d47cbe1a66816eb0e665a44299e7eb4a9823d73b66d43fbe0880f81f2e3af9b680cbc2cd6f300c6e40d36ca623b854ee669e3e91a5f5c6236b6efcce4345dc2cf347c7e34af2580bc21b3b3b5035bc743f9af531330546d71a5bea9eb1c924c1c45bc469fb69b2f1ba00d1eae2a800c76bbf7c87d9e86b9c749c6354b2e68db5e2d0cdae3d111b39103809decc245ce4d3b0b4420efb095564fde87965901b919f97bf2b76285cbe748809d68206f07222ff38cc99b41079c0d7e87076b1d15298900a5bc79a6cac73a611306cce42360ad35b8a6bcc06b3b694c6608ce1cea28d53e84a713887a535e3b9247c7dc7eb5d3e4b016183ede005a60fc62fa4d51cd51e13f2cb0ef1864e4a21e63afad17b5e5a136795b00580f79d1a5fefd5308e188f6ebe23851b51ac15ec687a7aeacf65f265e43fd58cfc6fd312804dca03e84541d3511e22686961a60be3688643f7d17ca40bf8dcb5285580c791426403d9f08a38ee2efde5470695a85791ae16a91de66ebf2eca448a71410bf3bf8c4624a2ee72cf8526991a6c4ddfa5973fad5b7a797fc95ba95a7a4b592b052ff2cd465445c3899003476e6449a40564dda34d756959960ccd7c7fb6932133548d76c6fb9878790cda9fb49230d03868b48b798eeb17fe1ef58f8dffa84aa1e0fcefe8fbebed4316781bc06493d812f6096d6c7f02c3621f62ecf87d7ffa4eb03a976aca2249bce0387226a04d722dd137dd8c4408c0e3d81c6898e44573d5b4a86dd43b1a59aa4d3e285147e88802fe7105d89fc9a0a486b1507b58d722cd98f23635a78cc14b4d035bd4e2414e9d785e6dc751b9b43a45fca4c238c122b7b80b08fc24459cd47b9e0d052b939e20d741e1853f02810f987d0a8d047ac76b0df89629f15b1f4d6b7cfe60778c90074579a3b6ee0555a2848176b00be406c8710ce8902148e26b9aeb168a7fc91a11ffe100e2cd9ad0a1ed18a843ea037f008ad7423df3e116843dee2f75d85d3ea29f935cf0bcac71bd1cb52c383c04b541ec4c1c96721cc4e4ee079e14a001e95c59ebb3d9c195354bedb3d46215e87afb367d5c6b8330aac29bb5281bfb59d3583a04cc205709795ecea1f80dafe66ed94e2c49c236efc12fa483f61c6c9c0be3fff2197c6c6e6b4f303c16802b53dfe3821e8e68e9dbe4b06274cf7a53a4abc0884e027196fb6e8a2a6c0b18034c3d314269967a028753388e2c3986c67e88c9a4841932b2d48885e20fe25f6c69fc42e5df7f73a67196842544efe7d6d97d228e8468fdbc37f36b17cc08a58ffe3497db05ac24b7f889228af085ca6092d244dcfca71d2b1bfb546e0a66b74188a974cd4d40f5068e3009c8297196ed83366e6b08ed336c6def9578b9b39aa6d91d73228af59df3f20697a9d9225451fba68de11df49a92ca219269efd29cabc9b5eb8a82f42fec14b9719dcaf4cbb07b0d156c15eecf8c81f158c0cbc31afb9b16d392ffff47b8dda06e598ea30add74b8b3d2fc78ab829534241307115cf663e11cb1950708ef9544177ff8d4ef12f3eadf81e3add26a15439499cc507e2bdc3ad99e97b84b36c16e6715c0ecef1b22c11a92936d393083857767826d6ca26b4b1fd8826b6c9a06f646df5047160939e6cfdcbe661e06992fb2344de9d2cc2d145e10208de99ea15bb115bffb0db62f058863cb281c5401ef1661b135eb828cbbed9a9c300e7fed62a5cafd7570a43e2018f9e9360e97c207c4eced3168c6063f33f8082c56fb939b3934ad5956eca0178d5c99fa429a0300b2fd0384eca2a001fb85b2395382960485f34d838f6a30a60b41444b18adefb903565a45674f811cf82eeee3ecb39e8f199b0b2c2c3bec1f570bc61d74298091aed58a8a7965f6435f31fb322d5808adedd50813481d84900364fedd7036dba89f1748cb846c888346e9790cffd8b61a915f6fd0a5e2b21f0e393f8d1ce125d29769943da9331b6c509d32a4a6f78667a83fe3da963e16c904209772acfb3152749f90438bd38a19b43c1103ce7631d41546d4f422df0c22e8ed6fc55df695c2a2065d9f4f84a9004d94e20df304f448208d0319402b0b75f56179a2004a5636055859edb22b7d463ea82fef683fc4a07233b451d5ac85bfcad80987a82f752a9542ad648317ec01dfb7029cd5049417b86212503f27e8f7adb82477f3e4afeea294e84526550743e8597aa17578e215bd59a7885d76ac1897438e4185681f999a8c891bad805a46590f509f90ca4e9410e0e21c2a3f6ff2e960f42d0470dcd502059183e13128905615b14156addaaee57d4472818a68bd8b11616565ea1228cd9a39d12687fbc3c0d5e655368b00f27b91231b069ce1c0442d8b711de355254ec22e19091201d6b899d220e890fb75e402fe8d49e3fb09c5a5ec648c80378bb893ed198d16a201fec3b2b5473941657521ef65f3ab8bfb44d99c0ec15a6eb9f6a92fb3020afb8b8b2b5da32afb8a68fc0b87109e8f5399d96dce8642e2d2bf2084f8e9c890430a79dc628a8fbe340a31f44ece59a4b47063fd3603eabc6b1efdb5000c6e2d442c0f3477823fe2a11d7da89eb510757dbf4d012d24bae88d5b3b4f1e09f070c13ffed90c35d61641d403a2b2d4b90cdcf4a3fe76758ecca3377fac8d9982909c5b3f1da031c0d39632bcdc6f912c035b963cd1fb417ffdd6303448a4ee8ad2e750b87a75110eb9044f710149fe0a945e2395b9594850e8be6b84e390044a2ab2205804c46c060aa6c6af01b514df56e12895f64345b30514c92104c80b723f9d4fd7e924abb6ede401ce4340e0f2ba276f94bb24af13d6416431124c0f6fd282503609f804d2a5f268c33483d5d39690158496837d55f1a9f35b056dd75919dadc03e65486f1d7ebe3443e9a2882d63f8752485b02ab4f8b6c31b9368a403400e8d903ab2b0702c37225b6fb7d229089100cd0ba89017524c7359733b0e5fbb7892e2a5e53b5e43bae145db23cf7dd7979a3a1b8bfcb7834e674bed50e2b45561497c4b1043f230299e52f032a1c698447ca2b025074fa99fa55c256324d456810f82c88c6e71ac58b6de14107c51f6c4c91aa0dd7a4af15b753f258ab634718b1d620942ac3af7a8ad4bcba46b99b5eacd0a8ce0ff873c239dc12b17c38c889bf3e6c8096e9ec6e57095464f6aa0cac8bfa55c6112f84b70d42411bbc8457dd9ff7c129b66efe44854fe99e012017807201fc5f9eddd3d51b2546410b3a00c93450566d1b64445b10646b1acbe4080d24a69906e823d210c6e383cad9988cb16908b7bdc455e071a74e10aa45fe935e4a7c8385061fce51c638f43bc1f4fbfb0a1142ad29ed25174e8a1a459c7cceaba5dd2ef5633b5bb903809a8411ccd08368ab7968057c23d2feed64c7deddb410dabb103eaea116a7a21b02da2b8f93a323d4bc2204a04a50d46f1b16d583cfad11948a51d0013b88af21d232cbcf91af6af62d76b4531f378621bce1c4b1e12eeacfe4c258ed509216b56849985815ae590652da61b6241592db43ca56191e468e84c4adc2d1c0825d3e3543f7e132ce4b71590ff14010d785304f1173084457f5e0edf7424d715eebe9b7b688caa1591d196ed3c8ba511142d44363a3e3b1ae663374c59964ab6c335763116f6ad0b2304eeef01c1ef76817e323491bb3f240b92f39d9a3b94099f11029a8b067d6b31a350b4c6a24880bac21c711013099b39cb74c9dbe330dc2d1854cce2d57436cee3fb1b595ef4d94402a5075ca09822129f753bd2023fe2cd7e9f22e22bc93328bc36fcd1962d7c4817c37fd8ed34869ad281c4e198c4a28ffef41a4be41d7172729fa81f229c709abb0415af2a81ae71048e934fc58b12e10c7fc97d1f48f46486f1ff473826272368325405e4211864cc570ceef80f3cc865a690e6ccc16ae6fd1598222b6f5f99bdacfbaa1a8b900078ebbd74bf47910dcccac56a934a9c6a70bc90ae606709f4dd027571fa7a9b79007aeaf8fcce97c9b7cb91bf898ef7ab054efd25f88792652ecd2e668fa61127ece4861a3e4fc8ba36c95056a1fa334e8f56da65bd959825b9daeede984cf7559263b8d0f5470c211f09644ea10e38b6c332f950cf0e2bcdcf9fd43c8624adbb9a8e330af58a668c8e3644d8a6db3e633394d411a1390ffa48cab53027ffe178f20d1a11f4652cae2ae72ce7d9f9ae26d209cab88a360e33ed691e80949b28da20663b79f5fdf8c505b37b1c539ae3983da62d8fcad5c84cf0c23c2c384cf507b26f937103ae17b641af08b458ddb65832deb037b421232a2a4510ca1c08e6c280ee78386019d51928c1d325ceef327b3001d5a0f9fa9518c404a9454de3aad08dd39507b09ec85c630ecc180a371e0ffc6607fdb80b15e33674e18c6f4603445e3ee7dd9209f90ee630b4a31681fb8f448b47092a5d3893936557e68034b65c82a3d6b4b7f5aacad3e556e6c21b2c0e3280ce1e18a22dd6012a96bbe7e6ea27bcf5bd60f11031ee4353729466825e5202a18144db71e5e12cdbde5728fd86a861a5627ab73bb70ac11b90cb5e0f713ef7e65529d7318f91900fe0d1ca23a9ea47616f3262d14aa9856cf92c9ea06ca98fffdc6ec90716e975c6d38b9eb07070cfbdf98698b4aa97862665c2e9eeffda40c85b1c0936a68e85d77be707c0c21ac51cd3a3d2dc1ba88a908423014a73d41929f25cd0a441ca8aa00ec404eb3eb95621135cb1b45989de1bc16a87517a49fb7077e80c2ac2823baca99994f6701ac086a65445164c840e0d17d17aa47b69141010152e6b1485931160619ce146e11d76cc731a37778e03d8d7c3772b4ab964348dcc3832f895e79560de06dce2c5a6e7ba81c463952fffcdb491a76f7ced2330779f4273a9390aa34d0b73b336e3a752b518c834be26d3f94d13d0e585a81ef094034e1e08fdb739fdc94fe322abacc0daf2cc10cbdcc5999d3ab0fbe8ef149ba719ea876cf8e05ed5e9f682dc1247854643a711f7fa6866b94a49dd38b49804a79f4043e251b06e39193c92eba5b6306962844bfcf63f68dc4aeea0b3e754d11f7fec77757c3fab3ee495b6eee12864e05a1465e86275cea94d00de3fd725066d06568714516d7613b07321495af3bb793ddf9ca0d589d4c1a9c874b8c22da3516672ca7b1f089658df37855bada1ad1ed74a3628dab16af5899b371a8146a10abe079f7e18062fa142196100abbc69ccf51b633e576e78cba8144ed23823def94b9975549c74288afb74ac68cff05d5f84c047bb71b970d9e87b868504d34a223dc03509fa64153cacaa1073269730fc534cff8f8ee0362134b3955c82169624fa7c94f16b1d89996b4c4b1fb14300ddba720a57cc19718ff89a388dbf3457283dc5edacdf30adcc9aafb73b48ba597a5de3ba27c815678dd8db4baccd4ea480a70e651d864c03466f0bac1d65275406c44848d0d855904cd4b808b873565c28571c3b7bfccdd13a87919f75722f2384b8dae6f52366286a52ff33831e5ee282d4d72a1230e8475a61eb4035609e78de4dd58c8d337b3a840a0de95bdd7c58d5a45c43fd018512a702bb991ca0a24641af3c88951eae006871ed721c9ef57d77b5ca360a379e5419bae1354a14755dc9d665aed99b11e74ecd5aa793cce7934d9312c36581e86634289925bf5e245f9a68b04990b2b0738be99d79ae51cc08d0d48251990b82405fede79e7672b918145570514e8a3b928404496791e81c13566c6c49e9eb7a131d04dd1018ece041efa09205eac0f8f5e0394524d9784d033a82cc1da4f16162274571935ac18ecd70316290a418f311d6e022ca39fb720b943751faadff411e6875ba93d2c903a880573a10289c4d9b2538ab37485e4f0a4ff059624fad0aaf8acfde43c43c150ea27faa8d8d54729b46a61f387d10d62cfbfe0877e7f61d59b3f5c9a6fadd8e08e197ba9fdbb2c4709aa1266af152aedaa9c7e093f547b57f613ccb417118b1647fd67300910ba3d33cdc82b80e7aca6497dd7ac91be9bad6de4a23ddb7279832561998439a6aea6ed5836be440e0dd05e8b94adae50929c895ec224e2bec20692077d654ef3f4d0d4c0c09645ba12328348ee486321869cb2b887ea2135a710662b3e7679a7cebf9116f963603bb14c06c558c889479e0259f2c71ef8def1bd17cb869881b1f490d67da45cff2bb4402b0d1b378c21641a85888c5642a36558efe145e92e01fc9946cfc37f61fbcccc297b6c43694f5a71013bf0d1f83278fea0ccdad2722ac6955beb0fe0bfc80b227c08b0b571ed8cc7acbb83e15870d531a7be33437f63049b7a8001326959b046b7b89520d710b62dea0bdb27bc667b974d2e6c0387a6aff8ef06727ac1a56124f5c0b3f44e6ff789dfe5a39f8712964379a41e1f72a723112d6dc69faf32860d3fc8b5a051fbf98509a2f2c417dbc8b03e9c17502a37a2bd4bd04a6ff9e8ce85fb48271e381d0059dfb4a15e25bb2e594c8ba562769a2acdf98b5f28a0f2cf947dacd7e1d2c2c93a6f431abf6ad4fd5f4f29aeb0a857eb23b9fe0ece64199fee34766a902c329a5c38d8c2bb1645f73bc93d864aa044823d59a7baca97d6d81dbe394b03962ee19f28f70bd2ca451d1f35aaa06d9ccd52f37fe1f6802d639cd3564bb4bb362cd517a95d644ff2a067c49ae3dd35030dcada3edf98c169f8f0cd4a45e2c030ce9dd4a41326381f0fb3264993efc3ca19f5fbf924b8715b86ed5183c3dfec841ee34c381bc39e6be587c74015fa1f91ad0373285c774766c5cc92f921263b3678a8c00c865153b3b60705a4bcb49ed53786e0ac0a6e7a377a3750b7e3dfb75fbf85d45196296db26948b5921617596e58edb6737173f75933f1a2a11177b7e0c7a27716c96c7ea6d38ad5829844b45897defafca5a6cc59c513fa9752d284754111b06cba4cfdeff60d5495b5dae0ac79618db8e5e8754c4844145b07cb5be4d536124f76799b19589909e722196e1966e1dc11d74ff3e60894d0ea5bd25989e7edaa555004ea93aac79b47cbef3ae0a868f29b6af2cc801ca9b91147dc2ee4eebffbdca48dbb552c109074d3517493d7cb43c3b48033f0d899515959977cec58b3be70c28c3138672fda06a25609b106f5c1aebc0dd404976f51a0b5ff690e341855aa39ce9c3c9fcba748636a8a6edc8fc6a6f546a26449ba02f573b72bd0343236c64971a867e30b502b6ebaa1770c6cc515436503a4d87b4c81fd098925ed8bfbd3f29160066c247c7e0d88d4aea5fbe7e74f7fed5f7225980b9344bd3b834bda8edbb7d99c93ab8cadd7283c79954da69cb44c0345b10ba9770dd8cad740593233a40b1a869c3de4dc454a5aa2919696e9cf94ee35a08e5eccc79c1496f3f11d16873cd822c2b3de198427e9555008fa8d1ed36dd640f3fadd963f3c190c4fb7581e31734533ee88143d8069faf930fe5470e3b60cd1488a56968c3da12ce18999123bf7831eea4af817d60a91b83b109b6a6529c0d6a80e66b7c5ccea55e78d89d9196fec77c7d3fd73e6c3856e8a24cb69c74342f169f51816d571e0945b36b9eae4663a74b175e73e0c14ce336995c52cdd406286d7d00fab8c191a29183090d54d21f9635b41b11a759d67eacf442a00f9a4faf943cdc33493a588849962abca4feaedf9d1a5083a94b854392a7c5df53a767b854583a21058d0157186750490feffd49b1606e6d4cc5c13349d0ddcd0c5ae9cf2f46d54a3ce41f6ee33e2cb0e774e86d37933ab1258430d46398993fbfe94e537d0098d4d4728960958aa3386a112b632f4830279b82b60264b9bbaadd6bfe5dc3a2b0eea4d914c124ecee8d5d5b9664c6ec9ddee077db9bb5a59d1760ec900a6de3f4889136426e3affcb838dd503fac072a026a5362ea5b7d8177aeec41bc5b9e226e6e3e10c4790c5deb80458be8468ec5734ce1da09cc72dc830d950954ddbf2d17d44b2fcca514c3a781e73cfe401c823f985d2a007a5c267389b2d070747107b20cf8f4f0632f212eb4f16336d507f62c201237f1b7962e3090f818b356dfdd01717e528badfe642b67a907edd47e80c888a63cc14624d0851298b03b199148900d00ec583e34dad105fb4094f3aab7f17f5c4c7b2fa401e6be153499e2b39bc8d8ce0feeab413b4bafcf39df0197b7b1c1447e320ba5c07d7de66297febb52dd63168cf9d853379c8e9ed8fe09def45f59c6f45bbb748b043c15eff14c4d6f48ae0b95a3e6ea8654ce7e2d13efccb741f6a28fd7fb36a9a61d8cffe6fd2a6acccec1c886e62625d4b75e7acc64238225eeeb8c3ce1271450782a59da15b9dc7ef244273a5a25e08077ff8fcbbafdfcab3697900148857de84997a9b846827d3d05b700c6bc7c7724055f4695a037dcfeb8e0e1b25afa920022357df1d399e2fa7ee605d28feadd3ecc66676eb56751ffab642c5eeaa40eef00ea760c7ead962be9f152afa6964785ed5e53a3945505297cdd7266d73f23cb18cc1dcc7cecedee1a1331d7b2c9dfeaab2cabed47fa4569f92001ea89d289d3f71b25aab9b793e4feed6251a72bd623495899e567f6ba10936d1b58a09cc7b8ea8f2801a620a4fa4b626d86b2d7e3c74bb07dca418aa7ffbd68b6e6582760c00112441bec497757e4b13413cb3869b0492a2673ba1deb29db4c2d59463ed32f65120006ddfbf02dbe545e5867abc8a60a11699991a0745ce815175ae124e90f326656991106f2f4718284066e2497778a3263a411e0e3df6c927fdfcd4b70d1fd6f2dfd312f87660fd52ae5bd0a03dcdfba281dc86db44dfef46949d55f7fe278f1cbfc59666eafe6431e4197d238a1e6f93fb3a7bbb04a52f99d062dffc4140c479960409cc9f6755b1ce9d443882719d84f12a60c1bbe3c57249b1655a2f504d0df618c6b45404e8cf17a80a1e7341727d8ac134719ea76c4261e03870bb49e1e7b22a4a91921982861839726628a9c2419cf9478f05a5766eb9d0a29bbf97242941787f69e5e91baf89c63a8e8cb071ab8104b8c4ed29b0f19c3fb07439819d1a515244240cfb07e269a1d1b84328b791727c68682a18ae7f5c44df990fabbbac151dc7d82db4ac545425913a5e911106356306d03358bc71e5553d252d8b0b0e17eba7ac90111ce11f28e532bdf203db2c5333594a47471ad669dd73da526931cd3ed118b2e1f2019060dcb05b1b444c0757f7eace65e266d56d06367f602fa2dc5c6b072c52ea24fb3101b9ff259cb6889f7e12aa3144911d14417e086724ea7a46f7acebb6a40f862bd7645ae0a15b34342c78fe93f8f3441c9570764ea1faaca90984d972f034737888b98cdf56ecfd0be5a4b0b5b3c45a160248865d85980a1ccdd8fa230a41121db1f8d25416b13dbbc23668898e5a12a66550494e431daa173362962366d276b397298bd366799852e9c91d9f89b4216d3caeef0783a3bb9f5d05435757e4cf6e0308b90ac3bf4f230bcf9f71b1326bc68383733c3921d4e49f5460e2c477699b9afa4c90d40110e4c872fa78dea557a55860b53c0114c243333a88b6f186e461253727a7cb37f5a7066009b99983d071f757b03d3b12625571f8a0339fb5af030ca3a5c9a31931ee393f2590ae66741e93a952e703a0656997563c539ab0a89336ddad951f7ef2a2ec29b978218ae19d7673dc37042fb4cf1cc573b91f99daa6ef141daf9245c4c8ee8871736a87044d75d61a6097740cb8c98c317323b73529756d427f797f2f4e9897a43f35b7c442ad0c31cda368939b6de27e7b4557c6a3132cb30d66ee345356549800c0dacb305828e4f8edfaeff32a960760fe8d03bcec2d14bf511229284954b71a3202c9db8628a4afb819ef6c977a399e82c6cd32a9e7cf1c8017f48527c24162582b79bac004837e668eb9884853ec819c4c0c04cf26675de0df3f334ac794ee1524e664b72236eecf290832c5138acc953da0903a8aabf9f24ad01eef9e33da5e2b080e2e5f6325baed5e050e6854beee1201a1572a90c3834055c8e805755ddbe98770b91791f6e5b5ae26f2ab74fe8c4b1a269123216a7b4f3625e794f523884e04162e91709e674809ed95225288f8e18c27521c5093d3be4f06a3deae70a1061dd02f0f14cb7ea816473158a282bfe895e7e65eed8c12542fbff3fa890ac8be3eeac4b416d84e0460ee144695270afc16675d61eed887203b300a250353a7994a885b2209e62502739c67e5931523a2fbeb506f9f95cdc0dbf691a23d7d63703bd93e47244c7c8cad2ef4684a19660036b27ad2e6d66edd21a77db1e10dea5714f19dbc1cf8438e90b8aa1788923daafe5f55d3916cede3bd1185d792b02aac28fcf78909544728e99a37c544667c51b7c191e5b6aa6d128e5527154bcc97221baa8071089b4d1d5ea4a8cce75c668b8cb3b5fb1b62622d6e4a38e0caa211447ee07d9852c6a165fd1523289fd734968e7dc49789c8a5e84538555ea38a6a3abb41b0d9433318c387d386c3be0d04ddc66bdb1499c722e8b01187a40ec0a615e4fd692f985a590c7fda0537f905fae6a33bae253f41f2ce11e7c02fe7df85c025bfc742ed0a48b9e9e4b2119c8131828ee419bb31a67cecf3e9f3f2a91160a16caa6fea02740bea39e286db039b12ef17780f7509b5268db4fc8b5bea3c3c0777eda3ad3bacd153dcfaf59f7fa120a4e0ff6afc7fa94f84630113d05b3d5d30d148cba3fa2b92a70820879611cbde02ae9fd5f326d30b007796774a67b04f15cfb9508148bc02ae404155eb4b15561f0e85bf8cf5ff262fa90f8c8c2b083d516f341c422fb9325f0df6cf0b31946473fd91acf252e7088dc2563ea08d5fca42e6718b89c59fbf6000c3dc9f82ff824a2acf3b56a72ffb6b345bec4af58c54b1603da4450bcd0b4f747d942bf9b5ac3024517c53658f72282cd93dc7dc79fa036610ecd5a2bc2cc2d141ba356006f72b7e2ee8f71b08131511ee85edaa201f3357a9db380a11a62522303866af0ce9043d8b00f933ade00f3e8e9a61176a3906551199bcd40bd3379c7f606e2691838f909a6041d6ece9bfe575a0f14433dce468482d25b993e800aed9e0ac14cc80c6c0b9a64d3e0c9cd2427356980d32bc9471053a4f4a8483e53166e82ceca018243df62be19d0a81e9cbc132615b9eb75dc3478c7264f4ade5004a356a11c62603978a2fca16a1b5622333ed1a716c26b5239da7885f645ddcf1f365c0094cef297564893004729437233a7f781f3ca31053f369cf8460af6538f07b89bf5a52d1c8d2532e330525b8f0fceff7fe6ec85b5fce72757ec9202d6db36af3528f72a45361eda4d2e15502a6c3708c5713e95e6cba7794d2857d035c01967808932839c67213f514914762a592dd247f1c66699b9dbfa1d89cb8707e0bbd9c430799f3c1ecda4738de9831885dd9e6b95ae68787c7f84528a1b6dd32914c1bc1da210bf246758f9e392a7504752a90ddeac1310279ddfc8426e44eb6afb1e574e684d4aae02dd45dfc77de894e043e7720ae910046c7e3f7d91717b44fb3396440d2f88682b3d05682b4aece5e10951127da7c1382fdbba2fd8a2914b5f58a80fcc1ad882c4d608862847502eadb0de3ef2233d6111c91ccd4cb8bb22dd8fd491ff6d33c7cd7892f771cd832507c076572ee3921da4bcbf30a022a13a861d7171d0eb42fab8d5fcd6595d4f8682d43c566ad8ec439c3b1a5e7a048848d3b3f75c411d2564326bb42b90ae981f6de448410ac74a2334ad6708ef1bae0bf545ba8200952c90b7c80159a0c05fb4f2d6934fe89e959d8d828f61d83539b2d22d381022e937cb1dea19e39e36ab8384dd81eba988f939dc44e7a8ef15313902573c63c8caf14103b88b97549af438728863f41ad01cc54460f3ff97232805b4c7fe67adc74969dcae26ea9e729dcef11a16ec04dc27a0f4a4a069fe2d3de12d2efa4a393fad6ec63f2c4b4a6988a4f650231c1ea87493ad7ee5a490286b800f2a2d414f35b3362fbdb2f461db8492a207beb1ba90ce494590f48710dfe5c0950bc606b6d60867702bbe2c0fef75655cb4b6dda5a3ca9d73544d2b0644d0fb7af24c0b9a12a8cbe36fbf8e3cac99431333770233d29ac169258aa76efa3c980eebb0652c60db126471af888c4a3068c3bad874c95833de74601e7be830c004ad09a2664d9cfa98fa5ae74736530f2707e1f2b217cf1a6434c2b471095d1c753a4800390857e165a4dd16b2d9790d0b82d7d8d8534595229ceb435955a41ac38b3ef77397ed7a09b0cdb38ced310d448583257720d1965009d6a775ab92e25b6cffe5671a249e358b81c4cf46a7c8e472fe368eb2c06dd0d8a7badab3788980f5adcdf6a3710d7791f4a79a6f9755cf0f0c47c898f381e8471371e6030c341467122c69f7f568f2219ab33534949ad1d14f16affd985dd9f5421f3bf4195116be594f2f0db08b929e0e9db7b472443e5e48d59c3f31e130d17f3ef02b48c4d95356eaad838c6bc858ba0412a974fd4df71b578a6af360f26cac7020d1992a08d5f1f78b3f9e2b51ff22575b555d1507d5a6d34fc1157c7d3316ba2477ab707631c5e188b6b5824b561405e21c4bf51cc6383bf1f3f361dd628c035e6130da504e1961f311b7fcde18a81673e3d98dd654023dd127b25db7dcf3e8159559ae427e8b8e4bdf4cdcba0d976b367ccfb721bd2aac85a196d966e6b5b2d535bcf7b7450ade6d5dd6e8b048a0eb45c469c4f7de46289d8aacc31c99dbcb699d079301143ee59945b501eae8e2244ddaabbccacf57557ca80258da77f3e6bc1ec1e4d035661f36b2afd510c1b3d681df5a490c7a5259c8181b0d3e5725f43d234f0913b39b55da897f5a92e30c7d0f4a3127e68fdb0460deb0b7d06f705626ee4fc89659fd89ecc50d1674458a39ca81e38e3ae658c78e71e4b8030e39921d3e82b3ca9c2ee85f64b4962303975fc44223449b2b0dc67a3e170b9ca56ca45498f45ec1290f1601819b5edf62aaaf2d26a4ab97e8460901d6d6b432e9b3175febf9059b967bd2408cfbe6b9f4522beed109b6847f4705519777cdcbe801383d1126b70e75dd74d8440e71ae12be2db718120d11d555d0c9abbad2e2f3e8243b4f266c091698a4f4dc14bc656c895b82512b7f01af1fc799e2c6f17cbe855b14a00d154172f6bae19d0e3817d5a138e5ff663dbfc40590e7a1ea2165addb434a241da9ad961904ac881905f4b73ff745a4aa2b61c3a5bf8f1ff0439e227698b1d6c4002782a3fee77a815460bc7e6d5a9a96b925582182a7e41292ab0303af66e26009f12633aa72b90993ef0e2d07f64c8b198d48395518f4c34186c03c044a2314f5f84d4a235110bc53b281ad948e9859ffdf4a934aa7f0d6e23bda342a472badd20e3b0dca283ff33d0f2f3f970ba414250fc1b642c72e60828e0ab654b558aff761e2d084c7e42f0258b184f51ba957d6e98775e8bfb8f8b0c401d22da712a53fd5e38fd1807496cad6f0b2572809d840c7e2cd00e78cc798d71fb7f2a487729940ff8e918705784452454520d11c79c312de29d146e03812620279694540c2d81ca2b025adea7d8dd41089a2b84e2b8cb8e70f8721e167e4292069d7f2a60d0ee1fad91ae458841490561c95700fe8ff68950204507fb5162ddc966dc68ef37732216bdd01539338528eec511ddb62d9e0c2efc34f948cd41d459446a0aaea70150006e0eb96948f28229c8bab6fd5ff400c65f41cf193c55f9f9bb4ce4003050fd3a0407ef64bfe4849a4e8cc4e9a1c091086d5960df734d1fe9a12f9a7efdfaf918b9f2a2aacab6080f9c91ce8d0297a589cef64d6c4d486028196ed022001b6371631b3febf2898c04dc116280d405d40dc9551fd7f2f88009c035631bc7e0801f851b821db0ba2270e44316188a37e301be0b6730e8295246f89719432c4a80cad0eefb6d1929047218a1059e96de56d17dbe297f440dff43c8f05b88bd277f0448bb3ec724bfca3755c3521dadc0c3a76a8f3c75cb1895d7a7bb0f242fc1a1a202d119e94231e9f1e13e5b33757a241ac7f5ae9e34159c24d1f6c6c71eeaa396fa3fcbd257f4c1f90ba0b91d964b5f04673037e32ceeca694c1a8295bd7557b94f7496798a2b6e82a8d1c49a2593eba043619a74423ea34e08fed0cbc1f69ac5be79e0203cde9981cdbfec4e200e89e6a799d6645aa3692e2b9652d3fae0a3e81d2c4a7d17fd5ac9a172a57582751b080fe31a75b91af4b1d2abecf5a19e768472d73240a331ede7d6f15d2d7311f607a0016eaf5f92cd23371e22a552ef33f5bef05de767938067b1e2ebceca711943c1ec8a52154a199cac7c654382af4e80b1cbd2cc7146dfadfd973a502e7fbcb8400f9e7d4f3d1c9fbda7419860f7e9200313d52fe1b5ff7d53c40f46284ec23a09db8121200a612ad18967bbfc3d73fe0f5f64c54643f970df682c335a54ae10784d3035a6fa27d5c30145a4d07eabf72d4a3f6e798c0cb5e8ee442992e861768ca2eee8d950c28abb7e5e89833d77d5a94191d5a1d2079b3fefe1cdeb71f780cc487d7ba8cfb453ec78c5128b15129ce8b612fe14af47adf7e0be94d9b6cb9b79429c914a5070f08a7072eb8dc1a32df8463837cbf336a5176442dca7a3b28403a22ede7ca154dfa807e40031acc66b0ef3f23fd9dec765a8ca145e9210dbe91ae0ac23a7b0da82db66845047714613e6b1d053e5c51edcc9f218f5710257aa04323fee7606144594d96d6431a34dbd190835eedb5378d3ceef6d91314993e506d931aa53e297d8d52b9a3925faf0c79a4ac4044444040ec31501d868a10410945942821fa21d3b5ef725c1af86f98ea0bb77e35c1d8af0e0321f367a8ea81be7cf9c8d77cf1d67a3f6789b6431af185588146b7da12db4ad528576a810375ea56e298a02f9979bcaaf637f0784d1e2f9503b4df9e47fb4de399aeead07edddefd446ae6f31b9c5fc11a5cda68517e8fa9f32f079b82b10c1572242061b247e7789f04225208913fca1f3acef2eea9a3ce953a2c744d843582eddef4a384d9973694d23b07a5d142275950f1603d943fa1ecd1a2144f602b4b1e4a2e0dfe2343699003c10a963a2857cea8555653899bafcdd0d3a20d0984036ba566a5ee800879bc512a95baf4dea8243653b27c1b9e6185143dd1c434838978eedc83dd73dc3783dc570dc4b1c2f237c7ce1d779d77210da5ef3801b6f93b0673f48581a9f840a50634f896c2cdabc1547ca0e2c39ddf75a6efbef4f561287df7a81f4696c1b44a2fffdbc57935baa7dfd13047794b5daac1bbee1b04553598060d54c1d01caa6a30b7a83d18aaeaf3e54055fd796b4803be112b59b622324b597cf818c2c794294c5f7b19dc7976f06b09a0bf343cc747be3c54f530c506fa9cc53f33c4ca8f2bc35187e68d483065ca122500aa2155fe434325105262c4f27b3c47c5a1ca01f4fd79de439f231cf2b8872af6f1a7a18ac31e361eaf5aaffd7ca688431b51899d6d058868f643ec4f986d0bad9599640c345f5ca12563c81f4b97ab5c415e0e4791e60adb922bb4206380628b3edf31389a98afd63d6de188c0feadc2c31dd9c8b9e7155be534da3e7927061a75a3b75f15ecd7c6cc3c04a41f3cdfdf24432e073bddf403ab5249d159fc6c6589db21f3ebe460471da49ecd78dc91c7eda7c1124390566ac1734706f15072dbb9411a6edc6028ef3468ef3f27cbefb417ba6bb841196ff05072b577a971f272203f572ba7f1c673a6e016418723d006fbd70a234d202bdf86b595c888a7dc1868b49c259de52ce9605f8e9fc8880004d3c07e5150c321e8c5de8c1d1e98fd6b65cbcc3403924e8401dcfec4d7284f8b5d7fab3ba25cc146c6e86f118765a890427d097ab79361e9ce392703660d55f4fbebfd61e9108f0f0f1e1f1e2ce350064747474fa5147bdad552ba74dfb12161a67db1458322c28eada9f3618fa4279802c611d3a75dfdeaa7e1d5dacf65f3fd3ddce13fc3ca346cf9d67ef66d8bb7ad4e0bceea249630374b2a94054b8b2c65b73ba55a0ba9a6ca71a552673261612727d4a8a37d6a93bd253d718bd3d4dded799ee749cfe3928d77e2d3e9748aa1459a7b02b1b0a3086261c739bdadb5d64a6bd974ea1086bd16cdb744f13ca94204f00d7f77a79853a954ca84d2c1f9558a65aaccf881db9d4c286f86e4e64e49eed3f8813b1b1c57f765f4b9dd918bcbcbcbcb0b0c4c4c8c8c8c378312bd30814bec0b282dce9868c02bacaabbdbb9ba6974b59aab95f74aaeba5f4adc4b7d7979e917f9f2d2fd6456c527c41156181d51c5cfed50b266f9609b784283211d127cc8d96ed2624c615d0b904d6301e1332331c201274ee4079901d3a2b42a80e239888569f9a3a9881afc80b1fd7f5998e28e361dc4f22fa148112040ba9fcee128af3797c43695a7b452cdb9b06ee1f851cdfdf9e953f6196487262614597e13a2c8c76997f738ef0dd31277fc9f20a6b8a6cdb0bb755a13d4c94171bacb7203174225887b046064f9c7561146d0030f741072049059111749749c5872c7dfe108894ca725be35d2455afdddb64a202731605e7d30d65485b4dae483fe16e0a0d6ef6b39ebeeeeee39a1a89cd8b1f5467ee8b11fa745d9dd7af9958891181021621bcb07905cfa0db28cb0fd2d7883d4e8cee94b1871c70fd244a0e28a377f5fad63ebb6747058e0f07bbb5c944410b7e1ffe572911339dcf19b5ad8f3c14a1b3a9e73ba7426cf172d6aba951d826e4a44e7bb06755a7cc3afd3aefebe5a67a8d3d26917db3ed241255b8243ec73119470a77c2d320de3d0a472ff5475a872007df9ef98efe10e9f233284f4c52f2682ac9a1341765691ec815c167484d85167c6c50c160b8429b200e12886831aba7e7eb9aac35791fd1594af5bca40dace91b02682c916214eb1d8abaa1baa28315160479024899124a80ef6f355616129a0a2648a8fdb39d1c847a614cc56abbddb42b29e6cb10cef4a5186624b476cbdf8bdfd68883457fee5fa8b4fd3d2a17101cfe11711114cc469b1ff47152344ab14d8f15b92a4595114451851ec5f28b5bf934623cf68115b25135ba56d1982df2214d6ffbfb636aa1324610453c48e16090845bba75d3d9207ecf9d90019e6e89e16fb775a6c1b3b261eec583f96e1ddf6b934c8cfd1dc5f3fcd90a577fcc0edbbeab9e02f9fbeccd17fd9a3e18a0bfb37b6831c8e768003100f4c14e121882b3e9ae8626803f2f6334d277e2ce0549bf934f25b94a3d832a20118f8cafd82b02f59f605613f4b1227ec81c0245768188d107bd4a3e3a195367cca3b1ba459c9daa2bbfb7f34262061477b5b7dfdc28c34d7674f8f6fda67539adae77b43edf4474a3994d6ad73013c69edbf242b7f6b554aa99f6cd8b3db943addde73d1043fa909e512f30285100027ef84429dbc95caab5101f0690230bdbb5b85a2c2ca6432198c6f060514bec60233ccbe1b9f7781181601d47480ab210058d3b5241c3978768c5ed8e8115938f825611ef8bd60b106301d09c7025a908941c6a3310002bc902180cdf4da4141624f90e7d4c059dcfe1a4a1bc2519a20c6f3c49918141414e4927a6199bc19388cec29aca08e01a450b5af0f5371509abf49a1fe58fb750d8ce3fb6030180c75b229c4e0e1c18b849442c2c11be01cef5b1a4917a8e0b61cc16d2d6c90511b054923272d0ae00729a490428c02a8305dcb819423690b8e991120e1d091c308a4180e1d2d760e236cac00a794ed1a859fa9cdf9a14e9e9c93563129163299acd326d5aad0624293c68c5e603a6d52ad0a2d2634694cc8a24e3228541d754e1a139a3426548da4ecf1a4c56167b3d9cc9b952d4ad326d77a674c489e7e06c92e838282824c53fa9cd26342b3d9a4dacc8f16139a34267402149d536d337137853a796005de5d3cce9195c6e8f687736d24c18442b252266560773aa1604c31d020ea7876eacb942acf566d83051dd3024c5e0bf6bf6b5127af9399cf5d2ac32f6a8f8d27e2b4beaac33d9c937a9e716a264187ebf57b4c61171e71141e360059779e6050dabdcb5b9dd3b30b980251ad9d93d7cdcc7833e88333683d9ec7a8671d1478023d8d074c60080a32a978a584db473d4c01cef15c36eca27f74d43f92ade02338e1cdbac76c369bdd96d12a9537c3f42a6f46f77c029b4cbc7a1ad186391b6d039cf1956b85ed99c146cf0c2db60d169c4e38a14e0cd4f5ca08520894524a29a594524ae74f26246fa1441276f0018840092c27f87358a6e339b2072888420a293dd8010e5a127d9c76c94801185d801f0683258de2287f664752ea5cd9ba96524a29a53e5ed464c72aa7d8b1baa59256b9c1d135c9920e6aad2e46419dcd629632aa8187ca02c81a0da54e4b204219fd00c6db4276325ae2332d01886774054cb70424531413a04a5b7eba2840525c1740a528462a1758b82844a0b06d91d5284cc8685c0c6d328a9694a45cb9007216d7d768e21b388ee3c2508a10006861248588992d6052aa7c49529260d22256f4832018527c3663ab72dbb69538192a96bb5cc4e4478c0dace97211931760616244ca923bfe0b22a46861bfcb454c8c70830862d0848718217bba5cd444080689264b6290b000b85cd4a4072e576c77b9a889145fd4448bcbb66d2f8c0c418218205ada90090332ad877a41a1508cfa176f86bdde285ecff3426b81dcd942eef4d1e2fc6971f6b043494237d0f6d12ed44f47421a3be6b98fd80c621ef3596c168b79cc6731a11667436924313f8ab951cc89621e8b792c16f359cc6744311bed8a0dc5260ca6061dd3747cc3746bed944cd3a39e86a5e738ee51262b7722c176505a9c4e5a9c3624b047c42e171d01643e012e171565b91d6d2b22ea8e6f53021b011eafefa59376a13caf93c63ed2d169b5c2d6d2e27c1b22166807a7d5ae173f79805aad56ab35da5c9904f2241015efebe0c2b81464a32998b8edb9f0726b905ddc023cb17c611b96d7177e3fca98e9e565a32c59ae9402cbeda3767194235cb9f32594cee99f96b9246a1795b176bd789e32321476c2028ecd0bb065c0b6f2e339bda567ce9a3f25261c7b084a23b9d3c94b38768c8553387e38b67f3e5438da5428eba4024cb17c6d38eab8f63d7094d7ab264781630ea7a005733805479e4bc3715eefeda3c0f12fca07f516b8f4471d17d573e98f382eca8235b8f728907b6f343580a606bf5e38ca8b01d32d99a4d70041175d74a1e5764f410c986e178e396e29bc61e2409a16e71709516d6860b9c52d043f708e8da58feefccf6530ed42452793406400c5e49054f27dbeaa52269f744ce3ad0d54f5509f5f9bffcc102b35fa2a2d74a1af46c3733808339da1bb807631b7abc559aebf36a704a1d6e834d3ecc13afdfafe12c4a1a00efdbabdea7b15e035338465dd92b0288ee5029ea3fd940c658ad8ad497383355d198ecfc51d6914a0fd235d99359149252d893c76fb639e435d8807cd6cd78a058bace9611d08fdb1b15c200b76f90e3fe40fa943c3c0863910dfb40311b21ee4e2107b83dd1eb0853ef2a5c970477b1f1e2f2d5455ebac7e04bc60b771b86303adbe1eac54ed684fb5779638c3fe09bb2609e6dd23c94b4abcc0ae14a59c4d91755010aefc0e6aa73abcee48f33c8d8acc0848cbeb34a9cd40455df690464190715110863c879180c160301b828eb8a2048797fc8672d4563a875f3ef5366a97d4947079868ce4d76aedf7fd8b6258c48e9c74e5ebf09c1e2a3d1ced4deaf19cd0daf0481ec9172a57ea13ca24436371d64e8bb2915a0bd85b1c06fa8ffb00fd8703f12027e2428e64821ba8013984851d5b3bedf2c642f3cf25eda0af839865047be2b6ef5059294020c15e9fb37e664811a2b81d76d0ff0b0cb582243976a689182cc96939ab69c4d0623f138d3a34765a3a1bc82ce0b46810b578c6e7188f1053e434bd0f76ac62cb73b69f95c0b902614ccca2efdf95d21da7c57e1af6b0793328b5c131c347cbd7021d923042072222202011d0964effd6ddf45bdb5ae2c04af66654b1fcf43b9955f5cbdb214e184e159237d98a83d9c4e7088ff6f37dfc55ac119124c9d050922494abb4886b4af8b563c7911ddb6b13d8c209d0f07504546586d26247d419753f7347c420f7bd7544ad8ea8336a17c304a95b07e1421ab15d74bc418db090020bbae2e5285df0703b6fb95c0a846ff8795c0e476a0297583ae31bf99d6c7a0c60272eedb46f7094d70053c8ee660024bb21f18d7ce69b4e33712fb804e1b8859a9daf466a754f31791615c010920c45f6220429248bfd107b010f41a40d4047ba27404395a13cf1c412a413f7c5e5a227a028b1eeee2aa72ffa3bb4a7e10e9f235aa87295873d6ccf2f3a41a63345bdfa5c49e72eab57087104c9c70a60f00217bc5c8bebde5d7777f749352f081b83168e624be7ca3c480d414b8888404bd10c765842152552b3caa7147ca1fb9b611fd1b1e7b06d754741626e1ddd7c102589ca7d15a0ad4a095a454749b75e2e3a42da7658a2a6a8382a82722493f1c110b3736653492423c0c8da31f14c7316929bc02318e61c66ead8b058f8089042df9992b6817c4b1447c78675e5b7f8044841748699d765386f86bbc3d07895e9cee499c08ee8fbfad378db7aba7f5f7f933bf9d3e79ceef3e3efebc994eb172bbabbe59c736a74dadbdddd6ea5eb6abbb87a77f74c13679e462744f19e692251cc3349d73177658c6466c6016f8b73ce49d3dddded32d3bd6f879d46690fa9b96bb4dbb4dfdaa5e5b37c57ac740c9d536330a57e6e9c66e16a5a58bc420e19a35f8747c6ec6737ad27471f3d08b4d450c7120fb40f1d9ef25cc97b6cebdb39c108d6a37be40a1ee018fd3fac0f10f04d1fe9589254ea244cfe48203a742c49ea4cb46ed2c84b019dd27d52267432a1d3e53b9d2ee964c284d6283a0a82d92ff4ddde4d1a8e7649ef7906c68263d37a16bbee58bcc202648cfeed2b9d349659dd9fc02e75a5da598be3d697359c9ab800d109bd5b4823073b3c30708c7e2dac61a5d1fa3a656f9d6f1934daf52cd6671a1b97be3cd1767b923378a69d185ae46956c3c0628dca46262c3468681bd52852a93b1dd82a76002a3a1ac1cbea4e1943186adb44f886106b599f73ce404410369041d20a7630f49a5a16779e60be696190607251b8f42b12495cfacdea02891baeebb343ec58a70fbb21899949621a151e7c7e44a92cc13510b149058a1889e4c70b4884348bef582d152d4a2f24393a1a92f10177a5480e64781882c86888257418228b133b2f170d81858c0f40ee96acdb6fb1d8bfade3ada07eaeb92f7d73618ffaa54d5eaec4f597b66799c08a4bd8d15a6f7fab792e789bbf149f05b0a5734321ecc65bfdea5b78c3370b23d640816d36744c0343e7210eec3ff74d58b1431a7c336158d500c1ce1fc07c1544f9f30910438a5294cd2dfd34ebfc17ce317145b14bfb39ef58efa43eb52d2c7d7aa53763a747890b776ac8be85cc3493f6803b05d89f2750d51ee8fde979bc3f7dff29f439d221cf497b55bfcbe97d545aed50e500998f791960de25dce1f2302ea16519ef79bc5243ed927979ed9f66fad013763e9216fd67d8432d3a187ad882b35e5eb5f3f2aa0768ef12f32a19644ca8d242d5045e3ee66548bd4bb8e308cfcbc77c2a5469ffe261bc0c319ffa54b8e3253cb285aa1adbcfdf7e86aa1aa5ef2f7d7f4ca872c08b87f12a2d94e1c5c350c9f0bdeabf573dbf644295f632cfe30513cafc11d3fba8eaabe87c95f631a690e7a5861ae07179fb0fe0978c8c0d7d5acef2770977a4c21d98975035430df0bc7cea1fc02fd1592a07b87ccccbe0f231e18e233c316f7f472af4790965b031e10cfce2178fd7c8b2981f5babedfb5f9e5fa99f797ebd8447545a4843e9fbf98e3ce37e034b1f03a6fe0544bd0ce8f230a07d69c27fcf9e4a7b2ddc81f13d268447fa55ff7dcfe3f5c284ff429fef4d088f6cdff730bf43e6777c210e987ff1263cce1526c060ce8af9d52861321ff31380f955a8da898979f97a7979f97a610d06a8d242d5ce8be7abfa55e803e355e1915283aafe17a0cf119e170f03c65b97df01239440f65fbcea71ae5085ecac17210e1536f533eff2f6550e70f9d44fc0fe4ca8da49bdea01fc4aa964902fd4cb174abe3e50be34502a6911498b489ad0a1a113d8481a16248404c9ab85644e64348432898882a67732319b09e6c553df227dfaf686d8b54d27b06120ca0776d656da35368cc8352750da281cfbe7fa7750bb54d2484e69a3ebd24a8b7e34033bcaa3d9cfdeacdacfa9fdac77761c17802decbc63f560d07e0b6b8b9ee2516a18a3ed3beebe54006e6ddbf6168bcdc18eadbbd168b10cbedbb75adb66a5b0daed96e7fc0d9408020f3308c2132c5e5b873d5826b0e212a5df9e46ac0560d6e6dd1ab6f866fbb175b79209b7bed401393086169cb57d83dc071899c814802d6c5ffe7e7fee03803acedab45008fbdf0cf7da56d24a30a040a1e4d677aff5abf5ade7dc106ffd597ac2d6df6aa86edd7edc4c01d8c25209db68b66fa1552cb03a214e8b3550ac94a92955a6dc000b2141a6dc90b2625faa90c2c2a88285109ec4000981082242c0410f21c44420c48a10806280d0e2b265cb86f9de66762e524af62ad7939b1dea74bd17cab980303ccd416bb4cd8a4d2e5a4ab35a57a2b9a9fad1eea695fbaaf566cc9294eda892a9647489ae28d28fc5d03be5cda05ef7d4d169b54466c9709c342245f56c1bd1f3aa53aa75aa9bc6eb0b33d49aa53965e5eac7d56bdd98d99968a3946a5a9d93526d727577e7f8519073cef8b0f29db92b71b53bc95031670e7aa7006e3fc87933e6871500d79bc60667a57548a78ff3697f93ce979f69be9c55243645b9336c75bf7477d1f31f03706942f04e13cccac4cc1faabb4d5ee99d3de79c34a82928a5d269e5c2fa7d755f5153fbec64c94bee3e39f75ab2a54a29a5eeee5ba9a4f151a7532de5dc1f85aef4ec73d378d35834b97ba51bd50292b953cbd30e5cb7cf3ac30c078c1c741d05b97bbbd62ebd1ded3453355116747470e8e872984adb0e4320870b71382b213b410849e3362afe3b0b88ad760838ae9492dfea69606ec0c0a03430c37f7bcfe1a84f0efc6c47e926af4f36f25af2bcd59b316136f68eca86e1afdf2ea5853c2708496f9ed33bcec430931575abdbb65d717451a8f93f770235b5ced2aa276d9e96849d77f4244fdab624b4eb96644e975b6c490c4a776f1464209de8f2b3a42f7d1c74e2cc39302236856c1a0a78dc294b52b6a073ce3989ec514c48e6eeeeee32a888296768215dba74e99c16427388910b0bfc879a80737c871d82041932c4889124d20e5d4b43070203ff61192e6ee436e898663c2941b22119e29ba65f74372450c82424b74f611656d250f24d7bbb8495924a5b4660479f25ddbe82a55d5fbbd4c1fd249b27e8eee611c2cafd3bad7684a0dbdbd4269d25e89866046777aab6a8925a9ceeaedac2302097a7f4dd77a57005e4acb9fae9401eaf127834c1292d4e155d0139f255d0fcd50fd00f21f3573125ed92cd95d09daba13b574eee940e1eb56b04a78056a683e094768daaa43b7faa92545b56b0e9ee3248ee746d9a3a9041792757661f773e9529ed3bd975cf5f9389813ed8d5cfcac7233d48d435d8ddfa5dfd9e0d96ae06caabb96bcf5ae85fc3c31a66f4bf202f7dba03bb6a8b1d8bf3c7eec79d632907777e6988dbe1cee7805806f70db47d273d2980e87ce7dcda30abdcf9234b713ae29b395f8518586a547d0b8a62f5b3026a71ae7cf4cac7eaa7c569a4c2153bae7eeefc2ed601e94e48bbb427c29d10b00bea80b4385f052c169c792ae89866bc4172fda9e98737e306a845977206f6e6c70d90169dab31bafeb546e62cbf09ba11526df26b8cda35de04d51cf9d7c888fc6ba0b44b4e9965a949f29a2bd76b90aed76cb9fe9beca0768d37429788cbbf01bafe3742ed1a6f806e806e7edc00e159d9e592b77bec9cdceea0804672fa0bd8eda4c9dee6e1fa0d10b39cd638b9393741412eb8fe2a34b909bafe35b21a27eddadebf86a85d9b6c9992dfc92e7b20e883b589b10c1779036319d2bb6b9cb46b768dcc26e67f03f36ead93ed936a9ba9c1aecaedb1f08d0b2e5b1576d199cc91132cfa8f3256aecbc06455ae3fcc8625f5e33609ecb22dba7c7f9be4395c0ae885b5a46030bad8f5adf322643da9135e04d321f8cc90eb417cd32aa2185899019060fb674b70bb2b24aba1956c65845742d7df57aa1f5cff0d5411f18dcc6cbbb3bf01dad56ee7a611460a88ff0d50bfb0eb46052c7a0d91b3bce6c85940edaa29e24605ecaa71c2a2bfd7c8b0b8a05d19d6a8a0c48e9a4cdb8176e439ec5a11e138634473a2c95886f6fe3ecec86a905d4850bb1cc87d057bfc7c7d1b23d77fdcb05caf91d9a46a64d76566d77f4c01b9fe1a3843c119a11924334a9ae55f679a5c7f19ae627c630099d90d92172994935dca0df10dd5d222456a91d624bea1dd10dfd03779e11576529b1691a816fada0f4a472c034937c43234570c16e98f9d12aac2a574d49e5c4a9f5a41a7a049e015681619837e497e0c1bf954854b7f9327b8f43bf955d2e76816b982641ee914f36ea0e99654dbf3159816e94f6abf558b94fea8817cdd9b21c398ed66f4084546406204d95d828683c580bf0c2a2276c7ef569e6db577125d2dfd7ceeeb3f7dede79c6108b69fdfb5d61056bf8621a83f9f0bdfe7c8d883f632c8298278128219ee6839f734b45c586d0d671f40fe16721f40fee35c41c796cf119ef9dafbb0b354ae853e139c62c10bcc14f9e868b19f93361edd1388aeb68b591a75b55dcca1457da3800761065a960a2566adb26ab5d2b0bebf576df2d86417752edeeaf45fa46da76b1e82d972d66d5a6591e6d8c2c922ad3a44aa492903e21288ca154809c42510dd56e0359092ca8c50050977754a8a28a6f8b1b2e4499128981089a20648a208e283287c0ce93477b96dd6ddfbcbd9b639e7f48298734e71ce13b4a0eeae31bbb3c9864ed6e9bc84d28d6af487ed078f4a2973a2b68ddbea86844352a7cb57bfc035661b6cf22565506c69d313286630aef69365e588abfd7403c82087121411458721b2d8604d60c15d214522e8d74385141a5831410e58d0e0a575a13d4eed2376fce4b73c674221f4528792d4c9ad9ed8f203501114376c4786fa7b2263c40db768074193522ab7a94d9f735229a5fc396da46ccc256be3d5f06b69c972d6528d6a9aa6c58498744c33b6844a9bd0dbb8ea587aeeb30ca0affdd4c051bc5ae9fb5a7bee3bad01a5a74f4be0487335fa96b369176dc0560304579b2eebfcc19a6a77cb9e75b27dc2b08ce6baa2611186bb5a981b2616298eeb5b3b955f8b6d695f772933fa8b74ed86ce222800e8c0320a004b24b3ff0c5d38f5957704548692996557fe9785cd9764f9432a965f8ef365f74b7672fb4fd031f3ced1a66928b8f6351cb7af736edbcf163864668d8673bad61e45c73c27759fde3016e645fe95f27bcec9f4085426c39062c5545bde0e12b1638caee53934ac4eab059a198365b084390f8c0418d4e0090e8ac0e087255c34414d44d68617cced974878118e4ad6060e33b8d2050f702022096d8b2230812945b1fd7ce7ed31df07217448820492143d18d1b65c0b85f58860b95be8af5dfd493e298990037aa23f2ed09e14fd9cd808160011450f4014c10225d38a2686684f9ae8e1448dc0c4116ca054d89958a2c8896b0da46aa8346e3725b16468060200004102d314000020100a8784229158309c478234fc14000b708c3c805e341588635190e3388c428618630021841030666486863803b48943e97f7b2c8a3a158d34ba0fcb0fc8b6c62eb0733e0274565b359e90d8c22ec8de0f5afac0defe6518e667a2afbb601c38909c021bcfcb05f934230b9886f370490746e4d242d323fb5f62ce503940829f4f82397098b651590d3c2a5324ac5238d14aecbf2c1289625c3069251fc1a77a42ff6fb7f3ca95d4ad75f06cf4b188513796d26687849fe28cfadfcf1e63a00c50c38c3f4695cc8d35d6eff3282d6b50337eb3aa9ae2b8a3e28a6c4736760b2df4b8aacad4f0a96aef5d456d7a31709d25823b513239a60e629b3a36364fb8c235faa060202e9ba69b19cb4206dbda2f0284714eb72bf37a8d7537d35790d33d276924ae7b2c2dc5e9e20b5f85300b652061e9472d3d384317749c0264e40e741d6c3fb5388ae39d6c2c2f0576e2cde4d6f098a48803f138ce6e9b86160c7ea24c456466c6dbcd39686466fce1b4cc0ad1d07021573c071c2b6125dbc55fc91f97d81ee1f8cee886f6e298ae5f08a7261d4852dd429a62612d975805ff5d19fc65d8ede745e1071be8b789cefcde807ade3c7e1069d6877888d1144f586539bc858992968f218466ec701fbc4f76a7062c598f38362ef41095e31af463395eaade87142d8b5664cf78bb113fd83344f6990174e356722be958239d933e11e41bd9053da9bf79a598838060939ad11dd6cdb4d8906722dd609a10c876ff3a3d65f448246d6a86ae7aec47c090cdf0a5ff187ddc75af21b555c89e410e7d8ae2ec701129809e71b0152d2201512f35f7e89e1365dc89a4af160acfe8d4468d4277c6e0ea02c56e36cfffea1b07013c643e4e35a0c17e4f428cbd6822b6ed091c04143f91bc8402bbacbf27c27c7fcf0a5d5571404e742fc1af3290772995c0fd21bc11eff4d02ecb697e4d5d4160853826324f98e621f5e6415951fb118b77c0ff52ae45ed01032c7e7995ae5e29930a17659d7fa552a840a928ea6a2bfe1732ad4cfd10b4f2705f94e7b074016ff515d04dbb305681aed96738d37c19043dbbbc9c765d4e36ae9558ec3e59b0e4c1e18a8b19d8b7d51b29e33b8725afb9d32df72a98a36eda3459703bb8726f9acb09517dc266475d6f478e2ae8ca78058ee72fbef6ecb2995605e0d98c97fad1c64f9c05a1540afe7016913e9a4f650b15fde963bba190704acdedb4ccf4e1ed89b7b900e6a67da3dd040d220583c9e7f4a35c9752adc91ac8323c431476f465d22bc84ed9f3c1cc3ea5ed8bb6a7aefbc417629e0510723802e5c3b78bf8250c005eba58ab8a8bd7a53a0edcfb24b3cdbc88c296b07e53313be5963d68c5cb608e5d26749edb3230ea01f5bdaabcb988822a32c86f3e1881d4fdae94923a01e771b33fbd3046e80cb3339df7081e374da3a6a79e8b4eb97b1048d23ce9e7a6c9dfb099cf593582817874be6b6e85f65a381cb6ad7b217d4839b0deef73228cc12c604d1ba3b02a745abef0617520e99c5def392ba0e7d8313b1558ad3fa844c5f29b7ea5c268144e030cd96f778b871ae36095d6013d2e861253c1501e9ec1fd476c25ea29ed8a6444db939e9e7c5ac2c46a254f16983c34a24cb86bb229706592f7d5e40984cfcc29a943e479c5396f86a9bf08a6d7a9dfb64239ddf9b94bec84ac25dfc808f42091e1ad9831955ff96d2c72896bd394d257670bfe2282180b478476face32945d48194d0ca0db1a07214676c688ab6bd7e0263dcb8b48d14ca1548867981276d3852c292233f2e01add41bb2dc2e4de7f94a760cc0481a41255958e5a936c9be74f4ccc6a1568394d4056db74068a5e9d9644f8c4d54fd3ce3a6f08feb2eb5995e39321e82c4e844e67138a75715634078ed0b336a9b4c371109915e22336ef054d59cebcf22b8f0014552f2579d63c0705f2b429bc2963ecb32aa4ab5ef7acf38c62ee41e6f5481349fc88076007b336090934bc0901b692563b37d902dc23f8453199246f978af0ac2a8c56ae4c8471c747c2e7727b0caf1115c9aa5fb26dadae59a5c99898278f506906840c874aad3bcc3f42e106c1b931e54ffbe749ad6f2a1e962a6a1b139b6c10f5a6a5b18e54ae9858e97cdb668e434b93081e328b276fa4841361d4046e57f8a6d26ba487af8c79908e5595c1016c9394f97080c9d42a8501f47d85b080862103616631b0e5d139804c3e747c3c763642b773a72c0dedbedf97af548947a60b3e40c93e74fd7c3960863891b0d341f076327c48031abb4322a81928709f08d68bf12868a98dd2ca8e818c8a14c08dbd8c8002ab4097840f8d89d26fa525725a15565f8dda569764020c9988aa969218253fa2d45715a0ad3d5452b1402bba7baac99d80e49a71d942c85f4d407aa7aeb978987036bdf8a21ec60524b69c9f39c400341cd442b8033cb9cc46f094cdf76fdbe243515236e9b569bf4ffab90019b5979dce3ee2881c19002a6042f6e820e7bc83f0e35bec10503b8194bec8ab347fe30c28abd7364e86749c79246bf8ec6cf309bb53ec315745aced21c764f4406340e83ceebe0488e2852f99e27b00c3a9cbb4524871e30bc78dd7aa480c25b174230b73dc48220e51e4b861d255bc86bea62620dbf68c5c99396e902273663f0b4a787a0ae5b8f94f77a5082f3c20448e9b716cee0c08312d48fbb1ec827ec687ca2f1445dd056a173e35dbeefafbdab0366a7f1dbd7c87841f1fa7e71a1000676e698e8dbaeeacbdeb0fa9cc14324e81fcfa714015ff350a6c8ccd39126a5e0d6d2c1be9d7cb2993f0cacd0e0985d7e4119caac9ce029d3f27d26a48a075c6a114cdcb15b46b8460587e64a1808ea4ac075aa4e2cfdd90216b76b809100286f373154a4fc653ddb90e3f10e22cf916c2e36082faa6c7ac3bd7abaa26ca01162bb47bb33da3e8c12ad6bc053716f9a7970a3f3a95fa56c725087c1fa9cd082bbcb25800b67607c7c7c15321c91c17498d794ab02b0e17ae64e31563232d4a3b29c88dd5b3db5ba60fbd884d9f07748e93120a89c3413413f38d340f96c515beb7d06c955f1e0378e6664c4b188409bbe05254389640cce502f0e5a6cd7c3588df478023c6663e59fc45379dadfb9d05c37d389dd147ec45c6491c87e933ca684d7f636a712e48ac5bc6bf12634215b54a784990661d5f91496a0513f83555a361f29a734404ad100ad13b1815ab5ab331713060eb9638c4dfe72c0466af621193dca3fa2ceea0fd176446b2cbcc4633a8e1327a0ad6533e7d85a1e33d97363ce2e3eabf91b590ab6fbc653a12b20a5ddd9eb82699018e0f46fd761db87f53a7ecb8a8d235305b8d12bb90b06b85c0909f4669236f12b72101150b3d1c9cdbe9c3bd928aee94baa4a6f90fc45cbd162a52b0a156918432d013c1d76c56efdc7d372e512b400bc9c9dff7e6053a46cb1fe8b6f915c254b67b547b0458c54c10f9147ab029aa8e697e96ed9a21304db4eb4f33655f245332b60ed843fe7523e6c292f30c6cf69b9bb42446ca57a4793611065ea9ffda028c404ed4d8ba7bf17a0752efe9b3b0b2b680016b8509537df7626dd14e4c1e640d6776089dc2b2048a382674e0d6e7b6a43384079e2771ecd125a616d8d6d2081143df0886156df2438bc4192a958ae372662a2194351ae40b91449df8bc4d9a2280373718823175dcb23dcb38a7967a5672badaa925c4d9445df09992d02679a8518146ae7c64984a032b81d7f4117027f1b7eef8060833938d8b68ce45826e04714227bda15ee94d85f7d6c0273f7830fce43691982194f4aaa5487f4d0196baabc976f94d2e238d0b2c00a26686a6ca1fddd3b05afffffd901594d34996e7d45373af44cf950d916ef87b84b757bab770b3e73f4c9dc6f14366cb4bd5559a0abb4d391e9b3a62146cff6039c08a1aad927fa4a295466d69d009d6a7574ba0b5714a77fc50d0f4cad66ad68ae235b98837827066665f73e119a0f50df25d43d06850ec5abe33e644cd0808640062b71e97bab7d663def78c2a183c19e936f8a8e516e16866d1a278a923061235af158c162753ec0e1c4a40a445e52ec78ba99cb0d8c533ba12a28e3d9e44558a2f99d3b2ba4d1160bd059151d9e87b7feb86732e60429c52358c1a4c68019d3a29b806ea44b325fe27617fd5c22299509e6a235581bc48c8891bd84e017b03bbf38f26113cfda67982c40eb8e9b5c222d95b8652da2bdc845ec7a4ad35cebaa8eb34be44da5d7eb6d7667a2070de2df31ce3ed602512d69b8451ef6a38d3e1a94c0043c2c25d0531231bdc4e67b25a945553aac59bcf1a40a0262d8d42c2c997c632b31c3e3f29211407a7e4598065b529810ac35fcbcb348bbe77f9d8308ff80620067bb13444bab38f68169cc775417a77158f980c7e70cda8f10189d908dbf9875236f2d04ed2403c496d19a7e9ab648224b8e6dfb4e454ea009680a6ed0c920a2d60f6786d9ee493c74caa38a806b0ab303e86b51d7251ea56f339e27eb3a80761b952a4ac19e6540298a71de9c5a61cc325f1f920837c87bb446308b8c40f1ac90f9292b68558b1f1e33fdeeb35f1c6171c3f805b4a6db1477cc36be9fa0bc47aba7612278fde1514ca02e0dcb3a417ab7c886d0c0f0e63933133ff1bcc9e621cace03a083299671509e22be4fe1c86bfae58d1f03b68de714681deff29bad3abb067ed18053639cb493117af1e26b8ff4a475916007fb7a1dd1ebcf408d0cd5b64dee7d88c1eeb607cf11fbe70e4a00f4306096d8a24db201fd79b8279414129778fc38b966f18b114539ac162b260137e3ccb86f7cd45047de6921466d63fcbb5ea94481c584be3d5c29eabedbfe51bdff24c40e0a11e696621d8f7b01df50bb97bb810bb1242006d286e1664fafa0647ba34b76ea4cfc18936d44b6aa01e6891ab005f08e8f0f79e0c3c3e7d37190500f1ee96c90c4d1b81f1aa4c7246f8132a9a04cc6862b0c99caf2745b6202d437ffdfcccb7d7eb8fd1e33e73876214f4ee7f97acaf760e68997d958493c031b2921f29ba3c3b23c8d0f4f2c402746c7f408544ba5c96fef8edbdba1c1be4b62faa401a9424d70582f53e50f1161753a1b68587a5448713d398205df98f12d3ac40568381816f50eda9b32d8ceff643a16db3397685fb2f18ae88420989e1e0d7ee2c8212bcbc3dae8e000958058a310084361182ad0e4e2ab98d359c6ea565804a5613a1386d45116409f8fd1b4a48a84634fb29cdbe59855fd5e16055d95f4d0580e6d8ae976e4f5952894a547886566ab83314c1b015974276020e656217f091ad1db7f09dc8ea23d1fedbdbf2f8939b56d1e8ab026b2adbe3446c0c649e57a8b964641c086741f66aaca672638dc004b2fee97394d5ff1aba8040895b590bfcf6ca52d33e56d9b26f0902c86c9c2d3ec8f45c232a2843792548964486a00c1591edd7538af48b25cc4cb3aaaeca27cebe2a597d6be839505089f452e3812dbfbbb20148160d51f525a58231131db51197562fba38c641b87eb2d958c7b7a43ad7fbfa5fd6aac4f68b1c5f6eb180dced4323261c6fbcb5c9fcaf368fd374656630f2933d4409cb84fc64179e37874a03d4710ffd23c760b1caa50affca946b6cd3e05bf522c7518e9f304b35aa4c822a07b45a8f7dbbcb016d51c4836a31f02818049c2b47a61d0f0146006754ca1c930bd4043ea938c662033fa58fd741a20f6d0485c0f9deb401c4c57f8490c04dc720f0117c2390b064aca047a45f78ef60a348b8380ad39023fd1945c7be66043fac6e22c13dcf92326041b19772d66bb1a726882b520aa36a099cc556f21f5b595c5ac4d8664af1862521c46ce30c0ff1fad35dc2aaba59bb525b3682e87651f19dabd04e490aedfb548118a97123d39c569209ec548bca8d23a0aa2187ca0b7dc6caa9fa714c4389b2ef3b4013b4fa2608d195a0ae442ea28280d8590e3f5baa2207aadaaed5f1b79d04b6876829fb9ea44445315fa01274beffd0e6dac0fed1cf7f04c86106902f5bb9557311eef5432539b111c13e827e23436d5c28594e620a3a638de2b17b46e229342751cfe75ae6bc7cffe2fe10f43bcbdaec76d97f34e3f80f715a689fc9adcc46fe2e3403f8b17e5c402aa114f034497dd288446a633abbad7ecdc607ce7c12d05388445c0bced704b3c423eaebfefcf11a22af6e42d32598a72162f868aab559e7ba6e563807f1dca36d7166224927bbb0e82ee006f6824534e4fe283203bb8e9319cd214fd44993990c7040bce00ea08d928902cf7230338520012869207b22b94f20b4ad40c967c179d8db85121f313199a3dd40232a413593e0a884baa6d7920c1ced84447fcd28f6c5fdca071d02be3b0c5cda8108a1b067bab9816535fd99d9add384af7f20408bf58a4076fc2a8fe8bf3050ef08fc5c9a342e7e8d446322aeab7a7be009f1e86787223684afcec4b40e3a2f0606c6b275444de91aa4e6f092ae499b686f17dc4a4139cdf2e2b0b2b80fcca0dd179497a7375bce21c66bf2361d7fec218f3e64e0d9cef5d9e0b2dc88315b8abbfae1ca6c3420b0027279b82085aae7df188176f8e3a58615203cb8af615faa059b9a9d4bf5c0673f7efa07f3bf53573889ee29a37185a99218c577e4eade37d065603714eed5a8ab4a6e70e4e151e4509c6c36ce1bff6bdcef5ba502d44aee91e8f254f3c345c4dcc9fae3ef159d21e1ac56a1446301dc78f84eabcfe7483f42f37db9b9bbf7b8673f1b08a75069444edbae22e8802795305073b07ca196d1dd71821d8147a9bf7ddddc22a7451df183e37a2b1ed0d867da9ee4953664bc5407d248b8484c5f810d692a2d7c9d6890109d8ada334a6e3feb16abf2c727e04af42a695680087105cc74d6ccb70e95b7a0b1689ee9142ade9419da716718f0ffc6a0d1483210e16a8930a058e085cb20342ef953687560158297b27e4f9546caaa307ce0d1c0c304e42ac1e0c3d9768d77e69cc2c0c5911076b4cbce28567984a61a7041b47009c191e9d6d8845caf61c8a55448a0807197b71d3e53027a7037abc49ebc371326253091bffcab0db5764e3c77ab015305b1b88fc0449681a6104ed5670182213fc151c7a6720703a0887959a798b4898a496056087e7aebd9503161a06aa0e0931aeec8d575a002630fdac2bb00e7d37067c66aa1c7f3e30fb47d5f4f0a2d08b2c199090e43e7537258aab840018bc3fc87a7f812f38c4f0452aefbf3f01f855b8a742eb43b20d9294128c5cee41aa048450d1e52ff7aa4c7abfa662c0167aa01a6793d32585de5571f7e2e7b46b22beb912703b19cb91a28d9698ce34c49d729fe0d85c03f27559e9256cdaa1117bcadf0900ea738428c0c418845636ef141131fdd52776fd76887c4dfa67d3a9932638f8f7a40465ef4bd9bb54a7928165f330734770dd2f11f457bda7a82cb703a3d850501da5ac5717c775d57ecd67ecf4045e8185ec561d1f972c2d65c604a6aa4e4be63d0ec767b68d38614b96a0b3f92386265e604150bb1e7c8a481adfcc4aa0081bf0bf84e3b209a5e795737cbb30411bfa76b67ee8a47b31c027a4c0fcd3dc2592e772902718bc345dbe915307cc47c7f5b59d6a84bc7e043a0c04d7b288dd62a190ecfe343cde8a6d45873061c222f0c1035d5666357226dfe1d8cf961bf7b932994b062bc9a2a9d9338d29551ba6b2c06797849a0ffa5537f25f79537637e1e67255e185a984b218b03a2783d4cd494ad413147bad06a40a1613932f628d8ab3e79d003c417e0ae0373dd66e197256946259dc4b35cd1e44b9edc979b1fe90b906ffa7567d7da9a4c6504dde5b1c6cb09981a46b4fc7d42a8a7f7e1819d04df2e4f0940749d00364c791643673fce561e410e7504698ddea0741fd51204da3fe8909c02f54445a065da6b9257ff1ee927b50a95d1f5dd11d716a532ca6b48a45e4a4734bf171053a2478cc54601ae2416c95d41b54505d4632c777d7d028c51d702122f88bcb4fe28393eba6653fcea3df8551d085fa9b21a9e3cd766dedbb1f5a56969cf8aa4e7b34516635ff1dc710259013c0f36a1948dbd9d471396559b1e35a84627da45c4344c0ed83637e0f5b75b9932973bffd432e10a248e64bf7b7d68a96c7b21020899b66afb245de2d4d097a9214905418c33afc421f43203c080d6a33c465fe47d304a0826369649ef0b816c6a0fe3e868de6105dd96d6e59c21863846be420c6605dd9f1de6b2414b904a99aa90ed141a7f86f7e5dac9e34475694462faa3340cb2af8809a5aff450ab70a0de761e018e363c65ae8fc2c380f49e6615b0f9ab8f82591711b790802d1fb56a16eec7f54453ae8fc030721cc257c82e49bd3e9ac53fe620c2d18f57c09df22d4599e23c8f78ad5302c656acf3d27d599935485b7f70e8ba681236751a5dcb466ad0d4ddd6eb6ea427bd29379384bc87cb285208d3c9a94fae0923d27d500022305c5710484b0ebf9d8300d985ba194245ff606afd9429580846cb84b00f0b8dabe8e4199a8abf1bd1509b1d6cb94150c73572b6732b8e90a0f197587aa858d7554b449d79b4788d5998aafad373dd06755681a243ac1b345bc0a621b2f80f92045829201ab2954ecdcc35a9c297f4051c962ffb08074f2246902ba8064c991fc61561a427762a52d2bc78bba73381f39b72f1ae6342860074533367b35741650ccd5bc6e5369b731af8f0d716d5ee93d7d523225646dd52dc630eb601347107a212073ed5831696dbb180624e863530fb37dce0e605a8d0c116b7becdd5645726fa522e509dea16ad9c58f3b1c5865100dd481d797d29475ac10f182f6fc673a747e889eb08723c44c92516ec4f167f7e2cc471b0db84ab5813a3114cf4859bfdf318e2ea8ac5d10e7b5bd66ffb9f0b026830d23086b8cd5bce5c3483dae9576f91220c492627416c7673e3472f10d214f90e20dfe695b7a269233036ff533f8c84dd9630e7e3e3de5d95ddaf40d07b3cc085653a64ccd887820a59dc2dbdfa2270e2385888877436724a38db3e770d43ef316bfbac4c457825e66c9f45d14c5d4f028750c73e3fae890162dfd0b2c696fd2451673f7132eccc22e75a2cfe3640b3a802bda6fb400494110d6277d872cc00467494c201fb0ec2236e876a3326f2b1f97022446e24d01ccbcf8064a77fc557c8863aef3f425302bf4144746ba4107eb42b454b1cff6cc310573fe688e1f08b6ef4f6fb75e2495722c16e4b30c6cd5ed44d836c620722182a0bdbc0f683b8eca12c6b35fd5e09c95655597d0508ca5eeab455eb8cccdbf061c1a339d08f5c86d4af9b015db243303a9511055b7f668713b841f2e1f11255589f3a8bcea9aca3b8729d18fb8d5fb0a493364ff7d5ec7c9d2044c754cff6f65457db7439bd75a44aca1be874a34ecd128e6ea1bb3cfbcf1a6847f051b581563305835e8c5f75ed4eaed1102b3d60e8415d60187c7e0bbf161810747fcd19dca08655c5af8f4d9201ff8573674530221132abdb103d3e46a48711c9fd32e5244f49cc111849a33e424ff25cbd0bbcc81eb445e0855c23c21d8597fe24707533f89ea5cacd67bf175502fa78ca634bc9e9344db4d0bc9c0cea89f1418f1c66d9aa45bea6145cccc70b75694fd645db42b74e1fd4ef359c73aea34f01f2e0a66b83341ed0aa7197ac126b3575ad3da296f3275331730eb9adc31781e1eafb55cb219ae51e4c8ee381cb77bbf1f28ca6f60d32a9e0eb0568b6b91dddaeff66f9c387d87d3d8905fc53ebb33b023ccee8490b961c98cdb4a97a7019fd61496e0c69ad9cfafd8f745e91c43ad01c3ab4b8c6b88968da97bc0534a93a11c774482aff9d389c8a0dc16386c051dae59855b05555a1eb00c6c98b80380c55fe6f8cea3133195bedaffe15a88e96d11e9e07f160cfeac99bb014d190a7589cd75809071115c817e72975a4132cff0e0b1d44b3eec429a432d99ab194942fc80ad13243a4046e13e54b355d80613931057a1cbb76f00845d63fad951ee34ebba7fae91558873bc426b0a509e0b8e0e57d314272061454b714780423e30a2c464eb13a4d1d02b71bbf401146db3385a37e5ca222d6dff0452268be95299ee3e18855e9b4e146f801abb703f165032bab4ba522dfa0528832c3769c8c607f02dcc8259dc08799e688081928feab8f8bd21d927e4d134cbc27b019781041d10c85e4649f17ea67a81d518d7b143dcce862fb8728c5e6318e9f7272131e82f25135ae806b7bd79af33205db395110ec9b9449ea0789b5ce64d83b8edf7d53acadae6bd24181ab29b9582cf4f29f6c9e054b2c567c60ff7c67a4f30167219ebc7daf0a40752396be643124d9744f3574f19947995ee73c0caaee0be2bafa1bf1947d86e8978d45ea0b87d894fa51cbd24f5f138d4665078fca272fbc44b09d124d57c8f73ccb8fbb310174d0a063d44c79f2dd92841feee02d4a455ac4b12a72a2f95c70660cd14ce555797c7a186253d04f777906f733c1a74ce37fd6b5c8695c51b4620018512bfbd426b955ccf40c150ea69a2ee812cb58a2eb8267bc98b9ec3b5a47608ab298b8654516a293be1d9e21d59e15ea488b717cad68df3c2158f95ec1c9e50b9b1c34c47f2251f0500a948710a552bdf2da674d2884a681a48e34ed6dc29307c119eac05e83fe0a45a2435360dfa5e7e28140054fe44ffd164585e1394812724445b1788bd10e3c5ace038467ee8cff069457ad868c0ae3ec52406ca0dd6a9a6e4091ff6a7d4168777c2403e31bba15d877af17b1483f62932221e7c26184cb248983bbd4232c6f3fe23575c40861872b1afedab7110a1899e58e42ee23572657ffa7a4a90a7b6200b0588339676141b1dd06c08544ea0614e775d062c29b9d0a65d841d03dfbffb83d614278aacbc3c70dde66a417a1652606cc4362b61d18c728810efdd495158d807790e02867907d7abb3ecc69cf71cd26f483925685c03e014b8927c31a969543d7a5d9b218deccf07025ddf6241bd92191992e19882a6debb3f91495ce6080c66965c106132ab35ac182613133d0b34db71d3611c30d9ca1f6064b56943ac8eb9b6fbdd6e3556700522c03da6ae20c23ebcdc3a500e0a064beed0cea2ff8100d26ed2b686340132a00199de25d51061bcc7c42478d2799d0dc145221556372c99b9e784646bdb2026c012c837613c981cf8df35aa6b0bc3397bebf61b2f47839600f6fb416afbe1952429c72869660ebf5750e43071a568f70144b48d5190ca95466a6e944340b133ff862471799e0af6833e2286dcec2ece919e19b5a842d2ef164e2d4a0d32c7c21878aa7e4c9ebfd05cc28080ad6c2b38ae3c21b392af87cb0fe88a0f3072389c8cbc53b3ca93c04acd81fc1a62db60fd822317c74782061baf83bd24b2fbf53b6f4abf8d719f333006f102c591a447241e005cb69e7718f73f4c6ce037fd3890d04a24c9de4f2309de8251d225d80780d7285b550636dccecf3cc0cd78f7d6b16e467208802742eaa71d76d16cd8b6b97046f6caa8d9fa9b7c9665085b6d1d0cee6c0e7a0edca0687b1217641d8b9aca329c9e5ad3852a36a54a22564c492404705566dfbdc23aa9b90fb09d37ac45b7ad94fff5c2efb660e35b7508b2f8d70119372cf9e0547acdc4f9d220d6ce7d60ba0bea70eec6f5b4d67d928358d68d7741b172b491f72ee5997619aa7537c55b48ba00d455a55b4a22ab8d6842718ca37036e5f4218e2d1897dd1ee53c8fb28f5885c41afd6b2d2a5e6d5364621a837924b999bf23779d2ff1070960d262578623f8c4cf87720041ea0203b9ede56b2034e5431158cf10410adaa0b59cc660ec2455a794cb346d4d1e2865bfa264c13ff308bdadf8067e21ba1b692001c365b0ca9f4399ad4c8c32b4588f2ab781ec72fec8f27e8c5f70fef4b7c7e5c5c8ff8708bb0daa3af142a86b3faeb7582498da09cf11bbdd74e9e0eb76e2eb43671d79f7265f0486a9be226c9ed0945eef34314e044c1d135ac1d398e34b3f5aba3b0876259a3d984b5fb2349c0439bb2de7783881029885cbc219551381ab326a5b4676ce98f063a450110074574592590ba2f57dfceafdbe0ee69d4894cfad645ebbf1b2ab294559bd9269362606967a495732eb5fa8b37ebb146427c33488aa19acd7d4d66872ad68be2a8aa97b25dd2687b827caaf15e97bcb5eb10187942b9c5d36682e4e441137f0b29414a60947ec91d4e1ae04f7ebd7a4186887d560028c43f22044b920c5d5890657cfa2c9aa08ac722454236e78623250459ddf78b493ebfa54dab0ea90a6b42a4e929443635548d93c803a89e05f5cc3aee24b22fc520544303ab7f8cbc19603d4487a1088f089341c69aca5443d010625831a912a5543da24174cca9290cd786f63fd74dba5a6618a7243a6fbe86b20f30f885b8bd7e35bcb04db546c175e5625099830a184354d0d1b73b638f64603ebaf97d8768b5ebf12da2b4a4b98cac957b8315af0dd9289fd2d9c8fea7b738192520e2eb66e3c48c697d277db360be5ebb36ec3fdae436dddab2e73af5728c3aec64f334119341e39a83a468f5135c5bd95e8a91673f39c31ddc99c869dbf3a787be5710a61b86aeda52e50b4adfa930897e68d0c6ad63233c886d093a724219f2908b889461043b0b58bcd8ca28b8ff79d9ffcc4ea41d0539adea024c7f99150892a3d73a68fe1f4af5dca6a1f2e185686d9a9f66e1ccc5560da9643b4a2874774b801e914d6b166d99914362f59ec99a8cb521a7d06958a24fff58ac0523c18bd09603ad9970e4d530e841af0ed6aead9be70c647197271db50718663fad7cb91202030e54971b73d8d406b2ed8c541bd2a079a96a037bfc7bfae0768f283a113164851959f8a0004e6f9a00a20cbb0ea837a33f0a053c7e2e4ce2b57a26fb8e74f489c81891a6e2429476441a599e0007e4f82adb459b31043d74d06cd3f93e1746f0006beaaa8db0b2df18e36f8ad079d4bff8bf7ef7f861a48b5c32826e11a0a675b68ea79c381ff370df4435d8deb5afd78d95f7a2ac7d19ac88d4e4e1f7be543c1aa0f08589fa82f5d2139c9bd54c81f6b3cf6b2c0e9a6dc1e140f68e89b89ac9b64298861bb5b949fff9098c996194714f621cb8460afdd5461b9f1154f9c19a99454aa27a675e8d39ebf5c49677cc52116009c2b54569209eb4983ca7fa20b13df81976a01de6a8c8b020e33b6349ea4062eef8ceb8c30cec1a68983a2f1c61be33d43fb2c1c08822c0735de4e88429533135dc2044646327ad43ce9030d733b5687106cbe7e9fd24490c8694fbf04b935ffcaf8ea4d72bba3d74e0c0fd3d625e8c08e3d80095355dc1138142afe4fd31057ec6d75b23544a35511900186e4e0938300429d8960a61e1a0315e27e067e689c2612bf49956459b4853953d75e154ab5168e820876c005f5203e2009c3b5db7f2721c30ed94319a67c262204b79140908fd9aee51f467b85d3ca25782063c29a21a15471ff8014a594ff70d9ad7c80e27f72ffc9e23c693bd1d18875a4eb62062ca4593882cc8c56ed4479b6e4808dae88855660065ffd2c5e80d7191eb178e1a1f7663358e216819b33c86afc9fc21c7886dadf1109b8e6c7ce8b27d0d05c3333cdb824c5a94396b03b4afdf2825a0c4fbe060078100bc5a5273a800a1b894cc022a43b21ef78c0cab2cfc16f709e998113d84460b9b38b119c550a773131de70f49181bb3306deab97527e3e9d573b5250efc41ea70e5f4681f4b117fdbf81fa8a00f925ae8adad8237a87424ed5f644c9432d632848e8cc17c3058789fcb3e4a23d75f204c3faaa1beb1bbc2af0cae36aecaa4f452d9cb7e221165eb148f4411caa21b124d6e29e35c435f551418c7b2ad62620cabca80987a191d43259101c331bb9813cd6f8fc3bb58189de246e35e902dff9f634ce207abf41afebddba88442e0e894abcc7c2bbc2a12dba5c56435db7199ab99909cb511f867af9c27d8fdc18918267b9aac80fb8284f4bb46805e101e745a3ddbaa0fbc49347403ac64e534c1499dd051462ac1fcb9410da01556061ae5dc306257acf10f31d24db734f6935c657945fff63d4435ae9d20c8edabb38d8102af46e6ca4113158925167b9ac009396d17338d0722e8579f8611232b86256877f9382807da8b9ee827b9bc92f9ce4194c07c5023e260081792b704f15368a153e47d241e50a8895ccf5b0909c34ec27b589577123b249b2da53532eae293bc9b4201217493c13b7e3f31df70a272e58b76ccaae530b9127ff790601a4158649e8d3fa2129674178ba383da657daa3f3a48683bd382bf3a1ba145adbb083de39a3c9db13efd0e0b293d6cb878cdc953e1f61302ffe6f4819d7c52f676f84814f94f7cafbd1c4f00e91725ad4e67456fe06afa3e403440e80161371ad52c57f4c234f24e6db5ba8c33f32d95fa0bf929d816bb6059c62f5a4b8d25cb2392bbcc2572ff4b924403fb08305999c07d234f344d967d92ad34b66300bcc884b56e08b2795a0d3cf44a29d5d2af983a8a05de70a1e7f878414ddecaa24e1f5058d58cb85c644b00e8b015a8b6c1a451a032af074389abc0668348e5d5339125e6fc3dc0b1ffaad7e40e11dac6757cbead47b857d825388a5be086e312ce17c0dabd80f0e678d839906c6349f33d561e047c2bd0443e23c26a60efc98b26e1d7361c86dc227923980466405c8debb3d72eb1d5421cd1e762d76a8344a4a03d545c0bfccb06bfc9fad3189e8c6fdc3cd567b718b1b07bb82b034def18c7517dd53b357631edc134fa908b9997d146895c9fd770625f8b477254d0f5bf01e709369a416baf99a5c8008a0401eb9ad41faf83a56f51c23352019dce45ab3e0b504c8608c80734040b4721a2454a941cf83c244f90bbac71680816c383b47bf36adcfe6481b63111b0e0412d3c77ced5727102193666a979aedc80cb9784d4b57b38fe1ed031cfd3703600a8f4a02be2a44d33a485928f2dfab4ab28864ab3696dba517dccccd6a411bf6571f4e439b4d45c3ac902a1cfb9f87eca236c6d46bf111cd99aef6cbd739fa7dcfd23c1feef8727b9aee1e81f0cf2d299a7b6e0585ba316a43fe11419615d2610ef269d0ac48ef9a42fec6f7a4566d02aca771584852a4874aa5dbc3443e24546024c844c879e05417a16113a7903e0e798e24827033b9d1fa65568c29c00d1ac01f0f43a7a060e96d6b9a0d00a8f84463502a9ab64ef986d5e672fba51e12fd97a931bf33548d69e6d78621e58dd261d3ef41a7f25da2aedf0a99ebcd64e7f371ca4a8a22309393b6b2c37c20f1c2c4c257e023c73bec1df641a284a714ee8883f1b496fe0e6109312a78be20430026e5e0568ee8a8005d28cc598d161ba27b7550c4ea3768288dd082730109e8fe0afce1960be8d4106a87a4a18028450b51854472c02ea8090eb6cadb82246dce424273e737911355452ba131283ed433e4db22d26e961e192bb5254c432712bcd71208a6f957c8b22e3f66030f9c136811806742c0fb0828a36cb0cfdc0c4b5e434f01b3a01fe5d52c85bb9c0c49df4fdd072741b4451b24ebf918302874285d5a7cc508e31ecc1a9144c429f1033901f0dda9a9a6d8e8c29465049b201b53be90df39dba9eb056abab0654570dd246d314dd76fd5327842ae253e021a9f570053ad81e148531f76598ba239393269d517f6dc4e58a1640ea2cc240fc07a627039a239a41630204d51c5a45aca1f0e5b972961e55d4eb8a79c246adb3c1688f60fc043070b6b783bb146ea9c1c56e384cf8f18d037b69c639e9fd60355b686ece993a9f6a1a30d50890db4d78c11f41b240a1a1f66eaa3ffa94e97702252945f6357a8bbcecfa5dab40d3821a8882491226add84ad560b6e024cd57d31d4ceff376d52b7fce696b231a318397126a3bf915711262b2d3600257f4c9d8c4309273f662ccaada63a25df89003ab5fcc7c0e5ecb814ff17be073edd1860f962fc07ff791293064a89bda58f061519dfc56812d41a01692bc26ad53af4d8c58691c7921ed291843342038a4b5e978d82633afc54f84c590f82ac045a96759d890e5c22a401d3d357322f12675a915ec83fbec00be57134d1f7a4657bc0e08026347490df7b6393da4e5a6482e26fd7af6ad8a08037b894c92a5387decb5482d048397bfa2da05e19fe4535a674e970de3d1244ef7f3944e577eded179276673661c6ae9b5cc07feea3999d84c6612084e77eeef5908938242b8dfdfba21653f21ddcd10bea15b8bba422fd38dcd48e02f310a6f2db3de0a2f69f85a0783650d36313063bdff6ce266d445957df90f61c0e41e91ac92cb79469a80ff48bec1175c0bc6b652dab82deb2fd561b294dcf314479bcb110c56bc40dece7470fa28dc0ec9a77590c842e061427e02f6b570a515859ef701852a5f8c734fb6bde82d445d059830e27edf735a9388e799ec1320174ac3d7309ad442b5bae8dee5b0689eb15588167557722765f75870d51969547342801c33d1b79931aa92dac0d67d6f5847725483bf1c07e1b23a9239dfddea06913ec13aa59204042309d58d90683e22048ce95948f7d880283cdfdcb8e40c1ba3d3347df8c3bb8e242a1f3d83c965d1825abf139c31ac1e81ad46da129ceb9bf718e0514600bfeba3b3ab4df0a40651ec1ba88688107a489ec349697fa586f9f3b2181b9a25525b2c20ef95b5770717ae9044000eaadea174a8edf7ea3f3071a2d3269a6fe548d67fce5189de05f7918536fda1556567e5f903a7ae95814c1bdad1379a333742b7a67c8686355191319b770f82722d7a761745c0f79a6f0b66e340cb261ac683d93eb4e9a521dcaf43bd30f4f50728c78abb4460739e0fcc5021e58ee1c3e2ebbfaaefc57b4c34667082d3145123d0c45cb0a51808a588aa6e4ff57b198207f822b57e5df91159809cde795aa167587d51cb564454beef65b5eddc5acd787ed561a69d1f592ae33ff0b471cff5e6e1485409ebce8aa6b234f6ef176a8a4ea0c76eb7aea2abbda177c096b93100446c90afdda984edda4d35a4f871d93306f25aacdb505a69518a9017bf2cfac9fab6b7952504b01006af9a4f92969a655ddb5611b86f0c22e89be942afce431d2b5135466b4709eb5dee9fb3fe334a640467d0fa75f29a1f84a546242bb42820cd0e9ce5833fb0b15a91dfab91e640ef85494a80ca52556fc701b88128790979f2b482472328d7e689835b27059ab35ca6f910fdec0259b76fc0257f73381f1445fe48c5b3b36e898572470f3a9fcc5ed0288fc7b533c08fae74f9b1366b200d85635b4210ca9d74bdea67df68e1ccb50617a44496cbef69e1fc357ff7bc37d71af81ab73444345118eeb3f1a6149bfb29eb7c1140394fc83c921e91de6cf6e48fd43158d24333cc23dc35d5f00dd42d4ba574f2e89fa0a0c8aaa180ed50510d4ef2b8527756172eef93f34689ea297e430ff5a44032678b000199dd0954b457d15d1784af6a6520f0dc4053dd451b3d1a4f9a1ed33c1554cf01713c4e057653c2a9f256728e6740b46a2021dd8c1d15881e59f0859d74d0fc48c448666eb061ded3d99bb7a14a644dde6ac1e6c464a7976be0db2a8f210c021b307189cd30c34686aa4214c01cf924cbf776c802de761442491051536ccc56c7e5bbf11c8ae05276092ee3e775066a60dcd612f0a9f66124ca6db7ada5a0502cd826a2e417bc65f156e43ecd0f55e3668cad2b80836343b3db8f01147fac342bb9f293c8984b01f0332a02404eeeb36802b8d718e44cc0a4e2757a54a860c5f4254ce786d01cc8ba1de28cf472b909bfc7e048a07579e43cfd6e391e8828825654aa4881790db89d207bbfa3acad8fec3daac23da5cc09a957c7217e6be3f5a0da7cb7365e47e5597f5fb39a25c43fd8f569c06c868381a3afdc1202941a8621b139f563c71d75d108bbd791da53f25332a0373936181e0a109612c8d0be159f2fe47594d718c202c29c3f9ba5160004d8d87856c71013d0acaa6ba879fe1bd21c03236f39dfce92b9598a49ba56a3ba6397aa8bd6b200413c07f2919d8af0f8e9358519736be8e13ecb5fcfc29ce72cf166a4d3469ec175f1ecc4070a49f10df3d70a7506ef257b19fe7c8f290379fa9c6cfcf2a032a74623dc84c04aa60d36d231b54d8805e5035a91ede627e6ab617c142d7a05566a4cb8de41ae57d73a55393ee8e1c90d18560cdcda15f4c939f74a5ddf5dc6f67d6f915aac5a636eac27a598e015f20a5e1f2d8b6d665a832771b6e840d68f4a4f85c398cb01b0eb888ed964e8000fc5abb731248b96813ca62d4df5ec1ad2f5d0310377c14f348c0be0f8b1d8a52d34888802f32853cd4fdd839fd3d079a5df76337bdf2dd334951409c969327767ee2f31728e371cff10c1b69072a0c33125bae882f0d00e7bc180c50a7444a1350a248455331245b85b4eb2f592cf8261da42d9ea6261402635f6b0c9a1e79f7525cba38b4eb5aa0be61db1c23752dff494521cc4036f122bd6771e6a02374320b6e03c7a7c09bba4cb1b1fb022c85c9b32568de294c392755040ee9b11f452cd4c5d0f638b8158f4044ddc912ee2d9626bb4334a7498485f5a4ef70506c3323909a81db2f79bd070d932abba3dfc24ea7a89a98bbb78ce2a166d2394b56d237549dc5989ba8d96225f7236b0263adaa8057e3db13de179e4d7608d0582046348c93516ac2372dc1f59ac4140cca7591e45d1ad766a314ea3ec670e6291643ed4a058f5be3c12d7d59f74aea76551b3b25b6d89f57d5c0c3d182f052e195fad17277125cc9eb1f15cba0932f034cbd327a57ed9ab08f13bc1d66b1857bfb3cdb711b0180c19af7de412b44851a41f4e33d47736b03c8026db19413b2aadb595302523995c0cc69395cee07509e7cb4e27fc4128a74d1315d2656e4c67ef55d1c18f16aac5648725f439764ceebb89aa48c0145370d6ab3b13a5439a9892624f0c6f120b80792d24fb6d20a888107ffd5d309ce125e15e004f1379357924b8a93de3b2c784f35c4c4cb609605142b3c577f07ec61bd2793530e6f3da891204dc9f82362f049739bc355d4221f3e42f8d8f4c3e64186de32999d6896cf06c2297b688c9e7f9409a27d21ad5af323cd87b5b9ee207cdcc7f95ee332fbd36dde91827d47cbe50663ac118f228fa83539976bb8f06a53b11d14ae684fd98aa09f0acf32ab6feaa1bda6a89f21708436a271ccee40f33cf52046124ffe8aa5daa989d557839a5a135228245b6aaea02640886ea1467e1a5e07d73c152f80c9e7aa1e12ae041fe57829db63a1212df056d4ca05ccab095bbfbe4be2b469d22ead342549443d819dc34c364454bf45d7c3d2b05d85aa16457844eafaf5cb3e45842bf29c1f58043d8a7180137e78a13ddb304601f6ce24386be61f4fbb082568b0c8f6124a612f63fe342335b36ea9daa84b70493ad4feceaa7fefabe19826970beb913b1881ecb56cbad832344d5bbae83a800cf08529c33ba8ec30d0d0ccd4d43fcb8646c0778a040a54aa163983cd4a63f41ab354c0dc3899b4867cebba1f916f388c96a9c7df28a88d3df47d56576e04c429299c6dcf89f6c8d4763d6d8c008464c3d9cc50fd97ea330a078da74bdedfc937a5530e25df46b0cf450b8973eb5cfdd8bab51e366af05d09a654c41c1af2fa8541327076c7f8ad6725404c938bd5905db8beb9be6bb59895da37c9429a0cbe3bc9f5cec944f9a0ab7c1c1869695adfe71d904d01186d21821b8ec2b71d9b05b38f9294afc64584a8f49549f0d73d8badcb9398712c56c1466364c82c84cb02102eb2d434eecc16ac0caea9f8c5ab39cb7640614b74c5ed3b5122a2c692f0017aeb2ea653b0c42cbb91cd98c0f14cf71cb5acbaf3500f6f27582f6edfff3e802ed6a34fffa13f757f290c1078e21950019b64ed451b8ab05bd1ec3fe2e530e19617247bf45153a04f8ce08735243c191b2932667409ecf2949add4ce8b23a229cc590aba89ac8c39237e5b0322ff8efbeeea1052872ae2acd865e56e88a4a99f48b4a4677bd16e920bc28faedd6a112573e0b668aa63f41ff1e2cf5c6bd9e6001ff08c9fc867805a8decd5f8c61aa5ac71a43550c530eac1dbdcad3be4bb4f0d11d9809dab99d147cf2fd3a63c21c137ec0a4b26e0a6bac6a1e3480b724fb4cbc754d0b9a759190102020b4708add8d74de71c21fccb2128c23a2b2a3b1882c5b0068398184beda1f77436a6df1205f47c4b3250ca8b101dfd712b65da1f92512810231886d48e0016ee131023613345c2a91a97e3dba5a5b4b7eadd499f06a4a058e05f77d59ef31e41481bfb43498293206d446ff7c1746ef15db769128a82b859010e640d4715bfd2d9eec5bc7dc150bd84ab1868a8bf0d7f645ca938a4a10b28def7f25926b8b179f51e237696014206cf2f014e308fa821ef582cd22e267175622961a3960b05729bd734bb36670a337fd088243f0bcdef3e2edca73ad992c202383516b876f9a345463c0719dd03bcbaa1fb737df02a75e2de45889669dbfe8c045d99f1545df04c4ad8801aaa12088faffd4b184b93503909d97c5f2c3152918eea23caa3775a736b70fb36a8c902ec2fb2f18f28d71d4a5fba57db128dbd270491e27c3427d0d6bd89e60acaab3cd0d23f9970ed67f385b91966601f4b09936836b5080403aa657d71cf6804b5a547a22aa50da397cf3d2ab5ec65790bf07201c57c67cf8ccd88a66e101c64efc48d265177da4ff041c43e1590020e6a303007d2e588e4e4ee39a6997cc48f2fc22a9557e697481a3ff9284ba1efae2ea2c59446141f73262e2f4d0243e0f2bbe69b227b4784bbbc0074edd43dc819e166dbb4c180bdc7bd1739e945a5f6a258def9f71809e6bafd9d7a25c8a59b8d0dcde4a352fbd6693426bab8be1646fee6bbf1b92bec97da802e853e37763ebcbab1d97a66664e716330c16c871cb2557b5beee55c6a747e8f43de39d2f9d57ef7b97ecfb7cae50a64733473ba3381fbaee69e6866440d4152b5a00ee5870f51b7884c918a8b2618bc3040285bd780f4ac41e059bc1524971ff8e20917e3c5152744900190bbe27f869124cabb908c4cee7e7f56279f0b56ba8ad8c25a6324a30810a8210816391ea92f9665cf2482e3d5cc62d1c1e227367db2cd8910324425027062b17448400a200a1a0d62a89a8433263648444d1e0f622719f581baccac9722d08913c973a27069695708cadbc021eb30de2a1452d105bd4dea9169971b8445d1b6339cef73d6c6abe3d51c89dc33bc944a4296e2a23825d6a363ae6c768a37404736db15f8c3abcc3759a5639f5daea2a7073b0f3648eaa40f46d4b3c5e36697709fa3e094a22fce8da1467c5be5273c6ad7b01289a17f41b587463bb703123e135a99811f617cdc92c962800434b5c043e0dea0d40cbf8824225205c13a51430f2ecf5f480b1f708f290024f36d4d28f653d95a0f6bd09e04573fd1584b345f0057e9806f58d6457e997c035321e97f0831300f89bfa209a4dac1fd238c3212e203c549e86e3f0f05c587661fd65b9ea6a95b1964a0bc27713644e0d79897d63bf4ef9437e89e8030a859edd6c1ef5037fb2823f899cad9cff57038fca6a4b423a3e140341e0345e74a2f7d984179dc9f9c75b3cd09ee01aba7469e354677f35cb0a90cc10197ecef886f33a6e50efd606576e3ae16e1d590fdfde4b944091b83735913fe1ad1c476edad99301b595abfa355e28de13b6e12229e4b4a7e1376834bc89f832ea7ba79590ee3228d68152c5d232defbca89ebab83f87623ac139e22068888813c56eb686a0713397ba1b5708fefc5441cfb7ab898a73c9ada08505bb202ea082a7085a2a8bf20c584b4874dc6a23418326127aa42a4cf821b8e12dcb6b124ce8e81e68990f42b66589d57a98adee14f576c0540b06795822f679428d643423454024641da9b430fdf89b1c28be8042203ed47806fcc761430c4cf5427daa9539afc3d3f2c4dd2449d42aa9a13973a23e76995110d9605b293d91ed7f254771f65ac365dd6f92c80e5af3ea2014e2fa099b0cad333c70f982ceffcbdc8db52bc10d07e41240d205d0b748006fae5943821eab802db9ed396339bf8d01e709adecdddbcfc2b6f19f142fe2c3c82e49b915f54072828e150d86d26d9c8bc5aabfc34e669873d1a939f0d6c74313c4d455006384bfefd4fe5a4288c7169dad54b4df08c11c1b5200a5621f21f145dd214cd56025e85f63eb675e6a8ec25077181f5a5d6aec3e7cdbcab2083b765e69bdb301781fabb563e37702effbf28d0fd6bc45f588f50396f7ead1cf21337ded70022d835f690b830848bfbdb4cc9e4d150b30925a57912d04e4f103ae4108cc1ce96cad9dbcc1a4d426a109aaa3181cff1245f9334e98547a3f1b66a8420a490313cbc4df5d43ab2fbb811d95c1769cb4b3117eaee02d6622c265d5fc6c579d827f5c8fc61c651b1223e62f81c0fe586fdcac906ee784087f444f1350d71cd327e2d46798f370b63d4efc86bbbd3c0640ef5bf0a3cd14cca9eeab4714b30c2e97f67e5148a8c9c04ab51320a03854465d280ee3e168fe9d657989a4d481583706f6e49a275c700b0ba3cd7a5dea7e66f2e7b340322a5d17091c8752920e6794a26c46498a01203fae00c80d0d0e0f192a004b51130911732e9d8e802d9e54a8ac3c3da5e5ef01831a3bf0626de16d6ed8e63ad7ce0cc9c6fe0e7e748a72b6ff18597e060684f7952b1317c2f59903d2dfc0301c628a6e5540212b1c4855c3ad77a222f780bb9fa21c7aee4bef1a2427030501c1cc9f5e751b40e5fe8ae37fc5a10ecb71815282112c50f15e01354e1b8feb025a3815f74f0be65486bb7e903f52bbfb444f5e4fe1dfee2b7cb4a3af5f00de0299c856329b01e888238e292d5497a13950d1a5b7a5676c01ffd0ebcdf6d82e202d9508a3f1b10cd39dda3938790247caa0429aaaf7a62dcf34d4db8153720fba38197ad9a17e936b55ecc48d0f2e54c264bacc67a489346e2606cbca5937c5abc14d042ff670626d3602d7ffd163b12abcd296ef8faba71f5471cb1e39e76c261459844cfdb8a41ab3154b760ac86151d612c84d037708bbc3989c8fc239253254c813404e75b147c7e0b0b2be5cc1cbd6f27560ceeb0417e7311259e14b4df74c1ddfcbec237ab6f4287cf60108dd666a193dde9a7bb6441eba5aa47c03be76ca6097a38eb0af46882800495194d5d380e2275963ea5c6e6aabf5a304104b04968183d1d88988e9b31557be19d5dac0283a3467f41834b1e32dc6e3808d593ddb7db3a5f1437b53cbd8a7aa78eca0dd527f3b3640dd8f24bdcce7b6a4bd3df4316fd423c1214310c06aca7dc6e7047d9031ba25daf62f07e23b25ba31403d5bc1262c90d5b1db772dba3adf73496cb5e07a746328605dbb8816f5f3b62ed85ba02bd9d9eac0ca6311a70557817da1e8d92b1fa986de0d352c7b29473a8b7404bff011ab4a706655fe29cce655d92ec4b6a3f1ee2119b771d9a1c4428e660f64fcfb4bdf7b9f3613fdb239827477bec69df75295b0984c661c393a8dd71115edc47310310c430a48b4907f1d41a4ecc7a0b1604b9b21dfca9612793a9189177b9f226776792789760a1f7042937e7fb18634b29124da5c7e4abd5ecc8040637364193fc92836b6c8f6d9d546ce77b3897d6c18bd72142d375a2208e783cd0182f2831c6fe90f10395388ca61c7b7b2e84200e204a21f26c166c2e37dfc1058ce2f39b1e25e6c0791ba879150fbf2ff6fe27f8707538815bc5a453ee9918f057e41412fb6823c5c1e1b9adbca62edbee735bfa9a3e600e81513786559d1086e33a5a358ac834ff7f2f8d4d3d25cd56ac02febd4a43196adeea8a9bb53678c6ad38078f47e1217090ab8ba42b0a084a654c7fe7139d2fc66b3aa98deeeed0c3f798fd39daeff78f16952e50e8b68f65ea84594da1fce734089146dd62f0cfa0613fb07053abbffecf0a8bff76cec4208094feed04704be96da8796e60e9b0d4fb28ad6d6f09c434769f4ed30fcc4a2c80dd39d69d603023e00b93c7fc6abaa0d5bbed4d84307d332c6a9dc217f61995c66c6d4597339b1d07178828608d2518d4170d9ac098cddaebb7b0d72da7661fe0821b62f545eab9cf91e3add1b0c382f0003e950c012e4283b735698b46d5c95c09d6f55446bffaec00b93a15c205ceab8df8b5aa6f4306d16a5ad3ea0a0659f809e1f45fa519f1703f665c8f1b8fdfb221bf546313709460663ccf21da287bc68abb78324902ce57bbb5e40a97d70f2cf4391a5ddf8ba9c652b30646a25a05289c5b242ad63063468d36ddf82415fbc2396240e61aaae249711f3310fae08958181fd73bf6600d1c5a3e4266f10d89e1ad948b755f0d2e695f770e343316e0f85364f0fb250b29977313707cfe0c01e7fa6cac61378df044d8750a6b9d5339fd4118fb16e21a404eee90f0c1236e8193fed2af6f5c65d8bea6d79ecbeb602fd0bc8ad59147dfac2d4ecd0c3e73a4cce62c589f3f7d682a871932ccdca631ad0e9334f87ee491bb2ec09d60a78c4d4036c30c97d4dda79be5de426750c4dc17e37be64f7ef15db45d2a93106f97c598b77ab321eeda01a5978e8b47d868b197e860a5a7d49eedec9b2f78680e1c93cfd6af3e08f4360d90d2d0b946dc955a8e8801094ff737ab6776d9206a1d070a684d3d6e5471db15a47c6c9b989c79a378077bb96d9e2e16ab32a714263d36f57f0822b131a565fcbbd92689795485bbfeb92301f7dbd71bfcc337bacb8faa5103084c2344bbd42ff9a7a9d7752ee08eac01b07124616312fc49072f3cbbf0d98ccbe694bf42a07323e16fb4782c0653824852cd2cabc93b8908744e111e93f73a166ae2d79241041f3d9d724d4b6c57a5c1f55a01793a76f1bf3a2612f1bb66f5777cbce26580b9025307d049d56a4ca45b40a148a863565670174fc2e46f01865a1bb1c1efc5c4ee6f3636f0f04d310beca36861267017b5815fa185cdc0210b34dd6dcb38036112cc341bda1e4c82e707715c594f4a3593cc520fc30a0b691c144d5cd4868e31ea834957ffa58cc3b9289f24097ef3db99a4074ccd8de0c5cfe8105abc5c83fd3f529f54ba82110c85d6fe4f7c0cf396d0c0505eae54fae778dc1e0255ff768face03c5c5439152b79509f416961d30ef5390da12ba2a2b9f406f3f5171b2354592036291007768eb1d1e617a611ff79c42b9e9a73ef103b0df66c84fd3643c90732dd21932d04ab29e1af0bee56bfe8ceb993771ccbb1c040fafba882dfb30a0db4e0128e9fee852cd3578833d77a923b21bea87c7ed9cccfc34a7caac753dbd89e7dbdf26fa5795263b227187301e21ff4cb7eb52c8cb7fa0428538f4cc838d116b0293e1665ba76990e3d58f0aa600e25e8f6200dddadf1c1a886a7dc75fd62bb48ad4e4bb47aef57b950a6d391ae7990fcd250b76229293ae8a9233842dc059a837710bcc93592f7bc95429a033324ac7c8e2e087a2f3633390ae6af12536a73df3eeb30027bedd95384d10920b404371c214802acb7eb84b94488c18698756e43902f0d4738357d8d8b0f32bc744a0a4a234b044fc036821e495fc17027bd6680d454f68de1d191dcca80b4290f0a2fa6ea0bd8dffb88646ecd4b8d39c47072694c6b05d05327d995a62ed5a61f5755a6051273b69c20cd4fae447be0f5337c2927db694427b28fbfaa5f4a3155e742d728a26071abc4030d864a1b522b0d0e463b40e5cf404d86041d342af6beb57dc38d4e7ccb3662c5f52d03ef24769e0aea68632b68d335ebaadf362db4d1bc01189147bceffc9237848f1b1e3543eca0269e9adb3ec7e8042ae540995722d946968e3715d67ba93c0d4e0bba8961e547af914c338fbedc3320e185b8aa5b401236260cd7b32ba7ad2b88fd437ac2c712fb5ae3d956b8b3950175b6a3098b97dfe75312cdd723fa30055579717aad30a05fd6556901cfad59d37cb093363f8c69705c8870ec79339c8f82525bcdcb75b383b54c3fa1f3ca504100a3c3b15e9a0f014b93e4a87db4b510c84a3dbbaec04449f117e6bb37200d0056376e89b3797d81bd3337485a5d59c4c8457d9ca7d366866e44911ac5dbe7ec5ac58c776244ab9071c88e5fb6f390bc644987b61c537631085f10039635d0be8d4a1f88e826d555b64ae1c7c23691aa338f96070e5fe297d7117eb8a44b44e7cc3da060f810828126ff3f6e0a4643f80eae3c97278414268241ca2b42c95a57acc68884b21eb72d15db3943770e500974ee787874bba52dfa8ef7695756d5a89dcc3b2e11bb974601078d8cf731cc0e08364ac3d2196037c1dd817704b5fc9590b23210b07ba259ea0b40c7326d69c90f8c93e698c7ccf0fae5e40acdf0fdb3b30918e250a230343ae04960fed7b8feee06f69add5f28ab2f123d7800ed3f89677e13d4fd067c82469f9f1c9c0e3044dc6ed58a0c121f20e82ec0c1805554091f63df2f34242bf031809f2be308b04d15cf1512068a3ecd108c6b489ea6a93528c7df765cea5cca263a02fa57a9e5fc6080476d7f21591e123f8d4edfd1ca52f1ffd91c51a10e3135cdbc3f72d27a87500301629c2dea22edaca1da655fe56d5418593519b32084f53c090b503fe87438ed4710dad429d55805cd6ed8fd3ecc9e3423bdbf4df06d8ab6fc5c4547df9f0050f3c52111f48bebf3a3835ae962f5395a3814eec10f9d0d1a2841ff83e9b7e5ccc28a9944e40773deed13564e434b12f5ece04c7e7416327f82f0c984707d8371b2f6a84e8aa95e2c33e75f41103167d93a03d07c94ab37c7bf92911e406166b7cd0756caa1b8f59a0a32ad956468b8535ee0fdd594b91d0e8f97a898fe4e98a3ea5f6835be92b49b51a93cb9861d24f0367d66f7f72ad418122621f0e6e59995827b74a2dddd563db1e2e3a15ea94304baf832d5e8c2f78f364abca40395a4f02b9c9067d3eadd950f4e574256a679d7df62b1a5dd3a10fccfdf76937dae903ca255cced5814d0e57a64b5455890aad1faa255a537c427b3a379b3f75b1ed11866514148c4754ba3e3ce6f3f25cd37cfe49e1c513023fa490812b691885b457e5a9f19039e0d9cbd4252760ad7ec42ee88e3cc11202f1302e0f689b403448ea8942328b888738b13d5869158abf07e07a2782ce5be339582558611653d8c367a54b531d4ef8416171d02502fec0a1016d5d7c28c5babd4f383a2f30f5ed8d54cad9877aba420a6f1e85ceea3b9456970f0012ca2ed4d26dfaffc33967b15f4ec9e242f071f4e832c4955dda1e259129f1fc86c5375280e0c990521a0f0d3fdc4ad20c5f93528d9dbd602777e8060ec0833754334e5553803bfd400fe1df8b87fa99f4b6bc9d64e6945792a7445ef0b95ba813d78d5b6000bda1d44c79b9a788012880aa1f50debd13ee99a133861e02cbc3a0e23f3b3d3199f7f01b2c9802a31b4e702e357d834fcaa34f3cd5be0e461d8d4c4c77f5e0288f272ffd0aaf91bb9049d0b4dbae5c9c9f16fd68125d52d073023a4a5225d14724c091abf101a02c748fcfbbb0045ec32c1aa07528b6e92e5dfb474f8f8471a5f9afae34e44b4650853d56df1660bbaf478c97d9753e27d730f0b34c1ee651ad0f3e75f6a88a92595a4a4ac8887248f1222b228f49d89a56335a649fdba38dff095e676af22bb01c2507ad9400c80c9bb901d4df1a1cf3cb58f71985252988f0ed6ccf54e135dd00653a2092c34d43b08029222c8979561f0aacd873505716635969db7744be8ece43dd34345dc432c628310f8edaa62bc98fb666e3d789ea461d53009b94ab2a1c0caa8f3991b25cf66a8a0b673d80dfcc2aca2efb6eef3456e2b37b0dccf0242b0842d5fc8f150a937ae2385f1f6916f984c250100368f4ab0496effeb587458ff8a72e942e689c917f3d65366846fa4effa4f0b207680fb4f596faa511c6414eeca1303f92d873fca2168dc7da8d0bc5dcd4741b5afce451c907e3b9f2ea13e53e85b9c0e994bbddb7de06a912fe19432463804d520b967b86e516a19c155b5118664c793a85e1a6916dd31ed93b2c99a55f281a88b35f26ab613252b73806d882ac68b7b1d12dd6e644111e4da590a59e64a86f54d0f92fd06065de8c3104c3874d135cfb2c2358c82ed28eecdaaa2b4a903bffc95e7c90cb4cde8def3ac4f4d638ae2e635da49bb25ce660c50f980090ab854c7823971f60714fd5c8e8f2b5ce11e09507083e3110fa513f0a3aca5d1453fc22331a09cb09a17d57011fcd6269f58e53a5046c30977e21e99d031ae10700d01c301d93aca405f98356823b19ab9301c2ad0a7845ff95ecae6d944dabbf200f3fa7fc61f46384ccc620449bd2d48fcc740a4dd6546b668818a2ef05939d6f7bc2770559df9a33e9c3f4971888992309639115f638b2bc5c421dcfd03fbe07553a39fdf48690c6d15ce19fe0978ac1ad1012db8d1330ecb10931b7dadcad963afee1c74f64cbc6b639f763ac357af0c53565affa8f3518b4f2e340cd1a886af4f49a2dd6da50b0923a3ba83d89e3cf7f8c458b9d79ac2f034c712bc9583afdc760d54586dbf17520f1fe55e8017385d9dc3e9b888248a048b01bc4049b8fbeb239e6186b5086134f7f9e1ffce755ee5aa2909a632c3af63eb8246aeb996065ed3cd313de9f46a4cdf1d0e29b95be827a3027ee0431ddfbb787f34197348af03d365cfe356cdace8136de85efbba0e322f6d2171f33b07f1a1abb7a9fa4678bdb7df2dff50050d85c13da2749671f51c97ecfd6bdddb0d7f5c816bf531126071c1e16481961e8e312bc31f1f43fe170919008939ac269722f3a5be4bb083cd772eaa2706ebbf6448ad55d4701aa64169a1f14ad8024b9d0dcc63906e4c08e7df444f93077ff4b3cfcdfd685e193dfbd22c40c4dfa9ea58d6e3eaf8cf6c76b9d197d8a8b16d5ba638b642f52bfa620b6d2bb07363bb04ac3f61afad99a04631b8c9240e49e5b5f267642bd3ea3306521b48d988ffa4924da59f443cc1a033cd735756daf8b2b6e3d765b91405f17a25ca1ca0f61a3a5afce53c4b04884766a0df4ae36febec89e60886ef3ba2ceb89fad233376934840fab44d2d1b7a46b17db056ed6da7932a8058da838936bf462cfd8fe430eb890e58b2e3028d74ea68639f22bbc9541ffc7a2f1d0c5106e2f6666f8c9a78134085dbdeace37a799447f2c5068d785d6c1640fc2628b0697bdb3f9a75bf8fd66deab9538bb6e222423db7db4a941e8cc4ea8c22e09e213f9b8bf6a32e504a6c84d9fde3c8e86b6aa3e7d80a8bfa60e6ec80064bb669d78111010ab5e55a5f3a6803c03229f3f5059a636e8572ba2dbb0d3b3454ea035dd4393b6dcde8ae5ab3ad189e311bce02d8c36ccd71c4c1313adb16b62bce5a5ca0677da411d2e0c92ba3215294db15b8f9231f636f38e134e517b0a75ee4d48b5b693f606266db2998e28c4b86f8a2bb0831d3493a846ee31944adfc2b80af2a69bce00126b4f48aa2976eb55f4038087461730b685be3904af2e42c1004470974b914020e0450e30ef298cfb3dff44bf4f7633ac2370966cfc626a8c400aa28bb24536ffbb51c028ab2b9bde92267b3a285c8fe712f3e292bc8cb8505fdaa674b43924c3921105b8949a642cf9ddd2a3b3a4c7cbd1a87fa47f87dc297a710d55269153bd6622810027c95e5fe8d4c9194e44f10c305b8bbfd4ad8ff02cf890228937cc9705ba528c4b229154021c88892f769f2a6f3202d1eabf32c12eaf6f413e63fcd557dcf699b5466dad9eac334d0d11008ab24de9d31bbd7f247a70e21018cdc081e697ae603875928df7cc01bb73892897e7cbfc32bd4c2ed3cff475364c086eb747566eef6d7964b8500954d3634007e9fdc9e3490add81c56738ae9ffa4605fd1e2bcb7b018d2860c84dcda005435fa3411a6aa1ffe4331223d835e6b83883a844f50fb29ddf989a47ce30b4c9b56a056e038eb27701db65c9daa9babd86233e7b88e817d9334f419bdd8439ecba71861049c4dd769a56349e883e0810cebf6236361faae9682f528bff3494a9cb47c78fab112db0ba207e9004838a57191a75457ef66630678fa39256567b35cad3e608b07a86208ded8a21de342f1cd31b17c4f5b9a7f659cb8feb7eddca5a64d66312bcc9b60b30a3e0e8679c10b2d3f380285c9b63610be3cd26924f1a159cd5852269962126ffd56aa3d6e01c08dbc5dbee58ee467e672639e053397dd9778881dad5ce756bcb8ed905e703fe6f6b4c5d186bf7f3772c584499b7ea4716c82b1a8a413a30d0306927eda90d350cc7beac0cd49baf1c2dcba141d19d198a322a7d5b50d0920848fcae76c4589745723d7f01f9bb18d752462eff3025d38367a30c06c63ba81aabde36d5d261523b67d4824c80faa5ac92a32c0eb421f6782d60e8330dee0d60a19740ebe046ca21a8fe589ebd0de67a20f3e678744154b62e21b011c6876010efd3e956fe3d769c2aa17d76c73c240ca1d74344bbcc0351836b16dd08f69c9ba05e828140613dd5f89011b60c10ff0f42941cdf1820cacd508229954fc9f1a51520846edfca91acf41aba84d24d88285cd8c2b771a8326e61ce534d1a1d8f3e75431141b421407f730eddc63699f44cc3e6c507673e6ed6df0f2553e81784b136dd4de3977e4250889e5d87992e81983f2fb359e743c32891771109a7871184f3051c01f9cf1b6ff8355311fb30f03efa5ed4a0f8caa058e030cc7d45c83b63b2e865e81082de18f0ff39e0e3070dbfd9c8e1e26b68d51fe739e6af96564e7d8810ad81de21e53c27f2d5d4a766cafc3bf6af114a20c138b6bc1cf6d6b11d0d0ca80bd152e04f9534bd2075b5a95789af8be1e70ea3dfadd91f5b1527e399f3fd798691454fc3a85a6190391d041dc7c1d6a08d1c569854dd447596d753fe904162237ecffc7d9db997d8829da6c56ab8054f198c921c5744c586a0d4fd45a53f46c5ccba1262fcadaed8c07d22183b9809a205005f54f285f281c251e500c08169e8cea853546243994e9168745905465f939466073a3eb27f78f2cd7ba2dd5a1f8817c094991d7fa419aee7dd1a386fe09ede6824d0befe0dda93350c44eaba78d904bd7ef4d200bc393c4cf470073f47f15cf2a7a05c38d4238e8535131a25e1bd9ee5b4941113943c1b28c45d38dd3e7d04103d9c01584479deb58475b5b879cf69e3bc305c97c8c4584b83b6bc517fbc1be0d6d7f68b9edb3f0c9bca0237146d49b90caa8205d09a09e4891e2a66a5186781750c3b5e001fc751103c57485cc6788b51459d06a454b8e15a447701ea19c7604da250fc4175a321ad3c74cacd7bfc22ab1410106edc73ccba0fec2b626bd4f76a375c86beb81a4df4d2bc35c5b24481c1e8249b7723912985602b9a7c26d927dc1f5233e3ef52712126dcbdcd088d0c5e24e70c26c9fb36aca0dac8a3cb2359701a9888b143b587d70671ed17f643cfc60c763f48171d6b4074afbf2c97cd74ad8e2f7729dd1091c76133b00aaae3b95fc9054ad89d7f7c11e6683bba9fac4869970a90717f7f1d59d0eaf487b1a91758c6d128ab93b69a1f202d57251a40482e7dfc00f3670b5004f5f152d2ba0844595b8fe289c9c156371c0ac1e53b24bdbdd3aea767d57faf5e4d9d9e3eeebd9ddeb659fecf397cdf63fa6f051da07edb9af96ee6042b9e3f49fee26fe9089f226ca872a85df374a4f96ab077dbb862b587d3830cb84913483ce1b275c0eab718141cf516ed5a5d8af9d19f30ed3b8ebd2d236a292b0f7bfa50cd02816089a4210bbeaa58e9216d56feda74b63d9c11f1c3bf1b42f34fcbd774e393615170c0c0d72fcfc2e99302f706287e9d769ddc78fdfa5e7e8d8c242274bc64094352d1082ff7d2d428f4ade5e39f870f5e6a2a3bf1f88722f8ce6bd867707a0b6a1ba6f653f6ed0a324f2aaf1d45e8e0ea76773a4db6624fdf310d7cf0a4c8b1757e0133e390d87fcf0a034db6a1aa943ae0ef4c16d201fabdc5991c8c0451ab1745a605088f48369892c6e892e092ffc38f4d7c00a5e53456e5bf2ce5697efd6557fd2689b7c622703db4c17f724fecdf504c603ed83a125687216c00c91cf7b975ee24d2124f87a8a7a4401ddf8a114b2358dbdfdca32e9bdc56bbfd9c836116a4ee567b83eb3a91e88dd224e11180ed4a3b95e3912a13112c2c2c979ae8f3299ec0cfeff74a6c0ff82972624f22832aab47ad6e12c69d0cf019e788cdaa659f4f71560f10eb8739ad99d0271496841d8625d548f14195e23d6571a11eff5233a4d0ecc2f2840a7c493e11f73e6d974dcf0c1c170eb62c85f6b529e1f3321ab53cc29891c194e7ab7140b8a5eabe40ef9195e72819490fe0834013f14b59f87ca29d5040a21bddb2b36797538335255a635f2bd70c75357300ba137b1d358f06de8b4546dcb1a6d13f758ca802872a02c9ac4106f492ffd5056e96810c48335350948ea4ff7ccd724810038b992d2674e62c779526f2b8e9924dc8fffa7501bb0113cfea5f626f62d79cef4826464ac75ee310130cd32ca0e6c76f06940d7fcf9073ffd9d3b4e9405abdb8bcc8539d05434aa16c7401b1dde881e17b9a4a6b9490d05984a480444289397ca95fe65762a4ca71711065477d4b38ae885df7090a234d87c838cdedafd1eefe38c8ad13fd7b5471d0b47dbc2513fcd55d0a6d19de69f0421282e46d91830423d843258602221a7bc990dc21c0afc7e9c7d5b156714399d583e843611bed90cd9388fa1592e4b06e503d437b185b9eb91ba07b0da972887999191cc515625357b969f5ef6c11451d8c9f0191c63604a74408c8635b9b6fa6a095332ec9c307b3aee8d84002819fbcffbd8ec0f3a3b1a585c7abaf8329132bc43c031a1dce6b5c40d619a7031ae9ba9584b180e3d43e9aa9daa9259fb1537f7500a1c50eb45647d4227e41093298248b4d7937b7a8e6c8ea26402ade1dc8322e5c83a42b1e6e18e70f42ec2cab31a608849b9487075cd1ff908ff66e6b5b4a29534a29a5068406d2062bd404294ed4156a0207ead37810074a6afc21a12035763fba5ac054bf1c542a55fd61aafc99c3672e9e34feacfbe24fd8d500bfabfce2cfae144fa620a8fc1ae07bad213e6daf69c9948328b502b4de10232b923273c47abbc315f84a801df4b1385db9c301d67e1f8bc3fb4209b4476a2b0dda4ef5d30bfefd3735dd51a9bc20d0d845610b7733775d36026d5bf6068fe6dbf0fcf907cc20853226baf9d836f8a3bd6ea13f4606627c805251a4c48de7b96abf0d8ffd7bd783300a5a53430593dacf428e18806a5ad5b11ac3233e64e678dae1281befa86f814c9ff72a1b315f92c14caf170f514665b2d7e643bf8e998ca05ff692e2ea171ea03136c5dee887bd3ae6369bd3450e54fbb397abbd8ef54008842655b551fdef02fac2088daff6fabbe88b302a82d4fe48859a686884794ef471d48a13bd49d515b428cbb205e2673ff59001fdb22ccb3a3ee24de1b26162a06ea15fc60594b6d71fbbcd03f225de67324df1a4f6cb6c5632b18a08ff20bc7258908463648101fd4c3afbf0ebd77e198f3d66f6161e3278d2ded6cf3b6d7d08618d4ce4b6b3213fd352fe7e53a9159b5fa23f968403fa799f6782416c740bed7538c4fa0356e7ca2799af3b0424469084a552a97872f69740d73d473d909b18f0f5df649a8248ed973141eff36a4a330b29b1d8d73197e4591f1f2515090f333333474752fba1bbf7b4d0afcd28519b67d01c1304fa491e67b9cde83be3894531b71975f18a45f5673c643ed4ee18ac7ececa62108d0c502881606728e86156ffc498f4780a3ca0419deae9e9496dc73ccda4dba75b88a104fdba87c787bb87081f9f2449f6467ff7b40f13e8c72c1e47e24978078b9e1aa309fdb2ca5bdc81168488f8423e47fed2f432b30cdcedc378b2d15e0bfd2b4828771f83c7746b362304fd32ce90d4fecdab79c18bf1a29fc946a33af3528842bd854b54a61c62abdaaf434665b222e8eeeeee2e6594534e39a5ec5ac8628040bf8c157fd0e42fcd1763158b46f5772efad11817fdba483e6c1a3f4a63b5bfd445aeea22aa04fa511811733a5beca0a0fad16eb5b6fbdaf5d17efd54193c4776d187b3827ef1058bd91663b188a5261aea2d53b7d0ef271b51d02aa323d08fb6dac5ccbb0b574ad57fe1c2850b77f9b41dbb584a0fe87ed659900d3904d918840fa5b417859f6347689cb3343ca01faf6a671faf3af5f5aa573eb5bf89f0918f573180687fabea97092d4952f79b6709acdabfc325b48455ed578014b1ad4e1eeab7d56f838210017f693c9aa70a68c1ff5b40bd5b274138529bc74fab5342555af547d70ac025b5f038e2090c5c79fcf0f881d2a97e3da95b1b9084a853fbc4aaa76ee5f103c53b1e3f50eacb552043e774e4a9fd3a58b86fe02daa14acba42523ca95d5d212978eafb7ba5271b48183c2cf2b4c34ef5d130ff8d5de02a85b6345ffb50f195a9a84d398a0a2380b07360f77599a6a25b778875148c13b40f4b880945425578a828aa3fbc328e10139650b9a38b732363b5698b166baf990a5369afbb8fe4deb12059d5151f1eabfc2bdc0c6b39ed9801d603604261651569716b396d6605d52187f67a4256b53c3fffb04d36c52b6679e69567e67fc088190ae3e867af5545d4b567e11f56cd918a3609a5bbe7ba72da2a7782758bf15f2209d01084f6f0d19ecc7e3ca7c39d0d3dd4a51035f9e7c0a792d396538e18b6f6805a4e353735b1e5f45e1534fbbee5444f5d159ab50775e04629635a16413d40b480851e9e26c9373314c700f30b1da752ef4909522a7d5132d1f6bc06331de8b6b79b3bd315b44d45b4db01eddfcfc73ea9fccb1d034dfb34d8c1f660d0b653be4c9490a402a0ae10159eaaf906659ceeeefe0169edd5f0f3b15848c838e0bb26c5b52938f4bb0e1d3a40267b0ca6f061717777a2042cbeb0a9c31a4570125eeabc356040f7d979b8f5f1139597872a0efcc4880ae7013200a21acc08a1fbe2b4e464c5c98a931533436686cc0c392d991932336466c8cc90992133436ecc0ca133436686cc0ce92428733b8cb061f66d3b22c10d723f1b4b34264e0984f0bf08a10c84bd10b6172becf666162f96bc904136777ba13b12f1dd612cd1d28bbb9bb818bce8e9fe820997dcb923361bad1cc218e5fc9973ce39e74c325b30a39c997b0bb29111941767495a8bccd3947c94342d6e72ba60dbe27331c6281d4ea6a166194b295bb022bf8eb815e75ac0390bb5410e03ac8d06a36bdd0e275a3b8ea0271e33c06ec78b18b0d016172dc7015800e4f2a26ddbe94f26d38817a704d3c2324fe3a2c425a0865229beb8c07038e8c0cf5c6899a37c482f9c8e9760005261882e5c7038e8907e3e0acc4cca46bf52d251c682c82c2b2898023b8c3eeb76188d3efb11933efbacdb217b5297e570769a3c8e82117ecc94d127cab0204481940a218410420863f4e9d43777a212c8e336f3c55dc1aaf1556002212c45c89179e23ef7b096f1f39c3c0a621672420b0820216c424e78c294bc62229df22435f6f0d1369ea3e2c7d9718fe74cea4d8d7c2a558db712236954641e940be8b7b0ba5a5521b2f2866d91e4eebbf95f2039b2fbbc5a74c5e2641b6fedc58cca5349a6877e266f5681c994325312d90728cbba793ac5489887c7477bf149a76d4f87c60df6ca03c9994fdda6df9fc7f62b5bb77d777467d8a6813bf968542c6d5b0f168a40791607d6f86c02b95a1cad46988c391c15238da320743bcd00e315e3100a902451c240ae18b3d903283ea1c61efa67709b1c918791fc80cadfda833ea2142a232b264a1644434686927c4046ab56bff8db24b30e3a116d693e173fadd60f27f133c5c54776b8d545ba2b9fb8ca31be8291c04f88626f14316c72943d7bd5457ed885d9fcd3737677d74f2c8993e09f2ed22b153cb1389c0079cce1ca8bb6d93f4a10b994601b9e42c46dac04a37e1ce53f3f4727e9d9f6240cb2e00760517e88ac16a77bb5518e20aaf3c4d53ef58e0f7bc31f7e80551bc62e740816476b400824b870331428cd2e7477302fcd1b02fde20e10bb8a6875d077c353d9f4038daaf62ec09595fd50e61fa2267a66c2ddfcd35de4796714d8c55362d72fc6e1bde2296cd345fac5adf6691314611b968251de2f7681b9f3ee05eb805b3c855d2c45f710b10b5d449fa07988aab34f9b6aa8b71304e3b8df7e8795df9e3bed40048f95df7e07fadc5328e856dae940040ffa2bbf8efa1220806a838f58e553a0d40db1c30c4fbb183e8fc51cfa2b14d6c351eedc6f6f8591bd718ae997bf3dcb6b311b0c02b24e9504d5d726ee2cca27cfd9b399f908c8c3e2581fd8826eb3c5a008f40361ad56dc813147451a5ad00fb24e35f1f7bbb58991048cf2872c762176ec621c91046cd32ae85ca338522d0f12ff98a453fba4055bf1a753db648958f514e47c9149750ea8099007ea17a354ff519408e04de3ed5e91444e50b537a6d81bfead02b6e91a308a875d58f1b0386ae04ec54bad5068cb73425944a9bdadb39c623229f468931e236dda12344302e57e2371326cceece9ff53760e83a169d080c29a44a553f23dc6186565e35f2052ca51dd4e496e5b696d651bb5701d8cb90cf4577e3bc574c783762ca718aee395a3fcb72ee318d0fd5b10746609fac59d2b903822c51026980115b11cff1616d02fee4c98a2ea0fd41e93f63ceeb038a140b33dd6a9c8d35e77f1487b4271e5282134eef84ec3fc9b012ee507da27d9ef2e97d2b086cd6e8f79915781ac956e968d85858bb15bbe703a7860b676d95892a05fdcf9b8b3f259dcf104700dfcac83b7a8f2e7ebd83abbd87d3c79886db575fc03c42409fd1af6936594966225181898394dd4fd575c7030707576bdda1b5dbf96e11452a8d3b4ad3a65849da572c15775872c93c95b79eeba8e7b2a7392179cce660465985701a4c56c0cfb8a7c18f3c4352626663482397bb672ba711450cf2e9078ea267bc35f9ebab537fc6370307095bb9e6182fa6f140ae57e2332c304855ab731a7b32308d71541d410540ff4832cd8aace5a9c9644160b0eb284b8034f2b573127a0fc6229ed793c5018338c61fc72ce39b713d7cddc276ece395b1e832ab8aa35b6e560e851d598999909cab0c589626d620816e571071677fc351a9ba90885d9591c0284606d1ae6a89dc55953117405d56126a8fede10e807599d5af947238b13739bed1d16557fd8729be601822cb771138cbe5ca6200a047fb28c527fcf087187e280729d0e44f0e07efb4e8714369002233caa1caef31cc5792a3ae3847ed163f548a7686441f9487bfe9fc7aaf3b41327963bff66625336d8147ce7b66b1d78b07d45f27877dfc83483d3c1d968341a693468ccb9ed7147831b7d8e962d3c7e90b4b735ee74cab5a8a30e1aa12f759b28515473f476da798a2dba379877dcc5a86f20e20a25452e1a10315a2d8535353554ca1af8bf6eddfa71178380affe5ffdbdcf9fe6dff3241138304509d5ff3b03dae26c7b91d3d10fbd9b49a3ac6a71837b636794559b9b8cb06aa32df3aa91b611247130f46bdba679154f5bad376776667698c321cc6090f6f537a94d6a3f437767ee06aa5946a9c95473e3bb40b50b506be85eef8e3b5d3fae1910259c6c139e92f7a626001e0ac812dba442af4022c3226d71b65dd69ab40b4731eb960da1cf6e2967dccde06e6a73e84f6b37a977b7dd34d2881bf50085f20f0b7585ac084251500d31fe4f5d3733434323a39b399dba6e868646868c193368946864c498799a938c6ec60c0d1a4f06aa86ac116bd480356ad4f0e61a356ad0749b8c193c63c68c0c9a193268783266cca041c3f350a81a3500408386e7a150356a000000366cdcb8515383b251c3c60a33b6c0d13858e7469be8e6834f2c45a0dce108800006c09365c616f4dbea6e775a6185154a2bacf0b2824b0b6559e15660147f573f1c2a770b28c22c3a68208c4900fcf8b0abfca3b35ee65f1d8054f8637db979797777797bb9096d6978593008c469d4e51640aa0e0408cbb5cc41f8a3a8ee10eba7f6d3ba43ac9eda8115730bd84e2f7f9c863800ab3b04844fed37d51d0262a76abe3990dd16537b0c0357d8de165b6ca14585694bf3693b840cb73b84314a39797797b30c05231249d3b68d721cefee32333333cb364304ba6ba29477b7e4dab6b8b8703a2c49a0dbbdbc30f3be944accbba50cc60c142acc807e5f1f88a651df25efbebd9921d0d75e9c15434576726024074aa648d162033e8b031f3050377630f0bb5453c5a28956eb89234fb89e2092056188c891a12a2d2028988c860cfd70e489941756423ca7879943440554402a95cac8aa871c26409165d9cb4e072ffb6872547fd49976aa06ff258a0bd85a3caee99bfe03ece8176a43e76f2b75a7f85f1e1b52a2a2a9455092453104130b9d82b1ff866136f3d1546f6668e876bcd07d1b94104228b76d93f0470521847ee3363d6e76fcec684f3819628f133b3b3b719b1b0ba451cb51fef05bda7273cf7519d78d62ab8753cdb647f7b0a908ac47437bcc517ab8cddc591a3a357d3a029b9a464c097394119b9a4eac4fa76650cf1fb7c968fc19c5d1488e648c31caade31d194992441a914692a5cb27ed0575ca6bcf894d01603dff1b00701218ac60e76327d597546771117bc3b78e5923093392c6d9c62cb7e91c7fde619fda7504b3f79faf4934619d224999653de3a2bd83bb981250cd03a2df6c91be7fbebe49c49c650d5f3b494ea749249e93946ddb0aa733fa154e076e23e95d41bfa982d5a922d2a52aab4898fb943059549d7758a250fe245168771fa744f571fca46f1d52b71ca0464e2d1bb376717ac645bbb2a8d08c456216d7d3a9d1fb73499af3e9d454c2fd744a32e954a6699a16a3b427e164173e01708dbadfb1ffba0db31645331436fe6f466aaaba29c47a2f363585d85412aaaa53cc9a3b9d92305879aaaac3d98210ced66c2dce1328b416676d50fd4f46a0f0358f5d276cb6a66b4a99af4934b1c856fe3336ab6444aa7f84cc21a07b8310460e7e9f461576afb0d3b801fd260f87a45badeab3355b527234f9e408c91fc9f9a39306c483c463f4b2d38136377334961372c36de918788c3f473f3b1d4c2308903eeb7420653ca0fdf1e443038a35e4f433159bc150f1c1032f47d0adee900f3e9480404775877c50b9f0404975875656b81882caba43abd80a36a4480592a38f7e14b398c52c8b5954e1e56b26d3322595f9169a17faa202dc381d27458f32a6cc24c3351e7d5181c6d73229b7e55e007d94754308bb4db0b965842d235c39121942243cdbcd3a2abbf528258491635cba05316a79c1efd598a0c6ed304618638c1146eeae8c468a114a0dc038e79c114a23249c31c2491a65d188481a6549c0d99364ce39238449c09e241d0989495a919bb6c242a96c29024ab8694b29f5961728bd085f229d8c7a5c5e9a347a29415fe29d8f6cc421601b81b634de0e258cd2e3588eea9b216a58b1636924f9d16dd429437acd0509300eee64a2271b7cb4f74302ecc204281638357444b283d106e7c9d188c4fd2daca6470f580f79b2c18724c922285313c7624441e520de46cd4d910eb0824c4184779a601e8410e15765863195a10cf4a06aa4511638918782f0a46e78d6d5830c6a74294930e25d154d54c7404ff558d5785681819d2868edca5b85bf525408877800823584c0a1df42055b6c51a14ac84404fdb2f52caae840d112ca228b519190511010241ea84508361da2222d52b0e910413564484811c907f25f561003a2ca154950af2b54050684a822033e5441440374a5ae50152060809098a3b64a99021b434290d4f825212b9aa8b0ee90101e3fe249164f78b63f73709e34fe09bbcfbb1afcbb6e9d1f7cd94106c4ae067fca9ec9642a519d8c0844602145284a952150a915c8ea0d2c503c8148090e4451451b6d8c0cfea37780ff68877eefb6d57599a3a0c951f0d751922787dbec301a7539dea30f134cac179be0fd191ed01313778b9ac5e280bf36daf36a58680fce1df842c31bd2fa937c9465dde6c44e3557b3a753df644d9fb9337926929964fecc27b33599cca01965b254d3480260e5f1d3ea9f2ab7711b7fe8362a47c5262a6c62bd6fb22adcc95a0ffeeeee439811eab74d1c204710ba63b4a3cfde01a4d7ba1d48d101592dacc55928db633210f31988c5e16ae4c43b36a0dfc27ac060310405052dd9dd65d7b28cb3cc336766661bbc3397b2bbbb2c087b98b5738407099320201f25307377c8ccec5b87c3a87eeac4f76f4e04d066a6d0aef26f16a7250d356b276abb0d8e624d9fafb16294a05a11582c2b4f1a3d64e916b5283fe1c0f563d68f285f9df22c8a4b0a8b592d2e4bc060e6c5bdb51c6e2db7913d8eea973ddae439e184bcccfda27ad97951bdac5e88748a5f8cbc2479f979f1a9fd2f3c2f485e98d47e3921f4d82bccbc0265cfb62d6154ff7ff419f56d4e6a3fcfb73551fb373f6d48ec8dfe1815a2f6fae5e2d22208c7c9558c314e4163fdb61f96db6cad4d7befa7b68fc9a3bf9d5c5e2fac172416c76bff8cca5d5eaef65c622e456eb3f2106eff723110d07e7b1e1c3fd731e7689dcbcb25c6ffa27a59b98d0bcce5e552c5a58809f465f512c4850afab9bc629dfab6567db90d7581b94d0c0ca19717941715cd0b41bfdf7e16a767a6a05cbfeda7f68baabd9755f712a43def3e17d78bea45556b5c5a2e515c5c52ea2781aad4feedd5441b6ca3b2c55a9bcb6db427914a32df9e04721b9aecaba99f0745aa64909554d517d58b6ae6f5a2c788d8942a4208a2aae2eeebcbd9ba5a31781683db984c93e7cc66c63964cfcaa153cb417845a479a7f948ed9e5967a700ec0d0138a9fd9f8753fb67aaa0b07e3592a8464e277b679408e83aac878f4ecdcfc13d670a92456d0c3dfaedbbbdeb23313268cf3d0fed398d87f65ba783d6658eca6a16a76b3f89442291d89d3392f62412493b6d165bf1451461d195833b90cb94a521a4882841a03245a542020a2d67f7f5656687ac2a2269b037e827aedae036391cd540312d7a8c30425f761923e55c154d559023b3a727ab8dd49e496abf8c904340d7de19f6463f606f408051fdbd4858287eb477030c5c6d7055a782acc0456c71f606b5b5ef9374b1f7cc1414560ec618a59472ce39b32ccbb26c34ca36180cb220cb7ffce7f5ea55afd8a7ca192ae8486619a723eb3a08e3747015d0919d8e8e675b4f26399df87277ff18fd34aacc5b7b406802fda4eb93546a53696f0a17275f19902ed96aaf67a6a07ce23ac3e2349fba36474d4f3f49e5870eaeded9d02f87d0de239d6a4637b24856a1b10595b1202836fcc8325794025f32266328b46060b1015f7776defd5e277d5fbb9d9dbacd8c19b5770674e6fa517a1377636c8d76b8cd683b428770e35e61777767e760406b40bf9b1a638b6f5cb24200593b332fca0a8af02bd5ec456110cb526508a11654825a104786abb5641640adba4340403ba83bb4048c248df0b0b058c255774889201cd41d9a4151e557102f168f91b6570292b5c71e93edd37ebd8d4e919e5d8d5a79ef56ba18ad6b2aedb9b46d65723a2b5d96555ad23a19cd64aa0c60150f7592b64a09c30a493367f76fc33382cb8e055953c3258055aa0a6bcfbba9ac80612ff40d0c27d0af4018525d07c8416309dda00d0aaa0e397207218410c629e3438eecec7294bb8a6b96209ab0ea0e3551d5187587805eb5656df867513280d5159281aa7e10261483188cd57ef7d22ee9d403e9357792467a2949a4f75324ed109ff4fca4784476ccaa3ca01fffb08b7ff8879930506bc889ea27a849516b29f0801a09e2279d6ab70932632e172a954ac5c390132652886255da86f4fd113aac535348edf7550e279d82b0b494705579fa688dd2de11fa39cc8be04a83a9604ec5635d1739163b5ba833935e2267a8094fed8fd07596f3207ba355d445d9e4e6234390be8bdc8679b8a7e8874a1df6afba4d444054bfaf30b7e9a02cc86141b015acba7c04f4f323f4a342d02eeb52972a2b6e313640f983fcbb3da8363442d3ac542a2181c2ff361d3cec07614b7777773f08a37417c6b286b1c15011980e9aeed39622841d3301fb04a14a9b32c2d94124dad2e4684bc3b4531984409ac602b91d46199a22745f6319692d25e8cda5126973612ec95882252f95bab425e6563e202b2ceb748616b4443338438b12ccc2c0c0c0b860172e5cb898a105dd2a848171181898868181e16da57361c186f772532a31c330bbbc04bd7043f3a52d43c1c4e964fc82c60a1a1333e2b8c4e9304c43938e8e59b3bd4161381d5cb3bd616a183060c080c1304627146a4a6b8a81199581dddd2d633784f206afdeddc0255ada5e369a2294d9c5763452baa180e504f4839496a8c321342098436bfaa460fa6ced906ecccc5c629a2294b91be9c0f062389d1844f4e3d1dccc0c21f5ee8592a590ad0acd504626851454508165fb3f755250eebe8dc6091d0d8d0c192e43860c19289862708c172ac0881123d375de75ddc5089f0ba834ceb6253185684600102020001315000020100a074442d148288e64514f1f14000b74904078523a9408a324c781180521638c3106014080310464a486843a00040afdac54170534a324e7c89d94092059114f62642105869278d1e0b6f7cfcbc2a60dbc09f51c2e0a51668d5cdbdd6cd686d16ec10b97dee541dae91929160c9f1210ba93343d5002b5b9c63a1c88e7d6e54016d153585dd539f4ec6f729345d565384827f6aba6947622e03e96e8cc669e08f4e0337ae3ad5a9b47c3fb1ef024d3315ebfc68d9266162b8f328ed9e0085db81f4f23da9cccae34627d485b1bcec836cca6d6b52b14e3a731ce16c5e690ff2c58ca1bbde99afd3eeb2672e86c5db342e479c88e8a38b8640401ca3ecc055e44c575af83eddcae1147fe59901e0c8aee9c10e34b5f7bd90d8637fbc140d4c87bec85daafa7634fbcc1b1931d87d1a94bfd317fed474d2db2d1ebc72d5ac0d776b44c420e4bf744a8e374310ea73ddd83b7f03c4dd7679fec024bf89ada9deb0e84b9835332f24b243c4da99196ec1f63c08f6089fbf862cc8faa2a3804521684657c40b1a48ab1c9fbe6a1b107808bbcf43ca3dcade7796bbe80fd632f30919cfe4acb020516cc3ece3a10a5768e06f8e107e8074f39ccd8a54121bcc1811cfd793843249d0d9735a24c7806c320d343c701493e724d7bb6ef2148336140ac78f5d929a1b0dab8fe97d145b7ba8a271a871b299f48de5d7b4614ae087d43c48ab1d05b239c2218c9291288d2340df259a2b81b81f55de187f98a06a79f5ef034b283304acbde6160ed634b98919973248d70cf78d75519409e04cbef42158a39854f84ca8c01afd92e38dcfad415eb91a99fb702e8eb995a9303ee601042a531a6169ca7f80e96409014f477c25f38c4117166db0c624bbaafe07e8e77531396f7059cb00623848c71e24ab76af775e0cc49e31f518c3ada3297780c5bb67b1b48cd1e2aa332f6ee1003b60db61369a457f93a2bc4b21187cc473500c81d4f0b3547f157acbf047adc800993d6e6eb6e838d9d8485c27b51d5bc9aa093b46ea923134a981c67f79167b3d195a8620841c30051591973d75a498a3f72b555eb38f88f20f0060d51aaf7264ebbed4c151eb3a03f2ac51a2eec5be1766a1c28505da13d6612a05f5b9a21324ef3c38ccf9021f84c570c1abfcde0bdf63cc6e0fe2a406afb8102f27295c7a5a2480c659849697632162f5006d9f566bd35fcc3eed820044ec2691a4709b687c966e5121f25a37a92129fb96273877477fff51118aec4519f85ab01ee665c17790ec6320b32ad460f761496b91dbba07903cdfc08b4c313c4eb433d519270228e36e4565336c0ae74db81da7159b69265e5b378334a327872b97a9f31047455de1a34e4637db3dd61c5183002eac693d81882a63b577360a83e336298a02c680656df1aaf62c598e591c96ac98fe53546a92f4fa1a9ee9837b08add7280bc8ee6c02eb40c6673ca96e79dfc992142c04d45a09c5f041884c22460225aeca934b2616715926f95f374c0d86207aab0da1cab067e41ff2cfd941f2dc06934ed6a10d043e22af3f8a10c9ade322b810491a14950933d98af908e8a3bff87fd92e193cb223e0bed8d6fb22fbe0c42942a3a5e40228f6070369399e4c23a3d088621ec59f192f51f4284f4c9c9886f5c7e8a177bcb990a2ce86a36393aeb6acc81d67b953b6d4f63b705a38fa7c94d35f67e6fabcdecd64e0663cb064f395abe8c7c53f692f0ae26f151a7b5a9bea64b07a1aef89d89165b2e619c8ef4dc0fba25098be6a1309af3b5d6cc9f47c1a184e923a35a4d2c238f2ecedd5fac1bb97563076fdd6b8dd460e14a6f3475b4b366f926afbfd6e6e66cbcd434552529993e441aababe8dbc125dde62abb474cf09bddeee732356e1d5df883f3310e86b04c8d800b35ce86d7bf732b7035dd10d0c95bc6fae1dd53f240ac40b48a9a1a11a091280414e33765fb7699498352543e6fbc1eeebd9066af74c39088b175c96b337a1ddb87c4ae92acdc62365e493ea92b44b05a569a3687b9f064462518e48fcb91fd38f8c0d97d44787a2f1a7626e2583d0883d0f2c502770859660c4fa1eaf62d1dede1edab2f51b4a0dbe356d13d5a903d354b0d808b2abf09c3b6b86e5e308ba37cf45986323c864c994562c7391ae87b0227b75538bf7139aa7e7fa0a1eafe3ae5bea51a42f48708f304ed1b25d789bde75620285fede2e2fa510497633253104bd85465080ad82084176ef2edc0a78d551ce85fd9795350f25279c3fd6846872cfb403c1f2137ee9b12e50b3ed691605a51b1e195437f98594726de5123cf8a20c4e788a694d0de22a78c5ec72a50f8fa81c383163c8b40a0f1a484e2be22e2c754924901e28ec07d8b69d90ecf0bcad41d6f3efb106299eb361e3af21a03b259397b6706d9373b869cd282c2a756f20d138ec6c4c9f59608a770a0c9f300194c707e41265419f7b8787f741b54de3cd60faeadcc29b3239330f04a357129792e746240e47d3f50b50bc810f3b63ed358b83e8a872191706ddd75f205b32c6283dc4a8a1cb987ce1a6a2053565085121cfa287b7096af437e3c802648162b274e82728d6216bc27bce48766344b73f77540362d586962b60235a51f39f17f612e5f814a202a0ac22992ba6c15b5b49f07f68463994e87306132980343d91922a2c3670b4964eb9223804bf8f4b21ac507fd3965e334232ea31b8a7200bbccc7942ce55177c3b6c744adfaead494a78571c7cb17b5278465dfbbc1edcdf2590ae56c6235850d58781125920b0035c733dfa83ea47571723473680547bc66d2cb7d6303a7f4453c439a3bae1c03f0413ac6eb252b5871f05bfd15173f57ae67c720d3fb47bde4dc687fbc07a64690c7c6e66f715496316e42cf1d0a0aa63aabedc5a6b95898d1bae844439c63304ce50a9ba171870d8a2f325cb1591860aa846083d80e238e0cd38d4f74b6e0d04bb22a7b798b9be4a4a69811fbfa99f984c3fa046a47afdd62c9714226d6c3180c8166e2192b51cc0026c0579ad2f871d656770453b87ca02683027bbccb38e306cc040410b096d36bfb2717703e1983bd42d668788f20f6172bee11a4b30ca4ea6cb63820e417e1290af6fe1eff5de8bf78fe26bc65989b5673f5b18d067235cec5d1ae479357603b360261912ce11ee6b0edc15a51d546d982df22ded11990e0f6f27e9a377dda413d55417b97d9d76a31a0ace1ee9cda8cfed7d3cc5bd530eb7c40d14d84e0fe2b03700e04a46a05ae02c445856a9c7e78036631588c926da0633e180c7d80e142ab9a1dc952e42d9068697df384e0da365a933ea35872cf2fe726a8801a4e8a2186caf9a0f83fb78e0ac75aab439ca72bad0e041a0192d543640f01efc7f5ff110d2d7dc61bf4c3b2d4ab71f1783e36dcfde380bf50f0f6caeb2f942d1b4069a396097e32d4301f955eb7d83e78fe26c8782a73a8186ece21f4a25e035ef5f8097dc151d82a7dd18508a2b7493840d8367a2b77f63ba27ffa0a021221957b92249f0813c2f5cddf42b7cc5b2b660a734b829d9a2b47388589a3464cd58a9f1df6c628f4bc034c875e6017aedc514f730d2d504ec974a7dc7de278802c625ffb38c9f6591896ab42f50e3a55d0663b714a4d8a8707e07b8c7e2964ee3eb81ff4fa555bc37ff2cd9fdf461714e032fc84021c49f0c1829442f07683b53888c56c27596e8c500ab767d33e19082242a73e0adc741129c0bfc79556c7c88f85b6ca9384ff73f1174ca9503ab33ad963d132641454240cf54d0c01d01bada072269711059f701a1cf1ace92160992bf112b1612c7b9752417b1e3c3e9dfb3a4fe580d0470632097bde3f5bb663938817f55a475668fc817af40d59c2ccb702d306ac9f97c87f4925878185e519d4ececc2f5a1b53e0dd973c0bf5b2ac555423f72657d656a82801fd05db00b3274f038b83a5d578b98247609e243ef7146148475722197b5f9e5ff666239ab6b899be0aafa82eba59eba7efc2cd8c7f15662b073adeb9102b8b87bc8b31ea60c8983dad9e5237c0998ac97b5078a472cb8cf93dae98449ba686f58e68db72eaabbd599045d53d76a6e1b73a12aace26448cf459914d2614b3395dae6a31ff0be80300adb7814be3c5beb2d0a452f67cab49eac3bb516ec7beacc869d9675a61070650237aa6b202bc475e59848b95bf84665ba68c36aa52c600a5b025234cc91316e80b7d91682db288558ebb282bb8c4ff3e9c1f39e163e3c1228717b0fa486344443fb32c511b91a028a1cf366c340a152ee63455503583e52e13684d7886a2917ccf2438b83bbd2683af19c541fb8338c56ffcb44bd29a0908f7e2c05bf4da5cdea4a647cc338278a3aad7e695edb1d195d8d24d220bc8507f7c86f27b921ba71951900833a369317cf2ba9dee474d07268bbc5580930f9d285bf30089c05289c8c5e8d089a0f32692ddcbcad447c194d5993ef23da8d19f463930eb98da9610ab940dcd642b4173a934108a3286d4c9b2c0017438a75d912cd9ace38f86914ad55cae34edc2d5867d6bfb74bbcba5919638c6eb719507099c220b47cf8177b62172e7e64c5c0405fefb897d051f206102e41c487f43d98b251e7ab122611561f5d00264dab8f8b67755e6edcdaabe6c2c6f62abdc9017cc7223dc68378074a2c764c89b07d817cb9ec15191af536e46cf95f1b934fbc11ac9d308ae1a949e5f6b74ad598b27c48c253dabd43421d3702869702aa2f0afcb9295ce8cd47a9ef5cc2dbd2b4204558336e6962bc80658871c559116083738adc2184c1968e6b7b5eb228273a239ee22cc905f27fa1132557293c8c993935107f5cdd189f4979b9a8e550b0fb58549f72d84a94b630381a62ab926003bffbff46fdeff9e9808fe2433cd50b0f7ba541af943b906adcce9691831c7223d61d861b4180183ba1183d157e4af15bb209ea37b38d8d6ea8b240ef12810bd1bdaf36b75fa9d9f69216c6916f8ecd941acaf40ff7a95a02340740f21b4f4170870d84d27f5b7438465b42926751b6c924af442223d929a46ad757c22d447101a7cd6879411ce9972c5bc5a23444c426df080011b8e1b230ba119b91be1331872cb9084be0a32d948c217d47767849f3419d051b9b5d64a4c2bdadde775275afef044faa6ff3369347e37967c3f14b5d8b8c1706873aecfb2a073926a72dea25566bff213d03a2046e8e2b234d9943d2990206210b0d0bc141be07c52f53c933cf76ced65cc94fda0e7676f220948b90855094a3694f90a969d6c0cc9929c8e7d316d7f0cf0f14a433d7b150c85286d4667554eda151f76909889dbfd10a1407a9b635724160d864284ba2424ab2d47f6a05639dedf50b0a59654b7fbb02bfddce02aac5b8c26c39f944412fc69cd67468c33d0d05f577e07075b9c26abde9850e4e81f68dc835b734e120005f50b4ccae28945c3b640b81d27fd327532050122163c60243feb5c62ab822a3dbdb5e4aef2b2fa00cbc99b5d044fb5cc93dabf50a6df9c9429ef0f71ea04479c3975762354512c634ce314e16cd96883304bfa19f94fe387844b4fec6a5511cf889fb60937c476a15b6f7ba0e5d54a91bae05121f678f0e46dd3113392de8a66cf13f5fc91d1e150c52be389f8c6892f1cb546f0e72ccab6490be1a9c2dfa1fd18422dd7ffd75ff8e057716e71fe9b6ab2ddd3232cbe49bed402c0e58c23f95c0fe783c9a5310815f4a84e23f4b4a45acfddadbcd1f735a9c83e1f1cf059ac81c7c76603270871f9141eee5902a6bc26b3e7e7fa4278e1968fd1f434b70bd6fd0919c95e498d9006d8404f02dfe4f2cc92a993afe2b2c0249b6b07b89a5dbe54be2ee399ecc8c55540124dd60d1daa182c8e5338ad3fb58a7219899f93511d4865a6204d9c068669f91ad1513fb3145a499e52d609073b627486bf5bf67897b4b16c58499fcc98c21da317e93e1f048d9fb830e8a5956fc9abcbf6f74cd305a70b2dfaf42c0a34b7da2b288e26bf6e3268872ae470cae9d9be1b83d2d74cfcccefedc4c2311c17cbbf501e6b8b7b4cc8e262f6d8a915f88b056614d00675e3529c3ad008a1ac9a6f865a57bf8d49f99a0d064429122328daf280b743a3997bfd9c8b168ce7ec1e6b91199309d2850269062d5f32a328b52a7cd3960de3be88086eddb975fd1b8cf7a6c7d02120c2b3257e22e90b8b4c73789e2a7ccdc00a09bf0a5d044a05492f6eafa8aa3cc147b44ea87f84ad3f607187c056c8818745b3074ee4f09c47a22783910d57effec7e5528ad54326bcb8ed322602c33cc9a3099bcaab6e9d363cef81765a767e9834888c9a0479974b145664802da68a667df84d324c8236b3edee161b7c8b44a87eef2370eef8f0276320bee18027dc1ec6a28a49111f85473074bbc635448bb505a463429d08e93c31bd461933afc54a5218da048a0bde0e862837f914c5768a661c5759ee27361b78c8a83e450e0cce66e72d210ead649ab5d22d3b0b41585a41f9568bf3a57118094bf827c02c4ad1ba594b02f09a757d81f326e738f0d765deb10ba676890e16cdf12ccc4460ecbd31993b9a95e8809436492171c873df7a01cb49b30be301a6dd38388df2f17ee42d17b111edbe73d590c7ffacac4660ed341a60024d55b072c6058f98564ab279550faf862f8e594abe42f7649c0fc0515f76d00842ab9171ab9635ed3c76bcd34b01ad0b60064ed9879897b0fcfc86bc34214de0201badfb30283c2d06bc792605fca7478d881e11f33b7de9f4193ad656ddddf22f442df1d56ffbbc52537cf3e1141b9b2ac0a8ce8886cfc080bc0baefc82be6fc077650090b9c0dc4e755dd89891fd65413e75c655f5116be35cef216fab32ba6a18b2055c42db431b30c28715df4e165f4b40d06d43575871f8918fa7e345815fd58f50cf4d820df6bdfbb56bf9dcc785dae20f0051f11aa89d7e31a97e52f14ae5d2fa280303b053fd6b346e5b77172ff2870ce4ff20a36456649e1a7d3f417fcfe744cd2b6b0c3066f8d9b85988bd98fcd3413bcfcb94ffb090a831c564ee300b13673a51cc9c3dc585219ba42ccb46df0bfbebcf90062648224338462c13100c96afeb8b5372f04c9e3007f0be09960eaaac9c814b8ad6ad27092649a529691f94b72acf33f96e92373fe7478635356014c3ed81d0a4ca3083d1e0831ec2e2884478e09b9c508458ceb72bfbae645e5a8253c5233a67ce3abe34de9caf2021ad25ad63099788435e2c275900813a777e5f90198a848d66ab834ccc574d52939faa181b29893731e3de7763c1069ae700a0510cff70e21236301522549feea4552adeb6fd3e7ff9140530b5b33079efdef16e6149b238008988afee4e827474726ba12418d768bdc86d5c819a0cf345d07bf637bb29944e913a721d0ed072c18622a7d84e392705b0d9773e0a74b940e39c402c1720ecbc4780a8de27e6b4cafb21c23c007632a1ed892689ee138c2b7812fdb537e3d7b2a2eac3cc240ac8fa2a52b01c1008d6fca0f385cc4a96c3cb73736eb7e7f29e764aa4eb6f73a996e03f92e968c5c04f574a84c1ea552eda5c4b17c2c10a42a53e4cb0df46cf57b9ba0af98e2c7ac0a3c568737bcb30bb2e5b1db0a9dbe29259de841586019c4b475172eeba792ea7122529aa6b3770050c15ffbe7dd74d06b8443e72be3b0ca6c49c335b46ddf49cb1b173513085e56c9a9d8f2db5b125053795b1b0d4fe298e543e6aa54f58a49e5ced4ac3236be4bbce1692c932496c3bb4b7060a64c5d825a7a41a7f5ffe28a0a5c3b95d30373f7dc48a9629068bd3ad89f424e79a665c0983ba6582057cb9035239e1a8e31748d0eb7d0afa9486424d7390ce773196e83a772ab75c6bbedcf3129b5a85f6319aa5942885467b7db36770044925b2aded5a3f3ec6086680e201f7f97509fb606b7f3b8d0b44b6f448095731373d9db6255ca9f26cb444311f9678acd641d89c85e05095bccaf7dff19b0613303cf6f7394700f995f46ac416ea3a1a5543bba8a41d7339789250a279764fd9135c87fc7eb5a3c14206d0641ba6b0fbb506298751f2f909552cb2f8b51e91d4d664e65d017eba69d5c786758db2c0410b596822637507b3c40e7dc75cf7aeb670e94fc5a002a70a49f61768d11465fa13932c7f02e4c44e15ab24dc1b2bb9cddb0ccb32e5dcddb44defdca44c13f47ee362a05f75a820b77afce4dd13a0c9c75cf2e2c7edba935c4ed2ffd8a194927fd5f5f7557786077a7c49096c0130ab36c2532969c8b6a79e11e3f01c5f62742aeb431af8f1e2c1c1f17ab22ef2a5bf615d8b6553d23dccb5297c0cb3a58559000f220ed2442104e2c0e94f2b71a4504ef8505bd02f84589ced263d945ff13778aaad4d07c1d7efaaf7ac3b2d364fc4d4451e31bb1647c8bcf99718c32696b25ac55eacff52f4eca46ee6361185e479eea64c375367945cb2a8a630c64bff3f8e249cd3e0af3f8b4c2db4a26c3e381936fcd35d7ee7e63ee69e367084f93d1c6cc770963e81b2311923788d9f02911f754dd501831667d97d9782578d8b0e77e6142c60cf8ca5a17ba209425e0ee2741d569b10b72a3bc3a86f94de3490e74c5b701449b2e7f565ddc73baabf3b156a9bf855da03b9aec964cdcaedd056cd488f011bb77cf810932218a3027297e73498ec8a8bad769f9515aafffec009680b6202a2c410bd7f88594abc09d34831aaebd8d40c3f428335f8e14479d5aebee570d77aa3f4ead68bcb6948d446c22dc63161a84c0bdcd29370d2f40e4bbd5b17e1a9193262aaf1d4e1de2058c7c15a11f42da2b11c71161adb1d35f12c006c433c7039495531d2c02c8938a19c8fe147b4def99b5702353de61b5378fd0cbdc86d544cf38250f760713b2a22610020b294ef1cbe4daad9067318f36215d48ee9bd7ee59a5cfd7855c7d3ffddb51ebb0204bebf8e60e0be6ae80fa4d5ca7f3d70e397132e0ef848ebfbf9e1ffade25ff8109a291600c37ff2c44d7572c7fda71c76586fe502304c53cd9d6d931d6a2271326c55b1b31a44976d8dac42c4c1266f0bed1ac4b3259189fdec3d30a739300a1651d6d3d470a121d5347cfd88e8507e26e82307e333b384f12dace0017854bab2927896e573f9727af0cf816e928127f986ac9b98d84b051259ef212003998f15e76a5c205de1352b4ee369ac69eefd228480b824a16b74d1850dc83fe662b6dd502b0d297c93cd9e97fc59f8a14d0f17359abd34cf5d3e0cd329dd4da25497e7bae126fad8912864bc384e8bddd3dc7f2bfabd68bd61539f59100343033ce6d72f863796240fb281435220423e56428905743fa53a58ccbdc6798a22118007a4a12b55d942f00c0f12f6e4b4ab0893d09a20a7a309541154c3a74785fe5e68b610cc72487ac0f2f4809080bb976c18046b8712384183419bbbff6f28fe5cad134f31c9065cc1371261a8e276a26f356122a93d263b0946006776da6e912455d02a5289fa5a242f2980c489b825b6bebc832cbeb2eb09620870e8df464ae5a68c99f590e8d3ace01f5950ffe1e9c8dba1edd32881b63b0129e557df3feb93f1a288ef2dcb8a7f0243a7edb99757a64edd3ba5695f4e49ca31f36178721722b2760654200bba3b0a31d6ca9c24e735eff21ae89d6dc32e7494ee4f1ec1e74d705266423d87c3ff0ea97cf90658648b042abc5d8bca686ed4589f455b7fa355781413f1ef641e28afe01db0bf32cfb8d7fa72f8525e29ea84192a75b7bd25652e9652eff0d9ab878460911da73a0b5821f763bbd73f08d5de78d0a3fecbdcb692310981b52a24ca51c67833e98fd771ccff9fc603d402b6c04bfeaeb3626e6fdd978f9860ed5a1e4ce06a5069eddc868102bfe472340f4d284e56fe56de1bf12c42ed0670c5e3432dd3b758f9897e70fed9d799eb016d4c0c353e7c1ac79bc923a60b71b948038cd11e824a48df9bae43a150d0a06a6e80573f0a2f08b3b8cd4bd16fdb052087c8709289c716a83a9e6b43bc9912b6da1b1784c689c4a3c7398bc4826b1cf3168ae7cc742b329bea3b55d6a7350ed4306cc8e0cd8b31d674552ec852f99eed00d559e8879e73f58ae6c9d4c2e25b54ed417ec279e2c3f745433354d62b346883158c4cb2f270b561a923ae97d588b2c2590dbd81ad77abbcec803bea9a7144da5132934734db713ac8ccd2e378da5ccfb1110d05233b46df2b5d3a1253b0e91a7e80d340172213365d91b8eb93dbdbdd723da82daca5bb402d68943823e7edd2e1d618ef1dbf3afe2c38b74166b6f4cee880f1d5bcf5100dfaa25331afa33a35cc68cba5e202bcfcee4a8e46510190a28783a6efb9807dabd8d6476e278385ef5af83ad4a13374da341c2c1e221d50c584e0a805b80c232137f37b510484d946047d87cd250c0147aaee9f0d050e1e00551ffdda55f59ea36128a5f22af4a739b936de6f85873e15e9804482ede298cf528359af930899e3be98a3433bec60997a329e3c6a49a8931765d657b37af856a62ae838da0fabc7b4164a9997cae3b2f00d89a205341fc0ab48eafa6619c9666feaf688c2738d68759f61e5f967ce563aa121beab8c2d2d99b3417ebbe202796e1e61569450a5e1b207ef2c8ed2c274c7e3e195d03e802118a9bb944c605350e57f13568719de9016caf9d4a42a0ddc826b6dec0e54918c5caad89b57e9482e38dd8c3d1cee3b2b5f494ffb45a48a7a7bbd773168929295a078337d2588d18e6874cf7fea3b5671f807ae20a441191ed69e571566721692eedf4d06a8ee69769c58856d394bbfd77d9456137a32e1765f5c26a69e2cdf1470ab193de8c9fded0e8aeef5cf9dba12d5f83628930eacec627230712e1ae7cc527b3c102ea608a86d8a1a7fa3f9b46ad9cb1bc6dee60993b32cdc59bbcfb453f94c1d56a19fe781fbefb138a7ab111c2e1a85e9433650f1cc53f58dc26cc6992cafdf69125dc48370f98f3927f04ab64f8109ed61cc5c22b288dfd4b0ea9e286191eaee0d8f0617a403dfd8c990ec1fe70e51b9b95f47034732c46661dd8a49a75c2e62beb1357f3f4f14d9b866a4764046ee9a6f2f8e9d094c12b6768bad500288b2f73ed49de11ec3d1b5a75b2ef8dcc5a9c8f796b3352ff13b9b881ec1dd8c58ba49dfd758c9e0308cefbf10e6ac7cd134e677bd1fb6f13ec7c0e582c7ba0ae4c199fe11849648d96b056aec7129bbcba0739aea501e5b40837daa2b829d86630e8af45f49ae8c85b43b9429d5ef12b4d89231be19b59176ec59fd0c48aa3c44e7a58c278aee344aba9fa6ceef47aada7ebcd40fbe743ac6b996adf9cf2d5199957adde8ecc129140223f06147b1942f6a6000ff944e3bf023c00ba7e546e714557ae2f2f2a9fac71349df63494aefc9a7fd771117f21c1cfc672b065efb0e1672e7d476f02492d4477643ee102c48c44ecee97652a68d451c2d2ad98624f5d455ad862615b88b624d1034016384c0f615bed8a7aea39fdd36da9717d716af82511a8871245ec64a13281834d364c5412331ef497d5eb2f54027262029518e82a2e10c00dd26461528f3c84f593846fc3fe54d777e3f4b0335b0cd7221ad20ffcc5535c934849f5ad2ebb5c746e42c02ac88ba202b5e6c915f23baa2b4aa04ea7b42cc803a53a5c5e6a8af8828d02a91bb2a7cdcc049c57495013a87f3ea0d29ba0f696dcb939294319f5841bd0caa9e9ae5432e7f91cf7785ca685010f046204e2d80c98f12b59100255c7b981b7b32af4167806276f647f3f013847622206a5b35a6c3916468a7d41571ea1bf6acfdbc859f3f358fb23ab1841c6f661647bf7a6741ed110e63347b8427f3fb0b28920c77c0cd97b25ce2073ead6c0cdbdc9b91804a742f357f385d0db3ceeee9bc032e6ab2c00d7b7eb3d16c804ca82830177e68602f621daabc419741a81a853ea5b297c5e4f010920653a713821c4259515423220ac5a16b6a044092feb23a793fd8b59f202203cc179586408629935a5877e2f24c0a12363a49685fc3e46fbc61194f0fb39dafc85fb0014737f8b6c2adc9e199acf1a1c6224b87ad7d855d73f46dda07d3985358a768f0398517b8096c705090ce7e51a140622baf3ba23514873019c93a4c17fe990b3e4651faebea640c391978fe378ba296c8432b1e4058388a618010d07c87464274109f3a02f52f1d87afc8c8465282c9811c1b0c0458c1ae55f7c39bd0c8c5af6a30efdf576d72c8e463bdfbd93237d3de0f53b7015a7e6f65997b67bc5dce25ab2cea57ed42b2452332a33c4f637981e8f1be056dd5e0451b3b3bd428622e5fd0a75a88652d00d54653f83e1bd43287e0f97c853e263a2a20e2320dc9da918ba1e7ced39f1af51db5637b32a812fb4adab7dd122205066770d61e845fa18594ce64e3840c950eaaa46f83ec510e5446cb34557e578787c6197e13ff3010294b240a984df33a167381e156609492be8602a26b0ec683ed8d5d8ef9cb4b5df25a83540df2e8bfcfe29bd882bcafdf0c709e836b34e7ea3b7391cf7c49696b234517f9f6b0729f9d6310bce32c850b575ca7b51d09738051f16862af47eb0ca4a60039d843ee02a31b2b081ba764725607a7b23360caa1fcc58029e86936e075214b19f41540a118e7d32379b8a69a3108b7b928341fd8efb88333cd1aaaa179a0067c151375df007582582f36715c1535fed59aac9e4518200072817fdab7004703e7ff32b50dd7c276e94c680500ba9435eb2b8902cf0f6ca93a4c95a91d3213f00cba7c4e3c126f771179b711a3a67fe800d99c3341c1e27c2f07bb4d14b7a3b04c3b06331db5a95862f19feb95836bef556aa9849de698d9e03d2f8b4d0cb98ccdab819ef69553552b2daf3c52c4564a8c644dfe816ebcf7f0279fe166bf2ba98a8034e97889ce9522635ab91a906108016ef8ce492f14b7992f92a2766f7a45aea42f2c464a1a641966cf8691a75c11a727be30e091db8efc3054ff01675f494061bed2fea539845175a4d45c12aeb1690d0b7744f1dd0cb122e062a2afb754734b24475916479b47c588afd43006ae5db95c1b45b1141c2689fa160db00fca2145850e3d75f846e692e3056862ba5cbe8ce5c20c1d85bd05c1c23f9942a61a3ee73440b762411d11da68e5c4877b92606a462c2edc8d9e70e369e59ba55e7028120c8f5d422b44fa975f058aa23d5697c9a2b20e3dab32df3fea1aa2693d1c860a5ad4fa922d5b1546f333ff469f740b5a338c79574e956c778500f8ccbf6c6ad966a54d571ddf0b2e85bbef39d78e356472aba5044cf46d92e6e95ca594669dc610cd499fb2656465d3ed633ae4488043d10a764a7e65d7cc66b87146b7dea97d3a498ce65f96f841e3bb67aa2a88af5305addfbf0a4d26ae8c4d01ce910fffdf52590f705541afcc0782e2d6a74328866ebd6ca2bbaebdeddc3697f476690ceb4e248c7fd01af622c91932c00bc6a2611678f41b65185f9691044e5df659023750ebd1271ed3cb7a99074a929c81d4104a4e03f91042cb426c2ea8fc6a0923e774dfba15e3fc50103b12aa2272bd3124b15fca036866c24543ea25f030ae52ca5ace476a478ff91b7d2ae007e6010d10274e2467131f32a5a29caf14506f0f9c809fac5ab9ef7829084552531ce8f088d129d2f73425ea01cc35bab08f2687a16078128c24411995c7829880fe15f4087b3d1298ebcb128a7c21b30dccf59fe0668eac79ff6b15e8522c41c1edebac8b6561592fd74619a4d56c8a9d8f1fc8221c9cc1edcfdc6eb40023971336497b56d9555adf285a03cb7ceff2ed290899417cda0dabbe5c329c3aacb5969f2a2f8b879e88b4ae654cddc044724faeaed8647379c6e65e1ce0f0aba0074a02c408a9134e53386a8823156006d1cd4d38e77b92687bb9ff868e004f1fc1010552fc09c19cd789b2f696521159cfd6bd630381be4070eb1dd01af99580a30fdee3492f187ad02348fadc397dbdb28e63a09e7eed4323b3b3377238ae44b4486880040ee151d356aa8d77c82a6dcbb1d2167170d2c4a8e0e5dae5ca0fe5fe25ebc61281200823a429fecb1c2b9ba3e3f6f94569f25bdee2fb27b3fd23c722ecb269561d065984f142ad15e4dccebaa72fed07ebf29ce66509ef9ccf0ba606e6a9bd0c8cdbfc1459b5a8dd374725c48d3e8fff300ddb45095b808194200fe88d52ae372d7984d549c647b32d8dd528a33ce9dbac8a7b4b06e704a7b39dc03e03ce152f5403e510c6420d629af6a4f33eb8a96ae5c90ec2c75527763f8ed0cf93e3f6de048908d2bab4bf1af871355cd478e44e2770df2985502721fcc5f3a485a12f4ac64ab46284caf8e642309da8849b43637ed8c94462b838b3970865400683b23cabd47f69b15a0c308140785851b4d69fb55fdc51cd7553cbf1045d9bd1249df10d14ebabed65667ffd9519aea62ef76090644fad4d9b2b508b7ce6f86615d8d36d03c0a2b758ddf3980c9e3ba1b86beddc2da67817b0b4b5ea8649ceb65162ab32e92a3f57174dbb21ebcd085be156f2cec0a9ae4060a9449c8ae231c29c7c318ca79c6076f3e53827ea75a9be6e0d2c5ee5b6e59f0341096b9638d1205ea95bb8d184780e3ed933adf4c074ea2f4a4027a9003fee876c9d67399d2e329025a97aa751acf7ee11d03f0b99724fa7ab9fa00fa4d81ec87f67b2695e54c6193845f7b5e9cf1378331a33fb44f287e93497eac4db7def34b6603c95ecfe435c5685491d74274cdbcf51d7f989817e839a7981683e4737a68680d78a5dcedd054c181a691806db9b808f4431f96c3474c864a8627944daecc114805b51a49e0774894854324f413b9dd04909238a394b471e8ad2bfb262580551e7848ae0ee7ae2d50ed5fa2665aa5c92d7a5f869a892a2109437ca49f14c7165209cd9edaaac9c40e6d0d47ee1503403fa2f3c12116522ad0c4abf1be45224ddcbcc02a8bc5737b7eb425bae8c726de42c1672ec39e2b3533e8009f2a0ee27101dd72a7c17f5d9a04d5c556ca800d42044551609ea01f462e57fde253ab4171e6e8bdb68ea3dcfd125f0559e8862594810e0e171ccd8597e61410fca5f98af15389cd29baf328bc24c89e5209c9c6435220019936340c67330f4d1fed3576d301de141983e2d7cc456c7887a762f201ff26f7542e10a9d269663a1e8398ed0aebb123f7c41b7f39e17095d0b3a14c1510b3937e5a3902520e78630bd5ab280e3c54d04236b0f8cafacc5614192c5c990e4e032058209355296e9e7e0299faeeba3060186b95c0893b0d9ab0e16ee364a9ad9a1e3ad6261184435cf738da069fa3508d48722ecf611977c45c8aa0f9c398c02403f71c871c1a54bb3f62e275635e49438087d8b8f843fb7f36761b877bd741fe4f2ce4689ca7782ac581874bf810b91d888a301fa26f8608c5960279dcfc0b08f3445c3b24eaf9377440737eb687b9b0709005681355e7822f8c4a7c64eb17014a39b862a1136a190c2e71bbb30685a96898b733b04db3b083e18746e2d09331877831049ddd65a5abec4eeb07fa02eda5553cdf108feccd33aa00460fd04f71f83767ecc77c250a511d6ef75fcef601a0af25d934277ef5f725f6147d5b80fe049aa2fdf4510f3a20bc2b3607e2a97ca656e22756dcd241333b91e14260af8a499f84d27abbed0967d4035149075f15a30c005c165406fe5382c12d18622c936ba609390ad403bb63a84480248d1a23402a81a41362bb9820168bf7e648cb0deec66f245644e932a8413a263bddc35a7ba1b1f94ae6f3e9495a6736f5e89616fa96628d5cd94064b0c1c810beaa405db00d7ecf2507a89cb49ee4c424a09f3e4db83295b034a8ede3ec96bc7fcb71ca0e2e16ccbbc1fa513ea80cf5403efc588f4fdb3d8518ed9e8189401ab3fdfd45f698075b95fab91fe0feda25951fd872edd8dd073d974b99302089278f28e59180e9a61bbd0ad61cdaaacb46d0ca34204fcb716a7cad284fe18c4f36f2b923aaa5fdf6c811d27bfce19511949be4cfdb86ce8e75c04ccfe93fc8b9bf05facb01c605a51a41bd90cead5cc77935b69f9b8cac92fe2297ebf702d43d768fce4c66e0fbae931a8382fce08feb32216a37409fbce426422a0cc311f67b5aff203f0281a7811d00931f14dcdccc064025c1e0733c381da58a78fa5e6d66986dd2f98b9fa29d7ef5d6cd59225784b4aab796c40498c30ac81c6037cf5bb5aa3ebe9ba257a4f175bebe30295eba640795cd714f9c5b60c2277d195f2dd9904d3d305cf8932684c9f643caaef4706c86216ae629a4b4c973706f167a988c7db68d8d58e3626349348533c3aee9223743099c1ae16d97bfad6aaebd8bd9df371caf9ef8b1864682c1f748b9a7c589aa7e26bbf30eaa0238f7c889f49cc5c7e73d4fac65a1ee2bf8cb5919e8cbe67bfa1c3aa1189b38f778c3b13f50d92bb11a721ecbb9899a5cf1d5cf44491bf9e0c99189a506947df5d1b08f44e3f7ca2f13e25b0800227284036e6cdeb5fa84a09f309a9314d3a52649bc20945c7f10f847da09de20338f03040f1f2e064ca55c66f43bec2d066eed696d720cc1eeeae983709a3c6439932e34fcd8fd7e0c3192bb9bd05fed0c10f107b14f6b1bcce71f60882fc45e01b09c6a75cd1cab89817ce83c49c9b9f04cf1acbde57ec47ee30c29986f86ed3c469b749f454eb036bf043f70bf5d0f73e467dc598ffa0b6189b7b517e02c1185bed29c727715810457835cc175799846feae085e549aa67342f1f4de7a578226fd18e7d039000b046216a3e2205c39b4f5c67916c53e3e7351e651b5d44ca0434b8ccc8fc981bd0e5565ca35919dcbb60ed6ed420904f35b854001658ace4981ed38e7485728e7640e727dd39ec14232e2678f08d57d52fba621ab28b82962d45fe107cf58a85a80aa5f539b5f9533acc2e5aa2a0c8c04cf017be17c92b50a9d4b82d6fb6f37cbbaa7abef1fe8828c20b9320f3b5146127838979f04b719f448fce30fea2d9f5c6f419715b29c9b327b1b04462163c093b17088df87580eeb3aebeceedacb8b2d813def8022b94431421e74a7958eed59a3e1946d6aaa7e24738cc167c4dc5331c016bb1f50de7501ca1dd029047614eb8af55226ac2043308df3d52e5d1f587973a72e6b1f5b86096152509f2832a7a91e0d58b094a188a200039ab558243f929df45a7e1474b2858b433bc14fcb9a021cf0c7b23620ab4f8ac559184335554c175334cb12e6dde29cd02769a6ca8f5b6736a33dec472575e88e1cfe325b98d60a2cd3e2cee813807635acb04185031f501ca32de963de285f6beaec564ebc969ac1f9bb43ee4f844a2e61054c550f09e268761922f19b951dbadb12dc0d9229a95733bcc51126e512bd2737264f3f4e7b484cf5b08422902d5146aca8e49d6dcabf20808bf1049a751d0146c54484ba1e1a6a6af852f6e1d4e91c6094101241e62149048cb435221057fe8811b7547193afc44124bd66659a30ccbb12816116e2e07eea10e92c70091f91e041ed2c484a9b2f6cda02f3124448c5d9d426173c7b5a2ef424cbf0c1385732be804096cd1bfcbcdcdd0f1963851a9bf1e1e3c8b7393904fc7271a1225284f039488527c95de9470fd8818ed1f153bcf7e2810ff9f43ef66753a694b3db7aba2557dd75f5a2451c9a893811b9c850f2aacdd5c9e4a49e26240788e44dd429a88541260da7eb1c41ad37b44f4af75c356092c8599f7162d152e00f8dc9743f4aa89cfe18eb82fba7c24901e29b9d2c55161bed464c40bbce8414c57b21bbd126a4e58abceab16bb1bcf93add517126a7eadb9b917453d83988c13f225d48c07d658a98aa1f74bf8b05b705502b455a3bd58ba392756fc3fd9900d1a29417f5c2e78c83130628c05a00a7c3306bd4a06b8cc5c037a8766a0134b970d409aa459ac8e285af3cdee06b2f6aeadc5a0c092e57bae7a3217cf3e90ae599e0b421b4d62a149ed21548b34ed9188ede9c5519d961ab8812ea4af9b5cdc9115b3e2d3e748d0abd9cc32b54e8f2b06e7ac4fdff76f0856fcb1666e2b29461cb59bd70d9ae7f9e5bc3578e1aadf87895fa4399fdd3968c50a35878660d488fef37a635d5c2cfa536520b513ae7202d01c086c476ba41079705a92dedebb872919f1165a917b219ef4303776185dc8e9ef83036dd856fbc79785284aec71954cfc8b3423c1579d73bb3b45fba608bc72443adc0392f8c8f1faabe7bd845144ba81521c9b929a6036420941944468c21c5bd6f57f0105b2b9d8d0fbcbcce721915018b0d034f04a4ba57c5d01a3d3127b3fe90e6935c99a050801b3e06b332e89f2160cb5fa0217a853fe0c0b22aa6ba01845c5d9a06d8900f4275264228b23917c6b2f028504d2444e37e883d98500ce6b110ff46e052695aa45cbbfb1e20944d2f29e0a60748a7d00c77b5d587a2cb7b0c53891a9287d8fd27a00b97218bdbe337ee586edbedf678a9f534ffc020a56b1cc0ca0f525df73a8b4a04622c8ab97c0867db474d2057adbf32692ea7b499d420155fc4026cd258617a3f13ce6175758c1e228bb31588250d38215b72ab37cddb6a04e889af95ce394db2f03c003d0fd3af1129cdba71972e4a6b5a6e1e8eb2b331a5947de44378c59fb68345835c6704fbe25abfc892a549cc681e879f8d1fb054f405c6cb9744c785052d74045f4831b439d68079e14584a1544d50f49658c22cc2e0f92363b94b9f73d167439c0cdc0b4ad0b273d0c6c323db7b7be3c16697d80ef67497ebb86b7062e745d7963bb6e49fe51c9acac2b103e324d3b3227da01b1abebef2c0ba698aeac767e75119bece5d5690182a7b9872ce6775829a6158d826d6f4b58d16d10c2f515f7e5a2e73f74ff52219d2031741e243ce918210b58dd17b7d50603600e15664dbefd305043f43db4485f0065b5961a6d3a627295e584c8d23a6e7d4d2a06b24e573009dbb588310d2c23877913ead4e0714a46c47fb179733a0d6ac87f8101209e93963eeac846230bd25100970222055301d680be6701cc4a082209e2dff4f270d62964ed198b6b839c3d23a70cbc8ceb802b7e0a0c3ff1e1080ef4d5bd6eb276b2aa3aefa42fb0cc83eab4b212af163d563225ed17dd10934564abef77bbac8548399f0c95acb747e40255250662b2248d402facde02586f88dbf2f381454ab76dc73c50c8c8504ac9b03f33b1e14d508c247d473360bc2fc678a827fbecade1d16213e021ba779a03762b3b634c927a70f59e0c5cf636aa069a3cecf9de7515437969ed2d264465eca3372dc9fac7738013cb22fed2c25a6b9de009a29819fc0ce8d35a8c6fbf4d92706d23b4e7aca9417c6d67eab728f5065cdf863e5e0ffb7cb68ecc368dbb771b3a52baf63449921d905e830981edd6c370556a20925b76f372d9192579404cb3308af8ac1559bb5c434700f8a26b22cc6325a72421b58f4814015787e8c1dba6f617d7de66e478097f84230b8fbff1a1a6e071834d5547ee77e4afb60f3002a04284d6b2323a88e56e92f0ae6e45ba17df71c3502b6536a09ca90b9ae5a6a9e5c99c0dfc4e4f9d17d85443423f8f42a59256a9d30045212d4182e30c66e2a1f617dab7e2a1a441edb55d5eff71443514cb1f63440d823ea6fb229cd4d56d424533a7fd19a9778fd5363a010b8eba56f38fd451387267eb4b8614ae7781032207e6d5c3d4d59649c3d10dad1ed83c6ed1606a14f8b800f248d904c626c8abe384c4a89803df0f3a775ee2e839b2ea2af01bed5ae4603958cd33803645a72ef6a3a63e636006aa6915ba82c727ce11f787e8150145c405f029bfad3848522d8d3c39948942043ce35adc49004c37efaec13e0e464b4ae888b8147bd7853cbe3a4a47e084c3d45f373a7a1fca923b2224a606c33916fc90c3f358de2a86070caf7701c64087bec5ccae9fef7d9f89f5a404e53d52478a4c8a59b27c6da9f0dbd8951bafe4ae53f5bed89cd0d7d2c0c849afe75f4ae35a3cd02469b4d63b094e475d0b5d14a2284761485571e2856600b36922929a7013514272811f9010b97f7d337aeacb136ae0e1762d08d9cb896d79e168b2195f397d7bdfe8512b1b82da24de5870843cc4315b060220f24fcc8eef763f5f26e0f5d5795da85c47377d50da26006ef56f8c043c2ce43177816fc2a3748f91028fc046d482dd3642382b954208d4d0a6dbc6c7b3cb7a60e394a3fa013b868b0b7d2c48af22f55923af1b85c6f760767bea30493c9d1a35051d951d8233d870d43537d6855da588cb800abd6c5e1418c9f379d4ba58cc01d3b21bdc4644571e26c4e1bd8c0c7da41e72ea7132f0142e884ac9c7ed20704430e087166448e3736992300a2eff75ca2d53623289f5a1de94a7d15ec232cbb9c39141e367302e1ff01b25beb5e6008e52a76d682394cc2a040683f2fb6f5d39eb9b5361f25868967dc8fb01c7e1f0adfe1fbc67971286bbf53678875ecbbe59845420019b3416d100d34b6ee9534a483077faf32973876a73126d5cb45d1adc39ccb8793f3d3fc08f0ffc679b76e781e21b087f490601507de9b56c7bc2c0e5ea702ac9ef97a87ed5004965a0758c1d132c5bb669a614e794b35003ac60ace978bcc1f6bcb02571c28e6b0a69e86c7a905584de421ca73a61a9588f957de0f4be3c75b75f616060c7b2406d237a74e1991515e28f12fb17f1f02e01d68b47d516cdab9ee146a01988323c87e0b1e1285cf0543c9cedf6803243bf939e6bda5bce01b083b69ad34811ff41b49db5ecb4796459eecf3089525e35abcafbbd6ab74f81a74fc64083c05521c5318a279acd85aace2c0a31043dbed638b55956f56bd18fabf1da0c64ba51fc68aca6893188b9c8eb1b6db2a928dc6c4bdbdc7a0e0930a32b9d02c15df48138d3f50d4f7ef32c42d4b625d4bee629f21205dc5424311e42e93b5295672e43c8c74dea2622f0cae280344fed0bb6275a04cec7649f5f3fa00749134e5abc899a2136ccab350a7353e0f65dfcd563a5ff9fb9a207e6be70146e39ccf84b4d11f68cb68517928a6fdb4bb171c26894c5fe45feab5fb974abc7c899dddfb2431abc522fd34a7043ed281b84d1942cb024f19f052e41cc889b794a6b66cfd1265a85d9f298ec598cad171671f46d1cf68be47e5425febb1a625089f0552290dcfde4b0123730168fed4abadae510f0c92ce825160e0c85459d2b6b60ec8e8d751f63a3b890eb5e319839c211947ebb9463c85b0038d08b0fcf30802e95c5da796512879012dadb493e7c0a33bdd14bb3f2bdd0dc33bff4265c7b820904e6d4fc2f7c2c2913ec1bc62c0e1666d579c8e60908c1683cedf62c37c68ec965806ca346393b820bcc547828142852ba2fd926146b5d9ab78a6bc2e156bcebcb24d9ca9ac5bbaf2e2ac6d39f5bd2e93861b4df3abc0157246dc0ac7058ba9d6eeef78e468045ce257ac3bcc7e9d292f4cb843f47e284817dc4423bb22a5d04921ab62a935063cc6aac86009c6d28053141ab539a292fb20f50b8e710bfeccbcace41ea1c332fc799504e93387f482f805e8b200ba387bc70feb18ff0c8674463c141d4c46d0985c6e4f472023c948926984bb877d46f4628c9bde865a4b25c9324f48f4a70c46e9d56ed4f947a03e937f5398b2b883c42d9f0e0a4262e74ed04a29a2b9be5310e93a5306a5d274a46bb64295f21cfe94d822a3aa367b5982f6f45a10113ff3ab82414a09a6ebf3cb357d248ecd1de29508c76cc30a9d3b8d3e1ebdb5daecfba51ebcb0c04c6d43ece8ceab792a6fa6c8d0e440af16681c21e858556fae70880580b95657a00c016c559ef7a194ea83e78c2dabc448fb053f6691df403894ceadd1bb8505ee373968b23f720dd81c338b818eab7764e08a4b10a9315f8d33aa01764e6f181bd0b83aa627e3c995bcf7ba6cecb669fe1289ddb1d32d221b2e22b7e8af251261069d0347543ad08c54d5d044163337d93b03b8046888f88074e36f9b31ec1f8946d52335bb5de2b66f18160ef5831ebb645c311f228cb3a1d91949e2e8e99fa3c92272667bab87a0f47ee90641367c491a7a5a72b90214d9047d9ae66dc5345ede4ea29387c270c8b14cfb7a97d902cff328f480714b8451d0030798c180b3f786ddd6016afed99992a13a99428e10f9ffe94fef4e129b7ad077abca286ed5ed75799378106526f749d2aa693c0f0bb7693de3bf106b5263f95b3c82685f7e88e8b5011765ee3807fc5a19cc032168487cac351d53a4c8a4011a5222737f1df00491152dd1c4682f145fbf13b201738d9319a0f9b9d915d6ec21848d11a01b058a9b67f7a2ddba64c9f91103c98c29ef32a8fb1a18fb170d1e44bfcc29fc2f4ea2477508251901b4545a8c4848b3841d060b20574363400283246c0edceafde0e72e976b32eba1844f02148d9187ba3840a206b568521a7928e88f7c3c6a0177e644345ce964cd2a663110c97ea38095dded8cd04e01e858d403062be55a5c18ed38533b547531665994e24ac76774a248f4a34c97aac73b8ee7fc8d3e5cefa9ed10cdece8819876a718a6324bc5f919843cf76f162d02d390e3d75bb64c811a9834ae9a42c3e102afc4924f9759011081f1e8cbcee34293c3e1fac522a134fc418429d47e15dbc96cf6afe7119ae313713695d5775171764509717558cdaa77138bb5c7917c37374e8e650960e1d9c4812564fba0f083b60667756233a45099e4d30a1b85764cc27e07b9b1b4c7875fffd9385e603256af0c153c8707e7ef3e9e8120bc9d73b30a870c9b8fe3dd9e3456d1d272616d6dcc1eae4be736c0e26b71ec4f5377b0679b2675575cdb08d902e75a69381cf086dbc7ca2fa51e5a5a08bc65c919bb642ed2bd3fae77adfdf34947647f1cb834c6f2684d7bd3c2ac37e3ebb43f54df2900261ce8a0ddfb4afc58ed4e2ee65ab50ba5150a9e95d17157cea6570d41b1310afc1c1edad0b35ceeb5962e2e3ec662d7d0bbd64f51991787651adcd458b481d9864f656c1f5eb06775402617141d807706ea94c84fb8bc0eda73c0d583f1cca2d5fc2b6d1829d4fd58d9720c2c6af1faa8b468d08085c9726fad1e4c8357aa37fe02126162dba5b503061c453369608408b550c892cc14ad1e72578e4b5b71b25fc959dd420169d55ac9fc7ab110489b17dabdfdaff0c3de57417f1d86bef39781cf7e2b609326dd6b5cb3dc2f388a9a63e5155f6c7a23f7bc8efaea60b791ce2888aebf2e1d18925b1b252b53c08c32166cc0eb3dab09e8590faa9fa67cfcf988c6a02d7a8a8796199a631f916f5b5b694a0f4dcdc44ded7096b6cf7bf82ad132365e73821509d2010b4a1220dc0f592eadb1d2432e3015c357b9b3d149283e643f948ed76b192501b687c09652026a82c8de409dc8bcb72de254339b3c4e9e56ca314c726609d1c58a1ab79211aa48c04350ff10d153a2b89361cea6c77820481d5fd5aee81485fa50ec2a2f7ae7e34ddae46f5fa4c6ce76a60a9f60836c4285f2877d3bb8d80c68f33067536771a3982968489b077f3110fd5e3ac7f42c15c9d89ada3cbeb3bea71d72ec1e1ab27084b8a765188956f1ff2532caaf3c36d4eef3f7f20c2ffb43521e20363e59a5af9a0dd2dcdd7e094e23fd3ae07fcac2e4f7d7cc6c96d843f9c3bbffa2cc0127852ef21073b4898d2406457165a5756003eeea3c98c619a5e7d54c001134819d48ac2c63a93c0c5b870011af3c14bbdfac539561e710b74d9bffe5482450637ffceca2e093203ba201cd426d1c736828767da4fda558138a7d163327e5ac3e50159dac28c72129a29a827a76709f96af4218f11cbf833ecaca12e4866b59ece11e8f39a46f12f7f00ecce40054df6d2bef92b9bd56ebe26d82b5aad7bfcb1912c4de542cf65c12199e6f91839b3c1dabef16d9c106e5bfb86069cbb575703e7183f92e9928beac1c1a8c1c926b671b1ededc1e9a487e4577fe951f1e567686944e175be0748ec2564c8bfa73eb212a7d1ab9728c57f014d3e8d6c91401ea3d97c93fe09cf4fc0d113c34d82a1ee74dbdf6380a5b491cf7a887c61d73a648b28017cedda2e23ddd70de04ad5e2870bf48105b3cea2b41e9cd6236d1c9b529f5cc0bb0b05ac68025eb415542a4f648b7aef9258070b3b24dd19e13daaa56e10d444227440ef16547b87b7fd4e2ea849c4d11c17d83415ab7180f1c81b02ee0598c369bcdbfbbf04b5ea7eb75a20293963d5865ec5587fa355f6a285bc764b47080a5c66aa616b2329ae26ab020ccaaa59163ca5fe5b8ec8d5e14dc928db0cb2d32b3a41522710eb655ac222f4d494b0942ccb980a78147a803402312897c19ac35d7468a1638c5d9bb801a3495dd4808a8f297af55cf6fdab2596a979d74a164780b140b827d87fc645a6fc632f0494c5487ba7c457bfa6978c92ba29e0d1c5e3cefd757b7279d11afd70d87ba11e21d92909c299885a0dbadee58a8f91f312c9a7f691bcdf2346c0e8687eeb433ad18c6bb8ca44b51209034da45e09e75c4d902a3cad098aa5be2eb5b18588fc47f0caeb35a6b2da3f3886eafe007eef120423ea4de1b5f9d65199ab66b7d53d87e7855b2d77cefa3335de6f8c40e73632c20c05813e01ac5df7d420384daa1e3d122095f36287b31fab2bb079132123c629d530f867d8a907bd87a14f06fedb600f1c1928e9dc7a2ebb37877a30a0d552626bdf7719e53809926e26c6e2a674781ff1b70c412948bd8661317a91b88cf798699172d81434ba2cf2444ec6e43cf7ba998fea31909a9721993dbf3c9dd08c311eee5acc276499adb323bc9227bf3e2180ce87e7a8a22605e0a7a50ef579a7a57e08570b545a6ea1dee311800e3394208ac2a9f3b448e1dcfedc61d31fe0e3629cf3863bd280802a95b24f538ecfe597df6b05bc4789fdfd01ec9f38f68e714ebb547382b5e30b72382547500d61281c22d059cf009bef3010b48f227a1aceb397210b09a10eea7486a128ab00c0d4b1e5e1821d384ee6719efba264c3fd41e9218d1e31b12f106d54b88abaf02146a375349d9a31f4e9b0f4b55f2feb7a4d70ed64374a8a57289a0f7ac422e063d0603ef15fd180a4dffc7050dd36cabd7572f4ab54d9b55a8fbb3ea254a0e6bbbc02e8ad7e81f807a693347188badab0f39ab6a13bfd6a79b367fc8c0aafda6da36c76304e300ac4d1f39aa798f5d903210266a077f29c6fe9125921943c8eaae81d74dbde24c16724cd70195946ddfa2bec38bbb3fb72f8646048d62c7ee8fcc440f045e426ccd257edddf53a1343a5cf7374835e62d94a79974288f9f33ca2c181feaefabcffab6c030136dd15da07cc595af2afe4d17b31d580321390f012fbf2d55b99f88e88947c56c8e0c2c155fcdd011a6b965dafc24b86f6cd95dc7bd1d09386f4e75873102ba709f698c831e83d45b9f5994c15b96e6d72cb009511b76a01d0a4f729798f0afc92c03a2a1b83394987a01b090650dae54eefefc94a4b8d453cfd3c2861df2d63578271c2753c9019ac31f82e9d7c24b6b381dd143875610c88bf9707ee580d8c612572546bc2cb165ee3946617ef2f20aa61285fc13a3b446926b3c824fca0bf6bb9776159566074544fd1785398805d8f0dbd7b4a1d6b202c4cf1200fbbfb9e604f73ef0b5b88ca794056ec7920441d054066f3c50eec85b15b72943b4c55fbaf2e6fe639238e2fb51b6a06864ec5cba18c31b9ccefea50173813e872a10104df600ea3ad2470751c3ee0e42967d3bf0765a724c4a494b85c28f33f9062493f8bdda52e93c4e65ec94f5e13e027974004002a45e428b60a59623e5681340f440de83ce8281d2bb5080dc3f27f44f7d7504fdf3cd2b6ab7ad52b7901dd4857918e64192ed19f4195a42ad55608ad09d76e09400d39b4b6754dc68bdcbb62af2eea5201a0c50695fc264008e048c39866eb79d0e379620a6620a26df4171faa2e34eb65b5c0e94168aebd14d259b719acb470ad9e14fa8c1f354b3d940c6e5a1abe2421b2adec70dd40307c11d61a078807e590aed3283880d984a893b95b7ac009737eba9ad8111511f320fcd70d56f4bd4f0f608c928021ed5211217cbb251571453cc0ad0ccd7a9475a94ad2760f77c3216f50bcf86d9a64a5ca3362f4e592a7fa64bdf7bd397b0ddc4a8a1539c96d84af9ab98c21fa482915bc9ce48cf7dc200e4e66a729cdb42c1445778b4035a66c4fe9dea4b07615e3b935de33224b085daa7e98b77fc4c3d39806b38ed7974adaaa1e7786632dd5d377eec86173acd6e28ac779e86804f2f6c95cb8d3cc9632b167927a7b1a716fdda9427383961268f0f4f07a53391fba0f0fb2324b13c7e834bc966f9a3f15718c636c5973229121d95f2eb5d6378d608dc982eac3c1289475158a57f33c6f045af37de76fb28e0d73c53c73599a6b8d8f8c179717b7a47e90d6acf1447c4372e7a2961bce4657d6b576ee064b067ec5118ae40d92ae0eae1e2a4df95dbf412003c331d26c81e469a53a56775bc661cf17bc786935d12183cb4f64423333de82e02156f5129bfe3e8c6f3c408e6206fe5b6109d80f46fc509fa32438bb7c23d499d299de4c40dd94036216f54e13aa90be4631ed56de54c51554ee447e64efca8f5e1a7c4233cdc2cd8e471aa24085c772a528be3e12f00a091e35c254b4537f8cec1096d6ae6350b4716dc417b24664eb198cefd9fdd12a823be4d479f6a1a88aff6bc1e4c75897b43e9c43ca4b39129e53ca1090770362eacb121fd903e357bfbf5abde60f7232f2f7fc50165b6201bdd6d59a4eb5c8183b15febf2e3293fb09374a3acad4ce93e19252b28e9a8cb6bfef2e541bd3422e30925f5d80d060c516b9d4c9477f4de7d89c22eabbb3c9dea6b18a2579b11a999834b88e4129419067ef52078170a29294661e28814cd6f7daf9322c37e10da81e7631bc8abfc7e14fbdf38b971abbe0b2eae59827861413eee78b630e70508b90124a49e5353a0153cc663a3be2c71d4c3fd44c430e7360b0f3c10a92ad3887059bb31a0865c54d7d71ef314e522a2655e66c57f2ef0354022edca9e7fb81b63c805ad43ed823448042c0f8f7e8549f47ddfbdd96be81defddbd6873871dce7bf3c6a95c9950d91eeb02f11eca04b5d3a75bf5bf3b993db9cc0ee1bf9dc2b75c1a6a964824c71515e35453a11ed9131c22191bf0283b431e5c56680a0b6289bcd177ce83892f89aa07a3bdede52d09a9e7fe9f4121155271932c6764fd6900d76ad617e462e519ad9e83b2984970a98df3653d85e3d1c5464b86fc2d4fc85e62000f74bef6d0981b05800aaa72790d019e62f097072c577621931fe412c92e8e8e046a9dcda99619afa2392101bee5b21d94d79a968873a3720b6100a5dec140025417f75cfff4382bc1cfe205b06f0b5471eaf1c7cbbbc5fd3406176cd8e5f24fc925425ff966288bc7baee0c8107a2a1e7b8486ad2784e1b31d58d91a9f05fdc08f714261022f45de89df6d5ce580d760b92a5eab5e99794d1776b98c34bc423207410838758d2861612318cbdc80bc22425d0f39130bad243c50815f10030572d82ed8d5339615ed82bc0e0616bf96cc3be48b2ced61090cf054bfa52a5413c023125108194e54625db61897cb18c688d743407f4cbd2e848d46fd6744e1faf7541a008a5e37c56ecc5e21bb930ac5d276785a23b14e72b7d801a7a435d9ed630722177d317ed028c3d136213ac4d5d7a3b343473034a2f926f59309cd5360799c21191915a8ed40367a9600f18f21a71e5f415bc511dfedca2940e508ed675aac19da260c85ca71f0b92362858188c8111df35800bdc5d89c64d7681d23bebb075f0a62f3ee2a75164f2b6bb7be59652ca9464d206e506ec0658e2af7e3eb96aebe753eb64912d6309a3427393931c24734b8f71d18db88c5dc118f39b92c3bfb97b6e3f43ed059873b05fdb3401874e0aa5dbd010618414ed90f90618b03ba1010ff4d862031d08a5166895b571f817623ee7cc2ec949194b0dab894685d8dddddddddd2db36e92ac558767599665b5134529f28ec90f0773d8a47b3f62f6d5cf63e11629c7c93ed20c75d35ef75eae072e67dfb2932d97c5fe5281439965f7d6cc9bdff325c74316c241767e0dd39eafebeb20a446b568b10536c0a30c17c080044d0b43ea700ef9b908902109b2198c1c7e3a7bdd9683b2c75c14352da359c9961a5614d962493648e61d2574162381124702248ded1d9e672e5b0ddbe059bbbbb117d873f6d87bf68160c061d7796ab01f7e2c01aab5f75a7b2ff65d77ef952de35d194949818814a26811a58b5a5db000b4f09ee052cc0427961d053ec1fd791ed007c8fd433c2484a45fa9d68a6158fdd1c2308c31962d3660b06329f25a6fb70d187c7388b13c2363d87769de5baa4fabb59452b0b117c241f77acc5a1b30d873883b0b71bf9602f3908083e01378be046e804188aabdbdbd3f27b27799a1eceb52e996542531e0cfa154e1074816ff2ca820802b70d8a54aada559b53a5bc0048972e3838b7c26b468686e688634116db4d0820c3500206157c4b01b739138a8e59295a7fcce6497e3c8a379ccd0bd18775d18ca31c641ab04c9c9411b48e0ee5bd302cfb728977e5357d5895224b1c82eb34572b515aa7431be6c8ac6602c8a38c93387778883ae14146972914c20029c05e4c8a61cdc3ab1bb9d28625f2bfbe524fb37c9ac158d8332a94b49f65f925dd57d8278333bb7a35fcbc4f0f387e970cdfb513dd7b776499eebbb412e8c83d9f3027cef905b063cbfd02ab9a5ab74ca37267bfd6caf4b0c12844571453b44e7d0da5c51b63886baa56bba4344eee568fbe6b6bee215efc5d8316b635ba155d9a866d56463583786bde5ba43d589b3607f4f486a0c14282c3c32a07df6dd1329bdd0be10a3c215afa86975a4010089062da8906aadb556e9241792fdd6d1efa67948654b71f96ea9cec1e91c7c4b71d725b55ac30a786e9ba721d1543c4d89b368473428648b6b2a1ec97fbbc9fe9cced1cde97befbdad9d9080c3cd146aacbe39cdd0469a2c359039b2f7df9a90229314a16668cb917dda17640e4c4890a6b5b26fa6ec9f1606d9e29a93feb49646050eb794e6573c593968871d8d33e461470c5a129ed4141df9d7951469bfa99ce42d3559327729647f2d26e675f8a5b166c82b4b4b4d2da5890eba3239dc524db20f21823e43e6fc8f9bb9f70cfb6dd338af5f83e13927250ccf8e38de0ec9f1b487e125b1801ca97cb83d21fb6f29c9e5704bd10d8637475beade3ade91a3554ee7535121c1cd9a13197f214beeaf31dbfb177279fb90f3edab31b56e9b86c7554da5538584bd9bc16206311b12a0e0848d37e594d8ec24169023abaa3464834601b4181bc6e1c6c072cba051007aadfde46439d1406936dab8d26a1cc4d29a38288a83607c6bb90625fb2624bbf57b31eeba7f10a4a7c9e2f4444fffb547ee0b1cdabf21e822f0bf703e141831ea7cca77de1f04800cd124a436e989f3299ff2bda43ce77b916148311901994ea410865192f9468c421a93fdf339719ca29a725fe07e1db3072f043d6610f463afc9ef1c587d7bc47a413c76afc7decbcb0b8c2431c2df9e366aa367942202644f79e97cca1b31ba9c057ca4f21ccfe303e7637c8cef2586d6f1e66ab2268b7b607c73e5e1bef3303e86e7f141c6c77819df8cf179b887f1510a33597ae4e1be0af848e555bed9fae6cdbda2235a7ac2b080436d5c390c29fb5f1a1cd213f7ae8da78be381e3388759e51db2ffc6bdff0e99fba46cb95f0804c5f1e4087b25a0811550a3144f8e360782ea31d3cfbc2176480bf888333b1b47e0f053e873ee17448f793e7dc2137976d3ebdecb7923389e367ada4ab6d8b741c2f6436dccdaa88ddd34509bc78099c1f248694d3384912ca9be15e2a0d2102431d58ad51ac9d5cae44a6bd59c522e774a1cf13348522455b9bead9609bb44ae36897af355285f60d2bdf3ebd141df0d2f604bb2a45a6b0bca0c561758f0a054e91634996ec1cab47e7394565a29ad1f082aa5b47a75f7fa75b4e794d94917a49444cc10460a42881f424c25521079f57fffbdae43f6d7a6c02e0efa3ba07dccd0553d1676b918779d8fd768b80105ffa8b201d8f6d06fc31f35f73bc005f7d62803eebfaeebbaaeeb9ab4ce99ad7d1f33f4cf7ad6d57fbdd694863f6ad79fd6b3d77e3d1c741e0ece10f6c183c29f65ab3f2780fccaa486bc4182e65f1fe290b5c99db41e01e5a04b8983ac64f9a8238d6c49714e5c2ce10a57d8620915e3381a41deb4800062da7477840e8819923636b23b80a83b42f731c016b873f8f9e494522adff35c445ed94a61a3b047e86cdd52ad5d6b0d2aa07301d77badb556e778b0b7d65a6badb5deaeebbe76bc2c19608cde9a302d07c9280eea19641299a729ce21b4a594628b2db6886188f886c11a2a2ca5942dce106e8cc18f67fa794ba52545fe05e92d29822245349c41bc0cd9afcf5bde4ac9309d846471d319b2033159fc5e81436f410187d2060829929c8be174c44ca2255bbc0a54e4cd845d54aae676504a5b2d7b8d2b1823e7468c114f48504a96acc6d44c8d28a6523a744c7c350ed8041cb678bfc5f97d5d0e6f8b0e7644294240284b514acfb44cde78a87df9748e13db37f7438fb6ef05c8a84f93454712ece2001ce0b049a4f9f7da80c15d44b6f8d3245c7687985dbfca4ed35f8fb2650b8cc93b39fd3a640b1170d8a20d18cc65e2146d1b393988c459fc9bc8168db459f2a9dae214f0f53f330cc3340d9b5e2747fb4ab33e225bb4720a29454791fd4f4630956cc1be4e8972c4de3ff34203e4c66480419336c2a692d2260581116204753211514284bcb84dcbb0cbdd8bff41f0fe0f708f6699735e57dbb06ca35a7683dddc9beb86dedc544ba9b5b49bb397bd21c25a50b6b46e52d5351b60a48fa571623f1f97443e1f299ad943d9ff1311204524c0069039fa23c1cd9fec946ab4bd99a513f73f3593e56252b22a6b7dcc10462201e1c4aa5cec9d728a2bb41047403a2bb4469977c375b0d65a2b37046cd61b030ea52a880b40c0250292021234df09981f612a29542b2dc6184b95cbbd5dca908045cc8c9dc2904c594832b5d5869dadfdaaccd7e5c5b0eef46906017d4cbb4f82c39416fe20d191dd52ca29e56782e07fee618309ecc9eea3cf07046b3029606b4a29a5df430819e7ba7ed2c3f140a574efde8c506bad986e56f835e24894843e3ca4a807077c7c0088203eb339ce5f1e77bb65578e87fb1a67e79433e38446e494cb041ccab1d29107c692decd411ca3a361e3268a838dcab28611298d5d21411de0e7068e04f8e0b2a4c965adadb5624b2291bc2f30c8e206d8e1eacb929ad2a95d5b4f8dd65a06ecd9088e6b02bb026949279029b0a6cbbe204f5ac17a53a38c20786f0d0b3504dadedd9a95c07b7fb45a4a29a594526abfbbed7811a1d4dd2a548c9db13536a3a59173ce19ca462ea5943e9234642ffb7b12448304fd3d09a26c14528a3e9fc24a919d63aaa8cdd2bf7fad0782f97d068a61d88f7afdb42707dd8a0e1ab1289b9a1fcde69c73ce3967f6b94c161f1b85a2b4b552d26e300355abd629d12619a314d590bb8e933ac83e0d1670ffcc611db9aeb5d65aeb65ebaa66066a6cf15a5d97102d831021a3740a674bb997f3bfdaa2c072947dadf5baaeeb7ac971385fb77d3e1a0862d7b7eab81eaeebeab6ab1edde3e559172b2419569421c3c6482428254b569ef2195b93fd65c897a2152bce10a5488ef312e20be8deff8271d0ac6faf530a4a76e996c6419c83b6f7b7350ed2ec85a1d279c7ef6fad2d2243f546b2b8146196c898cf909d0c32de6f96f1d913c8902143860c192f63e5ca7478733cd49b1919efaf4171500cb165ed8ad779860cafb6bc0ac5c17e189e55f13a9e15823d5b4af1ec108e674df664915894556263ac8c8376891d2d8d83ab9aceb3acc9b2429ae1da139a94f22f8ed1d1b8a103c441d2eeee6f09ecd65eddf6765ffb841def782f103c7a70c0c7071c24859050aeec5eebc8cd7b91a9130c61b4fd7db961aa220565c4fde60149400f46db6bde17389423105a032b8a8cb62f097881e3a770ffedec002ba1eaa96553d3a6015a3b30bd964d94b43116e5d76bab84c86851d7375e2f0a7befbdd7f3e6c991777c3828b4a80f38c83f630f182c928859be60544ae283110a28e4eb5a24d9dfed4cf66fa2c4ca7013904d6eb857b5e9b62e471e18766da5938b82c3f4dc78581e1b8f134fcb038586101a261aa5ec4f834423080d22d97fd2eef6f4c0659595ca8a524ab3189c554be7b43694b0a104a63f3595558d83d86a295c835931d8d3dfd9a3529355aecacac3b2a13543786583170460d96023451aeb26dbe024fbd360c312d9df86920d2fb2bf0d1b1a8e647f4ff44eb7dfc39222abb2c24770d8417945246806114f94220d34a30909fa879e911938789514613f630cd9bf06f1f2567855e398e520ec2096821469b28589cc816d5709cf35838883f0e8339a9020ec04b9c24138630ca1caaa48f6d74607d529700715aaac623096bf8a55f61a8ae41a44d9e25965fb7d1346c8d70fd12af5ef45e382ec160a2fb29fa0cf30dabeaa9a2c4f68b25f28326d714d70e86179284f8983aa8795ddc3f2b0aeab8e34ab1a1c5299ab3ce9b4a7bf1e3cf70c61241d3c244d4f29a5fc70b27cd0736c9d83bf740a94cc400823200b78e28a2546f6e5773201d7cb1cd6b000983bba1400038eaeef455221ca08480c28236b0019fa48d1cd5ebd5d072aa5fcce81c98d33bf4f16708803e10f0238823832810282a446402612e348fb10c4c84e685f11e0675fc79a488ca3edb30fbb2f6c1f0e50014152a310878b0f168b75af96b19aa47441a51de6a6a39082384812f1218ea4d5fa7ca4fc7c66e85e8cff3598ad9f24459fcf07c49f564b8a14d02d29eabccd10f6a8ab5533cf6b82b5cf435f7b2346d8e7a1df4b12fa2f9f0fdfcbf59a80a980c36e81335d051c76ab4739539a80ed78bf1aeca473f8118d85ce5a8daa548ec91e762bf493765d970d396c980ecb36f6b3ec2792c59dc465fa35be02639f7debf321fba64891c133f4f9b45a9f96c719c1b6cb58163cb20f5abd72d83040d8de41926e853d041cb658adb558ab85a9cc8042b6b7cd1e7df92104101fc8fd1cc8dd238738cca697278259af9417b59eb416ebc66e173dc28830a52126904c9d1ac98ced39b91d5886653158ce093361661892ee013abf7e941da49459645c0536e97777c334cca8448886c30cbd9752ef0a38ac37550c5d49f5c669e4b0de5821ee94524aa96a098d1c5e27f9de7b1365b44f9053ca963de79c73ce8997e0ebed7be370992c3ee5a8d26cfb938087095c3f1d3730c1dd9c5dbb7badb5ef123458564359aba9503132a91907491b6dd468ecb5620aad983acb564cd55ed7755dd775594c5e97b517263d113466ad7d6dc534439a632d9b568438e82b301d530f300d2612549d388d95146d5fb940a326bb178eb08249f6a7612545f79b742f883da80658bdd0246b859f9e64eddfbe7f0d6b49a19f2c13d99f90382d94671f36ad98f25d3149917dcd9b292fec1deecefd9da1ba72967e775c6d349486cab2282d2837acce18348c1dd1b574f9dca0fdb97241490edfdd5b60d35c976865d511d3d9aa574c3967cf9652823c12ecfecaef2cfe3924e8efd393f28a2364c8c7f45e02f31a66b294268b49b6489983481109fa33f1b17c7c2916edeeb6d6d660611103278ec50b887c9aa2b070c1921c766d9f216cacd7c899b22c935266db0d1c09a874be1cb74f866d5e678dd5c4411b270eda15146089aea0285d51ada05662566456522b332b352b362be30acd8a93ec4f653f953fc34ba5a4df1cb52ba81b505224adb85096446f20453d041f406171b08262e2834c3f547d02afa0b207801480209f15d40a6a05552b789f90a4846271ccd0d75abb7348fcb2c5bf4f0a2c6a000e0648d07c77c781e3de550d8b7484a3503132a9991a1bd6484329a56d62c2d42813110785397c7ef0017dce6951286bc59b0512255b04d902091743f2086e16410a1660b46aadf3344bd3241a9151a5504a6477a752a9542a954aa552a9542a4529ad61054cbbbb692a954aa52edc7d7f9aa73ef7f8b7ef6586152eb819bd00e9846194a41f48e7c0c888f3468cb6dfbe174ffdf0d726f17ba932182151479c2f49f61b0f3cb8af4bb3244537260ce42ccd215254bf4bfdac01f7cdd22cdd590a53ea9198d9441415f0d1f65d2649f412b299901f7691691ae2a0142607c9b771046b3f4b59be5660c9dd00c3a563fea839fb3cf5656e95a77e3dd329227846e1d7755dd72ccdd236c268552332576982985aa5544b461a2737ad6ed251ac0c19365253c84e4a8a1090b38e49f6ce02cb37505e130017d87eddaeedbab87edaa27813e5e6eb966cb1e9616620b6c0f60b716ca9d40ea9190fdd6f92aba8998226a59a29428f34d52a07adc5816388ce9d4a7d4960fa49755bc0ad9aa11f76ea934aa5ae4b45e41cb1f6e686084cc4cd0dd58270100807afcbfba2f378248a29e01b60c0df441491de51784ec0a1bcc9420421de6b735d17c773b1aa1d13cb3ec4f2e7574f6bafb6d6aa6999e7190807613f5ffb9ae4a0e739bf17793321c0a409064170ebde7018b4948a555575ec2c6daa131b24fbcb7afd5e8cbb4ed69e73085b6b0ff103cf1cfe942d32077ffbf980a0ead61a83331654154b15787e1738acaa6c22525555652dcd4a4b6930f8481db113d3113ba70e920eaaa3a4b3a4b3eaa43a331dd9ddf7fe8bdefe077c51fcacfd6ffb9a94a0f9d6ca1cea1756265382e8dbd7eebdd65a6badd73967b78e583ba227de4b841475eec81bfb756274287e1c52b4ea14e91ce944d191a2237644dbc3e22fc4aab5b62376c47bc71ad647ea1861914c24d931621b6999963c00c9e22f3d94019912c2fe89112f1cf31e415624921471242942003502ce02befe76866dabd58fead2d669fb37f5fa354c101c5e143cbfada8944422594bd361652556bd61d938694111622ad92044288b45b529606d955d1bbbbb291d6f0aa594d2ebba2e4d0ac9e2af4d917d458b912d2ee894fc3ba5393ba552a794afe6703ce72e8e674797b783c3f1e8c5f126beb81e500ea232154a1ee2c7cdd80ca5bc7f75d2baafa578ceba977559d995e2d951e6ed90f9ba3e85f3a17685ecaf8d1f5e6d4cf128eb5ed66565578a3747da384395c5d2469636b2ee655d5676711cceb579aaab5d557655acca929365db3cc60f023a5c8753bf6eb5f3eba1ff47cdf62da97ed6b6c5beb0b644d18a1100b313d937d7ddf56686b2b75fa94693712fa89dbbd7140048167fb05b823b1b27d6b69ed083121746b858821d516bad18638c31feb07aefe2038a5a73286df00cb9a8546088391e6456d9c002dbdc9f8bd8a8d911efcb7967db4c2a9eda8883d7e8e0ca9304ee1cf41ba280c58e9400909eacd6da7b5d775543c23226128c90d210243128d188eceea6739bdacfd3fc7c48fff98060d78d4b6652314a8894864c9214f59ca7498a7992f64dd264710293425826fb28f499eca12fa1c9ee2e47dafbfbea03761dc6ac21f39174e7229324769db366a84f2767b1ba50abf5d74ea0f31c6130e44e2d87b215812c4fc0497946e006987b4f3bbabb3112864dd30cdd28cd298339e79c734eecc298266992eed532182c1a3a50a15c26355363c31a69e6ecbaaeebba4e08324cef5e8c5fe331433e6aa1545051c850c35c6215a69214d95f747053027e37e2e0c9c11923850cb50d97f2e02a262605d9bfcb025791dda7709b6ba3027fedefcecf515d7f7efd1a06316405b84b327228736d7f391e64fe7cc091e6f985af69da1d713994ad1eeadf77d40c8517fb3a3b884ffd0bfb897533d43029301f783df6bd45cd100c47c150b9b7f3c1a474606e92a33ac6ac724e4e9f4e319e73bc8e9921771358fa09d3f94d4c0ab2e8aac053647feef3d93d0d07611a06069b73d63a6796655cad2854ad1c8c92e6346064649a00c5093353e8eb72919a8d2560bb044cb32f016399c506787e8f015fcac202ec722f0b1358ca16ebc28345091c76ddddb4d69a612ed91d3bb3c2c7ebbae425ad94224f14dcdaded6ed5d472ae5ee1a462261586d92b1d4b09c6844a4838610011052be6f839b5b6f9ac712011052ce3e1fa683649e12f489657f1e39647f2226f71bfe784568dc73fede7b2fa7719ed37ed37efb1fb4ff817bcea7e33341113c52be16e0508e4524f121e5f117b13de78b4879fcdeef03fe946fced35f0538bffd0f9cef07fcf5e0bcc5e30bec9ae6c9d16734d27ae33c6d7b1e2f2f9c4f4ecb7d2fdba77d52057b60c815099a0fd6b899cc7a726aa67159a67d9635b1c19cb3eaaeebbaaeebbaaeebba6a5d11a58800b9ffcac15fa2838c4891e52e71b2f4775f5f98d22d7186fa090f728ba1c7c9d25cae9798fbfb6f1538ecf1fa1abbc44bc456351d095b410cd4d44e736aa9134a498c0c0d6ba55aa235c9fe73da50825edc9a21ecdef93e3d58e672783930f7875b0eea0087dac90b09aa4db08d145d5d60275a58223b3d42f6e7d848517ded2445ddc50d5a906638420ebcc8fefe35dc0cd7d47278ed12377861068ecd2907da49b6e0126e9d2a6e65a772a6b43e75df550cd4f6841a65d0c10633947a5fe08edee6fcae6aeebd3455758955ca5a2baeb5ce690306cf1cdeecbb977559978b7a3591fd9b90a2be86789709e3aeab4faf52bd5080c3b7cf9af7e5a41685aa7d6b7713d623ce623161924516554c11d69b1d76c861bdb99f65b19c47576a2dcd25a6246195e0a41933e718939a512d69d2b2e9965a86dd6bb3dff6f968f7661877ddff030137785b44dccc39e7b457a6dd3b53a9eeaef762dc75ff20f8f9e08889d1e1225b6cc949d4b72c5aa792898883da1a9151a5504a2ced6ed949d72417b8d65a2a49915d4286bac922457d44da22d9df3291bdbba96d6bb243ba52f655a9b3255b9ad1ba2d908fe3411c3e3724d063a6e6fef7bd6fa5bc32dbda3694b8f884ed875f6f5837f7afffc7301a3a6f5f5365d55a6b12f0bcf4c75565d12e82e8aa177631404abb1b0b29e595b7a90c692f676e7707388bb3847249ce3207ff06d0c84e8313300fdb474313b0067a50e186d5c9ff63f7de7bddb32cab61c996263662b68227352c6b2dca241a3921991955313256b6c9d47d279eddfd09eac8ff9a739bdd3ab4398b7f0c67714c5ae193f39d211f71f41b691cce73388f9ffb5e6a7061062f462f40649860d4263f028911d7f9cef7e2e9c75f07e918d7c11f891fb58ceb00802c8c90b0468c7878fae39ef3f569b2705f8b5b0ec236e998213992f9a5cf200499278c5e8070aa3832e2fc0b9001b860b4b90efe40fa8b168cb84ff15e3e47462f405ac988f349d70148e760c47d49b4a74f606a32b5c973dbedeba1ffba3f6ad63e8f7d99b1e7b1df764d264b0486dd6037d8a4947226d3e55635ac6669de6141a7d3e94818a2105775462e22d7900c254aeeae201dec5eb6d2140eb76959a7d3e1a4743a9d4ea7f31d189ab67158e8607f185e6795daaa5082c008290d319d90a094c4c8a432223768a2058d16363065289d4a2622a21119550aa564892d95582c97169c7ccc900b769122ae740f90fd491f14f009f0fdb04956fbac8390db07434042d83db0c97cb048ed7f79f5eb92e57670d925067749bec7072524d1050c48a491f679eac723cbbe97249e1f5efb5e9204a21ba8f40d7805b5642302000800000243150000200c0886c301b16840ae4b82ac0f14000d637c4a7a5640190944498cc3408aa214520611028c014300406086862600dca65ffa758d088e0c9fbb2a80223a854921dc88db41a38e19c71f2e639496a7f744dc657595975523788ce5a50ba1cf153e2dd552211c9e8bc5d80139f76d0c3e85146879db58f205aced32b4176d5bec0f53ca2e22834ca258ecdaafd24c10685e9ec86e1ed6d9e0008126fe3cf031cfce5c5d169523feabebd20e83ac87a92f953b9624ff57b6ca76a2438acb79f3b1fe96b20f5f6f1852f058bb1d9bc9fdaa614087ad612060e5c03733a5b038b1285a4564be626c8be87a89d94226cf7d2044cf5f9d66456fd05671fbc39b42e5f5e63eabc96d6f790938bff207bf97cf44a2aea26140a70d9f5d5e835580a85454019daa30a0cae0e2933ad423f897084c82f159f28844e09bf65ec415650a9d66c9c427207227f18de17dd4c24ac5a363f0c10c9e1d11845cf8618ff211116793ee4a6e27c7eec081c303b885b9459f5b7739aac05252485fb85f7bb52df86713599cabd5380d6eaa498a483c1ec3ace36930c8477924e2db8c9af4f6435178c5e0ee2d748feb9bec0a0ba42344cfd679604f3df7302488bc4b5552151b37fc8a50d5e9134145e439e6a472766e232c34e08b7a665d3171b582a4003dc6b3a69aa6b568f0430dda12d426c0119563a6846bf4da3c8d07495df82068dc87bf01029b123f8f5b1759afda636fea2f9f779e383506588cf88a2cb373b213e39ab97b7cd54c73700d11db4735437e444b95bc8228c4d7cee30d8e86c93c33f0a0a83d1d422463be6bc7458b48cac2cb1d1816054cf77c899fe3d25e251e7e7065a238bb477cbf1e2a1beadb856a4f542c7882bca20d9994d6dfce419c8164fe5b1a015a4ec39652e722804927eaa3742f24d7d9e159e4e102e263baf083ea3b7114d86197e454b7925e2e7e6ef1f9a159ab1d82f60f09f415b7f8cab9a3b0a7b2c53a95307116028b74b9a0603806115df12ab9f38e8be0a963080b5d848692c00e1a2f6cdabf922224b40bef60245afa354b958637c12cabd2205935d436b14ffcd727fb6762e3966993dc7747879ad4f8530cab94e7f0c2bdd86ce70f18be2f372da00fc5f4f314501cf851e897740e258dab24e1342231feb32478435ac707ae266404e513434b04a869a56922cca61eaa75c509f9a31e74345d81454d8a1cbb081ada731cdbb7d44f713f2391e3954aa386fd0048799eee1f41e403eb24546b78d05ba47656a447916807c372e413c2cd7800f878812309501c19597344adf556ceb5013eb46db954f5ed95429f072f5612ae78424b8c8fb08abce15e71c53ac698e65048d165bf16c097b30d47137b4bfa3caf8ed3f27021764caa4134c153c5533fc2df91043078433b635fc57f15301ec9693f567132862509e779b5399affa58001cb2ff4c371a259ac8aa3501a6b6a4db9c685fbbb337d8e8d014fb366d263b7ac644e50f73dcca9950b976f306a9a471ea58f9c66bc88d314150c3e55435794f18482e7cb367ea1001f220e7f96d591a2f71ebf00445fb9226f80a124c2f88f6419059732a1efb886fbfeb809b4936f70a98bb6e0aecc8ad095c093efdefbb857998afb56a3f4db20759d032ed6f3593d3c148d7663156ad9361f6411285d269b383cb258b5f4d23408f240347c6ef8422f4a60ee6759efcfaf45ecdbce013636b3d3924f66be24ed4efcb47ad48a5608ebd5cfcdac2fe9e8cd536261e21ebba14a827a4b49ce5412fbc77a63f661ad31950404e623c6f065ade08683c42a8b9b22a0d61dea5e2d945ca20a97f46b762e48ddd274c325bde1372ef9dd2cdc6277a892d79c9d0be94c44ac4adfc55cc8c600a1cba04f217989472d92c29364d7ffd6489be6d3f7629138a77a2d2431e931c4ac1f04ad56846f8f2639ddaf2b93746fbd3c4ef401222e153527cfca03b211a01a2a66759b6f929aec638d95011d567318ea67ec855e6784a80813c378295c48f8978aeb1e59d0472629d1c680d188f66f0a1a0ef320bc080546746602fd037a4dbfb87603dc0ec9c4e219a25e0e7d2708ce5adbdc12f912543eaad33921bc2ff158d7cbe9ca3d5894d5205442a6942b6996fca768dc09ae7856c02014577938adde74164ad09012d22ddce24110453ef2624a02df1e9a3e3b2abe3e99d6440556456c4eeb4364e4588a6a22e67f29f2c75c2522fe02a3f5e31fe5557f4700509afc185566af0cd0e26a2c86b7b745c5294c922949156fa354802f8d5a5732530344c3ea36af71e1decfcac3274ce67b1a92b8e2a609e93c83ca5cb208d27b90c0be62138e6466130223993f29436551884f9a2e3488d79b6e2ed1e90eda73d2899587094409d8b7d85f4338d286723395811cb14b0212ee4753d6b85beb09eae7625681bc50eae7e459784af48844cd13d661f588a0b3a5b8cbab5f9c9933b367a3d2fc14f57418b81a8926017dc693d3526d1cd8b1a01c6693138a98d8a78572c152eeb0455bcafb5136a3f6e5ee8730371b612533ff28fe3b62387b48f7d6b5d728ca4077bc44086bb052d6418fc1c17a3d042b71f54b1017b6e25e61940cde3992ec4273a808556e072c2cff02eabe4d01aa7b9bd683fafdf963d447c5c266b5efa0f6764e7627db79d2bd64bffa67069fefbee62c754c0d3921492457b3856cda2ed310777b26d8190a3eaf569ba6ac559d08b9956f9c898e0d4961ecc3ba5793f36caa0ba866c0b773d05f35d87fe5470ea4cbe25121e649b035dd0377a545fc775b507e1a2fe8fea1eee09c20b45d227cc0e2d735f239bab14a719dc93c3c1578024f2b469223e1171a5e2534202fed853be3c860cf879e7c6fce99e184899c61753b2ae5a4e8c9e2f7f634d17b3d5dbd6697210c5653d3d59bc59f9678ca31c04c0c558832a6c68d842d5d6439667625dced9c32e719c4021d6147f6797646bab974e70846b07041fc99f052b1081dcf8cc66c34729d0bee04a8c08b15007aaffacfd237f4c6edd418fe038be65b6f238ad40abdd791ab5a218494184291e2afddf65530f8fb4e341b104263177892bfd5703fc4ad75b595e0698bc161787549da67a43e360bd12f5a85b5c27989954dc45df959980ec6820c85a94fac897ee793bcd8ac0af34187ed1321f9fa308297e8b6f3a3680aeda7cef416bd52a5bba20c8be3ed0cd2b2a818e95e6fc74577ae1e64d27129f866d813cfa6e50b4c26469b7acc61b32e6d95d854660f124f0fc410a36737927221ddb78c6d7fe67ee789655a3f047b8fc565b246d8b22d66d80b70e8c0d00ff61013c8784ba7af8dec22e8b6aec01e5896410c2636db3d2e6059bf1c9f03eedc48f920a5bc9b3110bc1011ae47b90a853eaf3233d832948cbd12b38a2492ff088b8c0608b2671dcae971724df25607de094727c9a8fa01d0c1e9924f4c7c947e284161aa94ee1e510f4661cd7870fc271f7490d8f531cb87d22d075a481755b4d3836433b0814083a00e8da726ef12483ef84578debc5b52667da3af290666687731de0a5a01d8ca3376e290e485dc899514a6ba077709fd23e1bccc66a55e6d95ad0295076942ff35af2efca1bc4e2e1bd188cced66041a5b75a1448e40322c89ee08efdc8a47f252618c41aef71398f4ac34e83f182eb139b1b14dc62014412f429d30a4602c19da5dd8104800a4733bcbcc0e90e42826c0021e7099287b348da5b05765f1b12460daab3472bfa4cf145a17ad339bfc8a868d630cd7b898b3d512bc5fd1f418b5160502e98e37ce8d98489c87e58040dc82eea49133f5ffa317f88bb8e74683d25ead83604dd46d9c5122b831768908cf0881ec369ca3041196b53324e7bd917e39731ab62af37ab3e7d83a43ab6fd48cdc2cef381944fde011b05e667423f353067c3739f64f5be0bcd320045a16919e7186e418085350c66b8411d4f7289b8beeec6b2b37e55b0e855d7bdec2629576ffa6453ab8a6a933cd195bb78a5202cc5abc26e0285aa55097392afe92009d8c9b2283d7d913ec740c9bbb98906469bbf3ac36d051bef3582b0422633790c6888117da680900db163eed28462c0c0a57763174b560560e3f9bee6e8b6df1d572a6fba1bbb673a0cc55d27eb9ac002c67d0179359dbc5cf102d0d8e411287b6aaaf2345c028e11efba3aabce7722f4f91191248f472df8370e7fdd8b122369ca2a39ae310e2c020b967c9a9aded74ab0ea4d032da1408f987a3364bb6a99590c60fb615093a29f342741b935e82b0325bed9582a1f9bf1f9e02b47060707b03ab3fa7833f60e878560871ac603fca29143b443dd88af70b661e7d46bb35aa6af3d45efb3816150237b5f6404954950ba686712464374c505aa4490a6edd3c022f46d6876ee1c36ac98663000730e3b4d412cc1f4e4a3461ff5fc88f2d46267a643e60a00aabe54eac9eec1e3c41656de54d4cb8a528eff3cfb14c64018a3d89a39252af20b55cd335db7290da8ace21ebcab9ba2599542a5f7e4ef3d7a2805cf728e612b1f2f2ca7d335402a29d4f476d1898d5d1e4e420c343d6d880a7fdcab37410d4f7d1eb7df8cab26e60ab802a3414a5b4fdd11b9da55c13b4292d1e9f00749c73e27a3041663263e4f2409acb2bb7cfb0acf359c23b06d6f5e9fe5c0f54e9fa8fb4d058bddebaa05d6e226aec3affb3fbb7e65434477b5b335373fd4446bdbded304b764c5648c2c21ecf93b707c6dd96b3bc7bffdc6d057e53707e52186ac9e6d3db40ce74720e7c0d5579edd483f531c4e2c73863c63c152bc6c72bb54b9efd72a47db6d758c34bc053b1e254d56cd97ae2c54daf01c599c58de1522dcced93e78c9b7835e9b3404cd2c60941bd990ffc9e4e4ecd5234ac2e942faf11e3fec7187fdff51ba722e0465d3715ed34311f90b50b348aba084f1c367dfe2f24158c8e3a6b2ef382acace0d62f936ab42b1caf4381eff65d2b3048088af15adeeda97c06fa7cabdce6802ebd07794e23052f4bf6049f5d86fa5b10f58b5c4093c0ec420222890acb675ba14c9c647db86006f28ff875bc0c263257eabc4538b1498f909dc8223cd90bfcef706069ffef871119b96c6f5d5021290aba2f81da860a507527525baf514389fd3e1a6d8a0634c7da9d5139428e0bfa6bd07a0bdd2ed4c7fa34dc9a72c08100ea06bc5392e744965c66bf8e8d87a9e2f3f65073d7ed77305b7d402a6040a361b23fe1fa3779c425ebd2f947bd4c32576c983ff5a069756907df4246d66ba5858d32905b47e0d320a81c5d92e08d5c26c7d806cb11f4fe7781545a715187649ae8e6f7dbb8c0d4ed0b2a4831425f3183de507f8f339e97ba7e2dc6a9ee732fc2bc6c095d9ebb9219e48acf28ad323176cd0036bc7566133e3e181eced13f7e08c17c07939c2ee903017be4d6e65eb81d8a664cde9e1359738734ca22f4beed2d42d512ce3854f6c2916405b329d7635b33017edfebe362cb28bd47f6015d37059fc02a873833b6974deff97e7d97fd4233e1aae5a5a43ed1fa7024a8dbeaf1b972b9df3dac6eac548106026bc49e2607877460f03a89d0f486a3986ac406478737e30006fac5a03065c9ce86c1d6fb40fb15d679f15aa4e1afac2363f3916a7c57fb2ba997caaf5b4d74db016b0c3499a25957dcf2234225681320972b08fffee2e07caa71fefcd81679ab92f13d752833e412229bbd61696bcd7b2e124f0c025098129744000111f2fd7534be547cd1c466de31fd9c019b3992cab9ea1d5eb8c58767a65ec83ad64d29a76978d77ae013ec4576e8655341483eb70527d078c36577985422be8e3204052bf33424cb9816ea134beff251b89d04fa7b5c019b2dea3c7177bbf82bcb983eb1ab8e9ad8c26b53e0dcf38960c53a8f244cf162ab14162eac46987606c1269e477c80af59f1f387e9bc5fb8326a3f8a77425e2d0c41c7c13438d14a36550c4b6e9e99e0296790a4886fdea0605710290d93584ae999490fbabbe9d18ac2b7f4bcbca066dbf6f1cec0ea70b229036f8d0fd968765f3412c347fd23b83de97d08e7532004ca689eed308314864c334d16de4258c7006e7361c5683f7b6b4c01b48e923365140e90b195f21ca00c40608c5898aa06045b05c70d329c931068c1db40f70947efa93c8bf41ad16c85e5342f44643eb916072e6ba84b545c88ae80d9f7b2861a15a85cf8952e338ed2b772632b8a7e13b253c187b0484ff90d91027871936d1b99393489130e5379f220917b7a2e1917a315d42379454212e7b01a877725040f88a3d685485ab138609ec0c74318071dc15ea384e427e2ff4a1c273789b1977568a6c8662d121c2c622aceb5306a2ad509b760f57f98de39ae1f851b5fb3ce84f60f82751536a8a341950e2ddad0c5bdbcd1634b72614b66cff13aca80b4d70399c28828b34ed69acde3386e1a56d87ee30c354c7a4c53658d6f457d44e1d2b2fb2dc90a1c102a274afbf0d32363bd702fb722fa3a3ff2c5a011e04a0e65b17415086b0302b6824c70fab9f7007442813ffe630be123f19fd7041d1f9885f9df266157acda0ce1b00208171c0bf2ff16c374465707aef66c9a8cbe63d0701cc618264c0e279b154d3d0fa8b2645c8bc9f8bcc7f16b4b18acc1312c0e540bfa37610d2d8bdde03e41994bd98db3835de83b47388652039b940d45c0d775812e16461c2c9dc74fb249a5932851dd4b29420faf416f77937f297970f5067ed0eaf02dc15982f9ad12c2559fe597bc05cfec648e25ef4dd4b39a0b7ca8088c2c93d2994d364e2a3afd9a9e1a4e18d08425191484e6ac2fe4b400b844795fb01a6c88eb122acefa225b1a771f1babe0bd6e31dd8ea8a4eb365ab8d60c4b136e02eec49b21a324421b76c2940ad32e177f5a7c6c8671ce3a7483c268e1497d002483503316f2b12516a44df873098384413d6d41369ab7af21a886808235217a5adad1e0e6e5fc08c851b695870c3f76676a978b981610b072f691c5e1c4e58659deb01d3452e72ea29620831e152bc805db5c94c184e785cc05d9d31435e1f11d86c629d126c440e05c10ca69924043e1a0a3b18620ce7ffe6e6bb10a8da1c64733c1ffa13504b52bc7c4562b5a2306f22c9dcde131d04546c15c4e0ebd90bbfc03dc7d07e49240974e6d09ee023208ae7d272f57f29389770e5f10e29f044b583588b7e43c364aabf9e81d013f5cb82c38a08574a3963c404a8975c57c8ff992211f919ebf61e7938a2e43c306e2e71ef378967954a4cc1109ac28fe20bb1ca1accb194d44511c5313ef3950953c3b2360cf49514b144cb413ac4966338761b4d8455f696108ceeedcd911a8841bfbcb47dadb18f08249c2149270f2ecb4cd9e4b6933b80cc7039c670453423922a79ae7efddbffb5da7e158a206c259ca883c4a5576934f4b8d21ccafe2235b1e3d11b1f57d31339a204dd57cee0df44a86cf26522d50ea5bf440838265fece68130c7a551fc6131d404aca620403887df098915b6cd8a0aef16f93ae0383adc37eb640fa8b6b2f9cb9ce64b2ec43664a49c114ddab5807e67f4dc4bcfcaec131b2d04ce73996e0e4a16e396581e4dfe561b82278817c46366623a16e85f0d3ea00fdeb12fc22528e330978888a84bf6c9841a26ae1bec9bad7352d1ce392d6d348f307896e2d01cf7a4744b97729972ea6d6f0a23fe51b0fbccfaf7df5e2ea803e4b067f12030b502e368ee0e306c022c35b315677961858a42009bcdd172a222d8a1166f066dbbc45e0b2909a4ee9140162ea67c3847873b15c78b9f32bf32acbec64488ffe6a4ae4dbbc20e7319b345902ec07f0dc23ba292cc9c4190550abc3419b00f2210232ae6a7856583f8cfe692cb5049a8495c91a109f4394f0d557685d6e0a58a3965f21253bf954277576697410d2f12d5594731d30e9dfd5ea14d8063cef82149ff2a3f1cafba9cd26e869a7212c8031fc5d0114c0448146ffea766c61eec9684e3b3f887a27e58668cc45d71ff4a80a5ad0239a126abdb3dbe73623c95b374d2837c18386418046b507cd24a641d44f9b6a733deca929687c1c03af9da869fb0f3dfe75861951bb9b48894693c482c743c1a3e8eaafcb527208229ffc0562e8c7b3d4588f0d799fbb440af6388d289101d756516d7abd923fe82b2f8ad290bdc29dc9b5f5fe377e2b9312a5c0972abea62589b651b02f5a3a6af577e97e0917f8372c81eda93868926a9f94faabbeec74a902e901942873ccdd12305ccd8cd36cdb6381e450e84073840a6056e8cb3866ab64137e63e8d9ab2e155185b84daab0cb0a7b124900f31d2cc40724d9176d6eb0eca4c7680716d32e6d25745c235b1097df9822d50317c5bb866927415cb6f93fb7b244fde84cfb312e3d7147cd202d7d320e023c51e4c54131209b718884231ab409349e4fd6b84b00d3f71251438e458d3a7b441397a2f54230387d6e0cc1d49f980313d93fb03e18969451684d0375bf026426813ec447da0da7db103653494ae00bbdbcdd2d39c70d35040a23c7ed2eebb4e07872619789d032bf9bcc9a57e0e585852e07b7c464bff65e5a517475f8b5a1719f83769868bbbf8a3c9996aebb049a7a5bae9b5c32d21b4df4ee45afa3b178b863c4f568705b2a4698045c824bb5086725a09555e17f6886a46144ba6585bec824d05a30b0e9e428a35ff3632e6e2ac3c8f6fc85d1d1482ac83930f0e05e31971d965079e971ed5429b149e34d0341250a564d24349c0e157a45fdd71ea7ee0608647d75fc7e563a71279db41127fd7d77d52e86df4ea9f721fe9576b6b38c93a90c489960b8f0ae6b30ec7a2afd60ca3d5264cb5d300c1eea8f8e098b4a0a6f4c7eecab23708b92db7cd928120c49d5aadb47bb7113e3e30fc89971c4d48482bf38e73ab635724bb3828c815ecb9130da3384adc3b03207123a8e4fce8ed5c58abbba9bb1373adcddb19e16b6af963d83a8277c7d84e6657459cf21acb8a6807341113d56918f310209e990185f2944a238735c80c0ccf6d52d1a94137a06b8e4c342f7e7405f104cdf8d14477b9f0c82bd03a5056edc4702a5a11d41b50ad7cbe5426eae6311b9b993514d918e445568966191e26b3f561f821b8c408d8938454eb267d9d42112260cde13ce2f9899b65dbdede9b8539f971275f47cadf3501604e12c08b353ad1e3ab52a58147102eb55ea495031d7ebea8bbc4807409748c67a69545a40d4d4c14572986d7321034cfd14065d2590cfcbb701aac6fc28caeee8ccbcd1ead3af68d6ef0ff97b7f85e9a28a96b71653b947631d8bcce23bb020a1d574e6449c24ccd1d719907c034ded12d921ad74167c2a032497daaae46518ec17129ad7096fc50c91c667a3d30a97f6a856b8d390c3a280908f5575754ed4399b4bf8e33d9e764e9dab3bf0c95a5fdd319ea045ef1718c692d3009686f43222f41dad53c48d33f5ff5230b41ac9e75fe51f91fc5e85bccbb9676cf96a93150935f75e7eef55a7d1e0e3a613380ffcb1ca2b614821eebdaa6f832b842ebb91567741a8f9e5d84f189e41d4cb65eeb94100c8f7093d295b0daa1283608027f55f7474041c9a5a1cfb6805b65d50f019ce5a99232e2e3140e31d5d57edcd03432f70ff48d77759ef8bea1cb01d099be4a889bca5939c33fd3e0daa6ed8dc4768b0668ae6f3db3e6fd1cbb6a85da56340094e7d1ffc325670f84a5ee4939923ee192ca40e79971bb8625f57fd5aca4dd229b6e6d454c6f974cbda939aa74bb681ea6d293f1f5df2a254303b7f2e2f40924121125e431605dbbbda93bc410073b86d62bac7d3f53c8ae615b2c2363c02475b861d192b2eb4b442d11cca5bf2bb6c940842f3b0394cc3d411cc44eb5c3de4a16ef4aa0e707d0f3a0b4859f992eef6a36c8154428de03e35c08353d4998a327117fa90faf926508d3ef5507421d22c49c9430e382d266116ad88426a0a5b8da7f4550da15793560a5d3c9bfa1fdc808b778d396d5da9467b8d523dec1b638a206bd7d8884c1b535bbeaec642ea6ead7d3b9f167c13711999166d5f05ed61e8ee4cd4f033705008988638f212ee2b3e8ed5ff4396f7fc8ca4dabaa1ac050c08131520b613c31dd9834052860b3dd4669230546b030b3eab684e9a68a10f8363acba1a7f965d89761272efd0cb4f0f5a1f6efecb2d8a80ea985f1d18f39ed333b420e9cfcf37eca297b804abd844194bae15dd07d802835f43c714674bb15d2fd8dea5cb80a974a0b5ba029483595970d8e1f29022b5686930b1532c97514ee8c1e3d750ac8830b55403f39dfb40ddc8de23d000cb311bd73d5ffeb4a43efc2681296d11279832c626bd84de5a0c515040aa587c46db2cd3d38f66bd1e9752ae2e2d6a4f0d1f0068a03675e5c0474d87f3a40631bc348cce9ec056349d83dff1fb7912792ab4bd8970216b593a0e3753a1f07dd457b84315836334c43f725aaa2d97398d9922d55981c1100686b8812a529d5e56a4d11b3ebaa48d820f5dd509a195f645cab2ab92061fa3601a4494aeb442010f76d41da9155b55d9b714aa089f00cf7247fa4a542a76374f888f1c6c8b69a010dbee65c865bf30229eab1008d4a522a2fe399648728359af7813874ea790e8af9638dd98b8bd6f33104db55108820cb9f9ac6f6e6c3de30a66fe8c7efce94ead3ca9382172e4b8a5b96fd349e0f3099908f32ea59d821c6ac463dc6a6744da57d97baf7892d5e29873b7d9528f94a76ffa8e8c1d930045f45c426af0cc6d4bb7057da85a4fcadb2d38b2b42e49b25eae4ccb394a3d8eec78e1c2ad068240fbd1208dc8ed7ac96d19d4667ff89ca46f97688558c8ca9f1194e098d436c8569962633eeb0154cc38cbd13479305c2e64be2483022cb54e7c79e96a6e32369a02ccdd69007ae7f647f0b7cda410315302bb08f774e6a2f63b07c6739f936d32bf41aa50e4096f925e9d3b7622268747a585c5e268147084729f879863b597b32cb26dc712570f64b1f19ce649b6c82f9f260e19dbba5a636fc4503cd68bc54b1574c304cc56537e65d9feda0a9e93ef4d385d9907d54e0794a261a999b4bea271e8ed3568c2f7b0c097d5e3487f374b1421d6fcb5f1089cc4003fab1de4b035776545b50c8d7c2bd3f4b10990a629c028e0d5596adaec7b5e2d8d9d2e3c9530c20081337a559fec08b1185d515287e3397c72bf4a94f852b7e1b6c64b6b3d0d598246ae273045373fd8c0825e91a67592c92c5b8065c49cab3e0703e430fae4b3c14d55bfaae26516f6bc715057071a972a01f43198d4d37a64981bbd19c77662b502ea6d30694368d41dcc72e6ba3af115a127d947a2b8bd2f3d8de49af3ae85262dd7d26ff4f1703d50649301e7850add0a194c12c6781fbba0eaccb698a2d4aa766c588f183f0b4b0ba52b008210e5165579f47bc064acbf9208a6907bfd4d4d411792e888620e6fdf2a708ac9d1730e1bef4ee2290935b94a3c097b6756b5b70c4e6d1734abf96005b90cc641f07904f2b994d718b0ed473eba06098110694b552e9b99696771333f65586e70adf7e20c5a45316ce6179ed2e77cbc6f28a78ac01fe0ef14e2d18260b50309745686da85871dc194f00c116e9402b320acbf6070db0cdd54f9c4c7798f355b2a4dadbff1193bd803ccd0e64d06461737987e0a393b2d302808c01971565fd2fcca723a5e5fc3710c068cefda4df6a2497c4a059bf031102c58f64b519c71c0e17d1ce432d523892541d4f0ff2dba07383dfe11b300a785b0481797d595ae2f396b20303299a82a47e6f670b0e7771d69ed98283d498284b1d540b42f0dfe1223b54e632a24a643a40a886070f45f660cde023fff568554a05b823c7717a34a4aa9a91669cfa92860905ecc1c5443b3a354269933f2701e95f284ae026366dcf192a5802b9840d7148f72e3f344279418333f250a339155b1faaa8ac140ad732c0c6244c19f028d6a75cd919f1f2e8969da6f28556b751c0496f89da49529ddf6c9e8397ed50587198a494007ccf6f69187c5699d47d40e3f18b4bfe4328aa65d48ff086bf90d0b538b0624e248c39d6a28ddb4466b35358e33337bf83d841c12de1fd4973f8914023d4d72c4230fdbc1704be31c781f5670ecd7793736d598568e9627f7f84d6414bd04ebf7cf2e7b686bcadb4f4d7f90f958e2184f56dddbf225536d11026865137c20bd6ceaeb6718084205f53e75611c1a56eca30a2b4129d8a1ed0722712ec85e9d33533d79c0b9cde5abbf42e831c33a6bef3c08fa8b524766ac0b40050405a000b89550f26bb141f5a319646109a94df15967c4200d7bdd714d3b871dbca281af1ce3ed4b3a78739979a5ffbe786235409f2507f22d80aeb4432c3fc8ae704f93f449303f58ccde1cf5f2cb0fdf7cf0461f86e89993cb91e729b4146c5ab15cd3d99b4bb101d3c6cff0944e22a0fb452e3e146051e1f0d8544730eb96e959a1489f88966da159dcb9c498a2bb6d879a203be30e35e385365bf848ec3932984c9f7f90a8abd8d160bb362dfdaf3d48ffc2ca7c3df8017f1f42db336a32c9322ea909b3aa7d69951e51034a3163e5f8838e368b5b061da8f42a29cc29fad8c94412ff64d815bb6260c47cd0b9cd41ca1a8970211a6557980f1a1454a63d3581a4ada8994646b056d38a834dcae9767b2dcf37320944992b1bc3696eeb22d280b81fe4cbd2135ee3047b3a18724c8d32670d652615857030e35f5acff416c2eddd42b1e3c0edafcb03078f8c16619787d446f8cecc7472b6471b6edc7b8ba37be28e91ea429b8761fd8a7256cee8c42590f70032c781162b62c86c65e5be9f2de9e9d49be23ded5a1b1901bdc5913e0ca4a138a38403d9dc0ed1ebbf155910ee3a8a3b9659232568896bdad6154e6b328d4bf42bf97b69e0fa24f2f2ecb993618a1cab429b6d2eb5c68ae6776baaf9a3803dbbaab0a79eb021c3469715ed315fdae932cf5c8e95e0238aad7114b4d3b6d1daab75bbbf2e579cb26bb53f5bb35377cded2a960b5b0e5b54f4ece9235172f67eb6e9a7a473cc8e3e45ff7904529b370f7302368cf72da7071379b5c00692407945acca2ce40f5f81e4c0e1712b1471923e8ffc1067eb70c5a54a7b50402f2e7522a333e6a428ac8be5263cb2bf88d2dd8aeccbbf3cead12f2d1ed4f56bff673d3940ee2fbe9e2cb955bb1027abc00c4153f8774b531ab953c70c964ae668af1dfcf70f3875d80f72deed8e0fad791a9ca641eaa2aa428483c1d1324ef87f13a9e73da80a4e47ddf00dfcd6ff5430592f1807b89f8373eb65760f0e85c0ad6db55396c5e2f6ac6878108f26813a225d205695f843e046bd5bd9bb1a9c21e2c5d28dd65f8141e9b9b358990e212fe144ab700656078a66c2a8a347b0d3684fd2348e7e775b9250414d3442e6dde27bbeb99de7fdcd8a9ad6517f5c6b3861997d4a30a5b6b4fc3aa2a4ef6b9195c2aee81fd42bc696a929dc805644c01348118e171e747723440144d41da33b8871f872ace86689bf8fdf3b670238d00d03f2243565f80a720a8d2b741a7a00eae1b5401963a1715d1a982bdd4482bd0a6afad0c47a837c4f1c94f8c0009357ca3f498438627fae4b9823e79d8cab766db3380c0dc8455e31421852c744a91e9be55d3dc4ec45704d0b5523f3689fb2cf7992231f9eeb0a7d7ce6809f08971bd367b3747f3e830a4ebb4a747b2001fcaa2621d8f37bd31fec0f2c7c2dfec095c67c360d4c055e7a1695533573a7aaa252e4ed0a46f2eef2ca01eb339f169db4ed3ae2b02557705fe60710bcce6ebbfa631b08d254d5daa6b037bcbeafb03bad064c36e5fb1210d0c4240d7e69b47977d6dd5d6e83bdb6e9d848da16512fadb481a0193af8835ffa5df26b6427aaeb0ab4f79aa7b569b038c2a59784c3ef6b7cae86e70c7e098745ac71d72b549965c312fc7242ce7627da43ca919a6b925fda1c8b623be8588f95d00c64797d9e52d660b5a98959f84343dfe8cd3dfa58389d4289710199f61b7d59c9e384ecc69805cc6310210472914dd9ca19d59f950da534c0e246832444b6004de9cc58e13453448ec0bb27f90e3201cfeb26f801959d62134034edd83c397858bdecf4bbc99728535c31a863b78c48363e06647506d9f9483fc3e52f03c8d4e787f9d8945eecf3416caba8f441c7d7c7864f39b40d472bde37fb1ab68c5648bb30f08f8f239b93852e398c9870644962fc9cf019211aa00517787057e588d3c5978116292213503a0644e28cd0b14f5386c85acab1210b6655689484f4f1c9c4d8a39900f59aea30395a4e24c57b546015cda90c2d565e00a095212de82efbb23c26d316310de31f96bf6d5d9c3c2806c9245e532c52b668eb4ee762304b0068dd1399417951439697d3534d6c5c842b9ba11612471b5475790a7a9737a4415ca3c502c0434827b7bca3d64ee153f204b79724c12bc629b415830977018f59e7e0b403148879b7ae35a7164460cb529ab990305c46814e85b2d16b5401a2824b2ab036541d6f8f003ba46ec400374a84891fc4855f4b34b10d2762cfda505e6cb3bcaad2a75d479e1cdfdbe32e9465a577475006079bc9b9a786bef35be808342bd0723596bc49d30a301085c91bb74e80064999741b8419fe606c23c9f16706f670b37564754e8b1b03446544eff1a400e9758f8a9f1d8de9d3627042207f053bb3e402469f43c40b22ec73915f09c64195b81b3da2f1f9782606b290a5323e89549fbee62eb7171bd4500019c633cbdae56139867d1b6b85351bdbc31a6b90c58bd609cc1d6d273e30ebf2fe5606ef3f2df7dcc340f3a6064e9003cb30db3f9e9cd9eab2a104f342ff4386fe3737b86ddd48fbb0b060f80e69d7122b80ed4392b5667e33a51f96e377bde5ca9665ffaf472cf8d657c0692b360941f542f6a35caaefd452f314345ba69ba0a867055c9238b097b5a61aa6a3329ebbaba8799e276c9e184a73a7cf76e18cac99019269df4e78daba679dd6a757b8021c818c9467ad034d78583173aaf87b9b8e5ee8827168626cda2d3c60bf6c7ba7c8624c1a05c6e58c47d28d095b9b7771ad1456ab5dadb768404a0fdf049c4a1c19125cc3f145d6197d96a7c8a332245c2b3d428d21392ae007c398419ea5a6686dcd1cb8670422899d2abe00243fbaa84e5fc60ac9d30c743de3b6eb023e913227cde93e2693fe8351191b448180ec062a301ace4f38cc8bd3944844b10f213bddf6155d19ad9088f711e7a8876e35fd2e29a2990a6690dadc6a1e3ac1149cb78507cd851662ffbfb1c08403b588a2d6f44d99c8566621ad6b2bdad5564f0313d4e2eebd90f592e7860f1335b59a23eb5dbd9d8baa581decb225b1cc63f08593f50a10f600d3bcb50eb2e9504e1edabe1d08d0687082ab9900ae5c8a1e160398610526f363df5dab7189950a39e92d2531f45b0ed37dd828db740a4f14d22cbf4dda5cb7cafd87e18000ced6e5562ed9e1532ec6a1a8670891a9021e95fac2446b42e8da22ec492d7182182081837e4c57122c5c1d388f003ee3793027538212ce4a2b82013759a0b337ee2a54c8c0c7afa19efe9e155884aa8bd898609ce41f080be3b3dfbf36b369bb5b2b2c51f320050590d626efb7e3312621f92bd59f0c6e9912550b4d128d071690b0e4ea6eb8f11bbc1803ef6aa48724261666f45e89d7431eeed48b73a07231d6847383742263bcaccc8a6ed6c6ba037712b43fed3b1d05072b046b8e16f32148cbc465f6b2d588dd0d8dbd48aa07c0d19feaab7447ece5b47d9a7ed55f96709a7e33eeca4b3aed342659a62fb13d535f0b666440f04406e5acb3fb311c90662b2741e0d0f4e2897a71d45131f1677a40a6ddb1583b4d3f919b894225927c3a14892c4f4e5093100d42c4f4a0ab5ca55d3245a7a3470ce655cada6e929a55be9933312b4f2fb62af4c4c8c37b4288f11dec9a4de80c9cd5021e70f187414ebd179dc06571c240d04340a7bfc3a781ca49130925ed2902b39e89fc6705b6ebb04b6fef51903cb3c62207988b286086ad4e6187a31da1469dba416f0b8fdc4d4f36695ba52fc60e24aa8bd7856b500667b46c1a69d61511b0c4048e82b5a18370376a7c573045e7e816866784c3353a9019e3f291cd5f249c8847d884777ff01c96faea944c2263438d1215146044abd21b14e40d0dfd812d327c97f0eed4ab931a463fcfe9585416bd406251b9edafe8c8be67d64580d431391f1d44d5a086620f931412b72b1bf53f843cea451f77728a757bf134e2a45e4b1f2391bdbdc23f84392c42cefe190e2d5713d26e096e4bc9dd347e84340f9cc49c7a2b625ec8e9b1bc2680bcb33233eb61d123964981d4c368ecec267f5e071fdfff94d6470857c5ca3b8cbc66144fcf50a50272cc80ee5e64dcef06f66693987a8d8e0d0295952e0f0f5b28e7a4e7a0b6a0a967193b4fad4ba2cf99d8fc95f7b4c3b312afea2208dbc9e16dc09bd12399c826c4ae6edc740b0ef41139a4e84f418c323d7a7a8ad6b60dc2fd72583e0a6e8cb01dce1b4efc106344e35c31cf26303057461ac79c7020dea46608fae1ac7c983fc38cb2a578efceb4d2b0d15030328a5ac7b38e160aec93214be35d118792cd334cc8393268268db4e105868bb08dfb1b0011eeaebc73e265346f927933fb875944d927d33d529af404aca0c059d8e63a60b303f8048500dfd2553cd34f66601b3472378769ef5b1ebb21f5a38e76ec1f50ede56f900dada0cca4801cddf592b219ea283c29b3af4fea1a079d55597316f32a86a25cbc4635d011a5d64b6f23ea8f5409eca7b58ef0707def68a00d20758c91d1b94fc55cd5d71acad08ca7dec4353179b3e8b11764ce486735fd7651345e3320fd18e92397bcbc31bdffd19e61a328187962b930075a354d3b158d1766ebe1b43bed533830405376a9b22b1efcfa018a9277005c8749e17bb721ca564dc04c6eec9f0be40d42d860d3933baeea0b61831b22ade9e0d1446aabd7510b1ab97def9074996a14cc9ea791034c7918e3a481df819ecc9ed63d0e07e8eaa7af495ef3e1625694d2e5be05a8fc56e80f6b01ae17643e5d0fb3126eacf284ab2670e42a34ed7fe2418362b5b5038e968a45232fa2c1ad1e6843bd9a7e5bfa3955428e39ea4a4c5723d49862ef5f1744e0beda5c3b80a1f6852ca1d7d3a8ee504a88d382e6ea73905ec86ef2e982dbb6007f776a47b5a2cb85270686e541dd961212fa92d2bcef44033583cea38e8e29e696925a22ebe632a74baa25ce11013667de65fe1e7103f8b12c3e91a7cad7a5db7ca482567d44efd5fc78d60c5f9b0bdd07f34192a77c615e67934642d9b4e38310b0c8e1d093e4f326b40e294279721d62e04a84a04c7ff53ac998230c4218982282a97c75206d906612534ac0fd131ec70451cf8b783d67096979efe8e44902f708781c99516e0bbbd11a30bb22f4d11f227c4c0df30af8bc00276f7f9549d1604e98c96831b17849507618ce77051efe4c24e786f0a81e5e7d4f0898eb7601eb0a14ff70f55f05f36955bfdf43ccbd7fc89fae38bfff9461422439750fc3b7234209146d3d3987b38c7d10e3b7daa0c784740b7e2278796f4c601484c371cce4c80f68c2256bf023fd8e6ed1989b7f1d73d2a57fb068147af27e734a6a88125aa443dc72fac578bf5260508632d98573cf59c5b3ed8f4dbe92813b74b8bc9325c1b482a91d476d19b10dab7e3b6465888d0430312d29d835ab00e27fa04d0208f115be953a34866a3f240bd66cc2c1c81e50a40c92968cff5717eb60794263ea168ea22e389b9e5389d536316138eb9c02531367d7600df68f1632e19a11f227a58e57bf2d84e8b569c61c59990396506b90084f9c06260af5eecb49c63acb5f7dc0e4444528c2d9bddd3d1e33f124158e1cd2c58b96777f8c1168f0b85b9febc1702605e3a499baf2cf351cbd07e1c5f94275c051cfab8a3e3232ad7ecd86646de5754a5a3a5f2e86e058abd5162662d3b4bee23e2c2004c041a1eb39cd8806efdc9201a43f548c992576aa54f5d90f9e66a9aa17e247e2679882ea0798ff380572c00fec21af7c0a0e8daf2c7d4839091076a371d8d24c5ffd582407e6df38beab4ece57fdbfb31500a962a00f01ef5cc0ca27994d9c923e900dc3dc2b5c9f3188d97dc3a9926bbdaf85d2c24a3bdf7e5d695289c97fd8168dae9e3166e93bfb02a004832e278276d4b26df81c1016208dbd8ad55d733b687099f1f347ad743f6aff180955d2bb299456b7dd43d5593f22fb4919a7274079fcff230dcca1e4e015e5867e7f5f1bb9c6bfc918141d9d02e45f58c227e8774e42a7a6d96a60e71e733529c8c1e58f17b738e44877cc5c6437ee471cd2c181c9c238723cce548e4b849275c0253553cc914ed761dcbe39ce211d62664240a267a239a349e6c99facd774d7fdf3ac5a0016574d6976f3b5323de118bdb174df7437b3586195438afd67fa865f434aec9e4563dbec25104933d9655c48e342a95445fed0ecb538bc727bb24bb927eb003a8075d99dc18125235620ee2519023522e492dc5af265b4ce5ffe5acbbb1e0ee76cee130714cf61456150749460efd59746f91b2e543c61e9ec6120680f5895f35b57fb7adceddec3545e83123c3018fa694c7d26bb9e13cbae2bf43a2e3b999f19d91ca9204c19c6c3025d56233ec6624696a3836789cd0759d578c4544e08f2a77248d589b22f4ae62f3843d53f4af18179b0bd56161e2f98e77874c9814b45f2ee30971e973ad0ba71275b50ab2538ee64db95b397bc4bf705ab860d1e6138468c6ae9c67be20f4c6db1d33916ab0a56a4136f8366cd1a0f169cf867fb5ee96c4ec2d658d71c100e827aa1d09c0f6adb8ac9c3ba80808a484e6c8581c1b2d4a271edd1bffc49d5c874aec714b2ae82f1a3e6d681c48f6eb7c7597d79b4f19bbedc13d2c6ddaa5465ae3743005091769e29e249418b7dfcd0058495cd9befbcd32376efc456aed878179bc5d8d912aa05ba8d300bc8fd24a968948d3b63cbd2f46046b21ca5d36298c91b066596e46520a492cca33f7acb0d6407dbdf9cd4dc24e00efa41d6432a92edd42b2be6ef9e7a34a80909098c16b410a62c486107257604c8759edff6b84c55d66b4d03048127aae9c76791223be2ad699ea4acfa4a7cc951badea33bde8afcce650d5270c2ccd99042fb9084faf246a5fe899363d122b194cfa1282ee5a49ec6df333bf245eb0609cf3ae7f90a23b79b6a67f4df342d276a980a8b377afd33464b1281e52868a96369994b0c8e09bdd1681e2f31d68b4a2aa460dbc3bc085f7dc48df5da360816b183a4d0646ee439701a1131303cd8c773ea5ce1ccd04d36bdbde8e1788d1e9685244b72582d026b39618095126c19080be15fce0f094b4c08e8f0aa0e0576836a2bfee4a312a124885a9c69f4e393f07a1f3d37f78e3a1922bd9c33dca5d11297349e2e9f471d681a1518339e47a35015d1da764e504229224ce19debdcee14c4afa5044e4a702329e760cc849294e1d50ff8d1cd80d68d49b5285545ac57a5aa75022c07e5512a4b680faf4e1ee34f78ab7cd6cae8eaee3037ae42402b1551a8abab14c2a82eb5377a3077ba9cf2ecb0ac3ac124ca53ffa53d66a719107eb71b681e179ba95d7796b85c6d2576d744eccbe48f809453a1fe64d496f2119cec4ed8e306bf8ebc2025a1f84f909b9f280a52eff136b01706119446017fa495cf8645f08c20a380d8a8c3515714bf3afd08d883d2ca2a67c4bc373a2ea0377b0451f7a0c019e1b84deb4f1f226836899b0ee6a87d5bede116df6b6fc9dc3f99ca8e8a5475f1f8dec1d4b148030c6100954dd6927f3d8c5730c2e10e240a82733efe0ac2639afe2e2d254f777c61941504fd6b79e26663bbb440ab499e7215215353af2c37eda74e7b46b407f4ad0fa4fc4e590d77887a0a4c04b5f71ec01bed301201df72da641231537f840bca6115fffb40d6336c58583889f7b4ccae6b524fb04c40a17d49d8218a7ea3fb903efddb36ea5eecaa5f66da07b1f63b702100fa830f89be71b031caac7e2a4b473b740d8ee5d27dbeb984dfce78b9969aeedf1782ff530aff7646c8c49d72223ed325a15a5e51363c9e8977c5f10ae14c199e04c7ba799a6d23041ddfae3d51b2de48495511ef6af825a887650b5f95b3bf684a91902171ffaf77a1049ca794a9c800c3779bc775a130605902f233606e5b0b47dbb324f5fc25402dd1d61588ceb27aecd9e63edfb48bfde2ef6d4a85d832d307999115c90c5e644864420374dbd52718fad91418d8fa87d64b8a22732c1d9c64dc21a659b07cfc971d4b193185c5b8c7f638f3d0d2d1f672ad63f9f83d776731b7dd2c8cb5cccbe1d38d236d423c4de166f895d6531f698f5eeaeface4efda182b7e78d23ba768fdac92f75a41420ca774c40631b5908663bb8d579415111933f9305bc4b4a52a0de507de82aecaeb1b950498b3285172fcf5890bab185636227dfacd9d7f154ea7d633d7d91f40a799e73f9975a8ecca980c0cc3631438f3e0cdc7931b1923a418aa984636026f7d7c4f97d1de6dee28ef98fcbbdc0241816d5f58cb053ca1116c71724c9f923b69e6a7ab97db61300b4ee15cc1090e4836357993f23ea6ef6cd280bc7f44ca05f8d2b566672aac59097bf0e3f56b519a6eca4269b0e8992383c9b585f308d0cb45248f96644abfdc141d7888d4cd6b1a3a26565034213e2214a28d8e5bcbb14ffffb4cae91fd1877a74eb9e9140ea6a35fc7669111c3cdd7a136d4f57d56d3696bdd8253f8d3c1e72139fc2823af8ec19b658056ad977d69dc3f6bf754ef30ac06bb8d5d32ca5f13e3206b147cf93639b19cbef251e962cef17df524ceb13945665dfe25f8f6a88c461041c7775ed2a01c2b61a07665607c031e628a1227d83b7a051d9de66bca220ee85ff587e201b72b92e4d5c47f9d1a8dcb84d276b7f4deb7475301cb2304c7d053753773d411e5702757c30a8939520723b46eebc140017b3544240498fa884f108baccda198c470d0f650d1bb0908b283bf90342dc4ae9fc4dbde918e80547fae1be892f85d27887e3bcb368ee9a94acc076183bfa405c1f156391a984d9c10183f9f83183c7cd024f00aa9ef079ed1a163705cff162ea1e7f937f610b058c405df6e7d5ee4a6fa3390d14840986e134b1553b4af2f9dd166fd319858d06927ffa7a9588d59a1aea55a312dff8186fbf448c14b380917bf14fb03adbb5038d8cf71dc13c12221ed5b430013d57598a0317e4f22793f88ead921b842ba3e60c72e18ace1ece83d4dd7c7ae953ae93ee77e75b53d530e8ac30f0d9e051a463ff12a2fdd5aa4daf8647fea2c09962af57751ac2f90f8cd774dd392c6b21924f7876b6e2975bbad1075e145ede5667ee9c75d0e1008a7840fe87a1deb2e1be3eaa64d6eb0198ab9faba9abe275efb4e278289b222edd1475cdee46beefa5ab5a2b1d710fbeed944e9a5d0a11db7672b48b09b5612e9e603c0b3baf0ec9e8568046e2cfa15c73b0e2de271c82340abbb6ae3cba3e01e63cfe6b56a589d027dd669cb0be8c4750627378cf8220a4968383e368cbb12574a51860668eeb6384a4de77a8f97771475f6acedd6cb1086e51efda7227f5a80fe04d286fd7ff76d1ccf050aecae032c92409124423f060c74fc0692bd35d52da49b57550f0b7c7e64baff873e1a8caa4f81268fafbf9d8df631bee48d6c51954735b9da8fada40807550a4b43ac0b6e1c3c0edb25fd5571407da8203b39848d2d4a2c265bd977234843dc161219ed9ffaf7a863668e42679c3de73e7c670475a350a658a03873d009ecd94bd784de56295c5ac56820eab984a7b19011ec0ab2d92c4d0f42476ca542e0a591e9b678b8a9396894c0acf4a063be5e30dba0678f5839e481c21d4e627e17731eaf1e6efa4cddaa39bb751928ee183df79c1f70f4d890067ca68f2751411b0c08cf782c4170efbdbae06438e86589ed728c7801ad9161f488101d4d9ed0c89adf43f9fb1ac2f53c330880f253a7474d410275db58195b2550f73904a3cb6147c40b6a8c4919fe24efa5ed65ec972079c16885b781488ee4a6c60b059e6632d669b6fe37bb466ef6736a2a21c3b988254140f76f2451f1ef4cbdf4c8162b822d6ea902dd90309c504b061d1c288be83740cc0ca3be395ef500fe64bb743917840b0c3c25af12ebf138ff1ceaf07127ce54bc7cfce7bbb412ffdffe07e9aa7ae74ecb259dead979a31c584fd85c630d3ee18af68d0666e7be58601edfded8567e913b67c2d6c636ac56101d20811198c72498f3b30b0d7201da1cb1bd74e12e3ada36d2b295dc3f95a31fffacb3485eb16b6b19570254a027d65652144471e17329503a65c54394925c8d13c3759c89299d5cb2ebd05e4a0d89de502a2d7283a7f5e66ba07d36d895f5829176dda34c0a50b0c608fd009b9a05a99abb7423a73afb1240b9c18ecfecccd43b7cda689b8773e6ba175af5870d3d681d77a391894cc3990708c667c12e5e05b79fa8397f787400545422725682a5bc596633e512e629a48a59c262cc8a650e0695bc415e100bfdd153028c9ae5028346563703008d480963c4bebe6f33d2b41d6a91ff196f631a3aa63f39e583f2b9b92f6c681b7d690563f05c9a16500ea1e420d130a2553fa188cae5a9d8799f7f7ccc2d124215f6904feb436f4f982dfa026da733a0a5e82be81c0e2af7af66ead25d607fb7e62c2508f9a1476689b2707879e3ad950ab54a15afd2a81026f5fc5f8cbf3106203938775f3ada0fbb37d30094a38f1523ef583da1a00d70533e1dd5c466d9ebe15435befd67aafe1eba8cf83d673822c0bb62e9a050b717d6495103c62175a7740bcdcc48347a2d26bce2a81aa97144f154fbe944409236c4311ba0893f360758cdc7fcc131aa7a9b1b9df86ef067035101e06ad31083583709cd2c058fe1248dd11b90830c1e63c7aac12e52b35ce27e9af98115b46acdec3058b668e08466038a873e27a4ef2108b73ecaa82393d9f75c49dc32f62a87c75c43de943209045abb8f856e1db1847840c651ddbbe6e0388421990f12a84ab19642bf50f1356dd507ed4bde651c94b855b8cde74c83e643cacc64ecf650de1a2eaffc4da1f21cea508cb58ceed0dc0a3e907f2aaa42677120655f0b341827b13820c29358344a883718f308733380a66a80ae5a6b341ec72ed5f40fcb557081163cf9b13c1b315aa55880836f4b99812f0e68fea9367b46bd07b999f3b912daf7a339801c305775562829ab9dfe75405d3a6797416603ee871c06084c37c2e00ad23ee22bf88c2b18e8e84fb6de444ef126b52e9d1bf31ad0c9448d1202d12bdabb3037e7898a831134b69e71521ab6f4661648228f7487cf590e7c382a8050088c956a6459532f25ffcac2ed4e95c8d25ab29745d31e07c7ed658bd7730de92baee1a60a096e2348c025f7600495f912418f63a07da8fb70beb82cada9dbd349c5984ac7625faed4838895e2d41808e28caff7ef4cf86345e62e1bc603dfdbdec209db8368fcaef1d40b16a6465c7e899d7af5a82195eb6e75c827c8ad82ef025d60d42ac0750a292548c60a5d20b5bfaeb242c77cd51f627dd97386672a244814cc740b63fc2b0e3a8b09f552c361765b667f29ce57cd6871298271bc963a7316b5c9c61cbc42675349b1dd4e41361b787136841985877972a07a114578defe7f7308c400c98d9f168afe00248f994ce0de1a69ea1dc796c65207999ed5e5e2f46809b5cce14eb8225e0392fc9ac56c59df046e9ee43bb48475eda52b1d4d50457d42e74a21f1cb5e44f00b79f302bae404e4511c8645af627de7a4e1657276dbda0c08ee8a5b271e2c8915dca7928da052b8adb91601a447f62498778ac0d8a4d2e340dae7b3d42af6621b522c254b5168fc40d70d18ac7842588cfa4e154a14d4161156289c42e07908fd27a41947ebecdd699cce403124a217f2889b617ee13e5f1f322e75dd5ce9c8844ea54c62a7fcf2085dc036a86e022fdfd99f737f9e189397defda94f314321778b57702514a0c311059a2e562d4603bafee8b175ed2e8b0505a63c8057e15aa88178901b8f1108ba14d616092f216e16a3981d860ae2cadb02c059149d28f6606ab7260aedeef4ba6f22277f5d15732072230494da8128e9391452aac2a1532fe1a8a50d0c6f507b8d4c738dd21417f031e4834dd90d4e70cbc7bc5339ddebbec1896521b93e61b13f761ba6c5a4209907259a53cc6a52cd9427030e0b5392d1a3fb8e51fa417d1d36c81a441923d2d75319fa4688976d9be2c2da5152928718889851c69044b39023cdc24af22747886f3cdd53a18c4bff3f93a41400bc1124224147ccbdc5536f91ed871d01e441f37a804bd5db8c8343acd0dd13619f35852e85c3c164b53065c4c0295f184919596a29420e1ed1bc1c70d60cd219a17a10f790d60c12c011caf98fd19d414cd03689461244fd708004119235f1b00f55f82e15aaf9f54d6bfa3e94640b8aa6048224498cd44115edd09f843956ec687e9fedd40961defc72e69bac3fd721a00f25278466e33e0a6f8d81b18989e1691c1cbc9ff94fc1297cdfdbddc3235a1e778f82e16835f897f92468149e0c279e95366879c905ccee73832077975d2ed4bce8fc78f929d24c2b3264a83ba6608e9b43aa767988bd9766eace2532bd6953b50d03b304a81fd37ea46e61b2b946acf425dca5df0a5e0de216c1faac1a111af6c415879c2e9117b2b2bbaab9834efc2e91221ab8bec3b6661cdd80da292586f6bf96fccd737388b5e9f22d07fe93a0d3ba39db2ccc3fddc32eccf25841fbf7c72d9f98147321aa88d756841ebb94a10f9dada772733dd9e6d1d83c95cc938f48fb6d4e24a786c242a362a86b328bf38336f6874a88dc3080ccd709d35f73c424d1e93e45ef1da936aab38fabc24378995d5020073aa15c7aa8d8ad9eb809a9c86e75b6e8de6c404bed909bad8f02644b600c6191730d8c66736c8d33a5f7b212794595645add1d6cfd097d5f24ac338523d82c63bd8f4075836729c30a56d2435d9be74e1148d3173e5d8365fbd78ee860b9654b139868f3b1ff46e82c36f64268b7c262a82657ab9bb7d1c94098ee4a594620d78e1bb8d5442465ccb084c6267b029ddd622603fb384207cb2fc9ebe4c9bf50240958b18d66a74ea7cca8655db2b42d278c487a5f6057d188c7acd288bea742ebc5d8803eb55a291b82057045fa8ab0dcd069076eb8299a13c183828e41e11f802c0f4dd30d8ee05f4051bf9d7ef18572714ecba122779b5dc9f31d3f453150fffe19d75873457346bb74c2b5ca9e582ba15b772c540c40cd6c706dd27823c65471115dc4263710876ac54e33b98adca2b041d405604c12bc5332d6be844ae18b283aec4e566dbd78be5c6ab3b141027dcb50ecd0af2c8c8817ed0eb78a828f09893000b36b1d93f68104d65ccbcb53a7c6d668d3081d23f43ebea64cba4c21b3cd358f5ee611a5bfd9a6ead29794c610abbb3ab7f289b679697b04524042e7532bb5bb95a8371a0ba5e620380eb14b44840234cd23f53c244e347e67e82c9ef54da146f45ce0b66d70871f004868a2c8b37a4a1385b7bd00aecc13f80f6e6943efa7f70c42e0473730ea9451ba4aaaed6abd77606d23978cdb29dfd0e21a40fa225144a281c617eb944fddffd253b6b9d0379f30d00c022e79dea43b80b9347874fdcec6dd52dad7238488fa2e69cc800018439f2e982a96d94333a50f0d6be0400aa67364b7153d7ef075c1920076aab8add39cf984327e6690168a093c1db58905bea15250c4ace254c4b1e98c0f827b79a02f165230354238f8d8d8aa0d2e12526134fc7281344052a3d6a2add14b0fdcf01d74233f6806bf74631a0623a4a0327265099232816a48b384d824660a8e5938c17296744eba66dc3d0a1dc5c8e9a4ab84226b0d77547548b5ca2ae8ccb53d045f36b1685b5a3bcaa3511a4586f5121469ec3ee4ef0965eb5f4ce2dfd41e4d37ae40ac33c22589ea7e978d99bf7d9d65497bb6b3a94778086e948e698ca3ca26cfe8f55f5e5ef5f5aac00e246b7674af354d909300a949e2ac19811a08c4f30ebb689fa45572691b07ed980c7ab8a94d541f1dc831aecc4df51c7ff2878efc291eabd08c3ab23783f584a822bd00dd46936b19029784cb23ed372cab7869fc3970b0a74700fde5b01523f0838bdcf5618f25f5d1e1caba30226d8dd16b885a19000db54287da200487eff2d0a6fe3582cc692d3834d75fecd02837dbfae21bd426d1398508f0b253e3f4b00564de73099edb942595b6284915dfe3748ace0c95dc050937ece727b55f94320897e98237eb859452c3f4180b63f4c96b3f02a3db082f63d34c9800a11226924f4eabe04f08fd4c8c856502f2f15d2a71a22e31ae3d91e29242d525d9043f34d1dac6b4e1baa136876751bcb9cf7c316aeb1c6d0fe3a12db82af6fe0f8679b62eae890f57c60e90f8a0974ecb5c7bc3788aa680bdcab6d41a1806feb1665b5ed556a993c2568952991e51049d017b841a85e655b83ecec949f78aaa30a693dece33fe390df3d8a7625b691a3f5d702d08ccd2ff54250487f32fe60a812c5aed811b70c891b1bb1b555d590eac65ce4f89ef2a26c525a35189b298c0e5c23b294ad6c7ec0c7b959abd2389c5d4674af11400f3a5c25aad03a7944430cf2f6e82b8b53eed795cdffb353491e8be71d4c26458b2a1080b461ab2ac0615b00a65faaeea89c46e20e24a1db39bc0b2ef10e88d79db614b2c9654d67a9b43a8d16b774075b85b96e52b564173a99c4e408db680c7c133065be5e3c3be3482cd16bd0210beccc2d5eeb53f2cf0d6dc4114d833345d8405ed33a874ad01cb90d100842f7766bec799dc69d85e56b32a448bbc7161d227a54fe7fa512ebab42aeb8a73d4ac7c2af94092043e2d10cacdf870c122873465e34582f1bd72e62fa5a5434464cef01d9e9b8116c09e7cf4642e1640793fc6da6f5ad3c2fb4baf8abed5c41d6976c9938e0d15c8e0d0a65eb6f596c6c7f2d0d95cfe18af3cda40e2c10c062fa969ed71a6b7e801edc0ff7fce7a8d184ec19765c6811aa94819c12ca9d4a678b891c028d1317e21384b613694c301bbcfa1d2a013aea974ecda0c0ae5956a9deb3e48aa17483aabf32032a476a3442f3476846bfc33a91780abcb703b2309a49fe88f8797437b622bdad31c2ed303444020533c081cbdd5545f113c3b4ae519e7946658afd4873c877593ae323b27cb0618514a53ffcb10ad92045c6269eb287303176b09759cbb9aa4f98668c5195f1e49d5ebe7b7c4eb9915518c3fa8bdb162f9b16d66dc86af472e821656c14f01bbb2961d2e4431cb8cb2c779ac78830bfa41f433468216a5433a93eb056eb8bdffbc27fb583b998ca2f6329405057cfd8c1edbf8891ec7a46d13fb960b69a4b59b29badd2d16061d398b61b4771fca8e4faf18c47b75f9be986a8061868823ea913b6caed3ec07f43e40a644139fa6b83a6a26e61319857eaa9a00517b94c3d2a6236b7137bbeab012d0242ee2f45f24b43a9aa3368b43116925e48e54ef996c06447ad5ba0ae5543d4d8cdac86465d05f10ef55e3e99072c8b0f78c6429b742fdfab56dcb6c1ba5000b0a605a562674d988bdd04e90d708afb8845a594a68405850a1e27303a58d91e74b19494a8f6694f1429587a9e0d61c643126aa9b4d825d1e5a1ec9c6f164a95950cc0a6e53a7206647c8aeb721d742971a220fdd91260d4777f607a572ea2a16f9f3c597892dddf8695fcbb846605d297171640e4ac1e19177c27746f8902a76dd83d3d1eccb7715bb3a2846dde6ae88c03e6643c743e0bf890dfade86e829f4d9c04922ffd911c2aa8f971de5ada151a3def8253668752ce44868367c3520102bf03c6a1a941500e50f351ce754efbba0905c8f42801dc01a2283db4158658ca9a2fd2108cf0c945854a434e024830967aba3afc5d29770413a0650b2e32889522d4b6ab679c5e83b5b47dcfd9a3f7d7ea856102616352e1ac18be68c92ee91a19c7118aa7f9c026ba883f863585ad7be4deb5c6487812aafd39f041cd70135ea81174ea7ece05848b63098923cfe8a7b0992c3421cfa36b81828a9626e935c390ae242d2ff9ddb82ce8febee8d19ac5807d9315a6a978c72c803b76cc2dad40165c838a3a5b03e4367f2607d3919f9b4c27e1d2be02d55e2cfdd778012cc155ff48110d2bd37e79d57df4e761a526d90ac8b5e413c3db1d8b97d9a1681e77f31087d7417d447b2aa67a79081892556495b60cf1acafd31ac4a774451053140847893a03dd11d9991a09372753b9dcb9f6e17783385d24ef4f76bb9591fcf6a67b80c760cec09eecf1297486d1ca741379f6f2ea7ff53780636a25c93b786587f33e9f956bd150c7b84fbdf3f67ba8bb320e63c79de91f659528e1215a82b88ff32e0558dd169800acdb42b5bc93b7f228e59239617bff0cfe8f58344e258b5da193fe01057c2409ff20c16bb976a3cf61176fa9726b1d3b18bf9ad13f49c493ab1d9bd6c7be9690b9b181afa2c9efa0980b2b9516ec5043a345743d421c50e30e120c29699ee1bbf3b7184714affe8c587a9c9bfee8ce071b2e4ec810701d87a0e2ce8128ed8b7b887db9526c2462afd01ed304b2bf9c8139b99352fe083f875a6551f8bb12c4f3f4fa27ab49a08f3117eac2b59b5233a0c09761fb9bd76b73701ac3d7bdbf074b403d720f647f1e3db74f7834fea207a7a504415c1c71af272ecd3997203c389a61d79e21908a48b2d863eb9befb7e69efeb87433e2400a58bee8bebb8e58ca233fb0148143b6677d2999e5929ef14051d1e1e7c443b67ac67baadd824caecab060c1b4e3c8b1db00c0228442d54fe0d10254503a8af353311d3db2618d95fe80b49f6497094830823c2971829adef49ac5899b9c4eec0c078fc1042b69122d9c41fd2641a846c6db07fca5adfcc831b22e3321ef23481f7ca719abc4007f864c7e456e349f9f2aa6cd6bf526e6c81a8315e19285e138133ce95c6f9be713cb1de9954ea7d1d1ed17dad741a3ab1e4ce4c494a5a46bc49b338eb8cd515f647e8b45b38d2f4b21857aa49c3422ac9f9fd45daaed04a5a643da5ff6daa089415088127c103ecbe2d2500645b659f00f67faf3915a284b790ba1fc9e94ca8b871a9d908dc4b064401b3989abed899a923af85f7f1b6996b16069c7cdf6323cd423652536fbf1fc3276ed536fdee007efa68b2f1f993888289f456f019fc4ec0e212f646db5a0a30dc333144081729a84014ebab2487b59b39ae2d0db916f52289a9a2830a9d7fe7e3390b549f4569242347047457ca11d962b843ab8b667d8fa1687c3d6076e3d55bb4688ea4e08631eab2b8811de89537a2a1c8ad20b4e0db06002ad69405dd9f841a2e988c2a845f55861d818751bfd29a6be6c781f28b448944e0883934a7cc94f21dd66be0a32228e06e426578d155c28f05b86b99f07abfb1e27203152eddee0111a8831bd4d48b036e67efb6825ce574711abf852a79779d2a0ee66c184c71dc8d47cc97947bdcc6e171fb39ddc6d1edd595d0006e14d819d52056015d6297d01e72974a99d745931e2f77c97c074d6fecd37a86c90840d09f2f689f6466a239df97f0e91f0fdf0ca5d280fbd467946e0e53eb022894123778d445b1573cdd8347f79f84ba589ab572ec48ce8813fcc96b642ced14c5dec72478bb5ada5ea0c0146e5ab6dcb8c52f25a7f3a4f2815e92c30ae261cde4ce5bb8c2e34447a201d4fe02eae2ed605c409ad5a80391287bc7c5798d7714e401deb06797db6e7925d587080e40d663e75ca95fa03fb112be10fa0015383c701e80ca6a561b4c0f18276af321426904bd10b9e1eb051c0bd8d8884dd7b21ab7ad1b0afa7befbda59452ca9452e305ea051006a51864fe731c7ac6f41c95bd44038c85e5015aeeffb47f77d75a25fb1d1f489794eeeefeffff2fdd9dcaf8546e0fe4bf972ff50aec1555def43db40c39ae050c0aa4bc892e1c874be154c000c9c6a08d2c5d86c749f4f7ce928ec3857b129ffede657e97ab4731cb8a45ae6b72b9b35a49fe5be17757af48e1c66843f67277f74829a574d24a5d2e4a2baba3426175f7f49769c39c37ce39e7b451058ce161261f89c8708cd1d6ea6ad9d82550faa1b91f1b204b97bbe7cb7394329e4cac514a29a59452fbb1d6c6750383ed943a854350324958ab192435dae9f47af9f0f17af978bd4e70a799fc04725493a6cc1da849dd699ec7f8a7699aa6d96072291317f453c560bfeca95d068a1d04011baad0349c1be5fc34edd33e2d6e1cd79d949aa66958761cd7b5eacdab575cdb7346acb56ddb79bc906580dadd3d5bdbb96240d3344d8705798e316a37af50436559966daf18ea8675ac962a9d124722381b5db19565ff5b94b46656a3275b29fd416128901896099918b5d65a6badb5d65abdbb31fe27b1b07c48598531d231606a101da230981eb990bf2e5191c8f588fc55487e901317ac3035c56d35aa28cc5a0af328ac1ae9950f22085889e4c715a657de460ffcc4af307e7a3589c1c0cc891303d69594006126bb90dc4a8e009244c5e292b8deaa69ff884da50a503c737f8288b05185abc2750cb2b0587294910583d85d473e2aaf2ef7d8b7746d526115e7c7a9645f1ebb6c1ae2e4344cca584819066b70336eada2e197420c866022ede032c0990214a42dcb32cfc551499076682594206d5e55bd011e8334726b9ec8eb4a84525d315cd654b518da70784fd956575dd5550c6dde0cc75d65c550e6a1e00d5f20c39da78386b3ccc33a702758f36644970e67de8ca8e11d19d670c49ae752247a3b34bc792e1cd6b0cb8633cc038907128a37c33d22527093507093e49c33a6802ce882a407de7ca3baa487f10f68d00322b2baeaebe63f5786357cd2552c8aa1ba44ab7c6d227f6b06c77f10b1adab276e75497aefe703e22cab0b042c59d60a035557758962a84ad12a8f63855920f55561b6d43d0358b7c85fb5901f572dda00df43ab7cfe01b4252547bce41ab995ccd4e4ef26ae38eed180be28acbaae0056d72bf3aa6b555934d5555759c6f8d9638cd1bb1a220e1dcb32e2665557757d54f5655411058d124ab477d7dafd9193d65a6badda56419f5e61722d0cad1be6c032418d62cafaa2e223274bad2c95a5feff9665b6daf48aeba657b61c2931b6165b6cb1f50c5a1b8638b6c8089190d2211485c31035048761ab421820380c8f28f19ac2860a940f374a9e9327750a87a0643c493c2ccf8c0789a766c6621fb3d6da4a842049721321c8910cda88e5c703c84d84172df24639dba30f7986bcca873c31aff223cf0c7aa5717882b40c8f97dc5a73f4cad3bcfe7b1ae6033e77af484cbf75f3ef69f21e9cfc9e9c5674d17ce84f9e9afcd8e341f22daae841c5d0a3b60c7a5627d5c92373be257bd77f364e5ce93decbf26fffd0b497b4ce096c13fc26342797e6471c14e2c3f36e5ff1e4aaa10c6f47202d235bd9c203bee1021484d7ecf4b7e3caf70c18fc970c17e3dcdab3cf6965cf02fcb649a3039a6794ef13da799e839615392fbb1ee870b624f901eb95083ab0265f796f64f08c7417a947be5f1c7885b44a87d881b4b2ecda05d72a58c1f4f72c462b177f7e1810e79847095c7465e45e47fcf1057642f7dce7f9f1117c4d373724fe88961e2e6c83df204e995c71e213ccf05173a1dcf096c95c704cf29c733c413e339b9e0829e537ecfc913c4c6a9479e538fa2c788878847088ed55aab794e9e53ad1aab6573a334438ab0a55ad1b06a9ac460ae9b1ca9524999a954488098206a62091aa9e4688852dd56a9181071740aa243c218c965a0263920e28a23c8e20f48ec33c6383d50464c2d06d95cad4767a28aaa5c45a9ca3d15953193524a29a59459a4319f4a35274e8cf0a4071307f7e8df5e8c414cdcd851344522514d0b268b3044c9a48ed0b458aa2436340c3ffe89a1fe7fb9d26fbcdc9a29a594de78b99fff692afa904c49a4a14c0e0c55dc99f31f8abaa4332d28e7a2a78473896ea1418366a301040dd3b7747fd9a3f2636b61f6644ff64461fe63d22df405f4b45141611c10eca99322c31486be809e605a06e387fc2ea480b970d9130c130d130d53b455740846134d609cb11229214e0961bc8070412c6154d1a1b9048cd74b0a29329812b66c22bb30bd186385e178ac172bd8b6fff7d831c6f8b2a59432ce3925e794d2a6542aa1d1755dd7755dd7755dd779776771412ec6487e5a840a1da2e911fd69595c777794d89568c86e725c57a251ea5177c487f010d7f21e3ac4a56257ead1d6d17c97a443928dc8ad2238969055105510f9b919eef4046a0a7ac2c5c48e6b3dee4aa518e9293b0dd77b4a111ca4b4aa9b870d12b8a173e89b969ee3c6b0aa1cdf42f3e3067c8baa472277c7d9bf195c10638cb12a07a529e1cab562d5b46cbea54b316f22bdbb29f0a4cac2f27d9f8fc55f8cd1629b95af56d25733477ce856ab54d68e44b77ceabfe741df3c91fe7870c36435235c7554891e635cad8ca8950a57fe67040d624ed4b4629c38f243ad75d6e926937b2a954aa552296befc5988525155958be0fe3d4939ce4e22b204750915c7658c0165168cd10840d664845b6090312624effcd4f93d9c15f7a618a16d7dad343d049f2071c73b806addc4a6ab09221b7921a9cb2b5f7726ebad6e4a6525391a7e76f8a214fb9d46341ee973c4789c77a74d25590bdd703efc77aa03df170afc0bcc3388cc37420b046ae1ef844f28314c7a961cf167c21bbbb3b92ec33d9793892dd9b38c75710183b498ed55f872213ebd0c12eb00e2fb007e31c3dea0fc201261d5ce00ed6c1835fe0f9c1ee4937c3f1053a9e0e76817774b00bece10149ececcb3caa5768c82235c387fb30ffe33f1894dc09ea8040d04972054012a2482249c57ffa10f4a68e2ad905a8495af664dec7e4c080849baa6f7a98ffe1c3ed615b079d73ce393bd8dacedfaf910333e79c73ce39e79c73ce39e79ccf596b571f25a66bfb2d8a1e5edfa2a3b3a524570c3dfd21db25b407568eb4ae578f2c7d9939f959516536a1ae2ab6d56a654fe6a65d8a330f6f17f45df70551d206d2d1d95e942edbb89b65d9666f96659b3d4141b15dc6655ba6651967d3bd0b2ba09cca289d3aa595b39cecba1a6426a3a454461965cc3ccf6f79bc69b6d26cca8c3b792fa3f9b06285c56882c572bec5ed4b0c2ab440dabf0fe38f606461f9be0f0c6691fc27a1f9c4fce748b63243f2e37a4587aaaa613ddaa0901f8683f8fcd08316f9714da27bcb60555d257ca0a854e4ff64e79ccbe1cab8ef362c419ad6d530abd5b68d8b31c69883d66a6d9669dac6495047931fab5a824eba1a8ee4c71b4aa52853a2c4f7d6522742dccbfd17da568f3a57d573a8c8faacae2acf54550ca56c9e8af3a4a7bab6c634b9d103fd64edbd61a636c200c5052b0cd65e8555588555558515d1be448c31aeac75555401f2211af32a4ee9902119ec9a0c76120e6f58c399c58f5d66a6c22aacebf08d185868102120073db1b897c10407ee2d1bd74d8d8216396fc3e67a7e520e1fae8fc8c272ef09c340c53d593f9de20fee639b75a7b48c06e9a0a753d7823967d3b4fb9453e2195544356070c1cfe7856f89f88bb9d323a27e1fcc56515da6ee0f1fc829e6886ae6653e8994524a6982910136b1c820b7c96472af2e2ca6097e9c604a2f31db83a0031cd040cbf0787ac516474c452c5fd5e6cc660575c0c77f593b915939eb55077ab4ab35d0a31e5adc2bacbb7b945276d5d5a3d6964d97046ff7e8b1c583526ed3325b7970adada5b5b2966dd5d61137c618638c91566db3d9e65acc6ca51edd7d4e96f683e973f66cb7271db769993de9b84dcb5e10c29552246adf5858b48ea974304d7386261820a79823aa19948cc964ed49c76d5a66bd136b3b8c33185ed7d4d1bf552aaa39e79c36e33a6deb26b7b1b068df77a7e7eed564aa157fb11cfa9b8d1530345840028bfdffffff7bc360dddac6757d3d1c442d82c144b0cd419d7190917110c5fe9e845940162a8289449d5807e7bf4eeb820eeb74581d5686c17a1471e87fc07a94809b57f1265c1160b01ae68c891130b1e72ab13bcc6f608e82cdf8018ac91019f419972e4460060cfca1ad154d510b8d23c38fb72db6184c0c6d2f1ac79179db924d8b6ed99a606d31cddb9ca06185ac502b820a331b86a1a665295a66b5101566360c434d0b516166c330d4ee546d35ecb84e66f1862bde3aa0efba29a903e9e8ac69b893828241ae07e1d6852761270cc36ddb3aad1386e1b66d9d7653523494ed64eb366edbb8cbba41f9185488a172c54af5a5c6b85cf7ef73a30ed14cca596b5dc9d4d52329e8148ec3f127e602a93f3e39f25b7241ea72ff78d405801ca04008352512484bf9fd6689bfa547153beeafa019eb15ea955425e97add30814e5829c6e93e61f2c18f0a68e203cc405dd445a965d5c4506db149f77e0755e1e65602848c77fe2f254b4896854b9c90a01e4dd3b26ccecfb2ac9b73ce8802a594524a29a594521a05c6185b6be3ba098388e67491c867d3b40086b4c3c78a16c95a908b39e79c2e3e29d77385b8e027dddd638cb5bab5020bcbf76994524a7b74448f34e040f0d0063a0a44f0530cb567d067eac94fd64f613f9103948ab4c3dbe044e2020023f950499c5764d340af9c52d75a95975c72b0d6665996596b391b970b8548775b20b6c5c35a6bade536cb6d2ec28015d65afbff9af6da7c983da74fef6e97cbe572b97a587befe783b1ab86ce5f9adf5dbb8eb2ab41e32ae5a6e468ed342eeb38ae7324aebc759d0f59e55b12d29dd2f7f0f38d3c914f9020fa7ff09aff58f6f6e851e89384fee6c6c6a6a6a62412cd30838a0a082443464aca975c1cece57a0ce7bf6745168ba5815679ac458fafac5a43a98b276cb03a308fa903ebc43a39a5971854e801e291c98f3bf354eabf868ab7cd41d535adab61c32c317cbd9272bd6ecd5a5ff3ae7ffdcd7fefbad9b7707ff5dfe79f0a1553f16752d69220e425c7a023f1a9f4ca13493082c46087c37466d05313df5872bf5eb19e735ffe7f58714187a93d6a87a9c25eb00303bde4840f10b7478f3a57f4ca77aae02a8f3d3f74fa8a0e16f26398910bdad99e1f9e92e7e5bf0eecbf87fd0783fb319cff9e89fb4d020e7751037560a04eac7345cb7073078b5e89118b335a8a2bf6eca91e7927d4e1418f3a58f48a91c6d1b962c9fd5c33e8a90e163dba42874ef0e3ce16ed514177608e23039d2af4e87107c77164512346ab38ae6165cbe018058452419166c719701cd6b55e69427edf263701991fd60f6b0922c167951e695ee70a0178a85305cf051732f875605f07f675703a3938fffdd781753ab02b3c588f9ad5a3f7fce0e901ec68018316d3d66ddbb6cd5adb6db8b70eac03dbb613d6ab890dd60b37e8b8344dd3acbdf7f3c13c5a9aa6699a76afe6c385b52d59dc7998ff297ff5a8bc799ee6756682992bc863ffe1641874771696efc3b154d2bcd27c964c8824fbccc7f103da0929b9decc43aba2a57911c6435d50a4f1f01e5e06442277918bdc9fc3cd719cebe6d564c23a2e4cd435670f5b39d305e94c3ea243076895c75996922223837426c690ad57c7733fdc1e94d650971059b8456ccd49fff80aa89fc36c4d5e37ab24aa5ee9d063bc9493c30e110d2c9c6cefffc67b1da17051aa61ad33214a267584a6a58a496abbfb0b181ddcb859429dcfd3dd5340b1d3700714676080e20b5044c55044a26758a1b8842a03750ae8492f404eea809a0403e4f230d8820e4ca417f1061660e01778071416c9c71be0f10b90cb0e36a6802115e9f00e3300e9418b54648b61d8a3517e1c676228c78b16ebae60e0d0c2c02f6a9d318ca838e4bf0a03e4526447a7835d606097223b5270c773e9e014ece2c12ea6cfca034c76ec020324ddd213dc241797223b60e0179ecb0b0cc39b7171935c60e019f784e2813c9c7814701e6672581e33a44781268da0b7d8628b9c3c6199e3f004e208629e2358c08bce8b2517205c45876610410409224408112246de4806db15c176bd0a620ceb5727aa578470a7c712438f988a333104793ad18b47aae7a30331549122904347b7c46e5525e4971d509362982dceb7d018c6d0b3ad69d9b85c9450beb384ad855b33b2c0a3631400d3b194d6daca2376d227e062860f6030a5b473809c4ff87caa9452bae7b0e69c724a1a261aa6a8d252ba4b29a59c5c8c938689862985868986292716c3042272414ac3e42dd12d9b8db7ea91b631f168321557e4c7200e08f931eea4c89f120ef9b7d3c459d74e2ce349c76d5ad6d1987befbdf75e7c3fcb59adb675271725a74cd8c47931fdf88fc25020f44451ff51199a3af2df0c45922d41e288443870173541dd18f19df4fa4116eb1e17763b5c08002365d87aa817911222c224fd5d059a94ddc830ee550ca2f082df4b494596d52afd0bb66ddb1a65c39d941c409f6fa6857474cee1757408a55572f8985c102be0e2c7fec31360c2a48b1fe3ad2fc861502aed260bf4f71600dd84d2211d3de330203f59e086ff3ee5445ae506cf4d442ed831892356000a7eec030438f0c8c0b764d8dd4f4e4eba462225c3e232279dbb735bcb663689331655bc7b141f32d8d6dd9b7718c69045d117db2b61586d507133bc75ffb66ddb3663ffd50cda8a84d87f3144adbdb6f4aaa62aedacad18dc16485f435235a96fd93e40dcc7dd920bce588fbc16691cb6082d432b864e3cbb7920e64cd4143d1832584dad4fff978426a12bd046018b17156205155e322f4ac321282328a1e98a896e51d22ddb7cbada3ca7445f38bc75772eb76ddbb0ec1c531997436232883305921d8314480671c6417b3069a171cc285a86b0d26dc6be25eb91c51405b11888f364c22483f884c32010eeba136eaba1a55ea12fd494c15c1c910a430ee5e4661b877272b3edc3facc0f2b440d298561a994dd6fea045f578b463ec11b8e2ab1c329c01b08056ba00da3e01468f804770a6e0a4e41e635de40dbf599a8820262798b74414d82c9e1e7e39a8677b4867768de8eccc39d03522853605971efbdf7de1b4336aceeeaaeeeeaaeeeeadad0c3c7bdabbbba723543c8103d9a09c81f3dc42fa5b4a1c74bf34ad7f34a429cc8c78ff8ee677e1e4e0fc4dc05028643690d07436348622d9daf7923b10a0b6c11a8026cadd67533a3055a433f1f9a59aa02e4469cd9ccba7b65cdc0355973be589efb4bb0f7ee4641f16e607d3edddd0dfb4c69eb87f5911fd6677e58ac564d8ac54aa5f2636b62f5e885d08643194e61f528013e035a650f0bd30cf696c9c4fa7c33d670088b4569e704236ad5b60fe682dd02bbc6a53606e2dc413f2f29fe18638b07922ccb32f9f1474e6e245cc1e685dc4a7eb8b267d1ce2ccbb2ec435958be2fdb3c1512bd822b076a5f82f5ff2a9528d689258edcb7840bba4a1543495cb05b436a7338e293d4910f10f78487b59be7abce5528b899e7aa7b842b8a11b839e20c1463c40fe8ff5e3ace6bba6d5bddb66de35e4dc2ce135c7bb76ce92259a9ac2a33b82045a150288aaab4ea406d392d8a12cd89c3952a0aa6d0821b3137625a50239c73da5aabb5d65a6beda4b57a5e9e57ac717a5e73ce686df79cb456d096b7c95598e7e57979683cabaef5d508d22d2f53e3d4a3ee775023e679000024f26300a87ab4c515d008921fd338f588934664b43e19a91e51567e58545941d14764b464189131234395bfc25a32a04039a1de043faddcdda52e798d2be8e697f9164feb77d02d1e289e07710532a4110ea4614fcb03c5e72519ada9a24cd88c6ca95e91d1aab0b8795ccbf3f2bc7a6437ab7d7ae479f5ca7b1ed87f238f15321a87a70acfcbf32a40102e58619e572775fc9fd8b7f68405c389d5085f4c215b4a97dedd52c6d55dddd55dddd55d5d1b6e7885423a726e84c80d5d4af9dd5ad792e26d7254c272aadfd0ffacfdf74a334a69c66aa504210a1a259488eed1c6d8c518630cbd23f214f4597673ce3931adc074af2c568e8c9465d99765d996b5b12e7b6373325306b338d90f8b42a15028c70e62b1a80d2a6eb5d65acbc4b23e2cbba4439bade991638b417b93bb9918da3ccbf26672c88a212ba4553ec5241361d95254f92e674fb8a54759255ccbb22cdb4487442226485145b530f72c8e116ec4e08765a39852f462a2e5a49f39a7665996a569325227476af55a6bad3146ef6131cdacc536c70d3cecacd4c6b549213485d7129278e2464c0b605274959a41a24a62f372b16a9ac4544a561b57dc984a7de8cc07a6e80c3d4265a84c4ccdd023ff518f86ff792a445f5ec531fd91c14f8e8125cb5c7c364dd5af120e39b898fc870fa12f1f4eddde18425c1e380360097c7c4004af2cbc7c4c91e2aab5869b9612d630ace1c97759966d5a4a4daf3c4e01b56896384153840b6e31705335578a019e7ea8f4ac5aab59a84600000000a00013160000200c080583c160403020cbb3181f14800c5e704a745c3a1c0a64490ee4408ca228a48802042002083040880cd99005710c50afadba54a793bff4224110d47c37802b676114503015164c626d49ef0b8a42f8a0ae940875055936c6554393d739505d6f4fd4200c644e253a9c591aa496d4a668f60fa6be33e32a443895ea699d53192d362cb68133b928ae3209fd469fd8fcbd2430ad4c28696c1ed7e808b30bec7486d1e559474badd87df8889c2c600adabf8163f258e3331f8b07999bfcde2dd12b15c20df6e02393c227b048a02ed75f2b0b29b285502005b6be878f7c09eb4ac552a2b4bddf1ff5d3e3c12f6e61602da9959c661f11f4bf21672920605af1708b2952b380e7adf7b7b4b1fabdb0c88bcdab748422a683e3d46a4d0a7330c2b17906eecf425368ce52bd930895fcafb78028a59fe10f93ba21a907ca26de99bb62661d0223408f912b1333eda2a27cbe7eb2a19e5315f02f3b8bdc30fbb95dd9d0178756dd7f0ad4a24faf119f143e8c381135175d8079d6453ba9f38a722462180bb15954e0c254be729c47842dd74eafad183ce02bec0a9f61148735b91b64dda2a00f94efa12953750b72af0bff5264a9d1f0f03158d080bdb26fda469797fd842035f7fde94bcf379f83ac5fc1a98eca56fe523daae79aa851c58974b034c0988d45b1de4f4281f60841b49a8906c77805737d11c7b74424b084c87c8e8dcf80ab75a63a083d703dd5d5c0dee1e2284e1f3e29fd6f93293107e7c76ce862f56d400d7a8c56a9920f22f72e1d1e9f788cce8e09d5666c14b3acc7531d439942ceb814ba5f62f9d70309ab10d26fb4e2001eacb7aadf921f69c442a5cfc4d2cce1684cf0039f395206f665d38221a535b5159c96e07ac21d58a15bc2ecfc150cc150ba286841361088c2b3b40d4f3a22a251a00d2a986880d341369e662db504e9b856ac1c2df858bdcf0071e6181b9b323cd97a5082f438761f3af5e4049ac5895d1404774495c223968a1f025a7cd4f79d7f7fa91e1e5d246d5715ecfc9d4897803043c06240ded8d06a1a764b3af3fb6de5745072782f858010efc2e382f3415ba9da2b2420afa4dd03970a637a1a3b175042d8c26c08e2488d1bf8891d4b5a5570a4deec2e7cdad62c6d72c1d2db05af1d49183646ab28151b3ceda8872aed1a3dc6565ca6c8dbfe8ff948c4b8a8440e54aa800948a3c0f95bcc07805366447a19a1b4c8d5687931a95972913c8843e7a606f8ce902bab01e898034b759f588807484c8b8ec45de6de8417e86a520dc433b5935af717d28476d077444ca96ff7d75da52925e68b4c99da2d0c457f8f909f4127c12dcd255bcfb1f730baf4741be051001beadccdbdfecf58e92ade37379f95cb31f34ddbe5efdfac8557db78242cebb9472a74894679ac6703f6b2973ad95f88486a7838aeab5658007e4211da81022edd814b018ee634460020113d1f91f8e88f6f9b29c9880f6d0216671b0ab297e2fa3de003d408401fdb5b820958d0f99d2a24921a5f8d3e3a654b5ec50c6f4973c8a36f299d2f4db31056746b7c1dc2859b53512a8424c2b13100d01fbce04ba3f21ae31f7d509e0c90469881f00767be316019682df79cac4c4d289ed7f7198c35775f2ce9d1c09067286cab93651927c2f5c81a93af3e6a7c8fe49925910d18745ee23931a1dbd5dc50d2d21df5d31907ce3207882a3f80043f1e78e867167b07aa9b0c044915a3f142c7767f465c315fd33fc76bd6921f8e0092360b824d892e94f5080c45345ded4a335144ec31a38da359c5438a47dcac6d39c5467647dd3c6283fe0357b43d39119f204f63c4c93c2d6f00f53f6bd01d3dd615cd17434123f25139ef844807daa67c156b7e64bbb1862822f3ee1105c78ebf6f41530fda9eab8ec645b2f395333e3d3e92c6efc4e75b069e57c380deabcb5c14799e6770c7da63a76f48e38c2e5c8fa23a6e85a540642fc7da361a4ba43574dd519595e39d9c5f51114cbd5e785222c98a36c4e01529b9d9466f269b803cb8487fd4766147bcfe5463576bc61639449858b66ca794168205036d09a0654434f6ccbe47aa3f6b74800e24ab683ec57b110ba18f4d3e1e70e5a84de5bd1119c450f23071401e810cc8610362159a6ee6eb98e49baf063f910c20c13f60f48af623b20f0c88b361280d9365a8ea192b4c5f8792e824d68f8a4dee9e097bc6f445b2e5f164b10c83d1a7e14a87fc99959085b0003659ed59614806bd4adfca316a8bcb09a9df388868ed80163160e223f5dcf7fdaf9fa2a7570d7d005ddbf5c4a8076498960082e3262e7315a30977b9c4bfe3ce2c20a4a77221995b4e4e72958af2664b291f6a848d1fe98e7081f6719718d137230540d894f0b54743fe1e338f04080e7d25517c79be125b1c8be401c6044332c916991d23d229c0e90924b2024258b6b973be3d8e4b446252ad878fe844d5b53ea3bc45ac1caaee894c6c13fe47c4f425977a5a725ee1f8c9cf7c093d3b152b8277174624d196c223a615eefde46046d5e226899d4e775c5621e5ab5a8c75d997d9b2c1a0e241d0761470b2794f6acc0e93d662bb3e0e16783f1de41475a10df3fc235a0047856ce698abadfaacd0734f9fd692f9a433e020ee71198725503a5d4a09c2d79c18718f18c255801250603465802c54a7a96b71d46ce597a453ae38f1a9bd354f775c77d191294d1f5ba647b43eb47a21042cf4ee89143181a7c8afa71671fea7a4b56a412acc29df6aaf6efe48bd52dc0d73db5243370ccf996e3c9cbbb5b15fbed2f761601d2350e5d01d2b725ba2cf1b7cdc581e7c702920285c0cc9eda56509c1fb871d29bf30bb071449352cfc242f3dac8cd9207b8771ac34cda3abc490f3abd71bdbc9d74af31ebeb6ecc69c07972d74da455396e25e2ada1dc388cc66727be204eed5740c798a812ea210ce6a5e7957d39f57c97c0ecb639b6e41f933be6c91aab1952c461acd1047c26083955bc68654704dcb7396b898e155fb195e73c4940154d30f4495316992763c3a4e1c1939ebe26fe67565e761eda2cc7b45f95a64cd4fa82396a07fe0009f316241179fcbbb3c11666fcb639587fd74e39e90af7d17ee0ce2d7900c28a0178825f1c122e8f0e12e41ec4d0462dfb55dd6cfdf323f7cc3e31e642bf96546dcf6b2ef3249f96294645cf1bc9f53432ee78c77b9fdae14dede4e5e17bd822006c07163d3234b296d4d26da0d3f4a82ac41a08786be13bafaf2c4ede2ade1ad56d3af25c499a7adf1a855884f0c5864ba5afbe96b4e36fad6b64108a0c285d94b5a8e17d83a272f7f5c5b6977820da3d3c16838fc94bbb36619b4fb1247c8099c7e95c77086bdf7d110450af8dc6d3c49a9b6ef36f4643d0b3e10c196132021fd7c065d5c9f6a138c01b04de01e7d6add1c23f89faf4e0a95ee2495f6b6a77b109047586549f924a602085b8f37cf693f9b9c8ad0ee454a297aa1aafcc2f49a46f5b9d826d8246654b468bfa539785973a950d81509db711d95e24e0595574a2efb4bae34dcaba2ad6569fc2bcd3629178a2e9967c2104f01a4a49967adeb563869ab4412935ff9203a125ba95e1ad9d02b2aed40d1dd7e2318685b2dc2279a34169b9ec40d9153f5ed1c44048e508cf5aa12eef596e1fd0abaf9dffa33a9001edf60b16ea8086548da8e4d72792059b8df80205bd112b2b3c68feb350d081b32fe584edd45f8bcb9975baf24803079560a1cb1642db584a191f0c3200c2ce444a8d84d5c545c871fd708b3914c509a8b010d10171ca17ce7da28de3ae7f0202788860b36d217cc5f9a03391c0fbe4a6e5c5165dde212a3624a4199630956f7b1d733c045c0daf5c4a43bbabfa55d012496be59e94aee42593e35eac53944a851db0ec531c8868a0bce17cb6a1ca5a4e1e483912ae7fec0ad2394fa81c0fa6112dcc1d6ea065f29bb87221326d9381389f549d656185885d00067b306ee71149ab12179267c46d69279d915f945e8342ccd6842acc71a616ea8b30d75ca8f4daeabd7c8b6ce2b5877d66b05eb5129d9d0b53475879899abf41c43bdedfdeab800384e118ef71f5c1bb8fd6fc3bd5a31a35bd948669925eeb0afa5d7a60706c3525cfba17c347309cfce7df3a060e68146de48b5a9a93c5490414966e0900dc7d5f34b9fee90791104c72be8bb3083706e3da38c6846b2c111d472a101c0ae8ba4382183232cb29a16a8049984c3252c223c2fd66323e92df0d1a806481708df022e6119dc24b3c3abdfbb6a4c41275e94980c9c680715b5444644273d2d4198675b56acea6c100ec6bb19052b5a68690fb5f5dbd16b8850e886ff43a223763455066e03bc6d030a6ee807ba4fea4ad7203a37caef401b1e94ad31535956eae6dc8cea13c86326399589d2bc24253c52c39fc81a6cce2dcca3513a35a518889190c5a202723475e752041ed2921a5bce62418246d9e6224e4841ca9a3806e7a92974e4606923afdfd12d4890f615c7ad9a4377e52dba7eb0dd4434b7059c5eb7f524f4ccea1e98312d509d253081e7632e48527de0cb06c2ece9573359736606d069ac8c16e7cf40306e36d950569e74988dcdfd6ac59a9147a0ef0456fbbdd793773b4a7732ca1ed6ab051b2c507613ddd82b41ca3e22366354a60047364dd4d74db1b8fca38127dbc593236839e3556b59842c0215e3aa79a08faf63501345cae2d1278783396d5079607c772cc79e1dbac35789e08f169c7e11832daa9a80b3c0d9a9c9cc039a87d8239e133851ed24fc314a56434a4f4dfd58320183cf1326e033408b6f5052caa6fdea3ffd5cdab824a74628b924cf546e60112125bb41596310ed93c318300ba287a7d5b46cd61d893c7fc1c7b46c216900c3ac553519420176aee60d1a705e2ec9da4e890d8ad16c2e6e49469d7cdcb04d329ba1eb3b4dcab8b6c37355c039a9c39f80462b02a2d569b262cc768fe70250be6491333ea8dc1b02261046bcf61e056b97ef7e3e12d7aa343703b4c6d3baf63b8ab7840748b2ec8317811f8551541fb2526be7191703ff08b926757636469299158c981aafa972e8068a75d5091aaa02849b82dd525771b7d4da7f616dfb13a3fd85c6070f3d6c10ad2a2588b47d79a55ef7c36dc8795d853721674525356253061ab33fdc775c814a3946700c1c722f21530b339fa129617d13eccc654f25639361a6bad595b34f6fd54bac6bd5d50424c13e78f1a13227512cad9dd9d0138dbc4422da5d25a59f91a0968f2f851e2d9fcf542170dd99d63fc70afa89661f5db105a56e822ebe6bec665cb679c4a2b14bedae03d30ba8fa9c6da4dd2c3e66aa079c91c37398f8385b7fc704e75020d63ff7e38c175fb563367741a15d6998de5738e9402333de19f2fc824e9976fd12f7ef9fd8de11733f207d1af48dee90cc5c701b78d309d073b73660d63652137fe35fcd47492fe6349ee6497436377a7f50705b9b05d42e5e79914e2e14d67af488b188da123fc8a63f4155c96a426307278c1badab1ed9b84462541979919c35aaa973093ad46bb13cb8d8c9de0f712c0b4ab222284669e6c10b4558d2bb9d70406e91b8a56a0be63b498fa4e2a812a429c6f2c572a3c9f3dba16578f28a455d1b6bad6b8a1be7228324840d5b5f5ee6175daaf7f81657c678ed00b9fd350231b43485de3a04589aa300361a5ce919a74ad38f67fae81a32e4d715fc74854a85fd21bf4dc8c2a34d2d20fe9b9932d8cbbd30a7192afeed60021fdd8f3d0f4bd3c20610d5be43d6c44257de6c1af328d44c09cab2d96586c1f7084b812dbd4dce3389802f4185e6842907f886a068450a408c34f7390435781319cd5bf350e4e2c4b57f440ab68c70aebce6bde8a66c119642cbbd093757f88cea8f62417d1c78cded8c7e362dafe92a733453bc6f2b9472c2d0013a655d1325c00549410281e1503a100d9edc7ceee3dd2c7df426bb8ac9d027355a015a14a91d11497aecdab18ffd47c9cc92b155353bc6873101fffc5f7b6547deb7c0aabc17a1ee7ffa6afdab99488997136f2f81ba3b1c8919222a987b614b76da680ba1d27c0da49cc4a586a1ba8ab58df561e88dd4030f7adb7e8654b394153de34e8d15ed6c6352c1da00bbf0b5f83c00d401ac33cbb35b2103b0677dcd1004a2399a65fd619c6cd1c30768539390cdffaa585f34a5b8340324660039ebe6dda7ebbe2d327a3d2c8ec5d3560f9878c07a986ec42e4c15831498227f1ff6b510097012e84a3c8c772116705ef4ba98106bfb2ef05697de2242af0bb1ee16e13e698e9f960212257bf01bb65d000ea281a0f92fbf8929bb73acff43e7adaeef7654ac8af42eb15ebb1085a9e58e1a2f86c449b1f2568c2f4f14e8217f8f57d25dae78736d87afbe0c93c9db462c6f7e4f9dc60eb9ccbf5214bc2b66429db8aad7861906ac943563d2931ef54551a7ad9a223e3dd66cc4921ae5f13200cc05b930e7c099ac0064049b0ad75fb91e512230fa5a9e0aa359428cedb57eeaca885b2e5b5ceefe51761e78df1bcba06f8d53fc83cc42035a312b50407fb2ff93537cfe605ac72ec65dd94cd1fcd78bf6ab15ca4883d4d42f4ecd69ee4095235026ea66f83ad2a2eb61221c36352e963183931ab1aef7e0dc1fb76b442be80ccc2ac320e52062340a246f84e2c686319852304e4f28d6fd3adfb2c4d215bc224012e77a04d4308ff30ee9401be4d33148b60d8b32f9be86c231cbd13075c5ebadb8366546ab630215c8053bc3541d0eaaf2bae9c7fddf5e8bc49aac0b3925a9a2225a7ce2fa512bca0589e8b91ed7a7c9758b7c337ae22e0961da9ee61dda6e37e2872a8779d83f30402e4f97822f6ced7ecdf433829bfce82fa466bf5cb2f3c96b07edad4530bfa553e256fb90afc248322431a3860b92e59eabb74fb504824d8c12162ed1af9a06a598ce9b2ce793293bd0f0d000273aaf5c808904a9c2d3325b462f914de793a53e5622f744f119525dfdb71b43e3eb4a5dc1d7d40f5c37e3625c6feed1ea7475d1acb96c77086a2961ef7bf98738f28cf6c5c7ace506fa7968223f2156fa81e65eeada629bec55ace80fca090e06529fbc814d4a5af65c5f090225c7e528c3f8c26f880d94924d0a35af82066d46f7152d877bca44433610f35f8bc3e04963bba3955a18d753ca4097896db6f6072ba6e55e4172f8f90d09d1ba5771e9ff1097f42b795b17bc7903656f8ebce9bee3e2022ad8931d2a7854c424842df996cabbb80a48f3a17a623fc038475aa312ab242ebe153b3731db78848b2e6fa05a1463fe928762a3d84ab3e1c5c97a10ba2a24a503311a262daf3a75e90dfed96838bbbf76173877d0e7a7fa35b192735b0b1b859d783ff488075b6cdb305c2743f25b2e079da35f6c4222ed38246dd1f63d81ae87142f75ea7a1a29b5de95e48d8d766d60db29b82bf3bc85f018ad7412f7b3325efb6feb89e166819c78183a0965ef24a4df11a73aec03389803e36ac07c33585e77933f8ff713e6fd6233ded2f0b0da6966c3d7eb72f2002ac091764445eec84cf79973e9a5a447db4e5f1e295a2d73b48b87bac00b8e808fdf2ab989ce19e949c5c0d617e6bae4881fe83035eae69660dc3514757a613d1e90b5f84d92cef51b3ea18ce3241506b8f860adb6e24c665123e86d8e0d3763a2c9a4609725f66ec9351d9a67f56fae7362910af8da1d43ea4be0b1524e69231b4aace1e23b29f7533a60c69852a250268cbf2ef40e51a2a20bc5b8748365a97372117b0b96247ce50b01962f302cff1e83acc4c842dbbe28230f7f61dc1733b840ceec507396dc89b02604b3a96996a1a36a845fcd27252a6183549e4a9782c566645265b08f0a6890a51ce4e563b6f27826d469fbe7aec3d795db28e1aea1145ff44020f7cacd49bca6391f2c20331b48b79a839efd0522b3e7bc41100ead9853524bba47cf1788aae25b5493cd87e3b9263d8092ef8d677f9622f4cd62d3bf35fb36f8465f6f62dd11e212566fc23374db95b07d842911e9b5571ed137dfce1cea316a0e69a1e95bf51d9877dbcf632d95db265ae964aa6ba2293750449f4c28fec58a888991513408f5cda1291da9483740ac595f701d6c1b6d1ca480c5b79e4f3c5342a9a549b3070b5ed3181231a1b6c5f3f541a113608adf9dc25e11ce7277e824f705f631e19b47635a8e6a4f533874cb6ec0c81a0132d01a17f512c756b5880fc7646eaa319bee7480948c139c52688c14ee53bcf93b6dcbd186e008b266e1fccc5fa3117758de641aa064ac56eda9c606e092368eae072f5e133abd5ce198cac8badcf42c76d1e2a78c453b096017922aa22fa08766d347215dc7148b3c09e64063d9f490cafc8851b0050cb8491cc3b0b1da7eb889050b0efd38385ab122033c9b84a5db0216ed9d384b831185d93efa68d0b889b764817b005af73c560d8ed9774cd1a6d801d10b08c239e12e19922847009ec43473451e06f0f5630996afadcbf32c087efaa0e69d549ea7f21ca960518012946381965057beae3d0fcdae339af29e3649f96814226c1a1c661e22ddf1a53d912993efc2a9a41c372bf6cd160f074efb0037511c9e8f656bf457ec60834a1179b2e6248997b4f62767bb65368685fe9c6d85ceee2c4e677f63abe96ce20f081898ce36e7747625d4d959b01f4732e3b367d0638efce3855420d3d19bdadf67e129fa5f71c217b2708ac45885bd44e385eaec8c2a6164b3930d8708dd13832e2c4164f553c995cd5c130a62bd0e893f411804b1e8320e9145c139e4a33ff93e87c449e3df5a735a21a902f626c3b6670b22e652047c76f3124d2bbf930af38db5f6e6c186e6ccc299c53bdade7794c13190226d77cce2ecc56f0eba60384f9d11f913a2b10d706ce2afefc8f5273804cedbf15f95ec0c83734be13df371f84485cbae813783ea67109c29e14ac1dba88d74274a42770586552383591426368de78bdebabeb8d0460811908e7056fd50391fb4e3afdd30c221c0674ea34e6ebe345ec5a0f7123b7bef4915d8088ebaa498500c6a524bc659564bd2f1a1256aa12eadd55cf5df9bff5c6a7814fb34c898ebe5efbd2bd06fd40a84c01d73dc054963da1d8e2e1db757e5da7e0f25c6598b3b4658d8801f990c20a9d222ac4f86bc3a6c2f117ca9f482e31a95501785ac0fe97edf0d1e2330136cc9589139b82a669810101f8044d8c2628b8835c7f416118b716f15c5cb33afbb87c40a726a161054898912152ee98594b9b017331b6a073236382d7f8d79785dc3d63bde95c5260dea8737036a0b5e7b994bb4f451b11f0592f8ef83610a4127e1d4938e6058d448918c367c73e11a37d65074e2ba6adee416554f717a6502314294e03d818e601096b870921e98335f6c866af4baa738410f266a45cf785e64d6360fe60a54e819b9de8052cf8e04d7d69dd76350a5d9777731dd872a3fcd97dc1e31ec687707f984b3db5a4832ac042cd41a3607e493426248652b7f77b2b0bf192349802db94f7f5744974e9957083d26ea73c3a21ea6897d4ac6a48de572f1d987e316db756f751892a1201a94eb40f50eb23e5e11fb098083ee01b79207830998b4b05675e2a1b9856ffb309331f164d6ed181060dfac3addef8a8e6b72c91dcb4daf165cfdf8a9da9e7459ec9cc72cfcaa88272ec0101299813016ab60925e33040aebe6697d96839689df6f2fc52f0a80f82594bb006ac3f522070e0789d71b3d8e7543aa6b79cacce1001ce524de81306c1c1afdfd361ce933b15b18361c79f8bc4d67038892b8ca2f90e8a44a3d9d199e8d3069f612c6dc5e5ac49ed50575b03403ee12cb20d1a0bbe931f094c8ea1242f0c4b3a25d0286dd68f9a568a50dd985a3f4ca34090c15c223d86edc29f82d8cf3d483f6cf7b09d720198b146f0046417306723e05c3087bb5cc05c0abf6afd59b76eddbbb8e50859f3a84d440c174477916664208e300e2ab031a1a0acb2847575767a669a7f7cbc72868a6f79fb416e4c7fd35b1ea049d3a59e5b71834b082cb5c77f8db021f87cd1334e3be8f93c5a22791d841ba3d50a0d1fd6b65280dc34bf6ade47d6206d6c5b5ae60682829f1e132b37548861984adb21a620affd04fd64f3110871a9f0558402cdfd1eab5899a8d37ee6ff92bba501ce6cf5c5113e350ec2e00f46042cf3ac7e79bde55fc8daccacb8d3cfbb9841df3d31dd3b38f2ad85b073e88ad16fb40125a3da9d760904e4f0cd846440fcd844ac5168316beaf7ca98426486928fbe57f68d050c99c0d3823adfd235ceb3e670b884e583256eb293c6d0b89e3e9271753c59de8f39a0b320b93ff0a868f6e09e03cf5573af4c0baf719ef60ccec223c06a340fe21fb678d808f965d1b5a7fb12231ddfd02903a37faf159a34ef11a510ad07e7e885caa547c715db98d8f92d492f9cc1fefdc32f75143076210e986f0cbfa312acb2b77864b72a61c59ab5e1a62aaab5e34b5679f47b87efe53ca000ab52fbe90ff9eca21588e4eee6cfb7cdd998c21c6ea54c9c28d177b27a44466522034ade6157b959490f300eedc3f7e51091ff98a65fe6b84bf02fa2e2706d90232b4caa49062c01015831197608d7edbea2c57f91a836bfbb0a7738acf282bcb37ace928954932074d8908e0fc8ed9de6632cd4ad56fce4399ccef0a631a4bb4c56494588e43cad0eb88d4528de5cc1e0336ecfacb4467ee5a70eee2b6a4846f3460a0cc04fcdc0ddb934edf40552799a5dd22ee7e839241522322444a898c927854a3a168c374382dfbb08ef656b658621788b8d4e1eb16a47ac47c547a9cb20111a384d81e0b935c89378e42de9d195ca2b48f4f7da632e1b692bab94b3a0e7d9cdafde1050f908f263f727a3815c969d6d1e4bff411f1638c5ee01007b98d54069f9f0d43d3cdb2248b01ecaa869c40322211c6d2519d9929c1f9c80f71d99f26a9aad238325bbd929692151ee46e24f00f348f1189231f333fbc9b0ae2846b8a63c6b6df962400dda72681c887794246a1d0e04c4453baa720d9ed4f5e1df8c1741a782f80ba96560caa3f6965ff7764e4e16acf6c12851e9644be66af16a2a5ca5dcddca2f602f7afdba5658129fecec4a5171a0a3a330922d2e96c3edd7442a2264a9088dabcb4bc8126be74172f2b3c682864c664eb235b280f958f236967695e852c4cc9af59318c6692023af89a84513011290788d06fc2a9242c0d3cf32ea9f49a794f6fec1dacaaf91f0e357eb6cc65f05e58885401d0a35aeaebb5f866cf4c9bc757314f7bec63295da4b4abccb72c3e64f86fad2c2286d9b186c73d80c84953febed36c6f5583f0132d941a9fab58287d4bc7fe29a6cf5be69eaa81e486f1078d7811a8757eb6a4ca2389696cf9e30c3bb045892f32c87ae95b30024bc51315f0248f34fd0a57a44e8658492f3f3ce8511f498defcca377009c169cb44dac59ed7583c2d3cf6b86a2395730ad77666d18a382d83e63405da61605cccb14e5c80ef2a2f96f893a13da6e47a556aff9d5ab87941aaaa8be3bdd7aee9bb07fb14faefe8c85b1f84ee66ab16e9ba6c7efe03b573c9e12b8bc0f235f98cfbc4c372e482d26a3506578cb2f0062a02aa3390dc38c195aa06293590afa4e294124224fbd0b4d31dabf649b6fceaf19b3b0d92b972b4f9660a0b8e6fb9d460461e6168e4f2f6c78bcf67a671c770f50b9e93247bec4b190ee70e638cf10f172d8a7e5d56c4b06d1ad18fc94861e5438001cfcb60b994a59701f1ff9e8d0bf9de4a401d7fa422d4dc9bfdd36a0c4c4fb038674510944d54967323eb93e2a534b5f183c6bd586273fa3b05980b6eb4336a3ea3a0ffdfdee600ea588c7d66a564bbf996de762758562a3ce6f790ec5eeabf20191fd5b1ee73ed7ee0d454a68cfbafaa642718b2a1a3c77f085aaee63a105732a50ec4efb454e44bb04b9cc793e30b1003dead1639a85b56264ad40d0535f02aaf14bc8c1de4db1ad16feb018a5d17699069fa2c8e691072f7ca34c3cf379c0ccf119263a9abb863f29ce89c8fbbfe76cd9ccb9f1ad7345f6b00a173476364ca690ab09e69b2aebe1130bdd54504515f0dac7fae4dfba47c2772030e2e636d9be40c8a1172ed111d55c3e029b7e7f0a440922a2f040a4068a6e1d470a6644bb8e8080564fb4c0a6247ea46a15e48a120d5c36e23486128772128699a791bce121a45713a19144ab0051bb0ceaa70811c9e607651bab6b3ef011cc67f74c9b2abfee58a24ba6df6f980d1178eaf0405df75db163d306b2a6f4772f7f5e803a243fc58f49cd0f561fabc94c214ecce76ae4680266336355340f89d5f93e37b9e53ea9f96c2f827d029624a25a58ad65aa255a8204ad455f09c1bf7e11ac5731f479651005adec48fa2095a4b27dacab03e99c39416603092fcae89c0baf23b4a2ba4616a71500dc8503a54f7d559d598cfa70437ddd202f31f04cebe9ce259333124afd6a11bc8d251866b9b6428f9fb2301499a360c0ddb0420e1665c77ee82fbb48ef966d51649d1df559a4ae7ab21372f334f65663b1771705d97832566603c89f81b06448f971f292e761a524ae1b8b931655ea0e74ff5351d53f1117dc2edc4eb344c7afdf3d4a8de9f843b6db2ecdd0d8661e24bb856f87850b8fb08dfbd5d0c0b1e38613acb121730a60fa282cc644cdd89a6fe62bf43c1e5888138663170c3da4d50b89d4b9c3033fb324f09477037b23c8b673a469f5efdf1acd1fc9837245b52bb92c0a34a113bdeebd90c34f14668843e912aa459908e331ed2464b35a711342952f0107f3337473df6ac510fb1b00bc586848a15554c02e32810ae919160d4b4ce622f5b5d3d176afe3fa9fbca210d6a52f5358a2fe8fa1ac14e651c7bf1c5d988b6fa8686915127d4217ed8884f93bb65547168e9e90d8ccd0f27277c2c210f93419e8ac621ac4db9d918552282dc759ee78c0be86fe4594324d14f744aec2ebb8334c50c261bc11711af63a9f36d8e88975be559d0e69894acb0c7d95abe604dd0f1adedd66059595f1258b3433a515566828a061913d696149755da52fbbeea6508cdd764e52ad3d3774c63e38cf190387034112750b33424106ddb202cad7e8cb54042112aad2e9d63f3c85c6a8d004d25e58bd7bb7eb41e56d60f0b880f3e094d60a3e8c33b134309a0be3179e6821c1a19c561133ada2bc74a3dea2e36cc2570df3119fe4dd6c565aa9a4ed2d73ccb9b77e6b6797d3bdc95b0667c1bbd1ade4927db884f20e05b25832ff037c2553b9f69da766e35909e48e4bb6959451d5b9221e20e12a2990afa529d26ac7f05b460d57c12c61a53b712f72f00c612bf95980d9c35a697e25c2ea2722dcc188e041a7413235e35125051e41a027e219c9b9deafbda94866ab291f2f8bc9d18caf500d087448301deda4a3078b4ea23bbd28ae4d2fa2aec9d64c139de7173002a6970e83f42498f52254b74055944b0b0d3b64f9e6a7d29b6fbdf1b70075021dd25fa2d3aff23d39894e89c95541d7667a001a244c1969a97141441960ebf9198ea9c5f2f723bbf21d5dfb606c7e18f7d7e04c5192329c43857d5ff5cb87b97c59472b7cf381ea13d06645e7aaca6b4b6e56b178df8a67fac0114535ac9d79f42ce4a4469097fe956745af2257511865418db9121382b070811ce37023706fe10b439352d0b5b8ac4251c8b23a87a13bafaca4c95bcbbb1931e518a80c7638c8e85c517dd18bcc5a019f3ab68faa03f6be324a56c1c9d62e1c4243498c1ac2ae81c917ea5c0f58605f9f8a541f501b9f6e8acf84342d8e293627ef8d58e1402a50d71a7592f10dba73740d9f616af5b3e38bbf46dd966f842b47d53b4eb8658dd27bc5ef8eb9e4ed2bb070d300ceb4b449cfc8e6071c5f1b79641276b653588bdd3af4add8b148116a04277c2d0fe6f2e2997529adb780711030d5d50db3feb83cd6052ad16edaf3c7a7d72b0a3793d0e82f176800def0fcd6b2011483ebaba8ed2294a30c4bdecf03c07d1f377ce4b58f37c60fd0c9f1bb68992fa70faf9ad9898095e3f4a0bbace604e1ed510423bbc61b2d1b9abb126cfff89b887d012aaa4a62d4269e4eb6f19ae6f487f29eb0c23b6cafd9312b09fcd70e14205f81c279cc765a513b5258846a3be5c9523ffe4ede858c143a0db805aaccc85d975b35798b0ade787d3c0c906486ec5b4558b34d9d211ab9e33b74846251103b854e3d9d42370a7863aba077382e4cb7709ce2976f9b9f1b2e76c1554b0b87940990ecb51932c87b1d88bdc11cfa2f8560963c72154a06529b5f1ad16d2b452c5aae34024db9bb27cd27814430ed764192f9a056948bfc22519425835b480cd4b3cabad1782dad6cdaa40b7ca8a3163b4a1aaf2dbae6badc61c58bf445ef47b218b025264a4a5ff2fa8f449fcd9a4cc7f07debf7de3064cb5cce0b12e2318d50cbda16376ab94a8b93c6bf242558d262f3011761e12669c543b025699377eaf2bade680f2ebb9c1a0508dcbd1c254938b11b980c71c610d92a098c149aa43a6141c44a0a8332719fb23d7afc4978840b05b2e8db0714b92d53d8a8d4c854c30d39a5c4e11f72c69bb749c99f2b41d289d5919dfd108934e37987794a84e2fafafc8b7740ae771cdbed52a207db1c13874060d2e1b2572f7418c83581ffc7730e48400c7ea8d41f1e98ec2700feb471bff116346b3cc4caadb8425e5965d581c6ee86e49d67a81573a37760d19a7f07e30943e0a7f19b6c5d651a12c6818b77e8404c9cc0b8b8447b17e0a535f13b9bf2a97264599d7343121371feb6b57364f1170300a2df919a8b2d8b9e17820b3b19373f9b5b61ee19e5203b64b0cb6cc86f9a861201a4f613510835ea15b1c6a3c49ce1db1de5d27923fb9e8c594186db008de34befaabed880c7d760ad0cefa2962fc30a69c96fdff858ccf1c714241ff728c93aa2f088368163d47b06f4c425966b166a0a2342982eb67e27d623c65419dc8e76b5050eb770e782d4fa33151c622b371071a2289e11b08133fab2d6a6b6cea8b23f89832af8fea866319794816af1963e1221f698dbc78066a991ad68c0e44aff8a41f14bd75eca4f63d876c7bb227a15cb34a812237a04b6f8b51ed6a4509bf907f150f32afac028e83d2280e3d46a4bc1c7c98f275a58970ae08f01710e683ef1837377ede3245a661e2f0b08c5054b57a36492acdd2281a0ffa8f411ea7915286685be37bb3549863185f9189fa5035f4264970cb18f7e7bf0acaea32fc757c2e5919d525e1991997f6e9c361d4e344e9058edc640267b22eb6604f395d098b49e46e4296c45eb921cfe39249cfe20a867d302d82c4451d9240be9f8b6857a62a0487d4128a5db31f6b05ee7d994331ca923f68b1a08c17da59d8107eae9551bea61eaeb13f121af4aebdf015e09ac46ee36b0a5e93641582c057d0f90b4dc439b99d94ea8667692130f6c544d0cd5ed388707a7a410f2af8c6dc11dd7ddb6751f833812080e9accc0c4893a9518013ab2f25992faf467eafd1c66cfc654488aaababe94ed6dba3bcd0753a242cbdc2bc0b2c366f4ec00a07874a8d344c93f22d85b358851d1ac8c62ed30a154689dd5ce25241e3d8e45d98e67f3c1afb9d0e8ef8cda44f19d91b38c06fd9aa430cbab24972554ce1cc6f42f03a71d2fc1ab1bb48e1390bf3c2c5a6c7c7c6d9344b91380fbb9627b29b4c5c0a2646bf4fb9ddea4ddd746e9fce20fe1f61b39139a6c93a8aa1fa2c3a4486e820ff1b185c2796c2910c0daa091ae816db6f02ae12f829e693343f8c6fa8754cb88e8c5db37dbe5be8a05875afde147695c9557d5228a5a26524055398531946d94336eec05391cef1dcd9e0d25280fdc3a6b311defda3ceca67e5e6bacb027e6b3c449915b39d1fbfd48dc9f71b157d620936010a92631b6fea4aa891497b4f2794c1e01ba4a030f8c05cedfee1e392a507a23df5a2a5da0d1334c8fc59e0672566160309a191c0569f1eac485feb3c88be53c454b9d70161196da33e5152cb0c498a90c1a0de1ee0d0907bb59bc5e4e238ca6b951e2d85fe9e8b659a9007ea38114043c22cd266baccfab959540f6f3cf1f1dca41714b225305cac9a36ab036f9317ae2243f1540c499fb1a7426f460922a38814bd98350c48cdbb9a980fed1a210503e707b6f8e91237de99979eb917343d6e86497105695d2b1818a5fa4cc2c050746017900d413b0a8f6066eb3503ee617ed8c22e156339255cf4682f382db89c214320f06ff6461a4888ff8778c2b1fc3358507884d835091c16be8362723e34ae132719059a82306080404fbdc5885e410d574b44e9ad0f09691ebd416e5a100b2576523717ebccde4027326f8a61cad7315698f8f29cc92ded25fb7adab4693fd3a92655b8afbabada203d508433ec14953451b200948b5af90cca6a5b4c67c9cd15f11bb4374545a2f6cc0d7106bd48b249d7c8bc5442781eb7dcb0a3af49ba92d55dbe67f627bd9567b7ceaab6ce8ec9d7c15821462454f61d1923dbd9a22c6a42302372e7da567a521d024cc9341e986314992ce8c77dbec7e26127fb88c1a252497dedc381dbd0370c606da9477350a57cc6593e553434d144731792ca85fc6f3847d69398a5c863dc6277e5dd0e3d806c42937eab831b6d52161a50d8c6cc28757eb130d8183c5ac82abd7b0d6a2f2e4d4aaa6b764b9ff3aefb756546cdd7bd36917b3151c537ffea4362b364a4aa51f5b8b979d535244392071ebf0436edafeda4d83d2da78dc66917627be390b055ebada94b4b3230ea86f8c1336a2b1942a725fe329809d99fc082eb9a3d52c76b069d1bb00d69d3b5db92c719992a1e19da15a50c4951125cad77a35ed82111102d3c8219b6bd25c3c7f34a687fc28db9db134b6494541122227c5378db0ff9bcda20876a2b42299eadb419b23913cc03ec634662e903f7eef181833f254e0a4169cfd315364b4eb0f4c0c20df3e024ac1b05577913fb59a4954ce599dae58f43e6869c12f89ffdc2548cca0e33ebbcb955933067000922e957a008a2711d7d26c0bf629636410a088152a6cef1320e43f55fc98b61080dab58540062bfc66046aeeae4397b8f02cb2d84bd2d56328398cc2e7c8099e77f426ceff975c2163089077e477b618690ca7802fb51474474c4cb839ea60f7a260b7bc991223afb9180195617c28c8fd40ff5eb8cc2671da47e22b61934d1e3b140a82d92bb0019b86612339d9acab061d56f534975a6d7634b276b16975706bae27f9cd6076a7a09d4fe5251d169cd65e6fdaccab1fd20e8a93837cf57a7c4416937d04a185c0795473b0c96fd88a353be1cf29f6ba32a9e4638b09db19a2e68299ab482f0cde05453b30724b5c40c11af5b59386ffad499d29ab7082f684cdfaa6cc5886120cc18f0ae325d0bd81d787373f5fa3ddd60369292bb25b03df03fff58882e960e3e268d049ebf3cb296fdf16042be79a56424f9f570320512bb72e3ccf8613b3861f30d5a0e3a2ebb4a08b36f37024f342c7ed4badae2e063c38193e18eba7f26b0af73ca393aee46bfb08de37373cdb2eead92284b904d72aa50515bcc2b47eeda30f04375767782ad5921e771f54d9a77922f767ca549e3f0e8d3862241ed0153473ba94c59168990599777b8f1fb8012171131ba3aa77aa7f074e7c308104394874c54801fd5274f2136ea4cd9130a68702ec43710da214753fdff7d6c14f8fdb17f5001e81d7c08d741579f093123c3370d87c6b534c7c2f725ae159380a80f4663867c2ebd0849f3a06cd9160aed228120b4c3e75e6ff07b89375bbcd6bca5d89bd0872337c5a1062f7332afbc388d5dfb32a8a2f4810324346179b3bfd3691c9b56bb1cb26ba530456c9f3ca892189c4d42eab61c80fbb4decf5008bf574e7de674fa5cef6bf696c3e9ecda2846839b2485b27ddc58a1601ad94e313c272e1f873aa6b9d9a7096ac58b99f4db12cde69a92597584e0195264422674391cf3bfd009ebc466610925ce897e254e233fbd8c316f75b4bd34df45d3c84898857c74a3b079a1bf2db64c435a98e2621265e90865f57865f35ae87292a033ee0658c43e490020efcde1ef711d645c59cf944b629c47d44bcd03bde8e837afa1e40f3d2ca28d92440fe7f4efec2948f143e31dc40974889986a87c26e81486dad2d310b4c706ce4a25d701a93899c6bc217a9f1336608485ddd9a0cbe3d4fae30c5c3b95d673cfdaea07a12dfdbadd893bef9d788eed5fdfd91271af267939dcc4195b6cd0c9ae67ccd4a0df4961dfb765472a3f52b02a97276633902990d22741b4dd48bfbf7fde272b61143d4ed1d9bc2bd6304ec88fea4532f4c3245f1e9161a2700828c0cb8697ae65bf8d89663d2668e49e6e5b4598804a2964b6d9ab2a6a50bf3f8d7d01503218c22b950859b65415bdc94ce3b9cfdee87a9241c6f7285489ec7bd8d8b378ea25dc75db5dcbaffecce2a6f7cb2c945d9a4b26c4a4ecc6674789a9d67ebfb23a0e9a9e2ca5a25ff1e814fea26968ca46a67f91fdbc38c31124edc0cde1506faa4c0deba542eeb6b6e795faf4b6e86b3d54da127be3049153e8f3537637a2b7b318bf62ede46c0427661b66abb84b39cc32e64f762301e8ac592ef36bac96d7c509b50f8ce69d798f3bcf90821ba0ee3418f96609b624c71ae460563e9009ac5dadbd2f6c5b3d0f17ddec161bc51d1c7afc0132e9b68ff3e05b819cc96eda1fdb792959340a14941dc9cbffa74c2ee4678183e082df67122b04bce625c4401599c435345942e1052c619683783656aaf65b5287d0ed6c86814a4219db492502f89b05d071505ec53a83c75e47fb6149322f653622eadb376dd79ed1524c51c9c17f92533b6db0a99f252da56c3c0bc21b699db1a4124e8c50f549eba0c4c0f97b9b039ba532e356081bf6bd0f70b771f9c79a5144d6af7f70c4efaa60dcd9ffa89be605aaaca702f13d1cd5f858246b40f9a5c59c8d8f35e7e13ebe302de6d3278bd912c13b6dda42990c8e699ad7f659332a62551643571bf741b37d8e8f5b329eca71efea4248eb024d3d97cc52eb738e65c50b488a0b9ea4af0ceb9959ab3d2a2f9a29509873c546d74655f93b25c2e8dc63a1593b1252709b6e0a131fc7c254e0f99995872d1c31b0a83f882f783a1e00867ddcc11ca1ac30136b5a796826988316b3fb45b3ba28e34e5105c089845079309e094700dcf849b115649da0e60c5b0f395b0454314d54b6efb6cf4566120cfd791316cbb846e839218a850afdef466599d777e6ea80d6b8cd78912e47a2c4c3c581808af7d3d76b61a3d89ad9c3f93b9b3a615b4ea3c114d52a52ea6795ced145191328283979d6fa614a70d052e2eaeb03c045850bf78239aa118ebd592705e951bb00ed87c70decd44cc03930651960306f6fb0f649f038171ec4487e044a554bea14473249320e3e3128105ce560cf94bffb0b5f8e8aa8c366b24507f0783d690e60742cde0808735df28c1259e6db0353b92847f777435a44bcee4e5601499896b2216aa903745ba590258dcdd6768948d768429493754dfbad1e0868b9505f1b880a7263ecd5827b55093343472ea935f89fcaef8d8791c4abde7fa1248c845cb4f1689d298a583a568e08d75c92a1260be803180332d6ae529a529fbf650c9c79573ec48231cf89b87ceace64e5308d26733076ea1b2b1711f71a7ff8f5662fa5992d06a26de29022153e216bdf70fee8e943ed3d04b24e24086a13d9861bdc99dfc3f30140584bea798f76dd09b99f88178d500edbdd048332eaa8b682a68c30e5a1a5f7093af6dc20e2848d494097fa1545fcbb047eab9f5b88e3cbf86de390f47db23d727b890e358ce249dba81eb9bce387d27e22fe68d59c31c23adb98c996b17204ae7e61e6e39895a407ce9509eb64988c51de1dba6f5ff1c41ef5b2f4c3830a6110922a4d85085688d2492137b5e426c170bdf6ebaf775017f5f1ed3d0c6fbdf7ba1868b85c08012a573866aebc9721107e30cd8903c61658e6574db4cbc7cd2d187c1cc778e4693e2535521d7d48a1a5a3f8b654d27a3b6c706e081a3f7a2ea292fa7afd5f8295292eca5d91f1df692245597b2c864c327dc809fb717ca9092246bcd094d2eb4b4d18024f29488c25fa00a1bb7c79c756a53f8b3e511af1ec51f0460a3f9f79854dc5d302ed6c1b5e1e85c25ff9110c087bc1e9461071a13e4f9cac5e4ad01ab08edc0ee963022d37dd8acf8a3a4076675579fb87d8d80ace0ac73dcd5b04ef206eeb647101f15709adf0c5e4ed6ac39ef489382dc50910e7376470f2f73d7cb33f880fc2faeb730d6b215af73be5bd727b5cef78f3a184812327e27e447bbcc9db5871646f5096f02761accf32a68abb5c5b5f952a43626ed345b7d059846dd90aa1de2ca1b249cd01e2aa2aefe2388bfd632d47858058950eb9876e4151313ba62956f6a61f846b6f4b7e3cba1f61fb492cc519607d72537f362b53a3530933d36c6c1248b1dfe9c759c01075330a80c0cee24e0427cdbdf2d0f9137d2c28c3421c9fe396c15d7c83137e81cf63a487acbb1223f4348c28b860bddf185b7c3f1794f52c807e5bb91c93325176c13c596df8a806bbf7ea5488d3d4aefbceafece0c363dca0d40087c465aa0f693729ddf685a9b467052f47b57a38a368e3d5e038b6bcab2b0a68289a5347cc4c1b058bedf9179bda137024fdcadd11cc8fe606c1bb71569577e90acd1b249a28306e1e752888092a04a5bbd808ca72565f5da57ff94c061bb3a4d6549f532142f990d8a010b99e11b8fda01ad8892efcde4e549cf70a4571260499747a3405d7152e2764d4c60f4f017825b478d02079c55c3a0673329412dcc8c34f6d6d3bce9d06a95f1930c73ed39dc7a7e47d11b090208194712103d78e5aa56f4f3965c12f3eccd7deb06e6ef83a588d2a7ec2e5bdd70f002d70c93700dd835cb01562e7d6abb3162398345a17081ea6bf3e17bef103158e28b8e9236daba441e22255544b95f6c7999c029520cf9ea6edff56ecc83688e1eb57b7b82aa6775d3e8075039be72e9bb7b3b648c790c9862197dc349d9a89d405a4c9e8f9623a76164c61116b0e9628b94c9e186d4b8a9add3d599ec5c31cd7f594fa26e5a67865a2b469dd8966832744f0b51e857f5283925aa3dfd19cd271948b45ce7d109193593339aa3cd278684918bf8fd65b4afc7d55d2a6b8d5d24fee7cd75f8df7ee7464e9df2a8e3003f161124b566eb32cf3f49e4f22ffe1bb7b96147d163b691ad92ac46173931cf377f8f9efcc2c3ea02108bf1fcc76b6266722e5ff7f14c4a00df3719aca5c7f35c15a71d5fa342f3c8bbdf745680d22ae68b976b4461d858a135d4c62552ade874993d967661b4d8f51a70e149fc20d3c69cee3a7346600b85a82fd8061c4d7936137e9a47a05d2f12c1ccb7451d0176c2cb4de135a6d8eef2fb06cdb22c9ee75d31da50338c7353762b420714fa5c2aa2d4883c0b2d08fdf07cc7a9af17747440465bf156520f6e09ce8ab23e30bc595144f37c8526518666c4a4131a18eb21d7f0ca1b2bc75a1f5aa139c5d444f46e2f8df03a6d4b38bbb54180424059c09c2cb429c7263fe7460027687ef0b3fe41d0e5bcd19f24eb636b4ab8fbe7eb223e239f06fc990484f63d4e9304b6a2f017657eaf24c94ad67d461ec1ced3bbc130f00c1c3682552850f27a4fedc016f3d87a95e75aa8e5456036db2a4206f2cde7af62bc3cbd1c62c4eadfc0da8949e50e5cde7ea62ba8a8263616476e5b27441b294a54090c08f394216720a75de59fd29262ba053256c8f1792f7320c4727c928bcaf935c606608aebe7ebaedaac2175725e51d281a1d660f29b55c0507d5e889d89624706242ef6b1be66d98e61ccc1d6f27cd1765b65c807ed8850433871c5c2c9e18be78f5a82f728139b3781b4604c6de01af5884c2256815fe9958e355ffb70fca1be02c95e2b459aa14d471476e399b9e7ccfdadc4f040b219cf14c7253323098b3b8db38c8e3d40c4bb1b80e8b3d64fea22d2cdc0dfb4238145895945b5f78c9d6e38766043f37d04493986a58210ff3eaefae807244a10d23f0429e82f883e3f42fa34156ddb40f239a6996a6f9033bb68129444a5d622e05d79b2761a11181c5d05da813ff2295c6bd510fb9742f530f2a1ab6a4169c4733b04080194224762d9ae3d4a352c8a369aaa79800acc6acee7c5d6f9c960ab0824f6a8973427928132a0bae6c612b2f3589aab16cbee2e2cd5cd1d612de59ba281a15f11383b506dc50c7e272215349d7b746fd6553ab07e4b6c6b5a4d5e0cc4722e90f9a319ded7bc9e3d740b699c3aaf13478e43dd081c5ed47681fa208ee97bf236be4a0790c67f4b72c88eec604045964741322116c0508436356293d7a557f4a99e8d772982a6f8ed0ce1dc3952889fa82691d371c4c6822812b6d3228dd33f18d794b9afd1c2e4e6acd8b6eb199e2de2ce8c8d8c7cfe985078aed16517ef12dc395f0287484724a50faea3a7f4d871fa4e299fbe724bdf5314a6149fc7f555d5689536a977453ec7842c82de8ce7f2b78d3ef9513ff55b50c65cce2f3f63ed4a937c24b88d52b18e744eecaabb611dad36ea883ffc0150dfb950080371f1e51ab683e188f11d499578b9c0a899f92b678a78ba8f0d571d0a3fe19c99709ae0dd4045ceb6f972fecbab4f9941febbd4b15aff29489fe91d2b0db30dd346e0f0727abdf210644c4c949b16187130ed3867d23601cf8b4eaa2a05c08b893be3e4c4ec583c9916740bb9b2fc99a293d477f2540b488003c53474d5981a8af6eae08327d9d0dfaf212a37a1592281bf2794ba4b69232442ca0770fdb1dc6e93f706d026c3b43fd976aa235ff1705b92dbf6df484cd541fcaeb6815ea2df5405b40a559041f31c387495a6cd54ef5871858afdea7a81f329a2a528c88687ba40b1ca3de39a445bc91eac690b06ebd5efcebf31c2519ced40df28efa291646814495254a0079ab656c82bc7a05fdc0dd72612671bb40f0b818b5bfc2874f9f278c6c555da1c62dd09b660f93c589915bc1eed0e238e800202e4aaf0802d9567e3398508956bb8de09418585bbd14f3b76ece5cd85f325ff8b36797b46671a105e5b81053392bd4bddf282ef09184a9647f71953ddeb1a4a638d57883e58dce6edc62dafb0d7d923e97dce51b81acd30b48c3814b2ec3cc3e1a43c29ba2e3eb92645dde22a2ffa6bd7407b36ba0d523d8b4a9bd75e25688de3b016011704b46e1deba98a5720c9a22c947313eada43f2dd73a80119f1cf621fb1ded41ef89e5ed64630ac86ac10007e0b23a121445b666194c0a2681192ab97fbd6dc943b78e19aa6e0006b74104a251a8a90341f8b9cc9b91eb4f656c0092d1160f7c7c23fcbc8d3045ee79cb95a18347a66579d9030ccf0b553b237bc1955b2a8f1bae320dbb8d7e3f2f6be12e282937a78b7340060a5d1d544744b2260612221b83c8d5be6ad1ead1079de949d02209abbab4182cd9cbae6a3e570599a78babad662d5964091c52429c39d1f2100f352003d7907179d57798b9f997c66b12c106c3877c5c5592fe24b896f379fe8bd00f314cf62fe7c21adc1a5df867ae3e11045dac60f99b7f28fdd330501f61a2f5c734f0e1af49eddd39032f4f56b4b1a62625566b0152456723d001c53646f49b5e4c98702e35e90e3a2fe6aa348c11ece3e0310e4d68a30ddac5237b13c91e37119297ecace329395063f859ae1463a07de15e85b30bb330c98569102b6db3afe991cd8a72c6da839529d3828e942d7445d079589d4403fcb3beb1831e15fb2163a9bdde62126633beb7e087f8fefa69043b64045680ac64cf55952f565ee41ddf0d87fa4f0fdc7f68712ac382b0a51125c37c0d2f7f86621879eeed0e63f0adce3433538d5902d36084a3c0ac048696a47f009ba9044c488e9d952fa1e86db9212066428e25bcd8b760c09bfda529a4984bbf66bc6a5a6770c07befca249231d2e7f69233ee6a4e5778c438d55e91496b3858ae72f1f8c2d4601e342b22d29ec775496f2ea955d88ac0f4825ae2fcc936c72d097a8c85545209e39a9a094e612e1bd505937237e4c3a2a863b377a1e9082ed3c0f7a0357f28f44db626067cb4a4827c4c34a242a78e5ec1eb60371f10246605456d99aec16acf75ca374728691d8fcc874e042273b3d53f6ee3003843efecb9a6f01e524042d7e4f25839c8ef3fcc3f3cb21fb2de22df010734f613fbf463a62d79fe6d107d077426203313f1f12a072bee71a9184747316903631c6f7f299c80eac75caaaf0da2875e4076d5983b62b197d4dfe7ebea0116fd2f144fa08299610e0352bc0c3ed78a20ec021faa4a0549420f56246202bcf341a42ddadc00c1a286750301146c0b5f7e708aec91ec402106eeb205d3cf114fdab314ccdfbd9c6560c8cfe6b4374f637fe68c33bb183c2d3593866ed6c29bdbdad8cc409bb194f6843e6e35caae360e2a80073f8d8f881b2a7c316e8f39f6db93bda6aae3a41a2e34c4692b6334ed40130803894b82a685f18ccb90e1fd5f7ccbf4d6209103bff8a1067fabc442352428717b16ae7a8c28bef54dd787b3ba60c8eda01883f5351d681f60fbb50c029562347b7e3aeb8113c6fcbf560c2e419c022c30fa49714351c37a0712ac8204dae60349934346efcccd831712f9384b2022bdb5dc7a8df559f7d15aa783578b6e9bccb4be41a231a84303e3a6dcea1b4b19f0abcdaaa43f01e64d5c9f00cd90bf486880a175eaa6c8022bad765bd2a5cdd7ec5ac678a68f7a3823d1aee529202456edd399d1f8a7aee96c4a49e1a0d50a781a9a3c2dad4cde8ffd6581ef79a18e7f651e42e3817d2b171fb53b8e949b85af34ea85522f1bd1bb640712d928ebc26861bd9dc8daaba0b3fb106ba0f7a8a31893ae7792579b4cb30bbba6e1dcbeb19ce06da08db1f13239de11bc14786d1800e58a87f1cee28330b745995d163783cf5c661c631d1b62faa5d7987577adaa93430b58565a04f3c0fc6956d256a3a3223b11ef5d4485eb1f00e5d8a86b096d87d17bec505d99a5ab92180b2ad76bf5be8942fea82b625f72727f7aca6a0531b95396279b91e99fa53c1bc478a87fe3769ab558c5bd40baca8da13f538f07a07172545f861f4f0969785188db3c629a2ea58c27b78109eababac31e20e55d8c0ad887b695b0a19ec0e7f17c4ef7ddca7aaa09c82374a1396ccadccc75f124e379b1029876e29890576b20a10bccf4e56ccb0762befe35673a3c062cd82b4eee3d882bb76f54ba27f728c451b64e62c0385e7311c5d6d0dbdea74f0a0662e08b89cb648cd2230d1a7f6c1c2b30c801343d8280e95bd992b00d302f5c99a9b2db1dcc899cb3f28aefec201b416acf7afa397246cdb0a0c2130b94f36320264c75e03099d5ace837e96992c6d338f270aa98e2504762ceea9d2b64e7abb1fdcc93f284bc997db4d5c2f1656e717853e7ae383741d8cb9280fc71a10f898c3779c3e3fcb631bf9dd4c3a22bf974a8ac177ac678e5dfafa6cccf9a027a999b6a3c50025e31274831ad3fcb04b0755c3c71a950d33b6a84857a3bae540ed14623ecc50914c0f17bfe6c0ac555224ad1a945fd6cc94786e35b2424c322a4bc8c1bd2475d881ae982d6bfe3237b91ef2c478fe9e57b21bec347d3e3b304dcc77309d4be104493d4e4a4100bce1e2a02ef45c5953b3c9c55b88137913d1ea2249627a33e6ad171cd56e4df72475c4bc614ceda39ad241e397be51114f740153439ec3e56171d0717e0c62c6b5f65687c236bec48cdd09bd0a286aa57289fef2438f2626ba431e21e0d2d361de8d398a330d4a686342019d48cd9c9b0eefae4308f36f0b0cb7027aacd5565b3056d2380779eec5907c1818a100aca65161108ddaf14a3a4e933049304d51af8b7743b1f20a91eef72d5f74c67bac04c171267d2ddaaf85205c38be3539585cb9cd2f08cb073f043d766222a00e556b95efa5252bb79452ca940265053b054a051a88337999a13a7dc3108b70132d3fb9688a8c644f28f6d4214d16712b36433a6691450ca32f9f8a41a43c38ed691270dad33c70da7bcd10073fbdc64d40e1b8e5694e9380c3e93432f536ca0e1cfd691e3ccd69da7acd1951d7987a218d2ce216279b2b4068407cacdf514b2db516040204b6c7f6bf1c318806e2f5edb491f81edde846b70d084dbffe7f7006a922de317b3e27db53cf91e328daa22f0efcf102107480042c85fab4a745eaa22ead4d61b8855245c6f8c8d87a34ca68b95228477560148f6bad1cc65c4c86e74916738b4e5373866558866558ce5aaefe1fadd65a2235a6be48f48f33ebbfc7ff31990d6a9db4e28ac39b6c6fb60d639cf2846c9bbb97f9deba6ddbb6959973838bcc32e223bbbcf6ca111d394497b98f4ffd98a169a3c2068a57b56ddb4629f5ba9999e37558260ec36b9b22ecd7e2ca9e331f5de7c53e95f78412d65aac59ac19c11ad6b0b8f7061d7d9ba72613a554bbf4b54b29a594524a29d52693b529965bab0877fc432399eaff7f4a45ffae19b9113b295527e5c9ece42625c488abb52ac2e2617c32002e6e795557e5273f2955a10ae67c52da185fe60a159d9427e58d984bfbbc8edbb0f6791db7612ab23b8e24ba5a6b2591c2506b91a8d62397441289364fbd714676aaf24fac30bad789219f265eca2c57f1d36b2668f6d448a8569db192b57e663573e53f364358ab9410fa2fa29a8e26ea47bf475ed290b8cad4538c3f3acdd1dce887a73fce913d5b339c1d9b4e796de7dfda1f55507c8e1b756a66383b35b643d3c9b10c93337641e6b03831d89efa65bbc0ca8f84fce00b4758454043f604a9b448192015869bd3628e1c9d26f935d5dc28d3111959e4bcf6d4a39a5cc13a57c46f96b348a475b84116e9438a99652486ed5d6031b333eb53d3c22206dcde0516af2cc8046cef220b969d59b4f43982963e35d8267f6e4420211ed9875ce59111320b5258b4b060bdddce45cc11bbcbacd60cefb39046d63350938901358c24097e4a083c0e2f493ee48b91fd216929dff933bbc071cc9d91c822a753d25256519554cd5cb91c52cc1c3f3dc1e9aca22550297e48d59e427c66eda93f1c92aaccff90a0162d795c2e0ee971713e1c727f62f6fc8c1fd2f52197c81e182d811f0f6c4fddc515375d5c612386cc67662a3172648b1fb27c01cd5c71254bb8ec8fcdfed4ec596464d93c6ee4a8b93f96eff5d57ce5d7fa663e72b70046163fe47fc8cffecccc157a673e369766d3bcadd55c7bea1680a0b1f6e4bc484ecb0c392e1e97c7f5b9581e339c31241071814f0f1c724fcd79d007db2302283fcc70ea0f2946135bfc9420a041943b464b1fcbe48cb4f4d54c95a95b62db66dc53735eb4f4b5e88c963e17e7f5cd60b195ec9b7d64ebe3142108e40fd287cfe8473faabb4929a54f5f1aec437ec857ca8867019250ba028c23aad7faf53d0cdddddd6ba5ee37aac8625869185eab821622b3eab57e7def6047b2885fbb0b958e66701c0b7095a961b0102971614f4d4da1c9052532d5d5da2b5bbddc41b01728c9f8224343c6626a6e599665f9f7de7bef3883c9baf54a1f663831583bfc3221a9ba7d2c9016a11a2442a62e7a6445554266087e91459ac22f303129afd2db13f4a22ab3445fafd764ed57895972cbce25123fd597498607e100899f64701c538bb4d81964051526c731f50b63fa32c93a2de68a98a305e45202e16089154ba85082f1b6d51245b2955ec395a057e7bf028f633bd753964049402d67f8099403335c070849cb0c5ff44524635d47e4dcd80721ec16c28e402d180411a0080b6a79815e16bfac0ba8658626930c7e0221397d098403d0cb047a99402f13e8b52d087a31c9227dd116500bc865833e243208049a01e88524e5f5f25375d012072901e5ef867b2f06bd402f4e867ca10558ce398a4f29a5f6f1638cb1c74cae6666bbcc9e4206490c147bea7ffd5e5985a8efb4566befd534bc8d4452e7353c1f89a21a58bf8e4d745dbaaeeb30de368eeb3acffb3e9a3b23238bed0bf323f1c66cb8301967ed665b339def94b65a7ef29b3939422667c8e414d9537f35737e367beacf8a2f79e5c7d2628b5f4b234104c62e83506ab1a7fe9af0920733ebd7f2d316e3d5289999420689077b02d51a899d828f880b4bc3f3ca0b9ba157def29b5feb6b519ae38c7c5df6eba903e031a25271f0c675dec7019f440a439128fb10b2e823adaf7a17a6a1d9d8dd0ba7b556ac52398ec964be2466b9668f8eade299e067a75ff33f8ec972b9a4069aa6b9bbe6afa5e8d77cacc14f754360d2c0699aa669f4ab7a0cfdbf7efd7adbb62e4643553cdbcb0a183c70c2beb56efdffadb5d65a6bffc5691adafcdfb2a31aa2bf3fadb59ac6c96438315fa34547d9088389c5d4cc15a7249da1377beafaee5e966559063183c05854ead04b92e88534b226d261b48890a81f409c49122a54a781789ab8a0a278111d473f9de8cb5ca97aac4bc8221dbdf43163f0f4a7354dbb24bc777854a7a96bae3c286a4e7fa33c72aabbea91e828a263572bdd72b0faea1bb84dd3176b3bc2fa699d49c14b76c9588ee5588ee55896231d9fbad096d80e3ad2f1de2e26abd1027db1c2e8791e9e792251ce9e96ba11bd91f636cea6c22489243516914861a8f58b65864766385945667833439cdaa5cdc643b08a24fde45ce0265e1239e9a727b54ae4028a165338202635970a1741b1da511cd55c71f1d363167c646323b8050fd9538b78e5a2253c52951b572812e52ce492b31c67644f6bfaea6d24de1bfad9702110647bbfb59196b2a4a7454c7a9ee77977c438671762a5debcb79eb55bd9822276f3a83712ed3bd284e410de807736c3a922a2a944dbddbffb2bc7f1f7fefd91786b465736c3a92f79afa7f18c9658689145ca1a9b6d086b4b6d4236237beaeb6dd57a9ee779f7de52d52b149398fcbe185b335566372b8c2e348131c698a34698000d14a080d080031f2c81f2baae037ffccb0505a4860dca037358fbdc28870901241c002264fab1d9e6944a29e5386e75466c1cb5ab6d625405f64d64987838f52cc7c850b85c238bebc5525de3cbf53243d80ce7e86242c6781c43d8057f74bda816dff56fffdfde1fc7ffdbd99076ddc2431c7e0b87759fa267a8886cad25020eaef25b3ccc3b9de44918580c061683cd994913a65c7ca41e06854c3ef9240e3b60b0184c1886a1adf7de1be394f1d6be497bc959b0b4c613d9c978023b8139899dc4d49c9027332737e3388e528ca39f3c0b8c731689b4beaaabbae3c9a83a194729c65591718b4ec693f1466babf58e1cd5cd397f743d40017112759d2863c68202e295b104ea8251bc76cd92454c29a5ff943efe4f62679a87891bb3d6da0f634f6b1caec0dd5dc39db7715e3792c6d0ea1a8b91611a26b23b8ecae2f26a1d49b243b4227a41954f6aadb5d21d33b4a51f42b4ab27127d2b8b98b0e3a6f2a7aaee81c70d3b6a0553b474e7a7489f721cff2a7afa12ece03a7e0887616a7c83d0c167b6ad3ba8d9818d9228d060d75137bd8abd25b2e8b11d287657d06ad50c49249216f3e430aad7fa43623b16f0c38e1dfc6439adff154d694e73465e6badd54f56019be4e1d49f005fc171b040800c4e50a499c84e553e30b6e3631c08927625ed06dcfb3ff7dd71af0ecbd9cb9b1c93566bce17bec86fadfd9525238b44ad2b32a986886650ddddebffcf696d0d3dca94d24ebf005e5db0a0c8bfbf787dd5a6ffff5aa7b624402358b002c618638c31c618e377f7711c473ad29196c2700c473ad2d182323051c0503f808c60258a0b7e51d3eb6097875d1b76d1d295c95c57e692c9b82bdb4621c07bb3aff98113bb5c1cd799a117c3f9262806ee4e6f8a50590f947e9b524a2945e1228f9a527aad2d5bb8e55e93c9f42693d6a2feae78974fc09efa79e02b3ef015daf93ee6bfc59edac5a7a2a38d6050fc97873188316e61930f2f9d0c4e6bd1c1f0303aa3939f3ad072a011ec688bac812823ba5b59fc978d9648a4699a0d283b78baa379f07407e4e172b4e6e97befbd9ac67932dcdd037bb924195f6468c83db527e6f1682feb6432ade7d64c720064f2d5280e78aded4e466fea6f4a36bf93690f76f30ad1b4a847daee3a994ca652ddeddf25e24b9e9f86f0d3a659e86e8abba9cdc471a454b4e4811d18df85549d6c453b59a893859cd85377b24e766d5cd10baa1cdaa2ee3cafadb970fabb581733c369928086e2c0ab52832c76b2ebe9c2edf1bc1ec7845e1d1fb87b859909c306842d08ad9eaffdff058212597499761a31acb5d6432c3f4d6abb970df2a73bdad31c7dbbadc3197d2a9cb5568b2a9653d9366b3537a278db364e4b7957f7ba562c23b3e5f77db5baa115e075d8445526e09d8947bea98a385ff5de7be76b3459d3e53866cb2e4d17aa329178484db434278b024826d18d4d0913dbe38b6cb592d1c9f2d3dd534f5cd219a31346e73857ab0d4ef0894c4b288e5ae53c8bf015dac46ab69a5d90b656abfba3f5375e5db06074afd0398eb3655ed99dc15cb14e14b1c51f42edad9fa669ddf5b4bb6ddbc68d1cc56d73b5c25886fc94789eac205563dcc86d9b913435b4a436754865d55415528deca9374fa552a9542a15629cc29fc29faab672dbeaeb6ddb46494a929892b8db0f761103d5e63e5b0c331288684183fa01c4c15032437d1a08fee285f230c624e9a7530fd24f7666ae3c4992248d4692aa1943f7b445078eba9035d9f7a33055f16cfc5118912c52f2653f4d6775cb816aab6fa89db6230ee4607cbf984c52951d83fc14f929f253e4a7c84f7d4a084ad2380e19d4bae9fae9f0aadf36942259531289fc280df44802101b700ef80a753f635f0d634c494a3a8e1ae30a49b8fbf52b7251242275c04f762fd9b4e6601ec264aaeb259972542d9262643255fc3f7d4a67b3d96ce683e6599ee5599ee5991036bcd6741691527e5a000e5746feccc6fa4ce9b797f3c66739f4b648baf973ce34e794bbebbfde0ff05c55dae9ee526bb10eb2b9113753a9d4ec1fbf4d49531e9d3fd0d2b4992a37e512b6388bd853e538668aaa505a6a565bebc54050e081abc94b13996a23c2335ebff7ef7b0f77158ebe28cee8afeea0bceee820288eee803f16206444713807d8537768d8537790c8fed970238d5cfaa02aa9206c8f2a68213047fac9b3c14bdf8ae8ed21dc4fbe57301421802164baffdefbb523832c44b56186b9f23e38e96d11ef1e76d82066b8810c380c53e3510f1f7e98e1d4af821cbae47aada6c964c68fa67aad5fdf29c65a93682591c250fbbc8edbb0f6791db7612764954aa552a9fea5b857fb8f8b913aa54f7fe6c3c76c369bcd6639c83215fab3d96c46673f9bf9d061397645689fd7711bd63eafe336bc5b4cbcc86c98b0c866f607f0f640079338a5b9346d74bd5a5c92c4903218cc9cd9536b8ee273ce395d296264aa6971ba346be7fb00334b17984b5c07052cb0c55c22c3757aea09f313b65a9cb23da71754574d5b5937f28fe3445752030f172d4d146abe6889d3d365a2be110a0f4e7ffa037f789a037f6c52d8a04401d14e808ac2ea20a8eeda2d4e9700bcc875739fae9f04268a645242d674cac0e29aaf29b2385dd3453946b2385d0ec305117beae99a2c2dafe32fe03317650a5a079fe1a66bba389cc2b3f345098c2bc0382200a9964bcbc5f26a8191c5c6179956eb26f94330ce596bd38e1ea689884fffd5eade7baf89961c35bf1b68e4ad744d93c96c47d8846c301cf2dc3e6ffbbc2fb268fab4e8b03dc3ace1f31e80c30472d0e123b11781cea969fdbae9755da76138745dcd8a8bf177efbcfb9f94765dd7755d87d3753822c8f1251841101faf23c7c33057fb7da65734ad15b08063c0576ec944793c0c539b409ebe1af6baf905f9be2fc7ebb8267018ded6f0781db6c97751b07fb462c4c864c8191a2177c8878212af3076ad58465a4792c0c6578b538c473ce2118f18e39568b5b5e896a298a47473d1edb5b9a8b6d5c6c234b9c433a7988897341a3f512d13c5607885823d57222872132ed058da0b195ed25c67bca6b03597126c23f6d4d30b43ad7df3f1ce3dbfacb75187f3be4eae9e9898b2668694c5c862621a6ce627d768a8cac4a30e4b11cd9eb2130dd21a288a6ae80a8a1900347bfefc9391bbca06da3008c338670de6d1354c8f3743bc5ad1155e518d35c3a9f7a7842ce2d5c8d2e23257aaa620ac459f797287f3791db751bcc2abcf47bf101a8094638633cc90d5e292647c81511551e999a29b6ea5fd749f848097ddbec495c880bbc82269e49b644615342f6314db5fc62af2f6e02868210027c09a80c6f5ebf1d3fb4bb51bd66564771c55e77d6dd63499cc85010b4d021b5f2d3074c78eb9030d6b77f8e9b5552c365a42c69a049ade56ab1f383d6697d72567a8ad8e909d46037d1493dd8a2314d93c5c10a5f280524574440d80afc69ac7d518fc1185d53fb4a3785cad813f2e8952f70a022df9d25c91456da5ad4ad666aabc686f68b495b6aab54e4f894ecbbeb56ebdfeb6d5c3a2254d7b73be2c883189961c6502c00f882821128331954265141398fd20c9561211582f56eb888be5250673491273592c99ac872c73f73277f6bdf7deab4244169fe5c282519649459545930c3f05bcc4e9aa652cf05de0affa23be871e1798e16d1911dd7befa494e24d2643929c19acfcddb72964fbc722b6d6e62d621bd664f161586b1ac8d818c3fe5dc70c0f43e74ff330d809c84d0340f4d80007c833b66ddbf40ca490863dbb8e93c6d37f6aa294524a2955d140c8a2c964da4c26c7b194463ac10a27dec791ecf1771cc7f18e75bcfa628c2dc6f85aaced16c3aeebee486faa040134f6ba0955283172341016b270417d35503b8e305bc7f11b51d68ce1f33c9db5fb2e188dcd91680361f5d59ded3a1025874d537d83d7511d646f5c11bb819c5148e3273b06499224b991d4da160f0e88f507f2708a7fe831c3897d2047ab7d3299d0104232140a8542a15028140a854236252525e5ff3f8555adfdb7d6da14560a8b9642ad2dd44a61a5b0c01b70d682ca2b5921135ff184e132db23c6107bea30e527ac3f5430d9530f40e6274d839aec9992a252c098c5500b4c61b5905ac26bb6c79a636c1ba58d99a7f296e8ccd8de2a85d5bd1eb36852eda9535429ab92e292c3e2b038ac14d50c3d61f84a8a112c313e546c0ea8c9a653542946785ec9298285262c705818b4a14a61a5b0f6d4292c0c5e6d24babab233c30b2f9830b9aed0755d17adb56aac6d5cb57eba251b63b8ca0c9976c8b443a69029640ad9b8ae900d1b347e7a1bb2211b6a89d60bab61dc855aa116c69dcd2c245948a3734eeabaee1d5daf16972431a40c06e3b9d3e968d185edd83555a676fc92e282f467e4d1777447c791478fea5c1fdc2af6d4770a8f616a5c037c03bf3726c59e8fba4f807467a4c228d0447946283c320d672051a2b20e82eaf2e8aaee8aaa8c50787874d61ef0aa501ef4d120f07e4094d71ed0a5a33be06d81d7b529218bd825fb669f675f2e5aea60ec3257b09e1ab7cd70381c0ee79bcd70622fb00bbf66d8825df092d70b7631f192c54df2187b9ab1a7fec6c816a6c5a7a7b6b0d7f175e156085eba4580dd8e6eb95a5cd719cdcf039b57a8a48dd9d516aa190000414001e3150000200c0a05830171382c1ec9faec1d14800c5b72467460421ac963911c889114864190320a10600c30841062c0504dd906bc98d5cb5b609f949b011c6076ad5833f00bc586f9ea663073bc5bfbff7f24d12abfb30f28ac60a73d00822f7ca4fbf64bee1769fec658e61f3a04a5118dc61f0ea5ada1c76ec0d0d99366329662a2adc109573b89dbd66948b4a09b6af9c87abdea60ca317baa810187f15a91c2f0cbc8d9370d7abe0906a2d5b3e5bf8872e3fba166c00eb4490147b69304c1129626d7a61701283320ad915e065f1f6855151f8a150463125261c4b6f5211f96427b848bbeee7b19ed2766cf175f4781f587a6d38e8cb910f863e1c1c1df23c45d7ddb640141f6142f43cca1dc8e2fc2e10a2226571f4927c6a7be8a63fc7b6133697211cdc309fdd2824c4ff73826e97745c78cb9e95fd5a33f2e481356a310168d6c665ca9c45d2a20b6322074aad3da9c25187d552cb97a24602cdd8b499d91c709c40050620e96a10a1bcc9565fa6a549714a6bdfee1e72fa9f98836a084aaad9a720028a41bef533b6e109d209b346e5468d8c7118ad1df1d0c516a6dbaa62709e06b79d359dee8260050d6980e6f425fe0de04fe6d5307d99a5acc15561a93d44363313ab90a94c3ab0fd7083fe4fcc20b24cdcd70e36f38caa4161d3b5b785549edc8c1604c4cf18381c1d6b3a192c65d2e6648e4bf382c6afde827ed0c2c06b858f84959057c6c23289ff0790e3ceb47fa14a84170eb234abb1b16270a2b6312c27925c214ede8b51ec4ddc8e2103be3ee90f578eb605051f48638937bed0ec92f9da956797539ae9cbf400358ec657f730545e42223c0f96fc03638cd71b4513948755e125aa10cba39e480ece9cb707335f55b20754fe7f9a337d8e0d18e3ac8f9fc71ad44ea597dbcc02e4a9b423cff7e8e8ca9ee2e95561029d859944169d66b41077880fc816001c03b6d3ca9662f9cdf477eca7f943cc306ec54c920143b19acee627507da4c416cd7676df1482a1e599e807a2b9dd027e7acd5f0e3419940cfd78839041ae6f881d2b6da0d966b123145dbd54cd744c9af6b5c7dbee9bc6044e99d9fd3080e311d4bcc868123460cef12c91d2542887234bb723e32bb4b4e9189c3e3244d9ce19088c85b43336bf2e098601c2bc75fad08500bb60857a5e22bc62c1b049113590a9472f3ba8ebc744b83c839916014254b839d38f64dc8539d15b7ea34c119261bc449ec440b2891b037644d9fac44dcea2282a871710ecd4add277e0401577f43af10a6c1d79a9a9cbd763025e14f69b6557448c42b32d54e3454338a88b79146656ab90e7a16dbb376fa6ce6f5aeef8e56c2d3157477597e24b34e47f04386adc55cef967b9827cc057dc31f194375b8e7b5b32be48511ff47788d02888332642704d0ed71daccbb0a1859a214a103b72b734e7f022c1eb14e5bfcbb009e7f821c60ffa4166267b3fdc66613beeedf6431c316423e56f150c9a11d0958b6110404b1923217e37e8ac92eccb141e23ab75a951d434133ee528b1c33c6a127393523c9cc8c9cdea971ad57218fe8ee74656e0d07d889ce49fe7cae08f124aa1d011818d39f4dee0b0632ddd72b6a4f408c2c7226dc02dfd82272e806eae7ff9a682a3241ab86f8086dbaed533703db5f5ad4b032a5ec0938301884e5582aa600337cea89bcf570ec7800ee941efe175460abacff7e5f2227fe3d450d754c39d60734876134ce5bda63606dec0c5acb69ff10486e359694ec6183bb81a2d115589c58092b82a015d8c57587e98d8495d6e8a89298a8fc489d974ef2cf721991e82d7ccdbcca2003b3158a18c1de1344b198f184494a728bea5540b4632851025151218afd8177ecffec40f56004f3252acf20b0dc89eb0573f305e03f3925ad60bee111239593b0d4c8619ef3f0ae68b48e70f4beef14031584eea19b07a1dbceee46fcecbd5fc672671064ceb0965c01946942d2e20df939a96d9774f0c9ff5eefc689f1d3ed70648c826d00f7453a43cc2a90bb8c5a47db03aba2c7bade9d8a80c53f41c1397abc1da4797a67cc56eb6f0397cd3c2f6914a86a26c02ea90c0020223fee46ebd63e1b3f0d25d9605c885a8c7e47a014f01274ed6f810747c906f5fa73ede6a04704388b9e2e6c43d970b6a6a5dfed83020ed93e80954b696921cee3ac2db731591c56cd1de81e7b00852e55e460320e8b6fe86892e0092fefb0545f0e0f31732a8ed60c1e4a2af8cf1ad865c3dce69190a3657b257202432a39d4f6099d63bf3ad538743a9967745d8cf58a8a216785942cfece01413407a79bb2aef8cb225ddbfc8cacf2d35fba6e994889a2bacd48a1fa27e52f0eba3329787b237568709fce80bb18862cd6a04e19a3e11fd11c24818d0b0eabf45e3cd6fd38007781f9a3c1339046cb00407b8bb023cde55390826fb411f9dd65600166d58d821415719d44f2553377cb47a96a3e4a996f943594763cd48ab0bc69167d5c892298104c9aec1a5637a8da874033b8b4c2fae73203ef03358ea4c262ffa77696ebf4156fc0f4bce9751a4057a6566663f6fe8436df60dcfb2818bd1dea04681a11d9049c7998c752eea521fdc75118e8908c65269174d5d465411b054c33256ff572d04f8798b10a10095ded0917bebaae80cc178f8ef2a77afc101d4563cf5ee1b20b2f5ebc5b1396845e9c6aad6953e06033ded1bb01a27b713901cb762e2872a08920166eb7a0c168d6ed2e4e2d05cb5b99b97de329ac2f6cf89b7fa7ca5b2c37a46e59b7943c4c6c32c1865dfec57ad392d76d42658491b7694bdb504e704b2feab5d70cb0409a45b0c3eabbf68c4a17b5a59335d586922914766a183f53fdc0dc1ead793e1652ea593cacba02d90a01478a53fd1e54be7b0b686a14d54a3316fb43f92329bb92f4e79190ac0b8357d5dc3580ee58928f66c41f07343717f6c6a4342e08cd0706d6993710208aa8f00bdf9b8fb9cfb377a3f6eab86dbe58c1dc61c4f068341b2b69f81fb73dadb566f6088ea9d12c27bb75338b8395827d3c206b8b3f52a19aac382dc5ca52c04a8ab6a5c61025211e36d4ada797051488f254c7b8315c2e5a26156d127ebbba649abde3409b21a4a94aa806e30023b027c1aa7eb6f17671180fa26be4250d4e37a9307071093944cbde5562adf020107b801685c55f7eaa81c7b8549420d574448897b1a7612718c950e529d458ac42976c134c1a0ac8162ccdefe5eb17b8dd35a9382bc35aebbd8e74ae1318b7228027bb192e7a2f4778f42f79c263a765f37c18e60f0c76541d985d5a5ff0fdcb4dd54051601236826bd121ae94eddc317b8b712006a8bac5297e1017fbf0a02b2bed198d6c87b1b3967d9e4fea004d520ebfbe682c87549a8d8573e67c31f5731cc63d365f2c01d40d9c5336e4c0d72df595f23c05871776b6533a18d1a95f5a652314e1601ca0d92a27e596a5dd0cdfd380de60ad4eb8a5f1af29563e99afa4bc406e6ddff03a5e5088d09332a8ea6ccd44a754c257a19b64e212b5681ae0f74c12697bd94317a407103902b09afc04273dc4ce4d9f00babc02775bb7778a052a270d50326cafbda2081527a6bb7d73d93921e7222e6218c77aac6fb790c989da0bf341dde0d59e9b9e4d543cda0bbadc57ec05801eb2f52bdf0933091a139e149b44723a3f9539aafcd73129e4c14a41fb6b257775b9131925a775babb762d464360a4cecc8a9c931ae92ab0c45603a331b894fce96e7440b3ccddd64ac3e95815076b175324576ce42c10a2189e4db0ef1527adeb6fa38fb972933b009034a31ee36ea176c43873f0a438289e893c41d4a79d33882b9a2acdb6f1248f9044fb9361c2c307514b22814a8e240a251aca632711a6bb890455686275fa37eb86399df2372898515b84cd14a138e1a5306d5c9bd713fff9b78eb4be1ac27a7b0d6a8b40dec98b4a286bc9a947f323de256e58719d539233cacf08f0aa525a78949d68ef7d10afb0aa5f99c38dab2e11fd97f993554a773957cde3662a6deee531c577a008d012e3a07e4da56be60ffc52b9bd28a568991aa58ac2adec26dc569630f6ade58877454d512cec8592abcc02c2ca359027d4758751aa66006637e59229f18b2a82f3f730f846d38779bb0802065d05e02d568fc8d98e01b2d34482b0d3f808fa392c8f57f3d0100d67e01d07259803b2bb4b6ab240ae66e07457bf8ffcb029e45f11c7705ba6f04af3ace89f9f9d0c0b38eb3e864177fcf9e38fff021863e0941cb36bcffc6a303e33b6972c39d66346169f5d5fadf3e0e76245093ae9b3a9bdee8d1f9b3b41ee92a6ecb579d10ba6a969e16bb1d35dc89c9e0eb79a0abe87dc58fe33e3efa7e486b38088183815564953991c150af7bb7918abaa54d23c40a854d62c8782d77da0391b04988703118cd839f497bba55daef8e3726630cce79a7825b2e00751e9897c7f0fce17a46df15c77ea5f027ca2353a90250ec07e39268e543584d18818ca09ac1955c4f0c1c0e9ade9169f09bf28bc1ca5d33a565edbb5444014095c5d4845b04f97aed6fe0a9637db967d54e7cebe3688fb8bff4e276a30aa6a81abd9ec8f9b5f301f0fd50f4f6e055e152a124f1621b78819d52480422b0bd90aa0f7a06249d802b43d4e11deb6ec472a40711120983f128dd61485901351dc84612225106feffb2777f63bf4b099d78e4f104a91cf489789a664d15fd1ea0dc247d9a5684bcb5f0d63b8862bdd400720203247dbc5f09de416e2b97ab08ccbeea19e58299d141cc3c7f16a1d949232e8fe431aad494484bb76c17fec7f607bc73146b326f25497f7544df9f42ba9aee7c94ac14959427f0a784297b1e53a9c4b6b0c3e267cb65c82cc7d78127239c3369cd28fd1e9e3332a487671f48f0fe99473921540a6701f088fc00f1700700954850ba0c2e5a2c0c70064796eca273dd53e7656a98b568c0293acd43548ef4e51c15bdf0be323b0c002314862bc54ea82219aea1ed142d79202a646e2f6a2a480cde576b75a46d96a198fcda52e9b3acb339b8c0a356928241d7d930381c068d46e93baa4308d3c4c063a8384a28f97ba7efad485ea54578432653c197516dab2de81b24994b5be1f393854e59af5a458fd53b9f8a584d61195cbec04b51596a75c1c9afbd4f778a59059627eca353f77cae57306abef19922d5a9563304835e53a9e870b8cb6a0bb68fcb3a433b88a9daaa2275ac7d6d7bdc340cb1fad6d77814e6dda74f77dd7786474da3dde021277b9b386e1cc8cc18f2d408b36d466dacdbd83e4b5f1b30515eb3b01058c027720b5c5c3eafc61a084ee7af874d02c012d73ab3814be79066370f294642091405342130d41ab0740f71d5b3d4ea9d5c471dac37e9b5c01d21e3235110fca3266bc8239ae1b1fd36bef2af6491b7b0c3affcf826c79ae710b8aff28b85fc58b49ebb3f7953a24909a1e551cdd5c4141e0215b216baf0690ad6c02a03f3be67f1e1c6be119d11b831504f51751ed7df9c3175b79fb7fa2c8ef6a2b3c93f8a9b0e92f4aea5742b7fef268ac40af079e5aa6a499a46aef74d920b5593add4a0ec605b91b3d87205f6fce04849ab556f0c5463a9f3199ececaa75fa5126c18931e9af20c4853ccf719361cf1b90e948cf855c6868ab118e333268944a8ac56c0e852c2eed4edba8a97e0ba7a8d86b39d9438b33df070f9913da612af4e591a08642e9aaf12f8faaa13946a8103b255c72a5a9e3419acf7362eccd123bf7c0b33d81100ce994448a3b0c19124284889cd3f87de511540010e23825a64605448b851d483d2d72c95b26b731302d9eeb57db1ea0971b135de6e63155284ef595198d97c642f7c6e0876cf120976f4557d6691cf16a6b1c402390f514f3462b62cbe46eb58450f438614549a2e75c09f172269e7198774d5278429c5f870a583997dbd3c293b3aae73178f1bfa51a31956cf784cf7ecaee8a507f7ec7085ebf5aba5a95a149a9739b45caf632cea3a9bdcd375d39c19d0fe2c0ef12eefd605c0e51dfa572e7bb213fa062daec725de339d11722317690066f9ab13fdea08f93df06886530150def14c666dc6ff33927076c03f097fb80cce60ce7df23e5c800313871aab2318df4631bd2901cfa22d7ae21b4e3aa71f47ad95a9f1aad067dd1f7cc764b227d944f94af679219d70fbb8b88c6c5dafa2848002c27f1e8881a9357dc7c8c95e1a7202708a2781ca9a9c66832bc5fe35abea4992d51a200bb2d27addf761519ae231d3a92db32987c24d275b98c27b0400e8a4a097fb7126477c1b87b739956c369fcc03859637a3b0b74b75438bd9e95304e5e9d11a3f55ef5865842de4696b98ad636894fdd0adacabf451889d042eeead190c3d71ac58022d8b87424a060e81426090c8575b210f1222b63c75405c13f41a8b4541540b35425582c6f0348960512554ef4d7e411cc04aa77d9dd9a41db95620dab0465623bc3b690016c1915745ab4a3e2400560c4b874447ff237bd069da9b9823cef992bb288f5b44a879ea00bda01383734654004e6852e1ece9be038beaae7e1b5829421dbd356b00b2600afedaa42351240d7c50328c235d3f88bfbed409f134ff0a095cb32742d5bae169a72a6b32bdbf0d4d1d66600a27de038b3b111e809d20c10f5ef0db7e946daf2a04b8b7887ff3552ae93bb9c145c217c5a8c3fb821591ebc0508d21c0ebf1ee5a308479adac428fba10ca9f225108a123f5da6f05324146644ca7cf0f05df3f702b751cfd2bd8cd9cc1d0c3a84ec2b0143c52f064a5caafeca851d7cb235202bda63f09c8a1093e45708aede1072f6cdbe574c2ec2f6b4f254918380778c9aceea6405d654c195a315ccef28dc8d372aaa6701e51816de77ad28970351137395d8930d20161512738959ea03ded4753de3dfe873a280402048ace6514740b15461922e338f8c261c4a35f13da2b532fbd2a23d4b23bcd809a4ee5ea78e5b4b52090c1359fa1bb3884795ca262f24c94f2eeccfb2c7fc458b0e8552b9be888dfc0ecb7ec6352b182fa13066012c773f6a4ec9422751694ea48b6f6a364e9ac062b25ae2b8364a068d284ea8b2ec770f3657a1dae0892e80985969d07166327e06b1b96f9f5c5b8f30d548ce0ca62855a97142c53cfed36f329d85b9acc9c18cf91c25053b190f4b70b7ec4467d9bdb1671f0ef84c98b04bb9bf116442b502c8c5978867c4234d5407ab04519c63e947331c9944bbc000200a90ed2766f8982cf84b6bb79b825c194e137ccfd55e47f1dd9249629a1bb6ab118ba97a292ff734324a1cf5cb05d73e335c9fc72bc7edf7294fa2dadfd00f30737a17284354065cc06bc32860bd366f36afbc9b453fde52905e583df7d262752873c3a033d6875a0ce558f1348c7ad646bb52ffa2d41ad513584396ef3d5285d8182f33002eed807fabe94b9e6b05a50bd14cc6639bdd3c5c1d0846c362d9750a04410f22bbdabe1345dbe610defb399df51a92f8029b39b1a972a06d4b8591cac1f8ab1cacac132a077a0c0286c36c851871c265f2d3c7751bafdb16e4e71de012effb0fb854cff6c9801bad112d92028f95e81eb40278c828347d7a5007ee6b6b14e2d05554cf73db9e2f625ed4e65d9e51203e6cb99e6955894e24b62cb2640282088d95af6c1117f1c138f9c13fa35f320a97f2fa88d1da05b2cec389d1079351e8b53d5a77d1b3cdd8243910bd91864d555009e7f6ec32408a46508a4f14e01442c3826946f0f5a70db88c26a2728d02f7aeca769d89bfbf0c68e031ab2b8334470d66d065ac6ae61e7a26eea7e72156c5c5c0afff987363cb45ecc99adae6d4010108c02661bf65bf9eda27af9eb4ae2f53316072329791a963136e621c52238b09cd0c43eb772e140a4bf43cb123b6b1493cdae136e456e83a3d724469a9b286a817cb2b6a1d893c447657a2fa02d3c964c1cf78fc098a0eb6497d4b5686f5315c4fb2799a5368ff521caee1f09229a720aac07130a122a78d1a470edf0506b1230e4f96e84d95c7b1b9de934f43c49ca35892bd6ccb976cd055755ac823acaab6a61fc617f6cec10d1cd4c4b1efe05cf4dc974e85490b3c5d4880100b71a7856b69a4e68efb6091ae43d28b3cb96f410a5a29f114bfb92d815707bd3bd891158d6581015bd149864bd29999afac00c7a62ccdf16a75e448702e7db7c2ac2935294659022260f83623bb31132e787128530b1e4060d64fb62b5a468592cfa4a705174570faad5a8386b05ed1043382995f947753c8c9c44b0bb2437ebb81840c85e0e14053f021149204deb03c8551c935878169b253a136a28eb5d04557516ea56c87f5712c35035c283342be91de122e837b7bf204e39bd0682623a23d6adff2e123c0d0768bb58a0d03e3af5f1055c1fd14662d3883c05c96507bd7e70e21175b368ef5ad5bec9d283dcedacd63f76bd6a2014d6c0131a3b0aaebec9014dc02b4ccc10680320f8fc07791a2c2ccb209963c70d2549013e39b37aa75f3f4e5cfbde4d0687e0020b2fc958d48bbb3a9fccb759bf73fe6fee2370841009c46cea4aedba42dd31a9d013a21a5b862ed125c7d4670b1c032ae654af4dc62fdab3da01c1f7c6e47cf8df7da4d69846d6adbd6703b7238967fc9021d1eaffa5655ea0e22c285bce9690d86b1ac368813254a0ce1bf26fcd9b03b9740c5edf31de8abbcc8b7044cca9d07130c2825c4217d58d7240d93fc35e61b4826fa6c248fe03d474a1df307162f52cef34b3318629706aa8428079796534f8f45d898b7bbd93eddd2390932548e46f58b9a0a076278bd7a168bdd7f544522fedb9d3194537c2bb135413189fa32b20ee7a147b44e7472534ebb06eb0985509b627c6297ab519ef49291e8eddd167c5ecf7f86b753b0eccda23804c4a50ccc47b68b42359a78f0360f9829c6abd0e6c7156db7beffdc4692444aad3ca8db46927da9ce58329b6e710211d9e6ca34dcb55c466ad8ae9d0bf24b734a608aad3de0b0dd2b21c4dbdac1b6cd3c0b17d72dfe24055ce9eeee1ffa5c0ba017bbe114b6a9e3b8b19fe3ce4ac94b9df094e8e6fd5535df01203dd2774fb8decb9ba18e34e734dc610c15b3250492370513a7ccedaa2a68a9d5cdb634730f44d94f6e4b991141b06430c2ede4edf18e6af0a78c15703f8038cc04770fe6ba28442efdf81a556bd895bde355936b7e33c1fba917740657881c18df196f2b67bec3a51b5b78557f4703c42e9e5f0740423623b42b3e879f0f2158d6c6091a152bc5c6326beb3d1eaa4c2068fd6aca76eedc8db9ff1b68020a483902585e838907ee7241249778fd0bb91fd649294c4568e6c249fe68ec92c9abfaca3ff6db1aea59bd152b00e50116ce3e5072b16256081a51ae1e49699ecd5d6033414c21f13260d7b02b7178106ce2768705b19fc82e086461370106f6512f2d155e3cbd649a2c78391ed9425bb157c5ba743456e76bb88ddc761f40909efe08eab1428c36e1c60b38afbf528189e475f7a72155c416e3c8b262b369f0cea21da73bc24f604cf8860692180185a5d909e8ad6de1458727e1610403a6eaa1721501727e58c0d1adc0527aef901f1639f5096f64700703b7d0cd091c91749f983851900ce9da082a235fba2d6690b855dd95b4fd89314a85a7068fde46250a7bb57b2a0ce98c1cbc12d9c1b0695b694c0d94aaf23f4cd857001f81cc2b26f85c6b80c432c1cd1eb2dd9609f86635cc6c59cbdd48727d5377e1f10f33ddf7e3ad493ab7b51303aa67e601350f84f30a4ae581176f6861ed93635098a31b4b036966142e885157a365469ed8b2c4dc1934dcf94e36afb56075b72ee4a5bf452654806bd6a4b069d5340c6035dc38791a4384f4f368e5f1fcdbf3d6c5b69e081cd50abc407e02a6ce07e82facb172607222e6b2410fc6e39156c12a879a0d07291f240bc50eb355d6f2eb55f1f6ba396ac12b1bcee7308de1edf56200975310fae9fa60b8223cd8f2105b400cfe7f5f7806e05254356fb082f6419615be40c77199d6658e73490e7c85d1c9f3d40fbfa65c679c220f2d7b8ac0166a556091ac10d78d2ce2a7809b25212ee3ae1a3448bb2398910ecad76c5532a4038dfd7b2e1c020730cd9653981d836284816620a7a64774ba214841529cf0444b0bb5b5c27a393b430220e6e57dd553b5a3da9fe9a30ea22e8376c00cf4d0010cb037593023c41e35d90501bd5770fe1e0b45797b9eb83f59b52bb10900af2ea0b5f41c9b633a8893a35488b3f5ba19d285257dae252f5b587c15006a9c19f4d04f41e7126e2db64eb09ebe897ba820fe896fab0da8f4366df2c7939662a515b47d2b3f0937f3bda81ee43b6768349720ce869c205616e156fa3d8adf8bb3d7578e263a61ffc37428d5fd80967486f905bc7289c4a6ed5e812d30969cad55d87709f51cea6eaf0c9d94a6a3925b0ba85d5490b7c796aec1679bd68f392b6515604edf9180f8b621d44327785f0b4f5277c03e6248186b3d67fdaa1bd0b19b1c1d60342759eda57336ea6248d97007868a1a14ad23d6147cf22b47f05d198dcad357ca3e6b8422e52d5fc811bbf62e7a4b2394be3f3c84526c1043e58747fba55bb242900bbde58b04375a87b4cf549e64a07d136bf09d2412aee9cd58157ed921c44f7efd0b3c4316b9b2fd281e1406db3cce3f0c58b69cb33f2129bb9fec633a03ae6c25567fa16c6045657c389e3c4ed08651c8c97af2c81a76e764b51418a97b1071d0eed5aef5a018a8787eb351e3b4bc47a8d73b1684da85f4de7f3a66bca3ea6653966c3459281f013852f7f5b47b1ef95cec9852a3681fac0a30b16052fc581b85ccbb3430465f831112c9278329c095d915108702d19b5998a844e276b4b7f767244f3a13d53e06abac8cc9a500326578d4351888f86b474b413a7eb6b954734a888afaf0e5dbfede083d6b4d1d9cb7aada06d92901deb463adc2d3b081aca68fe9542320666569c8363b9eacc555b2df717796cdf028854f40c6a489d25b563d87ccaa2973d4226851fa9007867558f50bb16282f864656e7c896ea6325133189dd0e038675d8fd16a0bd900a21d06b59d68201c0991e00b1c6e3dff7ae3090c4e615eea17ce5d56e2cda9f0481f50fc6c88621353b9bdc2e03c2ec1e04c3216d415b9294d35152bcfa6ab4e8dd4c98fe7c8041a6fd5892190a94505e19203e314d29ddef5df8b49c077086054c0f3f5a1017fd635a63802d3a6ccde1f5630be2e269810b5c6e7c08d33dc960f4503ff0c9cd1c22b1ccd6ea8a3c18f2b00c49f6c97d250b35a6935845004a8222ef8d5b7a5ad2bf4d4627175745212c01b15166c4dcdb0ba00c39e328d4326fc6866f0d72c58afb61cf755a22c09a1d7ca17022e214d47a9c3daa1c584fd5ffe79d349e9a69f83e1ece8467aacf49503806536313160b80b41a4aeff4a575b4119c55272eb9d478f956326f2c31ac2a433062e822291594f4a30c7e78e9aec2c5eaf79e4c24cb347864157fe908ff4c735feaaeb2a5d1555753ec5249696627dee01cbc58f02655a0af4b29b5cd5014976b3210207c3147d9e7bff70b54103b5220df527b6a6fdceba1838cced1947c613c9668638108a8fed9e2be357f786855b628e9d1300728957dd848505bf119389e0bcaf340d73e5151483c1e9917d41a677bc8a731efb27b3db8b12a9d12790853ab329629f4cfa3f1485840be61d9900de46a14fca0faf65a43e52536d62f54a35e521fe1450eae60f5c5bb6a84a6ab4fda47f8a2f14fc6180dfc4d0711ad7463c3c8e1e227bb19b372bec3513a8d9017679f38d45c1ee51cdf8b52a5d1475647032fc9714a91c909ae7214e52579f533491eb9e4bf97560486415b0e43840a2a2e07d599519b04e276d47e5370148eef929ae4dfcfef5d03b2c8cb68c1d8d55766f78c7dfb1cafa15e9d6bc483149e25bae7befa822b2a86059465f44909c277876921ea9606b07eaa74b3723d501ab5e7da2e9e293f8a35350622d02d00651acdab35fc05d2ea661af6445f98865473e9ae0ef0fc4fdc5c092a9a21aca678f9510c96f38c400b4b245d230b4a397baaee9011055359d12e462d0e313caba8b8effa3cf33a724db5b1798f49a71fbca004fe3afef67a526064fdb7cd64ba283af7ff888f7e67aa0ca78b1c2125c535b0ceb6100cf6e48e0147f5ea45a11c138160078e843fbf717b7b4b63964dfbc677674116f990d9a01ae8132827b811f3782e45067261e5ad16d3a0201438cd36a6cc26a230ba01e531d383ae57d6df64d41fc17d6f3b8da51c573486200297c775bcfd34330c00cd0c1e50b08a66771799253f682f7cbb691067ae2cc7dffa7397385a46b3ab61aa21ce09561b289be5f50689ea12d3291060350ee53a5685789bd0c0db292f57c7e92cacc28a84bb4074e33999f58be52c0bad47cd25a69f4340ad8532ae647900d8b077f2f6e73bf186283970b6638c364b180b8f80a942763bf766585afa19c4748208b7ff81bd593c9ca13a9909feec9014fcf1ed909b17545686cb8c3f4a9cf0968ce14e4fb0a9d60dbe6d2b1c80df24519a986e0b21f75b6308008bdbc0df0cdd3d7bc2e0acaa5cc26e095e3191f3a979fd85a07584650d011c5f5cc8ad97afb375f3353433de46d602500d75398cd26699155da8477d7024140afc3fd9766bb36a720c6e678859dbe1ff4e868c8048a52de29abffd48ebec4f523508e9364f85517210f7084ff6d7ca333196eceea55b38fb92231febe1359a0c591137a32b23c40598da61773879e674f137eceb24ed68facec2860ad0165ddccc57e172bc940aeb5089ef568738ea173dc11b4b3a9e28765ff76703d340d25e971e0a27ba4100b5657f87abc5b5caa4196aa090832e63beccf6d38b1772177f8d18897cc0a472e13f898bd7261e780ce3fb6bdb931c9ede6750ae8f3a018a05670b80bfb8acb2245a2c741d17cf0bcf32bd6e0a73ac34728f2cc2b08d1b574a6d8ba650872a8ac752c49f1116d177805d4960003661eb5cae022ca53d2e887e42db5ec7814bd8cc1c3107309fd32fa515b931979965cb701c34730b80879be72bf8af4d9aedba3a7dd909e0e0454fd62113eea8071272a1adccf1cb5e51738eb1fe322198dcadaf396c2d3ceaf5886909d443eb4732931452ea8d607cda2e69cce1ad7fc1a0777bfb651bbee0dc467cbe07dd819b4ea9740741848ce5dde99b1377c09129cf72f9648816179595e72c71d978fe11b60e8503c2e9db5c3cc72c0c2345e587624dc1b2f529eea70b7f192d7f7598ea5b85a3ea51ac280d73db0412ea15587dc295da6ba4994686b12bab0db27130684d6a67a8130819b23171927c18123e346ab7f182d132cf446e609956e953031963f74c56527fd8a3b96df94b104d2fc8f12ce6e094b7710eba0380eb8454d7e07d41ca29e09471c9c617ad2b0807c1c16489d289cb8157ded63a3b84c12452a1d2050a6201c7c847b60a1c38544eebaec1073b4c03d325e0799b553a1ef894933d33f6b087ef0a506c8dd3914b61fc0b58e1c936e3fb8752ed0202d0be04818d00590033f330513a19048f629561927419b53702acc132e407c4a55e0c68cf0ed50f47b8dde244c3cc673989b19f500f0f358cf3bd27253dbec84933268535fb064090f34cddf29ec249c99477a89324567c3c49b9d0a153bf12e6fcc1b290c44d0334c84b26c280f147c1ae5351644d08b522188b468f3c31e2bec5bb790e114f2448d785ee0866540e0a7bdd8dbcdc5a27a9527e84aa83d36411a295813f9f1f6537e92e396a8f2b0a970cb77e02b0471f296fff99a401fc1f789cd7f2196f7362c4e9ac234fcca094880471bb6d06dac45fa77e7200432013d6f98e839fe02bb7d1f203a6bf6a09ba1e4d50e0cb84b742fa5d89346d0544c4e1b21ded624ad69f9ef0821494986179161186fa5aa3696658f4a661c87dd691c3c1114df879b6c54eba0cd629e3831dadd823162fdc906dca71139535ca9cd9df709171106cdaeaf2d3518b6dcdd30e755621f12c2078a11bb9694cc1fd616e85a6b59023dfb1474a1928750a0498d36408ca3bf909d54ae219f00245101eaa90e55faa2671ecf9a2090f35a41ab042b56f01c4d5b44520163274d3205f879e533e8f0e78b27753518aedaf1e0853c625d6b82a9d7fb5398248bde30ceb21ae4520cd5e73bc2ebeba11ef1691619eadb1b6f7b86f71f8110700f1078908cbe2bff9cadd6185f9150be12b05199e44424f3a540145aecd243d0f12aaa6b543d3eb32ef05a25b6e6346f66ad1c49de04f6856046a0baef60115b9178e876851966128e12e7b0b37db5d75b2e883fc51873204071d4ca7e30927119768dc460b7380176c3c3df66067a2eb26379825801c5eb43a415bf1e769fdcd60a0107207c0847fcc428cb0ad811927ed211c8ecdc10702cd2d992c903e9af1b436714f2f6e6421ec14e080478c32061ed9d4f9caab3476027df4b189526fa960f4dd360002303ab51e36e7e9da7fc6d896f4ff351fb4240220450ff402d80ad0851d669fcba1fb59cb06af7cf97a6b6fdee91f67edea7954fb673a600711c96bf211d3e2bfc7372789add31234261cd4eac39183205bfa527a5074e42d1630ac7391b44cd795efe6d68cf0ccdafa36f21f402a50bc2e6529eda5aecc8fe9cc506bd5bd2676706a1baf500d84f6909613234fad0e1ee6c5fb2b4299cae7743de96d5b7af1f05e4b358e3658e4f1b9821b77876722a56364a2e535ffec1782fedad54c5f51f551aeba91a3ec28a330255cb31a7a5a8380b089b2f1e776114cfa6a91be6d8f2f3e4fc9b87bc56e8b3408ba07031cbb7832ed8dedb1558482002764cb2623deff30a84f575498f0b72866ed1012ca1c3385dc7a913b1a2938e9a2db6de22ede0d565efd0858b56d970d286578ee7e3ea7db8c12062591a7c9e727f8ce06b28bb04f53458dacbeaa3c4d97b8af4a334094849ab235b629d031582d204ec08fcf611dd40dc73d4876dd80a4e414080d2fe4614085ae70b8797bcba3153551e59e6e0d68b21b243de186581c86f02e15e81d5f4700021089319a169579345952a9f078e5147fd98e36b10c4a9336b9ba0678d1231134642112c44b4f60d3f0372082461e2797dfeb50a3c0aea6888c00da9de93fc542bc744bad6a46bda1cd35f955f8ab985e906a18e62e24c5da219e618ea9b394b7461377b3affab718b9c26a5f1542ca518d6bbdf4a8022e5b66bb85b1ce3792b7533b859d0378311456b00855d9e12f991e8b6d46599e4c66b641cc4e60d14e6c879bfc7e704503d5d0e7b57d8add59b5a888bd3070f1aa1dd08a6be9fc939c5c1ea745ac6afbf125c55bc000e3326a921f5ee7700b42a30994750de3f4c27c3f35f10cc322437017dd8f80b3e472cd224342a7ed7d9507ec41257823434bde31339189bdb64b9bd5d37ea3df6075e14376ce80e8cbe6ed71764c48c056055b24d1749cdf49ea44254cc5ef17f50483f920806448709f2ca8d864d763123619b1bbb1196124fce72ddf103743e9cf9c07ec402f2aec3f66fe868813fc84067f7a0e9352f7f1ddfc96638d068b4c0080c3130ea6a9abc02d036301c9805a4f3a8749bcbdbc0c497da262b6d6d05afedd0a8a7ab150caabd4880d702202e3bf498190c69c20e5614ecac663895e75a133c8f263a3b734e64b8959b07a162001a4f89a6fbcf0aadbb3eac050a9377e699d128026405280b046730f6790574356e49678688275ba67bd81e5e4f473f138c663b77d384c9b683a0742b2ac0e0f2705610c680033c01e2110a8026570e3f7ba7bfa7aad18d0bb5c1d458c956a70d85417f80857e42510e43d6a451ab266511461aa367ca32aecfc0d21df73d4d77fbc10ba559e8cb1713611a63eda01ba9bb1d768722ced8aa2d7bdb85cf7d804087cae9e7d5bf79ffb90b0a598f39f10879be2bb9f9503f0abe5ff686bc7159e82ee081eb4f1efd6825cd2aeea97de41a364cc31e63b798ff44638904b73b379755e87cfd244548aaee71d96e948c4166a0c692bd35098b4c1fc47ec3d226c2a86767f8d0587192271ad0bee2f5d642db4534f62348ca7d8813de2981c284a7f4a6f2ff0e3d800ebc8268bdb73508e3c674dac89e1b36691387809185adfe82b7d966664d32e178505dd87f0b08ccf59b688681a55722ff65afba1b8002d1914f07ccb4ff7680c35c7425aa5f4e442fee18abedd72c3e3f67d35b77a01d615d0ddc2ddc67835377ca24aa100f885f6384780e0658e1e8ab2093d2d5dc7198ce99ce26de9de3580fc5f286d76180890cdae7e0719e59b0ad274b12eb91dd39e0ec1df031800eece9060f18da8f1898354d4ab12f319e25353c425c6491f0dbcfc401424d1a69ee7b82803b94d313b63ae9dbe370dcb07576edd9d5d2e2ac02ef2d69dc26b5c3a837f01c5a38439ed182fdada8009c2313f4b64b42c329f7322dcbaab40afe7c20151476d06299969bc7af04698b5991666dbc33fe713e637c8393aa90d63ad1cd2a19eaa002159114538186b317636e1dde637184e78e603eab984dba85041649ec4f9d8d89ded29230f2b63d09af9eb53b8be4f579e7fda1aa3c34a4d21a1cc3146d8b4701e14e7fa49fbdcad1dbf1c39eaa858fdd05ace6fc21568cb9cfb6cb2675692a1a43b370d8c47da97d050c48bdee9ae72ef7a532e2dec92ce54cf7214d38e2a6223f82813102387fa4afaa884c28a26e64f58c4d00f04730592b46bc3512059a1d8d4ff1bbd18c449e92b5e5b4ecdfadbdeb22098497d43c386756f7dd1fba56149d8bc1194673d9d1797111b00758ee3d453987a37132992abac6c3cbed352c2e0f0af9364098d8fb24b327a4f402ace06473aa1b38305f51d8de756e163fc13bc6465e0339fe516adbb570a819e86dae42f95701aa406b772b869647b2775158ea0187f3f15d7c3449dd8daa9821a0f6c7713cf399d1c5c331eb088ca34d0a64eabf141ee0fc34f893ec3519dd961e1c764d78e6b4eb5e1ba9092c72aed28f266425f376705306e22390b5a7654494af0a4bd28b076805856de9c9592ec2aca3056e07c628ab0b9339466941dfe10356fd7efbff052bbafcf0d8778f918e2572b0846d3e59c0eb8157748cb188015580b39094ac9d692d1a3643c570d6eed5fe2cfa530137caabffc6baf51c5f9b699901ed0be32e83cb27b030a40baedbc3f225986371c82bff8dc94eee6c4e357e1e9339530e6c24844d0e7b216e192ca94047b22c9aa866ec7d1e249b96ff6b3dbd142fb604dc2f94029620eca50ec791d6e496c1d4ad2d9e86a20f11b170a9883032e82547b22b97fdbb0057454c61d4fb39b1d031dc0379fb9865366b276696ece1d389d8100c4b7b45231008ff2576ec47a4480ce0989a81f9111ef30caf15c8f4550772c9101750fb820ab923b033eb9e61821261bf7c3928bedd80413ebc0439d1610f5f8bf686940ee96e90e91bbc23f34106f487b922df2ed1dc8616f23e490a5a010e416d734fb4ba52f0b3dbb173eeb86cc841fae741c7144bb433612d44cece2e8d2d30bc84f94733eccb7b59213889f424e21f1b5c865a56d1c2a9cf6b79f799613850f7d6b626825a450f29556f801972169832988045929269c86966da19a13ead6bee2d2a67ba7af81e3fb86acae8ebbe2dfe963bda9139950e375129209be2d8f591947c803ce1df7be4d12eddf690f0ab63c59bd24f626f54495dce730d0850eacefec4f6477c8b6fcbb2a07681bb15a85a6ace074f8646ca3d8772a84ad35e1872147a733483ce05ec431ba3f272fa8fa89dc99ab2505e91f3b0cd2054af0ad0b9db298970b20f377b976046d996647c1e608da886a5d7fb9d21d5fba59979af1bb822a950929c5fdafa0d37fc9d1b73a817432f5b762a938c36de844fe9433d373cb0b841a14728f350f6b0f223ea7c024613e09a4af5bb8d78d567b1b206d998bc40c554146f75b51b33b17fc252aff12225cfc8f6f7b366c72f392710a2700661acd883e1cf8b9b0f19eba0e34bb6ef8045191ad2f4decdc1efa489fdc419a86102fd64066b180bbaedea2c717c554cbdb9a0daba6a34327e81a9790a92b12f87253c4ab74f9ccc9c7a2504a904a113a82ed6921774fa0a39019fe706b27244f4412cec89d88d2b00b5252e65a961809405de3fda2c05614cb85d8c054aa8a96a4971fcf1529256c083a64162730d67116a9bb1c8a638e3c674cd30cfa6cc62116a98a1ceded358a65474df10c1d3d8563a661f85d0b6ef84132c943dace18b9011ded24f68693250cde3a0719673e278ec4923251c844e6a032d303339ffc1a9cd06abfd16f95ec22b7378147f880d4ada6807b36e73179e6c951289ac77d70fdc8a2c162fd35cc9e1db60c954ffd70880fc1ee929457356d0880547503ca30b6940f31495990fbf1e19ef53991acc38885ea4162063640f81e03c85570b9c0ce9770f30c221630279c8bcb56b6be63bb460e2b65cf1f289a49a72af320e842971effb29c0f32399c3b78e56269c6ecd0e11ce76885648b6de8d11f8d131227ed45845ff7af33a209b231aa2001736122f74c8bb28e220b74aa12851bbe8050554145f6632ff6cdb21cc30ab9c93b9fe27e0aa24315b6e59f43dec198e83c9d837e66d310b3ae0edb1cd15801b0ec6099a6646ccbc84fa13a182b091618125a368eab6c6e5f2a18886d4829941dd936482ccd538d87fc38596a3694880025afcb7885f11d87275abce3ff33a670068d2c1a710f090a5ea41d954f040d603d62afbd0d2a4290c035a6221f91e3339bb5fe10da5d6f18c24893c1137dcbe957c12cc8f6f3efa8d2d7c99900e04e968f0181204150c033d14d600c2b310e92b5514691eb166ba4a9b7401d888ccf73780c698797e8eb9964884821995cd4d34f1f8d9ba7457fd9d4e6c414199093b961acf76c4492be47752ea61aff341e4eac1ba46a87d3a87bbc96cd1a4c46c0268dcf0160d91a8167f0a91d7153ab243f52e9db3efb7202ba2f8aca91e3fbf2de22421aeba5d63aaa844c34fceb8d12e512c5eb55cc0948cf0cbb5efe18d4a6e4b283e1b89cb6b7bd2d87803ef8a3ea5e3975831480aded3a447a8c09e52727b3fe508560f6ab067c6042ec4df6664130bdc765303408e269c95d8a9f11be9ae23db579f64593f3599a732f4a0ab7aa3e887083a7c81930685fc374a61e63f1f02c49017c1df540fc73607590963a74c16777290fcab4aa32dcd68941cabad0edc919ce625d1226afa414d380d4a3d8401a4d902a91cfbe7d6d5b2f929704999769f16f151703287e6087e6d1199e19fe428e6086d21a11df1681fd6971de30c611ef07a4ee7d7a9a29cf83fe668ede46b4ac149608416577aecb0bb5f30087deb6011af6afa651c29aee212ddaa4a0905e9fad8f5cf36db2f971f8192ee4bc778a813db7712270bcb598600dd9eb2660a77420bfd95947cf64c46f494d7d06c12607abf3864fe74844c96e99084921467b581108fd5419033049838502538e832d9a096cb7fe70de1efbf58e3ce6e2f761d8a5ceade56f3e67450ebb70045214d1f5912e02af256c841286f8a5de18aebbfea3a9105f7b9000cf044fffabf4fa042042428289ac053e60c5c1a1594feb3347bf413b8709298cc648f83b22c8b457befd294070f98e462cbccbc3c33cd2013f52327d5a76b6b81062aaadea6bc8cac96e433ac28bd4229fc2d9ada29d891664e3bb33bd81dc764bcd31433ecd97c3d5e5fff6ff803ebf5e33f81bd630dc2c75e8cc88c9efb29b37201d3dc7276225f7194eeec3e6343da9b10190d9ef23c01cefbaa3971ce939bd2c25d912b73947b1966ff2ebc693703eb7cdcc46037e8696a1f33d1d197970609cae5352498aa46ad81a5159951afab1b91b648c3bc95365ce0f7d4be88c8facd55b97b93a12e574e919e676accd9239fdcb0579028cf1aa85813d1b3e4abcfe24aa87a8d3608fae0b027f32da46be89a43744c6aad2ea18443bb3c91b7921c46113183068983116b913bb0a5ff594210a08ad17e338a93d8c93e5b7a206363123cac129b53f4629bd1ee5fa37bc6607474a2d207f7e000893785dc57b380bd6e9a35b0b21eb219c398182ad16c940ea371f5235c249c86b978bdc068d7b14f915d8a16077433f860931dfac83ea22a5f3abbe38a348ed2741cad6733ebe846d262942d733c793d6775c65e9cfcaf3b0f51084d9e70dc63181618f209f279e291c5b61dafe46206bc0a888a5acfa723e4da47e5402c0bf732e2b9c27515eec7737464306acffad663b5be9bf8346932e3aa865534834dcf3857a02c9530c6182f6f967f27a92548e9a8a64b5ae7c894f83af21490e7c2101602798d14e78a22b0defe7d0086182385e998eb44c437c3244e96196bcdae007bd250372d209acd339dee6475e89ef69ea6b1815cf92a428d5407998a5ffd977d7e5aa42ab06c9e2059be2d35978d9277887edad7c5f83c4791449e291c52de803e4d727fbc1d7dc12a7f27e6f4e45f40af7578830c6e923c42f8890b629a7c33e47e68440833c98ee6428d354e6fce4134465e58869b4489915186238366d8716128d8ac3f7fbc0490c7e8408d522018fd08d702333fb53a5952518531f2207ca7a858a0d03ec97c3d919be401061bc1c7efe8d55325fa1216df0d8d873da29c05388220eab62e6803e205dd8d183632bbd90eed51dc959a1b2c26d870f98a89b944cd488b2c902e7e906987adc900129c4ffd65c3b48498be2000242707fa36cc2d1098407f99d9bd166b4564a85ec04fe7b8c4989e1769967f351db5bb42fcf7a4ce29f7424879899a8cf759337b9bf9e123d5a5b9c81de68d03417bb3f66cc66dc25dce4d41ac1a404bd621b4245b71e886f0c2127d722d5bdf08114aa16ca15fe38ee47b9246903893dd433247ce513e893da22a9f9a81ce5ab2d42735b9b4f07786c7d4245b87f7365ce51ed517619a4e0a09d395a6db103cff67eb14c342729506296e71482e9d21a719dedf8b4e59a0590ff88896fac76868c929dee4565c0bc524b3d186864ef674a062ad8bcb41ae9f3aed936afa46ca7fe460ee54bb0567929f8da9b95375c2b0cbac8a245077325e178b6088fd6bf1d5dc9b22a3406e8a2c3da6bba87575356c2681605c7e58a96b9ac6037e08ebed0d034c2069f4e084dda3932a5fa73664830d6c5231d0149b47d1fabd7eea694e4a24a33a2d625c758f7c4f2cddf14586c91dd5b5b51dc11358ca62ce807a5ba9172adc1641776a8a3cf251fb690dc7431e812c2a1ac0d304f28848dea19f620fd5298c0179247b40c6208fe4bcf6d159fd67271a2b9f0837cd0f17e49188b3011037a0649d05c823a84c4a68c503b21216ea13239a019ebcd5880a428b1b98d0731543a603e8c4a5db71dc0fe2032d15549b95e5320823bc174a87ec4b7c20ed99bfb4a0eee4a248f6cf38489b718a06f120b45599cb6326e5843231fc3169b5110a3677f2403133d15d9605801809113551eaa74f8ba1a156297062d02785b0b315c9052d3544444df2a2fe029cbdf9681a366c5c75f2976f301e34954825d155681199fb7e7aa422e2716e5393a1c022482e51e4fe8c922962960a678415bfb0932546cfc2262fc48634427523f09116f59c6062b5a2f05370765b7b65831f5d032689d756a4dd9010d554c7986e565d0f2dd004dda1d3193d47a70c51e37a562be89e4d654facc25f2e0ce99ac2f16fab9a2b80868156e43cc744b6910fbeb6bd2a808108817d84d5a225a7c0f3400071d37068b8d9bdb7f02ecae0aa8a4ddf4e001ed991d4112682d14b78bad2149dd20513a6d80187fd50d2e55b6caebe6a64a8ac72067da9064bf02e07b1a1d49b60aad548f1fde8758ffd256dc7d4aedfc560ae00f78198993e0b1cfa6f80e909236c02713aa473930ba100e484231615589f48ea8a394300a6d3fb2949e76e003ca69774ade9f9a934b8ed973c315aee66d8c7cff94382a923804bfa6d1a92b3d0233f45e56ae142113baac40413a19ea714664c6fa1a600e22c9a05162af81e6dc4f2a3ba7b2a36b3584e814dbe0a302da29ad8b5fa7427d0e1165cbfa44021f703e7a7e93193a76f3dc187620134cd7a35a4f9774a81cdfb67e546a2c3e134e9ac100ded2c010509ecdd211ca7ce8e739e17b29837ae20e288d1b3917bfe1d536cd326cc2eb1e7c9fd2ab58b0e17dc06c3cc72482b497d018b8a8b40d5736dcb578e7c6109a4238999e7cad5524385dc8cff864da9e293ff38d86e9c03575d1794a8c638c2252becc1c787040ae2761d7c2af560a6385b2114048e9642cec5354be8ce441288a5e66a4c1dceec91547204e6153a77ffd50e4e10fc755cc92ce0d91101ba377ffbaa29a1ae9f73518579d8e1d62e57e9c249e07e2861f5f3651425cc181ac86640a18bab383471b314a4d9798617ee4eac0a95b4d76559ccedfaf42bbd17c7b9e7ce7472059fdaaa43f26e9264130f5ae8f121cd6eea29b5d0b9a4353e4162fa13730e87d1adaa9f0001fcee55a0bd99cc0ff4cdab34c02b1c9913af7fcd4f51b9e2b47e6de8577de4571382d3ee943b471e1a5f7a199cca411d206e4359fbdc6d7fba86defda78ee0195d8f5552d402840cf10101816801c31b804b947ff40fb83b8814b02dba42546078ba36dd9be12761ef46c45162f006efaba328c635d5f788edaf28d6b9d899b80087cf94b5d23d93bf65fab4e00387dcd779a14ceeae1300cd828bb163d3879dc6cb1b88f633f5b5c04961ccd4f31267c58bce14f8aa45bc50922ba74493513a7889255424fa4a84e526f1191108ebcefddfd42d9f30538fa55effea1434bc47e6cd9591d9b1c6055e4c0279699daddbdfd027f0ca2e576a4ace6f36585f65f02bcd9bbab3652ec63e43109c9945f6cb49e1b1a66d008be0be3b41b66180c8a966454358e8a762b40b20ec1c7e5e3e1611cc37c3465ca82356d77ffa3014bbd51d977a01a9e8738cb15bc6f44c0e85ac34316afa44cae26999a2f42ae3d7fa7faf409fb7a081163a2b9952e57282d6c910e1004c22d003bd3fc80c32828449583dfc41b0a87fa341e85b8d0ace1aed36e6d08c6c2785428f4b0618ceb9d63ec02914cd09560c0e6e5dedd5ccf49df9cf8234133a5629c96a5f0900eb79e922205d394cc70204a0f1868199f8b9c6ae28c089e1035478be68388a4ab3ae64387d3229ca9c9bbb06ea7e4d36ee6289947495a4fbb0d895a26c11f0671bb0f42ed78c293dcabb47f9a55081f4df62c27f0c3e4dc1bfc4e4663efd9cfa3c536cec50820983d527c00ff4c804da01af8b411e9aeb708d309018b0ed2251a3a6c028c44743a70e8f0c8e3eebc78562628b39c6321da49129ed143bf054d3c896b01b69efda754378745f164081ecaf5102de75a94b868036d533a73baa871607ce309c67b72315d9b3ab4beb9d49c677696ba9c0b71a17053d7841cb216425234eb648cd9f24992b3065ea80b6cdd81eb8de9efabd6847a443705322fed1f5ee3096521acfdd89d8c30384ea029ab579575a30dad9a603cd126ed211f06f6af6db6806e6fa5c9a65c4af566ca09702775c035dfae43ade01a790b259f1e8dcaebe94530ff2f3950f380962e8205117712d2cd24d6e462a784eebf7719c3e4fd3ffd2dadeddb69452ca94920c4b056f0542056c42b1a9c44118580394734e29594c5b163f880299688102ecd22a98269c9327c3fa19f64dfa64537e3efb88b029e287c4bec378416cd6dab43256524aaccbe130371c065e97e1c676dc66c8821de9107539b00c10d5e8afd945c77e2f22243d25a5ac28b3b12c6848126b6d02c330ec8a4c87c374f75700aceb1e204c3f47cce36135441150480ba08cb30d340ce11bf7086305e8cc816934df6d7b1a58940307a161d459b67d306db5a100ba1197cb5a6badb5368628d84929a5945a91a453d24fd36f57bb3e9212e1a23ac00ff08db45be84908ba8361d8a725e50451d334a8c19d1ca21c3b3b3b56278532d25f33db30738e666d3d596ba9c41acb423d6dff3577aafabbbd45e0bb33e7f63601983b8f4ccd5a6badd5a27faaa6450f02fca06e04f26a4f3b97cff3fd1829cd14c8bbfa61d0f44af374d2b4d04392d534106807b4b3699aa669ee9bf3c42972422267ce39439f8302db83405f8258804020bb694eb82f9cd9dd7d341af96834f2d16814fa1887e338b90038f3a9a5118c39f557a4bf8f578297c3178457b8fdfcee310e8ce1170fc7b994125ba96e9069b3e6abc958cbdebfc4fde5a691052f14e90710ce63a40b5213d997ec83b2d5ac79bd5e2f51263596353e536b4dada9ffc54cd3361c4af886c36fa05fbde9deb9ecc836fbd6fb615f7b20a46cebbcd5b9cb8ed06f1ff2bce582790ff6212fde98300fe4f96bf3624d458245f90b2bcd1a0cc3b07e53eb83c129788565f1e7dc7cb8017e3a2d7b67c632e66cce3967ad3563b9aab173560d853557844cc5cccebe5ac998b56c9bfe5c2d8761f914de82005f702e7777b73ec353ec10809d53d9ad07b8fd1ffcfa4b36c482d249a97438a54ab11ce92fd51f74c23d256ecd8eb71bb6015c6dc5f2998f671384c32035213f0595d4b382363ed3b3b919913e9f824aa22bfb9ad8d7a73f85f504c2c01a4a2c0598801267715b0125c6e2ae522a9dfe4457e42e72918bdc5d4af728a5bb9472155acd0089254859c2ab0b287465b8c50f9f1789466e6f5a4f93651feca3d3caeea31d40a1ea7382a58fc17a21d0922c537a9a1f3cbc7cf4d72a1d3bf827c62f25571d4c43e3a4947e56aa101553e798708a9c90d0d951a18e546bedb576421b9bc9e5331a8b09daa08151ecf21c955fde35ceccf57061e397e0ce8dc364056862ebb5d0069d619d86693ed2306d837b0063a00dfc04a4d1dff34bf616b93ea08df92618d3a61e538fa9c7d46382a1d4a695eaf51228d812a3765093513b45ea1fa11ea3604cbb6cc196da6432b9641a357b66e618e3f6f97c3e1a56b396949e29f69503293a442e4ca2238403dccfe2e18bea0995cb353333bcb21f80fffd7da10a8acde56d021cc4859fc99fdd4d25cd97dd8eae21cd875d09880b4910af7c171cf874a5e75e09084b2ac977c1e173a5d743e8462f89f9b00957046beeeca0c340e6c2f2f3857fed758ff396bb3a559392e15ed2525c3d1da5a9dc7e0a9d2dec228dd343faa3f2ba3d537c46cbaaf63e035b652dcdb28d9f24127d299ad252b3476058be3a704287b8fddd3ad824e09836c2b49714d8cf76c13269b5a57cf5be7a2656fb52a7529de2b1bde6f556011748da1e6688542ab5558049dab78e2ac364955e29f35aa5f3a9ea71ab2855512ae34a3ac5a74eb9af9cf5d9c06a5ff295e79204a8bf5396739856e9f4474f3948c0d7fd01be384c4a29e5e7f3d9a4263729652a85615a4b8abbb8d04e51a8c4d128954afd7fbc726a446eacd43e8b544a23f22e559338c0f94eb63435530ace149c29f8806677107dee666aeeccd48dfe25edf297341b6c604883e98f6aad72cab490c9d765f97a0219c23959074f9ea3dbcfc32f8f704657da550d8013aa7780950e234061c23979328430fce18fcfd4a0fa78a218d8af58cc96159ff67d6badb5d28b5521387467222c1e3c582c168b050467e7ff5c3c50b55ead9e292e2a43704c3536455aad2cca90afd88fa2b3765e318d28a278611a5f56bbb64db778d552a59cf4b76afbb04928aafa4bd2308c04721430660b60f89086b11dbb5e0ef0c9303f1d5faa7d34073d48e36cdb5a2d6715a7689679acc3ad14b75a8474ac23596e89534eeab34ecfb8d473e1d56527fdf5ca354348b31c86b70879dc6a61f5f369b5a40cad58545bb7d8780d86611083281464ac66a3d369d6671650c8aeb0ac84fe411c4739cb50a896949e292eaff9b406855d39aa1cd491948e93168b97400cd3364cdb72dc733cc7dd861a4c43d6b45c0cf468fa178036ec601a5d9fd5a26d9af7fd386a8c76d450e5e46499bb9ce84009259e88c2891b181663d47070b49012eeeeee57c0acb0c46879d84192735c8b8cc1c2cdf02b5d93583a26b5703046f7835f8005234ca41507a3e5573e03a20623b4483c56ba1f407c4552a426b014f4909aa0225ef951cba9e557be24923246a72d2bde8f9695175e00809471e55da2acf968d9b6f22dde8f965f59d9b4ec1363ad2f23d6d24152dbc87e0267a41227b83ac1d509ae4e707582ab135cf9c94f30c624a3e73844fa13b18e2efea43f70924d2d6e38f85b3a48925ddf18bc45cf8f54b1d2e3b1c33929a5c42157fe46afac625831038508505e8ab48089107a4840704e4e45a07650291d5592283dad95932928d49c73ce15146301f2137066244407c15f705b582cf8094f0191e0acac8c45a146422c0f9f097923ea9544ee8d3c8ee10aebb7bf4635aa5152fe0d9f3b7c49dc3c69c585df851f5ec983511e1f49c520a29e3881abb5b2d0b9b21285155a402985144e1a6e7715495061450262860d70fe6d344c7fe45899d8d21fe0d9db229c4fa79328ad2a059caa39279cd0c79cb007be3edcc03ac0981d600c08204c7f152e7cc0981deb03df883f2f84e9c7b0158ebb01633421ac8cfcd5548591c197d20b73ce39e79c73ce39638c1c03164c27252f98e4cb9b35269fc1e12fcd1a13f7166318767aa669c29944bc3065ad96992fa7a49415e505d787084f4829250e0edcb4ec8381e0e83382624b8c339a2e87c1c171f9cc7431f45899b3a3d1880726564627d404050fbc3a4c7c4a29a5d86703651a886eac651f8c320f664cca478bc8cc31debf30b7b905d450bb7bce1a2131468e2c1e3c6acb3a8bc562b1582c1e735296ec0f159c625ea5544976964871f5d028ec10420fad7cc99f22996207fb8470b89ce7727cc605fe60f6b813576b475332521409a4296843724dac92af8985a4124dad7834b5d35fa7acdd70c0cb344553ce94a6344d2372228283835f96cf6611aceb250ee7e2345704ae68125b2b0b4bc7c2e170278f2b42c5a66692fefa59ba0e5e08636744ad8127415bd0d59afe6c86982a4e7f452a12fde5a0ea91aaa3eaaf698a77e62af5ecf2d5ca67688aa65634b5a2a9cfc634e5332ddfdcd2f50063e7da9991545236d3666727958a71a55d5420a594524a598428887cd658eb4dd337b9350c9b1e3f1faf9a0be8571e08c9762edbb33c1052e67cb38ce3be6f47e857b66e87b59fadf4b4e8afb8ec6879966ff1bc877e0cba4229a5b304a7b8e1b683242d7ea883a4acf3215e49435fd26c0749a10e85680d8528dd1a861a30c7c8cc912311b63462661e8de6ac02123d3e7e064ece39e76ccda003478f08e01516c2982a128944af39e784ac5231ffcf69844aadff1b0ec86197310ce341c352b9562a79b19b9a17145be29fe1842df12932e5affc212756764fece779d3f1f17e3009f39a5593c7e796e04b02b6e64620d65cd549759a939979524a55aa5a57ac28ad15209898d9d95128f7effbeffeba119be81dbc3c5eeeeeee2c11eb73160adad86a651484e97720976f5d0569b1963f3d7c589691af8c42dee6714a470623649ed6b10ea738c5aa98691a9bda1b14a9c73ad80d08231fb64c8a7138ceda1254dda83fbc5e4ff32c8d81f131bec73ae9639ec861fa716855346a118d6ab415382d512702be336ce167e8c2da16aee3b02c782c7481800b0d2c730b215ba369190ebd0e9e0fae72dd79caf5872de5ba6ba08fdd0c18d3cf2aff50e7c367f8b4713d22e9f5e8c027f6d8090c3d16862996bd53dcb9f09f5a86fb48d75cff1e52e35dd332d57d8799542dbb531da08d7ed9a1eae1836de00be1f736fff3777fcc9d5906296c7cf692bdaddaf8f3c5122538f821b320e4ae72ed9538f7dcdddd5dfe8be35e2f9fe127208c7c2452a2608c3c4215f2a1fcf9fdaa96e31bc992df5de9f3812ffd493d7ec118f93f54b9d2004aec9c06e0b15d9f30213934a912871c201e1b5f96aa49fe0f3c7c52d2ff7c868390df9531e0b806c6c8ef2b8314164544065f82607b3ac3fe18e7ce27d2df8400df0d0adb9f49f718234b1941b00996bf07dfc9dfe353c5f2df40d3dff4214b3e7a1461815cc8249a1e74cba14bdf9c6b3334b165b8dd636cade39dfee6d3cc2f72670f12771ab9f331afc4bddcf9d42b7df33bd19d3c5a66fe7cd10d1d251177dfbfb4cc7c9e256ceeb78ccff9bcc2a074cb74777777b7b7a33fd92c39763bfa93abee563afa9352d2f80c24f1c05d6e0d919fe386942fa57cf9523ee6554fcaa79e0c4f8f06c64819a4b0fd1ca5b4be566b77e82f3e2a4694cfe80061e2c71863dcf10163e2ef58cb990860041b1f55abb51cf71f9f238c10f66899f8f1695a264619637c0328b1d0c68de616852a666666f6e2064a82bda251cbb40c44c215af5baa01554c050b7994a072e33f840e1dbecf889c45567a37fc8d1e1c5d7f910c41b01fbf880a2b84d33967fd7cd605c95e73cf1edeec3f9f2c7bef3a93b2b3af9f75fd4c6c563a5b6a64e94e64f04594b2efeeee0e6d4ba10350430b5126b20379af45505878a794d86b5d10edb718b5879bf618a6691fbb8f97657fc363f7d1b28ebe562fdd814b42377a4d8610e4c20d87d07557065f644062fd678ce4c0489428515c3561e4c0bf1f068f80069cb909d409f544ca932a44c018428321519a70c3842541ec4b47e1297262c2102618c16c7cc301fd088c0fa30ff1c2cb176e35baf81dc46089ce0a0bcd245d36a4ec962e9f81d2957d01615a0be2f687b297105b9aa75286037efed6e8fc89641eb992c59a37aced4a29a564f98c74b1b61b8a70a9c070a467a4ca61fae433da14538733e9f299793a4917e6d5cfb6ae3708efa6fd3c61f1b5754e9a279fc95ea71796bdaaa6c1a0c2324cf5c15418a669a690165fa57df3f5d7b7f4dd0fdad864f81150e3d59bb7c437d0d1ae28acbb8cd3094b08ee04a90a42c8d4099d425fb445a5d02ade6ad1700e9803423f996aa89643dbe04e0eaaa22a6803ca50411b09f809b74e49cf94e6aa8dad42454555717a543593a85034458ff4e7de0aaa5a86777cf6f8ec998e831ed172401b4ea750eda8a88a1ee98ffe8c0fc751144d5115add57237373737ade8c34b7f257ae32faf7bf0d2235e838a18301a39c188eb5e11bfa1c4e6a203de1d2f3ce189205bd4d490848030fd44d880d6d09b1d7b5385d5810d50155551ca9d5a56549090a194550ea0654b9005dd59ce6245ac624f695d614bc418679c52c618a58c31ce39e78c5dcecb4fa553cb60224ca41146868c8ad55ab3958bca0b6444ab325696b9582d293d536c4c375c258b3c3b31dce05006aff526c51b1f43c88620a9dbc29698f5b133cf2cd1c96178e5331b54aa9d125495988b84ba1c3a78d0f805e0d72a6f89543b20949af2838140a0ad0126179402ab50ec93655996b158cc76d556885a7304af152c04dabe0bc99de88a382b272d761ec855ddd326bbf3c1aa17c3c6a990abb66278d16a68c1c69eabfa5c8eebc958b70402a94005f8c41e6883050615007aa8e4fe7ca66df4257bf06e58c5a2470dc3b28ee1575fde6a821b9ffdd3d53d96fe6e05b312b208ed102502c059f81373317902154970c26689677104215b7881080e5a6f4b81909a2350aa2304598111448e308408975a12a57472355cc84345183774210f15ae990422a0b0a8028522f50a52caf7cbff99bcb070bba15b2c1186eca0a08a0bbd9041163524febf3ccc60934b3bf1f04391cbffa365986d580709991c1e82546222d726aa76c01a4a2709b7c4463e1bf0f79771e15291465ce09881e438c133852b58c03385174e056f00055d64d1c51298d859024906615b38015cc8f3832eeee7429e1f4cb925fb7c67a98aeedc41746327e446a7fcd42bc58efe4026f71319446c8c0b79a09822041456c86062e9853c5038e9d931badc703473b3cb18239785600c3f44811059732fcb1f5f42c97ceb0d1e8764ae3907bdb588f1815c201973bbdfd06a6d19658d860c108946114689d576ef9594c225953e290ca4c380099754faa43060e2c6291d064c307b0c63e447204b74bb7b4b9cc1cdc6a08cc3f8f0236429e5d75fcb979c778f61cc7c384b40dcf83ea11c02074592ae22b52b6fa9e54a1fa8e0ca2757faa005051229a5940808c2054a8af0c1102c8860c8164e7edff7f2418921820bc24d3158389081611813381108006062c57384275b024705140a1704a7be48d2056b2f64f2051300f0035b2f64f285162d1c012e64f285155a0bc9ceeeeee2ee5177772641bdd4dd5dbadb3954a365e3852e1f4a794466f6cc27aec4aac4ea64f54c2a4889559fd19f0cadb87b3eba4ba2feecbc1d1a462ac1c2d287e5c0e1775a0718235f3e0c9c29318c7ce9f570ee952018d02bc12c5cf9256c65f30163e40fc009fbfd651f4c7e9552d69bb9f40fed41a06f4bd7953f821f7c23a194b279860ef99205a35c39e35fa62be341fc2cd36e13dd7299bb8b71993b17eece856977f67277322ed3e72e77d3cfa676b93b96cb2e527e772eb2bbcfe5eee667a01a4aeccc89311ab931c6085b9ae6fd68a2ff87f69b57778040dee4819d46be2495dc1823ebc6a7e9817de42d2eb75c78e1477b600c8d5b00ca60007e3caa97d128c140dcb4f69460b5da32d78640366ea01e1ed82e4f8f1f802516f4a1d77e7b6863031d9ce1c0280b3433fa0b81340bb9160f2fa81e10b9f17768996e1e82c3366c2ac2cd78a1819b31579a0bc2ab839bb106841bc3082efdb04911d3854d6600e572e7d21e8d2b638b9081839b4d86d3413df8addc951d5c7901844b450a91db03bd2288b77e36a1dc291dcb951d6c72c4eb6698263b17fab0490d86b8f45beeec3ef7889b659afc687003f5e30063e2d32e87fe62931ae4dc8c03d0e4fbc48ff14b5005e5c6520d57c62d551d182e7661124ab810c6c41f8013f6a53f8d651d263ed625517b0624967be030eacdb8fb48e3339e2947e4e1c1941b7f47e441dddcf82368191861105b4744134a27be6c7ea1a1659c75e3935baa2181d8ff62a253d4be95a133338d11f0652eb50df29b7b308d18e51320464a3d87704794d1d11f47af5d0e876187371a1e9141772f557f1f84da371cd1637f5dbd3d463abdc6dbd793641e4262bdcec82fd5fedcfd2574cb4e4a1c8450c6fecbdd0fb8118f1cc1440a29455481b38517435880a321c172830d164e2f6025710330a89015bc6a8de605175808480d1856c851b2049221568843a0e2b5828d0a2fba10a2f5a11221f810266402141e0223a45085138410851148bcd545930f155d5881799121b30a16b860ba9220388f13a9c9e34412975ec8e3c4e996ec574121744a3dea0e7bc94b7cf9eec3da6a2d46770f82796c37edd03321b8c121173e43bbc212c36fece0918196d11e7e8ece4147cb54aff4239a9c89a8748ed87c14aa990180000053150000200c080583e170402c1a525565f80114800c697c4a7a583a9ac843490ec3388aa290410611020c0180008091291aea0460d9467983b2904febfc26e0196c04c2d3bde7a334ee9b17a1e4fad0c985fbdbb80112816a1c8284e5c272ce3ec588f2b1b647c89dba1c176c444d079b79a97b67683c7c65d55da40e883675fa027517956b48b588b0c5523285b770eb13c832cc4e22593fa600061b5dfa219c5d3f0cbb997db857de44ef595df6ac32edf67aad28c3113bf25b89463f8ffe221890fb8ea3cf2c5008fd0cf2d80ead7e786c71ef48248cab6915c6216ab8706af5cc6dbf53dbc6382f3026dd8e3a62a883c459d65b5682c6e708411cf893958a1e82b4dfd72b84a0201ed998e76cf724ad8b154056c8bbbe7ea3706351cae3e31777f11af98a6accd858c9c40e879afa0ec586733b89267a06513f724e5b1d1d39184d54794b009e2d46c1c5f9580edf329a6ae247e8ec25496e2a16a384ac83413e514a0e47419224b39650d9dc5c552e30954ace86418b52f3b68b1d58761acee079276ffc6425be9ce10cbe0d4870306e9d4929fe90ca3def4463d23fbaed1317c59c340d2e858d633f135752aa24e10ca33caf0dba93d9efbdeb35f4ba42847146ac504aad116e9d4ad2780fc48b56b378a1a35661f9dcd09aa632ccddedd554dce4ca8672b09098fc10db86d3a1a10845f03dde5a59a0cb68c3f1681fd128c0d27ceb0939262e54fc4f48c9e53099b909dc04527c8440983afe68d93b847d3cb9417cbb37dd812d69a59590aaf9f1e450bad37a5fd0321b12079339eebca96e19312b21fcb552a606caaa3d59c72e36b6404b44dd8997457118c41e3fa3f01e4f0cd425926f0676170f421884b74db60cb37b08ccdf0cc0d0f25230bbe37d0bffacd668c140745fd905861a66562af4dc8d643f264aedb184dff11ff084c35351625bd5b383d472c3b990b4f01894980171558df57ce9049999fd84d08bfb54f183fb43a5d77e9226e0d5932d59fc2dca3aaf24ee4264bbf486a9b91a69de9a772ba1d63ce554af9a8174b0f558bc508ec38af46d6442cc85de4bc26c93284ad84fd539cd6996c573b373a7100506d4f15a68a742289f0591e83234b228a585f66c72916dde5d8a6636fc430c240c0517e170494a3c1cca873e605fdd423d53b17a0a6fe43959b8d51ae2595d182e5cdb171c08b03681b7d0f6057f49557c5ff028860309a6289b26ff324eabd4c886f42680234c56828a7657af4a078d8cbf64c8f525fd4398ef7286527136cef7e12c5da58faede6a534c48eb9978515090019f61fdd0248969dd82177885085dcdd91a55058309cfddf61a57513b581bfc0e09b8da92a3be153495f4f47151c1f5ebfea5daaeddc173b31150ae4d4f5598056382f77d8d9ac3ff4bd27c62e2b457f8b235371db07a8565615d174406323b62e46d051d107f200f6859c770e545ca73d8067e946531d0c928fb9398da1758e6ca8c5a8f0dea581b3aa3b44701f36e46abc08df8a430437e0912428406586dbaf7fc09f5929a9883f31c6128912a3410987cf9624fc9cb9b9f5002f1bfd71acadf44b4a687fe781df0d0aca6aaf8bf688ddf0f96563c03f97aa7f0270b1ed53d044f1aa6e012897f9f888fc7db6f64eeaaa4d2874b38069ab503c31d5175069004d748c8fa487e0c658a3d81537207e69d56a7a53cfdaece35b43c9f92bcb7e3eab7f60db0a61ab7a03d4399ca259eda45bcaa3d0a10373609843f5fade1f4d590266381070551a36efd141a487cf0589e2be1c70a815b74ed22436f338bcd025b6498f1eb3599e4f194cf5f9fd569c385b7e483b3de783837d060e358bdd58c5673a41fee383ffde288b9a50da285eded9b00383337920aa7bf29908ae6733e1f781bca788c845aff3767de3242cc5dd06a5e6d1cecf5c19843b7352c2c9ee9eeb6d629d88f424ca858025fc72a41a9d0ccd21168b54c383ea1c8e112fc10da9d8a9faea2e0eae41a76efc015aa5cc3fc422ab1da0b1cf7cb30fc362dbb8997a63080258e9c8146a1533e9ba3285fcce0b8c298c1da11eea464bda9dace4b18cb895e00fdec1246bbc7e6669b64a938d85e420c764029bb8de2123070c3bcb5daf8aef89ef8236019751be14f1cc5555873ce60ae9186e051a8b876d3bc4a5f98704e665526b68508d3573d72073dafcae94325930199060390030aad844dec86353fd5b6c03658463e5cc42eb18dbaab39afbb317ba2b2cb833e618c06e402a1622f731eb93d5189b56289974a532801cafde3c25067102e5d96bb01b4cd505453d8c5862baeee4deb438b9a26babb443910e0660325eed7a588e6e2d372a22859e45aea1ec88d28c90af9d8eeeb29e88659489737fa42372d378a18cf538482c03fb7cc0de9eefef62ed2dc60a3020ca3dde611cf320903000d2c890c8c3293d18d39e90ae19fd60ac8a1f9fecf1a64a29f97ef0b1823ae871557f1cdef3a894d025194c038608a185f41df53a240f82b71c8197644b5e3515612f9ebc9a83bf64796934aca3f3aad4b70d38ab9c9c729d87ce1ca163276768d8e7fca9dd094e40114d74a61a2120e9f704198d03daed37e4590318844ae1e71820212b8b9cdc1ead1ba3375470ac2708e8d06908e201cf81c5fab0a12abf96845160b4714d74c4b9f6fb7dca39f9b06400b5b115c1fddd1067de2b5ca15c232b6436b794eaf1453a86cb4a24b00cfcbe238103ad504ec78175e6fbc33c2a68e31b1883b0094905e7a364eff0f2de780ab7f2823e540614039025d7ec44760d745528e0924cbda89730016c751c01a2c68c8e226ffab9124d74e7a236b593e3371c078e41dbf0736b7c8b592259c69ccc5ead354cc5dd21da664546012e8a25d58c6fdf98af91f489cf147d01eb410f3b25452e1ca5693008f251317a6466244179466f1c835335e17746bec73c2b532c41f0862b6a2e5f6cd6538fd82ea08d835603a8cb93ce1bd757cd3c74795e6545dcad2d0dab93c67c709218b02fcd05330e1608838f69485764f20e56feed82c960c3d8ce7da3be4f825622f2b3c53e136e5c717d96ab87847eecf087fc0530d32f411b55a4405b5bb593a4350bb31dce52072fb930f4411fdb3495051c23d731c7b0a4dc83a380e7f89bd7426c6d0c3dbff3668736d2772c07adc07123f153999127bbc9ef61c55e390a14b3f818ccaea2afc7d2dd2cf309fe360fe6611ee91a503a01dfd1346bdf963af21b26928e1dc6bac37a2c13404c860c5a2254bc77892c318db091071a7e0ff182987d12c8a45a2e882ea2c32315011c881d1053d2371ddbeac650a27a93275a814e17a2b748ce36a41e2455be5ce520f2d528e61346a85b711fa1d9efddf2060f8537c7e8bcdb2b82b1a5f00a756bff4dac59197f378ba4c355e28529fbd519dabaff78bca9da0518a1cabcd5453b63cd872d6619b1cec14f8b5c78b6d0ca68f9255319c3651068ddf0e355f6942ff94b58b7cb341f24fc193b52e1e9b3eeb004d536af679e06f4364c7b0e3a2bb71cdb6e62824f05a50575055911445d60759c60b2e772ac43a3ba359018eeedd89a1e813f4115a06ebd7e271250a3a42486cfd5a38f787aee887e2836108cb386ffec969d18b05dd54b313c498366d842baa95ef14fcff7f9a7078b06fb04d046b4b097e2a9cdec85eaf90f18888ea54c190755b368af87dde37511d196e26de56778d8f14478f25edf4c90743885846cdc681a21611882684803ded7d6de906e5a7114ed4f3a99b3c7f77fbbc3156ab8f47435dc811200b09bda1ee4031558f42d86f77e0f74d60679191cbd709f52385e4b737d4def9c8c6daa858efdc93582171b1353ead3c7555237c56bd116afa105d63023ad6e217eb27f1640b24d966d82d4f38594c0dd54ad10ccc44e7511cb8947cbc84dcd74a7de36b88b964f6aab5110730d919f1b2d3ebc7f7d15c14e47414ec691a8140061d106fe85c73014bfe2768b4920ad03d70eea09101c2a1ee66d474185868fd0c556334c9ea8076ee5f089955367aa38d45a4a7ef3969a4e1aa4c14b1831eb58920508752b231daa40a0ce4dacecabbcfbf1812bfffe4966d0ec8489b675b36f20df56198d4f49299676e814d5a63e0a8b6d40284a9c721d587dacc9131d8e69cd8fc04f05eec7784f3589a56ba740f196d6ae47d546c3449e400338a69f97d2b3e1eccdd2fc900aca6d4ab2da52f40410ebfdd10d843effb23bdc6aafe2b24aa02d7de4c910d49469e333a039cac2e4f10baea7951003d3e49368614b004ab626b269175e4923d420d8450f8ff7c4beda89c34e6d613b27a096e899e0a0ccdb31e96e18b30882f4ce572b7de49ee2a7ca467dd80ea4962b284e250cc3ae8d30d1e9ecb81ad203dad7b5d42ac025a6a740d518c0eec89e0b4677a7de84e0aaa0c961f09f01ad3d971cc3d6f12176f02feb1987890230762709043befc0398122e92002e25c042b893b24ae81b38db9fa8fec5b7b499af1e7682142d691254176d859a4cc11c392cb03f347c70969a8952c063e70d5532d7ce648eb9f6143bf44fcef943408f8be3582baa47a49884db00ecd430c5608cf5f49dbd04c78aba6296f95aff815f1a9cd8278ea6db9b30c339c78e24a38887dfa1dfa441bb5551fd1a98a1300006a31c1c6ace295a0b1a23541f985e72b1e17b069f2d12b98ea137018704025fc0fa2b049c083c16801088553322c6f5d5daef10a95ea205b3601d093b8bb36843eb34dbbcaa962ae1435801bf7d2e6f758740cc83a1416f7ebe0efd73dd1050d09cea76c4a32b662328f0df4d3f983ead9a91c64651e6301dab8d5eb4ad0125641ef182493727887c7bbaaa0ad1e61b0fec6ef191093e0d25fcb76b25e463e7231103bce89d4def3b9639e3184a0704f7c8b5041ec52a226cd9e0ca3d6c18ff791e6814bf145d8119e50e2e93de4011c7505eb5ee6c00ae008827ad3f039a79da37e881e6cd36b33a3188ae4621fd2b9370cccbc8585d1a415b096c58f220360ff1eafc3d2967e0fc67ddeb1a41f97b1c5aca11017a46a5bebac4a664e1872cc7e012214c0f639b417116a2032d4d3b1765b5677bfbcd01be2d07f0f35b55d430875181d7fd86642c31a14d641026e6bdc69791b456196622e483b9375d6120c7497b77924a643644d01c361b6f4d6a8ea4cfdf80f470e6aa542e2a8b3b7aa09468cc6b913feba8061f6fc046ce0fff5b49ed1bd76018a57a425ac080a671a94af5d3609d1712b5c5bdacd309ba649577c13b2fce06c5ecc99ab1be85eeb99dadb576cc2f111da3dc50fd0fa3a2698bd5146c7212f28990d48a0d09793c74cf4617c2a38d97c1316cc14e1fc1797e810f3e6469f02100364619ae7ccf9ff572133139cc7d0185ae931777736d7885ba3727f2d20a40ee70a913a146b624641803a09e04d0ab22f6094ee646ea79429dc3a979ddda6e37d3da1e5b3bd924a38b143c4de5b031dcb96f4c20610cf2238de50b0fb193bfe711350e3b7f3bf9db20364f40dd5e9a84fd1d701663a27643b479bfefaf8d8125a81a223bcbbc4a5bb0d28e33a220b933022be68ab607202faaf4a92cb2016030fd9bd7edab42a96b65b69abf1bfb094385deada4e3e9cf1d95b888020fd431c8697a0554d06383400862d6c1dfe131de36b023b100f4276550d0435c6b8a79715c2988e52bb044f610a38bbb523ef45814f6532aafb8c6476142e022d2f624aaca5dd1f894e0803a0b917ca3a0a2f0417a4546cdcd4db3e7e85c4250c8ae19628e477778c3d8a69ac1e364b344e4d9601ed11479be4660b9d7410f63269b098dcdc6ce8bab58b885b53a73f5416abb1a3a939395f5e509374c5aa48c8a8b082b37b010098ed5014145e9ac20a45c8b054a312247885b688bbcbd1e0d719fc5dcfeb0cb70f83604b93679b30020536de60349883b00e603a68c111962b0fe2ea7e5cc304c46917f1d429b56f9fa56963d4ccd32787d5b7501070c30d55a6c45aa86ce00deef09027fcac06dbee815ce3a9e99b1ae1a7694bab888a4e387cb8cf690c5bf9e68107aa463df89140d3c52621d65d287bcd8f165d248bbc7cf88979944e18055006d1c5a6032642ad21bb2082669231f402cefedaa2fa482dde545b9d05c9ab574fe0b91ef175a1debcf91e505750be46b73cb1cf092d76cd4a348d32d862f4b7957c8500fb62f9c0e3788b701e72783e385726fe64ecfef89bec4e9ce6da343adae7494f5b64e3ba7686d3f19405a386aab2f532eba69f2cb64a7d4e4eb2efee7701a2628ca6afdf731b57c34433c4c245ea00e35f94a6e2a45c64d4f19095a28549003c23c93cc9dd07826622220b3861122869fd2d35ce509f173f531b4b2951d0762e835acf3b29b65026cd262a2e6ff7504c36877f8b6328c21e7db205b7be32845b1bdae3b5608662b30f2f460e2f592fa65e2cd1de704a620541e5b6f07752f56c926b1acda80324dbf4a49bc00e586a825b611637f84a02ca54b1050a0850ea1844bbba2a91b5a2fd38f41acc096a0a01f1a2d23431d3672a5f081089d85bda617b88edaf19f1917463f70a17609c411b984695a6a8fa0bb40ec7a4066a53a244a97f7601a67878532529bee72f4303722b93abbd9668c166b74301dfc0f6ac7a34ec9fb0d91189d443ead0a1e70a3cd4a3be90f3e5fee90fa44aa8a428d9b54ded9c3aeeeed32529fc10257a7e3c07d8124406c84c7b4ecd35b17f059c71dd043bc51b52f709ab62cb8be78809b9b9160f288de673a6852c45ede1cb4f8c486e69a03ed8ed78b351da63fb6198cdbd2e4e8d7bd2c16d7273787407f3de3c7b0de6bc79c076727040b0de739ce0ceda12c606fc6acffc3c99150cf1f638c997fd814551cd1bd9ae88e36df04a41f84624d84bd585032e0c1653c12e40826e98914246c35fce0c3c5a39208dd6a3ff2154bf6f50f0b1461045fb9ddb2ffd0e2d6d71cbae17a66b6f9cbf13ef8e4fda225b397ec00fdb1d5a7f9a020b612f909c956bf0af0c00a843fefe71b3b7c991c1c8249ff3be931aaa0e23064dc9aac8581ed2c4283b120c19930ea06af212b0bbd976c8b342f376cba5183c646168f30f3652ecead575f240a9843e50e65e8d9adb255c559dbda1e1f823e2d2de9af96517b45183e2b365caab7ee19a3e3b89c650c0a9f09cd036347e162972238681a199f09c70684f85850ac46811e2957c68eab3cfdcb52ec261457f4c9a0215bb389484df6d4996691109c39e97095f405a446cd904501c9f9bcdb2fcbea1d5d9b33e8c6d370a29fc88da9f5081ba23817f0b5063d0da6ebe85e3b87918de4509489d5cc744014dd46c69cbb2eafc26f38168bb9514ea01b41917e7c159cbbf8821d66a43c8eb2829e81ec129c78eafb29c9e1e26396f5ddc7a1b90519d3398687483d3c8d927fa743ca46021ff8148e49432564be8982559ada0a6a09465d78f38adec0151ada6b940cf559a1c8616239c0ee25e504e01800b867da3cda9ec44b48def3cf690b0f12a4a73e5b30b775ecde047c8c45c7227e623c127747af099827ac0727aef7cafbfa09c4f98522e4cd77308032bda3fa7924e78adb19c84a050a2f5f81b6cbaf7f2110d02de469878bc7e338d7209f517eab3c640484b02ca687de4c26f59e106ae10cee5df03ba63f7902026a85fb0989ebc6afd2603a038b9eef6d4e74ba328f436bdfc863091dd96f31840f6011b66f818b8e557c4b59f4148d2199465aadb2f27c8462b4de7f18425e0236edbdb5d47bf0c9a05db33c3e446082d79cb099643ff25424a281fe68b80c0e5dd92f8b092598ff64dcb11278e8695fd00bc87c0b92191c8af78ed456161f5eded78e3cb7cdd5aaa44c430da9609054e6b440758ee049272b7546eead3cbd3f0395d65f308374091b04b93f33540f618ca38daacdf28c2ddfc4670d67176d401187329472ed1086095813e1877c2b7ad884172ff861362f543a5fdc9a3c9b1bacd0b3e1646d9c7085d3262a23ba5735e7937816b09348e541412d96140b6260963935d208ec44d9cb9797cfff370a8110665adffafe2ca8db374d05807384988edec03ca7fa46dbb35ad224e807e23290a45b66e89d5b591ed85612c930cc20ab2ad91f8b59503a171e1d7a39124d3b416e879eb678c67ed30a3e36bdd361f69773d4e266a97e37bea83515f01382b3c7c706f57f1e55ca86fe0e02b644baeaaad8231f3c01c388962faa70075827b803120d740b8840cad7c912a716bf7bac0f8c24ca910e983350db503ef9513cf54722bf7ddd14a9370a3db626b526745cbd043cf584f202b23c74f429eaa6787c87a5a0a159a00f42d7e860e3262e9c7738c3f50161f71fd9ea217b1ca22179642c4449794d1455cd63d7265625572d9fe9038df1800c508a7f905714745a8873e62d486eb734c483ad87bcb260b31ef910cdf8ea8011514932bc88f557140bd192b90200f73a009f2c61a79c8e38cb2c4f9ebbb3d46177a2eac525c6ad938d2a520155e58b70070fb48ed59c0261dbe0ca20201015098c381d927eac439b89024207b1a51e19608b25949b26053ed935d310b11d498a9b5226ad64ebb25f501ba9112df865d2b1d85d730c7fa29a859420ba89241a190f75078470f97c301f89f3149c758665b1643fd63661261b32af24c881ee3b207d4e622ffdcbe3cd92069aa498c5d03c4ed63e3e08c2e173a4a7237da87006a0944af621682aaecd4aac43586341cf7f32d7620b84675da492ab221bbb4daeaa15c9360ea120f4dd62a56c455cd936f7486c6b5c6d26ddbc28207e9f968db6fc5300ac6aaaa9409f225b8883eee31a5abc8ca56f76ec105be873dea6d63c107dc9d49deac8acef754bd34e1261d638a1969a00bee0b12ae61927c3abfb835b40cc1a0a1ea313d9e5f222714d4dfa590996635e474175982f9a8951e16068e169b631d39f4b8b32834daa313e98b5b8d8c9fd02bdf94f18bffa1fc4bc805e3e497f4fe9948458ec8f6928d301a6420ef2df53526a9953531cac72724d9bbf58309577fa00232cc3a0bb32c68247d90aedf36433ee1dbfbfc6cb07d8bdb13fd73c6a83798822c749b703870913cde7c52215a386ee54c3bc7d8463328fd85e228e806fb9fe444b2e07ed22de1668c2e2ca15e45a3bd292d00e1162906286551f614c4a0aa3fafffe2b8cf6c7c52db5edd91d1f44aa84c90047abf6073f752086321f076af54d1e74254437abcf6ba29a353bf5899cda58217132239603f25e386a8458b8351901f5a235d4089a33f49feaa1624508c70832831bc7a1136c85a7b920d71ca2e83c37a2aff6ee3c2043f5069c55deddbd7a05d663f6931f96bdeab204f2dc7a03b2ec7045a991455a0fe9763165225e9fc9457783d76de1fc8370451124ed1cf17dcc1536e3d024bc8e00a8d28ff4b86bb9e091c7becff6461e852427d70fcae017d04c477befe635d211760b7f3f15c696ce5f3b62f35771e447f4bfff255564e3d188e2067c78d58a9e59ebcea6b88d120809e1632ad65879aac6a32bb4ab82183055df7a705923650f74b9733d7add2e83ab3f49878c95d16d9d399d8d4a1171c3c347441b5f87fbeff8e30fa8f661545ebde4d3bdf26e74977293ca7a40839b70d218ab6b186c807eabccc9adca2b2f32a92cc4f874add26b1590a651653fc11b7b2b2356d9a6dd605890329f9fdb53dd10e8705a898897c111e854959776fa40f5e4404d23317a0c3cc98aa5da7085f0b98e429c8bc71cc27e3d65a19d02b45d1c02a0dd75dd41519b3ee9e7c2786782cc5aca08f7bcad5fdeb3d5358b0937a009a8968bb8f356a3099d617a297345051d2862bdd2e3e50ea49b35c704826e6df66b01340bc7daa063d9419f2678f76aefc49fb5a9acfe726a9033fe4ab60387ca6ccafef057e2424a9369fda8f37bf39ef2f4bc052a210dde98984854ac537aa1af90dcae8901cd5b449b5c512643cb5b5b571abaa0faf1f0b0a0d33221e6848250501cc76f781487c53792a1b5fd842ad1854a20ad23f6d14a3e4350d90ead50549a6f810951436e8e0e2ee768469d6fc755028981a8028515f4e04fd151113c374dc0fc05ee8c0c069d718823d697b217b6c43d3049827073cfaacaa0e4e4ea352417387898b67f119d39d55f112d2a0099d27177dde4a4a82a2f1104f21f876ba5fa4ec3e7134121949f20ccd275e2073ba9716fcba86e730413add6521056ca1d75ab591c2ccdd8544dcf935775f0c543fafb9d743eb9fec265198308947bc086e26322ee1da8a326ef1fdc06e473ea474b99dd0c4fe6acc1f6e0bdd7f6c3a4c995274bdf14042ea6cf183b2868196941b5604df3ce0074683a028bc2f5cb10f82c2ffede9199e19ef0a5a859268c669d382b56957b5a7bcd4166e5a33fd23838d5bdf69e92381917907a086dee012d7b33a438acc5d028e20a9ea7dfac8330f8d583542f1d71becdc435f1e09cc368de6627c9e15de108f62a7a935433f4fd3f48275bd76da9ccd9b038ce0c92c9bedbc5d045e0fb68d1adead55528d5945d67cc055408e6e655cc5eda2a90ffd9bdf8a274b2926783a144b35a11c79b550f7fd764c871bb9758fb952d432ad3cb303475ee23b639d414326d7e52c23191413137211af8f2aba06a6d23624673c588d0b1efab1a57551e25084331467a9b597bcbd3144317da2f494c65be74ed8a421514a14533bcd064373fc98e32176112681e56d3c4339f1ca2d6dff41741369fea9f3295048331589acc73c0d80e1519d5f762c9bcae6636d83ca6b73a11312e9bc39a79e5e13b012fe098d23f158429e6ca075bde090999b17426bfc7dd3877f6caa5749987a51b34c3ff158c4cba94d40c023daa43a85993da192e3462197ba98d031a69d6a4d25e7cc17c2864aae8f8d6b70d932bd17e473a1db8d2ff69d061b9e414bbbd948916d6b99446416095818d777251e9278fc2f2b945c53137353451ae228fbaee994cf9a765788fff8372c4e31051017fc9f2e242627ad151f5a3b7bd6fdd9ef92eed2803e29e07c9a48ad750b665a13105948040af283e02ec2008685a4d6dd1c31fa6b192c0e60d9c94ed0dfda036e8b51210ecd3430fb9ee4c7dafd43bea7d9c9166e2eacd3fa9ad208b3d07443428104e8fde038b6eb73feca40591344d680482c394f13d2866c26869e5ad0d3c35e2678bb0b0d3d179de48e467d1a5f8a447616368f578ec173855f66c0602d809ead27679e92da1bd551d34a8f6e244515aa9ff75283ddfe548a523d1d2d152fd8eb8edc5282985f79d83597e90691c181fa9da520b45d1b60e828d27afb825346e782f7a505ddd8ae1edf9cf01dd6cb00248bb017cf925d5077ed09aa2d3629bd036f8e59f6265a9388f9c7b2922719704aaf7a7c1e0514e9616cc1726131d2b35bb169bf1faebbc2beaeaf00332ef87a6be7df61badd220a6eb57d0b83d2e1055d6b427715fa9fc2bb010e46555ac0621ee40a68812744bb55491f8ab83761ea262ef95c11351c21804f985b9378ce47362165c08252485f0c6760e53a93d7e1d25a8e47cf980a740529c2ea2db5085b47a76480a0a3561975b09cd4d880543956d8b858a8fd94542e8987c2c2910e95cd5934cef28c45afaf77c4c72cc279156c843ba7e04b39867e5d2879fb6e5cde933049bf8e816c59199869ee9095eeae0d16e5bd1cab271f5e36b0ca68ecf8a537562176496431ea679919177d0567d572ce24956d1ecd46494e103098793931a04230c1e7369bd59e6188d8ce885d228f6f34b1ed0cf89a18170f10410ebc23204ba2f85a5a95b88afb43bcf97906a590fd90fbb563433fee7e00091a4739c3ae9f62a582da1f13569367403f1b4ba9c8221f062d82258b16cf17f220f5f7a1285a2efe10e66dc95d63dc1078937fbcf6f3027b8248a8d6b285d3bf8ea73abd7346b304a8448c7ad630b53f74a64b18157d25e11e2f568012d7c971681f0a6f00fd3c0389f58087e435cb306775dea67c76e1c1c15563194a058c9bf3973dd61eec114d6052da2af87dc51dfef0c133e031800feead75736aba37e5c903c56580ede5819d3c209ee3cd9258d603aeff445840edef7d39e1c6ca8dc3c0408369b033e628fb2c98d8da70f0642190c76dd52ea0c6eefcea4f13010ec565bdb9a9e326175da610711f020d0e1dc8c02c51f815349de92dfcc6d6dec147a3093a5276ace1c202532dcf2d4f660e36cd0dd330c02b0f21457870fc21a8ecd1f809dcfa9b5003f80e2d46b3fcefdfaf33e0013b6c645ce3d0923511fc474349143c63948d9d034d0d2770493899c0c8b047efa770da5da65201e8f0a79c774fc8cb16c86e6363b7da1d8c2a71639b6a217ac1839c9c1200e620d0cd098de15310778fd4a464c3d337772b90fd0aa01d3d607489bde3eed4a985309e800d9d667d04e5fa131f0860ec83fbe06fa690c58f47027e50ff93331f8e1ace764cb251367d8749f7e1a44716cc00a814456812a4636055ff5dd314dec09877241e3b18051f3d3df6782239b425a67c794d692d2455bfda9806906d1294d235b780325381181a62a800e8a2e0587dc045c01ea55d7ffa5fc0250cfc98c022d4b683c403d71c831185e6b3dd1b5af5e3ff5d39ffaa409b741554791a29fbe9c8fd177b1563fbd6dc054e250ffeeec40dd4a9cc6030518fe233298de21830be25c3a06f500f55ccda2bb8d6d6a02a81f2b656f7260302f1a855e7ef9497f784b93960415b6bfb5a4fef2cb621777fdc98667d11aaf8501019b0f286ac2445f68d269d1194568b04739803b95748ccd12a419fe8f758619c37245191c7dbe3fda95898e95db0f48ba9b2ab5610c06fc93ca9f3113f9a7bba82b66135fa68583dd4612c2b9f5b940846026f960708bce2ffdd8379b9f8807166190dbb7660b190dcc40f48c88d692232a34587c7b3628d96d11b76a28206a5e5bb83bf92e78132e6c0638e75634037c68fbb6efd401c1e9640f59fa3b0b2a20dd9b5bd49d7a49183301e5398b5054097fb77e76bccd90500194e115fdab6149d042ff9e39f226a07f915dcb102ad71302708b9d7c93d004278ae7710dc8edb87553449417f91177fc87e2ddbc8dc0c57b621ac8ca090346dc1b82b55b2651f8f9c58403b8ac565cfddb251bbec03ca29219656a4fd71cf69cd3566b1849132f3ef3bee694e35afe1954865d7668d32d6156cff02f1b27bd66f6808e62c047f46644967163146b2f1f0bcf37d4150588cdccdeb1812ff84616c66fd8ad959205c5355588aa9ca9f858260dc97486ba49c5d3a7f037b26fcbeacaea0da50e3df6ec22343927a59b33244f742674216b6d07b3a566e89f464e0bdb09969a61d57d45d4360c19a3584d1af9966e9ec998795869fa3d8b3649c6eef73a993a427c3e73d6781408eb9b0350f8ae5f7b128b65aba9f919ce663febee32662c54ac456ad39f33f490253b7d51fc07fb12db9175845672e28b56000019a2d5073f788a81199d2a14568209bbf7cae0acd453424d8e9ccb86d6c48c7d9367da22ab919af568d9652b86f6364aa5b17afdd25e89f8148b4b0317a43d9bac8eac7ac692d92c106414edb54e2849a94ee84699847447501e9bc85f1929f713bed11b631a371ab617856eaaf956bfb7849e813a387356ab04c8337d9e308cc1028c61f247ca4978e765a4d45f1a9d5bbd1ef4732078896181eef3aa228e75158a16458f94fa01e898ca2acf863fea4b04d72dc1bf7307dd44a45f15448e88dd4d345de3faa407a4aa345ad4f03029a100fc57449e79563f251f31ae8d6eea9e8288079355cab8be1636ac18100a0a481f131a7a6a3b604e7e1d5f9771a79fc74d51307b9fa54917b73d5ab51b3f341fdbde7fde3c84ddb91a01d984770e2535b088035726ff9f343b9bee032611b71fe37aa49f93d72d8aacfb2033ae4f7ade07e123fbd5936bcd7a334242cf367ea0856db0da45cb10cc9f45a58921365f9984a8f40dba3eab6bfc6088c4fac9633956103db49b4460a41a74f4931dd49e11427a748dc19124008d1fa8e5c11942a8fae3d8c60f9e4f49cee087da91ac0493866fd9dcb831512d67341228e2c3c05c3f4b7474bbc5b8a23868e093842b0957dd9bc76f725ff3c404f62192c836d2ba399114b03066c2c4f1836555a026aa036ab52668878d4c098970725bf9cd6b426be688f8413a4179040e8acd55adc6f7315b68620bfd5d71517f708a1b008813371fc071fe8a602a2a4fe742052f408aee6040fc447e1d88782560b3e519e61c654ff3134f421b2d4d010eb3ba80bd3dd09b738441c0c8058e8334f821934c493ea082e93465191d4a3364441866d3caccf7e18e8d646f1a74bbfdca0d73bcf3bdea4055f348741eb99f0e2034e256a17341c532cc9f8e57118e9c699c8cb7986f2e87c643aa77476a1dc42ee11ccc4161974e92abf8ce43a0b93712db546c8abc6905cbda8a5cb3e457e554dec432862da0b93de90147cbb081d16cae4587dee40fed602107cea1fbae76ec068ac5392a639cb483a4741f34a1f65386d48f21f3d5287e6bdd614c02a336c779209104919915ecb905cf97932baf98d70581ac956a56dd12cea85176235d398b3766cabe42528d04e12c46a58fb6523a4c9154873b79269264e8e4d0ab1609d0129a793fd5bc0c77963ddc7bf452dee269b4c7cf1885cc344c83810e4e27e4175212f440e34aedf45432d2d7798d6d18b653dd2418182c927be309ac794a0133d0476530379531421ebc846cbac95a8bd4422ccc0f903cd71331e9e09b1e1c0889a759c6e39ee57940e66f855acc3b1a3bb9520045bb166bb235756035e2f978865daf5e97ce98838d3b9a4d9e266eefd1c3c92705a2f71d17f51a9ae210f4d4297fae7914ec2b02cd7b8b77daac58f612d8745fc33a4ea88525e282c7972018bbf846ddc0e85a76ccf2ca35395010cfeee605aeffdf5ae6ce013aa29fddca07e5a956ba36eed58fa09291f8e824b932c6bd63460ebc6d3dfbb015f3468707bfdf93592d486ed8410b67259e4411ffe64122441cc2453c587ecdbbb2a45ec938d94373f4944cbb10e2f83682ceab71587fbfc9e028825eb254fa9c4eb91359e2eb440144d095475038dbc5179d788a773b9090f88f73cae85a72d4b95e251f13d001d6beefaebe1afa8030902ae32164d076382b61da7b45bd58b1b559281105ee8fee296af109d03e0fb2af88b2883cb32c65803c61fe421fc3953c663db0004f06db246502ebb20787325e96fefa153573a10d71e418b291ed60ed2da2e210f1e0926ad31613db1327b29d119d800b8b3e0e1b167d893b4ad0d1b61576e94d1dfd82a76c9313dfe6a5754db4150c96786b6f68a245d03e2f2ff010805eb34069c33fa440a31255f1349036950491f2cc9405f66545a61e550c53589fc95d821bc7ec0ef18bc0b19e2a89937dab7fd485d9d5e2459bba856f55adc1a95d2e2501f64dacd735886c9f49b3d162a9e54a69edc9a830c90978a7bcaa4fc4bd64acdf2ec27bf609e477a436c3860e8864dcde6b4083561a34c4c3a1c15e84150e47296c759a98c22c9bb3afbd4959e8a0971cda3a292b0978e27708f4fabf39474f1f23ff8334db61b75615e7d064f5330bf116af75aeb36400ad9c90258f35b19bd3886b758995bbd13bda2adca09a2cb49c0c94039bb78c6c9e80098dcfcb51cfb9637abfaf8264ab1e6084c478b078516a1cd206d4624d635dd7681011dffdd56ad744c681524b4fca122f67e3c6a835b96c45b68ed2b1829dea19f06516c53a656eab42fefb519e678c3914ae1d2a182dfb64a6d68849885e7a868c1767fccab746ac59984944df2a2bf150a11813faab51449353c40aab8dfbbb60fd9c2b25f0151f30e8126c457af624231237e6eadef4899be0c83d607344565071ae07f10ad71fb7522a913010b5326e8c63a916ee56f33615752e28e0d838b5348a7f783be6fe5d0aae1934f5ee9d350c20ccfe01186218ad32c79fdb104816c3bc316b6207747dc0509c7a125f79e3ab0340a8f39fab610eb4b7dc8eb1e5c8e590c05b45977d60be6e16e6b02e44b08a08caadadbee1ad5f5bfb756b8e414a3b226c1443c4a5182e81cf70be106db15fdd7cc31d382aa6373159500b1c6725634016fe64aedd105f28d0fcce808f2d85d3cb2e55a057adc8a2f472617aabfb2ed0cb04c4431c6a5d6eb5d1aeec0614225c98d2fcefe2a6f9570cde76038d9c603aad60caf84fbc8d09e1d8cb865b386acd5f782832389cf0c3a58049862a6ad064397425affac3df2dfd563d49a20e62632b9cbbbdd03265870a308e1eb18c3ba8492e96ea7918352191dad6756034232496fc7b983a51d3d66cc194c5670eca390650db172792a93fd38358d805218fc25331baec9cefccd05dcf0497e73bb35fc88c5946f2681de1147901b68ddbb9ea47002e91dd07a4519ec80b4dc9ef4d1a5108c7167367d16ca4e85f5ad60ce91190f2f1151c83a594b5a05cc61ff6654e3bddc64b61ba04f4883096085a879b26fb029017675c85c5fd73e193976c2f767fd8bec2666843ed8285f7f2fe1878f70fcc58c679d49629ba64046d2e8276b79cc604ddd66acb5b93787a3bc7deb86eeb753d208e46cc477c8e1f3ce9122926c1e512c8a36f2f6360014219296c4d4abf14856990aa6445ca46cdd64a167647657af9c1ca16d7d07fb8697f91f601bd58c66e2a89d188d10937b3995b30a405a29a9d3e26723fd2008241cc977d2f623025207fa72bc1cadcb6ada1c27494677a4501c1806e42f5ee1a4406f262aeff523200e9545b57832a4528c3f1d6ce71b1ea938e3312eca0b8a7e081ed627e51151ef63fb15b3f53b23cb4084e195c208a6d3dc574c09676539c88bbb1a260d8878c8e27cb07d6720dc00f278d28573b06c0c87a2c7091b20e846404416b7b5754fc9040d6d2ecc5f86a2342d0d0e9d2c41350dae9ae1279835c0a144f44cba8131ee08b781e93b7853a39c1b37bf1ef51ffee02f19a21dac073c13380cbce2cfe66c6d674af93f09ccf9380c467dcd51802b81b1a216e4900326ffe626315e033f84f53c1dba5a9ee7c04cf520f9c1d2b16585ff6dddfdf20eaed901446c9beaea917abca42667e466f0ed856c2e34bd29e29bb46fda244d2fca896b93854be58932e511581549bcfbe21df3f477b6c4ef0519d826a19193c2fb5b19b77788f6ec429ef255417ba1914847d9caab1be74d3d641c8b4a5395772aff88dd03baa7a5166c1ee50597ac9a26a82303d91fe36084241f189db20cc8476887118a4366f0b048a8aba5d90b4fbcc2c4b2b187d9cbbe2e0df5f38d7c6b8714541d629f054cb16b3a14e6de8583fe0f1bc3ad61e669c1ca70612c1fd22a9644c3bee1d8520cc75b92637f248438ecb50c175dd2ff2c9eda23d3d5fcb8790bd16521aea907e6c5a3d76f152585da2d0c175f7fa34bf0bd9a73b3277fb6fd852dae2c91468d494799275d8f950d2913ff5c387b3937d2bb31e4efd357cf8793fa9c7aa36b83d58381935ff83d84089fef8e9cd1e0cb1f129576b22e35b8c61f10bb5b08fd57066d05e654d1a6e97a8e17a2aaa1bea3a175540d904060a5ad7f5561c23a061fdd1ecf6e864a7e170ca91fc2f23a7a8213969deb8457193be875e399bd2196ad57ca158172d1714f2de6857280e5e2ea8ab3a46cab7300817ff0803602a5fce825ce88b2f7c51a64a8b0e1c87d504c741f8f599d51d474baed1bfc994501504a2548655dd652aceb38858bdffff7499d53cc08d3baad9061010cb8375fb52d411d9e9f36f26bfaca262a5bc99e8a2cf59c6e49931b028afb33d9af0c6983f69b176d92f0f7fe650ea7713177828808caa4ced5ad7f0f023c893e5251ec56005b6bc720380ac92fb795a1da4e267e66129dc9a6ad8ef2a856f6ff3d3591fc0b60efa6963992dae56edf98934211af1d28f10914841f7fce410655a971b2e014cb032a1ef7f9122c596c80d3d8ad41f727484fcafb2c37ad0c8d0eb41cbe25255b735b031b801a2a70949f507630debf3b2688b5a5207fdbc9296130966d79a1a8642fac4aebf62521b108b0c2fbe8288d4de7cca371003ac5e7772a63a46321fb51606bafdd985ca10eea50cc2434f943fd3223ccd3fe24c915d498258d354961c40f3d85c6c5a7d1c6a826d4d3e7c6e140d730a573fc43ff662bd68c6a24a35756db863b73716ac0b5a519d66e84c0ff0691132d6e6d8adf84c5006f23ab9bbf9e1f433fc44f7139a0e7c57dbe014d364b7f6995fbf7a1a377f7318f46ccc64bcc5939e306e81a9ae4bf1a73d70b7ec231e8983b41471928940f9fec354d548d027473678d64fd51dece837dd49a6a62685169d85282381e4ff41fa425bdc5cb88783971de8f24b0dcc6fbc7b0cf5ae3e8d112622db115d96bc9b314be339c7a9011c662b8ed8400957cb59165598505b8e3d4b55fd3bb1976a10d69f2f004fda5932ca6cfef43004a86299892f752a0c40484729f3ffdaf8b84cae8550ec956a3149de8eb3f674d6f1f472639b328e75144cddfe886a3a96fd5a7ab1f1189831c88ec39540a68955a46cb99ec9823c9b2b141b3589767c39029ffc4823cfd6ffd500ccb4b4721a9cb06727aea65b34f345815b784939fe23b2ccc6c36e2cb17cc111294b68318eb8650376b9363159157e3d73e2a46de325d0d13b985fea4e5674ec02efdaf7428dee194a9a703a8ed163358aaeb17d9788c21622c93144d6667d4388a5a6ff288c9cc483214dd802c4a315ceb73a27a690d81afd7db60fe70aefa8f96653ae1ffe0cc73031e6327a07bd8e09e473abc09dc388b70222e7af4e06cf440aa8cfb262ff90c745a271beea641b2cd7a57f1b543c4ac766d308dc0b3e2d174e47ff42db46fcacc2499a8d21806e77a9cfb7b90345f241a54c2f898cf1d3a188f55665d3e089d8c0fa1f3b962ee994cd241bdf235ac7daa614f2dc6cb428f17c97702610e2af59ded60bc089278b4720b3bd8d4847e553fa2de9b124469d0eaa88e49e923f9f4d8262475977ecb2054dd35eedb552060aebe19ee4be12a809cd55ce280e5f43dc8533e2fb0dcd16d7a54ef7780d58840bc220dd737f27e6a213627edf4b499e824ee85d0bc52ef56b3cd309e14e5384d5b49da8e652ebd33784d9722c5097a0b653fde25120e99ca815a873e2e4b41d92905deb2d6a6211bf6b629f0dd390dcf7f91ca2e43f2f238a98e509a799ac1e2e0f55d5d4baac134ac1db24a22e714ab123695124cf9806dc292a3d9f0b288e2bbf6e8940d0b064ad9a1c0127a072392603a2d3f054f7c1e1208a4c582dc3fcd456638764258772c8b3462f503b72609ac42aa57617e3c7d895f8ab7645aad245d94953b25f2095cb15d19ac79b551b2c0a978a2a4bf7074333812b805f5403a811af77263550d972329d35ab9faed86e4843507256d0a8c49b73a0dc41dccfa5a3f6c3274da498f9ad00a5b143f5ac0810a581a9f2286e47ec270e7d95fcfb3b2e4d9ef83a98c872e90df2dcce17b8c5f71da7e6ed3a2983d497593181bb4ae1c3fbd837246cd2e84ac10ad7e5e369b0c11832c9829f9d1f2b21794cfecf594455a991e18586f9f812ce0486187954aa5838d3ce184ce20ce3c5b1cb9455eb4d3ce02927ed9e2dfde6c87c05956866c8d8662c945350ba49f6bb60042a2737e9fa02ba6e2944f575b69be2a22e6b513ce7cdfa83832b5e1a7ca6dc7378a02c1ec9cad8bdb7378c07facaeb1949fde3bfc7f2ec1266d689a9c8d85caacc07803b59e8ca26a16a24b6d0316914d7df6c47357c9849ad85b273349edaef7eeb213694ff4fc7699aa44c0e2fe92878de6091edc231c38ab63b2ff0862e878645a94204995d67613f3314a7e46c39eac9bef846ac851f6015fe2ad39afa0da0c133a300b90978f24cf3ae8f8366f229a8b1dbe088685bb4d402520e2efc6d683c0fee9f0eebbc55e3ca65665b862b621457e45b7e87745c91940a0fc78c1d4605ee17dcb0888e1e17505b3b0f522cf2927e16ec1b291a707764b44d99c7b7761b0d75e222369c84e15f26a31eb27a94125364147ced76feb598c363f50cc92ebecd2d770e732da33dec36315d3734748c6848f4db5ff3edfe7ab869298209197930179e48f0fde8c7b7317b4894ac8eeea3e98885b0a4091c15093c4842471833a6d65fcdf3a1d823305b48b6ae6c30558d86e36c4d547f81027ea45a3ebc4fb0517fd1471756fb56f716b96d811dd8166da3b64cc52b81ddf467e7e17136043f4a895d5248bd0a3d8d7213a143846905d276477611b0d4813340514b3bde63ab5f0199af4df84c16744b7de46cdd1575ab4cfcca92d95763834270c98a25a46381f1aa5f1fcb4ec2b798d1bd1e9d2284a80a427894ed67c59d988ac013300f80c4ebbbda1974b880ef09a383bb9bf46bca6e844f73a17bab1500244f48df1fb745d6bcbb240932ae7577ee4125ab9d0aa1096ff42e98538d12b94739586793c2adee9788c4ff88a0e0865074c13d50b4f32b8c98cc4fdec480d31106c1e900e2d79fb1692877b48dcdef850885d4c2ffc510b7779c73721f1c3b6b01c6a698304a468bb9905d1e127bb4118895bc6bfede14535243eee4f1e09b86fd9e9d2f7ee17dde9525f6b61716e88162312f40f1028bb6282c826480aa0af810c24094070ed62f5199f91082d3e0760d77113d2b7ee5d7fea62b22958e4e5c8858d3156ed397b8e4a326d20f3db61bf9c73f4d7e29aa741322ee16df10dfc355309ad0e812c3ae4d0ba489dc8da1cd4ec861105fdc7ab91e99745c01126944b6395158649d602db5df585b2f2b3b33718b42f4a926400a0b60da1685e72824cca089dd9f17852cb884b7f4589887d02afb0dfbb8e7e75f82f11bcafb2f3c2f610583f8717b485971c90cff2bef34bb7e216b26fde0701ea2a69c21bb0f102abd20421a1eb8d6039e46cedc9258c3e90409ab40edf8cdb987ec2257a26f4c99f31d298e691eb47f41c9e3512f7e4de772da6e77b90f0bf28e0dc7485e676bb846333f71baefe7524d20976db311d80ef54f11500b45a5d09973da35ee0c7d9ebd960fdc7ebd64c3015c14eba28a09d6798a9cc62464aa1b7037f4956f27e5b38c5782ed0e75d839c82d05dc5b4b9e7383e661d3932318a08be41b84a657b3943b926dab5c8f3ad87407399f534a06452f1e83c11038573cb0540737e22c4ca090e29945457ab4ebbd23e8bd2b2cb15941c6c10208413713119bdf624c0152f519875892c32e481c68fec37c0804c46f82aada58d9531a3462ae971b9570be6b6b4c030453472e7d2e6a68f744653f820936748982835a74c19f9e2683047f28bd07e6ddc1582650c6b7ec4e1ce249aa530bf6504ac793e849cf93547b28a6133495c78a27f6e4769dc8204faed5485bb9c3a7577ebfa2be6301d506b14c42f3ebc253b6a025f0cad15f31369ab4ee36c0750bc4af811793b240bc94986a8e16ff83c62809a9bfe6b829f702349d95c8c8973787f95772ba51c464457dd6430e31a4dec9198d9f0aac8cc24b38114c3af86736a9d830b9524cf0fb45a402266f9ce405394cb47453e1861131ccc3f4f44ad4ca1cb27f7249f67286d5b361ed23c27dc96e354e94142e7af52140b1dab6f8ac3c9c28e981293702f24729299f8912d860fcfb87998802d7b22546a22b4f0de11b12b3e5f48e1b72302aef06931af187e8f4d43f51ea8d825a9ac3dcd79104eab58636dc2d24efd16620f45fb1a85eb94ffa94c6853b1647f111f90eb9e17a824a61207db7e0117f5de945a5f594dbef322a4f84b5a6fb13a0725ecc248a39040d4230bfe2d8582f65891d5a121be5f5206b1312b71b5705e8a71cfa3b036a3f67401a5de1ac388128f2ade146a853d28033cdab43bdc56d6bd80d65bb3adc222c872f991f97ea70b008fee43b9bedd0324c871ce370f27359af6d15878961877c27a8555b10ccab6187741c49d30a0ef1218b0d2bf90aab71fddc85c160302b7658ad16ceac86ea4adde756fa2210e9dd1a1ec70ea3505ec8dc77e6a89381751ea1f06285ca29649d346d9514975eb3cf68baf8a1f451544b123f99073b439011dd217875045ecf6e495b3d4c3ced355982765b8902cf8fa945c67cf8ba09c82688d476cc0b44e5a871c005cc6905dbc0aac9877e85050100ddc0de6c92ffb452d4086c6cbf06bc34a5e0b54d79901cc3a4cdc05e8a712600716f0fc03de244eb08887514e8a7034cd52182cce839a766d8eb4f6fb6f567c8f54b569b3957ceb594304229107f055979bd314a80bf1de0d9f519397d0e3a53a44149d5bf94c01362c4b8c487c3d70599f786717b1d8c38aa3d17a18e053227f1d82c6dd285f4eb610249aca841a2e27c9ae7004fa9977bfeda234e4191c17a76e2a8dabe93e8137de6b15a7b60057cbb32287ff5584be0c9a76a5b5b17aef573a88074cc933d06c2fd64cbef4968e2f31758dd14dc4e80d8bcb38d0376bfef41f8628cdfd6719268a4c655b55deaf417f1e54cf0a1d816d7591249dbe60172f79f8275a1a7719d69f16b4e3252747d3e00873ad5fdf422b41dbcf50464b1e13f07bf9245673017a2a25cd543de7d83d7796e1f9ea0b76eb87a6c0936ae3fe160c29771e23b47678382d87f22e786f74683348e04cdb6293c224bee4a5f9d1bb4e31f41e9ad33b71d6f8870e1cb112e340fc80123070c3c127edb89d630f3722a7ee277bad4b7c29de6bdb11a434cfa7b6e3e058b0bb357dfecd6db174d71701052935a8a8352acced9fd5e8ef5951046f182dd9dc69018adfa7b020a413cd529cf106b58d98ec318521ce197fb2b7239320ccb288e0e45513fc8ab83c6112e0edf7165aafce28b4fa701732e32ff359764b23fbf688e731d2f1ad29942da75a4260120f96b2fe6048a3a1972b74e818656e6d9acefec258f279cf0a82c57f5514ff784f790ab074b83d960701731c1628618552cf1fb7d2a756dd4fe00e9400ddef9a75820c7f1be8587830da18fbfbf50bca17d251a30374193953c0a98a4162979e995bbc3e13b6fa297f3dff977a5766e84a08fb04b4a1c0358dbc8e13353a191204f1e06d0040f8cd9d07cd61d58cd96255a723874e074e9691ac9e70c036be578940baf1714b00f37466ee73e8743df1cb9e014eac3391c3507a17fe82147d7929b2d97a6dc4d03717b5160ed0ffa9182d492ad9c45ff1b608cc4c080b4bb918661da9b05080a7422b5b493e23bcd158c61831756980b20a936b7f4879d80c6bb48d8c82b4e076edc5ee197612f750b3db9cf4d3cfa6c96de127a0cd1c88167f182a1d2e9fc29eb0ba13416c4785332b250778555e7eb9364fc6e383b5298d5121d3a5e167f68d38e3dc98060f5a176d1169034c1c61f44e8ec782a24bf0626c1175451768d89d9a4402e5c83b1bbb44f9eec017ba9d99a60f10a9da0f4f905462da7dea16cf36da53b0082bc56c173bf2baa55c43f85fa9c2e9ce72865ab6968d5244058c5b69fa17e0127218b642017a61a2049d27093799d09653d69541e824ac485d626d4788df1837de1cca46f38058f5c95ea6044e894acc58cf8bdfbdc0c88653fa426a80610181831da732575ee12d1eaba4de1d244b90bd5c00ace45007571fae7209c589b6c360cc2eb0e308d157a263fb0e8a15aa8f84fc7903b74768fadfa6e1044cd512806c83c41616985e859a2369c40a8168e83f6be7d4020480e699ad6422d8ff1b8f456fc12e3fb34635d62d14470eadca1a7b086a7b907bb3bc9dc0232ac3e6ba5e30e8d7060698f6f163e521239be0408d7f247305695200b99c0cbb12dd0d7ff77a78046a55065fc27607c018fbbb33f585688c012de733622cb5364478e29ba3b3e3094fce05a2c1458a3e281d65cb3ae055c408b404f261e751e4d994823d02d3639388e0afdeffe10f0de77f00653732ff6b2c1babfb2e164a088d161e8d78e757f74d7385fee1a96a15891e36494b73e21c0fb4317ab1c348e1558adefe3c3fcb3ac5148941f6e8a20c4fe5b105e7e298dec87eaf5df29166cf50bd2df0a2011d62ddca0405faed3e79055ee576f0cd2166e3a6b5c3f374717092277c10aa77e4a0a5f94f96e74cd270bdbf0111a2f0259e34308948862c1ee3a9f4518297aed3c1a3bb2e9d60582c928982bcb2060c0414dc1a99ba0a399b04339c5c8c5c8bc6123ac4a89a917bb44b94b56fc16a2da2085dffeeee694abab49d63c61fb33149c58a855d2e7ed9a5b37c41a177e6d158b64698a7cd1daf5fd165855e2bcab641a5b1dd03baa42f19546eb5838083106fd76762fa4125b1662e14a2d571b3232469b2996761bfa84e306adef592188f088134c5d4d8a429d69a068aad1204334df458bbf4a8b71d13d3496d000f2ced5c2c039bf29e2c575e42a998a8b13c0a61a8bc5957f486ea7ab380f9af19fe01ed769418a95e0833852a7358ca908d08c1c6c11f926796da0600cab55286f0e20b099ffbcc167056b3907216b7cf062d9b2441da372024a0e272a6572e25a2ec1e9068a7819362340d30736d756b68679f0dd2cf4c2d935fcd0e2d68651397f68340a62bb5926a9dcd93af953f1b3daaa14546a9f02310097b42e0805027b68d1f2e8a6385c025910d4785d3369ac271bd608d28c2c00e0e61a87de56019cf0ff2c80f2b4b05406f99c65d2afe0752fb7fc460532e0681e506802198fc7801bbf823222995d6708b71f7d52884e4e7eb92c069f11a740c500b03ff809f1e7aad8be2a64ba74d86d8296423d639698e447e396fcf5f24f07e8c3810918c660d4a298735a58f4a04fa4bd6664295594b275cd905c2e29b4fb560f8e60c13db37500ec789c073696aa606506bda6c696af75c6fd907c522ace95059b3d0c7c996e8ede17bab0684a02cbf8d57f93c57fe553e6f45e619743d0fca17172ec54b89d4a95fc900a29f37f5dc7c6cd53f84afdda0cfe7557dbdef9e29242975d374b1a4d6321c07dc1d23bb76bdd042afcdda0689117bab106df4a2be0afd0ef6b6cddc1c0fd8805df6e265ee1245a716677bb6b8060ff9971d9cc1456dbc794d64e67b5e23ef20114a6e101b004afbd8c245493ef3230fbe34971b261279a0c867b4b58d0e20850a651e93db758ac880490e424780718341742db64e433d6e12de79a67b57f032bfa1a53ecff1b7f50acbb18a045b9b72a2526dd68c5a43700defc0495b554c8b785a59903ea2c0ae9aca8bcd1a815ee2779090e19a600be9a225c37a44232640511eec98a0bd5e34033d7fa8e3849c61a37bfd71df046bd579ad93b06ebb8ff5b6760d00ffc5d9269560de3a01ae08814e23f02f9aa05d7ea0d230047a5cbf9924912e00371903249ae8e46a046cf6884f5c747ddc2b8a97850a305c294c2c28524bcfac2ab9d594a103e782f1ea42670cda30d0d910f151e997d220f892474cb51cb357a1e3d5f94318a8849f0d04465ce891a18d88bed119e1ca1f49e6d04b19d72ab6329ea11e88da85ab4619ff6dc121922c5c051dbeccb45e01d9b60e350182508e3be1fcafae77236708d26e7989027075414ea41bb856fb161ac0b08f678593bea548411100b73fb8b34b0700d6672f3d690f8b43ec33c9a303ead9fb2cb8da22c66f3416b7c56da0493f50ad1f938499a7a3c2c69ca0b149ed422763a21b90e59c9b2832de220cbfe5b32b6929a3120a78c62d5eccdb28442b3290ff4ca01ee2cabceb41503437caeadec9f7d4e2e72321f1cb67b850985776f7b7b3439e3516124c0c0ccab4f7034171bee1f2669215c8850a478040cf810b48c94ef031564bbf6aba85fd5369c017cdb03cac97a8e5d3052b29a0e696555f0305b32b4f52691980897b46141d51a45760e3e10cae6154bd9b5a2cac821475f2cfb57ae1b80aabbfaa13f7cec79c000e400122a3943edcf04b210c7fae1fae50fe571ba7595b76e24a4edbdf7967b6f995292018c084f099208394db3fd8fa639fdf63860be69b6edc1704689da7fe228a5de77dfe964fabe5308da919ac06a0abbafdd473dda7174eb81438df551a697a993298469917b54f82d7229eeb913c7a1b8130ac5711cc7711cc771dc09c571a71c0ef51cc771dc736fa369b4e7fe14ce2c51274a8542a950a84fa150a9140c678930900604154de69cb3893addddbd2710e6cf4ccace3219b20da5275b641873b67d3327a82307c5e48dc562b18cd2582cc6414149b1296cf988a3b43863da1f713f39cb4751184637af47b01929339f8428b5fbb13279cd67a2a62962a32ec4f1c0afa9e65b5359250705057d4ee96c710631b9a143a5b32fa78d728ad2fc2ca8c5f93332d4ecc5d9560a91322aa8bd94450a26d4cbdcb58d8e54478b994d9665df94716c32cf085f36808cc9fe892a45674f0214a25432c29322e0a0ce16d99b9c1449bce73c0ddcc139e7d1908570488b243c2119e42c6b7b6eb39b7da145ee678bdc7b34e4c1da9e089f304665f9e0d79e5ffbee69d8214e8bf3b9108516e777dbb659f9fdfcd0a6c5e9e1f65e486dbca6d6ba5a6d36f365082ba89c4dd370cfdc093ba8dcfb3373ec04e42fb2badb0e7ed0d6fbb538c9c0e2a11d4149e5bed69cde64e335272b647a2cccb8ea68c36fa30307050e75b43861733e51b3d186d3c29bc1a1b6f7b469668b9e15a18bfab5d83d4ecf2451bb5f358de73df5dedf39f6b8309bd4f33a4abd90b323edc291c7e776dcd785da7f9c46e736b56c4e275f380f79e5b30860d47ee6e1fddce375e6593777cf649ee2b95059dd8cb3af63401260f37dce6c06893a3fcb6466cee69c261ce6dca4c652667ad291942b918ea0cc5c8974c481fbc32dcd6971ca186b3522ebfc6071cef92e7a0d9d1e23654ae055db49bf1da29499fe3d7f0879c1edd7223da2faffe0d1ff9a863bd597efd57bc7d3a35e526a454b59a6fa3f9a66b4e1b81abce8e3f4885dfa2ae40849baf48bbc304a2b54ee171b0ae38e928c4bdf5439978ea6d96eb874ee1061897a5da1405b72280e986f794abf86334475b6485f7e733f9344e5acf4baaefbcff4a83006d4a7382e857a930965b9f0840a6b7d1ce7c213aa86dfa34e9fa903bbcfebfa8431aa9f60a825c2401b0d9e14e18bca3a40a5d2fd6b6f2f2f33114db32c1f623f4c28f6f713d1acd8a2bbd83430aeb9e6da08d3a2cf145c7befff6e5bcf6cf096aebf37e78c4999d9465ee32da09ede4f072af298f913c99ddbec3066eccea43bada549455e43953cc65fe993c655ece88e1a75ed9574fd1dc8bd025d9f5a542c2d6e626c4b49d719f037b35a10e77a5df76063b8cfd7809a6649d3f052a685d434ed5d93493276b10f19622c699a268fb4af41fd89649aa5a1154dd37ec3f1188d66210de5bb94526696dae958a078b2a70d92d820e888db4856946edb237d2bb0ba4756d702f4bab0650982cfe5ef6136e24918f9ec65eea00ff96d89c8efe7e73259e4bbf2a5fcf1412b462df2ddcfc3f1b32c1ffcdff37f7c3beeb5af208f6e7eff5e64ecefacf735941dc3d9b1c887e35dc877a35efdecf83df738fd8563fff7331c3b06c8ff5e7acd7bf5e7bfa95ae9e1f8f71de9c2229f7b362cf25dce12912f6ff611e997cf3d87a3e9f90bc779bf09fe7c3094ee85da7fe1f83d5b2e2cf211f15e5e3bee5cefbb9fe158bfef7ef333fde904ce3b43fa9371bc0b89b8b0c38523b5458edcb6459c48bfbc0dce67d0877759d3fecae5f3cb8be2d56fcacf9146d0e2c703000ffed932dbdd76e882e4246f7e4b8bcb7eb411b76db56423058725773e0a2ae830b9f3596861d2d01a2595a21feef792924313f3372d93527258725facecbbef69d1909569596824873e6777a86dc0cb560f8f99385d80f952ea98b1385a143b50c51667bb1849e416820df5b3ff11731e595bcd4879caf1439ad0dba665a9fc6ce9008a6a8ffc7e4c05f0cf9f96e7375bd6f37bae420f6bda14acd822a5b5665996655996653fb3969c79a6993e1c8093ca3f6157bb47e6f395a00b31f7c8b4ac14aeb4e3062edbb97471da1b4093eac4455bdcc7c0595a1c8ea6c1d1a2f81ffba2ce1f59dbcbdf6c0ae2952217ca8e61249e4905523afb161ed20a7e70258d2b6158145d7eefc44935bb1286c51197bf45d1bd464a97270bcc3bad942ebfa58c1c8015e1c8502e8ef312356e65688199c2e9caf92c1fdd9dd685d39532cb1dfdbdee02bcc0e31a547e89f208a003ff1175b419eb6d86224a93db5d337dfa4f903a8809d5d4f09c3394ef196dd1e77e0b5db4b5cd60d3da32fb637b79736a8b6a5a669d50f9388ed314693681b4022c3063b774fde5f3ebc81bd5f37351bbe44deaf95b49dea09edf8de44d7dfe09246f4e9f492baebfc6435cff4d86eb4f9bcaf5e7dc88ebdf79556e87dd35bafe4aa415da163cc4c6840c4b9a0af5c28df03cf63ad336ca75de37ff149abe86a74785150c53cf57662fade0215a86a6e246cc0ecc2ad708b5fda829c92afd51db423b713f6e4c6caab0e54ddd8f74c9f681a1ea4d21e8fd48bda09f29fcbe1f39286e4bd86f0abd0bfed885e0fa7bd4d412aa5221a3c2ae612b4919fe53e846520648ca30cb2b98080e8c5dc595b8fc5a384e1c2e7fc6ddd217833781ae7cf9f2e59b86300d2184a76d94a3492317b54bc98d26d09599691bdd6851bb94dc6802cd4cdbb44d0b472e6a97921b69d995492317b54b299b59bb7c94495ce4dfdd2d934c26a8fc2ca5eca14ca110010043210cd918620dd518a231b41a9a3104800f87564333865e865c865a865443a11d520da586504375e8346447183a0d9986c0a16f680498a16fc81bea86600230d40d7143012061881b22e1c6d00dd13fef25888888888888888888888888888888888888888888888888888888888888888888888888a823a1a39bc6511730b87d66da46b9cefb40d3a9a252aa169797192b1a35583642f86040338c5e945e5c2e452d492d3e2aa115d0ed67cd30bafd355e946e3f8d17d7ed5fb914ddfe192d49b7ffa5c5e7f6bb84200200502008f419794a9eab2b02816ebf4b8bca73ddfe140a005fb924ce870a6d310d4bdb6b76e7494e4c10eea9dd0941881ac080f9b4b4274c5168b163346cfd47594446117190d8b4e86c9d68df822f2dad64942509eb21c123ae9ad9991b55c4b6284b6200410e3f3191524a6770c0449b1e2a34b189f90471e70cfc9bc6943a9fa5d2ea13dd6da48cc348191b794323c0f206bc1ee435fe2f788d6cf71fe235eebeb10b7ccadafc6736cb7a80e94fdba3ecce93cd9aecca63fcabed696d566e1b0eb14517025aeb3eae9383541b464894978ea0136eb76f7f0aa91542453b31fdcadf4dab51bcfee09116fda765ff1b2da8ec750784283df9b3710b27534a659531ad49b9692af45cb7367382a08e3296f33f94c664c8e256f1e60a89ba6aa1f5252083298319130329a5ec7e0923a594b2816c49d9154961dca00a3fcd342c32987f84b128da5c2e97cbe5126f5b230c050d8eb85ba6e4359b92d256a4c45b726666f6ca2b3781a41e338f8eb2f67939d1640c674a734e6627aa441a8305575bd27ee049a5cb73ced95736cdf48a8a9a467e933be2b8382ed32beae8195d7e0f055e1425640e294d683ba22e94a681358d91bce9f7a6d8b8fca3270564c011bef38bb89452caefb04a19edc32c09256bb8ff30a4410375476a823bc65cafc1066c2dcd528fe14c29aba294f9e072160677a5949af594944a8095002b015602ac045809b0126025c04a8095002b015602ace872f794379037f3399437bb226f62f3c6133583654af28659f3a5150cc89bece5cdbcfc994bde7cdc4f0d6bd8d2227386e58a5744028f364d330c03414a29e9caddc5517eb7c4c16366e613e55876b7381d6c40b79666ba11c0850bb8d062298b152c4d2c5c6860689b155458ca0c443e448981061aa2643c60917151830c05294afc64b1e1099629b61fc0c8015b8161a67b0241348bbc10d0ca51281728e0b86842b9a022e3c205d904620a2f03238bacc7072a84e8c187255b94e0078c1780714402a21b5e89e4450c5f40b9235c89d485d2f5a427bf0ec7225286805d035c296588d805c375c766728f9a6674fe024b37cc873b7efc05933b764c227961749979b26250c786b11b79a89c13486951def148f60b909f3d4ef791ed28fd92d6c9f6fc30189ec8df6c1fb5d8a48e0d9332c607bd5d83145d54b93b6e9196a5e6247e6666666666a0531395a54f663908a845661f76f11266a6462c5df963bd31a08944c611920e5c62f0e0eba4fbda71d45d3dce097b22f3717a34a59e1743c18790cb8f8342d3643fada6254952471413cd159381883b7a4ab11d2a8a49d3d49846b29f5eccab42de645eac1ac91b0fe66778e3893a6a2ecd47deb0955b45de682ffed4513c6166f49474d8bc6ac09a90bbcb9226540474998db68841390abaacc431b4464dcae5514bba9cf9209561c41d352b97df5bce1a55d4ece7084e540d887ffc64365b727243893a7ee69232ccd90c7dae7c8f3127d1361de8f6ca61cab04de182d88c0b4658024aa24d42d0fce901481a35d84de21b6b19ac83cd0074a0ced8cc88ab246f6a9908e31c6d63a409310140d163d4714614ff57ee3e33c3592ecb47dff963cf9d7dbb3d32ba4872b44317afc3360108b2f93a2b77004eb069dd577f98293e8b1894a6991ff39a2ce44df699f7a836d3e60b9ba7f2666a3f330f649a09d8b92b4bda0665a32428610eb5695a4c73c157ee45f03e59c6f08b9b56df6b366b6359a0d96e881abbfedefe028355cd6c9d3c50b905c60aeeca842b91c008baa92b916e40a573609feb9dbea6b1c0bc449ede163c861f8b902b3f92268ec7c026900a8401c30e57109145113ab4a69df118e6e1e274875b0f777bdd51e4e18e3624b8a33c1ac11d651213de81936210424a1639b8a2a4498b45706f96aa6831e4f304890c5a38308ac20758f8200822b0d2f3430310c6e8418a222a825a3540e8e0c312448ca00620b4d80544f460081c7491430c2d1e1e48c28a2cb2c8e1035fb4f85bf09a1e117c11461838c4e0c39418b4d8e7e23416660eaaf54aa432c240c5a07a572295b185d8930407604e74d0440992e8c295946103a432762863063bcc74e300b5655d1481bad9af6698f0608c20cd23011745145b4c27537ea1c4fc8292583167d18a789144166464b1810729e60f3c7cd151bc4860daba48c15d39b9de95485dc0600539405899428626578881d4e2312e7ff58107083e8872858907964832b7608018485481c48b1b7c00c591bb945284c868e04d989322274ba8c0490a7838e226ec8e6fc512139933b919d252d1cdb2226c4005131a6a40c611adec67b2a3ef4aa4a5264b474820dd400ad2952529406471747158ba6c8f385f0348199628782d75500450085a1dae646851a1c40743ad0e3b0aa5961541908249ab4376c152cbf3af435ea2c9cf1358aeb436508b5ab20b40020d5a1eee300c576479b5367012620c201808b53a9c01446b03cd6c82132ca1e2c7a88a131c5d015c59051244978a250deed06f024b13455538e1bab20a2682aecd955540c1e232b86366a8ca9bcd7c331ca8db8fd46bb865a30b3d8ea8c5ce858d294b37d519ee7774cfdd739ded01ce04519d1a99775621c6954852acc828ae4492c2e44a49c20232ae4462c1177dc395485250b99e0477cc40a9fdde69a689da75ced9699ad6bd2ad5696057b3fa2daaaf55a57a0f532a29532a55980a478a7a9cf66056363efaa9906ede076a4534efc1702c02a6de6b2a1c850c69e108fb7012a0251cc4fc532487ca979542a6d36251aabb2872f8ab73ce79026f064a33b3c7c07d4729f7b2e33ecb38cb3d0d353bd28d861ab785fe9ce6194ff6e624bc19266650506597235b6c4e8bf26788a8fd3c54b03dcccc842745d0810861d4e92981dffc0354291e7f2a306c26fd6ab149d841dbd3efd7b0784dc3aaf7ab617efa694fdda7fa0edcb1316f73e3d197b31d2465b2ffe9ccce1ff2e02c8b7b22db77cf6ddffdf6ddd3f7a647b790a1340db749b6e95d9e939a86ba84e1d7623682925adfcb3edab0d477100ad6341ceab90c76b3902f43a9b54deed1902f2fc9763014207f5508a2c21a8e4ce56656282739a8c5cc04f2e0db826753eb66d362466d084cd4b183725acc42a634a34e5ee817595d16f7dc73f68516a975e2fad6cb27e298f1605acc1e4a07bd843fb20b30c3b79ed868315bb560d36266bfc5ec475052b95932d0f6933385a2cc32abe306794cf6dd423763207eef9b3d6f3c2343c561cb4b8042067a42136b076d38743ddcecb9ece9c60348ca64afd909a4846a5519de8c13352505914d85a2fafbbbbc19a3cac476327d05bf10a6c5ed4fe1b7b8d5ed37703b3deb034fdf77dab66ddbb66ddbb6ed3ff0b4fdb66d2730ab90c52f2f7ffa20ab47adfeb47a9e4a43b666cc9841e34f34683c8fe967bc6c799d52a95429d4a764ab2564b14bc862cb02e2f2ac0fd2f2362ccfe95b4edff23ca677f9907d50c0d1d182108fe917e93d4ee01c0648ca71822a94ad2d94ab1b2fa8f251f764fabafbc2e88858d2142c4c84bc49bd3f17c139c0778f364dd734b1a671124208efcf5ee39dc63beb475eea0ebaaa1f394a507dffba45ed6be35bde6f7051abcbcb4bc832bde812b24cd6488ecbff8e8b8be862a9a35a6ccc085f9e46e8f2441d442394ad55285b3542d9ea58a16cc1b82a0d9db43c2bfc99e15b362c8bbe8d57bdeb5b2d9605c4c6ab9e456d101baf62056979976f7997ef42560addd3ef2ccb47f7a63719dd9e4b717ea8356e6c51472eba2fcff25821abfb212f21abb346725e9e25846577745e965e5eb65a7e94575e4c2f5b367e9449acb0c74bccc6b7fc288f4cdf461ed3451ee3cf7a7779f76f096d84a0f7acb0a3b490aaa51439717d4bf50d3a51bd296ca316ed5b888bba49d37cefdfaf3692d234dc8ff4c3958ca99f0aa59441594a654c7d11c2da12c2015a7eec28d755ef36ac9431d5ce163b6422a48c3f1872116c82bf6774c4523816f29490b1b884dc3e2dbb002fe18c306807b3528b8b5eebb3d3a2c4724d3db54f3b70f6d9fbece7f83dbbf3036f77774f73017592768e51a9dd1d79495e11a244856349ce31777f77f9ab973ad6492d1eb54b08c6519aa69fd25add4fd841eda7e08e6cb372bd8f8c64cbbbe70fe2fd6779b8f79e2d0fd746a0e5e96cae5552c75e6a2cdec3ee3cc9e19e5f3a933181cc3ae159794babe341674551c8636ed02e9fefdf3790342c8514fddd5d43a40c1fb15e55c80a37aa74ec7ba2f1a6c50f3c1f9238cd39e79cf3e8ce282db67d20ead84b37f673ce296fb23bbfb178cdf6f35570e5256f64d08e5ed2e2fc49a5fabc0c760fefe00e233c7be9cecf93a86310b285669dabf9dd83a4612412266fac3ce8236fd847cacc67bdea9c7fa30accf4a63a14f143b34d6ebe369f88e69d77de69d4bfb3237dee3dcacddf348e736d9b76a66956f8a1538f70bca6dfc1243e7dba0e758927618e60362c2f78bd86e7c97c1ecec66b78bc0f61441610eefba7cdf1de0b59f3bb972d1610ef3b4bedcc7c66ce2ccbb22ccbb22ccb7cce647f42c6d3bdf75cc803fe479ffb0774effd939ceebdff421ed6fc69698b598d16549816b31b59d47ee7e8953099f71c438beaaf428fccdd516851d2d954a06c3ff841a98a0a68baabefc842ddee736699b685a30325b9feee3ed71fa7b15c31c6c6d2626c5a97cdeea86645de4b2b170315751552ca5491ec1b7415d957b8bf94adc47f714786b5507604ee68262dfa1220d74fffb4e89b06661374f14b289cd72fc3e48d56b342c73c216b68c8187f2b56a8aca4701c0a45834618c6c40c6000e34aa7693ed64fcde60d3af943c1d0366508e726b1169a869bbc421c3a2e73fdf98885fcd583bce99e3e4c863d5aded01aee814be2170f8f8569b1beea7950aae767d11cd5d7e71086456d9094951e1344657ba0705afea007b125ce3c5cfff1c6a51f00998347204df0a7e34af5f461e44df7f45545445ac45362f3d79b9fd6c2d28b72a6f79c9a787c3ebea7f65b3cbd04a965f9009f3e0ff0a9859132a7efb912b445c46beab938eddab3f660f8d96f7189bce9ac28657c690b75844eeaab5a2d04fcba22e563b221238a2266afd1f7329a651cc759aa6594665ae6a2ce4f0c062486aa0d9e8499daa5b4d6d5ea5ff41feecc92a28efc4d69f5157d4eecaafca1e3306d8a07f21898166db21f436090aa18eac069d13950ad402da960d77778567ca989d0cb7b93e7fd0e683d0b5af93dde33f83dad530d3949c9037fdbde6b3ee2d52fced1aeeb5d17f27b5e6beaab8ab658548bdda996c110279c091964010141d483bfd99c54eaf9c1fa29bb63faca33a8b1ded4839f937ab07ecaeea41eb4f5bf4d9f837a93dd79b2fd4e0eea4f76c7f428fb1ec3dab655157faba95052ef5bca781eb70311e07abb907b90a854abf5ff5a3b284d9345c4122e757de576cfc99a56f218ff4ede7cdf7545dea3211bd550998f78710e4a656b1857f52c5f5cfeee3ded634679a067e977b2c5629b7a9efae00749f198648b819c1ef5414e8fb23c4f78507ffa93e551594edade3385dbb631802d43798ffaa99e4e15e5a9dec4d3f2a8f74c9fa37a53cba36cf518efa9d7981ef55efdd37b3f519f637a54fd93951ee3f13cd99e07f5e0bfd7a42ccfe953ef7d05423df839a8072dcf137e1ef0eb6f36e7f429cb63fa14f8f573c0917d4e21ea73c04759b639a64fd9f718efbd1ab2f85bf018676b2407f5a76f806c9dec0ecabae947b984b231709616f83f4ec84195adae05bee94719e3e6d3d0e5665fd84ade67f1de73cffbcefb2c2b85efb7e7f159d962b779e1f30ecebae9d2bb85b2452e4a6a291da5a1f8b7d27ca9605db35c40af777677679feeee3c9e70426c86a00edca014f36122880e06c311d2a2afa0e3ff4410584148d36cefcfc20b3b0e903974b0bce14f7dcbfb0bc3aefbeabacc780f47caf8f70eed99f954bfbea70a55cf852c660159bdea59281b64f52a56101a9f7a1a9f7a062dcb073fea5176cc21e8a29ebfe7ae6aa85266a49799023b5ce0cb5246cab40f19f20225713d514769d447b4e87f638af3d1e52b5ec3029ff5b2e5bf62a12c0b088d5f7d101abfb23c4f725a7ef53c2e4f23c8ea693c0dcbd3f22bb98341cb02b2fa1a1f64f52f4fe36b589e27392f4fc3f295190fbe6c8176646e29c376a4389cc3c60e75e4239d99f1a59429d2627ffbc8733f6b3373615cf573f04f21117ef03d3ea14e28cb4a01f5dff3409d4ebffd47ff14d2e721fc853352a677c217581012aed0a2ff4bc82d433cc67f86bf4b58398703a409feb09922ff71866cb97054e7867ae305b54f6dd24288263118bc18c2c51d3a3a4d6384190552c69f9558c1dfbf5126b90ef30b6af6938d96660b5e63a32365fc47c8a2b28ebc01e9bbf3704fbfc3c072117025d292d26590e973cfa3fdf63cf4b9ef6701d17efb20f4b92001a384dd7e1d262220a020825857c67e902855b941889b99dd9dbd9999dbfd496841f59f25eef8fe2e0591183538199a82450888b06202c14f9325ae2412883354fe04c06e58622951295dad64d822882bbc0cd78fae2d65d4199d76eff6f6aad3fd23479bfe43c7997f056666f618121c6a600195296a0002193310d5d0edaef9412f17d0962d61116349de689b65659ce536cbf324a70bb2bdf79ee5e9a86565cfb1329bc35956f6decb1665e55856667f80ff8daca4d44b617b3e4a4da5452a494b49fd5aeaeb53823eb25fb58fff118d2529293119e231a1062eb7b88dc14b536249536249928695827c66cbe230a6d4e26aa9086777e728eeeebc5df95ef6bd206ffce2c001245c0efd9c0d86c120ff424d42637ee4622cb1184bbce49237d9f5d5aa56d91b57f1b92357f14972446b6cc112c67603b19bc69dabd95f016db16d99c675db779a16ea6cdd6f1fa4fbadfb20db77dd735d8ba34fd449b7c93eec3ae60f691a239dbdf6b4e648c7789126e2b9834fb4f7b7e95ea7ed90ee79e87bcfc37df71e6d30fb2dd4e9bca7cfd379f48374cfb18050cf769d97fdb86a75d96756c80956477965c80a4220206f7248193780b491328e139bcc3ed916937a30467582e11435fb17e44d90ed6d3c66be2065e6bbad5f92981520ce01720ef0ca222264cc9d4adcc0a24eff1584d8101ac97e7b4fd3b42903d01290367907bb8ab8082907b1eb2faf44c201952baea435f294eb0c03c281137766cd6dd23eca0a2d8485169d7b2eac1163202b5a0b90f01c9d12aeff4a0595f2ed10fc3c87ca98f71dca98cd0f9da661e6246a77dff7fbbef73ccff3bccffba2d4e64cba49c6187cede50f863f3e9d2ee70747639bb5d144f4002de26000ebd1afee41c6f8cf24a1d7bccede9f8a94ee782a52ba1c0da9ff40bf5fac201f820d402c79f9b4a865fdd879eae2167d11a078b5a8e5119f7b8900c56b65397776b9f6ce9b1d5989eb594bc9d334f25ccdb251df1f2ab4a809e9f0699ad1a67718d9a48f8f90ebc448e40df85e6146e3ca6a6fd3344636f797f72aa5aa5e5ef5d27d5e54fff2309c93a3fa97974152dfb2f324a7e55dfe5f5a2e2d76e5314eedd88de2453dea74f2b28a329950a8aaf929ecba37852e70960b5ad1498b9123552729298701a4092d214e0f1d4da3230457a0944e4d8100e595ba32f653451295cff5a69f0d42af6e4fc6c0c8582d168fe0446d2eec578d586d20a75247bec27c83862aa5c0c8e8a67179554a8d995248316ae980a235aeae94af57d3b8cdbb13d5356f2151499d9ef68daff99ccd9a8915a05db6fcca6cc3663618781e9dd763c1dd9d5d73ce8c0577f7eefe4b57dd3dca2a57feecec93215f498548991f493833994d77264a29a50784840c3948c256ae58e1176df0d89b241851fb4a0de4a1dd2b4930a24ecf8604232a07a6c064b4e8bf428bce821029557a8cc38e623e499e1375082bdd982b1ec73ee897ee5a665150a765a0249ca4ba0d7c7c5c41948088263e33c84149cc87491042fcc466f8b9f42a55b9e14a0c53402005cb0f42323683d01311c911ccd9a7bb3bf38f33bf83a3e006a30dc9932ae98d2054f92a48d85512848249f9d36b3679074b37a2044e83d9b325c559cd397facf3ebcc7efefcf7328d7fa56573f66987098392a3eeee963ddbbbe5d10a5f8194661340421f9062e5bb32f613851b2d39fb747767a551c68ac086e0f44072b4431de95dfa6187236275d582b35ab5d4bafaff5fd5dab2aaab1e28bca0ca8fc9e0630369a565cb997ed952f64b29abacb2ca2a5b66724a9b99aab3423777650c86cf0475a4374b42c58f0c3d7032650909194e6000f4ac2376b7fceeffa1c3cdddf3b39c1659fe8f9ca6c97eb6c5d122c7729891d0d0dc6c547190446b0112f4d332ee02dba4fe993481be30411f9ed14ccb00e538eb825f6a67b665feb20c4fc27c5fe62d3ad40c5c0048810bfaf0cfc7bcdc7bd3c7f4f1f1ae3f274df88e6499c6fd117a3929e34fe7530bf4e5beeb2c9532dc77811b4e39a7f7907af5cc8c28babb3b9617b214502a28b5848b52400d545ff0712354910b469886896024c6b82db0119246caa671418afed3d259b5d44b0732901071c715123478384d5b9ad34da31f13c240d2888129973110bb7cc4e7f2e7b3f5b66dbf6d46476020e9aebca8a356d461114de8d22fc9f5ff9268459a116d752d7e1eeec8755c96db356e50f9f329a209f977e1d692600a1c63f1cbbb62f1d396ba04181f100562b2eb675a16a3c57ea2e9e235a7ffe1927d8c9895947e64185f39c9eb12cad610d49bc2963fa97e86ac14e67f3f2dcbc77cee3996ecb91f98d3352c202e9f7ad3b3829cdef4a737d99f27dbcff02d132bb3415c3ef52e9fb23fae6f997e866f81ed436f6c51976eeaf4f3673ca6bfa7950a59f3c5eebced699d52dccb964bcae54f3f4f3aef65c677eafb888b58889bb4f8422271fcb4e86225a32493e5241dd3ff635ab75e8fd75c19454c61aefde5cf77cbec2f2d0eb1456efcabe110c5995fad347b24b3d1e2af7cc55d7f5173eb813a6d5d8dae69dad3a6d934d99aa8d54f6bbad5761b30a8f6678c3bda8844318ec9eb7a1f4569299cf5e6e01d1936bfbb7dfc328271afd7ebf57abd8296bc5c89a90051f92565fc25f48225358c5ee77ae98af6ede2f73e08fdcf7aeddaac6c6d766c2013f8e3071603d62fb86701e1a79fc3d47a51e9f3e750b6d2637260c0145aa8411fdd84b5b2d1a2376cf5633fe5fa7a776498a68494f16fb19590341c0229ca9b2d49fba057cdec0c0e9b2ae22b6b2f0cd4a99a5a5c5ebe47f53d206873523ba84ff57cafb23b4f3e9ba3fa17bb737ad58ee9533d52f5a770c6d730f5a8f0e55b5a5a567fb23b3bf55bbea7c7f4392e6f7a7e138d3fd99d1dd3bb7c8f29b4f1a790f5350ce151e18c9f31e37b5a21a45ef53929d5cbcfb03ba87ff99dca0a59acfa19cf6c73663ccbee9c7ec6ef985ef53d335e5c5a54a9daf3b53783275fc2e0589b9ba3bf87015a587dd3f8962f32dcbc915950d4b16d1a9593c494798748994ef21ad6f722bc6cf5cb8ef5416cb09ea7be8d20acb7c1b2b2d5b9c0b7fb2c0b08eb43f820365e041b1f820dcb491ed3cf637a96952dee25e8a3f90a12d5b35c242d13dd98d2df492965b6a298a8c42d56653d0b15918c04000000b314002020100c860322a1603020d8f3bcfb14800b82a64a744a9909a420c86118a59031c410600000000066604884a615c25470e8f010f189065bf4445d10b8b739b138fbc05893b52c3095e2ea83e6a8647a56bd77012bd51e3b6c9f3887742f8b20ee74a76fde9910832823f95d470083776d74d1bd868c54c9c931ef85466134463bcc318b876871ccd7dea7e1ac032819e1b65b597bafe9c1d59d278e2a2d962bdb15a405530967cf3788e411c9780ff2ea057afad6521295ea5e62226e38d4634c9ce8f25a5cf3ade504689716624e9772a0676b9c0254a8c6db688f243670f17d23c5e006bd59cb78d6aa32c1d8d7f28308082f6cb598bd412f270ae9ee8d8e7a3601dd6d39c61ce0fc640777b7fc3d6096209dc61c80a4bd13f86b5a6ebd987cd1b3bd8d7d18bb2fe8f56fa2f100f29f911bb2b7890035a7540654e02615f73010fe565000ea747ba3c6bdabd1af619f341064f88b497dac6a530156e1cc6534bc108dd2eda7788727cbeca858af8d6c3966aacbff080424d8e00850b128dd61a37933eb3d51f210b08ce82b80ae80016c850721253bf628f95803f48933683fa1fc9900b81b074db6b0b176751690b1b8ba6cafa7193b6dc39c86468d4cce4186041cb5cdf928754d5eb216483e0ac7b95c90b0a5d00095bea17056a4b211666bd557d56ff501fc7be05d8a62b6a69697a595c08b65bd3cb0044f378c103c4bc3ffe38cc5dc561796bd6db78d860d958192d0fd0af14302ec503b9dece29b40976330544f683355a455240d850342bd0457e6e538534ed3847c015ba04279aae07215ea38b21ef56cbedc145432396aec996804b067a49ebd213d5caff4593cb47fcb90821aa03f70d640e49b49ffffb09c40bc4f98844882bfc1218b12652d06f314d962aace0abc10cdf4c7b2ab6fdda9d783b6c0f87cc4ff7b8c111d7c3ab0c749ace3439196178b4f6c53cac2c01e1a6e08892a2acc6e9f025e0b4e21c29037f9ca3f186af1ae9ad928e321dd99bd7e725207062995f4c83a19ee95b2b5f9e8f16e4199700408646e3261482c4a73632330f60e79a39b2701c9c7c0cb7a0a70fa2e7ab31f7bd461083991336428b388419f1b4c21afa2775a3e3699a79ff8c2d4a305b83222d77af91e09de4c2a8b3886985c8be4d4a9a17146c2396f1a930cdd24324e9f5ea19d5f83f3f480f32888066e592d3ac26a40ff2852b61b29b6643f15ef007388c703abc909389937e78a1743539db5848079b8f91554d6918454d911687b50dc4a3e0fc4f1800e285d35fdf80dfa0c8b5c59aac688b3d22b4545c028dcd4ccae874f91b1e3ae2e053f2250520dd8860ae4bbefa2f6506b56bf913ed293b6df6be9ae642c66c9525c1ea8679fe54f421e88e0d5cfcead63c83b00d615d2f7403e42c04a268a8f7f54d138422c6864506ea23f235601e69060eb09ef68314ec109fc0f55db122f023902932e23eb01f67c357ea380ee81ecbbd5bdfaf0a0b21f582108050c5456e894a862d53c380f6f74b5309e6da2f4f455783c9134a77acbb79b078fa1bd2165cb7165bf579996a8d86179330ded40142e9c57f20acf645a16e44dd5714284cf8967b55f2cd974b3c70dfce67b0581b1f79c89c204977da5fd025fa51a360be647336b9aaf3be20bc45712fd5feeb3f629358e96c78feaee0decb519b509ad53c8aae236751276eda5292d4b2a8a2b4960a790c6af067158226678789f94ebb00eb96963cb4404f1c94f640406d8db0b13bd75bcd4e6707adbd44a3da9fb430218747d045266a214a4f460687fff26e435273598468b5dc1a2afdc829622bae443ee2a39c8b6c65fb3b8b866317299f487e2dd9a7114f0c74ea2c70e1252751b4ca6478dabf167427e6a6f69cd66cd34bba19680604b962633aeb6791506c6749be6216ba7cfc690dc180383d8c00358b17bd542a40fc33529b08c21c15a0304af3641f487e339b397bf7ba8d9251c870fb4c8670d29d2e6ba05916fbb6dee3eb468794245767e9c2da92ba0288c2b4ddd7d91d0b466fadde43b577a06a937a8ae88ae55ffd5b74cba41aa30ca83a1b4f6d35cbb4cc3b0cf146a36d8a5dea9ef6a3805c23e51e8ba8ec03fdab878df20e5e9327b1321f805b5483468c997f19f2ec7906a553ef16b877710d588f982c4e2bb6d6b45737b37e2bb74fa75ac7bcf78a2ce301be4de6ca4c3c346549f8d8d4e3b49b3dccd8d57879cc57dc52d26d5739785fda8baef19064bb06f6404050183f64d425a1d8ad4e1a1f6433fdcdb669b754ff2325f23e3a8930abbef90c004680037b5004304fa85f9fe87e92374fd246b70ca76365024553f9f050ff9d4cef2b1f40e664cd1f84174cafcd457e5303a543005559a1866690800c8b00dff3f9935652ef9c607b059d2bbc07a108df83fb911a19c2c7648c3b27a048b9c468154789f8fa8fbf55fbaa1e2ac3f7c608eb7b5de4e9e555308f1e1a28f5c0225c6ee0e536df9fb1d59df865e8b0b951dc36880503444fb56b709776e493b8bee32c9159ba0f02f7a9f5c9c5b5907b0fdaf6afa911b44c1244b07a85f6f645fa4abf00fb2e3941f01ff19e82de520ca473ff215d694167fcb3f8d816bde32ae356b487526310db9f820e04bd94c380de06fd19d9bca85eb55dae48751d34ab6491bbd19d67feee46210248036cb1360627fcf03f541f345f0cbf8165646eb9862255751985c43241598853450860ffb255a4d55dbd519bcd9921bb8a434e7e6dabe30d75ba1c2c09dd1820bf64d18dd7c68d09fb0867df2d50514c671b030829848c1b00fe7a04592c8a36124868f28f0cfb05a9f25c2efb0001ada901e309e14ac063d209a7c51759cd01fa0c0e370b39652a3318f2482a2ab7c9b17b098fb453557c69a94e9605cd1e3727f4609aba3305e4e40504ea09e94d048f4cc81bd69a26673212a190463e659a28b5ee763be46fc1a9b8ccdeaaac917766460bdac12570734aba76d591c386523ffc21085c1bc4330265cd1829ca3c9a999cf1c382c4500c6e57ea54bd0d490aea47e4f5390cb753eda2564fef53368229c82bc12027fb95a190d8bb50a1d1ef897b587a3486f46322019fd719c0237cccc8c669d8b911df5e6552e0f2f6bea79cf9a4d4165af648c4cc7ff453126f2256721f612dcb4c74e9b96b089d98559673259f94319193bdc21599affc7085ce20bab22d473ccdda37e1671910dbcf228be46605aa8f3f9895c29a39554db93d17f0d0a9ee816100d156ba574c92378f146d21a18c2dd2fb2081c183c02c62047b8c446b10243d67366270445bd5c313c7713e9cf279d25fa53b39d5492c435c36d9c9d7e1900b245f222a4275b14e8c89b026c34ea479e33ac0a675f70c26737f21b540d72acc898a1c73f742cce5974322315693f09691986be793ac27b5237de69e678bcc4df255c1e9f4fadac31dad044dc1e6e8ed364874bf25d437e4293ab291a6d8c312692c8e464468d5b7574c8a3f4cf01811db3521b080bbb510b0666ab16bee1880ebae585366287f9751be12bb0828fdf88c2a3cef2564131f5c6cebc51a03d79cdf6dec8bad1370a71e16de23ccd4d79a040cb86bc2c98eecf84b3ed3f109eaf9a9bf73dba4e5a6e9be3ba2f3ee86eef5ce021a4a32258b7ccc55137ec469fa43c8ef77f914c04aeb9271b1a9b58479406d42225ba015b1b0a5bf6569345431a3a570ee6df5a602a2883f378bd8c7bf163c6f45d4ab0be84f08101634db614b01117f7de32f562b7cb49e0dfcece4c20cdb69f1e434784a911812cc32d51945f903b9e1cf9f4032cec695ebadcf52550ee3f17a8592a4fd80091faaa187631b5abe3e4b2a95377d6010613bb571f2a9603b9f4a28885b109b30a9034ea36f62c0b0d19b92440513f8a8c2c6f630c7d8a2b5c59dcfcd4693a9ad8cd6d0855ad055da9df449f0bb2079d3663bd7f987562481203c1cbf4242bf745ab03a6c7026abb975f5d9778352188c012a85124b79c825993be82ee3af20b45482bc58a53bf8865c4c2901dc24083d8b0771818b57ff9d79214303aa8b1b86276229f97430ef1503b23725f5747aa0f24328d429c462385e8ba9424030dd05e4b51fba5dfd9450d3f5ea1d1b4098cf5ddea2f9e4cf00112f16aad5a1088f47a7fc95a39c65601ee623f68c6b28e19b9ffcbd6224abbf1cd42c33e5fc0211213f24317ade6b58cb40aee648d2b6d78f99cffd4f2d0a64383937f9bc8e08e3acdd11f6b420d16aafc215df4c1efda4489b0d3451b4e8669685cc633902525950c41b17404966c7174d7f9b34bff0bdd0182e591549c54fb70c98a154dadfcbeb24cb9cde24a34b9f1dae3df224cdb52b497ec4183e4f6725b6a4c43eb30d7580f6df2aea44eb14b951f4179cc7d2a992fa0cfabcd43a5ef1698d09afccf8b3fd19a2173f974463ca2e5f301e6cdd43dc6166931b319a17881f2a1e2fc27aefab11a3e0e5822d4f6168d5c9c89b52ce5b20dc43aa05b9a82a932a2c14c6680d8b760c61e4038fca1eef5887c5fa87b839b59617a343b60965850a43f67b53d79d378fcb4504162b0fd21f49f2b704776c9992227cf2f4cb0263d746c8a9117b63cf3abed6f6853f2e476a6cdabbccf24b0aee4361faba33b0dea4825527b251880a86c56699337145af63b88e70be9b19a3593b077215b8b99f0954f5e952017bfb42b12167a9712ec1123a768cf5489ffb39056610b75e2e9bd691a985c0b64d21b3fdef558a6cc1b83092058b623151629f0bcb995a18617aa56cf565ce9c421251e74e33bc28d27e85f1202144f0b7704eb545bbd7798a67d55031cbcc69afc90c194c80a8476265dc4568c709a9e326506f1d331f47b3e68c256e58a8433d5c11bbe32ff94e6a435334bbd876b6e33db9f3535276881f33196a272d854cd6b39439cab92ad04f01e6c747ef05cc7c515525a046254a84f332a9ed9f5539879c973680d86716a591c318d488ba38999b37c4637a81f757a5791687013911ecdc6b6f903b7bbe91df051484c34db22d9623d12aab375a95408fbdf459bdbcb17f028eaffb195c94d01de648a20be754124c0a5aa9f0fbc6996a3ff8a13ede018504d314337d7ce2a6497d2006b8c5920e10a52350824b6b8ec0e8c9e45346bd92060778f3574eb374554ea6ed79f6ef0df1099a36b3943e2d06941fb37e6d003b7c1e0d18ee9a5369906128f5760f17ce937015378fe15a6d547eb7998afdf79e8ce150285829c3ad010b3070f2fd4a01b8068397bd7956bef95943d99fcdd409b4fd0443c70b72e519e9959a43590b460c78a91f37f73e646f4120138cd01cc3d469291f667a906b6f1f64858814d71b3f14792db19e889db92a897083d9e9d577ba47fede66627cf2de46e01090b4af61ad6a55e7a0a2048e0a4a3a8341373205d02b90562eb6c1bd4184d67c4a5aa49cffcfaf4586fb4db9c16489d52f690362cc8af6877e3deaed0c590d0b9e76b281eef705c0f72c919be21ba755865f0ed47f5aaceef36eb8d000b405d410442654f1d2437d6e9081f5e54d6c125d39aa9e10803533c77ee1770dc38901defbc22a06420bd8f4515957f48205afe87e27033d3005b3b14e5f8081fde43c65ecc8514d30db1ebf0901898a1f886fbc8d58e17c831f2193a04e04e19019c7d2318ca41655b9b0ea7df2f4e5db2af3215bcabdc6c9409de5d26826eb6d73ac7207a70ef32182a41c0e3cb7f4133ad1c4d3aa7749a862a8988771218afac0621d1e3058ef1d271b4a9fc6f753dad9a2850c24863eacdae7c4e394b58d1b04fae0df7e144cd5d62419e2f0fe5529e38c9a65387d5aa5fcac01fd106298c82929dc0fd4c2a61bb055b3d1a453131d319388a462e51dd0d3800e0d96cb02dbaa21757fc39eea523d0df6438ce452a857c24be0d80b0df3647d6a38e76590a443e499c0e5ad11c469cca746da94f565d3c70c360eacc2afaa6e3c22670e34d5ad0c952e6d39d0fec0b2d2e7e28759cb71e85a6f050c50f91a70047afbf29a90c79cbca52c91f4c59d9edd687d0e374097c8cba579e07cb0a36b0290a763b08ca44e691909fa51138b1b5f0bff86c41c5d779ba824fd3a84e0f83b398f3ec2d87485373e9ec1570c3bb514a26631e27af642911dc80b1683658904d9b3a4090996ac30ddc42d316969c136b6f9160e150c4fe318b2ecdd353e0f02cebab7773407838ddcf8afd6f0f15c5fccae512d52963f5abba67e37a4affc98c10288ed26531ca2cf2df5d89df502bac042864cf0901e40e6bed50c85737dbc6edc592715d49535d0e09723eb8e330a5d1c7021f5407cd1c80a9f3fe059fc5792ae356660b74c0d9353d2d19f656605090634bcd49ea6354313f139f78721d8c2c31eec67d4a6a74be565cbf4c6df453c007d9fd9031f235b8709bcf72c7fd0f8a96734b4eb158115c9c4921540f982c41b6eece4522b7a5d07321b4f27ad65723274ee683ac495e6417adfcd05c9eb1668c0a6ed8f161eb70dd72c5b31cdf5773098554625b9af73fd36b6d7626595b373845cca7230aa441750fad3aa32ea9544d594bbf065e88f99dee28ea47f94eb0478e859e51357a2ae856e67f94cd99fdecfa0b34005002d0c6d25034e8a6db1e2536cca82d702469f5d88615fa4c598afd6aee5e1c0c51c9403191d989d8d819977f80c07633cc3015190800d23fb7961730c3662f9587da0e0e31b3d12e9907dfe7142b3e018fd160d9b64f067ef3a9e8a6b1ed10c4e2dec3f718d12898c7522c2de7695d2e44a0e55553cdc7df246b3aaef804440ca2c051cf287a85ee215a0f40a5860f8cf59fd24a46415038ce27deae40b8bb456cfe13b023213d4906a13fef4ea1d1519a0d90f3937cc820922a99a4932101c2de1dbc0901ecf2d5390fc4010fdfbf1ccc00fd0caddceba8175c43483167a3614b195a49a1c33a379ddf541f190177d5627cf426346f4558a5a7281b8fe2c7b88ac8fe793f7137c5f77ea1839f3d26a29888bc0fa7aa306c830f4d50f0816a00031284344f661b57341da69844abc798341203c20b73ec748a3dc83960c180a9117dff5559914ed85398104bc999a159b15ea734d09c2f2520cebb86fc6442cea436faf7e3a1348cc4ffe4484e1a139883071a1a8928a7bf0b27798600b7bc443e91ba3dff4d29919d93827224d2b5d617f1828b8eb1f284350fa583af5843a45db5195c7f9dec48323c2069a56c055ff66381de4d11acd0ae1cb83d66ed76b380912ae67c6041f730f8adf3479e4bea81d2963e0299b9b4b8aa022605b3ec3d5d1e0fb94109c4bc8273b06fd3c1cc9a830e202f2d3421fd5d975a59d74211d8ab3cdca04e3b99b381b9d0a1c46f71e581353db7e08c74fbb9727e7060555f9a485b3032160cb4d20fc7362cd825455bb2b0bc5852c829fa181e1781340981c562b060c16ae2836def6d2f6f2b1efe0a4e696aef6da160cfac75b77b627f5762d4fab23a3474f45dbac2b83c59df83e38f10eecf33728d4b6dbcfeb255a24861be3c941de4527fabb6e92a1945268287c55e643bff0213f660da8e1a616b0865a38998b6fb5ffc804d5b2e4cdeaf2ebc7528037cee50b4eef9aecdef707ae338b14f37cd2b523e9ddd6aef2bb098757340cb44d982a9376fd9cf6a72432835d9ea32fcd2bdb71e3ad7dc68918d1f5b77c13abfe04bf0b05747dbc0c3baed999fec41fcf4f12379566d364d902469515f4a7bcc063cfe92286d33d326acc081582168a3133cbebda683e852c5631d1affcda2752f862cc8bea5130b109163b4b54e06b2881b12c776b86525316b08ceb2fbc5b9b55ac3f709653484c521a053a1bb61bc1c43ff14b18b06c1ff2968e45df8e9618c732a238dc8b088fdebafe3aaa54c1b84ba17e87dc9911268352778efad21813662b7020810b7233dec45adc329e20b6a8cdb37aef6811932c5587f66888e81035c4ba6e4f38cac75f85015deeba9263b1d6d57c7ff0e04d688c74424e3701e030d2b798cae91ea5ad6a0d090d489e815da06f3563bb06f9e184c24b1c9c7a55e5da386953b28675ff97a6e80b390474f5eee72d4dd7d48752033b1a86ae561d08ba82622e4f47ee14e0e1951055d7055e8d777691e86a50f0b92dc7bc36de40c144564913b7a299b2e40cc2f3ffcf483bd208fc41729cc247d46fe08527e1a5e57ca736eb57a82a41707b652ff3425db8273ac8e8645a17e344cf552375b6f552fd8c5c1d16fd26fa9549c0ba39d4a4f1edd872d1f92c41f086aad8ecc54f2831eefde8c6590e013b87c96e52e1705ddbb9b590607eee4646cb6e1726e0b612e660dafe21b7ddd62811362e3d4c258f5c069b69964daabb3fe3fb725cef93303367b14aa48b5eec1d2a51fdd273964630929ad69374fc19d354123fb14665b4c15fd9abee282b77903662b8be7072864816170549aa0546ecb4e9a1e5344fe80561b9634af4c36406e0e06aa0b727a8067b488f47d6e4e72e5ea2e9c34b4ed01ab366d0dd2fa2695a4665bd14bb3b54d1831fc96cd7e6b8a0e4895372851f1ad13382dfdd27f8c8ae6d4821382b1ed103780bf30d6b08ff5a1b2201d5096f6a667e394305bccefd66170b051aab657d89d944ad6d3626eed17148d0e24dcd47c79e6af54d09b2281d6d74e16867eb0d76d81236f0c08d5dd0775ebc032e79dc458bd2f2bf5d6267dc53d37b539876a97216b5529732bc2f5e158614b367d04edb22aee61e7fbaf61043171587ea5adb32e9d88b332ae53097b4f408f14d32d84c0da94a9b30fb167d40d05eb54305c24d227453ba685b16288279e3fe180a61b900842a934f9d6705de6a4633181d02f12d057071678ffef94564a69042a54924b007c182b7c6b83292d74de3a32900ea89205c0b649ba2754dc82b1834fd51c99e1ae0ee3dde76707a856dc420957e283e4a900c12b49b83d230bde5b45e9f86d4ff55500fde9325b1c99b21b863c02a40a7ed64c8a0a42969bc6fdbeb43924ecec841b81b22d55b7518d27b6c3580f9ce6d33e186ccad382bf0fcd085d2f5514e8af0df92ef77c294728724f480cf0c19019c98e5455366af8aaa57989344d80c38b68303374265aa89df26efb895c1b3987a534c47caa935180e9ed207e65e0f9a30b685dba085c4d416a1878e33f735a5ad818ea6a2b630f9854f2bced44f6d1eb53530ebaadc0dd4b930a956a0010cf303b7caf12236f4833430f838b5a946d9d891bb09aca41c50d38148000d370ee83c00ba11d1b638d9e0b38941f1bcc4889bbc3f41de2c06bf4f98a4307e47edb04b48b5764477eae845e732b4beda13e7bbf154c7a2eb17a37a03140361824cbf39760deadc17244c92b8cef03566889026f3c05173d0393c830eadb1dd41ea4942164c02f26851998c1f208ef49280a60fc55b1cdef521a0d4b9b946aab05d01ef262fd9411a1558d87ca8e0d630581462ce587fce772743825745d3511c58d441dee81426519bc7937a4d148741032b478c3a720462545fd2816d035de52d7344a255d035816d612bd8ddcbdb3cf670a8931212a0d541a11c802167d1b902f0ead26de517a54962915c7057d57605ffa50fa599c9835d38f48499b53788e22aa59520fe5f44e45de3fa91f4111516177327b005da94f0bc8ae7aa6a6489dceb47887e83e4596a89080b476747b0d65150d03cf3265ea0a356b3fe34833a8dd8f7470c9d04da10ef83663a1b9f5903ed85219ac39b802a4d8b0627a75f2225e531f2679eefbd7293d973ab80787f9172353389a71aff7bf96b356b755a19c52f14878c094db47ce835f128046dd6af6033b504eb579fd53e68be769974032a2221e2bda37570aad997d6cc8c972a2080b7ae73620302b6982243aa2d445f72fdb765769a8ba263eab59acb940d348ca906c2301115ed53b79397d6411958328be5ed434cb3b40843a2831401406104c39b32c018ed3000b783185a67db5fc20b8983f0c2f7d6ac591685479364bfdc13dadd87eed6729d738bd5be4c5b35b642e8b6a24d767777015adaa73c9032a5514b11fc980e4e3515ef3019cd4b92bd71c1e273e0f73c5494c032c21a974471e14dc05e44053f590bf0e3e6442918030ffc081cba6aac622221eb6fab267b65673fc0d6b211b9a0d78987d940855ba492a199ca17200001de358474767946063e85a64d3f8578b64c5fac7331288abd6b164ff274412b00ec6f4a041598f3358014dd0b410f127620641d9d2c4146b93e6cfec8c4cf75c573425cfc7ccb41710d8af2cc469b181480a48ae977663762977049722d114650d41804640d27221fea5c7884eacfd5a42b190b3eda3c9410a791808a21767ea2382b82afd803a0b8b249b4c5640c26dc162d2eacf7f600eb839fff66e9a0d593dc2700de487f9c6545dec3765867b76f53833b83d40f06d9d9c2f42e8a88b6d1da413e59230318511c183d65216f3e2fd9cb0f23a410051bf16f693d766a46b630507d41fdab98014903627d8c1c49008280f0856064e12032446d90b554e6339d4f30bdfb3b8e6669d67cfbcc3886c0b2aa08674ca1bef0a14e8c80e0e6a3145a261d171ea23b1d3e134b4d0ed3ada74708b991c664caa82d0b12c4260eb4a12ea9772cc7914983b89606abca426761498ab76269925ff80c04558470b78787a245575025c691378cc99fcfd9eb70a3ba147681cdebb25148e80001cf910c937d0200e464a068a9e7d27bc7727806326e4be673f523e551266e0fc5d89c43aee38127722b72538f09413d03e0e3237c6188846adf51361df9b179a53e513c2b2b0bc518cb702b932915a71bd0ab077aa574b593d1b246293e362723308722701b99152056c3658b3ae704e2721ee30d95d42598c7859e7680a428aa5933fbfc7cd14c25e686a9fc558413ecc33cbfd9469dc78463e961499b4ae9ada0fb7b514020f1e07199aa13ec8b5b8682e2f7115daf72a032581def76a10987affebcf3ff96dfe5ac7a3d9f933727fbbbdf6e6e449e26f75716f6c1e9ba1cf90b507758e482320e4ebe1036c1def09e2837a9cb6a3c8a69ff729e9adf9721978953175d513c8ef9016d00ba0bb37c34e4cbb8e4b0b6ff8f33d6c554054a193a743c807048fc9c3c6195af627d0e8742eed4198117a7f1a0b1d480bc89816cd074772c38a5d09127c4d40d59f9e4cd7bd6469030244863eaec99cf25c1a6eadfe660618d6467ba6607545b6b4290a21874f6e4a3c9eb051e7c2a6478b66125d4d2bd7955534bd0ca6127d2c45accfad5e0e902090f3d7edd767dd43e99173605e6fc99920d1d8cc9200bb9972ac61c458403bb7190a5d1ccdf0c0e1e2f265ce946dab7c56ab746ab9512d6c275bb74ae58f0aac695600ac19e531c070192d675318116c378d3c8aa14b1aff8c0805125f86ba48256977b3ea8684f22dbab88355b9ec53b949ab7663fe5afc1d2ee6db1bad66b7b3c20d8eda8c88189a812386415042ed0d6b0270a5868c301cb952ba414b645c47eb714a08e8b776e7fe74fe0889839ffb13cd4442e2ca7509d2bc41e2a49bd678339dc0b33f0ea45ce7046896e684dded8799ab7c1a3c574102a501d0c5914b813eb06cb448c5300299a666181ef31713aea4f9875c50181975335958c378662ba73fa64618beb9b48a9843742010f8d10527ee64717f1c7e8de0c844ace8c854444978d84f54c46b24d472603f234927226e799d81861125109d97056bb303326239844d7b2f6742c96ecfdc7b362cd8eff33c7e787093489443c4ebd36b9add4a2b1feec5fea93b56a4cd9b453d8ecc91215ab3d41eecc276f4ff0e2798b10b79e054cf8d024e2a7583d5bb5791c5a053a9b38f7f539bc835e81eccc5281748e783720f9e866867cf2c005462ff22f9a5f8b20f5df0754437024a262ead2123af76cf986f947deb80d5fd15550bc0c9d7e716c8e6a68dc303226aec08a5d67390648f21b7c3be82c3bc75a796f08b310196d2edf093d80346822135cbe061e4b36fbe4dfbdcd128603af261f78d0895905e3a5e0a757ae22b87e77b6acd1378507e90ef814d151dc846d0a328d6c1769ef95c30e318584ae82910ae9d7ff728ee630ff9042c32b16216e04b2080c5e8648413016b87d638113658bb2fa81829d2a3c420184791c93707a5d463b295a77d8e396b49f1d884633c3c6d070130a6a9d569fb6ece01143f08308e7ec89391806533b001f900b2687c0550e19c0effc753ee2b09bbfcd7f222b658e069ac5a6a70b82c5767168ba6285f6dbc3bc4c9b3fb8639687d5ce457e0883153d810f087ae32dc35d5cc21e0237092f64b64254422d44242fa00e398d7f8a7f76c634da595025aeeb88203ac16b3135f13bd28151f9cbc7ae32263b3cb13ea3ab9d40d8918d47022d75946a06e379cc182ef068c5696ef4e93e5d369a1b788c075460f8acbbf08f40aaf56341e0d94b0d7117f2378f24df90ab100eabf811bcbae470fd4e4270531c3a36d67d7b4480314ed10e0fd401edc8fecdeddf04f854d0bf9abcc37a96a86291cd1c5924ad228676895c139674aaacbb3aa842bea158b6da699d176572515f8d754de50580dda02cbc520867c73d0021e4584f5eedaea7b917ba6f810be67204bafa080a9f7aa04401811f761e9554ee506a183cb013d426b22d6190250855073457b5a5f02875c8927e92cf3e1011f22961089887f0f1d4ee31f77e5da9fb34590a4dcd57890b2bf6f40aaafbe7ce7cebb515fc54ce9c3b2717a650bf33359d39a3b3912b53eb417835a96bce2eca281ef9103b7d694df7598d21188c56f5d84354ad5460b0e32bd797af662ce91fe8369cc3fdd9a4578408a440dedf00413552b7e6e615398a8ef7d247186d02d24faf6476f4ada3fb6a1bba98731876a632ead0ce13b2c5d0dba38d54a2746a3e8064dd2c41cba47509bf32b737ea98bdb81386ebfb780a004b16215e7c8697cc023b4971ebd910d437f1719e4f46f26ae27cfa9bd96f0721fada7666dbb022acbe4d710a80f2d67d5e4062927c10bc712559f2d7cc77e5c65849313ff06cb31241b7f8812d44a4436468933473da363d2f6e6bb4a087728bf5c3490aff63000f92ab7abac2ee10942f21b5ad961e4a17518f1b8c204e0005bbba5d925e0ec0161f5d5b0bfb67d3888fe00f3c22eaecf7d78b3d588a9210db8a38f1dcdd2748254beb9434315c726e454b3e7b46d1fbef875dab146b7c59a611491001ce6180a3f4f537764c57d75a55b90f6f97cdbf6b53345fbd87df2a29dc845a47b38cdfb26ef8d0d150520d6e5e51dca56666af7a0a358e4c0cd22e43a3fd294d50beae511180d09c18a916e701dd985ac9979747658153c16f5f7d0af46a919796892bb74c28bcdd8531266a62b0affd6a59d8979d26b9ef4f178974156a59717f6096064884e57718f65356012e43afde88069a837fcdd57a4637012c7abd9e2388df7d0d9e1066364d64f2c20ea277a0a064fed89978c56089e901f08b3af108d80a73ea8ddb0a52aa3ff2a927888628487b3f4f7652ee1c9df615a0ebeed3eaf9104c315f61fea1d763843c9a36288acaf424467e8c476049ed9f25e278d6b4fead7a567299d433494e8323aed8057a55d6bd7d3ab46267af9de5a9dbc1451bb35d3f9aeff1deb4c4058595de659796a012444bc9ed3c8a773c1be573bd8800528d799aa142f1e02b53371115a223b40d7d7efacf65ddf8b6e640157eec123390d9cfa35026d631445b77f0df22a0bb6da74c787bfa8bf2c0fb8174891e58a86274cb4dd5e3003e9b9e5925ccdda27fd98e5cde02c713d12adc04a1de07d6bc261bd90797c74e15ff4c66504f9d8f5f29bdb967b12edcd3f2a29fcbef64686b881fd275c6cc554789b5dd353824c24353516254602b346667b92fd3e59e1400482bac299fa36100ae167fa46ee6c955cdef16ff0ce4d4e39e13970ff7b298dab6ad6d84313309eb2b3fc4e75a8d8962825aec8b5c928453cec18ad603c8b1d0c39d5fd972453d6987e8f3522c23f6bad8006409cc5897b5e39da544138163d1b658e99ebfad2a12299711722d95c0bec67cdf2888bb00606d6068f7e940d3353d3ddfb9905ce18563d3dacae1661ab817135545c2511bfaf12260d0c72eab671c5b32a0e340e14c9554b071a149e3505d5520252b834b116d18692ae0b186948f37a3733827f86c366401322974012c33ff1687b856886ea1f744512673cf5c71c53292f0c1607fccfad329bad53c4e9059201db48a8197077bc44bfdadda7b20d129bb17080771466100e4f249b7b4f45d60199ed03ab5328a85baac9ad6b8101f1cc0cc7370b8390a87a01fbabfb660ffaf3b915b4963195e48f0d41c1258d2b82768b349025fd6b93545d647b744cc81d9f6b6b257651cdbc54655e61c8ac8ca8f3f9bdb3c1ea4ffb564aaf646485f33fc39096b861f668ff57e9a552f63380aeb147626c06f4a0decb1bb394b0080658764e69195ea6e7626debfb2d23433b933b5456754a0e2867972f9da15dfcc307187f7e645cb1b40008ad74dc70c47802af57f06550651e8d63fab6731c8a09301ff3ae68c8346ba1686819658d8c1cb3aa24aef9a5a01bb8d3c863f24797273e3af16736bdc0ce5ede1362c9570b5e87b89ac00ca69e48715af1c096db8a6ed2d61aa5e2a48bde01a5f170da0878b2bf161071b52ae2a289c3ea91621cd08b9c4458a0f1d96d7e4a5c4a2b9f05c4317828f329be12fc23cf4ff766b6720586170588d54d1ef560d6d3f2987ba38e840b6e7e75d521149d7f7ece6b7f1e169a0569246d12cc88c1183c94ea3bedf849c73aa110a76845944e7de13bc8ab62a429071a65349db979e67af230a9010b9cc4a7d7df04217ab609278fa983673978d0c242d883c913cb634df08327ae728e9120f4e06f6054a49a806df159d4487d8cd0a3c0d8ae5ad2294d3390724960e95637aeb45dcc8b6014f4fb1e44fc522c5c8348c591905d7a6d925830a3152a5f105071db42d4e350f1ab9f0f7f009b62b0eff2468a7ad03e5d5cdb7a17a58d8cc61b72f461080359391d6ddc1614ab4a879466f2bda90aeaeeb83a3ae2a396633e9e5176446563eae6445260ca33815b72be8120653d9bfb7aa84a6d5436b15818041aa67ad8533488d24772ff8ca3890f824922176af9a2e16e2236e6e75be085a62417812d870d5961b9e8137a285695b589aab5710678b0fa8ba6c51ab9952029308c8c3eb9fe1a31ca68cd7bf4874b382a9953c23adced8bbd06a6e4ee81f1dd0881edcba498c357da4bed07d6c50104c1325c8c5b46513598ae8c1900fc1aeefaa32c81bd9088cc44154c023608089aad020ffd404fd7757adfe7dae61fa81626a72252864e83f853cf052b4748c72a6aa13a8ea75971c69d997ef15f9ad48b0cbefca29a6ab28162c5aed25ae36b88ca56c00458cc49860a3b1ccc32e9d7dc7d4c88212e0784d108d172e1a5c19dc4db3e2953840481068044b5ddc9467492c4f000e9e27396421de5ea8cc2ceb5f7982c793dfc889765e016f1c233f5470bcab715f6aad7493f031a09898501403af3161c24efc8d1206c52c1b05cd62c2f24da06c329019d77e870a753f1b8855f5701b8d207f946e14c8d5b1316454323d4144ff4b32caf40e93477365168bee40c8288b11558f880620cb47c66f2bb1ca3efd8794bfd4eaecf67bd335592128acfdf9a9908a96b465485735e31e3841e0740780e9b0f718822b623f660e7a1492755738590781213664098e89630b5ef8e6fb8eee9bada6c433b64f95c27324534de524b0140bf6da4aeea7230cb6eb0c4c04000d1e79f8c733e67f83f366cb2ff2598b284310b3cd2531192f5e49b59a714e49b008eac3c15c29caaf0fd0304f59c69d34c477b6b19953dc84c0076bf9386f0a632c2bb7766fab10fd19f89ba8632542d20e1b355d9df0b9e0093b25fc674b8ac45a0192c15d579352bd0618913b0d0f03673b8471b6a2dd92adf6858c4bd212c24d2929cb91dbc5b098034bd5ea54af54a70ce72b1316a835d2881310f442db3440ec3d3b35050e142e0f597c4a5ba095a05b073014b6f628e4911fd94a45e19a2b70746136ed9c5e2889482d9fcc79bb1f0d5975902680b3169c94bec1b5081f75d7de1a4d9614d0407c108c9a7c5eb264e365e7efafaaf0fd4c3e57dbf2ac1a100f755b7a40b53a7a5cc309e5335fedb34836cd4a1106510d92ce3aeee3898f0af0cacc37e58a7501dea84fb07a40bc27c0963152cb67287a45e6908a518fa428d46b2c8ee7a9e653910a21814d56bbcb871ea7aa46af808829adb801947353eb27c0e9cacbc97033dc29da0be2d10f02df1eb1db68cc8253fbae8692d1c0fcb72eb879be86127ca35c771fdd7bcd97f193111b41bfba00515d15d4e3399684628d191e268b92a9acfda878610c62996f9e2ad9c934f04783c75642eb3691d4abf907fa9ac179d32e008008198485e24689581b30dcf53f8ab955fd1be885ddcbe9aa5b22b567ed7f0188b7640152fbb03c1d0444204d5513494cbf0f18769af0496155672c74ca48affe63c2190e86ac952118d1a7ad152dab61c485320c2d8754f479b413e815a99729d33413d91bf3f380bfe9507ec3b1f48bc0df5a3886553234413e4b49900a9c2f83dae330f6a26338b53f0e44fc3ad2a1e77c7a55d3d95cbca02e9a207716ffa419c0acaf92e08e2c40ae93e25b05c30ebfa8080028816959cbf2755abcd65dbf68099ef77ce40e0312d44d5091ab326e13c500cb22d1f213067343c2ead63852da80eaa53f5aea3b385adf31149e6eb9e7d49f342b8951206a830fee4917bf4fad94a9bfa809104dea15871b1cc480571cef8b50d86226212448ff9444e6e500230675ae47861f1d0705356756b53cd7a81b055b92d88953c060cb359c439c1f539e3859be135ba95f51f34ef5beff7707e1dc648e6207cc6ccb32f9d450bcf77fa29391a7dfc9e6bc4a80b63f7168ab86283a8c888314a6d55742fe5618a3a731013df5f4bacc15a3834967b7824f74c407b9addee292fbf0953c423239608e7cc11e039cef68018079c6294c745026e33acc0cf40325a9611af285ee51df75b265300ec547b12a4fec47772996faf1c6121dffecc12678fb5f2ff65f451591cf4526bd87fe340de1ed063c8569baac935663ad2cb50ed95d7077d31fd4c21864cd04bcbb6e955c1b12198669fc19ffb729508f019b3036489abd4f54f6da3d7d98dd669c148040064696bbee654e86cbe7eb4741f63ac28c0d4c154d6c3459cf088adaafafa629f05141a00423401014c26f6374d5d52de1a4403a305880693be4fb27f49865c3da4d23adb94685346468629003a38496454907396ddbecc4c35984898d61484800ae11b6e3ed3cd2d4031f82fee88c4905889ecb93ed9a0ebb786934c878f4114417e824dfc30a0211d0d9f4d6566380ebee97f62480d51b73b977e7dbb5f6f733804061c262a50920a167d61306ed0f937ae71c85538e4230a4bba36e486324a8903eb7160b6492ab39b26f052fe47ac213a2e4183a6b52f8884a1eb0d8e870d96d33168ce392736711cdac9e9fef8bd40cc9d613d858be4d8a141af61bd8e603f84dc401a8d5e94888a04dd2c53999073b48fce56b1822030565430153ef6a045abef5f099c34127383c2a98c725ef4a6068106fced04c80269926c22962c8a52aa22c6cc1611ca867f16458b7556ea40147a804a81203d0cc186110004aaf88a393e5dc8b3bf42477d4d5c001b2560be0e3772109bcc3955d0b8bc87dfd0413e1afab71963c70e58ca37cc48e0a33870e7f60d3d1d61584c73a1c9874673ae5806a6e30449fc62d985603a3624ab5eb05549216a2ebc21fbe978caf7a0a90406c71545c649a640b8e3a8202897d2f87802c5b48bb3a25315022b0a0239e2b3bbfa5e9ecb2aa8ca05af415329a9115573c3502ee470a0d251df3ee47a887825ab4a20c6a7a6707cd447904f20f6cbc9f78150fd3bd9b89ec1ad8fc8ba7b94f7ac2c04f7ea132880a5305a54b158bee46cf947febe08f6db01f5a7511d725b9c43ce63735d02a8d51499f67ad0cc2dc1b585a7b12736eb65050023189a9ed6f4a219aecf2118038255d2a0903312238a296929245369eb38844434e73e631b80dd10ec71746791e4a551b7174b82e5b3ea1ed4f22d97a2e68609537051b17c2068c65e114c4cab7953ab6a32e30748a8fc1b9d036dbe52b620ba0a8e7aacad8aaafdd5515a4ee04ab8aad94648638ac30488819c74ce4a6cad15dbba3aa919cc923d5f28b62cc3add3fd9e128d410d7da17784b972e5c73be36a2bc084ec346350b9a8e8d2f1d26fa54f6fc1a407091a55448f0628cd37f1c8d810134be218db72c43853386577b783016089481503e8b63958574da675bcc18c6b5c62513c9e47ad4174e606e7f663757564221c5e0a6ee1fd8128fc325452cfbffe691c0503441b97a28ca4aba56437e29683e3e6a94e0763a1d1a25e88717625781cd3f006fd7926e99da7f767f2deb12fd70f7cc855111d8c798e56060f745ed1b23a642e9cbd558ec77dcca789079da96a59ea75928f67cd8de5c3f1a996678f15d583ef608b2f2325f4c0d32c41ef7b113e8a510c682489125b35167d986c3357576dbad7e4d9d03c4afb2732ff6071069e5ef182b2664db68899e644231301f0460fb6fc54b4032ba0f5d2972f9e55de0c1b98c834845960839f1dfaef5d59233b9ec2a26c02022237de1a249d26488a1200830925dcc9dac3a49e9da1e7ca001c589396e4025d4089d56a1c30606f05178a9b1b5ecf90abb4906020996fce009eff1d0a3a6744ffff8c6caf73205498914e554b976fc3f6626c741de68085f5fd364610578a002067a034e1f8bfafe8df7f5e949690dced44b511c90d1959a607859f9500f7960621ecdd5de66e1e062096f71eafc025dda5196076426b3bb70953ddf4daf49d950e4a01ebcea44b3a1fcca397364716cf6b686648ca5f65b1dc1431a8b6c82fb8c8a41d730f1ad43be872ac064159ccef49a09ce04af7c07b589f80b0cb97b1c587cf44959137db774b826724522bca81d3e178d6421fcf6f222310ee2fcfebd382b8451a71bd5f848fa6365dd84035739d2a134a3fee466b19d36d1292f867fa93dd1b04dec7ddc79086fbbcc4e1e86b11e37570e65c010985727a5c3527453a07842d6c786eb8b333c7eb9239f2bbd731fd9c3ef9db9b98a627d3ba42577e7998522ed8188ac5fdaf7ef3b8d3b90662a008c464d1b3192bed24d57f1fe59339ed129c0531cd6c685002a903d7c107eeefba6a9524770441376b94c5b40fecbf932f86695d8bf0a4dc7350e24b0b5950c3fb71909f8e77938e4893827aeefa4384b4f98e236b22c17dfbf5e948e225ebd342b202b660d1d5138455c3658fd6d1f942b556fddd23b44f1264d84c0505efad12f961d9d876864baac1235c05eb022eb0033060048522217cdc5a1237bd0c2741cb7549109752232b783c7cf6a9f9a7eb3cd71eababf761f97b48428adf476ed82c29168430bc92528400fbecab03580aec4756e730922864f2cb34b0918990ca7c3fac94802c63736a0fc8bf0f3452810695581bd5245e5c08dd794c34016f217627c170f68130eb5dc142c9d6266847e058473fd74d7c84624b377ed153d1a0bd7e827b365ea9045fb00d6160b1c7e3a8a71606b1730e55665ef3046ca61c651d5189715a0d2a2202ed75ae2ae7d44d04f45e8e215ca021d4c0d5783f636e9659a1dbf5424d0f6b7f1abc999714e79b39040bd89f251ec3c9449d78659d408f1a5fc339f8e80b777e872626d018803697089c1659c832c90b7b10423c87be402882cc4068e57ef566e2b9e2deeb448769b31c8a4ca9ba9b708d2f69c7e581add40926bed6885800ac145853f8a3d275d480e69c246f0178d1d4333e60ce259c601e9131c4d86c3413c5a76aa5b9afb36694d5ac5c22bef1f9320fe2ca89075ee7ab605f26d499e13bd10a2dc863ee453245b14f91ee87183bd159667293dcf9a66f23bb82a0cb253300cabe507c445f5dc7b3822c551c36f9e8e3a539998c4005487082d4f57bfc4348242e9e1d576d7dc280cab50176314fa1d3d707a896d864050a185241645690499826c965bb62fc7323fd12af1f6202e34ccd44d836be93cf1656021c57b71db3f9987be3b0294284eadfa29755c02064de85c272063b720ac267fdc72143df5960098884634ef5f991aa674bbc092262fd850371727416539533e8e8c24138f1104c7d89d1aa5d2f114ad391daf342eed5d3f3e6e59d49038e78572421bfe1f77291b1e3f5043c1e9cd154522c1da14ce424a9ac20ee2b0d964d16bbeeab0c85c6f7415aac39e869800eafd19901431ebb8651947881e8b64270a9cee6f2558c4b1cea437cbc9703d7dc090f7f298c84107ddf3ece85740bf91360767da4a321a3553a3e3e062988f344d50d28980458f402833e9d73d1971bf879ecedb6dc7da85432bfbb30813944e594a9d8b1070935ba5860342dfd3974d9edf1e9e2c3974ad642972283fedfc430854fc49865fe62efb1eb02d9efcbf2c9a30c698a3ffc7dcd1e24c01a0168d719d6038a19909a2e38d60968e0dbfe8c8882bed66b59cda6b9376696e9a64c96ec13dc5fc10eecb45d6c1b38f3afd3b64f26e22d60eff0f57b09c1b593618a7a4be0ff30107256548a77061d556d271a0b8ba58ed055c76eed12f5a21e151bf4cae9a3cfaa84b39d76562e053aba7617548165d044158ba0b423f035523451f8266c4fa8f6f0715337b11af7f57ca253e7f6b163f9e287652e2b0cd8896dcecf4b69964f50d4295e13fc181b19423c89cbdf8d0bd36385624f0ea4098b039c1ced49282ddf20fb5cd6a85f0d1005030a340691c73dd2100c4d9a8700aae98d16b9388a64c6eedc926e013ffd40e2be52c652b38c526903954902f3d004d45d31cd27bc9e4a33d2abb5bf83f2459e43c596a0e4c365dbb35b6e7974c9b7017a1a9f48e192a706e8ad5d12a6d422a3e7b7c053a60946eae3c31d59ff3c0dc51a0606a7b99c04869f0fe9c1eec341238ba605e244678054226a1972a27f6222d9505c6ea3fa9b8578e06b71819c6f5ced8d06d91ce026cbfb4944cd02a83321951494857bdc1db7f3e4d4378ef98927c1a40ad95d411264534b7d3c78350a8a3e6905f834980ac5124d2d080b4fd5ecea30ec52ca65e177bb7283f89c929ba2a91f1c73121ce72460ec422e28102a99173b7caca3a2269453b7f7eb482a7750799459720d30004c40b33a394b6767ec35a83495da8604e4a2d2acaa81a1c27bd3f4eea7821d5a452443fa93064d10a3fe10ecc222bc50e6318a616495d7214da6df3b9b74bfb194c396ab5a48b6b4895eb52ce0e851ffae63e14932cbd7e1d1e6c8a61ce6db2181a19961d3158030b7fd0eb55e97bd85c441fc6fe8badb23d60f08a0ef9534e46409a59a19a859acd8bb395ea9578d6fb3ce97a536e0023e9a25168611fba276034c57bf81fb64639b0ce6c5febaea97f0c6bfbd202f457e9ab5af9f59125dee72805e38587b8eb67a3df5c3a5e8e3d75d5ea62beca0222d796509b9fe812dcd54457c68402cf3a255358ea9e23573c8edf7b4616ee146e42ba717299d504ca0ccf26ac56d7e239db9c00dd96e295735a6b0919b4ce6a9d3b89fe25d1e7e56e6b89bd5d55642ce11a85e9b8debf7bb782e969d604259bc1cbe3e24182a34432807660f951ea023c8f2925fd6ae9b00b80f1b4ad49a180e33e641e4100b3b2ff75b5643894225886362a91fcd3a9d5cbc1332991ccbd73f76847625da3f848f1c9d90cbe78248a83cd1bf280e63ae0811aec9b3dcf2aee6bc3b35ce0186d222807bb811ba6438f1ce3268e640dd540c9962b545da443cd48e8ac887e5ae4dbb9ae7ac22636ab7a94076f1a5cd145a310e6ef5a4df8788cfa4206954714517ae9554615cf840b229fb0167dcfb4ee877906b5f57dea253275c71d9d6d7a59bb182fd492fc3814c50b0b5addce4604e2c18d1968de82d5bca7c366aa66f050ef760c7f8ed8285890bdf9ca9c6de78fb26c41f74713e9a01ec9debf1bb42faac41b6dac762b66dd3c0c028e8e4009d7e91f16ca77e2452b045ba8fcd30328ddb2a38848b0fe3065be2271291967990621898fda99f73db0d59cc3da722a91330b841405fa827558d4cde5912a892b6d0170cfc50a4b917fff10d9f769dfaae263e144936f1fec1d6ffb88e72df1cdd019d4ef2cfba49c688541a9c67839d682e9241981e46602a23dce25b16ba883f4686a2fc8418b3021e047514e0e3d21b00408e34c327054187ffd5abcdaa350fd2ac3c7e31e8c059a84215a190f1b22c7a26f5de481f084ad3f8777ce016632d8827865d2c888646e5585e349f10cacc706d654540b90548e1a04bfcaa4b5318684ea0f5ea5c8f55789a42a2cb4f64654e460cdd91dd5ec9615912dde9fde34bb50df329c390305b8557e2d7f4ed311450f6d226c1dbbf2e16e38c3fb0bc9d4c517eaeb1c889522d798963c038df42fc6f77cddf8887721332b4a7735ed2fd2f2d1a9a50be27bba4af8898e16f4248a5892a43acbd16ea85f456faba1b7e659fde74d55c5592e7666f162ec2e8b6fd26b4348312348f446ba28f4b94060d303d403bdd31e371f55dbace651f4f7c34e7224efd263b50eee80cacf73cb5d69c13a0e0d9a98593167b9c9ac68a1bc48e3cc5c02d780c3ce0c9978dbe8f55904796b019cb958062717379ba3c5a761fdc3f27ee86d9dfdff0e8c3d24d84eac00af6dd2f74d048e9af496b0aa4a6876b29a7493069df08558e9414bb2231126d2aa73289b39a4579aeac0362b983a38ae2e98081161f6cfa0d1eab44419a6a878f11fe5e3ca5d4f3693f8411638c6aa66520f6e2e441a66070302dc6c39c653d0f391e72518f07f5798955ccb322daaa433742548c28c297ab40bfa28fe2b66ff74a79e6c98cd29cfd65744a0c57d7a32ba4d44df7ab60d8cdba3772d56d7ccab5d2b8da0f228c2e6d6e5a2171879e2e5001bfedc1dbdaae2e057f4e1a0ae3024dc5309958f58178914299baadf7e06fa7fbeffbca11de7718a53b8c3bde4da4f6dd4fb8f9315e94e4dea31471e4cc5f312323a44a0e9bd375b7657ae4683dd936925003c8130aa65a0e5747e06f7cb1a82f92634166d873e692c5dde791b91d603e961dc3f80164234d27de92ad1576f05a971b1bbd51224c492f240ac882b34101a468179827c2023881457334d191883886cc6e44caaa7a5e9ae014a09bd45a40ede122442588939d7555e1c4e32c6b5b7ac4a386440ea4d2395b1a4144f88bd7d59fe9d18ccb44a97eaa81a8bb2df7230cd888d97147cbaadaceed15bc04be58fa84361e3e9b807b6597c700ff99a58f5ddc6a016f3df8f8caf0b551d64ec993cb86d515970a511b22520e4be725d16cb747416abfe4a0675b368569db78a3f412ba3aaf098a5367543ccd335a71e0618636f6d910dc7d0e14c72e9178fb93c63b24a88e978c086baca9e80002b0191b5fe763e6c597b9526a4904ed80bc658d5b7dec2f28a777be78f1fef8d6f291c287cf78c18702776ffa6f8ad52a389fd085f6d3d591e8c1a5464e6982cd881c1d002956a9f8dcf655515d9f80021f16eba98432cf0d57fae331b42f006e07b4680bfc572778f26c02e76813df5c8a0e9f6e6d5948d7a0525b6d63f7e99a964c46195fc0480bc5415d6d0bb8f4930b69269c4070261d97b8cfa74775dac36d006211e134b44c5e8eb464830922315339593e31b2f6a8dcbdf92c3ec6999ee91fc2169324667ca72a7ef1fc59ed238a89945a0c35a6ef0077787c783fa2839c71e698bdff419cd05a65388138fdb6afe3b9ce39a9748957053b2c93ee487976ba3c84813a08a4f227d01db6400198599c5ef6a20080b255a0dfa993f852a1791029aa6aee9a6ddf36e4de87920ca457bc6e1433a2f0c8fca39d12fa16d690a2c0785158ffe80ac9321764e621a3f3f91f658119818110b8e3d08d45d75793da55c721d4e603d5ba3be6d2a3f2853f0d9ba282bf1c9ea9dc9c2c46350d4c9145c43a6fe1d75184b15a782bfab590c155f34f87a4b4968da0386f9d3e132d28f9411bf087764b9e858d79e11a0d582ba1763d88d93aa6e08dfd6d1bf43aee2a8f7026a1bd47a6f192bb09616a4cdad9224eb2d0b95459618fc8880369299522ea84c93b9ce9d782ffca24a609a34b6ac368926d0198dd820367eef3c266a07123c08764ba1060cbb016e7264fe1579331909247630480eb8b6e8e1753e6e72c73d6646dc6fde6dcbb1063a588c9e45356f338a00aa12513829095c833ad5eac9a30ead198537e20cfdcff4a8d854a95540d8f358aca745da52c7d7a5307d8a5c385b08e5729fe966e08c5f185b03dfa36074c69b01f909381b24047f818893aa3f2c7726e04e93ba15de26c222fcf4d7e36f428200373697ec12e60808da3c34c5e800c140011aca0140605832a805e4fc750f3cfd0006e801403e885aac7c43a8035ad0074e74158523a56b5c79b352579b30af2454034aa5a4565accb9c6846277dbe79e10387b04183e9334df460a544737c6afd51e6f69d55f947243cbfbe54cd6a1992aa4cb2019e9de65ad0d6d6a3aca30e9d17b64e789c728e333e5ea9af06c1bec91928f1e2b55c93f2ca0be70226cc96499109afd10e0016e75555b21b55564f05dc9b6f3b7f70078ca5f60eab8f81093abe01c561ba724387e13f2e6633b0e130b89604ab996f951dacbb62c32cbd39c745546122517a17517d0bc9db71ca5276b664acf62eeb7e9b8c6e579dff9794572ef335a32268c3835ca5d733bb4d039d0257d259c91a45b8fdbd30a4f05d3242c792ac5c540ac9dc1e55a6e1b16caf5839ca246bd8c7ec6a36cc597d2b07382b22feabbcb729d47fb3000c2ec9eebaccc86f00694a28d4674f94ee8fea2387a442ec5f133872ad05f58aa058ab47473a23ba14152ddca028a9d7d422f509135c11e1e1f024c9e309f0b879168e7e3e4566b404939631775c12053402afe5dae5ef9c145c7888d9589a5b832d191f9c903f1e788935a78b3db231b61b9cc77163950f18de70ce430c1d52b2265ff304b9c344b00f1e1e4a6971be8a7147b0353b3d906795921a7b96dc6a6bdb7ecb248f341a7e8383a00ea9e55fd129bae9c043553abc7804fd37f11da45359762a0227cf5f6d5a472b46aaafe299c1bd7b4316f0138b99b46a5d6627dcec9559db5c863ef0dd122f2f161c20c343ec42ab761d96e08eee462d082576acb4a629b1e34c2ee250eb9059dc3e5952ff9825f53a737cacb65eb3ff7a6c4af2289ebe4327679ed145bbdc1fc0bcd2bc50a459839ba1c0f846182684ef355ff2a231fac6d58ff3b7d1954e5e76c5d95281480c1d698f8de5119b120f05dd592b32c47640dcf8dc16ae587c6d7066f1acd830f12b9f053789e23d9e35bca066be77cab46ab767818d33fb5ccdf0da4fcb0aa6323f6778f2d2c130cc14228d38988fd1d2622749d6391c92c5e635ccc026882fee75f7e8029495e7bee9d702895f8d01d78ed41735d7a26ffcc1341f2f8252218099370f7fe5008b647757477a332560c26444f3d8e86a7651446d10f80a73d8b3ecbb8c59e09d9ded62c3fd2cebd45f2465d3026002e7b3f0da52527b8d701837b63f44499f4bde2184c0b50349d9f969454f122a8f1faa82ac8e9463c4c388b853952efe74422dc2322a4123b04f7c1981eecea0e7634a3049255c819f8c37c67843b1c5aa621e12c9a795b8d2772702c6861c8867f62b3bd7943f1616b654ad8c755ee2a6fe71bb9c0958016392f9dabffc41a57ba9063c0cb2287470c4807aa751ac2efcb4f73287a6a435a6f5c2962eeb75634265ed64960f4d55364950fdc4c896179c1feb7588236f51684b4e45ec26ea84285a2cbe3682fa2acfb13995d5c457442c2cb629fd35137d6fe25585a65e475a63dbe9e49e102ca38fbf066d921f55afccf8c017965a0afe59061103601411cb249e7316d0fa126400e6c8201b81b4c9275f96b27a580dc3b28e5cfca28f81986118d57d0c054734158361dac72425612831a6072a9e604cb5bdc051c520d294740679bbd15a6930a3d9efa02049663c8338ad743a4b1b16d051283ef9ab22d5c9456a0bf608491a4a37d35d461309406cc324ef5b9e9816a4cf0d0722dfb44a5d965996447c59f275d943672145a9ed5a224a2369b0b19a555cc8f9546b50f0bc54cd7edff8aff96caf052705526142d7c168b64e385cc9639021d6863c9c344957c33304062c5a6b3944ead6096ba019a4533c96d9cda99a0992c49797ef373d97a09b43b0f5af0aa165a1ade6dbb4254b0f986eb606db5828dc6fbbed0670f0947466bd3373c0406d58cd8030cb29950743b0603084e3dc82de3c6275befea09063b4379cc68497174f0b4d63bc8de6b0a650389761ee28a1ac6658ccebbcbe33695100203cef747afdb5636fecbf09c6465c3efc0bf71b7b64d8e214220ad21b1630d7c4884870a25b4adb24434a50aedc8e012feacc4d2b122ab3163ddf44a4f6d8e742db741aa879fe36d2f302dae923d600cb82917fbbf1e42b4ee1803688d72cbec56628366b7b8d548c2e42800f956696824af215a287be10260a82b605ee241e164c760e5c713266d05a3b3a145d38c9c7eb7466a2e191dc003669509bd110ef1a586a6aa26c4b40a0f3602f84ecb360d215a74483eec44f3cb43936d13298b6f00fa9df7809e94350a525ef1d1018bfa094737ae13cf474a0dad5ca903903391bdcc2539376d5351f46bbaf4def712ddda897a60a201293329c35ed95227e7d0ed758d1ce4675d091a1fa9b10b2fc7f9bcf11830733bc11f159109a0ab42a687959f05fbdd403d277f14de9c3c1bdb862a1e10555dc3a44718451fba468aac3fffd5a0532d0d13431848d46bd97aa184abd5f5cb5aa51ede27b0cad16110cae6c3a5272da2d73628c84845de06c11a8b4d696f94aa90f7c17bc7b1c65e1e1c9660d2ab05fdd2b87ddc2574ee1cf0a50935d1824fc06f689d53293a532e4e06d94ec2ba034e6f4a4065f693c19650b4d0f53a8ee303b634d4acc1610e86fd6b644b54593a1fd8befbc682d6b41eadc017885b199cfa447240b1c9b2c4080f1a8040d31d002b5c54d41e3dcb50c397a070f495dddfc3e11d17d292e85c5d24341a209a8cefe4f5073a045c7e6bee62e50ee57de597cc15ee59c1f15700ca672de03c88b6fbc680f6baaaf5aa10c51675913b48b4e5e6f963bb39fa7af33f7b1383cae97467077d6e7c6bc52e1eab0ee43316615ac4c7c87a0ae61cebac20c9c8af501f169c712a00edd16e5d628574bee056c394e77d43c89819195789b4c050a890148c5acc4ccff6f942a7fadb3bfb0c6751883173cb8e6113ae4448085ad6e4151f38d294a00d857b59d0fdb1ca06c420226d85a489eae68f9c90362d29bfcda784725a0c31e0b032fd77cfef4f1c2df19f5e89b90cd86ada1c7c94ef66ec97bb0a8343dce6bbed489738cf0b103300d57533392f52d609d48e2dfb24dc74feab723082415528e9eb9e689f860039b8c0beb068561c20f0fdf886303f77e1f7606952531ba8b2a34a9cdf29a21b040ce0d53d565ae69e5515fbf95a684a3e229a3db52ef1232dafd0301679790ee07b2953b8fe300015a470016e374b9278242f39cb18c495f6572bd3b73924e1f60ff03a3c3217f68bad4a15e17400032f03843736baa8d3f09fe19cf1c3ff5cd77cc739abb1d608a63fef7145411e6624c894d829a4dad2d10c58c5ae1ccc3fadaf376943682700cccb576120a4b85fe049b04a719d6dfae9fba036db4f82a7d8b62dc63a5a639d84a643d0394cd5b08bac01a5e0c1f4300b2ce2bb8548dcdce7b6daa4aeb37cfec8c09389293e386d91eb2668a54e16c1d7dc7c1b1809e2c0cc8b2e9d0f1f7bea4fc49b4082a426e8ad75a7c9bfa8434455556cdb5a71b3c0773cf89cefb5910aa73003888bf258437d9d4b38279499d7e066395a37f7526c4cd8bc5b78201228fbc40b854ec52f9e26791016363639e1ca8188e3685657ce6da55e0de70b2303bffbaa313230b4193b98bd8943d56f887a58e6bb59bca997783ac30f39035f0108c7e8eac66c6853d06b5f506b5a17490cc091060bbbe7f2225083a0b4ff0fc88be91bcc8bb1413339b4aa46a1596455fbc5888c98fa982e22b581c564269824555258f95d12806ad1ec1d69558ba2e58c4f552afe4440f1cee1313f3e1bbcc602f6d0501699294a7a97f5e4842091cf5343d0be14dc609a61f357ce4f656751057301ae899f10ca301d38f32a2143280269874e9e837f3d51a3646d83570774b7001ce8e1a714bec50ed97b2a887399ac4f8507170a2acbad935b56cc5104d507810e905bcf99fc08270d29bc8ac7f9b7201d77efc21c6945525ad9a5de007f5972c9afa83a12a013e4040550eaea15c628e94f8124c8f75004ca411845b42d60e40e968fd044d96bb658aa2d2d5905d75669d244f78787d5b14a2ed93f8ca9c60038c0ed6d7e230c0905e5afba66b0057dfa2f1bd72a0b1f5a7a72bd8c53a9acc6494fecf02c5c29193d9dff781a54fa174cf4a13afe8a99141e9a74061b019e2554375717dbd39125ffba1921c939cfceb7d8f13cc78d92ed84f32469da601f15ea83f5ef1f965816386948f266bc67cd73f1f818a3bf504c17596be81819b494e85d8a56cef71069cbd4a2c5f03d404a5df76253b20948a11c014093fc30bf3d6c7e243ba048ba8d1e692e595517109a5fc365be5666aec36f09faa915187558d784b56147bdb0e2d1c9f12f49eb57878d064de61304b4a7184da8d0fc13fc53f1ecb205c1acd35e9faa57026602fe8195c4ff991b62002b06f9110218d0b98abdd14a58d0183eeea041902066fbd2ff1aeaae7ad2b98301f05e4daed2a32e3387054983a669a3c98e39c802647227634f5f949451b7da599925efa851b5555cd09f083daaf5eed4fcc2431b78de1d6955e1bde2622d24766feb788f3478e82996dd851160beb214b4b24a1051b3dfe817588da275121286662fee488cd3e27d20273411d097983333c64af05fee29e61ac59750c0a9cd50e2be0be8e5eab966ec67a4d279e8b522d541e2ef4918801fc6279fe1d00a573e7a985624829486f383ef16dcf7ff191119f8c7b5b0adc42b832890df019fc5e180e24b386290e94bc5633a49d9611bf2960ea0245ff64eb6bc5c24cf2557dbfb7b7bad3689d8b1ee236a59a0b4b9a867f263d1226b6210cfacf662695aa2f2cc5b4130acd0efc1399295ae1c52b2684d107695baeeb94463fdb442aeb4f67d2fa533bca4a957e25d0cc8fc4884471ddfdd4dfa4fa1691b21aab68e67c825d0a044a51207da8a329c95f77146bd5d7e010148c1a509c158851bc73b1bda92696e6a032c766ea33e0f0c6b9825ab3012fa54395b2cebb684cee2d305eb7bae1c9865d1e6d50257adf1986d074479e9653ca99b3beca8e4e13eba39a12bebce2642e96d97d6b42636de2a4bf006c627f3fde03e4fc4e9a8cbfeeac14ecdd4eb7dadbdfc6404f031b2f247f75667eecaac9da189aba8c3ab2929908c5635e88593a8bf01d0ebaa5bb2676d4c1e359f0b6a2a119327c39ae2e7030499625c446e312787f3808075c254b18b0c79ce95925e7ee8c395db2093975d1c985c48cab7bf43871736bba6783d52e12c8b2fb3739347fed73d74709ee11d18cf909a29eb7fb7fa33a81b64fb2f0201fe4c73215c262cca24e05d6026bae3a3ddb74536e6316d78d080baea1d0dc6c6578d8bdc9a477058f5258380bcad25163aea436917a5c6aa25d6563ed87b2b2246b20a7a83b484e43cadcadc037f69fc555b1571588fbe9799a43d2ff3a27be6621dd9a9c36be28ba4535ae26033f01caaf699a669541047f5b800d3f466c6894dc0a30ff214cb269079b795db8e10d9f6400ed09f58baca8e133e9597596f2b63358b03517c5731fcdf4847fac2b81bae52702dc0cd528cb952cd27543366979a728708f221e9aa29890815018ed7c54ca30c86b58ceafd4271f90c55960c64860ca6f32ea8b54e3c668955228f0d351eb899a388e69100a9c594e4c3b304a38f2c915e16d8a69c1b8820bb8d010df28c6b454288da0e00951354ab75d896769a41c6df4390918472c8f15207a8b8f34419d03161a7f339ec7d8ad5620806eae40d17ece0deee4ae0560de0ad9af58f222999a3c2394434c6bbf8437fabae965434589b04d9f4fa303533c7218b2c5906f79b63957f5334f635157472d5a3c5e866966e52ea0e7461a034693589a1121e486354c59d06d435e2bf3cca32a3054ee435f800a7bc5f91680e5099f911be875224b9b4d3ac5b580bc7b5a00e2d5c77c6a3d256e9905702d7b7535b0d0f50af053f478ab6e062262ad80221cfa8c976eebdc80fb0174c4be0efc22fffe2a8002e47592f854404d50f389bcbf4a275b34269fb1a7ae191b68d59fa2d6b0067b48e27653af8cd51140a93af60d2dbc6f7c681e02a183677246b338b4dd16e31e12f431e34ddb229debbb28401336ea4ba56576c0def1143375f9d8ac2c81d4da3f157c2c67c1cbf5b59c15b17c5971a381e0cf2bcbdd72d0211a55d7ffe4e5b5cfde58330f97099b7851c897c3d241a2f0b4a7d68335d0b960cc8659592ff36404ec68e8a335aa1f648baacdfc799a81291713e025b7ad708b40e192ab6d12fdc7da4bfd17c5b707f8f67e352280995a332a6a8a1908d952f2c6e5394f2c48c9d4139f8b43d174f1ea331055ef6e8abfce304d26a0849ddd782cc69bbae8fb75c8a677cf06bc33ab4881ab7e101bbd198525112f796e070d9e453c645509bf2e5f44b385a471f79150fdb08007801c7e71ef66573694173b4f8e6a8a4f1670059a868566f2a2aca415e4b5d47751d89434593a5ca6e46ca02ba80934ff63d1ebc089dd4c5c235861b95ff3266622e986621d92f86211ad1bcac0b492757037db44c7eddb4fd2dbc56e98cd2c8263b042b7c7f89d73166912ced14431dde74333e03a716bbdc77b7dcc19ea1165ebed23e609f52548589176cab224ed31853a73a6b59299259612735f4c2593a9e02b2e32edbd5da1997ff10fd5b853d2f0c8dea91e91dd45c46af85358273e064ab53ad1ec761d42388fb2f86f0d22ec3530b70993839af385c1d253303ddd55cf4f6ee8b32b923b91b11129bbc8db88dc9d486c047146dc4b418f2d91ed8bc4dec86c4462532477223862b440dfbe48ec8dcc4624364572278223c601f4ed8bc4dec86c44625390274610376c896c5f24f6463862342b84e9141c0e21ee49ec7d94c594048c277381af9d3347db3d0b9d3bdfe2dcb54f9e0e12dc5cc283febfb1833960077a400773400e28a1af833b30077a600e74000bfa76b007763007e74006fa3ab88372b00719a0d7813978074edde8400e7a568258d64c5e9ba778dca03313a4dfb379eb616c8325a50edb0583846c2f87d25747cc023643889c08cf0e8c57c0750fc621e4b9c3e088f1f621f80630ce7ee77c93c5f160c08a9e796ec9a910a37ec9e1ddba9037c3dbdc91d9083f41c4aa9fcf5576633efbfd1098363215e12340530e4b61e0ad9cf543047d37a95e3ee4e9b640f6100752e34c669d43a5b0fb5552f99ef040882e980df59bac7809ff17f3f2b20a4000c2018a640dfa958e845cded8c5484ea4f3021aee11655c304ec29a0ebb16ff5f56e63fc39299a387f274685b5747e9998670c5a3e276d1fab7b438334b7c4703219e76fa2972d77d0210200ee70f898e8ccda6e20660d00fe4e1921dac7c74bddad86b88785eaa4f5eba91ddd6e49652262953210632061d06fdb5824e443a4be0fe19c5d3b7ef6f41f9f641e8e7427026d64c5915aa75babbbbbbbb573add4be0bedf8225acfeda97ef00eefbadf4e0be4359fd0ec225d897a1acd250c7095c448f6ab05539c1734fdf8932eb57e1f8df77efeab93036c56fc4ab9a1b08f797d5ad56ab5508649432b34020abefdcc9955c8140ee4b5b1d774199989ab1c0c8d9144539251debd397b4863fa7fc7ffa1e5271aab1d17777f76a694c61cfe397a9f59772eff7b9cffc09e23e3502edf341134df588b56654da6c4b3a09030ca6ef9f05729f2ba1f55d09567ab4e6dbb00f07129a370cfe04b542d990f7b21edd8f9fc8854084d451def139e867fd0565b3c0b148e67c3c608a9e573be8fbbe1e677486c0fde3e598743df33b438771963b1d7d45f002350359bdf70d5ea06618abd56370c5fa156bf5304020dd7b1f7b0cc6bef3c0f1b3f7de77fbc87ec4d9c30165600cb09b56d37ff32f4020fd37df7dffe23be9dd84ae1f85d4fc8563ff05647ef117dc802f2e009bc78bf1337e11874d387e1f2c1c31ae09c79bb1ab7b0c76ff02473a0aa9b9c18ed5a2114cbd876f5e14a664528434abe0227f162893c910842e6ca7c958a1e8404e9b5ebde16adff5458256a1acb6be7b1908adefbe15cab81f321bca3e60b158cf0a89b4c22061b5d5864fb97a4340402ec1b1a546cb932b8f8c7bef57cf02651f78bf7a191782e085b2fbdebf0c84ee59df85b21bbee779def845825814e0c9351c87b20d45e0c9228e2c6528abe1883f4976b32002e8c071939249344cc2b7055644206bb596569f866ec36e77177ba7c7eaf5ed7b7d20d6ddbd3a457266caab4ba8211f3f3f4046902ebd0dc3a55488236817da210a09edb00109dd7bafd00e1bd00e2120a1eeee242f58c1e433fac83cfaf8740d8a2874ce393fdb6f5b5c619e206990d2d5246a02b289071ca8a5943ba6d8dddddd504050edfdeeeebedd7d47af88fb5a6badd5defbddffa5e0829ce5ac550117128b7c09b0c0e8a0f9a0061410e13142aa68020cf8cc10170ca25104a40481254788eeeef6ee6e77f791b63de2414a51d7334969eca3b4f114297d9cd94341b109cb6fe2ab8f4c04b68d93674875825841fbd0fd72c9a5c2fe4da5ec6944e2f81eb07c9d234ab822822daa18d992e52badb51e81fb2796fecce04b7590c04d44e50ac745342cd16cafce83bd78f1e2851be39aae69ef1d9c9828048e6151083c5251082c25acc5a3c39faec50ee7474a29a5a45f8cf360bc3e0ca326064c668363e3c168b61737341b0d990c47c60c0c30902163c68c7f100c431a22558d1a39399e939393e3c178f93166c81e07031a349c068d49e31f04431a3466b31a357268ccc290068d598d1a39393a3a62ac06cf94ed60071383355a1dcc3047cea494f646bd7183deb871c3a7bc71e346e3d0abd1ea60e6e8481d9d594e0d9d1c9196a3a3238a349a0d1b376ee010451acd868d1b3770e0d8d901000032c8c0c6ce8d9d1c36b4ec0020c7cb86961c4a3aa9a79c12f468bf77777bd7eec7eedf7d710b4dd1774cd11fc70a1e3f1ee9ffe1cc1ed95234894e7217934b9dc0020c467460a2a10586063d1c85fb21e04df40d86c0f3e3470837a21f1863fc23841b51083f887ecc9e66ba7ed16c9266833de549e94b29a5940f8a2066e9af19ad5556f938536caf75d2ee0027cb6e3a83e8054b3af1121eb10d2db80d8b378c2de30177e8ddddddddedfdb53bc9086c69cea8702b8e4dd1bbbdc391e6af1d6856b025164f54ae3ced18b66fc3d8873f8c71ff4432d583ce2f46ef14bf89c7eaa4a1d71d5ef095058fd78176080109f51fe0bbbbdb027173ad82fdbf3c5ffe6cf759ff87aac5b556efea6e6b777717b100a54badb6fa6be97d3a1660a48c94785a2109c7ca51982954981005942da630924221469a16858476d88084eebd5768870d6887107520a109f401fa839254ea26f5bb25d0cc81c2f5c11607388f3064d22a26e48a850b172cb9b61034e2c8d589cb0f4ea79c5f99fc487daad5567f0050d299a59a2c49b43815b8a5726729a2514a89347be495575e79a54492455622cd1f21c8a22237534d801483852468985c292b30c6104043dc0619e22e648a1e44c810ea4186b8d00e3342660f111ff22165c449c6f18f05588468e244c9e8367ddec250d5b085094f5c61540413275390202751c28aaf50e555070f0108103bdcd356c01308eac77d866a4b280c76fdaba97e701f1e09711f36c141dca73ef7370c57c04342ee3384b6824c917bcc0496794afbf87bd8c7a1ec3efe0eea515f76c32198100c0ce234ee6bc0214ee38aa4f0d001a6c87d60dff53d2a0f29f82f781d3b8d8b31041e22648a9c58059ebfe2be1f7c47f17efb0469eeeffde9da7c8ebb1cc75323c54dd6130732cf8ff104cbef07f70659f68c2c7bf68c6f83194d93dfed44963f6e90e543a06bfd72ce88cdc05e249554d22cc0fc955d8c4081a4592bc953840450595258e2141585094e06314078d4bedd71cbf6df4f2055d443cfca4a1d5c8b07f582c06d63e20825d6978a3411c116685c50c10e25d8d2c59115a44a290dc2be8ea420fbd65a2bf327f34783a0ec7ff6dfbe689f67f6d8d79124c8fed0d753467145e9b88c6b92ba86c30f60afc918f88d20bb502186d35698b1691c6545172e58129b1a28a46c9ce03045302baf9798a41a2d2f179924ece5a635e6e97585181b6f0c92eb0a2c621d99aa169217ac32549e139b555177a575a1686295c0c53de1b40a22669f90ba58dc62950c1487c5153774cccd6691e4290b279803314f59cce0e220cc2d0b2d2f0eca30cd4f8baadb6a6200c40565badc682153042c0c8ee58e2223c6460c66e58e2293854d127615d92029b3248fdf4213581afcca1d55e626aa4c962db8953baa0c0f0aa89a8a82428a4c73475521ddba9e8db1a24cdf8adb99a63af3823d562b77ad0e5ab9d2f7419f3235149906711afd5995499054363953d75699be3fe9da741ff9f46d98b04c9152ea32b468ebc73623ab4cd1690c6ef916d7d377a6d9e33d7d9761f6744fdf9bbc8a3bcd9efb3d4fb3474bd7ea535738360a32fdd17768f16875156cbd7eb4effa1638b36c79e0fa5728bb9e025ca1ccf532bf7e456bec6b8b070e31c699227dd710497cc93574261a055faf08ecdffa7e31e378e56e555776a74ce9b77e74261ead90678a94e7a70309000a4db17b504aa933fda44f6301fb8f35565455574c30fd4b4bc29d3fcf7fa069c6044dbbbd776ae5b8afbbbb1ba445b84fee971183ec496a31c1239d03c8fd382dd474e47efdead6802f9c3bf157980aa006c07a8f712d83dc995ad0677e2981c75bd37a8141b599f362d430c197e72747eeb7a184c7bb0280545203058f94e5e53081479abd761f2bf2478c6d1d4ffd70bc8bb10de74e7a5caea037c58f61d3e261a5add4e7bd1c05a5b042efc3f9cea0eb1b3c53a2d4437d7865bb562b48ddab38e63e533c52e2aa77e44d2c765b3cb42617cd4c0c255e228803f67478300d3fcbdd49fc55eb2b4903eaa1ee9dc9301ca915305a3cec8d95b1b7bfc40c2578a417cca07219b99141a3083cde4f26050c9c1832590ca88f0c1e29ce0e18d8644421c3a7d837b9df7332e382aab0cbbfb85d2df078410f074beb1ea59e5d795ac71ec655826ebf135b3cac8ecc553695df8fc1340e0ab3160ba60f8e4d1c1f1df933028f14e7e878f7a382c72bff66670e285dcf3ab1084cbf1371665e3027a5a6f8611fc0fdd03a806bb464fb355a66cfd8531c4880295aeac376dc6cc602671df8ac27016709fee1535deb2ed9be8faedd6cbf015df3b74fe43ef3edca5acb711c178eadef3c90678af65b208e29da6795c1dedb560b87177ae0f8dc772f5b1c70bffa9ee20a01afdcadc04f47efd8e74057feecdf6bad7d4772c3b1afa36b9ded2c5b1cd9e61ebd23e3de87ec09afc2074cd1fe184c6301d35f5dd0b3f6db3e6641d9a8776df5db3b14e72a0a961a884695024d10b7f80929e92a2ad0b515641acefe7d483ab26285d3f7c3f37d3c53098f7b0f1ebe20e87a36f23c0e79a9f07c3aa77fbb3f9593674ad7b38a9bd601ce230ca154babbbbbbbbbbb432a89dba9e59e1218562a77d614c8c925302f3bb0c756de9b2a5ec9772ce3927889faca0136554a5db8a9c53b44148760bd97010217f0b22640811a21fb5217fbb8eff830c2142747bbf17e31ebfdfe50bf962379c4f804965180c6a8a22ccd6b6de99b2e9367b7e721709eaefef88b0586191a0fa78093ce4b409b3c16cf3615d60505316c9a4ee596fbb26fba07bd63ba09b72c02abc321d30172ac1fd30295a465e1d2646a925cb975a88aa508ff68d52e98214d18fa62c5f8420529a90252d925d56c93286ec923b8f5f500c293c431cea2cd144670199e5fb038846e9344a2c988a87bd45a069d95b8bae24049dc25286919b88148a322bf77ff77f5283190ac5e89a0c0bd03bf6795a5ec7fab1c922a7d9ffdcc7150a39cd7eeb5e0fe3eefb58ff571ce2b41b6834493fa3f0060dae4fbfefd6d0ea8126d4945c41c1ce4202cf4f9ab3ae309f070df6cfc0044c9f47eda7997e064630a5e32a8ff4b9ef2194722b37114260c9ddf2401ee5910b6f08444a06e4b72d5b2ab03cca9d474b8403948a0b087808b2325fe60107448a0656dfb68c6465840df23c6265840d3210db6abe4c9a513aa2ae5dcae3fa86c2fff2f6f68f492a257db2085751f1c4f4118a406b2082cc31bf9fb4585f14e244318a12f289132f8da04ee06286d0627d21f7f92102c7fd388d389026fbff943724ea304562c0e050d3eabfc01b135075f2409ece9b567f05e2cc3394bdd65b6fbd40da0c375758b80f51011257a2a882c31332222042cc8c0823b81fbe1c79713e1cc9c2b91fbc24558ec3b1af05ab1bcf8d2ca7e538cebeb801b77247a191420ab6b9a3d08c3902051f65e74cfc8163715c149a1d32c771ff22cc72fff3fc4c44e38446863c3e8f1da29b5f6df26787328ae3be738e9364acb5b68694caa4200fffae88a554a1ff8c42e6596daca632583ea534744a8be6135dcf469c1a27a755fa3defed6468a1f4468937457a832443870b769e7386183c7a33c8e011c674a364d2ea0d52538e655bd435efe5df7a1b6bb8186529eb012332e5ea6b56f87bd83cfed5e390889555d823167b22f86dbe48100f1d2e78ac5531d0a65275d03df54e7d1ca8dea9d289dcfab1860b158c0916cae6c32c58e3c424d7af374bb93ae92083bd06a96b36d79aa45c6b9472fdee032b8df550cd77ee811f68d68432fb355f240887321b92d0037f4d4864011d84a798eb4fd60dd2cdd20d53aedd7c85ed3457f8f3b312aa2ba895b52d1eb1bc92b4fa2216fc7afc63dfa4b81e68d6204eabb5e82629bc5132c5fa3a69f008638255aec563b5d2b161a8fa2d50c715ab1f6914ac5bd7bcaf6766fdcafa3ac6bceae9b80253a9ec81b4de604ceef37a18d38fb8b6c2f1aeeabf403a69ab67812eb0274d226120068f37483748374a4db3e78657c94dd2ecb15fff6669f67061ff0dd3ecc191aa0983041212f6fda8bba2fa5f13665d628a53764f9d0e5deadb6807667641284004cf9cdf7b57359403637605c2a8f1dbbf9a61eaad6bf567d5a2aea07ba7bb7148d729a5f3522a52496938524a29edd0ddddddb1b73bab899fe2ccd205319c5972b3846bbab0e9016315c09e60ccc4054bb8fbf28209e6bcbca0c285963c3e0e5c4c31c245930b60e022c9962dd26cd9a28a980ff82677d416535b486971ab3648d60adf4c692ce00a5e51fc3e2e3bcdd64cb3e79959d445f9129499b614d762f7fddd06f27d7929d735ef1bc759ef85dd3b9dfc428a2d9d5f087027e71173d23bc5216c135de31f5d9896701043a5c2132e4a0f5b64b036179896cb67f852c52a8ceb451caddc512de0825bc1a50c296d496f76eece72f066775f557cafbbc597e33e6a67ef5e79c4eade94bae72e4a9cdd59eee0e790bae751ea20cd4e5f18507173c0d29dfa4ade1c28bd96bbfd37b42f7bc7d25aa975f73b7bbabb67c8a6f329a554babbd329d650e93a968d0b04966f03064e70e6e41a34da0beb74e22c6ec9e596d80021fbcb6a5917a81503f93b8f95ebac74d2d0655dafda985a6b2d95d2056bad4d656a09e1b4721cf7cda8322a0843c6f7618023e39190d4e0601c03862cf4f9cc20914c303eac21536b0499ef977bc18b9b9607b7cebceeda4dcb0015c8dc537084e10b5e70356ccca6468e0d2ca77560353aa2012000be284532350d0a1559ab5757ebd5d1a8ab65a3d5f2c06d301dba9ec9e994e59c73ab6e258b6451d1e5ecb5dff7896828c1f281265157dae2519dfa886f77ada5cbba5ef5258b50dc2dfd65ac7d2e6e9fffafbf1bba6d4793edbd893cf8dc361e6575abcb627acd303fe89a9414cd9163d6dc2f5f4a4a2a478e1c510ac831cbf1350af949f9573e6e22cb8f19790b52801dc9ad674f1731c3480b8cc8624c76e95d6bcfc314f7347382db95b2a86bb3264f100da6b42fbdad402a734f47e81d3f40ffe859ce0b86e5f682f1cc0bb6c16648903e4292c6d1f79ef53d44e6be00dcfd92b907adc0417e84e76a58c2ebeb73df289d32c75dc994b9fa25b8defe0d5f60307d1268c6a06d05e9af63f6c88290376401c58b0a98e0808511b7650b4a299d35c44fe029c28f189d21e4516a8291b28bd8d00416252598a0c1862a9c16333539299522a529f4d0201a50e6c9920782f8018a114e0730486ac794e757af95d65a6bad7506db122c52bc888952c491400814bce0f1dedb359f1d1310beb425a97aadb4d65a71fdaffebb8f90322cf0d242540c532a04d516eaeba8b5d62a1681e737a5b3870d8e4441454c982853a0802a19f9000af385a6468c388cb32dc1379329689c48d1720407ea42ecdb028f78ce12d0a3aa15edd50d27a5ee5c3e50624c135694f8210b961c8e52d04a236563b13226092d43144181807b3a9a42626138c20914942788d8a18923598e8058d23f9c50454a133f68591286c301012778628317148e2091e486231eb83be77416b220426904383c8581da01cbd10d4be45c6240942566682285872e5f381b8e4290445671d40489cb3997649723252a6028466792a6df8c6e2cc870b4830a421871c28dab41894ca5f0fcce34538a5120657b80871b94a8f041062348dc09a32290ea527f99e1a6e4d445143180e04a16166a027ae8e19682d118295c7032bad277ce2065b75aa8baf2a54b1157aaa081ca11cbd30dc4962aca18d18509a6aa66304281f55f1778fc66de0563498d8ce6910ec250e4921d8eb8f03486872c56ae50a11ac10023b468e14a125888c181ab4266059f2f340c283b48e164459507ce70549448a1bec0802f634830834d8b12482300c37d56d8c42224a5b4851e8c985088b203143e4cd972730cf7ce5799e1407907ee7dfa22a54beec4194b87a98085165a349159418ba629763ebd8d93a04b2a5818fc87521b2ab08862429417262704514e4aa6f43b8347ecbee5de49291da294524aa3d29cc994524abf6978e752f7edeed99d64b9bbea56dd2ead948dcd64297f1505ee977fbb1b8fc9dd8d6f539449a4d0f0ed0fa4c672dc722481479adb7d46bbbb1be3e9454a0fa9aaaf80664a29a519cf26f8b6cc54724ed91fc6153cdf45e09ce4b79cc0d3bbd46ddd9d3dddeeb676944a5a43e7503954d56784c0e51c533b68469908985f9fcaa0f92fd95200ce40a8ffcf105f196f07b0ec3650b3a7f5f2ab4d4ae9c94eb2e44a5ec949a9775bd790ba465f862d90e61691dc7ad9aa505db3f58bff142e2cb40f27e5b4d9b5a4ae512ecd13577585333385a37ac2dd9ae4f1662e1cb9a9f15e2dbe1061a748812ea5de99df5069b854e560e60ad5949b3f99921ebeaa2c08cb9c94fbb89e4c4db95da1cac14c767181caf3bb241aba6aad5277a995c3f8ad2cdd1ad029491042b39422190832a8be0caa219217541f3bad5fe62fb3cc8357f67f65291aa8e1759acb2eec77924ed124683ae04a253598a14d9239a4e89a0c6d077ac77ad666ed5b9b8dc2daaccddafef59eccf274ca69f6efc55315a93a55a47aa55255a48a54912a5245c2e12bac5495aaab542bfbce7d46707d5a5555659f4a75cd7bfbd43e25824eb94f4d6893feb6c211076d8add6b8331ecfba6b2f542fbd43bf66fd2b892d3ec5ffcbd9243b952b6b2869aba5199e91a0c2ce108f6364fc42694815053820d11d8dbccd610ac4850b7780c5991ddce5e7daa4ff69f9ee613959ca23253e5458ee44953724a4e0d994833692a4da6d9349d6cc75a5d4e3675956c924ef249da2494ccf7fb3ee71002dba46c85867c10fd08122bcafd9385041eeb53b64f3649c97d8a04d9b74c6e9b6890b5666c741073f7b2d65a7befbd2ff070420d5f96cfdda52a5d966f6190557821220b2bcbaf4e82784286c690e5e329a8307579010657963fef9d0ff6958f7990d292e5bd5c18764db0cc958655640f6738fe6cf6c0b2fcbed27544f7381fc3b4bd98bbb54e4da1ac937db2360b65a5ec1485a250148a42d1af555da35fb5e81e3ba5c526f76185b6e8f32e8e2c656b53a63a60ced626a90117da229963045db3a13dea1d1adaa6dea16f04fb4f5ae53e4ee534faf762fc7dff5499fe2852aa44e548548932d126ea449fa8cd91901cc9911cc99f1c6936398dbacda15ccaa76e4db3694ecd260935a76e5466aabc484249a82a09f5a36a164da4994483ee0adf8fab52a9a994649374924fd2d635792fa54fc59c43083cfe645a846493ac9265b24d3f40ee532488da867cb80f0da2376f05b61fa082c6ee5275e0b8312972e1c863c3706c9b9017d2905a4f03ffcefd3fa4061e4a249d63d6642893f4ce7c28b0ec10ca7fb88f7ce2fd709f0e325385249fb0c823dc999b95a92361049926f70f719f19c4c1cf108fd3ec73d0e180fb0853a0597992bcd3209cada8a46d98052d54686800000000c3150000200c0a0704e29040280c346d0b3f14000d6590467c5636974723498ce3300c8218638c318600408031842084c8a8380a20a93ae0ef8e5b8d2b012d9687ec3d9145f2a3d70cdf0904b3335447e2ef2dd46f5ea2d6a06ab4793a636febde89617ff85ee29ca08cf731d4731a85b16434c5381f629f34d68985826ede26e7f649f4abc3f6c357c947c3f51bcd6630ebc3fe927b066cc6b9f1840e3e007099c2bea75ec762734322a7e01e20d3129ba6199e5431b84298cf6972ad21d2ed5a88aad7b5370d489dcb5777b6bc48fba388d74821dce2f905107e6b672cd9615052ee230f3d0e3a63152427e0fa0a346c0a688207f25c6ac528c153a5fc6c01ed2ac4d88f71d4b1c0d5cb46446938589de7fa15f64c21cda0164eac2c0281609d96ca199199071cc7ce20173b22ade8a627b5c8fcf5c023a37508b197198856ee74b8c60da8d37592dd4f01cefd105f468c8beea50d7d117033795c6f4d708c94b91fa723aa22fb8b314cb904ae006ba2665e440f21953b84baea1e47635659b6a394788c033364cb8614569dd18ec72f0a930bc686a0b05b8f9047da7442c89aef91a96c91797536906f38267c6239fd1eb8329579ecee0e924897aaa05a2bb4e0e225101c0cff461244ab9af151dc1c25a1326137859be91e9625e08e7178b2168b72526d7bc41868fc05176947f392646278829122274c66f95104c3098e1981226fbabce17a2631783ff2995d6e2f522e47e448efba56555c909b79413566399b7549c3d7c5a8d419c58a1d627e0c09bef9ebfb627ca92f844a61ee65218d24028fded8676118f3458af1b86bb1d4e2f49b7eff5fa310a095324a24c0dc309092a5a8178e190102cd148478c1f843382547f95889397492f1f1fd4ae8b59a7a1acb004b0ecf790aa8a8ce4b3f678544a194c383c260ba140bc417f7e580a62d1bd822de074b8d9723f23925518ccba28671c3f14780311335d1e7443d4dc9c2c988fe997cd82a5fe9a9db6e329a8598001e0b58cbd64e00575c62abcbe8b6bd4d87f666505d7fc2aadd810610771914f0d228e9cf4d8cc2924aa54a96493d3932a41112ca7219af7046e4117f50468749ba233047b04d8a15ab1b8d4bdd1949a3574703701d08147172461659501cfcf4593c2250229acfc300f93507632f88e5eb4d2bf90f84870538107b5054770f466b3fa9642c59ed90a41d251cd1f0c97294842d752deb416da859dd690c801031cca2f6e97f9a4ce49c443ccd05a07c56187d4c54ce9bf2d81378be6c8f50e7a863093b03e47d428f1086a24eea20cb8b146c795a7adff31822bbcceb8fd65806f147481f63e24fe82a120085331a78ba01342a37831226e64e48be0a22211bb57b293ac3f2d278efe05be6713565699b9a2f057797799446c0ee4012b8c00c604b2ea31082997549d582e8c40ae7f5916e0e9b4aa1cb4dabf9f9970001e6e1b715d5d8ed35bde3ed0d0f7c578235cfe407ede500c88e609b7e239b825544d0a098331b36fae22591b06f27350d75e8e6b11280403d621814f2e1c1db4bac01f2760511f9af68fbee09db11634efcf046c214c589626df939930a96e89b39d1084c56e8388a3136095390dcb46842a3791a2f9c464efab6e291234fd97b4e7b0a3b35b717a4ea47f5ec9178f80b0ed285ba2f5aa9875e0c8093561eb1cea0039de6873b268572ea3a49cbf9d4e00588156578e3a8b065567ae06876020e2686398d4461cb1dfff025a06bcec7cbb5bbc9ec36847408d85374be9e20c8168f9222176acafd830107e0e56be01e8e0a061c965ecf987de7df5b59c309f1a471fb3bca4fc09caf03a67bfd397edbee2c70999875af04b6d0e5a0b445fd7467560a56ed6b87af8a4ecddde252b1026463050a226e17916bc202c4073cfd2a1adc14b849a87cdff2c86132a7ae1a398e3e1a0670f187dd577a11581afc642c743cd669fbd0c20e2349047da8d7dd9b94cefe2f2aecc3b44b6972a496179862cab939217999213a999b4465782d86fb6d678103d1b114d38d8029696038564f4777b25b71f308e574a881bbbcf90742cc37830545c884ddd209d88b344fd339e5a4d43bf149d78661d5a3fc135eecbcbf98d69fd280676426cebc26e1cd85e00bbc15b9661aa4d25f3e45c1ca049bbce8292884a66473e629fb3c6dbb330c3ea06122a67c11457d8a160cae7882e7b620653e9a92024ccc299304025b152f8c277efae720b1275bd7e7a092bbf901444ce3bf6404b4cc5251ab3fa4d3fbdae1aa87e42286997ead6da8cafa5188835f626e6a065d1c3a320c66846afec000cda43768813e617cf6fe0e98c6bf9e58504ff6547c1f96936c88aca48c3a6f03028dada5dc633b21fe8a4696dbd958170acadf12e95dc1863913b150f5a1dadc27a42be6aae1fc2397654430ac9703edaf0e023a6a32b2f7fd5393e219731b40f2a04905b709804accd02f044b1bbe7ebff2f3879709c2980a54b7448042fe68d732ebdca18c0c3a12a20641bca3327a4c99920f98678974be4acdc3f193416acca76a536a2c66d41fe7de3c25788442062fe0b9b83f6b7419162ce584d082a73a584e3ecd25e4b3a4b02f67fceea2a1fd0ed959a6528e4d08d52c90c25ee502a919561b393f63882009039b48c24907ffc55faec6c388f25f49590094fdd680b436105464fc4d216decf73fbc44de9258ec94e2bf6da862b74008bdcde10024ad4dd125123f9375ba7026de6da164aa2498cca06535fb10108b88506b2a054072d75a352713e7688cf021ed8ab26059e2b70f47835f5748a23e9c079d963e960060ad0e2341094073e345746b2b04f2b7c896054f7fa34c38959a98bc2e5ae4318bf67318ca4ad0bc980e545bf39778b2fe9a35c6fee0951cbd7a1e36b0ab2870ea7cba53fd2d99845934720c1309e9197049e6789aa305176006009abc2754470cef553e848881e0a017f3a8ede61de60d174d6783a6801403c6a2de6956284eb4146b51dd430c45e5ed25ee4ac73ae563873ebece0421d39aad9701c0c9182fe5d1f67fadb4b08c5820b2b8f2fcb6eafb82c014dac21cc5449bf3e5df428794cfb8772e3888bf74668dd000e9f35d63b85adcf6bfe0ba2eb094c003653d70a1170b253c7a0ae0b25af56f83bc8434f42f63455daa498080076c762ccdd1a9f08cacf4344b7b26e85ae6460b5d346d9561a7d8c3a94c535293643cabd64bf19221a15cdf9baa3653b8479938536bae7501645de9c91a432497ccb464774d7030e944cd158a0e006e256b593ba209ca772445ff506a3f2e898d1b6bb867262a33f7a88240f360e32722ea3011a411d72cc4b0663526eed1a428436794d9f4fa410689adc9ff81eb71df79b313eacac0cf4d3c1e86b090060a07d52efc18e37ba172ef0794c05feb585bc74fe8e1bd969eb60a07b9c81de99d7cfe8e0800552ff58120b2094590b01a025fb584262e9f6630d25731f1fd43054e089dfc7a2bfa8f49e4cf280c219fdc3239fbf97891590b0a6ad961c1d222e3fadaf78c567929c6643daf4223878a14d1736f6a98487bc510d328ad894272beb7b4495811fb33f04761d6c944194359e7c3f3e4e67408493ec4984c64119b1e6b0f1055022371bf4849dad9cf82b1b292823d4eca58d0474b3ae1d08e1abd63e04c71241abf27b85767441240ec12c83ac2c79c203fd0c8a2ce05974a878a84ff1bd9e113f256f16f699804e64135baacf61499491b015606a40f9e48f21efd58a6ceb860f9898ee4a0cb2f8ddc2cd841cba83b39235ff8c7f5ea5fcb1dcd7bcb056d848d8d1d126505e2eeb799746b0a0e6aea530ed594a62ee5d0153b1b4d317368b5ae9508681142a95359c02d3892421000b09296c3334b033e343451b54b2a4c41b9005abcc996ff1607a71171e00902302fa5c16a78ce8ad8b61ed696d8856a22180379c7580eaa395c654074b2b8081db12cd3729f1afbeafa89dc74083317949794c8405faf2c68447424fb7741b0a14609793a21a992c022cfe4fcb871977437bc248a3e71561c3811c514b2f41b17c2047075fcf233c5fbc78d76fdc33e05a239714abdf9335499ff86af6ac02c3c3962a105f69ba903fb94840904cef8b4243f5f7e701bebd59095254ab81b2c70c4b844f71dc8f1a468f5093fadc570a30e4e814c8af48e391db00e46a9ca5dfcbf7d82e2ea58965daefef9594b9cd2ea73118fbe0406f7c5972fdcca3156b8f5d2763bd532ca76d2f2b85d1fbc13a5aa2d374af2789e5ba992712a9632c0f00d8d0f0bd091b91310139e4873f4a699c7d1374ca2f57cc77ee7e5e3490ccf7ae62f6796afd86def0d38de992f69603d28bafe4fb997d7e79240bcf1aeac6c3b59e9a28fff7d33d4221b5550556e565fee29d524ac2a6e298026b84eba309644995db12f7128b1017683900bfd6e44ca924c72145d53e83168fbdcb2c4490e859fb4478687c8bdef4612d41406912b5b972cbd5671db17678de8a278edf6825814e3e973ad6ef03a34b76633666a3112d4e46e8e6a46f10977dee66361f12ad4a25697f8cdf0bc056bad29757439d0838cbde43b30f7526564d00a90503a08caef1271c7efbd03dede3da83193bf996a39ebc5a5b35ce6996d994a236d519d8d3b5c61b590aa723da532b8951dd6e4b6a19de192eb76134d13fde0cbd63d5c289a2381a0a957b942fc08ba99e249441f0cdcc031072312f08f3b29170cc12bd1c2ce514120adef3c8c668343c0d090121845e9a928857b78b89adbd50b57d94a2ade94f5a34d4d5de12cb252980dfd948e343b6eedfbf727369224bc52ce66f1d392c2fe4ddc9ee9b84fcb0a73189f1bcf1af1d7de8cc70bf252042d846350eb3c2c6d00fd8dedb3a83da8f161ea67eda9a43a023cfdcadc6166efa5b2dcdaf57c123f501673d70904311ecc72765c529de80e135e0a1f816a25ad1f4a81573a90be298e78c72e5f7c71d67ea8c954545529096635fcc2ca063968dc292b9ef63ac29d8794ae2b3fcfbc68160edee7b37fb30cd84afc6d3ad4a45d6c090e7070194f052c37072086404c02b7179dd1091ad5ba6d104134591f6ad1f3faf918647f4b9c6e9f7102a13ecca24b69c4b366f18a0d683397f41c0524b20a22ae3c26ad17d0594848f7402c429759bc8988a7613a6b84cf55efd333ba2e222595a391c8a7fd2c53980e2adec814f695e1f97909ede7ba1dbb26e55ef4816e4a5e4f1cf043cd442450462cd6de269d7e3d4e899f9f9dabeb418e5693fcb0a22ae300112265470ba6df440af6c0e91eec389d6d0dcd170dcd1a22c496e80c31c18754134114be7ca856eaf6f62fa55e1c08cfe915765458c922d30a4cce248f575dbf349abd72be75492fdb387ecd35bf6af1bf6d5ced3ab46b08a9d75e084b3efb75c0f4b1d92f114111d6771d3b58573d490e7c7bfe05c4b4d2956c08a08848223ff92ccee8a2099b29c889f46c8f317d9c870637748719a2b430c0e09a1832fe668c1cb3668b634ead7e6f83e0ab6badb3b24de76a07ab1c8e7009c09c14eda3caaeb87b42cf78e40903326a4ac8c4e2f729044ee294bd5886bf21c39ca4a8e8b7b6cdca24faf9775f1d693f54c1c7816474c01402202c995865f40f80ea8f45c9526e84b0dac772d7d8e653e0c3c6222e3fb896bf76fcd32dd6e270a883d601d81d5e13df9532edb7924c004a98d924d31cc52bb4b495e92823c9d8957a3f9d65acaa50bd5d4c9b6e6c813858ee67b1dd181611ce61511368d3ff7497ca0fe9e9393559ef298b323d2509d36b785b5191c048754e7086f5143a9357fa5e0e4a0e43d16a837a7d97d3b87207d9033f05ce051bb6cc2ad010784b9aaa4879ef8ebaab26cfb3ea38f1a952c9c51fb6c54acfd2debc133de04d6ac5152945ac95ef458b948735d041e4c6b2643c6987c834d74336a2db4bea697c48889108842c2bc9e286bb8acc9b1f70bae800055655c392a7b35f893d4081250934c436454387cc242d293679cf1e4d5881346fa668f93e874630a5581344144963ae46b4801810e159f85a37417d193d2c2532371297e965efbfefa5b474ae24c75f359470e5ea98fe51c5e6e3a4aedbcb4d90472ca60210fd4bc2ab3940114526dc824f0b859898e28bd91d8622d9bd4dd23d94c4948bd3a41c1fa48a3ba05c2f5828dce05ac6fc00a39bcad625f6014d48a46f5e16bcfe383141b890a081278f1fe3350b4a64586b816599c78e2653fb61c3f9768e1586587c30634312e3ebfa659a78aa16a96b72c8970f551b8991b73f9927982e5466b0ded608b57dd578383357ce5307c84350b101e4ef9ec7e2a5a9052ab435bbea04e9345a8f4df1a1913237b1270e5f73c810da4cd037cabf50588022268ad294a621982b8b4ed8bd8870c2e8786904c0ff942b6a4aef9668438683d5ea27f15d9c3a274c7f1758c50ca3e9a350431bdc2c8d23893922576b43f0fa4b13953c7259fa4e2e70c0122966d436b5ea0f92c8f3f55b8d217a6b6771398d6f7eb5c95edfdbb23bd0c54c5abcafd07ef48523cfc8883897101839ca1c488365ae4be3ea4c98d8526aaa14f225e53819f145d20d7a53c70fa67e4b4fc31cc9ab12d269889524ff740f21a04dc6f1bf507256f0f1697e594fc36520a7c385c1528fed2bca1885d11a32c8e5e3ab7889c1e70d9d337289a75f2201ef3a0785551f3c6dfa984c438b841b9420d2a7a5c0fae5f7b8af278ca764e3ba02b80fe10db8a3aecd3f158817c829b47f2e2a8184ba5ea54b8210c1dee3ed86c70f14ec785e6d8a2f0ef934e2c0bd1a96d7d54ac209325aadecf1d41718e39f15c637d8cced5b0e8b2b44ce1f70042f6c8726d876e01aafbe4440c19fc18d8148cb1ec1ff1b4080ed87ecb5089cefecff4aa6cb4bf81ca3405578ef696af4400cb0024ce33b17dafaf701543d7614e22ee753f8371266c6c0c0be770457745addd675673c182ad8da4abae242b9a55a3032963420152cfd867c025fe449e0149c971eb94a55ac29003a5c33f839af7e5e969720738701cd7fac31c2bb7c355333575214f13139a011dc56aa2103ade595bf0d4c67a7a886acfe563226cd82ff85171801293e940a280d38b61070155b286876ac6632dc0cd92af6924f3f7d50d47309ee59697a0b09de8bd4f542a35999cd950cbf646008984d4069cea52c4df1ca6c6b93c99b0e5223ec90046eb4caafbf9f9c89a14ead1059260ea474c9e653774f4d506c0a157e00acce56561cd030db015e38eecb57cff97fc25eb5c1f6ff9d235be93e477b43b2524642cbc05b83fd3b53fc21c0102cec2ea8baf2f739edf825e2671a3653d40b7059ae8ce86174bc04b9f30119e71d5211ad7240dc3f65ef110ab2a4c625880937b9d1c75709b922bbd5c4fc673414f7b708e446f9a8aed8c412f91752d51932a24953448bdd864372b81b9e4dda8b44a98d97a50295f3926d671778a420a7d8a8f0b9e52a227d7d357ae924157de236a2e6d1b68c6f6cd9eb1c002bc0a30e01a837954eec654501023c49d8862c91a91f7d74b3825848a952785aab21ff1e9caf04b61f77e5656f18c0210ea7d673b2f9b39fd478cdd619aa09c9fb0f5f31532562d26fa96e8385144da4d3bb00093c0744adf907f2fe8b7500baafccdf3f38b527685e359e6ee2b0d7843dc211438b21294e1b3efac816baff6d2625dfe13011420eb40f4751e34bddbf6c91e2c0a42f6f22972597bec6873a0dd0b6bf98a7ee9feb587f2785f0d054d0bb525ae0f4e969c44bd5237e4e714b76b85b576ec6db78824129e884c070a6c5e4f2358181a0c17f38c9fa616db7201a63ff0c85cbf108644b542314453536211b24b9f521c064deb8d842eaad568cbc6c81bbe340c927b36ddf269fdb807f92f8ecdb7cdf932c0954b56525dd7a1916e69f8403991ab92c5e18853aee004a874bd9bab2e08cff14932feb4d26caaa7fa451caa4a85677a9163905e39a0d03b2db3345429278500df0ca909455dc53bc76566f4d0aad091626a2756dce78db39aef127592c79c4a50d3c50e33cf4832b97c793863ef21006d29847c61be5ef6137d68e622ef92ef7491216cd21956f2080e3fc7aab2208df42495865c582cae268d38065123a34a56f09fa41ba66d18ac8018fcc8d0e1c40f2371ba19bd22f86ead13de1d9d9cf29ec8ba681ccd02491f05b36351b37fa988fb1dbed74b9f13cc26dc861f69e7a3dd46f04cbc6b985247335918b4f063f660fb40d3d7cce79b2350076b810543a3aa1318553b62a956ae11c2d9ec34d3d4d9434e1bdf939d49d7c83679efce02b95de7ed1fe5376257573c76d3b1c58f45835769875b61dba5e50110ae0884908d58f1260defa5f05443c03ec865ebcd9ae52606c6580bd7a835a92f875c3cfaabe9ff1c166ecab77847e76f2598847c46d78e4687e4a62847e62cefb2aedfee29bfc956b09ec502bef2b12708c98f4cc20a8b31e955659276b3eb156c6153bf95be1ff43efc842fd1c195c70c3293a50d9cd29ca59aa2d781d52e9a266dfcb9b05e2a62833781e2b5646054c0f99362ae32e8ee1125c0d39b8cc51d600d14373ef6e6ceaf9238125af38417fc4f9975a891661919373705c1ad0850cc35a60526b5b3d598b45bd8b0bfdedb548e667d2a2e127f680468a0d238f418fedb5d27f86f654961084677279e6ff139359dbb6988c35b79efa66751a91d0225004c81828ccf283f2d4f8230a77141951f41b6d9bbde162ddc8cc38ed43369e235d8514b99d58552bf71f788132cb58bef9bb64476cf0f59952d41c4110bc6e7616bcc2a787369e590156b5365dcae5e43004bf2c440b60ab6309c58f688dc47d57eb7e586c6b23377a6f949a61ea9b98da90c55543608ceb5cc5ec5db3869d4162820b8cf6879e3c9503fdceb99af4de4a83b9385fa317f5eb0cd99e7290c5f5271c89665ea398c9d7d4a3a19bf235ac79507c6a26ad2e8d8cf388dfbcf304450a4712a9ab98378fe4a650f847f69853dd517aa1c0bd71df3fdc8ab48f3749690f7fbfb9dd0f134e6c7dff1d5e304e03542101788ad506b7ded09358e70e6b478c6e23b89b088c5d16c9ed9d4201c2460cdd0677ee1d672357334343b81b56e1fdd697199ffd8c245b5b370155760015c6098f434021a887855533c5a2a4a9f4230c38e738836089c240182ba0477c791b32e21f9942a10eb8b39225322ba82ab38cced79cc8fed51db71ac2cd67e0a4e256f97028099794ee772e18d8031c0705710dff2005ca711a00b52579667dacc4c98ad6683c998e9c09376571de6ffee5018d37e49a3db4b87606a09bb7842a81f2bc8b2d4ce841c60bce77c26809ccee9080fba76907e8f7948d96f52d30e98c4975a173f471382c5ab7860b774a5c7321a37305dd6fa3dc9b0ef41a2becd189dd99fe3c7e8843d8c03bebb1b2b69855565e2a4fd9c82fba57b9dfe8c938d8c742319f8ed24dc95ab1f560a2f6196ad254a2821dec00b6a623c8e61d56504ecbc7066c2f452a4115ea0ac31ef7436eff5e84ed7dfd1db40e3bbdfe1e9d1396efd295d512605a805138c60a063086d6d16d428bbe37fa7ab72d9760bfc79492d786751fa794859a4abce9b1080721dd681416d5b3ec819b0ad4d80866387aa28241387594073793dcc03f4a86af7c295ec1aa2eb0594f95efa2a386c77b8edc7cfd5f00d58ea838e7043404a84a5206a17c706a2887a04de17246d6dfd076927b29ae8a45c3999c533174b709e5d35a7760a664bcff6314de60561370ee79e9f655a7c6c32a044850f13229a0a596c1b05e23e2a6e80348b76d90812a2a0b6654490027aa845780158a02438ca84fc46413aaa4ffe6faa35280f75b1ca0da972491a5c530164168bd024319d792c561b23102ec96abb47847ddfc74df996c6243f8996351dc0f6c77ea977db026e28502f2e2b4b4d9f10382fb5f6457189976d52657029ddcb012127112f7ca8193ec5910b62326bb691d4053cd1c1722d22e1bd6a6c210a4667a1758ea42c2601aedff68e01fe8c4d254ad808eee1e6b423bace8b20a05b1863a171cec882d07cfe08fc872573748c66330b765979a2489f40ee28002a6b7957cbbdad79075eda207d0f77e0db3616525f16fde91d0700d51c25916c6342d5a24df00487e3065beb6201407a5581467b4ff341466ff22c8abaf51b642d5c032962586ea44c5a397a89c544dcae96fa03804a8f913065f67c406048622d0b7ac66449a02259c592e4114a1334aa9837e0a29b1542efdb6bb1e4f30f614c5ffe657f79ab2dc32149831aeed1a00e0d05ee23f7700c96b53e997fd1a2b85f711e361196ace96e6186047cdf3883a5bcf95a29c00fadfe252085f998e910cbb5d61dd989877c44a98b9ac22aa26a8165e2144804baf040e7084ae7ec46d2636f0367622256d8f73d81e53c820b259b1396e30138ff10740c55b08a129db116548036e9e1473b5515c1bdbc74aa70bc105f71385afbf1f70ada200ac3099084b60affc1116631f0cb145e17a0f8dec078d27fcd2a0fef12a289ec254e923458f32c4f12835334d5e1f89d728aa4b53f657bacf93730cd649d20b1a087e5730f8231722d29d0777d2dcf25a477c6d21da0230fd4e4a173a05c5c15acc19b28f5639ca2f8c2a20401e45f374c7be06a9abec57021d20eeb481ca66a7122c18c2ec23ecfad52ed1ea2dfd7b47ca78391ed89ed73ad002399332e9a064d4620982294da7e2de1bd47e078408992c62299b1f60dd5f076b302caf451da1fd844614fec971854664f030273d5b65f1390722e8502d65a1109b392dbfd442fcfdb7ef3cf7c2c92fa8258da6592faa7d0627f5c3d77aab735d57588c27384fabc9792d31a28b04ee5bd510528baf1ba116e2b51ea59275bbab111379aaf6686918e2f879571ff57a106c5c50d730dd7d4809317e0a6ddf062cabeff6ab0ceb2ad41659e020b1709f9fb83641a93ef5dc8335628a53915880d13e868e68ec0e8d28e0df01476a0870d155d8f12fbd86471606c74c2472479229733f3bbf85a2271770aca9789cf5778b91dbb87c44f56ceb952543140ae58fd7f8a79cce8bf229ef81730722149e7dece1224c407cc0d0ad83c3db19d33996b6ed3ab876a5aa1c2e6e2b4eaf9ae5d64b7ead3076cc6e7457f7fcd5a671177077d7963e3eac8bcb46c02e1ed3d8b784049a9a9351a384926c87973a477841c3de49401717a24575e3cc755a3380c62d95b07945f3f845ed7076ddc4a11a7b94db242ad04f178352ed1b2a44854e5a798b5e47f90b435195fb2f5b35e8436f05d517c6b37ace30ea1d59050dc4c001af7787bbbedf11a3b320a46b4c8f44f15354ddd92967dc23a6fdafb7f63b32ed3f42385eb64ec9af8da248caadc81848e7a4f42d1db5d49a7232fd7bab957fe6febb4832624383a3047877a028c43807a1b26489f5ef2d3f665feb636cb0542532bb84753d8068c60677b73791e3a908c9b062d6776f392de7dcc071e5a183b20443faa15c57799c14eac6e9450eeb2f7ea12d16ba3a0d0e982cb427bb3d18cc81eea3965704f05362651bc7c98021b5aa05c776d2e4d44c868c3f39f622d8ad54c49f818ba6f86cbad2c3f6e0626db89420f5457d75b5eb14560862879da0bd4eb9a612d66e7377fd27dabc62253c9a6d9bca19857450524a8d1ecf6eef3c5e4f20dd0149b51fd6b349e489e7a4913cafd9b6b04ccb640eaacd8a96e3d64986a389b3f53fa334be4e08c51f2a52662d141ba57df268b9f15b30ef7536bc69dc5e544e4bf09c62f3fc7836750a6f86d31f0a1b726bcb877f90b5cefe61cdc60fd3727dffce0b0b0285b0b054e69f0001c3b4e20ee04d207cc5ae9302b322d9a8dd93a219f1b48b626fb3050dce014a8de755f7907e1188ff58fb514776324c81cafa19f00d76888ade31efda917bf4c8e1564f2d30935886a755250342901fe07b5285d3391ece0f7acb94bde2283c9d1230127f8b97a3429955a3622219ab4553f321323fdb951bfea1d82485ccf17a5ec9c739af20d5b9b3a351eacfde7a141ae1fecca970b5c07740f8ede3a4ec50a4120fb48d9c0f33dfd50d4a037e069b99a1d1a39f3f7a12d3cc7990a41751118379967131e800e23ee9dc224a7d7ab6a4bfe5f639c6e7daccdd2300842854bba580ab7a21b695301c26ac90371452bb11d56cb0549f1c88cad19c4a345d9b32b3b92826bbf40a3ba9f02ab4d9ae0e4af5425a00ae91260d1c902c2930c56d4f69a0233189869eb8d6ee1e4f035467a407abed5003553d0adead603d27692145440d56f1176068cc59090b0e3176a94dea55a61769703fb347aa35d3564a4513cf1b72525fa72959e7edda665a8585a7af3db44e8e7fb69bbe0c8a8d8dad3da53dba70d43687dedfd0cad61f2b17e50a88ac1b8911af7abf47d2ae54f56aed18c2fe35e155ac5e519aca9468b0029fbeb6561d60e2f3953b97b493a9577d39c9238b5bc9694105b1b4d025b95578553769e16c2f615873e5a21ad65da76cd13757f14b3b08b70525722f87d3efe5c4a386c919d859cb845057110dc00a0df142607872e428371d7adb3584ce3b69a723a2064dcaafaea67a84bc90d140bb526410047d6ce09bce6550290df654b238146132719c3e06f5c2b6ce6d88d9b3184b83d676db57cec33c92f31287b82043111496699f50cd1d765eee12c772dfd82c21efe9fd0b4935967ddcab85615822dc632c97d3e31417c079413708cb2e2cbe311e9557b246f92f8aeae209cd515864dd3964812d43b489c2bf608971aaa421a432c4af2faf8ab92b8ca09ba78e71cee6e295a1fc3a8b1a06ddc0c6186c16b2c470030302c42995b9a70ca9a1f3fb08ed9ae8f412eb3e313750b93cb7f2694f943925b55ff9c326df8b72c9b123da875bccf4bbad51644e1a19c488746016538c7a52082c7bbe07a45f9ee4a82ff94bcb34b477e7e1678f1cd7f971e59ec8f20664aceafe9bf8a4463fdb580d4b5a7289b3d7340d06c7c609588da46d2c51b25558d1c3b271561b2e2ff6c4962896f4341c190e64183c9e3a1a4498a93c6238c8c078f454e04204b3a6460e5f24580c9c1a5f6430903c72b40861423242dc88b05661a4f89061bc68aae011875553230213114c474e052c8830d77104d5651a4a2540b9d75109e439f4121f92941afc904d704c6a36fe9394374afb165d76d21867a97eef11a1164fcf70d8832857c872306ba92edd27204387f8c2045ac48a5706a6a00b3520f210743bd5a191ef6a5688cdaf98c13ea1a3230c382dcde37e6524f7b5b42254b8944ebd0117691dca91b7b5d79bdb69a574a1de5bb529e74a8652038aaa89f669da02b83ab0475025d07fb0ec77a0518a7bda4547bacd1c535c9fe211054fd80b847ce525bcb56b3b4c8ba437f12c163827f1828290eb51970656058e5986f2ea1167cfe916404d1543bdd58e810933f4a3a66fa46e67d743ecd56877b77fbbd881bdf79b60f4eb8690daa24ebdaa4e0a4ddb858801fcfe25ae2de80f153c06d8ce6ada437ecfc08a4c86438f31e040facf8a54ea6bf9d355f4932376193de526be487eda0a175f4e14f8a4d0303141f6823669bde509ab64c511200569f08c88baddce0dc51610b7c2da8a512c3b329b2812aef74158fc989860d3170b4804f11d777843f563284c18942d13a6b703727e944e4fb6e7887a2b4d88fc5f0967ef76a2afd4f3b49a2fbaeec843a83220adb7da6c2bc373edd695fc3a7b1e07f9821a525c7aa82d24747e6ead965ffb851db305b3d2fdf92eb5f06d4175df2e634c6c50e41b602363ecf21b9c424aea3b4a9112a800a4f4b6acdf345e2515de8f1c4aaa97b38f45e6b97fcf07c67e1972f616c5bf879a8f2efe14fba4d54b08e49fdd60db344fc7068f94b86bb71ab4b531d72c30de2c0b2d48d97eb3005b44b34d80a4cdc8cc44fb887145a7e603710fce60aaa8d58f57dc6b58d1879ce34ee3a2fa39e561dbddd61a619ee78a1ae8e7b12c362346c2331157a844456850cfed8ea7b6a78ad5b8528799ad7a8bb621d28f5ddf6ebc57b0eb377b1f8feb6d9727c43ce14921afcf9634ebfeec0e2f926e378029a96bc88685c91e514a7e4200af9fb1a0303a0e5ab86e8a66f65c6b4649f7f50719e3944cd1c00ceb51152b5ca2472b192807914d5161786d7a67e48ab4327b0a15610fd86d04cb0fd8946356c7bd92614603ed431a00c629349b207612263023af88655ea445bdcfbc5d6a19802bcecd4350d163063e8b832aadc8499898fb99915be0bb210b2e312b72ba60700e30e04d6e6895d4a958cb4ef08ac1a497ed90b8e18f3ccc7b040c52c711936e70683184c6b9c3c15b46d6ea98a817ad491e50bd218089adedc60866598f981b28afe57adb8aacfc031bd533eaa2804ca3678198ac40c8d9ed5400eada248fb85046002fa362579103fb5ab54369ca31dec7f8dfe396133f6aa9d7feee051fc2a3b2406e8d64fe47785274a2d7f688b316c7614878961762835cba94ad675b4fade5be3ae03d575b037433f12139a73c58edf68994c3e4e7116a43fd3628c6c853a4ddccc89f084d15725fa3e096c1cc040b3f80078420ab9934c55bc3c332958f3ff5464412206206e3637932c8a2e0f94157e01c651851eb67361fade91e1674730b51d33dad704dfc1bf0dc45dd2ad6ca3f59bb2cc1209d795ada04050d62dbc122939b351b3b8de0b3d7765a9ce8c6eed940df135684ee58673e4e4ed28159ab46d0bbaee8d66139ddc155f5f9cf4bc3dd72d51e9318c7fdfda86c584132cb5ea2b866fe21a847534b9bc8f82f352ebb2876c9ae3d151501d61affbbf3fe0997ced4435d21d774f8248540770b679aad2335595925c964aadf51af48a59d5b1cfae4acd69744541e9a131274c2d1940f6b4a7491513ef51613550456ff41fff7d05d0566c48b1941ad76e40c7430fcc60ac1058f4cc6aed7a2c84a7df0729a38ff3961801eb6ecac5f2b6e73042e64cfc62b69c217b997a293d4e0234b604528b174431b08208b21653a96c682e7ee5a3aabde63eb8c40ddce7b9ad2788f7c06f2c62e091fada48ed64e495edf60471a5b68bc52cd48f0b1943de790448b65e96109590397acc36a3995fdb7ede3720b696d75b9cd48c56bec9329b7264d371acbaa80c556278a564609cd16b8c451519ce383ee28a2c9ea8cede91919f57c5d39f520e0b4aca382f1cf0d2ba3adf4d486b543ba96a60666feb8022e3612ea174193d6785e6e768604ca5e7344c0a8c42996aa540545b37c0b1d83181e38744682e072beaa6a2d1684c5930cb843e261b9c6003acc9f169320917ff4b81924c90ce91ac85acf64246d2d59203ec9537e333d882ba0c43821faced582293575e9d2e46ee8acab793c0141b824b1aaeb85a783f9bf173cf4c8a246ad01d81ad86f8ba1c3ca877001958fb99b2c3681588271ba036e28cf408f4d28a679abed1aee08dad5a99136ac067af6c389cae391b369f82e0527e01d6107d91b3318c192e1e7f012bbbd0a89dde4ba407071dcc99ac936614d660b0f4048c0ab2c17067319133c205a0d3e4c408a05b8ccf24cb489b68a0c14f0cccde967bdd6bf2c6045d5e94e472797669e3e2f35e1aab3bb9311d9fccacbc2e32b7a195b2828dd0a751b4ebf7602db2715a8a498db98adf685d11d20e049103dfc791560f21acacbae869b4dcf0d20555bf53fc0ca67b0a0bd7762c3775b79a9d51dcf8d3bcba984d8a6bf6a6b839ae181d262b1ff5457a081303f509e8eda3d784cb08d282177cdd4d5770f5fb8f69756d68a5ea0b15267f65aa22f3dbd961b3caf9f019d09436d0c924edbdff40141b2f6011a6e3d10739209b3c44a807e785ecdd3ba5c6026982e57fdb4703a46803cc30fa7bf11041828b37cf391d812a9c49e036bc192e68b3453ff067331f0df02ced36b34125d6fbb31ec0961c2eeba9e0ef96976d53130e600a213b15b36f2b7073e18bebdfe69055a95546f5a2f7a33c1281984eefcbcb4e9831fc1a44f6d68c65958608ee2142bc373de9d4715b50cc174ae3c68f86bff958bf511f3765c8f5528a67b9c93945813f2f97e1bcf76cf757d81e2603f9d200266572539c09db84050a5bff088568f396e2677713d3d802ed439b8b033c19bbdbe1357e1dcac7127ebb6e7a18d1ca757fab8aa717aabb2d6132d71b5504ddcb4ea8b758080ea9e39e52e7a979bb819f13d97a0a617329bf3d49956b551fe1980872550b748dfe1d97ec9c78fb4e75ff2b8c5ae171b411efb74c0e6801381da941be1ec15859d88e0b655abe4292ea80805291d77d493ed6defa7434fe02369bc42f362f9b42d8e8b344ce1460c94fd16266dcc8ab4804d7a8a1d1ef1b1beb50fb3a74c3f73ae899c4fb0da3913aba43eb14be3f9879ef3d64b691f839b0cafac3a3ac76c5e0ae58b0503c77b1be9d461cd815dfe1dad0eb6684e95ab79dc28cf59a0b01211b970f29b508d79756be6ccb6d7fccbd4693b6bbded06ce5127a8dce11552d855391b9228a1ed44bf0dfbd12c8a7ded358ce59151f97445ed18be79602dc65c9b2487529e4589db98100c1d9b110643cc0ad35e9513e31eec541be12162516856c6549998701669a2a2395910b038f55090d05795ab4bcbe171eefa6aeb0121c1e9450e36bc7f3b03919c8d8d8013ac498ce3e07ff44b245c6f444f2fc66298a31e8c338c79d05e3641d4b79fe2d8293fa25a9611f8df630f1bd2ca2206659070e0f33ce7f1d31cf4e88429e6938a95fa911488dce92622967e3b4ca2bb49b94964d6fc0dce90100b54f544d0a5b317844a7393b8ea5939e3b18e9c7da6aa5ce96c96830bf11ea2a94f40a1e0f3babdc15c637cf8685b656c3b20155b4aa74b746fc9b15d10325760b641703be9861a504da88dd4353e9afc9b2418cdc0523111eef268e5706c0e2fc3b4ea323171654e09d7c19c8bd9cb33aee24c0a50ac0dae10f291b66ef541dc0a4461a0b61bcfdda2d067f9e0082222f906dc10f5b82cbc8e19910a875855dd926ac101fc9673b5c6777d4e4cd402598003bb51504ab5fa15d0fa141283be5732a5c1743549a3dc206692b88295dadc4a24f81f1638abb21a66f66d909cee1cc4828ea80f048449b75e35f5641a93589e1bf20b9f02b20bfdbe59c5e745dcc27ae8fdab378bcb8e8f043b79c055f5a52d591b625a6e432de19dfb7e61c5dd5f55387c4b70cc6d2dbc349f979abd7a541c23163a1a5222e4d9a0c0a99445bac3d62b66b496be9a70453396a11e58158840acf8387eca6d8a053e90c7466ab87c13dd91b0f1665dedf7f1b18b768b87f8b29e45e6ad6e4f573672dd321232effbf48d5c105429099937787356d022114522384ea9f2440acdd551f979fcff753a2064dac216f78066d4731ac9381a64cbcb79ae14d59cda7ce9da6f61fd2daeab5bd20f2d0d3c2f43bcdf88442ff76139598eb0c7f63e5459e5e211445b2bf6c88ce5c58c36d10c86ef71a3db7260bc716614c44b19060850fa40bd53f234163d27647d20853bf85ff89750800b369e0153982d15645b694a34382753014d9a017b447db1fdbb4645f038d7e4ca7b733024a4a920be09e0a308de9697e425c1a9a04671007bf736f57dadda6122447bc6ed3722706c289c2270bc6171cbad4b776ceba6aa16e742771d7c8add1aa704ff01434f22a2a41fdebe71acec4cd381111c5abaccd74d98c3da13e355dfbf067e28a7339d6120680a5146d9ac2cc79e21a4e8470c0ab091312c2b03e08b99f3dcd5d549c4658d230520c0fdc1d4546df63334a8132481eaf4bdf3bd114fcecbaf2e398703b09682c146e3b050b605954a03678943b300e19c104c381d04722553ce7883a400d830264628b1d165c638f712403d4ec4d09f255ead0d9408650f0d23ba6981d2a365b184bbc367081d4779583c5323d4f133bb0fbed6585e314229947c4973cf1d85402c16a721cb6d26a9518e20e4f9d38af1c34464c560bfe9c884c1c2496fcf73f53fcd86b8cd8c8320887f1beb559454c5963343196b6e12e8a98aa5c9c0e16a64d4c4aeee78c0fdacc7a7f9d0a922c0ea7dfe1cc4c31a60d175def842cc05ff3a5d331e2725a3af1d61d7368643c39b1a078d5f995efed49a05bf45901cd56506b80206b5ad99886a3d2bf0afd5a9bcf08de5d87c5fba188509ddb8419e252a3768d53924753a70d5206a18cb2e7c64c8733dead2856b428c09e0710cd7d80cbcf473ec2e0775c1c84d06e03e3b9b7bfa3477e65662cef0aa8063f37c85588f2c97ae4d11b5dfa68852115403df78e0cf1cc881992c440c32af2fc859b4090e02156c744ff571c542e1accb1ef34f3e73d734c6ee01d5fb2289fa8fd7041b100ba4cbe48720df3bdfb8e87f0999cf1fd30f77372611dbe0f9eba4f71a0b37dea2c094b89045cb0825b03c0927f08c3c261bdddb0749d527f63eaf9a51f246dd98878be8e759ebb4e8954ae1e668eceacce388bcbf80f4f0832ed11ba447f2a308d2d9f471dfc37c46d71e29b3af7c0e7178e82218f89d8da3d4142280f858e65e12343e058d4fd6b45290b5db94c3491cc5ef35dcc733923f34dfcab5f3f6c9e0e9a9ffdd280c6ba25a07f55ac1107cd511b900bf8aed60cc86d364b9f8d916253add859740862eabb29c05f5b0c6733e3ff8dfab118a544dd1efd0b673ffd4ff4d61781443fe3efa3b8e06dffd43d831abfe8293837c2bf2529e87aea1a4b06410caf7076db752f8e39efd699bdf86ef5ea608472c7a677a232b64af55b7e1f0bc0fd5de926d3d4466cea71f8f40d05f94b8927ba4c134b298c485c3f73cba19f48a43c610bada53ffaf6ef61d0c4f9420e9b7dc5758d4e93b9d99591783c50a13cb039375488bff8387a8c6198b638994eb18b6031cd779cb0e88131da011b40f9f49a0d80741f08aab3455aad927dd4f6def4a40c53c9d3dac7e69b1fba826b604f95979f224cb0ad96dda7726f2582004c88f93d467993e16b179af09981c8c39faab34257a513047288745b32da046fd38f121b507ba3d03ad9493491b9e497850a75db96590c3602772f92a06ee363221e15b934fef2e1757b2ac4bd380e6f1d3a3d53f41d179b2430cd044e8fbacf31ceef7defc8657034370257290693d497ee3641e52c941d510c19dc80c65fd00eac2154c02ff2046ed9d8868a1bbd4a4110307546570d63422b055c92f41ec4adec2c484ef51fa91fdc1625295ebef2fd4a4bb3e4d5bbfb995398775405d717abc24808806cbe5f57bb8bf6617db6a10b4cff0c01b1431a672ad28a9e67d8c4f441c5c11d1d17775b7a5455297cf20a97524d5c34964b9d05e45d492afb8f38b96752852d0b6a4db0ea57c0d47bcebc415e8fbb261625f169bd9ba720525cca672e99876eec5607f46cd765c098f879c75abaa2307e582adfd21ab1a891459dbdca18bd5f1411e9fb5a9061747108503798b9ed5a2cd37e9bcb5fb3cf77282c9737bc2dd2d31f502deab54415e9c86643932a875dad0a86e61b4e8313d283bdd07dcc3f6560040546430943ede923f5931b0d1a3e91e04f538bc854618e6a12b9a566764e348ecb9b07ff1adbd7f937d9d48929046dd54b098a0614e9611cd4518cc41c360fce1a68420c047df0793f53250e887c43f7da4e2088797cc1021997f3a7970bac911022157a441510e65d78a241256cfe4581f6be94982b2e43f4cd2d827861c5ac54aa81b9069f53162aaedcd78240f17e14e518ee5cba01a5720b9529212456f260d6e71b60179fd0bf1c392bcf385a34054d1506decbb5814a519416fdb74e2e95d884bb85bd0ffb61ffa38e83283d633b4b701b047bb541d8a53106cb802f61c1d79db5777ec8deb7457b57b4d99de083333a2b13d3276db6efb7f44603891492bd69da790e2f29e142c243915c362e7c8e5f8f1ad932cb993444873adfe1649e9c62e32ea2fbee660baf29434caf33b1293675e0a48314ae5bab8a23c128ff21002abec96f804a2c797d33730e9ca23473d5e4752cab6829ae95fe04de1190b219b476c09b27ca1a7ce0e4edeadd3c8928c9b48f4813276a05d06f977dbc31ecb7fd38632e0490834759bf75373d962e9ba21ec1c8b1ab0ad4e73f5ba3e6181f46a17345759857b7e85b35c7941fcb1596bb019bb7b1196784b62040c12542a8ec4a85a896068d86faca8536d200543e2011905bd471950d31608266578786039d8878a2662c03bd0f7db563fcb90bd909d38249c4e04d29d3a22f3cb3ec6be2c5854ae1208e47a6e4d201e4c82db1c84afda7f1cab2b0c2e0b62289cda5dd16b365d168a23564534d9090d688acac5cc458e8c9eb95c61924c332e38154b3a78968bbe6c90a8d5eb5f7ebac63fa8beb393b5a847e9dfe8fc1dd30a60afbc8817c9968f3707b15e9309081173d724fbbd189dc839b91539071dba6b2c3b3e80a770c002f3d4f40eb8c71d442cca089dbdbe6582b79e2889f2a03ff080f39fb002c3d7831110b83775aae725310407a57ca36b584e62f4da09d11bc2bb5acb017c234b721333aa0230c1a863bdc2ef719b27e5435f9c30f3adacb0209f2ce55e4e9d00bcdb214ea4ae68a07181fb4d55fec23859de387d851c27c1d4849d5bbc4140a8047741303d3c927e03ba411544b8ac9702466f61d51d905bdb0fb0b7e3f0f1040e30be6ba756a1dbdfbe38fa008eeccd9e39471feab5051b1ff24d27c70baa4179e2537e6204a8617b645eb0a71846481a8cd9a9fedaf323ca5450a5c2481b247f61cb1da17c5010899289ae7aff01d9093c578db06ac6de76150e348a688b4c14a85b2e36b2d30d95efa453b343fbcf06c3a93dfe57fd848bf685161e5fe775324b6b01d852ac6c0e9a1a75f9c491614e6e8ab0f7912f879ee38af4818fc2cff77697ad0e12572b388a52b56acd14ccd8eb5272262a5e2f1bf1aa98949caf0cb53555fe9fff0e4c54c598483477910cfa76334b7b10af22f7a2559009d43dd07d8a4ffeb64e3e2fd0b3f5a34fcdac0ffee322b002baf916fe0daba2983fa126f28de1085c9c12048a616ca5016001c8542eb0028a9f98156061fa449bbbb938fcfbe1455b812caf2588060b740935e5edbcf601197a18502c421b9c48dcfbb014e65c2555dfc02b4b98bb3f8fa578cf9844ec7b3c49cace7cda0997919352e896ce828c05e20452446ad86634de98a027375d27ac967e5e5fba3163d350fef956cd70afcc5e0016aaba2a24ad1b6b4256d18b0a7ae1ff9d17dbc36ea0bfdc00bc26eddb238a5da9bc5782fc55ad9fd1b39e0f29f6a720dbde71cfd4b25cd0f38bbb154b66956ad86fe8aa7c75f4f475236c60fa48abbac8df366d94299b9ca0f165914c2eafe6ce60c443ff56e1cbd5f7fc5191a46140a315f0c2c1099d16c35fa2f592be61fb76e609acaf835dedeffc5cff8f5036d9b30a4f4a51783e6dfb2a936924492fd6142efda6dd0a5fa4963518d373cceaa8def3bb983eb81c00469d558f0604cc981e218adde2b2da63f4d73cb531293565c660a02b9ab86e25fd66680792b00669beef5684d0c65a13b70c4970dfa537722d9b7f248135a643bef2df14d0313d8a96882396a0c2743de67e3e2ec9ddcad7aa1239bee6d6682f37e10ac7b3b20654189811ec08c58b602c7b9fb1c5cf7cfc210e866bf247aab78fe94d360439e54dbfe96e119ff515814c6fdbe832befc25081ba69483d3f7fb4c844b647abf1a466e782567ee97b24c4baabdd59894d40bf40f217f008d0deea5a3a077b728fa1a4fde4af155a986e0faf288b2bb62d77fa501b3b2060b0f8d998384efe010407593b4ece6760b43a3514def765321539e6e94ea79df3271ffd89f9634db06f6638f2f0571a5e1afd8ef4dbe6fe4fff6efef8503379ce3a3dd2df7c4efb2e0e10ce2c20d179a4adf3a66cb0a65b141aef7430739ccc4e726e748d0cbb1964196c98fb95b8c0552b55b5b060227f91375712781c9832cb930f9225c1af92153a80e61d912c191ee1947802a4354f1c4963613a93fad655c838d11091a59ec2fe8f098ba8358e9d6211236d779f6a78bc87f9ed572d3c5defc7190b81feadb4e2e3b7b7aa3e79bf8bcb1ff9b7d3d14d9aa5d65aa1e1fba9774de01de244a0e2ff99eec2c85eed6775a3b543e716ee51a54bba5dcfc001266f6e2540c04a5847ac31915944c1449b854bb25e197dc2de5fac2922e8042bd4d58dc26f5f5bdcda64c18e276d76791ec063e15eae5ae856ab7380198e7f551bb0509548b4a26813cfa0a3939985829515f70991b6acea419016a4d580eeaa6369e5666f6096349f66db83d879cf96293918e9f79058f9182033b143ce21cef8e7bd0b0b6c67937e944b07e5d5eafb129774832c49a64c5699c2b501f7e9aa9c81c00dfe5ba4d43a8cfb356801fbcdfd21a171476517ae10d8443bd9db785bc39f1a1bac62217093012582cf1b256c18398bb405617967a56f181a8c0d148cfbaf274601ab45f6547a1e8b1c68318cd0f4b4c036c4f0b6b9041971562a5ff151acf301b89a664f851b47ea896661be994076b6371258e015202c8717c74ffec2c86af482a8b861ee64bb9fe5ba5ed4d98267e021397bd95ff0b418e199e98695a1143d1726cb786f3c1682490f0b839a6af519da86d0126be97c0397cfb712123353ae6406adbb57c9cd39576c66ef30766fe4b4c381902c89a8fe631a0193247b98d22470878ebdbd867cba4cbc8e1b41f11089c40c2079ca8bace9abd176d04ef0e766f18c2adc5f47aae1ed4a8ebbe6ba90eb2eea8cfbf71e6f438ba1bc7d8b8cf8338c2e83862906e28585538f3eb2bb087ed883e20f02f20d0dd1c0c72cfd5ba23215c7faee64a22d02369a03ff9b714ce538a515859f52ac0bfc67093a20e3cb6ad879220a5ae942e6260ce52c83bd7822681c84a016c0f319af889b6452df83024e6a1dd7c842c2f837410c0c7f54892694dcbd3c1509d08a859d131be3b7aef4ac54e59030ac57f0ce7bb267bf0d184cd7cb61ebb742e6cdb292a7f24d6bcfe5faf9d3a0df6ced2106678b868fa9670d208d9d4733d2e6dd9bbc45ea4ac7f164a5e106d893d17f86342d6eafe875e3014f84ab03c2e6f00e75992a0fbc1bd171895cabb112bdf31e2a132edc138123f1bba1ecad2f9717a16fd18cbd457dd2d20d3bb7b66ba892891097dcd90f2883b6e089738db10a2467418ad9a9704da1b71ce957eb416c70746542c9655d026dd0080619ec447ea59f4254d5ad035b8f759ce9b8ccd1d6ce383b15fc8030199e823490d7b6a21e4bb122a6b06cd395467b32c6074adfc904df5ac38c75d56cbcf76eb1eeb9d4190af7b9479480561a525ad30a60493afa1865d609218fa665da3be00e58d08e59d3e4819e7f627b2fe6ef832776b1a91cb2475a0d2350aa36f35d42c8d36f5b9149894041f10e769cec50bcd070dd7e76640b280749ecde97645b736cd2b3849d4aae72a05d261296963cc16e6a81b00328891d77b8bf5cb63abf20a5de34e81c59388d27deb94f2818ef22524d324f5f0b947b7bfee0fcf17e3124a58e2794d83277ff2c5cbc0a49595837133c2ebea9e4b92474ace5785b4c2326114b27f4712244a44674cb8e932a0b7cf7b11a10fac62eaa1a636e13a3f9876c76fce9704d320731b5908e6e8237102268d9f93a66b52af022c181340407f15a065fffcc20288bbc82a9ba71cc099bd9cad45643b494e5a01562805122f116486b9648b611ed644edf66c97e88117739c95217119d20b4b7f14def1715010aa3d941d85fdeec9860940513b6c38b7c70f449155dc8469c59444647a288156b8b53e369358ba1d71a743d86c77e6ea9dc415a97ecfa0a0c57b03314054bb97d193c9876edd318de8574a30e0f16638d318a28a1e555c22071fe9964b8f15a9936d3044437dc2cbf672d1a2e988bdb2ed6a512cb62a47a96d2a3b96c6e28d43f284b0c842d110ab3c43e0199be6a6a2e1b23a0d3009c1566f59e8e59bc52dd01923c76d485df09b148997349e54f4096cfe3654b021401d447c96b2e5762a74d1c6dcb28534b22e719667e3a2028b3e5bd7b1a567691c4643550eb9f66d6912099b1a6b74981303b3492f8a4d6d89a0d12e7714f7bc2d8d61da7d3549dc90ecc093665a8faafa56e41b63ba69f8937709810ac10199297e49d2523b42204523cf0e51283f1727a530c2a2c68ece0f7f39481f3a6fcd376daa1e4f2347522687997af12bcc90f846c4583882d6f0bdc3669031858028403859012443139f0cf3747d776dff0100dc2daa110ed4c9a21e0196eb20a0c75416d238c35beb42ece6a24fd2e6d5eb809dc8eac25e694d874d642a67347057669a19c12875420574ec3e00260444a70445741cbff49a6d8a7e107c73b1335cce83241388953773f8d69a30f075d312f6a994c97ce5da9bcc8b88982244af500344cb0b726925258109d78da0744d0b43d2344030c7e8b18959e305eaa893ff1bdae1042d4857adab6d2021e95260ca3769981c4f464ac3619e594139e095a9e088f73cc4229f950f668492a83c3279e59a381008811244c4b66b9833aa4b17b73ead8ffd36aa7bfa1b74e195576fa69f413cb70ae00b3913f1d29104f54873ecfa41ed0a41c1d3443abd3f02af50c4978b5bf0992e9755dcc59b0b7c46a39d1db6a7d617d5efd7f76533aa28a0a87e6d1450c3963bae1bae4d64c408af0b432dab0c62ee204447959d294504556ad14258fb82f0ebeeae0e1111ac2d8b3642e6c05c31c6258b0747f13b390aa23f4418c5c27c711679c8711c00577de477ddf460c343557bceecf56a4869e2d8014460b8245a43c7b7bf702125fb95c6f38ff38b7562e8f4f3172d1247f6604ea6242eaed3258afdf6bb8d581eb1324179b2fa00eef5f453665f6a40209496fb845eebfa2b18b38879ffdfa8f104d1a906625b8eb2a91072e6ef5d07d4187e2272b3b2b6dddd4e3755a038b489cf2960e5158af1c394caab9118d7da5ccbf4a1049aa12fb4582056229ae6c9f36df7c86fe447f6a4cca632d38e1e3e83c5c589c0775dbc3a8fe3c07f4060af27f94de839041c186f6266a000003ad84f8778810a42649c13fde33caa10e76884dea90dace60d5ffbdbd6cd7a696969c90e000c1a0bcb0a489020419db1d5679dd8a9eca2cb54866f648bf0915c18c9cb175b7e486418db7bf68145ecb9f8e2a8e2d7e343d5d987c52a0d44194b6d9449f946d2aa480317ce2a12c6f91867f8e58bfe900340d5f554ceebeb7f39bb4e4c5dc7b092926c7b8b95a4bc969e4c1f2f666cd9d2b4c0c01c02b67af92cbed2cf4baf92f4b5d6cf9b4d5debe5cd8939e00540d50b1236f847b10fdca388bc5a400f99400f17200263b0c7fba0236a812e513569105973485d7374639b3108d915d37951318629c460f6c2aedb4b8453974ad57285cdf5df02635ad22b2b9c873a378fbe197630b3801c86c896d8cac0c51699605406ef29ef79d2291f1d83198c2ec6511dddc978a44b4d7a843abbd6ea81d22987c7aecc69415c50933036ba299f81085bfc0c7de92f48d8a6ca3311538feede43ccb41bcd46e529388fae824fef5abb3508ecfa19b4d84c580e0d8031ef777ddbd1ad563352099a892e34bba01918039b5eaf42e6afbbecda4738bf5679bdb99e44537026d2295779d5849448a3bba75c9c112662eafa8d74f35eaf72479f89db25624a550c24bbe628a5946237c363375d1c78ed51bbd1b255171b3d0e7cca337ce92aa7a3d367a5a7a8dcd7231a47a347ad6644ba279d0a99278dee28b330667439baab236ca3c711bce9065ec3eab59bb2d19e72ed29c752ee76cc69254cbaf935e9a33fad46e52937ab6020cec190ee1ccce829d84b7723e1940de9d94978f46c84eb67a276332cbad775a67ed9f43e94ed00a37fad631485cd3de565f4666cde955eaad9e1844d70ba103b34a763323bb571e9ec18cca2c83b98d153a494f6f80d3ba84a91f08daa4927610755239c3dc339b41a27e77a9e21385ddbe1844fe7d9a139611ed34b18e75cae4550e57ebad2ab24e5a6145cc4e93c43f0ece0d3b1979d4aa7d3e9743a9d4ea7d38906a7884fa552a9542a954aa652a9542a954a25d3e9743a9d4ea793cae9743a9d4ea753e9743a9d4ea7d3e9439c524ea7d3e9743a9d4a2a7773a5eb48616045d4f3a0bce8772a6badb5d65a6bad143b6743765df47b65e1c2068bc841c3234495524a29a5a43c223802105ce0032964e1053f34f4f33c43f07ce049164cb6f082224ce1051af9212ae689afb5d65aeb89f04153318fbc115220821327b238430b1a787a5d9e0b8010c61152e001138aa0717952184182911874e1c6145a340f6648b00d357f5d171bda65d44a4f0de3e460cff641c45622ef5a648278217668e2e50d41bc39c3b6bec618cfb34313310f7dc53807bbcd76e80bf350324f272e229e475ec678c913cf13cfc383a2434c3865707951ee09607c7144002c80470c31a187465e478512d060309b34891870c1a299f2a6789842382a948066e2ed32630b832544834d12ac61c60f8dbc3a9ad060f4b1ceb0e2098dbc2b3aa0c1aa1bc21631f8a191d7c4031accda9006144d68b02b23001334584283890c60840a1f1a791d0ddc82ec22e479a69c8f2e56b51551cf432b9d527edae8f268002fb1fb93ce3cfaa56c5015dd4bc9a02a62c90390108c49bdc3bb96413088043dfd1e0f404250f5042c1e730f0b52226ba873f04eda885d34b3076f82f4daec49306c706ef3da7dac2b6ad71d26332c4889761dc3e84932d8b2bc754def6c32c998734e693fab06852d4f343a7ea20163aa13a8ea3c9d900155b1c924633a994da02ade075b9e42b30b28a361231a340084da75da67a084314e4203c027f291d12ecab776257429cda11d606e2a31cd39599cabd45a9cb1b14197771607b1a18e77b6cb42066d34065f74508e6c64cbebb298c248c3cf808227bff0220c2fa2f086105250450e80f04518c260038c2fc048e30649e841167e5cc08413be70b2050c844cf084282678c2462b88179c7801cf099cc0841cb4be908420196401544517d81002184940c20e0d9e388941194e40c1144690e08514710b2bc878d7eb556945a2247281848a57bd38e381e11305266c6109475690059ad905155c1598644109464c7146133d4d5ab66bad400cc9c64b10e083f70809b1ccf1c6069dcd724e9d202c480916448bb44832d8dce1100d1f25110fbb0dee401506c4dc63428af20f477eca48b9a45fbf6e2101d49462ec5a482069d7aeb1071d1cb140d613c308d81101732e92983823c618638c313e9fedcd26d80c725498f1c8733070ee603e392f65159040820926a080620633b002e27844523a8384e2d08b2fbef8e2b3a28af8e2ab22a6007bf1c5175f2c0293175f7cf14526b1e7bd161d7c497452cab7087d49c4820b1f787185b04565e902da76b56de328db3b8ccf0ba716989a606be9078b2336d8aeb5821ea8b0d60a6cf016556c97843790741645e7af50805d8ab8f2b3c198f7de7b5328b14115a2fc8a15f5076e37a8411357178c20c9271f154be493cf074b62845e5c6f04e1c5177d98bcf822132650bcf7ae80d1c5878a0f49840e660726c15c4b8e41ed2409d2166173e2848b2dc71ff85862f43b8c5a7849d04c64d5f6945a4ab948024ad3da94524a5b2be869ad5d6b052690620913212c59a28a254c7ef8707f2d28b3659603d9125514d1b39ddab58e4883045b8e76ad2396d0e4073896d874b46b1d1105185baa5deb8823113e075ddb57f36c946951f5aac70dedeae78cb1c72ac649a92a5e96a47a38a85e0d10ce581b804f2144cd9583f0d52660ae25c618a57cd2242995946e34c618a194324a09e393524a29a59492ca29a99c524a29a5943225b1237181b560f162242c42699d4a43f8f79b21743d72c4d12795a82a75fc848fb55aa1213c6ca904172bb677e79c7356cea037238c8931c61823bc7373cee943ce1e7435e79c2adaf26c9d73cee9361b6354cd29e79c536253ca299dfc4abaf8bcd311dfe06052c210b52b7b290e063bc6014d8475a0ed1f268a4b54b144154cc428a3fc99f1e7bd1fbbcd14777ae754e2c706306aa26cd456bb6ff3a1b1db67d73998eb58cc5c30d1455d584295c5760993254c2250768394f19a9eb66d13bbe95834d40d5b8db514b55189d5cd876a2bfdaa6e3e587bfdff6fc3021b5cb355d770b930f7986817895c2ccbe8ee2eeec773f39be8d9a576637f3d6a40765afb7573098876fb4cbbd374b0d73e03a1e8daf529bafd965d8772713fa0b58f5a8d48037259212c11827c01566bad22ad54b234d351842da96c24155366a3cc35fbf4b4f91cac13c8564faa4ef624dd91a6dd742065b357ad5ca6e8c2726439b49af81bdc8fbabac1fd806d37d40d2f3d1be61e1cd90a0495dd804d3a6d151dc184dadeb8641a0e094e2c115ec006dca2e709ad5648187c515b2af81992dbb6bd960a7c7e1843135c00e30c217cf10415345556a16b75f39a563363e4ad11553082082d9f6db5a7d60d094eba4802d36ae646ea9c5923749082282d2fdae8ec31c1135deb46b34081155270050a5095c78a5a6ba5938b1f8e8b22a228228d234d5a5ea266ad07e8baaab1d65aff2acfe85a6b6d3abd9051b5bc15a365eb08142d99a09c183161b109aa1e4aa8adb5d65a6b9d1089e002e4696badb5d65adb3a4113a6bac311acd72bec68a30a513aff0484273d496c3ada25e1c913377802a422b4a5da25e1c9182ced92608534d8c8dc0f99b91fb233f74374f76cddb197455f170210b280316636faf0b15aa9fa7297bbdc9545dbbf20f47441d2ba8c0af836d9441c0cfc0b0ab0e8eadd37d37bb8408e36b61e340055176863ab372e48b606a00ae20bdcb8a08e58d2e7e0e83998181ffc99497af0410994e00530a620c24fe582881e1ce104114c8e98492494324a29a54443005f202149122d48411657d862899137937ce00751a421060ba8006485231081a4e74d27464fa842108cc0a0091c2c518588286205701bc1125098c119342043091618810823b3065f5081856000821378c0840e946c81452d028f168ecc241b28028a9227a038410fbca844e039e332a1da403d210c28a8420a4f40030634528b963c5068f9e3411e2ca2a089d142f88239e79c730708356002c5185ff0f014413387d09307899eef39e79cd64208b769e77c63670927a070a18c263040a227073cac1f6fc623a80183286800041f0cc1092c08c10b221b7461056d2a91f27561640a4424e90207375090861016b67044145718f98205d3da678408cf08fb8023509c51022aa8f1c4106a1602184211a070a10443692c215e61a4072970e2ef46490cca98021a502c6982094c4637d89424e08d318a30e3491b2ae8420d3222c591f916242638438d1514810a2d8260248925e900d50359c344115588a28329442106409001ef4874a18f98aa8ed05b0bf14f6bebcb012ebac078a156032f92905231a08a4aaa7aaa1f85da286c423f039f5cb767628d76ed9a30a244bf7e4d34b9b2a11ea8a2a72d3a0455cf09ebc991a1079964e80397ac11259e3d43434e24946d43a14eff03216c88e5151248064927d327bad05bbb6d28d4904f9489d66e1b0ad58450135734e6a066335b447d4ca5676b2f8490fa2861b993165329a08a9e056f258ce7f4994b68ebc696e8c621a862b1a08f9125d6a6e4b30c822a9a836b275a401595912449775a8eb3c730092f82385b29a594524a295feba528a776bde8a6e2aae565c4d892563d3a69bb3cbcf22fad2dbe2ee5803dc4d8739d83998139b273b2a409297a748995a42e5938ee4e26151d3af00a46e11c38e29a61a20b4aabe92794d68f426d5bd6c25aa2d6d592cf92d503aa608eaf568eba34b2826f64a3b0f491ac887a8c28887afd02c696e3e6150eccfa09b34c38a354b0c592257d90b0499c4987cf32e8a5c32e7d26e6217af4ed6622af4706614c745589519f28e362a5b1561fea83895e2f718562c0d64bcbda6dc324928a049b34267d6a3abc1ebd456f6d8b0ec921ea438386a24ceaf4d327caa4306da952cf8fe1799b01cb6063c01bf691412f5f6c118a839141138a0c92413228684299502694d9c646c2f20a09045530ca0b8b4350f5c59602f2ba8c6d28650f1f218e43500555f4beb45af1ca2ba04a0241158d33f0c50a5ba6ad4c44d5ad1fdae407c65c0163808ec5cb868e41c51848747cb6baa1635031464f474c44d5b6e17d0163cb92155959d52da8a2b165b70df5d3167d4903129b427130f42f626c99fac8256c9245cf84194c88d14e2e617b4fc14331a08a3e4339a4e1168c710dc58031f414368932911597f8449947434f4f2914da01fac4255186465694a1ade8428fe4f408abe9af257643a15aaca67f4163a3495a3e43589e7abcb948c7223cb0e0db2c5f6be2a1b5f17abd3adacdf50ba76caac2242f616cf2b1fa9ca00d0bb007b51af9dc838752c611d56aacb32f7334f444411c5a5e0d538926f6beb6946acfecb5147bb63938efaef3d46ab26b74d26de0d98298a171eaafc666e6688abb4826054dcf71b7b91fa33b2e7a0e618543cf02f47c7130f33947bba39ccc8e93c341f56a98771912245dfabb34ddf4f284cdb5c438efa5e7cde6e1acf2f8d2a756737ac1c2e65a2eb8a2b36b29f1a4b36a088cc979511ac7df952bd781840c244048d0e8edda95704309347064272d086cfac3c8069e2de7f58d178828bfe1edf586b5bf679a0eda71de731cd3b2a705c9f177a769aee5b581677bade3dac0b38d9ee3e6edefe58c6e03cf06248eee6bd2d51e2feaf2be769a96326aabdd6cd7fe92856dfbfb4b16b60de368d72eb536fdd26cb4c715d35117c50255a6cb438e3b64bb1320dd1e46f7021870468cf04616902c29ddc1942d25e538704af4d3e5a174310cc36e10b1b1d1e8969422d9a8e00c5be7b5f6d2312d887c0907115f4a4bcacd46236d34c2b41aedd87d3dd248c7aed6a41129c33692a6d56c3845229d848d320cbb4e6ced3ab4b553ad06c3292c858d3ebaa88c85de0b40150f43265055f32d0f070bb81ae6a7aa636b661a7afeba39d7f34ebd40d4e7e0e4bc286d03cf966303cf763d621b78b69a06a29edede6cff4e6fd274b0c739654f0b22faa3da49d7069e2d88da398fd53979a7817030da2576edf6c2a61a906703cf56e31c8c869bf0a0d560f8e11d5e9cb005f19266e39a34c5f587da15a7e8ed757bb5beae046648fda4f1006952c77064f66a2dfa0c4c5d175d52d7553c1a3b65f662ed341d74ecdfdd25c52b36c048f0bd47e4f5386adf7b1778475633f6a031461a532f42083175f91d81ef214fe56c94f3bdf7de7b6fbe98531bae20c4a9d703aadced1ba900732dac0821c4f3bd236f0894f7c284ed5de57ec0c776d9a5df9dbb734310bb2c98a04517a05d164db068cc61328310ce534a2785134a6b53f3f06e62f99958af74d3cd4478b34e6c688bf8a081eea1694e918eb5f34ee7d48e973705dd9f13a84a417c2359edfecc802ad77365e14374496208663046f6e0c162b38d3e1da882458460f5e0b1b5d868e419a1848e6c07e483047a60b15824a011a207168b958a485211bb24384a40302f676afa703ce1bb83aa09af73db0ffb90c4e6831baab3d550cb8e91feb4e867af503d26a3f7a4d89edf92244f8967041a9b19f619c9618dd27befd8bb1b5a22d4eff9bc306193b88883799f81f5a75fbf255a74dbd3aedd12aca1967f2d310d88caaf3f20e9849abc5cf5fc8c340df243dc8f00dce5d999d102b83c0f3b3c3578b45cf57071316fe88731bf7c0b8c99e1f5f2165ede4b9cdf152f656c3248916cf3965150ea4d551a6e4afe35eceb66555f12aaaeeba91da7e142eca02100371580d354fd7f2f6f4afee52ec79c445600ee8d6c0a03f096a0a6e1005003220191702a085bae034301c057b00c180addc8fee5bd91fd724c74a516413e5208094133220baa5a4bb47a47bb56125a3446ca524ed26c66975ee4bd9f9ec792965aa0cf4001bc5c24ba530ba1b86da2190455528844d3a78aea14593ca5b84a603e7d2efa0e931cea210905c6c03e06a383f633103ac9366f3a9e512bcf1646218a5774dc45998de52eca581906804ac144e91387a6cf713cdbc6f1bc358e6754e3787ee358e15903b603d881f3b6c1e0098587c89e5e8894a5d3e7e5caa02ba5b8528b2b7d7e4ea701e7ad4f0f00feb1f4f24248fc9040950a064596b760190e009c6de37b6517573e9168e4384b8ecb70c578ba0c38db18300b4e611d18f5158cba628e9b65eb744d37dbbee8556e26a26a792a7a15dd69d6a61e9184072d3f5fcf4d3d220950cb6358f62c0dfc10ed64191b0f7b7b0955f22911fe0c9a3e4bf868998331b51d1c69015de0a714d005be8b86c762e80a2653c8c134d9b2f49152c0181f18e32292282387a20bfc634f1c8a32d267480e5df5a25fb25550256dc471238d542a95ea511d5e4b3c671054f9c820290455f0191a5d40177869068a8c86528c866f63cbd3a7a1cff4b19812d6c61e9115c51e2530775a8de5f18aa312b127cac060e963371f1eb1a707c62801654ea58f74d2ef6e064223bad4ae054e9ef6e60b84f9a2d5d8cbde180ddd8b640983ce8e8dcef1c9186bf40fb2d7884f94b039694da1283324ba40685b5b13949309855e28c8c76adb50a80bbdb762c5ff2d61b57a06be84b164be36b92e7a185b840255f092258d4823640f92244ba0aa88fb2149a30c13b5a878b8919661a267d4338bad53ba63eea56e62bfc30885641aa13496ec588b4875f1b0393ea15234bc5cd29249c735b6e806cac88d904a409988067481af88fb21e393880654c1b8460a360755f10954c1172774f4b21d6050155d74d1bd7cb1cd2ae5759dd835259f574ae8295622fac43da00ab25847e44dcf6402c3de734e4ae1002beb32103bfd9e1d273bceef22d838f3aeb13c444fd8f63575d88a5e2f4e4e10af87682cc341bc862dea1e6acc79382fa454427b9d78bd6225da9f5643e7219650751b5fccb0120651359cac56abd56a05b4eae1b15643dc0f1c7b98821fd00a08a8070828e2d4c3ceabd58156404db00002c20268b5025a01ad8080562d69e06a02ad7a4581269004025aedd063b55af5c01e7bac5651a6842f57d646fb4c04b36bb18b44bfc16e8fc95b9c12457964b55a39e7a4879593d50e3d56ab1eab1e9cac9cac9cac56d689939f56125758fb9ae2d47b3d266f754ef48b5e27f6fc4c14dd7cd9f0a9977a18ebc47e4fd1679b9297f8e5c9e6681e4e517c8355666cd9b692b8e2a9d48dfcab02e65af26ba9e261bf23ef012579489044991246a1e20b9234d007b4633c62980fd9842d5e3e657ffd00162b49b992d27dd821a5a75c74739116fdbab9080f25d1b1a75ccf445727e6229dcaae019dd82251ea7ac4a9eb50f544d72ffc88401544f202d7e59f2604bbc479a405a937fdbaa6a75c1cec2927dd8c9df452e92a37b572d7396e6fafeb948ea76eea06bb8e63d781532b18c84eab3c7583fa76d4b76f34479cb321c7d3b37c065e475d95e7b82ad74f1727e5aeaf9b70c67ea9dc126e81aa79968b737dcbd7e945d7078e86310c48fd6bc2e65a3538d2f556ca2945a2d30c88384540bc1c665a2463bd3fe8649da3807e0ee6ba0eed1c0534bc3933b40f1d7b9039381e1393188837af9be12a0b2ee82a428a43c046bab5f51785b28e24891463e48161d9ad177d0e06bbf43aeaaf63f6c2ee348bd1b6b2eb8dd9858d5d59b3ec3e25b2ed9ae88e24b62c9d8389dfd1822db3d8d3d76aafa8136f1c6c9119a43eb84cafafeb05ca7699a08a458d2d9b7e3dfe5d9fc0101618f31270e434f0f11626003e7e93f733ef34c5521280d7fe00780defdcfcaecf5b775a745d93f9299160cedd19634bc76a614b4f0955ce478f39a7291fe628209350cae7e668b620c618638c2f4241674e18638cd147bf97a43842123ee2832fc618231154bfc7f85ec6a0420944500d71eae6e15746ec42ebc4fe7cac27c06350c6bb86f24f9367b158fdee7466478912055ed94e7b4bdef4b11f9a29f459bdfba13dc618638c38575c9fa605c15ea34c6328d36a2a8d2fd60baf63250580fb96006096524a2f47a2d45afc474918c7fe223d1a849070867d9d86cba10e00ce35385131010038ff8b23ac601db8d68ae5faaacdb4668fb0fe4558ffa274a333bc0ec4217d88ae37c78e9732beca353ac347fa283bbcfe8eb31c5ab9dc9594e7deaa29c6a9bfb00eece844c5847e6fbe996fe86743bfe7d5bbd36eea49d9aee870bd479c5f63ac03db3e1803ce56069cb7197046cdf05f7ccf82730df115679bf82a24bebe4b341e0ef50fd35a33cb6146c2a9277da409c96286fac5c733e018700ad7c3f7940e161c23ce926acf5e44c5e788c7718a37d5a7b0caab10d36a329faed5d65aedadf522c12ad1b8f13351c7d5be72b78f6e86ba392e8e7bba2a178bd8c7dce6243dd7d0b3a6682935a8fe87df7befbd12f6529ec538a2d352f6b10509c52c8b19ae447af4f54ca44776e1ec5746717e19b63425ebc84ec1a9cb87386ba841a5fa51a86d1ba2af447ab47d26d2a349cf2ce9ef5976f68d5e0b628f43c2f9554d48d676092e71aecc8933911e4deb651a0f074baf65d9a95693615734a94824ba4874592cd3783554d9ae65e2f713503183245408f5aa5d8b0a17f40c8c58c2fae9aceb27943640bb5615415d454fabdab5a87852854f633dbd517a49c744daab37a29edaacaeebe57b7f2f5e5733b1c3e6bd8e611367af2fd6381fab0ecc2ecee843f4ac77b2dfb3fa0cbb385562f670b08f4a42329c618f5ec219365652c15907c688d517310ef6d1f3c35b4fba23c410457ad63c829ef925e94c1f2f4ef621fadd1c1b1b32ff94c8899d9fd48464d8d95368c49e45af15e7d75331ac037b8475608b70adaf669fa3f78a53a3c7531de61fce367f1f0263e2ebdf9187c37bc5d9cb269216a4fe619cf7eca31a4fb309ebc0ae5789b33e159c1d1941e671aa90ac27ce4060418d61b347d735ed77df6fbf6741e6afd3fb0eefe925fa942b722492ebeb3dd29b7fa43ba87a3ab031fb397176644c9dd8189e3ad4673af1914838553f3a9da787fdb263239c75a2e8279da85d981d1941de71329ca72624ebf7307691e80f050f871a11eee96bd2ae19046dedadc516aade6ba7d9605df143c1ab81e221dece064b5460ae25cf1fb8240b23f4b4cb82085a3827edb228c24fc31ff723b21ccc7bfc892e536cef130c507c583bacf1c617ba60d10c2d1915018c2d7a58342f88c5a2798fe6c52fc400430b16cdfb6b459ae7b26d92234b0351263e89ef1de941f27c222b2ef969f22e9db060cc9128f372b004254d68de63cf9328f3583322914f2290174e1e2b47d6eb7150dc50e7c89a3f53805acdcbd09417b5c3f2898309723013c6480cebe96610845a8d7330eec151c4d81107031f8c72d22964b108eb99420b2d25432d25463ab6a670a3638cd3612640ecb40766d076781a0376ee2e10eff03c843647e368f2a60dd140093df0410f0b471e08893d3043bfbfc72022a608eafaf9b4d71c043bceaf539e3de74501723de745d12e0e9b67a3f2d1a12644e5a3e3b859fb083bf70308e760f2e8a59b701efd3445ab553e3265edeea61bc4b5caa126e45dc3a56ba18afe90fd071ddb29d87fd0d97ac33aa826e11e6a6cf3f2a35ab59a511dddd71903766e44b0491260f76dab234bacdd36157c67a2e966d40a4edd6432994c2693c964fa4c5cb9ae53a99b50a9cfc0959cdaa9a36eca944ae194093f23864419c8b276dba4bc9442b08d26b28ced88ca4d972af85015b35bc2b61d715a38a13b24ba4819a28c0f29ef1502aaa056633a16c37d7d2f9462884549f89e3af6948aca8acaca0c2a4fcd709500e018b28ebc1e18039bc57590d82cb80854c9cb70874095bc0f89da3619fe341d64c7d03ffc0024b21c889d269b8497af69387d0b0068c0ef2700b8050300a36ec2d9b669055fe5d8caad57b9efc749f9644a65e5a6547ebdaa5cf6ca532a2b40503867d771d353d78ec52c7551299c5fa78ebae9aadc5ca455be72b3ed95151d57b9d957ee53a6ff4095e9eab8d36c503865ba6c95a7307e2da8d2896dba8e9b4a7d45a54645c58453297c95e7f7b372b796ca3599ae12fc2dca40564a0e1cd7b2bfa38ea95ce80355f228b972d38ac9f4b74cada470ca741d5809009e32e11bd92a57c14af051181a81ac2803004c9f03e70d077ec31f168c912669ba092bc15779259ced26af6d0555f2450af93fc8f7233f9bc01f19208e3330f7b2d8e4b3cd328a261d37803918859054bd9e10c279da36cad8973336788853f04d349cdf36caac6e871421694fc56738557b40558438452aa2dd2150d58a42a8e3b33facde1da276a8414822e114fc082b49814ab66731050f892ef1a8269bddb44a9fc562a7ab3cb594d214ad975a5aa356f32e9cdfa534452d4ed1533a2f29a50fe3541d1ec4a094d74919af79bdcaebd6779892d784549c92975d7f4959e994b71207111b07fec51e88de82c248bb96cf1a2d1fa1262d28802eb2b69f26fa9c50d8e8aa13bbf65063bb2610fb9c17254a94283ab1a7b42f880ce41dd73350084dd14f2a7bb6c42730983ded61ecd2dbebec9d84297bf7947d3db5972d3a661d144ba050220640bdd2ae15835fd86fb66d2f6fd681ef98944113070d206f139fbd39a509697b516aba5f3735ebbc9d38832a2a6c3307718d43244ecc81f8e7ec240206663ce146bb5292264eb49e40a371bbd61342d87b59f639b3939e32afbd482265d9356d5e9d78937dda64d933fc94360327e998bc339523d2ae133f9a4a4a774a52b0783d01d4f3f40542499e34163317658ea4e4e3274ec9f80285edc967f2da67d7dec9cb2b95a47c5e2525550a4aa5baee3aabaee866a913dbe21cc475c5390a0882b6c4f23ab4656ab6aa110763648e76323b38b1c4b9b89f0cc814c4d2ce09a116fa8384aa203247439c39982780762d2766d039a55f6f0ee65d07986bcce97899c2a61303e61e9fc3f03949066a8331442691d7231f4edd3c89755e47ec5e19d8df17c03052d46a20561d849ac4f27d0756e72e937ace64589e4d3231c8c8f0dc320396e18f018562d9280fda049496144f1aa65d2b8a274e2069ecd189235395831850354b10e6f86a2b9d32c29a53a465adb4d504d329237cee87abaee6d486540c15cd01aae87940d5d4d1438d0d0b823de2a8ddcc4b9cbac1c1ae99558ea3f2d2e361c4593ec3f210f5ddd6ec22d7b1a48283788d7d06ca8cd9c0c6306d0255f4d9a5622861b3d9cb32dc3ca08a069a86af8b4404c86cd0b64b18534f22d926dda4d590ecfdafeb1d34c8a91a10f7468b8e1120c3a08c3146e75a46335cd732dc6671ade3ba5e719de3bac6e14e373f349ade7473ecfc847e78a39bb34eb9ae371863ff9e89ee6b94fb8172302a59767770b1b9d612dce80cdb689173428b4eba26d915bbf93a96baeac334d1b13f2dab4f89ea7befb2b1bfaed798bdd783d85f43ed264763387fa045b8fec212b654b0adc05c4b86ce88255b7e46748cf1a93484f22f2573228422794c74494a61a539d1065ede07aa648e64b192689df7d751bbc9d10fe70f48d681b0c1c7c8ca1bf4e1c1dc5554e802e6acf377f460cb3646333ac630dca865848184be92ae4b0963b22b5e87bfb0186874fcc888784c8e91a4b5e708e308184d9a8c8e87a4d7560c3762bc133b66b3a96936f394be6234d36cea29ce152b41d18c3ed36eaeae38ef002325d59348a40b938e592dc8f669bb6a3538727c069e6c725c3b1151cb67b7c9b012d4e5536e96b21175f69467c7b420ae951c390d0a0f21a2a1813ca6dd5c9de1bcc3619436d7754c94892ea601797d3d47a0530e7f69589672a7d9c4a788349b948f7e6937da239cb738a2c7bfeda6432dc876a3c51c18c7cd298d1371e63bd026524a93bedddc81c6b99ef280efc0891a28610a3f28820f8d732e2aa79acdcd22959ad29d76337af61948f3759c78fbd1cdd7ed556e26e17c1dd60b873e06e1ea7c1dcb325f27dd6937f96ad16386457726a65cde0de3cc7fa02f9cf8149caf6943af1d4bb9d7b1a7a95cbbf3d7c5849a3e75739dfec299f4790ad4d8b7250d0692c67e1d9b5453c9d771483bd767f61a955fb774ede294aed97cbd9e6a42e8f305e4faf64c03723dcb6eea86f4eba45f38a5f294203b7d3def744ae5291bd24915e7f9d15140761a754b77231d3b09af7c08a178621c0dcfd742f408aedb3b445f3b2d3520d7a308cbaa106d4fca46903343037682d0d8106d45f8ea3ae7e7ea6561bbdab5c258d211978880b9df1d5f00b56bb5c8689976ad9614edb49a77c5d66a19d1d9a222744f89886d4decf7841d38882fbe2f76e060cb5b103334103b30093ff38f5229a994d339e9e8740e4239674e7ccf4518618592dea5e884ce1d42483521f2b46259e6dce7a4873745a79b333ed7d465639dce51eaea81d8e94921bd91b821760e067e62f7b015e4f76a9e76130fa9009d73ce39e79c736e0bcc3d1c5e3b8845c8057c38e447af233b8beea2f40312fb3aa4f633ba78ed9d68de622a6f6f314e4b1833678e9f120ad1f13455aff9949d534609e7d38220c108f8092ff1cef56a0bb6186a92764dbb2e91e8128944a24b04b52014622dfabb44221186c9ec61f83932600dd1ca6c8aa896b5e38cb22cbb62cb0e8f338212c6d4bc4929bd70c38b96ec6da8736a07514a5121a574bc0853c94437b399765f6fee8776edc20eea20688a7663a7044137271d4456723f7e78acce51406b8fda81d809c20fabb563a751c763550be2b460b176b0e86175dec182c56a20e20fab359c258bd53f08b15a5e47d462b56613a1b03a274689d2d905b15ae2d2abe1d560832eb408b64c713026a88a5664a2bbe367cb1b8c3175bc2eed46f42ba54597f9a59e7689b49b656b97bf6e0a1b6529aa5dd793971469371ab6412210abe50fab25ce895058ad61d1ab21da5743bc0db6cdc99e9e2cf3f13961d9493b9d4ea313e9743a6da7d229e5a4c2c32853a03b63f4242e58741b91b2ec66521bb5e899949a26354d8eb4ec224cab79686c5ad67e65d7afebb2234c864cb6e8754aaad9d04b9cb58f5e47c74677470e36eda36bc7196937f4a447cd066731f2a4163d6a35a2eb5a4eec0b6721fa3a76b3cca3e7ec993ebf8f328a3df53029af9b23444bd273624b1210dc23327af4ac5d8e8e8d70d6b01459edb2c545ab479a3c863bdbd6def5011663c4291bfbe0912d9ccccf3713affa4c7f6120a28e0e068828553110513f07f3449d1bf66bd733314788867f1d637ced3488611298abceb423073bae80ad230cfdaee5eec002de20e30e1785783b2fee3896957b64401cac118d903e930905aa42d6c975c51aa223f75df192b8160ebab892c9830274d182723484aa9193326eb07107a93e61cb811b94a7e16d4a06a10e90b4ad6434bc75972d61676073e6bcd39c0a88769038bf08c43d7e2606a1a78e1d18b483424fec1c4c970007422d1d8f79f778238e774224ce423410f79e8151cb2962a4042460b5732fe21c213ac7cf1793b87e54e943c6478d5c8f5447f67b662fac0365539900d1ef8e27a08d2e6f070bb61eec7b37c196ddd0456402f026541bdb565fb17df1c2e6fad12877304fc6045ddedd0e24b64ddab9fd3161e3b157ab68065acc5a6b31767314509fdd4c04c94b0255f4bd676f76d6fdc1f719089934b43b9cd8ec77f86ceef92141122dee61f1f5bac97e74c7130f66f8c9b650de2880078ca1421cde42551686cd459787418cc75139d4d3c79dba9737b634e4d04462480f9327b3a75fd0903969cf9c53f648d9337bdc4e4329a3504a295db9a6d9a41367694538675b86b3a9294b531e4d6feed1f42f6b6c19d57905af5f9f5826baeb1e2debd3a8a59158f28009943c6f0f3924d39068508903a01b30692887a41c822fefc0fa640e7ade6c227befbd1546c1b0ed105731fae8f99a58ad56ab15b518cedb8631bd832b1a7d94a438020b3ae294ec88239e40948da5a609ec4d343667a10aca0763e8f5ec03221f3f2f8ec4d004b75625c4bc2d2f6e3c7a4d79e59a05aa5050b56389ed3d23dc2049cb6330ef36eec7c8fd78fde8c5a93174e6cddb632a979658608cede9f9d40dfdbce9b3747b337db61fd53b072333cdf4a73f4d88b5c2a7b1d3d2e9ddce42bafd83c954c83c4d390b76fb472f2f6faa74156afae9669bbac14c38557aea4645bb8623e5a50b64a753308ebb5d1c12c6fae10cbfdbccfd7899fb01c46b9ab291b2633bcd66634156c35a6f14e243577b1ddad70fd775680f5d3f03ebaf9ba3807e1a0376ba62e778441caae530d3cef1c8f45103426fa8cc1cccbb7c97aec6c6c1bc0ff1764cd02221af0cc3eeebecf55d594a99331de982a402b007bd184d39927213498947a367972da311698ee61ccd3b98f7ccb6686a35d76b3c91968e8f05680b6674fc23d272c302b48529741cbda8851b18d1f0703b69a765479116634c8c98747ba8b1917e3d4ed2ef34d296836b129624b95dadc652f8aa331bce2967b03ba417cfc038d0d238f5d8e9c528cd2d4def30118661d7755d38c7451189e867a2c44e27075a1a877eca3baca55ba0dd01838d3eabae430c7bde5a24822ed8457f5acd756d3fc80b677762fbd8d86102ab82f0999d4d5b3de9e5c0aa27c6915862fbc8b8623d07508de3e24587d7b2b1d9bb862221417000d515e3c8536cdb694024ce6013d8bb6bc1de9fe66060e660e0dd7d429b6bd50049d776ad9f1974b6ed7eb89476ad1f24eda0aaf5f3d30eaa8c60d2416094892ce569ece130677e8e7446758c4d3a1e6503289114a585f8cdbfac13b31d48b68c42b1dc492436106ad7aa01194d8076ad1a50d13b4c0b7740b1dd770963eae5cb173679b9c305db53e2217938bc9edf215abb6d28d4af52f97859a8c19296d702e6e056ddddf1c4066fab0e543df97ee0a2488a309c571c5875dea17144c7a9b717e1bcea7c817e4474fa15e9775474817777c7131bfc75120f4c33b5c3201ce12c7a466d8de19c75d6992de54a0e01732d311ede69c162f50f396e88c56a9d528bfe438e023a3a98ebf5f1420c75e373dcf8d295d7d4a4eb5337f255c76bcdcae3757d3ae6346b45a42c7f41e9fa4883278d5d1eab19d56a562e2f8ec73b3ae63420cec10809a8fea8946d3595412d95aa19090000007314002028100c088542b1603ca04892e87a14000b96a04c705a97685112c328858c21c418020c0100801190119969053fce25c4d67c696e42f064afcddd82630290084fe9f6fe1907fdc6de405449b7eac93309e0efcd5409c3bb086052a7502ef3c405de888854c4f1402053bd0fdd73983f31f8510895ed3b74d4d62063f0af7fb92638804a34ed455e8adad1f42e62f2509f83fb4ebafa34a145e534e6f630ccd0d50c454f561bf3c6be0272d22eb3a3a56719a2de225601ba184418326490ff2c5cd48412b5b81731314dbf194a0ff39ce45b89f6dffb3ac68b383dd040189937fb22709881d88bcd925561a040415286c72beac136199884c6169178fcc140bfe4f55e2e6eb08d222ca2bcd04de3ccd0a565075b107dbfa62f3be99fdd841bebd3ee37da03bd6e4af0d751ed09f24910b23c69dfb89983c4e122571fa0a4ff5cf74bc114ea1c2b1f5e41fb3020d515410495994b8da542796ce3cf26e0f4cc9d89d0e30326d2d5907a3d5e447a2ff8729a5c728d8c932666e214acb20871b250f3c85f6a603dc8ec8e1142de291f17f2d73db1d63de59c39b38761716a22092fec8f58d38e0874a73f5e6611923450320187eb4d2937181aaa7b68452410737ad446a8a498a865c1b39e6e549f63a33cc282ecd447a65afae6d229ae687493e77245983b936ea9279a1b6767cb7b0e09ca2001d153722a53ed17f7e80c967e66d377a219c6ccd3234967d2d9831cb6f06ff2d42c59699fef3faf8c60a1f954cc0cb8437f475c5db8a59c2f89e00f9e0fda5f646b3dd7ece111ce13741df070994bba98703b1deae87aa97e8a99abc4181a718dcb8dfa7a3e1af02b2d632d0707304b1b899682c67cfa37e8c27a249a3ec5a862be4aa9f8251efcfda6e03532f8385b9d570f673f596ab2e769213a6b334ce3ccae710603637a20003613ce4735657139049cf61e69fedf067d387341534b72dc3414cb3392182b4859667a213297277a293856423eae55378512a1417ff6d79206272bb9153ba96c2d6c9078cd9157653025f1a86941cf08707d9743067a2484a4ddb7fb526940311eea8e90dcb74828264e016ec2c173ae4af42930768e113b5fbe0ebec912194a3b6bc0d6b18195aad101895050ea84d9670a73a49da37d53e33fe7222024617505f196a36618e341937546f7cd227b2910a8edbbdbdec3d705e9c3dd0245dcf8886b03330109e856d262bbf018eed402ac06ca58c1786bbc1f0f888487b5ef21baeb59914acec5e5ba80d0932a7c21403e2b2f3044e7cd01a81560eb1fc729d98faca61fcc68fe6b6f1b10389da2ec8d3f5e2de38d1b02dae8be3ed4d03c525f535656308a5465b7dd88ec9228380b1dad21161aecf31c8492d388d03e158d05accc23aba4167e55adeae94a6df3f672f40fef9b175be2eb6dce4863bd1e1e83044164cad974237140ffa5d85bfb31983742516481b8d0958b323fd80ba83a8e998b67462581870b3b557bb25a2576e557719499fef73a4ad4d773632ca0e71434d5c3790c5c4fc3b290b3ae9bf1889bd688b6e4c9660bf8d816872c61c59c0e5b13019f3a94618565bbb24ea691dee98b730ac085887ea57ab0a5096c476f0cb13b47c4b6895d355c810fde0212f065c024e640fd06f5c6aa160b8f8a8bcdcfa5692fd2a5315298bd474c37d612364f52bc936f1eac7273bf64aa414629f537456d1f5615e22d0e4889def116675da811f3a66e3535655ca8967f4b11aceb8a9d81ce9c7bdde2fb84974eb0a46ae0e68ec209814738b22e6211da0482abb8eeba221063ed1f589ddb57656956f2d59c53ebd690816b36732f412967f3796121fe19167da8560d92515cc4c6003343520dcf3fd88b53959c1d96b9740e88375e9ef38cad4eb1a600033d5d5474afad541d12d105b6602e7698c20ae443d57a995149c390c62aecae237ce5d448ed0028f0b5e53496f5376b8499840aef25eabe40fe99825c7156c706735d277500f7eb1daecb9aa34808a9b1c5cb206c805cdd311826b5a736d93f4a667015a898b662ebd149749e4f7b28dab34b33fcbca9d28cc8596d93db951633f6ea7505776699d7d88210c153a3a46859cd0dd795e00aa2905626c52fced99d797594772a9c4baefa10247e83073597f906357979c7283a4f2b777d98368f8bb9c8b3758c8810d75b3d31f49aaa683a4c6c7ac333c246513353b54a9965aba88a47f39daacc190b14e946fadfd18f1c0e2d722a805a8569c811e48dc2fc4b53a69fe7102eec9d74a409655f613c36438d4cde2a6d08c09d3c43d35bb1bdc81c065b6ad0cc657aada0d2887ea55964ae5a8786bf4eaa6d4400fd820fda2d4bf864f230de2f0e34ddbd49a57919f9e8b8a5e6c6084aff16c0768c1cde968705ac2cb8255a4ff9a2a6970c28917f11c6f22fb10e476a59cb2b5c349722c349f9d57320f797819bc53a5d68f3199df8627c02a46a59afeee0687ed27645e54a6de83719a6b18505b4ed16f2459f82f9e81958a6ba10f95ffe1c87103844892c2f0b403cdbf5772410a38426ecac0be8daf541e316d037dc5ab6a540bd61d0300e2e8741c10bc42db43c21b2546a3ab049e9ba81c246a29257759b12d1f284dbdf7dac4eec1a5ce267574b32ffebc05493ed0aa3532810751a5d730f8f50ac4d33b94c65268d1d5734ab5fc7f73999f20fcf6ab1978151e175766ed1c6de99f5a2a7afe00df11798b587a761748a9502f7b93ab5500563e9ba068df5c0c32f53cc32bd163da377b0829d1838fd53c5cf945058302d845ea0ce29550a9bdc66d24264c06a51ba47456c50e85d02403d2267a17ec9010a7ccbd68ff0793b91c715198d1f9114120066487c779945bd7377c7324aeb50e77362218034d55a087146d4f31369b24269e10e26531497dde49e6a97a0d3a767502d451a8822d4c867d4e2e31a6ba4b98e116de9e65e9448d2ff0904a4c3f8f6b5e6ebff5df3fd7df2fefdf2fefe79fa3d7996dfda07066683d505131491222195936b3127f5f830b3effb21cdeca2659cf9e69d1e8daae8fd74b66d8732cd4f84d6185860cd17b5156343617e5509ebebe98b039f9b7a15dc618d745c16e3621a31a0405c7e3c467095badf50f181f310270ba645622dc574afb7e6eed4f6771c5476624e4103809b304e2f4e636879f11a42d742c0e9dd4e6ad849a368ed8b9d3f2d5b5306a20605df450b1a479cb0d38e8893d75629b924afc343758fad90300ad8fa7bef7274522715f9c027e26811506ac5e751a5313e7a781c8ee692a8cba5af471b6e967ceeb72df7ce5527f99201255d5af246febdf7b505b16d2091cdb306162b7a2f897c5f17c389edda6308a2fc0e6f1830a95c11a5eae680a1c46a0d539b4cff584fff10b597789951cb5b86002317c0c53831d9d8f96f410b4ba8ea150319c37bcae5bf3c314bf6c25740b45ca697fd99295b6ab3e08190fc8c2a9362a1d28de336985a3e42a6b65102c4377321597b13ab33e214c47a8e0f83ff52f1e602d5aee8b3cf1219802d8c323aa6a45ec7f514f84a92f5c84d5b2a742bc90e8bef63b1d80786572ee6ea54fdb56f34b3efad13cc1d9f258f95ab13afb59e8e159926d191b455b6fcad4b1145f9e562f53527bcd3ca08597754fa5c6a0bfaaa08c868ec0dd24d04f2428b35797080a39724f31413b58891be3dd63a1ad0ef31181d2dac1818df623b56625258f7fd7fb2bebfaa4e6b1bd663f39965eaf523444fe8050323289080312dc5ce32b3f9a3a94f54a980e66037d573fe7e6fae42372ac0ee4a8970b75d96c2b0bfd2a2595ca8be35c64154150855e8350309ec537c474266687772066233bff7f151b5ac55d8f2f212b7c335a02923feb09c7fb5c4dc7416ceda71347dc9427fba27af6a5e0c7a18315e6b0985557a033ec061c6c747af6e0ba9055db9a678f22c5516ba919e6308416dfb95a466fd5701057f0894c1737a5ba772935d66082cb603db10138c6dcc2afd63d4cc04a27d087fba2a30ab94a2d9e040cc2ced5511378e76ba88a3f902a3d0b34dd792ce0f5405cc5df3207e4d4ffe85e7082d0a4dd690fb5ce55e57716e73b48486b0a024367a55bab9637daebd4aa291497decf0f4465eebc01ff94ce8ce0df4dc8295c98bce9e9f3e57f9e735003f295a1635eeeecc0694b65c5680068b6503920fb431c0e43b900605bf82edcc5fd9713dbd46b1df79852b1dd10ec2758a0af4095935627762f3ff272eb0273e709b40603fb1c03ee1c06c2202ff44efbf279c02bb4c34207829aff4ddf8aab72b14d6c773ed7b4f6839ef85e0d039d2a521d8c77c6a9cd09c09bbbc860d35d06b141dca20974c68822e3a67457a139ba2739829f1c6b1cdfcf63da596915ec19262a6617d982d234e70419ef5c26a0a5b04813fd4d31594e6b27c1244fa0cfa1ee2b06031610b8a8e672f7a7f5600d7a0a92119fdaa9f650bcb6e55652d34a5aadb8d55f4753ce84f5e442c231f37f06c729fadad008e7e705f10b0ed4d6ba1db935e498b80e4b42b3d1e48871b37a193645754227d777ac0f05a506cd18ba9b2b16cd4bbf9cdd5ecca9a45221e9d243832650a48362f4721afeefaaed2fdf9f28da151820bbf54847ec27637ac257c1e087d1d366eb28264bc707498548e6def1bd650a751ee7e7cae25f285563e853f6b87859503d228b6e20315dd254eb840a33bbb483b9d7b33b2b33af60ccc26715100e9aa005f754a41870aac9ba6d2d6d6c3ffe010dfc554d1c6a0cf706124a58156a52f27baed0ade1c7c4c18cf3a3a7d136f5b37fce544405a41451bfa248bce823330f7a2fdb5c4419b242a8053b96a1205719333034f6f92a3cb081a5a88a71d6f475474205257f124a3b4f89a3958e6e279b464eb23f80b3f4ce9f1da13bdc81661bf2ee3bffaea23162b9306c6900e917e07222011421cf8fdcfdfd5043caf7e1c98b4b29caebdbbce45b3a9140d9d24ab2348dc0b1870085b6f96a39d58379c454e00e54cc6676c0b053e7f4e9f00327185fe9064b26a23df490760e624aabe16a82668893b3db2c7e310c8921f02fd3226c55decc336b60b5379f83aca5a9145dccec3c1eb7189def9762dcea975f40adf9a21c79ba9a382e0acc9180b407ae07877a03cdb5d48715a1faba5a15cc16db4aab83c503eb238bd84514f89647824b79dcff8fb04e793784c8508f54f31ca4fb0f6bd2e3f12f75a97828a5c453a9f375078818e7c8261a4ccaab5a93cc9bc81cf9f84e3d554b30e60c4d73627446482f0a7f5ffda821b1d08c9d95a2397cf990aa3b6d739711583c09cad8a1c0ecc8f1fd2b555322d41ed80a716bab5a6410a07f2f84e5146075993b0d469bd69b7d6141574583d0b21d903613c2fff59bba33ea476bab62f1cc99edf477da5875559f5b0f4e86bf65e49638ee1c69a0c419362060fc3c72b89acce8e9c6b7cc5f80ca034c0de6b71efffb105dbeaf2bcd1cde4592dcafbe7787a3bbc8e8450dad94f7fc3f0854c535f967aa5974bbbf0f786c8a720aa2615c784fa21b9cd7585fe0097d71392859d99bd8c8f38de0d20d8b597cf95c9b91abed27d7653764323346d8bd4c71cb1c52f507c84de450a46bb30b1f474566d83c7e6224f74673f8b3d8aae64f019e2ec768e6ff6ec726db607ccc0f553c30d2ce58f1aa860b112e059d1a8846caa9184c21f3c0e4491aaac79c6f40a86c4392b11618a5f365b781229edd98c4a4e5bec22a401224ce70558da296ffb4f8420d67ee0fb327cbb84cc10630edc1f5c5e153fe888a47f471f2476c0fd030905c66e74a76de30f19d0bbedefff00bbaffc383de0f3ae9680919e31ae40e7ed172fefc2489c7ce07bf67fd9007bfbf45254ebed67992f71f3070925d84dc0e4a05287f3cb2c48b30899b9ea1b7d8c861370440a893cc00600b964514c8830a9bc7a4abcc29dd1149c1f4f78bbc2e0e5efeafefc4cdc5d6c2784377636cd93e8e73bdc537ada8bffe2679a1f6b552c8d9afc8273e307a631ff6a9356c8a24cbef119082c0c12accd42d760fe392fb42cd1782eaeacd042c803b95956c532a2ba6025838520a4d4dff7d235a406668a5e05d0ab548ad4835d6e9774e8709e9a8cd0c24f71f1f4c5a33e1a97b5c44c9abcd82a95093a4006b0105ffe430e47e28229cc2452e981b598c6426c6d7bbbda7c5fd1476b0f5ae602e2265835d2123c2b5449ac3bfb78c039a4b918a83ba808000ba1c3971644105c7f9113071b183a24aac97eb8189424b95d4f8359812b25d6dfff2b1a30bfe95a9ebc5ca3ed3fd4196759fc601a1f94f5d61b5bf4a4a36e6e0ebf64d12d8202de4946e8e7b968793c533fb7ffc0987fd3f5c4562e9595162ba0309d77c6f0617d14ac61a79d23bcdcaac193853050bef87a329ac9fc3976f8bc12836e51a3709b968dff14478ee6b7520d91612c56fe162755dd99cb699e7cad65a0504cba23164128bd93b32ad9881d7632a10ae0875166dcbd9ab2f6963432582d5f8abb3282c53dd71aa38874b8978e31b1fd2bfc7fb6aa00adf0118c62d573380e37ff9a07028d0352276e3899e70cf12567581230bd20c474ec6b062c33758a60f278d772ddf1608e17992b863d48fec2f3b6341dd553d43bdf2fa0481876f4a87f55f0ad03535c52a87906551b2a4f515ed39065ea031ce5f17ff820480dacc2e810c998a2a0363fec47979ee624544b17c29f398335aed828c122e5bec01e7c3968f6729810b3216305569d9c00679a144f11e522a25ce06792ef6c74b726662ad8e900dfd4e077224f44c4207a099cb6fcfb1622fefe750a4537d13a2ba335b1ee13c67bd0eb9c519a0c2a36edf84f7770bc4da6ade954cd498d4d755868ccaf5bb0bd60f39b686076b015077b57646c6be5cbc24cfb7bbc94eb9a0281c7ea4118df0e9a40c6a2cb35eee7bb783bc0e7e43be24046fa79ea027dc21b51d80acaa93e78a7c292eba828177641d7538cd91791f8c1102707514f059bd9522120d8cad12f2d50dd474dd4e435ebc5e8a6b265504f16c16054ca13b3d701bbd5293f11ee1dc02adf67ab6a6e93f5c55cc2f3a78abecae6e6c7b86e696cd0163378e814ba348a5b577537097fc84ffef286563073b578e0a49477f529c4236ba729c18a792db7e490654ffb96969cd357ddbe1f03ea69f7e2c353f7fc18d7a4879264113907b035b9f4b5a5b28fb578c68637d45fc3e83a6e17f9a86db694d5a40d4dd31a306db0264e622e2988f6e41ca7a59fb9703c2a6a7b6cce753b7d0104c12934dcdebf570d5ec96a055b91f9a7c3bb6c5950351eb8564e8301a87725fdcf3e7ae03c0572983531063fb2d23b8f718669d026e5b75acf96cc9b8867c7fcd5e51c3fbec5b634e94ced42b2244fd0fad1d5cfd319df189724fa6c0c3df052cb3c528af3d945f845d228aee948a5917ff41c29a21cb903de3b71aaab49a40fba115b72d023995273572e1b18698ed532f4317e099632712992a550149df06b060095d534049bbd73b378b1bcce360ab11cc72f67e0f0becd51ed3c5a076cf08da15122c4fb52efe25db73ab6e3e09474c5eee11357b601b54c31ee9ba7a7204d37edccaba760388ba304f6dc36d4f7cb681b8e0a830dfe4533cd334fef2ae234cea2d4a3df7e72682c50249f851755475de3699d69d719b5ba934711d0c3fbc0593211014cae81ecafead337a0132f2ebdd1d02683bc259bbf052e4cfae16371061a48262e65342a2c18e575d9a08a0cb3a6743bc9a33b663ee40cb4ed6537051540144d85fc7503611b584330ad171c1829980c21ab10126a798d89897a94e181a008b9d6a8cd64071430e20db00e5b18d7974489cb021b86845bd401f808121fc4c9436b1e8dd3895c1b699cef7bf3d68ef5256149b5f26c86199c535e4105c0b5b1c611878da3d7546a76f31f74733c2f32c72dedc99d018392b5fd65b5fa0acd5cb2bc556196152ec4e90e8ba06020ccc4ea915c1e326d0c7c4aa748171b1e2b4c84f98fbecf91f2301cdb29f6d4c66a5ff92ab5e4bde2cdc71ba414a6f4ae9a6424b3e3fef1451c9538f349a5f51d587864ebb2a5d002c854ecb522076d01d588ac3e7db1dd3cddb61b16a56e89ac801a1978a7ce6b9861f4b180452625108a0a64a15486974aad85d6932b374512748088f54204e5d34ef3ded8a39a9af74e1f93e44a1f88c32daa527b512cbba53baa50a7bba02c35ba192c749f63bd4b0d62a9c01f552c7fac7f75bd2b74f74d7bbd97d053d0706461794425aab0f677908531c975161e07dc969bf43762035c538584cc97226787aa192d80c0393cbc4dbdc2c39091c226ecf4b11fddbe076a0cb3eb94d2655e9297dd74bd05d299a44d1c9a6a57a15a9907c62d7c843f170480c860a198c5a6c195386343f4d52afd38a65a8a4c4284320cbd67c5a7af762c7b705cb4a64844cac87f0518ecbbba4797482762d9ff767d6fd172ac3238e0af2e2b27b289991898b5bb7d7f07e7887e1d6b5bee4260ec9b9e3cc9eb95b23c7744020d156b37c53d726c074d800aec303bf2976702d1f479e06b6e381f0ef99bb382b59801b0ac16f442fe89469cf3a717b35f0126f97c3d0bf90aab4ecfe3f74d1c6be0373bd4dbd5f272b744f5c3aaf7aaa48b77b67df489db601f280c6e53b498c052ca8a6dc478113317562c04049ecef91cbf287e245aca0e30b4d4238dd4de60b7c6d8d325f63ae1639f31ea9e6df7751c200d9230b9712a179cd2c9c0693fd003f1501db3a9dd1d4835f0c3d29331747fa463e6f0943bbd09a57038d909901d472a2d6315dfa68373561fd31db4681eeb062dce3980994b5babeb26132ebd10282225fa2c165f90b297c090d95237db8cf017853ce7226aab7d6e8fbc6e47b3ecc0c22a98603143ec1623aba5cc5dc253076bd80589721d6d189645e0e577180994b71d4046283a011b4308a9ac07773c98a01ad018dd3cd920cbb8d511439c794e216ea236b01455ea7c045f93743e2b4bb775900a8a8733bb0e5030391b08c538f433b80203a57472ca01752387520de00d11f237a5bf9540ad2b0e69ecd69d6910be90cfda09bd6780660ced560856e6990ba265a3bd4f89601c24f30130d5152b9e04ee366c0be52083ab7854112f65527ac679da3598e59e2e4f45d7e1e34b5e0cc6ee688abb0dc2ff79e897ee2e9422f4aad02da1456787b288a3914f1e0028ba6cc22ed2c3bdbb7abaa2392216d1cafc77206484ebb8d98e52dfc901fa7fa651989e695e5e110f508eb740288414804ba262e8aa192a6894d7c6d70ac6bb94c109b02772eba61080d065275715d7fab4629c6d47d71fc4e4ac714ca0099e60754346c0bd5113c4302e2e03d38ea97375cc22e2fe7ae8e06c84b1a24817244123101390cbbab48884d6f84d95acdb8348d33bf76cf464b0de1b37668e51897e6840e9320d698e71a282d4bcc9ca102ee7b8516f3e5b749363e18eaee040af43b4ad31f4434d0223aaa1b845ec1bc388361a1e26906b5bb06173ca6102f329c6a61b246ebfcf4e90f801afa09c7057842a02b90fe415f4b6681e7ff79a68c5fe9c1602e2bf4b488cf5ad9547d12a4a5c9388a0f67f724f95db4a11e1c9b40446fdee12b52350df6a91238834626aced96f5bf8ecbb740fd0c497029e14ce163677ce3a135415c91ba9ff9f91f3b466af99259ccb3eb8c090672bbb4017c4acd0b3370f0fc4b4ad34460829a349061f40005d6b69de758ba46dfa81dfea33840ccd8708f0500c635587f165912ea8840fab7f0900ef4c8c38aaf238572dbcc7650db07bf8b8df38273147565204910b3c9d4311f1c6d943083907359370736370e18768835a00b2360346bd777769b06115b41ba6354f2581d579d35f1a7aa0be7db747da11d5dd9a3283dc5d7265bdd3b91a2c08df78dbd3b0d67b9cb8c27a4f2c3209382cfd5fd2b81114cb489d41c82809d9df2d6222d9b26cb7b963dcec1c77f413a69955b61412744029cb5d8429488b9029cf84755fd47cc53185b26f4b8a514eb8ddaa893167d3671e34c5844dd9c79c00d410837cd80ee18f2b8f96a03f485db70f0cb075ce9ce010f2bdf82121094d523fbbd725ed16179423945c14434fd228c3f3bd9d21ec0cb39ecbfd112120248ad1a60953d6588a6716473cbe8e9bb535e546b9c511498e71b20edb2116b5ed4bb234b7d3cf615d031368a2bacfb425323562b62a8a65b3d3c1235cda8767e6e788afa40fb317f3e914fc5935d7b078cf0d8c8910d0a0309765afa07e96c36596d314b68ecb9451b07864da61c20418fef35a2048a340b0cd646dfc44d981a09444e5b0571942a05921a580fddb951736a39c334552ffe6b67737f6e2b58c1d974e49f02e01a6200c61c521ace76778a24f538bccc3767e9a3db4084f80f554b6e1eb445446c90cefcf5206187bc114c5c8566fdd57d3af1ff383494029edf0d00f6fe2153c4e1e820297a93f18cb72742a7fbc942368175376a093f80b2b07a63c9fc428bfe812949db85346b3f4008eeb296db959d21b7ec7d20c5073740a4e40cfc5e5370d554e9cce070806123e4c69d93b11f8c370d2812cd99315e1ca71d6e7d467ef48e4ea8465d1d943b4c5f345b8733fea9f80c2c0d2d07b547cfda7d7442332f0f6f36b2ab2b89bcb484e1a886dccc1ebff08d519db20f7704f1a86bb1d2c235ab2bff8dcada97d52d8e78e58a41daddb4af0f752db14c163687d6b945ec7d4782d7821b89285c532348ced412e8ec51051db18d75fd544b58332c7abbe4dbdfe780f89767038f696ae4dce6ac2919a4d331512028e3f5533c628fd805c21fd4060ce9050dbfdc1f913d764e94389add33a2049bca12c393d9d1d8b63d8df84e256f443dfc640a72c54a276e7032fc6f4b66fd2a50f0b0917022c16ce8d01056811ce4b86d041ccc68918e6976321d0d8a8ec7b212b48cc924eb08dbd755a343cd1242b82d99b13d2186a8fcd6690a7cd621fbbef99685dbef0c65a6d3611b88573e1ce4537032ca59a3e7d48465f31d020b08834a2c0b8083f3b673a69e891c161f5686f7ef9bcf982f10bf69270a2971e449b5af9d825d7acd99eada65bdba34c9dda18913c5a5b5a6980d08131f0e5a12fd40b955227ed274af03db2d8be35f0c1f3a52e93fc8a92f0116683d818a64c5c1551664e35b5caf25e1d6416a4a228a74c3f7e6a88074e43913bee8a5f1280bf69320b76690e48c8d20bccf5503f2346dd8faf6875bb44b9fedca1ee7a30e0d26797d79a8b28922b4e4328d1cbe58ef96c09aa9d0b559d10749e6d5b99f8fdcc8183d0ce4fd431ff77260f894c5a8ef9d512224222cbcca1cdc2cf0f588cbd6b99c054b80100848c03bfac4b6c24e51db09c98853c916051d6d7a20ecdfc4e16a71805163889bd69de704eb06813bcbfcb4b2c8ac58987991bf06c531f57bb10cc8fceb4e10f2d93feb69b72976638ecae5376014f6ad545266b11f3357751a0cb826167591b2eebb81c049c1a34ac7402ca0e91f3fe49efabf5fdf6ef4bec84f1d7d3f184654816b54a58f7d24986a0d5c9d64b1862177b81e84fd445864a108b545b4d63bf715a7d49bf1712580d2aa77bebafcdee8d5f00ae25b3b486ab5e7b0a3a42d9826f7b592e626e786bb6837c53e80bd6358530adaab1fab3f26c34315b8282a03de141b067ae6c9672cfae24f0b7264730516964f063554e67d739989523cff198d14c945083a1bd37a32a529e3d3df5e27fc08221aa0a98adf3257789d28e88cc149a5308af02bc7596f2b629cf82dc430503978ccee887b96d3c2fddec5695620897c7cfcee43bbe4a8e564c94f10b3b4e4848e461a0c742301a0d66e3642d9cbfb22883a3a2f03ee7382e6ba5750e066121b9cab395c378cc628dba2f921cdd64a90745f2acc9313127ee0f2886df2c9de205f4da2e48e83f43b49b009df288b38acfd7ad23dabc600d481defe1998744df12a8311c6e20f5cdb3e26db78aa4e9ff7249571a7be01b8939e559f2dce25bf84e0e7154d61cc7bfaad8271328db2f1a2b35c2c9d06adb88e51dcfabec66e36d4fb790e2bf3c964c695f0da0dc0486c6473451326567775a3a774418790ebd9a9630e32c601716c90376aa4260549492c89068ca50336ff6734cb354a491c895f3a3d8926309d43797ef3d7305b37b9383efd1ca9048b6705dc878797d8f974a6f38d67743eec121212d61931a4f1ebca494b8bbcde4d519fcf9c1a4eeb9cee61b4b1c638a53d2cbd3d879de805bb90ef1265742e6adbe3470cce0d884bdf9527e53828ac7e8e2d5a4a43ed82550da3d259154a817630be14f00bca2814f355bd8a801ac32b82de68342c17fb9dde9e90845c06f5a3f99575135249dc239f9b306b868d761b7f8c59add675be57f4256759a7d810d84f838844d97e2a24d4e37a0758b0225126fd6c5e51261f37b178ff60b033193d13df9c2b92fdf733edfc98f6f3e7400ca4fbda5f4fa24cf1f75ff9e9cb778d5c0295dd3e5bb93e31732aeef9e9d76e29aa4de23e3585e436eb7d4e2673aa18e639972a6edbd6d0edef651fc3cf014d1a5cb8af89004e9954f8948cabbd045a6cb4d5a0fd189e082697f240476ae4e8bee37f9b7026ce3923367be67c518fb1b2686af2f174290f9b213408bc3fe5abd4f99fef473228864ddd130e978409a824476c95741f644f84ffae3cea6bf22b06c7ea4e724609fb8c6d70fcbf49ffddf4413307813183e23c2d2a9faef3edb655628e8c6c20cc11aa98d092f25f1937cb244956a55a1413e72315d20dc0e3da98bfb9631906bb6bbe8d1e561466bcfc154fdb7b30f4b632646a469bea7bff3003a6659626afaa48043942e4b885c7df4024074ab9775556fc367ba7573bf4a409287354c4e14bc1d6e3f4dde9b32731a9f7410822bb4ac403af540603b52daa7569b027e74412086ce82d36dac96819b090b5fb58fc179ab2795f7a033d97dc9a0616ceb3e77e512242643df0b8f74b44bb6a5515784675289de1b488901df9997d98fe7b70ba7ffffe488f3b06c26ff8abc6d03dc6232f02ce2b88be0381f29da92c6f28641d13d654d975055195302089ecdb4d2920518c2cb3bf4db918f97b2ddc735f4a6779c691a84f12f34fbbc486137ca2726f150538ff0d5bf9e6ffd455b16c23848c9a783c1c373d824b143f334b74102de839668df23b3d605c054bd32636133d3764f654f65e65f4d42d12138fd03695d3fe6eeff837d70a7b1b3e772f8ba5a7933c918e26f2d11500bdb08d95ed5b908b125171eb8d25571a676512826b54a046978a9b08b4694d7c23ce090bc08f1654313d009e84177f0cb1f110206d1f20bbb7128d362d007754991dff5599dfcc29d46ebe49f08264cdb8d799a226d2356996a53649c24b65b9cb066a02babc68e80e3b244bceaf7ffd79a6252be984977c378553c8be33a6a328bedfde55d4d6a5b253e8e02070f3257eda6ebf84042dba49e1a7b3f2c48995b53317e7418c5b59d63c56a838f07e0b74e4292c476b7260a5608e6848853ce434d9f460823a5fd8c7c716267cc284abac8469d39d3d24fe2d7e7f5005b8ae15b29e53997d2c9fa619be632c15c3cf60b5e0a82587ddda7f54da029a5a1d350a2943e77db1a9209abf95940d28e407ab02b5842dcb5c560435289874df76bd7a800a8f7759d17b6c06b130d8a025edba97fb4dfcc50d9de2da7ba201a091ff1e10fcea83688cd2089f0001a1bf00d1a9bf32ca310c3a7d35c60a4fe2637ceb23a67e417d04af65f655406c82024132aa9cd431ccd5f03d3f312fe17216985d9288d3c41940f2bdcefac0c4b56ed38a92f357fac24b47ac6b8813d157854c080877208f12ace980211651a2cc1c6eda7e7937067c6c5f37b4ea85bb991de013c156b531293092b2e15f2d386ad3170b6a9ee53b82f9dad1a70204ec2ad488311dd1a3a563d8e0208f61afcaa9ac893ce4d477496da042ee27dec38ffe64cf83191cddefc511dc9d2abb6a693464025fa20a644f08de16e55d0e7839cac3e6811d6ec4746087719c58c4790d5f9f9be72f43c3966c4ebd0effacbac5feac369c025406b426b41517e6d0185cc94247242f31024a2ff04942adb5a20407118982e0549805584012ec41f6584d38b1aafccb2f0f9e559a7397928f1ed0fa0a2f3af0d29b261943dfa3eb707231b26e7c8b9ed2cf0ba71e33243ce6145792359156f5d8acbb9585845936dc60ea00908074d5127f8f360ba9a0648e4173c943363294604cdb9eddbaa9a457f13daca518615d7f91ffda400100f85682de2ef98e0255a155f57331a98e67e6f6cd008fdee8e25f7bcd37965374f2b151bdb3b3f5f1b08363734845a34f2d326109359315c2cd303166e8906647e01ae9163e8990fe84185cb41e9ef72b05ba596c4ddcb5ee0f09d7cecb6677df5a06128e75547ba170cea2252da7723560167a8407f717c549a5d5a27953e68f06704887e1c6f5eca11c02d7278410c29ec4fd9b910b908e816736203968803c8c19c9b00dcc5aa6d3425711db0369647771fd148b06283be19bd3acffdff32e384c56832610f5d913edd745254d3afaebd102acbba7270880c7ef6b109ded8474c4ac9fa583164a93785c06370b33b9b20cd1f32f20a2a08f80001c0cb96d68b549fe9f60de95f153506539244b000e15178bd35c4709dbf9a0d880a1a3138bc94a85150bd3d068e84c9d937bac3e1bd4b17b45b3f83b29bd91c8c8f9163193b7f86e01dc14863a32ea00ae0542d1795e9cc9319350d1288e493aba318bcf346c2f58ae39e6cd8dcb5de2032e0e1d1bb5eb891545640df9e4d3b86e104fd7f483fecc6be8460393f02000008d8a3887f84806d2676b0f4e96175b3d0321120195af59bde2893f278e2469eafdaf065168004bf3cbd2b993c27e1472ae8368a42ecb724e8da65c1d6e493d7a116516f1076b6b8249e94bbc0ac40624293635329faace5aa7874e627f586b2b1414dde529e20c624cc49a9e9de4c275d4ff558acc9367a47e2330453c1a0f18dfff2eef9c923ab607aa312e2ac3243e0d073398eb9982281e4284e12d80d29023de142a1c3106c36aaad7d18f6a78c9d8b0c38937075533f02fe8aab97ff157f7c56d1b0e495558e6c5daf121e2cc9bf55e206b5499b7937a8c432f64f251bdbd0f5df16ef151cc067ee5207497abd5615fc0c59b308e4859a274783e20b06865a3490055d8f208be262661f0aa518e27a6195d883a1d3026b9588281853dd5343266e544e006365ca67052e38a7af85ff8f7d7b9fdca392c7c5c5bb5aad22a1b8d7ca83468ea2916753f0d00a0f9d7755fd392cba3c5fe216a5276fb07b3faeb90387b1bd2d600dd151979f03bc06f4d8354b581b869765f0361b0460a2a9510ab1f6c6efa264265157d20aef3fd5f74d4b68bf9f2f705c90a9b42343d7c833db74adbeb00ecc90deebcebb1d42e34af786971f06c305a684cf0c16aa6a24ada4917253945a227d5faaf7bbe902c9f4e489babf8e84dc8ac626468072b771f815e0e3255b532909964082a94b46aa4cdcdd9b50bc783503a3021c1c8a83bbee317bfdcfe20ee684c573a82ce0712b1cb889b5a949b30a350b5895c778c022f990003fc480d5620191b0fa6b367b959b1820409955020423f0a8a22036e7eddd3ecb2df520f7a97924dd17b88c0024059ef0accb9f90d04460eed262066aac843eb85e733c3d5864db386c89453c974938e23fae5ce21efba117f1dfb2812b0114c054fb7c477c654734a8fd9f3d11663f75ad3efb1e3b286cea85b90ff8dc8b494c358373e5c5862d3c565d6f79d7d5e20da49f0d343025103e3acbed3761d2b65bb102d48e78aeb001ca9b120658f997a2e59ba9507dc4e6b0764090410857883f2a2cbfa3ba87365b5469740e504835773d9819e3f6d0dba35aa77688e89c81aebd4ffe427bbf1cb603fc76b59f6dd4ef6c053634bdd6ba945097ace2ce36eb8a3ad239e55e7938e2f7bd3852450bb24fb24366cf4f9900826c9f38d944d94c4b05827007b2215848a6de0f14608faf597befd6a261fd5f426c1b7762dc37b5bb5222de0315573765703dcdcba31e2a1119c92717302e970cf1df23318619bc2adcf19552381b5bf4d4a3e436d8cc060bff03b31240f0e5ac99e3bf74fa393c504c05c1cb0814cdb3310fcd12ef4c40b1f9770896022f4e260cccefa55e14f61daa7dbdfc335ff3a9c7549ff7b930bde298893346476a76f0b6b8c9c2d8a29f8efc73d67bf299c96eec0edd2f498c65865d267c75e868bf0ec48e7de46f2849350318fa94a2a68e54027df45b76d1f4a59226e1474e005b0da668d481f3bc164c1c68fa96b963419772267a313ea1b108d53c39d157fd713a683299436894dd006014af337d8fc4096cca75a82f56ef89a12dddeaddec68c736bd9e6a3f9b585b68d071a33c0f44fac018dbbae3de226d92db0741dbfb1c73687a80a1428c4491a4ffbc19c18894e5d8c3a7c3e4545c3225b0f1656cd6677ea791fdac5e93e95f9431298c1d60d4eb7a1ae92e03a36ddf8f02d46c7442d2556f2b29255002fb1716442b2f6be3da44c05d367d7f1c6ec927208955df1738e9a665fbe8a46868a51e87f82abd4c8072d8bf2e975cd0f8c1a1be00831312950b005522a2b182297dc2c6045c2dd2d794795d32cd4b01b62d5146247d33ecfc31afa722151fc1d6365b806eb55ca9df8781ce1fbd32f3b57a45fd04c70e864f344738efc1376424d7c15fc0a8372460bb9fd3b9505ba8d568100a7368bb14f3827f832fae400d68685a7be90b6ff25b413b19944c68e3d4744eaeb674ceecd7c411f321d8c784785009b578cbf4c84861307075086d9a7f47b39a9fcf58239b54fbbd8072756c6f7ef20287ed3fa6183cb3756d1d4867041a99d65bdf59c54fa5774b0d79ecb01776755db9ca23c31c7156bd7ac1666de5afc620622cdeb2f6cf65ff35d657c24132bbbd208df562d495c6fb4e8190ea2252cb7f9459436dc016d92e632c505e27f89952063a41099503e0a045d6f842b1406e04cf473a3efd76eafc96a0b88bdc16ff23cd01e659d26166936e36ca626ebfe34a2caa7c484534bdf299053b5947f11e96619e8c247fa9dcd4e2950a8203a836cfdeb3cfd7712900014108d7a58bde2ec00feacd4b4095df07a27f45b5e771c355234309f4e6a6468d7b46f21ef38ef542a9449d3ac14da82556148395c0a2d3f0f4ab1da7335f98025bc4b5f16b7c728f1682772938551e005c89a85d54450a367e249d0c6dd86e3527b02ec8b22791f5783082c2f13d421b3501ee7531d2bb478a7bcd0e004dfb0a79a1fce908bf05d844e25559de1f314c9be482fdc88609b00f2b886f06ed9459b88dd672da0a18eb395bf47175548556a9729e32e2213ca6a6120be6eb293908d0f030908eeab2e2b988893b8689c7ca933d55369e984ad865a5d12fc12911aeecfd28c4476a7ecf0108472b459f7c8f6de11155c11e71c528090047310c2a7a9db9c88eb90e550b2db1cf0b9805a8aaefe3d524e00cec18adb50c09cfa63b48413caee25ca38f692f3086c1e2b68eda3048a5379dcfc9b9c54a0bdbcb9697c10683652f07882dabcf11376430b793ed5e6c611ac789faee2fa93c4434e15d8abb482cf3d587849af51a27c8ed49ae4452e0b9c2688b54a766058510ba49012ba901c62f14730808fb41c418869208a2c1fc78faac7d8d7d96c17ead828c023c08100dc0a37a764a123c941fa378af926f422208368dd02058e7fd4b271b61ad26a74fe11c352ef199ddc615cc44ef00b574db5c792da084b764c446e5d6759755b34b5eecf60cf410628e2b90884b748985c5ada2184fb1dd03fad8255a28b366489fcb4937bfb8d8f7152ff0f755f2505c4c943e24b6f6afc90f16959b03139ca3b5078134dbb26563112ceba5d7a2c6e62323ca0b77313af3942e77cc1ec4767dec711cfe777829ec6a59508b463178e9110f5b00f98af42eb584cdcd9f32b15a8df6d0478232ccd70ce2979e47dedfe3349a9b55c36d431a9fff42a1fd03164a8e4641bb9d17bb8651069aef1619cffb4ffc5d584d4c994d4eb533d0a1e3b80a487e7191f7d576959fd67c1ae002975532df9104ef88e7f7cba4b41126f85a9fcf9b336006a4465efe1bd4709445f509247acdf812f8fda7bec7374ce2f1a9437ff150a921048ebab9ce6ecff01888fe3f8a14b0e54eb973f6fa2f00f2f4c10ecc475004723c1eb7fbfd072c01ce64ba0646fcd825c590cd309d94c3d8e0ee791c00d3d7b291b458ee6a374eebd78f659407d27f3bb765c5d956afb62edb1ccfec52717dc0d9043edfb315078051cdddbfcbe1577443fb99c53c93460083dc58285113e8001b16dd1ff50b421495a2ed6ee97902449f62642c736c5c310c6cbca86a532c36853892d353e60f1ac5ceceadd87410c6d3aebb66ec2be500df7e88d0b9a1fb3058848c1e0ddf5de77e7fc108f137ba6a85600cadc38ff3f80107120e0f217524a1d4dde1d7fea1ea9112f8fdddaa780ab15801e40d2e6339dbbe90153c2d0fe0da84256b123616fc9889bfbe06130166fd34755338111a77d06dcfaf27b070fe2f25773f14f008a41301e1a1c71c390107189082135e0c53cfdb3b833350bfd4fcf80740e4b57bf7ce1374078aae2781b4c6bc6cd9196a030a59816baed8d5bdb73f0b70d1a9c3de24d8b84da673b89d861967ed019baecd57816dfa9756b100ea1da9c0bb7d27888b6334f4a1d871dbc55e55b0f958a9f63420b78144f2a637c573be23c03a7dd2b9ae3297767f295d989734ebea6a3145a7b798761fc5b8110169e2a2b032a38f7053e80ccad07cad3788e9d31f18013fbdf153bf313ce9a75275a84d25c01a780aaac99a93679127c5b5cc6cc9f2932d3fac8a770d6b655f7d03db3b50649181488747a5c199008a57547a4bbf25eb06b8fa0c1ae602f651a5025b5ddc1ea9521a7a36bc19156ca143f18a9f80673ae1b28a95e5fc29b4beefaf563255b08d5af78e898f522db22aa1de41b89505fe71e7ff04a20c9d5d390163fef92001145517e607bb0175b7ae0095b27a96ea1f15bb88f0d91f255b08531da1ee47a495719e74e9944f1a4b2d473d8670ced96f70e0055d25ad17d1e793c7f512089b704b46b2b5e3a967e1fae488fc2a5fdafa5404410b8ceec9d69f06af0e74678c7030a78583e9c99e69fde34c2e515c5f88c744fd1fe93ea2cb0db1803b63735b31631b2c1016f5a52804511b8696db5cac0ddd7b6f24e0d305ce170f396b3d6c05721260e7ee8e120b8e4aad2124bc66303a6e18776f132e0003015b0a4065c0b603fe1381bdff6cb694427b4551c83281c5664b43fc8970e21f51014879b43662b740f4d47f123f0cbd4538c0c26aa97ba6bf5765ff6a84a9a675be388d7522c174af1b6872c47fd6942823d29ea300ed02a4e93d2778ed5aa2ee2d48d05eb7a72565c4318571b5f83f3b0c7285c81c3ab17c3e888a18655040469bc091b9b3c147689f145c2b0948967d2477816c86645d0972c96b412b9cc1acac769985d744af35b93a030d4bace6b41cfb502a517bbff04c252e744c3de7eac4101f337431e0fe30cb158dfe531c5792e8ca3f9d415109c73e1daa6fdf8330d88859673ee53f96d3de8c7c4a1956f4d845e2bb5e63abf1fd9eb87f0f31c757099a23158e1e30e733934c8d8ed5659bda6f9caa92b0da8e92995ccd6701bc4e5aa08741286e4606a6b3aff8142ddaa7beb8da3aded62cfa675455d4e79799ac873219355b03d0ba5d093191d86624c06d52a2dea2e94c2a15ec1c60f3a10632707dca9ba3af4dce69f56297e7fcca43b481f96d041ecca7e5f914cfc168cd6f721ac7ee8001452fb26296fd50f8063fc8a6f4643a80eb11109eda7334d9be47c64eefb633cffb784f3b14a7517560f1c05c64d77789017a1151f9149a8ccd7db68dcc718dbbe276acf66de8dc215200272b5b750afe63e1d1e091946d14662c61aae4eda2c1e66f7f0c2e127f59f95156ba08c08451e03a603dba14a5f271e0adcbb5887ddf22bc8aad71a94fc21ec081c7d27a5134827da6bc7ec3402e4c0bcd2d59709cb24b46948376a21ebf167fcabc1d88279858d51a46391025b86a6815eb5e27c2833279585b65abcae63554d185df06ea3fda2fbd97ee271ab2a800983ef9c94d06d1eeb11ec0ccf4d20d5ed1ca894aaf4f5d64cd45e9d77cf0498cc5f54993bad293df8ecd6edb8e2b0c2d2ab3c60c7becde67bca6eaa6792a4e9cba207e17833e55c614d1ec31625dddb5fd4fc7212a11aac37195d7827bf1b51fd9075690a83eb34f6c1b850cb75a7bd2fe22202647228f757fc5bface0dd8531a35497f6a8aef5a998419e855458d30b97dc8e3b93f68e27fcddd2cd3fa6059238ef12abb970eeab7eef00397631729d0917d5d411055c8448442e67763821bd853acd8f8b503de14057f1c18fc52a2720bba84445483a3d16cc71d72f44b104b68213790332a1645a8caadb6b8e849cc3026660c269ab2e0c35d150317345a64b5dc3f9d6f8923c4dd2260e59564078fed18abca7725adbe754e0ef9142e2e8e94a18beaaa49b0c4ce2becd86900ce481a4ef74e7222b42589c1957b297ce8e4c27f26578fa213261fda2871b093e5b2911f990a1421c47b04870fd0129067cacf2e0b8fb02648477f9ea85042a16575c913caae6f9d15be21d45a781af7db62c845fba2f62fd15245152f9c9aa4f5b5c38b90a65861ea810efa78fbe2f1ece40476a84947e437789cf3e11e733c42da3114cfdcaa4689eace9a64693b16d55f055a223f486d5c332a529e93736d4f7e1f3470e9e40d50b3cdd5c1174e30e2e2ac7fdb9a2f352e1e51a4e408c6b4d63c9985d88a5c9b538c18aae3363ea77b5b41015fa5fed8cdfe8297cf606947f56b32ad66fabd5a43d824255175b3c694e71ad616f7a49b21bcd6e718d8c7795c584be29d0ff05e796b182095ded9dd0f2dced84e0794505677fb2d5feead15964acd0cf5a085646c4a2f5c4d31f58d250002efe649d301a9e9d5d0ca0d30aa06daddba46e5005f5a2cbda94bd4da91a8a7262db713492c0ab3f6cea3c77881889a5d6b614e45684d4d7b9228b9b1d18d54692bd0f1230e1d00268383c0b19461b070327c48c2da1c3af4e51bc42a05e9903b41173543b4cc9ce41a243104d7cfc841018adde1c9d036866284ade62d9054070fca43887a9b001e7360c2d763b73512d6163e8bc67ca09829c5275524ac0983c6abf8e577cbc13f3fcb40d0f3287b9c14bd3f939d45b61c46f46e9a07465b2f82753440a47c6a94a53b6029999be5146abafdf05c774c929d30190ffe1469862eb1d0adba4c657eb5976ac1893533c206a58a462fb41b50f17b826c36f299a45aff759c3f34da79fa9748a8dc0e6d69be2128b1f2e574c6bde83f3dc4cdd7586b4441ab06c58f550055725c1edb96a973529d3f6f1d8d3ff770e3b305cf5c385460c7a200b2e0d51902a9705191d142dacbe12ea7389cdab39ee26d3bc27e34ec8008dc7abfc0efd8292ec8c34a174641939cccddf470567b97bc7627091fcf3f37a9a3da1d17efa6d2dd4b9ff590dd613ba36063ca8ba9ad575414c539715f5b0ac082e1f323d08363a2932869c2b00fc0f20893430f7de0b21d0f8a41cef409afa6db2b79adeec71dc594afd077ec2473d73327de5d6317e8c509e5fa6e4fefc4b3a3c8cfe05be4dd44838607b21e4f4fc7d3d0601e738a325ee266dc58dedf64feeaf23391bfcb0947c9921c34e539e689f410c33a4737bccfaeb10250013e82f2d2fb2c4580f1bbe6d455238ae9964140e63a5df7900a243fa0f718f9134cc381d835340507d2e8216450fbfe760dd468d0b7abdee149b41dc1691305df8bc0579303146c0141eea908ce4e736e9f98b855467cc9212077ce30d42142e3bfc2981c5cc6601091d3d412fed617d7e4a1623a2b75f2e89d5403e60e00661eba1ca24cec59270ed8da12475918bcee6491331927f06f0225031dcdb345360725f25fe843249f46c07a61dbcf6445542b5e99cc6302ec70c692ee9e2f538dfe02e0af02704d273f2807e73d13926b15a30d26a003ab663d8f0f9e6e69e1e33406e0ab87e81e654d24d9a876d31467f7ec9f0acbc567da4b99f5e56917ba4601228b0ea54df07d7598ec552131f33c0a24789fb9a5465933221e4aebada5d4900c02c811b5b289b0dac02f00be12f2c1559e48ee4d6787a75f67f4a50fa293584eb205a1ae2eb2de80b9ab4420831baccb04cc8dbcacef237116780b505f23c8d9e91e0c40709643d1b5a5fbde88b7b2d40e373092c9d7010053971db0babb569c7484fd00e0f99588b6d42d965d657eb9f512cacee16c253f8b782b8605956aca56c5d6a35625c0d07bb1a291ca10fd178e641150b481b6c9185daec36339b204f69f664862dea0f17844082f51bc59dfe458b971bb40c836aeab6f64e70ab622c92d3b4f391653dc704fa078bcf20db5ae18c837678ab17f4d6c5cc8474c23617c53f339348ce2f133d3007878dac8308cca11e350d6f1dd4ca693e24fa738ccc0cca7379c42abebb6e86c48b4b2953305c550e7f13c22d3d7d4f7966aa40282a56a89fecb5a3cbef8bcc9ac72c42a354fa56d7ab152c7bfe122b8320cccb1363246350c88e9941b668aae649f66b3e686e4b02215b3cd4ff7109cd91850d617e5b2209414252e3bc1638bc4c92f15551ac101d63026b77ce4b7a0c8ea3234500b3aa8a5770dedf61d93752e45cbdbdcd2c71adcc6452b668c257f790396be557f86df57d57f718c0db22fc4a2511b2a1adee4126033c449f6598b52122f888290de4a6b1c8379d22d1b2c68420b5ef43b82d5cfe4d0566080010a7856235697939b3a27ccf139594705107be6f7697919b9a99621e7680e990cbb65590f4ac8ad683739c8ed27c0fe4ca011e8a981a84ee8f2160e4e0781ad8c6130fe6e978777a5808fd8b1dc5c3e4632ff2bb4ee600375a0afa29cdaebaf74de2737a12738103e6f731444a91e0a83508e0d5fe7127d41c82259ab723fe8d68c1af39cec96a57917d3c84760051813d0f7003a36b4a39471d1a958957f7e4b5a4162fc2592b0cf699de98050327f87f2b54d078307ffd26137bc67fca320cf464e4c87ed24f353f87bf81ba0d3fd3236b8551e5fb730a0849d7b55451c1e751875b5c5c96c6a17fe55203a4158f75d4b6dd1a11b350109d1040ee60f486ee8eac7f9dd81b4d672e7f2621a5c636e70f98f1883c0e213c325329a590584c04255768c3f34959b186b9183fc1f8ebf9cc34219068c23886d5d70bea3370ae75375002505f3f7b737e31712a10c03f82dc81c8e512ba952056319f9de70d9fb03164fdfca37174d0b0006345810c9986270b2ab29859f2cd7a785c9a6de4101948cbd55215c5e2e21cef59e5457b2dbc4635091448184fc8b7b71bc0eae6ce67d7e793a58d1e041197b624fd1141dc347b2e2a03498ee76b7eb789aeefad5e01103ce5791793540b7f5479c6d5b99a13803380bebf8824fe9bd774f1ee90623981a2239067809a919bdcfae4137a6149803194774ecadf164fbfbd8d977f87e8393c043ff6474a989b63c6355624b692b9f4cb3ad132e02b052acca4a95af452e2f8309720455683cd283e4b028f608e944f52d47be01cb693b943b42f67d3b1c302845538b811067e7c3585c38c035516c5270050b7a2d81e0a7c6243585012ed4c159626f1c608e51611d0d8bab06a2f1c7062455246ce48fa554f26bde2af8648b68fb48741e87f60018eaee12a28b0d5b5aa9e4319243a3e600e5c34500652b8b05d133fa6716c681c79aedf8c93b4dd775375d65c63b0ec16361eeffca9fb93cc0a15dd20aa33add6a0e6044993b5e5c29127193cf3b0354547f53fb30a172b601808f3fbddae17d718abf258702a2c3044f3b103cebe427878d990c687a78056eaf8b2c50c4369359b62a4487286421ca244b6700f9296ce61135ace648d82164b7ca105b43773120e8fd75005935d797b5d4a08a354a5f543453a55383153a35fc57afaa859c4c3d1eb7db5ea14a47af26b25e75413238b6701e838c5e25db4ca5e4e099a549637af72061c843412e6be1da1b2c3c801d2a13e7bf6a2d2e412072a4f801095f7bce61d6238f9f80a6a946aa4a665b5f33e21d92341e1020bfc05c63cef1848c4f484c9d5473a54852315f029c2ccd91db5d7e6a275719c8da05f3ae430607fa50c7bbe66806e36ab0f6287c88aa3dcbae4a25524baf893c64e054e50816704c112d940a4ddf5d00d62fc76288455289e559c44ad55b32aa76c905fcae24ddf503801198ac3386243069ceb3cc6c745766bf14445a3018669a005f73f56d4a49feaad21db69f93abd9974d6dafcd4db389f2ee21a62624184d27a7e937208001480c4d5deac75e304697c1a150b8088d427b5ad6c367923b21c5a3d8a1c2c017e331edd9d92226d5f12a9c828bb9fa760298b9bd8d2320d8fbb5633699aaa186044c19de1f138e0c79d8a100a7eb76fd56c1d01891c561cc7597bbcff16f28ed27a7d9c585f43542c9f08ace66ba3ec8d688b962b2a1aa505fb2a3f2ffa0d9a97338ba46a35627be1431551929eab500ec3b260ea8e2cbb628d2e8b7688a0f9dc0822b9a232d99f03cbb411f9665edd895afc1b4bad1e34eee13d9abb9c8a7d58b9d48c863afa0d813586025cb42a21631f39d92ec402222dc64cdd84d4af47d6000b326b6a9517dab8b39f0c1feb063466a8a422e1fafa2b22b770e618c63ed30877c16604a9a63a326285b4238f7d89567d923039e27d9ac2f1c33162aee3a59e327e9533589425317c42cb55e3a073d7b1d6f3fc6aedbe7075679b2065a46ec910987d631d3c811df880caa814747c5bd46f2470dba8edca1db4ca44a7b064914f09f0f8147ae114bfc88d533e7549e0f7991ff03413c4fae9c94e304e26037170d36414ee73496819e8c6f49adf59c9726d0e65a25b3b31aa8a6e63e228d5c1b83e34bf99cf6f4e0652a9584d028515a2e7d3fd9fe4cb12781f1e2b5a14c6bcd43b190c851ad05fab27ea18a4eb0308cff4cdb6a1acdf413901f9d936f7658bdb2c9321583696577913562c54f2d3e775cba7177b22f802aeb4523033c6f97b45a55e58f5072f996235121aa0e2791f5f40c5e6c15dd192492c8b54a160c0672e739307b837cb8ab73121a3bf5921f6df57927707baadde4084f170d89a85f85357c56381b7b8a8a25730a75a3bf56cb618c341a41076d42503dc0fb07a568da281b060945e27685912cbc72bba989f0ea4f4b84e3099cca41945d25b4d5661abb46267c8ba36373d4122a6837ac37e1053183701fc46715876863af610ce00fc16d2307389df6a8ce411445ce1d3fe7c7f93b5ba20683516fa2af2ec3fcb9d90762353e423f450e060684d230b84c3efa1e1ea7f87ec67b08f2a342a455a5c5bd1e1971901f84c96fcae809669c958c6d09c413358fecd679f28a700071af0fd00d83265714843f87890f79c7e42a1377928ed3ca1577a190bd4da45e1b5d9c00903e49619f801800a508986c651b6f0d42dd4cbfb75c4d33d0122e715f64f6a832688f07b430cbcd000a42dfd2425800a6966b79ba4b1f130b788221fd7dbc71db4df7304426f47e3d4b831cb1cc5a1779aec1114ee8a53fee04031a62d8a895655cc394d87e21704c092ee4325b488c24a6d60cf927c608f161fc13e6a1c796bdd148e6de1fff16ce1974e6c1028224a4fdcf63f30ef0b1651380948c96b836490570f765cf80d614a41389359035d44ec0acca9971d0ef00d60bccbfd5443e1bb9064bd500f715d46f7e8323cd633c5b763a5ee867127a017c9c4398de46d4938c0025c0b602232882e7d6f483ae65d6dd5240030a5824cbb50ce2a1541ec1d33546d16b4af597377d052f40b6f4e6c582fef7e8e53226467755594451ff58805c26929788634f484502024a5abd6476ef46104dcc8d1bc82b5e3225331c420471c377839e1086400e1839e388f476617ad110e830ebacab5d21e56b5be2e0b3e9dbafe49ed283bbeb30fb00dc31b0296200436e9359621d015c5152cf1fcad5b9bcb9706095a559bdb83df2db5a52a6e65be0b416d8ad02bb1b09093fb57eed467850a61a7822fcb0b078644e8aee64f9ab3e79ecbfc19eff71fa83d2acd94d423224c3a132a876c134aa710ab52e8b4209d509efa1f3250b75757f533074431e594a3b0e23c651d75d9b13d5465d0b9d00ca95445b1f34a5322e48828e40e1854552a50fe69bc92bf3c2eea4d07997e1417bcf12d0ede228ab494b46ad960bd600ebf75fee6efa74abcd1af58ffd53f977d70d832a1a73a433fa5fc3f1940276baebeadc51c8728cd4f68b56356e3c5a7b7977888b42f092dc76864f901ec0cfd0980ed77050fbc5229d1ee16b534f9d0821cc7fdb82b69c8685512bd1bc6217ff42546781de01ac44d43ff4f0c92e842d92f694f17b97a886495962ec89b0ce4a4cba436b69a5b15c5e492bb9cc2f20423578a61ec4e400d1830c2879aa8eecac86b7fb1c03a4915b679226afe7aa3fd4d5ef90124438ed34e2bda671a2fb871d5f52f560a8a5614f4ad3e88ae0c2118ba0a7ef094a8f4d11d0ceb4664770691b7a4578134ff7ce047b2b081a5ebf39c3a6d90e8cf59c0d1f8710af0723e6356e559609e1e6f82adbaddb7d991c146823ffbcd48f062c98d29772b8c8892fbad70fa3f5c484948b9d288ef9904e4d353421ceb2cf7eadf1dca232bf19270b25a60a8dbf568552c7eaa778d91a473444e6ede05a3f33b30472785927368225c5e50850ceba9de58af73521de51c8a8bf36a2ab99e24a09f9be7e140727bad82e50b965326361e49909a1f73b5875019d73db6f579a2e1c818233e186540c573a220889188c79b17573279ddd4311df743e591af648934dd5825c65b43d1be2298b93de6488ddd0c0ba9b4b67ca8259db49742aeac19405041f8491724dfb955a6cf9dafb388eb172ea0db142f6db423cd01ae5932005eeb4ef06eb6a918e31d06db4acfb91f8cf32d78cbcc33982761778e074264f323d30bfb2cf4f87fc816544426bf1fa8e601a559243910e5958981d906b79416a0b204202c8f639890e50c54ecf06089a825eac2ad7095b97a052aef32380952126368def568d0f42a7b7b727c33c46c039ef219a796f26cc845a8f7884639a2023dcde7825b326a23fc21dc8b11b9a411dadefcdd82c3ac1c89775c0f79a6d0cf9436afc1b2e34a764484536c59474092f35827a186d17f66cd27c136919689b53437321bd1991412155b493eae55817a8b0dfb63798160e322db82db9e1a71b44812ad2d3c828f9d8419f9a105ca7f83ff653366103c8d2b9ec56c08f18ee64aa5099d9840b677bd9aa402fe39a2e1648e5fca9a0116708ebc15bb018b6e4fb98f56c89c499d3da4a19fcdf747184d21dbc86534834779f02d2af386d6d469f25010c50e943dd8d225da9d5001f58415e9299984e533820c734a3c28d6c42036685acd689f0120acc457625864e5b5bd0c10eb02568bf477febe3e40251159701d404062786262aba2b7c8ecd0a5b46c40800c10779d887ec64aa488bdf02e429fd3aebc425fbc2276d42adc331fdaa02b211f8667d60db09916c6331764fcce652fa4fbd160c829d4007cf8ee1cabcaa0659d8124db0f5134db87267c5bf6cdd1a12355f6aca267dea715ac34077675bf4ffa1cef2d2cd1bac4dce410dd30bdb3cde935e1baa2f1c4630422cd82cd5180151598a03249ab7a16c805b2214cc050d801adb50d0abd9ace9417522b0da70da15de037cde06791a04bc70b6a58817aadabc100752ee738d37ace0c4766d470deb80eba6643a2beec2a73a53df7cf52e921f73befe00dcc1914021bcb4194193c37d60803633a4745f3affd70e35d84a05d76836dd18b827c3ae30884f5c1c432d744aec0eb13b9fa4ecdc8e42d1cfa3fb75258d7d10680425b098a52107a40bbe2a208a99edca09f8380eb5548e09534800c66a6c85b8ba724a6618fdab1f4b322b5412e3b59bedd09253abf2c278e5bf1f93b832e7db2056983a1e95b3f11ae9f25c45b6fd5c15e97b4f76aad15f06f39595aecd139f4160371cd5c19e12538e17e6b403bb44f4c4af689ebdb544c133c68f04c00426e8e7e3628a6d8f06760fb4b4d7057ca99c62194e7fb338ca0d21b6669aaef6ce86567ed7b31a9cd98fbafeb2ab1d29c21a96d3ee94fb7bb7ec9af9bae59844bc022b3d750b0448134d88b91a50858eabd136ffe9127f5a16bad38d8fe52222970fb8981be0f49c57e30ac889bda119a0f62195c6e2fef82f3e804f7897572d8c0ff09455bc6bb4b70f2db7f10427e17c67ea3bf960b412cbb41d81ddabde94f0caf7aa70f2f4e642008c3dfd9eda8443a692fb160d30860aa817aa27be288b88309ac0fa6203b3c580ae4dc12645adc32a5c0dc0301909a9734542e42c94ddf8ddd34d1d200273be31d2b99150a0a990d66bc1b4b125bf7803cfbcb77ab7b4c91464b4483ba009644d9bad063453021e5805e8ef30bb6be50cf3e1ae18127c96a56cebf8f176f8342a06e1ae2ffaa235bac5289354c9d7b3750c3ce5a353d7e20997e04d9180b0be50a921e12beb6e04b3f71489f323d99ccf3de4f621ff4a4d30e8c20e174ff65df7d97a1a456548c92e9b94eb937ac759b9bbe7aa3e2077f948ebb9ec129c24325add580fabf983d559746d28e92da88365e9bb1670fad1621affabb5f9743ea790a62837b2edae8f5ed3c1104d9a72f7b363ea66509a2f68dfc9dfbb56dae06dbdfba92d121402003986fed280774700ff1e4ed8bccdcf2276c401b8ea36b0c572a8cfabd5702e3c7e21d62f1f0ae3a7753d8fe668576a6bacd06b0d17e755f06c1bbe94938fbf1b22f20a4690ea8a38b31c0c4109596d6db6875c0c5aea62150c28aeb3e791e4f7a09478b733832e80a452821502e5ef64ce06a45fa76e7c3b2439b282710baa91917fdd6079e6863eb4ac04cad80e04277aab247e9535756cf0ddbd8578fd1dc7f6dd1db5e26503bdfc92046afa4cf0a0522bef3558b7a08196ff27c982c8f56bc0ca63b2a8b833776096ae46ef622d08da6137ca3aa4f15d0e3c809363dbbb2410788701d93627ec13b02035eaa81cc54871850e8b78b9e66de5838c16482482d4521220646af7341fea11afc9984cc8ce8c33654496f0c0bb25483b0ab4381ef12a4de6add7e4b03721326e8d206c37455e0ec3012842bb99c7fa81c4344910136041e4e3b27420adabe875641e4c6e1d1ac97b0cba8e90209776ef61eea2693d9aef4f20cea412124701652d9c2c58d6dd687d05f62f0f1b25f3878a9066097fa24c2053affb9346904a04bc70939775c008b2a789e83b7dfc09529d9629d35db51d4297a7be7e0dd5dcb97175feb42b73091a6dcd54dd7b839f8e1842d830294c483c99b83177c1ae874d259f363fa6e9c925dabc8705a2e54ce54b3235e7cc214924f19de2df278722c20e9a655d59cdbb5fb2afc63ef727654580a8d234c1c190f1241d2bc3627f5de463d951818501031778a3c22fd414539a500fcaaabcc142dff0fa4e915a1ebe47d067655f31e41fe4fad752299d1a47376b9bb4736619d715f44fe4f45bd24d23c32e226122f7800b3aeca40a49f510f9fffa774d99583d217b54c8b43e6ed414b1660df3219fae2219ea13506550a2808b4748dd77340cdab1af972199c8636a909df6cd779c8b2ba13bb9be5570f2a9181745abb7860489de64b52cbd47ab9ee751ef4c2935553664c3bdb790948ef5bd8175c742df56eec52c2a3f6bf14d46561d1beafba55bea040b9c18b124e8daa7024e711cc2e98e34a41a8d3a37089b2c55ec7654ae5a92b725beb408c477b7e51f2ee0e20bb6031827752d3967c02ecbfc12bb636b9d58aceb6db88ed1f329448594b6b51d8fe9e3849fdf3feedad93a43753486b700b0f3068580a13cf69a1df1b82416c9b97b98679d2c98f7fdff3cbb868cf6628413da24231799bc78025799be6419c2cac6683017324c8541474dc61515f131f35740b7b944feea4005a2b3acac92d229de764cc39fa9e0e0b3feecac61c2700dfa6f579040b64708d321678d8679aff79ac95b23919213119dcf6e440825a17199419052faeb46b2bdfc4f0d4f427e3301367e5ead6077780f2309f61fbf3afc7a53c670cf257f5cc177d9a6b1e0a6145ab34d8c253d467014060c887e3974ac0789b46f45cc3f3858379b4547641073cd96674e50675174d7f68e16313aa8bc4dc8c54f6096a1ea604273d42574b48eed31c076fccf4a2f05b831678e0dc69aee6e9d7424f9ad1442bd6e67c9ab8f2b3a88bbb682950a5ba056ae724eaaa19ae8240144f2c27253d079848d562322504483b6930d97e5c97998921a41dedecce411b5c704b367683237e4b7aa0ca1ef3b1794e79f593c6f07d5646dab9a98dd1c06d22ebc4de5fd7426d3bd271e9038f27abf7c1872fdd1f3816f01eb7e68eef7da2c4ac591b2402e885e4e1b91c32d3fe7db1502583b0220f7aa73ebb566b56d37b116b3feb6c51450b046d52e4ad540d34b3e7816b96047f55c163bc4a928c17543ba3f68f0a29c8bb01bd5491b949a580810558aed5247994ae55723ac3c584e892c4bdb75cdb50a4c9ff2ac32d0684dbd6c5b8ae29d15203e8bf497eabfef4076565821ec525c4278ccc9b30e483d09eec06229f55481787d0a01815f76805eed433cf8eda44f68245f99434cbcb3c59954344eecb1dde8e753340a29ce9797bc00d3a398432f33671ab68f4e83cae38881f00ce8bfdf0737f063456125fa734478c250ef40bc099b1cbf7b43d832fc3377a517c64dc8f7bf30a449fd4f343e81985f1a07d3ca513f97070ae38e382f63d29207eed3cfa9158c9a91b769fc28ea831237276204bddcce5f59f4617e85abc82f8ef31c9bb26bb22298c93cc42bfcb316daee3ce719cd77b8f5c95c06f002a20a22e3bc4549d9d631b005d4edb7deaf93e2654ce442eaae8fb39f991af9f6c72a9240c0977f2e963246c25749bfbe0acbe1c20786befbff15eff5e306b53a220ae2e533e93941b082446549fd1707ca27f611924b67c0bc7967a0fcb8519a3c19f874bb36691178121614700940ac9a74e45d6230e89149faae63cb4e1dcd8721b809b758e8d0f25efc536529f7c323df535989fe9a2b491c83773b5ad7b834b8d35ecfbd7266283742f9ba0422612f04e2c981d1b4c6523a5350487eab8c06b85e82d11d5840630aa0c82cac2dd4a991c0bc1a895ecd825424673efddb0be1648cd66aaf5fd9c5e40c8773306fc2ef9619e5025c9b5df41bc8f7d4af546292db9c9f291c346ccafcb17c3cfe5b4ca3481584901e881103f28956a9a1ab6b08d13100c4b52080b1cb1d655959c34109674a847932e83eeee195e756f669055ba47e3d877fcb35ffcfcb3df3f67267d6d01a94b0969db6f00d8f3b06f1a250ac2c808e1a3717135673027aa080177764a95f1d9820779e58cb4da31e92eb958cc81e710198a9e9f1528f3ad096115cd8f55d0423caca09f7c27a63b488c199894fccc013b4a3f0b4771238fc44e68590e3667dc39eaec7b38671c9c7208d68b68d81edd2986c8a7b4d0233de3968ada2ff61edd49d374d73a17fd20412fda0e0dfb0e75ab1a6fa3095ee38116979c5025d7c8e42cf73eecec2546c14af509273adb530511f6cc1003c48808a1139b076ae9fb222bdbb9af4e2f0abad94985dfa725f08d45b3253fb11fdc174887921a646e9560256975f7168901111d9de5988adeeb3ad0846f1a15eecb2d383103cdb72c28bd7c065b9ed2a8ba9be83882fe48436bdadc9b8a86e51417c71301de1ed99e30761bf9c4ceaac432d17600925bf580fd72105db10be880a38d7f2b29a5297f1fc4bdee2c3f1a4ff4ce1fa861cb5c60b1ec856b93c68c3d7f0c560e26c88875d2d3bff0fe18a5c50b3453b7fec6790f3748374b66ea7c162d2219772bb242e5a904b14b6255e81e224ffb42e871cbd827b88489a847d70b6fbd78ec1e7c08e70388b8ea01787bf28108411f743c0c8d12b73686a7b167d2365e22c24f40e2d65c6e964a521649b3c77efaebf9a14c6c3fd2e6316ab718bcba6c1ee197928fdc229f8a31dd729cd54adb95d8daf317b0390474efc74d7afb03ed65288aa522c1b8fc19c30efd7917b2fef4384642a648d2ce5cdc8376c8e002f775f4f3c639d8d9b889f0ee29de35d15282a96bb002fa62636f05161bad1b65d107a44e6f2dd1837372cd6754f25e4f01d7b47ce2f75890250c7aee2c091bf1987eedfb6dcb8fa1a8c00aa5d81f8ee641e702fd9e26c16774bee67b1392e9a3f2fbc7d4007d14da9f2bd6088c5c35568f0be16c314519472b59d070d196bc12620706f9dc46d9b47061ae627da3bd3ec9e1ea6de95e57a503f2ee9eda5b354c2fe4795c66aa4c7e5d3d775b69eb6a03227004d29f1f3058c665fd3bcc8d8687e95083230cef45e2c1e5ceffcbfa8c8ad38b5cc35104086f3a411eb052beeaa613e109a74ecb366223592a58ea02368b67648877cd09e83f62a56dbcac11a00a90f6a101a36a36b873219aabbc3706b6ebb1d4f4dad594de6c3290ddb30d01018d910e692ac3bfb03b0d90ee472b63895580cc05edca70d6ec1707875daadce8fb1dd759dd9cfbb7a98b9762df815b609facc6f5e41f4068dbc4cb80a4b3809d0cdf14bc4d94087575990069190e79c03ffc387eca7976e81d5877bf635da5d5be6874c6776fbffef1d255ce0490c419ca47694b534230c401380c5e3a1384920893f57882c2dcaa89673bd2335ecd86f9e74e67f00cb2017f0b450b7918acbdd0eaf3af69b16042736bae8ecf591e76de9a784cda7997c00a0bf61f93c4d037a488839c70902f110e4aba4701bda173eaa8844cb2084c3b6e1a1e0a94c29d26d20e66d233ace66e58042aa69b2754f617caa2401639659adf65d61b1fbed5c6d0c7dbf2a2261e4a715be1e7b64ee3775022e8b2d226118d4b3bee40e0e0fd33896ce0d9384ab0e22f7a1ba6ae467343ae281ad9bd384ba7e7c97c9586128e22691243445ffbe9fa0851a5a3e6f731795e5373afad96ef94d9ea565bb48fce853f40e82da66ba4d253dccbe9965cf05ff86f002e8120cb461993fca9bbfb43d6e8789b614502623d9caf371947f4307a7060101fa71fe4bc80c893ed7b194cf499b92979de0066fdbbe5123419b290795c74a3ed6603c156a8b02e9af0ab3769aec6958b9d7d84533a28c2915010470218ac679e874d19e690ab05d16bee3316dfee717d35eaccc92cd09907499d9b340bfa6d4557ef5a71766320778b9cc982dd080c9f9a5be1c496813a3ab7f468d80aec23933cbe6d4282c89c9b8e6df208d78a0a1400e0664291783c5a32f6b662d967744c68b6580d4993d1a9ab470037d2dc9aff5dff15ceb572e797629a0306a6cc7f8c08cbcddd8d2f4c81c192170dffa0d189e97541b20bc7c5a5a0cd070a8aa1a218d0def3fda61d382652af6d1bae174147b7e8861ddb2369a0840c0c67a9087820dbeefafe96fa188a2080acf2c70c4eb6bf99e853fa93adae45c8bdac3554507b9b5a9ac023c057376602b8be405b27a7962bf163c7971f40b4da961273803ff4a115d2b888a5ce7b11871e98bf00ded33f9d2004a62cad884069627cb9ab8d3bc9548286aba93fd38efe483585f412c280d2953e9ad0ba29e6ec2822f14209ff97cc43c2e2e2e6f6c609ee08716f6f89a2e627f1bd09599eb6fd464378f7af8934683c4a78ce14a1a5b963811d81f6928778f047cdfabfbb0a81497e00f682c85887132a0fb4e9b253a30adb69d7682f2795f50c496120a12e1fb15456a3f5a9da6c38bc8529dd7d9b2be23ad1f6069313006e6d4c998a0397d7fa9392e9a2fb92814ca62bf13c28706946b325788bdf4d34665813031cde4a2f20b36d0d5c5e2974f3bf363c00be7750edf9ca18faee7a84b82de02cfa47db24ed5be0c1146857470df00172e82ba16461622faf5b0382ef295915f94868a0cbf8310c5d2400f825f813776b719b9f3ca27655c14e56b0e9cbc7bddd929e56b880a7e66c443dc5c1f4a42b564806e7c8f5cd947a127069a862cfbfd9e84185d670341c7dcf78763e860a8b46a95d36d18655f6d13f1cc0fbc71b434afda4cdc4ad87a7134a65b5d1316e74feb1d9ba701d73e1c0d1046e0db71c1036f121d82875cde2b1eee4f51dc3b2ba1c1d8f63a27018b8b5e71755b8c396ef615096aa0067392f20f25806f40c321ca94a41ffb60f4dadacfd1d4dba8916d756327c3207bc870bb181d21bbc0f1bbf47df0bf2f34e6836981431eac3b82a16d76bbdb22122325805d32f44a8fb810a75493b582f8ff4ef27d047e0a23fd0cc6b915f7a50f0cab0b14e0c3039769abfef8a7e0645122152b2cebecf5f0807e603c39c3c26a5e18ab1702f1a8cb8576c9a8b6c2c58d555baf9f04f36e225adaeac15ab78837456ea44b785f0210a684331b118df62b17e804b6430b30399f216b0d29864c6062a82d84dc496d3ad2d871187c6dd0348c5c5da89f290b4dc736882535fda7e200bff079878632b78a9899755f53e1ef263a88e809a1e0b825624f8f4c7bc31071f25aaaa1093b3f55f1759d3f767a7b8d59bcef24b14025034c09088296be31d91e546b0c54a79e328fa9229a2a12ebde204f977141dbc20b2d9ed4f1c92acb808d1ea93bcd3c5e9ec8516e5b633f6bbfdf31ffeeec4809779a87b1ee19f392f82cc37979850331bfb90494222b364430813912d5cc6a0380b5e3d8dbc8eac08f8a95aa218bb28f7f5a0ffb10bfb34ee5add1bf5d59a45ec4a03abd181f68905f95bbabbb4c2b2ccc344af5632354145b96d6b9681e1dd3fb77cd4278e448e3697ba130b784f66f3a18bc24d6f922a31f67f145606f5af772097e13e9b7111de0695041840de24bc275699f0347b4982e08b04d026f23d02c165473a49d623f902e11378040e5b3d6ea2528b0d3d5949315216c1cd976a9a91548cf5cfbc94e752e72b7795fe7edb1d49734695c8144c2996b8cbcaaded87c78203f9ff3a7d6c6b4b784aecb708c54d1dbc3fed63bddd7631325514bbb36110973150290ea7ce40b7761fbcd47666ecf09aaa5d7e5d4ec86f93c28804d5c3c5a506eef7c701b44874ea73017387d70f867d8a270d5ed911e91837c4a52804435cbae8509d1ff08bd9db29b63e3ba9d435d8e2baceafdf28202e57bd5cb07f4c897f6f612bc6deb059c4d1ce42870a26ff5a0f775453aa940847552bfea0323a94ac5e2e5d4f30c26a452560c55f2ca9fbb02d5fe0b16f0c5fc2d0b19648106a7decfb7f60cfef0699c5447f9c337a90698c189b8c4338ec464c00b93c488f0e76f4ed1168ad32b4432d8afee85f0e97e30fa6e36b0b3784743c6f65503747362a49379c871ec2dcb80a4b2f68dfb8fdb193ec142f8dd634ff9efffdab1ede72552b63bddb5606dca66fc07d38e4051a05ed481dab9ab13b7d96c3cc872df0215e2daf6907200f8ae94b242a5d98c4bf92a50ae01e682d273a743b10735d5308f2b2da7402d4120a0baf21ee3dd5e658fec7fda21b1a559c0e625e56682e421bbb2fb6d5ad5fb9a764228fa88bec93be5f5c58aa8bd6609a84dfc221d654682226cf4853d3a05653697c591e3e2ea71e60edee124a0bc3c9f81dc09e7a90d8a3b479589764aee2592a9798c912ad9b1b7318a42b69ab6543d520c5a30aeba36723eb2bd7e77296e85d759d8652c88e9d5118f268addad9e6686118add0a64d3293aab04caa540ed0a98baf7a8e4dff0fee755169cca885de9288b1499d1dc7a45d5cfbef21f9251b0ebb9e16504919dd192ab4707c95452cc6b59ac447ddeaabc2e7801aa879badeff7177893d813e9dfddca53ef4cad8db703e28d1dda30c2ffb1b419a71b1d2022d2a502f8a6774ab191cdaf804221544620246952a15be0aa200b3728a9acfa0ac9827eaba05d1ef170072d7951044f0488d54aea2ca40dc0d5bec8e57d2b58745267362457236e3e23638159933c770359b120556dc25239d9eba82f375265f67e85278e816a93aeaed2e61696f74b1325a4f5067369d1dc086b005d114a2748b3cdfb3161568ebc33f17e8093f0affb3f7fd08815af0a6b0426b908d64607fc81d0c4ae5fcb56584ad535bce8d0da7e1fd9f54e5db24c17af186624312989c555c6846823f3e5959c143414a99ac584fe96d63b38b5903a0ab875ed4f019951148661348beb24e35d5863b266b2821be78ace129a658ce73e1a38920df9c087d080a551d3a7c5b637ce5d3b877f7022a05dd6b46a3941b15e5f5fab98e59538f7bc48f255400f095de18911147b26f512242b82ebb7940cc834576eea198e0f65ab2c4922b1c1d6d73693bc86c273bb71ffa21763c79683f2b5b6f691e60d8ba344bb63ffd2c8c651b0000f30dee6f5a74d8fee928812204c815427ea5376fc3c4b22f1c11a85514bf75fd9ba208a9af20ad1abbd3180f7c9207c924a6df203b8c6b2bda29fe8a7efd55c4a1fabefcd9d16bdaccec0f6f602540efa1b9e9c5fc77aec0801d81288473c43cb08989fddbf32501e759dcb72ed622207eb8deaa063e198cf4755db5cd59f70fd6b7950294f2ccd0dc3d2baed7e39f63a561423208195e87d31a4b061dd9f6841ecd8a277fb6fcd64615495e6af0f1efb1526048f2581f7b0a267ef352665ede5670fcdd98d6f331a2887818bdb5bb695c2eb31adc3bbc49bb2a64480588b5d6390da0a480ffb8b6d0fbbbb05119b39832006b4689666bab9f9c662ce021877ca019a3f4f85b5f1154fe172d2f2069a79038eea284729bc68f90fe6847608d6c3aa7d95c05894b81e1584b7919f4df0e14783a5e55e01b55a558b945aeb448d533a55a1b8b3b319970e2a2d6a741c66094fbb755e306c001d5256929e718999a08e1ab7dcc231e2e2927caa8416339b386d3556746095529c776a2bfbaa4de90684dd3f719be1e94aecd17f7326819629f44edc76e0457ad40fe97c350204fa884fa813e4a6f649def117c2be4c06f9df26d9d69f4672c825e473f6a84e26c204ff652e6d74ead69428a1c1790d1452f639d3e8b01f15a00981c863f4beadf8e03b9249ecc020f9c80e34285b9ab15113167c739b7563ad57372650f8e7e1c4cda384607d7dcd1ddf520c18c9485910550665362ebc928f647a94c1cad6a71965a4c017cd303aa794bb254205e19a7319ddc8c95f9419b561f7ed2fbde615c06819b50bb15d13f2c378d74e91df559ad81ae1e0d60c00cc03f108359664f7f859d5a30d0e566f01fe8de8d6d49ffbb898888086d5ad2b6947b6f29f79652cac80a850bf40a964a6b6dfd9d41d0aed56ee3b8099381519b00683e7cc8ee44cb94d3f2a769acf22b4d8ee3388ea31ca59e8abbd4d1eb41a5b970f3e8c9d1a8e7a7d5f1e238298d91a3dd765abb8d528e7b766ea3996e418a169ce818de2d77dc2bc78538fa06af479c4247e26dc31977ca498e93f24537ee357f1316b92d8c32c2eed19b61cc10be2a4bdff3df84c5982d3e1a6486388463a27c5184b5dca55adcefa763078f68c510ac8610e02a180c775443838915a23588b2086999d371c668be1c128211083e9a334d6f1a6eb9d18dce8cfb8db676555659ab942ea1cda3b90fe82db4394896d119c658e15311e1c639b528352d462dc68cda5ac3cda3ada4b4a374b335a31cd7719cf6bbe12df372e696ac6c6a91c56db64e4dcb322d6351aad19c9d522d9c915bc194a732cb68cd42fb53b5bc94544e6ece4d6dd5e8dc366edb4422f998493927a5d9a434d36496519ad14c4fe7a400086d9ec849cd49f6f8ba3266f32b6599cc7f3d46ca171f01eddacc59b680adb347de885bd4536e0867b90013462b306ddce7024c180a0410be528c0e74542f088a1313854feae869bf9a5665ad73ebb8cd4ed60fedf59a96639c5c980c4cf3885668a01ac02a201846a6548b47b4a2b4865216a419e37476cfcbc9e464f245ecf188556c958c9e3c1ef5db1a328f47bdb5dc8643fb01993635a9516dcba13d4407da66d7a2156f0a3d31bbbca419cd92db2c3dabd22c9b19cd364a9fd07ee39c74679bad99d428ed414e0f08bd9459949282e1d6c757cc14bef83be58673a29eda6518731766e76c8f193de7e30c6398f8e2e5e9d5661d421f6766d159298dda66b58cce99f5c07940e8b3df897fd8b419d61edc18274061c6e4136885427ddcf5da0f35dcf4104d4a272e8e37a313247e0994f0049e38d133c0101c2f04017ec4d131af97f171221466eecd290a43af9dd6bc61263ccd09a19cef095fd41127e25c5169c228d6214563a8142ec6d2eb51af1d6721d943d0e1e0f7a00911bd02600f48a7b7b072386f20aa7dd5b2d7ac76dcdcb20a8489f92138777a3ca2153c221478ccfcb0a1ad357a0b6de8e1486d509c98695ab555cbe6f7c6eab8b9d95b9969cfb6d95911e3467560cdcf001f3f6699649265cf3c9d659565332944db67b9b26ec765676d9994b6ca5aabdcbc0974f1e8496088951007de31ce39f08e1f69cc8e3e4688a28ba0ba0271220743c020450d25384394243bf0a727802112883bf08f59045dc320f53b35dc80eb097a2173889d191637e609df766dd3340f5c1ffb8a62a0f0b1767c64af1740dc3162032e5dc320578ba1c2a71d88edb6fb109dbebf9ad783ed310622282145df0e48a7b9b07b05b2bd7b3dad5d67e50d432e66e7cebab59317a2ef6be6b84cdb58b67695b3db76ab01d9aad443acb4466e7cdd18287c1cc519d6b4c73081b9d0b95b59920bdd9ab7c8b244d49b38e4d1b12c17aa211dcafa11f27e74dfc22df516ddfe561c03e50b127a86639ef0713da2159a88ebef5c0e22baa8fbc2500e79bf1be67290ee99c7a3fbf6e8edd0b11012c82e7098b80f418743bf43b7ef41d33ab20b215452c6400425a48c81084ae0d0d0d438efa98374b71a08cd59f969515c51f7db65cec397bbcf3c20d9b9700fd137dca2d31865847eb328dc5edef752d31d0e390f7b1e1743e766a4214fe370d6a1de0fbaef2b8ffb799cb96f61cc41b490d5c3104f6a52e8694923d2883cd2fab1a9c1f8b3008599a37f52e40d5944d254d6aa152299b124d4466e61f9c87537ee1c9051e87a79857823f4ba8228030a283e1b3d22b8eb6cef11a5d4d6723da2fe5aee7939517fd6da9097f31d67fbfb7d4f647af06d974f74fd26ba21fcd55b60d6399fd870ab2111411649fd5eb9d73b7a6dbdba5e2fa3cc18cbabe8f5120a190bbd5e6241de6879bd9442def8ebe516e28df77af9835f2f93983672bdfd72d41fceb9bfad2c939041413d73d3d1738553dcb6649984a4912e9034d588a4a1e28ea8a6a3d7914194650b224d7d28cb174423f22b7d224925de445d6da6ef966db8fef56e74a9bb9128d4594f52a14245d6cbc1a9d6fd4e755714baddbda19c32613588e66deacb619cb7e065e9824d1a99f2659944fde580a0e8a8bf4f4e915324956dc341d4863462a4ca200db471a36769c495e5112af16bc9d2084b9647be502661ad0fec48fb01492229aab9a4437db894a56e65d9822823060ca8cebb1f36ddd612f8d2cbc12ca6d605f1491ea130222eb44ebf2ca4908c4194512f939034f572ca141d65c88ce07a3a2d52be16cbe2944c6295a50ba4118b33b65b96262f475671799605db166c5dd80245a12f0cbe59064d989515c49b30e822f2869c1269bc9c2d9455a29793ba8ee9c2f6d8666c5f602ba3c4a7e9e803f4a3334f476a14f5724e9f5e8ee9b2c485a48b4d00389b17d866297b4ef0c923b287c7d4d2884c023c0cfbaf860657f382631623b31f65980c078bf1a22e815f8e7a24ab7c9fe8c789de928bafc59a33a05c20268c5ea607df0e9b96055a51f48e41f2490c924dd8c0e61829df9e4966126a639b30188f1e6f23e688c11ebf63daa079bc0f330663c6e5f5f808cc58cce32d3063311e3fc48cc978bc068a983199c70b9137f2e33d206fbc3cde087903e6f133622c7ca4a9df252c74fd66f188326a8dbcb1e330a20d1f2f62ecc513406170165d3369fb6bad7c27b7ac43b74d863c2c7584e86db46d579371bb611b6ac38823882011b940020a298ade65723efd1c3baeeb421ebe9dd4f7fb7dcebcefcf3da21e1d636ba5e4381d2aa5873b4e8674a80e6d21ee232c121d94a1efe5f0b5d65abb75dfb0deb687b20ebd307d7f6ff8dd93f9f7e8e5c85cc7bc243c12fd96b00d8f7823a31065ec9037241449e383da904d906812e5c88f28e60adf967794a31ec55cc7bcf4f6dc2b92260a51284c9541d20a85a9bf2243268a4b26627b11dfbd3158c81d9e3b9030752ee1881174ad130848705f08a304f998416f5ec85307b10a41898c83b65e78e5890309abbf73de20260c79de20d2d4cf11c81b369c398834f53224f8b6ef99045fdbf0dee21784c49ba86d78b31a7fc6ec72f859aa95e2f0a5e6bc1e501a87b77a42a28ceae5088932ea1774f78b313ed6f82b31f16dbf56cb6296c5f80a712f792a0172c36cc2b6db709bb02d3462c2ea331833144633f5959c8c34b405983c95489afacbe1c0c6501193a79238719699c1177d7eace8e83345121df568142e21c3678490a7e2cdc6e1735786cc1766818e62728c4c2586ac0f3e2ce28430c25ff7c48884c16e891226855460c2a5d01a50f8b4a1218551def7292e38450b6691592267f4bb22e153961a66758f5db0df124665a969602dd46fc6f7be8b328c5f134e65a967f25c426160708125f5cb72c2aa2cf50bcb6d41e1950b095aae2b855959ead93363af70de20c2ea49e0ba57e15696fa4513284da0fce61566c95287792ab1728574d245906fc8c22d596aaeb4956ca9749c655014d3eba3e96720bdc6298348af290d82df2a781b4619323de17d816f0bbb70206992489a7a1d33a68aef85270a63acf0c98b3c1e52c396788e9ae5e57cbf2cd8c5138531517cf2f74545df9999a4d68daa97475cd151ac4822f286bcd2243a9137249448531f65949964a79258e1a289ae975096a0ebc8f529d0d032c51a583a12b4423afa00a940b35050f47de99ed0170627047d61d607532cd1370616651925be4e471fa025b4e6e948bd7aa63af572529f5e0eead2cb393d7a3923bb71ddc51e0e4d11c8c032a0161daca1518345b527caa89741e29b4b609288f28c01c217ba9cf9b4e82498cc9dddaf0cce66ec6add37c9eaec153db344210fdbdb75ac1f5c97b70c26540ab562ad5a2c2dd75d39cc2f97d70b8c179818303132313334333539d4cca031a346ac868d0e3637376e70ec8023878e1c383ce0ecc8d9d1c3478f1f02f8e1c30f3e0c00c800821022081f7c08912d5010d94e01225b2a40b20d1a40b6552890ad952cfb461f48024d27132a855ab1562d9696ebae1ce697cbeb05c60b4c0c98189998199a999a1c6a66d098512356c346079b9b1b373876c09143470e1c1e7076e4ece8e1a3c70f01fcf0e1071f42fa6a9af68d3e90049a4e26540ab562ad5a2c2dd75d39cc2f97d70b8c179818303132313334333539d4cca031a346ac868d0e3637376e70ec8023878e1c383ce0ecc8d9d1c3478f1f02f8e1c30f3e00fdfc90ad131fb27dd243b65004906d941fd94a9940b63e59f68d3e90049a4e26540ab562ad5a2c2dd75d39cc2f97d70b8c179818303132313334333539d4cca031a346ac868d0e3637376e70ec8023878e1c383ce0ecc8d9d1c3470f4f5f4dd3bed1079240d3c9844aa156ac558ba5e5ba2b87f9e5f27a81f1021303264626668666a626879a193466d488d5b0d1c1e6e6c60d8e1d70e4d0910387079c1d393b7af8e8e1a449134def235b243db24dc2235b2539d92ed9912d130964db44967da30f2481a693099542ad58ab164bcb75570ef3cbe5f502e30526064c8c4ccc0ccd4c4d0e353368cca811ab61a383cdcd8d1b1c3be0c8a123070e0f38585f4dd3bed1079240d3c9844aa156ac558ba5e5ba2b87f9e5f27a81f1021303264626668666a626879a193466d488d5b0d1c1e6e6c60d8e1d70e4d0910387071c8bc41ee121d72b38d9f6e86c89e8c816891cd9168940b646b2ec1b7d2009349d4ca8146ac55ab5585aaebb72985f2eaf17182f3031606264626668666a72a8994163468d580d1b1d6c6e6edce0d801c7d557d334d3c9844aa156ac558ba5e5ba2b87f9e5f27a81f1021303264626668666a626879a193466d488d5b0d1c1e6e6c60d8e1d705ce162875c8170e43a2500b952b9916bd04dae552090ab952c339d4ca8146ac55ab5585aaebb72985f2eaf17182f3031606264626668666a72a8994163468d580d1b1d6c3a7d354dfb461f48024d27132a855ab1562d9696ebae1ce697cbeb05c60b4c0c98189998199a999a1c6a66d098512356c346071ba09f1f4daf43ae4e6c727d62235728b15ca3d4c855ca0372f5f9461f48024d27132a855ab1562d9696ebae1ce697cbeb05c60b4c0c98189998199a999a1c6a66d098c1994e26540ab562ad5a2c2dd75d39cc2f97d70b8c179818303132313334333539d4cca031a33aa94d68e48a6446ae490090ab921c725d52932b1307e4da44967da30f2481a693099542ad58ab164bcb75570ef3cbe5f502e30526064c8c4ccc0ccdcca6afa669a693099542ad58ab164bcb75570ef3cbe5f502e30526064c8c4ccc0ccd4c45528fd4239a9e266b576672ed91912b11995c9188c9b548037235623a995029d48ab56ab1b45c77e530bf5c5e2f305e6062c0587d354dfb461f48024d27132a855ab1562d9696ebae1ce697cbeb05c60b4c0c982b5c70a1e963640d08266b536059a302236b412f59abc280ac59c9b26ff48124d07432a152a8156bd56269b9eeca617eb9bcea37fa4012683a995029d48ab56ab1b45c77e530bf5c5e403f2e5973f2cada9317598312662d4ace9a940564cd27cb4c27132a855ab1562d9696ebaeab69da37fa4012683a995029d48ab56ab1b45c773969d24443e2ca5a9296ac2961c9da9256d69828206b4d64d937fa4012683a995029d48ab5cabed1079240d3c9844aa156ac9586443ba21dd1f4ac9c5d5965ad47953522a9ac2181ca5a910464cd48965d4dd3bed1079240d3c974850b2e322053cea69472468594b3203067551090332b59f68d3e4dd3bed107f49333275fce9e8872062594b3285ecea41c20673e5976cdcbe19c34419225c994644b322613466f809c354161a81698e86db9d0f4356748268c6647268c4af1edcc88912c89782335a749a96d59966d9bbcdbc5d76e526e55ab75b3df3ace4eb9f5e8f82204a221424c494408a7940b52288e5a906ebd664c432dabd16620e2eccf0ff73a859393a354f6abfbf53ccff33c11ea3a26927993b05e7f99ac5e8fba3e507ca54d8787d42391089cdfc7dd2be5fdee95525ef9c9cecb893aeaebe588cee54e74974c58b5d65abb5dcede7bae095d3b8cbd9ca845dd4507d2f6fbe5c48c79afbf4dae93cefecc588efafa783f57c9b4215a42618e4c1ba2239789ae76c99249f5a53f16c852118553ec8fe808b56181a8e82a3a42edcf84dd28ba729b2622b340574abc895eb0a2398edbb6bb7ddb76ef76efbddb76efa3cc98fccd6ece19fd3ed15bb85b7afba51854fd7462ad7e3a9d4eabd36a754a653bc502752254b63f76ca84d5d00281f85aa0d249cf7a66acca177a6909933d81f85eef5ed053e286be16ec6516f8a84ffbfae89f093341d1a4548bd4ca768a677f2c906994a5deec14fb6381be1fd6c7f27d2d9b7595ec4ff6e58dc1aca7bbf2637d210f4b294512e39f227a8b9adc29a2273362d868501928151d2fad5079edd8fa6152669865a5fae9f1972513618204b48b2e7098107139060a9c39a93271971db6215128c47dbbf7de13c7711b66c9445a67b9f438ee75ba8ed9ca11c77e955f9baa958f384eeb5762aa5f3fa7fc92d15347cf1ee325295d732867b4e24dd42c39e2e0253a6a8d71d789ce12853cdc755db75d4ff3385546dd94bbaf72eaa395b5d6da4d75d36632dd9a54269589cb47bdbaf0cde33aef940f7b9deb94b898cb324a34c1e517c6a42cb52887973468f82c57825198fa0b62ae0b44d097b40457c2dc7d821e853ccff3501e17f2686cf15d1d7da88883e67e4d98ebc2135a85b7cc1a3da774eec354ac4173bf28ee9d97c36d96cb7fa53c4ef378485d3ae8d1d8828a2b34f7abc25c139a749247630b2acea0b9df9256a225592a952217da20d0298fc7d47f8157e5709b65719ce7b570c671c75e0eb7598f850452b9711ee642215128d455d1dba66b596b4df385055b0bf6da5e63905252b971872fdbb6eaf9107e5b666bad5ae6e530f178c8a825a192cd18cee49e34de9820dec87803347f26d0fc018a3730f8e20d8e322618e48d7803839b4a7dca1bd58b13cb296f78515f8aebe4017ef5a2969141d6d383836f3da9698e71f2451f2b51280faec4b44a95372895b24a9a5197d0dc94e8244dac42de983179e3eb622093f5f5643c588c021303eb81dd2364a954b6852bf393663945df7acd180d63ae90da98a099966d4400aa893a72b1d684dd30dc6ea822cdfc9eac5494315372cada59b1d656cd22b15a566badb53ef3ecb32cbba6691aa55956b56ab50c084a6e7ccdf975e1a35a46a595536652a35ca6ddbbc9aadd16d02c35a53636ea446f189d3234f84651c6fc94f8aa566badb6d63a7b4c1d81f0c9cff750a978a02317b63967cce60e2c0c466d6c35f5db75a32569ea378b8e3b20719c158a0bb57eab4a45b36b2a954af54ea5e2ee8c1e6ec91b8f34d7aa77f85b56e10e8a1e18257fb7cedb260c1f775dd71de71ceba1a697c38978b0da72a7ca30ee2e3bd5b76c8f6f459907abdb51acca5147adca52a3b24c0d0d224cd81f719cd5af9c1a2606bbca34660da9af8489e1db8f1165745df0606051c6946f5fd7bfe8ad9e0d63a2f84c79bb2aa7fe9954a66f4b95b8eda87cfa284b4d824dd8a9cad830a60956b8d0f29bbd22d3d1c70b26d0233ae7fc80a822071116f5bd4b601006f665de1d61db852ef497a5e6381c76d7416db8090144154b4498a86384b1bf20b65946892e5cd1f78457990813acef519b7ec47198289dcbacd1a32681d731319e54479f2a4a38c7de4d86682814ea640d6d10e89a09ab37793ca6169df0b66d291c338c55b8e255d4a028dbb61f247adb8c6a69de0835b3f4953e2d7cd93fe79cb3d3c2a5db763fef754cefb788be9ea7e19bbd67debdb6594a29a534ab1dadd5669bb576089877ef621926d55229a946e595d2daad6a34bbf55e8df531a3746b54669de5364aa564fdc8ae5dd3b2ccda70f36413d62d81b32c7cf4fbcb3e65a64996a5d67634cb6c4ec6c447bf37a9359ae3b6859b476aeb6551c6f472b228439e521b465ab23c229f4041c31528d0a277afb1c9a29006e17eaff480e07fcb98bbf7cdbdfbe532ecb5af6990fbf920dcbfed791c0af5e8429752f8e443efb40c83602fdcf71b6569aceb6f9e35bd29b795b55a314a8b091bce628ce223db708c3e566e7ce10953af6083a7e78c5ae893d6344d0bb709abf531168bcf3e3a410a3e241da3380312ad9dc313567378f2c53a61b4d78a832ffb84c30d8310a3e83ba3d0516a31587c5167b01e64c29a49c326081f4c66da885170e86134e24da471859e73c6b66b6a3a69d431afb7ec52aa88e8e883061ae878e98541b267fdd9c315a38c4c079541c26725abe28909a6e8193a3e39e2476b3e6440320625b741e4880d87c8111fce7d7722f8f138b7660dfa9b593107fa2eabe20c1cb6262c4cc51ca84c922f7bfdf6cc6ebdaddde2cb1eed10556f2107a8b6a756d79a0d417546a17043795b1d32031257946dd143f33e4e1d002498d0b1d1f5dfb7c7831edb68cbd24e8f6062fe7badd1307d9ddaf48d3236f86eac5a164517bde678510e82bfbd8b9c68abadbeb532d155577d370d89d6b4a66f970515d199cef4c5f48aa69aea1bc2a1bca70ebd8a9e7a6a32009141ca957a45dba02a7a3e5486227a3ef45ac2d2ebe1dd72797ee3b887a27ad1d4389c77dabc6f70e819468f87f719ee7afc2f13f97e04133a3b687b1db4dee8216eb4a8070e2db3eed10d3d3acafb905106becd33eaadfb766897ea9dd166fa50ae791bb183b541701f793fd8207ea8ba3ee405c1ddf37ed0743df682f821d3f59d17c40f34881fa6ae37a1423c42d74e43eaf5d0815090d01ea2a9a6e70ee43e742e874e73d5d63ed32c90b63a984152b411fa8aeab94c84d5dc3594c6af9ad33497698e6a6e6a8e08a9b92d3f1c6eeef21bcfc6c308cdfd867abb13ad834906263aea0868af87eedc2fcd60102e574b0b0b4babc562ad562a550aa350a793c9542a914820381a7ddfaedafb1565334604fe9557243a854226cf2b614cba17ecba11a7f1f77ddf475f48e4880f07f55148e48813cee9448e68e1984ee48810a7742247c070482772c40c0e782247dce07c3f8206cee85eb8ed33bcadbe97285d5f4f5533695929a3243ac1b9a510b20b9c510d427681f38531e620f7aa87792edcd711d03b027ab33d9e98c00a0f1cba86e11e423177bd85ac1e66106d33be9ddef4d5620dd51f51062eca604547118c01c92b2a201b61fbf9c871f1b1e372e4388ef3b82d9cdff6ecb7fbd6ae8771eee1715e163204c7e3c15dbb1089c384f6aa3d71e33d20ff9287c54c47bca19f88063149f8a68d9e3f9f7cbc8e496d643d2c98328f6d6a68a46e85931a194d53f1f4df13175c29736483e919db44a07dac40b25f7ace0c88618a8e3e62201206296170a2461fa17265eb21b2c5166ac86294182546f141a6061fbd94a9c1b7c52d6e78c26c67f8e8131b44644f768c4ba556ebf592913ee8888834d2d3d3d383c344fdbdb908a9ef0ff9fbee4478bf2177435c880b7161aeb7b9c7d4971b72435bd68c6f90fb2a7bc2cdfab1f5f4f4e8ed556b40b21e20b38703227bb670d773c06a7cb9a50ec249afc73d7743ee756aced69e4d0c576a99881791551f2db5ccb44c84d4dab32aa98c326ca5f264ffd0d91ed2034dbd1f9d06426735abd96d909a5d0b2fb369658b2dd410062434747cc2c4c8a6397de59d150c4434ab0b2daf694e679a1b585473fa56cdd2adda6ae9b4d266d6227165bc614da1e5afc61aeb6e3efa4cc182142266318429a46c51052b5041034e8c30f2379b4f68b9690a45cb571d3d1a5b4c61a2e1404b1a5b4c498196544b8fc6165344a0258d2daae042579106ceeb21a39441c748d375b5eb3a3a37d9755d174fa11d023def83332df28832e2e38f8e13568626516ac81320661326335a436eaa699a166ec0d399cc0f3efa3d040dd236344ec3700d201fe7a4f177e63db3d32ccb14201fa9f62054a335a2569fd5ec52fb90a38ba8b370039ea6a1119226a2200a1d234d0cd2b302f28610492313306d6c14081f3aa80d9b800923659435d346cd84913fe243c5121d7dbee00343479f2f2cd1d233c0109ccda7863c0286e0d850880e1650408108477a70843081011c449e84c006e108098196831e1c267b031b987a885b049d3d88165e2052d1d9b70eed427320ab2187a04686e041c1153406a8111d840a2047173a0b37e0692d01df8cd1ef22a4a6c7f9cbe2a3dfac78e2c89228b8218a295ac0891166d355d7304a9aeca587804df94f9bda1aae9454522c73d41246332aa5a6d51c69ea0c36fbfda5365bf38da228433e95fa9cb854ca20f9401d7dbe10037de7e3378d71df59cc7ee31b1b8d36c2e46dbe11268a30f2d325af85d9a63f24df75f401da42cbf0e0dba94f0da567047aa65a6688c38df3a4a3cf142a604841a7a30f156008f99078203a814f1554cc2b62ae00b53cb5498318a280346816a94214681015576459a6e91f99f4026c081850cc1543600d7f21ca1bf76e758b1ab61cf8f4f67b9b6f0c14b7d3aee8de6dbb9cc5f7de9b53bd9c7bab2365ec4f908e3a7a31244d85d9eb2d813b9167bbd0a341bce5223e1df2eee6c5f06092a63ea60ad0fba4628a1e15c424fc95be7b7f4d5ed7dd7befe96eddfd45e12d7357c7ec3a0f08f7ed33240a85ec0f136b8a22d41d39d26d9ba4eb64667f31c638077bb7db11eae5589b61cf7bc8e362a088ba0b12711cf77d36e788ee6dbf39dcf1b76dbbf6dabb1d91f7c3a0177597eda7f7ddd2f5becb1c07246f74afefa6cc18678f58241cdebe2990452269aad497fbb62ddcf7576aea85ec916d93e87a6b91849cb04cacb536d40410bc714b88ae284b0d7e346167f8ece53f3cc2f8b333903447244d1547ac47638b2aa8a0b9df0d57f184e63e8fc791aaa38f17a0e8fb7d3afa78c1097d51f866e9e408053a3261f51b5d44b2775e7a43db03da263982c4bb694371dcf7619ce262562bf72ee8eb8236d6a2efc31d1780f40e81a1272fb6b8648b8fdb930e5fce860146af9067e300a7ef0098bee39358e9510a02be8a3b4e497d472a31e83b56f977d4c2f57845f6c45adf92880d057c4b245cbea591d7b74ce245dc12c90222131d9d80f12d9bbc7c4b270cf8964f68be6594996f2945c6b7f491f99652c47ccb9f067c4b201adf92ca8c6f1904806f5925876f69a5e65b6ae1806fc9850edfb3c7e67b12b1f13d91887dcf2235bea791077ccf2476f89e48707ccf2401f89e4a6e7ccf2537df930904be67133c7ccf2638dfd389fe9e4f747c4f2839be6794ef29c5c7f794a2c7f7fce1f13d8172bee794d88eef49c58604be67d00fdfd38a0fdf538b1ebe271702f89e57623fbe698f8d097c5322427cd322417c5323407cd324800ce09b22a1408ce243cb2940017ea5b76545b2d49ab6655bb66d314a4e561feb0b6003f651025ccbd90b40ad644528a53e7c00a20033866f04a80d038c4e3f8406664c74fa226e849069e300a7a79b4e2f8bcc58e994747a99c48c81a70838659d5e2a519da64e8f3a4dc0e94f5da72da75266ac75059cbafc75fa17a7e1e965d08ce5d3059cc638853985c188bd30e094e674e6f4f3c88cc94032633231a70d38fd643263343ee3f4d3891903c0e9679319cbe1b4e609b5e1001d6c4e6d9c7e4a3163b1d31aa70f98b11d4e3f83660cc7e96795190bc08ddf40e0f4b467c678383d25326338a7a748cc983e3d2d32633a4e739c46e0f414c98cf938ed717aaa64c6789c9e2e99b19cd3532633b6e3f4b4096a4302a7a74d66ec87d3532733e6c3e9e99319ebe1f414ca8c09e0f434ca8cfd383d95326d4ce0f4548a191322881810a7a753660cc8e92995191bc029054e9f1120476d63aa20b313204b18b5e1c3a4339665198e1d70e4d0910387079c1d393b7af8e8f143003f7cf8c1870100194010420471354dfb461f48024da753043e5948a177e6930514594441c709f3c9828a16c18df3c63450d1231d7dacbc41476f099a7d7d8d55b220c128892c9bb07a1e6c5bf8c52df8a4410bec93450fd5649c686129e593c510b238a2f7f737d4d4c828a146260935324918a2a6660bceca109cc7f523d453e7722784085048431618639797be45c7dfa1d0795a74e8bbfb0e29f5101bc6200536cc799e959edf3b22f033dcf3afefd2bfef0b7da75027853aa8a73c80832674e10c2008eed449dfe0572d1629dc1d28c11bba70834824129dbe51ff482492eaf57ab1421d978fc680840812a8ebeca0be8fbe4ba7d3e93ba78cd8c10dac24813a08b27c9356ab55eaac5027f569a1008328608142a14a47859bf5f9edf2531886df2ddfa893e8a9542a15ee196eab640925b8c2057ca9d46ab5be3f0a75beda042454a10610045d0e86fb74d177eaa1cbe57a3112855b035243125770717129dd25dca256ce190441d65f843aac8fb22dc22005155a0fbf4b77b1b0b0bc98673d8a15258850fa9e0a37ebe1b7ebb9a5a5e5f417a1cee993eac0096d28c2f77da57fe1ce0fbfbfb3fc7f21fae9f3891b5c21a5543acf4a97be773ed74be13e3dfc66798b482412b5fe22d4695d14ee30dc320d5ff841e27bf1edfa4ba5d28b704b2bbc600431f8beef9324f0c1132b269369489226672801089ca05244c90b0445aae0a384eaf57a09498210729083954aa512e20220c4c00a69b55a79e04919a454014522913c00832ea2b8818742a13af082285d2801e8799e112b48810b80e00282a025c212182461e4e2e25297f4600c52bcbe53a3d1485362ca0c5ef0b3be5954df33954a7def8459198430c515d6f3b76bf55d9a738639dcd34a152734c93f7db748dfa252a9f4a904201894e0f4966f16d4b7492412b158ffc350e7ffc2dd126e790325582003cb7576585afe7dbb8e5faff388f4cb64327def84d7d9c967fdff633d8842142c6f85fbfbbf5b0fa954aa6ff03b843166b158dfd1393d3f0c75f259e17eb841c0440d70605ab55c670937cb59dfff6bb55a7dbb7cbf0885422d3f3de77c9e169d851ca147066af87576fed65de17e9df5edba8a44227d8fbec3172f5e9c4ea7efe87c6f69f929dcac707fc00d5674218556abf5bde3bace8eeb7f2bdcad9fbe595fa1503b8761c8f2ef2d2d2de769d12de13e85fb033d45ae10e5bfeb0ff7eaaaefd3499e771e91f69ef379543a7f7fdfd1799de52fa10ecbbf70abc2ed812648a1081a5c2e972bdcaa7fdfa4a34010fc2e7dbbfeb7fe3acb5958ced3a2593ad08436e0000ba87fdfac7b2e2e2edfa2ef1697eb3c2aedfa7ebdced3a25fdfd159bdf5975027dcf6086368811758d7d9617da783a3d1e8dbf4cdd2d2721e956ef9def1aeb3a3faeaadb75ae769d12dcd0a276401e8749d9dd35927851bfceb9b7497542af58dbf5b2c2ce7516996efd5ea3c2d7af51d1dd455f7421dd557e17e853bcb02164ee003d68a749d1dd24f6785dbfbeafbf5d19ce711e9c96ab55adf5157a954aa8985921f2c4ea713e9a7708feef2bd7aaa542a7dbff856b158e75169d637ea3b3ae0bfbf843a2ee19e4986f00429241289146e97a3be539f2291e83bfc3ea954aaef9d97ebec7807ff7ddf795af417e3704412a2b05f2f994ca6effc4d3a9dcea3d2271004bfa333baf79750c73b088736b0e088176a7511c6f8fbdf1f89741e95267def94aeb3e3f2d1bd7bde795ab417022568c84213567f3d156ed1c1efd44de1dee140e7e9d079443af4edfaf6bec301aabfeff084f4771e95febe47a3f3b4e891cb4ba18ecb47e106c32da4081661d0e2f53acf4abf525ffd35c20178b9b8b89ca745bb74800a2b2ae0c16ab54a7d650a8542a15068f33285db8823dc208638a452a9d40b1a16066d78428bb0668910def004d453592412894299d5bc411452b004d16111265732091518410425d70b05822735d0c211fcd4f7e82d2693e945a4b4297c844991e8a8af421dd4a7077ed2a0042d989efa0e9da5b5bace4ee9a2a350a8f3b46854075a10871228994f7d836fa544dfd1c12f7d15eaa4c2ad5d014a0ed2008abefa1e9d8542a1506129759d1dd3f14b2f95ced3a24be15e859b52610a22538caeb3333af850b8bba3be55a552e945a47429fc220ce3f3b468fc1d9d79d353a18ee938dca87087c00a5c38820e4010fcde095d6727f4d1c170732f7d9ff0f70e789d1dd1e74d3799ced3a24d1f000209d87085d168f4bd53431f7d9330c62f22a571b8ed39cfd3a2a7e860a823fa0cf728dcf6045f38410b7428749e950e7def68d7d9a9d71eda5f1661125f67a71389ced3a245e10e853b4b62491547f4f6422288e0404acfebd038f4680e6c7a9e081d7ba5a74717b1e9f922527a8631c2e4f74e769dfa1dedd9f70e8fd5f53b3c265dcfb3dae1e974f71d1e92eeced3a2bbefe874dfbe83439deedc75b86f2fa2ce2ce3af946abd640e1ddca8e3bcf2e71b5d1f2b49d027cc26f8186189119ab0d2038a854fea2dd2540473e34b6a1d20f3f23f58d9a3c613f64d6a29655cf0451f2b4e68798fce2237be76cd9c73ce99852529c99065d88a0c196aee174425a4a1868f0e4183b44022cc8864419911265f9d73ce39ed36f3376b6b8cb0929c97303d674c1abe999ab01d1386fe567c74c3f1c6472b818dcf0cf790cfe24dbce93e4f332dde789faff1262442dd7c9fefe2cde80624953e1f8a37a71b796308506b37fd9a72b6860f752a91c0d1270a79f876dc66ab954c5ad133b6994c9ff166bbe934de70373d8b37dd4dd7e2cdbde935dee09b6ee38d77d3b77853bae95cbc09ddf42ede886ebe9b8ee3cde8a67bf106bce9a17843bae9a278a3ddf44fdec86e329532099445f4fc284ba1e745bb027a1efbd0f397899eefb2167a7efbd1f3d649123db78ca2850002e80b1126ea3b473afa0059a1b35fd985b611da24371788620576b0b78c0d12ebe8e5ecaf24b3032851bb94524aa96956d3e88f8ea752e8781aa4239da223d08435e184922534097a8422418b7071a58a15a0293e523c81e24413254b8e4c18922257aa589942c5470a28519c68c2048991a80595024cd84f149b00c8b4e2e317691046c1bd77c618638cf2f69b599685f3dbc4818ee4b4709369c1a763c2c01014869e982deed4318a32e6e39c35dfb7e957cc2eedf14d985445199f8ea4322df83eda8515229a1e3c818f8f3fe56bca13bc919a07780df53bc14fa9994ca720a683d761ca3a5060b8c19f4ca69f4e5253d32fc5a8a34c2695eaa9d42965ca44a454a6eb982ad353275318a3cc29dce0b36bca41c0fb61e9f1000f9e9a320551a79f72d4d20b4519f2a75fea81f1069fe973f41bca1a0ff0bb8e796fcde04719fc6bc6c0832129343dab07f0f4604855f7504f1dccaa704b0dfe9453394619a7a3b229ef21da0462a185a637614145db83a483997b6bc642a1343dfbefa70784de14eed041d44f596a530e02c6509707b38ed788745428c19fc08c7fca2cd2eba38e9e29f4d24f79977e6fcaac1eecc183619052c822853c8668117e3d3ebe059f7d454560b8bb8744a2fccaadbc05c137c8165a1f3b6a68cc21a9d9bde10c47f4f6499f59ad93f1c1177b241124e40da9553afa5ca183efa359035ef420df65786ff47e5979fe4a6fe6a8bd20bd9d35c36db656f84a2ccf8084de2eb9d0a44f2fa7f5994ff7f236dde38efaf4806c97e1f680903ec33d445fefc7c17b199ca9cc6a3d6ad604f326ddbb9c390878d54399d53aebdb3bcb4379b31c7599593d905842562be43144a7ceea8175d559575d75d2a36e61e55410552893a4b274e294839842b96486bb14ee219a144a29a164326114cc5fb8e5bfd3af68a801e79d2fdb8c320df9efbb260c027e3ec8b7c177bf7487a47c2824a5943754e57d0d11515f440512012d6b482614ee794e0699b76239bfcdeba0a32ca7c62d9701a372a8944a1ca89a9e546a666400080002b316002018100a874422a1280a14496fd90114002481883a523a9688a260855118a49831c61862080001180119188cc6019d72fb003b9febfea45f2f352d55753a194ff4888c3c3e8397d9c9b0471493ad88bab2f77996c51f1100dc067d6d89f8373bf7f9960cfb507b068dd9b4ad0d083b27a1776eee21dfcf3384a8be9be67496a7bfdddd6404270d761e3e946f4e27480e2334fbbab4f8c0dbfebc245362cc4e6be2522d0fa8b1b9abb3cc99072046bc15f2c8a415b5014aae993ee7024d43bbce7ee4442ad1341b218acc74ac24f4f2f235f0bd23977af7838a3e1111b8396530f3ad8b85f2f1368edbe266a4f76affa7071789c60cd0a658eb6620f9b3f8c1b48e3e1bfea545ecf1324886308125255132ab81c5b450eb5c1da3fc0118dbc0c16f7c239c0b09fd5ee1014187c438674897e61aa826a47081df4865d92350d4c5aa5c7f408ef004de0342907b616686cf5f5086d0a3a11ad39e1db8159d62652f4b0fb4da74bdbb787feac7d8c577622afa1797d880f1b7e8269319735e64f87652051806861604adbbe78a001376736fbd2b55c3b7a2c467c999f397638339bcaabbe7a31c54993ab6a7b79a18b025783002d764af337c35c971983c832636174e53c5e61668f9b93d1aac7bfd94d10c059b496da11cfe326da8f133a414950a9747ebdddcd78dd387f7bcdc0c43c845fd625da32ebdf70465cd0fffe07e78979ac03263ccd115f3a2ec16f977789f9b6abebdd8fa1af06eb9886cfd1787d9c134fc34a116aa9ebff73c2acf54b44df2520c1fba6b5ab78bf185c11bbec928b312e54cf582c21d8249e5aa5d38e8870fea4335f16b727df10e650156dc279aa11d7ee6689491bfa141e6f1c40bed3bef5ffe7a68c2b3b8ccad9b78004df8c3f55c267f2934e16daee6d626fe4113fef03297c1df074df82bd5b9b589cfd0847fb9ce65e46f8126fcc5f5dcfac45368c25bae389759177f1f34101e7e8e355175756237470f5c78f35d3f0c4b1dfe1feddd0329fc783f06ce37d5611e9fdc3d38e1b7f70bed0bdb5267eaa47afd400a7ffe8ff135a16e261f68928bbe528d5469ddec551c4b7053c7d64aef5d9c69d65d48cc2411e3fb1e4776a2252b32b0cf29eb5e4863a1fb223210a1a8f7d809defe9487ad8b33d2787aa6bd55a034f30c84eb59d56dcf6af89c7c6fab8239e5d94fd4fdec910cbb697b41c887ea209f230e18cbd3db37af052d70ae0ebed0e59e19efaf637df0aedaf127d03862aefb50414473f7ea15b63f84bbe3e80ab6dc8365497baf7df00d3cdb4f0366d88d2e441c44057bdd1d566becc5e2eebe116f4f9b3e45eb5fb235677b256a1c33c3fbb2c0e47116e3c53a2be184d6f339273c62c2770633837da1ce7c52bfd7f549b393c72a543828a1ff02553cfeac02ac8ee326cecc61c816c0d9f77f5fc1903d2884eefa5cc2d9c43f073f8e808156f113541b5e55af42d904a14c2974cadf563899ce0e723c30cfdc41c905531c50becc649def40da082074ee47e93f33b9c919397c69d1df4e910f5ed7ab896e2a7df49b1ef7eeda4075dd30d57d017ea3c110ae754e0540547a82fdef37e695e7e2a0367d906ecba080fc5d48025f4db40e3820b052177ba0c3b0dbf8c6dac7ef98b26922236d23f34bc006e26148e1e05a6fff7599d0fbc73be29850a72f63c11a8939e068ad8d3c1dcad5aa5ee0c2ea16d058149300422d1c7dc37467ea0fa907529422a3b8e2a3924d3715bd10bb6da909c482e220bcd9afe32963a530fbf4ca0563d74e3da5832155e1a88d4ce9594b4945983aa21dfaa9195214c1af800235d1bcb74279aef9154d350ae3321054b14917defe7ed678e3bfaa191dbe936c5610f7e9e84313fa6debc4f5e6e9fb0c9fa28c395027233283c878b1b7e731081ee2d0b80e28f058c5830bc305ca9f9b7d39b3482c122208f93f88ad9ba58e50b2bc74a414843546aaf56d6d2c266504a30c80029b2f39ad227ac3db304f80f4ac4a97591838c1b39217daf4b55a026cff47633eec66f41932b9c09cc49a6731441b17cbe885963de6230504c24a81de3d82768e44fa1ef4d5329a0e657b6ed2cfdf3c9cb99ce67200967d4320db32e580117413a11b06426f75e3e3a030aa756595496c985eba0ebc456338b0e89f00e4ba0802f1a25438b410644216bc67193c5357cdcf26e664e87fda243244523224b657afa0f894132d8a7b347122aa637e33a8a1fb297441f749767968a0ccc66707b386b110982c05467723921d288d258833c9c1e8b99c91b01ac193c4cd2ef559b1d32c0bfd056cf32118c2bfd9b58f42d147a960da499d826bb579cb8762258efebdc550952c7e3228d9a4792beaa2b23798fb5ed2057113a4ae1fe6976038475644b073e012d39ced3a194b716e5751dfbad7724438d9d472399350a82bd5944ceeb3e1b3212e0722dffbe43e6dec9a58807202d463b5af1821d7f076f114710a34b17d3148ecb77b68f5588bc2bce8cc4a3defb0d8110aa780202bc8503f06c693aba5e3d825366595f22266bfd657bc47a4ba193b50d1afcecdd445d9e0da6d4c6dd4a0764f4cfdaf5e3871e5488496cd08c5c459bec1174e80e4f6893ba29f51af8206f65c01631373b43f4b18f08803f9d442186319620878d92712404940f6f91760e2f4547a3543f377e9bbf70fdd23184e98608d0adb714ab6b7a10fdbd782851d92cd3d6fef3b26241d14d17311ac65b08ed62ff6992c03c696e388204dd9d544073983659f0c1798b7cd81e5049080921a2f3afb932c2237eed6a73987a79933fcc857e3b18d3d6a8fc72469d146072e6facb901839057900f5989b0480099ed00141fcb3b3e573582d7ad1c9a335093d8ac318ac3c8289edd0f658b862d5d70d4e4e1a241591475c282d24016929fd972910b00d5142c5c2a3c2eacc05c78f8b963c60fa763d1cf733c262c45000dd5406e02df50a6e9adf989d0058f3d0258d73b2a7f9d2029fa6849acf1ae0f9e805653153fc2460104d9e2eec6d4afd6b2227d14bbc1a09af77834735c9a3dd0521fecb6563d79bad8a526e86bb120794e6a5a06fc1e687c7981683338eb47e8818aff25b0226b47e802f1f1923d74f8e4ed2139f54e58a39ba3e4f2a9c88b803bcfd4ac76043d50715f025464ad182d25e33670e81564523d98fcc617d3f1e3e56ccbda459f45922253d4832f1c62ddd7fd7f74af0ba6015fb60ebe90504bcb14a450fe8f77204249e9bef3da0cccc9a06eb5235d6ec95b99231920ebc0f5321227ea3ee1392d89fa546861a14f2b2515bfee546b140d9b4e541775aa9aeac48ad91d7dcc682261a973c6f0cc87bb8f2aacec39abcb71f77b73abe1c6ab9b5206026bc37efb7b4e14c47d58f9e29e364d2421b245762dd497209cfb51ce5212b0e6a2abe7fb0f9222c72a4186a0d203c3b72a501b8c134c0e3a72ae087779dcca1a992ee828b401fcc9737b3ace8265222495fed264b5b3c127cd0ab51ac9ff081f2d62da108a60b18185cc11865e58b2f255659616691de138303d1f3cb01cd09fae7f3853128a611edd7ae15db417aacd9783120c04668219991c6e70f9a5dc01a049f460b730c90f44aeb08694d21486777f999c9fc632575e59f4295ab0b1b9687c68f36a30034642700b643c760cde0f3f63e4d41b2fbdf503f8cbd973098ae70ab44fb96f73c973c2e2f4ceb61c6cde6b3231736ef073d2ace04fc15c320b368b4beac7291ec7f2f891df4bd1feee065fc9a7ad85a9a0f059ff359decd159ea6700008343234a26297f3821573fc2289b9ad5fd3154bf01bf4aa255941ae5ed5ed679076c48b8b77b7b478662dde4cd4199849a1adbbc0f12bea8ce9538720fd0d361ab9aad4a49d46b3e1ba9378dedeca7d61178be49b6e3ba489f08df60840f151c7b07a6f83bc6b0647b72c74ae108fa2f60578de3d58db44ef233b9d1af4e3ec972974e98afff82975c67a98d3308be68fe606094816ed8a1191a5a49302ad2e47b432833a10be9cff3719778a1d2a9446b51503ed02b13f6858199557afa62fb77b890c43821f6891ef42be1b84e66c6f959082bdb3af2868527a4c994773d660b5b618453ade7ff5b602f1eefbdb07dea9b024b9420fb4d4eb6df813963e520605c62f4fc049c584a853889d082a6afbf70c341fe24e1e0d92ee650ec2fa07dd5757cd53eaee4431bc150d5e950627952d3880dff88320499b2263d3cf5550cf912c6ed0501682fbb306e2e767f02a8c2ebfcafe3d12b07617bab449f57e0aea549ea7205fedccb0d5fdcd429ebf3998b54df319595ccf1f544625efc4df389476c74d3a8a50804e532505b622c96d2a1344e810b2d90e44be01421cbe81a849dfb35486c04daea00c47b1dbf435a00289107924c1dd8bddd2703c651880de6a50215dd5dc02d688dff7491dbe9d8fa3e1303dac5737d624e1f8a7f9e208bb8b0cdc56b25da04355c7a408194f4378c6922dc486e356d3c1dc94d2bbfa9527e399d64c9095cfad3d5e5c1a4db7367d5fea46bc7332ffd0f9288ed707dc13402130d4822d6e32769cd1a7a949b3151eafbecded222c479c00db33599c11c34871b0ff1e42e884282c066da8a0a197934c935af5b864bc0645a538a9bc37ff11085755cb3c03a9611522e8e5d2aec9152e2511ca290d275b74af46d18ff57731fe6d48804f164d6509d7d995b7d7f28a49381fea8f8d5627e18b103fc1a97ab90710ee154bee6884af64c400e72e908eaf4eade9996aadb268153e07cea0ac48a17b1fd515f5d7e7de702ad4ff76c0852d82813a2c0098fb9c4fcff9d88ec9b24e9a3a282f2c1abf5c9d894005b04fb9e9d72d818eb80c64b80d1cf49d39322a57b104eb499a49c0a5acc2ee29a93eb8ee934a8f3bcfac1711fad08cac008a776203ec521608ae9d827e082a371786ac290ffbd5c3267f0e20c07998c731ae6b233ae1f258bb4c8ae42da7f5e0cf8a9626ad3e86e561a67f187d53eef036f1e001daf56835c64c27e26d63936f71065393794e0017f0719bacbf76e458e9be9ad5da4bf865469417a7942d233f4b72b36331ef62130143e65a51885a7bee8a61b4930a4021dcd49f7ce99598a2f57c442e9a7e0f015985e817479f94c499ec897d205c90fec4631d398b72208b001957cf6c7e759c5ef91279ff85fe5be4422cac318ea7cf5c22b7d650e888fe5f15a0cf18e089bcc60817d0eb8601e83d688053b86b41fcc4f2b28c2cc76e2c62d4dd35412bb983483c37b1ef08d75473a251b29c531a3d6657e1d513dc0cbb4d8806754c81ac924e4db85db1e81ab77c0c488e00c2015449ee42f1710722360482e14e06eed6b987eef988d23be5a924b68a98c27460fba0988c06638c34588229444544f11dbb8f68db0a1562172709ee07906fdee47fe9d44930b430cfc2e625f12a400d641a3d5dde21f1b986c915f7f09403acc33c5080ad801df2396c5f5b0e3ebc94e9a7dbd13899cd4a98781155220487892349ac1d768936c83307eee4fba1d6770df62b25c3b243f62a100677a2af34cf4d4768f0c407b2725c7c048e214a581270581b6a4ff6629b8c73f0585e1f2437c8fcc0668b93ed8f1289a6b1065e62f2b78692bf9dc37953314651587866ab8c7ab2c44d19582b4873e61973146c1350b2323647ef47713608695a6c9995f2337a35aded9f8feb42ff03b04726a6f312f7a187511b57e6b50ba2da20f0c020f4604d42348c6860a3117c06c0da1137cacd76dec2625043ef334e4c08a2d63a0208273a9c01380267a3b743c33c48a1f900be6adb25368b581888ef1edb939bea4dff75e7695288ed789ee844f93c4bab7f8952bea88d619a78e63cae836943e1e7c61c12df3f331765bed2e879d8d070661d9029e95ce2811276121965dd21be8a08e2ad9ec40263640380c1208b12b8808025457ec6de3f69bcf677429aadde16c62b84c09b82840f316f00ddfe9cec8d88b6cd6202af60dd6c5b2081c52487e577d8b41020930371a7d49dbbcfc5b1c73e4db660dacb904242dd4622f06e7c6ec11cf42e27f728b951df3f05eab3b8578fdc52073e87e02a6057bffc40407dfdc7ea2653b56ccf26d446dd124e454261a09a0996c5d0e0829088af592cb9cb1bb1cc3a7e25cd1dfaaa52b5b695c05a9d01859348c9d53d8589a12ac3b64577c504d01f11a37087b924ada58b0ad019dfd8da5dc5829300602fdadbe8f776ab34ddf6604ad99529b330cc8b33a144223727ad7840b106d0d6f5ab38a0a41b0bcbb407ef7ba2b74de97ae2bc111156fa575981fd8c564605ba0a93c2aa53f7f288c2dc5f2df81b193fba2ac7782ee91bf4dae9728f467c259564f2d491ea0864e5b2e4065f13c19827ae4cbf200eac4c8ead10195e415fc0aef95348f4c5604dc70a9ca963c417f2827102bb9d703ca80e6fa4d5dfa494f3c9d08085350cea656e333019a38d97b40f80b22cad9efc0149948615dd11a2d9a22176b57e50171f894416bdaef7fce142c11b7c630aaf78f5c0baea06b816bec2ad2ae253be1439cee9a15666ee43d88ae62d7a22be89ae81abb922bf50270e6f0bfcc968cd2a69fcdb541b055ca5727bb3b2b6683138db28150edc056b470122e8f8bab8ed6945715d35db54e3187b6e4cb341e4f233ef3349ee951f934cac42bb5f54f11a0b36146237454d7bd7c9111e22bca256f627ad5f100cb266944a0095abe9751ad303db4d676a21bf1ae8c03c3516137f29445acf34dc6aea405e43f78e00f6561488f5db844cda305b08a5832ec74445541c11d9378f871185db83ebea313d004f183478c41d08dc0e7c95be702f372e27c16be2c57c2ecce98bea2ad3297a5caec7be0192180c5ee90735387f60c9f32fdc90c48ad68bdf59295179ab941225e7a8a06708c92ab246e8367397064d749a30045bc313bcba6e008b23852cd5f50dc1b35a05615b6242942450b3ab149e81121128c7f8d0d5ee921b1f696d5935555b71ce1760e5fce97dca40534e62e00102b24f0f116fc6b65c1cd949e01f0d5d2c3016915042003319b971dae7dfa082477cd9671f99c9ee5753cccda043f14461d7e253e9faae12268408c7b03b15efe0b7b767ec452cee89e8f6ad1b6003b1b0cdfde0e7ec8566f56552812889e430ef3d511338000322eeef4047588b26b5b664d82e966dcb3a32c0951f0e6a4ab6881bba5196a9642e4e9bb19ad35f8120d2b58b04623593f52ba2b75c1bc57c91f1c00a3527d705ea6061849a4aaa2ea838d1bae82ad0d9497d40a6f37ea65e03e03154b13b706da7d4aca91b6fefce50f35a818f44c8095333780ff26e6c5fab7022c43acba4df20aa353ca82d34956d7f04fe2464fa9a8b90f6211dc3926d1ebbb4514c4ac3355312813e2e2d06487c33d4b90f03db7d1694fc2a5f3d963edd01bb179bd715ca40ebe54cf2c33a246c6f2a9ebd85b14ea20fe16861c2c14ad40266e06b90f938acb83bf919a40836bd216d32975da167e1c94d45d28a7e561b8495a2a3a993c742440944dd8edbf3a0e5af93a051bf315fe13a7f09b21efa34ba30f96143b21ae3348b908e4d667c4931556a4c109dbba3ffced658f4e79d4ae67953777d4b9c66717000b8eb31382a72a9bdef6f1d6dcfee4e5ed07d066123e5f5b8f123103a63e816bb4981f80c684f68d825b3e00370e7738d9f03558f2b86ca20d1f93b4a023e807340b9d19f2ea73d6b1c54e4589ee149d247544bce747394175dfdfd829bc35de13e7d46e6ce447f78eef1864f17fb2bb803941396d6c82594495c9644ae900f2edc956709a05689d707e638cf5a17d354d160e17a7107b08122711d918612f0024ce3b20820c05f45571a84e1a20cce4e9379622140d88662ff4d5d3a53022728e9959a6c770de403101bd442c59c2d93baa055bd05e7c2ff0873a04cafb2f7901d5c63a0f5638687a0826946220b70736083032885591c7edf103774378f1872b81a71178eb979e91e4a196f0b283e813c7fc40993bf795489b2f8a8fbffd20690762c6d784ff16270eaf2bb3f308a200bd53ce5299ab0b52ed2ad4f8aadf2bf2c77dfd5d027b0769a86b7884eb301ecfccc573705262e89aa39f8514eb9463b68f66e03da3a0db948a9e66bb32ef66da4b3954e22dc110e6ded43245f2bcdce01e0d374ab9a6a6062224a36988a6f16595e856cac428d35699e8ea7f934ca913b53c57fad4bd9cf8f289c6c12a1afcc6181411e1ab1fe7c32265f6a524edfcadaeec45ade63df2cf30532520d7af140b180c8d6928ff82b4d8b640a341916c53aafe986c53277aa9a04b0849c3bc6dc3601f5805e884c0f085a0e9b08a02e015817b2a633fff6350617de93af83394a2f7ed5a42c252438e0a845ba69e01f4fcb8a9ee8a7abf1feb23ac69b52f69602eb0eaf6811c14995a830817cd20def4986e8cdf95c9539561af1034e48761dab2afbc33d9557da5eaff164020a82529fbda17616b33b2becd7bea187f596a365281d05e2e625f97b6e37f53584cd9311940de6f99cccdcd94f2cde2bfb023c2d9d9f958bf9853566d64124b63a23a6e0f61747a73693c2ef8deca29696b1c9b18b7fd377178f93a3fd8a6a89867963d1f7ac53bcd71958129a047aaa4a0af20f17930459b6a3d5884ebc35768ff0ef514cbf52fb432452deb87c5e8ef6f56e4dadaa51d6c3aceaef30e19b71ca78c96b4e1fd23258aa8f9883c81e7fff9967e62d988e3626a8295eac126d19e122284249d533f35ca9961bcc38d9f857d493802e57ce45a0baf3364c980cc438398db47ca1c5d131bb471d06bcfec8e1fa065c2fee2f9e48f4547d5db83874f8df00a0889fc31cf5b6b4690b778589064d2a5abc4b83e531b72bdf9618f0a4d7ec4329f1982a47f9da9742a764e4db1cbcf21bd0cc5d367724ecba91dacee70c114f4118343528e021e337f63f3f3c1d8da6bc0bc46617d2bd1221beca7789384a5d2d28acefb87beeee32367377dbd932385e2774b79a376b2585cd2bc770f7474ab511cf7b8133b986e802ae5487ed59548473d6e112b69e37cde37ec9ddae070bf5d92c8a72c0fac7ed26f07db1f597f0d6c3e1cd939a2469f8bbd17cc4acfb9a37c9a08c003ef841fb5f1feaf38d036d1d660e8c81ce76c0b1e363c37807f3974d8c4b8b861e6e929885409d3cb013e2adc7f7c43fcff201e27255031934893e8687e4fc0b3c12615d4d0dd3470562328a71bd277cad54de438a2f36f2ae8c5e2855e8405df4f5cb438bfb5da99d3845b45db036fbc4b676e7634b90e78ded75c57b68093eb70b0dc019ec9a776e59534f368ffc8d91b0b1062cb19f65e8f961ccb2a1f992a218f2a51247c6390c13e034c163d9e53d429045c475d74edaeb09e056130b4affc7622db2fe601692970a4c811b8645ae27ae4b11f19f891d21fe4eea113d939f99d1612a05e6c7f946c7478b78e52116a6079f67932a57a6189f30b789f731ddf7c7c62bd94632bde2df6c4cebf11b52c12b856131fdfe58377ebca1fc9235e1b5b7df2f110cb2519ad98b5bf12e8a5cc5acfb7072f528f6d4fc6744ba84596dd4042fe34182717274857307016f2ef1216e159358d2189f8085ee47f17db3d67ba5fd7d83118b2bf1e5c13ca4f00f6981575cac43dcd3400ff5ac58b8246e60ead28c9fc04543220df1d66a7a7cb908d88343f63c5c62bfad1f8188db64a3ca32404d43a28e3a7d4503992e5e7b95df159281494f622cf1c7d19457cdbf95b81ae49ddefd15da5e0e4d66caac3fbbcac3964f3accd38ff7acbeb19607839b293df5771caf3cbea6b1874d32a63ae642294d3b131ab97b657801e2e7599f14387d0b9b3e35bf8fc70977c7e086fbdd973fa17f69e7b06b718eb42b1251729632413f6cb864e3824d05260f8d582835d67e3b10304b96b9acb3f9fe4ec3f7a1e4183022894e77c5a47a7eb7d0a1378578d3a09f76e95c918882183c629241adede01839f571e2543ab6579cd48b3bf08cdf824199260d164d58f8b9e384990fa556138542ca5a9ff2dedbd2a214ef226bce141388123179e75eaf35255a5a45e05b8f0862b469bf08a7074fde261a6b23c59461a956b2a5d4b33375330c35c7bae16dd18d649b7b38fa3d3c0a3d29d82fca5066a67b52203187f8fc893551d6a638fceac8a1032749e2308bcbb234154eacfc66bcd556ce0787f28e84b4b74e5d511e600f82ad86700c67650e51044506e40291f2a3447f818cc15e6883ede1e9cd073f0cdb895e2c0403c57b9b10801534e83b589465b90baee44e16da9e4f0405f6387f9ebfdde4d27105ba0f03bb0212617f360b7944f4d62b7cce79105a88296ad4a74b58a5f9953033271e38a4a9cb72e63f194d21ac2e4a284dc16b4d927c84ef68e50d942c30be4d9158b621e594a6e0b47def803058ddfc9632ec9ec5550642406ff8e7edf2534a165126bbc90907414f8455920cbe50a8eb19b3c4cf596134e2fe2d2c39b2586070422733b5e206006358f89ac7a616600c6af1626bd45260ff71721843367a9051c2ffe7ed47064bd849db6d059e4411a81726173942ba88c75b69ddca9b38c4949e0edd8c6739b1362f465fc16edcca2ccb02bc67070209b4f3e03be1f0f916ecdf0057548b070676bb9d180f93247e47c9eb540d1665f2bbbd1c662e4587b3696f61c0cb1202ecd986fd6b52b711d15e8fe1e0fce50b7b398196b120bb706eb21ed0de41f898b056e0805528e9d1bd0836e1378b79e28989a34f60e15dbcba0dd7217e172709b1f06ffe76d78fafdda12e1dca2d3b511a2749d7b17e53bb7491097ec75bddf454634377e80bd356f29114dc82d4f4926759cefb0e89d32415a566d86700088b44fc610aeb9bf398a81a7159813cefa856b07b57b0e27e16e601be13f0e7c80dfa02cb495b2f0a91f2e8ff3e3ae7d0a8883d07b9f6fa939a85ee28c388ca6375dc6472031ada6430c0aca050ccd3f88cdcc612b6b7bd2343ceb2254f9c2ae711c9e22bf515d18ccf048238872b67f2d297adf789c5cc2ede4b7bc6262ada16bed652ea0b4ad18e5cc2eb4435195610b8a03fe6359d4a8953dcf5bbc05a7d781a7444a75754bce2402d1f3ca32a4acf3dbd97712806b3b108a4fdbce590ef0e892c18a4180b7e1a0f3d948a83bfc18b50632e01d6a662e1f43ce364d6540322f19a3334ac26b26691d9ae07dd3a90c4af7162314e3527cd5288dd193bf4c4c019556914f4518e980c8d111a77461d0472aa080ddf7ecb30f8c6c9cbbda54be3507a81614f3226e137a470d601f00d338c01ea1b45674163efe3c04467b5fd08e383aae74de0f41d0702c06b74a8076593fdcd409f8016625089e0eeba47bd8af5f7d94cce27998f59dbd595f8c79b0607b961d563c5664c80e444c9176c962b71fc90e85b0c9fd3d98b1c321e8649d6ba62c9a1e3b4e29c6402e520f2a60655abf316074bcb8e9d4326f50431b58012098d439642248c18842329a63150940ec29f1605ecea8a7145ceb33f1fe9e5c9b568ad71d4b45b54acdb4ce4a57fe29dc52603302254967a3f5805eb842864f404978c74680fd63c1d28c7820ac3f7a9cb82cc04fd1ed16f411470ceacb05cc58171461a11e592820513361b4bbb99db1510800611bcdad59cf94875babffab615a34a591509f72c0cc92c01775a6975486e2543b3ad9c71887f748a490241102dbc6a94543415fb774a5cce8a95a8a55f203ced63023bd8fb8272a3712950cc16a472f7270692dee2096de6863671957f82afd504c09172fca3ecff087432406e8cf05304fb22e18a14a02c1eabe09ea8a29dd41f99a681f664f6aa2f688b84f00ceb6b624afc4de011220aafa8175a347484e0eb5c32a97d2b120295a4591202d41d24d5a842f8e7e122cea4bfa27c47cad54859529d05188b9ed6fea6b6f5d184b66a50b5499910ac2d82f5fd33e7beb92b1b42355c2da085424c47ef935fd5b4b37cd851969055697a71af3a82d78b98229c18e9ff34b28e70dca98d0a2e1baf08fbae977705959382caf4ca9919e821a04f1d33f7dfb9bbd8769796b5a09d424d430883dfd6bcbbbed1d0c4b47d34a444db102a1c7676de4830969197f1935dd955e6165045a1063b7f9bafeac559fc6c22ca90a2b53a0a310b9dbdfd4675bfa3496cc4a17503523158498dbfea67df6d68571bb47ea6b8b6a3d1f4a826beb3ed8c75021dfa71fa1e677a40b509b818ee2d82f5fd33e7beb92b1b42355c2da085424c47ef935fd5b4b37cd85196905d64644453172abbfabfa3551f97fa0ba9df3717d7625ad06da106b1089befeb4d5dfd60e268bab2955a0a7508151fcd4a75bfeb6f6605a1e49552335841a88e2a77dfa76636ab2cf185e6afe4df547d8559a5e9bb907fda1625d06d42a1665652b2812a2244c4100ee95c7d6be527548285b4123212d402a8450a77cacf6955687d294a176f03f607eb5702efe06ddfa1db0ad0c0ecb47d36a444fa186b1f8ab4fdbbc6defd0b0bc9252467a081514c45ffdb4ed2f6b17a7791faaa80992eb370f8c946d2de677815c00980bf6cff5f3d19422d243ace1287eead32d7f5b7b302d8fa4aa911a420d44f1d33e7d7bcbbac76171544a8d542112918b05f2326877124009681080bdea73ddaf950e4a0aab5114a04b408121ec548f537eadf4a0541a894a21c55150ea7dce3f285e7c289b543a82bc91a02a2b721e04942115c2b053be5cf9baaa435969053a01b4085310863ded67dad76b3d8854a6c6876793d945c979801796e67181bd31c958da912a616d042a1262bffc9afeada59be6c28cb4026b23a2a2186c2e32933b800cae5d98e7f944f56f3bdfc80c1fead52cb52a23d380a3d5b85db854461aca6bd248540f501523bc9ae30e7ed19cec6580d23158285b45a32125613a8450a77cacf695568752d148a436f102f54b5024946f2e55760abb350f5cd4f78f6f519355d014a409480700ea6b8fa93ea5f54152d88a22605a022a8024debbce07005269cf394858426a0c61b7fab8fa6b5597a5d28e6802ea02a66288b46fdeac0a0b9d4b7aebc4fd7b5d510f27acc4087ef6cf36dfd63b6928af4991d12bfe62e4e18474bb3e424c774917581b1115c5c85bfeae3eebd687b1b046ba822667e148ff47e492e0b58f250b01ea05fd486db68356416a861414c25efd32edaf4a176765349f594901de726285b09dde7af5969572e12e7a152b115403d4e5db9210ca2c9db7e52f6d8c1bb890ee07806af666f3b1af3d7cf5b4da0f9295df2f170cdb69a98371573f454d9641d39012611d00e8ab7cbe7a624cfb1faf79e93c29c1cedf3393ffd9a535b92ede851ed8189f035b85c55119cd67362fe097948d1475b7578edac2a1e511aad209347fe65c37bb0706a95f1537435b3f9e2cf34968f3dc07fcd16abd2e0453ed8dae46d0fdb22165f3de5adf6455d9f4729c07ddf382885582db641de6824bf4815fdcb6474db7373514bb04ac02569dfe2cb1b6afb5a91f29617c5844a48ddd04e346e7483f24006b8899c8cc4eb985f5d08d58cfe53c0e08e19b6273698f4b8ea0c994012a5d0e482bb62e5a1c5a9b0d8438c59f4c41ddf7126e889c7be6f8922f5f913e54ef9dca1fdc83778087d0005f543a26d026d474c7db0e6672a7c2ccace018c8f7472dbf7558c5962c5c4c5d2195003351e6616950108e0d95c6b349941db7e2036510aef718183ae30bcacde0adb783587c1107b842bf4def4dd806776e26843ae3c821459c78d042d51b66d2de036a7a3d9a92080d935b4d5a025bb52c8ba5452f5b1205645ea5f2a1719b90441f973e1dbf63179e5df50694c78ee932e9d26e2b01ed5d2356c4a2364a5c9fa7ad53d531674931dc6b0a4dfc67fa53e15224f3a693d8e68448d542cb29d89a3082075d786f29f4737bc6c0daf6cfd1e0b85fc6878bdc99dacfb56ffede8df354b0e25939b0a5e72a12a007261d62278f5049d720ba6b800f90aaa92d3cb26bb4d52a2a895b687995ea8eda06b0122c00aced692f4bd12f16498b5eaed334756f0d97731690dce80de89bc0bba1e8d9855d9f39fca6ea5ac85b1596a1731937b548c025979b5de92958b4176c9238cbe39998ba6303c9b76af7c39246f42e5863a1e190c629d4717228ff931fc480a516b1a177a92b2fbb967e33d9b25cde7f3871130202889a6d8a32b110a36a4f72c0a249e33e1c906b518024b19564947968522ded686771d8f981dc40bbccc8b2a94dc0ec8f0eae1c7a5bee5f94fdc8433a7ce4f59a2e21b184d1794682626201a8349cc76e074905d8bea094a4cb3b610a4ad0dfa3987a4e7a65690f7f170915997f60581a9fbf821db52b760f88b7a3be7bfe6f15de365ed5d3b3912c9e768ef633d80dd1c83e2e213cb1b71ec9ebfe3cb6194e020991369079502520b9282d950e2dca63a7c30e9a6b3662ec9ec18769e4661010af47a30e564697e8ba6253f67cc83694d1bceea31527b349e304fa58ec26a68ee169c9a1c647550afdc9afa8c05e5e91dd343dcac74e81b1f707ec2501b781cb4ffc3db6d5fac009868fe47acc438f3a55d635b3acc4e345e9c80b16f71025f4dcd1cbb727b96e75b2401b73fb8407015f427fe6c45740493cb6e1e87a83064c543a0dfb62ec2ce28e9c2d6bf13b437399a130048e31da791119a93e6643d33b91329a5a79aa351699accd9143f0353d38560f1e62398c274869c9eb100f4394a622c63d67addf3cd174d741f6742f8b860fd308a18da29d81000c2d71c1de9f0ae88db8e7ec31638a47b80a8281fb410cda77466a90cb3a11453c89211e09aa3154037190f926fc061ed0519e5bcc0ae22d009f458fffabebf1e08ed64467ccfc1206373f5386a83d4105e37d316cda3b491d5522fac18c78b453debdf87afbf1010c9c4d8a34a49d6e8853440d64450d6b5df534c3895c054797b7ad76eb6fdf61c80d093d4fde7a709961747d9b0cefcc71122112bd6f06f3bd1191db62f1d783eeb2615becda17ace71c8e93dc672ae41d401d1ffb0d2c963d2f50b680de883db2750f47def3b74d5dcf4feeb685bf8c302b6f1b7f77db7875dbaea48e06e012648adb8961b3226d27508a395c9e1bf5f87a95336e85c90ddbca7102073ed62e1f110dc6bb02c48dd4764efe94dddd8adc2a3b540030ff94cfa73c5c7333af1cc6cdbabdea61f7f180abc32beeb38a0330e7d2bed8887c6bf05f8fb5513314a815008fac23f14abb42d68f217eb06e3b63d56f123f445a43acc0f73f95298a6d344b0b0674effdd4eff902ab15c71ed4db4f8f5de79c77bd75c105d17dab516ea68d9f9dda3d79d94707bc14697ed5e92782b921350d5b3bfc603fcdba3c344625cdd1d4e84b29d30dce3167f1957be3b7fa774b67ef183dd57a88549d9e32a56d374ca1e9c7be6e9047bc0d581af85ebc8a3c06b8641fb750559cab815b0a2ecc76945fa47a87a5907a014213d09cf563f7ffa00162330a69d6fea86ff3f7b6beff04cbc50b246215184b58bb77dd67c8ebbb6e0ba8207e3329fd109d51aeea87a30930fb69dbb341e47bb06cc912acbcfc49d1742a2eb0d4365cc9269afd4ed6e3130d49f1a076a20e9e22b563656492997c2424a8a5012eee067c2d7ccd3a81bfba8c1e8e9f41c0ed456fb4e58cc05474f950d6527f7e832e2578e70f4b289e59be276731f690782f74d7571b49d7f18a5591da3b5604cf26ff5cdedec78f2b6dd20b1e954645927f8a8336a22e8ab744885ab4add013da939d3e17a1c6c2d6112d332eca09d58e381ee121a137332e4aebf0c09bd780f10e27a3f4a109bd7666524aeb11fe56daa71bd071ac3bad003e22a6152e82aef5a887869152d254d73dd41c525da477ea8e274e99f16cee57683b9cf6700ac4aef1a7f031ee07b47b8554730705dfddeef16e6de5fe24664db93f95b6ed2b3a2cb056ee1fe230b03d840d9bc3c9e8d65095eea05ecd29cd613be566b3500ebaca751dc716e72fa0d98f54786fd2773a3db50e36a62ed78beb41958fdd51dab3c38c9602fa585130bd64272a0175574d092f5877025fb4ec184e58adad193a87d3de6b26e6f59d1cfc042cb0ad33f2334be8e74add8a345da6c09d7dc4aef2b05d4992a9254d0027b901e7b454e2068bd03c552c9e571ed84bacf1bb98206a181cf89e9be3fef1e8adc876484684c6ca9c760abeb0a18bb9b973d22493b7a69e9089c8b9c2375f793c3757a55a81aff30c9f73d0dc42460d289631d7725eee8ae69e4d48ae9a5b0ea30c4ba2bf227d706175268e2fb1b19130fc736ce8c541f45acecc9abc300c1a10730b835f5a3029b398acec6edc737b9b63c18a4ea5076ea3be96ec4643e40203b305042d1f98b6410dae842785d3617d98b1eee96d91547bb2877b649c58aaac6ff3fa60e3ec47a9cc9bd50cb53fbfdb8fdbd6fd99b679c2f29ef9f84a7db2bdbdb8fd47d97f69138db1dc14fdf3885de807d13950fa7ec54a94fa6ea5a8914f8bbfcbff07bc1b18c9093af1c7448e21b3914eaa63a2b0f2dc005ac15eaeb8edbcefb1654c14e46162947ca6429b40adf3b57fe77d407ec660f14300a358868caf52f97463c9fd48963d1e45fbd2147cf145c4224677062ea450accb2c3265232e479aa21c481d24e21ba944096d75dd909bef8ff9d3118d39e3ea20a7f2469911965893decc24f5764cf28f7f5d9df1a25782584c32565ddfbfc6c9c4819c0623b10a71a399f82fef097888fd6932708d08f49081356b420f3510a27c72522330503dd2c4d258ebacc70dac88e689e20e5fa36e72faa8aa4db4094ea88dfc481d24206c32a020ea9a878d405361883ad287f8ede212bc60d8425bcd961710ab0af01f53007d953d27666721d85ff9f0d83df2d8e152a72abaa2dcc82551fb334f9207c9a6284f3f5206fd9042a1a6cba9b7cdc68278cfec8acb4e18272b63e2e9efb8cd5c29f7a36eea5b618d7ebb9503cb854434b5381d3ae7acf4998284a3d4914f0173016849666c8916610b0a74c9bd937bad76604f04d15e049bc9a8e4dac54b77a857fc474e33f3c4afe027ede2f68e8a23b3fd9585239d0828675b0448c84620e0d62270c009455818af31e1605444c4aeab2aafe069982b412ae14c7b486f66b76331fae69e8f7392b4579620a1d9affa0c5467a9212fe2b852340e7980becd2a00de709728ca8b3345de2a0c1f919d6b77707eb6352628ddb626168f275bb82d378c16b154e68036d2a23c3460239643c814487b15c95b75447546bb1dd9155c7c46f8ad90018ba826ad98217f8764dcab4f7f74af48f94922aba743a21d2dbb1430d29f7bea1aa0e1b805e4a70329668d744ad3de70c19e44bea61e5e194ea7f442eb7a3db8bc6e75ec3f66ac71dd0a93aa364289de1fc4be0dd77d9bd6950cc5fef7e5090126f368e162220d1d22466a5e696b7936901edb4b380dbcd8cecaa68ec42c3a7e8538bb06c512b1f6b0411e63e4bd00916c6ea46c52f309b6f7145e36cf0709f64f2cff840dc921b65920f3c840094f0f03928b858f3e74cedc7c11a442f9cb7f2be761451be409e9ffbcad50a7305055d82be53c6187806edd83a624cd3e8ba8b82e92dc9cfca52097f461b882734110fb8acc368118768cbee84228806b0af42b68caeea38f1f0d193ae0051d11a6327f9db131ee899b0b6f3bf40d0133130941dec0cc575da708e334b7410e507d100a54444acdaf7cd6478fd0339d03c1967443438e13b3882a5f58e5219ad47e7261c36e57c965a4bf300f0066c67a3020668f3c1343384f02e94daf87945aec81cc3690f88e031412b4a295f7b4fbb374c45e001ae40f784641a798b55c7492f07652d5a8dbd199f798cbc47282eb936772bb1a8bd4ef1df1f45e63e197333f7f12cee4d5fc079b2b3efe95595d85537893b78fab9b31f9997e212090a0bd373254d8cf7256b18036f8c51c772380c325fa4e10d492a6e82a43daf8306afe78da7bfc0b7c07ac86913dd1b289a8cef772500275e243df9fd67b4425c64efcc7b77a6e40d7df05f054ea8808081411cf5f8fa10f93914bac002df9398c2772a8472fd7d890ec4c7f8f6622596e00fd53c19f04f1175f3f75c3ccf45bf7fe6c1feff78230962273a529e1b7649fcf1fdc53575ff4f97a85fc2321b60d2ddafd4d262cf29678eef141abdb516d215b7dd6cf35127ac536f902890aed620e5107d454bcc5d291fd3e5bced9bd01f4b2ebb87030e12bb0aa5830da4dfcc1d25e600640fe4b1bdc815ff5ad579566bea1f3ef18f23e2c7779b8789f13d872b3b0ab771fa53e0f41e4adf80ec99f0954d1a809015096e76aecc1a3d01f771b3f36144864a50bee6022b6c8d0b67401531924ff488248dbe708a9db730d40dd2beec1b9d5cbe5d65b764e08bd07ea61360144ab1778b56e8992091c37a22e768bbd809a5d7e76f42ee8e97034c6a19830ad4161f011a47c3d2ce2cba2a0c15d8509b2a0710684636706736ec908a338f107f3c1ed8f12ddf2595cb9d85395f41efc60a54e0efca333852d47f59fef7bb461a785f82faf4842d9e4d9119b9a394d5d92b886b79e1abc66435274e5fffc45224d2d1143f8856bd7e3f2f70708ed9e5a728fab7a50b3d2a89a80f95351441abad3bf8555a317340ca97d376cac51ab56f123a65d018347a479eae83d98bb71e743b94aaa1170152fecdfbd6341a8b404a497021ae99e53553bbfdf5342a1bb95993daaf38deb3c3c11ded2127cd12307b6c72928d9f556751b98027d160fe59b911f797b530589b3dc0a93a2ed50cedf7b73550ca65819e4ea69595402053eaccb4d91fafd49894b3cf82fd805b2bd38f0b613f5c4f38acfaab9bedfc12583425c85a1311598badf8385a708a1cb983b75e1248448d91072047c0c517579d82111e16ab1a576825ea82233670ae99c24132bc2b7f7054b0e4b5450d8cbae7faa69e418e31c13fa1ce14f29f627c2002a76dbf1150bf3da1a9d2d9091cec4450bfaa0762541a77a010dd116744f030e15a234e8110d4db23c80f47f27776f0e37ac1ea056914c3f8685b2ebbf3cf59365f47663d5ed24616cc57604e009ff724f3ddc772b3d527a577f9a51a2b3ad8d88baa6d4a2826694009b0f34457122f8ba9f603c9137c9a9c42fdcf2ec3f54a80a52d438fb6c87524859f8ddbbb81717bf5c72c21ff743978d843fa7b1219fd446469ce4bfd3884e39b925dd4ec8d83ea773b9659733495553592060060b17c05c68a75dcc4a7e584647b79294ad30b87dfe56fe77286b71cc68fc9d6dbc46231c3b7c37807363456dc3660445b50de697e8f97ed2bc13524f03037c6e39f9601e6be75d52ae4161b20278eb2d491104a0159360e3581acc9cb9340e554ce4b75d90033ce72717535f688c75add24f947b521272f4eef19de4404dbb90faeadcf097c426e783016028dbda537f6a20398390e00b9a207ae23704fc3c420a4b1a09c8a9220c72e864766673fa3cb9972a5859f19d805c2d63b027055a6771b37e7f4e4c1058bc5558c30fd012d5f1206c12182fd1bb6a733ebac5f789f4a69f352c2aa15f683af65237195facf67ee6e8bb0364455fadfffeb1ed4f9a2852fa50242eefa35302a7b681a181c5972b3aa1418c0d739a275dbb6da95049569a4b9a13577965c788a226b54bf21b704f3e22c77bc71d8da9b5101e04ea955d77eecb9d12779877af9511e9ee93def6b48d0a3f2e6aab5bffb40a94f84e0980e9bbaddd4653b1b1ced6205a1e01118fd27c1caac8f2a808f6c6d6030e4131cb27f4d95db37153e3848b6132feb919fe711304d1aafd661470acb61ee4dae9beb74a0fb9f89167166dd47065647bcc4f3ad6989bdbbae46d6644682d5cf7209163c6051fc089f349656f535f30e69fe5edb8d15b7634b41c325e407a5fe99f2073ec0f8e15a9d17fd47a8e704c241fbafafeeb045fac40eff909efae779886e71976a66cab3a1729f86212afd3ce7ae62806eb257af9199d3b22fb86603112cd10040c0240c7ef7b6013fa11c3007cbdf0ffa7ef4f9e4a4b4a0e7d2155306ea8e64025b7ab2e7bf4b3ce66246157441e82f0777ef649494c26eaa21fe4bae19a25be9d93cc1232eb471078450d89f7bba342a409af112fcf1b06df8fe45be350175cfc00c18ca6dcfcaf0f114d3421770dc4276b144dae442effd77e7970e3f310ae1cfda4ae17c92cb53a55036fe6e3ac79bd3615f43e1269f85627f3b37203ccddf97c68ea301e77188f1475718cb8c44dbc821ba53cec691f4a782e0925b7fd31ae3f5377ee873b6a97f3e68f16d6591618bb0d7899cafba2e5f92321ecfe8924d579d37c139628ef38c0e2b3b973ab935c67e28b0ccbd83231aa1441ebb33d4af4f2bd72b60cd4b785742a7cd1c05bcf9ca7d6d03de1eb00b6849d35e1594864a4c3819cb72f94b48855e52d7ad145f44c72745397cd200d171ec06a8fed26991badd3da363df402b17cf44f419e8b0f5b8c352c9dd4a865451a5100b0328e0ac5eabaeb77079aeae1e654f37ccc1565729da2c532e64ad6989312d4aed31f8701eca911ee4667f91bc8302649eedb07089d8926d89f7fd742ae3502a0cfa071bf7d5cb5844bd01f6223d41e5b01b2a817eb32d3a59288d960b7dadc6594070e806e9e15641217772229db4bf73991e8c44a0017da303264f49b0bb04236503686b4f7a4597856243c930b5587de80bf9348b6bb917759694da61448ae58473c76015cbe144a75397e47e97c6a7f658e7fcff2422585dfce2b99e4aaa0eb680c6e08354170e27233bf80f86adeb9a7ea79390e12764b16499c2689cabfb00f30911581c893b4a34e31ed05c1d31311fd7c316be76e34cbdfcae1707446f603f1685fadafe3fd93ed88aa2f7fd71d42aa94b32a64a50873d222870cfff86da7c5bc5ba89061b69fc2ee413e4f698f303d0600cfbcbdfe596e098e8bc8c5e370e65041436206c49cd13ebd38914dd95945ffdb1bddbf120b64f857d5736d43f5f1e10f1964618da4f79874668d4f58881f129791d8bb0808396f6905137df5648dc5702d86e890625b633352f632f543fa6595548f0b42d44d97795b328f2d332630dd7d35414826ebcdc42992ed233bdd5775deeef948ebf255bcddef4314bfb2918640753d120e414efbbaad8f5e676a84eb7f177b624e627c14a13dc736c219022c2b581a9e1f0ad0c0753d11f737d1d9ceef90c6bd963ab4aba407a4c48586ef38c089b4331b33cd1d1a62a2a51d5926e3046634834cf5cbcc5551ff8390effa38cbb7f1adde344a9e358c964290e4a07dc238eed504e960dadea3ce55862d4fe64e405091b6f0a7a6fd1d27d081f5baffd6982c77c612fa05b2631c78a44b7223608392aa6de8e3d33d9f1701a951689a22d542ef1ccd540e0c022e9d6d1ab01a72c6a1a1ed5f06bb05d4b76f2b681ce05412ee104b9c39db2b1b831fa148bf9acd966109adac5d6c448019ee7c6b4d651a36de8136b389811cd179538efad2846b035a2cddc84e0444f9e267ae904aa5cf2b30125aee6745e7f969ea77d887162e5cb19fa4f20f9dabe1c3393c1a2c67524960f9e7961d1f346102ee3719337feed1b29f00a5c68f0ccabf320a476ca5cc0296ca31fb5dd1d86230d5a82157eacf7e234e8cbd4d674aa6483ca07ed8dea5b70c2c66bf2aed9e18a39a78c1b8f0cf1137dc994194fc361f7fd494a4908cc59792c0866993c56fe8a2ecb00efaea4a637ebe4a690bc351ee74bc33ed34fa1204c837e0b8bf3b14a33d1e35a3be077c276615ed24c5848640204f76e56634d5063ca704a90a45900d8649e00690a349cb819bc21ecd8a0a123efea47458965f3391921004b09aab5e21d600b75e08db15aaa9e5873c40920aea3b0004daa0b1bd5ebdfdaf59efd65db01504e84b97c622b5a7bd414ffacd0bc54ba14f2120d56808d7ddfa8337b64da75ef44044feac99d6d647bcdd29377fc5a82dc95a15de65610862609c661a7b1cac331ca6e5fce9e4a47dd5cadab961fc5d4061141e0836dec1d9f9e221aa797f64e751c2f443a2ad41efd12a2bf08ae8d39e21c0e1ad155e8225b0bd2fd05edae544c05bc2251852cb65d6b4116133a7990f8983c193200c330e52d151f4cb64e280f2e59986e8e29e2aca9960d0a4a175b50a34f85b22f888d7e67b237ea3145c08c6b0fa6e436bd0b39bb4a05964deb512ba39ec81d5706272e81ea7e614f20ba2576702a952f026325f325c5c19b5b658e5526426ee258c5c42ad8771ff2b3b53330d4abfb77001f3cde68cf9e9d0d1ab91241756bf305b8914e4feb75cbc0c77811d3f1ced2a425301eefaa9821451d7b3a8dfee5fafc2006efb9a8afa00302869c92d8ba03c1072424f0e3f7ece8e2555749eb510ba8907bc57f6ac103f06ead1c8d293044bcbc616ddf1118c1dfcce3a646e1f3a8b1a328304c0db970e57c379811cc1d3120c6d5af82bb2e7585967b81c11330e3098a16aabca271adb4031280f36bb381670045cf4176230561ca85ea3389f6945f131e17619d1b23d3173462cbed3605776b321129d2ff0b159a938a9bf379a90aef04a60509041b9a68107e422079d824d56ebe6092bcd0ccb10e60c6abe8dde00d01da8bd1565bcd348f896f37514469457db80e284d249b7c08d0a2e1dbe8181dfbd67a11941f4c05dd5ede5d9b67a5033792bc1000eaad9432595722497c32ea07477779a4896aa242033daf3791bffaae28e2112e45a49b87904e774b7d444f112958bc02baa4fbcd0a0eb3a73b09bfbf477af542171c8c0859fe30232cbbff358dfc7123edc7fe63c4176460d3b7f1b5d1603a990c1366b6da42093c36faf154261b41b9abdadf5c7caf1a0c086e770318184953d377528ffa75e63dbc66e8761d611bf65741cc62244491852eb90ea56454166a9a629192243da8f2e18e958b2f74445f8b163b1955eb2b2109a4e13c3027e9c7b7756cd2e5007e43989e2eccf7f5ac2545277e494b01531a1265fe0ffbd8498fb09eecebd704ce64f6e343941be247030668461bf23dd9c9d6653dc9952257101b028211642eeff438933ed7711b8e17c480fd2b33821168a7679b0403ff24204898305c6cfdfbb16e932c67cd398e0460e508cedb7fbf66277b67fbf28e52124cfe8b4811eaead268c3a452fa234d78bc6ee7798f02e0b17673e9ed0ec584bc69e373bfc29bc5013e708f6a4a3cdc9b67d7d8e29700973a8b11d2bcdd35223d024c1c14142f7d6326cfbe28a8d6aa7e09b5324ce8aff5f66549803f51e3f7902da9390550a0a95cbb7238b90489b8c6ea2bf38f217d5c407dcfddb90f1c80c516dc89b9695724df8f05b060e6c6bcdf710d26bddeab57283abcde270b8e49a576f4d3551f13de77c5e5dc9af6d4ba93c1353580898fd4b783439d6b0f0b5d095b897c153b05c45fd7d6d44a18a28ed7488d69adfad3ef03eebdf796d33ed1869beb215fb88df4438e314dc22f66bed8cc97d0e3327c0c828d100a2535696810c2d81ea08e3e214ade9dbeb82b612e2be0a5026a477c805c43731638c1f4934616ba170360be81d558c22e40b0ddc51b1ccd283d6cb7acd59b116b3cc810236d63a96ff132e6334eb2b11577afe41bfcbe77c6206912cd0c16d9e64000c86613cb43064ab94030fed5b36cfaa7d39acd196c0cd99052086132a5e0e8a959d6ec6b3ba20b442f79f904d148da7275d562b467c04d1f3b0dff5a09e593dda03862fe29e5a299f4d4917bd81473953bec0bc1018d645c84a9fcfb59e97e60d24385f00bd94446d39aa001aa41678fd591a752a5a5f913fd55ccc7e7f11f0820fbd8df11473311fd6a63016d1f02d8f75e136065012b394e7c3dda7439a5119eec65ce821b13745604429dece2ddf1c25398ca85562b773d6dbf523bfbdaff1f255f6436fb83448d9557ae290cb51f113b860c6af8ed4a1f93a4038e85afeab32be5ae1c7530fc0f905741f8757efd5e5d478e4f06a13bcf44d1c7e21ae11b5c056d90a37bf07af9145856da072cbe5e39ed19fe12be7e7a5de79bae2d7df4937d887d8d4382aa3afa55e4ca746a904946a7d072b0ac5bc0cec9b028f37f7044b96022f699cc35314847f4c416238759182fb0a90367411df06c5bdd82267a7cfbc89289e872efc324e8fe9baf0e16e7b5b2977286a0e2c45112209b2c7f3f1a955b04a7a98890e88ae841e40067a66a88fd998d1954d153f2b38cc150d7f167da0fb98b3a70c55fe4eb10a596bbbf7bf8441f363992f8e424a5cfb6657b126b0fde67a452f76ff2a23447d5fa0e67f30a8805156e35eedb1462a67f7419d8c9dbeb3a6dd077c512865b1020ba88966359a4f805cabda24812fe6f27040c9dd680659f89339225dbf7e8007d298477d1007a91701214871b48a3513c8123a37a75dad5bbe77222069aa17a18920b99e636d69179bb47a729752d45ad829f4b58c359a191303418e17f06d3ad27e00fea8952352b1e3dd3c78ead0ca479372beed7ca8e32b412063a68d4d1f2265ef73c35e7fb649db674a31c44775a8955d290f0d7326e5ca31c491fbfbf4ff6cf0ef402aeb8ee5ef475c165b0afccc03e5dd4fd407cc460d4f3af07c15dbb806a9e31bbe3c6572676e64ec75caf3ee31e1ddd3dde0378d27e86090e95646de971c8d539455ab74f5cf70a617a800bb4a644a3436d302f91af434be1e76d1ab47bec02776e994f69b907f23b5c9d297c0c56faa6b63f01be9350014e52c87b74b3a1b5c171a505bf2a22cbc9d3e3d410359230b63ce8d71c6ee628d4717b01813491f112a78208d872b20d327fd69e572d5640a11483b5d2492d5b8ae3d9314835d67f39491457ae56df8546d9e75ef2b54d8c4282a32a9153a13cbb5650030ae001f7a9139c0723454ceb066d29067c91233669865b37cc2a3674d691bcaee626827f6dadeea36486cff0b926f98a8916423598614160d05c5c8fc425f0c8502bffc8173ca957ee4f47612fc0842966c9665718bf54ca80ce1e9fd9910e51871729608138a2bff5a7ea11d3caf453909c204f260adb1b3214c8c4e482a00082449ba842f85cf71047430cca97109f8178431e84cd9d0b2095e69f5cf51290d4cd56218710210e29799825cb514f6e50b282bb0c70de38668906623849103c014841e9d653249ab4ac8d03c34385a7a0f6b8ebd722e3818ea0a13435a35b4bbf8e49e23918653f1f5215120cc109492d250f0c90b85f7dee80b86fbc7e73e88a4c014847f6f8f61e39f1de5398261b40c08c1e1c4244bc0f2aeb77b2a7ccb80bafea163db415391250cadc211c9dc703777c38f07cf28b0ddfdc7414375f2255cb88595dfe2c72f2154df0e1db743e605334b4cc22af08f31186345add94a26e51a5e92d593f386e96084eed89ebfdf41d79392589ed642a23019514e4237fb6e443a39690fc36fbe8d03074f5ab7cdbb5c033150d5a5e928d11e2d2587cfc39678957191ce0d61177fd84a619e073129ebc76a0e84daea9da1e45582d59826e2f7b6b62ab1339c38819b01f3baa7259eb12732c0f77264bd3f09c0e853ebd9555d1e7de96d8be9720041fa5eb0a91ead424900646d8377511d7148fcd128252f9f12a3b3265538a5068f53cbf03ecfc62992bc36d781060e9a811bbca1256b6d1784d497921e0b9e7ffd19b5be079d7f3e8320351521af25a471cce18f0d28a277c0a5a64bc82fa50fd846f2c4da31e14d6709344b8810cb5ddf2a215e8b6a09e997d7f3471544941015c4c5f5e2dc5525c4e7803d41fdf903b3f34a08031026f8f8f5fd6bcc28f912124ae90c91a59a08c9aa08db24523f013bb0c8bba7ce44b962ec498c91bfd670205b04bb0c3958740d72436ac50ec887a28ef648814565e17595890311574f23e8fdd590f31d3dba7ed79759adaf06421f07ace63889553578afd9142c2e82faca0f6982fda4110a0da63312836768320956bcba0158fcac671b3f7f9d91acf58c8db68031ca7e68f0f452a9d38e142df1d98fb06bc6e60aa1e00aafc9d88a64966f03b93450eec0e8bc74b58411cb9f6ecba8a4c422c64003b830091eb99a268f7e9920678a69ac8798c4beb108fd6c2c7b872c437b0f2a1b4d83a75235d8eb4d08ebfd952fd551d4d81cca15fba87e014cef4ad5d05bbd8eed0c2cfda4a4b87c897726d00bf99439480cf8efe8feec8c08d86f19b566cf5314fb7497017888090bc5696649cbd13353acbbeb819aabfa8f9eb64f90c5056b0fc39fa8730cbc5fd7515d32f4ac70244181075bab8b0aaac42bf094e7c8726f69604eb1ae784aa6962bc9aa06562bfbaaece53a406700b268fe64843949cd66642b55cb0e6cda29552df35361751e6411084b6ec05fbb212034c8a19c885cf2f4a01d5cad02ccbeca2cf04f48cc0ed2f2f01b528526d711de82a2e59d4e92b976fc02775ae5b4a09377ef2d45a862521876851c19f845e4aba3161075527052e063f44552e555d3bf67c5c4ab604590950923f4b28cdf5d6aee7836026641894f7619b2ebcfd13319e937ef347b4901e2c11fb35cc2a9b03b232338c073304edd30acaeeb3db5a39f43255d6f73ba7e32097456fcb42958590177206a17376405c742536c2d3e67bf0c7d388c021c3dfad68415f3db4305b2837ddd32e253e1f8a571a385207aeac822454be6813ec69bc4dbcf1b94dfc6172eec201082d3e5dfcb53facef34067f8e22f5e463ec113e5e4a56f95739d04422899937f9a694acf8b60076bf504dd8bb612480734826e6306bb48994bf106e6ad98ae0f2d8df13e5a87c5d8414bc21d3944404800218871dcd5357b741349dc74715ed0c26995c7a2fc1af14a38d5deaeea19ad4666962c3b484468da771b3f0dc15230dd185c94f7841702cf3d1aa95764ac544d1141dd9ac9e8e30a021f75e749cb9bb6c8d71ca23812f72d5cb8705a3a9e85e8d6b1f6db567ae2e765e176138354c832ba0002367525ecd359d9ae294f72d8cef0d7e99652ccde4956ac69cf79f213b380998800a5f1a05bf79b43b8f1b68dc4f6671e5225ad9615681d327beb59a3974908d8020dcabc9aabd42a22708d1323003b40918cc0c0b60eadd2f93e27ce89d853f49c33276d4b3726050a7dc1d5ceb9ba69f269cede4110d216daedc7f13bd7422e17fe128f3e13d9f3dd4ed958249de5e75068faa4b62345e160e3f7c708f009ff1aa70ed9dfa2ca6a0abd8e0008ff020bf1fd8d24d47924f96333e5418f0a285044f00c69eb5156d3ede4643a5a1ce6947ef1252464515989ee1611c2c13e66f61feb5465ea62d696db8858746ef52b971d1b84f1aa2d446e7e5c91178185a8d7148a498c672ad5131e224447b4dc3e69cdc44408ef1520da77486427880c3ae456004da59a3c7fbe81753d658924f0bda449d4c8005a290a6ceeb048cff2315f4845daf7ca3ec41edae14403e9bc0f49ae1d916e7621ed9f2adf82a0c3b040b7bc29efd53bf652ab11e8c0c8503c236dd942d6bac59e9e40c00b52cb98de178c31b8270bf67611555654ff50697a51115d6c910a00f0e0df56b277f9e27565ad917600a2b2bf7cb9f024e0ad4d0bba68da5226ffb88316f075b32615c917c262edc12b16c43a9af03af3e96c8d4e5383825ef3582faf2eb90f7f94c5d73e550bd918b83bab8d860c757cf018504b820f6e3b23f43723b3240c04dd60f5527d9e137223b28ee1725dcfb1c812fd7c8bfea284dd72041e3dca6ee421dc360be9c3a90fbe02f15c39d6aca0dbd70c86d5874fb4e414eb8a3894253377eff1b25b6d287504d8f0dae6021e417affe671358beb29940e35b8a565ef0e19dd58e99246f82f84f306ace64f94c64d32d52819663d36bba18de728457ebd73d9973de25475f72241ace99df84a7e617936265b05f2b416e4db1f7c08d03d9490231d05c4a4ff083e65daf295b5e88827a53fc8a80e97cb186384babea888395b4a1ab4dc93950f2818c55f56963e4536fa04205b1fa703ced792d08f1101e9e07d759ba64ca00112cfaa0faf7ebad65b48f2b105d63e492f76a7799b6590775d1658c5ffd8230431a1a452735bb0d5f326e3456c1eeb1e6ace4158d49a565ab066617dad28cf58c8d5afebc55fd63b6008827f0b56d82166bb62cb1b8ffc64bb010a5241485b404a71950e110035b5253ac87902ebcf10b9247621e9946b425e361d2102fc5794dbf53b616b30066c57acf37b5ba0f609ef14b54fe07e9bc3dd6da680b8b7f3452985ec37f6a0d8b064aa1a81a8175f12b2f7267b6f29b794490652048204d504533146d85a887f47f336485dbdc05a1ad6678a8dbfbb7f3f14e2ae4f02c9f6456b6d77bb4a150280824c9fe2ae8afb7e47bbaf42bcd90c28d707c2fad333d247bedacd8494cca1c25ddc148787cda6000869932a44bd4d7178bab66ff24647dac8e77f05718ab50c2a884fc8763c5b1fb6fbe7a8b65a12f9fcf6e82784b482b00fb4b5e9ee682aac67800a9df77188470edcbfd2e8be230722a8255460af3dc20932ed4209325254b53fd3a03efd2f44f6aa67d97d0161874c3b5c8530b99439e4fb4851b6fb201c810d3f5948a69df85327dcc0b78f864c3b59a5891ee2e4f3f7b543f7effd0faa1a7c7ffffe540a6e4f468af29ee2bc770aa27befb3f774b41ac8beefbb49d44b25cc61468a72dde28968bd208358d0f78d1fc4ef9bcdc21361ad1a963f8496822af4c183d0907c0a6d2ba282a09f90909087da27fe80796a86f0f3325214fd161f0b71a6dda5f4fba8ee3252d4d52d9e68562fb04f06c9ef51a87d110dc8404409f914f10011222cae4a8513403972da34778463979be2f270ed7c01f247defafc20503520b2b83c5fb61592f4449dae68c20d7c7ba65eb8816f9aed2345f9062ccbf5ec4613dd637dd6ef3e9ce0c39a5c9fd65bd469a75285c4ef485b6bd177b91163d330190fd4a6784ad8ae1d50ad3f1d290e4f131c1eab6aad876f67eb8bb8afafaea3f449482bd1f9f92819f9723383c7982f2c5a65038d2d842b3482382919f9bea27c69e9fa52e18b052ee7d96de5ce03994cfd8b808ad1dd8530595034f019a0531ab0f433fd1909219b811ddace5a10b682a0ee1474445741e03b459e5d53d45dad8b1c245ccd8062024244090d26cf4bc7996fc6178f0f0be7e562875f9b765f495e3fcea8d8612689150b1b42b864f9647c09f9b0ee98b903074c101830779ad8b9fa72ef58d92e77ae76b729ee4e96305eb870a953a78e8c2b7a268c549124584e40a3c217c34e922c6707ca4e905acd83969ab5d65a5bc3d55a6bedf37007823eefc11345d08679a892bddb6db003411beba2ee2f15cf7231c6574bacfecc3e4df1ddfa7c0749f134c674ba36068930c61ea4d439dab24d7174dc745facde583a31c258bdb174420873db5409d26ccf8c169cac37715cb8f77a70d2ec7bef9d32c1a6b839521bdc1437276b9fb986f142fb34a4b2af34a3a8136218d60f1fd427626fb591ff7f909375ce76c87b99ee1ea6ed87b476780e1bbec36f78a3a8133f5fdf7bf7effe847fa74fcc665a02da28ea0487776d54b343de73f80e9a8336226187bc77edfd066d54337a3be4fd8fa676c87b58ec479aa88da2c037121ff6a03e21fb983672253be45ad4461eb043551bf991527dd746d40ed5378a3ae15fb591f7fe465127c477efc5371a3fd77a703e1a4e3ff2f1276165344af4d1bcf7a119459d085fc3cbbe87f681f8b0cfb40fa24e88da99ec90f7b0ff40fc0f7232feab5dca0e79ff818da83f308aa20025ba8f9f12c1f407f729d1e952db43aa71b8e41cd59890fb246a082401fc14a044f82be04497c8a76cf58858ff202a2a0f544142015e98ecf34b2ad9db34f702c93e6bdbadb5b91750db3ea5bbe60758626ab952ab4da9cd6626d5cc94720484879b17759ae01942f4c2a64fc202388b2aa4bbea0ebe6ed7fdd5a8448a81ff68f728c6b6388a31997f3dca34498e058e2d21adef349794862b97d4b514d2201fd185b0e993388052f6afa8d62f4fe048f229944bb2aab92429bbfe870c6a965dffcb5842dfb40b69f5c4f0c5574104347e6c466b16a2a410253d08e67d104c9f411474dd5bba67f85d44216efc332a9d2ec25ac87fce4cb3adf2ea1c089d366521b5a94e5137a5a405a193c9fe5482ce5a6badbf75514ccd7c320b329ffc58d0c3eacc8f275d1bbdb2f4790c4538a8b9ddb805b9c57c0c01bad81972e1c746bb846c2c6e386e0bb06dc1d160b372f32d5d6e329b14bf5561193e366ca3573c6e7ebe50472a4aeae88c0c2b271a8070dd467cdd445b190bc2732b14e0002fdcb428b0f99c01381da53817d828941f373c37096c5868dc8b0c32d80c60a35a406e42a26e5d026c48fe854ef130736eb48c97b4e60b4a8b8d16553254d980053173bb549848e5b9a9b949296d3a6e706a369a25cf08b72d606e15d8a200d136de25c226c26d861bed841ba51a6d5ed3cd83cdcf04c096bb65604b61cad1548f17395c8c0d1a83c738c385857eb9e2201cf17273a26e60b6bff7fed47befbdf7dedbe1ef4050771d967d2f6edf1ea27bafee3a6b44031b036c4e82921bc5c2c65ff81d30dce87661854e97394b92cc5c595104080b540c981b026c44fc0e7de34be80cb82a5637676a710bcd0db63a6b6e74ebea465b1873cbb6109ccb0436109c9224a94b19178c10b1c26285062028dca81600d8dc0b89b7a154fc4d8ddb9ddbcc36a4aa40e10593386cd27041caaab2224b0e42bfa8a8153cb7a91b94db071ba502c2180f086883f1044a4b09ee8486f1245e0ab07996aa1b999b9120afd3012b848d665991a92adce8381b4bb182c0a85ae1e3898b98292ec2201447d76060a371b3c0f6e44d565018ccb88b1b4de371aadc4cd0369f71fb2c6093a34b0e6bc6095e4458cac6b91523c88008c0e65951281a1f6e5ae8b1b91d2e1dc5d8fbd3b11c134ac6efdd97677ff56746c97477dfd55be89fc7caa6b819acec0f9be266a8b1e96802ef0f182093a8348892088772ee488907a102e4fb3ad4a07bfa3202645be2c3dfd3ff9e5cca03c8de23455dfc415f0582eebdf756a1fb42f75e21210f5503fcf7137f3aac2bc849e106be3590f779def53ccf0b21901ff6de7dcff33c4dcb4851e08bb05004f183e2857560ad6e09bf93d95915f220876cca6e7305c14177fa0657e7ae0a055535b5fab6b5d65db5938992e4689fb5ed210295464132c2ae75cd3ec53d7380896cdf73f73abfc561b267c7772bcc041fe0e4eea9bf3b0924d33fc57dba08b6d37abdee9e776375dd87b733414fdb8d1c8c26ec77fab45a771403da5192be0aeb554778558c1d789eedba1b49a75c7d4408aa1649a7dc759762f05d9a898e52a113bfc701feebe10fbcb6731bbb1fb0fbeb3c13f848288000f80a42dd5b2bc556daa66f39a86fbbfad6fe1d39c0c0a94dd0765167ab876d8d90d6dc11128a29209f72a5800602dff895f05f1a0de2e34f8f28e8d7c61fd3678db1bdfbaee45e7d7af745323ec245329d48c64d4fdfa34d2b50f1e312f0c84e60d882c689d49029a24b66dfcf5dfbcaf0a639a71556745eddad57aad7e45abdce4ed1458b474bf3af846f5b4151a442fe4ec712755bbb37cd3905d921ac84ddf64318f56abb98fd129da61ac3083fda7df5da4e3c2db5feee7e3ac555f8de8bef7592b1ef7735840444f7de7bef65e394549ac9dda63927a4224d5ee68eec66036d9a6bea62652525c459f0bd7111bbdb18d1d2ac46b4f33581e0c136cd35257d6b98cc8462a64c6d6061f7d1cc7407849548792a9767f2968c33e50a8968b6b1e9e9c8abec7f7980506e36f116757f24099784feb5c33026339b32b5d994e9ceb6d6daee2a8d2c30c6de0705638289200882630998a5b94d8aad49ce5b7a422e0da2e76c6c6432992ce7247cf403f270dacdb66915faa1be7fe8fffc6c7080d53724b95bd4180b77389037e5e598aa8850346c9a63ba9a137af6a12128ed6c0532c5e0152bc4546046f1daf8a8ba7bfe99e17484d45e8c493ab96b9b37c6ec3333fd00b3cf876d9afb81dbb14d733fa2ecf3eb9890d6d0ad773926a9ed3df1d8e7c7a4b4698ee9689f22cdfda8b3c34d733fd4e80d34e16802a22f6e6f03514d2949734c5536cd314d6d5ad6a80534c4d711dbdfd4ca676dd744e44098da3d9be68ebe6c334cfe20c2dada878e2622b71465db4d734b4ff6591b93c23e6ba50b51241c275369a93cb251fa5812815461e988d4a2b3628d89646684ac29576613962f282b28216730426e0952ca20610b0769c5078cd28e8f1574ec984bdae4ce94296895362ee4152bd306d58c15c82f2798524f4e3f56d061b6e82143861e48240b5e77de7489c169ab4ce3a58e0b3fa6b46862321d29899032d84c183c4a1d3c6894e1d1c254010fb9240e0e34e6129912c90b28e04c5b951c2c702529a7a0c434c9f1b165470d373b9258c893664ef9430dd9c5455a6195d162beb852f29812a24217134a284048184620f3dc90d2f182850e104aab3a251936e4160c5461ca365b483455a69228e5d212b28e14d982103725984772bcc911a33421070b2b774c14dcc8e92a6f88c1d3858ca185f2494af98589c9040592c910274c268e1d371c33ca30384228997c9941e098486428978cf1fa62829085cc428584e2c4ec81448522a49a5bd9a44799e58692c9c20d176495196cc8295da429d59431858021ab72275879f2e48514ca1d51e597d39c25d28c0df28e0d11cc281b4733e8705953c660864c92651e5d6561e901254a49a9c5480924488e0433090e924a0d1864931a2bca397694b431879c99a24562e1024306adca2419a4ea62428e39224291184d65094b259c1b6794609060945890595e24c0315da0298f94298d6099265c91295479a132733029571ca12a426a6902b36416b951bea001837c81060b928c5719048ed9044d9c32a4142c12cf159a2a9304aa2a264e8ecc50847cd3540e59227203c80c186594192ccc1a5e70b8d094b83224169619e3aacc5345b6a1225d60b2e6c80845b09a4aa525ad1b3a64c0a8228345925719070e149aa73222609946ae4c165562a8b83021a31c295b28d2d4443e592aa5dc0021060c33068b2baf320438a5171ad24e19320c560a57258d2a2254260f26e6ed08a9a44899d46496b074c20d2c3060983460b0286be4cfab84ca1f1c724d9a15cc9457b44c1f5e9ce04a36574c1951c8d569de6bf0a48abd712cd123f6783e6389dbf3b0d10371dfaf751a6a3d4d7618866158efcb1ed332cd7b12f6c23eec447fe1234e1fc71fc31fc30dd986d8a03f36fef9b98745e0df0fff1477a83d16d340df7b5fab8d2ffea8c35a376a5177de532fc686811f088220f86920831dcc02a1f2c7043ef959b3f6f50ab54122dec704551d7bae38f0eb6310e75eb25561f43d7da0124b2b92c5f0c7043e59292f268b11f9916d88e9b36ed96fd067dd9ebb7fb2ef44e1b9ecaba0e739e8814af6097e0acfbf27506a9fe007ec2ef2bafaa0f7b1cf8b55106a834f69088f0edd9fc086c7daa7a2006b8e79cdb2c7dafee76920d9d707df713644752f3444757fcf0326f0097f1ff82708b52b8e7d0c579c86afb8cbc17bf0ebf76007fce3e84195298c93f2be03f81cb4f71504b3766865d65a59ccfb276137d0c6ffa17d3eb41b7e4cd5a321eafb58a28e76cad62a3484ad4287ee5fdf6ad343933dfe936e6dc97a6894881561ef81188b187cf14317f5f93981443ea79d65a76c151aa2031dbab87d1d57f1d6d6e7b4c51f6912a0e4f79fccebf04d800e7d7fbf2d9cd3068980443e26900806a140226e7a1627010b3f58540ab7ba29ffb690ecfb6475c5a3d3502bdcaa20aac5153f61daf86118b3d6da18ad48a4326b63b16a7d422d1f61bfca3cf6a2fbe81f12d56967b8b56b78ba571fb7ba28f6e2fb9f28541855cfbf8669f6e9fd472bb23f82ed5dacd630cb47e090ab8e1ee0702bd4fac2adaa1d57ff9827553f633e1d883ad4d234209109639c55ad0db7be1fc71ffbb1d10331d4eaa4367807fc45f50777d0a727ddd727077d76f8e7fb44a51dc6449146772c1613ad0eb5f08faf747d74a5792fa37d4fc2e2f0ac4c4fe3579932ce18c7c41d6a79d228ee31e6622cf6e1fcb0ac81ec1393689fac7d4ada9fc77e8c899ec414fb1bd363a825ea50cb4d4fcb47d0fd855a9d8f7728f2b47fd31c902c213c766dd35c90ae0dc4ca690ac7163787af238e2159fb824d73439c9ee26ca14d734f563b370469875be4daf7a826895b22d7fd3ec735574c4124896444ae0a0263dd55215b69f9c3b0eaf1b17ff8abff61b1cd5869a7ddf87d3aff11ff583f1f3d7afdd13ffaacdb8a5c5557abc2c82b3e3fd8629b7d7a9fa2168dd5fef6fe7b71cb47d4ffc42e3c7ef5bef7f429726def53d4ed58636c71d5e0b52ab15ffdb91dc4fcb1fddeabb5be7f4d12b7fc47914be4dadf679a6c2cc1e15dc7387c3d5d5707afb30fc54cac5f84bf3aebc21d74d785f58962c6a1ebaafafc461c3bb4d6dd833bd6cf1afedba07feebbb8e58f69defbd0c427616bf81a68e76cf7d0724daa429fecfbb3c648da559f286418e3d9768f4c0c2ff6f5c5afb31dd345f8bf1f451f47519f28661beb8a612f7b1f4db84c03813fbef7301c756671f773a65f7fd6187bd41fe064142866019055a8146b9a705ae7100d0d004000f316000028100a85c4226192c240a0caea0114800970aa3a5a4224a24a22811043411083200c80300882000001800000c2300c4619d1fbdff62ae26eba29ee702381748989b6e8528981b1b920e4fdc20cfcc94279561952ed9a8b581f2526ddd88277cba8518421c1260eb455e3c559a51523db249f352906f7c5b422b74e87c930919632c0162367ef7e7145a0f7ae1a3cc91840dc9489239750a51130de45d9250d23e5da6b781ef1668649095d7b377e1b215e46ed86ec550aaf72a94b4dee326d83aea7fbfa14676077cf42e99281b261a08224df6aa74235512d979242f504b158675df0547f09315a3843ab988fce8cbf5db3de06bfa1628541675ee73e68e0edd81f63a24950d11cc4799479dc4dc79cd30c4b18569849871e2665a0a6d09cbc8c8b13fa19695f912ca19a21dce5b38ad6d7f5abe5ad84c8f95cb5c7b32fdaee1ba2ef7c47cd0b0dde3a750d62c254c58cedfe61a2f7d96b5a4278617a0a6037e1a96b3b863bc2a18cf27f30628d708dde6b1346a0d4150ab1dc930aeb109bcd084342d26533c2800f6485014745255291008f2d9a049749b4d44af1fe00fee2ca940ff4e9d7516f981fda1feb767f14f8de20e1bbc89b4df3dab6110c3d8babc157e97cc083e6598914fbfec8645f677f08a7e44d28debc96e7bc3235c61f5c97776c749ea840cbc98519aef79d46d7196f1cf6cd4e5b894b96a997c63b20066b9a06506bdda7b8d5661eda011295184c2f7071dfc62b218a63308a65f58cb57bc8a1ca70e187e0dabed83f46b5721db96fe62270cc8a3d2d4dc11aa5788a59c39d5cfb5840f66126b4e85d9c5ee739ed2f05a10810243605e5771f577733d978b56cd60e9682f9369a4301513539077443307dff7bea88ff48a27ab8a3ab59aadcda09380a333b107e40051fe0f789ffd13423d210e11a4a4b7423507f2321600f1feec02be989db3bd2ff1f048036f785ae61f1f98d0c5f3c2349c1ad3710a2620cc4415922f7e2f16d8b216b297b1ff8ce424ee312f8ac276604888e2329dad0b74ed5c29342871e06ec4aac9108660dfb04468acf7c89fbc3e793f407a75581b130ca4d08c8f5d996edf352ece51c08c0f80e02c2927b31ed1ed9030908c8de44e69baed2a202a888d5ab7fb3567f9ac28fd244388c049e1d4e2accabef86d9aa5f6195663850debde5867ce4771d0db47a84c2ce22831944cafd633fc9ce843ecc3579905c2f46af28176f9bd540a68b47ae960a0f1a101058b7088fc9bf44700a89ef75f6b44e7f2a027d894c346e1b6d27189bca1732ae83ce46dffc6af3771cb44238982f308184cb6e0701dc7cc49a66b3d339a38418725f42ecbae343023b5dcd73488655d11b0afb32127bf157f5629eebc31cc71647a05bd39b17346a5d789ca9d46c096202d43d47af9b6ee2d3d105cda34704019504d10561a8d264e8ce3082d01825f8c26dbc08d9fbb1eb161609e2cdb4cd47cb36756b2fdd86a8b967cc2b30b674f1e44ae65cd7e9cd1b291837c1cd77ac4b65ab0a136870a1096e3c784f7a67524282c44c3415de80021a14ea7044ed3333e8bbc44b594679d42e406864996b389ae01e8b0405e50812db9747b7ae3c3638a164923bcfda630188688df39bf0d4f50d5cf3050fb0f37adbb5be3d39f4f7d293b3fc645c19f81217bb7e1f18855213eb523af511e1ee8a9121983342d122df4233fe229fd12e410c8e4faa3924e41c29a453612dc1bf0d7f4244c6a3aef5e3d1f7da4c477cbca1e266930cb6e9350b9f8d1262236265cb49669281da9ab2457b30b0c6ecbeddcb9e3187d28a6ecca6133b155b356f0960e05e11d11c1a2f9aba1052814515b45acfc01032635dc14b76d93cbac96408f1d6ba722b67650af6403564ae3dd77799449f5dabe840f0b6b5e6ee8deca026a306ae4cd91f04b406a28a9bfa8607c148d5cccfe63a23bf17c7c939ea9a24950e58b29e34176de9f7a25850b30e42421d94ef5d6e7bbbd16f403d6f779f2a243276fee9887d485bebe850516f2c6993f901a2250ca9ea9a5eef88334652ccc86df76e93090949589d715449e0dbec9d23121776964c4220ad43788826125666eba6405d0c21d7294581d54f1182fe04cd24cb65a5d376aca18b2e910b5cdba857554d5d5a5b604b56d6ca8cd452b44466cf1f70983abad5d907160a66723106c7125ea55c674b8567ddd20c3fc24153b7463c5338d26493c168526006f03525e37363a3420dca529cf3c1843c8b3f5736a96f3155e145530382464110713186dcb3214e65d74b897c10f13a8683a7a12b5f2926cb8e9f1c8b987b89a4c7599634ac87ce3e4f6de26b24741771b0db7126ea55bc2d3d2eba3c76329e2aba37630c44843a857a65a43ba02cf392ade3c23ad1a58e5d6084747ca98bc5f491236d383a5c037b299fa36f026404241c7aa4b4f0aad32dd9878c49a8cee330090f1fe5ffcbe646cef5d8f462f65b244792ac7c3ab1c19116093e5ea4e950335776ab1c49962e1bd99c0c8044531bcda81d19c551a34c4dd12dc5c93a19aee6da8fb43d8110d3f6c25d4500c96427cb126b50248de696eaa25c58fe58e1686f1b0e8e309e373ba9ad5462a57cdfee5837406ed592779754184c8ebb1a08cdce8bf2f2151eaf45b3195bdae9c07da04c50cd70f2fc8e85003167a82e190bb987d1741e5d81b069876adf895e2e8de6c2c555acf52aaeacff569567da41e4228e3865533d349a59feb027f6876701660fbd06ff5c5d98a42f01a7c362425756147612b2394fd2652eba445416283d628ee3b5a4551136f195476d700502edd824079af50c4034b01c73626c64dcc57a820cd33f0067fc3c575a6f6805dd58ca48149f5ccbf2c850e8e90cb04b4efa2a624ee7e98079b3c968664f21b284d30d12ee0e013e331abf305aa7b8ef480dfaf209a68c5413da982f85fa3daea17024e9d30a16a5ecd00597442d66453b9cb31de220e9ce5d0bcb80f67c0e8537c62d69042eb61ed8993bd9219578e4f572db5ee309d0c33bda6487c0cc18321cc9762ed8f30c6a08a239c6ccb55aa4fd0a9f0ea25933eb32d096e01655450d11a80822bdc3b0fadec7978f3f688a7265b2bce8a31638a2a1b696476adf504d5b0926cd943dc7f22f15444f03819c02c68cde10911566c1a7eb068c560db4e731e1303b81b060203f15dc93804e0ce110d98c158f0586aa243a8d5c07a02081de0ad3fcb7b68e793cabb71eecf8ce181a0b4516902f41b4a5278d3d1f0b652e6ebb99b944c8e66b3716553c14c2cd9ad30838bacb80d88e4007de2984bc4a8e147ac854186787c2b775b22731b9426357d6a15563c2e3fd6f148f873810e54122897d83619c27807839c3e3737b8062d32835f8b3126c1fb1f474ea08891f198d74ca86eb8cfdf0e32675e6d50e334810cd90c45334ed3f2b95a89f79102b0fb43935a5b8c148b276a4a03dd17687909d49f8198047074e2cfed12ecaff662e91562c6937b9c89308b605d75cb7c355b1be2ba1fa893ae1156f0d23f78069e2dcde014745802b8d460c949a034f0366c57fcd25b7bd30a0a6e77363769cc68bc126bdf56fbaab6740be2d4d9f4fb32ff2d4392a52cc9bc7f2620cb8e8677250d453e98643db7c4ea0eadd13ad0f4889948d01a76f0293e7268c36ac6e127b30abecbfb99a1889858e0bef4f1bc4d22dd1b3e5fa6f85cf44e530682b642f0448582edfe70ed51199fdd348445b43448541a58ac1ecf650206192116686cfdf798ec42fc1c948e75b0ea23756baf5e6d271fa04c071a5a53bac3ed848981c27f95123bcff1f2bd70888805a30efd16d3cf8a85151d87bf2775fac6921f33f1eec9bcada6e57e1367bfcbd3d1af2df6571008440315ea834742f5b591f6e97a9b519e668a45dc1a2504b5492b08a223bb24eb6d914d09f5d31246695e8298341e53a04412e7049ec24d1ad411d67701a14e2b80de8a918b3ee9860b74cea09cac2deffad266ca87c68c134312e6097444d454da20f13464f2cba1c504d15433e14b822665a5d7dfcecf79693c40c8313637283f07ef83b4fe013c9a0ed039a883ed84e66ba6bcaa14d7d77e77e78b6a5fb15908e2553722ad17a8fbe3a31c5500f00133e381b5b8de3ecb9a09148751fb57d5323c2270418b42a0e6d0b2eb8d208b272030dfd29bf32b9b2bf31a23041a4005d80c2e28649bbd221ef390951190a1972ae58c827df44829640025b056f1f6ef19f3b16d34b976fb6e55fd9c8f89f284616d00fdd00218eaf619affc54db2038df7dd851789a057d1065697e18b6116f4e420a09e01ec6c98ae191a4c275cde6b6af56941bf3dbf2a0294db8a06fb66532cf0e41eb21d31846d365ff9d92a7fc43a4b859b43a9a0d1d116166f20eb8d83b9d1e8710f40576f658e661d65af0ae9f35ff2c72f7ca901c318af9ae133e445fbfc8097eafe7e14f6078414f82bdc903aa6c28afb06c395abb50c92e466929c46d426d63e848b8ea5b48d7d15a037519d6d74cc9b9984b89006a8156307001433fa0bafa03756bc6a560469b38f0cbd0b3ec385c7cfb85e1ed0dd91d9c266d2886cb80ac04b7b64d9e1964ad40b818e3ec891692bcc852a8c0492a6416a796693b815ac4388efc39d12217109c856f0208de63c8cdd963cc27571130891a17f6134f0dd6365bd8b64346239dcbdbb96787913f2770a8f35e5a1bca175a502bb48e5247085ff7bf597351f97d9752cd423dee3451a50e5ffe2a9b834fedebc03e12bf9874a9d4a8ac5aa142b94d6e4e721ffbb3020758fc89c31acd6e4e291bfbf180c9b776a297f63dbb2f603e9f0771cfe467d7ad9fdf90489b8d085f60468f79baefc8d4f6560e93916f3274591258c0569a84c24aad2ece174cb736f0ce0778921e8c12cc48d2637e7880461e21723d90680896b014647f5b509b6e5db84de4185a1ab2331ec1452b8b1d3519f3f7c3cd669fc8c0f713c7bb47b685afd8aace4f1573fcdc426f0605ddfb79daf603274ebc0900c6004fa8d7904079efbaa5672ad3f85cd28df862f6372edb1a8f300e3fcf9be74e70934a952ef93537d867c568cefb699fab94380241e7b637fcb539c378c725d6177e55b357636e84587f6b629bb9e38afdd2520d679625b8173b1e3118dee08b0f9b02eae6f9ca96df2901db47cc835ea0469585f51984bbf6ab3cb625a2b7d46fc42accb63c5cf33f3a064d163b63610eb9ac582f403f05cbc832981f95eb7d52a4d6eeeaaaad8c9827a2999b58ff1a3c6a10aaac370cd0582f21ab3dbd03655d74a32f66ff4f92b3185f4778e5953c17bb26648170e87cc75bfe68b190f6ca2899e19adec5becbaabf1e96a074072f986ce9bc4c7f4d7edbdbf85abcb055f58c2a1a02c31e1938ca815d5c94897971aeeeb4bf1dc562cfee18c5d33b2b5e1111270ba37da4392cb7c5339c22bef5f598d947a7777319827120e65e37d7c1be4406a6e95ce6a0d66f65d989292c311b40cb8241bb9bd65278a878ea1d91f54e859b497a79ac812ea1861867d93c69879ecd4146d0013d3b30c610f78817301e14f28d8f86150d3a44987e9ac2bd120ff3544612137c4e4f0b78723dc930610c35d848bd804ecec936fa29ec2feb019023c055e286ea9ac139c2c21f327ca86e23d18e5ed93b0b3a7fc9c62a98d300619ccc020867d08224a7fb2b202700db2a4e323251a6c455452ce55e5c1ec1e88c1310e3b785273aa8b814641e46a2b8c179bcf2084229b8c0490cba7b5def40c8121e1d9c928ce6eb5d070031cdf85d77256b0bcf99010fa5033917f6592891d106c077811d248bb59cd31f334323dfc00bdcc6112442e79ca0a82583f47a6b34dc0863e0b3e2434134d822fc53d1af0a1e71350f57e300b253d6f799dfee9e100e69ae822e029e8a5624bc959ce0f1107c20ea29a264d5a4c615da92602ce1cadc59f0487022e8f9180cd76883974322c38c0b55370e0829205dbe0e14eb4c3498c33afeb366e0bd8916777515e5b4035d2f421091e36548a0ef0510b82b7c2f1a8fd050395d409d571face8eacf52e10c64e3fc571ea66aa7a2002bce16b109e69408cfa686280308daf9cc3a99bc07e405dab5b937bee7438ad72975e822d81104b247ae38c1cfc8ff69edfeb51924c73b4812d3ba775110b4749d6c654497b1f489e64acf7c811c28d45177726f87900f5bedc33093cc48d5dfde98c857b70255b111adc8ac7e04adee0c481ae88e6e81fa2439d9c0474c0a5e20ad9497e7142f985003858ec6cccd644d77b871555d8e993ee8613c24ed32cee3d6fa54ff5495f30e3e24a26f444ae7120e1235cedfdaf8191ff568f8fe7b8d67e89dd39d7a3ba82a1c3a0619dc2f886d0f8bf920843fe9bd905b09acf91424c687ab16c5341e0b562e1f5158105260bfe4aa4a10e09b8f555ebce7fdf3afa11e8c4f4a6ce709effc6c75fd00121327cd8fb6ecb6f485ae46fdbd16fd67e67f865f237b07e73f88ed1001f6a8fd80672134d3baf34b40317e7093062c3654360339ab117b0658e3a0ffe4acd816330fd818b7b35b162695a8d9c166f1ec435e291a4cce24173b4742a35980c5dd66fc81765daa655b6e851154547526f0b97a65de898ba3f78b98fdec317c50a2e461082118d93bcb5bc327ad2f19ba3eaa891a7bc100a7b8b340bdcbc34ff8beec2ac7dfdf483a5c58435c8f8149ed02c5d428f6cea6756b5105c9250f05784e9d108fee4c7694a4fa5fadc25949969b68394b9faccbf8445451cb9206e3a4b3f2ca412754684e7e720dee50ae53f9efe4fb1073c25fde01fb48882601716e146187b15543c22b60faff4a049beba848afbd5be11427db143772c4385b604e3056dbffa94366846af32a61832784a6c21821449307508a7ee378e3d5889d45aa8fce97a8d8e46a1b05b9a3f914538dc0c0e59ac41c74dfec298d45ad7c429b344be6e1bbd510438e0708ae4304654c879001dfb9bcfe74cd45c928a802cc0cc464f06009805750be47c5de5b05ff5249d5c2f19797bb5cb63856f94dd2ac78a1fd784fed274944f065b5ea2a3f0fa186632745297f9cf663de9c9f1ef18c38a873300521c0ce4d97185bfc96b90117650004f6ce2c671edab8a04123fd2bd31403bc6843c890c1c5b6719f98712e8947e720f42f8d0ffe183ac065182c007792d8a14c1a6247fa9e6dc56a9e6ec03aa8aa7d43e88207754b449f4c18348f843092a254572e8875b5d8ae8f3a42055c359dbc85432a489466a3d3310897e487296b2c13c11996a24a30771ab904aaf34614ff5cefd4344d1904041bc40ba7acce8470264dd0f6ad5a4bcb2b27122334d826a402770a962d7528ca46c20270aa90f19ec2e042115fb38e05691a96dcfa90432c594bb03a18d90f2af34694fe59dfb07f143ef870fb2e243a9a2954000211237659c42f911093b25ab3c7d787c50409440d8ff90849a1a53ee0f886df9d4c8b3486429029626fea9e6dc40087ddc01f1a9f4a70a22f30fb7881439c9f3204b3429fb4c0a4824da521989e60f13dfd47e2a7e90f391e8035e90935aeaa364fd6013903e036232969c1924f42de9f4316b8a2c5f0e6755b09d689037c85f414e34a9b24fb755a9c9a4f08712dd94d7a76d8494e10cf48792444a793907392dc812e7947eee02529b8c9437a4c9265535731f903fcc7d48f7916d68cafaf3c4666aeaa924977220b70a12493b954186e9a3ed7f6a2f690151223be54d99649b5a490c08453f949c523d9c8e8c94328634d9a656e71c04027206e1838040a641183e4420383e9c3fd681e8407c108a1f0a207f3e282050822ce94bed4ce58f9c55952d0c794d33a50693a906df315e1b4b0e627ac922704f123d0941b268046c4ba29993ac55d75a2d5d91cdd7f9eec326345158061cfd09c83c785537f111a037ab7318e616c148c687e17c130ce84ae8ee788600028922488342212cb02b3540935b478697d334a0b7519445a434d1494d27952ca464942790f3a7f8ef58e9720184ff23fc8102d1064800c4524ca945e27c274315fe2f2b3d893ea603224948ca7ad2c4766a35733f207d98fbe0f9080249811c03e4442cd558d20e425b21e553b63ee0fc61d2913a4cad802c69a7b24b3a03b12d7fc92d4725482e020140276546695291aaf57af27dc4f547259a945d56350bb1bd4a35d9c9762d35f574db4ded96b47e2891d9b46dc49291ac206f1f743ff47f78419892dc36aa86392d51a43c2b4d4e5269b3f001bb754ea4afd38bc5929458f5b20361e5e35a10483ea57c37dd2a539899e669d999a957b2c9ced44e86c5e8ace7b10a0e240d9a09f15fb2b4264d3aa9dd5482c84022411e907a1ffaaa7a12a18f1ee4401f92a4a4244a0e819cec53559ffc2f4c0d67e403c187eb630dc4ba0f25ff947d72013203417ebc204c93f00fb862cd958f9c7fccdd8907fa88d5f4c0fe6bf92c8c52498545e6f943c92f55bae97629555869724ed5e7421f7c90f01f2810f663c64296e452c9ca591fd08290e491ba33b77c28399b6a28a39968bbd5974a952e1091c4ce183aba60e55d7fbae1ca9b915a18a9442985513681f87c544194407e2abab9d5879233a9e6720751e2d589fe9451ec4f1422eb518553ec28e5e96044a37cfa0c6b6ebb4adb2132f840bc9770efb35b05d60e749409b116595551707811a6a5b3ff6ccd00ec0dabd46de5e7332bbae7e4a1359aa6582c9e1953cc6b5e53209bc30cdeb0ce12b5077a9c086ffe402f144effff06feb2c734a1fffc66995375eb2f93bb59412b03f3eb552d8b9db4a3745a4fa1b18e738528d632dc241d31f687c79b92fd63769928addf4328454130d3bdd4943316c4d5ef6d30b6dca0a160d0e29539fe28e2e10bbb38348af741eb782af73ef057afc4c1501a1a0cf2e24fa6e6d8dc83e74d45fb747c78cf8f19bcb6b3bb796a8fb163967a6f9dc22ba4fa66d2c722f6b3b2b649528a824f26b1926c953e24959d92cd6db11c761748b3cb8cacc5c2f0745f060874e9f36489a2480c69cd324c5e0d207d8c1bf3b16caa36dcc31eece5adcb9317b479437c329017315d5b68b516950373e6136303c5ec88eebf3046fed5addb6e0d20dd941c77816fbcde72ef7749e098330a075da48373d8cebbd399f63592f55961b231c28a8e5906664347c413b8f50ce1256b02bbad5107116a3cefe7d0496351b7464c0a81dac64d9340fe1ecf960b09a89d0eb9cdb119f41c3bde1afc191ddb482598309ddbc607b2b1493dc0e167d064a4cd487e05d9f368eeff592199a938c1b2172f4c47ae2ba6b9e0c15721ae893318253518d7e453407e8b5b711bfb92d5546410b41cf3ac36b935ed1df55204925feba0a182baa0c66611e53cf08aed907be83c228aba8d3985c746210c339ab26585c10e2aac8045c4ecb349b4160dfb984eb37276c36bc845400c2a2be5a2760f133d106f49d5c093c22a4850e7589b7e1fc74e2a0e71ec330faf108d294aa0e0b488775f2b62678b8bdb80b13ede9ac4a211d5c77cc9a3767f924dbb9ae3b01417480b72ce41e54dfbf844ad7d1c2f32e7c51db70b7482b2862cae3521434f13805dd2c38e3d37ab05948d736faac815d24de8ad37b376eea788a1ea610413737f8ce012ae62c871ce58dfd4cd1d029f8c2199a1c0f2f6017b8a284d5c006ff92b452325750727a7fd2de402226f0f88a67e7802e784fc68875c22862677c5d0a720f6d6e21d7056abf27f184a03fac2b7e1f107c8b01ff4ba66523b7000705aa6c20112d75789445775a7709392b3571d22d2d761191db00201b5205fab57f65aa0cf68475e968eacbc58b431e999628f327244b6f2e6fe7a7947d1e8645975c11f8ea562419ad2403c5eb015cc3c13657b44f4a56184bb93265780d28ff787b2971affdfec1bb36677317bb9cbfe4cc5e345aa0a59657b914cffbc07c16686174995a9f64abe27197544a94b7a874a45249da1c5e59f4314b349362146c09bff1a2fc48a6921e1d0a369b4138476fc7d2dd3f11be4e56bc4bd591acb7e4e2bf3066ea3801e0f40bef97211dc5958cbcd3ec150d639cbd30dc0b4c8891668ee8cf4da232eaa65409e41fb8467d43a0d20483576ef198fae60489b12f4a9ded2b9120429470f18bac2d300234403f45bb409d26b11bc394140f97e35fc044dfcc871e0dcf939d248af949b2576966f0b02d6804b02f3bcbe706a84a775d6426d9711de303d8016011325b026cf9d6ce7c0122c42b256eb55ce800a0115e4ca1d33158d7fcb3544fba901c99bcb5a2279dbc902a7b8e5bf62012c69c0073f8540088f8d29e8ceb16f83ced84b744f1124f62eb3ee09022d5d1d3a7e84403633acad0f49b16555b8681983d67d58a07fc081fe23f3eeea945b72cc99f26ecd747ed123d3837058be6c2690321458a1250a0f5f73f9a34b4926a459fc400ea4f7548d76fbbb7d70fe16f2deeb3e6abb35d408c73900313cc60e303cb442d48c4d7b5ba50658766d794db0cb16b08488a4361015f16b09131f0088973ea1a4169b4ce9946553e54056db4ac2794b482240fcb466d7bb58bcb391d8089c2737f5400ac98ce05a12ad6be593d6798b2ed6f4cd6a87a2d1930405f83358f98bf5ac6cd5775f545ec02b7d312fb3cae37c82f56c69f1885b47c619a97abfe660dce49801be970159831f12c143e72c85c46653a667a3f6a085574ac66fbd9d3265e7ff6123099cd43faab91ba80ca5b78652254fef78f01d3c322f5d350efbcb4e39b43b65809b66480baa7a2b34c46a9bc0bc8f481d2018914023a95adec65af4d6091e92d96d276d9a02fe0711a7691a032c5f5c434b529305a3ac7b3f98bd3b330a6cedfe3beefc6fa18281c1fbcd314df905bd8023eac39e001c6314c499a89729ed2f149bc2746f10ad4f14dee12f92c331886cec8aed2b50a2818a288e49a5e1743571ec19574358e227d67fefac9157ce8b26a59ddb341ace6645e7268235b9fe0528fcfb65d9f2c15073069037051e65023beaf3de991f7ca012219ba83f9e37d6173cefffb1752d490a1f144cb4d3af1565d6abd4f6ee2d70f85fcb26bb4da4e1c677238b8ab1cfeb6f2ea0c0ca3502c4680dc5b7048d87c6da1f4831c08cfa48c298091a164858ceeec15f16fe44c230a8faf7370225086dc92c365c8a80d123fc13399053c1a642b7e17305179dcda8e3e51105094fc2ba18629fea54518d33052d097868c245890dcc35084a58d64d584d1daca380ea53a08b26417091dcb069f856081a301bc7c308c5f3d3d954383612d213328e370fd99c2461add455057f407c101bcc4285cbb48d44622ed80e6950f2b88362068f4686df927839d53daa8f7b1325aa4c5e19569f130cbdc372eaa6648a1528b78124d292c85e17771cc2c8c81dacfabb86ae5e69f81583fb482a23f7b7d205ccaa243fc0699df099bc17d4cd68ad86e339276f060c8b41be1884804d349561ac5f76dd20d2a9bf1de6bb987df3dbf27602969f00aedc1b859bbf73bafef0e8a71f30239775290cdc50c7f8eeb44bb1d0ea95256b6bc2253a89005dd3f18c30dc5f0c0653d1b5f338adf83d3474392c390e6dbf386f4eb90d5335bbb208418393adf9c6a653d1d62a4041526a0e0398b304ab9b3a33e28eb77130582348fa7a902dabd9d82a05fbb95a6161f552b9f8ae08faf159316344691818729cde7aa5c48d2177d28a0ec756c12e33f77bd2a4ad09f10230a4957b4049292b1fa07425af440b5158eea239d83aab14e26774bf5390f093607f46a75720ccbbb3d2f740bd1f34b3550a2c346956b6aa4e27eeab0b1c8f0b9d1a0b9322c4a0880f5bf606465af65aeb435a35d9a3c4563c11bf3fd684e773e7cbf8ede342f1430449ab2ad1700be0cb43f58199351a7d67174fc72338c0149873ac4c4a3aa979c48e64914c729cc1455ef2ea64313dbb1edd4b7f22c15c74a75222b0389ae68e439c8c03eb0fe87bbc5774f642c5bc22a9a5f34e0ad702cc05f8c93ebb6cb263b3dc7ed4ac750d6ee31257a409c082951283a21611e13a906e44c1d6945bf48a925d1862d5486192e5f848174beb60cb3002a531b2c70cc4b43494614ed307b726f8322876c0b47089a0c4e69a8084d0c6a405e69bbec501a663744ef70d79c47ef98ac0354fd5c3aa26fc7645c7a1724936b3c2465c8430a77fa60c39ea3c006e7cc7e8f529c05db57be86597f66281bf9894c34369d3d8a3d31e75dc98937868f10aaecc3fb1200545873fc4756663ea6d91079963f7bcfb2112cde4ac13130e88b192cb7c24cd52de49549a11cb8f61a46f6cd463394e60250bbf12a92de13277a944c8a7d9d30cb41a86ad6e2f3493fcce771ca4035ccea9c51e8db9cb578f1246cc7d0106c1465d01ab3187e2ae2b901d0908c4f5a9220ba709e3039a9f8f2167b8b512bd429f0b217ec536cea26317949ec1f4df6b4d28227900b45f4d308637671aaa206280ebdd66a9e760761dc185df31022526ec3c31df6c3e564379d65ae824343c50404722d76f73cb0f544ca85aee12545ab4471f074df58bebab687f2b103ae1d602ee54150d7616aa6e3730c634da4ab771f72e9026d6c9324095d906697b195f5d7c9efe0f34f86ffa7a13ad108d5c9504d6b42799a4793c30c5ef2ad6fa5fc80580dce4c775f6521552b01954932b3833703b0f396a758c77ef90040a62abadc751d4bddd90a7e3d8bd49072cc1650436f9881fce405d4a314e83bc38191981a2cca1f91c627341b6b19025d831d9ed71c36995c9dd0548b0a34ee4fb33060623afc08ea30a00349748222849002e8f1f22514f4d13021f106bf7d4a8e0e404f508100d8dd17867e667f4d32ba5fffd719b8146acc83898600468fddd052fc84f8a71a7ea51486ff99bdd96075b86508ed53ba741249d19bc0a5870f1ef09191fc5620f1c3b64a7e6ce13162561000f105b5e307288cb8d4db34fd47e07bb331ef260da8af14d51a895122891af145649cf1dda55b1b73bdcdc6e990015a6b2415013be9132a02c159a8230c4ccdf5ac31b8d420f15817c17b4f28984a72cab308c03db405348c59dbe924923186d9e4ed4c9470577d879607cf8770a7d2f161444a00acf0f188672ef670b01c4129d70897c0ebdf74eb54fd735c2d13157eb9e8d35e52141613fcbce95df44519f11f8c6701967185156072f72ddfb1a05d9ae1eb34ae926ce0db58afd88eac2522907ae4231bb8f00cd309a013c64f423fcf189d9b323f1169372d3edf97e59fe5f621de5452cc183f5c633b605db9227482634f1558258c2ba149634ee756060c729c172c8cf1d11a01c30a62961b976bc61050874a010bf887322f8e41275da43c6ce7aac0aef27e447106e65426e37de5ee8bf4bfd77ae4fc68f54ecd14b6680f8056611e29d8060ebce0bff989069c8128ab3af50c2ce522941da09b80834317c937a6e3e43517cf525ea4cdf975b4902f3390f244d04fa0aab975a30145ea503898cd4157575661ff874046611eebba07dc17a584c619312e8f24f8fedb2c74ba844ff50c24c36770f919500000603c0c72a01da49b62670632ced47531668811208c8bb06e028025a9384ec2dc996524a29934c01f7087d095609b32a3d76c43e1f7b6fa0b7c0ef18df77520e568d5ed5a4687adc77135de68c87e79c73b24738233f671e86571520ac180185e5439212248a84746d893280f2cffb493b41aac11ab5cd7bee64502426b10089d79e5b4d92f017eead8b6057a55e411c86fac8a88b88ece670f8e7d77bee7098d775c518bbbb9b5ef83007972cb1bb359a60b71adf7ee3637856b6d50d676a37395a0d343fafed529b89c106ebbc6768dbb88e46ec42ca0bbb4187f0badb7555a74aba56f7d565d12fac731cba9d7194d22ccbb2ab3a3950e6d24f994bcfaec45ee8eb49cbead057ed8aaee351ade116d3b986d29bfac2ba3333bc1ccec7fd5eadd57df8eb55610e541d3a86cd4bdb84fec234ece97453a012f50755e2e4a10658a7af2614e972f2d7158aa445e55417f5913e825dd4477d94a532b6e569d25b83fd6a2c7afdb27608e723228d7278f188d743cea8570da1430db61067e46342edb9e377ea7e39852af9c14a513e6fed39ec7739a957ba2a1901bd9bd8e9fc5ee34de7f4193a27bd349ecb71cd9c0114242d28465efa55c417d267c47898d2ecbaac858e41cd426a7bf52e7a39d62b79812ea0c9e392d74ef7d9f1532a00e9a6294925c5aa747d37a0ab85831e7060f44de70a8ee353d67939d45fe700e91f630cd66127f4542a59c943ae4b21743880b87f3e97cfabe2e168bf29e331fb4d990f4e9a1e1fbe734f2f642cf6c1312a115e5cb78a30f2dd2d22bc7c67007befbdf7f85df8584796d66021b1acb7797c37faee7dd2eba7843a81dae79066b1c03233d7105d2ae566caa584bce0871f6a2a8ddc184b89dd688adf41c8d687fcc0e2b7eb2d60b36b1181e4b9458491d60dac706911116542383d4ef9450cd792c75b6362ba44b09d2164478f1f2f03c1431fa6e3d15a6bbdcfaaea5cb11add550d23e20822947c7d18cb539df3d06fbe8d5802074ede653c2eeb61f9e0532fa535ba4ca9a49b1c624fbdcafb139f5e7702eb2ed62bca9c34c4932f1e014f95fc16b71facc45f855c4e64cb6e37433adcae260f2912bcb0594da336c37f5d95b26eb0d406a6e35d5abb09b6bbcc3d75da194fbdb45716c3c13e9f52a39a499b81ac1bece65eb3faa2cb0ed7420460d6027f741adda5e33ec5d77d9a3668f21b7d6803a487b0061896bacf6cd7a7e77e32d52836c3fa525fbfe76f1b72daf69edba2bbe74585cddecfde10f59e1d52d5e517f5e8f446e9432ff4d7d4a04f6de8b187b757cf0897932b08aa440c7a5dd7e590fdf9d0476dc35ee8e7065d470ffdd47e60da1b92cef5511fa98cb5465dc3e6acc7fdc9abb6a5be6eeea4f9f09f30e74c02109e1c566f8fa7abdac17f721ffed355991ce8e4d24d27977eba43afa35dd6534d589bb4a1bfb41fa9a76d87aaeb2f4a481c6c78b12d4a494a6df42e9fab4b9bf16e36a58429615aac5ca9d2ab37630cdb8e69a149615ac6b0ed1b7d8a592509840a1dbc2ca42af56a56a55ecd76adad9004e14bfae76f6a7783f07aad52db1c7ccffbb92633a2d0c46957c7db861e12d98662142cd7bce8e40ed529a4935e4b2f469d60a25b22bdb05761d8ed11d147bd349173469d63ba62920893c024b007eaa88ee76a1775e1b2c4a5cbd297265c969cd0843ac1b644242a8c5fa270f11205d342ab605cde39299d036b547a47afa84b1375d1237a444dd44498962e7a44f611d147f4cf44bdd6fb4cd41d9777535c302d483f54ae714547ef6e0d2faceb7a67ac05c3e4b04bdd0c28d0e774734bfc4ee39ff1040b243dfee6964cbed439d14593912e3269f479795ede176a7211be745b9c92e3e2943aa73ae4d239b3dd0c3090943ce78fd64ab11962d8e94a339e601d0fec37f79b9352b7bcf31c576175da6a52e4943ae76d4ea9971e5113a2cff9c7cf2d265bb87ba9627133dc853e622c724acfe6f512bddc64baee06af7b69cb1bb58ac5cd80174222ec686808d72bb5cbac5be2d010ae576a175b6d557245d615b511fbd0c238778e9d3198751818eb10ab582a968aa562a921e95d0a9e5b4e9c40e78d63bd31ee9cad6e9dad6e9dad6e9dad6e6334a04d3a75225fb5cdda59312ed45e26192f9fa7ead5c6c4d8ea313176c396ac85f16aad75547541ef635c47db18944555192fb7d0ce18eb28945d81c2d81973b7d45bb74ea1751868aba3a0c9a79f34db2bacbaeca7bee96ed22f553b8d4828477f387aefbd57b10c0de17a25ab57aa922bb2ae28dbe0cbd3093b393f1bde1856b1542c15cb51d2105ffe00cfad21a67c57dfa6c31951d15174831f7b384c8b5f99b6d91f1a82ca50a80c5bca1cd3804cce59965d8e658e05bd47399107726e42619e619751f4ccbf3354b6c2cc4e1996a132cf9c76e6a7ec5ecf2ba6c5cdb82ebddb94373ea4a9e5cde7f3ca9c13daa1215cafcc39e774589526ca51d651be65339bd89c73ca786731307ef218cd5e94cc29c326160c52283cf9de7bb41f103f0f3d85f0baaeeb3964d375410883de76f92585a8f20a786e0981e4a487cb8991105baeabc617f6429d321fa036a15e8682586318867577a350a84679ff48bda933acdebb0d615a3078fde0c94f6ccbd5187d9709dbb2657e22b2afa73ba2e997a3ee66ef96ea9ed6678c5f77b397c7d8bf629cba8cc66d735d1ea3c168b2a7464f1976b7367a5a0d2f6cbd3f523f7dfb917aa6ab8d1ca605d382697972eaa94443de9edb7e8c3aa714887f832fe49b7b1e04d22fa08b10474170f9fa321a849537c0732b882719cf66837627395d0d09c3eee68a1e528c37a56eb1b7308e5dcc63346e1b98bb9deeac7eba9b2bba346c1b02aad7e445d815fd5d20e7d365c5022192ed5902007427f5915236638c40588d5176ec3e2263ac11f31afdc8f6c9e78c7da48f3a27cef8a4b776720680d78acd69341bd3802ca3e6c4bc8d1c8e76ac91c0789c306e8f381cd323aa1bb3307df4115a6b61dcc278b4f1aa6cdf6dc7b3c18a9189de4611c3fa6866d353f019e735f3d99c69472ae6ce5a3be92b8c8581b12e3acd7cda4f2e3587d2eaa98f6018969218bf53c13de5a9674385cb7a36d037c7cf46eaf2b381329c4db9cbb33ee2666457e5d7d426b6633a8c7da48f1ca9b58ffa88924ccf1401131d12ce089a9aceeeeea90165b57b4ed995a3518dcee8a50b75edda0d5fcef639dbc18f77fb8135ea94f9a03ce36e6e7759d450ce305e6bcdb22c4b126d8cb5baa39ad90b546366a3118c7337fb8161edf1ea083818de77a73c8bf18cd3b097e855920f76734fbe8f784283599c037abb067012cc4cfc14d54f01fe39d073033cdf9c096a7e23c1b3b4703f06f8779940da6d80b75183592c166b26c8e9d9237476091d8ef7fcf4f1b946dbf8b0ba5827b7b0343737ac1bea5c8d5512b6d53b521f168f398599d79252f4efb925a5c8db991458c7cb9392e4b5a434814a9e5b528e78ee95eac73d91863b54eee7ee2beabd0a1fab098e19a705fa76a894759e7befdab987f5db01067d36763c9b764aad4da5dc5755d816289714541c503e3b0b0e07ec611d77736300033c5319947d3ae757238467c72ec6c1020b0e07bb661cc6a1c3cdd831b5c082c331019ed1befa2e5bae44f1fdeebac0384eb03bac03ef89711c8e773137a37d5e15d68771da29d63737353534345a0ce1db7d5887bf6511165487a2ac43db7da87ee283ce419fc82fa8b1a1a5716aae4eece686860683fe9c5e48efabd141372534411ecedd499f3b87b20e75de3c543f973b771768fae518d59e3feaef6ecf29ed95733c2ea7ee8371d683e5f3f971a946bf71dfff34f7f5619075e24daffa86d539daa6bd8a94d412df4f28f9e8ee5dd6e33eb2be57af8a754fa1e4111dde4df5231dbad4d8b9a4d3475e967cbf06427ececf356e6e6868ea66bfb8d1e585b6690c9b99a1a1a9a9a9f135301616964974e7309ca3681513bd7d2605c67141df56786865f45c30de16daa65d473317166699f929e9673242e8da6736cc32c97ca3364ebe6118b551678e5e69346df35ceac5e9be031d6fb0c2b858ca73152b4f87b6a385b6791eb517a0b6810ef4a672ce9f03eb951776a3dfeea2770f98f168973d3eedf002fdd0cf9e2668c52720eab9e58416614427b2fcf5dc72620a2d4a4a92a770a249133e605da184e9597164892278b0420826ba5042b970e208ea44d26359d16ac2054d20f942590aed2281309e8041161cc0f0c1922450b185143468000695294e3041110db660c208efb9c5849518b4a21cd11ac2132c2ae48c503071838c091f34db18c8c4345154831622e0400834a05a30b102c8c40e93091c30cb50c0bc3c9692058c9767194bc60241d21721c2e0a18b264b6e8828515e5e2f5b515a2fb31d29254b0a26a06022c9f4046b8a2a0f4b15568bab38426b0a15620821094528972c5a439082c310969001b30e2fe1e555786e05e1e82baa3e8cd584554d1ffa7937f73ca6d34aa97f80fae5ecdce5aa9ea63efc575ff37e603a7598f14c37aff5898cc38c23bda544510b085e9e7f7a049ab7330c639cb80d4d37c673e76c446af88c47134dca38f2aa644fbfea753467f1f6bcdf66524397933160b1584eb0b2b8801090048106ac160f598ea0c28b227470240c2c84a0e4634b08358061456929a1e4b1e7961249b8c896deb225ab89272c3ba462a1b3c46620847eb10e75e819eba4ea9402f876202e806f17c0b74300487acbabe2f1806f7fc0b7f318ef3360b186d044600de10ac38ede5f5028b00dff869a40125dd8861f5218042be339e3e18177cef0b595f18e88255c77bb873977d9152c203ca2a4f7d8a912a42b082d25d439eccf3d7eddcc19df1f33b08e0b8ce3fcddb8c162ad56eea99465e560553fd706eff09667a5c884aeac1658d84aea81d5c446e7dfbc267ef419176b780121843df08a73269024035ebd26fad2e5b9f5832b9fc473eb0749da9dfbc23aeecbb3fb892eb08e73e1a56a562cc8ee188cdace353f28f27223e3c1584158fecd39b10eddf9cc53411dbdb2c2495b2055543b2b08eb9eb5c46e944b2f412fbdfac221b92a3a58d60c2cf59ec238ce5930b05b2f29bd235272de4abda5b9b81ace88719ceb68d60bec466974b7fa25586c05d6c0318ced9c3879f7e4194a94efdd19158cdf77834fc34a62b7d5dfb0a08ecee91cd593d25b7af7c41b83956725bee2e21534b29c58e933c61863355d945e946237b0584258e8b1abbbc93337b594f2bdf7e6c44cfe4cf5eacc744d3925c558b0086531b1b19d95643b27730ce5186ae8b38c526a4fa813e653ab0e9b7113add8c649d7a374c6388d312f866504ebd4f105dddd43356abc722f1900a1c3f75846ac7d6e2519fdebe78818c73e265c91c262629d6584657fd199c5d7a5c418a31c621db3dd3dfb3a0c73acdb08e6d1e4f2849a8e9a7eba54e8313799b40d6658a60d3d56a5b774a963c6da3108483841220927cfad247a7898440e53648c43a6f3b371f4d918e276e8a4fd3c7af4785946ecf386168acafdde7befb9ee14cb06421d85fa08f6092490683b6357bde2b8810ec8d0edeaeb7ec1b133b9ac2fbd4cd774e1e63429bf61d570edd15be81c55eb884b5d743065073bfd390b0893c9e43b5ae89c1adda4b1cae4d4647293c9ab5f15c61c2689ed60e705027fb33645b3ba91fc91956aa870e907db5e6b8e1bd7f5c21249508e383969d2031286e4c848513644c88f193ab081176290c242b2db0d5575b657f0aa60df9ff8427af5ee7b3046879452eef2ed593bd650a65c268c9a62a41efd01c518238dafbaf0ea2643ea3355bc2e44aacd44d3b52a558c4f48af5e0cecc653a2bbf06cdc804078e255457a553106178a58940bd0dbb15c60a748b690cea47c8a6d52a12f21e1e49d14cfad1d5491e145872f6a2cf4ca29714dac3b2377044324242446031b98261676fc48fd7348e89081dd5827d8ab273dc27e8fafc0588d87d5abf6877a44bc9550bff3cede953a9e8d0c29d5bb271b9c694b2e435dab1a2a7ae90c878c5ef670af9243462fe361f5609feb00c2339d075ed5bba798f16051857220f64b88bfbc74ef04871e3e23f4b2d02b365dde7787e9ba2cb078b01ba5efa99eeaf9bcf227fe73eed142afd8553f38ec2f09068a7ab9a5eb727e39a1bedbe53fdc74d7c5d5b9eb72ce5dbe5155cd9c5d7557df4d06f64bc5f727bef38bdd694234560cec7683fd07f6f38673376e08e9d5e599b6b197bfbc52beaa5aab576c8a941a4cb05b8de8ce8abbb2c571715d3aa73ae611bb5b1b7db6a35731fa8dac3e0cc31c5e8e616e673aa7cece4e284ae3301efda6734e6e3d7a7487d26ee4c83416b41d5a0b33bd8a34ac2236bb3cd3aa9fb2edc64716b0a9e3ba91a373a8c74b734b58120b88d66870cfeac10afd46dd9f8d5751dfe0537704945e459fd185f524f72449896ba223ca3c9d1cf6c9273d9d4ed529c738dde4d167dc344d1505331ecc5a6baf0ac681ac4f87b13eddae60dce4432ff4274b515ae69c9d86fe9455a7af5e93269d26cd79a7c8287640a484a250633db1d219ca4de8e5ddd87fa4dea9a47314529bf62aca88823835d5ece9f1a553d5bc3f5e1e3e4b7937197e93fe23d5ce3ee34b17d2ab087df0fa51a4c7d2c13e67cdc05225979399849d9192f4d68aba28c360eac9e77ca1fce2d831330f8c3117be868e5f3ca97efaa3c3df489084a2014d3282e439c9062e493620f14a509e5b59ac6471f2b136811f0b929d1a75a83133c768f267baefe6d97dafa4ab22fb5312a5e6064dcfd088511f9347f50df35eb5a5339b4379b949d6ae41ee65673eb00ba566aa9555303ae6f1084a1ef32d424d08fecb7a609a0a8b4097531fd7954ea7bc3b1e3afecd23e4cc87cd9584ca5db9a61ae1c973ab0a295520cd2b50ae20a1516294da48a0a76dbe7f561f3bfaeae35df9a0d249275d318e36bd4ee72a4a7df5d3e15dad9a4c9728e734944ca7d1c43ad6b91cbac92f2d08f5d7ed21dd69419c5be7a58a5705d1d2f3d32b465e00cf2d236c7121f7986f73464de526c5347855c7a24f6cce395d4e6cd23ae1bb5e10f83eafca5d7737eaaa9fd54fa7dadb543fabffc2026decf4fecce77cb35ad150628350fca41394a624d5e78e679cb3ab9c5707dd95d593a33e087cea42f063ca4493aaaec7f9dc867eea00619cecaa82dc6fb087e906b9aa78f9457d3349870c21ecb9facb4df0a23ade948e7db6a008448faa379dc32ae8cf55eead6ee6049aee683b5fa04dd270553fab0be4bcefcd3b41f5e17f4b7fa504811f848a0e7d73734eaa92ae921e574ffd5a3dbdcef99cda5df5ca65cf0a12aff3dcb24264842a4648fa9b1b20ce99719e6fcfa3bfb85af58a37e9d16b843484b0eed9fd455fbd2aded5c31b2318e53369e5ac553cd89dfbf0952677f70d3dcc7c44e71b24f3d1ee6e90c7f4f2980e7d5e2009f4ba8b607e4de9346060653ba5cc99ab4cd59dc66ebab0497fa473865593cfcd6d2c542c7d75da23e4de390d18d8e61ed5a50a029f3d08f57c1d73a76d41ae07bd41dccb7c40e7db9aeaf2e9f05dd5757f567fe9bde99563b6ddaaec80589a820aa26f7f416ec9f973ae21c63aad138b487ae840cfe10b42bdbc9bd3dcf773d841dcf7a5d1391bd497c5932c90b6e84078d8a7a1fdf27979cf2dba90bbfcf975812e22cfda76f9d6d267952b1fdd1dfd733805118a3e9f4b1504bef320d4bb5b1d663ea4cf1bc4fd75b7e7d0df0de29eeff63c62a8a7c19f8f772f8f19cff30883b820eedf4d7f2ee45e02b50bb9a0200787a85c037d2a2d814ea5587aeab252ec3dd63fd6d3df582bd028c20639960d7e39febd25febd57e5e6af8c47469eee033af5b8412c36bc4e331e68f3ee0249a7d0695010f7f36e1dc47d74a07885dcc30b63132a774e90a31184dda09362cab7c320eedfa5d7020e2d952e4c134bbc02359f5b518441e54b154b10438927b66802094a0883ca0fa83091429778439c337ec9c10536c021090facc0c1135cf06060a292826bc9f342a5064ac5045da02065db04a52d680bd5c47442521338a844bc5613538b887782a2b2c064744d305a44b155821963442c81a371248a214c3844d124d2c0013bc1952850294252d1817ca1091cb8d0011268608316ec48da84975498bca43284b4cfad28aeb4a62cb5a614d140419c1206508890a0a50ad1168e424b06b2b5e4d1286a45b1c3c7e756144c6441c3043472c8a1832e96ae2822092642d02f2ec04b0401081dd8c0881e6831861731d0b881c60d3528c649614e8f1418dab1c0d08ea351c43e2ff21d080309f86530b0d3ab0a7243e20ebd444c3b942774aabe3d45430441e01dd7f882ccce906b872f730ef668dae19dd4438f9abf38e30c2a0d2226ecef3d9fee8eceaeef074c8e093bc347a4e711f1961de9ecd2731431edf02532ed48cf410222a61d79894c3bd2397fcff9134208111111116b4ca6576d73346ab040ecfcc3eeef3c887321444497c9f49d197dca77de5caa739f26226afb42f6c7608d6183d067f913f4c69037e88d21ed3b0fd24444cfcf43e6e2fbc341197368e29a3caa56ce7cd8317c3cecad6d447ae0079e3b9fc1f4ef7ec0f47c5d03fd30bdbb1f306dd7733ce83b7f4054764b8e9052c5eee3887ee8ebf640ececaeaaef0fd3b7cadd1eface8304cd77ee889e61673c64f8fe30b94be7a652a9e67ec997eccb677ef94c9794f2f0dd86743411a23cb7887004118c3ef5a2e678c2bca41947188cd22e16e88a99c38cc7e5993fc7dc72848117a38f067a79aba9dcf47ad280e80de2de3d7e0e9e9c71a0a3247dea0f4518cf2d289ef0530b9240cee596f9561de87220ec98cbab6a4c0bc2dcf954fae95572795784375755b657f06a5a080610e47a5809f88bf5cc381bb788f0c54fa1003cbd29e9d5b1ce36fd4d7ff33ac6a1ce7aa96dfdf4b974fa5c4a8df5d24d6fabd5a77651c66116bbc92f4dd5f3a8781bcf198f947703f24bb7eb37f609441427cfe911ef8afc83c2cabb224f5ddbdcbb9e04fcf377753493a21b9e3bf282c4911a76a8b6cddfd8a94f0d883ab5e1a9f497fdb822ff1cf607b9ff7135fcbb5b739fe665e9eeb7fe5a44e586d2b7985edddcd4d4d0cc0839e860d63dd7670b0b2f13797fb44dcbd0850b928c32c545d85f5fc7148dd7ac6454331a1315bc35979201801434198d4991efa870abec1818548655135d4105df6eccd38533291aaf59ddb06adcc8d1368f8719277aabe0af7d827d1ea3cd70afec45655a8df67c058d9f8d0a5a149b8585ae1db69417004d6d601d19bfd9678c5a4abf58e72789b9195158daabd7a39f16e81e7410fa36a7f4aa610a6a356ee4c01e17167a8d5e65f7a1d7681b3fdaa61dc3666668686a6a64807e4306be5b06ef8f5ef5095e26468670ce2e39c71041ecbb1b34c78802d1439d20f4211c220e01dd183b43d894af66601cbaf22fac67d34ea9b53fd88b6f0fe219edac87648ad1b7912f98bb33b40ccfa1b3c0f800e3f48c2e2c16847e52c3ded01aac668cc3b719cf06781e80a35006dba02896e11ce9ec881eea845df4ce9add953b8d8933d239d0953ce9a10912236df37c73475fe3630d66da303b933dd394f578377b6d8e9528cfe669f6ab56bd5ea0be2fc41077f4ea59495123179143e2a2bce749513ef5ac1267a457cf0888907d14ccd89c0effa0609958dfd899807314ad72b0ac733abdd381715cff5c05ffdc1d391cedcf3757f40e05ff1cb6bdee4bdbbc775e94609ff7601c41a80fd609926ac177740e7f773fc1ba90ef758c0fc618639c8cd353d2e0a02bc1c310a45e8871dae7f7641d8e3570d4394727947452eadbfcb7848594524a21f5e997976a37ab24ac20dfbc4789c074ca39676668686a6a6e6ea4bb7f34328e203448ea7b76774369e49dc683bd101111fd26641b4264c3bb8cc78b02d16f448a107dd010d1d7f0cf9971a6f4ab8a753a1e0d43440f31ca3ad70f95e0215116811bcc08d525f10009e672f876ac7344e0a6d01aaf734c36cc67671bd13714f44dc6db6a16c036ed323c1bf1062af062082fb2f000073e1801c798f30a82d238da01084964f9a2872876e0620a2eaaf8186394589ed8e006258200e34a0b7a8a844cc3c9154bbae841912ca25425f10757781104175d40e1810b1804262439bd2e7c403929e495514a29a594f1524a29a7904ba28c31c618638c312a200bd2143824f9a1c8869dc8828f31c698821d24490104125e7085879d88e4638c53a6d0c373920221972065289670905c04d14a381c283881d28322508650836b055c3cf125f052c1125d3229a46ce7a4434829a59452be270cfb09c94209484a40c5073fa002b96042146c490d4be9a46059e2030a7ec842c90ae00d98500506886631b208c1845296294d205d2958020c66249c730e197971421282580297221cd999473fc5f8e9347342e841380714a1d583122c960811c68502a47e02051d4ec0e58b134a5ec4600212d8bb8e70a1c5bc7410860e3ca082094ce8200ce8840b889631c618638c3e43a90f766084092b56e0c4071dba8831b9307201c19d20a907151479d1654b13700829158878197181022aa7fbb1431849b088228b0c50709d400946d95bc20d4eeecac1cb5ce2be18239b37ce39e79c73ce39e79c473fe79c7342cb54889448a2c484872c4a98400948af077372204a148460e2e4053960e22ad2a15b4ae0614ed8c48b49e2c3020b0f5ebca088154780c14ebc70f8b804167cec12c65b82004abe780214528c5064041cc2124e10598a2594402e60060fd832258b1bccc0052f58c27503174ee0027c983405c5ca1caad52df591239471da82be75a478e619fd6a6413aa8addb9ea67e69f6b36bb0d4980dff10d3f86c282ca3595461276e3281bab039db341cc7994e8402664557951ad07cf803e351f8c03634dafa0af9e0d179e0df4db02e3d058c2f2cbf00352cc5757097849f6435261787ef9e5a8633914db11515f0482dde89692f9e83431d6f42afa665987756aa2437a3d9895d150efe31e225919cfbd86728ff6545025ccab780626d52bea97cc5fcf1c4ff79d648c33bd8ad137cbce631ed32c8ca98961d42c9c60a1e4ab6b86723a3b16dfe560f603e36de87a50b9878ce00844434c3ee4f9f421d28710c9b1139d08cdd10e11ae9174131e15f088e8789050d8a95e2766d286f0959daa0d79c04ef57a61266dc80076aa571366d206b0c5171467d88989f3a90d79410721ec0cb99c04d48710692e76a617350c75c7dd21433bedb56a2a0af04e11deb2e35ce5429177b4e39c6627008ee6d288ded1ce743aef90a11de79cbd802262c73991e87a4b8d2ef32a1e5dd965bed9a32683dcfbb8375d6ed2a46f431118faeb3abe618fd765bee107e98534c8d1e03e48c697e969a8a9e28d13f6933cde1495552f38972e03838bcf190c923ef3b3611c1a4ad84dc6a7bee10ade9a5ea99ea75ec6cb609d777b64a45e06ebf0f7fba1665ebd66dac92bd38862b9a58595dfb0afce2d2e5f3cff49e64f5ab55a1376c62f9fd647e6ed8549c5d0ab6c870a523873a15799cfaaba8cb6811a60d818156e0c315703bdaa6eb5d3af9e8d15bcba651debd5bd7360bc7a4de7a4bc3aab7332af9eaa0ea339a25e555f417345cfa6b258abd5e68fa1300c25c3b7f900c06438009c8fac3603e354a751c55287bd3a798d984f0a2e5d8606c4d53c0034200ed3b69a4f41db84de8cb699dc871fcb7a367f94fb43b98ce642af4e1ea36d5ce54f3231f48a3a4fb1306e7b95b973594ff7c052d8ab8cf62af31bbd3addcc73f48a3a74186d73184d3de2e9b31fd8cd52f8a45893f3603374cec9ab0b750e0a8579a6c9e7ec745fe623d4abea427a554fd7097bf9c64b5f6778367408c9d86b0cbda28e754e4dbd406e0aaaaf2795bb95051251509723a17ba70571969fcd0d61b76b08e1eb796daa5791610a2f7da3691bf6d93c775a0dc6790c609b4763807f29fcc672168b06115838d06763731f6160ec13f6e49e550135a71185c5b1390c32764c37ba78a55348af9b1830f990a19d5a4d9a6a06d50cefe8dd6592790076687602b0c38f6647003b4930d2c2cbd776335376aabf8c02bc63030282d8a9f706ccdd8e491bc04ea60da94e84b7ec989c3318b01dcc5f10da1942c30e36d9198854c14063a7dee77c664766c73de71cfcaa0db99c8869c7a40d994ec4b4f3aefb1887deee213f82d113ddb1ece9a54e9999d5c538cf694c616f40937b93f35fd5b9faf55ed5dc158b715efbabd1abe7a9f784cb7c4a9528525239dec60dbd3618e8367a667a05fdd910f284b5da3c25c32d097936dc176d03ddb5d8063a84f56e2bd3dddc684b1979f885bd3c4cc9b0e2a1c7223cf4e79e3c945ead2015fbac67416f2847c022acfbe1616ae9d950eaa2ce39ea248d44a10962ad84a708cbfacd9a2e3aa58f150d7353180742b7ec60b85734bd7aae65f91d5227998830c73a0c59a7bd572fbe08b5d47bbed9c785cb96e756165e7eb35948f98a8a1e35550f3b7bbbccbbec879df966b0f92de3c019281646d50426a0c592cc671f359987466a7b6b33af0afa19db2bd3d7e740a4f3043920337bee32d7effe5d3d09b0771b7adb3e9b7f769971aa8ac70a26375dc7a3e3c168db73eb98565b53fd54a0ccabff5caffdb2ce998f2bbbfc00ef9867aea39fc60f0b2448e8f240975787994f021e663eaaf7dd68e849408fcb6ba31c080f75eb5705621d26e3c96c90731608ca79a8c7ec07029fddcd61ed7e520c529b796730bba8be8044a0ffe49cfd3831fe721807c2d39ed5ed6514460302e33ced10801d258c590f083c0c6d1f0e8ba1251fe4b23c7548b354e0e9c5fc3db7aa1f7f529068cc2701ef18077bfe7c0ef0df627ce5a90186bddce458f5761e331fd79aab48b8f2dc4282932d4dbe5e58f304654e0366f2b7b55f5e5dc7ebcd8388fce5970bb9affe7afc2f9e93b3d363413d416e8c9ef75f1fa4347e538c03bd351518073a8d2058fed54de7dce815643d8b71e04625e3b09d396d519fcb7cad3e323c93ba1cba9bf9777d60a94fec3e1d8eac057196da5562efb937e77b734ef80870da888cf1d8b58cc3506cf7b0db51af66418ed1071f2885bd6a1fd6cf40b11d539642b18cf490f20e2a77dd1283ecb9b525055b8c54c0ad2bbeb4ae4042c38854eb8a1bbe9f5b5718c9010e206ba992a587e72c46cf4b3cbbfce2a13b2d5bea0555f06a9cb13b6d3a6b3fee1d730fe7ec33eb31ef830f9d7b9cd139a772d2b932eb4c9fd37b6c43aa79f31c8fbc2a77552ae7b247e5a6bb79f69ba731cb7c387f310ad7e5eebadc4514d74c715538894e79cdcb65c6c349bf544e4aaf9c77f6f3e87549bd724e9d508f494b7c941f931e464881a2531ef142534f77bf944da4d3244d963c8f513e3a75129dfa7369c5112f7dca3837232313735d7509299df30090f5b8a48f77c3e85348ddc5c04887b1190faaaa4e9dbfde9efee8ae5fc78b58aa869563c70b1be89c1662e4a887269d034546ccb026d845531803518fec12cb7e5ccb0a2bff3c46cf7850ca6306a7d3a854ce548541eb14d100000008004314000028100a07c462b168402468b1ba3d14800b9ba84c724e1767518cc328648c31060042080102004400046668aa00c6255612461a7dc0acbe7c44027a4be74a4819804f658b63dc64f4376e5d1ddd68e405d132a732980a0493a6d2affc3f714254a5a4d0d34476d94b1ffbc7145345ea428f282b2e293d76f7530c545636e54f596ede60e6d45fd2cef45a8ff12a0f15a8e158996ee29c251a0986dffa313bad8a7cceffeb06d87ffde495ddaa5354b02a0d00d7058b228b6f81c90329c55945383111af13fadde1f81d7df60db2ff7c62e79292937560fde55c6ccc1a3be65d5992b24c5ca57c60590db3926222931e974fdec8dc065a59c66826ac7737bd7041161209c5eea261f547b9dbba66f4723741788a0103385bab344e3f10d1e58e35e7a7c835ac6b521527d54ad49466d3230109184b537e4a71fbad60270654dadef8a1b2f407288e40f7925deab1c172fd1efcf450d4218272d7cc436818c6d8c5fba384c058812cfde2dd2217719549df7b4395130c1edc64d1d3f4d1d99313cba15d4e600047924a8c742592ed7fa888319b69f3addee99b6157965036c94afd2977ab22aa949cb3b6831b319aafd8b734afdc0756da3da2728faf850f0f0d3c1d512c80200bb44d2ae0373db76f220158cca760e05c43495791c4d30e8d78739af1c614554652c4e25872888c0da5b37f5bcbdc30aabdb825403b7be3ad2de6a0c95fd50a93f2872c6e18b5602f51136ee95125265dc995f640f4275e1b199305e256d91b219019eed0be770633bad2dff19ae5b6c68086135a40614975a5445018ba34b175f7ff5fc15b1dd291c1c48a4b4a1f6f95534723a36cf54ede74bcf51276f462332fc5a2ac76dec45a350c67d21aa05deb0d95b592b367926537010f54e9407d2be803394cefc86685a19600557aedd201ea4d7d5c215c09fd2ed79739deb663b3246cb19a7561aa8eac2171f7dc7b02736ef127d43e89ef014f8c865dcc16489e55b7151ed7de5c878c29a1f2d781f407aa27b219ab243ffe4ba530b292e6d3c535023119574a16573b31df3eae897429d4aeabef95460d9d68c8fcef1e5e6a78899c26b497389c2e3d5a20d694efb073ab18ee7198a4410485a37cb2b46ae78dc48e57734f38f18d0be53a6c6a95b21ff236b093853809d55507d247090a4c5432a3d904445744ea391730f56d0ca18158243c2106f4ec0638adca0b528cba0b96ba82270cbd350bb96972225c2eaa381d3510c544a1f1e54a5fd77c38e460bfc05508b2c035223cb9493df8558e3a6841c968c075d44961780093c72f5e791964edcfebfba6ce6ca768b5850947688d966ecd8dfa96554d401f7a269c6763f4c2e1c774b4dfaf197d48a4bcf1bae6404b4924e76298e5e7e8aab5c3ae8945d9ed82392e4e7ea7f39d1593ea2733b99e32eb999a1e293a45072c7ae2f710aca922a0021f82a50ee577f94d0834698ebdfed13a9180fca2a8f8a618f52c7171d9722f5e33eacaef83303c087e675b066fe00aeba36785ea913e42a40c203e80bae6261aa58f6e7468ec36b126c0ed0f8907afa7f596f40db5b2aa1db5b83ba53a1084914e3ed2d1803d6747c6193495e2afcf4b439bfd0752d492bc821638b96f7cc529adbd4186da01511a2ec18d6a3fbd47ceb56fdeca7721eda59c805da5a617fe29ca682046da2999545ad961192f7ff6710214a5218a7ea7c6a61b4a09e0fd0c5f4fb8061f5d67ca91995820250101afff82703304991246b19488e650437c317fdc360c25d2fca4c6015dcacc827d8c2700146314f7a39b9617c9b68159f057fc61bb89fb601780fa0dbc283050068c48e2d1c89d6f0bc4d8b56c905f85e8480fccc651c300e9990d648997eca7fd6113913c57be224855845728ae9b0ad10e4eaae3af52e2c074f5e4d22043200e902d6900738363564797b5531497771a81e71725e7f1082bb2be0bcb9a461026d06862c8e0e26e32132fb570f08d0b49c04ef7760ae1297034837bdc9f6984e65983b1eba4ca61f6b4a2c656359b92d838de20d2a0cd1feffcba50157903bbcd3d967b3c0393100b21fcfb6288c2385146078724962be732d2a115d7491bc487fb76497c6fc4992b240bba2469cf0cee004a29db1504afb655024a1f25f8dda9e582d5ac16e17deb01f3239d4dd595482cc3e0bcaba37cb2438c2bf5f688fea76aa6a810a5c6819794c16d4501fc3cc6aa58915f3624919ea0ef63be1fb8baf1c8ac1aaa57d27efc1de80fbe5f90b5681aa84235590bc8e87db57d99ef358f528c56e213ef556d91de37edf1b05cfdb5411422f7f8d45751f8746d0bc23ebee6c5fd63d7d1c04749676bb68619c177d8420d8e07dc57b033ecd27df91b90bec47efc7d1c0cf8cf8430eeed5c71990a857b538199111eea2d4fbce7c99df447fd82cb3cc9b79c26fec4b1ac67c30a39fb3c0fa1e0d39cefda08c2bede4a6e91bd2fabd6190f90224f677c71d955f173d3ef7e0921757b20475ffae529c8ae18c395fc8d3aba92654fa00e7d3c23ecd012de398243cf4228d8b2b0e182377741d4b45ec71760e4d7bde61fe02525ac380e83ba07b6be54aa94fc76e466d19c425b9eddaf94a50d0ba185ad2a42822ef0c3ca84cd9e34b8396cee8928479b32380ade642b99b508049c79cc7e4e957a8e5013995700fcbe83bd99d2113790b427cbff1b002d253dad7c073ef6764efd1eb4a9e9a09bdb776928aaaee170dfa2e507ed083d011868b720739cccc52eedd91dc11ca80144f364a775fcba7ba966b9d047da2be7a788a38225ff190356f7aa16d8d1f24b1c8c3b74c89db4da0af1e8e34eb5819808fdc8579169ec420cfdb610c62dd8246d0c7be8336a7321b35e9df85e18c6bdfd302b2505a7fd9b003a235773cb50f73c716f88e32920bc7c1569cfa5c564dbfe9a2e6451a0ae7aacdf7b218150995602d20c84537d381c38be2a0783d1727ee57f1e6e6897e3bc2a717f1966961a826827eac675c80a218cc2ca412b08cdedcbfd6e55f86bf06d738a0c7d84c47e0d3af1e9a1fcb7f1cf2bedffd05df6d02a578af5959a5ebdb9f9b66ef218992ea3a66e6eda59cd62e2ae490714122ff15c440528923ff1f3768fa769e8d2cc963414bd7420091cd5324427f95e579d1208f52e8fb30e7a5b6e8a0c4161b9f157851e465670d933af57a1630b296656293bd40997edf7e55fca53044ac5c360977fe797aa110ff254af609d24dd62b98babc8932aff151820e384aa389485aa13a25828a1c21fe87cfdd1c1a58a838a0d3831e61bda606b232d668baebf66e3371080a19901f38642dbf18a5809fc8cd50406ea7eedb17832b99e5df0b92a370d0d3ee4b7a9f6e465e171fc632d34f3fac3c7bc5e034e64301471f8230f7dc8fed1d02739a12cb86991cc9d912a77ecf8dba50dbf90cd2d783ca06775da4cbf0b09160198580aefa677df4908a7ac084f5629945f219f596d0f9e9731001a9eb59ea65428d19b69e4a51d57991ba0e28831bdc6914d9066b0d2b2008c0ed26b52977369b77ccc3610a3888996c5559d415703b9ef3ba718cc920535f56ca336759dda5a911f3788cf702d6d0dfd6bc0ca283e51ecfb7e276cf1397823f6df4a4b3352c7e2060104a7efa28bbe2c1ed1ff6fa48b26b3d7743bec4860213d5812dfefab456226508c91d9a82599f39c693e897f8e5f1c03134b9717ce4f61d9b907657eb2011121b6fa2dc92ea404e47d623d7cc2bf0677a5c10799bae48757b41983799bb8321582d16dfd2741d0e4466e0d8b7d26fa9c8bdefb481405c84cb1bac3ecba886e78e5abb183db7f616adf3300086adf0cb3be1ca314c9e19e43f9557063111fe42cfad2e195457109cd0a380fd954824728445b8a108dcc5349ffa1bf6753698303ee90cf8dc735ee8bf6e6f0eaa9ae40c4a7da8b1b1031f2b2421bd934603749a705765a16878b4201d355ec9ff854af51fedb0f2b574b0f3b624c13adfbcd62bc43637b9de45ae49c2a460f32902d4005b476260dc7b66d8980e5c5279a9cc67cb174915f663fe1ebde50fc3ec47ee4de87a600a6637edaafc7a541db05716d7d9a11cfa8a09251b0309686785e4bd42887070ba13d6f907c324f1f3344f656cd8bed3bf57f16e9548acb6e05a7c5c7ad09d51295ab27d9dd983286466db9ccd0d0f3b0325329c4feebf85523ace3b30a8a21508a866656cba77d1ae32221ba703fcea524b978fd06054add51900b3d663a7606a0575f00743d3ffae14614f1593b9ec0273f43ca0448aaa60251f00b76abfc54268d77fe4cf72924bbe62d5285039c8e572a4b2b4b344e94064afaf179a64caca2eead42c57d711c742a33e00309c9f67cdfabe81e71d37b7782e2bfe89c064409d04567a447dc033e0e0726528cd9ca51aeb65ca9d80ac1d08d2ac0b8ad35eaaa8e2c14191682c9c950c1f1ef4e04e6a0ea5c8641f998f8da6f1babfbf9e3da6e90f9a548c86b038a7a8c3f3f6387d8d1a82baa3fe11c2c1f10c14d66e260f27640cd50448e109983d5f96817345670f097cb60f3721049a83841d6fe491750e6ea7d70f69642b3389b0f662eefbb41f83edca3926033eccb0c18a8376e3aaa13b13cd5979013e73e7f7ec4c2e977247d562656ce3c1d2c2aa4cd7d00c43486b2a27389a7c12908d2da672044cac4b73c610840bb2487dddc56d10446df0e8fd7b80f08ec798bd1d9a90daa9e1fafa396b24ffa47b7dc7418f3084c14eafda0bd9e4016be5a7966da536f97649aacc7c1e9273e019111a70da1637449522b6c4de9c4122a3251d397f36f12adce14deab02f484aa1668449316c9b4f681835ebc64381834d18515a449de3d39a199c965092b8293c30c38dfc36c33a2e193f8088e1f900f00ce797ceda90824c195241573d6e61704d384261de05c1a53144ee017d70f00315e31d774c08018009a9b4012cca0078c8a6bc0ca0f904a9ba6187bf52926b5adafd459ac9acf91b99e6500ce5b89f4f2a19f844ac8219523f196c0aaf3dda2fef62bdd6a89147676081507655c48398dcb476b5e43bd87116a627df0eec2e746b81507b7e5beae7e6888f3558dc55ebb5e217c2226edaf518d1be19d9b71bc90896a363a4285ca551524b649d07091e2b1a6d3cdb0c80db80519d3165bf7b10debb1307d3fc4e14213036c92d24b2b4bf0e3b9de5d388c811b2169d81943edbdea2a5d0b64d907e50d9c9aeda5ef52065b5a94c322589a3703a0c99b45811e5bb796a48c195e7dccadf401d18bb4c3d08f8058d0e891ae3ba06be86274ec62e9f4a9fdfaf0890b8f261efdb529a1116383501f1a64867c8fa28909c0730ab19b2c5f2a4dc55685d6cd9c17261baefe4200a58f2a2021c8a9101fcf024a57680570980b098c4b75e437cbb0c4abec3c804d0ed1004809bcca761cb684478dba8c69e0fa36f5fd703e7783531b61ba4b3ecc8315b752271e8bcd7dea93cb2c8d2c718d1646b4795012859b19a0507d81a57f9d43f77f3f24cf7944cba12a7eeb34f067373b39ed5b73b8cdfb6907d44bf64c1c0c022a243fba8313eff32d5e05c8c14d5c87233fb9bf079ef774849a129ca2d9e0a0bea94f206cfcd8ce5280187231d6a0bc3e4ff42a0e614f76e204e96d7a826c08536b68aa6555d7f24eb51a40bdc093536a97830e6be4cf765a52d8cbde874310de75789cb900974ddf8dd6f4b88f356d69b1787bbc5f6a9870383c2979ff1af8099a243d6942e38fbea5e86bbf03441ed7c57d5fab5bfd1819e46a1089b5d66214dc68f18e4c63301088bc1755deb593d5eb8cf0155c2b7f114455ec175874d5be0f7c2ea616b6e2f37babb5b17be2daf00518669fcb880550d74741b0d49d733c3d7ad5c3ba3f35a0ed4fb8db2b560b1b38d274c6cecfbae6115c913207d0e8ec121c54b81ab2e8fe78d7b275eedd6894dd1f9f7f9d86fa5c5d3ed5fdcadfdd3f509dbae16748a105ca239cab180424df742e8b1f9f3f4cd7486286d7c1dfef7a1fce814c9540e8ca7c4f0ab8a727f31b3f715fd5b80161f8624e264e33ecdad74c17665b1e10a28a3e3a40e1e443c61b5086a307949c7648996f3046d6174b305537b48d45626dd474606da3b65d2420fca99cc7f06af17e1bb58e11456f1e11ace0ffb9683ab4a79ece997a4d65436fd396ea141ad9124bc5a754aac90f90b346d75285691e908f85368a631f8cc800571372314d17ed71ded552e8b9d82b5c80766fb5656232aca07e29ef13d3e68d4a2f69a1858a9f88d650bf83288c8c916cb5f044b5ea1c18e11775e06d50a59d2df9f090412c92638197d0a84f036b7aec4dcb6c7d97b0475494666c78daa292d6f1396e46810c5fd296d02c5213602818efff2e5194cc8d933c03eed3517079073ad1039f872a892b712ce063f5270f2153fc734c47551988ac829e8a57a3330909d709e1166e772034e37b5f347ebef1b1fed867de0ad42a908af3dc6753abff8d1f025dd39f4341189a12668909b1d39872b0f662911954d07a4aa553655bc3953204718fdb07d54abc0c4491e78041a1e7355217066db5ca029766406ac24d0b516ee71925860da5cadc529df17901959944a35067752907432f0089c80da1498391b8a579cbb5990e885bf209a020c8ff2e38f86c71339dcf342a0e0f415ce5a9438495f33cb169a865d919e415cbb0851cf7562845b9ed553d013c12b7a19d36a85f51358da8c0b2cd86b2c0ccce3561a26453a4808877e4c520a5f684e2f41a13492ed5694f3c999ee1f1a1316470fb81103d990e3c439fabc3ddf5dfd996449b6a39734ac47363cad8f8239fba30831a0504493b5348e9e4b47feb9d0df312adc2b71dc3f32a54c1c98e97afe0bcf83a4f5a529524ca8bcfbb7bd13e12eef2faa3b493e0b2a8116652e68a2bd74ed03e824509dfd991ddd2adf3f7e8a4c471b256dd59b6e4f3a2c0f8ea410a3670d14730dabf6557bafd8689839c2417227822c0ac21ed2412149c0976c703014a04e958383806714b9f222d67baa3282d0002148dc6ee7a0a860252397ada61c098f345748877613a7d1be255ea03b6502b4d0b68a8a5cffe3ceb485fd251c37800eecf65ee298e4bf0a5f4e165d5a0949910fca60e37f582ebe28753afb85884c0a0e514a645dcf2e45f07407525f5102c9e2d49170a25f20b28a626369fcd8a106fb317f8927f797f36b5bb21e1ef0e8676ca93608b3bb240a117244f7f8c0e691a740c5d2b5f9672afb3167adb02efe2ac5c48014d4f9bac241d474694949c86dd2d223cd95f3fd3287c3ddb82d0f988ebb9c544c7437398221a014234add0ffca736612a120134d511981fad484afd69a6d6579c34c30c585de8cd6f86da32db820127a0cfb03f714d026e72dff1a1c806165eabca8378763afe4f7c9edb023a7cb890bf82d442f41c40be3534413d43a843b357f5a5609e93fd90cd15800762c5c6c44da83d180a5f361cee80f4b3dab723647fd2836d75d22b080503091e889287e63197ff3ae890c94186d824c8cbbb3ba12e52eedf230a8a45f74bee22c4ad7c0afa00099a6c007cba5cfb1be0ac0ec0680913dc016bac69624c8838c1ee45f9970b9fd64369f6f54e891bd46418ba0ac4a5fc3519c9dcba492edb01133990f18435af02717a00cacb35da33285be942df6810072d441be04ed40a13f1c96212884e50324015e80fe4f5d7252ecff0a1f17fcdc93e65c447bf997a30cb8b7b082ff17e66a7e106878f6106bcd83484db1d24f47f27fd0f557a29d9ef51125902bc5e97931821985a84b9c8e6b4a51abef13d96df888a649010635e7ff3b1bcceff4c0e806457ae008d1551737d0ed1b7d18a9810080b62366dbeecbbb207d8062fd68a60ac290378a2e38ee578df2fec56a41b3890e563ad941b918390cd340bef8570f90e47a82766b113b097d3f5d32e7ad92485886c5654f70fd6de3e164a740ea8acef9d2bdafcb8e74c19aae11ac5e788829090c45b08b879e9840381b362a54d1f19f73ad6ebcca6538c1155aba8915c96f6651b3a15c6437f241292ed2035946896c72d68d9bea45c1583b2f6af7ac244b0241254730f349fe32cf4df2b11b0b9feab8495febfad6c003737671ecc64fd4f701dbecc6b3b02d402bda6453995a43cd1559d9448d3fc19cc0bc8de12c9d931a31f82bcc480f5281ab8ffad0b7ee9b62b092d5177dce5fdafb27d40445ea79baa12d4e3adccf2d40ccfdf3860bdba866ff554c2b4afbe1755b755932ad3804dfeca885c92bdbb37bb176565dbeaacee4550ebe3f425e0af62c83b220ff5f87371065678372530f0ebdb627433e958b67da81b7fb12b770d75eb292dcf62a0bfe0260bf97bc2c2fdcf61d34172e0c9a673a6ec7641f0e359ca9123cf227b4bbb5ef975bd33e15f6bcbf528167417e0ac3b3ba0640562cd4f1e2cc0b34aac83c5807f487b2bc3310dbd9888f8aee2fbf98737291872fe3dbc086575ae42a1bc16c9647ef7fc9f9decdf53f53565e2599f9c9a375b239ebf467eaa73e9c7f652eb08cfa9c746c247f1c817c917a676495c04399094101fcf84c50c415cf2772a38cfc0d79c8ae89d822ae924acc4692cc0535e5cdf55b444c0a38e394fcc2d313c9983637c0071bb4793659f18394e39329f83df0d6755aeae844b899e8b04631030b84b4c980a7848165f4232335f08400d558f1ae032f718afa9334e4ad8310de388878f89e9eaaca8c71ce093887e06e24021ce27eb7343e327e5f232ee7747ff28b9bf5a85829517491ef2663201b5ca4f6d0393e5c33db19f099c7f95ddd008f86777178282ad7b29cdcf71efd8d5d0ae61715ed2e5efe40df2baf8918ee5127c062673d9baf82228f08241d6c87fd9f791b4cd565846e744f02cb64070898f0f5b1b7f09a8a36ff9eefd52b8290d9cfe375e422858a68944650784f663e0c60357f795190eaaf771beaf774144533b0d380eb3a089f39a38e7bf9692187602ac20f3f24b9de1eabdb3c1833b8a5ac53935c6d701b9e198261314a62739a421c671eabd3c6c2f85205cfd9dabd3faad926ba32d1ca2b0d462ada9ff40eedf4f5090405be35b70a0a6b7d05977206e20f0a4be7a953ffef688b922744aa6f94606e3651afd5ec2b9062220a6b4e54c97e2572383b7f1de0b178dc28e586c0ce60df73aa3926447daded09404189bc9b1e05fde9b2c63f1aa7f24d98dd74b9574ae49a3193e859ba2e764450cc774c470f1dee3c2bc514adc3d2f936e4ea748d2dc2d854a4ddbd14bd508dc04eeacb38cccf9c360854c193acef029163b13305f1a8bb43c5ca37a088a0192896ac0f157a54d66115794d2328e966065098ec2ff631b65ebc1959e7dd8b008968c6fa632f9c9dc05b40dd587867160da337b814b920454edd39cc214effcf3b664202542f9c81458c7adfba2ac6707da1ed449118f4adf34b6a6deba8c6007db77abaf966454dd2785e16002a3bbf27301f926156c60afab3747edafc1e8d4c7dc9355d95a503dc0e4e20018cf1bce2b9abd5cd25ea45b9365afa6dee217a74725b8486859f275740b8dc51b22d8f6fd1fd15f51fb30cab3fe70423ac50c398b8d90617eab94981e9d83b55412837651ad56fdb88ea0d6404cdc3e195545a790fbae7f1f197be26a0dd246f3b51934eecf9092da790247525d7822e15038d1bb63d215f31034b5745128a54ecdd79870b2e9a7542a9128107f40eba2074e601e48a95b3cdfcb8be94e326aca768e960858ab7a532c146bb264922219a9e2388adf560ed0c7ba4640d473802dd9eb43ee1352cc4051b8eb3b481ec80daaa9514426c3e69641707de8af1c2567354571e28d990a68c1a8522d5ee162313b411dd31596fc528db38282d4dc57e5549890fc92a672bbb468498453c16b09adfc1c9f099b33d1d3870269a3ead0ff9dfa3c71a1b0337201ab7be1a53bf2a65f3dedccaca59555790af303d2283eab8e907d8da1d8c1b8f04e0d8ac080f3579c129150de299f3af8972b88e9dbb73ea5e461503047ef26f8c38e523d29eb6d559bca1afd62fc580eda39160ddb51a47c1e677fee6103e3bfebd58aff6e1ff9d3dfd1a4372498098b721a362a6aeb1bfa36c37a6383ef146be2a2bc463ac4011597faabfd94f140f7abacd37b14de497db592e4e4a91c4cd0173621158ce45b5f23f9885a3a4954afe45611851dab5fdaadcf5a484fa60c1604c32da42c257b50b6e9a6fb54090f1cebc92e6a2b1292ce3123749684b8c3066524cdc582c72006f219d09595ab34e7537c9d0afc40cd835bbcee3aa4d0bd061f4e7256e35d4af61b1a2d819f26a398e1e8015b5bd913110455b8bf52195a831929ecac2c6fc2db553b8cd86bea934c9445a2a3341f7ed33e23a575e19ed4140c5366116ee0fa349e6c11a942e08360839bbb8e65e16bdcba9079a9e86571eae22d0098796e7a7976eda55d08d938baa6c64d80982b7bcaa0562d9e221dd5034a0574c291e16eb59266778d32e23c2f46c0d03dd4425950a306fea5809ec11aff58ef80d780039e89c694bb8e5a55961492cdaff847ea4955cd5b4ce20121ee9986b1523a58e063e3383850954f78d125b4818630e7ab9e7a3c8d8eb4513aae00bc85d6e57c7cebae51d96a7fedfa21422c64664559ef6f5417778e2ddf9f8633862fb3e9098c172a3571ff1468b4751c28a2a397769ebe26d3f90ed23f45439bc799c969f6f3fb3759bf0bd524459c2058e2039f4883a940ac4fd1a5d626c7bab6a10044af4e15ea86bcfa81bfbcd365dcab19d8e4758aba2505a0ff71ba776d01ea5da9f2099da7bb8dfa1a0d826631c8da7b77a64620e3ccadf05c796b5c4008774b9de889d741dfad6f5fb28fd720d83ca55ec644b24a55b012e7de263638855770f3b9b050578f8851f11e3f6c9e5097de9630dc9764d7637512dff9eb0e3b119382d39e0300406ffa10bf5db564367a71192bfdbcdf5475fbc0f153ddfe5c10e523f2005b7418b0a3eda560ba5fcb8022576efb3a7c81cefe721d745a87b2695299d43d01b063dfb02242913aa965bfa35988fcf8a35c5d259889be6f363b9b25def62dc7c782e654f2f3691867857a0c683647a8fcdcaeda6762b9a35dbd491eead5b7121a7ef4e1a7d2a678fd8e1fc5e7c4565c932be7e622eb761085385433fc840b81683d4c7c5627a3fa2d990ec7f1a6398711583ef69e5a319cfe719f73f40e5e5298d266e5c40fe21ee2805910daaeba6f03f37d6a4577046e588478beedaf086a93258f1b4eaa157342e46400fefee950be723e82186639e86e1731359b0969ccc70e04d338c6a78332a14985d452dbba682ef7851a1c9df8d40450fd6a3cbe7482511e8358523fc6a9ae71611d865f293ccb1ac46f6ae44df549bfb976dcc61bff4bc8122e9d7d8fe9dcac45a5a7979feb6dcb60cf821b381809ade5db236e1c32194ed6e816fa81e337715b2a5af146e7370cb94af138efce231444c78ceff36e3d7b8f1619c90dd4cf9a0680a7838296fda3cc89224ca29366a7d32faf93f9e6a09ab342f21708399d0f57e18b9df805910413a36f4c09ae4ad5cdbb265a4ed99b4a6f96ce5a3a36d7c2d7362f0a362cc5b89e44c23de15c47a8260ab66e0523702d9e2892aea7376f9501cd30a1d5c41ddcafba7674b164063680c449843a167939038d42b02b3df94e5b758503c1eed8e8fc045c8094ed9a594bf5ce40e1caf40a796d46196903f4ded04cd1715b9d876a110fd674677d1b1eb1ea8d2355b1386b73cd758fc993c680d491b22133c91d0e38df86d3828cb01f09b5fb967399a1be408289780f38d2f9ab76f81989dcf7400cefb2184da73eb2b1a57e897cee4c8c039d5a6c513ef35f02c10a1a2458c74584270cf9d7c85df51fbda4dc4982bc6129614d3d5c9b88ecdc4f4d38d9526518fa116145c9940ae99a5eee69e921aca0b58d1af9ad68ca1911570a3e1fb1b979a85db518e9f414c69c0cb5756eb9e2415390637ab791ff2318ae33548d1bcc229d35a209287ce5b39e45ef5ca4bf446fbd18c5e915541922d5acad3c23c48f3e0ef41ab0922d78aa569020992879137087509cfd509be7cb7d59e706cbcd99c0e61cd3addec0b4ffebdeed5855a6b893e4db3206057e4fe07ede42cfa5cff6ab636155572120920b09c5e7222186100536f9d9a0c1f5bda1600965c892e5fabb719b38550ae38403c254869d7bb60023c12d2350adfc709f05f1d2680086db3cb30af03e6ed126bd444c4fe595cf4acb87b1cf5b91b0ebb4b463c2482ae2e1bfb9f5d82410eb61ff0fbcf74a53007ea0f24bc83b3a0b3b567b2a77aab909d81d19ccab4b61fb1fcb797b943985bce52c10598ba1c828478d6d68e554d15d479e9c23bbf5e32dcfe0fbd752f7d1ac0630b7e9772aa95d8825eee7f1afbdd831b1fe5c366bd82aca9974f7e6208c1ef572b6cfa281ba1fe02a1b6e65eac02be5a72539c6ea11cbae442c997029c09e18002f7d5a29aa9acfc3d131e216be661ad7526d7d6b974d982c82315740c54d53a0288f66fa4a64a1e3acbaaaca6732281b3564783f43ec955a2d93d7a028ad3a33936b65c53d4e3e6251f6bfa2699132f772ac02234cbcd62c6760fb18c87f9162f73db1d11bed96c6953c9fa6fd20aea39aaf21877a2bc8eb8d50f3c5379a8f9fbfe52dcf7e264e6f35334708dcb875cefc8c66058db842dd669c54f7523ce68c2c77c400de1d1b653605280d1578a5d5d2682b5f6ae6881f4ae4b391c0c88b05aa99787aa47d724305a267198a475cb3f7b719d6c38eaa8bc2b327abc1cd9c7bb18205c7f81cc2a25eb063751f249fce2a1b1d076c65878e8b7fed4db00da7a1755926b5ee55640145a1200ce013c7feeb24f00ed7966ef7f347b1f6759796febca3b70cd9287cdee9af9973ab196ce3a237b9e129c3053fd7f5204177536d9100cb221f05fc5caa72f34bdc364c8ac2660da2cc3b774afd1553183a89e3e77266b3014a70efb924899e64e7ce7ed7545ae8117c89c989ce4351efafcca381fba08b1d865331ce76d571ebf85f56bcae702bee5782fcdf1ea633190cb62a0328b810b2245cfc464981bf7378547e46c783347c53b59efda35e6f1b2156b5d8a59e04df271ff944ba7b3faa45704c6fc66e572d87284ad97b79807024b4b64e3afdd7ade6523de351b490b14591f97f61d55d9a63419786477521f857a10d680e771b4cc559669ca74d431d1e3e2ff51d6e347f570d92191647209573983beaa659be343940dd8eac76e1da216da62e97fd0632eb07c85da757984145fb96ca8c7be1aabf20ae645bc3b703a69e8f45c3b5d9e17bd521fda82974d978a943faf5c2bdade15bb535ea1c05611a303cd61a13f9bd5cb9ec3da8e7f2b04de1b4c94588923062536cc091a20ff27281f97a518c353614df2c647711d6dac9bcd38c0e02b1f1f48788052206e6cd40dcc980b7c985857ae9bf0a7a4a97ef600a5de9c5b5f0e46d643ad0f37c907e706c59545b4c9b7879d9b64bbea58b59ac5dc7d6d01171d02512984cf5f6dd33518917f255a1a835c7188531957a1751823fc1f14a75178395b7e03b7c6010a8f42e20a464b5e251c534769f45c5577921253b484ba73731daf71592f622ecf95c9b993266234968779b26aaf74b4fa53628e7f54a880a2402b9aa05b41a47fbec05e3e6a1c1494aa33f9baa5f32f38039a930e9b84f557962281118ed0393ebcb6d6b1468cedc603aef686c40c66262632b3eef26b1c1a578524542c978fc5189fef443e91098a0027be2d7341a1f8cc4e1ec0b9c19d1d9119fa5dcc6c84a17a6ec7c3cccc1fd6aa96d5aaf257bb34bf4c619b1ae686d5a15f1dd232b9dfc112c24a0e67c7c192b207bcb1c5282353a3b1084b2763ca3ba095e03280b7b78b7f2cb1c7789e12571d2edab78f1c3eba8c1f271defb4fdc3feb546a561b5ce4ba32fbe541d32a749223329962f7217cae724ac3c4f595d6200aa889cb50ac10eb76b7d82a685cc580b1be5a76051af513388dd7dd3314b450f37ae0918d3d616b18a0a1da48672943b5e27e392568f8a27bfbe738df59dccd89e1e50878e0033efe1d4930293d4b01049864e170d4f95053c5dd1bdd2b709111817259d07df8073d54b3a413ed5bfe39decd9033460bfaf4a221b3a4997f626b195d0c399d4a4c829cfa81b37ba6ede833a439d01bc9ae62f6838eafe8e86335fd5a18ec803a64de6cd145e787f1f66d5e837caaa2f8b59528ae7d81f95d57252a752a383b33b888bf4f76d2fad626049902133989610391e92b04d86a72800e16886a955a0b1e759de581422ed79fdcf1d701244ed72a9a85db4d75b4e199d1cd0c96276fb9c7b27f5fa38b7a8e167ad9059ac076fbc84420623c3abb95f85d230b9c44f8b5eb9faac295eb25cb7421c4a3fcb19914f1f063575fd663b7bc7620ba9929afcc0e266261925a3a1ad0d6bc1b1e5f84665ab7ebce689b321a72cb785bbd60ab79ad40ed0f8b143dd8a29080dd38f5f7a57c8ba35f4a961d13ab25583eee7c4d8f3ab3ed236d1dc311d2c636651d351a2e7933cb324fe8c2b924e9b1fe913e3b41cd74c692fa35d168b9ec719a176337cd0a560dfac6ada83aaa1b96a60675593f8556bf923a05fb7bba4d85064ef31b62acc34350e64e26fd61d90a39f291fe514b9a9d68f64e148c3f94af2950f632ac508d2b76be85c9855a2ac5f7dfd3e88ab07ae1c26dd5aff5971ac991336144080737382d191898d98b18e42ef992896a37423a60a53123ea90ee3b21422c1cf4ac965f2299238de9d00c8ba205a2ad9b963815b7cc860cbbfc33b58d5dbc3711f3aea10fae2ceba35fe0b075b03a93123e333ca60499a94b8534d575bdf734ef3d457529c2550d4edc46c0942f1bb6d0c6268c9cce82a70fc9815593e5ef9b019df4e61f1f46418c771ed134bc956370656f632cc690fae42c197dc22c7abcaad034b7df3d7072607102ab63f4a92e4b57a6754c04387e86b1ab77fdeaf7356b3c60c803b28fd42a8607bc7a688188844115f2d5987d54cf4f7e2e2f47c30c3b39a1b1c171fe330ccc0de19306be822654b88ed52657eed4bbe3b4bc2246f4a5e9b9014af5394b0949ac8734bebe7006e239896a1be3aa08dc9550e6303c2baccccd898c3c82582382a544a1064f162a0bb61ad97d393029d63baf3bed4b12e9afb390cbf874a327108f3bf13c38660d0893992c5bd3b2b7582e2dafe1e75f9224d077158ac3285df917393ad6fba725be4a1f1373e49a7983b619d0f8588830187c3c7e25ad5358a2c7195e2e83210ed0be0a942f0f900728c0f55bba9140b83b4f8184cf196daea4c00ea8781dde2cfe5cef13af746c86a9a3d56924c133b02c9f03e4d07cfcf4d2e856b841deefdc8af9e7f0d0458c80c86f7ca0dea27410a3719e5c627526ea3f2e8074ed4077d1f7722eab8f87614b8db90abf7ac11ea675b9bf0f04e16ab6132841951c95bd3ffc743e31942e1675dbce1e7786aa8fff2ab9b2e2eaf781175740c4edc0aeb205eb8439fb06ab6d5471d6be661a87d0f213573263a1e62c82293f82e0c3b48a2933865fc253d2f2acbe031d7c510ebdc4f3f292ef1873ab305e28eda18e1106ea911bc00dfb0490af9ee0d50b31607a996d19aa0798ed66052185be345ad73bb3d6b8a34045c1234990e5397026006e394e1490c8807feb7754e644e490971103d08a69cd6f646aa7975484e40da129058c5c3d5b45258e70ef9f19a5291c0c7e3b216182c748b537b28f8237f9fa588a1e7da816eb735e81c5ba20596b8dcc253857010fce01a640d49ec2bdacb426418433571bf5478ffb9899097e3e8a9a25f01a9849017c2db2f7c70ca2569334ba8b004380f17dbaf4f7b8e7c3a88aac9033420709d1440219cc3e200e745070755b1433f55e9e2293d851e2d96a8968f6abc497fdd5296774658b5f39a1be767050635a437cc5f3490fee24709d48ec64ca7915d35d8ddb9e60ada2bb5447c841ded5eb1415f8cf6f58e561c2dde6f512b7bfd44769967ddeba3c808c88e0a4c8c50c4bb187947d31687adb849861ddb7038c69bf69e591aa7e07567edcf2d8e9a3f95c4d5abd25ace0d3467e2396a90a28754dfcb1260c904f2d01fe48ff1208af8616506a3591d5e24fe1e700b92999f3393d21e5ee5437217557cc911020ecb68283ef9abc43972b393d55adc0617b7e6f1b539f11170815accd437d761db05eee1985fd869d288e4d0cdf82a0ea7ce3e784c5f5c8b422c9d16d126e803cacb37e54b9ad245dfba9820f12b6aeece035c827622b21411847dbe9886a4d1e20118f0d1375a6034e1c225f0316f825d5b4369d64658f988336464100544e9a0ddc5b9f0bf467dee609fba1a938903c6cfaac593c1666d6c91e0c2e3d84c256307db2a97f805b8931f7ecb8ef9e7e4cffe1c8b0247fff0620592c66b1317b221016955b254921837fc55c402e12e11a385b99977ccf7978de95d1042a62d29140e41a8a0a689523b95c8a12ce3ea69735420ea85699d95ed40eaae0a4b4a73be9ddc80ee857d2aadb6eb4ac98680dd566ac4f6cd5ca080bd8b8c32121744bfc8e000176585deb4ebb5e6f9751ce45c8df2f3d28c49f851918e213926a94b7fe39b27d229216059b8f73b107a83fb68c81d47e082b31e44b130f4b46e90802eb3c2bf44da28b3ba942c4a94db215173fa85a63820269b11b9dee8b9c507e8f0324a00f023e70eefb78084aaa0cee69ba2a921063378b517d280eae69786891da11db91182d07c81be5e6828efc33e625668dfda9ab52c84f5baf446966f2016080f293bd2c04f5a90b1974ba3bca10514ee843d68bd0b9a2680702b365af90a00a1244672b1911448057a32d3d5c816fa92bc02e420077617d32bced81d69d42a15ee03c4a5289b581996605e0825b3121ea0586b683c795b587fe6d279e8ddac3f96659584eb709a984be94d9a45c17df5b6dd745670dd09b8541bf8d0259566c014e96b92acf2bc2e9ff915e0ceb70c8b36dda7507bad43a9b762f05533f721282792b3bd44c3112d4139c3d67bb634cc4732bcf2c67728388cef1924d81a571eb8dc42e4c470f4df7db5cd49b34c0b8f1bbadc86719db1a23bd80e1dce52ee9da247b85e5398906f4c8d8d95c152861a7a42b55580c9dd2178f5d61c67f5397522a862d335533300ad05ffe9cdaa260329c29391e4457e1290480ce91fc8fd5778adc69fa5d7d967c0308ca56c9915df7add5dc3fa1d5462bf506bbe904985a34305ae41862507372bd6f6d09a22d6f537e4b22ec41422d0ed528582fb5caba0a7480c38a66339cb126d266784b94f682acf13cb17f14a516299a8ed024f3171add24159d40fb67465ee57f531fa8364ab69c7125f9511330b5799f20d96fe3e87eb4a775743e753203ae6911331f4b5a12200a0140dd635d160045eece9bc2e934d7c4993b30f9b433820eb6af5df7438f5b5770fe0102f244ae1cf6054194b407c8986db699863b5f3509e32e1fe1ab6cafe5c45c6eafecda43b72f6903c3401c32e6d49cc84ad91d0f498ffec5672481c578713b4b78bea0462b3194facea771ebabbacbfce29616b8c0a59397cbbb9b11f0b9fdcc32436bade5735876e1ad76f75299cd67ebcb8afef88786c9aad447554a363e1214961ae99d5ff33959f929c33bbfbc8777560104cbacef0cab1c7c4e2c075ab6c5da162fc1c729c2d6312846af9da556fc4a6f15e31c1edf45a35a7c57170b761c02a1a731bee45cd8de3e82b18c24a47d690ee059a63ff267e0dc3e7447fbd316215e9c2d10fcdfcfc4e34803de1769109fd493fe9dbb4ac0cad6e605a2f8bdfefc808f71fbcd7a788df2f734c849ec4b7b9aad740486b1f6e6881b1ed842beeb28158d7ba29ef8775c44a4b595a6be544774b6aba2cb4895813e43652afbb26a094af8f0e4aa04c25dac4f6e1cc8fc05ddebf99418ee8516683898f5666871d5875d034d5f99242b4655e8bda64c284feebb171965470200204dfb792c482b2b0306df0c44293afb15b62f78b8526a1d7f85bfbc4e0b52219c8db36ee83c8ac404d83d286a31be243c513f689707694aeb0e0c026edc2524165e2ec895dd3c7761deb190441085bb21cb6e465f150d7fa0395aaff83a1d4bda17b5bbfe49a416360d8c046ac9d2100254b1e27ed77088e23d14e986fb4c4ec27a6c9310bd10e0970cac008fbf2b21cc5d85ec756f8bc00da39605fc688e970060974a1716be228e1e6c8cdde4d56130995c2641f3653335d7e1828f86f6f6f82b75dc15a42cb5cd9c38d7a904b15d1b91127250e0ca9d7543e2908d061fccf779650fb6fc6cd9cb13bdf4197d0908fb875edb9da576546063f926b4722c02371a962194c60eab80fb8ad25d92b7eaa710e8e7d3a6941b47c5364d5922a7cf1d5f114cc2b0a22537a6c0599c8813cc6255ea25f46b324e476315ef4c6dba2313d4d4ee24424dfc8eb58d8573e291241e4f168c8cd548a4e256005e133775a91c60bee038695511e84b970b472207edc206d65f4f43bb0502f473c4c69368a1509066984e7194a10940a08406ead2c71dac23eb3c4741edc05aa8c3cfb28df1202708a12cd206882b0c86a6a1b4d49d8a5458eff072ed1b683bffef9fddcc01c22743f2853051a66a341d01b6bbc1e3640842f1e66ef286370e51dfdff2f3fc172c55a5fc8708f54b88478cf32f46ba24f82ad441100380c685ac802f4a499eeab2a3ae80ae8eb807c604057d039a894d083851c2854f710ae1400e9a886de43e79366c159fa3a0d15a6f119aed810ee593542dd109798bee64adcaaf3764bad343aecc0d5c07002170c37857ec05d5258d465080048107c1d96339f681ae1f195d753165009ee6f443466c74892176aae7a7a857a06560c18e44a331c5fcf8d7522d57f31f5e99a8d14ad48a1af5fb9f184c719a82a92510d6324365274d743352c13ae57209d639eba16f411b5fe367acde723a4bdf8a2c16d7040ce7fdc3e0b7b291e3288d984d55b6e0fe89f0a62088f1d66da94b512cbf44b7d9cb1aa1707ec19e882d3b9a94606851953ad6a381d6205e27d96931dc6ec096a084e05d791b307e5082d21928b0cb8459495d6d84dbe2b0e74cc0544082047eb338850705a6f8e6470b1eba4d3d0269c1ee9d0dd30ca7c09470a0daece49ed54dceffa485654ca3e524fbf03cddbf21786c9921c0b3633c33e67a57bedc91727074787808f4d11861eb692accc7142b8a72752195bab98715c590fa78802e7760aabedd4900bd566262556ac44a63f9ac54483981fbefa2be1b5b1cd4d598f4cf60498265199de42fb0928a8f5c95a49ebaeef399190b95cb5f3305a79501a26d3356aba3af79890f7eaf595fa14e1927bbfeeb2187af7963da045a022f008aec1bef797aa43319ce791664af3864512c5b7984ba4ba0d7bec6af87612cb44fe320c09a904792fcb501cbb2886250c54198796d21f8c5e79c5f4e618885465ff3bcc65ce837e63d6b9ecba684e8a4d2bac2fcabaf3ae5f2aee34cfd9dec97d987df33d309564eb8750165938354614b1b038bafe64d3edb9bc9793a6dd60825e160fa44e048244d3cf549c0aed862572d8f7e9b11a5dc097df44ed4eb36b60a5369642c23744fdb3803714692cfa85e109823a7c13c8a53ae7462ca9b2aebb9ddeedc82541515a1eb96a7cf5284044b7d3308779df8d8350a88e8f2f46f487fae05f9ae0f4f71abd4b9753667828fb905bc1e1758bd1d9e981ebc6a831816a26e9cd99cbb0dcb5c6a7dc4cdb8bc4fb1a63ea18a9609746c8591f4f107e1de1cda511bc9aad465bae66a51b67a101d7e8db9ca5610c3cd92d716b00d2484f8f08e0d94fe12328f1376e21ebdfa63e712562aaeccfeaf90b3145c69424017b82999a76555b3eb38c6b87ed17582451ef49230ecb9f4eb31623677db9dd9fa415e60f123a8e6af3c716749a006756c4adb79965e69e54499812064284100998e6aa97b9127f4ef4fef23764db8b8e46f62a2e8c6178ae38a0602d9433f5ca84b6db458d0a9258f953d17816be5964f0e940824215b2ae7e78d6ea06d22d956949f1572c19c0c92b3737dce47cd098b3e3d243f8954c7f55db8a1f328fdf9f33812ffcd390f32299ec26fd4a05e6cc1a10cc9ef01b1c64b7317ed38741e893319e434f81e9f794297bef855b236f311f69845206c875e13e9d67715d0ee9db308c0a436715747d0cf284449c2ef0484e3ad709dfa2104f18096194e13123bad521084eec82bdddebac3cbab594b28c491e6a657d2b3bc87fee9565d3d912ba03a0f5231861393caebac5ece20d6790b7c060f4d07e140a6402e6c08e54b1e7f8494ab99828c90f212d94510d40758cfe1e76659448f3ce9b2f3b6ea5c8e468216457e3bd7a90fb6c21e585a08b08329e20b7612f2ebfb3bb2d62b050e9dd288da9e43d4814eb362fb8be3012e724abdd0fa4a40528345b5412fb664c1f24f856d3fe418281cd4cc2d173250066e463436fcc11123fb02ebf002fd148ed7fc70919deafe7d9365bcafe617caac4d447656df3e6b68a83680ac01617e6421a8a22b90be3ebe022605cc3636d5465daff4cec9d76b3fc6a85fe0472e2ea0fc0c90ad0e102f405b52090c754c033b83e3c81c9d80711c4d67a227b91c7ffe8a1f2cb0f240d88428cd3ee3c4a47aeb149e901c5421d32f90651b6e5b9b53da25556dc8357636a58da87c7be7bc8e64854724bcdf6ae620f70f95d92118d55fa3fb117ff3a106695673dd1352111e8be3f275cc4226aa09b587a40b214e5fa1c01c2b47e9bac47ac2451eb11b6f84fad5d9c518c70ea72b6816e0910ca3d72a050036472b4f31adfccd3d9d3811017110f880ee00cb4e7b3b3918728d9c6b9f8ba6e1c8839ea0657d6a7506d75530407c615af46ea4c3eda1a5b8eab68f2a07448226045e63a5219a43c623dcfe0883462415be4567bb6524bbc2a536e4594b7c228e325a901d5f206c31fbb6a663c04c658dec2f13483aa6f291b0ab6f0f3b6cdc22c249b24b819a6f84119b68f1dd3f17326fda1aac9474675edcd5587c16904cac1e710ca2d9756c229493933fc06cdda6c91aa26fc45ba91715d59d762a76239f3b7522a02086b122898b04db36469bb7badecffc34c31d3cd5651fca187ed61a761fdf9b44da3a2269fbb441e0a14b5980062663365b6bb8257f468b743ac3218ca2b75229bd6dbe30008656da54e2bea45adb4ef4d68820dc8de90737170179297c3221f520166b5094190c74e7859269753fcb36d9b4dcb01263c45c3138411e8ba7e06eda0b2b7ea1cabba616d4c2fde639475b285cf46c0c7006f22560b564b15f4a79644ddf52c5504fac81e76c3f52a5eb6dae0fdf2246458e7ba4f1dcab2e9e9c0d56bcab7828f1f616d66cf903807791408af94303ea6e2b1467fcc76bfa0e1152471009dbea6b09f76c6f7d42a232fdacdfc514d1dd5e4b2c7b11bcb9ab2fe9160d5350e3bf9a04c81b5890a9d07f618e46b64298522f7f31ad12f13502032bbe65fc98047f89d98848aeadb0d133d2d6fe629c14e45419ef51703d140b949a0281a5598f3ebc59fd04b4accc7207b89048043a3e5557f75b071199b0657e4f1132a642f18479f26f936741670fc183d71dd706d39243447fe1f496958466c56c1dca0ff10bfe62eb4d7844e1895b3a3584f25413b4558c180ca633107514c09da5d745ae64c45449698ce079d240ec7afea7c6a3ea1f39d4a32e6560b330ac656bf5ebf216cf479088e7a93fbfa96fd242bd873f0f8a4372698562b098958b3bfad58f5822e0fca379c1cf645e3578bf02ce7ebdee8e03c4729fea2f70a17b6bdd139237b8549d46abaca188772337f387f78338bcbf81386304605e4ea0a7af5a845acb4c8fb2bd52632635d775fa14f0e642d40cfe983882b05b08c0297bf05cb35c3fbdacc87136778ea561fd42c48fbe197671dc26fe8169a299398e053a68e37ed4c631bcadc3ec2eb46c9cb8af04e3398323ca6c28b3b4121aa06aa4a4b4352a1b965b4642c07a162782d546e2845f13520507bb69fdc11e645ef486bc011da011a03ff553c84046d0cf42b608f96420d3665bc4d7cdffd09648e7ac18b30aa723962efec4fdcb051b88c358da653baaaf5eb4029e48e1620adb086a58c43fdd852609fa434957065bc2a9f147076fe93c4e2e81cd6382e3803c5f085b054a8cbbd9c233495eb8d0308b9d5489297f3f271ef5e386134539f00e6aa9e5a5123864290759eafb6e49018950f7ccfee78ff5b56e4da0e46211e1675a6883135bee3107b742f93af106eeb022f2cb3b2c92804ddbe32e2dbcc061b90641774e7b351454330b1cb120639caf18fd8cd577356b8ef0fd84c09971dd727a0d55f21867f8c2895b023d71a3f15761a311e8a37abb3eb93b2fcd1793306f9e151805dce92fbcf63133411f3b33cbcca0f20bf2b8a68de82e42df33833b9acc2b80caa2203f6a95754280c2a1e05f69319301aba76835d4ad01668d9dd94e9eb648b25829e3dff78b6c13ec70510281caecaaf007ff266a7fb451819276972d4290ef93aa7ab11934d8c63be0e604d1e8e3aef101ce1041c07c1d139f7f753687c9ddad4d8ae5997db77fdc41fa8167b682ec3821bf33d405c779332fe814c864a621d247b90e347bf48fb87eb872c7c191146410429f018d694afae731c8c58c7ece6cb73bea1a94933720d2d3bc3ab7d4b754520ce4cd46ab0865c66d57275f8c61a3a3ab5a36529c40430e779c337015aa10d8273703431439a7c3bea12b5e78138f4b83fed35b4b25f6859c6eaa2c03c1d9a3decf053228b876cba541751b504e765512a3d874be6ccfa2f1ba807d4e15e8483ab3041110f99213fcce3a0ff919a99d2e86815333c9d61d2925984a2e89021a3b29e0e7c110082f2ae29666efcd8ea5ca11e27105889fed945fb6e65a18694efa8d6e98027998c66cfcb82dff84dfb000598e3c7724bcbdb0494c8d8b097d19b44d5556a892a6d7ad89c8ee0e7de702ffe9befe6a948357aac14aceb0aae4dc8d8eb87a47731b2f5c765244c54a981f62b9f892e09145dc57d0307bd307a600ae79744fdf3dd092e51564304398ede22f7c20817ee2c4071eb0884917db27a8d2a9f9cc6f0f2e82e6900e1b6c74ecd26140d765841fa34d6d87cf44a7ec40baf48bf31f44c99c9904470ceb05474e23ae4bc0a28ad060fafdcfa504b3373d992cf6f00e78dab93558ed75db20e2ae1f5e26e8c46692be5db179f021eb21335e77c95ee5f66d763a0aa385b96d675f612563837e5211f2a7ae36851396850967f368d64051eeeac5f24fba2c31b3588d31d2da37f73b1ba7470048ba366e0b86c09dcbd108d95cefd4749e5c99250ac8d85ab8a99641ac59c23bbe85cc4cf53c963d73588e78460ff8f217ed133a7d5bba49cf88c4e1529e38231e4173f13065f5863ae0069daeb3378160c7ca2bb47d4d0fcc9c1a1e199af0ff56dfe6843f7f1ead4758096c51af8df81c013655e3e30312f671aacdfb2068538a90164271188000f65fe0211a0677aef458a89aa578632ed925aede5f4f56447bcfc5ad69f0f8e676d0f9fa31c0d7844ca41086b9ddfeba44bf77ae8c7da0fd8df7cc80b7ac69fe3f495a2c454c429a5689491fb473c4e519ad20b8bab134ce819f3130b948087fa68b1764b4875546fa0fbbeda101497eb4f92d0a70e034102e62a9cceb1562474ac3e0c66b7111d797f48299a5112da4208d64c4c7d115b536a73cbf76f3cfce21c623db2ecef2084fb4d1bfd637a302dea994d6a2326a28ebb433f1ad34cbb9c4bebc1a31498ef6929ddd6a4a3d4af14fadd93c4207b77b273fc7d423bff3785153eaafb94666cbb0b24f9aeb50bfaed7bbb4f34ab0b56707e650d231ad8b9c47ce91e600e2403f11aef3a89a9f0a42cef3d0075b95ccd6e8d5b5bac367a57b59e7c09ceff359435105935065f30a63e8f00c448a92d01df58e5051aefaa50f192890eae4792d71c6211d603e44ba67380a57feb424810879a25250f2b81f62c028a124db1a9437776cc941e152f80f39f315f0c22b9ce998e73807e68eccd8c1258d3818586f0c0c223dd82934355208aadd96804102f9c261630ea5fc8666a23fda2618fd85f182c0b35d230309c48f01c6ab63874263c6b4764b7c38cdacf7672ad6e892f08fc118292a785418abf6e5c339b12e83624bafb424e4708720bcfb29d96dcd82a5fd4f21bbd070abf014df914ca09ae00b299c1bb552e0440a6f0cbb64852ca014b1a340e1f2372b817e5372509fc645b7e3d9caf8ae5c2e3b8a4520b78ca313c8f6e4a5c6c8e98a14fc7a844a051fd5185385dd8ef86288a496c2a07703519b1349d967507818a78c72cf37edb9678086a8becbdb9ec5e4c9920950e9433c6a03ce643ef9fde93df34d5dac45c61860454a8a2a44d3a5b81364d21495dea93cc9c382d3cb2a5011a48e27bb7742efa12628f2ef70a8daf58ae8fd5f67fe40982c9df97aca360f6380b8264582daaa222bc7d12c24dba7528546a656eba88d72c641bfe5dc0ddd225aecbf2b51a138bf5eba703ff28ec19f23ab4cefa7429cb29ec91ec52403a0f3cf76a0cbb0bf0d5cfe5a8abcd79e3f421c21f1f0d2f8a8f2bd5303833788256b45cfb6e75f473cc12a61a9e6cd919900e056b3dc09bade3c6bc18ff8be58870e030b8e8da66bd7fbb5d27723041df6f1c4086aef30b4fe4191f270ccd6dd2a95e3dc4081f807364ad1c153d542cf8ce3d479113b8a1d07de93fb60e81411ee11043680b0781dbbc85859cf2ed8dffbae908e803b57fc63af13b2b511a7874e5445f8f5e5af844147393a2063de4f1b4704aadbdc94fef5192b0a877c8e124f397f75f16995d63ea8f0896b439321b5e3684c60bc2dc0f33f139ef2f680294c0e19ea2826296c46b1829e4ae423e072b66af08dbe029d5f2ee7b1a70fd2585d68f528638078d03517dd6084899ab9e4cb7ae6800da54f21ba9ed3e842fbc090508c7d623469e2aeb418869b406fa7270d1d66336f793b83024f0e46b9c557b97107a0da1b071714d3953689a3e0dccdc9ac2a52baaccbdf634c697019b635ec0c48614f141c12ff89324f3310b284c94788a20ec31ba371d01cb68dc8324accd779659c0b7526e453386155e2ef31d10b3f25fad0c20e692eb71096f1ff0dc5f34c649110bfd8de66b3833329b359d92320181b4db5915800a92e9dd6f3ef7dc4de363af968c9bfb2e22662ab84d42ef34b0672ed0caeee45ceae6462ce2ba206ecb46073242c10b5d896b1f83d81734e8401183ee06e0ab668fccd96802611a330525868d5c4cac6b1b9c84de135ccfbac0ffbbd3b9d4768f588b7b1061e098c7846fc1980eec9624fcd8cd6a8ebaac1d8b6f2fc1ee32c8f5359f920fd9dd628083f2c99040823b5945e9606fa6611ff40fb95b32f7584c808fd055f40cc42a47c2c4c05af8b34eb2b61166577ee7ec3d5c5964118c95824b5b51b1340945874d5496501453a7dd9272b7b54ed6d2afe60458c5b019efba0856b1a907bf640b6cace27ae7a25bb56d1e7f32189527b08a3dd38b371a793bcf9e86a40787bd96c19e2f0d4693f48f5c654f85aafa5d9a3fc8da48fa07392e684688477a8bf28e068a3d58276dd767b731189b43fd59f9f60b39eb97619ef3918146fa8492640ece28f1f1dd3bdd117abe7f17179f2f5ec6e8ff6087b3991ba1ff828631bcfb5513c6db209107a20228d0136a8aaa97410a1b6f5e0da323a41e7562b6863ceb73b1e749889933a2abfbc9e05cdd1b647d07271789d36ec29021d7afa523214920ab20b0b3f62947fe113dfcc6c838ec3659218b211945033a24170c55d1f138c075f4fa791f0cfd5233d12240f707b5d2473543d3eb5f2e00a1e2a1ac44404e882101f47e901fc3313ac0ac9cb70358e5cde3fcee4abf6ecf9ae64a1c1357d29f7bc34fd5c0ca71f0636064c344199825468d0f5cf1528a27c0462003428c94736111a192fbfcb3e888c5d6eb8aeb035494c946e739e8fe4b8fee0619dd5ef1b8c605605c90eedf181bee0978361a233e13208391d829d57cea0e22b97c341a18285444a796facb826f4048a82dd28b2f6a5f0aeee0c05d62e580902d51449ad9f7409aeef849b16be8ec204b811e09a2a8b6fe17912620834729d08d9e1121050e0549104dd4310a873b885344f17be77d261e85613a005170158ff206065ac6143d8889634b3794da690955d5e97ad0cec49f7efd8f53ac2ebe45fc9341477b5c0c4c60d21aaf5668a141c6de44f68071c7b768bce754d102de797aab42664bc742d4cdd788ef7a655be947fa7168b473bea5d3a0592523b039b66c014922a266c7f051087047fb68c62bed676de7e4e3e88b6aea96dfd97c31d46da3004604499cd528ae57e4207b2f1df70680d85a2f510f8580bf85c4f713271febdc96d1aa27091b2d3948b42041af4437f42e8bc0b72b2219fc26d1abddbb7207c7ac18caaf16aa8bf854ddf05837d8521850f97113a9661556bf59ad46309e13e4eeaff4302a868475f209218bb03c121646150bfc4016670333b14d98e1cd02ce9d80d25d0db37201a5cbe5c8caeeb1c53b592ae4a5bbfd3a485541e1bcf93c220f4ff335376766dca91673245346e07a2d6a5c27c85cab9c05dfd43489e2123365d11c1b27222c538084e8e7c1d1c923667b3c4c48b2b4b732595f4ca13e23194f5ea9e0fed6d6a0222b25065bb906e6c5c9cf233e5191ed15ebe80a1df4efaae9211fb612ba59d328e71ea38fa81a703c5cc34412c2ebb4aa100b4e0408e6ff13f6e1b68c233800d1781a03dabc694fcd3a9b1dc64cb086d438b17e59b50fba17608ece1af052488d85ce062057815abd1713fb9b8eeb7b75cea8483f861174fff66d24467ac34c5967afb4ec9a8ff6ca09c9fe22bb058d7366d02a4ea98ccf44883b7a684d6ea9de5caa267001f9f2864606dd61fafd2a1cefda5c32e5fab9c7619d9441361f1f84aaec038aabdb8294707ff66af245a698e8f92ebd56461ef04a2f304956add347cce0588014e4084640f70edf3fd673da188700043461339433ab9c22d8e24e300969f1042f9974a97040a3aa35da1a6cec2a42d6ab8ec51d51b9a5645aa654ae43f9fff634752885e05fa2b905dfa5924a5c7e5fec08000db5107862b1dbb89260cb793221b4b1c43e902f2ac434f2f2436e1f578aa21a683bf07e7bb6f06ff42282b4ee5f14eaf24cc7998c24d1a34636a2a8c162340356ff849798a0c1c0c942645fd98d00d5fb6044cfa91611d43b84b83e295d57b3e6fa05fb9c357a31c1adfb1f15f985ad3df73be056ef6a6f2abee02ec541ac160b63cf52fc0bda7f034412cbf731f7c0a86a4b45a83c5f45f5f4aef407c2573b686e3ab4287c9e7e48c147b73c670e3c42a0e2170dbcf33d957f3e137e8f31e1954fee7221b0258fb8278f3bfa8bca69726fad3a10539eaa9982b36ee32b66affad9053abcecb25488fc294c26c01a69a6277830cbf12a5fa88a3804ae6c726d1f0ce4ba8b557631a72f0de95401b2eec8d95b155ee8f45b0e2ccfc19ebab673802b0f75069cbed0e55139f1ff4ff6ccb1028b359c462f608a0ccb25bfd22d287944e8fd9dcfbaaf7097ca9406eacf81751148d1c8b8d4fa16d2f706a0122785fe0a40d5aacde1015cd4b10828738f0711708c8e537c8eb2c981ec090a8d98e53dba5946d2404688da265474ffa0d6a76fccc540ad51a81b67bcf338e737630d12e0d11b081e5ff886823bc26180bbfc1822390149b988ab7166e5de0c31f6d903d98d2833ceb294b64e0eb63795b18a1a9aa330e7ac5cd61db778948bd64378c7da8d76ba5034ee0ec73aca6583ef0a015acd4a637828488f52a48e0928d49d85b07739be114193388334385aa3f5653a16e39ab31d97a7898024023aab3a450e7edaf37119389e5a4c1fb88c00c5199430260ab8df08ec1989b5bb2546d46cdc5ab7c0448ec24b3a5115b45bcfc930e34008c3b5a719f010e2cab2d17a0baa66aefe49cc2478da17567a17483c816027198849b3478720faa3c5377156e11113d0fa1af23cdbd04317033cb653a756ac848780eed288592c9cc96a100fc24d560ca71940ecdf4ed17aa2640f63915b4a80ab3f46177a04cdfda01748f171af39502770eed2ec78f1efe9eb598f15e5f2a57382c52cac5348d454e1bce11e5f760b54e7fd3d3221a2fbe5d13f01c1be7a40a88788a09294376fd402d1ed83214a603813369a00591e45886e0431425f9633567b2572df86ae4050c3ebdb7fdb4cf88076c234ca487f95970e04b18b2824525142815a3b1408d0a22c7c80c6ee840486dfbe79eb9acb3976cb853bce845a1991b20a50f83b8bf0165b462c2237343080fb3ed19ef55001cb1877de2fe4c44f39f45d9df42c7d08d54ab7a5cece833cc60735db33425303cb500a6a2c5e9b398aaa84af8f19bebccaa4abc3f5139c00e222e3c0e9a26b2c085f5b7fdae1c5359b0b68cad053e1c29380bdbfde4c48cd12a8351ee482bd3b871ac88387c5575a9039497584cdee070a702c925fb531fa0f7ad90c0c76fc12e9e476f4751dec502d68c5d01acf61c24aef693413659148a1841636429d91194466cc8dad0990d0214348eb8e1999ceeb3189222f793aa0c1efe8403ca2f58226a03c92b5ea95e37b8325c00925015c86389e8ccfeb24844887206319c35c379093d0915fa6146ba153f4a6d13bc986f5a0a864b8f42c87ab3355c462e8568e40aae7b7e485e5a33f43e9d703982673f65ea9694e65a4d9295796f80d19e8db4a8f452a9504918b3ce718be16e88050e2ecd43108e8899c6574347d5b886e8a3c00c0ffeec3da05a130e330072e2615b117710c87c9174a6e7762901dc7fc5292003f6df4984b5f618dc51b4146fe1d058109a4be390647ff8c806c23be839263687cde5590c509d00bbe8ff3fab43759137c8e636dfe91fb2c99b25bdb269bdaccfffefcd1a46557291ac86bc95449cca94110d3fd9e76fbf4b6111ed28307abbd4b4dc8cae4d286f2bda4023b4795a8d24dc29e5cb572e51040406fde2ce31355b32040f216057ae93e6fa9769ffc959b7ff78931de61bf911a585a4fd4fb24c05f631162f0ecd78b91c4c298c592df46fdf34bec623ed009803cc3ad40b91369f0306e514a82cc93ab0473c184e1ad2e60b1d52b3938b0332340b62e778d4920926ecfe74057659103721eee3ad6963c480c15d7f3ffb6447dec2cdfe8992c1913744bd4f1fb89232bd7f777943661bd113eb744abc7aa009fb1ba256af33e73ad3c76d81265d096601151cf2ed5129d7757f33dd90fb40e93a99a04be9827c081ec144a3e2aec0303d93a6d1fe4c78d5c3613b86ebad3d4eb0b8d70dfb0af0acbb2c629b359c01745d9f1592c13b27b472e774311df0108130ca3df81249eb36dd2b83ee21cbe7c7183409e5f6e0211a667172558b8d373525cd502e398fb433db5be15543fe043ee3c0dd045c62d9563aa7241ae770a09e0e4f7453cf1fb175af06030c0b36029cbf140ad0effa78fdf58c6b2db34e4e394331b9b0acf5fb8e36b6681abeec871ebf9653ab23775f41b4125357b43613a29654607a95c5696176e2e256a16265dfadbfbb50a5ea7b8f4c044f7520dddc6613f03fa16bb448848ae7f87a4664dbc19488b29ca5807223218d3dcfe84129491bcedb626542de7602e90e891a1d69c70c0885b0802660df92efabdd8061452a98127743882dafe46e65ec0c0a4eb75df314104f878316846f89f7f4003ca36d1a518b22ad590d12def2667819a7d3c984572afcccd7d4f284b394c15f895da30da3d86028d3e32732a28867eb2fef2540eae45090f1c34e0d1423fdce7fb3b6efd8487ed01502ed0c159a23294168a1da0b7040aee044da21fddec8a236a51bd1be83aa7df6a44c48d9c34be4df13bd9d737e97a30102ef913afa684d52274fc46dd1b78fd2357c4306fbae047f98f090eb7d2995788cc80f05b3168bc89b1ace9fc9c409d131b0b1562583cea177cfa3c8b7b475a6e8e7b377e0c82b08c9bab3d0c981ec6289671b31f41e375fd758d2fc983d9731194aaf1b034e93c0406bb2aee29c22a5c0ea849acd34a468787c56d3380100ced2f427dc4cc403864593044fab9e6468366c3a05f8e6f4219a23e95ae2f30c156325117e8d4c04526a5222a5cb11a78513bedf21cf35f275d8407142c81d7e1922eca26786723e00274f074f318312807e2e81845f4ac88ee3b00ef4233389e2d3f419a87ef6cd2b2d150e9df85fb2e248078927d76bcc31f612fad331519451daa8070d261163fefd4f0f375e4e4f24cf703e9d9531fd90e0b5e385af6ff6931533761b8b4d6828878c15f4b33ac21724e32b2002486b2cd988f6cac379507911ebad42404bc466322e64b9d92ada2380e779a63570b84d9ab4a804037e6ff3001a83d112be89eb401fefd530965343eec29fe29c03dadd27e68dc49c59d13efe0494942c16891f5a3d93913652a9f16b60bb81590a49e1f59f43f4ed8df0e194d680d4f34abdbedbd431cd2ceb68d3c2309cb2da15d5ba36147e46c91544258f6a99b8a4ea436b11e0a4f9da8620a0b9139e0104425c7d9530a5cd0e6ede9f633e2b3f727c081fea75214f7058ab32c11f8364681215eb076b42893945e6857b78767ca1da076e414125408c097a29d70c37bd1d47572fdc6c2114a4a0a155c39c3c532312038ec2e539c8295eb83390f2e607d02987e657269a311f2d49f9b576c73f93214b9e0149e1cbb368c368699a53cc2f836c20e85b4d151ce27f37b5faab87e88205e2dc112eb719b95ff22d751c364bda029170e39ca46d51f67150dedd1f4c00205eabde3621e407df05d75ff2ac545ca23a6ad6abe0aa367412fe48aead62ebd33345f8117a6289139ab1454887873be900dc5deba28443d02e0909747635e83298ddd05e6dcdf0c1a7b0c60028cb897c8b3109214a420491ed37bbcd735bad9e36d81b21081971109cec4b19a3b7b6387e2d789afc586c9c1cbf4e9b7eb7c0a121096bf00f8a98463e8ab90229edfab7da07e4cf1c946aaea0765d7b4cd4210f6c630f2da21f91673efc33aaffc4b2b2224f779e0deccaa6f15abd942039829e73dae5dd86c6990ff05fe5fbc81d220522445a4d01f577e680325c40e216959ef24a1550209717e1e8207aff841233b70de39d1de173e074f502b1f0d3c5683d3ef28cdb1d0ad1a72649bdc63be4b163ced72c7725aed4dc2edadf4af29876d1b5459ecbd07e4804399f2375db78f010ca6b33e82f82435000c98eb60c64fd3bd643d8753d420a32d605651e6bf0d349d15884553ccd9c603acab12b1ebf8519b61ebc43478680e73fbb7e32f13c574b9f25917630ca8d0a6c0c6709e32ef6d3214e521d7bcd2ef9180e2a615bbd453c190d965d33e93422908c9fcb9e14133c203f71503ffd3c18a62cec69570f68330a9fbb5bee229f15948c508d9e26055448a61fcab54b0b1e2736fa90135dc5544451ca7c58c080620018c15e705ec7620295e12ba10d11b7146ae2d74aebc149fc6a8438e49bc12583f2ee5bb5b90e89790a2bef639ff72c4140ccd1823f0768aa1e3ca457a83415bb848889626ba17e710dc3b8ad214cec7d786b936119790e29909312fb8610f28deb7f69edb54a504378a5598e4b7f1327348a452d6b76da4b7a8e90dfd9dea445ae25f110223b64a97174a17da47179e01861bdb6ed9177e18a5c73f82802bd3faef09fbc6b94adcc00189617f3a068a7d25e7c6ac066402585066d67e693712e049cf96e82dc30f0f9971c78d872700de4410594790dab8399c03d7407b63f94cb3026844038f46c06fd10e54286cf5b4110acbf83f7f8ef033b2f2547faf2d331ea9e77702e71d3e8cecddf148a5a492f5584b5c2889666fa29f815c90045fa57de148ceb8bebd54e994eac00364c881a20b1854be4eaaac7d819df6b0ab117ad054da003f3a637ac790c6bf17cae08e363c580da52ff7580eb4c0462d8d36b2f8f2636fdd23b5457b37f2aab393e7d72ea5f1d881e6867304c1e1ac06dfbf5f002427ebf9df3639f8744b72ece811e3c869f07567051bc8041c5380e94f30300ace17cec8bd3034c270fa9ff54f0f1707fd607897b09f159c685d97427123327b8da5cd25b2f0773985b3121e14babdc2d1364ce1f960c00119d6de2c2e05ac6313289b000472b2fadd898f4b59dc1bc46abea4b994f0963d55b4a60db298688271df115533a3a80021e2de8e1108700794d23ca610fc0459760d4ac359f626f2a9d6b7f64d59366815907016d5353eb67ed3a07c1762066bcb8751f26177af193910e9ae85156f2f024dc8025a588e0d3b631a36f0d9804a76ac7880283cbed449740247f958df590120a62706d9e3be3a32ee5600c8f205c25ddc8b8102e2abbf1f8703aa99207aff03702bdf5ba3eda738bf16ab60049a9b750cd1b98400d318619451d28b5ebcd212cfda41e7b740cbf277448ebf7a52fa440062a54bc8a356b002e49574fbd928d470f5b1b7d9cb3aec6d8326fe64d085576c32103828a5d223a8407172b67bf3f0176bf126f767fb4140b95ca15e78401c4ddbf1406db3083367bd6fdb060bfb268ab91338ef4ad842c2e797549e4e95105fa62ef2230a6229baafc64c135801743b1fdf64c2703bca467bacdae03d805d93b2d607dbd3d3ffe06396a32bed86e84bb06cca07afbbf434093853aa50e88419f93cf0ab5dc7ee7f6254f0d80d439666b16d0afeb3f40a19f8a9ab7563ae842ee7d1e1ed0ff13dc9912332f4373435219dffa6e0c378ee54b9584bb16b70a16a753c6e05ff24d01177a2a84777ff5bcd346e1a3a289395fef86369e662832b9980c9804cc5f1719fef52ff6eff5c446025efc3693d127eb1ee6f055d111a20cab233f43a0fa87cb88bb5971708e27d3a7176d2cc44a07ad2f9d86a94f9b0a20de214ef4d1f630c9e1b731ee7639f6d9f53e3ef714880bbb50d59be00779baea1530d48dd8a3f161a5b0461caa3cc02f9585bd0b69009aca34bf8f9f8c349a2e8d74803fc7d139254023839fb1deead10822a95a919f4c1a41de18f29208d0768bc39678a96bc89871c64a262546283b79032c84ea0d879389960ad13dbe138c86897c0364623b356bed52fecf23df6823177dd5b000b57f53aff88e00b4b261a8ef8425621a9e489340e80a23255f9681d4f6284ff24d1cf962c9236203a72adb0745e825448bb7ebf7d62699ce3861b43866aaff90d058a1bd14f3750130426c89152c74aae0ba2e49b8a3d79c7d318beb234321b2b5008068b191596a24b32ec7385fe9147e8434b7009c0826b2231e2a1404e1c8590bf8254f47fe1f506a18b6e5ca912808759883de3bc51cc8211b982d5f78e0c117fa4d80f08664404fd1df6b840d41298ab0fdb807c3d8d592a3a111a74ea9a96e4ef5a9956c82bc95c94604c332db1d810f7b2f36a278bc89f052d705513c9ba052d6d07393a782274776a79df730ce804b4069bf174341529b25820dac0a27e919055bb6b7af74363964508d3769f9e49dbd90d42184a679d7899c2f9c7eb0a1bb62df46f995f1cdccdbb5f8beaed780d5a03e9ba618b0554d2c9f06f3b400367400bd46f1dd951b90d64b7ad970a76cef21c8381eec4abaa2557c64eccfe012e68944044109443eae364c720652281170157103e4aad40fa62ee0d8d83fa03299b915a3cc47c12f30a9e0ea27c992234773b0e77381bbaef066c31c789f3cedda8bcb85d1ccfae635aa8536ae0c41081c8708e848d6560b577e8190d7be124c43be19a70a39a15f5012b35cefd1d786acee1ba6fbb15a83a05649d2b66470455377f3e24d10bfea9def41492352f8de019f070f5013e9dbd561cee1c1f672b1778825922d50425003c9b73d078416f7e9dc53afd820d93aca071d16dbe47b410134636352faa14ab5251752afba521af55348fe48cd4f0c7670704ced4175e001cf1256c7c348038a0a54bed0103ea16fb0a1010547185d66f53a2a760b8faddee8245e9896dca9080dc949dea0c9f578f43c508e22e557cba25968178a4fa89a020b989d0b8c1e8988e08e8334858e03f7c768c875a008dc1e159e18649d2a9acf83d73b6375e86a53109dfdb6ad023847cad77f6d594f8b306c2e5891dd506c958d23e57a7b3d36b4cd38fb1d4a69c6d205b79cc4d9093a0c1d9cea3a0cf20c87b0647b020debd423cd4fcad782d3afeaf36999adf8865be45514fe4af006bee5ccd26f6470afbaeb977bc37976716855d5e317e96c4e9a42e0ea292f45fb141d00308c708bc7b1e7a8da9ed6e58e9f799c1391b70ba140c23fd59eb0be547ff998343598167a5d7a984569a6ca25a455f71a27b7149fc539ee791060b37a61539a0aead5ec5a284c2540b6cf173eadefbea40202959b804e3d725a21273052105608fe772fb5d1c4d40e865db1d72eb0fe578ff5325011b66a67048eb3e4627724bb961afe010dc39bbf1a89eb41f286e1d7bbb6a418129cc41b560a01478468303fd0123849b5935c591c1648632a098dd1818e880439c9e54dbad95c127913a375749691fc49454b3d9aa34992c9f8899c816c1cee114abc0d22c846b2562e4e03f6fd347109219520f1349786838855fcc592dc57be637c815e0486f806ce67dc5d5c70d314f577549e4de8bb9771328ad9f8a8e614de4849c0242519315b4de94295d83958da82ead4f39ee063bcd6c4acb828e11de7408e71c0c03f4d68870ff3d9f85032065158e3a8408811417e3ae20f6ca933559dd3b9ab1bcb5bbb83b81df00263ebfb0b5d29241bd32ce9b74f72985f032e59841b25b8a7a1c0e0faecd08711dc0033de1d28814426c3968f36cfb4a11c5f2a656e7f7c79f2015308eeb916035bc5a33de0909e301140390470643ce275c40c0d2c226bbad08b8c0df8a8937fcf03089a95aecc0279a2f5d2aaf3e5c7ca21e3bab20b413e0a74552973212083708423b79a90b02a697b44b5d96c0a92a4ff2c423d032c74c4fe2314e46786b03d520ceb4227fb1910d9510864383c2cc5169a0db874de643985dc9be30cd9fe6756c21ba351994abd152e802ac55e07d9a15c64884528a6a57e5688e2ec1918926c8670af155e611f199d26d85030cd1c530dc6c057cf855fd3acb429f943c9bf4ea458dba5792442b666f3196bd38c3e2110c72b19d16e4c22671dcbdd9bd98cd5b54aa560cc14a8e4e8b915c5edefdae963a546275268fd50a19628ca8f4102cf60e79cb4183d6001d083e976ecd3348955c358346b06fd9b571b210f757bc89374e8b20fb37dfeb00955063bdb1c7b205fe560b67a67f135fc849644ee8bc767f0d9c88058239641ebc26c2050a793a6ba7dab40370b428ceff451d0895e6533c791882f9362957ce83191483b4df352e2519e9afbf3231213d8b68c341d11263cf73e417db176237e6a46bb0d8946c6d7b4c0309d4a2432796e1e43e7813e00d6fb2952b9713dd91028a821794733ca01f04b5d459fee94204b2c3f7f972708ea2244b9bd211ac1488275a2d370c780e3e41c0299db388d07476ca9f6ac308ba6f9d7a369ea5c02f3e28d46125085364e1862a20e82da591831c9343f1fcdc2e7685f21602691fffe6e3b0491258e5f931b212128fdc346d3c1d461293c3980e31e4b0c9d8c62675490d1d956a78dd05718580c3424267d5420ca63f62441cfcc69379a79066c53053747b936e1d19cb3ada8f1a47cc453a63d28e670b1d507532d497d968b441d19766641af17fb5d82fe437774bc2ff62e551f2917e307961306f89ba5bd2a474c3cf7eb04f1e4b6e8fa073af4e7e5e7d90a666687bbbd8b61d26eb46b7e1f10e3b4c58527081c162e3346d5c56b16d9232742ca116763e75a249f2505b72fe99bea1e3d5c39c247b6a4b0801ab24f4ce6652abeb7b0ed2e06526d2d2272c70e388766a89ba8c83e3b65859b551bfbcd8af177c62020ab8195b5f400e3aa2363acc36a04fd57e7d32e4cda7fe012ca22243e04e95bd63d3cdc99e9176ad479150d869db800e34949386d508288bcd44d863c01e513bdbfc51750e32351cb91cd483866e111b220bf65914a08aaaa2fadd9f484a22422bbbbb77bd059105a905a48f41c4bf87bfc1077c1adc1a74000779ba4e7abde5de7bef4973487a9e9c79bc4e7afdc9f9e52f243d0f09858261033f61845fa72e1f1447af8f73a45da6ba4c975148b8339923dfa67fb4fa50922e9954a9f5175d32a9b2435761da7c747e0d8306de23462677f2d36edef2d3a0bac7557295e0d725f9f4fa3a46a6a4df99dca111e18a9e5123fe4947a05f27bd644ec77f640e0c171f49396d83b1c91dfb9546f548b91ea5676b51e345d2a9a4ab3ee2a719217ff71d2af77184ee848cea50772673286ab4516e32c7766ae1a251086efd797625bb616153433323738a817931f151086efd79b9c3d7762d9712898f4270ebcfcb1dbe964602980db2b21acaf521c964080a58511c044a61d870eea40ce1af22a48fa97e2f932a3a984e1d58d1435c1ff957251c6061768217e0480243419095d6501313b7f967ae735a40d3f0c83e5134543e953f512bf415e654807ed942ea7029658c0380e2620fb22a06265e4c91c18b5b133938e92327410dfaf8bc88137de42a1da0e8e3bfb04205caa562032b7164ffaa2367ff38292a38e8e383900229415414c1b0d92c714430b4d0a30a0f1b58f65685945cc590e753c50d3aa6307ca8b0a0835d32a112c319bbda43eae41f1cc8c9e787c86a845696dca94ca40e8d999319945994d99419160a4481489d0d5417f4b30f1fd2658e1a1902c94f974f5d138acc51f894d3c44271c85a8ac92b3921e143f49b912e7f0e913af33581cc1f3d5e13c70b4b977f01a9435fb014e40efe5b0aca3b3931e14a6a1284948b174f3205903ab45667c89d6fd69f1ad4e9d76ab3f46f5d529f74fab8d63adb7595ce6e15c415438bd51343abeb56413a7dcff5b57a62e8f4770bb42058e9046747f696d9269d7e688146b34e9f1fb14b3a7d92fd29d952a9d259ea59716e713e3afd12cb6565739dbec90ef574fa2f2b180b0353e98451c5f8786d2eb0249dfecb0c461643e448a77f92c95819994aa74c0eafa4d506d9fbfdcb7e51a1a8d38fc9d1d4e9de3a7d991b347371349686a6d24993c30b13f3f5daaaae5a61355665466017109dbe4cacce489126480d4cda581b9b4aa74d0eefcbc8ec2aea5eabb5d65b2d4d15777f7d3628369bcd66b35d9c6d6c7615c17ebbd55a2bb641b1d96c36dbcd9e066f6e7615c33e6b6ec5621dfe705370381c0e87dbe088e4228abb8aa3be815cadb5e60ee3a6e070381c0e271b422693c9643252c904739a69d162d3a8124aa7514e58e8cab341b1d96c365b8771381c0e271b422693c96477b55aad62b62ac64f33352c1e55597287d4e5eb0e368dd96c369b61d72c2773326793b9582c168bc52eec769bb7799b37dcbcbd5eafd7eb25a34f6bb4466bb4466bb4263fa0b50f3e48a5fe254a8559b19391d7fa41aff3c78e85816017c7ae117685d80562d7c6ae4e1f6bdbb25d28369bcd66f3aaecc2ee900b0b2f0cbcb07d61f5c2f48575fa36531b4eee745370381c0ed751964ceee021ac6c5b59b5326d659e956559a74ff18cd995c5615776655776655776d5e9cfefa72a913a9889e791483232a28851a30b17285c7f3afd8bc24032873e0c183806aaf5c942b2b0d6eb6c2ab0408bf4442bc716e34a27cea19c31d07befbdf75e8131c638a6780207951a3cf91162120afaf2bd42b57e6f9d3dee65752eb82c10b1ad198e4801c50e285a86783af854fc830cb3258c9032031aac0aa8f4ece0c305fac2840531248722846a0092831c42d2c5f7de7befbdf7de7befbdf7de7b73ec761d2ee2e3853c7d64de01638cb15015b288b613988d80065a90c82141c207470500f7defba4881e6428024bcc85a2d78d0e433730810e970e4670a040b845654d31a2c1d9cd129a7001c105b9820a223754d144b883bd3eb84a708354cf05530bb9f75e57096e902a23b7849327a09019b1c5864e888824eba402c348c8f4865e40b0008a233a58b04fa6108522e08a807030a2090d4282803b4c9c690d51f04089a8fd48020742d050c4051a703168c143dd928b541b5346b0f2210724c5112038d41cba1ecf624a6b9d7203d2f45c35f3525c2103a94bda6a04300840875d57acfae3a4ae80e18a1c54052a2195904a4825a4125209a98454422a2195904a4825445f535145850d0b835dd00676b9462a2a5454d86c2a2af87c19ce8ac23768d5147cacac3e7fac2c0e0434a22e576803270cb6254ecf504dc1274bee7894dada0d7034edcdb99d0e389d6a6ae8b4ff54d23f9dea8dc963677571295649e1a305631071fa7482372447719a659e5e485f8237e8ad41df9d6b703cb8f69a4cdd62caa5951cb4614938289c71e733ef8aeab9779dda4ead2a083e9a28efeefc401bd79b99f39b394dcd1bb34b2f13dd3a05b2702b4ae059f12a62c5ca8a96152558a263ec1232220b21d14de101dc12bbac221e84eb1f2778140e856f1162b7c0b66459910f7bce49695193a29f6dadbd570b5017d4755dce454545547cdfa7f59618b6f8d822e45a1cd28c908a80a7021657d1c08b64e8fe715245418ad0a1a900ba89e6f941975ba7ebd1a123058d25a593c284f5a7b85d7890ea13e499e9f5ad0d1841f44f35230a15473737652ac3459733bd3eed6305684d81ae3fbffa9842fa7cfaa2d5555b7dbef55183ccca0aaaf6f2e04ecc9ef5bc4aa787bb9c79bcaf27059933dffbf44c6f906783e1c88e4695ced106c35c380279469c34e2a418a904f2945c4c2ff6e5a5d2f9526ae222a5cf37dd4c2fb6975a9f0fd38406f54989d02014081aa32f1a84ba86828a72b85b10ce7664124932935d22b2099b3d7268fa98ac3b345729c82521f43979e60c399a68a5f6d26a2fce36e74a67c65deebc6fdbbd2b9dfbd35b8321b79c573a7938e22352c9c5644da64aa7a9e46272016fbcc0bcec98933d9d2a9da793cc8c89a6a6664bd1868565c1a2d2c92266cfd3498a3433bb66da11faa8815eff06a9575465c99c89925f717dbe5c814e0fa0d0923ee1b8e3d50c2184bc291f6b3e95677dac89f5d1834eb500f531460cb44c9973525ab42a6a15c9c0aae96060b3e44780e0839b55107c82d00f828f057e9810c283680a1035e07e589c0c8fb54ca1c596811800ce8b20fee20a8e85e5752f86f8f76388ac870be12ff0f179e023e05998b051bcb0823be155701ccff97073974c7227a85274351d1114d9c3419889ac741d5151c65c5ee9c118638cf17d01e32b2e8c2556e9e02357cdc0af00d91cae34210114443820b2425474a5e7852baeaeebba9caff858bdbfeffbf49e576657ae00f56b833b79d09ee44674be813fc1380a7c6dceb7bb75d674ba42b8da9cffe6db59b1925526e03870a225fa111e11baeed701a100f28574517564a5d300f82477f28b3de0b3f035f416a524407e1bdf5711772bf6003e1669d49829fa5984c08de98282a80840d1cd4ee8febbece3f762ef3ed1eeba45164e358a74afbbdc6d2b765de76d45dcb5a73fad77b73f4b00bd7b15af157bd0bf4556aea151b68ab56fb1487dfdb5d35e6df8f54e9c32677e30d23eff5a992382b56b2dd2aef79474dbf0eb355717f3b5076ab1d6a035343825056d286bd8af461567bf913a269d8e83afeeb0f75db765215aa95dd9985ca1c124eda0b256b9ea57707db45d5e91526b9ea1827b07d9dd60af0fdc07ad5222f79313a2cbe572433d17d447de65ae868535ab944cb000d1b108e9e3ec124b0d587e506bedbd32c996755dd7656f6209c2d264ef3a5f649620d575b25886c02c447026598884b44b26392859585956598cd82008826128afc0b2c0a04b2e845625c143b562c4ca9224f9087e82a3e8acdca6152b5d7e44af4ed422d2617ab1b2854f264444888e7821ed7c6895923985d635c308c2354bfe885f16bfbe17775d061f80739639f6011ae36ee77c0abd53d855bb311883889bfaf8ba0379be4e92e996f49aa668dd1ff880f7be5a90c7e5492ea50f4be209e4b9bb2381361ad0b3c3c58eeae276d2eb6e7b600ca26eff9339f63b900777d2a77936c8f35912ca6a9047cad4484aed973c29495aa17f200fe732477e06797227bdf6b6f6ba7df03d30dfa36472e7da005d1896dcb9fffa5ea30d500d965e3fc3b0be16ad16b4c4214d4e47365b0d6d16bcbb8f59a26e5f97163784a4534aa004292550820941144065d0904996dce69c94de4063068e07314268592b015bc2bd26cc0021f5b92be172e6c4ab8fbc011228c184d7732ac344fff435381ec408a1cb3c9bcc81da3e288450967e42f23063529c4e481a8fa22e615debbac139c50bcc2b6c54148de5a38f1288c6f2a101228bc8a8080d630629b30d788d07142a38155d97341e55aae83d5535e078c269386e70efbd57f8d7250d47154370e47a7a6839608081875dd272dc1005d75dd2721ce1b41c48f413379d6a3d7749cb01d4475e93f81a45ba2f927fe435553fefe5d5013f8c51855bfb9a76b9e46a2cd2fe89d6f614d9fab5deb6c87ebd2b9d72dfd0a22c4d59097e9f20d675ca5a4710f48c02517c4e1a11bedbff6ea97431ff2bcd54f176620f59ec0144698dc5daf5873f794f32a77f9ecda0cc5ce6cc0f3fbde5e7856308ec0c9a4ad2abc5a36b3b4db19525a56e6f40884899e3d292cac88ae3482edbe0c216a155b3190557b98096238a576badd6ea806d17191826113a19e9b0810e21928e5c09e7700959263dc38bc987d61344cccfa9a7894c4f142693e9e52507119a1ea29a30870d6f4d91b6e375b3e307da0e22586c1b1b1b1b162c762441ed29d276d85aec20c22989a083910d1d6c1c1c1c9c0e3ad8014424002092d46809179e1302d853a4b120c500f614692c6891e992c683c7a94b1a8fd707341e47a442ce43c3e85167954285444a49dab2721f7dacc992247766a75ceec82e69aba21f5ad502559239e79c271a8e20b921eaa382e9d0c20b1c782ff49831f954bd56b9a1de755d772f6d55a59fb8e9445be5a005dddd1c514801a0e5c8e2020017ba0e5e48e1a52e693a62e8329716498428279f6883fd3a84bc1b1db98f450e6cc30a6b66d0343ea699205c647ef6a9491863b3e43d5160988e31c69888db2e693d547a88b629874b8b975e21e987cd89f84649bc70870d06dc41f4b24550d2368c3e222f1e12302f31ea9cf0300b52bc5c16b46ccb43062787d7a9064e0e32b0064e0e341e47641a0f5abf5dd278281180135824a49c53be9c524e29a79453ca26526e41b65a93201b50b5f65e8c3bf917e3aecbd9933fa3cbd9f33e229f96ef7d9fd65b3e18da30ac7486f2e5ef0dca1fc9971fde42f95ccaa744a82ba8283784bb050de16cf2ad9413269fd22adfce9e1442e8523ea556ce9093d25aadbd93d66aedbdd85e8cbb2e67efb3df57e9fcbaec79dfa7f5fef4de20188623301c8d3827914a2ed6c5a5d2e9523a995e5e60668c9ce268a7cb34cd1798181b1353e98c914fe5d79f9c202fb4b8607232318e91e34a897fba7c185170f9ac2e512345a1e2ec103da87cb8bce0abddeb47561d5056dbbdb5ab44ca58004dd127e12e99e00248d0e0cffd913b4055677fad559b4c80ac430c911d02c03f00eb95e8f225f8638d419714eb2df61451e1fbfa53752aad35dcc12f4615febd7dcfbbf35617b4deac7c516b076b0c608c55893e5f94a0282501c6aaa4cf261708c1aa7ba85c6badcf8caa3f57acdf89a48e71c5355b6c9339148a74413f013f66f4e8527fc2457dac414b6cf549add114b52855ad5596cce1b9dd4b04aa1c53c0c44c2d29a3ca54ad534a1954071229834e2a842c660436e4e5e3ea75d256af94555d5454a95f262e1086c15c489709208a6118f643ab94719398f1304c8794d1252153dd0f4dd59c393f9d3acaea28eb8af6ef0f957191c8541235499f1589ec806ace9c8f1d507d3976401d506601f510c37a0884c5d01536e9211359651f18490d799f131050af75949339f561e0c05d9cb8d4e40e7e0ec4813810079a363f86551d1727d245fd1f1908f7390df96a248561bd568c72a9c99cfa2a237cd42da05edf4619e5e44ef7f55f7dac3f3f21132943ca10480814bae40efefa61930f6429233fe4e4a35bac3eab2c99339339b5c758917455143e1fbfa47356538bd4e4450e023435a68081dabf1f2d4ded1f7da8d25f5004da4bff8925d438fbf7a3b7dfe847e2e8b38881d9bf9fa08d11066cfffe7b184338cd087df41b75827eefc19fa008fa3d148d08f3f77f9d268255f7a04b5a0b4dfa095a848f84f97aee30dfa3f59075ef75288e9bf43b7c92187e057f8b5e06661f3d0545004798ef8dde438dfa4792061d8d5e8fc47084da22fffd1c355e5cdf4fa38ec6fddd4ff006a51d86101cfcf1e23a18a24ed0bf51285c5cd7288ff74e1c2fae03ad0bdab0285c5c7fb9b8d3dc2fa893da60bc9ea8b5d65aeba42c9f1d9de2aa0d858bfb81871f17f7040e8c17081feb3416b324e627c94c064492596cc6dca894524ecf9b95fee852ff0fdf0e8f3ea13505b80513a0746b636e3d9d3e5e75313152628a62723445636e174f29a5b416e3d3eb48a79f65d4ab30211688184dd1d3ab3bd5783efc9aee16119890972b0621af969452ce9c4fb5d350a7ff9d70fa643b3d394939dd4e350fbc21f10431add6f35a443a7d0da3bbba62b0425e3445655a92567b35c8f3e1d7323f419d3e68a3b50a24b384a6a8cc13991a4d5912a9d249caa1cc8fccf9fa7d708378886d81ef2aea2b93c96432994cd669cd73ce392d1e72711777711777711777719dce2e7b9fb65a573af528ffe888c0ddcc3f3a7dd9dde4704744a7dfadba55b7ea56ddaa5b75ab6ed5e9fcf406491f132f8ba743ccece69c73a23e26d8cbe2e9906ff9966ff9966ff9966ff9d64b60141086bd021d749ade37c1289d7ef7d90e05c2d0e9e35df5d7ed15e8200dd3300dd3300dd3300dd330301c8d3827914aa65d45de494e4839b809464dc22dbada7cfd9b73ce69494e48393a7dca4d70474dc22de1ac16cec259380b67e12c9c85b39915692688abe432c39ae931cdc430d39a59c91cfa2fbb8aa40ee3d329a594ba1cd1292d55d129a5d95e0de3a3ad1ebdc0a0d3af5f08ee6ab5a94aa78f3d53904edf5a6badb5d6e5086badb5d696aa28c54ab152ac142bc54ab152ac1463a144364165fe6053c38e9a24f4490e6a0a686668a1cf1923fa9c28987d9233fba686e0efc94249a77f351f8537a8cd7fb4a1d2e9dbeffbbe7e3f0abf07f787aadca686d9b1e77dde8f42707ba871dafafc5a93a4d3af5dd7fd07ee0ef5853439e8f4b1875fa330ea43d1ccd0e9cf7c7393cb37b97c93cb37b97c93cb37b98cbac9757a336344a7a81b158d8f30b957a73fb3b276666567567666656756766665516365cdac7eaa0e05aad96eb85c5dfd74fa32adaa435d2f0a8bc9b46432ad994ceb47a6d5e99f6af36f19c767eeb47a56aa55ebf44faff9b12ce3b3d3cf03a5e6e9d5e9c7dce6cb5c5e71d6a9f5aed4add38f89cd9fe51f0e74aafd0d265773e6fc74fa4fa560722693b5a8fa7d6c85209c57bc75c38ed7097200228407ff818fdf02a7b188d05843d05831599b3116b555d9685b34227cddde467be3000b7c6d0dc70edce8cfcb361c3df0243e0ac11b8e1f1071388200f5372c6c6a6866ba700c410b540ec71550f68613ceef2bcc697f48b7c9e9a886360b8e38230c2f29d1923b2c847499dcb171d1426d72a7067cca923b342f4362726766f426c81d1912511f4b4af4fa2c44db6221dab7114d2525ba8b905edf46b45f23be08e1fb45fb3422ccc7b868197513add7a711edc7986861f832e2e9675e8680a397d9b18d5db9c32edd4fa20932677e8c386332673e8c485f446a12ab4ce6cc27d5b7a26e42af648e6bc75cbada8eb9945ca37632da284646da63a450c63a449fff891eedb06bc7482eb993776cc77a65c09db4da6d456b77eeb2175a94b5303573dba025ce7867b32aebdba6ee33245dbeb53ffa7c91743715f9a8db540ca908ee6ea3d432a577e6b568f5fafa3e38e78320ea36350976a3c6d9b792db8d702cfe237368e0230cab57f0eb6b50bcf93e0d0a8a5db701aa99993640bd7e99dca8240ed7f6247443230040100033180000100a45722048821ccae298e20314000d54823c4e62442a974643a1389ea4208601210622c800028031c0188310537a5200e05270fa7e8e80c2677fbec62ebe59675e27d2c9060ee777b6f49d655d5a2cd80a322181af14d483c53151183a276e9abe88cea310c155a6098925c60217b470c0b446f60be0af1c1ead5aa7a972c434bceacb302993df01b483b915f4048f032d9db42cbf18280b2ff8d2cb460ee7f7835fbd1c6454f2c58ee1755bf328fa91f5746a5abb5d740121c18926fdd4a006d28d17c0eec4a02244658db1eaf73e2fd2b5d80a018c39f990957e649db5b676c5c981f5d1b00f756356cbfaf2d2ff3f42ba53c57a9a29889876e58a3b7a9a06fb08e077e8664fdba7f648ec12ac309a6d23207ee548f9b74ab93620c987df5e66fd637eb6819e69db20be571ed92b15baa62e511f627b37a314076cca2db00185901192a8faa347c7186ec8fe8f15be1b189c8c6b766abd79f95c4ad81a9c721e0a6aff6739c1f2d55ff5aee404a470d6f6f3212079655ae6afa39bc574e14abfedbce12fba7d0726f4c68ee6ed3c2ab55a91d1050f567cf21f3042dc4fd30c612d3a49330fbc61b5fd3ebb6a7d7c4ec0f70e247c646fe81ddafd3a463d6194b178bd417a2fefe359000ffd1f8c054cb4205a7919995c2a897e569836746d2979738915be6c4835cffe63761b3618dc3893e199703c96027e80ae0dd0eeb30683ab199cd124d358feaee0f19cd238b5c4b4b18e8958aef1db0f5fc3600fbee39e046e983a8daa5996661428aeb5c2b9b162c9a30d8bc8200f03f0e25abf6799ebb4707ff77ee2ca3af143e944daf4ef5783a2d35a7ed3f1355a1ed0a34fd5723d7c0e2dd8503506b64894b25903c25a9ac0604351c400108aaf40343307e594b8c5153527146dd9c09fb8331fe91f1ffa3b37519f75f330f5a4716bffa9eb6b571c55d06cf94151d8e73424c26796659caffbe0c97182e6742bf874c4a21fcab206063f42547ad86d6c48c2d986c741680555185fa94a3d068095ef5a221f116905a006b58d37686e066a8105c03e6b349594aff96e00cd2947b9fe9d26aa0993e4c902d0ce40a7361d5f88ef3e8c572ad89877326db663cdecb52e5b2dbf5b8bc7af895cf1309a8b66360068cc8c7220bb12271090106c1896a084ea5784703a2bfba4be658b8d4ec637354c8cb40a0a3b352cea3da2087884eed210783ed16a391161c5f11d3bbbd12ebf3b0ae0034b05376391dd4082a1711792f9099fac7131e1d449d21645a5caa5483fd45b06c827cee0009096f7767cab145a6777f2b59d426ff76e038df045eb7a0407372e8e5108aa5e7215fe4d6979ff67bdd8877e010a85b366b69e8d61254708f6d39bbd189f5f1c4c85836ac57384131c43f4e54e2e198490d85567ebd022cb1622a70312e059f7285aa2bd33132e3ac1b9e431286813893f6819721c9e4810966f0f00b57180ad39e673c0422f1d44f5a35cce9da9a439e43155a0916c5225047eb971897d4df1d5e97f1f668fdc6f8aafcef6db6f608c6998413202f24724852b9772816a17e90c44762083861f120a71e9095490c03da1d9199b428d79c7a5e939c4822248eea4896bb229dcca0700d030173b1aff33f6b779d903ef820d1aa07eba872dd1d5726e00a420bafdf7bfe21c8c7d7a326054b1bff78af3508c69ca0240cdffdf0be4e3301324ca7fd91f7549b06d4262e299e039c23712581b1be92596ff91addd88cecd6c932e5798ef6c54b320aef2e381e695360631857c121bbd0c6fb616857e1417a5e09822c8029d23f3f78273d53c325f13a7abad283287f5e8fef739c39351c564515de9e5f12c1d94a12ceb1b1117808f09c4c7c75a50e3b26c329a3ffbc343cda84f5ce0cc90f65197046f12c947dacdb4ff1eaf3d5980ea0a68d6376062b13394f870e1489c58b3039016dbfc75739a285cecf71d682c1f82b220649d88b743d4a9ce6ed46ea41fe441a6b23199f4ddbbea2fb76fe45164880a05f42e380fc49de82191255b58a8cdfa5892959db13c9db5a020ab8bd2fba5dcec90ce7bc7fae3a1b6837abc6134e73b16178ff41dc9149d4de385f5835bca2f1052476706796893ae3ce0e3a5624974e51e60db91c0a4ed97f596beb188b15732310bb709e0842eaa3c468ad93cf328fc5e8f162cd124e7e736a88867384461b11adcf72a3ec76e09a385c0100fa80f02395d6dc6dbe9c2b7cdc0a5cec0efcfc0afd0c02f47239a465f5b2f8d172e2d1cc5afc358b8fde10a14ffc4cc994b33eb6d9782a8b770693586150b60c715b32be1a8cea4d6ba05c418fd50af16cbd50b38beabd6c66bb85f061a9739237bb6affea971b7f99f46ab714a233597343a331e0dd85cd1e8cd101aa06aa0d975f13c930bcdeb339ae27c221792ef2e33fdb924f9eef21ff73e98693efe5e6f1aef6f1f2cf0fdef7bdb781efbc73fe43428f32cd1ed2457108ce02a7eaa01da9c2de3c573138637b74dc622588a95e2355b649df0e06dc2d6463cd8206c43957d2063b09c910884818f3b30b9d48369dbc018153f1f8b849a1a2360d8398fa0c5f2293a2a9c49a4ff5e0356811828af26f1a1c2288575aa71aa973a9e688255a6928cb6c3fe2b86c1af6e1b5d8a00a39b02c0cd1700b0c6a28c9aacd7fb7a1bfe7fbb58067de9051835ed9bf310e90662cd118893f2526baddcaf942a9e967884b8b71d53460afcb871bd7baecf14ed30f3191d1724cdc840edf0851c09853c1383b57eb6c00981aa6f62f5c99ba00fec83dc0fbaa97c2c932a870b385f819e09b00ad3c1d25d78c006abf70b16861c0decaf73f01c04bb06fdcdfb33a280de04a506a038ee1853a66c89b3e990c088ff53ec58461455edbc96380e29ce74f1ec1b2e9869e36c5d56141af1bfa407e1aa3f14270a90ee6c9ca27eff252c292171faaf302930c031ffdbeed2b49633be8a41701ee1314770c089b5fa2374d8c9692e083b27eff208018edfc3854051c3d6998b12462376203fe8edd121b767f561681ad7f4c4090de88c24c25994dc0edd9e53edc48de104efce122dcecc00907a32cccddfc2edcfeba92157e42a44fa304eaeea01261747fcacb40d0e42b328ece91e1a760048adfff5160db0449a3ebaa1554c39a63ef03d1355b25b786c91f5c2446ff556a033a3793ff64c03cf0fc870cc1ab3d00ac8acb836693206e110b71e2566fe53e8aad1646a1b411aafd7ec9db776c13e54e0225c2f2018f504e658bdf609cb4c83473269825efe402b62f2690c7effbdc8ddccc7c48dc825892c7e5b3a51bdce92a3780986455fdecd0df37a3fef9c301875de23c9db84b908bf51503477c20f394332fdd01048160c57bf7029cd22c40e6c1f01cef3fbff41f9c2cf9b973a5d085c5213990c4be4b3c2755ed9a076f11061929cdcdcac8f50908302d20ffd45c85961aabbe4673f82bd87e517de8f3035a017218f8d2179f6084ef12fa52121e7859364d4a98df8c1361fe8383558f61034861177b7977993115b7c04f883554d411972fcbde89eae165158203c7ea201cbe8ae2453f250ad30eded01e01902111f58ace513a875f4e1cd0eb6f91d2c30cb0deb1e374e9687eb0b0f83a3490949039744f3f60390c76ac26acb190b1b295cf220f7099eae56200ea95b72eae3085ae27e8c8d7f0b05bca2da86550d7fc8807afea00aaad9d7d1f6964a146dabb0fe7d1eacc90d7d6bcb7001e7628346d39677343b485e29c84f10098fc7937df8a27a4c013d00d7e0b033de1458f197fe3cdafc214a066d84d0e2c6c7cd2fd4cbd81c7e818159b17ff4d484c4171ce7aacb5a33a08cac5f4d674b6bf1b8a081825c4af590e24aa2df4917a3cb5634288fa904fd6a2c0b40b1556a75749457fdebbf90a0b25899a2538af0d76486f09b812b89972d077c4d263230418f40d9628962bad6c83c237f65fe330fb3f6352bea3e9189d638891c2391add22a78a5378bb9a0ed084bbe3ad91a402969a5e29ec5aa173054c37ab01d945a9d30c5a6506bf47623977f003d22e2b7a3c64ec0c6e3353366107659c962c0be82ca998500374c5eb4f48fa226585810a7373738cc6ba8528142af23c702d77029018ca2010ebbcf4be8db0886705c40d06ee340b02cc8d4cf9eaef81890202dc0d263952c3d467242ffc758931870ec74285bae146ca585dc74b08c2b907c20811f6c94dc6bf8b8d831f34d7a07ac2a82c90ac5ac44502d43a2b26bc4b79272b63fbc6a89a04b24abb6227a1bfbd8253e734f234920107449b7df7bc7b28c548dd886ce503998c892e0ee61adff93bbc8fb830774d93dd5eebd19e44c0f729991b4c0a3ee171e912a036895fdd572d6f68957d1c17b7f17ad56e52774fe257fd7f19379643294340454685abc14d7e77e00a3529cf248132be184fbf5ab1dcd7e12519e0ed5d460bc370af095b62e802a4854ebb3ddd3884b87f9eb96f2a1f31cfa15d682ccdf54f5f79aaef81402f28344ec8b1f5cfa6de6456be8c4afa28afa64949e0e329af46173a52eb3cf6f54c48c867a99e4041ee10866b6f543b6e90c5c914d694c3547a72ab13552c6d76878954dedaf147d2efb0022e7e9b32de3d57d1725594a2562d69a18c74c52f0fbb701ce03b400f111061faf0584929db9fb1e2f4f56822d050d6d591f94e799b79128a4637c925d8b0821950a23124ea4bf876304a9b602d09fb50735928bbe769ec1b33418d3cea80dbacd3a7b9438ba3b5895de09cd3fb97a8cc8ba3f7b3647e38d7f8f45bca24017ea9a46a4b5b3dcc423c42f961cb607034544a935a98f801f2a712b400ea3cb8f0d0e0fccd4e874e4688931225962dfd637d7c8cb6cbacc2476ae4ba73d3a13e00bb283795778d7b35da275f1cf4d6a73a21ac452d9ba48e2da8cbfc7379f4283bb02e5224bd4cd71284c43a9eddaf894a96aac4ad0a29dac503c1f70994e2594fa2e1853873938486332370c88291607e0c3422d1b95d117ce933ae32c7133c42e753f77e4e77ea5396a172dbaa4ec840bb2a042e62ea4e99925f9462c23515acddb481b5a8b9194cdfba16d8db2455992e7b694e60ce1a52b277c6402b3a15746ade52ef0c3a31a1ab6b0ed1a9600deb8973dd3901f59c1a259e20031f0f49cc00c8230f127a4e3857cdb9b5583b4d5aa56e0ce96b1ad81f479ece93ebcd0b2015d57ef7007b49daa55119433e03ba1b77cb9580c2bf3c0d32adef9430d4062ba5c18ba60f6440633c11059682369d1a18c0d7a8760f2979975ee44f00fd92642d5e6f8e94ce0f6ef7abc97decf2a4e207046bf815770a725fd204caf1ec6741f71a2782eb8029aff7ffabf1020fac1726b778622c9ebb7cbdb3fbf2a9ca3cbf2d06d8fd5e314cc9d9e4500276dcb1009645830d4cc494235bdbed99ab5e959ead620924f3ebf02ba95e0a6cf9f77885e7fcb42b926ef91f9769c9245f98317f0770033408ad75d8c3ebb14a83a33546774fd0c511cfc352837287931d68f6b510d8cbc5c37ddcce7445c66e2b3fe09f3c85de509eb811728051ea5cbfe7a46e64808db20d24f0ee070e511fb660c41d4df95914f5c5086b1a4beead8cf682caee7245f30725b08f133a29b7ce89e9427812499e9e676b00cad5359a6266522d29807df87817237a722f309b4f478841ce682245ea6b36243512e47380fc437c59b6bac530b7b215e4190f63a434629637b0ca57ce0fd14899d10a7aa196c13d2aa7a9dcabbde602454669cf1086723d7841a3195cc4e35c261c0f619cd032fbe5c0f61c3eb37c677fadf7e46db61d3f4d87b20441d5d6db8db82ac432f7430a212c4bf1a8e3563173d867f389cba63a41530033f6b8046fe8b15236c63bada713b83d3b6a7e75e0fdd7a6afb217caf66ff39acb4f30087690bcfb676af68506bc7c0060f32ef43e849980bc8721b4238cc80e947374b4f49c6d703798d3f38cc46b0a53a45cc7da06706155c53c64b5fd0e08e3e85ca3838ef984adbeaeefb83907dfcd004e214650d44bf02726dcc69c5439e3ae2063e86ca8f4d1c88539035e8c58e2f73f20d4eae11b0d914b4f9eb53a5d59f872d08a240ce5ce39a51d2b677de4e1dff1f34563426d6378f550b5d3f4363978fbaf042b17107c531e4149d21777722405d4fe3763328b6c1c6d661099913312bd4817da3ffa58b0db09553df6021cdc385c1149104d8db5735664930e227960f47c42ab91e624c90ab94361a7aa6ab876a902cb3c7fbca79f835f0b9b0d0839ab33a76c386d5f2b3d596d01e145bdbe5c2814c0ef7bdf3f2fbb95787ccf8de2cdb3fad189ee16b7b94a4f42218ea3c4cc50f843df01a37e664de5573044199afcf6e51113c70f5224604e9118e5e553845fa08222ee793fd90610b978cb66621bcc266339252d426abc753ee185dba7494d2140d2c9ba3dea184d991ff3f4b99e02cc0201d71022a0c0bf613d260980400e7963e92c7955de9fe09fcc3c47a7fa9d5e5e9386ae776ce90a19ff5d13074ed40361f36af3f1eee88fcdee02d393fd73a17c6b7340ba6219e341d7522080e767bd09c26ac3ca67d37b6d05b40264dc047932d710072691e778d55538e0d0f0438348da347649edcb6093c8ac6581867680d958d564a11ffd05343edc85fe72ad62e92f5e9c38de1f939705ad8dbfc43b22eb259d0e423d5325a761635e8e058a7673c9129da4d40b971609fbcc09028f322b6461ec925a8a19f385f221b5d37479b394eaa4d6814745f156e6737fd32373338a263d9ccea1b2dc9916601a0a36ab2c1bc4dca45fb3420b53418066326ae879a822815fddeb5bc8b6961a58f4ae7b98fe30476497903390d4dd8743efa440227653b61a5187d23c8cfb849e1f9d1fc9bf710f86c04f89b6f293e339a2ff326851323f9356f53787eb457b5db7b6502fea06650eb269b0feab7809745278d30ac8188ce3067d87296b0da48788f1812457ebc6d0fb64ae54be18d7bcd0c9b30fbc6bd016747f86dde9bf8e408eb366d97f0e9687e0d36133b1fcddf6c37e1f911fe1ab7263a3fea3acd9b257e3a42a63260ec1a02367ef5b394b6b98559308c93877ebf7b196c48f6422d1f70eddf426ee7f73217c1788a53fe890231f4e247698589711c8b09aaf1dbf411bd2bd84063c6c41367a4d0a8e1404e4cf1a27115344d6f8bea47668d50cf7634cdad52bbeadc950a59bb79a67f0974281f393a880f8a5ab2bf29cb0195864512bf619b05946c86059a405de35a8eab4cf13f5bfc689e5bdcdfbec5ed447a8d859b178fbbad5e57c17cb13b343a68e28d787fc3b181bcee88e3de501c46be487f32db0d4ddf01af8206d23ae9b6d590251ad8426ee4ca0689c5a174ece3e01af22a483d4251bd4a1596e932643ac510553aefab9e6d261a58f50e8f8388576589b9dad35e887c5e55ef8bdad5675778adbbc35d3c43481d3eeaf4a3f0bbabee9b4622a6708bf23d3f9d12e4be2d39327e7e6c44cd9a174ed154db57357a5b07a1e1252628dc5c8a9ced72827b645f8e9f5d1da4c5254c0794003fd81d0057052aac5a5a8d0a70be94d15c379fc30ba02abc9592e60b371f96395cab82de984194ea79e646f5d955eb1854de2f52690e219ca1dea377298058de9969b6e0d276c9c095c3599571cd0a5fa7e666b3b62e10c7832d04d93df8d03663ef241376c1a1543298298773cc63e5056de40ac1710c22b9a41674266817e19a344872857af6eac0398e197bd4db3e315c5619c4076ae5237c9f190c4349fe1e97c57a45bf34b9139c6a366236d2f8e7b1108b4c2ddc82b83a5197bd48828eb7d36edc96a9e22d2b8c1262c6e635224254412a82694a47c8e310942a8c913dc6ed421eac6e34336c3a18c111d51437123345ac7a9f2a6b70d2e896226a2b2268703335579eed396935d7c8ad5cc969ab4a540aa0182216d41a0b9171640e4173db8c87b191d8758ac1a91eb2663b9a643ec6bc9411f33d083415f03b3ed9967e55b94edde2319f580e831b5825449c42dbc3991882b20f79b81ffe545116338b064cd1ffeadc022a26354f75d0687ae530cb86ee49dfc3fb54898d55bb20e007d44be5f9cae43ab7db2f65ba3b8fc7334c3314c4801a7a02ca75592c602207d4387c8f7e8c6e98bc8ab0a17fde046c0022fe21baf48744e074b2a749e8dc27538270cc79a9a098050a56284399e597e735dc11e02bda1c2800242edfe5bcae1552636885ca095af48c1c617d9c4772398c0afd2f315d690cb6d21288a48c0407ca485ec284ccf69dad973098fc72f314b3738637cf0770972c0bd53fa88c178c229c0a805c32f8c95cf0f11405c11ab6d1f4f83e711878dceb5c9af4f9f5a41c88e74d162ce3e98d0bfac5884d1941d72cc1f0e8dfe247a93679f0939e6a11a1f6b2cdbe7660032407137397209a0ad2147171dab3fa012a7107f9de6b07c031cc663c0caabfa337ced3498580b4603afdf71bf3f70c048236f981d85ee9d383a449e6887f76c52f92ab7c30ffe9aa8727129b9b1e2ea46b8b410b6d0dc8b2e9870c98f1c860ed5cb753ad71f9a81d546effc9c3a549670f0e95b63280273db04c6c1a00f39251126479c90385462374c70e32aeb3a0d6e021d444208379c21c0c1ca5af16cad828c0b1afe6e3fac92991b7da667689df78687ee1fe869cb2566bb4d36f5498f5f98921ea76b1c6e232e87a6ba5c761e8b658e47095fa3e82e1ae4a764b4eb99b3bf2b6b326c3e9c946dd8e75d129f231baf965a8c6988784c54f647a1744b409c174dfdd13203df429173636143ec96d60e4d582611734da1de7472368709516357c9bb3c8c0d77f405458ed6ce5c5ff2f91e1810a55f6534853f1973d00bba6bc70d5759959dcdd40686a84e38bb2d7a85b3f316b8e96e1a92ca76d5815abbe2bb7c92ce65356830ac69383358e3fc9f4278a326416bdf0c7d623085e8361d29f3df274bb1e694e05b0b58547f78cc573010fcd0fe14732280cf525138c3bafc1327b081c5abae6c61059c2761aaba30ccbe355cc8cce21937998056ed2221ee3dea395ee1d297c692338cc1b8185af9b8647205b46665524ee2ce0e04ca32997e1e7b45c1663a0cf4bb716cb39d6d162466f045b6450272de81136a29e653d5d92e597d0884ebb18a48402a4427fa7c82d09767ef42e1ab893db00015340af28ca17c40ad047ef549a6087053811cb5f709426545277efaee8e3c1e5c750f00b12ea9e0b8e953633511523965e98ec4390839fe0f4d856f95028223948e68e1d0a0988f3391e451b6e72dffc698692c6b86b219333d615d985e58cb3c99b1d438fad26b81f0967942bf466efd37a30150fb908bb0aa8ab6b9fc63dfc0bc66e4b9b3fd88bb5c9224efb6aabfcf63ba9a10356559e5c0c82c595404e475a767ae7df76a5b39ae0f6d8a721b3f0bde1ddbdf11867034ba415cbd7c140d61e54c04b11c1ed8abb4930b092c228900ecc43dad0c984e385a708fd316af6b193c797ab9200b88fd3ed906857282ee16768707f49ad68b698b37afa56e8533c399771a97f8a3d9f28b580317586d5ed1a991d29dd56506b69f0e8554950236a2989e97596149d5d833468b364bad02b47fcdce20d73d82cc93bf1441e0e7ef008980f2cf051421e082773584735650714ce910e8dcedfdea858438d2c4003b323362bd360a8371a889dde3996c2ff233d1c1838dc7f6fa8fda393f1cf15498bcd74409371df30bb2e706bd860d755391c44a98ceff2ee21e690553006d810b2bfec68e80c52e09b6dfc46bb9f80cbf09bad22434d7c6fbdedbabcfce95d91036374218301b2c07f9cf3150a97f364c1a2ba3ef7daabb0338181ee681d2c0f3055c15ee45d8a25fc2051daf65fb00037eeb2b9be4ab68803c7716e9a47c3601d02bb67661e0c3961454f8d37e9650c6b2b4c68c0e3a8b9a2ffd8e6b40a04c3d0a3661121f0e6c438867ea834089b6ef49d70d45aa984203c35c84f48020077ba56ca048a829150d3bf160915cad7fe67c79356481393313bc82b88bcc11552bc3446689927f6a6801710112a6bd91cee9af927bc89863b7ec7b619457d65db2e3a31b0a63b3b4be715cce72a8b4b18bc34869f5dac1ecb2e04942bbf48db9d3387c71adbfb08b243dde20b524618850d0a9d17a32eb3af16b76215ffb72d92b10fc2630346a6eba116071f6e9ce600347f1d045f7e7a8b0c1073f6a346868823bf0e491d3c07dfdbe68c380fd9026119850e3f876d04495ba325c586e3d359fbf5aa34ee71b2ba2fde80cd3498270c7a1dac554638931f332778d240ddda4ad16c9b1f96671f22fbc8235e1313d056eaec5368ea1ec0783e867a17705cdaf35b79515a92a693a28976f0191f17d709e0ecfc761e439ceafc57658ddaf7ce58539d479f48a6d23a5e77a671d9cb0d2dc2b05599d152b2f72d1c7ac35e678b07afc2127aa35c512cb840e7ae127eadaeac5ad4a9554816390ac37d40ed790d61765c12a80ae1ee3f62291174d251a10232f566beb6fc7dcb481f8862c5b080384a31948fbeda400ff8583dfa54b887d1706d871ee552b29029c30e09efb42bfd2871104e545be2362693e64a4e8f8a07f5166d566b688ef12db3a81559ad12122d6b1ccdf7338ae056a9a90956edcd017d73048a8a1b64b069c7e1bf3f3695119e0e8d0623a7007bc539909d70b2edb4fc93e4ad5776bce1e74bfc5dbdd90dd599ff7d76bdb5a7b728e049da33f4191e88f6a3604cf9c2b0c83a6e5e4a026d97983e8b285d0d44c999a5d22a81d2de5b0fbda4c19d934e0c9925efba567bf4a2d461f08e9efb89140a9d9e38e0578b817b82f6c772d1cb0faec87d7248d2f7fad843e4ca194115ba8aea328a46ccab7270385793f3a63475e82aa1ebea6c966b127173e4d0e0566f8059cd78ada63247d9e1f5c2a8d806405c24f21b505504a5e89f4f8b2529c16eb31acc68a944e92e4366353d14643bf300b191537445183000d2050c7db6d9ba9be181c4311813d03c236af9f890e7bd41f2a7280e1ae5e1b2f025798bd66e86d26ab91a375a5cbf17ed8adc575db3fbb15bf728ca10f451652d6628dde5681c7dc54530efa3264d0b028ec0a34ec5c0bf54fec73c3fae13d8a0b93964b4a5bb6bdbef548d2a2f4f1e41ae9bd1282baf829e60889b83aca3213b2f0a61b6fe86be87f53f788219be715e7905c014ebc1ee4067519101b01848770991bda4527ea5d2c989af00b55b292578565aa6ba2be08a4fc827adbec51e5b78597ab6605fd64efecbce6299aa19d7177b5e07122e666cb5d2fc07a04189a1ec8093dcd5436be325904d534b3e1b5ef31b636b347864aeb6edeb124712d90af504e2e3dc3ce2fa1d085e0ad4b3c82cad8ab2164b2ce8d3bb2a853ae880eeae13bd62e54f43b6de67e7feef030ff6fe21c9c4568927ef53127e8e632002a42a99b3fecde1ac2272e9bfe0daba8d6fb98dd3ee4481cb386aa5ade7b84a93138ad2cb666b55a7a6c93daeea4b086aef010edf41153ef5fd6f167d4f7b437a0c075811f82ec02df3b77cb3b3e7ddb9d055cd4b898153090893bf578a4c89a71d9d31e61ebb3a2c54489793d4330da9e4f87645be036026990485961a4b23c388e491b9747094527812719ec47eb5c1a04a5445d94e2be444ac5b1d932de78287924f990a6d17257550032dd21062c63d3dade0ab97f4e12fb34958178c827aac2e9ba41826760ca2624f38b19f5c035de48559f3c73b1aa13ef27c3c050046c5f6a76917649d3e47372b93d3ca9bb03daac4696da74b0bfa62070e888b6aaf3917cc47a7fb01e522136f79d7bab484f5e1023408460c2c924acf78f64e6ae06150648042cc146d3864189ce7523882c0083111ef5f317aa56e0fbacfbbd6d212dce3a13e45945e482f57528d5d8a1934bce78019e33845f0c0b98f98ea06b8ad7ec4915376cca0cd08a8281c365e41a8fe293cd32cdcc126d13eac2734a567df0faa8479b74030779fb77719ce3b6730c488213ab4adb059a807c8c076ba56be0b29f6d55186135e8773e3d6161d0542ee1ef3734f9a7160a4c3292e58f80bc6a507154e1daa4b62487b18029177acb388e2a5c74970e721c8650e2b6760211ec0c8be602b6ccb01cab26fe00ce6413c44b87186cf3158c50c0ff2472a3421919d67c3329dd92e1ffbed465209df0200c0311126e18790070ed44e35f8d7f79f069e1fbf585f5cd7ffbb4a0ac75261074eaf2d4ca0e03132b511da69ecd049af5c9ebb1b22783afe1d2b4761d753f4f2d701574bf4ede3e3db0e6ffe493c135b4186637e27497ecf119fd4701047162f3e33142d64bc27e40d004b4296baa84c57650f18c833c49ec3d8b56b21064fc1251b369c27143dc174ff1cc94b4e109bd01aba1610a2280f321c931e7b6cc281fc34145df213015d5defc20a51d292a712410d5b6fd75d44f862a17fe3d0eed57b7d3967dd58fb248d800342efc150e38995f7c07416fe43ef41ba485a860b91d2753e1b6cbd671a76cbd6eb42804eec9f1212ac780803ce7cd1ec03d1374772e77e559c2d1efd4640b61fff68eb1a360af8bc8d028a070bfa080feb5b9205f0f4b85260a832a560ae181ff26cd50b584c1923720b5c425d8d21a1e0e04e43916a917f25048d2b140d6da0e74e74bcd3530c7acf707d75f4ee7cdbbb45ac8b40646779d16c8aa4b32fad7d1f748c5f623ec9641f7d835554845c011340cbdc16d6a99a683e2b4f93e828fbe0b92d7bc661b5b5512bce099afe29410582a8ea692c5aa45bb2ea6ff51cad86f4d8382be85c8442c028ca5b2285d47dc9f06f91aee102a4866b49899a234607c49f4386627d708ecfda3cde32762ab3caecc72d81791634d26c53e8fb2e025813ed3af28135207ba5b67da9f15f4a04f02133ccb3dd2143c5f10cdf44f61248551f2416b79ec5a0a79d03dbd268d6ac9dceab75e8f3c9aa550f726756eeff692dc16df757130493dbc5787b0f448315cff5fb3dac75b211e7967d6f94d596ba9f4d2842be55899019949cce4091c9153e4f451fd7be2bc41a35b3b5da9bd01da9ab17dbd081fea7329c5fb06127a507dcf790d06eb1ba9bd80f32e995238287cb353c957fe34e5e293880373d8565655d18e8ef47fa197211915cd43ca402ab115a4332723f3c00e55ec8196662c438b3618b3116ea674fce011cafd3187f64536c152675132ba954c0427a5cb20e6d382f088b13c8c39aa1da0d43aad8f100ae1b1efb9d11b5c72cc1357501c035c65a8c6ad62fa9cdb03e4816c2d80a0e39b07ef558d133215ec8d701787d54a8e9818eb8896541600859b6bebb7ee0925e6038f124546e848e1b3c1c706bad63c1299161f59958f2193ccc8334f239598db629a3476a3f34cf20e373380e6d871e12f29d76c746a0a56269da715b835b6c903a44812703a739633541e2b809c327283ef1944e2e91be6cff93138277a3a8eb5a4a272296b08e2c538eb7f6223fc85f261162ef20673dcf0e66f439b37cc77300b7c77a0f85acd3a96621137c0bd8888a823aab48327a0dd2612742732e4c7644987a048405a779c3e45c9c1fc93f4c4a84d4c926164b07e7d087ad9e6417e13961998c9d2ef612a54f620b28e96b4bc79088f4b4244426d330f0ce4c66e0f3758f517913de4820e671f7648d7730909d774276ff2250ba3db6b74150ed51b393ae91d1799adb04c9c98098d3f003e46b71d1e7c1dd21045c8351f564db58802cf40969b6c2528b7b38c4ecadf8aaa43e2cb05193f1a47c76855a8f544c42389c54df6cd9be3575a0654c27c727846adf29969a7e18da2d4503af279fda66eac08ff4a8293b42f740cda53fd063bc061706ca2e23a9432ec500fffa326d24aebdf1624d0b58ccbe6155dad4de6bdd505cfcb8a8abe3337216572b615bda9131da239540c80f047e88b20c7c3289c804a0d70b9846048b0a583af7e6349e846b95316b5c8b6e93811b803fcc5c0935593a162d39006924516cf4251a5ceb7815d19b90db71ec7ad00e1e1af711f3b458829d5e340dfaf218d9c9934cf764f7517ef53c556b2e83ed005724ce29ec43b05a055ef1e3767ce1c4c6316d84e0047d3b0abd489817e606c124b777fe7036ce1f0877e1c24e5bcae70def3a028a140615988749dfd71b0522eaae66e1a17660e362d196aba3cd2e38e589483528e0e35ee83295637752a79a2888e614c21fb4d33224d169880cf34e4d8f8c5d9da900d823d81505acfb5e7274310487b1b04f2b668c7782d5bce4ac8cb6073a21850ad74efc9f4403cd903f738bce5cf53a4c538410f332cd20141bad2c7a63a436ed00ffeadb56baebe926d9c7755e4fd0e6118ad09dbc7ef86d89ee6a525009534e09234ea184e30ed97664b828b4a11248be0b7b4e17fc1a1d116a280a0f98780b2205b9d057d8e61a7a40e484607058e8beb2be6bd59eb3843df39e22982450d0aab1d9a6b3ae619a55a1ad181ef625ef7fc6d17f1dc5c032a028a4e81be9416fb3d0e97891a75b36d7fcf16700a6bd0b516b3f47aa59d1e98c916fd66e3ba234dc8870da67cdf09f5a69cb97061dfbbdee276a6bd3686721f63c1ef3840dbee8fb742a5f1297b9e84d95b1a40a3bb87d45c6e467f226a373a1750a6e1de029f7263b67750b46e6e480dc4d75502ca053b142c8987ee4fb4dce60276606cad44973626904686a320e60c1dbb0a90a9c65ff7b565b73e37d0a9572f7399b236633e56422be904998be621058a17b54372c9f456b525b142a3ec1e64e6376f5ba2f0dec28c6eaee2d37a62741cc279402a3def544acf836feb9bf3c9656a22fd31a943b336e4a94978688224595343a64e4835ce596a6d4702609cedc5eef877aa2d85ca49790c4cc017713c2c8cda9a46d52283964ea55083066a0401dec7844bc710faa1d6494f68ff5560fff51918013bda585a2c37850f29455e4aae86d677f56fab13248eecb81f3f34d1ef08b1a18fc0ae623387f4b78afb9080a418806f0aa180cce1967a0869471d9bc08289469220586b558c533c765d15566a463e051e0c13bc72978aa8027414d40eebf458afa280e7263282f39784b79dbbfacc889d0e663117364f131138e123d024b1873dc33a65b48ea8c94a3119313f61eec03d43bdda613cab46a96e850b8bc0777c7cccd7b94f2c04779286321a8885668f61d12c50127a6a4302fec3bf2ec2972967d0f424fed0504720a56d791e6e44a0a1fb3533ce6997b627b90b0a4e848390d871e5fba07cbae02d38e19a922705a6aa99ab36d9788601126a3e0e104507aaae74ba747fbb7101c1a88e9ef00de3438f65459da316355188648257e588d79701187b030cd608b2a980d484d7ea89af9405ae2f37c7a9e9e63f2700f51c2406ee955a61ac66725795ccd302435f9e16a868312131eacaa62ff5b32c7dd69390a708c1333da325d1a8620551d38d0b9fe0debd22a0ce2bcc4d22f491cbf6a6b3bfbdad2062db60049b39dd9c62f91dd757c77d00651a90e38ed1ab2aefad080ec87b431be9b5b6d09a40680fba4133423498eb2fc530a24a1e828e7f8c3856d0c1cb07e2737fdd2ab5550a293ab374ca41d64826bc0c8b4b477276658636dadafd9a73b4cd095b3b5214706ad97e1c4d8350cdbf7acfc8dfc2d4c70906828de26d85bbd32e4a99040bfc4aea816f6222c6cd0dea0007b5a91820061d3d44bf051a3bc03c56e3ebb50846e29adcb3114b2fdb5f6a3a4000316508719091dea7b366de2e1a2cf543906da74e51c7c8c14c9a81ae1e556a24a656e2b6a3d0d4374ff511d4ec436b5a9b1251b8e53e9ac39646c3aac5fc27f6e3dbc99bcd413d556c5ba54e406565d7512679e3aebe4870431c8e6ca09653580c587afd96956e7acbcfac96778e7f183a507426ab5fc5f35f42a638a012b15ef76940410662a4fbdfa6ed81247a15849ca2d1741362db8ad900617cf63581fa173160a0c78f1ff10a856dd4affeb9b99eb66e3bd378dfe0825ab38093886d274965dcb4d94399ee899ec23e206f8723f68c38d264a069a5cc4ab6d3a8d47daa636289f03cda5477a98651bf6bf689df5c11b958350ff3761257c447b789e5c9e5dc29503890d6e7ec895ed1e6101b7c1d2043012e4c209ef01547dd4751ac3293fa75d2be32b7670c90c42e822184a4b91f2cb74564b8a86ffdb91455fe27eecf9c6ee20b435354824336072324b15e9ba6220133cd98f7bb81e09175bc3adb702908f7c3f43727e8f5e96e8eb891d292787efb0b92150d91b65453badd30d4916da3c5478d7487de8a549fee67fbd8f4f7c68fa38e2b378b7af023b4c93bc704da9901ff5eb6b9f087f7e9bba9d6e9defd5b7d72097eeb19fe6555cdbc21b4348de6b46d535ef429450555fa596f8ac4e162da4067a5e46fb071519ad062eae111cacf8840c3241fa2d218dd0e0b6432399aa35bebc815a427523b19f8be802463b9e3c1b5c0b12ce88ca8198774b3915d917c1c35f1e1cebb69d574bc928733e5efa15d77904d028923d2ce30eb3e98ed9d847e550b5189c2e26f47da8775e55bd478d5e1d919389a2a3c4458e1682971cfaf88167cb45b98d8ae0bb1d8fdabebbabade5b08705f1c20932c997497239270fd927068852c9a5541f9cea7ece8d5beb66f907f24c815a70ce90fa17e61dde439b148a4b0beb7299bc5ad31e5d2c89c526261b6285a765c97979484a421229eb423ac6d9c8406f121e0806332241aaa1490591b9d86210095d1d3058ec098985b4ded20d909f025f59187dc22a96b15d230cb950b9486e013ba82f086b8f2841c21d1540af33b05817b8f7342f089622430f20abd5052726e482f73207e9c935c4018318890a50bb86992b03a87b11bcbdafe0f74603d3f71ef46146b7df1b79bfa1f769e39d79158fc779e014d5fce8a71fc495751180d6fc3c1a315376c603301b08cd7a25305368c0c08baccf039fc322b1140b7970e944439ba4a3bd2cab682cb6e18c85c14413020860f2c8f663e87b6909703605ff65014d9e5d4c031815819285a43026bd22a219dc5fa9947e10abac4495b6bef289c32c5a03c71d657f337e079a7c381b171cdbf7f5ded08aadd9b5f11df14b7dc9fb9a532b3e7152e058df74fde3a7265ab8a04e6a5ff702af2871098220f5e4236dce5e30960cc58642a4cee43f6ed32dedaec4b698d0c8a50f6e976c017b43c041d35f37f37e736f7b8bbabcb57415127ba8c94b34b513a55c5015377ac5155d7347010c17f648414c8751d0647c5ed76862af0bd27316db494be875ff84ca881a16d0279fe82736d158342a1b0b9562d2cbde0a795d43055088d293cce97376d1a068249bb13908c391260490c1e717128e338dbfdfe89d8dde8aad40e6410d401fa6734f12c4107dae874457dc502b6ea88a1bbae28a1a10df21074533074735ee7d3d14ed7dac7d72cf9088bcc0dd16325f981d9def8bea198576324c8ee50e2bbd9403864804603846c35d8e8e00431a50624063250399be19df34a4610c992e40d8e8cdcd9e6d88a5e90006704ddea5170c30bd9889c9842e9953c4cddcd26c89444701df9b36f076536f68feb2706418b982f591d45fd200a070d38cbd7c0c9a718f611980636826730c1e06e405aead04ff6db104552e59727880bf0e59da419e0d9a9b36d9c3011b4f18e46027255c9340d857b00b18310f0f8e9ead89325f55d0b13664d28c7d26919d11fb63d8f1056e5754aea4dc9e112c9bea1f3981a4c1c2b3e5241c4d3bfb2e711228868f269f99f4e7addfb645b308a73e9e527702c423acb6aa7b2742e821bacf9262dedb7bf29e3b2f2210c52d16939c196d4261f295cabba915330dbc2ad6f1f0b2810e11e7848fc26c61e76492ca99a7cf89304543f87ea347866e6290d4f8609c7beb8abc1df2622934e3222df96b5f5ce3c4440f01b259ad798b86406d171337ac85d8da428c6f11735c89856eb2c50e363d791359782f6e60125f547a0e50ab529473c974019ccbfcc0b858ce85ca9a2582502361f9e4a08f340c5012b6e9012a037906ba2fdbd69b3f91514bf2b2338da2b4945ccc0f291557eb4f7010986a075a939aaf599800de2159c58a14e70889d7dc36e083db0bef1e132f24fbd84503e24d618507026b55e443e0438dc77ff8f23f70446f0099b5e6ef45674acd309a3b513d0ee2db26bd8ba1915e26d7f504e7884eaf2f1d04e383a473693b2823ad03e66d3e3b5e8bc7378710dfd933a7aa60caed7264aedf60b6e506658feb8977a9a78423bc5ef2091496f2fb86d2343f8cf448be53f9e1475e539e331a129e32f68ad30e1b2d76c3508f5a1e9056d064a307bc1d64a22ab8806559a63272c7b3df9aead48dbbbe1c7200e67750ce550b392d1dab0f40c2246417e6ebc2ea115db3f17cab9899d96e100478e073adb98442c1bc5ff4ac59645e6d1fa508ef836fd1d31bb51c52df427a8eacb4270feb3b697dc5b165e697396ba1b1f12422bb6c9261298e004c12bf11f35b575b41abd59b049954ec55fc35c318ce519a570729a30306faabc0efb848e8735b0e581a85e82316d70e014e39727322f3188f5992f70049a4b037e78018c6eb97a201e515818d41cdf0218abc7b9399d8744c01e791b954b374adeee97f14c0a61203d2ef22ef0bf11691bee9c278361dba8073a4a6d2414052076dbbdb55b72b840f1766a775cbe4e36e9192bdc46a844b1710b008d1adb0104100bfa90dbeee87c91e3e51a2a57b1bb5127c2c341cc62cd2a2b976578c882b09d64ed311e155b8198a03a6042fa423a1814d92a57a9b813c64fa918cc7a4508ff9854e3613d55b57021213bc933b01e036c2840c98c02b7fa712d7415a5b1cbe5778f3329d4b2ce2effb04d35da7f74d98d3214b949ed4e8c0546fd925439dd5d76ae89101f1aa8843fa5f29a0b7f82aeead46d24a9a8f579e1d67f1c7d833792b5ec7f661a3476739c924b664930c566d3a7ca31ad0426e0df52859010744b2180e51b2e8190c6fa5c302b7fe3519a3b5b2cffb51d691cb3cc5b26abee13648e2a2c07a43aa82894a1be5b27e6ff0a3d18e1b945e9cc9762dd56b094a62efc45b233585f6b71f282788dc8a238b3de37474aa632ed9017aa8155eb7b7b006d8dc9715ba47cb735649a8b3787243ff8b03990831572de84d199505a0d82059635952065fbfb21b23b32be4f935252d7313502788c57080588749ab69a2d103de449fc0167facd6462c4d7ca3da2fe4574a4361d9042516e3f3be1ed3ef675ee34b0add99b35de0ce9dd28bff02431391667211626cee007a0f2b319d3fb06e000c11be064cf413f37123b90b543603ba4552735f50d415a70d9ebe079c5a6104e73715ea0d31fbf21551660ec8548f2dfb44f41f523b7b03af2bdfb224581f3674b75f23b48c01cdfc9c028843c8c477fbb8bf6c40cdb82d858a7bf11ddf8b8e2999310f44ff81ff641342441289eceeeede01ee0667070b072e2e534697faf5009ca0d4afeb14adaadc87f03d0e37a5904e0e425e618c73c618e3ced426f23823a516c298fbf53be159c494d29bc54a29a594520c537c2ddc74c7bae74a8a665a7884c0e1d317b419b3a84c8abc8adf09cfab49a37b248c7c95fdae7934cfec21858b77cc798648918c5b05a5f2e2f24352044117f54fd01101f91e5cb6e868b141c70c2a5370f92a2f95262a417266ce93a63fa88231f6cbabdcca489048515e4991443da1bbe659758be21922677a94903393c2161e0b45a63fbfd687f1619cd364b549a6878e7352200ef50c32b44be2803f7735c0090345f1050861b4ac79fefc39fbfcdbd378f182f1c780ed5e5b1c7bbceb6ac2c4d7368d1778f7bae2d8cb2c633a1a7318e72723849e3228d0113f7d22b45d8df0a8334977c8f47307655aa03be5b10ab8a5ac16c36e2874afd6186b5dabbdb86e31aeb5d7f3f03fc6a110868542d65efc22299d1836b3ff39af054aa58c4f9eb1b86709befcbbdd40fae2c27dfbd8de34f8dd4a554aec665abcd9502c66114a4e4729e54ba96d2fdcb7da568a2fdcb7bf6d31aeddb61207398ee3387a334b557018588b50e3667c19280d2a3757ce9d84905adec3a5cc709452ce394b94524a4bb5d65aabb5d65a6b3f191f7d1fcb4cf484e9e0952b48e6dc1f91a75b958c8fb62f318d01909f6419b12ccb1e7f19bfb695b6d77edb6e361e2e5f4bc138c176cf5a5cbe95bb572d623a9029225344a6884c1199223245648ac8149129225344a6884c919a4ac1988774cb4d81ec1289658c753569583e8ae200e257d78e31c68bb30f9a30d2de807514b2b5b96a4a6584d094051594636f08e2f259744091486e2fb0e88030f23d2010c67ed76d360da851430db9463929ac5ca7315fe521cbd378b1f2adac3ccbcfb963b07c68c7c082fa18569ec60b7be23228d05585e58482031effc453793f3c9d49c3824deda17e08579e6bb1fce82d425d73bb3b8b8ec9bbdd3d201e0f97bff5dce2b2874587cbcf64d41b9a34d505616e350245f7e50fe07e05e2f7b17d9fe5ab2b08737fe58310a6d7168c7b1f7f5047db1520a73104424e7c7e8d6449a5c8bc9a31c616a4985432431a8d06fb6a0492321864df2b131cbe4e4d1a6d5bd49c3474796a58964d93064e178f8f73adf57294eea9c2708cf023cc529e708b9a34d9944d16954d16954d16d5b389fe73fa4bb8fc0e08c508a499364018157471bfa70709248a28a2eb542aa6ba4e69225a2567e8cbbb4dd807972a8516643d30867e0a2cd0ab8e69930b50d733708ad2323db4fc5e338a53d70df2c4b0b885423286dc4af196e863ac936181fcc86970b8d9507843f7960f63b094732bddd01d238cb1f6ebd7805f5cb05f3f460c7ce956aa75bb897b471853b7128d17b7b4602211f69f65ffb686423066beb0c5b0bb6e3c61f02619e0ed2c140a85e69c76cead358c912a601b86c52df7508680dc5e8861f796f2b7127df9545aa094712c3f5cba899b6e5a05c736f913df4c56c165a034a6d48a9021c5ba7b590172f825c8e1ae468cc07039fd1b18e20bf0458d1ab6d7be861717b6d73ec6b6e1848991e184e975c5e19732ada2b4e3cbf4e858cafc4a8ddf39377e9f52caf1fbb5d65aeaf8b5d65aabf9bdf7de7b3d7e81805cae2dd3837dce60d40dc3bfb080e52e727c83ed9ab2008c137e1fc609afbb7462afb5158695755795e532501a586a1c48c92264a4df097fc0a4a9a99aaa295861abceff9a7a3e67cc262e65ca347364cdf3f79abf5f0e3ff4a4fcf0b394f4636093c9f48206a9e7cb0f7f0d0efc0bec7fd284a6c4f7cbde7e34c42a5ee4fc8b0cdb0fbeb8df1130c42a78c5f329ceb0141e1fdfcae3476880f839c66b69504981c81187e68de5144f9a126442007cce8fd25048ce4428b2f67274c31e32943882e0407120c039610eefb4aa388430de00e48a31ca69ba2188524aab459de6bdf762cc068f0d1d1b296ca305618c4f96e18112b6c478c3468c514a1baa1b3eec9e3f9867d60d1f1cb26ecc1069b0e2908523a571c8c23184c6142971b470004108278430cec8c21184a306eb46931b4260e18882952387432992540659c68812ae048060da811033f8c00635bcb047b89d411022431dadb5f6b26c0481671cb26ef4e08615270087ac1b7ee4fb4197d2b554beb0fdbb7b064edcbedd5d467dcdf8515f5c9a86743245e81844dedc70627980081f00872c1b82588891cf98289fadb4bccaa7847038fd99fbe8c7d780b8f62c2d960d2a3e35109f8f5d7cce9bedbbdd6574cf9562153c3ff7ba7bad8096df9ee63d1a82e65e6bfaeb587079edb7ede3b600fddd7ef1fec5fbfcda6fdf8bb7b9cf9f5f7baef3deaee0b24743d0df3d7db8b5d0f279e3b4fcb67158bc4f467d712d1b4ad1caebcdf2f0435fa73ce5a7dc6e583695a295fd2a4fa528a55b40b77be4280b40f9ecbf2e03cfbad73e6b5fdc58e8dc6b11e07972b8808eb2bb0678f6f59359f7dc86013c4c5aad7d7c6f96dd7bef66331fcb54a1e709ba38e132091affbd89319372ce99514a69dd4ab56ad9576badd55a6bad1dd5d0d8e7d4cae648d4ca555151c7c5ef77f8ea5487dfef2af03baaa1f1df2cd33ed33e7b6d0735e1f77a99a66dd96b5ba97beeb7eda6e3360c8f6f5bcbf76d10bf8fefeef6e9d74cdb6338719a5790b1943182eebaa7c44d6500fa365313890bb10d537aaee03c4d1a6f6b2ded07331a9014c9eff28030305a6bd268af0923ef49fb019cb93940917c4d7bd1e40067e4dfd3cb47c0499ee4cc54f1b8a7fc826df7c9356d4f26204df7dcf78ef7a9babce37464bbe31e404245dcdd1f8999040abc4f55a7e172aaa05d2141f77b52a94e1ba5a1c98b63c481b98a14e0596a3247d01d6fb5d6aaa363adb5dafceebdd706638cf1c8a4b1cdc8a4b1444994cb1575a24e87afae823647260dbf632cf2189fee9f70ce6fa6541680e1c1f038fd1374413f4747ef18638cf9c95c651d507e8c292912631a714a8adc5218a27b09a110c55ff1df8f81afad290c913fea400a437496278c15893ce79c73ce39e79c2ff37120fc39e7bcf7debb827d1cf9f5adfcfa726f2a322af2a442a3948aadd65aa9b0d65a4b4577efbd970a3d7366ce6ae5725181f105f005e6f43ccfdb3367e6dc3b2f11329cff0245332129c22d4018bcc20b9c61018a54e02ac0ae8b2bd8155690332f45b205482380de596efe77bc3f97d7e240170db4540e7471d2d363a6a08b499f48f4b8dd38f3fff9dcdd86febc336c80861a3570a003393678e0061b3770e438e9c021871d3aecc003d583871e7cf800636ce2be3fc018f936f1020163e44308a1350261e43711fa2522146010cd11223345442545560563e435a54c5aaa8a5511298cf0b1e2410f1e3ac82800893bace5c1035408a640a1652343f8b4aa7e42aeb52ba303149490f2638c31c64f8608471ce28c3088a616862e68a4946e284530063e8d1b88774dcb216887069038a2891c3a3491c28919602ddd35399233d7629c0311ac1c8450fc1cb272e0000e53f0008f44223b72505a76f4704352ec0862c710941d4576bc60870c76ec60071174a041871c3af4d021081d7a7480810e37d021083bd0b0c369072076d071d94105de0e31d881098f1a3c74f0f881470f171b30275420011048f40882144c1081bfa4acfa74b57c9faaeffb5cfdf7d922eddfbfbf4f26bcef9348ac0145a117970964c5f7d983c5f7a9434f1b54becfd4cac79487bac5ee98c58a90cb7ed95db4fb09bc6b970fbd3c354d1a7aa2a696cff2fdf2a1970fbdcb67bcd9b8bcfc7d71790955fef221974d4f2d1f85059893bb7c10c66cc977e42f1f72093dff3ea462f9527ee5f3b8cb68083ae5571e05c56e0aa0c15352565698186b1d0afd4f91a84315f63dd6a0281fdd91f251d4ca77514b34ca67af572b5f27512b1fe75af9b6a8b3f269f0339759a2f55f6de5cbb8cc128da5a4fcca8771952fc563ca86300665f7996373329ff6d801153a7ce96c5f8f2e14eff42457bcd3539f39bc53dae949c67cc538bfcef96241e600a971572ca40702160e4c1ec3e0044299a92a2ec63d6aa2ab0a05ce0c008ab82f241a0087bdbdf5f1379fce18eb172705f2001e1f7e5dd4934a7159ff670a37d013982f8e133f052974b72696947d4c055d602e3b4c631996310cab95889933dd653bce0a5471506bc515b2a4788dac912f0dcbb00c85b117f6c25ed80b7b71d9b9b2a8a2a3d2b9b87c95159798eac5ab5429a2258521a1f328b751ba944e775ed7755b101d39f7f2a1a73f653f0aa677b7639c38e0713ac1e36c82473da70abad03eee2dc5f5a4a1799b3486776fc1bba63aa6ddebab8471eda90963ad672814bfb7982adeef0b736de79ed10cba6797a7035d68f5b3fa58c5d9a5edda8287bc2272125c6e305619096254c54f46266484c80c4163082a8a2682e4e081c707b0d60328091c4095c09f1466c8c112968e286a60022374b7440a3ab45d25a13360b14e4860e9b8f1034b8710968e23583a44f00111a48a3031031d301102eb44847bbac1ce930e2c8770ea71fa619e80dc1cad3973d00093399ed0399a58d6a906cf3864e538421426160e271464cab4d1a428521ac38c0ac0cd26de3bb92e83099cb64891a44ba94042157c06fdc8b58451b1765acad5b71b0c13b0895970ecb38f371826ccb4e0d08597c0ed87a548ca1821e59660ed8c9052ae6e4af74b0dc110da07ad3964e550b920c78f1c3d72f4e4e0a11c1a9981a6417f40b372e44c8e43568e1b261338682dd1c10e392a1b8ef0a2c280d710d41ad22921201aa780062db8ae185300a55ce11614b931438e377c58cbbab1538401e46b6fd050e8cc21eb46101858ecd251e81d687b4ac106dd5f069a65a3b571c8b2818323c810f912bc81a528a59c136e8ce9949352aed38849c48f30c64eca52fc8da58852190472096da5776671ce1dd1081ebfea483b513b309d2718a3a4c98b09904b0913a0d614176758a659ad668ddb38dde9134dc9f6e24eead72513201944891ea92383c81f4c640dd314412f26530401c521475444523d4388a422cf1471473c45d314b412e131be6cc949895018a39473d21aa59c93d25a69add6de8bf1c518c3b22ce72c674ddb368edb38aeebb4f6bc9315149694904a8bcb4a271fb717450f171d7e208e492aad8828604e3a56b8483f2b9e5811b4820969b5a2c90ad70aa0152fd2cf4a6b3f5a69d89d3481c2133fd4a388a01c1813dc60a0f0887d0ff5e0f4e327fa917d0f0571fa281f0074260cfd939326b60ac650faa313e8bec2c56987e900e0e1f46b6c2300e81101a96163878f20750a9389b422fdb45c15a8be6a10cc496322778f217e8c34a26d816e3677771a31c6d6c9dfef0463286722feacbdc97ce6ab71b18b3a7af144d56433c99a7ca29a345a6bc2d0c75aefaeb91315a76f020fa742e4f0160e594130e1396a231c340efeca592061012467e8b3502267ec7e82c54aceb4e44cdccfc215474c68ed474ce8ae6d27af88e545419dbcd69a34211dd25a9cb66c264e4fb609393086ba30ecbd904b875c2117a790dbbd2587d3dfbe00a0600cfd93176d915fee17def0c5290b1414a73f428166b1e2541bc2e9e7af07a007a79fb15875136ce0f4b52158094e35229c868e708a84d3df215fd07d532d1a304c1ef78bd2386d4eb7274edf049e8e08dec7fc1d0648473aafebae4742d2455b493fdaf3482ad2118fa44477279ef75d975f3f497b9ea75f67fb15fb9bf2dafb3e83ea4fd18fa2b3edddf5b4eeb5de3df2a8483fa41fd20fe98776f242f183471d1cb280d8d04f73cef952fb5d773bec7367abf71da51da5ddd7cc4ee2680fbb93efbafc5ef75ea6271df5aebe54ebbe7bdd7d4d929a249b5e0f6c73cec955595f6a3549382931c9699da669cf4929b93b37f9aa495293a42689351284126e0287ac207878eee69c73ab5c7d4e23adb0a9719cc6715beb24253899d671dc6bdaa6fd06c3d4b8dfb6cbddbcdf38cd7bfdcde832348db3415cfbed493fa41fbbf90d0176edbd1789fc9a296526e52bb9f7ca7baf9d32ebf5759368d406616ef7dabbdd4be9b66ddbc5b68d8464dbec8f213c050e593f4c3fa6d87e30f94164fbb87d18e3ed5decf61de76298d2fbdabbf92fb7656c9a96afcef60ccab1dd69907e348a6778b56eadb3de7b31986addfbb3be789751b32d275693a426494d120a056925354c52918e9056d97c1397e190f5c311fe6201a16201d1c302e274f2f8f17679ec317efc27dccba8aaaee3f6e6e9bb67d01954dbd93ed667d0c7b0f9a41fd20fe967564eda1ae8675dbf2e917333a7d5ace40c126d638c366a5bc95afb35ad6cb3b1f7839b4d8ddad7570bcbab3c8aa7dd5aabf633244e0b2d6bd5fe5e0d86c971f48a9a243f43f2165f35a0100eaa13b5d61670bb7b01f65b7c8db4f565777d79417663695fd6ac6a90d89730f504ef336c8b8f8f6b666db171f06f2d3e493c80fcbaf51992b378fb706ba1c5ee926fcf6277c97145b12a96c5b658cbe2ed96b8b2b0d5fdb2fd7dede377debf7c0939dbdd6fecd7d4af41120f60bf5a6bfb0cd961aac56f6df1796b418bd725f470ae94f029f6b5ba95eae3c8dd23b6b5a0f1fadeaa8487b3d3aafdabd9e4257278c610726c9f72fcd916da23e1f6b3d7587cdcaff8eed797cffb3a2f6a59cd2abb260c7d97dd716877bdb255760fa5ec16f473974feac652a4396f3561e8631dca2e2dc7a2f4c9f782837d7cef7b7d69bd5fbcd5a41161911685bc15a75dcba91bf755d57d9c8d6e2d68fcbe68d2221da69ca04dd09a24f100b72649cdaa26496ed52489275896944b0e3e72f873c8e241891e82380a1cb27a50711e8ce8f1a309d7b8ca27c0c4fa4109d60f35583e2061f96004cb8727482bbef283dbcf9af69d446d0faeb177c136de3616321e33a62415e987b49233d70663797becef971f7fdb5723d39b1d8d18a47cd21192922ea2dc4b52ddefb04449f9fb3592f48372bbe7ae4a27ad62dc9cec33628c72e374cf7dc7bbd38d460c77c37f494a78df7e86c4912f03c75f9f9c77db634f3a120f101feb2424bc6f5d72f911fb8db4e2db7fd767d07bbb8d837bf7f8debdb1805fc62e4b2d729bf2d17277f74fee17eeb1dfbe1ac1f8f1c7ad85f8f8492ad2910da548e23e4376d28a637a2ba93cde38f8e5772a18feedb14d65e5c3f06fcf61bfddefda897bf1ab6cf8b14ddb6cb4049838c61dc61fe55d0b95634e6e4f3ac2f1dbedd33fbf95a71fcba37c1d496575f849e6e917b7d68b7fefee914f9af9f7efce946fdfb1cba8c9b671b2c7fe6e9fe302228fccfe7a1f79b8b75fb0ef1e77ed04b75ecfeb3e9e4129ef1ebfd63da73dcbb7f2cda0b8ebeceb4fc52f0fc7dfbd1e6e9ff4f3da9354a41fd2eade8b6dd24f3c016fca577eb040a1030aa8004940314135b13808c5e22819a088409d503da05640634708261822d5840a7c967802d553001ba04e3da0842880121e52a4c0033503ca068b0b70031e47701e48f0e8e1e1c383053c5ec063c5c3091c2a282c21fa90d671c2c13b5401c7505c7e570484918f449744b74467a46ba27342fb81da9d0e8c91df01fde0f227105e4d3855788610e79c14e3aa6975e25882904268eb163195a28961b7d2c7d9d956923f6f64b6dd4488d9aff8da9a6da50a21c459d3b8ad2423c4302207273737cc029fcdf9c9be6b9ec9c76a92c413e4e318e3d31f5dd38a5bb5a721e41e7a3ea004d3ae9ba19d7cdeb7b590e5531e58236fb68d7d3d72fa699a57ad3febbaac3b1632de6dd24f3ca1fbfbb9b389d5b5eb13dc578160cddc78286945fa8927c8c73eade1fb610d069ab48a9b758135f1c91d5142c999765f5d4d98fbbaf5ca085f585326a70d5d0906a05b1e2ee1ae694911fd1630463eac2320746ff143ca6f015dc011101da18de59627eea0663bef90a29a77f0fab907a5c36beee1f5332acb76c7f55f6458956559ce913336f229d7548540f56baa1251d5232fe0a4a19ffdccb2f9d96f99f6d90db2afeb8a7dd4da682df44c23383171f999c949f7cce4f432bdf2ab498c3ce6246076c99927e4cc04923395899c81f1656e82cb6c84cbbc047d595df3d3ea073f7e9657d7a4d176f800d24e5204444711942a1925eee15df34f7351eb33137b6018064421fc081379d031da6b5fec438ae3cb97f8109bb2063ef8c721cb4710cf5183d92659a0d10fdd3b3e516a9e73b31905a17b5565f831bba19422962045128e7ce85e0297df5f464c198140f77ff92324babf94524a694f39b9aae6969147252749455af10498482ad2aa074204c999ebaaa605532d0e97c8a959b500f5221d21a95845b8583a44482b999f14c826a0b576c9c7af2be8e2aa302ab9d98a917b8d949664c593e769758972fa54b318579eb1ede6d29112dae69e9d5f2f6c05ba5b1faf15e85e83b0ba031f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f9f97b59f5fe4a8d91719c629392574968231928e88689749c41d11d1ddd6e051fe8888be1f794c60813827a554ca9c9c5a6bb5d65a9b7befbd49e8245c2e9c848e0fb1943674ca7bc4fee6027ca1652d6f302014895c8010a61a813036d95218e5dc463d5adb2f302ccf90524a6b0bbaa81f5ffbb4cf9af69ca669f961a75139635fcb2db87c5f1326efab7d1486e5f9219c587dcd9c737e2c3fcebfe5a77246cb30ece74da528ef16747179fcaa11dcaa4ed89833282f619443f78ae467554918f8b3ea28bfbecbac91d7a75f452245308910b85a18ebb46c0bb75c745aab56cececececececececececececececececececececececececececececececececececece8eeb08ef44e555429ff2282bcfa25786847409293da44409292ddf6dad96af6fa16f09b5b46c5bcbf7b26d182d3a3a2d5fdf42ad50e85b36cecaf6c9a8ad904a8baf3c7c16941595931414949393939313cff33efbbc23b8d7b4e75aad566b6444abd5d269b99a20c2082153dc919018c569f401931026427e0c81c4233204912143040942248812593ff79ede23219ed69ee7e5fc3aef9110adb3d63a7b5a8f3e204489109e2176d88c848c848c84f8182131e2a9f6c505edf3c7c81e7b0d6ea52869494eac637c0a83da0827ad95abb50443ace2c6ce682995b6d63aadb5d6527befbdb75a8c31c678a4a3e54f6ca483b18d91ee4b6f34fb1f8431727e969b9c93525a6badd65a6befbdf7de6d4484963f5d2e22b42d5120a02e03a571a57e8d8204c9e9604dab669544a6a32126a5b5566badbdf7de3b3f77a321b0d110754e696da5745259ba479039674dcbb2f679cf7d0dfac505efb98fe1ed187a6794ca8aa7d554d3bed2b602e45a66bfbeb66db88d82d0d9fc6aa48cc97d32501a999c3ac8ab56a49262bf492bd26a3e7d6cf7a8a2a423a49f4c24ab724a8a6eeee1b302fd50817ec854562168a717dd35ad9a168529243549b41a5a8e663a8d7cb0a714bd473e68a71a2453a29a349cc63a72d47e35d24177ab9a34564747a5a3d251e5a071b04e7e1d395333a644ea5a200b6499dc8c9154bb2a69d9daaa4ab2acae918e0a5499acea1426a0576d528350da3ecc2187f4b38384c44766e3246732d48fda9233ddaaf884765595e8f0a8543a3aa49f8ca4cafa0c7a9fdb28b6553c2a4dfab1af9ccab5098f71635ae39063bea31db40dc236c8b66cd06887c6c1bef26e5bd9b65c3963f29233f05ed4455d1fab9a24dbdab039f6942367f049ce58694f231c503ee48c11728647ce5c949cc13f82c81939737fc443db87a31d3af26e7b2c113913b792237206df950f20de6d2b0848ce749b6383e44c8e9c997f4d366c8be583880db241b6655b17bbf4504d92fb838a39e7bd72bb97a4e27ece8aabed70d755aed639e7dc9efbb63be7bcb3d65aeba4f776f5f34887c6891bd75a2baeb76e926abba94b90f05a13c6be46e1f875108cc99bcda847c7bfc1126ebd25dc662878a74b9644140eb712a63a08bac04d348482c7c74eb413b7f1cb19fe88f1f79316b72db9c1c0b494c2f1074117293408c65829b8fdecc34e73dffad5af6fadb5b66e96d42635cfc5ede73cc241e3dcafdcde544ee5ccdf1d53ec579a638c5f8c3546daa23f77af9446fd9ad5adad8afdfcb078ef7d4c29fd9a16bd15c74823addb9a60568d4aa0ad35f1f833065e9f7edb523a6ba546d096b4f23c2f9254a41fd24afffd344905492b928af4336950029f3fa8b4ed95663dead4d000104000a315000028140e074442814814a6a2a0d80714000c858c466a4c9ac8e349962331884296006388218400800101919119221000605dee90e8f9ad514d2c92ec833f110d71489e850eca1a59de7780c6b88d73e870adac8d3a44c1a5bd43534ce9f228628adbd1f6f88f8121969d5b119b0af3be70166f8b0c3ede2413a1a49b40919060c4f102387f87bfa5916d89c6506b07566d24ec043d0d08c8537cc0952b7909d2166444067b51e2da4f0a1b310097efafba828ff8ef4d85b7af8385915dc4b1b775ce74a2b745350183ea658966a1e3e63555388c0d6ebab7b74f34ae8919b52c40b5fe07ad0f637393a1a5f48bd9c5e0ad5da52c9abcf50ad87dac33a7578de6ff838d3db5659b713fd14a509ab733541d2b59052505555eb3fc327e21549c426c151a3e30015919c609369db17d2102c4a776d681b856a9f0a5dc6c107ba6ef817aab0ecc10a4ac0a2b1829a9a13b1864ad944bae777b3800a481aae4a974620f73d8d835972adb3581a74e7cd9c91e488d457b026beef6adaf7ddf2148a8fb7e17e1d36f9049ae44b13a08296990de84ccfa37262b5411cba5d44dce2f8832e11325f6ed6b475f020c26abc9989dd027885e69626bb4637ef6770d867fa7efdd7ee61afb73d75776a238594ce6959264ab533439fb8825263211e1a026d9ec9501c625673712e331f1735b877c57379354f62c2703827be314d3262d263fd2ca8f74a1a6a59124659e408d936c9b750655e388fac3456bd65dd5ebde28b3474ab37f89903a06489b2ec7332c2d6ca70469cf35735c5a0f87814d423b84e82fddf52277d2f8728bafa5cc29b93c6eda15381d32cd6fb950921a3a0f8092ae5ca242dc5f77d2072cace5760aa4e8a4b391441bd46b48a6dea8bff5f2127b49146f78eb374e1f7c3a75409f0c89a811e7b709213d8017bb85df47a9db3e09ff8064831de2c810f1b56a495e8f0cf9b90432408298e8183c32d2209efd0b9d80c21f10fa2712fbe629400bdddb57c3fc6159ff27fa8f362a8a94bb40c1ad648acf6c4c861d244d2a19c9106b9ec40cfc05ba6934b8f86b918be8b5577080b9fbb0465634d9b2e20cf66e4708ebd16b536f07d5b38e0e6ef4e20b75c448967650745302b6d119a3b27e9e1f4283a05e31a8247c3abc1770249231af666a912693fe3a7a3a1b6e7c50f3ad50535ba9bd97f6aed5341f5c77ee7d7357af13a0cf79ddc8f417e86e0fdfc036ecf1b1447a9fc5cfaa440874f30de9fd5838588fd585811750be3b6d5d134ebd3981ab052139c84ee6b81eaa02b8c10e78da99491e16308e065e0f2091021a1cd1251e706b697f26dccc399a2d045955b20e7359578bb9e330a191b7b8c5c5261a23d30b6fb32b907cd1de2230041eedea0e6b2cb9ec49e1ef38f3be73e2c98c2c8acce4e455590285fe46ba090ca6d97dff53b493f6a1b562c39b72d358a1d800f41e1040668282c3ad57785b2b414fd34675e92cf486eff9bdf4a465ccba4a31c26506a929244bec7ffdc6a8829ffcddd6a755a46cda019ffcb0657d4b5af670e692842e005ef87c1220c146cbecd03bf41a501fca6403e556150b218e45ed6fdb2c7a8ff7bb6e100f0e25248c3b35d9b3184357d8ece078c633609a948f67e2eaead27ef605f241dbeb59a2cf44ecee31ec70dde518ac903e58980561191aaea3967a92e452282f3d1a88c913c0f39a056f6ea1cab0ee0c848f260bf529eccd4a22c06f866668dadbaaf2cc435d85928b52f0fcb180e3a7f4c11d48d33c78453e7719180ad204567ac1f67bd932e72dd1fec29a5c04b480780df968c584b42ce5981ef3f5229cc2429524e9d7e7e052230fd9f6956ef33587c112a6cbb3f7b19bffabd3199905e3fcd3ac08dced0497b936e915c91e26c81633f95458ab62905595e0a89c355285294ec36e833f266f81fc9d9920350429bdf1b2d8b0ced0abb7846e1b93a84734a5269aee05bd9d11950e26af929632aa6506941c0a20f5132f5a371cd45fc56f8ae2efe41d501e455a115e4c512e135f3c77a1fff44e48916faa1a0dad93e861a25d6e83a484936ea8d212e3a883f18dd0528fd2e5af9bfe1fe0dea984e079a8b27a35bc97f1b52a21eac7669e03de4b56d7bfdff544181e5b38c07a9fdfbd4ac8cd78edb44e007e59f5b461a2b207b47a012bd415047bfa20bdd93f7bf2a6d610425d58f932c5fcb63afe4d14fb38c2bc6a6e41ed8ee4750068f346ed13359af1d2eded57864f02e0b3fe26c2bce04796bfb26c66180ce8ddcb9c5ba317f4d66dd6d708f33a32beadb2f4be615461f0e7ea251f1361b6dcb73e17837cb9e573b47baca07dce84161755a384524a978b48639fe8f299aae5648456faacf8b272f1c00d934329d56c295cf3882bbd7cb6c98d6736e269d2a9cf747817bf440cdf6cf7eea2e1c2883f9a2411f9165a3ba786f3a8ce0b8719ab2ff742533b05a25368307f5eb3dc3409e092538d28ac12677b448828b63575f80d3ac9442fa2766d6904a300d2d4df1032a34a70747a06897b44455e0adecf92965ae866dbc0578163f2ad6b9b799d000b6ad704bd9ae2665b42288951b17c690b5a223c34fea3c103f7a153a204d4cbebe8e82037b746335fcd95d7c74e835d6afa91a2b3c64e0b97cd4653ea44b30feeb2c9a8543935f6825d6a1a9929c5e5de6a93704ede887e6f15499bab77de406ca1610d8dd3de4282ecc53b0ad72075507556bf7b5501a3e915c42d9ace84eb7ab5d5c2e6246ef021aabe24faf37553d520efcc514c625084591bc521dcb70561022ccce7cf4ad1355590ad0b3b8c7d41d80ffc26ab172970dbdd4092c9e7e33def8252468670bcd441036ff034f0679a8a289ec4e2f27b6e3adb8641c3d7643852f364abf817cdaa6e9cfbd6dffe0e3e590cef9a2c1ea6e8d98e66a73974c1c9846299bcb37363051b784caab43525e02cb3464d6435eb993df99d1dd13757353fd27b4892ef54d3b32eabac514c103f5dc7cc4e379ca6680b76f4bb5cbac7360563185c22a2b275515ba614f5b574f6b4a3e0df34ebbc1f99366ea60a32ca344934534d2ca37653d60c3052062fa09af61e1aa1968d8a794631e778fde0e557b2784c6326540170e2a444639bcb24ccbe56330530ae1999c43c37b7212c125c5489189d52c74ac4e7bb9586cfa586435c11d306d9cc83be5db837b1ecb72c12508e9608eb31fb98ee8435ac98bf44eb156d8def8f03d7ea65f27b49f97b224fac074b6f22270c66e1d6a1b2c9c501b0d1ee1e569aa9199699851fba3e8b9700a262420d83308c49c6ccf87b7a329577031c47e324bdfd345a985b8d1202af9f0b6df998e03470fddf0f2e1027efa4d252a0f4b885728b9aaab40e71e878e1c737f79fd0b52c21083c0ab5d5cdc5d9e4d4306dd2f8458300c68b029c80bab53ee2cfe955c0ebd030237c8c267900d2a64a92e3e729134ce42dbc1a25742ad8418db507cec53b4a1ad1813a204f7efea447fce8011556bddcc8d83506641a3aa2ed47cbe59bd353143cf2f913997a97888c4438d6dcf247a40c12d27d551dcdb323e4a8118a2c95febecb531eb559a74a39dc232b59180a86e61293a559ea640e87bf87694e3c9dc0617585920d93e0a5c5051599e4be5e84a721f5ca6217c961dc60e806b5b6b1ab0e19eb8ce07243f3f001bbcaeb7541a7b231bc210ba3971e6e1835c089bb5c53955c17aced173312f299955259dbd5c29697fe784fbe5a4f198cd14a22d84201fccd65daf9f7955eed2552c217936d26d21c4ff3e585e353412f35fd4ad15173afc5458d51523a44ef0abaa03952cabc5a7b412e348e3a0a611947af4a52a44bac788d12f84250ba9be6e06f71c6487b746fc4343a84683de86caaf403bcd83ae6c4055eec6e1d06feadabfb2d3a7a9125f062bb08cd17235e6ca5cce568494969ee02bc8ce11b3c05e8bd1aa41ef54774e065e06a742777fd0f10fbfdb3ba9410c07313c4cc1ebc5876e74be79bc083087c5dec9bc7be3426168b6259f6a1884a025c3b175b27da0289acb2a73beeb19a596c00f1f8817c7f85574cbd6d1d28453510ff066b1c271855eebf7ecff3be5125837ad24c29a6bf78c23873b70c286fae56794d792af5e15ec41c84b3e7cc8d6a5d7c81aa91ca8b24f53342aab9d54394b02f96ab5f00a46f514a21d5afff54c9c5bcdd328372200de6cd45699d7a21f22045118fba0d399454f72615a54aa55a96aaed7784a9be91ea7faf6a69de97d3e2cf948d4339b7a2080c787b71c1ec0be94f7047da450ff1b7ade1c1b36c852d0bdf8215fe54dc72c49f967c13b54bc7379be1e4a0830703adb1118adbd250cb59c4250d5808121e500c5ebfbec4f63141dfacdf9c57685e4640c3a311e7be0ecb36de558dfefdbe242e1b5f29766ba5397ca2287154e3632b2d9f1f380731365cf8fa7c3ab258cbdf675902e7e9e3c8fa2b1ab527c912fec03e472c5f1ad5e68613feaf58bc9fe7ac9732443c1452506ada72f043e979704b8ca3140585b7597f5cfc806593e57049a7a99924aec49e1f41f85d37a8181f432b1bd228fd9f270558ffd381f1565a30f19b28f647982123603edf7ebffd7cf2d1bd14098775b0178a29f4e2e043e3f6a616f48bb67da79c452a615a563c01fede9a37e167b2dd096d1559363b3ce17cd8519a5db560040715fdd50c88afd13e5981e658bd92aaf417a21d9fd69e3c79006f37af668710dae40993263b598858494a53b0c13b21335ee46511177a3ecbd5dbb572b46f10b045fe0482dc7cc9c5ae7cf226a90e0c8c2af0f262924cb33f8d0d97ccae30893f06b7d23d540a8025531a0404759470b7ee15ab35840ce7a9775f41707edf88ca8adcc51ccf78c327c0fbf0a4ab2fe269d3fc8eb6b92feb0325732713453c953542b8fead89783a95a2cbcc748f51f0d8219e340072cf3668d2abf7b6f3519a13e01b10b54d4a66f04d32300e4d03367cab850d2fca4d614f7cabf59efd45954b55cbf8166c60f20515678d5de1f1edc9ce2f5962411d052c63267ea5b7111c86d5f927f98641485aa88600c98cbcde3a549257be21300a1154f936ceb67dc162415906882837a6ba46bf9bf2c7a122315049622c669e4dbea9cc5f2d183aac924082268f9cf9861796240520157d2306f6729c349cf92ecd8f5a1125ed3b894af94e87856c60b4beca5fc4509b1c650ca53939f38e77839c2c0e41dbb47c7e6ba6f53984b929b629667226fb31a81a8eccb2555352e0fb5c88603680723a5a76209776901a1362bcb420ab6decb071012ec6404867747f3da1b008c5777d23539a1d9485b77f7639e1aeaf146631e6a112e78daa3c168506bb5657d36db89f58fa21999fb43dfe9bf9c812770d2bed492dfdce7433ba8608176152d8d5e80df9ef631d86475b2f7751e540ad11f22f52905bc29c6d9d3fc36efd5e94fd459530e65de6dc5683c9699353065bb060a2dce21c0762bab88bf0a438ae79249bb1d6119c28bebbda6a08ac2fb4ea54b8504af40351d2b2e7898df88bc9a5244b20aab8a561c98e34abf691a343df6ca19dd4e14814916a89c1c09e63b33a8e9e0d6ffa7d4d9de3fe2447a8b5ee0b05bcbd2fab1e006ca071ea3b8f3194e2f035c2024ab75740edf61bc6d2f15a4ce1ff6a16ca41dd50e624cd3f4259794a395740852db43af43c5b104d139f6a969af514c00d55c633c1d1d6f236945cd7feef28f63821456b26c5a554129b91958ae31eab65e830be3e05260530b1bc92a8119040bd0595606a0d92f4dec46c670626057726de0c051cc95d2691e19f6b7eee2a10f7b6a5be24b0c49e87a4d2d6621aebeed8fc1706a35d6d037c7d935585e22a25e0d5137c69d54b9d65c52d113701d492e45ddeaa861a7016c068e4bbaf9fea9884c830e1f15cc10b27f016f1e6f67de7abf072d5cddbf55b55f7ad75eb9da02ebc21df37f5d90094a1ddb8de8053893e2ccd0bc0d25bb61546bf9d3e045cc293d59a59118ff6c60610da252db76f7a8fc22f170dd2b74452c8770fc2113101872f3ea51fc383780e34da8b4d82cbca2b2f70a1ed6ed3152d286cec603b5a19674c807bbc2e52e9a1d89091704d23e2bc7317480fb598f73b8e4066585101a779eddc455f9f6407dde799145f76d1439967fa3fbcc0ccadef006227ecca4392071dd6a3518f1eaaf687ed3a8455f08637543814def186c2d5f22f2958f4a2b3c3b232cf210c334dc4fee0c286688046d062d7be4736755f9c0d6026df00212365b126380e4e467c9d87da1f5510341b63b69d0cb17906d784527a6c87b0627c63a925c0f4a51eb4ed479b31ce0817c73152189acace97f91fed0164c7f882f1d8dec4519b53cf5e6ed5a277d0c0b9930214dc499f37f1a9873a1fda503fba6a49b64f8bb3978a8e6d190d8af5b567291a9fcdc4ac5cd4ccd80933fdee6622c2bd774cdc48048306be0485d63c6766f46b12a23807d1fbed144a545af392399af5b10b79ee48c0f1479d7efb32f8884cd8a8f3774f5384aaabf03ff3c186d3c399584703fdb5c3c7bfa0d755c10af0f089a89f6392f249d93374fb5201af5243a0105fc4eb252bd8736a7be87884038b815f91ba48c34f3e9a5c674f4deb1fefc1cb856d305ba8d394fc94456da1521245fa1d242135cdbdf5b886cd117c69b88690e71fed273273810ea289046070f14430c0decd96d6599a7f6c43d93eaecb882af82e77aa47e911039e8ee75a1a00a41628ed3016de530213e6e532faf8d74936724722ca7f2e5017d5a54096536575578aae90d05ef675fa50cdff8fae22b0d02d3a467a19a8d0249908af1101954b970541401da3fbd0f8abb8d33ad136341ce745c2740f6cc57ab461a50e26ad7a03aa1660507b9cb5f934ea1716d98cce73868e773e2c008807b8155d3a4d0370e74e355376031737cab58e1abab2011290763d0d87e1ab5cce13d9265f1de153137e238be68f39d6f527143f8752e28114bd6eb0e40ed2adbed96918f1f10b545e50231b3760bc6b0fc38cbcf825c488f8d6560e6bbbbb7f1a51a42e36232d81339e5254cbd3711bb3d69109f9d3fd4836ea7ad449df1db4da3f0fa19dd78caf934be4d3c2c95e83500cce27e3e4032e8bf1d308926413da51f521d251a59a78375123c256b0aa55947d9a3c4b172dbfa92d4f1db0ba3a51f8b6c96d157acb4b942fe19724e4c366e4312038574d4e2daa4ff0069a7998fa9407e4b407545e8a014acf90c20607453a3d52c49faa0d7840ea23af9ce4d4acb1856483fd2960813a1117c2264b5d7f98d654874fa370fc6427e198d1239c48be0ba1c8d3d310fafc811e06a9cb0a872e9556739bd871521d0d217228e8f63909435747da0c8376e74631acba1308affd7f345bab7f917a234225f833cc3420f2e86ab2f22a7ea33cea073b06f16312da04a470eb67eb51e4a24fd15da92ffcd1d7f43e8b026a7f3765e001e8e5d7398eeb4db32a349ccb7a9126b479c43966027309e6383154525367daf211a9a7f355ff76a67527c108f3dade88ab0130ad229ad66ce5d48ef5caaf4450f3694537a046eda25d30a0bed3d9a9f5c868b79a804e4fdda8192d2bb2d49ed2bff74d8df61c962b9f025a0a8e6a37ffebc50610307fda1fabc88181938f31a2e3afbd981a46906fc10988cbaa915594fff41a3d1aabbeabe66bba34c83e602dd10770b0467b233557751470eac4c773fb8d364a61421048288ce41c174f8a0cdd5f606fc7dee5348604e8b8f7ce19940fe53f06cd45dceaf6f2bcf800a60bec12e874f5544defce212a7c73bcb04d58a5ddfc82c0e43a00452f5c12d733f7ebea608ef41f41065ed2fe5cd6c13f6d96d572fc2be089381fc9d9c4e185fe9bc83418e4e9c8eda78c5fd4251d085ee377bdf98cd9baca41be4f6e8a6453a321da594dd94ca78124da55a837e93d69d6c8d6019f4ad1419c995ecfc9d1132ce849222a251c7671044598a74ea18309b537bcb7d02e05c15f6c7a1e56c0176c0d89e89bf344ec061c7dd68da24089d994a8ace9434652756392176716b931a82b5f7c90c9496bca6301034d6d1df89e72409e1c8a9e7f7d1553db9b7ffb41cea1b2d407fb6dfdc08d3ae540bc711ca21a7de9ed486baa076ad4cfb4eeab7f8a09bd9ea41e4cab053660acadb1e970f93ba97d644c347fc850e1119608a2f0bceafc32be4a366b3ab82d4bc152b1fe12e9b05cf93245a6fed95ca05f4e2f05717d322bcee810f1d36d9dc36fa6cede552d1c755e1c1316d152d215cd050cad38106e4dff8ebb64c30ffd92a22732c5d0485406f282d0a6b862a5aa1a9b0cbe7d248513fd8c9115240929bc280adacf727ff656560d29b5a9ecb3a8acea1589fc1853f27c7a8db9323b21066ffab42e984ce0cb6c76530d192a0a6c5c63e2a6ce3a259cc5932bf5b59924abb109771c0daeddc42f336999e763a84169cd2e787d593e36a214ca06839077bac950dc924b2a41a19d3ff41e649a251dcc90dd83f3601e11c1661f8b61c5c5dfa6a9810fe794144b16dc5ea4a952a6979d32440a7c19deea5d223da2bae62d16c12d0a3831d0e58f7bcdb7356c1270e5dea02ca84eea3b8e07f8afd41bf6880bec20875b25809b23d12f58ae964d42e225afd4b08ef9c84ca5cb7a9cda5b3e8d1601caa97669a56e899774fc84bde6073e8c122f61df14b3f1a7b0d205643ef65f641393aca8d81cfca50bbec23f01550b38a38defbd232f5148c1cc43f13342f26f4ace03a856af2ecf022769df79550d7da1f55f532f2ac9a9ce6b4011e0f625bd696f166c5725748bbdfbbcf5a746549ba100437a854c8def2276a1d6518944843d519d70445918ed456ad003426c8c7c639c2b4a12693b10902c337d37f19095aa61cacbad55300f130bc52e76d9a8b35b3c297853707ad2543f27405692333c06ea519d2f29ad696612411387630e5ffc63a543acb9cebcd955c74a59479c01489a0c93dff82474c255add26a77ed58928c600e26018c8212578b7f8da27c1bef3c72ceca35d65fb5d7002373dc58e9f6d96ab6383b37422bf799a5f21a63a107a945c4e1f8b4e9c30a779cb3fa6677c2cd540e15fb498c522b4f0aa3b9901fcdcc9ad5f443677c89d52647492ba4ece4993bbd0e02fc8d8c2ad38df4f6aae916cf9037f0679af1d096de4b92dcdeddc31712e5d55f1dc90961f29d97844e2c6e9e2ac8102b45bb54bf4945772f255e153e075242b95401d35fca734e6d9182672ddc9358110b1424d20a53cec918f1ad2662c61d27dbed524b46295df79d3812772dc8b1cbe2ab915ab15136b22e394362c8f6bd3362aff3d1c07e25b3ca3c63b403c7b0c4f94991f587ae5840d74c5e23d03029a940f9ada1ccab865210cb876e76c85ce3fa4873e1024fc49c6654204800a7c7af892790fa3889ffd58624d5f9365ca45bb2ea7615474cd8e3ad4be5451ee4f2eb450c4b80f881dc5ef87413a31896aad14c996373919ed9118257dbe26e4085837b1256f61fb86aab1f7e818c38d354a00da8a52a90512be2b29bbad1101eadc2c9ff0f160de43b26f58eaa0778124bc0a458f149a2a027bcf13129041797b853e5ce58226aa4ada45e805ccecdfe2c753c653ff6c5ee324e49932c0e5321eca6f9bebae6fa1e3bd85cf4fd1013e1e323a11f9789c033fb47437e7c0d8769c4a94c6fa4dee6d09f22c8caca7b11fc3ea03f516dfb125754174004bde5a201da174c245cf7579ac294af8a951e9e865bcf66dcba220afcb60d1ea61447a4f0157949d7b6d17ea8dede633414b1a5da021265a08d9ad4114bdc7a0101835193b5d33ed61f5a7add9c7a94ecef8308fc7ea70b2bca55eb781b57ae49b354edc88eba5bb1eb0b21e45a3a82e234dc2f98797241593f6f51009f1c7ec122b99c7705acc4cd57b786cab35c4b454801ebaa0a312c1d49eb33c39ea81862c411aa17d8d3647e61d92833700c3b99da1fb2e55782648e19d0d9233d9d00e18f37ea8446d9c16f564cd372b70c50918a3154c00356c37bc4cb06ac77c575dc4a1abb62aed76fd9aa981a2e15024504c964ea842123739232d4c7121bff44b3d902dc505233ece4de5292e4966f434a0f7bf19d6a36a0a5a4c3b10c9027a844ea0003b5371a08a8c8deb9c3e3ee8fc05fbd2927c85e13f2e252713120d4743910ebc08d53c290a652ea8e1bb34302f3b9c72eab388ce85e005ef424aa2bdfd3c05aa2c1571a6f5a505f19a9d832f2bd2b3f4ecf2801873dc85ba73c16211d9008d13e18ad982a6d041a33c9a6f95d89a5276c812e0fbe444f05b99df6a7a2255ddaf6272a003076bc76aac1df4b49ae504e1dde0b5f8a3d131da4f3fc96bf97b6245f5ffd098a2a6044fdc8093f30c8510835fda741f180f88012288bdbe2f66a3d447596027fe9fda290b9bb33ac3ee8c631b94415081668ed54e201c643c0c7d00cf87993a5a90560d2e38d9308703a8f09fa587a9dfa767a4976220d3f4297a17b413c65c8cc7118b6ccc9248089c5a743fc600869678a514769104155d4ce3e349f01cba5b1069fac9045bbe6bee7d3f9f0653d6a74bb750b411d930faf7908ef37a6a1699a315de9979e82c5911092c5e7e509816208cbd58a05733825f157980ee8248d2c2d80efb92685314d71fd8d34abb93669945eae8c58adfad31dc094b853114ed3a860cb94ea7fb424ce844e4ba738b8cfb228fc7ba16504ec97f44e78605122346a625db8a805c3057b17f3ae2acaae29b33411a0b0dadad5c9dfac332ecde2f71bc2ee076965c2bd3c1a51510319dc1dc444a2d6d8b24283067d510f9a327ba6775494d66ee223fe4ce9435a7a94ddd7c3b40308b7d218404bc52c19005a32c8f34b108aca047d318a705221ec616f63ef2295bbfd23d30cdca705c845566b2900d39649f4430f242efd60a3091790a6a87d831f54047a450a4af442e7e1394e5a4df7a508af04ba4a7c862992b69e9c9528c68327b260ab54bc79480d19b5a8f4776b1b6f3c9a3d77f628a758c7b7a173b85007efb671a07671f5f3f81cbf4a74351038f9d1f9150aa542c4e0269e72c1dfa91ffbc4975b8665c5ded9df88744b00486416051a93f23a8d27f12870858192c99e4f69bd279abfc548ff91c20462a1d800564267e50bbcb42e39c8caf173e447f80394b516e61e9ffb40591b20f641c15bd343209faabb5398cf79674f1eddccd18d716839c874f3c68c3c99c49ff3cbb8f0d0bab82b819daeb1ff92bf7a6b81da1826e5187fc104e0075ce6323565d6f38d17fd8f5f966fd90c9b95356b0a62f95f73d7e5713302598977ffb4829bba4b8199810c44d9954af1ff7cc0931f018441d6f518cf94ae0d198c7a137b2eb31c822cecb0a2299f8a1e5e98a018e350a950f1945ddcc490f5437f27ab89eb8a51f4f06d68d5df247487310ca75790192c149f936b8e51d92d68d705d928537877880019976ba3df5144e23454a236a9a0d5ce7e82793acc6b6df18ad3afa3a0daf8eddbb09021098555f54c23d736a6825cbef50337021d4d70f0c05cce0bf50c73fcaf76d7cc1fe6f37814a2d10f222b0ca0ba30636eac8527383c5473f1b325659079f4d66ea4086fb383302bf3d0664c4121ba01b54b4f0e486bd8e879f4eee53394bf191c6d5718a82a4455025add591a6809aad2b713cf7b77fd66a3c3867074c4ef323d7ba92600992208638ae280dfd076126c219eaefda6aab417056a4abde7be17d634a425f4234d9b4afd1e1eebec684500d2525af0f3a6dd7b8541a9453c76044ef1c83b5a7753df5f10295e6a79654b64c6d1cc44eb0d3f8993543a1767deaa70e49366b85ba3499c3154fe0ae1e789b20032b0f3873c75204e0a8dfca23388a38437a183b6c2a62aa25df6f6055b9c886873aaf6cd59e8f603b33ca164cad24aac3961b529c6666d2afc7e40526c63c7b72b901247a87063a8b4490f26ea4568799e5fb569617953c4eb08c032f53a261155507468e99f1ecb071e46221a10b839c62b6d6633e95d774c4d713a39012728d2449b1e5c5fa2047bbd63f11bc4d9a10c3549dd305c39e103e52c8e6dee126d52cd846d915e28a4a04d58a2c3bdffd29d27c773faa57bd48ce3c3c36e4cd0fd3d351558f3d2ca76cea88c5a1978836b87ad4838d441d3927de4d64fbb7deddd186bfd24928e3893bb40b91b2ae15570e2116f26f547511fa059d6e79b4be85440b2273fe3138a13c5153adcb34e20e28f8036800c2ae03d0080b224ed081b5a38b896fe81e2341542261e5700177a667ef45efeb4de6c9313c541c7eb4bb5d3e3df42004ce5174e98270660f2bac400f5687a745a7074af294de4092e382437cb562cc549fb3f198970226dd26eeccc3b59b4ed991fa0cb958cfc37434d5ab8c14a9b320d588c322866d24c3f47b5ea62b39536e136ef990530f5d1a917e7d28b3982ba5d29ea7b2c3349ab61cfbcb43f2a15358a57ebfe2a51d84a2049c00cd4caea96be7fcd4f224caa6b67799b2626b2c952d4c0ea52b453f56eb7b7c4d7cd829581c10408683706d9ca517fb51b1971ff6b109810cdcd9164bc957fdfb5640c95b649ddd7ae6d384f23952506e2060330d74d6aa533d298c1e2ea72c7649defc1629b1d60b342967f49561b1ad76e3fd2fd5392c05d7ab671533479043a0a364bbb6f36d4c77e63f3041a3768ea4625d5c1094a762c6d5cde8e5a1245a4ecd1c4935c00756245ae17fa456aa8280827ea733d8507146e8c5f1ae8e0365e92d6670b3aad70538d6739fba09308fe70b655139aa79b5ded8290b0a080f20eb316ce0cd27130907aba67b83254eff9d89a877041fb01289acbce1d376833271352325b2fca2eab83563e1ef0239e59c32e252719888b54148936d6ea5737288a325c8340c2efdc70215825e65f1eb02a314465cb9df05b390018593fb959a20477d66d5b1dbbfa67af75744ba5d3913237d439bb1171b48df027937fb4fc581796c4f138f3e1d6432516d562952d6df1b035cef651f329802b95e9236157b36d0975abd396803f5273fa2bdbe8facaf7963875081285db04ef5f2eb3c6dc9cbde724b57e97d0da1723156763af6701845828360f19416927abaff0f6703691e01b798bc16339735235956b4284f8305a126e7059aca6ffee332ab50a9f8660de482fcbb28656a21cef937b32292f011960e9013c88157f70d7616afd26a15900f2d3fbc06117a24b944fe0db94c338c29e56d25bbd2a7dba3357324e6d8074e409a276a2d33159b633ed094c69250e3a34b6712185eb29b10c394d2f21fb8a1489e87f491a1f21fa085a02cfeccbbee4b2212fb54e54cdc209e1d6b5ded13c8464279a9d89c22e26c90f8996cffc63481bd22ca662a9514102d048d690683dc3d99d62a36347c91cf3d0083769a5febc877a68af7fc26c7df6f76a8af134f770ab61943ab56316548646cf10a4dedee7a41ffe8a7e0f23a4ef69bc3582c0d50d7d8c9e0dc106f22b39a297a6ce83d8b2ef372c7c3f3802eee1f3b1d84a254edb74db390eb3bb6b6eff569305011a4d4f74448ad8c151be2771f6be83340a4848675b82580309646482718a2721d2c4ed28826c838639959630f09d7352bf9fd51ba8b49517b15a82b21f1dd497aebc7b766383c1be8cd16df6bbd7982ac3edb49bb62f4c0ab096e6dc23bba51e9f029c46f014d1d41ca8e46fd82bc17b72fbee3fb5a9c0d0f6ab64a21c7efdcd337a9054a514e21318bfae7ffe42e3757bd9467bf9d6038d9e2adb9ec4125739ca5b5cb5674c5a5da9b2255050389880882658d0f397ba16bc624e0fdf176cd82caaec496a2dbc8ca04d904ddcc017eccb3fd769feafda6f280fbb80da0b9a4d6e9815791fa86de1494c15e29d19a628b1feaea01682cd2289ea9b52c742710032a2cc661c9d29471e555d124964ad04ad7ca3ea80aca611283aa2a253d4299f6ada3ff1dd61a130bfdf67a40ef0919c7b2cb825abd67286dacc280b136342b6ad38d493aa2552e7100a3c70c512a795d6e0e22cef1132cc14283e3c7c2745f6f6024ef51019c4d27b7e7772b6fcbb0d640f907e826d0c4dad45dbb0c2105f57cbcf989a15b1d2e6f11cefbe898c1c45ff9ecb651edaefb77b25fc1fc0862907cfc37bb96cc123420978c71d802acc43dab425771300ad54684c4b4520b3395453209532d256744fe33ada93c1f13061c34da0caf82bba0601d80862e5af73f197db5503c720c53cd946a88ef5d63aa93c1b247cac5932a0dcfe2a926f1c8c6a3c561445d43bf74e58bf298fdec8cf573ebb3ea8bb66b27696c846fbc477e311aadf56d6f3ac083a122e5d51eebed6e81b894aaefd58a6d88c8c885d3cab491bc5ccb7efc680f74ba38c684121861275463348aa5f2b4603761bd0d0da2f82e68ab35d801436bff812c8d34964585021a29e08e42a1996c063b8fcdac660ae7ffb905866c536ad2389991c2bfd5e110fe2f1117fb727a27591c2f4faa8c75270144fd4706329548a719c4abfa8eb8184f4fbcbcffccb41fb536a3e933492c53de5505b472ea30ae81d7725a51bdefcea3034f2175fc5c9d9c8e824ebe26277ce999fbb984427b564519b3dfb4a105070462b7ad18076bf21f9ebc1cc20847f866ade603e437ca33744a41d512e17e18d09e0b6810e56fd13bbf92851e4d9a9849baa3640e1a9ff8f3e036a1a16b4ddc5962b0a25c81be070fbdabab3a126147164c85ac859803cb9ce61f8988f54d791a5d856cef2acb73f7f3f5bff3edc227cf6699fb37aad4ae6b227f4d826201eaf892574b4c8e2bb938901ac30608104bda126ffc1f147f720a2ef9420a36905d0ddd17f98d452dd1ad4ce75b9d87b39d90f63792a037573b7b3e6dd474b3ffeb5e36f5951a338da5bf980cec22e3e55bd2969012d6991b4335b8e1b2c84b868cee82068970030de789a1fb89be23276a641247f627d8568c0424d02a10b035c994dc0add902ae671a7073f680bb0920770418372ce3df8b28594576fd526171126e895a59536acf630084554775447a0939852758ff9d564bbc472e4219ffdb036fc27ec40f4f3e69a5178684bf22caa8ac20defc06d4a6a27fdee6417f63f4a2d5211c6e6dddecedcd728624d09cad89da2b50c877e7bd64e469735d2c3a83bb14037e8396464ab06b28dd272c0796f6d59868d1c987cf3bd2bfd356b39985fba507854ab1138a2e0733ae9c16a3e375580e5c34e4e89bc39fce2a9aa7adb7dbe139f53ebec16ef24d61e173026771dc1e9d347d326d70c404e9828713370d46acfb9abf8d72a5dcc91d847a60d4d904b02556f6a8691b1fc1924a6aeedd90c23bec865337824deb38e1dcd5160c577c8dd045b3c92f8c007d64abda620d546460bc16bea30c6660e4fdc9c4e2df68e0b44d179cfed32e56038361f98a8c1d1c6ad8ff45f87ff4980abe40993d6a29c70d0c1e511c5a771f54e3c1628603870f5f0b6789a1df9cbf4b9dfed1bc3f1a909a9996e30e28f36327d44332f2484f00d09100840f18782fc04de004c881f7a585fa8cf632ca9bc081b7a62da3004e430c1e4b5ec5b6227e1f2eb25a32885d1b761e3461bc2b082eb0ed9a207fed83017c184ab09ba891e7439ff5ca51ecce239e39accd4d25ba1ec4a02090dc0df364121c8aba2a5d08922a04c29822e16defd1b4f0687a1d9c644ac3caf6c28cf29cbbd8f034cf1c18c5205d1cd6efe2a038d522ed5351cffd39552fdbd86bc8f1417e1022151060488bf3b459ffe32e121412af8940ebc5b4b6b5121e5b969f2cf793f2c6d1bb1a6108867a8bb047b5b569263bc20e053a6e434358e282abc20a182031734530bcbb840b5b6bd3a0064bb7411ae8588cbb48ac9a95236f62cb17305ccf0ac0aa31c58c152b568c183163c588292696981862638a892136a698b162c58a9161588e6d688008b108e87fbc2c3ff96cb9bb805bcdfe8948c0e33800bfb061132e4092cf59eeab1d52427fecb17846831aecaf6fef089af527801aec8baa91b458a9dcee3156146e8e8104398b3b9ffc3c58b675e0bf8b322706692d2693152fd8dfdca442db73ed8882fa9327064fa8905a510428a0b2c7d1d586ce4b568eca629a5015eebfc62cec4c88fd545bbd6f70f0a9d608a05bcb9563882dcdc95c9ca2043dac48dc479f9d96d63c86ba2e7947e1f875b031ca36eb3b724d26a219fe1f287d6ee314a66f3180d83c2cb6721528d23e917cf00b569eafe7367db7c512055470ccbe1fa2c7a96fb0084247a18cc95ea625c92d4dba92fe705ce1386418e008d95bff4583e81b747911d510d4ab37fff052412b1003aef4a053bd7a8aa48c18b8027bd6eaba80989891f21a4c16fe923533a889ae94588c1cf3c8c4212392016d9a4e3affdc2106ed380cfcb2eea1c48cfd861c906570598270a94a2d9a655f04286797d529f712219d68fdf8a19c50d1478b878ff4fefa6b2fcce8a5207a3409818a2aae8f49fc99e80875e4e31485c8acb393f6ce16afb9d37343162173c39d39bf3a6af0ca9e4115c1e362512b75afda4d6dd571736aff156593149e3bca5cc61c8dcaa016eea0d02713c3eac8783bed1756463a47397e7434a86d71c9192aeffea81c8142c78db59a8ab60c0c16dae9c361c140743b12f5d47d238a81c45ec9f47aa3658461c1eb8d02a4e410588c82586af77de8ac63f3715f4de72736b5fb3e74d6b1f9b8afa6f3139bda7d1f3aeb04197007082e7d9f58d46ebad095761cf45750ba88a32febb5fcd5a1cdc97d65c22296a37221275055d6e1f2096c042401688a480dbb09ca6a51f8d63625718ffd077ed8c898a593537526b6a278bad299080e92845226b580030cb372cb878de44072f8a503d73679fbed198ced53b49ab94e7ec0fb1e5f699f26397ee6cd60b370fcdf94a497de463a1184bee4d2e0fa76327558bb54bee1b0f146bd525b742afa458bf295e33aec0625638907dd1b1db5401633deaac52f920fa8732019b1c0c482265b9984d58c3402604d5f8f2bacc9173cf99d6ed959cbb5c16b5fac0db8bae785be0dcdd40957a798d836730fc5355f3a8cca7d8133b200f61df80c50f71ca5b6d56189fd3e0f4b6dbd65d75829ad4ee8b3dee82a47a5bff336de9d9ca316d75b807658361e25906ff0ceb7bdaa0f9d0ba2003f6062d56092c619ced13c18c8a11bcf36b7ba5120a3441859ec021b3fb9a4e67de984a65559d080c5376adb6939668a7a39270f01a4cb820c8281a417032191e22c46a80504af76f47f2eb41212a3e595669d57a14f95b1bb4e9dcf2d53f51d64f9fc37f0b955519fc03a3678ebe0eb67fd476f0c76dcdb3c36241629b4b89c995c5e12c74d195894029a302c3084dc8c272bb05f53e79a821574a563426515b665e67277a081d9536b832bd81bf3adc43688464c352f872a6c1f8934fc376f0bba829bfadc94af27b6e90773862374ee902975039d74997887ac8a8a0f085de40f9a44078b1afb130f68f05e0bda1467c99813668ae84e7e8a99658c36111d51aa4f367761fa895cc84dd291dee442a383f360ee1313168e9c4c562afb08f747c85b416f2265f3e4d71aa7fde0b2e64eb6c4cabfd2865706102b22f1ffc421acefc441bcc9fc8af9c2656bab812d5ae6d58cf0c389a4a03df7f50186de7e2d9d1afb9afee3bb335813865cfc859010cb30462156eb35889c6151a9ed2173e0bec55818b98c89a559723a6dac20624ed500e52cd09e74d8a2f4ad31197a8ad3471fec0f793320ab4adb3373fe2ef70afcb78d07f5c67a02673d8c196a2dff9cbc3829f19ad53f3b639e5b9ae35fa0a9364ec9e418503066360154bd5b5ba909330ec96cd0f3a86cd0da1b40e7d324bcc0edfe00fb46fc2510f33fb8c707e4d5773cfda14301f12802391da996055909e92249bec10cf86b15fd7f516ee59f7dfa50b3c79c29f803d546cece5ca93cc6a82c15f75b2109be02865ad1ef18272264a3034fc068ef9c03307fbb531a6889ffd350d2e6d2337a33409f2bea025ef69022626ca4188ec1036907a66408ea506c3e7102d4e92f25f8819d55246d8ab1c80d3772e9dbc94c143a9f8ba1734bcc48d6a0767292b35df342226a51f78708da20fa7a708c889dc5dc80a72903a1a4552d65c261110b156d1cc42d9adaa36e2f00cb2fd48104fe04cabe231129f1e87d72128d700815cdb95baf28d1342e48409f73054928a613721ca0d3010558fed8d07e02fba96cdcf8c41cf4c49c5578e2fe72064e40a7a4adacd6ceed5f6ca5989036655a15d6a8c919e2053eba13d14fad9ff2e0932a0088676e0c5635c0c431cb41608d96e3c63f2e1b9cecdfffd5296ce1f037e377b087dc7a396ba5717e94cf7a0b145b65e7f45e287043f5295ff626abb6df7e0749191d04807b65f29399a8c9c7b243b780226dee2b80a843035cf9ac71dbf67b97d45d664e4856a3cbaf3484b2b4a36e67e5f1d4db7c424900c283682c4ffc967ed7d96d330b5853cb5fcee478f071034a4292e64070ab538120cd9f16f26b44342deb9e2ef3d503761d8c4188c9940cbd7df10db32d32c11971d534c35e2f03d21e3449f7f9901bf620a54157f6075d885ebcb0fc11e593649ea21d1e8fefd6ff92ab9e1ad9f766501d1286e4baef840edab928475e841c7466a2e7f72cd046979efc2bc01ac46f2ed027bffbc5a11fc19003de67ab6111cd821031d0c4b3329961109b82afd6157d11856bdb6e91508d4e26c6c5fbe069b568051b9cb55e03f78289bd179705e81dc4558c9b7b712d40cf415cc5b8d98bfb02f448e23ea3381d5c16b1b4c03ff02e2911610d6eb3c6c16fd1658031988f94dd4aa60bf7218563f26eac08e9792541ac0895ea71e7033d88dc9b724b4ef500a4034523817367db63ba4bf4cbfd360f99d004bcb7503a580c246c1f55be45be15d782cc23a01cb737d3aae65d6287b7bfc3f0e848e216de472e6721849361fa826b6d2c38cfe750802170d7db926b963705031a2226e7a4f796ecd6daeb796d2c8c96fadc5fe4cb334978716ea948d9dcbf5b4e2c0e967db2be42b45e32890b8cc60ee6cc0aa4445f6c92712595089bb1927e8221fc26669ca9b72a976f2b02363a4caf1c9123114869c0dbab1e90142d17b59845006b787ff35254cf664acb83513ab777cda397a0fc5852e56747fb442261f7108c8a680db2bae66ccb6af1e54cf48a757c82ea101cdbc67ccc4eddae547ddead67468f520d5a1f7ec4ce2d95e3c401cd9dd1aa16c4cb42e8aaeaf23227100f6e0f04f5302697b120285025985a1a91abd5598b65db31185583517450bfe2493ead06ac1eae64d6379132c6fe3ab7051871076c3b0509ce4b683ffa2c86acc843573da5594b4f01e79a5ef9f5a1efde93f594fd37ee1eba18d32c21b6ba318921e1307ecaf3cb7e6f6185ea4cb7e56e875e9bd0bf2aff4aef39535008a81a89735c65c1bef113ebb4f3698e4e37e79cb094feb4fda73b13b021e9f8af229fff4c1bd049c99785efbf97e0f8fb5b77cbef7aa2febfcf0a433836c99ea4cf1eb210d3603775038ac90f00601d3635b67fbeece9df095d49e02bc663e642758c28d62639cbdf7e5c122812353dffddcc90c4ded4acfd9115cd6033b6569d74da7109941aa6b9d841ec11b8d7ffe40f98462dfa66a35e029da5d09951ef11f5ab016f7a5ae8d9e623bf0fe802412c274cd4695babee9e489bcaeddc7caec9aeb1f0acc2c055a7863f93cacda70848ac5f8ef62095f56d54211451b55beada8722d745752152b205b848141cc8230f3097cc769e84c88c66a3a120a0f924cf2dc0701ed0d4a060b9c839fcedb5e765c129dca04e747f0ff33e44842113ad8731d4136a53a887dcce0accb0a95815693c2a06947aa913202922eab237458320df8b84b1690daae4b05883e20de3c3ed8d7e000b9a8f46bdbb413bfa429d8d8d41dca95b626a58cf0e899699c605f7d926c3def34e4baa373f9c64697dd6d2334248057f62a280ff82cad72bae9046aa3c2cfda29daeeeaba0c66e866c0669f4b5a6d811442abc579719ff865b2bb11591b6a6547b3e932f4e8e094051cd91059f95bf9c043130e722c40e45f46758dafd38e845751b0420730b36ccce914f17b43320031f2ee2255af205215b8a01f8fdc306d829e0b7951fbc52ce79772ba147b2f0596831b21e5231f8fa67dfe224a05093f266ffecd7a503f844371648527364df30fdb0892e5da63e635ad11e3607518de18fa9ee317ac0fa62f2705cd7250c36742c51acaa5fe08a6e933957265f038df98fe8f66c001dd8594351c6e87ccbd7565030321a18035186260f10c8d436925ddd76656faa0def02e946fbe93ab516eb0f9ec8d7a262cb3c5384ab2ca22f55f9cda59510707223e3e318550ce1c208727861272eaa05628582712450aa85b471edf9059c7251bef6be235ae509de9868f2c92b43cde188b61de82a585826f6b2d23543fe2bd496da6efd9163875c49aee285d18729de1e0ecef36160291f2756bbfedf5d87d59f00daacea958c499c6698a7afd83b76403701942321eab9197ebe8fdcd17768f53ef0b28f9fbfc7d43e0cd06a496dde5fc5adb8357d021d2f77e60f93ab6df796f2eb32367fe0693d3c7ebff9560eb5e59bdc3fee7929da804291b1c326ce758611c7b9023f6511c3c6e95686ab62affea3e867ec8b42bb689d45d50d94146ad8ff9fcf1db6499b867e2549aa903e8c5122ed2255db027b84a18255a9eca07f09d03cb6344af1a511c0b9d4517265ef60f20140950ef150e659840b6eba4642f25c9640308706169081530bc2343f62ae5a0f86745be1cf8a536324c7a562873a587605537bfb2949e740955f832b8faf3ebead64734891bab3d47f9a075377bb248658c17a0102fc81fe7de86371a5c64dd01f066dfc0a7d0c9114dbdada67cb137062f5d088ebc3ddb90c794afaae316c51bd4ac3421a4841097575405867861a55ed0e443fe98acbe9327158c8d289c69a0c0ac8ec4795fb3cd09ec3511292729c6e624905a51776ef01a563a49a99e13c1631cddd7872502f2cb796d8d694e93c4543d63a0936713a246172380ce4b606295d5c7e19e4839096bc33bcb9c33dd1a159014c74b6a13cef532a7c06eebca6735ef5d46c43748a68fae31adb52485f33fe14a4b2958910b4a273079966426971051464c81ff43d3ab8b670abc75bc5d181fff626dd733914b515a2db416ffbf06d954c2a2e782c629efe81389c49a5bf029786347565d625783dc95833ac13302435612eba71c04fde9067553fd53af2722e5a619d2867e578da745e6a330789ff8aefa2521ab0324bfb6f3d2b8d841bc7e68e26bcfef7b8b5be68a15f857d0c6c09f4eefcc568fa68560746c1cc6cb445f22f6f4711a89dc0e229ed3fd189575c479f04539be8cc8ce4d4b9bce199e1a4f0aceec2954691cb816773453a722a9aac75081a1b64417049591c9a20bade1b51dac12557bc487081117840de0294b484379140276ba191a6c00af0d5abd127be7a79379bb80f2382eb83c705f1ac02124a75da8226961e3555f581e94c9dc9cf07dd720e7d4cecc60b158c91a3d8e1e0271caed73bf3560d07b2e4aec564e7eab7dfee158a77ef23f2ef7bac3e8a521acd65c2db712cf55c579157ca0d50ee51d822f0baa99bdbbd6359c0ffc49da000728dd49eebd2905c345bdb05d5a2d8903068e457308bbd95383d357195d98e712909c48086043f63df24e79128d8d631a6f5ada891cf125e6e402d41577a081d7641db81454f8268b03c70d2a38b6bd895c4c92a5cf45db6db25619880f387a52115148ba1c88722a76d11fa80665d65a905ad519bf69a749022ddcaa61a62ad623aac1548cee8f9e2daf5df3a3021ea52bfd234d50394738c521966d69e2e9da408aeeccfac7b00427b28ce2179b899cba7165e69156a0f801e89b2534ca5c95340b183c4f32176b77673b6a177b638d7e08f229c030a7f31817fd7414b34a093a4d7bd6c4cf8b05a9ed091e6129e66ea217a007378876faafb2adb2f78cbcdb144ff661aef32eb1400eb13f1499fd88b2ec35ee0f2ae5db114e9789056de4dd663af489cb6d921e5293a26f289f665d4609f3020bc2a040d034f495a12139d4e035bd33e051a7b544640528e5a548f2f52ca58e8801cbb1ddd510505677c524747f4d65c50a05250e3d69b49979a08a1b35f8a765247dbfdadd84339440f2178ae6dc46b9a089431d4013b9298c270a00c9a78599e97ad8ab1a39ba3e3c45d9631bc629cefba0df5d5f926113d30cb07b8112c854796a274b94d616e091acafb38f1ace20a9a3272d2019b1652f8e2065faca35bf88972f022e6d4cf04840f41ad7f80cd10a4b5365211edd61d5cbd34ce4079133c75c397ede2d43330454ecd6e526e301775792e8d6deffc59662352757f1d454d7223eec5fcb617cf523ea301f35c3694cd6d49e374e9eede901841ef8d87f118b57e2595d0a31fc40ac5c946a7314611fd65e3686450d8995a9bf32d6d2ad1bd18a15eeb89217d5ab0e81b484d15bd85d397f0b8b39474f54fb49deef37b389acfd984f60443100e4a1491135b1a7e5edd6f5845412d752535333d1536f42c0d578cfa53976bac433ae28c51d2a0f04c4b153ed763fd3e88fd1f1f27d2abe24a682d3b46151aace5cab83d996142d219fa5ff0699a5a137ca0088dd4c5f325c2eac80038590748924cd1d68befd8609625a8ca19a0ceb5680a37bc7f186b8a20f6d48088d1b53fd40554db9196db1aaf75b1530a1f90a1e0e3d2a15bfc11fd2c844d62b849e2c0da5cb09f4c970c98f4458cb57911c8c9268865a0da290e1cb075b8420e73a88a46a9157ef79a5957826c513ddaf57210ad0ccd0bac65dcc0ad39322cb62b065804d9c5f0c7426166d6c9a483f67f746162eb96f3c0ead5d492c51954a33ec5ab00699fd6260c2124f8276814555efe7e223849320e862862fa54776c2f8e7a130992f3943429964229aae23312b01a13aa90cbc30f621681ba912800d731b182ed234fba29897b8a4bdba2b2ac431c8a9d47b69c74c11b126d12abfec145e02d9cedb1559e87b0108010062fb7ad9a81ab92344d5d7defc194304d80680e19ea087cb29fa16ed7c94eb32cfb34d3661c025e5e3612c46f0458523a99ddc8ff888120b30624bb2f6811602ef08b759404e4139fe8ec5f11fae95e8eff74119a56b2e2580e23fc21ff980d3969356b22173806c462759194a11b3c3d874f50ad6c48d9ccd6cbea5290a48101b5227ad4701d50cb691e16a463fccf22561c87bde20ec2636b352f0883756a22087c18ce34fecceda57c4739e9ce9e9b3f822e8519e56a4d815aa05cef58e7ca018794e6fd5d187b9016c5f49b609b104e5bc8a403449cd6e81411f86dea49b2cb0f931dcd387097f96608ddb25e590884663195adfd2b896eabcfa24b44d34fd14c660a13dd9baad3f8975c8c0a3c60c0b9e2b2a0db570b1e8c3152e9710d268d2bd6012ce55ecc0bd5dc6b1247ac82043ef3dd9819f9ef6febd8f2a03d87b1640e977c27666e8bfd7246a7874c86d67328e4eae887ea474d7834f9605e257995760f382f21c3ed009550d088a67c2c55e6a64a76d2d9a06f5d7d0d6d0b7cefced1ef61bf1bd7b16366a32eee4609bbb1caaf9239ac971b227b49b698c9a16265d9137081ca13e93bf5cbed9570ace297e130a2d543f8fb5bace9000fd96a2fd1f2f67958fbf6fc1a47eb1430c034751f370dd3e90bea4825489572c64525dedcd8a3fb7fe2077e11bae4fb60b7f9c7a0a8bf4b22b59594c77932de0bac2381ec5666b6a6bcce582dd35361374a5effa88e43094f62eabea099315d248e02a6c30ecb454cf130f2e8e6080e6dc06bd396e3566742434f367a82e600a10e8200bc9f07d1f037ed09bea8ee76d912b3befc39c49898b53c4deed90f4c006b5aabc82781c39071bb6c9ec0dfc5754a41bed593e38b91c62a26f7d8ac17e8c0471f038ff6cd1e996c2ad78d58ee8b896f3133c1a4c778e56b7a28ea176856b739238f5ced894fa1339f6dba1a74375026ce78d8c5c83a8dfdd1399a7e35a0b9ade2b9b4e8fc080498f622ff26c98935bc5ead67681b7b0929c2977062b81ae00409db6dd4c3d0c71f15033fab7278a6935f25c67c42accc65c30dba1239fe012473b98b3f170509ccd8182ed4ee993085d91c1ebdd87b8d3674da7f016a40806bc2edafbfa7e248c4ed617f797a8cf88e2973cee970293e170974a5ebb18efd7c29d531c9fbd53d52635d5b50d18419cc82a9f6e3e1230bfbcc455128af81daba1f79b15f8d7e160d276670869b7d6f40f89f065d7a42d59b83e68432e220815647c68b86045ffc47fe4bbc48e97730a58fa1f02c8a5228a46c5d320bc2a5ea17db7fd8a8a8ead05c42ef5388d6aea5269521500d4ad5e143bb649ece3810c16d8bec78c903f4ca5f49475b0983acce0cd1fe762114973b038781a73257ab20ec10b3df8377711536d425244fc121f4fb0a5cefe4f907b8ba459a88521d2e4bc09e5d44a7c73c0a4e431f8ac230798f03a4e540f4f16320ce640ff5d8d9e31801514aaab50fc48081df01c71b89d72eddee7fcc3fcd61d6b3f7c3be1bab9f1e5d9ed45537601f57edc7088de8ed029eae5d89115b981d7ed5015a812e6e4db3e89289611beae7b91fb77b93b15429ab5eb6eb9fc1ce9f0ef28581a197ceac0b97b532b8a48f1814caef3603334d7ebc31da293d760c7c2438468274e8585bb86c42b1f64c7f829b6eb337cff3a016994f04145867261071ce89a2bbb4e88350cb0d8d7271e296e65e4c8adaf5764a580aaf36136f2e9fabffa39bf74cf568a083107b85a544ea04fb94c8106cd075bb0c5aca62fdacff9cf1b9d40b40817b3cf77ed157d6f66b866e3f471ccbaa141cc8bc2a0ea79167aca9180e8d0beabec4a6137ae78e3f622f088f451fd316aeb074234eb567a560ddce56083fb4365993de2174062394438edd07e1d5b4fe879b6bcda250ec90201930f567ab0a33957c6c4d50c169eb1e3ba75c4d2bd2ab37f698f97410a8440135025490c3ee7826ac269bd9dc1cb75d23ddf3b7ee967b6dc5a0d9c68c9340e74c1507c8a906a7008da0548d1fb8a48652e4df4084aa392b9038ae23a724741f2459c2f6e51c2eca3eb5fe07aef355666d37bdc8d752158ad4096a7c20c3fce9e2f8eaa0a4d4385adfa1e950014a75681144eca53202608baab1952070c378c6eb275c9a43d2232e3d58ed353391608df785f1c4c15492b24b57fecd362d03c749e3244d6721b4968c82fc32606d06b65a816192e13d49609973fb4fc9e21f2ec7e393438e8366108fa2842250d795f99b5e46bd1f28258b7b639cf95710fdbebe8cbedc15477d07090489fa3e3df4e1a21e1a3c6485b240c262023004d7a359bcb248eee241707a20cd6b7f29ce9cc2202b917a027e955dc3317857d53b54713943ec9936530a95087ab055f9f02c38a751acb3a26fd4c17ea0ec9be458bff5a5ef551673b154560e2c209d3fbdec25767a979a0b696dde502fa6ebaf87c91602664931ce87b2bd61d755b3226bcae888dcc92429837293ace95f6606295a1e713972fbe7c787e901cb4cd9e3f68114c4cb9fbb2ac16e729af48a8b00c508c7c8972b07832faba543c2f77b6299224106e12058a942128a39e8d395f990e1341ebe193fb11b014dc6d459090ad5bcd3320b3bd5def9abadef8430607f6bcb231d22ee6165026e4b6b9b2bd0574f06634c5c61e6d5662dcf3860c0bc5fa307a4916cc26ce8843aa423c386dd1a3f0087e385c9c46198f00dea0f1b18e8a85f5f75dadfe03e8aca7e13b094c2045e9ae3ec95297c072bc383d8c7e48d07485a5d07023a3d76b00960866f50fb80f1710b4fb6b02da84bca9811137cba5daf270a7b1ab528ff05212314ae6309bd3b090607cc3a99dd4e15cb096d9870304ee060b93bbe3f5d91c3de21a29515a64aa6309d5632d8fab9553b2d1e004b2abb134b53b4d166ac5bd32c321efaadf20c7edd2c2410a99cf6e36395731df9dab371386f460708f307544be5e996989d92aedff4d3f0b1fa81d25146ec45fcbe9fbfab023aade4c1bbcf39654a08d5720191c62c898b78ff54d64cda898f0d076c1cbdbc9b6f74ce178b8430cc0bfa00ee9b1a8af07e2174073016746b2b8407b193ec736b1eb36f5acacd74d10f2b45032a0dc2d59a75133c2b309868faa2fe41fa5f19b3a45f261044619a061830e579e3da649d913d64bf4ede981abab5e0abe7b8a11cfed72a69e9ee6b55e3ff8953c129270bebd46c13b32ade1e0319c9d88a37a3b3d613011241cd00e12878135a12decc8904c8d3c8a46371ad96c99d03773e9b228d569c144abcfc398708431a9242a0143be96d720e85980045ac85915a916040908a9be54b241359760420911a8e19df39e6285e4d0687cef18df1095c7d58b6e16a545b421ed1ffe8fd2041b33a9316d4a49c43b9e542bf392316e4f469c02ccf3325190da3a4975f22a452af7258c63361a05fecd94830f277897cb950c4cac5c4112f279f77234eb569e7977c0b7cce4ad498b53c1577e06059e7217ea200953a74d618bd2c51ff06fa1137cb1002cc36c72c0a9584d7e2f934df610c8a3986ca1cbb3caf4702d43c59c2bb1a3ce4feab069e9767ef8db50acab5b3d371f2e6af8637e37e48e25e4cd9ea044ce0052ea7064717591038c98e7355d63b46e97cbbbbddf79f5b82527ba9d50d898194ebffb16334fcd5524e99fe3f668d94ce6f7f22dad1420383b52fbb2bb722238ffe500d7a50d17ee4d95c7e505135f21951fa9a02eb297ca0dbdc5b371192029d18fc16a01758a72a514df1eeb80f59dd7b26650eb8e101c2444498c7061361fc03f73637a0071e7660800e1f9c3daabc5c75834d2e99151c60881608288a2438325f30c38d2656f0410a1c3a10992558c2c7860c31a0f003ce664a294030061d0f8eb2a48063de3004cd14434c1e9ec8e1619eb075c4e48192052851420e73c8830d26c10fc81637e40c93aa8a13062f688801460612c60402c3690315295081e7867499988a06579c385831c1f9c2849db04301ae98c0901832d8a25c8105884d4d0bb0e1e8b4a2a4e2050c4b4860c3028e88a628279003093eb0432245040ee0440943145024e0840b1aecdc9628457852c3881600a0d9419144094c027b0086102031de5044d9d4e40b2d6c6451838b22889287024e0cb1e3a540080ff850d6e0e288175c053c4900121ec82f6e8081085b1343287060037902132425e0020880d2932206520306f0e1039218b80025022d903c4cf9d91931e5004982a040ae60c2111356380283114430218b3ef0a6a0e1f8c44c710989240b1723007cf820ab844e1ad5c02a00012f5c5124b2923d4a40b620cd6048001590312b38a93838e0a8e2ea3f8b2292e8808191968e17feab90a081960264b0836ee2ff02514ca0855098d2430e35b000ad81678922bce8f1df2401503d3ab0f1420dd23fcb0408846cd821055bc2ff5d0a20f47800002a4032fc1792e282070080448c4604fe77882064c888a5051726ff660fc61518c1c30f26cb952b4bdc7066f1400c43bec812810f50c0c655143734ce16591080421049b8eca826495891058420a86849579865b08229b2a0600440025990f01b88e144161d0378f04080ca5708c112596a5320398bf0f103082c892c331020248a23a80020041e8a0803061d88c20195e6e199401061403180162cb00c214323cb87308aa8c0d1908514728041091ec2d0018b0e3d259af40f5ab0218c147080e20209f8818a1f5288218c0e050c8a3c8637205ca085308c1ce0a904145400a2032a14c210824410597c360cecec9884c141007ebdd7ba84c8094bc2904940023de4c0802c5b3f7430aed0220a2c2c9820032ee86005830905ec00bc8ae995808b140c209ae061e5f1c1ef062648c080c24256023c60010e9038000f8c128c78e2a8470621e800104d60643199b2041420384208902330a2202014f4c2c70f040a4004c6cf1536d9131b3e78a0c206060e282628d101178670610b1c307e04bd040e7030c24d033cbe40819303a8600b2d3d81caf1050788385b0072f2a22a68c6170f188148c631c9043c6005f3c5011a90844e8521c61d9bc5f505005410434d7183169cc0812fbec83268f190420f382021812dbe480a8114121b1eaa1748b0e20b1c0250d1a00727217c4134c5173321aa54b8029725021827bce0224bf1015f08118413504b78e1c40ec3306c68e0852336f0ff1f46125e60000519286106c900090a124822a9a535f8279962c4c0bc9032928cc13f0c30a0e4773c9d92eea8a7a4dbf5ae704e384811beb169f55a03bebfa3cdefe5c61b1bcd6edee36aedc6264d732fd559a816a2b5dee6e23a243e7f5bf53db1ef777011ee6d666b29776bed0e6637d5390675cf6ee73aa84e7bfa0a7cedbae839718507b66859e0c496131ae8822a089b2c340caeb0910415978266e1c520320a81111d348078f47004304a0710d06a99304015192588b4c32c13441d2183864e00aa902001ae102108c09127b525e4530a34e8c0c4c127841b4174204a098a7039d11202255e60c5067d0a1d191a4260985020c0a5668022f267a0cc140881c1162558800b2c688558900e81a501e96a410e8b3b52020f5788b08109596c0cfc177f5af8971510f1244fceff0e265b6fc60cf97fc2ff312aff3fa504f2c206fef58213c8180de971a6e453d38e17f4bc5760efa8a63aecdb6a77a33b384811ce7dd5a9fe67775a52cdba1bb866161fe9a08274fe9f68c7cea36eae3dea66d4c50555a3bd79a88b13eae1d13c1bfd7fce9adf8ee65477540f8d485d0daa47c73e649138eae290fa7eeafb88c7c3ffd74e1d3974a8a063ebffc6c6d52a50edad4e751dd5583fa81cfe9ff7a78e1c43b59d9c54dd399db77b8669cece1c2dc428ff6ffecbcf61138395ff4f9e38a8fc3f99f3ffb84ff2270e340325de84bdfedf84fdb801c6e7f4b4dda8e63eff557fde18f2acdad3751f737abb3db992463be40d1fffe40ed2858b2b78fc3f05aa66a466986694668efe9853f73de694bbc79c72dd1e73ca8f396d400f41fcf0ffb03f6d40e0b4e18006fc3f69a3871d6ce870dab0c10694ff77f56fbbfac7eadef97bd4ab2a448f6e7edda39bdf187efc3f0cff020194902ffbf4cd2bdfe3244d80f23246439e1c60ebfffff58213e0f87fa81abe219b3b37aaed8b3376374e350d2cfe5f07dbecdafc49438a10ed99c5eb4fe57c0ff16eff1fe74f1a286856ed386d33d63da758bf5a2a100b83ef6e35eebbc55ca5f99386efffb9ab3b9add2c44b18a79abe6de6e14d31802dc386d35d6eedb33abdde149c3e63fd8aaab9add7ed2f860abba9de35477770f872f6f5fec6e9ce61fe9c2ff17f973460bffafd38d62bdfeb210cdda6d5f9c6a57f756e3db3f80b6c4a75a732070bf84f8fffc27edf79a55bbee394db5cf7d8ff00fac5995a77b3ed244353ff97ee9cf03241e203152c5abe2453d453d352d190d1932e43ffd6d6d6d6df93cd8daf200c9d6d6d69691abadadabaaadad2aded6d6d6d654d4d656d4d3d6d6d6561391ad2d224b46465b5b4386fc3f07ff0f847940ce39fb7c3e5fafd7eb79e081071e2449922409122448901c3972e4881123468c142952a4c8d5d5d5959595955555555515151515158fc7e3ed76bbddd4d4d4949494945454545414141414d4d3d3d39393939353535353131313131311224488e8969696969494949492929292909090908e8e8e8e72b95ccec8c8c80887c3e1860c193244881021428a8a8a8a820409128488888808081020406eb7db6d686868484848482828282808080808e8e7e7e7c766b3d97c7c7c7c7a7a7a7a7876767676747474746ab55a2d27272707070707e7c78f1f3f7cf8f0e1e3e6e6e6c6c6c6c6a6478f1e3d3ae8a0830e38e080030e78f0e0c163830d36d8a0a6a6a68686868606638c35d040030d76ecd8b143870e1d3a72e4c89103070e1c3832c820830c6eccccccccd8b061c3468d1a356ad0a04183c68c193366d068349a0c193264cc66b3d9799ea78c8c8c4c8c183162c4c4c4c4c0c0c0c0bcbcbcbcc86432998b8b8b4b4b4b4b4b2c168bc1603098cbe5324d932449f263b8bcbcc85c6031302fa44c8c1853e622f3827991c562c4c0942e32315c4fe274bb9f7cb8dd6a1f422df97f0ffe6c9962cdadab7babea68a29a5b9c8eff0feaa0e5aacd283766160721c2adcae25baa573503797ef286ed9fe411fd93523bfe491194fe491386fe5f043dfe9f03ecff1ff933e67beed63477f350c7d653b3d5767276bb5d21cafbff9aa5ff96e8dfddf9ef3cfe776233ff4624270c4bccf5ff484e1896ff9adff3ff8ffa136680ffa9abbb7ff9ff69fcd3fe5ff7ef9ab94c19ffe7ffcbfc7f8c872163f8ffa93f5fc6f3d55f55f08da7edbb7f18b8717f37debdf7ff2f2effdcadd96a3c395cf7230e428483ad9a6eb44512f660ab9b5275cdc4564726fdbfd59f2e2c9ebb3577a70654e3c9e9a84f0fcf8e4e2d07e7878f1b9b1e1d70c063831a9a2c59821001b90d090501fdd88464c992a528cbffcbfe3f03ff4ff5a77902776b3adda84e796a3e3cb59d1c1b90e6f9d7df61abe256c53cab7d8528066eecea1ffbb6797dd135a3b8d5c222866a29a2f1a739f35d5d871cfb7af69da515ff6bdec1c69f250fff3fe3cff2c90771356fd5ff8ff97f8d50aedcada59bd54135f12ca36eff5fe3cf92c7ffb77ac54458ff70babe5bc8f10de6aa0d36eab455b1266e56bbbd612ef2ffeff927abfeffc69fa417dcada1ed915f60882bfe3fa6df3513b1cf75917cb8cdb8ddd8776333cc6eb17d6fb7bebe5c4ff970aad735a3ff8fffcbf4ff67fe245be06eadb340d8ff935fbebb5d57e336e354b7eedbb58bdbadf6dc5bcdea75c8aab8abd9ed38d8aabd67d6dd409ccb98ffcff127d9f2ffb33f491eff5fdc2bd0d5c48d8f5d45f330a3dcada19ad82b6617ddeb9a758e6e767feafaff2fd3f5ffa510264c4840024a2e36a4f07043012496443d21040fa8842d05302b920d0d0a84a8d08a2db5183cb1e26915800d2e42353709e0a142bb31809a39e4473c8460352941012d21f8ff2032fe5d02f8dfe0ffa9f87f237ffeebb95bebf1d1a8ba72a30ad4e9c0cd7b6a42b59d1caeb38e4f8f10aa877ee9d0500f108a6a9e1c76a3b5df2bec6a500775b9ced1ed5c0d6a576707dd8ceaac19ddab8ecb5f1d77bb2e920c1eacbcbc94ad2ddc9b332a204293264c9ab86a4cb0b160c912104a6c621048ecc24b7ae0c5300c2f61d2041bbd782ef8854168c132fc354b4cc046af9a2520c0b0aca6093632b14b0d082d354db011895f38560302ace65563e2c720c0c8f6c5b6029b0a5acca0d2a8a4318134814913135c353d6809c19958eba5e04c3ca4b49a39ff348362684afc429246256ea9d98281c12e3199eb63a44a170d131786c124cd072e982c5d625c2e3426083132b18c864913d2c8c426083172e18fc121e5c23198676218fc42f346313158f6829b9046241318fcf2462e4c60700c26693e9061d2a5e6831e78324ce20f5e30cc49f3660c8ea4188665c56a16702c31ac660147130bc1b970cb1bbdd03079c12d344c62c8989a2d139398ac61f201082696d56c994c9a60a3186cc61839b7b6b6b68c4c1c43f30108267ea9d932712965f2cc5246d384349261179a26a4910b7ea16162821023196e421abde097922606933430d88c41c221e5c231d8888961700b0d1317ab108c626a3ec01fc8683e78799199d08396101c0c9346b62c4eadcf8283d5642de058e2051ca34a172e31cfc4246e898972e18f8932318655c086c5e9c2e68b24895e6c5664bdb0aba6e63fe7433049a697d7325f6b0b9311442871e9ba911270b95c2e92245f5a704c6b09966b09b1ec267ee121e6cb7c2d211202ae2556e3a2c97ad5682dc1b9c060b8c6c42a3199d5f22e97699a2ed3e572b94cf33119c324832bf1932f1d5ebec426560b76c1258dd6bfce74bb0bc36a882586e1978b466b069755d6e064355a4b96485c0b960b93355a4b70257e99353093c426cd63578d964932c9e0caf2023c6038b178e04aec2263b8c7b5e87062c172206b604e264e2c1b1b1b1b9b7205371e3f0f54781802838087281bd8e0cc5859b3e34969033523868b0db21c42a3460d583983062b04a419356acc40a2316306b64143cea03133f39a79cdbc6a6668606862332bf8f5382458b32d70666963ceac5899612163cbf4c009c3002b48980e9c484833353b9ecca0e1a280b3059bf84507163388347ad998a979bd666ab462382c1d5f94363b7460296dcc2733d87489d1c53056d406ce9995b79283e6cd1b1a1e3566d0a8c1b29103cec42d3ab0cc60590c52895faff255beca1a1297361838b174e8c0b2a3490954c2502881604e9e9440387024568967de15a306eb0507ce81b17460b141c5061532070e1c8bc562317c63268a8e26240e5e0e8c0307ceb124c74c1417b691c3df4a33280736cf9336a3e1190e1b3ea470c2e01c58aee0cc1a2b2f5807161d5fecd8dac144c71553c795a5a62813470e1c2b5f346660367c2881b0de460e3678b011854a8d297f2bf1cccc4a0944039b7836c5eccacc0a1d4da8e04c1d58a2e0cc17cef1aac1218503e7c03c1c3847cd921e5e78490e8c4307c68171d42cc18175ccc4c0583a9ad498f239a60cc6d28165666536c5eccacc8ad2c62473d0e028310d0ea91c5807c651d6f072601d38783b300ebc03e3c0b01c76e868c1396870b4c468d0b841f3c21f43636666668606abc435ca174d08b8b246cd526963c66a9a4a1b73f6c3e7983807cd4c8a7963621c342f58ccaeccacd07096786605b703e3c0582d3930d6a90363cde0669833f00e1a1d34396870d0bcd9426306d3c0356ad480c16aa6d86a385fb865666686c6c68c0d1af84503c768e021660d1a2df83505eb85840c1aac971513cf66566656b0ce1831332b3813c3d060d9f00167e2171d58b09466d0927963c66a5c5f96ae182f3ca484bd6a1e06d764e20da4cc941b50215bb00c2e2106c7f8a00717fc010c96c1b0181c830783656a78b0d265e3c08905f3ba62d660b95e6ab46234582f34b61ace182eb18b0b86c94270e118cd10e7c2434c2a2ee58b07274ad0f47558dab866aecc6099a91244831f9f343430e50d9ed1e2fb293ba01c7162c988e22a3dae658a8c28244c4a0636b0c4b01e8b8c2836b0d8c062038b0d2c36b064009302a302b302930293022ba29402ab02a3c16a99a902f359318305aeac495d32d8158374e216fc5283f5c29886a4c1e60e12d3608c793418634c5343836bca16dccc0cfe18c63271376ee017cc0e5b0ae70ccc01e621036f1065c7941208268912c8dcb1044c0a0decc234a4c0f852210fec825bcc200eb04be9027381c12e2676c1641045535c300f2510d65bd90165870d3b72288134c0ae1a588794bf95d8069ea9e2c48c95294a20197661d9c08273c98802438343302a31a6c13c8c6938c09887310da6a959c203e39a108c4a171ab306c67a2c3630d68e293355669ca099b132334569e3d2c02461585c31514c38c03cf08b2d89130b86c57585f106f88a06d7e00f7ae0f1c035f8030e6a70c0f00618e30d70c9a306875923b501c61807ac86b741cd9b37650dc6c1c334b8a6c6c50586062b841d3430fc3130a669c2b00b4c29045ce92b6d5c349f4aa991414323c3898c03e70ccb706206d1601796d104e881c0b08e1c38f0bfe00c645830524c25702faf0ee05ecc580c528c4c5633c556c30953f2c3897389813fa6346942c09531602e5fdad4d8b6c022fb320696125c896964b00e9a1c3458305cac464a0b2e831a18293817be4183f542628606eb65c5060dd6598306cb95021a34583368b076f08075e264d0ec9802b3cac0b03869646860569436569436ae2ba58dabdc41c3dfb8f0073e4002123cd64c959a97e2c4825dc1b93079c50c72b9b0b02971623d96d74c951d505e62481951cc1b172ea7c88862069533333833ca0e1a607024ac660794cf71613d16b209f9c465741997905b2550894db3c646e505ebad6ce0c49866a6ca145c0bc61296362edc69687640316f5c18efc801e7d221e5735c184b46149c0b63cd54c1b9b00c2932a8e064447161988c28327c28817e905184d982b1ca9a9a9286fc9cb2243fa72c67905fbe2b06cc45fe93a42b060c0f2971b0b4c48287931c6507365879bdfc60de98980a15f385c5bfb09041f3a2f2f22f8f1413a324c330d7cb5e686fdef064d4bca89837af181aac107031250dd66b8aad86b3c452f203d6898b815d3432f86348d7fa9a021365888379c130342ea5cdeb3525c9e5c2e285e585050d678961388667e016192d334a9a970bd66b0acce9b22213616605c3c0349989802bf10c26075c8961606060609ac45eac3489c562313246fe808b61324a2cf6b8980cbf6cfd8dc42f58cb0f2f380423f205c3c060989a253038c63469609894d560bd88802b3199c313d813580c250c0acc86d206f6e4c5cacb95172c5eb0b85c2d2d2de40b16028e5c5f53702f9897590c062f36254ee112d64f2149db94130b0647da3470c29464165c0c8ad385cd58cdcbc5c56682d3854d18928d8813eba7cce420e2bc122e352d45bd13b8d28ab9530299402e6cda702517a50c8bf30733a8458a39055752c195af2955708f5bbe0687948bcbe3252dd8a5a685275be282652f2549e29224adf8500291b802641519125440a68a0c0b1916b22d6458645f9436322c70257e4d71b990284dd3e572bd5eaf170c0683c162b1582c167ba2e58996275a9e6879a2e58996275a9e284b927c79894992810be145b634b135616bc2d684ad095b13b6266c4dd89ab035616bc2d684ad09276c25287348c19919d89038b15eca17152a55aa60b560c161450a961a58660f38737072ea307bc08b14194ece1c6a60799152038bcc0ad992438a6d03270cc732784d318362b8acb169713ef91cf3c44283c60970a679629942c3cae7982f51b0e0cc269f43bea6d048295150749a3ef3a6c4c3d2a604e238570d960a33c4097124ce004b09141c240e01a723b19084808b2599b8184652da947846d66253e274f10dcb12f31617a2d266a6c49ac19ac19533a54d69be50c1b9d06011e14a01e060a04c8121ad98266ae217120fe43363b097f97ad1e0d099588f5f18c703a68993d284a18179a17982838162fa4a2018013c0a8302ae84c9410a9624982630293c4c1b959324732031162c8a8c0419254e13bfbc7c10322d3197982cf6125b8ac55e2038499c8cccd294b3e5a7c082804991029342e2c80c04018bb5b8c8605260b0874931cb9794571945091363c99861a97262c98072a5451614038633b822030a0cc7d4cc9c35301950aee06440c17a2161e34a066440c1cd389165a961e5c546e534c99a580c6b8509c149e2c812f6301bb67860cdcccccccccc5ca9f901576297ab86159c6b0b57621b95d35432f1abe61cc18935abb29543953305b812bfd88a38cd1a2c181cf99aa28a0f257ca08aed03568aa698b0a2294554801842c5344df2cd182e5c62184d0c9b34a5091b42e5158364e2b22c61b017ecf57a0da9f230292f2d4f92640cd410116899598688e0a5a605c360170d964b16c3e57cc578c5d40c11c1cb0bb605630213533e3cc53cd5c353cc533c3cc53c3554cc5342c53c1554cc5340c53cf553cc53b6629ef229e6a99e629ee229e6a99d629ed2ed7e320202fea0880f781f0ca5ab56938c70755f55602fdd1a98779d6bde921b485c0f8fddd56d11cae9d633eef179313602fdd87c7a8c3ca9ce4277936ef7134a6c778e7d533d35dc6e94920fe8beab769db76a0e1ebbea6eacece4eae1bbeb9b78bb1dd1eca29bd53cdd7715969e4a3571bbc3212ed57dcd7c0fb71b85aaed7e723590b7d9e5e9f5a706db37a9b79a8824d4c3f3a63a3da5d1763fe9a3d4e8f8b3ae3894ab4e5a27f15f8fb79b673d6594c138f31d741555d7a151ffcee37623880080210d510a776b443595d2c3e7f0e2c14182601edc014eb27324f79cd6466862faa74fcabd5111aee7cdf116df1c98bbb5636f379b41cf81bbb555c8ab8c200408781280a30dfe9f0655d7a1dad797c5c15675df14bb6e46717014b85b4333cb3520e2c9280de841071cc8ff305a48184c0c087caa87f4c1f25c6829a1c1210f2f0e9c439caeea984c8af030a3bda26e5f19f8219376cbff4b196287a7c693836ae2ba6696b72c7c6be31ca76dfe7f212ec0db31fd608f4e36879aab836e5e3157f10f6bfe6654ff70c6ec7681f8873b9addfe7b39eebb6d738ebbb5dfcbd72540b0eeff202cf0b9e7b4b72a555035fa7f99f5cf2c1bb85b6bd55eba59da99b5c3dd5a9a661dce0abbeaeee09a5d6e700962617917a816991809b1251f337e9982b28a124879d300114e55b6454a6d69d5d7760aad3c0dcc8e70c8298ce1ff69d4deea760f8d1a6ba2da7350b7dcad05d534a7b76a50fde5b06fcb12917a7edacad5bdab455eea6e94ab474ab99dd14637baa78e5dd5bd97856eb6e7a7ad767a702c11a9c727b7497a7c92ecf400090013fa7fa83f7511ffaf81d8c7dbb747ccf2a57afde55663fdc39dbf2c4edbacba39479d15c413dc6b9453c7d000bde3a3618ca450fe7d6a3d3cb59d9cb6b8dd9f906761ba6429ddafd9bdd3ed7ee26d60abeb3c37a95d6d754ad435b76a12d2711d0e719a676114ef762b4af570a8ba9ddf589e8b44a40fbf253aaa5d77a3b8ef96630c5431e62ad6421e06e2ebb9bbe74bb590abad0ac4ae4e57f535e26e8d7795555706fc3fa9c3546fc8359bdbdced46ecf1798b5c1dc57bae1e1a33ebaeb9efde3366b688c8985954e5adea76a3ee699e7f453d3e2f91aba38c99dd2cafcdc0ff541775830ded56b9ababb85b13f22c14f22cf431f9efee1672bc77c737cd5d4dd42efeb377c2d76ab51e5daf383d6b3788fb7ec2358ed72cec6a11075b356ddfdbaa897aeddd524d7435d7535abb492857d9db8db73a6bf7db8dbf3df79d46dbbc66a317a0d3032b403c18fe77aedb9eabbbda63b70beca17ac875504df4c04a4747c8b3b07d6fb7db4db36a6f5f37090e496c48e2e47df8e6c3bd0f5fd7ddb9ff8792800d6c754777f79cb6d969cd7a08b566d6dd4fb75b4fb3d905f2638ee2bac87e4a22c48f394a6b608f1ff390f3bce69018200618fe5bbdf65abdf674d7eb90dde89a51b5dd6d46dbfde494aa50ffff42aaee54850ab6aaab5317aaeb1d02581d35a5d3ed14ccbc60e6fdff13d305dd8fbfb6b8dbac962a9879ffaf822bd8aaad9a59edfeff013ecd3d1b4008d8a9fedf4930f7ff6f618576ab5de57bf8ff2cacf0ff69ab66b9db75917e3052442b51b7ab952851f98b79c65738a7db4d2b51b98a831061ad44e545bef87f15dafdf4ff4e52d0ecde9d45a228e204be19776c8299f784436a8282329a425242e23de974464a4fba29de0ef3907839a8a626aaa729245d928ef78474a4c3bc1c121123a8261cd2d411120f3785e444f5842494c4a342ca3d21514921ed78483b547535fb3e45e955f38cba6f9dfee0749a5579391e9566555eaa95a86b7675ab95d4aa2827a32b2bfeff087e82d2f170395d535414ee4acaff119cd325e9724851bb1cde1512ef092a7775430c57fd0a84f3eafd7f1b9ce40846e2e1aa74535137527f5e9dff59bb2458e5f0dcadb9baab6e11a8b693e3ead47cc209570cb11c9da7384810d4e55062a842f23c3807b86a8e8304c1c29a0ea6ba084f97c345e17298081b53951c9e541bd01966b655b330a70a5b9d90e7a5a222778968cdbddd4a54770b8b7ae9ee76d3aadb7b434e7473b12deea320676f3754136fb7b4f3de90e79ed39e7bbdd5bcc7e725ee61cf98d9dcf3519af5529ab570a9f7d4db5d55310db393d62ecfe869a98738cc3d1fb55bad4a75e72a7775d4babe49fbc9d5c20ec553bdcb82ea0d59d478cca84e7b6eafa7d9976b77b8ddb4c7e74dd72de4da15f65edaea217f795e8178de5ee7ae0a5cf7fe75ae1a758fafb90daabcbf50bdd5ea5045b55b7493a4872c7a85719eb2d0bd1ae59ed3dc35db635b9dabd3567329d7075b75fda9bbdb8d458dad1a545da828a9f2a5741ae20027d4063d0755626e75b476fb4f4787c7860a05f1fca43fb6ec030464f3b1a168f6497f867c8078843430037b343003519b4d07edfc75758ac4b7eba29b540753d5fde1304eaacb6e8eb221427515477bea4d8fcf8b717a7c5e1bad44e5bd54c8f3d2ed96662deca15a6c4f8b4d95384979a73f9d84ff4fc3a370ab75b1eb1fd63c6b176d557c5cf13781713661e0cf260dfcd9d401e0de6ed4516f35ffe18468cf2c579dfade69d65347b7b7486b4eb39eea7bdda5590b715b49753bd7533acd6e70489566bd846a3969b1475a89bad3af7ea58468cf43ae1eb5ba21eb2e71aedd20d2907597fe5feb87fb7fd56d9b85b921eb2ef1ce7bc7bc6af776ebf52de4c3dcee74cf7d176c5516dc407382092135a4800a24722001d1111ab0105a24209b49400915b0059494ad1613c85182143f702053421302689cc4f41840061f7cc8c962e600331e604287231040c01b401013c0c82a2711277f6cb390670d04aa29ce5813b310ef8e79aa758b85a82a2c629ca3bb59cde2dd5b35cd7b4d75475fb7f376a35cad650cdc42fee2e30fa71aeb5f9bd1ffcffa7facff77057544ce5f7f3fb5657bcf38f79c627eccc535e354735528e4598875ba5b9c7dfa5d73d5ed96eab608a5d38c62ed66acadfe5ffd7f6170886e66f866edbd9e4b53fce3dbccffdb6cf04fb3c43beaacde9ad1fd3bfc3f121c4ea5206c359e1a4f8ed6e9facbfd65956aa9ee5d65d98d9246b52c34ffb68bf50fb719c53d0b3bcebccd6ec7ad1e6ebc9fc0e8f16792137d6f17eb607677e730488232c4c7bcea292c49ebfff71e2dd73bc569d642dc5bede6289c13c9099d2c74afbf9eee99d59d1f794eab66219add3cd4e13a361ea0d640a90e0f104f06f204d97c6cc09e9e9fa19f9c5ad75cedaa51e3b5ddae4a6c917eff9f7dffdffb7f0fa07c16ff5a209da956dd8ee448aaf131cdda5df3bf12ad97e1ffd13f8f903c776b3d9d1f9bd0cf860ae9f0f4e49d201fd496faf8d8847674500ed7e1fddd3a5d0d06e04a097255da9f9eda4ece2fcdd1aadbaf72cf473a98a3f4ab5fadde904d7b5daf6b1ef6f8bbbeec8be69e8f822ab0dd390fcedc90e7c1563daeedc669d62bde1df3aefe706fb58aaa40e0cb71aa3b5015722ba3221ecd4376a33f359f1c54a71bcd3976d5cd43a03f8d98fca75a0b03d9f1f1a007b759d831e77a3db61973cdba99bf5b256a370aaab7ef467b45571377dabe3ba783392ad5fced756150d5566b7e5bb567cc2cae03ffcfdbfd8e876ae2edc6dbad7654afeb467ba9467555aad3f6dd463cb81e9c0fce86fbc101e1827042b821dc0e0f8e8707e7c3833bbabdd55d6de22fdbd5a6bed39cb5eea8cc66fe32e5350b99d857bb5ad8917255b9aa28275dd7bb9eb59b9b22e6156d9152bdbea916a2bb54ab4095f3bca22d95bb87acced56d50dda59aabee16f637b754ee765d2460df75ae5f2d3d05ecbbb4d53b9dee9c0eb67a5db33097b6ef4eeafbe9a89982ad9aae5a15ee5ccda934777394ab5395b8dda8dcf3d1b1eb356df352cf4f5be960e65c3be9964a0f8fbc60bb5dabdfbb6b83ea8e25221d81aaabab9238d76e9ae2582292ab891bd553479d75bb714d54bbcaaaeeb0a7dd8df677d85f28ae71499e909a7a48b927a8a75e1124a69ed293eea80949b7b4eb4d21eda83010a1f78846dbdda6391709bd44a8aeea46dd5d2d1caa286e5573d7473d3e2fcf7277b1eba760ab1a75daea76aeee9acd6e8e2ae211a1baea3150b493aeea1b54ebc9d9c056cdd16b46791b5439cfb8ef160b7b8e5a0aaa6bd64a54dedf7dcc4d4f3ef965599a8fc596ef636cec5def0a427e0c0a99be6664ec65c8570d3206d9d2e30a7ab305d78e58d9d2f2729924f936cada974f4ab984901f03f27a1918f92449be5eb6f2a57c9224cd72892463644992264c49499664acac3145923032f6251953334b18cc4686495759ba9c902e922c65e40b4ad2e55fa4ab34354962952459b65095384ab284b94a72052549c24a528ab4419266d9928197198b41d62049922c874a1a2d2629035992b092244bb347962e998bad84218b5ac8170f3308192b4b178f292b4bf246068804808be725c98c2adff5e50da4cbb471bd4ad2fc9701c828c82fff3ccf279f749125d902b2a5f44192e5ab2c4d92f42175c81612a62ccb1296237b94a5ab2477ccdacb8d960ec8181919942e90aff206e9224df2cba812cb48d7972aecb18f2480f93419207fc811a549c248578c8c21cd2765d972334921932c4b172e615c6cc81749c6765c3c1aec90a50cd652c648f246966513268c74295d2691ac295f923473489797926c8991e5907247b9a3d461bef9a40c092b4b32c6759aaef2465996248c740149171ee4cbab245f648c201ca52ef6e25292bf169858494a912d246996a48b5c22759443658ef2a58c952fd2244bb2246fa48ef2a58cb948f365926410699236a40b09439224107247293363648b8b2c49f24692b01ae50cd255922f173954be9066b98334cdb274952e72a82cc90c4a19e942b6b84a92246fa48e52163349578b8b24c9204ccef86821327fbc489374215d33a48bcbede5088e1de4062eb22c61654c93278d9d9725922cc99224c99c8ffdf08d84406251a4058f8bd070854a119a29acb0ca513480ea04569e475382dfd1f001bdcb4afc140d41c83045b3a1a468c0c2222adb8634d1b0438ba59c63678886199da11c6387a013c4f008a29191402720c100f26599010887f1359f173b727c3994385670d83878c7c70f28385768e0c3301a601b321e0a2dc9fb5e2a3c7691f06ffe23f98f128afa7fa5deeebde1db130276aaff4f1ad2ed7ed2ecdefd3f52ab63b79b7474793bb808bb5ad8f78e0d1361ded5a09afe764bf2700a19ff83ea4f877d5beed672cf690fc644c60107b6622e3117578c16a0988ba9038627c2534d8b0d4cd622e48291215d30b09eab68c698335715125ed882c528632e2e9c181d420dd89255c1a42e9c182294361c2f2a17092322622b48d3d18c84d2257335dd74b18582117c5011817cdd661a0c11a1746560e60c499aa2d70f26b660300da298d090312ac1541221005b375cac6066c0cc50924463d8c2655c6c11751725df0a67ccc58c7965b9048082082dae18301da48c8f0855d4e0e243044c5ab0b810a37c790d99c5865c4cfa489411682f1b5992ac031812978fd8d00815a041690406a450e3dc611283360da088ad9717080309313d3264550e1348ec069008b2d8104cd612c30cd229993a64495c6cc962ba985dcb120ea42499cb12cc2e25aac0960d170e900c76a3c5c0642f48351ee0b0256b59daf13b61eb659e2f12260593bd80c07c1419bdbc2e3d5a9660b2d88d9823171eae27171b33727490410d1f2d3f98a63a1041d6528bf9c4f804e9a26230ae5806af9b09e402e3ea8187c45c623297ce8bc92534847ce130695e35765c5a50730809c84c8bac864b9008b9a7175b8b8d8b878b078c015b3e62b88e5e3f5e3b5c78b872c8f0983a46d8aae99026d0cc71992f00d478c08210bb754003a84889e20006d83080103e30f22ca0467d1e2031725545b58b6a22b27413f2b1e980830db0eb0823b25c614515428a38a8c9e0460c4a079258000e5248426e3a68c0bcc08a0802881e7258800d0aa0018a0c54363d746a30bcc0db65f9628b9f912b5a30446fcf56484105160191c57250c149900b09aae890c36d08c8c68c17594b2c070e0a4c00894ea19e88e89290662880000220c3cacf051cd0000684605515043433c3f5012a5a541505017289c11e60021010a8e1002c9c008004cc30430a504f45407ac0905e983128b1b8b0c02d28afb8aa284ff0b24296a01c41290217266096283f502a5106513ec0744099e5c22279901ab4e878e588b951da2869903366b4978c72469eae18e5cb4b56bab4b494b1d8ab74912649c23e46c6c4610ab1e522c096ab09e60393b1178870e2b0f57ac1c43a2881082e1a785c36606cd80136802d57934b0d598e1912b65c8ab88c983b5e3a0ca625a94508263381ccc85e1cd86af9616b0612115c824c19b2808162eb9565eb05938108b6607a8d105b2e3331ca189097ceab8526345e6eb830820b852d191a191a3367a6d33233cb32c2eb478b508cc89431895a6cd8329d78746032180f5be60b2c0317ce0b8f49ba605c38b2a4d78f5811580630190c0b6606cc0c9719971ab122261823c03230a38cf09ab2c501968bc53d0e74b86e3032b0998b3473cc9c2b0ac606ac8c59c570c49e5e346290b017f3e582314db33463668be922cbe132635431193251b2590c1623cd98cbe6d271912d374c1c22b868f0da612b060f22cc602e1c2d4723b8a018a1a6873f4b185590a0ca07a82031e50dee54708264242448d06eaf68814e8f53a62576c408d453160f2c01020d52d879e2c29017a01881121a1882020e58804ead8303bc3d05eebec0055838c1c41246482004103c4062e40aea492949831d366a046181101cd000103ee8e9c8b15b0d624061022d762b4b185d7081e4888d1ab31168e0080c0c4181093c20850208a0e741112ba8279d121e38a2031778b2d4440994d08011430881830d279440820bb01801134308110404986ce95487348bc1828a29a040c2080b00e1830e2a1040a73d0f901cb1d22101b9ddcc6294f0001232c0a002139d7a4044978404e41623c6f5544ca184073670840580f0e1013aac5000264988e88200b905d9786e64cc5c9f858a294cb001248e30c202403c408715542800019844d14b8244884eed0b2f9a9864623c91c3090a275c59edd44080138ec61e5cb298619460bcbc2863d0b2838b01a50ee502c89e92c7dc216b2f39e60f13d7d0a0cc41e2886560de20675c36c81a2e341932ccd3250313e38cc900e6c64b0ed9cc25d6028b9530d8eb6592ff9fc1bfecec41e1d75feeadea0ed5f68df5f87a7ace1e1f678feb06db60ac5395b72ae62aee2a06727473e601018f0778a4fcfb70b0555175e537380811b6c169ab83fac7e3e4e429e1df87811babb81f7f496ab5da911485fdbcaa6a5e46278fab7bcf431db7bfcb2c9f3c752ea09343ab76ae53ac778a6f6c34eabe9b9f3a03d0e99fb6ba67cc4f1d5edaea53a746e7c42b066e8cdd0d7473e758ab668217a2ac66756e6c5c10e0b2025f3350bf3f405a9260bc1d9891da8cffdcff1b51f13fc4838bb0ebbea88fa121a1a1a021a0a19f21db90cf50cf10cfd04e901090d08f904dc847a847884768476828482828280828e827c816e413d413c413b4133404240414040404f4036403f201ea01e201da011afa11fa09fa01faf9f9b1fdf8fcf4fcf0fcecfc0cd9846c413620db8fcd66f3b1f5d8786c3bb6211f219f201f209f1f1f9b8f8f4f8f0f8fcf8ecf508f504f500f50cf4f8fadc7a7a7a787a767a76788478827880788e787c7c6e3c3d3c3c3c3b3c333b423b413b403b4f3b363dbf1d9e9d9e1d9d9d931eee8138704dcadb16fabd3596092ffc7c9706c64361fe00f300030c691e1c8008031c6f8ff87fcbf90ff2ffa7fd73f101c26f886e3f3e1dc4e9c1a4e0e1cf3fff1cde7c337198ecf876f1da8578c65be9b2e0caa2ec61da8571b5f90204168b8feff20401ec80f238ac0383d7ae09e71aab350b5cdc3188edc7eb83fa63057fbfbc398ab5ad8f1edfbebe46ed7452a6ed7dd463f70fe6bb51fb4f307cc8e2a376508ad5e8d997dca4fc056ddf99153abed0861e3ddcdc30bfcf740b2d303c90f17e1243b4780ef2f88d3070e144cff6508ca2090941d941b98e009d2891b9b631fb2bac7d51af0fdd1280d31fa276bc46c572bc1c75f5cadd5dc0cc49b631e6cd51de4baef2a5cebd1550c54310e0ed738effb29d8aa9cab4e7d57e9f7e8b8ba19696f1e574255028812365fbbb1c1a851e31b1b8c8bba095d4ae56ae25ed73dd55bf735c2055b35d51e80e18dd9a906545b8cb5b06fbe66cc553cbc21f1a09e708de7225b3bd20555ed6ae2e6987715075b95a8ba3ac5fcc538a98a7bb4ee6b541b62f7fd61ede69b639b3150b5d16e1ef260eead465d1d95b67ab8abf1541355ce358abe3cddaaaba38cd9894d71066ef665d55675c269bb8d6a188735ef3a88358a66dce2704da3791de2ddb1ab5377e356c5a94edbfde33ddc24dc24757331e3ae8fb8ef56a36adaaaf888e2dd716e55cc33d62ecf42ac853c5cd3696671abf50f0337c6dcd5469db67ccd6d76da9ba7b2ae8e6a757d3fe1e390639eb62f9055b15e7bd71cf71e6dbabe1bc53958b7ed465b5daaddacd71c12469c4820fdbbb8b8c8f811cceecedf9c8b8b8bec9cc282ffdaf1a7d75f76f510f736ab6e2662ddee1c6f5d73aec6f131cdda5d71a956a2f6fd94eaa754f7fd74822449563811f416fc8c41b295110298145fe58a0d9815481d05f8aff9687c699a7391b759b3f8b8aef9e52fe6aa9087695a15b7ef06e2fd44a488a5973262e8d3346b9df6bae6bddeb16bde3beaac1eefb99abf29ea6a62afa7d9cd73862c6a3c8be0a2882a67112e14e1e47d3e8c624ec43e1fce69a170ed46631f3e6c30c75cbb7945758a710a3f5c01e585281e8081f6ff73720a20c5f734aa125ddd6eb5c7a2c6e1fbff32529a3cf7f9b0167617eba09b8539dd5f541bb5ee9bd8e36aaaf95ed19e76873dbde6dcd33918b0f2ffd8dd40cce2dde2126288a248b3b9c52f9126e6e8e8bedbf675db778829a47e6d000729c2ad5e7b1da8d75eba6e2831a42044cb5fa0e84243c339791a4e004fc3f5a7e186348c38c09f4640f9d38807fc690406fe34e2037f1a51c59f4670f1e711af3f8f98f1e7113efe3ce2f6b31a670c023c2d060d4f8bd180a7c5c8000d195a789a0c323c4d061d9e2603104f9301044f9341054f9ba17cda0c369e3603ced366b83d6d86a4a7cda03e6d86feb4194c8099a1f142237af234a2284f23d2c0d3884ef034a22d9e16e4c5c67966e97f66f9e0cf2c05f833cb0d7f66a9c09f598ef8330b137f6691e2cf2c2cf8330b177f66c9f233998d18194d8b2c4fdbe27cda163b9eb685d0d3b6a0d29105eb67319a7e1623c9cf62b03f8bf1c1cf62b0f0b31835fc2cc6037e1643cacf6288e0673150f0b4208a785a1022785a1028385d9ca7b9414f73893ccd3df23437eb69ee92a7b905789a4b036d46a39d5a3c6dd6429bf168a16551c4d3b208c1d3b288e2695970f1342dfe695ac4789a16379ea685cdd3b4087a9a16b9ff9791c9d0e8e1693412f0341a283c8dc6d6d36639606831fcf0b41892785a0c533c4d867f9a0cb3a7c9c0e3ff67cc64517e2653e16732ad9fc9763f93dd7e26bbf999ace667b2979fb97cf133172cff6f03df88c96480e9cf0cac7f66a0c99f1948c09f1998c09f19e0c09f1990e2cf0c74f1671130ff4f6383060d5a273ead07e0691dcad33a104feb22785a4fc1d35ef3696f064f7b7b9ef6323ded053eed6d9ff63679daab80a7bd433ced05c1d3de269ef652f1b4f78ba711673c8d98f33422d1d388564f23eea71149781af185a71179781ad1034f235e791af105ff3fcbc0460b0e9a0d99191b3531b421304f1bc2e369437e9e36c4e9ff6766ce289ef8330a2afe8ce28a3fa380c19f52fc9f52c4fc29c58e3fa5b0f9530aa03fa508f2a7144c7f4a81e44f29b0fe94c2fd530a10febf25368b1123060c10c3a701717c1a10233c0d88129e06040a4f03c285ff7789d16456789a0c0e4f9381c0d36484789acc069e2653e56932579e26d3c5d3ced7ffcf808921e34ad4cbb872e4655c495fc695f6655c01c0cbb862c2cbb8c2824b4c0c11ec9f44b87f1251c29f4418e04f2210f0271150fe24620134578c0604cad380f0f0342016781a90229e068489a701b1f2342028781a902f9e46047b1a518ca71169f034229ca711013d8de8e96944c1a711159f461480a7119df0342215fe1fc6a586ecc6092322e74f2288fe2402f72711527f12e17bd166a8c0d36698f2b4199e78da0c563c6d062e68c8c248e2cf309af8338c2afe0c23067f6669f9330bedff65682f5296fe9462e44f29587f4a39febf0c2fd43fbd30fee9c5097f7a31c39f5ee0f0a7170ef8d30b20fef462ca9f5e2cf1a7174ffcbf0ccd25062da68ba7c5803d2d468da7c5d8f1ff322d510cf9330aa63fa3a8fa338afc6714587f46517c899151458f97510590975185ee655441f532aa405f46156a0c1954f4f032a810e2655081c4cba0828997418595974145172f838a2c2f0305312f2f2db075cdb954dd55ae5ed79cdbe99b856eb6b7a279f86e37d835e73ec3ed02bbb1b7b2ee4e8dba97dd37bb79035b75a8769678346e37a872de7b3b7d7759e876d22b9a5dad793a557746ed6acdcb5575aeaebaab42ab28275daecaed9a739c93abfbea33dcee11efea8845af722c7a3564d1ab5d54372265f7c565f7c50d5521c76d60abe34395c7b5dadb771be99c10d5bca12ae4aefeb1da6955d1f6ddb9a3a3fbf2ac5d5e14af8aeb606655ed4605554ee5f27630fc932f20e09f7cf24fbae0e400ffa4015668e19f64815ce1831ad81baa6052f582141d682ae1aa049c114490001d5c17c86046ce110230686880859f25489f170448424a141e42399c2000a310512c00d5689b5b5713b7d2aad136e7dafd746c717a78e41d8ddb8dfaffdf60caff937f36804703683f35c87681142ca8e0ffcd1c6ad0218a66812941ff4f0a59e108941301c810c412bf1e23901040eb89ff274f58810637ee8ba80949081527f438a18bff3769a440a5052e3c090204ff0f7bc10058c8256e610cf97f728a17a8b0e40b17a408fa7f170cbe1802841cc082e273f85133bd7e7a08e25d1d5205d2c9106b61ef7be518a759bbb8ef3627e39f9cfd93e7d943fa670ffd4f1eace46ebc765757320060927e82983194a0019f6a15a8a27ac85b2ae009725ad0820455d8060902433fb2ac28928480630cba0b6c1c48e0d16400218e2da8e19f943977b042c2b438b103d3e10ac0928d8a1af00e5dd0d444c00316af0e1899ec38a9120314bf9b222e00852b4b962c5f7c102888410f0bb03103132d2ab00122be403990ca92058c30b264c9e205b9433f42cb988510305040173644ad2b7022449618a0a081b285c914e30ce30de8ee298cd002616d6b7124860d403d55610091a11c3011b0450942023d968a4d3b82d6961b3660a0c6890565b8458c9f12448000188f0fac70e5860656290510c174c230870c804c350c718586155c9c12442002891a114b66012de3bc9d500ccd0987fda2868346a807056425ccb8b909c236804a31b10015948eb0f2a2c5104542d04014b3c7941c788e609f14494d1161d0a40448a2e8e00491ce84013929c0d93c606848420603321c7185104a264c01838a010cc0e0820e8313b0056c99e00161b84224e954301f6480074f0942c820e1085925c680273be4f0808915848c60431117cc5c305445c4911448a0891b2420c50b25b4828e54301a80ce937f201c5b43f0d9e22a4915e850a500640ed923cb4db6d9ae56d2e36aaddd2cbb511a122b01333c59e1831ca290323236e4b1950edcd0800412ec00c34b8882548ca9106e807ac18da8d5c2b540b0012560b9a02038810548f11ab000051ea003508895e5db45b5503adc101c60481e0338b98109776b3f3b3e3cc7750f753a7fdd1ef4b421893f6d90e24f1b60f0e70d327fdec0c19f37107d0d1b403f3d36211fa09f1ea09f1e9ea71dee08e94a97d4b309f9e096763d9b904f540fb73bca2199806403927f565dc910a2146065b8ffcc61c89f3dd810391530f34fbefe7fcd28ef659ea25ae7d7d35d7db94e104f0fd55ed4f0c373574df30e10b0e727a493837ec01d9dfef0e45f9a6621600e7fb73127d8aa6e0d3aa09f9ea51ace1aceffef19777aabb976a33adf3dc4db8d862b2857a074a048c8f352901ff3aad3b6b8d3756fb4f7ba42dd73aaa66d46d9b74ddd5c1cbec6cc1a33dbe3f326c0c7cfe0c2ef7e7b354a358b5ea53ab7ba67b4ddb95477bb65396a261ec65133a1eafa7ba364e07df1cfd372dceec3a39bfb7f2f6220c4d1ac2828314080bb3537b36c76833b4240b62014e8e6b07a0803a35c376a5eaa8b7b5d739af5d2fa63b376a38e6e6e371f66b445ea7c47fd3f962e7ed5bfdca487475e936fc2071550414601c39331bce0a4e4e0059c176c20808bc7418830bef97cb8f33cc41a6d3331cd28cadb3de47a8a45afd2152a6d71bceba09b79bdd5aefbe68e7c3fe99dd6c1dc7741d5c9dda89eea9bd5530320e14994273b2e5cf145443d3e2f77357f5d9d85ee7537a97d7d9d52edeab6b8857a78dedebe9bcd2e08fd7f162ec0e20029f054ed54058906f0a21b756f37da4389b75b0f2572f5c87591b2a090781c976a56771dabbb8e77d52aa77bab6b018a635757b5bf536e0b4e782ee275cd28c69d2dd44e16b0f82cc419b72aabbb8af51a6c558e71270b3ffc7f8df7f777b200c26ed31e9f9705dc0a567c6d5d7591678cd36aa21ac4c156c5c08d71edb8ae2f10a76a8ab9c6c06db4c208df53d5e278aa7aabd9631ef634cf7ad5532a34f15fd44fa70a4dffff2e2e2eb2daf1e7e2e222d3f84687e7701d1d8eee34a75533abb3d55a8da33bd5d1b9f161ef429b24bdd5447d046b21cfc5c545b6736202274efebfd6b90e065fce623d3cf6ac851d470b7babd937e866ac855da7bad5c36116629e855c735cd44f4e6e74292cc1ddda0a6cd51c2b56f0ff47485218c80ed63ca3b8737717f1e65cc56ed6c79eab873d176bb455790a2e373641bdeaa335abddcd51ebfa26e582ad4accba49afa94e13d58ee282ad9a953b7777cfeb9ab6ef9e2ac0acdd2a57896a7a450001f474aa169940210b776b6beead4e5b8d02d97e405bd6f1e90142857852a0a120609ada6cc09c541b5520920aaa104a81d0ff57f15950465a4c3f908c4b43584844a9223f4c44b2ae78d6aab418a50bda53bb8df21c199528098fdc23a31f2bde4f6755d223b3d22901852cea540564dca91af28252db8e13d5d28e4e109291d4484aeb047b743d58494c573b553b2325a5fc16c93c524742bca1560ba4ea191ad9c994907e4029498a7a83d07e253476f63db6bfaaa070f714a58b56513e5942d74a6d5aca45907e4c4a448044f62a8bd712b172fa51c448096b3b4efd901d89447a0f5aa4ab3b523b3d2ac77bd61e216d652372a5cb393d4ded1c7bac8238eb1a751e7a3abad255bba4aba3224b5a529deae887f087c8c42423ae423b1f1ff5c897b4d42723349813d2d9c919a37eb4711b91f229f2acfd54e4695d8beca2deaba9fd3444c488a7248575e56454e2647565a48749f64348a4eac78ac47942b8292555543a142aa8a7e5b1525521d610e849ab0d1a026a0d3db13e4061d40afc1d8b14d14db9565a4d436f9f2a0aedb7cbd49ff787ba4592389bb4faf02441e914291a9d7e98d4629ba97688c629261e5311dc7675ec0a04552449ab468454a774d5e259f540e5d2ac454426154ca78e767e96747e96a88c9a7e5352c59c1316d08ebac45605e923251dabd7ae7263d692d1548e67972544e4d8db6c340c1221b2a4cbfa2142441624452c1e556556a808906df7c386ea8cd0600ec9a709e98aad1a0abac575c986d4b259bc98a5c4883485453584823a02527982aeb29478a2a6a0baec87ab0a0a8f52ba9c1591a8223e197595807e1c57a56d44b5832464b58276c6dcb6fdc8c88ed13becf9c152b3785a4b2749872d2a193a5969f1a264c08e84748494797c7e8ed857e3928cf010ad7692947c9e7e448c601159f2211a891a72d2e964057fa68853c7148a35ca2a42c5b38363935a5c904e9d643a256c94ca63446b27379432baa94fdf198ae22959d72ab4c8102b1b6d514f483c234f39adbd23d2ea17686b81bf9facac937a2b5c3206814519554f96928e67aa2745117d8652a11414c7b136233498437512161450c9e875728d74aa8e574742ac2576955262cc4241449e7814d4502e454277643def1af5436724ca585cda5338ada19d2350cf91fbd3be4d3c6355c6ad451da4ada4c7e8c71194cf8fa5d60811eb48698869ef928286aaa47247563a59ab534478340a3955e98a7427292cb4db6c553c51ed9370aa871361736bd655be2a5aedac785a4621ca51232da9dd9beaa6948845234d3acd4599eed773aa54d0a9bf55382c95677584b6e8544fd413cee84705649a0a6afa813e65b93aaba21257a26a6a93a87634d165a2fab56ef1675562d42403ae6faeb823324c87a0766c15b10967b47315454544b88fa48a464c5246494223ddb3634caf947c7c8ce89e9d948e4fb1f3fcc0021af10cb948412d437faa88fc78817c86949472accbe3e394fab8563a9d2d298989889048de39ed7eaa88b83ccd7b126a22fea836bbfe289205ccb53f9c907ad36e2b914d5919c9ea91c20983b8a39fd028d483d5d55d55302b67156584e2452548c32724d6c9e604e411995272a453f5f1380c362d5541112952259565b4c4cab68ecd48fb8338d583733a168d57e8ae89c7d46231011d7154c024a2ce6a0a2a0a0a28e743c4eaca69a7aab843a4c996d361ed8c10714a3e4223a1212232ab5d56cac2f1743f74502851ca28a54aa9de2723e39071981e1987a270464b1bf7133416092a1e7f3a385c51abff18b9497ca82e116d4a433b2619ef4a2989fd2109157f928a14892fab7f8a5943a25567754343232d95ef824f3ea9d5d59092a8a8b42a2894a3c2d21111a64721d3ea93ba4ee92a2b4e158dc56ec4a3e345acde1e5d10d5f147ee68a4a4b36621ca85784eac2dabdd499b74d938b48bb44e47233e59b9482ea22a4d097d6c4aaa94644cee0fa7271ed3f1eab793aa1a62caa911526ea7dd1972b372db496987f8fe569695b2d9b81148a3ad8fae090b281bc18a3ad2495965a9ea902b53e223454c733f76da44a58f4cbfa19d1355aeb8ad863214911c7464d4a387591dcae51faf53136ec7ea68aacd0af658b1468ac5e0540e6b4aa795054969f178d4865aca1de18cfb4a873454fc2185a6e914b0cdfd7e4b47bbf8fe80aa1a2a411195e86c6544682777a435d4fe7250c39d54d14562656813baa4147564522ab2525a39be814632cb63b53475bcd22831352a5115854a6fd493522ab483f2c1fa6137d0b0458fde291f97c8b37f5345d91511223b41536a10f08d528dee6bac2a5e41fdd83c1da1223ac72c9f9cce7b6595d3e930719e9f8ea8a3a5b2cb85844dac100f8d92d21579bad292f9405d017545dc308aa8a35a26961f81a08ae8b44e424582908a4c69e5b27eec56289c52309893c96432994c26c3e18c74419bd2079d23f8f059e8667382b9cd6cceaae3aa021f3d21e5e4e4e4e4c88220e170464e41dc51ce253a51f9acee2bd47970edbb629250af7aab7cd89fdfd19030b52a32f58334a4dae1a1595b36f443eb25ae4256eece110d2a1275a56495443422621c32126c62a582d29c965b843d6222a205a41eb13f4c57534651413c362b61c602ea182d2d097964c6a6a5a66ca4247764c3a52a14562f423c068d1c73b89fcd0e51f9e8041d91b4dabbadf519420559573542fda82a92637a9aaacad94749cb4694e97029ad21d18829f83b6a796c43e2d295139392904a875b7aca4045a2b076dc258df534b4f9f0a7a528a59d1535c473d5e4e35e395171212875e3643e3ec657b87ff07646542af7a854cc42ee0e8772514a4a3d0b1d091df1764a4a56506abb59e00f26f44a2935eaa4a07eaa88e82ba7bcd3f947c6f38bda6d2256574a526cd39015d38fb5fab98a5a4a7a85522c1e2a54c4e85211c182e2057fa02894913b0554aa425ad249e2094aca2e931125463821599a66269d2238f587dd5985de8cc35d69e5dc6e29c80a086978e406d32c2b9ea353102a6a4bb545749e8c6d51f7eea45044a79faa9d0da8772419502898a58c4a3827ee021d611977766aba33ea449ca68ce4a88240afd390a929533511895cfde879b9111e21a1541e1ef91c89685db1534163d29651fd30028ba42fd027c875d71fbc5587090784432a82cb310555239dce092754049783c2e19290a470463bc52125354ba89515347ac2616d239dce49869f744a4846393939391fd385094b26f870f97f57084a7c1124268cdb4d154162c2395d931155940e6656e7ea60ab260d8351ab9a59a4bed5a99fb65a7350371df33ae4ea118f07f39ad45523a09f1ead5d212f2ba3a86602fae9c9c21dd04fcf2ef274565e8d7a7c8a798ac7a798a7767c8a796aa8a798a7847a8a792aa8a798a7807a8a79eaa7a798a76c3dc53ce5d353cc533d3dc53cb5d353cc53433cc53c25c453cc53413cc53c05c453cc533f3cc53c65e329e645ed622dec28d87cb05531113ee1cabfcff7ba2744a0e876e3dd6ebc138efeff87bbef0680c500aafcebac5ed7bcb6d337af2aabe606f0e43baab1067085850074f8ffd7cf046083004410c09210f76582d2e19acf8735578b9aa876df8d8def067504c573357f05f04d7cf8ffbda3a670c64d8c34b1118011bc6b266aa0fee1aee2dd8568c69aa8067d3edcaa6c8ab3ee3dd4ad7b47f5dc4b5bdd732fd59acd6dcfbd540720cae70600e79f022033818a094edc8ebb0e9ab084b909f8c9842fc1cabfd6492564a084265fc2550933ffdfaab9bb1ac5ee06ea2416bd6a5527264c9460e2e4bfc68f5a03d1146b2b265198ab4c6c1e33f9ff1a099c6f17256187e72ae615dd601cad814523a43042d3ff8ba082084e22bc6c51d972524b55cd665dc4c524eeaa7d7df1d6cc7fcd17420c5f0b2107082400e1c9bb1b88bbcaeaae6a0d5cb3ab899a7fd0c407367ce0fba0668909967460490b4ba496e896bc00600a008600000800205202c64cc9164a2af05f3baec254bb9aa8ae3ac5472dd4fcddee5ef170e7f01e5dc7374aecbbc5405d8dbb9a15f66d846badda7f5a037d35fd3b66b66b8e813a57ffd4ce75daabe99edd3cd49c670de45a45db0d6c754a9694d828b172f31d5ba8e393c71d858c5682ee3be41983301a3b9b8d422fe4159b2842799f0f639f7677ceb7665445aa197591977b4eb166379a9385c55445d577575474d44c479d75d44c3adda80de825de4044e1ff7d5df35e9b511ff6ed7cb91dfe8173c4a8ffdacdcf8839febfd6555667b999d5eed659d9e965c08be49df9ff9a765f14cd78f722e6fcc5bdef3de5626d857df8f0e1a3665481da1de635772cfe7f5d55a63ee5ff8399b3baab7ad7970cb31662de031fd71fab39c7fdb45530f721ae452e6703a5d38dfa803ac5fddd3a2deab68887aac3dd35cfc22112cf3da7403dc5b38b74bbf1843c0b7b43b5f3288eff7fe35c2c5c29eed67f8de374d2f65dddffdad0c55b2b8723d66a521baa5deb2aa8fef0de5dd532bfa6936a21cfc2221dc6e11101a186eb5067f8da56fe7fd7390eaee6bbdd78beecb465da30da08b448da196c95f74d61e0be618c71ed86f10fbc5b0ca4a85b5589c5ecccfa82358a75855548d0cfd6962c1ffe6bb71bef08e760ecbbe149756fa8f6be5b1bacab055b95738dfa34bbb92ee69e2f67a8663d9525839502ac24b056c05a82c581ca855a83daf43d7a60e0c6c1564ddb9c83710db87d5353439557d44f6aaa5d740b9ba6a87284729278543863ac7f40866a17f29c5313a259fb743f1ab93a2af77ce4bbd5b40662de23bfac9ad79c4e098310028532c11f66411e44f2ffb55b6da8f621700b78a353a059d040665a271d415a430a951aa12b4059408be806bf2e6a3e9e1c5d53f1babec03563a0aa62dc559f0fb7ea50edc52d5431cfc715d76e379e0f03f750a7b8e6f3e1e34f0f872f8a83a66dc618c7c7f3d57c3c5f11fb6e783650ddcdc2b6b8d3debe3b6bd7176c55bed71cef2a8b54f36d61d187811b673525aac1a1da7b43b5fb704eed48877dbe35bf1d6b61c7a96655ae0a7916621f77f570a8f27c19eb5f1b54f950edb8d5c39d93876ac7191f09795e728b6e706c88505dc5876a2fe26e512f5d776fa72fff09fdff1124b896b55f2c5cb6f25f4b812a4eb5ba0e872f4fd70d442df224485cbdd3971f4182b590977dc05ad877c66db4ae192de21101a18aba9de5209f95af1d75d64edf1b5f51b73e1b9cea703efeff4c3ff3d9d48e6efaee32af97c3ffd7fade533db587a477d3bbe1c111b51b1e1b289c93c31b6c50ebb1db4ddbbcd397f7560bfb8bd3da05b2db05f652b59785ee75f754c7f360e9bfc63dc09fea24556e764fc242922bbe57dcdf8ddb8cb7ab95e4b4bbc52599a9dda433245864e5e20c89947f7e84e4c9deaee6b819921789d07fed66771b5c44f2ff5df3361fb1f27fe4c96b0dc4797864f85f4b792e1ed9f9ff9b1caeb2fcc8f9ff46acbc1e1e3b0ef7ffbffdccc893df1d1bb9fa2c349d19b1d1991969f9dfbd0895ff2f02c548bbc05e51b75b58bcdd786951b71a75dfbdbbdd8a50b5e7de74bbf188525dee76e35dbd573e59583dc0eab5d259bd5425513580595553d5e944ed46bf6eb7c19aa8ae59f736bbf90dea15f7dc8fae266a7c638371b0557916a6adc6be75cd3d9cf5ba774ead5643bbc6383c988fedf137d4ee1027d5f9e5adc69b876bee0fe3dcf8f4eb769f0fb75aebf597b1ab819cd7a8865444ff9ffb190f06bc23663c26339eafe6eb7bbb3ecc55df06b6c3ac5d7717757be3d3adb96f9ecf867715d7dadcf56eb693c0ff0bf9d98eb82b9a026336356598b58b83535ddc6b0f9fd6493efd72aea65d57737dda4df261edab4de929a93066524f48c55073b7f6f9b2eebc557b9b8b9a5539181acac27db739c991bcfbff1f3f93b29172893a4114105102881a46e17ccdd5c036bb37dff0d86fbe54edf9704eadd7f79eea71b536c4f1f9d68e66235216ba9bb47681ad56b25da06ad4693b83aafa7fa8db8d45af845ea09f9ea554377b4a32f4b3271e4e4b38e1e0f4f5e59dab409c727c1224384d5234351de970cf6c51b7ee76ddbd719a8538262cf870f719d30e4c554cffb5feeededd8d71529c5515e37035d8662229911cff355d0c66ba2959e7ab71fe626e35d3bd2c4d60c9f74990e4d9128ed217ff4990e01c41d2a23ba5294a4b3e099260ab1ef3101f4152bbf1b1e855daea9d4f77e0b6695d5dc45ceb24a59e24276ac7956761520266494d707aab71b3a45d920f9213bbede9acdc7df89866a419905a248c7304490d557b66777f737b14c491048e7a4730b920726a6e063eaebffcdbeeb0d5c4205ef3db66275c4bf5510b3b7fb7ab836d4e6ffabb8fbbe3346bb7b5a91dd7a1d10766460330b2fd3fef2acb551557ebed16ea22e659a8c1cf702c98e124805b9320c1e9eb7bd3bafb6783bbca778b9be1cad9902a86b03084e89320c138ed1ebe79771c8ce372218feb9dce86d41062c527418235bbd1fe6e7c04490d49879910ded7d635a3792624561445110a4542ff9f04098e51a7ed112435df0dc649753e216e5f2006e25bd79cf3a59ac85d1ce4cabf42dcd5999f0591126458bb49dd5f576bc19ab60932b3ae6a4ff5cbf333a22affcf79332227ff1a4724accd8876bef6ebf133a2ff1a9029359ec5f22c0402a5b79a0359d2acbb53350f9b7e76c3a255815ac8bb8d6076dbfaff5cc4bbc5e1b9785bd23fde633684a596eaaedda16f3614c34eb95ac4c79b75cd36b82d6e57b7c521df50cbbf0602df1f9a85e615673ecc425747b52abe09b66a7fb7bb53bc7b4dd7541bcc336f2664e5bfc667424f5ec5fa87519f8f371312c277cfd16e5151d1bae65c113fee30cf9847544464dc4645453736442c7a55c4a2579debb4c7e7356ea319d00a404133a09a9f24663f5ab39fe0cf8c99cdcaffd77c6876731f40daadee7e5c792e1e7df4ddfae0aa707d81b8dda25ad8b9ba559f31b3fba9765cd7ec6e7c5cd320677d42a2c62dae86936a9c8c7daaf001c227fdff5ab0559d72573e9c53bb71ca5d09bb0d30ebdd8c0706339e15cc7806c033020fcece12b31d07ec20f9af699e85a8fb0e9d7257383939ef8ab66a16575ddcf3aa66a0daf361770385c1770f5f8c93bab9e86ea04e15339d07cc746ad089fa1af7e19c1a5781bb7d5976afebee46a459ed05b31a0eb3da0166b5a3af6957e53a4ddbecea60bb57bcdbbcbea89a673946cc72dc59ced4ff67fd0ca70a1c0fcc70569c1ab31f11f8a1ce7e10cd7c4c31f3e164e6a3a9868f7978cba91db313ae690ddcfd88f636a7d6e38371f8e63bba594555a06ef5cf87736a363c573eec6e8ce3bbb9a9d56c706c7aae7c58fff0baaa56b876f375ae531fcea939e5aed23663e01e669467dceaacdcd735e3a4ba7d5f614fb9d640ad813e1ff7a958eba41abbd7ccbb09c1ec06881b206ed6ffafdd7c7b4f39e19bcf87736a5d3d6657d5c2eee6a076317ff171779c7116c7f5776b56ed45ae565d96bb4537422fc6117a6d88d6bd7fbac7d52684d8b14381298656432c40e56a02606071e2c410253a4e5cc0a149495472d5a2009921300b58d99231e0877f591459b274810393058d2e5cb05226e603ff37ca1f70e0046459890580881a2f7c167083c219f2b922550496a52852644f1fe0534887b08598c592aaa389cc8785a5d4599ecca892fd701980bef2e20111cb3c70011b9a921eaa381585ffff30330770f25fe2fc973f4a9b190758cc386052faf82f6f4a9b07cc782c99f1c03074d001dec14168f06b03af0a74d0010e5284d356ffcbe95f425e375c4cb8967085c075c4ac8601dcad7577736376e2ae2eee771f8959c8b56acc4e3daceeba63ae4a97abcae56c3c57f5ee7255b9aa566553dc144f75cfc5bd26b99a08b5e3a0d6f12ed54455a37aaa1bf5d38c9fe930c14c47947f2cd469d6421c9cba59c85917a79a2969dd59e99e55b7e7a19e4aa9baee7c3775fe1ea5bab8d31649d7f2ec5463d5ce35eea9ae0db5ce62a7e05a8a136cd5de35dfb57b3daeede63e1fce986bfef2a39b75aaf260bbd78c7d3ecc713810b8759add8eb966378ab96a847dbe7717c13e9f0f7f8071511151eef908e3609c22a2db0db8ea1d11ab0a77c3ec848360edeebec318030063ac5775c86e74b73e9f0f096f806beeee7c1db2d9a831d6421e4e759a3bef9877b57df19afb3e7635555f2d75d54475c50db5660ab66a9ed9d0350dcc9cbb78b7b8eb23c6d128fba26fbadddeaa354ef0ffb5ce5fac34e3360bdd2bcf421cbe055bb575b315c659e86eca3d1f4d51dd10861112cb8d8326dc0c4c6924e554b694354ae40bcab214028354bb6f941090cfe713f2bce4c3386dc6d56e8078507578ec3638d53e9cf116b6c6ec94ea1ccdaa3d0ab86f6c6a3f708f8f2f2b779fbb3b9a9370f82be4e15a8e7687386b77b3d8e7c3c0dd79abe236a7ae1e6a9e8d6a479de5bbb1016ead44e53eccd556783462e0e6f9f7fbdacd5167d9e08ea387d909d7fa7ed2eb2fb754fb296da980abdeeda75eafd733f6e04c46e87543b3180a000943280b1803f0993dce8f2c47ff7cc855ae5bad94856a236f98dde22c26c830bb45bc7be6398a6b9d749c7273df49ad6a4e724ab5ca6b7556e6699ef656ef70b317a7992c89efa5fad8635123e7abee69abf9cca586ff3fa6594fb95a8d72f52b550037c5dacd1cd78e6dd6c1dc39e63d705653bd7bc63dbbbafb7a7c5e1fc6b5e26eb3b2d4b5887511d7801bb35ac5ba8879ab51ede2ce378b79c638dcc51c6b377776bbc0765d71b8c657ccdf5ddc6d16d6c5a68d72e076ca5d618d77c747b876b3ae19f7cc6383533d1c66b7bb6a15aeb96a1ee21b9f0fa71ac706e8a707f7e8acbcfeb01676265ce3c3ec76dc35e75a3dbafad5e2bae7d57d573527a5addeadaa5e7fb9a5d2eb4fd5f5fd74e46e21da663dd535e76936da4fa9fea92eca7fefaeb89bfa7eea5ceb244ed5ea58d4d84b5bcd67e6046666149cd90bc0dd40cc55a7dc154a448928b155d934f7bae6699af64c543b9a33eba6696675577b2831d52fe76a0f250acf2f663cd74475cdbda1d659eb9a7bed9b0030761e25f658b5c7bac60d06152c6accf9a28a2f90f8a2c9172218b71751e01bd7aa71bb43edbe43edbec356b3a946db77b76deec5c08a1838791162c0c3a873b2fb66187cc1f19a35c779eac5614dce663c41f9194f15f8194f5840cd7ec693909ff104fc194f5b41347ae024b2b072022c41905790607ce1450c608085ece29fe4e29f7cc13fb90599c53fe9827f128be13f79c5ffe772555df0f05d30f9ff2e7c5de02e82e07061c567b5eae4e2877f2e4ae8f1e16eadf78220fe89e368e70b6c5c075d4ddc6c8e0ef7f932d6bf76abdcadb55be5bd2d725bd83cbea5ad9a8571f0edd65d4d6c378a666da29efabdbb54a7292ed554abca94c50bb240e2ff6bdc989d6a1c075b15e3d482358d718046f6d8bb76876dc6d955a174745beb275c3bd2a9c7cc726376aaa938e7f772dce38335df42d5ed6dc6fae76a252a5f57b5c8eaaeea767734037f2fafe135a769c6ae1ea22acf46a976756e374e572d446ba9eaf3f18c62fdc36dbbd5be59bcaa68c6c75567a9ab0d6ed5a0ea6ebc669c5d21cf38a8fef0d1d544dc7510ef8e35e7eeeea8266295ab2a0ed77e2fc7bc876637ef19877735b87bcdefe5356bc66d8eab872f775f54fb7cd8005b516026a89c2b282b1eaeb5aa50fff011d8ea56edad0effde1d9b9ffa7e3af6218b94e6b44eda4fc72c54edbb561355253e956a56cd6beef7eefa7eeafbe9c8dd494456d081150c7bbd1a4ff5c65d65d595af6bcee5dfcb8fc335dd6c76bb11695d73eebddd82a96ea98ca0a1070af06e377ebbb9b55eabb3768febdb8d45532003c872b7a6fb30a7b977446f3757f758d428e47929d50dd5ce6bf510ea05295040f57097856a61ee890a9b2ab6aa305661a4631c7c63b70bec5521830217e09bfe1d335bcc6e2aec6ab177a2a001270a54d8c2627f77afd766f476e3dd6e2c6aa4220a0a9ca84040e73ac538dcadf1aeba3b87458d3a2c6ad4b1a13cbaa707d511d23d59dbf44f1ad40314f2d9b1e5f4dc8d6fdda871f0ad676111dfa6786200244c11c51229aa70732f4db3e66ed62bda43b54ed55eba6a15d8eb9aa72f566fb8ae6ad6efe5bd34cdbfb7fdbdbcd7d557abc7f3bae61ecf3d21daf3afa7517703855d2d9a22c43cf91dac16ffff2d3cb476b6ae644d7648faffbf31841119173af0ad709ea0857749c17902a1e76e0d26823fae2fc6f99f64e29f5ce29f0c01bb7769abe635aaebdd110a350bdd2ce6ea71d53daba96659550b3bd7425e11d7fd684464cc4eb21b4ef18d23e130bb417ca4c3f8078a5d7dd4591803d776e31b9fefb8daf02d2c628e8f5ccda98e2eaa8f8e707d3fb1aa1ba59bf6e665fddea8dd76b5912c74af46dacd75ae1a91fa7ed2c323af4a3982b30929fe3f67d722e95d9a8db2d1aae6a41d538d3be5aedaae8556b8a6b50b5cd54cccb81b75cbf5fa7b778a375f71b8e6f3b9d8d5448db9cf87b34ac4a96e337bd4c28e57b5b72f1e6616eb603ee6ce31d7c1f4fd616ccc2c4e35aab2b93da6586fb7b71b45798bc335b5b79a63fdc3bbabb9a85d15ebd7ed98ab78ddfb878f5d75b7ea0e7384415588334e5bcdf1ee580b3be62a06a2db8d7bc698637703718dfff8fcfc00ed1617b71bc45cb32fe7196b2b5cf3f9b02f0bca97b5cbd3b6d5c28e71d6fc6a69acddbc8b5d876b1b779e579cb61927d8aaec46f50f03774ebb5b9d54e7eaa1fee970cd0d0633c635ac622dec3b9cb67ab7792c7a9566a3341b7595559b5c4d8412410cff1867e8007368269948222072ca5de54439e5ae70b0dd6e5469a43cf93bd4b8a85b9c3190631fb23dda8c9a5330b1e4bf166cd5e170bb293eaebdd5abca5b1563ad64e39bd293ee690a6735640ad3654ac09c408f5288465b9d0153a3add668abcb154a1cbecce1c440d17faa31cff8d887ac6e7fc3cdc3454130c71bd8ea86ecceedfee2da6dc4b96e4adb6dc4dbadb6db2897ead2761b6d6054aa8f79d547ecee7d1b0d376ff37a3a4d719cbb5ac5f12c7437f11ec539170eb3ab74a4e33a2bf75dc771ddf3940eb659881a9172cf477a45f391ebbe87994d75aa7b5eb59b4b91d2a35d9543c6c0ddaad8dd2a310bf50febbe89b8af6f06eab4555957779d623e5cb550b3aa3bbc3962d9709ceaa540a8c46e0b07baa2059d5210cdc00c30000000331240304828180e870422c974dbbc320f14000476be7496441689a2284a29658c31c4100008000180011081a11901a50a9345c4818107274cda9a0c0c85ed8f84ec20174e38f0762d35f3e17834812a5a3de2b367b2c82645fb14053d27c3338bae65f2b3c1ba5ee8881cc5cbbcaa73fc18a1b49548bbcc7686a570487eec2d5d23152434d397e3063ff50ed5a5bbf9c2a6065d22e874146aeeaacc42dbe5e9ca27b8a8c8ad9d194ed8c500aa775c96b657f4b60b8751c68c7adc1745844210aa6474894cc82fc857689b6fee7f8b19cdfd42f9801cbc034be1ad1622208d6472e5c74c065a92df835781ed4a0355d081c692ce7b60af1105962d042f8beb3017bbd86fbdf08db41f9ce1de5b772c33634dcee83a179997defd9640b749d857a245d796aeaa51a0da09570f4b07fd75cd196e51f8bc7e29e65b3ee7f0556d2c8292af2ee9bdf6c50a5da03bcab507a1470a12db70b69b430351d03aa852d822a95e245bd92cb901d18b34fa7135df008d66f8e9e6041b886f0c80ece29ec93dbf0b524d4c02cf83fe975946d725059c46513a620f777d55f082f1ed460e70021823225241513942daf19a6b71dc21f0c82d92520b91df055d71b905d0d51c2bc18b0803849f54ceab59f68b5a8124baf729e2d055c10d63c1c8b17f7d7f92924b20627241d9111b2b36e78cc8ebfffcd95e7c574ee4784651098f40fbefa13800442748e042d32222f59642d14bfc88e1d3f3672a67d1b848592af3029dcec8b4b20d01f1d7c685451bec5f8ca459221500e94528ab762d659b22d38ab88a8ea616331031d0c822a86d8f9eadaa92102e8676b6cd899bfc3ea983182e881f5f35d61355b12512924a13f7aaab162df374a8f3a954710c9ad845a08bd20ed1c5c225003e844d88eb7ddde024967da3dce8192eda4c7377a59ef3473477d81f17f2c7a3b4db8fe38d3438047f7deffb21ddf7df614d857576841c57847705a82b2f05cb97b391e1d17a093255e34b7ef451414d3b3de4fa87b28f08cc364a591afe8184755f587556bff62ea5073738df1d29dd2aea4ff6bdf02e7396b1cd715179001b5fdac83cf28bdf71370fe27427b7a02ef9b386f4cd14d8b9e30a25f549afadb5ae16f949996283215d18128deaf10935295c8acfb210838c44db43f2a07134eb5a934e7057ba1fe97abc4c722f4dee10345e7d0f4a40e3c93067d27690ecf8c6d874c7bd346efa91f084e2d3ab2307a362ea8c3a4fa74a528b26d50f096b9d2d8ddd6a5efa4c01481818289d3748b52e02ab71b2049d6ce8eed078045b0e90b3c7d69f10bdf7b2ef28ea5920c94317475f1ce55e982d6146076f7cc12bb49e3168d9603b9375d2edf566eecf778e0cd4aa72efa214d066d4cc2878e5b1c0b5bffafdd0aa4923e8a0d47fb87e3739d2e3cfaac840f426af282f5d2d5daa3b099ce1e2d87ac5745fb993122909c9b8acfde6ea2a62c2dbe7dbd27c0ecb09f868c4c51cd6baa8538406d8c36851af7104786ed1781899252d191788380e5b5e723019cdc0c0bc9b7ee94a45da59da4fb0c7eda51e03339c336803401d9f7eee7af548a821c5e28b4a4fdcc3c840b1efd9f067ab31997a8e6fe16dd90c8bf05d0d7b765ca22c2b63fc5cd54dfdff1e933dcc74fc12c525bd3760c6d0604ed28fe5607cbb190b94d49ff29764c701337fca5f3faa63679f5120b6c45d313a8065af4aebca133da35c03b26de31dc507f4ad6dbd065efc681b2481004cb81c1f61a5436a2fbe1075260e1d605af0f078770cfb889e0477938e2b60655f2badfb2a7a9970834199be0f0f746bd8962ae4cb70805b2a527f0580cb751b7deb5654158aa12f79eed704ebd721bd3187fc5ce4a5203299a08390fd6bef056e317539be6f385b3a8a5a7b7432ccdc3bcdafd9539605031e6d4c56d24fed4d0c7f4ca4e4b7e14dfbbe9b0591a9ae4d5411c15573ce091e1129a3c4659cfc7c7f11831350e69027005e95d4e5362587be15a3e4c5d7b5e1caf7d8724606b1c61523b0aa084e4e4319b2c40aba75268b2b376a4582b2b068a0c310ea4c6b43defdc25b5586399423805154f9af4284f4af25b101af37af329be81a31a28feb8b1de7923701db3a28164c8819bc050bc4ec7e83a3a7f47abf16d952e1455a962392687b5fa648331839f6f8f3d3ebcbcdc27c04e5239198860b299965547b30ba4e41e9d3edf2507e8ace1d65f9104a896ea57ed04a0990e8d94d338d846bb6e1c2793f07ad7b68fae5b6eab5233197d0cf030f64cc480fedd8ab5d513ec54ef4bdb40f364237bbf0b39f99f7cfb6759777623ca6e701a4d761ec50d32631f5dab9c48ee187598ce16eb2d606486e0e4347a7e15dac9c9221970e3dbdb23da05cfc8c050c15b6e81e2599c79b2f3eda245fc79855aebc75495cf420a9470a155cc313bfde7ed99cd1e7664893394a47632728caec2c7e7dc2524884a87b45613ec3ada006a06e243b0734c7106cbd9309f583d70ac90d91f4ee04c7c4f05ef2d9b5d42b44897f522574157b13af9fa7017adf2e95061f0d26ac51a859b415d7d536a68e59a56bc9a2d008891cd69b74073432abe55c3006b84ab5e31cdcd8b5286586668291833e35deab95f3021077c40e38e29710ded4fa8f9130138350207f015e387cc7bfcf0a46713a42c01ce8dda4ca5e2c7f39c7072639eefe0712d024b0f1014d8441084be4ed32bf1238765da6c7c21bca8fe167dcbee4994549c18a9ce7b067dc8ed713c117f3d80887431a58988cf26bd77ee8a37e86f533cc1f58857e0faf920b5f31b4e8c0406419362703e3c49f6a82c5e7d0db0284988321be0276986315b1f1fd63a9907805d979839c281f39c4c9f1dab4e4f03e22b4bd7d11989116ec85fe49804544a7ead81078fe839407b2a679121ef8db4ed8507f1d38076f36fb33fb307d5683afc28e1d38d57f87f5246938256a0358f70b38d2e0e56b8a70f9227e3de11dbab463d3dba2d6421f127e3fd432065b3593d348584f1b08a40e39b15bb8db82f72a12a849a5556b68205bbb912d3a23219f482da9682625586ed6f969af45eebf82322a4f40d265919869f84ba9fb6938f3568762375658a6bbd1e82e552f78ea7deafde8287e21b36df2cfdb1adffd7bd669600991037efd0515fd02ddd7df16245fa0b41ddae6cf5d115dfa065eb811810a9998fc61d7745dfc1d67230f7756c33589f8666eb25aa1477e11409dd8bb8c0052e37c2760ef43bf00723996670a8db530368a1bf3935af1ff98bead1be563cebcad9907ffe3d2e9f2f263a87a769383e97d38c057e35ced9c1d3c847b9dffc0d8190772864f391adccb5ba522c376cce3d118befcad0b4c334c922b18755038ed43a278b048d1157ad029da898231b23e578fa387110d4c22d272834f926c046ecff4f6093f9a766688e89a0946a12f69172919d66b16618a2f46b4231bb8a8067e776ffb7c75f872d7d4f8393f675411af6a221787a03f5e36fb6b29ec067e8edecd1ad568594812164599b98527ed1ad6f4699e33864150995545d53b088d4f85d1e1b84dfc1b9b63f7239d11a2e80ba9d5093f9933e4b933282d4702d979d4da9471b6982c2b34190a83ac6fb78615bd9cba652ca4606c711936cdf9b3665202a32de1ba0547e0be854fc9cd7a83f61106c747bafe750e7d41c8b36d4e631afddce66874905ccc43528529e242fa4e473e28add15887b9731dd004055465b160e1f7cab382cadb3178d1a010e0a65237119232865c61de796caae51343d977c73c6a6379f5f911da408ea371fd0dbd694321e5adb2cdea5c7c22afbc27424b4b107db4ee344d542235458fa01b2037c94f7b2ea49bf03106ace60f577cf085888527a482255a8a40d67b4775b9b33df0fde2565532034c00ae0ad61811c9e87335d1ac81ec5183187aa9f7e11e2531eec967c51b05e7bf82a20edecc92b676383d7e082d5bd85411cebee9d6a5eb14e629f88c67692e3fb3148036af519b5957fb04c90b55d37b9e27cb11d220a9f22488d687efd681f884359b992e8bd3b3a3ca3e5499880504eb0a3a583111e6450ec5962e010f7795510ab0943fceffea964d8f00bb97d628fe598b86cec8101e47ebc3ed1729343ebf1d3efa3ccdcc13e7fc1b17680c494cc06cdde802162c2ff8d74933879f387f1969300b0012c7db0ce55989d9cf08e59aa0d06cec69f0f9969d46877efa4a08c463ee6afa4dae82de3fe4dcd329c2e83918234d4742c39b0bd976f59b1563b5fb217914faad3bc32f272aee26a3e79e98424b58995085da116daf46aaa6c35d6021a045b8df70b35786dd4a403a29e22ef03147f47140ce1d3294706b61dba7ead0f70a8f4981533a15e74a6d92e7d014e696c58282328793dbb7befd011e711800eb78e50a1174216d13c5ef616ebf334f054d1967799cb83d492c8d2db115a63c711f42b1db7b70a3aa914621a7a576f68c28a3bf29520e9c2ff41d41a024ee1db148e6c3936660221973e13b451200fafe4f20700c7ef2c6019d2376165feffeb3f38ccfad1b3548b3e927b9194c7c25f15d2e573c5efbe67a60f5a269a88ff9d717b861e8b9a38ed12f6593a905eed9fda18afb5740f1ec0aaf7a6ef91e3af158aebc65bf53b603b758e75f293d917d2f58fabefe8419dbfcf422d284bf5670aa27bee1b702c4408a92bd357a597fef0922e51f35297a6429a30b025a63f909269a5cf47c9780070e201053181c00b0700e336ede9402409f4a81ce4fe1a440ae58f9c26ab318fe09627460d01f09cfdf31d6c443d54e95028d69dffbf7e35380a35742e0494217090ca64ae4ecca20809c883e87da03e02bc14d3c89646c345541b5b45ea8f0483036038ce62f81e96c3db3d4886a8cf26181b1fe188628c90b03d58e2523b9d0b471d721f2adb319b143a7c1db0bc7f0dd73aa92d06cf0473bdfff6efce9c38f7f63ff84ef8b2d41ca5140cfe71fbb4b227e76088b25a42ba7b2046f8fff0fc9b6f5c0bd2293ab2adadb7824c78208e89c06015e80fa26c76973a97e0816884d2b936314c2443b0684abc6f5af3d6d1cb4a96ce1dd2d5cff3eec6fd66e6dff10cdfcc1acf65eda30f9b03a93ca470ea66b6dba71b93744d499478f13e55f59c2b9326b32a100b870b2fb2dea3b059c9af5af7f3d9cd72d591b4c5adb2887c7382091db9a51a45332017be229da0b93c384d491b51775697e13b4c20bd2b2f2da51711eec7f30ffd07319b3cf8768ccc23ea8f05db68dd96aa696b50ca13a7c7786d656258a3497080654ae54d8a4948090e2fd9c231e006a914466d67d2b277b832f5e617c1ad27d55f1e78b2f6aed97e52ef17932ca4d4ba4322326ce54fbbc041188883ec78fe40a7d962cbe97bf7bdc67c5940a232c1998c2fe41be4e9e58c8670ce3a084c5db52e40ea1201bcd593d4c5ef5d85a8d4d9095b7041d0fbcda42dbf1db73776794483eb1782403e3f2d33da557065c747a2ad72bcaa86d47639e076a583488954cb40060967179b740b4727f675ec85d6c9e6f0d0ea6403f8741983b234de2943c59d170330c8e356baf414e619e893effb768fe49f425386c765c5326f4d1fbaaa8a70a3994f558d2466e43c9ca823059240174cb2c3cae6c4b3551ec757140d63c51674ac5e423be53f31305aa9b6276065bf2791c7d3f443194308c3f20cd2c9b9d518d51a26d65e8e609939e981d300f1f07a0dfdc338f9140968e6772bb13d2b7e37d8a4fc15b3dfa9861b1f5e10092a6aa1162544016e02c80e7e676a3b7e5ffb99af8791b1732b5f82b96e0a61db42d7457deb41a9d3b92b3c96c121d6b372c2c799252630d0aba5fb4b3deb654238a01ae81dd15ae4b53886ec287ea4e98e865bcee711c6519872d821091ee85c1871e50649693987fc71bf12deea59eed94a6d4ccf907cc96c66d31bc83009aca743222d8e60d9e2da5dd2f48f5e6e36c62ee49d31897caad5c9edf3c8cc819c1a4771e0af9b8cb8013e414118a20f9a49b2bef4fe41a20fe56419f1a6240e87702d87fa6e6c3cee45f13b01ef285eba766de752421876eec4c7565dcee09ca450a0812bc0b3745239b4df3061fd1362208a77c00f2a019345c03fa4b565c988ca096d6c20062b814d8f8839893bbfbd0e4fa85fb89a036c2c00777887cc9092f4b90f7902e6ee5eafeabf0fcc90b0c161261b4620e5caca78a068787f8cc0bd7d9114ee2799d75f3a727ae4575045f33402bc86cd4ef8b9f730b348b52d429f48fc6a20619c4d5cfeb39245fc13be9481ebb244d463e70f758e3b4aae46bfee2d9e5315bb7755bd5cfc18e63566ad2875273a7ab9893a56619b6179e2df4830a17311bbb6a5ecdee0fa95f1bafbd4513672621c8ddcf57b56fe3c1947dfcab88d06e9923e38bf7c83ddedea50b5815caa954f413443ef45d789b52a3f5776614969930fcd117254796a3895482ab349577ba06110c69ea1ddef78035945cd283042000be00be9f8e41383ee9a4ed553a4abea022dee6dea1f6d2874d22c36bd1cf7d6d9d9de9e44b89b06f9213fdbe530865abcab96362b542572b6bd001b1127c8befb54a2a0eeeb4fc33e6aee6f1ced4072ea1c79dc4d6b3c1da8a1420f53de82a9b76245a0011f55018edf1c52e54482c3f8c9b9d74411486125cc455fbc0f4b60267dc9c43f01a0132672672120b27ab3cb45a7126df38e4831332a40e5fbe971bd877e984f6c75ee050697363a4c67ed0a0240fbd5a4dd2346d05cb946e09c109690818fa4bb2948de21d731cf6149a3884f6eb02be4408300ae04da8f593127aa20f5d25140bfe4defe3fd3671aef1e0c2e6af12eef23dd4318f4e5278bb1dbc8ac7c150a2f41f7f5f0dbe749d5efcc0f897f95f33c8459e9e59318f9de2a4d395c8f7ab4b8e1c9fdb84a265cacdce72f1048cdd90bcb18c43f63a5489a27b9e7cdeb1539dacdbc2e9737172fe2b5c6dd4c8425efbf6310f3da55380e6df4a8449d5cfd42c57cb1a10723aecb5dd8956e9822bd8732e9723e2b05edfe91eacb74cb1286d22569d8b134ded819a4315843c3510a1007863a6ab24ae418b4ec416b1bbf8c6ebd64ca15c0332c895fa3d49b1cabf91148a36574975aea5d0e0f0f25c83e1acee30f1582e67edbfec1436361609ccfd1f480a42b5c17443b26e18fd39000643797c79494dd3038e02e9574eeaf1233f718d3953ed7f570789bf29b1076b61dd4fbabf64b6c2cf3ea7da0530b4fa1aff887a7d8d709fad821af82c6e2ecb47b97eec7417585bf6908772b31299e2900a72734730b53121671b0554113f395c2e1d785f1362d5a55a735b8f1acfbdd747ec0248a8777da05c2a87937b718b1fbe49ec6d2e27a111163284f0c7c2a45e6c900d939e56000f91dff5f53b52cd664f9a54288e81660fc853209bbce147abbc28185456573ddca391919cba74dc4067a3c8b34dfb70708d55ca11a2b15809df80f8b54bc3607b5002a99e006fa1803e89750fed54b3350900d0cee9f8af7a6b21c28cef8e5667b2a31e4f8d05a507427358347d20125be02f77af3a40c9566e6503cd1d55d69609cea445c485aa5d44df7bb65ef75a0f0416b1e69858a758ed5b7c45e868582267505617f30c1da477234ff6821518e79759c9e50ab3ad1fa8048896aa6b44d8a3470adc50e0c135121e966e5a7f0f6b91335fc1dd59102a7f1d1652d1edc6566c39111d7b84f07e2e4cce417a7b587bb8ead28669b02bab063c4eec7be09e489fb58384b3d68281761602fb1f33088b875a53ae2ecd5b8e91ced7bd46ed1d822ad5c8ced8a611fe47eb88da88acdf9d82a21685cdccb4c9807dca51b1c77ae397dd24315e6ce3b5e4c5e0baa9d837e61c22cd97bcee03651c1aad360cda4f9a9d93605fd0046fc455b1e2279dd94fd3454ec8f82b413b793ec37d3a409955ae45070e4fd3e17ec15f24e613fcd9f376b81434d031ab13857a502dfccde407b0bf9f66a917627ed1f44679f14a283d56001279d58252b32a5dee877d6c1a62777dc5504ce02472258dd5caba27b917fa8c94d3efce5f5a013590a877958a8eab39deee216f87b17467399765d557b75c7a23d95f8b5931d1f38fbe4593885ee8be1ed1148627116f7118c3d3af01febcc8e9882fab7367df80117c26754cc15272d463d06aa3f751171137a4b79c395985060b3b5d38ee2e9c00609998f220d22724a698713876b2f30da071f7c41fabb44c7f60b4c8dfe5cee4efcaa3a24f5fbc356e4510b5bfafdaa9c8c37c6d2658adba20414cfea29beb70497e50936b0b1e5364c1df1fb99a50c831235dd4f2859900cffb59c10fad41e2e2d934e2225b3ca4f21a2245692960a1f8f27df35860030dc043ba742a06b0fed01569ee1cb07989e9c6b52b2a014025e220ddf52da63344fa7f5aff60b99245e1480a4441b72fdaeb372b9d374bba199083043965f6a43579eb01b94f310917d90001a47e5f01640f6a05572ea298a679bebfe3d785830e8fe866c733b5d4f497237ce66d9a4cbc31ff81a6e9b27b62855d3e3afaa923b74297086a2a39de74e1b4ecf6de2f7e379e6cb334b22e55d60e1603bea21105ddac7524330ff3b3837f7171c25c1512087df83f0f686a0654456b53adadc04aff9e30e1cfbdd2bfa681ca532f42fdfb76d7b86cc047e258331083b75b15ed3bfaef0b888dfa9805079e80abb4324870270e3773e5e5c527c7328c62e74809e5109a1db8a737643dce02063d4fe64a15060ea89f43e8e1c9c27ac825612a9e3795539f118400a3160af58dd9940989050ed32cc5b1460cfaae1671ed2023721f11c26d0bf116e8b825237d7a064d5300a3205ad82f7a1cccf05694edc140b8beaa50529752b222b77498445099024117ab7708a1531730161ffa972c76ed200e68d05a7c48b9b6ee03bc25af908c8ef839179cb5f318991c20ffe83d8710e8333cb013173116f376b088326980089816667317f13bae751e6cc2eaf3c747e8c96dcab912bb9e507a27e881e0248887321574f090dc6d8a7460a8e29e0956cdb160ea94e694997e0dd4c5113e5defea52e8256860f80bc513f53721400f07cb12c917250d7f09265930a542af4c00f90f2d32bf65f692084719cc97e36dd92032b8123e102d8700a7b8b0534b126695e0d83675e04eb04df6785877db1d3f88da9d35343e4b35fad9f61533bc8e36458c6082c9d4c06a3ea9e601f9ce020cd727b45b531e553f34f507f7862e61981dfc617f3c7b56a1e13c0cfdb366c8607bea03c4819889b2ae5bf721403d9dcab0fd327643c766b3713ab64fc3ef395a0a3ebdb20cb134599e60de0587f3fb131ae5f091104126100658223842b52357d90cc40157db2077318ace63bcb58202c3a8e31287a018d7dac4bbc979c34e10e2804a87112a81fef977d8f38797872c66761b3325dba4f2c9f843cfdeb977ec92d495941b0f11ee3e00a7b83229f17d5d80655813579c21d63d7f5f79e6de2dbfd726b66f51579ff6cc5bdff95f18a2dd2b0c10a85c1fa240ae262ee7cd4bac431434224f817ce00332db00526f7416e039632c0724913629f16c4dc74a023e5689755b5c9e4ddc750852a9c153f8a1c2de24ac10176b5a44af523e64c9a23511349fb1f445c897cf3e99fd32e80e0a715b3e87f813e52aec755a53d243b68fe2370d80f955eaaa7323cc120232f3c04e17cbfdeb5e65279f41f4a742d12e93d323a9559ca3ff82debb92f00175f5b0424b696fcaf415c4f6a77d4c604cfc831b168a30d888226829f05c89aa467fe242f234026060b4601247f9a598c974068c42079963a74c19aae4ea6bf04ccaa2a49f63fc1ab0e95a006a9ace602dee689bb43fa01df09bed338188960d65fca6431871ad27d0015c19f43dd72a4a8208ea9f3ff07e5ded5824f846d416d0025d9c5caa8a8a8d0b6ad7de671666d466f09d94d755e13031553c84efbf726eb0c7717b00ec0c5d3cc3a830e023ac09cb25a3ec41038081b12092eb514073975a4d0c69d9dda96bab5149ce164b8be9c8a44f0f98d0c026d005b9bc91ded31300b0c721a049bf250ad259ee5d42d30234cf034013e1e443991f18428f49d691290a5949b1d0f626156c51e6442788b1e89d8cf39d84cfed36554dc0624b06179283791cb3da12cb34f0c6c44a30dd54cad3eea39b0f3ab986650ccd914d5e92dab9c66abcccef4ef7da6bc6be08f53102a57ce938d004bea72822ad547cbd74f1bd44270c264f2b3145bb4926dda7ac3368eedf0238df3306010a390f41cabf27a5d9978b40897c2ba58313f0e5ec606690605bd18475462e03ac8ef02b695c0c15de972c26e8e3cae20433975f8c725eee89e4376ec1312aa7731147cc4ca5a9f0fee788fcd1b1fb408a3863fef273d09df63eef8f91a5c0831beef11cb6378bb12274da545c9a64ec6c8a43f304e821f65db1d46f0debf69ca302a44daf02e1241bd5ee94d2af0682266d14233ef269680a442e9b5e6219554bb90ae80d98a26c5f87538bdda6d5d8292644f3aaedda10114e8d5cdf0566389fd24b042ab714886875bc73af8368107969cd6baca4223cc9cd471dc69e2974983c043f17486829988ce5435252cf3aad808180b1bf17154792a085db2f032f961306c6b648dc6e8de430151e5d2da7882ac27c1d696b1b4a2d3afe431468870f88d48760b9142f06fa85cbb0420de48e2bcf292d9094cf08b90a1c4f0d94c6e0acaf8a76cb7db298b5104cb3ada1e5c00206daeac2996f17b6042eb20a432365db6a40fb57aa96034a0704c85acc929f84a30fa1752a00cb3322f9aadcd17e695a770f163822fc79c41068bc84c3f31aea6d3efb939ec513d9fa871fbb97682b81cf1b453b9b04a7b7520b3ccef76faff77c8041d6c313ccda95c3a01a8b76c447684c38665c1903bd803d32c399ddeb8e144a4f6847c73f0ee9314412cb16e03e14cf63d78e57c862ed687d9a56f0f431addbebce8e5d311fe48e28bc8373d1ba88a3ce2bc29bc1c76bee779a02a82bb43476ef410f3af49c9b9dab96bdeab629b7777a20fee300b6f2b6f39be881c88adf6c86e33187bf0090b33299a458ebf6b617c1bd217fbf5301dd1f04db19d226c502bb72ea297aa86b60f4cd4829a9a33d7d8e46beeba9f650c3b78cbf73a9f6c0aadce8cae864fbae84cb93820dd14ce6b094874022ec31b575fcdbf9ff380e8e519dda70b6cf4019c15932f2d8c8c06c86da35167f3c5989de819740133a7231889eaa18d4fb6727eccc8a5c294fe38ca150a79531c864532dc564163f460e6d945c9994d96cff704494a8aa335c4710eed5a7c82e006bb57101ac24af765a7d991fb827ab7ee5eef05181dff97cde6bfe3f20b7b1f80bf0878727c5bcfa2ddc3c7a4c402fea3bb71c7c54376eb1bf71f248e07f9fbaaa7f20941d0d7be3931d13a0de925bd018dfcdd74875d69e1f92bdd641065be5a0dbc380e9ebf27cb3f0eb3b15602e3b82ccb74ab7d73c3e1555f6f8ad23ebe08d7e146b173ffd6e0346b75433b994f2b6b1066c3fba74db88030360c6c0e15e33efa224ce3c0fbff5868c857fe414da5a1cf575cf4bcea4964a4fa24f05a068bfeeaa8750d7613a643bcc1f3610ba803875fa3a4576b4e5715e7c976de710e7917bc4210654dca2bc98ad05ec2b6761dff0c8ba5ec6db218afd249a60c62644b18f5567799fd0f05aa2e95e37aee81bef1c17e131eeb5d6cbeb625abb4c836112e2990a9655a1ca6885738283305fe0f84ee32098a5b750891c04951c1f1281374cda96806f96dd5aa641ed36621c567325430bec1957af926d68b32b99ea0ea09122dd0aa4a373d37589f274301b42bcaaa6fe59c7b9148189ba0a124ed65bd89f9714e2ae5cb2391113ab6c3eaa3cfafa7a05984df7a8d954b31be97fe6c86c682ccf5e484777b8221e76a782526365e1195b6fe434c6e4601604f3f29bd6005ca5b2083e45d4d9a910f54dd0e56def733b2efe59c676c0a998844dbfce1e2cf06d34e361ca35fd1a2af61a13de89c95bedf717aef2fb12f3b69fe3bbf31acc4fc85aef9fb478649256346021ed9929f339fe4849af9ec01a2d1732127c9e743d7e9f3d261240e0ddeb15c3048f973cb3b2036d43de1613a65f9cf83d4cfb3c5ecec22e3f6cb9245bcc5f258e62cd417fd1ebf4b6b7dd403fee68625c99ce97b4fc97a90f79e79d3b8ecea138b0c842167e5d85276263b1403d49c51ed2ce66d4b0acdfd4f49c87c525280e22d3b0a281bb95e3f81f61798b00608eaed0a0c891f7bfd3e73869e04e6dd117a872edc2c7d2d51a4f20ef05de36478fcff3c8857f763442e82db80514e7f8c1b35e33e36b511ade682702f8eeb0209f9cd6f47b368710fc1f3befe8c04bfd3a7b70a7af30d19091f52838ebc13dd84131ff7341f6da67fff9e461bfb19a3031f0d4c3a789b8942e209306833882893f8d239e5e53e6af7d11665544a3a076e0f60ae616842f4fdd7f204243cd28126e1f7271c144961e7c866e2f46dc0833c9c867ea27fa9433d822e17deff8ccfabefe78ec12e6e0cf71939e8abe47984ad771a95e5b5d939bebd4188042d7d816328773c78f28977dc9ff6226ccbf20a44920c2af09cbb5107892534051a165004fdf5786ceaca8b3099f3d409a18f5489efa23a2508490a4ac6884da222a02afd6438b55bd6d34643d9d2b5cb21b3c3993f09305784c2ce31c134a876a336b2426469cedfc4c743e1ebc9c2d4915f8a0712586005d1ad38769361f2922b7a1e46a46829b04255453cc8c484c87db4c12ed2907f0779044ce11106b3fd79c991280b08735b823a38b43ef3c7966c35889c589749a670d98b95364e5e97010e7c57275407b28b781bd4549f8ff07a4d256792c0a3929e76b17fe739f69eb15e0ef36c8e5208e9f046db97e85d2d226ab8fb651c2540055424f4aa52a53a7a07f18bf10dd3eb1c3022a285bb9a3489a1c85b4c04df62912d199d0010764060f26ddf985fb2406d5c25031239a6e93b75b19988e446b9f4ce0a024b9cb18db707edfbeb851680b181fc60c1278f6e673dce254a82322eaf56031f53f1f67c59b0cde78847f7de4c9429a83ae4e24e90011ba716b9b81dcf04bb2c487223148b4f2701cdc0fd7e50dc2d189d9280d9234a6ec15653237e511246cf10e582fa50dc35f39709e7151a0ea2fca0f7f543b07510d5c6c91ba06ca27c9e3c3721609e8649d096d846ce224a46f7c0ad5d62ab1731e607e6250ed427ba5cf44f7c172768c5aa0f679b7159bd91442658cc1daf3d018dab98bf8c6d120c3533885fae652525e00766bcfbfb4af3a6394f79faa3c996ec3646a33149fb85a4198d2b464f28f6cbca1dd8f57851ae99b7b24b2d4c5f2a1fc031daed6e383edf71e8a707f244bcead225c9f732d12715e96ec84f44f89947552bc5d9b8842f47b51b01d9f454321947d382880ee88f936903a05b373b442d114b25cdbd76283bee246f90d06ed46b094e2c586b3ec8298002dfb8326e211e61a1a599c3bf2b0fe0defff1deaa29be9ddaa3e6e87990a59741bbcc92b3945472a57196578a3dbea6830b8392f2ec642e86efe45b7cd0e4b10b633b62c4c95102a5aaa1d050bc5c5b35bf9bfab69cd57e5e25537c1ef410370320cafe1c1c4773063282df9d6090af018d7c156c4db86a4338258b70f753a2eecdcc636c759dae0ff3cadbfb23986a2bc89786b20b5869a4e7c77acb79aba3fad321b1b07b8959bff7944ca0941a41225d51c99bf3bdbc03f83323f8ed1f101145cb4a1d0dfedd89241e3f2dc44a8b6ba11449f63200e3a0341fe0d6f457da2c3c3fe046fc6e88e6fbbe521e18943d3407d8ae5e3bfe295b84c104eeb5f18fa0046d33643092fabd726653e9ecabb6820141e02bdbfd8a7f2a210c1c23a59f105ff8bf88222808dbb1e8e018c3168e845753fc52289be7b39988a26505e2d2490e0a31112213ff790a2351b0cbe7cb8fb096ddf0f356a0a412b4e91676a9d5b0a2915685669f82a79f58124fbcce3dd50d6305f95115b250b6fba57c58cf9fdb540e209f0103ed2e7a9211bc28e3167b6cc05bb781a7b8518920c34bff3f49d668a0b435ee6f381fe3e1f240d834d29b1e5a59ef71888a327a9e1f3a5c02eaf3781a0de303dfbe8fa12c3e953ad520789b079a59c207d3e4c9dd53b3ea4caa7f7a8dca6a99ceff796bcdd875c01790a0047487f041ac4eaa4ed0a598d8c4cf226659d327cfabfdd787e233e0044637ab027483755d98794f78c44c01b4c65b995806f009ab1d4a4cd862b4d8eaa4d010d1cb676787ac996b40d21ad75a2d50ff6d3ed4fd75902f2934b7a27c88b9d2a3558570646b0ba1109c998b9d0f17d314f635c060f1c0639c8c116dabea8dac1a216dbdd08700f236265506a91007170473e0fb89a93e2f0bc8a211270722eb7c33498a19c09d74e4d1c1275b82bebc34f9535ad53b33a74b80640d6cf966d56dd7190cac669fa365021dbefb5735e2b56b65a1b0126e286ecc53df0a9298770d5339967fc783276222f00844a386e3e1f2b8c9471062cb82602367a685dd5e6e444147dc422d48f1d640513b45316d109f6189079d12e3e6c1fa88798bbbfe1581ff682930b564de32d943a289eb17ff6a812d4c70e88494d6d56c2a342c8c59806f8d2356a1ffa4af14b3ab4808685f3074ff99380dd1c9085a5b566a165e3b71fcd2ffc5a1d6852855682f9c6f8c672b864121c08568b51e8df9a0b49ea81afa7f9edba3c10402987b0c91609e5dd2592b6daa52afdde2c8e8ccfbfb6e37c16bc9e1954127b5715b762f13a198158c475f619bf7c6840dec3d1f83938e16bdfe7421035d42fc57f4126efd2d08c8216068d2cd1942e3f4bac737ee910039b235d4798fb674e95e9f34e430c74a2919d9dfe939b572000b28234240a8ab88029d26c11e6bf84510bca9291a35ce73611c927911c3a0ae3c3996f0da6600ccd9e582c9854dddbca7a2dbe051df341e135e2c5267127d1fd6a3fe1f822575fa8ace147e38fe495f3d388763ed4d8c158ad80e482e302273508d9b7ada52fc160c7fe296ca61e3bbd9f5dde7b7a249ca0e054b0467391f16cb53f3e4c97cc47ea4f62f94ff7bfea0d02e40ad49d359d3d228464ccc79f875196d9f555f4a33f7257eba847a70ef321048483c0e2df27b07c77348cb12ba9025745febc4720c1c61159b77efd63aa4aa935cf81c5ed9baa13542dbc8ef9e0c247beddb86af5fefc5f426e089914523abc6d57821bd317a79cea958895045cc634d95091db6a3a1acd4dbeaef2225370f980f520e29951bbe713a21ffd87c3e38918cdd09c506ff27f34671cc8074902c8844be89007ff6666d8034114390744d2276a8ef26fd238eda115d363437e1efb03cfcee42aebba1e3cce7f3cf7645f4bbed35409460e5a83a557a7648d91f5a01051d409ca5afd23ff4e0a0773bbf5176c98e8edd0307f4a26435432f5752e6c795312cce0b970d87956b40e27993b3c03d596069eccfb051e77c670ab573ed614c1e7fb07163f97d4f4819f80013a10df26631bd5b8ea506ee6b9ce34a2a7af8969cbcd599a8a4100a95bbef1d26e9dc3ba9d6a40774b9d66df4697b3ac4beacda869bf4008b9b1070b21213ed94480b431024f5d0d78b7d43a55c6538ade3275f4fb7513713725f2397208ff9fca0027affc3feb4c8ed075eafd688b20385091c18fc6f4ffcc14617d944ac425b2589239661f70152c4b394814f746522ac99272a25b93b2fa55b02bc9c53e2e4e5582af547a001d53d8263434614a14a7a073f097788d67974d539a5a2c10fd0f876e885e02d719dea5f8cf97e41ad0eea5efdb21d1d0df1168de391fb2393039cc8478a50f177d82d993765c32b247370adc51f96a266cd24d5c7244c0963b480828219430eea197fe0dd11c6ea37cc94482cfeeb2a3bd84c071f569f97fd4d17901480510d2e7147e886fd7610cff636f380d2da48ddee70cacad885a9efa218a055812412243e8a2781d244d836a369d499c96d09903a1102cadb050ebe0cee4b9e5820eac53a2223e4c8da9fe6effc704e07626eb2b9080b171efa9f9b2a6d42bee4d102394db638ffdd6737bcd0307cb6e34fb579cf9a2d010b5de27fc8fc894590e7eb85264aee19e1c8f04fe81ab6e3af2a7f380d7d554de036a891b53f4f187867d9981276ad1d965ffa3794c1d069356c2796087fe670f9bf6dddfe8914fb10758e2f8e3704023b64df5befd3c08453ef6e4d2e267d9a006a0b4fdfa22b121f8cd49686f3c26c758b05d883d809bcb413ec90e909b644ffc08b5dcd60469abcbeaaaa1291788678f5af9d5084e78001aeb0b61220a090f12648329f446fc967417482c8c43fff0b2d4c477a315ceb10a58cbe31cb03101b8738cfa73be8b3fabd1c4bbff3d579c597f849a21593cc9138ece1c8b31448238b04a1644f3c9f5bd56f038a2e0bf3dc7cffb6801edbc10f53e1f6f10adb281b18d12879889f2039ccc74ac0c4ea11aa7b35d189b52bc497025f1f700c0120f45be717b78d7448f0cd19c4074eb7071d77681f830317c91d4a0b7a6c188244180e956a9c224f75504bc605da20c301c8624968418f0ffa9eb10ff2c153cb544b75e5bdf813e2d8819c87460904530b803e72240ca443f003914660694baca4e42a9ab3efd34212102ffd0830b6c0367b20bc8edb5a395636b7a612a5f17c3bad187ca1b6e8ca0bcba0e4626802172c3e085cf0b7a1f7efb901ef82b02120d0a4e4e2707a08b399bb20067132a5c1b5a547c1d247cdeb9f9f6b04bca6a2849b2a20f117e5673682d3be9f5a13c968b9d997ecf813309301c05d843c0063e976fa106381fe58e0f3226c3ebb93aec89bbaedc5642a726dceec16f73228dcee2301bd46b56f40101663a0ae8647d84275b75d77f8c9da97a64e7ddef3c6c566718b29d3f875f9d23db3ff29e460e343abe5883965fb123d1c9d3f9481848d1733d3f80f31b57e3d9c0b7e0ffc059ed9341cb1066e6f6cf990ad9a65dbaa4120efa62efec12ed5d66f3070f9dcb0ee1f7f0d9267bd81fd17e33594fbddbb92b624bc1f690681324de60a68ebdfc0dee1eadb5e7896156550adbc70e2c1156ee3762cbab739201de37914d6f657cf1c77088ebc760ae63c43334451e89b36ee19fb435b2796a31e7e165fb0227c31b032671b5f46f36f2232dfcc68d5b168fb3ba8b49451e146a7c70b3b0db70f6111bdd5bf5864cde54e619a9f8404d3f3feadb9ca3b55a585f5866beaf0de2c3789e33b670fa3371e32e261739ffc97517b8a7971e6e665ab703e9e5d73ea371aea9159fe4a35e9d56165f7cff09f3d62b6c747c95a76ee674c7f60f9af554a588fb411dfa66f0de1463abd20f16ef5801649c6c7610dda9809e822e7368bd58e7e84792782e075a7380c08a8a9707e7a20527c5a850707dedf0e6c3d5c591b7eb08595d1760f5c30f48e87ce2e5d69d7e6b6581e6f0f61b5d8b263819cf0450175d6e2b6a31d603284b5af06009a448026a9615a6bc82a0bd090bd67428aae8d7099d567a197ebc19a749d1ef026ecadf4f58a07012e374872f161677455518c18eea032dcb232f5a3afe9afff08177b5cb831f646a0fee56e117780a6783cbee1402e088760d58e7a9f8d8a07fc02902d052980d2f8faf00058d761d97efefe7251b189220cc913b3646dcf2cc42075092b2b97cd6a531ac1fa3f503b070e5e56adf5204b7fd68f0f072dc562471b0e02254259792fd88a9d86c1b3e3624aab631aaab0d28f8d04a1dbd95966937638dca04ccc8f30a4d10a6d0dff57f7522bdbf0433faf74b2debe6dfec2bae0718b0613f4b8cb15d5d730b484c18a55ed2206040207f7b538af4c8e0a41d897d93b0fbca83689014b7d9cfd2cb430b32171b30e9488d8512b882610d6b7a667210d6d0abd56304b114e45858227a1180e936a853f9ff127364b10ad2543eab60d7c5a80f258919c6691799b1e041ed3b45dffaa0cba5c2b9321b8d85ae7a05f0f99ae2bd2439a618495431302e3bd26e489142e7f3c429b725fc644a5bab7f9b4e0c97c7676431863c9610db991bc598235e18457f8d440dc12af331127d35777f539a0ec0ebe4fab50b94ef62ed35162093a607f5358f49f9a0bb36f8779ace6f1daf1f42c2d81bb17b0ce493f1eeb37c76dfc546010f877c9028d6d8078d01ff2e1d5ccd67e3644fb0f24fdab63efb899a692783303375e9737cee985cb20f8d6cdc435aaa2fcf0c528630d01647e7e1fb107f14f9bfd4b0d4013461e778dd72ad87dc5f6da15ac4877febb5f8a7173794a7218669b38366b5221f1667f0bae76521eaee06c9062a104ac0756d32958f16aef91e282ba01ea3fce2b1746ff198e9ff9b8efa43ec6d9867c863ab3f3310e0d2f1e5c3322bb649fcd0e593fdf227bb7baede71bce661089e5803ee3cf5406f0d4363b973a379c627bf3820aa950a06fabcd5de09e262772df9d809b588f4fc235c7b25d2eb66c6201e9907ab37fc8a54ae8a749c91de59a19e094893a984b9ed9ad043ecc66fe4e5388f4732a1f463189f9fb9d910abc781191f6479e0e1c828fad94e6f88decaa87ac25fbf54050532cf61e066b23ae8b6ea6ce664847200c8a49f563724641116a5662d1e6c179ae632d7730d40b904a963b96ed54875ce92329c3e36263462ff28959998d0785bcf526b4a454926ce637ba7c87179915b88c25ed6f4e95c068eb9f7c47c0347cec7762ac0ef097870d66a50661c15e35f0b7ca4aee092caef744bde889f6e0e0b8f4a3c94a5a21011aff573cd631b9747bc629c7a28f4ae71491f3345d6d02df98fda1061aa8d76cb1248bb81b5d07e74f3eea2f9ac761f6226f6cde18a02e6012cae0e0bdc6b6a9ae2d8a9411dc78d570f50c5797131556144262ca03fae4e1b03e1b0823a6375accf571aead0df86c72d858b9a932ec27b3cab269bd841af7d6b62f571f6dfa298634fa0b8d0193d63d74812aa1716da2e28c49c8919bc6f031b90027a04768f4d1c6f3daec28988120a7ea4f4807ddcd55346fb4feeef4e627f5eae173157c96dd8e779aba277dd2ac4d13269f8cdc2e7ac48472933d116f43f79c3b0aecbae44aa67bc6bd41de00dce85836ada79846adacbdee2872fdd238c3b7bde94780af09eb3dd64ea74e193c8414c5090ace00b25a3cfd2946f8d49d164ce3aae6ecba68d10d2c27749cebe587cd2ec29deba9f00bbe9e51b795f9b522d6bfba3f00d109e82d2c5fb9be2c3c6a36e2b688ede8d73e1cc803032f89ca3daa068953c30c622bef315fc4ba116b59dcff4693869f23200f5939c8b5327585eefc5b2e55418eee0dd9c62d08c58f1238e6af7803c7396c7ec10e522da288055a9b54f884a66103b93b0aa0fc33f14622ed1d2949ee071c595e5b98ab2eb4056213bbeac9820dee4e339d87a5052eb2318a55b0eaabd1f6dc37055fbeb4153ba22f25414c184fc3e87b1cf54a5eaad6cd0fb4040361a6e912f8ca3a09a90920c47fa359189b45efad82f36619e708bdba1c976fc6870626fccfd4783faffe10181de8447f168a2074fcb343b47b3347245cdc8cd1394a788911ae5ae9375740c50fcb53a5763a0c776593163784e8659b06f6fba991da2bbc4e822ee05caee027909feebe0f8e38a8da3caa807b8dd4cff9d0374bd60658733866207c1d547576270802e950c2ee85569c109ba553ab842a7940cced09b12833b74a8747081ee9b28a580dbc76f864a19bec7631e5bdb1185d7d1ae8ae319e0028b6a714a7975c780d7377ff8ddfd1ec8c0800b9dc563ea23b60c614828b01ac44284ebb20b29686c930252e743caa7bc67a0616bef84ff602afdaf2f4db861d0b48a50f8e5d3e70726ce8f2578306835e11fb58a3c026f809033203e0f82eb1e7d1dbbe3dceb2650762ea9bd7c0e5c5e723ed563fb6af0983fb811a22ce10596e9a6fc8a9db00cb0423c0ad5287ec3bb825b22f0f42de37391971a18abbf36ceae4aed90232311b01785d797cf5c3e552f7674320650d1ea3cd95d03a8f4073d53adbb3f509536d5cdf8b2d6e4aa76d1cc01e9da36e0439a1d08ba491a95d164a149bb0164ed7d2b62dfb0baf02a68d9ac66e7a1b6412f22666542d8133837f84712fc76344d0d7a4025b93315c1f858356ba8dd69f24f920c8a3c82f07df0d2a6accdf29369b62934516365865e3931f85d4651bec6c64f1d6c13cdeb3b1af541d38997a78c8d5b41ce59ce9d8e98b3b3bac7a3f690cf2b0aa5fe43c4a6f8efc4566a80c452ad6e96be5d71cb074163ec71eb7021a050b8191f341ef3cdf6438c0820a6cf1592807d975c64b42545b171b6e4cedf4b00f3ceaca55bcab965b60fd33b5f1003c9ee807143f3857edba16df311f707a4fb4fd0cc73fa244e4f6091ccfe9a93b792d1d611d203d6edfcf4287afae8d16f654975136a42c3d83fa9a520cf8e73a55d83f38e7432f6d6117885c8ed13d13b3c93ccb8bd69c05ad3337c989d59d9c3f73c15bd8f032d7e40ecff01e364084affc3719e1015fc798f4e5cf24b3b180476529399bf93b524cbbfabaaf6b5826b1dd8d1a32de079b64c49487d1805569d2d99f5544a5ecc67f8f4782b972c94f1a3327cd1a7afc5699e22ec83752ddf598303333cb70db629c006212f0272299a74c11384391ab979aed7c2ccc9603684b92743b0a3c40b3f6ba4aafe17e7feb4d2fae66ded3d7a8dc9715b0c5914d82cbc9fee59b9216759969c0db466f188f01c6cd43e334775d2cea49d38ba31032e3072ed324aa97878c183ed301ae9dc02664d03006381a1ca346ca1e3008918ba8492bda389708f83f3a2c06a03fe9051ac2faff447c34858d7df16e54300f09f417428bcfc309f6b2746597b1ea94746dc664942135fa3d1fa2d74494b53e1c3fb3aeb8a5c6bbbe7d046b6874d7da384a8341b9a79e65266fcef41c44fb2774ae8d632e5040c698ac50378e556533f74e3a7868602a39ed460a11fbcec75c62fd4934efa0445255be5da49301c8adc0d4b9972f5cf81ae632ee5c883c402aead6879326f2cfcc4e457647ca1875f67d8270878366960208a858e9b93ca878b9407885d4e9407608f78cd139b35f7f513a28ccc465cffe96c281daa47e49d7f5c9eef08687e25c12b338a290fc03b3f84b11442caf2fe483fba68f5b0bf48ccd3624283a5dfb5344e7e8852a8d578f603039a4a23b982fc12019b4df76099d03c95ee1ecf378ce7c80abd28cdbcfc94494e7d1eb2786c8ba4283ebff7b67b8c5876a18f947088e819bafe552d4066d7743e6cadce2eefe964442fc36c423f75ce3f06c43683b8fe0dba3cb8cf33606f9a08eb4d1b9e318542cd966999f469286a473b16e037c75dcb5f3fdb95a851db368d3d208962c4b7053ae25dafa7ae42a3b36e09228cfe84f3af1b4f06717ba34642fd1a42092c6cf877426659383843e986e5563139a099358d1de3f4609d4051e526fd0200af013a6dd32d391141295722804b28e3320d3d0383650c7fcb2467a7b05d8faa548e87b1734d247820f12a6d151e5a6e35a04084511f5a8a370dd806116e633c40176a519e75b030fd15a1654d5d8fdeb7972499c2d9a63b7b7c096d13b79539bdbe099c5ea80d9d4ccc6bc3323f62a0e862eb5c83adac0030a51114c16fef39f5f4179a2fcdbeb706e034e0d7360e61d63912d5a5edb3fec5f0f6044ba850d00a7e6a94bef265c3f1db0e25bec81d70adfa11a5402ea8f4996e4f3a0892c74bff4b7fcc47340be75c9e30bda20cf9cbfbbb7894b09921e06d06ee694f0574700d66acd2be58169daf04925374c664da7ad0fc7886ebd6600059fc31066e58f5f932f33d2453754c09ad56347fb8ae533d75212148e7195cdf6cdc91dc9756638cd99dc10aacdbd66fcd50a94ced6b32dc4725bc54c75432b5f9ceacfeb3227c14bea4a09a1736cc2f388adcb10ba84d071cfd76dabd367ab804d72fabc4a709e60e62af6fdaaa211843ca8b3cbcde59d59324fa2360a6de5816f3f3f117f789c7ed8830b0ec868d8e4b585dcb6be7ba2a42a6dea9ef46f1681b5f7aa7e467b9691d3161b01af98e5157fa4a989300a31211b8a940c5eed4b84d73e24266f13ed3e94b328f7421176086900c732537028dad17a49880b3d67cace1d09d2e1af58fa184911e16e0fdf821e92aa0bac0810fbdcf4d9f894dfb2789056366e074ebb87e5601f4635f0b8d4f3c04e640640d14eb3480a57fc2b8ca31d282ea19c36e589b3066b1c750ba0ec97f92ccf9f43cf2cea974b1b91e49c3bc72f92bffee82a632367337cba121db8c01a6feb8d32506fe616c281966f396faf9e036d46ccb752b7472e013f0b690cd6931d834824ec9c7f386342fb2e5036c45a73029156c4230941c10ae9a4600f4d26ecb310173fec1f8bc8ad21696cbce6ff4590e4bbb8a3b1d6ee0e02e1bc0c4488356b9e66dd20b5df687ba29cdcc5a7e24acfda7eecc236f6986138d069f0b65e9ca2e9d1b61dadac7d63f3d005cda2c6ea256d7fc0c2c59f8371cb6b94b4650b8011ee8c54d635fb7cc1da9564a0058c104cd0830a3ea54781e34251319ee6015835779b57da6962536576caeacd1075277f3fe609edd2bbd1d5d43d5b62fdd27fb8e39a91b0a0b172644eff13b6108cd3d02b0c845cdaf016296c3f3e63a63ff2446fb47c5ef400cb5697f2cce0d64c6c81e6dd8b688ad013f5f0c70bae312970463d303492166b5a772784db30965178f27ce1ecdd5118bf3a9f2544132458ad121af264eb1f34366768ff4ff613be9e65f3f96efefffb209fc82c52c81d2807c09177c1eadfa5f7d86f1ad371ce23e9781259586645f7353cd36e5c59b98a2e8c487d0178ea2fcc63afc5c08941d84f2848de98a1daa4510a1e160d9fdbaa577fb1f27c4071bd3083f4f3da4b649e8b3c77bc78e5752cf7f18e838f77bedd474a71cdcab23c856131dd4bc38bd44730f8d8b7b318de3a0043bcb9d95be5fd3fa04105aa28025511795edc27545055e5ac81dd2189ec9736f6c3f5235d894113be55a754e312fa31c28410ee44f92da13a452aa4bd27a9c4fbbcba9224b1f8a733701a4946732f0dd18771160562cbbe9e748b8021ad7755c030708dc5268dce751b5ed1044738c6806d190ae37f41f8c7f7e495c0adb476aca5d39410fa060821732172330b064c119c2a011a3283f58791592fc3e1ffa2221bb8977c240476c43a6e1f58d51b11be0d0a330d8a3def97dc78886ea62d582dbe13b2d6d660dbfb62973031081de82f4a11cb23353c0588356265a5d43931fc277c4272243ea9665417c6c8cfdd806a3696e08b6519975e0c5668b113264fc87958abf56113f61a767dd70dd8741077fc7c0bf5d0b7a6152b0fdea651ed91c0a3639fe7aa8c03948e2b70db40e1813deef26b138bc5a422646b2b05b6fa2c1d1ec170e0bd7dd02c1e5d6789d822e9d578af7e63166c789c5b9c9fc69d42f04e955bf13d69927460693a806fc2cdd9a47da9e7025fbc477f3f9c027888cb1ef2ff8795a9a1c65db077ee255856500b6e872634193c5760c78087cd2c5625ed15ed997ec9cb577a9fe539f1b58747b6d88dd678c27c0739ba9e009092a16853d189cd5261133eaed0a87ccb20406119a01c9a0fdf9ae148ec935b4de9b89f11c8fcb3f867c99be7519e5d9c1697fa9135d3fa4b083afdda0b52587808795317b2971b9f987b6f4ff30e8df9de189ec91fea6142510f3af772251be39878fa70abaa9dee9823a4d8b5153fd2fa03c38e477acc57461fd95dda27e68fc0ad1e45e8c18b831e23c248eff823ed31b8558dfe47ac70c69ef46eeceee866c36d0fe592879c0da29b064a4cb636f2fe18d41c3dafd27cbd133f682d991e1f0fb942f2aaa14240c2f534488dd7a5fbd7f1e5e77287335708c07048dc98307ee1983798f684067569ef189e17416c11f1a39b3285451b564de7e4def162be025353a57193ae85c5f8bbf83fc258fc65da55480fb4be2818bb1b77855b9a7d9b79eba8f067abaa29b718e4ea01382601b6c9dc6867601109569b2fc02a400cd6ec2fa871afec0f0cb7c13084b3f6bc03adf85b4591d34978f51a1149e3f06869ff51afcfd46f825ed16fe3894bc2d6e562e866ac713a179c4dcde18c51c32c150f0488b3695b8132aa50f9f935c9229c7b77073899bb8d2a0d781acd70cc1a7aa3c283ebe356ca625ca8966df5fbc5b2bbcbc51abb2ecc3914ea2643df5f5acd4118496131d9582b6022ca5c4f942ad78f8f2b56073899d98d2a1ef80acdf0cc1a7ae5c283abe750d45b4e92900fa8fb558d3893f81ca85ee41addabc25e2cc39a6459a425c269eb84629dfcc49fc40b52586ba5f094abe6dddff13f24d699e41342e1902c2a6492c0c3ad30c4cbd14abb3f002c6168d670a4357ee05f11c1e75d30f0830e0d08faa92d209c7b4a378224028f6cf29db6ff88aba33728309be3cfbd000a7289c4bbd9f9d6258978f2bb2ecbff1e9235879c15f17387d1842caf1765d252e33c6ce6c2a3e73999159f312627e192e4ca86f70233f5815d889bfaa3f322a8ee2824def4b495c53e13016ef0db4cdc23451d3215c8601de49049043e1fe5164ec8b9dfd5fc61d4d15813440c3dda3961c9588a609d84693f49cc9b5a8c01d201cf96b5e806cde32d1b244caafa498a3842764113d8c4f7196608d02802841e9427929376118724c2d275183926c7a2f2c5f857fd063be738f6c33a3be0446ee4fa73955b7a7fa86478da92154ecf921385e91e9de31ccf3959e5543217a82b24bec6c54f2a15080236d43fae3d63200d2fcb32b65cd70ee95876858b12d5cef697407384ab942c089cc4bffa92d781d1c17ad26720d3c727917e1ea89bff03948e882795e7f9ec5320745958471fe677cceca10c222fe22b96a06a82160260ad29124cd2047c72036a5a42eb80b549c9fe859f4bd6162d3db02b001b5c013cd5033dc82c47e3fe8faff99680d20bb03c69494441b6cbc2bfb700dd57d1b880fe2e93783048926e5379dfc0a7338e9cba79c995aef0b277996f656688769147b14f0ac6b71310ad42786b54f2b561781b0478f8e29baa5c4103a8c4b8910faa84ac43aa233aa14f18c7e5869ca77742a720380a1175129bd1f3f169b835b62f42c2aa5f7f143b17929b792c1336596f9587ac53a63a4f1b726bbe86490a13bf0771efe4e63f81b4cf0220ce9884c4bc9ead9a591f0761c87d2d3107914b1a3aa0f9bd3e9aec39f04385ae66590f6657bdf3b36c9c7d7c41820cdf13a05b4578834748e6806fb234f5b75bb4f51ba55d812600313d03594c1b35d5dde31ed6bd5d7f166929ea5a1c3204f6ac64c80a477cacb6f64a1d64ff2300408b73869689ac39f8d0853804f87e99c7ba3a2d7e1e9f0a80fdafe63baf808cffba266e750537b218e380d8bda0fd84bbdc9f84febda459b2c9d197ac6f1b4af2b66156d5468bd9f9c0c93711a61638da9078c12c57a625f0f834d2eae3e6ff1229f2ce1eef5c2459aef7830b6c2ba62db36f7cf8e25d56ddb8c575a9acc740bbecc2f96cccd530a793b191d04670de28f3a81052da25b7e5882fcd037337664eae6e07e0eecbb82774d60bfd5f4c0bd1c772cc82a2e01c24a8e2c65dadb8af3f84aeaaea0270589de088e405f4956bccf8a10317febf3570e4e9fd41b9a54f967aa030445a1b15458b7cd681a6ad7467f8d041c1a2573806a62f9a7f702f709fac236c5f281912850a7b78e40c866a2997029f0d42ef60444386c92a7a192d45c7600047eef4764a865d60e89cd6801723b0cde5ddadeb6db038d74647fa9312bc4065a47909592cb1e092eb8e3a08f3c63d4620a62489d908c0e362f10e3e8df844522089b51546bf32e6543074bb5f247e21ba631b15213acc13c086db654150bc0f90b89f3e9ed844cc74ba9faed215fbce5d714c411dc9fe12cb4c886de894b03d76b9dc3928c0c2cdc7f0f34a1c1cd12183be98395480244346169a0c32113d0421a39f7236d69733533ac5ede44f5f4530a0738680970c4d248f9de362ccd203c70290dc7f3cb37fa19062f7372de01ce955d575c85e5183d4935e483af2617574aac16baff1a247db14fd53c11241d6d745e10862b2db6a13b6fa6a57bea37ab39fb16f436467fb05044cb1aaaa5af75fe19c27857ca8c6387221bce1ce07c4f399fccfc925a18d851686feff548638906c351ae82b4f2355f2eb125b73fd162fecc0d0dca0daceb8a01e39c2237f4638043fcc63e02ea79281258fd6df3b38949afd011976a40a9430de8253b903ce4f8b3c1b456d749bc15ca1d0be60c480af91a1d039e2127b0fb10817241516cc8df6e5cf6e1a103ae4953ce38edd100bc475471ec85329b42e90fa0203e13deccfe1d0446cfaef0b2993f1cc2cd843adc879602ae4d5a4ccf8665abf02358df1d0fda6fbf5993008c44b577b5e94d8d34a60500a1b4213c7bd0ec486e86491df0a0deb5419c967b89626d31c4c926ba92f6b89fd1fcdd1367e25cf3d75e00098bd1c9fede14c4384377c5ea685f00343aeff115c4fbd6422e7df131d032bc03cb8f498016e6c13aa81cda7a88d4d714ca2bbd4988d4bf63bae4b2357cfaa7cba8aeb714916d8c7caa87826d05d24650df491cd48f30a546e4f886db2b9e26175435c92d269ae6d271ace372cb701d747f27faff394bacf9cd987267ad7dba2d557e72d4552914d750410cc775fc8f376f7d7039818f5ddced90d87b3ac61973b42d1b4f79baa6041c7b034227fcc6a18c7c1cca22b6ef286344d15bf40e522fa7d89d59a88891db1f24cede3f3621dde8ef30c3577f72c1492458353a0832e3bb60e968d11dc8436f6ba42f230504dd65aab41c2d43ca804f2b9967e57403b602f443805f4132f8cd9c1bc1fbc7b081230694c1b92cfbcf47d458d2d04d8c2bfd447a506522d02e26fdf7a8fff36ce33b574a7c60f818a03f36fa4caa082c812b6dbfe769310ad4a935bcd3da6e16cbcb0062d3020ec0f3332a77b5f26bc8d299c54d41b829f12e0c2c662e159dd23d79063046b8b7851451ecdaa16a5bd1ce96f068581066d0840ecc687c1b09745add195f5e7d9635a920051a521431825591fbab733182bbc192013617d75cd08ce06065146fe6e7708fa0697d1323b92b7a7ae452e56de8ffccb464d1931b258c4bb55c45736097c0620e5cb89f293d6627224cc75f57c3e23a4b0a43982ff0f274efab6936409fde7d9694dc12c6f3a129c042ac90506eb9b7f377101e8ddf1689c7231a39bd2098af991c9e924b8be14c8b2d1276adcabaa058382d775f814e480a43fdd847465e5a03ffe0663a143689585917baff47fe3cb8e691ba67d7d357e6ad91bfaf7a4d27426a7287f3d2433106c44712f7bc7e59cc7bf9bc9c4073e0b72708e55a512503485493e8bd2d8bc459564fd5adde647515d752d961441c2d804b451ecd96cf87a5703bb55f05be42539f2c778c08ca2090ea1a05f72c78310b4df46d07c823d510981dc2955889a21bbe3c0000e4ff76f08da6d84cce12403be75c3430868b042de31de66ae65e3a22e56a54060194918bbcbfb9a6b7f637c2b982f1221ab1ba2439acf6bbec9d5872cc5d80bdb412fb71333abac2acfa086d9792b28fa0d4e4570135160aff11f0b24681ecd710a5c24b20e76e1c55256c6b89ee5f298c43af027c890533b132855bc6317e647b30a3a8f803b74a21e890f1c4cc332443aadb0f2507f0593c3e243c7feeeb55e802aedbcdadda8d4da8105e7f848d042ea6182a162373adb886974218e0b54681aa2d4b1f148d79933dc31e68e43c26ecda1eaf01ab9626db462e84c847446615b437c7ac5b05c8a82c6949244d2a965550bc16ed726460a4348c6c92e212696ba86e0c2ee95543bc521f0ce2c4f931540ce74d4e5ce7593c504f6db9cd84cb98adb1a21a0ced2c6b029f13bc1826278cf321f7500bcdc5baca189654c0646e29cca24c91c8e60af9333de031518e7426276ed6e3c72baefa2523a66d232641f8692086425131449974607f085b91b98d7a710e355aa832cbe1a186e82182108d5983d7a9c301c844e6f9b658a6602cfc115418471ee37543ee8aa498897748c5c32e02b07f3da6dbe274863d12871a77d664910148dfb3b57f8338884822def359030e671f70e159d1e91349871a69d1cf408f399fdcce2afa277c8e96b907e0e79f80aeb7dd12bab8d8d168dacd21d4600feacee0ce48522682d8eea18b59e8f2e75af4ec7736831a5b30564cf5564fafd8d832e335d68167328e47d98be851c2798c7c43fb773b2785cee4ec1208b95d9ec6508eeb5db4ff79e8ef34009e43a707ccd2bded277154d02339fff87d0df17704feb8b54fad160504e3d1e7e7a406283ff2785f109bf4cf244a397c883813f37968915d6f4a42fac0925149eb3260893bc59b8f6029d3729a681a2c992045abbce6dbd4c1e8ed47656bba849dd4f104c30134277175b470a2d8da1c06a3006b464bb266183b14a8ba73adab39bed0e9881d6a72302209ed1320944dc241e429a98683e50c437485ad27515d2a9c2063417b9fb1b18a9a4838f1cb1becb112e2f79eef63eb53782908549c0b3f809af000d045040439e09ca60a8fbc83c30488f90bfeddd47369a299c6c3c034d3eafb64c36f2ae29120a976308c8069bca308bbb95164d513c0fd1230569e252a162bc0988c53cf84b536c9e7fb358dcfd1ec15b51aadee80e7c2aaf9f3584ecc873bf76921c43f82ee88aad635d3b9ff5269b45b32a714e31ab8354e917eb2687c3cabb90796a6fc950a19219749a0aeb739067d764badcaa43c6d69999cddc3686de35e4d445adc3a4c63c7b0cca56c01426c86a4f4d6649a580652f26fc02465e0a2f48a53a2bd25a4ad58b5eb4d0b8ae49cc9c20981b3be81763f09e9a56e325b7eda3f74f2c03d7914a06747310313855c90ed5dd243bcb2d75a34c496a04035ea96e0365acb8408aac5b6bf219b274c8f1a8802240c46e89d4eb3ddcfc502444bf4412701524fc2b854d97db9192360f0126c5233c194d0861bccccb33aa999d7179e3113b2b2f3a0a1f2125d1f533234e0c1da6e23705e7d433c408e43b482412f83e21bca79bb48dcd87e88b00ab89ed949e9a8cc2764f3f117d1ae42ccedf3593c3574a80ebe9b20a6c52da37290a3c46d1ba6ac7a1a568b126527ff33ff1cc4d7001a0ffdadb7a1351f401bf2f703f172002831cb82d00986a0fab290da8b60ea7efcfe2c0c474ea0e7d918c671350870ac77e063026bd27d8e23a6feb3d85df653e366d9ef9bb9a232eea7a134d7c1ec8add1b42bd5ea3fa4c0eb013cb384cd292ecdc7e1f80af0548273691cba8142f6e07b07ca1a8e8a15c75a36f292c65452cb0abaf11c914da57eefe65b8710289ae406946944b5955381d466fb18a5df2c85862e3d7d232c0c726caf10be6fc999358a441a585a53f4cbbe891910018f2af08b3c2497720aaf4e77ff2c90276e48f00a6a068da66385d835b3a2dd3e17cb61f67d477ceee308d2c64b8bdc1926f24d56186d4e54ca374fdb2ae83c8d617f264700535ff7b9c7c87bd8682392c553382af56914c3b109cf87e6f402a7e18c6535d798300f0eeb4381d99c3cd39b42e70216f538a44cea3c54c074e0a4c16758ac7c29048b5877ca94a51b16a201b566a3598a23e471c02d41090eab5c5dfe136e7965a79cc94cb541e0991c5cd6ec5dc5348277acf0b550f22a15e5bbe89bd5a23ac822a59ecc6b58fc875664ecc6799e7f30a2bf7dca98496d06a6949465dfd61593ae69902d749f2f2eaf61cf7ec940d4ec9f5f7d109ec11e198e66e5af669b1a8545f9b713ae3b192bbe7d265aa23c6201e000ad6f611a55c85549e70a655a092ec4cc096ec25752305439af53c46a500f59c3af79fe6085ac0425d9c50468e593013f4f66c321cf2b44d0647c38faca0372bf2f9623bc23db74e0fd5389be476c3aca2273a241930b85a13d9193336e306d0ce107d5ca9efe577acda71cf579a82bea38cdec4245cb2d1eec227092285bf5294f0ac5d8f9da2ca50c2374e98e28ba8129879520b074375dbef9076bff63f808e406cd1ae3aca0c35e5423f540e7e1e273dd37a8a97fd13b140a75bc0d944771e3d59210920b1ff2c0e6e455944e37f169388c60ce2c8c504fd8a96e5878bda594ff79f953bf0382cf833aeb584695300b1467e58a9230cfee72ec05529f4e5a9e7c1ed3c98498f6c5851dbc2934c1378b6e4cdb311f47d55e0a8bdf2f1b0d34aa911302d6217e25932eaa37f47fbcabbd8845642ba622e7ff40a78c8da56562a26ebd859989fb8b9754cf62d7413b76743fe9e1091a94584e9eb13abd788e024853621a2e6bc3621b14d7c3fa85d7f9262d9ebf4b5b760b140a75e8375485855b6aa44ce28f21b19528851329773f6729264e0baad321c1f8a4aa31a5a0ee19786323a3010bc6b671c8b62a826950c9bb1bbaf20c95d6ac1be01c54feafb0cb75a0e24e6a5f8deb2f4a7ec92e8e9a0d5ce65019fa46c5223405ec4923c4824f7105daa145229fa500a1adec9fdf3a49e684b413968d052e290ec8c7ada892cc57510cef535aa9c1ccf08cb8f11ee749ed3c502a17371cb9a08f73eba2d13f47cd494c807984a362d7a1f79b73985cf8cea3a5b8219bdb30f709279aea1ddbbaa6c1d01c691f9b2936a81bdbe135da2bd49187a38d40424f182f28fc3584ad705b4c3ebf0326ab2b2b36c39c4cb65067a59b6bd41ba541261d02e044fae35bef8fa55e09eac6ee4751472a3bcf82c36349d9fbb49b95805fa3f440f25e530f4e3dccd2e5694de53fe40255143ca537e38dd88c84c6c02d53c4801c7108f6eddd06a03ab1d42920fc8030c76a892e58023727c74bcb157d42cb95acd8a2d5687798abc149a88822fea899d4fe16ce48857433442a49efa5934eb304565490b0f743fb892ca7582db987fb2d7617bfd8683be6ffd69561ebb46444073c3110e320395025c9fc5fd096852883c02ae466067c53bac458976758b91cb69fc4095dd2f5d419df9387e0880fad33d7685ebfcd659244f438900432498d34ec4cd209d2551582422f9ba7f353fb7a542742b127a084ebc0a1cbf93f9f9d60cd8c474fe82948b6dbb5ac20b80964b8b8aa81ce72223849e796aa5904f71a1e8002a326c441921608f318970570373992edfb55064c36e979c1dc9e8704403f7e8628a8eb28a80efcd43c315ccaefcc42708d33f81076673da7f75a7e958daf68687fb823ecd34603af688daebffc8950ec55acb42e71e2cd71f9700444e5ef4f8fdcd4bd1fcd5cec2f8880ad7b28e380fba61ba052654dac8f24c00e854dc5984e1b5a849d7dac8fbb16e76afa8a1a315b9432feaac4583b4ca3a1adc03bd8a936f6254f3be40b96a8a67615da88880c1dcc6fa224a2f79f05bc84d1ecb323925f534cc342e54c18c83204f37a732c71aa1b300e82fc10f82d9e72dfce5ade38f0f305bef25dd74c6e1c5209a1ade1f5bac06cba047437abb087237691f956a6e3ba78cc7801e79c980ec06623a939a74f5a56ea6fd9b2b9729a8bfae9f9f588418b49cf288063e78a2f0a9efa120989f86380d16c0783954b677e4c975e26a79859de1d5906612e4d1db42afb1fa0cdb7bd256fc014ea6caf9b4eccd1c226c517ef9db55905a5901df8aca47316396ef26f2c9badd4d00ba545c54ef54e12833798681ee1c2a89b097d13c0323cf42d935b46787e7f04d0b54531dd899f7c243cb0debc97cdfdcf5042de9cf051a59dc4ff7fbc65f68e1af182093a17db41ff75356c80fd1f27c550d021259ed8bfb761fdf1ff7ad0d305314788678dcff3c18eed8a04e857b209032f160180c2d4f2c70bae09e94878c12a96834f06ce20d2dbdc6d227f5a8874a42a6b32715cfc8442ab6d71a243127033042a67bc162218f502f5ab21093f6d9930cd4e707f21b566647a10ac0828efe627400dd942dba0e3eb32645ddc13ec58380885a95c604c49e4bf3a7e0783c840a953e7f62c342d0a93e8566cf1fa0fc36a2ca9ad23a4db6faac5fe9df6b87c0e5c3c9fa407f4eb5f997bee159faeee40aacde00e857f29a09ef8ad49fb6932d0ab00e3a24b9e17a8b85b40bcf3782c420bb4c19fbf21112b47d614dcdcb1ef7cc5dcd04041daf93fc8235a39e71eae80514bd98ce86a77a9f05615ba80c9bc7ca3c91410f15532070a0f9f30a80bec8b494b5d5306c52d3f7f1e2d6bebcbdfbbfeb5fb48b041b4e0370183ccb749b65092e84cbdc38e16ba46102642d39614302693d0033ea4acf83f5a4ac09ce01eb87fb316bad172529dcdd6ab7e8ae6be2a29a4db292c22b5ffda2dc8bea4005af1693913a6533f734dd5e3dd1c83f5c0366c77284ee4592ad8140694970faab341116239023fc7c6b0524ef83563d893d8bdf926538dc742386d3d64279522c4c904a247204edbb297c961a9d2a79b5932cdc69617bbdba5a341897bb4d6818145834f4327441ff75d2ed6a85a7d1a269cfc3e2e3099fb24c4a0f7ffc7827a63352c435eee9daa2387d9c45389874968ab84429daea1ec982d2bdabe91e3bbdad42b6160ad51aa54c1c8a1d604b63771b36b42679c6d89440254aef07054da6e165a25a2c065c476f5d4e9fd1452ddc45cae3663812dc55e0843c461d086b40e8caa3155dabcadf5da9ad02d4d8935cd8a6df5f858d1c96f3018efdd6aa00a4b9fbe0b644bac9e72d888087ba78f5518d709fd36522ec1f6922480143e3fcd68c2d3b69e462eeaed11044fc58a8ee69f9bdadcf273fe8a61f5da19c0b76620f4e4d54cbd11a5b485d6f332a4fae0b49ea732b7b3cfb86e545ac0b7d5c348ad8fe3d218f5e9d3b4601a5aab55872e11d61b926f92fb93e3a74d1c2e734465263437e0abab23177e6c47c3243a22190233ef538e19589114135409d2aab662315d24818367a05c9ec10aa98c615fe3145fd0a58733a9e4d52c8e47214529e2d40af7605ac47175b6ead48cb4b57e5c2d6c9e60bb7659c0c61984f656f3250b07600c666e1aebcc6fcbea44eb69efb27949901263bb5e35e2b8f62925427084dd919e2e19a04b052d9c9945804e08163ea975867779a3232fd632bfd9fd388dd145a2d026a02739c0d7a3386e233accca2c55ac0b2e0d70a8fb2df273b6e9521c8cc40961bfd51ee16ab9688f5ca7d09dd5fc9331e1b1e5b4cf419d3fd99eb0f9a848d78e1585c5f7e8ccfb10442fe1899475b6ec36574d00ce63c1d56c4db545d55d717be8392853245a3667096555a515e08ff7ed4482c7bed76f57b7c9b0cb1a377d87d75d9deabcd2f163ee02e0f3f2ccefa1b1b18ded8feba61ee95d8207a470dd0602d73c875aba9e25d3d4810a01a458cf4231749f710fbf4cd31f61d118431a7c2df347b2b852fce13fae3777cd326334188905da6ecd93d3786af515e2ce1c7aceb95601d0fc598472fc23cb1bd1e8a28d2c52708ed680cd6c4570786780a82ad7053f70dcf9ce27aaf636a43a2b50b827cb592d4ca4d1a2f52f795cbb14fd55d628c7364b909a5d2bf762fc159b47e99a9ba5ecd7a8a60439918f4007c15fffc2f4276604ef96ce7e9ba331a61de275e672cd15bb8c886443afec7622cd88fa1762f1d16c9201d926391ad7d66073f058074b3cccf756afe83a085b85e624c7754c3716434d4e3c95f702870f49aa3bf79f961a57fea6a12c7c891d7e155887b79908b67e88189aceb4b270e7610b54aaaafe0fc8c245eebc77b03072f13142d1e80518acc2f4363ea9d6b64c5f24add9e5b4ed2806e17c5aac3dd81f53ff57aa4e5941943298deafff489d2e0411fef34f432a526cc0ca27fe146beb4cd9943d4ce2bd661f7555a6ddfd80d651b35ff33289a6a5e72c9ff2d4773da196721f893111a73c9854c6ee17d8c87e3dd4b44894858512005b6f95769c3df0e4f56d3ec1b119796ae48649ab2666eadca4b46f22c4a700e08b33639c963d28802b64370e429452a2c8e902321705bca24098cab9e34922f2c73e45168989867004017e31c2562c03e90bcdbd2b6ff6c256729c151c397921261bf51aa91dbffa7655ebed99b58b3fa0202a70b587cf6b1194859b587ceccb987782936fa674db0185951bef812ae6f897b823f56ab71bdef2cf07b52c83530091f10d01d29e195fc40230f900a6023122b1c950868a0e47461dcbe4440b148d43de31d364e4600c20d36b0cbd748bc538bb6a468bce4e5e5c2aa718f92296846e803a27d13754ba6a549a2aeb05252df0c142005da0b17a1521038ee361d7cc73e20f87928b4edcab0e339eac54473d522b2fbdf4684f5526bcaf5f26f22644bc9b1a5dc7d24bbed24bbc9274250da0dffbb102afeff1f6126aa41dc3142a15d5a557beca8856b53a91d29230a100acb090ea4065cd4e06b70430d36a0010d68e0001a20a0e2eec469d142c471dcbf376789b4ff354b248dd27414b178c27ba4f25da8976737953378330316cc808b19e01948f9c3057fac718e0806be0e3f7f7771c7692ed3fc47113feef0830e3fcef891851f5cfce840062670971c8b2bd53f9d6aa61fe9a45da33e55104b6ee824874842259de31a27a75da30e7f5b6e76533258f531833ef4e8a3893e6c1fda1b16b8cfc0d7232d654caaae51cbf7384eee68190d92a6d28e34ed60ef5a0dd2d7837b67dbd05aa9e05b20692ad14d7da4896eea437ab2b1cdd5f5b11d6f135fa0a5e1f3d166c58799994bf221ba4fcac790fbe443db3dea70277ba4d97b64bc0737f788e27b0c197ffc1203371e8335ee33969363606616032eee3e2b68bf4ec600003070e33ecaadc7d64cc140097787814cbdc08c17e81734719fa1a5a00b36e0822d5cd07247a15a9cb75372b600052d08a30540b48089fbec66e0159a9e9de551d3cf29d9e3a6036e8a70f3f9bca3979a0fe2dca558c0011614b15940030b06a0471c7aa071fff74c9c3ccd7fef3d4e9e662c63d3a892f3f56061057fac408f158c9921fe6274054756e0810ad850c118f789e28a320d7d54929327f95bf6930235526053a0e5e1461e378f13f090001e3ce0c1040f137cbaf455c959d459f163f5d297056d953f56bcb50b2e486deda51783a5595f8f2efa594872cabc308b9ce22867a0ad974a17f622b3a59ba6e4ec2c48436d4d7326ef956d479aee8879f28f956e196f77f8b8fb1d2314b42151c0030a48eefe76dcf1efd951666a1bca8c3d3b4477fbd9d1e4046ffc046cdce70998f0d4098698600226f8c1044d7c96b8ef2e69ce40b104af12e8d041822148b084044146f082115431822a75bca08e28eae0a2b3d539f975de7aa42225cb94731d2411fce1b3252444d433bf7389000d154116116ce033efd1254f33042bb801820b022774b4800e29e820820e1fe8d0a1438439c298439cc3670ea731cd9dee08d2ad479ffcaf97cdb1bfdbc528d4ea0ae93ddb5646b74bbb0d45344729bb33b0d2cff5a94a9ee6b3e4cb7af9edb6b9d37766fc81283e60c4079cb8fb7c010cf73751ff6dfdefdddf41dbd003683cc091ee782d951e48e2b33e973675b439b3f16dc3b581616a1a4b75008d0e8ceeb347cebfb86acd494d3f9d1dec5d150782e000b88121362024471f727821c7147210c941003958d0c01b1a8069a089064e19e04006c064e00806e4d0f9577e259cce1159da749b284ea7a4534d5309494b2a889328eef7e8b2796f2aeba5f8feebda57fe90d351e2a9de7ab6e2f08ea6bbb5a50fa39d936f6397aef7f3d6ffbdec27ffdbb1bf26fdca1f840119d8bc719f27ca46c546e7027b5ce08b0bc82ec04dcd65fd5dc6401718c1027358600d0b1459000a575f58380d93b34bafbcaecd2f568006eebe8342b59ec8308fa6dd63a900100a5060e75c1c93f552cddd2b145061027568d052cf0582f841fcc5c2106f3a012812c843024c4840058338d4c411441c49d69060cd02d66c6ba2709c04c1ff4a4313c7d94ba5e9eb7637b6e4d4e1d865db5d2b7be4e79e12a7290f0a45c5994b6a6dbf1649ce3de24cb5f554735fbab525498e93a8fd1bdfd9a51a0e06c0d1031ca437d8bcf1c31b436ef8e1461b93738d7ad3d4a4a3c4c810a764d3f4964051a412ef2a473cebe8ee463ca3aed3a59e4afea540339c5d5cc7d7a2ac7fdd783798f8d4b30d366d9c996d84a9df8696ba6a43aed8a0809e7d910c2dd6d2f4300bcebe0a1ba835d678638dbc860a6abca1c6125f74addcda47253fdb52a69b946ba552e7f8a8a47dd6ecaa915293023563a811424d14351d7889a4abdd665f05856a715c4949dddd7bde67bc6991de12efc9e9d91771126fa949b32fca6fbd4c3f561a63bad04deb16d9e5d3f4dbd265cb4da521e651b6d288e29e061134d6486d6aa1116682b2a231c54aca4263883ca3cdd5bf774afefeaf75c619972922f9baf60c999f3184576748efcca896f69861c694b9393304e0ba68db11b70ef669faedfcc6e3974da45dadbfc559eeee6f78dbfbc2ddb51d98c74de7a02d876051fe70eb31efcfdfb9babdd14c0617646821a383084020025cdc27486176fcf2a76d5d525bd4bf429cbd19f830ab47b0bbf837856daf6bb5fdb6c65f2c023a69a8c45b62af28e398fcdf36bf7ea7f9d2ac30061d630431c6149f5bf6b0575d919e4a940fda2ff6ed8c6392a39b566e6a4e6fdcc45b5edad11c7299e66d5d9952314c0076927277e4e4a5339082dd7d56131d25a31866ec46923a86af1861c4e0de93623471c722c69030c208e3ee9562704645d9d930be30a68441c4dd1d4d1da5d85f92fcb0a049e3180b1a3268acb897d090c068533299aaddee17e12d4dd56e261349ea16d04abeae05e30c18a2fbc679080c1218f87ec106afbe18e3eea1f551c92f3ecf5af9228a7bfd2f8638965eb4716df2228dbb1761bc88e2ae517b41c4dd939cb9c3ddffbd8b71eb8c1af77a26ccde673a1f155e89388bd56eb9daadcbbada1d087c01012c20c04120c904411b33a568d8059a2e74e8c2e43edf255573c430eac96b1f00c703c8b883d4545f6681e469560b9334c43d0f78e2ee332a72d107176cdc41ca05145c7071ff6d732ccb8abffda1a4526fe1664a2a7d54f25aaa7fb640620ba22d4c55ef67699187166db8cb921292507e2d645a28d122470b0038800c07c81cc913f982874da79d27f28539035fd7d60c669c9a3f197b3b4fbac74237fd1bc366d98ab2ff6bc1abaaffe0e751dce0b899299332f3f93433c5cd98662a0b3eb250e373cf5ca92cc6a4b298a273b2c082cdcc58d6c7428cfbc5789b40108b28ff7ad0c26c167f539076fa7bb0203293c9dad30010cc9d4fd32920487b50a85603805c71c615e0c59d150eb0a2b3a2481520a862892aa050f187fbe440fa594b7cf36bcac3490fcf8b37e53e7db1b51dd69a4ae9fa3ceed1937ffa3415312a60d0a47d3f9cdd1dca8465e4141a986288295653b8145f485184140490c248146da238f379e45adb963d274fb3a39c3c692a664e9ef0bbae9dc9f228cafa3746451d450e99109041e3f362cde527736200081870c68d18995b633065c4889cdffe8babf46c0c7fd2c47d1e454ece5c78de2b0c5802c51c505c008a1e7c7754f62c4e6acb3df1c513443cd1e4892563ea18c366cc6c4c0c633a70028d139c133f4e0869228d6b5348b5e962fb014d9c7f879a8493afc7ad472f239ec9cf39239edd2b7296380edb909ae8f8b2ae906a5b39799a2e2b7bd0c3fb61a28b9e26259af939e961fba0cb5efbe9cf9ea4f2c6a8c86a820626fa60e20c135a989895388ea4b32d55d2124e2cd15a42b504142550a0c40426274fb38886204a0fcd9bc73dfb4f86672e907e0641da29212a31c5dd5d0922f95d92d2a12460b0f3bb5e0a0c96841acf2be3b5a69210899288e24948ef11479ca5b09068816b29637f2b889130e38ec4870411316a4c263161b670911e1633e4de650b1789b7ecc2650b1731ee2f4df58f50e39e3a42d685cb162e52d38eca23a21c31c4ddb736624d12a92dc71911c69d869f8dd0e2d2080fae0dab1a2f020ce7d122a67454ee4b3b0a93f816e14ec4993b4a0f13f1799e720d8c999dff67242929284d128c0866c80f6c7e00e3e48715c62af5b6da0719f86086e34a3317a944f2819ba61998e9fb10c57d20e26db40288f1a939ed615a00d10b90441680480f6e8ad4a01e2af0ca5241a11dd5131ef0d078a88207301a0f3bf0008396d17068882434eb1b99d364daa1c90e426678ccc8cc7cb4999312c8889031d162297822e625464483b1a1c14477e794e4916322a140912514cac31b57e9678e5a98ecf9f6ebc81cf53df2207deda21a83336cb2b0198c738c0d188d18eb48726e8893279410b7a3d0f613fb47bf40b3d1f4121e4412a2f25f19b4b1f1cb6bd7c892131c3d6d6797d2d8a4337a6754dedc052cef642379852f2ff822c517f18b00be0cd1c435e2166d108fe00de028b0156ce286627f25b7e28256f2881c0a427ddbc6ba3bd3fb5ffbb50447ef33ed663735bbf4705b64b59d7d61903b71f2bf967c615bbd394efae8675dd92a583fb4db5ef93cf28af6cbb93cdc9d2b42c881508a50873a8401d0c0158010702f713a12ca8e8e92a1eefe087a976657d07b2792d4d7f2703a252543f2880c9247248f38ca3d8a32e312a7239f4892e4f4bcf7431c8442b562f816dd51d4a6084c11931a7861819729bc78f1628297c9edd75b7ef02fe6e417d18d4255ebc3490f93e4ecbee28e244325f254da7f853892e4662e89df75df74ad4de3d222f1f9abddbc6dcbfe7e7c6c7647d35691a6fb137d8220adf75fb1bf9fa5f60d7d49fcbb6f887b7da571ac5fa2bb6baf29547b79a0478f8d53d17a66dc7a9ad7c543bbadf7443b215d1569daf23c709fdfc6a9bc7fe6c1bc16f759bf05774db7a4329c5d7c533b3b9d9d6d8b42cdb60de9ca82b4a786f11a561edf609fc5fcb504efd6b8ef4e4cec6fa7c589b8d63599f5377eb9dc60d7197797a85d51e81b77ca66d232f4a353521ae5eee8bad79c199ff4e3c4c971ee3eb5dd5b1dbe95b91bd78df566bcb74fd36f1ba265bfd2c18dbb7fa5a10e6a7430e3ee3ac85c071d485a97377ea5f6c0d77fbbb4f12e69ba88e9c2b97731818b1a9f568fe122725971f1c067cdd8f3686b8b085a3b3b20487b3e4dbf1c9ac841082d8727390869e3ee9cce8ff7c3382c252c242c783f1698c45be2fd58b8fa5870b83844c1c1c344f2dbf66a0943d3f2458b122d1bf8ac1777a6cf2f2a3598a5882c4258fe70ff906a1bdb72d6dd97178bc5a2baf2c6a7a4d6753a497a450aed0a0e5760b8b281bbffb8d64a23c7b5d6189f5c890b494552dfd7924586454563915006d113d170430d6e68e30628b41b1070c3e98610863a303466680f5d195a3294047bbf31ccba42dc91a411230f03312cc4353f0c675a2fdd277c42d54b4d9e0a871cbdf4c16e4efa1b5b11cb9394bb1b75c62794a7127a2344874fad337db04713a222b4c26acd8a87150e2b9c2037829008ca62a50656b8702adf45ada65fc6401f7c80b7acaaa28e0281967a7fb19c81a7193803abd451058c2a3b548152050054c8a052a9b4a870a0ca808accfc4b5119739c947272f96f4c8863a9522a10a6d031458cfbdc188f5f2475725fe212e96774d376cacf942152ea904201f7c99594c817a47452a000a500e88c06f404908fbb732525f5f459a4f2f3eb5a13f79b7e9b33ed4ee1cf057ec8f8b13f3a3e73f898f1c9d5d77d97fcd05ef189e22344ebf1a3e7fbe14017dd5a8ff36cc1737970e011929223d5450a875400a294a14521e33e7f6398a61f952f0cca23b285614eb2a9fe6fcc5d53fefb0ac74aa318d16cd843b3410c1bae706e43a1765a4f50282de23cd4492852b4e1849d3740706dc78c9da29d1314174069830028493428459eb0717fd045a5bcf4db24c995c477dd94c7c399acf799eb2a95177baa59d451f0d230ff90131a388180e6240acd89e884086a0d4aa35ca8610635645183026a58a2d500a409174d7498725e2cabd43913a12657df25f5f8baf634631804b1a773f61d7f63d826d20a627d718764b62d4ce27b923263e9c49513dafdf9927e46f58cde3de29bc73d0341da9a8120dd6fda56a4ddce6f8cc5442aeab0951d5d67f462d8cfa8ded695b72d3f0c8320ce349cf1a9d100c669f8dc7dae341ae40c6e7c863433702088b3dcf4733243139f4cde684cd84c26665c6312041326f35aabaa765bc266c90fda921f9d18e854a1b3e76b2c8aff45270cc4711c57afa6a34447889233ee3ea5122f9a121692c8e13edf4a3a0e6949a448c221a10249d08c8136f5986c689301b3684a9f20955883d4347f5a532cc5a54842f2e49aa7119cc6fc08d22dd2d4658b3475d9c265ca2c5f3b79719fb1d85f4b875ad95271cb7ba7f5c485411e17065d5becef8774855974531f531af7a999c45cd36722d1d6113747cce0bbad76444bea08be462ae0ee931af162c44829052534d3c39f5fa4ff75f2ebc650d2fb60e9c70da98c4f5d2ffd70de5f442d156938bbb4520c8aa37c17c948ce0672d2b8e9756d7d994394f3022757a9292dc9fa0952b5e40f9150d04a48fafc58b192ea913f3cb225b4922dd69520c9524da93ba41d9d25e3ebdad7b5328899325cfc21d632c8f115831b8fc10cbea918448fa149ec3d1852308871c99d73ad74225b1a0cdcdc74d3aac1d0c467c652a70583b6a0f6c299fc3563ed05cee78cc6b41792f8d4a5cf3824c9d9a52eb4b156bb30c6852c34b6f3a44850911634290229463ef1d99303496882144645db9da854b520d35ac8d2420d1a0b24d058f082052e73069e2e96a6017cb0821a2b3c405b01b642111526a042102aeca8b08200dc4c0e0469779af7c1936ce790c3150241da238fc81ce411c99940cb150909c9c929e1e40cb47283e3cf2d53550a69b4143e051c525081881d44c620e21141c1041a0a7368281881c2160d0519b41332a09dd0c309f404124c30433301029a099cbb5771cd04134ae8400940b84b234740a9b7fd31fcad51a7df4a9448941012953ccd12eb8541921047925f97e96b39cbf45a0fcb2041cab166ae6e4a1649883399ae903c4d79baf80a8b1bf16cbbd882b45e9264a1b84dbb1249ead32963a9edc5527326905a8ed36f33de3825f2c4490f7bb6b35b5b9af1937d2d163fb4adfb5f6ce75a1a8edab83b086e28ae8dc4582ae6b836e28a341d25a159d3d86848d53436ae69466853b6a5a146c49dc73512522484e9522490d0c4672ecc2281c86caf48f049451ba2461b22f3d9a5720ee1b4214d7c081137ee3ec21a6d046d04313e82d81a61c87d6a2324f139c2100f001cee3e33f6aece63d761d7a87750a8d6932732cc2382024468a285604708526821642d049f2e5bf6885d5472f2b4b98935005c400340199f3e2a799a20e0a1814001106220d4a08190c2076bb40f44ed03e92ee5b7370ad5e26672729fa6208bab97d31e1440f3c0a475a087d6811c5a074db40e469a103c34215a68428870774e9eb69ed59ad238a043e380097727c1350e10a071e0d238b041e3e088b60107b40d88e08888e41199a3451e915af6b3b017fbbb3315adb60100b42027d08268a105e1e25c498b3c2259d8bb56e764fa608f86a387866326f6f9351c1f9fba560d881b9f290d48151a90253420d535ea39b56bd49a6fcd5f9aef68ee447311b48eb306ce1a6ae0a871c749c3090ed47002529b3796ae70d41bded76e350afd3acc54f515af787cdee696ac97a250ae70cc3d408478d0d23d86dbd614e41e96f331f7d968831574fe6df1181394830b599cb92410277082746014c4e4dbdbbc71d038c30c9c328078808c08a4c11903470c202a18e19ce03acf6fdb4c916811df2b2c5126a6f6b3f2b3f4088a796411cd469e2944eff3604fcf8b423db15f89619e92dfd3f75f078642859d2cecb4544b87fe81a6c6db8262483fc671550c47973461969c1a6b10b4ff498ee3a493d211e9e481a4117944fe7b1b1429dabded079d9444bb491d48bb0d8a9ced07251224d2b4f598398e93538ea04b9a4aa2dd24a94f33f08ef9b42fed389086595ffcfa2cafdd14a4db25da0d8e2137db36e36cb10ba2ddd9c25c909c05c56dc1314cc917aa8a350bc3d167f655364bd79ad2fc884275646a53f758a4e95e0141da5365604693814efea1700ced832eda00cb0426ffa4233fdf91094cee9ce4125891a654ce8b4d2ab9351dbaaa7f79103da81da18bc4da1813c528116adb56422a16d10f96ed474a8a48a8c5da36d4c7020f3a9e0b7ce4614316d3a886211fa2fa15f7ec61420c56c0ca38e79f18880141da33d46406166b5a6f2492335370bb00d46406ad5d6832038b255f724a912e9fa9e9a6f5d3748aac7fc72ccaadbf829834354acb20df98f262fb71d8bb1b5fe9595922c9d720059293d35932729cdcb4c571736b0cc6a467b99289c47defe1f7b4a579bfc0d3fe5e16944fc4cf241a24b99dd6132efc6f7bf8b4478caf0cf3c839cb38fcf074adc48287eaa8a768f291738a9cdc4cce528e1669489272ee512c917c54215d752fb2704bd7ff95eca7e7e215ce9fc3c5abfab1fa5fa4934fd36ff5471e7678a00379b491c718799cc9238b3c92d0f210a3e57184bb886529069244224b3148698a41a2442c4d314892942893965db6e441f39022512512450129e1e1c2c935147c71f72eec2861552bfd3cfba20d07d7ecb0c056353b82f04da4ff6dfbb59659eff35647565187835a3e61a7057b57b42d1bf4c292774c4f32060241dad3834281502dc68242a150db76bf56fb6d56a49ba851280f7cad83eba8b78e1271c4f9b58976eb28f94e65ca3b28140ab5238aa9160a0583d454d23ca69ed03cd22b2e1dba3458af2dcad80b05e94e499a74968c54c68ac38caf0db7df3477dbb561c6deb5fbd258c53dae190ddad64bded95fd4d95dafada2ff3d190d1f665f19dbad71b86d2aa3a14fd8c92eb63ab0b0d382422d81d59dd24eebc996499318f738be10f6713471c7370e0fdc676bdab8fb6f0a4a8cc7fff279cd185f2386b05f73ed1a2270bc81830d1c625c5b38b4c021251caf8b73ec0d36eefec6129ef3f3d37a5dfbb5bba3f7c6e7daeec0be84d50d99e64694531b6fa6ab8d34b30d31a936b44879536cbca19ab261c6ddd9d0f8638388cf35eec0ab35e25843e677d4d6854197b84613f789576ab4d9f60387d410c2ddef98c52b9f9a17a8d9424d4ccd15351ca47182f9a1694ad1ee34ba48438bbbcf99cbf4ef71a2dd9c894ba591c4ddd1d823bf1eef48f3eb71f64574d3fa8934bfb66ad190cd740e1a44dc5de733e438038933729802ca13fe62120a14694389244d1ef83aff8724b4dfe95d72b6cf2099f187bbbb7e33c6980184bb7bae99b1823b87b7ac20deb58c31cae8412b8308673f0c71a7c16eac9f4732b0e0e21a1954c89035c42f895d3468ce6838bb34024958d722504ad366062a49c979b1c559a45eeabf8e8a3a0d95343d5a1a20639c1903076d8c13c41881185e8821c6dd85248a9b331a72f23467607e116791861c87e28ae80eead1a2c538218c3bdc7dc4482651180a08a389735ac45b4b347ba0b9a247e7e41f421305cd0b683ed0c0b8c2b9c9f9e86fe7d11371ae5f673f0fe78709859d1630a23818448ab0d4be78f34519908efb8b6f6a4989a6c89bfa6248fb6288bb7bf1c60b365eef6b2fce54cae3c5e7ee45157777ca53553b321a5e1bea4d46c3edda4df61bdef5af756d2bfbadca2888b76d65af6534dcb6fc22fd6ab71dd2edda707b11efed5abcddf1da7093d170eba24ceee2eb22c97c180e1ff0e662d2ea016ca47c0018779ff582f87b40137fe3938b351f17613417a425a4d212494a6dc1c6dde7de628cfb1632ef6c91dc428b3a5c973e93e4901661a696fd48906e4f8b290e789372801af7300ed0e20069c68d9934939a0183bd9899e253e798f1c0bd278b2cb52cc2b867f169599ca06989542d1ddaf98cc39d7f5d4aa4f58358940141aa612152c182a4f5830df84003c8b8bb8cd66f80ea8a3793e2d7126351db2bc8f8d4207805d115292b5460451bd72779313559797a9615643ce3d00a2b7e8f1e27afcdd893f58be8d6559ca9e2ab8244051dee77d436d38cc5f05b549ca99552d1a2c27d72175b8e5a58993365a894c929e320c6e2cc75d22fe229ce80f89b4236a720798e499d31f6eac52e292620c5769fa58c39d2b6b297c214c51c5198e151acc8fc41c68ccf22acab7565ecc9a96ba631bc6517146a8ba4925a98e9c970d895b147260d03bedf746b060c71bf16f43cbce11757e9e759ece589a0b8e34128a4703fc16cf62ead77dcf01e69f758c49d9d27f5629e27fb59f5b57e508ff545bc772ebed86e5b7f0c839b8877cd34f6790341ebca3f74b1d57acb9807a41befa41e74d1fb5f0c57951de34e63523a61c6dd89cf0922bad5849a591347b8eceb6d62c8fd2b6e42ba37e1fbbe66828932eeee4dbc3d4abc352638cc8474778977de4b94bee2af385ce20525ec50c2082582945841536248c5a11289d23c3e5247be8b2b91f4b6f1ddc2ad9f35e57e97d4346fd9a366202c3f8c66597376f79e47efe8e18ac324aa48224c124490a800125e787d0e04e94a6a2b3d3b034ba68d74c70a6224c02001b4af0d75aadaac3731637c26a6062fd527a9f6b561052ddd5f8fa8e308315e0a65d68ef8dc9d86471c417277bd8ff0e0db4694c0dd6b0f16f95fab836dd96f5f3ef760d9f7f7c59d11548c40e1e7a7a5ff6b9df417d183af8aa0a10822ee2e2b116edc3d8d080710a125f657da4dc67e45c40cee6e2f0d65fe9d2dbfb855150ab5001a16408202ca50c057ede7adc730f6576251d64b53ef9a89f22fc62ce924534fe2fc5914e044012d0c51877b9214067a71882886b8610852ad29240fcbf9c3cc112601ee9e63b5528912f2116a6971d6daafb5a9aae8b56127d316a420768533ad411adaeeeb4a083c8448e342c87c0af1e3ee60be02e651f662cdbe8a6b1cfa8a83642fd6571c6eb2974e409a99806f2740babb6b41bc3185785ffa0d05b12647288830eed3d3d2490cc75a5f1043ee3e574124a914012140801a77af35c5e12f860016028e1ce00fbc451a63a150ad5a2907c3171f008c033c71009ffdfa894e9cd49a8af5d2fd40fce14044008825420b84101026770f5f1ba00c03fc60002aee735fba658ff7109ddcec8b441a63e1ab7f06060ff70fbe96175bd867d0454f1ef89a5a2b0b3795f9877490102886e0e2ee4576765a4f9e487cffe26d4645219bbec185106990ba0bb12326c2288c1761ca8cc280129593939323477cb1052d1e521551fd2ce9cad6a4b16c89b845f56bf0e5eb7a19ef975200e9e1cdc483f4bc1e99f14ac4ad6b7f563e193febaa7e563e3f2b9f9f95cfc536e37a318fd0c6abfd38782a212c4546838262187c9efd2ccdbaf46b6529cfb3f51854ef88893ea4ac9c05afae9da21f46df0a6ec57e563efa67e5b31f871f7d7efc72ffcbc26305b7b2d0a55f4bebb772319038dc7dc7473f14c0dd7f68f34319eefe1204e9f3d31aba424424d423759e3edb82228bf51bc3463edce145f66b59412c1b90c4146e7cc0800f66dc5f909b4a1d7b8a0304032737c907381d903e864a0823c36275159c0dba18130512fb3eab0711782862c4830e5dd14f5390c5f9ce1329d22079ed8b86569a34f54a2d2121a2d917cb425f37b2f02a7ca27b85350333fdb994a83e0c07dd2b9776140b5ee1915e6214dbee2e379d7d512c8abb974cb32f2205e962dbbfe95ae9b5d80bdef0eb330eb72de370ab17bbb47e70cb785bd94c360832d26bbc3217b9043b53116f8db1b86d1cb83b079e3384853ebe88220d5f70c719417ce3b26f218810bc47a20c328015dc83a8104400ee4152700f42c43d080aee414e700f62828f309a113653827b905110214148700f32c43dc808ee4102e0235c47584b1011dc838410240536ba6de83caf98b7797721fdec39ee5ec6e88e10040038110802827b900fdc8378104448284389a4f35c22dbc0301215a483204246452570f7d179eac05028144af4919736746012ef1767590c3b2d958243408122f3d805a152221561d9436993264d92a10769da66ae6d9b48f67dd650a7ad4f0a688889423d4b826327533ed2e6fc307cedeb5d31fac5f6cfaee44cc3fc9bc626d5535b18d5b25e17a6788718a43bbb689e9f0dff136d2829f715f7c47ec56dd156d78c6352df940dfbb3c8f936effd5d386e8b7c2ff6f7c16d250a9571b7895aa2a4feaecb8f8f500f0ab581e0c7b674d90256fa1f3de197c6babe05aba4aa2b339efa43a98d577895c2abfa3b8cba5871f72236ec4b610f3e11b7ed7f7d1971a18117a9344c2533c9495fccc572f9f1595fbe883b2daf65750fdb8ae8c78ae867b9a2c61603b87b9159def4cc072ed688e1051b3914e93cebfda28eba463910993afb78518618568c70c0e1f507205c7cb190bca9fab987055256fd8db15cd9783524a341b3becffcd7189497869e87418c7be6499eb6a6de7faf6be56b1d8e582668e9be2f75b65fb2c69ff1f72e0f4f1dfbfb5666a5202d91640c4fe9e8fdc93be777a9303075892439ce7b5157a62f4941ebb18086543263298663952b211615a9f5144e4ebc414a24e7b6a4fab32d86cfc993134ed32cadada9154e9e246a7f18c3f63f3b036734367b571639f5136048b0f70f506ae75c6db99f22eabaa3bc92165169faec519dfff5fbbe47595fac2527eeee1539b52c9162d8cae3d5a7e914bcaa8f7796bf7895f14ad73b02bdeec6abfdab2a8a5762d80a12578f4a8a9095036c514186229c04d11f0e0a1bf8e1c08f047ecef8a0e23225aa088fca8a44a94821fc08d1ea6806da98d0702589868370e8137633c0ce41ca0e5d94d9c6f0d2002046482132043eecad88b805f4c6258a488888e84716295204080ca02f46406380c478fe0d8944d547a237d33602022514285080a400e96c5b7f0b3bd94f113f3b8c7ef00f15f7d206d2dcaa5febc8e7012a8c7c4c40d552f15e8961104c01197284fbf551cf0f3d5b7aa6f8f774e0eea88de78c11cf14231e1d463c59dc2ff6d1295c4756b575648d526ea4c8b8c475d474c375c475d4a914dc61ee3e2bae236bdbafeb7dbde13aea6d739c276c984237add71260c9122556cff4088a1c3abb463b0770f700f86867dcf9d18e158992a64da274cf17d1160995a40639dcb15411c2894ad74aafe7e10dc4f9b76ddb9a7a783f6cd4dbb68114572740fc88112aeb3c434d631df52eaea18cbb447161c302e29e867b00dcb87584a00798291ea43103306548225c1b0124a044248a114479e195060c0e97115a308327c4c4c5cb05e2164d8e60f140140e7a464dd6709f1cb70110006cc0e9182dc161d46488cfd1920ddc5d0d8e1eee382b70c751813b4e0a2e752158e4084122244b8eb1e4d4ae51f3081163c5b1ebb0f4eaeb91056d83171499018ce7e18e8387071d0855ec8e73873b0e0a70ec70c7390108b8183121832f8dfdcaa760c25d0b5e8b858c11130fe68f5c522814ca1dc704ee382570770f70483002e1d321e30ea4482789ce13c91218922eeb116861ad8454ad9ed5152a9b9654d0e643b4219958f01048f3c7f6b639d36b254b0655d5fd22dc6a818621ee9981a238b2be8e3e510f167793bb91d154010dffeb344e1d227097784b3db5bc98e63125330692a0ab28e3584c8ffabe7e8d3f1ce4d4a348e5587116a5112334f63ca2cc860fe90a4868647ae2ddc5de6d26200eb2429c8170abfa6c4a74df8a8c0669190df2b08c069172a42e9124122c758efe11da78559faee8a63eafebc2204fec57f38e32bf38759694aa8a44f2f011c924ffa620d55ac41aa478157b208c5b5795f14a4683ea67bcdd9d0ad723fe8b73fe196f88612bbfa98f27b447a18ab1941bc3b70ad1c5767baa0f69f73caa07ad9747d38f4599865f779f474ed045a768f7ec5a199ddcb5321a14c320c57a4641918cf97594e74a0fd1030d81f6eba153aa8b0f2018185109248e510b2a1842c1a805342c2ea31664b35a97cd398c5a68b23166e1b4dc3dc7472cbcf1b1c20211231686dc670180a0613400f0b9aafa2aff4594db2ee6f6bfac1713bfa8ebacced1f5c7fd7536c417770fe6af77ead71ec6794885258557b3af52f5ecabe0d54800307077ba717e323424e7078829050d8c52c0c0288533661d7dbd15fd87153adc00848f0ed058137004f0434c0a03b887364c6ebb98db18d42314ea98fbbe54348f348f7484c216231486f03be62d4dfaedc6f977c0dac26ccd5f3da86fa5a8c356f6b38a3a6c8575f7b3f6d7d1095046269c3132e14817fac1b182de6713cebf83b6316c05e316de57a5adfcd440421cee3e82c947230ca12102199dd190d4161f0540c73790ee8c836294a8aa645f2f4d8d20f8e1fe6047b72d7ed7d1d936dbf5846524c20f1ca3102ae0786fb5d26da379a434236132839219089084229981490d4d7428131d1afe992ca161493d9d4ea7fb2246a146218c42d8608fa11d27f8c38f11089f3b4e087040e09e44a45b8776ebd917cdbe681b81c0c47d480942b4f1128498c34b10c2045e82103070ff40c81611a02204eeee44343f30e0ee5e421f4508d0640f0fb8bb8bc04116da86483a6dc39107643492affb2d3715a513efabe34051010ab86a8b22d7810ea30eea965fececfe7002da6abba9a63a7734944e38190d61904f6449464318907c2181f63b89447ee1d658030e09b8e3a889c31dc78d35ee3870a859c38d37dc71d4a4e1863b0e1b6d78af1fa8f433a7eba285884600000000831000203020160c872332a9743ea8f61400015bb4ac5cc9902e50f328879041c61803020000000000002006946aa5257dd9110cb67cd7cce717e4a4eb884d14df0b7ba26e8eeeceebe6315f23b0e6d6a4a11d168e2bab9a29134cd092cbcf1e3002f291f3dc9852d04fc3beb8a46812e698a658921bc6e23be2e9bf2591f75017a3c745e77a0ef09b3d22d8678c287b4d6265db6630223073c7975dc16b94f018a2950fe3767beacdea2c5726c0f155030d54683eebe2465d45ab8358f000fc148814c897c9d364915d22f371bdbe3add365062d8ea9021186f08c3b2a2da920d5c50e72746fcd6305bb4aaa8bfde33e162c4c5ed391242f81b7709c55627052af96e07a65cd7cf30d35f7fe6deef91bf770d980b6f04d52036b6ae2677fffbaf69eb9b91eecb2f36c2e43dc7e10ccd4100d428e2800af2a867b747c29feb684e29603ce257dd5a727fa8dd422cdaffa31f1a76c0bee7a7c3cec08568b58e3c0cf835c823656ebe02ead5b674eb61e8b30670f50f7be9948b7cad969688522c7fd03a49645a188cf0904f6648879fc144b0c029600745137fe58718ce449e66e680b35f187bba4ef0a13131aafc7a8230752256fcca748ace63493e87076b0d1ea040720457561fb633156a71c7a37a0045337b11a0db11af894c93dbcb5b1aeac4f440430432645f9c70075e5abe02aec3a1b2ad415d3cb989a006974ba63b044bc1ae40f5bdfccc9366165ca29699eb0d00803a7984dcda32051bc8339858efc7ca0d164fbf92bcb60a6b5d4f43815d554a596b90e14eb25ca061b98cd36ed33253d1ab4662b9726eb0c7ebca6ff0fab14d666969ce530ba4e34a17f3aa3434be6007426f5e9753c38be7597280c4eb90aca5ac16605c1aa2ba1db8f3f84539a32c153fef0b3e65d7c2ab3b8c6801deeabed348ecddf86f52be9233c89cb683aca155ec686bc00f795ef249d9c78548363100d9155c36e8d7a05ba7bf8383888b1983b4857ba1ce595f4577646cd66dca0f34dcb125b1d0a38f9633b4b1b5a679473f93350f656d12464b7c30547185ff37664bae833f474614d60132c6854af0c3c33242cc8bcfc1835841437c9966494a5b52ca3597669dd3c6a1e67a81f2eb0c8c61e70b3f05fc4d4b15a9c529d6f991b4c888416790e1f6f4cad6c3ce823686064404ec26add0f743fc6aa14fff83883dc0b465df2271f0899aa648149445a25904ada12bc9aa8ff00a4e8ba76c60a6bb127a44eefcd8e6de5bdd3927bd7dc4d50b6d604bad5f25db8476d68c412d235631b45e6570eac406051403925bb4ff943e2fec48d418485861fe4b6f47d9c1e448036f9fe9b0b0251205d0f9b91962a6964401747e8e061cd3525a00a8bf988ebf4c7a48ff41e7a7d9cb552ab3a65c315de23598cc4b80267cc4a670ce057b919eb6726c2c576d93963fc7732938da684e97b1f169cb2b70b5d1024a020e7d6d5f8f8f338bb3171eb1954fa8f002b3eb6009466a19a0912d8dc055574ee5eb79db310c29ff14cb97405e8f3704d1891519494100bd22bf2b235d2eed268140f3949712dd97c64dc26e1fd8df744b0ae10430740a1c7143550f7b88f56dc7586a910cddeee4134a096de403ab68f7e0fee76ef90ee329367dc693a10228e145a92e62ee2c543071a014120244ca7cd221d9489bd4b6ae91ff12db8e0786f1e6ae4a67c7c4a49c2321220889ba94f43a1c92f1436e644d546ce80c5852d35c8cc7061e6eb67b5467c8aa22f0430078d72b0140fcdd553ba1d9c771b8f5e62697c8268a5f252000dd91ba1387fcc53b7a31d9ef18395c23490ee2c7439ebdba070e0bd2b224878a261c899ca175c4999e39164ab5985684ddecbb494d3c51dfd0ea01acdde945b6768d5d6d0019d59f23e96a776e9f2ff9e18920b960c4bb0558cc11fb90b1c5aba7f68272b5a3f601c182cd6678fc49d31f110fc405d6c461e216d7a1a35dfcb83de41fae864cc4fe3d1bec6bf660cdfdc56c86d5521d8be56ffab9b8bd4974144d236fa62c9be4eebcbb80cac1ecf2e1a488818ad43116b6e6ecc065bdb54404d73f125f93404bcfbe60fe876fdea728c6ea8a064ed0f8708065b31b5fda9a6ca4ce92b56d435be111a97f3f416a3706cb6e02658a8a20e397f62dbf993137081285dcf060decad16e56d7141d2da6a73e834181822139a11fe4573422af1181824296e24489f22e63a4ca386e5babae677ab97424709101642d7b9cdf6183b7a0abb1de894f9b566507520f5f98a18a17a2e86d62be61d9c9a422b69ecf6a7f58648b1881794c8f6aaeea55a2ebe1bb3872073500435c2fb154170dda18d59b08e4ec795f93bf99d579e91bd839950e76f7cc86fafa461fb0f1e82ad39fd77bcc05282f9c2941c27f9dbf6753e8e283ed3d6afa6656d4d092aed7b9ed4cbc1292244c2ac76fd1f7e8d4d37ede2bc0dd8228b631c27df5dfe3b2d6c1fe33ef1e5705ba09ebad3bbb736757d417435f129b580dbf51a758be997222aa37516d0d4f255a1f8b82e6f869195b775a72c74af260f4792ec487bc86e0e2ccd8819ee85cc12015a2ed437e7c8f08bdb68756c3fcfd9508573036858e764b1d14a271da69c2ed56612b1080e15e6da8abf203b36c11ea35ac9f71e50bed4786973eeef86daa9915e93611cc7f9b73605c4c3c3de052b1f5cabb2a9a720688cd914a98553438a41aa929230d7a166f6cdd0e55c29fc4a85b9063e03f0f5197b3ef43b7080c1074c7d7ebb82100e63adc4e308884c2c692697b1b7aeca32d90d4da61fc3374a084c065dd2da1fa6badceb7ea9ac998992357dd2991bc4b2ba84c84996d4114b3ec87e2d3330d39a31dfcc214a1af1b3f11fc21cd84ed97989ce9ebbebe059b873c20880eb7ded5de4e83eb3151f52503eb246b577718525e3815eee25c1ad35329a0d81f66962d05cf3cd6e2fb461a118aaf9f3d44c75d917c85380a0cdc5c8314a3025061237eacad6912f462cd11bcdf30872f53f5d2322e4d1491a9da1425c39d639289fe661720c7a42f64b1422b614235ce3af0a4cab114e618a009040bc8e0240c13d1e482e693402d119bf243883b15518baf6f285b3dc73f27a93f3a4785447d0779ca5718bade7c60fbc8f9ac89dd8fd951909b279cdba5e4899912886d0ee4aeec0b3ad22b7d2b16ebba0da0b02b8406df25cccc315ce569c3320ec5eaab55a1090ad8dd895c1d45271a1010601b29bb272c832d4c54424ad870729a1009f200c232923543a26cf8ed998a8802d35996c499263beacd3872045e4fadd88950fb50e5243fc5591067d4ca355f2ecd52f9d5e0f51021ffa343f14f1038e191535e4a1c0fb86040ebdd0a055695cdfd72ec8708ee3273454f5cd0740302891a91c5f5ad1a269e7f79e0793259be4e4ee26c2fd680ae06f2963e34c184ab889f9fa965cb1dda87e56718430cb1cc4bab8c7d48307fe95fbb54b5796815e29a380a6d1161cb818d525a2f787341b24ac8921cf8bc3ff99885d82dee108659dd12a15dbd024a28461e4206e4085b449ea2c7a603cd0ae9cd793264d43fe5397d30ae621fa6d3922d5402e5068d6ff004f68af37e98e530bcbb0af5a25a635305a52337936b4f9634077a3c2cc7dcbb8efd1111ced26811f236c210c3bc959c98b7bda09280c3b257e29c173eb3bd13dc6f457f2296d6fa720da0d4738e6bac697e319f039bae3398626334d30763311dc83eeb4e741354e51a3320cf269e5acffc1b07a1c3e6e1eb803d4c03d14568ea501a7cfcc561c85cba6cb553d76cabe87fd5ddb18600cb6aea0141ed0f5ddcd789f2a219388f8ef2ee74eb84548fc4496738827f1c4d97965c94c274c18c7320677eeb033dc75545de45b7b1e2690719722603e2e9f0d44a85eb5cb85dc150a1980f803986a34a5095ef58cc1556a38e942e065e5bca5f06de368600ac01893dcef2ad92c4bf491ce9d01197116a3c464e250feef0d6561e8cb97b4c18e91aee65dc6e3f66cec844da0b39a89ba4d48d0207029abeeb186754a1c8aed7fcff288be3794fa20c8f5d7330ee0f3159b6a5bfd549fcc01857976f8ea2889676c7f1d74ba496a1ba4047e4e79ec9d88cfa239c0bcc86ceefbabfde74658a7fc77fbc908bd03d108dcb7d89180861df6c05102e01ac4e5c55d71b885646501a317f1c7ddb04f31d4406985076518a126cc874a1063898880bd729a366e767d0673a9d0eeba3ec55e5a12c2696620026cc0c5f2a3dbdedea58d5ffd7ace0551978b9d7f135ad834bd851c884fdafee3e0f08a7848194a21be2f9ec00d13d64a0d755ec23b3641213167315cd11a3901462fa1e0a6a4c59815927a94e3be31dcd5b9a6445bc73c05b928a8c8cef7d3f423fe6d2ccd1931aa91c7b1e491acaa63803b284a81304c4721423325d183ba8e874b847c30dcf066b395682a18b0c950ceead2f649b244a9e257252f93b5a02f704dbef00684a10b89be20399c814e99639799be0b62a12e540533101d159c7610ca63adbe5960036f93332d210548121a0ef19914b4391dfe38453f502439dd516c1ebe5b37fca9b0c63a6a820dde9e62e11639bbc670d3bf2c81a19dec173eb44a0f34468bc28ad7fbd9b5998887d3678792173bcaeb7b1a2207c6589e4d786ebabab804dcd22e4e47fc769e6c95efa5aa5ed943f1d424774d1a9159d4a38e75175b126848b9d72e662d41f3bfc49fd99fb3d811ac3b2db31423063050bd0f2c86a132409d28c7ad9f632603a1fed18dbe4c322bd6c174a6d1cdbb7e9652ec6993841b36e97f2193b41f22436edad46399bcab336487fd77c8e8029d2554028ee7571828a24c63d6f159936e532b55428d89dc0ee029a98d096e3c81d99152808e6d799fde3fac1029834f12e6ccad405fd49787d22782ca27733eaaf4189674112b3a640b678d84c004e553f068d5543b485a68420aad2f1f69a457636f11088051d1136614faf08a5b8113951a58e56bb1529d241bf0591e726bb1c10370e675b98a78128e7596d3cda66966c1e5d12bfa4418f09ebdf44e4af08f9b4594f8684120a9c2a6d2dbd4b000e2fdb64ca0aa1d529ce77f4bc443c82a1e92e45331b3d3d158e314409c619ef167ca3f823b60958ae29cb2cd5696ef0c5fe8cfb3388cf681e2bf8db4c5fcef3028fa0849df1e020b5f5a8cf3e5e82744d5bef054b5114c8a7d52055fb9332f03ac6eea6e9163fe4e2b844d8a2408ca616adce62912fd7013771df56c7f32e722c8b1149fdd03ad7d4dfa7d83acc4ac08e355baa3f420a8cd83bb76781f23d556c2a74e7baef3f9f796eea4fcc09bfaf8b33a22f793ca472f41c0ff7229e1f4d08823f577bb6d0c0c740370cee9aa372184845709d559163c69c799f97844a0f6e8c72ff089bc9b0b696a62e14080f8fa5baeef33a23614a11e6119e76612dd2799c71f54902a621601cea91737ac40f43cf15849b2a1a40ad949bae85c4456d484ed97e8802ec53bb4843b940146e312b026c06168abb9f7439d52539e77bcb1cd50e273378989d017ef2d3090c2f37c823d0cd62f45463260bf87ef02c7d0ea9e780492c56bcd2d5004353cd8e6a87cfdbf179a41bd0c870cb6d656164b5c74940c5178bcd4d33951111a35444478293b58a5348f085ab4b7ea9bc658385605e37f4815472bb542629088deb6271afa70c0c8dcbd59e856953986f4ab7265062808155c3e11da392f09e3b542f4248f7e77cc9fd51e7ee212b3698394904f8d06808cdf2eb692edb88d34d82e85076418e26bf099b0fabd194eed6a984182fe38a65920fc6a89189a4326af30e0cf700ce9b1510ebbe67b35cdbec5d0264a0c3fefe1e516dc58d3437492578671c230aade06cbf8c400cdcd7686f9bd1902d91a84387524bc183aecfd1705f35783eeec2d361ff71ceb8c003a63622fc26c7cf69e81811e056d98bf43c66ae9d6faa7a2f825c40dc4ddd6dc7f81ae4ec04b8c77463a34854a0f0abf5b0b0aab76a0d365bccd86554a58ec043fec41cef11c0537eec42142502c532c54ed5c7a0823890969c9c500210b83c9c27c2d2258c971115a8277bfa01346e0c04493b98213e771326735ecd08a2b747f584de21fc8be0f136c0bdee29472c6f0ef3c5a7e4d545b45b8279e46bb498e5a7a6d43fa213a56133d2c1a42158e108b85b6ed160d8ea4fc01ee399cd19ff1e861a1d012ee67faa68a2335acaf5724804d1e99917577d6aa6a1324be54680964c69a4d6887e7f445cf84b81ba13a88b41d1c5807521ae9595cf1613710a7ba3355bdb63dd89c46d4ca3874a88bde0c4174321cf81d8c5b372f647413f02d17b909fe3c551307eebaa5c3fa7914ea0d05c5b9cdefd82cfcbe872855bbc47bbb89559a9f974b0fab9227b7792ba5541990a6d738924dc901a86357b0d8a811dfe865ab5c621f6b02961728fb81c2f97cd20ca47afd844b28bb8aa230f18e8fe45a4939736ed845527e3d4892f65651770a6ad5b8bd2482b422144ebf9c5233e7ec5737da09fac05803ff42b91305c0f3fb8accd3ae6a398817d11321865172817edb5f09d36efc5ed75a37bb4f99c28861f6465ff117ed8a725e2d23591ad1d35c3d3b0f7d98f247337b2e8db6ff9ac42b013e52ecfaf4377626871ff9c20e0010cf9c58ab03a955c7fc12fc4f5c6486892e11fa1fc5d11fc8120dfdebb2a9ff3c12fc175fa4efb7bf1431bbab101b28e58293a9dc6cfcbf5b2ffd0d8bb78c3a6d141300a64457060665ed6c5698d9d09469727980237baa8e18787ed5a41466e0f6618f156ec6186e498bb44564c0c10f25bb2f7060b37b3b8f3824a2ef6426c6864950e676de88347b8298c0dca9df7b472e583c518a62ba65cb7d64019d5c9ca45ac96a2c1ac1ca37be831df6b3ee5d59d177225d8a355cf91e072b29e8e079d7b662e194dc57a6c1abbb6715bb2481b6f2a4146fd1da467431bfb0d26b445ba4eb2b120ebdf9ff3eab7996af8e0a45ca7acac428e6ea46d8e2b476d2b424b53e60c219344e0c744dc68382fb76dd4bc5e475f1cf17f1b8b62f4be3dbde1c5c18d36ae4a0303243808db00280c4091742942d9a60c950a00465c1dfb7d80b042c7016338d0f3107a949529d19cfedf9618ef53e6b44b58c4a4d901f0c95bb6038d37fbfb29f91f8269f1a3be987e8e41ecd3249314e8dfbcae277111ed6345c1a3a790ea8e69d099e630bc6d1c30213d3f264e4b795206d305328a5f82c3db9ac2c0eea173663ddabfcc2203f38096c578797f65b4c19fc621eb7b82e340921eaf4ddbab11fac8340443cf320a9d2db2a71f9b4e1f95bcc52cc516d4d5afb12b1577610e6af4843bf184f3d0cae0e98b037731c5f6f64746bfe79819de5fed38b6c82466bf2dd44fed69f86d127e1a72cc4340ef4fcddf53a96d06235f8766ff113c1e6630dc216722f1b476a0daa128ae2cd06da29bcf58a308e65e10af2485c7c0b9aa191516a7abe879011c40b606df72a1328785c154fd0126a5708298cb7f609dd4669b97beefccb496aadbe6f9e4b66df8283149355b1067a458954773328821f1868382cd7850bc8e498ec563e42608039cb0ba91cfbc0719e53180772ef84ba8074d619f25f2fb1f16f418389cdfa3a6cdd316614f13a18af57ea7c9a90fa3f613297fec408da8ff67c527133aba8f03349b55302a66515bb4c2c27c72b07ec27bac4c4760fd9857f68591e23e88c2521d98e17a2c8cb9e2479bb7e57b41649cfd81a8194b9bd1aab05d6ab884ed97bd27158765243d7a75386687eb2c8d7195b1517cd24832316fb7ae56ad34c4f8be589dab92354e48ca7896eebb254084161a89d282a575c4a233666f5d3f205cda45e06de5de10d9101342d5aaa0d5401083ce563217a9aa7124528fc6ccf56dc4c51cac76d43b97cd59f2a0951fca2cd207578ea32e3bf4bf02d5ab8eb885282e05d82ea2119b094325490871cd65d3ba01c5e2d3fdc203ada16cdaa4fec931f02bf4d02d8c38ecf33d6dcd7c4650d2fa99ed852406ea2a691aec109dfbb8d53c1444a04b4144480d3afd7a06ffc1982a1d7e879ad95da859d9de5065c2ac3ab6b7135880b0daaadde06542bfdaa3ecfd0f84a2a4b50d13a2f942bac55c772ec5bf884c10238c755fd2825e6bbca22d5b85024392190774c270e2b2dc53d0863e6914c06436a6c1451d076decee8ff4f1161ed0053b8e1889000a32df25fcbb5e5591442c7de51fd5730682edd1fa21b2f09215340bb13df46d56db7e8fda9e476acaffdc2654f630aa6c430d850696007f7c04b742709804d7583aabf71ec9d86f4d7627e568063e1ec4a4760fea98ca035e507ebe93f0657f8f6ec0d45265554935105ca67e51c82460dbbb532c9a1c63f77cc2f57bd93f01aa42397e9b2503788b68c48da96e47a7e28d09d76f9c0d303373b11e9ab3070d1816126898fe72cf4a2ca30d18210d02553d47f4b3dca6c151e378cfc59c0ae33692544629e4216710c4fca4a26cd8813ebd1d81e88ed14ff5c79ee4331f917e04303279f3a72774d7e3a82189c1172de5faaf51b4c112d103cdf72087a41628ff01636dc0819258be8749c8e3027e6de84e9f0b47f9a0f4871798da04a23f1cc60f410c60615a557524b0404f6e6808c3605cc8cbcf15845ab85ab398a34f40991439b3a56fe10476273f94a019ce1fb4154d835024ece284206ded36391318722ff58da58bf4d802328e04ec8e194cf19c110a1cffe179c6bb102667a09d3f21f0a4cc8760bdd6347e00ba0d99e4519f384ed6a0717f63472e5e9f83ede16265a5d3d1e9886677bd888a28697c24f0532f1240d8dd9ce5a29d88ebf017967fb2dc76547a2796733e677fbfd446a48cf853e144bf17848c4f4bb2c34d3625d25e90495b125d4cb9af4fb60bcc593c77c03993133bfa32200d00290f5ef15fc0092dcc9e907fb047ea39725ae04aab35afd048c9a36c3b7fde4e2dc1e9f5efeb0d46e568f8b2b51caca956c32184d4d47148e7565185d148f8a30827e298bdd69da203e34ae2828245b4f6bdc59a30274faa6d5639eca972db182da5a4b7e2c273302b757d5f5ee639e8f35d4177ebae775a2b3f18b2e5b41dbcd027890c314cd286df4f14269ae94e9f24e4d42c305fc231a43a123e95ebccc4abbd34b0863f79d2c59862f8cbd5dcf0012eaae3e8b393629a62cfe504a23b2350c28fcc1027ed30d4245f8b2a238d25b4fafd43e5ae2e09eb9efb47d8f6f31dfdc126bdfbe236cd3b01f333281f857ffa22b8083c14fe4506ad7c76f416cace6a6fc696a133c34a78edfc1d5c0b88b150c5ce3acb061f6ca8a1b72e8bff385638582033794a490e8ab17272e04d83c56c2f89de01d608659af490c2a29710a1e70ce12e621e6a9bdcc86940486c211afc60992bf148290bfb3d5d617a82f744bd993f2bb7307da7f38ee7621036780bb820310531b5db405283783c3a9cbed725da540de568336adfb0dac671f5cc813331bf586f13597807f883922b049f39bd6606c1ce46d35f7750198edfd6bf2143acbc9df53ec34f3e07fe314858a1669ecd1d87910fd225626198b179e8f9c664f13f75b86dd777d1f640d18a07752191a06de03821c021a3dc03193af567d113adf77f554e2cdc7c3920bb1f6ef955f7980e9794883fc01f449015891933bbcbdb279dd69c8e9353a5ce2fae71b69e8d5e57bb88b0d88fc58a0a633b1a4033d53ff7bda4a83257402dfe3d1c828769dbaa63958dbf43411092cf6d2a5c40ce11f9f81efa4d2d0c3980f2e74cbe887ccda3a270a32adbd4803251a50671b9f93f2be5fc1778fe3a02268665628a4d5b875c5e9917c3c1935b0e9ded8eca62f756d356653c2532e3a32080369c998409726ab8ec47130ea537a545053631dda4c17482e32c8fb6fe54dbda998fdd892650c83caecc61daa744bbe1ce830c4cb1ac37e743ba503a57cdd78017c83a41c37d425f65eb20bc1610aca8ef01f334a6517cf1036834ed65748a7ea8403772b0ec8530a9172fbcbc4fc873cb25327f8ef2eac42e82e125b0031367251c2dcb58fe1a64d9f416020d85903203f0d1f4860730b4c043bee9cfec7d8d5fdc21928f38c4578331cf500e23ec417ffc9a2dfd1ee0b8cb10b107fba3dbc46f8ab87aca8a4d6f6de0f648037f1fe42675fec7fa90fd6498617ea4a85e1529a2b230a719f6a0dc8db654b446ce8dbfff690131f15fb5fb9e6eced7a33543f111a953a1ffa2e9b64b5d1f2ec18410914d62b21ba21b3591be193f4df3bcbc87f103c0213e52b04da3d2c236273400f82f68078b7997642a22dcb4ba7c07776316d63661990a217ff9789941d0a87edbe462de4aaf40f402aa058f2fcab6f594fc8c0b7a63fb7ba7c1ba3008968d4381a385f19b142683b81b149ff3c309829228fd486352d35877d1f02dfb0e369c023f3ccb8efc624e513b248dbc6d5bb862df525f080f9155ffff8763159d5986f1fbdc9cd8d42aac8433e222ffdabe37dc902f63e28567e87f07697184f7ed349d02a79c70cc81e74e3fb92f8c0580e0be431be8faac079ae997b2a49f0ad6f44d1d14dd21b8af6fa868502ff07b9aa38839532f75f003eb37c513809d1598dd888be841a7f6621df05abd96bc4280be5d15de3954dffa2f71d5b68f7d00d0263215f33fb9636cd18e418a82a9627b2a555136d53d6bf688ebdd88514f7289861448a9b3b33fd59133b1059ec0357fbb54cff39c8ed36b46a5274043cb868f8737b0f21d7a2b8b6cb109ed53440a9431c689bddfb6df2cfeab850d3398bd1fa4b69433c3c9f2de2cddc7ab0494a39353b943792581f29bcb19a0e453e6c2a6a5e36a29ecadf62ea7c189cefb49b9eba0fe572c2bc6b4865d71011486fb60d520e8d59ff5ac955406b7aed1f364d5a0fc4db944684e9e2fcd55e5339f835e34697e259a23d2d1b52d32b709f117695036382828413f62b3d44aaf360e7690249b1a133946a08b4b96dbd9f7df0123b22c45cd1d62b849a0ee8db10d31b2df33404bea0c66c892d60e0392b4dee39ca462ef3d31eda790dffa62a7a404f8356e9cf3a7d6953be23ba91a0220a494314b4105ce1088016ff14f56c69178c69c0ba793d79fe0f50d902953af1cdc8d550e883b811ff3afddc16f13aed83e4708c897262ebc9b293d5680cfffc5743520fa35a089fa6c25b7911ea356153176433caf708a6dc491c2a0b13f181f3e17f27578b431123b313241e68c10dd1efee05baf00dce5452cf5474cce2ab4a53088c2f800d5d65e19793a48e2c9bddbc5d8191cbfce31293761f9430f54be9bb35e06c83bdf160d319ef986e154a260b535d526c8395961774642ed706a41c66f07e5012cf60d2f635a0dd26110d60d5982d6449a44a4cf00b8ce1aba2e70f20aecbc5ecf878b20f9815867fc24705a4d2e91300fdeb79bb83ac106294fdcdd182ecfeb4aac84117cc3277c76572c475845bbab430eea798784e072c6c506e3c417c27326aec3209605d99beed3eec5bde6dd452d889d4d874280dfdc7862461b86b6f9cf7509165d618298655be59b9d2c3b9f85bc96b9ef5b69b1b7ec7dd3b46430f5a43a8afd2a58c321ce79555831100bd55a5797ba08a31237520114678e22a60a9702a0ae263a7173a0c43954fefef0afbe8f97112ed1e81d944f47a2d9239af7bc847ae957c6366f2e76052b81100cf2c7710f4b068fff9058196a37b368a26110e6cb0c17e62a8b947e026defba89cc0c0e42c7145089d96ce830e671eb0e969ccaf719a0e50086defcee01562a97698db2e285a2349afcc53a183e8fc069142a0a7508ab9606c56d60cf1d2ff5a4db4e68d7a3276b7cc31c727b3a9431440fd49e161a171fc809b0c50e071422419f5387933e679d636aff641da810c1d9642127e7081ebf549a6e66c950b5a45143534039b557e0fcf896b5b7cd20773d9aa8af48dccf3f9ffb8b9344b20a74a6218364310e14b34cdac30023f823d4dfb4341364022b1d283ef7e99b61a08a3c362d471c08908aa8888a67dec8d3296eb90e4d325412f7dc0da0ca9d973b3b61e3bfa8fb4ce9eff99377cdb25a3bbb19a1fef0e2fa991785d721f186e672addf01e2666f5994566dc1eb168f4f2eb650c3eb8a2ef34eb230fdaeb8b8de90855ff5973b000c6453281a9c9c57303ccd3437c92c60d9086bbde6694e06892614b92e7b399b68d3d7f92ae06a38efcb41ab739923805d73fdef84be005b3acf6f3310ba5da149a0c4103ed474a357338a874d38a7a44f52dde7714984353a1142c100b75081e55dc3c5b9dd0e86a4d985c79e977deac877da904a027d4c6e014efb10f2304265819bc8a3b19c3a338604a15bad0bd95989650cf3ce44cb2d3951a68ddca08a1e32b7c84e857eb4c4ed01683b46d6f85064353b7be7d0454179c39f52bd8edeaeaef0717a5bf5cd84e92adefc2adab4b7c3df55586c05395930a45ce1c48a0fc3896eff381b5429143765d6ac2b51a2b47c995066c43bc319c8d8bb81bde06170f57d4610504420b6472562a63b55108951524c42b39ed936793b1450c3dc60713ae240ae0725a3afdadb23744c7c9254085a0262c230e0159f9e989f40b7a6c73c8826b25dfc98f34badd0a34c0cb600f4dbffbc0be750d7d17e1cbe1d7cf04cb6fe02d4efd60633fb5fcf36ea72da87bba2b51575df46c300c9e2dfe7ca0caeeae6b40ea6ed876991b4410e9daa4feec8ae035e2a257d47543cdca4afc2a5061cb21efd85dfbd31a7079cbf9d72a177c051b42a47dd885e528b4286dac2b49cee6b2a5dc6f7cf48e80130ee0cb4a4117680dd612981d9f19003b52fb219c52895ba03870e96c1aba3bbc773d32a016ed0f26f5d78940c7b3d159d9e283078d0eba81418dea8663d467799bec449a854376b903d33e17609b5ea04d321e94a7e4d3065c1c7b6a133489ad6c5d18f946fe033170d6a510c9a4ca765beda977f8c326ab9b8038d2e34e8c86ab050c3a1af288a09fec3828ac0d38b6e2036a01e78a12dd1f38d25c116f70f4018fe7c8a6585d744d7a1917c7ccbc0a5466348463583a8748df7458a013ad1975c5b7430f772408343ceafa75c75243c7032c2d37a8a9162b5ef54ac39051b536af5a6ae1501cfbd315e6e5ba85424bb9b8f704f5d61c83eaacb381bd7e1588252ffbb6297fe4423a8b0ed9c949efdf425653675d6c28c8033b6da0258f1d495b8739956fc764eb7c959594c5d608a5573534e6269ec1db3c7e24c195005c325ef7f95a35106f484c3307f76bf435ed8059722b447b294281fe92cd1c0498200770fb6a753badfcaca423b8d84512de993a280088841aac6eef0236c02fe3629c738b64c5edfc188d457f852722548fb0f02b8704f2968fc1888fc639e4b1dc1a9d60cc2d07ebf420fa2c0acf30ed26168a22ba8f1b7639a30f22dc3d0d7363fa485c7d540848af24e7a2459fabf8157dcba0df3903bfc45f34e37821115981fa6d510dd8364e67f519b08abcbb776cb3321e842708fef7d7f2ea60e7cb56f748d4f9bc4f315e07fbd1ab3a1f1c203dc74dfe4961d9c18a09ded1ca356c9658baa02e211f5cae2066f129b2e6647032842b3197f26f8e923fe429205c4437195b1fad0a240759a268166187118ca947022db983910fd7c272788a1bf3f2bf9cc943e4c4cfe73040c4be8f613c25e039dd7e19f05866984d0916deef5955949e618daba0698a68ef6bfcc03472ee2414ee8fdc421b517ca98ce0522e060dc4ad6604bc83f52d6130f719054e6b29072034ab2b26a64e0b4b4ea0ee0d70aeaa7de8d6515bcf960683f283ddd5a15ae0e689343002f730075dfaec0e7ea3666ecff35522026b9da06dcedff900631e03f4892cca6074cb4e50273ea8f6bed889c7384467234402c2a649d4a2b46108f4692f8b11eb482a41cef8ea882e1385f38ea3c8a9a113ef090ae830744709f2be8cdea7b53609071ad145449799be071118884e4b887cb5ff93d80480f123da86a38103125bd9b5ffc4f08e658a060e5debd73d226b44b36a78e0dd266248b8cebd21fc146efa8f28f48521b52ae2cc9a76a25de5a8baca24e8f22c125d31cd1f633e1fa571a260d485857e7612be12d23c64f4b988d575582066b6364bbc44c9618f799eff7017dd0443941a39bdaa9d6bc1f6752afe5a338bc5351b5be2cf996dded6dcf70cce2f75ee9cdeedaef0dc203d31e90e925145f4dd77e6effc74cb2e63a92623dde1d2146b9806f6d802823d02b4d5ae61c09cc258631d22e065b5f082c95c4cf04bd7093ce06659058dc291092eabda597533d2ac904a4c0f22ff82502e8d61ec3cc775d04fe31f25c7e5285c309b46eda8149dc2d35f7fd23c2c79f92287f541229e640dda27a79883bb1b1ab111d3c1e344ef294c41b83ed3f2463921609acb9ed649fc54a55509736d48d3b019e2eed28dd2aa16bb45c13fef52e0325023ebdb72068116f47a50c41e18a9ec9e87e842fbd02327a69d14befce18fd43b01e27c6651734efd3303cbbd069b7825125ca3c8b5ba26d66297b62295a2ea42f1c4fd8b4ff79512184b76a6d17450e72a5b7e06243b84009989eb857c8bc1bb5f0bc173375bc7a86228ef2b11082057e55f02ec23a46bc5cf7ae70d01669d36dc983bab75e2bdfdac419d9f598ca60bdf749e4175b3ed3d85ef5509debc9a3f08322a702464b507a5f675068d022feaa3ea10505fc0a77424b42bc4feade695a58aa7b8324017f4081eea4254975693c01b3896587a178b1494ae48488f88d492e4311a36dd12558e8c678d3554c75b9feb836677d5d53317bacaf4c96360c381414cc747da1962687b10832ed0e262431325c39688e1d6b9b04362a28461a58a5789b442f0d6f579d07dc12f8e702116287340a5859811069876e6d8b819d06bad99b0b65a57cc3597ee4120ebaecbd40f0fe9a9c76619ff2c9f59d03add0fa970a7b6173860a33bd41573281fcf7fc727041d357895e400094267e63e276eb1e1886d3fdfde07f1c7a7c197ae3807a29a9dfe08f0dee7596286b6a9782835ebe024f477ea77e1a9cd6047c64f22a8504f794ab8dd2d24df92c4a9c593229c3235f8c07ca4876af037e81534df944fe61d262bf0ef17dd7cc2b734ab8773c28bf336599a0ade5d932ad22a48683c5d5a178a2299c80b08314a01fb5bc8f0d5ca8075918b6acf6274d3b013f5bc4268ede47bcdfbec089beb97ad6401f4a1534fe618e5cbbdea12f9384992ea4763a76aec09e108cc7195f90820f236ac9e55b0e9557458d0d2ec594e34a8630919333531564939a91cf80a98acaf17e9fda36edbaf5846159d6d6e151deb731beb5d0f20598aaada1bbb408f0ea467069187b4ad7b16c71406b595115e91a3a300409fca9e03b66da819f32db23816a0e4577441a7e13e702b946085bcf8b2f804e68fb230408fa59e5293497f93cb121f615a7dcbdc734018c0b5fdddadb93a69176c828548743ebcb0b92025a1aac796979f9be68ef12e711b8b5100132d2c6d896b705380b39deb13a397bbd74a5c6378d7f86e52544bf63285c25fc3d41686f36fb7e15545788c632c3f2e8854f705f9a58508de26e18a61cefcd5540a56603033875f9122f6dd48a99a9690c5e0d771f18fe6a63e3bcc229451d0bbaf8606b982f4e64668e2cf209b201cb10dc85b6f71200dfd0f4be9d46150623d2df07961d45bc6e07e41915a8ddcce1f9b3b7e1689d590f60c3f2faf1de4669f037e70a9c249e7caf13f675f7884c35ad875f9d02280737a66b5c1536bfb6c2003d64b94e91788ecce029c6d43d11e8996e3ad27f65c7db055a7869550535511ba33c9ebb89ecd8f9aa834e2561efc5cefc2dd6f00401ae8c55bb5e55beec2c5ef44398ff25d9d861f1b947cc6f1d9063eb1d0add8d080574143dc113497118bda339d8d1fc34715637d192c1f8b6100e99f030af409be598ac6ed5d1bc17bc3c1bb25054a33b48de23e195a3ddd5d95a78d836292a291cb7924f9befc266eab3c38956716974314dd487ff96ab306253ffe2cd6786f1fa204490e7916862efb011b8c53afea81662143fefa724e35c71354df4c150f789096c9223e0926a2ed0790e74a38651eecd3f5277ce2afef9fee0f4c8a073238f7981d35a1e5caaa427a1af3d4ec5bdc14a882418982d054d2f919280846b6f32161908822f8dcfc2169b0642e888d4f7dd5c1afe236148834bc962ab6fa266f9b5949c79c4313ce49a202f8e456b748d56ebfc309f82e85d82f6dd877205d976bee7a07ed81794311cc00b2331488e271fc7456f2388a6a42b46c92205f40fd4bc1024b32a9e42af4f9b3eea2f36ca4100fc5100fd18b2a91442060a3f378efe871cd4210861cbf8b93f00c719478a25d3bdfcf75561ad8985203600fb8f7ae65a0cf99badd67b95243cc8dddf81b6ff787807bcf70331cac335ccbdda8516209e02068f51f67a302976e7a5f602fb3e51250d7b822204c561e161e5de3dec1c0c9e98a860dc5895854ac2a2df1668f62f0b55951b3765838230708c48b6aa0672411ce418c97cbd5932a34e119ce810fcf051d3d5077c9b49daf2e07cd25b0c070c7b81f0a6be875a9d215569e323c1ceff7705f037fc78b5f3b3f64a4bf6afacb35c19ae40c4bb1d27e3a3f93c81ff50949c5d38b783a9754ab48cd1960a7f8a77baa1711106db2209ddf505db45438dd9c091157e023df93069e5ea1b950fb5d6cb8932ae7f9b21ce068341638629dfdbebaa0d117a718c1d9c597c239f8ce7ef05c7cbb29e51a81f54d0f82db264230feccc1b80833df125a07a2f02a59bda437c1f2ceaa437a63ea0fd1c0d80bd21dc06c23726a4a0bc03971f7bc28af60fedb4ed0e35ac0baa1fc2737741f10a732ba56d7b3635c7f820f3cdd4bffb25104b9b6e232af6431117148c8392b343d3f470716253218e8695646df1b9f5e0526091f8b9752407def073a8f35e5181b90b706f6dd7dbfded8a5d6b7b1b781a5fad44bb8d3839d937b7ba00c8433efd604b85582530074fb2f1a82e159857d558d1a6c83d24e608258cdf12a8c773423d61ee91b84a34d79280ec1d288147f40278124787bc23af2cab7fe360e164beb9c6a03184d21eae897ec89dd65b99a7893810c1a04c6ef771395662b3fadafb11c06b746244f30eae5a6738cc84db55b377ab562a261650ea1de83f847021b93aa26070a133a4c50833924c395c08214b291a748b95c4f072fef9c08b3b074ef5ac00a578b702a9a1ab0da4f0aa4031ab99028aca517ddbbf1e70c5835280f722b3be2cf51905018b06ca44a01f02da5bd9ef7eb0db64cb552e04e67b4938ac7381d95cfb8793829326a89d7aedb6a2c467b4ccf118f2f7ee3a82d9ae04355df05b77ac6d1a6d30975078c428c8668666e2c37ca2f6ecd51faf7cc9712d335f39953a205a48f94beb944f56c8fbbc24278eec32cc6c2557a06078ca4beb12db3bd003317afeb9bd2bc7ca28cca4cb6c425f16be79f885993d45b961b423d3a144bca8e309234718c0bd73c73f1dcda74a465a3a505fb579bdaafffbeef30702114eaaba2b999fce119ffc68baca077bc952ec6567655d61f5b8b09ace068039ccf2a92f676c44bbf29a6f7dcba64bfd73206c23170e66c5e6f52b5f3f5bd6567ac0f3060ae0ecedcb0b37a0494e74c3c6ecf72255b29a7513d7f51d4a0c4cda4dc3d08f10716d23db0ce7840060463f00b3e3b8956f336b57a286c0763885cbb5cadc753a75d877f737a5756f62ad7dcf65dd17051857e883eca7a027075014dedabbe1bc401512f138e3ff1ce049ee5b6c2af1a9ef8da24b674182659420f502aa866118b36080f914511589339ff4f1a1ec40eff1aa64caead041d0420424a29a3839193cbf0d1025abf40fa9b5e83407affa6b785f9f3ac4e1e5933446087c739ea99073b2dd470167c5514ea999e2ffda2b8bd64001d6402b29869c28a464240a08a3812f043777516c98e60932c1ca2725250055bc12fb8aed07fc0a50b7cb2c28306bbf3abe840edf9866810cd4915b539cd4908684a6e351f561bed7235aec687a655aeaeb731553491ca307d1c90ac5daad7721bb5e1632d088df021fa0edb0b70bf9bdb25d403589038d84b6ac193a341d19a5b468f8a469a3e32fb7a2ff996c9ceddca2d241285590206d5e08d4e16ea5d484db222b05f45365172b23db323fa01a49ee9aeafa719bad6cbf0de16eddc3bded5891bc9bcb61bfb38038cef509a53119e8b1ddba87ceb5f3e0497d210260c852f67a32d09f5eeb3464ec18b303a5db0be3553ff1f3ce01e23f0b34edb1620297b687ecbce2cbea922578a079d83d90564ee82556f8032cb8f7cd5921726d8f2e607de92a393e59cf72870eaef49e11fcc76ccae47292ef09b3989fd86089e9467041dadeb24c2fc3b436e14407927f08d17146379b33c025a6f958d9c3788309ede2dcc270bced6b9809075fc0708469bee27761a1c0441a2a1a00e4be5259662e91398a802dbe68fb659e4c10e58d3d15544fd80f604a614c8456239410167677bb90abc8d0fa19ad65338359abcc9b1e583c0257f8b4fa1c521c5ce562c48f36f48591380dd15bc360f480f2e0e4298d7401fe1302c98d699f6b6c8a69ba856266038a90ab855c7d9a6db320f18288cd1d972b26803a786b3316d2d9633fcd694ce67754d07921edbcdee733759ce9aad051118518509ccba04abd9c0c5507d46ccd97f929b04567649142047f712ffa4446621948f1cc46d57a9e50acf501d08918d62c0a97cb9df0a79e21772f23174f06e9f92ccd122a412b3f307342c3f81b7b2b4200f14457692c39fa20ec87f869d313f9fd8a8a0cdf8fd1935bc83ad350f0a8e2d6afa3eda6c2d84c2c10fdfa87290c8d0ea13ddadd4fd8bf940f903a0a827cad945f9244e7a930e4d4b73bb5cf6aeb4b7d342d63be4aa7c66fc23333e705bc39eee9fe7487011352d4b9141b1fd5914673a5da1f904455d2911bec0573006b6cb1589e8a4288a56d63a0c264ceb194458eb38e4c0b3ae99edb52aa3aecc7d8be4fb22bf429a7668659a04476b9aa1be53b0d53c0cae13c25ad59dc114b4e74d9f1c8e9a64656b8aea66c45ff4d5d775bc748c0e42d10faf25bc476023cc55103eb1c8755ca7961d93209f051867ecb406365402e9d28f74a52a4e2648703f4229edde7eb83d7a46fe72262fc3f65073f5ff255027493a1966592ea3eed7caa9a690fc618c2982c26a30b3c136e0458294628eb060fc0dd6240d61f0a78aa5acecec4be43f1fb9e33312320ed7a04e3e0a2e4c1e80a5309c4aac3631003f662f972e2825234eb1f6555cce342b2801a90af4d7616613ed55e201b97df66abdc8351604c697337d854c9fd78732201242ba25ddd2007aeb6aba7068e2c078ba9e08511b006fa5ae0272d3a2f4d877a7cee46139be4ec5cba11aab5132dc5ff332e7329fe8dd826448fb8f337265d3abeecc362717e9559982ff8e68adaca3c07aa94e94b317ee281e76eaa57ca26b60661264ff1ec0b281c3e24e79f6b8c51db8a431351073bfe736554bb1e9c7e551a80543a59703037dd2787fc4b5ec5c851a3fb89024975bec5312e4f467073ff37f2662addb6adeced1c5467ecb5f004eaa96a186ef581efc405344706e444737fa50ec7ae88286805121c48c03ee57f00ff52b2111ddaed715c14eb81cbb09aae47b42201c4f5ccdaec883a39f8f50095a6c59f5cafef0a09c2078ae06d3b4313fe509e146b38670a2ef3b1d27e699ef680a23240920f83e306cadc1773209f253b39682778e49d5a2fc2afd78d06970f946b91f57ce9319475e0e3da4866c3909b4ccdb2891590f445ac6a0f721f98b6f798683aa250bdfb0b6627ec1a0ab04c32608593ab310766e854d16a1679aa7e54d11fb98f558c48c3543e7063453099ef138638b34a584b6642131f1798fc06478a62f3b808dfdba336447031d6671d0a5f33809b18af6d21c5d815b617a2aeb64813b2d948384883bd9844a13a09c6b4a73a584cbc9e821c2ac377b8c9d0c0a6e25bc40183072f4164747903d138fbb82889cd6ec1d01e3f244dc893058b75ca1185658d82bdd452bbda2c13938cfb87a40e46af7c0282f8e915c8853dfe2ac2d467ddee3aa9f78469e0d3182b05c3761281433a159010d67afc7f1d0f6c31605c2fa0bf15b889c79b01628c1ef0e80e0f3e8817de609528cd5810ccb40470fec8ee331f95cfd26e06d044c1778b339e5b19cc1f6c919a8c8943a5c346b17417c472bc0d829c9a95c03dee96850a8f38fd10b22888803457869cf7477a829758ebad3bd334f468e7aae3b59b5d1bb829a9dbbacc0a3cda9fe81a6089fccb892300ef826fc95e465bf4e381a17f2be20cf465ccb0d5163097aa0bf67f0cf27e326a861893f1038f82e6fc27341bd2d20fc2c352cf81011df95047fbf3baec61efb5581888a3273967e008f8c9065cb5c4b83e29dce98b5ce3522d0b688db31b99e64ced1362ff54fbea01e0349aca8e66c31c57bda596c60d6d9075cf65d87a7775616990261a85fe8e369254a654a9473c06a71254307a79668a7e47a6d79ecbab3e896a3da919200aefd4e6d9d5d407099393b9fbe6ecc5ee11949813f11eb42a98cd42f050f6cb79c33f931ad250473efa19319eded05bbc8041e72304c65cba45c7651b7203dbb4e37b1abc38b90173b86be784fe0550ce88bd67c9914bd87317ecb1e6c85a17554cb3f8b03c4621e022df685871cad3e492395085db32dd632cba53d28b2c6c71581e1683c0b522cff23a959cdc4662f9457a6def7fc2057e2c1854b0ca7cca0b7c454655d8740f222cc1e00ded8e114fa343dd841d47551529506cb01fd9eace13d3c2183a4572b4540289e09b0720966cffd9ff96b0d82d8aa1be38f099c646dcebde00727dd18f861bcc579a2bf16816831e42f286c286a0ec609adc39a9fe844005386df749bd65d11c3058d870e56dd9ce15e0e5df05c4614171a92eee524da5b8dbcb622e195ae05621bc3d97fd0b90e553ebce459a832f4030fe1ca84c24f375057246cda67fb971e77c5e26dff166b9535538fca4649332ba4c53b25412ba4d42e7bd7a40fe567d285f3f481787e41cc878491792ea8c92c06e81af73a35d9f4b51c7fcb0c9848ea2e6f4b31b233e894108fcdbd7a7fd000cd29c2ef29757ef4cd5982a82eaef3801e24a70f667c8a5d2284f85b813eaac30e20962054db9b3982f099231412290cd8c599b071afe33fbfc4df6555503265f5ab5925a03a6c2686772a55ab93d271b36d51350f9c6d92dfde07b04130e023ebe65e63e7f2c81530cbfd0e7d918608142039865c0c481edf45ec7d7208b9b0bdc18c8e2b97a48d331821144cd4d7b3b269ec2c26136c7634721e0b5139a88cf2b8c66f7f1207ae9f640f1014ce713d3631d9a8e4591e905d446d77206d1d3931de418ba440dc771929572e23d1c3b079b362ae44db5071fb84aaef0f287386a88996d022e92901e2498c71083e76a71e0119fe2d5519bebf2c435212dad6e3aa06ee0844a12c5f218e7440e783f25e6af97b75aaceb4027769e400404e4efe339110a1f274654e220d1b27aef06037f6079ce6e31a204bbeb4d582ed6c85c4b3a2b82874df21e9c01e3cfb970c66147f81386520c8dc28f6cc37aa1b481f1e605f0a224a07969ff2749cdf3e15bba94a2a64dbd36f6a5c0646fc47955533ae854648092cb15851959d970d800662b1a66093910cc0a15a241c1c631b54365d7b1a4f611f79813b17ce4d3e5be150ef1babb0d773a11783a89c6fff4812887a358ebabc76c6d89a1b4eaf0bf5d7f14068a520662670fc4e2a3b559c6a4587407cc8be59e40eb11fc7f1fecacc82df38d36c0c51c7b2ff3264b65044e8764690fe6aa14f3ed96ce6abd32fc2cdf4503a10f8fc45e425e304fc1e677511d202fd4eee4fec6e326fbcd1b5ca9dc8b813ffdda63603c0231071013565d486b8e747012cef37ef00d456d6d429ebb6a941a61e7ad37325dcbad6d20af2496e8b6fb597b068dc33e55b5b44a929448b6275075e3333afe51746125e9b7a62e3530f2659f0995cb2bce7c53ec4dd794a057f92bd6e8c874b0e6962c7aa66b55b743c924a1f88c794b66d20fa32a7bc497be07d0fe41f9dae7ca9584795684abe9c099510a631f4114a73786c5ed8ca2c8e77c0feec068727a046c0f0b77c623b34d53372beb390ac85728a3546702085db150f4d8f39720da72a79fdf8b8c8a43c3ad0394ac3ca6271faf35bfef42c2be0315af8a1d45614f0275d7f98514b1075f2574c20697cb298f2b9c1d7465a5107ccfdc5d2483de1386133b41612e024eab176a5f9dffdcdd5a3747612a53254c1b617a4321985b6bea6824a5d0a59a30bf484f59e407a200e0745ff30154ee9345a8467e065b1f457880dee4178cb9f242e7f0f9543e4f5a1cd82fe74eaf9fbdcfb13cff6902eabfad5aca0c820391614278ca6b835d38a77c11f22333812237aa98d52ed451d3c818b405ee20c212ab66332601d5a1fe133c6a6d5db7361fd23905d7de045afacab1205e6afc8b349a6668454b2283e410b886365772236660ed71532f3e5759855cf7a636ebd5127ec9ed1b57e8477ce56ca733c954e0319721e3b543ea8a5bda2225d626980f8c3be595f1ce4a6834aeb512807da2a71c0e8f3169b0d0687985819e2b0ad8c21a1d2a41a40d6350c3a7dcb6be152b8b5b033b84228fccf42cec640b1c8505da0e12eff2f88f2402ccfdd886d0b37173d98a8305cb61dbda57c93866d602ab4ef16825f6ef9a8be3aca3366563c7146d8ec90ca487c7cafc9c0a2ee5b4fb6f71c727c82dedb39b46d1eecec81900b44e1a9bbc6a3fbd3e1921c01b85b490a941231a1bea1ec9f7baf7f851835b7ccf135f62442de74fda417e59ae62a60f84106004c95406c3573e0bc31c20c24f1f3a7f81ac5ab57ef385e0468b8efaad8974632cb98933371bb3ef127c8759e75c7e6c3bac199b9a33bdf90efbce2371820fc1af81f1ac28346258d4e48177d7880d2faedc558c734c16608028b325730b6de3856bc91abc61c45347b7b8080c045de93ba3946db573bdbc2d40b7438709054ff59cf0498d506b81b4609fbc2d7443ca2508beeffd0b2e7b596117f866eaeb13b97bc7d329e5a04d40384fb22fc8890c91d2914f081272b5cc4403059c9a1b265764f8e1dc206e499159a7f05df4ec70cd45a475a65a64814705a6e24f53e52cfbd97dc93083f5befb4a8290943a6a6f015bc1d081a0975bad49b50405facff089c20bfa9475dab4d10432c6563450d45a3076bec6130872943eed85882fd57d3d435f02ab7e7ddb389bd55280e03dc5e3baebd6403c3db7672e1e8332698d9df66e186c047ae6b5272ae2e9291ad1e599d3fd3bf38e0994b7257de609f25b842e5d99c3129d7cc15fa931aa9062fe83ac7d47eca6016e294340043ea01e388261d204e7abe9659418ca558c262e4c3103cf82c4640967e8bccda78309fdc45a9e276e7c27300a687dea56f09b055061aa4dc838613851a88a44c9b4ad1412b9569e7e84554741b1dd7624f06544858ab27c0989174de78bf6fdf3e3ac1b50f3c84c7ae3ab58f4fb85dd9b5833f74cb18517d387d776e314b644b715dd291dd813b95a4c06ec251f9de62bb26a4e1ef9982f9ac4343be1b86b2a606e349f6b3f79aa18ddfa46eb0d0cb1d5aef0cf82815b00d9d8aab7c51f1b8ba76c6de82813e63bcbb004cd81c1dee0a6822fae485a6afe095948892b65620cf909811e4b19691ebc729f08ececbb6c20c68117ad3afffd8a23f5414041e8b580c8e6a223f6166272ae635dedfe036a99103c1ca7ba390b253d9ecb0b2454278d41dadfde0d6abec613c4bc603f5f30d4a64511b84210884ede27a5f12f2ed253d445929c8ed5dbb1bd26ee04b182fe50256553b2fea2da9868a0621bb5d15f9093fd267b1b24b728ec7e871ef1e85042605d4c3306d821deb07a70f4ac0e66c6759b14a527aba057acf6894f73109350daf380a2e8b47f95f5858063e88e114d9ee22fedf02da8a73ae79f0b7a31a34154cccffa0f81ac63265c22f32b0e9577c72df3603d151cadc1fb0050769077e35d3693cc40e7febb9cedc78889300a7273129ae5d61e898b86a45093ce4141515bb93f4b5dd6dc6997609747dbf2d3c0b53a806f2a6efe9d19c30b0aab76c96cebac48f0264372ec9130c2326687a87191db5c66dad774165aeb8b065d11f9ffdaec28e4e35ac8ab5526940a421b6dc717da4eadb7c590fe1d81b2a989c934c80f1fd471267f43db36f0d1e02f46f4a0f3f735cb8fecfc967de55bc1336e3c7b30116eb12019591292f2fadaa143132ce74ee9ba721825558e9a268a396439a88e84dcf5e32106b31618e153a1c83ea2f4badf60dd1c8fd3dd01cafa28a8a0cda5760485f3ad0d0b92f3348aa3179f44cb4e87dd302ba4c745eeae885490c22ed1e6986714c5299dbb916b548ac0a31e179a989319dc82eb270195447348fbd7d630beaf644a8d121c489adaef07ec3fc67ec77627e57d29014f69e0bc88bc37a6fddcb075d663d976c896a7f2c19e1b499deb1a3470ab786e66ce8aba5493fbbada2733f24c94e58dea2ba02b492a391c8652c0e46972156dea40fb2d25b0a20113904c6d6da8b63526dc9801ecf2c67cdfd35ac837a8c41d1a0972ba2e1603156007783c2143d64c9ba8fd3162e2d5a62a013cbbc98c453e1a902c08b568cfb4f6a22d4cef162db5609f88c512ee70753fc9ba7d33646126981c06565db69829802562ca706afd9b83203b5de6bb2be15a96223dfdec2abbeed839c779aa929f61fe2b0adbf158e793efe37a7fe6a305cbc10fbef01a72b27dd7e5be049a10618672760639b1dc52ad01b89ba403348e1a294e9f60a8c51bed08c48ef3b1d09f664727a4d25de8b38387e261439d3848743a9fe1994351fa1a0ec4e3ab691e9a31a398667d6630d03e55e7dfa0e5facfa7b4a16edfbab296a687ad840c1f36ed97c9bb4daa4a1db789562180f21657ab5698438b26a98dd91fdea6ef8e6ff37006e0822da0b14a95f7522e7102464f030e2772152d47d5d80b90bf3143f69807fa157dd508686cf412daf0b7e5ea69c1fdc3549446559e44f37170c43f2932f13e01a971d40b549d7b3dc261373b650888727e5c88fbb4a9493005dddb1c7cc2f9e2c9c606fbe4564d006e9cab9cce9c6ab570006981634d6ccf16cc2380b724f548bddbd992eeefeddac2472dee2e979a052add6e1b6975bd4127d6890d5a51e820c946b761295ae24e861b185f5a018c94e69c8b64905eba3dfe14a9305fa215ae94dbfdf8b5c18f3d9a82ce880db01a44c86e25c4a010a6eb7059f7ae90b2c207142a6b1f78649635bb080eb9efd1739fa67d089ce37f4f4e774db8f929f4dcee8c2eb5d6b5465e7759ada2ebfc5f3a1a5ef10999bd984c555182c81b45d75f5f817df0f94d339f853a00905310f75ce50ff0eea548e161d8173353c023907546448ab19de9099b8e08277177a8245a98322a3d5aa6d9b739263b1d19732ee81c4265a8de860a8b125ac8c66e508f8e9db854d2e148785c443b409786109a0902020f9e1ab6a9fa74a51e537e1f65ad18598e0ff4c98469a74ffaeb293c1afba12f617ce6bf9451acc07a651fe4bfb876e47239112e48b3a1efeb4a0f543a981c7282d63a76a755805ff7ce80befc9a838205577d3b50b6a2cfd7251959e0230d107a72eb0c9e8d3e9ddd771df70cb8434c5364ccc68c206a988895099ed2ce0a465d7f1854bfad4232cc9832236d9edc2a3fdc34121bf0d320904fcbf0793bfb45532ae312beed2fa8260899a7ee9f91c6ce6fae99981f01d03e556027f97b5a593c0e81a07db1c6777fd266e1af6bec63dc59eb3b4a4bef6345f0cbf26a07404998af0e3860030b1c1ef92c8ea08bfb99836d4ca6623ac2c89c6c20f6d988dee45db7c02367baf2b85cef672e7a7b73ebf3cc6e249cbd052fdfdf4e07be1f47f773f3aa3b0a3bd62c9f3e4ceb8ac63a727a740153451692b5ad548a1785ef69dd6bfe19dff096d49692289b79fe41f17b03ad5c4cd7d37159176218dd54ded3ef7ea409c94bb7c4717f730caf871143cfe9017c969f4d535e4b1c1f03a5e30862db47e2fccdca068798c7b8c44b565787dc379eed7d933a28db4505b1d6ee3675412d67b0ba1e30fb75953765341c11855e6aecb3332ddff7b7eb2d620ef1fae469f134abbe86b99e12d88516dc9f88cbb951779cf7e3b3f4c024a600706500ae3482f0c363433438e9ea966c9318f076e0cf9a79c737f52e3aef39a379484845fcbcb72ffcc2f9799f107077a5d6de7a8a5a6b5d2bdf6cb7e3cea66c2a5fbd99f027dd1cbaf24b4433938c3851ea27b8ac3c3c125827e67a2e8732517b30d65d6c58b80b508afdd43940b43264641d63c01b7f7d2b42f0109e6183e5d657e1762216c03a4c8e5339f596c0d967c156b9f2bf1fdf648f9e8aeb4f1adc7518323e0dec0ee66fba3ab8b017d0c02d13681522faa1e655a2438b90632a96e9e0a99dca88130c8d3ace4335b43ec302949803b8cd7cad1ce4c5fa28662327421e27f7d733bfbc9726a091cef6bcf55b240b25c2bbed5b91eb821dca08587feb514f29840f1ed0e8e5786b7866ffa1064c6c167e607e9a83cfaa03ed31bafedbd63b318bc1b586cdbb1ba3bceb8e902172769a679780decf1ce84cb4562975744cf7f23ff33e6006e1884685d4419658fba7df1c596294195c3ba08714e911321c16730c343a26725ab22e003fb47b30400be2e104276c3bee62fd44d8de6a28b2400062ced3d17a988a203347e83520fed7a3c42d0782e38385dfbbc5aa28bf37ab0239519236018efba7302c1384f66ad0a6d9de032ecc6ec3de07e28d0970bd14bb2486980080f804996d4baeb810d0475d74981d46c3ea4038bc6f9afa9665cf22e0f7807ac9544664bfb444c1cc8b9d74fd759b7d646349fbea78bab483991972e1347ae7adf6e5207ff7b3a3ea7aed9b16085a3150cebe188daf54725e2f712c496d280fa1ab12d5781c2e498c7dec0a2c11ec38e0fe00d0ecc01f534703785e8a4ae4aec12d6202a01bc12294f95fa7d2cdcfd86d6c3c186e4a6e1c5a4f3172bdb83609eb3bed076e66e970500ec6134edc071343dba60a360a2e461a7f1cc03ff7dab0f68b2a05ecd950718410afbae68c6335f0ffcb0798fa8fac5e687e63cdfa59e8ffb54ffbdf23665c33993ff936a1fe23ae36d7fea4007649429484943e9226bf4127e844fc170f274b82c70a89c1e2422477adc9b769d2d800022a743c9cc5c3b9c6c58bb719327f89f2abbf22eec2cb6acd1d2343aa3799f3215350243e5a10cf02948e67d05a2120abe3778c7b56b742e74ba7003144b7178ff5e0254e3b1ccf47a1becf78b92e3a87d4468efb209a319e7e19b6d6de2265bf2340e346fe06c8ee3502ce0222216fde923ae2d2dde3ada1aca54c935df5e01b9aac477d1f0e3532e0155c65f26eb31e4b642c7dd41f51b928f54310ce356603dbe41f7deca846d341a20ba05a90e10372174dbefab59a2c24c78cb7f626d00bf7927e85f01a96a6ba612608c679804a92ce4a6d1ed4b865ddb56dba0b9899fabe90ef57a8dee68b0742fe196c05e3c52e008f725dd22ed42e3a6073db4ef5ba8074ad282d3a02fd3da32534648618fe795a58390975602da2035ded81982f4db5802ec6d7ca005232aba2de8a4098df060caf44b58feee5d72f79719761be24048f0bf34f2a7acef6c5cf9c690386594cba1ab9a71dd8a14808873db1f4be2087c4a1a68e0b8a4e8b6277427bba5dabd71cbf3c40d40f27f7d07ae0bc431bb4e08ebb55a2709173091ecaab2243840cdd3ff1536955d6f9d84e4cb884c1371e77b0d2f2237f2c16bcfe087f97b490084d101288f1d698c17336555c8d5990e299efedbc45e6f71a12398ccf9638acb8ae08fd9a30dee2fb9624ab3d6a800e641ff9ca9c7df8109a56d8680df9fa35d5759d73b39a035c092e315c1ba7bc2f4fd5977d85322b384107d30f083730ff9583363ae84a11a2040a68f2eb9957e9e4b63f80a1dceb43f441b0f41bc8ee71388f14b46e088faf5e9b198575746503fb908f8ba5f351a233bd990a528409a344e2cf00d6a0454abf9d54dac045b1400ff60c8ef43cb8d9e64018c4e2a2a2e28970ec00444af9001d32f909839f079dcff06d4f2c7abcde2fbed1f4af9f8be1153bd8bfadc1d3facd30cca7fd1f81522ec27b16c4aba52d71a9042e8d99f425183b2441c93188adc8bdeaf8c1b60fa2f0a53a3932ed0eef6c647bb5ddc795b8b74f1c78b8c757cd8870137327eb91c960ad6ac10043f230d1fbcb3298c3f003961172d8352e1d81caa5f166db00d94968ca105259d2791472f44316b20624ef32403c4f60b84e2f20db905e79fcbfeca66c6661fc61e9f26fcfa4ad00c973e4ae95005882f8ba82d086d6330cfaeb3d2af3590660a59fe6e3ebf391425a4200b68606b72882d1d4e6bf90fd38f7dba3d3499d1b82eef21352f60f72dfc7442fd3e52d97d05c851eb64e69443adf2cbeb8b3201b160b078a1f569c7def7ed7adc3b22982f009c44be9ebc7cc9a23f145a2c607a34396e1919c84d5791b17f8c0283cad2b22ac60639de6361efd4a03447d05195f2d247f26b027453fcec13394f1bc0182a4c3c281efd1a7e8924f1f6162364657310951160d2ead9f12214f4c5c2102aa94b163acda3a49aeea6740bcd17df9273ce3810c404318011ae9fa1c3f595238f28cbbfa557f11ada54791a86ef030259133d8670dbf6319e29c99c25b79c6aaf76bd2482ba4c608a93e9caca020a7751f0322ef75dab1520f3523c837833c9e89cbcf6dd5acd8e9db24746b894d71d259fe84d378de2139b1f27a3817f6cee95275e6a7ae00ccd4f9149f9fb01cd37716e5e87749c935a89aef060af434927144511e5bbb2c94a44e8dab648f92974e1ad05bb56a873d8aecf8514c386044aa80b7b3fc0ad001517143d156bcd75cc076933ba7e135842d8356c0b7cf25cbafeeb8427ab6e6f1d0b37d4f8ed288e7538fdf5db59739fdfd02ebba65ad79c97190bbcb781bb31b478a14881a923198bfcd0be11ac0284b2906da70b14a026f8ac677dd547d41007446e9d023d4d10deb3c8e8607e713f37e6b2dec04a12584c75a68eec204a3e9dead37a979de6d74bb8966a00d82d79825470779939b62028cf3101dc5bf9ee3437a47e91c83dafcf73b3c5ae4e344d3a6be767d7246bdda2b4250434134454211e29a1eeb30bc833f3d914fedd1c83b6a4cec81804e14ab75da4fdbe9b8b11e10fd3a00b76e22772c936603989419a337ad72452bcf5309ab085737544b410eece6efe96563654d209cc9b34c0b02f1be3bede39803bb43d5fe8cfb83ff886116372272dec659ca6f1be2a758d1237a41daba0bbaf5b9421b5a4e24412ab547980343268f91cde747e755b6e83dc1b1315d8f96a05f90ea6f14e4923fec3fd5c59ff1591189946cbc3a1d6fc858cc30d43a0f23e73aeb62c50b5029aa0285694ec58be9a710ca910ef7fc94e1b1187a4287bfc025024e34ab6a111e0d0fe3c3645da55780344ffe8092e7c0b4252ced63a3a20ee8b2a119a8f4860755b674e8fefa0909fe7c74396fdb25df7bf8d60b87e6b7ebf2424cf3a6b201e315310106ac3f67726f9da8fa15c3b3b5f0921daeb7a5d1a4e38979b2a7d751b61070d281c6f3427f07d4c2eab3d8215984290eb8e5b7b06118c2978f17fe988b99120b2def3ee9c8df4faff46989774008da64cd81537f9b28680e5fc56b0f66b99476280cfd7a6aa5d0f140800f4347f3c8d3b87b30e67e1f5872fd5d050774c05d3111ac5d894c6297f710d29cfef458a3558491a057bc9df18bf820c0671edd50e7827dd5d2933d063ed9920773da1764232b36e38342364d566602a4d7c2431010be8d8c5ae70d538d522181c1c8d1069a02ee9adea580e3e753cca083e939e0c8f67395d68789f4bbc16f633b3938576246783fd6d812220f4648e0b077dc37341e1946d82e4d01e0262c458165908f1f1a704191e98378f9046cf9d11c3bf6130c017a440822113cdf8a1b8e85cfae02e9868cfcf6fd40da5a7065417fe4660bdde3885f88d1889ba9379dfcb53c61ca3ce7b5026e75acb1dda486b6696c837f8a86687b2ac383ba4fa833d596f42f2c1f1f5eaf9c9a1fa7d24161db590e8b409d426489171f16db7e4f8e8178e5ed399133ef4a6fe404f0fa1894cd1b37f1e510f1a48466270d8c01f08b66658ec4abd1cfcd7a48c80113f3fb01fed4a49f21858c53061a8d6ae41cb348f4c39e37253489873d7df1ac77753301b232e700142b0e441032644ef0a887d78382b0a87987eaff18f3c520e1b714e8e83d114345728a805eba4a6f5eaa8f0138789af8f5024da5a611ba93e014d202a031e9e02ee79dad46310d85224b2a1669553c8bd87869842da33e59e2eac16cc0a11be1fdb7b6a4a19a4ca3bbe5034f085f1192243f4c32f3c65ebc3d93c3ef81b5ec63857c631b27f97e348ff11db89b210cccefa6a1998882628145e13f14a65c09ff70fb2baddc52c0795398ddf6f5ef3d83df978e8d303b3a0dea0c27660be6cd4e1cb42bd97660dbfdbccd2234ff1ace5f8647816149e1f2640ec8193f83c0caeda29b60b0cd3dbbf0c4d05ffb8fc26a8d40333592d89a3512dad991fd0d931935579e4eaf013f356685f75815629726b02e1178c509c057a19d3113cac2d240fdf078dec407b2782d3fdef0ff412bfcc42e101cf70c934193d2cc68d692d189df601be2a1bda14888a1045818ccf81c4895de81502259911584cb0386e03d6ed075ce6002f6d2911d3a16d00d37f3f0950848553c7534e9cc6185f17a08089a313b93d087f529ad2bf9657ca788daada538c7db2733c1eb91f085614aadf2e172118ed26850685b93953555d261c9f6d09ae63b92cbe22e622d677a54534bfc8efccbb46aefb4812eb24b71580cebd3b4d7580c7d20f660782aae15f019bf176c344032666626cc6be66c322da7b18a83797eee77ba661b0445317715375b116149f64af360fd200ebad036897fde89234346b130cff79cf6f625d5e306267233803d23a198349a50562029d0da08159ed2a479374a43cb005c39640e34e34b9838508c2fe31570f37be984aadd20ccdba5e4078bbbdff1394f7e79431e9ed77963ef74987ed1018613c84a43f242534e42cd57456380023ef1e36d64fd728dd5ceface26b70fc1809756ac11541554bf341633f894f7c5dc1a16932c34817ef824c5da877df5e102697c82a42f5ac1a7fcfb5f39072cfa2dc6b750fbe1d4ddde250d334e3eeef2fcaa76166a43c4acf0639adada0b8e167094ee33ef519ced633c3ef9bb97b15c7b33cb8a2b902995d3b28ecd86db69c2e8d4c23170cef549b64b9fb307360c702e9a8b6f41f6bdd139cbf40864ea30cf1dff55227fb08aecc4de1dc4c32a6be8966bea3ce4be096eef4e45f949ab62dcb6949063a9e7d316d5684a307b67c18187afc1c0315f8d414022e19abc15d5a2b2e2a34449ac025b6580b4e5cdbb4ba1dde450fe97c1cf91baa625354b8df8449f364024d38aa48b0804d7d6c723dee8e7d0e002240a5fe8f04b84d7c413957b3dcf13e237982e75fb829c890ac53c9be006d75506eb336eab4805da660b1053964f4a0ec437c48ed87a1a0c30d98e8675e4205f57a0d2bda6b8a66c9609df64af3de7c95335d1bf096de6371fe819c7aa2b1cb067f4ee910dfc90bd734076867ec1b2adffb9fc6fb99236ae46f8cb06ec11e2ee3fee0928812e08511953f9d8a90fe7d3f04105edddbea229cbeb1110460e8bcd7b14ec1da70700e6c8a8a594c88a6719ac4900d0e83312fae5266e00adf35e9a4edd5870fb424138e2f7a387d85bc914a84523851c04962658d068af9d0f9809f8e696b4fcc03373d987e63463d52f42659153bcce50b010c2fb69d9b044f8596805440789015a215273af98808803a39a1df49b4f3105aebbf3d4dd0850067969a677c387a72bd0cb60a321cecb434fc03c1c0bb01e7aa66fda711075079428708d95ef1d5901ebc4bd630828a1da34997eac90eecfdb278c2299b23be2cdebb7a180ecd1c78fcbdb5d9d030ede7d89c2ce3b830d699e8c94ac9c58a9fa38e737396363f00a97a3f98425ace22e53c1a45d409bea352bda0eb45f671c33b531191071b069fb3ccbcfdd1bf10902d3774c72cdf9ff8d46c92257c225542f88d4f4cc1a286310a25fb2dff87d0cd8b6faed5077ea3423347c56d162423d443095f1911804680c24a1ce929396bb3eedfb4eb2bcd99277a45eb9ec7f40515090c26e313f2e8298b6dc8f0be8f068316d6a558e7affc3675cdc3457b7253695dfe70975f6050d254e690babaeb0141ca36d3ce9782f91a2c273de9753d3a91e795c9e3c6439af8569c3eec33d56b1e95c6517d4dcc4c0d15e6f7c3da57561315f4ae61809e2efcf058519b9d9047780119815af680c11e62337f9cdbf9c15038c3abe667d1883ab08b1bd42fd18ac2d1606ff9f0d2d1f48d6d020fb032997e54a378e34f93c8a2cf89eead1c03810163d5b146d6e87dad9d78735b70990dd51fe480e733006a9034377ca702e9a5e5fd5df9cb9bc79d199fa3378840a93b99e8f1e82605fb8b1c2cbe65aa36883211d3de58350393a7dde159489d6e37a194d5495018fa9c187b201adf658e1d7f1c3b96fbd10f1e0a94d764c4a9805ce9f0b4c161e16889e05397b23b5500b7a2edebacf64915e54727bb892742849973b487ee4f15dc5a149096713c95f517ab95d35fff8961b2c668854d40fa0e337ec26f960d1ec084dcf9184e91f809694e6c67936927e2f9f60587094a3dd03490ab000d9cbdb53665d0c4083d7715e902ff61398b696f53465f2192c4cc2bfbae35d6e29c24fb2ce69a69775b25a3100af7c36c2b11c65e425ae829f9684932eb9cae8dfd31c8ecdec6c08404881b6207c12a27aac91effb08f2505b55e5df40f796df51fc4edbf69e93cbff99c945b2a33a677799d545b8916d393a6e404e4c4995b536f7b31e1682fc75bc729c0d2e271f730dabf4c3d6707f7e356a8c0e8e8002741de7da93a0793a7fe4606156e5ca2646a093668f5535837f1990ae2faefcbb3d519f3f0a5f2a8145fb7d98a87f89b46fb10a3a16cc5869eab80b5914dbe5c339ef9d577b1a650f3dd626f109c4ca4e23fb79fd9df55395c850366ce20d73e454e7ce4cb3fd6e8272139eb4be346ea5c5ca8e1439a0ffb4140ff0b8becf83210bfda35791832a4233c019ea29e45c71674724c6e4f3d3decb02c91cb78bc39db0b15e68e20be075195c5608f96dd440df8e1c97fa3beb0fac0d3a5847476172be5c4d7001e64762cc39cb73fb9b10aadb9c4653ed671d9029e32f769291edf4c368059d507c6d7aba3ce2c8a27f574e1e357cbefbdbb17a6eac2adbc163263adabe86bf5be946b61a919299d49a146723be85a4e5a1859bd6b887e382f009ca7890e0b88f85afd1b54852d5f3f592fa5be7213afbcbae11b7ae1b0a6ffc2fc1cff7b9fec424bda1807dd3fb75a2b6b9c2da85c81e7e7e96846f3ebe610221695fd6b0f1cde6832f60f34190bad790eb68c76016579f8b59584e9eb36480f356141427c8c26cfddb5809c10cab71855c400080b205810980aa6d17bc8a092602ad44dd2bd17e4f8dec7954adc8cfe653dffe7eb100a20f0c6283e6b3cfe469671b08b53ddb39bf08d40a6b0566933bb0ed3a9488e7cd8309ea63c3c44f21f682e46ecfe30cb63636662f5e42face9cba6126d06d9aa755c7ee5295b5065edfe412246c239a70891013857731b85c09e385bdee428b6fd46ea180a964ce8284667c56eac5407c8a6eb8acdecdaa8c8957d19ef6b73ebd7c9a740a1f43e2e40ebbdf2dc6f3c2f3cacbfac1147401eb6ff93ce38657227ff0e0ece3a8dadf6d48ba6d548f50eba393c952bb56c6770734186d081bc937c95937ff01f148db231930404d9ac849076894cea120bb113c43f6512383d3c8913fb19564acee07372f4d640b12b5cdb466fe23fcafb6cba26596e4783333ab6d147e0e34610f0629dc0304956f127eadc55fefaaff31698c02cdc6e595f43a8ce3a32d4ea8768f384243f5266c8496db54053d64e0ae8aff016fa0d42ae9cd2505c7f7f127e917db5c50daa115525782035f18f605d2ce16ed7bf398198ffb412f367ba31d2bd7eef3644d1b202873650a57bbcb5b1b913079c8a363b4024f39105e0f940d5652499b2efe6ca168412daa2b0a78d12ca2fa96b42fe77d86ca8e79f4bc83395792c5e914115c76acc41aaabef63a661079794f3398e7006ce2cbdb86becdec37615657acff6b7ef738ef6d96cf16c9a7812d1d13750c0685c9a9bebcf1ca42a750ecc16d9e5b7099b71e90ab5350d3d7fa329b116d0852dc2793a898849680597df330a2d66f84a92fe217754207b1eebbd1d522480e9f6c43a06203544e598bf58812df48a78c0361c2b0454831c77cbd8745efefca93cdbee22d3d9d0e3a866b1dcce495d128d86c9f7f626148d157889903c6ee4d46b68a5045a3d625b6bcc878a8fcc10c6b2cc3e73080104ca3b9cbda6467316289352b4fad01dd3114cc3939908f40569eccafdd7d78008d80a92b168e91a953ae1b3ee934e7b9c7c26e5c039a5a54a3baf1389c6ac1cf40414b01b0887c0843853b17f00b5ce8cb20b0155c8bc269209775d94e159c41a4e8d17790152990f1a94481467301d9a04215fc14a4e151ad2edc3b27844ff25bcad691279f79777f31868aa8c14e28e4b363b1cb4505b69e73814727690f7f6c16d4b666c3dc30403817a04d928c55ded11e3e38a84d502d6f081a4d6bc619f504c242d832601782bb183bf2f8212a32753f3a7941d67ce20ef1d169d4addde193219d442bc3572eae83214ee956035936808efe6e869ea620c4fac710e1a20a847aa8c0b2a8d3125f8f6be3b5125f769840baf4e28c3b339399dc97e7ef43975e0f670ee0a75c9782adb8227cf38e21605a7a2807f609a028aa4f85f560501ec2838fe9b20e1d1d80bd54ba2d33e3fc80853817c31ce89fab8241087ba692b2645a8073da448d10b91fca3d936ad18929671849620269bf762bd7ac7da155fdf519249d42d5bbd8f4cc28145e40346bd0838dbb1a2afe1ceae2f84695833cda626a74a2b80add071ce8c040c35364984d3b690197f247683480822faad7617849938bf8e8a7767aa53c745270f5006f242917ff3fdde85363509aae78e7ff4f22875faa7ba441b17f9b5c86dd4b59c5f1b7b384a9dca6b93a1924814178c47b499d0495a3994d814cf1ba783776d594caf44e486d32b9a4aadec48eef161d8c38084d8ec71812f42b32a22da9e9c0d46a80b09d36d8c286b46121a77ae93581794eb2e7707acfad235d194143e1387935638dd75326e3d78f2bcdb7c1dc2e6b5e13de4ce5e459c8f96940b7e55b01d63867b97c6b6b84d6fafa2b9fccd26213517c96c185d89ec5133e0e082cf537d64b578c4a3011bc38898826504060766afdc3b1b3fdb9424855e1fa7ae1fe7433aa1aac0911bad07fe73ee5ad7f20fe3185d5c5c9990f37dd7d53afe4d3376c46627c7b130d006f477673696b83bb9c08617b2fedb51c3181afd6b2f76933bf45185d4d5c8f09bc6f334602ef124476423ea8c9b2613420c22eff0bc33bfd7fdbcd7bfae058157a757071c280f401510d4f8f430ec0e1775a13c9fefc3b49d6681585478e936111257b4cb4b61b131ba453ac615bb401393b95534aee4058e8827b120178b59464d11eeeb9220dfcbfc34e52d3c830883e862c078f0c0c2596dfb14f7a97c3a63895fd6b3676ca2a9550310da152f236e307e23ae52192a036ddf51fd44374ff5d85f631f1cff1ee039de2e58f4869a9154b31f6297e06091383b9eccde80ab05ed12cccd238d39cf441a44dd89c9b3826f282808deb15516d799445d26743096bb90050d9b9595794a218c7f072c49d3e7b1dd4a83cbbdeca942a27c2eaeb150bfa035988881cdc864d533a89a27b68078a53840c034eca9b4ed88394c9b8588e08c4aa1b78a0bd1615a7b0d8b3a4d75c507f14f767c086f0e7409c93c0f327b0cc42c1f6789daa1cfce4bf9629e9486cf488fd3c2472519b54411ad5f525afea4c19acd3341fd6a16dfc7330a2b53cca6b21ed0e4c09815363eb655c29183f3152f6fb45bd0a0359990982c1ad75aac826bcc481f22f96af8c0287a4be007cc22908dd37c5f39a3f5b147f32efb3c26801a9cc87dcadb9c7ef31593af0848464cd4a8ac42136ba754e41f368afc87cda3bd0c607aac2444c25968d610e018b5ad43534fede8e89bff0cb08d4469cb9ee5b988f9c91a845c11d332510dc99e7ce261059c693b55cc0b987365674dbce30ae0f9d49dec275e8a464d6d246209b05d58a49badcd02d93732e30635ec75d136643451c6b1a91031e83946563614fd68fb054f1114191a927e0bf7d3cc528c979b78e5fad1fc89e7eb70ffa289c9b39b793b5c7690c0849ad48b065f44327fc403e758ce34b36ac7db4af4f84a1b83c16bc5a6f1fc1e5dcc0b229c4753e3b841e91c6e56f45826111c8e31c01697c197a07c34d883e76838f3f49debe684b971a49971dcf3e40a718c1e8bcb6e0530041ab0458c13e5861b1fbd08115e7c7d68fff2558e13a9f97613116caaa81154ef6a41e09567864c6e0a5f0c1062888bab966a913a96039e3b3482a764a4a938e221581084067a4e271b995615cefbd6db2480548bda113520123a211e62443bbabce8354ec2e2854a5011a545f96dbaaefefed784aea02f3e23d648a4fa7a75cadff7fc4db9a11e85dd9e1c868e551e0535458c2a89ced8d4d2d7f59231db8dc51672e61ca8db4ae0e40d7235c08248919997b9905be327d467eb48c771646b0e04a2e039579e273de0c14db0eed93e3865a9589f8f480a3f1cec90156b3d5265a2bf57decc0bc4b80871dbb09f9d73269b096dc85b8f76fd7fc52b03568f1f34d891b91f8f70d153571190732bc995818b71adcb858ca8be3e6c3670467520cc0f7ddb6bca9d0d2f4ca45ead42e6493ae89abecbc176084cdff4a1fd0e54bfe79e629f886d3a9f7082037b8e5b1210c30950e74bb816e06962a16ed5ad0017c92e5a42888f29896f234875727556313d5b1ab83fd5dc3989d9833bab4b9a34dc2a614b9186adb8d88155007ef22ce979742abeef5f18504fcbce094f45a25209f1890531be7f21b04a9557494c2763564486a3c2a33461e68f3222d40e96dd2040d04370f4be97f9a3e4bb78bf87d8e12ac77a5ff5017bd356165bfc3bc901a1522c134c04af23b6460f1da8c218ef75485d53f45614225991a2d26b80cd52a11115f43352a925702a0390ffcc4a208fecf84d1a9519fe62dad6ccf64ccec5ed539f00b5f833ea0e5688adc95dcfa43940d99929e8316cb7f72d6b713e48e5028391cda0b70d0df1ed5bae60111d3186ba02a4d20d9990eeea0e43152a2c6c8c6dc80cd7ec791c4e9123e10e538cca7efcbbcce121f43296786f4bdeef1d29d213f0c3b729ddaf974f444db2eeaa2fdb8da0ca93244c6743696a70324eeb186c1d76c2487202c79d256a0a60210ab1d1d3472a6e7a644ad0186a207f5611949c05e055107be09f0728fe7932c830421260c8e89a65afec21ac2ff5f34a591534828ae08a2a723570b4bd6c9478d79d5f5d6e25b7e97dd0c475df1bc438a9f12ce97b414eb1d8e11ac58fd1162d66eb3c4808edd66ad5858695f0ed8e7967aa246f868e9b586a1ff06b90ac24f29d98e06cbdc455374d5818e7c6abbf95fbf593ae409df6f64a64687ad103a408b0785353fb89a538ee67b2a59f5b16ba7d561d0b146b4c6258eeefedeb7c17e05e36b326d769706a013992e792970346654dfb0a9855d5294be0700923b8866089082370a032cb610b345c8393e8dad181594e50f2eed3c325704f569503cc2dc3b5a7232362c3114db03c8e737981a90a9b02de86eb385adb5817e60a1bc2d36c3739347ee3dd727367b0eaaca247d83d5c6acc28037bf573bbf553e57d2d1c19bb8ab9a801719132b03805f58a0305859c428b2364df7b391cce6e0bf63c3c61bba9f56288f0026b474bb3ce581da17c8cccb2e7079be5775c7438f61bd8baf92319e21845daba227e56476819b95d76f2c07974df2b63f59643c96aff5df44c5b9bdd2f9095073a18dd1281d0d7461bf357d107fc3a334e987b68147a8eacc2169652b91294c28028fbe3186dc5433f9f39b4aa7e29d62d88a185ecc9cbe84a6bef80fcc201d42e6ce762565b6e5ab72931e44d938cc083970ca89518f874aacff837df968401c720fba0be4ec44bed963b5197f7fb014ef76d65b067562f2547ccc40c185272d27dd7a4221cd16394f57378b93128a9cfdb103af8caa746f3d2b750679297a852ba4bea3443d4fbd660f02c1daac3f064904491c92f094f9b7529c09e0635a2601cff99b12792ba141f3c86712fbb2b9a335acd7b7116d24c744cd39d25e7fcc81b14a3ad8244b8e4cdd64540fbc5c9b197ca6c8f8bebb5e5c6285d41ffc9a9bf77d13ae836e7a4780851fb0c7152d5deca049653001b10417d7db71d5f2df7c28db9fd11dcf93933e62b7e19279c1cebcd61ffdfde988b9e982d1227d0ae9b47e9fedd329d919677357eb708d149a39463b398b204b49363eb59ab151453e414dd63f30174c85e293d24f0ba64c04ca4a354faa714a6fec73a9990f036be4dfe169caa0262054f536554d653205b3fee32d71f7cd74fd2c0a3840554e36707c54aec2e9e91dc3897aee249a64ac81c0816a7f396b842a7e334e84ec7330fe0caf04e819c255bef892b90c6cbb6b1527b77e9ea4a5159eccf54916a30161d49ea4ae3a8c8c3b245a03eda2725be4e9d10b59b8278393bbc5bdbaa26d3c4cb7bc3812b4e847d274036db5838c72bf04b35803a99b622b4c42f1405e35afe4dbfe87b62e36b97791ec561f6110f14fb57402677dc9115ca387704e5bebd1db4547220e0e9e2233e6fcde37f03ffae46ad1a135b4eae688c73827d28115531bdda9e37637afea63abbf41160bc3ec35dba95ec5244a3bb0c421233eea3d57eca514ff3e4949d6788ff689d0ca7ca93a10586da02342feb7d6213dc1b8b4e3cf3a9580735f2dee0d2b73eb2451756b28a8f6fcf49fc44ab90b326f811be76b86e4c951e75c6e1c67e00e1a1af3563b59d4471fe9c2ddda9e75d00dce73e34319a2bb972db290219d14d7bd5c05d8c93cfc93838b8104ea94bf1baa809c7f985d563307631e96a173eb8a72fee6bc3a53ede915a2c41ce890ea5eceaf03ca2b6e165cfdc1fc4737c33ff86284204fda78fa80bcfd0071ecdc281b6b2199db5ae8edecaaab63ecc45e94ce51a424234f9593ca0a4b1482b150183c41faafb9f3586a11333b0fccffa47e61e66151b5122c3e1bf02fda762c383946c0b4121dedaa5ea8d41cd9979a6e30fd354064e5cc838e31da395d032634530ec795fc45fc28b283dfce1c5909ac3a846e6f32b98816588ee2d29e687645de4a3c0d9600acfb05beeb6134d8d968169648c88efc168dac9e27b6f09bb3fc88b1982b1710ce9d16c9444bac7c934a6704e04c9e9e861d0e45dc53aabeba1682cf48bd914d7ffe6a3fa54ff55300dd1f383210fe631896b06d6813be92a4f8d262d26a020678b9c3f488d68bd0bb65dc3d6456d89a7e3b8f329c22c74301ce68cd22decd89658ef9523eb2f2c2ce071972140797820b65944933207f2f4eee4d156dde39f452e36b0e8c207f6f2e94d05ca17b244508972cfb6f4188f8396e720cff8591f8ef31299ad95c913991e2bc89021b9b22344bbd657f5a7746afe51a6d935d016be54ad1feab372d05a2016f6b0b31b38af532d1eb6290b975331206401c9a01d65c90bfb94b98b7459a683132eff46ab8ef32e9e8413e3862b8851a5c8d0a2bca628e82b09ee04bf43bc2f88c8cbb7c2c5d0f38206fa4b4e5c3e5514508cc8f1f6d399bf52f01b9aefa029658b99e00b7d805889541f2f99dcbd9d938ee4ca25033b1e9a53f360498921e3857175feeba8adbf190ab89371f17f6660102c056fbd17ec65b6fbf82b41056df3ca448b0d0e7cdf6a87c4a00ab2a9a46d4cead80d4402ca705d9473b3f253c08f016685a001f6d17f3392015d199a3e0bad10debe94a8a102fc3a1af51f31da7038b53c56e0f2cb990b7f00515c2591e0784aa5cc77315481e04df81b3f546041093b333b97a3f5384674b419d0e01befe69dca8044e0e38f84b8e70e52c1c19dfcda9d0f0487aff43cc81a233d0d03442c64fa56b0ee9ba840df2f7a171c33f77e2720c0c0f9efbb37f1dd4f8d5785b5584b939e0d733898a7362b9720618567297bfe900544ad65657937d9c10fdddf6bb712b46d2c8efbfb40967ba01d5c18d3fd552d8e6d419e33ea96017c1528f3d953e0ef1260e3e00bccc25d439116c9b9b668b7011eec9fd774a24e8e0b48436efcb40b32f82be6bb1f546018f8376f302a3ed1d03f60f1c91130c217be0226a93d973accb576cfcad34526fccd8aefa1ab05a9503f8e5806638fe32e2ca67868b761156207188d6a673f562642f5f8c0bd729abd329f39660c3a113f610242a3880e3d4e7da64505f47f609de7ecf4d02c8238a8906f6af0ad7a7f2fb332872a795723b72d53d57543ccaa6e3530e7bda40e384b96be293c6163507566bce5381fb514fdef96ed16b741c02588c0399448cf877959441444523318e1f9bdd5f36013d9116197d781bceb1ccc8537a21dfdde85b2deee86cdfa79e0b89d130a32c1c523df4c085c2c33f1a6c501f8afd7664fdb9e1212cd6d438527ccec224037cd57ffdd16454636f258ef1de170b45bcfb30b6986b6b65c4b906e111aca090b581d6cba86c764fb54c2b7be5ef1af3f13de4cfcaf2d7e8cd83562aabfd1d90944b3bae6cb2fbe2198dd898ea93d93a4a3f95026a80324a780ed70de2ada5c86a1d19382ee6e1728895ffc138b421a1894817e50d02d3b23f4f5d9602092add60a749e283b36be262d17d8456e1ff169d6d9db3a47012009a8fd629d75bccdca033015da985e92fab278bc9f31a13e4e9caa260dc0525a69643cfed3b1f7deb09d9069757d3cb63b1061c419e6077476b48562f83858300443506d0e313d868d84079def8816bed8440b9f1cef62d7a8cc62cd83f4a6aef79c62eaa693fccc29973ac65d31eee2892b5f266408842976c884f601cad25fd65acbbb99fb7d0f67e6ab821659f8f3c4c8d5955b57e53b23ae65796f96a1b5df54564780288ea6ac3ddd0141b5fa19be7be364c27eb1624995cb0d9b0739e7140b04edecaba4f8855bc9f3af8318d90367a26451b7f5fb389b5ed48e7d0b2bbe9e3537db146d23e278cbd137cac1626e8cffc730abbb8f89cb5b3d88fc6452b9c4074956fb889cdba8bf1c565c12b4763da7ac3f152db8fc306373ee9df499ad4f0eac3e34c3bd3b725f3727c59b8d48afc95555478e32f1a0f62abc491084850acb6e0bc98b326dc97f7b2069130f00593ce49af941de7127f0453064b91a907bdf415a91ddcedce19a69bb30b177a6829151e548c56d341e7905d7bcf38d52bbc76a67868102a52124acc598fcf041dfceebdf6ade68fe46afdfa29a142198918247ca93cd710bc4f05178f03e8d104cf7a1d89dbe54bd7f224cb0c826d255cbf2c77e5da041382faba031ba8b2346586f858b77be356afd3b6d449d8da8da69fa8a98ea3ea48cbd3503ee57d7e21edb41e6011aefced544ba85575a02b666cdba370e99e82f61f25aacc6810f5c8efa1a34685960b80388fd0bf068b5110972b9eef5858317049eb38adfa539712cef31d4eb0d935d3df00799ee7570e574757258e4af79669abfa208d4aa4370bd65441a979b021e618c0c8fb388dbe1002445db8e2e5aff851810df66fb205d2e010a72cf84ddd2a3b8a1249b5c4a1be7a63e8dd83d9e2467c61736495d2822b701779407bdd4ab01fd8d9bd97d32845985db09aca618875ab0bac233a4c1a2225a9f9e0af9eb2f6e53d6c628b2d791d3c0df1db6fbe21786beeb8cdb491ec7a548904e41d96530d31616fe3fc7868a722f22c5d3c6a961c895aa9bde0f5b679f9c0894bcad7183bc887d54b31bb1b542031d31b8259f8edfa1e3f23df965cd856abd199bee9d8cdedd7fa4eca3b0fd8035a9e6bf68a16d195341df2b34eda95a89a1d8afd392e83560690f7be05cdacb1cb064c90dabd02b28a7154dd4f840256ffa9ebb1e5b0b351772a195e72ee9145601678b4acab5e78c2c91e46c0dbb18a59413d156e0a4932cc735ccbce4acfb4a033f712caec899da3b584c11b87309820ba17b40fa7a0da8835bb632130fa541c8ef7976fcb5993324466ac629a41a87867ed75b313fe96e669842c6f39c4c09b4c19f3ad476abc1cd915bb2f9ad659f1df9fc1b7cc4f32c632895eca2f874d81b0c3ac2d2e90937bb117d943cfdf63fef524d8c8da7ef3cd6334465c883f16d0e980759e262a2a3328d5b6abf006236955fd4b8910dda46ae9d376eac86ef4e210adc883c82c0e17a6354a85a83b367db71aaadf51cbd0c297dc2da8e9efa1fbd67aa226cd4a69c150d8c843ddadfa129bcc7ebbc9f9c6d81dcc9d8ed54c22d513f527f23ca4f215402136c9385f74f1361dc3086c4d8c0da537b63217c4660de9ea3e2230f2279d65c6653e02eaff23c8931cfeb8e5fffb1ce55ad6b410abe6f925089a103c04b867a5cf3fb1ad56dfbe9338829f8f9098fe6eeab88c2b87ac7ed654543fbc31280994026fb697c0134043a873ba073f097f835e1ffe5b3f4132c8c0eb3a4a885c2379489331bdd63fd063165dbb600e31770860d378f1d0bf1ff8b4c65cda6492a9bc407d3f7c91a916232672fa070e5a9cdc514d3a74866af2f11f83b898165c2d712681b7617d646d444030ceec0aa90dc695bb88ec1c9c8f1de8757d08c9ca63409b3a3dba33cd768463660c2e2c5855bd4d490eb334a2db335ee93f1912b1ec1a8fd41fb6858197f89996b9f9780065e4b94318c27d296e33f25a63e7b96bb412378656347c98199995732ae7cbc86f489bbfa780e4a8490a208098c0024330b032a23e606c78df1f837107dae01c7c28adf50d0e16e63a6aee804358f8aae14adc63d46a01c09c50f8df4a5a6812db936c11ff1a494785449319d191a45fa3ac90d7430d1117401ab94a569a4effcf519f74331d7da54a1720f7a2729c24062bc5246e8fb9f4eb4348a747120ec0410efe27ff7bf2f476accb111a75cf471296e4f89f44cdafb6a780f53fc1b7a52da161e79999b871fc00c7acd6ff2cf74ea5e34d3a306fa7ecc6af5afe93369e1cf03703e01b88d2cec4513040f08a31e9d6cc4202c3d75bc6967413357feed846cd65da97551c6b931f72e21a69fc50e0300a866934814ba06c3657d221141a1bf2e40761a73a0114bdc77a6260340ec96ca7f15525473bd0564a28e8003dfd10f1055861a01656f766bf5ec069fef58511e6fe799b8432980767088a532ce56e4c9714ad0c5d019a24ca60c2cad218bf7dcb54b15ecf23c8a2ec42f99da6c106baf600ee4d3c9da8345bdd8218e2baf28c5c3df99c1d0a953123c0f16ab8151a146c4a4f20e39c30f50e8ba34ac5d7e6a7b4ed84975ab5c02aa4cd9b0ac73178a92439b303f527f3a912512662708e8c73cc715fadb8fd92c81e3bde1de5348e9475fb02c3f70842d486df3a259fa6f423b16e375492fab6f816c4890815c7d6b84ec57885c271284437fc6aa6322aec978d0b9c476c7f3cadee1c0ab4010e81a7d37d045b1d4bf872174c8740962c798461fcecb63b41dae15406e36df46eca41132eca42393dc782b03bc63573e171cbf5fe9f126cb409fd8f05ce68322a52334e5f65144581d1f397fff56c4c901437fdd77f0a5417bc61038d3e30e37f29fea030f888958f12df1f51dd57f711631c50d140ba45e0673a002244c00d8287c8a0137ab94062197698d66daff4b1b96c71cc181c39c64e88c3033d2f167c39a60160271fe64c0a5241dff2b85810d8add7e5e9a46a34e501165243169781b1ae68370fcfe6117471fa0125010340f3c4ba6362e35512f4e126c6707e7af3a74d00ee7acea5e3e8bbbb0eeb25037a4afe9bfe9155af870bcca4534eb12b261d4db15c97bb3bf5b6adc087b1dea056a757d61be83a5163db3aee9a7b28160b1b108f8c50227c4e97c3f83964bf52cb512ddf268b99cc5bee096262435c9aeb84f4c8e44ce0da6ffb7387b8e8805b93543e290a23e18b4b4384cd2439753536ee62d5a2abe62ec0d0c0a4e23698c9002d6d6f2d7a89964a2f3b128f61463a61207f9c24e9efe87d58db84976d236e094a4e4e7332ee668f5248d7fe322d66dce600bec454aa7b8af972b453cea8dda0f1c640ca686be207db72a8bd49d9461d30e2e226ea09bfa55c941e8c800e8c6abc87f5caa1273d61c1dd7f67327f9800fa3181b67327543604711968e4874d6a7980e97c3fd6ba6afad9ebc1a399eb5e25c9265d71f34022a4f647651e3d1081fada8d2c5798d4c29eb3cda7525d223b19d405d8fb1fba22bef8f2ffaa32d104a796404c8d03b4c8079e9d4c832e3310a83a1d68369169c468d36666e68e6804b1594718a0c741765b73a106bf37f810702ab6ddd69bec9be2a0fa13d31afb52a6143230d22eb92e8bbcc704c5b7648192c711e0fa9c26c4ed1676f0a6db3f0b2fe67769b27b3143d2de4412324eaaeaf5715258e83b0e7efe841947dab58b7ad388820d41d424d7e20bf56de23e3f4fd1a385d879e4a44424dd0e5ae58849a6da0da3f4e34880e3d248147c6d0e71258265cfb7c76f0b6a3bf44e578cde4dde223f902aaa43c5d170459a7ee8be400f3e2b53a2cf124ac337f8a37dcd9191ef91c56bdbddb172b4ae14af5549fe410541be8f9cfb6e1f2aec4c70775e65c46f670adbf15956771e40243b3e07cf8ce6e4817534ab148d0094973ffb43474b41d472522a5c0f81c7c50b0dd2fa2d24543c1ab750bec4353da50c2836223382fce9c2ee439c1d723265d8f4042b86fe454bb2393479e04bcc3abd9c463a0fa8cb9fbe2aa0c3cf6468f52320759e8e8ad91d4f91f21883d39f42a4cb2f8138d448af460ecf387614c6d7c92898d276a10e7900035b760432ba27f402c63e740df99709271a40033e6e455485e793e4e086e650f8318b06fecd169ab6f2b17cc613355c519990bf24a3f115a394f2ad4b73da4bd1066fe1e5935e3410c3610ca1bc888ad5114dfd13c94c71c135820f4812eba7906dbe83053cce60c3d88fa161e84a14fdf1ea28b7d753618b6e2588792ea9167d78038fc3f1593e06b32da71363fb3f7004fda0269abccbede9882e98bf5179e36790aabc164e8c4eb60286260186c33bc449d3a5e6d0f02e0306b6de6ae60b2881a32f8d60e18f0cb1de1569c16321c62e461de2cdb9348f27ede112ca8838250c497f2f4f768c1f553ec4114d7bc58639bf204c018dc805f4135896faaf49095f03d0fc4e01ccbe831a453b010bf60f6c29a5919059e3814adc78328640be0d96306f027b7999a126fd0111d1459dd2fb0c360cbd0e43a95d26c68cbb81b1a70983a470398a8e4de773dee304f3979b3cb95e184b1e82518d5b5990dc5b512f57f482ca87ca11e66f1ad3b4d28c8243181bf551e8ce1c4c96762b6b929faada6e51cab9afe3b7e635c1d8e11ad28cbc1a4249aee1d024171b71e6a91c59f8e0e3953f6943e576d2eebc885d0c6731e9864789a33a1e47b0ef4126c0ae6bdf7c8db31acfc7f5e6a38ca5790bc1ce239552d36a4f50fd80c3f99d2036782a9b2c3916ab032e28fad4a7aea03c5f9425ba9306269ee490984fa728ba27446def8cfbf1588ebeecb6b3235fa5cf9cf75388876f8954c205ebda7c5b5c052f0504eb4730b6f14d6e70bf49ccc086dbb2e8211c31f82940f3573a017f9a2c081e42120a9fe5e1fef75abf5a81f53ad2da675117e9ff32205d13e2fa70fc1837f252dc4757fcf67366f51e56b08ec80a8c5f6a64fc4d0266f8960d969e898bbcffc25842439b1cfa1636c89d65a6d047df2d9aec4b953ba956ffe4cf9cf7d961e93283b2bcbc726d471d80be8e1ebaedd6727ac6005ac7e81a74327e66e83363d29ef9f8b5c958107a36cd4c9a072745374300eddd48d2f468277e3893bd280f612ee14506157a5a8d78bbd8c2f748506e1e83901ade062ad1e574b92ea4c7d5063509868bf5b0da8cd4297ec04c70832052e611caaa9b8a8711df56c5d157696bddc3999c5dd686c6df447a3f076cd47f756af33f3a18fa90067b5f07f0f19b40623788c216fee9cfea9b869c0bda7aa0332872f157245de9319d4ef89702875e75eac13b9afb348db6276f8a10166f5340cf957d335c089793cf8107903e1025ccaf1920a31f9d797c3e2c92ec28646bbeb052127f38187cc580033b41b48d079ae2d82708a904f90a44874f6f8d1fba39045e1f0e2c62441f9d0a950608e25f8d2d3bb6127c7a820691a11c74bc8c2ae315ca44de293b515d473ab06144c5874c13c430205f501536762170636410053619148710f9d368250ec107bed3204878723c51674a17c2460d0388a46199a0e1d222472f48c3065a82101c9d720c98d1498bdc0940877c5e2e5965caa420d2328805d984cb86493a54e828b2a549580995811f6d168870c2b5183df4280a10a2317916088638537442478090332a68e7091ebe390f8ec2535781a5e191113fd8390f600346ec4042b402f5a0119ab9eb43110f3e280cd2f972058a91811b2b127d4992c41031070fac214c13024e1e4c8afb4a380aace4e242a5c0163f80507020e140826492352489a6c86e880a24297502e4661f5e298380264b1326823d000ee5c6ceea1a68880b6441f561880a2a7b21aaca9c117b66fc9736254d7658460e12158b4b309d00948426dd5b30970021182a45833f0813b4c2fecc38318404ca6f5026342836020b07e0e032c6479e0e4193ac08b05cb63c411924f188e4510089aa32037e8299053d74f87190c1015009bc3f424a1b8c121da619b121e78a041b81964ea25d34cd3984c387271d0250419ac10894c972a00aeec1cc24c4eb14343820cdedab0702ad06666c06ec01f20ae1e2cdd9e3216205c63d803e520e3c7098bc59f606a1393558e1d3c9cb912862369865b535da530a4d089a0a615db6f34f1a01d8ef860538582099bd80a3f44346043371d21c12d1803236532aa85c458da8705277c7065b0e397204d60815c01c4e0a78baa354240f9a252d8ab4e1a323106f709af8d7a1f0b08a0b8fa348121c556131c7e96f47a9917e68f93485f850d1685194d628d29d0d531e55502b789a5a701305e5c1162d4677a23c09c1a0b9a511c29643114dca0cad1c896a105bb20981da13504b58bab5442a24b1a00b63000a9b3f8c5346f216ae1a649bc4845d98a3a34d6c48ba8941d3ab45dd224872e23439b2f685ae4db300e48ad4171b531d31fcf844e85b53e9c3609f2043162e0ea90b9a1aac645419a15c9a8e62e4c68da00fe58bb989c0118b136b36d438f0480e0c8c247a7d285075e19375aa8c34d92775dc03552128290901a092ad8f81b9d12050724c310eb87b6b54f561ace41568852606e08c986c2fce8084518522922e469cb092e4f6b48083d099e8c0aad2154f849e245e0031818b9a28703af038a40453983e404de7006e7148330056959a9c80c22b118f4ab049da12186a71be513766c8c3d42180416b2c1cb6a43b8892992aa0f4aca65a24c17181a3a4890d33c9839ba36c8d8c2763767c9a6128c69a8049ee33b5e4f44b9b8467819367bc88ea04022186e6ea1840c4c8ce92164158f26031c474c74f12085d2a909972f2ba90439b8520b1e4395817816b537283960b4242438d141e6e646c32839287c31125290abf44b8241f309c782097d7d51647adc995990c1635431d5b030b6b56cec418b88354e28cc85a6532c78513d304c1118e3e0d405c80486392468007248a3019c291e3e7881f3b2326ace25c95d243a4d1923f31c3b1193d0575c110d3a1d1e193f3cd0007532347ee9072d3047977a794a80b83b85499739cd364d31b2ac0116ffc6021149448ce445a3cb0420899178670dc70a22343888b2d01a1acbef0b1d2e7542135017f55084f16d9acfc1920d4028e0109ca812e1c0362dc1194b365518c574b16b237b0ae4943e09ce982818b151947402cd610c9788249c2e62e000711787ba2f864ad9053e7c6469ea311a968344a483529521d125b4ef4cc96b87802060d4e9b01502332102c28b9788a24fa08524de4004a511d0f25374c7d29c022edd3963f4b12ad9963186aca091b81a74ef199a9c38499a08806ace7fa546c73ccb25c31d1cb46a2e6b30d20b81eec19f3d620a22849866259dc9a32860a87485881b675556182537a4a4a49c98d13ee27c54c451e810d7273a781829f4eeb23410e7c004056e15a2334fd7003c6a39a511cf6d8289923c8e209b689eb04a61d44242fc2eac5a69d58f0c7b7298b26003e703c20f507c78a129ee6147271e120a61d88dbf31247f16a4af51284c18c2c1d0c477550e3276fc6beca5285a8b18fc68732bde78c4b830120fc820036d11107f1ab2b159d17155694206576001429312bbe4494005446e90009108751a32ebf844593232838285a73672ccfa11aeb823aa0ce09020b63be607adc4300e95b9af274644a44336b60a3b4b46bb30276d425698b03bd32f1123cae344cea74b9f18709d9290b8c51c004f23356a541c9d23a7646ee049935809348cc1903156342068c25589ec829b2d7a18728296d14c1719a68e10232931cc4605017018139e0b22c086184534251ce11420d2a645c0c323d2aa0549464a152a62bbb6898b608483789cef8f1b0d7a34e9e20af06080a318764141cf088a061831828a81cb35269a949d8e4068b541a042b3565ca28e0a02160ae858fb9d220750a1516d44bf1201d822404fa127587c4ca204570e093489c25738424aab4e7cc2227edcda32b30236ba628fca4d41b058a2470124e5a7c4d7880d28656a14080c32d3760c0698bc1e5ce8d36447af00462e858880b09b9cf48aeda931e2b08343e29c117c2d1bb868da8b5520a804811bca822d2e00d1001919c07af326e7a47e2c31409ec10081565012207157d31aa06d01987667dc64c286ef06120459cbf2ea7ab04ee90431d055100ad3164f1c805b603cf1050a51c3b1449f804e643446224350c22a550e469ce049f232506700dc91bb4f2d629169aa26a68e104c3125473e4545ea6335f486915c4a5658bccb1e62c8e05ddd23e2a1170405d1a99b97b15264bee7ee487fb54b01a5367bfb89af71753a762d44b9cdcab2c1df12946a45e49c0a43c4a93dc0fd30e2f806d114912a42d081790143ff4506528dcdf1f55666b5d78c93aa57f676dd52347ee558d182d72af5294c8bdaa0c221e5e8551b3766e3a5305019f766a6f6642f25f9f893f4679eee25e35888f3cc3fdfd09aa0a141584ba570192fbeeccd579fa8c4ad1aa4fb3aa3f32192fae1f87fb2cd9c278ca858fb7c9c2783a35c3c1e78e63843b95ea5ea5274f1ef7b9eeef4f504d4af7e78ca56ff29f746d76d13797e65e85c7ab5369a0741aad03ec8bffd0a474b39af42d309ed2cd80f1db5f3ca749dffc9ed2b6588ee3f78cab73542d77ec80e1a2e85ed5a50e35d48c37de96007c12ca6cc912ee5574dcbd6a4e151a390ef8b48bd6c9b37b559c2a38680454a19142a36c7f7f826fee556fa8556eaadab0a95a43278576a95293c6bd2a114d61551a438ea1b7150385fb0c1847dde599c2d9cfbdcaccbab685f388aa325564e26a2cbb578df1c279c45f5c25a63a8d03ddabc2b87b95dc3715fc8b73af02f3173ba57f21e6679fb4443cb755cddcabbe004aa3d1988f6e9e4add64b63e2f7e7d51a99b7b5597e660dfdedcf617f73dfb64411173da8a108567ee555caab6546571bfa954adf04c8ece55ea6c424efa943ea526dcabb46499a7523e6a8c16ed933eab7d67c9c1b1b12a2c56dcabae58d92aac5465658e8e3a4fe735d6aeb54bdab9764abba5dd6b07db8d8db583546adb2607c7c6dae4e0d8583b981c2c9342a36cd4b2e8dc4618bb4da5d13ec0b2b81acb6532dbd8d8740e14a4024aa3b30c288d52a954f9afcf4419d9732e210895f1e0ea348e2b94a567d5691c28b315cad2b3b2b23649d626ebaad4a814cd6b032c4806b7ac202c5838fbb94b41b9af4d0a960d1ad812bce35854fc0882116ce25e85634b908d7bd50d1beeae77159d98a097cbd1f92f7e5efd0e6065f50034886d5509bfad0a9051a38ac68cff4085f3576c0d13d44a9ec507be743ae75e2523461c6ddf9795db9683ecb6b3122a27671976c64a770e93ab546934accf2fd039b7a80a0646d9a07072b4598df609024e67ba3a1656d8b36a9f733d73f733193b660456caa4e9d0b369b3159866f5b725ade4ee01607cd0215dddaf04a46d45cba48aa601a680f302ca93263a0c0da765d53e3f9bced1689f5787d60bcc2b3affad5e1e24784567a5df10ea54ec390f82f2200a8c97b30beeae6488900f5b2bfe567c5fcc8716858b2b7c96399f74ce67350e2d3a48150c7c96399f743309b2e75cc20d6fc902e6e1b9ee527016a452fb96ace05e1f356fae4a0559f031d8da7351c8b7f60ef9d65e2277e72a5d09577757ab9a56b1d01056032abb85f0008de3d4a9d81654ceccbd2ad0bd4a1a75399ea7ee527086f376302f2f902a9b9233c98930788d6df0ca83ced30b742da45458f03997a0f6059a51fb02e3bd682060df73115d88b2ade707afce73b234ea54e3eece0bfe67b6623579d4ad58cb9d060c087a14dc3dc5ec4e9d8a51ab7195ea24c956528dce3e7250e7e9176ea9c822dd49e4c0b93a7bc974d2b79fa5d00d5757575703a2f1596175da27cbb3d9161e963fd94a11e75b28eca66cdd11027b71f7f5a52472e247ded609423b1c554f30bb2ac22d1389ee7d521305b64cf43921752af606b56212239a62c3060f651ebc3010ca7d17aad0b96d6caccab7d7273785ab42e7362f2f2faf688a175e84725f1e00e615000156a5f07820d3e0159dfff29c65565c5b738d3ecbd2e85ce296dc2997f3fb8be7b9791a27fb168934df2201e75b24ea7c8b44ec5b24007d8b44a16f91a851c0a56f735f9afc2728455373afb283ab8ae5a8557aee5ee55e95e7ee55ee552aeea2d2bec2b84dfae65e85e7ee555529aadcab5054ddb97b4c959fcd261a955a0d1414f49aa7f1dc27c77cd4e8ec423af5aa0a3abdbcfee2783ac7d3a652a9542a954ad7755dd7755dd74d2693c96432994c26dbb66ddbb66ddb9665599665599665d7766dd7766dd7766dd7766dd7766d994c2693c96432994c188661188661187edff77ddff77ddfe572b95c2e97cbe552a9542a954aa552a9745dd7755dd775dd6432994c2693c964b26ddbb66ddbb66d599665599665d7755dd7755dd7956532994c2693c9643261188661188661f87ddff77ddff77d97cbe572b95c2e974ba552a9542a954aa5d2755dd7755dd77593c96432994c2693c9b66ddbb66ddbb665599665599665579609bf4ba59b6c59374036f7135b693da63387675f955d9509f7aa12ee5575746969ee5573ee5572ee55247c2bcd018616d2c238f0afcf1947d9fabcf8aad33ea757ec15a58a39e33f2f6a2c2677288c6e7500e45b1d1af956874aee7ea0eacd0daf79c7369797d64c83437b6be6c9c1c9c935f39a6d7569706e7976666e63636eb06019e05c65237bce25a87bd2bf39dab7176da281e8c370e15dca5ff539cdf2c1ce9947a5c681551a3254a371b40fb06ffaa4f6c95e8082d119901ab7f092aeed45fbaa53a9d3cc4b6cf69a963572af4ab0e5ee52b6f6a27df21c576335f72aa496fb549ef15ce5d2f510a64dc654f93953abd23f6a55fa37e72e0523e50506c663634c56a96ca7543208ee3e954ea74d33e974be2b3c8b9a99a5fdfdc12d5b27c0c95813f7b1b1bc406a0700eebec50cd5e7845b368f3a9d03ff66bea4202c08b7ac20d3d0bd8a40d580bfe9b4f994fefd992d95ed9abb149ccece2df8870bba6f4f99b626afba72af125015c0bde2251b8d5f1cf354b0ea84c6f39f57da5bb3496786c6a6c64627d7444b936ba679490b673fafa7f4cf5d16ce2396585bca2c46a85faaaefc3e347fd4cd69b192b4034f97158fde16fd10c86120d28e44624188ec8502ab0b8c52890d9b65d6825412b4260bd6a10d611829a4a25224be03070e1d2d04aafc6c07f82d00c06b0f7cd67264080000b9ced569240033345d404055dd0670b51260e369fc87e61557a3f11c810201aaea3600ad758b9d4a03a752b40166687621e6bcfee66a942dabc0aeaadb00b8d62e56c955c56d42dde01715e47b46fbbc602f69d56b1d0364cb1bb1e6b2090ae8edd8a9122343047ec0742b1962abe5b4d52ebabb5e17f76a99fcd0d3db8bb6d256cfcc0ecb2929e68aad6184331f6ba40a4095957b55957bd5aed2eefbd17da772dfa84eb9fbaa440a8db2fdfd09aafdfd09aad985987bb4a84a942db14661847b374c39752a954609673ec299cf6b2fda179de569bc66626eaec66952bac0ba672015103a0716d2399f55996d7e068a8131fda8b1db93da07e8478ddda67374af8f3a05a456e53e593a0d1ca4f6399f55c2393a57e334b96f2b8c900d13e1cecf40aaf35925dca36e851170776aebc55715542b9c4af7e66afc8c0e52b736f04952d3d80ae5d8f9acced538cdf9ac3a9fd50d39dc9dea4607a983d43ef7ed8869439bbbb3ce27dd2e456a94a850a03e79eac46993a69dc9abe2aa324472f7dd8809cc7399f24c10335451a7625b1812f9df9f60b40fc31b0c62dcbdc6a27d3e1e3144e7bfc2699c37ed033020d5853b5b17fef6a56d69539a84e08081020406ec2b65ba421f3d835e510a9800a74ec5e4789e32c55631362c2aa5aec89be5e90cc97d3f72df8e1acd70b4f8c910d39d2833babc8840d6a59a9c317847521e0a4330cc381b2311b56148cd0c03191a44aa12324406213a480efc4c0fc998b2054e0408148f64002a1ab1c58b6c196f24b21d2ed844c676808aa9645498187c8cdc4981e1475b8c242d008491e061408ce7a11f9c2ec40e3138c475810ee9440a4629032512a9a0ecc0a033808be29c0c308c210278f8f5a173847102cb991a970e5130be0cf93c710120ef05273f02624cc16d2fd4a431baa10188da0bc33d49f3f000e8455c1f4cca3144442fba2635258c3aa1c28524c3aa061b42cc7021e65dc2a0f037bb78e1a3871eec45ea42edaa038d30133f5c64453905edd125b030916b67400b176e85578640e97078c743e1d4401b872c51d842b247c819d5a48dc2000dce1653887a42403094812254ec113a29b283cc96d50ae19e96310c749f1209db4c772460c929d522151b0897d293142dee8c2999d328234c8b22cead266dda0a2df2365d98a91b812d2ef419f4c1a1c9dde027431aa6fc889160f04d1c462b5cc46b0679ec49d274e78dc320dd1c04bb28653f06bdce6478694bc5287869a37ab495a79360993ea9de5a08802348e3ca4ce010704f500415418ce2c010104c00a76806f50d59d5510131ad9cc767954b881a97fe2479521504c4a7aeea82ab6a26c84291a83b5b55029b1c203171250795d10e129742b92aaa94466726d8a9faa1fe2d695335a5ab415d3e5afda018dc43d56f40a830f2084cf7887881c991e532458ce2e16104148fa9f34d002968a2044dc3524d9940e934c762542a390a180049c4624eeb2e724108128b2067d4a02272c28f85dd2107d66cab040b0a59c0e2b8a2acc04d542913d788a5c034182a2498b3852e108717a6b4263bd002e3baeafcc460f6096430870d8d3b296648233541b20750c1a2344c8c268b2f2d0f52174e016600dc30226d3618cbe0d764508af5c888263631364411554988e118338a5a694209d1548d19511622e4189dda5312edb00542326c2a240a408218393de41400fc532688b2039f40c026740ad61c429a0408d5c205cf191c26c05642893126540a7fa8348521a412df3f3bae25108aa514ff0e87a85902dbf9f38757066f4e900236fe2ccc91b124e041e9f749eb51219533f8b959b108d50c005bfc76d4cd605bbf357e732d9280ba5062f58b001627c7154e6d2b2a617ad810c880156436b9616f15012b6648f25a3b0180ba820d0783402efc84acd8eafb7276a74481be46743ef8a2a431f66df1626460cf58a7be2a252e42849c777d20121b75e9f206a66f409c3d175e4488e11bb46768aacda03b3e29119e3853a5adf1f9cd795e546306f89498046cc8638410dfef086442400be4dee201089db07c61da43c262cc5de3031e7b31a82060288810b4b7414d0c49566939a0a24c215e5ae10486ca7132d2b4264c292890158f91f26a08819ad8b178660c9f02d0098118490921e061d614c1cd9d0cc2784e643027604b559a6f84c08105ca4ee3fc5628d01b1d756be6f22258084d089a0ca9cda846cb024b190c921350368d4ac885cd2db9950ca19cf6a2553fc95194b136284761e083f234d4a884dd198854cf2a6408d598ecb5cf402145fcc018c6798ecd906b4a9ad2e769d566792f55b2e2f4136a2e6f93170e279309101e25b920e75c4692121caec5c9e2e170e1c775c4a6ee041a45c62d102b8ea16d10928231267247d9e6430cc238059587981e53a0e20a720481494fcdd1f3a41cc4710251ebb5996062ec4227277a3adeba88e9b020464fce4a091f50e440e93d1864a2a9074da63c4a8a18f95de575ca23b340d2a6313216f264fca0c28587699ab71668a330121b147948204ab138246054305aab5340c9c40c155a006c214ca3b5a8a26a5517a68788510588aab42f37185c545c450104f028d6c21344c3046ca64b102f0ab44b18de173a782b3c345a3b120910cf4de50660519c093cd713086804b530451e465d97b4e450a43832636d8d19221829e236ca113e6c6b0a0d38dc0990b2b8a110b553543ae3e501459c2622e6e84c4244f1230c2d4d87013f5094e8d1c408870e54504c101003cdee948dbbc6434e2b14614feed02468f0c2f8927167a3c55aa9f5417be7e6034b280677e0ee164c69a4b315e5c3894795daf46d61b078e28b1907048342bc9c2074c1ac909a763a8196e212a6b00b714e1c309545b866a6b42b74e790621437831d95408f601a18d6d849d3f481f2b33a76cc58c21057fad955b995a126f13699f0538621941c313f4c2841856093934a8d4cc879a8151664a2616295122a11f9052de1d884cd89c4310f25ea885843281a49558288800a500061e92981028487c51b6f5a25c016537950163a50d729508fac01f9a16e0d252e810821e4a9cb21b729911ed7943a12883e2920a356a9ce4111083d125950e92625e28a960295826e0c9b1730237362d0c538fb3245071431ba107c3ecc30dbc0e8b4d45ce1d9098430a74894a0b31099e71c16527895bca4809ba3862dc864224681b9b22f3fbe788abdcc09f041e5cd85b72fb940532ccd690a3d9083e287e00ac3093b727d13a6806abe30e5dc0641dc8875b223e70a08e8b18bf347020f1b465ce2285d903082c8a0849be10e093d42475973ea00496440f167acea5ec4854ab08454559a330ecea20445964e1ac4f538b5890427537971758860882c70981127a189e691e11b257098a6bcf133e81105dc99068b58b2942880ab0186b1f1c056165c5b9b0f245b1a33700aa84c11146484c8db230735462942c3f2d6c5b1efc7116681b716626a1815d9f1f076e6e30e974850e437035daa6a6349a0b8116a83e1cf1d170cdca6a05a7380692a845bd449079210525337186e5bfa502a94db9ef6e980c644dafa3c10b412d8a4415b92482a1e7c0a93a0ed69295224399fd2da38249212ad4a041c512a865b27277a2646d091cbee22b921470c89631fc579d032e28e81a5150c4e998df872a463c7161e3e223895f9fb53142d13a1464d88ad233156118631a04145a8e08820d1e0401d19f212110d54c81090674c089b24496c142977a86c6270582053264a0a361800ac34d22515d9d4fcd070424bf1842d6b93e2893e31dad6128d6114c575a770ed4a28423a8da2c46b533cc7b78b01a5350f4f0c9de6a4b0b216c0860e504d443c0801884fa00c0aa48809f16441229a89be0621f8b44af529f482142279164fedb8d9504be587c9a54230b6da9d2b9026a8e169a25624d18c19abe802b53c209b760808f3a586a1ec0433ca8f4b4d506c23c749842434e158a0c42182568d260f432c22a5c2a19b745e40a169b7b2e9e523c3860b9a48da2542b442434ecaa49909d3761c8910954683531f006e830ed3467445627cb4292e2d01980784667e8040736417498f880747e3120770efed8ea30dba260c0b457134b339856f231a8e56c02f5405d7fd8c910d1d0843dccfa6ac4d2481703f03ec3232e55d1bace4ee673a4a9ed79e3d3322211c4f2d3f66623868905a316787101027407c7de0b4640561c1386e5060ab8b93bbeb6d75f9d1f3aa46fba45d6fb6bacae8e979b97b00dfeaaae243dc0be3e934deea82e13e0bfef175c5b96f7581989f5b5dae07c6805b5d170005a3f356d7d61683532de6e8168348bec560d1dd9dc2748b81892d2e385c1f9c3a67b8b5a0d0d6022e3fb0b5e0cf3d0ee450584564885aa50aca7901eecd542fbe6a1ce8f5f7673636e6be0f19aa7a255891b1c2a260c79602015b5b6c7c6b4b438e2d248ebc2da49ebb4739b2a555893a15d322f42dad049b106356df1656a52d04a0dc1dce2005087c785e2120a0a0ec253048800f1472f778ea8e68eb00e1542947e329746c6c2f2a67c0548234aed2d75434d3cc5a76ab000ca74ec5a83c70c8357c8b009d3996ca04f4583157ac0d9bffaa4e41eacf1064a7d207fcf3db1af0e393a71a5b035cc90eb2d4a75f600bcbcc97c9a18dd7f5956556969fcbd79de7b0983a0d9356030ba75b5774edf6f23b0bba12342a10001016a82234b07268050ae01289948037889c5205c07277081b9884d87a13aff615b6027062c5d6b0aa543af5b3ba6ab44f706c0c50303a071656ab51b63a41eec9126d09c0a75dde1c58286f016823f6ecdb0b147c3ea56665651ec6c4bca8339fd786685f5c05fcfbe3f3021c9cfba6d5d80b2af592f3129b6e288456a95240af3e366a601f1d144e0a8db251a97f7f31da195b5c8dd3a86953a95ae13c826a36cf6a54ea5f0c859bce71d46a5fb40e0a4785c24da56a542934cae67cd2cd54eabc17c7510be71155c2f98dcd8c3a0785a342e14c40e1a84ec1392a353a0f36a1706e4540c0630c775753dc03fd9be7e46436ea54ec2f10706c2c2a057c12a6e273f75930909b330766357996aacd55698953924ecda70a885165681a5bdfdfdfec84ee3939144eab7d7fd579ae2a7de3a39e55a9d2aaf4add9944ae9e6594d9a36cff3ac46352b8ce3146cb0025bb5beeb979082e233a0746eaf6fc53cf5eab07a95797590a352e89c5648289d028e2ae43e2a898c14c5c95d506e6b42a374d3793abbc88b4aa348444191a2dabcc6bc7a0859820c052754157797202186fb441df2296e0e2cace6513f9da9ced4199ab727cf7f2da451bf67fc170fce090e6139f21005471e1a73e421b82db442df424be25b6886dc7d8147a8b080b965c6c6b7cc02f9d61903df3aa3f3ad33aa6f9d39f1adb339be75f6c8b7ce4af9169a976fa19dd0eadac2c2c24af4c3b1123971ac44651c2b511dc74a44c8b112353a96a22ac752e4c0b114c18ea5a88463290a742c453e1c4b1114c752c4c6b1142d3a9622488ea5e893632d42e0588b226461212800008947c691786f1c89e7c79178891c8957ca912a908e54c1c0912ac20200c06214e4588c901c8b319463319a722c420192605e0d922d02af0509ba68c43992c6ec481a301c49038c2369f871248d508eac81e5c81aab236bd039b286d491359e38b2c61f47d680e4481b091c69a382236d281d69e3cd9136a28eb461e8481b4d1c69038c236d283ad2862247da00e5c81b011c790382236f6870e40da6236f8c70e40d3d47dea03af2c60e47de4074e48d2b8ebc41c69137de38f2862147def894c541cf911cf81cc9c1852339f870f70309b220247a160445cf8260c8b3206cf2ac08559e1501e9591122785684d5b32298795684110bb6f69a6f6d14beb5a7beb50d7d6b2fb93265c0b54c35702d535fee8ec4c2ea93c5b1faac71ac3e7c1cabcf22c7ea33c9b1fa90722c3f568ee5078163f981e0587eb448b9ae458ae95aa446b81629a76b915a11608080ac2c11531c29628c2345c471a4883b8e1441c891222639528426478a7874e4882b478e50e0c811161c390276e48834478e6873e408138e1cc1e7c811828e1c31c391237a38720413478ef8e2c8116f1c39828f2347284262e509e25879a438561e348e95c78e63e509e4ee580d30383a32c300476690e0c80c648ecc40e7c80c808ecc60c391199608c0bab3c3b1ee1871ac3b4e1ceb8e15c7ba33c6b1eeb87177035ac80a551c59418c232bc0716485408eace0c891151a1d590194232b9c72a405048eb4f0e5480b4b475a08e1480b768eb4b0f7008081018d6b8ed5a8c2b11a5f3856e30dc76ae4e1588d888ed598c5b11acd3856a31cc76ae4e3588d8b1cabb1d1b11a4d3956262bc7ca84c0b1323170ac4c121c2b1386ac2b2f198ef4f2e1482f288ef4cae2482f338ef47ae3482f3d8ef432e4482f4b8ef40ae548098fe02ac182449eb50093672d10e5595c063c8b4b8167715df02cae0e9ec515c795604b18476ea9e3c82d8a1cb9659223b79802b0a08198231bbc8e6ce0c1910d4438b2c1d65656842c0ace95c5cb91593438320becc82c6c8ecc82e7c82c828eccc2c391599238328b16476679e3c82c8b1c99059423b55839528b03476af9e0482d271ca98505022472eb40294e8e2c85ca918e041ce908c1918e618e742473a4e308473a3a1de928e848471e8e747ce24847318e7474e348c745473a3672a42328479a22e04853101c694acc91a6c81ca9958585800001015908cc781602389e85408f672120e459081a7916024c9e85e093672130b580c116968216a71c4938c09184121c49a87424a1084712a2702461d591843b1c49d8c491845f1c4918c79184891c49d8e8c8c22b4716467077a41750f0a08096840453363872ca07474eb173e414d991530a1d39458823a72871e494288e9cd2c69153ec38720a23474ec1e4c8298e8ea422c09154ba1c49658323a9b839928a9d23a90022bb3095712d4c705c0b531fd7c2f4c8b5303dba56230377bf42ba01e54837a81cf9068023df2070e41b068e7c03e6ee08b4b01668a539526bce915a2a1ca915e848ad42476af170a4d613476a997177ab01050618b0d272028e3c6b4ff2acedc9b3f629cfaa42e059550d3cab0accb3aa58cfaa3af3acaa38cfaa42e15955b367554d3dab6a86675501f1acaa43cfaadae259556c3cab8a8e6755f5713771d868334aa4ce303a4b1231c2aae09e57a0546ae26a8018d56b80d8d41985ba7066f827f1635b1edc1d53a1412cdc770477c770610b125218c279c9610ce4a3369767af0dd237175ed2bda7a27004c7d32a396a73947484e57a7a5e651a319267b4b1b1b1b13c2d4fa480cbd98848dacce8dee0eed8e4e0d6bcdcdd30b2db478cb8bb9e5bdd5b5e3384d9dc5cd32d2f4dcecc445c5d9e9d999b1e75ce2233ae28d1fd5b456beebe33b1f012a3fe5d5d5d79d580aa2c79b693081946354434a38e4a8df9aa7a7a18cac8a2d2370b80523ab4aa342a7d438c0dd131540586bb1b920dc51952220d79799842918e14b2e2d5994a8dc3009f8448429408312214c7ffa675de84d0eaee48425b8402302e5207bd305c40321a22194d2019d3de9083189d701e1b9ba37d7ccfb96f5a1db4c1bd7611f77d3884c83b410a82119da9d439af0f52d0963bf52fee2b232b74ee0994657564a0c01581c800818aeeed400262e3fe5980e2a67f22fd29e37f92fca9bad7d806af316add87fd11d0b858298923fd10bad7989797971f10ee1ea38f20377df81ecca6e035364647750a5277813d4d9c149fd521eda1a3e3b7f6acb92772d7161659388dc57731831e52ee5e483d651cc305a49e2a860b7a5c77c770212f0f290c17f2349140ed1b9c652fb1b8cf6fae8a220fa1fb0522f39039860bd26ab4cffd7380921f069e2678c4fcfdc54d3c34dcbdcd0de1e172e49d1d82419076e0ec2176e8ecac0d1932048d73c1a008e7c30ff7177bd1be3c8a1bdc8dd4391318cf7c638e74a0b87b8d55e539b08faec5fc3607d59c18732aa0b189cd6ad4c03e3ab1c0beea2cdd0becabf6d1890dce7d7ccf981a9d03a5d30d5e627c16aa8082d139daa78741cad7c26b43544a8de7e9053d393076a306f6d17905f6d1a955a56f7f7dd5393d2fc0cd9fb701e5ee7c6d0cb8a0b3cd58d80b3559dcfd81ac69746f24c4451fb5b966cba9817d550e817dd5bc1673342fb0af1ad857cdfbaab55105330e7a703deff2bcfa9c50646056860b892054dcddb1e8b4e9e0efff32eabc110128837074223c70981f2aac3903ddddeff628589169f4dca5d0beb434177c9ea179d26a5e9a02ee4ecd9b676822a946d1c4454f2ce3ee7955e91f35d1883ba1530b67bf59cfa15069625ae206a7266239150d2977348d1c8d1f348968a2b87b150b3434dcc921120d9d570503a37d7ad15535867acd51e9d6823cd3b80d370e1b22dcd9ce8c98439ab11308f8248c01a3d4b84d06dbd8585e3496b350c6712a862ca33de6236c56f9f6fa4acc7bee9314bdad8d1a63e7f333da3737cb52b4ea3c27f7a5cd6dd4bf3fb32a356ea352e3366ae13cc24420e0748d4dfa37c7478dd70201a76bd4421269546a9bac332b8cffa885f30899fa479d65295a0be9db741eac52e3b6191acf5509e7b7ba5996baed093ae734bb107371354e9bce84b11b753a5709e737eafc17d837a593d2c95268946d2a559b06023eeda45d14b89788f6b989e9e979fdfd2111f36a31bf7989ed95a84adfaa662da46dd44218d428565a04f251e3b538bab5ea3c1717ad6b769856a56fd43f38a994ce8d706f4e9eabd2372a9bf44c9ec67c7353a99adbdfb42e966b4ee7b81aa7616974af31af3a2c77bcc6bcbcbcaad2a86f03db6bdfb041f5f24293a37585d3aad7181e8a2b46bc4ec7990d41c5182ba8532b6055ac20abac5551e0627a18f6a880152e8c8d4de7b1313a2f0d4f3bba36e8df3c2706fd9be7a46fd4782ded19ed934ed1aad237c0a75de1b44a9d9fd1795693a36653a9da336d9ed5a4d3f94e3a9defaad1796e2fda379f45a56f84b33ccf6a7dd01452e0c8526248c9930241ca82bc0748289f063d717c82840ed2c90668b42f8c0a8df641e973a7ce83f24c15ccab0a4ae3d9599d0ab2c8f31a239c67a8d704335d8b062e31401ab07b40e6091457aa2b616824c944aa8b871d0103f2fa2e84c09a2081cd9220411b80f0c04183ae2713ac2d68a16f57a97bfa1757a3718b79b06f8f05759ea1d5d9efd957a56a54ee1a8dfb0e9446dddf71068ca3ee3acd06fcd35e804f42f7edb7574cddbf9057779ffbdb79437cee7bcf7d43f7fc010c5148dcf767f6ec0b943efb026759ea469d67b5ea3c3757a56f7e4f695b752a0d246c52a7f3605fb46e1acf7f68d5673c153c4b6ad2cbdbb2fb7eba6fa7fb8eddb79efbce73df2adc379efb4ee1be51b8ef3bf77dc27ddbb96f13eebb84fbae73df74ee7bce7dcbb96f12ee3bce7dc3b9ef37f7ede6bedbdcf788cde6bed7dc7708f7ade6be9bee3bcd7da3b9ef33f76de6be4160b9ef0f5364912a2e261721743e6a9ce79e027948c7a57c70af52fbdae6e6b9ea3cd79ce7aaf3dc3ca726079ddb4644a57d53a95c1f61732a8d4afba0735bb58fb029fb3de3b36a7436314fa56ef22c4715d1627ef3abce4da55169dfec579d8bf6b9e9e945a56751bd0d182e38a7731c61ec568df6b91506bb09f37d151e8eec035d2ef8a3423f8e470b1f1fc3736477c002f338ba60e8047e401e90529696b006f74d209070265dccbecfa7ea8f6001c7c90ea17d15a6207e890c9433d182c7cb2076f9394190fe139244fd0586c3e310e8a04b2438f2932c3df8286ea5dc0feeca267242d1659888dd39c981274121c69d1090be070e4c4f3489cdf7109bf4555040784dc6d3f381f11e54232e1a91abc8affe68aff2c8e86a8258dfa388fd2b066f34e1190d6f94a5e5a30cc1782a778d368b54465ed111b798bc239fc1ae8e4f283bf08a2fc2e8b33168cee389270db7e2ea6ffc18e0a9d292786315bffd6618f1182c91e9980791bf838464571150f2ee9443b732e7e2cb008a6d2b5cfa7c6013cdb73133c8977d70da549cc1ffc0c6b9f51048e5cc491a3e0fc7d3b160fdd97b0cbdf93b191a6da7a308479e98dbed83c447fa18b3e167a84f9340822ee406e87f3a04ba9f287ebe06aae1a0b0f8b804011d7ed02946ee60caa19d2a4ae451fc1f5d768accd750a047ef351bb8559e385ff4b7c54785216a2bebfa27da70ed1e09da3703e6dc8424b5f93093c2b89b0e460e048a1e3f9340d087b090f10f1a71f91e04eb165440c7abe0516e0a4c347d1a0c1bba8b02d86fa93bdb895f777e644ee3c3b040c4e73462d110b8ec3c600af619bfea7c10260cafc840ff813e6d8e294ce14ba9b01f7888c5315c60a2c524d870409e16f998aa161e9d53b8094594f987b63bef9469cf6b9065d108c24cdfcd9947ff0a52f7f264625701b3c42f41c7b41fa586872286d2333a3ddd4c2c94ae0182ede19e6bbb0d0fccffe9141acd13bcef528acbcf7152391b37835fc2d19a6379d57422013d1c1004a55b5d92e403f83cd0cf00ef6a2428f8b317703f00cf89cd37a888c709d0b5c3bc017aaaac469bf932c415b87276942ea67e931a353bcd21430fea05a1ad084e93cfc007c363c9e97946217aec317564df318a933b5a32f861d0244fb646f9675c167772ce8f9b6541f072ee90382146739e76657b9b8da79dd0a0f11ca074d810b0b06f635b6d1e889c3896b9a8e71950e001953776916a1327d41adc7baa59fe1083553b205be37f1cabf69923207e869f7857b0d0c04169f0f3723dba7c520603ba0f2fd5578a22b6e3ec45fe088c800db7e67d23b1a47f9852c58d78e2a3057c59f22e073b9e8406322f0104fa982a283a8e4402769e46041e8f07235fd4a8cb63a069d22194765e841c88ffd0e4f533300e3b6f0f96f3bd685f472b922b7884a3db1e59ce62c5d35720defe46198f8f64aacf53f12ab427b548f4066830e85260969c07db49174a19e44ec422ded749911b26d9e42d8c4e3ea25485fdb7e8ed1780c8a31f5331f8b3be00de9e887b1579c2e820a94afd09ea9eed69ed84c791f2b7edf875792c3d56ec078192b862bb7ce6d89247e082eccf2c7dbc12290d7f54557408a0acf814eff47a16079da966c19944e49fc06094cf7bf8f81429557e42011fda530c2e4e2188dfb62106d4474855603bb56278254b5b2e6a6cf5346e607c1d4e7d9e12228c0f95cce2424c1c70185c725f8a8676357796788b3a221e020c959b5944e20fe2c347d30189df1144cac1d000f22f361878b7468834234759cfa451fb63cf170e07d2076fd00eba993467362738005ef681c76ebc10c2114920d1641ca5f9b3511276a22028beca11c957cd12b9a4b979bf00837c6722a01760c7e4cb0e21be0f3f341c4ecb802e6c62f7238a1c78421abcde1d24e1708ea878451d1c6948723a7e89a005ee044fe32fe93ba29b813c7cacc99a2f10c4c3ebe461d1625509bf0247154ffa40e069550c5e8e073bef43a1495fd110c52bb408f341585479a426af9de21225df44c6e773281e782f848c3ed40fb93741e6623b07c5b913530c1d6805cd73f17d780b871ebc906dc8a3d042e52c1d2c1a8006b8b75168937e13d7c325bdd1fb3ec449aea64b8adfb10a72ed49d1bd4a08710e2178b8933f886e274a2657f04080c363830ef815c8fd16cd7d96bfe4b78d513e11a893ff8288d32fdef9f1b81a513622ba48bf24c5d5863ed8f4163aa8704f889b3ccf004d3e0ad9e5fba4a2b393f0c9bf07cb127dc836e6ef2737da4ad2cbe302133f4285093ee90c875ef454c0bb242ebf8b908d23c16365b7a930e3c982b8e75933f839a250fa0866065d4c240b1b0ac3cb491878bd4e9e4c7f25c753cb9df8f8a33820f6a7429cfe0688f5031bd1b89954736e09cdf0b3d85a6c2f0326bc8aa34dfee7cdcc573a50c203959a5f529e44ce7cc1e702cad4d07a7c6dcff6624fd39154cacd9070d17185161d8d4cc463450d8e818f9ae75468eae3e0b9fb01382c7c032da79ead06886fe08175ea214eceac84f82c40e87851746cec3e875cbcc932d32f3135e82662119a8bcbc5ebf8c446cf42ea7c7bd6e6ed7402f0335e1cf84e63089dbdcba23738387436891bf698295f2fe5ca95e329c53cc099baa75313f267aeac1b48ddd4535589f2633e24fd8e1cbf4985faf18d2d006d2a0f049ec30f090f92f4e0463881d25604d4700a46f65c86060f4f46c6db1370e4c7c718aab3e1440d700e8b9a5bfaa7c787b2bb734670293ed018a01d23abfa6a3e85d806c4ecf01d7406f42e24c7c970f8f01b0edd27b4ffb6e08552be666ef9254e58f92b3962dc431f9d3f61e2e54b2405721b5c45b40bb6336e038dc7e6c232f075ce9e4b5160c4eba679fc0f104f8ea786090f3566f0094b58e9052c56f77029a96dbc307b4d04fe68326cb8b89d1c4e5f53b8c6070432a1bf3080f80d3448e81dd14b0f77644fcf95a2f3abe76921cf0c0ee744e44790f21fc0a3e3f17c29f304d8aed78a73e0af9430768d055cde8615f96f3c71f20f0e3f6c417c2278f5508a2ef49af91319670fc070e0efeaa6ce270115e7228867670150c7bf10a27a6512931fc852e7033892e497841479397730bd14b814cea5e5cbafc972e0842638dd45b4be930e63fe4e141b0d2302f1477e2c7227813e3d1e76c5be23d1c9179170a347e401f8071614ec2947a23c821d71db541c450f47d28f9fc4327e8e45129bcccedf8b1a93df4c0925af23d4fb6a8834791e9a8b6302337d371b7cf608463f5ea314eb5d746c7cb6c4f73aca72b88f13875e0a441aff429aedc41685af879185535824f820b4f4fe86630647f16cfcb9b6103ec8c981eff983e4192b65da888e74dc4dcdd16181617e0d2a1c7a0ecfd5df80cf5c0b5827af1335fbc02946dc87dd845fe2b4fb2182c8e82f8078b8de1e487bc6d60a6701e5f52409071c49c1856ffa43e68e1fa26c3f2d27af100a94a7faf2e8cd2aa069b3028dae0086d4750802782a7082f893bc3b1f6491896dc74beb5ca804d937fe7c7c965202b4a7b01cef08c3822e9cc3fe128b3d17a3b3c821e4a07bb94647fecf1d07bda046173f15494f23aac1f81cffe57b5c90712e4a555a51982abf488f906d15c8d22b4d3d7226ce078e22c9072d63859b731a42e9f3ca243c5817469bd11a316f8bd96c084c0c9e66c1025da6880f7f1a22d24c28a8fe6e02de46b2e2920f00c4676fb191f0115740788e48a85c87963e3f5525cfd7515834fbc6c3610c21d3606c05277129cf7653a5ee9b5984ef966890ab48d2d42a342ddfaf82bfd5263e4fa607d19eb6489e47218caf8b43e6d18459a0dd2e505e0f001897a275e1132f9d6953400af8272c0e5e452fcaaf61327047e9e33ba1b29fba20f14fe830b299114afd9c4d6bda4f9194072cd4a52915aa793274ab0ff253c22104a6f036383a388bbde2339101f02c2d54fb1382458ee146a407125b71b02b230ead64c08d6881a12b4128f49a18b83bc155d2af14b8f89953259fc2057631274e3ecb1a423fc585a307d363e095c8eafecf12f911308c1c858e0a5e057ce2a3d2405d8c27f73f7192eee4821d2f81006fdf88a3e739c591db031ce03d89479bb41e3803df45a7f0ed145af076e6333fd332c23d829d23b61973343faaecaf0663de0ec2aad1b450f003eea98de2c827e74a7ae9133780fc20d3f979b0f407aa32e6b96050bf854a999f93e1e6fb10a0e42d63a83794d4c51171fae45c3a7c788c64d523c0e1e5583ea9f1b646183687ede01ddd6dd27cc2c09e4d1c984f90d4e581a0126c413f9a7c8f27ae47e48b6e0312122fa5e3c05fc589e3c9c02e3762098ceba122c21d095af71940adcf73e6509b8123f076ae86b88cc61f5ee9c8a48dc090196fe047c0fbc139e181826c68e525f907e36cd98709327d84386ff405065d9e1082419f0b7cf4549438b800455a1e41058b5dc90d1797700650739d79fd2c916cdf998ab9221bf0d6fb73e5efee70da81d6310f81d1e3832902e13d4eecf1c53c344e00429dd73385e68599d6b82047541f49539c0d0671ceb7a47f088d40781669dfaf9864c945ec68d445fcf0f89a942b8fe64b1e8f334863231a25e95754d5b81cea98f74121a309cdfd6f5aa4751d1059fc44d7854ff405e8d72880ed1a02e07c469a53eea900b88e0043f4273d46dc4f5adc5fd2b2f4d694065fe4a91c1590eace3068e1f510c9f3eb2705ff4605a65734898c1b1ab1fc40692a9772e1c62e1386f79ab0ec71b91c3b9e84f24b1f9ecae1160655712b1ca87e6cc1182f93a3fb1aa9d6f80d008e6f2495a2c6c222f1283f43ffdd00f1364c19713a672abc243592f4f2ac912f151c3a1c1c77ce05559b23fae5f0196c8aec2ccec963e7f2f1e6f0f0050bae7635c99aff3a2cdf27848a37b1673c273c24bfa10313975047882761c4c4dbc8a21ec70b0f1b8ba02c1f65aac6a612f2b9221a22ffa14093370ca1df11d9f5792c217136879678231628fa0fbae9396919a40f3d85fa0378497c12df25dfea80e12b9088f47622d479398d5c9c0562a857f4e4f4421a5a6d3780fde809475d6aacce23986bf25a7b3e7c1447f32ab868f151c9453ec7708e6fe549db68d42471afaf099a8b431fa771a17043b211eaf71e723f2892e0790090b30fb0597b0f189cec0e04b23c98ac335da5d03fde8b2aba4a94377f894f89972e69732c094a7e9631f8d6991c9f18a7e511d320d90a5e34fa0196d1e65b5be0ad132c9a1089e12b651a1a4bd290679049c42ee160ea078c0cead500287f11a8f14f8400e0802e326946b6d20ba013f40c36c27ece1b313b838a427fa177410f3a6b3a04e9a50fa3e3d06d0c76d289558d1eae0c54c71183f33a3a553d154c39bcc5e127cff049f129a801dc398a44712b8386bb8c1ffa1f81568da7668f670951e119781ae4589cdc5e53043afe43868a672365e22bc630f8272f04df6489fd438078dccb2049df6805c9b55e588ff8a2e8851ca1afc8d08ba7024194969a9d7009f1aa8b58cdffe724ed05f1fab8973495fe4218169f17228be3b0e1e239ec68e1a502135f48b383233a43f43a5098bbc233954f92127fa340c04f54dc9ee44c881fa335e9d7d421f23000475c716fc0938113630f00f2e2d78049e238f688b70147753618e27e514801d7310fafa348c7334a88f44966006e402f9438a945403e2dedc61379c6700816c69ed12939e1a5062ec76d9487b102e6ef5e98d12dc45c701f8cd0ecc4c053dfa8d542e701b0c1536109f4568c5a9fe280a13f91a5c3bfb00ae2c925989c0bf4cc7f8ae3c3e51c3fdeef4b1bf73efe1a8ee17b6134e457f492fc150101bf74c3f3a368345f140a497e4a2ccc261208e9344c54b5a84d6c9ea2052afdc304de17421a744d18127dd598496ea094923f6b83491712e1e85814da575332f7775678d9a020f9f9a7091fb48e54c319932cbc4515267f2182a14baa74c44bfd88a295b4357e5c54d3ded085cda9202173008b5d5e91238b6d688e7f8590336fe88e82a7f8e3e90fd500f41ec844dfaf4725c75ba1e60a8894bd9933886b487ef268aa3cfe9664d46b397462d7ad611e4d140aef42cc1d5f1209f0bfa47df20c6e001d4d89771c9360cfa340e933ba38fa3c8a77dee6ac71f729b0f59e50f5e90e0aec7c08b7b9c71055fc1b964c6924a808bf921d994331533ea05bda7a3055f21a6c80b81b370e7c8906aec7d261c0c769d3da42c25cb9dc14b6dfb0a691dff9f3b8ff68f9e07ed6423f6ba13c193060de8d9086c72325a75d37951c314a533ba832f58b98003d6bc08a7759d468678979f83466a4ad8455f93f62c4e83f85be9e91a5485e4ad28da7ca51b793c8c173f21261abd940f57ee0390e8469c3c12e91da3feed8f9466f143c5f0633ae440dcfcbde347a2ec308fa4598326730a8cb37a824e1ebca4c9dcd40c85f2d28741c24f9fdd470e80d844c79951f5c1a0605217fa729d07661a2c543911be373d02cf9e067d03f2c51f93d070eedb03e0c9e054cd4b348e19e82920cfbf91a5f8bcc7b6b56c7cf1cfd5cebca9b571b42a6b53ca9fc952a60bbc15f78b94454b404c1097f4aaf8c47613cfab9b70e3bb0cfa9bfa2c4d4b62b60e0199b297ec31892aff0278716f5c28d0b22647b3625927c9c181eb6184913de43dd89dd272286cb5e4b362b8ac7379788f8437db6781b20a1361b84a80b804b7c03a72e79271a129e908ff90e191ce92ed2109ec0108866e2b6c79b36d61c4982352750c182fbf013f46100cd6d4d1cdc7e94992dbf02f0ca430d4ed99dce34ff4010e4e36984e2cf5838b439ec10e513da1ab810a5da2790e4e6d24a679e0a94c38793618113d892db63a6b47052cb2d6e044dcd1b50f2d97a77a478db1350eea0c2de87a509d2655c4f6f48059f7e6223ccb522479d47b8c507492f69168a14fca41d7a1b9e7178517ad434de9226cf2549ba137931e48a2b2cbd0d2519170268d16e31a1f99da1762bcabaf17e5e8ec682c6e892d8047d7446900fe439748446088fd7b7a7093548f421ba6c6cf6cfc45bc891479b49ff389616a24701a3e64955a5e80764419c4d5e151791a98797e8fae34fba1ebc159bbb91a879f84e2538bc03a9fc071c357c0d668c1f034888beb384f045252a7302636ccf0254831da12ac4f76df9db0358b71f4268e72d5dadf81475b8b8f28cd967e214e9abe025be975cd7b7e96bfa9a8585b33974e1d32cd136611d2c7e879475143302df9c90f68449145d05a83bdeb6457abd36595a30ec8acba0b4c897a9e02f03e3e0b1ea483d872cf16f3294e4c33a65d2d1082e3cc501ac0f0206fa987054da841cc95c8bc1ec730a2df1221558fd66dae7138c8570b9267a7e038902dbe9a7d0e344c1e10a5290f0256a36682d6c2efc064d530714b7713031c0761b85389e2691a10f11c0d145316afd23d5c55f5903b02f3d62f42dacd079870960fcc709acfdba579ec0400e8fa2c05dc473ebc72c29f2470ffef40ea5ec6a6880f132336d4e23714ee395aae1671c987a4a60007f0e13808793ca8b0fe280f178d5510f66e39176676c7212eb02b78408ca09b56578266e277cfdb26033f3e4714e55e07c8727749ed25edec6fbe95780f0f5b19ff983029b34199922ff221185dda1c08ebf54a8b80981647abf4f31361c3f26be8d04a0d7c21ae06b5c7c365b883e9fc74908dd2602a9bfc2428f236bd0b91b2c8eafc5503ddc9a307b531d17fe864f0b6db896e78c3434f938305478853959360530442ee6ccf0783ae8df13e99486d649e1132c59d166d841ff0240a0afdd20f56109a84f618d1b6fa1c5b959c337ce78294ccbc193e59f2f62ad45d8e8659b12f5802a991c4d1e2bbf2368fa5f0483ec1204a28e182b7eab4484fbedf8a4d3e8f571355d531c920ee97f1da2ade52f899bb5643bcc7bc991e8e8b1f1dc69e30d0ca59a2e4ea20f3046f8558e22b9e00a476d27eaf5647a14691705003c9a41773ed0db8aff537db3b5c0e9e3640866ec1c768b9c5586d10c14117dbca3d00ec4b2e0624a42380a0d21de499724ee034898cb78558772038737e3b0deb044ec9678383e10b9549f566776468098bc000e7c7461190a0f64cee0462334f6191a41d14d6615b74bc2c9f1e010731573d0f69c6011374360c70bb824c81b61d0f493e0d8f8932fa73cc221d6cfd2f469196761decd0fbbcdf794f35e448e36e3c4cf29316a7d2097a24701e849378092e4b95ca0b2d35021f0567c386a315aeebc1248a13411019f9c5408c26dca99c503d9309b86244dbe6054dade34c7c09b28b2e5a9b490388736d3ce90218777591dfd5ba2921b2181b55d306cfc479b9c0f4038bf1b901a9e600184d7f0e6c346d3b53dcf56e11eac4cfd1f1584b4a1415acf2547e0265cb3c39534eaedb72f13efc1498c5f2928795362a1362456c26b7d717cb7506c1fe20398edf858e837ed0adb4a6ae81a5220fe98277adc4408b477e16390c7a892c00f7972f2200e81bc9536d0a779b34f31498ae320206a4f1963c0f3fc977b3890f82e3aa5f9b7bc150ea7018ca6b26282431203e9458549f54724407235888bff6170b99d2c0274360024bd5c0535278b31e71098565c49a1a2fd27540277e33ad32bd01cf2462bbc0f7224e9d1c605be41ca2387f4667833a64a791615b5af0023d1cb20bed0634a88714a69379cd0a2ed727c287231117ef81c1d3436093d32dc8408e66b505ce109321c6ed60ffe3553bc9cb0cb977f21f5ed2822e55908c1f9294173df88ecce0b8c1979487c1f3c0ef0c163046e7a537d89beca220b9f2391cc9310b4434fe943f067e6003c87494b7c8d5487ed57447b6cc1d08e23f3e16490bc0f842bcb9b9140c47dbca1f8445cf43c93071efc440737175323f6463ad15b6049fc59a82a3d97c3c5af38a563133aa1c1598851e13ace78f13b322a9e8521fb5feeb82ed026d02f8953c4e534eaf103f0201d8cb2834fc9d2a69d1018f987444767e168877f16212d45ca1aefc306907b0214e772d6438f4181d23b3417f5a2bd39ee56b96c28a9ccfc943f17f4a6c53fafa68197979207e95c1602b9a71d1f7c0f68f3a452f8f961e38fcfa044ce8924091d11a7230f13a1b0ab685c71b2384bb495194ece04cb875e4e00f5700c68e9758f92ff92c8c2736220e80118d23a4f9306ef2a6bb2836405713066a89d285306b7732981767e39f0383a9dbe0702431f284804cda88de38fe9a249236a72e47f6812e17e7bdcb78a64f8769455bed207e4bef4e7c72321127b2e5e961e46a3e38710903daa4d697c6d8fec896562f492b9e68763267da35264be1193143b318de38b58b69aedd2c5e72d0b5bda78c0f338c2b16bac98fb266c6a789c40006f0826bf1f236cbcc49a32ce416eecc1a0443d930ce4cf2130e858bc28f044a54239cbb5c2c9d84a6c397f98ffa90d15df8a22f75e06912ec3408b2f93017c8d8d82e754e4d149a562e47d89437c501b46c7318ad55e965cbe12821efa8f8039770244d05361c8bd883c593b8c4f8097a2117c8bbe502e8a40d87e1120f1e90000db9dbaa0792083a43f8628751bd20b9a8727d88318fed1f195178f858f8d932520e16ab4fa68395150f899a7c0adb578eaeb623c9a80dd8a5f2f84d271beacbd1bb8259a8a99df3ba507362a1f9d7e0e1e1e07c204ea99da8cd25e1af09c4d6ccc231f5cf14356befe48d4ca3b0542f12f80597f636b8df6b4668937d13148e34daae27043f636a6066a5ee54348ff8084f6122ec5d96f68823c040b245c8a6781abc9e9f99ea5071fe729ec2b941ae5b05f90d762498fafcd917a2348badc0bf27dd9e2d0abada9f18f83863c1f21110de985e0df40dba4534842e0f108130f638c809f61d8c3d7f8487847aaa9dd672ae47f1026fa144becbecb4ec1568236f54140f297d140e625f979f99f37f2ef5081c31dc5417c48f09a1e20987c7d25e98252fa78914d6d9e1765cdc751e0f7680e89724c4e9e9a4d2436eec08ea4ef33a3c25f8170e01b9780dfa4c11b87e1e270161efaec0d2b4cbc2314499eeaa6ca2b1957788be9a66772c88cef188adf4998f5a92176ef040d8abde805c7ab98a4dc9070f43984057cb4140747fc048b3a6fc48021a7a204d1ad34b1f34f2f463b4a252caf64bad189422c71678b2e7a0e40e923b828e020e43c791d26a6de8658e429ac40f2d2345f5f97d7c4a357bc1ec13eb033f5b9f16e7ee27cae22fb0e241f9de069e63b66c839b58f00f763bba41f1b00721d24e2362a4d8e3c4682710a4ab05f94c17689b62c2fa6894127d3be3cc698113fc5a6e515b5b1d34b4ecd79983586fec48df380a236e81e21fe781d453c7a4ba74c7f6806e6ab7ce17d081851fe8e17bec7446aea3606d5382750f146ec41eab338a0ea0589009e463ce5035105b804081eb48d0e4e0730f76803b852f186822cd05ec2b6fc2d4296471054e56e384cfc23863c3f741148c711e2c24551c8e43e3e71f12620e2f6ea62860bc861e0b1dc0079c466dc6e9473f46bec7a389921316f7c8cf3352260f8b7916f5bb5f9f384145579112c0f57740749ef6062e7597489e343ee1adf0e1d281ae965edc3440769017598dcedcd8a07b541c53bb512f811b320df07ef877e1384e33a8cbcbb9322465ff302a82351507c2d6e263d264e823e2c0396bb88e3e0bfb406b58f4285ee47b187d7b9e1e863e00cec4a3aa42e3f0eea2d32427c1a8a171b3e62ea351560f46208317edbe3b78d1b10de5492d3c78880c71fa5a2f3013b4a7d280385362267872732e8e6bf3477bc07c33e9acaece8df19155c0883c067956cb62b23c1bf02441f6866e6d52480a453d9adaf256ad02990e5705651cb4971d170014d02ba8906074e224ea507934ad08f3a916a33d0a3f475310638d9629a673289cfcf9d79e0bf2863db11c2e3d18a04ea3c30861c8f9b231f424a252f65c8ce3f7ab0e6420264ed0e718cafe866c933c94ae06ca2573e408f381f69c604ff7136f72ea9bc3dc52b3cde8b13fbcbac4f2a91e97166165fc28205ee08cda11f5346c9bfa44074161bf1d71892f36d00757ab22dd6819412b51b59357f2a63c063e940f1510e7ded176d08dc0a1bc61d039dfa1e7e026db503a65ce6e3b2ab16647c57dda9bd20938137d1888b061501d157d899f0f28041ae34e5f87196615c9903d2261cc3c5492529b4a98a087c458a377b81dba24fa327cd8e71177b9050867bcc0fc3b7ea42f75c0257f8d894f8078071e48fb090da64d82e3d85188cfe70fef0ceb8df50d37f85736a0778f43f6b8ce3101ec73c21a9043f2664e95954c0afd10791ef71cfb41a221dbe4b15146e95f6c3e14e99fe509181674012419f612a7154f32187b258e3a012d76da08021ff70e5c1b6d1b6c883c071d027445c7da83dadaf0982e9a1877d76580645af00b0ca3b3492e23e662c5f4faa271ee8c811ad2760cabb2d62fb3fa0ba3c092a918ba1b1f85e9a963609311d7eb03085f66278e6cbd63a781d33b49f0a11dba1d800b98db9baa756a2e433224cd08d2064f9a330d0979128cf3939b9f340702afc44ecf406778c6f21c8144f31e9ca27841af45808c071366c7d76022421fc45dd97eb2108e0d22e81cfa502f00118eaf0852cccbc7dcba0e314307c4404c478209508aea7a3cc3bea43e44f1d3ad0aea08c233a64c54904b872ea140b9b80a3053e078f91bda74f8ca74055e82d2c42fb0f51e4b857569f8bb990eeeaa1156f487763bf793e3f552cf73facd87cdc5653a771d539dea102bbc80c2a0ee5c1a06744b8e93bfd11d47b5637bea4840a8da9d21c5f81466f0f0242f687f6261d0a6dcf7f11c55772c1ce2189c0da2a04213f45182b4e7738c767bc19e58d8726bd8543a3bc8c47fc4b2e95f60b42aea315d13af06bce9b4c2ae040a6303a8c3f3d3e43989647b5e6cf9e7b16782e6276f6893167ae580151e35882e5077040d38c0f0afc2541d8f50ec5783ec5163a912e94e3a8a2e50bd618f9213e1a7c85aa05ce0897c1d71814f8b523595a141aeb040e71ed65e2bf9f414a7e2e19bf04000cb6de6291fff49e399a8e28ae370ac4bf95f8e20e0a2cd868667aefc5e863b73d5bb722aa4bbf78f97e1e64e02bbd107c126efefc8245067e0f6ed00cc450f10a5c9aec478cf0dece121edaefc27f1955ed01f700f1259cb8f6012612dcc16ab72100e8e17fe876b8994230bf80058c2d6788910f95ea934ee515c0d506ddd76305cc8fc90cf616a200376128edf3b0ba5cbebae08422ec71343c045dcdb3f930c22e6dbe2da05c488a315a0b990e577315e9fd00f6f14c59fab4979ce0b798d83692271797a0354a3ff2f2e94165c2b01d95793e9840481e43cd815f82e9f02fd50fbfb50ce09600987a102e3639833b270efd1d1a9a8191a3702ef597972c0fa7e942e79053c017d930fe1629537f4890cced3c9ae45f1e8df82c8bfc5e861b0ffa8a9ef3b58be89fd319be0940845d45469a6fe06083c6eb80e84d1408d2f025107fc6a0aae56089f448116b342139083f38a3f9a416cdf0431b695a6dadf0b354cc3e98a8c3496dbaa48de419e26931aaec2f7183ee43d20dade8a8c62d15bed8480a0a7c0b8c11ada4afc9e7d98149934a02c29734e13463aa116e499153b7e5d0e33b2291d26bc6ce38dfd89dbe03628a37293df90d59e6b86154d0f6b319ff4cc0dcb6526de3ca192e7e4d13e31f9a3bf41fdfe663d0b0dafe98f68c19ae3c9eb61f0ee707853386707aa22d5874153b0efff525640bc1e29f20830d7fd48580039922443f21a5e7ad148b3c7ce2c797f851638f4931e7db7c7aa1238d18fb4e5632fc850b201ccb28a88ea2eae23e26b97361c0c7df40dc70414f10dd41aa1bef82d8e366aec47c010c49fe484652b34514798a1129b6da0e1e2f60eb8103b1c3f6275e68d1a2e2143d89148d34d548a877b312b5293d6af2885c38f4744e9e632854e8384428f02b9d1e3511349ffec0a36fb0b1a403daf2a8af5e38724a788a6c4109fc9f892679d58f245e56c643735540fe9aa140fb4b49a30f4289bc1933a87c461d467e49c1a277f106da34b0f8b85d243c5de1c2de4340d5c7b368e1f3217a26e8401c8efe608e056de3adeb3fac09f48c4663bf2541aa9ff101cb53b1668f06cb0c5f539cd96932f4b8a5ab42baedc2c0116d19f58adadcfc172f2eaf06ce9957f621e0899a0c7c90dde6501cf9700e08ce9c8108f6cd3847fc952b57ae8943133fe2603f28a5ce0bfd7ef86751712750eefc20d6728b5214e59d064fe86f20e53f199aa10518a8f19fb638edac248907510646b760d5b88ee923adb7c2c6ebb8139b50d385733173b22d817971015f34e8502ec2bc310948abc5ad1e05d2047fb681f3175eb42fe0aafa513df72d5959fe08a0df807160789f0251aec3f18c9b8263648f19b3e7235cc2e44dde94bc1e98a1272097f13893deb88beae253edbabc0ba84fffe94ec09eeb93caff16d57930ac131f292bd01d04067a3e5944e90d070ef90dc0264f3846ce6900c1b0099fecf9270820391424579c0f82189e47a3cd9bc053b17b3456782983b468035df2dc520c33df6000a9efa3e3cda96e0e7c1201937f13e789abf0d1dc25e21a1f10cba26d58a7920f5ac99a9140a0e74244c8a51424fc1f363174941d7bdec08cd8d7d5b87a4044fca90840f5035c3b3d7680e977341e3f0ba5274f4088a007a462f66808597ca4066cfea0cf8a2e40e0879fc81143233231c5d7bc8cfa29965c3c1e4189be004e043733c5f546da54f8e15aeb47b688fc825273769c1c9a1b70c2c019dc41e46a9e2c6cbf52da07a5f1fb29563a9c80a0431fb3c1df00cc8e7d2569d35742604123495672044cd8b80547c4f7a157b67134487edca0a3fdc60388d3f5c8b2170019e23bc0747a5289487c14bf2aba858c445eb508cabe22e6cf01112aeab00af0e31852689b71f2e1133e14d18972c0dc1977e7cda2f87946554abfa66a3a1f2c237a04169fd339d149277660f474c85ce8aa813b6e66c8810e4414c13f1de8a0d3a49af24cfec8d8703414dd0f2cc73fca4bbc4fa013dda8d18ea7318ace4b39f4703410633f47278f8fe083e505a7607c91cff91294b0f8b74306de1110213ee50699cd3806f085f0b9f28e1a20f8c1d8c88f71c0e23f28b5e900d049af23adb92fada5f1072a2aec1d9772b8d46dc41653e4f2b6af537ee2c4984f04e87a0304072e222f94378271f659500dd24a72c43d804d57af8283fec0549e1c5948c92579bae439bef43caaa6ca07b05be06055b2b8b30ed87b1168e4ce688b433924c7b713126ff6648c3eb3a8c8dd9c5afe2316323ee941d409953971190db4f6d608056ee789c8197171390d188bcf8c64c20d74ade922201638820a88b6102c336e3508c5696c593d961d0c8fa4cfd617d668d4247aa0b9272e43bb87171bef238acfd1ccd2bc230037a7e168edd7baa0d970ec80f0432768fc520f4c1e038efbe1981afe68538b0d050e08978924fa52881b5e4fc19ad381c1c3d98c30b5dbea7079355bb27c0b1f08fcc1a42ecd408b0aff04a6eb378488e133c4b0714a9cda1eb0060b0fc1a9fdaa41019a0e212aee80cd7a388a1efd174903761900991e07a0489a8496a3675b83ea104c2be7a4e6b9536502f3106466fc2736556e85422abd681495d7f3a78d1f4ad5c7ab9062e193e84c793b737dae95ec72549738bc04b3229e2503803ec1a4c1c3152ed15a18acfd1512533622437e2f38a975086b0e5fc6a8521ea7b1ea73103a37020e125ef1818a3d572586db5511b796e7256711e58b1b1e49f17427e86c048f983ec9abf70a4c59f20e3504e93e7cde3c0c0241ba849c30fea283e0b78562f1860240d18b0435f1c1ad014eadf2742a09e238211ad9fb7931e841420e78175ad587e9b0e70785087464181d2e46401e8d176783c760d049e771baf1364b8d3c003ce0c3fc117214af8587335d3e2a2f245e03832fbe72f8e46566113ea64dce4719fd3d050033deaa08950d415089a742c8b919b4153e81a6e84eb326fed79de6532accf052bc04beded89fe649a9a7128380c351f2d90b9850701871287ca734185c8f5bbcdfeac839168232ef27cfded771e1bcb1edf30090a2789e049c7ece20636bb1b5afe8f14d872dcef845b1f911049e70357f35be0281f5f580ba7b3b1d81de81f1c4bf78c4e7af1e39fa4b8d626ec3e9c2a13caaba5da0460f642de05d44fd793c714d0fa00bfc0a3112ee0a46f005f299b7d392a213bdb9f27c0eed5e845e128761c0c166b105df1012051d03aaf515704cd028fa08f2ae1c4cfc420e41d730755fcb8b0b6fe289496358763d74c399579ac0e5eda804d04d4c88bd05429a7615247a9e102530bbeed38f27b0e56b1bf2787b2a02cc7c813135c741e04d633adce4a368ac711859467d61f4cd193482734e0e76fc2ca9e9a1f2a03c1135b09f13c2cbcb3071fc098065beb7df49fc4970014c6287629569134144fc41059e7e23d0eb7f89f6369719bc9701a13c93c7c65f6040c3debab1c1b76810e223de4cf20a7d2f761208ad637870c171ac18f4315c8d3ec03194bb18a3e4c3d040e57267a05a47a5f59bd461b04b7c29e16008e1f8afb30c6e858451af6dcae3433654d17a47bcfc4986509e630a225fdb9bf093c27cf95c8d33fb6a45e25721abcec192a26fda9be05ad686bc133239bde6907347bff64514287d4900485e8409f5473d951ed32044efc287115f9420ed632ebaef826afda8325e5f7741d07fb579f22e270bfee4c3172de8d2257f938e6e78a6cceb6501f2280c28f84421963c8253225e0f23a88e2408e87249460fd4f6e4871cf0a05901485f53c384ae9602e4827a50794a3a4c79192b0a9a1363237fb3c2d3180ab53c314411d7f3058f3bd29147bb5dd32109b0db839ea8f1238516740c46341f2a4297de608a8703d8f2da1c0e747a2b0dd58dd8c092eb71f0c80f559ae14f48387208825c6eaa091cf7c487e73f6a7471c64e057ed013b2dff325f1012dbae46d00f41c102ab7d9f0e0f16389a8b8d62944ef66938e6f1688fb0e7a652e48c1cfa378d1f27296071e81c403475373e3191c107aa0a2969fb326c5cb39ba5e8423a53f9c50fd4a74615a09023a1e48419e43897c79009a246c3415fef8998c46b78321c40118626ed883a57744616b2f6b2870c04114bc8b14a7ff02a065739191f032bd357d202ccd67f801e43a3ca9f92c207e7ad3228f2f81e1f0534148fb2a45911e9a8acb4b7053e2fb83991790e0e65d0430bfca13c51d27841b2f8385857fbd35fd43872ae704417b860d4aafba1be58f7ed05d0524c40319f5b58b50c0e46d6a68d057be583d2040441b89292d37e0084233d7c7bf50277e3e93ae1e4fba64c7f852e6659dc0f429486edfc611cebd0aff7c54d60e7f6b34f60e7cccf930266ddf6523c54f7821c9195d71792984431741889476ac0af26706dded4aa7fc38114f86dec245041f5425cd26100088afe999b50744aea7a281615342da78276a7ef89cb4bc7714808f2e7b3af146321c775b1e0b6fca861ced44ce883b1edc4381c1f84978e47956051adec586884de591dcff0843b64f304e7806771e6c0e2a22f9d51a75ef5d51be883d97de2f919b4f5912e70cf48c6fc3f8c037c501f58bc808df0c450f97e17844cf1123e49317fe9e148601cfa9c317bde8e0c4c340734557491ae55766c4f91f2f861e0ca3d953af023c9122767c0080b4c762a3b7d9ac91703f33405fe9c2e760d33afe350ff1448a9cb8a022896f94a3aa5598097a37358e38a0ba20bed76748338884e81b3019d1601629f2377b0e5ed2283b17a3c6d162619eb861251f2fe60ffc867282bacc63255fe4086c2b3a22c71770dae44d25a197126ad45cf6f6fc011c8dad04c5e0e7b1a2a04fc9642f474f20cda231d1e5065075960f75dccd90d49742e1e1632484974bb9f00a6f207c00a525ffc770c91b8e12e47cf0a46ea5718eafa180448b0af0e6670042a43d3151b897b412a4527cc6f34e2fd9c4e6352a84d2926cc8bd1907246ea642ecd41539b6e06ac19938aaa3b5848df1c738cece42b0f796da9cd23c1eacf027871a351f10721eb1c7ea45d61ab9a33c3476d88ce4e522186e3f7e539ccca3229ac703150f804dbb7b70a1e248da286a2c698daf00cb8d0780e8e5899a3dfe052820cfc7cdd16b8ce0e33e144d680092503c5caa51bb122414ee46cddb05a2d47766e96d0e7c107d0c2e2ce701c4d2cfc17bf2881a35f04532944d26c814d701e09136d0627e1aadda77d031c3e1aabc67c1c2e78b39acfc1533196fe68efc0412c0ef37056b4f79b0c5e534373c401adc9370fad18f2475bd25383ebbca1f236fb1e58f2e134d73473295dc05a7c08f1077e51720f37ccb11c2ed07cbc62b9850e803c5ecf8649da1dea2f1f7a8a26f1c121f012e6817a689cc796f03f5b4eff885f02d1b7ffbd0c99d9be882e1072d3278248a0a1dc61909cff661895b25c1e05f8f78b4a41c217c0906335f88c9cb352435ef9253fb1d738fdf0eae79022df27893cb861f9522d5eb4df11ccc01043feb93e6675e95b42919529cc799295a0fa51dfe0611cc2ea227c8cf687ed04782a8f13622d2fcd8904adee46d82bf21de78fc078b0e3528f9615a3bdbc0f7793aad2cfa10fef066d430b90608943ef9b5f83fc612bc2181405b46358e5bf2e344571b0d701189589c0b4a904f3659f8220657dc51013b1ac41e483ee982241d6b92ba1b680eef4267e743685874c5538ade4b12036d89029c2f634950afa570fe973db1cdc18dde6bb9c3f86a9d16ff4d0ee02bea44e49d2e746c45c2b827b007b52842110e7b21f52320f170502716f7a3b54f7f653a7ddfb0fa17490136929ae69f7482bd11d0967f1c5b3f08073e232e575382e4c9272de1748ab6f82fedfd88a0a870c6bb4e1acb92e027c30675132f36be1d9b7d075dddc37194faa54e80de52a8315bc122c53f8502d14f7a5af21755509d4654a80f74b1e59f3c1c3edc25407de28da8cff3b347e7b57e5ccf981a8e2213227fe452f673c024cf906ac57e40763e131abbc7d422c367a892428f61177f0d8d05ba94133bae620ad803c659e0ab8cbc7d5884c9c37e82348b400d5c8bc0019d4959ea116c85d88a41163d9c36598fa34d29672b82f5441cbc871d6a7c328e325c4784b88ff2e67826d332ade88b952f51036a0759c4e1814cbf5e0a989cc7b8f2b23f51fe4a44be6c4a72897ff268f5215cdf9785fd361485d15d9c716d6413329f685090ad8825c54fa296ed176a2cb855112f2f6480c2ffbce9a1ab3018e209e6087f2249fb7d3e95f92096a2381998470f0a8a8c1ff4c8e969e880714d3b407c1b0b0d5e83bbcfc8081797a103c4178a25fd9429979e888c24ef094e277f4357e7ac9f54fe810d820f34458d5ec0278acb4c74bc2208081ec1b1875643a2f56a2043fe43419f87b4a68d8711bbf12588e8d07ea518bd12da0c8ddc00e9876071f3114c01723505426cbc4732b7d023ee05ade17b29727efb0334ea4ae464e8b7541ebec89bb8eba8607425704b7c0102185f274bd0e50008f1fbb1f0079f7e9c82a0a6132e01f2820a0ebd11a701be5806f815f6d0b828394b9bcf32ecb9dac45b5211531ec769c63d70c14e6701153feca0e8583195dd28a8cbdb3ccc3bc424bd2f9b936403704ef83484741c0cc993ff9322e6800679f14d6cd5db5810e10beac85ecb274bef4600f45929290773c2ea3444047ce0e304ad648dd607c0b063e7f1f1fa2128bce83c35c0874b4bf32cd1057e20cc51af2987388b4f695ea646d3fb1c72d2553860f95084b81e91cb764298aefc9310fd2834850d6191d7bfc9e8a217a786dcc69430bf6410f1c9a47dd15c1b40f9190b632e67410c07b529f06546575cc6a5353bcdccec4be565d18eeabc7e42318ff7496c9f14128223eee5f12ae80f3f33f53a12add823ed30f443bd204f3dc3e3e13b28b40a3a346e67c522efb3258907faa4c843d0d5f84618493da30f0dcf5b326b226fff60fa96ff04051337c3c1c837b864c7371401e43864087a11a39e5a4f0d348e618f80eb0989e0a81e61d15da908f9a13a510fa0e78a5bea1bb52f8091bf9ad6ba9a022edf4747e10b89a3e802fe4cbd05138e7c46da8b2f8003cbff38c3f7568a787220ac002d83d9c82fbdb1d895dc123cdca2a46d688897676b24e605114138a440af1d78b7c7236089d382a6f4702d6466bc7ae7e1470478b50f2a11fc9193124f6140119ff3674b67d213e7ffda8c7da018485f4654bb0d4518f177ea0f7042c0b7b084e2274917f9a4007c5e520fb857d11cf429eac03ea9a9661b72e987ae19fc464d587e27638e9f29a17b33c43aff030a20bf90a9866eb73c7d1a1736365b90038fa6a6e6d318833e28ae4bb315e478344ad3f5bae879004abc68bcabe5a7e50dd034f2f878c518855e1f4a7a9e1f150d855afd4993346d2786f01e510d3eeec3c6803f60a3cf9e42067d138c9f5e0c993bff42674ad3907bf16a4ecc781c2e32792a2f905e09880c5fd6b8b782505f7c041c14bfe02ffa5a6e33362230e8ff0509a319d1d8fb173fa4fb10601397a3e56aabc9b2e299de1afaf14819cfc3a1cc4f5119bd0eb31f1b0f9b282fe5c2a07d47ad8893fd20d448c8887a115d6cfa31038b9f31f5f3692b82fca3bb022f02ce0807d48bf30d8994933a92c00f046af91431a18ec9a0f89d8aaa55d419f12fa0346e2037bcfc0d9996ef5480eba3301d68af4b979e4da1b29d5626e8472af1d848d66cf928e9008d7460f55c68a070cf02e58f18e1b32d3dd07b2352dcdf3ef17db8e5d02d7bc8d3ec45fa2548007f019f212ff3a578bf36160fb663d0571ad4a41dc9dabc0aba249f408387cf9116ea039478fe2702759a0623245fa588f8194a17aea18f00373206c4e731c0659fb9507d1f63f2ec2d2db4788dad33baaff0f538500239a23a40dc4525e61e62d87143a1a2ae412ec3cb955975a449097e0ba7e71f61f2701d4a121b81fce89fc820f0453eca3e0e86285befb1ca5f34959ec0579ab77840634f9aef5c0b8a802f1430c6934018fc235a86f85308ab07259d791205135e0b2ae11bfc71f9900f3ddec417475d2ac5bfa70a6e7a6f09ea37813ad36f4014bfef0518a7b10c7b14806e7c83d6cc4f0853fcd5c7a5575048e879c2d6f758cf9b843438aa3e1db49541807f0180eb6f413479550d3cbf271de0472e35f2e999384f8447722f8ac9f40bb88cf2086e819f84abd456d008cd275852653bc964e0037582a1f1bc9ab81d80429774f7c5b1eef83d282782ffe829e3f99254f92753aabb2aecbc183d63db7503e4d7f440b5f10c157a7976d46c789e3e56b4c82134b9e28122486d345cbe381394a06fc1f0b8bc414f27011be4a206fdd0a9a88cf82288487c8a116d6fea13557b9023f913366b731d91f41ec650d28610007c1f95146f6586833f3234e029420d7235c23b3731ca91ab919ab1479102f584e4fe68c43a69bf47c006cdf868e0cb163cd24847fb351c7e78422c447c9fc0badd2a487c3f4810e8c1039fde0b0250eee00f2a3fa374e88b7080e47b42e8f0690fad0f03b1f427d43a27c1e535a8440d2ec3cf28a7d3e4cbeb394ae006eef8710c1116bd919e9d677348697782d1f86dce023a8c1a42e7f41b9c0e182a0e1dc1674379f1eea66585263cf5e5762a1ceac03a763e050142da83a103bee489412bb55678201b0474042b5f6f2a012aff26ae4b0b38d802a8ff807c0cda8f8e16fd0c261e3ea20c8de33571a13dcf8f97d191c72f5169e048b85cd25e2df178e82c5fedeb8863e0e37ac6d389eb706cb2e9b6087da52d81f45bc690bb82ae74813f4dfccb69e7e34446be8fb1d5cc02792e1728421baa44f89b941cd88a578f9e1258a1f729c1e851c470a39f54f7bc1dac4e1e4a0d997bf28467bb251c5fe5c5fba5ab4dbf6786ebb7e4de7c15a813df04e7c5d75052a05150c1e14e66c3db3e051ee1ed8ea3e2d13e92315f7b019a1bdf86439d764149cb330045e3df0001f40524b56e0a551b977448cce556b667e3a3906e6306936fcab166933882c5c7f270d87b0c2e7c131d09f4802c86be9695e88fde174e08c9f1a3c449e152489cf9124a6cbcc59b2e1d48839d83aae3fa1b4c7afe6d0fb5073d5d9e049dd3956d90de910d1c076561fa8dde26ba11888707f4d8eeb21a327e9291272f4153de1bc01aa4e5c8f8bc4ac88c473366c917c66d6d3e2a4e8fbee9d881101472148040bc421f297e4596f58d44f5f9b533709a4f9b4aef46c38bffa352f83a16e578029998cfc493fe2821389c0a058abeb3b55c8e1c383d82c10587fd4c72505164bf5afbb13bc801e3711d42fc1209025e902010bb149a3c9ed6a9eeb336b43d233a664ee7c5db9b2862f60d14393a0308495724c9895772af6c0d2b30f9e3ff79161266bc9c3b093e051af797a1a0ec278c42fe491b541f3db1f762a74a69137dc6381f331f5b0099b22fbc63e8edb869f41610c97d170a479fa9cde93a24cdf1447bb468010d34791e9aab1f4328d4077618a547d8a1f32e74516d0311f045e460b7842f835e8ed3db663dd87ec01e00f75304d0e7f2f43dcc9ce0004045d930880d3f8a81872d234da30b19b5a6797c09f3825741f4281764ef836ec7a329a5e69d2085f929240b5f446fcbde5368cc2f318ed017e69ef89468745b41d3e472fc582d1865832f5218e2a69a307f0db080e7e80bf02e16de9fb570be2ed06daf557178adc43dde46a7fcc1d9c96f1222e8874cc01d86c0a6679054f039065c70af0537b6e097073ee606ce2e3c20e71c9434be8aa5f5a544139f0dd21c8724804d9f2a83c8e55030a1491512f8180ca5ddc520ef2f65eaf08b9ea8b90d34751fd3c9f2710088e82a4fe03794f3c3d526e5fd56a23f0ffc4a0f5514a119f009781b61dabc9d3609de01079fd6f350c945a429d14ac640fa2c3a98b820542afe25c4e5ff6034f00a70d6378123e83ff65c6dbb00085e489c357fc551d20d5d31f4d1b43f9ee349a31f7149ced95491b13f8c35722d59a29a8b48a3c3a12672291eb21e01104c3a0ccf813b2ab2e26ba4b9f1b0c6561342b0c1032c1978812280be875bc9afa0a5f93e191276a565f5fbf40af58af5e8634ee8f9a09836af44c08f1dc8458d57a4e3b4cd1c1a7caee68a2d45502257d0b7c4436511734659f4681e8730ded044a6f7f060930bb03ae02504afbc281b90361f214a6fa68aea4b3112f18808296a1535a81fc5501dcf2168cf532d4cbd40179c6f2249caa6d4b2780a832df6567ce7f1141d6d3a4304af494e8c9e0b3b74e5a1960ed1c2f9291f906c214ea92302b346ffd0b0e82ab4847c0f44657c479b38ed2eee71b705785f7883f14795616d3e20f2fc008e409e890723bfb3e4932644a9ce1b70e040d3a148f01544cc4e268df40abcdee8042ee363e1436a6b80c3e0061ac93da842b4c7db9bdb2c28e823b9a8ed4aa3189d8a234fae200f7e237948b958214c5eca081a0d412ac4f99c7f3cc9b2c5e72119a2013813b80c39ec5b58b9f26bf070f89889c62db510b277c878e369041bf787bcea2b09cdfc9bd50d47115bf2ac295a7e8668a59551e63c0e1ee9466c91e323c18cef8d825e8b1b49cbfd39f1882ae89e0c15320f80c3a3e3982ef2528b4ee901615afe1114271dc12bbc8130a6f428489d1e4206413a909308ae820910ad20079a37c124692d23ac4b68d3b41189a1723a511ebe518d1a5e4869c3b6e312e298b6c06db7beab5f244dea375cd2fcc3994afa5dd4e6230835d8c83f188ecaca86fed100870ba24368ef801bf4260e08d1523423bed205a55e1482cb3f310a7e843b707cca26403e22fee072f00cf84fa9b8fe468f207e29a9e913e12ddb5413317750c951e7e8e3e40dd93df123074afd06d569bf80987c99d9e32f796a3d98671c07038a75c4463fb6201e4e8f63006b97c942f40cdee26c2c5aeafe071cf74878b0f14c437aec4785723c1d9fa79d2551d3c77c3c760c1d387c4d9610fbc67cc327046ad0a74cd5f944362d1bd24ac0e5c8557a4648ee2f2698b0955f763ca651a3de9da4c8bfe441703e01ee8a298a3c1736751eca858adfb04386a33171f553fcd49f08e47ab412f3f530b9a1af84bd8fe2eacec62be3bafba494177a91c661a921ade845cdfb8823b8e59e5587c00583937d89e08e01bef85d9948fe66c34fb77ff4b8a9015e7ec8851f0e0ac5927793137de718d9474812f00a8f58fea688983b1173f81a0a7878151d0437dc338ebf1021c5175595380035300d82470f2f85a7c7076b00fe91e6e37335f8e208be18f5a911db237481a17db809fc2245c8bc981637ef014ca71dc78ac0d37df1bd9f436f9f22079806b416e93fec701f50e1813ffad8e35c5d391c4d3ef41658893734c5c81695698593993143efc1b372a753f50150407d154f625e911e0c8f488ade0b6841f6155ab4d1156688fa0b47e2ec293b8dab6520fbbf87f0843ccc712c4ba973b162bc4c032dbea7d4b13fe500e17640003c7219e85ff099f9de87ea23d946b61db51cbe26ab70ab898af378d244782e93583c74cfa69d82c3fc014809700a65103da60d699a6b9027477109d22e3124c64b456870515fd09ec219996d05c6224f1b44be882e139e40a9349da2039c63e26bdcf160f4c344617d921ac56fccaaf3a5b4e65efee3e5130c60f9102d845cae8ba08f81404e63b883e349fe4878212f187c89f9d0c55c22f24b343ab49e3042bcd49b1b7a81609817d143e3651863b859d552435341f90230c46c51332957b0e54fdb29a2c423e139fa3c7bc1335a00c7b7ac9972bc28df0e3450e97fb868e315d450722f0c10683e4078aee6304d3f3a9c731480c4e8528a966f052b929711611dc5f6a3978001be1151755a465fe15b5152730d8e867c0d25a6f4a42d34fe9085988f0441817f3260c2f50cc1e2647433360aeaa08bb22275075e3c7ca1b0ab7d8285956f5dd627f4a9e47d30d1e931cb1e5e8091deae21394e4903915d05ccd8dbd16447fbd1d35e4310a6dd86829863d25abe824a4a3fc521c5d76982f4206e2c5e7007f16934ccab0961ea2b3540b015ff0abc10e8041d76818457c9517af4cd1e2f847ad90050e1f147728e6c2f67795ec7a13b3d004b0af72a4017c1be79367a60ee4ffeb7043d5e258f8cffbb60480f5970f65516e1b49f1a89dc95b1dc7d82647a19690a5dda88e5d5c82e68659343eee9cd6b0068bcbccbd2950685947af592d956d478f7d12b14f682a8946fec33a167207af47f5aa4f94058826fc12fc59e22a3fc290e5e6f8084db272a62625bc01bfb4a49f0b612c9a73794dbf080b3094755e4d003f51878258918be902935b764d6e17d6872e296dcd636a8422d5e0aa4abad4c3c7c0607c4f80f432a6fc866f7f0173ecfa805eb577cf8f01cb8f0d874e6bc0741206937df08fa376844fd88c052cefcd463176004c005b90cfe2eab93438a46fa2f2b575ee5079c9e2b30c2db39669b8760a817c06866eb2d40fb0c80a8e82913c0dc910640bb6a24cdafed9636d087cb81f4e9fa147d06fc8029163a7e93e24d98bdff38c9ce87d940a4052431e4583c38f03c06ccfca191be0dc391c96732b5be932b06fc50811f1b060c3cae8b84edf955f82719ae26a0a9ef9f2ae8b89e5d17373483d22aacc0710b67226d1e800a7e14182d2ee092869fb22973400f9e2eb682d136d1547454605268bc2a971c8cccde4cbe387edc99fb9824d078b6bcc7dd4850895f26863d09074b1c441b3e1b552334bf0182ce47a9a1fa6b81732f6102fc7039c90f4fe0fd13361adbee899507e184c3c7b0947d744628fd68ef824f3759e9798585278467c2eef303e659b0ec74e004039ed5a7cd7b0c32bf5012d996ff4c39252b32bcababc12b32af78862c58ee864ad8db41d4e2bf7c75fd98012ebeccd200efdab4e0e54292dccf02b387c422cef60c761e2ae2caa35813f3c5c707da4e95036e250b1c4d652dcf930824661bc27172b61a56b6211b264ec80496bd45203e9b26497e854fa09f9b917b2b6b8723b209a4273cd6f8367152e8418e7a3c059c985dbd81c7d7f8e26c1603a63892410134d9ded4a96ce0e111788c3d2435d21d6a9082af4159351014673e8968c7e70821e7db7059bff08f80af0333b801fdc0f0d58da12b5a39f39118a1daa52cc8f1042d0efc994552feecef81af5541bee70a1777e3c2d33bff78d93a0a277d0e3270eea070ccb36030b2b73635f9b72d58f45484d693654df0307fa27cc71e890d08cecc6f29fa690a6c87ae2863fac349f0e32162e88b8430bc29438a3b5e23fb45b7e8aed1d8f6803625d83556319f09ac71115b223e0d96d67ff521fc2a46a09a83dbe89318e5fd9d26a66721707b3925a9de83e3f44f587dfa1784fb918c39f1cb2a57aff013e1569c2b3ed43bbe0601af0b21ccfa498c8dfe4a0a2a0f629df481a4e0df1264a255c478e46a3204ec471420f83214a6ff3388eb673d599cc489012e2746111da8410f0713f145fb01d3c5fb8068f3c4b2c4af0306d6623752b91bdd95edec70c007a1d0f4633b3cb8a8b9efe34095bd1a9ce3677003f436da1c77ec698cf36df9c5bcf8f470fc185d508f15471ad07b5114b6bc9528871c41d61a47b5c5c84ea322f683a4acd892d4a07d972182baeb6b85830d19b13fd5e0fab91f627485c5099e47a482a33075e3352491b78e425c1c4d8ce03bb47cfcc6978eaf31a1ca456939ee25d49103d854a60b110971c345a9f432111ab7f044f397ac10f92c6e706c1e79763c52754ff74870c10780597cb819523e305083fe2461c277b0e4e758da18fa034aec741737224e860cd62b3208f4732d9c7a06a448afe08f9847c67afecd04a75de4418d37d183c2c612f8e26330387d27430fdf14cac83e1464cfd110dff660a73c8fe748a1bd2845ec7c8e39b6191f721c480176afe1a09d131f18af72c183776011e3319d017a0102739ccc0a327721aa9223739c7a37304c2f37a3f90699d278a34e2d1cce9911ef3577e88062de4b70d1bda899ec41085af394ee0ce805111279a6b5245ec790a00feae068fb9101ea3321f91c4a232bffd6458f26a2a1854f414242df4935c7f3b07ce8248553be831e91ed44418cf7d465cd5dab390faf65f1c1b98f339922dd801009722a9d34681269aacec6a984bf4120e5092dbadb326854bda6540efecf0b42e7c320c89b0a73f4bb53db8e7e3979b3b40f8e0517f7ad60007fd307f60542543d89e9a3bfa2b0c12d493d39daa708da109854ae01cec7bb7b32bd0e35607484a6a4277569d4038a24c421a8d9da6e0d14ce688f89bde0ce97a70a10c4134719f0035ab49b1285e389f829f3229df2fc953a795e61cefa1cf3e23e73e5740d3ffa6c3eb916bee248232fd323c49f9569f144f4b0781793686c342406fc20141dbc8021238e4253d7c3f110c82ddcc97a2824f8fc941db56d67499a8fd2804d1f8211c1e39a763421d884f72288c8dd54f17b2814331712a4f1218832e439f87878608c3dcee601d44f90d2e2251958f260700e2db6e5e24bb1317a0a8910bc8e03285b2b062517b0376a5359541dc426b0cd14ebf8802f777ea052a0977754d15c3c50f81c4db65e128279d5aef39f124972c1b14adb509a9b6fb3a26fb719f2389536195cd01f1fbf20092147fbd37b0c2e7468699454ae748ce39530e479984decde8a62f9404a2e69aed7f34d833ebc2a49150f43a5c1f10ee9bd9e15635c871a02dfe9caa73db840d0d5505568310686b893bca52b91d039ecd6435f60d67803743bdc511aeb0efa40791747371c48900c7b4f029daf821742cb0974e8016811e46a56183d5496123b0606068e0136b03d10bafdd246091d85898b1fd226b9ab0ccd712b77507d032ce8bb41f8b61964a53fbc12c7593880be2800e25edce2e633a1a0e45e4fc03c50e7f8067be63ec0a92e0fa543cda39a2460979a63e0ad187af3094b4ef8af617b158b895cd3f4e97e70875764577c004886de54221abf67b7e860a412b9daa916ef5528667f95fd7d0f3c1b7a459831af4489d363189ae359658dbe5058dccf4990b4ffb490a710a3cc0721eaf23c9e5aec313ee07c00e2d52e43e4fa5158a4369e9c2d0e83a949e310f4fa234d7f361f3724de6741c7ef4805c9bf60c9d15e8eded90042da5cb6c67e2bd1aa1bb9549f068b1e9a121b1faf28cf86bb3b145f52202a6ef725d1abb81bf004c844712d3710341248547c9022b00d17e9d1ffa575d184b4143d98548b8e8203095f2348851baab1f1042a10d288aad25fc0a4cb3671e8c129418ab3cdcedc9e2d928a4fd034e1a0e23a7d96051aff9652f29faacd8f12f86a477898dc1916c3171068f23ca041f657e2144794e6e517c1d9fb528f22f9e1591007a02474b596cbf1bc539d4a451ae7b263f37d0af37c4091307f08a1cb3bc4a3b69670f5691dba74003b316fcac09707dcebf26f1024eaabe7f311b508da9dbe852f802d791691498ee3d1c79332d3e8ddf94efb81b87a033fe02fb506e6cb3e50b4eb31f55c6641ede24af63e89717e24959e7fb466f55806bc788a3f287cc99b27dfa6cce06261087f0eb6a0950091e32d029fbacb134e7ea0d490176217e8970440bf8bdac6292c42fa02869afcc8911a9fa7657e5286426c212620f993d3994d4542f83f3816fb528be593871e6d02815cffc7494d936023e45fbca8b2cbec18f32f3e64fd55d48d6b5129e3876429ff05c8e41b0df4f94c2674bc2527957e865b9f5613e2f0dd1c3eee362adcfe8796425b5397d8079813e217a200baa54038af9af1fa0f30659a505694dfd20842434043e55f1e663c8038005e4e9ea2a95fa03c4e410a6fa5ad1f924adb2312dd390b31695e908e525fa96ec67f2260e845e0af6d7596c77f4cbf7ccd942adfa92befb9e2b479d8d7defb99f19e840d369f07907e3b3b2ffe50a54e5e48663b843f578fc04cd3f73c6d7851336eec360110bc801481e339abfcd8143f0e33bae06bcca6ce0306ccbb80f268cbf174e001dbaf0ffb04c42978c1a217ff8d6fbae06a1e29acfc9b387bb4238d31afa46d7c130ed29c2f4cd71f2174e8000235e83451c43cc35a9cd67094bc01031bf48f0f769e6d490b974a9f788b1cce27d38480cfa9b1d15a4932cf4527c1950eecbe830622fa5311a63b9a69d036eaeefc8824d82efc84e4c1ec2cf1c410713e076d94062409e908f630d06cb836fc86275397a052e75fd610bc9b45a79ec80113ef81060197f334b65c5481b7d939f56006c4b99b8020ae06e7f124a850bc893b5dae810ec55620a5f0a72c65f92c85de77c6429c0395118ef6c6826bca22e635c8f87c4725498ea910168d62cf79031dee776070c99f648a74113bf2ef8d35fae709bd1f9472677381adf06de78db69b32fa410a9bf6112a88dc9388d8afdc129fd19496fde41126dfb0fcfa205a85bf229e0df8783cc5a6bd4fb4e4c14b6202633f782b6e372580fe2e787c89a2b30d1887cf29ec35d97467b05e0318d6e964387996899bc6c1c6e2bb383bf8a4b04eafe544dbe70865e04bd531d886f2d4f84026167f063bfd6a933fcde194a9ff43771b11a081bf1317c391fcb8e29f06b89b90110d0f5c2ca4b59c637e6f4a8f2d24548467e364b8f1529970423337dc4d1a2b0f38d8e547a908f576ecc0bca0d9d103a193fb416e723e068cba4b448173530fc06c46896ebf264c6ff725950ee89114af1ac4c7878cb9e113da7039963e2b5eccc2d7cfdde1a20fd491f32774a6f6a80263fe4b92264f632c869bea71b61b3cd73cfc25d0537581f05154bcd8657ea4de448d0d2d615ee457c492bac726b04fc542ca3e806ad3bb652c39dfd894ef02e4ce37b681f1335256fc1018776e890b0f774263c5e7259b0fc58ae32b82bdff9b01e8dbaa815afec3c71028ec113c29e183ef433f19dcf22d4a086d3a39d4fc0dbc46fb1329536ff8a6429baa23c7b910416e3a2cef6e9e891eccf0f0d54cd0f32a75947c1f162bb744063f1e9de83739c3c8f118527d00940a2ef76787263344d0ff10b97e5003280ea90dcacf75cdf922a4127bc881128f00859833114cf57f82eda6e3067abb44be8fa44194e309f4e35ed6283f8863e296c026eeaf045ad93c36697d3253a84da62ad137093a77282d526f2a0b8fde9435e461eade453809720f951838610b463e800bebf11cf20f84caf015a224de5198eaa69087cbf38124c98104f9e406ca2ce84288d8fc1619526e456f834b3992c603eb98703b27105d8c73ea8d81873fa8a882bf6084e1678b3c5c00cba6b1d87d7243312ae93420327c114c1e7cca012f9f27559b57094cbe9902983c6c089f07014ca1b1746adf0c9d073f8da0e7f3562fa7d4e192f3908ef8b0107abeca82f3135c91f8198a21be44a9292e6350e0d7795df845a044b991187d9cc800c72750a1f0170b60f02450310e58b6b6b7944b5cafddf0ad0c2c3eefd39127ecd4742b22835c881ed73b9954ddef09388fb3a1e311f9d0bc86a90f2f62d4016fb1a8a89580a6eee8a5db4748117a872f4336a645243e42aee3186818f0cd7c6a2c6dfe4de181f41096f8790a5f75ba141ed9f1fc54d27f5b14fd0388db86105171036ba27be9b2f0775f7bafb69b9f458190e6101f713dca3aad63939837cbe064ef212edd0298c6470b4bf29b28fc78ba16cb479cfbe1815bc8f88d56856730b0c8990c32a52b114af9312645f612c33e7fe8678b572931f84c9ab4ed35646ef8873220ba0a08d253718978e89d407f2d29769655f015e980d972d25a7ca000289e03cba3af706443d3a19671b60450bc114c920794f7b81bbd91398d48737ea822d45f50f0f8ee25a6bf6d98f06f38ccf021cd39aee10bd94b2980e35f5c19e3656469bc8d11077f93b1789e0e397ec29fed39ea18f80f4fe92d6049baa2aa0b0ff3b5e51aee3eed337b9a1ee50f9e23512ce12c1bfc6e826c78a6ba3bfd9661f1813ab4d82d4a957da93db1d641b6e2f5c41e9f5321972f20e36ab72ca8bc4ea23e37dc5bfdd4b2d0bfe558e204109df89d38293f650045173e797c0c0420e841358eb882c5305a8c1e05ee69bfb6e2619363e023f4711033bd963841b60d3c597c53971e1acb69e8673c0369275a811e0f5da33621e19367fa13f6290445f14defb81dc3be1cd5870a7a1204c467a037c26d0cca7109f09dfda9b0826ba226b71e1c4067c6b8e39fa2a8fc141e057b4ca101df65cb99ee7445bf873585fec8abef352da9f15e566cefd828b6a91df8b8d24398b6a242cf2bf380381a9b41ff12616a37b194e824fc98fa5000184e870c9776d024f324a9bd3f42e8e047f9b0f2b196519ee61092374329c183c2c2c5fd44a8e34e0283b661591a6764f8e5f90808f3f7b2e683641e1fc009777b1941cadf1cadf496ade9a77094a7b11e99f925907efc9a133ea7e4edc75926793283567a1021b637f3a7d1eef086c253e281b73920c6f99a2e7abe09dbdd4322437c18ecc7e3199243939973f177181dea4f5ec987d6c0e11d94685e93a72bdfd08cf30538ac681c4e167f41cd8b1d29470dbf504480eb5104f43f140c34d655d50760b1491748c3f402512aed492e083d04a7867f1006c6975132612349c5c8978825701498c0feca8be83a8630fe1d2ba3740c12403c4d4f915d2307d2fbdee2bc10034abef89566cf10bcf3576d5ce81d6b2ab8b6c4e71f7d613a9b428fdb93d876536053fe018500be434f8a3fa0b3e46d14a0a28f586df9193128b8dd02075f38c6e82bcda5f9412c25fa4b93394f53c8c43d9d69e28cfc6ced00578a388cc3315e2785cecf40b073a68a24cfc1099d6da7e0cae55cfc784d54c83ca0a618de01039ebf63e8419329a6704191523c222410fc8a4fd8a01e8d381f3543b481af54ce45f1f787b2156ec311a437f142d059386d9f27a987cfd994c0478081e4182628d991ec70711280e6cd75a189e78d08f14f38097a3313c4b6193e4c7f2471669b795af37e7f8f76e3172c1e2745a29b9ca27ef668aaf5ce78f8602431dbad8ec25f4801e233588d712b3896ec278032f81bd7c2be1403c667c96969b6e9260f559db39548983890aa241f238e85ef90f3e633ed40fc2e4366fff246e77fd4e6f764e4edfd8435fa9e26a5fe8c021e3b4982456fa291915d43abce2f4300ee0e67e0277353c6b3fc86781799da43c932f5276c1cf9ad15bc981d63f692c5ad5fa1d51dc0bde414385972c516837e920e2d1b500dc1b7e446c7d1ccb0f0568e6cf0210a8e3c2257c16e1233f118594a3d5c8521ce48a782c6f22875423a98e8e7a6f5ebf6a6f8d68ba9c353e4bec581446f22eaa41f319ae46c9c7cd1678dba388d1d37362ce0cc29fd85f9a5c2c4975f48d13518173fd2a34cfb11989c0341eb7b293586fc290038be3a28e84e25f30ffe743825110fb4280bee8016f7ec026832b98a4560fbfdb0e0976f9ab61528a71c4b1a005d278989e7a14486f311a2e9ad9e14d17e758af89a12445fa0c3752ca6107d0d1f9397d445c3eba0da792b3fa7349b1f5bbe230da9c97c7aff45d7104fa285fd3ab4375b0d80e6ab6074e7a5306ae16628a4da26bcbcb82133584fa44fa06772e78813320ae27c84886c0b07ba7ce21c913d8a6df357429978316e34f95874bac5a46df20740266802a5bef884226a5bcad8865fa395e067d4d0f172e2266d1a774a4f6c456c5389407c8c0d647f0381a3b3b1d26427fa245eed14f60812057d4319d3e3bf4c7f0783d4adaeea3ecf17047d8848097fd363d459171a7cd24aaa0da30815f77026cfddc4413e1c184876983c8dce7282f10db29e78f202943d8246215f72d7e5c5a069ee44ce5e31cb8ec72b84c545cc307bc54557eec59091ff091b1f67c08d975af3490b6a23e1c95c82f494caf89e4ba444daccb0cc1f0070e72b6958f104c6d2e83a49232f878ddf020f3f57c221d11fd823ea9f7956ec54859efe485602ade840ed4fd821d09118acf9368a02f7e3967b76caabbb4cc8f364989df4639911df655ad588fc26f80c254eefc38485c71034f9a51eafef3161c519a83df94125577b521bc257dc1df1a473ccbb68b1c171a409fa1e5d95def08aea675837fe0cc0e7b3a8106a42721439a017669bd3e3a92f541ce09ca25dfed49dda962245ba95bb44276a92cadb9058340b670cdfe2c5f59e924cf9ea54c96694c5915711cce40b08507227766ab6073721dc0b090bda0e5387176c3ef78607381cab0e22bfa208c183a892f7583e02781c0e98dc4b90297f864b229d5492e6d554c1a04350fae349a0247a1b99e0afd13bf053a87e4fa58f9d9f2266c71539c9a2ab1832e493b232e939761c3d28071334256923575e20e22ab69070d90fa07719d1de9484067b69c7e7799451a4993b06bd19238a7e5341f51de417defedd792f311eec47868c6f47838eeb6913e49b6c92e15e22209d3019c00564f2f273a0505b8cebc22f9035f5912118fc50c6b217ef143e9f215bbe869be767fee8700233dafc1e19bd3dea080baf4b14a695893c7d8e4a69bb0bc40a8fb4ad6812090a5d54744c7b20c5e8721ec76c0f4312fd8a52c1335735c7343841a780c1e83f069cda93dc48fd11c1584703a4702c15695e02d1c16b51ba4f8963f29cdc8e6cb844a44311d5a7612451971369876725593c9727a42768e9f27b6d5fdec91d407f5141cafeb29bf32ca71e5a141e02dfa40cf552e8d4f13e4d8eb897884f9e064ecdc50896793f6a499c8e5415df0b15a6db408a1e24d38bad284b863772c5dc8028f579f28e0a4d68a380d77024c5e9dc2073c61c5c768bc3121e02d3809d64539ed72952e0dd60ddf919272474211dae17b324cc05bdb9f95457d169eeecbd230e65be088116de82b06b67457ae1747cb83c53e379078daee8ea283cbf226a8ade9bf4e57930ce5b0291add728ce769540b66f81b7c4175df2e3fa51d44dc87ddfe149e3eb01a1f07314fd762305755e539b737bc973e1b72425fa46b835a7e04843f301b2f65c4e5dd95b04277857a546ef838cd61b3ad9dacb08301e91aef53868988f70c0c1af1123e88937b4166424d28bf963c8c9ccd8784a52e2e8b92d22ae8005803de3aff5b268d59660a3d19d666eff28470cb7a264b89188427a9ff981e6aa427a25c9075e640da817f4e4b283586578317b1a6d37794efecb87b07d06c401cff444f0cf5c3d1f14c3a87f50b97c50948ee65261812f3aa2c8f3186db81d4613af78638ffba912e01faf12dd4723e7564b41ea5dd308bd3210f4a2789cd207d464f9991901b6163c329f812775b34186deab84826772c7e74867dfed81a3035220b229a19a7d929b45da8699ffe31b301b4097c6efe44af14133a47788f1b5efa0d073ba448e6f2236e153540cbccb1734af52754313e1e0e2cfe0489f2565ce0789c2ed2de18e873933f5a28e7470382919f6030a487f429e9c5215f5adf0d0de6480d89b3ad4fbb9cb18af2a7bdb7552edfdbce8649392d3e4e701fac990cafa4514fa6c42403cbe0503612f9ab3baa4114a379103957b2ab2e4c91e993c9798437a1d1bf265fea61a5523450fb1e0507749f1e70dfc60db6255189fe649725b9991f02b310a2fa0cd98eb50b46e40a3a8eec1c81ddff44c7ecc550287c3c4c4f3b0e873681e4e1f498ed6774294f8cb5056be4604833732c98613a1c3e198581bfa05d282f7f86be1a624157ab240d6e30094be8616364f6851f40d49b86d23f315ef24e0cc932a13e38a70038d07a2c047e852d309ba40f90d988078a2347c1c110b51e3399f0ea8c01b1da1cecf332192691ff9dbf044c87e04919a6dd2a97cdf56f9949dedfa8c213597cfa4d2652adf67bc74954cb9e57b59e6d7d08f9af1ba7432d9f585e524ecb66beb423b6a3295ebcb84c23374f932932cec521b359fedd2c932df240c2b9fafeb54326acef1bc269fd0f8b9cacab5852e1735a1cfa7527ea1719229cf4a992dd48a9a4bf975996fdc3e994ab99d9f2ddfcb265fe844cd560985ceabfbb6abdbc2f29a44d49c9f6fab9c676552b9be70f2b9e47b59b695ea43cda553e9b233b48561385ebeb1cbf7b2869acf6452764295acb2755bf6752ef95e56d95275a1269c84b66d0c9d656772e98459a99450534eae70eb945f1766199b4ce8ba542a99f0d309f3bd2c13500f6ab6c95719b7f3ca4cb250a87209ef096a325de80cb7cb79665d280bc33375b942076aaecc784ec24e7796e5767699cf794a95f2bdac9f06d46c6367fb649fac0c4d269db0f3e57bd9d6655d964dbedde54df59fe6525e425726dcb2cef995e1d74f53c9c6701bcb4b767db239749fa6fc945b16fa64e5e73cbbac1286dbc01830c9e4d36c63d84daeac9c845fe61376957c2f3bf785f655e20bed6b041f355edbd36c5f585ecaadccaecf57096526d7967ab1b97ca1cee7938d974a3829c34a177d2ccb32b51ef87d95abcb64e164f25dba2ebb4c2a99f0f39d974ae7d3855f36562e09759e26db2ad9d9f926e7651b2f9df2cbf7b24af67dbbcb5b359e66127e9f70d285e1e72ac32fec7c5d12fa4e937d5765d219bf6ff2c926675639f33d63b4b96f4a272686f64517a2701ec1478dd7d0beced2dcc4c49c72de175ddb57538ece7d533a313131a532b973683b4d66ab7c59d85d934e5776bec9f72b4eeeebec0bedcbec2baeed6b29a815934fa7dccaf3bb7cce4fbe975dcad237e6ca92e93acd24f3959dee0cb7c924bb2ea1cf3f2af339356bd967b490ea8e693a4da5ebc6affc5c9d2e7485ceac734e73998ca150a5bbbe33ab8c97cb98ef9d65e99b0b6b39eb13eabe4fd9a97465d6292f4de8384d66f2098599ced9e964a1ee7285f95e76c98a8945a57d55a752704d5ad1709af0facaf2cac2cc64abdf34e165f27d425b2754f98cdb55a974e3bacb956de195d9ae2bdb325dd65dd96792292b5f67bb26dd7895d758b7692ad7d8c96c97efd3096567d6f964d374bacba453c9c64ee6cbcab1dbb27d7a4d13ea3a93cea7eb4cb2f072a99c63be975d2adb353131ea1c5858cd13139b6569544ccc7dffb49ae60b5db270cc2661799964c6719eb4aa646759fab6b2b32c8dba4ef97dbbcb33d3699a49f75d9f72729e5fe733995c977c2f2bff49a1685f81b19b9858600cd8f2d089cd16eacaecd39597701286e5e8fcc7649530fb7697a7a6d134db569974cacf1686a1cb3699649e692adba5727e97ec3c2f9fee0bc7669a72bc742a956fbc842a59b695cb349f4927fc643ae3e5ebb6ac33d992693e6739a94cca6b32996c5ba8eb8e692a57d98d5fa5bc949ff07209af7c2f1bedcb63c528e176994cbeaf9b6cdfb76d97ca242bcbaf92855d79853add9985571da609859932ec4c2a6765725e26d795a94483693e65766526a1cf64927561263c8b89c1796c9edbbedde53d12fda5f94c3267270c5d269f71ac9ca5d5a698d87396a1b39c9858f529269697b77a693299710bb7c9768e5ddda5a99c5959669d2bfc8499cf2574e57bd9a4527369aecfd519c749966de11596e1765a0d2cd35b9acca4537eb2b1729697cf64bb84b534df767db6eefa6ce3b59d59e79ca539b370fcc22d94955d386e934a2ccc65cbb2c93509b34a97659930ab7ce5f9a94cae2ff45d67f9b926d72b4da50b2b972f9c4cb2f19365dbd94a937d425b671256c24ba5fc42d9e59c989898d8cae6b12ccb2ca3ab3493af3cb349160a7d59e833c97493682acd986599ae9b5c42dd997ddf77161363e6b1cc277a4a338e59b74dcaf2ab9c67367697ee102da529bf4c28dbcac97676c2d0d8094d0ad1519a7192855ba813fa5c59a533f92697701eab3cd4509aedeabacae4f2e95c99f10a65a14f9af2bc64caf2eb7c2695ca3529ad46d9d0bee89e73e05cd28b76d294d71976be5066dc32633629cf4d9a4c68f29ddfe43b27573676e5964e49433369c2b0d385df64ec4cb6b3724ece626285b39f98189cc716ce7e49e50fbda4e984592774a984b6c955a97c9931dfcb4aa151e6dbd7da0a7e7d39937360219d9858f2a5fe0502f6c9d04a9ab0ab74ba73ab6c57e5aa642ee124cde553c97c3aa16bdc2e97f0daba27346213ca642a9def537edda4d219275b24cd16ba64a1ed0b653a65d975dfb54d1f61994b787d95701266beed32c9aeacfc3a67660b7559f965b24911da48135e5ba6cc74ceeccaaeb2fc428b345717ea3a9770bb84aece27bb420f9bcc182a3b6339865b662b2bdd9948f385ae4f1786db785d93cba72c0f69b6ac72c974b64ae79c5cdfd7290b6942e57809c74978755bf7996ce320cde7131acbb3cbb66ccb42974f2690e6bb7c32dda53cc331bc946119fed14cb24be533096de7f709cfcbf7f5d164df182a2bd9e5520985e5d67d7b3495cab69d95ebfbb249b65d42953c9a4c18ba6497f1d2957734636772f98426952b0cbb6efbd4d17c26e3e792a974c6cf363927e33647f319aff3ba8c9dd0394ebeb3cb1a365d38393b97cb7556ceecdcbe389ac9769d9771ec54b2af0b6dd995ef65d5bee8dabea8255e5699b7b26f777969fa46d339b772ebcab0bc7cddd63933994e6da3c9cacc978d97cae50c75c2f332aed16cd9a7fb74d975e93e994ef7a974976f7779789a4613daaeb0d28593f30c85be6d3b3fcece5609659fcf187eb2739caa19c7ef7385d9350965b22bd38d512967679c9457e61bbff1bc264f35e7f66d59a5eb94e3e4927565534d560985e125d3095d4293301bb38ecd95f99499cf997dce4ee7ec3e5d65a9a6ecb64fa532099593f2eaaeab529054b395a1ae735e673686dba7fb7cf68d6ac24f6592553eddb75d2aa1b0fbb2f18b829d4f9819cb32fbb67c2feb2edf50cd395e5717ca2e6736e9329db30bf711ce6bd3b985b40d54d3e98c9dcaf6e9ba4aa60b752e577709fdd4949f731cb749e63cbfab92853eebc4a2d2a8a766ec743ed997b964dff5753a9f5040c1a898d83c7ddfeef29edfa9b97459a5f38d99f2ec6c99f1d355726a3e5979e95c3a9d6bbc6499f0d3c9dcd46c675766caccd7856726bc849954bfa8201f1a0cadd68989bdb0a6e69b4c42994af9955f3839b3ca27dfcbb698a3c9e93c37adceb1ec3bad5293999a4ae5735de37576954ce62c33a9f0b44a4d7e6353192b93b0cc26e5a5f27d3a63372f3affbd6c61a0f4a96465a5e017dd975329f8c56ce7c7d47ca15078969dcb27bc9c65b67d95687fa91933e7a712fac2f2bcb62bcc425f4bcde7cb2edbe40c852e6168dbae6c1eb352d36d632833c96497d067ab84bec965da536ac6cf25bc746118aa5c9db052e94e6acace799dd7f9e9b6712caf4f36e693d49c9fca566695ee3b2b9f3133f9f2bd79d4be9665466a2e5737f9bab3ec32974a586605fda4d2bfa59c174ff7946ccbbe221e5293b98432673996ddd6e92695ec92faa89964b26bf2c9c66bcc84db58d9fe49a54e47cd765d95d0e4ea3e59e752d9326165a36652194393ca79752e619751f3852a974957c9ba2e93c96c996f7251f365c6d0e52b3359f87d2aa14bb8552a6aba4af68565259c5cceed73f9aed444cde713eac6eecabeccd59d95c9bcbc658ba8b9b6f2fb54c24ee6dace70cc2a97ecb44a3dd49459e52c27d927dcba71eb4259b635d464dba4ec3ea1b2ac7c9d33bcc68149b12fd484a14919eaca6beb74329fec1af3bd6c4ba829bfee724d3adbd8b964b2ef3a8df99e7952d96595d32a35c9d864593876c62f1caf4b66525e95839af1bc5ce7a7bb426567ec642adb17d47497b2eb74c6f3baba5068bc5c3f50b375ddf71927e136092bd978b9026a2e65770975ae2e2b2799adf2e934f1a7d9c2ccd8c96461e713bac26b52396dfdc0f11296e7f9294399ab1ccb7c2f0bb7ac605e15100af7619f337365ba32bc8465e8ccf7b2ee52d0edf934e3d829b72bd319cbd07856bac936b9f67b9aacd2552a9f4ae63bc7333c53abd338302f4f8e0399ec74aeaa31ab80d0e4875f6c26e77655269fabbb42994999f91703f6315ba59e969d59d68de1558693b0b2705a8dcecae91c8db2d17d9e662b4399309b4cb24ce6eac6ee3bff050ad2ad789ace9595e7e73bc330ec746358c9f7b2ca399685ab80d03bcd245486994c68ccae4c28eb7cc67f719ecb2eed349dd0f8097d996ff25dc2cf64bb9ac9719c9818155e2a365ba6d2d93a5f99e9745de59b84936c9de62b2f67787ea14ae6fc84dde56ac654bedde5d93d1d577e2e59385e3e59190a5de1394be8fb2ee324946561568663be974dbebd9c26547ecaaf92a994677765ce32cb64e33465f829cbec72e9329f50e5d35dfec169b6f3cc7ce5f8192b57277486d9374de5325e5726d37d5728bcc6efeba6c9742a6516dac65067f25d2a616620605fb24d93b942d9d8e94293f2fc5c2e67289b26749e5f78095db64e68eb7c99f29aa653293357a7bc3a9d4ae8121ac7526894edd9178de3c4c492d057d37c9df3fb8c59d7c98495cff975ae9fa6093fd7766e95cfe50bb7ce64db26d965fb894dd96d9dc9967d26e179e954b66f72f9769797e2d134ddf8d9c22eac54c64b263baf62627f7ff3534c6c9e9e69c2c976b994d935b97c3a936e32e67b59b92f6f0e2cacbe513331b1c2689c7cbbcb6bbe99e6caceefd385c2ebcaae6deb32f95e5659058456f832f1ec84a16e129a9c57a52b43dbe42af8649a2d136e9f4fe5f25dce4c1886420965b62fbab62ff61dd3846558866198959fadbcc672fcb21d5e4c13facead52293fe1797eb6cb42374c13ca8c5bf7f926e1d9192b95ca2598e60cb3f1fb2a57e713ba64b2c9a5f2bf349531949599acab6493c997653e99ac20b56fbaa76c7b2fcdb9752a5718babef3ac8c9d4eb6edc2949ff3db2ad9a7f37dc68473abf65c9aed12ea542ea1d076c94cc64c2893ef65951b7e4b737661f95d9f50d729afabcc4cf2bd6c0b6b69cef17275c6ca27cb7ce1565e59be97ad52e73c25cbf6599ab39c84df59b9c2f0ea6c9532ccf7b2797f82802bbbba846d72afef0c5e020a46c91e4b938563a6bc64c26c0c3be5950ab37bd13e3fe695e6fc3257369edf95f9ca2ff409e57bd9e8fc97179df3dc5669a509af4f27ccb2ae7209afccb85df2bdeccab69006e6fd09023297f00b2818add2b6ca37e9aeef0bbbcbd76d5f7655b64fe8f3b96c6328335e426798ef65a773950d4d4c4c9efb02a54f31316abbb2d36a2095e6ea7c93ef726e5726fb8c954b25dfcbcecfa894393fa37051b5254c0d948efd94a63b339f2dbcbe2bec64c272e1b40a539f533397fa9cc62e530a93d92a93eb9b5432972dbb6c93c965fbbacce7ca26e3a5bc74ba73cbbaeede4769c66ef27d995025d375ca4ba8bcaecbb7bbbc130fa5098d9fcf76293be1f775dba792e57b5935b9afb79d56033dfc93e63c33db647255c6f2ea3e63e5b2fa9c5738e1c4c4e43e695e951a952e976f777979efe45dbef09275956e9b74954c26734dbe33d49563a8528e63e7fab2abd3757e9326cc26d9e4ca649d32d48d57e5cca4f96c99f39c8432a1cfd639b7d0245debbedde585f8254d26ccc2cff55d26936f2c3f994c184e4c4c4c6c5a9d03944ed5aa5465fb655e4953094d425739b97c5b96e98442f7a27d6d3b03f6d125693ed75556b2b3cc4299f3bc7c57be97cd935659c4e632292fdb671c2bdd250c3be33ca7207565c5c4a27b7d54aa9953704e4c6c06eca31313131363d9b7bbbc77f2489a4e67d26559e7ccc64c37b954aecaa8f40f4d4c4c960399cbb7bb3cf98f34db67fb4c26a130f37dca30935df2bd2c605f95d9cabd91e6ca32e5797d63769de1f565ae807dd522cdd765ba4b987d6566fcbaed0a3d6ccaaccc745b97c97c6365dcc2f00b856ba94c224d661bcbee0c9d97ac93d9b6d0794833e95ce517fac2ccb985b2cc25cbf7b25ff22bf8354f05a9d2bfe797f315fcca835bbd17d284972cec7c329feeaa5c2e5f19caf7b27979d2ea07692ae116fa7c5ba812665b376e997c2f4b2d8c65177edd07d25c2a9df3ca544259b765ca3354fed1642e677985aeb0f3e9ba4b27fcfa683e93b2ccb632f465d9d975cece1e4d9929af331386ce4a66eb7c3a997c2f2bf827e88287121abbb23ccbc995094dcece67759ea3521733605fd56d55fc8ee6ec5c61e5caca2e13ca429dadcbe175345916ea6c67d9659973bc7cc62bdb9a7d8e66fc5cca4c175e57b985ae4e96dd8b4afff2a6d2b57dc3e63ccbcb270cbf4a28ac8c954ea6df3cb748321f475366db577ee5b86d6736669f4fbe975da7523e6a0bff8de60c33992db47532a1c9977542932bbb7c1baceb26d7b75d5d25ac5c57e5eac22c3be26bb062539e46d3e974e3a532c9645f39f9ca30131e31a3f984dbe4cc6457d79567b655ca6842dff94d4263189a8ce7249375c668c6d016ba6c994c59562a5f2654c9f7b2d499ef598d0101fba6d597655b11309aabab9ce5a592f92e6196856599ef650363c0e4175d88bff8296d5bdb17cda51bc7f152862e93c957998c5931313131a50a17cd2553765dd6c9c230f4652ed9d9afef6faec6693088c2a6b35d67a7cbae712bbbf333093b05a9844db865e7b97db2ecea3edfa42cc7301ba245738d9fcb6792193f6165d27dbeccf9d9be0d369f4aa8f36d675696a1cb77f9b2728b4229b54f9926d894974b99f95c9d4ee70abf2d33509a272d6459e65c8d6557596d2a67270c43932c737657a6d385f95ed6ed406dc6f3dccecf996595ce767e42937c2fcb4c2693cab1699365c62b3309753a99f1fc2697d1f849755916cdd6b92ea1acbccef3fbce4f2593ef65db166e9fd0695e921d0b6ccaaf5276e3a732764299cc765d4a01a7b3539954c6499b6d7219cbd0e71acf315329bb4c6a612ce7010a460b6339a9948b36a1b12c2b5f788edb16ba7ca14ebe974d9e01365d2534e9749db07366932beccad2681c75d1fe9aef2b3f93cfd875d956e942db27dfcb7ef06bbecc5519bb6e1b3f95ed33997cf2bdec5c158cf601ae68c2ed92c954325d56b9742ed979c9f7f635d7e70b75b2ef0b3fdff95d6199ef655b762a285dd90f7c4d6532f964aeb1127e26e1e77385f2bd6c612c77d86bb22dfbc2b2ac64b2b21cbb7f31b4f95cc6ce7966d977c92ad73829f3bdacdf3cb79052fb58107313eabeb0527e2a5717969570db4a01e526bc7cc62e936565260c65325b99ef65a382d43cbf796ef1aa3d9b4bf75d5de7727d3e9dabdcb24cbe97e5ab46a5801e9ccd5929bbc9f5994cb64a78e92a5de65adc5c57262bbfeb53c9543a97b15266aee9355fa7f29d9d2d74666527bc845b29b58f0591d764aed055a964cab15286952e1ccb524015cd18dac24fa7b375c6cad7f964a17c2fbbae6cde609f9cb7649b78cdf9995cdb778597c9e733f9649f7c2f5b9da9b0bc9467ea340e5c2edfeef2c8523461a7cccab09b64c2f1ea84955f7421bee6bd682c272636ef5103a555ea175ddbd7b3ef6f4e4c4c4c8c6597d32af5a3a0682ae17676dda4929de525cb5c97d059ee5dee093a67595905842603ef9a71ecbeb13319aff2fa64beca98ef65ab53a933a670825dd7e70a5d325b66bc7cb233ccb2d9395ba7bc6cdd670c6d6766bcba7c2f9b1c61c25d974a7639439fcf25749d6168cb8a28113b6767eb5c5d985d59e5f36d992c893a26db269fccb68559a8d2753a63be9795a57374c924d45d3e93afbbc24c99293365592a37f74cbaecd24dc231b47dd757b9aead9c5cb36de5776699b133998c933053e67bd9bf40c0bebce73c384f633e2accbe2496d0249465ceefbabeccd8c954b62d5d5c53f93a99afdcc26e0b9d5de8f2c9477dd925dcf21943d7a5d36597edeb6ce1e83c38e74901a5d340b69d7b6b325d964dae6bf219c74c794e3af95e36503a95d9d5adc99cd7956d9fca769d9fc9a5cce47ba5d524dbd654265966bcb6492553e92add6554faf7cca3b62c3ba2d9be4b16fab2adcb6c61a8337ef2bd2ca0740a75bfe8427cc1826262cf7910503a5513133b131363bedde5b910d14ccaeebc9ce33986cab1b28d61be9785cfd8e0e4ba3297f3f2c984b6ed9399141313134b2aa7d5c0c0b5b67dd71666b2ebba6499ca95655f1776cab133292ba1f19b9467e52c857eadade05f20605fab04148c26ab80d016219af2cc74c2cee5fc8495f39a7cce7c2f5b259ca3ee175d882f3131b1e95ced9ba37d6d62625331b1ea137ebbcb1b546bba30fb8c5fa8ec32d9e713863aa15029b3add99c593839c3ccd785d9e4fa6ca1694d26bc3e9d4be7fab2b1dc26d7e4920dada95c9fcc9639b74b670c7d2e9f32dfcbe62559965db2cf79300977d69c93c924bb9463e8f3d92695f1caf7b28554aaf44fc92e9764664d9865b6f1ea9cd764cb26e7d6c9f7b2792dbbac0242934b10cd3639b32d3386d7799e9f32abe47bd9ea1406f1a1999ce1a5bc54b6cf24ab5c63e6cbf7b2792f5cd67457786d5937392f9f4a25bcca7c2f0bb3af8726ebb62edb266578863ee7b78d5bb2e61b27619829b350a5129a7c3a67be979d56a91d9af00cc3cf96c9b64f1676aeedcbac1b6bb62ebcbaf20aaff3cbce4e65cb6cba3133f99c95ced6653a63a6d2c9f7b27c54c1c0bca914ba64dbe0e6dc2ad765f27d9d4a799ee118caf7b2d3be698b959dab7d531326aa82805f6a725fabf2ed2ecfc40b335f97b9b2ebab5cd75509afcc65fc26d9a4cbbeadebce4fa553c9f7bae8a30a7ed1b57de545fbf202a55379d94eab81c9792a7dba6f777974cb26bbb2ca179a9c97d0e5d319bf2edfcb4ee7a8b2e92a5d59a9846326738dd7559e676a9e3c13ee29d92fba10737262628052391a4fc55ce6db5ddeef709bcff6392fddd6e954c6b2fc7442f95ed665269b505719c350269c9c93cb151ab77c2f4b8d020afe11b2ecb26dbe32fc84baeeab7cd77976be4fbe97750a529949b6c9caf2d2f93a6196193f992f14e67bd96a9f136ed7a63bbb2fb49597b1ecba4bd89df95e76a96ca973cc64e12a544a75a9739c7cbbcb2be3d07c5bb785caeb2acbf0ba26932edfcb5601a1c92fba105f62625540a898d83c953ea9f1d7da0a7e8989c9f11c7fd1b57de5c1eedb5d9e9b5893e94ccaeebb4293ceb54dc22ccbf7b279723496ca6c3b7dbfe8427c997da17dd17dd1b57d3de7122d6239e6893026cb8457985ddbd785936e927593ad18e0e0df9f5833b974ce4ce8fa94a16c9229cf50be976d219deeb1ecab7cbbcb1bb121ef49159ce6e5756960e7c1f92f8f30068c90614ffa97b717eddbdb93fe6148e6fdf5f9ad172c58b850e102d8862f0b14324c582560f0f28a30010220840753693576e0206fa96c3334b0d04565c0a0957671655820c7f3b44b018404d5798fc1164b7580ec0304945ed06a276435c07280c05d3e3840286d518560c02f7e3e67bf024b65eb45a065f3dad92ff61ac04eb862616855f08100366fe6cb7310c002809682551e5815a0f4f9ee362f2f8ff55b2adbc0e74cdda0f32e3c9b9737e7e55509670aee921253f4e867c0385a25b6288903022e28f18e24b43333101fca3c90751863c2ef52e9265b76e52016b601c3850a605f142648f08a00e18183065d0cb8162870afca8a0ad2e3514948a2a69da75b0d506f1823bb2e0363d6c26071d1d8c860c5621d0cd4c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7c7548f8f8f8feeeeeeee8f8f8f8f8b7fee6cd1e46ce01e1f1f1fdddd1f1f1f1f1f1f1f1fd94c72f48265c1131c9fd2e49173ea0946e2d3047168ac2f6e2f00c4bcc3caf03ce359e0eef2a88db348936a2bd243c69df898b4fd9851f00708295d0210ab27a4498a7355ed1f43e270bf0d88be04ba3bba0b4e0dff1413d13ffa10781d3baafc0cad452e6946a317a1d27b4f82fc68061406381f1d470ea48a9227e374769f4b511e4c13937d280ae217a8e26d26a7d61e8ba4a40f61b4e4839c8aea2019fefc825a8a2d4685d0af9e78e93f83da8d7c9af22718d4b997137c7acd2730de8668cd675a61e0e1bc2dea196f8a38900f79bad195fa5a06e907b88af101d404d0a9b4f8f8202f9336a2169a7cdd9145fb0c401fc5804e6b9863f41804e4f01d8b87be2bc7042fe002d05f1959e0469858b91e76c6ebf1b0e44e2f50d74e52f82650551fdb62c681603ae2a6eef6fc88c4340faca0e119e11c7e0eb4b5bf62e4a2c1d40a7da84716f619ece3035d001b71cf941366d5783a92463d1c0913348d0c8bbe8fd51d971046c0eb0d52b1656ce179417d146c1fa9107c13e6a39b8d187f8c43246f8269f016beef2378c1f3443c197a4855d45711264d3b6d0078345ab4276500fe8e3c1adb090dd901512ab3612f841e1393f1194482e4394299d14ace0adf0590475e88ccfc4a1e69d1599e1cfe928cc6578c52cab72ecd692f451bbc85974f7ad1400c873184f2222a564734f54f2433c505d7083e2049ac9f42b6f90e16f038830d633f8686a12b51f4c7aba3dc5e4f852dba9520e6b9a45af4e10d3c0ec767f918ccb69c4e8cedffc011f4839a68f22eb7a723ba60fe46e5cd1fd8524a2321b3c60395b8f1640c817c1b2c61de04f6f232434dfa0322a28b3aa5f7196c187a1d8652bb4c8c197703634f130649e172141d9bcee7bcc709e62f377972bd30963c04a31ab7b220b9b7a25eaee805950f9523ccdf34a669a51905873036eaa3d09d39982ced56d6249f2fca12dd4903134f7248cca75314dd13a2b677c6fd782c475f76dbd991afd267cefb29c4c3b7442ae182756dbe2dae82970282f52318dbf82637b8df246660c36d59f4108e18fc14a0f92b9d803f4d16040f210985cff270ff7bad5fadc07a1d69edb3a88bf47f1990ae09717d36cd4c9a072745374300eddd48d2f468277e3893bd280f612ee14506157a5a8d78bbd8c2f748506e1e83901ade062ad1e574b92ea4c7d5063509868bf5b0da8cd4297ec04c70832052e611caaa9b8a8711df56c5d157696bddc3999c5dd686c6df447a3f076cd47f756af33f3a18fa073769cfe001a9d71029cafba9d47e15c434fb8b16ec2f48e5d14212097a24174bdf3983ba1a2118df236dd1b3c400f56a6aa9fcce1b86fdb846cf8120befb6e9bf82f2e80be8e2be6f39e193fc34f8e6f2582db90d04cfa4c5bd6341b28e9d9980174bf059b5cd3a3215a8be0296fb283c86bd959f4644ce6680c4156775447c3cf792be0560ca23ca42a6a5eabc0937d64109a87851af42b73b69e00830bfacbd28fcfdb509d88c5e69d4ce8e26495e4789c463d3a5359f2916390e80cd5364f264669c75833c8c718233c2439405e07a1d7ae0373732e9710355698343f070e16dda7400d7f468af4a5d0c0703d61c6f61a18ab67a9229e11aad8119f5c1b55863c2f47c6909d490f06575ae8f48dd2dcfc102376bacccebd09f6612bf90373292933dff244f4317a167ca866826ffeb9d16c2cdcbc4b05a52bb0597431af1eba31cbcac7383ebeb630e467bc1b8f224e888fa154c0ff48217a4a65145c0e33f1c1daf0790d1d0abe4563b309c9c17232779ff4073188bc51b07d091c38fd5888151b4587464f65d4a3c76f1dfe00a9329fb426ca4f21a3461b6a63e614380dea403e0afd509ac2afc097c45960a1a4351cf9431121db143e40f80b9274e80d447a78861b835e0adce86dd390a68446882b88d3635f69f6d5beb01e52181207d065c4db0580e4678ed2f69e18187fc1d5b82016b75766d0b28518d1e48d166dd898e806f99ae3129da46be352fe04f01041c278fca8833fd0cae185b83aec4de5e15f85a8342028aa2f2168e6a344a17918879074991e261e879ea06f075df03a557af61d9b3b9732a8e2a998ef47f09a7ea6c594afc8b0ee3fbb2eef8bc0c56dc02c1cc918acf724a5e91542d9d155a206ffcba5014e0a49924f1622fe824d15be81a40adbc0853bcf94f1e7a7a61a9e112a3cdd49021647347cd46e715ddcc2b382f3e950e84bc270f14408563e81ce87d77810df6d0c4ef75082f14889987ccb8f1c7fe70d8a3e5376c635a8781d00d1140fa488d595942b1e4cab4cdf0955f662dcaaff61d4a08fa509e090ea163fd1a24e3a4ad5d407aa0dfa4d9628fd913808f48b37e2322ae5f02fa0063c5fde95f7b9f3e3e91c83b80d0b00be1010d81f6eb93f8289be1b1b9cbc0c88a17f1293c70961aaa2b194d2f33472106a4fad299f5688a1ab5d765f236c8736e2e1f13d01801703888d5f30206a43c9e0744667dc4da9028dff7280d1cfec91e003e650f1222be23cb08cc65379b2f01c8c087ddc27e2c71cad7e9a26cb3bba51f18d1f903c03a7a0ee90c7740f3e2879528315efb18384f3b8b2c20b298969344be08f92c6e8092d8e7a3c84b2b8a03104effa08dc93da80f80109b1de4be5e595b479e29ab400f93f21486d405d403cd3853719098e9e0460fc7fdc0eb9d693049bcc15169f42c8e86a454afd27486c7b93a1880fb026d013909af310b238d1aee7c54f0203f285d6517fc7658f77095ae030ec323d29292bbc500e9c777ab1f0c345411f2472e7e12cdad987e4a2eec0cdfe44680b77ea61d8600a167d8e89a5f94c88f05e185e6c36c8479fa64911dda9098c9714688ff7f834c00bd5bcfe8639e4652c5ffc29322b3ccf22c19df594e27fc470f8282a32ef9a81d2d52d440fc446890fd601f0155a4cf00860c91f2224c0dfa14ae26e73bab411bf189e94f93c8743500e640bd69dd8bc791d77ca2f6e18e113da006e1c91d47c9b0057768b4d8e9cd25f04972b30c41dc3acbc91c5fba0c212fa8e130c4e630400e77418f656da08d141387c7d1c33547e754ce1a388043adc9317afc7d0014d08678c03a004613b2729f218c6de53ffacf05471caddc08214cf9084aaa5671fbeebc48967e129d07701e4f86c925ddc4d1371170941c5f32c8af91475671ececfcdb17658f81c869f7e528d1e3e6708a7d7c8017a451f4e36832b433f0010f5dfe0367c52aaf85554980e7de4e165305af2073634f99f235e3e8c8038ae46129b77257e3a6bc59a33b872f24ce6c5a74b42a88b5c52fcaa1e25b4061d8eefa7c4c706934482a7b821f80d40351d451501ff12b8c5f5d07d6d974c99b722d1e51d78cdf1218956fc881f7ace2853759f1c361ec09b612f72a0f20fecc4b4a3d59cdf03e6ed875458f18a4544b9162a87dcecca8c86ab91c01dd869b17728c0e129c8083e92366d1caa03c8930d78f48ab8cc741228505eb0419c464207e0190fd1e90010383d8507859fe08c0867032395cbc044e563778486b078c107f070a35d4880ce5649852e92e3c8d3e9c31d67f5f22d9d4d4f15c2e2cbb490d84b90cc1ffc4ba3c744cae1d10c78fc8524497f2678a6133d95720a4bc6fed1c9c7f14660b93709f004229979261cc2f8842d4f5e8aa13fe77248ca866a72e162e414ea387106b89a4075cf63c2df43f1aad378063f7d1549a27eaf47996b6541da7055f0477501f16c762ab8045379ba439dbc1784dcfa30364affa882ee9b4d967faa4a214ddd377cc99fe413f1a4c3377d71b11d9d017c298c2ce8c61972cea99193f6e2c6d3e710aca40169f4f0c5301cef56087344a9989e4468cebb48b1f308817b5f05e267031105e125143973233d347d800e558e486990a3913ada18eababc0b10175a8d233a9eaa6c7053b9c29cc357aad77336754e8aa49e4c5fa77f9228e6f5b0307a3c73a6b6242b2e5c8cdd98472a62f56f1c553d83ea9b2f72c0b081504273236c9d740d1f609fa790eb2d05c2ff5204b4452d177fede2f3224efd399a0d4a171213f5837a34da9e1cb8137844612f86b0f13a6e04715161d1cf90248b8e1280924f0131ea3d213a7e8ab2d4bba013f66110f2e833321b5ee1ad4ecff061c5ad324cd207e44cb80a4450361f17c2ffd0baba7ae9cffff852b01f04ee475ad0a3cf2ca0e1405c08700e1f2cbcdb9e258f47419607b123f338480c1cc129177b4b8914fff232f11ba8e4f932751cdd0b0bc64b3190c5a1299ab8922f033e4318c1ef4166c9c70892e0d7a82dd25132559ea5534a17b1f0e6a6b4f8f0186008ff920738ed6b82efc788e72ab0ae3c8d19c327da10e543ad01fcbe3eaf4faaf2453b6221e47dda1e780c17d2bb9d80ecc5050d9e9002af77806ce148b25268ba176c0f84eec276a7d0bd1b24921ed056f42c8334db4f93312e620789fd4c18bd8bb7197f224720ffdde78dd099fd87228174054351fe07a23b9fc161d45f7d2df12b8c72cf15484fe30905c30d49987a2b5919dccf1f4c3ea748c83301e2c4376d18f3900c08be2119ef6f297bf48ad678f1449ecaec297a44de041e473ea92cd1f714c5a6a445f872cd2ddec94802dfa204ed1d5350fa249f0b9f4a0e228f43c6884b7924e62f34137c120a91be4ea7169e1548c22f32936597d179f48dc0dc38a5401abec905cf8b2df8f36e4910fd4fdb06577ca4ff9de1f822fc7cd8807d5b3cb0818b97a4e2d00fb9d2b38314187ba710e53f8461f1b7c43d1b14080c4e28cc9d9704278fc3415bec40056d5ea5ab8156d158e6e500657f6835c609cc7f3e58a3ce6fd138b417d838f537fe9ced1d1b02fd0ebda4b6506a8fbb31a2c31d20ea390c4c18fe8d20b04775e66d1f22f3e09dc47835125ee045b64cda8f8b777ea5e6e9796860e3cd0731b6a31c823e9158904d6d23e0bb7c22b3974c09fc1fcd27cec3d0eac92471b4f71e4677c1c3f9479254f0497aa89ed181355ff782d23b90c7fc9448371cc016f44bf880f80dab009e64d281efcbd0e77e64825eecd2265790167d519b60b81a2d389b4ad48e2b4e9dfb0aa8020f44c899f6a0e6eee9d212f5a115775e4c140b8e056fc790f7f4ba4c5fbcd985c136d381f4001794ff2522eb072141743b2d9c57fad3664f3b21f9005589b6110667de46c175167f261e8e1d0deee5aef18fb0993e9f2f699c6a0095bb66633e54a0223a4597afe704488b9b82b39fb003a0fb3863c8c9b4d06c2715389e640f9957b9dae46c1c08d07308f4de4f8d146fc54285d3184bf31374716f4a8bd013e0b0e6bb74e5e90f98d01ec40a43db4d9e16eea30da5973aa1f25b529a8dc44c936f03f3e7814c1d3901071cb6dc9920cfc370d01fca2b7b418586f40bb4508ed5a3d246400a84ff20c3a7cb48a2f3b52f40b61407dc83e1cbf4d1091e3e019f020fd608cd8dc039d9360cc3bc0c4219368e30b2570decf05402f6b8544a2a8de7efca0322054a675161e68b1c176c1d97723c803cefcf4d51f499be5278804c509783fab999e67f1a17e0ee41c1cb1bc9d3403f295972367f56ec3f4407cf05058b6fc2c4f8238ed8f90069966f8a44c5497118f17f9b0cb71b38c2474185c5c75812eaffb4f9b1ff2af8c7183bf3837ea6dc009237cffb217b8821507c0600106fc9019ead639191ebf1a44547e273e1803502bcdd9f0ccf0608d34bd04be53116b079a13989bf71c8a39356a1dcdda148eb3003ead79ce9ed4d775aded3568f9daac0daff707366a7a944e7f954856c228553fc52111ede650ad02d5881bd1b221f3c540949ce61480957c167ccd738faf08b4d289ac4571eaf9bbbec2f26b0bc6c02dcd6120a38140a72bbba22f1275101a5b5ee3cfc20111b7492423dff66c1fa61ce7078b22e41fea9d4e20b7181e23b392678023cd2f4010d8d1f8909751f2145f65860e76e5104c43f17d9b4a18c447f269392bde9ece97152535fd7f6e2cbb4aef5901af234d4b8fc29ba137e430b0e3f84e4c23f792368cf4963e33d19cab4039888a87450cc859116c4942106004090754303802401e312004048281c8c05e3e168481636ed031400044e8080c042994ba4d134c67110841031c4000380210418409099235b056700f75368ca0f3fa9c6e5252b0d2a9572127ebf967022fe21c25aa118d097ba678afdc727aa2fc0c4eac6e8ebe8d19247f1e0eef2fd252aab891c2881f9444857e5d4427c6f83b32115f43bb99071208d40063e4ce0dc323fe6d054b4bd558af163fc3364507347bc705a5a3c25a322013d7927a0556c9cbebf1b910ce3a2a5423b28604706916eeb14109b87892bb05d60804144fe24de39b96d5f63e5e158031fcd7a4f87671a650208cde085df6bf42fda5156bcab84db86a047558fa75a5dc6bc7654be54abaf8267e4ba731cf030f7cd8c74e313bfb71f2a1c99205c61a853f71778f210a2523db1a10e35735cf89d23ea40760466baf2ce54fcee8f14ca14a1875569b53a36b7bc78b9e4bde653b590d7e9c68a9cc0660cfa1acd5b29c6bbe18590317afe76ab96c10de01c34ebd509244120c0c0d6f779971e6a045fcfdd2f66d9e6e6526d4eb1f1276f9277949057d40c78d8af40a57d4b5723a704d1fdd626f8a2b3ffe9b6bc3f2671d40fb8f4f57c86e63f39a49e1a8979eeaa9675eac00fa58ab56303505eeb6a6613cca02b34f0f1ad149d6fd1c58f5ae2fac7b9ee4783a7b662f9b9da755c29fdd550601aebdf39bdbe024eb6f4a78a745b28d62cce693f8fc268ce93dbe0f927427b1f9bd947bed243b8db8fdc93ab6d084574f5734b13438960354650215d6c4508d2838c27c4966ca39779027f5b50b65209bfae9baf19201454c4984537deca969b238b7f024d7dc2f88a8bf817556bebaf740e1e56e5cea08d8644bdd3fbaf91e16dca9f61c871bddef9061cdb2737e6d7702b6e0cfdf07c009ddf80d6b77e3385c1f5cd6b20903cd0828d9bd8a5d58758948b9b7499042d23968f361b0c40d1e40d83434f9c1131b5c415e30427e707123e4b8cbea6e83bbb3a20708a3c2955a40bc06181d684fca3235efb968bffeba93cbf934ce4b2e7900d1bb9e1dd2e4db60dec7b8ca16b3a6c598bfb8cf02fdac987d790b646f1365bccd691cc1e7d171cd03a724c048598c520386c6c8e9b753443f0b03b9bb8c4c9307ac78de37d3a86709e1e6ea5a48b2ec78c41c5008f9e868cbcbfc3ad677f834ddbb31706fdaa10d7490172c0e64c0fbceb47a79eb82a43c75984a2a88e4b8d215a975a41b2a2bc792ae23d2acccc2f7c27c19598b07224fd1676f2ab3c21bc5286adaa646082621b1d0c7dbcea9f1f7c184ef797d0f653243cce07870605467e98cebc6bd118b65da1e3384d6770be1160f7547a12d699eeb89fb2068e26046b9f68f65c0181d684beb717f87b853e185d3d2559f2f70e362bce793b6e686b524b267183d8e41451f04831f35a06aba2964b41d4a3c2b3be855d756b45cdaf610139e03e9d131990cd8b596445dd37e88b19f337fd7d9424b4ce110c17fc2800fa5f4d2f7101810208f9687a3125053dc4662294963a021a4150504f6a1452d9908f43404cc82c0096b67c529c076e250812ea2b6e64a7a0da27d92261c0c02a4a135f0732dff58a980863c8ed23a00b0140d6bf0becb1d19914a5c6c602ca9b14f399a70b94c38de06a33b35ee5b83011331ffff775876c2a374f092918f3c19a278f9ec0c54ac86bdf8b18522368f8e4355223e660bf5912cd5610c00977553466e9765fa85f8a6d207708921a865c868b89ec097d9cd1de9f8255f01cce1a70474f6b15d271751e25f654277edfca1869943776eb94e20ff066d3f06b83966dffe6d94b9282849283d86351a80cfddbbb8e68ada57174eb0e662151f502161fc5bea76ffcd5fcf6c75117d9e3e76620c43ae42934a5950e1ef129191a930d5e36f9f18b12de5fa48b54980d9dd351abc9386b45b16a705a1ac427844b1cded3471e1703ec99195a357797479ed0d4525552d69209fd6197341ba8abdc74f4f03f5d87dcaa93403793686ccd60722cd2a9a5378be4fcb0142e2769844c516117ca66c61dbcba59c3dadf8d1e21d1644548ada602a1ad728695f9d54a83a53c04ef37c5ad552b268ae43a8020104c7802fb179ba886b170b562616549a9e6efc9044ec4e3062f40901253bbf4c3a55a3a901c0c9b64ea336c7160471caa4c11ed470abf9d6013b1c56cf31ae91837634d5ae32b37a498a963a9853b04484af70550c6b60e47bcffe1c5dc3c429ef8abcba494c5d1d55a5b7bd27786f625a97d85d4eec2c03a486957e13ede5978a5b41553f9930773004443caf03a35a514e22eb9954ac93478ab4c43eeeaf512733287bd56e01999ca23ab0d3984ab91f17f7f1fbe9d9eee6329e23cb4c388d11ad598f268a1b62638a71bcce7d075d9c0d1f3c5defd4ba6f9fb8147b88534683558c43e96e49210b74e928684a25433b66b0cf4a69479919a5ff0bc350e3606444ed449cabaeb784a895e5eea3fde504df1208d32e169d357e71447d456d1ce53563d0c22c815a66e236e6aac6cd08c38e90b518b29321f7a411ee2a3408969009210940f38f5756c10a7c87144b3005da7c20ba8173bfc87bc200650279da1c73fe1b4d2584c636a527090a3e0f11fe2e333b29a28043fc21f7c085f86507116a9051bd34819f728b556f34d8e778208b0e3639b0f7b04e12dc987df85ff665b2a789d53855f2644d07c25ee904ef9982fe695a43a4b0118122126a5dbee010a11c20150f0d05e7a4b363a8f98485af380d7d78f0d88101620324075a5f3c758c2a0e15e7746992c85e940b34056d38c5025d1f09518ed448f266699fae4c7c38b8fdb34371cffd39c4ca815aaa78abcd96a6e0dedb7a5812aaa7c29859a934537f5100451e1c0bcf41fb8b210c4ab6f769b8da8e2c9c9f643fc93a5536e29a366e0c60148c16fd334b21d2d56c146d102fcc1d144e2d44342c4e0efd50def43179efb43bb0b47eb5d9818446a8f4f48eb4fef06650ed7157a6e409f1138836122cb36e979c008837e4e0aa8b9c71f299506152acd32c7f4f636ae39440ac20cb94fbfa6b4a50052283e651fbd687cc5b76888fe226c65362d3dac6fd173b4bf85f4e00bead9eb84a2929003739529be5173a5df65c184086c3e5375292138fd12cb00a5b926c9be1bfd1c0831d493f66db0c4d6c050e1aecc4d3937cdf285713d88e62308e0b429a2525076943577a3eef511ce89b4aa4f745c929d085a10bac4a35bdc6835b973682577728f5c6974a4c5cd383b21e70b8c8c2c076ea3ab2ac996b29150b3d5b30a1b3909fe906cc37237dee20f85c98138426246833954cb6236033df533012b558b75b06e0f615f1a63d46854525dba7aaa292dfb8a96705fcbcd9d24ad7a01d137708f1d226702b98bdbb08c19ade0fda4e52529d54a711017fdda315698144304a0189fe36975f3c5aefb87fec83614dc53cfbaeecd18e54a127f532446b1a44e7f9754b128e921570711ecd06527ed6af9569d2f8de0230fe58e153557b3fd9668a3fb16808d4cbc424987d5e931c5b381ba9e92e59220c3fad18065a2bcd1bec104c529c423c551e1852a7e05045417c8a30afc5dd2d41494d3cc609e5d39f1bc893b9aa56aed6c2794a981e40ef8b3e861c7511249b5516392443c1954b818ea7927059105278433f2e4c715145910fbd1773e3b321ef4b98a3568fc6fca1f8504391ff033635b9c2b78599233105866858a0cdc6c0fa7cefb2fe95d9d6c5cc1b32c3f5449e2377fc12cc43321d2d53186a8c23d4997ef7174e25f735d0df7bbf74f81945a5eac76bd66ec815b5acb12ce328cb275a2bc82d85595d11741ce3f6938e8fe1cb35b33d3dc5ac3fdcc18078262953e39558145ccd1008423707085111cc6f789d3d82bc83b5cd33ed9f53de2529b3c02a45ab8cbd40b4868c732458a3c7558bc2f00d0819800e2b4acd753a5fd00a06e0ac0ecff5d2d5bd464f227450658ff0a4ec7b068f069661f40694c981d09855021116e0b8c562c51ae6d30e4390a472ae18f4a1d31007d36684bf337a792a1c94978b0f2f845c2d66f9f6b09d73afe34ad911d7181ca146098064188f52f18deaf4ef302a22f78ede3ff5c02ef9b87f033bfe1024a0ca548d80a67ae0644251126c7b8c34384b1f8af717948d4cbe29a8ddff1ba7b2a89b994f3f71aa2343780f0d43aed246271c9f1fabf0f6d6b5696364261fc0bf5202dee7c6133b44f294802a6e6a104c9a3cbbda52ad4b86aaf688559d1b7ca698670d86affd38cc6c9a2aab4e9f1139e359dfe2b6778908823eb1029d647362499318bcef73886154e0132296df54424746f49ff07d70b33e9d4443ad8760e76931ba68ea509eac3b1d7533eb0e426a5d3c5cd041b30a0be55bee760466cfc8aa0ba4b84d0d4168f411b3891e3153345f8ce68d7e35d8472f741f6b8b41e1d7226498be3e8489c9817d78191d3b3061163e6a32c55564acc82b9b0ce4e6ac8eef11dee20e4dae6406a08b49c984ad28168d476bacbbbc46b0a8bf2eda942bc1e2c63ed7316fdd69d9d99ede895cf3415f00b4ca6fb3ae27b3bdf71c027937e6405a0510b44fe0502d0bb2cd0509f8cfbaf837787ed1d7fd7b3b53036fbdc766faa5bd57470e41647b379e0ebe22e8c4836dc47f1d5ad079571bceac9e9dd8d10d4848bdaa589317066bd53f8c5e55265d091618fb255b5e1cdaa5f061272dbc17b9317bb08472ee0c03a94c400e3ddce296b4ec76440c817b1f78df0827697398e54f7117464a5251731e8a3cd653230ae9355fc72fa61f3ca81ee8aa3b89943ba41718b6270d71a047336693e9553aa820a990d39d4f65ea86e158451b009974391ee1a2ddbc2a424c9938fe4682476606656de266d11b45f399be487105ffb7d03ee08285dd7361042344cbb1d6692fb1006d7ae27b18d01dce7495d741212b94c4677fa8c10d3c864a7916e9cdc713130399c49162801e1c55bd26bab05802002a50118a328568cfdd02f030fe037db507e9c2a2812eb311edbe1ac407dde3bebc4edfd824784e6b49bc87a35b1a131f1884e510eac208297e6f23eecffe28ea61480ba8940891ef9cb0b53d440ec6675f26e76eed8ff61aaa4ac592fc1547fdacce8d1f3a7ec29601febc0cf2ca1b582deb00c5271a06b86278dd0a16f8cc9bfc92cab8ef4924d49e53782dd94bf64586a4d655cc827ddfb0e234784c2e617e15ea9ab38357f6e714e9906a0f91be0b8544b1b15a76ff7569f64ee324d06fe5e09e65ba202a7be0064b1e36fa534419375f0067e068ec2ceacb08e01569b9f16a53fbb2646e3025163498aaf196952937ba294f834a706d52cec77f15c451a3ce45cd08730303f64a7c8f9d2aa7244c22dfb6e5a3431d44e4af6f4ec591990cc2dc4e96944c440a0111e25a5c00ad0a14b773c83521e86fe316bd9dc29b3f86aa602bc8826bf7b923ebe2987b4b2ef4ce2ba997777e3a4024e7f3747c2da7b80362f17df49b38b5b507e88db754048359894674ba0a15652f03449587cbed4b194f3d337db4ec3142b3621d89f158df71e30eafb395dd40dcc416e8363be4bddc0ab384165833f102e0c4fa9e9e83901b2ff83d84ec125733a77f94e91300fb633ea3c9f9dada10f00647af963d32e696eb19d40a1af0196388e9271716461fca6614f9856ea00fd98a6ce606c436cfe5271d87813940c316d1faf70fe717ee1b5278dc27399b83d36238e209886924cc093b57c62fcceef85e4e0562094e0ba17eac8afa83c8f622d9af27695575d30287e7b21f6e2f607087924687a4fbe020329cdd07d835df373cfc4f3315d0048a8c7349b8620883158804fe718d7d6bbbbc08481bf49ab3af8d5a84e5b32c852cd1b521758e4812265bd2267eaba6fde12ce21e2a3d433e994e7c5bb911898cd83ce4c197f64e037128c1066f93adecd1effa7b1226f79fe0d409b0afa9cdf0dec5ad67f13dd9b1696accedbc43f94ebe4c75cc12831e2a21df5ed70b8826abfeae1de660fc0982e5dd959163041a9bb0ab39fe294347eeee56d844e6069fc38a481751d25e402a34c7f6d8b6aeeeed0b9a79d4466d39bb65517d9fddee606910d3266f9a32da5af3d79e0ff1fc9d874e1c00d87659621710a0e3bc690d8a34e247afae7976eb1d9244c4f994cceb71a2a29668d7732b3ea44ac5f9a938189e4d4a86d9c51fe2152d21eba198b5d84f92e650914313ca0f70fd48f0038c4ff7e82d58917927434553801a8c4a4173613ed77d04acb02c2f1410f36eedaf881bb6f42892743c8feaa714dde50ef5057280a89c08f8e137813fad640e03e1791aec93f0157f2adb43fb2f9c2240458d58c90179c256d0bec94879b02e89c6b1b3eab7b86324864217385bd8d8180acc16d03aa1bf6a54cf07b02cc9fbf21175732e958a6ef5172e097f99da8d4f4486067f07a08fca2ade20defdcd3e0844fed241987e32e529294bfc75fa7c10d1e10a9007c37416b4766f58988ff3e049466b06088f204867a0f719b157cc4bf841d0bac7891e94ba168e3dfe3bead167aed1057bb0f5b50fe83c82833f58137ddb0290d4fb30792a87202b510c4efa7cce450dc98cf09189118f63e793738bb583ebbe66e2052fda7d3f442fe33b343d4f7bb76c84fb99e0db2906f7c3c5ef0b8170f9743955dd9f13b38d801beef4078d516c99ca2f12e8517ee65f79ba0ebe8f6469850cc95cc61dae743fb9da3ae3be957ece1fcc88c4b3e1ddac3851ec5db23332317bba94d71bbf96189d8d7489ec6b6818f4cc2a4fb7d692eff9df12f86a970b7c4b7aebe97d35739e0a99a196adbe7fee83e33e66aff01e178f6845c9b547957f0521fe6bc44c2f659f7b7b0339bc524a6e9fcaf48cff52ae48dde04b8ed11b092620202c243a8602b6c0a2ce323670db8ff49ef8c411289d0adf6f3e051edde847be34c59bf092b5ff2980b17a7e5ee3a5108c6da72ce8ca8116f9d6ceca3d0c123120ade55bdb6ef506db44651f6063a2fc20a3e3920515d6e73ab34812e51d1c9b32b5b7cc5cd33106e44b222e16b78d663d3f221956b2afa3fb44e4251233baa77ec1edd41ace337b79145ea88a8616946fb2a0448d7c1c600a5b0628094494029b49aa8f12d31cab987bbab2ea8552cedd9056a6515bbe5b44a41172439f5336997d14baf68b5e7dd1e8e35ec7c0a27f21dfee8bd90863e85f4ee67f427d649ff3c06afb0fa77800bc1136882c6249827ff2e95ce3dc9557477ae0e52c34b585db35ee4d5a9cdd3a9807418f6e09d96310dbb4f57cff88a1e20b2f3931086dfa2feb071e259a511a851f47285f01b24fd9b2d92df52a5ec9c69824d9f63318ecc17d5f8b78e7e38a4804a0f33d5285563a4ba5e088e62735f649c6d9ff03c9468f61fbaa2b0d86d2fffa535fe139e33f5ca9733f67d8d3ffa04ee157ef0039fc2b5f2a424783c4560686f58ee5c14d04691ca10b6cf767f80bc597996aa9d064790542b85dd96ab6794e416f902f45d92d49f202b5c528a27acdfd5fd0ce7bfca6febb3d1c70f9bb8b38846bc02bc1be17eb7fc87bfb9560d1759900cb765784d4ba81c1eb979826f1642d83b1088c7484a14e5be9e62d3d2a297a4077cd7f03e024ffeaf2f765d49fc89fe55bc632b0bf6742cc423aa09227accfcff82f9f3090039be185ad1f91394d1753380b8a170b2e757949f83b523a0c640f176d87c2487332562afe3e7e813555d5f6b389fa1da1d67c5be484e26d31d519060e25b0c4111ad9c0ed9f0bf9ca403bffca56b7e6bdd45ad9d89395cba4ce876bf98b167cf6f9bfa56f3141fe30ce9999f2b24e40ce7cba432d11b79aeccd23b4436a9f3b84e90cfeec323d86fe3cf3d6a451a7936c9f725a3c21884cceaf4f4099d5d134f4c06c98b22a8a879c67aaf922acfc4aeeca6d801cc07d8167d0632f9d5ae7053cf39fd56cf943359fac5914dc369779bebd50e7f1c21d70325dc8c21b28c6f9a66e83fd042e4796d5d361309a4e5b3a2ae2391c82907bc4a5e4b71abfac3baecce17e723d31cc53904c56258aaf0c42d959ea1da619d7c67b0e115187ad4821338c6df5ef97d6f7bd490b33dc54dad8b1d9544442c163e3420b85e3724713b445de262212d78a2f84511100c7d22bc83134b0d9e709d747a6cd0654c8e3443ae911e4fd6632b25e97fc84748477b74793c55d6d92f68a4338da946b0f9ea692408099027fcec70396982fee43eed6e02ae9dec6d3254a848c226aa373d6ed17fe45b1890fc148baeca58a4f570faf7a3f93e84a9d443554483bcd0f64a85f513680c8c1bcb0211a9a5263d79fd404faf85b1d8db250f2ac66cf5ba89384da099d0c65dd8f19d4849ef6c7efa90cc21e2f1358a4680eb24a976404cf85c25c2a4f1c4609288084eef11d1123ca978a62bfb01d413b2bbfb6f49daa22f504211e65f3e520318084e159d9c32c25ce0ed2371283ef50eb243cd3da07e07f17160cb71502d07a8fede695d891a2d54e2f4c9643c1f24e30b740b3e8bf30e499d294eb3aa7df377931b4903d7fbd0c052fc8e1a922bc0f126d0283979de969ba072bb5212f0d1d2fa6596170636f77bac1c3e6dc25c79909363c5cd0247c5da8f36a2582453539713ad8cb1ebe60503cc9b04387a7029143032e9386d9db16c2cbc2bf4e590b2f2f62bb1adb6c2df9ac06ad6bbb470bb0116d30c7d51e8517e4d51534f7451d4d33b823143de48e55a4c73018289dc4cf53213a9d51c8f52ac8643dfe3626a646e9de3dc972d62d3147d799adf1501c877f46892d1c79dcea0e9610e1c0952a33128858b692ca4ad2661f79becc9c2b649f003830fc815fd83b191b22784250fac7748e0ecd85938a099b98f447014b501ed0b6471646120ce6c0b5c1f58cfad67dce74535bcbec0933b4d125f4feb1a71f5ecac7a3ec465f68b83ea19b70bdc6e0a3e8df15309da4c1fe6a6fad6d8996d2a97f458a6e4fc2da3014ddccdfe5fb0c2f93691948358ddf9bcc90d0e90d7fc942a93c87c1e745aa67f3ae663bec9b3ff03dc61fdab8c3dbdec29bc8b25a4c6130751387358029d25ccb3a823a789efef815af50ca04f453c4748b96af9fecac914aa3273a17054f3a1a483143b7bbfebbc693477296b32c2ab3d142da774715caf07ba1bceccb68e290028241b6d782060f125cdf1b01dd6b6abdf27b4bce47ecdb573fb6fb669e6ffd790ff9d4d0a6e9656e7494fff423d57ee6f5d56566bd92463ffc0f3c777ee82ed8fd48b2a6d8090a3d636985fac4c3e6c577ebbe81c8cea336949c5c36a489ebf75ac436f9f59d718a7869ca396c10060aaf8900740f794b39206ea437e3acd3873d74cf5aaeb41676e453828675b5f676657866eb689859dc5a0d7e212f943527e15bd5f903801614f7cc3b07bcda909d3ac6328c079a00c53275fbd32c3705ee1123dbbea5e152fe73862fb03acba563c884c6c1837549b7ce88e33ed7fcf2ce8d3adcfad9e02b9024b33fb7fd227a51744bbf53a2ec2c4e1677f44004e2d49c849dadaf09458e52e1d7bfa79bacf3cb4953a550fbd7ecb8d6365a4e744376849804343d24d5f2f984946761162d31952442525d7f43955daf35e0c381c36a3c7775eb894bc428151b06d46d35ae66fba93fac0fd229ef7ea36be9a80b7821041147fded05fdc70c2e4cecdf8a12262d720234b3b8c76f0cf3ac61480a47f7fd92f7bfe28884f981fd478e48704ecb63cf95bd6fa1ae67e42cd7bbce67657a28e200476f44aa29524b916599dd10187faf039ab38c209d50e963591445e153019f7b116877b34a245dd0171e8cea00083b0b0858e5cef62f589949ee81c62de51505c82fd121e54355f52f07d53251a0241b29915cb18b86a362da2bcdd53116c000d4a2e5edcfd595548b541b58456167876142ff6b013350c866c7f25902539a33a7a6258642751d03812fb3e0c506e5c24f16d4365041e4431b354f6f8904a7a2242be9d139118382a465aba64d3a5926d01cd6a1e4e3012d0513af12d065e870f979f2d77e0f674db6edade65db8bedfbb5ddadbdaab61d6ad7417a83d8761f1aaade7c9588de35ac8e8504a332b2a92ee34155e6a604694f8e69517810543832a2431614e9997d11fab589700233153a9aaefc3a1652b8faa88cbab41d4d898305a47135ae45e1a9c996543a220a4ae331edd4dc506292b2d838645df868503af32ba59eb43e59a422934577d0e4575d468134c34153f6e7b5eef5b62bbc520ce09d6ce6a32638b201619bfb5ebc41e78ca5058eb8abc038ab485d733d7ccbd81751c08bd977f20090120ac932b5c9b38143e22b178f044f0dd4a28c9e70072e9e9ebdf4f1524299e0437165ce6e23842d07b13611d4f1fda577c5a9c061a2b9f3b862e83cc74d764aa02ec1a93d07b5711719924409a233bfbb6e5aaf0742a161eb1d09c5cc9f155c821d93583a705b26583b7a6ac114efd955b311b7b7ff324b2bd49c73ec141ebb41ddb6c74b522338433cd99db225d49a1851219a78132eb0e942807f850b343560aaf93c83d3945324a66b160252e58c83e60718afb34deaeea2f368d84c55610995cdd8927fb326051210e5248c3bb54b16ad3e1621561120d0c2c6b146d1d3ad58fa3e395013f1422a4b58eb25265ee1757d2fe853fadd7f7ed0cf8759b96f709fd8a7d23152ec148c88c0f49852d0fa090f3a3c2efe0c77960f5da753984e103ff32f6ded63d89ffe149c8af706353c7c0f7938062196400b33f3f96e3b53ac8b75c38cf81a1b667b51e9f4d5e5609933c5bf36043b950107cbc960e93ad42b21e56201ed6d13b797184782cb586fb6be1a95b389794a571ba76eb90358b66b9e499c3f6ce0a61617954f054e2adc4125d45da37b55bf3e4e5193fc32500afa029cc43cd5e179a33b1f2b82627b45070e8de853e0154e4cff2f2605c58f53a0f3ce3ee1d06d3b5c624ba7c24c6cc955431ea6adfd1848e9e40487ec3b23849f2bfa2c1ab06dc34229f775be49b9efb203920e5a3bfc88903f95c0be71ae19a9caba3d84c7fa8d8f9cb5ab9fc7c91cfcd83b23ee4cd988ce9c5bd7cf09c1db43bec8a81b624ac20703cab3430fd61688e4bec890d299e9278cd096831a3e33cdccf1666fd271911caddfa7a372669931d266078db64813e9de120977fc50d81c0fa8a9c332c12dbbea37aef753a82ef3152b22f2a0f68f28982f9cbc8ce418f607600914dc86d2a35a4957764da0bc0318a32688cc4000209698e4393cc1d71de489cd2f817f21536714c08ef47a896a2575e7317a9219b51c06e06d8eea7d8301bf6146affa89858aae4b2796213d0ce4a4779a7a8a7de482085fdaa7e307fa16c206a9370e5e77ee1a0be7a7df810149a5f58eda55d9efe32cd69823eae5b68fb3c6a61f3ef0ecd316b95f98e45e942a9025403ff310aeb567f01571418c44d0e03ef786be70a2e9ef0b1f25cc3ab81908d618c028241518c4a5dd23592b1ceaa7f24d3e0e7a8a83933d8fe89c8b38878b0a243300e1ef1dc940a0c833f50239398bea9b43c6cce296935fef10f79a1cce94d0195ba0a020cd798d3fdeecd79c8a3dfb4ad4266e21b1fa81329a33fbd9a3fd7ed44bfa96fb4283fd62a35689007ec77ef5c0ccc052077157bb822d0b54f2816d3bbc177d2202b97dee9ff6187c29fada2cf6363dda39132e3d9a04df8a4bfd1a1cbe7bf18e538ae60455e8e17d599eac63a1dedf74e5043769c480f0165bb79b386328da5482f8a134e12f8d35834baf3918c53ce498d0251872c0c51b74efb00428faaba396b4eeba412494d2e11c59a2b1594ae3b426c09d1ead760f4b11a2c0bc03025392ab5a6c9bbde1f0cc59f03597b6dad1a860a1ffbb2638b6608ee072ef8bb15d75168d40d29b99000137da004c7c27b077fca916dbc27c8b215345db23dafaf0afd2699360ce95df92d5d7bd2838e61d79c6ac46442b1cbc41a9d6dff1109b653341976c012ca7017ae21436e3db2989367c3e05df9c8b5bb94ed0b63df6e77fc4a9640a220f358a6630c21fe090bfc2d440fbf01de4e1e62e4793fc27666fca791fb45519c2252cd9e79c4cd924b93845be5da954d125b4149d361d37be4a96934233ae4c1a44d0699d877490f94319f9da737334c188280f03c1db314a609e99382381721b12f5182890d4884a7571e7374761b9731df0f1189a9d9e681c1f979b99347118e142f67d9e3ca3a79effa7a3e2b4c075f2f6ee4ebc7f2b1c7126a0eb135e3e7d330c2b6c871dc4da2e3e72cf41b04dea0b1547b231f574f1572b13109bf3f77db666d046d9aec7fd311f45418d133dc0152333a5f529d044a012d40aca1367856cf5911e71d8ce9f81dbc34fce910101594901d190afe2fd24bf8314a3b36ce859a00288313f91ceeb00d83f822b42b30abc3ef234c2373e7bc8fd685c3bf2bba47cc14bee2273f462adee91704c5289c7c92170ed12cdd580fffb4c05bb3e7d7a20cd0d95cc830261673552294bab70425fc29fc3f8c2d73bd0ea5f6ecabf2b3b25105a102f8d6571b7cb6edd8b83a58b7922ff243a32b94f1b3bbe43c56df3d0b3163b9f4eaecb434f6b0b065256f1b77eb2f3ac4bc0fb2e3077d7b5c6b558910c2edbf180af3d4c741eeaed09b7a6b192d6a735d49ceb33980025bbe567f4a395dba63553386415f90290b51ecf2096a34c864bdc6b79cc9388ed07ce6806a031dfb8a0a955ef1707984061ddad55e98cc73b5c6f6dde5e04de78497131a60b96078f304c69e1cd1a240e263f9f7fa45c6fc4bbf94b8899f79554accb38674f3be2270371169b40cd10137a9225ea8e9caedfdb72f36c4d6d431c7d01014cd2911fa547391e28356880bfa2fe0bba964cb2c977330b371c858cd9c666fc9248ccdfa8698f689be762e7ff80db47e14f0ef2d87239c6bb65a41660973fbb2cba489914e01db35835f64a46a360c04661a4779bd944ba9b978e5a22bc26c6b47f01e83b7e396812ddece61a39922a61ca93c8c8b25fd3ece57db0dcd8fbdfa1099e99d0c9d997e54943ece5f68ec8c83a372ec80018de7d4c84b0ba9da611c6805b67f614999e86f15e6bda5de426a1fe239cef35a896c68cf94be65f1e558bd54d0d85b4667f35c9910ed1507f9120b16055c38f41fc9bb8a13fda6a3bf70adf5cf6beaf567846aacb33035788fdb0481cdf0457cf27f30bb3c3667cd5fd617ee2038ab17350b18a048fc68666fee08c6f5b6ac2598d77c9584b11f950b2693970afdbc2e7c52f30b30ef8045aeeffecb6b3e353ec3fbeecb9d80ef8513a983501d752cc56ba39d607c3603074120ee55227d4f34a9e31cae7d5a2c6fe582e49f8bee1fb3714e953ed9380e2fa4f8cb100e8e670f2def4c582ad7d96b5838d9972c83811fe93bc87ba6fd341c02aaeebb5174291acece273fcd263d6593881b9d9ff7fe452338ff874beb68526ce3c651d501cfc5a006fe8db66d1824a28848bb8477fcb62d3482e8bd3d72110af08bdb3120f9f4f62afe797f31587dd7b05c292310e34fe819106b4d5c7de32c772a2830db548e5c9270a5ac7ca2ca724cfe46af0f35f43d296c3fb9fc7dafe35141f1c2179594648b601736880b4f5639b6300ff0e2f718ac6ac3fd51564a1a404111875459b9c6fb77d19a6f8d6c597e3ed70bf7104f8bc87a08431c12db0e57296d5290afbb2f19013f4fd68632c4cc4739947e07c87c221ac4d607b515129da8d08de052e31cd1c9ff035290cced357691011408fbef22abbaf9dcdae94a428a0e0110b82260c22659dabaa36e637e4eb851259a06ab126c33732be33f27b6c2421a677f036d0ed284218136ece13ae8fc870461ec6d594506c0fe4c3c5d01e0bf5ec214e815f81788d896c0aff62b245d6b1db1b611d734e1bc057d8f5f9263f697808049495d22aa54c60543c58e4360be2850ef8abf64b602ba3a23cc048f7f5c2e3bcb08264479c73719c51d4c18b6a48546a993d1f362372c880250f8ec4f4e4b063a0a7a40b60a218626756bd0ec7228370afff0f80e98064bdf71c7a98e727777188911a363bdeba4511b586a82f81d1ac06446615226aa2700493b009572ed5a1fa38926656441885f229b08fdcfb8f6c1d8b92b04b85d15c37103ce771919e57b7d471730f09cc846229daffff18ae1c3043d901549c46c82e7b3fb7a3b61fa81d054db3c368158703c0c00b214e3e2a638a1a00ad512c09ca6b5d3a9d47365906e2a773fe36403ec9d9ee490541c722bed8ab13e28b03aa24dbe8be83c154a0c512d80843eab4bd559105ba6425fb659fdf0cc9b6decd6f7ba84928ec24aaea291f1296a1111d8f03032ed3a3db5fe8b2edef0b57caac00560ec9b5425f93bb05a260235ef31285c59b4c6092e28153f03ef5bf070d4028d0384f6805fd57994cfae01809bd410210a893940c95e496728db67dea0303bdff453bf78818347a48806ae256136eb6d731d1f7f18529824c4dc231497dd9d8f92e21bca4706258f32ed7e01615ce2772c0a265c984f4d03b9e5b5156d9317c79ee498047862bf949f5e35bbef45dfa9ae73dfe366f4204d4389b2e09873fcc09e0f3098dd31286429fc3d7cdee36cb5247ad2471da69d96c603dbe549c8601402f7be5c5d3a65cf8ecf98e5915802bd41882b379e99a90628ad07a24852a282571ee46022b63cf923bfb85b4bde48ffd18a6527b13417a9b4812cb82330f831dfd2d69506ae7ba2e0985515822477e99e394f45191d93a127b0ff8c7e5e4cfb294642ed7978646fb9462f94d40ba50e493f86b0470e472cd9ebb5172f50690afe782b7c5ba8621d913367d40c8b235270583835222437c3e509231af2a024edc5d66eaeb08ae0c1ad7a36e7b18286f66831415a11cd1e333ef72597b1f61e0ae07712a56c614c0b6ac7eac14f58d4811b1156d6a70c4ebf09532cf83ff99273ac49668178749b12b4220fb6556558f73627a50fa08f29ec700fadcb74e6b0f7bf55f25ee24f624d74e8849244a59e3a4b66f4e4a91ec7390ca7de9cd381cdadea6377767bde45c1f07de2b7b8104fc7b4e5997059204d01a65d8f5e44418cd0dcc626257148c58715531a7b38e22320842c308ce480c56d674fc8b36d90790cf626f51a3584c0245f9fe68cd14a3583b6a07a3373c5206547acbdef0ae459bbf815365b5dced7e0a574485accbad83485498a3c29c4821cc12b9d678dfb6c54fae760e02f3576fc8fd21f2fdef3de157fca0ab2183df6babb6f70666aff01137369f7beb3c0559bde970fd265aade350ecd64cb9b8d6065deee1fa066fcfedae7ec901bdb5a5f04fde543f5b6b63f14c78eefec95995a3e45aa44e1c0f64c35e84d71945c3ddef8d8bf397e773cee975287c00978d0af69bce6a3188b475d9f215289e30cedefdeffb3e9f72965e0cadfa901e1093d6b9a8fdc723f1a7324ddd0e247573d029e691e582e8331ec579a62cf099b39f78e0a17affa66641f8e7cd76c2e6a1320f05cf6f0f6acfd5291fa0a5e9dd52da157e84bed9eded5c236661563c1d1ff4c1714513de8d478073f768f9cf3023f7aa370fb824d3d3aaa0939f5f2814eddddcdcb644d6bed32edfff48861f9adc19f30f99f384ff77dd01c9f8c58a49496e14dc2de614cd0a0334c5c7630fea365439a3a761579fd9048b259895137ff945fb00c7e85cf3d199cfe56e23f837da77a4e4a3cc688fbc796bdb263a616ecea4fbd16528298cea8cc392743b216768363cfbf26da625f52f6ac05a991c435662a6f354a627a8b3d6a1e37fa66387c0939b7976a65cf243f5ec51daeeb2f772d70b9a84ff3be092db5d03d47fee8dbe38fc99445f91e7ef3046d400511dc124f01c5378cf300bad72fdfdbd292aab2ec94a4c1ff746e9cc3d9be80f96c51d689e663cfff0ba3f97ed22d51470dc6799f5ced2d5a8e0eeca28aefab60d83eefbf9072ba91f7d98d3e6669c37670470c2e40b8eaf2c17e5ee6ae35f41df6915f30a878b2ae9b529113ccc2102a89cd2b97dc9ff2b83317858dbe3b641f538db065e33bd936eb83ed4b5c5ba934338af5c5b08e3d1f85484a061801ca60ddbcb3eb42c438228a3b0597b68ed5d98d238e99ab7e4972c8709b67470a2c33392a2f5c63fdcf559861703cf6ca87e25b8ff97a894bd51703dfe77c7f230877a56ac674e5bfc8b1f910eca15737d51d665bb0d2e2361a7d8a0bcfee78bd07cc0c524d5cca0b30271e656c640f9b8695dbff631883f9c05a3023ae7c1291e85ef8f4179498a334394c9e4e858aa482048a5917d4ef4e27c9d0507747ae095fbb5c5af23dd75dfbdbbce2a731aeea21d17aae4b9f1d71a2d0753a43dc55c4aa864f6ca262dcd1d5c2567fb030a31c83afb32776a97b3410270cbffb5e23e7de7d1d1a0ee3394c3732adb3dc4b23d945f5107eb0af2fbce0272efdd8debd66bf72b73ef71d3e292781fd018185a4294ff17e7a9e67ff69abf33f479e934d772d1b3de8571755b8e761b6e3d103b29e14c9dede78be70d39f7d7960a4d7f5194abad33ad775cbb7dd76aca6efb8fe7be4115b378fdf9f3fe9634562f99f579cad29d28952801bfac21eed4d10e0fde8646f0e05da2c35890850a550d8e6654e11a46a32e2dcf6b6760fe2a3ee1c2b1120d31057ad377fc2cdea4d4d4018d7713affadc8451496ea83d098c13be985fbcccc6bb59c98aca6265f0954397ef62b8cc277c40f9e6330951f878629650b78cbb463d293846c6d206ab97c48423d71709283e4d7054eee566e67a7deb54cf87efbf1df9ec5a56f106214bdc3567d9b9a9de62e761d830f609ef2d360dfae92060dfcd3fb75568c1ab9bfba1926e1da357279272aa4cb077d41b84dfa171ff1155514508ee3652ec064224ec82995a23c51588780829d0759bf4ba88fcf805889e2a3723a186a8b53f72198d91bc8d76887355a7c39ee0b0b903cd32d256d9cf1163d6531a3f6b1b28da5060074ce3fc5678f817203f73dc81c1f34623c80f443de8d1ed13f118df73b34edb9d529d8781df887b0f78a8268e6451f74570b59795f8b5dec3e317e13e571e778808bdc90bca941f96d3707b50090df9f8f89417f7d1cf38fab4b14827683fe5d82b96bda4091c6144456eff702ae4ba0e9ba573778d6f9358b74e1ad20d0800cb4477efe48e8ee83d9af81c38453702cc18b367abc123a48977946e70181feb86c4334b85625f4cbedb6f24e3ccb2425fc709bf69af1c7bf34a4f3cd3cffb9a16945646ff75e28944948a5fe87d9ae2f9dceaf065bc4c53b1e2279026ceb9d78d8c1d84ebf58f830bb5346de66657d47f433b9d6eee37f22f66b3c477d9f9c8cc25befc25a06769a912060e85442e468666dd42766d1dd2d0e27e0e7eb8b9f9fb2738fa0fa5c46f6a3776b904f68b795a19ba89b894e0e148f26ee9997f411e5989c712743a9be0b1fb2b85d52d96042d99186652d49567a44ea3bfc9b71e475d4267f00896a3eae7398d92b1607e73da1994b9ee0e3e52952cc5009d576b907199516768c4b1af812b2fca8cda010dbc91e07c45b71d4a5e70fa29ebad0850e65ceeace2ee8b3be4fca2de9c8f5cd6271f0af88d947236eb4f5a3f15bd8cc7a148065954e560ce35ce8d951ade3c66d6eaf6fb6668e49f16a8827a59a2facd5c7b00b8a0267c3eaa53bfb046fab2f2a641740b7eca1b6ce38064ff3b51ec2bda99b80795b224ff86119e17c6db02c04d5e79bd6629ecd79f2b7f061667306952ed907e8a993713a317e3c72f9a3beb0c68b71cd732f9992510e731a3e3a7ed162348b1b7fdd577b897405db157d98b019864e764fb01b659ffd8c22b4aa8b69d4194d3436d5ea06d7a1fbd3db79b5cf99a874e5de1dd010ea10e794160425b9319d0c0367feef9072dfd717272dc1ae5fdee42895aa1fce46ab308e07ce3c9c915a3dfe712bcb233347e135c1b386a7690c6071a542c1bcb209d30788f1d772b7be2f0f4ff9dfaacdd5cab763f4583dcd307077fd3461bc11f5a68afc3a2405755fbe84fe73205e2d60cbc208e2490c7d6183a3ab95d66f494a03a360a7dc6dc99a2ea2b83fa33a003b6b3ebfe5d5c01a7b1ecb796c1d16a8c35ffe225c7a746d07df735eed54a7b0f3d8f00cd9dc221c96585cddd1ced69afca46f41d6c8578528d25f63acbeaebd05c9512ab68d7d66ee8351a25a0603937188f06be93996341f706306ab9d7745943e4fcb6f055cb2b9d384cf4278093ee0870ebd02301574f81845dd043eb1f43bd53e000fd0160843f881c7eeb2d974c18bda47ca8014f58e519697676f1fa55595c778591d120fdc6e3b67e31623d529cac84c6434f3f9a33d9d4e6cb487fce51b2acc1a95144e21ed959295623faad8a1725f9b4b27ef5dd76bde9007a01102cbe4050edda2d628b7a30342cab5daf881b9db9b1ef360c4fad250a3eac33b51648ac77c3122ad909f28a7b3dea36bf24a1afa6de7a6fbbe89cd9dcac962cb63f3c682c4baa308f8240c88fa802b99278f59258d0d3f15f4dcd062218c6809d43c5e56dfd90e355b9c8bad84049ac2eecb19e00b72e5e373421da57c71a2c14033d6176b0d7ff3025f7b2b051a79d4a43cc53e0c4919c516f7335bb210bad2ea80dc6ed4708295418e19a47dd5ec4543604764b5201aeec661e9c2851d2250cba4c1f5901f5964b635717baafb4aa59c2d3cf64c786798d7381dc27922bdfa3730d20c930ac3783734d9a377eadbfc1edddbe8fdb0c9b767401d1e947428bae67c30e9f4f329f34e0d4586998bd7e3c60634c54e2b76b03b53011259e1d7c89dbd4cf3894dd21eea25b1991df4527e46232e89c8e870cbaca95bd1af867d6a30c2251cb401fd8ef6d630a8bec3a46d6a79a24f2790d155192f699a36a5fd2a7902498376d2e784d42e53dce0098bac71107b18f484336580c134f632393e866d64aa22444ad47b9c501c496c2491370ef84ce6777d5c6f877d7e61e18f77e7d05dc10d6ba57029461afdfdf0cd0ee31587546e66e1b65dee57acead2c5ab7a7873286ecce902705100f34313c3354e3807b8fd97b937c3753229107811ac8be569b86e7d7656ad075531b8de7369b8889e727790fdd848975489eabfe9ab50a53f637c760b52e3dbb48fd79a3d5690fb5fa73542402df4f0267af768265e0acd787dc8a30cc138806fcf5a79c138dc97b311e38de1312feff040dbe21c1790023620fcfca12ca1b7cce848d7136b5e3f9cc197478488ab9b3e0ae5fdddded53bf8957f702bdbead66c10e235d12a11e2e54ea8825445e123621b2388c29af5366368ac9e4f72e1affa4ce0b46eed0a32df18932290a7ade17e00310349b446fab1b2781ed2c5f1cfcd786e35efaf9373de2148507efd0528cc74f3fb290f6e45f9f10dad7a7a0b5d81bc2dcfbc15796e91978a1a00760ad0cf0f26809ab97d4434b78bb20c8eeb894d5c5de8d1dce3b5634bf63c807850e168d77984928b187885a6166bdcfd98f84b21a8683d9da3f2cf083acde7aed7fd1ad6ba37dc69838def1335340215fdb68199ff9628cb73778a0786f9fc585e568453720762ba57be73b04984b7eff587f36a8842c800bb00eeb4d3260742a04d1e6db32e31a2262495260b36249f0034be8ce0672b53289f0bd8d352248015b7fcb1cd690d544c1b6f1c2cfcb115f09d57a218ebb728de6bf950db6a49b5c80fe439702cec25b398fce3e7657e8eed95a8e75367f9e3ef555fc3063fc4bb86d918978c52f88531ac9da3126eb2384322e9732ba4497d8045ff7a5b677d1080358655a1282031334585f8871f293693701314db9e163d88cea90f77738fbf6ba47da22834ea0209098cac206bf6d417549559fbd714fb6f8883d1ebc5903f2e1d89506c85450f0b08a64de922a2e6bcbf712f5b57a7b7d23cce4ebada128576ff869855884e1f92185ff6b329ba1582f319ecb576586657923dc3eba6c03b48d75908988aa864486d88b27e1a0e550c0471362cfe56623c6c36d4cf05b98ae78fbc98214f8d5b51dc5dbda5ec7a3d80314edbad40400fe7628f8da53c388b9075be1561f2c70f748ff3688cf93d6302a002527cf11e6219c125805c2b1e7a7e6591858582acb16c82e6e795e2c0db227e00471af508e7cdda8c865a989836bfcc6728dc4360dda167af5858edddeb737237a181665e7c3427101e134e0eb64163970ca001cb8adf155373d2b5331c10521b51669cfe4fd00aa7b0b66ffee382a9ecd577f89dfb375ebd13cc04f37ae6cc1e1185c8e68b780117b1db4dd0b28c433896596686cae2a7d5c412907271882728ddcf07ef20f8ec3af3f371c3303393ab6d7719e69b6d4c7175fa1c95484d3d087178f076c70526932e10bd80d7f7aba7e70da9eb7088dc16d3351f77fed30618383dd218ef4e3a169a6dea45241cda26fa06309f5e2450e171ef76bef450cee59f3b4ec4e5b477b00e3cda9d786f71aebedf1b1f302c7c89889152bf0739c2a7ba1c78e54a6ae95f7559b99ea0925cdbd94578e3497744d9b0b614e0c666977504f9dd029e9e75968b5117d4c15703fcd84980f42e4f04dbd014a27a8d5b0e83ef54cd171dd2484f01bba8c96cb7456f7409ebffb637883e73f499eee04ff6cea7d9e97e5ca402205f46c6eb74a8ca0a317a028630ab7cf321aa628de20da72a64e8295b13475d6196df7081323816693a67e7d9a47577b56d6edbd74e38e09cef3d1aabcf8232009ca70bbe902e5c624cd497c437600cfd0c4d00133bd1c2033442e681903b39f802bc0b5a6f439f8c066acbc61cc4da342323a44863dc822df0bf8ec6eea449fab497be76903efd25ef8f1fb8017717b459c29847133f1aa5b5c3931da73f2a4ff5f97c54c15a3385ef1a41cda6e3b258536c15e2082626684280b4ce917f2c28b2f8a620f83e99f3a27bd416e514ba323f184e78522469c19b73d137abf08346177f67d169f7884c23cd6ba3d38a8c32cff161e305309f4959591864c687744d8c494e6bc26dfc08d4402a48b5dd787dc1032b93eafdfc2ac9b90f7e1ac0b3a3c69ab5eed74484c8fa1da31a3ed66c236c3c74b2854b28d3da433a7d1cf12f0225c7a9cc8adf11f0331abb534afea231ac8154f7a5e518a34ebb9e7d47dbe7074354528245c5d9ef374ea0b8acea084e5e61cfbfd3c45f74a857ce065078e27dfe09ae84099a7138e7c5b155a8da3acbbcb9e2a40c153d8a5d34db70729fa2661452c159aee3803bfb5e62f17f44507e11e9979ff5cc0446e61c9673d0f1a69d33375678e625ded71da17a519f68698502bedcc8e975a48a4a26d9a2d8fcefc3be35ad168e327e6dff1a5f33178369cb6ce0993271bbb0373566685c9544c90ad2490943ac826a8f42d17f1dee1ec55fa0d6b6a157d367e5864423191b1c703d3b7d89b2cda139f32ae52f9409f8686959da054df34a3f77333a2fbd26768ce90e3d50970df387ea01e0b982618974827388c3de5976fb04e0c28d6fa89e52c0522e7b1408d5d6503673f398f0613d73c4f5e441bf685b465fa98f522de5dc7d460ebca35157f60732930e11e6eafc2760c22208941fc684b22f021d869ccb1659ae3cf757a5ce39dc795a1fcedbc92709643caf28c3b87fd4f815bd48e070f2ac6315d32110fd56090b5168cd5a9c4393f2d1a9bf41e9ef63b39aa4fa94f654f7b1ae32663f01f0a416b7a4de8be60ca78a020976cb367bbec5f862f6672b9f41fe1f77f2ab021e5effb572a2d9957be5d47ec13c4c365122ad7877810ec46a4f6804af39fe9e6f77934f18ba49941233f95c09390862d1add6b8e9c0ae63c81c1fc24e28f7096fd742b3de7cfbe8593bac19e6974f513e9dce1e7d9a03ff2969567e454009ef96422de8a833191e89798924edda61451d397ab6c4ea57d57dd94be2d88508f9531a7da70a03f7ff952e52e8b0832738d68da797985b4d771406156fe17932f37697044341fe6967c17f9c8efc6d4f29b8c850b49ce870e290d0f2f195d53b7dd71889bc3bbcca66abd0b99c04b4dab97e9c57337596b7a340293154a8ead17e84fbcc299efb8ff8a8c00b896f6f1e24cf6420c4a4eff14819f10718a4342a22263732af3dc35604b6e22eaa80a4cdd968977b766084b885a14965b0a0e57258bc28a8c028e354863751ef2f86e6887007291e3c9db868bf9da209edf9309c71f9268deb139de4d9c9033160bd1dc0d1266703622a6c5bde0f26ec899c67bd86383529de13c5388843d5c9eb2b6ffd6991a26a7edce9a4eb8f1877d0e6fa2c9992cdb8818227fa6189801d0757f42bccf0a54cd3f970605662ed5ec876e0780c598de0839aa1b92ec7c2c616b7bff1aa98aeafcc07f3409072f55f609bc20e76bf11bbb1394bc2c504a5f478e20dd39dc2eca9083343b49a6ddcbe526d44160324f50e69cedee128635792d53dac775da664ca2d798fd2fd5005f89b2f9988afffc9fac270e24088c70c7238d2bc79bc409e5440d49b87bda533d9ee0abf78fce74dbb15f023e9cb5826bf8b230a67406b3cc4344a53d03d3a4d7499cc1ec839622941b073205fa02109f318e7722e5b2678a0ae68cb9e289986ea582067ca44053448d5426d1b68e0905eadf4beebaff5fc54d897a56b0dd5b757f05717847de4a2863803ca0d6c340d5c6e12584407e740bb0c31fd99c604c2b445e67363c88b68b6d88c668324827917dca1d276f061c9bf8e981dcf9be6861fdcaf0bc46ad4cba815c7230c81a14b6b4173f41b918cb868403865df91a774a914ddcd4701b2b903a0822e2cadb77ea32fe5082049c0e03eeaa45ce0e3440b0a6d0013c0c3c0c3c0c3c0cac31c6ee1ddd7d446b5f262925d3f865f690e1524a29a59422f3f685672f04faa1fadcadbf1c17f90e5f0e690f48e31449234a7dd01d7ef35dc81409625b79293cc525cb9422295d87ba2d99dcfd5c5224768a9f27dea4082f47b1b8c555304bcbddaa6de1c1a3868553ebe5952d46c10c465e40431449b2f1f4c7a0f2782123e8000e1798a0c70be141222272344291f86b1bf784aa39b66ec7101eb863080f5024f6a5b510352556d4fa09aeabc4bc3bd4cb3b49d98c767944659886279283979cd158353a670ed0e844724ea69bb24766519b0f09823e24c87122d9752cc6f5ce78327ef005385c60021c3e84f418810a686c22b35b8bdd19235e515e743c879dee14b2b9cdb155a5120d4d24a7cb222c8366b6dcfc6a80462612ef35cf4b8b6778768c7c101d3b10a2c3477c0829b69848341df54ae6fbb73dfb12497ba9d388e928da47cfb1e54382f890165822e1ba376678f37ca223730875c00a342a915479a47ebe8da6b839901c414a01c9d1021111213a5cc70bc8d0e1011111114a9448426312092ab3eb928e9bdb095187ecd86178b440442497070d4924e8787562738b7bc63212c92e6aabaacaab3a487f201f3c1403342091603f1657495bb28e95901e232043870754c9d0814646780ce9818f4890da9bb3723c088ba61d68382249c70e95643ea665f8ca17683422b994f20e3bf16176e613030d462489db78953cce274d690b038d45249e76bf6c6f9eafa4f319682822f12e2b2df5ba6610974424d98613131fc57cf347444444849b062212a458f4bedbecd6f1a47188a4a42bf74ee796ecd968182279476db8afd411df8e46219292a8cad1dfed795f27446214abcb289edebbb48348ccd9f0243453da9b2f88c4241764ae5f0b163e1c880419eb2ae5d8af2473102012cc52085d5b26836dfa87abae52a9bb6ba560e1332d97c966b760daaaf143b2785026fcc6e4c8c9fb909445e6d59c92a89c47e643529cee73abb81a43767b48b41cbb7ca284d06fdb888e1f6664640405331811a1a18724edf98398331b1d5367c88e9424a091872471ee219f76f45f327cec3811d0c043d2a81c911634a6bce3e5d85a1f26b8439556572a9a9af195cdb6835cd30e5b41e74e4f06193e4cf0c3070a4444c8f0b1e38008f941c30e49aa72ca72315bba745487a42dcf5e493e6bb64e3381061d924c3f7c5df4fd6899ff2026870a76a4caa03187a4b418668425d3f4abe7d8da3184c7b9c00438760c39c10e1d2e228282198c00a12187a4ee98ee41d54f4d9d39b6340649230ec9b331c3dbdc2b2cfc7048b6944c26714973b6bcca40e30d49496905a59456d8ef300d3724ce88b1dfddf0e942a50d8925edadb2d46be3538b020d36247516b99d9459c75b125381c61a12345f52bf27b7d3fc8582198ce4a0a186c4f0cc5c4fd5a6aa2c0080028d34246cea8cbf13d59bf9e700f26d68483eb1bf29e49e8c135f8e2d0e62a5562898c1c81834ced0ab586caf581e7665af164229d5a6a4e70d8988041111e9dc010d3324aa6852e152a65a8ebb0c89feaa7d9d74e8ef60224382278da5e5937c4bcaa53186c4b8b172ce869dcf4dc5903cb2a4ed8d9bcef1320c09d6fd192fc64a88d9c190682232a8dee85371491a5fa8cc44e3a258b5cd9999b76d5a52c2aec335d8fda5a8507b2a6647aa0bc97f2b2a9bb89cb9a3070314cc60240734b890e8f963c2d2dca56e488bc61612f437f7766ef3ec99161111a9203a78a06a21c9b63a4b46d19cb4fb39b67a04dc5948d2ee2364a5b96e4f3616927c2f7d2625fcd2638ec615124529175d95fd29b511203e46843c1958bc56483c159e617ddfebbcdd0cd0a842720a995ee943ddbbe5a990d4252f9a45139f92b753483c69f6a5fa3ec9680b0d292476888ed9d4c73c7f8b461492544e71a77b979abbf3917a8c80af40030ac921dfd379967c7bcb8d051a4f488a1d6c5773bb4ead25481946052222222223c5f7041a4e4852da31c714849dad959a90e83eea3b5d8bfc64314c48109993fab6c50fd24a1a4b482a35b59fd954462d692821c9c74a6e288bcbfd291a49e0528513f3b4acedf8103fd11eddd8d727f2d14042f2e9dd14f465bfb83e3a42829df0105f7de56b6a232456b0b4e7ee614e7fb408895ed6d9d29cb9876f78041a44480ca5ecf2dda577519da3318404d163294c67eb65b53640430889bdb1724b53aa986af43fca70c11466042349ec72fd6cced5e8710130124c4578f8d8f973aa57c88c5f245ec86e7dda51f19f5435e28bc418d772b69bb5306b63c1e0ca1866f42249657b5dffb42df3c701f1a1021191e645c26eba9fec642a6e5f5830d845a2f99a0a52d4aeba485229bf629bf23ddf77c38c5c2478f78da7b64a44044b07583a385c245b07194b09d7b83933286f9158b174ca529d21e794e85520226235826b98618bc4beccf9197f39f38ab548b4533777954f78f857961609426c08f5964a47575d44a4d44819420c0d3366917ca3db43f6cd29954b2222226508111119a9205a861023c30c592406599674c43277fd8c45a2559eead11836acbd3360911843f3d6697a2fff393d0b84e8f080d588101d5eaa7a043108e4d1bd2231e35ce6e06b3afdc675862b922a775b25db90a7d25624cb07216f2d5dd85c2a2222ac48927be973b8ad20f38e5691e0ad41c8d26937f9aa480ae9ed95a4dfda5d8a67a422b18490a54eeb9c0e7ac119a868c5b2553a2b4ba92ccdaa44fbdfaecc885fac878e12189e22d144462f29f78c9b5211111acc304592aaf7b1eb2e9196772912b39667fb7d0ea5bfcd2045a2766f12db332ae69c3d20427ecc18455289874d2563d97b87449198838ecea7e44e650d4592aa12b13f6a74f4108122f9dc73a3fae5d0e1e74f24075defab4dae2792cdb2d385d20f569aec4472a5a5b8254b06cde044529ce6895d54b12c6f8ead1c3c19c605478611721698b189e4946bc359b6e799c85030839115ccd04462fc184d69bcd86d326604333291d49e4df5c9a5a8797c328c0b4444c8304252300313c941e56d52cfa33d69ea12c79893b66759d08e1996a8d35232b3d866c13fa50ad594e6c3401ac823f32ca852208f6230a312c9a7667aaaa9ba35f4385c100220690625924f47fed5e9532bae7d404444488fe731e4f8402222401e4d224997f8f079bba39cb792488ca2d3a714e764c9f7726c194084f448d87e181e3732231249f194fef13e13d2c393638b8c1e3a820019721ec84891819264de0463e01032e4042222401e07400c8f52f6c8470fccaa007861062492d493968f733a2c5c633ccc7844f225b33842d3bf7b9e71b8c00438aa460acd11c936f69931af967778b6e861462312adbb53d47fccee75568dd4c89e1f6630222979a86bb98771d77211c9a1325eeb4b66771e0c331491d4e5294737adb61e4f44e2a51c2fa81215c773c882cc404492999d389d944ac947818888e9404464a44c0716a40b0e330e9178fdbdf9533ef9a9374472b9a5e47f3a9a26aa1c5be8918f2043aeb410494163664bba5712a5448884b5ac2f197fac6af483488a36a74a79ef8248fa54396813b5fbda32100936576f35da49df2667002251637aa8179583896633fe807a65885d50b92f198dd3a7afe279395a6fe587a4127fffa0c2bc2fcce843a2e9e92c79d153ea0c33f890147aae924a4968cf2fea32ccd843f2698e95c6a285adce541766e821c1834c2a977598cba88a88a47161461e1274cebe7c316ddcbf82872451ee6afa544c7cd433ee9070a677fdfe64d29c2e33ec909cbff3281d4d77c63fcda84362ea561925c3fb4727d12131482f75d76a6b39e67348ee7fbbb0f9313253921c926ef4aa6b7be498d0c7018fb1cf16b7a0e5a9a2a9a0948d9fbc1b0ec99953ff735eac95b04544444478a494c7e1015f61c61b92532b8e5a36a59dd29ae186a48b5ef9528c15bd533fa30d49a2316e3a390bd6b133830d099f720e7aabdf838a7d0dc91a3a66a828e12d9a9ea106456bee525cb82dafd53a19b2d2b55c2cdd399d918664d3663a6d3ebd1936ef9e8186c4f1523fab7da3dd72ce90a4ae6f6ece74e6ce316648ceadaf0d6f6aba5237a30cc9d1c3c5fc1a2da7ad1a984186440d33a6932a357df7c7909ca4c6cd24c37fb4852222ff4084b88888884812668821e137cd29b1316fca2d991c0f044d30230cc921333dcdaf43e9395995edc00021c10c3024e50ef24d5d257ff800f20111911f3e80a00eecc0b04044640706487f216963e8494b97bb722cc7c0018212f06086179232ebd929ef9373391281084444b80e00ac98d185440bad3ba7ef45e952e5d80ac27c98c185c42f5925b3591bdee71d666c21b92c65edce6e1cad3187c3052110418e2046043982981c63e018038708708c81a3057498a105abb2797d6cc565c885370b49e2c40675df11a29d0d998185a470bb1075d971aaf546c10c468230e30a0923dd3b6dfe985bb722222222529f98618524195f4588ed9e907193636ba4ee0833aa902497530eba49bee78c8cf8206364081b11665021c97c4c48f1204406717704e931630a09a7632a058dff3136828c1d1266482129ea7e060f9bb2a818cfb13532d256ac0833a290f09536a39bd2c1f4fa50484ae27f748dca31bbf652c59e906096554fe697f7f41a34021111111120427ecc704292798e503d1121f2f78c262407b5a945e6f8d5df1833989058db35d6ab9982e713f398b184a495b994655de38eb271304309c973326a619a5d9dc91c5b5a2798918464fbd49e772c6ee594ef1948484a6255d332c8f8d8212222e4c91011c1e18210e800e2021c63140c444474bb30e3080932eeb69f2e966e6f7f0c19c1810f1f3bd670b82004385680630c1c26c0e10213e0681dcc304292d2171af2ec63f2d01521e9ec533d7b569341663c74e4082244070567308308c9f95e263c88bdb16ce5d8dab1c31cec0102ab1943e0ab44d542662db77b65ddeaf841efc26b73660821295310c2625da99cf9c1482af51015a5730ea647c048b2ac5bf174325749f48b24994a5fb456f1a047c717c9e3a54ab3284f2f92e23f46df50efae205e2466dd3b31162cbb537c1749c2c3e5e7f02f2f265d242995b19379ae3a139a5c24b50825d7ba9be16c5c2465a7a4bfd3eb292df62d922e86ac6856693fa22d922f06a56cf3e920e3712d12644c2d5dca90ff1b5a246dcccc56dbf6b2b7ce2241e5e6f3dd5aae994f16c91d6e66d37698103516c99a628c0813a7f636834562ee2515e683f6aaab5e91a477cc6b645bc870293a76805b653c0e467a87791104c01509ae99311eede3cb74ad48d2166b6f8be14e098d15097eefefa321634af9ad2241f9c58fc8cdfc29a6aa484c1e6246c5b01a936c39b6ce7210805424c73bff9341fc66f2ff801000542407f9295f305177bbd32992d4ffc5d9309e9b37c441a54d254f09cf241b4248fc2cdda036b574de2618c91a444f640a1634091b1889677266741ecb187355e317c58ed03166109d4d695fb0d51e9aed19a665ecc56d56f7f1969e5d6f41ade43dc7f896bbfc11adb21d35789178329bbca895b200870b4c8003052222436aec2229891aa5e9f2263dd8ba48cc96f46aae07af462e92d255e6fc6cfa2c730717c99af36234844a7ae3961ab7484a2927f12dd1a24b266d9134722b5c565026f4a7e4d8ea51aa356a91e8b13df55950426553cab1555d831689e1720c3bd22ec6a465e6408d5924cd47131afe6dfef23e7ee4778cfcd0014448902d2086070f03840c59247a4e5b52635229cc9262d17bca6a7a5cfaba8afb12a6b2f946bb9c83f6b0483a99cdf478ec945b751e82c373c82b926ebb66646c0815aee18a44ebfcd15a640a1d672b122c9a505f2d32ac48382b697136469dcad7088fffb10ab3abba44cbe6daac662c8a066da5efb9b33940c0021c3554919cae1d662c4f68d532158939a8143b7b42ec9c122a9245a93ea9e16b9d1a3d458210a3aa2dccad091525a3870e111116d43045b26e90f918d38a36cfe9408d52247d3695c554f3cf07f5f8111f42466e043548816e19bd71e341233bf81e552e30010e205a409647913c26d47e46535ff85a145b0a1e66b9c64d3dede4737d96b767518622f1f2a668bac2a679908322d9d2a65825c485533253e313491dd6f5e6dc7ed7429e48f8382a8e8a5ecade722792bdb2758d0961f355102043c608f242caf040193538c16d6625536f59cd6a6c22e9929aa8ccfb5c56a21a9a483a61faa27b1232d53b35329118c6f2ec3dc48547cb2e269274cc9ad39c184d25335d6a5c22415f28f5edd4d329dded2dd4b044520c5bd3d5dc9a5234c80b312648428d4a245b8d9b8c9b157d270b420d4a248b4a31b5f96306fb4e0810a3826220d498446255f6d0b2b433e7a21df1410d49247cdec7e456a188c8958da1462412f69214f11a199d636953a801894413beb7b66976c442778f48acfca0b3444524d4704472e834f11e3693dbcf6cf5841a8d483e9dc544c6848a27d38c4850d1341be2397b726f1149216c43c7542e94ac50a08b82198cf8a8a18824954ace8aba5cafe99388e4399d3695661a934f1191746a4e4dc3cc7de7f01049312c898d3187bc0b174324f56610963c55f08d4f2192d25d86e9a770bf362112d5a4abbe87f960e7d5184492ee932a6339de09a523d41044d2cb8fa5d29a749a0faa11880433cdb58ae9a6640901917c1bbdb269c77fb6afc61f92663c87f0d49e22770d3f24e8f8ff592bd3e6f193b149a1461f92931c917a29b3efdb1744444444e4742022c2e3f0a04f07c6e3f0e06af0217194d9f5670a32c3a80c1fc91164c88ff6408d3d24d67fb41bb34d9552af87a4b260322771a544ac55230f0942d375696a9de85b030fc92717f377e796e771ef9028b24c2c878a7648ee1511cd94e5d39375483cade822dbaf3e85990e49755aff4343bf2c65e7a0cd69bb655cd4107e328552613d7248fcd0b54bebaff97489439266bdd3d9425b3f3570287a69c9cacd5aca5d9da2ba622bdcc8cda2466f48b2b22de525fb7d2aa30321d47043720e23ba34cf3b7cbada9098deef4d8a8c619d5736249c164b1157de49462822222252aa588d3524e8b029aa2645cbbfa786e48fa7f4a84c25ae2ea7c1724fad9131b97472298cf48af5b92b2ec6d2a22129877c4fb2c67b3bc5121c6388882ca1c619924c27e53daba9e6a36386243523ee53d45252a32f43f2b9a6ee7ce72b322a1912d3688a5549cf31242513b519d46fce5e0c89e69783eed0701d5318064d978c7a2a770a189284af8c48133a8a5fe80b4952ecba82cc6691b57921292e6bde75b4508b295dc06c46b552956d5c5cda0a9bd6697e2e24e5ff2857417bdc335f44c4b450630b89a3cec497ca7b46931692fc3c844a71c487b59785ed529277734ba772293393ac14b34633866a602129fd7855fc147b17d715927cbde259b67c9ba62de5841a5648fcd5b6ec31ee874e9f2a24b96965df9dec924fa990a0e1d3831e377d4273a690e03d9a4c96d80bf79314123fc4cf48ab78e94f8f429d6919177651aed6b2c58df3a29f52030ac9b1e26590d14f3fa7477c0819f951d735a8f184445d59fd646e1ab4cf6d4084fca8e184a473cde9ca773f7ceae050810970648d2624c7889ddfe4a764f6bed5508309099a722fd8459f33fd2c216993fca7f7e7e0d1ab4e430d2524a89461c1824e3953af35929098f4061dba4cbb87e66b20213167315df9d27589f174a003990e747c60c79013b0958e54e308c9517c2ea3ab9f7cd68795358c90a044c6fa8c72b99bd232a8518424295629a4ce49b3351121e14a960cf9395363085d57d9bbc5a568b9ae52c72ca12c931c712a564308c9a57273ef86d82a29e2704108520e1798608c91213982181184800c1c2e30018e3c84118c444f151ba3af1a09f2a657100630b6b3142e9c79c55bb214366811daa9a272bad4a34118bf487e4f7d8bf312bda91ba932be04af021384055d410e0e7ea42f9246a74b616954bcf4ffa352070e7e040923d17aa6f963398407da9013242222403ec70f1d474718bc480a2a9ba754f35237bf8beeee3653bd5553b5829655ce962d6a09a54214862e12f4fa7c0a553b73f5837c075a408671018e31707c0f74b400c71838827c074e08781c3246827c18b9480a6fdd68a7e4981c9535df811d1d40c10c46c6080317c9697abdaf4f8c855cebb2d7932d923499f7e7b829338aa91649f971bd9ef9a745f2e914b7f421a3aae86791b49b84aa0bd62d6abd2c1eb5131f4369281689fe992b3fc7b878d2814562890e972e5f4ebf9cf38a24214d9dcb5c975ee6b82231c9aebde8fb3dba3aad489ef5b4a0f3686ecf382b922b09a921ac55246eca2144689295155645721233964fa8bb4f4a4f45825cbd509f39a3761c1549a9f3667f86916f9f394582582b59daa66b2a6d8a4413a2dcdccf42c5b64b91e8f12f2e7f483b4f991489a235fbb9fb9bbeb5a3480a21f36cbf3c28755251245e9bac67eba0bb852259e47cbd99c94dcb8222e17267af8d09b527cb4f248adabfcf31d8b7e79e4874f5f841d676143d3b91f89784e9175139eb889c485051bfd4f9274ff13791202c6637f1f194dd729a488c23e6360993977fb34c247c69d11edfdc554998484eaba67933dce84a954b249f4c498fc8d4711896483093ef74919a2c3d692b91a04e63e8a8bdccc59f124929d3bf987f8599ea2c8c4924dc788ee154fa20d7c123842189e4dce93b4c74eba91989a4ce4925cb29548e8d068904dda41d2fa78bea9d7e44d29d8ae13c871c717e3922297c50326b0a6acb3b258c4624e7204a05d5fc418a503322e146a587dc14b37f9645747776495cc4bbbc62ba56afffbe9ae6eae7159118fab974797fb2155322122db42b87579c0fe9232239bb7c73e85cd694fc4324a67a4b8b3de23e636f88042d25735ee7c6b0132a44624ab2e3a64d13de39881009b656aa32e820f2c2671009e667712b4a08a5dc238884cd31564e59d1ce2e271089dedba33f6868d2dd0191183d68874c414fa6ceff9058a3e353b21cc32f64fc90ec6526d4aaa60f0956a5eb848eaa29e9f9909c74b3528ec13e5b4aef21b9dfacc298cc5339ad8764eb7cf9dd2b699d340f492364e3bfb2665492f1901462ea76972f95e57b87e44e6da3c289af4f427648d88ed329a5bf707a538764adb1cdab9f79939a0e49f1d3ebc8cb5bed56e79074aff323c46af4c9520e8971ca7e2d55ae7e280e8959b3e7aa7d99f81c0e491a1ac455c9549b62de90b831c6aec678aba9d10dc95935b6cf892c3d7f1b92c3665d98b7a4d4d6c786e49c47ea08a1ae4e3f6b48f4cf31b899fc57911a927f366e2caa864b95a52131b3b56e66cf29531c0d8949eb6651b71cafda3a4362e91cb3738a1b9f233324962cf919229732245bfc91dd349d7261214382dda98b9e2958aa928e21f1fdf3c584e5d0973631dc96ccb3b4ae72cc5c4a5696ee295b2e6611c390f47d55232b7ea820ff09446c0b618021f9db5ba3a7c73d9d453d76900211111191c442185f48d06c2633e6bfb3c5b080210c2f2469556baac5a79a0a87d18524253373b7dbfb267a2e24e8be9f72cf1736a8b88584addc51fe2ee78796b4909ce5a393541196e5ff2c247b7956c6b2b6be94c44252a9d49326ab498a50e508e30ac95f99d2e3d70575a217111111e991c2d23584618584919117531065ca445548ceb0763265935fd1e25448be20b48585b1f558e92924e5f8b6b678b8afea5248961937212e2f9effa951c0e44ec62aab3d3e66be3a9cd83bf5f3c9e2e55048522a66ed31f7a52b7115c27842b2aef89928cdded0f3938174009142184e48ce31fe680a9f720cae87d1842419767cf367d5861b851006131236b3be8f0e26a67207218c2524aee9b09f64103e1f232524c6d8771d259f242478e9257d41550c1b72184848da94940c9bf36f784e3942d2c69c45854a2a23245a5de8a049b533da45287a6599a58b3bb1b738e5a9b29edd5e3a6724088308c917df57f335a9ed7a6410c610127d7cabc2ebc5ae5bc210425e55e75dc1c6b54d2cdbeaa9cdd93efe2e58c148d2251bd7f4c54ff7554464472a8740031889a7ef5a37465339fef78b64bbabeb937edbedc91164a46a478e20be481aa14de59455497a56073a502f12f3de664c1599d9f17820233ad081ae74a003f12231c7e0b3a753d6deeb2365d82e1233edef96f70735e53f0f1f6408e9e18347a93284f4f0c1233b40431749aaef2cb6bd3c68c78fe181c7e4223148cd7057eac458a777ecc04562ff6e58eba017b2191fd2825b24281583da185fdebf6d1ab6484afa3c9b8bf86ece5f2d12ee672bec2dc78a13ea802d0a6630f2346871b34830cf3163fa1c3d28e9c922c9d5c488bb68f2739d6291a4ca2aca27a1aba38ab0382ca69c865c785d0e0d8f39af2c7efb8a44ad1d8d337bfd3190e791e377b82251e6542dfc6dec76ff030d19413a769c217fad488a9e3998957f0a163a648ca07f2b74c86045526be6e6ecd1e5d8f2e182213ca0b10a135145724aea2d9a7e1b6e93468066a0918ac4a4396ebe12a533593cc7160868a0a220b2fab9b3280f171e4344a4036eced551572344628e7aab719e5e4a5f83c0423f4434c80822a95faee2a6ac15941b88245d3b5faff61d3f1620123bc558729a625364f587c4649f435faceea9ee87e4cdaa9e67f13e24a531addf514445950fc9b31d6fb4da5cdb0401ec21d963bab8f92de2c399f490209684b5f9fd7f4aa53c246c983851cbe961468f87c42b3d1ddb725a9acfdf21c933ea99bceb20d4fd7648dcddf64bae7d1d926355fc20749790b1f2744830ad993497c80d9e417348d054e163d66cb1ab457248b4e0622a059d9aa774e290a4f327cfa3e45b79cc81438296dc91794ec38ffabc21730ba7bd9b3d6e4870efcfa752a7294d9e36248ed0e17a4d2fccc6c386e49cef7e399b7fd690af214166bad31745df67d9d590242664bcdc77f2f93169484a37be5aaa3f2cc50d1a92665e6356ab8f8dae3943c29a14b5d1693324fd7898c586fbdce92e43621c25326b1b422dda6448ea78224e89daa88af518927ec4bbf75db4bad18a21596ccf2b6d3c0cc9a547e9fc71db15130c4931ecaba6aca5b7d47e21a9b22e5b506dab157b21596455c896cb57ecb40b89b1f3ac9bac4b9a772e24098d7b153fd8f585b790b81f9664a66ecabca61612d3678cf29a75b262b29074615cab72feca12221612d3ef8bfebd8d7e3a7785c46c3a936e5f8818911512d4b9fcd6c7947294568504b16dbb95b992e9890a09971ef329cfa1820c4d21297fb654d193a89b2e85e48f5174c692f1186b1492c48cae86bc2bf5b2a09078c13f67b2a896f72724090fda293de384240d6db2a366313db00802684252c878cd5c1532a99e04c08464ebf8ef95f289599b04b08424172b654296ec36350940094915f6d26a4478d6ec0b2009778e4fb174701f09499ee3c9a44b7385b6fc1192fa62449c8a0b4b216484a4fc51fbb94ee4670e1240119254e54ccbb431666c91008890d8415c3a0beba9aa21010c21492999319a772f79cc11801012734cc92ce718cf729f602497662c574baa279380916c6a33e7f511f3a6f38b048d374fdfa02733c67d91b82232bc36a8e6cede8bc4edcbd828ca548ae9bc48ca6d32c7ceeb074df92e927bb4888c3632ba48bacfb2b9415d25cde72239786ec91f7fb96d71911c437f341735791fbd4592d7fa6cbe678b643b5963614d2eb6d2b548baa42d3cbe85699120bb42d393bab348de74eea7bd2b2eca954582f61cf3b4f54947716391203f841471728545724a1a47bce6faba5b5f917c9deacbba652fcdea8a844f1f64e893235a5a6d4562127272c6e44e7854599194f76fb44b6a7e96721509aa4d33c9c85ac754aa22b93fe628e282053d11539198a6569b9e42459268bd1cba7f31de82a74836b7683107b99e397da648faa432b7eb7d3ca552247d276d6e719acc2745928c5529ba5cc7a97d1449517e4eea8569b05614491b979744a8d5ad9c8522413d695a901aa7770545d268ac67b0e4a132558c70e313c97139d765f498447353373c916429cc2dfbf8a87c3a52b8d189e4d7e8bba1662a9ffa8d13092a05f9994fc71495e91211791da4ddd8c4e93daba5604965cdb863479a256e682269e499f2e0d96f1ab61d3bca002224ab702313c971357f5a7fa344cc66beb88189f7d4fdadd39aa92e91dcb6e9c7e4a9e8ef694b24aeebc6a8f8dc6e41e14625125773f06a0b2693f65eaf7083128977aa4a58981ad78e27919c3bbea956fbac93a50216fcf9d3c3478f138888041903c7182f1011e1f14282948183f339c610630b372491f4eaa92fbe7f6d8c0682473e4e90871b9148d66cdfe775f7414c9a632b085619a90210871b90485242de6a58d2b3a911b31e2fa81b8f48b2ada0925a8ddffb508e15d9c10d47247a7cde8bbfa32fd721c38d462447d3e194507b3f73298c4850fe5ba7eb5d5f737c6311896a25f4e68af6712b223146919d82d22f6d3b0f7c784044043d0f7c380311f2e346222cd9f17363d0a2c9cab1a5831b88489675b3fc975757d6e0c6210c957bf9b2f9402222222222754084fc08c02d6e18a2df1ad9192a864b938848bde246210c0f2a89a9da80bc901d3ad20842a6940e03c40588b841085e944a6de27c63ed83d05ac6cd33defac55810ae6ac9673fb5a4321a886754d8aeb7ab874ec80d40204e8a7bf2bf53e16221434ed00304c9821b7f483239d35daad2e592b188e20d3f686539ebecd2da698975650a9bd161a512dce84392de0abb1f2a773ae8dce043929a92ef9bdbc1ed94ce70630f897a1d5eaba45fcedfe65821407cb4e06af5906072a3bd9eae144ab37948103a69de8e96f235d31b7848f298dc3ccd5876ec306360166edc214907256a2e8ed6bcbcda21513c581af9d93f7719328c1034208fce870ebb5187a451bbe5fad9ac43966ed02149e6d1b13a5bb8649acab1e543c899e0c61c92f3d6d584494b39c38337e4903c6bda9e231df4d05116e4870f12dc8843f2094dc983e7cecff4303adcc73137d85bc10d38a0e9b116e52cb9aab9bccb28d535ff2474463e8790911e3e4682e828037bdc7843e2fc9d77fbd7cbbf8f80f81819f9018210ac99c91104931b6e08620744c899c08d362ce0061bca781c8cfc0041082070630d09d2d33f96509dc6ef37fbc00d352486d2a284e6ec66fadb810f202342928e1c41d2909484e626ed5faf3a31a321c9e6cf93d01a37d653ba0337ce90b01dee74a9986b2cda39b67c0819d9da410e1f3d4682bce10ddc3043d2789a2d0f610a6e942169be7d35dce4e8f3518eadae203f52d082ac203f7cdc0d3224a5dd1cc477dce4e1fb3124cd7dc834ba46ff4c460c891e6329d7e875526fcd46c10c46ca8d30246e0c16b36dd8598fe606181254ad9c579041275b4b8e2d10b00047b9f185911102dcf0c2ef102244c70e09dce842b2081d44c9cf29c6f9f68790213e468214bbc185a45fcd7ba1ffdcffe2ba76630b493247772c0b4b85f0e08558f10d2d2498549d1317fa8d2cf470316e60a187dfb8c28e213cac90f896937fd9e9ca500ffa07f2630421c337aa809049c00d2af44048101d3d1870630a097fb6233fdca79ecce5d8ca1d14f3c00d292ce04614c8f81e507842026e38c187041941be1f04b8d184c458ef6dd9d639cb3652868fe860c75f21df8f911f890cbec104844c901f200841036e2c01488e2023376e28a1c71008dc48c248eec007eaa163070fb88104bb11ab54c08d23ecc861041f12a408c8078f11840c016e10e14f0f1f2308b8318405dc10420f93c3003682d1e375f0c0701e3a768c1cc0c62f7698213978316cf8c20790efc1c80331232df0c00946608202d8e8c58f07e2001bbc58808d5dfce071783c8f01d8d0458e203a7ae848b950800d5c08d1d143c72d122ef7eea34513672567b12d50878c0019413e788ce8a0878e1132bec7480faf4572c91b8db6af967ab44ab0418b4435a1c583ac7a04312341805c59e5e6096ccc223947d3eea6a4534e3a1fa2c0862c123e6876571f711b2f4371b820042222303041d0494444444444444444b6468e8d5824c61331730d7a33a54f08323fd0c8480f1d233d8c0ed4e347c8d0e1a5ce43c70e24a3870e2036b0018bc4bcf15d7e3486d6a44c818d572064760ce1317282b82248026cb4e2c9a8800d56ac828cef81001baa102244c8c88e213c186023150eb0818a740a0bd830057a1c04313c46cc0e43011ba5f833043d909113640136482164c7101e11b0318ac4db1c3ae54f428a4491f0175b2bda7357a7031f3c0ea28d5024788732e925ad3fe9f74a03364091a43e774a37e7fcdf208f9127633f91a0673febe52434e6dcd188fd187932ba6d7822297cabea96c539b6900f2123f7c3ac13cf438710204607233c18f901821048c0062792443e54a74dbd1e33f2417cf8d831f229379170b59ad152e4868d72c7101e239f0a03363491bc27c682d2ce535f990f21239fca056c6422f1d35450c9b2b3ec25f148569848dce077a7d2c71c7a71194080983362af0320434e2911d8b804036c580201362a8190a104901c049904016c48e283181f51808d48ec18c2a3003620919c3a5b715be5f731f6d0919211727ec7b73d22416efda655f7a9605b57066c3822492b27ad6974dcddec437ca011330ed86844e2e676f936a1ef6b4346246bb78a8a9914cdac16b16cca9c5b1ab18ab231bde2e696f48198213908a22eb0a188e4587b5932e36944d37e8c08313ad295a6fd4044c10c46d64622847c104494f1e3f0781e232668410b5090a8200505b07188c490b13958cc71934a691b8648b6eeb4e2154aa5b88d4224c52b0f659b4e4224698fcbaac74b4179741049f7e9d1caef4e93ce1184aa5e6975a3ae9a395c4b3385aeec4d0a44c2a8961e6122442619dd914a1b804890fdb39b33349ed0b88d3f24ef8fd0d6d77d97ea5214cc60640636fc908975ac6d8a7d855e99aaf85d7fde6df42131a90ab12abd67326982bce07ba0a3053d7cf0f851061015f010030448078e0e119191a30307085880831636f8909c1bf3e7c558d931e404c803bb17888808493e82888888ec303a28630fc99d622f74b9a668483d80630c1c2236f490a0b67de9222a25d9c11c23df031d417a043d7cec284eb09187442f31b7a93e89dd1363176ce021a9f4cc5aa6aa8da9d75eb07187a4ca9e6ecd53c7861d92920aa2f2eb6752bd241b75480c4d1b43675a8d35251d1237fba46ac720a65c9c43724c1dcacf44e698b26dc821296466dbdcfafff9b38d3824fcaad98b688c7f52da80436207952a2b4388f618f38684d30e96bd3398e651ba21f9d2a787905927de726d48d29cce77548f6cb02139851dcf3af22dc89cdb58c3729e95d2b865d79758eae69bc5a6b0dfda504362d4920b4a6da8a6936da421318ed21419910d36d090f867d7fffd1d9ed5e3828d3324658a7de947ce6be93b021b66484cb9bdadf6b07f3a2ac536ca90f8156eab840ef256836c9021f1455dcc3826c4f55e1b6348dedbf2106a357773fb061b6248982dcf1cdc72d9c68a106c8421296b4e72e675c5e2731b60488a1bfaa9c43dcfeff7d163c4c617927436d19b25e4e5abd70bc91f458fa9105a54bccd46179242b769eed2412b89d3061792f3996bfe94a3aa6ad9d882a2256a5e516336c64d3df4bf6b2f254ba64e5a48d6b720afd6aed94dc959c82c5e33e62a5af63a7b2fdd26a3c664caf6dbc04272574c9b35d26fdd4a574858bd6c1796376e38a91592624fddb27cac19d18d60a30a09f366c94a74caa94ca242528f5e903974f8123d4f2131e65f10ade8f53a5229247f29996536df96fd1285a4ca9779ebed2590df1cd880427290f58a96729a99474f480e3d5af36cca86131235a8dd34322631f3add8684272a8cbb853f79b3e8e3698909ccc374599d9b01da18d2524fdfd9a89f2741fe22a2131bcec69ac0f17543047602309c99e5a834c799be9d8d182175286f7b081842499ef7c3cecc77b9e6c1c21d14be87c3246891e211b464814b9d821c493c689080216e0b05184241d63a525959dc35ae8870fb64184a48d5796bff1e44b25d9184282ac39c0488e113f954b29ee34f30b937f2e7996625029f71dc4f04552ffb99cacf4c22ccdb0e93ffe749a17c9f6a6b3b6a9adec5aef224198e63e9db7d1ed2d2162e822f93253f0caeaa7f2fe5c2447b554a1fd3a89ba9a997f181e23e82b0e62e062dbda17f91d3cb7488e95161f84af39d6167f1e3df5b85597f1538b045156a61b639b7ec8d022c937e6decbaad1baf52c92942add9b82e7f40fb12c124caf5a944c32e9edc40216897b67524de7a0572465a5b060497fae488e96bd7279a76eac582b9252e6ca8b418f32cdb118ac484e49d89adc19b3e0965524587cc55819af54e5716084a02a1c2d31d1b0d139e72f15d5e5cd9a2e23544543457269109dd57ec783c59c02b9fd6141a65395b14da1481519b44a598ac4284a460979513fd34a8aa44ed25be542651ff9e620c628925f2c97768a17e476174592d4be34f22fbe3a2814492383e6f5384a2ecfa0481e3d5161c52b3ba5f0271ecd8dc15f73aaaca42712fb72e4b52f09559e5a4188d189e48f35225e7f2fcfe39c38d8a629b526feda623691f4faeb51c332ad7fecfc2086264ef329b7076526924ef766fc18e244671026d0a04644c3ecf644778904ede7ffd79d27a6b51e3a0c10647d10c312868bcaad499570377b2ca59e478f22258c294b3ffbe76a10a54924997ff2984aa733ed31922899501e4a854fc96f8118914856f3b68df59c7fdef2410c481ceb634c2756a7ddceb1f5427454084ad09110e3115869f8ab178fb11c5128d3963ea52e79ba1c86071b101f424c8bd188a44e7d3129d9b86ca22264088f9132800829c50373021c63e0e891021c63e01803c70fd9616080630c1c6655c69700c718380ac8e708624480630c1c2dd0523f0c8f91c288d2ea43456335b3aed243c458445268b615eb1c56c3b3e587188a48cafed713ad4139b6321109273ab542dfaa2d543f50055741ba04622022c9aaef327dbaca10e3100976c94e5f3279593393632b7d20862192f42b7baa2c7666252a44521695e4f456c7ca4988046d5dba1b653ee52a9d321c2e0841d7160a6630120022883188c40e1793888f1e3ce634c7d648c5400c4124eee6b0dbf962779a9e635fd0230556573c74f40dc4084472cc9a29c96953e65f95b383188048be8e9e57e2e78365bd6110e30f89c1c3d7765059bf54dce020861f9292b2df70153a37c7a5b620461f124eee65cbe2bef241870fc9699a7a74f6ce5aa5d741313688b187448b314737a93ed7b6a8410c3d24bced9c9a8fda733ad282187948d4b87bdd78a32107f1f1e3c020061e92c39ad241dba70efd81fcb0c2e18210f4f8821877484af23f7f89dd764850f24466fa87374d6131ea901caf2e9a974ca1bd0fee910211912038f0e123c796410c3a24884b5149547c2bfdb70a62cc2131357789eef2b2c420861c12b36fb9c83d3bfd8f6299418c3824c95342563c1dabed8339b682f8481d8882187048bc685a194df3e9eb5ae920c61b922ba5f26c23ec634da76e1162b8214944e489ca4e99392d1ec031860f0fd81ec4684392a95dff121f65cddfe682186c48ded29b4dbb8873cf3eb120c61a12d5f2e6b5cbddf466043b7698b382186a480e15691ddad4e61f3d1021235558412e21461a125b4ddb32295577f1d190181f4764a71679ad416748ea943b65c5dd69a8dd0c89ea7ece9da45d86a4f09af74e67cca429244382a5e0a3626bccfc5ac1c18e21de3b4c0f20295000e0428c3124451b95ec536adb74713124da7832a1c5aee2066518927e4478144f17f3590443528bf80b7b3ae97afc0b89e29ba556940a993313c30b4942b72a4751719414bb906cdd25e449713fa5f25c48d02e2a7dfebe680ea32d2466ca8a6332a74bb11f2d24288bd9fac4b2a84d791612d3e8d44aa64c4ef4060b49a9f9fa1696ede5bf429287ba1c9bcf0e8fdb0a09da9ff2dca7b60ac929eb695e7f950ac9f1f3c94f9b72888f4f21f164900da1f5eda54c2924fe6bbac698b011a7282466ff6911aa74fe190ac919cf3b469919dd2d3e21e9c44919d5b9a7434e481acd67991d2a987bac09c973d5d5c9b49e7b8809093acefa58cab92a6c969014bf6a7564cc59bf2503319490b0ed96bcebcdf7ee4f4262bcc80fa12bf8e6899090789b29efcfa7083d3a42d26c0eef2d3a5aa63142c2bf9b98cf94234611123df359fcff70994e2e06119242ff2817991b2ec72ec6101253aeb8e229fba3e82d86109264f7f7c8a48475d51d8ce4da8bbdcd5dbd3b36301277ef3ce34659cc60ff22312eb509958f9edf675f247e87eed318b634dadc8b04cd3f6a36c7a02da9971709c29210537bfa62a87717c96567de69e4a68b04e951ae541075fbd6e622c94bb48b1a1d73454971916cda2d332abf4a577a8ba4abb4c9fe54e80f16b545d2be9d8d0931f122cc5a248b570cd12958524b495a2487e5cdee2b1973fecd2231ec2993b1335d27f5c9222987ddff347e29f3bc58245dc8d6a9df53bb18834552864c515d8bb12b6aaf483aa17454fe7c39cc325724a90b59f3af5b91702737c6b28c5b32ca8a8419155a974f83ccdd2a125474cfa53fe60953952a12e4a89c623a2925a455a9483cf94977f20f2a1253b8cab1f941eca64f9194d475a5285e31c1004c91e81eb3c4c27a7bb65230f31d1e166cd3fa4787ddec1117d71a0029122ca3666639fbcf0d60144965ab214afdc5bcdb0c1145e276dda53b15e3190c201489393bc2a4961096a2840a8a84313932aaf666e711ed3e91bc5b194545dd2a6da11ab23218802792539d6cbaa991f5387522b16390953e9792aca07322313b74d0f3a6b647a32303d84472cc9362d9fb23bd633491149ed2655bbfd63a9a89a438efd85227fb016022f9c3536751b9bf446266d2144b578fdb6f89c42c514aa8a0947c9a330403a84462d0b33c8f1dea0e0c801209b729423f75dcb2701249294aa88c9b3de5724712491b1a3288d2f3654113890479d995a6c4d58edc20916cdaed3ff65a8f48f60bf27333ef4dc9932312ad934ab5cda446247529ddfdf61be3a81323923c688b99d5639d635a4452a8a496e4a7140d31292249c45cc6de936ce7522292e467f516cd3969d01222923d2c542e1326c468e9108996645b4caaed4c8cde10c9e9d455c959126ff2172249fb8611eaad1bd27c4224eea824caa45fce58428348da7953e17f533d0921412458bcb8d79be4790e428148f0537ae75e71791f048884bd9c994ba7c4881afd21713346ad098b273c8cfc90e029beaa9eb00fc9bba2c9459afa942ec487a4b4965257e9f39e7b0f49bed6165cdc738ef49098493d5b6851d57a1e9294bdb5274f6a33a878484c5b3265c87f3e3d9e3b24894bba19ff946750b243e2cf65a8d2acd33975483a6d51f11eadc9733a24650a7ef79ff428939943c207a56247df2e0747be5d683da1c72139c47a6ebdcbc6cf391c126654be1c73478beef91b12cb4ecce475f8dc147743c2290d3ab7685679501b12e3e94af2b35c8ede860d0997ab63847ff78c69d69058ea76c3684a692c346a48caa35e42bfb6aca9983424e8fa669dcce8a88b414362f49421442f36c7a43e4362888be551b3535b509b2169bb325b63b40b23ed3224080da18316f5712a6d3224c95b5fe6e5b4592c3d86a4ac1ff79bb3ac898e18922bcfc94a4a7e0a9be630248f3aed8b616e2737832149affa6d694eea77e62f2425cfa333d908cd95642f2426531e4f6f3b5564dc85e414ac4fb7ff29394a5c484a5145f34e796a50da42625ffc94b36ff8361d2d2449d3e1f22909d941be5948d41d8b3173a65bf3c54282ce24b4a9789a84b6f70a492363b0ab1c7334ab6b852425a3a89495a7b4745b85a418e7c9fc47641027a542d2f98de610a293fe904e21b164fa182666368d46a590f4bad9f306bd277bd4282426e527cc2d99298b291492cbdca2cce7511d9b7c8235627484be3a9d903c621e6aa3e6bcb9661392eeaa3e8c67ff9f9a4c4892ebb97df409cb71e6121254cc435facb22cb71212734eca44bd9c84a457eb95953b25d34542b25f1cb9a3515f737884e4a09eb4258fa3952b3442e251bf3f335f84c424846856ec4784844bb62b7fc13aa6f1063084046da6ab4cbb299139031042e226d11d35c5e3874f309244f57996da75571c189f3a75da1f63ec1789a5b92957e5ec1c35f345c2589cccdf65bd4852b567a5b456f430f12239a8ec9341a80fdd9c5d24d8684dbe17dadf575d2459306dcfd94467bf2a1749d2de828e39ee5c12c245f2c7671137b2faa3e616c9a641c36e97d0a3ac22005b24b676caa1dc92cdcca830f0c08ef3484404c8ff08420601d422b133656c051bddbf595a2498bace0f4bb3ef412c3208601649aa937bca183b64582e8be4f2d09ce326bd9d358a4572a6e7d0e9c48ca9dc60915c41b8c75892ad7b571904f08ae4a463ac28a21bbf42ae48d269b38ad21a6266f3562458c86556dc303b716a4100ac48f4100df2bb2cadb2050d02584572ff8790d5499cf0f0601504a08a04cb9b2bd672b8dc5ae7d8e2f580005291781932855cc5184bed07024045f2bdee6e327dd9b2a673ec8e1d660c211f822c08e014c9bbf7a2bca328f76ce6d81a11f2646c09f910404100a648daf97c398acce09d934a91b85d6954ab655c4c132912378ea94bba962e9ad02892536ff4a539759e4c4814c95e2ae6b13756ee1f852231c60e325baa145024992ca97e7d327d9ad1279294787b909993f0f8224f2426f1142a5f9d1dfcd38984d1ca31c68f339e520e2712646a7b8a29db94936f22493e77be7bb71f65724d24a69af8fc95e65b3fcf44622561ee39f6c5ec6430912cea4ea78faf9a52d25c021915a3c37ecc5822b97a7b43c7d9145a752592743c4fda6208254d892991d8a5c3bfe8e4195fa49348b23079b3a2766b719544720e391ff4c6e7181b8d44d28a4c979d534ef5b3422259c3c22f59c55476e72312e7c46f4c44e664c9744492a8779dd7c8e674c946246f4ca9a3af9268ed9111c997f629e69613b242b888c4d49a3b4787934b1b1591e47ff75731e518b38989484c396cca9cdf64574444247de51c5c3bd8e8ecdf2192aa55836ae639251f3344b209d77495bb4c9c6b8548fc6eef038dfaa8048e6543b250200a06436150200c06192ed701b31300001818201146a3e170200babed14800350543c522e2c18281a120b84e36030140c8501a1601008068381c140301006c2203594909b000a2a11594e3fe036c405c5883ddc3e418700be1e083f5d1086ab8e07a88343ee8e8cb125bf45db1c8fcd9d385ea24a4d2038e40dd60903577005fb8d4be833db3ec7cdc27136f2d800a94ce3c5c8b0edcdaa86fb63334610139862584ac57612dc106b7900db133bafd8dd2dba7435503fda81d8b1ff575e2e47420daf6e4bdfc66eea1921dee85d1ded846ea499ddd269c0bacb0172c7562d6fb846bb08503e277d1aede6cfa80314995da14124bc830706efbe5862cfe08610155a92f7fb130f4b22a7076663968ad9183690b6686b3283b2ae4f4f31331574f08c91473310ceb70cdbcd5cd4c1170ec3402fd8f11c5f58eb3d31c6e8182056479876c4cf2cad7f45d5e7ed97e1374dfddc1197a04863f6dbe22494cc990d50cbd4605eaa30bca97c1b4ea7df3937103de6c4734c19546bd28aca30f3a03cd9823f1eab1966190e9b02bd0b7f2a5ea4384ca0d0664c7223f884c7d4ced56b49d48ab39e15ead14b1c6562b48fc5798a16ce2f9f9287b7c00f4d981990628faf42b60026cfbc43cfba7bd01cf5f480ffba0bfb0fca8f441540dd341f077744d0d115940d8bfd6292b50cff538957f1b34940917bb2323a44b2c6c085b52d69a874c3551fa7c34cf7ba023b291801020d57795a30c82a78bcbb0c4753450b2cbac8357da429b530a3f0c7be9027d4652fb9c97f3f9491a3d5cbd0c2807f9af1be9de387e04ba5c0b39b56f744b652544f67e328aca0d792d6981bb2cfa2d6a16103de335eb23718350f17295411ca3d5c46d68ec06ce6dc2022cb0dda990b8ebc8be83468efccdfd065038c317ebce09a9da0dea441e329eec84c3821d96c33149579da5a4f167062bb35aa7d26d3178e60f17157445e96fdd2d4cdb5a0553d90415b93ba6b1b425f068c6733c38508ef5bd7d041d58a0f468371f8d82b06c4c28c6ac16317e86adf20d6734a414c93ac77ad604c6ce4b8121e405e70383c4a00e460c4c2e718bb34cfa9342153ec165b389e6537d62c7205de576e1281d24c0f151c823c23c3496cdef1cfe0ddd8a3e8fbb690b226e8a4dedb701a8a36e8821d14234b9052b5c3ae69d0fe9e914b794d3b69cac675319a6415bd4062cfb3a09224480fea802eea55c6529537bf92e60466fd931cf454b58189c059d40fe1283a524c7dabd613ca246f353f0c69078ebaefabe402ea8c3479eb055e1e009291b8cad2020035736f4f1f45c58d215f33eb936a9438a23663136cb37fbffbdaa902fd02017cad5f095f94ac0b6625944f31c614c72c2b7dc8da0a04c5d68c4f4a3736766ed07dc59bd0a77888facd160b14f6e535d5585caad2092b6492366736554e445840aa0351f09af80f3f8a8c339838a3aa6f12740a87fd322110cf034a32295ee3a5a598a97a09febf264aea274a1ebb5d27c8867666b5e805e7ba4c8989ca31a6ee8cce4b6b1b5cb3043af403df61a9d29e6d715583305d9b8586740ebda77152302b6070c4de573563d7f7dfb4c9eaacff1828d0e161e62b0bce99bdedb6a4260c71314153ecbbf32255f90434bf22a393723195a140f97ec0987bc845d9ef95fb73570415f6474d0e1c0743ceb8407950887a571228bb603a791c38945d0b2387a23ec016fe7f0bffa70bf7bf318ce4bf14c61cfb87625de4dd2447d5f1f6910661cfeea378df0c67a9b739333013e17f95e14fdfc9e07b328dee334998c79c1119f8b5376301eee5491a80f5cabbcf98b4333b095899b566f7597c76a7c569778a38ed8a1011b81732c0f5ec4231899ea6d0a8693a05354d45a012f4042a414fa011a44d390285a7acb7ae77bf57c62782c554e8b723d9e6bf726f939e0c7aba282f2535e71299e0a535b2126fac0d22f35472b7d24f17edc687cd76c34b32a0a348f37a381868fd75fbe8030c0488a175a0b6afff2be2a8a53d152bab15615533bbc67d5dbadde7872c64ade91a588d40f61a852ddf2d333e112603178abdc2a53b20f9359b9b8708970f8140d680517f068bd98aef3c36167d3b9206c1d3885ac605dfca6bce960e11690b3163ca49ea967dfb1474c169dc8b39713c92417684427ac48ec0481c35233c624b34792ea55a06a989f9529dc9b7e94d1d6026449f6fb8161a9561374feb0840ff486e097ead78879b71883caa0f3881f7183b0e4230248f6c08813427560542c59101a191d6c4c402bf20950cd9a238a4452c0888449009e191069119e100c09456bfd886d14847a2f57ab29843a824af5c7ba3674f46016ab9e1d956e05e49260e6ab2214cdc9d512be01316d214fdb5282000ea87c3b2fda6d6ee28f8928445ad32cd15f764ad894e8b613a9bcc2030b0fd86fafd6c44c6820d8db0aa9f81d53e41dffee07a49deb231b711902488fc7705025b24f515f3c74b055437522aacc418c438af9e7a0a3dc2247245a2e215063c35025fc0892687b0b470652e1b2a3a9c04c185fdc587ee44e0dde905addd38a03a5033da12f142e344674b7c005734e44f558a31a25fa1a6599a9ce2f8e10471d1684c34464cf391a31824aa3819cb1291991b72c0a6fee4e58c4d4f4b6f7db10944bcb303f0f3a6409ee7e9a91ee80bd494d0a06558f05707cd0db35c5229028ae1dd8298a8eecccd7f4ea4c8a5f153d785b44a187311fff04892a0894e49a3d0a86950b5ceac154bcd272d879ea367d3e1e8b9340c0d9f86450357bfecf9517ec9d25af4667a8bde4a6fd0b1d39b682c1a3b8d4563a03168cc34362d338d89c6a4b1d368d2ceda46b6283bddc6f6387accfae3d82100950cc183dd6ccd25c0e93e136657c285033f2cd442be23b3225f49dc1749fb96fe995648dbe426b999dc426e90df5cee30b749873264ffe438099e0427c193a048c48a3435685725cfc926e423f9844c934b04718236f0dc3393198372938941898913dbc47689616225312d653331293176627062e5c432314d82495005c9402d164f451cb325d50610844016ca2be57579893cd9464696f9cbe430819700258012b804de298014280a6c0235014d80df1cc190c60f3b4f67a50fa67f7a7402fbe8531e68d73c1790e1bb1216cc4d9c426ff1ccaa4d98790e817325ffcb5c655234a99bd4261593dac46acf65a899198289f69a5f3203a20ebf022b0540817702802e18f67564f7faf6c818bd0b40ab2d20715da9ec11036e7c18f7f8cc07f6689846dca8c3adf0df6f07afed2e56f7801dc39c0600a99524fb487e49607625dfed0814486b4066ad2579a38c2abe3db1111d6dc6ca067a688bd160a03119f71f8e00068ec9ec0fd64440205504d0b658a346a52b8ba68b1db0c884c6c7bb23fcc8b26bcd3cb746204128225bd5692548b4116f434f4b6d0f236d903e55c416da6145a6b9351a5c66d09405c14116565bcb2420e25c111bb6618c5dae575886e2385d34d89639cddfff71830d39ed6f7fa1adcd2c79c83437986057a06e0a80ec6f015546926fb7a23e8757b7c90a47692b7bbec3cfaeb552af6091e8dc97821fae271081a2256873f6779de8fe33d19969b5e6dc29c96ab0761addcd50919da96916a7755f47ce505a00b37d6c1472b6efe01dc20f00d9c6643f266de30d7a0efce25b81c0b4e8555c9792eadfa168b165cbe22b986616790ed31fccdbc0bb7c3af1cd946aaf9b8442cb53ddef873603cb9b10588a42e8a78893db3c5c40ad57479741a3b0cc2c742f643af31e40170e4184bf9b6e3ff7e1bacf6e5f11409eebf13dfe8fa24d4abf0bfbcf96463bf6214ce7222f55164fd7847083dedd6423d96e33af160f6bb4672029861ee89fbe520e82006eb63139ecbc424c2e15986e83257c69ad89b5342a738ebc74148b3e088c38bd5ec82c6965fa45e28d52e9137b3947ea3af34655b8191ab113baefe291b85c0e8d984c680cfe491bed936837dc01b63228af7215fff5ec15e6a6643849f1d4e9d883a02baecd0cb63c777c63407229a7bb8857c931cbc4904f6bae8fbac1632ba0872a2b5991884216ea6ee766ffdb37ae9b7672d6b5c8239d42d201ba8a64d757ed27a61f168b15e0a516015b5c5194c4599a26357c567120cd5773b00ecd633b4400c26f9f77d8a4b05701f8a0c4c6bc71313b5b6e4524bc052902a9b6c997e363820289d1dc632696254aeb4e1e129f3a3bb46611d133cf83f715cfae7136fd87c3e3aec49094c791fb7762b64add5b0bde87d0c50adc3f982a04fd381e3cd837954c008f9f9d850d44391bb1d9b68e09bd4f76ba9417a59d11b4d1cdb763e3bf9a06bca4e621b01f0c03460eea1782e8b553387ecdcd839b138673224e63fb957ec84aee833bccafb037a150497600e17833528ca57f224eecd31ffcb7220f8519e6d14f4cb26da223ae2b82d4290040b753c9322f35f8e0b0e6991d01b2329b41f46ad3654b3283e87a6cc3083639a9489daed40066d9c23986a66a63c6ae6c23a80394a0034a9f6dbd8e4c2da42327786308c7bfe7d3bba67426c1690901eca0d21483cfb9b384ffb99bd27576f153a1af255ee8b539a671b058933c4e5cdce83ac114d173d5431d933bcb8a691fe63905bb553dc8d30ca9f7b04c246f3ab337fd4cb70440064bc6b568373299e05de3086b1b59ecf853a8e9fe95a0272af00a5cc024b26993eff0c1eccfdc14862c01e865caa4ed167024072dad6da7fc69dc793b498720d90d2f8c91903492dd15a642675c85eec3a7a628184de929566a87f0905198fa648ac2c6d03c0b5cf03ffb970eaa2b1d344cb1c5c379ff215e53bdf33c8d58d5ebb25d499d4af834b2d36be1642308aa5b5646fdb470816d3a9ee04b5ad1aaeb5d3b2ba61496dfefdb3aed0bf60773ac7087e2a43d2e0b1bb755626c574f0650d7a3c8b3894b4f3d88b76159f840c25a2ffa2878da46d447fa6fe8752e52b3a8467886e3a83770c3872fe18480729e105a7f144c10ab9194731eedcd25aa637c4f9a0b24b83f742e5551c449cc18b5a3437e6c233b93a50c7b893dc5bf10cb028a5937bd43c890f2da379f0e146a42504407fc90dae3663aa2775adea1687411d75f371143191f53ee1b4e6b9218fc078150b8c94151f1ab18e4cc449716004eb81287c980e43b115287bd8f9199013f3b51fe8ee440ae4ca7eb5ba52295f7b76c2ff0f52ad5e1ae476e1577e93ee631cd16ad0f2e14e6a1e2c61a254319735ffb51d9454223cd598bd22b29c9faf02ef139cf40dc9f9f421c980bbe2721df6badbdc74a0bb46aa3e42445e5bedcf3fba6019caea8ccca4f7e69175ec2d773ba07fd16471dd4e6e4976b5272d5b026245eb010c89843b4daea962a078fce7c1b5ff7521bb2be81b6f787bfa990c178a5fdbcb8876a5f75d857baad96b1f5c370a0383e6b6ad7a6ebbc339f31f785976de16780e1b053f71a0a579b9ab75c6ba8ea481f528203f436360e9ccaf11f9028af7b01ee2e86155df3d028bda2bfe4039f20287e374879be25db565ffa9aa6f31862af687134526f105b598b387ceff6da5994994146def61ea236852e5f4bfa09bc9c243a91a1a37a15891cfdd99ea0cc0656ea058d6d94a656bfa32d7e3e4f5279add10d1c1f83c4e30e27e892d40f866ee0b05201285a70513bb062e2cf5accc068bae1210f36901365cbf91d27e2aa1468a120f71c30995b56aed38c06dac40847da3714e8745d3137a63a415452244ff87645c8410dcee89aca694ca3a19e3dc993bc4020d6a31b265dcce2374047aaef9afa1dd704764d2f222cbc4829e4ec8812413dad923b4119153e19d02b535c986cd51a80fd79b48421196b801845a12f17c1980ba34153a77ec0717de3cc001dc7d5225b7135e95e3e03680aa677d53ca6fb6d57d4d9575763ec408f27f6f5576aae9a02d5ab3c5157f14a37c3f821f302021cf66310da96756c11bcba01a3964365bb6d95f7ba2a0abca08f7fcbe497553d0931478172f6f5c04eb4d6525497767407a2f0cd0b48b8b85c2e6b147fa0fd97a16c8277f90d76afc7b0873c86ad127a4ed118c4b433b96c0a84469a0f5198278a2de8385b4bb80b491d616a76f0cab05af30de50e22f2929bff037aa886622724f3fbbddf749624a03c0e6f1be5cc3ae366b5d4ef3fe05622d1cf1aa2468dcf72f3ad29bbcc11df8ec45753b8de94d3cc73aee7f048f89edac655533449ad1cf13bf6da694ac7b3e2c1beadd159dcb59f5ccf670f6a7068af8b933078e637b992e827ca02c455b6fb6eaacf656086d4dc99c49e381fe7d5afae063308c51fe7c4ac451e6353b9dae289bab548922d8bceb2938638610d123b4eb838f567d30149be89fba7969a89a820b18ac4b48451eaca152e9cad013c3cda940380909b0d0b7bcef97a1ffdf8184ea7a73b3925e4e25a85e6e9c452f34daf2a280f7cacf2cdfaa0ec47a141b1031285526a032a3340867e4043d706acdd7d9334ea436c431f193b6f3ca28b3a25d4feb42d12b1ea4a0c6d4850000accd266c5ba145d9a2e07129d3ae5c4b7f575ef93c6c6364942c6860cd982213690f1a3f86593a302497739650003360682720a224dcbe9100dc42fd85294771ec0ab31a3cd5f7381811d67af991328e36b6784f47389311a3724d28b30f1008e5b536829177fe430b80a7673b596d7a9d2620c6cfe208a26f2ab56e115e16b03538e1904768c9abac739c3f096fd75417888f00d392e189e711647bbaa46adca19ac3d7f59c73d76328aea048cc5678f91b7aa361650d85ac9250e4abd283d982adaf48647ee227adc5e025e8648cf0c0c945eb1564d8842c1c62f5509b2a73e2780b49d4714dc7471699fee79fc3c9700c4de3228645584b62bd66cc5b5475961204610ecfa58a58d42ffd4b766a879c32536731f6b5a8139084deeac287870d92efe22cd91f68fd37b024cc2144d39aeb44a61bc698502a74821f967d3ca80b1765f16014379f1462ab228160235615da91cc9841cfff2f9cc03d74b6a235ba63b12c30f497dc9354c12c25a13728e90b81f86c930cca7b9f90b6d16d4efccf151980af01475cb0e8c1b2a1f8587d2947005ad58bf71c754fe727e0863650a6382060a05fae1c2b2f4f777497bbb859263ef4bd4f0756c05f69475cc38172e835a0489e441997af0891ff1f6515b99dffdc1109eb349514a4b0d55c2841bc562625b779dd64dbf8e72217a3ff4f2ad3bdb7e9cf4bad24952a24cdf0afb9477b54174da07fd5e7583ae0c8eff0041e79ec64bb22226b71db2f0a173a0afed4485e0fbc835c936f131d65abcecf0f876b2758811b8f059fe113443a4bb6958b238b650ee6ba02fc2aa7eb4d40f3ff88ebe8fe69c9bdc3a15b3884f64361782526f01120636545fe57167d28a48e66de7e422485d23d7f6ebf18fe838e2300ddcc9c6ac10d3b18bb54e51228ca909e772db8e19d2b8dfce1101fa9e014ab322656c7beed8dfc270229f221308cb81d72d3c300d743c27ce9217936ccd626a4f03d3f37904f5a580d2a6ad990af57166b52306cd21c5ef487958fc586044d7d37200d56de69a55172827388656baba6b6912da9b2c35024bc629adf5cc4241eabda30e0c35f2d79a09f572ac7de219619231d02aa719b7f1d91f6b990069d79794dcfd58469082832daaa07c92e22932b2686d333250073b3425103864ff6832d778c384094a414138dbdd04045d3e38dffe26965cd20b2c30d151c9404e99b081c4932b38c0b542b328243187c16addaf1717d5bc051e6c8144a1d3537140b21dc26352566871412ea8130ecdd8365a7cb38633ea7d44a8e37be7fb2c0c2ef99ca475ed5ac551f1550c4e2362e6219f40f6ea10c392848c4880db00549c707fd451f61f5276095e0349e1d0782d0edc7903babfff1d5bae7e75535b5450551afa3cc14a424225702d8c05b91392848fd255d9ab035078f936a2edabfef5869ea56e0a2dd48f598b6f2e9e2df57e9fd2a9c6c2c0a1479512f62e95e7fd536b7c4a8ad4578ecf2e5d26632ea36e26e9a1419846dca9af858d2a0a609a2e096fdc6f2c3ca86db59d9420f9ec66d68188df4460b4e3a661856923d5cc9d40253344ddb175e02c7a077c464d11e60c4d519329e1dd21b2774b1a3c7606a75ff44b1c990cadd34e4724f14d5aac76aab08b2a07fc8988b271e1fdc3b19cf52d326f9dd960029d91e2ab7a80967ab34c0b82ea5aa5dd4f0cf27dfd33ff7f1bea3add79e5fc15a5453ee0ed8d83a5c3eb3cdd07ecb294070ad762d3d63b900a4832a0b04034d31e0522bfe031f5004668322d7743beaed9048b100e93d916af872dfffe2f2b0a077a518ad37152e288e5862d5819434c6d0dc03b2971312d95ae65e093143765ed682adce71cd30f2985761f81e9bb4a8ae5d87ba466665efccc9811314e891daf1266543ad374ab14aa259ab7540add745f9dcfe42230ca1d60606f8905a148d2a1226075a6101d504ecbe9ba2ce9ec20b905008f45eaec91207fbfa02465bbd3f0133c789878f5f7d32a8917ab895e19a8f60f57afbcde818b2407046cfcf63a9148670fd6ecbee73181264a3d87e1831eac0d336770195fbbe8203702029eb97bdfb053ebb8c3faad48bc6cb0d9b82673816df9514ef6716dd2c04f734417297787d72f2cb15638ea70b2673c87f3aa5d223cbe4391ccecf00fae4286ece387ffefece85e9b08ac716d772e616b38332c2b202b83f1c212c7121e5607d1aa5812961843c290622018bbd08b1c041ad559d4aec82e6a576417b52b2c55ec1a4639465d474da324a3d846a1512d53a551c728cea0aa11aef20c99257b4060f867923d8f224e0096c24b1b4df2fb522cbfddb3bf17007ff24b14600b683e77061d8b4aacc3386a0b2e36c079ddb31ca8e00a0fb63fcc7dc4e18266ec0c96f15b08cbed417f857351cee43e75682e1e079f391dd5dde7ab49224a18394656a8e36834de8b1f9b4574d3649c98099e681116094e60448258089aa0675ab5335430a1126bc9deaf2b6eb78dd2f92a9a37ffe8193601b6c03f921e9bc15fea0ccb05a41147c60b6e742fb0cf94c41932f81216b1c181ca2cbbba75161028e64abcf7bddb6e81804626f85d34987e5921a1aab09857cca2cdbd76ac711de0541a62a161ff9212810ac74238f5f0b2214a860e48bc9a789b042a0904bdb0b69f9f227ef292669f3c1bb012bcad269c1d8d70b3bb9432921129f3a02b9cc019d43834ddc7c147d16ea15adb268296a2d7fa31e51a2ca4158f74d97c1362666625469aeb5c62b76577adf08ca7842c149611690a01a4816fc20765dc7dd43881fa34492fec9f93af1705a101e6725e9204a40668469d8c3b6118d3b36290e67c48e752c4b1bacbc4a57f9a9863c5c0df4d2c50a22fa9f38d91ec52d455c74880361eec583d70b577814d30ea4f08fe70b252c41aa6f00a297c99c2cf783a25582b3657714914757b7a186b7ffc91c7df07fa2bc8f3bd336629c0c2a011e224589f6ba04945d5a233528d931608ba4510d10390c37e2084268d6a4a1d121792e4c0965ad0776ca16de7eb5cf814a75b791738789b85e5a8bd0a11eef0f05d5906379666c4ff2b414a48da2520aa551f52f85288708e7fa675a02e0bf4422f2e00a298dcfe5dc8d25472028f66ae568bacf02e79a63efd72f023a8ad713d5a5860007c34de4e325ca51e8fca339d8b6209340929c7535306b18d26896910bb60449ea139c96970809734ec7f60e430653ecc16ca4950748beb6b2878ff62ee7df9c18bead36a55751bbf87219c753e1e5715c885a5be19222abe475bf5288899a92ded7238228a54d6675d8df3219eb87a1248c57eacd50d041bc520db0ea240851bef8ae533b759a6f117bd874416b043e235e862b9588b409953bca74143ade54b2a8aff95e019652ca18ad2b2d2fa3f580a22b7a21b1b59a8d9963881474a2ac3bb806600876782e843070e08f2342243f68d4ab1c1de52d9da0f7571be9eb414387d571dad99ab7b8159657906854af847a5404095eb08053fb2294e726d9481cbb4f0effad24410b226b0748d104f4d0005febca76a0ace6a490ca0901c7e703ea2b3c4755b269d18844f05579b008d796ab8fc4d83c055bbec7ef4b696ddd31828bcf997289034a15d8abcb13c334704c51f6d62a1fac8d3e5f273716f8ca2881660981b109f7bdeaacc1a19638e6aed96683f88a034b2d396fc7416ec8cd9b7444d463c6b14dffd107cb069af158c5e20d3ef0b6edfff7e08b93bf99dd6d97563e404212337a250f362be252997f3ceb239ba588a0db57d096e740b3512eb765f375e7c59071f9acbb14f637f31f7c9cc94088d017f8d054bd61a6994863156f67639c6a9970d8ba5c9924010307d1da26225ec95f10caca9986984c851a4ec756e00c43b957a47978eb184e687fc7680268b97be310014241403fb1226622d587cd7df10ffe6ebce22303e46281ef3a5d81d590e2f421fe1003480b7d52786490971f2544f0a20535f30b453dd09ad428427391621f839613d293d67dd7095fce2e1dae15812fd908142062d6a519cf9417537a4a6db435518fd14d79563e1e6cafec79c2ae0aa41ad112d361e02317fc461916b431b8001d0961f1a8995d9a0fec5d5c0752c1f9b5ac82950d799603dd1248a852a47fa078e36dad5794156a90d9ac3b3eedb10f20e931dd12e597b660bad43a2fa72b5af9819d5c2c8dd56e1f6dff64953e0decff826edeb067a8aed5d1ce62fe8d27b379361647cd362ad8693a900a2025e80c6feda517e5303c08257cd5e8a96a89822d37ff4e22ead35566ce86e6e9df4b4887d6066d586931daf7b400ed6d40d4b7e6eea701993abef7dafd355b5a1510c62a3348c2dff790ce229e86f5c00039f10f5df15f8b0cc8fa93fdad7d115ea3d0bbaba4db6df89a79989bf3599d7612240a030a59cca28221d29d49d9eaa9de353771266216940a63100415c955a0eac742a93499571c210042902bec94ece3b17a57ed3543d291423130f3a7e61e5a18324cf73934f2ca90383b88df7222557092232eaf467457380b127619ad64cd6caeeb50be11342766b50732ca8ca2a9a658e53de133a7af1ba8f6ac11d27bdac07af3e5a903d638b4fd329c15ac1633834d4b5b9837689038c6e0fef755df4b517d46c74251186522ea3b2b3ced5990eaecd6512c946bf305cb02de745dd2043b8e316a32e45b0acf396e550f2c9183287ecbee6e4cc79bbd8624bb58c649656a6735b69dd88b191e7b35ce2dcb72c83507c77b40e482ec10cd1fd28ba28c37e9d99f6129a912ada3486056d7485d6877dc1d8b150e503f31a6d3756cf638c8983ae3713fb121a52791ee6c12cfb7732a9542d6c3b6e6d7d7a23a1590986a04afecf98dd1a116c73fe915a09a784885f5aa8165ffaae04914b5d5221e92851a3c12d02923b995d20f07f6272995fcba1ffcc1e95f102760d1d144b6bdd8a4e5747453b90c80f9738145800bc4a428d9d0dfaa4ad08cd30372eab494df05c7bb381a324b71adab5e4de20d2801a85cd0a9ffff519c10631168f31ade23483930b51e6f08fd4e2f881f924fed330e8cc00a48b4a8c6d615c9c89dc237e6483785fa9f2261f545c35f2b48bacbdc6680825f99d14fac69cc9be54977e2720f65b94b2989fbbb1329e2a670d3243ae022608ab1ead04b705d842d4e0f725b7c11ad072aaba04c9ee75b117021f2bd5fa0b72b9a4b5bce954d597458f6455a5e11a01ddd093856a722ef1a438369799e624198888cfe1f6a110d603603cff985b5a0c4d56d74bcf540ab1e128d8504cd0fc92cd115851fcc57336e08c3912ac9d157d999f479046dcec8f436531762fad23dbe1081c28f4b3054e024adb3322a32627994981a729cc1da93e5bd8b9592ddd99b464c712c0baee7e931422a05d055e106f25be22b94185b55b3dba8f6f3c5d579d17e0688f4697c0162086865c8506632e7c6619e86504a435df71967c2f40aa87658fff813006ff97c455fe600094e4af0ca55aa7f2d50134c2c92d940f4d2874ea20ea52d6c31c6fdfd779566e7ca9e6de360fb247acd186e7b55ecec973dc258c984b613b908292292ff040d011f87ed293c3825e82c840a67c0981e5cb8894c21f83074eae0f333cf2378d701337ea5d9be0d598141fa336bf7a229d1c2300d1db81f5a491d2c3ba5c283bf6424b764b7f06c80a7ac6e5be6d116495d6b808c509c9e53ab36a729e85deb82201c9817aea9dd1209894db637a865fdcb98479743692af50e4ea6be499d1c32782ec57a80d768fcaa37e471f2995878334d9bc9b13d35b9afa7dac22e5135db374f72392f09789051ee923f75d8cc64fe295930b854b68da983312dea3927b5b40d3904981dee1d0a336feb1a15c0ca303c9b8e9f00a7bfac699a0827ee3c895db033d3fe3c2b28a27409f8128e753d75e1d9b9f329f6e704308d2eebfb828294b916b8ecfa1d889c1feed95eb894bce82e17a3b921ce5f74dbedb85adb4c086c25194404e70621c36a382da0e9ecd03bb6c23f4650522e87670725e78a828f92c1be1c6b5399efd6e815bc3ce0c8eda2d1d29d3b529940dc1e4c772c7a6bc55b908882b683773c7b7ae1e9200a80b0022de1f2ca80bc573ae1760e254062bd7eabad15dbf80616c75e0de7ebaf3f6ad5738e076d03b288eae066bde21ca5ea28936b70e2781110d78d66ca907403c0037c3791ee2fff2d98921bff62fa601161725f72a46a5bfd0979908c7ed02965d3399ea724479c5947bb62e122d0e1cc3d4ff06cf132f2410a368414d5e51fcacded1bc518f4ee193428668d25072ff3714dd3cdeb50476efbec93b6e3c4fd27337354a193b4a01a46ab8451fb43cb0195908a8f61f1e407f9fe160ad5a945415c990280e8a008a1bbaded12dfd57084943cde043f170fe2a32a02d2ea72953ff08aaaae6f50678d432dd37046532bb0c756730017102129edc687a81532a385ada71c2830c106966a7ca27ca3f8808acbe27bfb8c618fdf97d14702a4102a5ad347c53bf73a9b069276c0358070c9dd1c24391fb73f27904e8388d3c0e6a480f9aacaaee86f442c51f9bc73178abd9d32845d8916eb40203c65737b68b80bfd8584a0d4ba90c28b422ee37874c24b61b85ba16184a1bc0346f20d2a3075b70c51d3e25087c1a07118b095d2f5a4f1bff8c570e81330e4ef78281e4ca57350caec822486f18ca4a323c296d5ea6350ca1c19937278698ebe1e3aa93ac5879aaf4c24972202ded45a0198e1b3ee14d01f2545f84b56c97b7c79f35a1a13a85e27947d1f05221c3f8354d08a2a85f863eb0d8fa4c927907c4c904c377e8a6782fcfe63ce19da395787718efa6e1e8a1ff61ee378af10491806ccdf07035bb9fa9870efb4fd44cede7b8dd1593e140c1e4c9e7dce7a93941b4cb2b43ebacf499e0710a314050f6c0e489e315bc4203d5b5e00f55d018ce06b6b00410dd4da6a624c1800608a36963350421b934814a10a6e18d4256cdfbf5c59928c626f1046cec697e92b1c225cbc8ed098136e28b9b2996a28b3e47e2efc20dfc8d4e16941d8b2b1d5e616a6a924d242d12f75c293049c981632a7fcaa7f33aecc678370ef933f984534a5fca8085c3594011d1be1f4b3cddbe914643d0e3a2f7f26fb3f59709ee7bfd756662679e61d32978e0dd8cd6aef72192defc15827f3ae8969b1c26888cdcea230ea02403a86baffad22efd2c463ab0ece68ff4482c2d264013f8834130e66a34e8117961dd5b0ee826740636d469d8321d800dea2498ad86767a063b3b8945ce413d07cf4e112574c10b178be1d0c7474df663646a2cdf0ea786ebe0010eb7b8a6b8939c7afb06b65ad2fd2a805c8fc654e617ff187604e1df8fa3235bf548002ac4ae025e0045be0c3860b02485033033333333333333333353c7c6fc367e7f11db5811216d64e672e50bf28a94b429b3f10be1c2efe01dbc7dc8366bed226d6e952f0dc10ca50c85ac304306fa38e6abd4232d63a1f755eacdfac17d460a2cb4349639a58a9d4424640a325ea1f470d2e985f90fe9235728293f56f081491ecdb61890d10a7dd0553969fa4197048b0c566819b46f2f64f0914b4cc62ab47e3bc96e29920f3e55e86d757a79903fa950264d84cbf3f171eaeff10619a8d072f24b57ef8f33dde6586da0025968e1022d6cd8e8838c53e8317b6baeb9107387bb0419a6d07c503f1c39dd3ceee30d24166c8e2d707881a30b162c067084e1c5035c4629d46b9d8e7829628f224f0a7d18b1f7b56be207f38c428f1a1f260bf7215b0ca92043144a760d3d321f8f735bda43a17c556c4f9d3fe13d16149f50bc2d8f24ab07f57e6114647842cde3ecdae3fc117e106d27f44e5e3f1e7c90797c761a410627b4649122068f929c5c2e7e055cbc6f4239e948f1e463b8c6be39c2688166a1451619c8420b2dac9441862694b96c110b4f26d40f7eb25b553ff0ef31f1c844540e9a318f46199750ff479a2db6465a96d072b649fe711c49595f1995d022264f4a791cd2fd207203c9a880400625f89be463d1d39f0e479b1c38b4a84005b2d0228b7f01171908430515e8c0e7c0a1c577c1616861c3c677c15b84d1366c70f1c5dab03109edcd7e9c62b9581ec5a440bb582ec2f802050d862494cab311132185fefe9011095db4ca7af8c9b692446566900109fd22f23067a4c89e5388165f70a1012ffe8b0ad8b001c6175cd023741fc4ab3c7bdda992c60a321ca1a76c92bc62fa18b96aab828c46283f9290ec819fffa6b00c462836ee2e29ffb6851e464090b108e52ff3f92066cf25622a428b21e385ca963ea44c8e6714a8800259684002d75ca08c442821b6b22a4e90e02502642042efcecc1edd0d0d5339849291e5ba7d506d19a31b480707de00631d50508621b4dd10ae736c8d7199ba8154868ec82884d2b5b934c48dd557531201840c426831cf0f34c5d6cc91470f429b394b97f993cdc70b42df3c9e09352e6f1734815032a47ef371f0c9ca1320f47cf2a32c7a39197fd025478a5b967e7c9f7bf841cd1197902963e5818468918516e902197dd03c5c5ddb5d1ad9f2f0414ff136e5e1d77bd083fd7ba50e97936cad07e58386bbcd1693073dc6c922f1e2bd75e581074dc34dcc703ee80e7abc6e6f7fffa81c123b689563b3276232e6e9d4414df2396bd47ee486880e6a4dfecb911f83860d0c1973d0479d8791b9f9ad73b864c841dbf3c15d798794b25864c441939c30f152da3c1efe78dc4032439001074d4effeac72953b9fd37904a1264bc41f36c9363de3c3eccdda0e96954fc81fec49082c36c844164b441cbd9dcdbbb87b9818482a309d8b0415a6441bad0efe20b1568200b0b48208b2b2ec86083be1d31c6cbcc1aeb3e6bd0ee2a5f8a7b09963179fc40861a743dc99b91736e69dc345c6691ab2c6765aaecb269929f468c8a045cf0112828c840833e1ecce67f1fbffa1ccfa07c9c85c69452ce1b4232cca0e4cb0dcd83749741bd093f1f44329b694706cdcf2f495e90540e648c41cbfd830b327133d864c4a066d268db587947231706c5f32fe4e426491a2a3028e359b24b6ca64cfd17d4f892871f3d8a9962fabda0fcd8e45a26eef57bb80bbaebe7999d98e1a31ec8053d66df7c7e8ad40d646c414f96246b0f224cf2208603195a50cbde6ac235eceb77419091053d3c565bcc21e221648c08646041ad7dcbb6fbdc1632aea0e733cf71d2b96bdcc80232ac40365820a30a32a85076790852f3f2af2132a6a064f6b1779ef188bd611b366448414d16d161696abbdada838c28e816397fb039cf50d0c7a3cdb12e64b878a1c71314b120f1bae57a946952329ca08c578c7d67be61af347790d1045d2287d57469dcc40f13f4990cee3efc1fa58cb51d642c410f9fbc98e95fcb7e5782d2f16d7c2c27b1c693042d2ece4cee6affcd27cd410612f47c3dd39072ba1cb1c711f4ce1dbfc67bb3c64bd9186418a1aa34553799b5ad0523878c22a8239daf69fc0f83d8173288a0a4183eebfb604c624ad9a20b1943d0ec53907a9d8a1cdb628b13340e1418173284a047aab83d1ec882cdb1857f18fd5f94a098404610b4cca925f8a02d50b082df82d49101042dc5a4ecf0a127336b58c60f94142c484c97e2edf438e703fde3fa2f871c9a87d36e9106193da0b7c791c7977c5496b70c1ee8953fb3ad539ac7d1179ba3045b94a0462063076a88ab704f9a75af91ad41860e94bafe1cfa2c976872a0b9a75c9b3b0ff27f1cab41060e34b99c72b3c3e606bae75b5f875c39e3391b289f429c89c9c91964d44097eb9f4cd912ab2f84069a8cc5ce5e29ab87d9c723043266a064efe492d2a630fdba1764c840cd91597ebf13a4de63b81023169a8eb4f638fb76a61f7f030916ea76f8f1492ccd213edd20c62b341f6d381f7778060b3601440c5728f923e9a49d537ee9ce0d24301e4781d10abd2627edef1f76ddc55988c10ac5c73e797fe419b20fcb1b48888518abd0e386fe983a05cda926a38aecd3dd8ff24eb582fd2eb6f0623b154d72ad1c99321d03156a8eca9a9d7276f871f814faf99686c6310f175b984291cadaa9e3c464c9bf175c94427fbb2c7e2df679d41f14e4303a52682969fcea9c43f3f8e606120a72101c3146a18fae53ba3449728cce96238628f4d17c668f7a98b952418c5028c12d799c331f7decfc0da42d8c173140a126bb3ecfc17f36bf952888f109af3b42481ec411cbdd4002630b32307209313ca15f1e7645bf945d92080a7274421fa7ef38153ec58fb5c70d24244e383e4c791e429a60e50d24aa1dc4d8c4a3db8e8e3dc81a3df20652e2208626140d5f72492385cab88891093d5f87dddc162c888881092d227c7eef9014df3d333dc4b8843ed818a74795b323fe64871896507bb07938995e925d48da1c625442f781574e7937a6e41083125ae4d69690888dbff024d4b4d755912758c85993849af1f672e965339faae0102312daf8cc98bf56a4f8e371c4861890503a53ccff38f24072f0f1083d7dcb6da4ba378955a1218623f44148e6bce9bc8d916f84f6bd1922cc77880c3118a146c665b9a9aa388d8c21c622d48858d2bf297ec67314a14bd6545cbb591ed78950e7ab777a70f9528e3922f44f3a41c2fcb84478087ddcd2fc2054ec4148b521f4ccf5c33c9c94ff5cb2855092e651fc78d01e21d41fdd5d25999823675c00b8438c41e831d84d87b20fedc913843ec13c65931f4be8e71108357b9c2e5b687df2c10510fa2032fd583b6374d6ed0f4afaf2d1867699fa38f9419720163ecce4ffd3830021461f348d24e19f2fe68f762c366cbc22061f944c2962c69c9e1f46308b3660c3c66ae1812cb4c862021900430526f004fc33c09fd42862ec41cdf92a989f8de68b0d0262e841ff91e8461ebbfd8977f2a0d4f558b2c6d4ff16731a90401e62e041b18989e1fa7e44637907dd652422a7930f8b941df498196d3dcc672f218951075db287ec5cf5e0bda78392246e966bf9c66f660e4a8fa4c9dc30ef239313c490839e25697c8b9f86560a2a21461cd408d93e5f54580cf7992fc480833ec8ba11b90ff2e3d9bc41af4821e985186e505ea3269f66eb5097471b947cc97edcb961e13f6283a6171aa63375dbe708ae41b1c96333912e5d0e793528139a66cc47163bf8891e889106c57c94e35e54e87166120d4adc69984efa0ccac8871ff878b4298b853ca010c30c8a6518b758397f315b80c18559418c326871feee73c6fd43eec9a07ef6f2d26e8920361838bae82d7078aa20c618344b999268e4c4e570c5a025cdf12171241c2bd80287631831c2a09ea418bb0efb31138241afeb14e72e849e96ed9183185fd07d3c968999533c1fc4c70bfaa71f4cd2b91d11d9c0e0c2b7c0e1553688d105c54ffc83e464fef01f5cd0076192e323ed10337f0b7a8a61f2b82e0f2ce414d482f63d1e65964c31759ad40da42d70b899418c2ca89fbe72c32b8fa2472516d4c862397606bbcda3b77830707c11e30a5a75cedb79ae25a6fd1b488c8861053d52680b9e7978b14bca42030d381fc4a8822efaf9c3ebd3458f525888185450b274df72f6c3e49c008c0da308c7f1e2015e7051821c3b81a41c11883105ed2e844e15e23ab38739175b788103bf0b7fc0510c29e82159bad3f781f6b8fb28a8713925bb3cdc103a9831a0a079d7860b3dfe710b319ea0668fb9e9f0d9c16c27e89f2c24c40a3d9caeb016623441cf17f1b11452d688cf042dd287e42933d34fe74bd0c2c614721e9ee5f9854f097a4bff789ca7af2a840818b5458c24a851d741528574f0cb6e201d190ec44082baf7793cd25cb1528fa73421c61194f8b1414b2657878f11f44829f90f243b3b5efa0bbb2e6214412bcdc85bf1597aa01f2268a33942a5d0a1ac72d8ae1063087ad61e794ec9f4c52d148216bf4e5ac24b730e1f5688110425f5c68b88c803411bd91fcb213766e8f80fb46039879cbb53bbcb3b85183e5067b26465bdb85791471262f440cb973ce5571e44d95b4888c10335cdeba710cf711bd30da41c38b6281583183bd0bb5f2bc6255b1043077a083fdc9c3e649d9b25077a72af1c298feb2c4884035de4e3fc7b4f9009316e401ebd1f667b6a886103c5fe927e768e21d86c6aa0f7a7984173fe40cba228c4a0813eb6ede1e7f9a4ac31e8853a21c60cfc98abf3d74ec54ea91832d033885d5f0f6463ce4f2c3289d18f39176288888df820d6e461de44a143094acf6fddb994c4d810f1414712d43ecf1e5f5336312479d081043de68de0d7fa398ccb47e83882be397df820a7173b5ecc088a458e5f4cca7714414fa9b27ca0793642071134bff025ef31e9aa3d4350a3b2a64715513feebc10d4f0b379264f3779f54150347288e05afd62930782b61f435cb038ff401ff7d8c2ca3c23ea661fa8793a8f2f4592e881857ba08d75eccce9dbc47378a0fd30f6499787fdcfef0e74eb0dcdde89ae8eaf0e947eb964c1fe6737b83950734e8fbff284d2b1340e948b3dda0f7ac91b68f93f4946ca497994a30db45032957bdc23d7ecf1a881622f39a323a6d0404d4176425796b83c66a05ec5d61cb2259a721d32d047321e9b528f3ff5308b85fa831c7c94b23a471e5eb0d0079272de60b1cb5c7e855653f9c34b559ece07b9424d136cbae3e24fcbadd0a653f564e8eb414e2179031aac5072a76bf71c5a2f52bc0a4542e69453549eb9e56168a842d31bfdb1a649a6ad39a950638c8b8dff5115f6a3424fe1c52dc42c9ba6e25368412cd264ca79f0c937a65062c4cef84c86ceaf147ace7c6946b7463e8f24851e6452ba9c3c272fc651e8c1c6aa8366a2d02d4548f767a6173442a147fe7ebb0d69eef70685a61df9a7bef2678ce727f451acfc9959dd9262d2135accca9a655c36368c9d503b5865ecbd14762fe48492f3677c05d9cf395f36a1ce7796c8839469d26c9a5067f3280449666542998d3cf2617bae882126d43d6d2bf3c825d43d2ff91e77b21e6c8e25b41462777856de85985309ed7c9c2f459f58b6f729a17bddf78b973909ed7edc3655ade732be24f41c32cfe5e1c76dfb3d127a4857eac1d499865c4342c941cb53f88eef5cf523d4c9e3c8b4f19dcf3eec087d30967db451164be2dc087d3cb16df27f646d7f3262f790675c8412df72654c7938197214a1a68f3ff67185a9dc934722f4f281841e8f22ef048f2142bded9d0d1f94790f3f84b6417ae487b529fd86d0bf22cf849fb56f4c1542cde371feacec8d105a56fcfb20fc20fb4fa4310835238c68a8bf88b31eb73404a1947867580e793016fa4068f12abaf238afee930610fac8bf2245087277dde30f6a48fcf18b69f6383f289ebcf378547152c4f8f4411fbf5c8f355c7894e6f9a00ff4b285dbddff38cb7b50624fb2bdafb01e74bdcf17e6e3acf51e9307a5d355bf9b84aced241e949ddfbcb114bc83e23986e4588da70f1f76504b82eb54747d45675ea05107a5cbefc343ae3c7978d241bdf0c97db79dc1626e0eda56ceb0e972725072c44bffbeb6051f8f38e89647912522561cc90b1c344b294edece11b6c27603c90b2e368ccff106ad7d142e4836d31cba71839e5dc2a78c3ccc3156d1688396657b7b9c7abc210368b041b9eaf3af921412faaf410be1278fc23b63fc570d9a7ee4a41424e41e6498067d906773f861a4d809153428d9e3eff8c3fe4862db16e60334cea0ff387bf6718ff7324e63067dd09d47b2e13a65fa6419b4102f5b07689041ab081b394bae9f5d8f41e998232fc93b56884131a82952578717adf7ec230cea8f477fe5fdad61d942030c6a1e94bddf07ebf1588ec114d0f882f26e17f942c30bda55cc63f7ca1267aba304834617cc060b687081c616680434b4604cb9fd64378cc7d1b2a0c854fe4f112f0f73e419021a58c8f38e76ce61bc37872aa071851c34ac4075461e56d04896c7d9e38a182dff9124ad5812814615b4143e7cc4f6e834a8a0b6c590e2c38237d003848240630afaa54f1e3e8e1c29a829f78ff9402fb2e3864614b4f68164939648d6e36940410de2b13ed4f4349ea0c4866496439c9d6090a8f07f212b4dd03b488e886091bff24483097a8408f351ee85584e4281c612146dcd696a425dc7b02b41fb8e8afb4afa3dae32094abb8560c12705096abf679cf813f963b626d038823ec8229fcf46ec538fa3610435fbff848be70f5f3a1a45502724ab18f7fac75dbc8144a4010f030d22a0f72e614a27b68130b60b06d8b0e1c58711c6767168083486a0dfc720f775529e3b47087a08323e921f5cce6f27086a1e56c8659a9ff9f40341b15026eff3399befff40ddacdbe3b88e210fdbf7811a2e5c30f972dbcfbe076a8c6d1fb521cb62f23cd0b3041f94ccef7cce7b07fa786c417253dee41fa675a06d581a1fb4c439d0c5b6c763dbfc81069371a027f9d0f457c97e38e11b68123a3b7feed1c4f9ac0dd43c1fa2fcac7674363550ebe3a7fc935431e40c0d1ae831dfbfc514797b7f181a33d0c71a379b7772ec9669c84099f8123b316759b5b1d0a52e2ab4690c9a5312166afcd1c62dd1f2159a0fbfece2886fcc55ba420dd171ee2d851c41be56687e9af24d96c70a7d18ee9764e2ed3d77ab50c2f74f1e8f69cfc31faad0ec2634c5df8f47e28f54e8831edfeae003156a78079dd049ec73e8710a4d346c7c1c63f3a5ac29b4f8b8eeb0b53dec61a550772ca79eb694f7831452a8394bfcf0f73a93fca35063d8cdf9e0272bc2a2d07cac3dcaa88a8542bdb6fd4e778342edca1bfe9a7d90c72794caf5294cf9284f28e1c783cb54d5093d9c6b5bb6af0ff21327940ecd1b42f77a1cf326b42c1673861fc44a59d484561f3a68d09463168b6442cb573932228f88850826f4f0af49766b7b649bbe841a2178984b116162c91996507e5851de3111539e9b51093d7c58e52dfd565dc12dbe01366c80e1050e14740b680625f461b57fdcacff1bc9d662c624f4543a3f9ad47b9f932d09ade3e476b47eae4cd78c48a83d179f6a4ae2f95b3320714c7dfecb1f4c98f108fd2b468c58b74198e108f53426ef903ec5c8cb69841e151da3d3788cd0b38fc731f3c9e4ec135a84b6295992baca8e1b2286021fd80206331451e9ccc7dc1a555a1f185ce4d000116624420b9537e5b318fd4bef0c44a89f95e72fc6f338628f1c6ac3c6e67830661c42d3b9c9839a14bc62792cd81c86d052bce651accf2198c7881e740b985108cd3462ceb3c50fff529e8b1c1a280698410835dd85c9fe9f3c48b6c01146d1c1812387050a023306a1cd79c59eba9472de6ec3068e4341681aba5c3ad55624696f2085f12548090442fbdb79b7105923a51b47185e7051cc01424fbbf3972dcb0f32947fd03bff76235f78c9399360861f148db1bff0611ee5cae3dc40eaa28bdda2b84001171208830b1470d1c51637c2f8e2bd0533faa05588848e7049328f3e1f98c1072d548cbd0af7bdfe617b507b7b906a66a2c70c3da827f93d759765936d81197950427eeed9d1ac88183c28ada1ca2efbc71ffe30e782cd91631f77306b620f4f2383e7109a26ccb043e39fe72c244deaad0ea4d208937d1a3e4cb981c40f155c8e30beb018cca043b160c61c66c841b3cc61c3849194385c413c72da9a080e5908f1924edd48b66e207961c61b34dfca830b3d177bcf9a0a640f66b841c955f107d21b2c82f7b061c3860d30cc8c36a849646308c9df16e0608381196c503f4cc6ff287526332f30630d7a1093891fc61cb3c4980acc50832e3d3ff00e1f864b571e1498910645cc7c2cef038bcd111b11cc408352d2de3f65b93df782f1398a07669c4193ca489bea2ebe2497bc70c10216801b9861063d668cd3ce2ce9eafd32281e3a8f36b28f3fe5126790410d15a2c725620ae1f531e8a1a46cce5e9386266b0833c4a0f67027e76185454987c3a0668e1b3ede9aeef4a7d90c3068133d1d34cff5052dd2e4c6672a33c9bd17b409a9b3e7f3c02bff594098d105a526496fd2f8f1f82dcd05a54333e441ed54f984cd7e30630b7a5c0f626eceae4c3b5be0055ca0808b30bea8c0091a47174c9698a105b53527ab728678679b35ccc802d972d00fd25609c30c2ce81d4473e397fb8fbeba81b45bb8175c1cba11860ab2d0220b0da000470e0670c100e3891957d0b2cb266493a415740bf29f429c3c8cffe08c2a6895233bdbc557c00c2a2892c2f8302e7d06ffce14b4bc11f76372e1979782e2e9f257fa9f543747419fea41caf78310312d14f41e4dc5ff782cf1f9c713742f1f6c6be514622b77821e7e8365b8bbb77a4d13d4bd1ce4b276eef130974cd02a9c4b0fdf479143794b5034d9c57c9553f0cb4a095ab8bb8ed93fdcad1c3223094a903421ff0f740b2041ad1f669bd89f7f1d1f4750f6af36e369ce9fc3463090851659900b6461010964d1c5172a08638ba31946d0d2f496079374e139338aa066f908318dfc7022fcb8810406d5cf2082be913dfc58eedc47dd168171841482194350c256cba7935e086aa874a2ad99313bdd4150f7ddfcf32885e6d165670041bdb8943a6b82c54fa92c3420013cccf881da9db12ae96dbc0f24777a98e1037532cecd6cd870dfe3f440bf4b6375793dfa8db7113378f03066c654165ad8b06183123376a04bc576798f21ea3be60652a10a14abf3c30c1d6816225c8790c53687a01866e4401f45789bfc088b93076f415f988103cdb5355e7e66b4c52406aa30e3067a4839b69c04ebf15967860d94f7b3b8f9bf23879a8530a306ba8fad2d720ed38fe9b22bcca081667fdb216149aa5d9c81ded9272a8f44348504fdc51e8f07954c8f8396266cd267180d6138689f2ee50edf7983d64132b47c4ee3d97183363ef6f0ebb4410bf615f240538ffe6cd02aee578cfbf14c7a0d4a87e9f8a4cfbe1b35a8e183f91813c44afa34e88310e2c1248f063d0f2c57c798dd24ed67d0c347ce18f37033a83189a4905e736ce565d0c7930736b1fc3fe664d0cf87e361bc3ec4ec3168d7ee1ffc36652a5b0ccaa6f8f979d82771ea30e8c34e2739ec62cc518341afbad0a29f2f28a9e327f91c61fff5825a39464b8fc7ee61b80bfac0663c521ebec691b9a0bc0fd2e414e32d687ad31746c4bcc7d182e61572bffb2ffcdf2c28496c82051d0bda877896452e84d0afa00ff22083e6fa41dcdc5a411f4eb8d118d3b2b9ad825ac92e7a73b48f65a9a0e6d59f5b5b874f3b052d65074de537777923057d6f27cb879b2868f9d3e393e2f6e50c14943c100d975d63b8974fd0ecfcf370235c644a2768313e5c9c1c9ba04ed60c99feefd00399a0f97c6692509917e112b4b03dcefa39f48fea53827ad9f143f8478c994b827edeed3dbe499fbb232428527926ef23c2558e8ea0e96f920abe11f4f6698b1c36edc41f45d0b43b4c8eb97f1c2f11f4f1e9f6b8f5669543d03305137febf99c870941cb383521ec76849c20e879976e3af6f0521208fa7feef43086f012d60ff45c62fec17ef2667da0ee6bfce9e91cbfec81ba13e37dccb8550f1e28337d6d61210fc2b2033552cef7a135ae13d2819a3fae981ce249fa73a0c48a7161ffd6318d03a524db9bc6bddb84d00df48dfe916f898f3236503f7808b1af935ca7067af4e8addc23001a6897c1b2bc3dde538e0066a0e55d56cc1c6afb3a0290811af9f312fbcd25feb1d0428555a4c9c342ebfbbe37fdeb41fd0ae5ce2f73489687dcaed0340599df906132d8ad506254f08fef7421a459a14588655c79ccd8ab50daeb47591df3f7605528fdf5b9ff72da64722af44c792fc264bdf0312af48b207bd1231f5bc4a7d0737e8b8b9b2e466f0a45825e2c3b3fdf7429f4ef54973c8796c8a4d03da6fc1d7fb3a4dd5128dfa1b36dff6ec715851e44bb6d6724846a43a1e4758f485e9eec8342f1fafa3cd69dbafa139af60f376c84ad0c1b4f682f9963054956c9359d505cac62528613ba6fb5fe68737f546e4213ed10df2e777234a1c978698c1e990935878f6d5e89097ddc92326946dccdb9841e6d7316c763fb872514cf92c8cca3dd1855426ff7f16e4c3d1c0d414a2865e1f3f52287ac27a1a6fc51d262d3e39d24b4b43399b143ebdd9150b43b426e0a3e92cb03127a4a5921e225cdcd3e4289cfe9bd10f383ce116a8cc4748eec9e49698476db316bd68f9b61462867b1f2280f62ef666d115adea7720b15a9a1082d25cf15661efb1b223512a10ffb5332ed41b088215203114a8a31ef66cfb83789d43884565e1253feddea9b901a8650dc24c404b9389621350aa1c49c2e624576d38f2ca00621941eb3ca983af428e6773ea83108753ff368eede33f4481ed41084ee417762cab0feb8788d4068e59f07d93d427ba4bb0620f44961daf3c73c93d35de30fea757cd38d19362c796af8410b3ffe51a65cf129ce55f4801a7d201b7c201b5c630f9a688f539cf0d6016ae8418deca2e1471626b47979d06724876c9f25474e1d3c68a5e3419285f00eda8f83e46b986f073dc6a818cffcab83d2b9c7ae6f3958e573e9a0e761da9c3cd0cb93833c0725ee7e433cf1102e64e5a00ffa2ad84cfe1e680a89833e0edd1293bd2a5e4a38e896d971e276f60d7c0a91b879143b37a8fb771bdadb629f65dba0e4817b5f0a1179b2756cd06d828b66be9462fa6c0dba7ce5734d3e976358d4a00f46e2a68f982434b469d0a64ae6fada2eb667685023d86d48b23f2ad9cc1994983f089e3d4e55d59919b49f8d97245d65d035b8c5e95455313b4506358d6bd6a0ed1ae7426350732e75c60ab631f96250bbf7c7df35e6227d1894702dfaf17b8041edb4298f0766172973e70b7a86f251ae14f6827a19937774ab657359a30bfa678ab1fee26be4be04391e05846a70a1d860418d2dd4d0829622bae5f6d32ba89185836d929cf9971a58507fe38fa432c3c6cd588d2b94ade2c5fd286554c30a6af24ae6913ca7c6f7aa829eb1ec743ee49436d4a082fac142ae7dd44e41d789ada193e41197181b6a48411fe6ad60298ff228e8f3567d9b5384e6a4a1a0d5e87608e2d5a9f1046d42a69dacd72d3b91d250c3096a654f7e0f69ef083741c9b947974cf43a3598a0e72c3235e93fb987ac086a2c4109315e76378b8d9c3e3a25a86d9fa56a53d23cf6ab461294205f298f3c66774d3e12f49057af799c5bf4ba53e308baa4eb76bf92893fa88b09358cf04024f347cb5c320c358aa056bdf9e8e3445eea89a07ffe51fc0f3608861a43d062fc9007617bd0697e084111eb88f9529093209920a85db5f177dd7b91d91b48c503358050357e709cf02c79e4ffa30b357ca0a698644e6a3b43ce833a50a3074a6565c91fa590c7146af040b94a176fad7b929354a45063079a7b995c4b8512f9c11aa8a10325cec5d815d344f0705e161a68c0e1a891037d3c081f54a4e483eafe70a0c41f75e5c6902bf67853b250e3067ab8698685c862a1860d949bfe90392ca5147ad740ff9020fa319b32884b033564ce6977dccb9ac72ad4988162a13b744e22d3126ac840fbcf69b2ddb4a62c9928a123165a8c31bb7e9cc20fefbf1bf8385868a9fe7f18f1a973f29cefe25161e4c001465140c72bb48850b9e51564a6ee1b44872b944ce2a3904796b743472bb4ca21e798e70d2b94b6ef743dc8b955e821e665b1921ea80a5d3b6e67d32f3b52a15caec9eeb4e1273ba50315ea5c548ab8890f3eba3b4ea1849f1a0f731e4ee3ee308596f1bb7cbc314a2e871da550378fca475ff19b531edc410a65c2cccf235ce8b72c023a46a1e46b884a7972041fde1da2d034c4e73493efc7e1a33b42a1560c3ee73f39bce5680f50e83122cc649a88933fbf81543a3ea184f798f5badb462b97c320a1c3137aeaf8aa1052859f5e8ad0d1096dc25745df5cf851ee0618db051885ca103a38a1e987b81143720a4123613c1889838e4d283fd210ed79e29a382a86983b2246ac0c414a43ee8efec831b657f4c8843ef2d603f1b17444496e209da07174b185d30970744115001e7460424d33d172c925a472cb2574d730e1c3c95a4249e1b5fd83ae646eefa312da448a94428610c3f5a81b4894507296db0e6fd390a3a241c724943c1e8d6e84e01295bc1b4846061d9250277a946383ece5e1f73790b840f2e201140935a710392f611286175ca0208c25a5e880841e3d90785a9b3e69d2141d8fd027566756cca9bc1cbc81f439fa881eafe87084523f9a9db210b37af43542bdcf336797794ee67a420723f4303116957ff499ecb308bd47bfe42eccf648378a502cf445b6f0e341989c89d08761cab4ce7f3479e022826c9c8e43a8b1fbe3acaf89d03f1e86d0f3e59aebdca09d462a841ac1bbcc3b85a78d140f741042b1edc9d569b4c37c5b818e41e816f3575bda14c7444341683d3edade93ea2a107a488cef9d7212b9b2041d80d03ca7d91e6727c969071d7fd03f5f849c932a931f7803290b0d340003366cd8681b362a003de8f0837a392f4fe581f87c3954f04575d1d107250789d5d9228d75276f203d5cd0021c26e8e08352d9d19727681eb78961e8d883e6f9e3389907c1d283ba673eae37b31b7288f2a0c46e4c16828f6adceac083a217cf7bf85d27f9c37407a524fdf5380fe747113aeca0661eecc4d24c21631e4643e8a8839241db36327faa343dc0202174d0411f750af379bce962a86c0a1d735022c62c6bb00db6956a42871c94df0babe8291909ed16641d7150efc79d3af338747ae88083fee3d16bbc0c3a75953d41e39040c71bd4bd3c301fe5fff1e83fbe821cdfe106b56d83985e8c5073d1179ba3036dd0c642c5ceb27924133ad8a07de7e032e5af41f341e4eee4717752de2ca1430dda56181fbe8ff328bada34687a1a43c7e6cfc40f4403d91842c719c8c6093acca048e75108d96d5b337920123acaa0bc65281bcd2519f41d0f73e521b6624e080942c718941ff4b0b7e3c73ea14531e83926eb8e9d0cbe57150e3ac2a0dd8f4230b99af848b5163ac0a0e510248f877997efbc8342c717d4901ce2e39778bfc19a4087179492ce4817e3d658cb8f1f7474c1387a75ee317b7041f9cda9071f4b3cdc47b720bb630bbae7f614ae37954f8f5b418716f48a97eea73c7bbc704b181d5950539ee95d6c6c4faa727460410d2dd92c2a3f75f8e145c71594cebcb3d4f997a9a20d038c07163aaca04b8e9c9f77d930c0285968a00175858e2a28592643cc4e5b9f2a2b745041ddbc793febe6ce2796dd764c419bcb59b4ecb3698ec81cd021858e28a8613cfb279388f520ec400714c846c7133493a8fee8881eb6885de87002d9e86882b677d27ef9310f275ee06082d6e3f9810f2797976de8061251161a6800185fe0c8b1001b36c0a042c712f471458a6705e0815eadf9d2a60abd21260bb0037d38fba34d5eea401f5bc873a0d4778554de89bce3401fa41fcbe4fecd0ddf40ffce3fccd97879cfb381de916b7cb8d5401fd60fda47fd8306cabceb77a4b80033d025579fc885f68fb202c840cb7339042f4d1d278b859a43eb66333cef64b0502657766984fab1eb15faa6f71f07b7d215fa55c591f0996b5fca56a8133347ec902db927c90a4d52de4f15925c85723d1e75986acff1915485563166b2ac7b36fb49853eacc949521e9475f6a042d3a0b12363731eff29f4f0631f8f071ae452cc9b42f9711ebf50a19278bc145a6bc6acd7f323b39c144af8493e7c4f8f42998e217bfc711e4ba745a1e699f80c9d50a897623ebaa343ac41a1e509ee1a1a5fb2fb09f5073db6799447d9233da1a4b808a17b987edca3138a75eccbd8294b6ccd09358ed66484e730576f423df3f145d649974ad6841a62edf7b034fd28cf849eb47b2439c4841e3bf7488b463e6f2fd1556eb7981f6b0965f27878bb31fc307c6c2594f6c15fae987decbba1841e3d1b730f3393d0cf83f7fd8b65cc2909cd437c7fa226680a4642cd95bd7d344148a8c132b633f5bffc8f5073bf684890b017738ed0aefb2f4365c6fb1ba1767f94a6deff81cb08a5a2077539f558843e1eef0f2e841e8a50734d5d8c6521f73025116ae8ced88f82082505eff1864eb6fd39841adec93dcc86d0071a3fd23c8e71268f4268e9752348c808a17b0e1f3be583d0c76e1d3371b36dba04a1eda4f423d71f6da52b10ca65b9f648e44f520a106a9e0b1d7a78f5da11fe41bfcf7918c922f483e6637bfbff0ca779827dd034f5c596583d1e4b0e1f9498dfc79de23d28992cd2d9868d95eb41a9f1f3095e5561e741e998df94af197a1c1ef44f113aec7f3ce6e3efa069ea7108e94b963e7650f238e5d01676f97a1d120db7d341ef589eefc939e895da420ff3c5203d5c0efa650de11a5fbf07791c34dfe42da791b747371cb41c7e38392cf4e6d46f507325b3d461768362d29b4376aef196dbd0691ef460831ae1c24854464c7ed7a0568a98796e9f76b36a50df3737e46d678e360d5a7db09c7e3468504ac3650ee7dd2d9933281be1d6e35196f64e9a41ef7bb9f249731b9365d0bfcf871dcc0717be2483de3e12bb107423b36350b3e661a61fc5a4a34131e89962c494938f4c331806c52f5e4e2ec5cde3100c5abbdf8f73d426fd815fd0ec731ecf9985dbf6bca047740c693ae7ebeebaa07eae18333f0a49b4e382e6d3f723d93cb6a05e8c8d716942b9f9d0825ad2d9c7199b77793cb2a0bdd578a7ce0a3e4ec182161612c647ef15f4091b63f23c12db70b182924779e49a7bafb1875541afcaa92ffbe471fa1415b410e6c45baf296891b4ee473e8c8e2149414bd2315645c7b11e745150f38f25e6660c4f1a1d14942eb3dc13d48e375e5631864f91738252fde391be8ec9e5719aa0cfd486fb1c3a85fa99a04d55d878f32f41b1d8f6df1e75871eaf045d7334fc38c79caf7b1294ced2ff23b13c78db91a0ef848eba0fdb95f123a8793c4a21fff8248f6904ad53ec91857b9d5ce92268622edd2da137c79a085ae6d81edc59a7be7a087af9cde5c1a6ec2fb510b44bff9b6ac6dda50e821eb93b7c14b963923410a8cd171f2549ff400971e3e77777cfb90fb4f3815d1c1ff4c8b23dd042857ce2db1dda8379a05430dbc91a9a67e31de8fb12b73734a225ac033dbcb7c78a21e26673a066687ea70c0ed40aeea3fbfdf23ef6064aea1eebf48b5cf5581be8e394ecc7926d0df43457e692079a629a06ea87fd96cde447ceccc0daba3fc93902c8409f90ca58681de3deee7f6f7610165a8c65ea7821e8bdf80a2dd8c49be8923c7ad1157adc8933127998b7b956e8c3f26e0df97ff8dbb14277cf63fbd5ad420d9b2c8fe57f10c77da8428d290fcb42fb4c071fa9d03a3294f4383c6e7ba0429f5c5afbd3e314caa5cae8711e052d8f29f461f87d5bae8dc12c859ac7b653490ea963a45047a793e77ddfb946a1bd8f355bf6bc175211855ee6dec3cfad1ec7a1d07262d3a76059e3c340a1fd6e8a083fd926f909250f42e51e87e9d0a3ca13ca7bb5e4f1707a74420d27e1666e7a7042cb831c12733f4867d363139a5645984d76212cf4d084ba176f3ed39b77963c32a1c76dfe9764917b431e98d053cc30734f33e1248f4b28d6e25765d695fbb184b6fd3d901f7e2aa17926ed9ff194f3e35042cf9f760de1b12fe54c42b76d696d1309e9774968b33b79ac1b325f8c47429b91cae595afa77448289e53f6fed11fa175c6ffff95e7f4704768fe49520e1f6493c51ba15ede9c2d5132537146e852e383998bdde3b917a1dce5f154da72ef582b42719f6c31060bfa552742c9d5bd9d268d0835c585b07910f5ed398476729633eef948b286d07d7bd431eafb5ce442e8231fa52c2182f4fe845037c47e3439febd66109a5ebe2c713fe57e46104a99c4d31429a53a104a7e2a0f7173aef700a18c5624f794fc83f6b7d1a1537e50e36b53ca1b39cb04fba085a4df31c49af41d1f94f91019ff911b3d6e0f4ab8c983a45b39ebd7833ecaab6dc9e6413dcb56293378d07ee096f95c27dcbc83229bc71ede83af54da414d7f93b2a41e26b1eaa0071fd4e7d1d20bd5830e6a98c56e0e3de6a0c9e41472940f27c772509264b1dd588983de967b64c70207edb2ff62e2c79a83f6067d5cb941491f4683c4aab441d11caa62b8ebe43d296cd0c74c26244eb77452d6a0fcb8c332568a3f0a93a206dd45f340be6a9306bd2eefe798b3588f23050d6a4e2f5596edc77f9f33689e2bf7f2cbe5781f3328b93df56e84f8703a65d037267fc5d6c80f3f19b41f8714f3380f22bce6c7a08cf5d9b95df778941783f2959f4268cb113e1e06b52b861e8ff72588e660d0535b7cd9f7a8d2e55fd0a4c716639d5267b6bda06d9a8fa92cdd056db6f2f82da610233317f4c15efa1ea54e212d6f41cfd394f3a75f538eb5a07cae9c92257df9146741cb3dbce4e33c2ab38bb1a07fda917fcf15b4acfd9942fdf0a25f2be8ff2d29fc707f5cb355507a782e97b4226ecc52410dad31d975f2cfd34e41eff1a077279f4e8c8d14341f698a2f2974e81f260a7a87b1ed1ff5a02333507878aef9e4c7c927a81d37530ca907799c4e27a81fe65ede1dbacc6c825e21a7c903dfdd503341771f8fce47215c82a6717e1162c8332154821a9e62056bcb95259804bf3e77def80f097a654af5e3903a4fbf23a8c993d526edfbcdcf087a947744de5c11f4d4e3cddc3ed2902a47046d5cb28ff27cdfa76e08cac6d99cbb6cef1e216892bb7922b3976382a0c7aee49fd9966102410f293784faf14efc1e3fd0b524f73b4ecfa63c7ca0551e4e76ff288fb2f4e881f6c39c7fa4f340ab7495a2f220fec43b50b34d12911fe4895307fa8fbf07b5971ca81b34f2605270a07ee6c848ce3e2ae9068a6b8c7d3e48b101d840b71993b01cd3cc311b400d74d33cb6e0791a28b1b27eb8a30d60065acbc7d8f1791c266403908122631accb7bd53bc62a1a6fcb10ffa8265b00b165fbab35ea1be9c6e964abbd5952b9419bd303afea53faa158acee468ddb8f399154ae4417c1e8f3dda33abd0a72fe55715fa28dc2c9467f1414c2ab4cf1b72eaf1599012154af6f13868b6303e1e4fa164f0bf904b830f3685961347c73e4f70af145adacee3ce791029b44b9dac4ba351281f7763ceb9a7f3118516398b97dded9c855828dcdc19bd141f5028fa1fd27e8ff309a57a7072697bfa53c7135a9ec7d0bb2179889c4e681142c831316977fb9cd05b5247ba1fe6618cf94da89debd7843eeaca4172ec8e097d26f4cb66e1ca2bb9e71c137aaca8931ec6f9b0fc125acca37958137a5c99b684da1a76317f7c7e6057421f44c6fbbd85f0e39912da87e0f6a36c3fa89627a1fbf5a78bfdb399074b42710ddbbc1e1c097d1863c71fb75fc5144342d31c79ac377bd6107e841e3f7ca59c7b58d3631da1d8858ff81f5aa6cf46686e1fae337de5dbc9083db65d59ca7a26722e42fb0e7fb1b267d31c54843e4839d5a63111ba8f25237ef23ccaea10a186093216ee738cf271082579646ccce6fe9e21b4ea10bc83fdf0258f520865ff7c626dbe4f0e21b43dc91fdea7b6c80f42ddfc6521434c107ad21c3fcc960f84a2b9a5ba4273e8b18050f347b1872f9d64b63f28f251794ee2a498941f94081f0f47d2fccba60f8abfeb45ee880ffa75fc38b784f6a089f530e4d4e7aeb71e94bce8c9a942fa619907b562a6709bc3f606f1a0b659f076ef0e4a4c9cdc8b60d2e36107bd7fe43945dc6099d5410da9c28f34c41024468a0e5a327fbf0edb992c5273309d7cfe4b9192832e078cc3a8b46e65e2915020100684c150180804b8dc2e00a31408001030228fc482d1444e5469071400044528223e2e2c14201e161014140a160e044281303818060282a13018200c070382c0359ce67e49a47b5c54f1dd07e8aa76b4850e1d3b6145facf2950e060aa2d9544829c2cd02945ca743ad2a082db9d9f0fcbc84f361047fce44b6847e42966649281cadde704a7bd3597c48b64bc6667f54cff046dfbefdbc53d3ea10d7d7270ddb33143ccc8aa05b24366a686d5c4df934b8e3a151856832aec2e4f75cd676673442b41db20bb6d8de94965f867e9a998450245facaeabdb3453ebab314d70e9e912141de5c22a44385150b0a8cd699457d90ba69b69fe9f64ceb84751d5c3b9554aa0369f4aeb0904b9cc10a7a72de4aa8362a845d9d99f0b650606736b5ef34d7e670a2a773e3b8480146e62ebe04f6d1e141499bc06bf137bf4ee75de6397f0b829c679fa833dd81e5f37b32a7b995cbcfd099cb3e642ec484bbdf8bbb0bb30fef532cbd2bdfe70bd43e6ea002cdec0bd886528d3e1e379986db9e9a4cda2539fd685721927be9ec061dee3a3737cb5cbeaecb4f7daaeed0e83d9fd99865dbb156ba6ee266d399c4ea63b88243c29c920cab7e7a88774d9c2a4d19251d9a7d6f8abf22d6d3d3878a9eff84a7f94e97f8fb7851e09dcd1b1dfdce66c91c71d08dc26c58816e84959339a4df76331ba6ccd638096847d14fb0ee0d66eaa200f549916475796bb517b058e5577fdf8b73cbf922a39f23a977ca1738f169dfcd85dc303541eba7cc5c8d84802434643ce57c9ab20e1d2ad761d71acb67f6e91f3a2d52cc22d9371f47c5881807fb609aa5afd47911d348c699d4258b381584bda66572a95c6efe4d9916715ca2ecbc9b99f2e30602f5897f25e9fbf8d5238a1c4da89bbcfdba9ac762c449de1572cb999fd2fd5d728a53bd998bc46b3d5e40899ab8bb736ee2ac3736dc0efcf8943dc891835cff8e4eec3617c67d1c2412a7d9cbaec45444ac59a070c18cfb9d12c326f4cf40dbbb3da17e8206db8ae9ff6dce6152d4c1954ccefc4c7ad8b5415146aa172387541cc00d263a19b1428fa2750c622adcab13f41d1a84a72226353c1598a9f477a41cf5dc3433c38bcff24d2e058fabbb8eedd1e5d83a0bf3fb3d7bc8838b8cdf1a3954e2d156f97e3dec6dedc31a5b1fa92285ad785b2eb2996135ed6befe8f77da953962688e38e5d26cf329edc79946f75f717beab339d2eda0efc6e5d66bdef959cd7cdaf7d566790462fbad08eec5de56aec4f4966c35ba092dfbfa1aceecc8464e5fe6c8dce29322d40e564e43d627c1fff1145dd6ef71845ff906655d08b384670833a74bcb05703af1e0429503530a2fdb96fd4f70333234f123baf1a1d85e8382f6191f791d7ac7bab67f4bea168e0797d1bcd9a9b9ce6f4ff3e1af449a290cecaa7a8c3da2ea5ada4c5d92fa31fa5e48f423192aad3b8e155be51d8073ecd6cf14f779ab3a2d10b16d07bf6abbfe8fd9cc6bce8a45640fc21117dcb9539509c6a5b83499a981a1f610c2ba9374b1cc62b22b39a3aa9d891021c1a27354a33f798c12d56061649f35bba364b5021b577e71273413b5ecade65ce60aef8939dd3a261b576aa909b397cd46c9551e03ba72ebaf21398383cb46bb4d14e6a6c2463d394361bc17c364d38758529d7a99b3c9cd6d49f72ec44465ff9e83a1ec18ea3a64e1893380008c5a3a212aff9f15a39ba733aca162a0d32cb338af3008d3d3a1c56e38acb7d31d8554def87cc6f26d33c8cff47093a9317bc20438f03fd5f84045efe04649607b7dad305b44c38cbfb7997e4b21aefa6adbe5a76b974fe343ba10ac1701062d30f3c3857e3d661adb005d889277fee2ef260709e40ee55c2ec4c8399b4ef684eb7c81238d734ce51e2197f3073c1c44051f863268c4b2cc2cfe4ba6df2c02437ce97f00698f5c167f5ced4af050e8149edf6f3336df323ac1849846a736e61863b3436b5e0a9d49e52bf39b7f2bf7e1712e6dc9292b12ce4c00534b210582e3d58b56484282c2ef8ec4a6cc2f6cecdcd9f51cf52042748721c63c5d23d394f70e5c5a0366fa9606a4069f944e8c4e5b3f8c64d68455331f91e4569c2f87f42827d5b076147aa3978b0fe60ea8c2e6330717e2196ee0491246188e7bff9f61f0ed1f8fb19557168fd7b9f988c2e4a8a7fd615247b4042320ac502726943ff15788751be2089104ecccfaf184fcbb6293da0f9022df1ac05caa105bd03c8e690eed2fa43c087d4b37dd5741b0192e7a2e985413aeb01b84e05ab36cf4aaaca8a973bcc2d0104c5ec87e2148eb1a6a7a6dbb6b1272fb3b9d526743cf9abdbc8fc528d9b5bfc654381058a864407973ab031eedfb72b0665c46809de4b30a725b35aa65ad37b6d6885a9fe01ce43434e10329a6a17f287b752c8e935b0a1f4a9edc336925885544d969075fecf36720af5c40b75951d49b5df0c012724d71aa54f9a423681f76729a091562aceb6850371e2b6e0b191529f27064ea0bef41c90785b22b582f4fdbfc88b2768999e70308ed929e11e49e6834485c7cf57ae924dd47367b9d17ad68c2726319902cfd0177d692c2af0992dfd702a4317ac295c728ece8627601ab52f0ab6709565b477d7e2b277f1ebc24450a164967ff24d60011bdbfe2dc65eae5d92526658adf08318cd0c1e7e82f28a0117e3ab7534940fd2139811212195e4f55952ffc36e96fc5f586a8b78a5e811be7777cb7d4879b5a0a21e29945fdec4481eecf1a7ec45c06efdf6403706fff8f8952763225dc552609889ac4f6e93b485589e8ca53fd35466d123577c19eafe4b4c9d73dc7474b46866191377e98ea3b932e10aa0b9a25fbb66572b2425a526ad8b01a962628d2534ee240cb3b99864ab9e1bad585a24ac55f536bf1ccd0ccd20b627709963acba796b4e2ba576033554cc018f8114659af930205db0959f06d9adb4c04a52d644533c38d97c93bd17451a1a1ca1b9c65f1fb6c6abd7b7400c0599c9aa207430dad3aa5804e8f9f127d5be40c7d1b15d22027641433ca8e708dc76819c611fc85acbac49210fc84bf0f553b879a0013ba4a2662f3192c756584a6d0bc45f1a03dfbadefcfeae31379d14f4bbf25ae3553a8192eb73b85266774699821a77e3cc1676d72c7ca1d8d4126752dff500631ad547a8ae0a9b519382aac1d61f74475b13d1b437a19752909d9c29780bb61f40124b0e1669ad282937818f6eeaeac1a147f9ddaaa5a00106e97f314346367e01c11d7b0224517e90843b69af7e7a83e04610cfdbd2e06678e40de60917f761552f11d3686481069b4a15aeb10723589ba448e9773f026b65af1fb77ef48383729d2563a0ccbdfc197c0ee454a3311cac8a41d2173101b79505169e995902dc244250ec56429ef79081527478317627268fcad1ee12476ded224cec369793f8b645c21a2cc0f892e4eb591d0b1e76b325b7e48b9b6689d3001a82572598f5015dd85a2cfd51e19b0dc584536300629ed4985424fb8ca9d0b70eaf810d9fc053d7f85c8cfc82f4778618516e85666b91b3597c29e49104ac5a5207cef523d22bfd6aced08a493c325711d89573e40c04da0a2eb155e6b5845aa4129e21f32cb540e1da87c2718613eb28c128575de6c6c7a881e22bc3637b7c907050d50af0ef5d3be2e19f4a57dc53661e95855301f8820a596f30a69f9228321324e8c2a360868822ec30d242440eab23af002035e779af8e7065e2c114e16abe04a83cd675d6f01c36e8a518241376be7f4ef80ca8698b107a3c36c3b4ee160141f3e323a771a51621c8e898d064dca05066ab7e0c959cc4cc8d292093d4f7433386897e12a3cebf97ee1a3ce06ab8972f59884a2c6e79620186850e181aa614afebdb686680797e0bdf55007a8cd5037d9a84a18984aa593a08d6ead11e3303061af95ce603d3e4411e309f50880633ff18cb2ac98ca141c72f2a73a0a366f63c873caa8c301b0a0e66f89667a71345ff23dda58acde8fdda2e6f0107e4727ca005241cb2637bbbae324edaa007e145d0924383a30b906c2a40de20807732fc286741ad68d158909ad2d66d3343dc448a7c2d08bed592f7d5594f2185179751687a1f830f0aa361e2b078b03e89992147865d27fe29b3df53a2981137b961bc00d45e16239736ac51b930c03fcbf5518067995353280fda3afaf3591002e47f9c8d1ad88a043ec20c2b74c6e70550bd01c0c4dbde7820f468be866236d65683420c668ba7e4aabbb22cadb8b39e63ded237b679d8fdfcde522eebc33d18b767295f04b7a9f7b87338affc2271d40394ef33327d0c314a86b034936cacd6f7857c24a62ee0443130fa4ac46ea7fa9305085507ac300e9602b29b3194dca64dfcb282b370686f9e84d94e3a1be8e0e0c428f5f83c1ded00801cb2f6d14431c78c688b5f1dd4099bde41456b34ba8774f84a4657240c9d17d3987612c235396aeda2bbb8af9fe40469b714770c9dd4a76c8809a84ef818b2100fa07a06e77dc5a2581ffcce650a16192aa44d5134b8368260a3d5aa1dac8c6e6ffa45996d72c6ebcf7bb7d205f93b547d30261232f75ee83269d8ee950b66cc41af95f614eeec1f26bb10ef12b04bb009ba8e4481a955b77b83441dea33e23cb8147f6f6fd12d2608a61cb40fd72109420c6df46a596a1c9d4c1160779054a1c96a51c7af1cb40eb4030a5248a256665673ee8ddbeeb080f309512225673a618d8d25ed6e35ee8c17355685402d15ffffb530ca476c244fd19d625803d9db0952bd36cdc438f4f9f74eff9c019065433dea639b002da58acde7a5d8fc07f7c34aabdeaeb3588ae809409de31ae9125c808e4660da224c8e0d858d05a72f4598874c84b7947ba89c20ef8fde9c0928a3c45519f3e04d98db320bf3beb229a7c9704f6e547a1ccff8ec409aa228ea73356dddcbb39bc9bb5649ab141a192a2c7ac84097e0e97e9f159d1c7d9fbaa56a4397437750959ad4337aca914151025022847a023a1abed4a312daa0d3e4a867a93beaa634e555463a00618b6914d2286659181f1163dc15b37722020e4acd5847d640d74f7fc48f1e2f9fd92d471e0002f3f9d7acf10110cb8375c7cecf23d295e11146a6d9fb4cb336cf34bb6d32c98ae513d0d15858e7fae19d2c8cec469a229127161215a644cd022e5d6d4bf06554e6bb78c76412011e11500e98600f2bb90da43502bc4179816ee0391009b0343042c198fb66cf52075716eec2258220a04b70b21811c94206e8c86fa05704d43fca4a85ad07d951d939c449a8421e622c31a5d83578434fd05eb9d738880bcab0e20d614d804c3e9e3fa56231d11371dc4f41aa3b7f36686cfa743713dc749efbdee6a4cdaff8666c740b305dd984a0cdac9945aa2c2b6660df88d7c29961ec41e3514d6e005d51cc1e51318b43af90b24b2c26637c8fb8f7ca23d118d01588708538ba684cc7e77b023077ae3c1b1375b2a360a9b3620c4f93a8145e2c8a1eebcd97fa8a012275f24d38422078bfcb04794654a1ad3c36ab73204177a73f9b5294b79a2a0ed442f5f2a64b22ca267e979644609a51e662fb834603ba05baf2eea1a49b181f06b63d049fb2dcce479122c2c0bbd66a376e2169b1169eff26c64b451b3c031134f96b66980be37c0da1724ab1261ddabb7cb4d4c9f181e7c346053f4d4aec1f9c792a3889967598c1b771381b22920cda1f4f8bcec439e7e0799e9898b7e51cd79d6e8cea5a303ade6c14cfdfb1715afd16681a2def2a5d31e22d761ff244a5d81415742677af783f8436f8955590a128ebdbdf07949b188c4b25a36030d31fc03323e828997274b8144f9b3acaed8b37174d7caad890087e0a6abcd8696ab0b68112272655559bbc69bd836300203ebc44d1d4ab10f16c4127bf1422a6ff84c77918c58471d8754935c407bd01abb6d1af57b7538aba46d0c6353ce3415c07bf6d049905c5de6be26cb7b681056521934a24e94225c5483e558294dd066d2d8a65d6768ff747dabdec6f95f4aa083d253c1bbc53bd9a5e1c4f86e705ef90cadb98675a01bb87dcf3cc73d3dbe425d36d73a6f66c828745efd1f9cc73fe7941bcce9637c15fc47354eb4df1c07b9efcf7d9471e7699c1493e8fc35ba0c64f8970ba87878a0858a4557b0b50eb2604aec050963cb4ab578c8c9437c1f3c71aeae0e5fd5408a70c1e0ac01b94cffb4be3ef449d83f79c8ab0c76e1e7348515c38590c112825f76764ae4a890f78fb062c4d521705f6fe72d61668265eb064ddb74592fd9ba2ce120ba6d7272e449a71cf0e165ebcc40541f85c47e1e6a405cdf1b95c572dfea0ead126a0cff9b0810eeffe9cd032e0fcbb87b5127600ca480eb834e40fb01f8ee1708edfb2a33518db637111e33b582b6a8b0114c500f4acea6bb334da8f7582639e945e1a50c6eadb6664712adade155c4feab69f64919622ba8c17216dc0132404f9b736beed8a637803849440d540bc66d211be82614431f21629212b70880c49c2ef96685209a1a925ea68b011d683c4516ee9046c3d4eb5b65e4f9b37021aabf95c2f695dc8b4ea9019d2238792c602f59a487e4613d73d7cbbef0d7f8d2982b14870dbf70a614a5038cb1a50d7baf5ecde8e480d299e6fe8542e8039430c5d6c5caff185d2f842af9e825a60a9af57696a20abd1544a30ddc23c1105f9ad5c25044b3fdd03ecbc9ff5bbb5c4bd7c19a9548cc923c51bb596d50f9e61e1b9987b11878ad6535abf9634325d5acec033b45b642c793f338cf0ccd1e15adc46c4333b55e1717fe50bb968a0b10e1a8a3002f1e458312624a71c9219f1c752defc60402028588cd260023d48fa7f530ce423422efd2834f3cb6804de8e3671cd4348af5c8b46ba6a082b0ba74d1247004c6d5db81068a4e039f288e3a0c1aa370f3dbec6b550d0e2057f8af0e546927bbe1617c6ba61057ef5405cc90dbf925ec31aaca7d2831aed7ff307b9762db5a7d069e8d169f5ba4dabadd021ad33b258648956dd5229a2aab0a73c336901066781888d26264938311290ba18de49810ad26d51e8105f5ca0e54710905291b1ed85dad6c023949efdffa3485b3dec034b974f663f34526398eb97abe045297a9150d172c4125410984e94cb289a26abce2ab1a72588d4c708d70901724f9edde02821a9e0089536304cc34a5d2575447129f689fc7372df751b7a3895840f27ffdadccd9cd4bfd3eb7e650c6d0eae287e1320cabfe0bb4364303cfafae27af953afb78b8731b99918dc793853350da770c2a7a5010a96949cfe88f485b3ccb3169871f46741992e9c0b0e9edad5af6a3121a1c8f9c44fdcccd9d77bbf734136a8a1dc4182d6520e0e0be46e5fbec72404c5a373f69dea950415b0c59d106e3d76d2bd441349c0fb12af4456e317df5003bcdbdf9cc7bdc55def59e41c3e60331482ef737bee46bdab8bde38651dc8b9b70a14c797c188c3a7d154828cae223f215723bd2234cb612afb5bd8c7bcf6e0d6100a5f6f4a5bec54c018c6bf4244dde57ed02c9150de8856f7ab8ed852357aa1013aaf362c9984817f9c06fd2193ca2e798012eb73b31160dcb26a94c0dea7446cd7da39849024d324b19458d49ca71c7b19431e2d5acadc8eed25bab38faecf356b43cd165f215c5c4c91c6a999213d15fbd8f49452eb275096eabc17470a991378165fc810c0bc230cec8b2f0d2aecd02da835b310763738ade3cf4b7bd701a2af1b62da28b570e110e683331d0f3d81e18c21a7fd6d7de1093ee4b3706172c5388e433330d8178f402e04395fe0cf0e53152c960bc7ed3e4fcf057738eba53403d86441055297b891e62d2ba57be174437411b6dcad79dd3734546a7e3f47a023253df46b49931778ddacc12c797304c4aee2e5909116d143551d59ce2e36d3592fe644c4aeeba4f80b0af45e545b8e13e7bc30e0bb5013c0422f44bc4501f3c8eef5f001f501ad6506b0f7b7784e8436fc77076164b4e7f441e547a5d9c202dd5ccfdd64ca3628e78842cc3d13d5cac27ccd974fbe8d48fef5edaa99dcbd001a741e583ae81339df2e5151e8f93412b13892a3d279911e526d87d071bc4538e34593d54dd099a7255c5c19b8a64b4269574c90a00082c24921c5fe4590a40bf0003686555dee4574461465a088696c4877a26fdb34a925f530b328f64aaa701809a61b3348416de04733629860352caa3d1007599d1889de0cdf06438420fc91e4984554b1564be001c7f1f230956ff6322c4f0174d48ef893d30c3fa42de391f66a72e2ed2427f2ed33dcf2983c11a8cfa039a908f95c9fddc4cfec08d1d910cd93db06b45396a3882c8ea0255466676648255be11ffe2122d9cb6920dd4e658fc9fe9bf07f7da23b61e892532efc7ed5e8760be0413bd03b2a9bafb1c81020ff8d439154c73fd50229b05584ccfa98c394e8383cf077819eece1bc0321403ae4977792be719a09d9a2a2249d35a406e854112df13804f93cb7b83508eb74c8c5497b897148d0bdbb1768b51cb09458a8f79c42d3222d3d35dcbef9965b98dd3505f5b8b060a2d255f2eed39c732ceafe26a516b85167b8176871a411c15ab086e6dd2c3ee27036080e410ebc2889ef60224f3fc95a32c2f760bd607a1559d9819130020209826b86bef9c1e25ffc8003bc2cea31e486fa1641c0ed41132611ec016743f83e718dcae4dc6bac33b81f7421b1af4eba52b469fde083003fbbcae3ef0893a3335ebe42663d7b1149727bb68db117c4b33eee376b7baab15e1bd46eb84cda0e6e6f56fbd5585420ca64b43f99444551105fe70e247ba1ab7e0bd8355588a6b2eb560749b5612e571619d335803bcfe68655ac47ddb8b814793bf0e96da53f9728a77da01b4d65712681467d32185f22966da90e39f7ef6a4774d692f8a02710dd70ee1b598e47bec09fc89cf0b06bece904f50d110c35c6fe6cdd7f4d945bba9b7e3a9c4271f52020c38c9af592d8728b394d9b84faaba36c4d9c1624b35eb8d788f56b1833d2399645fb72a9c7d6f05e75ff682920930c5661f2440fff5abab6a4f7c87873c069fdae269d476b57a102e9e24ac1218e4b36c6b52c73e92d631b0c9d81e1bb4f779b1a53e3ed913a77cf62385668a244208c88f6e6777bcd94654fcde97265d61bc4f0a3d029253147302dcb04cf5abf8d2ec33c0952f88da4c151aae0ce9bd67a10265a3b98206a05ff23cc2520706a499032e1e05a059b9c5fd33008239c2b09569931df0da4a3111a89c731d75c31c29f0600c458438255fa6d046630cfd8f3e6880f425c67d9f0c7dd3af45532d1b9e86bc3429843548839fc5e15ee58479c37d2920ac848d31b6f75a7b0bc6ba71b5d9dadc9b9145aba5b94c4b614d8e81859bdd9847fdd222aa69517070b65c9e51cde55ce908bf1c5c86773ef71ccb7ee39d139461c5f18d3f59ca921f1fe2d877ffce2cf1278df99dd70ca4211e3b04ecf1f51ef0814515d2ab95ee3f3e064761c25657a3c52eb848500cb2042057991966be457d4886bb5663e973253623f8f604ff800b5449e809aedff2ea23e7c3b9ada5c0893fdcb5947ef9b00df41d4da7f0a15e9ee905f754cdd9c9c2886dc731056aaba3db5a1b1a05a28fe98e5fd4948ca121a40fb387f3af5249cb4e6859a8ad79c3bfbaf55a6321ccfa94b02c12805c22f1c13332cb397818e5dee670cb6a402af6cd852553037eaab86eed74cccac9a14bc880b6c3e72a759d452b851e1a0bd66fe929a7781ec3dde77d250a1544307ff04743d96a087f505b3b80035ef7364e5bcc6a9b7b31801cf222e281e7a2fb6205c7f59dca7cb05d86297b49cc9f25435ef506b760e963d3f3fa609006d25671479ea70a34258eea7b12cfadad0a35fce8d1bc73649824e3d5b2d08440548b325b54a060ed38f15c4652b4cff8821f3042ce407c98edaa5f7e51d464ace071d1ac300f5c27324ce508a04bbbd06a5a2ab08b7e3971ba7b92b5b604e361a38a0d64d2f757a6694703e9bd7da750f807ffa26a2a8e466f9a48180dcf5fa4876e52b4d6e8d8e940908804b3732b7aa9a89aac8825e6ecfadb2652354151e290b0404e7515af470738e08d90136bdd58a05a108b5437c35bda033d511284c450410f4f4c4ccb7c710179507a34127569133dfb87357789bcc651935fd760206d42cd98ee86eefa42761d5749fa4888df0f20385fc02658c0247235ee99eb87055502589539cf2186cbacb7ab9c28c4ca91f45cf86a47aa783b71a75a75c5ba7b5484151241eee77277cbec0bd7e96de33be74009f51bf3ba60328c4ecdca486b307e812a821a4207c877bdc2833cfac604d924b6435f0613085a6595745abec450862f21b580f5855716ab08cdfa99c2079c7cde35e9ba44d3132f5468e14bd034fd643c0da10006eb5ae164df21732ef7015454b01489c686d33ad9a090130ebb84e7d853a1f7c5dbed209ed20a1ca7a9e9efe43f2342b203db0a59754675bf86f194b09181af8287ebd83b4ab99bb5b2d5bbaaaa80e410f65d4c433dfa2a6af447290e3340d7cf661f38816d384dd65fce66f482a2de8579b548b381a5b7b61dfd0e70eaa8385bae60b7853dcea92b205b521e4c53c3468984a3e54a51609c5c70280096a18ca880301dbe7b6832fdb951cfd63904f5aac79dce7303c73013d96a58f1a8dd736940ef8a71c9909f774490d3e1fdcec821de3ec9979373f6d78bf41fae6a890719a2cffeefd96847863277f2edf9ec363c0efd18f55dec83849fbaf48ba040d8cc67e28d85be8b5b2b23fa996cd8ee9001df832f40ec3f84d565cdd8b5071ee85e91f8a41eaf0b08903ed35ea944e607803fae0c995e30946c4403575a371cc2938890926d2b568cc3b6e0ead5483bd9e94e1dea710922e7081bb3b2e7d91d076b5a08ceb6fc798654fc77db9050ca9cf65f9c56a99a501d02431d700a76536889cc16d7c9428d1c5ec28755d3d7e8d4f3895aeeb3432264a87c313912fec9ef68ab8d477558a3d5460aa46129a0c3d97fad915897db7cb52c00e5cd4816155229825a85dee61e562399bec571c232556f647a1cb71e2cb0302d43ddcbc5850f5e950ac0ebdbf47d4706809826e4888254f03e2847b4663453e4dd0dbaf928fd0d7e49dc1a76a2cd289ab55432efadce37b7ca00ec4216a252a4eb351c315471474a1f6edcd9d8fd1c0f2bb9e12117187d841099cedb3cd9ff3be25fcf3e82745f52b3e530f487ce9e31cb4de4c5ec68ce83b0158c77f3821501f60ce807050fdaef4b7d0ef4edf427de3b442fe49bf413635e61b01e049a779023a38f10c2de5b9cfa8b8f30d73eac844ae139c4200616fd88970f24d1f2b47aa42a5d36f9cb772e5506e61e6171ec938d5823561e282c72a65ed78fb081616d0891c5ff9e269fc5e824d4be72ff142274c9873dd29c23584cb824a7953645cbcf38b3bfac19a271b1b1e63c6aeca627fab1800e32aac7061c78838abededec12083b2b5a775c8794a67a9af66f5a4a0974b946d5a14d1a3044c0b11e2661c56bb88df9498198d4aa82157e977d87dcc57f1617d965d4cb455c61fc5b5d04030a385469d8de857dba5f812e0d240e5d77bf997101df8fc4074a920f4344f9f79624c90fc2185a18d87d6a813bb4a9f86a70bc1a2902031f37a463d80eeb7bef661e27ba165bd243f0e4a07131a36a195621f5914cdf6f20c65954010504870ff73567b24170054729d2b470c47f158ebd45d8a9630d85c05ab059985dc853802ae6afbaec633f3cad834b54d6b5d059720af48ce0340e2b0cf8661d8edd3297f580c3ce20b8e382672e1088d030141b3b6260ba1ba4d629d4f123a6e150f43687882b10a2e8818ccd0026ce0abfc3457e71c72d3c4398a5a7291bb13f6676c091c6eb2a3fa0b827bc8d16650a415e788e9bafd03d4ad97ae149e4fbd731653cf494c415d16c15ec4d33d42e97b99ad8e30beb64412a42323a7f339aa45d3f3ccf4507121d1b4acc0680a21fbda6118746f07ae12dc5adfaeb3d127ed044b78c18975f22c654f33945616d707be8fcc69c11fd4d658b3e206b2ef9bd0f466def3c6d43f5ad377999f9f31197b4f12c5612165e6a6b1acb542bd2be01d2c71a5739e1097f039d61b8def26aae03a6a764df8a8279996cbf855e7bbee0e9aa45d12b14569a784fa4366d39349fb62b1e2a602feb15738d5514246e714bb75e6f55c3795cb45b0bca11decdf431b656e89b45a97571a7f55821f75e868a42d29bc42a3e7dc773d39051e55264a17ae242413c31e89af4bebe22655f5ca13f9e628fb407a16b8ea56194f1018f36870c49ca808e54454d69bd184708bf33114d56251380c254e07f86e16bb2c3b5754b41300f04957105d7dc68ffbe9073c3098ce21485852d073a7c5795b3daa7dcdfc4aaeab03520a7c61acc9ba081c7d00b71c90fd07fcfcc85a5dcbfb059b8b0df4693bc5773966a7ffe5882687bab6127940aa2a16af55399e363a8f3128d1613a11cf71d3b2f95e48a88f98d6f496a8303cf785d1f4d30d88651e82c8ce43315854746abb9e2924cda064827513161a28a051133261349689a2faca602eecbc4180c3150b25472c33f3f3f3f3f3f3f3fbfe221b0b1496e694e7fa5e7e6a64cca4caa61140000a300b4669b66fa7501a380550004870b110c370ce57fae9040b0229553dc8ec3f4bb0282f70aadce39595e56ffc0eda658517e261e513fb0b1eaf207216d07a1f681ddcc95b2931c8da67ce0aff3fbc78d35d1937b60b2f26a0e7aea81cbf4b20e53764f95cc03af39bc7a4952df76e281cb4b76eb91e70f39f20e4c8c9863e4cb717f1cb4031ffd6ac7f9939ee6b10eeca578313aba8875413a3016244dbcf28d94e01c18eb33358f7278e18172e0d2e74e7949731c24471cf838354a5fcad0981d1cf83fefc8f17b10bab637f0f9d1bb7906b33c3137301eaff3e7460a765a1bf86a4f5e41670353f12c932697a89635f01e723fd5a6af704b0ddcb77ef87135f2a695063687e68f837839cd2c34305dab51aaab19b43a03b79ff22dc40c7c64c924bf4a07a153063eb8747bf4edbb0c19b8a01dfd6f5b4e53c7c08e57fd8748470cbce7f657bf4e18f8d03ab8f9e5c8b1c5c1c0aa5b4893693ce2e75fe0729e9018dd036d8d1738d70fd9dfa99e6cd305de2248b41cf4fd480c17d8209e2db0692be57fef285f5a0b4c0ccf397db2c0ee8da84715d2e5c002ab9ea3f5d29c9d2357e0ed3aceccd50a5c8a93c3f1b85205ae6a722d5854e063aefc217720554f81adfb403549c8e144450afc25afb4dcb9b23651e0d28e7545d574ff4281d74b1d5ed55f80271c9252b3c6bc13d8e49719a52d9a8bdb042687623176d65ecb96097cceae9de38a96324f96c0e41c3b4839addf07122570492cf353c8549d93043eecb073ee8d047ebb3e238ec71edd23f01e2dc6a9eb7c018cc06bb54885fabc48e617a0086c0c92d972d0a1abcb2f0011b81c574f5ac60a3905bf004360a2e8b7e6d4bcbdf00b2004a6d737d5e4588cfcf80204818f69f2dae7f4f7f5f105000263db714894f8e1bec783f10b2ec4ec1b57a525851c0f862fb8288b99237bc1f724cd71ee783078c1457f7b6bfb24a13b1e8c5d30713d96ba20ee993a1e0c5df0b179578c6945d27f0f462eb810a3c7ee7e5f1e730f062eb84f75c9e1e51e8c5b7029784473cfff34efc1b045153db66ac1fa76c5cad92942be68c1aba46e89ce91264bfd2cd8b34bf65e1e2e0b5622c69cd268aba5ea63c1e86fc59dbc29f5430f0b3ea44715f31a8f3afd2b9898ef3907295bb546ef0a4e6205d30fcf46c7d30abec3b4cc61072bb85831540e234e04efac828d99bba35533bd56154cc7c80ded51fc187e2a1849e9fd71fc8f56e3a8603c7b58c1263fce9d53303abe95462a3fd0144cda6e4bfcb28fa34ac1558ef3e85d44dbc99082eba82b0ec62838a95092e949cd238b83210ad6d7a38dbe4a28b8de389d9e7a2c4715507039dac4cfac7c821d9de4baee5bf9b627b81829bee59eae90dc4eb099e9953935521297136cfc1c9a6a79bc39c76e82d55069a2eea561219ae02f4f8c93ef3fe42824134c6930d760124cb011436e9334c95207b904e7b795fdb2dc2a554bf01d5ec86d51af93d24ab0a95fd2754f4af0a5591d468f3ee70d4e82df941cc458a32498b86dbad375d99318096e3cc4689e19b4420809467bd3e758ec3a73c72358f776914cb772ed70041f6a478ceb1dd6564723f8aa9c3cfdc756793c6704379d537b83bba676be082e9deedd4aa7085623a649a407121e4b041f66c93f5521376f86083ed27d5ad4891d323b046b1a436a9884689b32041b720731fc26e4cc94178293ac5c1bc9f2e620e584602f743f088d97b7960f82af088d4c527983562e082ea4ce548b29f661c803c14ed75d4a355fcf1c40301eb44b7a5ea4d3ff0f4c743535d70f5cdf7a7b1e7f0fb2ef03ef9f2269fd368e7ce0c3eff71c5d9687760f4cf6782fa5765696e881df2429761ce57830f2c0e546e7b4a3b9961b03061e58dd1452c8a71335c61830eec076e4f0959668b31803861d3893a841347d47951803461d78b1d8c14b54ffd36dc0a00367d771472239568dda8031072674f9a6e572e05cd4f27be8f4381907be63997ab9e4d8d3c281d31ce8d54793b2f70d6ce43834689aa46811377059338fa65abefcdbc0f4a88bc4081edac20636e6c85e73ee7a6a750d7c89c4983b4d35709e5252462dd3c0e730259a77341d4744039372e758d3079e81b7158da9927e5d6d0676a7ec7c2a5ee4f72803df9145ce31a7205e1d64603b448bb1726e0c4c9ba647be2a4db6183833c3c06a442e8fa6966b3330701de87720591930bec0e6fbc721f2a31c64c880e10547cd83df7f64bac0248b1ec5f3471362b8c076e891f4942db09aba933c2db01acda4b39fc5089d2c3031ad520e2c8f05de543cee94e30aac69dc8db53b55d55b810b91a15386e47184be0a7c1c7d464766bd4b9d0a7cee1b6bfbd6cd69330526bd9ed596460a6cc80e92e3a84a251d05ae4e3f887b7601030aa6249221eab1058c27f0f9f33beb72e0516e0b184ea02e67dcc80b6902a795249ae689dcb184098cc794c3dfbff315c912984e9dc30d7d1f3b234a60f28edde4ad987591243099affe3b12f87e37b10ea29fbe47604a62ea9de6ca4baa11f8ec717f24ea71d6a745e04d42f0379190c253223099339e27cf1078cb4c7e17cac35c1102fbb1cc42c490930e4610f8f43a6e1df4e6980303087ce8c9cd6297bfe0926d724b66fa8249bf1b3287f88d057bc1654ca92cbb684e09f2820f1ec4d770098f225876c1a6a6c77429ea82ef14cfa7d443ace0e582bbcbadd54952868ec3056fbb1ec4ccb92aa7d82df810c37bd342936bca16fcdb654bfbad5fb16ac179748e2bc5aa6ca92ab4e03f7dcaf34823f54b6516bce78821dd279745a9c88289fbb59597738d1d0b6ecca2640e3e2cf858a235047daf16ff15ec74ea90c30f1943ee5dc1b64a59b6ed5bc149a4dca16394a68eb382936029e4a6b1feacaf82ff9861e21faef5c455c147a51d55c4d5cb104f056b221d4f8d4775a8a3820f3b8ea8ed71902a99537062922e193505931453b01f49faf3f0b3eed3a538f00f935a789a147c985d66de9a35df1e05532e796e137cc26b517015db73fff32ec77528f8b4cc4b3935a3a516148cb4a68916ca3eeac927b898246bda649da3219ee0b322a8e7ef78f8924eb0b7fe972d4ffe0809279aa8f136c975139cea04c914b27774ab26b8b7bdcc0e72844a9a09fe4359c8d77b1e3b89092ec71b730e32ed7b262fc19a97de665868ef484bb02ff9c5f3a48eb38f953063d050828f434a21f7794a8993e04e4287b4fd0b0d51125c5eefe439a41425c248f081a414735ed51cd60724b8a47a1699ea973e8fe053a48e39a576ed1447b0fb9a721cea7523b8906f633abd146bbb66049bdbe793e38b6043a6ccd39ca3b46a8ae043fe8ead56c2f4b444f0579136638e33e61b117c947c36297d5ebeeb10ac7d98b6c31c444bd93204dff6fd710c9dda3fa80bc17e8eb4347fd657474d08b6c3904a3b6b3d729c41b091420e9dd925be1d41b076f126ab470fd71208eea3cc659923e4407d40b01b27f2bce3ffc04964bb9565a4d8713fa82f91225ea50ffc6db0cd15fc553be7031377637b8787a5ccf7c0474992fc48228f6ff4c0574e871e6b3c3d79e06274f4beca140f163c701d0689e6793cce63b903bf7942d2c78fdebcedc0e54bed4fb2ebc08712a3a7a91c6af4d0814b15d2fd2773d8d3c7398e3a9ac8814f3ee2ea917d040989032fd213e38514a472040e4c5964e6939473eabc81cf410a71427eca6671033f69ec3dc2fea36d0393438d51192a1bd8501fc4944c3b32d435303932a428a9c93e48d5c087695b39d0320d6ceaa02255336f4e251ab8cc2f2148fdf9fe7806deb23ea6110f9376680626dff5954f49577594810be6d1f6eae5d77664e0272b5f2ecf1fe8c6c6c069a8ba9c2f764a0f13039b4cd73dd20d693d0b03af9582a6e40103e7996d3a75ee9b7e8189b4d7e821b162585e304fa36f4a9d2e30216aaf049f960b7c875c29e6abca4ed26e81b129fbec23ad16784bb5f7141e45325960b249c8cacf16291e2cf0ae7ebe2931b37be70a6cc839d6b6ee7d0f6305c6eb3e9ba4ad55481558d1a9e920f754e0a3de2dcff3a3cb7e0aecf5a878865e0a7c47e7385e8ff6b18e022769937adc39a46a0305ee2e93a7ec255d59f3042ee79a69ef6a5fde09ace7c03ddc9bc0a4dac951d948ba0d13b8bbf7a9fc2884004be0e284903ade60e195253408e666ae09b6a30f2169ea4e345d32c155e4ddfdf8ca36f203137cd0789351f7368f2f7817fcba805ff02ef80ee312dc5abc4c16b3277ef05882abf6509ad3a132b4ce30e3282b6154e2c8d6cd398cc8a10467316e79dc297e962c93e034f7f4e4eb13497725c1a70eea7133c736cd31124c0ec4d433d8a4298b850109c6c34a96234453f11432c27804e3e165b64a88a4972304613882fbfc49bb11f38d60f2bd784e31d4479d1546f03f5929f249d48e83e8221857c9b1675fbfa70986a1082e3cfeb4e992a40cad31c618638c336630c6187d460d7a13816120e2c608e310e77febe83e118461083e5649aecec93ae4e938d405611482536df5d78e4a4f631d062138fb89691d769626db83e0cd927be65a7da4d58521082e7a70ef7c1ea6e6646104828f5247ff1ecf1353bec200045be92c447ae8c0438cfc81cf51fac7f58c1fd82cad1e558a173fd6541f3811edec38ba90f73b990fc2e003a71d058f651d6dcee9ec818fccb2ae50413db09d7cd22509ab4a9592073ed3c31c1e638807cee33079cc97a33b70953f8e33c7fa495dd31d84610736b3e3f82a0ec2a803971f216cef63746042e6499bccbc4c6a3307aecd6c54525447969d1cd811afcefc1e19076efab4f7e376f4f79c8203dbb1ae6fece8f42e585408e30d6ccccccc164277031fdd81640fcf17cfba0d7ce665db89e961c690610317f953d9e4c8629ee71a183f5d916afbb0534a35b097ed753b35a1391cd3c04e0a51cc3386a0be3a1ad8f3bd1c57ce9a9ce37b06ee2aecf762beccc07af630ac36a40e831554e0781046191857adb6902cde8f7964e07f327898f36e7706cf18b8a0d1636df51031b09b42aa9d6a93e813828430c2c086e68e3b19543070d1a3b8512958482be117b8cb110f5a25ffae2747185e603da5ff68bf1f0ba30b6caabf57919c33a70675100617f8d052693246e6eb9d2c0a616c81f3df4d5df993730cde0b1604616881a9c8513a422dcd52c8b18730b2c0fe86eb479b76cece868105c6e279a6981ef7dfd4615c81bfed1493a758953a088661056df2c30f31c6dfcef93f184615d84df13a47317efe45461b210c2ab0993fb3e3601e87eee31458cfd11d713f0c2970965a57ebf3630e3d5160423249ed972757db79868230a0c0daa66433f3ec61bc5020c278025395f726a494fb93629cc087541f2569fe46b54c13b824d593367d6dca95c2045e2a6378eb4bc7b1a42c818fbcf227b13af720ba4ae0623c9d8e3e9a654c3709ecd7eac6106d15c9572430ea9ab37354d123b07e2be1e1213c9e381a81dfa0632958945c1f824560b326692eff4cb6f98308ac85a764e61173a5ff86c07e643eb51b9a10989038be51b24f0c761058f328bbc4b1f4e84c0a03084c468fa3b6e3c81052e717dcf7e42eafdcc841f70593317be0a187781cd2ef05e329b9e75ef5974c0d2fd8efb0a2b3e577174c3ecdbe395c4d17dcee8defb7e77cda6172c1e41432c7cb1fa47e1c8a0b263553ee3cadd398730b2e74107434055d31136dc1664989d439a3ae7bae167c744b31435c69c17e9c3cbc2bfbb03cd066c1871c442778d0d19005ef932f4d07ae1ea47962c1e55bcacb71944e3233b0e05fa3a3caddb13a1e5fc1ded9ea4a9e1c0721e70a56522488f5c7984deb56b029b13bdd8ae59074c20a3e1eadbc922d27ea9dab6042ac98f552fe79eaa8829b68d937b58906b14e033452c1ffe694555443c727390d54f07184ea20670f314bfe2998142cc42d4d932938f730abc518371aa5e0537b5817828648c19705c9ba9b937f1e63038d5130153c6d697845148c59d6cada2e6e559150b0ebe671e441e6a4ec0b14dc779c727ce92289e5141a9f60f2b5a4183afc3873f8d1f004d7718cf4e59fca256b343ac17767eb6c3675d617a4c109aee3f4e44d6a96e44fe3d83a7baa7b99ad092e4acecd58a1427256052b60c19f519a092eca73103d3e9acf474c188d4b701f885844c4f08c2195020d4b7013514fed63d5a5eac719685482b1891c9d95a34dad86126c797a4b884e92630ba13109aea4af3d327aec972e92e0d3fa8f44e89e48f18f0417e1d1879843d4ce9d8704932ce66cb5d9375f873e82b1f21c55df4fb0481e0d47f0715dfced5472b22b1a8d60bdf3ba8398e34fcf7198800623d8cf899dd2ae9e79762c82cb9e3429519e151da7033414c1a40e37c690f06824828f6255f43416ccf4541a8860b3c58e7332e40d0cda9061866f0c681c828b9e735c62ae1d06af82262306358041bf0b0c0d43b0ab7d1d121d2bc4c8518656cd804621d8a9ccd1b3be55ec143a83062178b5b434ed7639f4f87e41c3800c335c734063107c9462f964766b91e84943d01004ebae617d79c7ddb70f041b4983f407f350ed3733d000049793aad245a598daf13ff0913b5d5abcf36bb4fdc07a0afe5daa91a309da621ff830bba7f638c7e10217aca0f0813dcfdabf6929dad38334f6c0eec7fd9ba2376ea0a107beb355eee7dfaa1c3134f2c08ada7798b4223cf0591382db5404a974dea0394077e022c4e390b32abee76b0c34ecc045e57b101937fa77a80c1aa800066f810e6c5d1db83e3fabbcdc568faa0d34e8300736c4a8ae4e297b1c960317c420068de4e4c0de7f744ff97d299a180726ddfe77353830eae1c6ca1e0493e8c03770f13248ed7adcc0d64a57941cc4b440a30d4cb6d3dc72f7d02fe6d9c0455bd14a151e84c61a188f83e5c778e91768a881b33dabd34e9963e83864c081461a98bccfdf4e3f8a80061ab838a9be12c173540759008d33b0136d7a3d0a4fbb92230334ccc08558914b542a8d028d32b0772e392978060a34c8c04f4766f57d68f3c839838c179871c6b9d280524d80c618386bad983e6ef6aa9a2aa021063642fe389aa55886d681031a612030b09e6a2fed85495a2b70410c62d06636a0f1853d6d56f7756c12b532b4687881b39446eb3fcacbd09ac1cfe0cfe802dbd271f41df484f230598696b9800617b8d5f7a8b3da3c684b51b180c616782f9b48bfb6d14a73b4c0ada7a8358f60f6d19e05563b74f83183876588c1021fa6daad85042feff70a9ead87b8d6162b70291e6de7ec359152abc0a68f4c969eb6ac46a5021f88646fe53aa7c0e6c80e6bc76387ff91021fbb6290f44481fb207d57dccb39a63c42817fc9ed8cc83f818b122ca25ec766d5111cbcbf0d1e6b40c3095cd0adcebc3839c0ff3000c0814613b88da57bd13f5267db683081ad98313d5aad2df74a06591a682ca1c6a0a104451a49b031905063d03802df92da399e8e989e23970c348cc0fdc741b2fd483554fb45e042a55bc8e81e3c874e0d3488a077142b87efa18ded6568bd195e3ca03104362bb68ed4c5888eb72ed01002651a21e251ab749c528e4986078b0c083482c0e520d2bfd5bf4d4aee8c32d00002e775c1a53d4504c9f6a842017ec1e5b0eb3cbde3290b9a02f882c9b154b4728f3e767c51a100bd60fb53c7183f4ae6196d180ac00b5e2f423f8e17f2acfb5d7021a4549a42c6b451d3ba603b4796a85ac9b1643517fc67c5241a24db34555028002eb8d839693dff6a76eac8a8d243016ec1068b999133dbf27a98591f0a600b4673707b9758d92a786ac1a4e8f4ced7a8f5711c5af0d99bf971aa743ad59905a71df425dd74ca82c921e64d1f46340daac782ffcf99628ebf2d5ea5c0828d995a3fe593e892d95770e9f2e68fa47a49a17505fbf6693d993ff4de482bb8ececdc1eba3fe45659c1df8634318dff7f0773155c96f65054a55405db31a3c7619ba32783a9e03c7eec74713bec2b880af63f8ef43e07d62938cfa99ac723680a3e7d55f75f785c31739482ff8e3ea5f59c7314f59182af1d3d4bafa951b0e691ee4a55e8258f28f874e9bd59735cf1180a05ffd13925677440c164e57af455b57969fd04571ea5a91fa2ec33ef09ae34879690dad2f2b0136cea28513df23838c144dfe4c7ec6f829364e913553445f2a3430134c14f768e9ef3bd4c5a2a4026989032c43d4ff78f2588092697998478779b110a70093e585bce91e86e097652d2db8ea3f0cd71490d05a80423a2b1c31c63bfea9445280025584b13aae34c933c5e8d150a30093e42e9664969fe5c8942010cc13ecc890497b45379dc595f3d1e124c674d67a51021e28fe02fb27ade8c69ed74049f2ca2cf737823b88e3fb68e9133820fa1935ac6dc1d42b3083eb4accee3ab15c2a2087e2a9366b590434e9544f0571d64ce6b23828f7235df985e8e601f820fd2ea61aab491c23604d3d6b1c73aba109cdba6ad1bd31ca72c21d8247dfd418a5b21b58360472a3d1669ad4e218260a2da727003c5689383d0492c9a0aa62ba76a376b6be81c15ac07219d295687a825418318a7e02b7608db1c32e4f8465330b9a742c73947bae3af14fc4847698f34523039b1236995ca76c1830c3146c14d7f1c96a1f57662c410051f74d3d4bd66cfd13e628482ad0fb33ecae91e3aa618a060b3566ec95a955a1196a19583bb81189f20627882ff20af43b5d2328f2c0d6274828ffd2be5aa0bed29fd32b46ec009763a3b7aff6212c9d318c4d80497dda7c47c2b867d258626d6b839922b6568b5c00c33ca7081afc08c10626482b5b70bb93d2964c8970c6260828dbdef2187a81fc6fbb20c625c824dc145434c663a6a1de7803268b08210ccc0052e6880011c6000187cc0000e3080030cd0010378c0020638a8d0127c5cbfcfb1d92706312ae19a25318b1e25257809be931df5425664124cada5ddb8112354f0be208624d860793c861cb8013122c185464f8cda9dbbc3be0a6240821109bd94c371cb28154205311ec1bfc4fcb03b4f56248f32b4c830c34f066238825b75f3d8d1be1d6688d108264a68a7c7d70cea3146f0116f63a5a07dfb6e21408c45f01d2c337dd02882554d957224ea413ef513c1774c17a2a79083cc410c44b0fb92d29a24ef3c558a71082e7fb277734f1b828b122bdae47883871029047bf6a3b97d1783106c5f4cd59fef171d688360f3e78e38a6d2271ee41a21862098a07a57e521f9fa3f6a108340f0be217ba5a73c4e758a01084e7ccc3b76fcfc810bfdfee167e37174397ee02e5fa67c5f925197d307bee3cf9159a60d2992870f8c8f78a6ffd0436878f6c0be7b8e39c89efef08e1e788f27a60f569d3cf0e96fde51aced20d5c10327a172dce1568c0e357f07c682464d9e35e7d8296f0736c71d86280921cc255f07aee387c9337a74bcb1a703571fb77e8c9aa36d8bcf814d1e72fd36678fb6b81cf83072ea0fc48c037ba67eb14a7298417438b09d83bed08f722269dec0e714430eed4082dbc50d4cca90c38cdf7ea9b781c9a1bb77a463fb940dec7a7d1047d3a389ba06267eca148d21a306be2a79d2d0d7754bc7c14603b769222a5db6474acfc0856458c75f3f0f4933f01e39470e9dab43fd2865e02bb5dd7dd8498366850c6c5772115db7c7c07ff4f4fe1e5e06535b0c4cea1b5f5fafc3c04ff0389adbd633ea05033751f5e97168b19df60bdce4108f29678eb12ae2052e455bcfa039860555bbc07887672dab758da1728193f08858f6133a5eba05de3c8cd1263ed5b9a3053eb61ca95ad4b3c094a7901d4fe88ad4b1c0aea8e4fe770eaa972bf0a97d5744b25660b3a4ecd19fa1f9c22af05932669df42515b85cf7f0b23805de2aaa75a899573993023f297edc1c1de2272ba3c047f96eb126595bb85060ff35d4777b76f7109fc0bf5688f2b2943c4e6024598e976d3ad00fd30436fa834756840cf983099c46ab31d5f158021fc7fe11ed26e7c7a14309dc76c42429720e72a827818921f884ec3d4f5e3924709a9234d6f9448c23f0217a98b204ed183931025fc9afbfa2a257885d113875a99c69d783c8be541552684d2162620c818b789b472bc6d110991842e0230f939e545d86ca1123084cc6918cba95796f2f3180c07ab766cc39bbdc27f50baeaaa31c6a86d96947f9820f2fbde03b487ad371a48de1f182fd74e74187dbafe62ed80f8f394d688cdd51a50b3e9cf4716ef7a8be7372c1e98b5eaeb8ffe53c2e78491e5a9e6a8ecbbd051bc43f9aa8d8828bde29e12984b2e041b5602f96a55b2d55d70ea9410bee3e773c2944f5a90f990597d3c64b39fdc3581ec3430d59b09f35a8ea763c39b78e05abe98107591b3ae20e0b7e2a3f429cd47911cc3ad47805d7ae9d394ac518d4c0ff0131a881bfbbe2742b6d6f8d928839f4ec9362eae0a697a1958333685035821aad48a37a88d6600593695983c59c2dda51656839da2aac862af83edfa4fd41c472fe656891118317987b810372e00218644003638c6166b082179ca5825157f70f6d7b4163880a36f859cc8abae9196a9c82f37c39d4ec51e6d85d620a3607193c65d5a895828d31a7b465d0dcc9bf04dc052b28c301a46062dacf514cb5ce0ecc5170e3a3a982dbea87270a3e59d68e12dcb263e7970b3542c15487b97368d4982a4441c1ff7f9a5a8fea137c559764b6e49ee0dff27d9047caa5634c27f898636b6d7b6d0ba182851a9c60b395a5dad6ca21a1c626f81442a7471ac3634b61086a6882dff548d27d9461a0462638c9f99aa38cf1c404976bd2a8b5a5f1127caed6a4faa86550c3127cbc1ee548fdd145d55f89f7438a21a5ff1812831a94e0d3644df0df0c2f5c418d49b02949f630a7cb51ae7d4b163524c178efd97bba3819736424d8cb815e0e2a25724702095672f44996c852a98e47b0bf295b4c15b523d8d2d431f1d1da18f44670d1f662a9790f83336a50d6001e88c00c0a153518c184d46ae9cddcb3d4bb082659c8b5f31c49ac5043117c8cb64134a737e9e0151a6a24828fcac36ec96d3e79ac29d440041f454c925ef27b085ea73447a79343685b13c0aa61082e9d6e8e466f2c04938267c67c1d722031ad41082e5db41c6e111a438d41b0fa614b88942977483504c1fe96869c9ee37695816034ea4e2d3a0e104cf5470e93878c16439c50e30f4c554e4ddb37c150c30fbcf4fb6bc8719a8c7a01f681fb20e45ed75787317b0c51830f95f8deaae4b0df03bf315bde762531c98c1ef8c991722c670eba6a1d0da2461e388f3d474fc910cad298554fa881073e0ed2c6dadc21c79cda1d989e94cfbd46e200ab3cd4b003ef3e29d953c69c1cf2191c89a85107b64afb24480c7d31230338a00051830eeca5aa6ae5d8b3253cd46a5cd925778e2987ee1863f40bbe0c330332d4900393238f42dea4afada5a9a1e4eac0374713ff2dd48003af59d4473fea2ce7d019aca1c61b388fe3ce1a1d85c8ebde0dac07ef30e7e946777129f0851a6de0c5a3a3fce51d9115abc1066ea7b433e62056630dbc2717dfee8cb5fe9135d4c09945ce10995fa11e3dc618e7881a69606332c97d9dbb3b9a748c31c618e328326a065b35d0c0c48f8e25f4da3ee30cac7e88bd7ac9a3d8f42ea8819bf18231c6d025d43003fb297bd49c420ef516af51063efd56f6447944851a6460f53ad845f4764eed7e0d5cd02018a3c618f8201d22a5261fa350430c4cc89759b5a35229240f50230cec6fcceff7bf8a937140a10618d88fbcf3320b314be935bec0d8c78aa839c7a8fffda08617f8a4ba1a2775f80e6a7481ef94bec56350cf10cf375ce09275e451c2939fc40c0e6a6c81ff30c5af8a7b61a9d125420d2d30a9742ff525b73c5fcbd0aa828022c10009c81000106a64810fd6517fbab43a16f71635b0c069c51fb1ca183c8ee3388ebbbbbbbb3b33333333b3aaaaaaaa5aa2892400b0a871053693478a0e3dd4da56e0835d1c77b3748fd553052edd72ac29f888754f053e10b1b7d09f3fc79629b0413bc4ebbe5e0a4cac8e8e5cd54481cb953d85ec4e9b3e2f50604a43f5a3142442db2730957153964ccd524d9dc0e7680ab973879dcc2a4d603ff2cf1ef91292e3304ce0f772b664b0f53cd15c02fb410e34a473749ce6daa08612d80c0b9a4c3d87d6a1930446aa4b7cd47390ff03096ce4641b35b142faf647e043d5e7f4c8367ab611388ddc9da364397e48bc08ece59426c7e179f76b86086c66d7e8b1db328457725efe4f8e2204c63cca8a5bbea1e3201b04f6a3209dfa345896b2061038cdfce25d23f9055b51dd3ca3bd87fc515f3099565deabce3cd1ded053f316dec38eaa41a5779c1459b9c681ae92ef8f841477e92bdd57e5d301a443a83483ebb3d73c1c49892c41c232d5706174c4a5172f4f96b4269780bfee31c6a9ab672253d6cc1e6e8bb651fdb65ef6bc1f5c4f2d3b6dd4fd3d182fbccb4c1528e27d5cc825df730e77f60ef139a2cd8ec398adef45b8e33b1e093e4dc269d6a82b9050baecef275f54561bc820ba9fdb3a7ef7b7a2c06c2700553fb21059b4c2149dae40261b482f51cd56ac4bbcfa1a39001832f830664182bf84939f44db6d8a66fd0679041031c3c0cae3a10c62ab894776e7ef5515eccc25005d3de5a3d7152736a3d155c670d71f70fdedf51ab1b3407d20807c24005b7c1ab2e5de83805f7296934297d0f1a5953f0b1b4f67f4e398a1c16462998be209e831c99240fd3803048c159cc1d75889eb653f3a360f42ca65051c283a89919d42006872858e98a49772c4de5a0854179208c50f0ed1d87f03833846e7f1d60823040c127f71cd328a119e35d86160d4cc7e005661832fc302a0ee313bca649b93ffe4aec48f404173fac94ecfd3d1525124627d84f77a99fa4aa200c4ed4182c30616c825f4b56d9dfeb6718335ef09e72b8c18b45b37b4ca91e75666ee2c62e8e4f32073156d6cefc92b5e1862eeab0a24af2b1b27351e4783c2a3569087181b6b6260d95b6f75b5ce3e1b67aba60793bdcb085ea9d4376dd89d6e767246ed422d3bcc16aaf5f35c36b300334dca0c51be287d319791b281f6eccc2c99ea6d2a493de4990b8210b7cd5e278a7e9e46bc5c2f6c8733cf94232f3c838dc8045313a781419ff328ba6cf38f20367b8f18a7a73ced25157106119ac2e6cc5931f957b3a567c63fa973a6a15da7b7f440a375461db86a416f9f5fb3da920e28e87f60415254bf9a3df5e8ae4f40a374e51ceec0f7f5ae27ecc8e31c6186398256e9802e98d9924dcef738a136e94c27c716fe9d41d4a0cd51d6e90828d19c73764c8669083afc02838c9943c268b17bcd21405fb29337290d483acfe915030398a5da219a347b0cf0cafc10d50303956bb140fef4ff069d3c42a2fb7fc3c3dc1597d106e67a7593c9d603b6d22fba8e4c714c209d6773b0e422bd524f49be0ed5366de0a538b91d504fb615acc21e44c26aa1833c20427d2ef6e1aab83681d976037e4d856166ff30b5a82dfbb8f9434588a94d31ab08001d870a3127c58a45c3907cdb93d8a093728c1a794a2b98ba9c7366d4e827155fb9e8e6107c6180325517ad8a94663928e7d32dc88049fb3dc37a56a0efd6321c1e746eff8c3c80c6dfe2398aa31dd5ca75529621b841b8ee0b635a3f63e5b307569d05cb8d1083683f8bb5a7d18d1bf69f5648be05c47d36d525c116c7e2076ed714248d6248289273d96b33388e0fd42a5c3b00f5c73f42138edb5b212b7d74fad217857b5cbce192d049383dcae41244a882a477977eaf2442f438fdc1804eb418d24cf7f51d59d2048d6b19a8444b5ab58d20d692c43eb2837dc08448d71031035c61ff8dfd841feb758aa1c3ff0952beb731c7b644b53126ef4810fd242cccd8af94e573e30f651ac586ee11e58ddd8711c224ac8517858116ee881f7df94c662c8f6f8571ef88d94e3d6c4ec20528a410dcc3843057860525ab7ec2987973ce4b8718701dcb003f9c3acdc9976d68195501539fe9e141ea4fb841b74e0747cb5acb3e87dacdd98039f95cc722c851c776b3930d59ae38a9d961f72240e7c94f9248d4f76030e4c0a4f29879403ab88a80b4a59010cc85824dc780317a246a849bf471ee4c7106eb881f57d49f5af49b9d1062696464c13f59e254d5a0cb8c106462779fea7c9b8db71d6c07adc143be588d6b4bb1a38b3f5e8eaf431737269831b69602ab895e6c9eecd81050ddc98ad7d2c1dc719b8cbbec8962ebd36aa66e0c4b365e8f69dec77fd0acef0c041831b65e0d28598a92ce7981ffd64e03cc799ad2ee580c18d31703976d8c69cd2a8fb1103935dc162e79413067e246f9e1033c64fd5fd0d30303908b97e53fb05dea5473d457f78610f37b447195a3930e30c1acce05ddd0c0c907581cdfb414bfa40731cf4c3c10ace72818f83103b5f908a999adf021f7828527d1f254d28cbd04207dcd082295ebab694e794ed230b8c07967bd37b182cb0c1929a77a8bbfb1ad32e88c19fa1a5811b57783bce761fb46b5cadc9d814dcb0029b266e0cf59f61c60a3270a30a5cbefd70f3b77f90a2a5029b21756a9fcc17ec2c221820011966dc9802ab292f34e25e49ca4fbf0bb60737a4c0ebd947678a68195a15b811053ec68ea635872155c7571937a0c044ba946ddca32367c913181bcd6127959863bb5051e08613b80b394e9b45cfecc16e0253fe1f19e57719f25486d60c5650862127b8c104b653547d373c9f8f65094cf80735294755570f2a434b09dce7b846f7d2eb793609ac9e75cad1615aade00612f82ad1606f951f810b7996ffb992b6236204f643f3a45c3fd260052f78811926cb8d2230aa919a9dc364172b15811b44e026a7fef0d18d509b6308ec7d102af3841821307a1221e64912b21b41e03afb658f2d24867b08831b988113b801043efced4a69ba831c45f70bd62a4a2be565f0cecb179caefda6b0f37a61487972a0316d9e17dcc51c7bda2553e91cdbc51d7b5e8817fa751bbae0b33cfeccf0d0e378aa33cc20e3b0910b3ef3d795c7fda8c9df0bcc38e31c2ed8d1fcb18fe52886506917c4800c09b8190eb0710bdea23fce93a1463d646568d5016cd8825dcb51ec3fcb51a6b4d4c26cd0c26ccc82ffb8d2c4dce194a587872cf854152f77a56dd6dc1d32f807980741d9d74006ef6498b7c1c682cbef8f4eb73cb060530cd19384b41942da365ec147684badd21d071a541baea8311260a3157ce598bb777b2bdfa6b0820939b46d7a8bf9e2a4ac8289fae22143323c2c6d872a38b37c316fce59b7a2853652c175ce1ade416f2457720ab0810a562f072a2189e7d1ec29432b07858a9cf13458c161e3148c4bb4ea9bb496a1a6481ba5384871902c1e7d2cd18e60195ab9021ba3d8638aad915fc4ea19c4600687b1210a36a43443f0d0f1b3bf8ab0110a3663544e31cddb600314dc47371d2b48fa94834954363ec165a998412f5de694e3cb202a4fb09639115183c7a06327788b35b91dbb7ed2f6e004ab9ab94c37ef4966ba09fe2f7656cd8eeba7febb1930a0b200a955810d4d70b7c942c75188508f533632c1e7e8b97a1ee2a2e9c104eb9fa727526f5d4cfd12ace5b01834e58c2558dbe89a737ba7c72f2bc17f14de217a7a94e0d4532f1b93e02be3471f6fe5f85fb32109b64f72ed4d6f871d3791e0934bd48e5d87f67d9060cbaff2e75c39f40f738fe024ad9be57825ef7354575ddd046c38826fcb955ae9be11bcc594c63e88d1f265c908beef4cbaffffe3386f3616c1b8d4880689a12218f7ca3ff9ba1e668f9308ced37f2d3bb6caca1122820ff2c5ff360f2297d85eb071083ef75a75b21cc6af960cc14678641582cd1d67ab6c21435dd408c1c6a49edef923d7241d04bfe57e96114c7d43c7046c088297e09ec5228f54b7051b81e0e399a6310f9dfe342964850d40701352baec515cf1cea9fb848d3ff0be1d897d65e6947f990d3f701ee4f66c53ffd598d71fd8e803fbb1c6de9d1c57af2b6528190e6cf081cf48cb9e38c9b423e30c33ce1ed8fb38aef41c45cbd02abba30636f4c07d6ba8fcd549cbe390330c90800c12d8c8039bfb036bc949d71c6ce081cd9ed37a621cf594931c6cdc81fbf178db7335e4183b76e0238e7ff6689a759bd6814dd11d3c536d2cdfde60830e6c576e4cc94b2b36e6c0e7f8b1a714592abd9a11d89003ef71d462889dcca3c56dc481f1e8be52f628f9593b0907ce4a2377e0915b8a39d40ad87803abed1f73b68d3951b20bb0e106c6f3caa2d62a5e78dc461b58cba943ac4df7d07e7a850d36309d453dc7bdc91ad8ab4f21397e6e430d67230d4cbd5f90c89a6dffe331f02a68189053d840031fbe6bc58f5e3fa6ae6d9c81ed4e11cf315f92d09ad9304319b88ed25b8a1f6a3a17572b61830c4c9e942784a4e4b7a68f81b5ec9aa27a14547a5731301da6ddc93adf8f62d046181895d61825b7254d60030cec6dc81cd946c721f71db0f105364323d57fa867397358b0e1053e2552c5ac1ca4e4215b645436c24617b8fc418e92a23f48da6133308003fe058d010378c00206b822a30661830b8c667bd039e5d44f1d320bd8d80213afcf3de84b41b2c5e4c0052e680f64176c688195e02a127352faf4f50461230bdc84c73936314fd37a06890546a2aed4c7b1a47a71f30a6c0c29e952949856e0e368e211db73bef9252561a30abc64444bfd16950d2ab01b2ca668c7e153e03a54071d1df95385500a5cfe7ffba0ec62c8fb4781d78d1339d01b0a5cce6059a2ae471ef64fe0434a39fecf1c71021f574e565db69c3f6d02d3296610a9f7b78e3713589b6ce695337a75331cb0b104cef3f7abf84797f797bd820d25f0f1c5ca1e5b2784b48656b09184b3810426daa3078f3e0881828d237099f7e26bcee96ab5bd32d8300297d42f6ba5b52b43bc085cfe581d8a74920c3688c0487ece9543ffcb443304ee52feedac087d39bb42e0738ce8e9eba3fe350a838d20f093a137879639a3ef12d80002e755e11d6d5b84e78b18bf60347f78b41ba94af3440c5f70dd1ef8498e693cfabb0cad858118bd60e3486ebecf8fa246f58c8f8119ea023178c166f8d5a729570f520e8741fb408c5db02993c4892998c7dddbfa20862e58f38c3a71824dea58920b3e8bbb69be86ea8d1a3170c175f00eeb3f486ec18975464828ff778f2db8f48d3e0f3a993bcad68249ab1f7b72ca19a4775a1435babb45640962cc82f3fcec1c5db39de6a02c2ed78992d45187c4826d2dcfdcb9217f3d7e068a018b927466ed1ec95fc175876a4892aa324275059382f6e486a8a9b342a606315ac179ec6bc1bce3d00c62b082d59432a5eff8eb3bf6090c62ac82d73a7fc939ba6839b4570c55f0297d048d1fa824af85f2582c0e0644c26030140684958e0f93140800003c248ec422c1288e436d7e14800350241c4a3628181c2014181c1287c5a15030100606c340503010088381a1709018800783b0372a7e5b7e368392c0aaa8e3660d8e539adbbb9f10a02802acdefa6f8578299b62eb01781bd474998152d4df3f450a4ffb4ff6be034b3b4d37ab979915c3ad2c3145443446d0ccdcd49523bf5810a23ee867872aa4172aa1d79110f977345a18eced9937cfe33bac996b7e0d89fe053cbde0f83470d5e2784478337415daa126a706a138e5b2e393ae3d23549aaa21b352b57e61a74b2b125265ce208559188bc6535ec1f71db11340133dadd39949c2578cec84470de49ba58e2ed0e2e10821128717418243bc55d07f00074097ded3d1cad20b56ad6525a130db7444193f86d78c8d4ec90044eb70ad405be3722b492d230740de7b1a8cf07dc575dad355f323a9a1ccad6f104b80c544211653fee537b8be507483a59d3393ae4fc876f3502fcc6164f6ef5a553454d73c46699bc354f50e6edab0b846887b1d78c51f9e51b4d1b575732d0d64430f90ca7032c672a05d0d96910f4da2e0ef8515ad1f9ad0c43964128771639ae1eedf701311a9b8968f9298f56ed6b8a7f1f1ff0f3ba28bcc9e640da1037d981f155c121bfb9366b52b6a2ec2e5f44816b8b38f1413079f2e8b0d7c582e2f67fa3967d71f074af8a1e24450f81e30371f567209a325c572fba46bddd50d433ff9f4b900a926775c2f0d4944ec255eb02c9ad58dfb6641cb020ddb3a6ddbf2cfc8f39655433f7da788530fa5cdbce8b5423878ded950872d03504c9b4f98340f411c9b856f707a09a1bf0ed076701d72e69273c1d8e0506fe8e0c08aa90b65d699e5e5bc6734424c5fba3f91ebd011586cedb7f093cd80982e8b2192068d69c2e1aa013775923a9cf4f08a5d2846a0989fe313e22cb1c2c11c4fd44702df72baef45c3854f48141f43eaec980ac950d68e121583ad189e0fb418d98c054acbfc3032f7250e69e46cabc221db11ccce78ff734234758cc15f68bcb3e612c3a079d3a80855737bd4021daa2a6c21a16d930c06c2dc1847f8df40fb0497bd1c4976d6a343d13aaa160d2ba91cc4d8c1d6060c3d6055cfe3580217d825dcb43164524f5c2fe43816aead19d7058b4112607eeba3377c4b176232c77983742a8d1a2dfc321a8988433c735ad251786fba3c3f25ef53eaad403ee63d677b6ad6e1178e195c5678952d83cbc9624db8ee8835ac2affdd55e79cd5ac45a606468658c4953dc552a34b19f189811efb50463c12378ac189f56867e28690d049f8716d57000cdeea9301cea4c1a798df309f8029d1a3a424564fd719e629876c36fbfd82813296f6e5bf42a696af3c91968b8f826971a0c11d78e329168ceced42863e5a7154c6539e0c51001edb1da1021e4a108d2adea6239cba3eeb4db3f00b1af8ee3c15550d1a3f6787bce5c08a98828842a4e82104adb3dca6f90833263741fb83ceb181bd0664161c17dcd337e25a080f9d65f1c88c0ceeec873f2e72e1ca0fe4eb48011917e01181f5edff8a905b2674a81da48319c7adfdb8325ffcf3041ac6c7f4bcb08285f08e09e3433032ae2f6c5e4bc1a9bfcbd4480d781a1cd19acb538b5ba1f917f141d177464b51248f4ecd6b597916f845804de3bcd4b072068d40eed956485326cd71a5e7ca9afe8bae819d7519be9f75120c1a4425104f0bd505e03a344f3bd885c3a2a2511aaba45a034cbee73c48c7daa06654213f2fbc0abb9cafb546fa22a8cc07acdd651413a30d5086489a9b44795266aa781fef4c0b6bddb64c8bccdd74c4e297b22e3b1b2ecb0971e83b05551e330a464f004ad30e9613006139dcd8d146fbe42f9ac9ab38b29df8074a0be226dd656b825af0ed78bf56b6f2383c459da562a8f322b5a50c32dc37ed0454e9cad014b2a769adda1cfd8049751e37150c73a3213882b0563c21150f72ef74089e4f097921ae6ce35e6ebe40cc27fee5682960c713d5ec5cfc10161ce88acbbab179e7c6c1326250d4bbe733f605d0b808f70573bdf4c1259e58a041192e32345b8232cbab1ac2d0d28a6a6e983b8f981a7c82b326ef748836c169da6e2a62932c979f49c3d244f8c1c691f7e596e14a6fcecc252576445d10203a734377f894ffce91d97b4972ed908f91b5aa47f516f2e772ecaf2e1ca1b933cb502f148a6c93d39150de86a9b27b49a10ebcc1137868dbf8a54ced7529654623d648a119ecb8a92a0cca046629adba254d96d2852f45ce4404db1b4dd2d11a0d44f9d8c7ac8fb42682130fd2353d7831b8cba36821a054830505f2447293d0f711c670f8fe22304248c1fc78c2c5fb7049143039b680390e83280b529f4afb912e8253483d05065c741935fcb41da54bd97fa83450220fda011b8bdae0836f05af750af66d11f270ad522d2b5407a5841df893364c70d20ad4f78a6aa73a7a722a2af02502837b41695918ee8e083b9cbfa5c6763bd048303c2eccee294ba2f9b4e5d323e91a0a7b3e8d6457538f9e1a18a6f8830c7c6d3a718272e1bb6987f3a005cd027008d53c8d98effbfcaf1bbfa76d8a3761803e34174cb56807d91c2539a012ad4649902b63dab4b46d68f4deedcc0642c1ceb9dc3af7918cb78c03527ba4972506904d514baecdcdef5aa8dbc4156dead9ce8f1f20cc3bc94c4c838b6e94d63484c3dd8c8f465423f930561d8d4023df23aa7199859c7b1d38e8b494cb2612204d7aae726ed9d924da802d0d36574808604fd62befdb4db2469d5853b57e2b4311d200126afa1a6d9b740fd950346edad9c908c20cfa3dc8047f50ea9528c501d6445e781a000de3da14b9001c7e1437ba962bfae64078281d24429175374974b984682d981d2b6a166cdcc52544f616e6c101082eab102b1261daa146413a6574a5c92c665b65ce75f66d3ec301f88ac6167c68e60879046213bf39012484d722557540f7a7bb194abb035263545da353ca65f9ef6226fe0d58c67b7a1d08acbd6057b515fce7b7caaf7e5eb91bf69788332c40489d95c7ee01ce579a0c5ed4501b66bf350833e556b81b7cfb4416df9fddb0e6d5ee045e261532caeab3e313f2b4042548f48afa6955d5c40b517ae5c8a55c694bc4ef249390a3706ac26dd66cdff5eccb85c0e3687b6cee9e6c32dedea53e5e8d3bd29f59d41279a8ad50ff01637bac091d3e8e83372a855fdeb3d8d52d3aff60d03aa1bf8651e18f03eb5aee17d57c019b94d75697a776459c1b610d08f0181b4f97b7a5e85f4e006c81f67c2b6bcdc1f5bb9591bfd641dc54036cbc68e6e633d03522cad0e3b4f56bf785767c83c73db2c3085cc694daa52a7a3e25cc3c1e03ffa4daf0c05a45f8fd668835d2ea6cfe7b286f17c1516310a96a792c7f70d947030a4770a490df3fc8d1f7bb717eb35d2a882f75aab61805843eb51312a24198f9b555ce80bf6b5a8dc160c1e45394c513e2226f147dba6db2ce958dc4d193a8be63e3e635a6a6220e9d8e4ef10b4ff0eb6fc6cf38a517556d38a37b8c6569ce3c7a5baaf78bc8c0b0e8b20ccbb3f4067f46b6a2e285924e5edfa3b6eb2a3abfdfde3419966dd76dd1ea1304db6dfcb1f54b4b10b03ee05b55cff61e6d86ac93e7ad66380f3e871aca1f7686f263241e845a30b84b985dafd99a1c87f644af856c8cb8dafac034a02f90135fc966d03fe52d630430c6de3e9971ba6d3679c39d1261dfae24a568740b26713b94a1931128779cf7a3e88b946716004891e0d93366304a20a1de4b17f79743ea802352eda8e1e995dbff230502df6680f9c076c04bb075c2dd4bc0d12d482d84f5b8c5659f03ac41cb5cfa9bcb1561549b46fca9616270e48c926dc944c3f9252250053ee757656af1f02ee10cb48216567cb23277571d97cfd316fc62e44347d1559f5a7aee8ac287d70d61f3e30946a7a68eaba25f3f26a2d68d66130364ddacd42b095ae6922da01b7546058b1a5f43d66b443d6e0c0c157778536d693c97c1a6da50cbb8b947dc39ea904f8512ba707dc68d55e4872bbeef137511fba1e8147d2d29e2b6a836f12da042c52af508532950fcd393d5eaf5da1c7925a441a0908fc3723583881308aa39b6e99513d05c0a961ac6da8a27151ec7220ab47cfcc356c5d49160c902a3bb6b523bcf1513139a87afd30ce027b742ea338e76c8dc13f5569a7559f3383b2809b4ed0c2e185bc8fb15b1a24b47af13ed41f62c89c1d9234e904718c07d0bcd5c59b962a12ba7441adc4e60240b9f36dc3c04c1920562c1d1008be5cd1fa34ce7fd5243838599bc3a034c9d02838b1b223408f2073a124a477e6e4333ed3df649f022696822531c8f67ea66026d5882c2206b3319a3bf5933349137df7204700d96dc669b2dd43029d09c1b32652513a30518145091a28255d1bb5f50c7911c856df9f4500d917cdde5b84a0ac4c90ea3c13609d8ea783bf9548af96bf10c28fc71533a9f74d62303d99f4ca8336c1dd8fccdef52bc6b239c378fd8f0193b4ac485af57455827b5127fa5b67675d7e505d643ddc5b00a8aa1b9ed28ee480a6bb9eae56d743b4ce174a4db7142ac9794965f4789d489325a03490d135cbb76c6855c4be8ac4b6ea59f729f6c1b32260882e25736d4b02f872e0a5c0084387bbd3b499b7e53b95af81d018e6aaf50265d3f5cf68979a12fa0b597172b180c0e2b99c54d11c1de59b0f3f95b1117f7be7b460d5240023e135bace39646f795db5e7a3f18320b1e0848a91273816ad40760851ead9fcaef6701cf41437bb9e9142a1cc5561368cda7282db0757d3015b09ce8375be759b316fa962c5039c566fad402d638e718fe87460812c01ef08c86416a41009bb7d1b12c5a49a2dc0adf7013130ed5896d3ffa209ddafcef146a632b87f57d7781a55c1fc67d37ab82d9af8e5df1305decd8886b19e044e8dcc55649e9e127c4207adb585b2e8ddf50d0a6ac9080a2a855ac7e36c0867473d17a415f92685c2c24659873a299f429562ca598e9ed4bc3ef6fea4eaf59d7bdccc594bea849d521f22579213a2f09f31b0d700da92b86b25298a763eb181dc1d98f12965f194068968a9530ae483a1c792f882cc9a3f5e6a3314061e83b8ea75d78c44f05d6cb97506b5cce8abe9fb7fff7ceda9a9eff831300582e9c81d9d5f6a248e76b885a8153a1612036d02a0dc6d80ff5ab5cad39e13cec8d5d7360c02e4ae55ef227ab9603d6e610af7420ae59109f184ce4a22828fc5546005a59e91f855c6005626d3e4d8543c02089a448b508e7d256ff4ad1b25a20700c04e8c4c9b30a497be776b79501dfcafe73cb2ab8d8e8de81a249f8e62c4c9e082f2e4b4597920a4bedcfed34e2317561b3f94439b96309c9a78a7493b828ebe277868ebde283c12fa44c2c72e9bfce1ce50b5d409b016618364dd49bbf2d3ac6e46dc9b7814e214ac789d16d33626066f084f2d5fbc042a1c33019ab5e438204b621dbb18bb2e0c5a74e3903ebbf1a0e7c42c0f02b564e4a05af16d631a9f54b344e24bdbc60282c925a98d190037206112cc460b07f35f9d02cd2e7e49c7e839394378213d4b47831253924259ebb3b92ba42a5cfe0b2518d54abf4d5145aef4995f3789ed8fb9a82efbcb988536a194b20a0414969afb23eb4ab29d10287a3061b156d3d770602a96da0ed357368c2c0f590acf834e8dc3673326f0f98c3a73046d358afc920efc865fcf6815fcfb6d8f0dd9140e995bdd8bffac904cc80b0d3211079c80a3dcf49facb54975a0958954f14d7b99f60dff75763b1036c8e6809c34c370e250b38da3763f8c88b4e53ece7a3b66bda64cc1694f4368c2f9b1f82ce5d9f0805bb0abbb6d6850e00e80b5c70924cb6c657fbc144f7ce9e805200638a255437f41f8ec660d084d93acaedd208ce845710895e89bc7ec6abd36885071c6429dabd7ca6332ebf18e02e1b5159f439a0d2347d09cbe831a454496fb3460b95cfe4cf02ebf26ac0df2944eb714aef3170a7661d71cf8c5edb07bf16fe50dceff618fef0689247831db6d4e1b3a61c62cb1e00c7570dd1652107252d40b219374f54590831d932dac205ab63907a67e3b9112a889272c6b435904b29fbceff59d1de1313a7920c4ef0fa3d10220b9f4ef03d612d045f8921426769db62221beb83af4eb9a17553fef0351c69af034e9c43ad57f545cfbebddbcdfcef552619fe5ea39ac377b6b7a7ace400938ddf38d24aa09ef07b7f0b5f1eede90032b548abfa7455384daa71f7ccf8fd5acac14fcf5ccbf3dd6b205d402d238a24a1e0f8a4c052bfe34d0516474057a7c0f4acf2073929e3408f2539dfb43b4f25f985f9527504d00870060b3dcf47555cb14e6c9737ed6608f7e0fc390de8de5f95ded7566d93cf29f2a82ddd82525763c4b06a8edf1a9aa850bcadcf4ef0931fc66c897498e9544b7eb0a4d0084b412200aed3b38b35936f15d2e09ecc240397a2c4f15582d7fb19905cf364827de568f219788f6c4112ad5380fb75a3475640f2f84256280c38c940788c99c2a64a30e499bd65afe2eddb87f3de420540b0588cb4f9ea2878a00e32b6249d5106a3cec2728e74a970c7fd35d26b334cbc80c90ae3e88ae173789ede170c2f4dd2b6e65c42b38422ba4780170bfe2240fce119789982fa8015661f904e00b4a6444ecd04ee3bd0f4d458dfcfeeea1ac2ff5b0254ec9ccb709249d15c6121da7fda48288327b274bcecb834c8ec8b4c79e60da1f8eeef813b742448b9d4dd338a3273be98bdbf0554e12113c1030b79c7c9373c50dfd8909ea464207bde15b896493d183b08a3c32480e3f4171f3c401a59097ef5fe1ce86b48ee59518db1e02c531c24049a3cfbf7277e9f0a370ecaf536fb5db7375d4fe3a14e07f9a1e600e9d6b68933ade898d9274ee3556a68930aa12200ad53513f28aef70918d957a5f616039ad6510b3629908fdea438b39549e528ac492c86517530756f204dca6908e8c48670cae77174096d39e807f4bb37a9b525d914bf3a27d89424ab4813481c43cb9319baf57a3f82e43c348da5eda8be7b0b79bb704243aa53001a7ae0f9bf0581be2a0d76de708f74c505f1072fbe1297ea38b621de7682e25b468970067c606c43d39428a363bd4b2d517734aa99059674c15fae44626b54e59ea5ead7aaefe6615c3f890a41f5af08a0023b371bfd2b78bfb8effcf9ad01a89ae599098c818188f8e659661f4f679a99780924be5f1e09df000fd43dd196d7543c51f3a4753dcb5e6010c063b327defd312b1a86691c72274ff48b5b45de49aea08867c4b2e1a0e4260803725cb869732105a5c33a41c04ae0a9d49c5cf08a0e9f3eb99d0d565e8373de16492e2dc5c9bda9f7a7a4f2bb5068016c7da8b98a7f55df32f3acfcd22732b467683a85bc71a8dfd50b6c97bedf9812c511578d4af0973b5b205618d00496865961213bf375abcaca94256b84c94057d99b7d2f7416cf0073d1a25e9dfc87da8fcd6bace4353714626371a93ef521a383b542b65cb0510886ff5240552bbc082c2d39c8cf5aaaf07a0870b1f9a2de1f9b808e827b76a5aed4751c16dde25976cad1d7e21efe1f0d92fd33e624a0e86789adeafe5e012e23e5224d18bad1f05b17304defdb12e14ebf950d9a6e8a9fff309afd9e669f1683830a420128e0e56ffad5bfd63de8d70b1587119644acb49f92ff5ee166d0ddefdf5073a389cec7d27906affd6700d0d3c49111789e204566607a1019e900e5b924490704af91542e00bc413c2981879716106745ca4a4055ea654ac8502ca1bdccc0d8cbc8b35ec6c8a98c844bfde6719189652c3b26d3f3cab0314a2a1379522d3463b493922dd872e153389cae7b8248fd342ff530c857097c0500c476e45444bb096f197a81756d96a289c396fe609cf07e804478271c0143bec10c3d8416ca7a0924535d048d430d3ee4eabd16db2ae811dc10fe95c362a475cf4139b089f83a44265c08500f0510d60f45117c06b688be1af220bc955e2900faa4f680f1138a5632197a198fde2a0604ee701679b752b968332657299004f43f9aaaa4f13158f16d0e6a6ce9d6d9ff2b2c0b638c4f2e7d40edddc1e2c43d92e6ed3635150aa94639c592f889651554477ecd5d27835d504362f91fe3c30cc438ce675b42250a730cb4b01d96cb7614482b56cfbf2a49782568199588917a93d2124eab9af96be01a3ee79e099df0fc5cd12980fa7233a8895a617fd36dd8566ebfe9c0bf5da6897aa855fbb3c2e9352b2dcbba985244608653baef57d763c6bb9bddccaac17652caacc8a783eef8d953dfa0b6cf8232840f994bb4a8dd495d7a236031f484856de63b0478c459bc4c1a24975f61993178ef5608d6f8a88fa381164a77df004bad145ac3b5035d66006d58fe10fc0c5168297c82569e361737bab900295b971dbf257ffba63e6bad79d14fd3ec5997cde17aca4e54a4533bef2ca613fd424b735f0f3ad7ec6a01858f1ea6583552391b2809c670f7d5a7785d64cd92729d326126f1acc30065366e3273f86e7d6bd454b84cb09f8143647f0a42c5a29edf38d7c115ec7b0936e55633d651c92178e96e575b494069319589573274de136764c348d1968f3b91a4876ada08a759de9554f829050ab5fb392fc7e61841b67bd1c115f6b6a2e9427ee31043c8495b45800953f1a06b10ffc5a071eb2261c8e2600e019cf0ebef4d8a001d087985ba2fae844f72ab5d123504288d6e5ff4af2bae460a39c32c676d69c080bddb442a2676f946d42e1b43060c6dcd165d079b5279edee8e0d36821fa4a749443913db2626b7c0dd6feea125a32d3f63e0586748730360f41d00cbe2705740b9a597baeb768410490040b9391a0a38c1d2c0f29f78a8d8a279f9aa2983029062988c6e28ee1c69556a54057d0c40821724e232f471eb68cb0038c7287b993a067790bafe3c2087827a7210dac1d40089623869633757689b1c05b214958dbb236339168af33eff0b7b4c0c39c13ce86a3d37cbb87f5578ace44463e71fa3b918a4d71b6bcc3936b922b168050186633363dd017668c3317f2cf7aa2a94b0641e1665ebd05a50f92a89dcb880d8b641991604ecb17309d37e28d10818a139dbd0adbe46d4ad94a2f446888d8148c62887990b6ca73036caf6a502e5dc35fa3dcec7fea762b28e2fb562d1c2ec069c9b0c263bf086428743342cf56d05029da19fac862564ee0807020f84f07142199c5a550e53049d3cbae44834de7a37380e5235a9c7f2f4cf4575c80613b2c3515f44aefeea2687bba65c05d1e1d07ebad8b1cf279818b190be371bbd6dac364acc6834466e8c726704af915ddd683312adb38bbf916246a0317a63d4dc693487f4768e9247558cb4830945711c99ae9ef90601405f716c7d68a4a2a980d3bfbb87b47b47849f7892f437c600d302c40ae3048e24ca58a8e19f479aeebac1177674ec51a41fbbd574d95f6dd85563699b9470571cc04108ab4aab19f0b940c8d89f4e95d40e31331cb0803b4334dff8aa32c6c79171d7bcc5e530e9fdb585ff77d581bf19fb0ad2e2e96c97c104c09128c8827970949277a3e9dbccd20714e482ef4ee8940cb70496614b1898294ca6cf780665272b526b01070758aba9512d43ec6fb10e23f3eff261690a8fd78db9bda6db6fc1ef445bcadaef1d85e0c0e4e1b5b2bd69386783dfdc9a4e60470f52e7038cf7fcd423679e543be7884b2e6914582591d1d70ce02378a3ab7e84c42af6f37614a20161cd93fc4122c68a886d2577c8aae786a2c2087175a63d712495d6f60293228398f42251222125122084a54d0202bfff8795f2b9192e39395baf9f6a4296b783a4b79032bc69ba21f723d99a0fcaf50492edd6ef60a61bdf24f16e9638b26ae37c5cde38f01a68249e8c1055382e9734b37123f18db1ba263f320af2348643c9a101ca48bf2325c55c7e83182a9d430a78729146db591242f807bfcbb993fbc05c0bbd743423161045fec6e333e0e10e63e93fdbb408865c6a02e695bdd06a17082da395611065b5b09a4a0bfdeeca501f7ef5a0aa91b83889cad104aea3c578d9d9ceebf38530949c5ef7bad02b5f1773552f6843e4acbdb5a01e782957c9a7267938799a8e51f06d993af6cad5f19deb748144713b6a99c4571642ac9a0e0a3f6e5baf2041ad9f86d54fbc21fa9c3e1d895c73c52604b55165f9cc2c66aaa08e8ccdfc4b7541ce6710e06aa87b7abd72ca6ac0bcdf39900cecef687bff19e2d6016e78d9b7abb12718de85a2e6342a8ac788d994d3f22c30844188ac850e95c41f1d74ae96b70439616150c79446fe68034e87bfa3a9939ba92ab822e80b0d08130418214a5c62b69485468b05d6ac71b9294853af9271c1236f9f013348cdb415fc4e44821cb872a7a0ebca6aff479589906fe3d997d7a1088501e190f337043b253509b017ab9014649899b33079303e0337f168166ce13ecb0f47ad0d7380fb13b63187b601aa9870a4326531906f504e2f5b93b7dbb819769988a6eb34913e76fc65dafaaa3082a58b5ee4c0cfc4d69d658a7ae20054bbd09323e1dfc3d6636ae0e92fc252e1bdcca9dce587861297e0234fd605a54e2feaf6e48e031f3a34bb84bf869a84c77da85a445c6262942cd5a76287d339a6b4969615a0e03d3f82fc0b05e5b26e24fcfe1e0668e9a69796d8dcf93418cd5375c5e96a8ab60e4e4fd8630cd3f552e302fabe7c8e5da98f9cbc335afa5ea666218b40ccb15b02a34df07226de58b214fb048256545987cc94c75e55b66329b8615130f933b50bcd91731c3871730935e4fc2d66bdf8018d2b07932b89a2ed0b6156d7a2e3e471eb36843ed08b8ff4eee3e8f5c7e7105a3f487580d84b1fb277fe582315a4259aa11fb55783ac51811aca99a110ebbd1f37d5db03139e1120af568e7e82174d19c9922fbb779bd676baeeaeb1d3dce211df39bb7acca4b2092115e0d37c567ec50bc108823eaaf53cc44143ed99df5e4c9820174f32373cb5382841519c4c30f141405de72ce88ad31a34e8b02acba0e5ec090501b1fa6f28e301a6aaff2a8392ab219dec6d301198ae0d4d76a7aa340bfb103fc4ff1b6d059ce88b3dff32a269c6a2598d8e2debf1bc3dfe59b373465d7fbe987129c81ca270b1aba90aa3cfa7b6e421ffc53a18e85a19ec51b414dbab02da4b853862522626bed30c7013bb2830aa5b6bf8eb4ac5442040026089f34854f6c676475452fa0f5d213f5112625406a489407dcc1b93f35f0f1ee15bf9b6c60843d406e02577f7a2d071ed421258a9d9f12ede94d8eec9f05e010ce2cebda9ef5a09792a14f4b298fe52a8217bf8bcac6b176cfdf17ef4d86504409763f913b31518b341887207b059807499780a81b972b09ba1ed42626f4f31307b285651a50b02800e043d4649526f5bb6ca59710f8e0da88f96af4421d057d27fa37ff171dc52b3d16cb14b8c352a7d2f82d8fca00c491c22322e08cb68a34938f4dc9cf3488ca13da33a417846ad94d77493132d6d0869a42dda6c0b9f9cc4752d1912e24baba8c5c115cad1280a98fb124723a22748e9125cd7083f1a3b1a287a179586d64091869a39f524c31b441e5506dd86512b5b85262fe7378a909dde2a4e803284d2095a918cd79c409fee269531aea5200239b61b54c62a3b867346d22a6326d48bd2fe3b9a69bc262ab8406640e5e8ec11c6fa8a75c9724b6d2cfe5c29d0dbdcada68ca79508468493c4ce590ae45504de4c9da62b9c8c42757a89d18b188a77d450bf292e666fd4ad8f2eb011075838894cedbb4160e06a4bb9174acfb6d1e713973d287ddef3650ac1ccb400d58075f703bc2e5d7f75a2dfa444b12e97088b6cd493af06c070987850bde59178c547ca2c11885079a46cadbaf43e34d80841e6f93cccdbfe61f1590266d3498e9d1f448e95e5cacfb13fda993aa4137b078e74e18ee4ec792b8f6963bc7cee78e88fec54ddd0c95e82033a73f773c2d7f190a5b50acb48202f22ce715774740790ef23e21822297a24c35d45c59a6e11cfadd664341051dcf57b589ea478f6bd484d17cfedf31820789b89156eb3abb3f79aca08158cf9cb89ca545cb26c54f135334ad796593a54d9d3d6822796ca823cdcc159604856813aa18eda39b9c8c61d4642e208081fd3242aaa0ee53dc76f8ce66b0ac67b702770b43a81f056110e95b8774420460670982336188a85ad1139668d0c6aefdfa9c5507f5556acab35bdceec4f3dd447a0945b1e658262a5233aae3c3355093ab2d6c134ac3d934ca61c8559e73e434c394ed3833e52face85ffa36fbdb1f2dcf733b83f57f07c075ced23d002e2f65ff20b1c64be088b525672beb4da76b03fbe21ab8eead0cfea589d8cdd214d5857778a5f26ce711ddbd15c67d3a44a421116552819179666e6fd32d8b9fb39c19a1309042a772936fc319974333ad2e91c92c4ae35468a71298d5b524219494c4cc79fc21006ddb96011d66f13f7faaac23e7c980db2b431a9f1a27b119c23ba343706c9c8ca48d864048bde25ec99821d3f6bd9c914ef51aad4211b47e5d71675487946568aae229e336d3bc5822627b26466d86d0ee2927db7eb82eebc5de40a1a1be1b49544c56f4a3c1f11088cc440ccd4599bacca5b0edf810edf35f2ccd6c124048c45aee43a918726c3b2e55808dd6846ec9617b1c81faa9d2c01f7417195c7d93d75096b43958ced01c0ef3ede5d3baed3751586206c544dce0bb13612e5ffd7799db4374182467a8ef3291df8151daa137987e77f2d9b207e2487ae7e6bcee0ad5da8131dda0b701e8dde0e6b9080fcca9ce1a15da953bac08ede492cc83537acd298953a8ff2e45b1eb25546227ff4aa250caeabc8539c209323376ceb12e8ccad3b498bfb6599a80ca78b001e148ddb55713b84bc132680747e842bf36359d577723a761174c0ba9f6a48988aed63dea85deb266671babf31a7d1c63017b20ab1f1a733aab10b1ecb3f41fcd1b5c1e909dfbb433a739772c047f05ad2b046188a3d8805899b29137d8fcf0731c2551815bf29bdaa158d6d15b050c15cbae07684fa82110c9952f97f387f66d0f4589663a8647628666419a9b14932d1f8ac5189ff1011bdd1ff414f630534a1028e6104420b3a50f0a4d001f3ffffffffffff0cf363c1c7cbb1db6ee2fb55882899922c95759595620428a594a44c29a96d20d6460821b0d71df94e0f033150026c0b320b7f0bc9e1e35488b7ae384a5c71aa2ed78ff225ad68748c7f7926332bdf6445fbea95c40e4afb89fd2a7a4b26f2c47cf22f5413022f3c4083024ef050455b92921f73cd732a69928a434539451793ec9ec49524fb25b9313c4cd19fe6e51d39ba94dc68297a939d3948133a677890a2132d7b9097d43498368ac63f4f4fcc96f4f9e739f010459f7f26cb62f50845a3a59b623a5e09efb31634780d30283a31514c09ebd54f16fd4497ddaee1f43fa6b8a58727fafe9c7c2de692190d2d3680048f4e74c2a36aa5acfd557ae544973f9b3ce25e4a9229e3b1893e8cce1fc34aead3d369a20b171ad2c4b24c51cb44d7964c4c765a26b9429868c6672b85f9be26b944e7b9165f4dd8cf8d134b741d1e735af839c1532ad14972f7c6c5a8bfa95b4af423c753923da732f593e8b44d8cccf2a91b36e92189b6e36514b7202b948a7b4422935429593a9a7f370889de826cb6244a7c66703d1ef1c767505eb94de3884e4a9364d1990da30b1b65d7a3119d1c4a98923327d961a211351b384e190e09e0c083117d4e52ecf4e0a5f74b4b038f45341bc3bfe9939358b19228a21393ae98989c92887675e5e49127694c551951ebe215118dccbc26564de5108d6acb92e4249774ebc8c3107d07352909cd511db25388634ce2a42852820721ba92a48a499a9efca8271e83687c4c8cce2f49383c048169ddd560aa9967e213a8c07a04a2598d667246cc46531120daa0b35c09cd258a7e923fb46bdab21fdacf5135a5f0a224f19b5d7af4a14d428bce312d175394f9d0ce960ea67e262a364e0e2ede3df6d067530b3225a16e1ec41e7a68332c6b5ef37c181e79e8e4080fcf1e4b449424236a36bcd8a2059fe4b871030c1174711e8c1c383a80021b30f0c0430c3cee80353cecd0574acd1d27fa040b7d1dfaea68a14ad2984fd679d0a1cd521e46996a791264ee8bd3051a1278cca12f51367f29512b579ee5d065fe595c0fa6ab44d7230e5dc9e6af96a1e46cd203873628495241e7da4399e6f186367edecea0621025f575436b62d8981178b4a14bcdeecd2d931294c0830dfd575f8e31b9383cd6a01e6a3069c8b7e2fbc9fdd1f9420434780da8954878a0e1cf2b9fe4d8a152ef65789cc13cccd06b92717ee5c3861c9947193a792d79c9ebb90719ba6aebfe1379160c788ca10bddf137c5f3c692b1181a6562286db96a26094d18da24f69fa7e43975bc0686becaa4c61c375fa6b4bed0fca768f1da3dc6ef510d0f2f587974c16a6cc0830b5daee72405f19cc716da0b3d97fd6476dc24ac852ea6e7bc65398ff60a8da8dd053cb2d08c8a39934105956451cdba4026f8828007163aeff3144d2fa749932960e4f8c2e30a8d7cbb9920dd3ba31721c377c720e4f47f333af76496b4b4eef5c95a6179312977681397d1892e9b5454d169ba4b556836ba89ba952862b924a3cd597373d99c330be3a042db49296db993a07398dc9dc714fa37e1e4d19a377e0ad28bc171c0430a8de5886cacdc8da8d930d8058f28b42aeb593ee7756c6d2042a1ef4e29a388af66783ca1eba463f288eb2f3de211b5a382c7188d12bb174f4768e784564c58cfeee221e27cce8347133ac147f4a98e267b541213da2a1545e47b9e704287078f25342a5912a49ebc182be54ae872279343b6346cd893d0888ffa392541a8aa92b43a7820a1312558125fae64f7b88ee071847399144b9239cfa3240c1c36d0c3085dca26651a36a60c1e45e894a0796da2852af9d9c483088d58117f264c7d83a2e0318446dc557474cb06c2438c3e671f21379a89a295d3850de4070f2174e2e2e7d8162a8610a507e306b2e11184b664135febbe5c923481d02651a252660e7afca0f13ffddafefba037a1c92fea95543925f1e801c2a29a242571f314c383079da4c43f7174aa78de6f153c76d0e73c913175a96e8bb9870e1a555238514f70f18ee32cbaf43dade699b35e672050597441eba725315e62d1088db9839652b27a34b0e85bc64ba89e3dab245ddc4039c2f000113a5ed169af78522c39ca2f74b8a2135dde273ac95bd1c91f9b49924950131dace873b55bfecbb544c72afaa0f2968eee191d84d8a18a4645483129496b5319f542472a1a5d517366b7aca2a24dcf9071f33b5d44c7299a519298d7142f3e8717e7b4e830452f23336617b10a0dd203414729facc69b2579538a2f65c6c3122031b3772d86052f4a76ea595c41877970b2ec2483a8ad647ac4b98d6d8d0408728ba9c428bdc34412dee35a286a360a023149daabc71f65f1f512b9b80260a8a4edc392d8d9f95b24c8a04782fe8f8441f3d7f8c166e31982a1951a341dac26f74b1617c71386065dce189def477ced75e7574a251b26f9245dce420ceece0449fc23dfab828a5326b36d1b79a78f72d7d9564d34287261a259aa4aa723651fa4d99e8a2be75994c3a4cb4dec9acd772eaca6a1d97685c338810954f87257ab7b832a77c4bce98eaa844eb23724d9b850660e4a044a7a1e3526a67c72ba9bdd13189d64d73ba25191f1afe11351b79c6830e49742558c93163124609471891e8620c7ab39592a36cd0bbc08b2d20d1570c8da9e2eb5cd6c8a0e3117d89ba9e4a271dbd53d7e1884e09a2b38e46b422774f8eda08f2228cc30586d1c188366ccc6f623ed6e47147d472742ca22bf9615a7e154de87ce6a14311fd680a3ea279d4943a12d1899c0d56e2d3e44b1f116d4a19b7b7ca6396890fd1e7142fc5fee467c28b637418a293ca2de3894cf2434721fa7d57cf7fbd26a849da4307215ad9dcda39f274cb890ea2cf8f6ddab1748cdd8c20fa11d791259f2f36c83a02d1c96e9d1d641e01a2ad8e62f98396db7e41b56e1d7ee863f6605236ef30afaaa30f8d34d94c72bf468db22074f0a1cf5dca4a5fb88ca855eea193b4a44cd144e79ab8e5c0e1c507364083023428400113802874e8e1ec13d394f4c47e72440d470e2e3af2801d78b88e3bf4154449a967c451bac30ecd55129412a5256b30dd881a1860bc8d2f4e17ca961d75c00e3a349734f4292d2b9b1f46ff8508e6d08652727d727e6eeec58d2f703c187a810e3934ba2ab6484bd12ea664448d47d011874689c9772b07fd39530b87368b9698ee9794cc71c71bba0a3afa06a995ef220c1c491838ca073adcd06bef6eb9776d683fd3a46462348da8ddc8c1863efb644949b8b96bae8ca83d186534b4d8008d2e9009cc6da0630d6daaf294459e92e5e48a1a1a15b149105b722ee93169e82b74640ead513ee6110d6da7768952b27686d635346cf20bf3fa9aa18d25a81ca23f6e0e298aa0a30c9d101a4a46d3ca2b297a460719fa929929c518e2885a7a306ce4b83134bae5ef7339e3f957cae81043d731285132c90cf2dcd2858e30a8f12499b7f47d30b4a5f955a949fe85ce4d66d09f9e1e26222f7499a992a42ee26418255de89390d6a3ff2d51e8e0427b49d23e72d72ab676980a1d5be8674ed69ecd7517f768a18dfd1c2d93258931aa53e8c842a3e2e68ec94344088fc142a3bfbfe3e71872415bae601d67f4d9cb941c4376c9316a46e9b0429f4cc65a864f49f42d14424719ed6893c49fef862cf1ea404715dad15229c9174ab4a04125a3d78b7f11bf202a74496e53c25f2d9720ee143abd99fd9468540aadc97773ef9c4a3f260a9d18b447bfc8d22782421f3ec6968d6d312b884fe8543c8ece616745ac6342c7188d0e4ab4f2e8c8096d0acda4d33247dddd9ad06b4e82a51cee2255e50e26f49f63788cbf9425742ca137934c7c7658097d10939be3726ce53993d0cc09ff9311e741e63b90d0ce9eecb9d283eb5736c7e33824741ca1133f9b8476152d2abd0e23f42756e1a79e17a1b54e9d530a7a2b25b941a1830889a6f034d3103a252d798bc82c792e2f465f69659e354d6ad4601c4ee81042df67325cb849e24518d811843e6c472f939d748fd27e66a003089ae68e5929a724173a7ee0858c2509baff5964860e1f3c5726997096d42c6727868e1e9892ef85d26ca18307e8fecc1cb5d584edc2d0b1834d44f95b084da2092aa8860e1d5c927e49bdde494c8ca959acdd41e9e934b93424401656a656b97c8d8985ae41ae09e559799f521d65457362c8b23e219bf9aa55a42a0a482a1abd5c9e61c387decba3a21f4d4ae7ac64e9a534a7684f89793fa1e4cd99d114cd09a3712e9e20964fcc162f28340029456b4afea0a2244f626225456f3d4a84a7f828dad112cb57c33f596844d1c94d65e1d3c47cfcf17184a2eb4a7252bc8310f90a28da13cd9324439b3ed1981093f132c913ed9fbc965d9212436bbe135d1ecff0d91373a9ca39d175e8a4f7b326a1f1b489dedd92cc0e2a48136d4aee95c1b308b10e65a22bfd9a2f7fb43e9de460a2ddb76062ac835ce57c89ae5409baa2a728e24916c4126de5283a6a4969253a957392a0e2c40b723194e8c40c9f64ff3e51959f446ba1a34512adb799f6bf0af19f5222d15cf00c1e673d48b4df1a1ac3735c3c8fe8a4558f9279b464b58e6834261d62a93b758ab14658153436ca5b944b995d637a78ed94699d936c294634a36562aa08f5afac16d1695653294d64d6d2bf22fadce12465d595b1825022daf5ec71a35a0e22d0efcf497037e143344287131dab32cc255943f4a1e5377b5b7af84b0bd1fe2555153e2ab2354888e632975052104a06d1c8202afc55c9f433b120fa8e9526bc7d93f43e105d2999ba52549cf79801a20dbf1676a4870b65f93f7472ca96a0e2224b85d70f5d14d792241dd511351b340023471f7a4dd5dbea1504e143b35e5ac34f1234a2662347185f300e903df496fb42365af4d05cc59c5a3ae979683bc92b9d7d3b683ef70920786894b0f032b72063bb2403e40ead26490ccf97a3d173cc0e5d25d1619464d6a1cdbfda2a2aa7d57a3ab4e59da4961c5b4ce69c437ff154f82f5193496ee5d0752c49d41283360e6dcbbaa99854289dd21110383472924a2d39a6e46df21dc81b0c881bda12455b66753ed37440dad075f651ba73d20c4b4f0a206ce8f20825e61b2a3a9c6c0d7d9c855af56908206ae84bf82c7282eeb7b0be0c9034580da3021034809ca1b3348d7947c63e4bcdd04942559c2fa1a3ec094d005286c66298b78b2ae91e945bbce0200b40c8d0a61cc5749f9ab605253786ce7a4b0e9bb192ccd11c51ab13018818baf899041da49ccfa516240c5df8519a2f28693a4511040c05e40b6d869025c93ee293c937a2e65e6cf102dc0088179a0b6261fec4e4781c784702902e7426635e0b11ad26e86c0640b8d097145a52c94a3a597f205bb88392657e52c5a4a185058cd142bf49de189e6ed1008c1cbc02902c344aa87789673145b73e0c18d878b4450cc000c142631df76413747d2edc8b335201d302c8151a5941cc456bd1373929cfe82f49414c695a884a31bc0288196d8aedcdf224548919ef0c102b744226133589b0be94513340ca6874e65f93534e662a3dc98b2daad0294ff952c69caa4915848cb6b77ac4c9a525e3e7c500a142335a92b57cfc5c82a6d08949346c6b924ba111d9da1d554ca2d09a981d279e2458a7f440a1dd784286cbe4d1045d9fd0c6d7911fcf534e9dcf31daf4984a4f75e384cee289f13cf2b284199bd0afac888bce24766f8c09fd7b75ce1aae4d7c76e501c8123a499216379378f9dd644094d08eb99b143ee47427d50c1e8cff1c6c049024f441c73c84181d9baf81d841054b263ba223f4be79dcf2f3aee630ff00c40807176162490c174811fa8af9fb9db2648f0ed90084087da910d1417aae9f94e521342e2643be9f3461f20411a3139a4dbbe73b1021b469e209b265524082d0677459ad985227d59b2f4080d078decaa09745e88cce0fbad89a52985259a693d48882f8a02b399ea02907417a60354e00c2834e2893234ed041901db415260932378ca90c23880edaa056e5c14d5031ac8225f89845bf6162e9d11fd4c27459b495edf9a6ea25ac24b588c5b9657c3b9e4a3d72c1072cba4afa290795c41093a657746292a4c2cb7a989f912bba0a73625a4c92b4a295cb51f6041384ace461454afe549e5574baa6e384aaeaea12251faae8b7848999c306293acb5434964a3f47d912319d828ace9345973941778a4e3c539a260669c2c7ebc314cd95f0f8399812374ebe147dd2fe23297a37afa4f28b7cee98338a3eb86693379f0aa3492c8ac655a38ee70a8d216628f00314adc7d0f94f4c4a313e3ed1964922663f5e7695c713bdcfe554613a37059dec441b93ea4791eb161332d5830f4e741eb6e2280fd3a5a5db44fb9bfb844d37b1c99434d1bb8c2579dec5a4dc4d26fad1e549664f98e8040d7a52e44a9e927489ae4a5ff3c414f4f8ea96e8447453a79833b8fea812bd8993ac936928d15692a4ac8f4e77071f93e8c4a43fe6959ca04ccc1749344a7bdcfcb1e413d54f22d1560c13438930d13d2d24fad19bcd63e7f021a32a8fe844b383d09c23dafd3c5abb63a5117d6bfc8ed818c41b7c30a29d1d99c42fe1543e631f8be84783289d1573c9fbf9a18846a95fb854a2a79224d944342755c77e50aa41468c88469729a14d38a1d4337a0835450b1aeae11ba2ddcbd3ff54425caf5888b6b5728bb7589f94a21a351075f04188bea4245f5eeacd26840cf163109dc798b72bc90cb2922a88e6f4b25f9ed964f011884e0cbda4cf3da88a4a32a286f7800f4034d77bf22649ca233af2f187763f9824f75c5586f3fdd02695262799cdd25a611f3a9d849a4a92e09df1c1874ee8e5c5509d726bf8d84397e4ecee5973c42ac9f5d0753e0fbd1e457a8a9d8f3cf4a64c8f503a1eda783267e8c8d83c49ca1d3ad17c4eac8e129f42b4431fc424f18491a5546be3b9480e7af15187e682f0544929a99248d33fe8f0091e3d63fe9ca7e0630e5daa70c2648e693a5352173ee4d08fbccee817a744b5fa11875e47cc2429a778768e0d38b4155f2969b638b6e0c2c6e7d802ed0d7d4982548b61e639abbc67f87043e72763784d82dec1b8a16de8c4b9ced319dd19cc1c5163439bca622e69b5236a38c0b8f11f6be8e272897272dc8b1b5b24aaa14bc165459ee8172ce4236a8869e883923557ce9abcd5e4e28071833fd0d0688bf30de1d11b317830f2e30c9d92539e5bca49fc9c6c44cd1c0d2d2ca0850f33f4a9425c8887f498f3fc87c105f202036568d7938ca23d3787ca213274c27308253fe531b49e67bada5475534cc5d046b79cc2b53b09269861e874deb0267e3160e82f0799528be53ebed026517e296ba29b9c222ff4ae1fb484cdebad99b9327c74a12d1f2d252fe5123dcc5ce894a8a2e424092f154d088bf0b185f62491f1b94989b29ed4c261b406d9924fb2bc66a18f1363522d5996498bf881854ec9c1e74c1099a32dbb42a35292e1173a676f8f3ecee8d42a8c1c8bd1d4ccfa30a393fb9292e273f261853eb6c9a274fa69442d8c1b05bbf828a3377d9e24bf2c3b4ae32e4a073eaad009cfb9f4cb523849eced838cdebf455e8e12b939f7e26de058f7a29d8b306e8c38e2830a5d4c794ddc249814407c4ca16fefca194c506981175be4b84102c40f29f45962fe3515df4c62670c1f51e8af4cf70972949c7c4250e84d471dbf9265530ce227747193ae86feab80e1638cbec32bdb7212447f6cc5f0e184fc42c931dbb2633ba27657838f2698625b4a5a95629b1f4c68e7ac62b0304d32c667446d101f4be8f4c7e435cf520f1f4ae8722649c94108a131e9c58cf19184de43533ce75b6b8a93166c81e30d1f48e842c482ac94c2f6c5af458d1a1f47e837557fd411990f2334dff93f9418faa424c4647c544974bf8756c889d0484d6e490ea321f465490c716269eeaaf910a30b954f9a79d2635e3a21b4293263922f5b4a266a3e82d027a571e3534e46d40c57f001843e56f582a9a5244e92093e7ed0e60de6af9a171f74a9e414452525562cc87071e3c61736727c0b3e7ad0a72083fccef379d4b21f3ce833c7ae4eba9392f0b18356cd72902e32e70f1f3ae8b77fc3259d39579e860605683806b8b871a3468d597482e62e31fc9229152617060f5974260927e6b2c4e478ca8382472c1a75cf5164ca2529bf81c38b1b14a82bc303167da9f8ea26479fce1bf48a0e4912a3d524a8184344969518cc33d01042ef2146680e1dcdc30c42eb5926867a08195bbe116d5b020d20f4255a85c99c64c340e307583e1d973dc9711968f8a0d7a445496d312755a6079d9f6a4afedfa2949405010d1ef47b264a3f6e8c6c1234061a3b68e3c3a4f6d861ddaaa40328b0c1050d1df4399f9cf262ca9d679945e7a384c9794159744a867393ad319524feb6412416cd9ff61853624583c3c582400416f6afe8b2998955e5dccfeabba2cb3ed31da3855ad158c7145359473f5ccc8a32fce75d453f5e5e7252a5e9da5145bb3aa742778c9983482afab7ec16525b4445fb7332fee47f0a638a562c6a4ab9f272b6eadf20528a46851ed541af34aa0929fa0ebf31e9c88ca28f1f4d345d5ad1bd342e0e8a88a2577d4f9252923c14cd9e14bf1e11e7794940d17f4949fc92db6a92bc9fe883f40a5a7356e50c229ee8bdc49379b4096fd5398a9de847a6c5c939262f8870a22fcfc1fc7cf54d34deb99458269a96203f4d7471e1a3552e693974cc05914c34ab7e5a83ec94fd4a4e0434b4d8008d369805114c885ca2d112c683e8945ba257ed8fd1a27c2295e862b7888e4cca94aa54930825dadf58d9938cef243a39b8ac550eb22f06a9243a9d9abde19d740e3237069148f4fd5f2589215320d1a7b86f2abaa9b0577a4423279a142eb89520a7f217441cd1f86f8c9f6314688499e5f25793f02be1b8f181911c5b94600c1146343a4f12839594b466b0c020b2087ca4f5596a75cae2e7c0e1c516783b1051c49992909f17f5e5000d0ad0a040c1349144b49fcd4d8f5b8a884efc70d2452dcae8123b44ff2a6a42696fd10c1143b4ab23db256c5feffc85e82adea3c50a1d5df9b1820821dabc5e417ff0ccd2cc1944eb299a74d398c2ec8882e852d21e6547a6491d55205acb4f6295e8d513acb2148800a291eddb96e2490844fed0cce73831c79f9820e2874e92f9a49254764de9db1244fad08812ffa45e388fbd213eb41d450653c9f426eb581744f6d065d15672b45a44f4d06735b790333a9b8fd0881a92219287d6e4be98143e5f886124657ec0d0e24c0a227868736e5052ccd5c1f1c51639c2207287563e84c5142c45c40e9dde30f12dc91e5639c482481dda6cf95b35c9e1acca17a14363717536891a2e98c944e6d0258d9b4754127c4c2a816107113974a9c433b5e78467f14a8e3a3788c4a12d4989b7e97e9ede92082270b0aa2fac34991c2188bca11332c50aaa4c4ca1e48a1bda9c525072b64bca797e9136344ab9c8df59d34a840d57c68bba5890f714cf7820b2864e18d18d26c51c6a9db9000e1abc068620a286464e7bc37c09be255a9134f425f698b4ca150ad0c040182322b0408a2182864ef2ec39ab323d3c2339b690c1191a119654fe0a273f97de861b5e41c40c6dc9faf265c24a4e164a6cd4e510018edf22c7165fe098408e19748d1a3966f0501029c38de40506284081068890610c2262608048186c6cf185043ee0c58d2d3e44c0b0c5171278e4c58d0e2440e40b0510f1828d2dbe90c001230c091840a40b0f22c2051b1e225bb0b1c517122881074044b4f02d68c1d1a2012259c081051c1f22573880c81936102062c60044ac6000913208205205018890d12541e9a07fb4a6072254e832432f9e4ccf31e7e4380f06ca3183f681c814fa9435caa5ae9c238848a1ff1295d7fb6114dad3ec9d929656509e1481421f2ba4faa8694fe4097d25419488f94ea6637a2263b43e1a221e643c294f4ac409ed497e217e614974ca8934a130a1882ca1f9cf4c4166970e2e1f1125b41bf39ee5ae8966728048123add29bf58f21711dea7f31b30b8394490d09ad0d59139968ed08972829632f1b22a4146e8541273789333ad3c39456846acf36651e2091f12a131dffcfd299426492a87d09634a1836f381d272a2262a4a3eea9282b958810b6c6ca402408270204911f34fa24a14b7f88f9aaee832e731267339f244910e9417b7951546bf8cc9a771ef4f1e7e4ee89b1cdb5dd41a7152a7f29132b68f8ee4474d06fcc9f5435ac24d16dc82c3a29e9294dd3b34264d15f05d511d17b2c1a5d694aa624273193feb0684dbe14a2b15f41dbe4155d8a41941493c6eaa027ae38db83924b8c65ae155d50b29a6c913935851056344a4ce91a624a2ecb9d85aca2cf7b4946099f3457bc901321aae82cc9cb73629fa426be4d84a4a2cbb578a6164ab35370442ddd58eb02cdc004d80114d80000244250e10831291d51b391e371d8ed293a4d3209a255d1a3867344adee4cd185922abe26774a61558b10d9a599388490a2959f739394c5cb194fa3e8a4aac70e11ba28da8cb9f9bc94a0503442a610fd215f50f4792be7cac57b44c34fb49b3756fc688e1b423cd1ee280b426c6cae923a9d68e3f6494a7cd37d0bbc3821204308275ad124c7f8cb55398bbe893e5aea8a1dfc4b6ef0d610a289ae4cd0372413ed0919a724f19e31a10fc1443b4a860f99a57955cb904b34a741459f6f50c25c7586104b74e2c9bd5bc32bb7fb2195784574f73fc72c84127d98f135cd73dd0f79127d895aa23be5d013af378448a2f9d8cefb2b1ab2d547a2cbf9213c7acc861048f4bee69ad43a8917421ed1660bbe59a39eaaf87c0b218ee8e4b0f3dd31880b218de84576094d72fc669fc788462993a6f1645229cc08842ca22de51ecd628a5f522a4411cdbffa6c5099b19ceb174212d1b6650ba3722c1937280d118288e65c3f7c49a26593e8107d450da1b22d28a54f43f47e294c887a5cbb9814a28dd5e2214e1226f77708d19c79cea96e31be85a8468d1a35e4103288aea44972085dd5cba011449be49bc7301fcb2ca9184202d16555ce5f4bfd93a207884ed6b8b9cc6384a8a03ff4a34a6e18e287ce3a6710f2c48f1e42fad0e9292fdd79acb49b9e8b83e3c6175508e143bbd59d576290d94323f4a74a29e7247ae8ad4ae736714cf2d0774ca9abdd7d3942081e7a0b3adb535ab6b23eef0a2177e8949cd9d17df2465d133b343b42f5e6d268481dfa787d39e82d9d0e7dc79474d22ca339f4a259a2a7a5c5364f0991436bfa635945a49a9cc32808894373924ee1458e3061650f814333b2b54de739d1947c0979436ffe26446ba942dcd05912fe9977651784b4a193429fa8a9f134a276c33706216c48eeb829c5cbac4ac81a9a912b72953763e9dc4f1d0d2d2c70002842881ada14da9238f5135cf34a436b959ab584af1067a62284a0a10fd57d49b6b0ec29e5cd8c903374a282688cc94a66684fffab4b5d4b5b8bac105286367f34757bf9b66c0e199a4b3ae94d82321943676143e9782ae69854434688183a133ec920740efa4048183a29c99d63948f7f82102f1342c0d0495245c69379857ca16d1d558b7baebdc91a51bb198478a1cd1f55b9728b9491814148171a1983c5a0e3ee9f786e8e6f0117da6ca9939ff20f1521763fd645c8167a6bad8abf164e670d7281bcf862be08d1421f4bdc0e3dd945c46934b4b04017373850a38608b0142159e8844c8265c7de4e41a74a08c1425f7d2573eaf58cc6fe0a7debe9b9c876cfe865d375cd4ca9a7960b0e31a30faf986485de4d36d3b322f38295cae83f787ed42b95a43cbf0abd56868bf2f029967732da510db2aa43c64cee54e8f3c40ea20431a2933f85e6521254501349a13f31c971347b124b72a3d08af63c172e080a6d7e8e8ed379748c167a423baf16d563768cded2ff3acfbc096e3aa1df3171b9f583fc6e9ad0891e9494a78209135a7d51929ce269095d8c8a239fe28fcfe628a10db9dc92b4e52c3b27a179f7d4dfe12bcdc24542eb561e7ec3ac47683f29c1244189aa11da60263b4719313a4c2d429f04d3184af8dfee7c12a1775fcbae1d7e2d647208cdc5943349933787d888d1c74c5925d6a7ab624608fd493987f038a953cc4c10da92bb72cae80508ed86c9f120ad645c4cf9419749cc151fb4a33149f13ffe727e7bd0c71293d049bc985be6416bb2c757ad4c9ec4dc417f4ae4ad744ed29a61880e7a2db93c8ee885e9d22c1acb2ff1972668de912cfab378c2f2799fa0af8b455f9e3525293b335b82459bfcf2cc3794eecaf68aae72d025fa5b92c433b9a28f673ac64b35d1ddb6a29f8f1eae5de8bd82aa3ca77410d7e1429f9e644f6e1ccb116fa153e2e74d93da3fd4d542a7992785e9491ab5cd42dfdd1e232ec6faa358e894a678498fa76c62f40abdfcc9a0f2c84e7e9633bad4a434c8b8161dd18c4ee7e4b12b6a857e4f30294cc5c57f57466b2977eaf3cf415fab42bf41e538199d56678e39c5a9d026c1620c32ee28e5f914fa4cb2c9f9662d964752e8a4249796b9478a9644a17993c398a472a0d0c73ca9c4247fbf49394f68b7434bd8ea3451dd317af7531ed38290f9d5095d580f6b2536a1379d4d2f912e6662421f347b4ac14b52a26896d0271dbb34f6f24a68b4b6ecc714fc24f4a1b2fcd3e40a21b44742279c5842cae6943f4b476863e5942a3fee780c324297493cddac996735a808ad88cd732d9fb46f88085d5fe60fefd21da1b38021349e4d3b778ce133092f408c3e34aea74aa1a74549de610142e89450be417b38086dc8139bf2e7706d1508ad896d51a234eac9f983d6d37ab7947042631ff4fbe1a76292a4ad353de8376ccefb67a682090f9ad3d952c9b7eca0534d8257ccb1f2ccf90274d06b926557c02c5ab520b6bb3fe5a3e60a90459fc5e5425914efa80262d15c5f09b2c41613b47205c0a231e916374952cc19f44801afe8672e94c9a932860ad31914e08a3e4d8e7e39a5a44ba55c4905b4a2b3307256b45dc2b5843949d5b48a54b4892a1a15b52fe56ad14f722afa331ffd37f1991da3a2cb983f4f96ec29ba1e13d5c2ea96ca5953b42d72435a92a252f4e69ee409d19ec43c1129fa1fcbf193ec23474e348a4e0cfa56495f26f9bdc43d284014fd8a1213c3c2a518cb50f4999396a689f961048af3f39fb0fb9a4f349b829c12224f74622729bc5f578e0b5127fad81f45c9a34cf2f510271296addb44af9ad2941679a2938634d1864fd12a29738b194399e8d5e35b0c9ae413368530d17f3e3d5da2648ea54bb4f33ab34998f6584996687393494d3ff1a4972ad12625c36490254faf44897eadf7b4849e3ef19f44a3f2a6443f13f3775e12ad26b9ec31dd631c3f12a700487461b1e27a831ed16a0e2346e5fcb962c811bd895f3963e71cca4a1ad19fb09b5b42cb88664dc972f2675209ed221a1125a724279fa90952548022ba98538f4ecb54e2a889e87489a133cf72644a22a2175dae169f4baf6c0ed1c8d112f54f1eef7c490cd1694b515c4736098f4d01856865f62b73e55813bb84106d2c99b1262337c5960ca2d31fa76d5de2adad44106d92c47b7613cf93ac9240b4c9ac933ecb8d9b55028836fc778a71f592b0f81fdaf13c173406f9a151a164a8d29774dc247d68f48caa08cb263ee6f0a1ad9872890f1f4f92b487f63c35a89a9c4c88f4d09b8e53e9a17b7ee6a15739492cbf180f9dffebca5e7b8736ee75a69c6487f6c49cb9bb3545d16a1d1add723a68d179f743874e66c8b06c829705e7d026ffb27025979f54caa10f4ae5dd0bf72053260e9d205ac793ae9282bcc0a115eb395941e834cb9d37744aa49af896dcd049d3e559e5d4863e2c636bc59e0d6dccf134d7c486f3f81a3af1e4901afa303105dd2e4943f326bac5acb12cae040ded289ddad99fa113c74498e55b9273ccd028b12b640ac293249f32f4c1ca24fd8f27d4c264e8754ccf4548c7d06affc7119e189a4d82c73e31260c9d6ecd6ea26486150d83a1abf8972f7449cc29426974f7307aa11f59eda7fb2f97b875a13f95c37f25b933c81473a18f9a4d65af4a29a62df4a32a5ceacc5a68b7afba4d6cb3d08552f91fa239163a9da62b537f1413d5bd42a3e926f794a87a3add339a750f9a336fcc684cf620433e970a2163854effa66cd61a746ccd96d1a90c72bd29b35c53b60a7d38372522ab264eb864742ac5f211a215a2dd52a19165622aabfe673e4da1d3ec592eab5676c94ba1994de24984c80fa247a1cfcf9b356f97968ba0d058cc7934c87b56113da1ef9354b789ec50fd8ed1aa6879a92464a9983aa18bbabb6a427be3cf2634fe3b97ad2613fa4c37d35f39df622ea1bdf29cd1c398ccb2514223830cb2f3750a699924f429ab93984a4442273ba9e63349124e353d4217835730d360962da6466864922aa64c4945684b87bef24a194ff449843ef352c7d21f425b42740ebdc15cc48918bd75329317235bc442e837a5783ac5937b150d42ab3d9b43e6dc5e420984564788cc97ce399e7ed09cef6578ca9cd0d107cda8e91ffdb0e0b9eb412bb27e62522a6bc6f0a04b25832ebdf3d9a3e50e7aebe819b753c59c490ad041a3e449118f7f165d92171b4ecc4eaa9745d739224cc409e115148bc6fc7d3bf72541438645a3278926ce29eda4dd577422ab5274ecd117e43ba266a3ca6868b1011a872348020d57f4eeaff1f262f2724d2b3a357d4246cf537d29ace863d672c68bf8909555580da4a18a46e6c25452522e4d4a457b9a848b1d25272142459b4fd0293fde293a4198247f53c8f8ec4cd19e75cee5ee3c974bd1c88b25ebff491321165234d264ff7892a3e84b26f953cad933c999281acfffe14c190aabd1050d5074e656c104ef139da5ff991253fc4e95f144bba193fc13349d68f762c48976b4e86ef2249b68d6b3cb458592734d34d165c668927332d129dd3116ccf2b506136d924faac5932ddfe34bb4b1257c282586ffbc251a9d7193bb62ee936f25baeedf3c49126745a744bfeedfb12be6205e33894e994951e3e2e452424982ab565c5089445f959488d0f0150f241aa5d55acb643c87b13ca27d3579f7cc56b2f23138cf45b9326838a2f72032f75a68cb229646742642c51815f117bac288d604a19412ed93dfaab2887e4764d04b327f2c254534ba74d27ac14f32e5398d44f426f9ff8f85d0317244b4497643ace410ada96cc68b31490bad213a8bc947e72ddf70b285e834e813b1f9cb3b5742749278b953eb6f3406d18593a953d85210adebae67509e3af440342a88d02c1f2db86c00d12699329bcc9b529573fed00915c3c6963c41957ee854e69225584a1fbaa4524ed5257ce8f79238f9c3a7c70bf7d0c7e855e7b81eda91b1b393874664ee4b69727868e46249df570fbd31bcc3aadda9fd5aa11d7a5161c6a3c6ca494a75e82b73896e3dbfdf263a349b82d05319333af773e84c8eaa7f49b67eece5d0e9e87859ba2d2fc82f0e5d8edef89444eb3f250787de4b92e1c9476e12a77d4327c224c14c36ae37c9d170432707d3240997a6a4181f8d36f4b9e43839570ea6a69369a0c186be54ee85d031bfa5b986764d87cf144d7f37a9864e708d39cfc7ef1463d2d0c54e3121fe6de284686846cf2ffe3f439ffe4997a43b08a5638636f9e666ea12e76f19ba7057d3253c6f7f47867653e5accadd185aef203f26214f148f89a19372f2c94cb130f449d8a0e5cc357c5b07864e935242769abed0c5544b96bbf74227e51f994b0e324ba6d585f684ce73315c4ebe880bbd5ccef3de4c4afc2d343a76c6ef33d1421bbb93263f9d2c347f4a8f4e3163a14f935a623011a2e5bd42efbb9d2dba67f465c2e7dd93191fae19fdbb88578c664bd30a8d36152ff9a5657471af476436abd0f7c87219999a5a1a32baa4f753902f0d2ab47f26322694a6d0ee69ccab3b9e458452e8fabc2bba49d13bd088421faae44aac5cf24484422b5ae4e6cbf84d3a674fe863c79262f54b4f7736462fa3c2b5c5ce9cd0f89ecc5c4ad2b88e59137ad390d5127a96242526746e4185b55fca654a4be8dcc49c314f5892544909ed898d1bc65244b99f844edc6c6a6ad262f81d0985c6113ab1b2478c3ccd396b84be72e3626cf2922c5e84ae4d58521d6345cb88089d24a7afa7e121742ab3e50f8d8ba844b0a4226130128ac4c180388841f8cc7b00b31308001838240d8582a178449235e9031480035528203a302a1c222018161418100e83a15030100a07c2c0701810060443e180303422b1b33d290560029d4034e01950060e02f2803fa721f8567e981a9e0a2e5cac220f451a1087fa547c7dff723a14334008a803a6ccb45ac05ba825ac0c6710fc99858cd7081c1d7f045c79906f9635f993ebd5ccf68113e74b06300383002ed0dda17ec943821e5827420046369641d510106485f2cc363605fc423bc0f9600530d8b80ece29fed9e0020d30dc9aed28e32ce420cc4e4fa783c4d8c4780b38f213b6cdda9135601d2cf882f5804c4e84fb70e59283a33f38aa65a020d3cea0edbc802fc6df12fff788b5db4165436e38d060c521345fb904cb06e4a0e4a53389dc617fc8efec1936678a44768c2116cd3074181d92aae4f1e721e5c0527109cf6512d91bfcd10bde156ee0aef959fa51bec25b9bf65f1e0c039f9cfbce270731f0080c031c86fffb405840a40006494833b10dc20b4332e33236f4171e0f103b6d2a281d082ae096e580a28b520d8f84dbe2f70807b64879284b600468e7b054974810bf10554aebb94e02640fc803e8803a401f70817d7526641420cc342c02fb8837e2878acb442e4ecd1c5c5f43445a74c1a8ba9fa2a678c800038a8b23f9b05b4004e0d45f6acd659c10e1c277d6f907ac8a6f036ce343031c2e8e43e6c902bc9a761856b030c49a0cfd2c4cc1292bc6570bc7e3df90a6c145e80c0b08035c84a4a23f58ac14fbe8e4c4c001f7d398f9be9ae403f1d682dbf00bbcc5ff5e5cce808c0a0100d70532465f1983ff831048653d314f81fb26e3f364301d9a40219c6be7cf01f8c0024e03a3a09bc026101a6006540653ecd3ee418fe1a6b0269c4df813237daba940f27e9aff8a32b8883e0332cf7f5ed7007f9b0e2fc101635e580eb61a110b1b0338019cc77ff925c8e37f19813363d670ca709de7b0de9113047966c32ef982c3ac26f5537cc0a838c1cc96e31797351d0bc2a78eb0701956ea83ac0f0717e574425a28e29abcbba595cbaad95d08133c2e7389d926618562409b00fb6fac8062aaf7051f602f4a488f80fd70287065225ec570101bcc0d3e51ee8937afb929b097e1388007abe86bfd65a7b12d15c275f33e0f35cd9dc31656548abbefb5e00d02a382026413080da01d9402a4034fc0721000e040f18e1a28094e12972ce91f8fd70725ed211044113b2fd180e8549fa28d2d3e19ce22247c5be7eaf303d0960fa622dd7d413269a52da22a81be14576994e2e0c822a30559ae96c14ab4da070cecf0f961253fe42c50639b3f69caf5d3c07ec19c25b9f767243d56089d02431a976a00216609ca8f3d828731b732c1282718572b1f75d30c5661c710cfffd13b82cb3e1f052434719d164a507b73c9fa58db9006d70d3dd8c2cbf21301ef209c0bf785e560638f9b8f45a85c99d995309633b816898b6e2652aa5f6b72c70c6f4fab80365c1a92143065abcf7a78d1171179c06f5899477b6ad982f58515ab8e4c20193c46fc1abc1caead01de09f3f49a0c9cffe870da2000c4fa9461390586b171f96eb365e903aef3db69ffe6b0eaeb752d4f875e16fe711da13a3ff202d2785c14feaa3fdd85d5ef67f9a63e3888002d145c6af1bd2884e2a517cf19bc35301ed26d9aae8a86d7722ef082e729874514c09e766cc18e8e1d7e8aab1b7adc8b1be30f86c70fff6701d0209b3077538196d26cdfccd0196466c14367dc23c67581688bbcea0307f5e1c802972de8180e55b8fadb29adb20f87b41e637c18b0f609d650bac0e67c5ecda2fc1f0753fcd1931c0e4ccd6c4b225e73e3a0dd2efd5e3e1850abfe446d8469e33ffdbc7f82b65c63841e12bce0485149dae47d9ec857e502cc6e4ae1ad0a79a0a4847930efe162386f752d4f84a14c000c03e1993426e429c553edda9c2ad7d82cc56e32d3513c6955d250dc01cc5cdb92497166ea1bc68a1da187cb43f8e9ae06501ca3801b2132ed1fec5576cbccd1fb76e2967fbab5533ac109c22c0589238d07f634d550028e81f4a99e11b9d3424c4f045c1da5b0f2e0563c85f63efa9e00dcb632cd19e30d93e33bc3ac3e0d421fcccd8c5cb9c7b3b2e1bc82b20273615ba59950ff10d379310bb0309a6b0d57192a233c9ed3ffb870e520862c4cc9bdf9836dd71576e7965a3de14abac5225ccf73b615889efe658b4650af3cbea55d001b1e3bb7bdcc582bb607ab6daff090990adb2b25e06ec5b8094b2f910a244f790d21e2d8a89bd9466a786bf45fc09a7f4df3c24ab8731a08280509f1e8c2e28f385e5daedd1c2eb0b42e6acdb43948fd7000322b1a3f45d95092c5903c03032f08785e4a623d5cc44db8b87e1720ef3cce79aa01ff7cf0bceb891d2c734a33786dcddf6da3c0db8ff05870a552e9572c92f8a4dbee9da5692def041ca36c3708943f702ce6ebb1a108f5e5d5c7fa54c696975812cc543a99655602f0d56c25b76861f2e672361f11094baafe4ae6b6c8f2cbd0282def8864011b3c935ced809315cd27db394b001e0eeeaa4588cf3b4e9c9698185a5849f5f8654c03c35e813f69d92e823dd653172c2847d014576a833603ad01069af40cbfa1b09408b11db0b0c536a0d6cb96519bf717f8259e2a4d8887bcbcb9d0190a6fd22f1daf248aa8f5a3f80a61cb226b9cf029184f466d8113eb3589d3ea7ab7f365c9a1491b2f001f0c28a13631e9b620e5987873fe7e77c330fda21b24f63ac72c79fd42406bedd59ab8406c869bd62cb1b04830a69f85d3514eb57449b155f193214255aba35d14042d3d4ea4afd707150dd8e9cc9c18661d83b425dbfbd0f89ba552cbaa164ac61f0cd10a87a289f8432a0f4ec26b800346addb1c711488bf3c78c9072de46265dc16b616468da84889fc1915c648c9035432257dc66c620d0b054e194de77c82fccda41d7dd3db1db099cc25e0de2384f6c34200f66114c941e4209e3192edc8c04813a723e937493c2ca6b9033476002a2160c9884b61133b3dc269c9edaec1d63be177d84ea135b858fd63721639f40b6ce8ad9a6ea9283772c36fcd09c46d28b242dda517dbd12e813217e0247f9cfda779af822f8aba8373140d4ee25745fa9065a8909c5101458dd2e6ed2b1ae12253180472ef5b3358b8c36e53bdda4ccd95802f1593295db81974590c090195579b19d97de92c786923c952b3bac998f427e0239ae83ab8239e3b3e2d9a78427d92b7e8b2730b5c239ff76a5c41311169b93278637c1c9787abc632c99ea62eaae6c6c1b94a32cd0cfd81cfb9d8dc3d0ea481281e1d930e866431bc3230458f7c94047cdb05fa426d54f0d8225bb708900b2b042f37023c1c91b738f038381c6e3a1cd0b1085170623457399f7bbe9129181165902f04958328961e62d515aacd803e71b71a9a9da5a9671010231dc431779cfa9b56d15908819a8531b80de5012a17dfa3a92696b238d7e31c7eb997a98607a819e4f898c6b4308440478ae113a0f415f2f550341f4caf8cda47ee401965226b632a7357d39543a4d6933980a1f0ce2863a1e20163cfaa4693b152dd3df6f932cb15c75d2e1f9de808e6a6e130fec52c4ed92924ac3ba649ce0b3a02afcc158bcde0eb6f83cff2bbf349d9a899c32c0bf30911b21b17e9b913d11cdbcf5db07c426ce85239821634a0e4930b5398b07bc813c402ffd57a983e07853f7b6816546eec8ab62605c7d1f57562c42764642889ad5ade40ae98b228918d0e9ff485193f1a1e2e03584f1800715b18407363006265cadb03ca8e73c567114e6c2960ddd126dd00672c6e0a8768ae06806726e2759a01303872bc265e19dae5da7df9d40142a0e8789bbcc169e726179f0f7d7d23ffa1c696150d056678f5855650f14aaea82fa21911579271832c44c31aedb3b0ca359e17549da46d2c325d64f87b3796a3312a176ec642aba4f0b5be2ec40d574ade1204e3e8760789c4bef9c3a7ad3a001ec02570c392b8a78afa6529c96404a16fda030402c76b20287031ad94b176aeeb460991b360dc811d3ac927154a7f9e531a9b1cf3f73c462c4c7710fc4345a32f5b27fe0d45937380c78de4d1d946c8e1cc1c863a4e394d8c302d5d58446ecc6c7d2dab432969818c79bd7d49dba980e776702aaaaae9e2cf60a63ac0209a386bc5477db4091d424410202d51ce1fbb322dcee700b4cab620dff3918df0a9598dfc71c175eda14343d8de53ef065c7d48746da39cfd973b47abee899b4facb35b565c2f8e963865565663b057041581b460e18d06f4a1c3a04425e27809d4f8fc99b39ae4771cf2f2db02f89f624b80574471136a2e9904473d2863fb14edc67c28bb13c3628775346353c65213c994d4bf29687353af455463908cf25ac9ba7d9d8bac48f21f41c60df799cca2c3b052e51db2ca8cc1d76fb42db2e4199d3df84f0b14018049d89ec55eed5ef85aeb690289e8c772ce62dc21a0f35039e4ec9502d80ea8f79788be5ce4c8d08223dbbddc0fbd02901d6530b97c6c66c88c532b0938835c8ef7c0409c75bdc19f48ad34c905ff4a45ea6b03774943a1ffc9315bd54cc2ce2a5ad8028b886baf8e85f324cdb1302a3f6623bca5826e440e8362910a9640d388a527f5a71fb2e4c52ff599462ae875320c5e3478c3d3cb8ce077e798bb7c55c1a11bf8dc92af26f0c3b493998da2f1c7ab5adff0e00b9d34f41c3c2fb046a5990cc04c5afa097afcbdaf512cee75846b356215091a1d6ad504c652255913601a24d158576069f667050a8e4e194e11853988676112860c4a59c7d58a3c862687ae041e61761a6f32402b053eb7d206a94426f50f10a4a395325b0a519cfef5f47bb4eae811a02dde1d11412c7159dc2485cb64a98605348e9a444fb4217219aed4553cb2e6d9c0afec940d32a1e71f1401003eaff31db956094635897387a1eecc5d5080a4cff66fcb385a310c1813c4df86dbfcaf755089f3bf3903986d5324de433d9c8d62fff0bda72027b2ade96fdfcfe9d81acecd38d4b45d209a1ee1728425466f67ce08cadf0031a0ee48d7b3929f9c1f8d47ea1a1e9793e4946be2d5835a369402ecc6cf8c6ba4d47cc3907ea191ed90a6fd98959c35e657476f184d16202514c1727ff7b4448b74c103fb02ed30dfb004a1f9c6ea0f8629e27b90d9d9cd71e39695c088af2a26b23a3c24470350261990301f3a310660c0c50fb884322648896512eb3f331d4529a952b3e6e53049f472f1bd54ded6f9ede53f187d520301bb5fa038313ba9429d69762b82e6ded0fe702de62f3b2add381ea990fd52a90122a8dc7d68d7e0da48ca1d67c87450e975a90abb73b2605e6f177db3270e939960335ae0394cb8866a8b2139d41c2bb47271c517b2485cf6ea08c328a0c2134e9b2d33b9cb899845d67969e8ecd47d623e7397aff75e4e3b9d0618894339cf9d2c4cc241f632e91164e468b866ce63e31e7fe4d0a2f1049f279fb5af3ed5caa983a3e612b0404eebe7578e3bf4942c9b143ba22c3f70a69d4a242e899cf521f69682add8f1bbb25e1764433a53e85c10976848e887417ea47a2b0e69aacc4d09ac466249d586ce22cd62ea79918f10a4138a8f0570cbef0e68974f59b7af05ec7b9cd8fead04a4906e4d5c2ddb60907e9c83f68941daa836c3f29100117b262b6f4f0fda36e36c54211c9a455ebc704a233162778033d9a38c2f0a203b8b8ca9932ea7339cb83fa88ffd076a4e670428770a862e8c085df13f58307965c3ca9593f238d4c2953152d2d1afa74f8cf972a67669429a46fd9d697587ff07b1ec6ce72e71ae9ae09f48902e0c9a7c0c949d14c5a47a4b9a158f0fd09c73e83b1254247b212ab40f15b8f8c34607fd5e4a3fa0d2c0aa4a776435c08f20e18b259ce43eff097bbd7ccac823a54cd6e2732a5755761649f9ce62fc50b347982b19e41ba422c16c459dda2523805e7870279911468f4414d0717973f7759adb2ab39c451d32db9521005285122f126512b313c248fdbf7189e551d14af54f56ecda852cf9fda90fb2d66abb54ca56f83415a09082c9115adae7cc8dc07150da4e3352af3c05e6a0aed8b6a5ba07f927d8260964299304e3846a8a9b04ada5ffaa2ea92db8f436a73c0a967f75fe2aeddd09722aa98bc7144588910a68144d9346144826ec2bf82b544605fe7c4ea503ad1e8cf8e30b8d37f3f7d200c1497b9502d70ec72b0127a4bdf39cc6a0b7a6c97f64f953a24ee731beca9c40007cc5f612ad13ba961d69de4f552c2c41e73966e8cdb73e7e6efcc18d21860e32b334061c19df6f245f346abffa513fa36c730f3d79ea3b674ab73ac777a60263e86eb3cbcd24d36194fd8ecfbaf6150368654a14b4d70875aa43cf3fd1014a987faff1b1ee4f1f106ee8d072bbe49c198dcce730be55e8823854110a93b0835d7cd5ec81fe7b73980b98c7742f623a53080fcd7987d318a1ea6a4919e143c4c11aa6e809f9344bd4ab0648e49f2bc42f87b4c60346feb9139dc37c5b39543e13643c746976258f8e9a1aa6aee1a7f5f5bda6048c9ff93d2a114fb4c04f44ad76917d269280c15cc64c5e011d40157d09d0be5e0e8ba22a235457e7ea8b3ec12b78b837f1e5687f625c1a6d44824e58deafdda469ced512fc295fdb8320c29f7d7566e256d0de3c5d50de9209b71e9a323390efbb7bbf9a818693a550302ab26372dd53f021a995369c08e50640a45a903acac1852a289432cc772ba5e971f0b37359baacfa423e028a5690d4c9496cfe307aa94e7d6e0a92c6e073f5af1aa8557dc409793fe8ac426fbbe79330dcbd4683e903e5f473bc1282a5e9988ae4967398b3e02bc1ea30fa718d33e43a8482ae25808b52eba28050ca770204e9a4ff371d28066b24e28041b44969e5986e56e34bf7895cbd5505d2696423904de5d545a5b6b200ba2993ae8e04181d7a756d633760f2a87fd7e58abfa95e8746044a898f89c5929c4108aa097ec078de2a4cf7648240256167b18d271042f6483b00618023df2843f83990d960078a5c7aa03696908e693110f92a23b72db7eae665cd7a8ff00f55e3c083930b330cc9b0446373616785cd31172a6842a960026b43c869759f17940a499ef31a0d22b294c3eb423281da48f88c984b7aae85779cda5bfb2e653357d142c7a741d7335259c7b8d0e331b94918502f30d51f7294850be564a9db7b026920f6acc69efca4d100f60b631639e844c859a0258c38170471614b19d15481f42a92b5f0f6bc5982d8bd430d9ed7922721f56126ce370d61d72c6ea0c26be6e4c46a6246e2c01e2b3fe0b14e7e710311b862a2158ab40c52c81d37a8b710672cb8e2bf2fa4aaae0fbc7436597a9b43e9cb7e3528e00f5f69f8065cdee4164b26c4ba57a039cb5aeb8332a62f0e033e6a3205c1e0e80fbfac5ea1589cd19b14d6873e8abe0a9f212a180618a04b7424dd7eb5e91670c8b4b4fbc0979cd3c317d93700fd81dbf2f58b2756947d134738ddfb66673d78b69495de39388fa819f040ebf3769fa15f784a94cf33a9ddf5518c269e8714ce857786bcd65417bdfcf3813d81ea026287cfd76734c2c00a66df183e6df5e5ea568f7593437970a59ba08cbe2783b77ee0a4ba7a871e5989e65a7214679d5775ede268b307e242805a7981cf4dcffa2d9366c3313e6bfa9552b46ed3cafc690b1117417cf6a07acaf4c2cf488cfd84cac936352d66257b3bde5c577e798082cbd911fc6921dca83903398f11b70a1568536924add15c1b529858671f895509086d4193e34158120ce230c45fe1eefb3d0790fcb137b0bf27d039df2b592af020b1492a6e4c4498f2a7b76334f387d1649771cb721b77f6e4c0bdcf40f94623dd4388b71811c41443c475d5b98b90889887c062d02a0e501e4e0e8139313f3af09230ee092980c1db2873f42e284b205a837667b76f26407312be361db2ac58809eb904f7e47d349512ec8fe0cd72c3688205ade88caa3c223e6c540ecc12bac4768cd9199dfa564fba50f7c7c109c684166182e3717f44003cff846ebc218108487ed56d0b12f6d23727a9e14d74a8e367e68889c59374e9e7a927cafc3eab48c1d6ea042cfa78ab6f2a6ce184845891bff0d97787426461a5c21c1cf1dbbc95719a01d16e3de222fecc067791c23e6ad2aa29a9a26549ba29fe2707c0892947dc1adc16096787f140520722c2c38234607670d52dbccfb2ba9f27ecd2e092d78c5ba99763ddb783c056bf41a158b54aada305add80515c9dc8874abab9d000dd401b6905c2dd0846da2f591366749e1a2fc971932f271585389ec7691f7eaa147903751456aab64012f57a1ba219f93cda64070a12eb7c4ab95d9c11e5e1d62a9384f336a6d27713148069d60babf2707cbb30113b22ec2d3423f029fd9ff67ee20b094fa80faf68c4ca4bcd0223e67e6ac3c37f240f311b02c83d3a9d663824d05dbdce2aaf5192df7c49c7935b7495b6875ac36e97b6bffd450d93cf7ea7ef75984332c01c4ca02d5199357320bb90b146b2af456f8a1bdb05bff584f5034bbc941cacce693bc92bc9d6c38f654d9600e2630b004a4a5e90a179b548f315fe2717304644ec3d642d4f0022c186d3cfebf350c8dae2ba6eddd0d0d84f36462eae397ec7db5859b59c8eed3a6656e784165bfb1d5670611f45f01a7e3ec6fdeab7424a6073679a03740cf51fe546a85d51594889eeedf9841e548db4c78e99d178cba0c1baed456596102414549387e7514d19a41bd01aec03bcedd95f85508dfcf63d9965060a6e9f403ca4e12d0ab20f72bf0eb49c6da2509472bd91dab4d497b955c9de18693be87ea2fca985d2948757aec9b6a042aacc92ec371f386437577c1e8f68eaf8e74dcfa2a6b103ae0bcde62aff3892fd53c967558ea5bd757f602e8e784472e6feeac04a3bc7c67c1c209a39d523de107e11eba092917f3cb8c2990e8dc9ea540d463d252da664d4ce711155d238a30460f84fa85570a394a02e6ed4fb2cc539bd172fbc6ce9f9cc86691d872a57fdb98ac35f4b525c0a6b55c32c2daff5991c904cacdfa788be72325134918df218931701b6244b023b0851d20920a5a5a9155b8a30f47f7c30d4bec0d72d83cb1d9a56d66e989e08a3a652fff651827f040fd32c9c376dde489a955f7aec436f907476b8aec0de9c0a4f330d0c212b09806f65aa34c87cbe93046a98f2f1f733574fd0849b12f745b620d92dd1bf1553e9f7d172dd0c518bedd515d2fcb4c48a004ac838644af95c141394dcc5696bb3645b19e075e0470c29b0664db1cb834be70da5e45b43423dcf4c81e0149aa053a3aab711648c5f8af4110f8231d0c9ca063bfcde1526038a8cae48eb03308631bf733cdeef1dcf5a6267810864c6aed59749e4e0e822a31f49c2816e71d190af08c92f0c07d9b4e7fe40d90692fba7f295e5570c23099107687ce624d72288cb7a3e57a453eff899012d166a14328429434a4634ad67722a7e2d2cba2c0ac0e6293140335e09e7a9be6423678fb6f9321cc9d0f86a78a8e995396e9a1ca1b7952825e2d98555fc5ae8a1ddfae4c8d9569b50a40224c70a6973af4af8f5e029c171d7251680a9609f012df821ffadb3e09679fa6cb2a05ea5d5391973319a98a5d1b72c823cee7e80690b0053659b94cfc50d4a443ec431f0f464a0b603d62e5ff02cd214f34c6c57ba0d34f0a76b9c144e2df123b389fb020a9c89d55b6b931f7a255db8a1860313fd83bb5570d5f9007c41a63ce6985d144cb17035ff77a1472d7b22223ac05b1231e5bf94b110ed61e4eb68ca822a7f91d542110d62102664e70e661328ee241309384fba6c061cb45a689b3d0ece75a984d22bf590d13039a6ad3509909f897426e85af70a5c5e00e03d24629b88554295b1432537252de072c6494330a0992363d1ab10a7d6d09f1cb3262343de4f626c64631245ebdbc2c4f16bdc2ff34c88cca04732354ec340cfd67a661c7edcc7096c46b57fd0f111957c8025718e4d255d46419adb33ccdf8d236d29610ef5af62e9bfc3f83ff06f152cc96a52365d800e8561b250821071af80a7629aa3fcdc616ad341846aa0a3d963c159f667b95ed1899844c38821426881a216cb0ee57c8170012e42af4b48b221f6f6e06f00887ce5ae405961b24fa11a3e60042a9b1dbd136cdee8e20c8f6b74610b1da17706ab2b6e91e1114206624cc214aa22e42f48b88680d3a82e5d108f443a4d238bad37b869a1b1c3edaa88d745779f9ef8565a1a354e4808bc5064f116e73b0b3c70979487e3a657c5fad945385c919e77aa816e42b482c7cf813108fc7519c703c37a04573e32cba917ed851f5294fafe7265aac1e556f0bc0c1626cfed07d127b65c91d5a5e674ec3ad3c6912e1c0b1a303c3a055c796d92c9cf02ef9e112693408b094c541fbcc2f5cf99ffc49421515b32acb086c6e310deed5f3f467397f2e496b902f398197b0ee4bcbba486b3b59664b266bbbf6b0e89ef025ee74ec5bce82088d7d8c79858d16e7041b8a706fce5eda4eed25882bdc655ea2fb5c514346383d1b4c75702c0342072c81cf42fbd8337fb22b730d361de709d6a7f68b0414ac573131bc6fea3e9c838e133b9d432266dcb14c71fc5f3963963cface354241e3fd34465b3b3f475756838071753c5e0837ea91c70d1366fcb12911ab8741b4bb985838e557439dac18f372b0178204f0b0ec52ad4b46f921709ddc5219f4ddf25b5f44548199baf0d9306aecccb9668ee4a302a078f90b8f415f975d04736c88b33c66b62f52fa9e8a0d926e1c6d70accaca964caba73a0b8dcbb09a151211ae9103ad289e76eb3266e1d6000a10835a62f2f8a65f9907542e683abd0e6b99e6fa964c2190fa3f3a3421b539f75f6dee546525abeb9e65fe2ec08b95fe319f63ce4e3dfbb5bf6729c069c4cb326a1bfd1639b5a963a9be3539410da64e2bda94aabad0a18a132ee2130508eabba9fa0e630d3778c5a560d6b620cfa4d9aa3d03f23c83a3272b31abb6bcc93a98b5651ef6294045d0834621eacddb247fddf0c179a473878ed833aab87c7e9b90cff917215d91baa79e62473143b05234b2185ddc17f6914632da0c8fc62aad56a7184420d2a263c0650d3921de8a865066cf407936ac352711a96e8c1b4c42396511c3aa52b47a32e2d2bca256fa1fe441cb8272d4a51abd889a785139f82f01aaae7161ff701ea07b7329c8a54cb1314b92eb57fc8240093d409d5f9a312f103c6a4345320377196ea18deed0df0856b60b0b68b79e88b059b02d97438000d45ece27d26e7e9e9b752a6fb0e9a8eeb74918c00253b3656b7929f1817f87e070940afb1231e4a4b6fae009a0df1663d6618baf7e240ee4455ed747016387d98005a229dd4a4324745e5f0b6af17e9481cf3911536945647cdc4e6db4f186101abb31efe3e42a109761dd5a0377f30bd4f14e6bab8034b04fa3db2a7b791bf9619f9ca6e2199dd0c1348ec65f0d2f48180619d1b2fff8ac68af32ec717583f4c2f52bfdd19b9c358fca51e1867def482e6d7dac2add48cc9517d7c157b06da0ec713d99c1423d7fc40cfdca5a679f1d1841a8d306793c98307eadcff9075c4e8dae975e4fb7d4805f3bc7c5a22d9fcfd69f01b438b08aa1bb977d6c214233d7d33a85fb736335882f9397f3b5ee0cb1fc68414dcdd222476211d6cf3c820a65a092f540054c802e85c85124e33242ffb18c17d7d80f500393b730fa7a09c3a0be903f8a1edb3abc0e210f647a9a6a0c675f085db6b90ce8b3cdc7edc4aeadc6365d23ce5e137c48bed5bd35c9c19eecf88d186a030cd3be33060659022bf9d3b598cae34ffae9707dbf97a550cd628fe9facb3cfe69d0a59b9146498ec3701ddceadd77151ea9a27aba072bdc242fb87a65d122e7225f0363ebe1a0265ccce4b585987d75583837972ee0bc6174233d6886dd06976e6c4ba3880bc0a2b68476f1103781f0720f6972b55d667e48c6c570d8587206dbc6b9268819e50cb1e7724748bccbea1db014095eb5f73be8060b400a4373654df6157800a9c22fbeb9db3c32dad1c8281269d7c7f54b05883d919a269a8a91312dc776c8ac323776beecf2a7e5c2ffed0f9f02857057b2cef87190ed893f79cd10646fe1e40dcc5cc8209d927f9b6b3651e4fb6ba34d72346554a3417c01f73ea006ec35a3a1620dddbfb47a77f4d96e8b12a1bf55714cf33c6d90aa9550f898dc48c8651eabb39d235a5c563431ba7096bdb0f3bec06028ab1db7a20707133cd64932e0545abf82e306768c0d67a19e8444f5752eb694974455a66cb63f816aac420a9d104e1a88f5bc34e3e9f0a2cb16d7814485e2e004d695eb066e07a927da878313868f0876572382ecaa105a9ede6d3d8b2261067cbab5ba23c8e8e13839f35773eaf6c2c00d27aff7d660e4809de427fb45076d090eae8064bc8d41d0f0c2445f8d2b2c39b838caf26612a84a4a209dc939f24c709860b1348daa75f200d32c22a07d5bc5505d7274fa382752bde48012b2835080210efb0dd52f8567b3e62b3938fd7aff113ea0ea9dce981bf2f0c78d86915f6960e6b9c23258a4e0fd143a45af295069ca5aa875b205189e5df6016f235844b63f644868bf858eebc12a432d62d0ceb675e526def90a2efe44516d71e33db4302905b475f9d20fc7a6b8e893c85027b81c0d5719c2f5ffcd0cc5104b8b90a76d7537b366892bf300d7ac085f8cae4d163e063a858faf986219295fb9164091770cda519327ece620de38531ce25d59dff76ed89bd45ac22b0df7ac4530b7ffdc81eef0a3072fe63711f031bac76d2e53af69edf9424283990b749258a868c95009e715aebd1069708c859ab1348c0cba470ec414a5e5610972b46bcbc6ce23dda4aacda241de41de2ac039c904677e8aa446a316d7b61119b7471ecccd50e6b45a2990e00eba506cca50bcc7a4ee9388ff5965f1845112a14879d1fe764ecebd683564a9f38c93c17dd24db1adb7e38c632a308bebe29dfdfaf04eb7cd5ca56183062363417788a05e673c51a533797252d10b19c2c0fcf12f0a2e174a5ef07dd10065bd642cf1a94d85dc6a3933c073a38d41afd0027787a2bc4dba0f185dae6a89a77a7018c73c743999a5785195878f8aa84db27c3ac6310b77983826aeab406bf243e407f2f1407949f11f8513c994dd00d0a2be343b9db87625acf429f004d705f04631951c52c43bc1486297665fa935cb3747cfa20da853060e75abaf5628c29e678d1096d9f3ae53389d39df4b0814ea03db20222000a6ebc62ec74b8011dad677d2d61108ec20a2dc0890b9ab0c2bc85e64606b09f57cc786aae5a6e486df6a20abbd083b2e7a714158284477099c74a2ecb714a23f1d3e1ff301c03e202ecb12c3058dc9ff6a84a49b799013768a9a6bc25c640303ccd785681e94ea4eeae385abdda919a7460ad57762404537afcc01b7b128f9e4a444d24d236b3fccfdfc8b64f9a7c7bedd350ed2e1efa8c92f7af72fc56badae58a86905e236ff2568bd045f8edf311a072db08cc154082f804053d03a87b81d9e938398718c285e9af0a0526893a0b0e04abc9cabc84d2cd16845c1921a1a80e5cf645fa5e43964261aca91cc845b606268ab296e3ac9f80b1c3fec454bf32f7669f33378594526c9c3b02cf12aff7d42fe04258cbc988da908a995a72118cd94db8cdbbc79350d019cf708024961b09709cd908c1e96d3ab61bc88f3d15a0e1f75d0c17028fd04025aaaf1efd524f96805fb1581f3860acf5212b139e3864c8ed1bd74927176510f9165d3b4ce902f2f83f8b26da41c864296161902f7e8699ccc0e6d21cbd1eadb635164d3749cbd6be884e4f3a38768f0416bd18d31165db2e53b80337d49666a78ac5dee9ca2a62d8eb461a1946a701fea984f6b1ad18de912160c7b67aa670559ffd80041d1cd172cd684c1951547b3d52a5d51af394d5ca88ea0cead32de2e7dade8b4aaceec62147863e6da3ea30fb872ecdcc52670136e7ffc81dc118bba02d97b4987fc2659a5e903158578d1404a2e35ba20208669dcfddfe954ea7b4f92d52d2f0ac1b5e0332cab02feb8440f0c3560b46439330f0f0f0f0f0f0f8f39c684d4d6da21909a924c124af9319c37644a29c99464df8d90644158f81769c31fede08d5f90810d0cf80b430c793809955490492f040f875331f8a664b102dc8174da95d62aaa49c80e5acc1353c2448c741d342932fda611ed75311d5e4d33ea5dd133640ea4da38a771715eb3298783105679455d88110a1007f3592e5196a6255f0038902de9492aa52eb92ebf81b0a167956e5b2337d429315dea36394a8a6d3877f96611ee351b1615e49fc80caae5351c539ecd05a196e32535d4751b4cee34142f315de38e864392d1e3e3f7caee3467c8c7c46286c2479fa95419ae5221eae575a34a2703f2548685a4b6f55dc7f05852a3421383b17c6448d2730f110b433298756be8c0b024a1c167b4c517fd17921572f3870e4b79572f586e31cce6126ad38563dc1a2d1b2552eba870e15a97f3dd1a992ab285362e6db75be6d40a6aa15029645a76692a0ba7b5ac22336d8605634b645d4cda35ba7a85c34e9c7ca2d2b2c229051366ea42a40805a8422ac5fa152926b13c2a904c2d898ed1bd0cd3148e794662d8440b31a85f0ac7487aff4d371f859388b98ab0e81692daa170dc594d2721e909a7d331f78d1ad37d899c709013d205fb0b42c5899b70aaa0cae24beaaaa0629870ce1161a5cd334b38e9dc6cb2e4c5574f56099a901b6385f3dd24e19827c8163dd944c229e697debdd0c917c7231ced64c82db55fa77e239c6561f64f45386daec969d2fee2c44284f3f96e89a07a86411b0a30044baa9cbb8a423808cb3e2193fcaaff8f0a0508821bad2aed4764d1970284d45ff43d794129fff50705cd72dbf88098e566439e9cd0bef7206171c22e4b0c4958001ea04189d2b72c3146b983ff46bbe868d917e9c0603392b499834e74e9a9ce2493e41d07c6c971016e704c4b79dbb28d0a600345cd8a88b597e6ddab05222ac4ed8a1647d92c257f24ceb6cdb348c47c9dadff75aa65591c54b8e6145d9b581c73c55f103329674a5a589cf436a48a9e2276a4fb0a654b99cae70a4497b294717525cedd8aa375caacd6f62529272b0e419d48924bb88add94960c25830c125520fc94491b35f1236fa9386bb434fa7726f60419a8e86254f4fe267fef14bf6be4f0bcceca8c9bc29a0de1235808517e538ad3a490c9e42d4f8a424cb2efb423bce44771b61efd96b19176f22e8a43f4b5ba3fe115b7e4a13867300b41a5b89aa937284e2a8a65b5d1e6965b7fe22ceb1567e6675450224f1c456dfaf27f3b719c6842933ea55a9a623871aa56f13849d1acd4bc89734cfaf7d195cd829a385804bd7651eccf429389f35fb0fa4b5d31a4a4c54495172a2b5cc6185fe2385a52b288ff88955e4b989410e2be249538cba8481a944495ac494a1c244dea9e24e7492062d6cbe9e5886fad24ce9821a810f248b0aa6a13446320611499a26a953eab1e718a1a9624e6d511a69090e4eede88d3659f5841882fd527230e2aed0499a153375bb8887ff6cfc28c7e47122922f91022250b9361ee4dc4a9c4dfacd7cfafbf82886365887b325888c8213ac431474c5a3d9145a9ce10f748b4a094e94ca3ce42144c8abce815429ca297dcf8c610376277436b1084133b972cbdee8b6fa4c2602f4e86208e5bc1cb4547ae0d83bd386c828c409c3393dacd8d18ec4d409cc4c45c46e9ea492dfde1107ca4c7fbe473dbda0fe730a5e316832635651fce7b7731a83c134658880f47f1526f17ebe667ea1e4e6ad4db64963535b51ecea5646c6cc49987d3fae5f291e9938107c3b45582a49060b9c349f3d465ba89bfc1e47638e88be239d7194d556da3e420a30ee74b41b72296a94977d520830e275dca4583daae2c0132e670101517564aa47c6ff10f5c608b94038cf60ec8e124d2694a21c6b628496b519011876334dfaeecfae37d9d7f7cb40e1c5ec0e17032ee2a5f628e742a5db000038902fa86834a7b9b8949d84c2c3bb0c3254081076cb1c5072ea023078e084841861bce7edee7a6f3b7e118d64de628f9a7b2335f90c186835ea650a5b69f5a6d2a41c61a4e3275c86c72535f2e4d861a4e71a5a934c609f12d54c608196938a6e6d2b96d4b025b3ce06cf1802d20808693d490d338bab933a66738c8ef0b7a92e5e593918f0f2ffa05fb05185e780146172ac830c3f12b3676978798a8de156494e194f27f57dc8ca334a8c9701e7da57e4958cc71221f1f5d903186a346d4d3be8911c3494eff6e583f35273361389d925916d6f54f7426030ce750ab23f4fcd2ac7d36aa0c32be704a17646dce74aea2688620c30bc7c93dd173ad429031eac26135263112f34406174e3d614355b4c4939174432b6520630bc7a87979a22ade454b18385c506020430bc798986c17f8175eb704195938e5d97fcd0ed98c195e24c8c0c2d9b448b8f8a5da3f4969041957386fdc97521f7135e26a85936baf88242e3aa4955538e9ef4a936f5e116450e1945c523e131f1b4338a770ca9b26d4e80d1d2ba9094186144eab954ec498771d5138cc9be504fbd2ea19430c0832a070d29ded946862f303194f38c5dcb45851f2ad76eaa20b1c2a70c249ef45fe6bda0619e3261ccd65f449de4cbacd9a810c261c4292ab143a5a9964b484c38e52bda04a1fc850c229769c0857d55dc97249389bf4be9ca59b45cc031948388b6a665cbe984a56e408e74c4988a0d515c7f6d2810c231cc49514a5f72e1d4538954cfa32cd62eab8fa86968d1d8e02229cb4ef6ba553dda1973184734c8a8dd1c2e5ca6c84708c72db173ce48b340867cbcf9882f69b989064389001849388d147d9049527b493f18383aee8253f72694657860f4e7a262e59055f13056820a307288307a7982b8910265d193b388813763257969873843274705013f4dd7f97fe55282307a724bcaccc43290307e7d96ce30db591634718048c1c89326e704c933a162ed7ae6f1205326c6062d4424d1083162c481c316691c8d0933974793164112316674d32a638a1b1fcd23a581c5e6373c4143b2b950721c62b4e5f6622379e737e22571c4f5cd6dfd36a396432462b8ee619b4964c4177aecf8a93522656a7adfac429ade2dc7fc2d25e6f551ce4c968d15915724f3815c79cbc29a717838a830c4b39a2e8f414a716714ba364e9b6a598e2f035f2275ff929b34a294e16d765448a61d7f4a438880b62c4bb3d8a73dfbd659e18665264a238a99cc82da9be7e55c508c5295494f81b82be0023c7dbb8a18305619032314071146d97f9a4297de298ec644e3a19267bac4988e189e359c87c62233fa4de9d3889695c1022069162843871f84b9bec3f7fa5a38cb1097d530411f484fd2e1143132751aa7d4c6edcf102dff105189d758d88918963369f0dd3287327dd189838ff28df924d99474cee86960d3076d8d0408c4b9c6ae38d66b81853347f5f8861897367b4d269d2ea57f42646250e6e722eab2fba536b4a9c6b4ceacaf96685189338551052c7437f74e6599238a6aab244e268fe5a3bb252dd5f4a0d312071d04d2f1b1233abe4f211c7204dab8c90bc3aa3230e735e71ae26d48853574c3e096230e2a4e75531699ab60b3116519c6b3b6328e2e03a59cbd4c46439520290831889388b8e6779ed8c08a52eb08881886385944bb48f90df78c0160fd8e20139fc46ef600c6cf1802d1a10818f0f1bc80679458c431ce3fb24cb35b1c3521ac31007b554a6e49f59888310c23486f813e2ebef181fd95c8c419cfa92e6923795076c4134b0c503b62019d8e2015b100c6cf1802dc805b678c016640e3104718c669623a2f54a5e550371f84b32d68db290100310a7a49d235436863ded1721c61f4e15724d8af04fd397ce01822d1eb0851662f8e134b96448f9fa364f3a3f3eb462f4e17425b49ce9cf75931846c4e0c321f904493222e94a97f522c61e0ee2ae232717fd2b67f470c8975a4972996b6e350f0769552a24cb0c69b1df7a410c3cbc6e996222ed2a487b428c3b9ccd4af66d84f3102b9f8e187638c436ad9bed4d83d24b8e1875388d3ad72d71e297217a43bb88410753e3fbe4d6236ea4f0ec0731e670301d21d5e90932e59637b40c0662c8e1bc1b34cded65c6caa85a20461c8eb5f1e7cccf4d26c9e660efa24f0231e070d60c22e3d76196fcbca175b5c50724b04599186f38b84c6c7d91ddda93729527861bce124c29d53f2af79f260d31da7096a4d634d6a898f8a33fc460c3d95e4be586af247ecb186b38ee86952072f9c6968a9d21861a0e32ec2a776388a966a7e1f0bd12377da4d37b1e1a4ed972373ec7186738954a12b73463105e6a0c339c5c84f20dd73446198eb12fe526f764386ecc3a39b44596901fc3b9f267093be5179b8be1a031ff224f0ab12a0fc3412e84cc23abbaad048683129a7495e6568c610de77d450ab96059250f4a1c93d2b3dcdb2023c8cd631295e6ee746f4b561e1e514d36698a3c62feb3ba808724ce1f3265baaca5b4da7001e7281bf8f87001e7988147240e7abd2d7596c893a607244e1d2321995026e22c1674c121481b608f471c5d2da8fd8ef817a7b9a145828f8f127838e2203f4d67be6b50972b0b3cf0f181430561e8c88247230e236452a7436b4544ea0ee0c188f38698f7910da337bbd5d12a0803055fe058d691e316718ed199f462cc56df53d58e2f2840030f4528a9ba2aa59458b1d4346b93f29a5341366c7824e22076b762b7f2049f11513e8ac7218e41581227c14ca901c43c0c71d69130ae236251737e430b8c2f6c98198f429c26450a25224fd4823872ecb0414c064860830b0f421c64ca23629fcb8c856c031e603b5c47043c0671c8a2d296fa8d9e15b50ad80b63000f419c35774491667f2737a78047208ec1eb5de45367b7321e80387897ebba6cb5aec53cfe704ab167399af42e5bca0e0f3f1c83945d9112e2e9cf5a87471f4e263bc44dc636ae890fa7d4244484a8cc1e4eb337c15ecc5bd328f5700c29fff2a68c7938bd99ea7f08a5364a160f073922aa79053115420c041400c1c7c78e2f70b0e0e363c717385850bc60c1171e060c76a8c71dd20ee95187f3c95cdb0230767c41010f3a9c465f69d8a442ed9ece630ea4ce430e1e7138a85e9e141f390f389c4704752a7a376f38c41b51926a52653a150f371c62e7aa89d174e0d18663bf5c309db549589c0da7b518522a593ab424cb1ace972d8a85470e19e3656ee0a1866392694b58676d6baa74181c78a4e1bcd133e59c2f95cb180dc7d4ffaec94a4aead89ce1dc1d2a3494bce83066380697dcfae29145a8b70c07dd1b93714925c3f1c4de579a74aa47c4630ce75bef8d30ee2b4a4b311c5289532a8cac5829a14718ce3a56997b54ed0186c376c952a72567636fbe70982c4aa531592a0465218287174ea754eabe92312b29df85f3052933174e49668cb1905479ac650ba75379ab52e1d2c2c13ddb3229112ff6ccc2692e64eaff8875b190207860e178f1925c05bcc3ca8c031e5738fe848fa4747c6d68d6040f2b9c4ccedb8f0551154e2652f0921063527a642a9c3e725969b578db78a7707a7bdd88666a829aa8144e6341d4775ca248ac44e1205bb76ff795f2a25f7058f080c2692f7f5ae94a330b79c221fae8882ce9f742dca0e0e18493127963b94d08cb5eda327834e19826f9d4dc59565b9b09673b8f13215746068f251c77ecafb3d2624934957032993453742d5a1099249ce4a44c377dba73f38884735a5e0c7e1fe19854fded8aeae1e0618453ba18df2c25d1202eb311068f221cb24fd0763f5a73bb66060f221c26688e65ab90c710cee7a73b43beb31483ed2184b3cc89b4d974db2ba58d0d2b7804e168256b824cb2bf00c30b2fc078c0211781f5c10308873cf6e9f396d6523cbf000347cdc1e307e7d55041a890b32e761f9cf3f2088ba09dab750f0eaa257f58bacfbfc98373984c7631ee8a06eb77708e206c4fe6af8353e5f64c16d61c1c4ee97c956caea6e88183f3a4f07b6162f84da2c70d0ea276d729522e95e81e3638a6c6526bf12cbd3cafc541d85889fcf9ffa5725a1c3624f99c9c98894c9ac539aeebe26b4c92c5c96a4566b0d2904432c5e2947f64fd7246539b048b53299b4b4ffb15078b103437eb5864d1156753b115532bdd8af3d9c8d4991483a9a45971fa9a2822687e15c70c4a66c92575c48954718e53751a265608254ec5e9f462aa78763a9245c569dbe2c2c8c913d4884e7112257c2be34389ef90294e6983be1407b519228df0f57b1393a2d469eb1bba8fe278a12bab88c888e298e226496651138ac3a6bc1125084b212f288ec9e59246523f71b66cb78b116b4984eb8983ee9ef4db60274e52349be995b79193e5c4c152881049d398108b6ee27c79f37efe9a4056ca1ecac4216dfbff5c8989a3261d624b26291293f012e70a12b78248d012c758328ed4f82e1b7e254ea7924bda9e85595d28714cb71d723f4bf9b6651287b4b15dfc92c461631c5569cd32424a89c4c12fd826bd9acdb687c4e1bb63d4fe6e9e8e1f41bc8941b9f6788e5853372f766dc461f4c24e6f54d2da33e2e0b3b1cad2a6dc978b38e8cd939151d16c838a38c973bb4b1a34a5c42c11073d277e2fd924661811a7b4d21bf95e1de27c2f31fdc6cb10c7daca1bb137970a932ac459675e37a6b4dfeb13e2389ab5b11b1dc4492ddec90a7dc1a4480c296608e2b451635698fc06e2a42f057fb5d11121df026600e2a8f1a7f9d45de9c8ff0fa6de9c4dac20e387a3a5dcdbc417a91bda3e9cbbfd54fb2557b537f9705241ae65936d49d78f7b388876d1e722a209abc80c3d1c7ee24af23f5922a5f370ce8ba55c6210bba74b33f07088b1b49ae55ed55bfe0e33ec608aa694868b4937a30e27218488ee0fa5197438e957cdf7e61c4ea952c7dbec9f8eee6b891972388e88b54b29d4586a461c0e675d36e1445288dcc3e1b0513d4e86e47a492550cc78c341095dfbb6ae6132253931c30da7e05d628487ecfab436d081ddc48c369ce62a288ffc619a4286d987196c38eebe464ca65294b13ad9d8e1c52b0cb88b3074e048ba33d670cc1242e56dd2666ba91a66a8e1f85f622666cdce48c3c94fb78c2c15e4c20c349c644c9bf37e62dbd32486196738a6d5d1911de373299ae120528acb7b56665a2633ca70eabc4a418acec9708897336867108b71d9180e4959583e115b5c2b258693787ee8fb593b150de4f01d2cd0c0161fb8c0161d701d39bc053820f01ac8e13776e0386e98118663cc64a32fe85df74bc1704896c1f44ab85849fa5f38484d71b9bf47a49d7b4298e18583fc3a15472e2c871944cd1fea4c65e8008086195c389f4ad64d69bcbac28c2d9c7fd3cb28b51e32de450b47d1dc4b8d16cc546d569891854318716215434ce8cd60e1a492c914e2894849857a8553ba52b94e8dccb0c241b8c85acb4c6046154e2567358f45b77c397f2530830a87d1f2e1d91763dffb3682195340b9fa6b04130433a4700a4177dba4f770db90edc08c289c424c5349527231a5cd1b5a5038c9fd4b96736366dbeb8c271c948a50b7ca9722ed84538a4185fecb3e2ab67b8e194d386bde33adddd3d15c99c184434a51e267d57533ef4b384bce97a8512da78ed286b7a00b3074780efbc00c251cf69288506a22a8d4ec0d2db6e13bc068815d604612ce19f2cbadbd3a36db1948d0194730798a6db6c828bfd20c239c46756b04e5f2fda2bfa11586172c40a402338a402c5113be244295ad4bbc86cb99326308267da1477ca5a9d809660881949a2e2d2897d8cd08c25143cce737a41083484ac20c209c4653d2db2072b566ff83532c154ceb68f6e9cb7d7050b2b1432ba67b70aacbbea4d9e7c15194943f93fd5a51e11d9c625ed15539e1f793d3c131fc05adec0ca5379e83630c62bfc7fa9f8183b3f76d9214a2267d313fe3062715163bd636db429f66d8e02c5a76c2478ecead512d0ef71ef9947b4c8b2a83d7c83917f76671ea493e7749999ecbcbe2906b7c6383f60f538ac549e9141122bcf42fc4c0e22062ace4f6842cf3f615c73832d8e5ec72ff93b9e278294a2cf7ad38cee6e62b3d71b3865971ca11f9974bfaabe0ec27d7e4d39b72559c4ee869d1d7669a574cc5168469d20b9bb6a48b8ad35ceaf8db540bbbfb294e39418e246b0b15456e8ac47e54eb529c259c92d9fb9d93325254227a97a75a1ac549b30851c99aa56d2551281a4a6b6da45d3d14079942c4d0ed3528ce5d17a336f36624ab3ff1850278e2904e36e553a9eec4712fba75aacb0921d29ce0f5beea36dec4594b5c268b3651e46c122880268e415b298dab36733967e258697d9547a5feea061347531a345c8875eea3bd441973222d86a690b3c441c51e8d717d5e19abc479e5bead4283669b2c258e992d8b95d9a69a3a8963d4f8953ca48ca44e257134d525d4c8142012a794b535d9bfa97c0d09620c9f6c7ab2c4d8235057a63b33a538bddd11c846505ad9928dd2ba11874d9578963a94b8301971fa92615a73b388a3eda8bad8674aab878a48c4f92aed9b85b820e2702e49b9a97039c429c43625ac4d63a8ae18e2769315e259c87b3252888352d99d21281d210a3088633e99bbb377bfff9d20625080401cc46fca7866f9debc03c4f1436f9cbaa46dceb53f9cde4663332bf383b2a7b4c910b4ebc341a5537216eb166a2c3e58daaadfc341c8107454ba779bac1ece2234891c375a6a93017578556b344b65e9953b35259154a95dda10873c226925fbb5146a17e294a2994e8d572a4fe90871cac9fb15c3a81b3088535216cff28b97ae7c21411cff828bd808a24452321c5e04e2d8bf313ee6c44d96500310a7ca197beb42bac61f4eca34529a5b9e081b6f68b500473a0898b532250335fc70ce9c793409b54b6993fa7090a464d0ab9274ff6df8704ad2472995fda76ec13d1c248cd5c6541b6a6ad3c3a6319967c54a2924e513dd67656741c835f2706c11b578263a7f7fae8187639aaa48e262bd93cc1a77388a68266fb9cc16410c410d3b1cbfff35b62c4ccae5e34307312ad4a8c3219b6db7b946da94b9061d0e79bf940aa75a8d391c56d77ed3424ef59fe4408c16596316af9452cbc33dc3ede8fb76c66ac4e1bc19fc72436b773c183a4aa2f10d1d990112d8a81a7038080b7639bfcb4218708e1c8c35de8068b6884948b9adba26c6755960956347186fa8e1865334c916d465380921a40da76425cac4a6ab94ffd970d64a3d49bce5dabebc865308572a412368be6f6a38a99d89e97aa9fee46938f6cfa69044645ecb161a8e753aa6845d9f461139c3292cb3c93d75a9e26630406986f39f79aaeb843fef3087083287a71a6538bfe8c81a6593e1e4b1252cdae90bf1f6188e3332b8a69ef9eae5da43f0f1a159430ca73022b88736350ce73bb1a7dcd7cf4e48c0608830553b9fa32f1c6324fb8962a3b9feabe18544527196458a5fa30b855a659746f22a4ba92c7986d91b95215a0a430d2e1c434a13638ddc242466bd6dec68ceb1e3055b385e5a1212fc334f5b98981a5a386cc94c97a80d6b408d2c1c73569420a38db31a5838a8784be61a8237b4468d2b6c9ee2195d5d5dac4d2be34515b56955d3cc00096c60a08615cee6216a312c59868820a046158e56396a2ac624e35f860ae791999522d5c5cccf53389c6d66c89a3b556c2b410d291c3353748aaf06b54614ceb7ab1125fb9ee6586e68951a5038e4082b415b48b7908d27903d44d2e48d3f71c231ae694f8bb496a5ae2bc41a4d68410d26bca0c61218af8ef9fdd6f0bd8612486d6159cd2c658aa6de95e96cff26895d2309674b3b8b284ae7e459359070b24f8b143b3428bbbdc6114ee92eb21a4638890c2126f3b26412be1a4538aea5a9fd65d3a43daa4184b3e691155fc91a4378ec6e3462476a08c139a5b2a45021572308a7916c27f4bdaf018473a5532aab6aa5357e70123936996bcc76e0d081a305668b0f48c0868d8f0f1b1f1f94a8e183f3caba8949ca36839c30a0460f0e429a8aca79175dfd83b1434b2b508307e71895ef54907317a9bba1a503c752a0c60ece696a726eb22fb1d5b7b03e504307a692ddbe5699269b03adec5e3626a1ab5d1c7813a289a5e4dc54b9012716d14792be5fe0378891b2f10214e820356c609694b52297564b8a2fd1a5d25e57e46a718ab467b1aeb12742b438c64cd297662342539ec541c8243a31dec610ebcae26c314cdce5a496f24a2cce6642d3c6cb8c31291d2c4e7ab2d58dfd89aed32b8ea6d982a9ca7f1f1a291aae389dfa8d24f625c3d78a5388983744f4bc285967c5315f0a8fef33b1d9cc559c26559beee95e15278b5732f682affe4553713a71c95f63bd43f7888a63ca9af4470a276ed4e514872d95f073299dec8b86294e27d2d55964d791b8a1510ad4bb2484606d2d1ad52ebf7a5e4f8314e7d3af495978a996138fe2245f72b282981bfd4b14e7b690dd92d0cba24f0b83053bf4073442719221bc62e3824071926caea5f6d54f9cd7fa26cd47bc94157be2ec63af7a21749526b71307d3f43b2727cd024e1c368a9ed2772287b8b78953e51871c2648ae476ddd042c1173834b1dabfdbaeea9f89634831d4456e996b1163e2bc394e3493f0cad1f512e7dbccac4d1b4b1cb206bf90979d912a770f7cc00b30767cc13736f0f191c3559083bda8adc469e654c819922eb588a1c441bbce6abd5fbe723b89a37ecabb67a6bebc99240ee797dc57c7d2eeac9138e50c89f577eeafd984c4292cc9941717af4ee88f38289154e345539ad4d11105d5cd104a4e4c23ce159bd6c47cc988d3281d254f5e2f9d8817710aa74e7e5fe5679229459c740661a262ec2bbc823da09188536e68751795d3bb705b817b001167512a04a1d2ebc80d1a291d3abcbb016130068c27c30c90c046d23844c122a66c070e1d3842906387073e3e7474118617388c17340c71d018f4b5c95cded05a81eb28c4b9424a420419930c5b18ec858df485eba1418873a879b884bfedf7bb00a36d803188e3558ad739a607d010041a5d53d335b659d4f24a25c35dd3c23ee594341047ddd4ff3bf6858006208ec1676573944b1ced610668fce120aca2299926a40bfdfbe16022cfc5d68afeeb210abe00a38be5008d3e1cf2888818692399df8902dff1050e3e1cdbb737d64f68933173434bc78e1c1c46c9dfc32188c4ba4a9d95c22a667a38abc4d0a1ddad46e8d0176084f1022f18a09187c3e9c999b29769c35b37b4ba602f70b4a7c3c34973ecaa6e58a83c2a37b4aaca2a40e30e0765f98216959632c4b6c3f1368b18a1275782fe7538e9caae915b1b5b5b7c40021f1f9eced0a0c3394785b465ba177f39529ecc68cce1f47da696c35936572ec4358a6996c4a13e3fe999299adba183059d5b7c4002957060018d37b880861b90f62252266b56128d36ac6a9242709978293935b541830d4755bf1411cda3b186d3c9ec2b1a26613368d58068abc6d46e6ec92ab4ab2e090d6bd2cca24d230d07ada3d4e476c6447c1ca4d0700c52928e5fafc91454b791038c2aa47186d395fadeb0d1a7b25a98d873940f1a6638e8a493e1d6e1365ee0376c680e1a65385c9b308d6e6eaf5eebc8c161181c34c8709a3fdd2db15e2d47674305ee615c7d41630ca794efd344a869d93bf0f171838618ceb3572fa682fe5dbb6884e1682993349c6ac07094705f59e2e234be708a496edc0daa4e726f34bc70bab9905456ba3e15742f6874e1144b77b55aca9f4908d1e0c249840ddaa382ce328d7d81c32a87ebc8c11bb0f2640ea0b18583482c8b7147fb5c3e2d1cc36f297941b756c37b011a5938ad6e664b0aa51dea7d7c78faf8f094c375d0c0c2c95be6f2a8d39d13b2385e070b72d8d081634b47173876b0400134ae70ce947fe2853319aef2ef1068010d2b1c379dfab30c6a32e9530d6854212b1da28249c280c18e2b182c0c722c0d2a1c4e88916bea972f6aa7318593866fc9192cfd6629d190c2d9e6b2724cbe670c9146148eb71be2afef9daa590b04810614ce6a565a66d4c6d59d9f70ec2f292644ca90acab133091e3424c13ac581ac52464d1482132f5cd2c0909b20de0e802093498709c74c144e8502f3ba5259cb4759d091584947096242bd5b6ef77ed422309c7242126a9ffe5656642c2f1dc54e65fc4348e705c7ff90e899531d030c2e94feab76b5816b9df8d1d3b388c8f0f18ec601a4538087535712b6113060d221c3f833e25359b90d57b08872c979da794dd9ff44b0ae1f499b2e5a5bc662a668370cc5693b61694aaa88006100e7fd73a3e277429a0f183ea455cb60b30c0405dd0f0c14162cbd796a424634a6241179e230c5d1a3d38f9ebb8f68d8c23253776f006ca8d1d1c4681c10e2b3478709cdb782a4296b4201b06d0d8c12108896129a618579aa48393b0d7a0512b7a966a3ba09183c3b598ecffa4b4a34c9663870e0bd0c0c1219574fb8f18a5718363c910534e4c4b25b349c306e7f2f88cc984b616e7f4486b7feacb01868d2bad1cbe19f0a0852ad9d2244630d71892294b51d21bea450e3022f0f1e1450e301e081eb33826533163b8b69452aab238c8beb0cb5dcded7f2c4e3a5fe6c2050f162739952788b8cce315a70ca95c548a76c24bec8af3a974b31ded5ec137ad38f5b668bbac9854dec80a33b2ab5b4c29b666caa426a2c6a99a0db2598f551ce5829d9a9cfda1524615c79141baff5cd60c42f548c5418ceae94abd952435c5000f541c64d658aba4580e1cbc016f018e1d9c819a84c729d4145a8ac3ac2953f54f598d16dbf1050e3036905575a438aec69052d2979a29e85f60a31e055eac0e52c4631407b11a91822c959492bfc0d1054243c3431407db9e0b4b7af408c541f5c9b0c1c4dc28a1f500c571728614798da5ede24f9c523ad994254e902022cf919e38d98f8c7023255aa83c3a71d012b994ae7ab58b1b4e2cc982044ded6d667d32e515559267d34d1c3f35a414db0b516ee2a18993e653e962269d6bf22f28f8a2031f1fe90bced1011878e1050b20f071c3231307d53011d921fc5b528e6c7ce128d04a5f70073ae01e9838d964d92032861e973086528bd958e220b2a72c8bc935a1151c11f8f840c117393e3ed2179cc3a31227a638ffec768848a2521c2f8ed58b687a991191e220839e399529a6d1221ac5c9ce43e5b52aa16e43a238689fec8bbd4271783d15940c22ab061502c5e992a9e0ff2a1acd429f382519245fe8effc8b204f9c841a916b4b7af3fd9d388c7b984c4c7f2b13270ebf212f24c4483ea64d1c47c4eb5811d1ca90268e294d4e535127518232715a1151e269d83d8f3171ca783966263f43762f71b4a041738fd212a738bbccf09bafb4acc45983c7a595d7a04c8512c7be932677bb499cae74879e595efd4c128719affb4c5ac4c4227108faae6f26c59038ecbca68d1be1471c444cfdf33176de3be21c3ba336a36fc471537ec3a4e683117f9fecee52321f8b384accee1337882032c97c28e22c79722693af52a9643e1271cebfbc9479bfa406990f442c97f7f3bb3ec4414d8d6e8590528a6c88b368935af24a55a47021ceb2a9c93784c977318438a4131fb941e8b04c0771d0193c4b8a0471ee125935ce84ac950cc4c9ac92e53d1503888359ed9e58e50f8789a74c248d67c9981f8e299fcd6ac55651a93e9c44b959a48a8bc127860fa711e31354d9997c0fe711d277feeb7e33ae87735f8c14c4fcaa44290f279f57b7602ac2337838c56b3edb0ba9eaea3b1ccc4ca64ac93d34dd3b4e67aec3a92b85fc934b2ea94c87534d783f51f964baca1c4ec2cfef3a8395576ee57034b1294729a12926b5713826b5790dd96f2a4f160ea776dd2483ca1b4e7db14ae34fbe85bc1b4e316d53a269c819f2369c548e8e8dd9fac1862fc9728bd7a1351c6d54cf5e92ee2252c36184e86c49a7f1729c86738c86ea0b115e4c8386f35e9e60a71ec2fa331ccd2dc5fccbeb49d40cc75cdaf1af1a278365389d86889d5a922121ec4cf5fb3886637897deeebbeb2e86d37aa8ef058d1063c270f41ea16fd2453b81e1f0f2b7357e7d9afdc2b172c4f56beebce285536e95bc992ea414b12e9ccc747d9f0c17535e5c385f2e132a279a6549740bc73b5d3135befda185a3ea68a524ae7ab5e747160e1e79d4f2820ad1effcc0c251736d729999a435e7c7150e922cc5d45e7a59c4f96105e747b2a8cb9b2a9c6499d49e31a970dca4f67467ec8c993285d3459f9f778b14cee37aae1333cf4f5138a995da90b56aab86c25956528c29e59e701a37bf52573ae118cefa35954836e1bc2b97296b8895f567c2c94f285d565735ee124ee9db7446d7a86174251cbd7c5316bda64a474938add6ad4a6cbd8d1b241c57f3aec9cba632b24738a697dd58fada4b4c239c529e2431e9ae8b122cc261be34e46c50f91b221c466fd88eb3bedbca100ef25e1b6258fe8e0f8570debf10ee2c262b99201c2404e93a13f3bd0884d38824ddae3784bcfc0f0e37776af684852e7d709468595e2a6308a9ee811db1849c89310f0e9232c6edcb0ece996a463684ffb55407c72034a24b7035b9e7e0f02656367b4bfa18717052e9e2c814732aed3738dac59021638a21371f3638e9643311d4f74eadc5294fcc6d123b5a9c4544927e512bb338ce057929ae85e9cf8a2c8efa95c25c4a95581ce7674cf765cd2d72581c3c94ed099d41dde2af38a99084722fc97f93e48a7345be92db34aa82502b4ef6176398acba0f21569c3389127d4af8d9885671f65149ac6543ac95557138db4b39292615e7b3f81f16648c598a8a93245326612d4d9d75a738ebfe5aec57678a83786b9fdcde6dda97e2f0ba9a14a7546a3efaba228dd0284e39feb29cc688e298f49b9c3d14c710d933fc6a38e92e288e2aaa9b84a845487fe2dc22ab765f7be2f8225faf7a77e2e823a7c2aac8947e4e1cc4e4fd4d1f2392ac6ce2903cd5a2a44b9f234d9cd3fa946748be5a33719ed154693497f8ee30718c16a369a74b9c25690b27532c713653964579055dcd2a71ded95832a88c122711d29252f19fc4f94ff26bd2af501397c431a26592ba47e268deea323985c4b127c5b079841e71f8ae7422a5902a32471c93f2758b575282841b714a0df13de355bf31e2a0627b76e6f089d52ee2605be1f4ae24459022ce75b2af1944b0ec6a22ceea9373ed7c4f45c46135cf282d11a4890e71b8901846c889b6350d719e5c92e6e4a51c3d16e2e0e33b262369cb23210e3935cbb7ac9f58ca20ce25926564aafbee4e10c7d03c27c4b40ac421b8a6ae790588d3bc5b5f89d46726a93f9ceb828e6f08eaf6bf1f0e9b32c577d39a3a4a7d38769a4a9a7b21e5cc879357e4d98f91b8dd1e0eaa4685c83075976a3d1c75b265be8ff270d8cab00e0be3e154ca46bc88255709dfe11846dd89688c1d0ed9943453624252a9a9c331b8bc98480821c5950ea7d0a4c5375b3726e91c4ee2828cb490c4dc53399c648e2f7d79c3ae8e713856beb5f7060ec7f3f4ebd04b4aaee50d874db929e8664a22379c527bd8ad083fb7db704897dd4ddbdc5accd8708825f32b8c848b351c66bd725e4a951b5ac6025ca8e13c793b35894c3b354269385d5bce1422b7617915a0e1b0af22e3c814a2e30c27b998bb52fb8caa6a66386eca5db6e984f6d1ca70d05411c63c432e9dc908b820c3e93662d451758de1a011ebf4655913b113c329467e454a9541c77d26e0220c2711efd4c830290b01176038a4107afec2d1c28855e6897053ab178e71d6d9126335cdb43ab8e8c2314dcdd86c4674158b0b2e9c77337a9814918b2d1ce7c4d9ab67584dd9b8d0c2b1aeab7ebe7b349b908b2c1ccd4a59c85fac6b0862e1386a34a8c9fa0e29e152573856485a7f2ff4c40b3e1756389b8964af419890a2e92a9c4a7a69f650bd32497301175428c932614a5d9223635c4cc1982c68ccda1a31d85c48e1244a69ccd03e4931d91586171480810374e8e00d7ce0e3e3830a5c44e1687fa6f3e4e88d19291cff85021188800e76c1c787377f0ee3020a27b91ad3b9e9453ee114a6d9c4af85cf4afb8b71c2f1cd92886397ded03ac39163476982176080610305396cd81000174c38585cd7917e11308e005c2c217d81c3055fb060005c28c132212f7e2e8b48471761b017555c24a11089266a19c943c48694541ae9e0343bbc782e9070343bb55e2a92fb8fb68b2e7058e0e3c3065c1ce1a06e7721a410612dcd5a1fe0c208a7ed2da979dbbaad4c1d4538a630d5a99753229c376dc2f56cc85de22326022e8670780ba1c557cb4226025c08e1206a74df2a5782708822f4895429cc84481d2e80704cb5144b33f76b227c43eb07795e0a32bd6c7ab9f0c1c1c2b85f87c6dd51312e7a7032a5e36dded75ee560efa251025cf0e01462747dc92664cdec5cece064ee726d4145d120ee0dad924a012e74700abae9325287c6968b1c9c44c492efd6f80d2d1c1c93a6dfb4b10bba5774432bd16e709cec7f5fca2b9c88140abec081012e6c708ee46df12c555003356a71dad9202ec9976f68edef6001295a9c6b2e8993a675ebc0e14599408d591c5b4dc62eb2b23865a850262aff992e128b43cc90cf2f9c960465c1e2147287b6049949956c947bc541b89cf286d6590d571c27a8d93ca63795deb4e2203e2d47fd66cef8ff8696b26163870e306ed8f82287819160e0b011868e1aac38e82d19b4c69890a2e53556710ceaa569929d570402355471d0da3bff8abb462a8e6ef25fb4de5664773b500315a70c192f29f447cbf2539c6df5d24cb5925caaa6288b440b2e6e1adb5542f0d1963566cabe612ac52988ae2c49547643cb465ea0010ed0c0052490c949e19d78939ee1ed28ce1ac247a828db063544714ab2b277a68a23d48a6a23b986e25cf99298d11dc20146086c941735407192b9620c4a84bb58658d4f1cb3b24878bb78e25c21fa2cdb52cb54df89a3e435cd9c675ebf1f270ed7a55c6496c6487a13a7f44c72e4421e5d42d3c4b9f24991a849d34ab66a64e2287af49bd037223ef23ca88189939bd6496fdd2193f57a831a9738c6661251ba82b486250e21e4cd15e4d9e86b5e89c35529517a3c4d5aac3d87da28d691dab1063528715c3791446d526908f3240e51cf4dc6914b374a2a8963856ecc7e0dd1312d12a8755599ba68994c21fdb24c522f41e26c2ac7e4ebb29032ff6074e1818f0f1d3bc0e842c7eaa0c6230e1e9af596a2dd9a501d7136954f29d5a4469cda9258516357a73ac30892a90617cf20c94c4bd42a9a12f9f32de2344135e2c90d49546baa65a8a188634dc8593b264cc4b1d4cbc934f3352b39220ec2260599fcd721b6048c6ba864ed2563f2602c140945e270301c0a914e57b3130800183c200d854291503051855d1f1480025f341e38322c1a201c141016148787a160200c060943613018100803426170301c5a8866241f7c84c2eff0ec64423b28a11144a2eb0721c0ecd1103d5a23dec3cbe72d3d5e8ee861ed616b3a03c074a7fa908f61bd21fd0cfb6f941d155434ab9d65b1ac88b1c16ab6429e82cae3bc5a35c694ae55334c495a5eb22194f1398793924c676b3b4853f5cd7dc9ddf05b04b0f96ea8a4a79802a305b522ec12e47b464611e8e6bf719bbf1a7c33bc1d0d65822b53a6fd5d80ef250332b0ef1dbfcbb69e66d2871476122162a5f3d243ac29cac672b0c070399b9859cce10cd63d33fe12bde17f2ada58f363f52748ec7223009fc688349b889476249ef41fb8e17ca520308e14678c19e6c377500547ee4967928bdc05f2d1b1db8787f54ec0aadfd063f29f4af3e6c405635350154b923b56bae8a7a75d635647a339111f5d47ece83bf0c7bc81985a8c4f42807c2449a334519a92e81e9ef879adeb8166cb51a9a70dcd69ed0cbebbf43395fe86a77cd522f83130d68dcc64edf053de009415af9776fc1ca1a3ea501db2396c54a9fa62cf0959a2a1c8cb3467e3aa0616111bf1c181f568f51c834f294116d88c7ad8d7ba38446ae5b1cf42e5c9e4734358abb7e62012833ecb1b8bc867e2744afa03beb16a467c2f2b4b94f5a929a6517f26ea1499cb78847077bf7d0abcea7f2a12957da99b74852b8f3b1356d75a3f72a5f19a448cd244bbc1a14412d61366f0244007aba70ccf0291af8ade0edc47c0acfb5a75bb5972b87f22fe9472d47b557817915e7c4285cf39af758249c5b0f704de8477f25ebdf4f2cc3cba0ed17576aafda148125e4d99c27beeebe04a9fabb4ed62c279a6d9518e42b4905ca376152e8b5fdb52865702d6a8c75955ad1921f8657da01d5a3c44393ece33039a5dddc9857237da40e71a6cc85b847b9c4d0f82d130f2769105cabc4677fb2b2f27eef20e7a6a0e685c2441919fc3c9987b0729b0f6f1d936aede758c887128fb08029c8df7de2bac2821ef1ce0c2d6c60b23df0941e60989e5f74e794d4d7798a58697c57db37d7da48a0090057969a6ab6af63e601faf5e9db67e1546902de75cc885f87e4f2f3c1b25880b522edcd7c539a6941e7eaeaf85a9a025ed8f9343f17223e137703b4f30fb7fc713a3e6d46ee894cdc6767ff5e3dd393c06e6e2413db0c3b5f4a3ffe3f0b597891f8b9bf2a9480940e55a1d369ec42d0a7b6032b0646021f9052aaecfeb24f02fd4016b8d39a659181f91ea209251f363468fc81745c9d4abfd88c3e526cbdae55279c722f569cd29d68bd0493ec4775e9ef617ab58df8d2c6a0492833ccd4c84b9d0649106561bfda2d0d6f93bf88c4e6e5a5388f49d872ae609f71941b73974d339bef57a8d5a81cdb901b480522b235299af35574ff966fb535ab2d817ba7e88b8bc2dc189148675b5782c0dbb1b0181f15e3798665dd0a7c398f707670818463cc2ed4000364eba0daca5c93774d6a78024637d797f2d5262d684801a8b3762202933ac28b2376e3c30c97589b40e9f3360466f429ebe6fbd9ff4f8685d05b0ef32122ba2098f2112cf79b79ef48be3d83f0d66e125d398112c32706584d8a90b9d7d0b871f2902445714ede5f9aca26460d3efe60944d1d86c346a9d306910965a82227a149c79b1cda576d540bf47b64800d80abeaef003928baffdd2ddc3c41c35257e63264ea125a6098b0998e17a169176734f6bc2936c215512f863b71391f9561e4d8d4013e9c662b338196bd17a90736dc2704ec2fad42b72551dc08cddde5c4897807c981b164874c42aca5643deecb62622205bd02b895e9a6c4413552a4b93f089621a42f5cc7b106b333e097e094a741463a18353e536b496132b281de908013f8d100fc39941498353dd822a849eeb2bb617d1c2a68e3ad0b05ccf453c9056af1746d7f0405f00e7581b3ed76687f5aae263dfc2f99125baba8e5ba99037c77ad695e47d9b41f83f3e9db3adb6eca8e691636374bc8d7ee34018e6a06ac97ded5e939a62ccdc06d32e8a12ca87dda4e8c6a626292c5aacca35687aa62a021bd81db77a8d2767ae38b1366656b014b0362a2b2d82ee39d17c049a10d6b93b3bd536b89e98fb4ddc027468bfc371781b32d6b59c86114c517abcafd9a879fe2a48ffc2302fa9d3c393e2eef6672c252e73c380e7143b97972b22977819f9911d7e414fffa8570c458161ed7ab40210ddd4211da9ba46740fed8057f01d6032617e759566b44dd27a6ccc7946a15f8ff041fba785cda49e8badee9dfddc1800d5f0facb0e2a700614c67b268132147619c224a6b0049ef17c2d2b70821366b98feea22767e9e5cfad52420bb28e28cbd0c69acedf324cc2ce08af0926c1301bf15e07e0d8f25ad802e811f47f1d666018a71918b8448b61e6cdb3705ab5d703cda0b6efd894137f3296771469ca92ff8643e3657280ce3dd26d07a1884995b56b8b37054fb8ef3001e5d98f9349347d781c8062a711a896c7b9021a753b29341d24fd87aa7a2ad4c75c8aad36c870e4fb2f28152d5f912b4907e73cd9fd9ea76aca441a597d305a14a8c60e35d825627abfb8837d4b94e6c5f4004bd99efb3acc89965e93d4c4d454b9335b0b88039869f79c490f45f0098e208a08b83efd87182b54acfee3c01f0cf81e0f3a916bc2ab7dfdd840e1f111e3852a2ab5d8765225a04690d565e5357dc581856b0aabe5bee10f0af4e709d5f6ce9af4192059e6d0ddefd724962f4a411cddfe9ccb2faf16d3825aa92a115fad1805d9c9bd06bd3e71c1eb1ff2cd2b638385a741850ba8e19c4ca98607ba1c83a0c7640158a1179e6138fdb1243f81a8a8fb3f00f00cf4391058c7a170a604a6b021335c38ed50d762eb07952ed60649b836ebf808c04973051e5a45cce2aca534cb437040a8fc81d4ce8e74d266a4970cccea2415db8a35a026ae283dff46171e5ce889509a68975211e75990782bbdd0c53bc20108eac21a288374a9960ae502289112554315deaa357b50fbac9bae2a3aeecba95730ccd6e075e3ec9c9e33cb9f6a41321c8d3fe69c8d726fbc0cbd66594265842bd650f521ef71c8051a8c104e418860812b1f0b0e97ab21b092153b7c4e8b7711e6aaf0786e50cab891a34983b006be967e4ef8338e1e35671baa1a8f4bcd52b75816062c7a05b12dee3de11ccb9f126e9a90125c030b125bb4ab207476e4c9f284617ff3d66d33b7fe555d701e6bf564416825312c9fd8beebc76534bdb1f313325d0fef0eda90a4df39c967457b39200e45cba8544db54836db93c0a3a9d20602f398ad9ea0ce64c87f90f304dc3bff433457e8e4db88e3004fecd86361e9768402cdfe4e40c9addd2cdca954e6273b4d51446ec36a3a85491c96b86c5a2933ca8b9bf08afa312f28da2ebce200f96bd52e255e6102616c9774538e602f7dc1dc7e3825737cf5a5bbb623af0694c3fe16e13725ff1852fba2f5239f0184e86d3e8af2296765b679559228322d08420c4839ac303d854183bbd5a9f0a9fe33b21accf67fba45d1626718d37ac71353a151b867e094e4629955b8143290b353554ae83fdf77ebbaaf5a0b8d785beec8a80b32d6d01864ae93e576afe3c0f89764220c047903a89ca496f94ce87d9780c6aa571219ef2ec9b8683c3a7eede506242e8a9e1e68816d2d409368d353c42f6d4c2bb22f338b7e4174c41b4925ba944920b43fa5d74f5042ae51ff2b3f48f6d27def27e77c854199b2df4948f421fa669674e235f3acce67d64e3d240663112113dea6c911fb91531719b0a74706f6c1516e8e8446588bb801afecca5cb990ca94fe16485978592ac7fdfecd02cb5c603b453cca1418f208a452164ff58af46af3dfd7d930b74cb1100840674efa723e12d5990f016c77c18510cc300837492ea0b1fa0a56694e771f2f839ecbdf4a1037c3a3ca31924c8116952d7a9a3440b3500c821b42064b58c59d29297b75ffd6ba51356394dc1ccd169d03735acac6c32c92b472521928058079ff2bbc8fdab9284df7fdcea340d0506ed29cf3b91bc2893d51a767056bee882d75af6b54c65a365ccc270f291cc198b3eb1c20245a4a9694cfc8a20b771bced88d760a5610f81d65126e7f67a727c194b7c9af2f36a42d289df9e7ea8f1a0a8b30b45a139ecd46678e90bdfb39890869ba4dec0d73dab56417446355253a519dab3e42c994ae3d9620572652f045da2cf63779d154459e2771cd92fde01eba89bfe480537d652d4ec9ae16b9c962b6e246694806ca8fb144776d3a768995f4e8342c4130cb727bd14a1fcc9567040fe935acc27171103e9f14eaa163a1e29d573244c2139623fa50f29d1e41119cd90a83703aa0b3493b9400b652eb57a056bd3885470e0841a151e823ef03d471ece7a8c9bdfde07f3fa3dc01af93d96f70321b230eb8dda158c00055b1b3855dcf38fd9dbf2a17f0ae34a7285baa2231af779f06ea938428fe67bf638fa81db58ce998b563523920d86dd6cf6e1a0d85d2fe89755eb1444dc7265f410ec6ed49c5c8b290147e95801f912da0c80988263237119f1261466332193b4923e9d39c65ce259b0dd3ca0cf5d0dd2fbf04e7ee2eb70413e568151bdde4286758da7c215a8d5b8854c5fec9139ca609933c9a14770c74254aa1c82c0713680b562cfaee8bf47453240a2b452d5427df7df7f8dcef90263d9015d931539b0906508a7f00c152fb0e101c3c88054d505f0bd1569a638959704051bd3ecf8140909ca8ed2eef3430b62044c09239308c007844a1a051577546c517bfa7554d35faaaa0ed57214a1aee3952fc95338e8dd3aa3be78b393340b97560424448666cf3786100099ea97ab12601cc424bc21d23a0e1c880f2e618073acb7ea90a1a1e17897bded3caea5db8f341f7fd040fdbb9d31dd138e63a89f422b6fbbebf5b56c993cd3887a00b71b4dee328665246151e4eaf0ddd0067c28b565dad781bbb4c032013d6252e397110e56ba275e045de26c5d6e1e30a0606461cd61255ce45cecd9b589c056288cf181a4b3e015a295252241aa00efc845562a5cd6cdccb84651f9a1d2f91e7fc2007d4b3170901e01842274036b28d6f61095572664e9521310ab1e1045c0d60d47316442802efbd7864c5cf5dfd2c5f51c4b7027443763e1530b4b54a71d94263f020f6dacba42ce63e1c043baeb4e005fd6d81a95261b35deb0ddb572912a3e8504e085769eabbd8e4078738152a73a83643911d208afac0474a23b5611dff452e839180c6480e7e844330d604510617dcba121c325c6c1a923238bafa22027c3101bf7640e49c462c92b99e65c14eba75509795fd5ec03da3251c3df0a644a1de923fbe4ec060448abb300eda72dddd5f922f334aaf2e96a133e71d9116773d187608c45407bea714937913e3593ee116bf71bc7031edf7c97546834d5a24e5872379ac69b414f55955ad01acf1ebf1d20b4bb330e2ffa6f0c3b8fdde2ed058b947011ee120c93f7a833e9f2e55899f685b8d13fd8fb5de4a4cab1cf315408f14365f301340633450f073a50888008ab5d5e99a0f840bcc4a10dabe17ac187eef4b28966644032589716fad1f9a8b45c479d15a01ed9f2fa4c6485b5a6c310e846cbf7d38c4871845655b437dfa8b48e918326e7710c8d2b37b104391383d5b33c890a54b81e42f78c961afb3b6d2d2e2c88cc73937bd1e7250736c480ca1dd9162e426659e01d4405861aeb14adf80d1f08021e5c446299fbe01903cb653e490e32dc830be8a0229f6f620ffcc38c5b9f5cd827c2956065cae0b1bfd6705d254be5e92be8ef6eca8b7a40a14cb74914c23e825afe02ab2aa6633941d2a6a0c34f3f4a68c054648eaebf959dac7a1a0837540b26d663920c7ed7bc6dba65e2c9460554fd8455ffc3d20c3094dc31f7614280c84785de08deb070c3b4412e3ad69e5c5e655e73607d4b20639e327622a7e81f5c7db1c7d79fdb689ea88a2683b3f7f202bfab6da84c251f23aa4a057228a306e1abb45baf331b1da5d4daf933addaa341dfc21c178867835b150809e356ebdc12feeda19143864b114dc118647ce2f9239d5d0c48716d60f7a8a7c25089671315dc6f3a30aeff73fb7377c452f84936583a6b596db4e83987c89118e4e00c7bc950bc3b2f9906111a1782961dc7c602c05f35bf0ca9600b872c4057b42ff345d14e7949441acc8331e1545901c3f9eb1e804f4f4c25f826cd0822ade2a181a7446a5c014a7129ba5804a20fb5a9bb284f1608d6e97c868fbe1fd1704f71932bc184772ed370a281b76736a32ac18c7a10d4ff9451506194e610b2fab4d98999b65545d18d77020d92119a70c396342ba3f6dbdf191e9a7fba52b37c3af5c1fc4089a7b25949b76b64614a590f2a4f4baf2a01a97333018129e756e9b94420f229d1d5af1ce66719b82fdca9692a4b418374637a3fcc9dceec6b0f16e710134974013f3588046499226592318b7d0aa1548eb8fba12651ad20aab08ffdc71546c5006fa1170e6049e278654e92701150de35b126c9461187bb5e61b0ea478ea4187a23e20c2718db5befb746d11ca770fe0e895ed0c59c90b0cec53ae63f298f602b0cf212ef4bc999928d962df608e02406986f67b75bcd9bd5d5c8d7c4204d99f01e96eb0bdb4e11a9d1bf2ba17142bc5d79ffb31b4ab4144e30011b02781004b9a3a3b04dcc7ac9514ac054dda53fa2516a4e16af3ed415eaac51dad501841208f1f61e44128b681077143c408406dc806f8cc0830d75f0b8b88d8370e99889fc63183e7ae7f028a53e61d0eb71f0c66d34c8a900459c35e6359743c81ac04bd5bbcc25da641d29231be02d6caedf7a56c72b853af9c4d6d553a8e71ab86c5163ac4ccadc3a824f99e59da835987001c9d3c546b9f2df19a391a6c2621e13f3ec45577325b97ab40faa372ef90de2e0a8ceb5fe0065a48fcf4feac80751c5409d9c9bdd675eb16d4f33ffc0c277247e43291db22476b24c58c1ec79ba946657d0a588e379c3a3b7d0cdf010267969a94451164b309f128e5e06a16785373f34cb6a24993696c8fcaa54e20fa4ecd86c4bf0edb175592b9fe2292c12c4b6da3c1cb5270ed3db81185d8c011b7dfb787245071ee3335017e58aab235074ad6c478265ee887d138cb90dd6b5676a5cc6123e142dbbf5dd3469665ac8e7678eaf14168e5e935bc1b84d432fd95db8d9aad5fe6d94a02281a6a846459a2096de316a352b87268e11447b1431d543959d5cc68fe3ae8a478e79f403a88ce0290b61523754c48ec655bd1c4c9baded2c4068560379945db3412db93f88bab8a7630a3ecddae773f6f2aab5b7f740834c87eef7906a8a79eeabda44b7397522e1d5dc874219bdd6c77b4fec87addaf76ef89f79c6de4adb9afd7697bcf67ba0b3954eafabf775f7b93518cfa7ba7e87db3f715ef3bddb4a07bee210a192de1055e789bd7adcf3ee850b9b2b7fe55ff18057cf7fc30807689eeee81de73b651c8de79c998dd6cce573933c5eb57f7adbb751af3c973f95baf2dd36012bbde8c72f73ce30efdc7a1eb60ed2e3f475ea1a8bbf77921d7455c7597e3f99dbae0fbc92e7fbd68e8adf3d3135655de7d6d26507783f9cdb837c7bd7b7971db05a7bc757383c940e3d2cd9689932d237969b73be778ebb0078b2619bcf5997c72d52202f1984289cd0793db96fb363ba551dc29e517dfaa9b377e5246b9bf253ea6f92ad6952540c0e315bb12eedb28816b82e6af93d2861611d0b690a38456462f0f285168c4dea8c08ce48972e9d06516780514c6440532cc071a88c409e748ba05110118ab48a4a46bf353a9592a028919e2f9cb69662c12ecb2056484bfcfcce2229b51cd526a583692890642a69646ab723aa10d6276abbd627cf4905d4e696b4abea0c70606fd73c69c671283fe6d673033dc172cf7cb88642ffa2f96eeb117a43157600f8fac1c6c28b4541e391e9903ff0ac0c45d51e9476b46e84f898b676d98b048e4b7b771c0f6e3b2e9769b1fae9c2077d75d2bcc68d3e99a4285593548235e66d1d3fd5a780d2a6295e1b126436128fa1a7722a1bf7d818b97ce5010351622ec97d624d2d4683640db7cf1c26f6677568102612a55dcf29402d4220cac59b484293a887e6f330eb678b7be1ea3b020187074d9d2f4153fba25cbe31f4de7340ff42d7002df94f554804aa76972fa211917c1ea83c5209603540a3e958c9f0421c93ea38c9acd75d0404984a1a08c4237837ee55414ad32beb0a23231fb747a9750c23322cae934ebed9054e1397524baf52e08579a97b7c2d49c1ad4f79604eec474cabb9a9a40590f46222e286b91f1ab83e78c435bed7092330a8fa59f2f005b35b290d1e3ca063faefb0fe963d6880a62ba3c3c7c20be098adc832c2905241be0e171c2e2d3f16322556d1ea338c380fa3248c8d1d5bb749e729af61d9edfdc5b28a0b72b42aba9c642dfa7c2d81026f6ab5c165e4c3284157badb29a79216160259975e95429f6419835bce42f94a09172dec802a762cb6aa16074cd65c2ecd76de1f7ece4ebcf1156ee45877e2b202d98a205d5da8e0f55e80c00d8914fd8fc6cddfb9b175a23ac86ac455c3e40342364a989d4f00f3187d807625b7b7e0f24412037c1f03722d898a84e122f51d232036c99818a2262cd06286a1c032b53522133dd18e2dc02fc8412a3f7e9f93c29f409e15e6b283fba375101f787cf7e6822ae0d0720b74fb65f9a2a2fe24dec10d6705a66176ded08f5568e9de4486bbf63f1136382712130e6363dfcba42d5dd9e8241d8f17111d36e810af64c8591ab900492af40c6b9fecbc2a6816240245780d5047305ae7720d324c40b841867ac7f00bb2b2046c05301896840805e5ac051294cacc6d2a0609f59157ebbb466c12402790219080cb9810c36410440e320c34f18151bc499d7488311db07e2330e79126aceba0637c246a8995034bd0bdb04c41029a0e712c273e593cd1bbad3be1509eef50e3963eed6145a048a431d81b2126d3d388d542d3f28501b03635862a9c0073033b3df82fd2e35a27c568015017a2832fd4ea16b45451f001eeda468d2345302a01780c70090f079957dfcee24cc227078008804195b0eecbd2343275c322e9c27ab4001a6480b2fd6e22eade6d43e524974ad879815c81c1669ec8120c8845e20e292f4b5c0adc5482020593d4c70d883d3332b266a5605ee311e02ee93023c0331df5ce83058f172ded501fb7e18491459862d39c35c24db84f403155bc83297435dbbb73e484d60d217889a11e44aaa04fa98f655b6756a0a6d03d207de456beef207bfbd21a514623337bf60e6176402bb99f88c43a615c799070938c188815efe7deda0850a78fdf64a351e0554ab87ab759e7f8e6f27b90ded574efa3d1ea90cdcbec399d4532bf76ab64780b90fd0c1af93b0069a9110dbb66f15f2a2518be7af7ed5f10ef4469477ebaacfd87b37b21d28aaafa2c801ad0530a329a33e1381013d6b9e2cdef12d39b3e64b51ba83693a9af53ec5e1ed3eb53a71546c3e80124dc738a2b8a715db3c423f012ff4f5e8a2951b86007bf4d4b73bff7a087ab32d54eb03fc3a68ca44397473f11541ec37a9af109eda4f9a01fa2b80eb7544231b9cd4ee71541c69d26533e6b1466f31e49ce02856994c8c5a37ddac731e62697fc040690d2330d8381a3570646c6a58828d45df82d446168d3e6a7cd3c08f1b47ad6873a796c6933684d916abd69a931f9a07615bbdfcbe46596f94a0cf01e26a7224684ecf43fa3c0256fdaf36b62776421222a2a8887e686bf14e45a0884f82756636690c08d5c0425ccb1951ff14d111e5b08f8580a9807ab3b376ee976536035c1c449d1100a7f376908ae770031e97d63a17a07d2c1115d3367065b3219dbda507fa01acfd636fffe7e95488db97baca644da68d57fb34014821a1eb950c8fc06eedafe4c79fc103c46e6e1e2cc99a046e7fac59241294eee21ef90657c4c1b10174957afc84b67608684820d44480e08c970dc8d35446ecd070fbeb06d6356efe870021f5ea5f2706c2b25b845698574bed4ba3bca0375aab165434129df7ebbe81145bec1499dabc5d8c172636645670405f14a3dea19875fbda6ab6d81e2901b9e486271e86a148af662ac35e06eb64c8d9c3901c1acac0d3fc3c5e2c9049ca3b10602c559fa41c06224178c28e41598b8637c36423268fda68c3dda708d14e24d0555dec1818ae61ec4847c73d0dc438ed3340451719ca4d6704a8d1aa5e0e0e8f87ce6be0a4cee000fe55667ac860df5e9efd76d16761240db06961e7e0799e81b2de4c59fbf84448690b9bc900b0c1243449a476a0e4158bd5fe1b325c11e8821cd5cf2bec8c23044256d89c01fa0fdc4e52e27606357cbd7a437178dd7882a1449dc449a1d2e4bc6dd0eb6a498914090d486c931a81204a1f3813f6058806d490ecd43f55584a23db77a1696b0eb08d3080baa8e66d1969ca2bc931231d963f45a7678804041a3776c8311128c765dc78592bcfba6556d4343c99adda27c82229fd111a674b2d3f6574a826a7e756ae69ef9e6c40dcab09e6ef25edf419fc8fe486e5429237c262c042636c595af90d461c10525793afcc4542c2d5aaff30b4b333abc17af9c54adb719a69d86d23d0ca6ea278495d8bd22f3bccaaea92c6e21306eac0f5f6c597d446686aeec1d81e9d585517647b6260a88a9cf9554ac5e50f831076a5080ab9b9b08c68b8641409e6e31fc6ab585270472e783f1bc3ad21c84f226ab62da11656c81431fa2301d1a8c39f58fa605d7a5a04fe4f5885b3c373de38f89cf28759843af086598354bb7511e797ecd2b0d01a429dc002fc7d8af8c1b24d6148b0b4798009556f737cc1eba953686f00f03018a158e165579b56d91804430414363c03d482dcc07931c86fe69dddd6e853df32f92691116be82f4821b651467e055776125acbc5310938aa5865ad934686d853c3996dfdc5823c9dec492d3b8dbac1ae070b3d9d9d284fba663877d9184033007280e350ea99b937b4b318e223b044887c9b6225c68ce1966bb6131b928f8b226e452931233ca245e7c676a4a6ca1936fa4fa16bbfb7b4d3c307603f2691eb5930e06b5236be99466fc070c4d240738cbd450a48aa111c5fca79391d4d8b31e98f1f2083851d3bf0036d78fec70b38a2882a81d30336055ba852aff49431b634f0d210e7002a3d702e5f849eb44000c58705371c66a95b0a70ae0b5b31a5c0fd7ebe83ac199bf67858b4b1ac381c9dfd27dafce7f929bd694ae78c8efbd2892075906f0addd62b78e62114889016b089bfa0155f0828986df616b4bd86803228cbe51960bf4f7760543db92a2c0627ae27e1167e2e7e3fd116f1fbf722267499e7927a1d3d33c25d38ffb1166140e70a998c0e2a4d5c2ec2eafef651f277c8c1ab45f88df32b52e4be8d7f58b229c4ae110fdc864aa1ed056e99e1b0f2a62e085c6b64480de3077c00dcd7876463ae8d1fdf3099679fe5138d4f93b533832c45865f14f9fa7236cb40211607fdb0d791f615590406a0db0da74201c2f73a07a008058c9eef73be86e08585d84681518902379b7dde757889c453772f034ba67f51dee09527b4ac26dd8410f95632f2345eb36999ecbb5cad61e2bfa4457f9794da2112eeecf5fe92ea3d5ea380db83f7fc78ea7867dae0620dc29848c0a3bc0ab0abc0f055091b2ba85c016c5be5bf35018848becf2573184dee8e6556e23e348de62237ad8e9193ff5aa0d71a11c07f7dba8479162db8bb014da86cba9c20f3b292f848304ca368a74f527bcd3eb8f3be0702128d4bef893c4bdad60590a253c1ba08f27ad484b2a118d2d0781ecfbd1e0f60d05a6c30f6c79675cca56f85f71f11af3f347e9a749ea223d8558609010e492ddfeaa5751ece6d13960b438af626bc65800a5cbd80df180b48bdcd36c0939faa7bba32a5f78debaa804eb51fde9719535696c536d146f1b0fd0a83849c3211819828294a8c6de87a2ac1482cccb9e33525d0cca03f58c5cccf49ab7bee93e9837e114b4c45c825d15a52e713c7b61467339b412b5a5f8c5086068e04c99d07142f2983a2560fc9062557a5557f3aaf6c625d13b266bd2fa3fbfec0ae91535fb3ef314ef3ae94b5879dba62ca75e3df25c1c54a7e64e55d7f5d86885e660700fe300b26139af2506f811186971a409b8f23155e11db1689a07311c9b9622a03fbf4746b028958eaa07511259ece4c5af0604db9f3c1c4e948cf815b67d0d5a3335d66aecc9354c0f7d93ba5b6999b3c7d7d076d910890a4e45aedc1ecb0526bc7338d6922c7733abc188b1e0fae993354a161c9ef3deb291b16faa6c34011cf68470657d4b0b85b5172dee220345808c707398c72228819d6f089d6e344bae2dacb58b259350b387bc340346d2f25d40c68f3ccd6c9959685b8233ca830bb5a748156cdc223204e893aa501cfdac12cdb9d7b7ca024f090c17b7aa9e8def893f5353e29a8951b8656fb9a4691327277eacf72d962432a3153baa902188bdb781bd77916790f9f95f56730360d49bb4827f7f1f0d372828faca220680c7477a51f6637f5a1d527303120ff059ac69c50df845284b800c175b44bc2267394236d12c71d15d9b99824f16db21d0abf4adcd059aa56f695fc9d2b3d0cc16898a1ec995b7bc95744de899bea46a530ef74fe2be8f8a2ef4b676ebc142320635f0054e83388facb718bc6400081b2555ea21ea4a3b4840850ec87d6990d3f25b9c65252f1578bc32a8d275de2f8411dd9aadaaed8917777f619c70c1ce020514b0790e0261965627dd5cfd91443fbc1f9b5086bec0d1b55c36c92852e242eb94b91c35e0d52e352acfea2cc1c963d971a28f13cb74707ebc67de170348dae1c8c6fb684bb8ff71daf9d3cd8f67bb943aaaf619a77122e36a92170d9c69db6894e77d0d1a75ae3ea97eba8b13432f7f490b2e4585b0f5ade525ca1503f884941f0a64e2e535c3199ecf55ff3e98f4f1bc040d3ad83d3849c26fc99745b768d9601f0bdbdb2e14024fa9d48883c5f622982d786ae529b153bc6dbddc71ace20f32802a5d50432e0e930d9fbafecdd32814c8990b7490a0669030f1b15dae5d8ee48378d4293d1885d6b53c2454df62f9271ee5d7269cc03ea6de473cb1f8285624708b31db90d3b158b746d07c8287bcaf83608ebbf02aa69fbd580b40684530f728d60bb29b1439784a689a8984926dd83f7b6f2c732213141290009e1ecab0b561be77e5380bd91d1def5689a8f07c2a77e6304ce7e0d0c0cd01fee5e7573c4fc44873ac9d713a0f9b4a622bc1f401f280c68061eba246ae36df501da68bb893740b2a4d001ffffffffffe7aab42bad5b3c631b21b3b5d6ec27c4ca9424195354d8c814c894524a29a5d4cfca0adb7700e77c3c1e9b2a1b8808950850089757527199d2fc6083c3665e2b73a2969a6e16be528e1d15fae2e3847a43f268dbb10b8dcf61350cca0d493948bfdff1b90d7a6a43b278c9f7759d6ce0e53e3dc6bee5347ee3d246a99bb8d69078a566f4e9394b0d49299e129929b4f4c44683060d1a34685c11a1ce4892add00c9d73a74c7d1a92339df020730e7d4113f21f3830bb43a121b931e7929933982ba4d7a63795e7ce0f36365d429921f954fbe5d0a05286e4d3a4bbd5bfd62f32b026b22a5b593ededa826a955efb48139df3a0c690983e8a96a711d13a16312446cfd5e616aa30247e92bdda5e391892f6673e9ad0b9fa426d5a66d6621662f369b6a7832aef6859657921c17f56dfe3b8bca9be0b899bad74dad0dba5c6e44292fc91f1123235c718de426298bbd09e23d542924a9f2bcd2aff779b9585a4cebba2c173d5721e61214989cbe952e62b24c8278b314ab6e27bb566941512e7af3e83d2a43eeeaf42c2e9eb70424ec8a85385fc480868d0d0616e14159253aad77d2da12ff27a0ac9592c960eb1c9a35dffc19663c4a314a1a4808c29ede6514763e03038781c1e213950061585e4a03166325da5d27eae06654692ba67aa91e5390585a46c2163a6b0750368233978fca29e90dcf1a367fbd79c53d4cb09c91ff437c7f77aff7a4d48f88d9a57d34427614a4c4852399a6ecc714ff65a4a2d812f7bab96d96e8bbf9576d49dbe141ba584648da2755dd4e2728c062a098927c3f78b4a5b27db2f242495c5919db74d8990fd83cd6324078f236d98161c24ea084949e63159aaa7367fe346080c176584041fa55d2b07f931a8a543c78e321264742d254aa83de47190c38687e3004977af638c153ce08b6256454850f94574f21c2223d1e2898f9bfe144f4d84242d2ab47243654ed1219c74d4ee4a0849498dd9c959523af91f84a451b12aa29dfd6013238cde4b1410129478f58b50a283db671749213ed37c7ccc079b18617824f3364600824b440d5de829a4c7ca59f65c24c9a4aa425b4c3fd81e0c7f3d5c24e9ceb6b143556e91e82b9bf3c4ba83d42ac4e8f0b0b345f27b5ed3ea26675632b548eedaa02b8976eb18f1834336d5a045e225cd3f71f97ea5994592baf34b39d1d8303f22e211868d1d470d0c1c20e5de73e0485924f7fd5bfe36a5582468cf98637edcee9843b0484cd2c3e68effbc226194bcab7429d4c94ed7704572c9f9aa5125e3a3bd1aad48d81ad1b33dcf146ab02249481bd9f6d99edaf31b7c18e83fbea855247e786dd97519cb36055b5491e82977c9950bed8b5fa4462a92ce3f2f6cbe995ebe5091a4f4bdedeaf767daa807354e919c27df9dcfe2354c61969395332dc58611428d5224ac89dd1483debbfb9cdc410d522475b25c7bd828923278ee4b7add57acc72b354491f81d73174bb58572b7f3c60e1c28831aa148128b215484878e392aa048d864aff51f4f5f7bfa13499e4f37e975fedd6d9e48ca233b66f24aba64b9353a9158ea3f07e9314877b33891a02fabe7206338dd2b6ee2a419454666659a48fc644ab6883fb9e9af1a99487c4bffb992c144925fccbc3aa66b44cf352e911c63ea78bf7c19f2a4352cd1ff67d754c21c449f5e9b72d4a044255b2909ef3a4fba418d4924af8f6c7f93ad86245a714b8d19ad0a5a565a9e1fbff3c1e61c468d4824cc86ce1746a58f592d4824a936f92a5e2148c8880a6a3c22c98407d36de9972caf1a8e488edf95af13a9e399ff1a8d4852a952d8cd69d13ab31a8c48d256593a3a78c0a8b1885d65b64b6ed63bc52a687d8eeb4abfd4cf853c1860e4b071351491d06b16ea44693ed870809cb5441447e6821a8848121eb6263a76dab45ce3108971bd5293990c919c72e7a01d57a355f9350a917c99dd6a9dacd598d586d4dd9041d5474d0d422449b54d5ab6b4c524ea1a8348ca1bf45fba70b24d481049d1e237b86771b994148804d55963e8cbdfb09b06c41d4efba9b01e18d4f8439257251395efeade5d3f246ae79329b4bb3e24a750a9e1e1a4a6acac061f1a519953b19bbbaf9c5ea649bc8cf2576d1b6bec2129c76388e5ee9cd543828bfeb354ed1fdc948744b1e071a13b7848f473bb0aaab943d267afbc98f46366da0e8995b23988d1f97490eb90703eba925241f54a7448d2a6527c7d4ee9f639245d09df146795c3a283655afbe390306a7a43eb4c8434e1909c4ba84d398dd21bbc0eb1dc905c613ac520e53dc76d48fcd6b05c514cf98bd8603a8f9e35242921be66c4a386446f2fb5d63971727346f26832d9bd61c9559386c498fb3b9f4c4143c2e820832cd3154dcd674858abca49b63543927fc8e76bb40c897179a9a74cdbe9c9909452126f99935c7fc690a0f42775aa366a53c490a46263fae4fc3024a8ff941edc7c30246d4a32698f135e22fc2f24bc08657994aad1bbbd171264a6f8bbec8e2fb2ef4292ae9c36e5545294d0732149fcf3eef674d5ee5b484aa1d36e89d80d15a4850475fbd9bf948504fb28f2fdd288d8b19024835c5163c24575e60a8999274bace573b08b159252b8fbc8982d74521592465f734cdc54485eb5b7d3f0149245ae7df88ae249c55248d2b90a1fb58d42b27b86c69c9975773423419cb6641d3f6ddca19074a7929acb5898d29e90a035683315436cef8424d52ea1196783ee9bf06e8fa7cd6039139262b61cc7b4f22524da897ef6110fb24d4a48562fdd3df24f4282bec77bcc9e4bc60c1292ee3f4e990c62ed1d21a93dffc28cd8d4ab182159e3c77dccdcc59c32925df3c90d69fb49ec2224c6a46be386b8ba94c9484cf93a2b9ce5fe6d899068ab41dfd2e9f53c84a4ce223ebca864a7a910122f06f1b2561a9f1384e4131a46798eb9863580901c7e94ca9c611756ee22495e5e189d945817c58aa29a3536948b04a1333aebc68a300de122d973d8d7eb18540e1aba4592d27572af84094f932d9263dedd8aa1d7a74cb5484e21cd7e63b8a9c86991b4977266919cf47283979aeb949145e2077131d7f7c9fd639178ff7ad143eb8f07164951c3f3890eeaa7bd22f9b554cccd5c9178c194d5b5d589c5ad603f58568c5554b74eda4a248caa9e15e1a144728a2b1b7486d2b8b1b24924e55f783d95a2c357e9d924d1c78ca6cd7d76570af37ef72bffe121dff6f811834012c848c823bd9190479148d6a449fa7d8a118dd107978d843cca1a068904755ee9435632070e46d41e81e4f840f688a4cc0fcb9c17b3c9b594c3032de41dcdaa1162b4a7e9530e909b8035226994ee925e56ea0c1823924368cfa6b3addf69e583cd30608bd0c5b2d95bca58d44ae61a7beab5edfe5cb3a68a144c1189a3630e1f434bbb52ff6043233b3c446e7cf88d316e808cd4f5052c1149276d64da864044ccc1eb802122c1e48d9e5bae774f9f0fce432498e8e841f687aabeef83cdccaccd10c9cb69ccbb5a95ac10c9a3f9c3e91c84a56d468864d3a4737d6b21c4bb360863c865f7122f4d1049a32afe7fecd398e214880419ea29e34459d2ed0144b27cc8cb6e9a37269d3f24ec78e770d19d3f63e387440dbfa1927bd21997ed436210fd77297b6e64ca3ed85acbf890ac292b77e60c7eb0d9b061d8d2f690a4af3fe6794a38403c728c7888dc08c99170e4401e0ee2811a03d34372c83bcb8df579ad291c202664e46f181c1e772061e8388f8335410c3c2a60794890a22b489ddf13a5e9e121d9b5d2812304e9048e23a1416387dd21c1f32ec77efb57603c86d92131e8b5787af2d277d6ad0e49a1569b9a2a75e61f8b0334688c801c0f1b01394887c4b86fab964935872411972c956b85cf7a914329a69895ad9de53adbd0eccdd07827bb3f290e09325ae6705163eaf179640c0eb4c121d1ff6c2d9938fd99a42309e443a488e8c8e15116b037248ad0585253c8fcf7a70f1cc6060ade7398a0df73e048343724a7f7facff78ffc3f7d1cc2318648b621a937698bd524636c285cba94f5b214b4c3ec353deb7aa6a6b9fa8db686842bf33b2fedc3286b6a48fa8fd91965948eb56ae5170f781d8088ec78000a48f0000fa4e0018eb033b018e66931d4c5c5d65d63ee34635852a6eb3424c85d5242a5a78a973e434352a6981a44692e25e3636748d44c26baf2b998faef83cdc386c191036444478e4333246e34ed2c2693caf9c461654874d3dbf1d4d54686a4d935915a2a271be18a181b6536b03124681a25934e49c55195f2c1a623870e343124fc6dd8ffe76facb33ed812bd18250c495faf753a943a61eab881d0434ec042303024a9136a5e3b7c0e7d0bec0bc97a75f63eea4d750cc5f010f142d2d6c9697dbd9c34e6695d50bff47abebea92c877121c92bb9a8eccfbeea9b82d8169243a9c9184f29dd9117869816927446b532b50b164ca3366259c8f7e23de72b739880068d7c046243c4ccb090584aa7ca72e35f2149a6f23d6979d7439f5648dc141de7ed3d754c31ab42829631bfcdeca172fc6c54483e8d4965fabd447ec70d3e053685e48df5a91b73560a495b156fb4cf3485cea4122c0ac9734a5f868ad1c276b29d60662445b7be1d593a24181412b573c905651e26d813122baf43484f5b3db9d2a0c143302724af5ad038f1152394da84c452e26387269962f0ef0c634282a75d877ad5a613a725248ba59b875cb0d4ef2821e1f7d6366afc1854105a1292e62b34ae9db07a192121316f285babd2b163c68e90244706b1dade8d90d8f983be7cca5a199b7575d685bc055f1da541fb360621b72224783459a6634a7eb0e520c7f10803191ba7bc8d91b343644d10038f08181989d9d3da35664c84a44b49c5ab279ddc21246caa3955d70921b92df9880dcfd22d088929425fc56905910121f182d8e0715e32a5fe900949693a6c3c08466e788046efd05d245f549351b3ab7b6a25e453dac181c540e9224984103a9c9e56b820ff60eb349282ca45628fde7cadf76a32a38643c4d0a0709128724bde3b6fb74832d72ead1a6725ab52b648101ece62ccb35d5be95a24a5b5a03926ac74774a46d122c1d2338e50d1a9592428315ef263c891e12b5924d685aacda3725490672c12935cda2f59bf41981a16092a6613aac6bf10d42b1233cf6c4dec8fb9855950ae48d2902998d293a95624862b4d2f4fb9a9cc5a41b1a2b1f1d0da8e91cdb414fe7259ed7e18d16dad2261ec3f8d6813f9e2ab226184da534ad5681cf15391e85aba1564dda92046053aa9cf8e0ae24aa7e0ce4ce6ee55de62eb9fd025f364f61b46992231e82f5529126d3387cc986fc49d5ba448ae985cb62ca520e37dd528923d4dfceef3b7258a64cfc12bdfda5f8790ffa04291f0d5256490d3d1db3bb77182310a1489315e6b105e631bd6f38964bdcaec121e3fa994792231c63ef78be1c3a712eac45d5f2d165a75b51e1bd47590165ae3c45e5a9baa6a152e55b00e19b7ac346e6aa84d24679a88baf158fdd5349134f699f734ecca44d2e8d091b17d726d1d2612fe3dc930272f9e56579748cc17bdeef9254b2498576788e9894cadc1418e2f68d0c0418e9090aa44c228655d32da6becee3e284a2497e820b4e88e26911cd4d3452bafa494c94822c9c3376c29cb99bece4864e556da6e75d166e33bf3546ced784122a9e5729af7d45ea11e9194152dfba99359c636a58c7244c2a86cb132bab444de675423924674a6cd22da352f568c483419add447cb4f4d9e5a44f2ac5ada7f5529478e1014a02212fdde4cc8bc5de27c4d4472c570dfb36e9d3cc9bc0d1d858804955d515d435b8ef10f916c177f955e754324ff09cd93ad9d6d4f5e88c40a3ae9f9cf232d5f4788abc45c2cccaa861a537dc9e54a7d3588e4bc399e224eb67c0cfaba1c094708dc06c8c717a50491a46f9b9fa46c52dae281c06664dce4b2c86646eb39a1f76392318048d05cfbe9474c7fe0c6de729d67a5987684d84fca2e3f14d3aeb5b5324cecea53a3db87cf22ca53cead3e2426ad7c4a9dfcdc9c151f926b9498986c6c0f899531a8b5a810a5db7fb085fc088ed74372e81feb9ca307fb1df390a4ae675aae25af74ca0b0f49e762a193f06a11967487a4cf4166bb1a8db1f5db2131e5248307551d73ccb93a2408d9612f1b3ec2ce628a0e09ef6dff97a4c7a918d5a3e69098efd2c38652e1d7a27248cca4aa6ed64a0629f70c2a0e89b3b189595dba2b5d76cc24c63454756d75ed76a3562263f2644a8b32b7068886a4f564ea9b9aab640ccf90602f36a2191235a96e6bcde1937b07cb9094f298afbbcfc99475321c7e2ebac856c6905c49b8dffb5ba5a7114d22ca5230c03024081d74eed39f73c6fc8021b94bebba63f7733c15fc42b2ce5b8ed3eb8b29d4e885d53e5c6eabebb3d64e4ec53f99da98fac32e246d45d3a27739c8852475233f9375e6b94ac12d24eea985d57027b62de714b590f45e95f3ca878d1ba32120c932805948eacf953bfa7c72d800c30307c8c708080eb0a0cac959cbbd8c66e6d2d9323ba8598b3f5f21f9e78377c74c8819f100c10da0151244b6c75ca7f1cb6611ac42c2b9e9f86fd3225221397c0ad66661f7a14b5348fe504d35af16292465ffe84f19738e090f4621b1652c73dc4e3aea6cd737043423f9b2c36f7c7eb3b82a1e4221e1baa4dba9e5cbd1729e909ca172baf0184507b9a2131274a85395a9c6262485eafcf857252624ec9ea8bc4ffb12123f7b3ced1a4a66e92025248b9bb0b2bda0a6f69384e4faf48b8d51838424bbb0b3683a7690397b011e21d9920e4a69ff731376d1bb73a45d46e255dc0f6d322fa8c84570577fd35d3c2623596da3a9d279a3c96d899098ad6383c7d21092f4a3c6d8fe4248984debcbb56710127ef4ff8770d5d4ff7d008190ec9e545c396b1709a6f565af16f3283be922f983aa93ee41a3acf6b9480e964153aa67cd593c641c2e923a76d0a9ad4a255f0b8ab1778b24e14185139d53501654670bbc42c3ea9258aa2e8f6bdb371d7e56d722498378909a555dccb2b448eed3eb758bcfb1467fb348b63f99e36515952c7e74e4649118b25eb3a6d31b8be4fb52de992fd3b048aee095ba4c7ce52899ffbe22f9d386ce75864a5e9f2b92dbd7747888052163b5e258d1786e15b9a594425732a5d9bc1f9c2aee5291e821c47ad6517321e46b5424f6d9cdc6ced775a9ea3bc5d140678adedd2b54eedbd28add6be9dca43c2279a548fcd9edb52432cb9776a4484efbac4987c74de44691a459d75a7dd511901b202468c18922e993c5f7702a85c7b8502406b1b8f1736e911d7b1d078ae44ef2a637d56f8659f7898457b9cba5ffe289c4922d197316f3b019af1389a38275cc7b9b62799cf0b498690eeefeeae03691aa3c1d733b67ee033c908207a0e134815faa18f13d09fe863141ef28bb4c60222f912cbacb839a8fa774e996a882c67aa757c8675df25422e93ba58a4bd3d93051c8512229ddea2ea5ad6a6fcb24126fbe2a378db05c2ade278944932adad5722529ead98b4492322163a9bbb1b49d1f2492e3e5a7c58bccd47b22c23d22e9e2cb730765f69f29758e688418c708a4b108451c2de6cd26026fb10e39b1b7f6b26c6e275b4363a86b329d394424cea96c26315a9b4a2767708748921d211afdee3f6e6988e4b306212de57a85481c79b71664a999dd4888848f1ebbb3b483785283718348eaa8a661feb4df20229d9c2092a39ed0b911421fa2e350041788c431795f651ea6f4080122f97f3bce5ede7f484c8dd6211bd5ac5ef643a2b87ed0d9d5e572a80f89716341c5c6cd946ebd717c309f5cfd375beff6b0e3f4902064e9ffacab109a5e1efc1ba963e2f090d8fd163c2c373cc914e21d189d84ef25df0e265549261d6465ba701dbe1835551d4f09f9513a2467c784454f675dc139944333cb564cb52dcad786f59492b8b00a2787c498e682a90b998b436207cdfba27398abbc1e1c123f66d690f9cd6cc2bd21b13c465ebffd67fe0d9a716e48162d167337065dba49916b4361743ded28951e1b92fd2eb976524a6bd83f5cc831d9931a1234fc68f17ead4a95744672284da7b3589a912da52149de2c6d0adf9be24a6848bcf2787a29e65a1e9d21418de5ea2a5bf5dc793324771252654e8e1215f36548127f9d329f869d7a9f0c49ae9e1f43925e693ad13a55a72486e4a4b63f89fa20fae26148106ad3a7f01b967a0443e28e29ff6cba2f245b756e39d1dc0b89a7be6443e35d4850751117923b2f7fbcb36c2169d4d27297cc9fb3ac8524613279dd958dc5370bc9a7f5ac928e8b3229c2427206bdcdaa397485c4fcae954689f9c9d2b142c2fbbfc6a7bd0ac9492e5490a62f5e10a242e2efe6d9d07123fb3953481cbd7d6a63d82dcf395248ee6b110df515c5435148d0bd4bd7d920733a6624a80d2a27995a53160f149242e75dedcfa51cd53c21c9ba928cba0d66b51927248afe8ef6addc1c2e4d48381d2f850989d1ab52ca399350da2d4b489a191d47645b9490a46c674b28df4d3a589290e82ae234dfc585fe0a1292c2789eebfc34b75d3942c256902132251d44fd4648ae4b7ea772c3c78ebb8ce40df1f094463488b58b9014eb4e4c6a928ce4bf4bfe575dfa4b44486cef1c56b27965be212455acb6e56752325b0b2149cf73b824ed35b9414870d1f9221a2b4c45078404bbb495acb76285cc2e92f4c6376ec5f6cbe92279844e91a744b85b251749a1d1b73e6b5c1c63b677ab0def2d92b369dc6c56aa2dc76b8b449fcbad4efbd62229b3e84bd5a5f152891649b2c4a94ca76c4d27679194ff1533445a8e1f592427cfd941caa7168b04bd95ced4c81416b72759e92b922c94f03f4da9b77b572488c54ef318c34793b722e15352b29e3d3c87ce8ac4990f7fe2d62d07a15524cc7c98568ed92633aa48ea3ea57252d99fde662a92fec744860d4a5424a7d57de77c8630f929925256fef9f8a02992f6d388fc0a9622318d6636ad99713b8da44890296789aeabf814711449c2bea2efa8549937144572bc9882de3b8f39c7301449b5dbf715c3d53d73a048fa14f4dd3daa8e8df789844d1e965d9e3ae7ec3c913476f7669f43257d5d2712642c15742afd5c5a324eb83ba3edc9de44a2adccc918a33f8dab89c47c7aa69ef2c5fd6426125b73ad785fb0cb9461227984a73aa54248192f913cf6415ab2ad72cb2d91a454fc0312c0a2001605f0ea1a90ee93492833020d18c3c6c807182038285034cad23008a011911d210400c018870209f0624464470a06008007c3ec000387b171800088843cdae13942742080055e00c00b0710c20b2fbc00800614d00111101d26010020c30b1191436300013023c66910000066c4788e101a06f042000c4040c87b8481cc8888878702bc00c0020c802023211f22363c3c1090b3d0714316e871808c8501121663e840af4090111b1f22c6c30301e90a0419f11c375a91ac97ffb2e76728edf083fb6cc7d98d0ff11003c43d1c04bd0e9162233840588120236280f80e0f0f04e42a465ee4c6df2840aa22297fc384870fe525d65424a86c277490db8ba02231838d884de68dbfc19ba748509676bec76312dee94037fec6def81b28820364c406c88ee311f2364074dcc881344d911c5ad34feddd6ad4bf4a912c72736f365d262992832c8db172181942bff7c851245b16adbdcc7e3138406e20a72812bd54af84997e0db37cb09d1d22a6810cc595292ae377efc5cbc386b9182428922b69d70cb539f4c8f6c1a6d681fc44f257d6c5ac90f960e30aa42792beb4a8d84b0f2b2ab6225f642792a4a7e41616caecfa45427202a5ce2d9b6813a989cbc461e2ec126689be82c85dc5705b39d9fa5bff9ff7ecb10fc3aca012491aafe4754e192512fc2e2ea978f31ebc3a424e224125153796285dbb17492241e8ee58a3e49685cc91485a758d39cc8fda746b422241af52a807bde42392462c7ffca78b264d85413a82f554b550bb70f7165de5a277859d873defb31189b1fe35c660c26444b258aedb08a1a529e54b107211c92c9b316daf08eb2cace22bd6cef3a8b83211097aae7e73929a21358388a498b459e80e974324ab751edf9cefe3de6788c498ad141fb35588048d9f4bb7b4a920b24488c4dc382657193fe6bb3f5a908348522f266f2998c915d5992012c4853eede49e6ad38c69c84024291de17ab9358c3e6d0222393c6cc5b449445ece3523ff90d43bf72294cc793c99f44392daa4af336692f529da87e43a59badecaf496a6241f700fa887e475cbce516e21a395f250acbbef3acd0a2fd74ac14372ca551df7b2cec1e3503042be0478213f022283bc43991dac0e7ba8a8a568655bb73197a5c2a71c4774b6b0705cd17103e107920e496339770c624a5453ca907348b04df2b4c28496136a39f0b1d43357256444870a320e9a70c0c262b9574a96434d54e482bc52b146e5827df986041d725b8352b547bac168b4a1201b6e0da786448dbd9d96738ef7ef9f9169484e31edefb4e8a93c8e86a48cfe9d4a83ac6f4ae61992355d06bd25376e9d4c33180dbc916528434986637c5752163b6e111d393ac76034c4603470061986e4201f74ae895cb45bf1110986deddc25a57ce0c19a7b14beafe2e467e216947bf3328db30bf5e7a2141c82933654acf2e247cce1843bfa7242dbbbd4472e198f5b1e416125b33659e65ba0a99a516125c83e6145a2a877a511692e6936ce99f909997935848aece9369d943c7d4f415124f8758102145e766437e04e48a905648da60ebe1fef22a24260f6a8ea44262e79bb68c9a163a88a790a4f36fd40e1fa61412532cb318de354b955014927fee947edda98b6b37a5194917e6ce3ffe9f5db8402149561af5fb61e51392722cb1a051ef626a921392cecd2da58f9c4d48d4a4645305d160a6f35d3221f194102ae7b7bccb252458b6c5aefff89a904a68f45a521d94b69290b8792bf3b2e249399dbb4442e2cfed768b6cd1417957461e21713683583efb7852d7bb3442b289cf6ea2d4ca629eb20ca3f1822c42929c6b2759dfb8fa24cc4292911cf62acc768ab59d532e899060174a89505b61fc4b974348b0764b1b572be9bb8f97424818b96fff98d64e742c8360342e819024b2f942d3c6888068ed22e1377fce9bcbae57ec74916816f34ae89874b948ca95b46254ecf17091f8b9f4f98a92f16e9188aad6c89a6ab7d98b6a0af27e2ee5830d6d91a4fb7137e6b1bb5a24c8a03af4cba593e2222d125554057db1f3056d8c9011b30ef91190649c45e2b8b55f57d8ee1c51164922bb25b7ddfb316c8c05ee952a8959b7b6969c70cb5c52b4086171f88a646d13bfe1b2ce3ee85d91a4937dd8d10bb62239c58c231f67b4ad9e901549db97ddde63b61159c2015791e8b32a325ffa9ce1525491942be8edaae9914189539114de446392335f3abc52405424e93cd3f8d151b31cbcc353247696eeb58b0c4d818bb01449e2bbc3662e96f29c435224e5da86174d1bd47785a348544d3696f132c3a75e1449a964b8914bd9cc7628123de9af9f4ba2b6620741917c9d3955cd9998860b3f5114f9fa74d113499db2eacc98a61349e2ef3bdca6c9bea890134939bdf3fd52b6f9accec04d247c90df0ec2eecd72ae89043119d55625672251467f34adb9622249b58c58cf9d72c58ae12592572e8a9231bf434b2458a8bcbb6ce94a60fa1f3359ee9012c9f957ef3b763b7916dd7ad8e1c04924970ead7439e9ee59eb3cecc438944482b6d1714c9ab6cc631e4622a93b958a9ac6cd2e730889e430eabae542c59cb5c1c347247ec79349c66a1b1d9198c7bc4643534ef741d888a4d05439e9b8d6222392774f9c36b7b332155f4462c778a793f80a5b296d838a4894f9df6b191543c6ac0c4c446254d310f3332122123777a630da544fd3623c44f2c50dbaf72e6bd8110d1a888648cefdb2f239d907512516224973bad267d5ea129010651009ae692b7ce747f5130b82cd30e51efbe440741f0444e22915622a3e966687be38c43f74fdd9d74174ee02fa21e1e292da7610f17c6b00fb906c1f6354efd0413e246ebc53b1826bacd21e0f1d1672021484817b4812ca74f8c8a49e47bf912324f589180b500fa8ea74bbd152bc59079887a43c97a97aae43a7f81103e221e137e70d15327d873288c676b6abec90283a9f7a260b551d122efd96bd58e55d1ce990642ae8a435c3e951da3287e4d5d0edd4a21fea3713500e89a396468c4362b4aeefea9c4396d8af80705876f3a6b631d3e31b9257dc437c9296bf53de0d89233a53dc65a80d494a8f1ccd95fdb2aa886c48ca2f159fcc646b2fbd06b442c9933aab2131a97bd3c1e4f6ba85cf088976a8c4ad2643f26030128944e280288e0273cb1413130000000c209146839160349c299a2c0f140003652c183c3c2c2024161416168fc5c380201c0884826140201c080402c1401044516b1c6a7ccdb854e8878d85ff8dfa7777780097f8b9a9ad0816a40dec0076a9fbf669ffd74f05013a005d385edf7f1b0913d0cfe88e8de8912e171121bfadfdf0b4d49a8ab7977b5ab52ec81f201f7241e88e2e569a9293f6dfe93d8d37caa56d1478068c553f92dadb82eb7c35b10b6337f61657f29502306283326d9a20261b9cd617b63b308d44f296afcd14635d596f1a9a5e1464bd6ca79254d66c22967b2f8d68ccca3eaa193960a1836b387c6854e82e21cec2b092f8f119923156a74f30e044bee7be117215499ce7ac48c044906c616da9bd49ad057325222174d3e8af6f8f24955ca740357c2222d217708729b6799c000f3bc850e5b29fc43087b234ea99624c9aace84761737ea94c58b268d3251f42fb646693f96755ea1958b3144632ce162993f068f0658a2627a4da4660379f4317e69d0bfa1baae4f8d7f2c10c30274a084de11b8ea5dc010c111bb4ed8177b9cb6c182644a305659862cf29d0507ccee1bb31e2deeab775e2dc79a95a5fd6571d517e2167d32c8478ee6ad7fae82014ff1962adafbbbac94caad15dc2989f28f84fbf0043e575e6833842f06aa5761a761b8739b02633b744acc67d2d96ba9b71891c4dda12b7bb429b13307af3f4d8c2be6980ba7fc1e0a7fa9ee818c8f3b851d7e7b994f2a00e0637b396ac550ac62f6baaaa8cc2404a335a96cc4fab0fe73566b669a2b2db23e8cc4e5724042d4969afcc77c86cedc29d8429e736f1a4deab704a8517379c60c3eafca007c0fe1183a600d7596575dcbbfe9a0f376696480aec0e8292313ed0952fb83c5eb514a4aaa6e3edc19bd41e3276ede6cb85384620300ac832db1c55ebfc87a047be2a94b3d95caccfb977463c4c959387e1339482173d6f140b1b074355f956ea161a5e915459cc925ec7be7504a099d9e9d164a40c525cd14ee692f99c8187fa8041eef4adb45233e5e72e1947e8a6a8aa48f8ca1accb5a6d548ff86bbf25677030153d9f216e0738c46b36e5737a52822c023083a28fa6af881617e40e96684376b93b96be4fca806360f6c889b0dfdc9c20a18aad9efda2f5d8521b94887053c11062d901ec5e3f05e0c90f75c308d5560ed7653d2234e0afb184e88296059d08031a9bbf4247364a8ab4a47525aa8ae2d0fb698083fb1f50ede74c7936c3d94fb2e2b99c329b19cf506eb208829d8b3355841006375a8407f0d2c48866804d718bd0210100c17724d9c117569d72d1bb146faa5c5f06b09de70f6e3e2bf8c032397dddb6809ce37117bd6382203a1e182a759e39e84fc22a058824d86b5303217ea44aaae60f7551fc04f58c9d89c11081c3b46aa092d54a8e133e2690a6497e6139f974082ca479396288cd9c52bab7587da734970f3d052c5ec3b26f34042e69ba7e5840494684438efd4a197a7e54e990f7f475a4ba464f6036728e00326338401632888a3547b16d2fb90b77895bbb6d9a5c417de47e0101d421c3901b5410b39504f8ea5ed9fb1fdc6cf6bcdc0a32be5f957ed84fd371e5829853b4b8b2f21d30657e342749cd14b044b21b0795d1ca6c9109016045ca13d7e408135edfd57543a8652ae2e85e15671a8ad8104a5f394aa442173ef29299eded50342be15eecc75b1e054d943fb50ce0566557cbab96821ffa438d4da5963fcfce65490c0d6b924303bc93532b1bab7e2052ac71de389424ec1e58467dd94c7702a0dc454901ebd3f9a3e75df45886ab41d1421ac395464d6f29122c4aaeae780d119dbc6d6f2c9031938010df768432567afc2a94570df45401f2e371668a8007525c008460f81c31483c1087d6027cbaef56acf5d158aeae228f69c27d4d46d62a090e225e8470eb3efdce82015a05fa9feada7e99bc9fcf5e7a87de0e660bbf38c53a415d6c0f5680d403869a227fc7349dfbb1d8ec23849fa5c78a01ee5b453ba01ba0200000c14e53bb00c50d4dcd13b18375624e1c43b603b383abf9b3cae3f8d2ed77b973b23c95013055f13dd2d9bd6822cb54139615eae8e1fbdfd35b6428d0b0a3444693f8f58ebebc6dbfe559e8737238452e85863459a348f3d865d87e1f5eb8539c1c7b201d84d80d4da616ecc55a6d990bd7804ba691864e6667fa7d0acbd30d68a2bac8b20a1a2486d2c35d4bbd4497914e11888a6534e3207f796f5cc8b47200f73550d609a13f6f2a88a0d90ca263de88fbb6c8136f4bfd73f620d5579998225d2b0ae50232ad85f292195dbe2a94fbcb78f669818e8b5aa1c502439f4a4acfc52bbed68c3c3f105960fd074b87fc9a884475e37fa23aa901af5fa315ad2f2c4c2f8a81712a21917810e996b86162edd77b2d84635d7035446d0c7cf3a563437c9bfab41c246317e4c6b0600c354aee48956f5bd7f010c9f4db4a13bc0c151b46ec11d16a76ec24578b3f0a8b75b114c87c675923718ace7c621db01baa5aa385a8c0358e56937cce97baff1ebd215568400d0cf508f41971725a1e63914460d89812fdc976b45d3a1f2776bd263f46515c4c54a23ac71e4b544cd86354f274dd8c3ced6960c6ea092a39287183ccf66a9faff4c09c4843f8a4ea323a1a47b0e38a38fc8fa1f9a426ce8e1cb08d8609d4aaf25c28ccf8649a73e4869ab08b31e9378908d1434779916278699790d18cb43d021eda4da59a6c5ce8c49c192304a92d940a22f7930c0e3252623339e51a212de2cda6259d7b38ade15c416e5ef2d29d0f233b3c22551428302c07cb26c193b7e8dc6ede4a3e64f8835e258c676df8bd23bed2632d9674e0b349b4d1d427bf6c80ea4d4e85efcc9ff07753b5af2eda6011e6e34295be272f99f3d4cbbd60bccc20bd21f9ef95415cb4fc87bc342dbb87ea1fd126aa4f357586dd9cfe700b1093e051f1e28ac758c3dc1368818cec2d15f31c453955016a32c1e75a4c358f9c4909607ee4d53779656ee0ccef992dfdf8afcfdf59c0b903611c03e7d79c91e93178f352f133e60694785767fd9a9b36c7fc8c1fb3c5bf25a016ed75695c0e480d3ddc787a59cdbc6b3cfb29a8d768fa992492ae46843237da6b2da41f990923ea3bddb784ac4288dc0293bd66b1adf70f888ae03884ea71e74663cea4eac30637b455223e2f4592dfb21c81429bf94a64bdee6e1cfa769a5fd8335158c1468fec501a12de7c67be8d7543069457b255bd282a778b1b49f525eb8e1e94e70106833bba789e7883636dbe887cc63042d740f2e0de1a39ea95895980a2b540b06ae1fb7d8198fc44904313447d581a2207b30fdc80fd5f183534318c61d65b96f8af9cdb2bc46f3b89b5070784977d83d706aa9ded3e5dd87d1940999535852b1cf3306be204e988f80b21c777c0009363a30ab3108d130c6bce72574a492f4360c0f1c145654a7962046020bf983cc32a4210352f6d256e3a1d2b43b3fad94f5920fd52613aa12bb8d43c9d42a826ee2ec16a0c1b9f9da201e026e835052c2af9f4247833aa801bb0f8ca62a0c4d8a76863a91b1a3624eb188c52847d59e7db212656054ac4571c4ddcc049935210457899f2f8ce097ab5855af22678f306b83e10019d7aca9eddbd2bd3d6f91130f289f99bd03bf6ac190d6b8fe40293ebc67c7292b63b477a688447fab9823431c4a9c8633de0a297d73d2bba7fc08ceda6c51dba930b17e193c030e3d96c8bde7fe85e4a80b2e293af1a8e5ac38082430a04bd219677a69b11663ca48ac83440cf0e2605cdc44f814c129b46dc309a71b42d9ce68e46f8d244ac248b92938d566976812eff054f851dc13d8169350909a92be8994343f0df293f40d035853d1face91efb6fb232c184db7605fc1845cd10a807878460246b5ab5e7871c91889bce05e4d3b739ad342ce77fa1a60470888678f87201f07e0bed2d969c71f38451dd680887b7a74aebcca99a920cbfe9ccfdebabefe36280155596df7cb205a1e06ea59929e2fa2220232d3c8dfc9d70771172a6155a033f370617030b08bfd394802ed7d9f1061294cb2d9c99df7bf80fe6a8a86ce94c0905c15f0cd218e6949e9bd1bc51295af05a38828f1ccf1b2841c66edd896d3e845d0501641a9661029f30476e8d364e3aff26e35a4eb09762b094703563979254e48470b0d99bd116d32297fc7d150bc7267f374fd850f80abca562f1946e53b1a909187e998c123cc32659aba79a595c9828502b8938643e18120e4fdac883d6c475f672182d15dbd8ed878ee896d74cb060c5e454571bfd66f0bc3090e8bc6157f7572745f95ffaaf9bf969b7c1cdb5395a93201687b97c055a71fc0b213fdb0472642a97229defef859124e81d510d072deb87d96f3feeecd10f1a0f74f95667e3544f3df3c4c74df2debe4f2174b75e83af62346ea0423452134034280e4221baeaf27f8f43633662364a68952d160e0db3766132a882ff0b919a3ff79c949ada5836536d01bd9b0bd9b142025306e9d4dc8d0b29ae46408d31db6eac06d381e8e9e07bded4714edc1fa9eb331694d88818106f790d953505659ea2234baabcb75f581bfcea1a4ab718bf9551a82a24a1c1df08cbe9db9512f39022f27c800ce7fe7aaed9189ea19e51061bada6ef05308fc7d0a3da7b8451787ae76eaa52cfb3963c1bdaba6f02cb53ab9c82a04b8f15c6a5aa1927cfc214bd3c367ab39000f1d3dde43ae79538a12902d848da45363f92e64aedcd1b2d84f4c828d99349e53d4a92957e6083d64178a39d809215b8dbefcdb030c554da87175b44fc2252afca894ffe7aa3ad282df146d333b2039695bd17260d267ece3ed54a6d42d1620212b4f16cabccdf815594a57972410edf6e686cacda6a21273f2a67568d49ba33cdab90cb4ba7f3d915b8407bdaf13750fbca1957e25462662b508611603f64c30b23008e4fa72108b9aa7911de513c07466f4c578cc39475deddd2f8586bd48053841ee411b046adcde50b704356a4764ad23284513a90b1554b9ec14912345e963cbcfbea2c1d96f4bbd7bca1e78306568036dc63aa586dd792797a458153817d1372560221076fa6e451fb98fd933f76f77799cd5663245128dd73eb5925c57b2b7ac33e7bd7bb7aa28988ae7ae3d7eb38fce2e12be88d1de988ce2fcf5917f16fd8705d7290e71910b944a85d80b4433aab5c4f5bef9b7b6b9c54024db663ca5633f4da23f85dd4fe9a277910413741108afe9239621d9df62f05964a5804a80fc7d1390a46715540ad1c72d0ab103ec87e8e2e4487346cf3847cd54ac228c0ba66d5ebd688af5710788654a26a323a30b4a0ce9238191263a8d90c9239d20ca89bed000ac9778bc3b7a2699ae9aa09acea722d3eb0d0a34a59bf3e8d3f23775425aba7a3cdcae2b9da67ee3449c7b302c106685ec39f12ca055f8fdcb457c464374e1dc58812cd7826ad281b02be40b47d9c244b6a73259103b1a9c5af296da29025f29b301d1845e7c6dffcbdcd2708fbf22d95fa31e250aa2d6004c20ca0eeff473ce5c5d545c08eab4ce25a7fc300d96e0e518fa8dfee7168f71a803a714ef1eec9f556600f75fd9e2dcaa15e42bec11dd78877e0f1f0b371d9c3908dfa010a116ea50efee21d16212465864cab371208aef322945ad403bf47fb26f88b6da0de308a30f70759c70823841371973f69429c62dc4f343490ea1703de7ddb865e349b1cf8595466639bf9008c5c7b990b503767c659e47a5523d56167064ae0c2f380653380dc3c386a0583b3b07918c597c0bb5af9121908da667b8f9db58e5fb85598ff118a44e3ec5b772be98df31e00017cf4729488b9bc5c925c23e202596b2d46a035dd4bfeeb852443981be5231fe84b7af35d49aca3d854d6c443cc5c992e4d0b32496e6853f56c061509d3ccdfba1e508d9bfc01a3e85cf1e51af8f84fcfa3f4f9dea6e1cb1d8f6fb368f580d3d68ed0e2317734556d3d178f15eeaa4ab8b725028d6bfa268497b7ab35635dbec936c7a2fdb2516ecf86a51a20cb45e19a3d5971f779d8a1a51d84a5eea0a82ffe6033533408a78d2b4bba9a19a172ed0322910430966145fb41fc6d066fdf90f185472c46d4ea1073fa1fa0e3acc67284b05b968e6743c1fb853e3819a7aaa509744e94f234184bf7ce935c7c0f209b173a02d3d9ab1207f56e534432e52c83b61046ea156e37342d8b476ce92baa681e9872703618d1faa2d00e15b385e1236c8c1e8c70255e61f20049da460d3099b745f6c38bff49107af8d27db07ba61d23e205e79c44472ce535ccbfa1a7f67600b0c381fba1ccd8ac7103326cfab35f53c5cfff2fd65e1880047a6170875153d6a3cca2e026676a098aa18ed034628f00bf4d34e858171f2b88bace20407e1a1f50eab2d79913e25f3ec35890f2c17f1588557889af603d98a4e15b322dc9ca9bd581ce70fae9211732f9215548bb9f3ea3ef32c7276fe27361331829d5dbe6413accd6851babe707a1bc35af1abf6cb077a7333fea54b3be85dd96ee528bdbff5dc9b6265279f86bce2d29f77c8d485ab2dc07e86842345061ae5079e8fd898752efb1c36aa52ab1c5bbc5c099f44e7885682370fcf67bd67e6ce82db1f38c7de232d949ea52b6fc63ff68c43dba28a2da26e664f38bd03ced0b99e58f3be3ca2bb31c2c4dbb3a44952735a237158d2527e79993cb00e8ee0a65e757700675f072127014b97ba503a157fd0b044967743e3d22fc080d89f27430da48a509fce067d8c05a5d3e63c8566a7572a70d1461caa126b978c485dd42bfe7e2794154cf9f330fc5e739763066b0f02fe0a044bd8d9831583b3d0c652589a1f3bcdaf8da2842f2dac19e9aa2943bc77984b6647926d8518f2d853d8c3ca97b34db24b10cc27cd2111fc0edea7bd98a3731e48208e8c8b03753194d15cb1e4f19a9215eab642916d442a5f0fef993d44eb62ca0e5bdcb9f1f4c4b4327d3c12e5a9ed1d2550b9c6c04f9872a1e7e8c484c9ac6f454bcb8700c2e9885404cb8d2b0440b43a94c54ffd48313dc76cf66f87f13d23f68e445f8019e6df6f33223ee41eb4d80c317dad5f6584200e62d728403c81754362746ee4cd89d81a7c3685513724068c857d1539543c25f30e6928310a7c5ed9528f6fc320a1037b4d0c912884d6f4d0a2f7f8b806755bedcd5603583ece3d1f39fb174e163d0608b5d8c4cb3498168738ce95afe312dca7af9badf39e1c81e382a1b78a16fe3592f2b3bf9aa13a0e0be7e2f808b6f933ead246c1abc49ec4d863b529f031ae16b889a124fa882c26cb4551c44ab40a6d3886fc0fc770d531f1970bd0146c1e6044cb567bf922a822a8c3798e6fc03f42622d5b0b749b597b9a1d8a8ed51c338f84abbe84e697b2aa0a89c871ea934a85fca03f6a07f97f80580e797570ac55674756084b0f768758fa98351298c5d88322e0b01f5f78bbf4e9c75fd2d7798f091f1c9960e6ce11892ed05a1a9a7cda052c80705eed2da348504c6092677d4b2f334b063db3623dc0b151d25977250ef027bf410531c0073ecc1d247cd06764229c0f03be1643b90e484fcd6c5f9adcd5673d9fd52b541f7420bc351c0174687b71f3da99c2db0365b7336a33d8f12441283e07c5cc393ed8da916ad77a94771f9975127c2b03919cba5348c8ec2eaccf2557f0133d56236bd76c5cb2b150e213deace351b1848de2c6b1043fee0d6435ab25a37a5655cc6109e46d2d64e4433882de4078bf17b73fb89d37137c6a392fcc2bcef04c4fa694f89994fba57a5146721c381c4c23f9700ae0522f49f4449451439093ef12550d4aa21c288c88cd08110261672e9870c10b598abd80298158d07d50419e23cafa02af03eb204baa5d681f6fd24f03e384f89c49723b960164703f74baeda59550491ef7c44e0d2a4ed139127eb84b03f19f942ffd90fdeee0c346f48c423d64ffd60b8bb66662e81dc6ad4f933ed402dc3cb2d5613b7fa332aae4f7ec88173b038f1d61e52a614df61850d23750769184807fa0b8bc9e39c5a12120a06fe33d28ddb8646b28d6913039108e9e0a0175a6eced11d1e13c8448d6be19ce7ad6428f979293b05b172c81632381203bed414ec1ce27095a037f411c583ea0f3832d88003da86a6e0122821dd7c6754c45732d7e229cfa1dc779bea7f47d82c516f5c9f3efdbe45066ab25617f64b5e59911d790e50a4402e21ce4013a4f0109346a93b106e00c34b4721bc5433519f2ce484122be5ef161cb59fd3562d9fb6c177c751a5946772ed51c4dea9aeba3908b7eef2bee1b4a6705ce80ffa4052cc652dbf47706b881d6f96772c57322c03f908376287f56c783cf3c2b8097db4f0a064b65041c288b6045b2260fc748a59b9860a999d3966021bc469161c29d38b29055f778280666b93c7931efb257f6bd1c291a28789356dc4121d3bcf37040ebfae154f2c399c14080a1978e1a6be841058684ffb630d07826d2357bb6cc029921070b46942385a0aa243831798ac0e09dd9d2edffa3c1d1572a5e09a5f52ef12acdaec8128461ec836820a70cd3e55eab21c9c0bbcc64638381c6283426b589a2b2809f7b9de10b1d74fe73cf42dfc46446b0c3175d686eeb387a24c9ea30330a74b96026e2477a436a7f522e5acab45d42230fb51cab8dc7c7c8e9670e533aa0e3af29cdb29483d3fb102c79245aeea29729723757d604cb4bce8fdde1f61bfa7329894db2baae42bbabc58cf1557d4d5fab32aa03ce930745e6409ea3e81d90141e2a6a47a514f27f62e2498a4020069140e380ebd9163b0a2c288e0c1c55655b2635b2ca7aaaa9381d16effb6da9d2e398a4b4287037786dbb7e91c8f59830cebe62fcee944032e3b093b0aa93382763c17b55e88ac1995e63ef56f0a28009c100118b1953b84fda551359b4329f34dc8b999e1544006a48413d902825bbf0b3fd70b9e2d0a9cbbdad762d941bb830f24dbf73096f6184db2a786f54c8e15e2e344347db8004c974491ce1a81b32bdbe9bbd3cd2a6471c8a7161ccd6d794ab04ffa082568bd259a1b7bcd96e20827092b4eb607da3f34288dfdd6d878f6dd3c2088cebb538e9b475b880f776ecfcef53e1b05d3f0616b203a7e16a02e48322c746960430482f9ed97c41f5ef3385c8cc78caf0f0c53db31941826d4004e263d471449fa1ac2fdad8422a964294121fc357fd6410f9f7ac3ade81ab5484379c44d68930d6729194c65688984a087490d3b4449a5ced925f479d458bdce660c212812f518d639706db13b7f9a1558e944dff261376b2a181320451f6b80cbbae3a4640361e24724a9b9c4a6a534c455859db3d5f2f19e875313aa003d556f4d70a1e50547871048756b42dc681110e8d51be7124182a3d2a06f00e72d6a5f52c0452b29b0867d95a02063181af1e5c2965d36ceaeef1d24c8d15da594ffb2179ebe39976a924e9b27a886b64be04676f0600d860f73a4a665595d1f9e8636e4f5b5772de85604f1bf4fad34e1c4ea00d48d35f89a90698a5edd2a4bf352e67ae2621421592e0e31bfc6df1de7c3c21d3e9cd9b07da377c089cf668114ad3ed4f66f296ed85de3fa2e91bfdd6ac8fbafa519d6f98b89f15f7f2f30dd1c059ab6068258acc7d35f29a018e11186d6cfb5a7af3a757909bcc41b88844256b7919f136c7628fe195a941d22e16fb40c78d949dd28a7fcdb75abcea847c7b73e5a6cf84523a11dde54e6df24f45c888a58fd21252dbd1bffb186084e9a6b7014ad0bab5b7d962bc24a0d7426d0d92ded6a8a75402728ed37d8fa61006e7d0089e195ff13f10bc275718cb14930715915e1853cc454ea2af53ea328e30851830a12d2cf8fbad6397cc45b5d97b2a35a5268d22f0f8009d1bb664283124fda276b36811ec240e40c617a3531824a66aefb40f7ff900296c44876d3177a9080534e52586e8790fec0305b94912944cede2643f1379668f17a321c2aea588cbba2dca548aaf7dcbe1222657776c105f345a6bf90d20e3e9dade9a6638eefd95482a341088607b8a003f18371b2a1d77d5305fa027717d1a5553a91d3e293d77ee5a036ecab52b90936933a7087eadae5aadfcaf4ef8c74491c2a9e6efd3231c332b0ba382ff7b10617b9a5af43829da1d8c30174b6a95e19a3250eeb28c9732b882436a35", + "0xcd710b30bd2eab0352ddcc26417aa1944e7b9012096b41c4eb3aaf947f6ea429": "0x0000", + "0xcd710b30bd2eab0352ddcc26417aa1948c27d984a48a10b1ebf28036a4a4444be2440b598d56f335b5f7155d9b03cef974a1a23824f49049675dd63800988661": "0x01000000", + "0xcd710b30bd2eab0352ddcc26417aa1949f4993f016e2d2f8e5f43be7bb259486": "0x00", + "0xcd710b30bd2eab0352ddcc26417aa194e2d1c22ba0a888147714a3487bd51c633cf5030be27db95e3a080000": "0xe2440b598d56f335b5f7155d9b03cef974a1a23824f49049675dd63800988661", + "0xcec5070d609dd3497f72bde07fc96ba04c014e6bf8b8c2c011e7290b85696bb30e5be00fbc2e15b5fe65717dad0447d715f660a0a58411de509b42e6efb8375f562f58a554d5860e": "0xd17c2d7823ebf260fd138f2d7e27d114c0145d968b5ff5006125f2414fadae698eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a488eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a488eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a488eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a488eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a480390084fdbf27d2b79d26a4f13f0ccd982cb755a661969143c37cbc49ef5b91f27", + "0xcec5070d609dd3497f72bde07fc96ba04c014e6bf8b8c2c011e7290b85696bb3e535263148daaf49be5ddb1579b72e84524fc29e78609e3caf42e85aa118ebfe0b0ad404b5bdd25f": "0x88dc3417d5058ec4b4503e0c12ea1a0a89be200fe98922423d4334014fa6b0eed43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27dd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27dd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27dd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27dd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d020a1091341fe5664bfa1782d5e04779689068c916b04cb365ec3153755684d9a1", + "0xcec5070d609dd3497f72bde07fc96ba04e7b9012096b41c4eb3aaf947f6ea429": "0x0000", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa19500b42ace3b5fab73c6265656684020a1091341fe5664bfa1782d5e04779689068c916b04cb365ec3153755684d9a1": "0xbe5ddb1579b72e84524fc29e78609e3caf42e85aa118ebfe0b0ad404b5bdd25f", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa19500e3a507571a62417696d6f6e808eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48": "0xfe65717dad0447d715f660a0a58411de509b42e6efb8375f562f58a554d5860e", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950246b6699fb8b8db670617261808eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48": "0xfe65717dad0447d715f660a0a58411de509b42e6efb8375f562f58a554d5860e", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa19504a8e42157609c6c86173676e80d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d": "0xbe5ddb1579b72e84524fc29e78609e3caf42e85aa118ebfe0b0ad404b5bdd25f", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa19505905fe216cc5924c6772616e80d17c2d7823ebf260fd138f2d7e27d114c0145d968b5ff5006125f2414fadae69": "0xfe65717dad0447d715f660a0a58411de509b42e6efb8375f562f58a554d5860e", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa195066b8d48da86b869b6261626580d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d": "0xbe5ddb1579b72e84524fc29e78609e3caf42e85aa118ebfe0b0ad404b5bdd25f", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa195079b38849014a07307061726180d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d": "0xbe5ddb1579b72e84524fc29e78609e3caf42e85aa118ebfe0b0ad404b5bdd25f", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa19509d4a4cfe1c2ef0b961756469808eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48": "0xfe65717dad0447d715f660a0a58411de509b42e6efb8375f562f58a554d5860e", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950c0cadce9c18510226173676e808eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48": "0xfe65717dad0447d715f660a0a58411de509b42e6efb8375f562f58a554d5860e", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950c7e637254b9ea61962656566840390084fdbf27d2b79d26a4f13f0ccd982cb755a661969143c37cbc49ef5b91f27": "0xfe65717dad0447d715f660a0a58411de509b42e6efb8375f562f58a554d5860e", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950c9b0c13125732d276175646980d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d": "0xbe5ddb1579b72e84524fc29e78609e3caf42e85aa118ebfe0b0ad404b5bdd25f", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950d62c40514b41f31962616265808eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48": "0xfe65717dad0447d715f660a0a58411de509b42e6efb8375f562f58a554d5860e", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950ed43a85541921049696d6f6e80d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d": "0xbe5ddb1579b72e84524fc29e78609e3caf42e85aa118ebfe0b0ad404b5bdd25f", + "0xcec5070d609dd3497f72bde07fc96ba0726380404683fc89e8233450c8aa1950f5537bdb2a1f626b6772616e8088dc3417d5058ec4b4503e0c12ea1a0a89be200fe98922423d4334014fa6b0ee": "0xbe5ddb1579b72e84524fc29e78609e3caf42e85aa118ebfe0b0ad404b5bdd25f", + "0xcec5070d609dd3497f72bde07fc96ba088dcde934c658227ee1dfafcd6e16903": "0x08be5ddb1579b72e84524fc29e78609e3caf42e85aa118ebfe0b0ad404b5bdd25ffe65717dad0447d715f660a0a58411de509b42e6efb8375f562f58a554d5860e", + "0xcec5070d609dd3497f72bde07fc96ba0e0cdd062e6eaf24295ad4ccfc41d4609": "0x08be5ddb1579b72e84524fc29e78609e3caf42e85aa118ebfe0b0ad404b5bdd25f88dc3417d5058ec4b4503e0c12ea1a0a89be200fe98922423d4334014fa6b0eed43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27dd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27dd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27dd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27dd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d020a1091341fe5664bfa1782d5e04779689068c916b04cb365ec3153755684d9a1fe65717dad0447d715f660a0a58411de509b42e6efb8375f562f58a554d5860ed17c2d7823ebf260fd138f2d7e27d114c0145d968b5ff5006125f2414fadae698eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a488eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a488eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a488eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a488eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a480390084fdbf27d2b79d26a4f13f0ccd982cb755a661969143c37cbc49ef5b91f27", + "0xd57bce545fb382c34570e5dfbf338f5e4e7b9012096b41c4eb3aaf947f6ea429": "0x0000", + "0xd5c41b52a371aa36c9254ce34324f2a54e7b9012096b41c4eb3aaf947f6ea429": "0x0100", + "0xd5e1a2fa16732ce6906189438c0a82c64e7b9012096b41c4eb3aaf947f6ea429": "0x0000", + "0xd8bbe27baf3aa64bb483afabc240f68e4e7b9012096b41c4eb3aaf947f6ea429": "0x0000", + "0xd8f314b7f4e6b095f0f8ee4656a448254e7b9012096b41c4eb3aaf947f6ea429": "0x0100", + "0xda7d4185f8093e80caceb64da45219e30c98535b82c72faf3c64974094af4643": "0x010000000000000002000000697ea2a8fe5b03468548a7a413424a6292ab44a82a6f5cc594c3fa7dda7ce402", + "0xda7d4185f8093e80caceb64da45219e34e7b9012096b41c4eb3aaf947f6ea429": "0x0000", + "0xda7d4185f8093e80caceb64da45219e3c52aa943bf0908860a3eea0fad707cdc": "0x000000000000000002000000697ea2a8fe5b03468548a7a413424a6292ab44a82a6f5cc594c3fa7dda7ce402", + "0xe2e62dd81c48a88f73b6f6463555fd8e4e7b9012096b41c4eb3aaf947f6ea429": "0x0400", + "0xed25f63942de25ac5253ba64b5eb64d14e7b9012096b41c4eb3aaf947f6ea429": "0x0400", + "0xedfb05b766f199ce00df85317e33050e4e7b9012096b41c4eb3aaf947f6ea429": "0x0000", + "0xf0c365c3cf59d671eb72da0e7a4113c44e7b9012096b41c4eb3aaf947f6ea429": "0x0000", + "0xf2794c22e353e9a839f12faab03a911b4e7b9012096b41c4eb3aaf947f6ea429": "0x0100", + "0xf2794c22e353e9a839f12faab03a911b7f17cdfbfa73331856cca0acddd7842e": "0x00000000", + "0xf2794c22e353e9a839f12faab03a911bbdcb0c5143a8617ed38ae3810dd45bc6": "0x00000000", + "0xf2794c22e353e9a839f12faab03a911be2f6cb0456905c189bcb0458f9440f13": "0x00000000", + "0xf5207f03cfdce586301014700e2c25934e7b9012096b41c4eb3aaf947f6ea429": "0x0100" + }, + "childrenDefault": {} + } + } +} \ No newline at end of file diff --git a/bitacross-worker/docker/multiworker-docker-compose.yml b/bitacross-worker/docker/multiworker-docker-compose.yml new file mode 100644 index 0000000000..081077de84 --- /dev/null +++ b/bitacross-worker/docker/multiworker-docker-compose.yml @@ -0,0 +1,257 @@ +services: + relaychain-alice: + image: docker_relaychain-alice:latest + networks: + - litentry-test-network + ports: + - 9946:9944 + - 9936:9933 + - 30336:30333 + volumes: + - relaychain-alice:/data + build: + context: litentry + dockerfile: relaychain.Dockerfile + command: + - --base-path=/data + - --chain=/app/rococo-local.json + - --validator + - --ws-external + - --rpc-external + - --rpc-cors=all + - --name=alice + - --alice + - --rpc-methods=unsafe + - --execution=wasm + environment: + RUST_LOG: parachain::candidate-backing=trace,parachain::candidate-selection=trace,parachain::pvf=trace,parachain::collator-protocol=trace,parachain::provisioner=trace + ulimits: + &a1 + nofile: + soft: 65536 + hard: 65536 + relaychain-bob: + image: docker_relaychain-bob:latest + networks: + - litentry-test-network + ports: + - 9947:9944 + - 9937:9933 + - 30337:30333 + volumes: + - relaychain-bob:/data + build: + context: litentry + dockerfile: relaychain.Dockerfile + command: + - --base-path=/data + - --chain=/app/rococo-local.json + - --validator + - --ws-external + - --rpc-external + - --rpc-cors=all + - --name=bob + - --bob + - --rpc-methods=unsafe + - --execution=wasm + environment: + RUST_LOG: parachain::candidate-backing=trace,parachain::candidate-selection=trace,parachain::pvf=trace,parachain::collator-protocol=trace,parachain::provisioner=trace + ulimits: *a1 + litentry-node: + image: docker_litentry-node:latest + container_name: litentry-node + networks: + - litentry-test-network + ports: + # TODO: maybe not use 9912 as port + - 9944:9912 + - 9933:9933 + - 30333:30333 + volumes: + - parachain-2106-0:/data + build: + context: litentry + dockerfile: parachain-2106.Dockerfile + depends_on: ['relaychain-alice', 'relaychain-bob'] + healthcheck: + test: ["CMD", "nc", "-z", "litentry-node", "9912"] + interval: 30s + timeout: 10s + retries: 20 + command: + - --base-path=/data + - --chain=/app/rococo-dev-2106.json + - --ws-external + - --rpc-external + - --rpc-cors=all + - --name=parachain-2106-0 + - --ws-port=9912 + - --collator + - --rpc-methods=unsafe + - --force-authoring + - --execution=wasm + - --alice + - --node-key=e998e728d8bf5bff6670c5e2b20455f6de1742b7ca564057680c9781cf037dd1 + - --listen-addr=/ip4/0.0.0.0/tcp/30333 + - -- + - --chain=/app/rococo-local.json + - --execution=wasm + environment: + RUST_LOG: sc_basic_authorship=trace,cumulus-consensus=trace,cumulus-collator=trace,collator_protocol=trace,collation_generation=trace,aura=debug + + ulimits: *a1 + bitacross-worker-1: + image: litentry/bitacross-worker:latest + container_name: bitacross-worker-1 + build: + context: ${PWD}/.. + dockerfile: build.Dockerfile + target: deployed-worker + depends_on: + litentry-node: + condition: service_healthy + devices: + - "${SGX_PROVISION:-/dev/null}:/dev/sgx/provision" + - "${SGX_ENCLAVE:-/dev/null}:/dev/sgx/enclave" + volumes: + - "${AESMD:-/dev/null}:/var/run/aesmd" + - "${SGX_QCNL:-/dev/null}:/etc/sgx_default_qcnl.conf" + environment: + - RUST_LOG=info,litentry_worker=debug,ws=warn,sp_io=error,substrate_api_client=warn,itc_parentchain_light_client=info,jsonrpsee_ws_client=warn,jsonrpsee_ws_server=warn,enclave_runtime=debug,ita_stf=debug,its_rpc_handler=warn,itc_rpc_client=warn,its_consensus_common=debug,its_state=warn,its_consensus_aura=warn,aura*=warn,its_consensus_slots=warn,itp_attestation_handler=debug,http_req=debug,lc_mock_server=warn,itc_rest_client=debug,lc_credentials=debug,lc_identity_verification=debug,lc_stf_task_receiver=debug,lc_stf_task_sender=debug,lc_data_providers=debug,itp_top_pool=debug,itc_parentchain_indirect_calls_executor=debug, + - TWITTER_OFFICIAL_URL=http://localhost:19527 + - TWITTER_LITENTRY_URL=http://localhost:19527 + - TWITTER_AUTH_TOKEN_V2= + - DISCORD_OFFICIAL_URL=http://localhost:19527 + - DISCORD_LITENTRY_URL=http://localhost:19527 + - DISCORD_AUTH_TOKEN= + - ACHAINABLE_URL=http://localhost:19527 + - ACHAINABLE_AUTH_KEY= + - CREDENTIAL_ENDPOINT=http://localhost:9933 + - ONEBLOCK_NOTION_KEY=ABCDEFGHIJKLMNOPQRSTUVWXYZ + - ONEBLOCK_NOTION_URL=https://abc.com + - SORA_QUIZ_MASTER_ID=SORA_QUIZ_MASTER_ID + - SORA_QUIZ_ATTENDEE_ID=SORA_QUIZ_ATTENDEE_ID + - NODEREAL_API_KEY=NODEREAL_API_KEY + - NODEREAL_API_URL=https://open-platform.nodereal.io/ + - CONTEST_LEGEND_DISCORD_ROLE_ID=CONTEST_LEGEND_DISCORD_ROLE_ID + - CONTEST_POPULARITY_DISCORD_ROLE_ID=CONTEST_POPULARITY_DISCORD_ROLE_ID + - CONTEST_PARTICIPANT_DISCORD_ROLE_ID=CONTEST_PARTICIPANT_DISCORD_ROLE_ID + networks: + - litentry-test-network + healthcheck: + test: curl -s -f http://bitacross-worker-1:4645/is_initialized || exit 1 + interval: 30s + timeout: 10s + retries: 20 + entrypoint: + "/usr/local/bin/bitacross-worker --clean-reset --ws-external -M bitacross-worker-1 -T wss://bitacross-worker-1 + -u ws://litentry-node -U ws://bitacross-worker-1 -P 2011 -w 2101 -p 9912 -h 4645 + run --dev --skip-ra" + restart: "no" + bitacross-worker-2: + image: litentry/bitacross-worker:latest + container_name: bitacross-worker-2 + build: + context: ${PWD}/.. + dockerfile: build.Dockerfile + target: deployed-worker + depends_on: + litentry-node: + condition: service_healthy + bitacross-worker-1: + condition: service_healthy + devices: + - "${SGX_PROVISION:-/dev/null}:/dev/sgx/provision" + - "${SGX_ENCLAVE:-/dev/null}:/dev/sgx/enclave" + volumes: + - "${AESMD:-/dev/null}:/var/run/aesmd" + - "${SGX_QCNL:-/dev/null}:/etc/sgx_default_qcnl.conf" + environment: + - RUST_LOG=info,litentry_worker=debug,ws=warn,sp_io=error,substrate_api_client=warn,itc_parentchain_light_client=info,jsonrpsee_ws_client=warn,jsonrpsee_ws_server=warn,enclave_runtime=debug,ita_stf=debug,its_rpc_handler=warn,itc_rpc_client=warn,its_consensus_common=debug,its_state=warn,its_consensus_aura=warn,aura*=warn,its_consensus_slots=warn,itp_attestation_handler=debug,http_req=debug,lc_mock_server=warn,itc_rest_client=debug,lc_credentials=debug,lc_identity_verification=debug,lc_stf_task_receiver=debug,lc_stf_task_sender=debug,lc_data_providers=debug,itp_top_pool=debug,itc_parentchain_indirect_calls_executor=debug, + - TWITTER_OFFICIAL_URL=http://localhost:19527 + - TWITTER_LITENTRY_URL=http://localhost:19527 + - TWITTER_AUTH_TOKEN_V2= + - DISCORD_OFFICIAL_URL=http://localhost:19527 + - DISCORD_LITENTRY_URL=http://localhost:19527 + - DISCORD_AUTH_TOKEN= + - ACHAINABLE_URL=http://localhost:19527 + - ACHAINABLE_AUTH_KEY= + - CREDENTIAL_ENDPOINT=http://localhost:9933 + - ONEBLOCK_NOTION_KEY=ABCDEFGHIJKLMNOPQRSTUVWXYZ + - ONEBLOCK_NOTION_URL=https://abc.com + - SORA_QUIZ_MASTER_ID=SORA_QUIZ_MASTER_ID + - SORA_QUIZ_ATTENDEE_ID=SORA_QUIZ_ATTENDEE_ID + - NODEREAL_API_KEY=NODEREAL_API_KEY + - NODEREAL_API_URL=https://open-platform.nodereal.io/ + - CONTEST_LEGEND_DISCORD_ROLE_ID=CONTEST_LEGEND_DISCORD_ROLE_ID + - CONTEST_POPULARITY_DISCORD_ROLE_ID=CONTEST_POPULARITY_DISCORD_ROLE_ID + - CONTEST_PARTICIPANT_DISCORD_ROLE_ID=CONTEST_PARTICIPANT_DISCORD_ROLE_ID + networks: + - litentry-test-network + healthcheck: + test: curl -s -f http://bitacross-worker-2:4645/is_initialized || exit 1 + interval: 30s + timeout: 10s + retries: 20 + entrypoint: + "/usr/local/bin/bitacross-worker --clean-reset --ws-external -M bitacross-worker-2 -T wss://bitacross-worker-2 + -u ws://litentry-node -U ws://litentry-worker-2 -P 2011 -w 2101 -p 9912 -h 4645 + run --dev --skip-ra --request-state" + restart: "no" + litentry-worker-3: + image: litentry/litentry-worker:latest + container_name: litentry-worker-3 + build: + context: ${PWD}/.. + dockerfile: build.Dockerfile + target: deployed-worker + depends_on: + litentry-node: + condition: service_healthy + litentry-worker-2: + condition: service_healthy + devices: + - "${SGX_PROVISION:-/dev/null}:/dev/sgx/provision" + - "${SGX_ENCLAVE:-/dev/null}:/dev/sgx/enclave" + volumes: + - "${AESMD:-/dev/null}:/var/run/aesmd" + - "${SGX_QCNL:-/dev/null}:/etc/sgx_default_qcnl.conf" + environment: + - RUST_LOG=info,litentry_worker=debug,ws=warn,sp_io=error,substrate_api_client=warn,itc_parentchain_light_client=info,jsonrpsee_ws_client=warn,jsonrpsee_ws_server=warn,enclave_runtime=debug,ita_stf=debug,its_rpc_handler=warn,itc_rpc_client=warn,its_consensus_common=debug,its_state=warn,its_consensus_aura=warn,aura*=warn,its_consensus_slots=warn,itp_attestation_handler=debug,http_req=debug,lc_mock_server=warn,itc_rest_client=debug,lc_credentials=debug,lc_identity_verification=debug,lc_stf_task_receiver=debug,lc_stf_task_sender=debug,lc_data_providers=debug,itp_top_pool=debug,itc_parentchain_indirect_calls_executor=debug, + - TWITTER_OFFICIAL_URL=http://localhost:19527 + - TWITTER_LITENTRY_URL=http://localhost:19527 + - TWITTER_AUTH_TOKEN_V2= + - DISCORD_OFFICIAL_URL=http://localhost:19527 + - DISCORD_LITENTRY_URL=http://localhost:19527 + - DISCORD_AUTH_TOKEN= + - ACHAINABLE_URL=http://localhost:19527 + - ACHAINABLE_AUTH_KEY= + - CREDENTIAL_ENDPOINT=http://localhost:9933 + - ONEBLOCK_NOTION_KEY=ABCDEFGHIJKLMNOPQRSTUVWXYZ + - ONEBLOCK_NOTION_URL=https://abc.com + - SORA_QUIZ_MASTER_ID=SORA_QUIZ_MASTER_ID + - SORA_QUIZ_ATTENDEE_ID=SORA_QUIZ_ATTENDEE_ID + - NODEREAL_API_KEY=NODEREAL_API_KEY + - NODEREAL_API_URL=https://open-platform.nodereal.io/ + - CONTEST_LEGEND_DISCORD_ROLE_ID=CONTEST_LEGEND_DISCORD_ROLE_ID + - CONTEST_POPULARITY_DISCORD_ROLE_ID=CONTEST_POPULARITY_DISCORD_ROLE_ID + - CONTEST_PARTICIPANT_DISCORD_ROLE_ID=CONTEST_PARTICIPANT_DISCORD_ROLE_ID + networks: + - litentry-test-network + healthcheck: + test: curl -s -f http://litentry-worker-3:4645/is_initialized || exit 1 + interval: 30s + timeout: 10s + retries: 20 + entrypoint: + "/usr/local/bin/litentry-worker --clean-reset --ws-external -M litentry-worker-3 -T wss://litentry-worker-3 + -u ws://litentry-node -U ws://litentry-worker-3 -P 2011 -w 2101 -p 9912 -h 4645 + run --dev --skip-ra --request-state" + restart: "no" +volumes: + ? relaychain-alice + ? relaychain-bob + ? parachain-2106-0 +networks: + litentry-test-network: + driver: bridge diff --git a/bitacross-worker/docker/ping.Dockerfile b/bitacross-worker/docker/ping.Dockerfile new file mode 100644 index 0000000000..50ea4b7723 --- /dev/null +++ b/bitacross-worker/docker/ping.Dockerfile @@ -0,0 +1,19 @@ +# Copyright 2021 Integritee AG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +FROM alpine:latest + +RUN apk add --update iproute2 + +ENTRYPOINT ping \ No newline at end of file diff --git a/bitacross-worker/docker/sidechain-benchmark.yml b/bitacross-worker/docker/sidechain-benchmark.yml new file mode 100644 index 0000000000..5158cc3588 --- /dev/null +++ b/bitacross-worker/docker/sidechain-benchmark.yml @@ -0,0 +1,27 @@ +services: + sidechain-benchmark: + image: bitacross-cli:${VERSION:-dev} + devices: + - "${SGX_PROVISION:-/dev/null}:/dev/sgx/provision" + - "${SGX_ENCLAVE:-/dev/null}:/dev/sgx/enclave" + volumes: + - "${AESMD:-/dev/null}:/var/run/aesmd" + - "${SGX_QCNL:-/dev/null}:/etc/sgx_default_qcnl.conf" + build: + context: ${PWD}/.. + dockerfile: build.Dockerfile + target: deployed-client + depends_on: + litentry-node-${VERSION}: + condition: service_healthy + bitacross-worker-1-${VERSION}: + condition: service_healthy + networks: + - litentry-test-network + entrypoint: + "/usr/local/worker-cli/benchmark.sh -p 9912 -A 2011 -u ws://litentry-node + -V wss://bitacross-worker-1 -C /usr/local/bin/bitacross-cli 2>&1" + restart: "no" +networks: + litentry-test-network: + driver: bridge \ No newline at end of file diff --git a/bitacross-worker/docs/README.md b/bitacross-worker/docs/README.md new file mode 100644 index 0000000000..c0e42e94fa --- /dev/null +++ b/bitacross-worker/docs/README.md @@ -0,0 +1,25 @@ +# Knowhow Dump + +This folder contains documents and links that contain some (potentially outdated) information about the worker. +Use with caution, as this is work in progress. Hence, the code is most likely progressing faster than this documentation. + +## Useful links: +### O- / Ecalls +- Ocall Bridge: https://github.com/integritee-network/worker/pull/293 & https://github.com/integritee-network/worker/pull/299 +- Enclave ecalls / ocalls: https://github.com/integritee-network/worker/issues/279 +- Abstract ecalls in enclave: https://github.com/integritee-network/worker/issues/286 +- Abstract ocalls in enclave: https://github.com/integritee-network/worker/issues/279 + +### Sidechain +- Sidechain functionality: https://polkadot.polkassembly.io/post/111 +- Sidechain flow: https://github.com/integritee-network/worker/pull/627 +- Simplified sidechain sequence, of a user call and the STF: https://raw.githubusercontent.com/haerdib/substraTEE_diagramms/main/sidechain-sequence.svg +- Top_pool sequence: https://raw.githubusercontent.com/haerdib/substraTEE_diagramms/main/submit_and_watch_sequence.svg +### Parentchain +- A rough overview of the architecture surrounding the parentchain block import dispatching: https://github.com/integritee-network/worker/pull/530 + +### Runtime +- Enclave runtime: https://github.com/integritee-network/worker/pull/472 + +### Non-worker related graphics +- substrate related graphics: https://github.com/brenzi/substrate-doc diff --git a/bitacross-worker/docs/diagramms/block_import_sequence.svg b/bitacross-worker/docs/diagramms/block_import_sequence.svg new file mode 100644 index 0000000000..369cecb4ab --- /dev/null +++ b/bitacross-worker/docs/diagramms/block_import_sequence.svg @@ -0,0 +1,4 @@ + + + +
For every
sidechain block
For every...
For every
parentchain block
For every...
For every
extrinsic
For every...
For every
shard
For every...
Parentchain BlockImport Queue
pop queue until()
pop queue until()
Light Client
verify block
verify block
import block
import block
! state update
! state update
Node
Validateer / Worker
Validateer / Worker
Substrate Node
Substrate Node
Event: New Finalized Blockget_blocks(last_synced_header)
finalized blocks
finalized blocks
Parentchain BlockImporter
push_to_
import_queue
push_to_...
sync_parentchain(finalized blocks)
last_synced_header
last_synced_header
Sgx Runtime
Sgx Runtime
Sidechain BlockImport Queue
new block
new block
import_block
import_block
Sidechain BlockProducer
create 
sidechain
block
create...
create proposed_sidechain_block
extrinsic
create proposed_sidechain_block...
Top PoolState
calculate state diff
(no state update!)
calculate state diff...
import_parentchain_block(import_until(sidechain block -> parentchain block))Untrusted Listenersubmit_simple_header
Ok()
Ok()
send parentchain extrinsics
send parentchai...
check time
check time
(if_author == self)remove tops (shard, hashes)
Ok()
Ok()
retrieve sidechain blocks
parentchain header
parentchain header
pop until(parentchain header)
blocks
blocks
peek assosciated parentchain header
sidechain blocks
sidechain blocks
latest imported parentchain header
latest imported parentchain header
Sidechain BlockImporter
verify sidechain
block
verify sidechain...
load_state(shard)
load_state(shard)
trigger sidechainblock import
latest parentchain header
latest parentchain header
trusted_calls(shard)
trusted_calls(shard)
get_trusted_calls(shard)Top Pool Execution Loop
intervall trigger
intervall t...
claim_slot
claim_slot
list_shards
shards
shards
exec_aura_on_slot(shards,parentchain header)execute trusted calls(trusted calls)
state_diff, executed hashes
state_diff, executed hashes
sidechain blocks,
extrinsics
sidechain blocks,...
broadcast sidechain block
broadcast sidechai...
Stf::execute(state)
updated state
updated state
Executor
write
(updated state)
write...
execute_indirect_calls_extrinsic(block)
Ok()
Ok()
write(updated_state)
write(updated_state)
For every
parentchain block
For every...
For every
extrinsic
For every...
pop queue until()
pop queue until()
verify block
verify block
import block
import block
! state update
! state update
submit_simple_header
Ok()
Ok()
pop until(parentchain header)
blocks
blocks
latest imported parentchain header
latest imported parentchain header
write
(updated state)
write...
execute_indirect_calls_extrinsic(block)
Ok()
Ok()
import_latest_parentchain_block(parentchain_hedaer)Stf::execute(state)
updated state
updated state
apply_state_update(state, state_diff)+ set_last_block
updated state
updated state
remove invalid tops
Ok()
Ok()
Viewer does not support full SVG 1.1
\ No newline at end of file diff --git a/bitacross-worker/enclave-runtime/Cargo.lock b/bitacross-worker/enclave-runtime/Cargo.lock new file mode 100644 index 0000000000..ce53c8dc84 --- /dev/null +++ b/bitacross-worker/enclave-runtime/Cargo.lock @@ -0,0 +1,5349 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "Inflector" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3" +dependencies = [ + "lazy_static", + "regex 1.9.5", +] + +[[package]] +name = "ac-compose-macros" +version = "0.4.2" +source = "git+https://github.com/scs/substrate-api-client.git?branch=polkadot-v0.9.42-tag-v0.14.0#e4ed74b0fb6c2fd5585f55c2702b97b56d99c7f6" +dependencies = [ + "ac-primitives", + "log", + "maybe-async", +] + +[[package]] +name = "ac-node-api" +version = "0.5.1" +source = "git+https://github.com/scs/substrate-api-client.git?branch=polkadot-v0.9.42-tag-v0.14.0#e4ed74b0fb6c2fd5585f55c2702b97b56d99c7f6" +dependencies = [ + "ac-primitives", + "bitvec", + "derive_more", + "either", + "frame-metadata", + "hex", + "log", + "parity-scale-codec", + "scale-bits", + "scale-decode", + "scale-encode", + "scale-info", + "serde 1.0.193", + "serde_json 1.0.107", + "sp-application-crypto", + "sp-core", + "sp-runtime", + "sp-runtime-interface", +] + +[[package]] +name = "ac-primitives" +version = "0.9.0" +source = "git+https://github.com/scs/substrate-api-client.git?branch=polkadot-v0.9.42-tag-v0.14.0#e4ed74b0fb6c2fd5585f55c2702b97b56d99c7f6" +dependencies = [ + "impl-serde", + "parity-scale-codec", + "primitive-types", + "scale-info", + "serde 1.0.193", + "serde_json 1.0.107", + "sp-application-crypto", + "sp-core", + "sp-core-hashing", + "sp-runtime", + "sp-runtime-interface", + "sp-staking", + "sp-version", + "sp-weights", +] + +[[package]] +name = "aes" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "884391ef1066acaa41e766ba8f596341b96e93ce34f9a43e7d24bf0a0eaf0561" +dependencies = [ + "aes-soft", + "aesni", + "cipher", +] + +[[package]] +name = "aes-soft" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be14c7498ea50828a38d0e24a765ed2effe92a705885b57d029cd67d45744072" +dependencies = [ + "cipher", + "opaque-debug 0.3.0", +] + +[[package]] +name = "aesni" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea2e11f5e94c2f7d386164cc2aa1f97823fed6f259e486940a71c174dd01b0ce" +dependencies = [ + "cipher", + "opaque-debug 0.3.0", +] + +[[package]] +name = "ahash" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" +dependencies = [ + "getrandom 0.2.12", + "once_cell 1.18.0", + "version_check", +] + +[[package]] +name = "ahash" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" +dependencies = [ + "cfg-if 1.0.0", + "once_cell 1.18.0", + "version_check", +] + +[[package]] +name = "aho-corasick" +version = "0.7.10" +source = "git+https://github.com/mesalock-linux/aho-corasick-sgx#7558a97cdf02804f38ec4edd1c0bb0dc2866267f" +dependencies = [ + "memchr 2.2.1", + "sgx_tstd", +] + +[[package]] +name = "aho-corasick" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea5d730647d4fadd988536d06fecce94b7b4f2a7efdae548f1cf4b63205518ab" +dependencies = [ + "memchr 2.6.3", +] + +[[package]] +name = "array-bytes" +version = "4.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f52f63c5c1316a16a4b35eaac8b76a98248961a533f061684cb2a7cb0eafb6c6" + +[[package]] +name = "array-bytes" +version = "6.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b1c5a481ec30a5abd8dfbd94ab5cf1bb4e9a66be7f1b3b322f2f1170c200fd" + +[[package]] +name = "arrayref" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" + +[[package]] +name = "arrayvec" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" + +[[package]] +name = "arrayvec" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" + +[[package]] +name = "async-trait" +version = "0.1.73" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc00ceb34980c03614e35a3a4e218276a0a824e911d07651cd0d858a51e8c0f0" +dependencies = [ + "proc-macro2", + "quote 1.0.33", + "syn 2.0.37", +] + +[[package]] +name = "auto_impl" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fee3da8ef1276b0bee5dd1c7258010d8fffd31801447323115a25560e1327b89" +dependencies = [ + "proc-macro-error", + "proc-macro2", + "quote 1.0.33", + "syn 1.0.109", +] + +[[package]] +name = "autocfg" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dde43e75fd43e8a1bf86103336bc699aa8d17ad1be60c76c0bdfd4828e19b78" +dependencies = [ + "autocfg 1.1.0", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "base-x" +version = "0.2.6" +source = "git+https://github.com/whalelephant/base-x-rs?branch=no_std#906c9ac59282ff5a2eec86efd25d50ad9927b147" + +[[package]] +name = "base16ct" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" + +[[package]] +name = "base64" +version = "0.13.0" +source = "git+https://github.com/mesalock-linux/rust-base64-sgx?tag=sgx_1.1.3#dc7389e10817b078f289386b3b6a852ab6c4c021" +dependencies = [ + "sgx_tstd", +] + +[[package]] +name = "base64" +version = "0.13.0" +source = "git+https://github.com/mesalock-linux/rust-base64-sgx?rev=sgx_1.1.3#dc7389e10817b078f289386b3b6a852ab6c4c021" +dependencies = [ + "sgx_tstd", +] + +[[package]] +name = "base64" +version = "0.13.0" +source = "git+https://github.com/mesalock-linux/rust-base64-sgx#dc7389e10817b078f289386b3b6a852ab6c4c021" +dependencies = [ + "sgx_tstd", +] + +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + +[[package]] +name = "bech32" +version = "0.10.0-beta" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98f7eed2b2781a6f0b5c903471d48e15f56fb4e1165df8a9a2337fd1a59d45ea" + +[[package]] +name = "binary-merkle-tree" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "hash-db 0.16.0", +] + +[[package]] +name = "bit-vec" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" + +[[package]] +name = "bitcoin" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5973a027b341b462105675962214dfe3c938ad9afd395d84b28602608bdcec7b" +dependencies = [ + "bech32", + "bitcoin-internals", + "bitcoin_hashes", + "core2", + "hex-conservative", + "hex_lit", + "secp256k1 0.28.0", +] + +[[package]] +name = "bitcoin-internals" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9425c3bf7089c983facbae04de54513cce73b41c7f9ff8c845b54e7bc64ebbfb" + +[[package]] +name = "bitcoin_hashes" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1930a4dabfebb8d7d9992db18ebe3ae2876f0a305fab206fd168df931ede293b" +dependencies = [ + "bitcoin-internals", + "core2", + "hex-conservative", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + +[[package]] +name = "blake2" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" +dependencies = [ + "digest 0.10.7", +] + +[[package]] +name = "blake2b_simd" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afa748e348ad3be8263be728124b24a24f268266f6f5d58af9d75f6a40b5c587" +dependencies = [ + "arrayref", + "arrayvec 0.5.2", + "constant_time_eq 0.1.5", +] + +[[package]] +name = "blake2b_simd" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23285ad32269793932e830392f2fe2f83e26488fd3ec778883a93c8323735780" +dependencies = [ + "arrayref", + "arrayvec 0.7.4", + "constant_time_eq 0.3.0", +] + +[[package]] +name = "blake2s_simd" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e461a7034e85b211a4acb57ee2e6730b32912b06c08cc242243c39fc21ae6a2" +dependencies = [ + "arrayref", + "arrayvec 0.5.2", + "constant_time_eq 0.1.5", +] + +[[package]] +name = "block-buffer" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" +dependencies = [ + "block-padding 0.1.5", + "byte-tools", + "byteorder 1.4.3", + "generic-array 0.12.4", +] + +[[package]] +name = "block-buffer" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" +dependencies = [ + "block-padding 0.2.1", + "generic-array 0.14.7", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array 0.14.7", +] + +[[package]] +name = "block-padding" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" +dependencies = [ + "byte-tools", +] + +[[package]] +name = "block-padding" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" + +[[package]] +name = "bounded-collections" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb5b05133427c07c4776906f673ccf36c21b102c9829c641a5b56bd151d44fd6" +dependencies = [ + "log", + "parity-scale-codec", + "scale-info", +] + +[[package]] +name = "bs58" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3" + +[[package]] +name = "bumpalo" +version = "3.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" + +[[package]] +name = "byte-slice-cast" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" + +[[package]] +name = "byte-tools" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" + +[[package]] +name = "byteorder" +version = "1.3.4" +source = "git+https://github.com/mesalock-linux/byteorder-sgx?tag=sgx_1.1.3#325f392dcd294109eb05f0a3c45e4141514c7784" +dependencies = [ + "sgx_tstd", +] + +[[package]] +name = "byteorder" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" + +[[package]] +name = "bytes" +version = "1.0.1" +source = "git+https://github.com/integritee-network/bytes-sgx?branch=sgx-experimental#62ed3082be2e23cb9bc8cc7ee9983a523de69292" +dependencies = [ + "sgx_tstd", +] + +[[package]] +name = "bytes" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" + +[[package]] +name = "cargo_toml" +version = "0.16.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3f9629bc6c4388ea699781dc988c2b99766d7679b151c81990b4fa1208fafd3" +dependencies = [ + "serde 1.0.193", + "toml", +] + +[[package]] +name = "cc" +version = "1.0.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +dependencies = [ + "libc", +] + +[[package]] +name = "cfg-expr" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0aacacf4d96c24b2ad6eb8ee6df040e4f27b0d0b39a5710c30091baa830485db" +dependencies = [ + "smallvec 1.11.1", +] + +[[package]] +name = "cfg-if" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "chrono" +version = "0.4.11" +source = "git+https://github.com/mesalock-linux/chrono-sgx#f964ae7f5f65bd2c9cd6f44a067e7980afc08ca0" +dependencies = [ + "num-integer", + "num-traits 0.2.10", + "sgx_tstd", +] + +[[package]] +name = "chrono" +version = "0.4.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38" +dependencies = [ + "num-traits 0.2.16", +] + +[[package]] +name = "cid" +version = "0.5.1" +source = "git+https://github.com/whalelephant/rust-cid?branch=nstd#cca87467c46106c801ca3727500477258b0f13b0" +dependencies = [ + "multibase", + "multihash", + "unsigned-varint", +] + +[[package]] +name = "cipher" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12f8e7987cbd042a63249497f41aed09f8e65add917ea6566effbc56578d6801" +dependencies = [ + "generic-array 0.14.7", +] + +[[package]] +name = "common-primitives" +version = "0.1.0" +source = "git+https://github.com/integritee-network/pallets.git?branch=sdk-v0.12.0-polkadot-v0.9.42#eaf611b79bc9d56b20c155150e99b549bf98436b" +dependencies = [ + "derive_more", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "const-oid" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28c122c3980598d243d63d9a704629a2d748d101f278052ff068be5a4423ab6f" + +[[package]] +name = "constant_time_eq" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" + +[[package]] +name = "constant_time_eq" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7144d30dcf0fafbce74250a3963025d8d52177934239851c917d29f1df280c2" + +[[package]] +name = "convert_case" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" + +[[package]] +name = "core-primitives" +version = "0.9.12" +dependencies = [ + "frame-support", + "litentry-hex-utils", + "litentry-macros 0.9.12", + "litentry-proc-macros", + "pallet-evm 6.0.0-dev (git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42)", + "parity-scale-codec", + "ring 0.16.20", + "scale-info", + "serde 1.0.193", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", + "strum", + "strum_macros", +] + +[[package]] +name = "core2" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "239fa3ae9b63c2dc74bd3fa852d4792b8b305ae64eeede946265b6af62f1fff3" +dependencies = [ + "memchr 2.6.3", +] + +[[package]] +name = "cpufeatures" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" +dependencies = [ + "libc", +] + +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + +[[package]] +name = "crypto-bigint" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "740fe28e594155f10cfc383984cbefd529d7396050557148f79cb0f621204124" +dependencies = [ + "generic-array 0.14.7", + "rand_core 0.6.4", + "subtle", + "zeroize", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array 0.14.7", + "typenum 1.17.0", +] + +[[package]] +name = "curve25519-dalek" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a9b85542f99a2dfa2a1b8e192662741c9859a846b296bef1c92ef9b58b5a216" +dependencies = [ + "byteorder 1.4.3", + "digest 0.8.1", + "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "subtle", + "zeroize", +] + +[[package]] +name = "curve25519-dalek" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b9fdf9972b2bd6af2d913799d9ebc165ea4d2e65878e329d9c6b372c4491b61" +dependencies = [ + "byteorder 1.4.3", + "digest 0.9.0", + "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "subtle", + "zeroize", +] + +[[package]] +name = "darling" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "109c1ca6e6b7f82cc233a97004ea8ed7ca123a9af07a8230878fcfda9b158bf0" +dependencies = [ + "fnv 1.0.7", + "ident_case", + "proc-macro2", + "quote 1.0.33", + "strsim", + "syn 1.0.109", +] + +[[package]] +name = "darling_macro" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e" +dependencies = [ + "darling_core", + "quote 1.0.33", + "syn 1.0.109", +] + +[[package]] +name = "data-encoding" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308" + +[[package]] +name = "der" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fffa369a668c8af7dbf8b5e56c9f744fbd399949ed171606040001947de40b1c" +dependencies = [ + "const-oid", + "zeroize", +] + +[[package]] +name = "derive-syn-parse" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e79116f119dd1dba1abf1f3405f03b9b0e79a27a3883864bfebded8a3dc768cd" +dependencies = [ + "proc-macro2", + "quote 1.0.33", + "syn 1.0.109", +] + +[[package]] +name = "derive_more" +version = "0.99.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +dependencies = [ + "convert_case", + "proc-macro2", + "quote 1.0.33", + "rustc_version", + "syn 1.0.109", +] + +[[package]] +name = "digest" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" +dependencies = [ + "generic-array 0.12.4", +] + +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array 0.14.7", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer 0.10.4", + "const-oid", + "crypto-common", + "subtle", +] + +[[package]] +name = "ecdsa" +version = "0.16.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4b1e0c257a9e9f25f90ff76d7a68360ed497ee519c8e428d1825ef0000799d4" +dependencies = [ + "der", + "digest 0.10.7", + "elliptic-curve", + "rfc6979", + "signature", +] + +[[package]] +name = "ed25519-zebra" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c24f403d068ad0b359e577a77f92392118be3f3c927538f2bb544a5ecd828c6" +dependencies = [ + "curve25519-dalek 3.2.0", + "hashbrown 0.12.3", + "hex", + "rand_core 0.6.4", + "sha2 0.9.9", + "zeroize", +] + +[[package]] +name = "either" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" + +[[package]] +name = "elliptic-curve" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "968405c8fdc9b3bf4df0a6638858cc0b52462836ab6b1c87377785dd09cf1c0b" +dependencies = [ + "base16ct", + "crypto-bigint", + "digest 0.10.7", + "ff", + "generic-array 0.14.7", + "group", + "rand_core 0.6.4", + "sec1", + "subtle", + "zeroize", +] + +[[package]] +name = "enclave-runtime" +version = "0.0.1" +dependencies = [ + "array-bytes 6.1.0", + "cid", + "derive_more", + "env_logger", + "frame-support", + "frame-system", + "hex", + "ipfs-unixfs", + "ita-oracle", + "ita-parentchain-interface", + "ita-sgx-runtime", + "ita-stf", + "itc-direct-rpc-client", + "itc-direct-rpc-server", + "itc-offchain-worker-executor", + "itc-parentchain", + "itc-parentchain-block-import-dispatcher", + "itc-parentchain-test", + "itc-peer-top-broadcaster", + "itc-tls-websocket-server", + "itp-attestation-handler", + "itp-component-container", + "itp-enclave-metrics", + "itp-extrinsics-factory", + "itp-import-queue", + "itp-node-api", + "itp-node-api-metadata", + "itp-nonce-cache", + "itp-ocall-api", + "itp-primitives-cache", + "itp-rpc", + "itp-settings", + "itp-sgx-crypto", + "itp-sgx-externalities", + "itp-sgx-temp-dir", + "itp-stf-executor", + "itp-stf-interface", + "itp-stf-primitives", + "itp-stf-state-handler", + "itp-stf-state-observer", + "itp-storage", + "itp-test", + "itp-time-utils", + "itp-top-pool", + "itp-top-pool-author", + "itp-types", + "itp-utils", + "its-block-verification", + "its-primitives", + "its-sidechain", + "jsonrpc-core", + "lazy_static", + "lc-scheduled-enclave", + "litentry-macros 0.1.0", + "litentry-primitives", + "log", + "multibase", + "once_cell 1.4.0", + "parity-scale-codec", + "primitive-types", + "rust-base58", + "rustls 0.19.0 (git+https://github.com/mesalock-linux/rustls?rev=sgx_1.1.3)", + "serde_json 1.0.60 (git+https://github.com/mesalock-linux/serde-json-sgx?tag=sgx_1.1.3)", + "sgx_rand", + "sgx_serialize", + "sgx_serialize_derive", + "sgx_tcrypto", + "sgx_tcrypto_helper", + "sgx_trts", + "sgx_tse", + "sgx_tseal", + "sgx_tstd", + "sgx_tunittest", + "sgx_types", + "sp-core", + "sp-runtime", + "teerex-primitives 0.1.0 (git+https://github.com/integritee-network/pallets.git?branch=sdk-v0.12.0-polkadot-v0.9.42)", + "webpki", +] + +[[package]] +name = "env_logger" +version = "0.9.0" +source = "git+https://github.com/integritee-network/env_logger-sgx#55745829b2ae8a77f0915af3671ec8a9a00cace9" +dependencies = [ + "humantime", + "log", + "regex 1.3.1", + "sgx_tstd", + "termcolor", +] + +[[package]] +name = "environmental" +version = "1.1.3" +dependencies = [ + "sgx_tstd", +] + +[[package]] +name = "environmental" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e48c92028aaa870e83d51c64e5d4e0b6981b360c522198c23959f219a4e1b15b" + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "ethbloom" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c22d4b5885b6aa2fe5e8b9329fb8d232bf739e434e6b87347c63bdd00c120f60" +dependencies = [ + "crunchy", + "fixed-hash", + "impl-codec", + "impl-rlp", + "scale-info", + "tiny-keccak", +] + +[[package]] +name = "ethereum" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a89fb87a9e103f71b903b80b670200b54cc67a07578f070681f1fffb7396fb7" +dependencies = [ + "bytes 1.5.0", + "ethereum-types", + "hash-db 0.15.2", + "hash256-std-hasher", + "parity-scale-codec", + "rlp", + "scale-info", + "sha3 0.10.8", + "triehash", +] + +[[package]] +name = "ethereum-types" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02d215cbf040552efcbe99a38372fe80ab9d00268e20012b79fcd0f073edd8ee" +dependencies = [ + "ethbloom", + "fixed-hash", + "impl-codec", + "impl-rlp", + "primitive-types", + "scale-info", + "uint", +] + +[[package]] +name = "evm" +version = "0.39.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a49a4e11987c51220aa89dbe1a5cc877f5079fa6864c0a5b4533331db44e9365" +dependencies = [ + "auto_impl", + "ethereum", + "evm-core 0.39.0 (registry+https://github.com/rust-lang/crates.io-index)", + "evm-gasometer 0.39.0 (registry+https://github.com/rust-lang/crates.io-index)", + "evm-runtime 0.39.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log", + "parity-scale-codec", + "primitive-types", + "rlp", + "scale-info", + "sha3 0.10.8", +] + +[[package]] +name = "evm" +version = "0.39.1" +source = "git+https://github.com/rust-blockchain/evm?rev=b7b82c7e1fc57b7449d6dfa6826600de37cc1e65#b7b82c7e1fc57b7449d6dfa6826600de37cc1e65" +dependencies = [ + "auto_impl", + "ethereum", + "evm-core 0.39.0 (git+https://github.com/rust-blockchain/evm?rev=b7b82c7e1fc57b7449d6dfa6826600de37cc1e65)", + "evm-gasometer 0.39.0 (git+https://github.com/rust-blockchain/evm?rev=b7b82c7e1fc57b7449d6dfa6826600de37cc1e65)", + "evm-runtime 0.39.0 (git+https://github.com/rust-blockchain/evm?rev=b7b82c7e1fc57b7449d6dfa6826600de37cc1e65)", + "log", + "parity-scale-codec", + "primitive-types", + "rlp", + "scale-info", + "sha3 0.10.8", +] + +[[package]] +name = "evm-core" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f1f13264b044cb66f0602180f0bc781c29accb41ff560669a3ec15858d5b606" +dependencies = [ + "parity-scale-codec", + "primitive-types", + "scale-info", +] + +[[package]] +name = "evm-core" +version = "0.39.0" +source = "git+https://github.com/rust-blockchain/evm?rev=b7b82c7e1fc57b7449d6dfa6826600de37cc1e65#b7b82c7e1fc57b7449d6dfa6826600de37cc1e65" +dependencies = [ + "parity-scale-codec", + "primitive-types", + "scale-info", +] + +[[package]] +name = "evm-gasometer" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d43eadc395bd1a52990787ca1495c26b0248165444912be075c28909a853b8c" +dependencies = [ + "evm-core 0.39.0 (registry+https://github.com/rust-lang/crates.io-index)", + "evm-runtime 0.39.0 (registry+https://github.com/rust-lang/crates.io-index)", + "primitive-types", +] + +[[package]] +name = "evm-gasometer" +version = "0.39.0" +source = "git+https://github.com/rust-blockchain/evm?rev=b7b82c7e1fc57b7449d6dfa6826600de37cc1e65#b7b82c7e1fc57b7449d6dfa6826600de37cc1e65" +dependencies = [ + "evm-core 0.39.0 (git+https://github.com/rust-blockchain/evm?rev=b7b82c7e1fc57b7449d6dfa6826600de37cc1e65)", + "evm-runtime 0.39.0 (git+https://github.com/rust-blockchain/evm?rev=b7b82c7e1fc57b7449d6dfa6826600de37cc1e65)", + "primitive-types", +] + +[[package]] +name = "evm-runtime" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2aa5b32f59ec582a5651978004e5c784920291263b7dcb6de418047438e37f4f" +dependencies = [ + "auto_impl", + "evm-core 0.39.0 (registry+https://github.com/rust-lang/crates.io-index)", + "primitive-types", + "sha3 0.10.8", +] + +[[package]] +name = "evm-runtime" +version = "0.39.0" +source = "git+https://github.com/rust-blockchain/evm?rev=b7b82c7e1fc57b7449d6dfa6826600de37cc1e65#b7b82c7e1fc57b7449d6dfa6826600de37cc1e65" +dependencies = [ + "auto_impl", + "evm-core 0.39.0 (git+https://github.com/rust-blockchain/evm?rev=b7b82c7e1fc57b7449d6dfa6826600de37cc1e65)", + "primitive-types", + "sha3 0.10.8", +] + +[[package]] +name = "expander" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f360349150728553f92e4c997a16af8915f418d3a0f21b440d34c5632f16ed84" +dependencies = [ + "blake2", + "fs-err", + "proc-macro2", + "quote 1.0.33", + "syn 1.0.109", +] + +[[package]] +name = "fake-simd" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" + +[[package]] +name = "ff" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" +dependencies = [ + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "finality-grandpa" +version = "0.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36530797b9bf31cd4ff126dcfee8170f86b00cfdcea3269d73133cc0415945c3" +dependencies = [ + "either", + "futures 0.3.28", + "num-traits 0.2.16", + "parity-scale-codec", + "scale-info", +] + +[[package]] +name = "fixed-hash" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" +dependencies = [ + "byteorder 1.4.3", + "rustc-hex", + "static_assertions", +] + +[[package]] +name = "fnv" +version = "1.0.6" +source = "git+https://github.com/mesalock-linux/rust-fnv-sgx#c3bd6153c1403c1fa32fa54be5544d91f5efb017" +dependencies = [ + "hashbrown 0.3.1", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "fp-account" +version = "1.0.0-dev" +source = "git+https://github.com/integritee-network/frontier.git?branch=bar/polkadot-v0.9.42#a5a5e1e6ec08cd542a6084c310863150fb8841b1" +dependencies = [ + "hex", + "libsecp256k1", + "log", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "fp-account" +version = "1.0.0-dev" +source = "git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42#2499d18c936edbcb7fcb711827db7abb9b4f4da4" +dependencies = [ + "hex", + "libsecp256k1", + "log", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-io", + "sp-runtime", + "sp-runtime-interface", + "sp-std", +] + +[[package]] +name = "fp-evm" +version = "3.0.0-dev" +source = "git+https://github.com/integritee-network/frontier.git?branch=bar/polkadot-v0.9.42#a5a5e1e6ec08cd542a6084c310863150fb8841b1" +dependencies = [ + "evm 0.39.1 (registry+https://github.com/rust-lang/crates.io-index)", + "frame-support", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "fp-evm" +version = "3.0.0-dev" +source = "git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42#2499d18c936edbcb7fcb711827db7abb9b4f4da4" +dependencies = [ + "evm 0.39.1 (git+https://github.com/rust-blockchain/evm?rev=b7b82c7e1fc57b7449d6dfa6826600de37cc1e65)", + "frame-support", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "frame-executive" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "frame-support", + "frame-system", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", + "sp-tracing", +] + +[[package]] +name = "frame-metadata" +version = "15.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "878babb0b136e731cc77ec2fd883ff02745ff21e6fb662729953d44923df009c" +dependencies = [ + "cfg-if 1.0.0", + "parity-scale-codec", + "scale-info", + "serde 1.0.193", +] + +[[package]] +name = "frame-support" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "bitflags", + "environmental 1.1.4", + "frame-metadata", + "frame-support-procedural", + "impl-trait-for-tuples", + "k256", + "log", + "parity-scale-codec", + "paste", + "scale-info", + "smallvec 1.11.1", + "sp-api", + "sp-arithmetic", + "sp-core", + "sp-core-hashing-proc-macro", + "sp-inherents", + "sp-io", + "sp-runtime", + "sp-staking", + "sp-std", + "sp-tracing", + "sp-weights", + "tt-call", +] + +[[package]] +name = "frame-support-procedural" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "Inflector", + "cfg-expr", + "derive-syn-parse", + "frame-support-procedural-tools", + "itertools 0.10.5", + "proc-macro-warning", + "proc-macro2", + "quote 1.0.33", + "syn 2.0.37", +] + +[[package]] +name = "frame-support-procedural-tools" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "frame-support-procedural-tools-derive", + "proc-macro-crate", + "proc-macro2", + "quote 1.0.33", + "syn 2.0.37", +] + +[[package]] +name = "frame-support-procedural-tools-derive" +version = "3.0.0" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "proc-macro2", + "quote 1.0.33", + "syn 2.0.37", +] + +[[package]] +name = "frame-system" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "frame-support", + "log", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", + "sp-version", + "sp-weights", +] + +[[package]] +name = "fs-err" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0845fa252299212f0389d64ba26f34fa32cfe41588355f21ed507c59a0f64541" + +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + +[[package]] +name = "futures" +version = "0.3.8" +source = "git+https://github.com/mesalock-linux/futures-rs-sgx#d54882f24ddf7d61327a067b2f608d6940a36444" +dependencies = [ + "futures-channel 0.3.8", + "futures-core 0.3.8", + "futures-executor", + "futures-io 0.3.8", + "futures-sink 0.3.8", + "futures-task 0.3.8", + "futures-util 0.3.8", + "sgx_tstd", +] + +[[package]] +name = "futures" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40" +dependencies = [ + "futures-channel 0.3.28", + "futures-core 0.3.28", + "futures-io 0.3.28", + "futures-sink 0.3.28", + "futures-task 0.3.28", + "futures-util 0.3.28", +] + +[[package]] +name = "futures-channel" +version = "0.3.8" +source = "git+https://github.com/mesalock-linux/futures-rs-sgx#d54882f24ddf7d61327a067b2f608d6940a36444" +dependencies = [ + "futures-core 0.3.8", + "futures-sink 0.3.8", + "sgx_tstd", +] + +[[package]] +name = "futures-channel" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" +dependencies = [ + "futures-core 0.3.28", + "futures-sink 0.3.28", +] + +[[package]] +name = "futures-core" +version = "0.3.8" +source = "git+https://github.com/mesalock-linux/futures-rs-sgx#d54882f24ddf7d61327a067b2f608d6940a36444" +dependencies = [ + "sgx_tstd", +] + +[[package]] +name = "futures-core" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" + +[[package]] +name = "futures-executor" +version = "0.3.8" +source = "git+https://github.com/mesalock-linux/futures-rs-sgx#d54882f24ddf7d61327a067b2f608d6940a36444" +dependencies = [ + "futures-core 0.3.8", + "futures-task 0.3.8", + "futures-util 0.3.8", + "sgx_tstd", +] + +[[package]] +name = "futures-io" +version = "0.3.8" +source = "git+https://github.com/mesalock-linux/futures-rs-sgx#d54882f24ddf7d61327a067b2f608d6940a36444" +dependencies = [ + "sgx_tstd", +] + +[[package]] +name = "futures-io" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" + +[[package]] +name = "futures-macro" +version = "0.3.8" +source = "git+https://github.com/mesalock-linux/futures-rs-sgx#d54882f24ddf7d61327a067b2f608d6940a36444" +dependencies = [ + "proc-macro-hack", + "proc-macro2", + "quote 1.0.33", + "syn 1.0.109", +] + +[[package]] +name = "futures-sink" +version = "0.3.8" +source = "git+https://github.com/mesalock-linux/futures-rs-sgx#d54882f24ddf7d61327a067b2f608d6940a36444" + +[[package]] +name = "futures-sink" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" + +[[package]] +name = "futures-task" +version = "0.3.8" +source = "git+https://github.com/mesalock-linux/futures-rs-sgx#d54882f24ddf7d61327a067b2f608d6940a36444" +dependencies = [ + "once_cell 1.4.0", + "sgx_tstd", +] + +[[package]] +name = "futures-task" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" + +[[package]] +name = "futures-util" +version = "0.3.8" +source = "git+https://github.com/mesalock-linux/futures-rs-sgx#d54882f24ddf7d61327a067b2f608d6940a36444" +dependencies = [ + "futures-channel 0.3.8", + "futures-core 0.3.8", + "futures-io 0.3.8", + "futures-macro", + "futures-sink 0.3.8", + "futures-task 0.3.8", + "memchr 2.2.1", + "pin-project-lite", + "pin-utils", + "proc-macro-hack", + "proc-macro-nested", + "sgx_tstd", + "slab 0.4.2", +] + +[[package]] +name = "futures-util" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" +dependencies = [ + "futures-core 0.3.28", + "futures-sink 0.3.28", + "futures-task 0.3.28", + "pin-project-lite", + "pin-utils", +] + +[[package]] +name = "generic-array" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd" +dependencies = [ + "typenum 1.17.0", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum 1.17.0", + "version_check", + "zeroize", +] + +[[package]] +name = "getrandom" +version = "0.1.14" +source = "git+https://github.com/mesalock-linux/getrandom-sgx#0aa9cc20c7dea713ccaac2c44430d625a395ebae" +dependencies = [ + "cfg-if 0.1.10", + "sgx_libc", + "sgx_trts", + "sgx_tstd", +] + +[[package]] +name = "getrandom" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" +dependencies = [ + "cfg-if 1.0.0", + "libc", + "wasi", +] + +[[package]] +name = "group" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" +dependencies = [ + "ff", + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "hash-db" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d23bd4e7b5eda0d0f3a307e8b381fdc8ba9000f26fbe912250c0a4cc3956364a" + +[[package]] +name = "hash-db" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e7d7786361d7425ae2fe4f9e407eb0efaa0840f5212d109cc018c40c35c6ab4" + +[[package]] +name = "hash256-std-hasher" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92c171d55b98633f4ed3860808f004099b36c1cc29c42cfc53aa8591b21efcf2" +dependencies = [ + "crunchy", +] + +[[package]] +name = "hashbrown" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29fba9abe4742d586dfd0c06ae4f7e73a1c2d86b856933509b269d82cdf06e18" + +[[package]] +name = "hashbrown" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04" + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +dependencies = [ + "ahash 0.7.6", +] + +[[package]] +name = "hashbrown" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" +dependencies = [ + "ahash 0.8.3", +] + +[[package]] +name = "hashbrown" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" + +[[package]] +name = "hashbrown_tstd" +version = "0.12.0" +source = "git+https://github.com/apache/incubator-teaclave-sgx-sdk?branch=master#3c903bdac4e503dd27b9b1f761c4abfc55f2464c" + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hex-conservative" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30ed443af458ccb6d81c1e7e661545f94d3176752fb1df2f543b902a1e0f51e2" +dependencies = [ + "core2", +] + +[[package]] +name = "hex-literal" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46" + +[[package]] +name = "hex_lit" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3011d1213f159867b13cfd6ac92d2cd5f1345762c63be3554e84092d85a50bbd" + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest 0.10.7", +] + +[[package]] +name = "http" +version = "0.2.1" +source = "git+https://github.com/integritee-network/http-sgx.git?branch=sgx-experimental#307b5421fb7a489a114bede0dc05c8d32b804f49" +dependencies = [ + "bytes 1.0.1", + "fnv 1.0.6", + "itoa 0.4.5", + "sgx_tstd", +] + +[[package]] +name = "http_req" +version = "0.8.1" +source = "git+https://github.com/integritee-network/http_req#3723e88235f2b29bc1a31835853b072ffd0455fd" +dependencies = [ + "log", + "rustls 0.19.0 (git+https://github.com/mesalock-linux/rustls?branch=mesalock_sgx)", + "sgx_tstd", + "unicase", + "webpki", + "webpki-roots 0.21.0 (git+https://github.com/mesalock-linux/webpki-roots?branch=mesalock_sgx)", +] + +[[package]] +name = "httparse" +version = "1.4.1" +source = "git+https://github.com/integritee-network/httparse-sgx?branch=sgx-experimental#cc97e4b34d2c44a1e3df5bdebef446b9771f5cc3" +dependencies = [ + "sgx_tstd", +] + +[[package]] +name = "humantime" +version = "1.3.0" +source = "git+https://github.com/mesalock-linux/humantime-sgx#c5243dfa36002c01adbc9aade288ead1b2c411cc" +dependencies = [ + "quick-error", + "sgx_tstd", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "idna" +version = "0.2.0" +source = "git+https://github.com/mesalock-linux/rust-url-sgx?tag=sgx_1.1.3#23832f3191456c2d4a0faab10952e1747be58ca8" +dependencies = [ + "matches", + "sgx_tstd", + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "impl-codec" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba6a270039626615617f3f36d15fc827041df3b78c439da2cadfa47455a77f2f" +dependencies = [ + "parity-scale-codec", +] + +[[package]] +name = "impl-rlp" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f28220f89297a075ddc7245cd538076ee98b01f2a9c23a53a4f1105d5a322808" +dependencies = [ + "rlp", +] + +[[package]] +name = "impl-serde" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc88fc67028ae3db0c853baa36269d398d5f45b6982f95549ff5def78c935cd" +dependencies = [ + "serde 1.0.193", +] + +[[package]] +name = "impl-trait-for-tuples" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb" +dependencies = [ + "proc-macro2", + "quote 1.0.33", + "syn 1.0.109", +] + +[[package]] +name = "indexmap" +version = "1.6.1" +source = "git+https://github.com/mesalock-linux/indexmap-sgx#19f52458ba64dd7349a5d3a62227619a17e4db85" +dependencies = [ + "autocfg 1.1.0", + "hashbrown 0.9.1", + "sgx_tstd", +] + +[[package]] +name = "indexmap" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d" +dependencies = [ + "equivalent", + "hashbrown 0.14.0", +] + +[[package]] +name = "integer-sqrt" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "276ec31bcb4a9ee45f58bec6f9ec700ae4cf4f4f8f2fa7e06cb406bd5ffdd770" +dependencies = [ + "num-traits 0.2.16", +] + +[[package]] +name = "iovec" +version = "0.1.4" +source = "git+https://github.com/mesalock-linux/iovec-sgx#5c2f8e81925b4c06c556d856f3237461b00e27c9" +dependencies = [ + "sgx_libc", +] + +[[package]] +name = "ipfs-unixfs" +version = "0.0.1" +source = "git+https://github.com/whalelephant/rust-ipfs?branch=w-nstd#52f84dceea7065bb4ee2c24da53b3bedf162241a" +dependencies = [ + "cid", + "either", + "multihash", + "quick-protobuf", + "sha2 0.9.9", +] + +[[package]] +name = "ita-oracle" +version = "0.9.0" +dependencies = [ + "itc-rest-client", + "itp-enclave-metrics", + "itp-ocall-api", + "lazy_static", + "log", + "parity-scale-codec", + "serde 1.0.193", + "sgx_tstd", + "substrate-fixed", + "thiserror", + "url", +] + +[[package]] +name = "ita-parentchain-interface" +version = "0.9.0" +dependencies = [ + "bs58", + "ita-sgx-runtime", + "ita-stf", + "itc-parentchain-indirect-calls-executor", + "itp-api-client-types", + "itp-node-api", + "itp-stf-primitives", + "itp-types", + "itp-utils", + "lc-scheduled-enclave", + "litentry-primitives", + "log", + "parity-scale-codec", + "sgx_tstd", + "sp-core", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "ita-sgx-runtime" +version = "0.9.0" +dependencies = [ + "frame-executive", + "frame-support", + "frame-system", + "itp-sgx-runtime-primitives", + "pallet-balances", + "pallet-evm 6.0.0-dev (git+https://github.com/integritee-network/frontier.git?branch=bar/polkadot-v0.9.42)", + "pallet-parentchain", + "pallet-sudo", + "pallet-timestamp", + "pallet-transaction-payment", + "parity-scale-codec", + "scale-info", + "sp-api", + "sp-core", + "sp-runtime", + "sp-std", + "sp-version", +] + +[[package]] +name = "ita-stf" +version = "0.9.0" +dependencies = [ + "frame-support", + "frame-system", + "hex", + "hex-literal", + "ita-sgx-runtime", + "itp-hashing", + "itp-node-api", + "itp-node-api-metadata", + "itp-node-api-metadata-provider", + "itp-sgx-externalities", + "itp-stf-interface", + "itp-stf-primitives", + "itp-storage", + "itp-types", + "itp-utils", + "litentry-primitives", + "log", + "pallet-balances", + "pallet-parentchain", + "pallet-sudo", + "parity-scale-codec", + "rlp", + "sgx_tstd", + "sha3 0.10.8", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "itc-direct-rpc-client" +version = "0.1.0" +dependencies = [ + "itp-rpc", + "itp-types", + "itp-utils", + "litentry-primitives", + "log", + "parity-scale-codec", + "rustls 0.19.0 (git+https://github.com/mesalock-linux/rustls?tag=sgx_1.1.3)", + "serde_json 1.0.107", + "sgx_tstd", + "tungstenite", + "url", + "webpki", +] + +[[package]] +name = "itc-direct-rpc-server" +version = "0.9.0" +dependencies = [ + "itc-tls-websocket-server", + "itp-rpc", + "itp-types", + "itp-utils", + "jsonrpc-core", + "log", + "parity-scale-codec", + "serde_json 1.0.107", + "sgx_tstd", + "sp-runtime", + "thiserror", +] + +[[package]] +name = "itc-offchain-worker-executor" +version = "0.9.0" +dependencies = [ + "itc-parentchain-light-client", + "itp-extrinsics-factory", + "itp-stf-executor", + "itp-stf-interface", + "itp-stf-primitives", + "itp-stf-state-handler", + "itp-top-pool-author", + "itp-types", + "log", + "parity-scale-codec", + "sgx_tstd", + "sp-runtime", + "thiserror", +] + +[[package]] +name = "itc-parentchain" +version = "0.9.0" +dependencies = [ + "itc-parentchain-block-import-dispatcher", + "itc-parentchain-block-importer", + "itc-parentchain-indirect-calls-executor", + "itc-parentchain-light-client", + "itp-types", + "parity-scale-codec", + "sp-runtime", +] + +[[package]] +name = "itc-parentchain-block-import-dispatcher" +version = "0.9.0" +dependencies = [ + "itc-parentchain-block-importer", + "itp-import-queue", + "log", + "sgx_tstd", + "sgx_types", + "thiserror", +] + +[[package]] +name = "itc-parentchain-block-importer" +version = "0.9.0" +dependencies = [ + "ita-stf", + "itc-parentchain-indirect-calls-executor", + "itc-parentchain-light-client", + "itp-enclave-metrics", + "itp-extrinsics-factory", + "itp-ocall-api", + "itp-stf-executor", + "itp-types", + "log", + "parity-scale-codec", + "sgx_tstd", + "sgx_types", + "sp-runtime", + "thiserror", +] + +[[package]] +name = "itc-parentchain-indirect-calls-executor" +version = "0.9.0" +dependencies = [ + "binary-merkle-tree", + "bs58", + "core-primitives", + "futures 0.3.8", + "itp-api-client-types", + "itp-node-api", + "itp-sgx-crypto", + "itp-sgx-runtime-primitives", + "itp-stf-executor", + "itp-stf-primitives", + "itp-test", + "itp-top-pool-author", + "itp-types", + "itp-utils", + "lc-scheduled-enclave", + "litentry-primitives", + "log", + "parity-scale-codec", + "sgx_tstd", + "sgx_types", + "sp-core", + "sp-runtime", + "sp-std", + "thiserror", +] + +[[package]] +name = "itc-parentchain-light-client" +version = "0.9.0" +dependencies = [ + "finality-grandpa", + "itc-parentchain-test", + "itp-ocall-api", + "itp-sgx-io", + "itp-sgx-temp-dir", + "itp-storage", + "itp-test", + "itp-types", + "log", + "parity-scale-codec", + "sgx_tstd", + "sgx_types", + "sp-consensus-grandpa", + "sp-runtime", + "thiserror", +] + +[[package]] +name = "itc-parentchain-test" +version = "0.9.0" +dependencies = [ + "itp-types", + "sp-runtime", +] + +[[package]] +name = "itc-peer-top-broadcaster" +version = "0.1.0" +dependencies = [ + "itc-direct-rpc-client", + "itc-direct-rpc-server", + "itp-rpc", + "itp-stf-primitives", + "itp-types", + "itp-utils", + "litentry-primitives", + "log", + "sgx_tstd", +] + +[[package]] +name = "itc-rest-client" +version = "0.9.0" +dependencies = [ + "base64 0.13.1", + "http", + "http_req", + "log", + "serde 1.0.193", + "serde_json 1.0.107", + "sgx_tstd", + "thiserror", + "url", +] + +[[package]] +name = "itc-tls-websocket-server" +version = "0.9.0" +dependencies = [ + "bit-vec", + "chrono 0.4.31", + "log", + "mio", + "mio-extras", + "rcgen", + "rustls 0.19.0 (git+https://github.com/mesalock-linux/rustls?branch=mesalock_sgx)", + "sgx_tstd", + "sp-core", + "thiserror", + "tungstenite", + "webpki", + "yasna", +] + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "0.4.5" +source = "git+https://github.com/mesalock-linux/itoa-sgx#295ee451f5ec74f25c299552b481beb445ea3eb7" +dependencies = [ + "sgx_tstd", +] + +[[package]] +name = "itoa" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" + +[[package]] +name = "itp-api-client-types" +version = "0.9.0" +dependencies = [ + "itp-types", + "sp-runtime", + "substrate-api-client", +] + +[[package]] +name = "itp-attestation-handler" +version = "0.8.0" +dependencies = [ + "arrayvec 0.7.4", + "base64 0.13.0 (git+https://github.com/mesalock-linux/rust-base64-sgx?rev=sgx_1.1.3)", + "bit-vec", + "chrono 0.4.11", + "hex", + "httparse", + "itertools 0.10.5", + "itp-ocall-api", + "itp-settings", + "itp-sgx-crypto", + "itp-sgx-io", + "itp-time-utils", + "log", + "num-bigint", + "parity-scale-codec", + "rustls 0.19.0 (git+https://github.com/mesalock-linux/rustls?rev=sgx_1.1.3)", + "serde_json 1.0.60 (git+https://github.com/mesalock-linux/serde-json-sgx?tag=sgx_1.1.3)", + "sgx_rand", + "sgx_tcrypto", + "sgx_tse", + "sgx_tstd", + "sgx_types", + "sp-core", + "thiserror", + "webpki", + "webpki-roots 0.21.0 (git+https://github.com/mesalock-linux/webpki-roots?branch=mesalock_sgx)", + "yasna", +] + +[[package]] +name = "itp-component-container" +version = "0.8.0" +dependencies = [ + "sgx_tstd", + "thiserror", +] + +[[package]] +name = "itp-enclave-metrics" +version = "0.9.0" +dependencies = [ + "parity-scale-codec", + "sgx_tstd", + "substrate-fixed", +] + +[[package]] +name = "itp-extrinsics-factory" +version = "0.9.0" +dependencies = [ + "itp-node-api", + "itp-nonce-cache", + "itp-types", + "log", + "parity-scale-codec", + "sgx_tstd", + "sgx_types", + "sp-core", + "sp-runtime", + "substrate-api-client", + "thiserror", +] + +[[package]] +name = "itp-hashing" +version = "0.9.0" +dependencies = [ + "sp-core", +] + +[[package]] +name = "itp-import-queue" +version = "0.8.0" +dependencies = [ + "sgx_tstd", + "sgx_types", + "thiserror", +] + +[[package]] +name = "itp-node-api" +version = "0.9.0" +dependencies = [ + "itp-api-client-types", + "itp-node-api-metadata", + "itp-node-api-metadata-provider", +] + +[[package]] +name = "itp-node-api-metadata" +version = "0.9.0" +dependencies = [ + "derive_more", + "itp-api-client-types", + "itp-stf-primitives", + "parity-scale-codec", + "sp-core", +] + +[[package]] +name = "itp-node-api-metadata-provider" +version = "0.9.0" +dependencies = [ + "itp-node-api-metadata", + "itp-stf-primitives", + "sgx_tstd", + "thiserror", +] + +[[package]] +name = "itp-nonce-cache" +version = "0.8.0" +dependencies = [ + "sgx_tstd", + "thiserror", +] + +[[package]] +name = "itp-ocall-api" +version = "0.9.0" +dependencies = [ + "derive_more", + "itp-storage", + "itp-types", + "parity-scale-codec", + "sgx_types", + "sp-core", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "itp-primitives-cache" +version = "0.9.0" +dependencies = [ + "lazy_static", + "sgx_tstd", + "thiserror", +] + +[[package]] +name = "itp-rpc" +version = "0.9.0" +dependencies = [ + "itp-types", + "parity-scale-codec", + "serde 1.0.193", + "serde_json 1.0.107", + "sgx_tstd", +] + +[[package]] +name = "itp-settings" +version = "0.9.0" + +[[package]] +name = "itp-sgx-crypto" +version = "0.9.0" +dependencies = [ + "aes", + "derive_more", + "itp-sgx-io", + "itp-sgx-temp-dir", + "log", + "ofb", + "parity-scale-codec", + "serde_json 1.0.60 (git+https://github.com/mesalock-linux/serde-json-sgx?tag=sgx_1.1.3)", + "sgx_crypto_helper", + "sgx_rand", + "sgx_tstd", + "sgx_types", + "sp-core", +] + +[[package]] +name = "itp-sgx-externalities" +version = "0.9.0" +dependencies = [ + "derive_more", + "environmental 1.1.3", + "itp-hashing", + "log", + "parity-scale-codec", + "postcard", + "serde 1.0.193", + "sgx_tstd", + "sp-core", +] + +[[package]] +name = "itp-sgx-io" +version = "0.8.0" +dependencies = [ + "sgx_tstd", +] + +[[package]] +name = "itp-sgx-runtime-primitives" +version = "0.9.0" +dependencies = [ + "frame-system", + "litentry-primitives", + "pallet-balances", + "sp-core", + "sp-runtime", +] + +[[package]] +name = "itp-sgx-temp-dir" +version = "0.1.0" +dependencies = [ + "lazy_static", + "sgx_tstd", +] + +[[package]] +name = "itp-stf-executor" +version = "0.9.0" +dependencies = [ + "hex", + "itc-parentchain-test", + "itp-enclave-metrics", + "itp-node-api", + "itp-ocall-api", + "itp-sgx-crypto", + "itp-sgx-externalities", + "itp-stf-interface", + "itp-stf-primitives", + "itp-stf-state-handler", + "itp-stf-state-observer", + "itp-test", + "itp-time-utils", + "itp-top-pool-author", + "itp-types", + "litentry-primitives", + "log", + "parity-scale-codec", + "sgx_tstd", + "sgx_types", + "sp-core", + "sp-runtime", + "thiserror", +] + +[[package]] +name = "itp-stf-interface" +version = "0.8.0" +dependencies = [ + "itp-node-api-metadata", + "itp-node-api-metadata-provider", + "itp-stf-primitives", + "itp-types", + "parity-scale-codec", +] + +[[package]] +name = "itp-stf-primitives" +version = "0.9.0" +dependencies = [ + "derive_more", + "itp-sgx-runtime-primitives", + "litentry-primitives", + "parity-scale-codec", + "sp-core", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "itp-stf-state-handler" +version = "0.9.0" +dependencies = [ + "itp-hashing", + "itp-settings", + "itp-sgx-crypto", + "itp-sgx-externalities", + "itp-sgx-io", + "itp-sgx-temp-dir", + "itp-stf-interface", + "itp-stf-state-observer", + "itp-time-utils", + "itp-types", + "log", + "parity-scale-codec", + "rust-base58", + "sgx_tstd", + "sgx_types", + "sp-core", + "thiserror", +] + +[[package]] +name = "itp-stf-state-observer" +version = "0.9.0" +dependencies = [ + "itp-types", + "log", + "sgx_tstd", + "thiserror", +] + +[[package]] +name = "itp-storage" +version = "0.9.0" +dependencies = [ + "derive_more", + "frame-metadata", + "frame-support", + "hash-db 0.15.2", + "itp-types", + "parity-scale-codec", + "sgx_tstd", + "sp-core", + "sp-runtime", + "sp-std", + "sp-trie", + "thiserror", +] + +[[package]] +name = "itp-teerex-storage" +version = "0.9.0" +dependencies = [ + "itp-storage", + "sp-std", +] + +[[package]] +name = "itp-test" +version = "0.9.0" +dependencies = [ + "hex", + "itp-node-api", + "itp-node-api-metadata-provider", + "itp-ocall-api", + "itp-sgx-crypto", + "itp-sgx-externalities", + "itp-stf-interface", + "itp-stf-primitives", + "itp-stf-state-handler", + "itp-storage", + "itp-teerex-storage", + "itp-time-utils", + "itp-types", + "jsonrpc-core", + "litentry-primitives", + "log", + "parity-scale-codec", + "sgx_crypto_helper", + "sgx_tstd", + "sgx_types", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "itp-time-utils" +version = "0.9.0" +dependencies = [ + "chrono 0.4.11", + "sgx_tstd", +] + +[[package]] +name = "itp-top-pool" +version = "0.9.0" +dependencies = [ + "byteorder 1.4.3", + "derive_more", + "itc-direct-rpc-server", + "itp-stf-primitives", + "itp-types", + "its-primitives", + "jsonrpc-core", + "linked-hash-map", + "log", + "parity-scale-codec", + "sgx_tstd", + "sp-core", + "sp-runtime", +] + +[[package]] +name = "itp-top-pool-author" +version = "0.9.0" +dependencies = [ + "derive_more", + "itp-enclave-metrics", + "itp-ocall-api", + "itp-sgx-crypto", + "itp-stf-primitives", + "itp-stf-state-handler", + "itp-test", + "itp-top-pool", + "itp-types", + "itp-utils", + "jsonrpc-core", + "lazy_static", + "litentry-primitives", + "log", + "parity-scale-codec", + "sgx_tstd", + "sp-core", + "sp-runtime", +] + +[[package]] +name = "itp-types" +version = "0.9.0" +dependencies = [ + "frame-system", + "itp-sgx-crypto", + "itp-sgx-runtime-primitives", + "itp-stf-primitives", + "itp-utils", + "litentry-primitives", + "pallet-balances", + "parity-scale-codec", + "sp-core", + "sp-runtime", + "sp-std", + "substrate-api-client", +] + +[[package]] +name = "itp-utils" +version = "0.9.0" +dependencies = [ + "hex", + "parity-scale-codec", +] + +[[package]] +name = "its-block-composer" +version = "0.9.0" +dependencies = [ + "itp-node-api", + "itp-settings", + "itp-sgx-crypto", + "itp-sgx-externalities", + "itp-stf-executor", + "itp-stf-primitives", + "itp-time-utils", + "itp-top-pool-author", + "itp-types", + "its-primitives", + "its-state", + "log", + "parity-scale-codec", + "sgx_tstd", + "sgx_types", + "sp-core", + "sp-runtime", + "thiserror", +] + +[[package]] +name = "its-block-verification" +version = "0.9.0" +dependencies = [ + "frame-support", + "itp-types", + "itp-utils", + "its-primitives", + "log", + "sgx_tstd", + "sp-consensus-slots", + "sp-core", + "sp-runtime", + "thiserror", +] + +[[package]] +name = "its-consensus-aura" +version = "0.9.0" +dependencies = [ + "finality-grandpa", + "ita-stf", + "itc-parentchain-block-import-dispatcher", + "itc-peer-top-broadcaster", + "itp-enclave-metrics", + "itp-ocall-api", + "itp-settings", + "itp-sgx-crypto", + "itp-sgx-externalities", + "itp-stf-executor", + "itp-stf-primitives", + "itp-stf-state-handler", + "itp-time-utils", + "itp-top-pool-author", + "itp-types", + "itp-utils", + "its-block-composer", + "its-block-verification", + "its-consensus-common", + "its-consensus-slots", + "its-primitives", + "its-state", + "its-validateer-fetch", + "lc-scheduled-enclave", + "log", + "parity-scale-codec", + "sgx_tstd", + "sp-core", + "sp-runtime", +] + +[[package]] +name = "its-consensus-common" +version = "0.9.0" +dependencies = [ + "itc-parentchain-light-client", + "itp-enclave-metrics", + "itp-extrinsics-factory", + "itp-import-queue", + "itp-node-api-metadata", + "itp-node-api-metadata-provider", + "itp-ocall-api", + "itp-settings", + "itp-sgx-crypto", + "itp-types", + "its-block-verification", + "its-primitives", + "its-state", + "log", + "parity-scale-codec", + "sgx_tstd", + "sgx_types", + "sp-runtime", + "thiserror", +] + +[[package]] +name = "its-consensus-slots" +version = "0.9.0" +dependencies = [ + "derive_more", + "hex", + "itp-settings", + "itp-sgx-externalities", + "itp-stf-state-handler", + "itp-time-utils", + "itp-types", + "its-block-verification", + "its-consensus-common", + "its-primitives", + "its-state", + "lazy_static", + "lc-scheduled-enclave", + "log", + "parity-scale-codec", + "sgx_tstd", + "sp-consensus-slots", + "sp-runtime", +] + +[[package]] +name = "its-primitives" +version = "0.1.0" +dependencies = [ + "itp-types", + "parity-scale-codec", + "scale-info", + "serde 1.0.193", + "sp-core", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "its-rpc-handler" +version = "0.9.0" +dependencies = [ + "futures 0.3.8", + "itp-rpc", + "itp-stf-primitives", + "itp-top-pool-author", + "itp-types", + "itp-utils", + "its-primitives", + "jsonrpc-core", + "litentry-primitives", + "log", + "parity-scale-codec", + "rust-base58", + "sgx_tstd", + "sp-core", +] + +[[package]] +name = "its-sidechain" +version = "0.9.0" +dependencies = [ + "its-block-composer", + "its-consensus-aura", + "its-consensus-common", + "its-consensus-slots", + "its-primitives", + "its-rpc-handler", + "its-state", + "its-validateer-fetch", +] + +[[package]] +name = "its-state" +version = "0.9.0" +dependencies = [ + "frame-support", + "itp-sgx-externalities", + "itp-storage", + "its-primitives", + "log", + "parity-scale-codec", + "sgx_tstd", + "sp-core", + "sp-io", + "sp-runtime", + "thiserror", +] + +[[package]] +name = "its-validateer-fetch" +version = "0.9.0" +dependencies = [ + "derive_more", + "frame-support", + "itp-ocall-api", + "itp-teerex-storage", + "itp-types", + "parity-scale-codec", + "sp-core", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "js-sys" +version = "0.3.65" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54c0c35952f67de54bb584e9fd912b3023117cbafc0a77d8f3dee1fb5f572fe8" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "jsonrpc-core" +version = "18.0.0" +source = "git+https://github.com/scs/jsonrpc?branch=no_std_v18#0faf53c491c3222b96242a973d902dd06e9b6674" +dependencies = [ + "futures 0.3.8", + "log", + "serde 1.0.118", + "serde_derive 1.0.118", + "serde_json 1.0.60 (git+https://github.com/mesalock-linux/serde-json-sgx)", +] + +[[package]] +name = "k256" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cadb76004ed8e97623117f3df85b17aaa6626ab0b0831e6573f104df16cd1bcc" +dependencies = [ + "cfg-if 1.0.0", + "ecdsa", + "elliptic-curve", + "sha2 0.10.7", +] + +[[package]] +name = "keccak" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f6d5ed8676d904364de097082f4e7d240b571b67989ced0240f08b7f966f940" +dependencies = [ + "cpufeatures", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +dependencies = [ + "spin", +] + +[[package]] +name = "lazycell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + +[[package]] +name = "lc-scheduled-enclave" +version = "0.8.0" +dependencies = [ + "itp-settings", + "itp-sgx-io", + "itp-types", + "lazy_static", + "log", + "parity-scale-codec", + "sgx_tstd", + "sp-std", + "thiserror", +] + +[[package]] +name = "libc" +version = "0.2.152" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7" + +[[package]] +name = "libsecp256k1" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95b09eff1b35ed3b33b877ced3a691fc7a481919c7e29c53c906226fcf55e2a1" +dependencies = [ + "arrayref", + "base64 0.13.1", + "digest 0.9.0", + "libsecp256k1-core", + "libsecp256k1-gen-ecmult", + "libsecp256k1-gen-genmult", + "rand 0.8.5", + "serde 1.0.193", +] + +[[package]] +name = "libsecp256k1-core" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5be9b9bb642d8522a44d533eab56c16c738301965504753b03ad1de3425d5451" +dependencies = [ + "crunchy", + "digest 0.9.0", + "subtle", +] + +[[package]] +name = "libsecp256k1-gen-ecmult" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3038c808c55c87e8a172643a7d87187fc6c4174468159cb3090659d55bcb4809" +dependencies = [ + "libsecp256k1-core", +] + +[[package]] +name = "libsecp256k1-gen-genmult" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3db8d6ba2cec9eacc40e6e8ccc98931840301f1006e95647ceb2dd5c3aa06f7c" +dependencies = [ + "libsecp256k1-core", +] + +[[package]] +name = "linked-hash-map" +version = "0.5.2" +source = "git+https://github.com/mesalock-linux/linked-hash-map-sgx#03e763f7c251c16e0b85e2fb058ba47be52f2a49" +dependencies = [ + "sgx_tstd", +] + +[[package]] +name = "litentry-hex-utils" +version = "0.9.12" +dependencies = [ + "hex", +] + +[[package]] +name = "litentry-macros" +version = "0.1.0" +dependencies = [ + "cargo_toml", + "quote 1.0.33", +] + +[[package]] +name = "litentry-macros" +version = "0.9.12" + +[[package]] +name = "litentry-primitives" +version = "0.1.0" +dependencies = [ + "bitcoin", + "core-primitives", + "hex", + "itp-sgx-crypto", + "itp-utils", + "log", + "pallet-evm 6.0.0-dev (git+https://github.com/integritee-network/frontier.git?branch=bar/polkadot-v0.9.42)", + "parity-scale-codec", + "rand 0.7.3", + "ring 0.16.20", + "scale-info", + "secp256k1 0.28.0", + "serde 1.0.193", + "sgx_tstd", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", + "strum", + "strum_macros", + "teerex-primitives 0.1.0", +] + +[[package]] +name = "litentry-proc-macros" +version = "0.9.12" +dependencies = [ + "cargo_toml", + "proc-macro2", + "quote 1.0.33", + "syn 2.0.37", +] + +[[package]] +name = "log" +version = "0.4.17" +source = "git+https://github.com/integritee-network/log-sgx#483383a9be3e2e900042eef9b6b2d0837411783f" +dependencies = [ + "cfg-if 1.0.0", + "sgx_tstd", +] + +[[package]] +name = "matches" +version = "0.1.8" +source = "git+https://github.com/mesalock-linux/rust-std-candidates-sgx#5747bcf37f3e18687758838da0339ff0f2c83924" + +[[package]] +name = "maybe-async" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f1b8c13cb1f814b634a96b2c725449fe7ed464a7b8781de8688be5ffbd3f305" +dependencies = [ + "proc-macro2", + "quote 1.0.33", + "syn 1.0.109", +] + +[[package]] +name = "memchr" +version = "2.2.1" +source = "git+https://github.com/mesalock-linux/rust-memchr-sgx#fb51ee32766cb9a2be39b7fb2b5de26bb86dcdeb" +dependencies = [ + "sgx_libc", + "sgx_tstd", + "sgx_types", +] + +[[package]] +name = "memchr" +version = "2.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f232d6ef707e1956a43342693d2a31e72989554d58299d7a88738cc95b0d35c" + +[[package]] +name = "memory-db" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "808b50db46293432a45e63bc15ea51e0ab4c0a1647b8eb114e31a3e698dd6fbe" +dependencies = [ + "hash-db 0.16.0", +] + +[[package]] +name = "merlin" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e261cf0f8b3c42ded9f7d2bb59dea03aa52bc8a1cbc7482f9fc3fd1229d3b42" +dependencies = [ + "byteorder 1.4.3", + "keccak", + "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "zeroize", +] + +[[package]] +name = "mio" +version = "0.6.21" +source = "git+https://github.com/mesalock-linux/mio-sgx?tag=sgx_1.1.3#5b0e56a3066231c7a8d1876c7be3a19b08ffdfd5" +dependencies = [ + "iovec", + "log", + "net2", + "sgx_libc", + "sgx_trts", + "sgx_tstd", + "slab 0.4.2", +] + +[[package]] +name = "mio-extras" +version = "2.0.6" +source = "git+https://github.com/integritee-network/mio-extras-sgx?rev=963234b#963234bf55e44f9efff921938255126c48deef3a" +dependencies = [ + "lazycell", + "log", + "mio", + "sgx_tstd", + "sgx_types", + "slab 0.4.9", +] + +[[package]] +name = "multibase" +version = "0.8.0" +source = "git+https://github.com/whalelephant/rust-multibase?branch=nstd#df67fb30e86998f7c10d4eea16a1cd480d2448c0" +dependencies = [ + "base-x", + "data-encoding", + "lazy_static", +] + +[[package]] +name = "multihash" +version = "0.11.4" +source = "git+https://github.com/whalelephant/rust-multihash?branch=nstd#2c8aca8fa1fcbcba26951d925de40fa81696020a" +dependencies = [ + "blake2b_simd 0.5.11", + "blake2s_simd", + "digest 0.9.0", + "sha-1", + "sha2 0.9.9", + "sha3 0.9.1", + "unsigned-varint", +] + +[[package]] +name = "net2" +version = "0.2.33" +source = "git+https://github.com/mesalock-linux/net2-rs-sgx#554583d15f3c9dff5d862a6ae64e227bb38fa729" +dependencies = [ + "cfg-if 0.1.10", + "sgx_libc", + "sgx_tstd", +] + +[[package]] +name = "num" +version = "0.2.0" +source = "git+https://github.com/mesalock-linux/num-sgx#22645415542cc67551890dfdd34f4d5638b9ec78" +dependencies = [ + "num-bigint", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits 0.2.10", +] + +[[package]] +name = "num-bigint" +version = "0.2.5" +source = "git+https://github.com/mesalock-linux/num-bigint-sgx#76a5bed94dc31c32bd1670dbf72877abcf9bbc09" +dependencies = [ + "autocfg 1.1.0", + "num-integer", + "num-traits 0.2.10", + "sgx_tstd", +] + +[[package]] +name = "num-complex" +version = "0.2.3" +source = "git+https://github.com/mesalock-linux/num-complex-sgx#19700ad6de079ebc5560db472c282d1591e0d84f" +dependencies = [ + "autocfg 0.1.8", + "num-traits 0.2.10", + "sgx_tstd", +] + +[[package]] +name = "num-integer" +version = "0.1.41" +source = "git+https://github.com/mesalock-linux/num-integer-sgx#404c50e5378ca635261688b080dee328ff42b6bd" +dependencies = [ + "autocfg 0.1.8", + "num-traits 0.2.10", + "sgx_tstd", +] + +[[package]] +name = "num-iter" +version = "0.1.39" +source = "git+https://github.com/mesalock-linux/num-iter-sgx#f19fc44fcad0b82a040e5a24c511e5049cc04b60" +dependencies = [ + "num-integer", + "num-traits 0.2.10", + "sgx_tstd", +] + +[[package]] +name = "num-rational" +version = "0.2.2" +source = "git+https://github.com/mesalock-linux/num-rational-sgx#be65f9ce439f3c9ec850d8041635ab6c3309b816" +dependencies = [ + "autocfg 0.1.8", + "num-bigint", + "num-integer", + "num-traits 0.2.10", + "sgx_tstd", +] + +[[package]] +name = "num-traits" +version = "0.2.10" +source = "git+https://github.com/mesalock-linux/num-traits-sgx#af046e0b15c594c960007418097dd4ff37ec3f7a" +dependencies = [ + "autocfg 0.1.8", + "sgx_tstd", +] + +[[package]] +name = "num-traits" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2" +dependencies = [ + "autocfg 1.1.0", +] + +[[package]] +name = "ofb" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5e609fc8b72da3dabd56427be9489d8a9f4bd2e4dc41660dd033c3c8e90b93c" +dependencies = [ + "cipher", +] + +[[package]] +name = "once_cell" +version = "1.4.0" +source = "git+https://github.com/mesalock-linux/once_cell-sgx#cefcaa03fed4d85276b3235d875f1b45d399cc3c" +dependencies = [ + "sgx_tstd", +] + +[[package]] +name = "once_cell" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" + +[[package]] +name = "opaque-debug" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" + +[[package]] +name = "opaque-debug" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" + +[[package]] +name = "pallet-balances" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "frame-support", + "frame-system", + "log", + "parity-scale-codec", + "scale-info", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "pallet-evm" +version = "6.0.0-dev" +source = "git+https://github.com/integritee-network/frontier.git?branch=bar/polkadot-v0.9.42#a5a5e1e6ec08cd542a6084c310863150fb8841b1" +dependencies = [ + "evm 0.39.1 (registry+https://github.com/rust-lang/crates.io-index)", + "fp-account 1.0.0-dev (git+https://github.com/integritee-network/frontier.git?branch=bar/polkadot-v0.9.42)", + "fp-evm 3.0.0-dev (git+https://github.com/integritee-network/frontier.git?branch=bar/polkadot-v0.9.42)", + "frame-support", + "frame-system", + "hex", + "impl-trait-for-tuples", + "log", + "parity-scale-codec", + "rlp", + "scale-info", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "pallet-evm" +version = "6.0.0-dev" +source = "git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42#2499d18c936edbcb7fcb711827db7abb9b4f4da4" +dependencies = [ + "evm 0.39.1 (git+https://github.com/rust-blockchain/evm?rev=b7b82c7e1fc57b7449d6dfa6826600de37cc1e65)", + "fp-account 1.0.0-dev (git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42)", + "fp-evm 3.0.0-dev (git+https://github.com/paritytech/frontier?branch=polkadot-v0.9.42)", + "frame-support", + "frame-system", + "hex", + "hex-literal", + "impl-trait-for-tuples", + "log", + "parity-scale-codec", + "rlp", + "scale-info", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "pallet-parentchain" +version = "0.9.0" +dependencies = [ + "frame-support", + "frame-system", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-io", + "sp-runtime", +] + +[[package]] +name = "pallet-sudo" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "frame-support", + "frame-system", + "parity-scale-codec", + "scale-info", + "sp-io", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "pallet-timestamp" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "frame-support", + "frame-system", + "log", + "parity-scale-codec", + "scale-info", + "sp-inherents", + "sp-runtime", + "sp-std", + "sp-timestamp", +] + +[[package]] +name = "pallet-transaction-payment" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "frame-support", + "frame-system", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "parity-scale-codec" +version = "3.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dec8a8073036902368c2cdc0387e85ff9a37054d7e7c98e592145e0c92cd4fb" +dependencies = [ + "arrayvec 0.7.4", + "bitvec", + "byte-slice-cast", + "bytes 1.5.0", + "impl-trait-for-tuples", + "parity-scale-codec-derive", + "serde 1.0.193", +] + +[[package]] +name = "parity-scale-codec-derive" +version = "3.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "312270ee71e1cd70289dacf597cab7b207aa107d2f28191c2ae45b2ece18a260" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote 1.0.33", + "syn 1.0.109", +] + +[[package]] +name = "paste" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" + +[[package]] +name = "pem" +version = "0.8.2" +source = "git+https://github.com/mesalock-linux/pem-rs-sgx#fdfef4f24a9fb3fa72e8a71bb28bd8ff15feff2f" +dependencies = [ + "base64 0.13.0 (git+https://github.com/mesalock-linux/rust-base64-sgx)", + "once_cell 1.4.0", + "regex 1.3.1", + "sgx_tstd", +] + +[[package]] +name = "percent-encoding" +version = "2.1.0" +source = "git+https://github.com/mesalock-linux/rust-url-sgx?tag=sgx_1.1.3#23832f3191456c2d4a0faab10952e1747be58ca8" + +[[package]] +name = "pin-project-lite" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "postcard" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a25c0b0ae06fcffe600ad392aabfa535696c8973f2253d9ac83171924c58a858" +dependencies = [ + "postcard-cobs", + "serde 1.0.193", +] + +[[package]] +name = "postcard-cobs" +version = "0.1.5-pre" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c68cb38ed13fd7bc9dd5db8f165b7c8d9c1a315104083a2b10f11354c2af97f" + +[[package]] +name = "ppv-lite86" +version = "0.2.6" +source = "git+https://github.com/mesalock-linux/cryptocorrosion-sgx#32d7de50b5f03a10fe5a42167410be2dd3c2e389" + +[[package]] +name = "primitive-types" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f3486ccba82358b11a77516035647c34ba167dfa53312630de83b12bd4f3d66" +dependencies = [ + "fixed-hash", + "impl-codec", + "impl-rlp", + "impl-serde", + "scale-info", + "uint", +] + +[[package]] +name = "proc-macro-crate" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" +dependencies = [ + "once_cell 1.18.0", + "toml_edit 0.19.15", +] + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote 1.0.33", + "syn 1.0.109", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote 1.0.33", + "version_check", +] + +[[package]] +name = "proc-macro-hack" +version = "0.5.20+deprecated" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" + +[[package]] +name = "proc-macro-nested" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc881b2c22681370c6a780e47af9840ef841837bc98118431d4e1868bd0c1086" + +[[package]] +name = "proc-macro-warning" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e99670bafb56b9a106419397343bdbc8b8742c3cc449fec6345f86173f47cd4" +dependencies = [ + "proc-macro2", + "quote 1.0.33", + "syn 2.0.37", +] + +[[package]] +name = "proc-macro2" +version = "1.0.67" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quick-error" +version = "1.2.2" +source = "git+https://github.com/mesalock-linux/quick-error-sgx#468bf2cce746f34dd3df8c1c5b4a5a6494914d36" + +[[package]] +name = "quick-protobuf" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e489d4a83c17ea69b0291630229b5d4c92a94a3bf0165f7f72f506e94cda8b4b" +dependencies = [ + "byteorder 1.4.3", +] + +[[package]] +name = "quote" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" + +[[package]] +name = "quote" +version = "1.0.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + +[[package]] +name = "rand" +version = "0.7.3" +source = "git+https://github.com/mesalock-linux/rand-sgx?tag=sgx_1.1.3#83583f073de3b4f75c3c3ef5e174d484ed941f85" +dependencies = [ + "getrandom 0.1.14", + "rand_chacha", + "rand_core 0.5.1 (git+https://github.com/mesalock-linux/rand-sgx?tag=sgx_1.1.3)", + "sgx_tstd", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.2.2" +source = "git+https://github.com/mesalock-linux/rand-sgx?tag=sgx_1.1.3#83583f073de3b4f75c3c3ef5e174d484ed941f85" +dependencies = [ + "ppv-lite86", + "rand_core 0.5.1 (git+https://github.com/mesalock-linux/rand-sgx?tag=sgx_1.1.3)", + "sgx_tstd", +] + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "git+https://github.com/mesalock-linux/rand-sgx?tag=sgx_1.1.3#83583f073de3b4f75c3c3ef5e174d484ed941f85" +dependencies = [ + "getrandom 0.1.14", + "sgx_tstd", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" + +[[package]] +name = "rcgen" +version = "0.9.2" +source = "git+https://github.com/integritee-network/rcgen#1852c8dbeb74de36a422d218254b659497daf717" +dependencies = [ + "chrono 0.4.11", + "pem", + "ring 0.16.19", + "sgx_tstd", + "yasna", +] + +[[package]] +name = "ref-cast" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acde58d073e9c79da00f2b5b84eed919c8326832648a5b109b3fce1bb1175280" +dependencies = [ + "ref-cast-impl", +] + +[[package]] +name = "ref-cast-impl" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f7473c2cfcf90008193dd0e3e16599455cb601a9fce322b5bb55de799664925" +dependencies = [ + "proc-macro2", + "quote 1.0.33", + "syn 2.0.37", +] + +[[package]] +name = "regex" +version = "1.3.1" +source = "git+https://github.com/mesalock-linux/regex-sgx#76aef86f9836532d17764523d0fa23bb7d2e31cf" +dependencies = [ + "aho-corasick 0.7.10", + "memchr 2.2.1", + "regex-syntax 0.6.12", + "sgx_tstd", + "thread_local", +] + +[[package]] +name = "regex" +version = "1.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "697061221ea1b4a94a624f67d0ae2bfe4e22b8a17b6a192afb11046542cc8c47" +dependencies = [ + "aho-corasick 1.1.1", + "memchr 2.6.3", + "regex-automata", + "regex-syntax 0.7.5", +] + +[[package]] +name = "regex-automata" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2f401f4955220693b56f8ec66ee9c78abffd8d1c4f23dc41a23839eb88f0795" +dependencies = [ + "aho-corasick 1.1.1", + "memchr 2.6.3", + "regex-syntax 0.7.5", +] + +[[package]] +name = "regex-syntax" +version = "0.6.12" +source = "git+https://github.com/mesalock-linux/regex-sgx#76aef86f9836532d17764523d0fa23bb7d2e31cf" +dependencies = [ + "sgx_tstd", +] + +[[package]] +name = "regex-syntax" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" + +[[package]] +name = "rfc6979" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" +dependencies = [ + "hmac", + "subtle", +] + +[[package]] +name = "ring" +version = "0.16.19" +source = "git+https://github.com/mesalock-linux/ring-sgx?tag=v0.16.5#844efe271ed78a399d803b2579f5f2424d543c9f" +dependencies = [ + "cc", + "sgx_tstd", + "spin", + "untrusted", +] + +[[package]] +name = "ring" +version = "0.16.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" +dependencies = [ + "cc", + "libc", + "once_cell 1.18.0", + "spin", + "untrusted", + "web-sys", + "winapi", +] + +[[package]] +name = "rlp" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb919243f34364b6bd2fc10ef797edbfa75f33c252e7998527479c6d6b47e1ec" +dependencies = [ + "bytes 1.5.0", + "rlp-derive", + "rustc-hex", +] + +[[package]] +name = "rlp-derive" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e33d7b2abe0c340d8797fe2907d3f20d3b5ea5908683618bfe80df7f621f672a" +dependencies = [ + "proc-macro2", + "quote 1.0.33", + "syn 1.0.109", +] + +[[package]] +name = "rust-base58" +version = "0.0.4" +source = "git+https://github.com/mesalock-linux/rust-base58-sgx?rev=sgx_1.1.3#13fb3e0a543690e6e19332f37ba85fd74c56cb2f" +dependencies = [ + "num", + "sgx_tstd", +] + +[[package]] +name = "rustc-hex" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" + +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver", +] + +[[package]] +name = "rustls" +version = "0.19.0" +source = "git+https://github.com/mesalock-linux/rustls?tag=sgx_1.1.3#95b5e79dc24b02f3ce424437eb9698509d0baf58" +dependencies = [ + "base64 0.13.0 (git+https://github.com/mesalock-linux/rust-base64-sgx)", + "log", + "ring 0.16.19", + "sct", + "sgx_tstd", + "webpki", +] + +[[package]] +name = "rustls" +version = "0.19.0" +source = "git+https://github.com/mesalock-linux/rustls?branch=mesalock_sgx#95b5e79dc24b02f3ce424437eb9698509d0baf58" +dependencies = [ + "base64 0.13.0 (git+https://github.com/mesalock-linux/rust-base64-sgx)", + "log", + "ring 0.16.19", + "sct", + "sgx_tstd", + "webpki", +] + +[[package]] +name = "rustls" +version = "0.19.0" +source = "git+https://github.com/mesalock-linux/rustls?rev=sgx_1.1.3#95b5e79dc24b02f3ce424437eb9698509d0baf58" +dependencies = [ + "base64 0.13.0 (git+https://github.com/mesalock-linux/rust-base64-sgx)", + "log", + "ring 0.16.19", + "sct", + "sgx_tstd", + "webpki", +] + +[[package]] +name = "rustversion" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" + +[[package]] +name = "ryu" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" + +[[package]] +name = "scale-bits" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "036575c29af9b6e4866ffb7fa055dbf623fe7a9cc159b33786de6013a6969d89" +dependencies = [ + "parity-scale-codec", + "scale-info", + "serde 1.0.193", +] + +[[package]] +name = "scale-decode" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea509715113edab351e1f4d51fba6b186653259049a1155b52e2e994dd2f0e6d" +dependencies = [ + "parity-scale-codec", + "primitive-types", + "scale-bits", + "scale-decode-derive", + "scale-info", + "smallvec 1.11.1", +] + +[[package]] +name = "scale-decode-derive" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66c9d7a1341497e9d016722144310de3dc6c933909c0376017c88f65092fff37" +dependencies = [ + "darling", + "proc-macro-crate", + "proc-macro2", + "quote 1.0.33", + "syn 1.0.109", +] + +[[package]] +name = "scale-encode" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f6f51bc8cd927dab2f4567b1a8a8e9d7fd5d0866f2dbc7c84fc97cfa9383a26" +dependencies = [ + "parity-scale-codec", + "primitive-types", + "scale-bits", + "scale-encode-derive", + "scale-info", + "smallvec 1.11.1", +] + +[[package]] +name = "scale-encode-derive" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f28be1877787156a2df01be3c029b92bdffa6b6a9748d4996e383fff218c88f3" +dependencies = [ + "darling", + "proc-macro-crate", + "proc-macro2", + "quote 1.0.33", + "syn 1.0.109", +] + +[[package]] +name = "scale-info" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f7d66a1128282b7ef025a8ead62a4a9fcf017382ec53b8ffbf4d7bf77bd3c60" +dependencies = [ + "bitvec", + "cfg-if 1.0.0", + "derive_more", + "parity-scale-codec", + "scale-info-derive", + "serde 1.0.193", +] + +[[package]] +name = "scale-info-derive" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abf2c68b89cafb3b8d918dd07b42be0da66ff202cf1155c5739a4e0c1ea0dc19" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote 1.0.33", + "syn 1.0.109", +] + +[[package]] +name = "schnorrkel" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "021b403afe70d81eea68f6ea12f6b3c9588e5d536a94c3bf80f15e7faa267862" +dependencies = [ + "arrayref", + "arrayvec 0.5.2", + "curve25519-dalek 2.1.3", + "merlin", + "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.8.2", + "subtle", + "zeroize", +] + +[[package]] +name = "sct" +version = "0.6.0" +source = "git+https://github.com/mesalock-linux/sct.rs?branch=mesalock_sgx#c4d859cca232e6c9d88ca12048df3bc26e1ed4ad" +dependencies = [ + "ring 0.16.19", + "sgx_tstd", + "untrusted", +] + +[[package]] +name = "sec1" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" +dependencies = [ + "base16ct", + "der", + "generic-array 0.14.7", + "subtle", + "zeroize", +] + +[[package]] +name = "secp256k1" +version = "0.24.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b1629c9c557ef9b293568b338dddfc8208c98a18c59d722a9d53f859d9c9b62" +dependencies = [ + "secp256k1-sys 0.6.1", +] + +[[package]] +name = "secp256k1" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2acea373acb8c21ecb5a23741452acd2593ed44ee3d343e72baaa143bc89d0d5" +dependencies = [ + "bitcoin_hashes", + "secp256k1-sys 0.9.1", +] + +[[package]] +name = "secp256k1-sys" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83080e2c2fc1006e625be82e5d1eb6a43b7fd9578b617fcc55814daf286bba4b" +dependencies = [ + "cc", +] + +[[package]] +name = "secp256k1-sys" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dd97a086ec737e30053fd5c46f097465d25bb81dd3608825f65298c4c98be83" +dependencies = [ + "cc", +] + +[[package]] +name = "secrecy" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bd1c54ea06cfd2f6b63219704de0b9b4f72dcc2b8fdef820be6cd799780e91e" +dependencies = [ + "zeroize", +] + +[[package]] +name = "semver" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0293b4b29daaf487284529cc2f5675b8e57c61f70167ba415a463651fd6a918" + +[[package]] +name = "serde" +version = "1.0.118" +source = "git+https://github.com/mesalock-linux/serde-sgx#db0226f1d5d70fca6b96af2c285851502204e21c" +dependencies = [ + "serde_derive 1.0.118", + "sgx_tstd", +] + +[[package]] +name = "serde" +version = "1.0.193" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" +dependencies = [ + "serde_derive 1.0.193", +] + +[[package]] +name = "serde-big-array" +version = "0.3.0" +source = "git+https://github.com/mesalock-linux/serde-big-array-sgx#94122c5167aee38b39b09a620a60db2c28cf7428" +dependencies = [ + "serde 1.0.118", + "serde_derive 1.0.118", +] + +[[package]] +name = "serde_derive" +version = "1.0.118" +source = "git+https://github.com/mesalock-linux/serde-sgx#db0226f1d5d70fca6b96af2c285851502204e21c" +dependencies = [ + "proc-macro2", + "quote 1.0.33", + "syn 1.0.109", +] + +[[package]] +name = "serde_derive" +version = "1.0.193" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" +dependencies = [ + "proc-macro2", + "quote 1.0.33", + "syn 2.0.37", +] + +[[package]] +name = "serde_json" +version = "1.0.60" +source = "git+https://github.com/mesalock-linux/serde-json-sgx?tag=sgx_1.1.3#380893814ad2a057758d825bab798aa117f7362a" +dependencies = [ + "indexmap 1.6.1", + "itoa 0.4.5", + "ryu", + "serde 1.0.118", + "sgx_tstd", +] + +[[package]] +name = "serde_json" +version = "1.0.60" +source = "git+https://github.com/mesalock-linux/serde-json-sgx#380893814ad2a057758d825bab798aa117f7362a" +dependencies = [ + "itoa 0.4.5", + "ryu", + "serde 1.0.118", + "sgx_tstd", +] + +[[package]] +name = "serde_json" +version = "1.0.107" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65" +dependencies = [ + "itoa 1.0.9", + "ryu", + "serde 1.0.193", +] + +[[package]] +name = "serde_spanned" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96426c9936fd7a0124915f9185ea1d20aa9445cc9821142f0a73bc9207a2e186" +dependencies = [ + "serde 1.0.193", +] + +[[package]] +name = "sgx_alloc" +version = "1.1.6" +source = "git+https://github.com/apache/incubator-teaclave-sgx-sdk?branch=master#3c903bdac4e503dd27b9b1f761c4abfc55f2464c" + +[[package]] +name = "sgx_backtrace_sys" +version = "1.1.6" +source = "git+https://github.com/apache/incubator-teaclave-sgx-sdk?branch=master#3c903bdac4e503dd27b9b1f761c4abfc55f2464c" +dependencies = [ + "cc", + "sgx_build_helper", + "sgx_libc", +] + +[[package]] +name = "sgx_build_helper" +version = "1.1.6" +source = "git+https://github.com/apache/incubator-teaclave-sgx-sdk?branch=master#3c903bdac4e503dd27b9b1f761c4abfc55f2464c" + +[[package]] +name = "sgx_crypto_helper" +version = "1.1.6" +source = "git+https://github.com/apache/incubator-teaclave-sgx-sdk?branch=master#3c903bdac4e503dd27b9b1f761c4abfc55f2464c" +dependencies = [ + "itertools 0.11.0", + "serde 1.0.118", + "serde-big-array", + "serde_derive 1.0.118", + "sgx_tcrypto", + "sgx_tstd", + "sgx_types", +] + +[[package]] +name = "sgx_demangle" +version = "1.1.6" +source = "git+https://github.com/apache/incubator-teaclave-sgx-sdk?branch=master#3c903bdac4e503dd27b9b1f761c4abfc55f2464c" + +[[package]] +name = "sgx_libc" +version = "1.1.6" +source = "git+https://github.com/apache/incubator-teaclave-sgx-sdk?branch=master#3c903bdac4e503dd27b9b1f761c4abfc55f2464c" +dependencies = [ + "sgx_types", +] + +[[package]] +name = "sgx_rand" +version = "1.1.6" +source = "git+https://github.com/apache/incubator-teaclave-sgx-sdk?branch=master#3c903bdac4e503dd27b9b1f761c4abfc55f2464c" +dependencies = [ + "sgx_trts", + "sgx_tstd", + "sgx_types", +] + +[[package]] +name = "sgx_serialize" +version = "1.1.6" +source = "git+https://github.com/apache/incubator-teaclave-sgx-sdk?branch=master#3c903bdac4e503dd27b9b1f761c4abfc55f2464c" +dependencies = [ + "sgx_tstd", +] + +[[package]] +name = "sgx_serialize_derive" +version = "1.1.6" +source = "git+https://github.com/apache/incubator-teaclave-sgx-sdk?branch=master#3c903bdac4e503dd27b9b1f761c4abfc55f2464c" +dependencies = [ + "quote 0.3.15", + "sgx_serialize_derive_internals", + "syn 0.11.11", +] + +[[package]] +name = "sgx_serialize_derive_internals" +version = "1.1.6" +source = "git+https://github.com/apache/incubator-teaclave-sgx-sdk?branch=master#3c903bdac4e503dd27b9b1f761c4abfc55f2464c" +dependencies = [ + "syn 0.11.11", +] + +[[package]] +name = "sgx_tcrypto" +version = "1.1.6" +source = "git+https://github.com/apache/incubator-teaclave-sgx-sdk?branch=master#3c903bdac4e503dd27b9b1f761c4abfc55f2464c" +dependencies = [ + "sgx_types", +] + +[[package]] +name = "sgx_tcrypto_helper" +version = "1.1.6" +source = "git+https://github.com/apache/incubator-teaclave-sgx-sdk?branch=master#3c903bdac4e503dd27b9b1f761c4abfc55f2464c" +dependencies = [ + "sgx_crypto_helper", +] + +[[package]] +name = "sgx_tprotected_fs" +version = "1.1.6" +source = "git+https://github.com/apache/incubator-teaclave-sgx-sdk?branch=master#3c903bdac4e503dd27b9b1f761c4abfc55f2464c" +dependencies = [ + "sgx_trts", + "sgx_types", +] + +[[package]] +name = "sgx_trts" +version = "1.1.6" +source = "git+https://github.com/apache/incubator-teaclave-sgx-sdk?branch=master#3c903bdac4e503dd27b9b1f761c4abfc55f2464c" +dependencies = [ + "sgx_libc", + "sgx_types", +] + +[[package]] +name = "sgx_tse" +version = "1.1.6" +source = "git+https://github.com/apache/incubator-teaclave-sgx-sdk?branch=master#3c903bdac4e503dd27b9b1f761c4abfc55f2464c" +dependencies = [ + "sgx_types", +] + +[[package]] +name = "sgx_tseal" +version = "1.1.6" +source = "git+https://github.com/apache/incubator-teaclave-sgx-sdk?branch=master#3c903bdac4e503dd27b9b1f761c4abfc55f2464c" +dependencies = [ + "sgx_tcrypto", + "sgx_trts", + "sgx_tse", + "sgx_types", +] + +[[package]] +name = "sgx_tstd" +version = "1.1.6" +source = "git+https://github.com/apache/incubator-teaclave-sgx-sdk?branch=master#3c903bdac4e503dd27b9b1f761c4abfc55f2464c" +dependencies = [ + "hashbrown_tstd", + "sgx_alloc", + "sgx_backtrace_sys", + "sgx_demangle", + "sgx_libc", + "sgx_tprotected_fs", + "sgx_trts", + "sgx_types", + "sgx_unwind", +] + +[[package]] +name = "sgx_tunittest" +version = "1.1.6" +source = "git+https://github.com/apache/incubator-teaclave-sgx-sdk?branch=master#3c903bdac4e503dd27b9b1f761c4abfc55f2464c" +dependencies = [ + "sgx_tstd", +] + +[[package]] +name = "sgx_types" +version = "1.1.6" +source = "git+https://github.com/apache/incubator-teaclave-sgx-sdk?branch=master#3c903bdac4e503dd27b9b1f761c4abfc55f2464c" + +[[package]] +name = "sgx_unwind" +version = "1.1.6" +source = "git+https://github.com/apache/incubator-teaclave-sgx-sdk?branch=master#3c903bdac4e503dd27b9b1f761c4abfc55f2464c" +dependencies = [ + "sgx_build_helper", +] + +[[package]] +name = "sha-1" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99cd6713db3cf16b6c84e06321e049a9b9f699826e16096d23bbcc44d15d51a6" +dependencies = [ + "block-buffer 0.9.0", + "cfg-if 1.0.0", + "cpufeatures", + "digest 0.9.0", + "opaque-debug 0.3.0", +] + +[[package]] +name = "sha1" +version = "0.6.0" +source = "git+https://github.com/mesalock-linux/rust-sha1-sgx?tag=sgx_1.1.3#482a4d489e860d63a21662aaea988f600f8e20a4" +dependencies = [ + "sgx_tstd", +] + +[[package]] +name = "sha2" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a256f46ea78a0c0d9ff00077504903ac881a1dafdc20da66545699e7776b3e69" +dependencies = [ + "block-buffer 0.7.3", + "digest 0.8.1", + "fake-simd", + "opaque-debug 0.2.3", +] + +[[package]] +name = "sha2" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" +dependencies = [ + "block-buffer 0.9.0", + "cfg-if 1.0.0", + "cpufeatures", + "digest 0.9.0", + "opaque-debug 0.3.0", +] + +[[package]] +name = "sha2" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8" +dependencies = [ + "cfg-if 1.0.0", + "cpufeatures", + "digest 0.10.7", +] + +[[package]] +name = "sha3" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f81199417d4e5de3f04b1e871023acea7389672c4135918f05aa9cbf2f2fa809" +dependencies = [ + "block-buffer 0.9.0", + "digest 0.9.0", + "keccak", + "opaque-debug 0.3.0", +] + +[[package]] +name = "sha3" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" +dependencies = [ + "digest 0.10.7", + "keccak", +] + +[[package]] +name = "signature" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e1788eed21689f9cf370582dfc467ef36ed9c707f073528ddafa8d83e3b8500" +dependencies = [ + "digest 0.10.7", + "rand_core 0.6.4", +] + +[[package]] +name = "slab" +version = "0.4.2" +source = "git+https://github.com/mesalock-linux/slab-sgx#0b0e6ec2abd588afd2f40fd082bc473d100d0f40" +dependencies = [ + "sgx_tstd", +] + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg 1.1.0", +] + +[[package]] +name = "smallvec" +version = "1.6.1" +source = "git+https://github.com/mesalock-linux/rust-smallvec-sgx#b5925f10aa5bc3370a0fb339140ee063f5a888dd" +dependencies = [ + "sgx_tstd", +] + +[[package]] +name = "smallvec" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a" + +[[package]] +name = "sp-api" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "log", + "parity-scale-codec", + "scale-info", + "sp-api-proc-macro", + "sp-core", + "sp-metadata-ir", + "sp-runtime", + "sp-std", + "sp-version", +] + +[[package]] +name = "sp-api-proc-macro" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "Inflector", + "blake2", + "expander", + "proc-macro-crate", + "proc-macro2", + "quote 1.0.33", + "syn 2.0.37", +] + +[[package]] +name = "sp-application-crypto" +version = "7.0.0" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-io", + "sp-std", +] + +[[package]] +name = "sp-arithmetic" +version = "6.0.0" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "integer-sqrt", + "num-traits 0.2.16", + "parity-scale-codec", + "scale-info", + "sp-std", + "static_assertions", +] + +[[package]] +name = "sp-consensus-grandpa" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "finality-grandpa", + "log", + "parity-scale-codec", + "scale-info", + "sp-api", + "sp-application-crypto", + "sp-core", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "sp-consensus-slots" +version = "0.10.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "parity-scale-codec", + "scale-info", + "sp-std", + "sp-timestamp", +] + +[[package]] +name = "sp-core" +version = "7.0.0" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "array-bytes 4.2.0", + "bitflags", + "blake2", + "bounded-collections", + "ed25519-zebra", + "hash-db 0.16.0", + "hash256-std-hasher", + "libsecp256k1", + "log", + "merlin", + "parity-scale-codec", + "paste", + "primitive-types", + "scale-info", + "schnorrkel", + "secp256k1 0.24.3", + "secrecy", + "sp-core-hashing", + "sp-debug-derive", + "sp-runtime-interface", + "sp-std", + "sp-storage", + "ss58-registry", + "zeroize", +] + +[[package]] +name = "sp-core-hashing" +version = "5.0.0" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "blake2b_simd 1.0.2", + "byteorder 1.4.3", + "digest 0.10.7", + "sha2 0.10.7", + "sha3 0.10.8", + "sp-std", + "twox-hash", +] + +[[package]] +name = "sp-core-hashing-proc-macro" +version = "5.0.0" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "proc-macro2", + "quote 1.0.33", + "sp-core-hashing", + "syn 2.0.37", +] + +[[package]] +name = "sp-debug-derive" +version = "5.0.0" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "proc-macro2", + "quote 1.0.33", + "syn 2.0.37", +] + +[[package]] +name = "sp-externalities" +version = "0.13.0" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "environmental 1.1.4", + "parity-scale-codec", + "sp-std", + "sp-storage", +] + +[[package]] +name = "sp-inherents" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "impl-trait-for-tuples", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-std", +] + +[[package]] +name = "sp-io" +version = "7.0.0" +dependencies = [ + "itp-sgx-externalities", + "libsecp256k1", + "log", + "parity-scale-codec", + "sgx_tstd", + "sp-core", +] + +[[package]] +name = "sp-metadata-ir" +version = "0.1.0" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "frame-metadata", + "parity-scale-codec", + "scale-info", + "sp-std", +] + +[[package]] +name = "sp-runtime" +version = "7.0.0" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "either", + "hash256-std-hasher", + "impl-trait-for-tuples", + "log", + "parity-scale-codec", + "paste", + "scale-info", + "sp-application-crypto", + "sp-arithmetic", + "sp-core", + "sp-io", + "sp-std", + "sp-weights", +] + +[[package]] +name = "sp-runtime-interface" +version = "7.0.0" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "bytes 1.5.0", + "impl-trait-for-tuples", + "parity-scale-codec", + "primitive-types", + "sp-externalities", + "sp-runtime-interface-proc-macro", + "sp-std", + "sp-storage", + "sp-tracing", + "sp-wasm-interface", + "static_assertions", +] + +[[package]] +name = "sp-runtime-interface-proc-macro" +version = "6.0.0" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "Inflector", + "proc-macro-crate", + "proc-macro2", + "quote 1.0.33", + "syn 2.0.37", +] + +[[package]] +name = "sp-staking" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "sp-std" +version = "5.0.0" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" + +[[package]] +name = "sp-storage" +version = "7.0.0" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "parity-scale-codec", + "ref-cast", + "sp-debug-derive", + "sp-std", +] + +[[package]] +name = "sp-timestamp" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "parity-scale-codec", + "sp-inherents", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "sp-tracing" +version = "6.0.0" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "parity-scale-codec", + "sp-std", + "tracing", + "tracing-core", +] + +[[package]] +name = "sp-trie" +version = "7.0.0" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "hash-db 0.16.0", + "memory-db", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-std", + "trie-db", + "trie-root", +] + +[[package]] +name = "sp-version" +version = "5.0.0" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "parity-scale-codec", + "scale-info", + "sp-core-hashing-proc-macro", + "sp-runtime", + "sp-std", + "sp-version-proc-macro", +] + +[[package]] +name = "sp-version-proc-macro" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "parity-scale-codec", + "proc-macro2", + "quote 1.0.33", + "syn 2.0.37", +] + +[[package]] +name = "sp-wasm-interface" +version = "7.0.0" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "impl-trait-for-tuples", + "parity-scale-codec", + "sp-std", +] + +[[package]] +name = "sp-weights" +version = "4.0.0" +source = "git+https://github.com/paritytech/substrate.git?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "parity-scale-codec", + "scale-info", + "smallvec 1.11.1", + "sp-arithmetic", + "sp-core", + "sp-debug-derive", + "sp-std", +] + +[[package]] +name = "spin" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" + +[[package]] +name = "ss58-registry" +version = "1.43.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e6915280e2d0db8911e5032a5c275571af6bdded2916abd691a659be25d3439" +dependencies = [ + "Inflector", + "proc-macro2", + "quote 1.0.33", + "serde 1.0.193", + "serde_json 1.0.107", + "unicode-xid 0.2.4", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "strum" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125" + +[[package]] +name = "strum_macros" +version = "0.25.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23dc1fa9ac9c169a78ba62f0b841814b7abae11bdd047b9c58f893439e309ea0" +dependencies = [ + "heck", + "proc-macro2", + "quote 1.0.33", + "rustversion", + "syn 2.0.37", +] + +[[package]] +name = "substrate-api-client" +version = "0.14.0" +source = "git+https://github.com/scs/substrate-api-client.git?branch=polkadot-v0.9.42-tag-v0.14.0#e4ed74b0fb6c2fd5585f55c2702b97b56d99c7f6" +dependencies = [ + "ac-compose-macros", + "ac-node-api", + "ac-primitives", + "async-trait", + "derive_more", + "frame-metadata", + "hex", + "log", + "maybe-async", + "parity-scale-codec", + "serde 1.0.193", + "serde_json 1.0.107", + "sp-core", + "sp-runtime", + "sp-runtime-interface", +] + +[[package]] +name = "substrate-fixed" +version = "0.5.9" +source = "git+https://github.com/encointer/substrate-fixed?tag=v0.5.9#a4fb461aae6205ffc55bed51254a40c52be04e5d" +dependencies = [ + "parity-scale-codec", + "scale-info", + "typenum 1.16.0", +] + +[[package]] +name = "subtle" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" + +[[package]] +name = "syn" +version = "0.11.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" +dependencies = [ + "quote 0.3.15", + "synom", + "unicode-xid 0.0.4", +] + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote 1.0.33", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7303ef2c05cd654186cb250d29049a24840ca25d2747c25c0381c8d9e2f582e8" +dependencies = [ + "proc-macro2", + "quote 1.0.33", + "unicode-ident", +] + +[[package]] +name = "synom" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" +dependencies = [ + "unicode-xid 0.0.4", +] + +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + +[[package]] +name = "teerex-primitives" +version = "0.1.0" +dependencies = [ + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-std", +] + +[[package]] +name = "teerex-primitives" +version = "0.1.0" +source = "git+https://github.com/integritee-network/pallets.git?branch=sdk-v0.12.0-polkadot-v0.9.42#eaf611b79bc9d56b20c155150e99b549bf98436b" +dependencies = [ + "common-primitives", + "derive_more", + "log", + "parity-scale-codec", + "scale-info", + "serde 1.0.193", + "sp-core", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "termcolor" +version = "1.0.5" +source = "git+https://github.com/mesalock-linux/termcolor-sgx#fee5ac79b4a90197d646f3df5e1b45ac56be718b" +dependencies = [ + "sgx_tstd", +] + +[[package]] +name = "thiserror" +version = "1.0.9" +source = "git+https://github.com/mesalock-linux/thiserror-sgx?tag=sgx_1.1.3#c2f806b88616e06aab0af770366a76885d974fdc" +dependencies = [ + "sgx_tstd", + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.9" +source = "git+https://github.com/mesalock-linux/thiserror-sgx?tag=sgx_1.1.3#c2f806b88616e06aab0af770366a76885d974fdc" +dependencies = [ + "proc-macro2", + "quote 1.0.33", + "syn 1.0.109", +] + +[[package]] +name = "thread_local" +version = "1.0.0" +source = "git+https://github.com/mesalock-linux/thread_local-rs-sgx#a8e6e6ce280c53358f7b9e6febe534cba9950547" +dependencies = [ + "lazy_static", + "sgx_tstd", +] + +[[package]] +name = "tiny-keccak" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] + +[[package]] +name = "toml" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c226a7bba6d859b63c92c4b4fe69c5b6b72d0cb897dbc8e6012298e6154cb56e" +dependencies = [ + "serde 1.0.193", + "serde_spanned", + "toml_datetime", + "toml_edit 0.20.0", +] + +[[package]] +name = "toml_datetime" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" +dependencies = [ + "serde 1.0.193", +] + +[[package]] +name = "toml_edit" +version = "0.19.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" +dependencies = [ + "indexmap 2.0.0", + "toml_datetime", + "winnow", +] + +[[package]] +name = "toml_edit" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ff63e60a958cefbb518ae1fd6566af80d9d4be430a33f3723dfc47d1d411d95" +dependencies = [ + "indexmap 2.0.0", + "serde 1.0.193", + "serde_spanned", + "toml_datetime", + "winnow", +] + +[[package]] +name = "tracing" +version = "0.1.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" +dependencies = [ + "cfg-if 1.0.0", + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" + +[[package]] +name = "trie-db" +version = "0.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "767abe6ffed88a1889671a102c2861ae742726f52e0a5a425b92c9fbfa7e9c85" +dependencies = [ + "hash-db 0.16.0", + "hashbrown 0.13.2", + "log", + "smallvec 1.11.1", +] + +[[package]] +name = "trie-root" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4ed310ef5ab98f5fa467900ed906cb9232dd5376597e00fd4cba2a449d06c0b" +dependencies = [ + "hash-db 0.16.0", +] + +[[package]] +name = "triehash" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1631b201eb031b563d2e85ca18ec8092508e262a3196ce9bd10a67ec87b9f5c" +dependencies = [ + "hash-db 0.15.2", + "rlp", +] + +[[package]] +name = "tt-call" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4f195fd851901624eee5a58c4bb2b4f06399148fcd0ed336e6f1cb60a9881df" + +[[package]] +name = "tungstenite" +version = "0.14.0" +source = "git+https://github.com/integritee-network/tungstenite-rs-sgx?branch=sgx-experimental#c87a2c08ea00897bb8b127ca0a5c30c3671492b0" +dependencies = [ + "base64 0.13.0 (git+https://github.com/mesalock-linux/rust-base64-sgx?tag=sgx_1.1.3)", + "byteorder 1.3.4", + "bytes 1.0.1", + "http", + "httparse", + "log", + "rand 0.7.3", + "rustls 0.19.0 (git+https://github.com/mesalock-linux/rustls?tag=sgx_1.1.3)", + "sgx_tstd", + "sha1", + "thiserror", + "url", + "utf-8", + "webpki", + "webpki-roots 0.21.0 (git+https://github.com/mesalock-linux/webpki-roots?tag=sgx_1.1.3)", +] + +[[package]] +name = "twox-hash" +version = "1.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" +dependencies = [ + "cfg-if 1.0.0", + "digest 0.10.7", + "static_assertions", +] + +[[package]] +name = "typenum" +version = "1.16.0" +source = "git+https://github.com/encointer/typenum?tag=v1.16.0#4c8dddaa8bdd13130149e43b4085ad14e960617f" +dependencies = [ + "parity-scale-codec", + "scale-info", +] + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "uint" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76f64bba2c53b04fcab63c01a7d7427eadc821e3bc48c34dc9ba29c501164b52" +dependencies = [ + "byteorder 1.4.3", + "crunchy", + "hex", + "static_assertions", +] + +[[package]] +name = "unicase" +version = "2.6.0" +source = "git+https://github.com/mesalock-linux/unicase-sgx#0b0519348572927118af47af3da4da9ffdca8ec6" +dependencies = [ + "sgx_tstd", + "version_check", +] + +[[package]] +name = "unicode-bidi" +version = "0.3.4" +source = "git+https://github.com/mesalock-linux/unicode-bidi-sgx#eb10728a635a046e75747849fbc680cbbb7832c7" +dependencies = [ + "matches", + "sgx_tstd", +] + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "unicode-normalization" +version = "0.1.12" +source = "git+https://github.com/mesalock-linux/unicode-normalization-sgx#c1b030611969f87d75782c1df77975167cbbd509" +dependencies = [ + "smallvec 1.6.1", +] + +[[package]] +name = "unicode-xid" +version = "0.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" + +[[package]] +name = "unicode-xid" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" + +[[package]] +name = "unsigned-varint" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7fdeedbf205afadfe39ae559b75c3240f24e257d0ca27e85f85cb82aa19ac35" + +[[package]] +name = "untrusted" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" + +[[package]] +name = "url" +version = "2.1.1" +source = "git+https://github.com/mesalock-linux/rust-url-sgx?tag=sgx_1.1.3#23832f3191456c2d4a0faab10952e1747be58ca8" +dependencies = [ + "idna", + "matches", + "percent-encoding", + "sgx_tstd", +] + +[[package]] +name = "utf-8" +version = "0.7.4" +source = "git+https://github.com/integritee-network/rust-utf8-sgx?branch=sgx-experimental#b026700da83a2f00f0e9f36f813ef28e447a719e" +dependencies = [ + "sgx_tstd", +] + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.88" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7daec296f25a1bae309c0cd5c29c4b260e510e6d813c286b19eaadf409d40fce" +dependencies = [ + "cfg-if 1.0.0", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.88" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e397f4664c0e4e428e8313a469aaa58310d302159845980fd23b0f22a847f217" +dependencies = [ + "bumpalo", + "log", + "once_cell 1.18.0", + "proc-macro2", + "quote 1.0.33", + "syn 2.0.37", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.88" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5961017b3b08ad5f3fe39f1e79877f8ee7c23c5e5fd5eb80de95abc41f1f16b2" +dependencies = [ + "quote 1.0.33", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.88" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5353b8dab669f5e10f5bd76df26a9360c748f054f862ff5f3f8aae0c7fb3907" +dependencies = [ + "proc-macro2", + "quote 1.0.33", + "syn 2.0.37", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.88" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d046c5d029ba91a1ed14da14dca44b68bf2f124cfbaf741c54151fdb3e0750b" + +[[package]] +name = "web-sys" +version = "0.3.65" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5db499c5f66323272151db0e666cd34f78617522fb0c1604d31a27c50c206a85" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webpki" +version = "0.21.4" +source = "git+https://github.com/mesalock-linux/webpki?branch=mesalock_sgx#8dbe6fbeefadf05582ae47c7fa818b04db49c61e" +dependencies = [ + "ring 0.16.19", + "sgx_tstd", + "untrusted", +] + +[[package]] +name = "webpki-roots" +version = "0.21.0" +source = "git+https://github.com/mesalock-linux/webpki-roots?tag=sgx_1.1.3#6ff3be547ac13ccd46ae55605ad6506ce30688ef" +dependencies = [ + "sgx_tstd", + "webpki", +] + +[[package]] +name = "webpki-roots" +version = "0.21.0" +source = "git+https://github.com/mesalock-linux/webpki-roots?branch=mesalock_sgx#6ff3be547ac13ccd46ae55605ad6506ce30688ef" +dependencies = [ + "sgx_tstd", + "webpki", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +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" + +[[package]] +name = "winnow" +version = "0.5.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c2e3184b9c4e92ad5167ca73039d0c42476302ab603e2fec4487511f38ccefc" +dependencies = [ + "memchr 2.6.3", +] + +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + +[[package]] +name = "yasna" +version = "0.3.1" +source = "git+https://github.com/mesalock-linux/yasna.rs-sgx?rev=sgx_1.1.3#a1f50714cd3eb29608ecf7888cacedc173edfdb2" +dependencies = [ + "bit-vec", + "chrono 0.4.11", + "num-bigint", + "sgx_tstd", +] + +[[package]] +name = "zeroize" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +dependencies = [ + "proc-macro2", + "quote 1.0.33", + "syn 2.0.37", +] + +[[patch.unused]] +name = "getrandom" +version = "0.2.3" +source = "git+https://github.com/integritee-network/getrandom-sgx?branch=update-v2.3#0a4af01fe1df0e6200192e7a709fd18da413466e" diff --git a/bitacross-worker/enclave-runtime/Cargo.toml b/bitacross-worker/enclave-runtime/Cargo.toml new file mode 100644 index 0000000000..c6eae4b549 --- /dev/null +++ b/bitacross-worker/enclave-runtime/Cargo.toml @@ -0,0 +1,175 @@ +[package] +name = "enclave-runtime" +version = "0.0.1" +authors = ['Trust Computing GmbH ', 'Integritee AG '] +edition = "2021" + +[workspace] +members = [] + +[lib] +name = "enclave_runtime" +crate-type = ["staticlib"] + +[features] +default = [] +evm = [ + "ita-sgx-runtime/evm", + "ita-stf/evm", +] +production = ["itp-settings/production", "itp-attestation-handler/production"] +sidechain = ["itp-settings/sidechain", "itp-top-pool-author/sidechain"] +offchain-worker = [ + "itp-settings/offchain-worker", + "itp-top-pool-author/offchain-worker", +] +teeracle = [ + "ita-oracle", + "itp-settings/teeracle", + "itp-top-pool-author/teeracle", +] +test = [ + "ita-stf/test", + "itc-parentchain/test", + "itp-attestation-handler/test", + "itp-extrinsics-factory/mocks", + "itp-sgx-crypto/test", + "itp-sgx-temp-dir", + "itp-stf-executor/test", + "itp-stf-executor/mocks", + "itp-stf-state-handler/test", + "itp-stf-state-observer/mocks", + "itp-storage/test", + "itp-test/sgx", + "itp-top-pool-author/test", + "itp-top-pool-author/mocks", + # substrate + "frame-system", +] +dcap = [] + +[target.'cfg(not(target_env = "sgx"))'.dependencies] +sgx-crypto-helper = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git", package = "sgx_tcrypto_helper" } +sgx_rand = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git" } +sgx_serialize = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git" } +sgx_serialize_derive = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git" } +sgx_tcrypto = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git" } +sgx_trts = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git" } +sgx_tse = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git" } +sgx_tseal = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git" } +sgx_tstd = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git", features = ["untrusted_fs", "net", "backtrace"] } +sgx_tunittest = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git" } +sgx_types = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git" } + +[dependencies] +array-bytes = { version = "6.0.0" } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +derive_more = { version = "0.99.5" } +hex = { version = "0.4.3", default-features = false, features = ["alloc"] } +ipfs-unixfs = { default-features = false, git = "https://github.com/whalelephant/rust-ipfs", branch = "w-nstd" } +lazy_static = { version = "1.1.0", features = ["spin_no_std"] } +primitive-types = { version = "0.12.1", default-features = false, features = ["codec", "serde_no_std"] } + +# scs / integritee +jsonrpc-core = { default-features = false, git = "https://github.com/scs/jsonrpc", branch = "no_std_v18" } + +# mesalock +env_logger = { git = "https://github.com/integritee-network/env_logger-sgx" } +log = { git = "https://github.com/integritee-network/log-sgx" } +# Todo #1313: use the `once_cell` included in rusts core library once we use rust v1.70.0 +once_cell = { git = "https://github.com/mesalock-linux/once_cell-sgx" } +rustls = { rev = "sgx_1.1.3", features = ["dangerous_configuration"], git = "https://github.com/mesalock-linux/rustls" } +serde_json = { tag = "sgx_1.1.3", git = "https://github.com/mesalock-linux/serde-json-sgx" } +webpki = { git = "https://github.com/mesalock-linux/webpki", branch = "mesalock_sgx" } + +# for attestation +base58 = { rev = "sgx_1.1.3", package = "rust-base58", default-features = false, features = ["mesalock_sgx"], git = "https://github.com/mesalock-linux/rust-base58-sgx" } + +cid = { default-features = false, git = "https://github.com/whalelephant/rust-cid", branch = "nstd" } +multibase = { default-features = false, git = "https://github.com/whalelephant/rust-multibase", branch = "nstd" } +teerex-primitives = { default-features = false, git = "https://github.com/integritee-network/pallets.git", branch = "sdk-v0.12.0-polkadot-v0.9.42" } + +# local deps +ita-oracle = { path = "../app-libs/oracle", default-features = false, optional = true, features = ["sgx"] } +ita-parentchain-interface = { path = "../app-libs/parentchain-interface", default-features = false, features = ["sgx"] } +ita-sgx-runtime = { path = "../app-libs/sgx-runtime", default-features = false } +ita-stf = { path = "../app-libs/stf", default-features = false, features = ["sgx"] } +itc-direct-rpc-client = { path = "../core/direct-rpc-client", default-features = false, features = ["sgx"] } +itc-direct-rpc-server = { path = "../core/direct-rpc-server", default-features = false, features = ["sgx"] } +itc-offchain-worker-executor = { path = "../core/offchain-worker-executor", default-features = false, features = ["sgx"] } +itc-parentchain = { path = "../core/parentchain/parentchain-crate", default-features = false, features = ["sgx"] } +itc-parentchain-block-import-dispatcher = { path = "../core/parentchain/block-import-dispatcher", default-features = false, features = ["sgx"] } +itc-parentchain-test = { path = "../core/parentchain/test", default-features = false } +itc-peer-top-broadcaster = { path = "../core/peer-top-broadcaster", default-features = false, features = ["sgx"] } +itc-tls-websocket-server = { path = "../core/tls-websocket-server", default-features = false, features = ["sgx"] } +itp-attestation-handler = { path = "../core-primitives/attestation-handler", default-features = false, features = ["sgx"] } +itp-component-container = { path = "../core-primitives/component-container", default-features = false, features = ["sgx"] } +itp-enclave-metrics = { path = "../core-primitives/enclave-metrics", default-features = false, features = ["sgx"] } +itp-extrinsics-factory = { path = "../core-primitives/extrinsics-factory", default-features = false, features = ["sgx"] } +itp-import-queue = { path = "../core-primitives/import-queue", default-features = false, features = ["sgx"] } +itp-node-api = { path = "../core-primitives/node-api", default-features = false, features = ["sgx"] } +itp-node-api-metadata = { path = "../core-primitives/node-api/metadata", default-features = false } +itp-nonce-cache = { path = "../core-primitives/nonce-cache", default-features = false, features = ["sgx"] } +itp-ocall-api = { path = "../core-primitives/ocall-api", default-features = false } +itp-primitives-cache = { path = "../core-primitives/primitives-cache", default-features = false, features = ["sgx"] } +itp-rpc = { path = "../core-primitives/rpc", default-features = false, features = ["sgx"] } +itp-settings = { path = "../core-primitives/settings" } +itp-sgx-crypto = { path = "../core-primitives/sgx/crypto", default-features = false, features = ["sgx"] } +itp-sgx-externalities = { path = "../core-primitives/substrate-sgx/externalities", default-features = false, features = ["sgx"] } +itp-stf-executor = { path = "../core-primitives/stf-executor", default-features = false, features = ["sgx"] } +itp-stf-interface = { path = "../core-primitives/stf-interface", default-features = false } +itp-stf-primitives = { path = "../core-primitives/stf-primitives", default-features = false } +itp-stf-state-handler = { path = "../core-primitives/stf-state-handler", default-features = false, features = ["sgx"] } +itp-stf-state-observer = { path = "../core-primitives/stf-state-observer", default-features = false, features = ["sgx"] } +itp-storage = { path = "../core-primitives/storage", default-features = false, features = ["sgx"] } +itp-test = { path = "../core-primitives/test", default-features = false, optional = true } +itp-time-utils = { path = "../core-primitives/time-utils", default-features = false, features = ["sgx"] } +itp-top-pool = { path = "../core-primitives/top-pool", default-features = false, features = ["sgx"] } +itp-top-pool-author = { path = "../core-primitives/top-pool-author", default-features = false, features = ["sgx"] } +itp-types = { path = "../core-primitives/types", default-features = false } +itp-utils = { path = "../core-primitives/utils", default-features = false } +its-block-verification = { path = "../sidechain/block-verification", default-features = false } +its-primitives = { path = "../sidechain/primitives", default-features = false } +its-sidechain = { path = "../sidechain/sidechain-crate", default-features = false, features = ["sgx"] } + +# litentry +lc-scheduled-enclave = { path = "../litentry/core/scheduled-enclave", default-features = false, features = ["sgx"] } +litentry-macros = { path = "../litentry/macros" } +litentry-primitives = { path = "../litentry/primitives", default-features = false, features = ["sgx"] } + +# substrate deps +frame-support = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } +frame-system = { optional = true, default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } +sp-core = { default-features = false, features = ["full_crypto"], git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } +sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } + +# test-deps +itp-sgx-temp-dir = { version = "0.1", default-features = false, optional = true, path = "../core-primitives/sgx/temp-dir" } + +[patch.crates-io] +env_logger = { git = "https://github.com/integritee-network/env_logger-sgx" } +getrandom = { git = "https://github.com/integritee-network/getrandom-sgx", branch = "update-v2.3" } +log = { git = "https://github.com/integritee-network/log-sgx" } + +[patch."https://github.com/mesalock-linux/log-sgx"] +log = { git = "https://github.com/integritee-network/log-sgx" } + +[patch."https://github.com/paritytech/substrate"] +sp-io = { path = "../core-primitives/substrate-sgx/sp-io" } + +[patch."https://github.com/apache/teaclave-sgx-sdk.git"] +sgx_alloc = { version = "1.1.6", git = "https://github.com/apache/incubator-teaclave-sgx-sdk", branch = "master" } +sgx_crypto_helper = { version = "1.1.6", git = "https://github.com/apache/incubator-teaclave-sgx-sdk", branch = "master" } +sgx_libc = { version = "1.1.6", git = "https://github.com/apache/incubator-teaclave-sgx-sdk", branch = "master" } +sgx_rand = { version = "1.1.6", git = "https://github.com/apache/incubator-teaclave-sgx-sdk", branch = "master" } +sgx_serialize = { version = "1.1.6", git = "https://github.com/apache/incubator-teaclave-sgx-sdk", branch = "master" } +sgx_serialize_derive = { version = "1.1.6", git = "https://github.com/apache/incubator-teaclave-sgx-sdk", branch = "master" } +sgx_serialize_derive_internals = { version = "1.1.6", git = "https://github.com/apache/incubator-teaclave-sgx-sdk", branch = "master" } +sgx_tcrypto = { version = "1.1.6", git = "https://github.com/apache/incubator-teaclave-sgx-sdk", branch = "master" } +sgx_tcrypto_helper = { version = "1.1.6", git = "https://github.com/apache/incubator-teaclave-sgx-sdk", branch = "master" } +sgx_trts = { version = "1.1.6", git = "https://github.com/apache/incubator-teaclave-sgx-sdk", branch = "master" } +sgx_tse = { version = "1.1.6", git = "https://github.com/apache/incubator-teaclave-sgx-sdk", branch = "master" } +sgx_tseal = { version = "1.1.6", git = "https://github.com/apache/incubator-teaclave-sgx-sdk", branch = "master" } +sgx_tstd = { version = "1.1.6", git = "https://github.com/apache/incubator-teaclave-sgx-sdk", branch = "master" } +sgx_tunittest = { version = "1.1.6", git = "https://github.com/apache/incubator-teaclave-sgx-sdk", branch = "master" } +sgx_types = { version = "1.1.6", git = "https://github.com/apache/incubator-teaclave-sgx-sdk", branch = "master" } diff --git a/bitacross-worker/enclave-runtime/Enclave.config.production.xml b/bitacross-worker/enclave-runtime/Enclave.config.production.xml new file mode 100644 index 0000000000..00336e8aa8 --- /dev/null +++ b/bitacross-worker/enclave-runtime/Enclave.config.production.xml @@ -0,0 +1,12 @@ + + + 0 + 0 + 0x40000 + 0x20000000 + 32 + 0 + 1 + 0 + 0xFFFFFFFF + diff --git a/bitacross-worker/enclave-runtime/Enclave.config.xml b/bitacross-worker/enclave-runtime/Enclave.config.xml new file mode 100644 index 0000000000..62e08c1a5f --- /dev/null +++ b/bitacross-worker/enclave-runtime/Enclave.config.xml @@ -0,0 +1,12 @@ + + + 0 + 0 + 0x40000 + 0x20000000 + 32 + 0 + 0 + 0 + 0xFFFFFFFF + diff --git a/bitacross-worker/enclave-runtime/Enclave.edl b/bitacross-worker/enclave-runtime/Enclave.edl new file mode 100644 index 0000000000..04c02fea61 --- /dev/null +++ b/bitacross-worker/enclave-runtime/Enclave.edl @@ -0,0 +1,277 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +enclave { + from "sgx_backtrace.edl" import *; + from "sgx_tstd.edl" import *; + from "sgx_stdio.edl" import *; + from "sgx_backtrace.edl" import *; + from "sgx_tstdc.edl" import *; + from "sgx_tprotected_fs.edl" import *; + from "sgx_fs.edl" import *; + from "sgx_net.edl" import *; + from "sgx_time.edl" import *; + from "sgx_env.edl" import *; + from "sgx_thread.edl" import *; + from "sgx_pipe.edl" import *; + from "sgx_file.edl" import *; + from "sgx_dcap_tvl.edl" import *; + + include "sgx_quote.h" + include "sgx_report.h" + include "sgx_ql_quote.h" + include "sgx_qve_header.h" + + trusted { + /* define ECALLs here. */ + public sgx_status_t init( + [in, size=mu_ra_addr_size] uint8_t* mu_ra_addr, uint32_t mu_ra_addr_size, + [in, size=untrusted_worker_addr_size] uint8_t* untrusted_worker_addr, uint32_t untrusted_worker_addr_size, + [in, size=encoded_base_dir_size] uint8_t* encoded_base_dir_str, uint32_t encoded_base_dir_size + ); + + public sgx_status_t init_enclave_sidechain_components( + [in, size=fail_mode_size] uint8_t* fail_mode, uint32_t fail_mode_size, + [in, size=fail_at_size] uint8_t* fail_at, uint32_t fail_at_size + ); + + public sgx_status_t init_direct_invocation_server( + [in, size=server_addr_size] uint8_t* server_addr, uint32_t server_addr_size + ); + + public sgx_status_t init_parentchain_components( + [in, size=params_size] uint8_t* params, size_t params_size, + [out, size=latest_header_size] uint8_t* latest_header, size_t latest_header_size + ); + + public sgx_status_t init_shard( + [in, size=shard_size] uint8_t* shard, uint32_t shard_size + ); + + public sgx_status_t init_proxied_shard_vault( + [in, size=shard_size] uint8_t* shard, uint32_t shard_size, + [in, size=parentchain_id_size] uint8_t* parentchain_id, uint32_t parentchain_id_size + ); + + public sgx_status_t execute_trusted_calls(); + + public sgx_status_t sync_parentchain( + [in, size=blocks_size] uint8_t* blocks, size_t blocks_size, + [in, size=events_size] uint8_t* events, size_t events_size, + [in, size=events_proofs_size] uint8_t* events_proofs, size_t events_proofs_size, + [in, size=parentchain_id_size] uint8_t* parentchain_id, uint32_t parentchain_id_size, + int is_syncing + ); + + public sgx_status_t set_nonce( + [in] uint32_t* nonce, + [in, size=parentchain_id_size] uint8_t* parentchain_id, uint32_t parentchain_id_size + ); + + public sgx_status_t set_node_metadata( + [in, size=node_metadata_size] uint8_t* node_metadata, uint32_t node_metadata_size, + [in, size=parentchain_id_size] uint8_t* parentchain_id, uint32_t parentchain_id_size + ); + + public sgx_status_t get_rsa_encryption_pubkey( + [out, size=pubkey_size] uint8_t* pubkey, uint32_t pubkey_size); + + public sgx_status_t get_ecc_signing_pubkey( + [out, size=pubkey_size] uint8_t* pubkey, uint32_t pubkey_size); + + public sgx_status_t get_ecc_vault_pubkey( + [in, size=shard_size] uint8_t* shard, uint32_t shard_size, + [out, size=pubkey_size] uint8_t* pubkey, uint32_t pubkey_size); + + public sgx_status_t get_mrenclave( + [out, size=mrenclave_size] uint8_t* mrenclave, uint32_t mrenclave_size); + + public sgx_status_t generate_ias_ra_extrinsic( + [in, size=w_url_size] uint8_t* w_url, uint32_t w_url_size, + [out, size=unchecked_extrinsic_max_size] uint8_t* unchecked_extrinsic, uint32_t unchecked_extrinsic_max_size, + [out] uint32_t* unchecked_extrinsic_size, + int skip_ra + ); + public sgx_status_t generate_dcap_ra_quote( + int skip_ra, + [in] const sgx_target_info_t* quoting_enclave_target_info, + uint32_t quote_size, + [out, size=dcap_quote_size] uint8_t* dcap_quote_p, uint32_t dcap_quote_size + ); + + public sgx_status_t generate_dcap_ra_extrinsic_from_quote( + [in, size=w_url_size] uint8_t* w_url, uint32_t w_url_size, + [in, size=quote_size] uint8_t* quote, uint32_t quote_size, + [out, size=unchecked_extrinsic_max_size] uint8_t* unchecked_extrinsic, uint32_t unchecked_extrinsic_max_size, + [out] uint32_t* unchecked_extrinsic_size + ); + + public sgx_status_t generate_dcap_ra_extrinsic( + [in, size=w_url_size] uint8_t* w_url, uint32_t w_url_size, + [out, size=unchecked_extrinsic_max_size] uint8_t* unchecked_extrinsic, uint32_t unchecked_extrinsic_max_size, + [out] uint32_t* unchecked_extrinsic_size, + int skip_ra, + [in] const sgx_target_info_t* quoting_enclave_target_info, + [in] uint32_t* quote_size + ); + + public sgx_status_t generate_register_quoting_enclave_extrinsic( + [in] const sgx_ql_qve_collateral_t *p_quote_collateral, + [out, size=unchecked_extrinsic_max_size] uint8_t* unchecked_extrinsic, uint32_t unchecked_extrinsic_max_size, + [out] uint32_t* unchecked_extrinsic_size + ); + + public sgx_status_t generate_register_tcb_info_extrinsic( + [in] const sgx_ql_qve_collateral_t *p_quote_collateral, + [out, size=unchecked_extrinsic_max_size] uint8_t* unchecked_extrinsic, uint32_t unchecked_extrinsic_max_size, + [out] uint32_t* unchecked_extrinsic_size + ); + + public sgx_status_t update_market_data_xt( + [in, size=crypto_currency_size] uint8_t* crypto_currency, uint32_t crypto_currency_size, + [in, size=fiat_currency_size] uint8_t* fiat_currency, uint32_t fiat_currency_size, + [out, size=unchecked_extrinsic_max_size] uint8_t* unchecked_extrinsic, uint32_t unchecked_extrinsic_max_size, + [out] uint32_t* unchecked_extrinsic_size + ); + + public sgx_status_t update_weather_data_xt( + [in, size=weather_info_logitude_size] uint8_t* weather_info_logitude, uint32_t weather_info_logitude_size, + [in, size=weather_info_latitude_size] uint8_t* weather_info_latitude, uint32_t weather_info_latitude_size, + [out, size=unchecked_extrinsic_max_size] uint8_t* unchecked_extrinsic, uint32_t unchecked_extrinsic_max_size, + [out] uint32_t* unchecked_extrinsic_size + ); + + public sgx_status_t dump_ias_ra_cert_to_disk(); + + public sgx_status_t dump_dcap_ra_cert_to_disk([in] const sgx_target_info_t* quoting_enclave_target_info, uint32_t quote_size); + + public sgx_status_t dump_dcap_collateral_to_disk([in] const sgx_ql_qve_collateral_t *p_quote_collateral); + + public sgx_status_t run_state_provisioning_server( + int fd, + sgx_quote_sign_type_t quote_type, + [in] sgx_target_info_t* quoting_enclave_target_info, + [in] uint32_t* quote_size, + int skip_ra + ); + public sgx_status_t request_state_provisioning( + int fd, + sgx_quote_sign_type_t quote_type, + [in] sgx_target_info_t* quoting_enclave_target_info, + [in] uint32_t* quote_size, + [in, size=shard_size] uint8_t* shard, uint32_t shard_size, + int skip_ra + ); + + public sgx_status_t call_rpc_methods( + [in, size=request_len] uint8_t* request, uint32_t request_len, + [out, size=response_len] uint8_t* response, uint32_t response_len + ); + + public size_t test_main_entrance(); + + public sgx_status_t migrate_shard( + [in, size=shard_size] uint8_t* old_shard, + [in, size=shard_size] uint8_t* new_shard, + uint32_t shard_size + ); + + public sgx_status_t ignore_parentchain_block_import_validation_until( + [in] uint32_t* until + ); + }; + + untrusted { + sgx_status_t ocall_sgx_init_quote( + [out] sgx_target_info_t *ret_ti, + [out] sgx_epid_group_id_t *ret_gid + ); + + sgx_status_t ocall_get_ias_socket([out] int *ret_fd); + + sgx_status_t ocall_get_quote( + [in, size = sigrl_len] uint8_t * p_sigrl, uint32_t sigrl_len, + [in] sgx_report_t *report, sgx_quote_sign_type_t quote_type, + [in] sgx_spid_t *p_spid, [in] sgx_quote_nonce_t *p_nonce, + [out] sgx_report_t *p_qe_report, + [out, size = maxlen] sgx_quote_t *p_quote, uint32_t maxlen, + [out] uint32_t* p_quote_len + ); + + sgx_status_t ocall_get_dcap_quote( + [in] sgx_report_t *report, + [out, size = quote_size] sgx_quote_t *p_quote, uint32_t quote_size + ); + + sgx_status_t ocall_get_qve_report_on_quote( + [in, size = quote_size] const uint8_t * quote, uint32_t quote_size, + time_t current_time, + [in] const sgx_ql_qve_collateral_t *p_quote_collateral, + [out] uint32_t *collateral_expiration_status, + [out] sgx_ql_qv_result_t *quote_verification_result, + [in, out] sgx_ql_qe_report_info_t *qve_report_info, + [out, size=supplemental_data_size] uint8_t *p_supplemental_data, + uint32_t supplemental_data_size + ); + + sgx_status_t ocall_get_update_info( + [in] sgx_platform_info_t * platformBlob, int32_t enclaveTrusted, + [out] sgx_update_info_bit_t * update_info + ); + + sgx_status_t ocall_read_ipfs( + [in, size = cid_size] uint8_t * cid, uint32_t cid_size + ); + + sgx_status_t ocall_write_ipfs( + [in, size = state_size] uint8_t * enc_state, uint32_t state_size, + [out, size = cid_size] uint8_t * cid, uint32_t cid_size + ); + + sgx_status_t ocall_worker_request( + [in, size = req_size] uint8_t * request, uint32_t req_size, + [in, size=parentchain_id_size] uint8_t* parentchain_id, uint32_t parentchain_id_size, + [out, size = resp_size] uint8_t * response, uint32_t resp_size + ); + + sgx_status_t ocall_update_metric( + [in, size = metric_size] uint8_t * metric, uint32_t metric_size + ); + + sgx_status_t ocall_propose_sidechain_blocks( + [in, size = signed_blocks_size] uint8_t * signed_blocks, uint32_t signed_blocks_size + ); + + sgx_status_t ocall_store_sidechain_blocks( + [in, size = signed_blocks_size] uint8_t * signed_blocks, uint32_t signed_blocks_size + ); + + sgx_status_t ocall_fetch_sidechain_blocks_from_peer( + [in, size = last_imported_block_hash_size] uint8_t * last_imported_block_hash, uint32_t last_imported_block_hash_size, + [in, size = maybe_until_block_hash_size] uint8_t * maybe_until_block_hash, uint32_t maybe_until_block_hash_size, + [in, size = shard_identifier_size] uint8_t * shard_identifier, uint32_t shard_identifier_size, + [out, size = sidechain_blocks_size] uint8_t * sidechain_blocks, uint32_t sidechain_blocks_size + ); + + sgx_status_t ocall_get_trusted_peers_urls([out, size = peers_size] uint8_t * peers, uint32_t peers_size); + + sgx_status_t ocall_send_to_parentchain( + [in, size = extrinsics_size] uint8_t * extrinsics, uint32_t extrinsics_size, + [in, size=parentchain_id_size] uint8_t* parentchain_id, uint32_t parentchain_id_size, + int await_each_inclusion + ); + }; +}; diff --git a/bitacross-worker/enclave-runtime/Enclave.lds b/bitacross-worker/enclave-runtime/Enclave.lds new file mode 100644 index 0000000000..e3d9d0ee0d --- /dev/null +++ b/bitacross-worker/enclave-runtime/Enclave.lds @@ -0,0 +1,9 @@ +enclave.so +{ + global: + g_global_data_sim; + g_global_data; + enclave_entry; + local: + *; +}; diff --git a/bitacross-worker/enclave-runtime/Enclave_private.pem b/bitacross-worker/enclave-runtime/Enclave_private.pem new file mode 100644 index 0000000000..529d07be35 --- /dev/null +++ b/bitacross-worker/enclave-runtime/Enclave_private.pem @@ -0,0 +1,39 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIG4gIBAAKCAYEAroOogvsj/fZDZY8XFdkl6dJmky0lRvnWMmpeH41Bla6U1qLZ +AmZuyIF+mQC/cgojIsrBMzBxb1kKqzATF4+XwPwgKz7fmiddmHyYz2WDJfAjIveJ +ZjdMjM4+EytGlkkJ52T8V8ds0/L2qKexJ+NBLxkeQLfV8n1mIk7zX7jguwbCG1Pr +nEMdJ3Sew20vnje+RsngAzdPChoJpVsWi/K7cettX/tbnre1DL02GXc5qJoQYk7b +3zkmhz31TgFrd9VVtmUGyFXAysuSAb3EN+5VnHGr0xKkeg8utErea2FNtNIgua8H +ONfm9Eiyaav1SVKzPHlyqLtcdxH3I8Wg7yqMsaprZ1n5A1v/levxnL8+It02KseD +5HqV4rf/cImSlCt3lpRg8U5E1pyFQ2IVEC/XTDMiI3c+AR+w2jSRB3Bwn9zJtFlW +KHG3m1xGI4ck+Lci1JvWWLXQagQSPtZTsubxTQNx1gsgZhgv1JHVZMdbVlAbbRMC +1nSuJNl7KPAS/VfzAgEDAoIBgHRXxaynbVP5gkO0ug6Qw/E27wzIw4SmjsxG6Wpe +K7kfDeRskKxESdsA/xCrKkwGwhcx1iIgS5+Qscd1Yg+1D9X9asd/P7waPmWoZd+Z +AhlKwhdPsO7PiF3e1AzHhGQwsUTt/Y/aSI1MpHBvy2/s1h9mFCslOUxTmWw0oj/Q +ldIEgWeNR72CE2+jFIJIyml6ftnb6qzPiga8Bm48ubKh0kvySOqnkmnPzgh+JBD6 +JnBmtZbfPT97bwTT+N6rnPqOOApvfHPf15kWI8yDbprG1l4OCUaIUH1AszxLd826 +5IPM+8gINLRDP1MA6azECPjTyHXhtnSIBZCyWSVkc05vYmNXYUNiXWMajcxW9M02 +wKzFELO8NCEAkaTPxwo4SCyIjUxiK1LbQ9h8PSy4c1+gGP4LAMR8xqP4QKg6zdu9 +osUGG/xRe/uufgTBFkcjqBHtK5L5VI0jeNIUAgW/6iNbYXjBMJ0GfauLs+g1VsOm +WfdgXzsb9DYdMa0OXXHypmV4GwKBwQDUwQj8RKJ6c8cT4vcWCoJvJF00+RFL+P3i +Gx2DLERxRrDa8AVGfqaCjsR+3vLgG8V/py+z+dxZYSqeB80Qeo6PDITcRKoeAYh9 +xlT3LJOS+k1cJcEmlbbO2IjLkTmzSwa80fWexKu8/Xv6vv15gpqYl1ngYoqJM3pd +vzmTIOi7MKSZ0WmEQavrZj8zK4endE3v0eAEeQ55j1GImbypSf7Idh7wOXtjZ7WD +Dg6yWDrri+AP/L3gClMj8wsAxMV4ZR8CgcEA0fzDHkFa6raVOxWnObmRoDhAtE0a +cjUj976NM5yyfdf2MrKy4/RhdTiPZ6b08/lBC/+xRfV3xKVGzacm6QjqjZrUpgHC +0LKiZaMtccCJjLtPwQd0jGQEnKfMFaPsnhOc5y8qVkCzVOSthY5qhz0XNotHHFmJ +gffVgB0iqrMTvSL7IA2yqqpOqNRlhaYhNl8TiFP3gIeMtVa9rZy31JPgT2uJ+kfo +gV7sdTPEjPWZd7OshGxWpT6QfVDj/T9T7L6tAoHBAI3WBf2DFvxNL2KXT2QHAZ9t +k3imC4f7U+wSE6zILaDZyzygA4RUbwG0gv8/TJVn2P/Eynf76DuWHGlaiLWnCbSz +Az2DHBQBBaku409zDQym3j1ugMRjzzSQWzJg0SIyBH3hTmnYcn3+Uqcp/lEBvGW6 +O+rsXFt3pukqJmIV8HzLGGaLm62BHUeZf3dyWm+i3p/hQAL7Xvu04QW70xuGqdr5 +afV7p5eaeQIJXyGQJ0eylV/90+qxjMKiB1XYg6WYvwKBwQCL/ddpgOdHJGN8uRom +e7Zq0Csi3hGheMKlKbN3vcxT5U7MdyHtTZZOJbTvxKNNUNYH/8uD+PqDGNneb29G +BfGzvI3EASyLIcGZF3OhKwZd0jUrWk2y7Vhob91jwp2+t73vdMbkKyI4mHOuXvGv +fg95si9oO7EBT+Oqvhccd2J+F1IVXncccYnF4u5ZGWt5lLewN/pVr7MjjykeaHqN +t+rfnQam2psA6fL4zS2zTmZPzR2tnY8Y1GBTi0Ko1OKd1HMCgcAb5cB/7/AQlhP9 +yQa04PLH9ygQkKKptZp7dy5WcWRx0K/hAHRoi2aw1wZqfm7VBNu2SLcs90kCCCxp +6C5sfJi6b8NpNbIPC+sc9wsFr7pGo9SFzQ78UlcWYK2Gu2FxlMjonhka5hvo4zvg +WxlpXKEkaFt3gLd92m/dMqBrHfafH7VwOJY2zT3WIpjwuk0ZzmRg5p0pG/svVQEH +NZmwRwlopysbR69B/n1nefJ84UO50fLh5s5Zr3gBRwbWNZyzhXk= +-----END RSA PRIVATE KEY----- diff --git a/bitacross-worker/enclave-runtime/Makefile b/bitacross-worker/enclave-runtime/Makefile new file mode 100644 index 0000000000..b4dc322eed --- /dev/null +++ b/bitacross-worker/enclave-runtime/Makefile @@ -0,0 +1,58 @@ +# Copyright (C) 2017-2018 Baidu, Inc. All Rights Reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Baidu, Inc., nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +######## Worker Feature Settings ######## +# Set sidechain as default feature mode +WORKER_MODE ?= sidechain + +Rust_Enclave_Name := libenclave.a +Rust_Enclave_Files := $(wildcard src/*.rs) $(wildcard ../stf/src/*.rs) +RUSTFLAGS :="-C target-feature=+avx2" + +ifeq ($(SGX_DEBUG), 1) + OUTPUT_PATH := debug + CARGO_TARGET := +else + OUTPUT_PATH := release + CARGO_TARGET := --release +endif + +ifeq ($(SGX_PRODUCTION), 1) + ENCLAVE_FEATURES = --features=production,$(WORKER_MODE),$(ADDITIONAL_FEATURES) +else + ENCLAVE_FEATURES = --features=test,$(WORKER_MODE),$(ADDITIONAL_FEATURES) +endif + +.PHONY: all + +all: $(Rust_Enclave_Name) + +$(Rust_Enclave_Name): $(Rust_Enclave_Files) + RUSTFLAGS=$(RUSTFLAGS) cargo build $(CARGO_TARGET) $(ENCLAVE_FEATURES) + cp ./target/$(OUTPUT_PATH)/libenclave_runtime.a ../lib/libenclave.a + diff --git a/bitacross-worker/enclave-runtime/README.md b/bitacross-worker/enclave-runtime/README.md new file mode 100644 index 0000000000..a4b88a52d1 --- /dev/null +++ b/bitacross-worker/enclave-runtime/README.md @@ -0,0 +1,2 @@ +# sidechain dependency graph +cargo depgraph --features dcap,sidechain --include enclave-runtime,itp-types,ita-stf | dot -Tsvg > dependency-graph.svg diff --git a/bitacross-worker/enclave-runtime/rust-toolchain.toml b/bitacross-worker/enclave-runtime/rust-toolchain.toml new file mode 100644 index 0000000000..23ed88e6c8 --- /dev/null +++ b/bitacross-worker/enclave-runtime/rust-toolchain.toml @@ -0,0 +1,4 @@ +[toolchain] +channel = "nightly-2022-10-22" +targets = ["wasm32-unknown-unknown"] +profile = "default" # include rustfmt, clippy diff --git a/bitacross-worker/enclave-runtime/rustfmt.toml b/bitacross-worker/enclave-runtime/rustfmt.toml new file mode 100644 index 0000000000..104b9aa998 --- /dev/null +++ b/bitacross-worker/enclave-runtime/rustfmt.toml @@ -0,0 +1,18 @@ +# Basic +hard_tabs = true +max_width = 100 +use_small_heuristics = "Max" +# Imports +imports_granularity = "Crate" +reorder_imports = true +# Consistency +newline_style = "Unix" +# Misc +chain_width = 80 +spaces_around_ranges = false +match_arm_leading_pipes = "Preserve" +match_arm_blocks = false +match_block_trailing_comma = true +trailing_comma = "Vertical" +trailing_semicolon = false +use_field_init_shorthand = true \ No newline at end of file diff --git a/bitacross-worker/enclave-runtime/src/attestation.rs b/bitacross-worker/enclave-runtime/src/attestation.rs new file mode 100644 index 0000000000..5b7f7ded3a --- /dev/null +++ b/bitacross-worker/enclave-runtime/src/attestation.rs @@ -0,0 +1,554 @@ +// Copyright 2022 Integritee AG and Supercomputing Systems AG +// Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in +// the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Baidu, Inc., nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +use crate::{ + initialization::global_components::{ + GLOBAL_ATTESTATION_HANDLER_COMPONENT, GLOBAL_SHIELDING_KEY_REPOSITORY_COMPONENT, + }, + utils::{ + get_extrinsic_factory_from_integritee_solo_or_parachain, + get_node_metadata_repository_from_integritee_solo_or_parachain, + }, + Error as EnclaveError, Result as EnclaveResult, +}; +use codec::{Decode, Encode}; +use itp_attestation_handler::{AttestationHandler, RemoteAttestationType, SgxQlQveCollateral}; +use itp_component_container::ComponentGetter; +use itp_extrinsics_factory::CreateExtrinsics; +use itp_node_api::metadata::{ + pallet_teerex::TeerexCallIndexes, + provider::{AccessNodeMetadata, Error as MetadataProviderError}, + Error as MetadataError, +}; +use itp_node_api_metadata::NodeMetadata; +use itp_settings::worker::MR_ENCLAVE_SIZE; +use itp_sgx_crypto::{ + ed25519_derivation::DeriveEd25519, key_repository::AccessKey, Error as SgxCryptoError, +}; +use itp_types::OpaqueCall; +use itp_utils::write_slice_and_whitespace_pad; +use log::*; +use sgx_types::*; +use sp_core::Pair; +use sp_runtime::OpaqueExtrinsic; +use std::{prelude::v1::*, slice, vec::Vec}; + +#[no_mangle] +pub unsafe extern "C" fn get_mrenclave(mrenclave: *mut u8, mrenclave_size: usize) -> sgx_status_t { + if mrenclave.is_null() || mrenclave_size < MR_ENCLAVE_SIZE { + return sgx_status_t::SGX_ERROR_INVALID_PARAMETER + } + let attestation_handler = match GLOBAL_ATTESTATION_HANDLER_COMPONENT.get() { + Ok(r) => r, + Err(e) => { + error!("Component get failure: {:?}", e); + return sgx_status_t::SGX_ERROR_UNEXPECTED + }, + }; + match attestation_handler.get_mrenclave() { + Ok(mrenclave_value) => { + let mrenclave_slice = slice::from_raw_parts_mut(mrenclave, mrenclave_size); + if let Err(e) = + write_slice_and_whitespace_pad(mrenclave_slice, mrenclave_value.to_vec()) + { + error!("Failed to transfer mrenclave to o-call buffer: {:?}", e); + return sgx_status_t::SGX_ERROR_UNEXPECTED + } + sgx_status_t::SGX_SUCCESS + }, + Err(e) => e.into(), + } +} + +// FIXME: add dcap suppoort for call site +pub fn create_ra_report_and_signature( + skip_ra: bool, + remote_attestation_type: RemoteAttestationType, + sign_type: sgx_quote_sign_type_t, + quoting_enclave_target_info: Option<&sgx_target_info_t>, + quote_size: Option<&u32>, +) -> EnclaveResult<(Vec, Vec)> { + let attestation_handler = match GLOBAL_ATTESTATION_HANDLER_COMPONENT.get() { + Ok(r) => r, + Err(e) => { + error!("Component get failure: {:?}", e); + return Err(e.into()) + }, + }; + + match remote_attestation_type { + RemoteAttestationType::Epid => { + match attestation_handler.create_epid_ra_report_and_signature(sign_type, skip_ra) { + Ok(epid) => Ok(epid), + Err(e) => { + error!("create_epid_ra_report_and_signature failure: {:?}", e); + Err(e.into()) + }, + } + }, + RemoteAttestationType::Dcap => { + match attestation_handler.generate_dcap_ra_cert( + quoting_enclave_target_info, + quote_size, + skip_ra, + ) { + Ok((key_der, cert_der, _qe_quote)) => Ok((key_der, cert_der)), + Err(e) => { + error!("generate_dcap_ra_cert failure: {:?}", e); + Err(e.into()) + }, + } + }, + } +} + +#[no_mangle] +pub unsafe extern "C" fn generate_ias_ra_extrinsic( + w_url: *const u8, + w_url_size: u32, + unchecked_extrinsic: *mut u8, + unchecked_extrinsic_max_size: u32, + unchecked_extrinsic_size: *mut u32, + skip_ra: c_int, +) -> sgx_status_t { + if w_url.is_null() || unchecked_extrinsic.is_null() { + return sgx_status_t::SGX_ERROR_INVALID_PARAMETER + } + let mut url_slice = slice::from_raw_parts(w_url, w_url_size as usize); + let url = match String::decode(&mut url_slice) { + Ok(url) => url, + Err(_) => + return EnclaveError::Other("Could not decode url slice to a valid String".into()).into(), + }; + let extrinsic_slice = + slice::from_raw_parts_mut(unchecked_extrinsic, unchecked_extrinsic_max_size as usize); + + let extrinsic = match generate_ias_ra_extrinsic_internal(url, skip_ra == 1) { + Ok(xt) => xt, + Err(e) => return e.into(), + }; + + *unchecked_extrinsic_size = + match write_slice_and_whitespace_pad(extrinsic_slice, extrinsic.encode()) { + Ok(l) => l as u32, + Err(e) => return EnclaveError::BufferError(e).into(), + }; + sgx_status_t::SGX_SUCCESS +} + +#[no_mangle] +pub unsafe extern "C" fn generate_dcap_ra_extrinsic( + w_url: *const u8, + w_url_size: u32, + unchecked_extrinsic: *mut u8, + unchecked_extrinsic_max_size: u32, + unchecked_extrinsic_size: *mut u32, + skip_ra: c_int, + quoting_enclave_target_info: Option<&sgx_target_info_t>, + quote_size: Option<&u32>, +) -> sgx_status_t { + if w_url.is_null() || unchecked_extrinsic.is_null() { + return sgx_status_t::SGX_ERROR_INVALID_PARAMETER + } + let mut url_slice = slice::from_raw_parts(w_url, w_url_size as usize); + let url = match String::decode(&mut url_slice) { + Ok(url) => url, + Err(_) => + return EnclaveError::Other("Could not decode url slice to a valid String".into()).into(), + }; + let extrinsic_slice = + slice::from_raw_parts_mut(unchecked_extrinsic, unchecked_extrinsic_max_size as usize); + + let extrinsic = match generate_dcap_ra_extrinsic_internal( + url, + skip_ra == 1, + quoting_enclave_target_info, + quote_size, + ) { + Ok(xt) => xt, + Err(e) => return e.into(), + }; + + *unchecked_extrinsic_size = + match write_slice_and_whitespace_pad(extrinsic_slice, extrinsic.encode()) { + Ok(l) => l as u32, + Err(e) => return EnclaveError::BufferError(e).into(), + }; + sgx_status_t::SGX_SUCCESS +} + +pub fn generate_dcap_ra_extrinsic_internal( + url: String, + skip_ra: bool, + quoting_enclave_target_info: Option<&sgx_target_info_t>, + quote_size: Option<&u32>, +) -> EnclaveResult { + let attestation_handler = GLOBAL_ATTESTATION_HANDLER_COMPONENT.get()?; + + if !skip_ra { + let (_priv_key_der, _cert_der, dcap_quote) = attestation_handler.generate_dcap_ra_cert( + quoting_enclave_target_info, + quote_size, + skip_ra, + )?; + + generate_dcap_ra_extrinsic_from_quote_internal(url, &dcap_quote) + } else { + generate_dcap_skip_ra_extrinsic_from_mr_enclave( + url, + &attestation_handler.get_mrenclave()?.encode(), + ) + } +} + +#[no_mangle] +pub unsafe extern "C" fn generate_dcap_ra_quote( + skip_ra: c_int, + quoting_enclave_target_info: &sgx_target_info_t, + quote_size: u32, + dcap_quote_p: *mut u8, + dcap_quote_size: u32, +) -> sgx_status_t { + if dcap_quote_p.is_null() { + return sgx_status_t::SGX_ERROR_INVALID_PARAMETER + } + let dcap_quote = match generate_dcap_ra_quote_internal( + skip_ra == 1, + quoting_enclave_target_info, + quote_size, + ) { + Ok(dcap_quote) => dcap_quote, + Err(e) => return e.into(), + }; + + let dcap_quote_slice = slice::from_raw_parts_mut(dcap_quote_p, dcap_quote_size as usize); + + if let Err(e) = write_slice_and_whitespace_pad(dcap_quote_slice, dcap_quote) { + return EnclaveError::BufferError(e).into() + }; + + sgx_status_t::SGX_SUCCESS +} + +pub fn generate_dcap_ra_quote_internal( + skip_ra: bool, + quoting_enclave_target_info: &sgx_target_info_t, + quote_size: u32, +) -> EnclaveResult> { + let attestation_handler = GLOBAL_ATTESTATION_HANDLER_COMPONENT.get()?; + + let (_priv_key_der, _cert_der, dcap_quote) = attestation_handler.generate_dcap_ra_cert( + Some(quoting_enclave_target_info), + Some("e_size), + skip_ra, + )?; + + Ok(dcap_quote) +} + +#[no_mangle] +pub unsafe extern "C" fn generate_dcap_ra_extrinsic_from_quote( + w_url: *const u8, + w_url_size: u32, + quote: *const u8, + quote_size: u32, + unchecked_extrinsic: *mut u8, + unchecked_extrinsic_max_size: u32, + unchecked_extrinsic_size: *mut u32, +) -> sgx_status_t { + if w_url.is_null() || unchecked_extrinsic.is_null() { + return sgx_status_t::SGX_ERROR_INVALID_PARAMETER + } + let mut url_slice = slice::from_raw_parts(w_url, w_url_size as usize); + let url = match String::decode(&mut url_slice) { + Ok(url) => url, + Err(_) => + return EnclaveError::Other("Could not decode url slice to a valid String".into()).into(), + }; + + let extrinsic_slice = + slice::from_raw_parts_mut(unchecked_extrinsic, unchecked_extrinsic_max_size as usize); + + let quote_slice = slice::from_raw_parts(quote, quote_size as usize); + + let extrinsic = match generate_dcap_ra_extrinsic_from_quote_internal(url, quote_slice) { + Ok(xt) => xt, + Err(e) => return e.into(), + }; + + *unchecked_extrinsic_size = + match write_slice_and_whitespace_pad(extrinsic_slice, extrinsic.encode()) { + Ok(l) => l as u32, + Err(e) => return EnclaveError::BufferError(e).into(), + }; + sgx_status_t::SGX_SUCCESS +} + +pub fn generate_dcap_ra_extrinsic_from_quote_internal( + url: String, + quote: &[u8], +) -> EnclaveResult { + let node_metadata_repo = get_node_metadata_repository_from_integritee_solo_or_parachain()?; + info!(" [Enclave] Compose register enclave getting callIDs:"); + + let call_ids = node_metadata_repo + .get_from_metadata(|m| m.register_enclave_call_indexes())? + .map_err(MetadataProviderError::MetadataError)?; + info!(" [Enclave] Compose register enclave call DCAP IDs: {:?}", call_ids); + + let shielding_pubkey = get_shielding_pubkey()?; + let vc_pubkey = get_vc_pubkey()?; + + let call = OpaqueCall::from_tuple(&(call_ids, quote, url, shielding_pubkey, vc_pubkey)); + + info!(" [Enclave] Compose register enclave got extrinsic, returning"); + create_extrinsics(call) +} + +pub fn generate_dcap_skip_ra_extrinsic_from_mr_enclave( + url: String, + quote: &[u8], +) -> EnclaveResult { + let node_metadata_repo = get_node_metadata_repository_from_integritee_solo_or_parachain()?; + info!(" [Enclave] Compose register enclave (skip-ra) getting callIDs:"); + + let call_ids = node_metadata_repo + .get_from_metadata(|m| m.register_enclave_call_indexes())? + .map_err(MetadataProviderError::MetadataError)?; + info!(" [Enclave] Compose register enclave (skip-ra) call DCAP IDs: {:?}", call_ids); + + let shielding_pubkey = get_shielding_pubkey()?; + let vc_pubkey = get_vc_pubkey()?; + + let call = OpaqueCall::from_tuple(&(call_ids, quote, url, shielding_pubkey, vc_pubkey)); + + info!(" [Enclave] Compose register enclave (skip-ra) got extrinsic, returning"); + create_extrinsics(call) +} + +fn generate_ias_ra_extrinsic_internal( + url: String, + skip_ra: bool, +) -> EnclaveResult { + let attestation_handler = GLOBAL_ATTESTATION_HANDLER_COMPONENT.get()?; + let cert_der = attestation_handler.generate_ias_ra_cert(skip_ra)?; + + generate_ias_ra_extrinsic_from_der_cert_internal(url, &cert_der) +} + +pub fn generate_ias_ra_extrinsic_from_der_cert_internal( + url: String, + cert_der: &[u8], +) -> EnclaveResult { + let node_metadata_repo = get_node_metadata_repository_from_integritee_solo_or_parachain()?; + + info!(" [Enclave] Compose register ias enclave (skip-ra) call"); + let call_ids = node_metadata_repo + .get_from_metadata(|m| m.register_enclave_call_indexes())? + .map_err(MetadataProviderError::MetadataError)?; + + let shielding_pubkey = get_shielding_pubkey()?; + let vc_pubkey = get_vc_pubkey()?; + + let call = OpaqueCall::from_tuple(&(call_ids, cert_der, url, shielding_pubkey, vc_pubkey)); + + create_extrinsics(call) +} + +fn create_extrinsics(call: OpaqueCall) -> EnclaveResult { + let extrinsics_factory = get_extrinsic_factory_from_integritee_solo_or_parachain()?; + let extrinsics = extrinsics_factory.create_extrinsics(&[call], None)?; + + match extrinsics.get(0) { + Some(xt) => Ok(xt.clone()), + None => Err(EnclaveError::Other("Could not create extrinsic".into())), + } +} + +#[no_mangle] +pub unsafe extern "C" fn generate_register_quoting_enclave_extrinsic( + collateral: *const sgx_ql_qve_collateral_t, + unchecked_extrinsic: *mut u8, + unchecked_extrinsic_max_size: u32, + unchecked_extrinsic_size: *mut u32, +) -> sgx_status_t { + if unchecked_extrinsic.is_null() || collateral.is_null() { + return sgx_status_t::SGX_ERROR_INVALID_PARAMETER + } + let extrinsic_slice = + slice::from_raw_parts_mut(unchecked_extrinsic, unchecked_extrinsic_max_size as usize); + let collateral = SgxQlQveCollateral::from_c_type(&*collateral); + let collateral_data = match collateral.get_quoting_enclave_split() { + Some(d) => d, + None => return sgx_status_t::SGX_ERROR_INVALID_PARAMETER, + }; + + let call_index_getter = |m: &NodeMetadata| m.register_quoting_enclave_call_indexes(); + *unchecked_extrinsic_size = match generate_generic_register_collateral_extrinsic( + call_index_getter, + extrinsic_slice, + &collateral_data.0, + &collateral_data.1, + &collateral.qe_identity_issuer_chain, + ) { + Ok(l) => l as u32, + Err(e) => return e.into(), + }; + sgx_status_t::SGX_SUCCESS +} + +#[no_mangle] +pub unsafe extern "C" fn generate_register_tcb_info_extrinsic( + collateral: *const sgx_ql_qve_collateral_t, + unchecked_extrinsic: *mut u8, + unchecked_extrinsic_max_size: u32, + unchecked_extrinsic_size: *mut u32, +) -> sgx_status_t { + if unchecked_extrinsic.is_null() || collateral.is_null() { + return sgx_status_t::SGX_ERROR_INVALID_PARAMETER + } + let extrinsic_slice = + slice::from_raw_parts_mut(unchecked_extrinsic, unchecked_extrinsic_max_size as usize); + let collateral = SgxQlQveCollateral::from_c_type(&*collateral); + let collateral_data = match collateral.get_tcb_info_split() { + Some(d) => d, + None => return sgx_status_t::SGX_ERROR_INVALID_PARAMETER, + }; + + let call_index_getter = |m: &NodeMetadata| m.register_tcb_info_call_indexes(); + *unchecked_extrinsic_size = match generate_generic_register_collateral_extrinsic( + call_index_getter, + extrinsic_slice, + &collateral_data.0, + &collateral_data.1, + &collateral.tcb_info_issuer_chain, + ) { + Ok(l) => l as u32, + Err(e) => return e.into(), + }; + sgx_status_t::SGX_SUCCESS +} + +pub fn generate_generic_register_collateral_extrinsic( + getter: F, + extrinsic_slice: &mut [u8], + collateral_data: &str, + data_signature: &[u8], + issuer_chain: &[u8], +) -> EnclaveResult +where + F: Fn(&NodeMetadata) -> Result<[u8; 2], MetadataError>, +{ + let node_metadata_repo = get_node_metadata_repository_from_integritee_solo_or_parachain()?; + let call_ids = node_metadata_repo + .get_from_metadata(getter)? + .map_err(MetadataProviderError::MetadataError)?; + info!(" [Enclave] Compose register collateral call: {:?}", call_ids); + let call = OpaqueCall::from_tuple(&(call_ids, collateral_data, data_signature, issuer_chain)); + + let xt = create_extrinsics(call)?; + write_slice_and_whitespace_pad(extrinsic_slice, xt.encode()) + .map_err(|e| format!("{:?}", e).into()) +} + +#[no_mangle] +pub extern "C" fn dump_ias_ra_cert_to_disk() -> sgx_status_t { + let attestation_handler = match GLOBAL_ATTESTATION_HANDLER_COMPONENT.get() { + Ok(r) => r, + Err(e) => { + error!("Component get failure: {:?}", e); + return sgx_status_t::SGX_ERROR_UNEXPECTED + }, + }; + match attestation_handler.dump_ias_ra_cert_to_disk() { + Ok(_) => sgx_status_t::SGX_SUCCESS, + Err(e) => e.into(), + } +} + +#[no_mangle] +pub unsafe extern "C" fn dump_dcap_ra_cert_to_disk( + quoting_enclave_target_info: &sgx_target_info_t, + quote_size: u32, +) -> sgx_status_t { + let attestation_handler = match GLOBAL_ATTESTATION_HANDLER_COMPONENT.get() { + Ok(r) => r, + Err(e) => { + error!("Component get failure: {:?}", e); + return sgx_status_t::SGX_ERROR_UNEXPECTED + }, + }; + match attestation_handler.dump_dcap_ra_cert_to_disk(quoting_enclave_target_info, quote_size) { + Ok(_) => sgx_status_t::SGX_SUCCESS, + Err(e) => e.into(), + } +} + +#[no_mangle] +pub unsafe extern "C" fn dump_dcap_collateral_to_disk( + collateral: *const sgx_ql_qve_collateral_t, +) -> sgx_status_t { + let collateral = SgxQlQveCollateral::from_c_type(&*collateral); + collateral.dump_to_disk(); + sgx_status_t::SGX_SUCCESS +} + +fn get_shielding_pubkey() -> EnclaveResult>> { + let shielding_pubkey = GLOBAL_SHIELDING_KEY_REPOSITORY_COMPONENT + .get()? + .retrieve_key() + .and_then(|keypair| { + keypair + .export_pubkey() + .and_then(|pubkey| { + serde_json::to_vec(&pubkey).map_err(|e| SgxCryptoError::Serialization(e).into()) + }) + .map_err(|e| SgxCryptoError::Other(Box::new(e))) + }) + .ok(); + + debug!("[Enclave] shielding_pubkey size: {:?}", shielding_pubkey.clone().map(|key| key.len())); + + Ok(shielding_pubkey) +} + +fn get_vc_pubkey() -> EnclaveResult>> { + let vc_pubkey = GLOBAL_SHIELDING_KEY_REPOSITORY_COMPONENT + .get()? + .retrieve_key() + .and_then(|keypair| { + // vc signing pubkey + keypair.derive_ed25519().map(|keypair| keypair.public().to_vec()) + }) + .ok(); + + debug!("[Enclave] VC pubkey: {:?}", vc_pubkey); + + Ok(vc_pubkey) +} diff --git a/bitacross-worker/enclave-runtime/src/empty_impls.rs b/bitacross-worker/enclave-runtime/src/empty_impls.rs new file mode 100644 index 0000000000..e401fa8d05 --- /dev/null +++ b/bitacross-worker/enclave-runtime/src/empty_impls.rs @@ -0,0 +1,56 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +/// Empty tests entry for production mode. +#[cfg(not(feature = "test"))] +#[no_mangle] +#[allow(clippy::unreachable)] +pub extern "C" fn test_main_entrance() -> sgx_types::size_t { + unreachable!("Tests are not available when compiled in production mode.") +} + +/// Empty Teeracle market data implementation. +#[cfg(not(feature = "teeracle"))] +#[no_mangle] +#[allow(clippy::unreachable)] +pub unsafe extern "C" fn update_market_data_xt( + _crypto_currency_ptr: *const u8, + _crypto_currency_size: u32, + _fiat_currency_ptr: *const u8, + _fiat_currency_size: u32, + _unchecked_extrinsic: *mut u8, + _unchecked_extrinsic_max_size: u32, + _unchecked_extrinsic_size: *mut u32, +) -> sgx_types::sgx_status_t { + unreachable!("Cannot update market data, teeracle feature is not enabled.") +} + +/// Empty Teeracle Weather data implementation. +#[cfg(not(feature = "teeracle"))] +#[no_mangle] +#[allow(clippy::unreachable)] +pub unsafe extern "C" fn update_weather_data_xt( + _weather_info_longitude: *const u8, + _weather_info_longitude_size: u32, + _weather_info_latitude: *const u8, + _weather_info_latitude_size: u32, + _unchecked_extrinsic: *mut u8, + _unchecked_extrinsic_max_size: u32, + _unchecked_extrinsic_size: *mut u32, +) -> sgx_types::sgx_status_t { + unreachable!("Cannot update weather data, teeracle feature is not enabled.") +} diff --git a/bitacross-worker/enclave-runtime/src/error.rs b/bitacross-worker/enclave-runtime/src/error.rs new file mode 100644 index 0000000000..da657f87de --- /dev/null +++ b/bitacross-worker/enclave-runtime/src/error.rs @@ -0,0 +1,87 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 derive_more::From; +use sgx_types::{sgx_quote3_error_t, sgx_status_t}; +use std::{boxed::Box, result::Result as StdResult, string::String}; + +pub type Result = StdResult; + +#[derive(Debug, From)] +pub enum Error { + TopPoolAuthor(itp_top_pool_author::error::Error), + Codec(codec::Error), + ComponentContainer(itp_component_container::error::Error), + Crypto(itp_sgx_crypto::Error), + ChainStorage(itp_ocall_api::Error), + ExtrinsicsFactory(itp_extrinsics_factory::error::Error), + IO(std::io::Error), + LightClient(itc_parentchain::light_client::error::Error), + NodeMetadataProvider(itp_node_api::metadata::provider::Error), + Sgx(sgx_status_t), + SgxQuote(sgx_quote3_error_t), + Consensus(its_sidechain::consensus_common::Error), + Stf(String), + StfStateHandler(itp_stf_state_handler::error::Error), + StfExecution(itp_stf_executor::error::Error), + ParentchainBlockImportDispatch(itc_parentchain::block_import_dispatcher::error::Error), + ExpectedTriggeredImportDispatcher, + CouldNotDispatchBlockImport, + NoLitentryParentchainAssigned, + NoTargetAParentchainAssigned, + NoTargetBParentchainAssigned, + ParentChainValidation(itp_storage::error::Error), + ParentChainSync, + PrimitivesAccess(itp_primitives_cache::error::Error), + MutexAccess, + Attestation(itp_attestation_handler::error::Error), + Metadata(itp_node_api_metadata::error::Error), + BufferError(itp_utils::buffer::BufferError), + Other(Box), +} + +impl From for sgx_status_t { + /// return sgx_status for top level enclave functions + fn from(error: Error) -> sgx_status_t { + match error { + Error::Sgx(status) => status, + _ => { + log::error!("Returning error {:?} as sgx unexpected.", error); + sgx_status_t::SGX_ERROR_UNEXPECTED + }, + } + } +} + +impl From for sgx_quote3_error_t { + /// return sgx_quote error + fn from(error: Error) -> sgx_quote3_error_t { + match error { + Error::SgxQuote(status) => status, + _ => { + log::error!("Returning error {:?} as sgx unexpected.", error); + sgx_quote3_error_t::SGX_QL_ERROR_UNEXPECTED + }, + } + } +} + +impl From for StdResult { + fn from(error: Error) -> StdResult { + Err(error) + } +} diff --git a/bitacross-worker/enclave-runtime/src/initialization/global_components.rs b/bitacross-worker/enclave-runtime/src/initialization/global_components.rs new file mode 100644 index 0000000000..8f45ddcc7f --- /dev/null +++ b/bitacross-worker/enclave-runtime/src/initialization/global_components.rs @@ -0,0 +1,501 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +//! Defines all concrete types and global components of the enclave. +//! +//! This allows the crates themselves to stay as generic as possible +//! and ensures that the global instances are initialized once. +use crate::{ + initialization::parentchain::{ + integritee_parachain::IntegriteeParachainHandler, + integritee_solochain::IntegriteeSolochainHandler, + target_a_parachain::TargetAParachainHandler, target_a_solochain::TargetASolochainHandler, + target_b_parachain::TargetBParachainHandler, target_b_solochain::TargetBSolochainHandler, + }, + ocall::OcallApi, + rpc::rpc_response_channel::RpcResponseChannel, + tls_ra::seal_handler::SealHandler, +}; +use ita_parentchain_interface::{integritee, target_a, target_b}; +use ita_sgx_runtime::Runtime; +use ita_stf::{Getter, State as StfState, Stf, TrustedCallSigned}; +use itc_direct_rpc_client::DirectRpcClientFactory; +use itc_direct_rpc_server::{ + rpc_connection_registry::ConnectionRegistry, rpc_responder::RpcResponder, + rpc_watch_extractor::RpcWatchExtractor, rpc_ws_handler::RpcWsHandler, +}; +use itc_parentchain::{ + block_import_dispatcher::{ + immediate_dispatcher::ImmediateDispatcher, triggered_dispatcher::TriggeredDispatcher, + BlockImportDispatcher, + }, + block_importer::ParentchainBlockImporter, + indirect_calls_executor::{filter_metadata::EventCreator, IndirectCallsExecutor}, + light_client::{ + concurrent_access::ValidatorAccessor, io::LightClientStateSealSync, + light_validation::LightValidation, light_validation_state::LightValidationState, + }, +}; +use itc_peer_top_broadcaster::DirectRpcBroadcaster; +use itc_tls_websocket_server::{ + config_provider::FromFileConfigProvider, ws_server::TungsteniteWsServer, ConnectionToken, +}; +use itp_attestation_handler::IntelAttestationHandler; +use itp_component_container::ComponentContainer; +use itp_extrinsics_factory::ExtrinsicsFactory; +use itp_import_queue::ImportQueue; +use itp_node_api::{ + api_client::PairSignature, + metadata::{provider::NodeMetadataRepository, NodeMetadata}, +}; +use itp_nonce_cache::NonceCache; +use itp_sgx_crypto::{key_repository::KeyRepository, Aes, AesSeal, Ed25519Seal, Rsa3072Seal}; +use itp_stf_executor::{ + enclave_signer::StfEnclaveSigner, executor::StfExecutor, getter_executor::GetterExecutor, + state_getter::StfStateGetter, +}; +use itp_stf_primitives::types::{Hash, TrustedOperation}; +use itp_stf_state_handler::{ + file_io::sgx::SgxStateFileIo, state_initializer::StateInitializer, + state_snapshot_repository::StateSnapshotRepository, StateHandler, +}; +use itp_stf_state_observer::state_observer::StateObserver; +use itp_top_pool::basic_pool::BasicPool; +use itp_top_pool_author::{ + api::SidechainApi, + author::{Author, AuthorTopFilter, BroadcastedTopFilter}, +}; +use itp_types::{Block as ParentchainBlock, SignedBlock as SignedParentchainBlock}; +use its_primitives::{ + traits::{Block as SidechainBlockTrait, SignedBlock as SignedSidechainBlockTrait}, + types::block::SignedBlock as SignedSidechainBlock, +}; +use its_sidechain::{ + aura::block_importer::BlockImporter as SidechainBlockImporter, + block_composer::BlockComposer, + consensus_common::{BlockImportConfirmationHandler, BlockImportQueueWorker, PeerBlockSync}, + slots::FailSlotOnDemand, +}; +use lazy_static::lazy_static; +use litentry_primitives::BroadcastedRequest; +use sgx_crypto_helper::rsa3072::Rsa3072KeyPair; +use sgx_tstd::vec::Vec; +use sp_core::{ed25519, ed25519::Pair}; +use std::sync::Arc; + +pub type EnclaveParentchainSigner = + itp_node_api::api_client::StaticExtrinsicSigner; + +pub type EnclaveGetter = Getter; +pub type EnclaveTrustedCallSigned = TrustedCallSigned; +pub type EnclaveStf = Stf; +pub type EnclaveStateKeyRepository = KeyRepository; +pub type EnclaveShieldingKeyRepository = KeyRepository; +pub type EnclaveSigningKeyRepository = KeyRepository; +pub type EnclaveStateFileIo = SgxStateFileIo; +pub type EnclaveStateSnapshotRepository = StateSnapshotRepository; +pub type EnclaveStateObserver = StateObserver; +pub type EnclaveStateInitializer = + StateInitializer; +pub type EnclaveStateHandler = + StateHandler; +pub type EnclaveGetterExecutor = + GetterExecutor, Getter>; +pub type EnclaveOCallApi = OcallApi; +pub type EnclaveNodeMetadataRepository = NodeMetadataRepository; +pub type EnclaveStfExecutor = StfExecutor< + EnclaveOCallApi, + EnclaveStateHandler, + EnclaveNodeMetadataRepository, + EnclaveStf, + EnclaveTrustedCallSigned, + EnclaveGetter, +>; +pub type EnclaveStfEnclaveSigner = StfEnclaveSigner< + EnclaveOCallApi, + EnclaveStateObserver, + EnclaveShieldingKeyRepository, + EnclaveStf, + EnclaveTopPoolAuthor, + EnclaveTrustedCallSigned, + EnclaveGetter, +>; +pub type EnclaveAttestationHandler = + IntelAttestationHandler; + +pub type EnclaveRpcConnectionRegistry = ConnectionRegistry; +pub type EnclaveRpcWsHandler = + RpcWsHandler, EnclaveRpcConnectionRegistry, Hash>; +pub type EnclaveWebSocketServer = TungsteniteWsServer; +pub type EnclaveRpcResponder = RpcResponder; +pub type EnclaveSidechainApi = SidechainApi; + +// Parentchain types relevant for all parentchains +pub type EnclaveLightClientSeal = + LightClientStateSealSync>; +pub type EnclaveExtrinsicsFactory = + ExtrinsicsFactory; + +pub type EnclaveValidatorAccessor = ValidatorAccessor< + LightValidation, + ParentchainBlock, + EnclaveLightClientSeal, +>; + +pub type IntegriteeParentchainBlockImportQueue = ImportQueue; +pub type TargetAParentchainBlockImportQueue = ImportQueue; +pub type TargetBParentchainBlockImportQueue = ImportQueue; + +/// Import queue for the events +/// +/// Note: `Vec` is correct. It should not be `Vec` +pub type IntegriteeParentchainEventImportQueue = ImportQueue>; +pub type TargetAParentchainEventImportQueue = ImportQueue>; +pub type TargetBParentchainEventImportQueue = ImportQueue>; + +// Stuff for the integritee parentchain + +pub type IntegriteeParentchainIndirectCallsExecutor = IndirectCallsExecutor< + EnclaveShieldingKeyRepository, + EnclaveStfEnclaveSigner, + EnclaveTopPoolAuthor, + EnclaveNodeMetadataRepository, + integritee::ShieldFundsAndInvokeFilter, + EventCreator, + integritee::ParentchainEventHandler, + EnclaveTrustedCallSigned, + EnclaveGetter, +>; + +pub type IntegriteeParentchainBlockImporter = ParentchainBlockImporter< + ParentchainBlock, + EnclaveValidatorAccessor, + EnclaveStfExecutor, + EnclaveExtrinsicsFactory, + IntegriteeParentchainIndirectCallsExecutor, + EnclaveOCallApi, +>; + +pub type IntegriteeParentchainTriggeredBlockImportDispatcher = TriggeredDispatcher< + IntegriteeParentchainBlockImporter, + IntegriteeParentchainBlockImportQueue, + IntegriteeParentchainEventImportQueue, +>; + +pub type IntegriteeParentchainImmediateBlockImportDispatcher = + ImmediateDispatcher; + +pub type IntegriteeParentchainBlockImportDispatcher = BlockImportDispatcher< + IntegriteeParentchainTriggeredBlockImportDispatcher, + IntegriteeParentchainImmediateBlockImportDispatcher, +>; + +// Stuff for the Target A parentchain + +/// IndirectCalls executor instance of the Target A parentchain. +/// +/// **Note**: The filter here is purely used for demo purposes. +/// +/// Also note that the extrinsic parser must be changed if the signed extra contains the +/// `AssetTxPayment`. +pub type TargetAParentchainIndirectCallsExecutor = IndirectCallsExecutor< + EnclaveShieldingKeyRepository, + EnclaveStfEnclaveSigner, + EnclaveTopPoolAuthor, + EnclaveNodeMetadataRepository, + target_a::TransferToAliceShieldsFundsFilter, + EventCreator, + target_a::ParentchainEventHandler, + EnclaveTrustedCallSigned, + EnclaveGetter, +>; + +pub type TargetAParentchainBlockImporter = ParentchainBlockImporter< + ParentchainBlock, + EnclaveValidatorAccessor, + EnclaveStfExecutor, + EnclaveExtrinsicsFactory, + TargetAParentchainIndirectCallsExecutor, + EnclaveOCallApi, +>; + +pub type TargetAParentchainTriggeredBlockImportDispatcher = TriggeredDispatcher< + TargetAParentchainBlockImporter, + TargetAParentchainBlockImportQueue, + TargetAParentchainEventImportQueue, +>; + +pub type TargetAParentchainImmediateBlockImportDispatcher = + ImmediateDispatcher; + +pub type TargetAParentchainBlockImportDispatcher = BlockImportDispatcher< + TargetAParentchainTriggeredBlockImportDispatcher, + TargetAParentchainImmediateBlockImportDispatcher, +>; + +// Stuff for the Target B parentchain + +/// IndirectCalls executor instance of the Target B parentchain. +/// +/// **Note**: The filter here is purely used for demo purposes. +/// +/// Also note that the extrinsic parser must be changed if the signed extra contains the +/// `AssetTxPayment`. +pub type TargetBParentchainIndirectCallsExecutor = IndirectCallsExecutor< + EnclaveShieldingKeyRepository, + EnclaveStfEnclaveSigner, + EnclaveTopPoolAuthor, + EnclaveNodeMetadataRepository, + target_b::TargetBExtrinsicFilter, + EventCreator, + target_b::ParentchainEventHandler, + EnclaveTrustedCallSigned, + EnclaveGetter, +>; + +pub type TargetBParentchainBlockImporter = ParentchainBlockImporter< + ParentchainBlock, + EnclaveValidatorAccessor, + EnclaveStfExecutor, + EnclaveExtrinsicsFactory, + TargetBParentchainIndirectCallsExecutor, + EnclaveOCallApi, +>; + +pub type TargetBParentchainTriggeredBlockImportDispatcher = TriggeredDispatcher< + TargetBParentchainBlockImporter, + TargetBParentchainBlockImportQueue, + TargetBParentchainEventImportQueue, +>; + +pub type TargetBParentchainImmediateBlockImportDispatcher = + ImmediateDispatcher; + +pub type TargetBParentchainBlockImportDispatcher = BlockImportDispatcher< + TargetBParentchainTriggeredBlockImportDispatcher, + TargetBParentchainImmediateBlockImportDispatcher, +>; + +/// Sidechain types +pub type EnclaveTopPool = BasicPool< + EnclaveSidechainApi, + ParentchainBlock, + EnclaveRpcResponder, + TrustedOperation, +>; + +pub type EnclaveTopPoolAuthor = Author< + EnclaveTopPool, + AuthorTopFilter, + BroadcastedTopFilter, + EnclaveStateHandler, + EnclaveShieldingKeyRepository, + EnclaveOCallApi, + EnclaveTrustedCallSigned, + EnclaveGetter, +>; +pub type EnclaveDirectRpcBroadcaster = DirectRpcBroadcaster; +pub type EnclaveSidechainBlockComposer = + BlockComposer; +pub type EnclaveSidechainBlockImporter = SidechainBlockImporter< + Pair, + ParentchainBlock, + SignedSidechainBlock, + EnclaveOCallApi, + EnclaveStateHandler, + EnclaveStateKeyRepository, + EnclaveTopPoolAuthor, + // For now the sidechain does only support one parentchain. + IntegriteeParentchainTriggeredBlockImportDispatcher, + EnclaveDirectRpcBroadcaster, + EnclaveTrustedCallSigned, + EnclaveGetter, +>; +pub type EnclaveSidechainBlockImportQueue = ImportQueue; +pub type EnclaveBlockImportConfirmationHandler = BlockImportConfirmationHandler< + ParentchainBlock, + <::Block as SidechainBlockTrait>::HeaderType, + EnclaveNodeMetadataRepository, + EnclaveExtrinsicsFactory, + EnclaveValidatorAccessor, +>; +pub type EnclaveSidechainBlockSyncer = PeerBlockSync< + ParentchainBlock, + SignedSidechainBlock, + EnclaveSidechainBlockImporter, + EnclaveOCallApi, + EnclaveBlockImportConfirmationHandler, +>; +pub type EnclaveSidechainBlockImportQueueWorker = BlockImportQueueWorker< + ParentchainBlock, + SignedSidechainBlock, + EnclaveSidechainBlockImportQueue, + EnclaveSidechainBlockSyncer, +>; +pub type EnclaveSealHandler = SealHandler< + EnclaveShieldingKeyRepository, + EnclaveStateKeyRepository, + EnclaveStateHandler, + EnclaveLightClientSeal, +>; +pub type EnclaveOffchainWorkerExecutor = itc_offchain_worker_executor::executor::Executor< + ParentchainBlock, + EnclaveTopPoolAuthor, + EnclaveStfExecutor, + EnclaveStateHandler, + EnclaveValidatorAccessor, + EnclaveExtrinsicsFactory, + EnclaveStf, + EnclaveTrustedCallSigned, + EnclaveGetter, +>; + +// Base component instances +//------------------------------------------------------------------------------------------------- + +/// State key repository +pub static GLOBAL_STATE_KEY_REPOSITORY_COMPONENT: ComponentContainer = + ComponentContainer::new("State key repository"); + +/// Shielding key repository +pub static GLOBAL_SHIELDING_KEY_REPOSITORY_COMPONENT: ComponentContainer< + EnclaveShieldingKeyRepository, +> = ComponentContainer::new("Shielding key repository"); + +/// Signing key repository +pub static GLOBAL_SIGNING_KEY_REPOSITORY_COMPONENT: ComponentContainer< + EnclaveSigningKeyRepository, +> = ComponentContainer::new("Signing key repository"); + +/// Light client db seal for the Integritee parentchain +pub static GLOBAL_INTEGRITEE_PARENTCHAIN_LIGHT_CLIENT_SEAL: ComponentContainer< + EnclaveLightClientSeal, +> = ComponentContainer::new("Integritee Parentchain EnclaveLightClientSealSync"); + +/// Light client db seal for the Target A parentchain. +pub static GLOBAL_TARGET_A_PARENTCHAIN_LIGHT_CLIENT_SEAL: ComponentContainer< + EnclaveLightClientSeal, +> = ComponentContainer::new("Target A EnclaveLightClientSealSync"); + +/// Light client db seal for the Target A parentchain. +pub static GLOBAL_TARGET_B_PARENTCHAIN_LIGHT_CLIENT_SEAL: ComponentContainer< + EnclaveLightClientSeal, +> = ComponentContainer::new("Target B EnclaveLightClientSealSync"); + +/// O-Call API +pub static GLOBAL_OCALL_API_COMPONENT: ComponentContainer = + ComponentContainer::new("O-call API"); + +/// Trusted Web-socket server +pub static GLOBAL_WEB_SOCKET_SERVER_COMPONENT: ComponentContainer = + ComponentContainer::new("Web-socket server"); + +/// State handler. +pub static GLOBAL_STATE_HANDLER_COMPONENT: ComponentContainer = + ComponentContainer::new("state handler"); + +/// State observer. +pub static GLOBAL_STATE_OBSERVER_COMPONENT: ComponentContainer = + ComponentContainer::new("state observer"); + +/// TOP pool author. +pub static GLOBAL_TOP_POOL_AUTHOR_COMPONENT: ComponentContainer = + ComponentContainer::new("top_pool_author"); + +/// Direct RPC broadcaster +pub static GLOBAL_DIRECT_RPC_BROADCASTER_COMPONENT: ComponentContainer< + EnclaveDirectRpcBroadcaster, +> = ComponentContainer::new("direct_rpc_broadcaster"); + +pub static DIRECT_RPC_REQUEST_SINK_COMPONENT: ComponentContainer< + sgx_tstd::sync::mpsc::SyncSender, +> = ComponentContainer::new("direct_rpc_request_sink"); + +/// attestation handler +pub static GLOBAL_ATTESTATION_HANDLER_COMPONENT: ComponentContainer = + ComponentContainer::new("Attestation handler"); + +// Parentchain component instances +//------------------------------------------------------------------------------------------------- + +lazy_static! { + /// Global nonce cache for the Integritee Parentchain. + pub static ref GLOBAL_INTEGRITEE_PARENTCHAIN_NONCE_CACHE: Arc = Default::default(); + + /// Global nonce cache for the Target A parentchain.. + pub static ref GLOBAL_TARGET_A_PARENTCHAIN_NONCE_CACHE: Arc = Default::default(); + + /// Global nonce cache for the Target B parentchain.. + pub static ref GLOBAL_TARGET_B_PARENTCHAIN_NONCE_CACHE: Arc = Default::default(); +} + +/// Solochain Handler. +pub static GLOBAL_INTEGRITEE_SOLOCHAIN_HANDLER_COMPONENT: ComponentContainer< + IntegriteeSolochainHandler, +> = ComponentContainer::new("integritee solochain handler"); + +pub static GLOBAL_INTEGRITEE_PARACHAIN_HANDLER_COMPONENT: ComponentContainer< + IntegriteeParachainHandler, +> = ComponentContainer::new("integritee parachain handler"); + +pub static GLOBAL_TARGET_A_SOLOCHAIN_HANDLER_COMPONENT: ComponentContainer< + TargetASolochainHandler, +> = ComponentContainer::new("target A solochain handler"); + +pub static GLOBAL_TARGET_A_PARACHAIN_HANDLER_COMPONENT: ComponentContainer< + TargetAParachainHandler, +> = ComponentContainer::new("target A parachain handler"); + +pub static GLOBAL_TARGET_B_SOLOCHAIN_HANDLER_COMPONENT: ComponentContainer< + TargetBSolochainHandler, +> = ComponentContainer::new("target B solochain handler"); + +pub static GLOBAL_TARGET_B_PARACHAIN_HANDLER_COMPONENT: ComponentContainer< + TargetBParachainHandler, +> = ComponentContainer::new("target B parachain handler"); + +// Sidechain component instances +//------------------------------------------------------------------------------------------------- + +/// Enclave RPC WS handler. +pub static GLOBAL_RPC_WS_HANDLER_COMPONENT: ComponentContainer = + ComponentContainer::new("rpc_ws_handler"); + +/// Sidechain import queue. +pub static GLOBAL_SIDECHAIN_IMPORT_QUEUE_COMPONENT: ComponentContainer< + EnclaveSidechainBlockImportQueue, +> = ComponentContainer::new("sidechain_import_queue"); + +/// Sidechain import queue worker - processes the import queue. +pub static GLOBAL_SIDECHAIN_IMPORT_QUEUE_WORKER_COMPONENT: ComponentContainer< + EnclaveSidechainBlockImportQueueWorker, +> = ComponentContainer::new("sidechain_import_queue_worker"); + +/// Sidechain block composer. +pub static GLOBAL_SIDECHAIN_BLOCK_COMPOSER_COMPONENT: ComponentContainer< + EnclaveSidechainBlockComposer, +> = ComponentContainer::new("sidechain_block_composer"); + +/// Sidechain block syncer. +pub static GLOBAL_SIDECHAIN_BLOCK_SYNCER_COMPONENT: ComponentContainer< + EnclaveSidechainBlockSyncer, +> = ComponentContainer::new("sidechain_block_syncer"); + +/// Sidechain fail slot on demand. +pub static GLOBAL_SIDECHAIN_FAIL_SLOT_ON_DEMAND_COMPONENT: ComponentContainer< + Option, +> = ComponentContainer::new("sidechain_fail_slot_on_demand"); diff --git a/bitacross-worker/enclave-runtime/src/initialization/mod.rs b/bitacross-worker/enclave-runtime/src/initialization/mod.rs new file mode 100644 index 0000000000..1510341a61 --- /dev/null +++ b/bitacross-worker/enclave-runtime/src/initialization/mod.rs @@ -0,0 +1,366 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 global_components; +pub mod parentchain; +use crate::{ + error::{Error, Result as EnclaveResult}, + initialization::global_components::{ + EnclaveBlockImportConfirmationHandler, EnclaveGetterExecutor, EnclaveLightClientSeal, + EnclaveOCallApi, EnclaveRpcResponder, EnclaveShieldingKeyRepository, EnclaveSidechainApi, + EnclaveSidechainBlockImportQueue, EnclaveSidechainBlockImportQueueWorker, + EnclaveSidechainBlockImporter, EnclaveSidechainBlockSyncer, EnclaveStateFileIo, + EnclaveStateHandler, EnclaveStateInitializer, EnclaveStateObserver, + EnclaveStateSnapshotRepository, EnclaveStfEnclaveSigner, EnclaveTopPool, + EnclaveTopPoolAuthor, DIRECT_RPC_REQUEST_SINK_COMPONENT, + GLOBAL_ATTESTATION_HANDLER_COMPONENT, GLOBAL_DIRECT_RPC_BROADCASTER_COMPONENT, + GLOBAL_INTEGRITEE_PARENTCHAIN_LIGHT_CLIENT_SEAL, GLOBAL_OCALL_API_COMPONENT, + GLOBAL_RPC_WS_HANDLER_COMPONENT, GLOBAL_SHIELDING_KEY_REPOSITORY_COMPONENT, + GLOBAL_SIDECHAIN_BLOCK_COMPOSER_COMPONENT, GLOBAL_SIDECHAIN_BLOCK_SYNCER_COMPONENT, + GLOBAL_SIDECHAIN_FAIL_SLOT_ON_DEMAND_COMPONENT, GLOBAL_SIDECHAIN_IMPORT_QUEUE_COMPONENT, + GLOBAL_SIDECHAIN_IMPORT_QUEUE_WORKER_COMPONENT, GLOBAL_SIGNING_KEY_REPOSITORY_COMPONENT, + GLOBAL_STATE_HANDLER_COMPONENT, GLOBAL_STATE_KEY_REPOSITORY_COMPONENT, + GLOBAL_STATE_OBSERVER_COMPONENT, GLOBAL_TARGET_A_PARENTCHAIN_LIGHT_CLIENT_SEAL, + GLOBAL_TARGET_B_PARENTCHAIN_LIGHT_CLIENT_SEAL, GLOBAL_TOP_POOL_AUTHOR_COMPONENT, + GLOBAL_WEB_SOCKET_SERVER_COMPONENT, + }, + ocall::OcallApi, + rpc::{rpc_response_channel::RpcResponseChannel, worker_api_direct::public_api_rpc_handler}, + utils::{ + get_extrinsic_factory_from_integritee_solo_or_parachain, + get_node_metadata_repository_from_integritee_solo_or_parachain, + get_triggered_dispatcher_from_integritee_solo_or_parachain, + get_validator_accessor_from_integritee_solo_or_parachain, + }, + Hash, +}; +use base58::ToBase58; +use codec::Encode; +use core::str::FromStr; +use ita_stf::{Getter, TrustedCallSigned}; +use itc_direct_rpc_server::{ + create_determine_watch, rpc_connection_registry::ConnectionRegistry, + rpc_ws_handler::RpcWsHandler, +}; +use itc_peer_top_broadcaster::init; +use itc_tls_websocket_server::{ + certificate_generation::ed25519_self_signed_certificate, create_ws_server, ConnectionToken, + WebSocketServer, +}; +use itp_attestation_handler::{AttestationHandler, IntelAttestationHandler}; +use itp_component_container::{ComponentGetter, ComponentInitializer}; +use itp_primitives_cache::GLOBAL_PRIMITIVES_CACHE; +use itp_settings::files::{ + LITENTRY_PARENTCHAIN_LIGHT_CLIENT_DB_PATH, STATE_SNAPSHOTS_CACHE_SIZE, + TARGET_A_PARENTCHAIN_LIGHT_CLIENT_DB_PATH, TARGET_B_PARENTCHAIN_LIGHT_CLIENT_DB_PATH, +}; +use itp_sgx_crypto::{ + get_aes_repository, get_ed25519_repository, get_rsa3072_repository, key_repository::AccessKey, +}; +use itp_stf_state_handler::{ + file_io::StateDir, handle_state::HandleState, query_shard_state::QueryShardState, + state_snapshot_repository::VersionedStateAccess, + state_snapshot_repository_loader::StateSnapshotRepositoryLoader, StateHandler, +}; +use itp_top_pool::pool::Options as PoolOptions; +use itp_top_pool_author::author::{AuthorTopFilter, BroadcastedTopFilter}; +use itp_types::{parentchain::ParentchainId, ShardIdentifier}; +use its_sidechain::{ + block_composer::BlockComposer, + slots::{FailSlotMode, FailSlotOnDemand}, +}; +use lc_scheduled_enclave::{ScheduledEnclaveUpdater, GLOBAL_SCHEDULED_ENCLAVE}; +use litentry_primitives::BroadcastedRequest; +use log::*; +use sgx_types::sgx_status_t; +use sp_core::crypto::Pair; +use std::{collections::HashMap, path::PathBuf, string::String, sync::Arc}; +pub(crate) fn init_enclave( + mu_ra_url: String, + untrusted_worker_url: String, + base_dir: PathBuf, +) -> EnclaveResult<()> { + let signing_key_repository = Arc::new(get_ed25519_repository(base_dir.clone())?); + GLOBAL_SIGNING_KEY_REPOSITORY_COMPONENT.initialize(signing_key_repository.clone()); + let signer = signing_key_repository.retrieve_key()?; + info!("[Enclave initialized] Ed25519 prim raw : {:?}", signer.public().0); + + let shielding_key_repository = Arc::new(get_rsa3072_repository(base_dir.clone())?); + GLOBAL_SHIELDING_KEY_REPOSITORY_COMPONENT.initialize(shielding_key_repository.clone()); + + // Create the aes key that is used for state encryption such that a key is always present in tests. + // It will be overwritten anyway if mutual remote attestation is performed with the primary worker. + let state_key_repository = Arc::new(get_aes_repository(base_dir.clone())?); + GLOBAL_STATE_KEY_REPOSITORY_COMPONENT.initialize(state_key_repository.clone()); + + let integritee_light_client_seal = Arc::new(EnclaveLightClientSeal::new( + base_dir.join(LITENTRY_PARENTCHAIN_LIGHT_CLIENT_DB_PATH), + ParentchainId::Litentry, + )?); + GLOBAL_INTEGRITEE_PARENTCHAIN_LIGHT_CLIENT_SEAL.initialize(integritee_light_client_seal); + + let target_a_light_client_seal = Arc::new(EnclaveLightClientSeal::new( + base_dir.join(TARGET_A_PARENTCHAIN_LIGHT_CLIENT_DB_PATH), + ParentchainId::TargetA, + )?); + GLOBAL_TARGET_A_PARENTCHAIN_LIGHT_CLIENT_SEAL.initialize(target_a_light_client_seal); + + let target_b_light_client_seal = Arc::new(EnclaveLightClientSeal::new( + base_dir.join(TARGET_B_PARENTCHAIN_LIGHT_CLIENT_DB_PATH), + ParentchainId::TargetB, + )?); + GLOBAL_TARGET_B_PARENTCHAIN_LIGHT_CLIENT_SEAL.initialize(target_b_light_client_seal); + + let state_file_io = + Arc::new(EnclaveStateFileIo::new(state_key_repository, StateDir::new(base_dir))); + let state_initializer = + Arc::new(EnclaveStateInitializer::new(shielding_key_repository.clone())); + let state_snapshot_repository_loader = StateSnapshotRepositoryLoader::< + EnclaveStateFileIo, + EnclaveStateInitializer, + >::new(state_file_io, state_initializer.clone()); + + let state_snapshot_repository = + state_snapshot_repository_loader.load_snapshot_repository(STATE_SNAPSHOTS_CACHE_SIZE)?; + let state_observer = initialize_state_observer(&state_snapshot_repository)?; + GLOBAL_STATE_OBSERVER_COMPONENT.initialize(state_observer.clone()); + + let state_handler = Arc::new(StateHandler::load_from_repository( + state_snapshot_repository, + state_observer.clone(), + state_initializer, + )?); + + GLOBAL_STATE_HANDLER_COMPONENT.initialize(state_handler.clone()); + + let ocall_api = Arc::new(OcallApi); + GLOBAL_OCALL_API_COMPONENT.initialize(ocall_api.clone()); + + // For debug purposes, list shards. no problem to panic if fails. + #[allow(clippy::unwrap_used)] + let shards = state_handler.list_shards().unwrap(); + debug!("found the following {} shards on disk:", shards.len()); + for s in shards { + debug!("{}", s.encode().to_base58()) + } + + itp_primitives_cache::set_primitives( + GLOBAL_PRIMITIVES_CACHE.as_ref(), + mu_ra_url, + untrusted_worker_url, + ) + .map_err(Error::PrimitivesAccess)?; + + let watch_extractor = Arc::new(create_determine_watch::()); + + let connection_registry = Arc::new(ConnectionRegistry::::new()); + + // We initialize components for the public RPC / direct invocation server here, so we can start the server + // before registering on the parentchain. If we started the RPC AFTER registering on the parentchain and + // initializing the light-client, there is a period of time where a peer might want to reach us, + // but the RPC server is not yet up and running, resulting in error messages or even in that + // validateer completely breaking (IO PipeError). + // Corresponding GH issues are #545 and #600. + + let response_channel = Arc::new(RpcResponseChannel::default()); + let rpc_responder = + Arc::new(EnclaveRpcResponder::new(connection_registry.clone(), response_channel)); + + let (request_sink, broadcaster) = init(rpc_responder.clone()); + let request_sink_cloned = request_sink.clone(); + + let top_pool_author = create_top_pool_author( + rpc_responder, + state_handler.clone(), + ocall_api.clone(), + shielding_key_repository.clone(), + request_sink_cloned, + ); + GLOBAL_TOP_POOL_AUTHOR_COMPONENT.initialize(top_pool_author.clone()); + + GLOBAL_DIRECT_RPC_BROADCASTER_COMPONENT.initialize(broadcaster); + DIRECT_RPC_REQUEST_SINK_COMPONENT.initialize(request_sink); + + let getter_executor = Arc::new(EnclaveGetterExecutor::new(state_observer)); + let io_handler = public_api_rpc_handler( + top_pool_author, + getter_executor, + shielding_key_repository, + Some(state_handler), + ); + let rpc_handler = Arc::new(RpcWsHandler::new(io_handler, watch_extractor, connection_registry)); + GLOBAL_RPC_WS_HANDLER_COMPONENT.initialize(rpc_handler); + + let sidechain_block_import_queue = Arc::new(EnclaveSidechainBlockImportQueue::default()); + GLOBAL_SIDECHAIN_IMPORT_QUEUE_COMPONENT.initialize(sidechain_block_import_queue); + + let attestation_handler = + Arc::new(IntelAttestationHandler::new(ocall_api, signing_key_repository)); + GLOBAL_ATTESTATION_HANDLER_COMPONENT.initialize(attestation_handler); + + Ok(()) +} + +fn initialize_state_observer( + snapshot_repository: &EnclaveStateSnapshotRepository, +) -> EnclaveResult> { + let shards = snapshot_repository.list_shards()?; + let mut states_map = HashMap::< + ShardIdentifier, + ::StateType, + >::new(); + for shard in shards.into_iter() { + let state = snapshot_repository.load_latest(&shard)?; + states_map.insert(shard, state); + } + Ok(Arc::new(EnclaveStateObserver::from_map(states_map))) +} + +pub(crate) fn init_enclave_sidechain_components( + fail_mode: Option, + fail_at: u64, +) -> EnclaveResult<()> { + let state_handler = GLOBAL_STATE_HANDLER_COMPONENT.get()?; + let ocall_api = GLOBAL_OCALL_API_COMPONENT.get()?; + let direct_rpc_broadcaster = GLOBAL_DIRECT_RPC_BROADCASTER_COMPONENT.get()?; + + let top_pool_author = GLOBAL_TOP_POOL_AUTHOR_COMPONENT.get()?; + let state_key_repository = GLOBAL_STATE_KEY_REPOSITORY_COMPONENT.get()?; + + // GLOBAL_SCHEDULED_ENCLAVE must be initialized after attestation_handler and enclave + let attestation_handler = GLOBAL_ATTESTATION_HANDLER_COMPONENT.get()?; + let mrenclave = attestation_handler.get_mrenclave()?; + GLOBAL_SCHEDULED_ENCLAVE.init(mrenclave).map_err(|e| Error::Other(e.into()))?; + + let parentchain_block_import_dispatcher = + get_triggered_dispatcher_from_integritee_solo_or_parachain()?; + + let signer = GLOBAL_SIGNING_KEY_REPOSITORY_COMPONENT.get()?.retrieve_key()?; + + let sidechain_block_importer = Arc::new(EnclaveSidechainBlockImporter::new( + state_handler, + state_key_repository.clone(), + top_pool_author, + parentchain_block_import_dispatcher, + ocall_api.clone(), + direct_rpc_broadcaster, + )); + + let sidechain_block_import_queue = GLOBAL_SIDECHAIN_IMPORT_QUEUE_COMPONENT.get()?; + let metadata_repository = get_node_metadata_repository_from_integritee_solo_or_parachain()?; + let extrinsics_factory = get_extrinsic_factory_from_integritee_solo_or_parachain()?; + let validator_accessor = get_validator_accessor_from_integritee_solo_or_parachain()?; + + let sidechain_block_import_confirmation_handler = + Arc::new(EnclaveBlockImportConfirmationHandler::new( + metadata_repository, + extrinsics_factory, + validator_accessor, + )); + + let sidechain_block_syncer = Arc::new(EnclaveSidechainBlockSyncer::new( + sidechain_block_importer, + ocall_api, + sidechain_block_import_confirmation_handler, + )); + GLOBAL_SIDECHAIN_BLOCK_SYNCER_COMPONENT.initialize(sidechain_block_syncer.clone()); + + let sidechain_block_import_queue_worker = + Arc::new(EnclaveSidechainBlockImportQueueWorker::new( + sidechain_block_import_queue, + sidechain_block_syncer, + )); + GLOBAL_SIDECHAIN_IMPORT_QUEUE_WORKER_COMPONENT.initialize(sidechain_block_import_queue_worker); + + let block_composer = Arc::new(BlockComposer::new(signer, state_key_repository)); + GLOBAL_SIDECHAIN_BLOCK_COMPOSER_COMPONENT.initialize(block_composer); + if let Some(fail_mode) = fail_mode { + let fail_mode = FailSlotMode::from_str(&fail_mode) + .map_err(|_| Error::Sgx(sgx_status_t::SGX_ERROR_UNEXPECTED))?; + let fail_on_demand = Arc::new(Some(FailSlotOnDemand::new(fail_at, fail_mode))); + GLOBAL_SIDECHAIN_FAIL_SLOT_ON_DEMAND_COMPONENT.initialize(fail_on_demand); + } else { + GLOBAL_SIDECHAIN_FAIL_SLOT_ON_DEMAND_COMPONENT.initialize(Arc::new(None)); + } + + Ok(()) +} + +pub(crate) fn init_direct_invocation_server(server_addr: String) -> EnclaveResult<()> { + let rpc_handler = GLOBAL_RPC_WS_HANDLER_COMPONENT.get()?; + let signer = GLOBAL_SIGNING_KEY_REPOSITORY_COMPONENT.get()?.retrieve_key()?; + + let cert = + ed25519_self_signed_certificate(signer, "Enclave").map_err(|e| Error::Other(e.into()))?; + + // Serialize certificate(s) and private key to PEM. + // PEM format is needed as a certificate chain can only be serialized into PEM. + let pem_serialized = cert.serialize_pem().map_err(|e| Error::Other(e.into()))?; + let private_key = cert.serialize_private_key_pem(); + + let web_socket_server = + create_ws_server(server_addr.as_str(), &private_key, &pem_serialized, rpc_handler); + + GLOBAL_WEB_SOCKET_SERVER_COMPONENT.initialize(web_socket_server.clone()); + + match web_socket_server.run() { + Ok(()) => {}, + Err(e) => { + error!("Web socket server encountered an unexpected error: {:?}", e) + }, + } + + Ok(()) +} + +pub(crate) fn init_shard(shard: ShardIdentifier) -> EnclaveResult<()> { + let state_handler = GLOBAL_STATE_HANDLER_COMPONENT.get()?; + let _ = state_handler.initialize_shard(shard)?; + Ok(()) +} + +pub(crate) fn migrate_shard( + old_shard: ShardIdentifier, + new_shard: ShardIdentifier, +) -> EnclaveResult<()> { + let state_handler = GLOBAL_STATE_HANDLER_COMPONENT.get()?; + let _ = state_handler.migrate_shard(old_shard, new_shard)?; + Ok(()) +} + +/// Initialize the TOP pool author component. +pub fn create_top_pool_author( + rpc_responder: Arc, + state_handler: Arc, + ocall_api: Arc, + shielding_key_repository: Arc, + requests_sink: Arc>, +) -> Arc { + let side_chain_api = Arc::new(EnclaveSidechainApi::new()); + let top_pool = + Arc::new(EnclaveTopPool::create(PoolOptions::default(), side_chain_api, rpc_responder)); + + Arc::new(EnclaveTopPoolAuthor::new( + top_pool, + AuthorTopFilter::::new(), + BroadcastedTopFilter::::new(), + state_handler, + shielding_key_repository, + ocall_api, + requests_sink, + )) +} diff --git a/bitacross-worker/enclave-runtime/src/initialization/parentchain/common.rs b/bitacross-worker/enclave-runtime/src/initialization/parentchain/common.rs new file mode 100644 index 0000000000..7db3228214 --- /dev/null +++ b/bitacross-worker/enclave-runtime/src/initialization/parentchain/common.rs @@ -0,0 +1,297 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{ + error::Result, + initialization::{ + global_components::{ + EnclaveExtrinsicsFactory, EnclaveNodeMetadataRepository, EnclaveOffchainWorkerExecutor, + EnclaveParentchainSigner, EnclaveStfExecutor, EnclaveValidatorAccessor, + IntegriteeParentchainBlockImportDispatcher, IntegriteeParentchainBlockImportQueue, + IntegriteeParentchainBlockImporter, IntegriteeParentchainEventImportQueue, + IntegriteeParentchainImmediateBlockImportDispatcher, + IntegriteeParentchainIndirectCallsExecutor, + IntegriteeParentchainTriggeredBlockImportDispatcher, + TargetAParentchainBlockImportDispatcher, TargetAParentchainBlockImportQueue, + TargetAParentchainBlockImporter, TargetAParentchainEventImportQueue, + TargetAParentchainImmediateBlockImportDispatcher, + TargetAParentchainIndirectCallsExecutor, + TargetAParentchainTriggeredBlockImportDispatcher, + TargetBParentchainBlockImportDispatcher, TargetBParentchainBlockImportQueue, + TargetBParentchainBlockImporter, TargetBParentchainEventImportQueue, + TargetBParentchainImmediateBlockImportDispatcher, + TargetBParentchainIndirectCallsExecutor, + TargetBParentchainTriggeredBlockImportDispatcher, GLOBAL_OCALL_API_COMPONENT, + GLOBAL_SHIELDING_KEY_REPOSITORY_COMPONENT, GLOBAL_SIGNING_KEY_REPOSITORY_COMPONENT, + GLOBAL_STATE_HANDLER_COMPONENT, GLOBAL_STATE_OBSERVER_COMPONENT, + GLOBAL_TOP_POOL_AUTHOR_COMPONENT, + }, + EnclaveStfEnclaveSigner, + }, +}; +use itp_component_container::ComponentGetter; +use itp_nonce_cache::NonceCache; +use itp_sgx_crypto::key_repository::AccessKey; +use log::*; +use sp_core::H256; +use std::sync::Arc; + +pub(crate) fn create_integritee_parentchain_block_importer( + validator_access: Arc, + stf_executor: Arc, + extrinsics_factory: Arc, + node_metadata_repository: Arc, +) -> Result { + let state_observer = GLOBAL_STATE_OBSERVER_COMPONENT.get()?; + let top_pool_author = GLOBAL_TOP_POOL_AUTHOR_COMPONENT.get()?; + let shielding_key_repository = GLOBAL_SHIELDING_KEY_REPOSITORY_COMPONENT.get()?; + let ocall_api = GLOBAL_OCALL_API_COMPONENT.get()?; + + let stf_enclave_signer = Arc::new(EnclaveStfEnclaveSigner::new( + state_observer, + ocall_api.clone(), + shielding_key_repository.clone(), + top_pool_author.clone(), + )); + let indirect_calls_executor = Arc::new(IntegriteeParentchainIndirectCallsExecutor::new( + shielding_key_repository, + stf_enclave_signer, + top_pool_author, + node_metadata_repository, + )); + Ok(IntegriteeParentchainBlockImporter::new( + validator_access, + stf_executor, + extrinsics_factory, + indirect_calls_executor, + ocall_api, + )) +} + +pub(crate) fn create_target_a_parentchain_block_importer( + validator_access: Arc, + stf_executor: Arc, + extrinsics_factory: Arc, + node_metadata_repository: Arc, +) -> Result { + let state_observer = GLOBAL_STATE_OBSERVER_COMPONENT.get()?; + let top_pool_author = GLOBAL_TOP_POOL_AUTHOR_COMPONENT.get()?; + let shielding_key_repository = GLOBAL_SHIELDING_KEY_REPOSITORY_COMPONENT.get()?; + let ocall_api = GLOBAL_OCALL_API_COMPONENT.get()?; + + let stf_enclave_signer = Arc::new(EnclaveStfEnclaveSigner::new( + state_observer, + ocall_api.clone(), + shielding_key_repository.clone(), + top_pool_author.clone(), + )); + let indirect_calls_executor = Arc::new(TargetAParentchainIndirectCallsExecutor::new( + shielding_key_repository, + stf_enclave_signer, + top_pool_author, + node_metadata_repository, + )); + Ok(TargetAParentchainBlockImporter::new( + validator_access, + stf_executor, + extrinsics_factory, + indirect_calls_executor, + ocall_api, + )) +} + +pub(crate) fn create_target_b_parentchain_block_importer( + validator_access: Arc, + stf_executor: Arc, + extrinsics_factory: Arc, + node_metadata_repository: Arc, +) -> Result { + let state_observer = GLOBAL_STATE_OBSERVER_COMPONENT.get()?; + let top_pool_author = GLOBAL_TOP_POOL_AUTHOR_COMPONENT.get()?; + let shielding_key_repository = GLOBAL_SHIELDING_KEY_REPOSITORY_COMPONENT.get()?; + let ocall_api = GLOBAL_OCALL_API_COMPONENT.get()?; + + let stf_enclave_signer = Arc::new(EnclaveStfEnclaveSigner::new( + state_observer, + ocall_api.clone(), + shielding_key_repository.clone(), + top_pool_author.clone(), + )); + let indirect_calls_executor = Arc::new(TargetBParentchainIndirectCallsExecutor::new( + shielding_key_repository, + stf_enclave_signer, + top_pool_author, + node_metadata_repository, + )); + Ok(TargetBParentchainBlockImporter::new( + validator_access, + stf_executor, + extrinsics_factory, + indirect_calls_executor, + ocall_api, + )) +} + +pub(crate) fn create_extrinsics_factory( + genesis_hash: H256, + nonce_cache: Arc, + node_metadata_repository: Arc, +) -> Result> { + let signer = GLOBAL_SIGNING_KEY_REPOSITORY_COMPONENT.get()?.retrieve_key()?; + + Ok(Arc::new(EnclaveExtrinsicsFactory::new( + genesis_hash, + EnclaveParentchainSigner::new(signer), + nonce_cache, + node_metadata_repository, + ))) +} + +pub(crate) fn create_integritee_offchain_immediate_import_dispatcher( + stf_executor: Arc, + block_importer: IntegriteeParentchainBlockImporter, + validator_access: Arc, + extrinsics_factory: Arc, +) -> Result> { + let state_handler = GLOBAL_STATE_HANDLER_COMPONENT.get()?; + let top_pool_author = GLOBAL_TOP_POOL_AUTHOR_COMPONENT.get()?; + + let offchain_worker_executor = Arc::new(EnclaveOffchainWorkerExecutor::new( + top_pool_author, + stf_executor, + state_handler, + validator_access, + extrinsics_factory, + )); + let immediate_dispatcher = IntegriteeParentchainImmediateBlockImportDispatcher::new( + block_importer, + ) + .with_observer(move || { + if let Err(e) = offchain_worker_executor.execute() { + error!("Failed to execute trusted calls: {:?}", e); + } + }); + + Ok(Arc::new(IntegriteeParentchainBlockImportDispatcher::new_immediate_dispatcher(Arc::new( + immediate_dispatcher, + )))) +} + +pub(crate) fn create_target_a_offchain_immediate_import_dispatcher( + stf_executor: Arc, + block_importer: TargetAParentchainBlockImporter, + validator_access: Arc, + extrinsics_factory: Arc, +) -> Result> { + let state_handler = GLOBAL_STATE_HANDLER_COMPONENT.get()?; + let top_pool_author = GLOBAL_TOP_POOL_AUTHOR_COMPONENT.get()?; + + let offchain_worker_executor = Arc::new(EnclaveOffchainWorkerExecutor::new( + top_pool_author, + stf_executor, + state_handler, + validator_access, + extrinsics_factory, + )); + let immediate_dispatcher = TargetAParentchainImmediateBlockImportDispatcher::new( + block_importer, + ) + .with_observer(move || { + if let Err(e) = offchain_worker_executor.execute() { + error!("Failed to execute trusted calls: {:?}", e); + } + }); + + Ok(Arc::new(TargetAParentchainBlockImportDispatcher::new_immediate_dispatcher(Arc::new( + immediate_dispatcher, + )))) +} + +pub(crate) fn create_target_b_offchain_immediate_import_dispatcher( + stf_executor: Arc, + block_importer: TargetBParentchainBlockImporter, + validator_access: Arc, + extrinsics_factory: Arc, +) -> Result> { + let state_handler = GLOBAL_STATE_HANDLER_COMPONENT.get()?; + let top_pool_author = GLOBAL_TOP_POOL_AUTHOR_COMPONENT.get()?; + + let offchain_worker_executor = Arc::new(EnclaveOffchainWorkerExecutor::new( + top_pool_author, + stf_executor, + state_handler, + validator_access, + extrinsics_factory, + )); + let immediate_dispatcher = TargetBParentchainImmediateBlockImportDispatcher::new( + block_importer, + ) + .with_observer(move || { + if let Err(e) = offchain_worker_executor.execute() { + error!("Failed to execute trusted calls: {:?}", e); + } + }); + + Ok(Arc::new(TargetBParentchainBlockImportDispatcher::new_immediate_dispatcher(Arc::new( + immediate_dispatcher, + )))) +} + +pub(crate) fn create_sidechain_triggered_import_dispatcher( + block_importer: IntegriteeParentchainBlockImporter, +) -> Arc { + let parentchain_block_import_queue = IntegriteeParentchainBlockImportQueue::default(); + let parentchain_event_import_queue = IntegriteeParentchainEventImportQueue::default(); + let triggered_dispatcher = IntegriteeParentchainTriggeredBlockImportDispatcher::new( + block_importer, + parentchain_block_import_queue, + parentchain_event_import_queue, + ); + Arc::new(IntegriteeParentchainBlockImportDispatcher::new_triggered_dispatcher(Arc::new( + triggered_dispatcher, + ))) +} + +pub(crate) fn create_sidechain_triggered_import_dispatcher_for_target_a( + block_importer: TargetAParentchainBlockImporter, +) -> Arc { + let parentchain_block_import_queue = TargetAParentchainBlockImportQueue::default(); + let parentchain_event_import_queue = TargetAParentchainEventImportQueue::default(); + let triggered_dispatcher = TargetAParentchainTriggeredBlockImportDispatcher::new( + block_importer, + parentchain_block_import_queue, + parentchain_event_import_queue, + ); + Arc::new(TargetAParentchainBlockImportDispatcher::new_triggered_dispatcher(Arc::new( + triggered_dispatcher, + ))) +} + +pub(crate) fn create_sidechain_triggered_import_dispatcher_for_target_b( + block_importer: TargetBParentchainBlockImporter, +) -> Arc { + let parentchain_block_import_queue = TargetBParentchainBlockImportQueue::default(); + let parentchain_event_import_queue = TargetBParentchainEventImportQueue::default(); + let triggered_dispatcher = TargetBParentchainTriggeredBlockImportDispatcher::new( + block_importer, + parentchain_block_import_queue, + parentchain_event_import_queue, + ); + Arc::new(TargetBParentchainBlockImportDispatcher::new_triggered_dispatcher(Arc::new( + triggered_dispatcher, + ))) +} diff --git a/bitacross-worker/enclave-runtime/src/initialization/parentchain/integritee_parachain.rs b/bitacross-worker/enclave-runtime/src/initialization/parentchain/integritee_parachain.rs new file mode 100644 index 0000000000..f297c4960e --- /dev/null +++ b/bitacross-worker/enclave-runtime/src/initialization/parentchain/integritee_parachain.rs @@ -0,0 +1,118 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{ + error::Result, + initialization::{ + global_components::{ + EnclaveExtrinsicsFactory, EnclaveNodeMetadataRepository, EnclaveOCallApi, + EnclaveStfExecutor, EnclaveValidatorAccessor, + IntegriteeParentchainBlockImportDispatcher, + GLOBAL_INTEGRITEE_PARENTCHAIN_LIGHT_CLIENT_SEAL, + GLOBAL_INTEGRITEE_PARENTCHAIN_NONCE_CACHE, GLOBAL_OCALL_API_COMPONENT, + GLOBAL_STATE_HANDLER_COMPONENT, + }, + parentchain::common::{ + create_extrinsics_factory, create_integritee_offchain_immediate_import_dispatcher, + create_integritee_parentchain_block_importer, + create_sidechain_triggered_import_dispatcher, + }, + }, +}; +use itc_parentchain::light_client::{concurrent_access::ValidatorAccess, LightClientState}; +use itp_component_container::ComponentGetter; +use itp_settings::worker_mode::{ProvideWorkerMode, WorkerMode}; +use itp_types::parentchain::ParentchainId; +use std::{path::PathBuf, sync::Arc}; + +pub use itc_parentchain::primitives::{ParachainBlock, ParachainHeader, ParachainParams}; + +#[derive(Clone)] +pub struct IntegriteeParachainHandler { + pub genesis_header: ParachainHeader, + pub node_metadata_repository: Arc, + pub stf_executor: Arc, + pub validator_accessor: Arc, + pub extrinsics_factory: Arc, + pub import_dispatcher: Arc, +} + +impl IntegriteeParachainHandler { + pub fn init( + _base_path: PathBuf, + params: ParachainParams, + ) -> Result { + let ocall_api = GLOBAL_OCALL_API_COMPONENT.get()?; + let state_handler = GLOBAL_STATE_HANDLER_COMPONENT.get()?; + let node_metadata_repository = Arc::new(EnclaveNodeMetadataRepository::default()); + + let genesis_header = params.genesis_header.clone(); + + let light_client_seal = GLOBAL_INTEGRITEE_PARENTCHAIN_LIGHT_CLIENT_SEAL.get()?; + let validator = itc_parentchain::light_client::io::read_or_init_parachain_validator::< + ParachainBlock, + EnclaveOCallApi, + _, + >(params, ocall_api.clone(), &*light_client_seal, ParentchainId::Litentry)?; + let validator_accessor = + Arc::new(EnclaveValidatorAccessor::new(validator, light_client_seal)); + + let genesis_hash = validator_accessor.execute_on_validator(|v| v.genesis_hash())?; + + let extrinsics_factory = create_extrinsics_factory( + genesis_hash, + GLOBAL_INTEGRITEE_PARENTCHAIN_NONCE_CACHE.clone(), + node_metadata_repository.clone(), + )?; + + let stf_executor = Arc::new(EnclaveStfExecutor::new( + ocall_api, + state_handler, + node_metadata_repository.clone(), + )); + + let block_importer = create_integritee_parentchain_block_importer( + validator_accessor.clone(), + stf_executor.clone(), + extrinsics_factory.clone(), + node_metadata_repository.clone(), + )?; + + let import_dispatcher = match WorkerModeProvider::worker_mode() { + WorkerMode::OffChainWorker => create_integritee_offchain_immediate_import_dispatcher( + stf_executor.clone(), + block_importer, + validator_accessor.clone(), + extrinsics_factory.clone(), + )?, + WorkerMode::Sidechain => create_sidechain_triggered_import_dispatcher(block_importer), + WorkerMode::Teeracle => + Arc::new(IntegriteeParentchainBlockImportDispatcher::new_empty_dispatcher()), + }; + + let parachain_handler = Self { + genesis_header, + node_metadata_repository, + stf_executor, + validator_accessor, + extrinsics_factory, + import_dispatcher, + }; + + Ok(parachain_handler) + } +} diff --git a/bitacross-worker/enclave-runtime/src/initialization/parentchain/integritee_solochain.rs b/bitacross-worker/enclave-runtime/src/initialization/parentchain/integritee_solochain.rs new file mode 100644 index 0000000000..b5ae349479 --- /dev/null +++ b/bitacross-worker/enclave-runtime/src/initialization/parentchain/integritee_solochain.rs @@ -0,0 +1,117 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{ + error::Result, + initialization::{ + global_components::{ + EnclaveExtrinsicsFactory, EnclaveNodeMetadataRepository, EnclaveOCallApi, + EnclaveStfExecutor, EnclaveValidatorAccessor, + IntegriteeParentchainBlockImportDispatcher, + GLOBAL_INTEGRITEE_PARENTCHAIN_LIGHT_CLIENT_SEAL, + GLOBAL_INTEGRITEE_PARENTCHAIN_NONCE_CACHE, GLOBAL_OCALL_API_COMPONENT, + GLOBAL_STATE_HANDLER_COMPONENT, + }, + parentchain::common::{ + create_extrinsics_factory, create_integritee_offchain_immediate_import_dispatcher, + create_integritee_parentchain_block_importer, + create_sidechain_triggered_import_dispatcher, + }, + }, +}; +use itc_parentchain::light_client::{concurrent_access::ValidatorAccess, LightClientState}; +use itp_component_container::ComponentGetter; +use itp_settings::worker_mode::{ProvideWorkerMode, WorkerMode}; +use itp_types::parentchain::ParentchainId; +use std::{path::PathBuf, sync::Arc}; + +pub use itc_parentchain::primitives::{SolochainBlock, SolochainHeader, SolochainParams}; + +pub struct IntegriteeSolochainHandler { + pub genesis_header: SolochainHeader, + pub node_metadata_repository: Arc, + pub stf_executor: Arc, + pub validator_accessor: Arc, + pub extrinsics_factory: Arc, + pub import_dispatcher: Arc, +} + +impl IntegriteeSolochainHandler { + pub fn init( + _base_path: PathBuf, + params: SolochainParams, + ) -> Result { + let ocall_api = GLOBAL_OCALL_API_COMPONENT.get()?; + let state_handler = GLOBAL_STATE_HANDLER_COMPONENT.get()?; + let light_client_seal = GLOBAL_INTEGRITEE_PARENTCHAIN_LIGHT_CLIENT_SEAL.get()?; + let node_metadata_repository = Arc::new(EnclaveNodeMetadataRepository::default()); + + let genesis_header = params.genesis_header.clone(); + + let validator = itc_parentchain::light_client::io::read_or_init_grandpa_validator::< + SolochainBlock, + EnclaveOCallApi, + _, + >(params, ocall_api.clone(), &*light_client_seal, ParentchainId::Litentry)?; + let validator_accessor = + Arc::new(EnclaveValidatorAccessor::new(validator, light_client_seal)); + + let genesis_hash = validator_accessor.execute_on_validator(|v| v.genesis_hash())?; + + let extrinsics_factory = create_extrinsics_factory( + genesis_hash, + GLOBAL_INTEGRITEE_PARENTCHAIN_NONCE_CACHE.clone(), + node_metadata_repository.clone(), + )?; + + let stf_executor = Arc::new(EnclaveStfExecutor::new( + ocall_api, + state_handler, + node_metadata_repository.clone(), + )); + + let block_importer = create_integritee_parentchain_block_importer( + validator_accessor.clone(), + stf_executor.clone(), + extrinsics_factory.clone(), + node_metadata_repository.clone(), + )?; + + let import_dispatcher = match WorkerModeProvider::worker_mode() { + WorkerMode::OffChainWorker => create_integritee_offchain_immediate_import_dispatcher( + stf_executor.clone(), + block_importer, + validator_accessor.clone(), + extrinsics_factory.clone(), + )?, + WorkerMode::Sidechain => create_sidechain_triggered_import_dispatcher(block_importer), + WorkerMode::Teeracle => + Arc::new(IntegriteeParentchainBlockImportDispatcher::new_empty_dispatcher()), + }; + + let solochain_handler = Self { + genesis_header, + node_metadata_repository, + stf_executor, + validator_accessor, + extrinsics_factory, + import_dispatcher, + }; + + Ok(solochain_handler) + } +} diff --git a/bitacross-worker/enclave-runtime/src/initialization/parentchain/mod.rs b/bitacross-worker/enclave-runtime/src/initialization/parentchain/mod.rs new file mode 100644 index 0000000000..b0045d6ca5 --- /dev/null +++ b/bitacross-worker/enclave-runtime/src/initialization/parentchain/mod.rs @@ -0,0 +1,120 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{ + error::Result, + initialization::{ + global_components::{ + GLOBAL_INTEGRITEE_PARACHAIN_HANDLER_COMPONENT, + GLOBAL_INTEGRITEE_SOLOCHAIN_HANDLER_COMPONENT, + GLOBAL_TARGET_A_PARACHAIN_HANDLER_COMPONENT, + GLOBAL_TARGET_A_SOLOCHAIN_HANDLER_COMPONENT, + GLOBAL_TARGET_B_PARACHAIN_HANDLER_COMPONENT, + GLOBAL_TARGET_B_SOLOCHAIN_HANDLER_COMPONENT, + }, + parentchain::{ + target_a_parachain::TargetAParachainHandler, + target_a_solochain::TargetASolochainHandler, + target_b_parachain::TargetBParachainHandler, + target_b_solochain::TargetBSolochainHandler, + }, + }, +}; +use codec::{Decode, Encode}; +use integritee_parachain::IntegriteeParachainHandler; +use integritee_solochain::IntegriteeSolochainHandler; +use itc_parentchain::{ + light_client::{concurrent_access::ValidatorAccess, LightClientState}, + primitives::{ParentchainId, ParentchainInitParams}, +}; +use itp_component_container::ComponentInitializer; +use itp_settings::worker_mode::ProvideWorkerMode; +use std::{path::PathBuf, vec::Vec}; + +mod common; +pub mod integritee_parachain; +pub mod integritee_solochain; +pub mod target_a_parachain; +pub mod target_a_solochain; +pub mod target_b_parachain; +pub mod target_b_solochain; + +pub(crate) fn init_parentchain_components( + base_path: PathBuf, + encoded_params: Vec, +) -> Result> { + match ParentchainInitParams::decode(&mut encoded_params.as_slice())? { + ParentchainInitParams::Parachain { id, params } => match id { + ParentchainId::Litentry => { + let handler = + IntegriteeParachainHandler::init::(base_path, params)?; + let header = handler + .validator_accessor + .execute_on_validator(|v| v.latest_finalized_header())?; + GLOBAL_INTEGRITEE_PARACHAIN_HANDLER_COMPONENT.initialize(handler.into()); + Ok(header.encode()) + }, + ParentchainId::TargetA => { + let handler = + TargetAParachainHandler::init::(base_path, params)?; + let header = handler + .validator_accessor + .execute_on_validator(|v| v.latest_finalized_header())?; + GLOBAL_TARGET_A_PARACHAIN_HANDLER_COMPONENT.initialize(handler.into()); + Ok(header.encode()) + }, + ParentchainId::TargetB => { + let handler = + TargetBParachainHandler::init::(base_path, params)?; + let header = handler + .validator_accessor + .execute_on_validator(|v| v.latest_finalized_header())?; + GLOBAL_TARGET_B_PARACHAIN_HANDLER_COMPONENT.initialize(handler.into()); + Ok(header.encode()) + }, + }, + ParentchainInitParams::Solochain { id, params } => match id { + ParentchainId::Litentry => { + let handler = + IntegriteeSolochainHandler::init::(base_path, params)?; + let header = handler + .validator_accessor + .execute_on_validator(|v| v.latest_finalized_header())?; + GLOBAL_INTEGRITEE_SOLOCHAIN_HANDLER_COMPONENT.initialize(handler.into()); + Ok(header.encode()) + }, + ParentchainId::TargetA => { + let handler = + TargetASolochainHandler::init::(base_path, params)?; + let header = handler + .validator_accessor + .execute_on_validator(|v| v.latest_finalized_header())?; + GLOBAL_TARGET_A_SOLOCHAIN_HANDLER_COMPONENT.initialize(handler.into()); + Ok(header.encode()) + }, + ParentchainId::TargetB => { + let handler = + TargetBSolochainHandler::init::(base_path, params)?; + let header = handler + .validator_accessor + .execute_on_validator(|v| v.latest_finalized_header())?; + GLOBAL_TARGET_B_SOLOCHAIN_HANDLER_COMPONENT.initialize(handler.into()); + Ok(header.encode()) + }, + }, + } +} diff --git a/bitacross-worker/enclave-runtime/src/initialization/parentchain/target_a_parachain.rs b/bitacross-worker/enclave-runtime/src/initialization/parentchain/target_a_parachain.rs new file mode 100644 index 0000000000..bf24f6fdd4 --- /dev/null +++ b/bitacross-worker/enclave-runtime/src/initialization/parentchain/target_a_parachain.rs @@ -0,0 +1,122 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +//! Naive implementation of adding a second parachain handler to the setup. +//! +//! Ideally, most of the redundant code can be abstracted away, but it turns out +//! that this is quite tedious, so for now this is a copy-past of the [IntegriteeParachainHandler]: +//! * https://github.com/integritee-network/worker/issues/1417 + +use crate::{ + error::Result, + initialization::{ + global_components::{ + EnclaveExtrinsicsFactory, EnclaveNodeMetadataRepository, EnclaveOCallApi, + EnclaveStfExecutor, EnclaveValidatorAccessor, TargetAParentchainBlockImportDispatcher, + GLOBAL_OCALL_API_COMPONENT, GLOBAL_STATE_HANDLER_COMPONENT, + GLOBAL_TARGET_A_PARENTCHAIN_LIGHT_CLIENT_SEAL, GLOBAL_TARGET_A_PARENTCHAIN_NONCE_CACHE, + }, + parentchain::common::{ + create_extrinsics_factory, create_sidechain_triggered_import_dispatcher_for_target_a, + create_target_a_offchain_immediate_import_dispatcher, + create_target_a_parentchain_block_importer, + }, + }, +}; +use itc_parentchain::light_client::{concurrent_access::ValidatorAccess, LightClientState}; +pub use itc_parentchain::primitives::{ParachainBlock, ParachainHeader, ParachainParams}; +use itp_component_container::ComponentGetter; +use itp_settings::worker_mode::{ProvideWorkerMode, WorkerMode}; +use itp_types::parentchain::ParentchainId; +use std::{path::PathBuf, sync::Arc}; + +#[derive(Clone)] +pub struct TargetAParachainHandler { + pub genesis_header: ParachainHeader, + pub node_metadata_repository: Arc, + pub stf_executor: Arc, + pub validator_accessor: Arc, + pub extrinsics_factory: Arc, + pub import_dispatcher: Arc, +} + +impl TargetAParachainHandler { + pub fn init( + _base_path: PathBuf, + params: ParachainParams, + ) -> Result { + let ocall_api = GLOBAL_OCALL_API_COMPONENT.get()?; + let state_handler = GLOBAL_STATE_HANDLER_COMPONENT.get()?; + let node_metadata_repository = Arc::new(EnclaveNodeMetadataRepository::default()); + + let genesis_header = params.genesis_header.clone(); + + let light_client_seal = GLOBAL_TARGET_A_PARENTCHAIN_LIGHT_CLIENT_SEAL.get()?; + let validator = itc_parentchain::light_client::io::read_or_init_parachain_validator::< + ParachainBlock, + EnclaveOCallApi, + _, + >(params, ocall_api.clone(), &*light_client_seal, ParentchainId::TargetA)?; + let validator_accessor = + Arc::new(EnclaveValidatorAccessor::new(validator, light_client_seal)); + + let genesis_hash = validator_accessor.execute_on_validator(|v| v.genesis_hash())?; + + let extrinsics_factory = create_extrinsics_factory( + genesis_hash, + GLOBAL_TARGET_A_PARENTCHAIN_NONCE_CACHE.clone(), + node_metadata_repository.clone(), + )?; + + let stf_executor = Arc::new(EnclaveStfExecutor::new( + ocall_api, + state_handler, + node_metadata_repository.clone(), + )); + + let block_importer = create_target_a_parentchain_block_importer( + validator_accessor.clone(), + stf_executor.clone(), + extrinsics_factory.clone(), + node_metadata_repository.clone(), + )?; + + let import_dispatcher = match WorkerModeProvider::worker_mode() { + WorkerMode::OffChainWorker => create_target_a_offchain_immediate_import_dispatcher( + stf_executor.clone(), + block_importer, + validator_accessor.clone(), + extrinsics_factory.clone(), + )?, + WorkerMode::Sidechain => + create_sidechain_triggered_import_dispatcher_for_target_a(block_importer), + WorkerMode::Teeracle => + Arc::new(TargetAParentchainBlockImportDispatcher::new_empty_dispatcher()), + }; + + let parachain_handler = Self { + genesis_header, + node_metadata_repository, + stf_executor, + validator_accessor, + extrinsics_factory, + import_dispatcher, + }; + + Ok(parachain_handler) + } +} diff --git a/bitacross-worker/enclave-runtime/src/initialization/parentchain/target_a_solochain.rs b/bitacross-worker/enclave-runtime/src/initialization/parentchain/target_a_solochain.rs new file mode 100644 index 0000000000..f5cf2ae8ff --- /dev/null +++ b/bitacross-worker/enclave-runtime/src/initialization/parentchain/target_a_solochain.rs @@ -0,0 +1,115 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{ + error::Result, + initialization::{ + global_components::{ + EnclaveExtrinsicsFactory, EnclaveNodeMetadataRepository, EnclaveOCallApi, + EnclaveStfExecutor, EnclaveValidatorAccessor, TargetAParentchainBlockImportDispatcher, + GLOBAL_OCALL_API_COMPONENT, GLOBAL_STATE_HANDLER_COMPONENT, + GLOBAL_TARGET_A_PARENTCHAIN_LIGHT_CLIENT_SEAL, GLOBAL_TARGET_A_PARENTCHAIN_NONCE_CACHE, + }, + parentchain::common::{ + create_extrinsics_factory, create_sidechain_triggered_import_dispatcher_for_target_a, + create_target_a_offchain_immediate_import_dispatcher, + create_target_a_parentchain_block_importer, + }, + }, +}; +use itc_parentchain::light_client::{concurrent_access::ValidatorAccess, LightClientState}; +pub use itc_parentchain::primitives::{SolochainBlock, SolochainHeader, SolochainParams}; +use itp_component_container::ComponentGetter; +use itp_settings::worker_mode::{ProvideWorkerMode, WorkerMode}; +use itp_types::parentchain::ParentchainId; +use std::{path::PathBuf, sync::Arc}; + +pub struct TargetASolochainHandler { + pub genesis_header: SolochainHeader, + pub node_metadata_repository: Arc, + pub stf_executor: Arc, + pub validator_accessor: Arc, + pub extrinsics_factory: Arc, + pub import_dispatcher: Arc, +} + +impl TargetASolochainHandler { + pub fn init( + _base_path: PathBuf, + params: SolochainParams, + ) -> Result { + let ocall_api = GLOBAL_OCALL_API_COMPONENT.get()?; + let state_handler = GLOBAL_STATE_HANDLER_COMPONENT.get()?; + let light_client_seal = GLOBAL_TARGET_A_PARENTCHAIN_LIGHT_CLIENT_SEAL.get()?; + let node_metadata_repository = Arc::new(EnclaveNodeMetadataRepository::default()); + + let genesis_header = params.genesis_header.clone(); + + let validator = itc_parentchain::light_client::io::read_or_init_grandpa_validator::< + SolochainBlock, + EnclaveOCallApi, + _, + >(params, ocall_api.clone(), &*light_client_seal, ParentchainId::TargetA)?; + let validator_accessor = + Arc::new(EnclaveValidatorAccessor::new(validator, light_client_seal)); + + let genesis_hash = validator_accessor.execute_on_validator(|v| v.genesis_hash())?; + + let extrinsics_factory = create_extrinsics_factory( + genesis_hash, + GLOBAL_TARGET_A_PARENTCHAIN_NONCE_CACHE.clone(), + node_metadata_repository.clone(), + )?; + + let stf_executor = Arc::new(EnclaveStfExecutor::new( + ocall_api, + state_handler, + node_metadata_repository.clone(), + )); + + let block_importer = create_target_a_parentchain_block_importer( + validator_accessor.clone(), + stf_executor.clone(), + extrinsics_factory.clone(), + node_metadata_repository.clone(), + )?; + + let import_dispatcher = match WorkerModeProvider::worker_mode() { + WorkerMode::OffChainWorker => create_target_a_offchain_immediate_import_dispatcher( + stf_executor.clone(), + block_importer, + validator_accessor.clone(), + extrinsics_factory.clone(), + )?, + WorkerMode::Sidechain => + create_sidechain_triggered_import_dispatcher_for_target_a(block_importer), + WorkerMode::Teeracle => + Arc::new(TargetAParentchainBlockImportDispatcher::new_empty_dispatcher()), + }; + + let solochain_handler = Self { + genesis_header, + node_metadata_repository, + stf_executor, + validator_accessor, + extrinsics_factory, + import_dispatcher, + }; + + Ok(solochain_handler) + } +} diff --git a/bitacross-worker/enclave-runtime/src/initialization/parentchain/target_b_parachain.rs b/bitacross-worker/enclave-runtime/src/initialization/parentchain/target_b_parachain.rs new file mode 100644 index 0000000000..be44224c65 --- /dev/null +++ b/bitacross-worker/enclave-runtime/src/initialization/parentchain/target_b_parachain.rs @@ -0,0 +1,122 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +//! Naive implementation of adding a second parachain handler to the setup. +//! +//! Ideally, most of the redundant code can be abstracted away, but it turns out +//! that this is quite tedious, so for now this is a copy-past of the [IntegriteeParachainHandler]: +//! * https://github.com/integritee-network/worker/issues/1417 + +use crate::{ + error::Result, + initialization::{ + global_components::{ + EnclaveExtrinsicsFactory, EnclaveNodeMetadataRepository, EnclaveOCallApi, + EnclaveStfExecutor, EnclaveValidatorAccessor, TargetBParentchainBlockImportDispatcher, + GLOBAL_OCALL_API_COMPONENT, GLOBAL_STATE_HANDLER_COMPONENT, + GLOBAL_TARGET_B_PARENTCHAIN_LIGHT_CLIENT_SEAL, GLOBAL_TARGET_B_PARENTCHAIN_NONCE_CACHE, + }, + parentchain::common::{ + create_extrinsics_factory, create_sidechain_triggered_import_dispatcher_for_target_b, + create_target_b_offchain_immediate_import_dispatcher, + create_target_b_parentchain_block_importer, + }, + }, +}; +use itc_parentchain::light_client::{concurrent_access::ValidatorAccess, LightClientState}; +pub use itc_parentchain::primitives::{ParachainBlock, ParachainHeader, ParachainParams}; +use itp_component_container::ComponentGetter; +use itp_settings::worker_mode::{ProvideWorkerMode, WorkerMode}; +use itp_types::parentchain::ParentchainId; +use std::{path::PathBuf, sync::Arc}; + +#[derive(Clone)] +pub struct TargetBParachainHandler { + pub genesis_header: ParachainHeader, + pub node_metadata_repository: Arc, + pub stf_executor: Arc, + pub validator_accessor: Arc, + pub extrinsics_factory: Arc, + pub import_dispatcher: Arc, +} + +impl TargetBParachainHandler { + pub fn init( + _base_path: PathBuf, + params: ParachainParams, + ) -> Result { + let ocall_api = GLOBAL_OCALL_API_COMPONENT.get()?; + let state_handler = GLOBAL_STATE_HANDLER_COMPONENT.get()?; + let node_metadata_repository = Arc::new(EnclaveNodeMetadataRepository::default()); + + let genesis_header = params.genesis_header.clone(); + + let light_client_seal = GLOBAL_TARGET_B_PARENTCHAIN_LIGHT_CLIENT_SEAL.get()?; + let validator = itc_parentchain::light_client::io::read_or_init_parachain_validator::< + ParachainBlock, + EnclaveOCallApi, + _, + >(params, ocall_api.clone(), &*light_client_seal, ParentchainId::TargetB)?; + let validator_accessor = + Arc::new(EnclaveValidatorAccessor::new(validator, light_client_seal)); + + let genesis_hash = validator_accessor.execute_on_validator(|v| v.genesis_hash())?; + + let extrinsics_factory = create_extrinsics_factory( + genesis_hash, + GLOBAL_TARGET_B_PARENTCHAIN_NONCE_CACHE.clone(), + node_metadata_repository.clone(), + )?; + + let stf_executor = Arc::new(EnclaveStfExecutor::new( + ocall_api, + state_handler, + node_metadata_repository.clone(), + )); + + let block_importer = create_target_b_parentchain_block_importer( + validator_accessor.clone(), + stf_executor.clone(), + extrinsics_factory.clone(), + node_metadata_repository.clone(), + )?; + + let import_dispatcher = match WorkerModeProvider::worker_mode() { + WorkerMode::OffChainWorker => create_target_b_offchain_immediate_import_dispatcher( + stf_executor.clone(), + block_importer, + validator_accessor.clone(), + extrinsics_factory.clone(), + )?, + WorkerMode::Sidechain => + create_sidechain_triggered_import_dispatcher_for_target_b(block_importer), + WorkerMode::Teeracle => + Arc::new(TargetBParentchainBlockImportDispatcher::new_empty_dispatcher()), + }; + + let parachain_handler = Self { + genesis_header, + node_metadata_repository, + stf_executor, + validator_accessor, + extrinsics_factory, + import_dispatcher, + }; + + Ok(parachain_handler) + } +} diff --git a/bitacross-worker/enclave-runtime/src/initialization/parentchain/target_b_solochain.rs b/bitacross-worker/enclave-runtime/src/initialization/parentchain/target_b_solochain.rs new file mode 100644 index 0000000000..842baa8129 --- /dev/null +++ b/bitacross-worker/enclave-runtime/src/initialization/parentchain/target_b_solochain.rs @@ -0,0 +1,115 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{ + error::Result, + initialization::{ + global_components::{ + EnclaveExtrinsicsFactory, EnclaveNodeMetadataRepository, EnclaveOCallApi, + EnclaveStfExecutor, EnclaveValidatorAccessor, TargetBParentchainBlockImportDispatcher, + GLOBAL_OCALL_API_COMPONENT, GLOBAL_STATE_HANDLER_COMPONENT, + GLOBAL_TARGET_B_PARENTCHAIN_LIGHT_CLIENT_SEAL, GLOBAL_TARGET_B_PARENTCHAIN_NONCE_CACHE, + }, + parentchain::common::{ + create_extrinsics_factory, create_sidechain_triggered_import_dispatcher_for_target_b, + create_target_b_offchain_immediate_import_dispatcher, + create_target_b_parentchain_block_importer, + }, + }, +}; +use itc_parentchain::light_client::{concurrent_access::ValidatorAccess, LightClientState}; +pub use itc_parentchain::primitives::{SolochainBlock, SolochainHeader, SolochainParams}; +use itp_component_container::ComponentGetter; +use itp_settings::worker_mode::{ProvideWorkerMode, WorkerMode}; +use itp_types::parentchain::ParentchainId; +use std::{path::PathBuf, sync::Arc}; + +pub struct TargetBSolochainHandler { + pub genesis_header: SolochainHeader, + pub node_metadata_repository: Arc, + pub stf_executor: Arc, + pub validator_accessor: Arc, + pub extrinsics_factory: Arc, + pub import_dispatcher: Arc, +} + +impl TargetBSolochainHandler { + pub fn init( + _base_path: PathBuf, + params: SolochainParams, + ) -> Result { + let ocall_api = GLOBAL_OCALL_API_COMPONENT.get()?; + let state_handler = GLOBAL_STATE_HANDLER_COMPONENT.get()?; + let light_client_seal = GLOBAL_TARGET_B_PARENTCHAIN_LIGHT_CLIENT_SEAL.get()?; + let node_metadata_repository = Arc::new(EnclaveNodeMetadataRepository::default()); + + let genesis_header = params.genesis_header.clone(); + + let validator = itc_parentchain::light_client::io::read_or_init_grandpa_validator::< + SolochainBlock, + EnclaveOCallApi, + _, + >(params, ocall_api.clone(), &*light_client_seal, ParentchainId::TargetB)?; + let validator_accessor = + Arc::new(EnclaveValidatorAccessor::new(validator, light_client_seal)); + + let genesis_hash = validator_accessor.execute_on_validator(|v| v.genesis_hash())?; + + let extrinsics_factory = create_extrinsics_factory( + genesis_hash, + GLOBAL_TARGET_B_PARENTCHAIN_NONCE_CACHE.clone(), + node_metadata_repository.clone(), + )?; + + let stf_executor = Arc::new(EnclaveStfExecutor::new( + ocall_api, + state_handler, + node_metadata_repository.clone(), + )); + + let block_importer = create_target_b_parentchain_block_importer( + validator_accessor.clone(), + stf_executor.clone(), + extrinsics_factory.clone(), + node_metadata_repository.clone(), + )?; + + let import_dispatcher = match WorkerModeProvider::worker_mode() { + WorkerMode::OffChainWorker => create_target_b_offchain_immediate_import_dispatcher( + stf_executor.clone(), + block_importer, + validator_accessor.clone(), + extrinsics_factory.clone(), + )?, + WorkerMode::Sidechain => + create_sidechain_triggered_import_dispatcher_for_target_b(block_importer), + WorkerMode::Teeracle => + Arc::new(TargetBParentchainBlockImportDispatcher::new_empty_dispatcher()), + }; + + let solochain_handler = Self { + genesis_header, + node_metadata_repository, + stf_executor, + validator_accessor, + extrinsics_factory, + import_dispatcher, + }; + + Ok(solochain_handler) + } +} diff --git a/bitacross-worker/enclave-runtime/src/ipfs.rs b/bitacross-worker/enclave-runtime/src/ipfs.rs new file mode 100644 index 0000000000..c376456455 --- /dev/null +++ b/bitacross-worker/enclave-runtime/src/ipfs.rs @@ -0,0 +1,105 @@ +use cid::{Cid, Result as CidResult}; +use ipfs_unixfs::file::adder::FileAdder; +use log::*; +use multibase::Base; +use std::{convert::TryFrom, vec::Vec}; + +pub struct IpfsContent { + pub cid: CidResult, + pub file_content: Vec, + pub stats: Stats, +} +#[derive(Debug, PartialEq)] +pub enum IpfsError { + InputCidInvalid, + FinalCidMissing, + Verification, +} + +impl IpfsContent { + pub fn new(_cid: &str, _content: Vec) -> IpfsContent { + IpfsContent { cid: Cid::try_from(_cid), file_content: _content, stats: Stats::default() } + } + + pub fn verify(&mut self) -> Result<(), IpfsError> { + let mut adder: FileAdder = FileAdder::default(); + let mut total: usize = 0; + while total < self.file_content.len() { + #[allow(clippy::string_slice)] + let bytes = &self.file_content.get(total..).ok_or(IpfsError::Verification)?; + let (blocks, consumed) = adder.push(bytes); + total = total.saturating_add(consumed); + self.stats.process(blocks); + } + let blocks = adder.finish(); + self.stats.process(blocks); + + if let Some(last_cid) = self.stats.last.as_ref() { + let cid_str = Base::Base58Btc.encode(last_cid.hash().as_bytes()); + info!( + "new cid: {} generated from {} blocks, total of {} bytes", + cid_str, self.stats.blocks, self.stats.block_bytes + ); + match self.cid.as_ref() { + Ok(initial_cid) => + if last_cid.hash().eq(&initial_cid.hash()) { + Ok(()) + } else { + Err(IpfsError::Verification) + }, + Err(_) => Err(IpfsError::InputCidInvalid), + } + } else { + Err(IpfsError::FinalCidMissing) + } + } +} +#[derive(Default)] +pub struct Stats { + pub blocks: usize, + pub block_bytes: u64, + pub last: Option, +} + +impl Stats { + fn process)>>(&mut self, new_blocks: I) { + for (cid, block) in new_blocks { + self.last = Some(cid); + self.blocks = self.blocks.saturating_add(1); + self.block_bytes = self.block_bytes.saturating_add(block.len() as u64); + } + } +} + +#[allow(unused)] +pub fn test_creates_ipfs_content_struct_works() { + let cid = "QmSaFjwJ2QtS3rZDKzC98XEzv2bqT4TfpWLCpphPPwyQTr"; + let content: Vec = vec![20; 512 * 1024]; + let ipfs_content = IpfsContent::new(cid, content.clone()); + + #[allow(clippy::unwrap_used)] + let cid_str = Base::Base58Btc.encode(ipfs_content.cid.as_ref().unwrap().hash().as_bytes()); + assert_eq!(cid_str, cid); + assert_eq!(ipfs_content.file_content, content); +} + +#[allow(unused)] +pub fn test_verification_ok_for_correct_content() { + let cid = "QmSaFjwJ2QtS3rZDKzC98XEzv2bqT4TfpWLCpphPPwyQTr"; + let content: Vec = vec![20; 512 * 1024]; + let mut ipfs_content = IpfsContent::new(cid, content); + let verification = ipfs_content.verify(); + assert!(verification.is_ok()); +} + +#[allow(unused)] +pub fn test_verification_fails_for_incorrect_content() { + let cid = "QmSaFjwJ2QtS3rZDKzC98XEzv2bqT4TfpWLCpphPPwyQTr"; + let content: Vec = vec![10; 512 * 1024]; + let mut ipfs_content = IpfsContent::new(cid, content); + let verification = ipfs_content.verify(); + #[allow(clippy::unwrap_used)] + { + assert_eq!(verification.unwrap_err(), IpfsError::Verification); + } +} diff --git a/bitacross-worker/enclave-runtime/src/lib.rs b/bitacross-worker/enclave-runtime/src/lib.rs new file mode 100644 index 0000000000..9c3b078558 --- /dev/null +++ b/bitacross-worker/enclave-runtime/src/lib.rs @@ -0,0 +1,708 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ +#![feature(structural_match)] +#![feature(rustc_attrs)] +#![feature(core_intrinsics)] +#![feature(derive_eq)] +#![feature(trait_alias)] +#![crate_name = "enclave_runtime"] +#![crate_type = "staticlib"] +#![cfg_attr(not(target_env = "sgx"), no_std)] +#![cfg_attr(target_env = "sgx", feature(rustc_private))] +#![allow(clippy::missing_safety_doc)] +#![warn( + clippy::unwrap_used, + clippy::unreachable, + /* comment out for the moment. There are some upstream code `unimplemented` */ + // clippy::unimplemented, + // clippy::panic_in_result_fn, + clippy::string_slice, + clippy::panic, + clippy::indexing_slicing, + clippy::expect_used, + clippy::arithmetic_side_effects +)] + +#[cfg(not(target_env = "sgx"))] +#[macro_use] +extern crate sgx_tstd as std; + +use crate::{ + error::{Error, Result}, + initialization::global_components::{ + GLOBAL_INTEGRITEE_PARACHAIN_HANDLER_COMPONENT, GLOBAL_INTEGRITEE_PARENTCHAIN_NONCE_CACHE, + GLOBAL_INTEGRITEE_SOLOCHAIN_HANDLER_COMPONENT, GLOBAL_SHIELDING_KEY_REPOSITORY_COMPONENT, + GLOBAL_SIDECHAIN_IMPORT_QUEUE_COMPONENT, GLOBAL_SIGNING_KEY_REPOSITORY_COMPONENT, + GLOBAL_STATE_HANDLER_COMPONENT, GLOBAL_TARGET_A_PARACHAIN_HANDLER_COMPONENT, + GLOBAL_TARGET_A_PARENTCHAIN_NONCE_CACHE, GLOBAL_TARGET_A_SOLOCHAIN_HANDLER_COMPONENT, + GLOBAL_TARGET_B_PARACHAIN_HANDLER_COMPONENT, GLOBAL_TARGET_B_PARENTCHAIN_NONCE_CACHE, + GLOBAL_TARGET_B_SOLOCHAIN_HANDLER_COMPONENT, + }, + rpc::worker_api_direct::sidechain_io_handler, + utils::{ + get_node_metadata_repository_from_integritee_solo_or_parachain, + get_node_metadata_repository_from_target_a_solo_or_parachain, + get_node_metadata_repository_from_target_b_solo_or_parachain, + get_validator_accessor_from_integritee_solo_or_parachain, utf8_str_from_raw, DecodeRaw, + }, +}; +use codec::Decode; +use core::ffi::c_int; +use itc_parentchain::{ + block_import_dispatcher::DispatchBlockImport, + light_client::{concurrent_access::ValidatorAccess, Validator}, + primitives::ParentchainId, +}; +use itp_component_container::ComponentGetter; +use itp_import_queue::PushToQueue; +use itp_node_api::metadata::NodeMetadata; +use itp_nonce_cache::{MutateNonce, Nonce}; +use itp_settings::worker_mode::{ProvideWorkerMode, WorkerMode, WorkerModeProvider}; +use itp_sgx_crypto::key_repository::AccessPubkey; +use itp_storage::{StorageProof, StorageProofChecker}; +use itp_types::{ShardIdentifier, SignedBlock}; +use itp_utils::{if_production_or, write_slice_and_whitespace_pad}; +use log::*; +use once_cell::sync::OnceCell; +use sgx_types::sgx_status_t; +use sp_runtime::traits::BlakeTwo256; +use std::{ + path::PathBuf, + slice, + string::{String, ToString}, + vec::Vec, +}; +mod attestation; +mod empty_impls; +mod initialization; +mod ipfs; +mod ocall; +mod shard_vault; +mod stf_task_handler; +mod utils; + +pub mod error; +pub mod rpc; +mod sync; +mod tls_ra; +pub mod top_pool_execution; + +#[cfg(feature = "teeracle")] +pub mod teeracle; + +#[cfg(feature = "test")] +pub mod test; + +pub type Hash = sp_core::H256; +pub type AuthorityPair = sp_core::ed25519::Pair; + +static BASE_PATH: OnceCell = OnceCell::new(); + +fn get_base_path() -> Result { + let base_path = BASE_PATH.get().ok_or_else(|| { + Error::Other("BASE_PATH not initialized. Broken enclave init flow!".to_string().into()) + })?; + + Ok(base_path.clone()) +} + +/// Initialize the enclave. +#[no_mangle] +pub unsafe extern "C" fn init( + mu_ra_addr: *const u8, + mu_ra_addr_size: u32, + untrusted_worker_addr: *const u8, + untrusted_worker_addr_size: u32, + encoded_base_dir_str: *const u8, + encoded_base_dir_size: u32, +) -> sgx_status_t { + // Initialize the logging environment in the enclave. + if_production_or!( + { + let module_names = litentry_macros::local_modules!(); + println!( + "Initializing logger to filter only following local modules: {:?}", + module_names + ); + let mut builder = env_logger::Builder::new(); + builder.filter(None, LevelFilter::Off); + module_names.into_iter().for_each(|module| { + builder.filter(Some(module), LevelFilter::Info); + }); + builder.init(); + }, + env_logger::init() + ); + + let mu_ra_url = + match String::decode(&mut slice::from_raw_parts(mu_ra_addr, mu_ra_addr_size as usize)) + .map_err(Error::Codec) + { + Ok(addr) => addr, + Err(e) => return e.into(), + }; + + let untrusted_worker_url = match String::decode(&mut slice::from_raw_parts( + untrusted_worker_addr, + untrusted_worker_addr_size as usize, + )) + .map_err(Error::Codec) + { + Ok(addr) => addr, + Err(e) => return e.into(), + }; + + let base_dir = match String::decode(&mut slice::from_raw_parts( + encoded_base_dir_str, + encoded_base_dir_size as usize, + )) + .map_err(Error::Codec) + { + Ok(b) => b, + Err(e) => return e.into(), + }; + + info!("Setting base_dir to {}", base_dir); + let path = PathBuf::from(base_dir); + // Litentry: the default value here is only for clippy checking + BASE_PATH.set(path.clone()).unwrap_or(()); + + match initialization::init_enclave(mu_ra_url, untrusted_worker_url, path) { + Err(e) => e.into(), + Ok(()) => sgx_status_t::SGX_SUCCESS, + } +} + +#[no_mangle] +pub unsafe extern "C" fn get_rsa_encryption_pubkey( + pubkey: *mut u8, + pubkey_size: u32, +) -> sgx_status_t { + let shielding_key_repository = match GLOBAL_SHIELDING_KEY_REPOSITORY_COMPONENT.get() { + Ok(s) => s, + Err(e) => { + error!("{:?}", e); + return sgx_status_t::SGX_ERROR_UNEXPECTED + }, + }; + + let rsa_pubkey = match shielding_key_repository.retrieve_pubkey() { + Ok(key) => key, + Err(e) => return e.into(), + }; + + let rsa_pubkey_json = match serde_json::to_string(&rsa_pubkey) { + Ok(k) => k, + Err(x) => { + println!("[Enclave] can't serialize rsa_pubkey {:?} {}", rsa_pubkey, x); + return sgx_status_t::SGX_ERROR_UNEXPECTED + }, + }; + + let pubkey_slice = slice::from_raw_parts_mut(pubkey, pubkey_size as usize); + + if let Err(e) = + write_slice_and_whitespace_pad(pubkey_slice, rsa_pubkey_json.as_bytes().to_vec()) + { + return Error::BufferError(e).into() + }; + + sgx_status_t::SGX_SUCCESS +} + +#[no_mangle] +pub unsafe extern "C" fn get_ecc_signing_pubkey(pubkey: *mut u8, pubkey_size: u32) -> sgx_status_t { + let signing_key_repository = match GLOBAL_SIGNING_KEY_REPOSITORY_COMPONENT.get() { + Ok(s) => s, + Err(e) => { + error!("{:?}", e); + return sgx_status_t::SGX_ERROR_UNEXPECTED + }, + }; + + let signer_public = match signing_key_repository.retrieve_pubkey() { + Ok(s) => s, + Err(e) => return e.into(), + }; + + debug!("Restored ECC pubkey: {:?}", signer_public); + + let pubkey_slice = slice::from_raw_parts_mut(pubkey, pubkey_size as usize); + pubkey_slice.clone_from_slice(&signer_public); + + sgx_status_t::SGX_SUCCESS +} + +#[no_mangle] +pub unsafe extern "C" fn set_nonce( + nonce: *const u32, + parentchain_id: *const u8, + parentchain_id_size: u32, +) -> sgx_status_t { + let id = match ParentchainId::decode_raw(parentchain_id, parentchain_id_size as usize) { + Err(e) => { + error!("Failed to decode parentchain_id: {:?}", e); + return sgx_status_t::SGX_ERROR_UNEXPECTED + }, + Ok(m) => m, + }; + + info!("Setting the nonce of the enclave to: {} for parentchain: {:?}", *nonce, id); + + let nonce_lock = match id { + ParentchainId::Litentry => GLOBAL_INTEGRITEE_PARENTCHAIN_NONCE_CACHE.load_for_mutation(), + ParentchainId::TargetA => GLOBAL_TARGET_A_PARENTCHAIN_NONCE_CACHE.load_for_mutation(), + ParentchainId::TargetB => GLOBAL_TARGET_B_PARENTCHAIN_NONCE_CACHE.load_for_mutation(), + }; + + match nonce_lock { + Ok(mut nonce_guard) => *nonce_guard = Nonce(*nonce), + Err(e) => { + error!("Failed to set {:?} parentchain nonce in enclave: {:?}", id, e); + return sgx_status_t::SGX_ERROR_UNEXPECTED + }, + }; + + sgx_status_t::SGX_SUCCESS +} + +#[no_mangle] +pub unsafe extern "C" fn set_node_metadata( + node_metadata: *const u8, + node_metadata_size: u32, + parentchain_id: *const u8, + parentchain_id_size: u32, +) -> sgx_status_t { + let id = match ParentchainId::decode_raw(parentchain_id, parentchain_id_size as usize) { + Err(e) => { + error!("Failed to decode parentchain_id: {:?}", e); + return sgx_status_t::SGX_ERROR_UNEXPECTED + }, + Ok(m) => m, + }; + + let metadata = match NodeMetadata::decode_raw(node_metadata, node_metadata_size as usize) { + Err(e) => { + error!("Failed to decode node metadata: {:?}", e); + return sgx_status_t::SGX_ERROR_UNEXPECTED + }, + Ok(m) => m, + }; + + info!("Setting node meta data for parentchain: {:?}", id); + + let node_metadata_repository = match id { + ParentchainId::Litentry => get_node_metadata_repository_from_integritee_solo_or_parachain(), + ParentchainId::TargetA => get_node_metadata_repository_from_target_a_solo_or_parachain(), + ParentchainId::TargetB => get_node_metadata_repository_from_target_b_solo_or_parachain(), + }; + + match node_metadata_repository { + Ok(repo) => repo.set_metadata(metadata), + Err(e) => { + error!("Could not get {:?} parentchain component: {:?}", id, e); + return sgx_status_t::SGX_ERROR_UNEXPECTED + }, + }; + + info!("Successfully set the node meta data"); + + sgx_status_t::SGX_SUCCESS +} + +/// This is reduced to the sidechain block import RPC interface (i.e. worker-worker communication). +/// The entire rest of the RPC server is run inside the enclave and does not use this e-call function anymore. +#[no_mangle] +pub unsafe extern "C" fn call_rpc_methods( + request: *const u8, + request_len: u32, + response: *mut u8, + response_len: u32, +) -> sgx_status_t { + let request = match utf8_str_from_raw(request, request_len as usize) { + Ok(req) => req, + Err(e) => { + error!("[SidechainRpc] FFI: Invalid utf8 request: {:?}", e); + return sgx_status_t::SGX_ERROR_UNEXPECTED + }, + }; + + let res = match sidechain_rpc_int(request) { + Ok(res) => res, + Err(e) => { + error!("RPC request failed: {:?}", e); + return e.into() + }, + }; + + let response_slice = slice::from_raw_parts_mut(response, response_len as usize); + if let Err(e) = write_slice_and_whitespace_pad(response_slice, res.into_bytes()) { + return Error::BufferError(e).into() + }; + + sgx_status_t::SGX_SUCCESS +} + +fn sidechain_rpc_int(request: &str) -> Result { + let sidechain_block_import_queue = GLOBAL_SIDECHAIN_IMPORT_QUEUE_COMPONENT.get()?; + + let io = sidechain_io_handler(move |signed_block| { + sidechain_block_import_queue.push_single(signed_block) + }); + + // note: errors are still returned as Option + Ok(io + .handle_request_sync(request) + .unwrap_or_else(|| format!("Empty rpc response for request: {}", request))) +} + +/// Initialize sidechain enclave components. +/// +/// Call this once at startup. Has to be called AFTER the light-client +/// (parentchain components) have been initialized (because we need the parentchain +/// block import dispatcher). +#[no_mangle] +pub unsafe extern "C" fn init_enclave_sidechain_components( + fail_mode: *const u8, + fail_mode_size: u32, + fail_at: *const u8, + fail_at_size: u32, +) -> sgx_status_t { + let fail_mode = match Option::::decode_raw(fail_mode, fail_mode_size as usize) { + Ok(s) => s, + Err(e) => { + error!("failed to decode fail mode {:?}", e); + return sgx_status_t::SGX_ERROR_UNEXPECTED + }, + }; + let fail_at = match u64::decode_raw(fail_at, fail_at_size as usize) { + Ok(v) => v, + Err(e) => { + error!("failed to decode fail at {:?}", e); + return sgx_status_t::SGX_ERROR_UNEXPECTED + }, + }; + if let Err(e) = initialization::init_enclave_sidechain_components(fail_mode, fail_at) { + error!("Failed to initialize sidechain components: {:?}", e); + return sgx_status_t::SGX_ERROR_UNEXPECTED + } + + sgx_status_t::SGX_SUCCESS +} + +/// Call this once at worker startup to initialize the TOP pool and direct invocation RPC server. +/// +/// This function will run the RPC server on the same thread as it is called and will loop there. +/// That means that this function will not return as long as the RPC server is running. The calling +/// code should therefore spawn a new thread when calling this function. +#[no_mangle] +pub unsafe extern "C" fn init_direct_invocation_server( + server_addr: *const u8, + server_addr_size: usize, +) -> sgx_status_t { + let mut server_addr_encoded = slice::from_raw_parts(server_addr, server_addr_size); + + let server_addr = match String::decode(&mut server_addr_encoded) { + Ok(s) => s, + Err(e) => { + error!("Decoding RPC server address failed. Error: {:?}", e); + return sgx_status_t::SGX_ERROR_UNEXPECTED + }, + }; + + if let Err(e) = initialization::init_direct_invocation_server(server_addr) { + error!("Failed to initialize direct invocation server: {:?}", e); + return sgx_status_t::SGX_ERROR_UNEXPECTED + } + + sgx_status_t::SGX_SUCCESS +} + +#[no_mangle] +pub unsafe extern "C" fn init_parentchain_components( + params: *const u8, + params_size: usize, + latest_header: *mut u8, + latest_header_size: usize, +) -> sgx_status_t { + info!("Initializing light client!"); + + let encoded_params = slice::from_raw_parts(params, params_size); + let latest_header_slice = slice::from_raw_parts_mut(latest_header, latest_header_size); + + match init_parentchain_params_internal(encoded_params.to_vec(), latest_header_slice) { + Ok(()) => sgx_status_t::SGX_SUCCESS, + Err(e) => e.into(), + } +} + +/// Initializes the parentchain components and writes the latest header into the `latest_header` slice. +fn init_parentchain_params_internal(params: Vec, latest_header: &mut [u8]) -> Result<()> { + use initialization::parentchain::init_parentchain_components; + + let encoded_latest_header = + init_parentchain_components::(get_base_path()?, params)?; + + write_slice_and_whitespace_pad(latest_header, encoded_latest_header)?; + + Ok(()) +} + +#[no_mangle] +pub unsafe extern "C" fn init_shard(shard: *const u8, shard_size: u32) -> sgx_status_t { + let shard_identifier = + ShardIdentifier::from_slice(slice::from_raw_parts(shard, shard_size as usize)); + + if let Err(e) = initialization::init_shard(shard_identifier) { + error!("Failed to initialize shard ({:?}): {:?}", shard_identifier, e); + return sgx_status_t::SGX_ERROR_UNEXPECTED + } + + sgx_status_t::SGX_SUCCESS +} + +#[no_mangle] +pub unsafe extern "C" fn migrate_shard( + old_shard: *const u8, + new_shard: *const u8, + shard_size: u32, +) -> sgx_status_t { + let old_shard_identifier = + ShardIdentifier::from_slice(slice::from_raw_parts(old_shard, shard_size as usize)); + + let new_shard_identifier = + ShardIdentifier::from_slice(slice::from_raw_parts(new_shard, shard_size as usize)); + + if let Err(e) = initialization::migrate_shard(old_shard_identifier, new_shard_identifier) { + error!("Failed to initialize shard ({:?}): {:?}", old_shard_identifier, e); + return sgx_status_t::SGX_ERROR_UNEXPECTED + } + + sgx_status_t::SGX_SUCCESS +} + +#[no_mangle] +pub unsafe extern "C" fn sync_parentchain( + blocks_to_sync: *const u8, + blocks_to_sync_size: usize, + events_to_sync: *const u8, + events_to_sync_size: usize, + events_proofs_to_sync: *const u8, + events_proofs_to_sync_size: usize, + parentchain_id: *const u8, + parentchain_id_size: u32, + is_syncing: c_int, +) -> sgx_status_t { + if let Err(e) = sync_parentchain_internal( + blocks_to_sync, + blocks_to_sync_size, + events_to_sync, + events_to_sync_size, + events_proofs_to_sync, + events_proofs_to_sync_size, + parentchain_id, + parentchain_id_size, + is_syncing == 1, + ) { + error!("Error synching parentchain: {:?}", e); + } + + sgx_status_t::SGX_SUCCESS +} + +#[allow(clippy::too_many_arguments)] +unsafe fn sync_parentchain_internal( + blocks_to_sync: *const u8, + blocks_to_sync_size: usize, + events_to_sync: *const u8, + events_to_sync_size: usize, + events_proofs_to_sync: *const u8, + events_proofs_to_sync_size: usize, + parentchain_id: *const u8, + parentchain_id_size: u32, + is_syncing: bool, +) -> Result<()> { + let blocks_to_sync = Vec::::decode_raw(blocks_to_sync, blocks_to_sync_size)?; + let events_proofs_to_sync = + Vec::::decode_raw(events_proofs_to_sync, events_proofs_to_sync_size)?; + let parentchain_id = ParentchainId::decode_raw(parentchain_id, parentchain_id_size as usize)?; + + let blocks_to_sync_merkle_roots: Vec = + blocks_to_sync.iter().map(|block| block.block.header.state_root).collect(); + + if let Err(e) = validate_events(&events_proofs_to_sync, &blocks_to_sync_merkle_roots) { + return e.into() + } + + let events_to_sync = Vec::>::decode_raw(events_to_sync, events_to_sync_size)?; + + dispatch_parentchain_blocks_for_import::( + blocks_to_sync, + events_to_sync, + &parentchain_id, + is_syncing, + ) +} + +#[no_mangle] +pub unsafe extern "C" fn ignore_parentchain_block_import_validation_until( + until: *const u32, +) -> sgx_status_t { + let va = match get_validator_accessor_from_integritee_solo_or_parachain() { + Ok(r) => r, + Err(e) => { + error!("Can't get validator accessor: {:?}", e); + return sgx_status_t::SGX_ERROR_UNEXPECTED + }, + }; + + let _ = va.execute_mut_on_validator(|v| v.set_ignore_validation_until(*until)); + + sgx_status_t::SGX_SUCCESS +} + +/// Dispatch the parentchain blocks for import. +/// Depending on the worker mode, a different dispatcher is used: +/// +/// * An immediate dispatcher will immediately import any parentchain blocks and execute +/// the corresponding extrinsics (offchain-worker executor). +/// * The sidechain uses a triggered dispatcher, where the import of a parentchain block is +/// synchronized and triggered by the sidechain block production cycle. +/// +fn dispatch_parentchain_blocks_for_import( + blocks_to_sync: Vec, + events_to_sync: Vec>, + id: &ParentchainId, + is_syncing: bool, +) -> Result<()> { + if WorkerModeProvider::worker_mode() == WorkerMode::Teeracle { + trace!("Not importing any parentchain blocks"); + return Ok(()) + } + trace!( + "[{:?}] Dispatching Import of {} blocks and {} events", + id, + blocks_to_sync.len(), + events_to_sync.len() + ); + match id { + ParentchainId::Litentry => { + if let Ok(handler) = GLOBAL_INTEGRITEE_SOLOCHAIN_HANDLER_COMPONENT.get() { + handler.import_dispatcher.dispatch_import( + blocks_to_sync, + events_to_sync, + is_syncing, + )?; + } else if let Ok(handler) = GLOBAL_INTEGRITEE_PARACHAIN_HANDLER_COMPONENT.get() { + handler.import_dispatcher.dispatch_import( + blocks_to_sync, + events_to_sync, + is_syncing, + )?; + } else { + return Err(Error::NoLitentryParentchainAssigned) + }; + }, + ParentchainId::TargetA => { + if let Ok(handler) = GLOBAL_TARGET_A_SOLOCHAIN_HANDLER_COMPONENT.get() { + handler.import_dispatcher.dispatch_import( + blocks_to_sync, + events_to_sync, + is_syncing, + )?; + } else if let Ok(handler) = GLOBAL_TARGET_A_PARACHAIN_HANDLER_COMPONENT.get() { + handler.import_dispatcher.dispatch_import( + blocks_to_sync, + events_to_sync, + is_syncing, + )?; + } else { + return Err(Error::NoTargetAParentchainAssigned) + }; + }, + ParentchainId::TargetB => { + if let Ok(handler) = GLOBAL_TARGET_B_SOLOCHAIN_HANDLER_COMPONENT.get() { + handler.import_dispatcher.dispatch_import( + blocks_to_sync, + events_to_sync, + is_syncing, + )?; + } else if let Ok(handler) = GLOBAL_TARGET_B_PARACHAIN_HANDLER_COMPONENT.get() { + handler.import_dispatcher.dispatch_import( + blocks_to_sync, + events_to_sync, + is_syncing, + )?; + } else { + return Err(Error::NoTargetBParentchainAssigned) + }; + }, + } + + Ok(()) +} + +/// Validates the events coming from the parentchain +fn validate_events( + events_proofs: &Vec, + blocks_merkle_roots: &Vec, +) -> Result<()> { + info!( + "Validating events, events_proofs_length: {:?}, blocks_merkle_roots_lengths: {:?}", + events_proofs.len(), + blocks_merkle_roots.len() + ); + + if events_proofs.len() != blocks_merkle_roots.len() { + return Err(Error::ParentChainSync) + } + + let events_key = itp_storage::storage_value_key("System", "Events"); + + let validated_events: Result>> = events_proofs + .iter() + .zip(blocks_merkle_roots.iter()) + .map(|(proof, root)| { + StorageProofChecker::::check_proof( + *root, + events_key.as_slice(), + proof.clone(), + ) + .ok() + .flatten() + .ok_or_else(|| Error::ParentChainValidation(itp_storage::Error::WrongValue)) + }) + .collect(); + + let _ = validated_events?; + + Ok(()) +} + +// This is required, because `ring` / `ring-xous` would not compile without it non-release (debug) mode. +// See #1200 for more details. +#[cfg(debug_assertions)] +#[no_mangle] +pub extern "C" fn __assert_fail( + __assertion: *const u8, + __file: *const u8, + __line: u32, + __function: *const u8, +) -> ! { + use core::intrinsics::abort; + abort() +} diff --git a/bitacross-worker/enclave-runtime/src/ocall/attestation_ocall.rs b/bitacross-worker/enclave-runtime/src/ocall/attestation_ocall.rs new file mode 100644 index 0000000000..3a3abbae9e --- /dev/null +++ b/bitacross-worker/enclave-runtime/src/ocall/attestation_ocall.rs @@ -0,0 +1,275 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::ocall::{ffi, OcallApi}; +use frame_support::ensure; +use itp_ocall_api::EnclaveAttestationOCallApi; +use lazy_static::lazy_static; +use log::*; +use sgx_tse::rsgx_create_report; +use sgx_types::*; +use std::{ptr, sync::Arc, vec::Vec}; + +use std::sync::SgxRwLock as RwLock; + +const RET_QUOTE_BUF_LEN: usize = 2048; + +lazy_static! { + /// Global cache of MRENCLAVE + /// will never change at runtime but must be initialized at runtime + static ref MY_MRENCLAVE: RwLock> = RwLock::new(Default::default()); +} + +#[derive(Default, Copy, Clone, Debug)] +pub struct MrEnclave { + pub maybe_mrenclave: Option, +} + +impl MrEnclave { + pub fn current() -> SgxResult> { + Ok(MY_MRENCLAVE + .read() + .map_err(|e| { + error!("fetching current value of MR_ENCLAVE lazy static failed: {:?}", e); + sgx_status_t::SGX_ERROR_UNEXPECTED + })? + .clone()) + } + pub fn make_current(self) -> SgxResult<()> { + *MY_MRENCLAVE.write().map_err(|e| { + error!("writing current value of MR_ENCLAVE lazy static failed: {:?}", e); + sgx_status_t::SGX_ERROR_UNEXPECTED + })? = Arc::new(self); + Ok(()) + } +} + +impl EnclaveAttestationOCallApi for OcallApi { + fn sgx_init_quote(&self) -> SgxResult<(sgx_target_info_t, sgx_epid_group_id_t)> { + let mut ti: sgx_target_info_t = sgx_target_info_t::default(); + let mut eg: sgx_epid_group_id_t = sgx_epid_group_id_t::default(); + let mut rt: sgx_status_t = sgx_status_t::SGX_ERROR_UNEXPECTED; + + let res = unsafe { + ffi::ocall_sgx_init_quote( + &mut rt as *mut sgx_status_t, + &mut ti as *mut sgx_target_info_t, + &mut eg as *mut sgx_epid_group_id_t, + ) + }; + + ensure!(res == sgx_status_t::SGX_SUCCESS, res); + ensure!(rt == sgx_status_t::SGX_SUCCESS, rt); + + Ok((ti, eg)) + } + + fn get_ias_socket(&self) -> SgxResult { + let mut rt: sgx_status_t = sgx_status_t::SGX_ERROR_UNEXPECTED; + let mut ias_sock: i32 = 0; + + let res = unsafe { + ffi::ocall_get_ias_socket(&mut rt as *mut sgx_status_t, &mut ias_sock as *mut i32) + }; + + ensure!(res == sgx_status_t::SGX_SUCCESS, res); + ensure!(rt == sgx_status_t::SGX_SUCCESS, rt); + + Ok(ias_sock) + } + + fn get_quote( + &self, + sig_rl: Vec, + report: sgx_report_t, + sign_type: sgx_quote_sign_type_t, + spid: sgx_spid_t, + quote_nonce: sgx_quote_nonce_t, + ) -> SgxResult<(sgx_report_t, Vec)> { + let mut qe_report = sgx_report_t::default(); + let mut return_quote_buf = [0u8; RET_QUOTE_BUF_LEN]; + let mut quote_len: u32 = 0; + + let (p_sigrl, sigrl_len) = if sig_rl.is_empty() { + (ptr::null(), 0) + } else { + (sig_rl.as_ptr(), sig_rl.len() as u32) + }; + let p_report = &report as *const sgx_report_t; + let quote_type = sign_type; + + let mut rt: sgx_status_t = sgx_status_t::SGX_ERROR_UNEXPECTED; + let p_spid = &spid as *const sgx_spid_t; + let p_nonce = "e_nonce as *const sgx_quote_nonce_t; + let p_qe_report = &mut qe_report as *mut sgx_report_t; + let p_quote = return_quote_buf.as_mut_ptr(); + let maxlen = RET_QUOTE_BUF_LEN as u32; + let p_quote_len = &mut quote_len as *mut u32; + + let result = unsafe { + ffi::ocall_get_quote( + &mut rt as *mut sgx_status_t, + p_sigrl, + sigrl_len, + p_report, + quote_type, + p_spid, + p_nonce, + p_qe_report, + p_quote, + maxlen, + p_quote_len, + ) + }; + + ensure!(result == sgx_status_t::SGX_SUCCESS, result); + ensure!(rt == sgx_status_t::SGX_SUCCESS, rt); + + #[allow(clippy::indexing_slicing)] + let quote_vec: Vec = Vec::from(&return_quote_buf[..quote_len as usize]); + + Ok((qe_report, quote_vec)) + } + + fn get_dcap_quote(&self, report: sgx_report_t, quote_size: u32) -> SgxResult> { + let mut return_quote_buf = vec![0u8; quote_size as usize]; + let p_quote = return_quote_buf.as_mut_ptr(); + let p_report = &report as *const sgx_report_t; + let mut rt: sgx_status_t = sgx_status_t::SGX_ERROR_UNEXPECTED; + + let result = unsafe { + ffi::ocall_get_dcap_quote(&mut rt as *mut sgx_status_t, p_report, p_quote, quote_size) + }; + ensure!(result == sgx_status_t::SGX_SUCCESS, result); + ensure!(rt == sgx_status_t::SGX_SUCCESS, rt); + #[allow(clippy::indexing_slicing)] + let quote_vec: Vec = Vec::from(&return_quote_buf[..quote_size as usize]); + Ok(quote_vec) + } + + fn get_qve_report_on_quote( + &self, + quote: Vec, + current_time: i64, + quote_collateral: sgx_ql_qve_collateral_t, + qve_report_info: sgx_ql_qe_report_info_t, + supplemental_data_size: u32, + ) -> SgxResult<(u32, sgx_ql_qv_result_t, sgx_ql_qe_report_info_t, Vec)> { + let mut supplemental_data = vec![0u8; supplemental_data_size as usize]; + let mut qve_report_info_return_value: sgx_ql_qe_report_info_t = qve_report_info; + let mut quote_verification_result = sgx_ql_qv_result_t::SGX_QL_QV_RESULT_UNSPECIFIED; + let mut collateral_expiration_status = 1u32; + let mut rt: sgx_status_t = sgx_status_t::SGX_ERROR_UNEXPECTED; + + let result = unsafe { + ffi::ocall_get_qve_report_on_quote( + &mut rt as *mut sgx_status_t, + quote.as_ptr(), + quote.len() as u32, + current_time, + "e_collateral as *const sgx_ql_qve_collateral_t, + &mut collateral_expiration_status as *mut u32, + &mut quote_verification_result as *mut sgx_ql_qv_result_t, + &mut qve_report_info_return_value as *mut sgx_ql_qe_report_info_t, + supplemental_data.as_mut_ptr(), + supplemental_data_size, + ) + }; + ensure!(result == sgx_status_t::SGX_SUCCESS, result); + ensure!(rt == sgx_status_t::SGX_SUCCESS, rt); + + Ok(( + collateral_expiration_status, + quote_verification_result, + qve_report_info_return_value, + supplemental_data.to_vec(), + )) + } + + fn get_update_info( + &self, + platform_info: sgx_platform_info_t, + enclave_trusted: i32, + ) -> SgxResult { + let mut rt: sgx_status_t = sgx_status_t::SGX_ERROR_UNEXPECTED; + let mut update_info = sgx_update_info_bit_t::default(); + + let result = unsafe { + ffi::ocall_get_update_info( + &mut rt as *mut sgx_status_t, + &platform_info as *const sgx_platform_info_t, + enclave_trusted, + &mut update_info as *mut sgx_update_info_bit_t, + ) + }; + + // debug logging + if rt != sgx_status_t::SGX_SUCCESS { + warn!("ocall_get_update_info unsuccessful. rt={:?}", rt); + // Curly braces to copy `unaligned_references` of packed fields into properly aligned temporary: + // https://github.com/rust-lang/rust/issues/82523 + debug!("update_info.pswUpdate: {}", { update_info.pswUpdate }); + debug!("update_info.csmeFwUpdate: {}", { update_info.csmeFwUpdate }); + debug!("update_info.ucodeUpdate: {}", { update_info.ucodeUpdate }); + } + + ensure!(result == sgx_status_t::SGX_SUCCESS, result); + ensure!(rt == sgx_status_t::SGX_SUCCESS, rt); + + Ok(update_info) + } + + fn get_mrenclave_of_self(&self) -> SgxResult { + if let Some(mrenclave) = MrEnclave::current()?.maybe_mrenclave { + trace!("found cached MRENCLAVE"); + return Ok(mrenclave) + }; + debug!("initializing MY_MRENCLAVE cache"); + let mrenclave_value = self.get_report_of_self()?.mr_enclave; + MrEnclave { maybe_mrenclave: Some(mrenclave_value) }.make_current()?; + Ok(mrenclave_value) + } +} + +trait GetSgxReport { + fn get_report_of_self(&self) -> SgxResult; +} + +impl GetSgxReport for T { + fn get_report_of_self(&self) -> SgxResult { + // (1) get ti + eg + let init_quote_result = self.sgx_init_quote()?; + + let target_info = init_quote_result.0; + let report_data: sgx_report_data_t = sgx_report_data_t::default(); + + let rep = match rsgx_create_report(&target_info, &report_data) { + Ok(r) => { + debug!( + " [Enclave] Report creation successful. mr_signer.m = {:?}", + r.body.mr_signer.m + ); + r + }, + Err(e) => { + error!(" [Enclave] Report creation failed. {:?}", e); + return Err(e) + }, + }; + Ok(rep.body) + } +} diff --git a/bitacross-worker/enclave-runtime/src/ocall/ffi.rs b/bitacross-worker/enclave-runtime/src/ocall/ffi.rs new file mode 100644 index 0000000000..388cc0c54a --- /dev/null +++ b/bitacross-worker/enclave-runtime/src/ocall/ffi.rs @@ -0,0 +1,138 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 sgx_types::*; + +extern "C" { + pub fn ocall_sgx_init_quote( + ret_val: *mut sgx_status_t, + ret_ti: *mut sgx_target_info_t, + ret_gid: *mut sgx_epid_group_id_t, + ) -> sgx_status_t; + + pub fn ocall_get_ias_socket(ret_val: *mut sgx_status_t, ret_fd: *mut i32) -> sgx_status_t; + + pub fn ocall_get_quote( + ret_val: *mut sgx_status_t, + p_sigrl: *const u8, + sigrl_len: u32, + p_report: *const sgx_report_t, + quote_type: sgx_quote_sign_type_t, + p_spid: *const sgx_spid_t, + p_nonce: *const sgx_quote_nonce_t, + p_qe_report: *mut sgx_report_t, + p_quote: *mut u8, + maxlen: u32, + p_quote_len: *mut u32, + ) -> sgx_status_t; + + pub fn ocall_get_dcap_quote( + ret_val: *mut sgx_status_t, + p_report: *const sgx_report_t, + p_quote: *mut u8, + quote_size: u32, + ) -> sgx_status_t; + + pub fn ocall_get_qve_report_on_quote( + ret_val: *mut sgx_status_t, + p_quote: *const u8, + quote_len: u32, + current_time: i64, + p_quote_collateral: *const sgx_ql_qve_collateral_t, + p_collateral_expiration_status: *mut u32, + p_quote_verification_result: *mut sgx_ql_qv_result_t, + p_qve_report_info: *mut sgx_ql_qe_report_info_t, + p_supplemental_data: *mut u8, + supplemental_data_size: u32, + ) -> sgx_status_t; + + pub fn ocall_get_update_info( + ret_val: *mut sgx_status_t, + platform_blob: *const sgx_platform_info_t, + enclave_trusted: i32, + update_info: *mut sgx_update_info_bit_t, + ) -> sgx_status_t; + + pub fn ocall_worker_request( + ret_val: *mut sgx_status_t, + request: *const u8, + req_size: u32, + parentchain_id: *const u8, + parentchain_id_size: u32, + response: *mut u8, + resp_size: u32, + ) -> sgx_status_t; + + pub fn ocall_update_metric( + ret_val: *mut sgx_status_t, + metric_ptr: *const u8, + metric_size: u32, + ) -> sgx_status_t; + + pub fn ocall_propose_sidechain_blocks( + ret_val: *mut sgx_status_t, + signed_blocks: *const u8, + signed_blocks_size: u32, + ) -> sgx_status_t; + + pub fn ocall_store_sidechain_blocks( + ret_val: *mut sgx_status_t, + signed_blocks: *const u8, + signed_blocks_size: u32, + ) -> sgx_status_t; + + pub fn ocall_fetch_sidechain_blocks_from_peer( + ret_val: *mut sgx_status_t, + last_imported_block_hash: *const u8, + last_imported_block_hash_size: u32, + maybe_until_block_hash: *const u8, + maybe_until_block_hash_encoded_size: u32, + shard_identifier: *const u8, + shard_identifier_size: u32, + sidechain_blocks: *mut u8, + sidechain_blocks_size: u32, + ) -> sgx_status_t; + + pub fn ocall_get_trusted_peers_urls( + ret_val: *mut sgx_status_t, + peers: *mut u8, + peers_size: u32, + ) -> sgx_status_t; + + pub fn ocall_send_to_parentchain( + ret_val: *mut sgx_status_t, + extrinsics: *const u8, + extrinsics_size: u32, + parentchain_id: *const u8, + parentchain_id_size: u32, + await_each_inclusion: c_int, + ) -> sgx_status_t; + + pub fn ocall_read_ipfs( + ret_val: *mut sgx_status_t, + cid: *const u8, + cid_size: u32, + ) -> sgx_status_t; + + pub fn ocall_write_ipfs( + ret_val: *mut sgx_status_t, + enc_state: *const u8, + enc_state_size: u32, + cid: *mut u8, + cid_size: u32, + ) -> sgx_status_t; +} diff --git a/bitacross-worker/enclave-runtime/src/ocall/ipfs_ocall.rs b/bitacross-worker/enclave-runtime/src/ocall/ipfs_ocall.rs new file mode 100644 index 0000000000..d1a5530856 --- /dev/null +++ b/bitacross-worker/enclave-runtime/src/ocall/ipfs_ocall.rs @@ -0,0 +1,57 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::ocall::{ffi, OcallApi}; +use frame_support::ensure; +use itp_ocall_api::{EnclaveIpfsOCallApi, IpfsCid}; +use sgx_types::{sgx_status_t, SgxResult}; + +impl EnclaveIpfsOCallApi for OcallApi { + fn write_ipfs(&self, encoded_state: &[u8]) -> SgxResult { + let mut rt: sgx_status_t = sgx_status_t::SGX_ERROR_UNEXPECTED; + let mut cid_buf = IpfsCid([0u8; 46]); + + let res = unsafe { + ffi::ocall_write_ipfs( + &mut rt as *mut sgx_status_t, + encoded_state.as_ptr(), + encoded_state.len() as u32, + cid_buf.0.as_mut_ptr(), + cid_buf.0.len() as u32, + ) + }; + + ensure!(rt == sgx_status_t::SGX_SUCCESS, rt); + ensure!(res == sgx_status_t::SGX_SUCCESS, res); + + Ok(cid_buf) + } + + fn read_ipfs(&self, cid: &IpfsCid) -> SgxResult<()> { + let mut rt: sgx_status_t = sgx_status_t::SGX_ERROR_UNEXPECTED; + + let res = unsafe { + ffi::ocall_read_ipfs(&mut rt as *mut sgx_status_t, cid.0.as_ptr(), cid.0.len() as u32) + }; + + ensure!(rt == sgx_status_t::SGX_SUCCESS, rt); + ensure!(res == sgx_status_t::SGX_SUCCESS, res); + + Ok(()) + } +} diff --git a/bitacross-worker/enclave-runtime/src/ocall/metrics_ocall.rs b/bitacross-worker/enclave-runtime/src/ocall/metrics_ocall.rs new file mode 100644 index 0000000000..0d12dfd7d6 --- /dev/null +++ b/bitacross-worker/enclave-runtime/src/ocall/metrics_ocall.rs @@ -0,0 +1,42 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::ocall::{ffi, OcallApi}; +use codec::Encode; +use frame_support::ensure; +use itp_ocall_api::EnclaveMetricsOCallApi; +use sgx_types::{sgx_status_t, SgxResult}; + +impl EnclaveMetricsOCallApi for OcallApi { + fn update_metric(&self, metric: Metric) -> SgxResult<()> { + let mut rt: sgx_status_t = sgx_status_t::SGX_ERROR_UNEXPECTED; + let metric_encoded = metric.encode(); + + let res = unsafe { + ffi::ocall_update_metric( + &mut rt as *mut sgx_status_t, + metric_encoded.as_ptr(), + metric_encoded.len() as u32, + ) + }; + + ensure!(rt == sgx_status_t::SGX_SUCCESS, rt); + ensure!(res == sgx_status_t::SGX_SUCCESS, res); + + Ok(()) + } +} diff --git a/bitacross-worker/enclave-runtime/src/ocall/mod.rs b/bitacross-worker/enclave-runtime/src/ocall/mod.rs new file mode 100644 index 0000000000..7374b63fde --- /dev/null +++ b/bitacross-worker/enclave-runtime/src/ocall/mod.rs @@ -0,0 +1,26 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 attestation_ocall; +mod ffi; +mod ipfs_ocall; +mod metrics_ocall; +mod on_chain_ocall; +mod sidechain_ocall; + +#[derive(Clone, Debug, Default)] +pub struct OcallApi; diff --git a/bitacross-worker/enclave-runtime/src/ocall/on_chain_ocall.rs b/bitacross-worker/enclave-runtime/src/ocall/on_chain_ocall.rs new file mode 100644 index 0000000000..95b9183269 --- /dev/null +++ b/bitacross-worker/enclave-runtime/src/ocall/on_chain_ocall.rs @@ -0,0 +1,144 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::ocall::{ffi, OcallApi}; +use codec::{Decode, Encode}; +use frame_support::ensure; +use itc_parentchain::primitives::ParentchainId; +use itp_ocall_api::{EnclaveOnChainOCallApi, Result}; +use itp_storage::{verify_storage_entries, Error as StorageError}; +use itp_types::{storage::StorageEntryVerified, WorkerRequest, WorkerResponse, H256}; +use log::*; +use sgx_types::*; +use sp_runtime::{traits::Header, OpaqueExtrinsic}; +use std::vec::Vec; + +impl EnclaveOnChainOCallApi for OcallApi { + fn send_to_parentchain( + &self, + extrinsics: Vec, + parentchain_id: &ParentchainId, + await_each_inclusion: bool, + ) -> SgxResult<()> { + let mut rt: sgx_status_t = sgx_status_t::SGX_ERROR_UNEXPECTED; + let extrinsics_encoded = extrinsics.encode(); + let parentchain_id_encoded = parentchain_id.encode(); + + let res = unsafe { + ffi::ocall_send_to_parentchain( + &mut rt as *mut sgx_status_t, + extrinsics_encoded.as_ptr(), + extrinsics_encoded.len() as u32, + parentchain_id_encoded.as_ptr(), + parentchain_id_encoded.len() as u32, + await_each_inclusion.into(), + ) + }; + + ensure!(rt == sgx_status_t::SGX_SUCCESS, rt); + ensure!(res == sgx_status_t::SGX_SUCCESS, res); + + Ok(()) + } + + fn worker_request( + &self, + req: Vec, + parentchain_id: &ParentchainId, + ) -> SgxResult>> { + let mut rt: sgx_status_t = sgx_status_t::SGX_ERROR_UNEXPECTED; + // Litentry: since #1221 we need 28139 bytes + let mut resp: Vec = vec![0; 4196 * 16]; + let request_encoded = req.encode(); + let parentchain_id_encoded = parentchain_id.encode(); + + let res = unsafe { + ffi::ocall_worker_request( + &mut rt as *mut sgx_status_t, + request_encoded.as_ptr(), + request_encoded.len() as u32, + parentchain_id_encoded.as_ptr(), + parentchain_id_encoded.len() as u32, + resp.as_mut_ptr(), + resp.len() as u32, + ) + }; + + ensure!(rt == sgx_status_t::SGX_SUCCESS, rt); + ensure!(res == sgx_status_t::SGX_SUCCESS, res); + + let decoded_response: Vec> = Decode::decode(&mut resp.as_slice()) + .map_err(|e| { + error!("Failed to decode WorkerResponse: {}", e); + sgx_status_t::SGX_ERROR_UNEXPECTED + })?; + + Ok(decoded_response) + } + + fn get_storage_verified, V: Decode>( + &self, + storage_hash: Vec, + header: &H, + parentchain_id: &ParentchainId, + ) -> Result> { + // the code below seems like an overkill, but it is surprisingly difficult to + // get an owned value from a `Vec` without cloning. + Ok(self + .get_multiple_storages_verified(vec![storage_hash], header, parentchain_id)? + .into_iter() + .next() + .ok_or(StorageError::StorageValueUnavailable)?) + } + + fn get_multiple_storages_verified, V: Decode>( + &self, + storage_hashes: Vec>, + header: &H, + parentchain_id: &ParentchainId, + ) -> Result>> { + let requests = storage_hashes + .into_iter() + .map(|key| WorkerRequest::ChainStorage(key, Some(header.hash()))) + .collect(); + + let storage_entries = self + .worker_request::>(requests, parentchain_id) + .map(|storages| verify_storage_entries(storages, header))??; + + Ok(storage_entries) + } + + fn get_storage_keys(&self, key_prefix: Vec) -> Result>> { + // always using the latest state - we need to support optional header + let requests = vec![WorkerRequest::ChainStorageKeys(key_prefix, None)]; + + let responses: Vec>> = self + .worker_request::>(requests, &ParentchainId::Litentry)? + .iter() + .filter_map(|r| match r { + WorkerResponse::ChainStorageKeys(k) => Some(k.clone()), + _ => None, + }) + .collect(); + + // we should only have one response as we only sent one request + let first_response = responses.get(0).ok_or(StorageError::WrongValue)?; + Ok(first_response.clone()) + } +} diff --git a/bitacross-worker/enclave-runtime/src/ocall/sidechain_ocall.rs b/bitacross-worker/enclave-runtime/src/ocall/sidechain_ocall.rs new file mode 100644 index 0000000000..b961e93752 --- /dev/null +++ b/bitacross-worker/enclave-runtime/src/ocall/sidechain_ocall.rs @@ -0,0 +1,139 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::ocall::{ffi, OcallApi}; +use codec::{Decode, Encode}; +use frame_support::ensure; +use itp_ocall_api::EnclaveSidechainOCallApi; +use itp_types::{BlockHash, ShardIdentifier}; +use log::*; +use sgx_types::{sgx_status_t, SgxResult}; +use std::{string::String, vec::Vec}; + +impl EnclaveSidechainOCallApi for OcallApi { + fn propose_sidechain_blocks( + &self, + signed_blocks: Vec, + ) -> SgxResult<()> { + let mut rt: sgx_status_t = sgx_status_t::SGX_ERROR_UNEXPECTED; + let signed_blocks_encoded = signed_blocks.encode(); + + let res = unsafe { + ffi::ocall_propose_sidechain_blocks( + &mut rt as *mut sgx_status_t, + signed_blocks_encoded.as_ptr(), + signed_blocks_encoded.len() as u32, + ) + }; + + ensure!(rt == sgx_status_t::SGX_SUCCESS, rt); + ensure!(res == sgx_status_t::SGX_SUCCESS, res); + + Ok(()) + } + + fn store_sidechain_blocks( + &self, + signed_blocks: Vec, + ) -> SgxResult<()> { + let mut rt: sgx_status_t = sgx_status_t::SGX_ERROR_UNEXPECTED; + let signed_blocks_encoded = signed_blocks.encode(); + + let res = unsafe { + ffi::ocall_store_sidechain_blocks( + &mut rt as *mut sgx_status_t, + signed_blocks_encoded.as_ptr(), + signed_blocks_encoded.len() as u32, + ) + }; + + ensure!(rt == sgx_status_t::SGX_SUCCESS, rt); + ensure!(res == sgx_status_t::SGX_SUCCESS, res); + + Ok(()) + } + + fn fetch_sidechain_blocks_from_peer( + &self, + last_imported_block_hash: BlockHash, + maybe_until_block_hash: Option, + shard_identifier: ShardIdentifier, + ) -> SgxResult> { + const BLOCK_BUFFER_SIZE: usize = 262144; // Buffer size for sidechain blocks in bytes (256KB). + + let mut rt: sgx_status_t = sgx_status_t::SGX_ERROR_UNEXPECTED; + let last_imported_block_hash_encoded = last_imported_block_hash.encode(); + let maybe_until_block_hash_encoded = maybe_until_block_hash.encode(); + let shard_identifier_encoded = shard_identifier.encode(); + + // We have to pre-allocate the vector and hope it's large enough (see GitHub issue #621). + let mut signed_blocks_encoded: Vec = vec![0; BLOCK_BUFFER_SIZE]; + + let res = unsafe { + ffi::ocall_fetch_sidechain_blocks_from_peer( + &mut rt as *mut sgx_status_t, + last_imported_block_hash_encoded.as_ptr(), + last_imported_block_hash_encoded.len() as u32, + maybe_until_block_hash_encoded.as_ptr(), + maybe_until_block_hash_encoded.len() as u32, + shard_identifier_encoded.as_ptr(), + shard_identifier_encoded.len() as u32, + signed_blocks_encoded.as_mut_ptr(), + signed_blocks_encoded.len() as u32, + ) + }; + + ensure!(rt == sgx_status_t::SGX_SUCCESS, rt); + ensure!(res == sgx_status_t::SGX_SUCCESS, res); + + let decoded_signed_blocks: Vec = + Decode::decode(&mut signed_blocks_encoded.as_slice()).map_err(|e| { + error!("Failed to decode WorkerResponse: {}", e); + sgx_status_t::SGX_ERROR_UNEXPECTED + })?; + + Ok(decoded_signed_blocks) + } + + fn get_trusted_peers_urls(&self) -> SgxResult> { + let mut rt: sgx_status_t = sgx_status_t::SGX_ERROR_UNEXPECTED; + const BLOCK_BUFFER_SIZE: usize = 262144; // Buffer size for sidechain blocks in bytes (256KB). + + // We have to pre-allocate the vector and hope it's large enough (see GitHub issue #621). + let mut peers_encoded: Vec = vec![0; BLOCK_BUFFER_SIZE]; + + let res = unsafe { + ffi::ocall_get_trusted_peers_urls( + &mut rt as *mut sgx_status_t, + peers_encoded.as_mut_ptr(), + peers_encoded.len() as u32, + ) + }; + + ensure!(rt == sgx_status_t::SGX_SUCCESS, rt); + ensure!(res == sgx_status_t::SGX_SUCCESS, res); + + let decoded_peers: Vec = + Decode::decode(&mut peers_encoded.as_slice()).map_err(|e| { + error!("Failed to decode peers list: {}", e); + sgx_status_t::SGX_ERROR_UNEXPECTED + })?; + + Ok(decoded_peers) + } +} diff --git a/bitacross-worker/enclave-runtime/src/rpc/mod.rs b/bitacross-worker/enclave-runtime/src/rpc/mod.rs new file mode 100644 index 0000000000..5b359ab270 --- /dev/null +++ b/bitacross-worker/enclave-runtime/src/rpc/mod.rs @@ -0,0 +1,19 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 rpc_response_channel; +pub mod worker_api_direct; diff --git a/bitacross-worker/enclave-runtime/src/rpc/rpc_response_channel.rs b/bitacross-worker/enclave-runtime/src/rpc/rpc_response_channel.rs new file mode 100644 index 0000000000..7a84fde928 --- /dev/null +++ b/bitacross-worker/enclave-runtime/src/rpc/rpc_response_channel.rs @@ -0,0 +1,40 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::initialization::global_components::GLOBAL_WEB_SOCKET_SERVER_COMPONENT; +use itc_direct_rpc_server::{response_channel::ResponseChannel, DirectRpcError}; +use itc_tls_websocket_server::{ConnectionToken, WebSocketResponder}; +use itp_component_container::ComponentGetter; +use std::string::String; + +/// RPC response channel. +/// +/// Uses the web-socket server to send an RPC response/update. +/// In case no server is available or running, the response will be discarded. +#[derive(Default)] +pub struct RpcResponseChannel; + +impl ResponseChannel for RpcResponseChannel { + type Error = DirectRpcError; + + fn respond(&self, token: ConnectionToken, message: String) -> Result<(), Self::Error> { + let web_socket_server = GLOBAL_WEB_SOCKET_SERVER_COMPONENT + .get() + .map_err(|e| DirectRpcError::Other(e.into()))?; + web_socket_server.send_message(token, message).map_err(|e| e.into()) + } +} diff --git a/bitacross-worker/enclave-runtime/src/rpc/worker_api_direct.rs b/bitacross-worker/enclave-runtime/src/rpc/worker_api_direct.rs new file mode 100644 index 0000000000..4133bccca6 --- /dev/null +++ b/bitacross-worker/enclave-runtime/src/rpc/worker_api_direct.rs @@ -0,0 +1,565 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{ + attestation::{ + generate_dcap_ra_extrinsic_from_quote_internal, + generate_ias_ra_extrinsic_from_der_cert_internal, + }, + utils::{ + get_stf_enclave_signer_from_solo_or_parachain, + get_validator_accessor_from_integritee_solo_or_parachain, + }, +}; +use codec::Encode; +use core::result::Result; +use ita_sgx_runtime::{Runtime, System}; +use ita_stf::{Getter, TrustedCallSigned}; +use itc_parentchain::light_client::{concurrent_access::ValidatorAccess, ExtrinsicSender}; +use itp_primitives_cache::{GetPrimitives, GLOBAL_PRIMITIVES_CACHE}; +use itp_rpc::RpcReturnValue; +use itp_sgx_crypto::{ + ed25519_derivation::DeriveEd25519, + key_repository::{AccessKey, AccessPubkey}, + ShieldingCryptoDecrypt, ShieldingCryptoEncrypt, +}; +use itp_sgx_externalities::SgxExternalitiesTrait; +use itp_stf_executor::{getter_executor::ExecuteGetter, traits::StfShardVaultQuery}; +use itp_stf_primitives::types::AccountId; +use itp_stf_state_handler::handle_state::HandleState; +use itp_top_pool_author::traits::AuthorApi; +use itp_types::{ + DirectRequestStatus, Index, MrEnclave, RsaRequest, ShardIdentifier, SidechainBlockNumber, H256, +}; +use itp_utils::{if_not_production, FromHexPrefixed, ToHexPrefixed}; +use its_primitives::types::block::SignedBlock; +use its_sidechain::rpc_handler::{ + direct_top_pool_api, direct_top_pool_api::decode_shard_from_base58, import_block_api, +}; +use jsonrpc_core::{serde_json::json, IoHandler, Params, Value}; +use lc_scheduled_enclave::{ScheduledEnclaveUpdater, GLOBAL_SCHEDULED_ENCLAVE}; +use litentry_primitives::DecryptableRequest; +use log::debug; +use sgx_crypto_helper::rsa3072::Rsa3072PubKey; +use sp_core::Pair; +use sp_runtime::OpaqueExtrinsic; +use std::{borrow::ToOwned, format, str, string::String, sync::Arc, vec::Vec}; + +fn compute_hex_encoded_return_error(error_msg: &str) -> String { + RpcReturnValue::from_error_message(error_msg).to_hex() +} + +fn get_all_rpc_methods_string(io_handler: &IoHandler) -> String { + let method_string = io_handler + .iter() + .map(|rp_tuple| rp_tuple.0.to_owned()) + .collect::>() + .join(", "); + + format!("methods: [{}]", method_string) +} + +pub fn public_api_rpc_handler( + top_pool_author: Arc, + getter_executor: Arc, + shielding_key: Arc, + state: Option>, +) -> IoHandler +where + Author: AuthorApi + Send + Sync + 'static, + GetterExecutor: ExecuteGetter + Send + Sync + 'static, + AccessShieldingKey: AccessPubkey + AccessKey + Send + Sync + 'static, + ::KeyType: + ShieldingCryptoDecrypt + ShieldingCryptoEncrypt + DeriveEd25519 + Send + Sync + 'static, + State: HandleState + Send + Sync + 'static, + State::StateT: SgxExternalitiesTrait, +{ + let mut io = direct_top_pool_api::add_top_pool_direct_rpc_methods( + top_pool_author.clone(), + IoHandler::new(), + ); + + let shielding_key_cloned = shielding_key.clone(); + io.add_sync_method("author_getShieldingKey", move |_: Params| { + debug!("worker_api_direct rpc was called: author_getShieldingKey"); + let rsa_pubkey = match shielding_key_cloned.retrieve_pubkey() { + Ok(key) => key, + Err(status) => { + let error_msg: String = format!("Could not get rsa pubkey due to: {}", status); + return Ok(json!(compute_hex_encoded_return_error(error_msg.as_str()))) + }, + }; + + let rsa_pubkey_json = match serde_json::to_string(&rsa_pubkey) { + Ok(k) => k, + Err(x) => { + let error_msg: String = + format!("[Enclave] can't serialize rsa_pubkey {:?} {}", rsa_pubkey, x); + return Ok(json!(compute_hex_encoded_return_error(error_msg.as_str()))) + }, + }; + let json_value = + RpcReturnValue::new(rsa_pubkey_json.encode(), false, DirectRequestStatus::Ok); + Ok(json!(json_value.to_hex())) + }); + + // author_getEnclaveSignerAccount + let rsa_pubkey_name: &str = "author_getEnclaveSignerAccount"; + io.add_sync_method(rsa_pubkey_name, move |_: Params| { + let enclave_signer_public_key = match shielding_key + .retrieve_key() + .and_then(|keypair| keypair.derive_ed25519().map(|keypair| keypair.public().to_hex())) + { + Err(e) => { + let error_msg: String = format!("{:?}", e); + return Ok(json!(compute_hex_encoded_return_error(error_msg.as_str()))) + }, + Ok(public_key) => public_key, + }; + debug!("[Enclave] enclave_signer_public_key: {:?}", enclave_signer_public_key); + + let json_value = RpcReturnValue { + do_watch: false, + value: enclave_signer_public_key.encode(), + status: DirectRequestStatus::Ok, + }; + + Ok(json!(json_value.to_hex())) + }); + + let local_top_pool_author = top_pool_author.clone(); + let local_state = state.clone(); + io.add_sync_method("author_getNextNonce", move |params: Params| { + let local_state = match local_state.clone() { + Some(s) => s, + None => + return Ok(json!(compute_hex_encoded_return_error( + "author_getNextNonce is not avaiable" + ))), + }; + + match params.parse::<(String, String)>() { + Ok((shard_base58, account_hex)) => { + let shard = match decode_shard_from_base58(shard_base58.as_str()) { + Ok(id) => id, + Err(msg) => { + let error_msg: String = + format!("Could not retrieve author_getNextNonce calls due to: {}", msg); + return Ok(json!(compute_hex_encoded_return_error(error_msg.as_str()))) + }, + }; + let account = match AccountId::from_hex(account_hex.as_str()) { + Ok(acc) => acc, + Err(msg) => { + let error_msg: String = format!( + "Could not retrieve author_getNextNonce calls due to: {:?}", + msg + ); + return Ok(json!(compute_hex_encoded_return_error(error_msg.as_str()))) + }, + }; + + match local_state.load_cloned(&shard) { + Ok((mut state, _hash)) => { + let trusted_calls = + local_top_pool_author.get_pending_trusted_calls_for(shard, &account); + let pending_tx_count = trusted_calls.len(); + #[allow(clippy::unwrap_used)] + let pending_tx_count = Index::try_from(pending_tx_count).unwrap(); + let nonce = state.execute_with(|| System::account_nonce(&account)); + let json_value = RpcReturnValue { + do_watch: false, + value: (nonce.saturating_add(pending_tx_count)).encode(), + status: DirectRequestStatus::Ok, + }; + Ok(json!(json_value.to_hex())) + }, + Err(e) => { + let error_msg = format!("load shard failure due to: {:?}", e); + Ok(json!(compute_hex_encoded_return_error(error_msg.as_str()))) + }, + } + }, + Err(e) => { + let error_msg: String = + format!("Could not retrieve author_getNextNonce calls due to: {}", e); + Ok(json!(compute_hex_encoded_return_error(error_msg.as_str()))) + }, + } + }); + + let local_top_pool_author = top_pool_author.clone(); + io.add_sync_method("author_getShardVault", move |_: Params| { + debug!("worker_api_direct rpc was called: author_getShardVault"); + let shard = + local_top_pool_author.list_handled_shards().first().copied().unwrap_or_default(); + if let Ok(stf_enclave_signer) = get_stf_enclave_signer_from_solo_or_parachain() { + if let Ok(vault) = stf_enclave_signer.get_shard_vault(&shard) { + let json_value = + RpcReturnValue::new(vault.encode(), false, DirectRequestStatus::Ok); + Ok(json!(json_value.to_hex())) + } else { + Ok(json!(compute_hex_encoded_return_error("failed to get shard vault").to_hex())) + } + } else { + Ok(json!(compute_hex_encoded_return_error( + "failed to get stf_enclave_signer to get shard vault" + ) + .to_hex())) + } + }); + + io.add_sync_method("author_getShard", move |_: Params| { + debug!("worker_api_direct rpc was called: author_getShard"); + let shard = top_pool_author.list_handled_shards().first().copied().unwrap_or_default(); + let json_value = RpcReturnValue::new(shard.encode(), false, DirectRequestStatus::Ok); + Ok(json!(json_value.to_hex())) + }); + + io.add_sync_method("author_getMuRaUrl", move |_: Params| { + debug!("worker_api_direct rpc was called: author_getMuRaUrl"); + let url = match GLOBAL_PRIMITIVES_CACHE.get_mu_ra_url() { + Ok(url) => url, + Err(status) => { + let error_msg: String = format!("Could not get mu ra url due to: {}", status); + return Ok(json!(compute_hex_encoded_return_error(error_msg.as_str()))) + }, + }; + + let json_value = RpcReturnValue::new(url.encode(), false, DirectRequestStatus::Ok); + Ok(json!(json_value.to_hex())) + }); + + io.add_sync_method("author_getUntrustedUrl", move |_: Params| { + debug!("worker_api_direct rpc was called: author_getUntrustedUrl"); + let url = match GLOBAL_PRIMITIVES_CACHE.get_untrusted_worker_url() { + Ok(url) => url, + Err(status) => { + let error_msg: String = format!("Could not get untrusted url due to: {}", status); + return Ok(json!(compute_hex_encoded_return_error(error_msg.as_str()))) + }, + }; + + let json_value = RpcReturnValue::new(url.encode(), false, DirectRequestStatus::Ok); + Ok(json!(json_value.to_hex())) + }); + + io.add_sync_method("chain_subscribeAllHeads", |_: Params| { + debug!("worker_api_direct rpc was called: chain_subscribeAllHeads"); + let parsed = "world"; + Ok(Value::String(format!("hello, {}", parsed))) + }); + + io.add_sync_method("state_getMetadata", |_: Params| { + debug!("worker_api_direct rpc was called: tate_getMetadata"); + let metadata = Runtime::metadata(); + let json_value = RpcReturnValue::new(metadata.into(), false, DirectRequestStatus::Ok); + Ok(json!(json_value.to_hex())) + }); + + io.add_sync_method("state_getRuntimeVersion", |_: Params| { + debug!("worker_api_direct rpc was called: state_getRuntimeVersion"); + let parsed = "world"; + Ok(Value::String(format!("hello, {}", parsed))) + }); + + io.add_sync_method("state_executeGetter", move |params: Params| { + debug!("worker_api_direct rpc was called: state_executeGetter"); + let json_value = match execute_getter_inner(getter_executor.as_ref(), params) { + Ok(state_getter_value) => RpcReturnValue { + do_watch: false, + value: state_getter_value.encode(), + status: DirectRequestStatus::Ok, + } + .to_hex(), + Err(error) => compute_hex_encoded_return_error(error.as_str()), + }; + Ok(json!(json_value)) + }); + + io.add_sync_method("attesteer_forwardDcapQuote", move |params: Params| { + debug!("worker_api_direct rpc was called: attesteer_forwardDcapQuote"); + let json_value = match forward_dcap_quote_inner(params) { + Ok(val) => RpcReturnValue { + do_watch: false, + value: val.encode(), + status: DirectRequestStatus::Ok, + } + .to_hex(), + Err(error) => compute_hex_encoded_return_error(error.as_str()), + }; + + Ok(json!(json_value)) + }); + + io.add_sync_method("attesteer_forwardIasAttestationReport", move |params: Params| { + debug!("worker_api_direct rpc was called: attesteer_forwardIasAttestationReport"); + let json_value = match attesteer_forward_ias_attestation_report_inner(params) { + Ok(val) => RpcReturnValue { + do_watch: false, + value: val.encode(), + status: DirectRequestStatus::Ok, + } + .to_hex(), + Err(error) => compute_hex_encoded_return_error(error.as_str()), + }; + Ok(json!(json_value)) + }); + + // state_getMrenclave + io.add_sync_method("state_getMrenclave", |_: Params| { + let json_value = match GLOBAL_SCHEDULED_ENCLAVE.get_current_mrenclave() { + Ok(mrenclave) => RpcReturnValue { + do_watch: false, + value: mrenclave.encode(), + status: DirectRequestStatus::Ok, + } + .to_hex(), + Err(error) => { + let error_msg: String = + format!("Could not get current mrenclave due to: {}", error); + compute_hex_encoded_return_error(error_msg.as_str()) + }, + }; + Ok(json!(json_value)) + }); + + if_not_production!({ + // state_updateScheduledEnclave, params: sidechainBlockNumber, hex encoded mrenclave + io.add_sync_method("state_updateScheduledEnclave", move |params: Params| { + match params.parse::<(SidechainBlockNumber, String)>() { + Ok((bn, mrenclave)) => + return match hex::decode(&mrenclave) { + Ok(mrenclave) => { + let mut enclave_to_set: MrEnclave = [0u8; 32]; + if mrenclave.len() != enclave_to_set.len() { + return Ok(json!(compute_hex_encoded_return_error( + "mrenclave len mismatch, expected 32 bytes long" + ))) + } + + enclave_to_set.copy_from_slice(&mrenclave); + return match GLOBAL_SCHEDULED_ENCLAVE.update(bn, enclave_to_set) { + Ok(()) => Ok(json!(RpcReturnValue::new( + vec![], + false, + DirectRequestStatus::Ok + ) + .to_hex())), + Err(e) => { + let error_msg = + format!("Failed to set scheduled mrenclave {:?}", e); + Ok(json!(compute_hex_encoded_return_error(error_msg.as_str()))) + }, + } + }, + Err(e) => { + let error_msg = format!("Failed to decode mrenclave {:?}", e); + Ok(json!(compute_hex_encoded_return_error(error_msg.as_str()))) + }, + }, + Err(_) => Ok(json!(compute_hex_encoded_return_error("parse error"))), + } + }); + + // state_getStorage + io.add_sync_method("state_getStorage", move |params: Params| { + let local_state = match state.clone() { + Some(s) => s, + None => + return Ok(json!(compute_hex_encoded_return_error( + "state_getStorage is not avaiable" + ))), + }; + match params.parse::<(String, String)>() { + Ok((shard_str, key_hash)) => { + let key_hash = if key_hash.starts_with("0x") { + #[allow(clippy::unwrap_used)] + key_hash.strip_prefix("0x").unwrap() + } else { + key_hash.as_str() + }; + let key_hash = match hex::decode(key_hash) { + Ok(key_hash) => key_hash, + Err(_) => + return Ok(json!(compute_hex_encoded_return_error("docode key error"))), + }; + + let shard: ShardIdentifier = match decode_shard_from_base58(shard_str.as_str()) + { + Ok(id) => id, + Err(msg) => { + let error_msg = format!("decode shard failure due to: {}", msg); + return Ok(json!(compute_hex_encoded_return_error(error_msg.as_str()))) + }, + }; + match local_state.load_cloned(&shard) { + Ok((state, _)) => { + // Get storage by key hash + let value = state.get(key_hash.as_slice()).cloned().unwrap_or_default(); + debug!("query storage value:{:?}", &value); + let json_value = + RpcReturnValue::new(value, false, DirectRequestStatus::Ok); + Ok(json!(json_value.to_hex())) + }, + Err(e) => { + let error_msg = format!("load shard failure due to: {:?}", e); + return Ok(json!(compute_hex_encoded_return_error(error_msg.as_str()))) + }, + } + }, + Err(_err) => Ok(json!(compute_hex_encoded_return_error("parse error"))), + } + }); + }); + + // system_health + io.add_sync_method("system_health", |_: Params| { + debug!("worker_api_direct rpc was called: system_health"); + let parsed = "world"; + Ok(Value::String(format!("hello, {}", parsed))) + }); + + io.add_sync_method("system_name", |_: Params| { + debug!("worker_api_direct rpc was called: system_name"); + let parsed = "world"; + Ok(Value::String(format!("hello, {}", parsed))) + }); + + io.add_sync_method("system_version", |_: Params| { + debug!("worker_api_direct rpc was called: system_version"); + let parsed = "world"; + Ok(Value::String(format!("hello, {}", parsed))) + }); + + let rpc_methods_string = get_all_rpc_methods_string(&io); + io.add_sync_method("rpc_methods", move |_: Params| { + debug!("worker_api_direct rpc was called: rpc_methods"); + Ok(Value::String(rpc_methods_string.to_owned())) + }); + + io +} + +// Litentry: TODO - we still use `RsaRequest` for trusted getter, as the result +// in unencrypted, see P-183 +fn execute_getter_inner( + getter_executor: &GE, + params: Params, +) -> Result>, String> { + let hex_encoded_params = params.parse::>().map_err(|e| format!("{:?}", e))?; + + let param = &hex_encoded_params.get(0).ok_or("Could not get first param")?; + let request = RsaRequest::from_hex(param).map_err(|e| format!("{:?}", e))?; + + let shard: ShardIdentifier = request.shard(); + let encoded_trusted_getter: Vec = request.payload().to_vec(); + + let getter_result = getter_executor + .execute_getter(&shard, encoded_trusted_getter) + .map_err(|e| format!("{:?}", e))?; + + Ok(getter_result) +} + +fn forward_dcap_quote_inner(params: Params) -> Result { + let hex_encoded_params = params.parse::>().map_err(|e| format!("{:?}", e))?; + + if hex_encoded_params.len() != 1 { + return Err(format!( + "Wrong number of arguments for IAS attestation report forwarding: {}, expected: {}", + hex_encoded_params.len(), + 1 + )) + } + + let param = &hex_encoded_params.get(0).ok_or("Could not get first param")?; + let encoded_quote_to_forward: Vec = + itp_utils::hex::decode_hex(param).map_err(|e| format!("{:?}", e))?; + + let url = String::new(); + let ext = generate_dcap_ra_extrinsic_from_quote_internal(url, &encoded_quote_to_forward) + .map_err(|e| format!("{:?}", e))?; + + let validator_access = get_validator_accessor_from_integritee_solo_or_parachain() + .map_err(|e| format!("{:?}", e))?; + validator_access + .execute_mut_on_validator(|v| v.send_extrinsics(vec![ext.clone()])) + .map_err(|e| format!("{:?}", e))?; + + Ok(ext) +} + +fn attesteer_forward_ias_attestation_report_inner( + params: Params, +) -> Result { + let hex_encoded_params = params.parse::>().map_err(|e| format!("{:?}", e))?; + + if hex_encoded_params.len() != 1 { + return Err(format!( + "Wrong number of arguments for IAS attestation report forwarding: {}, expected: {}", + hex_encoded_params.len(), + 1 + )) + } + + let param = &hex_encoded_params.get(0).ok_or("Could not get first param")?; + let ias_attestation_report = + itp_utils::hex::decode_hex(param).map_err(|e| format!("{:?}", e))?; + + let url = String::new(); + let ext = generate_ias_ra_extrinsic_from_der_cert_internal(url, &ias_attestation_report) + .map_err(|e| format!("{:?}", e))?; + + let validator_access = get_validator_accessor_from_integritee_solo_or_parachain() + .map_err(|e| format!("{:?}", e))?; + validator_access + .execute_mut_on_validator(|v| v.send_extrinsics(vec![ext.clone()])) + .map_err(|e| format!("{:?}", e))?; + + Ok(ext) +} + +pub fn sidechain_io_handler(import_fn: ImportFn) -> IoHandler +where + ImportFn: Fn(SignedBlock) -> Result<(), Error> + Sync + Send + 'static, + Error: std::fmt::Debug, +{ + let io = IoHandler::new(); + import_block_api::add_import_block_rpc_method(import_fn, io) +} + +#[cfg(feature = "test")] +pub mod tests { + use super::*; + use std::string::ToString; + + pub fn test_given_io_handler_methods_then_retrieve_all_names_as_string() { + let mut io = IoHandler::new(); + let method_names: [&str; 4] = ["method1", "another_method", "fancy_thing", "solve_all"]; + + for method_name in method_names.iter() { + io.add_sync_method(method_name, |_: Params| Ok(Value::String("".to_string()))); + } + + let method_string = get_all_rpc_methods_string(&io); + + for method_name in method_names.iter() { + assert!(method_string.contains(method_name)); + } + } +} diff --git a/bitacross-worker/enclave-runtime/src/shard_vault.rs b/bitacross-worker/enclave-runtime/src/shard_vault.rs new file mode 100644 index 0000000000..50bb362ad1 --- /dev/null +++ b/bitacross-worker/enclave-runtime/src/shard_vault.rs @@ -0,0 +1,250 @@ +/* + Copyright 2021 Integritee AG + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{ + error::{Error, Result as EnclaveResult}, + initialization::global_components::{ + GLOBAL_OCALL_API_COMPONENT, GLOBAL_SIGNING_KEY_REPOSITORY_COMPONENT, + GLOBAL_STATE_HANDLER_COMPONENT, + }, + utils::{ + get_extrinsic_factory_from_integritee_solo_or_parachain, + get_extrinsic_factory_from_target_a_solo_or_parachain, + get_extrinsic_factory_from_target_b_solo_or_parachain, + get_node_metadata_repository_from_integritee_solo_or_parachain, + get_node_metadata_repository_from_target_a_solo_or_parachain, + get_node_metadata_repository_from_target_b_solo_or_parachain, DecodeRaw, + }, +}; +use codec::{Compact, Decode, Encode}; +use itp_component_container::ComponentGetter; +use itp_extrinsics_factory::CreateExtrinsics; +use itp_node_api::{ + api_client::{PairSignature, StaticExtrinsicSigner}, + metadata::{ + pallet_proxy::PROXY_DEPOSIT, + provider::{AccessNodeMetadata, Error as MetadataProviderError}, + }, +}; +use itp_node_api_metadata::pallet_proxy::ProxyCallIndexes; +use itp_nonce_cache::NonceCache; +use itp_ocall_api::EnclaveOnChainOCallApi; +use itp_sgx_crypto::key_repository::AccessKey; +use itp_stf_interface::SHARD_VAULT_KEY; +use itp_stf_state_handler::{handle_state::HandleState, query_shard_state::QueryShardState}; +use itp_types::{ + parentchain::{AccountId, Address, ParentchainId, ProxyType}, + OpaqueCall, ShardIdentifier, +}; +use log::*; +use sgx_types::sgx_status_t; +use sp_core::crypto::{DeriveJunction, Pair}; +use std::{slice, sync::Arc, vec::Vec}; + +#[no_mangle] +pub unsafe extern "C" fn init_proxied_shard_vault( + shard: *const u8, + shard_size: u32, + parentchain_id: *const u8, + parentchain_id_size: u32, +) -> sgx_status_t { + let shard_identifier = + ShardIdentifier::from_slice(slice::from_raw_parts(shard, shard_size as usize)); + let parentchain_id = + match ParentchainId::decode_raw(parentchain_id, parentchain_id_size as usize) { + Ok(id) => id, + Err(e) => { + error!("Could not decode parentchain id: {:?}", e); + return sgx_status_t::SGX_ERROR_UNEXPECTED + }, + }; + + if let Err(e) = init_proxied_shard_vault_internal(shard_identifier, parentchain_id) { + error!("Failed to initialize proxied shard vault ({:?}): {:?}", shard_identifier, e); + return sgx_status_t::SGX_ERROR_UNEXPECTED + } + + sgx_status_t::SGX_SUCCESS +} + +/// reads the shard vault account id form state if it has been initialized previously +#[no_mangle] +pub unsafe extern "C" fn get_ecc_vault_pubkey( + shard: *const u8, + shard_size: u32, + pubkey: *mut u8, + pubkey_size: u32, +) -> sgx_status_t { + let shard = ShardIdentifier::from_slice(slice::from_raw_parts(shard, shard_size as usize)); + + let shard_vault = match get_shard_vault_account(shard) { + Ok(account) => account, + Err(e) => { + warn!("Failed to fetch shard vault account: {:?}", e); + return sgx_status_t::SGX_ERROR_UNEXPECTED + }, + }; + let pubkey_slice = slice::from_raw_parts_mut(pubkey, pubkey_size as usize); + pubkey_slice.clone_from_slice(shard_vault.encode().as_slice()); + sgx_status_t::SGX_SUCCESS +} + +/// reads the shard vault account id form state if it has been initialized previously +pub(crate) fn get_shard_vault_account(shard: ShardIdentifier) -> EnclaveResult { + let state_handler = GLOBAL_STATE_HANDLER_COMPONENT.get()?; + + state_handler + .execute_on_current(&shard, |state, _| { + state + .state + .get::>(&SHARD_VAULT_KEY.into()) + .and_then(|v| Decode::decode(&mut v.clone().as_slice()).ok()) + })? + .ok_or_else(|| { + Error::Other("failed to fetch shard vault account. has it been initialized?".into()) + }) +} + +pub(crate) fn init_proxied_shard_vault_internal( + shard: ShardIdentifier, + parentchain_id: ParentchainId, +) -> EnclaveResult<()> { + let state_handler = GLOBAL_STATE_HANDLER_COMPONENT.get()?; + if !state_handler + .shard_exists(&shard) + .map_err(|_| Error::Other("get shard_exists failed".into()))? + { + return Err(Error::Other("shard not initialized".into())) + }; + + let ocall_api = GLOBAL_OCALL_API_COMPONENT.get()?; + let enclave_signer = GLOBAL_SIGNING_KEY_REPOSITORY_COMPONENT.get()?.retrieve_key()?; + let vault = enclave_signer + .derive(vec![DeriveJunction::hard(shard.encode())].into_iter(), None) + .map_err(|_| Error::Other("failed to derive shard vault keypair".into()))? + .0; + info!("shard vault account derived pubkey: 0x{}", hex::encode(vault.public().0)); + + let (enclave_extrinsics_factory, node_metadata_repo) = match parentchain_id { + ParentchainId::Litentry => { + let (state_lock, mut state) = state_handler.load_for_mutation(&shard)?; + state.state.insert(SHARD_VAULT_KEY.into(), vault.public().0.to_vec()); + state_handler.write_after_mutation(state, state_lock, &shard)?; + let enclave_extrinsics_factory = + get_extrinsic_factory_from_integritee_solo_or_parachain()?; + let node_metadata_repo = + get_node_metadata_repository_from_integritee_solo_or_parachain()?; + (enclave_extrinsics_factory, node_metadata_repo) + }, + ParentchainId::TargetA => { + let enclave_extrinsics_factory = + get_extrinsic_factory_from_target_a_solo_or_parachain()?; + let node_metadata_repo = + get_node_metadata_repository_from_target_a_solo_or_parachain()?; + (enclave_extrinsics_factory, node_metadata_repo) + }, + ParentchainId::TargetB => { + let enclave_extrinsics_factory = + get_extrinsic_factory_from_target_b_solo_or_parachain()?; + let node_metadata_repo = + get_node_metadata_repository_from_target_b_solo_or_parachain()?; + (enclave_extrinsics_factory, node_metadata_repo) + }, + }; + + info!("[{:?}] send existential funds from enclave account to vault account", parentchain_id); + let call_ids = node_metadata_repo + .get_from_metadata(|m| m.call_indexes("Balances", "transfer_keep_alive"))? + .map_err(MetadataProviderError::MetadataError)?; + + let call = OpaqueCall::from_tuple(&( + call_ids, + Address::from(AccountId::from(vault.public().0)), + Compact(PROXY_DEPOSIT), + )); + + info!("[{:?}] vault funding call: 0x{}", parentchain_id, hex::encode(call.0.clone())); + let xts = enclave_extrinsics_factory.create_extrinsics(&[call], None)?; + + //this extrinsic must be included in a block before we can move on. otherwise the next will fail + ocall_api.send_to_parentchain(xts, &parentchain_id, true)?; + + // we are assuming nonce=0 here. + let nonce_cache = Arc::new(NonceCache::default()); + let vault_extrinsics_factory = enclave_extrinsics_factory + .with_signer(StaticExtrinsicSigner::<_, PairSignature>::new(vault), nonce_cache); + + info!("[{:?}] register enclave signer as proxy for shard vault", parentchain_id); + let call_ids = node_metadata_repo + .get_from_metadata(|m| m.call_indexes("Proxy", "add_proxy"))? + .map_err(MetadataProviderError::MetadataError)?; + + let call = OpaqueCall::from_tuple(&( + call_ids, + Address::from(AccountId::from(enclave_signer.public().0)), + ProxyType::Any, + 0u32, // delay + )); + + info!("[{:?}] add proxy call: 0x{}", parentchain_id, hex::encode(call.0.clone())); + let xts = vault_extrinsics_factory.create_extrinsics(&[call], None)?; + + ocall_api.send_to_parentchain(xts, &parentchain_id, false)?; + Ok(()) +} + +pub(crate) fn add_shard_vault_proxy( + shard: ShardIdentifier, + proxy: &AccountId, +) -> EnclaveResult<()> { + let state_handler = GLOBAL_STATE_HANDLER_COMPONENT.get()?; + if !state_handler + .shard_exists(&shard) + .map_err(|_| Error::Other("get shard_exists failed".into()))? + { + return Err(Error::Other("shard not initialized".into())) + }; + + let ocall_api = GLOBAL_OCALL_API_COMPONENT.get()?; + let enclave_extrinsics_factory = get_extrinsic_factory_from_integritee_solo_or_parachain()?; + let node_metadata_repo = get_node_metadata_repository_from_integritee_solo_or_parachain()?; + let vault = get_shard_vault_account(shard)?; + + debug!( + "adding proxy 0x{} to shard vault account 0x{}", + hex::encode(proxy.clone()), + hex::encode(vault.clone()) + ); + + let add_proxy_call = OpaqueCall::from_tuple(&( + node_metadata_repo.get_from_metadata(|m| m.add_proxy_call_indexes())??, + Address::from(proxy.clone()), + ProxyType::Any, + 0u32, // delay + )); + let call = OpaqueCall::from_tuple(&( + node_metadata_repo.get_from_metadata(|m| m.proxy_call_indexes())??, + Address::from(vault), + None::, + add_proxy_call, + )); + + info!("proxied add proxy call: 0x{}", hex::encode(call.0.clone())); + let xts = enclave_extrinsics_factory.create_extrinsics(&[call], None)?; + + ocall_api.send_to_parentchain(xts, &ParentchainId::Litentry, false)?; + Ok(()) +} diff --git a/bitacross-worker/enclave-runtime/src/stf_task_handler.rs b/bitacross-worker/enclave-runtime/src/stf_task_handler.rs new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/bitacross-worker/enclave-runtime/src/stf_task_handler.rs @@ -0,0 +1 @@ + diff --git a/bitacross-worker/enclave-runtime/src/sync.rs b/bitacross-worker/enclave-runtime/src/sync.rs new file mode 100644 index 0000000000..a348134d6f --- /dev/null +++ b/bitacross-worker/enclave-runtime/src/sync.rs @@ -0,0 +1,104 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 to handle multithreaded state access in the enclave. +//! +//! Note: In general the design should try to minimize usage of these, as potential deadlocks can +//! occur. Documentation of the `SgxRwLock` says that panics __might__ occur when trying to acquire +//! a lock multiple times in the same thread. However, tests have shown that it also might result in +//! a deadlock. +//! +//! @clangenb: Does currently not see any way to entirely get rid of these synchronization +//! primitives because we can only start new threads from the untrusted side. `parking_lot` would be +//! an alternative to consider for the primitives. It has several performance and ergonomic benefits +//! over the `std` lib's. One of the benefits would be compile-time deadlock detection (experimental). +//! Unfortunately, it would need to be ported to SGX. +//! +//! `https://amanieu.github.io/parking_lot/parking_lot/index.html` + +use crate::error::{Error, Result as EnclaveResult}; +use lazy_static::lazy_static; +use std::sync::{SgxRwLock, SgxRwLockReadGuard, SgxRwLockWriteGuard}; + +lazy_static! { + pub static ref SIDECHAIN_DB_LOCK: SgxRwLock<()> = Default::default(); +} + +pub struct EnclaveLock; + +impl SidechainRwLock for EnclaveLock { + fn read_sidechain_db() -> EnclaveResult> { + SIDECHAIN_DB_LOCK.read().map_err(|e| Error::Other(e.into())) + } + + fn write_sidechain_db() -> EnclaveResult> { + SIDECHAIN_DB_LOCK.write().map_err(|e| Error::Other(e.into())) + } +} + +pub trait SidechainRwLock { + fn read_sidechain_db() -> EnclaveResult>; + fn write_sidechain_db() -> EnclaveResult>; +} + +// simple type defs to prevent too long names +type AggregatedReadGuards<'a> = SgxRwLockReadGuard<'a, ()>; +type AggregatedWriteGuards<'a> = SgxRwLockWriteGuard<'a, ()>; + +/// Useful, if all state must be accessed. Reduces the number of lines. +pub trait EnclaveStateRWLock: SidechainRwLock { + /// return read locks of all enclave states + fn read_all() -> EnclaveResult>; + + /// return write locks of all enclave states + fn write_all() -> EnclaveResult>; +} + +impl EnclaveStateRWLock for T { + fn read_all() -> EnclaveResult> { + Self::read_sidechain_db() + } + + fn write_all() -> EnclaveResult> { + Self::write_sidechain_db() + } +} + +#[cfg(feature = "test")] +pub mod tests { + use super::*; + pub fn sidechain_rw_lock_works() { + drop(EnclaveLock::read_sidechain_db().unwrap()); + drop(EnclaveLock::write_sidechain_db().unwrap()); + + let x1 = EnclaveLock::read_sidechain_db().unwrap(); + let x2 = EnclaveLock::read_sidechain_db().unwrap(); + + drop((x1, x2)); + drop(EnclaveLock::write_sidechain_db().unwrap()) + } + + pub fn enclave_rw_lock_works() { + drop(EnclaveLock::read_all().unwrap()); + drop(EnclaveLock::write_all().unwrap()); + + let x1 = EnclaveLock::read_all().unwrap(); + let x2 = EnclaveLock::read_all().unwrap(); + + drop((x1, x2)); + drop(EnclaveLock::write_all().unwrap()) + } +} diff --git a/bitacross-worker/enclave-runtime/src/teeracle/mod.rs b/bitacross-worker/enclave-runtime/src/teeracle/mod.rs new file mode 100644 index 0000000000..c38dd27c2e --- /dev/null +++ b/bitacross-worker/enclave-runtime/src/teeracle/mod.rs @@ -0,0 +1,279 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{ + error::{Error, Result}, + initialization::global_components::GLOBAL_OCALL_API_COMPONENT, + utils::{ + get_extrinsic_factory_from_integritee_solo_or_parachain, + get_node_metadata_repository_from_integritee_solo_or_parachain, + }, +}; +use codec::{Decode, Encode}; +use core::slice; +use ita_oracle::{ + create_coin_gecko_oracle, create_coin_market_cap_oracle, create_open_meteo_weather_oracle, + metrics_exporter::ExportMetrics, + oracles::{ + exchange_rate_oracle::{ExchangeRateOracle, GetExchangeRate}, + weather_oracle::{GetLongitude, WeatherOracle}, + }, + traits::OracleSource, + types::{TradingInfo, TradingPair, WeatherInfo, WeatherQuery}, +}; +use itp_component_container::ComponentGetter; +use itp_extrinsics_factory::CreateExtrinsics; +use itp_node_api::metadata::{pallet_teeracle::TeeracleCallIndexes, provider::AccessNodeMetadata}; +use itp_types::OpaqueCall; +use itp_utils::write_slice_and_whitespace_pad; +use log::*; +use sgx_types::sgx_status_t; +use sp_runtime::OpaqueExtrinsic; +use std::{string::String, vec::Vec}; + +fn update_weather_data_internal(weather_info: WeatherInfo) -> Result> { + let extrinsics_factory = get_extrinsic_factory_from_integritee_solo_or_parachain()?; + let ocall_api = GLOBAL_OCALL_API_COMPONENT.get()?; + + let mut extrinsic_calls: Vec = Vec::new(); + + let open_meteo_weather_oracle = create_open_meteo_weather_oracle(ocall_api); + + match get_longitude(weather_info, open_meteo_weather_oracle) { + Ok(opaque_call) => extrinsic_calls.push(opaque_call), + Err(e) => { + error!("[-] Failed to get the newest longitude from OpenMeteo. {:?}", e); + }, + }; + let extrinsics = extrinsics_factory.create_extrinsics(extrinsic_calls.as_slice(), None)?; + Ok(extrinsics) +} + +fn get_longitude( + weather_info: WeatherInfo, + oracle: WeatherOracle, +) -> Result +where + OracleSourceType: OracleSource< + WeatherInfo, + OracleRequestResult = std::result::Result, + >, + MetricsExporter: ExportMetrics, +{ + let longitude = + oracle.get_longitude(weather_info.clone()).map_err(|e| Error::Other(e.into()))?; + + let base_url = oracle.get_base_url().map_err(|e| Error::Other(e.into()))?; + let source_base_url = base_url.as_str(); + + println!("Update the longitude: {}, for source {}", longitude, source_base_url); + + let node_metadata_repository = + get_node_metadata_repository_from_integritee_solo_or_parachain()?; + + let call_ids = node_metadata_repository + .get_from_metadata(|m| m.update_oracle_call_indexes()) + .map_err(Error::NodeMetadataProvider)? + .map_err(|e| Error::Other(format!("{:?}", e).into()))?; + + let call = OpaqueCall::from_tuple(&( + call_ids, + weather_info.weather_query.key().as_bytes().to_vec(), + source_base_url.as_bytes().to_vec(), + longitude.encode(), + )); + + Ok(call) +} + +#[no_mangle] +pub unsafe extern "C" fn update_weather_data_xt( + weather_info_longitude: *const u8, + weather_info_longitude_size: u32, + weather_info_latitude: *const u8, + weather_info_latitude_size: u32, + unchecked_extrinsic: *mut u8, + unchecked_extrinsic_max_size: u32, + unchecked_extrinsic_size: *mut u32, +) -> sgx_status_t { + let mut weather_info_longitude_slice = + slice::from_raw_parts(weather_info_longitude, weather_info_longitude_size as usize); + let longitude = match String::decode(&mut weather_info_longitude_slice) { + Ok(val) => val, + Err(e) => { + error!("Could not decode longitude: {:?}", e); + return sgx_status_t::SGX_ERROR_UNEXPECTED + }, + }; + + let mut weather_info_latitude_slice = + slice::from_raw_parts(weather_info_latitude, weather_info_latitude_size as usize); + let latitude = match String::decode(&mut weather_info_latitude_slice) { + Ok(val) => val, + Err(e) => { + error!("Could not decode latitude: {:?}", e); + return sgx_status_t::SGX_ERROR_UNEXPECTED + }, + }; + + let weather_query = WeatherQuery { longitude, latitude, hourly: " ".into() }; + let weather_info = WeatherInfo { weather_query }; + + let extrinsics = match update_weather_data_internal(weather_info) { + Ok(xts) => xts, + Err(e) => { + error!("Updating weather info failed: {:?}", e); + return sgx_status_t::SGX_ERROR_UNEXPECTED + }, + }; + + let extrinsic_slice = + slice::from_raw_parts_mut(unchecked_extrinsic, unchecked_extrinsic_max_size as usize); + + // Save created extrinsic as slice in the return value unchecked_extrinsic. + *unchecked_extrinsic_size = + match write_slice_and_whitespace_pad(extrinsic_slice, extrinsics.encode()) { + Ok(l) => l as u32, + Err(e) => { + error!("Copying encoded extrinsics into return slice failed: {:?}", e); + return sgx_status_t::SGX_ERROR_UNEXPECTED + }, + }; + + sgx_status_t::SGX_SUCCESS +} + +/// For now get the crypto/fiat currency exchange rate from coingecko and CoinMarketCap. +#[no_mangle] +pub unsafe extern "C" fn update_market_data_xt( + crypto_currency_ptr: *const u8, + crypto_currency_size: u32, + fiat_currency_ptr: *const u8, + fiat_currency_size: u32, + unchecked_extrinsic: *mut u8, + unchecked_extrinsic_max_size: u32, + unchecked_extrinsic_size: *mut u32, +) -> sgx_status_t { + let mut crypto_currency_slice = + slice::from_raw_parts(crypto_currency_ptr, crypto_currency_size as usize); + #[allow(clippy::unwrap_used)] + let crypto_currency: String = Decode::decode(&mut crypto_currency_slice).unwrap(); + + let mut fiat_currency_slice = + slice::from_raw_parts(fiat_currency_ptr, fiat_currency_size as usize); + #[allow(clippy::unwrap_used)] + let fiat_currency: String = Decode::decode(&mut fiat_currency_slice).unwrap(); + + let extrinsics = match update_market_data_internal(crypto_currency, fiat_currency) { + Ok(xts) => xts, + Err(e) => { + error!("Update market data failed: {:?}", e); + return sgx_status_t::SGX_ERROR_UNEXPECTED + }, + }; + + if extrinsics.is_empty() { + error!("Updating market data yielded no extrinsics"); + return sgx_status_t::SGX_ERROR_UNEXPECTED + } + let extrinsic_slice = + slice::from_raw_parts_mut(unchecked_extrinsic, unchecked_extrinsic_max_size as usize); + + // Save created extrinsic as slice in the return value unchecked_extrinsic. + *unchecked_extrinsic_size = + match write_slice_and_whitespace_pad(extrinsic_slice, extrinsics.encode()) { + Ok(l) => l as u32, + Err(e) => { + error!("Copying encoded extrinsics into return slice failed: {:?}", e); + return sgx_status_t::SGX_ERROR_UNEXPECTED + }, + }; + + sgx_status_t::SGX_SUCCESS +} + +fn update_market_data_internal( + crypto_currency: String, + fiat_currency: String, +) -> Result> { + let extrinsics_factory = get_extrinsic_factory_from_integritee_solo_or_parachain()?; + let ocall_api = GLOBAL_OCALL_API_COMPONENT.get()?; + + let mut extrinsic_calls: Vec = Vec::new(); + + // Get the exchange rate + let trading_pair = TradingPair { crypto_currency, fiat_currency }; + + let coin_gecko_oracle = create_coin_gecko_oracle(ocall_api.clone()); + + match get_exchange_rate(trading_pair.clone(), coin_gecko_oracle) { + Ok(opaque_call) => extrinsic_calls.push(opaque_call), + Err(e) => { + error!("[-] Failed to get the newest exchange rate from CoinGecko. {:?}", e); + }, + }; + + let coin_market_cap_oracle = create_coin_market_cap_oracle(ocall_api); + match get_exchange_rate(trading_pair, coin_market_cap_oracle) { + Ok(oc) => extrinsic_calls.push(oc), + Err(e) => { + error!("[-] Failed to get the newest exchange rate from CoinMarketCap. {:?}", e); + }, + }; + + let extrinsics = extrinsics_factory.create_extrinsics(extrinsic_calls.as_slice(), None)?; + Ok(extrinsics) +} + +fn get_exchange_rate( + trading_pair: TradingPair, + oracle: ExchangeRateOracle, +) -> Result +where + OracleSourceType: OracleSource, + MetricsExporter: ExportMetrics, +{ + let (rate, base_url) = oracle + .get_exchange_rate(trading_pair.clone()) + .map_err(|e| Error::Other(e.into()))?; + + let source_base_url = base_url.as_str(); + + println!( + "Update the exchange rate: {} = {:?} for source {}", + trading_pair.clone().key(), + rate, + source_base_url, + ); + + let node_metadata_repository = + get_node_metadata_repository_from_integritee_solo_or_parachain()?; + + let call_ids = node_metadata_repository + .get_from_metadata(|m| m.update_exchange_rate_call_indexes()) + .map_err(Error::NodeMetadataProvider)? + .map_err(|e| Error::Other(format!("{:?}", e).into()))?; + + let call = OpaqueCall::from_tuple(&( + call_ids, + source_base_url.as_bytes().to_vec(), + trading_pair.key().as_bytes().to_vec(), + Some(rate), + )); + + Ok(call) +} diff --git a/bitacross-worker/enclave-runtime/src/test/Counter.sol b/bitacross-worker/enclave-runtime/src/test/Counter.sol new file mode 100644 index 0000000000..ce3cce3259 --- /dev/null +++ b/bitacross-worker/enclave-runtime/src/test/Counter.sol @@ -0,0 +1,31 @@ +pragma solidity >=0.8.0; + +contract Counter { + uint256 private value; + address private last_caller; + + constructor() { + value = 1; + last_caller = msg.sender; + } + + fallback() external payable { value = 5; } + + function inc() public { + value += 1; + last_caller = msg.sender; + } + + function add(uint delta) public { + value += delta; + last_caller = msg.sender; + } + + function get_value() view public returns (uint) { + return value; + } + + function get_last_caller() view public returns (address) { + return last_caller; + } +} \ No newline at end of file diff --git a/bitacross-worker/enclave-runtime/src/test/cert_tests.rs b/bitacross-worker/enclave-runtime/src/test/cert_tests.rs new file mode 100644 index 0000000000..ad3b78df76 --- /dev/null +++ b/bitacross-worker/enclave-runtime/src/test/cert_tests.rs @@ -0,0 +1,72 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::test::mocks::attestation_ocall_mock::AttestationOCallMock; +use hex::FromHexError; +use itp_attestation_handler::cert::{verify_attn_report, verify_mra_cert}; +use sgx_types::{sgx_measurement_t, sgx_status_t, SGX_HASH_SIZE}; +use std::vec::Vec; + +// Test data and tests are mostly copied from: +// https://github.com/integritee-network/pallet-teerex/blob/master/ias-verify/ + +const TEST4_CERT: &[u8] = include_bytes!("fixtures/ra_dump_cert_TEST4.der"); + +const TEST4_MRENCLAVE: &str = "7a3454ec8f42e265cb5be7dfd111e1d95ac6076ed82a0948b2e2a45cf17b62a0"; + +#[allow(clippy::octal_escapes)] +const CERT_WRONG_PLATFORM_BLOB: &[u8] = b"0\x82\x0c\x8c0\x82\x0c2\xa0\x03\x02\x01\x02\x02\x01\x010\n\x06\x08*\x86H\xce=\x04\x03\x020\x121\x100\x0e\x06\x03U\x04\x03\x0c\x07MesaTEE0\x1e\x17\r190617124609Z\x17\r190915124609Z0\x121\x100\x0e\x06\x03U\x04\x03\x0c\x07MesaTEE0Y0\x13\x06\x07*\x86H\xce=\x02\x01\x06\x08*\x86H\xce=\x03\x01\x07\x03B\0\x04RT\x16\x16 \xef_\xd8\xe7\xc3\xb7\x03\x1d\xd6:\x1fF\xe3\xf2b!\xa9/\x8b\xd4\x82\x8f\xd1\xff[\x9c\x97\xbc\xf27\xb8,L\x8a\x01\xb0r;;\xa9\x83\xdc\x86\x9f\x1d%y\xf4;I\xe4Y\xc80'$K[\xd6\xa3\x82\x0bw0\x82\x0bs0\x82\x0bo\x06\t`\x86H\x01\x86\xf8B\x01\r\x04\x82\x0b`{\"id\":\"117077750682263877593646412006783680848\",\"timestamp\":\"2019-06-17T12:46:04.002066\",\"version\":3,\"isvEnclaveQuoteStatus\":\"GROUP_OUT_OF_DATE\",\"platformInfoBlob\":\"1602006504000900000909020401800000000000000000000008000009000000020000000000000B401A355B313FC939B4F48A54349C914A32A3AE2C4871BFABF22E960C55635869FC66293A3D9B2D58ED96CA620B65D669A444C80291314EF691E896F664317CF80C\",\"isvEnclaveQuoteBody\":\"AgAAAEALAAAIAAcAAAAAAOE6wgoHKsZsnVWSrsWX9kky0kWt9K4xcan0fQ996Ct+CAj//wGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwAAAAAAAAAHAAAAAAAAAFJJYIbPVot9NzRCjW2z9+k+9K8BsHQKzVMEHOR14hNbAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACD1xnnferKFHD2uvYqTXdDA8iZ22kCD5xw7h38CMfOngAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABSVBYWIO9f2OfDtwMd1jofRuPyYiGpL4vUgo/R/1ucl7zyN7gsTIoBsHI7O6mD3IafHSV59DtJ5FnIMCckS1vW\"}|EbPFH/ThUaS/dMZoDKC5EgmdUXUORFtQzF49Umi1P55oeESreJaUvmA0sg/ATSTn5t2e+e6ZoBQIUbLHjcWLMLzK4pJJUeHhok7EfVgoQ378i+eGR9v7ICNDGX7a1rroOe0s1OKxwo/0hid2KWvtAUBvf1BDkqlHy025IOiXWhXFLkb/qQwUZDWzrV4dooMfX5hfqJPi1q9s18SsdLPmhrGBheh9keazeCR9hiLhRO9TbnVgR9zJk43SPXW+pHkbNigW+2STpVAi5ugWaSwBOdK11ZjaEU1paVIpxQnlW1D6dj1Zc3LibMH+ly9ZGrbYtuJks4eRnjPhroPXxlJWpQ==|MIIEoTCCAwmgAwIBAgIJANEHdl0yo7CWMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEUMBIGA1UEBwwLU2FudGEgQ2xhcmExGjAYBgNVBAoMEUludGVsIENvcnBvcmF0aW9uMTAwLgYDVQQDDCdJbnRlbCBTR1ggQXR0ZXN0YXRpb24gUmVwb3J0IFNpZ25pbmcgQ0EwHhcNMTYxMTIyMDkzNjU4WhcNMjYxMTIwMDkzNjU4WjB7MQswCQYDVQQGEwJVUzELMAkGA1UECAwCQ0ExFDASBgNVBAcMC1NhbnRhIENsYXJhMRowGAYDVQQKDBFJbnRlbCBDb3Jwb3JhdGlvbjEtMCsGA1UEAwwkSW50ZWwgU0dYIEF0dGVzdGF0aW9uIFJlcG9ydCBTaWduaW5nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqXot4OZuphR8nudFrAFiaGxxkgma/Es/BA+tbeCTUR106AL1ENcWA4FX3K+E9BBL0/7X5rj5nIgX/R/1ubhkKWw9gfqPG3KeAtIdcv/uTO1yXv50vqaPvE1CRChvzdS/ZEBqQ5oVvLTPZ3VEicQjlytKgN9cLnxbwtuvLUK7eyRPfJW/ksddOzP8VBBniolYnRCD2jrMRZ8nBM2ZWYwnXnwYeOAHV+W9tOhAImwRwKF/95yAsVwd21ryHMJBcGH70qLagZ7Ttyt++qO/6+KAXJuKwZqjRlEtSEz8gZQeFfVYgcwSfo96oSMAzVr7V0L6HSDLRnpb6xxmbPdqNol4tQIDAQABo4GkMIGhMB8GA1UdIwQYMBaAFHhDe3amfrzQr35CN+s1fDuHAVE8MA4GA1UdDwEB/wQEAwIGwDAMBgNVHRMBAf8EAjAAMGAGA1UdHwRZMFcwVaBToFGGT2h0dHA6Ly90cnVzdGVkc2VydmljZXMuaW50ZWwuY29tL2NvbnRlbnQvQ1JML1NHWC9BdHRlc3RhdGlvblJlcG9ydFNpZ25pbmdDQS5jcmwwDQYJKoZIhvcNAQELBQADggGBAGcIthtcK9IVRz4rRq+ZKE+7k50/OxUsmW8aavOzKb0iCx07YQ9rzi5nU73tME2yGRLzhSViFs/LpFa9lpQL6JL1aQwmDR74TxYGBAIi5f4I5TJoCCEqRHz91kpG6Uvyn2tLmnIdJbPE4vYvWLrtXXfFBSSPD4Afn7+3/XUggAlc7oCTizOfbbtOFlYA4g5KcYgS1J2ZAeMQqbUdZseZCcaZZZn65tdqee8UXZlDvx0+NdO0LR+5pFy+juM0wWbu59MvzcmTXbjsi7HY6zd53Yq5K244fwFHRQ8eOB0IWB+4PfM7FeAApZvlfqlKOlLcZL2uyVmzRkyR5yW72uo9mehX44CiPJ2fse9Y6eQtcfEhMPkmHXI01sN+KwPbpA39+xOsStjhP9N1Y1a2tQAVo+yVgLgV2Hws73Fc0o3wC78qPEA+v2aRs/Be3ZFDgDyghc/1fgU+7C+P6kbqd4poyb6IW8KCJbxfMJvkordNOgOUUxndPHEi/tb/U7uLjLOgPA==0\n\x06\x08*\x86H\xce=\x04\x03\x02\x03H\00E\x02!\0\xae6\x06\t@Sy\x8f\x8ec\x9d\xdci^Ex*\x92}\xdcG\x15A\x97\xd7\xd7\xd1\xccx\xe0\x1e\x08\x02 \x15Q\xa0BT\xde'~\xec\xbd\x027\xd3\xd8\x83\xf7\xe6Z\xc5H\xb4D\xf7\xe2\r\xa7\xe4^f\x10\x85p"; + +pub fn test_verify_mra_cert_should_work() { + let mr_enclave = get_mr_enclave_from_hex_string(TEST4_MRENCLAVE).unwrap(); + let attestation_ocall = + AttestationOCallMock::create_with_mr_enclave(sgx_measurement_t { m: mr_enclave }); + let result = verify_mra_cert(TEST4_CERT, false, false, &attestation_ocall); + + assert!(result.is_ok()); +} + +pub fn test_verify_wrong_cert_is_err() { + let mr_enclave = get_mr_enclave_from_hex_string(TEST4_MRENCLAVE).unwrap(); + let attestation_ocall = + AttestationOCallMock::create_with_mr_enclave(sgx_measurement_t { m: mr_enclave }); + let result = verify_mra_cert(CERT_WRONG_PLATFORM_BLOB, false, false, &attestation_ocall); + + assert!(result.is_err()); + assert_eq!(result.unwrap_err(), sgx_status_t::SGX_ERROR_UNEXPECTED); +} + +pub fn test_given_wrong_platform_info_when_verifying_attestation_report_then_return_error() { + let attestation_ocall = AttestationOCallMock::new(); + let result = verify_attn_report(CERT_WRONG_PLATFORM_BLOB, Vec::new(), &attestation_ocall); + + assert!(result.is_err()); + assert_eq!(result.unwrap_err(), sgx_status_t::SGX_ERROR_UNEXPECTED); +} + +fn get_mr_enclave_from_hex_string(input_str: &str) -> Result<[u8; SGX_HASH_SIZE], FromHexError> { + let decoded_str = hex::decode(input_str)?; + + if decoded_str.len() != SGX_HASH_SIZE { + return Err(FromHexError::InvalidStringLength) + } + + let mut mr_enclave = [0u8; SGX_HASH_SIZE]; + mr_enclave.clone_from_slice(decoded_str.as_slice()); + + Ok(mr_enclave) +} diff --git a/bitacross-worker/enclave-runtime/src/test/direct_rpc_tests.rs b/bitacross-worker/enclave-runtime/src/test/direct_rpc_tests.rs new file mode 100644 index 0000000000..bcb7ba5d45 --- /dev/null +++ b/bitacross-worker/enclave-runtime/src/test/direct_rpc_tests.rs @@ -0,0 +1,91 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{rpc::worker_api_direct::public_api_rpc_handler, Hash}; +use codec::{Decode, Encode}; +use ita_stf::{Getter, PublicGetter}; +use itc_direct_rpc_server::{ + create_determine_watch, rpc_connection_registry::ConnectionRegistry, + rpc_ws_handler::RpcWsHandler, +}; +use itc_tls_websocket_server::{ConnectionToken, WebSocketMessageHandler}; +use itp_rpc::{Id, RpcRequest, RpcReturnValue}; +use itp_sgx_crypto::get_rsa3072_repository; +use itp_sgx_temp_dir::TempDir; +use itp_stf_executor::{getter_executor::GetterExecutor, mocks::GetStateMock}; +use itp_stf_state_observer::mock::ObserveStateMock; +use itp_test::mock::handle_state_mock::HandleStateMock; +use itp_top_pool_author::mocks::AuthorApiMock; +use itp_types::{DirectRequestStatus, RsaRequest, ShardIdentifier}; +use itp_utils::{FromHexPrefixed, ToHexPrefixed}; +use litentry_primitives::{Address32, Identity}; +use std::{string::ToString, sync::Arc, vec::Vec}; + +pub fn get_state_request_works() { + type TestState = u64; + + let temp_dir = TempDir::with_prefix("get_state_request_works").unwrap(); + + let connection_registry = Arc::new(ConnectionRegistry::::new()); + let watch_extractor = Arc::new(create_determine_watch::()); + let rsa_repository = get_rsa3072_repository(temp_dir.path().to_path_buf()).unwrap(); + + let state: TestState = 78234u64; + let state_observer = Arc::new(ObserveStateMock::::new(state)); + let getter_executor = + Arc::new(GetterExecutor::<_, GetStateMock, Getter>::new(state_observer)); + let top_pool_author = Arc::new(AuthorApiMock::default()); + + let io_handler = public_api_rpc_handler( + top_pool_author, + getter_executor, + Arc::new(rsa_repository), + None::>, + ); + let rpc_handler = Arc::new(RpcWsHandler::new(io_handler, watch_extractor, connection_registry)); + + let getter = + Getter::public(PublicGetter::nonce(Identity::Substrate(Address32::from([0u8; 32])))); + + let request = RsaRequest::new(ShardIdentifier::default(), getter.encode()); + + let request_string = RpcRequest::compose_jsonrpc_call( + Id::Text("1".to_string()), + "state_executeGetter".to_string(), + vec![request.to_hex()], + ) + .unwrap(); + + let response_string = + rpc_handler.handle_message(ConnectionToken(1), request_string).unwrap().unwrap(); + + assert!(!response_string.is_empty()); + + // Because we cannot de-serialize the RpcResponse here (unresolved serde_json and std/sgx feature issue), + // we hard-code the expected response. + //error!("{}", response_string); + //let response: RpcResponse = serde_json::from_str(&response_string).unwrap(); + + const EXPECTED_HEX_RETURN_VALUE: &str = "0x2801209a310100000000000000"; + assert!(response_string.contains(EXPECTED_HEX_RETURN_VALUE)); + let rpc_return_value = RpcReturnValue::from_hex(EXPECTED_HEX_RETURN_VALUE).unwrap(); + assert_eq!(rpc_return_value.status, DirectRequestStatus::Ok); + let decoded_value: Option> = + Option::decode(&mut rpc_return_value.value.as_slice()).unwrap(); + assert_eq!(decoded_value, Some(state.encode())); +} diff --git a/bitacross-worker/enclave-runtime/src/test/enclave_signer_tests.rs b/bitacross-worker/enclave-runtime/src/test/enclave_signer_tests.rs new file mode 100644 index 0000000000..7698091dd6 --- /dev/null +++ b/bitacross-worker/enclave-runtime/src/test/enclave_signer_tests.rs @@ -0,0 +1,169 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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; +use ita_sgx_runtime::Runtime; +use ita_stf::{Getter, Stf, TrustedCall, TrustedCallSigned}; +use itp_node_api::metadata::{metadata_mocks::NodeMetadataMock, provider::NodeMetadataRepository}; +use itp_ocall_api::EnclaveAttestationOCallApi; +use itp_sgx_crypto::{ + ed25519_derivation::DeriveEd25519, key_repository::AccessKey, mocks::KeyRepositoryMock, +}; +use itp_sgx_externalities::SgxExternalities; +use itp_stf_executor::{enclave_signer::StfEnclaveSigner, traits::StfEnclaveSigning}; +use itp_stf_interface::{ + mocks::GetterExecutorMock, system_pallet::SystemPalletAccountInterface, InitState, + StateCallInterface, +}; +use itp_stf_primitives::{ + traits::TrustedCallVerification, + types::{AccountId, ShardIdentifier, TrustedOperation}, +}; +use itp_stf_state_observer::mock::ObserveStateMock; +use itp_test::mock::onchain_mock::OnchainMock; +use itp_top_pool_author::{mocks::AuthorApiMock, traits::AuthorApi}; +use itp_types::RsaRequest; +use litentry_primitives::Identity; +use sgx_crypto_helper::{rsa3072::Rsa3072KeyPair, RsaKeyPair}; +use sp_core::Pair; +use std::{sync::Arc, vec::Vec}; + +type ShieldingKeyRepositoryMock = KeyRepositoryMock; +type TestStf = Stf; + +pub fn derive_key_is_deterministic() { + let rsa_key = Rsa3072KeyPair::new().unwrap(); + + let first_ed_key = rsa_key.derive_ed25519().unwrap(); + let second_ed_key = rsa_key.derive_ed25519().unwrap(); + assert_eq!(first_ed_key.public(), second_ed_key.public()); +} + +pub fn enclave_signer_signatures_are_valid() { + let top_pool_author = Arc::new(AuthorApiMock::default()); + let ocall_api = Arc::new(OnchainMock::default()); + let shielding_key_repo = Arc::new(ShieldingKeyRepositoryMock::default()); + let enclave_account: AccountId = shielding_key_repo + .retrieve_key() + .unwrap() + .derive_ed25519() + .unwrap() + .public() + .into(); + + let state_observer: Arc> = + Arc::new(ObserveStateMock::new(TestStf::init_state(enclave_account.clone()))); + let shard = ShardIdentifier::default(); + let mr_enclave = ocall_api.get_mrenclave_of_self().unwrap(); + let enclave_signer = StfEnclaveSigner::<_, _, _, TestStf, _, TrustedCallSigned, Getter>::new( + state_observer, + ocall_api, + shielding_key_repo, + top_pool_author, + ); + let trusted_call = TrustedCall::balance_shield( + Identity::Substrate(enclave_account.into()), + AccountId::new([3u8; 32]), + 200u128, + ); + + let trusted_call_signed = enclave_signer.sign_call_with_self(&trusted_call, &shard).unwrap(); + assert!(trusted_call_signed.verify_signature(&mr_enclave.m, &shard)); +} + +pub fn nonce_is_computed_correctly() { + let top_pool_author = Arc::new(AuthorApiMock::default()); + let ocall_api = Arc::new(OnchainMock::default()); + let shielding_key_repo = Arc::new(ShieldingKeyRepositoryMock::default()); + let enclave_account: AccountId = shielding_key_repo + .retrieve_key() + .unwrap() + .derive_ed25519() + .unwrap() + .public() + .into(); + let mut state = TestStf::init_state(enclave_account.clone()); + // only used to create the enclave signer, the state is **not** synchronised + let state_observer: Arc> = + Arc::new(ObserveStateMock::new(state.clone())); + let shard = ShardIdentifier::default(); + let enclave_signer = StfEnclaveSigner::<_, _, _, TestStf, _, TrustedCallSigned, Getter>::new( + state_observer, + ocall_api, + shielding_key_repo, + top_pool_author.clone(), + ); + assert_eq!(enclave_account, enclave_signer.get_enclave_account().unwrap()); + + // create the first trusted_call and submit it + let trusted_call_1 = TrustedCall::balance_shield( + Identity::Substrate(enclave_account.clone().into()), + AccountId::new([1u8; 32]), + 100u128, + ); + let trusted_call_1_signed = + enclave_signer.sign_call_with_self(&trusted_call_1, &shard).unwrap(); + top_pool_author.submit_top(RsaRequest::new( + shard, + TrustedOperation::::indirect_call(trusted_call_1_signed.clone()) + .encode(), + )); + assert_eq!(1, top_pool_author.get_pending_trusted_calls_for(shard, &enclave_account).len()); + // create the second trusted_call and submit it + let trusted_call_2 = TrustedCall::balance_shield( + Identity::Substrate(enclave_account.clone().into()), + AccountId::new([2u8; 32]), + 200u128, + ); + let trusted_call_2_signed = + enclave_signer.sign_call_with_self(&trusted_call_2, &shard).unwrap(); + top_pool_author.submit_top(RsaRequest::new( + shard, + TrustedOperation::::indirect_call(trusted_call_2_signed.clone()) + .encode(), + )); + assert_eq!(2, top_pool_author.get_pending_trusted_calls_for(shard, &enclave_account).len()); + // there should be no pending trusted calls for non-enclave-account + assert_eq!( + 0, + top_pool_author + .get_pending_trusted_calls_for(shard, &AccountId::new([1u8; 32])) + .len() + ); + + assert_eq!(0, TestStf::get_account_nonce(&mut state, &enclave_account)); + let repo = Arc::new(NodeMetadataRepository::new(NodeMetadataMock::new())); + assert!(TestStf::execute_call( + &mut state, + &shard, + trusted_call_1_signed, + Default::default(), + &mut Vec::new(), + repo.clone(), + ) + .is_ok()); + + assert!(TestStf::execute_call( + &mut state, + &shard, + trusted_call_2_signed, + Default::default(), + &mut Vec::new(), + repo, + ) + .is_ok()); + assert_eq!(2, TestStf::get_account_nonce(&mut state, &enclave_account)); +} diff --git a/bitacross-worker/enclave-runtime/src/test/evm_pallet_tests.rs b/bitacross-worker/enclave-runtime/src/test/evm_pallet_tests.rs new file mode 100644 index 0000000000..61a8912e2e --- /dev/null +++ b/bitacross-worker/enclave-runtime/src/test/evm_pallet_tests.rs @@ -0,0 +1,401 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::test::fixtures::test_setup::{test_setup, TestStf}; +use core::str::FromStr; +use ita_sgx_runtime::{AddressMapping, HashedAddressMapping, Index, System}; +use ita_stf::{ + evm_helpers::{ + create_code_hash, evm_create2_address, evm_create_address, get_evm_account_codes, + get_evm_account_storages, + }, + test_genesis::{endow, endowed_account as funded_pair}, + State, TrustedCall, +}; +use itp_node_api::metadata::{metadata_mocks::NodeMetadataMock, provider::NodeMetadataRepository}; +use itp_sgx_externalities::SgxExternalitiesTrait; +use itp_stf_interface::StateCallInterface; +use itp_stf_primitives::{traits::TrustedCallSigning, types::KeyPair}; +use itp_types::{parentchain::ParentchainCall, AccountId, ShardIdentifier}; +use primitive_types::H256; +use sp_core::{crypto::Pair, H160, U256}; +use std::{sync::Arc, vec::Vec}; + +pub fn test_evm_call() { + // given + let (_, mut state, shard, mrenclave, ..) = test_setup(); + let mut parentchain_calls = Vec::new(); + + // Create the sender account. + let sender = funded_pair(); + let sender_acc: AccountId = sender.public().into(); + let mut sender_evm_acc_slice: [u8; 20] = [0; 20]; + sender_evm_acc_slice + .copy_from_slice((<[u8; 32]>::from(sender_acc.clone())).get(0..20).unwrap()); + let sender_evm_acc: H160 = sender_evm_acc_slice.into(); + // Ensure the substrate version of the evm account has some money. + let sender_evm_substrate_addr = + ita_sgx_runtime::HashedAddressMapping::into_account_id(sender_evm_acc); + endow(&mut state, vec![(sender_evm_substrate_addr, 51_777_000_000_000)]); + + // Create the receiver account. + let destination_evm_acc = H160::from_str("1000000000000000000000000000000000000001").unwrap(); + let destination_evm_substrate_addr = + ita_sgx_runtime::HashedAddressMapping::into_account_id(destination_evm_acc); + assert_eq!( + state.execute_with(|| System::account(&destination_evm_substrate_addr).data.free), + 0 + ); + + let transfer_value: u128 = 1_000_000_000; + + let trusted_call = TrustedCall::evm_call( + sender_acc, + sender_evm_acc, + destination_evm_acc, + Vec::new(), + U256::from(transfer_value), + 21776, // gas limit + U256::from(1_000_000_000), + None, + Some(U256::from(0)), + Vec::new(), + ) + .sign(&sender.into(), 0, &mrenclave, &shard); + + // when + let repo = Arc::new(NodeMetadataRepository::::default()); + let shard = ShardIdentifier::default(); + TestStf::execute_call( + &mut state, + &shard, + trusted_call, + Default::default(), + &mut parentchain_calls, + repo, + ) + .unwrap(); + + // then + assert_eq!( + transfer_value, + state.execute_with(|| System::account(&destination_evm_substrate_addr).data.free) + ); +} + +pub fn test_evm_counter() { + // given + let (_, mut state, shard, mrenclave, ..) = test_setup(); + let mut parentchain_calls = Vec::new(); + + // Create the sender account. + let sender = funded_pair(); + let sender_acc: AccountId = sender.public().into(); + let mut sender_evm_acc_slice: [u8; 20] = [0; 20]; + sender_evm_acc_slice + .copy_from_slice((<[u8; 32]>::from(sender_acc.clone())).get(0..20).unwrap()); + let sender_evm_acc: H160 = sender_evm_acc_slice.into(); + // Ensure the substrate version of the evm account has some money. + let sender_evm_substrate_addr = + ita_sgx_runtime::HashedAddressMapping::into_account_id(sender_evm_acc); + endow(&mut state, vec![(sender_evm_substrate_addr, 51_777_000_000_000)]); + + // Smart Contract from Counter.sol. + let smart_contract = "608060405234801561001057600080fd5b50600160008190555033600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550610377806100696000396000f3fe6080604052600436106100435760003560e01c80631003e2d21461004d57806333cf508014610076578063371303c0146100a157806358992216146100b857610044565b5b60056000819055005b34801561005957600080fd5b50610074600480360381019061006f9190610209565b6100e3565b005b34801561008257600080fd5b5061008b61013f565b6040516100989190610245565b60405180910390f35b3480156100ad57600080fd5b506100b6610148565b005b3480156100c457600080fd5b506100cd6101a4565b6040516100da91906102a1565b60405180910390f35b806000808282546100f491906102eb565b9250508190555033600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60008054905090565b600160008082825461015a91906102eb565b9250508190555033600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600080fd5b6000819050919050565b6101e6816101d3565b81146101f157600080fd5b50565b600081359050610203816101dd565b92915050565b60006020828403121561021f5761021e6101ce565b5b600061022d848285016101f4565b91505092915050565b61023f816101d3565b82525050565b600060208201905061025a6000830184610236565b92915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061028b82610260565b9050919050565b61029b81610280565b82525050565b60006020820190506102b66000830184610292565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006102f6826101d3565b9150610301836101d3565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115610336576103356102bc565b5b82820190509291505056fea2646970667358221220b37e993e133ed19c840809cc8acbbba8116dee3744ba01c81044d75146805c9364736f6c634300080f0033"; + + let trusted_call = TrustedCall::evm_create( + sender_acc.clone(), + sender_evm_acc, + array_bytes::hex2bytes(smart_contract).unwrap().to_vec(), + U256::from(0), + 10_000_000, // gas limit + U256::from(1), // max_fee_per_gas !>= min_gas_price defined in runtime + None, + Some(U256::from(0)), + Vec::new(), + ) + .sign(&sender.into(), 0, &mrenclave, &shard); + + // when + let execution_address = evm_create_address(sender_evm_acc, 0); + let repo = Arc::new(NodeMetadataRepository::::default()); + let shard = ShardIdentifier::default(); + TestStf::execute_call( + &mut state, + &shard, + trusted_call, + Default::default(), + &mut parentchain_calls, + repo, + ) + .unwrap(); + + // then + assert_eq!( + execution_address, + H160::from_slice( + &array_bytes::hex2bytes("0xce2c9e7f9c10049996173b2ca2d9a6815a70e890").unwrap(), + ) + ); + + assert!(state.execute_with(|| get_evm_account_codes(&execution_address).is_some())); + + let counter_value = state + .execute_with(|| get_evm_account_storages(&execution_address, &H256::zero())) + .unwrap(); + assert_eq!(H256::from_low_u64_be(1), counter_value); + let last_caller = state + .execute_with(|| get_evm_account_storages(&execution_address, &H256::from_low_u64_be(1))) + .unwrap(); + assert_eq!(H256::from(sender_evm_acc), last_caller); + + // Call to inc() function + // in solidity compile information you get the hash of the call + let inc_function_input = array_bytes::hex2bytes("371303c0").unwrap(); + + execute_and_verify_evm_call( + sender_acc.clone(), + sender_evm_acc, + execution_address, + inc_function_input.to_vec(), + 1, + 1, + sender.into(), + &mrenclave, + &shard, + &mut state, + &mut parentchain_calls, + 2, + ); + + // Call the fallback function + execute_and_verify_evm_call( + sender_acc.clone(), + sender_evm_acc, + execution_address, + Vec::new(), // Empty input calls the fallback function. + 2, + 2, + sender.into(), + &mrenclave, + &shard, + &mut state, + &mut parentchain_calls, + 5, + ); + + // Call to inc() function + // in solidity compile information you get the hash of the call + execute_and_verify_evm_call( + sender_acc.clone(), + sender_evm_acc, + execution_address, + inc_function_input, + 3, + 3, + sender.into(), + &mrenclave, + &shard, + &mut state, + &mut parentchain_calls, + 6, + ); + + // Call to add() function + // in solidity compile information you get the hash of the call + let function_hash = "1003e2d2"; + // 32 byte string of the value to add in hex + let add_value = "0000000000000000000000000000000000000000000000000000000000000002"; + let add_function_input = + array_bytes::hex2bytes(&format!("{}{}", function_hash, add_value)).unwrap(); + + execute_and_verify_evm_call( + sender_acc, + sender_evm_acc, + execution_address, + add_function_input, + 4, + 4, + sender.into(), + &mrenclave, + &shard, + &mut state, + &mut parentchain_calls, + 8, + ); +} + +#[allow(clippy::too_many_arguments)] +fn execute_and_verify_evm_call( + sender_acc: AccountId, + sender_evm_acc: H160, + execution_address: H160, + function_input: Vec, + evm_nonce: i8, + nonce: Index, + pair: KeyPair, + mrenclave: &[u8; 32], + shard: &ShardIdentifier, + state: &mut State, + calls: &mut Vec, + counter_expected: u64, +) { + let inc_call = TrustedCall::evm_call( + sender_acc, + sender_evm_acc, + execution_address, + function_input, + U256::from(0), + 10_000_000, // gas limit + U256::from(1), // max_fee_per_gas !>= min_gas_price defined in runtime + None, + Some(U256::from(evm_nonce)), + Vec::new(), + ) + .sign(&pair, nonce, mrenclave, shard); + let repo = Arc::new(NodeMetadataRepository::::default()); + let shard = ShardIdentifier::default(); + TestStf::execute_call(state, &shard, inc_call, Default::default(), calls, repo).unwrap(); + + let counter_value = state + .execute_with(|| get_evm_account_storages(&execution_address, &H256::zero())) + .unwrap(); + assert_eq!(counter_value, H256::from_low_u64_be(counter_expected)); +} + +pub fn test_evm_create() { + // given + let (_, mut state, shard, mrenclave, ..) = test_setup(); + let mut parentchain_calls = Vec::new(); + + // Create the sender account. + let sender = funded_pair(); + let sender_acc: AccountId = sender.public().into(); + let mut sender_evm_acc_slice: [u8; 20] = [0; 20]; + sender_evm_acc_slice + .copy_from_slice((<[u8; 32]>::from(sender_acc.clone())).get(0..20).unwrap()); + let sender_evm_acc: H160 = sender_evm_acc_slice.into(); + // Ensure the substrate version of the evm account has some money. + let sender_evm_substrate_addr = HashedAddressMapping::into_account_id(sender_evm_acc); + endow(&mut state, vec![(sender_evm_substrate_addr.clone(), 51_777_000_000_000)]); + + // Bytecode from Counter.sol + let smart_contract = "608060405234801561001057600080fd5b50600160008190555033600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550610377806100696000396000f3fe6080604052600436106100435760003560e01c80631003e2d21461004d57806333cf508014610076578063371303c0146100a157806358992216146100b857610044565b5b60056000819055005b34801561005957600080fd5b50610074600480360381019061006f9190610209565b6100e3565b005b34801561008257600080fd5b5061008b61013f565b6040516100989190610245565b60405180910390f35b3480156100ad57600080fd5b506100b6610148565b005b3480156100c457600080fd5b506100cd6101a4565b6040516100da91906102a1565b60405180910390f35b806000808282546100f491906102eb565b9250508190555033600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60008054905090565b600160008082825461015a91906102eb565b9250508190555033600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600080fd5b6000819050919050565b6101e6816101d3565b81146101f157600080fd5b50565b600081359050610203816101dd565b92915050565b60006020828403121561021f5761021e6101ce565b5b600061022d848285016101f4565b91505092915050565b61023f816101d3565b82525050565b600060208201905061025a6000830184610236565b92915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061028b82610260565b9050919050565b61029b81610280565b82525050565b60006020820190506102b66000830184610292565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006102f6826101d3565b9150610301836101d3565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115610336576103356102bc565b5b82820190509291505056fea2646970667358221220b37e993e133ed19c840809cc8acbbba8116dee3744ba01c81044d75146805c9364736f6c634300080f0033"; + let smart_contract = array_bytes::hex2bytes(smart_contract).unwrap(); + + let trusted_call = TrustedCall::evm_create( + sender_acc, + sender_evm_acc, + smart_contract, + U256::from(0), // value + 10_000_000, // gas limit + U256::from(1), // max_fee_per_gas !>= min_gas_price defined in runtime + None, + Some(U256::from(0)), + Vec::new(), + ) + .sign(&sender.into(), 0, &mrenclave, &shard); + + // Should be the first call of the evm account + let nonce = state.execute_with(|| System::account_nonce(&sender_evm_substrate_addr)); + assert_eq!(nonce, 0); + let execution_address = evm_create_address(sender_evm_acc, nonce); + let repo = Arc::new(NodeMetadataRepository::::default()); + let shard = ShardIdentifier::default(); + TestStf::execute_call( + &mut state, + &shard, + trusted_call, + Default::default(), + &mut parentchain_calls, + repo, + ) + .unwrap(); + + assert_eq!( + execution_address, + H160::from_slice( + &array_bytes::hex2bytes("0xce2c9e7f9c10049996173b2ca2d9a6815a70e890").unwrap(), + ) + ); + assert!(state.execute_with(|| get_evm_account_codes(&execution_address).is_some())); + + // Ensure the nonce of the evm account has been increased by one + // Should be the first call of the evm account + let nonce = state.execute_with(|| System::account_nonce(&sender_evm_substrate_addr)); + assert_eq!(nonce, 1); +} + +pub fn test_evm_create2() { + // given + let (_, mut state, shard, mrenclave, ..) = test_setup(); + let mut parentchain_calls = Vec::new(); + + // Create the sender account. + let sender = funded_pair(); + let sender_acc: AccountId = sender.public().into(); + let mut sender_evm_acc_slice: [u8; 20] = [0; 20]; + sender_evm_acc_slice + .copy_from_slice((<[u8; 32]>::from(sender_acc.clone())).get(0..20).unwrap()); + let sender_evm_acc: H160 = sender_evm_acc_slice.into(); + // Ensure the substrate version of the evm account has some money. + let sender_evm_substrate_addr = HashedAddressMapping::into_account_id(sender_evm_acc); + endow(&mut state, vec![(sender_evm_substrate_addr, 51_777_000_000_000)]); + + let salt = H256::from_low_u64_be(20); + // Bytecode from Counter.sol + let smart_contract = "608060405234801561001057600080fd5b50600160008190555033600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550610377806100696000396000f3fe6080604052600436106100435760003560e01c80631003e2d21461004d57806333cf508014610076578063371303c0146100a157806358992216146100b857610044565b5b60056000819055005b34801561005957600080fd5b50610074600480360381019061006f9190610209565b6100e3565b005b34801561008257600080fd5b5061008b61013f565b6040516100989190610245565b60405180910390f35b3480156100ad57600080fd5b506100b6610148565b005b3480156100c457600080fd5b506100cd6101a4565b6040516100da91906102a1565b60405180910390f35b806000808282546100f491906102eb565b9250508190555033600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60008054905090565b600160008082825461015a91906102eb565b9250508190555033600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600080fd5b6000819050919050565b6101e6816101d3565b81146101f157600080fd5b50565b600081359050610203816101dd565b92915050565b60006020828403121561021f5761021e6101ce565b5b600061022d848285016101f4565b91505092915050565b61023f816101d3565b82525050565b600060208201905061025a6000830184610236565b92915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061028b82610260565b9050919050565b61029b81610280565b82525050565b60006020820190506102b66000830184610292565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006102f6826101d3565b9150610301836101d3565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115610336576103356102bc565b5b82820190509291505056fea2646970667358221220b37e993e133ed19c840809cc8acbbba8116dee3744ba01c81044d75146805c9364736f6c634300080f0033"; + let smart_contract = array_bytes::hex2bytes(smart_contract).unwrap(); + + let trusted_call = TrustedCall::evm_create2( + sender_acc, + sender_evm_acc, + smart_contract.clone(), + salt, + U256::from(0), // value + 10_000_000, // gas limit + U256::from(1), // max_fee_per_gas !>= min_gas_price defined in runtime + None, + Some(U256::from(0)), + Vec::new(), + ) + .sign(&sender.into(), 0, &mrenclave, &shard); + + // when + let code_hash = create_code_hash(&smart_contract); + let execution_address = evm_create2_address(sender_evm_acc, salt, code_hash); + let repo = Arc::new(NodeMetadataRepository::::default()); + let shard = ShardIdentifier::default(); + TestStf::execute_call( + &mut state, + &shard, + trusted_call, + Default::default(), + &mut parentchain_calls, + repo, + ) + .unwrap(); + + // then + assert_eq!( + execution_address, + H160::from_slice( + &array_bytes::hex2bytes("0xe07ad7925f6b2b10c5a7653fb16db7a984059d11").unwrap(), + ) + ); + + assert!(state.execute_with(|| get_evm_account_codes(&execution_address).is_some())); +} diff --git a/bitacross-worker/enclave-runtime/src/test/fixtures/components.rs b/bitacross-worker/enclave-runtime/src/test/fixtures/components.rs new file mode 100644 index 0000000000..dd1237672d --- /dev/null +++ b/bitacross-worker/enclave-runtime/src/test/fixtures/components.rs @@ -0,0 +1,69 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::test::mocks::types::{TestOCallApi, TestRpcResponder, TestSigner, TestTopPool}; +use codec::Encode; +use ita_stf::{Getter, TrustedCall, TrustedCallSigned}; +use itp_ocall_api::EnclaveAttestationOCallApi; +use itp_sgx_crypto::ShieldingCryptoEncrypt; +use itp_stf_primitives::{ + traits::TrustedCallSigning, + types::{KeyPair, TrustedOperation}, +}; +use itp_top_pool::pool::Options as PoolOptions; +use itp_top_pool_author::api::SidechainApi; +use itp_types::{Block as ParentchainBlock, Enclave, ShardIdentifier}; +use sp_core::{ed25519, Pair, H256}; +use sp_runtime::traits::Header as HeaderTrait; +use std::{boxed::Box, sync::Arc, vec::Vec}; +pub(crate) fn create_top_pool() -> Arc { + let rpc_responder = Arc::new(TestRpcResponder::new()); + let sidechain_api = Arc::new(SidechainApi::::new()); + Arc::new(TestTopPool::create(PoolOptions::default(), sidechain_api, rpc_responder)) +} + +pub(crate) fn create_ocall_api>( + header: &Header, + signer: &TestSigner, +) -> Arc { + let enclave_validateer = Enclave::new( + signer.public().into(), + Default::default(), + Default::default(), + Default::default(), + ); + Arc::new(TestOCallApi::default().add_validateer_set(header, Some(vec![enclave_validateer]))) +} + +pub(crate) fn encrypt_trusted_operation( + shielding_key: &ShieldingKey, + trusted_operation: &TrustedOperation, +) -> Vec { + let encoded_operation = trusted_operation.encode(); + shielding_key.encrypt(encoded_operation.as_slice()).unwrap() +} + +pub(crate) fn sign_trusted_call( + trusted_call: &TrustedCall, + attestation_api: &AttestationApi, + shard_id: &ShardIdentifier, + from: ed25519::Pair, +) -> TrustedCallSigned { + let mr_enclave = attestation_api.get_mrenclave_of_self().unwrap(); + trusted_call.sign(&KeyPair::Ed25519(Box::new(from)), 0, &mr_enclave.m, shard_id) +} diff --git a/bitacross-worker/enclave-runtime/src/test/fixtures/initialize_test_state.rs b/bitacross-worker/enclave-runtime/src/test/fixtures/initialize_test_state.rs new file mode 100644 index 0000000000..98e23261b6 --- /dev/null +++ b/bitacross-worker/enclave-runtime/src/test/fixtures/initialize_test_state.rs @@ -0,0 +1,42 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +use super::test_setup::TestStf; +use ita_stf::State; +use itp_sgx_externalities::{SgxExternalities, SgxExternalitiesTrait}; +use itp_stf_interface::InitState; +use itp_stf_primitives::types::AccountId; +use itp_stf_state_handler::handle_state::HandleState; +use itp_types::ShardIdentifier; + +/// Returns an empty `State` with the corresponding `ShardIdentifier`. +pub fn init_state>( + state_handler: &S, + enclave_account: AccountId, +) -> (State, ShardIdentifier) { + let shard = ShardIdentifier::default(); + + let _hash = state_handler.initialize_shard(shard).unwrap(); + let (lock, _) = state_handler.load_for_mutation(&shard).unwrap(); + let mut state = TestStf::init_state(enclave_account); + state.prune_state_diff(); + + state_handler.write_after_mutation(state.clone(), lock, &shard).unwrap(); + + (state, shard) +} diff --git a/bitacross-worker/enclave-runtime/src/test/fixtures/mod.rs b/bitacross-worker/enclave-runtime/src/test/fixtures/mod.rs new file mode 100644 index 0000000000..bc01106db1 --- /dev/null +++ b/bitacross-worker/enclave-runtime/src/test/fixtures/mod.rs @@ -0,0 +1,21 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 components; +pub mod initialize_test_state; +pub mod test_setup; diff --git a/bitacross-worker/enclave-runtime/src/test/fixtures/ra_dump_cert_TEST4.der b/bitacross-worker/enclave-runtime/src/test/fixtures/ra_dump_cert_TEST4.der new file mode 100644 index 0000000000..2e775236d6 Binary files /dev/null and b/bitacross-worker/enclave-runtime/src/test/fixtures/ra_dump_cert_TEST4.der differ diff --git a/bitacross-worker/enclave-runtime/src/test/fixtures/test_ra_signer_attn_MRSIGNER1_MRENCLAVE1.bin b/bitacross-worker/enclave-runtime/src/test/fixtures/test_ra_signer_attn_MRSIGNER1_MRENCLAVE1.bin new file mode 100644 index 0000000000..d7149d37d5 Binary files /dev/null and b/bitacross-worker/enclave-runtime/src/test/fixtures/test_ra_signer_attn_MRSIGNER1_MRENCLAVE1.bin differ diff --git a/bitacross-worker/enclave-runtime/src/test/fixtures/test_setup.rs b/bitacross-worker/enclave-runtime/src/test/fixtures/test_setup.rs new file mode 100644 index 0000000000..78c2bef328 --- /dev/null +++ b/bitacross-worker/enclave-runtime/src/test/fixtures/test_setup.rs @@ -0,0 +1,128 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{ + ocall::OcallApi, + test::{ + fixtures::initialize_test_state::init_state, mocks::rpc_responder_mock::RpcResponderMock, + }, +}; +use ita_sgx_runtime::Runtime; +use ita_stf::{Getter, State, Stf, TrustedCallSigned}; +use itp_node_api::metadata::{metadata_mocks::NodeMetadataMock, provider::NodeMetadataRepository}; +use itp_ocall_api::EnclaveAttestationOCallApi; +use itp_sgx_crypto::{ed25519_derivation::DeriveEd25519, mocks::KeyRepositoryMock}; +use itp_sgx_externalities::SgxExternalities; +use itp_stf_executor::executor::StfExecutor; +use itp_stf_primitives::types::{ShardIdentifier, TrustedOperation}; +use itp_test::mock::{ + handle_state_mock::HandleStateMock, metrics_ocall_mock::MetricsOCallMock, + shielding_crypto_mock::ShieldingCryptoMock, +}; +use itp_top_pool::{basic_pool::BasicPool, pool::ExtrinsicHash}; +use itp_top_pool_author::{ + api::SidechainApi, + author::Author, + top_filter::{AllowAllTopsFilter, DirectCallsOnlyFilter}, +}; +use itp_types::{Block, MrEnclave}; +use sp_core::{crypto::Pair, ed25519 as spEd25519}; +use std::sync::Arc; +pub type TestRpcResponder = RpcResponderMock>>; +pub type TestTopPool = BasicPool< + SidechainApi, + Block, + TestRpcResponder, + TrustedOperation, +>; +pub type TestShieldingKeyRepo = KeyRepositoryMock; +pub type TestTopPoolAuthor = Author< + TestTopPool, + AllowAllTopsFilter, + DirectCallsOnlyFilter, + HandleStateMock, + TestShieldingKeyRepo, + MetricsOCallMock, + TrustedCallSigned, + Getter, +>; +pub type TestStf = Stf; + +pub type TestStfExecutor = StfExecutor< + OcallApi, + HandleStateMock, + NodeMetadataRepository, + TestStf, + TrustedCallSigned, + Getter, +>; + +/// Returns all the things that are commonly used in tests and runs +/// `ensure_no_empty_shard_directory_exists` +pub fn test_setup() -> ( + Arc, + State, + ShardIdentifier, + MrEnclave, + ShieldingCryptoMock, + Arc, + Arc, +) { + let shielding_key = ShieldingCryptoMock::default(); + let shielding_key_repo = Arc::new(KeyRepositoryMock::new(shielding_key.clone())); + + let state_handler = Arc::new(HandleStateMock::default()); + let (state, shard) = + init_state(state_handler.as_ref(), enclave_call_signer(&shielding_key).public().into()); + let top_pool = test_top_pool(); + let mrenclave = OcallApi.get_mrenclave_of_self().unwrap().m; + + let node_metadata_repo = Arc::new(NodeMetadataRepository::new(NodeMetadataMock::new())); + let stf_executor = Arc::new(TestStfExecutor::new( + Arc::new(OcallApi), + state_handler.clone(), + node_metadata_repo, + )); + + let (sender, _receiver) = std::sync::mpsc::sync_channel(1000); + + ( + Arc::new(TestTopPoolAuthor::new( + Arc::new(top_pool), + AllowAllTopsFilter::::new(), + DirectCallsOnlyFilter::::new(), + state_handler.clone(), + shielding_key_repo, + Arc::new(MetricsOCallMock::default()), + Arc::new(sender), + )), + state, + shard, + mrenclave, + shielding_key, + state_handler, + stf_executor, + ) +} + +pub fn test_top_pool() -> TestTopPool { + let chain_api = Arc::new(SidechainApi::::new()); + BasicPool::create(Default::default(), chain_api, Arc::new(TestRpcResponder::new())) +} + +pub fn enclave_call_signer(key_source: &Source) -> spEd25519::Pair { + key_source.derive_ed25519().unwrap() +} diff --git a/bitacross-worker/enclave-runtime/src/test/ipfs_tests.rs b/bitacross-worker/enclave-runtime/src/test/ipfs_tests.rs new file mode 100644 index 0000000000..f1f94d3696 --- /dev/null +++ b/bitacross-worker/enclave-runtime/src/test/ipfs_tests.rs @@ -0,0 +1,42 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{ipfs::IpfsContent, ocall::OcallApi}; +use itp_ocall_api::EnclaveIpfsOCallApi; +use log::*; +use std::{fs::File, io::Read, vec::Vec}; + +#[allow(unused)] +fn test_ocall_read_write_ipfs() { + info!("testing IPFS read/write. Hopefully ipfs daemon is running..."); + let enc_state: Vec = vec![20; 4 * 512 * 1024]; + + let cid = OcallApi.write_ipfs(enc_state.as_slice()).unwrap(); + + OcallApi.read_ipfs(&cid).unwrap(); + + let cid_str = std::str::from_utf8(&cid.0).unwrap(); + let mut f = File::open(cid_str).unwrap(); + let mut content_buf = Vec::new(); + f.read_to_end(&mut content_buf).unwrap(); + info!("reading file {:?} of size {} bytes", f, &content_buf.len()); + + let mut ipfs_content = IpfsContent::new(cid_str, content_buf); + let verification = ipfs_content.verify(); + assert!(verification.is_ok()); +} diff --git a/bitacross-worker/enclave-runtime/src/test/mocks/attestation_ocall_mock.rs b/bitacross-worker/enclave-runtime/src/test/mocks/attestation_ocall_mock.rs new file mode 100644 index 0000000000..a480890761 --- /dev/null +++ b/bitacross-worker/enclave-runtime/src/test/mocks/attestation_ocall_mock.rs @@ -0,0 +1,101 @@ +/* + CCopyright 2021 Integritee AG and Supercomputing Systems AG + Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 itp_ocall_api::EnclaveAttestationOCallApi; +use sgx_types::*; +use std::{ + fmt::{Debug, Formatter, Result as FormatResult}, + vec::Vec, +}; + +#[derive(Clone)] +pub struct AttestationOCallMock { + mr_enclave: sgx_measurement_t, +} + +impl AttestationOCallMock { + pub fn new() -> Self { + Default::default() + } + + pub fn create_with_mr_enclave(mr_enclave: sgx_measurement_t) -> Self { + AttestationOCallMock { mr_enclave } + } +} + +impl EnclaveAttestationOCallApi for AttestationOCallMock { + fn sgx_init_quote(&self) -> SgxResult<(sgx_target_info_t, sgx_epid_group_id_t)> { + unreachable!() + } + + fn get_ias_socket(&self) -> SgxResult { + unreachable!() + } + + fn get_quote( + &self, + _sig_rl: Vec, + _report: sgx_report_t, + _sign_type: sgx_quote_sign_type_t, + _spid: sgx_spid_t, + _quote_nonce: sgx_quote_nonce_t, + ) -> SgxResult<(sgx_report_t, Vec)> { + unreachable!() + } + + fn get_dcap_quote(&self, _report: sgx_report_t, _quote_size: u32) -> SgxResult> { + unreachable!() + } + + fn get_qve_report_on_quote( + &self, + _quote: Vec, + _current_time: i64, + _quote_collateral: sgx_ql_qve_collateral_t, + _qve_report_info: sgx_ql_qe_report_info_t, + _supplemental_data_size: u32, + ) -> SgxResult<(u32, sgx_ql_qv_result_t, sgx_ql_qe_report_info_t, Vec)> { + unreachable!() + } + + fn get_update_info( + &self, + _platform_info: sgx_platform_info_t, + _enclave_trusted: i32, + ) -> SgxResult { + Ok(sgx_update_info_bit_t { csmeFwUpdate: 0, pswUpdate: 0, ucodeUpdate: 0 }) + } + + fn get_mrenclave_of_self(&self) -> SgxResult { + Ok(self.mr_enclave) + } +} + +impl Default for AttestationOCallMock { + fn default() -> Self { + AttestationOCallMock { mr_enclave: sgx_measurement_t { m: [1; SGX_HASH_SIZE] } } + } +} + +impl Debug for AttestationOCallMock { + fn fmt(&self, f: &mut Formatter<'_>) -> FormatResult { + f.debug_struct("AttestationOCallMock") + .field("mr_enclave", &self.mr_enclave.m) + .finish() + } +} diff --git a/bitacross-worker/enclave-runtime/src/test/mocks/enclave_rpc_ocall_mock.rs b/bitacross-worker/enclave-runtime/src/test/mocks/enclave_rpc_ocall_mock.rs new file mode 100644 index 0000000000..23003989e8 --- /dev/null +++ b/bitacross-worker/enclave-runtime/src/test/mocks/enclave_rpc_ocall_mock.rs @@ -0,0 +1,40 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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; +use itp_ocall_api::EnclaveRpcOCallApi; +use itp_types::TrustedOperationStatus; +use sgx_types::SgxResult; +use std::vec::Vec; + +#[derive(Clone, Debug, Default)] +pub struct EnclaveRpcOCallMock; + +impl EnclaveRpcOCallApi for EnclaveRpcOCallMock { + fn update_status_event( + &self, + _hash: H, + _status_update: TrustedOperationStatus, + ) -> SgxResult<()> { + Ok(()) + } + + fn send_state(&self, _hash: H, _value_opt: Option>) -> SgxResult<()> { + Ok(()) + } +} diff --git a/bitacross-worker/enclave-runtime/src/test/mocks/mod.rs b/bitacross-worker/enclave-runtime/src/test/mocks/mod.rs new file mode 100644 index 0000000000..26551844d6 --- /dev/null +++ b/bitacross-worker/enclave-runtime/src/test/mocks/mod.rs @@ -0,0 +1,24 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 attestation_ocall_mock; +pub mod enclave_rpc_ocall_mock; +pub mod peer_updater_mock; +pub mod propose_to_import_call_mock; +pub mod rpc_responder_mock; +pub mod types; diff --git a/bitacross-worker/enclave-runtime/src/test/mocks/peer_updater_mock.rs b/bitacross-worker/enclave-runtime/src/test/mocks/peer_updater_mock.rs new file mode 100644 index 0000000000..63a60108df --- /dev/null +++ b/bitacross-worker/enclave-runtime/src/test/mocks/peer_updater_mock.rs @@ -0,0 +1,24 @@ +// Copyright 2020-2023 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . + +use itc_peer_top_broadcaster::PeerUpdater; +use sgx_tstd::{string::String, vec::Vec}; + +pub struct PeerUpdaterMock {} + +impl PeerUpdater for PeerUpdaterMock { + fn update(&self, _peers: Vec) {} +} diff --git a/bitacross-worker/enclave-runtime/src/test/mocks/propose_to_import_call_mock.rs b/bitacross-worker/enclave-runtime/src/test/mocks/propose_to_import_call_mock.rs new file mode 100644 index 0000000000..fa47ae9539 --- /dev/null +++ b/bitacross-worker/enclave-runtime/src/test/mocks/propose_to_import_call_mock.rs @@ -0,0 +1,137 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::test::mocks::types::TestBlockImporter; +use codec::{Decode, Encode}; +use itc_parentchain::primitives::ParentchainId; +use itp_ocall_api::{ + EnclaveMetricsOCallApi, EnclaveOnChainOCallApi, EnclaveSidechainOCallApi, Result, +}; +use itp_types::{ + storage::StorageEntryVerified, BlockHash, Header as ParentchainHeader, ShardIdentifier, + WorkerRequest, WorkerResponse, H256, +}; +use its_primitives::types::block::SignedBlock as SignedSidechainBlockType; +use its_sidechain::consensus_common::BlockImport; +use sgx_types::SgxResult; +use sp_runtime::{traits::Header as ParentchainHeaderTrait, OpaqueExtrinsic}; +use std::{string::String, sync::Arc, vec::Vec}; + +/// OCallApi mock that routes the proposed sidechain blocks directly to the importer, +/// short circuiting all the RPC calls. +#[derive(Clone)] +pub struct ProposeToImportOCallApi { + parentchain_header: ParentchainHeader, + block_importer: Arc, +} + +impl ProposeToImportOCallApi { + pub fn new( + parentchain_header: ParentchainHeader, + block_importer: Arc, + ) -> Self { + ProposeToImportOCallApi { parentchain_header, block_importer } + } +} + +impl EnclaveOnChainOCallApi for ProposeToImportOCallApi { + fn send_to_parentchain( + &self, + _extrinsics: Vec, + _: &ParentchainId, + _: bool, + ) -> SgxResult<()> { + Ok(()) + } + + fn worker_request( + &self, + _req: Vec, + _: &ParentchainId, + ) -> SgxResult>> { + todo!() + } + + fn get_storage_verified, V: Decode>( + &self, + _storage_hash: Vec, + _header: &H, + _: &ParentchainId, + ) -> Result> { + todo!() + } + + fn get_multiple_storages_verified, V: Decode>( + &self, + _storage_hashes: Vec>, + _header: &H, + _: &ParentchainId, + ) -> Result>> { + todo!() + } + + fn get_storage_keys(&self, _key_prefix: Vec) -> Result>> { + todo!() + } +} + +impl EnclaveSidechainOCallApi for ProposeToImportOCallApi { + fn propose_sidechain_blocks( + &self, + signed_blocks: Vec, + ) -> SgxResult<()> { + let decoded_signed_blocks: Vec = signed_blocks + .iter() + .map(|sb| sb.encode()) + .map(|e| SignedSidechainBlockType::decode(&mut e.as_slice()).unwrap()) + .collect(); + + for signed_block in decoded_signed_blocks { + self.block_importer + .import_block(signed_block, &self.parentchain_header) + .unwrap(); + } + Ok(()) + } + + fn store_sidechain_blocks( + &self, + _signed_blocks: Vec, + ) -> SgxResult<()> { + Ok(()) + } + + fn fetch_sidechain_blocks_from_peer( + &self, + _last_imported_block_hash: BlockHash, + _maybe_until_block_hash: Option, + _shard_identifier: ShardIdentifier, + ) -> SgxResult> { + Ok(Vec::new()) + } + + fn get_trusted_peers_urls(&self) -> SgxResult> { + Ok(vec![]) + } +} + +impl EnclaveMetricsOCallApi for ProposeToImportOCallApi { + fn update_metric(&self, _metric: Metric) -> SgxResult<()> { + Ok(()) + } +} diff --git a/bitacross-worker/enclave-runtime/src/test/mocks/rpc_responder_mock.rs b/bitacross-worker/enclave-runtime/src/test/mocks/rpc_responder_mock.rs new file mode 100644 index 0000000000..d466e35a91 --- /dev/null +++ b/bitacross-worker/enclave-runtime/src/test/mocks/rpc_responder_mock.rs @@ -0,0 +1,75 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 itc_direct_rpc_server::{DirectRpcResult, RpcHash, SendRpcResponse}; +use itp_types::TrustedOperationStatus; +use std::{marker::PhantomData, vec::Vec}; + +pub struct RpcResponderMock { + _hash: PhantomData, +} + +impl RpcResponderMock { + pub fn new() -> Self { + RpcResponderMock { _hash: PhantomData } + } +} +impl Default for RpcResponderMock { + fn default() -> Self { + Self::new() + } +} + +impl SendRpcResponse for RpcResponderMock +where + Hash: RpcHash, +{ + type Hash = Hash; + + fn update_status_event( + &self, + _hash: Self::Hash, + _status_update: TrustedOperationStatus, + ) -> DirectRpcResult<()> { + Ok(()) + } + + fn send_state(&self, _hash: Self::Hash, _state_encoded: Vec) -> DirectRpcResult<()> { + Ok(()) + } + + fn update_force_wait(&self, _hash: Self::Hash, _force_wait: bool) -> DirectRpcResult<()> { + Ok(()) + } + + fn update_connection_state( + &self, + _hash: Self::Hash, + _encoded_value: Vec, + _force_wait: bool, + ) -> DirectRpcResult<()> { + Ok(()) + } + + fn swap_hash(&self, _old_hash: Self::Hash, _new_hash: Self::Hash) -> DirectRpcResult<()> { + Ok(()) + } + + fn is_force_wait(&self, _hash: Self::Hash) -> bool { + false + } +} diff --git a/bitacross-worker/enclave-runtime/src/test/mocks/types.rs b/bitacross-worker/enclave-runtime/src/test/mocks/types.rs new file mode 100644 index 0000000000..ae939c53e4 --- /dev/null +++ b/bitacross-worker/enclave-runtime/src/test/mocks/types.rs @@ -0,0 +1,114 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +//! Type definitions for testing. Includes various mocks. + +use crate::test::mocks::{ + peer_updater_mock::PeerUpdaterMock, rpc_responder_mock::RpcResponderMock, +}; +use ita_sgx_runtime::Runtime; +use ita_stf::{Getter, Stf, TrustedCallSigned}; +use itc_parentchain::block_import_dispatcher::trigger_parentchain_block_import_mock::TriggerParentchainBlockImportMock; +use itp_node_api::metadata::{metadata_mocks::NodeMetadataMock, provider::NodeMetadataRepository}; +use itp_sgx_crypto::{mocks::KeyRepositoryMock, Aes}; +use itp_sgx_externalities::SgxExternalities; +use itp_stf_executor::executor::StfExecutor; +use itp_stf_primitives::types::TrustedOperation; +use itp_test::mock::{ + handle_state_mock::HandleStateMock, metrics_ocall_mock::MetricsOCallMock, + onchain_mock::OnchainMock, +}; +use itp_top_pool::basic_pool::BasicPool; +use itp_top_pool_author::{ + api::SidechainApi, + author::Author, + top_filter::{AllowAllTopsFilter, DirectCallsOnlyFilter}, +}; +use itp_types::{Block as ParentchainBlock, SignedBlock as SignedParentchainBlock}; +use its_primitives::types::SignedBlock as SignedSidechainBlock; +use its_sidechain::{aura::block_importer::BlockImporter, block_composer::BlockComposer}; +use primitive_types::H256; +use sgx_crypto_helper::rsa3072::Rsa3072KeyPair; +use sp_core::ed25519 as spEd25519; + +pub type TestSigner = spEd25519::Pair; +pub type TestShieldingKey = Rsa3072KeyPair; +pub type TestStateKey = Aes; + +pub type TestGetter = Getter; +pub type TestCall = TrustedCallSigned; +pub type TestStf = Stf; + +pub type TestShieldingKeyRepo = KeyRepositoryMock; + +pub type TestStateKeyRepo = KeyRepositoryMock; + +pub type TestStateHandler = HandleStateMock; + +pub type TestOCallApi = OnchainMock; + +pub type TestParentchainBlockImportTrigger = + TriggerParentchainBlockImportMock; + +pub type TestNodeMetadataRepository = NodeMetadataRepository; + +pub type TestStfExecutor = StfExecutor< + TestOCallApi, + TestStateHandler, + TestNodeMetadataRepository, + TestStf, + TrustedCallSigned, + Getter, +>; + +pub type TestRpcResponder = RpcResponderMock; + +pub type TestTopPool = BasicPool< + SidechainApi, + ParentchainBlock, + TestRpcResponder, + TrustedOperation, +>; + +pub type TestTopPoolAuthor = Author< + TestTopPool, + AllowAllTopsFilter, + DirectCallsOnlyFilter, + TestStateHandler, + TestShieldingKeyRepo, + MetricsOCallMock, + TrustedCallSigned, + Getter, +>; + +pub type TestBlockComposer = + BlockComposer; + +pub type TestBlockImporter = BlockImporter< + TestSigner, + ParentchainBlock, + SignedSidechainBlock, + TestOCallApi, + HandleStateMock, + TestStateKeyRepo, + TestTopPoolAuthor, + TestParentchainBlockImportTrigger, + PeerUpdaterMock, + TrustedCallSigned, + Getter, +>; diff --git a/bitacross-worker/enclave-runtime/src/test/mod.rs b/bitacross-worker/enclave-runtime/src/test/mod.rs new file mode 100644 index 0000000000..6f3d7a252e --- /dev/null +++ b/bitacross-worker/enclave-runtime/src/test/mod.rs @@ -0,0 +1,34 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 cert_tests; +pub mod direct_rpc_tests; +pub mod enclave_signer_tests; +#[cfg(feature = "evm")] +pub mod evm_pallet_tests; +pub mod fixtures; +pub mod ipfs_tests; +pub mod mocks; +pub mod sidechain_aura_tests; +pub mod sidechain_event_tests; +mod state_getter_tests; +pub mod tests_main; +pub mod top_pool_tests; + +#[cfg(feature = "teeracle")] +pub mod teeracle_tests; diff --git a/bitacross-worker/enclave-runtime/src/test/sidechain_aura_tests.rs b/bitacross-worker/enclave-runtime/src/test/sidechain_aura_tests.rs new file mode 100644 index 0000000000..36ad0f69b9 --- /dev/null +++ b/bitacross-worker/enclave-runtime/src/test/sidechain_aura_tests.rs @@ -0,0 +1,287 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{ + test::{ + fixtures::{ + components::{ + create_ocall_api, create_top_pool, encrypt_trusted_operation, sign_trusted_call, + }, + initialize_test_state::init_state, + test_setup::{enclave_call_signer, TestStf}, + }, + mocks::{ + peer_updater_mock::PeerUpdaterMock, + propose_to_import_call_mock::ProposeToImportOCallApi, types::*, + }, + }, + top_pool_execution::{exec_aura_on_slot, send_blocks_and_extrinsics}, +}; +use codec::Decode; +use ita_stf::{ + test_genesis::{endowed_account, second_endowed_account, unendowed_account}, + Balance, Getter, TrustedCall, TrustedCallSigned, +}; +use itc_parentchain_test::ParentchainHeaderBuilder; +use itp_node_api::metadata::{metadata_mocks::NodeMetadataMock, provider::NodeMetadataRepository}; +use itp_ocall_api::EnclaveAttestationOCallApi; +use itp_settings::{ + sidechain::SLOT_DURATION, + worker_mode::{ProvideWorkerMode, WorkerMode, WorkerModeProvider}, +}; +use itp_sgx_crypto::{Aes, ShieldingCryptoEncrypt, StateCrypto}; +use itp_sgx_externalities::SgxExternalitiesDiffType; +use itp_stf_interface::system_pallet::{SystemPalletAccountInterface, SystemPalletEventInterface}; +use itp_stf_primitives::types::{StatePayload, TrustedOperation}; +use itp_stf_state_handler::handle_state::HandleState; +use itp_test::mock::{handle_state_mock::HandleStateMock, metrics_ocall_mock::MetricsOCallMock}; +use itp_time_utils::duration_now; +use itp_top_pool_author::{ + top_filter::{AllowAllTopsFilter, DirectCallsOnlyFilter}, + traits::AuthorApi, +}; +use itp_types::{AccountId, Block as ParentchainBlock, RsaRequest, ShardIdentifier}; +use its_block_verification::slot::slot_from_timestamp_and_duration; +use its_primitives::{traits::Block, types::SignedBlock as SignedSidechainBlock}; +use its_sidechain::{aura::proposer_factory::ProposerFactory, slots::SlotInfo}; +use jsonrpc_core::futures::executor; +use lc_scheduled_enclave::ScheduledEnclaveMock; +use litentry_primitives::Identity; +use log::*; +use primitive_types::H256; +use sgx_crypto_helper::RsaKeyPair; +use sp_core::{ed25519, Pair}; +use std::{sync::Arc, vec, vec::Vec}; + +/// Integration test for sidechain block production and block import. +/// (requires Sidechain mode) +/// +/// - Create trusted calls and add them to the TOP pool. +/// - Run AURA on a valid and claimed slot, which executes the trusted operations and produces a new block. +/// - Import the new sidechain block, which updates the state. +pub fn produce_sidechain_block_and_import_it() { + // Test can only be run in Sidechain mode + if WorkerModeProvider::worker_mode() != WorkerMode::Sidechain { + info!("Ignoring sidechain block production test: Not in sidechain mode"); + return + } + + let _ = env_logger::builder().is_test(true).try_init(); + info!("Setting up test."); + + let signer = TestSigner::from_seed(b"42315678901234567890123456789012"); + let shielding_key = TestShieldingKey::new().unwrap(); + let state_key = TestStateKey::new([3u8; 16], [1u8; 16]); + let shielding_key_repo = Arc::new(TestShieldingKeyRepo::new(shielding_key)); + let state_key_repo = Arc::new(TestStateKeyRepo::new(state_key)); + let parentchain_header = ParentchainHeaderBuilder::default().build(); + + let ocall_api = create_ocall_api(&parentchain_header, &signer); + + info!("Initializing state and shard.."); + let state_handler = Arc::new(TestStateHandler::default()); + let enclave_call_signer = enclave_call_signer(&shielding_key); + let (_, shard_id) = init_state(state_handler.as_ref(), enclave_call_signer.public().into()); + let shards = vec![shard_id]; + + let node_metadata_repo = Arc::new(NodeMetadataRepository::new(NodeMetadataMock::new())); + let stf_executor = Arc::new(TestStfExecutor::new( + ocall_api.clone(), + state_handler.clone(), + node_metadata_repo, + )); + let top_pool = create_top_pool(); + + let (sender, _receiver) = std::sync::mpsc::sync_channel(1000); + + let metrics_ocall_mock = Arc::new(MetricsOCallMock::default()); + + let top_pool_author = Arc::new(TestTopPoolAuthor::new( + top_pool, + AllowAllTopsFilter::::new(), + DirectCallsOnlyFilter::::new(), + state_handler.clone(), + shielding_key_repo, + metrics_ocall_mock.clone(), + Arc::new(sender), + )); + let parentchain_block_import_trigger = Arc::new(TestParentchainBlockImportTrigger::default()); + let peer_updater_mock = Arc::new(PeerUpdaterMock {}); + let block_importer = Arc::new(TestBlockImporter::new( + state_handler.clone(), + state_key_repo.clone(), + top_pool_author.clone(), + parentchain_block_import_trigger.clone(), + ocall_api.clone(), + peer_updater_mock, + )); + let block_composer = Arc::new(TestBlockComposer::new(signer, state_key_repo)); + let proposer_environment = ProposerFactory::new( + top_pool_author.clone(), + stf_executor, + block_composer, + metrics_ocall_mock, + ); + + info!("Create trusted operations.."); + let sender = endowed_account(); + let sender_with_low_balance = second_endowed_account(); + let receiver = unendowed_account(); + let transfered_amount: Balance = 1000; + let trusted_operation = encrypted_trusted_operation_transfer_balance( + ocall_api.as_ref(), + &shard_id, + &shielding_key, + sender, + receiver.public().into(), + transfered_amount, + ); + let invalid_trusted_operation = encrypted_trusted_operation_transfer_balance( + ocall_api.as_ref(), + &shard_id, + &shielding_key, + sender_with_low_balance, + receiver.public().into(), + ita_stf::test_genesis::SECOND_ENDOWED_ACC_FUNDS + 1, + ); + info!("Add trusted operations to TOP pool.."); + executor::block_on(top_pool_author.submit_top(RsaRequest::new(shard_id, trusted_operation))) + .unwrap(); + executor::block_on( + top_pool_author.submit_top(RsaRequest::new(shard_id, invalid_trusted_operation)), + ) + .unwrap(); + + // Ensure we have exactly two trusted calls in our TOP pool, and no getters. + assert_eq!(2, top_pool_author.get_pending_trusted_calls(shard_id).len()); + assert!(top_pool_author.get_pending_getters(shard_id).is_empty()); + + info!("Setup AURA SlotInfo"); + let timestamp = duration_now(); + let slot = slot_from_timestamp_and_duration(duration_now(), SLOT_DURATION); + let ends_at = timestamp + SLOT_DURATION; + let slot_info = SlotInfo::new( + slot, + timestamp, + SLOT_DURATION, + ends_at, + parentchain_header.clone(), + None, + None, + ); + + info!("Test setup is done."); + + let state_hash_before_block_production = get_state_hash(state_handler.as_ref(), &shard_id); + let scheduled_enclave = Arc::new(ScheduledEnclaveMock::default()); + + info!("Executing AURA on slot.."); + let (blocks, opaque_calls) = + exec_aura_on_slot::<_, ParentchainBlock, SignedSidechainBlock, _, _, _, _, _, _, _>( + slot_info, + signer, + ocall_api, + parentchain_block_import_trigger.clone(), + None::>, + None::>, + proposer_environment, + shards, + scheduled_enclave, + state_handler.clone(), + ) + .unwrap(); + + assert_eq!(1, blocks.len()); + assert_eq!( + state_hash_before_block_production, + get_state_hash(state_handler.as_ref(), &shard_id) + ); + + let (apriori_state_hash_in_block, aposteriori_state_hash_in_block) = + get_state_hashes_from_block(blocks.first().unwrap(), &state_key); + assert_ne!(state_hash_before_block_production, aposteriori_state_hash_in_block); + assert_eq!(state_hash_before_block_production, apriori_state_hash_in_block); + + // Ensure we have triggered the parentchain block import, because we claimed the slot. + assert!(parentchain_block_import_trigger.has_import_been_called()); + + // Ensure that invalid calls are removed from pool. Valid calls should only be removed upon block import. + assert_eq!(1, top_pool_author.get_pending_trusted_calls(shard_id).len()); + + info!("Executed AURA successfully. Sending blocks and extrinsics.."); + let propose_to_block_import_ocall_api = + Arc::new(ProposeToImportOCallApi::new(parentchain_header, block_importer)); + + send_blocks_and_extrinsics::( + blocks, + opaque_calls, + propose_to_block_import_ocall_api, + ) + .unwrap(); + + // After importing the sidechain block, the trusted operation should be removed. + assert!(top_pool_author.get_pending_trusted_calls(shard_id).is_empty()); + + // After importing the block, the state hash must be changed. + // We don't have a way to directly compare state hashes, because calculating the state hash + // would also involve applying set_last_block action, which updates the state upon import. + assert_ne!( + state_hash_before_block_production, + get_state_hash(state_handler.as_ref(), &shard_id) + ); + + let (mut state, _) = state_handler.load_cloned(&shard_id).unwrap(); + let free_balance = TestStf::get_account_data(&mut state, &receiver.public().into()).free; + assert_eq!(free_balance, transfered_amount); + assert!(TestStf::get_event_count(&mut state) > 0); + assert!(!TestStf::get_events(&mut state).is_empty()); +} + +fn encrypted_trusted_operation_transfer_balance< + AttestationApi: EnclaveAttestationOCallApi, + ShieldingKey: ShieldingCryptoEncrypt, +>( + attestation_api: &AttestationApi, + shard_id: &ShardIdentifier, + shielding_key: &ShieldingKey, + from: ed25519::Pair, + to: AccountId, + amount: Balance, +) -> Vec { + let call = TrustedCall::balance_transfer(Identity::Substrate(from.public().into()), to, amount); + let call_signed = sign_trusted_call(&call, attestation_api, shard_id, from); + let trusted_operation = TrustedOperation::::direct_call(call_signed); + encrypt_trusted_operation(shielding_key, &trusted_operation) +} + +fn get_state_hashes_from_block( + signed_block: &SignedSidechainBlock, + state_key: &Aes, +) -> (H256, H256) { + let mut encrypted_state_diff = signed_block.block.block_data().encrypted_state_diff.clone(); + state_key.decrypt(&mut encrypted_state_diff).unwrap(); + let decoded_state = + StatePayload::::decode(&mut encrypted_state_diff.as_slice()) + .unwrap(); + (decoded_state.state_hash_apriori(), decoded_state.state_hash_aposteriori()) +} + +fn get_state_hash(state_handler: &HandleStateMock, shard_id: &ShardIdentifier) -> H256 { + let (_, state_hash) = state_handler.load_cloned(shard_id).unwrap(); + state_hash +} diff --git a/bitacross-worker/enclave-runtime/src/test/sidechain_event_tests.rs b/bitacross-worker/enclave-runtime/src/test/sidechain_event_tests.rs new file mode 100644 index 0000000000..64294f0121 --- /dev/null +++ b/bitacross-worker/enclave-runtime/src/test/sidechain_event_tests.rs @@ -0,0 +1,190 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{ + test::{ + fixtures::{ + components::{create_ocall_api, create_top_pool}, + initialize_test_state::init_state, + test_setup::{enclave_call_signer, TestStf}, + }, + mocks::{ + peer_updater_mock::PeerUpdaterMock, + propose_to_import_call_mock::ProposeToImportOCallApi, types::*, + }, + }, + top_pool_execution::{exec_aura_on_slot, send_blocks_and_extrinsics}, +}; +use ita_sgx_runtime::Runtime; +use ita_stf::{helpers::set_block_number, Getter, TrustedCallSigned}; +use itc_parentchain_test::ParentchainHeaderBuilder; +use itp_node_api::metadata::{metadata_mocks::NodeMetadataMock, provider::NodeMetadataRepository}; +use itp_settings::{ + sidechain::SLOT_DURATION, + worker_mode::{ProvideWorkerMode, WorkerMode, WorkerModeProvider}, +}; +use itp_sgx_externalities::SgxExternalitiesTrait; +use itp_stf_interface::system_pallet::SystemPalletEventInterface; +use itp_stf_state_handler::handle_state::HandleState; +use itp_test::mock::metrics_ocall_mock::MetricsOCallMock; +use itp_time_utils::duration_now; +use itp_top_pool_author::top_filter::{AllowAllTopsFilter, DirectCallsOnlyFilter}; +use itp_types::Block as ParentchainBlock; +use its_block_verification::slot::slot_from_timestamp_and_duration; +use its_primitives::types::SignedBlock as SignedSidechainBlock; +use its_sidechain::{aura::proposer_factory::ProposerFactory, slots::SlotInfo}; +use lc_scheduled_enclave::ScheduledEnclaveMock; +use log::*; +use primitive_types::H256; +use sgx_crypto_helper::RsaKeyPair; +use sp_core::Pair; +use std::{sync::Arc, vec}; + +/// Integration test to ensure the events are reset upon block import. +/// Otherwise we will have an ever growing state. +/// (requires Sidechain mode) +pub fn ensure_events_get_reset_upon_block_proposal() { + // Test can only be run in Sidechain mode + if WorkerModeProvider::worker_mode() != WorkerMode::Sidechain { + info!("Ignoring sidechain block production test: Not in sidechain mode"); + return + } + + let _ = env_logger::builder().is_test(true).try_init(); + info!("Setting up test."); + + let signer = TestSigner::from_seed(b"42315678901234567890123456789012"); + let shielding_key = TestShieldingKey::new().unwrap(); + let state_key = TestStateKey::new([3u8; 16], [1u8; 16]); + let shielding_key_repo = Arc::new(TestShieldingKeyRepo::new(shielding_key)); + let state_key_repo = Arc::new(TestStateKeyRepo::new(state_key)); + let parentchain_header = ParentchainHeaderBuilder::default().build(); + + let ocall_api = create_ocall_api(&parentchain_header, &signer); + + info!("Initializing state and shard.."); + let state_handler = Arc::new(TestStateHandler::default()); + let enclave_call_signer = enclave_call_signer(&shielding_key); + let (_, shard_id) = init_state(state_handler.as_ref(), enclave_call_signer.public().into()); + let shards = vec![shard_id]; + + let node_metadata_repo = Arc::new(NodeMetadataRepository::new(NodeMetadataMock::new())); + let stf_executor = Arc::new(TestStfExecutor::new( + ocall_api.clone(), + state_handler.clone(), + node_metadata_repo, + )); + let top_pool = create_top_pool(); + let (sender, _receiver) = std::sync::mpsc::sync_channel(1000); + + let enclave_metrics_ocall_mock = Arc::new(MetricsOCallMock::default()); + + let top_pool_author = Arc::new(TestTopPoolAuthor::new( + top_pool, + AllowAllTopsFilter::::new(), + DirectCallsOnlyFilter::::new(), + state_handler.clone(), + shielding_key_repo, + enclave_metrics_ocall_mock.clone(), + Arc::new(sender), + )); + let parentchain_block_import_trigger = Arc::new(TestParentchainBlockImportTrigger::default()); + let peer_updater_mock = Arc::new(PeerUpdaterMock {}); + let block_importer = Arc::new(TestBlockImporter::new( + state_handler.clone(), + state_key_repo.clone(), + top_pool_author.clone(), + parentchain_block_import_trigger.clone(), + ocall_api.clone(), + peer_updater_mock, + )); + let block_composer = Arc::new(TestBlockComposer::new(signer, state_key_repo)); + let proposer_environment = ProposerFactory::new( + top_pool_author, + stf_executor, + block_composer, + enclave_metrics_ocall_mock, + ); + + // Add some events to the state. + let topic_hash = H256::from([7; 32]); + let event = frame_system::Event::::CodeUpdated; + let (lock, mut state) = state_handler.load_for_mutation(&shard_id).unwrap(); + state.execute_with(|| { + set_block_number(10); + frame_system::Pallet::::deposit_event_indexed( + &[topic_hash], + ita_sgx_runtime::RuntimeEvent::System(event), + ) + }); + state_handler.write_after_mutation(state.clone(), lock, &shard_id).unwrap(); + + // Check if state now really contains events and topics. + let (mut state, _) = state_handler.load_cloned(&shard_id).unwrap(); + assert_eq!(TestStf::get_event_count(&mut state), 1); + assert_eq!(TestStf::get_events(&mut state).len(), 1); + assert_eq!(TestStf::get_event_topics(&mut state, &topic_hash).len(), 1); + + info!("Setup AURA SlotInfo"); + let timestamp = duration_now(); + let slot = slot_from_timestamp_and_duration(duration_now(), SLOT_DURATION); + let ends_at = timestamp + SLOT_DURATION; + let slot_info = SlotInfo::new( + slot, + timestamp, + SLOT_DURATION, + ends_at, + parentchain_header.clone(), + None, + None, + ); + + let scheduled_enclave = Arc::new(ScheduledEnclaveMock::default()); + info!("Executing AURA on slot.."); + let (blocks, opaque_calls) = + exec_aura_on_slot::<_, ParentchainBlock, SignedSidechainBlock, _, _, _, _, _, _, _>( + slot_info, + signer, + ocall_api, + parentchain_block_import_trigger, + None::>, + None::>, + proposer_environment, + shards, + scheduled_enclave, + state_handler.clone(), + ) + .unwrap(); + + info!("Executed AURA successfully. Sending blocks and extrinsics.."); + let propose_to_block_import_ocall_api = + Arc::new(ProposeToImportOCallApi::new(parentchain_header, block_importer)); + + send_blocks_and_extrinsics::( + blocks, + opaque_calls, + propose_to_block_import_ocall_api, + ) + .unwrap(); + + // Ensure events have been reset. + let (mut state, _) = state_handler.load_cloned(&shard_id).unwrap(); + assert_eq!(TestStf::get_event_count(&mut state), 0); + assert_eq!(TestStf::get_event_topics(&mut state, &topic_hash).len(), 0); + assert_eq!(TestStf::get_events(&mut state).len(), 0); +} diff --git a/bitacross-worker/enclave-runtime/src/test/state_getter_tests.rs b/bitacross-worker/enclave-runtime/src/test/state_getter_tests.rs new file mode 100644 index 0000000000..f902061e9e --- /dev/null +++ b/bitacross-worker/enclave-runtime/src/test/state_getter_tests.rs @@ -0,0 +1,53 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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; +use ita_sgx_runtime::Runtime; +use ita_stf::{ + test_genesis::{endowed_account, test_genesis_setup, ENDOWED_ACC_FUNDS}, + Balance, Getter, Stf, TrustedCallSigned, TrustedGetter, +}; +use itp_sgx_externalities::SgxExternalities; +use itp_stf_executor::state_getter::{GetState, StfStateGetter}; +use litentry_primitives::Identity; +use sp_core::Pair; + +type TestState = SgxExternalities; +type TestStf = Stf; +type TestStfStateGetter = StfStateGetter; + +pub fn state_getter_works() { + let sender = endowed_account(); + let signed_getter = TrustedGetter::free_balance(Identity::Substrate(sender.public().into())) + .sign(&sender.into()); + let mut state = test_state(); + + let encoded_balance = TestStfStateGetter::get_state(signed_getter.into(), &mut state) + .unwrap() + .unwrap(); + + let balance = Balance::decode(&mut encoded_balance.as_slice()).unwrap(); + + assert_eq!(balance, ENDOWED_ACC_FUNDS); +} + +fn test_state() -> TestState { + let mut state = TestState::default(); + test_genesis_setup(&mut state); + state +} diff --git a/bitacross-worker/enclave-runtime/src/test/teeracle_tests.rs b/bitacross-worker/enclave-runtime/src/test/teeracle_tests.rs new file mode 100644 index 0000000000..bd9a4c8391 --- /dev/null +++ b/bitacross-worker/enclave-runtime/src/test/teeracle_tests.rs @@ -0,0 +1,50 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::alloc::string::ToString; +use ita_oracle::{ + create_coin_gecko_oracle, create_coin_market_cap_oracle, + oracles::exchange_rate_oracle::GetExchangeRate, types::TradingPair, +}; +use itp_test::mock::metrics_ocall_mock::MetricsOCallMock; +use std::sync::Arc; + +pub(super) fn test_verify_get_exchange_rate_from_coin_gecko_works() { + // Get the exchange rate + let trading_pair = + TradingPair { crypto_currency: "DOT".to_string(), fiat_currency: "USD".to_string() }; + + let coin_gecko_oracle = create_coin_gecko_oracle(Arc::new(MetricsOCallMock::default())); + + let result = coin_gecko_oracle.get_exchange_rate(trading_pair.clone()); + assert!(result.is_ok()); +} + +/// Get exchange rate from coin market cap. Requires API key (therefore not suited for unit testing). +#[allow(unused)] +pub(super) fn test_verify_get_exchange_rate_from_coin_market_cap_works() { + // Get the exchange rate + let trading_pair = + TradingPair { crypto_currency: "DOT".to_string(), fiat_currency: "USD".to_string() }; + + let coin_market_cap_oracle = + create_coin_market_cap_oracle(Arc::new(MetricsOCallMock::default())); + + let result = coin_market_cap_oracle.get_exchange_rate(trading_pair.clone()); + assert!(result.is_ok()); +} diff --git a/bitacross-worker/enclave-runtime/src/test/tests_main.rs b/bitacross-worker/enclave-runtime/src/test/tests_main.rs new file mode 100644 index 0000000000..8632bfbeea --- /dev/null +++ b/bitacross-worker/enclave-runtime/src/test/tests_main.rs @@ -0,0 +1,810 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 = "evm")] +use crate::test::evm_pallet_tests; + +use crate::{ + rpc, + sync::tests::{enclave_rw_lock_works, sidechain_rw_lock_works}, + test::{ + cert_tests::*, + direct_rpc_tests, enclave_signer_tests, + fixtures::test_setup::{ + enclave_call_signer, test_setup, TestStf, TestStfExecutor, TestTopPoolAuthor, + }, + mocks::types::TestStateKeyRepo, + sidechain_aura_tests, sidechain_event_tests, state_getter_tests, top_pool_tests, + }, + tls_ra, +}; +use codec::Decode; +use ita_sgx_runtime::Parentchain; +use ita_stf::{ + helpers::{account_key_hash, set_block_number}, + stf_sgx_tests, + test_genesis::{endowed_account as funded_pair, unendowed_account}, + AccountInfo, Getter, State, TrustedCall, TrustedCallSigned, TrustedGetter, +}; +use itp_node_api::metadata::{metadata_mocks::NodeMetadataMock, provider::NodeMetadataRepository}; +use itp_sgx_crypto::{Aes, StateCrypto}; +use itp_sgx_externalities::{SgxExternalitiesDiffType, SgxExternalitiesTrait, StateHash}; +use itp_stf_executor::{ + executor_tests as stf_executor_tests, traits::StateUpdateProposer, BatchExecutionResult, +}; +use itp_stf_interface::{ + parentchain_pallet::ParentchainPalletInterface, + system_pallet::{SystemPalletAccountInterface, SystemPalletEventInterface}, + StateCallInterface, +}; +use itp_stf_primitives::{ + traits::TrustedCallSigning, + types::{ShardIdentifier, StatePayload, TrustedOperation}, +}; +use itp_stf_state_handler::handle_state::HandleState; +use itp_test::mock::handle_state_mock; +use itp_top_pool_author::{test_utils::submit_operation_to_top_pool, traits::AuthorApi}; +use itp_types::{AccountId, Balance, Block, Header}; +use its_primitives::{ + traits::{ + Block as BlockTrait, BlockData, Header as SidechainHeaderTrait, + SignedBlock as SignedBlockTrait, + }, + types::block::SignedBlock, +}; +use its_sidechain::{ + block_composer::{BlockComposer, ComposeBlock}, + state::SidechainSystemExt, +}; +use litentry_primitives::Identity; +use sgx_tunittest::*; +use sgx_types::size_t; +use sp_core::{crypto::Pair, ed25519 as spEd25519, H256}; +use sp_runtime::traits::Header as HeaderT; +use std::{string::String, sync::Arc, time::Duration, vec::Vec}; +#[no_mangle] +pub extern "C" fn test_main_entrance() -> size_t { + rsgx_unit_tests!( + itp_attestation_handler::attestation_handler::tests::decode_spid_works, + stf_sgx_tests::enclave_account_initialization_works, + stf_sgx_tests::shield_funds_increments_signer_account_nonce, + stf_sgx_tests::test_root_account_exists_after_initialization, + itp_stf_state_handler::test::sgx_tests::test_write_and_load_state_works, + itp_stf_state_handler::test::sgx_tests::test_sgx_state_decode_encode_works, + itp_stf_state_handler::test::sgx_tests::test_encrypt_decrypt_state_type_works, + itp_stf_state_handler::test::sgx_tests::test_write_access_locks_read_until_finished, + itp_stf_state_handler::test::sgx_tests::test_ensure_subsequent_state_loads_have_same_hash, + itp_stf_state_handler::test::sgx_tests::test_state_handler_file_backend_is_initialized, + itp_stf_state_handler::test::sgx_tests::test_multiple_state_updates_create_snapshots_up_to_cache_size, + itp_stf_state_handler::test::sgx_tests::test_state_files_from_handler_can_be_loaded_again, + itp_stf_state_handler::test::sgx_tests::test_file_io_get_state_hash_works, + itp_stf_state_handler::test::sgx_tests::test_list_state_ids_ignores_files_not_matching_the_pattern, + itp_stf_state_handler::test::sgx_tests::test_in_memory_state_initializes_from_shard_directory, + itp_sgx_crypto::tests::aes_sealing_works, + itp_sgx_crypto::tests::using_get_aes_repository_twice_initializes_key_only_once, + itp_sgx_crypto::tests::ed25529_sealing_works, + itp_sgx_crypto::tests::using_get_ed25519_repository_twice_initializes_key_only_once, + itp_sgx_crypto::tests::rsa3072_sealing_works, + itp_sgx_crypto::tests::using_get_rsa3072_repository_twice_initializes_key_only_once, + test_compose_block, + test_submit_trusted_call_to_top_pool, + test_submit_trusted_getter_to_top_pool, + test_differentiate_getter_and_call_works, + test_create_block_and_confirmation_works, + test_create_state_diff, + test_executing_call_updates_account_nonce, + test_call_set_update_parentchain_block, + test_invalid_nonce_call_is_not_executed, + test_signature_must_match_public_sender_in_call, + test_non_root_shielding_call_is_not_executed, + test_shielding_call_with_enclave_self_is_executed, + test_retrieve_events, + test_retrieve_event_count, + test_reset_events, + rpc::worker_api_direct::tests::test_given_io_handler_methods_then_retrieve_all_names_as_string, + handle_state_mock::tests::initialized_shards_list_is_empty, + handle_state_mock::tests::shard_exists_after_inserting, + handle_state_mock::tests::from_shard_works, + handle_state_mock::tests::initialize_creates_default_state, + handle_state_mock::tests::load_mutate_and_write_works, + handle_state_mock::tests::ensure_subsequent_state_loads_have_same_hash, + handle_state_mock::tests::ensure_encode_and_encrypt_does_not_affect_state_hash, + handle_state_mock::tests::migrate_shard_works, + // mra cert tests + test_verify_mra_cert_should_work, + test_verify_wrong_cert_is_err, + test_given_wrong_platform_info_when_verifying_attestation_report_then_return_error, + // sync tests + sidechain_rw_lock_works, + enclave_rw_lock_works, + // unit tests of stf_executor + stf_executor_tests::propose_state_update_always_executes_preprocessing_step, + stf_executor_tests::propose_state_update_executes_no_trusted_calls_given_no_time, + stf_executor_tests::propose_state_update_executes_only_one_trusted_call_given_not_enough_time, + stf_executor_tests::propose_state_update_executes_all_calls_given_enough_time, + enclave_signer_tests::enclave_signer_signatures_are_valid, + enclave_signer_tests::derive_key_is_deterministic, + enclave_signer_tests::nonce_is_computed_correctly, + state_getter_tests::state_getter_works, + // sidechain integration tests + sidechain_aura_tests::produce_sidechain_block_and_import_it, + sidechain_event_tests::ensure_events_get_reset_upon_block_proposal, + top_pool_tests::process_indirect_call_in_top_pool, + top_pool_tests::submit_shielding_call_to_top_pool, + // tls_ra unit tests + tls_ra::seal_handler::test::seal_shielding_key_works, + tls_ra::seal_handler::test::seal_shielding_key_fails_for_invalid_key, + tls_ra::seal_handler::test::unseal_seal_shielding_key_works, + tls_ra::seal_handler::test::seal_state_key_works, + tls_ra::seal_handler::test::seal_state_key_fails_for_invalid_key, + tls_ra::seal_handler::test::unseal_seal_state_key_works, + tls_ra::seal_handler::test::seal_state_works, + tls_ra::seal_handler::test::seal_state_fails_for_invalid_state, + tls_ra::seal_handler::test::unseal_seal_state_works, + tls_ra::tests::test_state_and_key_provisioning, + tls_ra::tests::test_tls_ra_server_client_networking, + // RPC tests + direct_rpc_tests::get_state_request_works, + + // EVM tests + run_evm_tests, + + // light-client-test + itc_parentchain::light_client::io::sgx_tests::init_parachain_light_client_works, + itc_parentchain::light_client::io::sgx_tests::sealing_creates_backup, + + // these unit test (?) need an ipfs node running.. + // ipfs::test_creates_ipfs_content_struct_works, + // ipfs::test_verification_ok_for_correct_content, + // ipfs::test_verification_fails_for_incorrect_content, + // test_ocall_read_write_ipfs, + + // Teeracle tests + run_teeracle_tests, + ) +} + +#[cfg(feature = "teeracle")] +fn run_teeracle_tests() { + use super::teeracle_tests::*; + test_verify_get_exchange_rate_from_coin_gecko_works(); + // Disabled - requires API key, cannot run locally + //test_verify_get_exchange_rate_from_coin_market_cap_works(); +} + +#[cfg(not(feature = "teeracle"))] +fn run_teeracle_tests() {} + +#[cfg(feature = "evm")] +fn run_evm_tests() { + evm_pallet_tests::test_evm_call(); + evm_pallet_tests::test_evm_counter(); + evm_pallet_tests::test_evm_create(); + evm_pallet_tests::test_evm_create2(); +} +#[cfg(not(feature = "evm"))] +fn run_evm_tests() {} + +fn test_compose_block() { + // given + let (_, _, shard, _, _, state_handler, _) = test_setup(); + let block_composer = BlockComposer::::new( + test_account(), + Arc::new(TestStateKeyRepo::new(state_key())), + ); + + let signed_top_hashes: Vec = vec![[94; 32].into(), [1; 32].into()].to_vec(); + + let (mut state, _) = state_handler.load_cloned(&shard).unwrap(); + state.set_block_number(&1); + let state_hash_before_execution = state.hash(); + + // when + let signed_block = block_composer + .compose_block( + &latest_parentchain_header(), + signed_top_hashes, + shard, + state_hash_before_execution, + &state, + ) + .unwrap(); + + // then + assert!(signed_block.verify_signature()); + assert_eq!(signed_block.block().header().block_number(), 1); +} + +fn test_submit_trusted_call_to_top_pool() { + // given + let (top_pool_author, _, shard, mrenclave, shielding_key, ..) = test_setup(); + + let sender = funded_pair(); + + let signed_call = TrustedCall::balance_set_balance( + Identity::Substrate(sender.public().into()), + sender.public().into(), + 42, + 42, + ) + .sign(&sender.into(), 0, &mrenclave, &shard); + let trusted_operation = direct_top(signed_call); + + // when + submit_operation_to_top_pool( + top_pool_author.as_ref(), + &trusted_operation, + &shielding_key, + shard, + false, + ) + .unwrap(); + + let calls = top_pool_author.get_pending_trusted_calls(shard); + + // then + assert_eq!(calls[0], trusted_operation); +} + +// The TOP pool can hold any TrustedOperation, which at the moment also includes Getters. +// However, in reality we don't submit getters to the TOP pool anymore, they are executed immediately. +// The filter set in the TOP pool author prevents getters from being submitted. +// In this test however, we set the filter to `AllowAllTops`, so getters can be submitted. +// We want to keep this back door open, in case we would want to submit getter into the TOP pool again in the future. +fn test_submit_trusted_getter_to_top_pool() { + // given + let (top_pool_author, _, shard, _, shielding_key, ..) = test_setup(); + + let sender = funded_pair(); + + let signed_getter = TrustedGetter::free_balance(Identity::Substrate(sender.public().into())) + .sign(&sender.into()); + + // when + submit_operation_to_top_pool( + top_pool_author.as_ref(), + &TrustedOperation::::get(Getter::trusted(signed_getter.clone())), + &shielding_key, + shard, + false, + ) + .unwrap(); + + let getters = top_pool_author.get_pending_getters(shard); + + // then + assert_eq!( + getters[0], + TrustedOperation::::get(Getter::trusted(signed_getter)) + ); +} + +fn test_differentiate_getter_and_call_works() { + // given + let (top_pool_author, _, shard, mrenclave, shielding_key, ..) = test_setup(); + + // create accounts + let sender = funded_pair(); + + let signed_getter = TrustedGetter::free_balance(Identity::Substrate(sender.public().into())) + .sign(&sender.into()); + + let signed_call = TrustedCall::balance_set_balance( + Identity::Substrate(sender.public().into()), + sender.public().into(), + 42, + 42, + ) + .sign(&sender.into(), 0, &mrenclave, &shard); + let trusted_operation = direct_top(signed_call); + + // when + submit_operation_to_top_pool( + top_pool_author.as_ref(), + &TrustedOperation::::get(Getter::trusted(signed_getter.clone())), + &shielding_key, + shard, + false, + ) + .unwrap(); + submit_operation_to_top_pool( + top_pool_author.as_ref(), + &trusted_operation, + &shielding_key, + shard, + false, + ) + .unwrap(); + + let calls = top_pool_author.get_pending_trusted_calls(shard); + let getters = top_pool_author.get_pending_getters(shard); + + // then + assert_eq!(calls[0], trusted_operation); + assert_eq!( + getters[0], + TrustedOperation::::get(Getter::trusted(signed_getter)) + ); +} + +fn test_create_block_and_confirmation_works() { + // given + let (top_pool_author, _, shard, mrenclave, shielding_key, _, stf_executor) = test_setup(); + + let block_composer = BlockComposer::::new( + test_account(), + Arc::new(TestStateKeyRepo::new(state_key())), + ); + + let sender = funded_pair(); + let receiver = unfunded_public(); + + let signed_call = TrustedCall::balance_transfer( + Identity::Substrate(sender.public().into()), + receiver.into(), + 1000, + ) + .sign(&sender.into(), 0, &mrenclave, &shard); + let trusted_operation = direct_top(signed_call); + + let (top_hash, _) = submit_operation_to_top_pool( + top_pool_author.as_ref(), + &trusted_operation, + &shielding_key, + shard, + false, + ) + .unwrap(); + + // when + let execution_result = execute_trusted_calls(&shard, stf_executor.as_ref(), &top_pool_author); + + let executed_operation_hashes = execution_result.get_executed_operation_hashes().to_vec(); + + let signed_block = block_composer + .compose_block( + &latest_parentchain_header(), + executed_operation_hashes, + shard, + execution_result.state_hash_before_execution, + &execution_result.state_after_execution, + ) + .unwrap(); + + // then + assert!(signed_block.verify_signature()); + assert_eq!(signed_block.block().header().block_number(), 1); + assert_eq!(signed_block.block().block_data().signed_top_hashes()[0], top_hash); +} + +fn test_create_state_diff() { + // given + let (top_pool_author, _, shard, mrenclave, shielding_key, _, stf_executor) = test_setup(); + + let block_composer = BlockComposer::::new( + test_account(), + Arc::new(TestStateKeyRepo::new(state_key())), + ); + + let sender = funded_pair(); + let receiver = unfunded_public(); + const TX_AMOUNT: Balance = 1_000_000_000_000; + let signed_call = TrustedCall::balance_transfer( + Identity::Substrate(sender.public().into()), + receiver.into(), + TX_AMOUNT, + ) + .sign(&sender.into(), 0, &mrenclave, &shard); + let trusted_operation = direct_top(signed_call); + + submit_operation_to_top_pool( + top_pool_author.as_ref(), + &trusted_operation, + &shielding_key, + shard, + false, + ) + .unwrap(); + + // when + let execution_result = execute_trusted_calls(&shard, stf_executor.as_ref(), &top_pool_author); + + let executed_operation_hashes = execution_result.get_executed_operation_hashes().to_vec(); + + let signed_block = block_composer + .compose_block( + &latest_parentchain_header(), + executed_operation_hashes, + shard, + execution_result.state_hash_before_execution, + &execution_result.state_after_execution, + ) + .unwrap(); + + let encrypted_state_diff = encrypted_state_diff_from_encrypted( + signed_block.block().block_data().encrypted_state_diff(), + ); + let state_diff = encrypted_state_diff.state_update(); + + // then + let sender_acc_info: AccountInfo = + get_from_state_diff(state_diff, &account_key_hash::(&sender.public().into())); + + let receiver_acc_info: AccountInfo = + get_from_state_diff(state_diff, &account_key_hash::(&receiver.into())); + + // state diff should consist of the following updates: + // (last_hash, sidechain block_number, sender_funds, receiver_funds, fee_recipient account [no clear, after polkadot_v0.9.26 update], events, frame_system::LastRuntimeUpgradeInfo,) + assert_eq!(state_diff.len(), 8); + assert_eq!(receiver_acc_info.data.free, TX_AMOUNT); + assert_eq!( + sender_acc_info.data.free, + ita_stf::test_genesis::ENDOWED_ACC_FUNDS - TX_AMOUNT - ita_stf::STF_TX_FEE + ); +} + +fn test_executing_call_updates_account_nonce() { + // given + let (top_pool_author, _, shard, mrenclave, shielding_key, _, stf_executor) = test_setup(); + + let sender = funded_pair(); + let receiver = unfunded_public(); + + let trusted_operation = TrustedCall::balance_transfer( + Identity::Substrate(sender.public().into()), + receiver.into(), + 1000, + ) + .sign(&sender.into(), 0, &mrenclave, &shard) + .into_trusted_operation(false); + + submit_operation_to_top_pool( + top_pool_author.as_ref(), + &trusted_operation, + &shielding_key, + shard, + false, + ) + .unwrap(); + + // when + let mut execution_result = + execute_trusted_calls(&shard, stf_executor.as_ref(), &top_pool_author); + + let nonce = TestStf::get_account_nonce( + &mut execution_result.state_after_execution, + &sender.public().into(), + ); + assert_eq!(nonce, 1); +} + +fn test_call_set_update_parentchain_block() { + let (_, _, shard, _, _, state_handler, _) = test_setup(); + let (mut state, _) = state_handler.load_cloned(&shard).unwrap(); + + let block_number = 3; + let parent_hash = H256::from([1; 32]); + + let header: Header = HeaderT::new( + block_number, + Default::default(), + Default::default(), + parent_hash, + Default::default(), + ); + + TestStf::update_parentchain_block(&mut state, header.clone()).unwrap(); + + assert_eq!(header.hash(), state.execute_with(Parentchain::block_hash)); + assert_eq!(parent_hash, state.execute_with(Parentchain::parent_hash)); + assert_eq!(block_number, state.execute_with(Parentchain::block_number)); +} + +fn test_signature_must_match_public_sender_in_call() { + // given + let (top_pool_author, _, shard, mrenclave, shielding_key, _, stf_executor) = test_setup(); + + // create accounts + let sender = funded_pair(); + let receiver = unfunded_public(); + + let trusted_operation = TrustedCall::balance_transfer( + Identity::Substrate(receiver.into()), + sender.public().into(), + 1000, + ) + .sign(&sender.into(), 10, &mrenclave, &shard) + .into_trusted_operation(true); + + submit_operation_to_top_pool( + top_pool_author.as_ref(), + &trusted_operation, + &shielding_key, + shard, + false, + ) + .unwrap(); + + let executed_batch = execute_trusted_calls(&shard, stf_executor.as_ref(), &top_pool_author); + + // the top pool doesn't verify signatures, the call will only fail upon execution + assert!(!executed_batch.executed_operations[0].is_success()); +} + +fn test_invalid_nonce_call_is_not_executed() { + // given + let (top_pool_author, _, shard, mrenclave, shielding_key, _, stf_executor) = test_setup(); + + // create accounts + let sender = funded_pair(); + let receiver = unfunded_public(); + + let trusted_operation = TrustedCall::balance_transfer( + Identity::Substrate(sender.public().into()), + receiver.into(), + 1000, + ) + .sign(&sender.into(), 10, &mrenclave, &shard) + .into_trusted_operation(true); + + submit_operation_to_top_pool( + top_pool_author.as_ref(), + &trusted_operation, + &shielding_key, + shard, + false, + ) + .unwrap(); + + let executed_batch = execute_trusted_calls(&shard, stf_executor.as_ref(), &top_pool_author); + + // due to #1488, even invalid nonces will enter the pool ready state, so we can only verify that the call will fail + assert!(!executed_batch.executed_operations[0].is_success()); +} + +fn test_non_root_shielding_call_is_not_executed() { + // given + let (top_pool_author, _state, shard, mrenclave, shielding_key, _, stf_executor) = test_setup(); + + let sender = funded_pair(); + let sender_acc: AccountId = sender.public().into(); + + let signed_call = TrustedCall::balance_shield( + Identity::Substrate(sender_acc.clone().into()), + sender_acc, + 1000, + ) + .sign(&sender.into(), 0, &mrenclave, &shard); + + submit_operation_to_top_pool( + top_pool_author.as_ref(), + &direct_top(signed_call), + &shielding_key, + shard, + false, + ) + .unwrap(); + + // when + let executed_batch = execute_trusted_calls(&shard, stf_executor.as_ref(), &top_pool_author); + + // then + assert!(!executed_batch.executed_operations[0].is_success()); +} + +fn test_shielding_call_with_enclave_self_is_executed() { + let (top_pool_author, _state, shard, mrenclave, shielding_key, _, stf_executor) = test_setup(); + + let sender = funded_pair(); + let sender_account: AccountId = sender.public().into(); + let enclave_call_signer = enclave_call_signer(&shielding_key); + + let signed_call = TrustedCall::balance_shield( + Identity::Substrate(enclave_call_signer.public().into()), + sender_account, + 1000, + ) + .sign(&enclave_call_signer.into(), 0, &mrenclave, &shard); + let trusted_operation = + TrustedOperation::::indirect_call(signed_call); + + submit_operation_to_top_pool( + top_pool_author.as_ref(), + &trusted_operation, + &shielding_key, + shard, + false, + ) + .unwrap(); + + // when + let executed_batch = + execute_trusted_calls(&shard, stf_executor.as_ref(), top_pool_author.as_ref()); + + // then + assert_eq!(1, executed_batch.executed_operations.len()); + assert!(executed_batch.executed_operations[0].is_success()); +} + +pub fn test_retrieve_events() { + // given + let (_, mut state, shard, mrenclave, ..) = test_setup(); + let mut opaque_vec = Vec::new(); + let sender = funded_pair(); + let receiver = unendowed_account(); + let transfer_value: u128 = 1_000; + // Events will only get executed after genesis. + state.execute_with(|| set_block_number(100)); + + // Execute a transfer extrinsic to generate events via the Balance pallet. + let trusted_call = TrustedCall::balance_transfer( + Identity::Substrate(sender.public().into()), + receiver.public().into(), + transfer_value, + ) + .sign(&sender.into(), 0, &mrenclave, &shard); + let repo = Arc::new(NodeMetadataRepository::::default()); + let shard = ShardIdentifier::default(); + TestStf::execute_call( + &mut state, + &shard, + trusted_call, + Default::default(), + &mut opaque_vec, + repo, + ) + .unwrap(); + + assert_eq!(TestStf::get_events(&mut state).len(), 4); +} + +pub fn test_retrieve_event_count() { + let (_, mut state, shard, mrenclave, ..) = test_setup(); + let mut opaque_vec = Vec::new(); + let sender = funded_pair(); + let receiver = unendowed_account(); + let transfer_value: u128 = 1_000; + // Events will only get executed after genesis. + state.execute_with(|| set_block_number(100)); + + // Execute a transfer extrinsic to generate events via the Balance pallet. + let trusted_call = TrustedCall::balance_transfer( + Identity::Substrate(sender.public().into()), + receiver.public().into(), + transfer_value, + ) + .sign(&sender.into(), 0, &mrenclave, &shard); + + // when + let repo = Arc::new(NodeMetadataRepository::::default()); + let shard = ShardIdentifier::default(); + TestStf::execute_call( + &mut state, + &shard, + trusted_call, + Default::default(), + &mut opaque_vec, + repo, + ) + .unwrap(); + + let event_count = TestStf::get_event_count(&mut state); + assert_eq!(event_count, 4); +} + +pub fn test_reset_events() { + let (_, mut state, shard, mrenclave, ..) = test_setup(); + let mut opaque_vec = Vec::new(); + let sender = funded_pair(); + let receiver = unendowed_account(); + let transfer_value: u128 = 1_000; + // Events will only get executed after genesis. + state.execute_with(|| set_block_number(100)); + // Execute a transfer extrinsic to generate events via the Balance pallet. + let trusted_call = TrustedCall::balance_transfer( + Identity::Substrate(sender.public().into()), + receiver.public().into(), + transfer_value, + ) + .sign(&sender.into(), 0, &mrenclave, &shard); + let repo = Arc::new(NodeMetadataRepository::::default()); + let shard = ShardIdentifier::default(); + TestStf::execute_call( + &mut state, + &shard, + trusted_call, + Default::default(), + &mut opaque_vec, + repo, + ) + .unwrap(); + let receiver_acc_info = TestStf::get_account_data(&mut state, &receiver.public().into()); + assert_eq!(receiver_acc_info.free, transfer_value); + // Ensure that there really have been events generated. + assert_eq!(TestStf::get_events(&mut state).len(), 4); + + // Remove the events. + TestStf::reset_events(&mut state); + + // Ensure that the events storage has been cleared. + assert_eq!(TestStf::get_events(&mut state).len(), 0); +} + +fn execute_trusted_calls( + shard: &ShardIdentifier, + stf_executor: &TestStfExecutor, + top_pool_author: &TestTopPoolAuthor, +) -> BatchExecutionResult { + let top_pool_calls = top_pool_author.get_pending_trusted_calls(*shard); + stf_executor + .propose_state_update( + &top_pool_calls, + &latest_parentchain_header(), + shard, + Duration::from_millis(600), + |mut s| { + s.set_block_number(&s.get_block_number().map_or(1, |n| n + 1)); + s + }, + ) + .unwrap() +} + +// helper functions +/// Decrypt `encrypted` and decode it into `StatePayload` +pub fn encrypted_state_diff_from_encrypted( + encrypted: &[u8], +) -> StatePayload { + let mut encrypted_payload: Vec = encrypted.to_vec(); + let state_key = state_key(); + state_key.decrypt(&mut encrypted_payload).unwrap(); + StatePayload::decode(&mut encrypted_payload.as_slice()).unwrap() +} + +pub fn state_key() -> Aes { + Aes::default() +} + +/// Some random account that has no funds in the `Stf`'s `test_genesis` config. +pub fn unfunded_public() -> spEd25519::Public { + spEd25519::Public::from_raw(*b"asdfasdfadsfasdfasfasdadfadfasdf") +} + +pub fn test_account() -> spEd25519::Pair { + spEd25519::Pair::from_seed(b"42315678901234567890123456789012") +} + +/// transforms `call` into `TrustedOperation::direct(call)` +pub fn direct_top(call: TrustedCallSigned) -> TrustedOperation { + call.into_trusted_operation(true) +} + +/// Just some random onchain header +pub fn latest_parentchain_header() -> Header { + Header::new(1, Default::default(), Default::default(), [69; 32].into(), Default::default()) +} + +/// Reads the value at `key_hash` from `state_diff` and decodes it into `D` +pub fn get_from_state_diff(state_diff: &SgxExternalitiesDiffType, key_hash: &[u8]) -> D { + // fixme: what's up here with the wrapping?? + state_diff + .get(key_hash) + .unwrap() + .as_ref() + .map(|d| Decode::decode(&mut d.as_slice())) + .unwrap() + .unwrap() +} diff --git a/bitacross-worker/enclave-runtime/src/test/top_pool_tests.rs b/bitacross-worker/enclave-runtime/src/test/top_pool_tests.rs new file mode 100644 index 0000000000..22776fbd39 --- /dev/null +++ b/bitacross-worker/enclave-runtime/src/test/top_pool_tests.rs @@ -0,0 +1,236 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::test::{ + fixtures::{ + components::{ + create_ocall_api, create_top_pool, encrypt_trusted_operation, sign_trusted_call, + }, + initialize_test_state::init_state, + test_setup::TestStf, + }, + mocks::types::{ + TestShieldingKey, TestShieldingKeyRepo, TestSigner, TestStateHandler, TestTopPoolAuthor, + }, +}; +use codec::Encode; +use ita_parentchain_interface::integritee; +use ita_stf::{ + test_genesis::{endowed_account, unendowed_account}, + Getter, TrustedCall, TrustedCallSigned, +}; +use itc_parentchain::indirect_calls_executor::{ + mock::TestEventCreator, ExecuteIndirectCalls, IndirectCallsExecutor, +}; +use itc_parentchain_test::{ + parentchain_block_builder::ParentchainBlockBuilder, + parentchain_header_builder::ParentchainHeaderBuilder, +}; +use itp_node_api::{ + api_client::{ + ExtrinsicParams, ParentchainAdditionalParams, ParentchainExtrinsicParams, + ParentchainUncheckedExtrinsic, + }, + metadata::{metadata_mocks::NodeMetadataMock, provider::NodeMetadataRepository}, +}; +use itp_node_api_metadata::pallet_teerex::TeerexCallIndexes; +use itp_ocall_api::EnclaveAttestationOCallApi; +use itp_sgx_crypto::ShieldingCryptoEncrypt; +use itp_stf_executor::enclave_signer::StfEnclaveSigner; +use itp_stf_primitives::{traits::TrustedCallVerification, types::TrustedOperation}; +use itp_stf_state_observer::mock::ObserveStateMock; +use itp_test::mock::metrics_ocall_mock::MetricsOCallMock; +use itp_top_pool_author::{ + top_filter::{AllowAllTopsFilter, DirectCallsOnlyFilter}, + traits::AuthorApi, +}; +use itp_types::{ + parentchain::Address, AccountId, Block, RsaRequest, ShardIdentifier, ShieldFundsFn, H256, +}; +use jsonrpc_core::futures::executor; +use litentry_primitives::Identity; +use log::*; +use sgx_crypto_helper::RsaKeyPair; +use sp_core::{ed25519, Pair}; +use sp_runtime::{MultiSignature, OpaqueExtrinsic}; +use std::{sync::Arc, vec::Vec}; +pub fn process_indirect_call_in_top_pool() { + let _ = env_logger::builder().is_test(true).try_init(); + info!("Setting up test."); + + let signer = TestSigner::from_seed(b"42315678901234567890123456789012"); + let shielding_key = TestShieldingKey::new().unwrap(); + let shielding_key_repo = Arc::new(TestShieldingKeyRepo::new(shielding_key)); + let header = ParentchainHeaderBuilder::default().build(); + + let ocall_api = create_ocall_api(&header, &signer); + + let state_handler = Arc::new(TestStateHandler::default()); + let (_, shard_id) = init_state(state_handler.as_ref(), signer.public().into()); + + let top_pool = create_top_pool(); + let (sender, _receiver) = std::sync::mpsc::sync_channel(1000); + + let top_pool_author = Arc::new(TestTopPoolAuthor::new( + top_pool, + AllowAllTopsFilter::::new(), + DirectCallsOnlyFilter::::new(), + state_handler, + shielding_key_repo, + Arc::new(MetricsOCallMock::default()), + Arc::new(sender), + )); + + let encrypted_indirect_call = + encrypted_indirect_call(ocall_api.as_ref(), &shard_id, &shielding_key); + + executor::block_on( + top_pool_author.submit_top(RsaRequest::new(shard_id, encrypted_indirect_call)), + ) + .unwrap(); + + assert_eq!(1, top_pool_author.get_pending_trusted_calls(shard_id).len()); +} + +pub fn submit_shielding_call_to_top_pool() { + let _ = env_logger::builder().is_test(true).try_init(); + + let signer = TestSigner::from_seed(b"42315678901234567890123456789012"); + let shielding_key = TestShieldingKey::new().unwrap(); + let shielding_key_repo = Arc::new(TestShieldingKeyRepo::new(shielding_key)); + let header = ParentchainHeaderBuilder::default().build(); + + let ocall_api = create_ocall_api(&header, &signer); + let mr_enclave = ocall_api.get_mrenclave_of_self().unwrap(); + + let state_handler = Arc::new(TestStateHandler::default()); + let (state, shard_id) = init_state(state_handler.as_ref(), signer.public().into()); + let state_observer = Arc::new(ObserveStateMock::new(state)); + + let top_pool = create_top_pool(); + let (sender, _receiver) = std::sync::mpsc::sync_channel(1000); + + let top_pool_author = Arc::new(TestTopPoolAuthor::new( + top_pool, + AllowAllTopsFilter::::new(), + DirectCallsOnlyFilter::::new(), + state_handler, + shielding_key_repo.clone(), + Arc::new(MetricsOCallMock::default()), + Arc::new(sender), + )); + + let enclave_signer = + Arc::new(StfEnclaveSigner::<_, _, _, TestStf, _, TrustedCallSigned, Getter>::new( + state_observer, + ocall_api, + shielding_key_repo.clone(), + top_pool_author.clone(), + )); + let node_meta_data_repository = Arc::new(NodeMetadataRepository::default()); + node_meta_data_repository.set_metadata(NodeMetadataMock::new()); + let indirect_calls_executor = + IndirectCallsExecutor::< + _, + _, + _, + _, + integritee::ShieldFundsAndInvokeFilter, + TestEventCreator, + integritee::ParentchainEventHandler, + TrustedCallSigned, + Getter, + >::new( + shielding_key_repo, enclave_signer, top_pool_author.clone(), node_meta_data_repository + ); + + let block_with_shielding_call = create_shielding_call_extrinsic(shard_id, &shielding_key); + + let _ = indirect_calls_executor + .execute_indirect_calls_in_extrinsics(&block_with_shielding_call, &Vec::new()) + .unwrap(); + + assert_eq!(1, top_pool_author.get_pending_trusted_calls(shard_id).len()); + let trusted_operation = + top_pool_author.get_pending_trusted_calls(shard_id).first().cloned().unwrap(); + let trusted_call = trusted_operation.to_call().unwrap(); + assert!(trusted_call.verify_signature(&mr_enclave.m, &shard_id)); +} + +fn encrypted_indirect_call< + AttestationApi: EnclaveAttestationOCallApi, + ShieldingKey: ShieldingCryptoEncrypt, +>( + attestation_api: &AttestationApi, + shard_id: &ShardIdentifier, + shielding_key: &ShieldingKey, +) -> Vec { + let sender = endowed_account(); + let receiver = unendowed_account(); + + let call = TrustedCall::balance_transfer( + Identity::Substrate(sender.public().into()), + receiver.public().into(), + 10000u128, + ); + let call_signed = sign_trusted_call(&call, attestation_api, shard_id, sender); + let trusted_operation = + TrustedOperation::::indirect_call(call_signed); + encrypt_trusted_operation(shielding_key, &trusted_operation) +} + +fn create_shielding_call_extrinsic( + shard: ShardIdentifier, + shielding_key: &ShieldingKey, +) -> Block { + let target_account = shielding_key.encrypt(&AccountId::new([2u8; 32]).encode()).unwrap(); + let test_signer = ed25519::Pair::from_seed(b"33345678901234567890123456789012"); + let signature = test_signer.sign(&[0u8]); + + let default_extra_for_test = ParentchainExtrinsicParams::new( + 0, + 0, + 0, + H256::default(), + ParentchainAdditionalParams::default(), + ); + + let dummy_node_metadata = NodeMetadataMock::new(); + + let shield_funds_indexes = dummy_node_metadata.shield_funds_call_indexes().unwrap(); + let opaque_extrinsic = OpaqueExtrinsic::from_bytes( + ParentchainUncheckedExtrinsic::::new_signed( + ( + shield_funds_indexes, + target_account, + ita_stf::test_genesis::SECOND_ENDOWED_ACC_FUNDS, + shard, + ), + Address::Address32([1u8; 32]), + MultiSignature::Ed25519(signature), + default_extra_for_test.signed_extra(), + ) + .encode() + .as_slice(), + ) + .unwrap(); + + ParentchainBlockBuilder::default() + .with_extrinsics(vec![opaque_extrinsic]) + .build() +} diff --git a/bitacross-worker/enclave-runtime/src/tls_ra/README.md b/bitacross-worker/enclave-runtime/src/tls_ra/README.md new file mode 100644 index 0000000000..3f4effa148 --- /dev/null +++ b/bitacross-worker/enclave-runtime/src/tls_ra/README.md @@ -0,0 +1,33 @@ +# provisioning + +each worker runs a provisioning server for other workers of the same MRENCLAVE and shard to get recent stf state and secrets from. + +Light client storage can also be provisioned to avoid re-synching the entire parentchains with each worker + +enclave instances are short-lived on both sides, just for a single request. + +```mermaid +sequenceDiagram +participant untrusted_server +participant enclave_server +participant enclave_client +participant untrusted_client +enclave_server ->> enclave_server: generate shielding & state encryption key +enclave_server ->> enclave_server: init_shard & sync parentchains +untrusted_client ->> untrusted_server: connect TCP +untrusted_client ->> enclave_client: request_state_provisioning +activate enclave_client +untrusted_server ->> enclave_server: run_state_provisioning_server +activate enclave_server +enclave_server ->> enclave_server: load state and secrets +enclave_client ->> enclave_server: open TLS session (including MU RA) +enclave_client ->> enclave_server: request_state_provisioning(shard, account) +enclave_server ->> enclave_client: write_provisioning_payloads +enclave_server ->> enclave_server: add client as vault proxy for shard +enclave_client ->> enclave_client: seal state and secrets to disk +enclave_client -->> untrusted_client: _ +deactivate enclave_client +enclave_server -->> untrusted_server: _ +deactivate enclave_server +untrusted_client --> untrusted_server: disconnect TCP +``` diff --git a/bitacross-worker/enclave-runtime/src/tls_ra/authentication.rs b/bitacross-worker/enclave-runtime/src/tls_ra/authentication.rs new file mode 100644 index 0000000000..a3c14528de --- /dev/null +++ b/bitacross-worker/enclave-runtime/src/tls_ra/authentication.rs @@ -0,0 +1,158 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +//! Remote attestation certificate authentication of server and client +use itp_attestation_handler::cert; +use itp_ocall_api::EnclaveAttestationOCallApi; +use log::*; +use sgx_types::*; +use webpki::DNSName; + +pub struct ClientAuth { + outdated_ok: bool, + skip_ra: bool, + attestation_ocall: A, +} + +impl ClientAuth { + pub fn new(outdated_ok: bool, skip_ra: bool, attestation_ocall: A) -> Self { + ClientAuth { outdated_ok, skip_ra, attestation_ocall } + } +} + +impl rustls::ClientCertVerifier for ClientAuth +where + A: EnclaveAttestationOCallApi, +{ + fn client_auth_root_subjects( + &self, + _sni: Option<&DNSName>, + ) -> Option { + Some(rustls::DistinguishedNames::new()) + } + + fn verify_client_cert( + &self, + certs: &[rustls::Certificate], + _sni: Option<&DNSName>, + ) -> Result { + debug!("client cert: {:?}", certs); + let issuer = + certs.get(0).ok_or(rustls::TLSError::NoCertificatesPresented).and_then(|cert| { + cert::parse_cert_issuer(&cert.0) + .map_err(|_| rustls::TLSError::NoCertificatesPresented) + })?; + info!("client signer (issuer) is: 0x{}", hex::encode(issuer)); + + // This call will automatically verify cert is properly signed + if self.skip_ra { + warn!("Skip verifying ra-report"); + return Ok(rustls::ClientCertVerified::assertion()) + } + + if certs.is_empty() { + return Err(rustls::TLSError::NoCertificatesPresented) + } + + #[cfg(feature = "dcap")] + let is_dcap = true; + #[cfg(not(feature = "dcap"))] + let is_dcap = false; + match certs.first() { + Some(cert) => { + match cert::verify_mra_cert(&cert.0, true, is_dcap, &self.attestation_ocall) { + Ok(()) => Ok(rustls::ClientCertVerified::assertion()), + Err(sgx_status_t::SGX_ERROR_UPDATE_NEEDED) => + if self.outdated_ok { + warn!("outdated_ok is set, overriding outdated error"); + Ok(rustls::ClientCertVerified::assertion()) + } else { + Err(rustls::TLSError::WebPKIError(webpki::Error::ExtensionValueInvalid)) + }, + Err(_) => + Err(rustls::TLSError::WebPKIError(webpki::Error::ExtensionValueInvalid)), + } + }, + None => Err(rustls::TLSError::WebPKIError(webpki::Error::ExtensionValueInvalid)), + } + } +} + +pub struct ServerAuth { + outdated_ok: bool, + skip_ra: bool, + attestation_ocall: A, +} + +impl ServerAuth { + pub fn new(outdated_ok: bool, skip_ra: bool, attestation_ocall: A) -> Self { + ServerAuth { outdated_ok, skip_ra, attestation_ocall } + } +} + +impl rustls::ServerCertVerifier for ServerAuth +where + A: EnclaveAttestationOCallApi, +{ + fn verify_server_cert( + &self, + _roots: &rustls::RootCertStore, + certs: &[rustls::Certificate], + _hostname: webpki::DNSNameRef, + _ocsp: &[u8], + ) -> Result { + debug!("server cert: {:?}", certs); + let issuer = + certs.get(0).ok_or(rustls::TLSError::NoCertificatesPresented).and_then(|cert| { + cert::parse_cert_issuer(&cert.0) + .map_err(|_| rustls::TLSError::NoCertificatesPresented) + })?; + info!("server signer (issuer) is: 0x{}", hex::encode(issuer)); + + if self.skip_ra { + warn!("Skip verifying ra-report"); + return Ok(rustls::ServerCertVerified::assertion()) + } + + if certs.is_empty() { + return Err(rustls::TLSError::NoCertificatesPresented) + } + + #[cfg(feature = "dcap")] + let is_dcap = true; + #[cfg(not(feature = "dcap"))] + let is_dcap = false; + // This call will automatically verify cert is properly signed + match certs.first() { + Some(cert) => { + match cert::verify_mra_cert(&cert.0, true, is_dcap, &self.attestation_ocall) { + Ok(()) => Ok(rustls::ServerCertVerified::assertion()), + Err(sgx_status_t::SGX_ERROR_UPDATE_NEEDED) => + if self.outdated_ok { + warn!("outdated_ok is set, overriding outdated error"); + Ok(rustls::ServerCertVerified::assertion()) + } else { + Err(rustls::TLSError::WebPKIError(webpki::Error::ExtensionValueInvalid)) + }, + Err(_) => + Err(rustls::TLSError::WebPKIError(webpki::Error::ExtensionValueInvalid)), + } + }, + None => Err(rustls::TLSError::WebPKIError(webpki::Error::ExtensionValueInvalid)), + } + } +} diff --git a/bitacross-worker/enclave-runtime/src/tls_ra/mocks.rs b/bitacross-worker/enclave-runtime/src/tls_ra/mocks.rs new file mode 100644 index 0000000000..e7f6900a0f --- /dev/null +++ b/bitacross-worker/enclave-runtime/src/tls_ra/mocks.rs @@ -0,0 +1,87 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +use super::seal_handler::{SealStateAndKeys, UnsealStateAndKeys}; +use crate::error::Result as EnclaveResult; +use itp_types::ShardIdentifier; +use std::{ + sync::{Arc, SgxRwLock as RwLock}, + vec::Vec, +}; + +#[derive(Clone)] +pub struct SealHandlerMock { + pub shielding_key: Arc>>, + pub state_key: Arc>>, + pub state: Arc>>, + pub light_client_state: Arc>>, +} + +impl SealHandlerMock { + pub fn new( + shielding_key: Arc>>, + state_key: Arc>>, + state: Arc>>, + light_client_state: Arc>>, + ) -> Self { + Self { shielding_key, state_key, state, light_client_state } + } +} + +impl SealStateAndKeys for SealHandlerMock { + fn seal_shielding_key(&self, bytes: &[u8]) -> EnclaveResult<()> { + *self.shielding_key.write().unwrap() = bytes.to_vec(); + Ok(()) + } + + fn seal_state_key(&self, bytes: &[u8]) -> EnclaveResult<()> { + *self.state_key.write().unwrap() = bytes.to_vec(); + Ok(()) + } + + fn seal_state(&self, bytes: &[u8], _shard: &ShardIdentifier) -> EnclaveResult<()> { + *self.state.write().unwrap() = bytes.to_vec(); + Ok(()) + } + + fn seal_new_empty_state(&self, _shard: &ShardIdentifier) -> EnclaveResult<()> { + Ok(()) + } + + fn seal_light_client_state(&self, bytes: &[u8]) -> EnclaveResult<()> { + *self.light_client_state.write().unwrap() = bytes.to_vec(); + Ok(()) + } +} + +impl UnsealStateAndKeys for SealHandlerMock { + fn unseal_shielding_key(&self) -> EnclaveResult> { + Ok(self.shielding_key.read().unwrap().clone()) + } + + fn unseal_state_key(&self) -> EnclaveResult> { + Ok(self.state_key.read().unwrap().clone()) + } + + fn unseal_state(&self, _shard: &ShardIdentifier) -> EnclaveResult> { + Ok(self.state.read().unwrap().clone()) + } + + fn unseal_light_client_state(&self) -> EnclaveResult> { + Ok(self.light_client_state.read().unwrap().clone()) + } +} diff --git a/bitacross-worker/enclave-runtime/src/tls_ra/mod.rs b/bitacross-worker/enclave-runtime/src/tls_ra/mod.rs new file mode 100644 index 0000000000..07474f3f8b --- /dev/null +++ b/bitacross-worker/enclave-runtime/src/tls_ra/mod.rs @@ -0,0 +1,81 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 all logic of the state provisioning mechanism +//! including the remote attestation and tls / tcp connection part. + +use codec::{Decode, Encode, MaxEncodedLen}; +use itp_types::{AccountId, ShardIdentifier}; + +mod authentication; +pub mod seal_handler; +mod tls_ra_client; +mod tls_ra_server; + +#[cfg(feature = "test")] +pub mod tests; + +#[cfg(feature = "test")] +pub mod mocks; + +/// Header of an accompanied payload. Indicates the +/// length an the type (opcode) of the following payload. +#[derive(Clone, Debug, Decode, Encode, MaxEncodedLen)] +pub struct TcpHeader { + pub opcode: Opcode, + pub payload_length: u64, +} + +impl TcpHeader { + fn new(opcode: Opcode, payload_length: u64) -> Self { + Self { opcode, payload_length } + } +} + +/// Indicates the payload content type. +#[derive(Copy, Clone, Debug, Eq, PartialEq, Decode, Encode, MaxEncodedLen)] +pub enum Opcode { + ShieldingKey, + StateKey, + State, + LightClient, +} + +impl From for Opcode { + fn from(item: u8) -> Self { + match item { + 0 => Opcode::ShieldingKey, + 1 => Opcode::StateKey, + 2 => Opcode::State, + 3 => Opcode::LightClient, + _ => unimplemented!("Unsupported/unknown Opcode for MU-RA exchange"), + } + } +} + +impl Opcode { + pub fn to_bytes(self) -> [u8; 1] { + (self as u8).to_be_bytes() + } +} + +/// The data structure to be sent by the client to request provisioning +#[derive(Clone, Debug, Eq, PartialEq, Decode, Encode, MaxEncodedLen)] +pub struct ClientProvisioningRequest { + pub shard: ShardIdentifier, + pub account: AccountId, +} diff --git a/bitacross-worker/enclave-runtime/src/tls_ra/seal_handler.rs b/bitacross-worker/enclave-runtime/src/tls_ra/seal_handler.rs new file mode 100644 index 0000000000..bb7828dd57 --- /dev/null +++ b/bitacross-worker/enclave-runtime/src/tls_ra/seal_handler.rs @@ -0,0 +1,268 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +//! Abstraction of the reading (unseal) and storing (seal) part of the +//! shielding key, state key and state. + +use crate::error::{Error as EnclaveError, Result as EnclaveResult}; +use codec::{Decode, Encode}; +use ita_stf::{State as StfState, StateType as StfStateType}; +use itc_parentchain::light_client::LightClientSealing; +use itp_sgx_crypto::{ + key_repository::{AccessKey, MutateKey}, + Aes, +}; +use itp_sgx_externalities::SgxExternalitiesTrait; +use itp_stf_state_handler::handle_state::HandleState; +use itp_types::ShardIdentifier; +use log::*; +use sgx_crypto_helper::rsa3072::Rsa3072KeyPair; +use std::{sync::Arc, vec::Vec}; + +/// Handles the sealing and unsealing of the shielding key, state key and the state. +#[derive(Default)] +pub struct SealHandler { + state_handler: Arc, + state_key_repository: Arc, + shielding_key_repository: Arc, + light_client_seal: Arc, +} + +impl + SealHandler +{ + pub fn new( + state_handler: Arc, + state_key_repository: Arc, + shielding_key_repository: Arc, + light_client_seal: Arc, + ) -> Self { + Self { state_handler, state_key_repository, shielding_key_repository, light_client_seal } + } +} + +pub trait SealStateAndKeys { + fn seal_shielding_key(&self, bytes: &[u8]) -> EnclaveResult<()>; + fn seal_state_key(&self, bytes: &[u8]) -> EnclaveResult<()>; + fn seal_state(&self, bytes: &[u8], shard: &ShardIdentifier) -> EnclaveResult<()>; + fn seal_new_empty_state(&self, shard: &ShardIdentifier) -> EnclaveResult<()>; + fn seal_light_client_state(&self, bytes: &[u8]) -> EnclaveResult<()>; +} + +pub trait UnsealStateAndKeys { + fn unseal_shielding_key(&self) -> EnclaveResult>; + fn unseal_state_key(&self) -> EnclaveResult>; + fn unseal_state(&self, shard: &ShardIdentifier) -> EnclaveResult>; + fn unseal_light_client_state(&self) -> EnclaveResult>; +} + +impl SealStateAndKeys + for SealHandler +where + ShieldingKeyRepository: AccessKey + MutateKey, + StateKeyRepository: AccessKey + MutateKey, + StateHandler: HandleState, + LightClientSeal: LightClientSealing, + LightClientSeal::LightClientState: Decode, +{ + fn seal_shielding_key(&self, bytes: &[u8]) -> EnclaveResult<()> { + let key: Rsa3072KeyPair = serde_json::from_slice(bytes).map_err(|e| { + error!(" [Enclave] Received Invalid RSA key"); + EnclaveError::Other(e.into()) + })?; + self.shielding_key_repository.update_key(key)?; + info!("Successfully stored a new shielding key"); + Ok(()) + } + + fn seal_state_key(&self, mut bytes: &[u8]) -> EnclaveResult<()> { + let aes = Aes::decode(&mut bytes)?; + self.state_key_repository.update_key(aes)?; + info!("Successfully stored a new state key"); + Ok(()) + } + + fn seal_state(&self, mut bytes: &[u8], shard: &ShardIdentifier) -> EnclaveResult<()> { + let state = StfStateType::decode(&mut bytes)?; + let state_with_empty_diff = StfState::new(state); + + self.state_handler.reset(state_with_empty_diff, shard)?; + info!("Successfully updated shard {:?} with provisioned state", shard); + Ok(()) + } + + fn seal_light_client_state(&self, mut bytes: &[u8]) -> EnclaveResult<()> { + let state = ::LightClientState::decode(&mut bytes)?; + self.light_client_seal.seal(&state)?; + info!("Successfully sealed light client state"); + Ok(()) + } + + /// Seal an empty, newly initialized state. + /// + /// Requires the shielding key to be sealed and updated before calling this. + /// + /// Call this function in case we don't provision the state itself, only the shielding key. + /// Since the enclave signing account is derived from the shielding key, we need to + /// newly initialize the state with the updated shielding key. + fn seal_new_empty_state(&self, shard: &ShardIdentifier) -> EnclaveResult<()> { + self.state_handler.initialize_shard(*shard)?; + info!("Successfully reset state with new enclave account, for shard {:?}", shard); + Ok(()) + } +} + +impl UnsealStateAndKeys + for SealHandler +where + ShieldingKeyRepository: AccessKey + MutateKey, + StateKeyRepository: AccessKey + MutateKey, + StateHandler: HandleState, + LightClientSeal: LightClientSealing, + LightClientSeal::LightClientState: Encode, +{ + fn unseal_shielding_key(&self) -> EnclaveResult> { + let shielding_key = self + .shielding_key_repository + .retrieve_key() + .map_err(|e| EnclaveError::Other(format!("{:?}", e).into()))?; + serde_json::to_vec(&shielding_key).map_err(|e| EnclaveError::Other(e.into())) + } + + fn unseal_state_key(&self) -> EnclaveResult> { + self.state_key_repository + .retrieve_key() + .map(|k| k.encode()) + .map_err(|e| EnclaveError::Other(format!("{:?}", e).into())) + } + + fn unseal_state(&self, shard: &ShardIdentifier) -> EnclaveResult> { + Ok(self.state_handler.execute_on_current(shard, |state, _| state.state.encode())?) + } + + fn unseal_light_client_state(&self) -> EnclaveResult> { + Ok(self.light_client_seal.unseal()?.encode()) + } +} + +#[cfg(feature = "test")] +pub mod test { + use super::*; + use itc_parentchain::light_client::mocks::validator_mock_seal::LightValidationStateSealMock; + use itp_sgx_crypto::mocks::KeyRepositoryMock; + use itp_test::mock::handle_state_mock::HandleStateMock; + + type StateKeyRepositoryMock = KeyRepositoryMock; + type ShieldingKeyRepositoryMock = KeyRepositoryMock; + + type SealHandlerMock = SealHandler< + ShieldingKeyRepositoryMock, + StateKeyRepositoryMock, + HandleStateMock, + LightValidationStateSealMock, + >; + + pub fn seal_shielding_key_works() { + let seal_handler = SealHandlerMock::default(); + let key_pair_in_bytes = serde_json::to_vec(&Rsa3072KeyPair::default()).unwrap(); + + let result = seal_handler.seal_shielding_key(&key_pair_in_bytes); + + assert!(result.is_ok()); + } + + pub fn seal_shielding_key_fails_for_invalid_key() { + let seal_handler = SealHandlerMock::default(); + + let result = seal_handler.seal_shielding_key(&[1, 2, 3]); + + assert!(result.is_err()); + } + + pub fn unseal_seal_shielding_key_works() { + let seal_handler = SealHandlerMock::default(); + + let key_pair_in_bytes = seal_handler.unseal_shielding_key().unwrap(); + + let result = seal_handler.seal_shielding_key(&key_pair_in_bytes); + + assert!(result.is_ok()); + } + + pub fn seal_state_key_works() { + let seal_handler = SealHandlerMock::default(); + let key_pair_in_bytes = Aes::default().encode(); + + let result = seal_handler.seal_state_key(&key_pair_in_bytes); + + assert!(result.is_ok()); + } + + pub fn seal_state_key_fails_for_invalid_key() { + let seal_handler = SealHandlerMock::default(); + + let result = seal_handler.seal_state_key(&[1, 2, 3]); + + assert!(result.is_err()); + } + + pub fn unseal_seal_state_key_works() { + let seal_handler = SealHandlerMock::default(); + let key_pair_in_bytes = seal_handler.unseal_state_key().unwrap(); + + let result = seal_handler.seal_state_key(&key_pair_in_bytes); + + assert!(result.is_ok()); + } + + pub fn seal_state_works() { + let seal_handler = SealHandlerMock::default(); + let state = ::StateT::default(); + let shard = ShardIdentifier::default(); + let _init_hash = seal_handler.state_handler.initialize_shard(shard).unwrap(); + + let result = seal_handler.seal_state(&state.encode(), &shard); + + assert!(result.is_ok()); + } + + pub fn seal_state_fails_for_invalid_state() { + let seal_handler = SealHandlerMock::default(); + let shard = ShardIdentifier::default(); + + let result = seal_handler.seal_state(&[1, 0, 3], &shard); + + assert!(result.is_err()); + } + + pub fn unseal_seal_state_works() { + let seal_handler = SealHandlerMock::default(); + let shard = ShardIdentifier::default(); + seal_handler.state_handler.initialize_shard(shard).unwrap(); + // Fill our mock state: + let (lock, mut state) = seal_handler.state_handler.load_for_mutation(&shard).unwrap(); + let (key, value) = ("my_key", "my_value"); + state.insert(key.encode(), value.encode()); + seal_handler.state_handler.write_after_mutation(state, lock, &shard).unwrap(); + + let state_in_bytes = seal_handler.unseal_state(&shard).unwrap(); + + let result = seal_handler.seal_state(&state_in_bytes, &shard); + + assert!(result.is_ok()); + } +} diff --git a/bitacross-worker/enclave-runtime/src/tls_ra/tests.rs b/bitacross-worker/enclave-runtime/src/tls_ra/tests.rs new file mode 100644 index 0000000000..5cdbd2a184 --- /dev/null +++ b/bitacross-worker/enclave-runtime/src/tls_ra/tests.rs @@ -0,0 +1,196 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 of tls-ra client / server communication. + +use super::{ + mocks::SealHandlerMock, tls_ra_client::request_state_provisioning_internal, + tls_ra_server::run_state_provisioning_server_internal, +}; +use crate::{ + initialization::global_components::EnclaveStf, + tls_ra::seal_handler::{SealHandler, SealStateAndKeys, UnsealStateAndKeys}, +}; +use ita_stf::State; +use itc_parentchain::light_client::mocks::validator_mock_seal::LightValidationStateSealMock; +use itp_settings::worker_mode::{ProvideWorkerMode, WorkerMode, WorkerModeProvider}; +use itp_sgx_crypto::{mocks::KeyRepositoryMock, Aes}; +use itp_stf_interface::InitState; +use itp_stf_primitives::types::AccountId; +use itp_stf_state_handler::handle_state::HandleState; +use itp_test::mock::handle_state_mock::HandleStateMock; +use itp_types::ShardIdentifier; +use sgx_crypto_helper::{rsa3072::Rsa3072KeyPair, RsaKeyPair}; +use sgx_types::{sgx_quote_sign_type_t, sgx_target_info_t}; +use std::{ + net::{TcpListener, TcpStream}, + os::unix::io::AsRawFd, + string::String, + sync::{Arc, SgxRwLock as RwLock}, + thread, + time::Duration, + vec::Vec, +}; + +static SIGN_TYPE: sgx_quote_sign_type_t = sgx_quote_sign_type_t::SGX_UNLINKABLE_SIGNATURE; +static SKIP_RA: i32 = 1; +static QUOTE_SIZE: u32 = 0; + +fn run_state_provisioning_server(seal_handler: impl UnsealStateAndKeys, port: u16) { + let listener = TcpListener::bind(server_addr(port)).unwrap(); + + let (socket, _addr) = listener.accept().unwrap(); + let sgx_target_info: sgx_target_info_t = sgx_target_info_t::default(); + run_state_provisioning_server_internal::<_, WorkerModeProvider>( + socket.as_raw_fd(), + SIGN_TYPE, + Some(&sgx_target_info), + Some("E_SIZE), + SKIP_RA, + seal_handler, + ) + .unwrap(); +} + +fn server_addr(port: u16) -> String { + format!("127.0.0.1:{}", port) +} + +pub fn test_tls_ra_server_client_networking() { + let shard = ShardIdentifier::default(); + let client_account = AccountId::from([42; 32]); + let shielding_key_encoded = vec![1, 2, 3]; + let state_key_encoded = vec![5, 2, 3, 7]; + let state_encoded = Vec::from([1u8; 26000]); // Have a decently sized state, so read() must be called multiple times. + let light_client_state_encoded = Vec::from([1u8; 10000]); // Have a decently sized state, so read() must be called multiple times. + + let server_seal_handler = SealHandlerMock::new( + Arc::new(RwLock::new(shielding_key_encoded.clone())), + Arc::new(RwLock::new(state_key_encoded.clone())), + Arc::new(RwLock::new(state_encoded.clone())), + Arc::new(RwLock::new(light_client_state_encoded.clone())), + ); + let initial_client_state = vec![0, 0, 1]; + let initial_client_state_key = vec![0, 0, 2]; + let initial_client_light_client_state = vec![0, 0, 3]; + let client_shielding_key = Arc::new(RwLock::new(Vec::new())); + let client_state_key = Arc::new(RwLock::new(initial_client_state_key.clone())); + let client_state = Arc::new(RwLock::new(initial_client_state.clone())); + let client_light_client_state = Arc::new(RwLock::new(initial_client_light_client_state)); + + let client_seal_handler = SealHandlerMock::new( + client_shielding_key.clone(), + client_state_key.clone(), + client_state.clone(), + client_light_client_state.clone(), + ); + + let port: u16 = 3149; + + // Start server. + let server_thread_handle = thread::spawn(move || { + run_state_provisioning_server(server_seal_handler, port); + }); + thread::sleep(Duration::from_secs(1)); + + // Start client. + let socket = TcpStream::connect(server_addr(port)).unwrap(); + let sgx_target_info: sgx_target_info_t = sgx_target_info_t::default(); + let result = request_state_provisioning_internal( + socket.as_raw_fd(), + SIGN_TYPE, + Some(&sgx_target_info), + Some("E_SIZE), + shard, + SKIP_RA, + client_seal_handler, + client_account, + ); + + // Ensure server thread has finished. + server_thread_handle.join().unwrap(); + + assert!(result.is_ok()); + assert_eq!(*client_shielding_key.read().unwrap(), shielding_key_encoded); + assert_eq!(*client_light_client_state.read().unwrap(), light_client_state_encoded); + + // State and state-key are provisioned only in sidechain mode + if WorkerModeProvider::worker_mode() == WorkerMode::Sidechain { + assert_eq!(*client_state.read().unwrap(), state_encoded); + assert_eq!(*client_state_key.read().unwrap(), state_key_encoded); + } else { + assert_eq!(*client_state.read().unwrap(), initial_client_state); + assert_eq!(*client_state_key.read().unwrap(), initial_client_state_key); + } +} + +// Test state and key provisioning with 'real' data structures. +pub fn test_state_and_key_provisioning() { + let client_account = AccountId::from([42; 32]); + let state_key = Aes::new([3u8; 16], [0u8; 16]); + let shielding_key = Rsa3072KeyPair::new().unwrap(); + let initialized_state = EnclaveStf::init_state(AccountId::new([1u8; 32])); + let shard = ShardIdentifier::from([1u8; 32]); + + let server_seal_handler = + create_seal_handler(state_key, shielding_key, initialized_state, &shard); + let client_seal_handler = + create_seal_handler(Aes::default(), Rsa3072KeyPair::default(), State::default(), &shard); + + let port: u16 = 3150; + + // Start server. + let server_thread_handle = thread::spawn(move || { + run_state_provisioning_server(server_seal_handler, port); + }); + thread::sleep(Duration::from_secs(1)); + + // Start client. + let socket = TcpStream::connect(server_addr(port)).unwrap(); + let sgx_target_info: sgx_target_info_t = sgx_target_info_t::default(); + let result = request_state_provisioning_internal( + socket.as_raw_fd(), + SIGN_TYPE, + Some(&sgx_target_info), + Some("E_SIZE), + shard, + SKIP_RA, + client_seal_handler, + client_account, + ); + + // Ensure server thread has finished. + server_thread_handle.join().unwrap(); + + assert!(result.is_ok()); +} + +fn create_seal_handler( + state_key: Aes, + shielding_key: Rsa3072KeyPair, + state: State, + shard: &ShardIdentifier, +) -> impl UnsealStateAndKeys + SealStateAndKeys { + let state_key_repository = Arc::new(KeyRepositoryMock::::new(state_key)); + let shielding_key_repository = + Arc::new(KeyRepositoryMock::::new(shielding_key)); + let state_handler = Arc::new(HandleStateMock::default()); + state_handler.reset(state, shard).unwrap(); + let seal = Arc::new(LightValidationStateSealMock::new()); + + SealHandler::new(state_handler, state_key_repository, shielding_key_repository, seal) +} diff --git a/bitacross-worker/enclave-runtime/src/tls_ra/tls_ra_client.rs b/bitacross-worker/enclave-runtime/src/tls_ra/tls_ra_client.rs new file mode 100644 index 0000000000..442512701e --- /dev/null +++ b/bitacross-worker/enclave-runtime/src/tls_ra/tls_ra_client.rs @@ -0,0 +1,327 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 client part of the state provisioning. + +use super::{authentication::ServerAuth, Opcode, TcpHeader}; +use crate::{ + attestation::create_ra_report_and_signature, + error::{Error as EnclaveError, Result as EnclaveResult}, + initialization::global_components::{ + EnclaveSealHandler, GLOBAL_INTEGRITEE_PARENTCHAIN_LIGHT_CLIENT_SEAL, + GLOBAL_SHIELDING_KEY_REPOSITORY_COMPONENT, GLOBAL_STATE_KEY_REPOSITORY_COMPONENT, + }, + ocall::OcallApi, + tls_ra::{seal_handler::SealStateAndKeys, ClientProvisioningRequest}, + GLOBAL_SIGNING_KEY_REPOSITORY_COMPONENT, GLOBAL_STATE_HANDLER_COMPONENT, +}; +use codec::Encode; +use itp_attestation_handler::{RemoteAttestationType, DEV_HOSTNAME}; +use itp_component_container::ComponentGetter; +use itp_ocall_api::EnclaveAttestationOCallApi; +use itp_sgx_crypto::key_repository::AccessPubkey; +use itp_types::{AccountId, ShardIdentifier}; +use log::*; +use rustls::{ClientConfig, ClientSession, Stream}; +use sgx_types::*; +use std::{ + backtrace::{self, PrintFormat}, + convert::TryInto, + io::{Read, Write}, + net::TcpStream, + slice, + sync::Arc, + vec::Vec, +}; +/// Client part of the TCP-level connection and the underlying TLS-level session. +/// +/// Includes a seal handler, which handles the storage part of the received data. +struct TlsClient<'a, StateAndKeySealer> +where + StateAndKeySealer: SealStateAndKeys, +{ + tls_stream: Stream<'a, ClientSession, TcpStream>, + seal_handler: StateAndKeySealer, + shard: ShardIdentifier, +} + +impl<'a, StateAndKeySealer> TlsClient<'a, StateAndKeySealer> +where + StateAndKeySealer: SealStateAndKeys, +{ + fn new( + tls_stream: Stream<'a, ClientSession, TcpStream>, + seal_handler: StateAndKeySealer, + shard: ShardIdentifier, + ) -> TlsClient { + TlsClient { tls_stream, seal_handler, shard } + } + + /// Read all data sent by the server of the specific shard. + /// + /// We trust here that the server sends us the correct data, as + /// we do not have any way to test it. + fn obtain_provisioning_for_shard(&mut self, account: AccountId) -> EnclaveResult<()> { + debug!( + "obtain_provisioning_for_shard called, about to call self.send_provisioning_request()." + ); + self.send_provisioning_request(account)?; + debug!("self.send_provisioning_request() succeeded."); + self.read_and_seal_all() + } + + /// Send the shard of the state we want to receive to the provisioning server. + fn send_provisioning_request(&mut self, account: AccountId) -> EnclaveResult<()> { + debug!("self.send_provisioning_request() called."); + self.tls_stream + .write_all(&ClientProvisioningRequest { shard: self.shard, account }.encode())?; + debug!("write_all succeeded."); + Ok(()) + } + + /// Read and seal all relevant data sent by the server. + fn read_and_seal_all(&mut self) -> EnclaveResult<()> { + let mut received_payloads: Vec = Vec::new(); + + loop { + let maybe_opcode = self.read_and_seal()?; + match maybe_opcode { + None => break, + Some(o) => { + received_payloads.push(o); + }, + } + } + info!("Successfully read and sealed all data sent by the state provisioning server."); + + // In case we receive a shielding key, but no state, we need to reset our state + // to update the enclave account. + if received_payloads.contains(&Opcode::ShieldingKey) + && !received_payloads.contains(&Opcode::State) + { + self.seal_handler.seal_new_empty_state(&self.shard)?; + } + + Ok(()) + } + + /// Read a server header / payload pair and directly seal the received data. + fn read_and_seal(&mut self) -> EnclaveResult> { + let mut start_byte = [0u8; 1]; + let read_size = self.tls_stream.read(&mut start_byte)?; + // If we're reading but there's no data: EOF. + if read_size == 0 { + return Ok(None) + } + let header = self.read_header(start_byte[0])?; + let bytes = self.read_until(header.payload_length as usize)?; + match header.opcode { + Opcode::ShieldingKey => self.seal_handler.seal_shielding_key(&bytes)?, + Opcode::StateKey => self.seal_handler.seal_state_key(&bytes)?, + Opcode::State => self.seal_handler.seal_state(&bytes, &self.shard)?, + Opcode::LightClient => self.seal_handler.seal_light_client_state(&bytes)?, + }; + Ok(Some(header.opcode)) + } + + /// Reads the payload header, indicating the sent payload length and type. + fn read_header(&mut self, start_byte: u8) -> EnclaveResult { + debug!("Read first byte: {:?}", start_byte); + // The first sent byte indicates the payload type. + let opcode: Opcode = start_byte + .try_into() + .map_err(|_| EnclaveError::Other("Could not convert opcode".into()))?; + debug!("Read header opcode: {:?}", opcode); + // The following bytes contain the payload length, which is a u64. + let mut payload_length_buffer = [0u8; std::mem::size_of::()]; + self.tls_stream.read_exact(&mut payload_length_buffer)?; + let payload_length = u64::from_be_bytes(payload_length_buffer); + debug!("Payload length of {:?}: {}", opcode, payload_length); + + Ok(TcpHeader::new(opcode, payload_length)) + } + + /// Read all bytes into a buffer of given length. + fn read_until(&mut self, length: usize) -> EnclaveResult> { + let mut bytes = vec![0u8; length]; + self.tls_stream.read_exact(&mut bytes)?; + Ok(bytes) + } +} + +#[no_mangle] +pub unsafe extern "C" fn request_state_provisioning( + socket_fd: c_int, + sign_type: sgx_quote_sign_type_t, + quoting_enclave_target_info: Option<&sgx_target_info_t>, + quote_size: Option<&u32>, + shard: *const u8, + shard_size: u32, + skip_ra: c_int, +) -> sgx_status_t { + let _ = backtrace::enable_backtrace("enclave.signed.so", PrintFormat::Short); + let shard = ShardIdentifier::from_slice(slice::from_raw_parts(shard, shard_size as usize)); + + let state_handler = match GLOBAL_STATE_HANDLER_COMPONENT.get() { + Ok(s) => s, + Err(e) => { + error!("{:?}", e); + return sgx_status_t::SGX_ERROR_UNEXPECTED + }, + }; + + let state_key_repository = match GLOBAL_STATE_KEY_REPOSITORY_COMPONENT.get() { + Ok(s) => s, + Err(e) => { + error!("{:?}", e); + return sgx_status_t::SGX_ERROR_UNEXPECTED + }, + }; + + let shielding_key_repository = match GLOBAL_SHIELDING_KEY_REPOSITORY_COMPONENT.get() { + Ok(s) => s, + Err(e) => { + error!("{:?}", e); + return sgx_status_t::SGX_ERROR_UNEXPECTED + }, + }; + + let light_client_seal = match GLOBAL_INTEGRITEE_PARENTCHAIN_LIGHT_CLIENT_SEAL.get() { + Ok(s) => s, + Err(e) => { + error!("{:?}", e); + return sgx_status_t::SGX_ERROR_UNEXPECTED + }, + }; + + let seal_handler = EnclaveSealHandler::new( + state_handler, + state_key_repository, + shielding_key_repository, + light_client_seal, + ); + + let signing_key_repository = match GLOBAL_SIGNING_KEY_REPOSITORY_COMPONENT.get() { + Ok(s) => s, + Err(e) => { + error!("{:?}", e); + return sgx_status_t::SGX_ERROR_UNEXPECTED + }, + }; + + let client_account = match signing_key_repository.retrieve_pubkey() { + Ok(s) => AccountId::from(s), + Err(e) => return e.into(), + }; + + if let Err(e) = request_state_provisioning_internal( + socket_fd, + sign_type, + quoting_enclave_target_info, + quote_size, + shard, + skip_ra, + seal_handler, + client_account, + ) { + error!("Failed to sync state due to: {:?}", e); + return e.into() + }; + + sgx_status_t::SGX_SUCCESS +} + +/// Internal [`request_state_provisioning`] function to be able to use the handy `?` operator. +// allowing clippy rant because this fn will be refactored with MU RA deprecation +#[allow(clippy::too_many_arguments)] +pub(crate) fn request_state_provisioning_internal( + socket_fd: c_int, + sign_type: sgx_quote_sign_type_t, + quoting_enclave_target_info: Option<&sgx_target_info_t>, + quote_size: Option<&u32>, + shard: ShardIdentifier, + skip_ra: c_int, + seal_handler: StateAndKeySealer, + client_account: AccountId, +) -> EnclaveResult<()> { + debug!("Client config generate..."); + let client_config = tls_client_config( + sign_type, + quoting_enclave_target_info, + quote_size, + OcallApi, + skip_ra == 1, + )?; + debug!("Client config retrieved"); + let (mut client_session, mut tcp_stream) = tls_client_session_stream(socket_fd, client_config)?; + debug!("Client sesssion established."); + + let mut client = TlsClient::new( + rustls::Stream::new(&mut client_session, &mut tcp_stream), + seal_handler, + shard, + ); + + info!("Requesting keys and state from mu-ra server of fellow validateer"); + client.obtain_provisioning_for_shard(client_account) +} + +fn tls_client_config( + sign_type: sgx_quote_sign_type_t, + quoting_enclave_target_info: Option<&sgx_target_info_t>, + quote_size: Option<&u32>, + ocall_api: A, + skip_ra: bool, +) -> EnclaveResult { + #[cfg(not(feature = "dcap"))] + let attestation_type = RemoteAttestationType::Epid; + #[cfg(feature = "dcap")] + let attestation_type = RemoteAttestationType::Dcap; + + // report will be signed with client enclave ed25519 signing key + let (key_der, cert_der) = create_ra_report_and_signature( + skip_ra, + attestation_type, + sign_type, + quoting_enclave_target_info, + quote_size, + )?; + debug!("got key_der and cert_der"); + + let mut cfg = rustls::ClientConfig::new(); + let certs = vec![rustls::Certificate(cert_der)]; + let privkey = rustls::PrivateKey(key_der); + #[allow(clippy::unwrap_used)] + cfg.set_single_client_cert(certs, privkey).unwrap(); + // ServerAuth will perform MU RA as part of authentication process + cfg.dangerous() + .set_certificate_verifier(Arc::new(ServerAuth::new(true, skip_ra, ocall_api))); + cfg.versions.clear(); + cfg.versions.push(rustls::ProtocolVersion::TLSv1_2); + Ok(cfg) +} + +fn tls_client_session_stream( + socket_fd: i32, + client_config: ClientConfig, +) -> EnclaveResult<(ClientSession, TcpStream)> { + let dns_name = webpki::DNSNameRef::try_from_ascii_str(DEV_HOSTNAME) + .map_err(|e| EnclaveError::Other(e.into()))?; + let sess = rustls::ClientSession::new(&Arc::new(client_config), dns_name); + let conn = TcpStream::new(socket_fd)?; + Ok((sess, conn)) +} diff --git a/bitacross-worker/enclave-runtime/src/tls_ra/tls_ra_server.rs b/bitacross-worker/enclave-runtime/src/tls_ra/tls_ra_server.rs new file mode 100644 index 0000000000..33f72e9095 --- /dev/null +++ b/bitacross-worker/enclave-runtime/src/tls_ra/tls_ra_server.rs @@ -0,0 +1,323 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 server part of the state provisioning. + +use super::{authentication::ClientAuth, ClientProvisioningRequest, Opcode, TcpHeader}; +use crate::{ + attestation::create_ra_report_and_signature, + error::{Error as EnclaveError, Result as EnclaveResult}, + initialization::global_components::{ + EnclaveSealHandler, GLOBAL_INTEGRITEE_PARENTCHAIN_LIGHT_CLIENT_SEAL, + GLOBAL_SHIELDING_KEY_REPOSITORY_COMPONENT, GLOBAL_STATE_KEY_REPOSITORY_COMPONENT, + }, + ocall::OcallApi, + shard_vault::add_shard_vault_proxy, + tls_ra::seal_handler::UnsealStateAndKeys, + GLOBAL_STATE_HANDLER_COMPONENT, +}; +use codec::Decode; +use itp_attestation_handler::RemoteAttestationType; +use itp_component_container::ComponentGetter; +use itp_ocall_api::EnclaveAttestationOCallApi; +use itp_settings::worker_mode::{ProvideWorkerMode, WorkerMode, WorkerModeProvider}; +use itp_types::ShardIdentifier; +use log::*; +use rustls::{ServerConfig, ServerSession, StreamOwned}; +use sgx_types::*; +use std::{ + backtrace::{self, PrintFormat}, + io::{Read, Write}, + net::TcpStream, + sync::Arc, +}; + +#[derive(Clone, Eq, PartialEq, Debug)] +enum ProvisioningPayload { + Everything, + ShieldingKeyAndLightClient, +} + +impl From for ProvisioningPayload { + fn from(m: WorkerMode) -> Self { + match m { + WorkerMode::OffChainWorker | WorkerMode::Teeracle => + ProvisioningPayload::ShieldingKeyAndLightClient, + WorkerMode::Sidechain => ProvisioningPayload::Everything, + } + } +} + +/// Server part of the TCP-level connection and the underlying TLS-level session. +/// +/// Includes a seal handler, which handles the reading part of the data to be sent. +struct TlsServer { + tls_stream: StreamOwned, + seal_handler: StateAndKeyUnsealer, + provisioning_payload: ProvisioningPayload, +} + +impl TlsServer +where + StateAndKeyUnsealer: UnsealStateAndKeys, +{ + fn new( + tls_stream: StreamOwned, + seal_handler: StateAndKeyUnsealer, + provisioning_payload: ProvisioningPayload, + ) -> Self { + Self { tls_stream, seal_handler, provisioning_payload } + } + + /// Sends all relevant data of the specific shard to the client. + fn handle_shard_request_from_client(&mut self) -> EnclaveResult<()> { + println!( + " [Enclave] (MU-RA-Server) handle_shard_request_from_client, calling read_shard()" + ); + let request = self.await_shard_request_from_client()?; + println!(" [Enclave] (MU-RA-Server) handle_shard_request_from_client, await_shard_request_from_client() OK"); + println!(" [Enclave] (MU-RA-Server) handle_shard_request_from_client, write_all()"); + self.write_provisioning_payloads(&request.shard)?; + + info!( + "will make client account 0x{} a proxy of vault for shard {:?}", + hex::encode(request.account.clone()), + request.shard + ); + if let Err(e) = add_shard_vault_proxy(request.shard, &request.account) { + // we can't be sure that registering the proxy will succeed onchain at this point, + // therefore we can accept an error here as the client has to verify anyway and + // retry if it failed + error!("failed to add shard vault proxy for {:?}: {:?}", request.account, e); + }; + Ok(()) + } + + /// Read the shard of the state the client wants to receive. + fn await_shard_request_from_client(&mut self) -> EnclaveResult { + let mut request = [0u8; std::mem::size_of::()]; + println!( + " [Enclave] (MU-RA-Server) await_shard_request_from_client, calling read_exact()" + ); + self.tls_stream.read_exact(&mut request)?; + ClientProvisioningRequest::decode(&mut request.as_slice()) + .map_err(|_| EnclaveError::Other("matching byte size can't fail to decode".into())) + } + + /// Sends all relevant data to the client. + fn write_provisioning_payloads(&mut self, shard: &ShardIdentifier) -> EnclaveResult<()> { + debug!("Provisioning is set to: {:?}", self.provisioning_payload); + match self.provisioning_payload { + ProvisioningPayload::Everything => { + self.write_shielding_key()?; + self.write_state_key()?; + self.write_state(shard)?; + self.write_light_client_state()?; + }, + ProvisioningPayload::ShieldingKeyAndLightClient => { + self.write_shielding_key()?; + self.write_light_client_state()?; + }, + } + + debug!("Successfully provisioned all payloads to peer"); + Ok(()) + } + + fn write_shielding_key(&mut self) -> EnclaveResult<()> { + let shielding_key = self.seal_handler.unseal_shielding_key()?; + self.write(Opcode::ShieldingKey, &shielding_key)?; + Ok(()) + } + + fn write_state_key(&mut self) -> EnclaveResult<()> { + let state_key = self.seal_handler.unseal_state_key()?; + self.write(Opcode::StateKey, &state_key)?; + Ok(()) + } + + fn write_state(&mut self, shard: &ShardIdentifier) -> EnclaveResult<()> { + let state = self.seal_handler.unseal_state(shard)?; + self.write(Opcode::State, &state)?; + Ok(()) + } + + fn write_light_client_state(&mut self) -> EnclaveResult<()> { + let state = self.seal_handler.unseal_light_client_state()?; + self.write(Opcode::LightClient, &state)?; + Ok(()) + } + + /// Sends the header followed by the payload. + fn write(&mut self, opcode: Opcode, bytes: &[u8]) -> EnclaveResult<()> { + let payload_length = bytes.len() as u64; + self.write_header(TcpHeader::new(opcode, payload_length))?; + debug!("Write payload - opcode: {:?}, payload_length: {}", opcode, payload_length); + self.tls_stream.write_all(bytes)?; + Ok(()) + } + + /// Sends the header which includes the payload length and the Opcode indicating the payload type. + fn write_header(&mut self, tcp_header: TcpHeader) -> EnclaveResult<()> { + self.tls_stream.write_all(&tcp_header.opcode.to_bytes())?; + self.tls_stream.write_all(&tcp_header.payload_length.to_be_bytes())?; + debug!( + "Write header - opcode: {:?}, payload length: {}", + tcp_header.opcode, tcp_header.payload_length + ); + Ok(()) + } +} + +#[no_mangle] +pub unsafe extern "C" fn run_state_provisioning_server( + socket_fd: c_int, + sign_type: sgx_quote_sign_type_t, + quoting_enclave_target_info: Option<&sgx_target_info_t>, + quote_size: Option<&u32>, + skip_ra: c_int, +) -> sgx_status_t { + let _ = backtrace::enable_backtrace("enclave.signed.so", PrintFormat::Short); + + let state_handler = match GLOBAL_STATE_HANDLER_COMPONENT.get() { + Ok(s) => s, + Err(e) => { + error!("{:?}", e); + return sgx_status_t::SGX_ERROR_UNEXPECTED + }, + }; + + let state_key_repository = match GLOBAL_STATE_KEY_REPOSITORY_COMPONENT.get() { + Ok(s) => s, + Err(e) => { + error!("{:?}", e); + return sgx_status_t::SGX_ERROR_UNEXPECTED + }, + }; + + let shielding_key_repository = match GLOBAL_SHIELDING_KEY_REPOSITORY_COMPONENT.get() { + Ok(s) => s, + Err(e) => { + error!("{:?}", e); + return sgx_status_t::SGX_ERROR_UNEXPECTED + }, + }; + + let light_client_seal = match GLOBAL_INTEGRITEE_PARENTCHAIN_LIGHT_CLIENT_SEAL.get() { + Ok(s) => s, + Err(e) => { + error!("{:?}", e); + return sgx_status_t::SGX_ERROR_UNEXPECTED + }, + }; + + let seal_handler = EnclaveSealHandler::new( + state_handler, + state_key_repository, + shielding_key_repository, + light_client_seal, + ); + + if let Err(e) = run_state_provisioning_server_internal::<_, WorkerModeProvider>( + socket_fd, + sign_type, + quoting_enclave_target_info, + quote_size, + skip_ra, + seal_handler, + ) { + error!("Failed to provision state due to: {:?}", e); + return e.into() + }; + + sgx_status_t::SGX_SUCCESS +} + +/// Internal [`run_state_provisioning_server`] function to be able to use the handy `?` operator. +pub(crate) fn run_state_provisioning_server_internal< + StateAndKeyUnsealer: UnsealStateAndKeys, + WorkerModeProvider: ProvideWorkerMode, +>( + socket_fd: c_int, + sign_type: sgx_quote_sign_type_t, + quoting_enclave_target_info: Option<&sgx_target_info_t>, + quote_size: Option<&u32>, + skip_ra: c_int, + seal_handler: StateAndKeyUnsealer, +) -> EnclaveResult<()> { + let server_config = tls_server_config( + sign_type, + quoting_enclave_target_info, + quote_size, + OcallApi, + skip_ra == 1, + )?; + let (server_session, tcp_stream) = tls_server_session_stream(socket_fd, server_config)?; + + let provisioning = ProvisioningPayload::from(WorkerModeProvider::worker_mode()); + + let mut server = + TlsServer::new(StreamOwned::new(server_session, tcp_stream), seal_handler, provisioning); + + // todo: verify client signer belongs to a registered enclave on integritee network with a + // matching or whitelisted MRENCLAVE as replacement for MU RA #1385 + + println!(" [Enclave] (MU-RA-Server) MU-RA successful sending keys"); + println!( + " [Enclave] (MU-RA-Server) MU-RA successful, calling handle_shard_request_from_client()" + ); + server.handle_shard_request_from_client() +} + +fn tls_server_session_stream( + socket_fd: i32, + server_config: ServerConfig, +) -> EnclaveResult<(ServerSession, TcpStream)> { + let sess = ServerSession::new(&Arc::new(server_config)); + let conn = TcpStream::new(socket_fd).map_err(|e| EnclaveError::Other(e.into()))?; + Ok((sess, conn)) +} + +fn tls_server_config( + sign_type: sgx_quote_sign_type_t, + quoting_enclave_target_info: Option<&sgx_target_info_t>, + quote_size: Option<&u32>, + ocall_api: A, + skip_ra: bool, +) -> EnclaveResult { + #[cfg(not(feature = "dcap"))] + let attestation_type = RemoteAttestationType::Epid; + #[cfg(feature = "dcap")] + let attestation_type = RemoteAttestationType::Dcap; + + // report will be signed with server enclave ed25519 signing key + let (key_der, cert_der) = create_ra_report_and_signature( + skip_ra, + attestation_type, + sign_type, + quoting_enclave_target_info, + quote_size, + )?; + + // ClientAuth will perform MU RA as part of authentication process + let mut cfg = rustls::ServerConfig::new(Arc::new(ClientAuth::new(true, skip_ra, ocall_api))); + let certs = vec![rustls::Certificate(cert_der)]; + let privkey = rustls::PrivateKey(key_der); + cfg.set_single_cert_with_ocsp_and_sct(certs, privkey, vec![], vec![]) + .map_err(|e| EnclaveError::Other(e.into()))?; + Ok(cfg) +} diff --git a/bitacross-worker/enclave-runtime/src/top_pool_execution.rs b/bitacross-worker/enclave-runtime/src/top_pool_execution.rs new file mode 100644 index 0000000000..a8168864e3 --- /dev/null +++ b/bitacross-worker/enclave-runtime/src/top_pool_execution.rs @@ -0,0 +1,412 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{ + error::Result, + initialization::global_components::{ + GLOBAL_OCALL_API_COMPONENT, GLOBAL_SIDECHAIN_BLOCK_COMPOSER_COMPONENT, + GLOBAL_SIDECHAIN_FAIL_SLOT_ON_DEMAND_COMPONENT, + GLOBAL_SIDECHAIN_IMPORT_QUEUE_WORKER_COMPONENT, GLOBAL_SIGNING_KEY_REPOSITORY_COMPONENT, + GLOBAL_STATE_HANDLER_COMPONENT, GLOBAL_TOP_POOL_AUTHOR_COMPONENT, + }, + sync::{EnclaveLock, EnclaveStateRWLock}, + utils::{ + get_extrinsic_factory_from_integritee_solo_or_parachain, + get_extrinsic_factory_from_target_a_solo_or_parachain, + get_extrinsic_factory_from_target_b_solo_or_parachain, + get_stf_executor_from_solo_or_parachain, + get_triggered_dispatcher_from_integritee_solo_or_parachain, + get_triggered_dispatcher_from_target_a_solo_or_parachain, + get_triggered_dispatcher_from_target_b_solo_or_parachain, + get_validator_accessor_from_integritee_solo_or_parachain, + get_validator_accessor_from_target_a_solo_or_parachain, + get_validator_accessor_from_target_b_solo_or_parachain, + }, +}; +use codec::Encode; +use itc_parentchain::{ + block_import_dispatcher::triggered_dispatcher::TriggerParentchainBlockImport, + light_client::{ + concurrent_access::ValidatorAccess, BlockNumberOps, ExtrinsicSender, LightClientState, + NumberFor, + }, +}; +use itp_component_container::ComponentGetter; +use itp_enclave_metrics::EnclaveMetric; +use itp_extrinsics_factory::CreateExtrinsics; +use itp_ocall_api::{EnclaveMetricsOCallApi, EnclaveOnChainOCallApi, EnclaveSidechainOCallApi}; +use itp_settings::sidechain::SLOT_DURATION; +use itp_sgx_crypto::key_repository::AccessKey; +use itp_sgx_externalities::SgxExternalities; +use itp_stf_state_handler::{handle_state::HandleState, query_shard_state::QueryShardState}; +use itp_time_utils::duration_now; +use itp_types::{parentchain::ParentchainCall, Block, OpaqueCall, H256}; +use itp_utils::if_not_production; +use its_primitives::{ + traits::{ + Block as SidechainBlockTrait, Header as HeaderTrait, ShardIdentifierFor, SignedBlock, + }, + types::block::SignedBlock as SignedSidechainBlock, +}; +use its_sidechain::{ + aura::{proposer_factory::ProposerFactory, Aura, SlotClaimStrategy}, + consensus_common::{Environment, Error as ConsensusError, ProcessBlockImportQueue}, + slots::{yield_next_slot, LastSlot, PerShardSlotWorkerScheduler, SlotInfo}, + validateer_fetch::ValidateerFetch, +}; +use lc_scheduled_enclave::{ScheduledEnclaveUpdater, GLOBAL_SCHEDULED_ENCLAVE}; +use log::*; +use sgx_types::sgx_status_t; +use sp_core::{crypto::UncheckedFrom, Pair}; +use sp_runtime::{ + generic::SignedBlock as SignedParentchainBlock, traits::Block as BlockTrait, MultiSignature, +}; +use std::{sync::Arc, time::Instant, vec::Vec}; + +#[no_mangle] +pub unsafe extern "C" fn execute_trusted_calls() -> sgx_status_t { + if let Err(e) = execute_top_pool_trusted_calls_internal() { + return e.into() + } + + sgx_status_t::SGX_SUCCESS +} + +/// Internal [`execute_trusted_calls`] function to be able to use the `?` operator. +/// +/// Executes `Aura::on_slot() for `slot` if it is this enclave's `Slot`. +/// +/// This function makes an ocall that does the following: +/// +/// * Import all pending parentchain blocks. +/// * Sends sidechain `confirm_block` xt's with the produced sidechain blocks. +/// * Broadcast produced sidechain blocks to peer validateers. +fn execute_top_pool_trusted_calls_internal() -> Result<()> { + let start_time = Instant::now(); + + debug!("----------------------------------------"); + debug!("Start sidechain block production cycle"); + + // We acquire lock explicitly (variable binding), since '_' will drop the lock after the statement. + // See https://medium.com/codechain/rust-underscore-does-not-bind-fec6a18115a8 + let _enclave_write_lock = EnclaveLock::write_all()?; + + let slot_beginning_timestamp = duration_now(); + + let integritee_parentchain_import_dispatcher = + get_triggered_dispatcher_from_integritee_solo_or_parachain()?; + let maybe_target_a_parentchain_import_dispatcher = + get_triggered_dispatcher_from_target_a_solo_or_parachain().ok(); + let maybe_target_b_parentchain_import_dispatcher = + get_triggered_dispatcher_from_target_b_solo_or_parachain().ok(); + + let maybe_latest_target_a_parentchain_header = + if let Some(ref _triggered_dispatcher) = maybe_target_a_parentchain_import_dispatcher { + let validator_access = get_validator_accessor_from_target_a_solo_or_parachain()?; + Some(validator_access.execute_on_validator(|v| { + let latest_parentchain_header = v.latest_finalized_header()?; + Ok(latest_parentchain_header) + })?) + } else { + None + }; + + let maybe_latest_target_b_parentchain_header = + if let Some(ref _triggered_dispatcher) = maybe_target_b_parentchain_import_dispatcher { + let validator_access = get_validator_accessor_from_target_b_solo_or_parachain()?; + Some(validator_access.execute_on_validator(|v| { + let latest_parentchain_header = v.latest_finalized_header()?; + Ok(latest_parentchain_header) + })?) + } else { + None + }; + + let integritee_validator_access = get_validator_accessor_from_integritee_solo_or_parachain()?; + + // This gets the latest imported block. We accept that all of AURA, up until the block production + // itself, will operate on a parentchain block that is potentially outdated by one block + // (in case we have a block in the queue, but not imported yet). + let current_integritee_parentchain_header = + integritee_validator_access.execute_on_validator(|v| { + let latest_parentchain_header = v.latest_finalized_header()?; + Ok(latest_parentchain_header) + })?; + + // Import any sidechain blocks that are in the import queue. In case we are missing blocks, + // a peer sync will happen. If that happens, the slot time might already be used up just by this import. + let sidechain_block_import_queue_worker = + GLOBAL_SIDECHAIN_IMPORT_QUEUE_WORKER_COMPONENT.get()?; + + let latest_integritee_parentchain_header = sidechain_block_import_queue_worker + .process_queue(¤t_integritee_parentchain_header)?; + + trace!( + "Elapsed time to process sidechain block import queue: {} ms", + start_time.elapsed().as_millis() + ); + + let stf_executor = get_stf_executor_from_solo_or_parachain()?; + + let top_pool_author = GLOBAL_TOP_POOL_AUTHOR_COMPONENT.get()?; + + let block_composer = GLOBAL_SIDECHAIN_BLOCK_COMPOSER_COMPONENT.get()?; + + let state_handler = GLOBAL_STATE_HANDLER_COMPONENT.get()?; + + let ocall_api = GLOBAL_OCALL_API_COMPONENT.get()?; + + let authority = GLOBAL_SIGNING_KEY_REPOSITORY_COMPONENT.get()?.retrieve_key()?; + + let fail_on_demand = GLOBAL_SIDECHAIN_FAIL_SLOT_ON_DEMAND_COMPONENT.get()?; + + match yield_next_slot( + slot_beginning_timestamp, + SLOT_DURATION, + latest_integritee_parentchain_header, + maybe_latest_target_a_parentchain_header, + maybe_latest_target_b_parentchain_header, + &mut LastSlot, + )? { + Some(slot) => { + if slot.duration_remaining().is_none() { + warn!("No time remaining in slot, skipping AURA execution"); + return Ok(()) + } + log_remaining_slot_duration(&slot, "Before AURA"); + + let shards = state_handler.list_shards()?; + let env = ProposerFactory::::new( + top_pool_author, + stf_executor, + block_composer, + ocall_api.clone(), + ); + + if_not_production!({ + if let Some(ref fail_on_demand) = *fail_on_demand { + fail_on_demand.next_slot(); + if fail_on_demand.check_before_on_slot() { + Result::Err(crate::error::Error::Sgx(sgx_status_t::SGX_ERROR_UNEXPECTED))?; + } + } + }); + + let (blocks, parentchain_calls) = + exec_aura_on_slot::<_, _, SignedSidechainBlock, _, _, _, _, _, _, _>( + slot.clone(), + authority, + ocall_api.clone(), + integritee_parentchain_import_dispatcher, + maybe_target_a_parentchain_import_dispatcher, + maybe_target_b_parentchain_import_dispatcher, + env, + shards, + GLOBAL_SCHEDULED_ENCLAVE.clone(), + state_handler, + )?; + + if_not_production!({ + if let Some(ref fail_on_demand) = *fail_on_demand { + if fail_on_demand.check_after_on_slot() { + Result::Err(crate::error::Error::Sgx(sgx_status_t::SGX_ERROR_UNEXPECTED))?; + } + } + }); + + debug!("Aura executed successfully"); + + // Drop lock as soon as we don't need it anymore. + drop(_enclave_write_lock); + + log_remaining_slot_duration(&slot, "After AURA"); + + send_blocks_and_extrinsics::(blocks, parentchain_calls, ocall_api)?; + + log_remaining_slot_duration(&slot, "After broadcasting and sending extrinsic"); + }, + None => { + debug!("No slot yielded. Skipping block production."); + return Ok(()) + }, + }; + + debug!("End sidechain block production cycle"); + Ok(()) +} + +/// Executes aura for the given `slot`. +#[allow(clippy::too_many_arguments)] +pub(crate) fn exec_aura_on_slot< + Authority, + ParentchainBlock, + SignedSidechainBlock, + OCallApi, + PEnvironment, + IntegriteeBlockImportTrigger, + TargetABlockImportTrigger, + TargetBBlockImportTrigger, + ScheduledEnclave, + StateHandler, +>( + slot: SlotInfo, + authority: Authority, + ocall_api: Arc, + integritee_block_import_trigger: Arc, + maybe_target_a_block_import_trigger: Option>, + maybe_target_b_block_import_trigger: Option>, + proposer_environment: PEnvironment, + shards: Vec>, + scheduled_enclave: Arc, + state_handler: Arc, +) -> Result<(Vec, Vec)> +where + ParentchainBlock: BlockTrait, + SignedSidechainBlock: + SignedBlock + 'static, // Setting the public type is necessary due to some non-generic downstream code. + SignedSidechainBlock::Block: SidechainBlockTrait, + <::Block as SidechainBlockTrait>::HeaderType: + HeaderTrait, + SignedSidechainBlock::Signature: From, + Authority: Pair, + Authority::Public: Encode + UncheckedFrom<[u8; 32]>, + OCallApi: ValidateerFetch + EnclaveOnChainOCallApi + EnclaveSidechainOCallApi + Send + 'static, + NumberFor: BlockNumberOps, + PEnvironment: + Environment + Send + Sync, + IntegriteeBlockImportTrigger: + TriggerParentchainBlockImport>, + TargetABlockImportTrigger: + TriggerParentchainBlockImport>, + TargetBBlockImportTrigger: + TriggerParentchainBlockImport>, + ScheduledEnclave: ScheduledEnclaveUpdater, + StateHandler: HandleState, +{ + debug!("[Aura] Executing aura for slot: {:?}", slot); + + let mut aura = + Aura::<_, ParentchainBlock, SignedSidechainBlock, PEnvironment, _, _, _, _, _, _>::new( + authority, + ocall_api.as_ref().clone(), + integritee_block_import_trigger, + maybe_target_a_block_import_trigger, + maybe_target_b_block_import_trigger, + proposer_environment, + scheduled_enclave, + state_handler, + ) + .with_claim_strategy(SlotClaimStrategy::RoundRobin); + + // We only check if there are more workers registered, which might not really mean they are + // online and syncing sidechain state but that should be enough for now. + let is_single_worker = match ocall_api.get_trusted_peers_urls() { + Ok(urls) => urls.is_empty(), + Err(e) => { + warn!("Could not get trusted peers urls, error: {:?}", e); + warn!("Falling back to non single worker mode"); + false + }, + }; + + let (blocks, pxts): (Vec<_>, Vec<_>) = + PerShardSlotWorkerScheduler::on_slot(&mut aura, slot, shards, is_single_worker) + .into_iter() + .map(|r| (r.block, r.parentchain_effects)) + .unzip(); + + let opaque_calls: Vec = pxts.into_iter().flatten().collect(); + Ok((blocks, opaque_calls)) +} + +/// Broadcasts sidechain blocks to fellow peers and sends opaque calls as extrinsic to the parentchain. +pub(crate) fn send_blocks_and_extrinsics( + blocks: Vec, + parentchain_calls: Vec, + ocall_api: Arc, +) -> Result<()> +where + ParentchainBlock: BlockTrait, + SignedSidechainBlock: SignedBlock + 'static, + OCallApi: EnclaveSidechainOCallApi + EnclaveMetricsOCallApi, + NumberFor: BlockNumberOps, +{ + let started = std::time::Instant::now(); + debug!("Proposing {} sidechain block(s) (broadcasting to peers)", blocks.len()); + ocall_api.propose_sidechain_blocks(blocks)?; + if let Err(e) = + ocall_api.update_metric(EnclaveMetric::SidechainBlockBroadcastingTime(started.elapsed())) + { + warn!("Failed to update metric for sidechain block broadcasting time: {:?}", e); + }; + + let calls: Vec = parentchain_calls + .iter() + .filter_map(|parentchain_call| parentchain_call.as_litentry()) + .collect(); + debug!("Enclave wants to send {} extrinsics to Integritee Parentchain", calls.len()); + if !calls.is_empty() { + let extrinsics_factory = get_extrinsic_factory_from_integritee_solo_or_parachain()?; + let xts = extrinsics_factory.create_extrinsics(calls.as_slice(), None)?; + let validator_access = get_validator_accessor_from_integritee_solo_or_parachain()?; + validator_access.execute_mut_on_validator(|v| v.send_extrinsics(xts))?; + } + let calls: Vec = parentchain_calls + .iter() + .filter_map(|parentchain_call| parentchain_call.as_target_a()) + .collect(); + debug!("Enclave wants to send {} extrinsics to TargetA Parentchain", calls.len()); + if !calls.is_empty() { + let extrinsics_factory = get_extrinsic_factory_from_target_a_solo_or_parachain()?; + let xts = extrinsics_factory.create_extrinsics(calls.as_slice(), None)?; + let validator_access = get_validator_accessor_from_target_a_solo_or_parachain()?; + validator_access.execute_mut_on_validator(|v| v.send_extrinsics(xts))?; + } + let calls: Vec = parentchain_calls + .iter() + .filter_map(|parentchain_call| parentchain_call.as_target_b()) + .collect(); + debug!("Enclave wants to send {} extrinsics to TargetB Parentchain", calls.len()); + if !calls.is_empty() { + let extrinsics_factory = get_extrinsic_factory_from_target_b_solo_or_parachain()?; + let xts = extrinsics_factory.create_extrinsics(calls.as_slice(), None)?; + let validator_access = get_validator_accessor_from_target_b_solo_or_parachain()?; + validator_access.execute_mut_on_validator(|v| v.send_extrinsics(xts))?; + } + + Ok(()) +} + +fn log_remaining_slot_duration>( + slot_info: &SlotInfo, + stage_name: &str, +) { + match slot_info.duration_remaining() { + None => { + info!("No time remaining in slot (id: {:?}, stage: {})", slot_info.slot, stage_name); + }, + Some(remainder) => { + trace!( + "Remaining time in slot (id: {:?}, stage {}): {} ms, {}% of slot time", + slot_info.slot, + stage_name, + remainder.as_millis(), + (remainder.as_millis() as f64 / slot_info.duration.as_millis() as f64) * 100f64 + ); + }, + }; +} diff --git a/bitacross-worker/enclave-runtime/src/utils.rs b/bitacross-worker/enclave-runtime/src/utils.rs new file mode 100644 index 0000000000..47ff73ce26 --- /dev/null +++ b/bitacross-worker/enclave-runtime/src/utils.rs @@ -0,0 +1,279 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{ + error::{Error, Result}, + initialization::global_components::{ + EnclaveExtrinsicsFactory, EnclaveNodeMetadataRepository, EnclaveStfEnclaveSigner, + EnclaveStfExecutor, EnclaveValidatorAccessor, + IntegriteeParentchainTriggeredBlockImportDispatcher, + TargetAParentchainTriggeredBlockImportDispatcher, + TargetBParentchainTriggeredBlockImportDispatcher, + GLOBAL_INTEGRITEE_PARACHAIN_HANDLER_COMPONENT, + GLOBAL_INTEGRITEE_SOLOCHAIN_HANDLER_COMPONENT, GLOBAL_TARGET_A_PARACHAIN_HANDLER_COMPONENT, + GLOBAL_TARGET_A_SOLOCHAIN_HANDLER_COMPONENT, GLOBAL_TARGET_B_PARACHAIN_HANDLER_COMPONENT, + GLOBAL_TARGET_B_SOLOCHAIN_HANDLER_COMPONENT, + }, +}; +use codec::{Decode, Input}; +use itc_parentchain_block_import_dispatcher::BlockImportDispatcher; +use itp_component_container::ComponentGetter; +use std::{result::Result as StdResult, slice, sync::Arc}; + +/// Helper trait to transform the sgx-ffi pointers to any type that implements +/// `parity-scale-codec::Decode` +pub unsafe trait DecodeRaw { + /// the type to decode into + type Decoded: Decode; + + unsafe fn decode_raw<'a, T>( + data: *const T, + len: usize, + ) -> StdResult + where + T: 'a, + &'a [T]: Input; +} + +unsafe impl DecodeRaw for D { + type Decoded = D; + + unsafe fn decode_raw<'a, T>( + data: *const T, + len: usize, + ) -> StdResult + where + T: 'a, + &'a [T]: Input, + { + let mut s = slice::from_raw_parts(data, len); + + Decode::decode(&mut s) + } +} + +pub unsafe fn utf8_str_from_raw<'a>( + data: *const u8, + len: usize, +) -> StdResult<&'a str, std::str::Utf8Error> { + let bytes = slice::from_raw_parts(data, len); + + std::str::from_utf8(bytes) +} + +// FIXME: When solving #1080, these helper functions should be obsolete, because no dynamic allocation +// is necessary anymore. +pub(crate) fn get_triggered_dispatcher_from_integritee_solo_or_parachain( +) -> Result> { + let dispatcher = + if let Ok(solochain_handler) = GLOBAL_INTEGRITEE_SOLOCHAIN_HANDLER_COMPONENT.get() { + get_triggered_dispatcher(solochain_handler.import_dispatcher.clone())? + } else if let Ok(parachain_handler) = GLOBAL_INTEGRITEE_PARACHAIN_HANDLER_COMPONENT.get() { + get_triggered_dispatcher(parachain_handler.import_dispatcher.clone())? + } else { + return Err(Error::NoLitentryParentchainAssigned) + }; + Ok(dispatcher) +} + +pub(crate) fn get_triggered_dispatcher_from_target_a_solo_or_parachain( +) -> Result> { + let dispatcher = + if let Ok(solochain_handler) = GLOBAL_TARGET_A_SOLOCHAIN_HANDLER_COMPONENT.get() { + get_triggered_dispatcher(solochain_handler.import_dispatcher.clone())? + } else if let Ok(parachain_handler) = GLOBAL_TARGET_A_PARACHAIN_HANDLER_COMPONENT.get() { + get_triggered_dispatcher(parachain_handler.import_dispatcher.clone())? + } else { + return Err(Error::NoTargetAParentchainAssigned) + }; + Ok(dispatcher) +} + +pub(crate) fn get_triggered_dispatcher_from_target_b_solo_or_parachain( +) -> Result> { + let dispatcher = + if let Ok(solochain_handler) = GLOBAL_TARGET_B_SOLOCHAIN_HANDLER_COMPONENT.get() { + get_triggered_dispatcher(solochain_handler.import_dispatcher.clone())? + } else if let Ok(parachain_handler) = GLOBAL_TARGET_B_PARACHAIN_HANDLER_COMPONENT.get() { + get_triggered_dispatcher(parachain_handler.import_dispatcher.clone())? + } else { + return Err(Error::NoTargetBParentchainAssigned) + }; + Ok(dispatcher) +} + +pub(crate) fn get_triggered_dispatcher( + dispatcher: Arc>, +) -> Result> { + let triggered_dispatcher = dispatcher + .triggered_dispatcher() + .ok_or(Error::ExpectedTriggeredImportDispatcher)?; + Ok(triggered_dispatcher) +} + +pub(crate) fn get_validator_accessor_from_integritee_solo_or_parachain( +) -> Result> { + let validator_accessor = + if let Ok(solochain_handler) = GLOBAL_INTEGRITEE_SOLOCHAIN_HANDLER_COMPONENT.get() { + solochain_handler.validator_accessor.clone() + } else if let Ok(parachain_handler) = GLOBAL_INTEGRITEE_PARACHAIN_HANDLER_COMPONENT.get() { + parachain_handler.validator_accessor.clone() + } else { + return Err(Error::NoLitentryParentchainAssigned) + }; + Ok(validator_accessor) +} + +pub(crate) fn get_validator_accessor_from_target_a_solo_or_parachain( +) -> Result> { + let validator_accessor = + if let Ok(solochain_handler) = GLOBAL_TARGET_A_SOLOCHAIN_HANDLER_COMPONENT.get() { + solochain_handler.validator_accessor.clone() + } else if let Ok(parachain_handler) = GLOBAL_TARGET_A_PARACHAIN_HANDLER_COMPONENT.get() { + parachain_handler.validator_accessor.clone() + } else { + return Err(Error::NoTargetAParentchainAssigned) + }; + Ok(validator_accessor) +} + +pub(crate) fn get_validator_accessor_from_target_b_solo_or_parachain( +) -> Result> { + let validator_accessor = + if let Ok(solochain_handler) = GLOBAL_TARGET_B_SOLOCHAIN_HANDLER_COMPONENT.get() { + solochain_handler.validator_accessor.clone() + } else if let Ok(parachain_handler) = GLOBAL_TARGET_B_PARACHAIN_HANDLER_COMPONENT.get() { + parachain_handler.validator_accessor.clone() + } else { + return Err(Error::NoTargetBParentchainAssigned) + }; + Ok(validator_accessor) +} + +pub(crate) fn get_node_metadata_repository_from_integritee_solo_or_parachain( +) -> Result> { + let metadata_repository = + if let Ok(solochain_handler) = GLOBAL_INTEGRITEE_SOLOCHAIN_HANDLER_COMPONENT.get() { + solochain_handler.node_metadata_repository.clone() + } else if let Ok(parachain_handler) = GLOBAL_INTEGRITEE_PARACHAIN_HANDLER_COMPONENT.get() { + parachain_handler.node_metadata_repository.clone() + } else { + return Err(Error::NoLitentryParentchainAssigned) + }; + Ok(metadata_repository) +} + +pub(crate) fn get_node_metadata_repository_from_target_a_solo_or_parachain( +) -> Result> { + let metadata_repository = + if let Ok(solochain_handler) = GLOBAL_TARGET_A_SOLOCHAIN_HANDLER_COMPONENT.get() { + solochain_handler.node_metadata_repository.clone() + } else if let Ok(parachain_handler) = GLOBAL_TARGET_A_PARACHAIN_HANDLER_COMPONENT.get() { + parachain_handler.node_metadata_repository.clone() + } else { + return Err(Error::NoTargetAParentchainAssigned) + }; + Ok(metadata_repository) +} + +pub(crate) fn get_node_metadata_repository_from_target_b_solo_or_parachain( +) -> Result> { + let metadata_repository = + if let Ok(solochain_handler) = GLOBAL_TARGET_B_SOLOCHAIN_HANDLER_COMPONENT.get() { + solochain_handler.node_metadata_repository.clone() + } else if let Ok(parachain_handler) = GLOBAL_TARGET_B_PARACHAIN_HANDLER_COMPONENT.get() { + parachain_handler.node_metadata_repository.clone() + } else { + return Err(Error::NoTargetBParentchainAssigned) + }; + Ok(metadata_repository) +} + +pub(crate) fn get_extrinsic_factory_from_integritee_solo_or_parachain( +) -> Result> { + let extrinsics_factory = + if let Ok(solochain_handler) = GLOBAL_INTEGRITEE_SOLOCHAIN_HANDLER_COMPONENT.get() { + solochain_handler.extrinsics_factory.clone() + } else if let Ok(parachain_handler) = GLOBAL_INTEGRITEE_PARACHAIN_HANDLER_COMPONENT.get() { + parachain_handler.extrinsics_factory.clone() + } else { + return Err(Error::NoLitentryParentchainAssigned) + }; + Ok(extrinsics_factory) +} + +pub(crate) fn get_extrinsic_factory_from_target_a_solo_or_parachain( +) -> Result> { + let extrinsics_factory = + if let Ok(solochain_handler) = GLOBAL_TARGET_A_SOLOCHAIN_HANDLER_COMPONENT.get() { + solochain_handler.extrinsics_factory.clone() + } else if let Ok(parachain_handler) = GLOBAL_TARGET_A_PARACHAIN_HANDLER_COMPONENT.get() { + parachain_handler.extrinsics_factory.clone() + } else { + return Err(Error::NoTargetAParentchainAssigned) + }; + Ok(extrinsics_factory) +} + +pub(crate) fn get_extrinsic_factory_from_target_b_solo_or_parachain( +) -> Result> { + let extrinsics_factory = + if let Ok(solochain_handler) = GLOBAL_TARGET_B_SOLOCHAIN_HANDLER_COMPONENT.get() { + solochain_handler.extrinsics_factory.clone() + } else if let Ok(parachain_handler) = GLOBAL_TARGET_B_PARACHAIN_HANDLER_COMPONENT.get() { + parachain_handler.extrinsics_factory.clone() + } else { + return Err(Error::NoTargetBParentchainAssigned) + }; + Ok(extrinsics_factory) +} + +pub(crate) fn get_stf_executor_from_solo_or_parachain() -> Result> { + let stf_executor = + if let Ok(solochain_handler) = GLOBAL_INTEGRITEE_SOLOCHAIN_HANDLER_COMPONENT.get() { + solochain_handler.stf_executor.clone() + } else if let Ok(parachain_handler) = GLOBAL_INTEGRITEE_PARACHAIN_HANDLER_COMPONENT.get() { + parachain_handler.stf_executor.clone() + } else { + return Err(Error::NoLitentryParentchainAssigned) + }; + Ok(stf_executor) +} + +pub(crate) fn get_stf_enclave_signer_from_solo_or_parachain() -> Result> +{ + let stf_enclave_signer = + if let Ok(solochain_handler) = GLOBAL_INTEGRITEE_SOLOCHAIN_HANDLER_COMPONENT.get() { + match &*solochain_handler.import_dispatcher { + BlockImportDispatcher::TriggeredDispatcher(dispatcher) => + dispatcher.block_importer.indirect_calls_executor.stf_enclave_signer.clone(), + BlockImportDispatcher::ImmediateDispatcher(dispatcher) => + dispatcher.block_importer.indirect_calls_executor.stf_enclave_signer.clone(), + _ => return Err(Error::NoLitentryParentchainAssigned), + } + } else if let Ok(parachain_handler) = GLOBAL_INTEGRITEE_PARACHAIN_HANDLER_COMPONENT.get() { + match &*parachain_handler.import_dispatcher { + BlockImportDispatcher::TriggeredDispatcher(dispatcher) => + dispatcher.block_importer.indirect_calls_executor.stf_enclave_signer.clone(), + BlockImportDispatcher::ImmediateDispatcher(dispatcher) => + dispatcher.block_importer.indirect_calls_executor.stf_enclave_signer.clone(), + _ => return Err(Error::NoLitentryParentchainAssigned), + } + } else { + return Err(Error::NoLitentryParentchainAssigned) + }; + Ok(stf_enclave_signer) +} diff --git a/bitacross-worker/enclave-runtime/src/vc_issuance_task.rs b/bitacross-worker/enclave-runtime/src/vc_issuance_task.rs new file mode 100644 index 0000000000..e69de29bb2 diff --git a/bitacross-worker/enclave-runtime/x86_64-unknown-linux-sgx.json b/bitacross-worker/enclave-runtime/x86_64-unknown-linux-sgx.json new file mode 100644 index 0000000000..10d37a7490 --- /dev/null +++ b/bitacross-worker/enclave-runtime/x86_64-unknown-linux-sgx.json @@ -0,0 +1,31 @@ +{ + "arch": "x86_64", + "cpu": "x86-64", + "data-layout": "e-m:e-i64:64-f80:128-n8:16:32:64-S128", + "dynamic-linking": true, + "env": "sgx", + "exe-allocation-crate": "alloc_system", + "executables": true, + "has-elf-tls": true, + "has-rpath": true, + "linker-flavor": "gcc", + "linker-is-gnu": true, + "llvm-target": "x86_64-unknown-linux-gnu", + "max-atomic-width": 64, + "os": "linux", + "position-independent-executables": true, + "pre-link-args": { + "gcc": [ + "-Wl,--as-needed", + "-Wl,-z,noexecstack", + "-m64" + ] + }, + "relro-level": "full", + "stack-probes": true, + "target-c-int-width": "32", + "target-endian": "little", + "target-family": "unix", + "target-pointer-width": "64", + "vendor": "mesalock" +} diff --git a/bitacross-worker/extract_identity b/bitacross-worker/extract_identity new file mode 100755 index 0000000000..2c79268c15 --- /dev/null +++ b/bitacross-worker/extract_identity @@ -0,0 +1,28 @@ +#!/usr/bin/python3 + +import argparse + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument('--mrsigner', action="store_true") + args = parser.parse_args() + + line = "" + + searched_header = "enclave_hash.m" + output_header = "MRENCLAVE" + if args.mrsigner: + searched_header = "mrsigner->value" + output_header = "MRSIGNER" + while searched_header not in line: + line = input() + value = list() + line = input() + while line.startswith("0x"): + value += line.strip().split() + try: + line = input() + except: + break + value = "".join(map(lambda x: x.replace("0x",""), value)) +print("{}: {}".format(output_header, value)) diff --git a/bitacross-worker/lib/readme.txt b/bitacross-worker/lib/readme.txt new file mode 100644 index 0000000000..7951405f85 --- /dev/null +++ b/bitacross-worker/lib/readme.txt @@ -0,0 +1 @@ +lib \ No newline at end of file diff --git a/bitacross-worker/license_header_scs.txt b/bitacross-worker/license_header_scs.txt new file mode 100644 index 0000000000..6ded8ce2fd --- /dev/null +++ b/bitacross-worker/license_header_scs.txt @@ -0,0 +1,16 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ \ No newline at end of file diff --git a/bitacross-worker/litentry/core/scheduled-enclave/Cargo.toml b/bitacross-worker/litentry/core/scheduled-enclave/Cargo.toml new file mode 100644 index 0000000000..8e6f1904e7 --- /dev/null +++ b/bitacross-worker/litentry/core/scheduled-enclave/Cargo.toml @@ -0,0 +1,37 @@ +[package] +name = "lc-scheduled-enclave" +version = "0.8.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +codec = { version = "3.0.0", default-features = false, features = ["derive"], package = "parity-scale-codec" } +lazy_static = { version = "1.1.0", features = ["spin_no_std"] } +log = { version = "0.4", default-features = false } +sp-std = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } +thiserror = { version = "1.0.26", optional = true } + +# sgx-deps +sgx_tstd = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git", features = ["untrusted_fs"], optional = true } +thiserror-sgx = { package = "thiserror", git = "https://github.com/mesalock-linux/thiserror-sgx", tag = "sgx_1.1.3", optional = true } + +# local dependencies +itp-settings = { path = "../../../core-primitives/settings" } +itp-sgx-io = { path = "../../../core-primitives/sgx/io", default-features = false } +itp-types = { path = "../../../core-primitives/types", default-features = false } + +[features] +default = ["std"] +sgx = [ + "sgx_tstd", + "thiserror-sgx", + "itp-sgx-io/sgx", +] +std = [ + "thiserror", + "itp-sgx-io/std", + "itp-types/std", + "sp-std/std", + "codec/std", +] diff --git a/bitacross-worker/litentry/core/scheduled-enclave/src/error.rs b/bitacross-worker/litentry/core/scheduled-enclave/src/error.rs new file mode 100644 index 0000000000..6353db15f5 --- /dev/null +++ b/bitacross-worker/litentry/core/scheduled-enclave/src/error.rs @@ -0,0 +1,51 @@ +// Copyright 2020-2023 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . + +use std::boxed::Box; +#[cfg(feature = "sgx")] +use thiserror_sgx as thiserror; + +pub type Result = core::result::Result; + +#[derive(Debug, thiserror::Error)] +pub enum Error { + #[error("poison lock")] + PoisonLock, + #[error("empty ScheduledEnclave registry")] + EmptyRegistry, + #[error("no previous MRENCLAVE")] + NoPreviousMRENCLAVE, + #[error(transparent)] + Other(#[from] Box), +} + +impl From for Error { + fn from(e: std::io::Error) -> Self { + Self::Other(e.into()) + } +} + +impl From for Error { + #[cfg(feature = "std")] + fn from(e: codec::Error) -> Self { + Self::Other(e.into()) + } + + #[cfg(feature = "sgx")] + fn from(e: codec::Error) -> Self { + Self::Other(std::format!("{:?}", e).into()) + } +} diff --git a/bitacross-worker/litentry/core/scheduled-enclave/src/io.rs b/bitacross-worker/litentry/core/scheduled-enclave/src/io.rs new file mode 100644 index 0000000000..9912fe4a6f --- /dev/null +++ b/bitacross-worker/litentry/core/scheduled-enclave/src/io.rs @@ -0,0 +1,179 @@ +// Copyright 2020-2023 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . + +#[cfg(all(feature = "std", feature = "sgx"))] +compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the same time"); + +use crate::{ + error::{Error, Result}, + MrEnclave, ScheduledEnclave, ScheduledEnclaveUpdater, SidechainBlockNumber, + GLOBAL_SCHEDULED_ENCLAVE, +}; + +#[cfg(feature = "sgx")] +mod sgx { + use crate::{ + error::{Error, Result}, + ScheduledEnclaveMap, + }; + pub use codec::{Decode, Encode}; + pub use itp_settings::files::SCHEDULED_ENCLAVE_FILE; + pub use itp_sgx_io::{seal, unseal, SealedIO}; + pub use log::*; + pub use std::{boxed::Box, fs, path::PathBuf, sgxfs::SgxFile, sync::Arc}; + + #[derive(Clone, Debug)] + pub struct ScheduledEnclaveSeal { + base_path: PathBuf, + } + + impl ScheduledEnclaveSeal { + pub fn new(base_path: PathBuf) -> Self { + Self { base_path } + } + + pub fn path(&self) -> PathBuf { + self.base_path.join(SCHEDULED_ENCLAVE_FILE) + } + } + + impl SealedIO for ScheduledEnclaveSeal { + type Error = Error; + type Unsealed = ScheduledEnclaveMap; + + fn unseal(&self) -> Result { + Ok(unseal(self.path()).map(|b| Decode::decode(&mut b.as_slice()))??) + } + + fn seal(&self, unsealed: &Self::Unsealed) -> Result<()> { + info!("Seal scheduled enclave to file: {:?}", unsealed); + Ok(unsealed.using_encoded(|bytes| seal(bytes, self.path()))?) + } + } +} + +#[cfg(feature = "sgx")] +use sgx::*; + +// TODO: unit-test +impl ScheduledEnclaveUpdater for ScheduledEnclave { + #[cfg(feature = "std")] + fn init(&self, _mrenclave: MrEnclave) -> Result<()> { + Ok(()) + } + + #[cfg(feature = "std")] + fn update(&self, _sbn: SidechainBlockNumber, _mrenclave: MrEnclave) -> Result<()> { + Ok(()) + } + + #[cfg(feature = "std")] + fn remove(&self, _sbn: SidechainBlockNumber) -> Result<()> { + Ok(()) + } + + // if `SCHEDULED_ENCLAVE_FILE` exists, unseal and init from it + // otherwise create a new instance and seal to static file + #[cfg(feature = "sgx")] + fn init(&self, mrenclave: MrEnclave) -> Result<()> { + let _ = self.set_current_mrenclave(mrenclave)?; + let _ = self.set_block_production_paused(false)?; + let enclave_seal = ScheduledEnclaveSeal::new(self.seal_path.clone()); + if SgxFile::open(SCHEDULED_ENCLAVE_FILE).is_err() { + info!( + "[Enclave] ScheduledEnclave file not found, creating new! {}", + SCHEDULED_ENCLAVE_FILE + ); + let mut registry = + GLOBAL_SCHEDULED_ENCLAVE.registry.write().map_err(|_| Error::PoisonLock)?; + registry.clear(); + registry.insert(0, mrenclave); + enclave_seal.seal(&*registry) + } else { + let m = enclave_seal.unseal()?; + info!("[Enclave] ScheduledEnclave unsealed from file: {:?}", m); + let mut registry = + GLOBAL_SCHEDULED_ENCLAVE.registry.write().map_err(|_| Error::PoisonLock)?; + *registry = m; + Ok(()) + } + } + + #[cfg(feature = "sgx")] + fn update(&self, sbn: SidechainBlockNumber, mrenclave: MrEnclave) -> Result<()> { + let mut registry = + GLOBAL_SCHEDULED_ENCLAVE.registry.write().map_err(|_| Error::PoisonLock)?; + registry.insert(sbn, mrenclave); + ScheduledEnclaveSeal::new(self.seal_path.clone()).seal(&*registry) + } + + #[cfg(feature = "sgx")] + fn remove(&self, sbn: SidechainBlockNumber) -> Result<()> { + let mut registry = + GLOBAL_SCHEDULED_ENCLAVE.registry.write().map_err(|_| Error::PoisonLock)?; + let old_value = registry.remove(&sbn); + if old_value.is_some() { + return ScheduledEnclaveSeal::new(self.seal_path.clone()).seal(&*registry) + } + Ok(()) + } + + fn get_current_mrenclave(&self) -> Result { + self.current_mrenclave.read().map_err(|_| Error::PoisonLock).map(|l| *l) + } + + fn set_current_mrenclave(&self, mrenclave: MrEnclave) -> Result<()> { + let mut m = self.current_mrenclave.write().map_err(|_| Error::PoisonLock)?; + *m = mrenclave; + Ok(()) + } + + fn get_expected_mrenclave(&self, sbn: SidechainBlockNumber) -> Result { + let registry = GLOBAL_SCHEDULED_ENCLAVE.registry.read().map_err(|_| Error::PoisonLock)?; + let r = registry + .iter() + .filter(|(k, _)| **k <= sbn) + .max_by_key(|(k, _)| **k) + .ok_or(Error::EmptyRegistry)?; + Ok(*r.1) + } + + fn get_previous_mrenclave(&self, sbn: SidechainBlockNumber) -> Result { + // TODO: optimise it + let registry = GLOBAL_SCHEDULED_ENCLAVE.registry.read().map_err(|_| Error::PoisonLock)?; + let r = registry + .iter() + .filter(|(k, _)| **k <= sbn) + .max_by_key(|(k, _)| **k) + .ok_or(Error::NoPreviousMRENCLAVE)?; + let v = registry + .iter() + .filter(|(k, _)| **k < *r.0) + .max_by_key(|(k, _)| **k) + .ok_or(Error::NoPreviousMRENCLAVE)?; + Ok(*v.1) + } + + fn is_block_production_paused(&self) -> Result { + self.block_production_paused.read().map_err(|_| Error::PoisonLock).map(|l| *l) + } + + fn set_block_production_paused(&self, should_pause: bool) -> Result<()> { + let mut p = self.block_production_paused.write().map_err(|_| Error::PoisonLock)?; + *p = should_pause; + Ok(()) + } +} diff --git a/bitacross-worker/litentry/core/scheduled-enclave/src/lib.rs b/bitacross-worker/litentry/core/scheduled-enclave/src/lib.rs new file mode 100644 index 0000000000..e71edfb88a --- /dev/null +++ b/bitacross-worker/litentry/core/scheduled-enclave/src/lib.rs @@ -0,0 +1,153 @@ +// Copyright 2020-2023 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . + +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg(all(feature = "std", feature = "sgx"))] +compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the same time"); + +#[cfg(feature = "sgx")] +extern crate sgx_tstd as std; + +// TODO: maybe use parachain primitives for single source of truth +use itp_types::{MrEnclave, SidechainBlockNumber}; +use sp_std::collections::btree_map::BTreeMap; +use std::path::PathBuf; + +pub mod error; +use error::Result; +pub mod io; + +#[cfg(feature = "std")] +use std::sync::RwLock; +#[cfg(feature = "sgx")] +use std::sync::SgxRwLock as RwLock; + +use lazy_static::lazy_static; +use std::sync::Arc; + +lazy_static! { + /// Global instance of a ScheduledEnclave + pub static ref GLOBAL_SCHEDULED_ENCLAVE: Arc = Default::default(); +} + +pub type ScheduledEnclaveMap = BTreeMap; + +#[derive(Default)] +pub struct ScheduledEnclave { + pub block_production_paused: RwLock, + pub current_mrenclave: RwLock, + pub registry: RwLock, + pub seal_path: PathBuf, +} + +pub trait ScheduledEnclaveUpdater { + fn init(&self, mrenclave: MrEnclave) -> Result<()>; + + fn update(&self, sbn: SidechainBlockNumber, mrenclave: MrEnclave) -> Result<()>; + + fn remove(&self, sbn: SidechainBlockNumber) -> Result<()>; + + fn get_current_mrenclave(&self) -> Result; + + fn set_current_mrenclave(&self, mrenclave: MrEnclave) -> Result<()>; + + // given a SidechainBlockNumber, return the expected MRENCLAVE + // For example, the registry is: + // 0 -> 0xAA + // 19 -> 0xBB + // 21 -> 0xCC + // + // get_expected_mrenclave(0) -> 0xAA + // get_expected_mrenclave(18) -> 0xAA + // get_expected_mrenclave(19) -> 0xBB + // get_expected_mrenclave(20) -> 0xBB + // get_expected_mrenclave(21) -> 0xCC + // get_expected_mrenclave(30) -> 0xCC + fn get_expected_mrenclave(&self, sbn: SidechainBlockNumber) -> Result; + + // given a SidechainBlockNumber, return the previous MRENCLAVE + // we can't simply use `get_previous_mrenclave(sbn - 1)` due to possible gap + // For example, the registry is: + // 0 -> 0xAA + // 19 -> 0xBB + // 21 -> 0xCC + // + // get_previous_mrenclave(0) -> NoPreviousMRENCLAVE error + // get_previous_mrenclave(1) -> NoPreviousMRENCLAVE error + // get_previous_mrenclave(19) -> 0xAA + // get_previous_mrenclave(20) -> 0xAA + // get_previous_mrenclave(21) -> 0xBB + // get_previous_mrenclave(30) -> 0xBB + fn get_previous_mrenclave(&self, sbn: SidechainBlockNumber) -> Result; + + fn is_block_production_paused(&self) -> Result; + + fn set_block_production_paused(&self, should_pause: bool) -> Result<()>; + + fn is_mrenclave_matching(&self, sbn: SidechainBlockNumber) -> bool { + let current = self.get_current_mrenclave(); + let expected = self.get_expected_mrenclave(sbn); + + if current.is_err() || expected.is_err() { + return false + } + + current.unwrap() == expected.unwrap() + } +} + +#[derive(Default)] +pub struct ScheduledEnclaveMock; + +// todo! +impl ScheduledEnclaveUpdater for ScheduledEnclaveMock { + fn init(&self, _mrenclave: MrEnclave) -> Result<()> { + Ok(()) + } + + fn update(&self, _sbn: SidechainBlockNumber, _mrenclave: MrEnclave) -> Result<()> { + Ok(()) + } + + fn remove(&self, _sbn: SidechainBlockNumber) -> Result<()> { + Ok(()) + } + + fn get_current_mrenclave(&self) -> Result { + Ok(MrEnclave::default()) + } + + fn set_current_mrenclave(&self, _mrenclave: MrEnclave) -> Result<()> { + Ok(()) + } + + fn get_expected_mrenclave(&self, _sbn: SidechainBlockNumber) -> Result { + Ok(MrEnclave::default()) + } + + fn get_previous_mrenclave(&self, _sbn: SidechainBlockNumber) -> Result { + Ok(MrEnclave::default()) + } + + fn is_block_production_paused(&self) -> Result { + Ok(false) + } + + fn set_block_production_paused(&self, _should_pause: bool) -> Result<()> { + Ok(()) + } +} diff --git a/bitacross-worker/litentry/macros/Cargo.toml b/bitacross-worker/litentry/macros/Cargo.toml new file mode 100644 index 0000000000..c3039927e1 --- /dev/null +++ b/bitacross-worker/litentry/macros/Cargo.toml @@ -0,0 +1,12 @@ +[package] +authors = ["Trust Computing GmbH "] +name = "litentry-macros" +version = "0.1.0" +edition = "2021" + +[dependencies] +cargo_toml = "0.16.3" +quote = "1.0.33" + +[lib] +proc-macro = true diff --git a/bitacross-worker/litentry/macros/src/lib.rs b/bitacross-worker/litentry/macros/src/lib.rs new file mode 100644 index 0000000000..b57ac19473 --- /dev/null +++ b/bitacross-worker/litentry/macros/src/lib.rs @@ -0,0 +1,59 @@ +// Copyright 2020-2023 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . + +use cargo_toml::{Dependency, Manifest}; +use proc_macro::TokenStream; +use quote::quote; +use std::fs; + +#[proc_macro] +pub fn local_modules(_item: TokenStream) -> TokenStream { + let mut deps: Vec = vec![]; + read_module_names("", ".", &mut deps); + let output = quote! { + { + let deps: Vec<&str> = vec![ + #(#deps),* + ]; + deps + } + }; + output.into() +} + +fn read_module_names(path: &str, relative_to: &str, module_names: &mut Vec) { + let current_path = relative_to.to_string() + "/" + path; + let cargo_file = current_path.to_string() + "/Cargo.toml"; + let contents = fs::read_to_string(&cargo_file) + .unwrap_or_else(|_| panic!("Should have been able to read the file: {}", cargo_file)); + let manifest = Manifest::from_str(&contents) + .unwrap_or_else(|_| panic!("Could not parse manifest file locate at {}", cargo_file)); + if let Some(package) = manifest.package { + let module_name = package.name.replace('-', "_"); + // skip package if it is unnamed or it was already visited + if !package.name.is_empty() && !module_names.contains(&module_name) { + module_names.push(module_name); + // go through all dependencies and visit the ones that has `path`, which means they are local + manifest.dependencies.values().for_each(|dep| { + if let Dependency::Detailed(details) = dep { + if let Some(path) = &details.path { + read_module_names(path, ¤t_path, module_names) + } + } + }); + } + } +} diff --git a/bitacross-worker/litentry/primitives/Cargo.toml b/bitacross-worker/litentry/primitives/Cargo.toml new file mode 100644 index 0000000000..2ad014ae67 --- /dev/null +++ b/bitacross-worker/litentry/primitives/Cargo.toml @@ -0,0 +1,64 @@ +[package] +authors = ["Trust Computing GmbH "] +edition = "2021" +name = "litentry-primitives" +version = "0.1.0" + +[dependencies] +bitcoin = { version = "0.31.0", default-features = false, features = ["secp-recovery", "no-std"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +hex = { version = "0.4.3", default-features = false } +log = { version = "0.4", default-features = false } +pallet-evm = { default-features = false, git = "https://github.com/integritee-network/frontier.git", branch = "bar/polkadot-v0.9.42" } +rand = { version = "0.7", optional = true } +rand-sgx = { package = "rand", git = "https://github.com/mesalock-linux/rand-sgx", tag = "sgx_1.1.3", features = ["sgx_tstd"], optional = true } +ring = { version = "0.16.20", default-features = false } +scale-info = { version = "2.4.0", default-features = false, features = ["derive"] } +secp256k1 = { version = "0.28.0", default-features = false } +serde = { version = "1.0", default-features = false, features = ["alloc", "derive"] } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42", default-features = false } +sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42", default-features = false } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42", default-features = false } +sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42", default-features = false } +strum = { version = "0.25.0", default-features = false } +strum_macros = { version = "0.25.0", default-features = false } + +# sgx dependencies +base64_sgx = { package = "base64", rev = "sgx_1.1.3", git = "https://github.com/mesalock-linux/rust-base64-sgx", optional = true } +sgx_tstd = { git = "https://github.com/apache/teaclave-sgx-sdk.git", branch = "master", optional = true, features = ["net", "thread"] } + +# internal dependencies +itp-sgx-crypto = { path = "../../core-primitives/sgx/crypto", default-features = false } +itp-utils = { path = "../../core-primitives/utils", default-features = false } +parentchain-primitives = { package = "core-primitives", path = "../../../primitives/core", default-features = false } +teerex-primitives = { path = "../../../primitives/teerex", default-features = false } + +[dev-dependencies] +base64 = { version = "0.13", features = ["alloc"] } + +[features] +default = ["std"] +production = [] +sgx = [ + "sgx_tstd", + "rand-sgx", + "itp-sgx-crypto/sgx", +] +std = [ + "strum/std", + "hex/std", + "serde/std", + "itp-sgx-crypto/std", + "itp-utils/std", + "sp-core/std", + "sp-std/std", + "sp-io/std", + "sp-runtime/std", + "ring/std", + "parentchain-primitives/std", + "teerex-primitives/std", + "rand", + "log/std", + "bitcoin/std", + "secp256k1/std", +] diff --git a/bitacross-worker/litentry/primitives/src/aes.rs b/bitacross-worker/litentry/primitives/src/aes.rs new file mode 100644 index 0000000000..d63b02432a --- /dev/null +++ b/bitacross-worker/litentry/primitives/src/aes.rs @@ -0,0 +1,134 @@ +// Copyright 2020-2023 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +extern crate sgx_tstd as std; + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +extern crate rand_sgx as rand; + +use crate::{Decode, Encode, Vec}; + +use rand::Rng; + +use ring::{ + aead::{Aad, BoundKey, LessSafeKey, Nonce, NonceSequence, SealingKey, UnboundKey, AES_256_GCM}, + error::Unspecified, +}; + +// we use 256-bit AES-GCM as request enc/dec key +pub const REQUEST_AES_KEY_LEN: usize = 32; +pub use ring::aead::{MAX_TAG_LEN, NONCE_LEN}; + +pub type RequestAesKey = [u8; REQUEST_AES_KEY_LEN]; +pub type RequestAesKeyNonce = [u8; NONCE_LEN]; + +// all-in-one struct containing the encrypted ciphertext with other +// metadata that is required for decryption +// +// by default a postfix tag is used => last 16 bytes of ciphertext is MAC tag +#[derive(Debug, Default, Clone, Eq, PartialEq, Encode, Decode)] +pub struct AesOutput { + pub ciphertext: Vec, + pub aad: Vec, + pub nonce: RequestAesKeyNonce, // IV +} + +// Returns the default if any error happens +// We don't propagate the error to upper level as this function is used in too many places, +// it's too verbose to handle them all and pass back to the parentchain as events. +// We rely on the parentchain event consumers to handle them correctly (and they kind of +// have to, because they'll find all fields are 0) +pub fn aes_encrypt_default(key: &RequestAesKey, data: &[u8]) -> AesOutput { + let mut in_out = data.to_vec(); + + let mut nonce = RingAeadNonceSequence::new(); + if nonce.advance().is_ok() { + let aad = b""; + if let Ok(unbound_key) = UnboundKey::new(&AES_256_GCM, key.as_slice()) { + let mut sealing_key = SealingKey::new(unbound_key, nonce.clone()); + if sealing_key.seal_in_place_append_tag(Aad::from(aad), &mut in_out).is_ok() { + return AesOutput { + ciphertext: in_out.to_vec(), + aad: aad.to_vec(), + nonce: nonce.nonce, + } + } + } + } + + AesOutput::default() +} + +// use LessSafeKey::seal_in_place_append_tag to encrypt the data using the given nonce +// don't be scared by the name, it's similar to `SealingKey::seal_in_place_append_tag`, +// except that it accepts an arbitrary nonce. +// It's only used by the one-off verification message calculation. +pub fn aes_encrypt_nonce(key: &RequestAesKey, data: &[u8], nonce: RequestAesKeyNonce) -> AesOutput { + let mut in_out = data.to_vec(); + let aad = b""; + if let Ok(unbound_key) = UnboundKey::new(&AES_256_GCM, key.as_slice()) { + let less_safe_key = LessSafeKey::new(unbound_key); + if less_safe_key + .seal_in_place_append_tag( + Nonce::assume_unique_for_key(nonce), + Aad::from(aad), + &mut in_out, + ) + .is_ok() + { + return AesOutput { ciphertext: in_out.to_vec(), aad: aad.to_vec(), nonce } + } + } + + AesOutput::default() +} + +pub fn aes_decrypt(key: &RequestAesKey, data: &mut AesOutput) -> Option> { + let in_out = data.ciphertext.as_mut(); + if let Ok(unbound_key) = UnboundKey::new(&AES_256_GCM, key.as_slice()) { + let less_safe_key = LessSafeKey::new(unbound_key); + return less_safe_key + .open_in_place( + Nonce::assume_unique_for_key(data.nonce), + Aad::from(data.aad.clone()), + in_out, + ) + .ok() + .map(|data| data.to_vec()) + } + None +} + +#[derive(Clone)] +pub struct RingAeadNonceSequence { + pub nonce: RequestAesKeyNonce, +} + +impl RingAeadNonceSequence { + fn new() -> RingAeadNonceSequence { + RingAeadNonceSequence { nonce: [0u8; NONCE_LEN] } + } +} + +impl NonceSequence for RingAeadNonceSequence { + fn advance(&mut self) -> Result { + let nonce = Nonce::assume_unique_for_key(self.nonce); + let nonce_vec = rand::thread_rng().gen::(); + self.nonce.copy_from_slice(&nonce_vec[0..NONCE_LEN]); + Ok(nonce) + } +} diff --git a/bitacross-worker/litentry/primitives/src/aes_request.rs b/bitacross-worker/litentry/primitives/src/aes_request.rs new file mode 100644 index 0000000000..7c133429e2 --- /dev/null +++ b/bitacross-worker/litentry/primitives/src/aes_request.rs @@ -0,0 +1,69 @@ +// Copyright 2020-2023 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +extern crate sgx_tstd as std; + +/// A morphling of itp_types::RsaRequest which stems from teerex_primitives::RsaRequest +/// +/// Instead of encrypting the TrustedCallSigned with the TEE's shielding key, we encrypt +/// it with a 32-byte ephemeral AES key which is generated from the client's side, and +/// send the encrypted payload together with the AES key encrypted using TEE's shielding key. +/// +/// After the enclave gets the request, it will decrypt to get the AES key and use that key +/// to decrypt the payload and decode it to get the real TrustedCall. +/// +/// The motivation of having such a struct is: +/// 1. RSA has a limitation of maximum allowed test to be encrypted. In our case, the encoded +/// `TrustedCallSigned` can exceed the limit, AES doesn't have such problem. +/// +/// 2. we want to efface the shielding key setup completely to achieve a better UE. +use crate::{ + aes_decrypt, AesOutput, Box, Debug, DecryptableRequest, RequestAesKey, ShardIdentifier, + ShieldingCryptoDecrypt, Vec, +}; +use codec::{Decode, Encode}; + +#[derive(Encode, Decode, Default, Clone, PartialEq, Eq, Debug)] +pub struct AesRequest { + pub shard: ShardIdentifier, + pub key: Vec, + pub payload: AesOutput, +} + +impl DecryptableRequest for AesRequest { + type Error = (); + + fn shard(&self) -> ShardIdentifier { + self.shard + } + + fn payload(&self) -> &[u8] { + self.payload.ciphertext.as_slice() + } + + fn decrypt( + &mut self, + enclave_shielding_key: Box>, + ) -> core::result::Result, ()> { + let aes_key: RequestAesKey = enclave_shielding_key + .decrypt(&self.key) + .map_err(|_| ())? + .try_into() + .map_err(|_| ())?; + aes_decrypt(&aes_key, &mut self.payload).ok_or(()) + } +} diff --git a/bitacross-worker/litentry/primitives/src/bitcoin_address.rs b/bitacross-worker/litentry/primitives/src/bitcoin_address.rs new file mode 100644 index 0000000000..32dcdcafcb --- /dev/null +++ b/bitacross-worker/litentry/primitives/src/bitcoin_address.rs @@ -0,0 +1,57 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 bitcoin::{ + address::Address, key::PublicKey, network::Network, secp256k1::Secp256k1, XOnlyPublicKey, +}; +use core::str::FromStr; +use std::string::{String, ToString}; + +// Some dependency conflict of bitcoin crate with enclave building +// when putting these functions into core-premitives/utils. +pub fn p2wpkh_address(pubkey_string: &str) -> String { + let pubkey = PublicKey::from_str(pubkey_string).expect("pubkey"); + let address = Address::p2wpkh(&pubkey, Network::Bitcoin); + if let Ok(address) = address { + return address.to_string() + } + "".to_string() +} + +pub fn p2sh_address(pubkey_string: &str) -> String { + let pubkey = PublicKey::from_str(pubkey_string).expect("pubkey"); + let address = Address::p2shwpkh(&pubkey, Network::Bitcoin); + if let Ok(address) = address { + return address.to_string() + } + "".to_string() +} + +pub fn p2tr_address(pubkey_string: &str) -> String { + let pubkey = PublicKey::from_str(pubkey_string).expect("pubkey"); + let xonly_pubkey = XOnlyPublicKey::from(pubkey.inner); + // unisat wallet uses is this way + let secp = Secp256k1::verification_only(); + let address = Address::p2tr(&secp, xonly_pubkey, None, Network::Bitcoin); + address.to_string() +} + +pub fn p2pkh_address(pubkey_string: &str) -> String { + let pubkey = PublicKey::from_str(pubkey_string).expect("pubkey"); + let address = Address::p2pkh(&pubkey, Network::Bitcoin); + address.to_string() +} diff --git a/bitacross-worker/litentry/primitives/src/bitcoin_signature.rs b/bitacross-worker/litentry/primitives/src/bitcoin_signature.rs new file mode 100644 index 0000000000..cb6db71a23 --- /dev/null +++ b/bitacross-worker/litentry/primitives/src/bitcoin_signature.rs @@ -0,0 +1,72 @@ +// Copyright 2020-2023 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . +#[cfg(feature = "std")] +use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; + +use codec::{Decode, Encode, MaxEncodedLen}; +use scale_info::TypeInfo; + +#[derive(Encode, Decode, MaxEncodedLen, TypeInfo, PartialEq, Eq, Clone, Debug)] +pub struct BitcoinSignature(pub [u8; 65]); + +impl TryFrom<&[u8]> for BitcoinSignature { + type Error = (); + + fn try_from(data: &[u8]) -> Result { + if data.len() == 65 { + let mut inner = [0u8; 65]; + inner.copy_from_slice(data); + Ok(BitcoinSignature(inner)) + } else { + Err(()) + } + } +} + +#[cfg(feature = "std")] +impl Serialize for BitcoinSignature { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + serializer.serialize_str(&hex::encode(self)) + } +} + +#[cfg(feature = "std")] +impl<'de> Deserialize<'de> for BitcoinSignature { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let signature_hex = hex::decode(&String::deserialize(deserializer)?) + .map_err(|e| de::Error::custom(format!("{:?}", e)))?; + BitcoinSignature::try_from(signature_hex.as_ref()) + .map_err(|e| de::Error::custom(format!("{:?}", e))) + } +} + +impl AsRef<[u8; 65]> for BitcoinSignature { + fn as_ref(&self) -> &[u8; 65] { + &self.0 + } +} + +impl AsRef<[u8]> for BitcoinSignature { + fn as_ref(&self) -> &[u8] { + &self.0[..] + } +} diff --git a/bitacross-worker/litentry/primitives/src/ethereum_signature.rs b/bitacross-worker/litentry/primitives/src/ethereum_signature.rs new file mode 100644 index 0000000000..75496fa61d --- /dev/null +++ b/bitacross-worker/litentry/primitives/src/ethereum_signature.rs @@ -0,0 +1,72 @@ +// Copyright 2020-2023 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . +#[cfg(feature = "std")] +use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; + +use codec::{Decode, Encode, MaxEncodedLen}; +use scale_info::TypeInfo; + +#[derive(Encode, Decode, MaxEncodedLen, TypeInfo, PartialEq, Eq, Clone, Debug)] +pub struct EthereumSignature(pub [u8; 65]); + +impl TryFrom<&[u8]> for EthereumSignature { + type Error = (); + + fn try_from(data: &[u8]) -> Result { + if data.len() == 65 { + let mut inner = [0u8; 65]; + inner.copy_from_slice(data); + Ok(EthereumSignature(inner)) + } else { + Err(()) + } + } +} + +#[cfg(feature = "std")] +impl Serialize for EthereumSignature { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + serializer.serialize_str(&hex::encode(self)) + } +} + +#[cfg(feature = "std")] +impl<'de> Deserialize<'de> for EthereumSignature { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let signature_hex = hex::decode(&String::deserialize(deserializer)?) + .map_err(|e| de::Error::custom(format!("{:?}", e)))?; + EthereumSignature::try_from(signature_hex.as_ref()) + .map_err(|e| de::Error::custom(format!("{:?}", e))) + } +} + +impl AsRef<[u8; 65]> for EthereumSignature { + fn as_ref(&self) -> &[u8; 65] { + &self.0 + } +} + +impl AsRef<[u8]> for EthereumSignature { + fn as_ref(&self) -> &[u8] { + &self.0[..] + } +} diff --git a/bitacross-worker/litentry/primitives/src/lib.rs b/bitacross-worker/litentry/primitives/src/lib.rs new file mode 100644 index 0000000000..b439190a30 --- /dev/null +++ b/bitacross-worker/litentry/primitives/src/lib.rs @@ -0,0 +1,279 @@ +// Copyright 2020-2023 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . + +#![cfg_attr(not(feature = "std"), no_std)] + +extern crate core; +#[cfg(all(not(feature = "std"), feature = "sgx"))] +extern crate sgx_tstd as std; + +#[cfg(all(feature = "std", feature = "sgx"))] +compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the same time"); + +mod aes; +mod aes_request; +mod bitcoin_address; +mod bitcoin_signature; +mod ethereum_signature; +mod validation_data; + +pub use aes::*; +pub use aes_request::*; +pub use bitcoin_address::*; +pub use bitcoin_signature::*; +pub use ethereum_signature::*; +use sp_std::{boxed::Box, fmt::Debug, vec::Vec}; +pub use validation_data::*; + +use bitcoin::sign_message::{signed_msg_hash, MessageSignature}; +use codec::{Decode, Encode, MaxEncodedLen}; +use itp_sgx_crypto::ShieldingCryptoDecrypt; +use itp_utils::hex::hex_encode; +use log::error; +pub use parentchain_primitives::{ + all_bitcoin_web3networks, all_evm_web3networks, all_substrate_web3networks, all_web3networks, + identity::*, AccountId as ParentchainAccountId, AchainableAmount, AchainableAmountHolding, + AchainableAmountToken, AchainableAmounts, AchainableBasic, AchainableBetweenPercents, + AchainableClassOfYear, AchainableDate, AchainableDateInterval, AchainableDatePercent, + AchainableMirror, AchainableParams, AchainableToken, AmountHoldingTimeType, Assertion, + Balance as ParentchainBalance, BlockNumber as ParentchainBlockNumber, BnbDigitDomainType, + BoundedWeb3Network, ContestType, EVMTokenType, ErrorDetail, ErrorString, + GenericDiscordRoleType, Hash as ParentchainHash, Header as ParentchainHeader, IMPError, + Index as ParentchainIndex, IntoErrorDetail, OneBlockCourseType, ParameterString, + SchemaContentString, SchemaIdString, Signature as ParentchainSignature, SoraQuizType, + VCMPError, VIP3MembershipCardLevel, Web3Network, MINUTES, +}; +use scale_info::TypeInfo; +use sp_core::{ecdsa, ed25519, sr25519, ByteArray}; +use sp_io::{ + crypto::secp256k1_ecdsa_recover, + hashing::{blake2_256, keccak_256}, +}; +use sp_runtime::traits::Verify; +use std::string::{String, ToString}; +pub use teerex_primitives::{decl_rsa_request, ShardIdentifier, SidechainBlockNumber}; + +#[cfg(feature = "std")] +use serde::{Deserialize, Serialize}; + +pub const LITENTRY_PRETTIFIED_MESSAGE_PREFIX: &str = "Litentry authorization token: "; + +#[derive(Encode, Decode, Clone, Debug, PartialEq, Eq, TypeInfo, MaxEncodedLen)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +pub enum LitentryMultiSignature { + /// An Ed25519 signature. + #[codec(index = 0)] + Ed25519(ed25519::Signature), + /// An Sr25519 signature. + #[codec(index = 1)] + Sr25519(sr25519::Signature), + /// An ECDSA/SECP256k1 signature. + #[codec(index = 2)] + Ecdsa(ecdsa::Signature), + /// An ECDSA/keccak256 signature. An Ethereum signature. hash message with keccak256 + #[codec(index = 3)] + Ethereum(EthereumSignature), + /// Same as above, but the payload bytes are prepended with a readable prefix and `0x` + #[codec(index = 4)] + EthereumPrettified(EthereumSignature), + /// Bitcoin signed message, a hex-encoded string of original &[u8] message, without `0x` prefix + #[codec(index = 5)] + Bitcoin(BitcoinSignature), + /// Same as above, but the payload bytes are prepended with a readable prefix and `0x` + #[codec(index = 6)] + BitcoinPrettified(BitcoinSignature), +} + +impl LitentryMultiSignature { + pub fn verify(&self, msg: &[u8], signer: &Identity) -> bool { + match signer { + Identity::Substrate(address) => + self.verify_substrate(substrate_wrap(msg).as_slice(), address) + || self.verify_substrate(msg, address), + Identity::Evm(address) => self.verify_evm(msg, address), + Identity::Bitcoin(address) => self.verify_bitcoin(msg, address), + _ => false, + } + } + + fn verify_substrate(&self, msg: &[u8], signer: &Address32) -> bool { + match (self, signer) { + (Self::Ed25519(ref sig), who) => match ed25519::Public::from_slice(who.as_ref()) { + Ok(signer) => sig.verify(msg, &signer), + Err(()) => false, + }, + (Self::Sr25519(ref sig), who) => match sr25519::Public::from_slice(who.as_ref()) { + Ok(signer) => sig.verify(msg, &signer), + Err(()) => false, + }, + (Self::Ecdsa(ref sig), who) => { + let m = blake2_256(msg); + match sp_io::crypto::secp256k1_ecdsa_recover_compressed(sig.as_ref(), &m) { + Ok(pubkey) => + &blake2_256(pubkey.as_ref()) == >::as_ref(who), + _ => false, + } + }, + _ => false, + } + } + + fn verify_evm(&self, msg: &[u8], signer: &Address20) -> bool { + match self { + Self::Ethereum(ref sig) => + return verify_evm_signature(evm_eip191_wrap(msg).as_slice(), sig, signer) + || verify_evm_signature(msg, sig, signer), + Self::EthereumPrettified(ref sig) => { + let prettified_msg = + LITENTRY_PRETTIFIED_MESSAGE_PREFIX.to_string() + &hex_encode(msg); + let msg = prettified_msg.as_bytes(); + return verify_evm_signature(evm_eip191_wrap(msg).as_slice(), sig, signer) + || verify_evm_signature(msg, sig, signer) + }, + _ => false, + } + } + + fn verify_bitcoin(&self, msg: &[u8], signer: &Address33) -> bool { + match self { + Self::Bitcoin(ref sig) => + verify_bitcoin_signature(hex::encode(msg).as_str(), sig, signer), + Self::BitcoinPrettified(ref sig) => { + let prettified_msg = + LITENTRY_PRETTIFIED_MESSAGE_PREFIX.to_string() + &hex_encode(msg); + verify_bitcoin_signature(prettified_msg.as_str(), sig, signer) + }, + _ => false, + } + } +} + +pub fn verify_evm_signature(msg: &[u8], sig: &EthereumSignature, who: &Address20) -> bool { + let digest = keccak_256(msg); + return match recover_evm_address(&digest, sig.as_ref()) { + Ok(recovered_evm_address) => recovered_evm_address == who.as_ref().as_slice(), + Err(_e) => { + error!("Could not verify evm signature msg: {:?}, signer {:?}", msg, who); + false + }, + } +} + +pub fn verify_bitcoin_signature(msg: &str, sig: &BitcoinSignature, who: &Address33) -> bool { + if let Ok(msg_sig) = MessageSignature::from_slice(sig.as_ref()) { + let msg_hash = signed_msg_hash(msg); + let secp = secp256k1::Secp256k1::new(); + return match msg_sig.recover_pubkey(&secp, msg_hash) { + Ok(recovered_pub_key) => &recovered_pub_key.inner.serialize() == who.as_ref(), + Err(_) => { + error!("Could not recover pubkey from bitcoin msg: {:?}, signer {:?}", msg, who); + false + }, + } + } + + false +} + +impl From for LitentryMultiSignature { + fn from(x: ed25519::Signature) -> Self { + Self::Ed25519(x) + } +} + +impl From for LitentryMultiSignature { + fn from(x: sr25519::Signature) -> Self { + Self::Sr25519(x) + } +} + +impl From for LitentryMultiSignature { + fn from(x: ecdsa::Signature) -> Self { + Self::Ecdsa(x) + } +} + +pub fn recover_evm_address( + msg: &[u8; 32], + sig: &[u8; 65], +) -> Result<[u8; 20], sp_io::EcdsaVerifyError> { + let pubkey = secp256k1_ecdsa_recover(sig, msg)?; + let hashed_pk = keccak_256(&pubkey); + + let mut addr = [0u8; 20]; + addr[..20].copy_from_slice(&hashed_pk[12..32]); + Ok(addr) +} + +// see https://github.com/litentry/litentry-parachain/issues/1137 +fn substrate_wrap(msg: &[u8]) -> Vec { + ["".as_bytes(), msg, "".as_bytes()].concat() +} + +// see https://github.com/litentry/litentry-parachain/issues/1970 +fn evm_eip191_wrap(msg: &[u8]) -> Vec { + ["\x19Ethereum Signed Message:\n".as_bytes(), msg.len().to_string().as_bytes(), msg].concat() +} + +pub type IdentityNetworkTuple = (Identity, Vec); + +// Represent a request that can be decrypted by the enclave +// Both itp_types::RsaRequest and AesRequest should impelement this +pub trait DecryptableRequest { + type Error; + // the shard getter + fn shard(&self) -> ShardIdentifier; + // the raw payload - AFAICT only used in mock + fn payload(&self) -> &[u8]; + // how to decrypt the payload + fn decrypt( + &mut self, + enclave_shielding_key: Box>, + ) -> Result, Self::Error>; +} + +pub struct BroadcastedRequest { + pub id: String, + pub payload: String, + pub rpc_method: String, +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn verify_bitcoin_signature_works() { + // generated by unisat-wallet API: https://docs.unisat.io/dev/unisat-developer-service/unisat-wallet + let msg: Vec = vec![ + 3, 93, 250, 112, 216, 101, 89, 57, 83, 88, 100, 252, 203, 15, 64, 127, 138, 37, 2, 40, + 147, 95, 245, 27, 97, 202, 62, 205, 151, 0, 175, 177, + ]; + let pubkey: Vec = vec![ + 3, 93, 250, 112, 216, 101, 89, 57, 83, 88, 100, 252, 203, 15, 64, 127, 138, 37, 2, 40, + 147, 95, 245, 27, 97, 202, 62, 205, 151, 0, 175, 177, 216, + ]; + let sig: Vec = base64::decode("G2LhyYzWT2o8UoBsuhJsqFgwm3tlE0cW4aseCXKqVuNATk6K/uEHlPzDFmtlMADywDHl5vLCWcNpwmQLD7n/yvc=").unwrap(); + + let pubkey_ref: &[u8] = pubkey.as_ref(); + let sig_ref: &[u8] = sig.as_ref(); + assert!(verify_bitcoin_signature( + hex::encode(msg).as_str(), + &sig_ref.try_into().unwrap(), + &pubkey_ref.try_into().unwrap() + )); + } +} diff --git a/bitacross-worker/litentry/primitives/src/validation_data.rs b/bitacross-worker/litentry/primitives/src/validation_data.rs new file mode 100644 index 0000000000..aac3427799 --- /dev/null +++ b/bitacross-worker/litentry/primitives/src/validation_data.rs @@ -0,0 +1,96 @@ +// Copyright 2020-2023 Trust Computing GmbH. +// This file is part of Litentry. +// +// Litentry is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Litentry is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Litentry. If not, see . + +#[cfg(feature = "std")] +use serde::{Deserialize, Serialize}; + +use crate::LitentryMultiSignature; +use codec::{Decode, Encode, MaxEncodedLen}; +use scale_info::TypeInfo; +use sp_runtime::{traits::ConstU32, BoundedVec}; + +pub type MaxStringLength = ConstU32<64>; +pub type ValidationString = BoundedVec; + +#[derive(Encode, Decode, Clone, Debug, PartialEq, Eq, TypeInfo, MaxEncodedLen)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +pub struct TwitterValidationData { + pub tweet_id: ValidationString, +} + +#[derive(Encode, Decode, Clone, Debug, PartialEq, Eq, TypeInfo, MaxEncodedLen)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +pub struct DiscordValidationData { + pub channel_id: ValidationString, + pub message_id: ValidationString, + pub guild_id: ValidationString, +} + +#[derive(Encode, Decode, Clone, Debug, PartialEq, Eq, TypeInfo, MaxEncodedLen)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +pub struct Web3CommonValidationData { + pub message: ValidationString, // or String if under std + pub signature: LitentryMultiSignature, +} + +#[derive(Encode, Decode, Clone, Debug, PartialEq, Eq, TypeInfo, MaxEncodedLen)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +#[allow(non_camel_case_types)] +pub enum Web2ValidationData { + #[codec(index = 0)] + Twitter(TwitterValidationData), + #[codec(index = 1)] + Discord(DiscordValidationData), +} + +#[derive(Encode, Decode, Clone, Debug, PartialEq, Eq, TypeInfo, MaxEncodedLen)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +#[allow(non_camel_case_types)] +pub enum Web3ValidationData { + #[codec(index = 0)] + Substrate(Web3CommonValidationData), + #[codec(index = 1)] + Evm(Web3CommonValidationData), + #[codec(index = 2)] + Bitcoin(Web3CommonValidationData), +} + +impl Web3ValidationData { + pub fn message(&self) -> &ValidationString { + match self { + Self::Substrate(data) => &data.message, + Self::Evm(data) => &data.message, + Self::Bitcoin(data) => &data.message, + } + } + + pub fn signature(&self) -> &LitentryMultiSignature { + match self { + Self::Substrate(data) => &data.signature, + Self::Evm(data) => &data.signature, + Self::Bitcoin(data) => &data.signature, + } + } +} + +#[derive(Encode, Decode, Clone, Debug, PartialEq, Eq, TypeInfo, MaxEncodedLen)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +pub enum ValidationData { + #[codec(index = 0)] + Web2(Web2ValidationData), + #[codec(index = 1)] + Web3(Web3ValidationData), +} diff --git a/bitacross-worker/local-setup/.env.example b/bitacross-worker/local-setup/.env.example new file mode 100644 index 0000000000..b8fab39de9 --- /dev/null +++ b/bitacross-worker/local-setup/.env.example @@ -0,0 +1,13 @@ +AliceWSPort=9946 +AliceRPCPort=9936 +AlicePort=30336 +BobWSPort=9947 +BobRPCPort=9937 +BobPort=30337 +CollatorWSPort=9944 +CollatorRPCPort=9933 +CollatorPort=30333 +TrustedWorkerPort=2000 +UntrustedWorkerPort=2001 +MuRaPort=3443 +UntrustedHttpPort=4545 \ No newline at end of file diff --git a/bitacross-worker/local-setup/README.md b/bitacross-worker/local-setup/README.md new file mode 100644 index 0000000000..25342ca038 --- /dev/null +++ b/bitacross-worker/local-setup/README.md @@ -0,0 +1,37 @@ +# How to use the local-setup + +## Prerequisite +- worker built with ` SGX_MODE=SW make` +- integritee-node built with `cargo build --release --features skip-ias-check` + +In case you have +- a sgx hardware and compile the worker with `SGX_MODE=HW` (default mode) +- a valid intel IAS key (development key is fine) + +you can omit the `--features skip-ias-check` when building the node, but you must not use the subcommand flag `--skip-ra` in the json file (see [`two-workers.json`](./config/two-workers.json)) you're using to start the worker. + +## Steps +Adapt or create your own config file, as in the example of [`two-workers.json`](./config/two-workers.json). Be mindful of the ports in case you're running the script on a server multiple people are working on. + +### Launch worker and node in terminal one +You can launch the workers and the node with: +```bash +./local-setup/launch.py --config ./local-setup/config/two-workers.json +``` +wait a little until all workers have been launched. You can stop the worker and node simply by pressing `Ctrl + c`. + +### Open a second terminal to show logs +```bash +cd local-setup +./tmux_logger.sh +``` + +You can remove the tmux session of the script by running +```bash +tmux kill-session -t integritee_logger +``` +### Open a third terminal to run a demo +```bash +cd /cli +./demo_shielding_unshielding.sh -p 99xx -P 20xx +``` diff --git a/bitacross-worker/local-setup/__init__.py b/bitacross-worker/local-setup/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/bitacross-worker/local-setup/config/benchmark.json b/bitacross-worker/local-setup/config/benchmark.json new file mode 100644 index 0000000000..f997396e3a --- /dev/null +++ b/bitacross-worker/local-setup/config/benchmark.json @@ -0,0 +1,44 @@ +{ + "nodes": [ + { + "bin": "../integritee-node/target/release/integritee-node", + "flags": [ + "--tmp", + "--dev", + "-lruntime=info", + "-lteerex=debug", + "--ws-port", + "9944", + "--port", + "30390", + "--rpc-port", + "9933", + "--ws-external", + "--rpc-external" + ] + } + ], + "workers": [ + { + "source": "bin", + "flags": [ + "--clean-reset", + "-P", + "2030", + "-p", + "9930", + "-r", + "3430", + "-w", + "2031", + "-h", + "4530", + "--ws-external" + ], + "subcommand_flags": [ + "--skip-ra", + "--dev" + ] + } + ] +} diff --git a/bitacross-worker/local-setup/config/one-worker.json b/bitacross-worker/local-setup/config/one-worker.json new file mode 100644 index 0000000000..ff80710677 --- /dev/null +++ b/bitacross-worker/local-setup/config/one-worker.json @@ -0,0 +1,49 @@ +{ + "nodes": [ + { + "bin": "../integritee-node/target/release/integritee-node", + "flags": [ + "--tmp", + "--dev", + "-lruntime=info", + "-lteerex=debug", + "--ws-port", + "9944", + "--port", + "30390", + "--rpc-port", + "9933", + "--ws-external", + "--rpc-external" + ] + } + ], + "workers": [ + { + "source": "bin", + "flags": [ + "--clean-reset", + "-P", + "2000", + "-p", + "9944", + "-r", + "3443", + "-w", + "2001", + "-h", + "4545", + "--ws-external", + "--parentchain-start-block", + "0", + "--data-dir", + "/tmp/data-dir", + "--enable-metrics" + ], + "subcommand_flags": [ + "--skip-ra", + "--dev" + ] + } + ] +} diff --git a/bitacross-worker/local-setup/config/three-nodes-one-worker.json b/bitacross-worker/local-setup/config/three-nodes-one-worker.json new file mode 100644 index 0000000000..f01b325153 --- /dev/null +++ b/bitacross-worker/local-setup/config/three-nodes-one-worker.json @@ -0,0 +1,94 @@ +{ + "nodes": [ + { + "bin": "../integritee-node/target/release/integritee-node", + "flags": [ + "--tmp", + "--dev", + "-lruntime=info", + "-lteerex=debug", + "--ws-port", + "9944", + "--port", + "30390", + "--rpc-port", + "9933", + "--ws-external", + "--rpc-external" + ] + }, + { + "bin": "../integritee-node/target/release/integritee-node", + "flags": [ + "--tmp", + "--chain", + "dev2", + "--force-authoring", + "--alice", + "-lruntime=info", + "-lteerex=debug", + "--ws-port", + "9966", + "--port", + "30395", + "--rpc-port", + "9955", + "--ws-external", + "--rpc-external" + ] + }, + { + "bin": "../integritee-node/target/release/integritee-node", + "flags": [ + "--tmp", + "--chain", + "dev3", + "--force-authoring", + "--alice", + "-lruntime=info", + "-lteerex=debug", + "--ws-port", + "9988", + "--port", + "30395", + "--rpc-port", + "9977", + "--ws-external", + "--rpc-external" + ] + } + ], + "workers": [ + { + "source": "bin", + "flags": [ + "--clean-reset", + "-P", + "2000", + "-p", + "9944", + "--target-a-parentchain-rpc-url", + "ws://127.0.0.1", + "--target-a-parentchain-rpc-port", + "9966", + "--target-b-parentchain-rpc-url", + "ws://127.0.0.1", + "--target-b-parentchain-rpc-port", + "9988", + "-r", + "3490", + "-w", + "2001", + "-h", + "4545", + "--ws-external", + "--data-dir", + "/tmp/data-dir" + ], + "subcommand_flags": [ + "--skip-ra", + "--dev" + ] + } + ] +} diff --git a/bitacross-worker/local-setup/config/three-workers.json b/bitacross-worker/local-setup/config/three-workers.json new file mode 100644 index 0000000000..49e66c49a5 --- /dev/null +++ b/bitacross-worker/local-setup/config/three-workers.json @@ -0,0 +1,76 @@ +{ + "workers": [ + { + "id": 1, + "source": "bin", + "flags": [ + "--clean-reset", + "-T", + "wss://localhost", + "-P", + "2000", + "-w", + "2001", + "-r", + "3443", + "-h", + "4545", + "--parentchain-start-block", + "0", + "--enable-metrics" + ], + "subcommand_flags": [ + "--skip-ra", + "--dev" + ] + }, + { + "id": "2", + "source": "bin", + "flags": [ + "--clean-reset", + "-T", + "wss://localhost", + "-P", + "2010", + "-w", + "2011", + "-r", + "3453", + "-h", + "4555", + "--parentchain-start-block", + "0" + ], + "subcommand_flags": [ + "--skip-ra", + "--dev", + "--request-state" + ] + }, + { + "id": "3", + "source": "bin", + "flags": [ + "--clean-reset", + "-T", + "wss://localhost", + "-P", + "2020", + "-w", + "2021", + "-r", + "3463", + "-h", + "4565", + "--parentchain-start-block", + "0" + ], + "subcommand_flags": [ + "--skip-ra", + "--dev", + "--request-state" + ] + } + ] +} diff --git a/bitacross-worker/local-setup/config/two-workers.json b/bitacross-worker/local-setup/config/two-workers.json new file mode 100644 index 0000000000..9e0194f282 --- /dev/null +++ b/bitacross-worker/local-setup/config/two-workers.json @@ -0,0 +1,76 @@ +{ + "nodes": [ + { + "bin": "../integritee-node/target/release/integritee-node", + "flags": [ + "--tmp", + "--dev", + "-lruntime=info", + "-lteerex=debug", + "--ws-port", + "9944", + "--port", + "30390", + "--rpc-port", + "9933", + "--ws-external", + "--rpc-external" + ] + } + ], + "workers": [ + { + "source": "bin", + "flags": [ + "--clean-reset", + "-P", + "2000", + "-p", + "9944", + "-r", + "3490", + "-w", + "2001", + "-h", + "4545", + "--ws-external", + "--parentchain-start-block", + "0", + "--data-dir", + "/tmp/data-dir", + "--enable-metrics" + ], + "subcommand_flags": [ + "--skip-ra", + "--dev" + ] + }, + { + "source": "bin", + "flags": [ + "--clean-reset", + "-P", + "3000", + "-p", + "9944", + "-r", + "4490", + "-w", + "3001", + "-h", + "4546", + "--ws-external", + "--parentchain-start-block", + "0", + "--data-dir", + "/tmp/data-dir2", + "--enable-metrics" + ], + "subcommand_flags": [ + "--skip-ra", + "--dev", + "--request-state" + ] + } + ] +} diff --git a/bitacross-worker/local-setup/development-worker.json b/bitacross-worker/local-setup/development-worker.json new file mode 100644 index 0000000000..a85b5fbeb3 --- /dev/null +++ b/bitacross-worker/local-setup/development-worker.json @@ -0,0 +1,28 @@ +{ + "workers": [ + { + "id": "dev", + "source": "bin", + "flags": [ + "--clean-reset", + "-P", + "$TrustedWorkerPort", + "-w", + "$UntrustedWorkerPort", + "-r", + "$MuRaPort", + "-h", + "$UntrustedHttpPort", + "-p", + "$CollatorWSPort", + "--parentchain-start-block", + "0", + "--enable-metrics" + ], + "subcommand_flags": [ + "--skip-ra", + "--dev" + ] + } + ] +} diff --git a/bitacross-worker/local-setup/launch.py b/bitacross-worker/local-setup/launch.py new file mode 100755 index 0000000000..ae4a6e5b24 --- /dev/null +++ b/bitacross-worker/local-setup/launch.py @@ -0,0 +1,275 @@ +#!/usr/bin/env python3 +""" +Launch handily a local dev setup consisting of the parachain network and some workers. + +Example usage: `./local-setup/launch.py --config local-setup/development-worker.json --parachain local-binary` + +The worker log is piped to `./log/worker0.log` etc. folder in the current-working dir. + +""" +import argparse +import json +import signal +from subprocess import Popen, PIPE, STDOUT, run +import os +import sys +from time import sleep +from typing import Union, IO +from dotenv import load_dotenv + +import pycurl +from io import BytesIO + +from py.worker import Worker +from py.helpers import GracefulKiller, mkdir_p + +import socket +import toml +import datetime + +log_dir = "log" +mkdir_p(log_dir) + +OFFSET = 100 +PORTS = [ + "AliceWSPort", + "AliceRPCPort", + "AlicePort", + "BobWSPort", + "BobRPCPort", + "BobPort", + "CollatorWSPort", + "CollatorRPCPort", + "CollatorPort", + "TrustedWorkerPort", + "UntrustedWorkerPort", + "MuRaPort", + "UntrustedHttpPort", +] + + +def setup_worker(work_dir: str, source_dir: str, std_err: Union[None, int, IO], log_config_path): + print(f"Setting up worker in {work_dir}") + print(f"Copying files from {source_dir}") + + log_level_dic = setup_worker_log_level(log_config_path) + worker = Worker(cwd=work_dir, source_dir=source_dir, std_err=std_err, log_level_dic=log_level_dic) + worker.init_clean() + print("Initialized worker.") + return worker + + +def run_worker(config, i: int, log_config_path): + id = config.get('id', i) + log = open(f"{log_dir}/worker-{id}.log", "w+") + # TODO: either hard-code 'local-setup' directory, or take from input config.json + w = setup_worker(f"tmp/w-{id}", config["source"], log, log_config_path) + + print(f"Starting worker {id} in background") + return w.run_in_background( + log_file=log, flags=config["flags"], subcommand_flags=config["subcommand_flags"] + ) + + +# Function to check if a port is open +def is_port_open(port): + try: + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + sock.bind(("127.0.0.1", int(port))) + sock.close() + return True + except OSError: + return False + +# Function to reallocate port if it is not available +def reallocate_ports(env_name, port): + # Offset the original port by 100 + new_port = int(port) + int(OFFSET) + while not is_port_open(str(new_port)): + new_port = int(port) + int(OFFSET) + + # Set the new port value in the environment variable + os.environ[env_name] = str(new_port) + print("Port for {} changed to: {}".format(env_name, os.environ.get(env_name))) + + +# Function to iterate over all ports and automatically reallocate +def check_all_ports_and_reallocate(): + for x in PORTS: + if is_port_open(os.environ.get(x)): + continue + else: + reallocate_ports(x, os.environ.get(x)) + + print("All preliminary port checks completed") + + +def run_node(config, i: int): + node_log = open(f'{log_dir}/node{i}.log', 'w+') + node_cmd = [config["bin"]] + config["flags"] + print(f'Run node {i} with command: {node_cmd}') + return Popen(node_cmd, stdout=node_log, stderr=STDOUT, bufsize=1) + + +def offset_port(offset): + for x in PORTS: + port = os.environ.get(x) + new_port = int(port) + int(offset) + os.environ[x] = str(new_port) + + +def setup_environment(offset, config, parachain_dir): + load_dotenv(".env.dev") + offset_port(offset) + check_all_ports_and_reallocate() + + # TODO: only works for single worker for now + for p in [ + "CollatorWSPort", + "TrustedWorkerPort", + "UntrustedWorkerPort", + "MuRaPort", + "UntrustedHttpPort", + ]: + if len(config["workers"]) > 0: + config["workers"][0]["flags"] = [ + flag.replace("$" + p, os.environ.get(p, "")) + for flag in config["workers"][0]["flags"] + ] + +def setup_worker_log_level(log_config_path): + log_level_dic = {} + with open(log_config_path) as f: + log_data = toml.load(f) + + # Section + for (section, item) in log_data.items(): + log_level_string = ""; + indx = 0 + + for (k, v) in item.items(): + if indx == 0: + log_level_string += v+"," + else: + log_level_string += k+"="+v+"," + + indx += 1 + + log_level_dic[section] = log_level_string + + return log_level_dic + + +def main(processes, config_path, parachain_type, log_config_path, offset, parachain_dir): + with open(config_path) as config_file: + config = json.load(config_file) + + # Litentry + print("Starting litentry parachain in background ...") + if parachain_type == "local-docker": + os.environ['LITENTRY_PARACHAIN_DIR'] = parachain_dir + setup_environment(offset, config, parachain_dir) + # TODO: use Popen and copy the stdout also to node.log + run(["./scripts/litentry/start_parachain.sh"], check=True) + elif parachain_type == "local-binary-standalone": + os.environ['LITENTRY_PARACHAIN_DIR'] = parachain_dir + setup_environment(offset, config, parachain_dir) + run(["../scripts/launch-standalone.sh"], check=True) + elif parachain_type == "local-binary": + os.environ['LITENTRY_PARACHAIN_DIR'] = parachain_dir + setup_environment(offset, config, parachain_dir) + run(["../scripts/launch-local-binary.sh", "rococo"], check=True) + elif parachain_type == "remote": + print("Litentry parachain should be started remotely") + else: + sys.exit("Unsupported parachain_type") + + print("Litentry parachain is running") + print("------------------------------------------------------------") + + c = pycurl.Curl() + worker_i = 0 + worker_num = len(config["workers"]) + for w_conf in config["workers"]: + processes.append(run_worker(w_conf, worker_i, log_config_path)) + print() + # Wait a bit for worker to start up. + sleep(5) + + idx = 0 + if "-h" in w_conf["flags"]: + idx = w_conf["flags"].index("-h") + 1 + elif "--untrusted-http-port" in w_conf["flags"]: + idx = w_conf["flags"].index("--untrusted-http-port") + 1 + else: + print('No "--untrusted-http-port" provided in config file') + return 0 + untrusted_http_port = w_conf["flags"][idx] + url = "http://localhost:" + str(untrusted_http_port) + "/is_initialized" + c.setopt(pycurl.URL, url) + + if worker_i < worker_num: + counter = 0 + while True: + sleep(5) + buffer = BytesIO() + c.setopt(c.WRITEDATA, buffer) + try: + c.perform() + except Exception as e: + print("Try to connect to worker error: " + str(e)) + return 0 + + if "I am initialized." == buffer.getvalue().decode("iso-8859-1"): + break + if counter >= 600: + print("Worker initialization timeout (3000s). Exit") + return 0 + counter += 1 + + worker_i += 1 + + c.close() + print("Worker(s) started!") + + # keep script alive until terminated + signal.pause() + + +if __name__ == "__main__": + parser = argparse.ArgumentParser( + description="Run a setup consisting of a node and some workers" + ) + parser.add_argument("-c", "--config", type=str, help="Config for the node and workers") + parser.add_argument( + "-p", + "--parachain", + nargs="?", + default="local-docker", + type=str, + help="Config for parachain selection: local-docker / local-binary / remote", + ) + parser.add_argument( + "-l", + "--log-config-path", + nargs="?", + default="./local-setup/worker-log-level-config.toml", + type=str, + help="log level config file path" + ) + parser.add_argument( + "-o", "--offset", nargs="?", default="0", type=int, help="offset for port" + ) + args = parser.parse_args() + + today = datetime.datetime.now() + formatted_date = today.strftime('%d_%m_%Y_%H%M') + directory_name = f"parachain_dev_{formatted_date}" + temp_directory_path = os.path.join('/tmp', directory_name) + parachain_dir = temp_directory_path + print("Directory has been assigned to:", temp_directory_path) + + process_list = [] + killer = GracefulKiller(process_list, args.parachain) + if main(process_list, args.config, args.parachain, args.log_config_path, args.offset, parachain_dir) == 0: + killer.exit_gracefully() diff --git a/bitacross-worker/local-setup/py/__init__.py b/bitacross-worker/local-setup/py/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/bitacross-worker/local-setup/py/helpers.py b/bitacross-worker/local-setup/py/helpers.py new file mode 100644 index 0000000000..957e51f162 --- /dev/null +++ b/bitacross-worker/local-setup/py/helpers.py @@ -0,0 +1,104 @@ +import os +import signal +import subprocess +import shutil +import sys +import docker +from typing import Union, IO +from datetime import datetime + + +def run_subprocess( + log_level, args, stdout: Union[None, int, IO], stderr: Union[None, int, IO], cwd: str = "./" +): + """Wrapper around subprocess that allows a less verbose call""" + + # todo: make configurable + env = dict( + os.environ, + RUST_LOG=log_level, + ) + + return ( + subprocess.run(args, stdout=stdout, env=env, cwd=cwd, stderr=stderr) + .stdout.decode("utf-8") + .strip() + ) + + +def setup_working_dir(source_dir: str, target_dir: str): + """Setup the working dir such that the necessary files to run a worker are contained. + + Args: + source_dir: the directory containing the files the be copied. Usually this is the bitacross-worker/bin dir. + target_dir: the working directory of the worker to be run. + """ + + optional = ["key.txt", "spid.txt"] + + for file in optional: + source = f"{source_dir}/{file}" + target = f"{target_dir}/{file}" + + if os.path.exists(source): + shutil.copy(source, target) + else: + print(f'{source} does not exist, this may be fine for DCAP or skip-ra, but you can\'t perform IAS remote attestation without this file.') + + mandatory = ["enclave.signed.so", "bitacross-worker"] + + for file in mandatory: + source = f"{source_dir}/{file}" + target = f"{target_dir}/{file}" + + if os.path.exists(source): + shutil.copy(source, target) + else: + print(f"{source} does not exist. Did you run make?") + + +def mkdir_p(path): + """Surprisingly, there is no simple function in python to create a dir if it does not exist.""" + return subprocess.run(["mkdir", "-p", path]) + + +class GracefulKiller: + signals = {signal.SIGINT: "SIGINT", signal.SIGTERM: "SIGTERM"} + + def __init__(self, processes, parachain_type): + signal.signal(signal.SIGINT, self.exit_gracefully) + signal.signal(signal.SIGTERM, self.exit_gracefully) + self.processes = processes + self.parachain_type = parachain_type + + def exit_gracefully(self, signum=signal.SIGTERM, frame=None): + print("\nReceived {} signal".format(self.signals[signum])) + + print("Save Parachain/Relaychain logs") + client = docker.from_env() + container_list = client.containers.list() + for container in container_list: + if "generated-rococo-" in container.name: + logs = container.logs() + with open(f"log/{container.name}.log", "w") as f: + f.write(logs.decode("utf-8")) + + print("Cleaning up processes.") + for p in self.processes: + try: + p.kill() + except: + pass + + if os.path.isdir(f"log"): + new_folder_name = datetime.now().strftime("log-backup/log-%Y%m%d-%H%M%S") + shutil.copytree(f"log", new_folder_name) + print(f"Backup log into " + new_folder_name) + if self.parachain_type == "local-docker": + print("Cleaning up litentry-parachain...") + subprocess.run(["./scripts/litentry/stop_parachain.sh", "||", "true"]) + if self.parachain_type == "local-binary": + print("Cleaning up litentry-parachain...") + subprocess.run(["../scripts/clean-local-binary.sh", "||", "true"]) + + sys.exit(0) diff --git a/bitacross-worker/local-setup/py/worker.py b/bitacross-worker/local-setup/py/worker.py new file mode 100644 index 0000000000..9492088b6a --- /dev/null +++ b/bitacross-worker/local-setup/py/worker.py @@ -0,0 +1,220 @@ +import os +import pathlib +import shutil +import subprocess +from subprocess import Popen, STDOUT +from typing import Union, TextIO, IO + +from .helpers import run_subprocess, setup_working_dir, mkdir_p + + +class Worker: + def __init__( + self, + worker_bin: str = "./bitacross-worker", + cwd: str = "./", + source_dir: str = "./", + std_err: Union[None, int, IO] = STDOUT, + log_level_dic: {} = {}, + ): + """ + bitacross-worker wrapper. + + Args: + worker_bin: Path to the worker bin relative to `cwd` or as absolute path. + + cwd: working directory of the worker. + + source_dir: directory of the source binaries, which will be copied to cwd because + the rust worker looks for files relative to cwd. + + std_err: Were the workers error output will be logged. Note: `std_out` is intended to be unconfigurable + because the prints from the rust worker are often intended to be used in scripts. Making this + configurable, could cause some weird errors. + + + """ + self.cwd = cwd + self.cli = [worker_bin] + self.source_dir = source_dir + self.std_err = std_err + # cache fields + self._mrenclave = None + self.log_level_dic = log_level_dic + + def setup_cwd(self): + mkdir_p(self.cwd) + setup_working_dir(self.source_dir, self.cwd) + + def init_clean(self): + """Purges all db files first and initializes the environment afterwards.""" + mkdir_p(self.cwd) + print("Copying source files to working directory") + self.setup_cwd() + + def init(self): + """Initializes the environment such that the worker can be run.""" + print("Initializing worker") + print(self.init_shard()) + print(self.write_signer_pub()) + print(self.write_shielding_pub()) + + def init_shard(self, shard=None): + """ + :param shard: Shard to be initialized. Use mrenclave if `None`. + :return msg: `println!`'s generated by the rust worker. + """ + if not shard: + shard = self.mrenclave() + if self.check_shard_and_prompt_delete(shard): + return "Shard exists already, will not initialize." + + return run_subprocess( + self.log_level_dic['bitacross-cli'], + self.cli + ["init-shard", shard], + stdout=subprocess.PIPE, + stderr=self.std_err, + cwd=self.cwd, + ) + + def shard_exists(self, shard): + """Checks if the shard in './shards/[shard]' exists + + :return: exists: True if exists, false otherwise. + """ + return self._shard_path(shard).exists() + + def check_shard_and_prompt_delete(self, shard=None): + """ + Checks if the shard exists and will prompt to delete it. + If shard is none, this will just return. + + :return: + exists: True if file exists at the end of this call. False otherwise. + + """ + if self.shard_exists(shard): + should_purge = input( + "Do you want to purge existing the shards and sidechain db? [y, n]" + ) + if should_purge == "y": + self.purge_shards_and_sidechain_db() + print(f"Deleted shard {shard}.") + return False + else: + print("Leaving shard as is.") + return True + else: + return False + + def purge(self): + """Deletes the light_client_db.bin, the shards and the sidechain_db""" + self.purge_last_slot_seal() + self.purge_light_client_db() + self.purge_shards_and_sidechain_db() + return self + + def purge_shards_and_sidechain_db(self): + if pathlib.Path(f"{self.cwd}/shards").exists(): + print(f"Purging shards") + shutil.rmtree(pathlib.Path(f"{self.cwd}/shards")) + + if pathlib.Path(f"{self.cwd}/sidechain_db").exists(): + print(f"purging sidechain_db") + shutil.rmtree(pathlib.Path(f"{self.cwd}/sidechain_db")) + + def purge_light_client_db(self): + print(f"purging light_client_db") + for db in pathlib.Path(self.cwd).glob("light_client_db.bin*"): + print(f"remove: {db}") + db.unlink() + + def purge_last_slot_seal(self): + print(f"purging last_slot_seal") + for db in pathlib.Path(self.cwd).glob("last_slot.bin"): + print(f"remove: {db}") + db.unlink() + + def mrenclave(self): + """Returns the mrenclave and caches it.""" + if not self._mrenclave: + # `std_out` needs to be subProcess.PIPE here! + self._mrenclave = run_subprocess( + self.log_level_dic['bitacross-cli'], + self.cli + ["mrenclave"], + stdout=subprocess.PIPE, + stderr=self.std_err, + cwd=self.cwd, + ) + return self._mrenclave + + def write_shielding_pub(self): + return run_subprocess( + self.log_level_dic['bitacross-cli'], + self.cli + ["shielding-key"], + stdout=subprocess.PIPE, + stderr=self.std_err, + cwd=self.cwd, + ) + + def write_signer_pub(self): + return run_subprocess( + self.log_level_dic['bitacross-cli'], + self.cli + ["signing-key"], + stdout=subprocess.PIPE, + stderr=self.std_err, + cwd=self.cwd, + ) + + def sync_state(self, flags: [str] = None, skip_ra: bool = False): + """Returns the keys from another worker.""" + + if skip_ra: + subcommand_flags = ["request-state", "--skip-ra"] + else: + subcommand_flags = ["request-state"] + + return run_subprocess( + self.log_level_dic['bitacross-cli'], + self.cli + flags + subcommand_flags, + stdout=subprocess.PIPE, + stderr=self.std_err, + cwd=self.cwd, + ) + + def _shard_path(self, shard): + return pathlib.Path(f"{self.cwd}/shards/{shard}") + + def run_in_background( + self, log_file: TextIO, flags: [str] = None, subcommand_flags: [str] = None + ): + """Runs the worker in the background and writes to the supplied logfile. + + :return: process handle for the spawned background process. + """ + + env = dict( + os.environ, + RUST_LOG=self.log_level_dic['bitacross-worker'], + ) + + worker_cmd = self._assemble_cmd(flags=flags, subcommand_flags=subcommand_flags) + print("worker command is: "+ str(worker_cmd)) + return Popen( + worker_cmd, + env=env, + stdout=log_file, + stderr=STDOUT, + bufsize=1, + cwd=self.cwd, + ) + + def _assemble_cmd(self, flags: [str] = None, subcommand_flags: [str] = None): + """Assembles the cmd skipping None values.""" + cmd = self.cli + if flags: + cmd += flags + cmd += ["run"] + if subcommand_flags: + cmd += subcommand_flags + return cmd diff --git a/bitacross-worker/local-setup/rococo_one_worker.json b/bitacross-worker/local-setup/rococo_one_worker.json new file mode 100644 index 0000000000..10e0e556cc --- /dev/null +++ b/bitacross-worker/local-setup/rococo_one_worker.json @@ -0,0 +1,29 @@ +{ + "workers": [ + { + "source": "bin", + "flags": [ + "--clean-reset", + "--ws-external", + "-P", + "2000", + "-w", + "2001", + "-r", + "3443", + "-h", + "4545", + "-u", + "wss://rpc.rococo-parachain.litentry.io", + "-p", + "443", + "--running-mode", + "mock", + "--parentchain-start-block", + "3299860" + ], + "subcommand_flags": [ + ] + } + ] +} \ No newline at end of file diff --git a/bitacross-worker/local-setup/tmux_logger.sh b/bitacross-worker/local-setup/tmux_logger.sh new file mode 100755 index 0000000000..a0476468cc --- /dev/null +++ b/bitacross-worker/local-setup/tmux_logger.sh @@ -0,0 +1,32 @@ +#!/bin/bash + +# script that setups a tmux session with three panes that attach to the log files +# of the node and the two workers launched by `./launch.py` + +################################################################################# +# If you work with docker: +# +# 1. run: ./launch.py in docker +# 2. open a new bash session in a new window in the running container: +# docker exec -it [container-id] bash +# 3. run this script: ./tmux_logger.sh +################################################################################# + + +if tmux has-session -t integritee_logger ; then + echo "detected existing polkadot logger session, attaching..." +else + # or start it up freshly + tmux new-session -d -s integritee_logger \; \ + split-window -v \; \ + split-window -v \; \ + select-layout even-vertical \; \ + send-keys -t integritee_logger:0.0 'tail -f ../log/node1.log' C-m \; \ + send-keys -t integritee_logger:0.1 'tail -f ../log/worker1.log' C-m \; \ + send-keys -t integritee_logger:0.2 'tail -f ../log/worker2.log' C-m + + # Attention: Depending on your tmux conf, indexes may start at 1 + + tmux setw -g mouse on +fi +tmux attach-session -d -t integritee_logger \ No newline at end of file diff --git a/bitacross-worker/local-setup/tmux_logger_three_nodes.sh b/bitacross-worker/local-setup/tmux_logger_three_nodes.sh new file mode 100755 index 0000000000..5856e910b6 --- /dev/null +++ b/bitacross-worker/local-setup/tmux_logger_three_nodes.sh @@ -0,0 +1,34 @@ +#!/bin/bash + +# script that setups a tmux session with three panes that attach to the log files +# of the node and the two workers launched by `./launch.py` + +################################################################################# +# If you work with docker: +# +# 1. run: ./launch.py in docker +# 2. open a new bash session in a new window in the running container: +# docker exec -it [container-id] bash +# 3. run this script: ./tmux_logger.sh +################################################################################# + + +if tmux has-session -t integritee_logger_three_nodes ; then + echo "detected existing polkadot logger session, attaching..." +else + # or start it up freshly + tmux new-session -d -s integritee_logger_three_nodes \; \ + split-window -v \; \ + split-window -v \; \ + split-window -v \; \ + select-layout even-vertical \; \ + send-keys -t integritee_logger_three_nodes:0.0 'tail -f ../log/node1.log' C-m \; \ + send-keys -t integritee_logger_three_nodes:0.1 'tail -f ../log/node2.log' C-m \; \ + send-keys -t integritee_logger_three_nodes:0.2 'tail -f ../log/node3.log' C-m \; \ + send-keys -t integritee_logger_three_nodes:0.3 'tail -f ../log/worker1.log' C-m \; \ + + # Attention: Depending on your tmux conf, indexes may start at 1 + + tmux setw -g mouse on +fi +tmux attach-session -d -t integritee_logger_three_nodes \ No newline at end of file diff --git a/bitacross-worker/local-setup/worker-log-level-config.toml b/bitacross-worker/local-setup/worker-log-level-config.toml new file mode 100644 index 0000000000..44a4ea00b2 --- /dev/null +++ b/bitacross-worker/local-setup/worker-log-level-config.toml @@ -0,0 +1,38 @@ +[bitacross-worker] +RUST_LOG="info" +litentry_worker="debug" +ws="warn" +sp_io="error" +substrate_api_client="warn" +itc_parentchain_light_client="info" +jsonrpsee_ws_client="warn" +jsonrpsee_ws_server="warn" +enclave_runtime="debug" +ita_stf="debug" +its_rpc_handler="warn" +itc_rpc_client="warn" +its_consensus_common="debug" +its_state="warn" +its_consensus_aura="warn" +"aura*"="warn" +its_consensus_slots="warn" +itc_direct_rpc_server="debug" +itp_attestation_handler="debug" +http_req="debug" +lc_mock_server="warn" +itc_rest_client="debug" +lc_credentials="debug" +lc_identity_verification="debug" +lc_stf_task_receiver="debug" +lc_stf_task_sender="debug" +lc_data_providers="debug" +itp_top_pool="debug" +itc_parentchain_indirect_calls_executor="debug" +itc_direct_rpc_client="debug" + +[bitacross-cli] +RUST_LOG="debug" +ws="warn" +sp_io="warn" +substrate_api_client="warn" +enclave="debug" diff --git a/bitacross-worker/rust-sgx-sdk/Readme.md b/bitacross-worker/rust-sgx-sdk/Readme.md new file mode 100644 index 0000000000..4c71699c10 --- /dev/null +++ b/bitacross-worker/rust-sgx-sdk/Readme.md @@ -0,0 +1,5 @@ +# RUST-SGX-SDK + +This folder contains only the neccessary parts from the [RUST-SGX-SDK](https://github.com/baidu/rust-sgx-sdk). + +All the crates are directly fetched from github. \ No newline at end of file diff --git a/bitacross-worker/rust-sgx-sdk/buildenv.mk b/bitacross-worker/rust-sgx-sdk/buildenv.mk new file mode 100644 index 0000000000..ce28be4e55 --- /dev/null +++ b/bitacross-worker/rust-sgx-sdk/buildenv.mk @@ -0,0 +1,179 @@ +# +# Copyright (C) 2017-2018 Baidu, Inc. All Rights Reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Baidu, Inc., nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# + +CP := /bin/cp -f +MKDIR := mkdir -p +STRIP := strip +OBJCOPY := objcopy + +# clean the content of 'INCLUDE' - this variable will be set by vcvars32.bat +# thus it will cause build error when this variable is used by our Makefile, +# when compiling the code under Cygwin tainted by MSVC environment settings. +INCLUDE := + +# turn on stack protector for SDK +COMMON_FLAGS += -fstack-protector + +ifdef DEBUG + COMMON_FLAGS += -O0 -g -DDEBUG -UNDEBUG +else + COMMON_FLAGS += -O2 -D_FORTIFY_SOURCE=2 -UDEBUG -DNDEBUG +endif + +# turn on compiler warnings as much as possible +COMMON_FLAGS += -Wall -Wextra -Winit-self -Wpointer-arith -Wreturn-type \ + -Waddress -Wsequence-point -Wformat-security \ + -Wmissing-include-dirs -Wfloat-equal -Wundef -Wshadow \ + -Wcast-align -Wconversion -Wredundant-decls + +# additional warnings flags for C +CFLAGS += -Wjump-misses-init -Wstrict-prototypes -Wunsuffixed-float-constants + +# additional warnings flags for C++ +CXXFLAGS += -Wnon-virtual-dtor + +# for static_assert() +CXXFLAGS += -std=c++0x + +.DEFAULT_GOAL := all +# this turns off the RCS / SCCS implicit rules of GNU Make +% : RCS/%,v +% : RCS/% +% : %,v +% : s.% +% : SCCS/s.% + +# If a rule fails, delete $@. +.DELETE_ON_ERROR: + +HOST_FILE_PROGRAM := file + +UNAME := $(shell uname -m) +ifneq (,$(findstring 86,$(UNAME))) + HOST_ARCH := x86 + ifneq (,$(shell $(HOST_FILE_PROGRAM) -L $(SHELL) | grep 'x86[_-]64')) + HOST_ARCH := x86_64 + endif +else + $(info Unknown host CPU architecture $(UNAME)) + $(error Aborting) +endif + + +ifeq "$(findstring __INTEL_COMPILER, $(shell $(CC) -E -dM -xc /dev/null))" "__INTEL_COMPILER" + ifeq ($(shell test -f /usr/bin/dpkg; echo $$?), 0) + ADDED_INC := -I /usr/include/$(shell dpkg-architecture -qDEB_BUILD_MULTIARCH) + endif +endif + +ARCH := $(HOST_ARCH) +ifeq "$(findstring -m32, $(CXXFLAGS))" "-m32" + ARCH := x86 +endif + +ifeq ($(ARCH), x86) +COMMON_FLAGS += -DITT_ARCH_IA32 +else +COMMON_FLAGS += -DITT_ARCH_IA64 +endif + +CFLAGS += $(COMMON_FLAGS) +CXXFLAGS += $(COMMON_FLAGS) + +# Enable the security flags +COMMON_LDFLAGS := -Wl,-z,relro,-z,now,-z,noexecstack + +# mitigation options +MITIGATION_INDIRECT ?= 0 +MITIGATION_RET ?= 0 +MITIGATION_C ?= 0 +MITIGATION_ASM ?= 0 +MITIGATION_AFTERLOAD ?= 0 +MITIGATION_LIB_PATH := + +ifeq ($(MITIGATION-CVE-2020-0551), LOAD) + MITIGATION_C := 1 + MITIGATION_ASM := 1 + MITIGATION_INDIRECT := 1 + MITIGATION_RET := 1 + MITIGATION_AFTERLOAD := 1 + MITIGATION_LIB_PATH := cve_2020_0551_load +else ifeq ($(MITIGATION-CVE-2020-0551), CF) + MITIGATION_C := 1 + MITIGATION_ASM := 1 + MITIGATION_INDIRECT := 1 + MITIGATION_RET := 1 + MITIGATION_AFTERLOAD := 0 + MITIGATION_LIB_PATH := cve_2020_0551_cf +endif + +MITIGATION_CFLAGS := +MITIGATION_ASFLAGS := +ifeq ($(MITIGATION_C), 1) +ifeq ($(MITIGATION_INDIRECT), 1) + MITIGATION_CFLAGS += -mindirect-branch-register +endif +ifeq ($(MITIGATION_RET), 1) + MITIGATION_CFLAGS += -mfunction-return=thunk-extern +endif +endif + +ifeq ($(MITIGATION_ASM), 1) + MITIGATION_ASFLAGS += -fno-plt +ifeq ($(MITIGATION_AFTERLOAD), 1) + MITIGATION_ASFLAGS += -Wa,-mlfence-after-load=yes +else + MITIGATION_ASFLAGS += -Wa,-mlfence-before-indirect-branch=register +endif +ifeq ($(MITIGATION_RET), 1) + MITIGATION_ASFLAGS += -Wa,-mlfence-before-ret=not +endif +endif + +MITIGATION_CFLAGS += $(MITIGATION_ASFLAGS) + +# Compiler and linker options for an Enclave +# +# We are using '--export-dynamic' so that `g_global_data_sim' etc. +# will be exported to dynamic symbol table. +# +# When `pie' is enabled, the linker (both BFD and Gold) under Ubuntu 14.04 +# will hide all symbols from dynamic symbol table even if they are marked +# as `global' in the LD version script. +ENCLAVE_CFLAGS = -ffreestanding -nostdinc -fvisibility=hidden -fpie -fno-strict-overflow -fno-delete-null-pointer-checks +ENCLAVE_CXXFLAGS = $(ENCLAVE_CFLAGS) -nostdinc++ +ENCLAVE_LDFLAGS = $(COMMON_LDFLAGS) -Wl,-Bstatic -Wl,-Bsymbolic -Wl,--no-undefined \ + -Wl,-pie,-eenclave_entry -Wl,--export-dynamic \ + -Wl,--gc-sections \ + -Wl,--defsym,__ImageBase=0 + +ENCLAVE_CFLAGS += $(MITIGATION_CFLAGS) +ENCLAVE_ASFLAGS = $(MITIGATION_ASFLAGS) \ No newline at end of file diff --git a/bitacross-worker/rust-sgx-sdk/common/inc/assert.h b/bitacross-worker/rust-sgx-sdk/common/inc/assert.h new file mode 100644 index 0000000000..a153995416 --- /dev/null +++ b/bitacross-worker/rust-sgx-sdk/common/inc/assert.h @@ -0,0 +1,63 @@ +/* $OpenBSD: assert.h,v 1.12 2006/01/31 10:53:51 hshoexer Exp $ */ +/* $NetBSD: assert.h,v 1.6 1994/10/26 00:55:44 cgd Exp $ */ + +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)assert.h 8.2 (Berkeley) 1/21/94 + */ + +/* + * Unlike other ANSI header files, may usefully be included + * multiple times, with and without NDEBUG defined. + */ + +#include + +#undef assert + +#ifdef NDEBUG +# define assert(e) ((void)0) +#else +# define assert(e) ((e) ? (void)0 : __assert(__FILE__, __LINE__, __func__, #e)) +#endif + +#ifndef _ASSERT_H_DECLS +#define _ASSERT_H_DECLS +__BEGIN_DECLS + +void _TLIBC_CDECL_ __assert(const char *, int, const char *, const char *); + +__END_DECLS +#endif /* Not _ASSERT_H_DECLS */ + diff --git a/bitacross-worker/rust-sgx-sdk/common/inc/complex.h b/bitacross-worker/rust-sgx-sdk/common/inc/complex.h new file mode 100644 index 0000000000..904cb31fbf --- /dev/null +++ b/bitacross-worker/rust-sgx-sdk/common/inc/complex.h @@ -0,0 +1,134 @@ +/* $OpenBSD: complex.h,v 1.3 2010/07/24 22:17:03 guenther Exp $ */ +/* + * Copyright (c) 2008 Martynas Venckus + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _COMPLEX_H_ +#define _COMPLEX_H_ + +#include + +/* + * C99 + */ +#ifdef __GNUC__ +#if __STDC_VERSION__ < 199901 +#define _Complex __complex__ +#endif +#define _Complex_I 1.0fi +#elif defined(lint) +#define _Complex_I 1.0fi +#endif + +#define complex _Complex + +/* XXX switch to _Imaginary_I */ +#undef I +#define I _Complex_I + +__BEGIN_DECLS +/* + * Double versions of C99 functions + */ +double complex cacos(double complex); +double complex casin(double complex); +double complex catan(double complex); +double complex ccos(double complex); +double complex csin(double complex); +double complex ctan(double complex); +double complex cacosh(double complex); +double complex casinh(double complex); +double complex catanh(double complex); +double complex ccosh(double complex); +double complex csinh(double complex); +double complex ctanh(double complex); +double complex cexp(double complex); +double complex clog(double complex); +double cabs(double complex); +double complex cpow(double complex, double complex); +double complex csqrt(double complex); +double carg(double complex); +double cimag(double complex); +double complex conj(double complex); +double complex cproj(double complex); +double creal(double complex); +/* + * C99 reserved + */ +double complex clog10(double complex); + +/* + * Float versions of C99 functions + */ +float complex cacosf(float complex); +float complex casinf(float complex); +float complex catanf(float complex); +float complex ccosf(float complex); +float complex csinf(float complex); +float complex ctanf(float complex); +float complex cacoshf(float complex); +float complex casinhf(float complex); +float complex catanhf(float complex); +float complex ccoshf(float complex); +float complex csinhf(float complex); +float complex ctanhf(float complex); +float complex cexpf(float complex); +float complex clogf(float complex); +float cabsf(float complex); +float complex cpowf(float complex, float complex); +float complex csqrtf(float complex); +float cargf(float complex); +float cimagf(float complex); +float complex conjf(float complex); +float complex cprojf(float complex); +float crealf(float complex); +/* + * C99 reserved + */ +float complex clog10f(float complex); + +/* + * Long double versions of C99 functions + */ +long double complex cacosl(long double complex); +long double complex casinl(long double complex); +long double complex catanl(long double complex); +long double complex ccosl(long double complex); +long double complex csinl(long double complex); +long double complex ctanl(long double complex); +long double complex cacoshl(long double complex); +long double complex casinhl(long double complex); +long double complex catanhl(long double complex); +long double complex ccoshl(long double complex); +long double complex csinhl(long double complex); +long double complex ctanhl(long double complex); +long double complex cexpl(long double complex); +long double complex clogl(long double complex); +long double cabsl(long double complex); +long double complex cpowl(long double complex, long double complex); +long double complex csqrtl(long double complex); +long double cargl(long double complex); +long double cimagl(long double complex); +long double complex conjl(long double complex); +long double complex cprojl(long double complex); +long double creall(long double complex); +/* + * C99 reserved + */ +long double complex clog10l(long double complex); + +__END_DECLS + +#endif /* !_COMPLEX_H_ */ diff --git a/bitacross-worker/rust-sgx-sdk/common/inc/ctype.h b/bitacross-worker/rust-sgx-sdk/common/inc/ctype.h new file mode 100644 index 0000000000..57ac70ff11 --- /dev/null +++ b/bitacross-worker/rust-sgx-sdk/common/inc/ctype.h @@ -0,0 +1,65 @@ +/* $OpenBSD: ctype.h,v 1.22 2010/10/01 20:10:24 guenther Exp $ */ +/* $NetBSD: ctype.h,v 1.14 1994/10/26 00:55:47 cgd Exp $ */ + +/* + * Copyright (c) 1989 The Regents of the University of California. + * All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ctype.h 5.3 (Berkeley) 4/3/91 + */ + +#ifndef _CTYPE_H_ +#define _CTYPE_H_ + +#include + +__BEGIN_DECLS + +int _TLIBC_CDECL_ isalnum(int); +int _TLIBC_CDECL_ isalpha(int); +int _TLIBC_CDECL_ iscntrl(int); +int _TLIBC_CDECL_ isdigit(int); +int _TLIBC_CDECL_ isgraph(int); +int _TLIBC_CDECL_ islower(int); +int _TLIBC_CDECL_ isprint(int); +int _TLIBC_CDECL_ ispunct(int); +int _TLIBC_CDECL_ isspace(int); +int _TLIBC_CDECL_ isupper(int); +int _TLIBC_CDECL_ isxdigit(int); +int _TLIBC_CDECL_ tolower(int); +int _TLIBC_CDECL_ toupper(int); +int _TLIBC_CDECL_ isblank(int); +int _TLIBC_CDECL_ isascii(int); + +__END_DECLS + +#endif /* _CTYPE_H_ */ diff --git a/bitacross-worker/rust-sgx-sdk/common/inc/dirent.h b/bitacross-worker/rust-sgx-sdk/common/inc/dirent.h new file mode 100644 index 0000000000..a0ede0375c --- /dev/null +++ b/bitacross-worker/rust-sgx-sdk/common/inc/dirent.h @@ -0,0 +1,48 @@ +// +// Copyright © 2005-2020 Rich Felker, et al. +// Licensed under the MIT license.s +// + +/* Copyright © 2005-2020 Rich Felker, et al. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef _DIRENT_H_ +#define _DIRENT_H_ + +struct dirent { + __ino_t d_ino; + __off_t d_off; + unsigned short d_reclen; + unsigned char d_type; + char d_name[256]; +}; + +struct dirent64 { + __ino64_t d_ino; + __off64_t d_off; + unsigned short d_reclen; + unsigned char d_type; + char d_name[256]; +}; + +#define d_fileno d_ino + +#endif /* _DIRENT_H_ */ diff --git a/bitacross-worker/rust-sgx-sdk/common/inc/endian.h b/bitacross-worker/rust-sgx-sdk/common/inc/endian.h new file mode 100644 index 0000000000..2620c5898f --- /dev/null +++ b/bitacross-worker/rust-sgx-sdk/common/inc/endian.h @@ -0,0 +1,33 @@ +/* $OpenBSD: endian.h,v 1.18 2006/03/27 07:09:24 otto Exp $ */ + +/*- + * Copyright (c) 1997 Niklas Hallqvist. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _ENDIAN_H_ +#define _ENDIAN_H_ + +#include + +#endif /* _ENDIAN_H_ */ + diff --git a/bitacross-worker/rust-sgx-sdk/common/inc/errno.h b/bitacross-worker/rust-sgx-sdk/common/inc/errno.h new file mode 100644 index 0000000000..dbe293cb9e --- /dev/null +++ b/bitacross-worker/rust-sgx-sdk/common/inc/errno.h @@ -0,0 +1,187 @@ +/* $OpenBSD: errno.h,v 1.1 2005/12/28 16:33:56 millert Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1989, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)errno.h 8.5 (Berkeley) 1/21/94 + */ + +#ifndef _ERRNO_H_ +#define _ERRNO_H_ + +#include + +#define EPERM 1 +#define ENOENT 2 +#define ESRCH 3 +#define EINTR 4 +#define EIO 5 +#define ENXIO 6 +#define E2BIG 7 +#define ENOEXEC 8 +#define EBADF 9 +#define ECHILD 10 +#define EAGAIN 11 +#define ENOMEM 12 +#define EACCES 13 +#define EFAULT 14 +#define ENOTBLK 15 +#define EBUSY 16 +#define EEXIST 17 +#define EXDEV 18 +#define ENODEV 19 +#define ENOTDIR 20 +#define EISDIR 21 +#define EINVAL 22 +#define ENFILE 23 +#define EMFILE 24 +#define ENOTTY 25 +#define ETXTBSY 26 +#define EFBIG 27 +#define ENOSPC 28 +#define ESPIPE 29 +#define EROFS 30 +#define EMLINK 31 +#define EPIPE 32 +#define EDOM 33 +#define ERANGE 34 +#define EDEADLK 35 +#define ENAMETOOLONG 36 +#define ENOLCK 37 +#define ENOSYS 38 +#define ENOTEMPTY 39 +#define ELOOP 40 +#define EWOULDBLOCK EAGAIN +#define ENOMSG 42 +#define EIDRM 43 +#define ECHRNG 44 +#define EL2NSYNC 45 +#define EL3HLT 46 +#define EL3RST 47 +#define ELNRNG 48 +#define EUNATCH 49 +#define ENOCSI 50 +#define EL2HLT 51 +#define EBADE 52 +#define EBADR 53 +#define EXFULL 54 +#define ENOANO 55 +#define EBADRQC 56 +#define EBADSLT 57 +#define EDEADLOCK EDEADLK +#define EBFONT 59 +#define ENOSTR 60 +#define ENODATA 61 +#define ETIME 62 +#define ENOSR 63 +#define ENONET 64 +#define ENOPKG 65 +#define EREMOTE 66 +#define ENOLINK 67 +#define EADV 68 +#define ESRMNT 69 +#define ECOMM 70 +#define EPROTO 71 +#define EMULTIHOP 72 +#define EDOTDOT 73 +#define EBADMSG 74 +#define EOVERFLOW 75 +#define ENOTUNIQ 76 +#define EBADFD 77 +#define EREMCHG 78 +#define ELIBACC 79 +#define ELIBBAD 80 +#define ELIBSCN 81 +#define ELIBMAX 82 +#define ELIBEXEC 83 +#define EILSEQ 84 +#define ERESTART 85 +#define ESTRPIPE 86 +#define EUSERS 87 +#define ENOTSOCK 88 +#define EDESTADDRREQ 89 +#define EMSGSIZE 90 +#define EPROTOTYPE 91 +#define ENOPROTOOPT 92 +#define EPROTONOSUPPORT 93 +#define ESOCKTNOSUPPORT 94 +#define EOPNOTSUPP 95 +#define EPFNOSUPPORT 96 +#define EAFNOSUPPORT 97 +#define EADDRINUSE 98 +#define EADDRNOTAVAIL 99 +#define ENETDOWN 100 +#define ENETUNREACH 101 +#define ENETRESET 102 +#define ECONNABORTED 103 +#define ECONNRESET 104 +#define ENOBUFS 105 +#define EISCONN 106 +#define ENOTCONN 107 +#define ESHUTDOWN 108 +#define ETOOMANYREFS 109 +#define ETIMEDOUT 110 +#define ECONNREFUSED 111 +#define EHOSTDOWN 112 +#define EHOSTUNREACH 113 +#define EALREADY 114 +#define EINPROGRESS 115 +#define ESTALE 116 +#define EUCLEAN 117 +#define ENOTNAM 118 +#define ENAVAIL 119 +#define EISNAM 120 +#define EREMOTEIO 121 +#define EDQUOT 122 +#define ENOMEDIUM 123 +#define EMEDIUMTYPE 124 +#define ECANCELED 125 +#define ENOKEY 126 +#define EKEYEXPIRED 127 +#define EKEYREVOKED 128 +#define EKEYREJECTED 129 +#define EOWNERDEAD 130 +#define ENOTRECOVERABLE 131 +#define ERFKILL 132 +#define EHWPOISON 133 +#define ENOTSUP EOPNOTSUPP + +__BEGIN_DECLS + +#ifndef errno +int * _TLIBC_CDECL_ __errno(void); +#define errno (*__errno()) +#endif /* errno */ +__END_DECLS + +#endif /* _ERRNO_H_ */ diff --git a/bitacross-worker/rust-sgx-sdk/common/inc/fenv.h b/bitacross-worker/rust-sgx-sdk/common/inc/fenv.h new file mode 100644 index 0000000000..a233172a41 --- /dev/null +++ b/bitacross-worker/rust-sgx-sdk/common/inc/fenv.h @@ -0,0 +1,139 @@ +/* $OpenBSD: fenv.h,v 1.2 2011/05/25 21:46:49 martynas Exp $ */ +/* $NetBSD: fenv.h,v 1.2.4.1 2011/02/08 16:18:55 bouyer Exp $ */ + +/* + * Copyright (c) 2010 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _FENV_H_ +#define _FENV_H_ + +#include + +/* + * Each symbol representing a floating point exception expands to an integer + * constant expression with values, such that bitwise-inclusive ORs of _all + * combinations_ of the constants result in distinct values. + * + * We use such values that allow direct bitwise operations on FPU/SSE registers. + */ +#define FE_INVALID 0x01 +#define FE_DENORMAL 0x02 +#define FE_DIVBYZERO 0x04 +#define FE_OVERFLOW 0x08 +#define FE_UNDERFLOW 0x10 +#define FE_INEXACT 0x20 + +/* + * The following symbol is simply the bitwise-inclusive OR of all floating-point + * exception constants defined above. + */ +#define FE_ALL_EXCEPT (FE_INVALID | FE_DENORMAL | FE_DIVBYZERO | \ + FE_OVERFLOW | FE_UNDERFLOW | FE_INEXACT) +#define _SSE_MASK_SHIFT 7 + +/* + * Each symbol representing the rounding direction, expands to an integer + * constant expression whose value is distinct non-negative value. + * + * We use such values that allow direct bitwise operations on FPU/SSE registers. + */ +#define FE_TONEAREST 0x000 +#define FE_DOWNWARD 0x400 +#define FE_UPWARD 0x800 +#define FE_TOWARDZERO 0xc00 + +/* + * The following symbol is simply the bitwise-inclusive OR of all floating-point + * rounding direction constants defined above. + */ +#define _X87_ROUND_MASK (FE_TONEAREST | FE_DOWNWARD | FE_UPWARD | \ + FE_TOWARDZERO) +#define _SSE_ROUND_SHIFT 3 + +/* + * fenv_t represents the entire floating-point environment. + */ +typedef struct { + struct { + unsigned int __control; /* Control word register */ + unsigned int __status; /* Status word register */ + unsigned int __tag; /* Tag word register */ + unsigned int __others[4]; /* EIP, Pointer Selector, etc */ + } __x87; + unsigned int __mxcsr; /* Control, status register */ +} fenv_t; + +/* + * The following constant represents the default floating-point environment + * (that is, the one installed at program startup) and has type pointer to + * const-qualified fenv_t. + * + * It can be used as an argument to the functions within the header + * that manage the floating-point environment, namely fesetenv() and + * feupdateenv(). + */ +__BEGIN_DECLS +extern fenv_t __fe_dfl_env; +__END_DECLS +#define FE_DFL_ENV ((const fenv_t *)&__fe_dfl_env) + +/* + * fexcept_t represents the floating-point status flags collectively, including + * any status the implementation associates with the flags. + * + * A floating-point status flag is a system variable whose value is set (but + * never cleared) when a floating-point exception is raised, which occurs as a + * side effect of exceptional floating-point arithmetic to provide auxiliary + * information. + * + * A floating-point control mode is a system variable whose value may be set by + * the user to affect the subsequent behavior of floating-point arithmetic. + */ +typedef unsigned int fexcept_t; + +__BEGIN_DECLS + +int feclearexcept(int); +int fegetexceptflag(fexcept_t *, int); +int feraiseexcept(int); +int fesetexceptflag(const fexcept_t *, int); +int fetestexcept(int); + +int fegetround(void); +int fesetround(int); + +int fegetenv(fenv_t *); +int feholdexcept(fenv_t *); +int fesetenv(const fenv_t *); +int feupdateenv(const fenv_t *); + +int feenableexcept(int); +int fedisableexcept(int); +int fegetexcept(void); + +__END_DECLS + +#endif /* ! _FENV_H_ */ diff --git a/bitacross-worker/rust-sgx-sdk/common/inc/float.h b/bitacross-worker/rust-sgx-sdk/common/inc/float.h new file mode 100644 index 0000000000..e38a7c6a9f --- /dev/null +++ b/bitacross-worker/rust-sgx-sdk/common/inc/float.h @@ -0,0 +1,84 @@ +/* $OpenBSD: float.h,v 1.3 2008/07/21 20:50:54 martynas Exp $ */ +/* $NetBSD: float.h,v 1.8 1995/06/20 20:45:37 jtc Exp $ */ + +/* + * Copyright (c) 1989 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)float.h 7.1 (Berkeley) 5/8/90 + */ + +#ifndef _FLOAT_H_ +#define _FLOAT_H_ + +#include + +#define FLT_RADIX 2 /* b */ + +// The rounding direction can be specified by fesetround() in +#define FLT_ROUNDS 1 /* addition rounding: near */ +#define DECIMAL_DIG 21 /* max precision in decimal digits */ + +// NOTE: FLT_EVAL_METHOD is -1 under FREEBSD x86. +#ifdef __i386__ +#define FLT_EVAL_METHOD 2 /* long double */ +#else +#define FLT_EVAL_METHOD 0 /* no promotions */ +#endif + +#define DBL_MANT_DIG 53 +#define DBL_EPSILON 2.2204460492503131E-16 +#define DBL_DIG 15 +#define DBL_MIN_EXP (-1021) +#define DBL_MIN 2.2250738585072014E-308 +#define DBL_MIN_10_EXP (-307) +#define DBL_MAX_EXP 1024 +#define DBL_MAX_10_EXP 308 + +#define FLT_MANT_DIG 24 /* p */ +#define FLT_DIG 6 /* floor((p-1)*log10(b))+(b == 10) */ +#define FLT_MIN_EXP (-125) /* emin */ +#define FLT_MIN_10_EXP (-37) /* ceil(log10(b**(emin-1))) */ +#define FLT_MAX_EXP 128 /* emax */ +#define FLT_MAX_10_EXP 38 /* floor(log10((1-b**(-p))*b**emax)) */ + +#define DBL_MAX 1.7976931348623157E+308 +#define FLT_EPSILON 1.19209290E-07F /* b**(1-p) */ +#define FLT_MIN 1.17549435E-38F /* b**(emin-1) */ +#define FLT_MAX 3.40282347E+38F /* (1-b**(-p))*b**emax */ + +#define LDBL_MANT_DIG 64 +#define LDBL_EPSILON 1.08420217248550443401e-19L +#define LDBL_DIG 18 +#define LDBL_MIN_EXP (-16381) +#define LDBL_MIN 3.36210314311209350626e-4932L +#define LDBL_MIN_10_EXP (-4931) +#define LDBL_MAX_EXP 16384 +#define LDBL_MAX 1.18973149535723176502e+4932L +#define LDBL_MAX_10_EXP 4932 + +#endif /* _FLOAT_H_ */ diff --git a/bitacross-worker/rust-sgx-sdk/common/inc/inttypes.h b/bitacross-worker/rust-sgx-sdk/common/inc/inttypes.h new file mode 100644 index 0000000000..fbc009c975 --- /dev/null +++ b/bitacross-worker/rust-sgx-sdk/common/inc/inttypes.h @@ -0,0 +1,330 @@ +/* $OpenBSD: inttypes.h,v 1.10 2009/01/13 18:13:51 kettenis Exp $ */ + +/* + * Copyright (c) 1997, 2005 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _INTTYPES_H_ +#define _INTTYPES_H_ + +#include + +/* + * 7.8.1 Macros for format specifiers + * + * Each of the following object-like macros expands to a string + * literal containing a conversion specifier, possibly modified by + * a prefix such as hh, h, l, or ll, suitable for use within the + * format argument of a formatted input/output function when + * converting the corresponding integer type. These macro names + * have the general form of PRI (character string literals for the + * fprintf family) or SCN (character string literals for the fscanf + * family), followed by the conversion specifier, followed by a + * name corresponding to a similar typedef name. For example, + * PRIdFAST32 can be used in a format string to print the value of + * an integer of type int_fast32_t. + */ + +/* fprintf macros for signed integers */ +#define PRId8 "d" /* int8_t */ +#define PRId16 "d" /* int16_t */ +#define PRId32 "d" /* int32_t */ +#ifdef __x86_64__ +#define PRId64 "ld" /* int64_t */ +#else +#define PRId64 "lld" /* int64_t */ +#endif + +#define PRIdLEAST8 "d" /* int_least8_t */ +#define PRIdLEAST16 "d" /* int_least16_t */ +#define PRIdLEAST32 "d" /* int_least32_t */ +#ifdef __x86_64__ +#define PRIdLEAST64 "ld" /* int_least64_t */ +#else +#define PRIdLEAST64 "lld" /* int_least64_t */ +#endif + +#define PRIdFAST8 "d" /* int_fast8_t */ +#ifdef __x86_64__ +#define PRIdFAST16 "ld" /* int_fast16_t */ +#define PRIdFAST32 "ld" /* int_fast32_t */ +#define PRIdFAST64 "ld" /* int_fast64_t */ +#else +#define PRIdFAST16 "d" /* int_fast16_t */ +#define PRIdFAST32 "d" /* int_fast32_t */ +#define PRIdFAST64 "lld" /* int_fast64_t */ +#endif + +#ifdef __x86_64__ +#define PRIdMAX "ld" /* intmax_t */ +#else +#if defined(__i386__) +#define PRIdMAX "lld" /* intmax_t */ +#else +#define PRIdMAX "jd" /* intmax_t */ +#endif +#endif + +#ifdef __i386__ +#define PRIdPTR "d" /* intptr_t */ +#else +#define PRIdPTR "ld" /* intptr_t */ +#endif + +#define PRIi8 "i" /* int8_t */ +#define PRIi16 "i" /* int16_t */ +#define PRIi32 "i" /* int32_t */ +#ifdef __x86_64__ +#define PRIi64 "li" /* int64_t */ +#else +#define PRIi64 "lli" /* int64_t */ +#endif + +#define PRIiLEAST8 "i" /* int_least8_t */ +#define PRIiLEAST16 "i" /* int_least16_t */ +#define PRIiLEAST32 "i" /* int_least32_t */ +#ifdef __x86_64__ +#define PRIiLEAST64 "li" /* int_least64_t */ +#else +#define PRIiLEAST64 "lli" /* int_least64_t */ +#endif + +#define PRIiFAST8 "i" /* int_fast8_t */ +#ifdef __x86_64__ +#define PRIiFAST16 "li" /* int_fast16_t */ +#define PRIiFAST32 "li" /* int_fast32_t */ +#define PRIiFAST64 "li" /* int_fast64_t */ +#else +#define PRIiFAST16 "i" /* int_fast16_t */ +#define PRIiFAST32 "i" /* int_fast32_t */ +#define PRIiFAST64 "lli" /* int_fast64_t */ +#endif + +#ifdef __x86_64__ +#define PRIiMAX "li" /* intmax_t */ +#else +#if defined(__i386__) +#define PRIiMAX "lli" /* intmax_t */ +#else +#define PRIiMAX "ji" /* intmax_t */ +#endif +#endif + +#ifdef __i386__ +#define PRIiPTR "i" /* intptr_t */ +#else +#define PRIiPTR "li" /* intptr_t */ +#endif + +/* fprintf macros for unsigned integers */ +#define PRIo8 "o" /* int8_t */ +#define PRIo16 "o" /* int16_t */ +#define PRIo32 "o" /* int32_t */ +#ifdef __x86_64__ +#define PRIo64 "lo" /* int64_t */ +#else +#define PRIo64 "llo" /* int64_t */ +#endif + +#define PRIoLEAST8 "o" /* int_least8_t */ +#define PRIoLEAST16 "o" /* int_least16_t */ +#define PRIoLEAST32 "o" /* int_least32_t */ +#ifdef __x86_64__ +#define PRIoLEAST64 "lo" /* int_least64_t */ +#else +#define PRIoLEAST64 "llo" /* int_least64_t */ +#endif + +#define PRIoFAST8 "o" /* int_fast8_t */ +#ifdef __x86_64__ +#define PRIoFAST16 "lo" /* int_fast16_t */ +#define PRIoFAST32 "lo" /* int_fast32_t */ +#define PRIoFAST64 "lo" /* int_fast64_t */ +#else +#define PRIoFAST16 "o" /* int_fast16_t */ +#define PRIoFAST32 "o" /* int_fast32_t */ +#define PRIoFAST64 "llo" /* int_fast64_t */ +#endif + +#ifdef __x86_64__ +#define PRIoMAX "lo" /* intmax_t */ +#else +#if defined(__i386__) +#define PRIoMAX "llo" /* intmax_t */ +#else +#define PRIoMAX "jo" /* intmax_t */ +#endif +#endif + +#ifdef __i386__ +#define PRIoPTR "o" /* intptr_t */ +#else +#define PRIoPTR "lo" /* intptr_t */ +#endif + +#define PRIu8 "u" /* uint8_t */ +#define PRIu16 "u" /* uint16_t */ +#define PRIu32 "u" /* uint32_t */ + +#ifdef __x86_64__ +#define PRIu64 "lu" /* uint64_t */ +#else +#define PRIu64 "llu" /* uint64_t */ +#endif + +#define PRIuLEAST8 "u" /* uint_least8_t */ +#define PRIuLEAST16 "u" /* uint_least16_t */ +#define PRIuLEAST32 "u" /* uint_least32_t */ + +#ifdef __x86_64__ +#define PRIuLEAST64 "lu" /* uint_least64_t */ +#else +#define PRIuLEAST64 "llu" /* uint_least64_t */ +#endif + +#define PRIuFAST8 "u" /* uint_fast8_t */ + +#ifdef __x86_64__ +#define PRIuFAST16 "lu" /* uint_fast16_t */ +#define PRIuFAST32 "lu" /* uint_fast32_t */ +#define PRIuFAST64 "lu" /* uint_fast64_t */ +#else +#define PRIuFAST16 "u" /* uint_fast16_t */ +#define PRIuFAST32 "u" /* uint_fast32_t */ +#define PRIuFAST64 "llu" /* uint_fast64_t */ +#endif + +#ifdef __x86_64__ +#define PRIuMAX "lu" /* uintmax_t */ +#else +#if defined(__i386__) +#define PRIuMAX "llu" /* uintmax_t */ +#else +#define PRIuMAX "ju" /* uintmax_t */ +#endif +#endif + +#ifdef __i386__ +#define PRIuPTR "u" /* uintptr_t */ +#else +#define PRIuPTR "lu" /* uintptr_t */ +#endif + +#define PRIx8 "x" /* uint8_t */ +#define PRIx16 "x" /* uint16_t */ +#define PRIx32 "x" /* uint32_t */ +#ifdef __x86_64__ +#define PRIx64 "lx" /* uint64_t */ +#else +#define PRIx64 "llx" /* uint64_t */ +#endif + +#define PRIxLEAST8 "x" /* uint_least8_t */ +#define PRIxLEAST16 "x" /* uint_least16_t */ +#define PRIxLEAST32 "x" /* uint_least32_t */ +#ifdef __x86_64__ +#define PRIxLEAST64 "lx" /* uint_least64_t */ +#else +#define PRIxLEAST64 "llx" /* uint_least64_t */ +#endif + +#define PRIxFAST8 "x" /* uint_fast8_t */ +#ifdef __x86_64__ +#define PRIxFAST16 "lx" /* uint_fast16_t */ +#define PRIxFAST32 "lx" /* uint_fast32_t */ +#define PRIxFAST64 "lx" /* uint_fast64_t */ +#else +#define PRIxFAST16 "x" /* uint_fast16_t */ +#define PRIxFAST32 "x" /* uint_fast32_t */ +#define PRIxFAST64 "llx" /* uint_fast64_t */ +#endif + +#ifdef __x86_64__ +#define PRIxMAX "lx" /* uintmax_t */ +#else +#if defined(__i386__) +#define PRIxMAX "llx" /* uintmax_t */ +#else +#define PRIxMAX "jx" /* uintmax_t */ +#endif +#endif + +#ifdef __i386__ +#define PRIxPTR "x" /* uintptr_t */ +#else +#define PRIxPTR "lx" /* uintptr_t */ +#endif + +#define PRIX8 "X" /* uint8_t */ +#define PRIX16 "X" /* uint16_t */ +#define PRIX32 "X" /* uint32_t */ + +#ifdef __x86_64__ +#define PRIX64 "lX" /* uint64_t */ +#else +#define PRIX64 "llX" /* uint64_t */ +#endif + +#define PRIXLEAST8 "X" /* uint_least8_t */ +#define PRIXLEAST16 "X" /* uint_least16_t */ +#define PRIXLEAST32 "X" /* uint_least32_t */ +#ifdef __x86_64__ +#define PRIXLEAST64 "lX" /* uint_least64_t */ +#else +#define PRIXLEAST64 "llX" /* uint_least64_t */ +#endif + +#define PRIXFAST8 "X" /* uint_fast8_t */ +#ifdef __x86_64__ +#define PRIXFAST16 "lX" /* uint_fast16_t */ +#define PRIXFAST32 "lX" /* uint_fast32_t */ +#define PRIXFAST64 "lX" /* uint_fast64_t */ +#else +#define PRIXFAST16 "X" /* uint_fast16_t */ +#define PRIXFAST32 "X" /* uint_fast32_t */ +#define PRIXFAST64 "llX" /* uint_fast64_t */ +#endif + +#ifdef __x86_64__ +#define PRIXMAX "lX" /* uintmax_t */ +#else +#if defined(__i386__) +#define PRIXMAX "llX" /* uintmax_t */ +#else +#define PRIXMAX "jX" /* uintmax_t */ +#endif +#endif + +#ifdef __i386__ +#define PRIXPTR "X" /* uintptr_t */ +#else +#define PRIXPTR "lX" /* uintptr_t */ +#endif + +typedef struct { + intmax_t quot; /* quotient */ + intmax_t rem; /* remainder */ +} imaxdiv_t; + +__BEGIN_DECLS + +intmax_t _TLIBC_CDECL_ imaxabs(intmax_t); +imaxdiv_t _TLIBC_CDECL_ imaxdiv(intmax_t, intmax_t); +intmax_t _TLIBC_CDECL_ strtoimax(const char *, char **, int); +uintmax_t _TLIBC_CDECL_ strtoumax(const char *, char **, int); + +__END_DECLS + +#endif /* _INTTYPES_H_ */ diff --git a/bitacross-worker/rust-sgx-sdk/common/inc/iso646.h b/bitacross-worker/rust-sgx-sdk/common/inc/iso646.h new file mode 100644 index 0000000000..a0c341b658 --- /dev/null +++ b/bitacross-worker/rust-sgx-sdk/common/inc/iso646.h @@ -0,0 +1,26 @@ +/* $OpenBSD: iso646.h,v 1.3 2001/10/11 00:05:21 espie Exp $ */ +/* $NetBSD: iso646.h,v 1.1 1995/02/17 09:08:10 jtc Exp $ */ + +/* + * Written by J.T. Conklin 02/16/95. + * Public domain. + */ + +#ifndef _ISO646_H_ +#define _ISO646_H_ + +#ifndef __cplusplus +#define and && +#define and_eq &= +#define bitand & +#define bitor | +#define compl ~ +#define not ! +#define not_eq != +#define or || +#define or_eq |= +#define xor ^ +#define xor_eq ^= +#endif + +#endif /* !_ISO646_H_ */ diff --git a/bitacross-worker/rust-sgx-sdk/common/inc/limits.h b/bitacross-worker/rust-sgx-sdk/common/inc/limits.h new file mode 100644 index 0000000000..9d42cb545c --- /dev/null +++ b/bitacross-worker/rust-sgx-sdk/common/inc/limits.h @@ -0,0 +1,41 @@ +/* $OpenBSD: limits.h,v 1.15 2008/02/10 09:59:54 kettenis Exp $ */ +/* $NetBSD: limits.h,v 1.7 1994/10/26 00:56:00 cgd Exp $ */ + +/* + * Copyright (c) 1988 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)limits.h 5.9 (Berkeley) 4/3/91 + */ + + +#ifndef _LIMITS_H_ +#define _LIMITS_H_ + +#include + +#endif /* !_LIMITS_H_ */ diff --git a/bitacross-worker/rust-sgx-sdk/common/inc/math.h b/bitacross-worker/rust-sgx-sdk/common/inc/math.h new file mode 100644 index 0000000000..6ea425b840 --- /dev/null +++ b/bitacross-worker/rust-sgx-sdk/common/inc/math.h @@ -0,0 +1,430 @@ +/* $OpenBSD: math.h,v 1.27 2010/12/14 11:16:15 martynas Exp $ */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* + * from: @(#)fdlibm.h 5.1 93/09/24 + */ + +#ifndef _MATH_H_ +#define _MATH_H_ + +#include +#include +#include + +#include + +typedef __float_t float_t; +typedef __double_t double_t; + +#define FP_NAN 0x00 +#define FP_INFINITE 0x01 +#define FP_ZERO 0x02 +#define FP_SUBNORMAL 0x03 +#define FP_NORMAL 0x04 + +#define FP_ILOGB0 (-INT_MAX - 1) +#define FP_ILOGBNAN (-INT_MAX - 1) + +#define fpclassify(x) \ + ((sizeof (x) == sizeof (float)) ? \ + __fpclassifyf(x) \ + : (sizeof (x) == sizeof (double)) ? \ + __fpclassify(x) \ + : __fpclassifyl(x)) +#define isfinite(x) \ + ((sizeof (x) == sizeof (float)) ? \ + __isfinitef(x) \ + : (sizeof (x) == sizeof (double)) ? \ + __isfinite(x) \ + : __isfinitel(x)) +#define isnormal(x) \ + ((sizeof (x) == sizeof (float)) ? \ + __isnormalf(x) \ + : (sizeof (x) == sizeof (double)) ? \ + __isnormal(x) \ + : __isnormall(x)) +#define signbit(x) \ + ((sizeof (x) == sizeof (float)) ? \ + __signbitf(x) \ + : (sizeof (x) == sizeof (double)) ? \ + __signbit(x) \ + : __signbitl(x)) +#define isinf(x) \ + ((sizeof (x) == sizeof (float)) ? \ + __isinff(x) \ + : (sizeof (x) == sizeof (double)) ? \ + __isinf(x) \ + : __isinfl(x)) +#define isnan(x) \ + ((sizeof (x) == sizeof (float)) ? \ + __isnanf(x) \ + : (sizeof (x) == sizeof (double)) ? \ + __isnan(x) \ + : __isnanl(x)) + +#define isgreater(x, y) (!isunordered((x), (y)) && (x) > (y)) +#define isgreaterequal(x, y) (!isunordered((x), (y)) && (x) >= (y)) +#define isless(x, y) (!isunordered((x), (y)) && (x) < (y)) +#define islessequal(x, y) (!isunordered((x), (y)) && (x) <= (y)) +#define islessgreater(x, y) (!isunordered((x), (y)) && ((x) > (y) || (y) > (x))) +#define isunordered(x, y) (isnan(x) || isnan(y)) + +__BEGIN_DECLS + +extern char __infinity[]; +#define HUGE_VAL (*(double *)(void *)__infinity) +#define HUGE_VALF ((float)HUGE_VAL) +#define HUGE_VALL ((long double)HUGE_VAL) +#define INFINITY HUGE_VALF +extern char __nan[]; +#define NAN (*(float *)(void *)__nan) + +/* + * ANSI/POSIX + */ +double _TLIBC_CDECL_ acos(double); +double _TLIBC_CDECL_ asin(double); +double _TLIBC_CDECL_ atan(double); +double _TLIBC_CDECL_ atan2(double, double); +double _TLIBC_CDECL_ cos(double); +double _TLIBC_CDECL_ sin(double); +double _TLIBC_CDECL_ tan(double); + +double _TLIBC_CDECL_ cosh(double); +double _TLIBC_CDECL_ sinh(double); +double _TLIBC_CDECL_ tanh(double); + +double _TLIBC_CDECL_ exp(double); +double _TLIBC_CDECL_ frexp(double, int *); +double _TLIBC_CDECL_ ldexp(double, int); +double _TLIBC_CDECL_ log(double); +double _TLIBC_CDECL_ log10(double); +double _TLIBC_CDECL_ modf(double, double *); + +double _TLIBC_CDECL_ pow(double, double); +double _TLIBC_CDECL_ sqrt(double); + +double _TLIBC_CDECL_ ceil(double); +double _TLIBC_CDECL_ fabs(double); +double _TLIBC_CDECL_ floor(double); +double _TLIBC_CDECL_ fmod(double, double); + +/* + * C99 + */ +double _TLIBC_CDECL_ acosh(double); +double _TLIBC_CDECL_ asinh(double); +double _TLIBC_CDECL_ atanh(double); + +double _TLIBC_CDECL_ exp2(double); +double _TLIBC_CDECL_ expm1(double); +int _TLIBC_CDECL_ ilogb(double); +double _TLIBC_CDECL_ log1p(double); +double _TLIBC_CDECL_ log2(double); +double _TLIBC_CDECL_ logb(double); +double _TLIBC_CDECL_ scalbn(double, int); +double _TLIBC_CDECL_ scalbln(double, long int); + +double _TLIBC_CDECL_ cbrt(double); +double _TLIBC_CDECL_ hypot(double, double); + +double _TLIBC_CDECL_ erf(double); +double _TLIBC_CDECL_ erfc(double); +double _TLIBC_CDECL_ lgamma(double); +double _TLIBC_CDECL_ tgamma(double); + +double _TLIBC_CDECL_ nearbyint(double); +double _TLIBC_CDECL_ rint(double); +long int _TLIBC_CDECL_ lrint(double); +long long int _TLIBC_CDECL_ llrint(double); +double _TLIBC_CDECL_ round(double); +long int _TLIBC_CDECL_ lround(double); +long long int _TLIBC_CDECL_ llround(double); +double _TLIBC_CDECL_ trunc(double); + +double _TLIBC_CDECL_ remainder(double, double); +double _TLIBC_CDECL_ remquo(double, double, int *); + +double _TLIBC_CDECL_ copysign(double, double); +double _TLIBC_CDECL_ nan(const char *); +double _TLIBC_CDECL_ nextafter(double, double); + +double _TLIBC_CDECL_ fdim(double, double); +double _TLIBC_CDECL_ fmax(double, double); +double _TLIBC_CDECL_ fmin(double, double); + +double _TLIBC_CDECL_ fma(double, double, double); + +/* + * Float versions of C99 functions + */ + +float _TLIBC_CDECL_ acosf(float); +float _TLIBC_CDECL_ asinf(float); +float _TLIBC_CDECL_ atanf(float); +float _TLIBC_CDECL_ atan2f(float, float); +float _TLIBC_CDECL_ cosf(float); +float _TLIBC_CDECL_ sinf(float); +float _TLIBC_CDECL_ tanf(float); + +float _TLIBC_CDECL_ acoshf(float); +float _TLIBC_CDECL_ asinhf(float); +float _TLIBC_CDECL_ atanhf(float); +float _TLIBC_CDECL_ coshf(float); +float _TLIBC_CDECL_ sinhf(float); +float _TLIBC_CDECL_ tanhf(float); + +float _TLIBC_CDECL_ expf(float); +float _TLIBC_CDECL_ exp2f(float); +float _TLIBC_CDECL_ expm1f(float); +float _TLIBC_CDECL_ frexpf(float, int *); +int _TLIBC_CDECL_ ilogbf(float); +float _TLIBC_CDECL_ ldexpf(float, int); +float _TLIBC_CDECL_ logf(float); +float _TLIBC_CDECL_ log10f(float); +float _TLIBC_CDECL_ log1pf(float); +float _TLIBC_CDECL_ log2f(float); +float _TLIBC_CDECL_ logbf(float); +float _TLIBC_CDECL_ modff(float, float *); +float _TLIBC_CDECL_ scalbnf(float, int); +float _TLIBC_CDECL_ scalblnf(float, long int); + +float _TLIBC_CDECL_ cbrtf(float); +float _TLIBC_CDECL_ fabsf(float); +float _TLIBC_CDECL_ hypotf(float, float); +float _TLIBC_CDECL_ powf(float, float); +float _TLIBC_CDECL_ sqrtf(float); + +float _TLIBC_CDECL_ erff(float); +float _TLIBC_CDECL_ erfcf(float); +float _TLIBC_CDECL_ lgammaf(float); +float _TLIBC_CDECL_ tgammaf(float); + +float _TLIBC_CDECL_ ceilf(float); +float _TLIBC_CDECL_ floorf(float); +float _TLIBC_CDECL_ nearbyintf(float); + +float _TLIBC_CDECL_ rintf(float); +long int _TLIBC_CDECL_ lrintf(float); +long long int _TLIBC_CDECL_ llrintf(float); +float _TLIBC_CDECL_ roundf(float); +long int _TLIBC_CDECL_ lroundf(float); +long long int _TLIBC_CDECL_ llroundf(float); +float _TLIBC_CDECL_ truncf(float); + +float _TLIBC_CDECL_ fmodf(float, float); +float _TLIBC_CDECL_ remainderf(float, float); +float _TLIBC_CDECL_ remquof(float, float, int *); + +float _TLIBC_CDECL_ copysignf(float, float); +float _TLIBC_CDECL_ nanf(const char *); +float _TLIBC_CDECL_ nextafterf(float, float); + +float _TLIBC_CDECL_ fdimf(float, float); +float _TLIBC_CDECL_ fmaxf(float, float); +float _TLIBC_CDECL_ fminf(float, float); + +float _TLIBC_CDECL_ fmaf(float, float, float); + +/* + * Long double versions of C99 functions + */ + +/* Macros defining long double functions to be their double counterparts + * (long double is synonymous with double in this implementation). + */ + +long double _TLIBC_CDECL_ acosl(long double); +long double _TLIBC_CDECL_ asinl(long double); +long double _TLIBC_CDECL_ atanl(long double); +long double _TLIBC_CDECL_ atan2l(long double, long double); +long double _TLIBC_CDECL_ cosl(long double); +long double _TLIBC_CDECL_ sinl(long double); +long double _TLIBC_CDECL_ tanl(long double); + +long double _TLIBC_CDECL_ acoshl(long double); +long double _TLIBC_CDECL_ asinhl(long double); +long double _TLIBC_CDECL_ atanhl(long double); +long double _TLIBC_CDECL_ coshl(long double); +long double _TLIBC_CDECL_ sinhl(long double); +long double _TLIBC_CDECL_ tanhl(long double); + +long double _TLIBC_CDECL_ expl(long double); +long double _TLIBC_CDECL_ exp2l(long double); +long double _TLIBC_CDECL_ expm1l(long double); +long double _TLIBC_CDECL_ frexpl(long double, int *); +int _TLIBC_CDECL_ ilogbl(long double); +long double _TLIBC_CDECL_ ldexpl(long double, int); +long double _TLIBC_CDECL_ logl(long double); +long double _TLIBC_CDECL_ log10l(long double); +long double _TLIBC_CDECL_ log1pl(long double); +long double _TLIBC_CDECL_ log2l(long double); +long double _TLIBC_CDECL_ logbl(long double); +long double _TLIBC_CDECL_ modfl(long double, long double *); +long double _TLIBC_CDECL_ scalbnl(long double, int); +long double _TLIBC_CDECL_ scalblnl(long double, long int); + +long double _TLIBC_CDECL_ cbrtl(long double); +long double _TLIBC_CDECL_ fabsl(long double); +long double _TLIBC_CDECL_ hypotl(long double, long double); +long double _TLIBC_CDECL_ powl(long double, long double); +long double _TLIBC_CDECL_ sqrtl(long double); + +long double _TLIBC_CDECL_ erfl(long double); +long double _TLIBC_CDECL_ erfcl(long double); +long double _TLIBC_CDECL_ lgammal(long double); +long double _TLIBC_CDECL_ tgammal(long double); + +long double _TLIBC_CDECL_ ceill(long double); +long double _TLIBC_CDECL_ floorl(long double); +long double _TLIBC_CDECL_ nearbyintl(long double); +long double _TLIBC_CDECL_ rintl(long double); +long int _TLIBC_CDECL_ lrintl(long double); +long long int _TLIBC_CDECL_ llrintl(long double); +long double _TLIBC_CDECL_ roundl(long double); +long int _TLIBC_CDECL_ lroundl(long double); +long long int _TLIBC_CDECL_ llroundl(long double); +long double _TLIBC_CDECL_ truncl(long double); + +long double _TLIBC_CDECL_ fmodl(long double, long double); +long double _TLIBC_CDECL_ remainderl(long double, long double); +long double _TLIBC_CDECL_ remquol(long double, long double, int *); + +long double _TLIBC_CDECL_ copysignl(long double, long double); +long double _TLIBC_CDECL_ nanl(const char *); +long double _TLIBC_CDECL_ nextafterl(long double, long double); + +long double _TLIBC_CDECL_ fdiml(long double, long double); +long double _TLIBC_CDECL_ fmaxl(long double, long double); +long double _TLIBC_CDECL_ fminl(long double, long double); +long double _TLIBC_CDECL_ fmal(long double, long double, long double); + +/* nexttoward(): +* The implementation in Intel math library is incompatible with MSVC. +* Because sizeof(long double) is 8bytes with MSVC, +* but the expected long double size is 10bytes. +* And by default, MSVC doesn't provide nexttoward(). +* So we only provide Linux version here. +*/ +double _TLIBC_CDECL_ nexttoward(double, long double); +float _TLIBC_CDECL_ nexttowardf(float, long double); + +long double _TLIBC_CDECL_ nexttowardl(long double, long double); + +/* + * Library implementation + */ +int _TLIBC_CDECL_ __fpclassify(double); +int _TLIBC_CDECL_ __fpclassifyf(float); +int _TLIBC_CDECL_ __isfinite(double); +int _TLIBC_CDECL_ __isfinitef(float); +int _TLIBC_CDECL_ __isinf(double); +int _TLIBC_CDECL_ __isinff(float); +int _TLIBC_CDECL_ __isnan(double); +int _TLIBC_CDECL_ __isnanf(float); +int _TLIBC_CDECL_ __isnormal(double); +int _TLIBC_CDECL_ __isnormalf(float); +int _TLIBC_CDECL_ __signbit(double); +int _TLIBC_CDECL_ __signbitf(float); + +int _TLIBC_CDECL_ __fpclassifyl(long double); +int _TLIBC_CDECL_ __isfinitel(long double); +int _TLIBC_CDECL_ __isinfl(long double); +int _TLIBC_CDECL_ __isnanl(long double); +int _TLIBC_CDECL_ __isnormall(long double); +int _TLIBC_CDECL_ __signbitl(long double); + +/* + * Non-C99 functions. + */ +double _TLIBC_CDECL_ drem(double, double); +double _TLIBC_CDECL_ exp10(double); +double _TLIBC_CDECL_ gamma(double); +double _TLIBC_CDECL_ gamma_r(double, int *); +double _TLIBC_CDECL_ j0(double); +double _TLIBC_CDECL_ j1(double); +double _TLIBC_CDECL_ jn(int, double); +double _TLIBC_CDECL_ lgamma_r(double, int *); +double _TLIBC_CDECL_ pow10(double); +double _TLIBC_CDECL_ scalb(double, double); +/* C99 Macro signbit.*/ +double _TLIBC_CDECL_ significand(double); +void _TLIBC_CDECL_ sincos(double, double *, double *); +double _TLIBC_CDECL_ y0(double); +double _TLIBC_CDECL_ y1(double); +double _TLIBC_CDECL_ yn(int, double); +/* C99 Macro isinf.*/ +/* C99 Macro isnan.*/ +int _TLIBC_CDECL_ finite(double); + +float _TLIBC_CDECL_ dremf(float, float); +float _TLIBC_CDECL_ exp10f(float); +float _TLIBC_CDECL_ gammaf(float); +float _TLIBC_CDECL_ gammaf_r(float, int *); +float _TLIBC_CDECL_ j0f(float); +float _TLIBC_CDECL_ j1f(float); +float _TLIBC_CDECL_ jnf(int, float); +float _TLIBC_CDECL_ lgammaf_r(float, int *); +float _TLIBC_CDECL_ pow10f(float); +float _TLIBC_CDECL_ scalbf(float, float); +int _TLIBC_CDECL_ signbitf(float); +float _TLIBC_CDECL_ significandf(float); +void _TLIBC_CDECL_ sincosf(float, float *, float *); +float _TLIBC_CDECL_ y0f(float); +float _TLIBC_CDECL_ y1f(float); +float _TLIBC_CDECL_ ynf(int, float); +int _TLIBC_CDECL_ finitef(float); +int _TLIBC_CDECL_ isinff(float); +int _TLIBC_CDECL_ isnanf(float); + +long double _TLIBC_CDECL_ dreml(long double, long double); +long double _TLIBC_CDECL_ exp10l(long double); +long double _TLIBC_CDECL_ gammal(long double); +long double _TLIBC_CDECL_ gammal_r(long double, int *); +long double _TLIBC_CDECL_ j0l(long double); +long double _TLIBC_CDECL_ j1l(long double); +long double _TLIBC_CDECL_ jnl(int, long double); +long double _TLIBC_CDECL_ lgammal_r(long double, int *); +long double _TLIBC_CDECL_ pow10l(long double); +long double _TLIBC_CDECL_ scalbl(long double, long double); +int _TLIBC_CDECL_ signbitl(long double); +long double _TLIBC_CDECL_ significandl(long double); +void _TLIBC_CDECL_ sincosl(long double, long double *, long double *); +long double _TLIBC_CDECL_ y1l(long double); +long double _TLIBC_CDECL_ y0l(long double); +long double _TLIBC_CDECL_ ynl(int, long double); +int _TLIBC_CDECL_ finitel(long double); +int _TLIBC_CDECL_ isinfl(long double); +int _TLIBC_CDECL_ isnanl(long double); + +/* + * TODO: From Intel Decimal Floating-Point Math Library + * signbitd32/signbitd64/signbitd128, finited32/finited64/finited128 + * isinfd32/isinfd64/isinfd128, isnand32/isnand64/isnand128 + */ +#if defined(__cplusplus) +/* Clang does not support decimal floating point types. + * + * c.f.: + * http://clang.llvm.org/docs/UsersManual.html#gcc-extensions-not-implemented-yet + */ +#if !defined(__clang__) +typedef float _Decimal32 __attribute__((mode(SD))); +typedef float _Decimal64 __attribute__((mode(DD))); +typedef float _Decimal128 __attribute__((mode(TD))); +#endif +#endif + +__END_DECLS + +#endif /* !_MATH_H_ */ diff --git a/bitacross-worker/rust-sgx-sdk/common/inc/mbusafecrt.h b/bitacross-worker/rust-sgx-sdk/common/inc/mbusafecrt.h new file mode 100644 index 0000000000..91d888b3f8 --- /dev/null +++ b/bitacross-worker/rust-sgx-sdk/common/inc/mbusafecrt.h @@ -0,0 +1,85 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +/*** +* mbusafecrt.h - public declarations for SafeCRT lib +* + +* +* Purpose: +* This file contains the public declarations SafeCRT +* functions ported to MacOS. These are the safe versions of +* functions standard functions banned by SWI +* + +****/ + +/* shields! */ + +#ifndef MBUSAFECRT_H +#define MBUSAFECRT_H +#include +#include +#include +typedef wchar_t WCHAR; + +#ifdef __cplusplus + extern "C" { +#endif + +extern errno_t strcat_s( char* ioDest, size_t inDestBufferSize, const char* inSrc ); +extern errno_t wcscat_s( WCHAR* ioDest, size_t inDestBufferSize, const WCHAR* inSrc ); + +extern errno_t strncat_s( char* ioDest, size_t inDestBufferSize, const char* inSrc, size_t inCount ); +extern errno_t wcsncat_s( WCHAR* ioDest, size_t inDestBufferSize, const WCHAR* inSrc, size_t inCount ); + +extern errno_t strcpy_s( char* outDest, size_t inDestBufferSize, const char* inSrc ); +extern errno_t wcscpy_s( WCHAR* outDest, size_t inDestBufferSize, const WCHAR* inSrc ); + +extern errno_t strncpy_s( char* outDest, size_t inDestBufferSize, const char* inSrc, size_t inCount ); +extern errno_t wcsncpy_s( WCHAR* outDest, size_t inDestBufferSize, const WCHAR* inSrc, size_t inCount ); + +extern char* strtok_s( char* inString, const char* inControl, char** ioContext ); +extern WCHAR* wcstok_s( WCHAR* inString, const WCHAR* inControl, WCHAR** ioContext ); + +extern size_t wcsnlen( const WCHAR* inString, size_t inMaxSize ); + +extern errno_t _itoa_s( int inValue, char* outBuffer, size_t inDestBufferSize, int inRadix ); +extern errno_t _itow_s( int inValue, WCHAR* outBuffer, size_t inDestBufferSize, int inRadix ); + +extern errno_t _ltoa_s( long inValue, char* outBuffer, size_t inDestBufferSize, int inRadix ); +extern errno_t _ltow_s( long inValue, WCHAR* outBuffer, size_t inDestBufferSize, int inRadix ); + +extern errno_t _ultoa_s( unsigned long inValue, char* outBuffer, size_t inDestBufferSize, int inRadix ); +extern errno_t _ultow_s( unsigned long inValue, WCHAR* outBuffer, size_t inDestBufferSize, int inRadix ); + +extern errno_t _i64toa_s( long long inValue, char* outBuffer, size_t inDestBufferSize, int inRadix ); +extern errno_t _i64tow_s( long long inValue, WCHAR* outBuffer, size_t inDestBufferSize, int inRadix ); + +extern errno_t _ui64toa_s( unsigned long long inValue, char* outBuffer, size_t inDestBufferSize, int inRadix ); +extern errno_t _ui64tow_s( unsigned long long inValue, WCHAR* outBuffer, size_t inDestBufferSize, int inRadix ); + +extern int sprintf_s( char *string, size_t sizeInBytes, const char *format, ... ); +extern int swprintf_s( WCHAR *string, size_t sizeInWords, const WCHAR *format, ... ); + +extern int _snprintf_s( char *string, size_t sizeInBytes, size_t count, const char *format, ... ); +extern int _snwprintf_s( WCHAR *string, size_t sizeInWords, size_t count, const WCHAR *format, ... ); + +extern int _vsprintf_s( char* string, size_t sizeInBytes, const char* format, va_list arglist ); +extern int _vsnprintf_s( char* string, size_t sizeInBytes, size_t count, const char* format, va_list arglist ); + +extern int _vswprintf_s( WCHAR* string, size_t sizeInWords, const WCHAR* format, va_list arglist ); +extern int _vsnwprintf_s( WCHAR* string, size_t sizeInWords, size_t count, const WCHAR* format, va_list arglist ); + +extern errno_t memcpy_s( void * dst, size_t sizeInBytes, const void * src, size_t count ); +extern errno_t memcpy_verw_s( void * dst, size_t sizeInBytes, const void * src, size_t count ); +extern errno_t memmove_s( void * dst, size_t sizeInBytes, const void * src, size_t count ); +extern errno_t memmove_verw_s( void * dst, size_t sizeInBytes, const void * src, size_t count ); + +#ifdef __cplusplus + } +#endif + +#endif /* MBUSAFECRT_H */ diff --git a/bitacross-worker/rust-sgx-sdk/common/inc/netdb.h b/bitacross-worker/rust-sgx-sdk/common/inc/netdb.h new file mode 100644 index 0000000000..264f90ff39 --- /dev/null +++ b/bitacross-worker/rust-sgx-sdk/common/inc/netdb.h @@ -0,0 +1,41 @@ +// +// Copyright © 2005-2020 Rich Felker, et al. +// Licensed under the MIT license.s +// + +/* Copyright © 2005-2020 Rich Felker, et al. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef _NETDB_H +#define _NETDB_H + +struct addrinfo { + int ai_flags; + int ai_family; + int ai_socktype; + int ai_protocol; + socklen_t ai_addrlen; + struct sockaddr *ai_addr; + char *ai_canonname; + struct addrinfo *ai_next; +}; + +#endif diff --git a/bitacross-worker/rust-sgx-sdk/common/inc/poll.h b/bitacross-worker/rust-sgx-sdk/common/inc/poll.h new file mode 100644 index 0000000000..fc786fc279 --- /dev/null +++ b/bitacross-worker/rust-sgx-sdk/common/inc/poll.h @@ -0,0 +1,38 @@ +// +// Copyright © 2005-2020 Rich Felker, et al. +// Licensed under the MIT license. +// + +/* Copyright © 2005-2020 Rich Felker, et al. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef _POLL_H_ +#define _POLL_H_ + +typedef unsigned long nfds_t; + +struct pollfd { + int fd; + short int events; + short int revents; +}; + +#endif diff --git a/bitacross-worker/rust-sgx-sdk/common/inc/pthread.h b/bitacross-worker/rust-sgx-sdk/common/inc/pthread.h new file mode 100644 index 0000000000..e79668ffd6 --- /dev/null +++ b/bitacross-worker/rust-sgx-sdk/common/inc/pthread.h @@ -0,0 +1,34 @@ +#ifndef _SYS_THREAD_H_ +#define _SYS_THREAD_H_ + +/* Thread identifiers. The structure of the attribute type is not + exposed on purpose. */ +typedef unsigned long int pthread_t; + +#if defined __x86_64__ && !defined __ILP32__ +# define __WORDSIZE 64 +#else +# define __WORDSIZE 32 +#define __WORDSIZE32_SIZE_ULONG 0 +#define __WORDSIZE32_PTRDIFF_LONG 0 +#endif + +#ifdef __x86_64__ +# if __WORDSIZE == 64 +# define __SIZEOF_PTHREAD_ATTR_T 56 +# else +# define __SIZEOF_PTHREAD_ATTR_T 32 +#endif + +union pthread_attr_t +{ + char __size[__SIZEOF_PTHREAD_ATTR_T]; + long int __align; +}; +#ifndef __have_pthread_attr_t +typedef union pthread_attr_t pthread_attr_t; +# define __have_pthread_attr_t 1 +#endif + +#endif +#endif diff --git a/bitacross-worker/rust-sgx-sdk/common/inc/pwd.h b/bitacross-worker/rust-sgx-sdk/common/inc/pwd.h new file mode 100644 index 0000000000..a45b145a94 --- /dev/null +++ b/bitacross-worker/rust-sgx-sdk/common/inc/pwd.h @@ -0,0 +1,40 @@ +// +// Copyright © 2005-2020 Rich Felker, et al. +// Licensed under the MIT license. +// + +/* Copyright © 2005-2020 Rich Felker, et al. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef _PWD_H +#define _PWD_H + +struct passwd { + char *pw_name; + char *pw_passwd; + __uid_t pw_uid; + __gid_t pw_gid; + char *pw_gecos; + char *pw_dir; + char *pw_shell; +}; + +#endif diff --git a/bitacross-worker/rust-sgx-sdk/common/inc/sched.h b/bitacross-worker/rust-sgx-sdk/common/inc/sched.h new file mode 100644 index 0000000000..4d237c4044 --- /dev/null +++ b/bitacross-worker/rust-sgx-sdk/common/inc/sched.h @@ -0,0 +1,62 @@ +// +// Copyright © 2005-2020 Rich Felker, et al. +// Licensed under the MIT license.s +// + +/* Copyright © 2005-2020 Rich Felker, et al. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef _SCHED_H +#define _SCHED_H +#include + +typedef struct { + unsigned long __bits[128/sizeof(long)]; +} cpu_set_t; + +#define __CPU_op_S(i, size, set, op) ( (i)/8U >= (size) ? 0 : \ + (((unsigned long *)(set))[(i)/8/sizeof(long)] op (1UL<<((i)%(8*sizeof(long))))) ) + +#define CPU_SET_S(i, size, set) __CPU_op_S(i, size, set, |=) +#define CPU_CLR_S(i, size, set) __CPU_op_S(i, size, set, &=~) +#define CPU_ISSET_S(i, size, set) __CPU_op_S(i, size, set, &) + +#define __CPU_op_func_S(func, op) \ +static __inline void __CPU_##func##_S(size_t __size, cpu_set_t *__dest, \ + const cpu_set_t *__src1, const cpu_set_t *__src2) \ +{ \ + size_t __i; \ + for (__i=0; __i<__size/sizeof(long); __i++) \ + ((unsigned long *)__dest)[__i] = ((unsigned long *)__src1)[__i] \ + op ((unsigned long *)__src2)[__i] ; \ +} + +__CPU_op_func_S(AND, &) +__CPU_op_func_S(OR, |) +__CPU_op_func_S(XOR, ^) + +#define CPU_AND_S(a,b,c,d) __CPU_AND_S(a,b,c,d) +#define CPU_OR_S(a,b,c,d) __CPU_OR_S(a,b,c,d) +#define CPU_XOR_S(a,b,c,d) __CPU_XOR_S(a,b,c,d) + +typedef __pid_t pid_t; + +#endif diff --git a/bitacross-worker/rust-sgx-sdk/common/inc/setjmp.h b/bitacross-worker/rust-sgx-sdk/common/inc/setjmp.h new file mode 100644 index 0000000000..752f0cf763 --- /dev/null +++ b/bitacross-worker/rust-sgx-sdk/common/inc/setjmp.h @@ -0,0 +1,65 @@ +/* $NetBSD: setjmp.h,v 1.26 2011/11/05 09:27:06 joerg Exp $ */ + +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)setjmp.h 8.2 (Berkeley) 1/21/94 + */ + +#ifndef _SETJMP_H_ +#define _SETJMP_H_ + +#ifndef _JB_ATTRIBUTES +#define _JB_ATTRIBUTES /**/ +#else +#endif +#ifndef _BSD_JBSLOT_T_ +#define _BSD_JBSLOT_T_ long +#endif + +#define _JBLEN 8 + +typedef _BSD_JBSLOT_T_ jmp_buf[_JBLEN] _JB_ATTRIBUTES; + +#include +#define __returns_twice __attribute__((__returns_twice__)) +#define __dead + + +__BEGIN_DECLS +int setjmp(jmp_buf) __returns_twice; +void longjmp(jmp_buf, int) __dead; +__END_DECLS + +#endif /* !_SETJMP_H_ */ + diff --git a/bitacross-worker/rust-sgx-sdk/common/inc/signal.h b/bitacross-worker/rust-sgx-sdk/common/inc/signal.h new file mode 100644 index 0000000000..c0da74f456 --- /dev/null +++ b/bitacross-worker/rust-sgx-sdk/common/inc/signal.h @@ -0,0 +1,104 @@ +// +// Copyright © 2005-2020 Rich Felker, et al. +// Licensed under the MIT license.s +// + +/* Copyright © 2005-2020 Rich Felker, et al. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef _SIGNAL_H +#define _SIGNAL_H + +#include + +typedef struct { + unsigned long _bits[128/sizeof(long)]; +} __sigset_t; + +typedef __sigset_t sigset_t; + +union sigval { + int sival_int; + void *sival_ptr; +}; + +typedef struct { + int si_signo; + int si_errno; + int si_code; + union { + char __pad[128 - 2*sizeof(int) - sizeof(long)]; + struct { + union { + struct { + __pid_t si_pid; + __uid_t si_uid; + } __piduid; + struct { + int si_timerid; + int si_overrun; + } __timer; + } __first; + union { + union sigval si_value; + struct { + int si_status; + __clock_t si_utime, si_stime; + } __sigchld; + } __second; + } __si_common; + struct { + void *si_addr; + short si_addr_lsb; + union { + struct { + void *si_lower; + void *si_upper; + } __addr_bnd; + unsigned si_pkey; + } __first; + } __sigfault; + struct { + long si_band; + int si_fd; + } __sigpoll; + struct { + void *si_call_addr; + int si_syscall; + unsigned si_arch; + } __sigsys; + } __si_fields; +} siginfo_t; + +struct sigaction { + union { + void (*sa_handler) (int); + void (*sa_sigaction) (int, siginfo_t *, void *); + } __sa_handler; + __sigset_t sa_mask; + int sa_flags; + void (*sa_restorer) (void); +}; + +#define sa_handler __sa_handler.sa_handler +#define sa_sigaction __sa_handler.sa_sigaction + +#endif diff --git a/bitacross-worker/rust-sgx-sdk/common/inc/stdalign.h b/bitacross-worker/rust-sgx-sdk/common/inc/stdalign.h new file mode 100644 index 0000000000..93b8f6016e --- /dev/null +++ b/bitacross-worker/rust-sgx-sdk/common/inc/stdalign.h @@ -0,0 +1,15 @@ +#ifndef _STDALIGN_H +#define _STDALIGN_H +#ifndef __cplusplus +/* this whole header only works in C11 or with compiler extensions */ +#if __STDC_VERSION__ < 201112L && defined( __GNUC__) +#define _Alignas(t) __attribute__((__aligned__(t))) +#define _Alignof(t) __alignof__(t) +#endif +#define alignas _Alignas +#define alignof _Alignof +#endif +#define __alignas_is_defined 1 +#define __alignof_is_defined 1 +#endif + diff --git a/bitacross-worker/rust-sgx-sdk/common/inc/stdarg.h b/bitacross-worker/rust-sgx-sdk/common/inc/stdarg.h new file mode 100644 index 0000000000..b2a5d36e82 --- /dev/null +++ b/bitacross-worker/rust-sgx-sdk/common/inc/stdarg.h @@ -0,0 +1,48 @@ +/* $OpenBSD: stdarg.h,v 1.14 2010/12/30 05:01:36 tedu Exp $ */ +/* $NetBSD: stdarg.h,v 1.12 1995/12/25 23:15:31 mycroft Exp $ */ + +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)stdarg.h 8.1 (Berkeley) 6/10/93 + */ + +#ifndef _STDARG_H_ +#define _STDARG_H_ + +#include +#include + +typedef __va_list va_list; + +#define va_start(ap, last) __builtin_va_start((ap), last) +#define va_end __builtin_va_end +#define va_arg __builtin_va_arg +#define va_copy(dst, src) __builtin_va_copy((dst),(src)) + +#endif /* !_STDARG_H_ */ diff --git a/bitacross-worker/rust-sgx-sdk/common/inc/stdbool.h b/bitacross-worker/rust-sgx-sdk/common/inc/stdbool.h new file mode 100644 index 0000000000..86b866d5d7 --- /dev/null +++ b/bitacross-worker/rust-sgx-sdk/common/inc/stdbool.h @@ -0,0 +1,44 @@ +/* $OpenBSD: stdbool.h,v 1.5 2010/07/24 22:17:03 guenther Exp $ */ + +/* + * Written by Marc Espie, September 25, 1999 + * Public domain. + */ + +#ifndef _STDBOOL_H_ +#define _STDBOOL_H_ + +#ifndef __cplusplus + +#ifndef __GNUC__ +/* Support for _C99: type _Bool is already built-in. */ +/* `_Bool' type must promote to `int' or `unsigned int'. */ +typedef enum { + false = 0, + true = 1 +} _Bool; + +/* And those constants must also be available as macros. */ +# define false false +# define true true +#else /* __GNUC__ */ +# define false 0 +# define true 1 +#endif + +/* User visible type `bool' is provided as a macro which may be redefined */ +#define bool _Bool + +#else /* __cplusplus */ + +# define _Bool bool +# define bool bool +# define false false +# define true true + +#endif + +/* Inform that everything is fine */ +#define __bool_true_false_are_defined 1 + +#endif /* _STDBOOL_H_ */ diff --git a/bitacross-worker/rust-sgx-sdk/common/inc/stddef.h b/bitacross-worker/rust-sgx-sdk/common/inc/stddef.h new file mode 100644 index 0000000000..62d653029d --- /dev/null +++ b/bitacross-worker/rust-sgx-sdk/common/inc/stddef.h @@ -0,0 +1,70 @@ +/* $OpenBSD: stddef.h,v 1.10 2009/09/22 21:40:02 jsg Exp $ */ +/* $NetBSD: stddef.h,v 1.4 1994/10/26 00:56:26 cgd Exp $ */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)stddef.h 5.5 (Berkeley) 4/3/91 + */ + +#ifndef _STDDEF_H_ +#define _STDDEF_H_ + +#include +#include + +#ifndef _PTRDIFF_T_DEFINED_ +#define _PTRDIFF_T_DEFINED_ +typedef __ptrdiff_t ptrdiff_t; +#endif + +#ifndef _SIZE_T_DEFINED_ +#define _SIZE_T_DEFINED_ +typedef __size_t size_t; +#endif + +#if !defined(_WCHAR_T_DEFINED_) && !defined(__cplusplus) +#define _WCHAR_T_DEFINED_ +#ifndef __WCHAR_TYPE__ +#define __WCHAR_TYPE__ int +#endif +typedef __WCHAR_TYPE__ wchar_t; +#endif + +#ifndef NULL +#ifdef __cplusplus +#define NULL 0 +#else +#define NULL ((void *)0) +#endif +#endif + +#define offsetof(type, member) __builtin_offsetof (type, member) + +#endif /* _STDDEF_H_ */ + diff --git a/bitacross-worker/rust-sgx-sdk/common/inc/stdint.h b/bitacross-worker/rust-sgx-sdk/common/inc/stdint.h new file mode 100644 index 0000000000..e574484062 --- /dev/null +++ b/bitacross-worker/rust-sgx-sdk/common/inc/stdint.h @@ -0,0 +1,24 @@ +/* $OpenBSD: stdint.h,v 1.4 2006/12/10 22:17:55 deraadt Exp $ */ + +/* + * Copyright (c) 1997, 2005 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _STDINT_H_ +#define _STDINT_H_ + +#include + +#endif /* _STDINT_H_ */ diff --git a/bitacross-worker/rust-sgx-sdk/common/inc/stdio.h b/bitacross-worker/rust-sgx-sdk/common/inc/stdio.h new file mode 100644 index 0000000000..92d01a0d9e --- /dev/null +++ b/bitacross-worker/rust-sgx-sdk/common/inc/stdio.h @@ -0,0 +1,95 @@ +/* $OpenBSD: stdio.h,v 1.38 2009/11/09 00:18:27 kurt Exp $ */ +/* $NetBSD: stdio.h,v 1.18 1996/04/25 18:29:21 jtc Exp $ */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)stdio.h 5.17 (Berkeley) 6/3/91 + */ + +#ifndef _STDIO_H_ +#define _STDIO_H_ + +#include +#include + +#include + +#ifndef _SIZE_T_DEFINED_ +typedef __size_t size_t; +#define _SIZE_T_DEFINED_ +#endif + +#ifndef NULL +# ifdef __cplusplus +# define NULL 0 +# else +# define NULL ((void *)0) +# endif +#endif + +# define BUFSIZ 8192 + +#define EOF (-1) + +__BEGIN_DECLS + +int _TLIBC_CDECL_ snprintf(char *, size_t, const char *, ...) _GCC_PRINTF_FORMAT_(3, 4); +int _TLIBC_CDECL_ vsnprintf(char *, size_t, const char *, __va_list) _GCC_PRINTF_FORMAT_(3, 0); + +/* + * Deprecated definitions. + */ +#if 0 /* No FILE */ +_TLIBC_DEPRECATED_FUNCTION_(int _TLIBC_CDECL_, fprintf, FILE *, const char *, ...); +_TLIBC_DEPRECATED_FUNCTION_(int _TLIBC_CDECL_, putc, int, FILE *); +_TLIBC_DEPRECATED_FUNCTION_(int _TLIBC_CDECL_, fputc, int, FILE *); +_TLIBC_DEPRECATED_FUNCTION_(int _TLIBC_CDECL_, fputs, const char *, FILE *); +_TLIBC_DEPRECATED_FUNCTION_(int _TLIBC_CDECL_, fscanf, FILE *, const char *, ...); +_TLIBC_DEPRECATED_FUNCTION_(size_t _TLIBC_CDECL_, fwrite, const void *, size_t, size_t, FILE *); +_TLIBC_DEPRECATED_FUNCTION_(int _TLIBC_CDECL_, printf, const char *, ...); +_TLIBC_DEPRECATED_FUNCTION_(int _TLIBC_CDECL_, putchar, int); +_TLIBC_DEPRECATED_FUNCTION_(int _TLIBC_CDECL_, puts, const char *); +_TLIBC_DEPRECATED_FUNCTION_(int _TLIBC_CDECL_, scanf, const char *, ...); +_TLIBC_DEPRECATED_FUNCTION_(int _TLIBC_CDECL_, sprintf, char *, const char *, ...); +_TLIBC_DEPRECATED_FUNCTION_(int _TLIBC_CDECL_, sscanf, const char *, const char *, ...); +_TLIBC_DEPRECATED_FUNCTION_(int _TLIBC_CDECL_, vfprintf, FILE *, const char *, __va_list); +_TLIBC_DEPRECATED_FUNCTION_(int _TLIBC_CDECL_, vfscanf, FILE *, const char *, __va_list); +_TLIBC_DEPRECATED_FUNCTION_(int _TLIBC_CDECL_, vprintf, const char *, __va_list); +_TLIBC_DEPRECATED_FUNCTION_(int _TLIBC_CDECL_, vscanf, const char *, __va_list); +_TLIBC_DEPRECATED_FUNCTION_(int _TLIBC_CDECL_, vsprintf, char *, const char *, __va_list); +_TLIBC_DEPRECATED_FUNCTION_(int _TLIBC_CDECL_, vsscanf, const char *, const char *, __va_list); +#endif + +__END_DECLS + + +#endif /* !_STDIO_H_ */ diff --git a/bitacross-worker/rust-sgx-sdk/common/inc/stdlib.h b/bitacross-worker/rust-sgx-sdk/common/inc/stdlib.h new file mode 100644 index 0000000000..8128e0d56d --- /dev/null +++ b/bitacross-worker/rust-sgx-sdk/common/inc/stdlib.h @@ -0,0 +1,159 @@ +/* $OpenBSD: stdlib.h,v 1.47 2010/05/18 22:24:55 tedu Exp $ */ +/* $NetBSD: stdlib.h,v 1.25 1995/12/27 21:19:08 jtc Exp $ */ + +/*- +* Copyright (c) 1990 The Regents of the University of California. +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* 3. Neither the name of the University nor the names of its contributors +* may be used to endorse or promote products derived from this software +* without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +* SUCH DAMAGE. +* +* @(#)stdlib.h 5.13 (Berkeley) 6/4/91 +*/ + +#ifndef _STDLIB_H_ +#define _STDLIB_H_ + +#include +#include + +#ifndef _SIZE_T_DEFINED_ +#define _SIZE_T_DEFINED_ +typedef __size_t size_t; +#endif + +#if !defined(_WCHAR_T_DEFINED_) && !defined(__cplusplus) +#define _WCHAR_T_DEFINED_ +#ifndef __WCHAR_TYPE__ +#define __WCHAR_TYPE__ int +#endif +typedef __WCHAR_TYPE__ wchar_t; +#endif + +#ifndef _DIV_T_DEFINED +typedef struct { + int quot; /* quotient */ + int rem; /* remainder */ +} div_t; + +typedef struct { + long quot; /* quotient */ + long rem; /* remainder */ +} ldiv_t; + +typedef struct { + long long quot; /* quotient */ + long long rem; /* remainder */ +} lldiv_t; +#define _DIV_T_DEFINED +#endif + +#ifndef NULL +#ifdef __cplusplus +#define NULL 0 +#else +#define NULL ((void *)0) +#endif +#endif + +#define EXIT_FAILURE 1 +#define EXIT_SUCCESS 0 + +#define RAND_MAX 0x7fffffff +#define MB_CUR_MAX 1 + +__BEGIN_DECLS + +_TLIBC_NORETURN_ void _TLIBC_CDECL_ abort(void); +int _TLIBC_CDECL_ atexit(void (*)(void)); +int _TLIBC_CDECL_ abs(int); +double _TLIBC_CDECL_ atof(const char *); +int _TLIBC_CDECL_ atoi(const char *); +long _TLIBC_CDECL_ atol(const char *); +void * _TLIBC_CDECL_ bsearch(const void *, const void *, size_t, size_t, int (*)(const void *, const void *)); +void * _TLIBC_CDECL_ calloc(size_t, size_t); +div_t _TLIBC_CDECL_ div(int, int); +void _TLIBC_CDECL_ free(void *); +long _TLIBC_CDECL_ labs(long); +ldiv_t _TLIBC_CDECL_ ldiv(long, long); +void * _TLIBC_CDECL_ malloc(size_t); +void * _TLIBC_CDECL_ memalign(size_t, size_t); +#ifndef __cplusplus +int _TLIBC_CDECL_ posix_memalign(void **, size_t, size_t); +#else +int _TLIBC_CDECL_ posix_memalign(void **, size_t, size_t) throw (); +#endif +void * _TLIBC_CDECL_ aligned_alloc(size_t, size_t); +void _TLIBC_CDECL_ qsort(void *, size_t, size_t, int (*)(const void *, const void *)); +void * _TLIBC_CDECL_ realloc(void *, size_t); +double _TLIBC_CDECL_ strtod(const char *, char **); +long _TLIBC_CDECL_ strtol(const char *, char **, int); +float _TLIBC_CDECL_ strtof(const char *, char **); + +long long + _TLIBC_CDECL_ atoll(const char *); +long long + _TLIBC_CDECL_ llabs(long long); +lldiv_t + _TLIBC_CDECL_ lldiv(long long, long long); +long long + _TLIBC_CDECL_ strtoll(const char *, char **, int); +unsigned long + _TLIBC_CDECL_ strtoul(const char *, char **, int); +long double + _TLIBC_CDECL_ strtold(const char *, char **); +unsigned long long + _TLIBC_CDECL_ strtoull(const char *, char **, int); + +int _TLIBC_CDECL_ mblen(const char *, size_t); +size_t _TLIBC_CDECL_ mbstowcs(wchar_t *, const char *, size_t); +int _TLIBC_CDECL_ wctomb(char *, wchar_t); +int _TLIBC_CDECL_ mbtowc(wchar_t *, const char *, size_t); +size_t _TLIBC_CDECL_ wcstombs(char *, const wchar_t *, size_t); + + +/* + * Deprecated C99. + */ +_TLIBC_DEPRECATED_FUNCTION_(int _TLIBC_CDECL_, atexit, void (_TLIBC_CDECL_ *)(void)); +_TLIBC_DEPRECATED_FUNCTION_(int _TLIBC_CDECL_, rand, void); +_TLIBC_DEPRECATED_FUNCTION_(void _TLIBC_CDECL_, srand, unsigned); +_TLIBC_DEPRECATED_FUNCTION_(void _TLIBC_CDECL_, exit, int); +_TLIBC_DEPRECATED_FUNCTION_(void _TLIBC_CDECL_, _Exit, int); +_TLIBC_DEPRECATED_FUNCTION_(char * _TLIBC_CDECL_, getenv, const char *); +_TLIBC_DEPRECATED_FUNCTION_(int _TLIBC_CDECL_, system, const char *); + +/* + * Non-C99 Functions. + */ +void * _TLIBC_CDECL_ alloca(size_t); + +/* + * Deprecated Non-C99. + */ +//_TLIBC_DEPRECATED_FUNCTION_(void _TLIBC_CDECL_, _exit, int); + +__END_DECLS + +#endif /* !_STDLIB_H_ */ diff --git a/bitacross-worker/rust-sgx-sdk/common/inc/string.h b/bitacross-worker/rust-sgx-sdk/common/inc/string.h new file mode 100644 index 0000000000..00a89fde77 --- /dev/null +++ b/bitacross-worker/rust-sgx-sdk/common/inc/string.h @@ -0,0 +1,130 @@ +/* $OpenBSD: string.h,v 1.20 2010/09/24 13:33:00 matthew Exp $ */ +/* $NetBSD: string.h,v 1.6 1994/10/26 00:56:30 cgd Exp $ */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)string.h 5.10 (Berkeley) 3/9/91 + */ + +#ifndef _STRING_H_ +#define _STRING_H_ + +#include +#include + +#ifndef _SIZE_T_DEFINED_ +typedef __size_t size_t; +#define _SIZE_T_DEFINED_ +#endif + +#ifndef _ERRNO_T_DEFINED +#define _ERRNO_T_DEFINED +typedef int errno_t; +#endif + +#ifndef NULL +#ifdef __cplusplus +#define NULL 0 +#else +#define NULL ((void *)0) +#endif +#endif + +__BEGIN_DECLS + +void * _TLIBC_CDECL_ memchr(const void *, int, size_t); +int _TLIBC_CDECL_ memcmp(const void *, const void *, size_t); +void * _TLIBC_CDECL_ memcpy_nochecks(void *, const void *, size_t); +void * _TLIBC_CDECL_ memcpy(void *, const void *, size_t); +void * _TLIBC_CDECL_ memcpy_verw(void *, const void *, size_t); +void * _TLIBC_CDECL_ memmove(void *, const void *, size_t); +void * _TLIBC_CDECL_ memmove_verw(void *, const void *, size_t); +void * _TLIBC_CDECL_ memset(void *, int, size_t); +void * _TLIBC_CDECL_ memset_verw(void *, int, size_t); +char * _TLIBC_CDECL_ strchr(const char *, int); +int _TLIBC_CDECL_ strcmp(const char *, const char *); +int _TLIBC_CDECL_ strcoll(const char *, const char *); +size_t _TLIBC_CDECL_ strcspn(const char *, const char *); +char * _TLIBC_CDECL_ strerror(int); +size_t _TLIBC_CDECL_ strlen(const char *); +char * _TLIBC_CDECL_ strncat(char *, const char *, size_t); +int _TLIBC_CDECL_ strncmp(const char *, const char *, size_t); +char * _TLIBC_CDECL_ strncpy(char *, const char *, size_t); +char * _TLIBC_CDECL_ strpbrk(const char *, const char *); +char * _TLIBC_CDECL_ strrchr(const char *, int); +size_t _TLIBC_CDECL_ strspn(const char *, const char *); +char * _TLIBC_CDECL_ strstr(const char *, const char *); +char * _TLIBC_CDECL_ strtok(char *, const char *); +size_t _TLIBC_CDECL_ strxfrm(char *, const char *, size_t); +size_t _TLIBC_CDECL_ strlcpy(char *, const char *, size_t); +errno_t _TLIBC_CDECL_ memset_s(void *s, size_t smax, int c, size_t n); +errno_t _TLIBC_CDECL_ memset_verw_s(void *s, size_t smax, int c, size_t n); + +/* + * Deprecated C99. + */ +_TLIBC_DEPRECATED_FUNCTION_(char * _TLIBC_CDECL_, strcat, char *, const char *); +_TLIBC_DEPRECATED_FUNCTION_(char * _TLIBC_CDECL_, strcpy, char *, const char *); + +/* + * Common used non-C99 functions. + */ +char * _TLIBC_CDECL_ strndup(const char *, size_t); +size_t _TLIBC_CDECL_ strnlen(const char *, size_t); +int _TLIBC_CDECL_ consttime_memequal(const void *b1, const void *b2, size_t len); + +/* + * Non-C99 + */ +int _TLIBC_CDECL_ bcmp(const void *, const void *, size_t); +void _TLIBC_CDECL_ bcopy(const void *, void *, size_t); +void _TLIBC_CDECL_ bzero(void *, size_t); +char * _TLIBC_CDECL_ index(const char *, int); +void * _TLIBC_CDECL_ mempcpy(void *, const void *, size_t); +char * _TLIBC_CDECL_ rindex(const char *, int); +char * _TLIBC_CDECL_ stpncpy(char *dest, const char *src, size_t n); +int _TLIBC_CDECL_ strcasecmp(const char *, const char *); +int _TLIBC_CDECL_ strncasecmp(const char *, const char *, size_t); + +int _TLIBC_CDECL_ ffs(int); +int _TLIBC_CDECL_ ffsl(long int); +int _TLIBC_CDECL_ ffsll(long long int); + +char * _TLIBC_CDECL_ strtok_r(char *, const char *, char **); +int _TLIBC_CDECL_ strerror_r(int, char *, size_t); + +/* + * Deprecated Non-C99. + */ +_TLIBC_DEPRECATED_FUNCTION_(char * _TLIBC_CDECL_, strdup, const char *); +_TLIBC_DEPRECATED_FUNCTION_(char * _TLIBC_CDECL_, stpcpy, char *dest, const char *src); + +__END_DECLS + +#endif /* _STRING_H_ */ diff --git a/bitacross-worker/rust-sgx-sdk/common/inc/sys/_types.h b/bitacross-worker/rust-sgx-sdk/common/inc/sys/_types.h new file mode 100644 index 0000000000..5dc6d5bbfb --- /dev/null +++ b/bitacross-worker/rust-sgx-sdk/common/inc/sys/_types.h @@ -0,0 +1,168 @@ +/* $OpenBSD: _types.h,v 1.2 2008/03/16 19:42:57 otto Exp $ */ + +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)types.h 8.3 (Berkeley) 1/5/94 + */ + +#ifndef _SYS__TYPES_H_ +#define _SYS__TYPES_H_ + +#include +/* 7.18.1.1 Exact-width integer types */ +typedef signed char __int8_t; +typedef unsigned char __uint8_t; +typedef short __int16_t; +typedef unsigned short __uint16_t; +typedef int __int32_t; +typedef unsigned int __uint32_t; +#ifdef __x86_64__ +typedef long __int64_t; +typedef unsigned long __uint64_t; +#else +typedef long long __int64_t; +typedef unsigned long long __uint64_t; +#endif + +/* 7.18.1.2 Minimum-width integer types */ +typedef __int8_t __int_least8_t; +typedef __uint8_t __uint_least8_t; +typedef __int16_t __int_least16_t; +typedef __uint16_t __uint_least16_t; +typedef __int32_t __int_least32_t; +typedef __uint32_t __uint_least32_t; +typedef __int64_t __int_least64_t; +typedef __uint64_t __uint_least64_t; + +/* 7.18.1.3 Fastest minimum-width integer types */ +typedef __int8_t __int_fast8_t; +typedef __uint8_t __uint_fast8_t; +#ifdef __x86_64__ +/* Linux x86_64, from stdint.h */ +typedef long int __int_fast16_t; +typedef unsigned long int __uint_fast16_t; +typedef long int __int_fast32_t; +typedef unsigned long int __uint_fast32_t; +typedef long int __int_fast64_t; +typedef unsigned long int __uint_fast64_t; +#else +/* Android x86, and Linux x86 */ +typedef __int32_t __int_fast16_t; +typedef __uint32_t __uint_fast16_t; +typedef __int32_t __int_fast32_t; +typedef __uint32_t __uint_fast32_t; +typedef __int64_t __int_fast64_t; +typedef __uint64_t __uint_fast64_t; +#endif + +typedef long __off_t; +#ifdef __x86_64__ +typedef long int __off64_t; +#else +typedef long long int __off64_t; +#endif + +/* 7.18.1.4 Integer types capable of holding object pointers */ +#ifdef __i386__ +typedef __int32_t __intptr_t; +typedef __uint32_t __uintptr_t; +typedef __int32_t __ptrdiff_t; +/* Standard system types */ +typedef __uint32_t __size_t; +typedef __int32_t __ssize_t; +typedef long double __double_t; +typedef long double __float_t; +#else +typedef __int64_t __intptr_t; +typedef __uint64_t __uintptr_t; +typedef __int64_t __ptrdiff_t; + +/* Standard system types */ +typedef unsigned long __size_t; +typedef long __ssize_t; +typedef double __double_t; +typedef float __float_t; + +#endif /* !__i386__ */ + +typedef long __clock_t; + +typedef long __time_t; +typedef __builtin_va_list __va_list; +typedef unsigned int __wint_t; +/* wctype_t and wctrans_t are defined in wchar.h */ +typedef unsigned long int __wctype_t; +typedef int * __wctrans_t; + +/* + * mbstate_t is an opaque object to keep conversion state, during multibyte + * stream conversions. The content must not be referenced by user programs. + */ +/* For Linux, __mbstate_t is defined in wchar.h */ +typedef struct { + int __c; + union { + __wint_t __wc; + char __wcb[4]; + } __v; +} __mbstate_t; + +/* 7.18.1.5 Greatest-width integer types */ +typedef __int64_t __intmax_t; +typedef __uint64_t __uintmax_t; + + +typedef unsigned long int __ino_t; +typedef unsigned int __mode_t; +typedef unsigned int __uid_t; +typedef unsigned int __gid_t; +typedef long int __blksize_t; +typedef long int __blkcnt_t; + +#ifdef __x86_64__ +typedef unsigned long int __dev_t; +typedef long int __off64_t; +typedef unsigned long int __nlink_t; +typedef long int __blkcnt64_t; +typedef unsigned long int __ino64_t; +#else +typedef unsigned long long int __dev_t; +typedef long long int __off64_t; +typedef unsigned int __nlink_t; +typedef long long int __blkcnt64_t; +typedef unsigned long long int __ino64_t; +#endif + +typedef unsigned int __socklen_t; +typedef int __pid_t; +typedef long __cpu_mask; +#endif /* !_SYS__TYPES_H_ */ + + + diff --git a/bitacross-worker/rust-sgx-sdk/common/inc/sys/cdefs.h b/bitacross-worker/rust-sgx-sdk/common/inc/sys/cdefs.h new file mode 100644 index 0000000000..71c3c1ce22 --- /dev/null +++ b/bitacross-worker/rust-sgx-sdk/common/inc/sys/cdefs.h @@ -0,0 +1,132 @@ +/* $OpenBSD: cdefs.h,v 1.34 2012/08/14 20:11:37 matthew Exp $ */ +/* $NetBSD: cdefs.h,v 1.16 1996/04/03 20:46:39 christos Exp $ */ + +/* + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Berkeley Software Design, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)cdefs.h 8.7 (Berkeley) 1/21/94 + */ + +#ifndef _SYS_CDEFS_H_ +#define _SYS_CDEFS_H_ + +/* Declaration field in C/C++ headers */ +#if defined(__cplusplus) +# define __BEGIN_DECLS extern "C" { +# define __END_DECLS } +#else +# define __BEGIN_DECLS +# define __END_DECLS +#endif + +#if defined(__STDC__) || defined(__cplusplus) +# define __CONCAT(x,y) x ## y +# define __STRING(x) #x +#else +# define __CONCAT(x,y) x/**/y +# define __STRING(x) "x" +#endif +/* + * Macro to test if we're using a specific version of gcc or later. + */ +#if defined __GNUC__ && defined __GNUC_MINOR_ +# define __GNUC_PREREQ__(ma, mi) \ + ((__GNUC__ > (ma)) || (__GNUC__ == (ma) && __GNUC_MINOR__ >= (mi))) +#else +# define __GNUC_PREREQ__(ma, mi) 0 +#endif + +/* Calling Convention: cdecl */ +#define _TLIBC_CDECL_ + +/* Thread Directive */ +#define _TLIBC_THREAD_ /* __thread */ + +/* Deprecated Warnings */ +#define _TLIBC_DEPRECATED_MSG(x) __STRING(x)" is deprecated in tlibc." +#define _TLIBC_DEPRECATED_(x) __attribute__((deprecated(_TLIBC_DEPRECATED_MSG(x)))) + +#ifndef _TLIBC_WARN_DEPRECATED_FUNCTIONS_ +# define _TLIBC_DEPRECATED_FUNCTION_(__ret, __func, ...) +#else +# define _TLIBC_DEPRECATED_FUNCTION_(__ret, __func, ...) \ + _TLIBC_DEPRECATED_(__func) \ + __ret __func(__VA_ARGS__) +#endif + +/* Static analysis for printf format strings. + * _MSC_PRINTF_FORMAT_: MSVC SAL annotation for specifying format strings. + * _GCC_PRINTF_FORMAT_(x, y): GCC declaring attribute for checking format strings. + * x - index of the format string. In C++ non-static method, index 1 is reseved for 'this'. + * y - index of first variadic agrument in '...'. + */ +#define _GCC_PRINTF_FORMAT_(x, y) __attribute__((__format__ (printf, x, y))) + +/* Attribute - noreturn */ +#define _TLIBC_NORETURN_ __attribute__ ((__noreturn__)) + +/* + * GNU C version 2.96 adds explicit branch prediction so that + * the CPU back-end can hint the processor and also so that + * code blocks can be reordered such that the predicted path + * sees a more linear flow, thus improving cache behavior, etc. + * + * The following two macros provide us with a way to utilize this + * compiler feature. Use __predict_true() if you expect the expression + * to evaluate to true, and __predict_false() if you expect the + * expression to evaluate to false. + * + * A few notes about usage: + * + * * Generally, __predict_false() error condition checks (unless + * you have some _strong_ reason to do otherwise, in which case + * document it), and/or __predict_true() `no-error' condition + * checks, assuming you want to optimize for the no-error case. + * + * * Other than that, if you don't know the likelihood of a test + * succeeding from empirical or other `hard' evidence, don't + * make predictions. + * + * * These are meant to be used in places that are run `a lot'. + * It is wasteful to make predictions in code that is run + * seldomly (e.g. at subsystem initialization time) as the + * basic block reordering that this affects can often generate + * larger code. + */ +#if defined(__GNUC__) && __GNUC_PREREQ__(2, 96) +#define __predict_true(exp) __builtin_expect(((exp) != 0), 1) +#define __predict_false(exp) __builtin_expect(((exp) != 0), 0) +#else +#define __predict_true(exp) ((exp) != 0) +#define __predict_false(exp) ((exp) != 0) +#endif + +#endif /* !_SYS_CDEFS_H_ */ diff --git a/bitacross-worker/rust-sgx-sdk/common/inc/sys/endian.h b/bitacross-worker/rust-sgx-sdk/common/inc/sys/endian.h new file mode 100644 index 0000000000..1cd7b810c3 --- /dev/null +++ b/bitacross-worker/rust-sgx-sdk/common/inc/sys/endian.h @@ -0,0 +1,54 @@ +/* $OpenBSD: endian.h,v 1.18 2006/03/27 07:09:24 otto Exp $ */ + +/*- + * Copyright (c) 1997 Niklas Hallqvist. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Generic definitions for little- and big-endian systems. Other endianesses + * has to be dealt with in the specific machine/endian.h file for that port. + * + * This file is meant to be included from a little- or big-endian port's + * machine/endian.h after setting _BYTE_ORDER to either 1234 for little endian + * or 4321 for big.. + */ + +#ifndef _SYS_ENDIAN_H_ +#define _SYS_ENDIAN_H_ + +#define _LITTLE_ENDIAN 1234 +#define _BIG_ENDIAN 4321 +#define _PDP_ENDIAN 3412 +#define _BYTE_ORDER _LITTLE_ENDIAN + +#define LITTLE_ENDIAN _LITTLE_ENDIAN +#define BIG_ENDIAN _BIG_ENDIAN +#define PDP_ENDIAN _PDP_ENDIAN +#define BYTE_ORDER _BYTE_ORDER + +#define __BYTE_ORDER _BYTE_ORDER +#define __BIG_ENDIAN _BIG_ENDIAN +#define __LITTLE_ENDIAN _LITTLE_ENDIAN + +#endif /* _SYS_ENDIAN_H_ */ + diff --git a/bitacross-worker/rust-sgx-sdk/common/inc/sys/epoll.h b/bitacross-worker/rust-sgx-sdk/common/inc/sys/epoll.h new file mode 100644 index 0000000000..958a4c4fb0 --- /dev/null +++ b/bitacross-worker/rust-sgx-sdk/common/inc/sys/epoll.h @@ -0,0 +1,42 @@ +// +// Copyright © 2005-2020 Rich Felker, et al. +// Licensed under the MIT license. +// + +/* Copyright © 2005-2020 Rich Felker, et al. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef _SYS_EPOLL_H +#define _SYS_EPOLL_H + +typedef union epoll_data { + void *ptr; + int fd; + uint32_t u32; + uint64_t u64; +} epoll_data_t; + +struct epoll_event { + uint32_t events; + epoll_data_t data; +} __attribute__ ((__packed__)); + +#endif diff --git a/bitacross-worker/rust-sgx-sdk/common/inc/sys/fpu.h b/bitacross-worker/rust-sgx-sdk/common/inc/sys/fpu.h new file mode 100644 index 0000000000..4c218a91b6 --- /dev/null +++ b/bitacross-worker/rust-sgx-sdk/common/inc/sys/fpu.h @@ -0,0 +1,99 @@ +/* $OpenBSD: fpu.h,v 1.16 2018/10/07 22:43:06 guenther Exp $ */ +/* $NetBSD: fpu.h,v 1.1 2003/04/26 18:39:40 fvdl Exp $ */ + +#ifndef _MACHINE_FPU_H_ +#define _MACHINE_FPU_H_ + +#include + +/* + * If the CPU supports xsave/xrstor then we use them so that we can provide + * AVX support. Otherwise we require fxsave/fxrstor, as the SSE registers + * are part of the ABI for passing floating point values. + * While fxsave/fxrstor only required 16-byte alignment for the save area, + * xsave/xrstor requires the save area to have 64-byte alignment. + */ + +struct fxsave64 { + u_int16_t fx_fcw; + u_int16_t fx_fsw; + u_int8_t fx_ftw; + u_int8_t fx_unused1; + u_int16_t fx_fop; + u_int64_t fx_rip; + u_int64_t fx_rdp; + u_int32_t fx_mxcsr; + u_int32_t fx_mxcsr_mask; + u_int64_t fx_st[8][2]; /* 8 normal FP regs */ + u_int64_t fx_xmm[16][2]; /* 16 SSE2 registers */ + u_int8_t fx_unused3[96]; +} __packed; + +struct xstate_hdr { + uint64_t xstate_bv; + uint64_t xstate_xcomp_bv; + uint8_t xstate_rsrv0[0]; + uint8_t xstate_rsrv[40]; +} ___packed; + +struct savefpu { + struct fxsave64 fp_fxsave; /* see above */ + struct xstate_hdr fp_xstate; + u_int64_t fp_ymm[16][2]; + u_int16_t fp_ex_sw; /* saved status from last exception */ + u_int16_t fp_ex_tw; /* saved tag from last exception */ +}; + +/* + * The i387 defaults to Intel extended precision mode and round to nearest, + * with all exceptions masked. + */ +#define __INITIAL_NPXCW__ 0x037f +#define __INITIAL_MXCSR__ 0x1f80 +#define __INITIAL_MXCSR_MASK__ 0xffbf + +#ifdef _KERNEL +/* + * XXX + */ +struct trapframe; +struct cpu_info; + +extern size_t fpu_save_len; +extern uint32_t fpu_mxcsr_mask; +extern uint64_t xsave_mask; + +void fpuinit(struct cpu_info *); +int fputrap(int _type); +void fpusave(struct savefpu *); +void fpusavereset(struct savefpu *); +void fpu_kernel_enter(void); +void fpu_kernel_exit(void); + +int xrstor_user(struct savefpu *_addr, uint64_t _mask); +#define fpureset() \ + xrstor_user(&proc0.p_addr->u_pcb.pcb_savefpu, xsave_mask) +int xsetbv_user(uint32_t _reg, uint64_t _mask); + +#define fninit() __asm("fninit") +#define fwait() __asm("fwait") +/* should be fxsave64, but where we use this it doesn't matter */ +#define fxsave(addr) __asm("fxsave %0" : "=m" (*addr)) +#define ldmxcsr(addr) __asm("ldmxcsr %0" : : "m" (*addr)) +#define fldcw(addr) __asm("fldcw %0" : : "m" (*addr)) + +static inline void +xsave(struct savefpu *addr, uint64_t mask) +{ + uint32_t lo, hi; + + lo = mask; + hi = mask >> 32; + /* should be xsave64, but where we use this it doesn't matter */ + __asm volatile("xsave %0" : "=m" (*addr) : "a" (lo), "d" (hi) : + "memory"); +} + +#endif + +#endif /* _MACHINE_FPU_H_ */ diff --git a/bitacross-worker/rust-sgx-sdk/common/inc/sys/ieee.h b/bitacross-worker/rust-sgx-sdk/common/inc/sys/ieee.h new file mode 100644 index 0000000000..47379b28ed --- /dev/null +++ b/bitacross-worker/rust-sgx-sdk/common/inc/sys/ieee.h @@ -0,0 +1,170 @@ +/* $OpenBSD: ieee.h,v 1.2 2008/09/07 20:36:06 martynas Exp $ */ +/* $NetBSD: ieee.h,v 1.1 1996/09/30 16:34:25 ws Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ieee.h 8.1 (Berkeley) 6/11/93 + */ + +/* + * ieee.h defines the machine-dependent layout of the machine's IEEE + * floating point. It does *not* define (yet?) any of the rounding + * mode bits, exceptions, and so forth. + */ + +/* + * Define the number of bits in each fraction and exponent. + * + * k k+1 + * Note that 1.0 x 2 == 0.1 x 2 and that denorms are represented + * + * (-exp_bias+1) + * as fractions that look like 0.fffff x 2 . This means that + * + * -126 + * the number 0.10000 x 2 , for instance, is the same as the normalized + * + * -127 -128 + * float 1.0 x 2 . Thus, to represent 2 , we need one leading zero + * + * -129 + * in the fraction; to represent 2 , we need two, and so on. This + * + * (-exp_bias-fracbits+1) + * implies that the smallest denormalized number is 2 + * + * for whichever format we are talking about: for single precision, for + * + * -126 -149 + * instance, we get .00000000000000000000001 x 2 , or 1.0 x 2 , and + * + * -149 == -127 - 23 + 1. + */ + +#include +#include + +#define SNG_EXPBITS 8 +#define SNG_FRACBITS 23 + +#define DBL_EXPBITS 11 +#define DBL_FRACHBITS 20 +#define DBL_FRACLBITS 32 +#define DBL_FRACBITS 52 + +#define EXT_EXPBITS 15 +#define EXT_FRACHBITS 32 +#define EXT_FRACLBITS 32 +#define EXT_FRACBITS 64 + +#define EXT_TO_ARRAY32(p, a) do { \ + (a)[0] = (uint32_t)(p)->ext_fracl; \ + (a)[1] = (uint32_t)(p)->ext_frach; \ +} while(0) + +struct ieee_single { + u_int sng_frac:23; + u_int sng_exp:8; + u_int sng_sign:1; +}; + +struct ieee_double { + u_int dbl_fracl; + u_int dbl_frach:20; + u_int dbl_exp:11; + u_int dbl_sign:1; +}; + +struct ieee_ext { + u_int ext_fracl; + u_int ext_frach; + u_int ext_exp:15; + u_int ext_sign:1; + u_int ext_padl:16; + u_int ext_padh; +}; + +/* + * Floats whose exponent is in [1..INFNAN) (of whatever type) are + * `normal'. Floats whose exponent is INFNAN are either Inf or NaN. + * Floats whose exponent is zero are either zero (iff all fraction + * bits are zero) or subnormal values. + * + * A NaN is a `signalling NaN' if its QUIETNAN bit is clear in its + * high fraction; if the bit is set, it is a `quiet NaN'. + */ +#define SNG_EXP_INFNAN 255 +#define DBL_EXP_INFNAN 2047 +#define EXT_EXP_INFNAN 32767 + +#if 0 +#define SNG_QUIETNAN (1 << 22) +#define DBL_QUIETNAN (1 << 19) +#define EXT_QUIETNAN (1 << 15) +#endif + +/* + * Exponent biases. + */ +#define SNG_EXP_BIAS 127 +#define DBL_EXP_BIAS 1023 +#define EXT_EXP_BIAS 16383 + +typedef int fp_except; +#define FP_X_INV 0x01 /* invalid operation exception */ +#define FP_X_DNML 0x02 /* denormalization exception */ +#define FP_X_DZ 0x04 /* divide-by-zero exception */ +#define FP_X_OFL 0x08 /* overflow exception */ +#define FP_X_UFL 0x10 /* underflow exception */ +#define FP_X_IMP 0x20 /* imprecise (loss of precision) */ + +typedef enum { + FP_RN=0, /* round to nearest representable number */ + FP_RM=1, /* round toward negative infinity */ + FP_RP=2, /* round toward positive infinity */ + FP_RZ=3 /* round to zero (truncate) */ +} fp_rnd; + +__BEGIN_DECLS +extern fp_rnd fpgetround(void); +extern fp_rnd fpsetround(fp_rnd); +extern fp_except fpgetmask(void); +extern fp_except fpsetmask(fp_except); +extern fp_except fpgetsticky(void); +extern fp_except fpsetsticky(fp_except); +__END_DECLS diff --git a/bitacross-worker/rust-sgx-sdk/common/inc/sys/limits.h b/bitacross-worker/rust-sgx-sdk/common/inc/sys/limits.h new file mode 100644 index 0000000000..3d1f9673ad --- /dev/null +++ b/bitacross-worker/rust-sgx-sdk/common/inc/sys/limits.h @@ -0,0 +1,77 @@ +/* $OpenBSD: limits.h,v 1.8 2009/11/27 19:54:35 guenther Exp $ */ +/* + * Copyright (c) 2002 Marc Espie. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OPENBSD + * PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef _SYS_LIMITS_H_ +#define _SYS_LIMITS_H_ + +#include + +/* Common definitions for limits.h. */ + +#define CHAR_BIT 8 /* number of bits in a char */ + +#define SCHAR_MAX 0x7f /* max value for a signed char */ +#define SCHAR_MIN (-0x7f - 1) /* min value for a signed char */ + +#define UCHAR_MAX 0xff /* max value for an unsigned char */ +#ifdef __CHAR_UNSIGNED__ +# define CHAR_MIN 0 /* min value for a char */ +# define CHAR_MAX 0xff /* max value for a char */ +#else +# define CHAR_MAX 0x7f +# define CHAR_MIN (-0x7f-1) +#endif + +#define MB_LEN_MAX 1 /* Allow UTF-8 (RFC 3629) */ + +#define USHRT_MAX 0xffff /* max value for an unsigned short */ +#define SHRT_MAX 0x7fff /* max value for a short */ +#define SHRT_MIN (-0x7fff-1) /* min value for a short */ + +#define UINT_MAX 0xffffffffU /* max value for an unsigned int */ +#define INT_MAX 0x7fffffff /* max value for an int */ +#define INT_MIN (-0x7fffffff-1) /* min value for an int */ + +#ifdef __x86_64__ +# define ULONG_MAX 0xffffffffffffffffUL /* max value for unsigned long */ +# define LONG_MAX 0x7fffffffffffffffL /* max value for a signed long */ +# define LONG_MIN (-0x7fffffffffffffffL-1) /* min value for a signed long */ +#else +# define ULONG_MAX 0xffffffffUL /* max value for an unsigned long */ +# define LONG_MAX 0x7fffffffL /* max value for a long */ +# define LONG_MIN (-0x7fffffffL-1) /* min value for a long */ +#endif + +#define ULLONG_MAX 0xffffffffffffffffULL /* max value for unsigned long long */ +#define LLONG_MAX 0x7fffffffffffffffLL /* max value for a signed long long */ +#define LLONG_MIN (-0x7fffffffffffffffLL-1) /* min value for a signed long long */ + +#ifdef __x86_64__ +# define LONG_BIT 64 +#else +# define LONG_BIT 32 +#endif + +#endif /* !_SYS_LIMITS_H_ */ diff --git a/bitacross-worker/rust-sgx-sdk/common/inc/sys/sockaddr.h b/bitacross-worker/rust-sgx-sdk/common/inc/sys/sockaddr.h new file mode 100644 index 0000000000..ba6811cbf7 --- /dev/null +++ b/bitacross-worker/rust-sgx-sdk/common/inc/sys/sockaddr.h @@ -0,0 +1,32 @@ +// +// Copyright © 2005-2020 Rich Felker, et al. +// Licensed under the MIT license. +// + +/* Copyright © 2005-2020 Rich Felker, et al. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef _SYS_SOCKADDR_H_ +#define _SYS_SOCKADDR_H_ + +typedef unsigned short int sa_family_t; + +#endif diff --git a/bitacross-worker/rust-sgx-sdk/common/inc/sys/socket.h b/bitacross-worker/rust-sgx-sdk/common/inc/sys/socket.h new file mode 100644 index 0000000000..0b16699cc6 --- /dev/null +++ b/bitacross-worker/rust-sgx-sdk/common/inc/sys/socket.h @@ -0,0 +1,54 @@ +// +// Copyright © 2005-2020 Rich Felker, et al. +// Licensed under the MIT license. +// + +/* Copyright © 2005-2020 Rich Felker, et al. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef _SYS_SOCKET_H_ +#define _SYS_SOCKET_H_ + +#include +#include +#include + +typedef __socklen_t socklen_t; + +struct sockaddr { + sa_family_t sa_family; + char sa_data[14]; +}; + +struct msghdr { + void *msg_name; + socklen_t msg_namelen; + + struct iovec *msg_iov; + size_t msg_iovlen; + + void *msg_control; + size_t msg_controllen; + + int msg_flags; +}; + +#endif diff --git a/bitacross-worker/rust-sgx-sdk/common/inc/sys/stat.h b/bitacross-worker/rust-sgx-sdk/common/inc/sys/stat.h new file mode 100644 index 0000000000..1cf090a7a1 --- /dev/null +++ b/bitacross-worker/rust-sgx-sdk/common/inc/sys/stat.h @@ -0,0 +1,127 @@ +// +// Copyright © 2005-2020 Rich Felker, et al. +// Licensed under the MIT license. +// + +/* Copyright © 2005-2020 Rich Felker, et al. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + + +#ifndef _SYS_STAT_H_ +#define _SYS_STAT_H_ + +#include +#include +#include + +typedef __dev_t dev_t; +typedef __ino_t ino_t; +typedef __ino64_t ino64_t; +typedef __mode_t mode_t; +typedef __nlink_t nlink_t; +typedef __uid_t uid_t; +typedef __gid_t gid_t; +typedef __blksize_t blksize_t; +typedef __blkcnt_t blkcnt_t; +typedef __blkcnt64_t blkcnt64_t; + +struct stat { + dev_t st_dev; + ino_t st_ino; + nlink_t st_nlink; + + mode_t st_mode; + uid_t st_uid; + gid_t st_gid; + unsigned int __pad0; + dev_t st_rdev; + off_t st_size; + blksize_t st_blksize; + blkcnt_t st_blocks; + + struct timespec st_atim; + struct timespec st_mtim; + struct timespec st_ctim; + long __unused[3]; +}; + +struct stat64 { + dev_t st_dev; + ino64_t st_ino; + nlink_t st_nlink; + + mode_t st_mode; + uid_t st_uid; + gid_t st_gid; + unsigned int __pad0; + dev_t st_rdev; + off_t st_size; + blksize_t st_blksize; + blkcnt64_t st_blocks; + + struct timespec st_atim; + struct timespec st_mtim; + struct timespec st_ctim; + long __unused[3]; +}; + +#define S_IFMT 0170000 + +#define S_IFDIR 0040000 +#define S_IFCHR 0020000 +#define S_IFBLK 0060000 +#define S_IFREG 0100000 +#define S_IFIFO 0010000 +#define S_IFLNK 0120000 +#define S_IFSOCK 0140000 + +#define S_TYPEISMQ(buf) 0 +#define S_TYPEISSEM(buf) 0 +#define S_TYPEISSHM(buf) 0 +#define S_TYPEISTMO(buf) 0 + +#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) +#define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR) +#define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK) +#define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG) +#define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO) +#define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK) +#define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK) + +#ifndef S_IRUSR +#define S_ISUID 04000 +#define S_ISGID 02000 +#define S_ISVTX 01000 +#define S_IRUSR 0400 +#define S_IWUSR 0200 +#define S_IXUSR 0100 +#define S_IRWXU 0700 +#define S_IRGRP 0040 +#define S_IWGRP 0020 +#define S_IXGRP 0010 +#define S_IRWXG 0070 +#define S_IROTH 0004 +#define S_IWOTH 0002 +#define S_IXOTH 0001 +#define S_IRWXO 0007 +#endif + +#endif /* _SYS_STAT_H_ */ diff --git a/bitacross-worker/rust-sgx-sdk/common/inc/sys/stdint.h b/bitacross-worker/rust-sgx-sdk/common/inc/sys/stdint.h new file mode 100644 index 0000000000..51599456d5 --- /dev/null +++ b/bitacross-worker/rust-sgx-sdk/common/inc/sys/stdint.h @@ -0,0 +1,260 @@ +/* $OpenBSD: stdint.h,v 1.4 2006/12/10 22:17:55 deraadt Exp $ */ + +/* + * Copyright (c) 1997, 2005 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _SYS_STDINT_H_ +#define _SYS_STDINT_H_ + +#include +#include + +/* 7.18.1.1 Exact-width integer types (also in sys/types.h) */ +#ifndef _INT8_T_DEFINED_ +#define _INT8_T_DEFINED_ +typedef __int8_t int8_t; +#endif + +#ifndef _UINT8_T_DEFINED_ +#define _UINT8_T_DEFINED_ +typedef __uint8_t uint8_t; +#endif + +#ifndef _INT16_T_DEFINED_ +#define _INT16_T_DEFINED_ +typedef __int16_t int16_t; +#endif + +#ifndef _UINT16_T_DEFINED_ +#define _UINT16_T_DEFINED_ +typedef __uint16_t uint16_t; +#endif + +#ifndef _INT32_T_DEFINED_ +#define _INT32_T_DEFINED_ +typedef __int32_t int32_t; +#endif + +#ifndef _UINT32_T_DEFINED_ +#define _UINT32_T_DEFINED_ +typedef __uint32_t uint32_t; +#endif + +#ifndef _INT64_T_DEFINED_ +#define _INT64_T_DEFINED_ +typedef __int64_t int64_t; +#endif + +#ifndef _UINT64_T_DEFINED_ +#define _UINT64_T_DEFINED_ +typedef __uint64_t uint64_t; +#endif + +/* 7.18.1.2 Minimum-width integer types */ +typedef __int_least8_t int_least8_t; +typedef __uint_least8_t uint_least8_t; +typedef __int_least16_t int_least16_t; +typedef __uint_least16_t uint_least16_t; +typedef __int_least32_t int_least32_t; +typedef __uint_least32_t uint_least32_t; +typedef __int_least64_t int_least64_t; +typedef __uint_least64_t uint_least64_t; + +/* 7.18.1.3 Fastest minimum-width integer types */ +typedef __int_fast8_t int_fast8_t; +typedef __uint_fast8_t uint_fast8_t; +typedef __int_fast16_t int_fast16_t; +typedef __uint_fast16_t uint_fast16_t; +typedef __int_fast32_t int_fast32_t; +typedef __uint_fast32_t uint_fast32_t; +typedef __int_fast64_t int_fast64_t; +typedef __uint_fast64_t uint_fast64_t; + +/* 7.18.1.4 Integer types capable of holding object pointers */ +#ifndef _INTPTR_T_DEFINED_ +#define _INTPTR_T_DEFINED_ +typedef __intptr_t intptr_t; +#endif + +#ifndef _UINTPTR_T_DEFINED_ +#define _UINTPTR_T_DEFINED_ +typedef __uintptr_t uintptr_t; +#endif + +/* 7.18.1.5 Greatest-width integer types */ +typedef __intmax_t intmax_t; +typedef __uintmax_t uintmax_t; + +//#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) +/* + * 7.18.2 Limits of specified-width integer types. + * + * The following object-like macros specify the minimum and maximum limits + * of integer types corresponding to the typedef names defined above. + */ + +/* 7.18.2.1 Limits of exact-width integer types */ +#define INT8_MIN (-0x7f - 1) +#define INT16_MIN (-0x7fff - 1) +#define INT32_MIN (-0x7fffffff - 1) +#ifdef __x86_64__ +#define INT64_MIN (-0x7fffffffffffffffL - 1) +#else +#define INT64_MIN (-0x7fffffffffffffffLL - 1) +#endif + +#define INT8_MAX 0x7f +#define INT16_MAX 0x7fff +#define INT32_MAX 0x7fffffff +#ifdef __x86_64__ +#define INT64_MAX 0x7fffffffffffffffL +#else +#define INT64_MAX 0x7fffffffffffffffLL +#endif + +#define UINT8_MAX 0xff +#define UINT16_MAX 0xffff +#define UINT32_MAX 0xffffffffU +#ifdef __x86_64__ +#define UINT64_MAX 0xffffffffffffffffUL +#else +#define UINT64_MAX 0xffffffffffffffffULL +#endif + +/* 7.18.2.2 Limits of minimum-width integer types */ +#define INT_LEAST8_MIN INT8_MIN +#define INT_LEAST16_MIN INT16_MIN +#define INT_LEAST32_MIN INT32_MIN +#define INT_LEAST64_MIN INT64_MIN + +#define INT_LEAST8_MAX INT8_MAX +#define INT_LEAST16_MAX INT16_MAX +#define INT_LEAST32_MAX INT32_MAX +#define INT_LEAST64_MAX INT64_MAX + +#define UINT_LEAST8_MAX UINT8_MAX +#define UINT_LEAST16_MAX UINT16_MAX +#define UINT_LEAST32_MAX UINT32_MAX +#define UINT_LEAST64_MAX UINT64_MAX + +/* 7.18.2.3 Limits of fastest minimum-width integer types */ +#define INT_FAST8_MIN INT8_MIN +#define INT_FAST16_MIN INT16_MIN +#define INT_FAST32_MIN INT32_MIN +#define INT_FAST64_MIN INT64_MIN + +#define INT_FAST8_MAX INT8_MAX +#ifdef __x86_64__ +#define INT_FAST16_MAX INT64_MAX +#define INT_FAST32_MAX INT64_MAX +#else +#define INT_FAST16_MAX INT32_MAX +#define INT_FAST32_MAX INT32_MAX +#endif +#define INT_FAST64_MAX INT64_MAX + +#define UINT_FAST8_MAX UINT8_MAX +#ifdef __x86_64__ +#define UINT_FAST16_MAX UINT64_MAX +#define UINT_FAST32_MAX UINT64_MAX +#else +#define UINT_FAST16_MAX UINT32_MAX +#define UINT_FAST32_MAX UINT32_MAX +#endif +#define UINT_FAST64_MAX UINT64_MAX + +/* 7.18.2.4 Limits of integer types capable of holding object pointers */ +#ifdef __x86_64__ +#define INTPTR_MIN INT64_MIN +#define INTPTR_MAX INT64_MAX +#define UINTPTR_MAX UINT64_MAX +#else +#define INTPTR_MIN INT32_MIN +#define INTPTR_MAX INT32_MAX +#define UINTPTR_MAX UINT32_MAX +#endif + +/* 7.18.2.5 Limits of greatest-width integer types */ +#define INTMAX_MIN INT64_MIN +#define INTMAX_MAX INT64_MAX +#define UINTMAX_MAX UINT64_MAX + +/* + * 7.18.3 Limits of other integer types. + * + * The following object-like macros specify the minimum and maximum limits + * of integer types corresponding to types specified in other standard + * header files. + */ + +/* Limits of ptrdiff_t */ +#define PTRDIFF_MIN INTPTR_MIN +#define PTRDIFF_MAX INTPTR_MAX + +/* Limits of size_t (also in limits.h) */ +#ifndef SIZE_MAX +#define SIZE_MAX UINTPTR_MAX +#endif + +/* Limits of wchar_t */ +# ifdef __WCHAR_MAX__ +# define WCHAR_MAX __WCHAR_MAX__ +# else +# define WCHAR_MAX (2147483647) +# endif +# ifdef __WCHAR_MIN__ +# define WCHAR_MIN __WCHAR_MIN__ +# elif L'\0' - 1 > 0 +# define WCHAR_MIN L'\0' +# else +# define WCHAR_MIN (-WCHAR_MAX - 1) +# endif + +/* Limits of wint_t */ +# define WINT_MIN (0u) +# define WINT_MAX (4294967295u) + +//#endif /* __cplusplus || __STDC_LIMIT_MACROS */ + +//#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) +/* + * 7.18.4 Macros for integer constants. + * + * The following function-like macros expand to integer constants + * suitable for initializing objects that have integer types corresponding + * to types defined in . The argument in any instance of + * these macros shall be a decimal, octal, or hexadecimal constant with + * a value that does not exceed the limits for the corresponding type. + */ + +/* 7.18.4.1 Macros for minimum-width integer constants. */ +#define INT8_C(_c) (_c) +#define INT16_C(_c) (_c) +#define INT32_C(_c) (_c) +#define INT64_C(_c) __CONCAT(_c, LL) + +#define UINT8_C(_c) (_c) +#define UINT16_C(_c) (_c) +#define UINT32_C(_c) __CONCAT(_c, U) +#define UINT64_C(_c) __CONCAT(_c, ULL) + +/* 7.18.4.2 Macros for greatest-width integer constants. */ +#define INTMAX_C(_c) __CONCAT(_c, LL) +#define UINTMAX_C(_c) __CONCAT(_c, ULL) + +//#endif /* __cplusplus || __STDC_CONSTANT_MACROS */ + +#endif /* _SYS_STDINT_H_ */ diff --git a/bitacross-worker/rust-sgx-sdk/common/inc/sys/struct_timespec.h b/bitacross-worker/rust-sgx-sdk/common/inc/sys/struct_timespec.h new file mode 100644 index 0000000000..bca02c8809 --- /dev/null +++ b/bitacross-worker/rust-sgx-sdk/common/inc/sys/struct_timespec.h @@ -0,0 +1,37 @@ +// +// Copyright © 2005-2020 Rich Felker, et al. +// Licensed under the MIT license. +// + +/* Copyright © 2005-2020 Rich Felker, et al. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef _SYS_TIMESPEC_H_ +#define _SYS_TIMESPEC_H_ + +#include + +struct timespec { + __time_t tv_sec; + long tv_nsec; +}; + +#endif diff --git a/bitacross-worker/rust-sgx-sdk/common/inc/sys/types.h b/bitacross-worker/rust-sgx-sdk/common/inc/sys/types.h new file mode 100644 index 0000000000..b64f89df04 --- /dev/null +++ b/bitacross-worker/rust-sgx-sdk/common/inc/sys/types.h @@ -0,0 +1,129 @@ +/* $OpenBSD: types.h,v 1.31 2008/03/16 19:42:57 otto Exp $ */ +/* $NetBSD: types.h,v 1.29 1996/11/15 22:48:25 jtc Exp $ */ + +/*- + * Copyright (c) 1982, 1986, 1991, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)types.h 8.4 (Berkeley) 1/21/94 + */ + +#ifndef _SYS_TYPES_H_ +#define _SYS_TYPES_H_ + +#include +#include + +typedef unsigned char u_char; +typedef unsigned short u_short; +typedef unsigned int u_int; +typedef unsigned long u_long; + +typedef unsigned char unchar; /* Sys V compatibility */ +typedef unsigned short ushort; /* Sys V compatibility */ +typedef unsigned int uint; /* Sys V compatibility */ +typedef unsigned long ulong; /* Sys V compatibility */ + +#ifndef _INT8_T_DEFINED_ +#define _INT8_T_DEFINED_ +typedef __int8_t int8_t; +#endif + +#ifndef _UINT8_T_DEFINED_ +#define _UINT8_T_DEFINED_ +typedef __uint8_t uint8_t; +#endif + +#ifndef _INT16_T_DEFINED_ +#define _INT16_T_DEFINED_ +typedef __int16_t int16_t; +#endif + +#ifndef _UINT16_T_DEFINED_ +#define _UINT16_T_DEFINED_ +typedef __uint16_t uint16_t; +#endif + +#ifndef _INT32_T_DEFINED_ +#define _INT32_T_DEFINED_ +typedef __int32_t int32_t; +#endif + +#ifndef _UINT32_T_DEFINED_ +#define _UINT32_T_DEFINED_ +typedef __uint32_t uint32_t; +#endif + +#ifndef _INT64_T_DEFINED_ +#define _INT64_T_DEFINED_ +typedef __int64_t int64_t; +#endif + +#ifndef _UINT64_T_DEFINED_ +#define _UINT64_T_DEFINED_ +typedef __uint64_t uint64_t; +#endif + +#ifndef _INTPTR_T_DEFINED_ +#define _INTPTR_T_DEFINED_ +typedef __intptr_t intptr_t; +#endif + +#ifndef _UINTPTR_T_DEFINED_ +#define _UINTPTR_T_DEFINED_ +typedef __uintptr_t uintptr_t; +#endif + +/* BSD-style unsigned bits types */ +typedef __uint8_t u_int8_t; +typedef __uint16_t u_int16_t; +typedef __uint32_t u_int32_t; +typedef __uint64_t u_int64_t; + + +#ifndef _SIZE_T_DEFINED_ +#define _SIZE_T_DEFINED_ +typedef __size_t size_t; +#endif + +#ifndef _SSIZE_T_DEFINED_ +#define _SSIZE_T_DEFINED_ +typedef __ssize_t ssize_t; +#endif + +#ifndef _OFF_T_DEFINED_ +#define _OFF_T_DEFINED_ +typedef __off_t off_t; +typedef __off64_t off64_t; +#endif + +#endif /* !_SYS_TYPES_H_ */ diff --git a/bitacross-worker/rust-sgx-sdk/common/inc/sys/uio.h b/bitacross-worker/rust-sgx-sdk/common/inc/sys/uio.h new file mode 100644 index 0000000000..2544f06a7d --- /dev/null +++ b/bitacross-worker/rust-sgx-sdk/common/inc/sys/uio.h @@ -0,0 +1,35 @@ +// +// Copyright © 2005-2020 Rich Felker, et al. +// Licensed under the MIT license. +// + +/* Copyright © 2005-2020 Rich Felker, et al. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef _SYS_UIO_H_ +#define _SYS_UIO_H_ + +struct iovec { + void *iov_base; + size_t iov_len; +}; + +#endif diff --git a/bitacross-worker/rust-sgx-sdk/common/inc/time.h b/bitacross-worker/rust-sgx-sdk/common/inc/time.h new file mode 100644 index 0000000000..01cfd6e4e9 --- /dev/null +++ b/bitacross-worker/rust-sgx-sdk/common/inc/time.h @@ -0,0 +1,105 @@ +/* $OpenBSD: time.h,v 1.18 2006/01/06 18:53:04 millert Exp $ */ +/* $NetBSD: time.h,v 1.9 1994/10/26 00:56:35 cgd Exp $ */ + +/* + * Copyright (c) 1989 The Regents of the University of California. + * All rights reserved. + * + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)time.h 5.12 (Berkeley) 3/9/91 + */ + +#ifndef _TIME_H_ +#define _TIME_H_ + +#include +#include +#include + +#ifndef NULL +#ifdef __cplusplus +#define NULL 0 +#else +#define NULL ((void *)0) +#endif +#endif + +#if !defined (_CLOCK_T_DEFINED_) && !defined (_CLOCK_T_DEFINED) +#define _CLOCK_T_DEFINED_ +#define _CLOCK_T_DEFINED +typedef __clock_t clock_t; +#endif + +#if !defined (_TIME_T_DEFINED_) && !defined (_TIME_T_DEFINED) +#define _TIME_T_DEFINED_ +#define _TIME_T_DEFINED +typedef __time_t time_t; +#endif + +#if !defined (_SIZE_T_DEFINED_) && !defined (_SIZE_T_DEFINED) +#define _SIZE_T_DEFINED_ +#define _SIZE_T_DEFINED +typedef __size_t size_t; +#endif + +#if !defined (_TM_DEFINED) +#define _TM_DEFINED +struct tm { + int tm_sec; /* seconds after the minute [0-60] */ + int tm_min; /* minutes after the hour [0-59] */ + int tm_hour; /* hours since midnight [0-23] */ + int tm_mday; /* day of the month [1-31] */ + int tm_mon; /* months since January [0-11] */ + int tm_year; /* years since 1900 */ + int tm_wday; /* days since Sunday [0-6] */ + int tm_yday; /* days since January 1 [0-365] */ + int tm_isdst; /* Daylight Saving Time flag */ + /* FIXME: naming issue exists on Fedora/Ubuntu */ + long tm_gmtoff; /* offset from UTC in seconds */ + char *tm_zone; /* timezone abbreviation */ +}; +#endif + +__BEGIN_DECLS + +double _TLIBC_CDECL_ difftime(time_t, time_t); +char * _TLIBC_CDECL_ asctime(const struct tm *); +size_t _TLIBC_CDECL_ strftime(char *, size_t, const char *, const struct tm *); + +/* + * Non-C99 + */ +char * _TLIBC_CDECL_ asctime_r(const struct tm *, char *); + +__END_DECLS + +#endif /* !_TIME_H_ */ diff --git a/bitacross-worker/rust-sgx-sdk/common/inc/unistd.h b/bitacross-worker/rust-sgx-sdk/common/inc/unistd.h new file mode 100644 index 0000000000..2ab3a9a042 --- /dev/null +++ b/bitacross-worker/rust-sgx-sdk/common/inc/unistd.h @@ -0,0 +1,59 @@ +/* $OpenBSD: unistd.h,v 1.62 2008/06/25 14:58:54 millert Exp $ */ +/* $NetBSD: unistd.h,v 1.26.4.1 1996/05/28 02:31:51 mrg Exp $ */ + +/*- + * Copyright (c) 1991 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)unistd.h 5.13 (Berkeley) 6/17/91 + */ + +#ifndef _UNISTD_H_ +#define _UNISTD_H_ + +#include +#include + +__BEGIN_DECLS + +void * _TLIBC_CDECL_ sbrk(intptr_t); + +/* + * Deprecated Non-C99. + */ +_TLIBC_DEPRECATED_FUNCTION_(int _TLIBC_CDECL_, execl, const char *, const char *, ...); +_TLIBC_DEPRECATED_FUNCTION_(int _TLIBC_CDECL_, execlp, const char *, const char *, ...); +_TLIBC_DEPRECATED_FUNCTION_(int _TLIBC_CDECL_, execle, const char *, const char *, ...); +_TLIBC_DEPRECATED_FUNCTION_(int _TLIBC_CDECL_, execv, const char *, char * const *); +_TLIBC_DEPRECATED_FUNCTION_(int _TLIBC_CDECL_, execve, const char *, char * const *, char * const *); +_TLIBC_DEPRECATED_FUNCTION_(int _TLIBC_CDECL_, execvp, const char *, char * const *); + +//_TLIBC_DEPRECATED_FUNCTION_(pid_t _TLIBC_CDECL_, fork, void); /* no pid_t */ + +__END_DECLS + +#endif /* !_UNISTD_H_ */ diff --git a/bitacross-worker/rust-sgx-sdk/common/inc/wchar.h b/bitacross-worker/rust-sgx-sdk/common/inc/wchar.h new file mode 100644 index 0000000000..2db86f28eb --- /dev/null +++ b/bitacross-worker/rust-sgx-sdk/common/inc/wchar.h @@ -0,0 +1,143 @@ +/* $OpenBSD: wchar.h,v 1.11 2010/07/24 09:58:39 guenther Exp $ */ +/* $NetBSD: wchar.h,v 1.16 2003/03/07 07:11:35 tshiozak Exp $ */ + +/*- + * Copyright (c)1999 Citrus Project, + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/*- + * Copyright (c) 1999, 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Julian Coleman. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _WCHAR_H_ +#define _WCHAR_H_ + +#include +#include +#include /* WCHAR_MAX/WCHAR_MIN */ + +#ifndef NULL +#ifdef __cplusplus +#define NULL 0 +#else +#define NULL ((void *)0) +#endif +#endif + +#if !defined(_WCHAR_T_DEFINED_) && !defined(__cplusplus) +#define _WCHAR_T_DEFINED_ +#ifndef __WCHAR_TYPE__ +#define __WCHAR_TYPE__ int +#endif +typedef __WCHAR_TYPE__ wchar_t; +#endif + +#ifndef _MBSTATE_T_DEFINED_ +#define _MBSTATE_T_DEFINED_ +typedef __mbstate_t mbstate_t; +#endif + +#ifndef _WINT_T_DEFINED_ +#define _WINT_T_DEFINED_ +typedef __wint_t wint_t; +#endif + +#ifndef _SIZE_T_DEFINED_ +#define _SIZE_T_DEFINED_ +typedef __size_t size_t; +#endif + +#ifndef WEOF +#define WEOF ((wint_t)-1) +#endif + +__BEGIN_DECLS + +wint_t _TLIBC_CDECL_ btowc(int); +int _TLIBC_CDECL_ wctob(wint_t); +size_t _TLIBC_CDECL_ mbrlen(const char *, size_t, mbstate_t *); +size_t _TLIBC_CDECL_ mbrtowc(wchar_t *, const char *, size_t, mbstate_t *); +int _TLIBC_CDECL_ mbsinit(const mbstate_t *); +size_t _TLIBC_CDECL_ mbsrtowcs(wchar_t *, const char **, size_t, mbstate_t *); +size_t _TLIBC_CDECL_ wcrtomb(char *, wchar_t, mbstate_t *); +wchar_t * _TLIBC_CDECL_ wcschr(const wchar_t *, wchar_t); +int _TLIBC_CDECL_ wcscmp(const wchar_t *, const wchar_t *); +int _TLIBC_CDECL_ wcscoll(const wchar_t *, const wchar_t *); +size_t _TLIBC_CDECL_ wcscspn(const wchar_t *, const wchar_t *); +size_t _TLIBC_CDECL_ wcslen(const wchar_t *); +wchar_t * _TLIBC_CDECL_ wcsncat(wchar_t *, const wchar_t *, size_t); +int _TLIBC_CDECL_ wcsncmp(const wchar_t *, const wchar_t *, size_t); +wchar_t * _TLIBC_CDECL_ wcsncpy(wchar_t *, const wchar_t *, size_t); +wchar_t * _TLIBC_CDECL_ wcspbrk(const wchar_t *, const wchar_t *); +wchar_t * _TLIBC_CDECL_ wcsrchr(const wchar_t *, wchar_t); +size_t _TLIBC_CDECL_ wcsrtombs(char *, const wchar_t **, size_t, mbstate_t *); +size_t _TLIBC_CDECL_ wcsspn(const wchar_t *, const wchar_t *); +wchar_t * _TLIBC_CDECL_ wcsstr(const wchar_t *, const wchar_t *); +wchar_t * _TLIBC_CDECL_ wcstok(wchar_t *, const wchar_t *, wchar_t **); +size_t _TLIBC_CDECL_ wcsxfrm(wchar_t *, const wchar_t *, size_t); +wchar_t * _TLIBC_CDECL_ wmemchr(const wchar_t *, wchar_t, size_t); +int _TLIBC_CDECL_ wmemcmp(const wchar_t *, const wchar_t *, size_t); +wchar_t * _TLIBC_CDECL_ wmemcpy(wchar_t *, const wchar_t *, size_t); +wchar_t * _TLIBC_CDECL_ wmemmove(wchar_t *, const wchar_t *, size_t); +wchar_t * _TLIBC_CDECL_ wmemset(wchar_t *, wchar_t, size_t); + +int _TLIBC_CDECL_ swprintf(wchar_t *, size_t, const wchar_t *, ...); +int _TLIBC_CDECL_ vswprintf(wchar_t *, size_t, const wchar_t *, __va_list); + +long double _TLIBC_CDECL_ wcstold (const wchar_t *, wchar_t **); +long long _TLIBC_CDECL_ wcstoll (const wchar_t *, wchar_t **, int); +unsigned long long _TLIBC_CDECL_ wcstoull (const wchar_t *, wchar_t **, int); + +/* leagcy version of wcsstr */ +wchar_t * _TLIBC_CDECL_ wcswcs(const wchar_t *, const wchar_t *); + +__END_DECLS + +#endif /* !_WCHAR_H_ */ diff --git a/bitacross-worker/rust-sgx-sdk/common/inc/wctype.h b/bitacross-worker/rust-sgx-sdk/common/inc/wctype.h new file mode 100644 index 0000000000..0ab9497d78 --- /dev/null +++ b/bitacross-worker/rust-sgx-sdk/common/inc/wctype.h @@ -0,0 +1,80 @@ +/* $OpenBSD: wctype.h,v 1.5 2006/01/06 18:53:04 millert Exp $ */ +/* $NetBSD: wctype.h,v 1.5 2003/03/02 22:18:11 tshiozak Exp $ */ + +/*- + * Copyright (c)1999 Citrus Project, + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * citrus Id: wctype.h,v 1.4 2000/12/21 01:50:21 itojun Exp + */ + +#ifndef _WCTYPE_H_ +#define _WCTYPE_H_ + +#include +#include + +#ifndef _WINT_T_DEFINED_ +#define _WINT_T_DEFINED_ +typedef __wint_t wint_t; +#endif + +#ifndef _WCTRANS_T_DEFINED_ +#define _WCTRANS_T_DEFINED_ +typedef __wctrans_t wctrans_t; +#endif + +#ifndef _WCTYPE_T_DEFINED_ +#define _WCTYPE_T_DEFINED_ +typedef __wctype_t wctype_t; +#endif + +#ifndef WEOF +#define WEOF ((wint_t)-1) +#endif + +__BEGIN_DECLS + +int _TLIBC_CDECL_ iswalnum(wint_t); +int _TLIBC_CDECL_ iswalpha(wint_t); +int _TLIBC_CDECL_ iswblank(wint_t); +int _TLIBC_CDECL_ iswcntrl(wint_t); +int _TLIBC_CDECL_ iswdigit(wint_t); +int _TLIBC_CDECL_ iswgraph(wint_t); +int _TLIBC_CDECL_ iswlower(wint_t); +int _TLIBC_CDECL_ iswprint(wint_t); +int _TLIBC_CDECL_ iswpunct(wint_t); +int _TLIBC_CDECL_ iswspace(wint_t); +int _TLIBC_CDECL_ iswupper(wint_t); +int _TLIBC_CDECL_ iswxdigit(wint_t); +int _TLIBC_CDECL_ iswctype(wint_t, wctype_t); +wint_t _TLIBC_CDECL_ towctrans(wint_t, wctrans_t); +wint_t _TLIBC_CDECL_ towlower(wint_t); +wint_t _TLIBC_CDECL_ towupper(wint_t); +wctrans_t _TLIBC_CDECL_ wctrans(const char *); +wctype_t _TLIBC_CDECL_ wctype(const char *); + +__END_DECLS + +#endif /* _WCTYPE_H_ */ diff --git a/bitacross-worker/rust-sgx-sdk/edl/inc/dirent.h b/bitacross-worker/rust-sgx-sdk/edl/inc/dirent.h new file mode 100644 index 0000000000..be63f8332d --- /dev/null +++ b/bitacross-worker/rust-sgx-sdk/edl/inc/dirent.h @@ -0,0 +1,39 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License.. + +#ifndef _EDL_DIRENT_H +#define _EDL_DIRENT_H + +struct dirent_t +{ + uint64_t d_ino; + int64_t d_off; + unsigned short int d_reclen; + unsigned char d_type; + char d_name[256]; +}; + +struct dirent64_t +{ + uint64_t d_ino; + int64_t d_off; + unsigned short int d_reclen; + unsigned char d_type; + char d_name[256]; +}; + +#endif diff --git a/bitacross-worker/rust-sgx-sdk/edl/inc/stat.h b/bitacross-worker/rust-sgx-sdk/edl/inc/stat.h new file mode 100644 index 0000000000..7f04c3cec9 --- /dev/null +++ b/bitacross-worker/rust-sgx-sdk/edl/inc/stat.h @@ -0,0 +1,65 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License.. + +#ifndef _EDL_STAT_H +#define _EDL_STAT_H + +struct stat_t +{ + uint64_t st_dev; + uint64_t st_ino; + uint64_t st_nlink; + uint32_t st_mode; + uint32_t st_uid; + uint32_t st_gid; + int __pad0; + uint64_t st_rdev; + uint64_t st_size; + int64_t st_blksize; + int64_t st_blocks; + int64_t st_atime; + int64_t st_atime_nsec; + int64_t st_mtime; + int64_t st_mtime_nsec; + int64_t st_ctime; + int64_t st_ctime_nsec; + int64_t __reserved[3]; +}; + +struct stat64_t +{ + uint64_t st_dev; + uint64_t st_ino; + uint64_t st_nlink; + uint32_t st_mode; + uint32_t st_uid; + uint32_t st_gid; + int __pad0; + uint64_t st_rdev; + uint64_t st_size; + int64_t st_blksize; + int64_t st_blocks; + int64_t st_atime; + int64_t st_atime_nsec; + int64_t st_mtime; + int64_t st_mtime_nsec; + int64_t st_ctime; + int64_t st_ctime_nsec; + int64_t __reserved[3]; +}; + +#endif diff --git a/bitacross-worker/rust-sgx-sdk/edl/intel/sgx_dcap_tvl.edl b/bitacross-worker/rust-sgx-sdk/edl/intel/sgx_dcap_tvl.edl new file mode 100644 index 0000000000..7c5c0d8c69 --- /dev/null +++ b/bitacross-worker/rust-sgx-sdk/edl/intel/sgx_dcap_tvl.edl @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2011-2020 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +enclave { + + include "sgx_qve_header.h" + include "sgx_ql_quote.h" + + + trusted { + + /** + * Verify QvE Report and Identity + * + * @param p_quote[IN] - Pointer to SGX Quote. + * @param quote_size[IN] - Size of the buffer pointed to by p_quote (in bytes). + * @param p_qve_report_info[IN] - The output of API "sgx_qv_verify_quote", it should contain QvE report and nonce + * @param expiration_check_date[IN] - This is the date to verify QvE report data, you should use same value for this API and "sgx_qv_verify_quote" + * @param collateral_expiration_status[IN] - The output of API "sgx_qv_verify_quote" about quote verification collateral's expiration status + * @param quote_verification_result[IN] - The output of API "sgx_qv_verify_quote" about quote verification result + * @param p_supplemental_data[IN] - The output of API "sgx_qv_verify_quote", the pointer to supplemental data + * @param supplemental_data_size[IN] - Size of the buffer pointed to by p_quote (in bytes) + * @param qve_isvsvn_threshold [IN] - The threshold of QvE ISVSVN, the ISVSVN of QvE used to verify quote must be greater or equal to this threshold. You can get latest QvE ISVSVN in QvE Identity (JSON) from Intel PCS. + * + * @return Status code of the operation, one of: + * - SGX_QL_SUCCESS + * - SGX_QL_ERROR_INVALID_PARAMETER + * - SGX_QL_ERROR_REPORT // Error when verifying QvE report + * - SGX_QL_ERROR_UNEXPECTED // Error when comparing QvE report data + * - SGX_QL_QVEIDENTITY_MISMATCH // Error when comparing QvE identity + * - SGX_QL_QVE_OUT_OF_DATE // QvE ISVSVN is smaller than input QvE ISV SVN threshold + **/ + + public quote3_error_t sgx_tvl_verify_qve_report_and_identity( + [in, size=quote_size] const uint8_t *p_quote, + uint32_t quote_size, + [in, count=1] const sgx_ql_qe_report_info_t *p_qve_report_info, + time_t expiration_check_date, + uint32_t collateral_expiration_status, + sgx_ql_qv_result_t quote_verification_result, + [in, size=supplemental_data_size] const uint8_t *p_supplemental_data, + uint32_t supplemental_data_size, + sgx_isv_svn_t qve_isvsvn_threshold); + }; +}; diff --git a/bitacross-worker/rust-sgx-sdk/edl/intel/sgx_pthread.edl b/bitacross-worker/rust-sgx-sdk/edl/intel/sgx_pthread.edl new file mode 100644 index 0000000000..7a097a7396 --- /dev/null +++ b/bitacross-worker/rust-sgx-sdk/edl/intel/sgx_pthread.edl @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2011-2019 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +enclave { + untrusted { + [cdecl] int pthread_wait_timeout_ocall (unsigned long long waiter, unsigned long long timeout); + [cdecl] int pthread_create_ocall(unsigned long long self); + [cdecl] int pthread_wakeup_ocall(unsigned long long waiter); + }; +}; diff --git a/bitacross-worker/rust-sgx-sdk/edl/intel/sgx_tkey_exchange.edl b/bitacross-worker/rust-sgx-sdk/edl/intel/sgx_tkey_exchange.edl new file mode 100644 index 0000000000..3e18c89582 --- /dev/null +++ b/bitacross-worker/rust-sgx-sdk/edl/intel/sgx_tkey_exchange.edl @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2011-2019 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +enclave { + trusted { + public sgx_status_t sgx_ra_get_ga(sgx_ra_context_t context, + [out] sgx_ec256_public_t *g_a); + + public sgx_status_t sgx_ra_proc_msg2_trusted(sgx_ra_context_t context, + [in]const sgx_ra_msg2_t *p_msg2, /*copy msg2 except quote into enclave */ + [in] const sgx_target_info_t *p_qe_target, + [out] sgx_report_t *p_report, + [out] sgx_quote_nonce_t *p_nonce); + + public sgx_status_t sgx_ra_get_msg3_trusted(sgx_ra_context_t context, + uint32_t quote_size, + [in]sgx_report_t* qe_report, + [user_check]sgx_ra_msg3_t *p_msg3, + uint32_t msg3_size); + }; +}; diff --git a/bitacross-worker/rust-sgx-sdk/edl/intel/sgx_tprotected_fs.edl b/bitacross-worker/rust-sgx-sdk/edl/intel/sgx_tprotected_fs.edl new file mode 100644 index 0000000000..2dfad370a9 --- /dev/null +++ b/bitacross-worker/rust-sgx-sdk/edl/intel/sgx_tprotected_fs.edl @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2011-2019 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +enclave { + from "sgx_tstdc.edl" import *; + untrusted { + void* u_sgxprotectedfs_exclusive_file_open([in, string] const char* filename, uint8_t read_only, [out] int64_t* file_size, [out] int32_t* error_code); + uint8_t u_sgxprotectedfs_check_if_file_exists([in, string] const char* filename); + int32_t u_sgxprotectedfs_fread_node([user_check] void* f, uint64_t node_number, [out, size=node_size] uint8_t* buffer, uint32_t node_size); + int32_t u_sgxprotectedfs_fwrite_node([user_check] void* f, uint64_t node_number, [in, size=node_size] uint8_t* buffer, uint32_t node_size); + int32_t u_sgxprotectedfs_fclose([user_check] void* f); + uint8_t u_sgxprotectedfs_fflush([user_check] void* f); + int32_t u_sgxprotectedfs_remove([in, string] const char* filename); + + void* u_sgxprotectedfs_recovery_file_open([in, string] const char* filename); + uint8_t u_sgxprotectedfs_fwrite_recovery_node([user_check] void* f, [in, count=data_length] uint8_t* data, uint32_t data_length); + int32_t u_sgxprotectedfs_do_file_recovery([in, string] const char* filename, [in, string] const char* recovery_filename, uint32_t node_size); + }; +}; diff --git a/bitacross-worker/rust-sgx-sdk/edl/intel/sgx_tstdc.edl b/bitacross-worker/rust-sgx-sdk/edl/intel/sgx_tstdc.edl new file mode 100644 index 0000000000..4124debcfb --- /dev/null +++ b/bitacross-worker/rust-sgx-sdk/edl/intel/sgx_tstdc.edl @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2011-2019 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +enclave { + untrusted { + [cdecl] void sgx_oc_cpuidex([out] int cpuinfo[4], int leaf, int subleaf); + + /* Go outside and wait on my untrusted event */ + [cdecl] int sgx_thread_wait_untrusted_event_ocall([user_check] const void *self); + + /* Wake a thread waiting on its untrusted event */ + [cdecl] int sgx_thread_set_untrusted_event_ocall([user_check] const void *waiter); + + /* Wake a thread waiting on its untrusted event, and wait on my untrusted event */ + [cdecl] int sgx_thread_setwait_untrusted_events_ocall([user_check] const void *waiter, [user_check] const void *self); + + /* Wake multiple threads waiting on their untrusted events */ + [cdecl] int sgx_thread_set_multiple_untrusted_events_ocall([in, count = total] const void **waiters, size_t total); + }; +}; diff --git a/bitacross-worker/rust-sgx-sdk/edl/intel/sgx_tswitchless.edl b/bitacross-worker/rust-sgx-sdk/edl/intel/sgx_tswitchless.edl new file mode 100644 index 0000000000..a20669ab59 --- /dev/null +++ b/bitacross-worker/rust-sgx-sdk/edl/intel/sgx_tswitchless.edl @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2011-2019 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +enclave { + + trusted { + public sgx_status_t sl_init_switchless([user_check]void* sl_data); + public sgx_status_t sl_run_switchless_tworker(); + }; + +}; diff --git a/bitacross-worker/rust-sgx-sdk/edl/intel/sgx_ttls.edl b/bitacross-worker/rust-sgx-sdk/edl/intel/sgx_ttls.edl new file mode 100644 index 0000000000..ca0906f578 --- /dev/null +++ b/bitacross-worker/rust-sgx-sdk/edl/intel/sgx_ttls.edl @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2011-2021 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +enclave{ + include "sgx_report.h" + include "sgx_qve_header.h" + include "sgx_ql_lib_common.h" + include "sgx_ql_quote.h" + + untrusted { + quote3_error_t sgx_tls_get_qe_target_info_ocall([size = target_info_size, out] sgx_target_info_t *p_target_info, + size_t target_info_size); + + quote3_error_t sgx_tls_get_quote_size_ocall([out] uint32_t *p_quote_size); + + quote3_error_t sgx_tls_get_quote_ocall([size = report_size, in] sgx_report_t* p_report, + size_t report_size, + [size = quote_size, out] uint8_t *p_quote, + uint32_t quote_size); + + quote3_error_t sgx_tls_get_supplemental_data_size_ocall([out] uint32_t *p_supplemental_data_size); + + quote3_error_t sgx_tls_verify_quote_ocall( + [size = quote_size, in] const uint8_t *p_quote, + uint32_t quote_size, + time_t expiration_check_date, + [out] sgx_ql_qv_result_t *p_quote_verification_result, + [size = qve_report_info_size, in, out] sgx_ql_qe_report_info_t *p_qve_report_info, + size_t qve_report_info_size, + [size = supplemental_data_size, out] uint8_t *p_supplemental_data, + uint32_t supplemental_data_size); + + }; +}; diff --git a/bitacross-worker/rust-sgx-sdk/edl/sgx_asyncio.edl b/bitacross-worker/rust-sgx-sdk/edl/sgx_asyncio.edl new file mode 100644 index 0000000000..f46373894e --- /dev/null +++ b/bitacross-worker/rust-sgx-sdk/edl/sgx_asyncio.edl @@ -0,0 +1,33 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +enclave { + + include "sys/epoll.h" + include "poll.h" + + trusted { + /* define ECALLs here. */ + }; + + untrusted { + int u_poll_ocall([out] int *error, [in, out, count=nfds] struct pollfd *fds, nfds_t nfds, int timeout); + int u_epoll_create1_ocall([out] int *error, int flags); + int u_epoll_ctl_ocall([out] int *error, int epfd, int op, int fd, [in] struct epoll_event *event); + int u_epoll_wait_ocall([out] int *error, int epfd, [out, count=maxevents] struct epoll_event *events, int maxevents, int timeout); + }; +}; diff --git a/bitacross-worker/rust-sgx-sdk/edl/sgx_backtrace.edl b/bitacross-worker/rust-sgx-sdk/edl/sgx_backtrace.edl new file mode 100644 index 0000000000..4a9e7ef8c4 --- /dev/null +++ b/bitacross-worker/rust-sgx-sdk/edl/sgx_backtrace.edl @@ -0,0 +1,31 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +enclave { + + from "sgx_fd.edl" import *; + from "sgx_file.edl" import *; + from "sgx_mem.edl" import *; + + trusted { + /* define ECALLs here. */ + }; + + untrusted { + /* define OCALLs here. */ + }; +}; diff --git a/bitacross-worker/rust-sgx-sdk/edl/sgx_env.edl b/bitacross-worker/rust-sgx-sdk/edl/sgx_env.edl new file mode 100644 index 0000000000..d4a77cc816 --- /dev/null +++ b/bitacross-worker/rust-sgx-sdk/edl/sgx_env.edl @@ -0,0 +1,40 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +enclave { + + include "pwd.h" + + trusted { + /* define ECALLs here. */ + }; + + untrusted { + char **u_environ_ocall(); + char *u_getenv_ocall([in, string] const char *name); + int u_setenv_ocall([out] int *error, [in, string] const char *name, [in, string] const char *value, int overwrite); + int u_unsetenv_ocall([out] int *error, [in, string] const char *name); + int u_chdir_ocall([out] int *error, [in, string] const char *dir); + char *u_getcwd_ocall([out] int *error, [out, size=buflen] char *buf, size_t buflen); + int u_getpwuid_r_ocall(unsigned int uid, + [out] struct passwd *pwd, + [out, size=buflen] char *buf, + size_t buflen, + [out] struct passwd **passwd_result); + unsigned int u_getuid_ocall(); + }; +}; diff --git a/bitacross-worker/rust-sgx-sdk/edl/sgx_fd.edl b/bitacross-worker/rust-sgx-sdk/edl/sgx_fd.edl new file mode 100644 index 0000000000..cd668b71c0 --- /dev/null +++ b/bitacross-worker/rust-sgx-sdk/edl/sgx_fd.edl @@ -0,0 +1,57 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +enclave { + + include "inc/stat.h" + include "sys/uio.h" + include "time.h" + + from "sgx_mem.edl" import *; + + trusted { + /* define ECALLs here. */ + }; + + untrusted { + size_t u_read_ocall([out] int *error, int fd, [user_check] void *buf, size_t count); + size_t u_pread64_ocall([out] int *error, int fd, [user_check] void *buf, size_t count, int64_t offset); + size_t u_readv_ocall([out] int *error, int fd, [in, count=iovcnt] const struct iovec *iov, int iovcnt); + size_t u_preadv64_ocall([out] int *error, int fd, [in, count=iovcnt] const struct iovec *iov, int iovcnt, int64_t offset); + + size_t u_write_ocall([out] int *error, int fd, [user_check] const void *buf, size_t count); + size_t u_pwrite64_ocall([out] int *error, int fd, [user_check] const void *buf, size_t count, int64_t offset); + size_t u_writev_ocall([out] int *error, int fd, [in, count=iovcnt] const struct iovec *iov, int iovcnt); + size_t u_pwritev64_ocall([out] int *error, int fd, [in, count=iovcnt] const struct iovec *iov, int iovcnt, int64_t offset); + + size_t u_sendfile_ocall([out] int *error, int out_fd, int in_fd, [in, out] int64_t *offset, size_t count); + size_t u_copy_file_range_ocall([out] int *error, int fd_in, [in, out] int64_t *off_in, int fd_out, [in, out] int64_t *off_out, size_t len, unsigned int flags); + size_t u_splice_ocall([out] int *error, int fd_in, [in, out] int64_t *off_in, int fd_out, [in, out] int64_t *off_out, size_t len, unsigned int flags); + + int u_fcntl_arg0_ocall([out] int *error, int fd, int cmd); + int u_fcntl_arg1_ocall([out] int *error, int fd, int cmd, int arg); + int u_ioctl_arg0_ocall([out] int *error, int fd, int request); + int u_ioctl_arg1_ocall([out] int *error, int fd, int request, [in, out] int *arg); + + int u_close_ocall([out] int *error, int fd); + int u_isatty_ocall([out] int *error, int fd); + int u_dup_ocall([out] int *error, int oldfd); + int u_eventfd_ocall([out] int *error, unsigned int initval, int flags); + + int u_futimens_ocall([out] int *error, int fd, [in, count=2] const struct timespec *times); + }; +}; diff --git a/bitacross-worker/rust-sgx-sdk/edl/sgx_file.edl b/bitacross-worker/rust-sgx-sdk/edl/sgx_file.edl new file mode 100644 index 0000000000..c70ec599a2 --- /dev/null +++ b/bitacross-worker/rust-sgx-sdk/edl/sgx_file.edl @@ -0,0 +1,66 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +enclave { + + include "inc/stat.h" + include "inc/dirent.h" + + trusted { + /* define ECALLs here. */ + }; + + untrusted { + int u_open_ocall([out] int *error, [in, string] const char *pathname, int flags); + int u_open64_ocall([out] int *error, [in, string] const char *path, int oflag, int mode); + int u_openat_ocall([out] int *error, int dirfd, [in, string] const char *pathname, int flags); + + int u_fstat_ocall([out] int *error, int fd, [out] struct stat_t *buf); + int u_fstat64_ocall([out] int *error, int fd, [out] struct stat64_t *buf); + int u_stat_ocall([out] int *error, [in, string] const char *path, [out] struct stat_t *buf); + int u_stat64_ocall([out] int *error, [in, string] const char *path, [out] struct stat64_t *buf); + int u_lstat_ocall([out] int *error, [in, string] const char *path, [out] struct stat_t *buf); + int u_lstat64_ocall([out] int *error, [in, string] const char *path, [out] struct stat64_t *buf); + uint64_t u_lseek_ocall([out] int *error, int fd, int64_t offset, int whence); + int64_t u_lseek64_ocall([out] int *error, int fd, int64_t offset, int whence); + int u_ftruncate_ocall([out] int *error, int fd, int64_t length); + int u_ftruncate64_ocall([out] int *error, int fd, int64_t length); + int u_truncate_ocall([out] int *error, [in, string] const char *path, int64_t length); + int u_truncate64_ocall([out] int *error, [in, string] const char *path, int64_t length); + + int u_fsync_ocall([out] int *error, int fd); + int u_fdatasync_ocall([out] int *error, int fd); + int u_fchmod_ocall([out] int *error, int fd, uint32_t mode); + int u_unlink_ocall([out] int *error, [in, string] const char *pathname); + int u_link_ocall([out] int *error, [in, string] const char *oldpath, [in, string] const char *newpath); + int u_unlinkat_ocall([out] int *error, int dirfd, [in, string] const char *pathname, int flags); + int u_linkat_ocall([out] int *error, int olddirfd, [in, string] const char *oldpath, int newdirfd, [in, string] const char *newpath, int flags); + int u_rename_ocall([out] int *error, [in, string] const char *oldpath, [in, string] const char *newpath); + int u_chmod_ocall([out] int *error, [in, string] const char *path, uint32_t mode); + size_t u_readlink_ocall([out] int *error, [in, string] const char *path, [out, size=bufsz] char *buf, size_t bufsz); + int u_symlink_ocall([out] int *error, [in, string] const char *path1, [in, string] const char *path2); + char *u_realpath_ocall([out] int *error, [in, string] const char *pathname); + int u_mkdir_ocall([out] int *error, [in, string] const char *pathname, uint32_t mode); + int u_rmdir_ocall([out] int *error, [in, string] const char *pathname); + void *u_fdopendir_ocall([out] int *error, int fd); + void *u_opendir_ocall([out] int *error, [in, string] const char *pathname); + int u_readdir64_r_ocall([user_check] void *dirp, [in, out] struct dirent64_t *entry, [out] struct dirent64_t **result); + int u_closedir_ocall([out] int *error, [user_check] void *dirp); + int u_dirfd_ocall([out] int *error, [user_check] void *dirp); + int u_fstatat64_ocall([out] int *error, int dirfd, [in, string] const char *pathname, [out] struct stat64_t *buf, int flags); + }; +}; diff --git a/bitacross-worker/rust-sgx-sdk/edl/sgx_fs.edl b/bitacross-worker/rust-sgx-sdk/edl/sgx_fs.edl new file mode 100644 index 0000000000..2618be9352 --- /dev/null +++ b/bitacross-worker/rust-sgx-sdk/edl/sgx_fs.edl @@ -0,0 +1,31 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +enclave { + + from "sgx_mem.edl" import *; + from "sgx_fd.edl" import *; + from "sgx_file.edl" import *; + + trusted { + /* define ECALLs here. */ + }; + + untrusted { + /* define OCALLs here. */ + }; +}; diff --git a/bitacross-worker/rust-sgx-sdk/edl/sgx_mem.edl b/bitacross-worker/rust-sgx-sdk/edl/sgx_mem.edl new file mode 100644 index 0000000000..db55802755 --- /dev/null +++ b/bitacross-worker/rust-sgx-sdk/edl/sgx_mem.edl @@ -0,0 +1,40 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +enclave { + + trusted { + /* define ECALLs here. */ + }; + + untrusted { + void *u_malloc_ocall([out] int *error, size_t size); + void u_free_ocall([user_check] void *p); + + void *u_mmap_ocall([out] int *error, + [user_check] void *start, + size_t length, + int prot, + int flags, + int fd, + int64_t offset); + int u_munmap_ocall([out] int *error, [user_check] void *start, size_t length); + + int u_msync_ocall([out] int *error, [user_check] void *addr, size_t length, int flags); + int u_mprotect_ocall([out] int *error, [user_check] void *addr, size_t length, int prot); + }; +}; diff --git a/bitacross-worker/rust-sgx-sdk/edl/sgx_net.edl b/bitacross-worker/rust-sgx-sdk/edl/sgx_net.edl new file mode 100644 index 0000000000..a803b53ac2 --- /dev/null +++ b/bitacross-worker/rust-sgx-sdk/edl/sgx_net.edl @@ -0,0 +1,41 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +enclave { + + include "sys/socket.h" + include "netdb.h" + + from "sgx_socket.edl" import *; + from "sgx_asyncio.edl" import *; + from "sgx_fd.edl" import *; + from "sgx_time.edl" import *; + + trusted { + /* define ECALLs here. */ + }; + + untrusted { + int u_getaddrinfo_ocall([out] int *error, + [in, string] const char *node, + [in, string] const char *service, + [in] const struct addrinfo *hints, + [out] struct addrinfo **res); + void u_freeaddrinfo_ocall([user_check] struct addrinfo *res); + char *u_gai_strerror_ocall(int errcode); + }; +}; diff --git a/bitacross-worker/rust-sgx-sdk/edl/sgx_net_switchless.edl b/bitacross-worker/rust-sgx-sdk/edl/sgx_net_switchless.edl new file mode 100644 index 0000000000..ec5c500cfc --- /dev/null +++ b/bitacross-worker/rust-sgx-sdk/edl/sgx_net_switchless.edl @@ -0,0 +1,92 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +enclave { + + include "sys/socket.h" + include "poll.h" + from "sgx_fs.edl" import *; + from "sgx_time.edl" import *; + from "sgx_mem.edl" import *; + + trusted { + /* define ECALLs here. */ + }; + + untrusted { + + int u_net_socket_ocall([out] int *error, int domain, int ty, int protocol) transition_using_threads; + int u_net_socketpair_ocall([out] int *error, int domain, int ty, int protocol, [out] int sv[2]) transition_using_threads; + int u_net_bind_ocall([out] int *error, int sockfd, [in, size=addrlen] const struct sockaddr *addr, socklen_t addrlen) transition_using_threads; + int u_net_listen_ocall([out] int *error, int sockfd, int backlog) transition_using_threads; + int u_net_accept4_ocall([out] int *error, + int sockfd, + [in, out, size=addrlen_in] struct sockaddr *addr, + socklen_t addrlen_in, + [out] socklen_t *addrlen_out, + int flags) transition_using_threads; + int u_net_connect_ocall([out] int *error, + int sockfd, + [in, size=addrlen] const struct sockaddr *addr, + socklen_t addrlen) transition_using_threads; + size_t u_net_recv_ocall([out] int *error, int sockfd, [out, size=len] void *buf, size_t len, int flags) transition_using_threads; + size_t u_net_recvfrom_ocall([out] int *error, + int sockfd, + [out, size=len] void *buf, + size_t len, + int flags, + [out, size=addrlen_in] struct sockaddr *src_addr, + socklen_t addrlen_in, + [out] socklen_t *addrlen_out) transition_using_threads; + size_t u_net_recvmsg_ocall([out] int *error, int sockfd, [in, out] struct msghdr *msg, int flags) transition_using_threads; + size_t u_net_send_ocall([out] int *error, int sockfd, [in, size=len] const void *buf, size_t len, int flags) transition_using_threads; + size_t u_net_sendto_ocall([out] int *error, + int sockfd, + [in, size=len] const void *buf, + size_t len, + int flags, + [in, size=addrlen] const struct sockaddr *dest_addr, + socklen_t addrlen) transition_using_threads; + size_t u_sendmsg_ocall([out] int *error, int sockfd, [in] const struct msghdr *msg, int flags) transition_using_threads; + int u_net_getsockopt_ocall([out] int *error, + int sockfd, + int level, + int optname, + [out, size=optlen_in] void *optval, + socklen_t optlen_in, + [out] socklen_t *optlen_out) transition_using_threads; + int u_net_setsockopt_ocall([out] int *error, + int sockfd, + int level, + int optname, + [in, size=optlen] const void *optval, + socklen_t optlen) transition_using_threads; + int u_net_getsockname_ocall([out] int *error, + int sockfd, + [out, size=addrlen_in] struct sockaddr *addr, + socklen_t addrlen_in, + [out] socklen_t *addrlen_out) transition_using_threads; + int u_net_getpeername_ocall([out] int *error, + int sockfd, + [out, size=addrlen_in] struct sockaddr *addr, + socklen_t addrlen_in, + [out] socklen_t *addrlen_out) transition_using_threads; + int u_net_shutdown_ocall([out] int *error, int sockfd, int how) transition_using_threads; + int u_net_ioctl_ocall([out] int *error, int fd, int request, [in, out] int *arg) transition_using_threads; + int u_net_poll_ocall([out] int *error, [in, out, count=nfds] struct pollfd *fds, nfds_t nfds, int timeout) transition_using_threads; + }; +}; diff --git a/bitacross-worker/rust-sgx-sdk/edl/sgx_pipe.edl b/bitacross-worker/rust-sgx-sdk/edl/sgx_pipe.edl new file mode 100644 index 0000000000..00c12f5e7c --- /dev/null +++ b/bitacross-worker/rust-sgx-sdk/edl/sgx_pipe.edl @@ -0,0 +1,31 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +enclave { + + from "sgx_fd.edl" import *; + from "sgx_asyncio.edl" import *; + + trusted { + /* define ECALLs here. */ + }; + + untrusted { + int u_pipe_ocall([out] int *error, [out, count=2] int *pipefd); + int u_pipe2_ocall([out] int *error, [out, count=2] int *pipefd, int flags); + }; +}; diff --git a/bitacross-worker/rust-sgx-sdk/edl/sgx_process.edl b/bitacross-worker/rust-sgx-sdk/edl/sgx_process.edl new file mode 100644 index 0000000000..69123df5d8 --- /dev/null +++ b/bitacross-worker/rust-sgx-sdk/edl/sgx_process.edl @@ -0,0 +1,28 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +enclave { + + trusted { + /* define ECALLs here. */ + + }; + + untrusted { + int u_getpid_ocall(); + }; +}; diff --git a/bitacross-worker/rust-sgx-sdk/edl/sgx_signal.edl b/bitacross-worker/rust-sgx-sdk/edl/sgx_signal.edl new file mode 100644 index 0000000000..fd9b0f0d14 --- /dev/null +++ b/bitacross-worker/rust-sgx-sdk/edl/sgx_signal.edl @@ -0,0 +1,43 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +enclave { + include "signal.h" + + trusted { + /* define ECALLs here. */ + public int t_signal_handler_ecall([in]const siginfo_t *info); + }; + + untrusted { + int u_sigaction_ocall([out]int *error, + int signum, + [in] const struct sigaction *act, + [out] struct sigaction *oldact, + uint64_t enclave_id); + + int u_sigprocmask_ocall([out]int *error, + int signum, + [in] const sigset_t *set, + [out] sigset_t *oldset); + + int u_raise_ocall(int signum) allow(t_signal_handler_ecall); + + void u_signal_clear_ocall(uint64_t enclave_id); + }; +}; + diff --git a/bitacross-worker/rust-sgx-sdk/edl/sgx_socket.edl b/bitacross-worker/rust-sgx-sdk/edl/sgx_socket.edl new file mode 100644 index 0000000000..6fc8ff7c85 --- /dev/null +++ b/bitacross-worker/rust-sgx-sdk/edl/sgx_socket.edl @@ -0,0 +1,111 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +enclave { + + include "sys/socket.h" + + from "sgx_mem.edl" import *; + + trusted { + /* define ECALLs here. */ + }; + + untrusted { + int u_socket_ocall([out] int *error, int domain, int ty, int protocol); + int u_socketpair_ocall([out] int *error, int domain, int ty, int protocol, [out] int sv[2]); + int u_bind_ocall([out] int *error, int sockfd, [in, size=addrlen] const struct sockaddr *addr, socklen_t addrlen); + int u_listen_ocall([out] int *error, int sockfd, int backlog); + int u_accept_ocall([out] int *error, + int sockfd, + [in, out, size=addrlen_in] struct sockaddr *addr, + socklen_t addrlen_in, + [out] socklen_t *addrlen_out); + int u_accept4_ocall([out] int *error, + int sockfd, + [in, out, size=addrlen_in] struct sockaddr *addr, + socklen_t addrlen_in, + [out] socklen_t *addrlen_out, + int flags); + int u_connect_ocall([out] int *error, + int sockfd, + [in, size=addrlen] const struct sockaddr *addr, + socklen_t addrlen); + size_t u_recv_ocall([out] int *error, int sockfd,[user_check] void *buf, size_t len, int flags); + size_t u_recvfrom_ocall([out] int *error, + int sockfd, + [user_check] void *buf, + size_t len, + int flags, + [out, size=addrlen_in] struct sockaddr *src_addr, + socklen_t addrlen_in, + [out] socklen_t *addrlen_out); + size_t u_recvmsg_ocall([out] int *error, + int sockfd, + [out, size=msg_namelen] void *msg_name, + socklen_t msg_namelen, + [out] socklen_t* msg_namelen_out, + [in, count=msg_iovlen] struct iovec* msg_iov, + size_t msg_iovlen, + [out, size=msg_controllen] void *msg_control, + size_t msg_controllen, + [out] size_t* msg_controllen_out, + [out] int* msg_flags, + int flags); + size_t u_send_ocall([out] int *error, int sockfd, [user_check] const void *buf, size_t len, int flags); + size_t u_sendto_ocall([out] int *error, + int sockfd, + [user_check] const void *buf, + size_t len, + int flags, + [in, size=addrlen] const struct sockaddr *dest_addr, + socklen_t addrlen); + size_t u_sendmsg_ocall([out] int *error, + int sockfd, + [in, size=msg_namelen] const void* msg_name, + socklen_t msg_namelen, + [in, count=msg_iovlen] const struct iovec* msg_iov, + size_t msg_iovlen, + [in, size=msg_controllen] const void* msg_control, + size_t msg_controllen, + int flags); + int u_getsockopt_ocall([out] int *error, + int sockfd, + int level, + int optname, + [out, size=optlen_in] void *optval, + socklen_t optlen_in, + [out] socklen_t *optlen_out); + int u_setsockopt_ocall([out] int *error, + int sockfd, + int level, + int optname, + [in, size=optlen] const void *optval, + socklen_t optlen); + int u_getsockname_ocall([out] int *error, + int sockfd, + [out, size=addrlen_in] struct sockaddr *addr, + socklen_t addrlen_in, + [out] socklen_t *addrlen_out); + int u_getpeername_ocall([out] int *error, + int sockfd, + [out, size=addrlen_in] struct sockaddr *addr, + socklen_t addrlen_in, + [out] socklen_t *addrlen_out); + int u_shutdown_ocall([out] int *error, int sockfd, int how); + }; +}; diff --git a/bitacross-worker/rust-sgx-sdk/edl/sgx_stdio.edl b/bitacross-worker/rust-sgx-sdk/edl/sgx_stdio.edl new file mode 100644 index 0000000000..5367d9ab97 --- /dev/null +++ b/bitacross-worker/rust-sgx-sdk/edl/sgx_stdio.edl @@ -0,0 +1,29 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +enclave { + + from "sgx_fd.edl" import *; + + trusted { + /* define ECALLs here. */ + }; + + untrusted { + /* define OCALLs here. */ + }; +}; diff --git a/bitacross-worker/rust-sgx-sdk/edl/sgx_sys.edl b/bitacross-worker/rust-sgx-sdk/edl/sgx_sys.edl new file mode 100644 index 0000000000..bc74b96843 --- /dev/null +++ b/bitacross-worker/rust-sgx-sdk/edl/sgx_sys.edl @@ -0,0 +1,32 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +enclave { + + include "sched.h" + + trusted { + /* define ECALLs here. */ + }; + + untrusted { + long u_sysconf_ocall([out] int *error, int name); + int u_prctl_ocall([out] int *error, int option, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5); + int u_sched_setaffinity_ocall([out] int *error, pid_t pid, size_t cpusetsize, [in, size=cpusetsize] cpu_set_t *mask); + int u_sched_getaffinity_ocall([out] int *error, pid_t pid, size_t cpusetsize, [out, size=cpusetsize] cpu_set_t *mask); + }; +}; diff --git a/bitacross-worker/rust-sgx-sdk/edl/sgx_thread.edl b/bitacross-worker/rust-sgx-sdk/edl/sgx_thread.edl new file mode 100644 index 0000000000..71512f0e56 --- /dev/null +++ b/bitacross-worker/rust-sgx-sdk/edl/sgx_thread.edl @@ -0,0 +1,32 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +enclave { + + include "time.h" + + from "intel/sgx_pthread.edl" import *; + from "sgx_sys.edl" import *; + + trusted { + /* define ECALLs here. */ + }; + + untrusted { + int u_sched_yield_ocall([out]int *error); + int u_nanosleep_ocall([out]int *error, [in]const struct timespec *req, [out]struct timespec *rem); + }; +}; diff --git a/bitacross-worker/rust-sgx-sdk/edl/sgx_time.edl b/bitacross-worker/rust-sgx-sdk/edl/sgx_time.edl new file mode 100644 index 0000000000..adeeeccf92 --- /dev/null +++ b/bitacross-worker/rust-sgx-sdk/edl/sgx_time.edl @@ -0,0 +1,29 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +enclave { + + include "time.h" + + trusted { + /* define ECALLs here. */ + }; + + untrusted { + int u_clock_gettime_ocall([out] int *error, int clk_id, [out] struct timespec *tp); + }; +}; diff --git a/bitacross-worker/rust-sgx-sdk/edl/sgx_tstd.edl b/bitacross-worker/rust-sgx-sdk/edl/sgx_tstd.edl new file mode 100644 index 0000000000..9b74272f50 --- /dev/null +++ b/bitacross-worker/rust-sgx-sdk/edl/sgx_tstd.edl @@ -0,0 +1,38 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +enclave { + + from "sgx_time.edl" import *; + + trusted { + /* define ECALLs here. */ + public void t_global_init_ecall(uint64_t id, [in, size=len] const uint8_t *path, size_t len); + public void t_global_exit_ecall(); + }; + + untrusted { + /* define OCALLs here. */ + int u_thread_set_event_ocall([out] int *error, [user_check] const void *tcs); + int u_thread_wait_event_ocall([out] int *error, [user_check] const void *tcs, [in] const struct timespec *timeout); + int u_thread_set_multiple_events_ocall([out] int *error, [in, count=total] const void **tcss, int total); + int u_thread_setwait_events_ocall([out] int *error, + [user_check] const void *waiter_tcs, + [user_check] const void *self_tcs, + [in] const struct timespec *timeout); + }; +}; diff --git a/bitacross-worker/rust-sgx-sdk/version b/bitacross-worker/rust-sgx-sdk/version new file mode 100644 index 0000000000..78e68ab976 --- /dev/null +++ b/bitacross-worker/rust-sgx-sdk/version @@ -0,0 +1 @@ +27bd225ae6dbcd1d0a6d4d9590acc4d73c5195c2 diff --git a/bitacross-worker/rust-toolchain.toml b/bitacross-worker/rust-toolchain.toml new file mode 100644 index 0000000000..23ed88e6c8 --- /dev/null +++ b/bitacross-worker/rust-toolchain.toml @@ -0,0 +1,4 @@ +[toolchain] +channel = "nightly-2022-10-22" +targets = ["wasm32-unknown-unknown"] +profile = "default" # include rustfmt, clippy diff --git a/bitacross-worker/rustfmt.toml b/bitacross-worker/rustfmt.toml new file mode 100644 index 0000000000..104b9aa998 --- /dev/null +++ b/bitacross-worker/rustfmt.toml @@ -0,0 +1,18 @@ +# Basic +hard_tabs = true +max_width = 100 +use_small_heuristics = "Max" +# Imports +imports_granularity = "Crate" +reorder_imports = true +# Consistency +newline_style = "Unix" +# Misc +chain_width = 80 +spaces_around_ranges = false +match_arm_leading_pipes = "Preserve" +match_arm_blocks = false +match_block_trailing_comma = true +trailing_comma = "Vertical" +trailing_semicolon = false +use_field_init_shorthand = true \ No newline at end of file diff --git a/bitacross-worker/samples/teeracle/README.md b/bitacross-worker/samples/teeracle/README.md new file mode 100644 index 0000000000..05758f7d09 --- /dev/null +++ b/bitacross-worker/samples/teeracle/README.md @@ -0,0 +1,58 @@ +# Teeracle install into Securitee's kubernetes cluster + +This example is about to install [Integritee's Teeracle](https://docs.integritee.network/3-our-technology/3.5-use-cases/3.5.3-teeracle-oracle-framework). + +*Prerequisites:* + +* Ensure you have access to a Kubernetes cluster with SGX-enabled nodes and kubectl installed and configured. The easiest way to get started is to order Kubernetes from Securitee [Securitee Kubernetes](https://securitee.tech/products/), which offers SGX-enabled nodes. +* You have [Helm](https://helm.sh/docs/intro/install/) installed + +## Kubernetes deployment walkthrough + +We are now installing Teeracle + +### Install steps + + +* Edit the configuration values in file [kubernetes/values.yaml](kubernetes/values.yaml) + ```yaml + app: + url: "wss://rococo.api.integritee.network" + interval: "2m" + ``` +* Install the Teeracle into the cluster + + ```bash + helm install -f ./kubernetes/values.yaml teeracle ./kubernetes --create-namespace -n teeracle + or run + ./install-teeracle.sh + ``` + + +## Misc. + +### SGX Plugin + +If you are running in simulation mode, or are using a different plugin please edit the [kubernetes/templates/teeracle.yaml](kubernetes/templates/teeracle.yaml) + ```yaml + limits: + sgx.intel.com/epc: "10Mi" + sgx.intel.com/enclave: 1 + sgx.intel.com/provision: 1 + ``` + +### PCCS server + +The DCAP attestation requires a running PCCS server - which is provided by Securitee by default that's why we need to mount the ```/etc/sgx_default_qcnl.conf``` config file +see [kubernetes/templates/teeracle.yaml](kubernetes/templates/teeracle.yaml) + ```yaml + volumeMounts: + - name: qcnl + mountPath: /etc/sgx_default_qcnl.conf + ... + volumes: + - name: qcnl + hostPath: + path: /etc/sgx_default_qcnl.conf + + ``` diff --git a/bitacross-worker/samples/teeracle/install-teeracle.sh b/bitacross-worker/samples/teeracle/install-teeracle.sh new file mode 100755 index 0000000000..dbc21bc2b4 --- /dev/null +++ b/bitacross-worker/samples/teeracle/install-teeracle.sh @@ -0,0 +1,7 @@ +#!/bin/env bash + +namespace=teeracle +helm uninstall -n $namespace teeracle + +helm install -f ./kubernetes/values.yaml teeracle ./kubernetes --create-namespace -n $namespace + diff --git a/bitacross-worker/samples/teeracle/kubernetes/Chart.yaml b/bitacross-worker/samples/teeracle/kubernetes/Chart.yaml new file mode 100644 index 0000000000..d1f3a9a7f8 --- /dev/null +++ b/bitacross-worker/samples/teeracle/kubernetes/Chart.yaml @@ -0,0 +1,7 @@ +apiVersion: v2 +name: teeracle +description: teeracle dcap + +type: application +version: 0.1.0 +appVersion: 1.0.0 \ No newline at end of file diff --git a/bitacross-worker/samples/teeracle/kubernetes/templates/teeracle.yaml b/bitacross-worker/samples/teeracle/kubernetes/templates/teeracle.yaml new file mode 100644 index 0000000000..130ad79cb4 --- /dev/null +++ b/bitacross-worker/samples/teeracle/kubernetes/templates/teeracle.yaml @@ -0,0 +1,73 @@ +kind: ServiceAccount +apiVersion: v1 +metadata: + name: teeracle + namespace: {{ .Release.Namespace }} +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: teeracle-main + namespace: {{ .Release.Namespace }} + labels: + app: teeracle + role: main + tier: backend +spec: + replicas: 1 + selector: + matchLabels: + app: teeracle + role: main + tier: backend + template: + metadata: + labels: + app: teeracle + spec: + serviceAccountName: teeracle + containers: + - image: {{ .Values.image }} + imagePullPolicy: {{ .Values.imagePullPolicy }} + + args: [ + "-p", "443", + "-u", {{ .Values.app.url }}, + "--enable-metrics", + "--data-dir", "/opt/teeracle", + "run", + "--teeracle-interval", {{ .Values.app.interval }} + ] + name: teeracle + + resources: + # Resource request to use Intel SGX Device Plugin + # If you are running in simulation mode, or are using a different plugin, + # update these values accordingly + limits: + sgx.intel.com/epc: "10Mi" + sgx.intel.com/enclave: 1 + sgx.intel.com/provision: 1 + + volumeMounts: + - name: aesmd-socket + mountPath: /var/run/aesmd + - name: data-dir + mountPath: /opt/teeracle + - name: qcnl + mountPath: /etc/sgx_default_qcnl.conf + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + volumes: + - name: aesmd-socket + hostPath: + path: /var/run/aesmd + - name: data-dir + hostPath: + path: /opt/teeracle + - name: qcnl + hostPath: + path: /etc/sgx_default_qcnl.conf + diff --git a/bitacross-worker/samples/teeracle/kubernetes/values.yaml b/bitacross-worker/samples/teeracle/kubernetes/values.yaml new file mode 100644 index 0000000000..8a423ee3ab --- /dev/null +++ b/bitacross-worker/samples/teeracle/kubernetes/values.yaml @@ -0,0 +1,14 @@ +imagePullSecrets: + - name: regcred + +imagePullPolicy: IfNotPresent + +image: integritee/teeracle:v0.12.2-dev + +# +# To get more insights run: +# docker run integritee/teeracle:v0.12.2-dev --help +# +app: + url: "wss://rococo.api.integritee.network" + interval: "2m" \ No newline at end of file diff --git a/bitacross-worker/scripts/benchmark_local-setup.sh b/bitacross-worker/scripts/benchmark_local-setup.sh new file mode 100644 index 0000000000..40bc700f05 --- /dev/null +++ b/bitacross-worker/scripts/benchmark_local-setup.sh @@ -0,0 +1,31 @@ +#!/bin/bash +set -e + +pushd .. + +pushd bin +./litentry-worker mrenclave | tee ~/mrenclave.b58 +popd + +ulimit -S -n 4096 + +python3 local-setup/launch.py local-setup/config/benchmark.json & +PID=$! +echo $PID > ./benchmark.pid +echo "Benchmark PID: $PID" + +sleep 40s + +pushd bin +./bitacross-cli -p 9930 -P 2030 trusted --direct --mrenclave "$(cat ~/mrenclave.b58)" benchmark 20 100 -w +popd + +sleep 10s + +if test -f "./benchmark.pid"; then + echo "Killing benchmark process" + kill -s SIGTERM "$(cat ./benchmark.pid)" + rm benchmark.pid +fi + +popd diff --git a/bitacross-worker/scripts/changelog/.gitignore b/bitacross-worker/scripts/changelog/.gitignore new file mode 100644 index 0000000000..4fbcc523b0 --- /dev/null +++ b/bitacross-worker/scripts/changelog/.gitignore @@ -0,0 +1,4 @@ +changelog.md +*.json +release*.md +.env diff --git a/bitacross-worker/scripts/changelog/Gemfile b/bitacross-worker/scripts/changelog/Gemfile new file mode 100644 index 0000000000..f2d7c3bd71 --- /dev/null +++ b/bitacross-worker/scripts/changelog/Gemfile @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +source 'https://rubygems.org' + +git_source(:github) { |repo_name| "https://github.com/#{repo_name}" } + +gem 'octokit', '~> 4' + +gem 'git_diff_parser', '~> 3' + +gem 'toml', '~> 0.3.0' + +gem 'rake', group: :dev + +gem 'optparse', '~> 0.1.1' + +gem 'logger', '~> 1.4' + +gem 'test-unit', group: :dev + +gem 'rubocop', group: :dev, require: false diff --git a/bitacross-worker/scripts/changelog/Gemfile.lock b/bitacross-worker/scripts/changelog/Gemfile.lock new file mode 100644 index 0000000000..855d7f91a5 --- /dev/null +++ b/bitacross-worker/scripts/changelog/Gemfile.lock @@ -0,0 +1,79 @@ +GEM + remote: https://rubygems.org/ + specs: + addressable (2.8.0) + public_suffix (>= 2.0.2, < 5.0) + ast (2.4.2) + faraday (1.8.0) + faraday-em_http (~> 1.0) + faraday-em_synchrony (~> 1.0) + faraday-excon (~> 1.1) + faraday-httpclient (~> 1.0.1) + faraday-net_http (~> 1.0) + faraday-net_http_persistent (~> 1.1) + faraday-patron (~> 1.0) + faraday-rack (~> 1.0) + multipart-post (>= 1.2, < 3) + ruby2_keywords (>= 0.0.4) + faraday-em_http (1.0.0) + faraday-em_synchrony (1.0.0) + faraday-excon (1.1.0) + faraday-httpclient (1.0.1) + faraday-net_http (1.0.1) + faraday-net_http_persistent (1.2.0) + faraday-patron (1.0.0) + faraday-rack (1.0.0) + git_diff_parser (3.2.0) + logger (1.4.4) + multipart-post (2.1.1) + octokit (4.21.0) + faraday (>= 0.9) + sawyer (~> 0.8.0, >= 0.5.3) + optparse (0.1.1) + parallel (1.21.0) + parser (3.0.2.0) + ast (~> 2.4.1) + parslet (2.0.0) + power_assert (2.0.1) + public_suffix (4.0.6) + rainbow (3.0.0) + rake (13.0.6) + regexp_parser (2.1.1) + rexml (3.2.5) + rubocop (1.23.0) + parallel (~> 1.10) + parser (>= 3.0.0.0) + rainbow (>= 2.2.2, < 4.0) + regexp_parser (>= 1.8, < 3.0) + rexml + rubocop-ast (>= 1.12.0, < 2.0) + ruby-progressbar (~> 1.7) + unicode-display_width (>= 1.4.0, < 3.0) + rubocop-ast (1.13.0) + parser (>= 3.0.1.1) + ruby-progressbar (1.11.0) + ruby2_keywords (0.0.5) + sawyer (0.8.2) + addressable (>= 2.3.5) + faraday (> 0.8, < 2.0) + test-unit (3.5.1) + power_assert + toml (0.3.0) + parslet (>= 1.8.0, < 3.0.0) + unicode-display_width (2.1.0) + +PLATFORMS + x86_64-darwin-20 + +DEPENDENCIES + git_diff_parser (~> 3) + logger (~> 1.4) + octokit (~> 4) + optparse (~> 0.1.1) + rake + rubocop + test-unit + toml (~> 0.3.0) + +BUNDLED WITH + 2.2.22 diff --git a/bitacross-worker/scripts/changelog/README.md b/bitacross-worker/scripts/changelog/README.md new file mode 100644 index 0000000000..4776277e70 --- /dev/null +++ b/bitacross-worker/scripts/changelog/README.md @@ -0,0 +1,3 @@ +## License + +Everything in this folder is GPL 3.0 licensed. The original has been authored by parity and was taken from here: https://github.com/paritytech/polkadot/tree/master/scripts/ci/changelog. \ No newline at end of file diff --git a/bitacross-worker/scripts/changelog/bin/changelog b/bitacross-worker/scripts/changelog/bin/changelog new file mode 100755 index 0000000000..15b17d6166 --- /dev/null +++ b/bitacross-worker/scripts/changelog/bin/changelog @@ -0,0 +1,84 @@ +#!/usr/bin/env ruby + +# frozen_string_literal: true + +# call for instance as: +# ./bin/changelog [] [] +# for instance, for the release notes of v1.2.3: +# ./bin/changelog v1.2.3 +# or +# ./bin/changelog v1.2.3 v1.2.2 +# +# You may set the ENV NO_CACHE to force fetching from Github +# You should also ensure you set the ENV: GITHUB_TOKEN + +require_relative '../lib/changelog' +require 'logger' + +logger = Logger.new($stdout) +logger.level = Logger::DEBUG +logger.debug('Starting') + +owner = 'integritee-network' +repo = 'worker' + +gh_worker = SubRef.new(format('%s/%s', { owner: owner, repo: repo })) +last_release_ref = gh_worker.get_last_ref() + +worker_ref2 = ARGV[0] || 'HEAD' +worker_ref1 = ARGV[1] || last_release_ref + +output = ARGV[2] || 'release-notes.md' + +ENV['REF1'] = worker_ref1 +ENV['REF2'] = worker_ref2 + +pallets_ref1 = gh_worker.get_dependency_reference(worker_ref1, 'pallet-teerex') +pallets_ref2 = gh_worker.get_dependency_reference(worker_ref2, 'pallet-teerex') + +logger.debug("Worker from: #{worker_ref1}") +logger.debug("Worker to: #{worker_ref2}") + +logger.debug("Pallets from: #{pallets_ref1}") +logger.debug("Pallets to: #{pallets_ref2}") + +pallets_data = 'pallets.json' +worker_data = 'worker.json' + +logger.debug("Using PALLETS: #{pallets_data}") +logger.debug("Using WORKER: #{worker_data}") + +logger.warn('NO_CACHE set') if ENV['NO_CACHE'] + +if ENV['NO_CACHE'] || !File.file?(worker_data) + logger.debug(format('Fetching data for Worker into %s', worker_data)) + cmd = format('changelogerator %s/%s -f %s -t %s > %s', + { owner: owner, repo: 'worker', from: worker_ref1, to: worker_ref2, output: worker_data }) + system(cmd) +else + logger.debug("Re-using:#{worker_data}") +end + +if ENV['NO_CACHE'] || !File.file?(pallets_data) + logger.debug(format('Fetching data for Pallets into %s', pallets_data)) + cmd = format('changelogerator %s/%s -f %s -t %s > %s', + { owner: owner, repo: 'pallets', from: pallets_ref1, to: pallets_ref2, output: pallets_data }) + system(cmd) +else + logger.debug("Re-using:#{pallets_data}") +end + +# Here we compose all the pieces together into one +# single big json file. +cmd = format('jq \ + --slurpfile pallets %s \ + --slurpfile worker %s \ + -n \'{ + pallets: $pallets[0], + worker: $worker[0], + }\' > context.json', pallets_data, worker_data) +system(cmd) + +cmd = format('tera --env --env-key env --include-path templates \ + --template templates/template.md.tera context.json > %s', output) +system(cmd) diff --git a/bitacross-worker/scripts/changelog/digests/.gitignore b/bitacross-worker/scripts/changelog/digests/.gitignore new file mode 100644 index 0000000000..a6c57f5fb2 --- /dev/null +++ b/bitacross-worker/scripts/changelog/digests/.gitignore @@ -0,0 +1 @@ +*.json diff --git a/bitacross-worker/scripts/changelog/digests/.gitkeep b/bitacross-worker/scripts/changelog/digests/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/bitacross-worker/scripts/changelog/lib/changelog.rb b/bitacross-worker/scripts/changelog/lib/changelog.rb new file mode 100644 index 0000000000..d7cf92e7d2 --- /dev/null +++ b/bitacross-worker/scripts/changelog/lib/changelog.rb @@ -0,0 +1,38 @@ +# frozen_string_literal: true + +# A Class to find Substrate references +class SubRef + require 'octokit' + require 'toml' + + attr_reader :client, :repository + + def initialize(github_repo) + @client = Octokit::Client.new( + access_token: ENV['GITHUB_TOKEN'] + ) + @repository = @client.repository(github_repo) + end + + # This function checks the Cargo.lock of a given + # Rust project, for a given package, and fetches + # the dependency git ref. + def get_dependency_reference(ref, package) + cargo = TOML::Parser.new( + Base64.decode64( + @client.contents( + @repository.full_name, + path: 'Cargo.lock', + query: { ref: ref.to_s } + ).content + ) + ).parsed + cargo['package'].find { |p| p['name'] == package }['source'].split('#').last + end + + # Get the git ref of the last release for the repo. + # repo is given in the form integritee-network/worker + def get_last_ref() + 'refs/tags/' + @client.latest_release(@repository.full_name).tag_name + end +end diff --git a/bitacross-worker/scripts/changelog/templates/_free_notes.md.tera b/bitacross-worker/scripts/changelog/templates/_free_notes.md.tera new file mode 100644 index 0000000000..c4a841a992 --- /dev/null +++ b/bitacross-worker/scripts/changelog/templates/_free_notes.md.tera @@ -0,0 +1,10 @@ + +{# This file uses the Markdown format with additional templating such as this comment. -#} +{# Such a comment will not show up in the rendered release notes. -#} +{# The content of this file (if any) will be inserted at the top of the release notes -#} +{# and generated for each new release candidate. -#} +{# Ensure you leave an empty line at both top and bottom of this file. -#} + + + + diff --git a/bitacross-worker/scripts/changelog/templates/challenge_level.md.tera b/bitacross-worker/scripts/changelog/templates/challenge_level.md.tera new file mode 100644 index 0000000000..c4a8934fd4 --- /dev/null +++ b/bitacross-worker/scripts/changelog/templates/challenge_level.md.tera @@ -0,0 +1,37 @@ +{%- import "change.md.tera" as m_c -%} + +{# This macro convert a merge challenge level into readable output #} +{%- macro challenge_level(e, changes) -%} + +{%- if e >= 5 -%} + {%- set level = "‼️ Breaking Changes" -%} + {%- set text = "This release contains **breaking changes**. Be sure to upgrade the affected interfaces." -%} +{%- elif e >= 3 -%} + {%- set level = "❗️ Attention" -%} + {%- set text = "This release contains some non-trivial updates. Be mindful when upgrading." -%} +{%- else -%} + {%- set level = "Trivial" -%} + {%- set text = "This release contains relatively small updates." -%} +{%- endif %} + + + + +{%- if level %} +{{level}}: {{text}} + +{% if e >= 3 %} +The changes motivating this challenge level are: +{% for pr in changes | sort(attribute="merged_at") -%} + {%- if pr.meta.E -%} + {%- if pr.meta.E.value == e %} +- {{ m_c::change(c=pr) }} + {%- endif -%} + {%- endif -%} +{%- endfor -%} +{%- else -%} + +{%- endif -%} +{%- endif -%} + +{%- endmacro level -%} diff --git a/bitacross-worker/scripts/changelog/templates/change.md.tera b/bitacross-worker/scripts/changelog/templates/change.md.tera new file mode 100644 index 0000000000..25cc04edec --- /dev/null +++ b/bitacross-worker/scripts/changelog/templates/change.md.tera @@ -0,0 +1,42 @@ +{# This macro shows ONE change #} +{%- macro change(c, cml="[C]", pal="[P]", wor="[W]") -%} + +{%- if c.meta.C and c.meta.C.value >= 7 -%} +{%- set prio = " ‼️ HIGH" -%} +{%- elif c.meta.C and c.meta.C.value >= 3 -%} +{%- set prio = " ❗️ Medium" -%} +{%- elif c.meta.C and c.meta.C.value < 3 -%} +{%- set prio = " Low" -%} +{%- else -%} +{%- set prio = "" -%} +{%- endif -%} + + +{%- if c.html_url is containing("worker") -%} +{%- set repo = wor -%} +{%- elif c.html_url is containing("pallets") -%} +{%- set repo = pal -%} +{%- else -%} +{%- set repo = " " -%} +{%- endif -%} + +{# For now don't show pallets or worker #} +{%- set repo = " " -%} + +{%- if c.meta.E and c.meta.E.value >= 7 -%} +{%- set challenge = " 💥 breaking changes " -%} +{%- elif c.meta.E and c.meta.E.value == 6 -%} +{%- set challenge = " ⚡ breaks parentchain interface " -%} +{%- elif c.meta.E and c.meta.E.value == 5 -%} +{%- set challenge = " 🔥 breaks public rpc api " -%} +{%- elif c.meta.E and c.meta.E.value >= 3 -%} +{%- set challenge = " 📢 attention required " -%} +{%- elif c.meta.E and c.meta.E.value < 3 -%} +{%- set challenge = " ✅ easy merge " -%} +{%- else -%} +{%- set challenge = "" -%} +{%- endif -%} + + +{{- repo }} {{ challenge }}[`#{{c.number}}`]({{c.html_url}}) {{- prio }} - {{ c.title | capitalize | truncate(length=120, end="…") }} +{%- endmacro change -%} \ No newline at end of file diff --git a/bitacross-worker/scripts/changelog/templates/changes.md.tera b/bitacross-worker/scripts/changelog/templates/changes.md.tera new file mode 100644 index 0000000000..571f2f4cab --- /dev/null +++ b/bitacross-worker/scripts/changelog/templates/changes.md.tera @@ -0,0 +1,24 @@ +{# This include generates the section showing the changes #} +## Changes + +{# for not now printed until pallet is actually included #} +{# ### Legend #} + +{# - {{ WOR }} Worker #} +{# - {{ PAL }} Pallet #} + +{% include "changes_applibs.md.tera" %} + +{% include "changes_client.md.tera" %} + +{% include "changes_core.md.tera" %} + +{% include "changes_evm.md.tera" %} + +{% include "changes_offchain.md.tera" %} + +{% include "changes_sidechain.md.tera" %} + +{% include "changes_teeracle.md.tera" %} + +{% include "changes_misc.md.tera" %} diff --git a/bitacross-worker/scripts/changelog/templates/changes_applibs.md.tera b/bitacross-worker/scripts/changelog/templates/changes_applibs.md.tera new file mode 100644 index 0000000000..db393f764e --- /dev/null +++ b/bitacross-worker/scripts/changelog/templates/changes_applibs.md.tera @@ -0,0 +1,17 @@ +{% import "change.md.tera" as m_c -%} +### App-Libs + +{#- The changes are sorted by merge date #} +{%- for pr in changes | sort(attribute="merged_at") %} + +{%- if pr.meta.B %} + {%- if pr.meta.B.value == 0 %} + {#- We skip silent ones -#} + {%- else -%} + + {%- if pr.meta.A.value == 2 %} +- {{ m_c::change(c=pr) }} + {%- endif -%} + {% endif -%} + {% endif -%} +{% endfor %} diff --git a/bitacross-worker/scripts/changelog/templates/changes_client.md.tera b/bitacross-worker/scripts/changelog/templates/changes_client.md.tera new file mode 100644 index 0000000000..5e96861812 --- /dev/null +++ b/bitacross-worker/scripts/changelog/templates/changes_client.md.tera @@ -0,0 +1,17 @@ +{% import "change.md.tera" as m_c -%} +### Client + +{#- The changes are sorted by merge date #} +{%- for pr in changes | sort(attribute="merged_at") %} + +{%- if pr.meta.B %} + {%- if pr.meta.B.value == 0 %} + {#- We skip silent ones -#} + {%- else -%} + + {%- if pr.meta.A.value == 1 %} +- {{ m_c::change(c=pr) }} + {%- endif -%} + {% endif -%} + {% endif -%} +{% endfor %} diff --git a/bitacross-worker/scripts/changelog/templates/changes_core.md.tera b/bitacross-worker/scripts/changelog/templates/changes_core.md.tera new file mode 100644 index 0000000000..f88447b9e9 --- /dev/null +++ b/bitacross-worker/scripts/changelog/templates/changes_core.md.tera @@ -0,0 +1,17 @@ +{% import "change.md.tera" as m_c -%} +### Core + +{#- The changes are sorted by merge date #} +{%- for pr in changes | sort(attribute="merged_at") %} + +{%- if pr.meta.B %} + {%- if pr.meta.B.value == 0 %} + {#- We skip silent ones -#} + {%- else -%} + + {%- if pr.meta.A.value == 0 %} +- {{ m_c::change(c=pr) }} + {%- endif -%} + {% endif -%} + {% endif -%} +{% endfor %} diff --git a/bitacross-worker/scripts/changelog/templates/changes_evm.md.tera b/bitacross-worker/scripts/changelog/templates/changes_evm.md.tera new file mode 100644 index 0000000000..92747435fd --- /dev/null +++ b/bitacross-worker/scripts/changelog/templates/changes_evm.md.tera @@ -0,0 +1,17 @@ +{% import "change.md.tera" as m_c -%} +### EVM Feature + +{#- The changes are sorted by merge date #} +{%- for pr in changes | sort(attribute="merged_at") %} + +{%- if pr.meta.B %} + {%- if pr.meta.B.value == 0 %} + {#- We skip silent ones -#} + {%- else -%} + + {%- if pr.meta.A.value == 6 %} +- {{ m_c::change(c=pr) }} + {%- endif -%} + {% endif -%} + {% endif -%} +{% endfor %} diff --git a/bitacross-worker/scripts/changelog/templates/changes_misc.md.tera b/bitacross-worker/scripts/changelog/templates/changes_misc.md.tera new file mode 100644 index 0000000000..1beb2efd91 --- /dev/null +++ b/bitacross-worker/scripts/changelog/templates/changes_misc.md.tera @@ -0,0 +1,37 @@ +{%- import "change.md.tera" as m_c -%} + +{%- set_global misc_count = 0 -%} +{#- First pass to count #} +{%- for pr in changes -%} + {%- if pr.meta.B %} + {%- if pr.meta.B.value == 0 -%} + {#- We skip silent ones -#} + {%- else -%} +{%- set_global misc_count = misc_count + 1 -%} + {% endif -%} + {% endif -%} +{% endfor -%} + +### Misc + +{% if misc_count > 10 %} +There are other misc. changes. You can expand the list below to view them all. +
Other misc. changes +{% endif -%} + +{#- The changes are sorted by merge date #} +{%- for pr in changes | sort(attribute="merged_at") %} + {%- if pr.meta.B %} + {%- if pr.meta.B.value == 0 %} + {#- We skip silent ones -#} + {%- else -%} + {%- if pr.meta.B.value >= 1 %} +- {{ m_c::change(c=pr) }} + {%- endif -%} + {% endif -%} + {% endif -%} +{% endfor %} + +{% if misc_count > 10 %} +
+{% endif -%} diff --git a/bitacross-worker/scripts/changelog/templates/changes_offchain.md.tera b/bitacross-worker/scripts/changelog/templates/changes_offchain.md.tera new file mode 100644 index 0000000000..d298752043 --- /dev/null +++ b/bitacross-worker/scripts/changelog/templates/changes_offchain.md.tera @@ -0,0 +1,17 @@ +{% import "change.md.tera" as m_c -%} +### Offchain + +{#- The changes are sorted by merge date #} +{%- for pr in changes | sort(attribute="merged_at") %} + +{%- if pr.meta.B %} + {%- if pr.meta.B.value == 0 %} + {#- We skip silent ones -#} + {%- else -%} + + {%- if pr.meta.A.value == 4 %} +- {{ m_c::change(c=pr) }} + {%- endif -%} + {% endif -%} + {% endif -%} +{% endfor %} diff --git a/bitacross-worker/scripts/changelog/templates/changes_sidechain.md.tera b/bitacross-worker/scripts/changelog/templates/changes_sidechain.md.tera new file mode 100644 index 0000000000..f953cfbcdf --- /dev/null +++ b/bitacross-worker/scripts/changelog/templates/changes_sidechain.md.tera @@ -0,0 +1,17 @@ +{% import "change.md.tera" as m_c -%} +### Sidechain + +{#- The changes are sorted by merge date #} +{%- for pr in changes | sort(attribute="merged_at") %} + +{%- if pr.meta.B %} + {%- if pr.meta.B.value == 0 %} + {#- We skip silent ones -#} + {%- else -%} + + {%- if pr.meta.A.value == 3 %} +- {{ m_c::change(c=pr) }} + {%- endif -%} + {% endif -%} + {% endif -%} +{% endfor %} diff --git a/bitacross-worker/scripts/changelog/templates/changes_teeracle.md.tera b/bitacross-worker/scripts/changelog/templates/changes_teeracle.md.tera new file mode 100644 index 0000000000..6e94e88b2c --- /dev/null +++ b/bitacross-worker/scripts/changelog/templates/changes_teeracle.md.tera @@ -0,0 +1,17 @@ +{% import "change.md.tera" as m_c -%} +### Teeracle + +{#- The changes are sorted by merge date #} +{%- for pr in changes | sort(attribute="merged_at") %} + +{%- if pr.meta.B %} + {%- if pr.meta.B.value == 0 %} + {#- We skip silent ones -#} + {%- else -%} + + {%- if pr.meta.A.value == 5 %} +- {{ m_c::change(c=pr) }} + {%- endif -%} + {% endif -%} + {% endif -%} +{% endfor %} diff --git a/bitacross-worker/scripts/changelog/templates/debug.md.tera b/bitacross-worker/scripts/changelog/templates/debug.md.tera new file mode 100644 index 0000000000..41f3702d7c --- /dev/null +++ b/bitacross-worker/scripts/changelog/templates/debug.md.tera @@ -0,0 +1,8 @@ +{%- set to_ignore = changes | filter(attribute="meta.B.value", value=0) %} + + diff --git a/bitacross-worker/scripts/changelog/templates/global_challenge_level.md.tera b/bitacross-worker/scripts/changelog/templates/global_challenge_level.md.tera new file mode 100644 index 0000000000..d2108dce4d --- /dev/null +++ b/bitacross-worker/scripts/changelog/templates/global_challenge_level.md.tera @@ -0,0 +1,26 @@ +{% import "challenge_level.md.tera" as m_p -%} +## Upgrade Challenge Level + +{%- set worker_prio = 0 -%} +{%- set pallet_prio = 0 -%} + +{# We fetch the various levels #} +{%- if worker.meta.E -%} +{%- set worker_level = worker.meta.E.max -%} +{%- else -%} +{%- set worker_level = 0 -%} +{%- endif -%} +{%- if pallet.meta.E -%} +{%- set pallet_level = pallet.meta.E.max -%} +{%- else -%} +{%- set pallet_level = 0 -%} +{%- endif -%} + +{# We compute the global level #} +{%- set global_level = worker_level -%} +{%- if pallet_level > global_level -%} +{%- set global_level = pallet_level -%} +{%- endif -%} + +{#- We show the result #} +{{ m_p::challenge_level(e=global_level, changes=changes) }} diff --git a/bitacross-worker/scripts/changelog/templates/global_priority.md.tera b/bitacross-worker/scripts/changelog/templates/global_priority.md.tera new file mode 100644 index 0000000000..87a6d52aaf --- /dev/null +++ b/bitacross-worker/scripts/changelog/templates/global_priority.md.tera @@ -0,0 +1,27 @@ +{% import "high_priority.md.tera" as m_p -%} +## Upgrade Priority + +{%- set worker_prio = 0 -%} +{%- set pallet_prio = 0 -%} + +{# We fetch the various priorities #} +{%- if worker.meta.C -%} +{%- set worker_prio = worker.meta.C.max -%} +{%- else -%} +{%- set worker_prio = 0 -%} +{%- endif -%} +{%- if pallet.meta.C -%} +{%- set pallet_prio = pallet.meta.C.max -%} +{%- else -%} +{%- set pallet_prio = 0 -%} +{%- endif -%} + +{# We compute the global priority #} +{%- set global_prio = worker_prio -%} +{%- if pallet_prio > global_prio -%} +{%- set global_prio = pallet_prio -%} +{%- endif -%} + + +{#- We show the result #} +{{ m_p::high_priority(p=global_prio, changes=changes) }} diff --git a/bitacross-worker/scripts/changelog/templates/high_priority.md.tera b/bitacross-worker/scripts/changelog/templates/high_priority.md.tera new file mode 100644 index 0000000000..117d335efd --- /dev/null +++ b/bitacross-worker/scripts/changelog/templates/high_priority.md.tera @@ -0,0 +1,38 @@ +{%- import "change.md.tera" as m_c -%} + +{# This macro convert a priority level into readable output #} +{%- macro high_priority(p, changes) -%} + +{%- if p >= 7 -%} + {%- set prio = "‼️ HIGH" -%} + {%- set text = "This is a **high priority** release and you must upgrade as as soon as possible." -%} +{%- elif p >= 3 -%} + {%- set prio = "❗️ Medium" -%} + {%- set text = "This is a medium priority release and you should upgrade in a timely manner." -%} +{%- else -%} + {%- set prio = "Low" -%} + {%- set text = "This is a low priority release and you may upgrade at your convenience." -%} +{%- endif %} + + + +{%- if prio %} +{{prio}}: {{text}} + +{% if p >= 3 %} +The changes motivating this priority level are: +{% for pr in changes | sort(attribute="merged_at") -%} + {%- if pr.meta.C -%} + {%- if pr.meta.C.value == p %} +- {{ m_c::change(c=pr) }} +{%- if pr.meta.B and pr.meta.B.value == 7 %} (RUNTIME) +{% endif %} + {%- endif -%} + {%- endif -%} +{%- endfor -%} +{%- else -%} + +{%- endif -%} +{%- endif -%} + +{%- endmacro priority -%} diff --git a/bitacross-worker/scripts/changelog/templates/pre_release.md.tera b/bitacross-worker/scripts/changelog/templates/pre_release.md.tera new file mode 100644 index 0000000000..7d4ad42dd8 --- /dev/null +++ b/bitacross-worker/scripts/changelog/templates/pre_release.md.tera @@ -0,0 +1,11 @@ +{%- if env.PRE_RELEASE == "true" -%} +
⚠️ This is a pre-release + +**Release candidates** are **pre-releases** and may not be final. +Although they are reasonably tested, there may be additional changes or issues +before an official release is tagged. Use at your own discretion, and consider +only using final releases on critical production infrastructure. +
+{% else -%} + +{%- endif %} diff --git a/bitacross-worker/scripts/changelog/templates/template.md.tera b/bitacross-worker/scripts/changelog/templates/template.md.tera new file mode 100644 index 0000000000..2c61f3d5a1 --- /dev/null +++ b/bitacross-worker/scripts/changelog/templates/template.md.tera @@ -0,0 +1,33 @@ +{# This is the entry point of the template -#} + +{% include "pre_release.md.tera" -%} + +{% if env.PRE_RELEASE == "true" -%} +This pre-release contains the changes from `{{ env.REF1 | replace(from="refs/tags/", to="") }}` to `{{ env.REF2 | +replace(from="refs/tags/", to="") }}`. +{%- else -%} +This release contains the changes from `{{ env.REF1 | replace(from="refs/tags/", to="") }}` to `{{ env.REF2 | +replace(from="refs/tags/", to="") }}`. +{% endif -%} + +{# -- For now no pallet changes included -- #} +{# {%- set changes = worker.changes | concat(with=pallet.changes) -%}##} +{%- set changes = worker.changes -%} +{%- include "debug.md.tera" -%} + +{%- set CML = "[C]" -%} +{%- set WOR = "[W]" -%} +{%- set PAL = "[P]" -%} + +{# -- Manual free notes section -- #} +{% include "_free_notes.md.tera" -%} + +{# -- Important automatic section -- #} +{% include "global_priority.md.tera" -%} + +{# -- Important automatic section -- #} +{% include "global_challenge_level.md.tera" -%} + +{# --------------------------------- #} + +{% include "changes.md.tera" -%} diff --git a/bitacross-worker/scripts/init_env.sh b/bitacross-worker/scripts/init_env.sh new file mode 100755 index 0000000000..9b68a64b22 --- /dev/null +++ b/bitacross-worker/scripts/init_env.sh @@ -0,0 +1,15 @@ +#!/bin/bash + +# script that sets the correct environment variables to execute other scripts + +export SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" +export PROJ_ROOT="$(dirname "$SCRIPT_DIR")" +export CLIENT_DIR="$PROJ_ROOT/cli" +export LOG_DIR="$PROJ_ROOT/log" +export CI_DIR="$PROJ_ROOT/ci" +export RUST_LOG=info,ws=warn,substrate_api_client=warn,ac_node_api=warn + +echo "Set environment variables:" +echo " BASH_SCRIPT_DIR: $SCRIPT_DIR" +echo " PROJ_ROOT: $PROJ_ROOT" +echo " CLIENT_DIR: $CLIENT_DIR" \ No newline at end of file diff --git a/bitacross-worker/scripts/launch.sh b/bitacross-worker/scripts/launch.sh new file mode 100755 index 0000000000..def2dd9e22 --- /dev/null +++ b/bitacross-worker/scripts/launch.sh @@ -0,0 +1,90 @@ +#!/usr/bin/env bash + +set -euo pipefail + +PARACHAIN="rococo" +ROOTDIR=$(git rev-parse --show-toplevel) +ROOTDIR="${ROOTDIR}/tee-worker" + +function usage() { + echo "Usage: $0 " + echo "" + echo " All mode apply to ${PARACHAIN} context." + echo " dev: start worker(s) together with local ${PARACHAIN} for development" + echo " staging: start worker(s) sync with staging ${PARACHAIN} on tee-staging server" + echo " prod: start worker(s) sync with production ${PARACHAIN} on polkadot.js" + echo " mock: start worker(s) together with local ${PARACHAIN} for development" +} + +function start_local_parachain() { + cd ${ROOTDIR} + echo "------------------------------------------------------------" + echo "Start local parachain: ${PARACHAIN} ..." + # TODO: only `rococo` is supported for the moment. And it's hard-coded inside `start_parachain.sh` + ./scripts/litentry/start_parachain.sh + if [ $? -ne 0 ]; then + exit 1 + fi +} + +function start_worker_for_dev() { + start_local_parachain + cd ${ROOTDIR} + worker_num=2 + echo "------------------------------------------------------------" + echo "Start ${worker_num} workers with dev ${PARACHAIN} ..." + ./scripts/launch_local_worker.sh -c true -n ${worker_num} -m "dev" +} + +function start_worker_for_staging() { + cd ${ROOTDIR} + worker_num=2 + # staging_parachain_url + url="wss://tee-staging.litentry.io" + # staging_parachain_port + port=443 + echo "------------------------------------------------------------" + echo "Start ${worker_num} workers with staging ${PARACHAIN} ..." + ./scripts/launch_local_worker.sh -c true -n ${worker_num} -u ${url} -p ${port} -m "staging" +} + +function start_worker_for_prod() { + cd ${ROOTDIR} + worker_num=2 + # production_parachain_url + url="wss://rpc.${PARACHAIN}-parachain-sg.litentry.io" + # production_parachain_port + port=443 + echo "------------------------------------------------------------" + echo "Start ${worker_num} workers with production ${PARACHAIN} ..." + ./scripts/launch_local_worker.sh -c true -n ${worker_num} -u ${url} -p ${port} -m "prod" +} + +function start_worker_for_mock() { + start_local_parachain + cd ${ROOTDIR} + worker_num=2 + echo "------------------------------------------------------------" + echo "Start ${worker_num} workers with local ${PARACHAIN} ..." + ./scripts/launch_local_worker.sh -c true -n ${worker_num} -m "mock" +} + + +[ $# -ne 1 ] && (usage; exit 1) +MODE=$1 + +if [ "$MODE" = "dev" ] || [ "$MODE" = "staging" ] || [ "$MODE" = "prod" ] || [ "$MODE" = "mock" ]; then + echo "Launch in $MODE mode" + start_worker_for_$MODE +else + echo "Unknow mode: $MODE" + usage; exit 1 +fi + +echo "Done" + + + + + + diff --git a/bitacross-worker/scripts/launch_local_worker.sh b/bitacross-worker/scripts/launch_local_worker.sh new file mode 100755 index 0000000000..ccacaaa262 --- /dev/null +++ b/bitacross-worker/scripts/launch_local_worker.sh @@ -0,0 +1,138 @@ +#!/usr/bin/env bash + +# TODO: Sanity check of parameters +while getopts ":c:n:u:p:m:" opt; do + case $opt in + c) + cleanup_flag=$OPTARG + ;; + n) + worker_num=$OPTARG + ;; + u) + node_url=$OPTARG + ;; + p) + node_port=$OPTARG + ;; + m) + mode=$OPTARG + ;; + esac +done + +CLEANUP=${cleanup_flag:-true} +WORKER_NUM=${worker_num:-1} + +NODE_URL=${node_url:-"ws://127.0.0.1"} # "ws://host.docker.internal" +NODE_PORT=${node_port:-"9944"} # "9946" + +# Fixed values: +WORKER_ENDPOINT="localhost" +MU_RA_PORT="3443" +UNTRUSTED_HTTP_PORT="4545" +TRUSTED_WORKER_PORT="2000" +UNTRUSTED_WORKER_PORT="3000" + +F_CLEAN="" +FSUBCMD_DEV="" +FSUBCMD_REQ_STATE="" + +WAIT_INTERVAL_SECONDS=10 +WAIT_ROUNDS=20 + +if [ "${CLEANUP}" = 'true' ]; then + F_CLEAN="--clean-reset" + FSUBCMD_DEV="--dev" +fi + +function wait_worker_is_initialized() +{ + for index in $(seq 1 $WAIT_ROUNDS); do + state=$(curl -s http://localhost:$1/is_initialized) + if [ "$state" == "I am initialized." ]; then + echo "Initialization successful: $state" + return + else + echo "sleep $WAIT_INTERVAL_SECONDS" + sleep $WAIT_INTERVAL_SECONDS + fi + done + echo + echo "Worker initialization failed" + exit 1 +} + +echo "Number of WORKER_NUM: ${WORKER_NUM}" +############################################################################## +### Start execution +############################################################################## + +ROOTDIR=$(git rev-parse --show-toplevel) +ROOTDIR="${ROOTDIR}/tee-worker" +RUST_LOG="info,litentry_worker=debug,ws=warn,sp_io=error,substrate_api_client=warn,\ +itc_parentchain_light_client=info,\ +jsonrpsee_ws_client=warn,jsonrpsee_ws_server=warn,enclave_runtime=debug,ita_stf=debug,\ +its_rpc_handler=warn,itc_rpc_client=warn,its_consensus_common=debug,its_state=warn,\ +its_consensus_aura=warn,aura*=warn,its_consensus_slots=warn,\ +itp_attestation_handler=debug,http_req=debug,itc_rest_client=debug,\ +itp_top_pool=debug,itc_parentchain_indirect_calls_executor=debug" + +# Create the log directory, in case not existed. +mkdir -p ${ROOTDIR}/log + +for ((i = 0; i < ${WORKER_NUM}; i++)); do + worker_name="worker${i}" + echo "" + echo "--------------------setup worker(${worker_name})----------------------------------------" + + if ((i > 0)); then + FSUBCMD_REQ_STATE="--request-state" + fi + + if [ "${CLEANUP}" = 'true' ]; then + echo "clear dir: ${ROOTDIR}/tmp/${worker_name}" + rm -rf "${ROOTDIR}"/tmp/"${worker_name}" + fi + mkdir -p "${ROOTDIR}"/tmp/"${worker_name}" + for Item in 'enclave.signed.so' 'key.txt' 'spid.txt' 'litentry-worker' 'bitacross-cli'; do + cp "${ROOTDIR}/bin/${Item}" "${ROOTDIR}"/tmp/"${worker_name}" + done + + cd "${ROOTDIR}"/tmp/${worker_name} || exit + echo "enter ${ROOTDIR}/tmp/${worker_name}" + + mu_ra_port=$((${MU_RA_PORT} + i)) + untrusted_http_port=$((${UNTRUSTED_HTTP_PORT} + i)) + trusted_worker_port=$((${TRUSTED_WORKER_PORT} + i)) + untrusted_worker_port=$((${UNTRUSTED_WORKER_PORT} + i)) + echo "${worker_name} ports: + mu-ra-port: ${mu_ra_port} + untrusted-http-port: ${untrusted_http_port} + trusted-worker-port: ${trusted_worker_port} + untrusted-worker-port: ${untrusted_worker_port} + " + + launch_command="RUST_LOG=${RUST_LOG} ./litentry-worker ${F_CLEAN} --ws-external \ +--mu-ra-external-address ${WORKER_ENDPOINT} \ +--mu-ra-port ${mu_ra_port} \ +--node-port ${NODE_PORT} \ +--node-url ${NODE_URL} \ +--trusted-external-address wss://${WORKER_ENDPOINT} \ +--trusted-worker-port ${trusted_worker_port} \ +--untrusted-external-address ws://${WORKER_ENDPOINT} \ +--untrusted-http-port ${untrusted_http_port} \ +--untrusted-worker-port ${untrusted_worker_port} \ +run --skip-ra ${FSUBCMD_DEV} ${FSUBCMD_REQ_STATE}" + + echo "${worker_name} command: ${launch_command}" + eval "${launch_command}" > "${ROOTDIR}"/log/${worker_name}.log 2>&1 & + echo "${worker_name}(litentry-worker) started successfully. log: ${ROOTDIR}/log/${worker_name}.log" + + if ((${WORKER_NUM} > 0)); then + wait_worker_is_initialized ${untrusted_http_port} + fi +done + +echo "" +echo "--- Setup work(s) done ---" diff --git a/bitacross-worker/scripts/litentry/cleanup.sh b/bitacross-worker/scripts/litentry/cleanup.sh new file mode 100755 index 0000000000..c1271e4eb9 --- /dev/null +++ b/bitacross-worker/scripts/litentry/cleanup.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +set -eo pipefail + +pid=$(ps aux | grep '[l]ocal-setup/launch' | awk '{print $2}') + +if [ ! -z "$pid" ]; then + echo "killing $pid" + kill -9 "$pid" +fi + +killall litentry-worker 2>/dev/null || true diff --git a/bitacross-worker/scripts/litentry/generate_parachain_artefacts.sh b/bitacross-worker/scripts/litentry/generate_parachain_artefacts.sh new file mode 100755 index 0000000000..e24bc4f940 --- /dev/null +++ b/bitacross-worker/scripts/litentry/generate_parachain_artefacts.sh @@ -0,0 +1,13 @@ +#!/bin/bash +set -euo pipefail + +ROOTDIR=$(git rev-parse --show-toplevel) +DESTDIR="$ROOTDIR/tee-worker/docker/litentry" + +# generate files +cd "$ROOTDIR" +make generate-docker-compose-rococo + +# copy files over to `DESTDIR` +mkdir -p "$DESTDIR" +cp docker/generated-rococo/* "$DESTDIR/" \ No newline at end of file diff --git a/bitacross-worker/scripts/litentry/identity_test.sh b/bitacross-worker/scripts/litentry/identity_test.sh new file mode 100755 index 0000000000..a9159714c8 --- /dev/null +++ b/bitacross-worker/scripts/litentry/identity_test.sh @@ -0,0 +1,36 @@ +#!/usr/bin/env bash + +set -eo pipefail + +root_dir=$(git rev-parse --show-toplevel) +root_dir="$root_dir/tee-worker" + +#NODE PORT +node_port=9912 +node_url=ws://litentry-node + +worker_url=wss://tee-builder +worker_port=2000 + +CLIENT="./bitacross-cli --node-url ${node_url} --node-port ${node_port} --worker-url ${worker_url} --trusted-worker-port ${worker_port}" + +cd "$root_dir/bin" +./litentry-worker mrenclave | tee ~/mrenclave.b58 +MRENCLAVE=$(cat ~/mrenclave.b58) + +cd "$root_dir/tmp/worker1" + +# node-js: tweet_id: Buffer.from("1571829863862116352").toJSON().data.toString() +validation_data='{"Web2":{"Twitter":{"tweet_id":[49,53,55,49,56,50,57,56,54,51,56,54,50,49,49,54,51,53,50]}}}' + +# node-js: twitter_username: Buffer.from("litentry").toJSON().data.toString() +identity='{"web_type":{"Web2":"Twitter"},"handle":{"String":[108,105,116,101,110,116,114,121]}}' + +echo "create_identity" +RUST_LOG=warn ${CLIENT} trusted --mrenclave ${MRENCLAVE} create-identity "//Alice" "$identity" + +echo "set-challenge-code" +${CLIENT} trusted --mrenclave ${MRENCLAVE} set-challenge-code "//Alice" "$identity" 1134 + +echo "verify-identity-preflight" +RUST_LOG=info ${CLIENT} trusted --mrenclave ${MRENCLAVE} verify-identity-preflight "//Alice" "$identity" "$validation_data" diff --git a/bitacross-worker/scripts/litentry/release/ReadMe.md b/bitacross-worker/scripts/litentry/release/ReadMe.md new file mode 100644 index 0000000000..3faea84187 --- /dev/null +++ b/bitacross-worker/scripts/litentry/release/ReadMe.md @@ -0,0 +1,106 @@ + +# Release package + + +## Step 0: Preparation + +This package is generated from [litentry-parachain](https://github.com/litentry/litentry-parachain) +From the root folder ~/litentry-parachain/tee-worker/: +``` +make release-pkg +``` +A release package will be generated, within which there are: + +- enclave.sign.so +- litentry-worker +- config.json.eg +- prepare.sh + +
+ +## Step 1: Deploy on production + +Before starting the workers, please make sure the target parachain is already up and accessable. As well as the following directory/files: + +| Name | Value | Comment | +|-----|------|---| +| WORKER_DIR | /opt/worker | Working directory of workers | +| CONFIG_DIR | /opt/configs | Config directory which contains the following 4 secret files | +| +| CONFIG | config.json | Configs for twitter/discord/data provider/etc. url/keys. Take reference from config.json.eg | +| ACCOUNT | account.json | Substrate account exported json file | +| INTEL_KEY | key_production.txt | Intel SGX production key. Need to apply from Intel | +| INTEL_SPI | spid_production.txt | Intel SGX production spid. Need to apply from Intel | + +
+ +1. Extract the release package to one target location. Worker will be executed from there. Then execute `prepare.sh`: + ``` + ./prepare.sh + ``` + This script will generate out `MRENCLAVE` hex value (mrenclave.txt) and `Enclave Account` info (account.txt). They will be used later by ts scripts to setup enclave account. +
+ +2. Startup options. + + The service will start up like this example: + ``` + RUST_LOG=info,litentry_worker=debug,ws=warn,sp_io=error,substrate_api_client=warn,itc_parentchain_light_client=info,jsonrpsee_ws_client=warn,jsonrpsee_ws_server=warn,enclave_runtime=debug,ita_stf=debug,its_rpc_handler=warn,itc_rpc_client=warn,its_consensus_common=debug,its_state=warn,its_consensus_aura=warn,aura*=warn,its_consensus_slots=warn,itp_attestation_handler=debug,http_req=debug,lc_mock_server=warn,itc_rest_client=debug,lc_credentials=debug,lc_identity_verification=debug,lc_stf_task_receiver=debug,lc_stf_task_sender=debug,lc_data_providers=debug,itp_top_pool=debug,itc_parentchain_indirect_calls_executor=debug ./litentry-worker --clean-reset --ws-external --mu-ra-external-address localhost --mu-ra-port 3443 --node-port 9944 --node-url ws://127.0.0.1 --trusted-external-address wss://localhost --trusted-worker-port 2000 --untrusted-external-address ws://localhost --untrusted-http-port 4545 --untrusted-worker-port 3000 run --skip-ra --dev + ``` + The first part is RUST_LOG info. In production env, most of them will be disabled. Or `RUST_LOG=info` is enough. + + Starting from `./litentry-worker`, the following is the real startup options: + + ``` + USAGE: + litentry-worker [FLAGS] [OPTIONS] + + FLAGS: + -c, --clean-reset Cleans and purges any previous state and key files and generates them anew before starting. + --enable-metrics Enable the metrics HTTP server to serve metrics + --help Prints help information + -V, --version Prints version information + --ws-external Set this flag in case the worker should listen to external requests. + + OPTIONS: + -i, --metrics-port + Set the port on which the metrics are served. [default: 8787] + + -M, --mu-ra-external-address + Set the mutual remote attestation worker address to be retrieved by a trusted rpc call. If no port is given, the same as in `mu-ra-port` will be used. + -r, --mu-ra-port + Set the websocket port to listen for mu-ra requests [default: 3443] + + -p, --node-port + Set the websocket port to listen for substrate events [default: 9944] + + -u, --node-url + Set the node server protocol and IP address [default: ws://127.0.0.1] + + -T, --trusted-external-address + Set the trusted worker address to be advertised on the parentchain. If no port is given, the same as in + `trusted-worker-port` will be used. + -P, --trusted-worker-port + Set the trusted websocket port of the worker, running directly in the enclave. [default: 2000] + + -U, --untrusted-external-address + Set the untrusted worker address to be retrieved by a trusted rpc call. If no port is given, the same as in + `untrusted-worker-port` will be used. + -h, --untrusted-http-port Set the port for the untrusted HTTP server + -w, --untrusted-worker-port + Set the untrusted websocket port of the worker [default: 2001] + + SUBCOMMANDS: + dump-ra Perform RA and dump cert to disk + help Prints this message or the help of the given subcommand(s) + init-shard Initialize new shard (do this only if you run the first worker for that shard). if shard is not + specified, the MRENCLAVE is used instead + migrate-shard Migrate shard + mrenclave Dump mrenclave to stdout. base58 encoded. + request-state join a shard by requesting key provisioning from another worker + run Start the litentry-worker + shielding-key Get the public RSA3072 key from the TEE to be used to encrypt requests + signing-key Get the public ed25519 key the TEE uses to sign messages and extrinsics + test Run tests involving the enclave + ``` + diff --git a/bitacross-worker/scripts/litentry/release/build.sh b/bitacross-worker/scripts/litentry/release/build.sh new file mode 100755 index 0000000000..aafd70210d --- /dev/null +++ b/bitacross-worker/scripts/litentry/release/build.sh @@ -0,0 +1,50 @@ +#!/bin/bash + +# this script builds the release artefacts for TEE client and/or the enclave + +set -euo pipefail + +function usage() { + echo "Usage: $0 if-build-worker if-build-enclave" + echo "Example:" + echo " $0 true true" +} + +[ $# -ne 2 ] && (usage; exit 1) + +echo "build worker: $1" +echo "build enclave: $2" + +ROOTDIR=$(git rev-parse --show-toplevel) +WORKERDIR="$ROOTDIR/tee-worker" + +# hardcoded sgx signing key, adjust it accordingly if you call the script manually +SGX_COMMERCIAL_KEY="/opt/enclave_release/sgx_sign_key.pem" + +if [ ! -f "$SGX_COMMERCIAL_KEY" ]; then + echo "Cannot find SGX sign key under $SGX_COMMERCIAL_KEY" + exit 1 +fi + +DESTDIR="$WORKERDIR/enclave_release" +[ -d "$DESTDIR" ] && rm -rf "$DESTDIR" +mkdir -p "$DESTDIR" + +cd "$WORKERDIR" + +make clean + +export SGX_PRODUCTION=1 +export SGX_COMMERCIAL_KEY="$SGX_COMMERCIAL_KEY" +if [ "$1" = "true" ]; then + make service + cp bin/litentry-worker "$DESTDIR" +fi +if [ "$2" = "true" ]; then + make bin/enclave.signed.so + cp bin/enclave.signed.so "$DESTDIR" + make mrenclave 2>&1 | grep MRENCLAVE | awk '{print $2}' > "$DESTDIR/mrenclave.txt" +fi + +echo "Build tee done" +ls -l "$DESTDIR" diff --git a/bitacross-worker/scripts/litentry/release/config.json.eg b/bitacross-worker/scripts/litentry/release/config.json.eg new file mode 100644 index 0000000000..acfdbc872a --- /dev/null +++ b/bitacross-worker/scripts/litentry/release/config.json.eg @@ -0,0 +1,11 @@ +{ + "twitter_official_url": "https://api.twitter.com", + "twitter_litentry_url": "", + "twitter_auth_token_v2": "abcdefghijklmnopqrstuvwxyz", + "discord_official_url": "https://discordapp.com", + "discord_litentry_url": "", + "discord_auth_token": "ABCDEFGHIJKLMNOPQRSTUVWXYZ", + "achainable_url": "https://graph.tdf-labs.io/", + "achainable_auth_key": "88888888-4444-4444-4444-1234567890ab", + "credential_endpoint": "" +} \ No newline at end of file diff --git a/bitacross-worker/scripts/litentry/release/deploy.sh b/bitacross-worker/scripts/litentry/release/deploy.sh new file mode 100755 index 0000000000..72c7060dfa --- /dev/null +++ b/bitacross-worker/scripts/litentry/release/deploy.sh @@ -0,0 +1,555 @@ +#!/bin/bash + +set -eo pipefail + +# This script is used to perform actions on the target host, including: +# - generate: generate the systemd service files from the template +# - restart: restart the parachain, or the worker, or both +# - upgrade-worker: uprade the worker0 to the rev in local repo +# +# TODO: +# the combinations of flags are not yet well verified/organised, especially the following: +# --only-worker +# --build +# --discard + +# ------------------------------ +# path setting +# ------------------------------ + +ROOTDIR=$(git rev-parse --show-toplevel) +BASEDIR=/opt/litentry +PARACHAIN_BASEDIR="$BASEDIR/parachain" +WORKER_BASEDIR="$BASEDIR/worker" +BACKUP_BASEDIR="$BASEDIR/backup" +LOG_BACKUP_BASEDIR="$BACKUP_BASEDIR/log" +WORKER_BACKUP_BASEDIR="$BACKUP_BASEDIR/worker" +RELAYCHAIN_ALICE_BASEDIR="$PARACHAIN_BASEDIR/relay-alice" +RELAYCHAIN_BOB_BASEDIR="$PARACHAIN_BASEDIR/relay-bob" +PARACHAIN_ALICE_BASEDIR="$PARACHAIN_BASEDIR/para-alice" + +# ------------------------------ +# default arg setting +# ------------------------------ + +BUILD=false +DISCARD=false +WORKER_CONFIG= +CHAIN=rococo +ONLY_WORKER=false +PARACHAIN_HOST=localhost +PARACHAIN_PORT=9944 +DOCKER_IMAGE=litentry/litentry-parachain:tee-prod +COPY_FROM_DOCKER=false +PRODUCTION=false +ACTION= + +# ------------------------------ +# Some global setting +# ------------------------------ + +WORKER_COUNT= +PARACHAIN_ID= +OLD_MRENCLAVE= +NEW_MRENCLAVE= +OLD_SHARD= +LATEST_FINALIZED_BLOCK= + +SGX_SDK=/opt/intel/sgxsdk +SGX_ENCLAVE_SIGNER=$SGX_SDK/bin/x64/sgx_sign + +# ------------------------------ +# main() +# ------------------------------ + +function main { + # 0/ check if $USER has sudo + if sudo -l -U $USER 2>/dev/null | grep -q 'may run the following'; then + source "$SGX_SDK/environment" + else + echo "$USER doesn't have sudo permission" + exit 1 + fi + + # 1/ create folders if missing + sudo mkdir -p "$BASEDIR" + sudo chown $USER:$GROUPS "$BASEDIR" + for d in "$LOG_BACKUP_BASEDIR" "$WORKER_BACKUP_BASEDIR" "$RELAYCHAIN_ALICE_BASEDIR" "$RELAYCHAIN_BOB_BASEDIR" \ + "$PARACHAIN_ALICE_BASEDIR" "$WORKER_BASEDIR"; do + mkdir -p "$d" + done + + # 2/ parse command lines + echo "Parsing command line ..." + while [ $# -gt 0 ]; do + case "$1" in + -h|--help) + display_help + exit 0 + ;; + -b|--build) + BUILD=true + shift + ;; + -d|--discard) + DISCARD=true + shift + ;; + -c|--config) + WORKER_CONFIG="$(realpath -s $2)" + shift 2 + ;; + -a|--only-worker) + ONLY_WORKER=true + shift + ;; + -x|--chain) + CHAIN="$2" + shift 2 + ;; + -p|--parachain-port) + PARACHAIN_PORT="$2" + shift 2 + ;; + -z|--parachain-host) + PARACHAIN_HOST="$2" + shift 2 + ;; + -v|--copy-from-docker) + COPY_FROM_DOCKER=true + DOCKER_IMAGE="$2" + shift 2 + ;; + --prod) + PRODUCTION=true + shift + ;; + generate|restart|upgrade-worker) + ACTION="$1" + shift + ;; + *) + echo "Error: unknown option or subcommand $1" + display_help + exit 1 + ;; + esac + done + + # 3/ sanity checks + if [ ! -f "$WORKER_CONFIG" ]; then + echo "Worker config not found: $WORKER_CONFIG" + exit 1 + fi + + WORKER_COUNT=$(cat "$WORKER_CONFIG" | jq '.workers | length') + echo "Worker count: $WORKER_COUNT" + + # TODO: check flags conflict, e.g. + # - having `--discard` together with `upgrade-worker` doesn't make sense + # - `upgrade-worker` should ignore the `--only-worker` flag + + # 4/ main business logic + case "$ACTION" in + generate) + backup_services + generate_services + exit + ;; + restart) + backup_logs + backup_workers + stop_services + prune + build + setup_working_dir + if [ "$ONLY_WORKER" = true ]; then + remove_clean_reset + fi + restart_services + exit + ;; + upgrade-worker) + # build the new worker, the code must be under $ROOTDIR/tee-worker already + build_worker + # update the schedule + set_scheduled_enclave + + # wait until sidechain stalls + wait_for_sidechain + backup_workers + stop_worker_services + get_old_mrenclave + # TODO: actually we only need the copy-up + setup_working_dir + migrate_shard + remove_clean_reset + restart_services + exit + ;; + *) + echo "Unknown action: $ACTION" + exit 1 ;; + esac +} + +# ------------------------------ +# helper functions +# ------------------------------ + +function print_divider { + echo "------------------------------------------------------------" +} + +function display_help { + echo "usage: ./deploy.sh [options]" + echo "" + echo "subcommands:" + echo " generate Generate the parachain and worker systemd files" + echo " restart Restart the services" + echo " upgrade-worker Upgrade the worker" + echo "" + echo "options:" + echo " -h, --help Display this help message and exit" + echo " -b, --build Build the parachain and worker binaries (default: false)" + echo " -d, --discard Clean the existing state for parachain and worker (default: false)" + echo " -c, --config Config file for the worker" + echo " -a, --only-worker Start only the worker (default: false)" + echo " -x, --chain Chain type for launching the parachain network (default: rococo)" + echo " -h, --parachain-host Parachain ws URL (default: localhost)" + echo " -p, --parachain-port Parachain ws port (default: 9944)" + echo " -v, --copy-from-docker Copy the parachain binary from a docker image (default: litentry/litentry-parachain:tee-prod)" + echo " --prod Use a prod configuration to build and run the worker (default: false)" + echo "" + echo "examples:" + echo " ./deploy.sh generate --config tmp.json" + echo " ./deploy.sh restart --config tmp.json --discard --build" + echo " ./deploy.sh restart --config tmp.json --only-worker" + echo " ./deploy.sh upgrade-worker --config tmp.json --only-worker" + echo "" + echo "notes:" + echo " - This script requires an OS that supports systemd." + echo " - It is mandatory to provide a JSON config file for the worker." + echo " - jq is required to be installed on the system " + echo "" + echo "For more information or assistance, please contact Litentry parachain team." +} + +# TODO: in fact, this function only backs up the parachain logs +# maybe we want to remove it as it's not so critical anyway +function backup_logs { + echo "Backing up logs ..." + now=$(date +"%Y%m%d-%H%M%S") + outdir="$LOG_BACKUP_BASEDIR/log-$now" + mkdir -p "$outdir" + cp "$PARACHAIN_BASEDIR"/*.log "$outdir" || true + echo "Logs backed up into $outdir" +} + +function backup_workers { + echo "Backing up workers ..." + now=$(date +"%Y%m%d-%H%M%S") + cd "$WORKER_BASEDIR" || exit + for i in $(ls -d * 2>/dev/null); do + outdir="$WORKER_BACKUP_BASEDIR/$i-$now" + cp -rf "$i" "$outdir" + echo "Worker backed up into $outdir" + done +} + +function backup_services { + echo "Backing up services ..." + now=$(date +"%Y%m%d-%H%M%S") + cd /etc/systemd/system || exit + outdir="$WORKER_BACKUP_BASEDIR/service-$now" + mkdir -p "$outdir" + for f in para-alice.service relay-alice.service relay-bob.service $(ls worker*.service 2>/dev/null); do + cp "$f" "$outdir" || true + done +} + +function prune { + if [ "$DISCARD" = true ]; then + echo "Pruning the existing state ..." + rm -rf "$PARACHAIN_BASEDIR"/* + rm -rf "$WORKER_BASEDIR"/* + fi +} + +function generate_services { + echo "Generating systemd service files ..." + cd "$ROOTDIR/tee-worker/scripts/litentry/release" + cp template/* . + sed -i "s/CHAIN/$CHAIN/g" *.service + sed -i "s/USER/$USER/g" *.service + for ((i = 0; i < WORKER_COUNT; i++)); do + cp worker.service worker$i.service + sed -i "s/NUMBER/$i/g" worker$i.service + # populate args + flags=$(cat "$WORKER_CONFIG" | jq -r ".workers[$i].flags[]") + subcommand_flags=$(cat "$WORKER_CONFIG" | jq -r ".workers[$i].subcommand_flags[]") + args= + for flag in $flags; do + args+=" $flag" + done + args+=" run" + for subcommand_flag in $subcommand_flags; do + args+=" $subcommand_flag" + done + sed -i "s;ARGS;$args;" worker$i.service + done + rm worker.service + sudo cp *.service -f /etc/systemd/system/ + rm *.service + sudo systemctl daemon-reload + echo "Done, please check files under /etc/systemd/system/" + echo "Restart the services to take effect" +} + +function build_worker { + echo "Building worker ..." + cd $ROOTDIR/tee-worker/ || exit + if [ "$PRODUCTION" = true ]; then + # we will get an error if SGX_COMMERCIAL_KEY is not set for prod + SGX_PRODUCTION=1 make + else + # use SW mode for dev + SGX_MODE=SW make + fi +} + +# TODO: take github rev into consideration +function build { + if [ "$BUILD" = true ]; then + echo "Building the parachain and worker binaries ..." + + # download polkadot + echo "Downloading polkadot binary ..." + url="https://github.com/paritytech/polkadot/releases/download/v0.9.42/polkadot" + polkadot_bin="$PARACHAIN_BASEDIR/polkadot" + wget -O "$polkadot_bin" -q "$url" + chmod a+x "$polkadot_bin" + if [ ! -s "$polkadot_bin" ]; then + echo "$polkadot_bin is 0 bytes, download URL: $url" && exit 1 + fi + if ! "$polkadot_bin" --version &> /dev/null; then + echo "Cannot execute $polkadot_bin, wrong executable?" && exit 1 + fi + + # pull or build parachain + if [ "$COPY_FROM_DOCKER" = true ]; then + echo "Pulling binary from $DOCKER_IMAGE ..." + docker pull "$DOCKER_IMAGE" + docker cp "$(docker create --rm $DOCKER_IMAGE):/usr/local/bin/litentry-collator" "$PARACHAIN_BASEDIR" + else + echo "Building parachain binary ..." + cd "$ROOTDIR" || exit + if [ "$PRODUCTION" = true ]; then + cargo build --locked --profile production + else + pwd + make build-node + fi + cp "$ROOTDIR/target/release/litentry-collator" "$PARACHAIN_BASEDIR" + fi + chmod a+x "$PARACHAIN_BASEDIR/litentry-collator" + fi +} + +function restart_services { + sudo systemctl daemon-reload + if [ "$ONLY_WORKER" = false ]; then + echo "Restarting parachain services ..." + + cd "$PARACHAIN_BASEDIR" || exit + ./polkadot build-spec --chain rococo-local --disable-default-bootnode --raw > rococo-local-chain-spec.json + ./litentry-collator export-genesis-state --chain $CHAIN-dev > genesis-state + ./litentry-collator export-genesis-wasm --chain $CHAIN-dev > genesis-wasm + + sudo systemctl restart relay-alice.service + sleep 5 + sudo systemctl restart relay-bob.service + sleep 5 + sudo systemctl restart para-alice.service + sleep 5 + register_parachain + fi + + echo "Restarting worker services ..." + for ((i = 0; i < WORKER_COUNT; i++)); do + sudo systemctl restart "worker$i.service" + sleep 5 + done + echo "Done" +} + +function stop_worker_services { + echo "Stopping worker services ..." + for ((i = 0; i < WORKER_COUNT; i++)); do + sudo systemctl stop "worker$i.service" + sleep 5 + done +} + +function stop_parachain_services { + echo "Stopping parachain services ..." + sudo systemctl stop para-alice.service relay-alice.service relay-bob.service +} + +function stop_services { + stop_worker_services + + # TODO: it means we can't stop parachain service alone + # this needs to be done directly via `systemctl` + if [ "$ONLY_WORKER" = false ]; then + stop_parachain_services + fi +} + +function register_parachain { + echo "Register parathread now ..." + cd "$ROOTDIR" || exit + export PARACHAIN_ID=$(grep DEFAULT_PARA_ID node/src/chain_specs/$CHAIN.rs | grep u32 | sed 's/.* = //;s/\;//') + cd "$ROOTDIR/ts-tests" || exit + if [[ -z "$NODE_ENV" ]]; then + echo "NODE_ENV=ci" > .env + else + echo "NODE_ENV=$NODE_ENV" > .env + fi + # The genesis state path file needs to be updated as it is hardcoded to be /tmp/parachain_dev + jq --arg genesis_state "$PARACHAIN_BASEDIR/genesis-state" --arg genesis_wasm "$PARACHAIN_BASEDIR/genesis-wasm" '.genesis_state_path = $genesis_state | .genesis_wasm_path = $genesis_wasm' config.ci.json > config.ci.json.1 + mv config.ci.json.1 config.ci.json + pnpm install + pnpm run register-parathread 2>&1 | tee "$PARACHAIN_BASEDIR/register-parathread.log" + print_divider + + echo "Upgrade parathread to parachain now ..." + # Wait for 90s to allow onboarding finish, after that we do the upgrade + sleep 90 + pnpm run upgrade-parathread 2>&1 | tee "$PARACHAIN_BASEDIR/upgrade-parathread.log" + print_divider + + echo "done. please check $PARACHAIN_BASEDIR for generated files if need" + print_divider + git restore config.ci.json +} + +function setup_working_dir { + echo "Setting up working dir ..." + cd "$ROOTDIR/tee-worker/bin" || exit + + if [ "$PRODUCTION" = false ]; then + for f in 'key.txt' 'spid.txt'; do + [ -f "$f" ] || touch "$f" + done + fi + + for ((i = 0; i < WORKER_COUNT; i++)); do + worker_dir="$WORKER_BASEDIR/w$i" + mkdir -p "$worker_dir" + for f in 'key.txt' 'spid.txt' 'enclave.signed.so' 'litentry-worker'; do + [ -f "$f" ] && cp -f "$f" "$worker_dir" + done + + cd "$worker_dir" + [ -f light_client_db.bin/db.bin.backup ] && cp -f light_client_db.bin/db.bin.backup light_client_db.bin/db.bin + + enclave_account=$(./litentry-worker signing-key | grep -oP '^Enclave account: \K.*$$') + + if [ "$PRODUCTION" = true ]; then + echo "Transferring balance to the enclave account $enclave_account ..." + cd $ROOTDIR/scripts/ts-utils/ || exit + pnpm install + pnpm exec ts-node transfer.ts $enclave_account + fi + done +} + +function get_old_mrenclave { + cd "$WORKER_BASEDIR/w0" || exit + OLD_SHARD=$(./litentry-worker mrenclave) + $SGX_ENCLAVE_SIGNER dump -enclave ./enclave.signed.so -dumpfile df.out + OLD_MRENCLAVE=$($ROOTDIR/tee-worker/extract_identity < df.out | awk '{print $2}') + rm df.out + echo "old shard: $OLD_SHARD" + echo "old mrenclave: $OLD_MRENCLAVE" +} + +function set_scheduled_enclave { + echo "Setting scheduled enclave ..." + cd $ROOTDIR/tee-worker || exit + NEW_MRENCLAVE=$(make mrenclave 2>&1 | grep MRENCLAVE | awk '{print $2}') + echo "new mrenclave: $NEW_MRENCLAVE" + + latest_sidechain_block + + echo "Setting up the new worker on chain ..." + cd $ROOTDIR/ts-tests/ || exit + pnpm install + pnpm run setup-enclave $NEW_MRENCLAVE $SCHEDULED_UPDATE_BLOCK +} + +function wait_for_sidechain { + echo "Waiting for sidechain to reach block $SCHEDULED_UPDATE_BLOCK ..." + found=false + for _ in $(seq 1 30); do + sleep 20 + block_number=$(grep -F 'Enclave produced sidechain blocks' $WORKER_BASEDIR/w0/worker.log | tail -n 1 | sed 's/.*\[//;s/]//') + echo "current sidechain block: $block_number" + if [ $((block_number+1)) -eq $SCHEDULED_UPDATE_BLOCK ]; then + echo "we should stall soon ..." + fi + if tail -n 50 $WORKER_BASEDIR/w0/worker.log | grep -q "Skipping sidechain block $SCHEDULED_UPDATE_BLOCK due to mismatch MRENCLAVE"; then + echo "we reach $SCHEDULED_UPDATE_BLOCK now" + found=true + break + fi + done + if [ $found = false ]; then + echo "not reached, timeout" + exit 1 + fi +} + +function migrate_shard { + echo "Migrating shards for workers ..." + for ((i = 0; i < WORKER_COUNT; i++)); do + cd "$WORKER_BASEDIR/w$i" || exit + echo "old MRENCLAVE: $OLD_MRENCLAVE" + echo "new MRENCLAVE: $NEW_MRENCLAVE" + ./litentry-worker migrate-shard --old-shard $OLD_MRENCLAVE --new-shard $NEW_MRENCLAVE + + cd shards || exit + rm -rf $OLD_SHARD + done + echo "Done" +} + +function remove_clean_reset { + echo "Removing --clean-reset flag for workers ..." + for ((i = 0; i < WORKER_COUNT; i++)); do + sudo sed -i 's/--clean-reset//' /etc/systemd/system/worker$i.service + done + echo "Done" +} + +# TODO: here we only read worker0 logs here +function latest_sidechain_block { + block_number=$(grep -F 'Enclave produced sidechain blocks' $WORKER_BASEDIR/w0/worker.log | tail -n 1 | sed 's/.*\[//;s/]//') + SCHEDULED_UPDATE_BLOCK=$((block_number + 30)) + echo "Current sidechain block: $block_number, scheduled update block: $SCHEDULED_UPDATE_BLOCK" +} + +# TODO: unused +function _latest_parentchain_block { + # JSON-RPC request payload + request='{"jsonrpc":"2.0","id":1,"method":"chain_getHeader","params":[]}' + + # Make the JSON-RPC request and retrieve the latest finalized block + response=$(curl -s -H "Content-Type: application/json" -d "$request" http://$PARACHAIN_HOST:$PARACHAIN_PORT) + hex_number=$(echo "$response" | grep -oP '(?<="number":")[^"]+') + LATEST_FINALIZED_BLOCK=$(printf "%d" "$hex_number") + echo "Current parachain block: $LATEST_FINALIZED_BLOCK" +} + +main "$@" diff --git a/bitacross-worker/scripts/litentry/release/prepare.sh b/bitacross-worker/scripts/litentry/release/prepare.sh new file mode 100755 index 0000000000..e9817e8d71 --- /dev/null +++ b/bitacross-worker/scripts/litentry/release/prepare.sh @@ -0,0 +1,50 @@ +#!/bin/bash +set -euo pipefail + + +# This WORKER_DIR is the directory where worker will start from. +WORKER_DIR=/opt/worker/ + +# CONFIG_DIR provides all the necessary private secret files. +# They should only exist on the running machine. +CONFIG_DIR=/opt/configs/ +CONFIG=$CONFIG_DIR/config.json +ACCOUNT=$CONFIG_DIR/private_account.json +INTEL_KEY=$CONFIG_DIR/key_production.txt +INTEL_SPID=$CONFIG_DIR/spid_production.txt + +############################################################################## +# Don't edit anything from here +if [[ ! -e "$WORKER_DIR" ]]; then + mkdir -p $WORKER_DIR +fi + +for Item in $CONFIG $ACCOUNT $INTEL_KEY $INTEL_SPID; do + if [[ ! -e "$Item" ]]; then + echo "Error: $Item is not a valid path." + exit 1 + fi +done + +# Generate keys and copy around. +SRC_DIR=$(dirname "$0") +cd $SRC_DIR + +./litentry-worker signing-key | grep -oP '^Enclave account: \K.*$$' > enclave_account.txt +echo "Enclave account is prepared inside enclave_account.txt" + +./litentry-worker shielding-key + +for Item in 'enclave.signed.so' 'litentry-worker' 'aes_key_sealed.bin' 'ed25519_key_sealed.bin' 'enclave-shielding-pubkey.json' 'enclave-signing-pubkey.bin' 'rsa3072_key_sealed.bin' 'sidechain_db'; do + cp -r "${Item}" "${WORKER_DIR}" +done + +cp $CONFIG "${WORKER_DIR}/config.json" +cp $INTEL_KEY "${WORKER_DIR}/key_production.txt" +cp $INTEL_SPID "${WORKER_DIR}/spid_production.txt" + +# Comment out for the moment. Need to adapt together with PR-1587 ts-utils. +cp $ACCOUNT "${WORKER_DIR}/ts-utils/private_account.json" +cp "enclave_account.txt" "${WORKER_DIR}/ts-utils/enclave_account.txt" +cp "mrenclave.txt" "${WORKER_DIR}/ts-utils/mrenclave.txt" + diff --git a/bitacross-worker/scripts/litentry/release/template/para-alice.service b/bitacross-worker/scripts/litentry/release/template/para-alice.service new file mode 100644 index 0000000000..ab1e88e3cd --- /dev/null +++ b/bitacross-worker/scripts/litentry/release/template/para-alice.service @@ -0,0 +1,15 @@ +[Unit] +Description=Litentry Parachain + +[Service] +Type=simple +User=USER +WorkingDirectory=/opt/litentry/parachain +ExecStart=/opt/litentry/parachain/litentry-collator --base-path /opt/litentry/parachain/para-alice --alice --collator --force-authoring --chain CHAIN-dev --unsafe-ws-external --unsafe-rpc-external --rpc-cors=all --ws-max-connections 3000 --port 30333 --ws-port 9944 --rpc-port 9933 --execution wasm --state-pruning archive --blocks-pruning archive -- --execution wasm --chain /opt/litentry/parachain/rococo-local-chain-spec.json --port 30332 --ws-port 9943 --rpc-port 9932 +Restart=always +RestartSec=120 +StandardOutput=append:/opt/litentry/parachain/para.alice.log +StandardError=inherit + +[Install] +WantedBy=multi-user.target diff --git a/bitacross-worker/scripts/litentry/release/template/relay-alice.service b/bitacross-worker/scripts/litentry/release/template/relay-alice.service new file mode 100644 index 0000000000..1263086c97 --- /dev/null +++ b/bitacross-worker/scripts/litentry/release/template/relay-alice.service @@ -0,0 +1,15 @@ +[Unit] +Description=Litentry Relaychain Alice + +[Service] +Type=simple +User=USER +WorkingDirectory=/opt/litentry/parachain +ExecStart=/opt/litentry/parachain/polkadot --base-path /opt/litentry/parachain/relay-alice --chain /opt/litentry/parachain/rococo-local-chain-spec.json --alice --port 30336 --ws-port 9946 --rpc-port 9936 +Restart=always +RestartSec=120 +StandardOutput=append:/opt/litentry/parachain/relay.alice.log +StandardError=inherit + +[Install] +WantedBy=multi-user.target diff --git a/bitacross-worker/scripts/litentry/release/template/relay-bob.service b/bitacross-worker/scripts/litentry/release/template/relay-bob.service new file mode 100644 index 0000000000..14e297bbdb --- /dev/null +++ b/bitacross-worker/scripts/litentry/release/template/relay-bob.service @@ -0,0 +1,15 @@ +[Unit] +Description=Litentry Relaychain Bob + +[Service] +Type=simple +User=USER +WorkingDirectory=/opt/litentry/parachain +ExecStart=/opt/litentry/parachain/polkadot --base-path /opt/litentry/parachain/relay-bob --chain /opt/litentry/parachain/rococo-local-chain-spec.json --bob --port 30337 --ws-port 9947 --rpc-port 9937 +Restart=always +RestartSec=120 +StandardOutput=append:/opt/litentry/parachain/relay.bob.log +StandardError=inherit + +[Install] +WantedBy=multi-user.target diff --git a/bitacross-worker/scripts/litentry/release/template/worker.service b/bitacross-worker/scripts/litentry/release/template/worker.service new file mode 100644 index 0000000000..e218d60278 --- /dev/null +++ b/bitacross-worker/scripts/litentry/release/template/worker.service @@ -0,0 +1,14 @@ +[Unit] +Description=Litentry TEE worker + +[Service] +Type=simple +User=USER +Environment='RUST_LOG=info,litentry_worker=debug,ws=warn,sp_io=error,substrate_api_client=warn,itc_parentchain_light_client=info,jsonrpsee_ws_client=warn,jsonrpsee_ws_server=warn,enclave_runtime=debug,ita_stf=debug,its_rpc_handler=warn,itc_rpc_client=warn,its_consensus_common=debug,its_state=warn,its_consensus_aura=warn,aura*=warn,its_consensus_slots=warn,itp_attestation_handler=debug,http_req=debug,lc_mock_server=warn,itc_rest_client=debug,lc_credentials=debug,lc_identity_verification=debug,lc_stf_task_receiver=debug,lc_stf_task_sender=debug,lc_data_providers=debug,itp_top_pool=debug,itc_parentchain_indirect_calls_executor=debug' +WorkingDirectory=/opt/litentry/worker/wNUMBER +ExecStart=/bin/bash -c 'cd /opt/litentry/worker/wNUMBER && source /opt/intel/sgxsdk/environment && ./litentry-worker ARGS' +StandardOutput=append:/opt/litentry/worker/wNUMBER/worker.log +StandardError=inherit + +[Install] +WantedBy=multi-user.target \ No newline at end of file diff --git a/bitacross-worker/scripts/litentry/start_parachain.sh b/bitacross-worker/scripts/litentry/start_parachain.sh new file mode 100755 index 0000000000..2963fee5b2 --- /dev/null +++ b/bitacross-worker/scripts/litentry/start_parachain.sh @@ -0,0 +1,22 @@ +#!/bin/bash +set -euo pipefail + +# check the port before launching the parachain +# this script is called in bothe launch.sh and launch.py +# +# please note this check doesn't apply to standalone litentry-node +# as it's started without any pre-check script bound +# +# 9944: default ws port for parachain node +# 30333: default p2p port for relaychain node +# 4545: default untrusted-http-port for tee-worker (see config.json) +for p in ${CollatorWSPort:-9944} ${CollatorPort:-30333} ${UntrustedHttpPort:-4545}; do + if [ ! -z "$(netstat -nat | grep :$p)" ]; then + echo "port $p is in use, quit now" + exit 1 + fi +done + +ROOTDIR=$(git rev-parse --show-toplevel) +cd "$ROOTDIR" +make launch-docker-rococo diff --git a/bitacross-worker/scripts/litentry/stop_parachain.sh b/bitacross-worker/scripts/litentry/stop_parachain.sh new file mode 100755 index 0000000000..759083e8e5 --- /dev/null +++ b/bitacross-worker/scripts/litentry/stop_parachain.sh @@ -0,0 +1,6 @@ +#!/bin/bash +set -euo pipefail + +ROOTDIR=$(git rev-parse --show-toplevel) +cd "$ROOTDIR" +make clean-docker-rococo || true diff --git a/bitacross-worker/scripts/litentry/ubuntu_setup.sh b/bitacross-worker/scripts/litentry/ubuntu_setup.sh new file mode 100755 index 0000000000..ef02a6418e --- /dev/null +++ b/bitacross-worker/scripts/litentry/ubuntu_setup.sh @@ -0,0 +1,71 @@ +#!/bin/bash + +set -eo pipefail + +# most is copied from +# https://github.com/apache/incubator-teaclave-sgx-sdk/blob/v1.1.4/dockerfile/Dockerfile.2004.nightly + +# install rust +curl -s https://sh.rustup.rs -sSf | sh -s -- -y +# shellcheck source=${HOME}/.cargo/env +source ${HOME}/.cargo/env +rustup show + +# install substrate build deps +sudo apt-get update +sudo apt-get install -y cmake pkg-config libssl-dev git clang libclang-dev gnupg2 protobuf-compiler + +# install llvm +sudo apt-get update +wget https://apt.llvm.org/llvm.sh && chmod +x llvm.sh && sudo ./llvm.sh 10 + +# override binutils +wget https://download.01.org/intel-sgx/sgx-linux/2.20/as.ld.objdump.r4.tar.gz +tar xzf as.ld.objdump.r4.tar.gz +sudo cp -f external/toolset/ubuntu20.04/* /usr/bin/ + +# install sgx_sdk +SDK_URL="https://download.01.org/intel-sgx/sgx-linux/2.20/distro/ubuntu20.04-server/sgx_linux_x64_sdk_2.20.100.4.bin" +curl -o sdk.sh $SDK_URL +chmod a+x sdk.sh +echo -e 'no\n/opt' | ./sdk.sh +source /opt/sgxsdk/environment + +# install runtime sgx libs (psw) +CODENAME=focal +VERSION=2.20.100.4-focal1 +DCAP_VERSION=1.17.100.4-focal1 + +curl -fsSL https://download.01.org/intel-sgx/sgx_repo/ubuntu/intel-sgx-deb.key | sudo apt-key add - && \ +sudo add-apt-repository "deb https://download.01.org/intel-sgx/sgx_repo/ubuntu $CODENAME main" && \ +sudo apt-get update && \ +sudo apt-get install -y \ + libsgx-headers=$VERSION \ + libsgx-ae-epid=$VERSION \ + libsgx-ae-le=$VERSION \ + libsgx-ae-pce=$VERSION \ + libsgx-aesm-ecdsa-plugin=$VERSION \ + libsgx-aesm-epid-plugin=$VERSION \ + libsgx-aesm-launch-plugin=$VERSION \ + libsgx-aesm-pce-plugin=$VERSION \ + libsgx-aesm-quote-ex-plugin=$VERSION \ + libsgx-enclave-common=$VERSION \ + libsgx-enclave-common-dev=$VERSION \ + libsgx-epid=$VERSION \ + libsgx-epid-dev=$VERSION \ + libsgx-launch=$VERSION \ + libsgx-launch-dev=$VERSION \ + libsgx-quote-ex=$VERSION \ + libsgx-quote-ex-dev=$VERSION \ + libsgx-uae-service=$VERSION \ + libsgx-urts=$VERSION \ + sgx-aesm-service=$VERSION \ + libsgx-ae-qe3=$DCAP_VERSION \ + libsgx-pce-logic=$DCAP_VERSION \ + libsgx-qe3-logic=$DCAP_VERSION \ + libsgx-ra-network=$DCAP_VERSION \ + libsgx-ra-uefi=$DCAP_VERSION +mkdir -p /var/run/aesmd || true + +# store env +echo "$(env)" >> $GITHUB_ENV \ No newline at end of file diff --git a/bitacross-worker/scripts/m6.sh b/bitacross-worker/scripts/m6.sh new file mode 100755 index 0000000000..d6ed56786d --- /dev/null +++ b/bitacross-worker/scripts/m6.sh @@ -0,0 +1,23 @@ +#!/bin/bash +set -euo pipefail + +# Runs M6 demo: Either set `CLIENT_DIR` env var directly or run script with: +# +# source ./init_env.sh && ./m6.sh + +echo "$CLIENT_DIR" + +cd "$CLIENT_DIR" || exit + +LOG_1="${LOG_1:-$LOG_DIR/m6_demo_shielding_unshielding_1.log}" +LOG_2="${LOG_2:-$LOG_DIR/m6_demo_shielding_unshielding_2.log}" + +echo "[m6.sh] printing to logs:" +echo " $LOG_1" +echo " $LOG_2" + +touch "$LOG_1" +touch "$LOG_2" + +./demo_shielding_unshielding.sh -p 9944 -P 2000 -C ./../bin/bitacross-cli -t first 2>&1 | tee "$LOG_1" +./demo_shielding_unshielding.sh -p 9944 -P 3000 -C ./../bin/bitacross-cli -t second 2>&1 | tee "$LOG_2" diff --git a/bitacross-worker/scripts/m8.sh b/bitacross-worker/scripts/m8.sh new file mode 100755 index 0000000000..402875a8c8 --- /dev/null +++ b/bitacross-worker/scripts/m8.sh @@ -0,0 +1,21 @@ +#!/bin/bash +set -euo pipefail + +# Runs M8 demo: Either set `CLIENT_DIR` env var directly or run script with: +# +# source ./init_env.sh && ./m8.sh + +cd "$CLIENT_DIR" || exit + +LOG_1="${LOG_1:-$LOG_DIR/m8_demo_direct_call_1.log}" +LOG_2="${LOG_2:-$LOG_DIR/m8_demo_direct_call_2.log}" + +echo "[m8.sh] printing to logs:" +echo " $LOG_1" +echo " $LOG_2" + +touch "$LOG_1" +touch "$LOG_2" + +./demo_direct_call.sh -p 9944 -P 2000 -C ./../bin/bitacross-cli -t first 2>&1 | tee "$LOG_1" +./demo_direct_call.sh -p 9944 -P 3000 -C ./../bin/bitacross-cli -t second 2>&1 | tee "$LOG_2" diff --git a/bitacross-worker/scripts/polkadot_update.sh b/bitacross-worker/scripts/polkadot_update.sh new file mode 100755 index 0000000000..0ba52f86e3 --- /dev/null +++ b/bitacross-worker/scripts/polkadot_update.sh @@ -0,0 +1,97 @@ +#!/bin/bash + +# A script to automate the polkadot update for our repository as far as possible +# Needs the diener and sd (sed replacement) tool. Install with: +# cargo install diener +# cargo install sd + +# These are the values that need to be adjusted for an update +CHECKOUT_DIR="$HOME/polkadot_update2" +DEVELOPER_ID="tn" +OLD_VERSION_NUMBER="0.9.27" +NEW_VERSION_NUMBER="0.9.28" +NEW_NIGHTLY_VERSION="2022-09-12" + +OLD_POLKADOT_VERSION_NUMBER="polkadot-v${OLD_VERSION_NUMBER}" +NEW_POLKADOT_VERSION_NUMBER="polkadot-v${NEW_VERSION_NUMBER}" +DEVELOPMENT_BRANCH="${DEVELOPER_ID}/${NEW_POLKADOT_VERSION_NUMBER}" + +# Make sure that the directory does not exist. We don't want to mess up existing stuff +if [ -d "${CHECKOUT_DIR}" ]; then + echo "Directory ${CHECKOUT_DIR} already exists. Please delete directory first." + exit 1 +fi + +mkdir "${CHECKOUT_DIR}" +pushd "${CHECKOUT_DIR}" + +git clone https://github.com/integritee-network/integritee-node.git +git clone https://github.com/integritee-network/pallets.git +git clone https://github.com/integritee-network/parachain.git +git clone https://github.com/scs/substrate-api-client.git +git clone https://github.com/integritee-network/worker.git + +declare -a REPO_NAMES=("integritee-node" "pallets" "parachain" "substrate-api-client" "worker" ) + +# Create new branch for all repos +for REPO in ${REPO_NAMES[@]}; do + pushd ${REPO};git checkout -b ${DEVELOPMENT_BRANCH};popd +done + +# Update the polkadot version +# We cannot combine the flags into a single call. Don't use the all flag because it relly changes all dependencies +diener update --cumulus --branch ${NEW_POLKADOT_VERSION_NUMBER} +diener update --substrate --branch ${NEW_POLKADOT_VERSION_NUMBER} +# Polkadot uses another branch pattern, because why not... +diener update --polkadot --branch "release-v${NEW_VERSION_NUMBER}" + +# Add commit for all repos +for REPO in ${REPO_NAMES[@]}; do + pushd ${REPO};git add -A;git commit -m "Update polkadot version (Auto generated commit)";popd +done + +# Execute cargo update for all repos. Currently not active as it is not clear when is the "right moment" to do this +#for REPO in ${REPO_NAMES[@]}; do +# pushd ${REPO};cargo update;popd +#done + +# Add commit for all repos +#for REPO in ${REPO_NAMES[@]}; do +# pushd ${REPO};git add -A;git commit -m "Run cargo update (Auto generated)";popd +#done + +#set -o xtrace +# Update internal dependencies by doing search replace +for REPO in ${REPO_NAMES[@]}; do + SEARCH_STRING_VERSION="${REPO}\", branch = \"${OLD_POLKADOT_VERSION_NUMBER}\"" + SEARCH_STRING_VERSION_GIT="${REPO}.git\", branch = \"${OLD_POLKADOT_VERSION_NUMBER}\"" + SEARCH_STRING_MASTER="${REPO}\", branch = \"master\"" + SEARCH_STRING_MASTER_GIT="${REPO}.git\", branch = \"master\"" + REPLACE_STRING="${REPO}.git\", branch = \"${DEVELOPMENT_BRANCH}\"" + sd "${SEARCH_STRING_VERSION}" "${REPLACE_STRING}" $(find . -type f -name 'Cargo.toml') + sd "${SEARCH_STRING_VERSION_GIT}" "${REPLACE_STRING}" $(find . -type f -name 'Cargo.toml') + sd "${SEARCH_STRING_MASTER}" "${REPLACE_STRING}" $(find . -type f -name 'Cargo.toml') + sd "${SEARCH_STRING_MASTER_GIT}" "${REPLACE_STRING}" $(find . -type f -name 'Cargo.toml') +done + +# Add commit for all repos +for REPO in ${REPO_NAMES[@]}; do + pushd ${REPO};git add -A;git commit -m "Update versions for internal dependencies (Auto generated commit)";popd +done + +NIGHTLY_SEARCH_STRING="channel = \"nightly-.*\"" +NIGHTLY_SEARCH_STRING="channel = \"nightly-${NEW_NIGHTLY_VERSION}\"" +sd "${NIGHTLY_SEARCH_STRING}" "${NIGTHLY_NEW_STRING}" $(find . -type f -name 'rust-toolchain.toml') + +# Add commit for all repos +for REPO in ${REPO_NAMES[@]}; do + pushd ${REPO};git add -A;git commit -m "Update rust toolchain to new nightly version (Auto generated commit)";popd +done + +echo "" +echo "" +echo "Search results for old version number ${OLD_VERSION_NUMBER} in Cargo.toml files:" +# Exclude the lock files as they still refer to the old version +grep -F -r --exclude *.lock "${OLD_VERSION_NUMBER}" . + +popd diff --git a/bitacross-worker/scripts/sidechain.sh b/bitacross-worker/scripts/sidechain.sh new file mode 100755 index 0000000000..908c538eb1 --- /dev/null +++ b/bitacross-worker/scripts/sidechain.sh @@ -0,0 +1,17 @@ +#!/bin/bash +set -euo pipefail + +# Runs sidechain demo: Either set `CLIENT_DIR` env var directly or run script with: +# +# source ./init_env.sh && ./sidechain.sh + +cd "$CLIENT_DIR" || exit + +LOG="${LOG:-$LOG_DIR/sidechain_demo.log}" + +echo "[sidechain.sh] printing to logs:" +echo " $LOG" + +touch "$LOG" + +./demo_sidechain.sh -p 9944 -A 2000 -B 3000 -C ./../bin/bitacross-cli 2>&1 | tee "$LOG" \ No newline at end of file diff --git a/bitacross-worker/scripts/teeracle.sh b/bitacross-worker/scripts/teeracle.sh new file mode 100644 index 0000000000..829c67b2a3 --- /dev/null +++ b/bitacross-worker/scripts/teeracle.sh @@ -0,0 +1,19 @@ +#!/bin/bash +set -euo pipefail + +# Runs Teeracle1 demo: Either set `CLIENT_DIR` env var directly or run script with: +# +# source ./init_env.sh && ./teeracle.sh + +echo "$CLIENT_DIR" + +cd "$CLIENT_DIR" || exit + +LOG_1="${LOG_1:-$LOG_DIR/teeracle1_demo_whitelist.log}" + +echo "[teeracle.sh] printing to logs:" +echo " $LOG_1" + +touch "$LOG_1" + +./demo_teeracle_whitelist.sh -p 9944 -P 2000 -d 120 -i 24 2>&1 | tee "$LOG_1" diff --git a/bitacross-worker/scripts/test_transfer/README.md b/bitacross-worker/scripts/test_transfer/README.md new file mode 100644 index 0000000000..13ff80ca8e --- /dev/null +++ b/bitacross-worker/scripts/test_transfer/README.md @@ -0,0 +1,6 @@ +## Test transfer from Alice to random account + +## Install +```bash +npm install +``` diff --git a/bitacross-worker/scripts/test_transfer/package-lock.json b/bitacross-worker/scripts/test_transfer/package-lock.json new file mode 100644 index 0000000000..237b27764d --- /dev/null +++ b/bitacross-worker/scripts/test_transfer/package-lock.json @@ -0,0 +1,1322 @@ +{ + "name": "test_transfer", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "test_transfer", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "@polkadot/api": "^10.9.1", + "@polkadot/keyring": "^12.3.2", + "@polkadot/util-crypto": "^12.3.2" + } + }, + "node_modules/@noble/curves": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.1.0.tgz", + "integrity": "sha512-091oBExgENk/kGj3AZmtBDMpxQPDtxQABR2B9lb1JbVTs6ytdzZNwvhxQ4MWasRNEzlbEH8jCWFCwhF/Obj5AA==", + "dependencies": { + "@noble/hashes": "1.3.1" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@noble/hashes": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.1.tgz", + "integrity": "sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA==", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@polkadot/api": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/@polkadot/api/-/api-10.9.1.tgz", + "integrity": "sha512-ND/2UqZBWvtt4PfV03OStTKg0mxmPk4UpMAgJKutdgsz/wP9CYJ1KbjwFgPNekL9JnzbKQsWyQNPVrcw7kQk8A==", + "dependencies": { + "@polkadot/api-augment": "10.9.1", + "@polkadot/api-base": "10.9.1", + "@polkadot/api-derive": "10.9.1", + "@polkadot/keyring": "^12.3.1", + "@polkadot/rpc-augment": "10.9.1", + "@polkadot/rpc-core": "10.9.1", + "@polkadot/rpc-provider": "10.9.1", + "@polkadot/types": "10.9.1", + "@polkadot/types-augment": "10.9.1", + "@polkadot/types-codec": "10.9.1", + "@polkadot/types-create": "10.9.1", + "@polkadot/types-known": "10.9.1", + "@polkadot/util": "^12.3.1", + "@polkadot/util-crypto": "^12.3.1", + "eventemitter3": "^5.0.1", + "rxjs": "^7.8.1", + "tslib": "^2.5.3" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@polkadot/api-augment": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/@polkadot/api-augment/-/api-augment-10.9.1.tgz", + "integrity": "sha512-kRZZvCFVcN4hAH4dJ+Qzfdy27/4EEq3oLDf3ihj0LTVrAezSWcKPGE3EVFy+Mn6Lo4SUc7RVyoKvIUhSk2l4Dg==", + "dependencies": { + "@polkadot/api-base": "10.9.1", + "@polkadot/rpc-augment": "10.9.1", + "@polkadot/types": "10.9.1", + "@polkadot/types-augment": "10.9.1", + "@polkadot/types-codec": "10.9.1", + "@polkadot/util": "^12.3.1", + "tslib": "^2.5.3" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@polkadot/api-base": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/@polkadot/api-base/-/api-base-10.9.1.tgz", + "integrity": "sha512-Q3m2KzlceMK2kX8bhnUZWk3RT6emmijeeFZZQgCePpEcrSeNjnqG4qjuTPgkveaOkUT8MAoDc5Avuzcc2jlW9g==", + "dependencies": { + "@polkadot/rpc-core": "10.9.1", + "@polkadot/types": "10.9.1", + "@polkadot/util": "^12.3.1", + "rxjs": "^7.8.1", + "tslib": "^2.5.3" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@polkadot/api-derive": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/@polkadot/api-derive/-/api-derive-10.9.1.tgz", + "integrity": "sha512-mRud1UZCFIc4Z63qAoGSIHh/foyUYADfy1RQYCmPpeFKfIdCIrHpd7xFdJXTOMYOS0BwlM6u4qli/ZT4XigezQ==", + "dependencies": { + "@polkadot/api": "10.9.1", + "@polkadot/api-augment": "10.9.1", + "@polkadot/api-base": "10.9.1", + "@polkadot/rpc-core": "10.9.1", + "@polkadot/types": "10.9.1", + "@polkadot/types-codec": "10.9.1", + "@polkadot/util": "^12.3.1", + "@polkadot/util-crypto": "^12.3.1", + "rxjs": "^7.8.1", + "tslib": "^2.5.3" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@polkadot/keyring": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/@polkadot/keyring/-/keyring-12.3.2.tgz", + "integrity": "sha512-NTdtDeI0DP9l/45hXynNABeP5VB8piw5YR+CbUxK2e36xpJWVXwbcOepzslg5ghE9rs8UKJb30Z/HqTU4sBY0Q==", + "dependencies": { + "@polkadot/util": "12.3.2", + "@polkadot/util-crypto": "12.3.2", + "tslib": "^2.5.3" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "@polkadot/util": "12.3.2", + "@polkadot/util-crypto": "12.3.2" + } + }, + "node_modules/@polkadot/networks": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/@polkadot/networks/-/networks-12.3.2.tgz", + "integrity": "sha512-uCkyybKoeEm1daKr0uT/9oNDHDDzCy2/ZdVl346hQqfdR1Ct3BaxMjxqvdmb5N8aCw0cBWSfgsxAYtw8ESmllQ==", + "dependencies": { + "@polkadot/util": "12.3.2", + "@substrate/ss58-registry": "^1.40.0", + "tslib": "^2.5.3" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@polkadot/rpc-augment": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/@polkadot/rpc-augment/-/rpc-augment-10.9.1.tgz", + "integrity": "sha512-MaLHkNlyqN20ZRYr6uNd1BZr1OsrnX9qLAmsl0mcrri1vPGRH6VHjfFH1RBLkikpWD82v17g0l2hLwdV1ZHMcw==", + "dependencies": { + "@polkadot/rpc-core": "10.9.1", + "@polkadot/types": "10.9.1", + "@polkadot/types-codec": "10.9.1", + "@polkadot/util": "^12.3.1", + "tslib": "^2.5.3" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@polkadot/rpc-core": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/@polkadot/rpc-core/-/rpc-core-10.9.1.tgz", + "integrity": "sha512-ZtA8B8SfXSAwVkBlCcKRHw0eSM7ec/sbiNOM5GasXPeRujUgT7lOwSH2GbUZSqe9RfRDMp6DvO9c2JoGc3LLWw==", + "dependencies": { + "@polkadot/rpc-augment": "10.9.1", + "@polkadot/rpc-provider": "10.9.1", + "@polkadot/types": "10.9.1", + "@polkadot/util": "^12.3.1", + "rxjs": "^7.8.1", + "tslib": "^2.5.3" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@polkadot/rpc-provider": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/@polkadot/rpc-provider/-/rpc-provider-10.9.1.tgz", + "integrity": "sha512-4QzT2QzD+320+eT6b79sGAA85Tt3Bb8fQvse4r5Mom2iiBd2SO81vOhxSAOaIe4GUsw25VzFJmsbe7+OObItdg==", + "dependencies": { + "@polkadot/keyring": "^12.3.1", + "@polkadot/types": "10.9.1", + "@polkadot/types-support": "10.9.1", + "@polkadot/util": "^12.3.1", + "@polkadot/util-crypto": "^12.3.1", + "@polkadot/x-fetch": "^12.3.1", + "@polkadot/x-global": "^12.3.1", + "@polkadot/x-ws": "^12.3.1", + "eventemitter3": "^5.0.1", + "mock-socket": "^9.2.1", + "nock": "^13.3.1", + "tslib": "^2.5.3" + }, + "engines": { + "node": ">=16" + }, + "optionalDependencies": { + "@substrate/connect": "0.7.26" + } + }, + "node_modules/@polkadot/types": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/@polkadot/types/-/types-10.9.1.tgz", + "integrity": "sha512-AG33i2ZGGfq7u+5rkAdGrXAQHHl844/Yv+junH5ZzX69xiCoWO1bH/yzDUNBdpki2GlACWvF9nLYh3F2tVF93w==", + "dependencies": { + "@polkadot/keyring": "^12.3.1", + "@polkadot/types-augment": "10.9.1", + "@polkadot/types-codec": "10.9.1", + "@polkadot/types-create": "10.9.1", + "@polkadot/util": "^12.3.1", + "@polkadot/util-crypto": "^12.3.1", + "rxjs": "^7.8.1", + "tslib": "^2.5.3" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@polkadot/types-augment": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/@polkadot/types-augment/-/types-augment-10.9.1.tgz", + "integrity": "sha512-OY9/jTMFRFqYdkUnfcGwqMLC64A0Q25bjvCuVQCVjsPFKE3wl0Kt5rNT01eV2UmLXrR6fY0xWbR2w80bLA7CIQ==", + "dependencies": { + "@polkadot/types": "10.9.1", + "@polkadot/types-codec": "10.9.1", + "@polkadot/util": "^12.3.1", + "tslib": "^2.5.3" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@polkadot/types-codec": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/@polkadot/types-codec/-/types-codec-10.9.1.tgz", + "integrity": "sha512-mJ5OegKGraY1FLvEa8FopRCr3pQrhDkcn5RNOjmgJQozENVeRaxhk0NwxYz7IojFvSDnKnc6lNQfKaaSe5pLHg==", + "dependencies": { + "@polkadot/util": "^12.3.1", + "@polkadot/x-bigint": "^12.3.1", + "tslib": "^2.5.3" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@polkadot/types-create": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/@polkadot/types-create/-/types-create-10.9.1.tgz", + "integrity": "sha512-OVz50MGTTuiuVnRP/zAx4CTuLioc0hsiwNwqN2lNhmIJGtnQ4Vy/7mQRsIWehiYz6g0Vzzm5B3qWkTXO1NSN5w==", + "dependencies": { + "@polkadot/types-codec": "10.9.1", + "@polkadot/util": "^12.3.1", + "tslib": "^2.5.3" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@polkadot/types-known": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/@polkadot/types-known/-/types-known-10.9.1.tgz", + "integrity": "sha512-zCMVWc4pJtkbMFPu72bD4IhvV/gkHXPX3C5uu92WdmCfnn0vEIEsMKWlVXVVvQQZKAqvs/awpqIfrUtEViOGEA==", + "dependencies": { + "@polkadot/networks": "^12.3.1", + "@polkadot/types": "10.9.1", + "@polkadot/types-codec": "10.9.1", + "@polkadot/types-create": "10.9.1", + "@polkadot/util": "^12.3.1", + "tslib": "^2.5.3" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@polkadot/types-support": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/@polkadot/types-support/-/types-support-10.9.1.tgz", + "integrity": "sha512-XsieuLDsszvMZQlleacQBfx07i/JkwQV/UxH9q8Hz7Okmaz9pEVEW1h3ka2/cPuC7a4l32JhaORBUYshBZNdJg==", + "dependencies": { + "@polkadot/util": "^12.3.1", + "tslib": "^2.5.3" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@polkadot/util": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/@polkadot/util/-/util-12.3.2.tgz", + "integrity": "sha512-y/JShcGyOamCUiSIg++XZuLHt1ktSKBaSH2K5Nw5NXlgP0+7am+GZzqPB8fQ4qhYLruEOv+YRiz0GC1Zr9S+wg==", + "dependencies": { + "@polkadot/x-bigint": "12.3.2", + "@polkadot/x-global": "12.3.2", + "@polkadot/x-textdecoder": "12.3.2", + "@polkadot/x-textencoder": "12.3.2", + "@types/bn.js": "^5.1.1", + "bn.js": "^5.2.1", + "tslib": "^2.5.3" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@polkadot/util-crypto": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/@polkadot/util-crypto/-/util-crypto-12.3.2.tgz", + "integrity": "sha512-pTpx+YxolY0BDT4RcGmgeKbHHD/dI6Ll9xRsqmVdIjpcVVY20uDNTyXs81ZNtfKgyod1y9JQkfNv2Dz9iEpTkQ==", + "dependencies": { + "@noble/curves": "1.1.0", + "@noble/hashes": "1.3.1", + "@polkadot/networks": "12.3.2", + "@polkadot/util": "12.3.2", + "@polkadot/wasm-crypto": "^7.2.1", + "@polkadot/wasm-util": "^7.2.1", + "@polkadot/x-bigint": "12.3.2", + "@polkadot/x-randomvalues": "12.3.2", + "@scure/base": "1.1.1", + "tslib": "^2.5.3" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "@polkadot/util": "12.3.2" + } + }, + "node_modules/@polkadot/wasm-bridge": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/@polkadot/wasm-bridge/-/wasm-bridge-7.2.1.tgz", + "integrity": "sha512-uV/LHREDBGBbHrrv7HTki+Klw0PYZzFomagFWII4lp6Toj/VCvRh5WMzooVC+g/XsBGosAwrvBhoModabyHx+A==", + "dependencies": { + "@polkadot/wasm-util": "7.2.1", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "@polkadot/util": "*", + "@polkadot/x-randomvalues": "*" + } + }, + "node_modules/@polkadot/wasm-crypto": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/@polkadot/wasm-crypto/-/wasm-crypto-7.2.1.tgz", + "integrity": "sha512-SA2+33S9TAwGhniKgztVN6pxUKpGfN4Tre/eUZGUfpgRkT92wIUT2GpGWQE+fCCqGQgADrNiBcwt6XwdPqMQ4Q==", + "dependencies": { + "@polkadot/wasm-bridge": "7.2.1", + "@polkadot/wasm-crypto-asmjs": "7.2.1", + "@polkadot/wasm-crypto-init": "7.2.1", + "@polkadot/wasm-crypto-wasm": "7.2.1", + "@polkadot/wasm-util": "7.2.1", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "@polkadot/util": "*", + "@polkadot/x-randomvalues": "*" + } + }, + "node_modules/@polkadot/wasm-crypto-asmjs": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/@polkadot/wasm-crypto-asmjs/-/wasm-crypto-asmjs-7.2.1.tgz", + "integrity": "sha512-z/d21bmxyVfkzGsKef/FWswKX02x5lK97f4NPBZ9XBeiFkmzlXhdSnu58/+b1sKsRAGdW/Rn/rTNRDhW0GqCAg==", + "dependencies": { + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "@polkadot/util": "*" + } + }, + "node_modules/@polkadot/wasm-crypto-init": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/@polkadot/wasm-crypto-init/-/wasm-crypto-init-7.2.1.tgz", + "integrity": "sha512-GcEXtwN9LcSf32V9zSaYjHImFw16hCyo2Xzg4GLLDPPeaAAfbFr2oQMgwyDbvBrBjLKHVHjsPZyGhXae831amw==", + "dependencies": { + "@polkadot/wasm-bridge": "7.2.1", + "@polkadot/wasm-crypto-asmjs": "7.2.1", + "@polkadot/wasm-crypto-wasm": "7.2.1", + "@polkadot/wasm-util": "7.2.1", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "@polkadot/util": "*", + "@polkadot/x-randomvalues": "*" + } + }, + "node_modules/@polkadot/wasm-crypto-wasm": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/@polkadot/wasm-crypto-wasm/-/wasm-crypto-wasm-7.2.1.tgz", + "integrity": "sha512-DqyXE4rSD0CVlLIw88B58+HHNyrvm+JAnYyuEDYZwCvzUWOCNos/DDg9wi/K39VAIsCCKDmwKqkkfIofuOj/lA==", + "dependencies": { + "@polkadot/wasm-util": "7.2.1", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "@polkadot/util": "*" + } + }, + "node_modules/@polkadot/wasm-util": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/@polkadot/wasm-util/-/wasm-util-7.2.1.tgz", + "integrity": "sha512-FBSn/3aYJzhN0sYAYhHB8y9JL8mVgxLy4M1kUXYbyo+8GLRQEN5rns8Vcb8TAlIzBWgVTOOptYBvxo0oj0h7Og==", + "dependencies": { + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "@polkadot/util": "*" + } + }, + "node_modules/@polkadot/x-bigint": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/@polkadot/x-bigint/-/x-bigint-12.3.2.tgz", + "integrity": "sha512-JLqLgfGXe/x+hZJETd5ZqfpVsbwyMsH5Nn1Q20ineMMjXN/ig+kVR8Mc15LXBMuw4g7LldFW6UUrotWnuMI8Yw==", + "dependencies": { + "@polkadot/x-global": "12.3.2", + "tslib": "^2.5.3" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@polkadot/x-fetch": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/@polkadot/x-fetch/-/x-fetch-12.3.2.tgz", + "integrity": "sha512-3IEuZ5S+RI/t33NsdPLIIa5COfDCfpUW2sbaByEczn75aD1jLqJZSEDwiBniJ2osyNd4uUxBf6e5jw7LAZeZJg==", + "dependencies": { + "@polkadot/x-global": "12.3.2", + "node-fetch": "^3.3.1", + "tslib": "^2.5.3" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@polkadot/x-global": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/@polkadot/x-global/-/x-global-12.3.2.tgz", + "integrity": "sha512-yVZq6oIegjlyh5rUZiTklgu+fL+W/DG1ypEa02683tUCB3avV5cA3PAHKptMSlb6FpweHu37lKKrqfAWrraDxg==", + "dependencies": { + "tslib": "^2.5.3" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@polkadot/x-randomvalues": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/@polkadot/x-randomvalues/-/x-randomvalues-12.3.2.tgz", + "integrity": "sha512-ywjIs8CWpvOGmq+3cGCNPOHxAjPHdBUiXyDccftx5BRVdmtbt36gK/V84bKr6Xs73FGu0jprUAOSRRsLZX/3dg==", + "dependencies": { + "@polkadot/x-global": "12.3.2", + "tslib": "^2.5.3" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "@polkadot/util": "12.3.2", + "@polkadot/wasm-util": "*" + } + }, + "node_modules/@polkadot/x-textdecoder": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/@polkadot/x-textdecoder/-/x-textdecoder-12.3.2.tgz", + "integrity": "sha512-lY5bfA5xArJRWEJlYOlQQMJeTjWD8s0yMhchirVgf5xj8Id9vPGeUoneH+VFDEwgXxrqBvDFJ4smN4T/r6a/fg==", + "dependencies": { + "@polkadot/x-global": "12.3.2", + "tslib": "^2.5.3" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@polkadot/x-textencoder": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/@polkadot/x-textencoder/-/x-textencoder-12.3.2.tgz", + "integrity": "sha512-iP3qEBiHzBckQ9zeY7ZHRWuu7mCEg5SMpOugs6UODRk8sx6KHzGQYlghBbWLit0uppPDVE0ifEwZ2n73djJHWQ==", + "dependencies": { + "@polkadot/x-global": "12.3.2", + "tslib": "^2.5.3" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@polkadot/x-ws": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/@polkadot/x-ws/-/x-ws-12.3.2.tgz", + "integrity": "sha512-yM9Z64pLNlHpJE43+Xtr+iUXmYpFFY5u5hrke2PJt13O48H8f9Vb9cRaIh94appLyICoS0aekGhDkGH+MCspBA==", + "dependencies": { + "@polkadot/x-global": "12.3.2", + "tslib": "^2.5.3", + "ws": "^8.13.0" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@scure/base": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.1.tgz", + "integrity": "sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA==", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ] + }, + "node_modules/@substrate/connect": { + "version": "0.7.26", + "resolved": "https://registry.npmjs.org/@substrate/connect/-/connect-0.7.26.tgz", + "integrity": "sha512-uuGSiroGuKWj1+38n1kY5HReer5iL9bRwPCzuoLtqAOmI1fGI0hsSI2LlNQMAbfRgr7VRHXOk5MTuQf5ulsFRw==", + "optional": true, + "dependencies": { + "@substrate/connect-extension-protocol": "^1.0.1", + "eventemitter3": "^4.0.7", + "smoldot": "1.0.4" + } + }, + "node_modules/@substrate/connect-extension-protocol": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@substrate/connect-extension-protocol/-/connect-extension-protocol-1.0.1.tgz", + "integrity": "sha512-161JhCC1csjH3GE5mPLEd7HbWtwNSPJBg3p1Ksz9SFlTzj/bgEwudiRN2y5i0MoLGCIJRYKyKGMxVnd29PzNjg==", + "optional": true + }, + "node_modules/@substrate/connect/node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "optional": true + }, + "node_modules/@substrate/ss58-registry": { + "version": "1.40.0", + "resolved": "https://registry.npmjs.org/@substrate/ss58-registry/-/ss58-registry-1.40.0.tgz", + "integrity": "sha512-QuU2nBql3J4KCnOWtWDw4n1K4JU0T79j54ZZvm/9nhsX6AIar13FyhsaBfs6QkJ2ixTQAnd7TocJIoJRWbqMZA==" + }, + "node_modules/@types/bn.js": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.1.tgz", + "integrity": "sha512-qNrYbZqMx0uJAfKnKclPh+dTwK33KfLHYqtyODwd5HnXOjnkhc4qgn3BrK6RWyGZm5+sIFE7Q7Vz6QQtJB7w7g==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/node": { + "version": "20.3.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.3.1.tgz", + "integrity": "sha512-EhcH/wvidPy1WeML3TtYFGR83UzjxeWRen9V402T8aUGYsCHOmfoisV3ZSg03gAFIbLq8TnWOJ0f4cALtnSEUg==" + }, + "node_modules/bn.js": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", + "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==" + }, + "node_modules/data-uri-to-buffer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", + "engines": { + "node": ">= 12" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==" + }, + "node_modules/fetch-blob": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", + "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "paypal", + "url": "https://paypal.me/jimmywarting" + } + ], + "dependencies": { + "node-domexception": "^1.0.0", + "web-streams-polyfill": "^3.0.3" + }, + "engines": { + "node": "^12.20 || >= 14.13" + } + }, + "node_modules/formdata-polyfill": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "dependencies": { + "fetch-blob": "^3.1.2" + }, + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==" + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/mock-socket": { + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/mock-socket/-/mock-socket-9.2.1.tgz", + "integrity": "sha512-aw9F9T9G2zpGipLLhSNh6ZpgUyUl4frcVmRN08uE1NWPWg43Wx6+sGPDbQ7E5iFZZDJW5b5bypMeAEHqTbIFag==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/nock": { + "version": "13.3.1", + "resolved": "https://registry.npmjs.org/nock/-/nock-13.3.1.tgz", + "integrity": "sha512-vHnopocZuI93p2ccivFyGuUfzjq2fxNyNurp7816mlT5V5HF4SzXu8lvLrVzBbNqzs+ODooZ6OksuSUNM7Njkw==", + "dependencies": { + "debug": "^4.1.0", + "json-stringify-safe": "^5.0.1", + "lodash": "^4.17.21", + "propagate": "^2.0.0" + }, + "engines": { + "node": ">= 10.13" + } + }, + "node_modules/node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "github", + "url": "https://paypal.me/jimmywarting" + } + ], + "engines": { + "node": ">=10.5.0" + } + }, + "node_modules/node-fetch": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.1.tgz", + "integrity": "sha512-cRVc/kyto/7E5shrWca1Wsea4y6tL9iYJE5FBCius3JQfb/4P4I295PfhgbJQBLTx6lATE4z+wK0rPM4VS2uow==", + "dependencies": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-fetch" + } + }, + "node_modules/pako": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/pako/-/pako-2.1.0.tgz", + "integrity": "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==", + "optional": true + }, + "node_modules/propagate": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/propagate/-/propagate-2.0.1.tgz", + "integrity": "sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/rxjs": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/smoldot": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/smoldot/-/smoldot-1.0.4.tgz", + "integrity": "sha512-N3TazI1C4GGrseFH/piWyZCCCRJTRx2QhDfrUKRT4SzILlW5m8ayZ3QTKICcz1C/536T9cbHHJyP7afxI6Mi1A==", + "optional": true, + "dependencies": { + "pako": "^2.0.4", + "ws": "^8.8.1" + } + }, + "node_modules/tslib": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.3.tgz", + "integrity": "sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w==" + }, + "node_modules/web-streams-polyfill": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz", + "integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/ws": { + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", + "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + } + }, + "dependencies": { + "@noble/curves": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.1.0.tgz", + "integrity": "sha512-091oBExgENk/kGj3AZmtBDMpxQPDtxQABR2B9lb1JbVTs6ytdzZNwvhxQ4MWasRNEzlbEH8jCWFCwhF/Obj5AA==", + "requires": { + "@noble/hashes": "1.3.1" + } + }, + "@noble/hashes": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.1.tgz", + "integrity": "sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA==" + }, + "@polkadot/api": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/@polkadot/api/-/api-10.9.1.tgz", + "integrity": "sha512-ND/2UqZBWvtt4PfV03OStTKg0mxmPk4UpMAgJKutdgsz/wP9CYJ1KbjwFgPNekL9JnzbKQsWyQNPVrcw7kQk8A==", + "requires": { + "@polkadot/api-augment": "10.9.1", + "@polkadot/api-base": "10.9.1", + "@polkadot/api-derive": "10.9.1", + "@polkadot/keyring": "^12.3.1", + "@polkadot/rpc-augment": "10.9.1", + "@polkadot/rpc-core": "10.9.1", + "@polkadot/rpc-provider": "10.9.1", + "@polkadot/types": "10.9.1", + "@polkadot/types-augment": "10.9.1", + "@polkadot/types-codec": "10.9.1", + "@polkadot/types-create": "10.9.1", + "@polkadot/types-known": "10.9.1", + "@polkadot/util": "^12.3.1", + "@polkadot/util-crypto": "^12.3.1", + "eventemitter3": "^5.0.1", + "rxjs": "^7.8.1", + "tslib": "^2.5.3" + } + }, + "@polkadot/api-augment": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/@polkadot/api-augment/-/api-augment-10.9.1.tgz", + "integrity": "sha512-kRZZvCFVcN4hAH4dJ+Qzfdy27/4EEq3oLDf3ihj0LTVrAezSWcKPGE3EVFy+Mn6Lo4SUc7RVyoKvIUhSk2l4Dg==", + "requires": { + "@polkadot/api-base": "10.9.1", + "@polkadot/rpc-augment": "10.9.1", + "@polkadot/types": "10.9.1", + "@polkadot/types-augment": "10.9.1", + "@polkadot/types-codec": "10.9.1", + "@polkadot/util": "^12.3.1", + "tslib": "^2.5.3" + } + }, + "@polkadot/api-base": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/@polkadot/api-base/-/api-base-10.9.1.tgz", + "integrity": "sha512-Q3m2KzlceMK2kX8bhnUZWk3RT6emmijeeFZZQgCePpEcrSeNjnqG4qjuTPgkveaOkUT8MAoDc5Avuzcc2jlW9g==", + "requires": { + "@polkadot/rpc-core": "10.9.1", + "@polkadot/types": "10.9.1", + "@polkadot/util": "^12.3.1", + "rxjs": "^7.8.1", + "tslib": "^2.5.3" + } + }, + "@polkadot/api-derive": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/@polkadot/api-derive/-/api-derive-10.9.1.tgz", + "integrity": "sha512-mRud1UZCFIc4Z63qAoGSIHh/foyUYADfy1RQYCmPpeFKfIdCIrHpd7xFdJXTOMYOS0BwlM6u4qli/ZT4XigezQ==", + "requires": { + "@polkadot/api": "10.9.1", + "@polkadot/api-augment": "10.9.1", + "@polkadot/api-base": "10.9.1", + "@polkadot/rpc-core": "10.9.1", + "@polkadot/types": "10.9.1", + "@polkadot/types-codec": "10.9.1", + "@polkadot/util": "^12.3.1", + "@polkadot/util-crypto": "^12.3.1", + "rxjs": "^7.8.1", + "tslib": "^2.5.3" + } + }, + "@polkadot/keyring": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/@polkadot/keyring/-/keyring-12.3.2.tgz", + "integrity": "sha512-NTdtDeI0DP9l/45hXynNABeP5VB8piw5YR+CbUxK2e36xpJWVXwbcOepzslg5ghE9rs8UKJb30Z/HqTU4sBY0Q==", + "requires": { + "@polkadot/util": "12.3.2", + "@polkadot/util-crypto": "12.3.2", + "tslib": "^2.5.3" + } + }, + "@polkadot/networks": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/@polkadot/networks/-/networks-12.3.2.tgz", + "integrity": "sha512-uCkyybKoeEm1daKr0uT/9oNDHDDzCy2/ZdVl346hQqfdR1Ct3BaxMjxqvdmb5N8aCw0cBWSfgsxAYtw8ESmllQ==", + "requires": { + "@polkadot/util": "12.3.2", + "@substrate/ss58-registry": "^1.40.0", + "tslib": "^2.5.3" + } + }, + "@polkadot/rpc-augment": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/@polkadot/rpc-augment/-/rpc-augment-10.9.1.tgz", + "integrity": "sha512-MaLHkNlyqN20ZRYr6uNd1BZr1OsrnX9qLAmsl0mcrri1vPGRH6VHjfFH1RBLkikpWD82v17g0l2hLwdV1ZHMcw==", + "requires": { + "@polkadot/rpc-core": "10.9.1", + "@polkadot/types": "10.9.1", + "@polkadot/types-codec": "10.9.1", + "@polkadot/util": "^12.3.1", + "tslib": "^2.5.3" + } + }, + "@polkadot/rpc-core": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/@polkadot/rpc-core/-/rpc-core-10.9.1.tgz", + "integrity": "sha512-ZtA8B8SfXSAwVkBlCcKRHw0eSM7ec/sbiNOM5GasXPeRujUgT7lOwSH2GbUZSqe9RfRDMp6DvO9c2JoGc3LLWw==", + "requires": { + "@polkadot/rpc-augment": "10.9.1", + "@polkadot/rpc-provider": "10.9.1", + "@polkadot/types": "10.9.1", + "@polkadot/util": "^12.3.1", + "rxjs": "^7.8.1", + "tslib": "^2.5.3" + } + }, + "@polkadot/rpc-provider": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/@polkadot/rpc-provider/-/rpc-provider-10.9.1.tgz", + "integrity": "sha512-4QzT2QzD+320+eT6b79sGAA85Tt3Bb8fQvse4r5Mom2iiBd2SO81vOhxSAOaIe4GUsw25VzFJmsbe7+OObItdg==", + "requires": { + "@polkadot/keyring": "^12.3.1", + "@polkadot/types": "10.9.1", + "@polkadot/types-support": "10.9.1", + "@polkadot/util": "^12.3.1", + "@polkadot/util-crypto": "^12.3.1", + "@polkadot/x-fetch": "^12.3.1", + "@polkadot/x-global": "^12.3.1", + "@polkadot/x-ws": "^12.3.1", + "@substrate/connect": "0.7.26", + "eventemitter3": "^5.0.1", + "mock-socket": "^9.2.1", + "nock": "^13.3.1", + "tslib": "^2.5.3" + } + }, + "@polkadot/types": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/@polkadot/types/-/types-10.9.1.tgz", + "integrity": "sha512-AG33i2ZGGfq7u+5rkAdGrXAQHHl844/Yv+junH5ZzX69xiCoWO1bH/yzDUNBdpki2GlACWvF9nLYh3F2tVF93w==", + "requires": { + "@polkadot/keyring": "^12.3.1", + "@polkadot/types-augment": "10.9.1", + "@polkadot/types-codec": "10.9.1", + "@polkadot/types-create": "10.9.1", + "@polkadot/util": "^12.3.1", + "@polkadot/util-crypto": "^12.3.1", + "rxjs": "^7.8.1", + "tslib": "^2.5.3" + } + }, + "@polkadot/types-augment": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/@polkadot/types-augment/-/types-augment-10.9.1.tgz", + "integrity": "sha512-OY9/jTMFRFqYdkUnfcGwqMLC64A0Q25bjvCuVQCVjsPFKE3wl0Kt5rNT01eV2UmLXrR6fY0xWbR2w80bLA7CIQ==", + "requires": { + "@polkadot/types": "10.9.1", + "@polkadot/types-codec": "10.9.1", + "@polkadot/util": "^12.3.1", + "tslib": "^2.5.3" + } + }, + "@polkadot/types-codec": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/@polkadot/types-codec/-/types-codec-10.9.1.tgz", + "integrity": "sha512-mJ5OegKGraY1FLvEa8FopRCr3pQrhDkcn5RNOjmgJQozENVeRaxhk0NwxYz7IojFvSDnKnc6lNQfKaaSe5pLHg==", + "requires": { + "@polkadot/util": "^12.3.1", + "@polkadot/x-bigint": "^12.3.1", + "tslib": "^2.5.3" + } + }, + "@polkadot/types-create": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/@polkadot/types-create/-/types-create-10.9.1.tgz", + "integrity": "sha512-OVz50MGTTuiuVnRP/zAx4CTuLioc0hsiwNwqN2lNhmIJGtnQ4Vy/7mQRsIWehiYz6g0Vzzm5B3qWkTXO1NSN5w==", + "requires": { + "@polkadot/types-codec": "10.9.1", + "@polkadot/util": "^12.3.1", + "tslib": "^2.5.3" + } + }, + "@polkadot/types-known": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/@polkadot/types-known/-/types-known-10.9.1.tgz", + "integrity": "sha512-zCMVWc4pJtkbMFPu72bD4IhvV/gkHXPX3C5uu92WdmCfnn0vEIEsMKWlVXVVvQQZKAqvs/awpqIfrUtEViOGEA==", + "requires": { + "@polkadot/networks": "^12.3.1", + "@polkadot/types": "10.9.1", + "@polkadot/types-codec": "10.9.1", + "@polkadot/types-create": "10.9.1", + "@polkadot/util": "^12.3.1", + "tslib": "^2.5.3" + } + }, + "@polkadot/types-support": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/@polkadot/types-support/-/types-support-10.9.1.tgz", + "integrity": "sha512-XsieuLDsszvMZQlleacQBfx07i/JkwQV/UxH9q8Hz7Okmaz9pEVEW1h3ka2/cPuC7a4l32JhaORBUYshBZNdJg==", + "requires": { + "@polkadot/util": "^12.3.1", + "tslib": "^2.5.3" + } + }, + "@polkadot/util": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/@polkadot/util/-/util-12.3.2.tgz", + "integrity": "sha512-y/JShcGyOamCUiSIg++XZuLHt1ktSKBaSH2K5Nw5NXlgP0+7am+GZzqPB8fQ4qhYLruEOv+YRiz0GC1Zr9S+wg==", + "requires": { + "@polkadot/x-bigint": "12.3.2", + "@polkadot/x-global": "12.3.2", + "@polkadot/x-textdecoder": "12.3.2", + "@polkadot/x-textencoder": "12.3.2", + "@types/bn.js": "^5.1.1", + "bn.js": "^5.2.1", + "tslib": "^2.5.3" + } + }, + "@polkadot/util-crypto": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/@polkadot/util-crypto/-/util-crypto-12.3.2.tgz", + "integrity": "sha512-pTpx+YxolY0BDT4RcGmgeKbHHD/dI6Ll9xRsqmVdIjpcVVY20uDNTyXs81ZNtfKgyod1y9JQkfNv2Dz9iEpTkQ==", + "requires": { + "@noble/curves": "1.1.0", + "@noble/hashes": "1.3.1", + "@polkadot/networks": "12.3.2", + "@polkadot/util": "12.3.2", + "@polkadot/wasm-crypto": "^7.2.1", + "@polkadot/wasm-util": "^7.2.1", + "@polkadot/x-bigint": "12.3.2", + "@polkadot/x-randomvalues": "12.3.2", + "@scure/base": "1.1.1", + "tslib": "^2.5.3" + } + }, + "@polkadot/wasm-bridge": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/@polkadot/wasm-bridge/-/wasm-bridge-7.2.1.tgz", + "integrity": "sha512-uV/LHREDBGBbHrrv7HTki+Klw0PYZzFomagFWII4lp6Toj/VCvRh5WMzooVC+g/XsBGosAwrvBhoModabyHx+A==", + "requires": { + "@polkadot/wasm-util": "7.2.1", + "tslib": "^2.5.0" + } + }, + "@polkadot/wasm-crypto": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/@polkadot/wasm-crypto/-/wasm-crypto-7.2.1.tgz", + "integrity": "sha512-SA2+33S9TAwGhniKgztVN6pxUKpGfN4Tre/eUZGUfpgRkT92wIUT2GpGWQE+fCCqGQgADrNiBcwt6XwdPqMQ4Q==", + "requires": { + "@polkadot/wasm-bridge": "7.2.1", + "@polkadot/wasm-crypto-asmjs": "7.2.1", + "@polkadot/wasm-crypto-init": "7.2.1", + "@polkadot/wasm-crypto-wasm": "7.2.1", + "@polkadot/wasm-util": "7.2.1", + "tslib": "^2.5.0" + } + }, + "@polkadot/wasm-crypto-asmjs": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/@polkadot/wasm-crypto-asmjs/-/wasm-crypto-asmjs-7.2.1.tgz", + "integrity": "sha512-z/d21bmxyVfkzGsKef/FWswKX02x5lK97f4NPBZ9XBeiFkmzlXhdSnu58/+b1sKsRAGdW/Rn/rTNRDhW0GqCAg==", + "requires": { + "tslib": "^2.5.0" + } + }, + "@polkadot/wasm-crypto-init": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/@polkadot/wasm-crypto-init/-/wasm-crypto-init-7.2.1.tgz", + "integrity": "sha512-GcEXtwN9LcSf32V9zSaYjHImFw16hCyo2Xzg4GLLDPPeaAAfbFr2oQMgwyDbvBrBjLKHVHjsPZyGhXae831amw==", + "requires": { + "@polkadot/wasm-bridge": "7.2.1", + "@polkadot/wasm-crypto-asmjs": "7.2.1", + "@polkadot/wasm-crypto-wasm": "7.2.1", + "@polkadot/wasm-util": "7.2.1", + "tslib": "^2.5.0" + } + }, + "@polkadot/wasm-crypto-wasm": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/@polkadot/wasm-crypto-wasm/-/wasm-crypto-wasm-7.2.1.tgz", + "integrity": "sha512-DqyXE4rSD0CVlLIw88B58+HHNyrvm+JAnYyuEDYZwCvzUWOCNos/DDg9wi/K39VAIsCCKDmwKqkkfIofuOj/lA==", + "requires": { + "@polkadot/wasm-util": "7.2.1", + "tslib": "^2.5.0" + } + }, + "@polkadot/wasm-util": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/@polkadot/wasm-util/-/wasm-util-7.2.1.tgz", + "integrity": "sha512-FBSn/3aYJzhN0sYAYhHB8y9JL8mVgxLy4M1kUXYbyo+8GLRQEN5rns8Vcb8TAlIzBWgVTOOptYBvxo0oj0h7Og==", + "requires": { + "tslib": "^2.5.0" + } + }, + "@polkadot/x-bigint": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/@polkadot/x-bigint/-/x-bigint-12.3.2.tgz", + "integrity": "sha512-JLqLgfGXe/x+hZJETd5ZqfpVsbwyMsH5Nn1Q20ineMMjXN/ig+kVR8Mc15LXBMuw4g7LldFW6UUrotWnuMI8Yw==", + "requires": { + "@polkadot/x-global": "12.3.2", + "tslib": "^2.5.3" + } + }, + "@polkadot/x-fetch": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/@polkadot/x-fetch/-/x-fetch-12.3.2.tgz", + "integrity": "sha512-3IEuZ5S+RI/t33NsdPLIIa5COfDCfpUW2sbaByEczn75aD1jLqJZSEDwiBniJ2osyNd4uUxBf6e5jw7LAZeZJg==", + "requires": { + "@polkadot/x-global": "12.3.2", + "node-fetch": "^3.3.1", + "tslib": "^2.5.3" + } + }, + "@polkadot/x-global": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/@polkadot/x-global/-/x-global-12.3.2.tgz", + "integrity": "sha512-yVZq6oIegjlyh5rUZiTklgu+fL+W/DG1ypEa02683tUCB3avV5cA3PAHKptMSlb6FpweHu37lKKrqfAWrraDxg==", + "requires": { + "tslib": "^2.5.3" + } + }, + "@polkadot/x-randomvalues": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/@polkadot/x-randomvalues/-/x-randomvalues-12.3.2.tgz", + "integrity": "sha512-ywjIs8CWpvOGmq+3cGCNPOHxAjPHdBUiXyDccftx5BRVdmtbt36gK/V84bKr6Xs73FGu0jprUAOSRRsLZX/3dg==", + "requires": { + "@polkadot/x-global": "12.3.2", + "tslib": "^2.5.3" + } + }, + "@polkadot/x-textdecoder": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/@polkadot/x-textdecoder/-/x-textdecoder-12.3.2.tgz", + "integrity": "sha512-lY5bfA5xArJRWEJlYOlQQMJeTjWD8s0yMhchirVgf5xj8Id9vPGeUoneH+VFDEwgXxrqBvDFJ4smN4T/r6a/fg==", + "requires": { + "@polkadot/x-global": "12.3.2", + "tslib": "^2.5.3" + } + }, + "@polkadot/x-textencoder": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/@polkadot/x-textencoder/-/x-textencoder-12.3.2.tgz", + "integrity": "sha512-iP3qEBiHzBckQ9zeY7ZHRWuu7mCEg5SMpOugs6UODRk8sx6KHzGQYlghBbWLit0uppPDVE0ifEwZ2n73djJHWQ==", + "requires": { + "@polkadot/x-global": "12.3.2", + "tslib": "^2.5.3" + } + }, + "@polkadot/x-ws": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/@polkadot/x-ws/-/x-ws-12.3.2.tgz", + "integrity": "sha512-yM9Z64pLNlHpJE43+Xtr+iUXmYpFFY5u5hrke2PJt13O48H8f9Vb9cRaIh94appLyICoS0aekGhDkGH+MCspBA==", + "requires": { + "@polkadot/x-global": "12.3.2", + "tslib": "^2.5.3", + "ws": "^8.13.0" + } + }, + "@scure/base": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.1.tgz", + "integrity": "sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA==" + }, + "@substrate/connect": { + "version": "0.7.26", + "resolved": "https://registry.npmjs.org/@substrate/connect/-/connect-0.7.26.tgz", + "integrity": "sha512-uuGSiroGuKWj1+38n1kY5HReer5iL9bRwPCzuoLtqAOmI1fGI0hsSI2LlNQMAbfRgr7VRHXOk5MTuQf5ulsFRw==", + "optional": true, + "requires": { + "@substrate/connect-extension-protocol": "^1.0.1", + "eventemitter3": "^4.0.7", + "smoldot": "1.0.4" + }, + "dependencies": { + "eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "optional": true + } + } + }, + "@substrate/connect-extension-protocol": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@substrate/connect-extension-protocol/-/connect-extension-protocol-1.0.1.tgz", + "integrity": "sha512-161JhCC1csjH3GE5mPLEd7HbWtwNSPJBg3p1Ksz9SFlTzj/bgEwudiRN2y5i0MoLGCIJRYKyKGMxVnd29PzNjg==", + "optional": true + }, + "@substrate/ss58-registry": { + "version": "1.40.0", + "resolved": "https://registry.npmjs.org/@substrate/ss58-registry/-/ss58-registry-1.40.0.tgz", + "integrity": "sha512-QuU2nBql3J4KCnOWtWDw4n1K4JU0T79j54ZZvm/9nhsX6AIar13FyhsaBfs6QkJ2ixTQAnd7TocJIoJRWbqMZA==" + }, + "@types/bn.js": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.1.tgz", + "integrity": "sha512-qNrYbZqMx0uJAfKnKclPh+dTwK33KfLHYqtyODwd5HnXOjnkhc4qgn3BrK6RWyGZm5+sIFE7Q7Vz6QQtJB7w7g==", + "requires": { + "@types/node": "*" + } + }, + "@types/node": { + "version": "20.3.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.3.1.tgz", + "integrity": "sha512-EhcH/wvidPy1WeML3TtYFGR83UzjxeWRen9V402T8aUGYsCHOmfoisV3ZSg03gAFIbLq8TnWOJ0f4cALtnSEUg==" + }, + "bn.js": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", + "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==" + }, + "data-uri-to-buffer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==" + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "requires": { + "ms": "2.1.2" + } + }, + "eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==" + }, + "fetch-blob": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", + "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", + "requires": { + "node-domexception": "^1.0.0", + "web-streams-polyfill": "^3.0.3" + } + }, + "formdata-polyfill": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "requires": { + "fetch-blob": "^3.1.2" + } + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==" + }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "mock-socket": { + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/mock-socket/-/mock-socket-9.2.1.tgz", + "integrity": "sha512-aw9F9T9G2zpGipLLhSNh6ZpgUyUl4frcVmRN08uE1NWPWg43Wx6+sGPDbQ7E5iFZZDJW5b5bypMeAEHqTbIFag==" + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "nock": { + "version": "13.3.1", + "resolved": "https://registry.npmjs.org/nock/-/nock-13.3.1.tgz", + "integrity": "sha512-vHnopocZuI93p2ccivFyGuUfzjq2fxNyNurp7816mlT5V5HF4SzXu8lvLrVzBbNqzs+ODooZ6OksuSUNM7Njkw==", + "requires": { + "debug": "^4.1.0", + "json-stringify-safe": "^5.0.1", + "lodash": "^4.17.21", + "propagate": "^2.0.0" + } + }, + "node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==" + }, + "node-fetch": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.1.tgz", + "integrity": "sha512-cRVc/kyto/7E5shrWca1Wsea4y6tL9iYJE5FBCius3JQfb/4P4I295PfhgbJQBLTx6lATE4z+wK0rPM4VS2uow==", + "requires": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + } + }, + "pako": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/pako/-/pako-2.1.0.tgz", + "integrity": "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==", + "optional": true + }, + "propagate": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/propagate/-/propagate-2.0.1.tgz", + "integrity": "sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag==" + }, + "rxjs": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "requires": { + "tslib": "^2.1.0" + } + }, + "smoldot": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/smoldot/-/smoldot-1.0.4.tgz", + "integrity": "sha512-N3TazI1C4GGrseFH/piWyZCCCRJTRx2QhDfrUKRT4SzILlW5m8ayZ3QTKICcz1C/536T9cbHHJyP7afxI6Mi1A==", + "optional": true, + "requires": { + "pako": "^2.0.4", + "ws": "^8.8.1" + } + }, + "tslib": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.3.tgz", + "integrity": "sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w==" + }, + "web-streams-polyfill": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz", + "integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==" + }, + "ws": { + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", + "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==", + "requires": {} + } + } +} diff --git a/bitacross-worker/scripts/test_transfer/package.json b/bitacross-worker/scripts/test_transfer/package.json new file mode 100644 index 0000000000..a3e2b769b8 --- /dev/null +++ b/bitacross-worker/scripts/test_transfer/package.json @@ -0,0 +1,16 @@ +{ + "name": "test_transfer", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "ISC", + "dependencies": { + "@polkadot/api": "^10.9.1", + "@polkadot/keyring": "^12.3.2", + "@polkadot/util-crypto": "^12.3.2" + } +} diff --git a/bitacross-worker/scripts/test_transfer/transfer.js b/bitacross-worker/scripts/test_transfer/transfer.js new file mode 100644 index 0000000000..6d45154008 --- /dev/null +++ b/bitacross-worker/scripts/test_transfer/transfer.js @@ -0,0 +1,53 @@ +// Import the API & Provider and some utility functions +const { ApiPromise } = require('@polkadot/api'); + +const { Keyring } = require('@polkadot/keyring'); + +// Utility function for random values +const { randomAsU8a } = require('@polkadot/util-crypto'); + +// Some constants we are using in this sample +const AMOUNT = 1000000000000; + +async function main () { + // Create the API and wait until ready + const api = await ApiPromise.create(); + + // Create an instance of a testing keyring + const keyring = new Keyring({ type: 'sr25519', ss58Format: 42 }); + const alice = keyring.addFromUri('//Alice'); + + // Access the publicKey and address + const { publicKey, address } = alice; + + console.log('Alice Public Key:', publicKey); + console.log('Alice Address:', address); + + const { nonce, data: balance } = await api.query.system.account(publicKey); + + // Create a new random recipient + const recipient = keyring.addFromSeed(randomAsU8a(32)).address; + + console.log('Sending', AMOUNT, 'from', address, 'who has a balance of', balance.free, 'to', recipient, 'with nonce', nonce.toString()); + + api.tx.balances + .transfer(recipient, AMOUNT) + .signAndSend(alice, { nonce }, ({ events = [], status }) => { + console.log('Transaction status:', status.type); + + if (status.isInBlock) { + console.log('Included at block hash', status.asInBlock.toHex()); + console.log('Events:'); + + events.forEach(({ event: { data, method, section }, phase }) => { + console.log('\t', phase.toString(), `: ${section}.${method}`, data.toString()); + }); + } else if (status.isFinalized) { + console.log('Finalized block hash', status.asFinalized.toHex()); + + process.exit(0); + } + }); +} + +main().catch(console.error); diff --git a/bitacross-worker/service/Cargo.toml b/bitacross-worker/service/Cargo.toml new file mode 100644 index 0000000000..f076e26cf5 --- /dev/null +++ b/bitacross-worker/service/Cargo.toml @@ -0,0 +1,107 @@ +[package] +name = 'bitacross-worker' +version = '0.0.1' +authors = ['Trust Computing GmbH ', 'Integritee AG '] +build = 'build.rs' +edition = '2021' + +[dependencies] +async-trait = "0.1.50" +base58 = "0.2" +clap = { version = "2.33", features = ["yaml"] } +dirs = "3.0.2" +env_logger = "0.9" +futures = "0.3" +hex = "0.4.3" +jsonrpsee = { version = "0.2.0", features = ["client", "ws-server", "macros"] } +lazy_static = "1.4.0" +log = "0.4" +parking_lot = "0.12.1" +parse_duration = "2.1.1" +# for litentry-parachain: otherwise we have a conflict in substrate-prometheus-endpoint +prometheus = { version = "0.13.0", default-features = false, features = ["process"] } +regex = "1.9.5" +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } +serde = "1.0" +serde_derive = "1.0" +serde_json = "1.0" +thiserror = "1.0" +tokio = { version = "1.6.1", features = ["full"] } +warp = "0.3" + +# ipfs +ipfs-api = "0.11.0" + +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +primitive-types = { version = "0.12.1", default-features = false, features = ["codec"] } + +sgx_crypto_helper = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git" } +sgx_types = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git" } + +# local +itc-parentchain = { path = "../core/parentchain/parentchain-crate" } +itc-rest-client = { path = "../core/rest-client" } +itc-rpc-client = { path = "../core/rpc-client" } +itc-rpc-server = { path = "../core/rpc-server" } +itp-api-client-types = { path = "../core-primitives/node-api/api-client-types" } +itp-enclave-api = { path = "../core-primitives/enclave-api" } +itp-enclave-metrics = { path = "../core-primitives/enclave-metrics" } +itp-node-api = { path = "../core-primitives/node-api" } +itp-settings = { path = "../core-primitives/settings" } +itp-storage = { path = "../core-primitives/storage" } +itp-types = { path = "../core-primitives/types" } +itp-utils = { path = "../core-primitives/utils" } +its-consensus-slots = { path = "../sidechain/consensus/slots" } +its-peer-fetch = { path = "../sidechain/peer-fetch" } +its-primitives = { path = "../sidechain/primitives" } +its-rpc-handler = { path = "../sidechain/rpc-handler" } +its-storage = { path = "../sidechain/storage" } + +# `default-features = false` to remove the jsonrpsee dependency. +substrate-api-client = { default-features = false, features = ["std", "sync-api"], git = "https://github.com/scs/substrate-api-client.git", branch = "polkadot-v0.9.42-tag-v0.14.0" } + +# Substrate dependencies +frame-support = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } +pallet-balances = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } +sp-consensus-grandpa = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } +sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42", features = ["full_crypto"] } +sp-keyring = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } +sp-runtime = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } + +# litentry +config = "0.13.3" +ita-stf = { path = "../app-libs/stf", default-features = false } +litentry-primitives = { path = "../litentry/primitives" } +my-node-runtime = { package = "rococo-parachain-runtime", path = "../../runtime/rococo" } +sgx-verify = { path = "../../pallets/teerex/sgx-verify", default-features = false } +teerex-primitives = { path = "../../primitives/teerex", default-features = false } + +[features] +default = [] +evm = [] +sidechain = ["itp-settings/sidechain"] +offchain-worker = ["itp-settings/offchain-worker"] +production = ["itp-settings/production"] +teeracle = ["itp-settings/teeracle"] +dcap = [] +attesteer = ["dcap"] +# Must be enabled to build a binary and link it with the enclave successfully. +# This flag is set in the makefile. +# +# Must not be enabled to run cargo test without an sgx-sdk providing environment +# https://github.com/rust-lang/cargo/issues/2549. +# +# It has been chosen to not make this a default feature because this makes test execution +# more ergonomic as we can simply do `cargo test` on the whole workspace like this. +link-binary = [ + "itp-enclave-api/implement-ffi", +] + +[dev-dependencies] +# crates.io +anyhow = "1.0.40" +mockall = "0.11" +# local +itc-parentchain-test = { path = "../core/parentchain/test" } +its-peer-fetch = { path = "../sidechain/peer-fetch", features = ["mocks"] } +its-test = { path = "../sidechain/test" } diff --git a/bitacross-worker/service/build.rs b/bitacross-worker/service/build.rs new file mode 100644 index 0000000000..1fb664ecc0 --- /dev/null +++ b/bitacross-worker/service/build.rs @@ -0,0 +1,31 @@ +// Copyright (C) 2017-2018 Baidu, Inc. All Rights Reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in +// the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Baidu, Inc., nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +fn main() { + // All the linker options are now defined in `itp-enclave-api-ffi` +} diff --git a/bitacross-worker/service/src/account_funding.rs b/bitacross-worker/service/src/account_funding.rs new file mode 100644 index 0000000000..20f3f14a77 --- /dev/null +++ b/bitacross-worker/service/src/account_funding.rs @@ -0,0 +1,168 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::error::{Error, ServiceResult}; +use itp_node_api::api_client::{AccountApi, ParentchainApi}; +use itp_settings::worker::{ + EXISTENTIAL_DEPOSIT_FACTOR_FOR_INIT_FUNDS, REGISTERING_FEE_FACTOR_FOR_INIT_FUNDS, +}; +use itp_types::parentchain::Balance; +use log::*; +use sp_core::{ + crypto::{AccountId32, Ss58Codec}, + Pair, +}; +use sp_keyring::AccountKeyring; +use sp_runtime::MultiAddress; +use substrate_api_client::{ + extrinsic::BalancesExtrinsics, GetBalance, GetTransactionPayment, SubmitAndWatch, XtStatus, +}; + +/// Information about the enclave on-chain account. +pub trait EnclaveAccountInfo { + fn free_balance(&self) -> ServiceResult; +} + +pub struct EnclaveAccountInfoProvider { + node_api: ParentchainApi, + account_id: AccountId32, +} + +impl EnclaveAccountInfo for EnclaveAccountInfoProvider { + fn free_balance(&self) -> ServiceResult { + self.node_api.get_free_balance(&self.account_id).map_err(|e| e.into()) + } +} + +impl EnclaveAccountInfoProvider { + pub fn new(node_api: ParentchainApi, account_id: AccountId32) -> Self { + EnclaveAccountInfoProvider { node_api, account_id } + } +} + +pub fn setup_account_funding( + api: &ParentchainApi, + accountid: &AccountId32, + encoded_extrinsic: Vec, + is_development_mode: bool, +) -> ServiceResult<()> { + // Account funds + if is_development_mode { + // Development mode, the faucet will ensure that the enclave has enough funds + ensure_account_has_funds(api, accountid)?; + } else { + // Production mode, there is no faucet. + let registration_fees = enclave_registration_fees(api, encoded_extrinsic)?; + info!("Registration fees = {:?}", registration_fees); + let free_balance = api.get_free_balance(accountid)?; + info!("TEE's free balance = {:?}", free_balance); + + let min_required_funds = + registration_fees.saturating_mul(REGISTERING_FEE_FACTOR_FOR_INIT_FUNDS); + let missing_funds = min_required_funds.saturating_sub(free_balance); + + if missing_funds > 0 { + // If there are not enough funds, then the user can send the missing TEER to the enclave address and start again. + println!( + "Enclave account: {:}, missing funds {}", + accountid.to_ss58check(), + missing_funds + ); + return Err(Error::Custom( + "Enclave does not have enough funds on the parentchain to register.".into(), + )) + } + } + Ok(()) +} + +// Alice plays the faucet and sends some funds to the account if balance is low +fn ensure_account_has_funds(api: &ParentchainApi, accountid: &AccountId32) -> Result<(), Error> { + // check account balance + let free_balance = api.get_free_balance(accountid)?; + info!("TEE's free balance = {:?} (Account: {})", free_balance, accountid); + + let existential_deposit = api.get_existential_deposit()?; + info!("Existential deposit is = {:?}", existential_deposit); + + let min_required_funds = + existential_deposit.saturating_mul(EXISTENTIAL_DEPOSIT_FACTOR_FOR_INIT_FUNDS); + let missing_funds = min_required_funds.saturating_sub(free_balance); + + if missing_funds > 0 { + info!("Transfer {:?} from Alice to {}", missing_funds, accountid); + bootstrap_funds_from_alice(api, accountid, missing_funds)?; + } + Ok(()) +} + +fn enclave_registration_fees( + api: &ParentchainApi, + encoded_extrinsic: Vec, +) -> Result { + let reg_fee_details = api.get_fee_details(&encoded_extrinsic.into(), None)?; + match reg_fee_details { + Some(details) => match details.inclusion_fee { + Some(fee) => Ok(fee.inclusion_fee()), + None => Err(Error::Custom( + "Inclusion fee for the registration of the enclave is None!".into(), + )), + }, + None => + Err(Error::Custom("Fee Details for the registration of the enclave is None !".into())), + } +} + +// Alice sends some funds to the account +fn bootstrap_funds_from_alice( + api: &ParentchainApi, + accountid: &AccountId32, + funding_amount: u128, +) -> Result<(), Error> { + let alice = AccountKeyring::Alice.pair(); + let alice_acc = AccountId32::from(*alice.public().as_array_ref()); + + let alice_free = api.get_free_balance(&alice_acc)?; + info!(" Alice's free balance = {:?}", alice_free); + let nonce = api.get_account_next_index(&alice_acc)?; + info!(" Alice's Account Nonce is {}", nonce); + + if funding_amount > alice_free { + println!( + "funding amount is too high: please change EXISTENTIAL_DEPOSIT_FACTOR_FOR_INIT_FUNDS ({:?})", + funding_amount + ); + return Err(Error::ApplicationSetup) + } + + let mut alice_signer_api = api.clone(); + alice_signer_api.set_signer(alice.into()); + + println!("[+] send extrinsic: bootstrap funding Enclave from Alice's funds"); + let xt = alice_signer_api + .balance_transfer_allow_death(MultiAddress::Id(accountid.clone()), funding_amount); + let xt_report = alice_signer_api.submit_and_watch_extrinsic_until(xt, XtStatus::InBlock)?; + info!( + "[<] L1 extrinsic success. extrinsic hash: {:?} / status: {:?}", + xt_report.extrinsic_hash, xt_report.status + ); + // Verify funds have arrived. + let free_balance = alice_signer_api.get_free_balance(accountid); + trace!("TEE's NEW free balance = {:?}", free_balance); + + Ok(()) +} diff --git a/bitacross-worker/service/src/cli.yml b/bitacross-worker/service/src/cli.yml new file mode 100644 index 0000000000..e517e6b1bb --- /dev/null +++ b/bitacross-worker/service/src/cli.yml @@ -0,0 +1,227 @@ +name: "litentry-worker" +version: "0.0.1" +about: Worker using Intel SGX TEE for litentry parachain node +authors: "Trust Computing GmbH " + +# AppSettings can be defined as a list and are **not** ascii case sensitive +settings: + - ColoredHelp + - SubcommandRequired + +# All subcommands must be listed in the 'subcommand:' object, where the key to +# the list is the name of the subcommand, and all settings for that command are +# part of a Hash +args: + - node-url: + short: u + long: node-url + help: Set the url and the protocol of the RPC endpoint. + takes_value: true + default_value: "ws://127.0.0.1" + - node-port: + short: p + long: node-port + help: Set the port of the RPC endpoint. + takes_value: true + default_value: "9944" + - target-a-parentchain-rpc-url: + long: target-a-parentchain-rpc-url + help: Set the url and the protocol of an optional Target A parentchain RPC endpoint that contains your business logic specific pallets. + takes_value: true + required: false + - target-a-parentchain-rpc-port: + long: target-a-parentchain-rpc-port + help: Set the port of the optional Target A parentchain RPC endpoint. + takes_value: true + required: false + - target-b-parentchain-rpc-url: + long: target-b-parentchain-rpc-url + help: Set the url and the protocol of an optional Target B parentchain RPC endpoint that contains your business logic specific pallets. + takes_value: true + required: false + - target-b-parentchain-rpc-port: + long: target-b-parentchain-rpc-port + help: Set the port of the optional Target B parentchain RPC endpoint. + takes_value: true + required: false + - data-dir: + short: d + long: data-dir + help: Data dir where the worker stores it's keys and other data. + takes_value: true + - ws-external: + long: ws-external + help: Set this flag in case the worker should listen to external requests. + - mu-ra-port: + short: r + long: mu-ra-port + help: Set the websocket port to listen for mu-ra requests + takes_value: true + default_value: "3443" + - trusted-worker-port: + short: P + long: trusted-worker-port + help: Set the trusted websocket port of the worker, running directly in the enclave. + takes_value: true + default_value: "2000" + - untrusted-worker-port: + short: w + long: untrusted-worker-port + help: Set the untrusted websocket port of the worker + takes_value: true + default_value: "2001" + - trusted-external-address: + short: T + long: trusted-external-address + help: Set the trusted worker address to be advertised on the parentchain. If no port is given, the same as in `trusted-worker-port` will be used. + takes_value: true + required: false + - untrusted-external-address: + short: U + long: untrusted-external-address + help: Set the untrusted worker address to be retrieved by a trusted rpc call. If no port is given, the same as in `untrusted-worker-port` will be used. + takes_value: true + required: false + - mu-ra-external-address: + short: M + long: mu-ra-external-address + help: Set the mutual remote attestation worker address to be retrieved by a trusted rpc call. If no port is given, the same as in `mu-ra-port` will be used. + takes_value: true + required: false + - enable-metrics: + long: enable-metrics + help: Enable the metrics HTTP server to serve metrics + - metrics-port: + short: i + long: metrics-port + help: Set the port on which the metrics are served. + takes_value: true + default_value: "8787" + required: false + - untrusted-http-port: + short: h + long: untrusted-http-port + help: Set the port for the untrusted HTTP server + takes_value: true + required: false + - clean-reset: + long: clean-reset + short: c + help: Cleans and purges any previous state and key files and generates them anew before starting. + - parentchain-start-block: + long: parentchain-start-block + help: Set the parentchain block number to start syncing with + takes_value: true + required: false + default_value: "0" + - fail-slot-mode: + long: fail-slot-mode + help: Set the mode of failing a slot, values [BeforeOnSlot, AfterOnSlot] + takes_value: true + required: false + - fail-at: + long: fail-at + help: Set the slot to fail on + takes_value: true + required: false + default_value: "0" + +subcommands: + - run: + about: Start the litentry-worker + args: + - skip-ra: + long: skip-ra + help: skip remote attestation. Set this flag if running enclave in SW mode + - shard: + required: false + index: 1 + help: shard identifier base58 encoded. Defines the state that this worker shall operate on. Default is mrenclave + - dev: + long: dev + short: d + help: Set this flag if running in development mode to bootstrap enclave account on parentchain via //Alice. + - request-state: + long: request-state + short: r + help: Run the worker and request key and state provisioning from another worker. + - teeracle-interval: + required: false + long: teeracle-interval + short: i + help: Set the teeracle exchange rate update interval. Example of accepted syntax <5 seconds 15 minutes 2 hours 1 days> or short <5s15m2h1d> + takes_value: true + - reregister-teeracle-interval: + required: false + long: reregister + help: Set the teeracle reregistration interval. Example of accepted syntax <5 seconds 15 minutes 2 hours 1 days> or short <5s15m2h1d> + takes_value: true + - request-state: + about: join a shard by requesting key provisioning from another worker + args: + - shard: + long: shard + required: false + help: shard identifier base58 encoded. Defines the state that this worker shall operate on. Default is mrenclave + - skip-ra: + long: skip-ra + help: skip remote attestation. Set this flag if running enclave in SW mode + - shielding-key: + about: Get the public RSA3072 key from the TEE to be used to encrypt requests + - signing-key: + about: Get the public ed25519 key the TEE uses to sign messages and extrinsics + - dump-ra: + about: Perform RA and dump cert to disk + - mrenclave: + about: Dump mrenclave to stdout. base58 encoded. + - init-shard: + about: Initialize new shard (do this only if you run the first worker for that shard). if shard is not specified, the MRENCLAVE is used instead + args: + - shard: + required: false + multiple: true + index: 1 + help: shard identifier base58 encoded + - migrate-shard: + about: Migrate shard + args: + - old-shard: + long: old-shard + help: shard identifier hex encoded + takes_value: true + - new-shard: + long: new-shard + help: shard identifier hex encoded + takes_value: true + - test: + about: Run tests involving the enclave + takes_value: true + args: + - all: + short: a + long: all + help: Run all tests (beware, all corrupts the counter state for some whatever reason...) + takes_value: false + - unit: + short: u + long: unit + help: Run unit tests + takes_value: false + - ecall: + short: e + long: ecall + help: Run enclave ecall tests + takes_value: false + - integration: + short: i + long: integration + help: Run integration tests + takes_value: false + - provisioning-server: + long: provisioning-server + help: Run TEE server for MU-RA key provisioning + takes_value: false + - provisioning-client: + long: provisioning-client + help: Run TEE client for MU-RA key provisioning + takes_value: false diff --git a/bitacross-worker/service/src/config.rs b/bitacross-worker/service/src/config.rs new file mode 100644 index 0000000000..bc9b8b7cdb --- /dev/null +++ b/bitacross-worker/service/src/config.rs @@ -0,0 +1,641 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 clap::ArgMatches; +use itc_rest_client::rest_client::Url; +use itp_settings::teeracle::{DEFAULT_MARKET_DATA_UPDATE_INTERVAL, ONE_DAY, THIRTY_MINUTES}; +use parse_duration::parse; +use serde::{Deserialize, Serialize}; +use std::{ + fs, + path::{Path, PathBuf}, + time::Duration, +}; + +static DEFAULT_NODE_URL: &str = "ws://127.0.0.1"; +static DEFAULT_NODE_PORT: &str = "9944"; +static DEFAULT_TRUSTED_PORT: &str = "2000"; +static DEFAULT_UNTRUSTED_PORT: &str = "2001"; +static DEFAULT_MU_RA_PORT: &str = "3443"; +static DEFAULT_METRICS_PORT: &str = "8787"; +static DEFAULT_UNTRUSTED_HTTP_PORT: &str = "4545"; +static DEFAULT_PARENTCHAIN_START_BLOCK: &str = "0"; +static DEFAULT_FAIL_AT: &str = "0"; + +#[derive(Clone, Debug, PartialEq)] +pub struct Config { + pub litentry_rpc_url: String, + pub litentry_rpc_port: String, + pub target_a_parentchain_rpc_url: Option, + pub target_a_parentchain_rpc_port: Option, + pub target_b_parentchain_rpc_url: Option, + pub target_b_parentchain_rpc_port: Option, + pub worker_ip: String, + /// Trusted worker address that will be advertised on the parentchain. + pub trusted_external_worker_address: Option, + /// Port to directly communicate with the trusted tls server inside the enclave. + pub trusted_worker_port: String, + /// Untrusted worker address that will be returned by the dedicated trusted ws rpc call. + pub untrusted_external_worker_address: Option, + /// Port to the untrusted ws of the validateer. + pub untrusted_worker_port: String, + /// Mutual remote attestation address that will be returned by the dedicated trusted ws rpc call. + pub mu_ra_external_address: Option, + /// Port for mutual-remote attestation requests. + pub mu_ra_port: String, + /// Enable the metrics server + pub enable_metrics_server: bool, + /// Port for the metrics server + pub metrics_server_port: String, + /// Port for the untrusted HTTP server (e.g. for `is_initialized`) + pub untrusted_http_port: String, + /// Data directory used by all the services. + pub data_dir: PathBuf, + /// Config of the 'run' subcommand + pub run_config: Option, + + /// the parentchain block number to start syncing with + pub parentchain_start_block: String, + /// mode to use for failing sidechain slot + pub fail_slot_mode: Option, + /// slot number to fail at + pub fail_at: u64, +} + +#[allow(clippy::too_many_arguments)] +impl Config { + pub fn new( + litentry_rpc_url: String, + litentry_rpc_port: String, + target_a_parentchain_rpc_url: Option, + target_a_parentchain_rpc_port: Option, + target_b_parentchain_rpc_url: Option, + target_b_parentchain_rpc_port: Option, + worker_ip: String, + trusted_external_worker_address: Option, + trusted_worker_port: String, + untrusted_external_worker_address: Option, + untrusted_worker_port: String, + mu_ra_external_address: Option, + mu_ra_port: String, + enable_metrics_server: bool, + metrics_server_port: String, + untrusted_http_port: String, + data_dir: PathBuf, + run_config: Option, + parentchain_start_block: String, + fail_slot_mode: Option, + fail_at: u64, + ) -> Self { + Self { + litentry_rpc_url, + litentry_rpc_port, + target_a_parentchain_rpc_url, + target_a_parentchain_rpc_port, + target_b_parentchain_rpc_url, + target_b_parentchain_rpc_port, + worker_ip, + trusted_external_worker_address, + trusted_worker_port, + untrusted_external_worker_address, + untrusted_worker_port, + mu_ra_external_address, + mu_ra_port, + enable_metrics_server, + metrics_server_port, + untrusted_http_port, + data_dir, + run_config, + parentchain_start_block, + fail_slot_mode, + fail_at, + } + } + + /// Integritee RPC endpoint (including ws://). + pub fn litentry_rpc_endpoint(&self) -> String { + format!("{}:{}", self.litentry_rpc_url, self.litentry_rpc_port) + } + + pub fn target_a_parentchain_rpc_endpoint(&self) -> Option { + if self.target_a_parentchain_rpc_url.is_some() + && self.target_a_parentchain_rpc_port.is_some() + { + return Some(format!( + "{}:{}", + // Can be done better, but this code is obsolete anyhow with clap v4. + self.target_a_parentchain_rpc_url.clone().unwrap(), + self.target_a_parentchain_rpc_port.clone().unwrap() + )) + }; + + None + } + + pub fn target_b_parentchain_rpc_endpoint(&self) -> Option { + if self.target_b_parentchain_rpc_url.is_some() + && self.target_b_parentchain_rpc_port.is_some() + { + return Some(format!( + "{}:{}", + // Can be done better, but this code is obsolete anyhow with clap v4. + self.target_b_parentchain_rpc_url.clone().unwrap(), + self.target_b_parentchain_rpc_port.clone().unwrap() + )) + }; + + None + } + + pub fn trusted_worker_url_internal(&self) -> String { + format!("{}:{}", self.worker_ip, self.trusted_worker_port) + } + + /// Returns the trusted worker url that should be addressed by external clients. + pub fn trusted_worker_url_external(&self) -> String { + match &self.trusted_external_worker_address { + Some(external_address) => external_address.to_string(), + None => format!("wss://{}:{}", self.worker_ip, self.trusted_worker_port), + } + } + + pub fn untrusted_worker_url(&self) -> String { + format!("{}:{}", self.worker_ip, self.untrusted_worker_port) + } + + /// Returns the untrusted worker url that should be addressed by external clients. + pub fn untrusted_worker_url_external(&self) -> String { + match &self.untrusted_external_worker_address { + Some(external_address) => external_address.to_string(), + None => format!("ws://{}:{}", self.worker_ip, self.untrusted_worker_port), + } + } + + pub fn mu_ra_url(&self) -> String { + format!("{}:{}", self.worker_ip, self.mu_ra_port) + } + + /// Returns the mutual remote attestion worker url that should be addressed by external workers. + pub fn mu_ra_url_external(&self) -> String { + match &self.mu_ra_external_address { + Some(external_address) => external_address.to_string(), + None => format!("{}:{}", self.worker_ip, self.mu_ra_port), + } + } + + pub fn data_dir(&self) -> &Path { + self.data_dir.as_path() + } + + pub fn run_config(&self) -> &Option { + &self.run_config + } + + pub fn enable_metrics_server(&self) -> bool { + self.enable_metrics_server + } + + pub fn try_parse_metrics_server_port(&self) -> Option { + self.metrics_server_port.parse::().ok() + } + + pub fn try_parse_untrusted_http_server_port(&self) -> Option { + self.untrusted_http_port.parse::().ok() + } + + pub fn try_parse_parentchain_start_block(&self) -> Option { + self.parentchain_start_block.parse::().ok() + } +} + +impl From<&ArgMatches<'_>> for Config { + fn from(m: &ArgMatches<'_>) -> Self { + let trusted_port = m.value_of("trusted-worker-port").unwrap_or(DEFAULT_TRUSTED_PORT); + let untrusted_port = m.value_of("untrusted-worker-port").unwrap_or(DEFAULT_UNTRUSTED_PORT); + let mu_ra_port = m.value_of("mu-ra-port").unwrap_or(DEFAULT_MU_RA_PORT); + let is_metrics_server_enabled = m.is_present("enable-metrics"); + let metrics_server_port = m.value_of("metrics-port").unwrap_or(DEFAULT_METRICS_PORT); + let untrusted_http_port = + m.value_of("untrusted-http-port").unwrap_or(DEFAULT_UNTRUSTED_HTTP_PORT); + + let data_dir = match m.value_of("data-dir") { + Some(d) => { + let p = PathBuf::from(d); + if !p.exists() { + log::info!("Creating new data-directory for the service {}.", p.display()); + fs::create_dir_all(p.as_path()).unwrap(); + } else { + log::info!("Starting service in existing directory {}.", p.display()); + } + p + }, + None => { + log::warn!("[Config] defaulting to data-dir = PWD because it was previous behaviour. This might change soon.\ + Please pass the data-dir explicitly to ensure nothing breaks in your setup."); + pwd() + }, + }; + + let run_config = m.subcommand_matches("run").map(RunConfig::from); + + let parentchain_start_block = + m.value_of("parentchain-start-block").unwrap_or(DEFAULT_PARENTCHAIN_START_BLOCK); + let fail_slot_mode = m.value_of("fail-slot-mode").map(|v| v.to_string()); + let fail_at = m.value_of("fail-at").unwrap_or(DEFAULT_FAIL_AT).parse().unwrap(); + Self::new( + m.value_of("node-url").unwrap_or(DEFAULT_NODE_URL).into(), + m.value_of("node-port").unwrap_or(DEFAULT_NODE_PORT).into(), + m.value_of("target-a-parentchain-rpc-url").map(Into::into), + m.value_of("target-a-parentchain-rpc-port").map(Into::into), + m.value_of("target-b-parentchain-rpc-url").map(Into::into), + m.value_of("target-b-parentchain-rpc-port").map(Into::into), + if m.is_present("ws-external") { "0.0.0.0".into() } else { "127.0.0.1".into() }, + m.value_of("trusted-external-address") + .map(|url| add_port_if_necessary(url, trusted_port)), + trusted_port.to_string(), + m.value_of("untrusted-external-address") + .map(|url| add_port_if_necessary(url, untrusted_port)), + untrusted_port.to_string(), + m.value_of("mu-ra-external-address") + .map(|url| add_port_if_necessary(url, mu_ra_port)), + mu_ra_port.to_string(), + is_metrics_server_enabled, + metrics_server_port.to_string(), + untrusted_http_port.to_string(), + data_dir, + run_config, + parentchain_start_block.to_string(), + fail_slot_mode, + fail_at, + ) + } +} + +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct RunConfig { + /// Skip remote attestation. Set this flag if running enclave in SW mode + skip_ra: bool, + /// Set this flag if running in development mode to bootstrap enclave account on parentchain via //Alice. + dev: bool, + /// Request key and state provisioning from a peer worker. + request_state: bool, + /// Shard identifier base58 encoded. Defines the shard that this worker operates on. Default is mrenclave. + shard: Option, + /// Optional teeracle update interval + teeracle_update_interval: Option, + /// Optional teeracle reregistration interval + reregister_teeracle_interval: Option, + /// Marblerun's Prometheus endpoint base URL + marblerun_base_url: Option, +} + +impl RunConfig { + pub fn skip_ra(&self) -> bool { + self.skip_ra + } + + pub fn dev(&self) -> bool { + self.dev + } + + pub fn request_state(&self) -> bool { + self.request_state + } + + pub fn shard(&self) -> Option<&str> { + self.shard.as_deref() + } + + pub fn teeracle_update_interval(&self) -> Duration { + self.teeracle_update_interval.unwrap_or(DEFAULT_MARKET_DATA_UPDATE_INTERVAL) + } + + /// The periodic registration period of the teeracle. + /// + /// Defaults to 23h30m, as this is slightly below the currently configured automatic + /// deregistration period on the Integritee chains. + pub fn reregister_teeracle_interval(&self) -> Duration { + // Todo: Derive this from chain https://github.com/integritee-network/worker/issues/1351 + self.reregister_teeracle_interval.unwrap_or(ONE_DAY - THIRTY_MINUTES) + } + + pub fn marblerun_base_url(&self) -> &str { + // This conflicts with the default port of a substrate node, but it is indeed the + // default port of marblerun too: + // https://github.com/edgelesssys/marblerun/blob/master/docs/docs/workflows/monitoring.md?plain=1#L26 + self.marblerun_base_url.as_deref().unwrap_or("http://localhost:9944") + } +} + +impl From<&ArgMatches<'_>> for RunConfig { + fn from(m: &ArgMatches<'_>) -> Self { + let skip_ra = m.is_present("skip-ra"); + let dev = m.is_present("dev"); + let request_state = m.is_present("request-state"); + let shard = m.value_of("shard").map(|s| s.to_string()); + let teeracle_update_interval = m.value_of("teeracle-interval").map(|i| { + parse(i).unwrap_or_else(|e| panic!("teeracle-interval parsing error {:?}", e)) + }); + let reregister_teeracle_interval = m.value_of("reregister-teeracle-interval").map(|i| { + parse(i).unwrap_or_else(|e| panic!("teeracle-interval parsing error {:?}", e)) + }); + + let marblerun_base_url = m.value_of("marblerun-url").map(|i| { + Url::parse(i) + .unwrap_or_else(|e| panic!("marblerun-url parsing error: {:?}", e)) + .to_string() + }); + + Self { + skip_ra, + dev, + request_state, + shard, + teeracle_update_interval, + reregister_teeracle_interval, + marblerun_base_url, + } + } +} + +fn add_port_if_necessary(url: &str, port: &str) -> String { + // [Option("ws(s)"), ip, Option(port)] + match url.split(':').count() { + 3 => url.to_string(), + 2 => { + if url.contains("ws") { + // url is of format ws://127.0.0.1, no port added + format!("{}:{}", url, port) + } else { + // url is of format 127.0.0.1:4000, port was added + url.to_string() + } + }, + 1 => format!("{}:{}", url, port), + _ => panic!("Invalid worker url format in url input {:?}", url), + } +} + +pub fn pwd() -> PathBuf { + std::env::current_dir().expect("works on all supported platforms; qed.") +} + +#[cfg(test)] +mod test { + use super::*; + use std::{assert_matches::assert_matches, collections::HashMap}; + + #[test] + fn check_correct_config_assignment_for_empty_input() { + let empty_args = ArgMatches::default(); + let config = Config::from(&empty_args); + let expected_worker_ip = "127.0.0.1"; + + assert_eq!(config.litentry_rpc_url, DEFAULT_NODE_URL); + assert_eq!(config.litentry_rpc_port, DEFAULT_NODE_PORT); + assert_eq!(config.target_a_parentchain_rpc_url, None); + assert_eq!(config.target_a_parentchain_rpc_port, None); + assert_eq!(config.target_b_parentchain_rpc_url, None); + assert_eq!(config.target_b_parentchain_rpc_port, None); + assert_eq!(config.trusted_worker_port, DEFAULT_TRUSTED_PORT); + assert_eq!(config.untrusted_worker_port, DEFAULT_UNTRUSTED_PORT); + assert_eq!(config.mu_ra_port, DEFAULT_MU_RA_PORT); + assert_eq!(config.worker_ip, expected_worker_ip); + assert!(config.trusted_external_worker_address.is_none()); + assert!(config.untrusted_external_worker_address.is_none()); + assert!(config.mu_ra_external_address.is_none()); + assert!(!config.enable_metrics_server); + assert_eq!(config.untrusted_http_port, DEFAULT_UNTRUSTED_HTTP_PORT); + assert_eq!(config.data_dir, pwd()); + assert!(config.run_config.is_none()); + assert_eq!(config.parentchain_start_block, DEFAULT_PARENTCHAIN_START_BLOCK); + assert_matches!(config.fail_slot_mode, Option::None); + assert_eq!(config.fail_at, DEFAULT_FAIL_AT.parse::().unwrap()) + } + + #[test] + fn worker_ip_is_set_correctly_for_set_ws_external_flag() { + let expected_worker_ip = "0.0.0.0"; + + let mut args = ArgMatches::default(); + args.args = HashMap::from([("ws-external", Default::default())]); + let config = Config::from(&args); + + assert_eq!(config.worker_ip, expected_worker_ip); + } + + #[test] + fn check_correct_config_assignment_for_given_input() { + let node_ip = "ws://12.1.58.1"; + let node_port = "111111"; + let trusted_ext_addr = "wss://1.1.1.2:700"; + let trusted_port = "7119"; + let untrusted_ext_addr = "ws://1.723.3.1:11"; + let untrusted_port = "9119"; + let mu_ra_ext_addr = "1.1.3.1:1000"; + let mu_ra_port = "99"; + let untrusted_http_port = "4321"; + + let parentchain_start_block = "30"; + + let mut args = ArgMatches::default(); + args.args = HashMap::from([ + ("node-url", Default::default()), + ("node-port", Default::default()), + ("ws-external", Default::default()), + ("trusted-external-address", Default::default()), + ("untrusted-external-address", Default::default()), + ("mu-ra-external-address", Default::default()), + ("mu-ra-port", Default::default()), + ("untrusted-worker-port", Default::default()), + ("trusted-worker-port", Default::default()), + ("untrusted-http-port", Default::default()), + ("mock-server-port", Default::default()), + ("parentchain-start-block", Default::default()), + ]); + // Workaround because MatchedArg is private. + args.args.get_mut("node-url").unwrap().vals = vec![node_ip.into()]; + args.args.get_mut("node-port").unwrap().vals = vec![node_port.into()]; + args.args.get_mut("trusted-external-address").unwrap().vals = vec![trusted_ext_addr.into()]; + args.args.get_mut("untrusted-external-address").unwrap().vals = + vec![untrusted_ext_addr.into()]; + args.args.get_mut("mu-ra-external-address").unwrap().vals = vec![mu_ra_ext_addr.into()]; + args.args.get_mut("mu-ra-port").unwrap().vals = vec![mu_ra_port.into()]; + args.args.get_mut("untrusted-worker-port").unwrap().vals = vec![untrusted_port.into()]; + args.args.get_mut("trusted-worker-port").unwrap().vals = vec![trusted_port.into()]; + args.args.get_mut("untrusted-http-port").unwrap().vals = vec![untrusted_http_port.into()]; + args.args.get_mut("parentchain-start-block").unwrap().vals = + vec![parentchain_start_block.into()]; + + let config = Config::from(&args); + + assert_eq!(config.litentry_rpc_url, node_ip); + assert_eq!(config.litentry_rpc_port, node_port); + assert_eq!(config.trusted_worker_port, trusted_port); + assert_eq!(config.untrusted_worker_port, untrusted_port); + assert_eq!(config.mu_ra_port, mu_ra_port); + assert_eq!(config.trusted_external_worker_address, Some(trusted_ext_addr.to_string())); + assert_eq!(config.untrusted_external_worker_address, Some(untrusted_ext_addr.to_string())); + assert_eq!(config.mu_ra_external_address, Some(mu_ra_ext_addr.to_string())); + assert_eq!(config.untrusted_http_port, untrusted_http_port.to_string()); + assert_eq!(config.parentchain_start_block, parentchain_start_block.to_string()); + } + + #[test] + fn default_run_config_is_correct() { + let empty_args = ArgMatches::default(); + let run_config = RunConfig::from(&empty_args); + + assert_eq!(run_config.request_state, false); + assert_eq!(run_config.dev, false); + assert_eq!(run_config.skip_ra, false); + assert!(run_config.shard.is_none()); + assert!(run_config.teeracle_update_interval.is_none()); + } + + #[test] + fn run_config_parsing_works() { + let shard_identifier = "shard-identifier"; + + let mut args = ArgMatches::default(); + args.args = HashMap::from([ + ("request-state", Default::default()), + ("dev", Default::default()), + ("skip-ra", Default::default()), + ("shard", Default::default()), + ("teeracle-interval", Default::default()), + ]); + // Workaround because MatchedArg is private. + args.args.get_mut("shard").unwrap().vals = vec![shard_identifier.into()]; + args.args.get_mut("teeracle-interval").unwrap().vals = vec!["42s".into()]; + + let run_config = RunConfig::from(&args); + + assert_eq!(run_config.request_state, true); + assert_eq!(run_config.dev, true); + assert_eq!(run_config.skip_ra, true); + assert_eq!(run_config.shard.unwrap(), shard_identifier.to_string()); + assert_eq!(run_config.teeracle_update_interval.unwrap(), Duration::from_secs(42)); + } + + #[test] + fn external_addresses_are_returned_correctly_if_not_set() { + let trusted_port = "7119"; + let untrusted_port = "9119"; + let mu_ra_port = "99"; + let expected_worker_ip = "127.0.0.1"; + + let mut args = ArgMatches::default(); + args.args = HashMap::from([ + ("mu-ra-port", Default::default()), + ("untrusted-worker-port", Default::default()), + ("trusted-worker-port", Default::default()), + ]); + // Workaround because MatchedArg is private. + args.args.get_mut("mu-ra-port").unwrap().vals = vec![mu_ra_port.into()]; + args.args.get_mut("untrusted-worker-port").unwrap().vals = vec![untrusted_port.into()]; + args.args.get_mut("trusted-worker-port").unwrap().vals = vec![trusted_port.into()]; + + let config = Config::from(&args); + + assert_eq!( + config.trusted_worker_url_external(), + format!("wss://{}:{}", expected_worker_ip, trusted_port) + ); + assert_eq!( + config.untrusted_worker_url_external(), + format!("ws://{}:{}", expected_worker_ip, untrusted_port) + ); + assert_eq!(config.mu_ra_url_external(), format!("{}:{}", expected_worker_ip, mu_ra_port)); + } + + #[test] + fn teeracle_interval_parsing_panics_if_format_is_invalid() { + let teeracle_interval = "24s_invalid-format"; + let mut args = ArgMatches::default(); + args.args = HashMap::from([("teeracle-interval", Default::default())]); + args.args.get_mut("teeracle-interval").unwrap().vals = vec![teeracle_interval.into()]; + + let result = std::panic::catch_unwind(|| RunConfig::from(&args)); + assert!(result.is_err()); + } + + #[test] + fn external_addresses_are_returned_correctly_if_set() { + let trusted_ext_addr = "wss://1.1.1.2:700"; + let untrusted_ext_addr = "ws://1.723.3.1:11"; + let mu_ra_ext_addr = "1.1.3.1:1000"; + + let mut args = ArgMatches::default(); + args.args = HashMap::from([ + ("trusted-external-address", Default::default()), + ("untrusted-external-address", Default::default()), + ("mu-ra-external-address", Default::default()), + ]); + // Workaround because MatchedArg is private. + args.args.get_mut("trusted-external-address").unwrap().vals = vec![trusted_ext_addr.into()]; + args.args.get_mut("untrusted-external-address").unwrap().vals = + vec![untrusted_ext_addr.into()]; + args.args.get_mut("mu-ra-external-address").unwrap().vals = vec![mu_ra_ext_addr.into()]; + + let config = Config::from(&args); + + assert_eq!(config.trusted_worker_url_external(), trusted_ext_addr); + assert_eq!(config.untrusted_worker_url_external(), untrusted_ext_addr); + assert_eq!(config.mu_ra_url_external(), mu_ra_ext_addr); + } + + #[test] + fn ensure_no_port_is_added_to_url_with_port() { + let url = "ws://hello:4000"; + let port = "0"; + + let resulting_url = add_port_if_necessary(url, port); + + assert_eq!(resulting_url, url); + } + + #[test] + fn ensure_port_is_added_to_url_without_port() { + let url = "wss://hello"; + let port = "0"; + + let resulting_url = add_port_if_necessary(url, port); + + assert_eq!(resulting_url, format!("{}:{}", url, port)); + } + + #[test] + fn ensure_no_port_is_added_to_url_with_port_without_prefix() { + let url = "hello:10001"; + let port = "012"; + + let resulting_url = add_port_if_necessary(url, port); + + assert_eq!(resulting_url, url); + } + + #[test] + fn ensure_port_is_added_to_url_without_port_without_prefix() { + let url = "hello_world"; + let port = "10"; + + let resulting_url = add_port_if_necessary(url, port); + + assert_eq!(resulting_url, format!("{}:{}", url, port)); + } +} diff --git a/bitacross-worker/service/src/enclave/api.rs b/bitacross-worker/service/src/enclave/api.rs new file mode 100644 index 0000000000..e3901672d0 --- /dev/null +++ b/bitacross-worker/service/src/enclave/api.rs @@ -0,0 +1,114 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::config::Config; +use itp_enclave_api::{enclave_base::EnclaveBase, error::Error as EnclaveApiError, EnclaveResult}; +use itp_settings::files::{ENCLAVE_FILE, ENCLAVE_TOKEN}; +use log::*; +use sgx_types::*; +use std::{ + fs::File, + io::{Read, Write}, + path::PathBuf, +}; + +use itp_enclave_api::{Enclave, SgxEnclave}; + +pub fn enclave_init(config: &Config) -> EnclaveResult { + const LEN: usize = 1024; + let mut launch_token = [0; LEN]; + let mut launch_token_updated = 0; + + // Step 1: try to retrieve the launch token saved by last transaction + // if there is no token, then create a new one. + // + // try to get the token saved in $HOME */ + let mut home_dir = PathBuf::new(); + let use_token = match dirs::home_dir() { + Some(path) => { + info!("[+] Home dir is {}", path.display()); + home_dir = path; + true + }, + None => { + error!("[-] Cannot get home dir"); + false + }, + }; + let token_file = home_dir.join(ENCLAVE_TOKEN); + if use_token { + match File::open(&token_file) { + Err(_) => { + info!( + "[-] Token file {} not found! Will create one.", + token_file.as_path().to_str().unwrap() + ); + }, + Ok(mut f) => { + info!("[+] Open token file success! "); + match f.read(&mut launch_token) { + Ok(LEN) => { + info!("[+] Token file valid!"); + }, + _ => info!("[+] Token file invalid, will create new token file"), + } + }, + } + } + + // Step 2: call sgx_create_enclave to initialize an enclave instance + // Debug Support: 1 = debug mode, 0 = not debug mode + #[cfg(not(feature = "production"))] + let debug = 1; + #[cfg(feature = "production")] + let debug = 0; + + let mut misc_attr = + sgx_misc_attribute_t { secs_attr: sgx_attributes_t { flags: 0, xfrm: 0 }, misc_select: 0 }; + let enclave = (SgxEnclave::create( + ENCLAVE_FILE, + debug, + &mut launch_token, + &mut launch_token_updated, + &mut misc_attr, + )) + .map_err(EnclaveApiError::Sgx)?; + + // Step 3: save the launch token if it is updated + if use_token && launch_token_updated != 0 { + // reopen the file with write capability + match File::create(&token_file) { + Ok(mut f) => match f.write_all(&launch_token) { + Ok(()) => info!("[+] Saved updated launch token!"), + Err(_) => error!("[-] Failed to save updated launch token!"), + }, + Err(_) => { + warn!("[-] Failed to save updated enclave token, but doesn't matter"); + }, + } + } + + // create an enclave API and initialize it + let enclave_api = Enclave::new(enclave); + enclave_api.init( + &config.mu_ra_url_external(), + &config.untrusted_worker_url_external(), + &config.data_dir().display().to_string(), + )?; + + Ok(enclave_api) +} diff --git a/bitacross-worker/service/src/enclave/mod.rs b/bitacross-worker/service/src/enclave/mod.rs new file mode 100644 index 0000000000..bb9ba4fe84 --- /dev/null +++ b/bitacross-worker/service/src/enclave/mod.rs @@ -0,0 +1,20 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 = "link-binary")] +pub mod api; +pub mod tls_ra; diff --git a/bitacross-worker/service/src/enclave/tls_ra.rs b/bitacross-worker/service/src/enclave/tls_ra.rs new file mode 100644 index 0000000000..cc07e3f4e9 --- /dev/null +++ b/bitacross-worker/service/src/enclave/tls_ra.rs @@ -0,0 +1,110 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 itp_enclave_api::{ + error::Error, + remote_attestation::{RemoteAttestation, TlsRemoteAttestation}, + EnclaveResult, +}; +use itp_types::ShardIdentifier; +use log::*; +use sgx_types::*; +use std::{ + net::{TcpListener, TcpStream}, + os::unix::io::AsRawFd, +}; + +pub fn enclave_run_state_provisioning_server( + enclave_api: &E, + sign_type: sgx_quote_sign_type_t, + quoting_enclave_target_info: Option<&sgx_target_info_t>, + quote_size: Option<&u32>, + addr: &str, + skip_ra: bool, +) { + info!("Starting MU-RA-Server on: {}", addr); + let listener = match TcpListener::bind(addr) { + Ok(l) => l, + Err(e) => { + error!("error starting MU-RA server on {}: {}", addr, e); + return + }, + }; + loop { + match listener.accept() { + Ok((socket, addr)) => { + info!("[MU-RA-Server] a worker at {} is requesting key provisiong", addr); + + let result = enclave_api.run_state_provisioning_server( + socket.as_raw_fd(), + sign_type, + quoting_enclave_target_info, + quote_size, + skip_ra, + ); + + match result { + Ok(_) => { + debug!("[MU-RA-Server] ECALL success!"); + }, + Err(e) => { + error!("[MU-RA-Server] ECALL Enclave Failed {:?}!", e); + }, + } + }, + Err(e) => error!("couldn't get client: {:?}", e), + } + } +} + +pub fn enclave_request_state_provisioning( + enclave_api: &E, + sign_type: sgx_quote_sign_type_t, + addr: &str, + shard: &ShardIdentifier, + skip_ra: bool, +) -> EnclaveResult<()> { + info!("[MU-RA-Client] Requesting key provisioning from {}", addr); + + let stream = TcpStream::connect(addr).map_err(|e| Error::Other(Box::new(e)))?; + + let quoting_enclave_target_info = if !skip_ra { + match enclave_api.qe_get_target_info() { + Ok(quote_size) => Some(quote_size), + Err(e) => return Err(e), + } + } else { + None + }; + + let quote_size = if !skip_ra { + match enclave_api.qe_get_quote_size() { + Ok(quote_size) => Some(quote_size), + Err(e) => return Err(e), + } + } else { + None + }; + + enclave_api.request_state_provisioning( + stream.as_raw_fd(), + sign_type, + quoting_enclave_target_info.as_ref(), + quote_size.as_ref(), + shard, + skip_ra, + ) +} diff --git a/bitacross-worker/service/src/error.rs b/bitacross-worker/service/src/error.rs new file mode 100644 index 0000000000..c99f51e6fc --- /dev/null +++ b/bitacross-worker/service/src/error.rs @@ -0,0 +1,61 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::Error as CodecError; +use itp_node_api::api_client::ApiClientError; +use itp_types::ShardIdentifier; + +pub type ServiceResult = Result; + +#[derive(Debug, thiserror::Error)] +pub enum Error { + #[error("{0}")] + Codec(#[from] CodecError), + #[error("{0:?}")] + ApiClient(ApiClientError), + #[error("Node API terminated subscription unexpectedly")] + ApiSubscriptionDisconnected, + #[error("Enclave API error: {0}")] + EnclaveApi(#[from] itp_enclave_api::error::Error), + #[error("Trusted Rpc Client error: {0}")] + TrustedRpcClient(#[from] itc_rpc_client::error::Error), + #[error("{0}")] + JsonRpSeeClient(#[from] jsonrpsee::types::Error), + #[error("{0}")] + Serialization(#[from] serde_json::Error), + #[error("{0}")] + FromUtf8(#[from] std::string::FromUtf8Error), + #[error("Application setup error!")] + ApplicationSetup, + #[error("Failed to find any peer worker")] + NoPeerWorkerFound, + #[error("No worker for shard {0} found on parentchain")] + NoWorkerForShardFound(ShardIdentifier), + #[error("Returned empty parentchain block vec after sync, even though there have been blocks given as input")] + EmptyChunk, + #[error("Could not find genesis header of the parentchain")] + MissingGenesisHeader, + #[error("Could not find last finalized block of the parentchain")] + MissingLastFinalizedBlock, + #[error("{0}")] + Custom(Box), +} + +impl From for Error { + fn from(error: ApiClientError) -> Self { + Error::ApiClient(error) + } +} diff --git a/bitacross-worker/service/src/globals/mod.rs b/bitacross-worker/service/src/globals/mod.rs new file mode 100644 index 0000000000..ee250661c5 --- /dev/null +++ b/bitacross-worker/service/src/globals/mod.rs @@ -0,0 +1,19 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 tokio_handle; diff --git a/bitacross-worker/service/src/globals/tokio_handle.rs b/bitacross-worker/service/src/globals/tokio_handle.rs new file mode 100644 index 0000000000..54e49d985e --- /dev/null +++ b/bitacross-worker/service/src/globals/tokio_handle.rs @@ -0,0 +1,108 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 lazy_static::lazy_static; +use parking_lot::RwLock; +use tokio::runtime::Handle; + +lazy_static! { + static ref TOKIO_HANDLE: RwLock> = RwLock::new(None); +} + +/// Wrapper for accessing a tokio handle +pub trait GetTokioHandle { + fn get_handle(&self) -> Handle; +} + +/// implementation, using a static global variable internally +/// +pub struct GlobalTokioHandle; + +/// these are the static (global) accessors +/// reduce their usage where possible and use an instance of TokioHandleAccessorImpl or the trait +impl GlobalTokioHandle { + /// this needs to be called once at application startup! + pub fn initialize() { + let rt = tokio::runtime::Builder::new_multi_thread() + .enable_all() + .worker_threads(2) + .build() + .unwrap(); + *TOKIO_HANDLE.write() = Some(rt); + } + + /// static / global getter of the handle (try to keep private!, use trait to access handle) + fn read_handle() -> Handle { + TOKIO_HANDLE + .read() + .as_ref() + .expect("Tokio handle has not been initialized!") + .handle() + .clone() + } +} + +impl GetTokioHandle for GlobalTokioHandle { + fn get_handle(&self) -> Handle { + GlobalTokioHandle::read_handle() + } +} + +/// Implementation for a scoped Tokio handle. +/// +/// +pub struct ScopedTokioHandle { + tokio_runtime: tokio::runtime::Runtime, +} + +impl Default for ScopedTokioHandle { + fn default() -> Self { + ScopedTokioHandle { tokio_runtime: tokio::runtime::Runtime::new().unwrap() } + } +} + +impl GetTokioHandle for ScopedTokioHandle { + fn get_handle(&self) -> Handle { + self.tokio_runtime.handle().clone() + } +} + +#[cfg(test)] +mod tests { + + use super::*; + + #[tokio::test] + async fn given_initialized_tokio_handle_when_runtime_goes_out_of_scope_then_async_handle_is_valid( + ) { + // initialize the global handle + // be aware that if you write more tests here, the global state will be shared across multiple threads + // which cargo test spawns. So it can lead to failing tests. + // solution: either get rid of the global state, or write all test functionality in this single test function + { + GlobalTokioHandle::initialize(); + } + + let handle = GlobalTokioHandle.get_handle(); + + let result = handle.spawn_blocking(|| "now running on a worker thread").await; + + assert!(result.is_ok()); + assert!(!result.unwrap().is_empty()) + } +} diff --git a/bitacross-worker/service/src/initialized_service.rs b/bitacross-worker/service/src/initialized_service.rs new file mode 100644 index 0000000000..f35a17fa28 --- /dev/null +++ b/bitacross-worker/service/src/initialized_service.rs @@ -0,0 +1,172 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +//! Service to determine if the integritee services is initialized and registered on the node, +//! hosted on a http server. + +use crate::error::ServiceResult; +use itp_settings::worker_mode::{ProvideWorkerMode, WorkerMode}; +use log::*; +use parking_lot::RwLock; +use std::{default::Default, marker::PhantomData, net::SocketAddr, sync::Arc}; +use warp::Filter; + +pub async fn start_is_initialized_server( + initialization_handler: Arc, + port: u16, +) -> ServiceResult<()> +where + Handler: IsInitialized + Send + Sync + 'static, +{ + let is_initialized_route = warp::path!("is_initialized").and_then(move || { + let handler_clone = initialization_handler.clone(); + async move { + if handler_clone.is_initialized() { + Ok("I am initialized.") + } else { + Err(warp::reject::not_found()) + } + } + }); + + let socket_addr: SocketAddr = ([0, 0, 0, 0], port).into(); + + info!("Running initialized server on: {:?}", socket_addr); + warp::serve(is_initialized_route).run(socket_addr).await; + + info!("Initialized server shut down"); + Ok(()) +} + +/// Trait to query of a worker is considered fully initialized. +pub trait IsInitialized { + fn is_initialized(&self) -> bool; +} + +/// Tracker for initialization. Used by components that ensure these steps were taken. +pub trait TrackInitialization { + fn registered_on_parentchain(&self); + + fn sidechain_block_produced(&self); + + fn worker_for_shard_registered(&self); +} + +pub struct InitializationHandler { + registered_on_parentchain: RwLock, + sidechain_block_produced: RwLock, + worker_for_shard_registered: RwLock, + _phantom: PhantomData, +} + +// Cannot use #[derive(Default)], because the compiler complains that WorkerModeProvider then +// also needs to implement Default. Which does not make sense, since it's only used in PhantomData. +// Explicitly implementing Default solves the problem +// (see https://stackoverflow.com/questions/59538071/the-trait-bound-t-stddefaultdefault-is-not-satisfied-when-using-phantomda). +impl Default for InitializationHandler { + fn default() -> Self { + Self { + registered_on_parentchain: Default::default(), + sidechain_block_produced: Default::default(), + worker_for_shard_registered: Default::default(), + _phantom: Default::default(), + } + } +} + +impl TrackInitialization for InitializationHandler { + fn registered_on_parentchain(&self) { + let mut registered_lock = self.registered_on_parentchain.write(); + *registered_lock = true; + } + + fn sidechain_block_produced(&self) { + let mut block_produced_lock = self.sidechain_block_produced.write(); + *block_produced_lock = true; + } + + fn worker_for_shard_registered(&self) { + let mut registered_lock = self.worker_for_shard_registered.write(); + *registered_lock = true; + } +} + +impl IsInitialized for InitializationHandler +where + WorkerModeProvider: ProvideWorkerMode, +{ + fn is_initialized(&self) -> bool { + match WorkerModeProvider::worker_mode() { + WorkerMode::Sidechain => + *self.registered_on_parentchain.read() + && *self.worker_for_shard_registered.read() + && *self.sidechain_block_produced.read(), + _ => *self.registered_on_parentchain.read(), + } + } +} + +#[cfg(test)] +mod tests { + + use super::*; + + struct OffchainWorkerMode; + impl ProvideWorkerMode for OffchainWorkerMode { + fn worker_mode() -> WorkerMode { + WorkerMode::OffChainWorker + } + } + + struct SidechainWorkerMode; + impl ProvideWorkerMode for SidechainWorkerMode { + fn worker_mode() -> WorkerMode { + WorkerMode::Sidechain + } + } + + #[test] + fn default_handler_is_initialized_returns_false() { + let offchain_worker_handler = InitializationHandler::::default(); + let sidechain_handler = InitializationHandler::::default(); + + assert!(!offchain_worker_handler.is_initialized()); + assert!(!sidechain_handler.is_initialized()); + } + + #[test] + fn in_offchain_worker_mode_parentchain_registration_is_enough_for_initialized() { + let initialization_handler = InitializationHandler::::default(); + initialization_handler.registered_on_parentchain(); + + assert!(initialization_handler.is_initialized()); + } + + #[test] + fn in_sidechain_mode_all_condition_have_to_be_met() { + let sidechain_handler = InitializationHandler::::default(); + + sidechain_handler.registered_on_parentchain(); + assert!(!sidechain_handler.is_initialized()); + + sidechain_handler.worker_for_shard_registered(); + assert!(!sidechain_handler.is_initialized()); + + sidechain_handler.sidechain_block_produced(); + assert!(sidechain_handler.is_initialized()); + } +} diff --git a/bitacross-worker/service/src/main.rs b/bitacross-worker/service/src/main.rs new file mode 100644 index 0000000000..6c5a888eee --- /dev/null +++ b/bitacross-worker/service/src/main.rs @@ -0,0 +1,52 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +#![cfg_attr(test, feature(assert_matches))] +#![allow(unused)] + +mod account_funding; +mod config; +mod enclave; +mod error; +mod globals; +mod initialized_service; +mod ocall_bridge; +mod parentchain_handler; +mod prometheus_metrics; +mod setup; +mod sidechain_setup; +mod sync_block_broadcaster; +mod sync_state; +#[cfg(feature = "teeracle")] +mod teeracle; +mod tests; +mod utils; +mod worker; +mod worker_peers_registry; + +#[cfg(feature = "link-binary")] +pub mod main_impl; + +#[cfg(feature = "link-binary")] +fn main() { + main_impl::main(); +} + +#[cfg(not(feature = "link-binary"))] +fn main() { + panic!("tried to run the binary without linking. Make sure to pass `--feature link-binary`") +} diff --git a/bitacross-worker/service/src/main_impl.rs b/bitacross-worker/service/src/main_impl.rs new file mode 100644 index 0000000000..6860fef3d3 --- /dev/null +++ b/bitacross-worker/service/src/main_impl.rs @@ -0,0 +1,1046 @@ +#[cfg(feature = "teeracle")] +use crate::teeracle::{schedule_periodic_reregistration_thread, start_periodic_market_update}; + +#[cfg(not(feature = "dcap"))] +use crate::utils::check_files; +use crate::{ + account_funding::{setup_account_funding, EnclaveAccountInfoProvider}, + config::Config, + enclave::{ + api::enclave_init, + tls_ra::{enclave_request_state_provisioning, enclave_run_state_provisioning_server}, + }, + error::Error, + globals::tokio_handle::{GetTokioHandle, GlobalTokioHandle}, + initialized_service::{ + start_is_initialized_server, InitializationHandler, IsInitialized, TrackInitialization, + }, + ocall_bridge::{ + bridge_api::Bridge as OCallBridge, component_factory::OCallBridgeComponentFactory, + }, + parentchain_handler::{HandleParentchain, ParentchainHandler}, + prometheus_metrics::{start_metrics_server, EnclaveMetricsReceiver, MetricsHandler}, + setup, + sidechain_setup::{sidechain_init_block_production, sidechain_start_untrusted_rpc_server}, + sync_block_broadcaster::SyncBlockBroadcaster, + sync_state, tests, + utils::extract_shard, + worker::Worker, + worker_peers_registry::WorkerPeersRegistry, +}; +use base58::ToBase58; +use clap::{load_yaml, App, ArgMatches}; +use codec::{Decode, Encode}; +use itp_enclave_api::{ + direct_request::DirectRequest, + enclave_base::EnclaveBase, + remote_attestation::{RemoteAttestation, TlsRemoteAttestation}, + sidechain::Sidechain, + teeracle_api::TeeracleApi, +}; +use itp_node_api::{ + api_client::{AccountApi, PalletTeerexApi, ParentchainApi}, + metadata::NodeMetadata, + node_api_factory::{CreateNodeApi, NodeApiFactory}, +}; +use itp_settings::worker_mode::{ProvideWorkerMode, WorkerMode, WorkerModeProvider}; +use itp_utils::if_production_or; +use its_peer_fetch::{ + block_fetch_client::BlockFetcher, untrusted_peer_fetch::UntrustedPeerFetcher, +}; +use its_primitives::types::block::SignedBlock as SignedSidechainBlock; +use its_storage::{interface::FetchBlocks, BlockPruner, SidechainStorageLock}; +use log::*; +use my_node_runtime::{Hash, Header, RuntimeEvent}; +use regex::Regex; +use serde_json::Value; +use sgx_types::*; +use sp_runtime::traits::Header as HeaderT; +use substrate_api_client::{ + ac_primitives::serde_impls::StorageKey, api::XtStatus, rpc::HandleSubscription, storage_key, + GetChainInfo, GetStorage, SubmitAndWatch, SubscribeChain, SubscribeEvents, +}; +use teerex_primitives::{Enclave as TeerexEnclave, ShardIdentifier}; + +#[cfg(feature = "dcap")] +use sgx_verify::extract_tcb_info_from_raw_dcap_quote; + +use itc_parentchain::primitives::ParentchainId; +use itp_enclave_api::Enclave; +use sp_core::crypto::{AccountId32, Ss58Codec}; +use sp_keyring::AccountKeyring; +use sp_runtime::MultiSigner; +use std::{ + collections::HashSet, env, fmt::Debug, fs::File, io::Read, str, sync::Arc, thread, + time::Duration, +}; +use substrate_api_client::ac_node_api::{EventRecord, Phase::ApplyExtrinsic}; + +const VERSION: &str = env!("CARGO_PKG_VERSION"); + +#[cfg(feature = "link-binary")] +pub type EnclaveWorker = + Worker>; +pub type Event = substrate_api_client::ac_node_api::EventRecord; + +pub(crate) fn main() { + // Setup logging + env_logger::init(); + + let yml = load_yaml!("cli.yml"); + let matches = App::from_yaml(yml).get_matches(); + + let config = Config::from(&matches); + + GlobalTokioHandle::initialize(); + + // log this information, don't println because some python scripts for GA rely on the + // stdout from the service + #[cfg(feature = "production")] + info!("*** Starting service in SGX production mode"); + #[cfg(not(feature = "production"))] + info!("*** Starting service in SGX debug mode"); + + info!("*** Running worker in mode: {:?} \n", WorkerModeProvider::worker_mode()); + + let clean_reset = matches.is_present("clean-reset"); + if clean_reset { + crate::setup::purge_files_from_dir(config.data_dir()).unwrap(); + } + + // build the entire dependency tree + let tokio_handle = Arc::new(GlobalTokioHandle {}); + let sidechain_blockstorage = Arc::new( + SidechainStorageLock::::from_base_path( + config.data_dir().to_path_buf(), + ) + .unwrap(), + ); + let node_api_factory = + Arc::new(NodeApiFactory::new(config.litentry_rpc_endpoint(), AccountKeyring::Alice.pair())); + let enclave = Arc::new(enclave_init(&config).unwrap()); + let initialization_handler = Arc::new(InitializationHandler::default()); + let worker = Arc::new(EnclaveWorker::new( + config.clone(), + enclave.clone(), + node_api_factory.clone(), + initialization_handler.clone(), + HashSet::new(), + )); + let sync_block_broadcaster = + Arc::new(SyncBlockBroadcaster::new(tokio_handle.clone(), worker.clone())); + let peer_updater = Arc::new(WorkerPeersRegistry::new(worker)); + let untrusted_peer_fetcher = UntrustedPeerFetcher::new(node_api_factory.clone()); + let peer_sidechain_block_fetcher = + Arc::new(BlockFetcher::::new(untrusted_peer_fetcher)); + let enclave_metrics_receiver = Arc::new(EnclaveMetricsReceiver {}); + + let maybe_target_a_parentchain_api_factory = config + .target_a_parentchain_rpc_endpoint() + .map(|url| Arc::new(NodeApiFactory::new(url, AccountKeyring::Alice.pair()))); + + let maybe_target_b_parentchain_api_factory = config + .target_b_parentchain_rpc_endpoint() + .map(|url| Arc::new(NodeApiFactory::new(url, AccountKeyring::Alice.pair()))); + + // initialize o-call bridge with a concrete factory implementation + OCallBridge::initialize(Arc::new(OCallBridgeComponentFactory::new( + node_api_factory.clone(), + maybe_target_a_parentchain_api_factory, + maybe_target_b_parentchain_api_factory, + sync_block_broadcaster, + enclave.clone(), + sidechain_blockstorage.clone(), + peer_updater, + peer_sidechain_block_fetcher, + tokio_handle.clone(), + enclave_metrics_receiver, + ))); + + #[cfg(feature = "dcap")] + let quoting_enclave_target_info = match enclave.qe_get_target_info() { + Ok(target_info) => Some(target_info), + Err(e) => { + warn!("Setting up DCAP - qe_get_target_info failed with error: {:?}, continuing.", e); + None + }, + }; + #[cfg(feature = "dcap")] + let quote_size = match enclave.qe_get_quote_size() { + Ok(size) => Some(size), + Err(e) => { + warn!("Setting up DCAP - qe_get_quote_size failed with error: {:?}, continuing.", e); + None + }, + }; + + #[cfg(not(feature = "dcap"))] + let quoting_enclave_target_info = None; + #[cfg(not(feature = "dcap"))] + let quote_size = None; + + if let Some(run_config) = config.run_config() { + let shard = extract_shard(run_config.shard(), enclave.as_ref()); + + println!("Worker Config: {:?}", config); + + if clean_reset { + setup::initialize_shard_and_keys(enclave.as_ref(), &shard).unwrap(); + } + + let node_api = + node_api_factory.create_api().expect("Failed to create parentchain node API"); + + if run_config.request_state() { + sync_state::sync_state::<_, _, WorkerModeProvider>( + &node_api, + &shard, + enclave.as_ref(), + run_config.skip_ra(), + ); + } + + start_worker::<_, _, _, _, WorkerModeProvider>( + config, + &shard, + enclave, + sidechain_blockstorage, + node_api, + tokio_handle, + initialization_handler, + quoting_enclave_target_info, + quote_size, + ); + } else if let Some(smatches) = matches.subcommand_matches("request-state") { + println!("*** Requesting state from a registered worker \n"); + let node_api = + node_api_factory.create_api().expect("Failed to create parentchain node API"); + sync_state::sync_state::<_, _, WorkerModeProvider>( + &node_api, + &extract_shard(smatches.value_of("shard"), enclave.as_ref()), + enclave.as_ref(), + smatches.is_present("skip-ra"), + ); + } else if matches.is_present("shielding-key") { + setup::generate_shielding_key_file(enclave.as_ref()); + } else if matches.is_present("signing-key") { + setup::generate_signing_key_file(enclave.as_ref()); + } else if matches.is_present("dump-ra") { + info!("*** Perform RA and dump cert to disk"); + #[cfg(not(feature = "dcap"))] + enclave.dump_ias_ra_cert_to_disk().unwrap(); + #[cfg(feature = "dcap")] + { + let skip_ra = false; + let dcap_quote = enclave.generate_dcap_ra_quote(skip_ra).unwrap(); + let (fmspc, _tcb_info) = extract_tcb_info_from_raw_dcap_quote(&dcap_quote).unwrap(); + enclave.dump_dcap_collateral_to_disk(fmspc).unwrap(); + enclave.dump_dcap_ra_cert_to_disk().unwrap(); + } + } else if matches.is_present("mrenclave") { + println!("{}", enclave.get_fingerprint().unwrap().encode().to_base58()); + } else if let Some(sub_matches) = matches.subcommand_matches("init-shard") { + setup::init_shard( + enclave.as_ref(), + &extract_shard(sub_matches.value_of("shard"), enclave.as_ref()), + ); + } else if let Some(sub_matches) = matches.subcommand_matches("test") { + if sub_matches.is_present("provisioning-server") { + println!("*** Running Enclave MU-RA TLS server\n"); + enclave_run_state_provisioning_server( + enclave.as_ref(), + sgx_quote_sign_type_t::SGX_UNLINKABLE_SIGNATURE, + quoting_enclave_target_info.as_ref(), + quote_size.as_ref(), + &config.mu_ra_url(), + sub_matches.is_present("skip-ra"), + ); + println!("[+] Done!"); + } else if sub_matches.is_present("provisioning-client") { + println!("*** Running Enclave MU-RA TLS client\n"); + let shard = extract_shard(sub_matches.value_of("shard"), enclave.as_ref()); + enclave_request_state_provisioning( + enclave.as_ref(), + sgx_quote_sign_type_t::SGX_UNLINKABLE_SIGNATURE, + &config.mu_ra_url_external(), + &shard, + sub_matches.is_present("skip-ra"), + ) + .unwrap(); + println!("[+] Done!"); + } else { + tests::run_enclave_tests(sub_matches); + } + } else if let Some(sub_matches) = matches.subcommand_matches("migrate-shard") { + // This subcommand `migrate-shard` is only used for manual testing. Maybe deleted later. + let old_shard = sub_matches + .value_of("old-shard") + .map(|value| { + let mut shard = [0u8; 32]; + hex::decode_to_slice(value, &mut shard) + .expect("shard must be hex encoded without 0x"); + ShardIdentifier::from_slice(&shard) + }) + .unwrap(); + + let new_shard: ShardIdentifier = sub_matches + .value_of("new-shard") + .map(|value| { + let mut shard = [0u8; 32]; + hex::decode_to_slice(value, &mut shard) + .expect("shard must be hex encoded without 0x"); + ShardIdentifier::from_slice(&shard) + }) + .unwrap(); + + if old_shard == new_shard { + println!("old_shard should not be the same as new_shard"); + } else { + setup::migrate_shard(enclave.as_ref(), &old_shard, &new_shard); + } + } else { + println!("For options: use --help"); + } +} + +/// FIXME: needs some discussion (restructuring?) +#[allow(clippy::too_many_arguments)] +fn start_worker( + config: Config, + shard: &ShardIdentifier, + enclave: Arc, + sidechain_storage: Arc, + litentry_rpc_api: ParentchainApi, + tokio_handle_getter: Arc, + initialization_handler: Arc, + quoting_enclave_target_info: Option, + quote_size: Option, +) where + T: GetTokioHandle, + E: EnclaveBase + + DirectRequest + + Sidechain + + RemoteAttestation + + TlsRemoteAttestation + + TeeracleApi + + Clone, + D: BlockPruner + FetchBlocks + Sync + Send + 'static, + InitializationHandler: TrackInitialization + IsInitialized + Sync + Send + 'static, + WorkerModeProvider: ProvideWorkerMode, +{ + let run_config = config.run_config().clone().expect("Run config missing"); + let skip_ra = run_config.skip_ra(); + + #[cfg(feature = "teeracle")] + let flavor_str = "teeracle"; + #[cfg(feature = "sidechain")] + let flavor_str = "sidechain"; + #[cfg(feature = "offchain-worker")] + let flavor_str = "offchain-worker"; + #[cfg(not(any(feature = "offchain-worker", feature = "sidechain", feature = "teeracle")))] + let flavor_str = "offchain-worker"; + + println!("Litentry Worker for {} v{}", flavor_str, VERSION); + + #[cfg(feature = "dcap")] + println!(" DCAP is enabled"); + #[cfg(not(feature = "dcap"))] + println!(" DCAP is disabled"); + #[cfg(feature = "production")] + println!(" Production Mode is enabled"); + #[cfg(not(feature = "production"))] + println!(" Production Mode is disabled"); + #[cfg(feature = "evm")] + println!(" EVM is enabled"); + #[cfg(not(feature = "evm"))] + println!(" EVM is disabled"); + + info!("starting worker on shard {}", shard.encode().to_base58()); + // ------------------------------------------------------------------------ + // check for required files + if !skip_ra { + #[cfg(not(feature = "dcap"))] + check_files(); + } + // ------------------------------------------------------------------------ + // initialize the enclave + let mrenclave = enclave.get_fingerprint().unwrap(); + println!("MRENCLAVE={}", mrenclave.0.to_base58()); + println!("MRENCLAVE in hex {:?}", hex::encode(mrenclave)); + + // ------------------------------------------------------------------------ + // let new workers call us for key provisioning + println!("MU-RA server listening on {}", config.mu_ra_url()); + let is_development_mode = run_config.dev(); + let ra_url = config.mu_ra_url(); + let enclave_api_key_prov = enclave.clone(); + thread::spawn(move || { + enclave_run_state_provisioning_server( + enclave_api_key_prov.as_ref(), + sgx_quote_sign_type_t::SGX_UNLINKABLE_SIGNATURE, + quoting_enclave_target_info.as_ref(), + quote_size.as_ref(), + &ra_url, + skip_ra, + ); + info!("State provisioning server stopped."); + }); + + let tokio_handle = tokio_handle_getter.get_handle(); + + // ------------------------------------------------------------------------ + // Get the public key of our TEE. + let tee_accountid = enclave_account(enclave.as_ref()); + println!("Enclave account {:} ", &tee_accountid.to_ss58check()); + + // ------------------------------------------------------------------------ + // Start `is_initialized` server. + let untrusted_http_server_port = config + .try_parse_untrusted_http_server_port() + .expect("untrusted http server port to be a valid port number"); + let initialization_handler_clone = initialization_handler.clone(); + tokio_handle.spawn(async move { + if let Err(e) = + start_is_initialized_server(initialization_handler_clone, untrusted_http_server_port) + .await + { + error!("Unexpected error in `is_initialized` server: {:?}", e); + } + }); + + // ------------------------------------------------------------------------ + // Start prometheus metrics server. + if config.enable_metrics_server() { + let enclave_wallet = Arc::new(EnclaveAccountInfoProvider::new( + litentry_rpc_api.clone(), + tee_accountid.clone(), + )); + let metrics_handler = Arc::new(MetricsHandler::new(enclave_wallet)); + let metrics_server_port = config + .try_parse_metrics_server_port() + .expect("metrics server port to be a valid port number"); + tokio_handle.spawn(async move { + if let Err(e) = start_metrics_server(metrics_handler, metrics_server_port).await { + error!("Unexpected error in Prometheus metrics server: {:?}", e); + } + }); + } + + // ------------------------------------------------------------------------ + // Start trusted worker rpc server + if WorkerModeProvider::worker_mode() == WorkerMode::Sidechain + || WorkerModeProvider::worker_mode() == WorkerMode::OffChainWorker + { + let direct_invocation_server_addr = config.trusted_worker_url_internal(); + let enclave_for_direct_invocation = enclave.clone(); + thread::spawn(move || { + println!( + "[+] Trusted RPC direct invocation server listening on {}", + direct_invocation_server_addr + ); + enclave_for_direct_invocation + .init_direct_invocation_server(direct_invocation_server_addr) + .unwrap(); + println!("[+] RPC direct invocation server shut down"); + }); + } + + // ------------------------------------------------------------------------ + // Start untrusted worker rpc server. + // i.e move sidechain block importing to trusted worker. + if WorkerModeProvider::worker_mode() == WorkerMode::Sidechain { + sidechain_start_untrusted_rpc_server( + &config, + enclave.clone(), + sidechain_storage.clone(), + &tokio_handle, + ); + } + + // ------------------------------------------------------------------------ + // Init parentchain specific stuff. Needed for parentchain communication. + + let (parentchain_handler, last_synced_header) = + init_parentchain(&enclave, &litentry_rpc_api, &tee_accountid, ParentchainId::Litentry); + + #[cfg(feature = "dcap")] + register_collateral(&litentry_rpc_api, &*enclave, &tee_accountid, is_development_mode, skip_ra); + + let trusted_url = config.trusted_worker_url_external(); + + #[cfg(feature = "attesteer")] + fetch_marblerun_events_every_hour( + litentry_rpc_api.clone(), + enclave.clone(), + tee_accountid.clone(), + is_development_mode, + trusted_url.clone(), + run_config.marblerun_base_url().to_string(), + ); + + // ------------------------------------------------------------------------ + // Perform a remote attestation and get an unchecked extrinsic back. + + if skip_ra { + println!( + "[!] skipping remote attestation. Registering enclave without attestation report." + ); + } else { + println!("[!] creating remote attestation report and create enclave register extrinsic."); + }; + + #[cfg(feature = "dcap")] + enclave.set_sgx_qpl_logging().expect("QPL logging setup failed"); + + let enclave2 = enclave.clone(); + let node_api2 = litentry_rpc_api.clone(); + let tee_accountid2 = tee_accountid.clone(); + let trusted_url2 = trusted_url.clone(); + + #[cfg(not(feature = "dcap"))] + let register_xt = move || enclave2.generate_ias_ra_extrinsic(&trusted_url2, skip_ra).unwrap(); + #[cfg(feature = "dcap")] + let register_xt = move || enclave2.generate_dcap_ra_extrinsic(&trusted_url2, skip_ra).unwrap(); + + let mut register_enclave_xt_header: Option
= None; + let mut we_are_primary_validateer: bool = false; + + let send_register_xt = move || { + println!("[+] Send register enclave extrinsic"); + send_extrinsic(register_xt(), &node_api2, &tee_accountid2, is_development_mode) + }; + + // litentry: check if the enclave is already registered + // TODO: revisit the registration process (P-10) + match litentry_rpc_api.get_keys(storage_key("Teerex", "EnclaveRegistry"), None) { + Ok(Some(keys)) => { + let trusted_url = trusted_url.as_bytes().to_vec(); + let mrenclave = mrenclave.0.to_vec(); + let mut found = false; + for key in keys { + let key = if key.starts_with("0x") { + let bytes = &key.as_bytes()[b"0x".len()..]; + hex::decode(bytes).unwrap() + } else { + hex::decode(key.as_bytes()).unwrap() + }; + match litentry_rpc_api.get_storage_by_key::>>( + StorageKey(key.clone()), + None, + ) { + Ok(Some(value)) => { + if value.mr_enclave.to_vec() == mrenclave && value.url == trusted_url { + // After calling the perform_ra function, the nonce will be incremented by 1, + // so enclave is already registered, we should reset the nonce_cache + let nonce = + litentry_rpc_api.get_account_next_index(&tee_accountid).unwrap(); + enclave + .set_nonce(nonce, ParentchainId::Litentry) + .expect("Could not set nonce of enclave. Returning here..."); + found = true; + info!("fond enclave: {:?}", value); + break + } + }, + Ok(None) => { + warn!("not found from key: {:?}", key); + }, + Err(_) => {}, + } + } + if !found { + // Todo: Can't unwrap here because the extrinsic is for some reason not found in the block + // even if it was successful: https://github.com/scs/substrate-api-client/issues/624. + let register_enclave_block_hash = send_register_xt(); + let api_register_enclave_xt_header = + litentry_rpc_api.get_header(register_enclave_block_hash).unwrap().unwrap(); + + // TODO: #1451: Fix api-client type hacks + // TODO(Litentry): keep an eye on it - it's a hacky way to convert `SubstrateHeader` to `Header` + let header = + Header::decode(&mut api_register_enclave_xt_header.encode().as_slice()) + .expect("Can decode previously encoded header; qed"); + + println!( + "[+] Enclave registered at block number: {:?}, hash: {:?}", + header.number(), + header.hash() + ); + + register_enclave_xt_header = Some(header); + } + }, + _ => panic!("unknown error"), + } + + if let Some(register_enclave_xt_header) = register_enclave_xt_header.clone() { + we_are_primary_validateer = + we_are_primary_worker(&litentry_rpc_api, ®ister_enclave_xt_header).unwrap(); + } + + if we_are_primary_validateer { + println!("[+] We are the primary worker"); + } else { + println!("[+] We are NOT the primary worker"); + } + + initialization_handler.registered_on_parentchain(); + + match WorkerModeProvider::worker_mode() { + WorkerMode::Teeracle => { + // ------------------------------------------------------------------------ + // initialize teeracle interval + #[cfg(feature = "teeracle")] + schedule_periodic_reregistration_thread( + send_register_xt, + run_config.reregister_teeracle_interval(), + ); + + #[cfg(feature = "teeracle")] + start_periodic_market_update( + &litentry_rpc_api, + run_config.teeracle_update_interval(), + enclave.as_ref(), + &tokio_handle, + ); + }, + WorkerMode::OffChainWorker => { + println!("*** [+] Finished initializing light client, syncing parentchain..."); + + // Syncing all parentchain blocks, this might take a while.. + let last_synced_header = + parentchain_handler.sync_parentchain(last_synced_header, 0, true).unwrap(); + + start_parentchain_header_subscription_thread(parentchain_handler, last_synced_header); + + info!("skipping shard vault check because not yet supported for offchain worker"); + }, + WorkerMode::Sidechain => { + println!("*** [+] Finished initializing light client, syncing parentchain..."); + + // Litentry: apply skipped parentchain block + let parentchain_start_block = config + .try_parse_parentchain_start_block() + .expect("parentchain start block to be a valid number"); + + println!( + "*** [+] last_synced_header: {}, config.parentchain_start_block: {}", + last_synced_header.number, parentchain_start_block + ); + + // ------------------------------------------------------------------------ + // Initialize the sidechain + let last_synced_header = sidechain_init_block_production( + enclave.clone(), + register_enclave_xt_header, + we_are_primary_validateer, + parentchain_handler.clone(), + sidechain_storage, + &last_synced_header, + parentchain_start_block, + config.clone().fail_slot_mode, + config.fail_at, + ) + .unwrap(); + + start_parentchain_header_subscription_thread(parentchain_handler, last_synced_header); + + init_provided_shard_vault(shard, &enclave, we_are_primary_validateer); + + spawn_worker_for_shard_polling(shard, litentry_rpc_api.clone(), initialization_handler); + }, + } + + if let Some(url) = config.target_a_parentchain_rpc_endpoint() { + init_target_parentchain( + &enclave, + &tee_accountid, + url, + shard, + ParentchainId::TargetA, + is_development_mode, + ) + } + + if let Some(url) = config.target_b_parentchain_rpc_endpoint() { + init_target_parentchain( + &enclave, + &tee_accountid, + url, + shard, + ParentchainId::TargetB, + is_development_mode, + ) + } + + // ------------------------------------------------------------------------ + // Subscribe to events and print them. + println!("*** [{:?}] Subscribing to events", ParentchainId::Litentry); + let mut subscription = litentry_rpc_api.subscribe_events().unwrap(); + println!("[+] [{:?}] Subscribed to events. waiting...", ParentchainId::Litentry); + loop { + if let Some(Ok(events)) = subscription.next_events::() { + print_events(events, ParentchainId::Litentry) + } + } +} + +fn init_provided_shard_vault( + shard: &ShardIdentifier, + enclave: &Arc, + we_are_primary_validateer: bool, +) { + if let Ok(shard_vault) = enclave.get_ecc_vault_pubkey(shard) { + println!( + "[Litentry] shard vault account is already initialized in state: {}", + shard_vault.to_ss58check() + ); + } else if we_are_primary_validateer { + println!("[Litentry] initializing proxied shard vault account now"); + enclave.init_proxied_shard_vault(shard, &ParentchainId::Litentry).unwrap(); + println!( + "[Litentry] initialized shard vault account: : {}", + enclave.get_ecc_vault_pubkey(shard).unwrap().to_ss58check() + ); + } else { + panic!( + "[Litentry] no vault account has been initialized and we are not the primary worker" + ); + } +} + +fn init_target_parentchain( + enclave: &Arc, + tee_account_id: &AccountId32, + url: String, + shard: &ShardIdentifier, + parentchain_id: ParentchainId, + is_development_mode: bool, +) where + E: EnclaveBase + Sidechain, +{ + println!("Initializing parentchain {:?} with url: {}", parentchain_id, url); + let node_api = NodeApiFactory::new(url, AccountKeyring::Alice.pair()) + .create_api() + .unwrap_or_else(|_| panic!("[{:?}] Failed to create parentchain node API", parentchain_id)); + + // some random bytes not too small to ensure that the enclave has enough funds + setup_account_funding(&node_api, tee_account_id, [0u8; 100].into(), is_development_mode) + .unwrap_or_else(|_| { + panic!("[{:?}] Could not fund parentchain enclave account", parentchain_id) + }); + + let (parentchain_handler, last_synched_header) = + init_parentchain(enclave, &node_api, tee_account_id, parentchain_id); + + if WorkerModeProvider::worker_mode() != WorkerMode::Teeracle { + println!( + "*** [+] [{:?}] Finished initializing light client, syncing parentchain...", + parentchain_id + ); + + // Syncing all parentchain blocks, this might take a while.. + let last_synched_header = + parentchain_handler.sync_parentchain(last_synched_header, 0, true).unwrap(); + + start_parentchain_header_subscription_thread(parentchain_handler, last_synched_header) + } + println!("[{:?}] initializing proxied shard vault account now", parentchain_id); + enclave.init_proxied_shard_vault(shard, &parentchain_id).unwrap(); + + // Subscribe to events and print them. + println!("*** [{:?}] Subscribing to events...", parentchain_id); + let mut subscription = node_api.subscribe_events().unwrap(); + println!("[+] [{:?}] Subscribed to events. waiting...", parentchain_id); + + thread::Builder::new() + .name(format!("{:?}_parentchain_event_subscription", parentchain_id)) + .spawn(move || loop { + if let Some(Ok(events)) = subscription.next_events::() { + print_events(events, parentchain_id) + } + }) + .unwrap(); +} + +fn init_parentchain( + enclave: &Arc, + node_api: &ParentchainApi, + tee_account_id: &AccountId32, + parentchain_id: ParentchainId, +) -> (Arc>, Header) +where + E: EnclaveBase + Sidechain, +{ + let parentchain_handler = Arc::new( + ParentchainHandler::new_with_automatic_light_client_allocation( + node_api.clone(), + enclave.clone(), + parentchain_id, + ) + .unwrap(), + ); + let last_synced_header = parentchain_handler.init_parentchain_components().unwrap(); + println!("[{:?}] last synced parentchain block: {}", parentchain_id, last_synced_header.number); + + let nonce = node_api.get_nonce_of(tee_account_id).unwrap(); + info!("[{:?}] Enclave nonce = {:?}", parentchain_id, nonce); + enclave.set_nonce(nonce, parentchain_id).unwrap_or_else(|_| { + panic!("[{:?}] Could not set nonce of enclave. Returning here...", parentchain_id) + }); + + let metadata = node_api.metadata().clone(); + let runtime_spec_version = node_api.runtime_version().spec_version; + let runtime_transaction_version = node_api.runtime_version().transaction_version; + enclave + .set_node_metadata( + NodeMetadata::new(metadata, runtime_spec_version, runtime_transaction_version).encode(), + parentchain_id, + ) + .unwrap_or_else(|_| { + panic!("[{:?}] Could not set the node metadata in the enclave", parentchain_id) + }); + + (parentchain_handler, last_synced_header) +} + +/// Start polling loop to wait until we have a worker for a shard registered on +/// the parentchain (TEEREX WorkerForShard). This is the pre-requisite to be +/// considered initialized and ready for the next worker to start (in sidechain mode only). +/// considered initialized and ready for the next worker to start. +fn spawn_worker_for_shard_polling( + shard: &ShardIdentifier, + node_api: ParentchainApi, + initialization_handler: Arc, +) where + InitializationHandler: TrackInitialization + Sync + Send + 'static, +{ + let shard_for_initialized = *shard; + thread::spawn(move || { + const POLL_INTERVAL_SECS: u64 = 2; + + loop { + info!("Polling for worker for shard ({} seconds interval)", POLL_INTERVAL_SECS); + if let Ok(Some(_enclave)) = node_api.worker_for_shard(&shard_for_initialized, None) { + // Set that the service is initialized. + initialization_handler.worker_for_shard_registered(); + println!("[+] Found `WorkerForShard` on parentchain state",); + break + } + thread::sleep(Duration::from_secs(POLL_INTERVAL_SECS)); + } + }); +} + +fn print_events(events: Vec>, parentchain_id: ParentchainId) +where + R: Debug, +{ + for evr in &events { + if evr.phase == ApplyExtrinsic(0) { + // not interested in intrinsics + continue + } + let re = Regex::new(r"\s[0-9a-f]*\s\(").unwrap(); + let event_str = re + .replace_all(format!("{:?}", evr.event).as_str(), "(") + .replace("RuntimeEvent::", "") + .replace("Event::", ""); + println!("[{}] Event: {}", parentchain_id, event_str); + } +} + +#[cfg(feature = "attesteer")] +fn fetch_marblerun_events_every_hour( + api: ParentchainApi, + enclave: Arc, + accountid: AccountId32, + is_development_mode: bool, + url: String, + marblerun_base_url: String, +) where + E: RemoteAttestation + Clone + Sync + Send + 'static, +{ + let enclave = enclave.clone(); + let handle = thread::spawn(move || { + const POLL_INTERVAL_5_MINUTES_IN_SECS: u64 = 5 * 60; + loop { + info!("Polling marblerun events for quotes to register"); + register_quotes_from_marblerun( + &api, + enclave.clone(), + &accountid, + is_development_mode, + url.clone(), + &marblerun_base_url, + ); + + thread::sleep(Duration::from_secs(POLL_INTERVAL_5_MINUTES_IN_SECS)); + } + }); + + handle.join().unwrap() +} +#[cfg(feature = "attesteer")] +fn register_quotes_from_marblerun( + api: &ParentchainApi, + enclave: Arc, + accountid: &AccountId32, + is_development_mode: bool, + url: String, + marblerun_base_url: &str, +) { + let enclave = enclave.as_ref(); + let events = crate::prometheus_metrics::fetch_marblerun_events(marblerun_base_url) + .map_err(|e| { + info!("Fetching events from Marblerun failed with: {:?}, continuing with 0 events.", e); + }) + .unwrap_or_default(); + let quotes: Vec<&[u8]> = + events.iter().map(|event| event.get_quote_without_prepended_bytes()).collect(); + + for quote in quotes { + match enclave.generate_dcap_ra_extrinsic_from_quote(url.clone(), "e) { + Ok(xt) => { + send_extrinsic(xt, api, accountid, is_development_mode); + }, + Err(e) => { + error!("Extracting information from quote failed: {}", e) + }, + } + } +} +#[cfg(feature = "dcap")] +fn register_collateral( + api: &ParentchainApi, + enclave: &dyn RemoteAttestation, + accountid: &AccountId32, + is_development_mode: bool, + skip_ra: bool, +) { + //TODO generate_dcap_ra_quote() does not really need skip_ra, rethink how many layers skip_ra should be passed along + if !skip_ra { + let dcap_quote = enclave.generate_dcap_ra_quote(skip_ra).unwrap(); + let (fmspc, _tcb_info) = extract_tcb_info_from_raw_dcap_quote(&dcap_quote).unwrap(); + println!("[>] DCAP setup: register QE collateral"); + let uxt = enclave.generate_register_quoting_enclave_extrinsic(fmspc).unwrap(); + send_extrinsic(uxt, api, accountid, is_development_mode); + + println!("[>] DCAP setup: register TCB info"); + let uxt = enclave.generate_register_tcb_info_extrinsic(fmspc).unwrap(); + send_extrinsic(uxt, api, accountid, is_development_mode); + } +} + +fn send_extrinsic( + extrinsic: Vec, + api: &ParentchainApi, + fee_payer: &AccountId32, + is_development_mode: bool, +) -> Option { + // ensure account funds + if let Err(x) = setup_account_funding(api, fee_payer, extrinsic.clone(), is_development_mode) { + error!("Ensure enclave funding failed: {:?}", x); + // Return without registering the enclave. This will fail and the transaction will be banned for 30min. + return None + } + + info!("[>] send extrinsic"); + trace!( + " encoded extrinsic len: {}, payload: 0x{:}", + extrinsic.len(), + hex::encode(extrinsic.clone()) + ); + + // fixme: wait ...until_success doesn't work due to https://github.com/scs/substrate-api-client/issues/624 + // fixme: currently, we don't verify if the extrinsic was a success here + match api.submit_and_watch_opaque_extrinsic_until(&extrinsic.into(), XtStatus::Finalized) { + Ok(xt_report) => { + info!( + "[+] L1 extrinsic success. extrinsic hash: {:?} / status: {:?}", + xt_report.extrinsic_hash, xt_report.status + ); + xt_report.block_hash + }, + Err(e) => { + error!("ExtrinsicFailed {:?}", e); + None + }, + } +} + +fn start_parentchain_header_subscription_thread( + parentchain_handler: Arc>, + last_synced_header: Header, +) { + let parentchain_id = *parentchain_handler.parentchain_id(); + thread::Builder::new() + .name(format!("{:?}_parentchain_sync_loop", parentchain_id)) + .spawn(move || { + if let Err(e) = + subscribe_to_parentchain_new_headers(parentchain_handler, last_synced_header) + { + error!( + "[{:?}] parentchain block syncing terminated with a failure: {:?}", + parentchain_id, e + ); + } + println!("[!] [{:?}] parentchain block syncing has terminated", parentchain_id); + }) + .unwrap(); +} + +/// Subscribe to the node API finalized heads stream and trigger a parent chain sync +/// upon receiving a new header. +fn subscribe_to_parentchain_new_headers( + parentchain_handler: Arc>, + mut last_synced_header: Header, +) -> Result<(), Error> { + // TODO: this should be implemented by parentchain_handler directly, and not via + // exposed parentchain_api + let mut subscription = parentchain_handler + .parentchain_api() + .subscribe_finalized_heads() + .map_err(Error::ApiClient)?; + + // TODO(Kai@Litentry): + // originally we had an outer loop to try to handle the disconnection, + // see https://github.com/litentry/litentry-parachain/commit/b8059d0fad928e4bba99178451cd0d473791c437 + // but I reverted it because: + // - no graceful shutdown, we could have many mpsc channel when it doesn't go right + // - we might have multiple `sync_parentchain` running concurrently, which causes chaos in enclave side + // - I still feel it's only a workaround, not a perfect solution + // + // TODO: now the sync will panic if disconnected - it heavily relys on the worker-restart to work (even manually) + let parentchain_id = parentchain_handler.parentchain_id(); + loop { + let new_header = subscription + .next() + .ok_or(Error::ApiSubscriptionDisconnected)? + .map_err(|e| Error::ApiClient(e.into()))?; + + info!( + "[{:?}] Received finalized header update ({}), syncing parent chain...", + parentchain_id, new_header.number + ); + + last_synced_header = parentchain_handler.sync_parentchain(last_synced_header, 0, false)?; + } +} + +/// Get the public signing key of the TEE. +pub fn enclave_account(enclave_api: &E) -> AccountId32 { + let tee_public = enclave_api.get_ecc_signing_pubkey().unwrap(); + trace!("[+] Got ed25519 account of TEE = {}", tee_public.to_ss58check()); + AccountId32::from(*tee_public.as_array_ref()) +} + +/// Checks if we are the first validateer to register on the parentchain. +fn we_are_primary_worker( + node_api: &ParentchainApi, + register_enclave_xt_header: &Header, +) -> Result { + let enclave_count_of_previous_block = + node_api.enclave_count(Some(*register_enclave_xt_header.parent_hash()))?; + Ok(enclave_count_of_previous_block == 0) +} diff --git a/bitacross-worker/service/src/ocall_bridge/bridge_api.rs b/bitacross-worker/service/src/ocall_bridge/bridge_api.rs new file mode 100644 index 0000000000..71899760c1 --- /dev/null +++ b/bitacross-worker/service/src/ocall_bridge/bridge_api.rs @@ -0,0 +1,264 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 itp_enclave_api::remote_attestation::QveReport; +use lazy_static::lazy_static; +use log::*; +use parking_lot::RwLock; +use sgx_types::*; +use std::{sync::Arc, vec::Vec}; + +#[cfg(test)] +use mockall::predicate::*; +#[cfg(test)] +use mockall::*; + +lazy_static! { + /// global state for the component factory + /// access is always routed through 'Bridge', do not use directly! + static ref COMPONENT_FACTORY: RwLock>> = + RwLock::new(None); +} + +/// The Bridge is the static/global interface to inject concrete implementations +/// (or rather the factories for them) - this is done at startup of the worker. +/// On the other side, it is used by the o-call FFI to retrieve the state and forward calls +/// to their respective implementation. +pub struct Bridge; + +impl Bridge { + pub fn get_ra_api() -> Arc { + debug!("Requesting RemoteAttestation OCall API instance"); + + COMPONENT_FACTORY + .read() + .as_ref() + .expect("Component factory has not been set. Use `initialize()`") + .get_ra_api() + } + + pub fn get_sidechain_api() -> Arc { + COMPONENT_FACTORY + .read() + .as_ref() + .expect("Component factory has not been set. Use `initialize()`") + .get_sidechain_api() + } + + pub fn get_oc_api() -> Arc { + debug!("Requesting WorkerOnChain OCall API instance"); + + COMPONENT_FACTORY + .read() + .as_ref() + .expect("Component factory has not been set. Use `initialize()`") + .get_oc_api() + } + + pub fn get_ipfs_api() -> Arc { + debug!("Requesting IPFS OCall API instance"); + + COMPONENT_FACTORY + .read() + .as_ref() + .expect("Component factory has not been set. Use `initialize()`") + .get_ipfs_api() + } + + pub fn get_metrics_api() -> Arc { + COMPONENT_FACTORY + .read() + .as_ref() + .expect("Component factory has not been set. Use `initialize()`") + .get_metrics_api() + } + + pub fn initialize(component_factory: Arc) { + debug!("Initializing OCall bridge with component factory"); + + *COMPONENT_FACTORY.write() = Some(component_factory); + } +} + +/// Factory trait (abstract factory) that creates instances +/// of all the components of the OCall Bridge +pub trait GetOCallBridgeComponents { + /// remote attestation OCall API + fn get_ra_api(&self) -> Arc; + + /// side chain OCall API + fn get_sidechain_api(&self) -> Arc; + + /// on chain (parentchain) OCall API + fn get_oc_api(&self) -> Arc; + + /// ipfs OCall API + fn get_ipfs_api(&self) -> Arc; + + /// Metrics OCall API. + fn get_metrics_api(&self) -> Arc; +} + +/// OCall bridge errors +#[derive(Debug, thiserror::Error)] +pub enum OCallBridgeError { + #[error("GetQuote Error: {0}")] + GetQuote(sgx_status_t), + #[error("InitQuote Error: {0}")] + InitQuote(sgx_status_t), + #[error("GetUpdateInfo Error: {0}")] + GetUpdateInfo(sgx_status_t), + #[error("GetIasSocket Error: {0}")] + GetIasSocket(String), + #[error("UpdateMetric Error: {0}")] + UpdateMetric(String), + #[error("Propose sidechain block failed: {0}")] + ProposeSidechainBlock(String), + #[error("Failed to fetch sidechain blocks from peer: {0}")] + FetchSidechainBlocksFromPeer(String), + #[error("Sending extrinsics to parentchain failed: {0}")] + SendExtrinsicsToParentchain(String), + #[error("IPFS Error: {0}")] + IpfsError(String), + #[error("DirectInvocation Error: {0}")] + DirectInvocationError(String), + #[error(transparent)] + Codec(#[from] codec::Error), + #[error("Node API factory error: {0}")] + NodeApiFactory(#[from] itp_node_api::node_api_factory::NodeApiFactoryError), + #[error("Target A parentchain not initialized")] + TargetAParentchainNotInitialized, + #[error("Target B parentchain not initialized")] + TargetBParentchainNotInitialized, +} + +impl From for sgx_status_t { + fn from(o: OCallBridgeError) -> sgx_status_t { + match o { + OCallBridgeError::GetQuote(s) => s, + OCallBridgeError::InitQuote(s) => s, + OCallBridgeError::GetUpdateInfo(s) => s, + _ => sgx_status_t::SGX_ERROR_UNEXPECTED, + } + } +} + +pub type OCallBridgeResult = Result; + +/// Trait for all the OCalls related to remote attestation +#[cfg_attr(test, automock)] +pub trait RemoteAttestationBridge { + /// initialize the quote + fn init_quote(&self) -> OCallBridgeResult<(sgx_target_info_t, sgx_epid_group_id_t)>; + + /// get the intel attestation service socket + fn get_ias_socket(&self) -> OCallBridgeResult; + + /// retrieve the quote from intel + fn get_quote( + &self, + revocation_list: Vec, + report: sgx_report_t, + quote_type: sgx_quote_sign_type_t, + spid: sgx_spid_t, + quote_nonce: sgx_quote_nonce_t, + ) -> OCallBridgeResult<(sgx_report_t, Vec)>; + + /// retrieve the quote from dcap server + fn get_dcap_quote(&self, report: sgx_report_t, quote_size: u32) -> OCallBridgeResult>; + + // Retrieve verification of quote + fn get_qve_report_on_quote( + &self, + quote: Vec, + current_time: i64, + quote_collateral: &sgx_ql_qve_collateral_t, + qve_report_info: sgx_ql_qe_report_info_t, + supplemental_data_size: u32, + ) -> OCallBridgeResult; + + /// -- + fn get_update_info( + &self, + platform_blob: sgx_platform_info_t, + enclave_trusted: i32, + ) -> OCallBridgeResult; +} + +/// Trait for all the OCalls related to parentchain operations +#[cfg_attr(test, automock)] +pub trait WorkerOnChainBridge { + fn worker_request( + &self, + request: Vec, + parentchain_id: Vec, + ) -> OCallBridgeResult>; + + fn send_to_parentchain( + &self, + extrinsics_encoded: Vec, + parentchain_id: Vec, + await_each_inclusion: bool, + ) -> OCallBridgeResult<()>; +} + +/// Trait for updating metrics from inside the enclave. +#[cfg_attr(test, automock)] +pub trait MetricsBridge { + fn update_metric(&self, metric_encoded: Vec) -> OCallBridgeResult<()>; +} + +/// Trait for all the OCalls related to sidechain operations +#[cfg_attr(test, automock)] +pub trait SidechainBridge { + fn propose_sidechain_blocks(&self, signed_blocks_encoded: Vec) -> OCallBridgeResult<()>; + + fn store_sidechain_blocks(&self, signed_blocks_encoded: Vec) -> OCallBridgeResult<()>; + + fn fetch_sidechain_blocks_from_peer( + &self, + last_imported_block_hash_encoded: Vec, + maybe_until_block_hash_encoded: Vec, + shard_identifier_encoded: Vec, + ) -> OCallBridgeResult>; + + fn get_trusted_peers_urls(&self) -> OCallBridgeResult>; +} + +/// type for IPFS +pub type Cid = [u8; 46]; + +/// Trait for all the OCalls related to IPFS +#[cfg_attr(test, automock)] +pub trait IpfsBridge { + fn write_to_ipfs(&self, data: &'static [u8]) -> OCallBridgeResult; + + fn read_from_ipfs(&self, cid: Cid) -> OCallBridgeResult<()>; +} + +/// Trait for the direct invocation OCalls +#[cfg_attr(test, automock)] +pub trait DirectInvocationBridge { + fn update_status_event( + &self, + hash_vec: Vec, + status_update_vec: Vec, + ) -> OCallBridgeResult<()>; + + fn send_status(&self, hash_vec: Vec, status_vec: Vec) -> OCallBridgeResult<()>; +} diff --git a/bitacross-worker/service/src/ocall_bridge/component_factory.rs b/bitacross-worker/service/src/ocall_bridge/component_factory.rs new file mode 100644 index 0000000000..e23c509101 --- /dev/null +++ b/bitacross-worker/service/src/ocall_bridge/component_factory.rs @@ -0,0 +1,176 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{ + globals::tokio_handle::GetTokioHandle, + ocall_bridge::{ + bridge_api::{ + GetOCallBridgeComponents, IpfsBridge, MetricsBridge, RemoteAttestationBridge, + SidechainBridge, WorkerOnChainBridge, + }, + ipfs_ocall::IpfsOCall, + metrics_ocall::MetricsOCall, + remote_attestation_ocall::RemoteAttestationOCall, + sidechain_ocall::SidechainOCall, + worker_on_chain_ocall::WorkerOnChainOCall, + }, + prometheus_metrics::ReceiveEnclaveMetrics, + sync_block_broadcaster::BroadcastBlocks, + worker_peers_registry::PeersRegistry, +}; +use itp_enclave_api::{enclave_base::EnclaveBase, remote_attestation::RemoteAttestationCallBacks}; +use itp_node_api::node_api_factory::CreateNodeApi; +use its_peer_fetch::FetchBlocksFromPeer; +use its_primitives::types::block::SignedBlock as SignedSidechainBlock; +use its_storage::BlockStorage; +use std::sync::Arc; + +/// Concrete implementation, should be moved out of the OCall Bridge, into the worker +/// since the OCall bridge itself should not know any concrete types to ensure +/// our dependency graph is worker -> ocall bridge +pub struct OCallBridgeComponentFactory< + NodeApi, + Broadcaster, + EnclaveApi, + Storage, + WorkerPeersRegistry, + PeerBlockFetcher, + TokioHandle, + MetricsReceiver, +> { + integritee_rpc_api_factory: Arc, + target_a_parentchain_rpc_api_factory: Option>, + target_b_parentchain_rpc_api_factory: Option>, + block_broadcaster: Arc, + enclave_api: Arc, + block_storage: Arc, + peers_registry: Arc, + peer_block_fetcher: Arc, + tokio_handle: Arc, + metrics_receiver: Arc, +} + +impl< + NodeApi, + Broadcaster, + EnclaveApi, + Storage, + WorkerPeersRegistry, + PeerBlockFetcher, + TokioHandle, + MetricsReceiver, + > + OCallBridgeComponentFactory< + NodeApi, + Broadcaster, + EnclaveApi, + Storage, + WorkerPeersRegistry, + PeerBlockFetcher, + TokioHandle, + MetricsReceiver, + > +{ + #[allow(clippy::too_many_arguments)] + pub fn new( + integritee_rpc_api_factory: Arc, + target_a_parentchain_rpc_api_factory: Option>, + target_b_parentchain_rpc_api_factory: Option>, + block_broadcaster: Arc, + enclave_api: Arc, + block_storage: Arc, + peers_registry: Arc, + peer_block_fetcher: Arc, + tokio_handle: Arc, + metrics_receiver: Arc, + ) -> Self { + OCallBridgeComponentFactory { + integritee_rpc_api_factory, + target_a_parentchain_rpc_api_factory, + target_b_parentchain_rpc_api_factory, + block_broadcaster, + enclave_api, + block_storage, + peers_registry, + peer_block_fetcher, + tokio_handle, + metrics_receiver, + } + } +} + +impl< + NodeApi, + Broadcaster, + EnclaveApi, + Storage, + WorkerPeersRegistry, + PeerBlockFetcher, + TokioHandle, + MetricsReceiver, + > GetOCallBridgeComponents + for OCallBridgeComponentFactory< + NodeApi, + Broadcaster, + EnclaveApi, + Storage, + WorkerPeersRegistry, + PeerBlockFetcher, + TokioHandle, + MetricsReceiver, + > where + NodeApi: CreateNodeApi + 'static, + Broadcaster: BroadcastBlocks + 'static, + EnclaveApi: EnclaveBase + RemoteAttestationCallBacks + 'static, + Storage: BlockStorage + 'static, + WorkerPeersRegistry: PeersRegistry + 'static, + PeerBlockFetcher: FetchBlocksFromPeer + 'static, + TokioHandle: GetTokioHandle + 'static, + MetricsReceiver: ReceiveEnclaveMetrics + 'static, +{ + fn get_ra_api(&self) -> Arc { + Arc::new(RemoteAttestationOCall::new(self.enclave_api.clone())) + } + + fn get_sidechain_api(&self) -> Arc { + Arc::new(SidechainOCall::new( + self.block_broadcaster.clone(), + self.block_storage.clone(), + self.peers_registry.clone(), + self.peer_block_fetcher.clone(), + self.tokio_handle.clone(), + )) + } + + fn get_oc_api(&self) -> Arc { + Arc::new(WorkerOnChainOCall::new( + self.enclave_api.clone(), + self.integritee_rpc_api_factory.clone(), + self.target_a_parentchain_rpc_api_factory.clone(), + self.target_b_parentchain_rpc_api_factory.clone(), + )) + } + + fn get_ipfs_api(&self) -> Arc { + Arc::new(IpfsOCall {}) + } + + fn get_metrics_api(&self) -> Arc { + Arc::new(MetricsOCall::new(self.metrics_receiver.clone())) + } +} diff --git a/bitacross-worker/service/src/ocall_bridge/ffi/fetch_sidechain_blocks_from_peer.rs b/bitacross-worker/service/src/ocall_bridge/ffi/fetch_sidechain_blocks_from_peer.rs new file mode 100644 index 0000000000..c6c8b9e89e --- /dev/null +++ b/bitacross-worker/service/src/ocall_bridge/ffi/fetch_sidechain_blocks_from_peer.rs @@ -0,0 +1,193 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::ocall_bridge::bridge_api::{Bridge, SidechainBridge}; +use itp_utils::write_slice_and_whitespace_pad; +use log::*; +use sgx_types::sgx_status_t; +use std::{slice, sync::Arc}; + +/// # Safety +/// +/// FFI are always unsafe +#[no_mangle] +pub unsafe extern "C" fn ocall_fetch_sidechain_blocks_from_peer( + last_imported_block_hash_ptr: *const u8, + last_imported_block_hash_size: u32, + maybe_until_block_hash_ptr: *const u8, + maybe_until_block_hash_size: u32, + shard_identifier_ptr: *const u8, + shard_identifier_size: u32, + sidechain_blocks_ptr: *mut u8, + sidechain_blocks_size: u32, +) -> sgx_status_t { + fetch_sidechain_blocks_from_peer( + last_imported_block_hash_ptr, + last_imported_block_hash_size, + maybe_until_block_hash_ptr, + maybe_until_block_hash_size, + shard_identifier_ptr, + shard_identifier_size, + sidechain_blocks_ptr, + sidechain_blocks_size, + Bridge::get_sidechain_api(), + ) +} + +#[allow(clippy::too_many_arguments)] +fn fetch_sidechain_blocks_from_peer( + last_imported_block_hash_ptr: *const u8, + last_imported_block_hash_size: u32, + maybe_until_block_hash_ptr: *const u8, + maybe_until_block_hash_size: u32, + shard_identifier_ptr: *const u8, + shard_identifier_size: u32, + sidechain_blocks_ptr: *mut u8, + sidechain_blocks_size: u32, + sidechain_api: Arc, +) -> sgx_status_t { + let last_imported_block_hash_encoded = unsafe { + Vec::from(slice::from_raw_parts( + last_imported_block_hash_ptr, + last_imported_block_hash_size as usize, + )) + }; + let maybe_until_block_hash = unsafe { + Vec::from(slice::from_raw_parts( + maybe_until_block_hash_ptr, + maybe_until_block_hash_size as usize, + )) + }; + let shard_identifier_encoded = unsafe { + Vec::from(slice::from_raw_parts(shard_identifier_ptr, shard_identifier_size as usize)) + }; + + let sidechain_blocks_encoded = match sidechain_api.fetch_sidechain_blocks_from_peer( + last_imported_block_hash_encoded, + maybe_until_block_hash, + shard_identifier_encoded, + ) { + Ok(r) => r, + Err(e) => { + error!("fetch sidechain blocks from peer failed: {:?}", e); + return sgx_status_t::SGX_ERROR_UNEXPECTED + }, + }; + + let sidechain_blocks_encoded_slice = + unsafe { slice::from_raw_parts_mut(sidechain_blocks_ptr, sidechain_blocks_size as usize) }; + if let Err(e) = + write_slice_and_whitespace_pad(sidechain_blocks_encoded_slice, sidechain_blocks_encoded) + { + error!("Failed to transfer encoded sidechain blocks to o-call buffer: {:?}", e); + return sgx_status_t::SGX_ERROR_UNEXPECTED + } + + sgx_status_t::SGX_SUCCESS +} + +#[cfg(test)] +mod tests { + + use super::*; + use crate::ocall_bridge::test::mocks::sidechain_bridge_mock::SidechainBridgeMock; + use codec::{Decode, Encode}; + use its_primitives::types::block::SignedBlock; + use its_test::sidechain_block_builder::{SidechainBlockBuilder, SidechainBlockBuilderTrait}; + use primitive_types::H256; + + #[test] + fn fetch_sidechain_blocks_from_peer_works() { + let sidechain_blocks = vec![ + SidechainBlockBuilder::random().build_signed(), + SidechainBlockBuilder::random().build_signed(), + ]; + + let sidechain_bridge_mock = + Arc::new(SidechainBridgeMock::default().with_peer_blocks(sidechain_blocks.encode())); + + let last_known_block_hash = H256::random(); + let shard_identifier = H256::random(); + let mut block_buffer = vec![0; 16 * 4096]; + + let result = call_fetch_sidechain_blocks_from_peer( + last_known_block_hash, + None, + shard_identifier, + &mut block_buffer, + sidechain_bridge_mock, + ); + + let decoded_blocks: Vec = + Decode::decode(&mut block_buffer.as_slice()).unwrap(); + + assert_eq!(result, sgx_status_t::SGX_SUCCESS); + assert_eq!(sidechain_blocks, decoded_blocks); + } + + #[test] + fn returns_error_if_buffer_is_too_small() { + let sidechain_blocks = vec![ + SidechainBlockBuilder::random().build_signed(), + SidechainBlockBuilder::random().build_signed(), + SidechainBlockBuilder::random().build_signed(), + SidechainBlockBuilder::random().build_signed(), + ]; + + let sidechain_bridge_mock = + Arc::new(SidechainBridgeMock::default().with_peer_blocks(sidechain_blocks.encode())); + + let last_known_block_hash = H256::random(); + let shard_identifier = H256::random(); + let mut block_buffer = vec![0; 16]; // way too small to hold the encoded blocks + + let result = call_fetch_sidechain_blocks_from_peer( + last_known_block_hash, + None, + shard_identifier, + &mut block_buffer, + sidechain_bridge_mock, + ); + + assert_eq!(result, sgx_status_t::SGX_ERROR_UNEXPECTED); + } + + fn call_fetch_sidechain_blocks_from_peer( + last_imported_block_hash: H256, + maybe_until_block_hash: Option, + shard_identifier: H256, + buffer: &mut Vec, + sidechain_bridge: Arc, + ) -> sgx_status_t { + let last_imported_block_hash_encoded = last_imported_block_hash.encode(); + let maybe_until_block_hash_encoded = maybe_until_block_hash.encode(); + let shard_identifier_encoded = shard_identifier.encode(); + + fetch_sidechain_blocks_from_peer( + last_imported_block_hash_encoded.as_ptr(), + last_imported_block_hash_encoded.len() as u32, + maybe_until_block_hash_encoded.as_ptr(), + maybe_until_block_hash_encoded.len() as u32, + shard_identifier_encoded.as_ptr(), + shard_identifier_encoded.len() as u32, + buffer.as_mut_ptr(), + buffer.len() as u32, + sidechain_bridge, + ) + } +} diff --git a/bitacross-worker/service/src/ocall_bridge/ffi/get_ias_socket.rs b/bitacross-worker/service/src/ocall_bridge/ffi/get_ias_socket.rs new file mode 100644 index 0000000000..4b48d2b1ad --- /dev/null +++ b/bitacross-worker/service/src/ocall_bridge/ffi/get_ias_socket.rs @@ -0,0 +1,86 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::ocall_bridge::bridge_api::{Bridge, RemoteAttestationBridge}; +use log::*; +use sgx_types::{c_int, sgx_status_t}; +use std::sync::Arc; + +#[no_mangle] +pub extern "C" fn ocall_get_ias_socket(ret_fd: *mut c_int) -> sgx_status_t { + get_ias_socket(ret_fd, Bridge::get_ra_api()) // inject the RA API (global state) +} + +fn get_ias_socket(ret_fd: *mut c_int, ra_api: Arc) -> sgx_status_t { + debug!(" Entering ocall_get_ias_socket"); + let socket_result = ra_api.get_ias_socket(); + + return match socket_result { + Ok(s) => { + unsafe { + *ret_fd = s; + } + sgx_status_t::SGX_SUCCESS + }, + Err(e) => { + error!("[-] Failed to get IAS socket: {:?}", e); + return e.into() + }, + } +} + +#[cfg(test)] +mod tests { + + use super::*; + use crate::ocall_bridge::bridge_api::{MockRemoteAttestationBridge, OCallBridgeError}; + use std::sync::Arc; + + #[test] + fn get_socket_sets_pointer_result() { + let expected_socket = 4321i32; + + let mut ra_ocall_api_mock = MockRemoteAttestationBridge::new(); + ra_ocall_api_mock + .expect_get_ias_socket() + .times(1) + .returning(move || Ok(expected_socket)); + + let mut ias_sock: i32 = 0; + + let ret_status = get_ias_socket(&mut ias_sock as *mut i32, Arc::new(ra_ocall_api_mock)); + + assert_eq!(ret_status, sgx_status_t::SGX_SUCCESS); + assert_eq!(ias_sock, expected_socket); + } + + #[test] + fn given_error_from_ocall_impl_then_return_sgx_error() { + let mut ra_ocall_api_mock = MockRemoteAttestationBridge::new(); + ra_ocall_api_mock + .expect_get_ias_socket() + .times(1) + .returning(|| Err(OCallBridgeError::GetIasSocket("test error".to_string()))); + + let mut ias_sock: i32 = 0; + let ret_status = get_ias_socket(&mut ias_sock as *mut i32, Arc::new(ra_ocall_api_mock)); + + assert_ne!(ret_status, sgx_status_t::SGX_SUCCESS); + assert_eq!(ias_sock, 0); + } +} diff --git a/bitacross-worker/service/src/ocall_bridge/ffi/get_peers.rs b/bitacross-worker/service/src/ocall_bridge/ffi/get_peers.rs new file mode 100644 index 0000000000..2cc380d6e4 --- /dev/null +++ b/bitacross-worker/service/src/ocall_bridge/ffi/get_peers.rs @@ -0,0 +1,37 @@ +use crate::ocall_bridge::bridge_api::{Bridge, SidechainBridge}; +use itp_utils::write_slice_and_whitespace_pad; +use log::*; +use sgx_types::sgx_status_t; +use std::{slice, sync::Arc}; + +#[no_mangle] +pub unsafe extern "C" fn ocall_get_trusted_peers_urls( + peers_ptr: *mut u8, + peers_size: u32, +) -> sgx_status_t { + get_trusted_peers_urls(peers_ptr, peers_size, Bridge::get_sidechain_api()) +} + +fn get_trusted_peers_urls( + peers_ptr: *mut u8, + peers_size: u32, + sidechain_api: Arc, +) -> sgx_status_t { + debug!(" Entering ocall_get_trusted_peers_urls"); + + let peers_encoded = match sidechain_api.get_trusted_peers_urls() { + Ok(r) => r, + Err(e) => { + error!("get peers failed: {:?}", e); + return sgx_status_t::SGX_ERROR_UNEXPECTED + }, + }; + + let peers_encoded_slice = unsafe { slice::from_raw_parts_mut(peers_ptr, peers_size as usize) }; + if let Err(e) = write_slice_and_whitespace_pad(peers_encoded_slice, peers_encoded) { + error!("Failed to transfer encoded peers to o-call buffer: {:?}", e); + return sgx_status_t::SGX_ERROR_UNEXPECTED + } + + sgx_status_t::SGX_SUCCESS +} diff --git a/bitacross-worker/service/src/ocall_bridge/ffi/get_quote.rs b/bitacross-worker/service/src/ocall_bridge/ffi/get_quote.rs new file mode 100644 index 0000000000..abf2954170 --- /dev/null +++ b/bitacross-worker/service/src/ocall_bridge/ffi/get_quote.rs @@ -0,0 +1,140 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::ocall_bridge::bridge_api::{Bridge, RemoteAttestationBridge}; +use log::*; +use sgx_types::{sgx_quote_nonce_t, sgx_quote_sign_type_t, sgx_report_t, sgx_spid_t, sgx_status_t}; +use std::{slice, sync::Arc}; + +/// p_quote must be a pre-allocated memory region of size `maxlen` +#[no_mangle] +pub unsafe extern "C" fn ocall_get_quote( + p_sigrl: *const u8, + sigrl_len: u32, + p_report: *const sgx_report_t, + quote_type: sgx_quote_sign_type_t, + p_spid: *const sgx_spid_t, + p_nonce: *const sgx_quote_nonce_t, + p_qe_report: *mut sgx_report_t, + p_quote: *mut u8, + maxlen: u32, + p_quote_len: *mut u32, +) -> sgx_status_t { + get_quote( + p_sigrl, + sigrl_len, + p_report, + quote_type, + p_spid, + p_nonce, + p_qe_report, + p_quote, + maxlen, + p_quote_len, + Bridge::get_ra_api(), // inject the RA API (global state) + ) +} + +#[allow(clippy::too_many_arguments)] +fn get_quote( + p_sigrl: *const u8, + sigrl_len: u32, + p_report: *const sgx_report_t, + quote_type: sgx_quote_sign_type_t, + p_spid: *const sgx_spid_t, + p_nonce: *const sgx_quote_nonce_t, + p_qe_report: *mut sgx_report_t, + p_quote: *mut u8, + maxlen: u32, + p_quote_len: *mut u32, + ra_api: Arc, +) -> sgx_status_t { + debug!(" Entering ocall_get_quote"); + + let revocation_list: Vec = + unsafe { slice::from_raw_parts(p_sigrl, sigrl_len as usize).to_vec() }; + + let report = unsafe { *p_report }; + let spid = unsafe { *p_spid }; + let quote_nonce = unsafe { *p_nonce }; + + let get_quote_result = + match ra_api.get_quote(revocation_list, report, quote_type, spid, quote_nonce) { + Ok(r) => r, + Err(e) => { + error!("[-] Failed to get quote: {:?}", e); + return e.into() + }, + }; + + let quote = get_quote_result.1; + + if quote.len() as u32 > maxlen { + return sgx_status_t::SGX_ERROR_FAAS_BUFFER_TOO_SHORT + } + + let quote_slice = unsafe { slice::from_raw_parts_mut(p_quote, quote.len()) }; + quote_slice.clone_from_slice(quote.as_slice()); + + unsafe { + *p_qe_report = get_quote_result.0; + *p_quote_len = quote.len() as u32; + }; + + sgx_status_t::SGX_SUCCESS +} + +#[no_mangle] +pub unsafe extern "C" fn ocall_get_dcap_quote( + p_report: *const sgx_report_t, + p_quote: *mut u8, + quote_size: u32, +) -> sgx_status_t { + get_dcap_quote( + p_report, + p_quote, + quote_size, + Bridge::get_ra_api(), // inject the RA API (global state) + ) +} + +fn get_dcap_quote( + p_report: *const sgx_report_t, + p_quote: *mut u8, + quote_size: u32, + ra_api: Arc, +) -> sgx_status_t { + let report = unsafe { *p_report }; + + let quote = match ra_api.get_dcap_quote(report, quote_size) { + Ok(r) => r, + Err(e) => { + error!("Failed to get dcap quote: {:?}", e); + return e.into() + }, + }; + + if quote.len() as u32 > quote_size { + return sgx_status_t::SGX_ERROR_FAAS_BUFFER_TOO_SHORT + } + + let quote_slice = unsafe { slice::from_raw_parts_mut(p_quote, quote.len()) }; + quote_slice.clone_from_slice(quote.as_slice()); + + sgx_status_t::SGX_SUCCESS +} diff --git a/bitacross-worker/service/src/ocall_bridge/ffi/get_qve_report_on_quote.rs b/bitacross-worker/service/src/ocall_bridge/ffi/get_qve_report_on_quote.rs new file mode 100755 index 0000000000..2b73894830 --- /dev/null +++ b/bitacross-worker/service/src/ocall_bridge/ffi/get_qve_report_on_quote.rs @@ -0,0 +1,100 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::ocall_bridge::bridge_api::{Bridge, RemoteAttestationBridge}; +use log::*; +use sgx_types::*; +use std::{slice, sync::Arc}; + +#[no_mangle] +pub unsafe extern "C" fn ocall_get_qve_report_on_quote( + p_quote: *const u8, + quote_len: u32, + current_time: i64, + p_quote_collateral: *const sgx_ql_qve_collateral_t, + p_collateral_expiration_status: *mut u32, + p_quote_verification_result: *mut sgx_ql_qv_result_t, + p_qve_report_info: *mut sgx_ql_qe_report_info_t, + p_supplemental_data: *mut u8, + supplemental_data_size: u32, +) -> sgx_status_t { + get_qve_report_on_quote( + p_quote, + quote_len, + current_time, + p_quote_collateral, + p_collateral_expiration_status, + p_quote_verification_result, + p_qve_report_info, + p_supplemental_data, + supplemental_data_size, + Bridge::get_ra_api(), // inject the RA API (global state) + ) +} + +#[allow(clippy::too_many_arguments)] +fn get_qve_report_on_quote( + p_quote: *const u8, + quote_len: u32, + current_time: i64, + p_quote_collateral: *const sgx_ql_qve_collateral_t, + p_collateral_expiration_status: *mut u32, + p_quote_verification_result: *mut sgx_ql_qv_result_t, + p_qve_report_info: *mut sgx_ql_qe_report_info_t, + p_supplemental_data: *mut u8, + supplemental_data_size: u32, + ra_api: Arc, +) -> sgx_status_t { + debug!("Entering ocall_get_qve_report_on_quote"); + if p_quote.is_null() + || quote_len == 0 + || p_quote_collateral.is_null() + || p_collateral_expiration_status.is_null() + || p_quote_verification_result.is_null() + || p_qve_report_info.is_null() + || p_supplemental_data.is_null() + || supplemental_data_size == 0 + { + return sgx_status_t::SGX_ERROR_INVALID_PARAMETER + } + let quote: Vec = unsafe { slice::from_raw_parts(p_quote, quote_len as usize).to_vec() }; + let quote_collateral = unsafe { &*p_quote_collateral }; + let qve_report_info = unsafe { *p_qve_report_info }; + + let qve_report = match ra_api.get_qve_report_on_quote( + quote, + current_time, + quote_collateral, + qve_report_info, + supplemental_data_size, + ) { + Ok(return_values) => return_values, + Err(e) => { + error!("Failed to get quote: {:?}", e); + return e.into() + }, + }; + + let supplemental_data_slice = + unsafe { slice::from_raw_parts_mut(p_supplemental_data, supplemental_data_size as usize) }; + supplemental_data_slice.clone_from_slice(qve_report.supplemental_data.as_slice()); + + unsafe { + *p_collateral_expiration_status = qve_report.collateral_expiration_status; + *p_quote_verification_result = qve_report.quote_verification_result; + *p_qve_report_info = qve_report.qve_report_info_return_value; + }; + + sgx_status_t::SGX_SUCCESS +} diff --git a/bitacross-worker/service/src/ocall_bridge/ffi/get_update_info.rs b/bitacross-worker/service/src/ocall_bridge/ffi/get_update_info.rs new file mode 100644 index 0000000000..55a9c7bfb4 --- /dev/null +++ b/bitacross-worker/service/src/ocall_bridge/ffi/get_update_info.rs @@ -0,0 +1,61 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::ocall_bridge::bridge_api::{Bridge, RemoteAttestationBridge}; +use log::*; +use sgx_types::{sgx_platform_info_t, sgx_status_t, sgx_update_info_bit_t}; +use std::sync::Arc; + +#[no_mangle] +pub extern "C" fn ocall_get_update_info( + p_platform_blob: *const sgx_platform_info_t, + enclave_trusted: i32, + p_update_info: *mut sgx_update_info_bit_t, +) -> sgx_status_t { + get_update_info( + p_platform_blob, + enclave_trusted, + p_update_info, + Bridge::get_ra_api(), // inject the RA API (global state) + ) +} + +fn get_update_info( + p_platform_blob: *const sgx_platform_info_t, + enclave_trusted: i32, + p_update_info: *mut sgx_update_info_bit_t, + ra_api: Arc, +) -> sgx_status_t { + debug!(" Entering ocall_get_update_info"); + + let platform_blob = unsafe { *p_platform_blob }; + + let update_info_result = match ra_api.get_update_info(platform_blob, enclave_trusted) { + Ok(r) => r, + Err(e) => { + error!("[-] Failed to get update info: {:?}", e); + return e.into() + }, + }; + + unsafe { + *p_update_info = update_info_result; + } + + sgx_status_t::SGX_SUCCESS +} diff --git a/bitacross-worker/service/src/ocall_bridge/ffi/init_quote.rs b/bitacross-worker/service/src/ocall_bridge/ffi/init_quote.rs new file mode 100644 index 0000000000..095e01af6d --- /dev/null +++ b/bitacross-worker/service/src/ocall_bridge/ffi/init_quote.rs @@ -0,0 +1,85 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::ocall_bridge::bridge_api::{Bridge, RemoteAttestationBridge}; +use log::*; +use sgx_types::{sgx_epid_group_id_t, sgx_status_t, sgx_target_info_t}; +use std::sync::Arc; + +#[no_mangle] +pub unsafe extern "C" fn ocall_sgx_init_quote( + ret_ti: *mut sgx_target_info_t, + ret_gid: *mut sgx_epid_group_id_t, +) -> sgx_status_t { + sgx_init_quote(ret_ti, ret_gid, Bridge::get_ra_api()) // inject the RA API (global state) +} + +fn sgx_init_quote( + ret_ti: *mut sgx_target_info_t, + ret_gid: *mut sgx_epid_group_id_t, + ra_api: Arc, +) -> sgx_status_t { + debug!(" Entering ocall_sgx_init_quote"); + let init_result = match ra_api.init_quote() { + Ok(r) => r, + Err(e) => { + error!("[-] Failed to init quote: {:?}", e); + return e.into() + }, + }; + + unsafe { + *ret_ti = init_result.0; + *ret_gid = init_result.1; + } + + sgx_status_t::SGX_SUCCESS +} + +#[cfg(test)] +mod tests { + + use super::*; + use crate::ocall_bridge::bridge_api::MockRemoteAttestationBridge; + use std::sync::Arc; + + #[test] + fn init_quote_sets_results() { + let mut ra_ocall_api_mock = MockRemoteAttestationBridge::new(); + ra_ocall_api_mock + .expect_init_quote() + .times(1) + .returning(|| Ok((dummy_target_info(), [8u8; 4]))); + + let mut ti: sgx_target_info_t = sgx_target_info_t::default(); + let mut eg: sgx_epid_group_id_t = sgx_epid_group_id_t::default(); + + let ret_status = sgx_init_quote( + &mut ti as *mut sgx_target_info_t, + &mut eg as *mut sgx_epid_group_id_t, + Arc::new(ra_ocall_api_mock), + ); + + assert_eq!(ret_status, sgx_status_t::SGX_SUCCESS); + assert_eq!(eg, [8u8; 4]); + } + + fn dummy_target_info() -> sgx_target_info_t { + sgx_target_info_t::default() + } +} diff --git a/bitacross-worker/service/src/ocall_bridge/ffi/ipfs.rs b/bitacross-worker/service/src/ocall_bridge/ffi/ipfs.rs new file mode 100644 index 0000000000..e264b49db2 --- /dev/null +++ b/bitacross-worker/service/src/ocall_bridge/ffi/ipfs.rs @@ -0,0 +1,76 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::ocall_bridge::bridge_api::{Bridge, Cid, IpfsBridge}; +use log::*; +use sgx_types::sgx_status_t; +use std::{slice, sync::Arc}; + +/// C-API exposed for o-call from enclave +#[no_mangle] +pub unsafe extern "C" fn ocall_write_ipfs( + enc_state: *const u8, + enc_state_size: u32, + cid: *mut u8, + cid_size: u32, +) -> sgx_status_t { + write_ipfs(enc_state, enc_state_size, cid, cid_size, Bridge::get_ipfs_api()) +} + +/// C-API exposed for o-call from enclave +#[no_mangle] +pub unsafe extern "C" fn ocall_read_ipfs(cid: *const u8, cid_size: u32) -> sgx_status_t { + read_ipfs(cid, cid_size, Bridge::get_ipfs_api()) +} + +fn write_ipfs( + enc_state: *const u8, + enc_state_size: u32, + cid: *mut u8, + cid_size: u32, + ipfs_api: Arc, +) -> sgx_status_t { + let state = unsafe { slice::from_raw_parts(enc_state, enc_state_size as usize) }; + let cid = unsafe { slice::from_raw_parts_mut(cid, cid_size as usize) }; + + return match ipfs_api.write_to_ipfs(state) { + Ok(r) => { + cid.clone_from_slice(&r); + sgx_status_t::SGX_SUCCESS + }, + Err(e) => { + error!("OCall to write_ipfs failed: {:?}", e); + sgx_status_t::SGX_ERROR_UNEXPECTED + }, + } +} + +fn read_ipfs(cid: *const u8, cid_size: u32, ipfs_api: Arc) -> sgx_status_t { + let _cid = unsafe { slice::from_raw_parts(cid, cid_size as usize) }; + + let mut cid: Cid = [0; 46]; + cid.clone_from_slice(_cid); + + match ipfs_api.read_from_ipfs(cid) { + Ok(_) => sgx_status_t::SGX_SUCCESS, + Err(e) => { + error!("OCall to read_ipfs failed: {:?}", e); + sgx_status_t::SGX_ERROR_UNEXPECTED + }, + } +} diff --git a/bitacross-worker/service/src/ocall_bridge/ffi/mod.rs b/bitacross-worker/service/src/ocall_bridge/ffi/mod.rs new file mode 100644 index 0000000000..d146db1046 --- /dev/null +++ b/bitacross-worker/service/src/ocall_bridge/ffi/mod.rs @@ -0,0 +1,36 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +//! Foreign Function interface for all the OCalls. +//! Implementations of C-API functions, that can be called from the Enclave. +//! These should just be wrappers that transform the C-API structures and call the +//! actual implementation of the OCalls (using the traits defined in the bridge_api). + +pub mod fetch_sidechain_blocks_from_peer; +pub mod get_ias_socket; +pub mod get_peers; +pub mod get_quote; +pub mod get_qve_report_on_quote; +pub mod get_update_info; +pub mod init_quote; +pub mod ipfs; +pub mod propose_sidechain_blocks; +pub mod send_to_parentchain; +pub mod store_sidechain_blocks; +pub mod update_metric; +pub mod worker_request; diff --git a/bitacross-worker/service/src/ocall_bridge/ffi/propose_sidechain_blocks.rs b/bitacross-worker/service/src/ocall_bridge/ffi/propose_sidechain_blocks.rs new file mode 100644 index 0000000000..21ff07d0bb --- /dev/null +++ b/bitacross-worker/service/src/ocall_bridge/ffi/propose_sidechain_blocks.rs @@ -0,0 +1,50 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::ocall_bridge::bridge_api::{Bridge, SidechainBridge}; +use log::*; +use sgx_types::sgx_status_t; +use std::{slice, sync::Arc}; + +/// # Safety +/// +/// FFI are always unsafe +#[no_mangle] +pub unsafe extern "C" fn ocall_propose_sidechain_blocks( + signed_blocks_ptr: *const u8, + signed_blocks_size: u32, +) -> sgx_status_t { + propose_sidechain_blocks(signed_blocks_ptr, signed_blocks_size, Bridge::get_sidechain_api()) +} + +fn propose_sidechain_blocks( + signed_blocks_ptr: *const u8, + signed_blocks_size: u32, + sidechain_api: Arc, +) -> sgx_status_t { + let signed_blocks_vec: Vec = + unsafe { Vec::from(slice::from_raw_parts(signed_blocks_ptr, signed_blocks_size as usize)) }; + + match sidechain_api.propose_sidechain_blocks(signed_blocks_vec) { + Ok(_) => sgx_status_t::SGX_SUCCESS, + Err(e) => { + error!("send sidechain blocks failed: {:?}", e); + sgx_status_t::SGX_ERROR_UNEXPECTED + }, + } +} diff --git a/bitacross-worker/service/src/ocall_bridge/ffi/send_to_parentchain.rs b/bitacross-worker/service/src/ocall_bridge/ffi/send_to_parentchain.rs new file mode 100644 index 0000000000..d7e524a254 --- /dev/null +++ b/bitacross-worker/service/src/ocall_bridge/ffi/send_to_parentchain.rs @@ -0,0 +1,67 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::ocall_bridge::bridge_api::{Bridge, WorkerOnChainBridge}; +use log::*; +use sgx_types::{c_int, sgx_status_t}; +use std::{slice, sync::Arc, vec::Vec}; + +/// # Safety +/// +/// FFI are always unsafe +#[no_mangle] +pub unsafe extern "C" fn ocall_send_to_parentchain( + extrinsics_encoded: *const u8, + extrinsics_encoded_size: u32, + parentchain_id: *const u8, + parentchain_id_size: u32, + await_each_inclusion: c_int, +) -> sgx_status_t { + send_to_parentchain( + extrinsics_encoded, + extrinsics_encoded_size, + parentchain_id, + parentchain_id_size, + await_each_inclusion == 1, + Bridge::get_oc_api(), + ) +} + +fn send_to_parentchain( + extrinsics_encoded: *const u8, + extrinsics_encoded_size: u32, + parentchain_id: *const u8, + parentchain_id_size: u32, + await_each_inclusion: bool, + oc_api: Arc, +) -> sgx_status_t { + let extrinsics_encoded_vec: Vec = unsafe { + Vec::from(slice::from_raw_parts(extrinsics_encoded, extrinsics_encoded_size as usize)) + }; + + let parentchain_id: Vec = + unsafe { Vec::from(slice::from_raw_parts(parentchain_id, parentchain_id_size as usize)) }; + + match oc_api.send_to_parentchain(extrinsics_encoded_vec, parentchain_id, await_each_inclusion) { + Ok(_) => sgx_status_t::SGX_SUCCESS, + Err(e) => { + error!("send extrinsics_encoded failed: {:?}", e); + sgx_status_t::SGX_ERROR_UNEXPECTED + }, + } +} diff --git a/bitacross-worker/service/src/ocall_bridge/ffi/store_sidechain_blocks.rs b/bitacross-worker/service/src/ocall_bridge/ffi/store_sidechain_blocks.rs new file mode 100644 index 0000000000..70361d8fd7 --- /dev/null +++ b/bitacross-worker/service/src/ocall_bridge/ffi/store_sidechain_blocks.rs @@ -0,0 +1,50 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::ocall_bridge::bridge_api::{Bridge, SidechainBridge}; +use log::*; +use sgx_types::sgx_status_t; +use std::{slice, sync::Arc}; + +/// # Safety +/// +/// FFI are always unsafe +#[no_mangle] +pub unsafe extern "C" fn ocall_store_sidechain_blocks( + signed_blocks_ptr: *const u8, + signed_blocks_size: u32, +) -> sgx_status_t { + store_sidechain_blocks(signed_blocks_ptr, signed_blocks_size, Bridge::get_sidechain_api()) +} + +fn store_sidechain_blocks( + signed_blocks_ptr: *const u8, + signed_blocks_size: u32, + sidechain_api: Arc, +) -> sgx_status_t { + let signed_blocks_vec: Vec = + unsafe { Vec::from(slice::from_raw_parts(signed_blocks_ptr, signed_blocks_size as usize)) }; + + match sidechain_api.store_sidechain_blocks(signed_blocks_vec) { + Ok(_) => sgx_status_t::SGX_SUCCESS, + Err(e) => { + error!("store sidechain blocks failed: {:?}", e); + sgx_status_t::SGX_ERROR_UNEXPECTED + }, + } +} diff --git a/bitacross-worker/service/src/ocall_bridge/ffi/update_metric.rs b/bitacross-worker/service/src/ocall_bridge/ffi/update_metric.rs new file mode 100644 index 0000000000..0b97de74f9 --- /dev/null +++ b/bitacross-worker/service/src/ocall_bridge/ffi/update_metric.rs @@ -0,0 +1,50 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::ocall_bridge::bridge_api::{Bridge, MetricsBridge}; +use log::*; +use sgx_types::sgx_status_t; +use std::{slice, sync::Arc}; + +/// # Safety +/// +/// FFI are always unsafe +#[no_mangle] +pub unsafe extern "C" fn ocall_update_metric( + metric_ptr: *const u8, + metric_size: u32, +) -> sgx_status_t { + update_metric(metric_ptr, metric_size, Bridge::get_metrics_api()) +} + +fn update_metric( + metric_ptr: *const u8, + metric_size: u32, + oc_api: Arc, +) -> sgx_status_t { + let metric_encoded: Vec = + unsafe { Vec::from(slice::from_raw_parts(metric_ptr, metric_size as usize)) }; + + match oc_api.update_metric(metric_encoded) { + Ok(_) => sgx_status_t::SGX_SUCCESS, + Err(e) => { + error!("update_metric o-call failed: {:?}", e); + sgx_status_t::SGX_ERROR_UNEXPECTED + }, + } +} diff --git a/bitacross-worker/service/src/ocall_bridge/ffi/worker_request.rs b/bitacross-worker/service/src/ocall_bridge/ffi/worker_request.rs new file mode 100644 index 0000000000..7dbd9be957 --- /dev/null +++ b/bitacross-worker/service/src/ocall_bridge/ffi/worker_request.rs @@ -0,0 +1,77 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::ocall_bridge::bridge_api::{Bridge, WorkerOnChainBridge}; +use itp_utils::write_slice_and_whitespace_pad; +use log::*; +use sgx_types::sgx_status_t; +use std::{slice, sync::Arc, vec::Vec}; + +/// # Safety +/// +/// FFI are always unsafe +#[no_mangle] +pub unsafe extern "C" fn ocall_worker_request( + request: *const u8, + req_size: u32, + parentchain_id: *const u8, + parentchain_id_size: u32, + response: *mut u8, + resp_size: u32, +) -> sgx_status_t { + worker_request( + request, + req_size, + parentchain_id, + parentchain_id_size, + response, + resp_size, + Bridge::get_oc_api(), + ) +} + +fn worker_request( + request: *const u8, + req_size: u32, + parentchain_id: *const u8, + parentchain_id_size: u32, + response: *mut u8, + resp_size: u32, + oc_api: Arc, +) -> sgx_status_t { + let request_vec: Vec = + unsafe { Vec::from(slice::from_raw_parts(request, req_size as usize)) }; + + let parentchain_id: Vec = + unsafe { Vec::from(slice::from_raw_parts(parentchain_id, parentchain_id_size as usize)) }; + + match oc_api.worker_request(request_vec, parentchain_id) { + Ok(r) => { + let resp_slice = unsafe { slice::from_raw_parts_mut(response, resp_size as usize) }; + if let Err(e) = write_slice_and_whitespace_pad(resp_slice, r) { + error!("Failed to transfer worker request response to o-call buffer: {:?}", e); + return sgx_status_t::SGX_ERROR_UNEXPECTED + } + sgx_status_t::SGX_SUCCESS + }, + Err(e) => { + error!("Worker request failed: {:?}", e); + sgx_status_t::SGX_ERROR_UNEXPECTED + }, + } +} diff --git a/bitacross-worker/service/src/ocall_bridge/ipfs_ocall.rs b/bitacross-worker/service/src/ocall_bridge/ipfs_ocall.rs new file mode 100644 index 0000000000..1dc1d9beab --- /dev/null +++ b/bitacross-worker/service/src/ocall_bridge/ipfs_ocall.rs @@ -0,0 +1,112 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::ocall_bridge::bridge_api::{Cid, IpfsBridge, OCallBridgeError, OCallBridgeResult}; +use futures::TryStreamExt; +use ipfs_api::IpfsClient; +use log::*; +use std::{ + fs::File, + io::{Cursor, Write}, + str, + sync::mpsc::channel, +}; + +pub struct IpfsOCall; + +impl IpfsBridge for IpfsOCall { + fn write_to_ipfs(&self, data: &'static [u8]) -> OCallBridgeResult { + debug!(" Entering ocall_write_ipfs"); + write_to_ipfs(data) + } + + fn read_from_ipfs(&self, cid: Cid) -> OCallBridgeResult<()> { + debug!("Entering ocall_read_ipfs"); + + let result = read_from_ipfs(cid); + match result { + Ok(res) => { + let filename = str::from_utf8(&cid).map_err(|_| { + OCallBridgeError::IpfsError("Could not convert cid bytes".to_string()) + })?; + create_file(filename, &res).map_err(OCallBridgeError::IpfsError) + }, + Err(_) => Err(OCallBridgeError::IpfsError("failed to read from IPFS".to_string())), + } + } +} + +fn create_file(filename: &str, result: &[u8]) -> Result<(), String> { + match File::create(filename) { + Ok(mut f) => f + .write_all(result) + .map_or_else(|e| Err(format!("failed writing to file: {}", e)), |_| Ok(())), + Err(e) => Err(format!("failed to create file: {}", e)), + } +} + +#[tokio::main] +async fn write_to_ipfs(data: &'static [u8]) -> OCallBridgeResult { + // Creates an `IpfsClient` connected to the endpoint specified in ~/.ipfs/api. + // If not found, tries to connect to `localhost:5001`. + let client = IpfsClient::default(); + + match client.version().await { + Ok(version) => info!("version: {:?}", version.version), + Err(e) => eprintln!("error getting version: {}", e), + } + + let datac = Cursor::new(data); + let (tx, rx) = channel(); + + match client.add(datac).await { + Ok(res) => { + info!("Result Hash {}", res.hash); + tx.send(res.hash.into_bytes()).map_err(|e| { + OCallBridgeError::IpfsError(format!( + "Could not get result from IPFS, reason: {:?}", + e + )) + })? + }, + Err(e) => eprintln!("error adding file: {}", e), + } + let mut cid: Cid = [0; 46]; + let result = &rx.recv().map_err(|e| { + OCallBridgeError::IpfsError(format!("Could not get result from IPFS, reason: {:?}", e)) + })?; + cid.clone_from_slice(result); + Ok(cid) +} + +#[tokio::main] +pub async fn read_from_ipfs(cid: Cid) -> Result, String> { + // Creates an `IpfsClient` connected to the endpoint specified in ~/.ipfs/api. + // If not found, tries to connect to `localhost:5001`. + let client = IpfsClient::default(); + let h = str::from_utf8(&cid).map_err(|_| "Could not convert cid bytes".to_string())?; + + info!("Fetching content from: {}", h); + + client + .cat(h) + .map_ok(|chunk| chunk.to_vec()) + .map_err(|e| e.to_string()) + .try_concat() + .await +} diff --git a/bitacross-worker/service/src/ocall_bridge/metrics_ocall.rs b/bitacross-worker/service/src/ocall_bridge/metrics_ocall.rs new file mode 100644 index 0000000000..a06deff339 --- /dev/null +++ b/bitacross-worker/service/src/ocall_bridge/metrics_ocall.rs @@ -0,0 +1,51 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{ + ocall_bridge::bridge_api::{MetricsBridge, OCallBridgeError, OCallBridgeResult}, + prometheus_metrics::ReceiveEnclaveMetrics, +}; +use codec::Decode; +use itp_enclave_metrics::EnclaveMetric; +use std::sync::Arc; + +pub struct MetricsOCall { + receiver: Arc, +} + +impl MetricsOCall { + pub fn new(receiver: Arc) -> Self { + MetricsOCall { receiver } + } +} + +impl MetricsBridge for MetricsOCall +where + MetricsReceiver: ReceiveEnclaveMetrics, +{ + fn update_metric(&self, metric_encoded: Vec) -> OCallBridgeResult<()> { + let metric: EnclaveMetric = + Decode::decode(&mut metric_encoded.as_slice()).map_err(|e| { + OCallBridgeError::UpdateMetric(format!("Failed to decode metric: {:?}", e)) + })?; + + self.receiver.receive_enclave_metric(metric).map_err(|e| { + OCallBridgeError::UpdateMetric(format!("Failed to receive enclave metric: {:?}", e)) + }) + } +} diff --git a/bitacross-worker/service/src/ocall_bridge/mod.rs b/bitacross-worker/service/src/ocall_bridge/mod.rs new file mode 100644 index 0000000000..91a5f8887f --- /dev/null +++ b/bitacross-worker/service/src/ocall_bridge/mod.rs @@ -0,0 +1,32 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +// TODO This entire module should be extracted to a separate crate and re-named to o-call tunnel, see #288 and #316 + +pub mod bridge_api; +pub mod component_factory; + +mod ffi; +mod ipfs_ocall; +mod metrics_ocall; +mod remote_attestation_ocall; +mod sidechain_ocall; +mod worker_on_chain_ocall; + +#[cfg(test)] +pub mod test; diff --git a/bitacross-worker/service/src/ocall_bridge/remote_attestation_ocall.rs b/bitacross-worker/service/src/ocall_bridge/remote_attestation_ocall.rs new file mode 100644 index 0000000000..0310f7ad18 --- /dev/null +++ b/bitacross-worker/service/src/ocall_bridge/remote_attestation_ocall.rs @@ -0,0 +1,150 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::ocall_bridge::bridge_api::{ + OCallBridgeError, OCallBridgeResult, RemoteAttestationBridge, +}; +use itp_enclave_api::remote_attestation::{QveReport, RemoteAttestationCallBacks}; +use log::debug; +use sgx_types::*; +use std::{ + net::{SocketAddr, TcpStream}, + os::unix::io::IntoRawFd, + sync::Arc, +}; + +pub struct RemoteAttestationOCall { + enclave_api: Arc, +} + +impl RemoteAttestationOCall { + pub fn new(enclave_api: Arc) -> Self { + RemoteAttestationOCall { enclave_api } + } +} + +impl RemoteAttestationBridge for RemoteAttestationOCall +where + E: RemoteAttestationCallBacks, +{ + fn init_quote(&self) -> OCallBridgeResult<(sgx_target_info_t, sgx_epid_group_id_t)> { + debug!("RemoteAttestationBridge: init quote"); + self.enclave_api.init_quote().map_err(|e| match e { + itp_enclave_api::error::Error::Sgx(s) => OCallBridgeError::InitQuote(s), + _ => OCallBridgeError::InitQuote(sgx_status_t::SGX_ERROR_UNEXPECTED), + }) + } + + fn get_ias_socket(&self) -> OCallBridgeResult { + let port = 443; + let hostname = "api.trustedservices.intel.com"; + + let addr = lookup_ipv4(hostname, port).map_err(OCallBridgeError::GetIasSocket)?; + + let stream = TcpStream::connect(addr).map_err(|_| { + OCallBridgeError::GetIasSocket("[-] Connect tls server failed!".to_string()) + })?; + + Ok(stream.into_raw_fd()) + } + + fn get_quote( + &self, + revocation_list: Vec, + report: sgx_report_t, + quote_type: sgx_quote_sign_type_t, + spid: sgx_spid_t, + quote_nonce: sgx_quote_nonce_t, + ) -> OCallBridgeResult<(sgx_report_t, Vec)> { + debug!("RemoteAttestationBridge: get quote type: {:?}", quote_type); + let real_quote_len = + self.enclave_api.calc_quote_size(revocation_list.clone()).map_err(|e| match e { + itp_enclave_api::error::Error::Sgx(s) => OCallBridgeError::GetQuote(s), + _ => OCallBridgeError::GetQuote(sgx_status_t::SGX_ERROR_UNEXPECTED), + })?; + + debug!("RemoteAttestationBridge: real quote length: {}", real_quote_len); + self.enclave_api + .get_quote(revocation_list, report, quote_type, spid, quote_nonce, real_quote_len) + .map_err(|e| match e { + itp_enclave_api::error::Error::Sgx(s) => OCallBridgeError::GetQuote(s), + _ => OCallBridgeError::GetQuote(sgx_status_t::SGX_ERROR_UNEXPECTED), + }) + } + + fn get_dcap_quote(&self, report: sgx_report_t, quote_size: u32) -> OCallBridgeResult> { + debug!("RemoteAttestationBridge: get dcap quote, size: {}", quote_size); + + self.enclave_api.get_dcap_quote(report, quote_size).map_err(|e| match e { + itp_enclave_api::error::Error::Sgx(s) => OCallBridgeError::GetQuote(s), + _ => OCallBridgeError::GetQuote(sgx_status_t::SGX_ERROR_UNEXPECTED), + }) + } + + fn get_qve_report_on_quote( + &self, + quote: Vec, + current_time: i64, + quote_collateral: &sgx_ql_qve_collateral_t, + qve_report_info: sgx_ql_qe_report_info_t, + supplemental_data_size: u32, + ) -> OCallBridgeResult { + debug!("RemoteAttestationBridge: get qve report on quote, length: {}", quote.len()); + + self.enclave_api + .get_qve_report_on_quote( + quote, + current_time, + quote_collateral, + qve_report_info, + supplemental_data_size, + ) + .map_err(|e| match e { + itp_enclave_api::error::Error::Sgx(s) => OCallBridgeError::GetQuote(s), + _ => OCallBridgeError::GetQuote(sgx_status_t::SGX_ERROR_UNEXPECTED), + }) + } + + fn get_update_info( + &self, + platform_blob: sgx_platform_info_t, + enclave_trusted: i32, + ) -> OCallBridgeResult { + debug!("RemoteAttestationBridge: get update into"); + + self.enclave_api + .get_update_info(platform_blob, enclave_trusted) + .map_err(|e| match e { + itp_enclave_api::error::Error::Sgx(s) => OCallBridgeError::GetUpdateInfo(s), + _ => OCallBridgeError::GetUpdateInfo(sgx_status_t::SGX_ERROR_UNEXPECTED), + }) + } +} + +fn lookup_ipv4(host: &str, port: u16) -> Result { + use std::net::ToSocketAddrs; + + let addrs = (host, port).to_socket_addrs().map_err(|e| format!("{:?}", e))?; + for addr in addrs { + if let SocketAddr::V4(_) = addr { + return Ok(addr) + } + } + + Err("Cannot lookup address".to_string()) +} diff --git a/bitacross-worker/service/src/ocall_bridge/sidechain_ocall.rs b/bitacross-worker/service/src/ocall_bridge/sidechain_ocall.rs new file mode 100644 index 0000000000..667901cced --- /dev/null +++ b/bitacross-worker/service/src/ocall_bridge/sidechain_ocall.rs @@ -0,0 +1,282 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{ + globals::tokio_handle::GetTokioHandle, + ocall_bridge::bridge_api::{OCallBridgeError, OCallBridgeResult, SidechainBridge}, + sync_block_broadcaster::BroadcastBlocks, + worker_peers_registry::PeersRegistry, +}; +use codec::{Decode, Encode}; +use itp_types::{BlockHash, ShardIdentifier}; +use its_peer_fetch::FetchBlocksFromPeer; +use its_primitives::{traits::Block, types::SignedBlock as SignedSidechainBlock}; +use its_storage::BlockStorage; +use log::*; +use std::sync::Arc; + +pub struct SidechainOCall< + BlockBroadcaster, + Storage, + WorkerPeerRegistry, + PeerBlockFetcher, + TokioHandle, +> { + block_broadcaster: Arc, + block_storage: Arc, + peer_registry: Arc, + peer_block_fetcher: Arc, + tokio_handle: Arc, +} + +impl + SidechainOCall +{ + pub fn new( + block_broadcaster: Arc, + block_storage: Arc, + peer_registry: Arc, + peer_block_fetcher: Arc, + tokio_handle: Arc, + ) -> Self { + SidechainOCall { + block_broadcaster, + block_storage, + peer_registry, + peer_block_fetcher, + tokio_handle, + } + } +} + +impl SidechainBridge + for SidechainOCall +where + BlockBroadcaster: BroadcastBlocks, + Storage: BlockStorage, + WorkerPeerRegistry: PeersRegistry, + PeerBlockFetcher: FetchBlocksFromPeer, + TokioHandle: GetTokioHandle, +{ + fn propose_sidechain_blocks(&self, signed_blocks_encoded: Vec) -> OCallBridgeResult<()> { + // TODO: improve error handling, using a mut status is not good design? + let mut status: OCallBridgeResult<()> = Ok(()); + + // handle blocks + let signed_blocks: Vec = + match Decode::decode(&mut signed_blocks_encoded.as_slice()) { + Ok(blocks) => blocks, + Err(_) => { + status = Err(OCallBridgeError::ProposeSidechainBlock( + "Could not decode signed blocks".to_string(), + )); + vec![] + }, + }; + + if !signed_blocks.is_empty() { + info!( + "Enclave produced sidechain blocks: {:?}", + signed_blocks + .iter() + .map(|b| b.block.header().block_number) + .collect::>() + ); + } else { + debug!("Enclave did not produce sidechain blocks"); + } + + // FIXME: When & where should peers be updated? + debug!("Updating peers.."); + if let Err(e) = self.peer_registry.update_peers() { + error!("Error updating peers: {:?}", e); + // Fixme: returning an error here results in a `HeaderAncestryMismatch` error. + // status = sgx_status_t::SGX_ERROR_UNEXPECTED; + } else { + info!("Successfully updated peers"); + } + + debug!("Broadcasting sidechain blocks ..."); + if let Err(e) = self.block_broadcaster.broadcast_blocks(signed_blocks) { + error!("Error broadcasting blocks: {:?}", e); + // Fixme: returning an error here results in a `HeaderAncestryMismatch` error. + // status = sgx_status_t::SGX_ERROR_UNEXPECTED; + } else { + info!("Successfully broadcast blocks"); + } + + status + } + + fn store_sidechain_blocks(&self, signed_blocks_encoded: Vec) -> OCallBridgeResult<()> { + // TODO: improve error handling, using a mut status is not good design? + let mut status: OCallBridgeResult<()> = Ok(()); + + let signed_blocks: Vec = + match Decode::decode(&mut signed_blocks_encoded.as_slice()) { + Ok(blocks) => blocks, + Err(_) => { + status = Err(OCallBridgeError::ProposeSidechainBlock( + "Could not decode signed blocks".to_string(), + )); + vec![] + }, + }; + + if let Err(e) = self.block_storage.store_blocks(signed_blocks) { + error!("Error storing blocks: {:?}", e); + } + + status + } + + fn fetch_sidechain_blocks_from_peer( + &self, + last_imported_block_hash_encoded: Vec, + maybe_until_block_hash_encoded: Vec, + shard_identifier_encoded: Vec, + ) -> OCallBridgeResult> { + let last_imported_block_hash: BlockHash = + Decode::decode(&mut last_imported_block_hash_encoded.as_slice()).map_err(|_| { + OCallBridgeError::FetchSidechainBlocksFromPeer( + "Failed to decode last imported block hash".to_string(), + ) + })?; + + let maybe_until_block_hash: Option = + Decode::decode(&mut maybe_until_block_hash_encoded.as_slice()).map_err(|_| { + OCallBridgeError::FetchSidechainBlocksFromPeer( + "Failed to decode optional until block hash".to_string(), + ) + })?; + + let shard_identifier: ShardIdentifier = + Decode::decode(&mut shard_identifier_encoded.as_slice()).map_err(|_| { + OCallBridgeError::FetchSidechainBlocksFromPeer( + "Failed to decode shard identifier".to_string(), + ) + })?; + + info!("[O-call] fetching blocks from peer.."); + + let tokio_handle = self.tokio_handle.get_handle(); + + let signed_sidechain_blocks = tokio_handle + .block_on(self.peer_block_fetcher.fetch_blocks_from_peer( + last_imported_block_hash, + maybe_until_block_hash, + shard_identifier, + )) + .map_err(|e| { + OCallBridgeError::FetchSidechainBlocksFromPeer(format!( + "Failed to execute block fetching from peer: {:?}", + e + )) + })?; + + info!("[O-call] successfully fetched {} blocks from peer", signed_sidechain_blocks.len()); + + Ok(signed_sidechain_blocks.encode()) + } + + fn get_trusted_peers_urls(&self) -> OCallBridgeResult> { + let peers = self.peer_registry.read_trusted_peers().unwrap(); + Ok(peers.encode()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::{ + globals::tokio_handle::ScopedTokioHandle, + tests::mocks::{ + broadcast_blocks_mock::BroadcastBlocksMock, + update_worker_peers_mock::WorkerPeersRegistryMock, + }, + }; + use codec::Decode; + use its_peer_fetch::mocks::fetch_blocks_from_peer_mock::FetchBlocksFromPeerMock; + use its_primitives::types::block::SignedBlock as SignedSidechainBlock; + use its_storage::{interface::BlockStorage, Result as StorageResult}; + use its_test::sidechain_block_builder::{SidechainBlockBuilder, SidechainBlockBuilderTrait}; + use primitive_types::H256; + use std::{collections::HashMap, vec::Vec}; + + struct BlockStorageMock; + impl BlockStorage for BlockStorageMock { + fn store_blocks(&self, _blocks: Vec) -> StorageResult<()> { + Ok(()) + } + } + + type TestSidechainOCall = SidechainOCall< + BroadcastBlocksMock, + BlockStorageMock, + WorkerPeersRegistryMock, + FetchBlocksFromPeerMock, + ScopedTokioHandle, + >; + + #[test] + fn fetch_sidechain_blocks_from_peer_works() { + let last_imported_block_hash = H256::random(); + let until_block_hash: Option = None; + let shard_identifier = H256::random(); + let blocks = vec![ + SidechainBlockBuilder::random().build_signed(), + SidechainBlockBuilder::random().build_signed(), + ]; + let peer_blocks_map = HashMap::from([(shard_identifier, blocks.clone())]); + let sidechain_ocall = setup_sidechain_ocall_with_peer_blocks(peer_blocks_map); + + let fetched_blocks_encoded = sidechain_ocall + .fetch_sidechain_blocks_from_peer( + last_imported_block_hash.encode(), + until_block_hash.encode(), + shard_identifier.encode(), + ) + .unwrap(); + + let fetched_blocks_decoded: Vec = + Decode::decode(&mut fetched_blocks_encoded.as_slice()).unwrap(); + + assert_eq!(blocks, fetched_blocks_decoded); + } + + fn setup_sidechain_ocall_with_peer_blocks( + peer_blocks_map: HashMap>, + ) -> TestSidechainOCall { + let block_broadcaster_mock = Arc::new(BroadcastBlocksMock {}); + let block_storage_mock = Arc::new(BlockStorageMock {}); + let worker_peers_registry_mock = Arc::new(WorkerPeersRegistryMock {}); + let peer_block_fetcher_mock = Arc::new( + FetchBlocksFromPeerMock::::default() + .with_signed_blocks(peer_blocks_map), + ); + let scoped_tokio_handle = Arc::new(ScopedTokioHandle::default()); + + SidechainOCall::new( + block_broadcaster_mock, + block_storage_mock, + worker_peers_registry_mock, + peer_block_fetcher_mock, + scoped_tokio_handle, + ) + } +} diff --git a/bitacross-worker/service/src/ocall_bridge/test/mocks/mod.rs b/bitacross-worker/service/src/ocall_bridge/test/mocks/mod.rs new file mode 100644 index 0000000000..298b05435a --- /dev/null +++ b/bitacross-worker/service/src/ocall_bridge/test/mocks/mod.rs @@ -0,0 +1,19 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 sidechain_bridge_mock; diff --git a/bitacross-worker/service/src/ocall_bridge/test/mocks/sidechain_bridge_mock.rs b/bitacross-worker/service/src/ocall_bridge/test/mocks/sidechain_bridge_mock.rs new file mode 100644 index 0000000000..dc1ba7d8da --- /dev/null +++ b/bitacross-worker/service/src/ocall_bridge/test/mocks/sidechain_bridge_mock.rs @@ -0,0 +1,54 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::ocall_bridge::bridge_api::{OCallBridgeResult, SidechainBridge}; + +#[derive(Default)] +pub struct SidechainBridgeMock { + peer_blocks_encoded: Vec, +} + +impl SidechainBridgeMock { + pub fn with_peer_blocks(mut self, blocks_encoded: Vec) -> Self { + self.peer_blocks_encoded = blocks_encoded; + self + } +} + +impl SidechainBridge for SidechainBridgeMock { + fn propose_sidechain_blocks(&self, _signed_blocks_encoded: Vec) -> OCallBridgeResult<()> { + Ok(()) + } + + fn store_sidechain_blocks(&self, _signed_blocks_encoded: Vec) -> OCallBridgeResult<()> { + Ok(()) + } + + fn fetch_sidechain_blocks_from_peer( + &self, + _last_imported_block_hash_encoded: Vec, + _maybe_until_block_hash_encoded: Vec, + _shard_identifier_encoded: Vec, + ) -> OCallBridgeResult> { + Ok(self.peer_blocks_encoded.clone()) + } + + fn get_trusted_peers_urls(&self) -> OCallBridgeResult> { + Ok(vec![]) + } +} diff --git a/bitacross-worker/service/src/ocall_bridge/test/mod.rs b/bitacross-worker/service/src/ocall_bridge/test/mod.rs new file mode 100644 index 0000000000..0c205a3799 --- /dev/null +++ b/bitacross-worker/service/src/ocall_bridge/test/mod.rs @@ -0,0 +1,19 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 mocks; diff --git a/bitacross-worker/service/src/ocall_bridge/worker_on_chain_ocall.rs b/bitacross-worker/service/src/ocall_bridge/worker_on_chain_ocall.rs new file mode 100644 index 0000000000..9218186ae8 --- /dev/null +++ b/bitacross-worker/service/src/ocall_bridge/worker_on_chain_ocall.rs @@ -0,0 +1,257 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::ocall_bridge::bridge_api::{OCallBridgeError, OCallBridgeResult, WorkerOnChainBridge}; +use codec::{Decode, Encode}; +use itp_api_client_types::ParentchainApi; +use itp_enclave_api::enclave_base::EnclaveBase; +use itp_node_api::{api_client::AccountApi, node_api_factory::CreateNodeApi}; +use itp_types::{parentchain::ParentchainId, WorkerRequest, WorkerResponse}; +use log::*; +use sp_runtime::OpaqueExtrinsic; +use std::{sync::Arc, thread, vec::Vec}; +use substrate_api_client::{ + ac_primitives::serde_impls::StorageKey, GetStorage, SubmitAndWatch, SubmitExtrinsic, XtStatus, +}; + +#[cfg(feature = "link-binary")] +use crate::main_impl::enclave_account; + +pub struct WorkerOnChainOCall { + enclave_api: Arc, + integritee_api_factory: Arc, + target_a_parentchain_api_factory: Option>, + target_b_parentchain_api_factory: Option>, +} + +impl WorkerOnChainOCall { + pub fn new( + enclave_api: Arc, + integritee_api_factory: Arc, + target_a_parentchain_api_factory: Option>, + target_b_parentchain_api_factory: Option>, + ) -> Self { + WorkerOnChainOCall { + enclave_api, + integritee_api_factory, + target_a_parentchain_api_factory, + target_b_parentchain_api_factory, + } + } +} + +impl WorkerOnChainOCall { + pub fn create_api(&self, parentchain_id: ParentchainId) -> OCallBridgeResult { + Ok(match parentchain_id { + ParentchainId::Litentry => self.integritee_api_factory.create_api()?, + ParentchainId::TargetA => self + .target_a_parentchain_api_factory + .as_ref() + .ok_or(OCallBridgeError::TargetAParentchainNotInitialized) + .and_then(|f| f.create_api().map_err(Into::into))?, + ParentchainId::TargetB => self + .target_b_parentchain_api_factory + .as_ref() + .ok_or(OCallBridgeError::TargetBParentchainNotInitialized) + .and_then(|f| f.create_api().map_err(Into::into))?, + }) + } +} + +impl WorkerOnChainBridge for WorkerOnChainOCall +where + E: EnclaveBase, + F: CreateNodeApi, +{ + fn worker_request( + &self, + request: Vec, + parentchain_id: Vec, + ) -> OCallBridgeResult> { + debug!(" Entering ocall_worker_request"); + + let requests: Vec = Decode::decode(&mut request.as_slice())?; + if requests.is_empty() { + debug!("requests is empty, returning empty vector"); + return Ok(Vec::::new().encode()) + } + + let parentchain_id = ParentchainId::decode(&mut parentchain_id.as_slice())?; + + let api = self.create_api(parentchain_id)?; + + let resp: Vec>> = requests + .into_iter() + .map(|req| match req { + WorkerRequest::ChainStorage(key, hash) => WorkerResponse::ChainStorage( + key.clone(), + api.get_opaque_storage_by_key(StorageKey(key.clone()), hash).unwrap(), + api.get_storage_proof_by_keys(vec![StorageKey(key)], hash).unwrap().map( + |read_proof| read_proof.proof.into_iter().map(|bytes| bytes.0).collect(), + ), + ), + WorkerRequest::ChainStorageKeys(key, hash) => { + let keys: Vec> = match api.get_keys(StorageKey(key), hash) { + Ok(Some(keys)) => keys.iter().map(String::encode).collect(), + _ => Default::default(), + }; + WorkerResponse::ChainStorageKeys(keys) + }, + }) + .collect(); + + let encoded_response: Vec = resp.encode(); + + Ok(encoded_response) + } + + fn send_to_parentchain( + &self, + extrinsics_encoded: Vec, + parentchain_id: Vec, + await_each_inlcusion: bool, + ) -> OCallBridgeResult<()> { + // TODO: improve error handling, using a mut status is not good design? + let mut status: OCallBridgeResult<()> = Ok(()); + + let extrinsics: Vec = + match Decode::decode(&mut extrinsics_encoded.as_slice()) { + Ok(calls) => calls, + Err(_) => { + status = Err(OCallBridgeError::SendExtrinsicsToParentchain( + "Could not decode extrinsics".to_string(), + )); + Default::default() + }, + }; + + if !extrinsics.is_empty() { + let parentchain_id = ParentchainId::decode(&mut parentchain_id.as_slice())?; + debug!( + "Enclave wants to send {} extrinsics to parentchain: {:?}. await each inclusion: {:?}", + extrinsics.len(), + parentchain_id, await_each_inlcusion + ); + let api = self.create_api(parentchain_id)?; + let mut send_extrinsic_failed = false; + for call in extrinsics.into_iter() { + if await_each_inlcusion { + if let Err(e) = api.submit_and_watch_opaque_extrinsic_until( + &call.encode().into(), + XtStatus::InBlock, + ) { + error!( + "Could not send extrinsic to node: {:?}, error: {:?}", + serde_json::to_string(&call), + e + ); + } + } else if let Err(e) = api.submit_opaque_extrinsic(&call.encode().into()) { + error!( + "Could not send extrinsic to node: {:?}, error: {:?}", + serde_json::to_string(&call), + e + ); + send_extrinsic_failed = true; + } + } + + // Try to reset nonce, see + // - https://github.com/litentry/litentry-parachain/issues/1036 + // - https://github.com/integritee-network/worker/issues/970 + // It has to be done in a separate thread as nested ECALL/OCALL is disallowed + // + // This workaround is likely to cause duplicate nonce or "transaction outdated" error in the parentchain + // tx pool, because the retrieved on-chain nonce doesn't count the pending tx, meanwhile the extrinsic factory + // keeps composing new extrinsics. So the nonce used for composing the new extrinsics can collide with the nonce + // in the already submitted tx. As a result, a few txs could be dropped during the parentchain tx pool processing. + // Not to mention the thread dispatch delay and network delay (query on-chain nonce). + // + // However, we still consider it better than the current situation, where the nonce never gets rectified and + // all following extrinsics will be blocked. Moreover, the txs sent to the parentchain are mostly + // "notification extrinsics" and don't cause chain state change, therefore we deem it less harmful to drop them. + // The worst case is some action is wrongly intepreted as "failed" (because F/E doesn't get the event in time) + // while it actually succeeds. In that case, the user needs to re-do the extrinsic, which is suboptimal, + // but still better than the chain stalling. + // + // To have a better synchronisation handling we probably need a sending queue in extrinsic factory that + // can be paused on demand (or wait for the nonce synchronisation). + // + // Another small thing that can be improved is to use rpc.system.accountNextIndex instead of system.account.nonce + // see https://polkadot.js.org/docs/api/cookbook/tx/#how-do-i-take-the-pending-tx-pool-into-account-in-my-nonce + #[cfg(feature = "link-binary")] + if send_extrinsic_failed { + // drop &self lifetime + let node_api_factory_cloned = self.integritee_api_factory.clone(); + let enclave_cloned = self.enclave_api.clone(); + thread::spawn(move || { + let api = node_api_factory_cloned.create_api().unwrap(); + let enclave_account = enclave_account(enclave_cloned.as_ref()); + warn!("send_extrinsic failed, try to reset nonce ..."); + match api.get_account_next_index(&enclave_account) { + Ok(nonce) => { + warn!("query on-chain nonce OK, reset nonce to: {}", nonce); + if let Err(e) = enclave_cloned.set_nonce(nonce, ParentchainId::Litentry) + { + warn!("failed to reset nonce due to: {:?}", e); + } + }, + Err(e) => warn!("query on-chain nonce failed: {:?}", e), + } + }); + } + } + status + } +} + +#[cfg(test)] +mod tests { + + use super::*; + use crate::tests::mocks::enclave_api_mock::EnclaveMock; + use itp_node_api::{ + api_client::ParentchainApi, + node_api_factory::{CreateNodeApi, Result as NodeApiResult}, + }; + use mockall::mock; + + #[test] + fn given_empty_worker_request_when_submitting_then_return_empty_response() { + mock! { + NodeApiFactory {} + impl CreateNodeApi for NodeApiFactory { + fn create_api(&self) -> NodeApiResult; + } + } + + let mock_enclave = Arc::new(EnclaveMock {}); + let mock_node_api_factory = Arc::new(MockNodeApiFactory::new()); + + let on_chain_ocall = + WorkerOnChainOCall::new(mock_enclave, mock_node_api_factory, None, None); + + let response = on_chain_ocall + .worker_request(Vec::::new().encode(), ParentchainId::Litentry.encode()) + .unwrap(); + + assert!(!response.is_empty()); // the encoded empty vector is not empty + let decoded_response: Vec = Decode::decode(&mut response.as_slice()).unwrap(); + assert!(decoded_response.is_empty()); // decode the response, and we get an empty vector again + } +} diff --git a/bitacross-worker/service/src/parentchain_handler.rs b/bitacross-worker/service/src/parentchain_handler.rs new file mode 100644 index 0000000000..8a58f10876 --- /dev/null +++ b/bitacross-worker/service/src/parentchain_handler.rs @@ -0,0 +1,260 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::error::{Error, ServiceResult}; +use codec::{Decode, Encode}; +use itc_parentchain::{ + light_client::light_client_init_params::{GrandpaParams, SimpleParams}, + primitives::{ParentchainId, ParentchainInitParams}, +}; +use itp_api_client_types::ParentchainApi; +use itp_enclave_api::{enclave_base::EnclaveBase, sidechain::Sidechain}; +use itp_node_api::api_client::ChainApi; +use itp_storage::StorageProof; +use litentry_primitives::ParentchainHeader as Header; +use log::*; +use sp_consensus_grandpa::VersionedAuthorityList; +use sp_runtime::traits::Header as HeaderTrait; +use std::{cmp::min, sync::Arc}; +use substrate_api_client::ac_primitives::{Block, Header as HeaderT}; + +const BLOCK_SYNC_BATCH_SIZE: u32 = 1000; + +pub trait HandleParentchain { + /// Initializes all parentchain specific components on the enclave side. + /// Returns the latest synced block header. + fn init_parentchain_components(&self) -> ServiceResult
; + + /// Fetches the parentchain blocks to sync from the parentchain and feeds them to the enclave. + /// Returns the latest synced block header. + /// + /// Litentry: `overriden_start_block` to forcibly start from the given parentchain block number + fn sync_parentchain( + &self, + last_synced_header: Header, + overriden_start_block: u32, + is_syncing: bool, + ) -> ServiceResult
; + + /// Syncs and directly imports parentchain blocks from the latest synced header + /// until the specified until_header. + /// + /// Litentry: `overriden_start_block` to forcibly start from the given parentchain block number + fn sync_and_import_parentchain_until( + &self, + last_synced_header: &Header, + until_header: &Header, + overriden_start_block: u32, + ) -> ServiceResult
; +} + +/// Handles the interaction between parentchain and enclave. +pub(crate) struct ParentchainHandler { + parentchain_api: ParentchainApi, + enclave_api: Arc, + parentchain_init_params: ParentchainInitParams, +} + +// #TODO: #1451: Reintroduce `ParentchainApi: ChainApi` once there is no trait bound conflict +// any more with the api-clients own trait definitions. +impl ParentchainHandler +where + EnclaveApi: EnclaveBase, +{ + pub fn new( + parentchain_api: ParentchainApi, + enclave_api: Arc, + parentchain_init_params: ParentchainInitParams, + ) -> Self { + Self { parentchain_api, enclave_api, parentchain_init_params } + } + + // FIXME: Necessary in the future? Fix with #1080 + pub fn new_with_automatic_light_client_allocation( + parentchain_api: ParentchainApi, + enclave_api: Arc, + id: ParentchainId, + ) -> ServiceResult { + let genesis_hash = parentchain_api.get_genesis_hash()?; + let genesis_header = + parentchain_api.header(Some(genesis_hash))?.ok_or(Error::MissingGenesisHeader)?; + + let parentchain_init_params: ParentchainInitParams = if parentchain_api + .is_grandpa_available()? + { + let grandpas = parentchain_api.grandpa_authorities(Some(genesis_hash))?; + let grandpa_proof = parentchain_api.grandpa_authorities_proof(Some(genesis_hash))?; + + debug!("[{:?}] Grandpa Authority List: \n {:?} \n ", id, grandpas); + + let authority_list = VersionedAuthorityList::from(grandpas); + + ( + id, + GrandpaParams::new( + // #TODO: #1451: clean up type hacks + Header::decode(&mut genesis_header.encode().as_slice())?, + authority_list.into(), + grandpa_proof, + ), + ) + .into() + } else { + ( + id, + SimpleParams::new( + // #TODO: #1451: clean up type hacks + Header::decode(&mut genesis_header.encode().as_slice())?, + ), + ) + .into() + }; + + Ok(Self::new(parentchain_api, enclave_api, parentchain_init_params)) + } + + pub fn parentchain_api(&self) -> &ParentchainApi { + &self.parentchain_api + } + + pub fn parentchain_id(&self) -> &ParentchainId { + self.parentchain_init_params.id() + } +} + +impl HandleParentchain for ParentchainHandler +where + EnclaveApi: Sidechain + EnclaveBase, +{ + fn init_parentchain_components(&self) -> ServiceResult
{ + Ok(self + .enclave_api + .init_parentchain_components(self.parentchain_init_params.clone())?) + } + + fn sync_parentchain( + &self, + last_synced_header: Header, + overriden_start_block: u32, + is_syncing: bool, + ) -> ServiceResult
{ + let id = self.parentchain_id(); + trace!("[{:?}] Getting current head", id); + let curr_block = self + .parentchain_api + .last_finalized_block()? + .ok_or(Error::MissingLastFinalizedBlock)?; + let curr_block_number = curr_block.block.header().number(); + + info!( + "[{:?}] Syncing blocks from {} to {}", + id, last_synced_header.number, curr_block_number + ); + + let mut until_synced_header = last_synced_header; + let mut start_block = until_synced_header.number + 1; + if overriden_start_block > start_block { + start_block = overriden_start_block; + // ask the enclave to ignore the parentchain block import validation until `overriden_start_block` + // TODO: maybe ignoring the next block import is enough, since the given `overriden_start_block` + // should be the very first parentchain block to be imported + self.enclave_api + .ignore_parentchain_block_import_validation_until(overriden_start_block)?; + } + + loop { + let block_chunk_to_sync = self.parentchain_api.get_blocks( + start_block, + min(start_block + BLOCK_SYNC_BATCH_SIZE, curr_block_number), + )?; + info!("[{:?}] Found {} block(s) to sync", id, block_chunk_to_sync.len()); + if block_chunk_to_sync.is_empty() { + return Ok(until_synced_header) + } + + let events_chunk_to_sync: Vec> = block_chunk_to_sync + .iter() + .map(|block| { + self.parentchain_api.get_events_for_block(Some(block.block.header.hash())) + }) + .collect::, _>>()?; + + info!("[{:?}] Found {} event vector(s) to sync", id, events_chunk_to_sync.len()); + + let events_proofs_chunk_to_sync: Vec = block_chunk_to_sync + .iter() + .map(|block| { + self.parentchain_api.get_events_value_proof(Some(block.block.header.hash())) + }) + .collect::, _>>()?; + + self.enclave_api.sync_parentchain( + block_chunk_to_sync.as_slice(), + events_chunk_to_sync.as_slice(), + events_proofs_chunk_to_sync.as_slice(), + self.parentchain_id(), + is_syncing, + )?; + + let api_client_until_synced_header = block_chunk_to_sync + .last() + .map(|b| b.block.header.clone()) + .ok_or(Error::EmptyChunk)?; + info!( + "[{:?}] Synced {} out of {} finalized parentchain blocks", + id, until_synced_header.number, curr_block_number, + ); + + // #TODO: #1451: fix api/client types + until_synced_header = + Header::decode(&mut api_client_until_synced_header.encode().as_slice()) + .expect("Can decode previously encoded header; qed"); + + start_block = until_synced_header.number + 1; + println!( + "[{:?}] Synced {} out of {} finalized parentchain blocks", + id, until_synced_header.number, curr_block_number, + ); + } + } + + fn sync_and_import_parentchain_until( + &self, + last_synced_header: &Header, + until_header: &Header, + overriden_start_block: u32, + ) -> ServiceResult
{ + let id = self.parentchain_id(); + + trace!( + "[{:?}] last synced block number: {}. synching until {}", + id, + last_synced_header.number, + until_header.number + ); + let mut last_synced_header = last_synced_header.clone(); + + while last_synced_header.number() < until_header.number() { + last_synced_header = + self.sync_parentchain(last_synced_header, overriden_start_block, true)?; + println!("[{:?}] synced block number: #{}", id, last_synced_header.number); + std::thread::sleep(std::time::Duration::from_secs(1)); + } + Ok(last_synced_header) + } +} diff --git a/bitacross-worker/service/src/prometheus_metrics.rs b/bitacross-worker/service/src/prometheus_metrics.rs new file mode 100644 index 0000000000..64a3615135 --- /dev/null +++ b/bitacross-worker/service/src/prometheus_metrics.rs @@ -0,0 +1,300 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +//! Service for prometheus metrics, hosted on a http server. + +#[cfg(feature = "teeracle")] +use crate::teeracle::teeracle_metrics::update_teeracle_metrics; + +use crate::{ + account_funding::EnclaveAccountInfo, + error::{Error, ServiceResult}, +}; +use async_trait::async_trait; +use codec::{Decode, Encode}; +#[cfg(feature = "attesteer")] +use core::time::Duration; +use frame_support::scale_info::TypeInfo; +#[cfg(feature = "dcap")] +use itc_rest_client::{ + http_client::{DefaultSend, HttpClient}, + rest_client::{RestClient, Url as URL}, + RestGet, RestPath, +}; +use itp_enclave_metrics::EnclaveMetric; +use lazy_static::lazy_static; +use litentry_primitives::{Assertion, Identity}; +use log::*; +use prometheus::{ + proto::MetricFamily, register_counter_vec, register_histogram, register_histogram_vec, + register_int_gauge, register_int_gauge_vec, CounterVec, Histogram, HistogramVec, IntGauge, + IntGaugeVec, +}; +use serde::{Deserialize, Serialize}; +use std::{net::SocketAddr, sync::Arc}; +use warp::{Filter, Rejection, Reply}; + +lazy_static! { + /// Register all the prometheus metrics we want to monitor (aside from the default process ones). + + static ref ENCLAVE_ACCOUNT_FREE_BALANCE: IntGauge = + register_int_gauge!("litentry_worker_enclave_account_free_balance", "Free balance of the enclave account") + .unwrap(); + static ref ENCLAVE_SIDECHAIN_BLOCK_HEIGHT: IntGauge = + register_int_gauge!("litentry_worker_enclave_sidechain_block_height", "Enclave sidechain block height") + .unwrap(); + static ref ENCLAVE_SIDECHAIN_TOP_POOL_SIZE: IntGauge = + register_int_gauge!("litentry_worker_enclave_sidechain_top_pool_size", "Enclave sidechain top pool size") + .unwrap(); + static ref ENCLAVE_STF_TASKS: IntGaugeVec = + register_int_gauge_vec!("litentry_worker_enclave_stf_total_tasks", "Litentry Stf Tasks", &["request_type", "variant"]) + .unwrap(); + static ref ENCLAVE_STF_TASKS_EXECUTION: HistogramVec = + register_histogram_vec!("litentry_worker_enclave_stf_tasks_execution_times", "Litentry Stf Tasks Exeuction Time", &["request_type", "variant"]) + .unwrap(); + static ref ENCLAVE_SUCCESSFUL_TRUSTED_OPERATION: CounterVec = + register_counter_vec!("litentry_worker_enclave_successful_trusted_operation", "Litentry Successful Trusted Operation", &["call"]) + .unwrap(); + static ref ENCLAVE_FAILED_TRUSTED_OPERATION: CounterVec = + register_counter_vec!("litentry_worker_enclave_failed_trusted_operation", "Litentry Failed Trusted Operation", &["call"]) + .unwrap(); + static ref ENCLAVE_PARENTCHAIN_BLOCK_IMPORT_TIME: Histogram = + register_histogram!("litentry_worker_enclave_parentchain_block_import_time", "Time taken to import parentchain block") + .unwrap(); + static ref ENCLAVE_SIDECHAIN_BLOCK_IMPORT_TIME: Histogram = + register_histogram!("litentry_worker_enclave_sidechain_block_import_time", "Time taken to import sidechain block") + .unwrap(); + static ref ENCLAVE_SIDECHAIN_SLOT_PREPARE_TIME: Histogram = + register_histogram!("litentry_worker_enclave_sidechain_slot_prepare_time", "Time taken to prepare sidechain extrinsics for execution") + .unwrap(); + static ref ENCLAVE_SIDECHAIN_SLOT_STF_EXECUTION_TIME: Histogram = + register_histogram!("litentry_worker_enclave_sidechain_slot_stf_execution_time", "Time taken to execute sidechain extrinsics") + .unwrap(); + static ref ENCLAVE_SIDECHAIN_SLOT_BLOCK_COMPOSITION_TIME: Histogram = + register_histogram!("litentry_worker_enclave_sidechain_slot_block_composition_time", "Time taken to compose sidechain block") + .unwrap(); + static ref ENCLAVE_SIDECHAIN_BLOCK_BROADCASTING_TIME: Histogram = + register_histogram!("litentry_worker_enclave_sidechain_block_broadcasting_time", "Time taken to broadcast sidechain block") + .unwrap(); + +} + +pub async fn start_metrics_server( + metrics_handler: Arc, + port: u16, +) -> ServiceResult<()> +where + MetricsHandler: HandleMetrics + Send + Sync + 'static, +{ + let metrics_route = warp::path!("metrics").and_then(move || { + let handler_clone = metrics_handler.clone(); + async move { handler_clone.handle_metrics().await } + }); + let socket_addr: SocketAddr = ([0, 0, 0, 0], port).into(); + + info!("Running prometheus metrics server on: {:?}", socket_addr); + warp::serve(metrics_route).run(socket_addr).await; + + info!("Prometheus metrics server shut down"); + Ok(()) +} + +#[async_trait] +pub trait HandleMetrics { + type ReplyType: Reply; + + async fn handle_metrics(&self) -> Result; +} + +/// Metrics handler implementation. +pub struct MetricsHandler { + enclave_wallet: Arc, +} + +#[async_trait] +impl HandleMetrics for MetricsHandler +where + Wallet: EnclaveAccountInfo + Send + Sync, +{ + type ReplyType = String; + + async fn handle_metrics(&self) -> Result { + self.update_metrics().await; + + let default_metrics = match gather_metrics_into_reply(&prometheus::gather()) { + Ok(r) => r, + Err(e) => { + error!("Failed to gather prometheus metrics: {:?}", e); + String::default() + }, + }; + + Ok(default_metrics) + } +} + +impl MetricsHandler +where + Wallet: EnclaveAccountInfo + Send + Sync, +{ + pub fn new(enclave_wallet: Arc) -> Self { + MetricsHandler { enclave_wallet } + } + + async fn update_metrics(&self) { + match self.enclave_wallet.free_balance() { + Ok(b) => { + ENCLAVE_ACCOUNT_FREE_BALANCE.set(b as i64); + }, + Err(e) => { + error!("Failed to fetch free balance metric, value will not be updated: {:?}", e); + }, + } + } +} + +fn gather_metrics_into_reply(metrics: &[MetricFamily]) -> ServiceResult { + use prometheus::Encoder; + let encoder = prometheus::TextEncoder::new(); + + let mut buffer = Vec::new(); + encoder.encode(metrics, &mut buffer).map_err(|e| { + Error::Custom(format!("Failed to encode prometheus metrics: {:?}", e).into()) + })?; + + let result_string = String::from_utf8(buffer).map_err(|e| { + Error::Custom( + format!("Failed to convert Prometheus encoded metrics to UTF8: {:?}", e).into(), + ) + })?; + + Ok(result_string) +} + +/// Trait to receive metric updates from inside the enclave. +pub trait ReceiveEnclaveMetrics { + fn receive_enclave_metric(&self, metric: EnclaveMetric) -> ServiceResult<()>; +} + +pub struct EnclaveMetricsReceiver; + +impl ReceiveEnclaveMetrics for EnclaveMetricsReceiver { + fn receive_enclave_metric(&self, metric: EnclaveMetric) -> ServiceResult<()> { + match metric { + EnclaveMetric::SetSidechainBlockHeight(h) => { + ENCLAVE_SIDECHAIN_BLOCK_HEIGHT.set(h as i64); + }, + EnclaveMetric::TopPoolSizeSet(pool_size) => { + ENCLAVE_SIDECHAIN_TOP_POOL_SIZE.set(pool_size as i64); + }, + EnclaveMetric::TopPoolSizeIncrement => { + ENCLAVE_SIDECHAIN_TOP_POOL_SIZE.inc(); + }, + EnclaveMetric::TopPoolSizeDecrement => { + ENCLAVE_SIDECHAIN_TOP_POOL_SIZE.dec(); + }, + EnclaveMetric::SuccessfulTrustedOperationIncrement(metric_name) => { + ENCLAVE_SUCCESSFUL_TRUSTED_OPERATION.with_label_values(&[&metric_name]).inc(); + }, + EnclaveMetric::FailedTrustedOperationIncrement(metric_name) => { + ENCLAVE_FAILED_TRUSTED_OPERATION.with_label_values(&[&metric_name]).inc(); + }, + EnclaveMetric::ParentchainBlockImportTime(time) => + ENCLAVE_PARENTCHAIN_BLOCK_IMPORT_TIME.observe(time.as_secs_f64()), + EnclaveMetric::SidechainBlockImportTime(time) => + ENCLAVE_SIDECHAIN_BLOCK_IMPORT_TIME.observe(time.as_secs_f64()), + EnclaveMetric::SidechainSlotPrepareTime(time) => + ENCLAVE_SIDECHAIN_SLOT_PREPARE_TIME.observe(time.as_secs_f64()), + EnclaveMetric::SidechainSlotStfExecutionTime(time) => + ENCLAVE_SIDECHAIN_SLOT_STF_EXECUTION_TIME.observe(time.as_secs_f64()), + EnclaveMetric::SidechainSlotBlockCompositionTime(time) => + ENCLAVE_SIDECHAIN_SLOT_BLOCK_COMPOSITION_TIME.observe(time.as_secs_f64()), + EnclaveMetric::SidechainBlockBroadcastingTime(time) => + ENCLAVE_SIDECHAIN_BLOCK_BROADCASTING_TIME.observe(time.as_secs_f64()), + #[cfg(feature = "teeracle")] + EnclaveMetric::ExchangeRateOracle(m) => update_teeracle_metrics(m)?, + #[cfg(not(feature = "teeracle"))] + EnclaveMetric::ExchangeRateOracle(_) => { + error!("Received Teeracle metric, but Teeracle feature is not enabled, ignoring metric item.") + }, + } + Ok(()) + } +} + +// Function to increment STF calls with labels +fn inc_stf_calls(category: &str, label: &str) { + ENCLAVE_STF_TASKS.with_label_values(&[category, label]).inc(); +} + +// Function to observe STF call execution time with labels +fn observe_execution_time(category: &str, label: &str, time: f64) { + ENCLAVE_STF_TASKS_EXECUTION.with_label_values(&[category, label]).observe(time); +} + +#[derive(Serialize, Deserialize, Debug)] +struct PrometheusMarblerunEvents(pub Vec); + +#[cfg(feature = "attesteer")] +impl RestPath<&str> for PrometheusMarblerunEvents { + fn get_path(path: &str) -> Result { + Ok(format!("{}", path)) + } +} + +#[cfg(feature = "attesteer")] +pub fn fetch_marblerun_events(base_url: &str) -> Result, Error> { + let base_url = URL::parse(&base_url).map_err(|e| { + Error::Custom( + format!("Failed to parse marblerun prometheus endpoint base URL: {:?}", e).into(), + ) + })?; + let timeout = 3u64; + let http_client = + HttpClient::new(DefaultSend {}, true, Some(Duration::from_secs(timeout)), None, None); + + let mut rest_client = RestClient::new(http_client, base_url.clone()); + let events: PrometheusMarblerunEvents = rest_client.get("events").map_err(|e| { + Error::Custom( + format!("Failed to fetch marblerun prometheus events from: {}, error: {}", base_url, e) + .into(), + ) + })?; + + Ok(events.0) +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Encode, Decode, TypeInfo)] +pub struct PrometheusMarblerunEvent { + pub time: String, + pub activation: PrometheusMarblerunEventActivation, +} + +#[cfg(feature = "attesteer")] +impl PrometheusMarblerunEvent { + pub fn get_quote_without_prepended_bytes(&self) -> &[u8] { + let marblerun_magic_prepended_header_size = 16usize; + &self.activation.quote.as_bytes()[marblerun_magic_prepended_header_size..] + } +} +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Encode, Decode, TypeInfo)] +#[serde(rename_all = "camelCase")] +pub struct PrometheusMarblerunEventActivation { + pub marble_type: String, + pub uuid: String, + pub quote: String, +} diff --git a/bitacross-worker/service/src/setup.rs b/bitacross-worker/service/src/setup.rs new file mode 100644 index 0000000000..4bd056edd8 --- /dev/null +++ b/bitacross-worker/service/src/setup.rs @@ -0,0 +1,242 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::error::{Error, ServiceResult}; +use itp_settings::files::{ + LITENTRY_PARENTCHAIN_LIGHT_CLIENT_DB_PATH, SCHEDULED_ENCLAVE_FILE, SHARDS_PATH, + SIDECHAIN_STORAGE_PATH, TARGET_A_PARENTCHAIN_LIGHT_CLIENT_DB_PATH, + TARGET_B_PARENTCHAIN_LIGHT_CLIENT_DB_PATH, +}; +use std::{fs, path::Path}; + +#[cfg(feature = "link-binary")] +pub(crate) use needs_enclave::{ + generate_shielding_key_file, generate_signing_key_file, init_shard, initialize_shard_and_keys, + migrate_shard, +}; + +#[cfg(feature = "link-binary")] +mod needs_enclave { + use crate::error::{Error, ServiceResult}; + use codec::Encode; + use itp_enclave_api::{enclave_base::EnclaveBase, Enclave}; + use itp_settings::files::{ + LITENTRY_PARENTCHAIN_LIGHT_CLIENT_DB_PATH, SHARDS_PATH, SHIELDING_KEY_FILE, + SIDECHAIN_STORAGE_PATH, SIGNING_KEY_FILE, TARGET_A_PARENTCHAIN_LIGHT_CLIENT_DB_PATH, + TARGET_B_PARENTCHAIN_LIGHT_CLIENT_DB_PATH, + }; + use itp_types::ShardIdentifier; + use log::*; + use std::{fs, fs::File, path::Path}; + + /// Initializes the shard and generates the key files. + pub(crate) fn initialize_shard_and_keys( + enclave: &Enclave, + shard_identifier: &ShardIdentifier, + ) -> ServiceResult<()> { + println!("[+] Initialize the shard"); + init_shard(enclave, shard_identifier); + + println!("[+] Generate key files"); + generate_signing_key_file(enclave); + generate_shielding_key_file(enclave); + + Ok(()) + } + + pub(crate) fn init_shard(enclave: &Enclave, shard_identifier: &ShardIdentifier) { + use base58::ToBase58; + + match enclave.init_shard(shard_identifier.encode()) { + Err(e) => { + println!( + "Failed to initialize shard {:?}: {:?}", + shard_identifier.0.to_base58(), + e + ); + }, + Ok(_) => { + println!("Successfully initialized shard {:?}", shard_identifier.0.to_base58()); + }, + } + } + + pub(crate) fn migrate_shard( + enclave: &Enclave, + old_shard: &ShardIdentifier, + new_shard: &ShardIdentifier, + ) { + match enclave.migrate_shard(old_shard.encode(), new_shard.encode()) { + Err(e) => { + println!( + "Failed to migrate old shard {:?} to new shard{:?}. {:?}", + old_shard, new_shard, e + ); + }, + Ok(_) => { + println!( + "Successfully migrate old shard {:?} to new shard{:?}", + old_shard, new_shard + ); + }, + } + } + + pub(crate) fn generate_signing_key_file(enclave: &Enclave) { + info!("*** Get the signing key from the TEE\n"); + let pubkey = enclave.get_ecc_signing_pubkey().unwrap(); + debug!("[+] Signing key raw: {:?}", pubkey); + match fs::write(SIGNING_KEY_FILE, pubkey) { + Err(x) => { + error!("[-] Failed to write '{}'. {}", SIGNING_KEY_FILE, x); + }, + _ => { + println!("[+] File '{}' written successfully", SIGNING_KEY_FILE); + }, + } + } + + pub(crate) fn generate_shielding_key_file(enclave: &Enclave) { + info!("*** Get the public key from the TEE\n"); + let pubkey = enclave.get_rsa_shielding_pubkey().unwrap(); + let file = File::create(SHIELDING_KEY_FILE).unwrap(); + match serde_json::to_writer(file, &pubkey) { + Err(x) => { + error!("[-] Failed to write '{}'. {}", SHIELDING_KEY_FILE, x); + }, + _ => { + println!("[+] File '{}' written successfully", SHIELDING_KEY_FILE); + }, + } + } +} + +/// Purge all worker files from `dir`. +pub(crate) fn purge_files_from_dir(dir: &Path) -> ServiceResult<()> { + println!("[+] Performing a clean reset of the worker"); + + println!("[+] Purge all files from previous runs"); + purge_files(dir)?; + + Ok(()) +} + +/// Purge all worker files in a given path. +fn purge_files(root_directory: &Path) -> ServiceResult<()> { + remove_dir_if_it_exists(root_directory, SHARDS_PATH)?; + remove_dir_if_it_exists(root_directory, SIDECHAIN_STORAGE_PATH)?; + + remove_dir_if_it_exists(root_directory, LITENTRY_PARENTCHAIN_LIGHT_CLIENT_DB_PATH)?; + remove_dir_if_it_exists(root_directory, TARGET_A_PARENTCHAIN_LIGHT_CLIENT_DB_PATH)?; + remove_dir_if_it_exists(root_directory, TARGET_B_PARENTCHAIN_LIGHT_CLIENT_DB_PATH)?; + + remove_file_if_it_exists(root_directory, SCHEDULED_ENCLAVE_FILE)?; + Ok(()) +} + +fn remove_dir_if_it_exists(root_directory: &Path, dir_name: &str) -> ServiceResult<()> { + let directory_path = root_directory.join(dir_name); + if directory_path.exists() { + fs::remove_dir_all(directory_path).map_err(|e| Error::Custom(e.into()))?; + } + Ok(()) +} + +fn remove_file_if_it_exists(root_directory: &Path, file_name: &str) -> ServiceResult<()> { + let file = root_directory.join(file_name); + if file.exists() { + fs::remove_file(file).map_err(|e| Error::Custom(e.into()))?; + } + Ok(()) +} + +#[cfg(test)] +mod tests { + use super::*; + use itp_settings::files::{SHARDS_PATH, TARGET_A_PARENTCHAIN_LIGHT_CLIENT_DB_PATH}; + use std::{fs, path::PathBuf}; + + #[test] + fn purge_files_deletes_all_relevant_files() { + let test_directory_handle = + TestDirectoryHandle::new(PathBuf::from("test_purge_files_deletes_all_relevant_files")); + let root_directory = test_directory_handle.path(); + + let shards_path = root_directory.join(SHARDS_PATH); + fs::create_dir_all(&shards_path).unwrap(); + fs::File::create(&shards_path.join("state_1.bin")).unwrap(); + fs::File::create(&shards_path.join("state_2.bin")).unwrap(); + + let sidechain_db_path = root_directory.join(SIDECHAIN_STORAGE_PATH); + fs::create_dir_all(&sidechain_db_path).unwrap(); + fs::File::create(&sidechain_db_path.join("sidechain_db_1.bin")).unwrap(); + fs::File::create(&sidechain_db_path.join("sidechain_db_2.bin")).unwrap(); + fs::File::create(&sidechain_db_path.join("sidechain_db_3.bin")).unwrap(); + + fs::create_dir_all(&root_directory.join(LITENTRY_PARENTCHAIN_LIGHT_CLIENT_DB_PATH)) + .unwrap(); + fs::create_dir_all(&root_directory.join(TARGET_A_PARENTCHAIN_LIGHT_CLIENT_DB_PATH)) + .unwrap(); + fs::create_dir_all(&root_directory.join(TARGET_B_PARENTCHAIN_LIGHT_CLIENT_DB_PATH)) + .unwrap(); + + purge_files(&root_directory).unwrap(); + + assert!(!shards_path.exists()); + assert!(!sidechain_db_path.exists()); + assert!(!root_directory.join(LITENTRY_PARENTCHAIN_LIGHT_CLIENT_DB_PATH).exists()); + assert!(!root_directory.join(TARGET_A_PARENTCHAIN_LIGHT_CLIENT_DB_PATH).exists()); + assert!(!root_directory.join(TARGET_B_PARENTCHAIN_LIGHT_CLIENT_DB_PATH).exists()); + } + + #[test] + fn purge_files_succeeds_when_no_files_exist() { + let test_directory_handle = TestDirectoryHandle::new(PathBuf::from( + "test_purge_files_succeeds_when_no_files_exist", + )); + let root_directory = test_directory_handle.path(); + + assert!(purge_files(&root_directory).is_ok()); + } + + /// Directory handle to automatically initialize a directory + /// and upon dropping the reference, removing it again. + struct TestDirectoryHandle { + path: PathBuf, + } + + impl TestDirectoryHandle { + pub fn new(path: PathBuf) -> Self { + let test_path = std::env::current_dir().unwrap().join(&path); + fs::create_dir_all(&test_path).unwrap(); + TestDirectoryHandle { path: test_path } + } + + pub fn path(&self) -> &PathBuf { + &self.path + } + } + + impl Drop for TestDirectoryHandle { + fn drop(&mut self) { + if self.path.exists() { + fs::remove_dir_all(&self.path).unwrap(); + } + } + } +} diff --git a/bitacross-worker/service/src/sidechain_setup.rs b/bitacross-worker/service/src/sidechain_setup.rs new file mode 100644 index 0000000000..a499c85fed --- /dev/null +++ b/bitacross-worker/service/src/sidechain_setup.rs @@ -0,0 +1,129 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{ + config::Config, + error::{Error, ServiceResult}, + parentchain_handler::HandleParentchain, +}; +use futures::executor::block_on; +use itp_enclave_api::{ + direct_request::DirectRequest, enclave_base::EnclaveBase, sidechain::Sidechain, +}; +use itp_settings::{ + files::{SIDECHAIN_PURGE_INTERVAL, SIDECHAIN_PURGE_LIMIT}, + sidechain::SLOT_DURATION, +}; +use itp_types::Header; +use its_consensus_slots::start_slot_worker; +use its_primitives::types::block::SignedBlock as SignedSidechainBlock; +use its_storage::{interface::FetchBlocks, start_sidechain_pruning_loop, BlockPruner}; +use log::*; +use std::{sync::Arc, thread}; +use tokio::runtime::Handle; + +pub(crate) fn sidechain_start_untrusted_rpc_server( + config: &Config, + enclave: Arc, + sidechain_storage: Arc, + tokio_handle: &Handle, +) where + Enclave: DirectRequest + Clone, + SidechainStorage: BlockPruner + FetchBlocks + Sync + Send + 'static, +{ + let untrusted_url = config.untrusted_worker_url(); + println!("[+] Untrusted RPC server listening on {}", &untrusted_url); + let _untrusted_rpc_join_handle = tokio_handle.spawn(async move { + itc_rpc_server::run_server(&untrusted_url, enclave, sidechain_storage) + .await + .unwrap(); + }); +} + +#[allow(clippy::too_many_arguments)] +pub(crate) fn sidechain_init_block_production( + enclave: Arc, + register_enclave_xt_header: Option
, + we_are_primary_validateer: bool, + parentchain_handler: Arc, + sidechain_storage: Arc, + last_synced_header: &Header, + overriden_start_block: u32, + fail_mode: Option, + fail_at: u64, +) -> ServiceResult
+where + Enclave: EnclaveBase + Sidechain, + SidechainStorage: BlockPruner + FetchBlocks + Sync + Send + 'static, + ParentchainHandler: HandleParentchain, +{ + // If we're the first validateer to register, also trigger parentchain block import. + let mut updated_header: Option
= None; + + if we_are_primary_validateer { + info!( + "We're the first validateer to be registered, syncing parentchain blocks until the one we have registered ourselves on." + ); + updated_header = Some(parentchain_handler.sync_and_import_parentchain_until( + last_synced_header, + ®ister_enclave_xt_header.unwrap(), + overriden_start_block, + )?); + } + + // ------------------------------------------------------------------------ + // Initialize sidechain components (has to be AFTER init_parentchain_components() + enclave.init_enclave_sidechain_components(fail_mode, fail_at).unwrap(); + + // ------------------------------------------------------------------------ + // Start interval sidechain block production (execution of trusted calls, sidechain block production). + let sidechain_enclave_api = enclave; + println!("[+] Spawning thread for sidechain block production"); + thread::Builder::new() + .name("interval_block_production_timer".to_owned()) + .spawn(move || { + let future = start_slot_worker( + || execute_trusted_calls(sidechain_enclave_api.as_ref()), + SLOT_DURATION, + ); + block_on(future); + println!("[!] Sidechain block production loop has terminated"); + }) + .map_err(|e| Error::Custom(Box::new(e)))?; + + // ------------------------------------------------------------------------ + // start sidechain pruning loop + thread::Builder::new() + .name("sidechain_pruning_loop".to_owned()) + .spawn(move || { + start_sidechain_pruning_loop( + &sidechain_storage, + SIDECHAIN_PURGE_INTERVAL, + SIDECHAIN_PURGE_LIMIT, + ); + }) + .map_err(|e| Error::Custom(Box::new(e)))?; + + Ok(updated_header.unwrap_or_else(|| last_synced_header.clone())) +} + +/// Execute trusted operations in the enclave. +fn execute_trusted_calls(enclave_api: &E) { + if let Err(e) = enclave_api.execute_trusted_calls() { + error!("{:?}", e); + }; +} diff --git a/bitacross-worker/service/src/sync_block_broadcaster.rs b/bitacross-worker/service/src/sync_block_broadcaster.rs new file mode 100644 index 0000000000..b0752c900d --- /dev/null +++ b/bitacross-worker/service/src/sync_block_broadcaster.rs @@ -0,0 +1,57 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +#[cfg(test)] +use mockall::predicate::*; +#[cfg(test)] +use mockall::*; + +use crate::{ + globals::tokio_handle::GetTokioHandle, + worker::{AsyncBlockBroadcaster, WorkerResult}, +}; +use its_primitives::types::block::SignedBlock as SignedSidechainBlock; +use std::sync::Arc; + +/// Allows to broadcast blocks, does it in a synchronous (i.e. blocking) manner +#[cfg_attr(test, automock)] +pub trait BroadcastBlocks { + fn broadcast_blocks(&self, blocks: Vec) -> WorkerResult<()>; +} + +pub struct SyncBlockBroadcaster { + tokio_handle: Arc, + worker: Arc, +} + +impl SyncBlockBroadcaster { + pub fn new(tokio_handle: Arc, worker: Arc) -> Self { + SyncBlockBroadcaster { tokio_handle, worker } + } +} + +impl BroadcastBlocks for SyncBlockBroadcaster +where + T: GetTokioHandle, + W: AsyncBlockBroadcaster, +{ + fn broadcast_blocks(&self, blocks: Vec) -> WorkerResult<()> { + let handle = self.tokio_handle.get_handle(); + handle.block_on(self.worker.broadcast_blocks(blocks)) + } +} diff --git a/bitacross-worker/service/src/sync_state.rs b/bitacross-worker/service/src/sync_state.rs new file mode 100644 index 0000000000..21d2d4d7e0 --- /dev/null +++ b/bitacross-worker/service/src/sync_state.rs @@ -0,0 +1,99 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +//! Request state keys from a fellow validateer. + +use crate::{ + enclave::tls_ra::enclave_request_state_provisioning, + error::{Error, ServiceResult as Result}, +}; +use futures::executor; +use itc_rpc_client::direct_client::{DirectApi, DirectClient as DirectWorkerApi}; +use itp_enclave_api::{ + enclave_base::EnclaveBase, + remote_attestation::{RemoteAttestation, TlsRemoteAttestation}, +}; +use itp_node_api::api_client::PalletTeerexApi; +use itp_settings::worker_mode::{ProvideWorkerMode, WorkerMode}; +use itp_types::ShardIdentifier; +use sgx_types::sgx_quote_sign_type_t; +use std::string::String; + +pub(crate) fn sync_state< + E: TlsRemoteAttestation + EnclaveBase + RemoteAttestation, + NodeApi: PalletTeerexApi, + WorkerModeProvider: ProvideWorkerMode, +>( + node_api: &NodeApi, + shard: &ShardIdentifier, + enclave_api: &E, + skip_ra: bool, +) { + // FIXME: we now assume that keys are equal for all shards. + let provider_url = match WorkerModeProvider::worker_mode() { + WorkerMode::Sidechain => + executor::block_on(get_author_url_of_last_finalized_sidechain_block(node_api, shard)) + .expect("Author of last finalized sidechain block could not be found"), + _ => executor::block_on(get_enclave_url_of_first_registered(node_api, enclave_api)) + .expect("Author of last finalized sidechain block could not be found"), + }; + + println!("Requesting state provisioning from worker at {}", &provider_url); + + enclave_request_state_provisioning( + enclave_api, + sgx_quote_sign_type_t::SGX_UNLINKABLE_SIGNATURE, + &provider_url, + shard, + skip_ra, + ) + .unwrap(); + println!("[+] State provisioning successfully performed."); +} + +/// Returns the url of the last sidechain block author that has been stored +/// in the parentchain state as "worker for shard". +/// +/// Note: The sidechainblock author will only change whenever a new parentchain block is +/// produced. And even then, it might be the same as the last block. So if several workers +/// are started in a timely manner, they will all get the same url. +async fn get_author_url_of_last_finalized_sidechain_block( + node_api: &NodeApi, + shard: &ShardIdentifier, +) -> Result { + let enclave = node_api + .worker_for_shard(shard, None)? + .ok_or_else(|| Error::NoWorkerForShardFound(*shard))?; + let worker_api_direct = DirectWorkerApi::new(enclave.url); + Ok(worker_api_direct.get_mu_ra_url()?) +} + +/// Returns the url of the first Enclave that matches our own MRENCLAVE. +/// +/// This should be run before we register ourselves as enclave, to ensure we don't get our own url. +async fn get_enclave_url_of_first_registered( + node_api: &NodeApi, + enclave_api: &EnclaveApi, +) -> Result { + let self_mr_enclave = enclave_api.get_fingerprint()?; + let first_enclave = node_api + .all_enclaves(None)? + .into_iter() + .find(|e| e.mr_enclave == self_mr_enclave.to_fixed_bytes()) + .ok_or(Error::NoPeerWorkerFound)?; + let worker_api_direct = DirectWorkerApi::new(first_enclave.url); + Ok(worker_api_direct.get_mu_ra_url()?) +} diff --git a/bitacross-worker/service/src/teeracle/mod.rs b/bitacross-worker/service/src/teeracle/mod.rs new file mode 100644 index 0000000000..420a175b26 --- /dev/null +++ b/bitacross-worker/service/src/teeracle/mod.rs @@ -0,0 +1,142 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{error::ServiceResult, teeracle::schedule_periodic::schedule_periodic}; +use codec::{Decode, Encode}; +use itp_enclave_api::teeracle_api::TeeracleApi; +use itp_node_api::api_client::ParentchainApi; +use itp_types::parentchain::Hash; +use itp_utils::hex::hex_encode; +use log::*; +use sp_runtime::OpaqueExtrinsic; +use std::time::Duration; +use substrate_api_client::{SubmitAndWatch, XtStatus}; +use teeracle_metrics::{increment_number_of_request_failures, set_extrinsics_inclusion_success}; +use tokio::runtime::Handle; + +pub(crate) mod schedule_periodic; +pub(crate) mod teeracle_metrics; + +/// Schedule periodic reregistration of the enclave. +/// +/// The `send_register_xt` needs to create a fresh registration extrinsic every time it is called +/// (updated nonce, fresh IAS-RA or DCAP-Quote). +/// +/// Currently, this is only used for the teeracle, but could also be used for other flavors in the +/// future. +pub(crate) fn schedule_periodic_reregistration_thread( + send_register_xt: impl Fn() -> Option + std::marker::Send + 'static, + period: Duration, +) { + println!("Schedule periodic enclave reregistration every: {:?}", period); + + std::thread::Builder::new() + .name("enclave_reregistration_thread".to_owned()) + .spawn(move || { + schedule_periodic( + || { + trace!("Reregistering the enclave."); + if let Some(block_hash) = send_register_xt() { + println!( + "✅ Successfully reregistered the enclave. Block hash: {}.", + block_hash + ) + } else { + error!("❌ Could not reregister the enclave.") + } + }, + period, + ); + }) + .unwrap(); +} + +/// Executes a periodic teeracle data update and sends the new data to the parentchain. +/// +/// Note: Puts the current thread to sleep for `period`. +pub(crate) fn start_periodic_market_update( + api: &ParentchainApi, + period: Duration, + enclave_api: &E, + tokio_handle: &Handle, +) { + let updates_to_run = || { + if let Err(e) = execute_oracle_update(api, tokio_handle, || { + // Get market data for usd (hardcoded) + enclave_api.update_market_data_xt("TEER", "USD") + }) { + error!("Error running market update {:?}", e) + } + + // TODO: Refactor and add this back according to ISSUE: https://github.com/integritee-network/worker/issues/1300 + // if let Err(e) = execute_oracle_update(api, tokio_handle, || { + // enclave_api.update_weather_data_xt("54.32", "15.37") + // }) { + // error!("Error running weather update {:?}", e) + // } + }; + info!("Teeracle will update now"); + updates_to_run(); + + info!("Schedule teeracle updates every {:?}", period); + schedule_periodic(updates_to_run, period); +} + +fn execute_oracle_update( + node_api: &ParentchainApi, + tokio_handle: &Handle, + get_oracle_xt: F, +) -> ServiceResult<()> +where + F: Fn() -> Result, itp_enclave_api::error::Error>, +{ + let oracle_xt = get_oracle_xt().map_err(|e| { + increment_number_of_request_failures(); + e + })?; + + let extrinsics = >::decode(&mut oracle_xt.as_slice())?; + + // Send the extrinsics to the parentchain and wait for InBlock confirmation. + for call in extrinsics.into_iter() { + let node_api_clone = node_api.clone(); + tokio_handle.spawn(async move { + let encoded_extrinsic = call.encode(); + debug!("Hex encoded extrinsic to be sent: {}", hex_encode(&encoded_extrinsic)); + + println!("[>] Update oracle data (send the extrinsic)"); + let extrinsic_hash = match node_api_clone.submit_and_watch_opaque_extrinsic_until( + &encoded_extrinsic.into(), + XtStatus::InBlock, + ) { + Err(e) => { + error!("Failed to send extrinsic: {:?}", e); + set_extrinsics_inclusion_success(false); + return + }, + Ok(report) => { + set_extrinsics_inclusion_success(true); + report.extrinsic_hash + }, + }; + + println!("[<] Extrinsic got included into a block. Hash: {:?}\n", extrinsic_hash); + }); + } + + Ok(()) +} diff --git a/bitacross-worker/service/src/teeracle/schedule_periodic.rs b/bitacross-worker/service/src/teeracle/schedule_periodic.rs new file mode 100644 index 0000000000..cde09af452 --- /dev/null +++ b/bitacross-worker/service/src/teeracle/schedule_periodic.rs @@ -0,0 +1,46 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{ + thread, + time::{Duration, Instant}, +}; + +/// Schedules a periodic task in the current thread. +/// +/// In case the task takes longer than is scheduled by the interval duration, +/// the interval timing will drift. The task is responsible for +/// ensuring it does not use up more time than is scheduled. +pub(super) fn schedule_periodic(task: T, period: Duration) +where + T: Fn(), +{ + let mut interval_start = Instant::now(); + loop { + let elapsed = interval_start.elapsed(); + + if elapsed >= period { + // update interval time + interval_start = Instant::now(); + task(); + } else { + // sleep for the rest of the interval + let sleep_time = period - elapsed; + thread::sleep(sleep_time); + } + } +} diff --git a/bitacross-worker/service/src/teeracle/teeracle_metrics.rs b/bitacross-worker/service/src/teeracle/teeracle_metrics.rs new file mode 100644 index 0000000000..8fe62c2092 --- /dev/null +++ b/bitacross-worker/service/src/teeracle/teeracle_metrics.rs @@ -0,0 +1,76 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::error::{Error, ServiceResult}; +use itp_enclave_metrics::ExchangeRateOracleMetric; +use lazy_static::lazy_static; +use prometheus::{ + register_gauge_vec, register_int_counter, register_int_counter_vec, register_int_gauge, + register_int_gauge_vec, GaugeVec, IntCounter, IntCounterVec, IntGauge, IntGaugeVec, +}; + +lazy_static! { + /// Register Teeracle specific metrics + + static ref EXCHANGE_RATE: GaugeVec = + register_gauge_vec!("integritee_teeracle_exchange_rate", "Exchange rates partitioned into source and trading pair", &["source", "trading_pair"]) + .unwrap(); + static ref RESPONSE_TIME: IntGaugeVec = + register_int_gauge_vec!("integritee_teeracle_response_times", "Response times in ms for requests that the oracle makes", &["source"]) + .unwrap(); + static ref NUMBER_OF_REQUESTS: IntCounterVec = + register_int_counter_vec!("integritee_teeracle_number_of_requests", "Number of requests made per source", &["source"]) + .unwrap(); + + static ref NUMBER_OF_REQUEST_FAILURES: IntCounter = + register_int_counter!("integritee_teeracle_request_failures", "Number of requests that failed") + .unwrap(); + + static ref EXTRINSIC_INCLUSION_SUCCESS: IntGauge = + register_int_gauge!("integritee_teeracle_extrinsic_inclusion_success", "1 if extrinsics was successfully finalized, 0 if not") + .unwrap(); +} + +pub(super) fn increment_number_of_request_failures() { + NUMBER_OF_REQUEST_FAILURES.inc(); +} + +pub(super) fn set_extrinsics_inclusion_success(is_successful: bool) { + let success_values = i64::from(is_successful); + EXTRINSIC_INCLUSION_SUCCESS.set(success_values); +} + +pub fn update_teeracle_metrics(metric: ExchangeRateOracleMetric) -> ServiceResult<()> { + match metric { + ExchangeRateOracleMetric::ExchangeRate(source, trading_pair, exchange_rate) => + EXCHANGE_RATE + .get_metric_with_label_values(&[source.as_str(), trading_pair.as_str()]) + .map(|m| m.set(exchange_rate.to_num())) + .map_err(|e| Error::Custom(e.into()))?, + + ExchangeRateOracleMetric::ResponseTime(source, t) => RESPONSE_TIME + .get_metric_with_label_values(&[source.as_str()]) + .map(|m| m.set(t as i64)) + .map_err(|e| Error::Custom(e.into()))?, + + ExchangeRateOracleMetric::NumberRequestsIncrement(source) => NUMBER_OF_REQUESTS + .get_metric_with_label_values(&[source.as_str()]) + .map(|m| m.inc()) + .map_err(|e| Error::Custom(e.into()))?, + }; + Ok(()) +} diff --git a/bitacross-worker/service/src/tests/commons.rs b/bitacross-worker/service/src/tests/commons.rs new file mode 100644 index 0000000000..df6b5c9172 --- /dev/null +++ b/bitacross-worker/service/src/tests/commons.rs @@ -0,0 +1,63 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 serde_derive::{Deserialize, Serialize}; +use sgx_types::*; +use std::str; + +#[cfg(test)] +use crate::config::Config; + +#[derive(Debug, Serialize, Deserialize)] +pub struct Message { + pub account: String, + pub amount: u32, + pub sha256: sgx_sha256_hash_t, +} + +#[cfg(test)] +pub fn local_worker_config( + worker_url: String, + untrusted_worker_port: String, + mu_ra_port: String, +) -> Config { + let mut url = worker_url.split(':'); + + Config::new( + Default::default(), + Default::default(), + Default::default(), + Default::default(), + Default::default(), + Default::default(), + url.next().unwrap().into(), + None, + url.next().unwrap().into(), + None, + untrusted_worker_port, + None, + mu_ra_port, + false, + "8787".to_string(), + "4545".to_string(), + crate::config::pwd(), + None, + "0".to_string(), + None, + 0, + ) +} diff --git a/bitacross-worker/service/src/tests/mock.rs b/bitacross-worker/service/src/tests/mock.rs new file mode 100644 index 0000000000..0587669dc4 --- /dev/null +++ b/bitacross-worker/service/src/tests/mock.rs @@ -0,0 +1,68 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 itp_node_api::api_client::{ApiResult, PalletTeerexApi}; +use itp_types::{Enclave, MrEnclave, ShardIdentifier, H256 as Hash}; +use std::collections::HashSet; + +pub struct TestNodeApi; + +pub const W1_URL: &str = "127.0.0.1:22222"; +pub const W2_URL: &str = "127.0.0.1:33333"; + +pub fn enclaves() -> Vec { + vec![ + Enclave::new([0; 32].into(), [1; 32], 1, format!("wss://{}", W1_URL)), + Enclave::new([2; 32].into(), [3; 32], 2, format!("wss://{}", W2_URL)), + ] +} + +impl PalletTeerexApi for TestNodeApi { + type Hash = Hash; + + fn enclave(&self, index: u64, _at_block: Option) -> ApiResult> { + Ok(Some(enclaves().remove(index as usize))) + } + fn enclave_count(&self, _at_block: Option) -> ApiResult { + unreachable!() + } + + fn all_enclaves(&self, _at_block: Option) -> ApiResult> { + Ok(enclaves()) + } + + fn worker_for_shard( + &self, + _: &ShardIdentifier, + _at_block: Option, + ) -> ApiResult> { + unreachable!() + } + fn latest_ipfs_hash( + &self, + _: &ShardIdentifier, + _at_block: Option, + ) -> ApiResult> { + unreachable!() + } + + fn all_scheduled_mrenclaves(&self, _at_block: Option) -> ApiResult> { + let enclaves = enclaves(); + let mr_enclaves: HashSet<_> = enclaves.into_iter().map(|e| e.mr_enclave).collect(); + Ok(mr_enclaves.into_iter().collect()) + } +} diff --git a/bitacross-worker/service/src/tests/mocks/broadcast_blocks_mock.rs b/bitacross-worker/service/src/tests/mocks/broadcast_blocks_mock.rs new file mode 100644 index 0000000000..2df5f65506 --- /dev/null +++ b/bitacross-worker/service/src/tests/mocks/broadcast_blocks_mock.rs @@ -0,0 +1,28 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{sync_block_broadcaster::BroadcastBlocks, worker::WorkerResult}; +use its_primitives::types::block::SignedBlock as SignedSidechainBlock; +use std::vec::Vec; + +pub struct BroadcastBlocksMock; + +impl BroadcastBlocks for BroadcastBlocksMock { + fn broadcast_blocks(&self, _blocks: Vec) -> WorkerResult<()> { + Ok(()) + } +} diff --git a/bitacross-worker/service/src/tests/mocks/direct_request_mock.rs b/bitacross-worker/service/src/tests/mocks/direct_request_mock.rs new file mode 100644 index 0000000000..a2c572dfc6 --- /dev/null +++ b/bitacross-worker/service/src/tests/mocks/direct_request_mock.rs @@ -0,0 +1,26 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 itp_enclave_api::{direct_request::DirectRequest, EnclaveResult}; + +pub struct DirectRequestMock; + +impl DirectRequest for DirectRequestMock { + fn rpc(&self, request: Vec) -> EnclaveResult> { + Ok(request) + } +} diff --git a/bitacross-worker/service/src/tests/mocks/enclave_api_mock.rs b/bitacross-worker/service/src/tests/mocks/enclave_api_mock.rs new file mode 100644 index 0000000000..af27dd3fae --- /dev/null +++ b/bitacross-worker/service/src/tests/mocks/enclave_api_mock.rs @@ -0,0 +1,124 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 core::fmt::Debug; +use itc_parentchain::primitives::{ + ParentchainId, ParentchainInitParams, + ParentchainInitParams::{Parachain, Solochain}, +}; +use itp_enclave_api::{enclave_base::EnclaveBase, sidechain::Sidechain, EnclaveResult}; +use itp_settings::worker::MR_ENCLAVE_SIZE; +use itp_storage::StorageProof; +use itp_types::ShardIdentifier; +use sgx_crypto_helper::rsa3072::Rsa3072PubKey; +use sp_core::ed25519; +use teerex_primitives::EnclaveFingerprint; + +/// mock for EnclaveBase - use in tests +pub struct EnclaveMock; + +impl EnclaveBase for EnclaveMock { + fn init(&self, _mu_ra_url: &str, _untrusted_url: &str, _base_dir: &str) -> EnclaveResult<()> { + Ok(()) + } + + fn init_enclave_sidechain_components( + &self, + _fail_mode: Option, + _fail_at: u64, + ) -> EnclaveResult<()> { + Ok(()) + } + + fn init_direct_invocation_server(&self, _rpc_server_addr: String) -> EnclaveResult<()> { + unreachable!() + } + + fn init_parentchain_components( + &self, + params: ParentchainInitParams, + ) -> EnclaveResult
{ + let genesis_header_encoded = match params { + Solochain { params, .. } => params.genesis_header.encode(), + Parachain { params, .. } => params.genesis_header.encode(), + }; + let header = Header::decode(&mut genesis_header_encoded.as_slice())?; + Ok(header) + } + + fn init_shard(&self, _shard: Vec) -> EnclaveResult<()> { + unimplemented!() + } + + fn init_proxied_shard_vault( + &self, + _shard: &ShardIdentifier, + _parentchain_id: &ParentchainId, + ) -> EnclaveResult<()> { + unimplemented!() + } + + fn set_nonce(&self, _: u32, _: ParentchainId) -> EnclaveResult<()> { + unimplemented!() + } + + fn set_node_metadata(&self, _metadata: Vec, _: ParentchainId) -> EnclaveResult<()> { + todo!() + } + + fn get_rsa_shielding_pubkey(&self) -> EnclaveResult { + unreachable!() + } + + fn get_ecc_signing_pubkey(&self) -> EnclaveResult { + unreachable!() + } + + fn get_ecc_vault_pubkey(&self, _shard: &ShardIdentifier) -> EnclaveResult { + unreachable!() + } + + fn get_fingerprint(&self) -> EnclaveResult { + Ok([1u8; MR_ENCLAVE_SIZE].into()) + } + + fn migrate_shard(&self, _old_shard: Vec, _new_shard: Vec) -> EnclaveResult<()> { + unimplemented!() + } +} + +impl Sidechain for EnclaveMock { + fn sync_parentchain( + &self, + _blocks: &[sp_runtime::generic::SignedBlock], + _events: &[Vec], + _events_proofs: &[StorageProof], + _: &ParentchainId, + _: bool, + ) -> EnclaveResult<()> { + Ok(()) + } + + fn execute_trusted_calls(&self) -> EnclaveResult<()> { + todo!() + } + + fn ignore_parentchain_block_import_validation_until(&self, _until: u32) -> EnclaveResult<()> { + todo!() + } +} diff --git a/bitacross-worker/service/src/tests/mocks/initialization_handler_mock.rs b/bitacross-worker/service/src/tests/mocks/initialization_handler_mock.rs new file mode 100644 index 0000000000..e4539afc0e --- /dev/null +++ b/bitacross-worker/service/src/tests/mocks/initialization_handler_mock.rs @@ -0,0 +1,36 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::initialized_service::{IsInitialized, TrackInitialization}; + +pub struct TrackInitializationMock; + +impl TrackInitialization for TrackInitializationMock { + fn registered_on_parentchain(&self) {} + + fn sidechain_block_produced(&self) {} + + fn worker_for_shard_registered(&self) {} +} + +pub struct IsInitializedMock; + +impl IsInitialized for IsInitializedMock { + fn is_initialized(&self) -> bool { + true + } +} diff --git a/bitacross-worker/service/src/tests/mocks/mod.rs b/bitacross-worker/service/src/tests/mocks/mod.rs new file mode 100644 index 0000000000..cfe0d6fc76 --- /dev/null +++ b/bitacross-worker/service/src/tests/mocks/mod.rs @@ -0,0 +1,23 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 broadcast_blocks_mock; +pub mod direct_request_mock; +pub mod enclave_api_mock; +pub mod initialization_handler_mock; +pub mod parentchain_api_mock; +pub mod update_worker_peers_mock; diff --git a/bitacross-worker/service/src/tests/mocks/parentchain_api_mock.rs b/bitacross-worker/service/src/tests/mocks/parentchain_api_mock.rs new file mode 100644 index 0000000000..712441b24c --- /dev/null +++ b/bitacross-worker/service/src/tests/mocks/parentchain_api_mock.rs @@ -0,0 +1,104 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 itc_parentchain_test::{ParentchainBlockBuilder, ParentchainHeaderBuilder}; +use itp_node_api::api_client::{ApiResult, Block, ChainApi, SignedBlock}; +use itp_types::{ + parentchain::{Hash, Header, StorageProof}, + H256, +}; +use sp_consensus_grandpa::AuthorityList; + +pub struct ParentchainApiMock { + parentchain: Vec, +} + +impl ParentchainApiMock { + // Todo: Remove when #1451 is resolved + #[allow(unused)] + pub(crate) fn new() -> Self { + ParentchainApiMock { parentchain: Vec::new() } + } + + /// Initializes parentchain with a default block chain of a given length. + // Todo: Remove when #1451 is resolved + #[allow(unused)] + pub fn with_default_blocks(mut self, number_of_blocks: u32) -> Self { + self.parentchain = (1..=number_of_blocks) + .map(|n| { + let header = ParentchainHeaderBuilder::default().with_number(n).build(); + ParentchainBlockBuilder::default().with_header(header).build_signed() + }) + .collect(); + self + } +} + +impl ChainApi for ParentchainApiMock { + type Hash = Hash; + type Block = Block; + type Header = Header; + type BlockNumber = u32; + + fn last_finalized_block(&self) -> ApiResult> { + Ok(self.parentchain.last().cloned()) + } + + fn signed_block(&self, _hash: Option) -> ApiResult> { + todo!() + } + + fn get_genesis_hash(&self) -> ApiResult { + todo!() + } + + fn header(&self, _header_hash: Option) -> ApiResult> { + todo!() + } + + fn get_blocks(&self, from: u32, to: u32) -> ApiResult> { + let num_elements = to.checked_sub(from).map(|n| n + 1).unwrap_or(0); + let blocks = self + .parentchain + .iter() + .skip(from as usize) + .take(num_elements as usize) + .cloned() + .collect(); + ApiResult::Ok(blocks) + } + + fn is_grandpa_available(&self) -> ApiResult { + todo!() + } + + fn grandpa_authorities(&self, _hash: Option) -> ApiResult { + todo!() + } + + fn grandpa_authorities_proof(&self, _hash: Option) -> ApiResult { + todo!() + } + + fn get_events_value_proof(&self, _block_hash: Option) -> ApiResult { + Ok(Default::default()) + } + + fn get_events_for_block(&self, _block_hash: Option) -> ApiResult> { + Ok(Default::default()) + } +} diff --git a/bitacross-worker/service/src/tests/mocks/update_worker_peers_mock.rs b/bitacross-worker/service/src/tests/mocks/update_worker_peers_mock.rs new file mode 100644 index 0000000000..1f9173f686 --- /dev/null +++ b/bitacross-worker/service/src/tests/mocks/update_worker_peers_mock.rs @@ -0,0 +1,33 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{ + worker::{Url, WorkerResult}, + worker_peers_registry::PeersRegistry, +}; + +pub struct WorkerPeersRegistryMock; + +impl PeersRegistry for WorkerPeersRegistryMock { + fn update_peers(&self) -> WorkerResult<()> { + Ok(()) + } + + fn read_trusted_peers(&self) -> WorkerResult> { + Ok(Vec::new()) + } +} diff --git a/bitacross-worker/service/src/tests/mod.rs b/bitacross-worker/service/src/tests/mod.rs new file mode 100644 index 0000000000..0ef2c4f253 --- /dev/null +++ b/bitacross-worker/service/src/tests/mod.rs @@ -0,0 +1,48 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 commons; +pub mod mock; + +#[cfg(test)] +pub mod mocks; + +// Todo: Revive when #1451 is resolved +// #[cfg(test)] +// pub mod parentchain_handler_test; + +#[cfg(feature = "link-binary")] +use clap::ArgMatches; + +#[cfg(feature = "link-binary")] +pub fn run_enclave_tests(matches: &ArgMatches) { + use crate::{config::Config, enclave::api::*, setup}; + use itp_enclave_api::enclave_test::EnclaveTest; + + println!("*** Starting Test enclave"); + let config = Config::from(matches); + setup::purge_files_from_dir(config.data_dir()).unwrap(); + let enclave = enclave_init(&config).unwrap(); + + if matches.is_present("all") || matches.is_present("unit") { + println!("Running unit Tests"); + enclave.test_main_entrance().unwrap(); + println!("[+] unit_test ended!"); + } + + println!("[+] All tests ended!"); +} diff --git a/bitacross-worker/service/src/tests/parentchain_handler_test.rs b/bitacross-worker/service/src/tests/parentchain_handler_test.rs new file mode 100644 index 0000000000..30339e92bb --- /dev/null +++ b/bitacross-worker/service/src/tests/parentchain_handler_test.rs @@ -0,0 +1,51 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{ + parentchain_handler::{HandleParentchain, ParentchainHandler}, + tests::mocks::{enclave_api_mock::EnclaveMock, parentchain_api_mock::ParentchainApiMock}, +}; +use itc_parentchain::{ + light_client::light_client_init_params::SimpleParams, + primitives::{ParentchainId, ParentchainInitParams}, +}; +use itc_parentchain_test::ParentchainHeaderBuilder; +use itp_node_api::api_client::ChainApi; +use std::sync::Arc; + +#[test] +fn test_number_of_synced_blocks() { + let number_of_blocks = 42; + + let parentchain_api_mock = ParentchainApiMock::new().with_default_blocks(number_of_blocks); + let last_synced_block = + parentchain_api_mock.get_blocks(2, 2).unwrap().first().cloned().unwrap(); + + let enclave_api_mock = EnclaveMock; + let parentchain_params: ParentchainInitParams = + (ParentchainId::Litentry, SimpleParams::new(ParentchainHeaderBuilder::default().build())) + .into(); + + let parentchain_handler = ParentchainHandler::new( + parentchain_api_mock, + Arc::new(enclave_api_mock), + parentchain_params, + ); + + let header = parentchain_handler.sync_parentchain(last_synced_block.block.header).unwrap(); + assert_eq!(header.number, number_of_blocks); +} diff --git a/bitacross-worker/service/src/utils.rs b/bitacross-worker/service/src/utils.rs new file mode 100644 index 0000000000..fd0b60fe82 --- /dev/null +++ b/bitacross-worker/service/src/utils.rs @@ -0,0 +1,53 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 base58::{FromBase58, ToBase58}; +use itp_enclave_api::enclave_base::EnclaveBase; +use itp_types::ShardIdentifier; +use log::info; + +pub fn extract_shard( + maybe_shard_str: Option<&str>, + enclave_api: &E, +) -> ShardIdentifier { + match maybe_shard_str { + Some(value) => { + let shard_vec = value.from_base58().expect("shard must be hex encoded"); + let mut shard = [0u8; 32]; + shard.copy_from_slice(&shard_vec[..]); + shard.into() + }, + _ => { + let mrenclave = enclave_api.get_fingerprint().unwrap(); + info!("no shard specified. using mrenclave as id: {}", mrenclave.0.to_base58()); + ShardIdentifier::from_slice(&mrenclave[..]) + }, + } +} + +#[cfg(not(feature = "dcap"))] +pub fn check_files() { + use itp_settings::files::{ENCLAVE_FILE, RA_API_KEY_FILE, RA_SPID_FILE}; + use log::debug; + use std::path::Path; + debug!("*** Check files"); + let files = [ENCLAVE_FILE, RA_SPID_FILE, RA_API_KEY_FILE]; + for f in files.iter() { + assert!(Path::new(f).exists(), "File doesn't exist: {}", f); + } +} diff --git a/bitacross-worker/service/src/wasm.rs b/bitacross-worker/service/src/wasm.rs new file mode 100644 index 0000000000..fe99445759 --- /dev/null +++ b/bitacross-worker/service/src/wasm.rs @@ -0,0 +1,62 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 sgx_types::*; + +extern "C" { + fn sgxwasm_init(eid: sgx_enclave_id_t, retval: *mut sgx_status_t) -> sgx_status_t; +} + +#[derive(Debug, Serialize, Deserialize)] +pub enum SgxWasmAction { + #[codec(index = 0)] + Call { module: Option>, function: String }, +} + +#[derive(Debug, Serialize, Deserialize)] +pub enum BoundaryValue { + #[codec(index = 0)] + I32(i32), + #[codec(index = 1)] + I64(i64), + #[codec(index = 2)] + F32(u32), + #[codec(index = 3)] + F64(u64), +} + +pub fn sgx_enclave_wasm_init(eid: sgx_enclave_id_t) -> Result<(), String> { + let mut retval: sgx_status_t = sgx_status_t::SGX_SUCCESS; + let result = unsafe { sgxwasm_init(eid, &mut retval) }; + + match result { + sgx_status_t::SGX_SUCCESS => {}, + _ => { + println!("[-] ECALL Enclave Failed {}!", result.as_str()); + panic!("sgx_enclave_wasm_init's ECALL returned unknown error!"); + }, + } + + match retval { + sgx_status_t::SGX_SUCCESS => {}, + _ => { + println!("[-] ECALL Enclave Function return fail: {}!", retval.as_str()); + return Err(format!("ECALL func return error: {}", retval.as_str())) + }, + } + + Ok(()) +} diff --git a/bitacross-worker/service/src/worker.rs b/bitacross-worker/service/src/worker.rs new file mode 100644 index 0000000000..638e4f081b --- /dev/null +++ b/bitacross-worker/service/src/worker.rs @@ -0,0 +1,297 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +///! Integritee worker. Inspiration for this design came from parity's substrate Client. +/// +/// This should serve as a proof of concept for a potential refactoring design. Ultimately, everything +/// from the main.rs should be covered by the worker struct here - hidden and split across +/// multiple traits. +use crate::{config::Config, error::Error, initialized_service::TrackInitialization}; +use async_trait::async_trait; +use codec::{Decode, Encode}; +use itc_rpc_client::direct_client::{DirectApi, DirectClient as DirectWorkerApi}; +use itp_enclave_api::enclave_base::EnclaveBase; +use itp_node_api::{api_client::PalletTeerexApi, node_api_factory::CreateNodeApi}; +use its_primitives::types::SignedBlock as SignedSidechainBlock; +use its_rpc_handler::constants::RPC_METHOD_NAME_IMPORT_BLOCKS; +use jsonrpsee::{ + types::{to_json_value, traits::Client}, + ws_client::WsClientBuilder, +}; +use log::*; +use std::{ + collections::HashSet, + sync::{Arc, RwLock}, +}; + +pub type WorkerResult = Result; +pub type Url = String; + +#[derive(Clone, Hash, Eq, PartialEq, Encode, Decode, Debug)] +pub struct PeerUrls { + pub trusted: Url, + pub untrusted: Url, + pub me: bool, +} + +impl PeerUrls { + pub fn new(trusted: Url, untrusted: Url, me: bool) -> Self { + PeerUrls { trusted, untrusted, me } + } +} + +pub struct Worker { + _config: Config, + // unused yet, but will be used when more methods are migrated to the worker + _enclave_api: Arc, + node_api_factory: Arc, + initialization_handler: Arc, + peer_urls: RwLock>, +} + +impl + Worker +{ + pub fn new( + config: Config, + enclave_api: Arc, + node_api_factory: Arc, + initialization_handler: Arc, + peer_urls: HashSet, + ) -> Self { + Self { + _config: config, + _enclave_api: enclave_api, + node_api_factory, + initialization_handler, + peer_urls: RwLock::new(peer_urls), + } + } +} + +#[async_trait] +/// Broadcast Sidechain blocks to peers. +pub trait AsyncBlockBroadcaster { + async fn broadcast_blocks(&self, blocks: Vec) -> WorkerResult<()>; +} + +#[async_trait] +impl AsyncBlockBroadcaster + for Worker +where + NodeApiFactory: CreateNodeApi + Send + Sync, + Enclave: Send + Sync, + InitializationHandler: TrackInitialization + Send + Sync, +{ + async fn broadcast_blocks(&self, blocks: Vec) -> WorkerResult<()> { + if blocks.is_empty() { + debug!("No blocks to broadcast, returning"); + return Ok(()) + } + + let blocks_json = vec![to_json_value(blocks)?]; + let peers = self + .peer_urls + .read() + .map_err(|e| { + Error::Custom(format!("Encountered poisoned lock for peers: {:?}", e).into()) + }) + .map(|l| l.clone())?; + + self.initialization_handler.sidechain_block_produced(); + + for url in peers { + let blocks = blocks_json.clone(); + + tokio::spawn(async move { + let untrusted_peer_url = url.untrusted; + + debug!("Broadcasting block to peer with address: {:?}", untrusted_peer_url); + // FIXME: Websocket connection to a worker should stay, once established. + let client = match WsClientBuilder::default().build(&untrusted_peer_url).await { + Ok(c) => c, + Err(e) => { + error!("Failed to create websocket client for block broadcasting (target url: {}): {:?}", untrusted_peer_url, e); + return + }, + }; + + if let Err(e) = + client.request::>(RPC_METHOD_NAME_IMPORT_BLOCKS, blocks.into()).await + { + error!( + "Broadcast block request ({}) to {} failed: {:?}", + RPC_METHOD_NAME_IMPORT_BLOCKS, untrusted_peer_url, e + ); + } + }); + } + Ok(()) + } +} + +/// Looks for new peers and updates them. +pub trait UpdatePeers { + fn search_peers(&self) -> WorkerResult>; + + fn set_peers_urls(&self, peers: HashSet) -> WorkerResult<()>; + + fn update_peers(&self) -> WorkerResult<()> { + let peers = self.search_peers()?; + self.set_peers_urls(peers) + } +} + +pub trait GetPeers { + fn read_peers_urls(&self) -> WorkerResult>; +} + +impl GetPeers + for Worker +where + NodeApiFactory: CreateNodeApi + Send + Sync, + Enclave: EnclaveBase + itp_enclave_api::remote_attestation::TlsRemoteAttestation, +{ + fn read_peers_urls(&self) -> WorkerResult> { + if let Ok(peer_urls) = self.peer_urls.read() { + Ok(peer_urls.clone()) + } else { + Err(Error::Custom("Encountered poisoned lock for peers".into())) + } + } +} + +impl UpdatePeers + for Worker +where + NodeApiFactory: CreateNodeApi + Send + Sync, + Enclave: EnclaveBase + itp_enclave_api::remote_attestation::TlsRemoteAttestation, +{ + fn search_peers(&self) -> WorkerResult> { + let worker_url_external = self._config.trusted_worker_url_external(); + let node_api = self + .node_api_factory + .create_api() + .map_err(|e| Error::Custom(format!("Failed to create NodeApi: {:?}", e).into()))?; + let enclaves = node_api.all_enclaves(None)?; + let mut peer_urls = HashSet::::new(); + for enclave in enclaves { + // FIXME: This is temporary only, as block broadcasting should be moved to trusted ws server. + let enclave_url = enclave.url.clone(); + let worker_api_direct = DirectWorkerApi::new(enclave_url.clone()); + match worker_api_direct.get_untrusted_worker_url() { + Ok(untrusted_worker_url) => { + let is_me = enclave_url == worker_url_external; + peer_urls.insert(PeerUrls::new(enclave_url, untrusted_worker_url, is_me)); + }, + Err(e) => { + warn!("Failed to get untrusted worker url (enclave: {}): {:?}", enclave_url, e); + }, + } + } + Ok(peer_urls) + } + + fn set_peers_urls(&self, peers: HashSet) -> WorkerResult<()> { + let peers_vec: Vec = peers.clone().into_iter().collect(); + info!("Setting peers urls: {:?}", peers_vec); + + let mut peer_urls = self.peer_urls.write().map_err(|e| { + Error::Custom(format!("Encountered poisoned lock for peers urls: {:?}", e).into()) + })?; + *peer_urls = peers; + Ok(()) + } +} +#[cfg(test)] +mod tests { + use super::*; + use crate::{ + tests::{ + commons::local_worker_config, + mock::{W1_URL, W2_URL}, + mocks::initialization_handler_mock::TrackInitializationMock, + }, + worker::{AsyncBlockBroadcaster, Worker}, + }; + use frame_support::assert_ok; + use itp_node_api::node_api_factory::NodeApiFactory; + use its_primitives::types::block::SignedBlock as SignedSidechainBlock; + use its_test::sidechain_block_builder::{SidechainBlockBuilder, SidechainBlockBuilderTrait}; + use jsonrpsee::{ws_server::WsServerBuilder, RpcModule}; + use log::debug; + use sp_keyring::AccountKeyring; + use std::{net::SocketAddr, sync::Arc}; + use tokio::net::ToSocketAddrs; + + fn init() { + let _ = env_logger::builder().is_test(true).try_init(); + } + + async fn run_server(addr: impl ToSocketAddrs) -> anyhow::Result { + let mut server = WsServerBuilder::default().build(addr).await?; + let mut module = RpcModule::new(()); + + module.register_method(RPC_METHOD_NAME_IMPORT_BLOCKS, |params, _| { + debug!("{} params: {:?}", RPC_METHOD_NAME_IMPORT_BLOCKS, params); + let _blocks: Vec = params.one()?; + Ok("ok".as_bytes().to_vec()) + })?; + + server.register_module(module).unwrap(); + + let socket_addr = server.local_addr()?; + tokio::spawn(async move { server.start().await }); + Ok(socket_addr) + } + + #[tokio::test] + async fn broadcast_blocks_works() { + init(); + run_server(W1_URL).await.unwrap(); + run_server(W2_URL).await.unwrap(); + let untrusted_worker_port = "4000".to_string(); + let mut peer_urls: HashSet = HashSet::new(); + + peer_urls.insert(PeerUrls { + untrusted: format!("ws://{}", W1_URL), + trusted: format!("ws://{}", W1_URL), + me: false, + }); + peer_urls.insert(PeerUrls { + untrusted: format!("ws://{}", W2_URL), + trusted: format!("ws://{}", W2_URL), + me: false, + }); + + let worker = Worker::new( + local_worker_config(W1_URL.into(), untrusted_worker_port.clone(), "30".to_string()), + Arc::new(()), + Arc::new(NodeApiFactory::new( + "ws://invalid.url".to_string(), + AccountKeyring::Alice.pair(), + )), + Arc::new(TrackInitializationMock {}), + peer_urls, + ); + + let resp = worker + .broadcast_blocks(vec![SidechainBlockBuilder::default().build_signed()]) + .await; + assert_ok!(resp); + } +} diff --git a/bitacross-worker/service/src/worker_peers_registry.rs b/bitacross-worker/service/src/worker_peers_registry.rs new file mode 100644 index 0000000000..156408b634 --- /dev/null +++ b/bitacross-worker/service/src/worker_peers_registry.rs @@ -0,0 +1,56 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +#[cfg(test)] +use mockall::predicate::*; +#[cfg(test)] +use mockall::*; + +use crate::worker::{GetPeers, UpdatePeers, Url, WorkerResult}; +use std::sync::Arc; + +/// Updates the peers of the global worker. +#[cfg_attr(test, automock)] +pub trait PeersRegistry { + fn update_peers(&self) -> WorkerResult<()>; + fn read_trusted_peers(&self) -> WorkerResult>; +} + +pub struct WorkerPeersRegistry { + worker: Arc, +} + +impl WorkerPeersRegistry { + pub fn new(worker: Arc) -> Self { + WorkerPeersRegistry { worker } + } +} + +impl PeersRegistry for WorkerPeersRegistry +where + WorkerType: UpdatePeers + GetPeers, +{ + fn update_peers(&self) -> WorkerResult<()> { + self.worker.update_peers() + } + + fn read_trusted_peers(&self) -> WorkerResult> { + let peer_urls = self.worker.read_peers_urls()?; + Ok(peer_urls.into_iter().filter(|urls| !urls.me).map(|urls| urls.trusted).collect()) + } +} diff --git a/bitacross-worker/sidechain/block-composer/Cargo.toml b/bitacross-worker/sidechain/block-composer/Cargo.toml new file mode 100644 index 0000000000..f1be550d61 --- /dev/null +++ b/bitacross-worker/sidechain/block-composer/Cargo.toml @@ -0,0 +1,64 @@ +[package] +name = "its-block-composer" +version = "0.9.0" +authors = ['Trust Computing GmbH ', 'Integritee AG '] +edition = "2021" + +[dependencies] +# sgx dependencies +sgx_tstd = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git", optional = true } +sgx_types = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git" } + +# local dependencies +itp-node-api = { path = "../../core-primitives/node-api", default-features = false } +itp-settings = { path = "../../core-primitives/settings", default-features = false } +itp-sgx-crypto = { path = "../../core-primitives/sgx/crypto", default-features = false } +itp-sgx-externalities = { path = "../../core-primitives/substrate-sgx/externalities", default-features = false } +itp-stf-executor = { path = "../../core-primitives/stf-executor", default-features = false } +itp-stf-primitives = { path = "../../core-primitives/stf-primitives", default-features = false } +itp-time-utils = { path = "../../core-primitives/time-utils", default-features = false } +itp-top-pool-author = { path = "../../core-primitives/top-pool-author", default-features = false } +itp-types = { path = "../../core-primitives/types", default-features = false } +its-primitives = { path = "../primitives", default-features = false, features = ["full_crypto"] } +its-state = { path = "../state", default-features = false } + +# sgx enabled external libraries +thiserror_sgx = { package = "thiserror", git = "https://github.com/mesalock-linux/thiserror-sgx", tag = "sgx_1.1.3", optional = true } + +# std compatible external libraries (make sure these versions match with the sgx-enabled ones above) +thiserror = { version = "1.0", optional = true } + +# no-std compatible libraries +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +log = { version = "0.4", default-features = false } +sp-core = { default-features = false, features = ["full_crypto"], git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } +sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } + + +[features] +default = ["std"] +std = [ + "itp-node-api/std", + "itp-sgx-crypto/std", + "itp-sgx-externalities/std", + "itp-stf-executor/std", + "itp-stf-primitives/std", + "itp-time-utils/std", + "itp-top-pool-author/std", + "itp-types/std", + "its-primitives/std", + "its-state/std", + "log/std", + "thiserror", +] +sgx = [ + "sgx_tstd", + "itp-node-api/sgx", + "itp-sgx-crypto/sgx", + "itp-sgx-externalities/sgx", + "itp-stf-executor/sgx", + "itp-time-utils/sgx", + "itp-top-pool-author/sgx", + "its-state/sgx", + "thiserror_sgx", +] diff --git a/bitacross-worker/sidechain/block-composer/src/block_composer.rs b/bitacross-worker/sidechain/block-composer/src/block_composer.rs new file mode 100644 index 0000000000..d87f7e61d3 --- /dev/null +++ b/bitacross-worker/sidechain/block-composer/src/block_composer.rs @@ -0,0 +1,185 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::error::{Error, Result}; +use codec::Encode; +use itp_settings::worker::BLOCK_NUMBER_FINALIZATION_DIFF; +use itp_sgx_crypto::{key_repository::AccessKey, StateCrypto}; +use itp_sgx_externalities::{SgxExternalitiesTrait, StateHash}; +use itp_stf_primitives::types::StatePayload; +use itp_time_utils::now_as_millis; +use itp_types::{ShardIdentifier, H256}; +use its_primitives::traits::{ + Block as SidechainBlockTrait, BlockData, Header as HeaderTrait, SignBlock, + SignedBlock as SignedSidechainBlockTrait, +}; +use its_state::{LastBlockExt, SidechainState, SidechainSystemExt}; +use log::*; +use sp_core::Pair; +use sp_runtime::{ + traits::{Block as ParentchainBlockTrait, Header}, + MultiSignature, +}; +use std::{format, marker::PhantomData, sync::Arc, vec::Vec}; + +/// Compose a sidechain block and corresponding confirmation extrinsic for the parentchain +/// +pub trait ComposeBlock { + type SignedSidechainBlock: SignedSidechainBlockTrait; + + fn compose_block( + &self, + latest_parentchain_header: &::Header, + top_call_hashes: Vec, + shard: ShardIdentifier, + state_hash_apriori: H256, + aposteriori_state: &Externalities, + ) -> Result; +} + +/// Block composer implementation for the sidechain +pub struct BlockComposer { + signer: Signer, + state_key_repository: Arc, + _phantom: PhantomData<(ParentchainBlock, SignedSidechainBlock)>, +} + +impl + BlockComposer +where + ParentchainBlock: ParentchainBlockTrait, + SignedSidechainBlock: + SignedSidechainBlockTrait, + SignedSidechainBlock::Block: SidechainBlockTrait, + <::Block as SidechainBlockTrait>::HeaderType: + HeaderTrait, + SignedSidechainBlock::Signature: From, + Signer: Pair, + Signer::Public: Encode, + StateKeyRepository: AccessKey, + ::KeyType: StateCrypto, +{ + pub fn new(signer: Signer, state_key_repository: Arc) -> Self { + BlockComposer { signer, state_key_repository, _phantom: Default::default() } + } +} + +type HeaderTypeOf = <::Block as SidechainBlockTrait>::HeaderType; +type BlockDataTypeOf = + <::Block as SidechainBlockTrait>::BlockDataType; + +impl + ComposeBlock + for BlockComposer +where + ParentchainBlock: ParentchainBlockTrait, + SignedSidechainBlock: + SignedSidechainBlockTrait, + SignedSidechainBlock::Block: SidechainBlockTrait, + <::Block as SidechainBlockTrait>::HeaderType: + HeaderTrait, + SignedSidechainBlock::Signature: From, + Externalities: SgxExternalitiesTrait + + SidechainState + + SidechainSystemExt + + StateHash + + LastBlockExt + + Encode, + ::SgxExternalitiesType: Encode, + ::SgxExternalitiesDiffType: Encode, + Signer: Pair, + Signer::Public: Encode, + StateKeyRepository: AccessKey, + ::KeyType: StateCrypto, +{ + type SignedSidechainBlock = SignedSidechainBlock; + + fn compose_block( + &self, + latest_parentchain_header: &ParentchainBlock::Header, + top_call_hashes: Vec, + shard: ShardIdentifier, + state_hash_apriori: H256, + aposteriori_state: &Externalities, + ) -> Result { + let author_public = self.signer.public(); + + let state_hash_new = aposteriori_state.hash(); + + let (block_number, parent_hash, next_finalization_block_number) = + match aposteriori_state.get_last_block() { + Some(block) => ( + block.header().block_number() + 1, + block.hash(), + block.header().next_finalization_block_number(), + ), + None => { + info!("Seems to be first sidechain block."); + (1, Default::default(), 1) + }, + }; + + if block_number != aposteriori_state.get_block_number().unwrap_or(0) { + return Err(Error::Other("[Sidechain] BlockNumber is not LastBlock's Number + 1".into())) + } + + // create encrypted payload + let mut payload: Vec = + StatePayload::new(state_hash_apriori, state_hash_new, aposteriori_state.state_diff()) + .encode(); + + let state_key = self + .state_key_repository + .retrieve_key() + .map_err(|e| Error::Other(format!("Failed to retrieve state key: {:?}", e).into()))?; + + state_key.encrypt(&mut payload).map_err(|e| { + Error::Other(format!("Failed to encrypt state payload: {:?}", e).into()) + })?; + + let block_data = BlockDataTypeOf::::new( + author_public, + latest_parentchain_header.hash(), + top_call_hashes, + payload, + now_as_millis(), + ); + + let mut finalization_candidate = next_finalization_block_number; + if block_number == 1 { + finalization_candidate = 1; + } else if block_number > finalization_candidate { + finalization_candidate += BLOCK_NUMBER_FINALIZATION_DIFF; + } + + let header = HeaderTypeOf::::new( + block_number, + parent_hash, + shard, + block_data.hash(), + finalization_candidate, + ); + + let block = SignedSidechainBlock::Block::new(header.clone(), block_data); + + debug!("Block header hash {}", header.hash()); + + let signed_block = block.sign_block(&self.signer); + + Ok(signed_block) + } +} diff --git a/bitacross-worker/sidechain/block-composer/src/error.rs b/bitacross-worker/sidechain/block-composer/src/error.rs new file mode 100644 index 0000000000..6baba32eb7 --- /dev/null +++ b/bitacross-worker/sidechain/block-composer/src/error.rs @@ -0,0 +1,59 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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(all(not(feature = "std"), feature = "sgx"))] +use crate::sgx_reexport_prelude::*; + +use sgx_types::sgx_status_t; +use std::{boxed::Box, format}; + +pub type Result = core::result::Result; + +/// Block composer error +#[derive(Debug, thiserror::Error)] +pub enum Error { + #[error("SGX error, status: {0}")] + Sgx(sgx_status_t), + #[error("STF execution error: {0}")] + StfExecution(#[from] itp_stf_executor::error::Error), + #[error("TOP pool RPC author error: {0}")] + TopPoolAuthor(#[from] itp_top_pool_author::error::Error), + #[error("Node Metadata error: {0:?}")] + NodeMetadata(itp_node_api::metadata::Error), + #[error("Node metadata provider error: {0:?}")] + NodeMetadataProvider(#[from] itp_node_api::metadata::provider::Error), + #[error(transparent)] + Other(#[from] Box), +} + +impl From for Error { + fn from(sgx_status: sgx_status_t) -> Self { + Self::Sgx(sgx_status) + } +} + +impl From for Error { + fn from(e: codec::Error) -> Self { + Self::Other(format!("{:?}", e).into()) + } +} + +impl From for Error { + fn from(e: itp_node_api::metadata::Error) -> Self { + Self::NodeMetadata(e) + } +} diff --git a/bitacross-worker/sidechain/block-composer/src/lib.rs b/bitacross-worker/sidechain/block-composer/src/lib.rs new file mode 100644 index 0000000000..038f348c1d --- /dev/null +++ b/bitacross-worker/sidechain/block-composer/src/lib.rs @@ -0,0 +1,36 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ +//! Sidechain block composing logic. +#![feature(trait_alias)] +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg(all(feature = "std", feature = "sgx"))] +compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the same time"); + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +extern crate sgx_tstd as std; + +// re-export module to properly feature gate sgx and regular std environment +#[cfg(all(not(feature = "std"), feature = "sgx"))] +pub mod sgx_reexport_prelude { + pub use thiserror_sgx as thiserror; +} + +pub mod block_composer; +pub mod error; + +pub use block_composer::*; diff --git a/bitacross-worker/sidechain/block-verification/Cargo.toml b/bitacross-worker/sidechain/block-verification/Cargo.toml new file mode 100644 index 0000000000..9265b86517 --- /dev/null +++ b/bitacross-worker/sidechain/block-verification/Cargo.toml @@ -0,0 +1,52 @@ +[package] +name = "its-block-verification" +description = "Verification logic for sidechain blocks" +version = "0.9.0" +authors = ['Trust Computing GmbH ', 'Integritee AG '] +homepage = "https://litentry.com/" +repository = "https://github.com/litentry/litentry-parachain" +license = "Apache-2.0" +edition = "2021" + +[dependencies] +log = { version = "0.4.17", default-features = false } +thiserror = { version = "1.0.26", optional = true } + +# local deps +itp-types = { default-features = false, path = "../../core-primitives/types" } +itp-utils = { default-features = false, path = "../../core-primitives/utils" } +its-primitives = { default-features = false, path = "../primitives" } + +# substrate deps +frame-support = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } +sp-consensus-slots = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } +sp-core = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } +sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } + +# sgx deps +sgx_tstd = { branch = "master", features = ["untrusted_fs", "net", "backtrace"], git = "https://github.com/apache/teaclave-sgx-sdk.git", optional = true } +thiserror-sgx = { package = "thiserror", git = "https://github.com/mesalock-linux/thiserror-sgx", tag = "sgx_1.1.3", optional = true } + +[features] +default = ["std"] +std = [ + "log/std", + "thiserror", + # local + "itp-types/std", + "its-primitives/std", + # substrate + "frame-support/std", + "sp-consensus-slots/std", + "sp-core/std", + "sp-runtime/std", +] +sgx = [ + "sgx_tstd", + "thiserror-sgx", +] + +[dev-dependencies] +itc-parentchain-test = { path = "../../core/parentchain/test" } +its-test = { path = "../../sidechain/test" } +sp-keyring = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } diff --git a/bitacross-worker/sidechain/block-verification/src/error.rs b/bitacross-worker/sidechain/block-verification/src/error.rs new file mode 100644 index 0000000000..bac9b8d60b --- /dev/null +++ b/bitacross-worker/sidechain/block-verification/src/error.rs @@ -0,0 +1,46 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 sidechain consensus + +use itp_types::BlockHash as ParentchainBlockHash; +use its_primitives::types::{block::BlockHash as SidechainBlockHash, BlockNumber}; +use std::string::String; + +pub type Result = std::result::Result; + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +pub use thiserror_sgx as thiserror; + +#[derive(Debug, thiserror::Error)] +#[non_exhaustive] +pub enum Error { + #[error("Message sender {0} is not a valid authority")] + InvalidAuthority(String), + #[error("Could not get authorities: {0:?}.")] + CouldNotGetAuthorities(String), + #[error("Bad parentchain block (Hash={0}). Reason: {1}")] + BadParentchainBlock(ParentchainBlockHash, String), + #[error("Bad sidechain block (Hash={0}). Reason: {1}")] + BadSidechainBlock(SidechainBlockHash, String), + #[error("Could not import new block due to {2}. (Last imported by number: {0:?})")] + BlockAncestryMismatch(BlockNumber, SidechainBlockHash, String), + #[error("Could not import new block. Expected first block, but found {0}. {1:?}")] + InvalidFirstBlock(BlockNumber, String), + #[error("Could not import block (number: {0}). A block with this number is already imported (current state block number: {1})")] + BlockAlreadyImported(BlockNumber, BlockNumber), +} diff --git a/bitacross-worker/sidechain/block-verification/src/lib.rs b/bitacross-worker/sidechain/block-verification/src/lib.rs new file mode 100644 index 0000000000..b496bcc0be --- /dev/null +++ b/bitacross-worker/sidechain/block-verification/src/lib.rs @@ -0,0 +1,492 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ +#![feature(assert_matches)] +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg(all(feature = "std", feature = "sgx"))] +compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the same time"); + +#[cfg(all(not(feature = "std"), not(feature = "sgx")))] +compile_error!("feature \"std\" and feature \"sgx\" cannot be disabled at the same time"); + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +#[macro_use] +extern crate sgx_tstd as std; + +use crate::slot::{slot_author, slot_from_timestamp_and_duration}; +use error::Error as ConsensusError; +use frame_support::ensure; +use itp_utils::stringify::public_to_string; +use its_primitives::{ + traits::{ + Block as SidechainBlockTrait, BlockData, Header as HeaderTrait, + SignedBlock as SignedSidechainBlockTrait, SignedBlock, + }, + types::block::BlockHash, +}; +use log::*; +pub use sp_consensus_slots::Slot; +use sp_core::ByteArray; +use sp_runtime::{ + app_crypto::Pair, + traits::{Block as ParentchainBlockTrait, Header as ParentchainHeaderTrait}, +}; +use std::{fmt::Debug, time::Duration}; + +pub mod error; +pub mod slot; + +type AuthorityId

=

::Public; + +pub fn verify_sidechain_block( + signed_block: SignedSidechainBlock, + slot_duration: Duration, + last_block: &Option<::Block>, + parentchain_header: &ParentchainBlock::Header, + authorities: &[AuthorityId], +) -> Result +where + AuthorityPair: Pair, + AuthorityPair::Public: Debug, + ParentchainBlock: ParentchainBlockTrait, + SignedSidechainBlock: 'static + SignedSidechainBlockTrait, + SignedSidechainBlock::Block: SidechainBlockTrait, +{ + ensure!( + signed_block.verify_signature(), + ConsensusError::BadSidechainBlock(signed_block.block().hash(), "bad signature".into()) + ); + + let slot = slot_from_timestamp_and_duration( + Duration::from_millis(signed_block.block().block_data().timestamp()), + slot_duration, + ); + + // We need to check the ancestry first to ensure that an already imported block does not result + // in an author verification error, but rather a `BlockAlreadyImported` error. + match last_block { + Some(last_block) => + verify_block_ancestry::(signed_block.block(), last_block)?, + None => ensure_first_block(signed_block.block())?, + } + + if let Err(e) = verify_author::( + &slot, + signed_block.block(), + parentchain_header, + authorities, + ) { + error!( + "Author verification for block (number: {}) failed, block will be discarded", + signed_block.block().header().block_number() + ); + return Err(e) + } + + Ok(signed_block) +} + +/// Verify that the `blocks` author is the expected author when comparing with onchain data. +fn verify_author( + slot: &Slot, + block: &SignedSidechainBlock::Block, + parentchain_head: &ParentchainHeader, + authorities: &[AuthorityId], +) -> Result<(), ConsensusError> +where + AuthorityPair: Pair, + AuthorityPair::Public: Debug, + SignedSidechainBlock: SignedSidechainBlockTrait + 'static, + ParentchainHeader: ParentchainHeaderTrait, +{ + ensure!( + parentchain_head.hash() == block.block_data().layer_one_head(), + ConsensusError::BadParentchainBlock( + parentchain_head.hash(), + "Invalid parentchain head".into(), + ) + ); + + let expected_author = slot_author::(*slot, authorities) + .ok_or_else(|| ConsensusError::CouldNotGetAuthorities("No authorities found".into()))?; + + ensure!( + expected_author == block.block_data().block_author(), + ConsensusError::InvalidAuthority(format!( + "Expected author: {}, author found in block: {}", + public_to_string(&expected_author.to_raw_vec()), + public_to_string(&block.block_data().block_author().to_raw_vec()) + )) + ); + + Ok(()) +} + +fn verify_block_ancestry( + block: &SidechainBlock, + last_block: &SidechainBlock, +) -> Result<(), ConsensusError> { + // These next two checks might seem redundant at first glance. However, they are distinct (see comments). + + // We have already imported this block. + ensure!( + block.header().block_number() > last_block.header().block_number(), + ConsensusError::BlockAlreadyImported( + block.header().block_number(), + last_block.header().block_number() + ) + ); + + // We are missing some blocks between our last known block and the one we're trying to import. + ensure!( + last_block.header().block_number() + 1 == block.header().block_number(), + ConsensusError::BlockAncestryMismatch( + last_block.header().block_number(), + last_block.hash(), + format!( + "Invalid block number, {} does not succeed {}", + block.header().block_number(), + last_block.header().block_number() + ) + ) + ); + + ensure!( + last_block.hash() == block.header().parent_hash(), + ConsensusError::BlockAncestryMismatch( + last_block.header().block_number(), + last_block.hash(), + "Parent hash does not match".into(), + ) + ); + + Ok(()) +} + +fn ensure_first_block( + block: &SidechainBlock, +) -> Result<(), ConsensusError> { + ensure!( + block.header().block_number() == 1, + ConsensusError::InvalidFirstBlock( + block.header().block_number(), + "No last block found, expecting first block. But block to import has number != 1" + .into() + ) + ); + ensure!( + block.header().parent_hash() == Default::default(), + ConsensusError::InvalidFirstBlock( + block.header().block_number(), + "No last block found, excepting first block. But block to import has parent_hash != 0" + .into() + ) + ); + + Ok(()) +} + +#[cfg(test)] +mod tests { + use super::*; + use core::assert_matches::assert_matches; + use frame_support::assert_ok; + use itc_parentchain_test::ParentchainHeaderBuilder; + use itp_types::{AccountId, Block as ParentchainBlock}; + use its_primitives::types::{block::SignedBlock, header::SidechainHeader as Header}; + use its_test::{ + sidechain_block_builder::{SidechainBlockBuilder, SidechainBlockBuilderTrait}, + sidechain_block_data_builder::SidechainBlockDataBuilder, + sidechain_header_builder::SidechainHeaderBuilder, + }; + use sp_core::{ed25519::Pair, ByteArray, H256}; + use sp_keyring::ed25519::Keyring; + + pub const SLOT_DURATION: Duration = Duration::from_millis(300); + + fn assert_ancestry_mismatch_err(result: Result) { + assert_matches!(result, Err(ConsensusError::BlockAncestryMismatch(_, _, _,))) + } + + fn block(signer: Keyring, header: Header) -> SignedBlock { + let parentchain_header = ParentchainHeaderBuilder::default().build(); + let block_data = SidechainBlockDataBuilder::default() + .with_signer(signer.pair()) + .with_timestamp(0) + .with_layer_one_head(parentchain_header.hash()) + .build(); + + SidechainBlockBuilder::default() + .with_header(header) + .with_block_data(block_data) + .with_signer(signer.pair()) + .build_signed() + } + + fn block1(signer: Keyring) -> SignedBlock { + let header = SidechainHeaderBuilder::default().with_block_number(1).build(); + + block(signer, header) + } + + fn block2(signer: Keyring, parent_hash: H256) -> SignedBlock { + let header = SidechainHeaderBuilder::default() + .with_parent_hash(parent_hash) + .with_block_number(2) + .build(); + + block(signer, header) + } + + fn block3(signer: Keyring, parent_hash: H256, block_number: u64) -> SignedBlock { + let header = SidechainHeaderBuilder::default() + .with_parent_hash(parent_hash) + .with_block_number(block_number) + .build(); + + block(signer, header) + } + + #[test] + fn ensure_first_block_works() { + let block = SidechainBlockBuilder::default().build(); + assert_ok!(ensure_first_block(&block)); + } + + #[test] + fn ensure_first_block_errs_with_invalid_block_number() { + let header = SidechainHeaderBuilder::default().with_block_number(2).build(); + let block = SidechainBlockBuilder::default().with_header(header).build(); + assert_matches!(ensure_first_block(&block), Err(ConsensusError::InvalidFirstBlock(2, _))) + } + + #[test] + fn ensure_first_block_errs_with_invalid_parent_hash() { + let parent = H256::random(); + let header = SidechainHeaderBuilder::default().with_parent_hash(parent).build(); + let block = SidechainBlockBuilder::default().with_header(header).build(); + + assert_matches!(ensure_first_block(&block), Err(ConsensusError::InvalidFirstBlock(_, _))); + } + + #[test] + fn verify_block_ancestry_works() { + let last_block = SidechainBlockBuilder::default().build(); + let header = SidechainHeaderBuilder::default() + .with_parent_hash(last_block.hash()) + .with_block_number(2) + .build(); + let curr_block = SidechainBlockBuilder::default().with_header(header).build(); + + assert_ok!(verify_block_ancestry(&curr_block, &last_block)); + } + + #[test] + fn verify_block_ancestry_errs_with_invalid_parent_block_number() { + let last_block = SidechainBlockBuilder::default().build(); + let header = SidechainHeaderBuilder::default() + .with_parent_hash(last_block.hash()) + .with_block_number(5) + .build(); + let curr_block = SidechainBlockBuilder::default().with_header(header).build(); + + assert_ancestry_mismatch_err(verify_block_ancestry(&curr_block, &last_block)); + } + + #[test] + fn verify_block_ancestry_errs_with_invalid_parent_hash() { + let last_block = SidechainBlockBuilder::default().build(); + let header = SidechainHeaderBuilder::default().with_block_number(2).build(); + let curr_block = SidechainBlockBuilder::default().with_header(header).build(); + + assert_ancestry_mismatch_err(verify_block_ancestry(&curr_block, &last_block)); + } + + #[test] + fn verify_works() { + let signer = Keyring::Alice; + let signer_account: AccountId = signer.public().into(); + let authorities = [AuthorityId::::from_slice(signer_account.as_ref()).unwrap()]; + + let parentchain_header = ParentchainHeaderBuilder::default().build(); + let last_block = SidechainBlockBuilder::default().build(); + let curr_block = block2(signer, last_block.hash()); + + assert_ok!(verify_sidechain_block::( + curr_block, + SLOT_DURATION, + &Some(last_block), + &parentchain_header, + &authorities, + )); + } + + #[test] + fn verify_works_for_first_block() { + let signer = Keyring::Alice; + let signer_account: AccountId = signer.public().into(); + let authorities = [AuthorityId::::from_slice(signer_account.as_ref()).unwrap()]; + + let parentchain_header = ParentchainHeaderBuilder::default().build(); + let curr_block = block1(signer); + + assert_ok!(verify_sidechain_block::( + curr_block, + SLOT_DURATION, + &None, + &parentchain_header, + &authorities, + )); + } + + #[test] + fn verify_errs_on_wrong_authority() { + let signer = Keyring::Alice; + let signer_account: AccountId = signer.public().into(); + let bob_account: AccountId = Keyring::Bob.public().into(); + let authorities = [ + AuthorityId::::from_slice(bob_account.as_ref()).unwrap(), + AuthorityId::::from_slice(signer_account.as_ref()).unwrap(), + ]; + + let parentchain_header = ParentchainHeaderBuilder::default().build(); + let last_block = SidechainBlockBuilder::default().build(); + let curr_block = block2(signer, last_block.hash()); + + assert_matches!( + verify_sidechain_block::( + curr_block, + SLOT_DURATION, + &Some(last_block), + &parentchain_header, + &authorities, + ) + .unwrap_err(), + ConsensusError::InvalidAuthority(_) + ); + } + + #[test] + fn verify_errs_on_invalid_ancestry() { + let signer = Keyring::Alice; + let signer_account: AccountId = signer.public().into(); + let authorities = [AuthorityId::::from_slice(signer_account.as_ref()).unwrap()]; + + let parentchain_header = ParentchainHeaderBuilder::default().build(); + let last_block = SidechainBlockBuilder::default().build(); + let curr_block = block2(signer, Default::default()); + + assert_ancestry_mismatch_err(verify_sidechain_block::( + curr_block, + SLOT_DURATION, + &Some(last_block), + &parentchain_header, + &authorities, + )); + } + + #[test] + fn verify_errs_on_wrong_first_block() { + let signer = Keyring::Alice; + let signer_account: AccountId = signer.public().into(); + let authorities = [AuthorityId::::from_slice(signer_account.as_ref()).unwrap()]; + + let parentchain_header = ParentchainHeaderBuilder::default().build(); + let curr_block = block2(signer, Default::default()); + + assert_matches!( + verify_sidechain_block::( + curr_block, + SLOT_DURATION, + &None, + &parentchain_header, + &authorities, + ) + .unwrap_err(), + ConsensusError::InvalidFirstBlock(2, _) + ); + } + + #[test] + fn verify_errs_on_already_imported_block() { + let signer = Keyring::Alice; + let signer_account: AccountId = signer.public().into(); + let authorities = [AuthorityId::::from_slice(signer_account.as_ref()).unwrap()]; + + let parentchain_header = ParentchainHeaderBuilder::default().build(); + let last_block = SidechainBlockBuilder::default().build(); + // Current block has also number 1, same as last. So import should return an error + // that a block with this number is already imported. + let curr_block = block3(signer, last_block.hash(), 1); + + assert_matches!( + verify_sidechain_block::( + curr_block, + SLOT_DURATION, + &Some(last_block), + &parentchain_header, + &authorities, + ) + .unwrap_err(), + ConsensusError::BlockAlreadyImported(1, 1) + ); + } + + #[test] + fn verify_block_already_imported_error_even_if_parentchain_block_mismatches() { + // This test is to ensure that we get a 'AlreadyImported' error, when the sidechain block + // is already imported, and the parentchain block that is passed into the verifier is newer. + // Important because client of the verifier acts differently for an 'AlreadyImported' error than an 'AncestryErrorMismatch'. + + let signer = Keyring::Alice; + let signer_account: AccountId = signer.public().into(); + let authorities = [AuthorityId::::from_slice(signer_account.as_ref()).unwrap()]; + + let parentchain_header_1 = ParentchainHeaderBuilder::default().with_number(1).build(); + let parentchain_header_2 = ParentchainHeaderBuilder::default().with_number(2).build(); + + let block_data = SidechainBlockDataBuilder::default() + .with_layer_one_head(parentchain_header_1.hash()) + .with_signer(signer.pair()) + .build(); + let last_block = SidechainBlockBuilder::default() + .with_block_data(block_data) + .with_signer(signer.pair()) + .build(); + + let block_data_for_signed_block = SidechainBlockDataBuilder::default() + .with_layer_one_head(parentchain_header_1.hash()) + .with_signer(signer.pair()) + .build(); + let signed_block_to_verify = SidechainBlockBuilder::default() + .with_block_data(block_data_for_signed_block) + .with_signer(signer.pair()) + .build_signed(); + + assert_matches!( + verify_sidechain_block::( + signed_block_to_verify, + SLOT_DURATION, + &Some(last_block), + &parentchain_header_2, + &authorities, + ) + .unwrap_err(), + ConsensusError::BlockAlreadyImported(1, 1) + ); + } +} diff --git a/bitacross-worker/sidechain/block-verification/src/slot.rs b/bitacross-worker/sidechain/block-verification/src/slot.rs new file mode 100644 index 0000000000..5eb2ede417 --- /dev/null +++ b/bitacross-worker/sidechain/block-verification/src/slot.rs @@ -0,0 +1,45 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::AuthorityId; +pub use sp_consensus_slots::Slot; +use sp_runtime::app_crypto::Pair; +use std::time::Duration; + +/// Get slot author for given block along with authorities. +pub fn slot_author(slot: Slot, authorities: &[AuthorityId

]) -> Option<&AuthorityId

> { + if authorities.is_empty() { + log::warn!("Authorities list is empty, cannot determine slot author"); + return None + } + + let idx = *slot % (authorities.len() as u64); + assert!( + idx <= usize::MAX as u64, + "It is impossible to have a vector with length beyond the address space; qed", + ); + + let current_author = authorities.get(idx as usize).expect( + "authorities not empty; index constrained to list length;this is a valid index; qed", + ); + + Some(current_author) +} + +pub fn slot_from_timestamp_and_duration(timestamp: Duration, duration: Duration) -> Slot { + ((timestamp.as_millis() / duration.as_millis()) as u64).into() +} diff --git a/bitacross-worker/sidechain/consensus/aura/Cargo.toml b/bitacross-worker/sidechain/consensus/aura/Cargo.toml new file mode 100644 index 0000000000..a7a52de35e --- /dev/null +++ b/bitacross-worker/sidechain/consensus/aura/Cargo.toml @@ -0,0 +1,105 @@ +[package] +name = "its-consensus-aura" +version = "0.9.0" +authors = ['Trust Computing GmbH ', 'Integritee AG '] +edition = "2021" + +[dependencies] +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive", "chain-error"] } +finality-grandpa = { version = "0.16.0", default-features = false, features = ["derive-codec"] } +log = { version = "0.4", default-features = false } + +# sgx deps +sgx_tstd = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git", optional = true } + +# substrate deps +sp-core = { default-features = false, features = ["full_crypto"], git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } +sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } + +# local deps +ita-stf = { path = "../../../app-libs/stf", default-features = false } +itc-parentchain-block-import-dispatcher = { path = "../../../core/parentchain/block-import-dispatcher", default-features = false } +itc-peer-top-broadcaster = { path = "../../../core/peer-top-broadcaster", default-features = false } +itp-enclave-metrics = { path = "../../../core-primitives/enclave-metrics", default-features = false } +itp-ocall-api = { path = "../../../core-primitives/ocall-api", default-features = false } +itp-settings = { path = "../../../core-primitives/settings" } +itp-sgx-crypto = { path = "../../../core-primitives/sgx/crypto", default-features = false } +itp-sgx-externalities = { path = "../../../core-primitives/substrate-sgx/externalities", default-features = false } +itp-stf-executor = { path = "../../../core-primitives/stf-executor", default-features = false } +itp-stf-primitives = { path = "../../../core-primitives/stf-primitives", default-features = false } +itp-stf-state-handler = { path = "../../../core-primitives/stf-state-handler", default-features = false } +itp-time-utils = { path = "../../../core-primitives/time-utils", default-features = false } +itp-top-pool-author = { path = "../../../core-primitives/top-pool-author", default-features = false } +itp-types = { path = "../../../core-primitives/types", default-features = false } +its-block-composer = { path = "../../block-composer", default-features = false } +its-block-verification = { path = "../../block-verification", optional = true, default-features = false } +its-consensus-common = { path = "../common", default-features = false } +its-consensus-slots = { path = "../slots", default-features = false } +its-primitives = { path = "../../primitives", default-features = false } +its-state = { path = "../../state", default-features = false } +its-validateer-fetch = { path = "../../validateer-fetch", default-features = false } + +# litentry +itp-utils = { path = "../../../core-primitives/utils", default-features = false } +lc-scheduled-enclave = { path = "../../../litentry/core/scheduled-enclave", default-features = false } + +[dev-dependencies] +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } +env_logger = "0.9.0" +itc-parentchain-block-import-dispatcher = { path = "../../../core/parentchain/block-import-dispatcher", features = ["mocks"] } +itc-parentchain-test = { path = "../../../core/parentchain/test" } +itp-storage = { path = "../../../core-primitives/storage" } +itp-test = { path = "../../../core-primitives/test" } +its-test = { path = "../../../sidechain/test" } +sp-keyring = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } + +[features] +default = ["std"] +std = [ + #crates.io + "codec/std", + "finality-grandpa/std", + "log/std", + #substrate + "sp-core/std", + "sp-runtime/std", + #local + "ita-stf/std", + "itc-parentchain-block-import-dispatcher/std", + "itc-peer-top-broadcaster/std", + "itp-enclave-metrics/std", + "itp-ocall-api/std", + "itp-sgx-crypto/std", + "itp-sgx-externalities/std", + "itp-stf-executor/std", + "itp-stf-primitives/std", + "itp-stf-state-handler/std", + "itp-time-utils/std", + "itp-types/std", + "its-block-composer/std", + "its-block-verification/std", + "its-consensus-common/std", + "its-consensus-slots/std", + "its-state/std", + "its-validateer-fetch/std", + "its-primitives/std", + "lc-scheduled-enclave/std", +] +sgx = [ + "sgx_tstd", + "ita-stf/sgx", + "itc-parentchain-block-import-dispatcher/sgx", + "itc-peer-top-broadcaster/sgx", + "itp-enclave-metrics/sgx", + "itp-sgx-crypto/sgx", + "itp-sgx-externalities/sgx", + "itp-stf-executor/sgx", + "itp-stf-state-handler/sgx", + "itp-time-utils/sgx", + "its-block-composer/sgx", + "its-consensus-common/sgx", + "its-consensus-slots/sgx", + "its-state/sgx", + "its-block-verification/sgx", + "lc-scheduled-enclave/sgx", +] diff --git a/bitacross-worker/sidechain/consensus/aura/src/block_importer.rs b/bitacross-worker/sidechain/consensus/aura/src/block_importer.rs new file mode 100644 index 0000000000..fb6f4e246a --- /dev/null +++ b/bitacross-worker/sidechain/consensus/aura/src/block_importer.rs @@ -0,0 +1,367 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 sidechain block importer struct. +//! Imports sidechain blocks and applies the accompanying state diff to its state. + +use codec::{Decode, Encode}; +use core::fmt::Debug; +// Reexport BlockImport trait which implements fn block_import() +use crate::{AuraVerifier, EnclaveOnChainOCallApi, SidechainBlockTrait}; +use itc_parentchain_block_import_dispatcher::triggered_dispatcher::TriggerParentchainBlockImport; +use itc_peer_top_broadcaster::PeerUpdater; +use itp_enclave_metrics::EnclaveMetric; +use itp_ocall_api::{EnclaveMetricsOCallApi, EnclaveSidechainOCallApi}; +use itp_settings::sidechain::SLOT_DURATION; +use itp_sgx_crypto::{key_repository::AccessKey, StateCrypto}; +use itp_sgx_externalities::SgxExternalities; +use itp_stf_primitives::{traits::TrustedCallVerification, types::TrustedOperationOrHash}; +use itp_stf_state_handler::handle_state::HandleState; +use itp_top_pool_author::traits::{AuthorApi, OnBlockImported}; +use itp_types::H256; +pub use its_consensus_common::BlockImport; +use its_consensus_common::Error as ConsensusError; +use its_primitives::traits::{ + BlockData, Header as HeaderTrait, ShardIdentifierFor, SignedBlock as SignedBlockTrait, +}; +use its_validateer_fetch::ValidateerFetch; +use log::*; +use sp_core::{crypto::UncheckedFrom, Pair}; +use sp_runtime::{ + generic::SignedBlock as SignedParentchainBlock, + traits::{Block as ParentchainBlockTrait, Header}, +}; +use std::{marker::PhantomData, sync::Arc}; + +/// Implements `BlockImport`. +#[derive(Clone)] +pub struct BlockImporter< + Authority, + ParentchainBlock, + SignedSidechainBlock, + OCallApi, + StateHandler, + StateKeyRepository, + TopPoolAuthor, + ParentchainBlockImporter, + PeersUpdater, + TCS, + G, +> { + state_handler: Arc, + state_key_repository: Arc, + top_pool_author: Arc, + parentchain_block_importer: Arc, + ocall_api: Arc, + peer_updater: Arc, + _phantom: PhantomData<(Authority, ParentchainBlock, SignedSidechainBlock, TCS, G)>, +} + +impl< + Authority, + ParentchainBlock, + SignedSidechainBlock, + OCallApi, + StateHandler, + StateKeyRepository, + TopPoolAuthor, + ParentchainBlockImporter, + PeersUpdater, + TCS, + G, + > + BlockImporter< + Authority, + ParentchainBlock, + SignedSidechainBlock, + OCallApi, + StateHandler, + StateKeyRepository, + TopPoolAuthor, + ParentchainBlockImporter, + PeersUpdater, + TCS, + G, + > where + Authority: Pair, + Authority::Public: std::fmt::Debug + UncheckedFrom<[u8; 32]>, + ParentchainBlock: ParentchainBlockTrait, + SignedSidechainBlock: SignedBlockTrait + 'static, + <::Block as SidechainBlockTrait>::HeaderType: + HeaderTrait, + OCallApi: EnclaveSidechainOCallApi + + ValidateerFetch + + EnclaveOnChainOCallApi + + EnclaveMetricsOCallApi + + Send + + Sync, + StateHandler: HandleState, + StateKeyRepository: AccessKey, + ::KeyType: StateCrypto, + TopPoolAuthor: AuthorApi + OnBlockImported, + ParentchainBlockImporter: TriggerParentchainBlockImport> + + Send + + Sync, + PeersUpdater: PeerUpdater, + TCS: PartialEq + Encode + Decode + Debug + Clone + Send + Sync + TrustedCallVerification, + G: PartialEq + Encode + Decode + Debug + Clone + Send + Sync, +{ + pub fn new( + state_handler: Arc, + state_key_repository: Arc, + top_pool_author: Arc, + parentchain_block_importer: Arc, + ocall_api: Arc, + peer_updater: Arc, + ) -> Self { + Self { + state_handler, + state_key_repository, + top_pool_author, + parentchain_block_importer, + ocall_api, + peer_updater, + _phantom: Default::default(), + } + } + + fn update_top_pool(&self, sidechain_block: &SignedSidechainBlock::Block) { + // Notify pool about imported block for status updates of the calls. + self.top_pool_author.on_block_imported( + sidechain_block.block_data().signed_top_hashes(), + sidechain_block.hash(), + ); + + // Remove calls from pool. + let executed_operations = sidechain_block + .block_data() + .signed_top_hashes() + .iter() + .map(|hash| (TrustedOperationOrHash::Hash(*hash), true)) + .collect(); + + let _calls_failed_to_remove = self + .top_pool_author + .remove_calls_from_pool(sidechain_block.header().shard_id(), executed_operations); + + // In case the executed call did not originate in our own TOP pool, we will not be able to remove it from our TOP pool. + // So this error will occur frequently, without it meaning that something really went wrong. + // TODO: Once the TOP pools are synchronized, we will want this check again! + // for call_failed_to_remove in _calls_failed_to_remove { + // error!("Could not remove call {:?} from top pool", call_failed_to_remove); + // } + } +} + +impl< + Authority, + ParentchainBlock, + SignedSidechainBlock, + OCallApi, + StateHandler, + StateKeyRepository, + TopPoolAuthor, + ParentchainBlockImporter, + PeersUpdater, + TCS, + G, + > BlockImport + for BlockImporter< + Authority, + ParentchainBlock, + SignedSidechainBlock, + OCallApi, + StateHandler, + StateKeyRepository, + TopPoolAuthor, + ParentchainBlockImporter, + PeersUpdater, + TCS, + G, + > where + Authority: Pair, + Authority::Public: std::fmt::Debug + UncheckedFrom<[u8; 32]>, + ParentchainBlock: ParentchainBlockTrait, + SignedSidechainBlock: SignedBlockTrait + 'static, + <::Block as SidechainBlockTrait>::HeaderType: + HeaderTrait, + OCallApi: EnclaveSidechainOCallApi + + ValidateerFetch + + EnclaveOnChainOCallApi + + EnclaveMetricsOCallApi + + Send + + Sync, + StateHandler: HandleState, + StateKeyRepository: AccessKey, + ::KeyType: StateCrypto, + TopPoolAuthor: AuthorApi + OnBlockImported, + ParentchainBlockImporter: TriggerParentchainBlockImport> + + Send + + Sync, + PeersUpdater: PeerUpdater, + TCS: PartialEq + Encode + Decode + Debug + Clone + Send + Sync + TrustedCallVerification, + G: PartialEq + Encode + Decode + Debug + Clone + Send + Sync, +{ + type Verifier = AuraVerifier; + type SidechainState = SgxExternalities; + type StateCrypto = ::KeyType; + type Context = OCallApi; + + fn verifier( + &self, + maybe_last_sidechain_block: Option, + ) -> Self::Verifier { + AuraVerifier::::new( + SLOT_DURATION, + maybe_last_sidechain_block, + ) + } + + fn apply_state_update( + &self, + shard: &ShardIdentifierFor, + mutating_function: F, + ) -> Result<(), ConsensusError> + where + F: FnOnce(Self::SidechainState) -> Result, + { + let (write_lock, state) = self + .state_handler + .load_for_mutation(shard) + .map_err(|e| ConsensusError::Other(format!("{:?}", e).into()))?; + + // We load a copy of the state and apply the update. In case the update fails, we don't write + // the state back to the state handler, and thus guaranteeing state integrity. + let updated_state = mutating_function(state)?; + + self.state_handler + .write_after_mutation(updated_state, write_lock, shard) + .map_err(|e| ConsensusError::Other(format!("{:?}", e).into()))?; + + Ok(()) + } + + fn verify_import( + &self, + shard: &ShardIdentifierFor, + verifying_function: F, + ) -> Result + where + F: FnOnce(&Self::SidechainState) -> Result, + { + self.state_handler + .execute_on_current(shard, |state, _| verifying_function(state)) + .map_err(|e| ConsensusError::Other(format!("{:?}", e).into()))? + } + + fn state_key(&self) -> Result { + self.state_key_repository + .retrieve_key() + .map_err(|e| ConsensusError::Other(format!("{:?}", e).into())) + } + + fn get_context(&self) -> &Self::Context { + &self.ocall_api + } + + fn import_parentchain_block( + &self, + sidechain_block: &SignedSidechainBlock::Block, + last_imported_parentchain_header: &ParentchainBlock::Header, + ) -> Result { + // get new peer list on each parentchain block import + if let Ok(peers) = self.ocall_api.get_trusted_peers_urls() { + self.peer_updater.update(peers); + } + + // We trigger the import of parentchain blocks up until the last one we've seen in the + // sidechain block that we're importing. This is done to prevent forks in the sidechain (#423) + let maybe_latest_imported_block = self + .parentchain_block_importer + .import_until(|signed_parentchain_block| { + signed_parentchain_block.block.hash() + == sidechain_block.block_data().layer_one_head() + }) + .map_err(|e| ConsensusError::Other(format!("{:?}", e).into()))?; + + Ok(maybe_latest_imported_block + .map(|b| b.block.header().clone()) + .unwrap_or_else(|| last_imported_parentchain_header.clone())) + } + + fn peek_parentchain_header( + &self, + sidechain_block: &SignedSidechainBlock::Block, + last_imported_parentchain_header: &ParentchainBlock::Header, + ) -> Result { + let last = last_imported_parentchain_header; + debug!("Peeking parentchain header"); + debug!( + "sidechain block parentchain head: {}", + sidechain_block.block_data().layer_one_head() + ); + debug!( + "last imported head: {}, number: {:?}, parenthash: {}", + last.hash(), + last.number(), + last.parent_hash() + ); + + let parentchain_header_hash_to_peek = sidechain_block.block_data().layer_one_head(); + if parentchain_header_hash_to_peek == last_imported_parentchain_header.hash() { + debug!("No queue peek necessary, sidechain block references latest imported parentchain block"); + return Ok(last_imported_parentchain_header.clone()) + } + + let maybe_signed_parentchain_block = self + .parentchain_block_importer + .peek(|parentchain_block| { + parentchain_block.block.header().hash() == parentchain_header_hash_to_peek + }) + .map_err(|e| ConsensusError::Other(format!("{:?}", e).into()))?; + + maybe_signed_parentchain_block + .map(|signed_block| signed_block.block.header().clone()) + .ok_or_else(|| { + ConsensusError::Other( + format!( + "Failed to find parentchain header in import queue (hash: {}) that is \ + associated with the current sidechain block that is to be imported (number: {}, hash: {})", + parentchain_header_hash_to_peek, + sidechain_block.header().block_number(), + sidechain_block.hash() + ) + .into(), + ) + }) + } + + fn cleanup(&self, signed_sidechain_block: &SignedSidechainBlock) -> Result<(), ConsensusError> { + let sidechain_block = signed_sidechain_block.block(); + + // Remove all successfully applied trusted calls from the top pool. + self.update_top_pool(sidechain_block); + + // Send metric about sidechain block height (i.e. block number) + let block_height_metric = + EnclaveMetric::SetSidechainBlockHeight(sidechain_block.header().block_number()); + if let Err(e) = self.ocall_api.update_metric(block_height_metric) { + warn!("Failed to update sidechain block height metric: {:?}", e); + } + + Ok(()) + } +} diff --git a/bitacross-worker/sidechain/consensus/aura/src/lib.rs b/bitacross-worker/sidechain/consensus/aura/src/lib.rs new file mode 100644 index 0000000000..193eb0501c --- /dev/null +++ b/bitacross-worker/sidechain/consensus/aura/src/lib.rs @@ -0,0 +1,773 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 worker for the sidechain. +//! +//! It is inspired by parity's implementation but has been greatly amended. + +#![cfg_attr(not(feature = "std"), no_std)] +#![cfg_attr(test, feature(assert_matches))] + +#[cfg(all(feature = "std", feature = "sgx"))] +compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the same time"); + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +#[macro_use] +extern crate sgx_tstd as std; + +use codec::Encode; +use core::marker::PhantomData; +use itc_parentchain_block_import_dispatcher::triggered_dispatcher::TriggerParentchainBlockImport; +use itp_ocall_api::EnclaveOnChainOCallApi; +use itp_sgx_externalities::SgxExternalities; +use itp_stf_state_handler::handle_state::HandleState; +use itp_time_utils::duration_now; + +use itp_utils::hex::hex_encode; +use its_block_verification::slot::slot_author; +use its_consensus_common::{Environment, Error as ConsensusError, Proposer}; +use its_consensus_slots::{SimpleSlotWorker, Slot, SlotInfo}; +use its_primitives::{ + traits::{Block as SidechainBlockTrait, Header as HeaderTrait, SignedBlock}, + types::block::BlockHash, +}; +use its_validateer_fetch::ValidateerFetch; +use lc_scheduled_enclave::ScheduledEnclaveUpdater; +use sp_core::ByteArray; +use sp_runtime::{ + app_crypto::{sp_core::H256, Pair}, + generic::SignedBlock as SignedParentchainBlock, + traits::{Block as ParentchainBlockTrait, Header as ParentchainHeaderTrait}, +}; +use std::{string::ToString, sync::Arc, time::Duration, vec::Vec}; + +pub mod block_importer; +pub mod proposer_factory; +pub mod slot_proposer; +mod verifier; + +pub use verifier::*; + +#[cfg(test)] +mod test; + +/// Aura consensus struct. +pub struct Aura< + AuthorityPair, + ParentchainBlock, + SidechainBlock, + Environment, + OcallApi, + IntegriteeImportTrigger, + TargetAImportTrigger, + TargetBImportTrigger, + ScheduledEnclave, + StateHandler, +> { + authority_pair: AuthorityPair, + ocall_api: OcallApi, + parentchain_integritee_import_trigger: Arc, + maybe_parentchain_target_a_import_trigger: Option>, + maybe_parentchain_target_b_import_trigger: Option>, + environment: Environment, + claim_strategy: SlotClaimStrategy, + scheduled_enclave: Arc, + state_handler: Arc, + _phantom: PhantomData<(AuthorityPair, ParentchainBlock, SidechainBlock)>, +} + +impl< + AuthorityPair, + ParentchainBlock, + SidechainBlock, + Environment, + OcallApi, + IntegriteeImportTrigger, + TargetAImportTrigger, + TargetBImportTrigger, + ScheduledEnclave, + StateHandler, + > + Aura< + AuthorityPair, + ParentchainBlock, + SidechainBlock, + Environment, + OcallApi, + IntegriteeImportTrigger, + TargetAImportTrigger, + TargetBImportTrigger, + ScheduledEnclave, + StateHandler, + > +{ + #[allow(clippy::too_many_arguments)] + pub fn new( + authority_pair: AuthorityPair, + ocall_api: OcallApi, + parentchain_integritee_import_trigger: Arc, + maybe_parentchain_target_a_import_trigger: Option>, + maybe_parentchain_target_b_import_trigger: Option>, + environment: Environment, + scheduled_enclave: Arc, + state_handler: Arc, + ) -> Self { + Self { + authority_pair, + ocall_api, + parentchain_integritee_import_trigger, + maybe_parentchain_target_a_import_trigger, + maybe_parentchain_target_b_import_trigger, + environment, + claim_strategy: SlotClaimStrategy::RoundRobin, + scheduled_enclave, + state_handler, + _phantom: Default::default(), + } + } + + pub fn with_claim_strategy(mut self, claim_strategy: SlotClaimStrategy) -> Self { + self.claim_strategy = claim_strategy; + + self + } +} + +/// The fraction of total block time we are allowed to be producing the block. So that we have +/// enough time send create and send the block to fellow validateers. +pub const BLOCK_PROPOSAL_SLOT_PORTION: f32 = 0.7; + +#[derive(PartialEq, Eq, Debug)] +pub enum SlotClaimStrategy { + /// try to produce a block always even if it's not the authors slot + /// Intended for first phase to see if aura production works + Always, + /// Proper Aura strategy: Only produce blocks, when it's the authors slot. + RoundRobin, +} + +type AuthorityId

=

::Public; +type ShardIdentifierFor = + <<::Block as SidechainBlockTrait>::HeaderType as HeaderTrait>::ShardIdentifier; + +impl< + AuthorityPair, + ParentchainBlock, + SignedSidechainBlock, + E, + OcallApi, + IntegriteeImportTrigger, + TargetAImportTrigger, + TargetBImportTrigger, + ScheduledEnclave, + StateHandler, + > SimpleSlotWorker + for Aura< + AuthorityPair, + ParentchainBlock, + SignedSidechainBlock, + E, + OcallApi, + IntegriteeImportTrigger, + TargetAImportTrigger, + TargetBImportTrigger, + ScheduledEnclave, + StateHandler, + > where + AuthorityPair: Pair, + // todo: Relax hash trait bound, but this needs a change to some other parts in the code. + ParentchainBlock: ParentchainBlockTrait, + E: Environment, + E::Proposer: Proposer, + SignedSidechainBlock: SignedBlock + Send + 'static, + OcallApi: ValidateerFetch + EnclaveOnChainOCallApi + Send + 'static, + IntegriteeImportTrigger: + TriggerParentchainBlockImport>, + TargetAImportTrigger: + TriggerParentchainBlockImport>, + TargetBImportTrigger: + TriggerParentchainBlockImport>, + ScheduledEnclave: ScheduledEnclaveUpdater, + StateHandler: HandleState, +{ + type Proposer = E::Proposer; + type Claim = AuthorityPair::Public; + type EpochData = Vec>; + type Output = SignedSidechainBlock; + type ScheduledEnclave = ScheduledEnclave; + type StateHandler = StateHandler; + + fn logging_target(&self) -> &'static str { + "aura" + } + + fn get_scheduled_enclave(&mut self) -> Arc { + self.scheduled_enclave.clone() + } + + fn get_state_handler(&mut self) -> Arc { + self.state_handler.clone() + } + + fn epoch_data( + &self, + header: &ParentchainBlock::Header, + _shard: ShardIdentifierFor, + _slot: Slot, + ) -> Result { + authorities::<_, AuthorityPair, ParentchainBlock::Header>(&self.ocall_api, header) + } + + fn authorities_len(&self, epoch_data: &Self::EpochData) -> Option { + Some(epoch_data.len()) + } + + // While the header is not used in aura, it is used in different consensus systems, so it should be left there. + fn claim_slot( + &self, + _header: &ParentchainBlock::Header, + slot: Slot, + epoch_data: &Self::EpochData, + ) -> Option { + let expected_author = slot_author::(slot, epoch_data)?; + + if expected_author == &self.authority_pair.public() { + log::info!(target: self.logging_target(), "Claiming slot ({})", *slot); + return Some(self.authority_pair.public()) + } + + if self.claim_strategy == SlotClaimStrategy::Always { + log::debug!( + target: self.logging_target(), + "Not our slot but we still claim it." + ); + return Some(self.authority_pair.public()) + } + + None + } + + fn proposer( + &mut self, + header: ParentchainBlock::Header, + shard: ShardIdentifierFor, + ) -> Result { + self.environment.init(header, shard) + } + + fn proposing_remaining_duration(&self, slot_info: &SlotInfo) -> Duration { + proposing_remaining_duration(slot_info, duration_now()) + } + + // Design remark: the following may seem too explicit and it certainly could be abstracted. + // however, as pretty soon we may not want to assume same Block types for all parentchains, + // it may make sense to abstract once we do that. + + fn import_integritee_parentchain_blocks_until( + &self, + parentchain_header_hash: &::Hash, + ) -> Result, ConsensusError> { + log::trace!(target: self.logging_target(), "import Integritee blocks until {}", hex_encode(parentchain_header_hash.encode().as_ref())); + let maybe_parentchain_block = self + .parentchain_integritee_import_trigger + .import_until(|parentchain_block| { + parentchain_block.block.hash() == *parentchain_header_hash + }) + .map_err(|e| ConsensusError::Other(e.into()))?; + + Ok(maybe_parentchain_block.map(|b| b.block.header().clone())) + } + + fn import_target_a_parentchain_blocks_until( + &self, + parentchain_header_hash: &::Hash, + ) -> Result, ConsensusError> { + log::trace!(target: self.logging_target(), "import TargetA blocks until {}", hex_encode(parentchain_header_hash.encode().as_ref())); + let maybe_parentchain_block = self + .maybe_parentchain_target_a_import_trigger + .clone() + .ok_or_else(|| ConsensusError::Other("no target_a assigned".into()))? + .import_until(|parentchain_block| { + parentchain_block.block.hash() == *parentchain_header_hash + }) + .map_err(|e| ConsensusError::Other(e.into()))?; + + Ok(maybe_parentchain_block.map(|b| b.block.header().clone())) + } + + fn import_target_b_parentchain_blocks_until( + &self, + parentchain_header_hash: &::Hash, + ) -> Result, ConsensusError> { + log::trace!(target: self.logging_target(), "import TargetB blocks until {}", hex_encode(parentchain_header_hash.encode().as_ref())); + let maybe_parentchain_block = self + .maybe_parentchain_target_b_import_trigger + .clone() + .ok_or_else(|| ConsensusError::Other("no target_b assigned".into()))? + .import_until(|parentchain_block| { + parentchain_block.block.hash() == *parentchain_header_hash + }) + .map_err(|e| ConsensusError::Other(e.into()))?; + + Ok(maybe_parentchain_block.map(|b| b.block.header().clone())) + } + + fn peek_latest_integritee_parentchain_header( + &self, + ) -> Result, ConsensusError> { + let maybe_parentchain_block = self + .parentchain_integritee_import_trigger + .peek_latest() + .map_err(|e| ConsensusError::Other(format!("{:?}", e).into()))?; + + Ok(maybe_parentchain_block.map(|b| b.block.header().clone())) + } + + fn peek_latest_target_a_parentchain_header( + &self, + ) -> Result, ConsensusError> { + let maybe_parentchain_block = self + .maybe_parentchain_target_a_import_trigger + .clone() + .ok_or_else(|| ConsensusError::Other("no target_a assigned".into()))? + .peek_latest() + .map_err(|e| ConsensusError::Other(format!("{:?}", e).into()))?; + + Ok(maybe_parentchain_block.map(|b| b.block.header().clone())) + } + + fn peek_latest_target_b_parentchain_header( + &self, + ) -> Result, ConsensusError> { + let maybe_parentchain_block = self + .maybe_parentchain_target_b_import_trigger + .clone() + .ok_or_else(|| ConsensusError::Other("no target_b assigned".into()))? + .peek_latest() + .map_err(|e| ConsensusError::Other(format!("{:?}", e).into()))?; + + Ok(maybe_parentchain_block.map(|b| b.block.header().clone())) + } +} + +/// unit-testable remaining duration fn. +fn proposing_remaining_duration( + slot_info: &SlotInfo, + now: Duration, +) -> Duration { + // if a `now` before slot begin is passed such that `slot_remaining` would be bigger than `slot.slot_duration` + // we take the total `slot_duration` as reference value. + let proposing_duration = slot_info.duration.mul_f32(BLOCK_PROPOSAL_SLOT_PORTION); + + let slot_remaining = slot_info + .ends_at + .checked_sub(now) + .map(|remaining| remaining.mul_f32(BLOCK_PROPOSAL_SLOT_PORTION)) + .unwrap_or_default(); + + std::cmp::min(slot_remaining, proposing_duration) +} + +fn authorities( + ocall_api: &ValidateerFetcher, + header: &ParentchainHeader, +) -> Result>, ConsensusError> +where + ValidateerFetcher: ValidateerFetch + EnclaveOnChainOCallApi, + P: Pair, + ParentchainHeader: ParentchainHeaderTrait, +{ + Ok(ocall_api + .current_validateers(header) + .map_err(|e| ConsensusError::CouldNotGetAuthorities(e.to_string()))? + .into_iter() + .filter_map(|e| AuthorityId::

::from_slice(e.pubkey.as_ref()).ok()) + .collect()) +} + +pub enum AnyImportTrigger { + Integritee(Integritee), + TargetA(TargetA), + TargetB(TargetB), +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::test::{ + fixtures::{types::TestAura, validateer, SLOT_DURATION}, + mocks::environment_mock::{EnvironmentMock, OutdatedBlockEnvironmentMock}, + }; + use itc_parentchain_block_import_dispatcher::trigger_parentchain_block_import_mock::TriggerParentchainBlockImportMock; + use itc_parentchain_test::{ParentchainBlockBuilder, ParentchainHeaderBuilder}; + use itp_test::mock::{handle_state_mock::HandleStateMock, onchain_mock::OnchainMock}; + use itp_types::{ + Block as ParentchainBlock, Enclave, Header as ParentchainHeader, ShardIdentifier, + SignedBlock as SignedParentchainBlock, + }; + use its_consensus_slots::PerShardSlotWorkerScheduler; + use lc_scheduled_enclave::ScheduledEnclaveMock; + use sp_core::ed25519::Public; + use sp_keyring::ed25519::Keyring; + + fn get_aura( + onchain_mock: OnchainMock, + trigger_parentchain_import: Arc>, + ) -> TestAura { + Aura::new( + Keyring::Alice.pair(), + onchain_mock, + trigger_parentchain_import, + None, + None, + EnvironmentMock, + Arc::new(ScheduledEnclaveMock::default()), + Arc::new(HandleStateMock::from_shard(ShardIdentifier::default()).unwrap()), + ) + } + + fn get_aura_outdated( + onchain_mock: OnchainMock, + trigger_parentchain_import: Arc>, + ) -> TestAura { + Aura::new( + Keyring::Alice.pair(), + onchain_mock, + trigger_parentchain_import, + None, + None, + OutdatedBlockEnvironmentMock, + Arc::new(ScheduledEnclaveMock::default()), + Arc::new(HandleStateMock::from_shard(ShardIdentifier::default()).unwrap()), + ) + } + + fn get_default_aura() -> TestAura { + get_aura(Default::default(), Default::default()) + } + + fn now_slot(slot: Slot, header: &ParentchainHeader) -> SlotInfo { + let now = duration_now(); + SlotInfo { + slot, + timestamp: now, + duration: SLOT_DURATION, + ends_at: now + SLOT_DURATION, + last_imported_integritee_parentchain_head: header.clone(), + maybe_last_imported_target_a_parentchain_head: None, + maybe_last_imported_target_b_parentchain_head: None, + } + } + + fn now_slot_with_default_header(slot: Slot) -> SlotInfo { + now_slot(slot, &ParentchainHeaderBuilder::default().build()) + } + + fn default_authorities() -> Vec { + vec![Keyring::Alice.public(), Keyring::Bob.public(), Keyring::Charlie.public()] + } + + fn create_validateer_set_from_publics(authorities: Vec) -> Vec { + authorities.iter().map(|a| validateer(a.clone().into())).collect() + } + + fn onchain_mock( + parentchain_header: &ParentchainHeader, + authorities: Vec, + ) -> OnchainMock { + let validateers = create_validateer_set_from_publics(authorities); + OnchainMock::default().add_validateer_set(parentchain_header, Some(validateers)) + } + + fn onchain_mock_with_default_authorities_and_header() -> OnchainMock { + let parentchain_header = ParentchainHeaderBuilder::default().build(); + onchain_mock(&parentchain_header, default_authorities()) + } + + fn create_import_trigger_with_header( + header: ParentchainHeader, + ) -> Arc> { + let latest_parentchain_block = + ParentchainBlockBuilder::default().with_header(header).build_signed(); + Arc::new( + TriggerParentchainBlockImportMock::default() + .with_latest_imported(Some(latest_parentchain_block)), + ) + } + + #[test] + fn current_authority_should_claim_its_slot() { + let authorities = + vec![Keyring::Bob.public(), Keyring::Charlie.public(), Keyring::Alice.public()]; + let aura = get_default_aura(); + let header = ParentchainHeaderBuilder::default().build(); + + assert!(aura.claim_slot(&header, 0.into(), &authorities).is_none()); + assert!(aura.claim_slot(&header, 1.into(), &authorities).is_none()); + // this our authority + assert!(aura.claim_slot(&header, 2.into(), &authorities).is_some()); + + assert!(aura.claim_slot(&header, 3.into(), &authorities).is_none()); + assert!(aura.claim_slot(&header, 4.into(), &authorities).is_none()); + // this our authority + assert!(aura.claim_slot(&header, 5.into(), &authorities).is_some()); + } + + #[test] + fn current_authority_should_claim_all_slots() { + let header = ParentchainHeaderBuilder::default().build(); + let authorities = default_authorities(); + let aura = get_default_aura().with_claim_strategy(SlotClaimStrategy::Always); + + assert!(aura.claim_slot(&header, 0.into(), &authorities).is_some()); + assert!(aura.claim_slot(&header, 1.into(), &authorities).is_some()); + // this our authority + assert!(aura.claim_slot(&header, 2.into(), &authorities).is_some()); + assert!(aura.claim_slot(&header, 3.into(), &authorities).is_some()); + } + + #[test] + fn on_slot_returns_block() { + let _ = env_logger::builder().is_test(true).try_init(); + + let onchain_mock = onchain_mock_with_default_authorities_and_header(); + let mut aura = get_aura(onchain_mock, Default::default()); + + let slot_info = now_slot_with_default_header(0.into()); + + assert!( + SimpleSlotWorker::on_slot(&mut aura, slot_info, Default::default(), false).is_some() + ); + } + + #[test] + fn on_slot_returns_no_block_if_slot_time_exceeded_for_multi_worker() { + let _ = env_logger::builder().is_test(true).try_init(); + + let onchain_mock = onchain_mock_with_default_authorities_and_header(); + let mut aura = get_aura_outdated(onchain_mock, Default::default()); + let slot_info = now_slot_with_default_header(0.into()); + + assert!( + SimpleSlotWorker::on_slot(&mut aura, slot_info, Default::default(), false).is_none() + ); + } + + #[test] + fn on_slot_returns_block_if_slot_time_exceeded_for_single_worker() { + let _ = env_logger::builder().is_test(true).try_init(); + + let onchain_mock = onchain_mock_with_default_authorities_and_header(); + let mut aura = get_aura_outdated(onchain_mock, Default::default()); + let slot_info = now_slot_with_default_header(0.into()); + + assert!(SimpleSlotWorker::on_slot(&mut aura, slot_info, Default::default(), true).is_some()); + } + + #[test] + fn on_slot_for_multiple_shards_returns_blocks() { + let _ = env_logger::builder().is_test(true).try_init(); + + let onchain_mock = onchain_mock_with_default_authorities_and_header(); + let mut aura = get_aura(onchain_mock, Default::default()); + + let slot_info = now_slot_with_default_header(0.into()); + + let result = PerShardSlotWorkerScheduler::on_slot( + &mut aura, + slot_info, + vec![Default::default(), Default::default()], + false, + ); + + assert_eq!(result.len(), 2); + } + + #[test] + fn on_slot_with_nano_second_remaining_duration_does_not_panic() { + let _ = env_logger::builder().is_test(true).try_init(); + + let mut aura = get_default_aura(); + + let nano_dur = Duration::from_nanos(999); + let now = duration_now(); + + let slot_info = SlotInfo { + slot: 0.into(), + timestamp: now, + duration: nano_dur, + ends_at: now + nano_dur, + last_imported_integritee_parentchain_head: ParentchainHeaderBuilder::default().build(), + maybe_last_imported_target_a_parentchain_head: None, + maybe_last_imported_target_b_parentchain_head: None, + }; + + let result = PerShardSlotWorkerScheduler::on_slot( + &mut aura, + slot_info, + vec![Default::default(), Default::default()], + false, + ); + + assert_eq!(result.len(), 0); + } + + #[test] + fn on_slot_triggers_parentchain_block_import_if_slot_is_claimed() { + let _ = env_logger::builder().is_test(true).try_init(); + let latest_parentchain_header = ParentchainHeaderBuilder::default().with_number(84).build(); + let parentchain_block_import_trigger = + create_import_trigger_with_header(latest_parentchain_header.clone()); + let authorities = default_authorities(); + + let mut aura = get_aura( + onchain_mock(&latest_parentchain_header, authorities), + parentchain_block_import_trigger.clone(), + ); + + let slot_info = now_slot(0.into(), &latest_parentchain_header); + + let result = + SimpleSlotWorker::on_slot(&mut aura, slot_info, Default::default(), false).unwrap(); + + assert_eq!( + result.block.block.block_data().layer_one_head, + latest_parentchain_header.hash() + ); + assert!(parentchain_block_import_trigger.has_import_been_called()); + } + + #[test] + fn on_slot_does_not_trigger_parentchain_block_import_if_slot_is_not_claimed() { + let _ = env_logger::builder().is_test(true).try_init(); + let latest_parentchain_header = ParentchainHeaderBuilder::default().with_number(84).build(); + let parentchain_block_import_trigger = + create_import_trigger_with_header(latest_parentchain_header.clone()); + let authorities = default_authorities(); + + let mut aura = get_aura( + onchain_mock(&latest_parentchain_header, authorities), + parentchain_block_import_trigger.clone(), + ); + + let slot_info = now_slot(2.into(), &latest_parentchain_header); + + let result = SimpleSlotWorker::on_slot(&mut aura, slot_info, Default::default(), false); + + assert!(result.is_none()); + assert!(!parentchain_block_import_trigger.has_import_been_called()); + } + + #[test] + fn on_slot_claims_slot_if_latest_parentchain_header_in_queue_contains_correspondent_validateer_set( + ) { + let _ = env_logger::builder().is_test(true).try_init(); + let already_imported_parentchain_header = + ParentchainHeaderBuilder::default().with_number(84).build(); + let latest_parentchain_header = ParentchainHeaderBuilder::default().with_number(85).build(); + let parentchain_block_import_trigger = + create_import_trigger_with_header(latest_parentchain_header.clone()); + let validateer_set_one = create_validateer_set_from_publics(vec![ + Keyring::Alice.public(), + Keyring::Bob.public(), + ]); + let validateer_set_two = create_validateer_set_from_publics(vec![ + Keyring::Alice.public(), + Keyring::Bob.public(), + Keyring::Charlie.public(), + ]); + let onchain_mock = OnchainMock::default() + .add_validateer_set(&already_imported_parentchain_header, Some(validateer_set_one)) + .add_validateer_set(&latest_parentchain_header, Some(validateer_set_two)); + + let mut aura = get_aura(onchain_mock, parentchain_block_import_trigger.clone()); + + let slot_info = now_slot(3.into(), &already_imported_parentchain_header); + + let result = + SimpleSlotWorker::on_slot(&mut aura, slot_info, Default::default(), false).unwrap(); + + assert_eq!( + result.block.block.block_data().layer_one_head, + latest_parentchain_header.hash() + ); + assert!(parentchain_block_import_trigger.has_import_been_called()); + } + + #[test] + fn on_slot_does_not_claim_slot_if_latest_parentchain_header_in_queue_contains_correspondent_validateer_set( + ) { + let _ = env_logger::builder().is_test(true).try_init(); + let already_imported_parentchain_header = + ParentchainHeaderBuilder::default().with_number(84).build(); + let latest_parentchain_header = ParentchainHeaderBuilder::default().with_number(85).build(); + let parentchain_block_import_trigger = + create_import_trigger_with_header(latest_parentchain_header.clone()); + let validateer_set_one = create_validateer_set_from_publics(vec![ + Keyring::Alice.public(), + Keyring::Bob.public(), + ]); + let validateer_set_two = create_validateer_set_from_publics(vec![ + Keyring::Alice.public(), + Keyring::Bob.public(), + Keyring::Charlie.public(), + ]); + let onchain_mock = OnchainMock::default() + .add_validateer_set(&already_imported_parentchain_header, Some(validateer_set_one)) + .add_validateer_set(&latest_parentchain_header, Some(validateer_set_two)); + + let mut aura = get_aura(onchain_mock, parentchain_block_import_trigger.clone()); + + // If the validateer set one (instead of the latest one) is looked up, the slot will be claimed. But it should not, as the latest one should be used. + let slot_info = now_slot(2.into(), &already_imported_parentchain_header); + let result = SimpleSlotWorker::on_slot(&mut aura, slot_info, Default::default(), false); + + assert!(result.is_none()); + assert!(!parentchain_block_import_trigger.has_import_been_called()); + } + + #[test] + fn proposing_remaining_duration_works() { + let slot_info = now_slot_with_default_header(0.into()); + + // hard to compare actual numbers but we can at least ensure that the general concept works + assert!( + proposing_remaining_duration(&slot_info, duration_now()) + < SLOT_DURATION.mul_f32(BLOCK_PROPOSAL_SLOT_PORTION + 0.01) + ); + } + + #[test] + fn proposing_remaining_duration_works_for_now_before_slot_timestamp() { + let slot_info = now_slot_with_default_header(0.into()); + + assert!( + proposing_remaining_duration(&slot_info, Duration::from_millis(0)) + < SLOT_DURATION.mul_f32(BLOCK_PROPOSAL_SLOT_PORTION + 0.01) + ); + } + + #[test] + fn proposing_remaining_duration_returns_default_if_now_after_slot() { + let slot_info = now_slot_with_default_header(0.into()); + + assert_eq!( + proposing_remaining_duration(&slot_info, duration_now() + SLOT_DURATION), + Default::default() + ); + } +} diff --git a/bitacross-worker/sidechain/consensus/aura/src/proposer_factory.rs b/bitacross-worker/sidechain/consensus/aura/src/proposer_factory.rs new file mode 100644 index 0000000000..61fa21557f --- /dev/null +++ b/bitacross-worker/sidechain/consensus/aura/src/proposer_factory.rs @@ -0,0 +1,131 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::slot_proposer::{ExternalitiesFor, SlotProposer}; +use codec::Encode; +use finality_grandpa::BlockNumberOps; +use ita_stf::{Getter, TrustedCallSigned}; +use itp_ocall_api::EnclaveMetricsOCallApi; +use itp_sgx_externalities::{SgxExternalitiesTrait, StateHash}; +use itp_stf_executor::traits::StateUpdateProposer; +use itp_top_pool_author::traits::AuthorApi; +use itp_types::H256; +use its_block_composer::ComposeBlock; +use its_consensus_common::{Environment, Error as ConsensusError}; +use its_primitives::traits::{ + Block as SidechainBlockTrait, Header as HeaderTrait, ShardIdentifierFor, + SignedBlock as SignedSidechainBlockTrait, +}; +use its_state::{SidechainState, SidechainSystemExt}; +use sp_runtime::{ + traits::{Block, NumberFor}, + MultiSignature, +}; +use std::{marker::PhantomData, sync::Arc}; + +///! `ProposerFactory` instance containing all the data to create the `SlotProposer` for the +/// next `Slot`. +pub struct ProposerFactory< + ParentchainBlock: Block, + TopPoolAuthor, + StfExecutor, + BlockComposer, + MetricsApi, +> { + top_pool_author: Arc, + stf_executor: Arc, + block_composer: Arc, + metrics_api: Arc, + _phantom: PhantomData, +} + +impl + ProposerFactory +{ + pub fn new( + top_pool_executor: Arc, + stf_executor: Arc, + block_composer: Arc, + metrics_api: Arc, + ) -> Self { + Self { + top_pool_author: top_pool_executor, + stf_executor, + block_composer, + metrics_api, + _phantom: Default::default(), + } + } +} + +impl< + ParentchainBlock: Block, + SignedSidechainBlock, + TopPoolAuthor, + StfExecutor, + BlockComposer, + MetricsApi, + > Environment + for ProposerFactory +where + NumberFor: BlockNumberOps, + SignedSidechainBlock: SignedSidechainBlockTrait + + 'static, + SignedSidechainBlock::Block: SidechainBlockTrait, + <::Block as SidechainBlockTrait>::HeaderType: + HeaderTrait, + TopPoolAuthor: + AuthorApi + Send + Sync + 'static, + StfExecutor: StateUpdateProposer + Send + Sync + 'static, + ExternalitiesFor: + SgxExternalitiesTrait + SidechainState + SidechainSystemExt + StateHash, + as SgxExternalitiesTrait>::SgxExternalitiesType: Encode, + BlockComposer: ComposeBlock< + ExternalitiesFor, + ParentchainBlock, + SignedSidechainBlock = SignedSidechainBlock, + > + Send + + Sync + + 'static, + MetricsApi: EnclaveMetricsOCallApi, +{ + type Proposer = SlotProposer< + ParentchainBlock, + SignedSidechainBlock, + TopPoolAuthor, + StfExecutor, + BlockComposer, + MetricsApi, + >; + type Error = ConsensusError; + + fn init( + &mut self, + parent_header: ParentchainBlock::Header, + shard: ShardIdentifierFor, + ) -> Result { + Ok(SlotProposer { + top_pool_author: self.top_pool_author.clone(), + stf_executor: self.stf_executor.clone(), + block_composer: self.block_composer.clone(), + parentchain_header: parent_header, + shard, + metrics_api: self.metrics_api.clone(), + _phantom: PhantomData, + }) + } +} diff --git a/bitacross-worker/sidechain/consensus/aura/src/slot_proposer.rs b/bitacross-worker/sidechain/consensus/aura/src/slot_proposer.rs new file mode 100644 index 0000000000..2baea76519 --- /dev/null +++ b/bitacross-worker/sidechain/consensus/aura/src/slot_proposer.rs @@ -0,0 +1,206 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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; +use finality_grandpa::BlockNumberOps; +use ita_stf::{Getter, TrustedCallSigned}; +use itp_enclave_metrics::EnclaveMetric; +use itp_ocall_api::EnclaveMetricsOCallApi; +use itp_sgx_externalities::{SgxExternalitiesTrait, StateHash}; +use itp_stf_executor::traits::StateUpdateProposer; +use itp_time_utils::now_as_millis; +use itp_top_pool_author::traits::AuthorApi; +use itp_types::H256; +use its_block_composer::ComposeBlock; +use its_consensus_common::{Error as ConsensusError, Proposal, Proposer}; +use its_primitives::traits::{ + Block as SidechainBlockTrait, Header as HeaderTrait, ShardIdentifierFor, + SignedBlock as SignedSidechainBlockTrait, +}; +use its_state::{SidechainState, SidechainSystemExt}; +use log::*; +use sp_runtime::{ + traits::{Block, NumberFor}, + MultiSignature, +}; +use std::{marker::PhantomData, string::ToString, sync::Arc, time::Duration, vec::Vec}; + +pub type ExternalitiesFor = >::Externalities; +///! `SlotProposer` instance that has access to everything needed to propose a sidechain block. +pub struct SlotProposer< + ParentchainBlock: Block, + SignedSidechainBlock: SignedSidechainBlockTrait, + TopPoolAuthor, + StfExecutor, + BlockComposer, + MetricsApi, +> { + pub(crate) top_pool_author: Arc, + pub(crate) stf_executor: Arc, + pub(crate) block_composer: Arc, + pub(crate) parentchain_header: ParentchainBlock::Header, + pub(crate) shard: ShardIdentifierFor, + pub(crate) metrics_api: Arc, + pub(crate) _phantom: PhantomData, +} + +impl< + ParentchainBlock, + SignedSidechainBlock, + TopPoolAuthor, + BlockComposer, + StfExecutor, + MetricsApi, + > Proposer + for SlotProposer< + ParentchainBlock, + SignedSidechainBlock, + TopPoolAuthor, + StfExecutor, + BlockComposer, + MetricsApi, + > where + ParentchainBlock: Block, + NumberFor: BlockNumberOps, + SignedSidechainBlock: SignedSidechainBlockTrait + + 'static, + SignedSidechainBlock::Block: SidechainBlockTrait, + <::Block as SidechainBlockTrait>::HeaderType: + HeaderTrait, + StfExecutor: StateUpdateProposer, + ExternalitiesFor: + SgxExternalitiesTrait + SidechainState + SidechainSystemExt + StateHash, + as SgxExternalitiesTrait>::SgxExternalitiesType: Encode, + TopPoolAuthor: + AuthorApi + Send + Sync + 'static, + BlockComposer: ComposeBlock< + ExternalitiesFor, + ParentchainBlock, + SignedSidechainBlock = SignedSidechainBlock, + > + Send + + Sync + + 'static, + MetricsApi: EnclaveMetricsOCallApi, +{ + /// Proposes a new sidechain block. + /// + /// This includes the following steps: + /// 1) Retrieve all trusted calls from the top pool. + /// 2) Calculate a new state that will be proposed in the sidechain block. + /// 3) Compose the sidechain block and the parentchain confirmation. + fn propose( + &self, + max_duration: Duration, + ) -> Result, ConsensusError> { + let mut started = std::time::Instant::now(); + let latest_parentchain_header = &self.parentchain_header; + + // 1) Retrieve trusted calls from top pool. + let trusted_calls = self.top_pool_author.get_pending_trusted_calls(self.shard); + + if !trusted_calls.is_empty() { + debug!("Got following trusted calls from pool: {:?}", trusted_calls); + } + + if let Err(e) = self + .metrics_api + .update_metric(EnclaveMetric::SidechainSlotPrepareTime(started.elapsed())) + { + warn!("Failed to update metric for sidechain slot prepare time: {:?}", e); + }; + + started = std::time::Instant::now(); + // 2) Execute trusted calls. + let batch_execution_result = self + .stf_executor + .propose_state_update( + &trusted_calls, + latest_parentchain_header, + &self.shard, + max_duration, + |mut sidechain_db| { + sidechain_db.reset_events(); + sidechain_db + .set_block_number(&sidechain_db.get_block_number().map_or(1, |n| n + 1)); + sidechain_db.set_timestamp(&now_as_millis()); + sidechain_db.set_parentchain_block_number(latest_parentchain_header); + sidechain_db + }, + ) + .map_err(|e| ConsensusError::Other(e.to_string().into()))?; + + let parentchain_extrinsics = batch_execution_result.get_extrinsic_callbacks(); + + let executed_operation_hashes: Vec<_> = + batch_execution_result.get_executed_operation_hashes().to_vec(); + let number_executed_transactions = executed_operation_hashes.len(); + + // store the rpc response value to top pool + let rpc_responses_values = batch_execution_result.get_connection_updates(); + self.top_pool_author.update_connection_state(rpc_responses_values); + + // Remove all not successfully executed operations from the top pool. + let failed_operations = batch_execution_result.get_failed_operations(); + self.top_pool_author.remove_calls_from_pool( + self.shard, + failed_operations + .into_iter() + .map(|e| { + let is_success = e.is_success(); + (e.trusted_operation_or_hash, is_success) + }) + .collect(), + ); + + if let Err(e) = self + .metrics_api + .update_metric(EnclaveMetric::SidechainSlotStfExecutionTime(started.elapsed())) + { + warn!("Failed to update metric for sidechain slot stf execution time: {:?}", e); + }; + + started = std::time::Instant::now(); + + // 3) Compose sidechain block. + let sidechain_block = self + .block_composer + .compose_block( + latest_parentchain_header, + executed_operation_hashes, + self.shard, + batch_execution_result.state_hash_before_execution, + &batch_execution_result.state_after_execution, + ) + .map_err(|e| ConsensusError::Other(e.to_string().into()))?; + + if let Err(e) = self + .metrics_api + .update_metric(EnclaveMetric::SidechainSlotBlockCompositionTime(started.elapsed())) + { + warn!("Failed to update metric for sidechain slot block composition time: {:?}", e); + }; + + info!( + "Queue/Timeslot/Transactions: {:?};{}ms;{}", + trusted_calls.len(), + max_duration.as_millis(), + number_executed_transactions + ); + + Ok(Proposal { block: sidechain_block, parentchain_effects: parentchain_extrinsics }) + } +} diff --git a/bitacross-worker/sidechain/consensus/aura/src/test/block_importer_tests.rs b/bitacross-worker/sidechain/consensus/aura/src/test/block_importer_tests.rs new file mode 100644 index 0000000000..447aa18c62 --- /dev/null +++ b/bitacross-worker/sidechain/consensus/aura/src/test/block_importer_tests.rs @@ -0,0 +1,318 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{ + block_importer::BlockImporter, + test::{fixtures::validateer, mocks::peer_updater_mock::PeerUpdaterMock}, + ShardIdentifierFor, +}; +use codec::Encode; +use core::assert_matches::assert_matches; +use itc_parentchain_block_import_dispatcher::trigger_parentchain_block_import_mock::TriggerParentchainBlockImportMock; +use itc_parentchain_test::{ParentchainBlockBuilder, ParentchainHeaderBuilder}; +use itp_sgx_crypto::{aes::Aes, mocks::KeyRepositoryMock, StateCrypto}; +use itp_sgx_externalities::SgxExternalitiesDiffType; +use itp_stf_state_handler::handle_state::HandleState; +use itp_test::mock::{ + handle_state_mock::HandleStateMock, + onchain_mock::OnchainMock, + stf_mock::{GetterMock, TrustedCallSignedMock}, +}; +use itp_time_utils::{duration_now, now_as_millis}; +use itp_top_pool_author::mocks::AuthorApiMock; +use itp_types::{Block as ParentchainBlock, Header as ParentchainHeader, H256}; +use its_consensus_common::{BlockImport, Error as ConsensusError}; +use its_primitives::{ + traits::{SignBlock, SignedBlock}, + types::SignedBlock as SignedSidechainBlock, +}; +use its_state::StateUpdate; +use its_test::{ + sidechain_block_builder::{SidechainBlockBuilder, SidechainBlockBuilderTrait}, + sidechain_block_data_builder::SidechainBlockDataBuilder, + sidechain_header_builder::SidechainHeaderBuilder, +}; +use sp_core::{blake2_256, ed25519::Pair}; +use sp_keyring::ed25519::Keyring; +use sp_runtime::generic::SignedBlock as SignedParentchainBlock; +use std::sync::Arc; + +type TestTopPoolAuthor = AuthorApiMock; +type TestParentchainBlockImportTrigger = + TriggerParentchainBlockImportMock>; +type TestStateKeyRepo = KeyRepositoryMock; +type TestBlockImporter = BlockImporter< + Pair, + ParentchainBlock, + SignedSidechainBlock, + OnchainMock, + HandleStateMock, + TestStateKeyRepo, + TestTopPoolAuthor, + TestParentchainBlockImportTrigger, + PeerUpdaterMock, + TrustedCallSignedMock, + GetterMock, +>; + +fn state_key() -> Aes { + Aes::new([3u8; 16], [0u8; 16]) +} + +fn shard() -> ShardIdentifierFor { + blake2_256(&[1, 2, 3, 4, 5, 6]).into() +} + +fn default_authority() -> Pair { + Keyring::Alice.pair() +} + +fn test_fixtures( + parentchain_header: &ParentchainHeader, + parentchain_block_import_trigger: Arc, +) -> (TestBlockImporter, Arc, Arc) { + let state_handler = Arc::new(HandleStateMock::from_shard(shard()).unwrap()); + let top_pool_author = Arc::new(TestTopPoolAuthor::default()); + let ocall_api = Arc::new(OnchainMock::default().add_validateer_set( + parentchain_header, + Some(vec![validateer(Keyring::Alice.public().into())]), + )); + let state_key_repository = Arc::new(TestStateKeyRepo::new(state_key())); + + let peer_updater_mock = Arc::new(PeerUpdaterMock {}); + + let block_importer = TestBlockImporter::new( + state_handler.clone(), + state_key_repository, + top_pool_author.clone(), + parentchain_block_import_trigger, + ocall_api, + peer_updater_mock, + ); + + (block_importer, state_handler, top_pool_author) +} + +fn test_fixtures_with_default_import_trigger( + parentchain_header: &ParentchainHeader, +) -> (TestBlockImporter, Arc, Arc) { + test_fixtures(parentchain_header, Arc::new(TestParentchainBlockImportTrigger::default())) +} + +fn empty_encrypted_state_update(state_handler: &HandleStateMock) -> Vec { + let (_, apriori_state_hash) = state_handler.load_cloned(&shard()).unwrap(); + let empty_state_diff = SgxExternalitiesDiffType::default(); + let mut state_update = + StateUpdate::new(apriori_state_hash, apriori_state_hash, empty_state_diff).encode(); + state_key().encrypt(&mut state_update).unwrap(); + state_update +} + +fn signed_block( + parentchain_header: &ParentchainHeader, + state_handler: &HandleStateMock, + signer: Pair, +) -> SignedSidechainBlock { + let state_update = empty_encrypted_state_update(state_handler); + + let header = SidechainHeaderBuilder::default() + .with_parent_hash(H256::default()) + .with_shard(shard()) + .build(); + + let block_data = SidechainBlockDataBuilder::default() + .with_timestamp(now_as_millis()) + .with_layer_one_head(parentchain_header.hash()) + .with_signer(signer.clone()) + .with_payload(state_update) + .build(); + + SidechainBlockBuilder::default() + .with_header(header) + .with_block_data(block_data) + .with_signer(signer) + .build_signed() +} + +fn default_authority_signed_block( + parentchain_header: &ParentchainHeader, + state_handler: &HandleStateMock, +) -> SignedSidechainBlock { + signed_block(parentchain_header, state_handler, default_authority()) +} + +#[test] +fn simple_block_import_works() { + let parentchain_header = ParentchainHeaderBuilder::default().build(); + let (block_importer, state_handler, _) = + test_fixtures_with_default_import_trigger(&parentchain_header); + let signed_sidechain_block = + default_authority_signed_block(&parentchain_header, state_handler.as_ref()); + + block_importer + .import_block(signed_sidechain_block, &parentchain_header) + .unwrap(); +} + +#[test] +fn block_import_with_invalid_signature_fails() { + let parentchain_header = ParentchainHeaderBuilder::default().build(); + let (block_importer, state_handler, _) = + test_fixtures_with_default_import_trigger(&parentchain_header); + + let state_update = empty_encrypted_state_update(state_handler.as_ref()); + + let header = SidechainHeaderBuilder::default() + .with_parent_hash(H256::default()) + .with_shard(shard()) + .build(); + + let block_data = SidechainBlockDataBuilder::default() + .with_timestamp(duration_now().as_millis() as u64) + .with_layer_one_head(parentchain_header.hash()) + .with_signer(Keyring::Charlie.pair()) + .with_payload(state_update) + .build(); + + let block = SidechainBlockBuilder::default() + .with_signer(Keyring::Charlie.pair()) + .with_header(header) + .with_block_data(block_data) + .build(); + + // Bob signs the block, but Charlie is set as the author -> invalid signature. + let invalid_signature_block: SignedSidechainBlock = block.sign_block(&Keyring::Bob.pair()); + + assert!(!invalid_signature_block.verify_signature()); + assert!(block_importer + .import_block(invalid_signature_block, &parentchain_header) + .is_err()); +} + +#[test] +fn block_import_with_invalid_parentchain_block_fails() { + let parentchain_header_invalid = ParentchainHeaderBuilder::default().with_number(2).build(); + let parentchain_header = ParentchainHeaderBuilder::default().with_number(10).build(); + let (block_importer, state_handler, _) = + test_fixtures_with_default_import_trigger(&parentchain_header); + + let signed_sidechain_block = + default_authority_signed_block(&parentchain_header_invalid, state_handler.as_ref()); + + assert!(block_importer + .import_block(signed_sidechain_block, &parentchain_header) + .is_err()); +} + +#[test] +fn cleanup_removes_tops_from_pool() { + let parentchain_header = ParentchainHeaderBuilder::default().build(); + let (block_importer, state_handler, top_pool_author) = + test_fixtures_with_default_import_trigger(&parentchain_header); + let signed_sidechain_block = + default_authority_signed_block(&parentchain_header, state_handler.as_ref()); + let bob_signed_sidechain_block = + signed_block(&parentchain_header, state_handler.as_ref(), Keyring::Bob.pair()); + + block_importer.cleanup(&signed_sidechain_block).unwrap(); + block_importer.cleanup(&bob_signed_sidechain_block).unwrap(); + + assert_eq!(2, *top_pool_author.remove_attempts.read().unwrap()); +} + +#[test] +fn sidechain_block_import_triggers_parentchain_block_import() { + let previous_parentchain_header = ParentchainHeaderBuilder::default().with_number(4).build(); + let latest_parentchain_header = ParentchainHeaderBuilder::default() + .with_number(5) + .with_parent_hash(previous_parentchain_header.hash()) + .build(); + + let latest_parentchain_block = ParentchainBlockBuilder::default() + .with_header(latest_parentchain_header.clone()) + .build_signed(); + + let parentchain_block_import_trigger = Arc::new( + TestParentchainBlockImportTrigger::default() + .with_latest_imported(Some(latest_parentchain_block)), + ); + let (block_importer, state_handler, _) = + test_fixtures(&latest_parentchain_header, parentchain_block_import_trigger.clone()); + + let signed_sidechain_block = + default_authority_signed_block(&latest_parentchain_header, state_handler.as_ref()); + + block_importer + .import_block(signed_sidechain_block, &previous_parentchain_header) + .unwrap(); + + assert!(parentchain_block_import_trigger.has_import_been_called()); +} + +#[test] +fn peek_parentchain_block_finds_block_in_queue() { + let previous_parentchain_header = ParentchainHeaderBuilder::default().with_number(4).build(); + let latest_parentchain_header = ParentchainHeaderBuilder::default() + .with_number(5) + .with_parent_hash(previous_parentchain_header.hash()) + .build(); + + let latest_parentchain_block = ParentchainBlockBuilder::default() + .with_header(latest_parentchain_header.clone()) + .build_signed(); + + let parentchain_block_import_trigger = Arc::new( + TestParentchainBlockImportTrigger::default() + .with_latest_imported(Some(latest_parentchain_block)), + ); + + let (block_importer, state_handler, _) = + test_fixtures(&latest_parentchain_header, parentchain_block_import_trigger); + + let signed_sidechain_block = + default_authority_signed_block(&latest_parentchain_header, state_handler.as_ref()); + + let peeked_header = block_importer + .peek_parentchain_header(&signed_sidechain_block.block, &previous_parentchain_header) + .unwrap(); + + assert_eq!(peeked_header, latest_parentchain_header); +} + +#[test] +fn peek_parentchain_block_returns_error_if_no_corresponding_block_can_be_found() { + let previous_parentchain_header = ParentchainHeaderBuilder::default().with_number(1).build(); + let latest_parentchain_header = ParentchainHeaderBuilder::default() + .with_number(2) + .with_parent_hash(previous_parentchain_header.hash()) + .build(); + + let parentchain_block_import_trigger = Arc::new( + TestParentchainBlockImportTrigger::default(), // Parentchain block import queue is empty, so nothing will be found when peeked. + ); + + let (block_importer, state_handler, _) = + test_fixtures(&latest_parentchain_header, parentchain_block_import_trigger); + + let signed_sidechain_block = + default_authority_signed_block(&latest_parentchain_header, state_handler.as_ref()); + + let peek_result = block_importer + .peek_parentchain_header(&signed_sidechain_block.block, &previous_parentchain_header); + + assert_matches!(peek_result, Err(ConsensusError::Other(_))); +} diff --git a/bitacross-worker/sidechain/consensus/aura/src/test/fixtures/mod.rs b/bitacross-worker/sidechain/consensus/aura/src/test/fixtures/mod.rs new file mode 100644 index 0000000000..54d47324fa --- /dev/null +++ b/bitacross-worker/sidechain/consensus/aura/src/test/fixtures/mod.rs @@ -0,0 +1,27 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 types; + +use itp_types::{AccountId, Enclave}; +use std::time::Duration; + +pub const SLOT_DURATION: Duration = Duration::from_millis(300); + +pub fn validateer(account: AccountId) -> Enclave { + Enclave::new(account, Default::default(), Default::default(), Default::default()) +} diff --git a/bitacross-worker/sidechain/consensus/aura/src/test/fixtures/types.rs b/bitacross-worker/sidechain/consensus/aura/src/test/fixtures/types.rs new file mode 100644 index 0000000000..b5eae68582 --- /dev/null +++ b/bitacross-worker/sidechain/consensus/aura/src/test/fixtures/types.rs @@ -0,0 +1,48 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{test::mocks::environment_mock::EnvironmentMock, Aura}; +use itc_parentchain_block_import_dispatcher::trigger_parentchain_block_import_mock::TriggerParentchainBlockImportMock; +use itp_test::mock::{handle_state_mock::HandleStateMock, onchain_mock::OnchainMock}; +use itp_types::Block as ParentchainBlock; +use its_primitives::{ + traits::{ + Block as SidechainBlockTrait, Header as SidechainHeaderTrait, + SignedBlock as SignedBlockTrait, + }, + types::block::SignedBlock as SignedSidechainBlock, +}; +use lc_scheduled_enclave::ScheduledEnclaveMock; +use sp_runtime::{app_crypto::ed25519, generic::SignedBlock}; + +type AuthorityPair = ed25519::Pair; + +pub type ShardIdentifierFor = + <<::Block as SidechainBlockTrait>::HeaderType as SidechainHeaderTrait>::ShardIdentifier; + +pub type TestAura = Aura< + AuthorityPair, + ParentchainBlock, + SignedSidechainBlock, + E, + OnchainMock, + TriggerParentchainBlockImportMock>, + TriggerParentchainBlockImportMock>, + TriggerParentchainBlockImportMock>, + ScheduledEnclaveMock, + HandleStateMock, +>; diff --git a/bitacross-worker/sidechain/consensus/aura/src/test/mocks/environment_mock.rs b/bitacross-worker/sidechain/consensus/aura/src/test/mocks/environment_mock.rs new file mode 100644 index 0000000000..58f98d3687 --- /dev/null +++ b/bitacross-worker/sidechain/consensus/aura/src/test/mocks/environment_mock.rs @@ -0,0 +1,58 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{ + test::{ + fixtures::types::ShardIdentifierFor, + mocks::proposer_mock::{DefaultProposerMock, OutdatedBlockProposerMock}, + }, + ConsensusError, +}; +use itp_types::{Block as ParentchainBlock, Header}; +use its_consensus_common::Environment; +use its_primitives::types::block::SignedBlock as SignedSidechainBlock; + +/// Mock proposer environment. +pub struct EnvironmentMock; + +impl Environment for EnvironmentMock { + type Proposer = DefaultProposerMock; + type Error = ConsensusError; + + fn init( + &mut self, + header: Header, + _: ShardIdentifierFor, + ) -> Result { + Ok(DefaultProposerMock { parentchain_header: header }) + } +} + +pub struct OutdatedBlockEnvironmentMock; + +impl Environment for OutdatedBlockEnvironmentMock { + type Proposer = OutdatedBlockProposerMock; + type Error = ConsensusError; + + fn init( + &mut self, + header: Header, + _: ShardIdentifierFor, + ) -> Result { + Ok(OutdatedBlockProposerMock { parentchain_header: header }) + } +} diff --git a/bitacross-worker/sidechain/consensus/aura/src/test/mocks/mod.rs b/bitacross-worker/sidechain/consensus/aura/src/test/mocks/mod.rs new file mode 100644 index 0000000000..f5c7248d2f --- /dev/null +++ b/bitacross-worker/sidechain/consensus/aura/src/test/mocks/mod.rs @@ -0,0 +1,20 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 environment_mock; +pub mod peer_updater_mock; +pub mod proposer_mock; diff --git a/bitacross-worker/sidechain/consensus/aura/src/test/mocks/peer_updater_mock.rs b/bitacross-worker/sidechain/consensus/aura/src/test/mocks/peer_updater_mock.rs new file mode 100644 index 0000000000..b474e825c1 --- /dev/null +++ b/bitacross-worker/sidechain/consensus/aura/src/test/mocks/peer_updater_mock.rs @@ -0,0 +1,7 @@ +use itc_peer_top_broadcaster::PeerUpdater; + +pub struct PeerUpdaterMock {} + +impl PeerUpdater for PeerUpdaterMock { + fn update(&self, _peers: Vec) {} +} diff --git a/bitacross-worker/sidechain/consensus/aura/src/test/mocks/proposer_mock.rs b/bitacross-worker/sidechain/consensus/aura/src/test/mocks/proposer_mock.rs new file mode 100644 index 0000000000..00f78298c3 --- /dev/null +++ b/bitacross-worker/sidechain/consensus/aura/src/test/mocks/proposer_mock.rs @@ -0,0 +1,73 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::ConsensusError; +use itp_time_utils::now_as_millis; +use itp_types::{Block as ParentchainBlock, Header}; +use its_consensus_common::{Proposal, Proposer}; +use its_primitives::types::block::SignedBlock as SignedSidechainBlock; +use its_test::{ + sidechain_block_builder::{SidechainBlockBuilder, SidechainBlockBuilderTrait}, + sidechain_block_data_builder::SidechainBlockDataBuilder, +}; +use std::time::Duration; + +pub struct DefaultProposerMock { + pub(crate) parentchain_header: Header, +} + +impl Proposer for DefaultProposerMock { + fn propose( + &self, + _max_duration: Duration, + ) -> Result, ConsensusError> { + Ok(Proposal { + block: { + let block_data = SidechainBlockDataBuilder::random() + .with_layer_one_head(self.parentchain_header.hash()) + .build(); + SidechainBlockBuilder::random().with_block_data(block_data).build_signed() + }, + + parentchain_effects: Default::default(), + }) + } +} + +pub struct OutdatedBlockProposerMock { + pub(crate) parentchain_header: Header, +} + +impl Proposer for OutdatedBlockProposerMock { + fn propose( + &self, + _max_duration: Duration, + ) -> Result, ConsensusError> { + let past = now_as_millis() - 1000; + Ok(Proposal { + block: { + let block_data = SidechainBlockDataBuilder::random() + .with_layer_one_head(self.parentchain_header.hash()) + .with_timestamp(past) + .build(); + SidechainBlockBuilder::random().with_block_data(block_data).build_signed() + }, + + parentchain_effects: Default::default(), + }) + } +} diff --git a/bitacross-worker/sidechain/consensus/aura/src/test/mod.rs b/bitacross-worker/sidechain/consensus/aura/src/test/mod.rs new file mode 100644 index 0000000000..7c40ba019d --- /dev/null +++ b/bitacross-worker/sidechain/consensus/aura/src/test/mod.rs @@ -0,0 +1,20 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 block_importer_tests; +pub mod fixtures; +pub mod mocks; diff --git a/bitacross-worker/sidechain/consensus/aura/src/verifier.rs b/bitacross-worker/sidechain/consensus/aura/src/verifier.rs new file mode 100644 index 0000000000..0c1f64b138 --- /dev/null +++ b/bitacross-worker/sidechain/consensus/aura/src/verifier.rs @@ -0,0 +1,89 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{authorities, EnclaveOnChainOCallApi, ShardIdentifierFor}; +use core::marker::PhantomData; +use its_block_verification::verify_sidechain_block; +use its_consensus_common::{Error as ConsensusError, Verifier}; +use its_primitives::{ + traits::{Block as SidechainBlockTrait, SignedBlock as SignedSidechainBlockTrait}, + types::block::BlockHash, +}; +use its_validateer_fetch::ValidateerFetch; +use sp_runtime::{app_crypto::Pair, traits::Block as ParentchainBlockTrait}; +use std::{fmt::Debug, time::Duration}; + +#[derive(Default)] +pub struct AuraVerifier +where + SignedSidechainBlock: SignedSidechainBlockTrait + 'static, + SignedSidechainBlock::Block: SidechainBlockTrait, +{ + slot_duration: Duration, + last_sidechain_block: Option, + _phantom: PhantomData<(AuthorityPair, ParentchainBlock, Context)>, +} + +impl + AuraVerifier +where + SignedSidechainBlock: SignedSidechainBlockTrait + 'static, + SignedSidechainBlock::Block: SidechainBlockTrait, +{ + pub fn new( + slot_duration: Duration, + last_sidechain_block: Option, + ) -> Self { + Self { slot_duration, last_sidechain_block, _phantom: Default::default() } + } +} + +impl + Verifier + for AuraVerifier +where + AuthorityPair: Pair, + AuthorityPair::Public: Debug, + // todo: Relax hash trait bound, but this needs a change to some other parts in the code. + ParentchainBlock: ParentchainBlockTrait, + SignedSidechainBlock: SignedSidechainBlockTrait + 'static, + SignedSidechainBlock::Block: SidechainBlockTrait, + Context: ValidateerFetch + EnclaveOnChainOCallApi + Send + Sync, +{ + type BlockImportParams = SignedSidechainBlock; + + type Context = Context; + + fn verify( + &self, + signed_block: SignedSidechainBlock, + parentchain_header: &ParentchainBlock::Header, + _shard: ShardIdentifierFor, + ctx: &Self::Context, + ) -> Result { + let authorities = + authorities::<_, AuthorityPair, ParentchainBlock::Header>(ctx, parentchain_header)?; + + Ok(verify_sidechain_block::( + signed_block, + self.slot_duration, + &self.last_sidechain_block, + parentchain_header, + &authorities, + )?) + } +} diff --git a/bitacross-worker/sidechain/consensus/common/Cargo.toml b/bitacross-worker/sidechain/consensus/common/Cargo.toml new file mode 100644 index 0000000000..6408dd9c08 --- /dev/null +++ b/bitacross-worker/sidechain/consensus/common/Cargo.toml @@ -0,0 +1,85 @@ +[package] +name = "its-consensus-common" +version = "0.9.0" +authors = ['Trust Computing GmbH ', 'Integritee AG '] +edition = "2021" + +[dependencies] +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false } +log = { version = "0.4", default-features = false } +thiserror = { version = "1.0.26", optional = true } + +# local deps +itc-parentchain-light-client = { path = "../../../core/parentchain/light-client", default-features = false } +itp-enclave-metrics = { path = "../../../core-primitives/enclave-metrics", default-features = false } +itp-extrinsics-factory = { path = "../../../core-primitives/extrinsics-factory", default-features = false } +itp-import-queue = { path = "../../../core-primitives/import-queue", default-features = false } +itp-node-api-metadata = { path = "../../../core-primitives/node-api/metadata", default-features = false } +itp-node-api-metadata-provider = { path = "../../../core-primitives/node-api/metadata-provider", default-features = false } +itp-ocall-api = { path = "../../../core-primitives/ocall-api", default-features = false } +itp-settings = { path = "../../../core-primitives/settings" } +itp-sgx-crypto = { path = "../../../core-primitives/sgx/crypto", default-features = false } +itp-types = { path = "../../../core-primitives/types", default-features = false } +its-block-verification = { path = "../../block-verification", optional = true, default-features = false } +its-primitives = { path = "../../primitives", default-features = false } +its-state = { path = "../../state", default-features = false } + +# sgx deps +sgx_tstd = { optional = true, git = "https://github.com/apache/teaclave-sgx-sdk.git", branch = "master" } +sgx_types = { git = "https://github.com/apache/teaclave-sgx-sdk.git", branch = "master" } +thiserror-sgx = { package = "thiserror", optional = true, git = "https://github.com/mesalock-linux/thiserror-sgx", tag = "sgx_1.1.3" } + +# substrate deps +sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } + +[dev-dependencies] +# local +itc-parentchain-test = { path = "../../../core/parentchain/test" } +itp-sgx-externalities = { default-features = false, path = "../../../core-primitives/substrate-sgx/externalities" } +itp-test = { path = "../../../core-primitives/test" } +its-test = { path = "../../test" } +fork-tree = { path = "../../fork-tree", default-features = false } + +# substrate +sp-core = { default-features = false, features = ["full_crypto"], git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } + +[features] +default = ["std"] +std = [ + "codec/std", + "log/std", + "thiserror", + # local + "itc-parentchain-light-client/std", + "itp-import-queue/std", + "itp-enclave-metrics/std", + "itp-extrinsics-factory/std", + "itp-node-api-metadata/std", + "itp-node-api-metadata-provider/std", + "itp-ocall-api/std", + "itp-sgx-crypto/std", + "itp-sgx-externalities/std", + "itp-types/std", + "its-primitives/std", + "its-block-verification/std", + "its-state/std", + "fork-tree/std", + # substrate + "sp-runtime/std", +] +sgx = [ + "sgx_tstd", + "thiserror-sgx", + # local + "itc-parentchain-light-client/sgx", + "itp-import-queue/sgx", + "itp-enclave-metrics/sgx", + "itp-extrinsics-factory/sgx", + "itp-node-api-metadata-provider/sgx", + "itp-sgx-crypto/sgx", + "itp-sgx-externalities/sgx", + "its-state/sgx", + "fork-tree/sgx", + # scs + "its-block-verification/sgx", +] diff --git a/bitacross-worker/sidechain/consensus/common/src/block_import.rs b/bitacross-worker/sidechain/consensus/common/src/block_import.rs new file mode 100644 index 0000000000..826b1e456b --- /dev/null +++ b/bitacross-worker/sidechain/consensus/common/src/block_import.rs @@ -0,0 +1,201 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +//! Abstraction around block import + +use crate::{Error, Verifier}; +use codec::Decode; +use itp_enclave_metrics::EnclaveMetric; +use itp_ocall_api::{EnclaveMetricsOCallApi, EnclaveSidechainOCallApi}; +use itp_sgx_crypto::StateCrypto; +use its_primitives::traits::{ + Block as SidechainBlockTrait, BlockData, Header as HeaderTrait, ShardIdentifierFor, + SignedBlock as SignedSidechainBlockTrait, +}; +use its_state::{LastBlockExt, SidechainState}; +use log::*; +use sp_runtime::traits::Block as ParentchainBlockTrait; +use std::{time::Instant, vec::Vec}; + +pub trait BlockImport +where + ParentchainBlock: ParentchainBlockTrait, + SignedSidechainBlock: SignedSidechainBlockTrait, +{ + /// The verifier for of the respective consensus instance. + type Verifier: Verifier< + ParentchainBlock, + SignedSidechainBlock, + BlockImportParams = SignedSidechainBlock, + Context = Self::Context, + >; + + /// Context needed to derive verifier relevant data. + type SidechainState: SidechainState + LastBlockExt; + + /// Provides the cryptographic functions for our the state encryption. + type StateCrypto: StateCrypto; + + /// Context needed to derive verifier relevant data. + type Context: EnclaveSidechainOCallApi + EnclaveMetricsOCallApi; + + /// Get a verifier instance. + fn verifier( + &self, + maybe_last_sidechain_block: Option, + ) -> Self::Verifier; + + /// Apply a state update by providing a mutating function. + fn apply_state_update( + &self, + shard: &ShardIdentifierFor, + mutating_function: F, + ) -> Result<(), Error> + where + F: FnOnce(Self::SidechainState) -> Result; + + /// Verify a sidechain block that is to be imported. + fn verify_import( + &self, + shard: &ShardIdentifierFor, + verifying_function: F, + ) -> Result + where + F: FnOnce(&Self::SidechainState) -> Result; + + /// Key that is used for state encryption. + fn state_key(&self) -> Result; + + /// Getter for the context. + fn get_context(&self) -> &Self::Context; + + /// Import parentchain blocks up to and including the one we see in the sidechain block that + /// is scheduled for import. + /// + /// Returns the latest header. If no block was imported with the trigger, + /// we return `last_imported_parentchain_header`. + fn import_parentchain_block( + &self, + sidechain_block: &SignedSidechainBlock::Block, + last_imported_parentchain_header: &ParentchainBlock::Header, + ) -> Result; + + /// Peek the parentchain import queue for the block that is associated with a given sidechain. + /// Does not perform the import or mutate the queue. + /// + /// Warning: Be aware that peeking the parentchain block means that it is not verified (that happens upon import). + fn peek_parentchain_header( + &self, + sidechain_block: &SignedSidechainBlock::Block, + last_imported_parentchain_header: &ParentchainBlock::Header, + ) -> Result; + /// Cleanup task after import is done. + fn cleanup(&self, signed_sidechain_block: &SignedSidechainBlock) -> Result<(), Error>; + + /// Import a sidechain block and mutate state by `apply_state_update`. + fn import_block( + &self, + signed_sidechain_block: SignedSidechainBlock, + parentchain_header: &ParentchainBlock::Header, + ) -> Result { + let start_time = Instant::now(); + + let sidechain_block = signed_sidechain_block.block().clone(); + let shard = sidechain_block.header().shard_id(); + let block_number = signed_sidechain_block.block().header().block_number(); + + debug!( + "Attempting to import sidechain block (number: {}, hash: {:?}, parentchain hash: {:?})", + block_number, + signed_sidechain_block.block().hash(), + signed_sidechain_block.block().block_data().layer_one_head() + ); + + let peeked_parentchain_header = + self.peek_parentchain_header(&sidechain_block, parentchain_header) + .unwrap_or_else(|e| { + warn!("Could not peek parentchain block, returning latest parentchain block ({:?})", e); + parentchain_header.clone() + }); + + let block_import_params = self.verify_import(&shard, |state| { + let verifier = self.verifier(state.get_last_block()); + verifier.verify( + signed_sidechain_block.clone(), + &peeked_parentchain_header, + shard, + self.get_context(), + ) + })?; + + let latest_parentchain_header = + self.import_parentchain_block(&sidechain_block, parentchain_header)?; + + let state_key = self.state_key()?; + + let state_update_start_time = Instant::now(); + self.apply_state_update(&shard, |mut state| { + let encrypted_state_diff = + block_import_params.block().block_data().encrypted_state_diff(); + + info!( + "Applying state diff for block {} of size {} bytes", + block_number, + encrypted_state_diff.len() + ); + + let update = state_update_from_encrypted(encrypted_state_diff, state_key)?; + + state.apply_state_update(&update).map_err(|e| Error::Other(e.into()))?; + + state.set_last_block(block_import_params.block()); + + Ok(state) + })?; + info!( + "Applying state update from block {} took {} ms", + block_number, + state_update_start_time.elapsed().as_millis() + ); + + self.cleanup(&signed_sidechain_block)?; + + // Store block in storage. + self.get_context().store_sidechain_blocks(vec![signed_sidechain_block])?; + + let import_duration = start_time.elapsed(); + info!("Importing block {} took {} ms", block_number, import_duration.as_millis()); + if let Err(e) = self + .get_context() + .update_metric(EnclaveMetric::SidechainBlockImportTime(import_duration)) + { + warn!("Failed to update metric for sidechain block import: {:?}", e); + }; + + Ok(latest_parentchain_header) + } +} + +fn state_update_from_encrypted( + encrypted: &[u8], + key: Key, +) -> Result { + let mut payload: Vec = encrypted.to_vec(); + key.decrypt(&mut payload).map_err(|e| Error::Other(format!("{:?}", e).into()))?; + + Ok(Decode::decode(&mut payload.as_slice())?) +} diff --git a/bitacross-worker/sidechain/consensus/common/src/block_import_confirmation_handler.rs b/bitacross-worker/sidechain/consensus/common/src/block_import_confirmation_handler.rs new file mode 100644 index 0000000000..be93feb51c --- /dev/null +++ b/bitacross-worker/sidechain/consensus/common/src/block_import_confirmation_handler.rs @@ -0,0 +1,130 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::error::{Error, Result}; +use itc_parentchain_light_client::{ + concurrent_access::ValidatorAccess, BlockNumberOps, ExtrinsicSender, NumberFor, +}; +use itp_extrinsics_factory::CreateExtrinsics; +use itp_node_api_metadata::{pallet_sidechain::SidechainCallIndexes, NodeMetadataTrait}; +use itp_node_api_metadata_provider::AccessNodeMetadata; +use itp_settings::worker::BLOCK_NUMBER_FINALIZATION_DIFF; +use itp_types::{OpaqueCall, ShardIdentifier}; +use its_primitives::traits::Header as HeaderTrait; +use log::*; +use sp_runtime::traits::Block as ParentchainBlockTrait; +use std::{marker::PhantomData, sync::Arc}; + +/// Trait to confirm a sidechain block import. +pub trait ConfirmBlockImport { + fn confirm_import(&self, header: &SidechainHeader, shard: &ShardIdentifier) -> Result<()>; +} + +/// Creates and sends a sidechain block import confirmation extrsinic to the parentchain. +pub struct BlockImportConfirmationHandler< + ParentchainBlock, + SidechainHeader, + NodeMetadataRepository, + ExtrinsicsFactory, + ValidatorAccessor, +> { + metadata_repository: Arc, + extrinsics_factory: Arc, + validator_accessor: Arc, + _phantom: PhantomData<(ParentchainBlock, SidechainHeader)>, +} + +impl< + ParentchainBlock, + SidechainHeader, + NodeMetadataRepository, + ExtrinsicsFactory, + ValidatorAccessor, + > + BlockImportConfirmationHandler< + ParentchainBlock, + SidechainHeader, + NodeMetadataRepository, + ExtrinsicsFactory, + ValidatorAccessor, + > +{ + pub fn new( + metadata_repository: Arc, + extrinsics_factory: Arc, + validator_accessor: Arc, + ) -> Self { + Self { + metadata_repository, + extrinsics_factory, + validator_accessor, + _phantom: Default::default(), + } + } +} + +impl< + ParentchainBlock, + SidechainHeader, + NodeMetadataRepository, + ExtrinsicsFactory, + ValidatorAccessor, + > ConfirmBlockImport + for BlockImportConfirmationHandler< + ParentchainBlock, + SidechainHeader, + NodeMetadataRepository, + ExtrinsicsFactory, + ValidatorAccessor, + > where + ParentchainBlock: ParentchainBlockTrait, + NumberFor: BlockNumberOps, + SidechainHeader: HeaderTrait, + NodeMetadataRepository: AccessNodeMetadata, + NodeMetadataRepository::MetadataType: NodeMetadataTrait, + ExtrinsicsFactory: CreateExtrinsics, + ValidatorAccessor: ValidatorAccess + Send + Sync + 'static, +{ + fn confirm_import(&self, header: &SidechainHeader, shard: &ShardIdentifier) -> Result<()> { + let call = self + .metadata_repository + .get_from_metadata(|m| m.confirm_imported_sidechain_block_indexes()) + .map_err(|e| Error::Other(e.into()))? + .map_err(|e| Error::Other(format!("{:?}", e).into()))?; + + if header.block_number() == header.next_finalization_block_number() { + let opaque_call = OpaqueCall::from_tuple(&( + call, + shard, + header.block_number(), + header.next_finalization_block_number() + BLOCK_NUMBER_FINALIZATION_DIFF, + header.hash(), + )); + + let xts = self + .extrinsics_factory + .create_extrinsics(&[opaque_call], None) + .map_err(|e| Error::Other(e.into()))?; + + debug!("Sending sidechain block import confirmation extrinsic.."); + self.validator_accessor + .execute_mut_on_validator(|v| v.send_extrinsics(xts)) + .map_err(|e| Error::Other(e.into()))?; + } + Ok(()) + } +} diff --git a/bitacross-worker/sidechain/consensus/common/src/block_import_queue_worker.rs b/bitacross-worker/sidechain/consensus/common/src/block_import_queue_worker.rs new file mode 100644 index 0000000000..fc7d9a23ef --- /dev/null +++ b/bitacross-worker/sidechain/consensus/common/src/block_import_queue_worker.rs @@ -0,0 +1,120 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{Error, Result, SyncBlockFromPeer}; +use core::marker::PhantomData; +use itp_import_queue::PopFromQueue; +use its_primitives::traits::{Block as BlockTrait, SignedBlock as SignedSidechainBlockTrait}; +use log::debug; +use sp_runtime::traits::Block as ParentchainBlockTrait; +use std::{sync::Arc, time::Instant}; + +/// Trait to trigger working the sidechain block import queue. +pub trait ProcessBlockImportQueue { + /// Pop sidechain blocks from the import queue and import them until queue is empty. + fn process_queue( + &self, + current_parentchain_header: &ParentchainBlockHeader, + ) -> Result; +} + +pub struct BlockImportQueueWorker< + ParentchainBlock, + SignedSidechainBlock, + BlockImportQueue, + PeerBlockSyncer, +> { + block_import_queue: Arc, + peer_block_syncer: Arc, + _phantom: PhantomData<(ParentchainBlock, SignedSidechainBlock)>, +} + +impl + BlockImportQueueWorker +where + ParentchainBlock: ParentchainBlockTrait, + SignedSidechainBlock: SignedSidechainBlockTrait, + SignedSidechainBlock::Block: BlockTrait, + BlockImportQueue: PopFromQueue, + PeerBlockSyncer: SyncBlockFromPeer, +{ + pub fn new( + block_import_queue: Arc, + peer_block_syncer: Arc, + ) -> Self { + BlockImportQueueWorker { + block_import_queue, + peer_block_syncer, + _phantom: Default::default(), + } + } + + fn record_timings(start_time: Instant, number_of_imported_blocks: usize) { + let elapsed_time_millis = start_time.elapsed().as_millis(); + let time_millis_per_block = + (elapsed_time_millis as f64 / number_of_imported_blocks as f64).ceil(); + debug!( + "Imported {} blocks in {} ms (average of {} ms per block)", + number_of_imported_blocks, elapsed_time_millis, time_millis_per_block + ); + } +} + +impl + ProcessBlockImportQueue + for BlockImportQueueWorker< + ParentchainBlock, + SignedSidechainBlock, + BlockImportQueue, + PeerBlockSyncer, + > where + ParentchainBlock: ParentchainBlockTrait, + SignedSidechainBlock: SignedSidechainBlockTrait, + SignedSidechainBlock::Block: BlockTrait, + BlockImportQueue: PopFromQueue, + PeerBlockSyncer: SyncBlockFromPeer, +{ + fn process_queue( + &self, + current_parentchain_header: &ParentchainBlock::Header, + ) -> Result { + let mut latest_imported_parentchain_header = current_parentchain_header.clone(); + let mut number_of_imported_blocks = 0usize; + let start_time = Instant::now(); + + loop { + match self.block_import_queue.pop_front() { + Ok(maybe_block) => match maybe_block { + Some(block) => { + latest_imported_parentchain_header = self + .peer_block_syncer + .sync_block(block, &latest_imported_parentchain_header)?; + number_of_imported_blocks += 1; + }, + None => { + Self::record_timings(start_time, number_of_imported_blocks); + return Ok(latest_imported_parentchain_header) + }, + }, + Err(e) => { + Self::record_timings(start_time, number_of_imported_blocks); + return Err(Error::FailedToPopBlockImportQueue(e)) + }, + } + } + } +} diff --git a/bitacross-worker/sidechain/consensus/common/src/block_production_suspension.rs b/bitacross-worker/sidechain/consensus/common/src/block_production_suspension.rs new file mode 100644 index 0000000000..ae664925da --- /dev/null +++ b/bitacross-worker/sidechain/consensus/common/src/block_production_suspension.rs @@ -0,0 +1,112 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +//! Mechanisms to (temporarily) suspend the production of sidechain blocks. + +#[cfg(feature = "sgx")] +use std::sync::SgxRwLock as RwLock; + +#[cfg(feature = "std")] +use std::sync::RwLock; + +use crate::error::{Error, Result}; +use log::*; + +/// Trait to suspend the production of sidechain blocks. +pub trait SuspendBlockProduction { + /// Suspend any sidechain block production. + fn suspend_for_sync(&self) -> Result<()>; + + /// Resume block sidechain block production. + fn resume(&self) -> Result<()>; +} + +/// Trait to query if sidechain block production is suspended. +pub trait IsBlockProductionSuspended { + fn is_suspended(&self) -> Result; + + fn is_sync_ongoing(&self) -> Result; +} + +/// Implementation for suspending and resuming sidechain block production. +#[derive(Default)] +pub struct BlockProductionSuspender { + is_suspended: RwLock, + sync_is_ongoing: RwLock, +} + +impl BlockProductionSuspender { + pub fn new(is_suspended: bool) -> Self { + BlockProductionSuspender { + is_suspended: RwLock::new(is_suspended), + sync_is_ongoing: RwLock::new(false), + } + } +} + +impl SuspendBlockProduction for BlockProductionSuspender { + fn suspend_for_sync(&self) -> Result<()> { + let mut suspended_lock = self.is_suspended.write().map_err(|_| Error::LockPoisoning)?; + *suspended_lock = true; + + let mut sync_is_ongoing_lock = + self.sync_is_ongoing.write().map_err(|_| Error::LockPoisoning)?; + *sync_is_ongoing_lock = true; + + info!("Suspend sidechain block production"); + Ok(()) + } + + fn resume(&self) -> Result<()> { + let mut suspended_lock = self.is_suspended.write().map_err(|_| Error::LockPoisoning)?; + *suspended_lock = false; + info!("Resume sidechain block production"); + Ok(()) + } +} + +impl IsBlockProductionSuspended for BlockProductionSuspender { + fn is_suspended(&self) -> Result { + Ok(*self.is_suspended.read().map_err(|_| Error::LockPoisoning)?) + } + + fn is_sync_ongoing(&self) -> Result { + Ok(*self.sync_is_ongoing.read().map_err(|_| Error::LockPoisoning)?) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn initial_production_is_not_suspended() { + let block_production_suspender = BlockProductionSuspender::default(); + assert!(!block_production_suspender.is_suspended().unwrap()); + } + + #[test] + fn suspending_production_works() { + let block_production_suspender = BlockProductionSuspender::default(); + + block_production_suspender.suspend_for_sync().unwrap(); + assert!(block_production_suspender.is_suspended().unwrap()); + + block_production_suspender.resume().unwrap(); + assert!(!block_production_suspender.is_suspended().unwrap()); + } +} diff --git a/bitacross-worker/sidechain/consensus/common/src/error.rs b/bitacross-worker/sidechain/consensus/common/src/error.rs new file mode 100644 index 0000000000..f6ba8b6fd0 --- /dev/null +++ b/bitacross-worker/sidechain/consensus/common/src/error.rs @@ -0,0 +1,99 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 sidechain consensus + +use itp_types::BlockHash as ParentchainBlockHash; +use its_block_verification::error::Error as VerificationError; +use its_primitives::types::{block::BlockHash as SidechainBlockHash, BlockNumber}; +use sgx_types::sgx_status_t; +use std::{ + boxed::Box, + error, + string::{String, ToString}, + vec::Vec, +}; + +pub type Result = std::result::Result; + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +pub use thiserror_sgx as thiserror; + +#[derive(Debug, thiserror::Error)] +#[non_exhaustive] +pub enum Error { + #[error("SGX error, status: {0}")] + Sgx(sgx_status_t), + #[error("Unable to create block proposal.")] + CannotPropose, + #[error("Encountered poisoned lock")] + LockPoisoning, + #[error("Message sender {0} is not a valid authority")] + InvalidAuthority(String), + #[error("Could not get authorities: {0:?}.")] + CouldNotGetAuthorities(String), + #[error("Chain lookup failed: {0}")] + ChainLookup(String), + #[error("Failed to sign using key: {0:?}. Reason: {1}")] + CannotSign(Vec, String), + #[error("Bad parentchain block (Hash={0}). Reason: {1}")] + BadParentchainBlock(ParentchainBlockHash, String), + #[error("Bad sidechain block (Hash={0}). Reason: {1}")] + BadSidechainBlock(SidechainBlockHash, String), + #[error("Could not import new block due to {2}. (Last imported by number: {0:?})")] + BlockAncestryMismatch(BlockNumber, SidechainBlockHash, String), + #[error("Could not import new block. Expected first block, but found {0}. {1:?}")] + InvalidFirstBlock(BlockNumber, String), + #[error("Could not import block (number: {0}). A block with this number is already imported (current state block number: {1})")] + BlockAlreadyImported(BlockNumber, BlockNumber), + #[error("Failed to pop from block import queue: {0}")] + FailedToPopBlockImportQueue(#[from] itp_import_queue::error::Error), + #[error("Verification Error: {0}")] + VerificationError(its_block_verification::error::Error), + #[error(transparent)] + Other(#[from] Box), +} + +impl core::convert::From for Error { + fn from(e: std::io::Error) -> Self { + Self::Other(e.into()) + } +} + +impl core::convert::From for Error { + fn from(e: codec::Error) -> Self { + Self::Other(e.to_string().into()) + } +} + +impl From for Error { + fn from(sgx_status: sgx_status_t) -> Self { + Self::Sgx(sgx_status) + } +} + +impl From for Error { + fn from(e: VerificationError) -> Self { + match e { + VerificationError::BlockAncestryMismatch(a, b, c) => + Error::BlockAncestryMismatch(a, b, c), + VerificationError::InvalidFirstBlock(a, b) => Error::InvalidFirstBlock(a, b), + VerificationError::BlockAlreadyImported(a, b) => Error::BlockAlreadyImported(a, b), + _ => Error::VerificationError(e), + } + } +} diff --git a/bitacross-worker/sidechain/consensus/common/src/header_db.rs b/bitacross-worker/sidechain/consensus/common/src/header_db.rs new file mode 100644 index 0000000000..f15acd5028 --- /dev/null +++ b/bitacross-worker/sidechain/consensus/common/src/header_db.rs @@ -0,0 +1,44 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 itp_types::H256; +use its_primitives::traits::Header as HeaderT; +use std::{collections::HashMap, convert::From, hash::Hash as HashT}; + +/// Normally implemented on the `client` in substrate. +/// Is a trait which can offer methods for interfacing with a block Database. +pub trait HeaderDbTrait { + type Header: HeaderT; + /// Retrieves Header for the corresponding block hash. + fn header(&self, hash: &H256) -> Option; +} + +/// A mocked Header Database which allows you to take a Block Hash and Query a Block Header. +pub struct HeaderDb(pub HashMap); + +impl HeaderDbTrait for HeaderDb +where + // TODO: the H256 trait bounds are needed because: #1203 + Hash: PartialEq + HashT + Into + From + core::cmp::Eq + Clone, + Header: HeaderT + Clone, +{ + type Header = Header; + + fn header(&self, hash: &H256) -> Option { + let header = self.0.get(&Hash::from(*hash))?; + Some(header.clone()) + } +} diff --git a/bitacross-worker/sidechain/consensus/common/src/is_descendant_of_builder.rs b/bitacross-worker/sidechain/consensus/common/src/is_descendant_of_builder.rs new file mode 100644 index 0000000000..5e13c6f69a --- /dev/null +++ b/bitacross-worker/sidechain/consensus/common/src/is_descendant_of_builder.rs @@ -0,0 +1,133 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::header_db::HeaderDbTrait; +use core::{hash::Hash as HashT, marker::PhantomData}; +use itp_types::H256; +use its_primitives::traits::Header as HeaderT; + +pub struct IsDescendantOfBuilder(PhantomData<(Hash, HeaderDb, Error)>); + +impl<'a, Hash, HeaderDb, Error> IsDescendantOfBuilder +where + Error: From<()>, + Hash: PartialEq + HashT + Default + Into + From + Clone, + HeaderDb: HeaderDbTrait, +{ + /// Builds the `is_descendant_of` closure for the fork-tree + /// used when adding and removing nodes from the tree. + pub fn build_is_descendant_of( + current: Option<(&'a Hash, &'a Hash)>, + header_db: &'a HeaderDb, + ) -> impl Fn(&Hash, &Hash) -> Result + 'a { + move |base, head| { + // If the base is equal to the proposed head, then the head is for sure not a descendant of the base. + if base == head { + return Ok(false) + } + + let mut head = head; + if let Some((current_hash, current_parent_hash)) = current { + // If the current hash is equal to the base, then it will not be a descendant of base. + if current_hash == base { + return Ok(false) + } + + // If the current hash is the head and the parent is the base, then we know that + // this current hash is the descendant of the parent. Otherwise we can set the + // head to the parent and find the lowest common ancestor between `head` + // and `base` in the tree. + if current_hash == head { + if current_parent_hash == base { + return Ok(true) + } else { + head = current_parent_hash; + } + } + } + + let ancestor = + >::find_lowest_common_ancestor( + head, base, header_db, + )?; + Ok(ancestor == *base) + } + } +} + +pub struct LowestCommonAncestorFinder(PhantomData<(Hash, HeaderDb)>); + +impl LowestCommonAncestorFinder +where + Hash: PartialEq + Default + Into + From + Clone, + HeaderDb: HeaderDbTrait, +{ + /// Used by the `build_is_descendant_of` to find the LCA of two nodes in the fork-tree. + fn find_lowest_common_ancestor(a: &Hash, b: &Hash, header_db: &HeaderDb) -> Result { + let header_1 = header_db.header(&a.clone().into()).ok_or(())?; + let header_2 = header_db.header(&b.clone().into()).ok_or(())?; + let mut blocknum_1 = header_1.block_number(); + let mut blocknum_2 = header_2.block_number(); + let mut parent_1 = Hash::from(header_1.parent_hash()); + let mut parent_2 = Hash::from(header_2.parent_hash()); + + if *a == parent_2 { + // Then a is the common ancestor of b and it means it is itself the ancestor + return Ok(parent_2) + } + + if *b == parent_1 { + // Then b is the common ancestor of a and it means it is itself the ancestor + return Ok(parent_1) + } + + while blocknum_1 > blocknum_2 { + // This means block 1 is further down in the tree than block 2 + let new_parent = header_db.header(&parent_1.clone().into()).ok_or(())?; + + if new_parent.block_number() >= blocknum_2 { + blocknum_1 = new_parent.block_number(); + parent_1 = Hash::from(new_parent.parent_hash()); + } else { + break + } + } + + while blocknum_2 > blocknum_1 { + // This means block 2 is further down in the tree than block 1 + let new_parent = header_db.header(&parent_2.clone().into()).ok_or(())?; + + if new_parent.block_number() >= blocknum_1 { + blocknum_2 = new_parent.block_number(); + parent_2 = Hash::from(new_parent.parent_hash()); + } else { + break + } + } + + // At this point will be at equal height + while parent_1 != parent_2 { + // go up on both nodes + let new_header_1 = header_db.header(&parent_1.into()).ok_or(())?; + let new_header_2 = header_db.header(&parent_2.into()).ok_or(())?; + parent_1 = Hash::from(new_header_1.parent_hash()); + parent_2 = Hash::from(new_header_2.parent_hash()); + } + + // Return any Parent node Hash as in worst case scenario it is the root which is shared amongst all + Ok(parent_1) + } +} diff --git a/bitacross-worker/sidechain/consensus/common/src/lib.rs b/bitacross-worker/sidechain/consensus/common/src/lib.rs new file mode 100644 index 0000000000..adb91d9ec8 --- /dev/null +++ b/bitacross-worker/sidechain/consensus/common/src/lib.rs @@ -0,0 +1,114 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 stuff that could be shared across multiple consensus engines + +#![cfg_attr(not(feature = "std"), no_std)] +#![cfg_attr(test, feature(assert_matches))] + +#[cfg(all(feature = "std", feature = "sgx"))] +compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the same time"); + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +#[macro_use] +extern crate sgx_tstd as std; + +use its_primitives::traits::{ShardIdentifierFor, SignedBlock as SignedSidechainBlockTrait}; +use sp_runtime::traits::Block as ParentchainBlockTrait; +use std::{time::Duration, vec::Vec}; + +mod block_import; +mod block_import_confirmation_handler; +mod block_import_queue_worker; +mod error; +mod header_db; +mod peer_block_sync; + +// The feature flag will be removed once we use the module outside of tests. +#[cfg(test)] +mod is_descendant_of_builder; + +#[cfg(test)] +mod test; + +pub use block_import::*; +pub use block_import_confirmation_handler::*; +pub use block_import_queue_worker::*; +pub use error::*; +use itp_types::parentchain::ParentchainCall; +pub use peer_block_sync::*; + +pub trait Verifier: Send + Sync +where + ParentchainBlock: ParentchainBlockTrait, + SignedSidechainBlock: SignedSidechainBlockTrait, +{ + /// Contains all the relevant data needed for block import + type BlockImportParams; + + /// Context used to derive slot relevant data + type Context; + + /// Verify the given data and return the `BlockImportParams` if successful + fn verify( + &self, + block: SignedSidechainBlock, + parentchain_header: &ParentchainBlock::Header, + shard: ShardIdentifierFor, + ctx: &Self::Context, + ) -> Result; +} + +/// Environment for a Consensus instance. +/// +/// Creates proposer instance. +pub trait Environment< + ParentchainBlock: ParentchainBlockTrait, + SignedSidechainBlock: SignedSidechainBlockTrait, +> +{ + /// The proposer type this creates. + type Proposer: Proposer + Send; + /// Error which can occur upon creation. + type Error: From + std::fmt::Debug + 'static; + + /// Initialize the proposal logic on top of a specific header. + fn init( + &mut self, + parent_header: ParentchainBlock::Header, + shard: ShardIdentifierFor, + ) -> std::result::Result; +} + +pub trait Proposer< + ParentchainBlock: ParentchainBlockTrait, + SignedSidechainBlock: SignedSidechainBlockTrait, +> +{ + fn propose(&self, max_duration: Duration) -> Result>; +} + +/// A proposal that is created by a [`Proposer`]. +pub struct Proposal { + /// The sidechain block that was build. + pub block: SignedSidechainBlock, + /// Parentchain state transitions triggered by sidechain state transitions. + /// + /// Any sidechain stf that invokes a parentchain stf must not commit its state change + /// before the parentchain effect has been finalized. + pub parentchain_effects: Vec, +} diff --git a/bitacross-worker/sidechain/consensus/common/src/peer_block_sync.rs b/bitacross-worker/sidechain/consensus/common/src/peer_block_sync.rs new file mode 100644 index 0000000000..945c1c014e --- /dev/null +++ b/bitacross-worker/sidechain/consensus/common/src/peer_block_sync.rs @@ -0,0 +1,320 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{BlockImport, ConfirmBlockImport, Error, Result}; +use core::marker::PhantomData; +use itp_ocall_api::{EnclaveMetricsOCallApi, EnclaveSidechainOCallApi}; +use itp_types::H256; +use its_primitives::{ + traits::{ + Block as BlockTrait, Header as HeaderTrait, ShardIdentifierFor, + SignedBlock as SignedSidechainBlockTrait, + }, + types::BlockHash, +}; +use log::*; +use sp_runtime::traits::{Block as ParentchainBlockTrait, Header as ParentchainHeaderTrait}; +use std::{sync::Arc, vec::Vec}; + +/// Trait for syncing sidechain blocks from a peer validateer. +/// +/// This entails importing blocks and detecting if we're out of date with our blocks, in which +/// case we fetch the missing blocks from a peer. +pub trait SyncBlockFromPeer +where + ParentchainHeader: ParentchainHeaderTrait, + SignedSidechainBlock: SignedSidechainBlockTrait, +{ + fn sync_block( + &self, + sidechain_block: SignedSidechainBlock, + last_imported_parentchain_header: &ParentchainHeader, + ) -> Result; +} + +/// Sidechain peer block sync implementation. +pub struct PeerBlockSync< + ParentchainBlock, + SignedSidechainBlock, + BlockImporter, + OCallApi, + ImportConfirmationHandler, +> { + importer: Arc, + ocall_api: Arc, + import_confirmation_handler: Arc, + _phantom: PhantomData<(ParentchainBlock, SignedSidechainBlock)>, +} + +impl< + ParentchainBlock, + SignedSidechainBlock, + BlockImporter, + OCallApi, + ImportConfirmationHandler, + > + PeerBlockSync< + ParentchainBlock, + SignedSidechainBlock, + BlockImporter, + OCallApi, + ImportConfirmationHandler, + > where + ParentchainBlock: ParentchainBlockTrait, + SignedSidechainBlock: SignedSidechainBlockTrait, + <::Block as BlockTrait>::HeaderType: + HeaderTrait, + BlockImporter: BlockImport, + OCallApi: EnclaveSidechainOCallApi + EnclaveMetricsOCallApi, + ImportConfirmationHandler: ConfirmBlockImport< + <::Block as BlockTrait>::HeaderType, + >, +{ + pub fn new( + importer: Arc, + sidechain_ocall_api: Arc, + import_confirmation_handler: Arc, + ) -> Self { + PeerBlockSync { + importer, + ocall_api: sidechain_ocall_api, + import_confirmation_handler, + _phantom: Default::default(), + } + } + + fn fetch_and_import_blocks_from_peer( + &self, + last_imported_sidechain_block_hash: BlockHash, + import_until_block_hash: BlockHash, + current_parentchain_header: &ParentchainBlock::Header, + shard_identifier: ShardIdentifierFor, + ) -> Result { + info!( + "Initiating fetch blocks from peer, last imported block hash: {:?}, until block hash: {:?}", + last_imported_sidechain_block_hash, import_until_block_hash + ); + + let blocks_to_import: Vec = + self.ocall_api.fetch_sidechain_blocks_from_peer( + last_imported_sidechain_block_hash, + Some(import_until_block_hash), + shard_identifier, + )?; + + info!("Fetched {} blocks from peer to import", blocks_to_import.len()); + + let mut latest_imported_parentchain_header = current_parentchain_header.clone(); + + for block_to_import in blocks_to_import { + let block_number = block_to_import.block().header().block_number(); + + latest_imported_parentchain_header = match self + .importer + .import_block(block_to_import, &latest_imported_parentchain_header) + { + Err(e) => { + error!("Failed to import sidechain block that was fetched from peer: {:?}", e); + return Err(e) + }, + Ok(h) => { + info!( + "Successfully imported peer fetched sidechain block (number: {})", + block_number + ); + h + }, + }; + } + + Ok(latest_imported_parentchain_header) + } +} + +impl + SyncBlockFromPeer + for PeerBlockSync +where + ParentchainBlock: ParentchainBlockTrait, + SignedSidechainBlock: SignedSidechainBlockTrait, + <::Block as BlockTrait>::HeaderType: + HeaderTrait, + BlockImporter: BlockImport, + OCallApi: EnclaveSidechainOCallApi + EnclaveMetricsOCallApi, + ImportConfirmationHandler: ConfirmBlockImport<<::Block as BlockTrait>::HeaderType>, +{ + fn sync_block( + &self, + sidechain_block: SignedSidechainBlock, + current_parentchain_header: &ParentchainBlock::Header, + ) -> Result { + let shard_identifier = sidechain_block.block().header().shard_id(); + let sidechain_block_number = sidechain_block.block().header().block_number(); + let sidechain_block_hash = sidechain_block.hash(); + + // Attempt to import the block - in case we encounter an ancestry error, we go into + // peer fetching mode to fetch sidechain blocks from a peer and import those first. + match self.importer.import_block(sidechain_block.clone(), current_parentchain_header) { + Err(e) => match e { + Error::BlockAncestryMismatch(_block_number, block_hash, _) => { + warn!("Got ancestry mismatch error upon block import. Attempting to fetch missing blocks from peer"); + let updated_parentchain_header = self.fetch_and_import_blocks_from_peer( + block_hash, + sidechain_block_hash, + current_parentchain_header, + shard_identifier, + )?; + + self.importer.import_block(sidechain_block, &updated_parentchain_header) + }, + Error::InvalidFirstBlock(block_number, _) => { + warn!("Got invalid first block error upon block import (expected first block, but got block with number {}). \ + Attempting to fetch missing blocks from peer", block_number); + let updated_parentchain_header = self.fetch_and_import_blocks_from_peer( + Default::default(), // This is the parent hash of the first block. So we import everything. + sidechain_block_hash, + current_parentchain_header, + shard_identifier, + )?; + + self.importer.import_block(sidechain_block, &updated_parentchain_header) + }, + Error::BlockAlreadyImported(to_import_block_number, last_known_block_number) => { + warn!("Sidechain block from queue (number: {}) was already imported (current block number: {}). Block will be ignored.", + to_import_block_number, last_known_block_number); + Ok(current_parentchain_header.clone()) + }, + _ => Err(e), + }, + Ok(latest_parentchain_header) => { + info!("Successfully imported broadcast sidechain block (number: {}), based on parentchain block {:?}", + sidechain_block_number, latest_parentchain_header.number()); + + // We confirm the successful block import. Only in this case, not when we're in + // on-boarding and importing blocks that were fetched from a peer. + if let Err(e) = self.import_confirmation_handler.confirm_import(sidechain_block.block().header(), &shard_identifier) { + error!("Failed to confirm sidechain block import: {:?}", e); + } + + Ok(latest_parentchain_header) + }, + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::test::mocks::{ + block_importer_mock::BlockImportMock, confirm_block_import_mock::ConfirmBlockImportMock, + }; + use core::assert_matches::assert_matches; + use itc_parentchain_test::ParentchainHeaderBuilder; + use itp_test::mock::sidechain_ocall_api_mock::SidechainOCallApiMock; + use itp_types::Block as ParentchainBlock; + use its_primitives::types::block::SignedBlock as SignedSidechainBlock; + use its_test::sidechain_block_builder::{SidechainBlockBuilder, SidechainBlockBuilderTrait}; + + type TestBlockImport = BlockImportMock; + type TestOCallApi = SidechainOCallApiMock; + type TestPeerBlockSync = PeerBlockSync< + ParentchainBlock, + SignedSidechainBlock, + TestBlockImport, + TestOCallApi, + ConfirmBlockImportMock, + >; + + #[test] + fn if_block_import_is_successful_no_peer_fetching_happens() { + let parentchain_header = ParentchainHeaderBuilder::default().build(); + let signed_sidechain_block = SidechainBlockBuilder::default().build_signed(); + + let block_importer_mock = Arc::new( + BlockImportMock::::default() + .with_import_result_once(Ok(parentchain_header.clone())), + ); + + let sidechain_ocall_api = + Arc::new(SidechainOCallApiMock::::default()); + + let peer_syncer = + create_peer_syncer(block_importer_mock.clone(), sidechain_ocall_api.clone()); + + peer_syncer.sync_block(signed_sidechain_block, &parentchain_header).unwrap(); + + assert_eq!(1, block_importer_mock.get_imported_blocks().len()); + assert_eq!(0, sidechain_ocall_api.number_of_fetch_calls()); + } + + #[test] + fn error_is_propagated_if_import_returns_error_other_than_ancestry_mismatch() { + let block_importer_mock = Arc::new( + BlockImportMock::::default() + .with_import_result_once(Err(Error::InvalidAuthority("auth".to_string()))), + ); + + let sidechain_ocall_api = + Arc::new(SidechainOCallApiMock::::default()); + + let peer_syncer = + create_peer_syncer(block_importer_mock.clone(), sidechain_ocall_api.clone()); + + let parentchain_header = ParentchainHeaderBuilder::default().build(); + let signed_sidechain_block = SidechainBlockBuilder::default().build_signed(); + + let sync_result = peer_syncer.sync_block(signed_sidechain_block, &parentchain_header); + + assert_matches!(sync_result, Err(Error::InvalidAuthority(_))); + assert_eq!(1, block_importer_mock.get_imported_blocks().len()); + assert_eq!(0, sidechain_ocall_api.number_of_fetch_calls()); + } + + #[test] + fn blocks_are_fetched_from_peer_if_initial_import_yields_ancestry_mismatch() { + let block_importer_mock = + Arc::new(BlockImportMock::::default().with_import_result_once( + Err(Error::BlockAncestryMismatch(1, H256::random(), "".to_string())), + )); + + let sidechain_ocall_api = Arc::new( + SidechainOCallApiMock::::default().with_peer_fetch_blocks(vec![ + SidechainBlockBuilder::random().build_signed(), + SidechainBlockBuilder::random().build_signed(), + ]), + ); + + let peer_syncer = + create_peer_syncer(block_importer_mock.clone(), sidechain_ocall_api.clone()); + + let parentchain_header = ParentchainHeaderBuilder::default().build(); + let signed_sidechain_block = SidechainBlockBuilder::default().build_signed(); + + peer_syncer.sync_block(signed_sidechain_block, &parentchain_header).unwrap(); + + assert_eq!(4, block_importer_mock.get_imported_blocks().len()); + assert_eq!(1, sidechain_ocall_api.number_of_fetch_calls()); + } + + fn create_peer_syncer( + block_importer: Arc, + ocall_api: Arc, + ) -> TestPeerBlockSync { + let import_confirmation_handler = Arc::new(ConfirmBlockImportMock {}); + TestPeerBlockSync::new(block_importer, ocall_api, import_confirmation_handler) + } +} diff --git a/bitacross-worker/sidechain/consensus/common/src/test/mocks/block_import_queue_worker_mock.rs b/bitacross-worker/sidechain/consensus/common/src/test/mocks/block_import_queue_worker_mock.rs new file mode 100644 index 0000000000..fb2b0d8bcc --- /dev/null +++ b/bitacross-worker/sidechain/consensus/common/src/test/mocks/block_import_queue_worker_mock.rs @@ -0,0 +1,263 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{header_db::HeaderDb, is_descendant_of_builder::IsDescendantOfBuilder}; +use core::marker::PhantomData; +use fork_tree::ForkTree; +use itp_types::H256; +use its_primitives::{ + traits::{Block as BlockT, Header as HeaderT}, + types::{header::SidechainHeader as Header, Block}, +}; +use its_test::sidechain_block_builder::{SidechainBlockBuilder, SidechainBlockBuilderTrait}; +use std::collections::VecDeque; + +#[derive(Default)] +pub struct BlockQueueBuilder { + queue: VecDeque, + _phantom_data: PhantomData, +} + +impl BlockQueueBuilder +where + Builder: SidechainBlockBuilderTrait + Default, + B: BlockT + From, +{ + fn new() -> Self { + Self { queue: VecDeque::new(), _phantom_data: PhantomData::default() } + } + + /// Allows definining a mock queue based and assumes that a genesis block + /// will need to be appended to the queue as the first item. + /// Returns: BuiltQueue + fn build_queue(self, f: impl FnOnce(VecDeque) -> VecDeque) -> VecDeque { + f(self.queue) + } + + fn add_genesis_block_to_queue(self) -> Self { + let mut self_mut = self; + let genesis_header = Header { + block_number: 0, + parent_hash: H256::from_slice(&[0; 32]), + ..Default::default() + }; + let block: B = Builder::default().with_header(genesis_header).build().into(); + self_mut.queue.push_back(block); + self_mut + } +} + +pub trait BlockQueueHeaderBuild { + type QueueHeader; + /// Helper trait to build a Header for a BlockQueue. + fn build_queue_header(block_number: BlockNumber, parent_hash: Hash) -> Self::QueueHeader; +} + +pub struct BlockQueueHeaderBuilder(PhantomData<(BlockNumber, Hash)>); + +impl BlockQueueHeaderBuild + for BlockQueueHeaderBuilder +where + BlockNumber: Into, + Hash: Into, +{ + type QueueHeader = Header; + /// Helper trait to build a Header for a BlockQueue. + fn build_queue_header(block_number: BlockNumber, parent_hash: Hash) -> Self::QueueHeader { + Header { + block_number: block_number.into(), + parent_hash: parent_hash.into(), + block_data_hash: H256::random(), + ..Default::default() + } + } +} + +#[derive(Debug)] +pub enum TestError { + Error, +} + +impl From<()> for TestError { + fn from(_a: ()) -> Self { + TestError::Error + } +} + +impl std::fmt::Display for TestError { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(f, "TestError") + } +} + +impl std::error::Error for TestError {} + +#[cfg(test)] +mod tests { + use super::*; + + fn fork_tree_from_header_queue(queue: VecDeque) -> ForkTree + where + B: BlockT, + { + // Store all block_headers in db + let db = HeaderDb::( + queue.iter().map(|block| (block.hash(), *block.header())).collect(), + ); + + // Import into forktree + let is_descendant_of = + , TestError>>::build_is_descendant_of(None, &db); + let mut tree = >::new(); + queue.iter().for_each(|block| { + let _ = tree + .import(block.header().hash(), block.header().block_number(), (), &is_descendant_of) + .unwrap(); + }); + tree + } + + #[test] + fn process_sequential_queue_no_forks() { + // Construct a queue which is sequential with 5 members all with distinct block numbers and parents + let mut queue = >::new() + .add_genesis_block_to_queue() + .build_queue(|mut queue| { + for i in 1..5 { + let parent_header = queue.back().unwrap().header(); + let header = >::build_queue_header( + i, + parent_header.hash(), + ); + queue.push_back(SidechainBlockBuilder::default().with_header(header).build()); + } + queue + }); + + // queue -> [0, 1, 2, 3, 4] + assert_eq!(queue.len(), 5); + + let mut tree = fork_tree_from_header_queue::(queue.clone()); + + // We have a tree which looks like this. H0 is the only root. + // + // H0 - H1 - H2 - H3 - H4 + // + + // We see that the only root of this tree is so far H0 + assert_eq!(tree.roots_hash_and_number(), vec![(&queue.front().unwrap().header.hash(), &0)]); + + // Now finalize H0 and so the new Root should be H1 + tree.finalize_root(&queue.front().unwrap().header.hash()).unwrap(); + let _ = queue.pop_front(); + assert_eq!(tree.roots_hash_and_number(), vec![(&queue.front().unwrap().header.hash(), &1)]); + } + + #[test] + fn process_sequential_queue_with_forks() { + // Construct a queue which is sequential and every odd member has 2 block numbers which are the same + let mut queue = >::new() + .add_genesis_block_to_queue() + .build_queue(|mut queue| { + for i in 1..8 { + let parent_header = queue.back().unwrap().header(); + if i % 2 == 0 && i != 1 { + // 1 is not even want all odds to have 2 of the same block_number + let header = >::build_queue_header( + i, + parent_header.hash(), + ); + queue.push_back( + SidechainBlockBuilder::default().with_header(header).build(), + ); + } else { + // build a Queue with 2 headers which are of the same block_number + let headers = vec![ + >::build_queue_header( + i, + parent_header.hash(), + ), + >::build_queue_header( + i, + parent_header.hash(), + ), + ]; + headers.iter().for_each(|header| { + queue.push_back( + SidechainBlockBuilder::default().with_header(*header).build(), + ); + }); + } + } + queue + }); + + // queue -> [0, 1, 1, 2, 3, 3, 4, 5, 5, 6, 7, 7] + assert_eq!(queue.len(), 12); + + let mut tree = fork_tree_from_header_queue::(queue.clone()); + + // We have a tree which looks like the following + // - (H5, B3).. + // / + // - (H3, B2) + // / \ + // - (H1, B1) - (H4, B3).. + // / + // / + // (H0, B0) + // \ + // \ + // - (H2, B1).. + // + // + + // H0 is the first root + assert_eq!(tree.roots_hash_and_number(), vec![(&queue.front().unwrap().header.hash(), &0)]); + + // Now if we finalize H0 we should see 2 roots H1 and H2 + tree.finalize_root(&queue.front().unwrap().header.hash()).unwrap(); + let _ = queue.pop_front(); + assert_eq!( + tree.roots_hash_and_number(), + vec![(&queue[1].header.hash(), &1), (&queue[0].header.hash(), &1)] + ); + + // If we finalize (H1, B1) then we should see one roots (H3, B2) + let _ = queue.pop_front(); // remove (H1, B1) + tree.finalize_root(&queue.front().unwrap().header.hash()).unwrap(); + let _ = queue.pop_front(); // remove (H2, B1) + assert_eq!(tree.roots_hash_and_number(), vec![(&queue[0].header.hash(), &2)]); + + // If we finalize (H3, B2) we should see two roots (H4, B3), (H5, B3) + tree.finalize_root(&queue.front().unwrap().header.hash()).unwrap(); + let _ = queue.pop_front(); // remove (H3, B2) + assert_eq!( + tree.roots_hash_and_number(), + vec![(&queue[1].header.hash(), &3), (&queue[0].header.hash(), &3)] + ); + } + + #[test] + fn process_non_sequential_queue_without_forks() { + // TODO + } + + #[test] + fn process_non_sequential_queue_with_forks() { + // TODO + } +} diff --git a/bitacross-worker/sidechain/consensus/common/src/test/mocks/block_importer_mock.rs b/bitacross-worker/sidechain/consensus/common/src/test/mocks/block_importer_mock.rs new file mode 100644 index 0000000000..9d6060561f --- /dev/null +++ b/bitacross-worker/sidechain/consensus/common/src/test/mocks/block_importer_mock.rs @@ -0,0 +1,168 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{test::mocks::verifier_mock::VerifierMock, BlockImport, Error, Result}; +use core::marker::PhantomData; +use itp_ocall_api::EnclaveMetricsOCallApi; +use itp_sgx_crypto::aes::Aes; +use itp_sgx_externalities::SgxExternalities; +use itp_test::mock::onchain_mock::OnchainMock; +use itp_types::H256; +use its_primitives::traits::{ShardIdentifierFor, SignedBlock as SignedSidechainBlockTrait}; +use sp_core::Pair; +use sp_runtime::traits::Block as ParentchainBlockTrait; +use std::{collections::VecDeque, sync::RwLock}; + +/// Block importer mock. +pub struct BlockImportMock +where + ParentchainBlock: ParentchainBlockTrait, + SignedSidechainBlock: + SignedSidechainBlockTrait::Public> + 'static, +{ + import_result: RwLock>>, + imported_blocks: RwLock>, + _phantom: PhantomData<(ParentchainBlock, SignedSidechainBlock)>, +} + +impl BlockImportMock +where + ParentchainBlock: ParentchainBlockTrait, + SignedSidechainBlock: + SignedSidechainBlockTrait::Public> + 'static, +{ + pub fn with_import_result_once(self, result: Result) -> Self { + let mut imported_results_lock = self.import_result.write().unwrap(); + imported_results_lock.push_back(result); + std::mem::drop(imported_results_lock); + self + } + + #[allow(unused)] + pub fn with_import_result_sequence( + self, + mut results: VecDeque>, + ) -> Self { + let mut imported_results_lock = self.import_result.write().unwrap(); + imported_results_lock.append(&mut results); + std::mem::drop(imported_results_lock); + self + } + + pub fn get_imported_blocks(&self) -> Vec { + (*self.imported_blocks.read().unwrap()).clone() + } +} + +impl Default + for BlockImportMock +where + ParentchainBlock: ParentchainBlockTrait, + SignedSidechainBlock: + SignedSidechainBlockTrait::Public> + 'static, +{ + fn default() -> Self { + BlockImportMock { + import_result: RwLock::default(), + imported_blocks: RwLock::default(), + _phantom: Default::default(), + } + } +} + +impl BlockImport + for BlockImportMock +where + ParentchainBlock: ParentchainBlockTrait, + SignedSidechainBlock: + SignedSidechainBlockTrait::Public> + 'static, +{ + type Verifier = + VerifierMock; + type SidechainState = SgxExternalities; + type StateCrypto = Aes; + type Context = OnchainMock; + + fn verifier( + &self, + _maybe_last_sidechain_block: Option, + ) -> Self::Verifier { + todo!() + } + + fn apply_state_update( + &self, + _shard: &ShardIdentifierFor, + _mutating_function: F, + ) -> Result<()> + where + F: FnOnce(Self::SidechainState) -> Result, + { + todo!() + } + + fn verify_import( + &self, + _shard: &ShardIdentifierFor, + _verifying_function: F, + ) -> core::result::Result + where + F: FnOnce(&Self::SidechainState) -> core::result::Result, + { + todo!() + } + + fn state_key(&self) -> Result { + todo!() + } + + fn get_context(&self) -> &Self::Context { + todo!() + } + + fn import_parentchain_block( + &self, + _sidechain_block: &SignedSidechainBlock::Block, + _last_imported_parentchain_header: &ParentchainBlock::Header, + ) -> Result { + todo!() + } + + fn peek_parentchain_header( + &self, + _sidechain_block: &SignedSidechainBlock::Block, + _last_imported_parentchain_header: &ParentchainBlock::Header, + ) -> core::result::Result { + todo!() + } + + fn cleanup(&self, _signed_sidechain_block: &SignedSidechainBlock) -> Result<()> { + todo!() + } + + fn import_block( + &self, + signed_sidechain_block: SignedSidechainBlock, + parentchain_header: &ParentchainBlock::Header, + ) -> Result { + let mut imported_blocks_lock = self.imported_blocks.write().unwrap(); + imported_blocks_lock.push(signed_sidechain_block); + + let mut imported_results_lock = self.import_result.write().unwrap(); + imported_results_lock.pop_front().unwrap_or(Ok(parentchain_header.clone())) + } +} diff --git a/bitacross-worker/sidechain/consensus/common/src/test/mocks/confirm_block_import_mock.rs b/bitacross-worker/sidechain/consensus/common/src/test/mocks/confirm_block_import_mock.rs new file mode 100644 index 0000000000..a810da2f3b --- /dev/null +++ b/bitacross-worker/sidechain/consensus/common/src/test/mocks/confirm_block_import_mock.rs @@ -0,0 +1,29 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{error::Result, ConfirmBlockImport}; +use itp_types::ShardIdentifier; +use its_primitives::types::header::SidechainHeader; + +/// Mock implementation of the `ConfirmBlockImport` trait. +pub struct ConfirmBlockImportMock; + +impl ConfirmBlockImport for ConfirmBlockImportMock { + fn confirm_import(&self, _header: &SidechainHeader, _shard: &ShardIdentifier) -> Result<()> { + Ok(()) + } +} diff --git a/bitacross-worker/sidechain/consensus/common/src/test/mocks/mod.rs b/bitacross-worker/sidechain/consensus/common/src/test/mocks/mod.rs new file mode 100644 index 0000000000..1408ce9402 --- /dev/null +++ b/bitacross-worker/sidechain/consensus/common/src/test/mocks/mod.rs @@ -0,0 +1,21 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 block_import_queue_worker_mock; +pub mod block_importer_mock; +pub mod confirm_block_import_mock; +pub mod verifier_mock; diff --git a/bitacross-worker/sidechain/consensus/common/src/test/mocks/verifier_mock.rs b/bitacross-worker/sidechain/consensus/common/src/test/mocks/verifier_mock.rs new file mode 100644 index 0000000000..e6d8cbeb0e --- /dev/null +++ b/bitacross-worker/sidechain/consensus/common/src/test/mocks/verifier_mock.rs @@ -0,0 +1,62 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{Result, ShardIdentifierFor, Verifier}; +use itp_types::H256; +use its_primitives::traits::SignedBlock as SignedSidechainBlockTrait; +use sp_core::Pair; +use sp_runtime::traits::Block as ParentchainBlockTrait; +use std::marker::PhantomData; + +/// Verifier mock implementation. +pub struct VerifierMock< + ParentchainBlock, + SignedSidechainBlock, + BlockImportParameters, + VerifierContext, +> { + _phantom: PhantomData<( + ParentchainBlock, + SignedSidechainBlock, + BlockImportParameters, + VerifierContext, + )>, +} + +impl + Verifier + for VerifierMock +where + ParentchainBlock: ParentchainBlockTrait, + SignedSidechainBlock: + SignedSidechainBlockTrait::Public> + 'static, + BlockImportParameters: Send + Sync, + VerifierContext: Send + Sync, +{ + type BlockImportParams = BlockImportParameters; + type Context = VerifierContext; + + fn verify( + &self, + _block: SignedSidechainBlock, + _parentchain_header: &ParentchainBlock::Header, + _shard: ShardIdentifierFor, + _ctx: &Self::Context, + ) -> Result { + todo!() + } +} diff --git a/bitacross-worker/sidechain/consensus/common/src/test/mod.rs b/bitacross-worker/sidechain/consensus/common/src/test/mod.rs new file mode 100644 index 0000000000..43e6cb274d --- /dev/null +++ b/bitacross-worker/sidechain/consensus/common/src/test/mod.rs @@ -0,0 +1,18 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 mocks; diff --git a/bitacross-worker/sidechain/consensus/slots/Cargo.toml b/bitacross-worker/sidechain/consensus/slots/Cargo.toml new file mode 100644 index 0000000000..41070d0af0 --- /dev/null +++ b/bitacross-worker/sidechain/consensus/slots/Cargo.toml @@ -0,0 +1,78 @@ +[package] +name = "its-consensus-slots" +version = "0.9.0" +authors = ['Trust Computing GmbH ', 'Integritee AG '] +edition = "2021" + + +[dependencies] +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +derive_more = "0.99.16" +lazy_static = { version = "1.1.0", features = ["spin_no_std"] } +log = { version = "0.4", default-features = false } + +# local deps +itp-types = { path = "../../../core-primitives/types", default-features = false } +its-block-verification = { path = "../../block-verification", default-features = false } +its-primitives = { path = "../../primitives", default-features = false } + +# only for slot-stream +futures-timer = { version = "3.0", optional = true } + +# sgx deps +sgx_tstd = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git", optional = true, features = ["untrusted_time"] } + +# substrate deps +sp-consensus-slots = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } +sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } + +# local deps +itp-settings = { path = "../../../core-primitives/settings" } +itp-time-utils = { path = "../../../core-primitives/time-utils", default-features = false } +its-consensus-common = { path = "../common", default-features = false } + +# litentry +hex = { version = "0.4", default-features = false } +itp-sgx-externalities = { path = "../../../core-primitives/substrate-sgx/externalities", default-features = false } +itp-stf-state-handler = { path = "../../../core-primitives/stf-state-handler", default-features = false } +its-state = { path = "../../state", default-features = false } +lc-scheduled-enclave = { path = "../../../litentry/core/scheduled-enclave", default-features = false } + + +[dev-dependencies] +itc-parentchain-test = { path = "../../../core/parentchain/test" } +its-test = { path = "../../test" } +sp-keyring = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } +itp-test = { path = "../../../core-primitives/test" } +tokio = { version = "1.6.1", features = ["full"] } + +[features] +default = ["std"] +std = [ + "codec/std", + "log/std", + # only for slot-stream + "futures-timer", + # substrate + "sp-consensus-slots/std", + "sp-runtime/std", + # local + "itp-time-utils/std", + "itp-types/std", + "its-primitives/std", + "its-block-verification/std", + "its-consensus-common/std", + "itp-stf-state-handler/std", + "itp-sgx-externalities/std", + "its-state/std", + "lc-scheduled-enclave/std", +] +sgx = [ + "itp-time-utils/sgx", + "its-consensus-common/sgx", + "sgx_tstd", + "itp-stf-state-handler/sgx", + "itp-sgx-externalities/sgx", + "its-state/sgx", + "lc-scheduled-enclave/sgx", +] diff --git a/bitacross-worker/sidechain/consensus/slots/src/lib.rs b/bitacross-worker/sidechain/consensus/slots/src/lib.rs new file mode 100644 index 0000000000..9c22327580 --- /dev/null +++ b/bitacross-worker/sidechain/consensus/slots/src/lib.rs @@ -0,0 +1,613 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +//! Slots functionality for the integritee-sidechain. +//! +//! Some consensus algorithms have a concept of *slots*, which are intervals in +//! time during which certain events can and/or must occur. This crate +//! provides generic functionality for slots. + +#![cfg_attr(not(feature = "std"), no_std)] +#![cfg_attr(test, feature(assert_matches))] + +#[cfg(all(feature = "std", feature = "sgx"))] +compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the same time"); + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +#[macro_use] +extern crate sgx_tstd as std; + +use codec::Encode; +use core::str::FromStr; +use derive_more::From; +use itp_sgx_externalities::SgxExternalities; +use itp_stf_state_handler::handle_state::HandleState; +use itp_time_utils::{duration_difference, duration_now}; + +use its_consensus_common::{Error as ConsensusError, Proposer}; +use its_primitives::traits::{ + Block as SidechainBlockTrait, Header as HeaderTrait, ShardIdentifierFor, + SignedBlock as SignedSidechainBlockTrait, +}; +use its_state::SidechainSystemExt; +use lc_scheduled_enclave::ScheduledEnclaveUpdater; +use log::*; +pub use slots::*; +use sp_runtime::traits::{Block as ParentchainBlockTrait, Header as ParentchainHeaderTrait}; +use std::{fmt::Debug, sync::Arc, time::Duration, vec::Vec}; + +#[cfg(feature = "std")] +mod slot_stream; +mod slots; + +#[cfg(feature = "sgx")] +use std::sync::SgxRwLock as RwLock; + +#[cfg(feature = "std")] +use std::sync::RwLock; + +#[cfg(test)] +mod mocks; + +#[cfg(test)] +mod per_shard_slot_worker_tests; + +use itp_types::parentchain::ParentchainCall; +#[cfg(feature = "std")] +pub use slot_stream::*; +pub use slots::*; + +/// The result of [`SlotWorker::on_slot`]. +#[derive(Debug, Clone, Encode, From)] +pub struct SlotResult { + /// The result of a slot operation. + pub block: SignedSidechainBlock, + /// Parentchain state transitions triggered by sidechain state transitions. + /// + /// Any sidechain stf that invokes a parentchain stf must not commit its state change + /// before the parentchain effect has been finalized. + pub parentchain_effects: Vec, +} + +pub struct FailSlotOnDemand { + // we need to keep a internal counter because node's slot number is a function of slot_beginning_timestamp and SLOT_DURATION + current_slot: RwLock, + fail_at_slot: u64, + mode: FailSlotMode, +} + +impl FailSlotOnDemand { + pub fn new(fail_at_slot: u64, mode: FailSlotMode) -> Self { + Self { current_slot: Default::default(), fail_at_slot, mode } + } + + pub fn next_slot(&self) { + let mut current_slot_lock = self.current_slot.write().unwrap(); + *current_slot_lock += 1; + } + + pub fn check_before_on_slot(&self) -> bool { + let current_slot = self.current_slot.read().unwrap(); + *current_slot == self.fail_at_slot && matches!(&self.mode, FailSlotMode::BeforeOnSlot) + } + + pub fn check_after_on_slot(&self) -> bool { + let current_slot = self.current_slot.read().unwrap(); + *current_slot == self.fail_at_slot && matches!(&self.mode, FailSlotMode::AfterOnSlot) + } +} + +#[derive(Clone, Debug, PartialEq)] +pub enum FailSlotMode { + BeforeOnSlot, + AfterOnSlot, +} + +impl FromStr for FailSlotMode { + type Err = &'static str; + + fn from_str(s: &str) -> Result { + match s { + "BeforeOnSlot" => Ok(FailSlotMode::BeforeOnSlot), + "AfterOnSlot" => Ok(FailSlotMode::AfterOnSlot), + _ => Err("no match"), + } + } +} + +/// A worker that should be invoked at every new slot for a specific shard. +/// +/// The implementation should not make any assumptions of the slot being bound to the time or +/// similar. The only valid assumption is that the slot number is always increasing. +pub trait SlotWorker { + /// Output generated after a slot + type Output: SignedSidechainBlockTrait + Send + 'static; + + /// Called when a new slot is triggered. + /// + /// Returns a [`SlotResult`] iff a block was successfully built in + /// the slot. Otherwise `None` is returned. + fn on_slot( + &mut self, + slot_info: SlotInfo, + shard: ShardIdentifierFor, + is_single_worker: bool, + ) -> Option>; +} + +/// A slot worker scheduler that should be invoked at every new slot. +/// +/// It manages the timeslots of individual per shard `SlotWorker`s. It gives each shard an equal +/// amount of time to produce it's result, equally distributing leftover time from a previous shard's +/// slot share to all subsequent slots. +pub trait PerShardSlotWorkerScheduler { + /// Output generated after a slot + type Output: Send + 'static; + + /// The shard type 'PerShardWorker's operate on. + type ShardIdentifier: Send + 'static + Debug + Clone; + + /// Called when a new slot is triggered. + /// + /// Returns a [`SlotResult`] iff a block was successfully built in + /// the slot. Otherwise `None` is returned. + fn on_slot( + &mut self, + slot_info: SlotInfo, + shard: Vec, + is_single_worker: bool, + ) -> Self::Output; +} + +/// A skeleton implementation for `SlotWorker` which tries to claim a slot at +/// its beginning and tries to produce a block if successfully claimed, timing +/// out if block production takes too long. +pub trait SimpleSlotWorker { + /// The type of proposer to use to build blocks. + type Proposer: Proposer; + + /// Data associated with a slot claim. + type Claim: Send + 'static; + + /// Epoch data necessary for authoring. + type EpochData: Send + 'static; + + /// Output generated after a slot + type Output: SignedSidechainBlockTrait + Send + 'static; + + /// Scheduled enclave context for authoring + type ScheduledEnclave: ScheduledEnclaveUpdater; + + /// State handler context for authoring + type StateHandler: HandleState; + + /// The logging target to use when logging messages. + fn logging_target(&self) -> &'static str; + + /// Get scheduled enclave + fn get_scheduled_enclave(&mut self) -> Arc; + + /// Get state handler for query and mutation + fn get_state_handler(&mut self) -> Arc; + + /// Returns the epoch data necessary for authoring. For time-dependent epochs, + /// use the provided slot number as a canonical source of time. + fn epoch_data( + &self, + header: &ParentchainBlock::Header, + shard: ShardIdentifierFor, + slot: Slot, + ) -> Result; + + /// Returns the number of authorities given the epoch data. + /// None indicate that the authorities information is incomplete. + fn authorities_len(&self, epoch_data: &Self::EpochData) -> Option; + + /// Tries to claim the given slot, returning an object with claim data if successful. + fn claim_slot( + &self, + header: &ParentchainBlock::Header, + slot: Slot, + epoch_data: &Self::EpochData, + ) -> Option; + + /// Creates the proposer for the current slot + fn proposer( + &mut self, + header: ParentchainBlock::Header, + shard: ShardIdentifierFor, + ) -> Result; + + /// Remaining duration for proposing. + fn proposing_remaining_duration(&self, slot_info: &SlotInfo) -> Duration; + + /// Trigger the import of the given parentchain block. + /// + /// Returns the header of the latest imported block. In case no block was imported with this trigger, + /// None is returned. + fn import_integritee_parentchain_blocks_until( + &self, + last_imported_parentchain_header: &::Hash, + ) -> Result, ConsensusError>; + + fn import_target_a_parentchain_blocks_until( + &self, + last_imported_parentchain_header: &::Hash, + ) -> Result, ConsensusError>; + + fn import_target_b_parentchain_blocks_until( + &self, + last_imported_parentchain_header: &::Hash, + ) -> Result, ConsensusError>; + + /// Peek the parentchain import queue for the latest block in queue. + /// Does not perform the import or mutate the queue. + fn peek_latest_integritee_parentchain_header( + &self, + ) -> Result, ConsensusError>; + + fn peek_latest_target_a_parentchain_header( + &self, + ) -> Result, ConsensusError>; + + fn peek_latest_target_b_parentchain_header( + &self, + ) -> Result, ConsensusError>; + + /// Implements [`SlotWorker::on_slot`]. This is an adaption from + /// substrate's sc-consensus-slots implementation. There, the slot worker handles all the + /// scheduling itself. Unfortunately, we can't use the same principle in the enclave due to some + /// futures-primitives not being available in sgx, e.g. `Delay` in our case. Hence, before + /// reimplementing the those things ourselves, we take a simplified approach and simply call + /// this function from the outside at each slot. + fn on_slot( + &mut self, + slot_info: SlotInfo, + shard: ShardIdentifierFor, + is_single_worker: bool, + ) -> Option> { + let (_timestamp, slot) = (slot_info.timestamp, slot_info.slot); + let logging_target = self.logging_target(); + + let remaining_duration = self.proposing_remaining_duration(&slot_info); + + if remaining_duration == Duration::default() { + debug!( + target: logging_target, + "Skipping proposal slot {} since there's no time left to propose", *slot, + ); + + return None + } + + let latest_integritee_parentchain_header = + match self.peek_latest_integritee_parentchain_header() { + Ok(Some(peeked_header)) => peeked_header, + Ok(None) => slot_info.last_imported_integritee_parentchain_head.clone(), + Err(e) => { + warn!( + target: logging_target, + "Failed to peek latest Integritee parentchain block header: {:?}", e + ); + return None + }, + }; + trace!( + target: logging_target, + "on_slot: a priori latest Integritee block number: {:?}", + latest_integritee_parentchain_header.number() + ); + // fixme: we need proper error handling here. we just assume there is no target_a if there is an error here, which is very brittle + let maybe_latest_target_a_parentchain_header = + match self.peek_latest_target_a_parentchain_header() { + Ok(Some(peeked_header)) => Some(peeked_header), + Ok(None) => slot_info.maybe_last_imported_target_a_parentchain_head.clone(), + Err(e) => { + debug!( + target: logging_target, + "Failed to peek latest target_a_parentchain block header: {:?}", e + ); + None + }, + }; + trace!( + target: logging_target, + "on_slot: a priori latest TargetA block number: {:?}", + maybe_latest_target_a_parentchain_header.clone().map(|h| *h.number()) + ); + + let maybe_latest_target_b_parentchain_header = + match self.peek_latest_target_b_parentchain_header() { + Ok(Some(peeked_header)) => Some(peeked_header), + Ok(None) => slot_info.maybe_last_imported_target_b_parentchain_head.clone(), + Err(e) => { + debug!( + target: logging_target, + "Failed to peek latest target_a_parentchain block header: {:?}", e + ); + None + }, + }; + trace!( + target: logging_target, + "on_slot: a priori latest TargetB block number: {:?}", + maybe_latest_target_b_parentchain_header.clone().map(|h| *h.number()) + ); + + let epoch_data = match self.epoch_data(&latest_integritee_parentchain_header, shard, slot) { + Ok(epoch_data) => epoch_data, + Err(e) => { + warn!( + target: logging_target, + "Unable to fetch epoch data at block {:?}: {:?}", + latest_integritee_parentchain_header.hash(), + e, + ); + + return None + }, + }; + + let authorities_len = self.authorities_len(&epoch_data); + + if !authorities_len.map(|a| a > 0).unwrap_or(false) { + debug!( + target: logging_target, + "Skipping proposal slot. Authorities len {:?}", authorities_len + ); + } + + // Return early if MRENCLAVE doesn't match - it implies that the enclave should be updated + let scheduled_enclave = self.get_scheduled_enclave(); + let state_handler = self.get_state_handler(); + // TODO: is this always consistent? Reference: `propose_state_update` in slot_proposer.rs + let (state, _) = state_handler.load_cloned(&shard.into()).ok()?; + let next_sidechain_number = state.get_block_number().map_or(1, |n| n + 1); + + if !scheduled_enclave.is_mrenclave_matching(next_sidechain_number) { + warn!( + target: logging_target, + "Skipping sidechain block {} due to mismatch MRENCLAVE, current: {:?}, expect: {:?}", + next_sidechain_number, + scheduled_enclave.get_current_mrenclave().map(hex::encode), + scheduled_enclave.get_expected_mrenclave(next_sidechain_number).map(hex::encode), + ); + if let Ok(false) = scheduled_enclave.is_block_production_paused() { + let _ = scheduled_enclave.set_block_production_paused(true); + info!("Pause sidechain block production"); + } + return None + } else { + // TODO: this block production pause/unpause is not strictly needed but I add it here as placeholder. + // Maybe we should add a field to describe the reason for pausing/unpausing, as + // it's possible that we want to manually/focibly pause the sidechain + if let Ok(true) = scheduled_enclave.is_block_production_paused() { + info!("Resume sidechain block production"); + let _ = scheduled_enclave.set_block_production_paused(false); + } + } + + // TODO: about the shard migration and state migration + // - the shard migration(copy-over) is done manually by the subcommand "migrate-shard". + // - the state migration is done via conditionally calling on_runtime_upgrade() by comparing + // the current runtime version and LastRuntimeUpgrade, see `stf_sgx.rs`. + // It means we need to bump the runtime version for the new enclave if we want the state + // migration to be executed. + + let _claim = self.claim_slot(&latest_integritee_parentchain_header, slot, &epoch_data)?; + + // Import the peeked parentchain header(s). + let last_imported_integritee_header = match self.import_integritee_parentchain_blocks_until( + &latest_integritee_parentchain_header.hash(), + ) { + Ok(h) => h, + Err(e) => { + debug!( + target: logging_target, + "Failed to import Integritee blocks until nr{:?}: {:?}", + latest_integritee_parentchain_header.number(), + e + ); + None + }, + }; + trace!( + target: logging_target, + "on_slot: a posteriori latest Integritee block number: {:?}", + last_imported_integritee_header.clone().map(|h| *h.number()) + ); + + let maybe_last_imported_target_a_header = + if let Some(ref header) = maybe_latest_target_a_parentchain_header { + match self.import_target_a_parentchain_blocks_until(&header.hash()) { + Ok(Some(h)) => Some(h), + Ok(None) => None, + Err(e) => { + debug!( + target: logging_target, + "Failed to import TargetA blocks until nr{:?}: {:?}", + header.number(), + e + ); + None + }, + } + } else { + None + }; + trace!( + target: logging_target, + "on_slot: a posteriori latest TargetA block number: {:?}", + maybe_last_imported_target_a_header.map(|h| *h.number()) + ); + + let maybe_last_imported_target_b_header = + if let Some(ref header) = maybe_latest_target_b_parentchain_header { + match self.import_target_b_parentchain_blocks_until(&header.hash()) { + Ok(Some(h)) => Some(h), + Ok(None) => None, + Err(e) => { + debug!( + target: logging_target, + "Failed to import TargetB blocks until nr{:?}: {:?}", + header.number(), + e + ); + None + }, + } + } else { + None + }; + + trace!( + target: logging_target, + "on_slot: a posteriori latest TargetB block number: {:?}", + maybe_last_imported_target_b_header.map(|h| *h.number()) + ); + + let proposer = match self.proposer(latest_integritee_parentchain_header.clone(), shard) { + Ok(p) => p, + Err(e) => { + warn!(target: logging_target, "Could not create proposer: {:?}", e); + return None + }, + }; + + let proposing = match proposer.propose(remaining_duration) { + Ok(p) => p, + Err(e) => { + warn!(target: logging_target, "Could not propose: {:?}", e); + return None + }, + }; + + if is_single_worker { + error!("Running as single worker, skipping timestamp within slot check") + } else if !timestamp_within_slot(&slot_info, &proposing.block) { + warn!( + target: logging_target, + "⌛️ Discarding proposal for slot {}, block number {}; block production took too long", + *slot, proposing.block.block().header().block_number(), + ); + + return None + } + + if last_imported_integritee_header.is_some() { + println!( + "Syncing Parentchains: Integritee: {:?} TargetA: {:?}, TargetB: {:?}, Sidechain: {:?}", + latest_integritee_parentchain_header.number(), + maybe_latest_target_a_parentchain_header.map(|h| *h.number()), + maybe_latest_target_b_parentchain_header.map(|h| *h.number()), + proposing.block.block().header().block_number() + ); + } + + info!("Proposing sidechain block (number: {}, hash: {}) based on integritee parentchain block (number: {:?}, hash: {:?})", + proposing.block.block().header().block_number(), proposing.block.hash(), + latest_integritee_parentchain_header.number(), latest_integritee_parentchain_header.hash() + ); + + Some(SlotResult { + block: proposing.block, + parentchain_effects: proposing.parentchain_effects, + }) + } +} + +impl + Send> + SlotWorker for T +{ + type Output = T::Output; + + fn on_slot( + &mut self, + slot_info: SlotInfo, + shard: ShardIdentifierFor, + is_single_worker: bool, + ) -> Option> { + SimpleSlotWorker::on_slot(self, slot_info, shard, is_single_worker) + } +} + +impl> + PerShardSlotWorkerScheduler for T +{ + type Output = Vec>; + + type ShardIdentifier = ShardIdentifierFor; + + fn on_slot( + &mut self, + slot_info: SlotInfo, + shards: Vec, + is_single_worker: bool, + ) -> Self::Output { + let logging_target = SimpleSlotWorker::logging_target(self); + + let mut remaining_shards = shards.len(); + let mut slot_results = Vec::with_capacity(remaining_shards); + + for shard in shards.into_iter() { + let now = duration_now(); // It's important we have a common `now` for all following computations. + let shard_remaining_duration = duration_difference(now, slot_info.ends_at) + .and_then(|time| time.checked_div(remaining_shards as u32)) + .unwrap_or_default(); + + // important to check against millis here. We had the corner-case in production + // setup where `shard_remaining_duration` contained only nanos. + if shard_remaining_duration.as_millis() == u128::default() { + info!( + target: logging_target, + "⌛️ Could not produce blocks for all shards; block production took too long", + ); + + return slot_results + } + + let shard_slot_ends_at = now + shard_remaining_duration; + let shard_slot = SlotInfo::new( + slot_info.slot, + now, + shard_remaining_duration, + shard_slot_ends_at, + slot_info.last_imported_integritee_parentchain_head.clone(), + slot_info.maybe_last_imported_target_a_parentchain_head.clone(), + slot_info.maybe_last_imported_target_b_parentchain_head.clone(), + ); + + match SimpleSlotWorker::on_slot(self, shard_slot.clone(), shard, is_single_worker) { + Some(res) => { + slot_results.push(res); + debug!( + target: logging_target, + "on_slot: produced block for slot: {:?} in shard {:?}", shard_slot, shard + ) + }, + None => info!( + target: logging_target, + "Did not propose a block for slot {} in shard {:?}", *slot_info.slot, shard + ), + } + + remaining_shards -= 1; + } + + slot_results + } +} diff --git a/bitacross-worker/sidechain/consensus/slots/src/mocks.rs b/bitacross-worker/sidechain/consensus/slots/src/mocks.rs new file mode 100644 index 0000000000..409fb41987 --- /dev/null +++ b/bitacross-worker/sidechain/consensus/slots/src/mocks.rs @@ -0,0 +1,158 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{slots::Slot, SimpleSlotWorker, SlotInfo, SlotResult}; +pub use itp_test::mock::handle_state_mock::HandleStateMock; +use its_consensus_common::{Proposal, Proposer, Result}; +use its_primitives::{traits::ShardIdentifierFor, types::SignedBlock as SignedSidechainBlock}; +use lc_scheduled_enclave::ScheduledEnclaveMock; +use sp_runtime::traits::{Block as ParentchainBlockTrait, Header as ParentchainHeaderTrait}; +use std::{marker::PhantomData, sync::Arc, thread, time::Duration}; + +#[derive(Default)] +pub(crate) struct ProposerMock { + _phantom: PhantomData, +} + +impl Proposer for ProposerMock +where + B: ParentchainBlockTrait, +{ + fn propose(&self, _max_duration: Duration) -> Result> { + todo!() + } +} + +#[derive(Default)] +pub(crate) struct SimpleSlotWorkerMock +where + B: ParentchainBlockTrait, +{ + pub slot_infos: Vec>, + pub slot_time_spent: Option, +} + +impl SimpleSlotWorker for SimpleSlotWorkerMock +where + B: ParentchainBlockTrait, +{ + type Proposer = ProposerMock; + + type Claim = u64; + + type EpochData = u64; + + type Output = SignedSidechainBlock; + + type ScheduledEnclave = ScheduledEnclaveMock; + + type StateHandler = HandleStateMock; + + fn logging_target(&self) -> &'static str { + "test" + } + + fn get_scheduled_enclave(&mut self) -> Arc { + todo!() + } + + fn get_state_handler(&mut self) -> Arc { + todo!() + } + + fn epoch_data( + &self, + _header: &B::Header, + _shard: ShardIdentifierFor, + _slot: Slot, + ) -> Result { + todo!() + } + + fn authorities_len(&self, _epoch_data: &Self::EpochData) -> Option { + todo!() + } + + fn claim_slot( + &self, + _header: &B::Header, + _slot: Slot, + _epoch_data: &Self::EpochData, + ) -> Option { + todo!() + } + + fn proposer( + &mut self, + _header: B::Header, + _shard: ShardIdentifierFor, + ) -> Result { + todo!() + } + + fn proposing_remaining_duration(&self, _slot_info: &SlotInfo) -> Duration { + todo!() + } + + fn import_integritee_parentchain_blocks_until( + &self, + _last_imported_parentchain_header: &::Hash, + ) -> Result> { + todo!() + } + + fn peek_latest_integritee_parentchain_header(&self) -> Result> { + todo!() + } + + fn import_target_a_parentchain_blocks_until( + &self, + _last_imported_parentchain_header: &::Hash, + ) -> Result> { + todo!() + } + + fn peek_latest_target_a_parentchain_header(&self) -> Result> { + todo!() + } + + fn import_target_b_parentchain_blocks_until( + &self, + _last_imported_parentchain_header: &::Hash, + ) -> Result> { + todo!() + } + + fn peek_latest_target_b_parentchain_header(&self) -> Result> { + todo!() + } + + fn on_slot( + &mut self, + slot_info: SlotInfo, + _shard: ShardIdentifierFor, + _is_single_worker: bool, + ) -> Option> { + self.slot_infos.push(slot_info); + + if let Some(sleep_duration) = self.slot_time_spent { + thread::sleep(sleep_duration); + } + + None + } +} diff --git a/bitacross-worker/sidechain/consensus/slots/src/per_shard_slot_worker_tests.rs b/bitacross-worker/sidechain/consensus/slots/src/per_shard_slot_worker_tests.rs new file mode 100644 index 0000000000..b9bcaf92f0 --- /dev/null +++ b/bitacross-worker/sidechain/consensus/slots/src/per_shard_slot_worker_tests.rs @@ -0,0 +1,100 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{mocks::SimpleSlotWorkerMock, PerShardSlotWorkerScheduler, SlotInfo}; +use itc_parentchain_test::ParentchainHeaderBuilder; +use itp_settings::sidechain::SLOT_DURATION; +use itp_time_utils::duration_now; +use itp_types::{Block as ParentchainBlock, ShardIdentifier}; +use its_block_verification::slot::slot_from_timestamp_and_duration; + +type TestSlotWorker = SimpleSlotWorkerMock; + +#[test] +fn slot_timings_are_correct_with_multiple_shards() { + let slot_info = slot_info_from_now(); + let mut slot_worker = + TestSlotWorker { slot_infos: Vec::new(), slot_time_spent: Some(SLOT_DURATION / 10) }; + + let shards = + vec![ShardIdentifier::default(), ShardIdentifier::default(), ShardIdentifier::default()]; + + let _slot_results = PerShardSlotWorkerScheduler::on_slot( + &mut slot_worker, + slot_info.clone(), + shards.clone(), + false, + ); + + assert_eq!(slot_worker.slot_infos.len(), shards.len()); + + // end-time of the first shard slot should not exceed timestamp + 1/(n_shards) of the total slot duration + let first_shard_slot_end_time = slot_worker.slot_infos.first().unwrap().ends_at.as_millis(); + let expected_upper_bound = (slot_info.timestamp.as_millis() + + SLOT_DURATION.as_millis().checked_div(shards.len() as u128).unwrap()) + + 2u128; + assert!( + first_shard_slot_end_time <= expected_upper_bound, + "First shard end time, expected: {}, actual: {}", + expected_upper_bound, + first_shard_slot_end_time + ); + + // none of the shard slot end times should exceed the global slot end time + for shard_slot_info in slot_worker.slot_infos { + assert!( + shard_slot_info.ends_at.as_millis() <= slot_info.ends_at.as_millis(), + "shard slot info ends at: {} ms, total slot info ends at: {} ms", + shard_slot_info.ends_at.as_millis(), + slot_info.ends_at.as_millis() + ); + } +} + +#[test] +fn if_shard_takes_up_all_slot_time_subsequent_shards_are_not_served() { + let slot_info = slot_info_from_now(); + let mut slot_worker = + TestSlotWorker { slot_infos: Vec::new(), slot_time_spent: Some(SLOT_DURATION) }; + + let shards = + vec![ShardIdentifier::default(), ShardIdentifier::default(), ShardIdentifier::default()]; + + let _slot_results = PerShardSlotWorkerScheduler::on_slot( + &mut slot_worker, + slot_info.clone(), + shards.clone(), + false, + ); + + assert_eq!(1, slot_worker.slot_infos.len()); +} + +fn slot_info_from_now() -> SlotInfo { + let timestamp_now = duration_now(); + let slot = slot_from_timestamp_and_duration(timestamp_now, SLOT_DURATION); + let slot_ends_at = timestamp_now + SLOT_DURATION; + SlotInfo::new( + slot, + timestamp_now, + SLOT_DURATION, + slot_ends_at, + ParentchainHeaderBuilder::default().build(), + None, + None, + ) +} diff --git a/bitacross-worker/sidechain/consensus/slots/src/slot_stream.rs b/bitacross-worker/sidechain/consensus/slots/src/slot_stream.rs new file mode 100644 index 0000000000..1c738419bf --- /dev/null +++ b/bitacross-worker/sidechain/consensus/slots/src/slot_stream.rs @@ -0,0 +1,116 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +//! Slots functionality for Substrate. +//! +//! Some consensus algorithms have a concept of *slots*, which are intervals in +//! time during which certain events can and/or must occur. This crate +//! provides generic functionality for slots. + +use crate::time_until_next_slot; +use futures_timer::Delay; +use std::time::Duration; + +/// Executes given `task` repeatedly when the next slot becomes available. +pub async fn start_slot_worker(task: F, slot_duration: Duration) +where + F: Fn(), +{ + let mut slot_stream = SlotStream::new(slot_duration); + + loop { + slot_stream.next_slot().await; + task(); + } +} + +/// Stream to calculate the slot schedule with. +pub struct SlotStream { + slot_duration: Duration, + inner_delay: Option, +} + +impl SlotStream { + pub fn new(slot_duration: Duration) -> Self { + SlotStream { slot_duration, inner_delay: None } + } +} + +impl SlotStream { + /// Waits for the duration of `inner_delay`. + /// Upon timeout, `inner_delay` is reset according to the time left until next slot. + pub async fn next_slot(&mut self) { + self.inner_delay = match self.inner_delay.take() { + None => { + // Delay is not initialized in this case, + // so we have to initialize with the time until the next slot. + let wait_dur = time_until_next_slot(self.slot_duration); + Some(Delay::new(wait_dur)) + }, + Some(d) => Some(d), + }; + + if let Some(inner_delay) = self.inner_delay.take() { + inner_delay.await; + } + + let ends_in = time_until_next_slot(self.slot_duration); + + // Re-schedule delay for next slot. + self.inner_delay = Some(Delay::new(ends_in)); + } +} + +#[cfg(test)] +mod tests { + use super::*; + use std::{thread, time::Instant}; + + const SLOT_DURATION: Duration = Duration::from_millis(300); + const SLOT_TOLERANCE: Duration = Duration::from_millis(10); + + #[tokio::test] + async fn short_task_execution_does_not_influence_next_slot() { + let mut slot_stream = SlotStream::new(SLOT_DURATION); + + slot_stream.next_slot().await; + let now = Instant::now(); + // Task execution is shorter than slot duration. + thread::sleep(Duration::from_millis(200)); + slot_stream.next_slot().await; + + let elapsed = now.elapsed(); + assert!(elapsed >= SLOT_DURATION - SLOT_TOLERANCE); + assert!(elapsed <= SLOT_DURATION + SLOT_TOLERANCE); + } + + #[tokio::test] + async fn long_task_execution_does_not_cause_drift() { + let mut slot_stream = SlotStream::new(SLOT_DURATION); + + slot_stream.next_slot().await; + let now = Instant::now(); + // Task execution is longer than slot duration. + thread::sleep(Duration::from_millis(500)); + slot_stream.next_slot().await; + slot_stream.next_slot().await; + + let elapsed = now.elapsed(); + assert!(elapsed >= 2 * SLOT_DURATION - SLOT_TOLERANCE); + assert!(elapsed <= 2 * SLOT_DURATION + SLOT_TOLERANCE); + } +} diff --git a/bitacross-worker/sidechain/consensus/slots/src/slots.rs b/bitacross-worker/sidechain/consensus/slots/src/slots.rs new file mode 100644 index 0000000000..7f8a910a97 --- /dev/null +++ b/bitacross-worker/sidechain/consensus/slots/src/slots.rs @@ -0,0 +1,421 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 stream for yielding slots in a loop. +//! +//! This is used instead of `futures_timer::Interval` because it was unreliable. + +use itp_time_utils::duration_now; +use its_block_verification::slot::slot_from_timestamp_and_duration; +use its_consensus_common::Error as ConsensusError; +use its_primitives::traits::{ + Block as SidechainBlockTrait, BlockData, SignedBlock as SignedSidechainBlockTrait, +}; +use lazy_static::lazy_static; +use log::warn; +use sp_runtime::traits::Block as ParentchainBlockTrait; +use std::time::Duration; + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +use std::sync::SgxRwLock as RwLock; + +#[cfg(all(feature = "std", not(feature = "sgx")))] +use std::sync::RwLock; + +pub use sp_consensus_slots::Slot; + +/// Returns the duration until the next slot from now. +pub fn time_until_next_slot(slot_duration: Duration) -> Duration { + let now = duration_now().as_millis(); + + if slot_duration.as_millis() == u128::default() { + log::warn!("[Slots]: slot_duration.as_millis() is 0"); + return Default::default() + } + + let next_slot = (now + slot_duration.as_millis()) / slot_duration.as_millis(); + let remaining_millis = next_slot * slot_duration.as_millis() - now; + Duration::from_millis(remaining_millis as u64) +} + +/// Information about a slot. +#[derive(Debug, Clone)] +pub struct SlotInfo { + /// The slot number as found in the inherent data. + pub slot: Slot, + /// Current timestamp as found in the inherent data. + pub timestamp: Duration, + /// Slot duration. + pub duration: Duration, + /// The time at which the slot ends. + pub ends_at: Duration, + /// Last imported parentchain header, potentially outdated. + pub last_imported_integritee_parentchain_head: ParentchainBlock::Header, + /// Last imported parentchain header, potentially outdated. + pub maybe_last_imported_target_a_parentchain_head: Option, + /// Last imported parentchain header, potentially outdated. + pub maybe_last_imported_target_b_parentchain_head: Option, +} + +impl SlotInfo { + /// Create a new [`SlotInfo`]. + /// + /// `ends_at` is calculated using `now` and `time_until_next_slot`. + pub fn new( + slot: Slot, + timestamp: Duration, + duration: Duration, + ends_at: Duration, + last_imported_integritee_parentchain_head: ParentchainBlock::Header, + maybe_last_imported_target_a_parentchain_head: Option, + maybe_last_imported_target_b_parentchain_head: Option, + ) -> Self { + Self { + slot, + timestamp, + duration, + ends_at, + last_imported_integritee_parentchain_head, + maybe_last_imported_target_a_parentchain_head, + maybe_last_imported_target_b_parentchain_head, + } + } + + pub fn duration_remaining(&self) -> Option { + let duration_now = duration_now(); + if self.ends_at <= duration_now { + return None + } + Some(self.ends_at - duration_now) + } +} + +/// The time at which the slot ends. +/// +/// !! Slot duration needs to be the 'global' slot duration that is used for the sidechain. +/// Do not use this with 'custom' slot durations, as used e.g. for the shard slots. +pub fn slot_ends_at(slot: Slot, slot_duration: Duration) -> Duration { + Duration::from_millis(*slot.saturating_add(1u64) * (slot_duration.as_millis() as u64)) +} + +#[allow(dead_code)] +pub(crate) fn timestamp_within_slot< + ParentchainBlock: ParentchainBlockTrait, + SignedSidechainBlock: SignedSidechainBlockTrait, +>( + slot: &SlotInfo, + proposal: &SignedSidechainBlock, +) -> bool { + let proposal_stamp = proposal.block().block_data().timestamp(); + + let is_within_slot = slot.timestamp.as_millis() as u64 <= proposal_stamp + && slot.ends_at.as_millis() as u64 >= proposal_stamp; + + if !is_within_slot { + warn!( + "Proposed block slot time: {} ms, slot start: {} ms , slot end: {} ms", + proposal_stamp, + slot.timestamp.as_millis(), + slot.ends_at.as_millis() + ); + } + + is_within_slot +} + +pub fn yield_next_slot( + timestamp: Duration, + duration: Duration, + integritee_header: ParentchainBlock::Header, + maybe_target_a_header: Option, + maybe_target_b_header: Option, + last_slot_getter: &mut SlotGetter, +) -> Result>, ConsensusError> +where + SlotGetter: LastSlotTrait, + ParentchainBlock: ParentchainBlockTrait, +{ + if duration == Default::default() { + return Err(ConsensusError::Other("Tried to yield next slot with 0 duration".into())) + } + + let last_slot = last_slot_getter.get_last_slot()?; + let slot = slot_from_timestamp_and_duration(timestamp, duration); + + if slot <= last_slot { + return Ok(None) + } + + last_slot_getter.set_last_slot(slot)?; + + let slot_ends_time = slot_ends_at(slot, duration); + Ok(Some(SlotInfo::new( + slot, + timestamp, + duration, + slot_ends_time, + integritee_header, + maybe_target_a_header, + maybe_target_b_header, + ))) +} + +pub trait LastSlotTrait { + fn get_last_slot(&self) -> Result; + fn set_last_slot(&mut self, slot: Slot) -> Result<(), ConsensusError>; +} + +pub struct LastSlot; + +lazy_static! { + static ref LAST_SLOT: RwLock = Default::default(); +} + +impl LastSlotTrait for LastSlot { + fn get_last_slot(&self) -> Result { + Ok(*LAST_SLOT.read().map_err(|e| ConsensusError::Other(format!("{:?}", e).into()))?) + } + + fn set_last_slot(&mut self, slot: Slot) -> Result<(), ConsensusError> { + *LAST_SLOT + .write() + .map_err(|e| ConsensusError::Other(format!("{:?}", e).into()))? = slot; + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use core::assert_matches::assert_matches; + use itc_parentchain_test::ParentchainHeaderBuilder; + use itp_types::Block as ParentchainBlock; + use its_primitives::{ + traits::{Block as BlockT, SignBlock}, + types::block::{Block, SignedBlock}, + }; + use its_test::{ + sidechain_block_data_builder::SidechainBlockDataBuilder, + sidechain_header_builder::SidechainHeaderBuilder, + }; + use sp_keyring::ed25519::Keyring; + use std::{fmt::Debug, thread, time::SystemTime}; + + const SLOT_DURATION: Duration = Duration::from_millis(1000); + const ALLOWED_THRESHOLD: Duration = Duration::from_millis(1); + + fn test_block_with_time_stamp(timestamp: u64) -> SignedBlock { + let header = SidechainHeaderBuilder::default().build(); + + let block_data = SidechainBlockDataBuilder::default().with_timestamp(timestamp).build(); + + Block::new(header, block_data).sign_block(&Keyring::Alice.pair()) + } + + fn slot(slot: u64) -> SlotInfo { + SlotInfo { + slot: slot.into(), + timestamp: duration_now(), + duration: SLOT_DURATION, + ends_at: duration_now() + SLOT_DURATION, + last_imported_integritee_parentchain_head: ParentchainHeaderBuilder::default().build(), + maybe_last_imported_target_a_parentchain_head: None, + maybe_last_imported_target_b_parentchain_head: None, + } + } + + fn timestamp_in_the_future(later: Duration) -> u64 { + let moment = SystemTime::now() + later; + let dur = moment.duration_since(SystemTime::UNIX_EPOCH).unwrap_or_else(|e| { + panic!("Current time {:?} is before unix epoch. Something is wrong: {:?}", moment, e) + }); + dur.as_millis() as u64 + } + + fn timestamp_in_the_past(earlier: Duration) -> u64 { + let moment = SystemTime::now() - earlier; + let dur = moment.duration_since(SystemTime::UNIX_EPOCH).unwrap_or_else(|e| { + panic!("Current time {:?} is before unix epoch. Something is wrong: {:?}", moment, e) + }); + dur.as_millis() as u64 + } + + fn assert_consensus_other_err(result: Result, msg: &str) { + assert_matches!(result.unwrap_err(), ConsensusError::Other( + m, + ) if m.to_string() == msg) + } + + #[test] + fn time_until_next_slot_returns_default_on_nano_duration() { + // prevent panic: https://github.com/integritee-network/worker/issues/439 + assert_eq!(time_until_next_slot(Duration::from_nanos(999)), Default::default()) + } + + #[test] + fn slot_info_ends_at_does_not_change_after_second_calculation() { + let timestamp = duration_now(); + let pc_header = ParentchainHeaderBuilder::default().build(); + let slot: Slot = 1000.into(); + + let slot_end_time = slot_ends_at(slot, SLOT_DURATION); + let slot_one: SlotInfo = SlotInfo::new( + slot, + timestamp, + SLOT_DURATION, + slot_end_time, + pc_header.clone(), + None, + None, + ); + thread::sleep(Duration::from_millis(200)); + let slot_two: SlotInfo = + SlotInfo::new(slot, timestamp, SLOT_DURATION, slot_end_time, pc_header, None, None); + + let difference_of_ends_at = + (slot_one.ends_at.as_millis()).abs_diff(slot_two.ends_at.as_millis()); + + assert!( + difference_of_ends_at < ALLOWED_THRESHOLD.as_millis(), + "Diff in ends at timestamp: {} ms, tolerance: {} ms", + difference_of_ends_at, + ALLOWED_THRESHOLD.as_millis() + ); + } + + #[test] + fn duration_remaing_returns_none_if_ends_at_is_in_the_past() { + let slot: SlotInfo = SlotInfo { + slot: 1.into(), + timestamp: duration_now() - Duration::from_secs(5), + duration: SLOT_DURATION, + ends_at: duration_now() + SLOT_DURATION - Duration::from_secs(5), + last_imported_integritee_parentchain_head: ParentchainHeaderBuilder::default().build(), + maybe_last_imported_target_a_parentchain_head: None, + maybe_last_imported_target_b_parentchain_head: None, + }; + assert!(slot.duration_remaining().is_none()); + } + + #[test] + fn duration_remaining_returns_some_if_ends_at_is_in_the_future() { + let slot: SlotInfo = SlotInfo { + slot: 1.into(), + timestamp: duration_now() - Duration::from_secs(5), + duration: SLOT_DURATION, + ends_at: duration_now() + Duration::from_secs(60), + last_imported_integritee_parentchain_head: ParentchainHeaderBuilder::default().build(), + maybe_last_imported_target_a_parentchain_head: None, + maybe_last_imported_target_b_parentchain_head: None, + }; + let maybe_duration_remaining = slot.duration_remaining(); + assert!(maybe_duration_remaining.is_some()); + assert!(maybe_duration_remaining.unwrap() > Duration::from_secs(30)); + } + + #[test] + fn slot_info_ends_at_does_is_correct_even_if_delay_is_more_than_slot_duration() { + let timestamp = duration_now(); + let pc_header = ParentchainHeaderBuilder::default().build(); + let slot: Slot = 1000.into(); + let slot_end_time = slot_ends_at(slot, SLOT_DURATION); + + thread::sleep(SLOT_DURATION * 2); + let slot: SlotInfo = + SlotInfo::new(slot, timestamp, SLOT_DURATION, slot_end_time, pc_header, None, None); + + assert!(slot.ends_at < duration_now()); + } + + #[test] + fn timestamp_within_slot_returns_true_for_correct_timestamp() { + let slot = slot(1); + let time_stamp_in_slot = timestamp_in_the_future(SLOT_DURATION / 2); + + let block = test_block_with_time_stamp(time_stamp_in_slot); + + assert!(timestamp_within_slot(&slot, &block)); + } + + #[test] + fn timestamp_within_slot_returns_false_if_timestamp_after_slot() { + let slot = slot(1); + let time_stamp_after_slot = + timestamp_in_the_future(SLOT_DURATION + Duration::from_millis(10)); + + let block_too_late = test_block_with_time_stamp(time_stamp_after_slot); + + assert!(!timestamp_within_slot(&slot, &block_too_late)); + } + + #[test] + fn timestamp_within_slot_returns_false_if_timestamp_before_slot() { + let slot = slot(1); + let time_stamp_before_slot = timestamp_in_the_past(Duration::from_millis(10)); + + let block_too_early = test_block_with_time_stamp(time_stamp_before_slot); + + assert!(!timestamp_within_slot(&slot, &block_too_early)); + } + + #[test] + fn yield_next_slot_returns_none_when_slot_equals_last_slot() { + let _lock = + LastSlot.set_last_slot(slot_from_timestamp_and_duration(duration_now(), SLOT_DURATION)); + assert!(yield_next_slot::<_, ParentchainBlock>( + duration_now(), + SLOT_DURATION, + ParentchainHeaderBuilder::default().build(), + None, + None, + &mut LastSlot, + ) + .unwrap() + .is_none()) + } + + #[test] + fn yield_next_slot_returns_next_slot() { + let _lock = + LastSlot.set_last_slot(slot_from_timestamp_and_duration(duration_now(), SLOT_DURATION)); + assert!(yield_next_slot::<_, ParentchainBlock>( + duration_now() + SLOT_DURATION, + SLOT_DURATION, + ParentchainHeaderBuilder::default().build(), + None, + None, + &mut LastSlot + ) + .unwrap() + .is_some()) + } + + #[test] + fn yield_next_slot_returns_err_on_0_duration() { + assert_consensus_other_err( + yield_next_slot::<_, ParentchainBlock>( + duration_now(), + Default::default(), + ParentchainHeaderBuilder::default().build(), + None, + None, + &mut LastSlot, + ), + "Tried to yield next slot with 0 duration", + ) + } +} diff --git a/bitacross-worker/sidechain/fork-tree/Cargo.toml b/bitacross-worker/sidechain/fork-tree/Cargo.toml new file mode 100644 index 0000000000..6b9c4fc561 --- /dev/null +++ b/bitacross-worker/sidechain/fork-tree/Cargo.toml @@ -0,0 +1,27 @@ +[package] +name = "fork-tree" +version = "3.0.0" +authors = ["Parity Technologies "] +edition = "2021" +license = "Apache-2.0" +homepage = "https://substrate.io" +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" +readme = "README.md" + +[dependencies] +codec = { package = "parity-scale-codec", version = "3.2.2", features = ["derive"], default-features = false } + +# sgx deps +sgx_tstd = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git", optional = true } + +[features] +default = ["std"] +std = [ + "codec/std", +] +sgx = [ + # teaclave + "sgx_tstd", +] diff --git a/bitacross-worker/sidechain/fork-tree/src/lib.rs b/bitacross-worker/sidechain/fork-tree/src/lib.rs new file mode 100644 index 0000000000..0af11b653b --- /dev/null +++ b/bitacross-worker/sidechain/fork-tree/src/lib.rs @@ -0,0 +1,1552 @@ +// This file is part of Substrate. + +// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT 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. + +#![cfg_attr(not(feature = "std"), no_std)] +#![warn(missing_docs)] + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +#[macro_use] +extern crate sgx_tstd as std; + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +use std::vec::Vec; + +use codec::{Decode, Encode}; +use core::cmp::Reverse; + +/// Error occurred when iterating with the tree. +#[derive(Clone, Debug, PartialEq)] +pub enum Error { + /// Adding duplicate node to tree. + Duplicate, + /// Finalizing descendent of tree node without finalizing ancestor(s). + UnfinalizedAncestor, + /// Imported or finalized node that is an ancestor of previously finalized node. + Revert, + /// Error throw by client when checking for node ancestry. + Client(E), +} + +impl std::fmt::Display for Error { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + let message = match *self { + Error::Duplicate => "Hash already exists in Tree".into(), + Error::UnfinalizedAncestor => "Finalized descendent of Tree node without finalizing its ancestor(s) first".into(), + Error::Revert => "Tried to import or finalize node that is an ancestor of a previously finalized node".into(), + Error::Client(ref err) => format!("Client error: {}", err), + }; + write!(f, "{}", message) + } +} + +impl std::error::Error for Error { + fn cause(&self) -> Option<&dyn std::error::Error> { + None + } +} + +impl From for Error { + fn from(err: E) -> Error { + Error::Client(err) + } +} + +/// Result of finalizing a node (that could be a part of the tree or not). +#[derive(Debug, PartialEq)] +pub enum FinalizationResult { + /// The tree has changed, optionally return the value associated with the finalized node. + Changed(Option), + /// The tree has not changed. + Unchanged, +} + +/// Filtering action. +#[derive(Debug, PartialEq)] +pub enum FilterAction { + /// Remove the node and its subtree. + Remove, + /// Maintain the node. + KeepNode, + /// Maintain the node and its subtree. + KeepTree, +} + +/// A tree data structure that stores several nodes across multiple branches. +/// +/// Top-level branches are called roots. The tree has functionality for +/// finalizing nodes, which means that that node is traversed, and all competing +/// branches are pruned. It also guarantees that nodes in the tree are finalized +/// in order. Each node is uniquely identified by its hash but can be ordered by +/// its number. In order to build the tree an external function must be provided +/// when interacting with the tree to establish a node's ancestry. +#[derive(Clone, Debug, Decode, Encode, PartialEq)] +pub struct ForkTree { + roots: Vec>, + best_finalized_number: Option, +} + +impl Default for ForkTree { + fn default() -> ForkTree { + ForkTree { roots: Vec::new(), best_finalized_number: None } + } +} + +impl ForkTree +where + H: PartialEq, + N: Ord, +{ + /// Create a new empty tree. + pub fn new() -> ForkTree { + ForkTree { roots: Vec::new(), best_finalized_number: None } + } + + /// Rebalance the tree, i.e. sort child nodes by max branch depth (decreasing). + /// + /// Most operations in the tree are performed with depth-first search + /// starting from the leftmost node at every level, since this tree is meant + /// to be used in a blockchain context, a good heuristic is that the node + /// we'll be looking for at any point will likely be in one of the deepest chains + /// (i.e. the longest ones). + pub fn rebalance(&mut self) { + self.roots.sort_by_key(|n| Reverse(n.max_depth())); + let mut stack: Vec<_> = self.roots.iter_mut().collect(); + while let Some(node) = stack.pop() { + node.children.sort_by_key(|n| Reverse(n.max_depth())); + stack.extend(node.children.iter_mut()); + } + } + + /// Import a new node into the tree. The given function `is_descendent_of` + /// should return `true` if the second hash (target) is a descendent of the + /// first hash (base). This method assumes that nodes in the same branch are + /// imported in order. + /// + /// Returns `true` if the imported node is a root. + // WARNING: some users of this method (i.e. consensus epoch changes tree) currently silently + // rely on a **post-order DFS** traversal. If we are using instead a top-down traversal method + // then the `is_descendent_of` closure, when used after a warp-sync, may end up querying the + // backend for a block (the one corresponding to the root) that is not present and thus will + // return a wrong result. + pub fn import( + &mut self, + hash: H, + number: N, + data: V, + is_descendent_of: &F, + ) -> Result> + where + E: std::error::Error, + F: Fn(&H, &H) -> Result, + H: std::fmt::Debug, + { + if let Some(ref best_finalized_number) = self.best_finalized_number { + if number <= *best_finalized_number { + return Err(Error::Revert) + } + } + + let (children, is_root) = + match self.find_node_where_mut(&hash, &number, is_descendent_of, &|_| true)? { + Some(parent) => (&mut parent.children, false), + None => (&mut self.roots, true), + }; + + if children.iter().any(|elem| elem.hash == hash) { + return Err(Error::Duplicate) + } + + children.push(Node { data, hash, number, children: Default::default() }); + + if children.len() == 1 { + // Rebalance may be required only if we've extended the branch depth. + self.rebalance(); + } + + Ok(is_root) + } + + /// Iterates over the existing roots in the tree. + pub fn roots(&self) -> impl Iterator { + self.roots.iter().map(|node| (&node.hash, &node.number, &node.data)) + } + + /// Iterates over the roots and gives just the hash and block number + pub fn roots_hash_and_number(&self) -> Vec<(&H, &N)> { + self.roots.iter().map(|node| (&node.hash, &node.number)).collect::>() + } + + fn node_iter(&self) -> impl Iterator> { + // we need to reverse the order of roots to maintain the expected + // ordering since the iterator uses a stack to track state. + ForkTreeIterator { stack: self.roots.iter().rev().collect() } + } + + /// Iterates the nodes in the tree in pre-order. + pub fn iter(&self) -> impl Iterator { + self.node_iter().map(|node| (&node.hash, &node.number, &node.data)) + } + + /// Map fork tree into values of new types. + /// + /// Tree traversal technique (e.g. BFS vs DFS) is left as not specified and + /// may be subject to change in the future. In other words, your predicates + /// should not rely on the observed traversal technique currently in use. + pub fn map(self, f: &mut F) -> ForkTree + where + F: FnMut(&H, &N, V) -> VT, + { + let mut queue: Vec<_> = + self.roots.into_iter().rev().map(|node| (usize::MAX, node)).collect(); + let mut next_queue = Vec::new(); + let mut output = Vec::new(); + + while !queue.is_empty() { + for (parent_index, node) in queue.drain(..) { + let new_data = f(&node.hash, &node.number, node.data); + let new_node = Node { + hash: node.hash, + number: node.number, + data: new_data, + children: Vec::with_capacity(node.children.len()), + }; + + let node_id = output.len(); + output.push((parent_index, new_node)); + + for child in node.children.into_iter().rev() { + next_queue.push((node_id, child)); + } + } + + std::mem::swap(&mut queue, &mut next_queue); + } + + let mut roots = Vec::new(); + while let Some((parent_index, new_node)) = output.pop() { + if parent_index == usize::MAX { + roots.push(new_node); + } else { + output[parent_index].1.children.push(new_node); + } + } + + ForkTree { roots, best_finalized_number: self.best_finalized_number } + } + + /// Find a node in the tree that is the deepest ancestor of the given + /// block hash and which passes the given predicate. The given function + /// `is_descendent_of` should return `true` if the second hash (target) + /// is a descendent of the first hash (base). + pub fn find_node_where( + &self, + hash: &H, + number: &N, + is_descendent_of: &F, + predicate: &P, + ) -> Result>, Error> + where + E: std::error::Error, + F: Fn(&H, &H) -> Result, + P: Fn(&V) -> bool, + { + let maybe_path = self.find_node_index_where(hash, number, is_descendent_of, predicate)?; + Ok(maybe_path.map(|path| { + let children = + path.iter().take(path.len() - 1).fold(&self.roots, |curr, &i| &curr[i].children); + &children[path[path.len() - 1]] + })) + } + + /// Same as [`find_node_where`](ForkTree::find_node_where), but returns mutable reference. + pub fn find_node_where_mut( + &mut self, + hash: &H, + number: &N, + is_descendent_of: &F, + predicate: &P, + ) -> Result>, Error> + where + E: std::error::Error, + F: Fn(&H, &H) -> Result, + P: Fn(&V) -> bool, + { + let maybe_path = self.find_node_index_where(hash, number, is_descendent_of, predicate)?; + Ok(maybe_path.map(|path| { + let children = path + .iter() + .take(path.len() - 1) + .fold(&mut self.roots, |curr, &i| &mut curr[i].children); + &mut children[path[path.len() - 1]] + })) + } + + /// Same as [`find_node_where`](ForkTree::find_node_where), but returns indices. + /// + /// The returned indices represent the full path to reach the matching node starting + /// from first to last, i.e. the earliest index in the traverse path goes first, and the final + /// index in the traverse path goes last. If a node is found that matches the predicate + /// the returned path should always contain at least one index, otherwise `None` is + /// returned. + // WARNING: some users of this method (i.e. consensus epoch changes tree) currently silently + // rely on a **post-order DFS** traversal. If we are using instead a top-down traversal method + // then the `is_descendent_of` closure, when used after a warp-sync, will end up querying the + // backend for a block (the one corresponding to the root) that is not present and thus will + // return a wrong result. + pub fn find_node_index_where( + &self, + hash: &H, + number: &N, + is_descendent_of: &F, + predicate: &P, + ) -> Result>, Error> + where + E: std::error::Error, + F: Fn(&H, &H) -> Result, + P: Fn(&V) -> bool, + { + let mut stack = vec![]; + let mut root_idx = 0; + let mut found = false; + let mut is_descendent = false; + + while root_idx < self.roots.len() { + if *number <= self.roots[root_idx].number { + root_idx += 1; + continue + } + // The second element in the stack tuple tracks what is the **next** children + // index to search into. If we find an ancestor then we stop searching into + // alternative branches and we focus on the current path up to the root. + stack.push((&self.roots[root_idx], 0)); + while let Some((node, i)) = stack.pop() { + if i < node.children.len() && !is_descendent { + stack.push((node, i + 1)); + if node.children[i].number < *number { + stack.push((&node.children[i], 0)); + } + } else if is_descendent || is_descendent_of(&node.hash, hash)? { + is_descendent = true; + if predicate(&node.data) { + found = true; + break + } + } + } + + // If the element we are looking for is a descendent of the current root + // then we can stop the search. + if is_descendent { + break + } + root_idx += 1; + } + + Ok(if found { + // The path is the root index followed by the indices of all the children + // we were processing when we found the element (remember the stack + // contains the index of the **next** children to process). + let path: Vec<_> = + std::iter::once(root_idx).chain(stack.iter().map(|(_, i)| *i - 1)).collect(); + Some(path) + } else { + None + }) + } + + /// Prune the tree, removing all non-canonical nodes. We find the node in the + /// tree that is the deepest ancestor of the given hash and that passes the + /// given predicate. If such a node exists, we re-root the tree to this + /// node. Otherwise the tree remains unchanged. The given function + /// `is_descendent_of` should return `true` if the second hash (target) is a + /// descendent of the first hash (base). + /// + /// Returns all pruned node data. + pub fn prune( + &mut self, + hash: &H, + number: &N, + is_descendent_of: &F, + predicate: &P, + ) -> Result, Error> + where + E: std::error::Error, + F: Fn(&H, &H) -> Result, + P: Fn(&V) -> bool, + { + let root_index = + match self.find_node_index_where(hash, number, is_descendent_of, predicate)? { + Some(idx) => idx, + None => return Ok(RemovedIterator { stack: Vec::new() }), + }; + + let mut old_roots = std::mem::take(&mut self.roots); + + let curr_children = root_index + .iter() + .take(root_index.len() - 1) + .fold(&mut old_roots, |curr, idx| &mut curr[*idx].children); + let mut root = curr_children.remove(root_index[root_index.len() - 1]); + + let mut removed = old_roots; + + // 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::take(&mut root.children); + let mut is_first = true; + + for child in root_children { + if is_first + && (child.number == *number && child.hash == *hash + || child.number < *number && is_descendent_of(&child.hash, hash)?) + { + root.children.push(child); + // assuming that the tree is well formed only one child should pass this + // requirement due to ancestry restrictions (i.e. they must be different forks). + is_first = false; + } else { + removed.push(child); + } + } + + self.roots = vec![root]; + self.rebalance(); + + Ok(RemovedIterator { stack: removed }) + } + + /// Finalize a root in the tree and return it, return `None` in case no root + /// with the given hash exists. All other roots are pruned, and the children + /// of the finalized node become the new roots. + pub fn finalize_root(&mut self, hash: &H) -> Option { + self.roots + .iter() + .position(|node| node.hash == *hash) + .map(|position| self.finalize_root_at(position)) + } + + /// Finalize root at given position. See `finalize_root` comment for details. + fn finalize_root_at(&mut self, position: usize) -> V { + let node = self.roots.swap_remove(position); + self.roots = node.children; + self.best_finalized_number = Some(node.number); + node.data + } + + /// Finalize a node in the tree. This method will make sure that the node + /// being finalized is either an existing root (and return its data), or a + /// node from a competing branch (not in the tree), tree pruning is done + /// accordingly. The given function `is_descendent_of` should return `true` + /// if the second hash (target) is a descendent of the first hash (base). + pub fn finalize( + &mut self, + hash: &H, + number: N, + is_descendent_of: &F, + ) -> Result, Error> + where + E: std::error::Error, + F: Fn(&H, &H) -> Result, + { + if let Some(ref best_finalized_number) = self.best_finalized_number { + if number <= *best_finalized_number { + return Err(Error::Revert) + } + } + + // check if one of the current roots is being finalized + if let Some(root) = self.finalize_root(hash) { + return Ok(FinalizationResult::Changed(Some(root))) + } + + // make sure we're not finalizing a descendent of any root + for root in self.roots.iter() { + if number > root.number && is_descendent_of(&root.hash, hash)? { + return Err(Error::UnfinalizedAncestor) + } + } + + // we finalized a block earlier than any existing root (or possibly + // another fork not part of the tree). make sure to only keep roots that + // are part of the finalized branch + let mut changed = false; + let roots = std::mem::take(&mut self.roots); + + for root in roots { + if root.number > number && is_descendent_of(hash, &root.hash)? { + self.roots.push(root); + } else { + changed = true; + } + } + + self.best_finalized_number = Some(number); + + if changed { + Ok(FinalizationResult::Changed(None)) + } else { + Ok(FinalizationResult::Unchanged) + } + } + + /// Finalize a node in the tree and all its ancestors. The given function + /// `is_descendent_of` should return `true` if the second hash (target) is + // a descendent of the first hash (base). + pub fn finalize_with_ancestors( + &mut self, + hash: &H, + number: N, + is_descendent_of: &F, + ) -> Result, Error> + where + E: std::error::Error, + F: Fn(&H, &H) -> Result, + { + if let Some(ref best_finalized_number) = self.best_finalized_number { + if number <= *best_finalized_number { + return Err(Error::Revert) + } + } + + // check if one of the current roots is being finalized + if let Some(root) = self.finalize_root(hash) { + return Ok(FinalizationResult::Changed(Some(root))) + } + + // we need to: + // 1) remove all roots that are not ancestors AND not descendants of finalized block; + // 2) if node is descendant - just leave it; + // 3) if node is ancestor - 'open it' + let mut changed = false; + let mut idx = 0; + while idx != self.roots.len() { + let (is_finalized, is_descendant, is_ancestor) = { + let root = &self.roots[idx]; + let is_finalized = root.hash == *hash; + let is_descendant = + !is_finalized && root.number > number && is_descendent_of(hash, &root.hash)?; + let is_ancestor = !is_finalized + && !is_descendant && root.number < number + && is_descendent_of(&root.hash, hash)?; + (is_finalized, is_descendant, is_ancestor) + }; + + // if we have met finalized root - open it and return + if is_finalized { + return Ok(FinalizationResult::Changed(Some(self.finalize_root_at(idx)))) + } + + // if node is descendant of finalized block - just leave it as is + if is_descendant { + idx += 1; + continue + } + + // if node is ancestor of finalized block - remove it and continue with children + if is_ancestor { + let root = self.roots.swap_remove(idx); + self.roots.extend(root.children); + changed = true; + continue + } + + // if node is neither ancestor, nor descendant of the finalized block - remove it + self.roots.swap_remove(idx); + changed = true; + } + + self.best_finalized_number = Some(number); + + if changed { + Ok(FinalizationResult::Changed(None)) + } else { + Ok(FinalizationResult::Unchanged) + } + } + + /// Checks if any node in the tree is finalized by either finalizing the + /// node itself or a node's descendent that's not in the tree, guaranteeing + /// that the node being finalized isn't a descendent of (or equal to) any of + /// the node's children. Returns `Some(true)` if the node being finalized is + /// a root, `Some(false)` if the node being finalized is not a root, and + /// `None` if no node in the tree is finalized. The given `predicate` is + /// checked on the prospective finalized root and must pass for finalization + /// to occur. The given function `is_descendent_of` should return `true` if + /// the second hash (target) is a descendent of the first hash (base). + pub fn finalizes_any_with_descendent_if( + &self, + hash: &H, + number: N, + is_descendent_of: &F, + predicate: P, + ) -> Result, Error> + where + E: std::error::Error, + F: Fn(&H, &H) -> Result, + P: Fn(&V) -> bool, + { + if let Some(ref best_finalized_number) = self.best_finalized_number { + if number <= *best_finalized_number { + return Err(Error::Revert) + } + } + + // check if the given hash is equal or a descendent of any node in the + // tree, if we find a valid node that passes the predicate then we must + // ensure that we're not finalizing past any of its child nodes. + for node in self.node_iter() { + if predicate(&node.data) && (node.hash == *hash || is_descendent_of(&node.hash, hash)?) + { + for child in node.children.iter() { + if child.number <= number + && (child.hash == *hash || is_descendent_of(&child.hash, hash)?) + { + return Err(Error::UnfinalizedAncestor) + } + } + + return Ok(Some(self.roots.iter().any(|root| root.hash == node.hash))) + } + } + + Ok(None) + } + + /// Finalize a root in the tree by either finalizing the node itself or a + /// node's descendent that's not in the tree, guaranteeing that the node + /// being finalized isn't a descendent of (or equal to) any of the root's + /// children. The given `predicate` is checked on the prospective finalized + /// root and must pass for finalization to occur. The given function + /// `is_descendent_of` should return `true` if the second hash (target) is a + /// descendent of the first hash (base). + pub fn finalize_with_descendent_if( + &mut self, + hash: &H, + number: N, + is_descendent_of: &F, + predicate: P, + ) -> Result, Error> + where + E: std::error::Error, + F: Fn(&H, &H) -> Result, + P: Fn(&V) -> bool, + { + if let Some(ref best_finalized_number) = self.best_finalized_number { + if number <= *best_finalized_number { + return Err(Error::Revert) + } + } + + // check if the given hash is equal or a a descendent of any root, if we + // find a valid root that passes the predicate then we must ensure that + // we're not finalizing past any children node. + let mut position = None; + for (i, root) in self.roots.iter().enumerate() { + if predicate(&root.data) && (root.hash == *hash || is_descendent_of(&root.hash, hash)?) + { + for child in root.children.iter() { + if child.number <= number + && (child.hash == *hash || is_descendent_of(&child.hash, hash)?) + { + return Err(Error::UnfinalizedAncestor) + } + } + + position = Some(i); + break + } + } + + let node_data = position.map(|i| { + let node = self.roots.swap_remove(i); + self.roots = node.children; + self.best_finalized_number = Some(node.number); + node.data + }); + + // Retain only roots that are descendents of the finalized block (this + // happens if the node has been properly finalized) or that are + // ancestors (or equal) to the finalized block (in this case the node + // wasn't finalized earlier presumably because the predicate didn't + // pass). + let mut changed = false; + let roots = std::mem::take(&mut self.roots); + + for root in roots { + let retain = root.number > number && is_descendent_of(hash, &root.hash)? + || root.number == number && root.hash == *hash + || is_descendent_of(&root.hash, hash)?; + + if retain { + self.roots.push(root); + } else { + changed = true; + } + } + + self.best_finalized_number = Some(number); + + match (node_data, changed) { + (Some(data), _) => Ok(FinalizationResult::Changed(Some(data))), + (None, true) => Ok(FinalizationResult::Changed(None)), + (None, false) => Ok(FinalizationResult::Unchanged), + } + } + + /// Remove from the tree some nodes (and their subtrees) using a `filter` predicate. + /// + /// The `filter` is called over tree nodes and returns a filter action: + /// - `Remove` if the node and its subtree should be removed; + /// - `KeepNode` if we should maintain the node and keep processing the tree. + /// - `KeepTree` if we should maintain the node and its entire subtree. + /// + /// An iterator over all the pruned nodes is returned. + pub fn drain_filter(&mut self, filter: F) -> impl Iterator + where + F: Fn(&H, &N, &V) -> FilterAction, + { + let mut removed = vec![]; + let mut retained = Vec::new(); + + let mut queue: Vec<_> = std::mem::take(&mut self.roots) + .into_iter() + .rev() + .map(|node| (usize::MAX, node)) + .collect(); + let mut next_queue = Vec::new(); + + while !queue.is_empty() { + for (parent_idx, mut node) in queue.drain(..) { + match filter(&node.hash, &node.number, &node.data) { + FilterAction::KeepNode => { + let node_idx = retained.len(); + let children = std::mem::take(&mut node.children); + retained.push((parent_idx, node)); + for child in children.into_iter().rev() { + next_queue.push((node_idx, child)); + } + }, + FilterAction::KeepTree => { + retained.push((parent_idx, node)); + }, + FilterAction::Remove => { + removed.push(node); + }, + } + } + + std::mem::swap(&mut queue, &mut next_queue); + } + + while let Some((parent_idx, node)) = retained.pop() { + if parent_idx == usize::MAX { + self.roots.push(node); + } else { + retained[parent_idx].1.children.push(node); + } + } + + if !removed.is_empty() { + self.rebalance(); + } + RemovedIterator { stack: removed } + } +} + +// Workaround for: https://github.com/rust-lang/rust/issues/34537 +use node_implementation::Node; + +mod node_implementation { + use super::*; + + #[derive(Clone, Debug, Decode, Encode, PartialEq)] + pub struct Node { + pub hash: H, + pub number: N, + pub data: V, + pub children: Vec>, + } + + impl Node { + /// Finds the max depth among all branches descendent from this node. + pub fn max_depth(&self) -> usize { + let mut max: usize = 0; + let mut stack = vec![(self, 0)]; + while let Some((node, height)) = stack.pop() { + if height > max { + max = height; + } + node.children.iter().for_each(|n| stack.push((n, height + 1))); + } + max + } + } +} + +struct ForkTreeIterator<'a, H, N, V> { + stack: Vec<&'a Node>, +} + +impl<'a, H, N, V> Iterator for ForkTreeIterator<'a, H, N, V> { + type Item = &'a Node; + + fn next(&mut self) -> Option { + self.stack.pop().map(|node| { + // child nodes are stored ordered by max branch height (decreasing), + // we want to keep this ordering while iterating but since we're + // using a stack for iterator state we need to reverse it. + self.stack.extend(node.children.iter().rev()); + node + }) + } +} + +struct RemovedIterator { + stack: Vec>, +} + +impl Iterator for RemovedIterator { + type Item = (H, N, V); + + fn next(&mut self) -> Option { + self.stack.pop().map(|mut node| { + // child nodes are stored ordered by max branch height (decreasing), + // we want to keep this ordering while iterating but since we're + // using a stack for iterator state we need to reverse it. + let children = std::mem::take(&mut node.children); + + self.stack.extend(children.into_iter().rev()); + (node.hash, node.number, node.data) + }) + } +} + +#[cfg(test)] +mod test { + use crate::FilterAction; + + use super::{Error, FinalizationResult, ForkTree}; + + #[derive(Debug, PartialEq)] + struct TestError; + + impl std::fmt::Display for TestError { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(f, "TestError") + } + } + + impl std::error::Error for TestError {} + + fn test_fork_tree<'a>( + ) -> (ForkTree<&'a str, u64, ()>, impl Fn(&&str, &&str) -> Result) { + let mut tree = ForkTree::new(); + + #[rustfmt::skip] + // + // - B - C - D - E + // / + // / - G + // / / + // A - F - H - I + // \ \ + // \ - L - M - N + // \ \ + // \ - O + // - J - K + // + // (where N is not a part of fork tree) + // + // NOTE: the tree will get automatically rebalance on import and won't be laid out like the + // diagram above. the children will be ordered by subtree depth and the longest branches + // will be on the leftmost side of the tree. + let is_descendent_of = |base: &&str, block: &&str| -> Result { + let letters = vec!["B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O"]; + match (*base, *block) { + ("A", b) => Ok(letters.into_iter().any(|n| n == b)), + ("B", b) => Ok(b == "C" || b == "D" || b == "E"), + ("C", b) => Ok(b == "D" || b == "E"), + ("D", b) => Ok(b == "E"), + ("E", _) => Ok(false), + ("F", b) => + Ok(b == "G" || b == "H" || b == "I" || b == "L" || b == "M" || b == "N" || b == "O"), + ("G", _) => Ok(false), + ("H", b) => Ok(b == "I" || b == "L" || b == "M" || b == "N" || b == "O"), + ("I", _) => Ok(false), + ("J", b) => Ok(b == "K"), + ("K", _) => Ok(false), + ("L", b) => Ok(b == "M" || b == "O" || b == "N"), + ("M", b) => Ok(b == "N"), + ("O", _) => Ok(false), + ("0", _) => Ok(true), + _ => Ok(false), + } + }; + + tree.import("A", 1, (), &is_descendent_of).unwrap(); + + tree.import("B", 2, (), &is_descendent_of).unwrap(); + tree.import("C", 3, (), &is_descendent_of).unwrap(); + tree.import("D", 4, (), &is_descendent_of).unwrap(); + tree.import("E", 5, (), &is_descendent_of).unwrap(); + + tree.import("F", 2, (), &is_descendent_of).unwrap(); + tree.import("G", 3, (), &is_descendent_of).unwrap(); + + tree.import("H", 3, (), &is_descendent_of).unwrap(); + tree.import("I", 4, (), &is_descendent_of).unwrap(); + tree.import("L", 4, (), &is_descendent_of).unwrap(); + tree.import("M", 5, (), &is_descendent_of).unwrap(); + tree.import("O", 5, (), &is_descendent_of).unwrap(); + + tree.import("J", 2, (), &is_descendent_of).unwrap(); + tree.import("K", 3, (), &is_descendent_of).unwrap(); + + (tree, is_descendent_of) + } + + #[test] + fn import_doesnt_revert() { + let (mut tree, is_descendent_of) = test_fork_tree(); + + tree.finalize_root(&"A"); + + assert_eq!(tree.best_finalized_number, Some(1)); + + assert_eq!(tree.import("A", 1, (), &is_descendent_of), Err(Error::Revert)); + } + + #[test] + fn import_doesnt_add_duplicates() { + let (mut tree, is_descendent_of) = test_fork_tree(); + + assert_eq!(tree.import("A", 1, (), &is_descendent_of), Err(Error::Duplicate)); + + assert_eq!(tree.import("I", 4, (), &is_descendent_of), Err(Error::Duplicate)); + + assert_eq!(tree.import("G", 3, (), &is_descendent_of), Err(Error::Duplicate)); + + assert_eq!(tree.import("K", 3, (), &is_descendent_of), Err(Error::Duplicate)); + } + + #[test] + fn finalize_root_works() { + let finalize_a = || { + let (mut tree, ..) = test_fork_tree(); + + assert_eq!(tree.roots().map(|(h, n, _)| (*h, *n)).collect::>(), vec![("A", 1)]); + + // finalizing "A" opens up three possible forks + tree.finalize_root(&"A"); + + assert_eq!( + tree.roots().map(|(h, n, _)| (*h, *n)).collect::>(), + vec![("B", 2), ("F", 2), ("J", 2)], + ); + + tree + }; + + { + let mut tree = finalize_a(); + + // finalizing "B" will progress on its fork and remove any other competing forks + tree.finalize_root(&"B"); + + assert_eq!(tree.roots().map(|(h, n, _)| (*h, *n)).collect::>(), vec![("C", 3)],); + + // all the other forks have been pruned + assert!(tree.roots.len() == 1); + } + + { + let mut tree = finalize_a(); + + // finalizing "J" will progress on its fork and remove any other competing forks + tree.finalize_root(&"J"); + + assert_eq!(tree.roots().map(|(h, n, _)| (*h, *n)).collect::>(), vec![("K", 3)],); + + // all the other forks have been pruned + assert!(tree.roots.len() == 1); + } + } + + #[test] + fn finalize_works() { + let (mut tree, is_descendent_of) = test_fork_tree(); + + let original_roots = tree.roots.clone(); + + // finalizing a block prior to any in the node doesn't change the tree + assert_eq!(tree.finalize(&"0", 0, &is_descendent_of), Ok(FinalizationResult::Unchanged)); + + assert_eq!(tree.roots, original_roots); + + // finalizing "A" opens up three possible forks + assert_eq!( + tree.finalize(&"A", 1, &is_descendent_of), + Ok(FinalizationResult::Changed(Some(()))), + ); + + assert_eq!( + tree.roots().map(|(h, n, _)| (*h, *n)).collect::>(), + vec![("B", 2), ("F", 2), ("J", 2)], + ); + + // finalizing anything lower than what we observed will fail + assert_eq!(tree.best_finalized_number, Some(1)); + + assert_eq!(tree.finalize(&"Z", 1, &is_descendent_of), Err(Error::Revert)); + + // trying to finalize a node without finalizing its ancestors first will fail + assert_eq!(tree.finalize(&"H", 3, &is_descendent_of), Err(Error::UnfinalizedAncestor)); + + // after finalizing "F" we can finalize "H" + assert_eq!( + tree.finalize(&"F", 2, &is_descendent_of), + Ok(FinalizationResult::Changed(Some(()))), + ); + + assert_eq!( + tree.finalize(&"H", 3, &is_descendent_of), + Ok(FinalizationResult::Changed(Some(()))), + ); + + assert_eq!( + tree.roots().map(|(h, n, _)| (*h, *n)).collect::>(), + vec![("L", 4), ("I", 4)], + ); + + // finalizing a node from another fork that isn't part of the tree clears the tree + assert_eq!( + tree.finalize(&"Z", 5, &is_descendent_of), + Ok(FinalizationResult::Changed(None)), + ); + + assert!(tree.roots.is_empty()); + } + + #[test] + fn finalize_with_ancestor_works() { + let (mut tree, is_descendent_of) = test_fork_tree(); + + let original_roots = tree.roots.clone(); + + // finalizing a block prior to any in the node doesn't change the tree + assert_eq!( + tree.finalize_with_ancestors(&"0", 0, &is_descendent_of), + Ok(FinalizationResult::Unchanged), + ); + + assert_eq!(tree.roots, original_roots); + + // finalizing "A" opens up three possible forks + assert_eq!( + tree.finalize_with_ancestors(&"A", 1, &is_descendent_of), + Ok(FinalizationResult::Changed(Some(()))), + ); + + assert_eq!( + tree.roots().map(|(h, n, _)| (*h, *n)).collect::>(), + vec![("B", 2), ("F", 2), ("J", 2)], + ); + + // finalizing H: + // 1) removes roots that are not ancestors/descendants of H (B, J) + // 2) opens root that is ancestor of H (F -> G+H) + // 3) finalizes the just opened root H (H -> I + L) + assert_eq!( + tree.finalize_with_ancestors(&"H", 3, &is_descendent_of), + Ok(FinalizationResult::Changed(Some(()))), + ); + + assert_eq!( + tree.roots().map(|(h, n, _)| (*h, *n)).collect::>(), + vec![("L", 4), ("I", 4)], + ); + + assert_eq!(tree.best_finalized_number, Some(3)); + + // finalizing N (which is not a part of the tree): + // 1) removes roots that are not ancestors/descendants of N (I) + // 2) opens root that is ancestor of N (L -> M+O) + // 3) removes roots that are not ancestors/descendants of N (O) + // 4) opens root that is ancestor of N (M -> {}) + assert_eq!( + tree.finalize_with_ancestors(&"N", 6, &is_descendent_of), + Ok(FinalizationResult::Changed(None)), + ); + + assert_eq!(tree.roots().map(|(h, n, _)| (*h, *n)).collect::>(), vec![],); + + assert_eq!(tree.best_finalized_number, Some(6)); + } + + #[test] + fn finalize_with_descendent_works() { + #[derive(Debug, PartialEq)] + struct Change { + effective: u64, + } + + let (mut tree, is_descendent_of) = { + let mut tree = ForkTree::new(); + + let is_descendent_of = |base: &&str, block: &&str| -> Result { + // A0 #1 - (B #2) - (C #5) - D #10 - E #15 - (F #100) + // \ + // - (G #100) + // + // A1 #1 + // + // Nodes B, C, F and G are not part of the tree. + match (*base, *block) { + ("A0", b) => Ok(b == "B" || b == "C" || b == "D" || b == "E" || b == "G"), + ("A1", _) => Ok(false), + ("C", b) => Ok(b == "D"), + ("D", b) => Ok(b == "E" || b == "F" || b == "G"), + ("E", b) => Ok(b == "F"), + _ => Ok(false), + } + }; + + let is_root = tree.import("A0", 1, Change { effective: 5 }, &is_descendent_of).unwrap(); + assert!(is_root); + let is_root = tree.import("A1", 1, Change { effective: 5 }, &is_descendent_of).unwrap(); + assert!(is_root); + let is_root = + tree.import("D", 10, Change { effective: 10 }, &is_descendent_of).unwrap(); + assert!(!is_root); + let is_root = + tree.import("E", 15, Change { effective: 50 }, &is_descendent_of).unwrap(); + assert!(!is_root); + + (tree, is_descendent_of) + }; + + assert_eq!( + tree.finalizes_any_with_descendent_if( + &"B", + 2, + &is_descendent_of, + |c| c.effective <= 2, + ), + Ok(None), + ); + + // finalizing "D" is not allowed since it is not a root. + assert_eq!( + tree.finalize_with_descendent_if(&"D", 10, &is_descendent_of, |c| c.effective <= 10), + Err(Error::UnfinalizedAncestor) + ); + + // finalizing "D" will finalize a block from the tree, but it can't be applied yet + // since it is not a root change. + assert_eq!( + tree.finalizes_any_with_descendent_if(&"D", 10, &is_descendent_of, |c| c.effective + == 10), + Ok(Some(false)), + ); + + // finalizing "E" is not allowed since there are not finalized anchestors. + assert_eq!( + tree.finalizes_any_with_descendent_if(&"E", 15, &is_descendent_of, |c| c.effective + == 10), + Err(Error::UnfinalizedAncestor) + ); + + // finalizing "B" doesn't finalize "A0" since the predicate doesn't pass, + // although it will clear out "A1" from the tree + assert_eq!( + tree.finalize_with_descendent_if(&"B", 2, &is_descendent_of, |c| c.effective <= 2), + Ok(FinalizationResult::Changed(None)), + ); + + assert_eq!(tree.roots().map(|(h, n, _)| (*h, *n)).collect::>(), vec![("A0", 1)],); + + // finalizing "C" will finalize the node "A0" and prune it out of the tree + assert_eq!( + tree.finalizes_any_with_descendent_if( + &"C", + 5, + &is_descendent_of, + |c| c.effective <= 5, + ), + Ok(Some(true)), + ); + + assert_eq!( + tree.finalize_with_descendent_if(&"C", 5, &is_descendent_of, |c| c.effective <= 5), + Ok(FinalizationResult::Changed(Some(Change { effective: 5 }))), + ); + + assert_eq!(tree.roots().map(|(h, n, _)| (*h, *n)).collect::>(), vec![("D", 10)],); + + // finalizing "F" will fail since it would finalize past "E" without finalizing "D" first + assert_eq!( + tree.finalizes_any_with_descendent_if(&"F", 100, &is_descendent_of, |c| c.effective + <= 100,), + Err(Error::UnfinalizedAncestor), + ); + + // it will work with "G" though since it is not in the same branch as "E" + assert_eq!( + tree.finalizes_any_with_descendent_if(&"G", 100, &is_descendent_of, |c| c.effective + <= 100), + Ok(Some(true)), + ); + + assert_eq!( + tree.finalize_with_descendent_if(&"G", 100, &is_descendent_of, |c| c.effective <= 100), + Ok(FinalizationResult::Changed(Some(Change { effective: 10 }))), + ); + + // "E" will be pruned out + assert_eq!(tree.roots().count(), 0); + } + + #[test] + fn iter_iterates_in_preorder() { + let (tree, ..) = test_fork_tree(); + assert_eq!( + tree.iter().map(|(h, n, _)| (*h, *n)).collect::>(), + vec![ + ("A", 1), + ("B", 2), + ("C", 3), + ("D", 4), + ("E", 5), + ("F", 2), + ("H", 3), + ("L", 4), + ("M", 5), + ("O", 5), + ("I", 4), + ("G", 3), + ("J", 2), + ("K", 3), + ], + ); + } + + #[test] + fn minimizes_calls_to_is_descendent_of() { + use std::sync::atomic::{AtomicUsize, Ordering}; + + let n_is_descendent_of_calls = AtomicUsize::new(0); + + let is_descendent_of = |_: &&str, _: &&str| -> Result { + n_is_descendent_of_calls.fetch_add(1, Ordering::SeqCst); + Ok(true) + }; + + { + // Deep tree where we want to call `finalizes_any_with_descendent_if`. The + // search for the node should first check the predicate (which is cheaper) and + // only then call `is_descendent_of` + let mut tree = ForkTree::new(); + let letters = vec!["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K"]; + + for (i, letter) in letters.iter().enumerate() { + tree.import::<_, TestError>(*letter, i, i, &|_, _| Ok(true)).unwrap(); + } + + // "L" is a descendent of "K", but the predicate will only pass for "K", + // therefore only one call to `is_descendent_of` should be made + assert_eq!( + tree.finalizes_any_with_descendent_if(&"L", 11, &is_descendent_of, |i| *i == 10,), + Ok(Some(false)), + ); + + assert_eq!(n_is_descendent_of_calls.load(Ordering::SeqCst), 1); + } + + n_is_descendent_of_calls.store(0, Ordering::SeqCst); + + { + // Multiple roots in the tree where we want to call `finalize_with_descendent_if`. + // The search for the root node should first check the predicate (which is cheaper) + // and only then call `is_descendent_of` + let mut tree = ForkTree::new(); + let letters = vec!["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K"]; + + for (i, letter) in letters.iter().enumerate() { + tree.import::<_, TestError>(*letter, i, i, &|_, _| Ok(false)).unwrap(); + } + + // "L" is a descendent of "K", but the predicate will only pass for "K", + // therefore only one call to `is_descendent_of` should be made + assert_eq!( + tree.finalize_with_descendent_if(&"L", 11, &is_descendent_of, |i| *i == 10,), + Ok(FinalizationResult::Changed(Some(10))), + ); + + assert_eq!(n_is_descendent_of_calls.load(Ordering::SeqCst), 1); + } + } + + #[test] + fn map_works() { + let (mut tree, _) = test_fork_tree(); + + // Extend the single root fork-tree to also excercise the roots order during map. + let is_descendent_of = |_: &&str, _: &&str| -> Result { Ok(false) }; + let is_root = tree.import("A1", 1, (), &is_descendent_of).unwrap(); + assert!(is_root); + let is_root = tree.import("A2", 1, (), &is_descendent_of).unwrap(); + assert!(is_root); + + let old_tree = tree.clone(); + let new_tree = tree.map(&mut |hash, _, _| hash.to_owned()); + + // Check content and order + assert!(new_tree.iter().all(|(hash, _, data)| hash == data)); + assert_eq!( + old_tree.iter().map(|(hash, _, _)| *hash).collect::>(), + new_tree.iter().map(|(hash, _, _)| *hash).collect::>(), + ); + } + + #[test] + fn prune_works() { + let (mut tree, is_descendent_of) = test_fork_tree(); + + let removed = tree.prune(&"C", &3, &is_descendent_of, &|_| true).unwrap(); + + assert_eq!(tree.roots.iter().map(|node| node.hash).collect::>(), vec!["B"]); + + assert_eq!( + tree.iter().map(|(hash, _, _)| *hash).collect::>(), + vec!["B", "C", "D", "E"], + ); + + assert_eq!( + removed.map(|(hash, _, _)| hash).collect::>(), + vec!["A", "F", "H", "L", "M", "O", "I", "G", "J", "K"] + ); + + let removed = tree.prune(&"E", &5, &is_descendent_of, &|_| true).unwrap(); + + assert_eq!(tree.roots.iter().map(|node| node.hash).collect::>(), vec!["D"]); + + assert_eq!(tree.iter().map(|(hash, _, _)| *hash).collect::>(), vec!["D", "E"]); + + assert_eq!(removed.map(|(hash, _, _)| hash).collect::>(), vec!["B", "C"]); + } + + #[test] + fn find_node_backtracks_after_finding_highest_descending_node() { + let mut tree = ForkTree::new(); + + // A - B + // \ + // — C + // + let is_descendent_of = |base: &&str, block: &&str| -> Result { + match (*base, *block) { + ("A", b) => Ok(b == "B" || b == "C" || b == "D"), + ("B", b) | ("C", b) => Ok(b == "D"), + ("0", _) => Ok(true), + _ => Ok(false), + } + }; + + tree.import("A", 1, 1, &is_descendent_of).unwrap(); + tree.import("B", 2, 2, &is_descendent_of).unwrap(); + tree.import("C", 2, 4, &is_descendent_of).unwrap(); + + // when searching the tree we reach node `C`, but the + // predicate doesn't pass. we should backtrack to `B`, but not to `A`, + // since "B" fulfills the predicate. + let node = tree.find_node_where(&"D", &3, &is_descendent_of, &|data| *data < 3).unwrap(); + + assert_eq!(node.unwrap().hash, "B"); + } + + #[test] + fn rebalance_works() { + let (mut tree, _) = test_fork_tree(); + + // the tree is automatically rebalanced on import, therefore we should iterate in preorder + // exploring the longest forks first. check the ascii art above to understand the expected + // output below. + assert_eq!( + tree.iter().map(|(h, _, _)| *h).collect::>(), + vec!["A", "B", "C", "D", "E", "F", "H", "L", "M", "O", "I", "G", "J", "K"], + ); + + // let's add a block "P" which is a descendent of block "O" + let is_descendent_of = |base: &&str, block: &&str| -> Result { + match (*base, *block) { + (b, "P") => Ok(vec!["A", "F", "H", "L", "O"].into_iter().any(|n| n == b)), + _ => Ok(false), + } + }; + + tree.import("P", 6, (), &is_descendent_of).unwrap(); + + // this should re-order the tree, since the branch "A -> B -> C -> D -> E" is no longer tied + // with 5 blocks depth. additionally "O" should be visited before "M" now, since it has one + // descendent "P" which makes that branch 6 blocks long. + assert_eq!( + tree.iter().map(|(h, _, _)| *h).collect::>(), + ["A", "F", "H", "L", "O", "P", "M", "I", "G", "B", "C", "D", "E", "J", "K"] + ); + } + + #[test] + fn drain_filter_works() { + let (mut tree, _) = test_fork_tree(); + + let filter = |h: &&str, _: &u64, _: &()| match *h { + "A" | "B" | "F" | "G" => FilterAction::KeepNode, + "C" => FilterAction::KeepTree, + "H" | "J" => FilterAction::Remove, + _ => panic!("Unexpected filtering for node: {}", *h), + }; + + let removed = tree.drain_filter(filter); + + assert_eq!( + tree.iter().map(|(h, _, _)| *h).collect::>(), + ["A", "B", "C", "D", "E", "F", "G"] + ); + + assert_eq!( + removed.map(|(h, _, _)| h).collect::>(), + ["H", "L", "M", "O", "I", "J", "K"] + ); + } + + #[test] + fn find_node_index_works() { + let (tree, is_descendent_of) = test_fork_tree(); + + let path = tree + .find_node_index_where(&"D", &4, &is_descendent_of, &|_| true) + .unwrap() + .unwrap(); + assert_eq!(path, [0, 0, 0]); + + let path = tree + .find_node_index_where(&"O", &5, &is_descendent_of, &|_| true) + .unwrap() + .unwrap(); + assert_eq!(path, [0, 1, 0, 0]); + + let path = tree + .find_node_index_where(&"N", &6, &is_descendent_of, &|_| true) + .unwrap() + .unwrap(); + assert_eq!(path, [0, 1, 0, 0, 0]); + } + + #[test] + fn find_node_index_with_predicate_works() { + let is_descendent_of = |parent: &char, child: &char| match *parent { + 'A' => Ok(['B', 'C', 'D', 'E', 'F'].contains(child)), + 'B' => Ok(['C', 'D'].contains(child)), + 'C' => Ok(['D'].contains(child)), + 'E' => Ok(['F'].contains(child)), + 'D' | 'F' => Ok(false), + _ => Err(TestError), + }; + + // A(t) --- B(f) --- C(t) --- D(f) + // \-- E(t) --- F(f) + let mut tree: ForkTree = ForkTree::new(); + tree.import('A', 1, true, &is_descendent_of).unwrap(); + tree.import('B', 2, false, &is_descendent_of).unwrap(); + tree.import('C', 3, true, &is_descendent_of).unwrap(); + tree.import('D', 4, false, &is_descendent_of).unwrap(); + + tree.import('E', 2, true, &is_descendent_of).unwrap(); + tree.import('F', 3, false, &is_descendent_of).unwrap(); + + let path = tree + .find_node_index_where(&'D', &4, &is_descendent_of, &|&value| !value) + .unwrap() + .unwrap(); + assert_eq!(path, [0, 0]); + + let path = tree + .find_node_index_where(&'D', &4, &is_descendent_of, &|&value| value) + .unwrap() + .unwrap(); + assert_eq!(path, [0, 0, 0]); + + let path = tree + .find_node_index_where(&'F', &3, &is_descendent_of, &|&value| !value) + .unwrap(); + assert_eq!(path, None); + + let path = tree + .find_node_index_where(&'F', &3, &is_descendent_of, &|&value| value) + .unwrap() + .unwrap(); + assert_eq!(path, [0, 1]); + } + + #[test] + fn find_node_works() { + let (tree, is_descendent_of) = test_fork_tree(); + + let node = tree.find_node_where(&"B", &2, &is_descendent_of, &|_| true).unwrap().unwrap(); + assert_eq!((node.hash, node.number), ("A", 1)); + + let node = tree.find_node_where(&"D", &4, &is_descendent_of, &|_| true).unwrap().unwrap(); + assert_eq!((node.hash, node.number), ("C", 3)); + + let node = tree.find_node_where(&"O", &5, &is_descendent_of, &|_| true).unwrap().unwrap(); + assert_eq!((node.hash, node.number), ("L", 4)); + + let node = tree.find_node_where(&"N", &6, &is_descendent_of, &|_| true).unwrap().unwrap(); + assert_eq!((node.hash, node.number), ("M", 5)); + } + + #[test] + fn post_order_traversal_requirement() { + let (mut tree, is_descendent_of) = test_fork_tree(); + + // Test for the post-order DFS traversal requirement as specified by the + // `find_node_index_where` and `import` comments. + let is_descendent_of_for_post_order = |parent: &&str, child: &&str| match *parent { + "A" => Err(TestError), + "K" if *child == "Z" => Ok(true), + _ => is_descendent_of(parent, child), + }; + + // Post order traversal requirement for `find_node_index_where` + let path = tree + .find_node_index_where(&"N", &6, &is_descendent_of_for_post_order, &|_| true) + .unwrap() + .unwrap(); + assert_eq!(path, [0, 1, 0, 0, 0]); + + // Post order traversal requirement for `import` + let res = tree.import(&"Z", 100, (), &is_descendent_of_for_post_order); + assert_eq!(res, Ok(false)); + assert_eq!( + tree.iter().map(|node| *node.0).collect::>(), + vec!["A", "B", "C", "D", "E", "F", "H", "L", "M", "O", "I", "G", "J", "K", "Z"], + ); + } +} diff --git a/bitacross-worker/sidechain/peer-fetch/Cargo.toml b/bitacross-worker/sidechain/peer-fetch/Cargo.toml new file mode 100644 index 0000000000..63e2612d91 --- /dev/null +++ b/bitacross-worker/sidechain/peer-fetch/Cargo.toml @@ -0,0 +1,36 @@ +[package] +name = "its-peer-fetch" +version = "0.9.0" +authors = ['Trust Computing GmbH ', 'Integritee AG '] +edition = "2021" + +[dependencies] +# crates.io +async-trait = { version = "0.1.50" } +jsonrpsee = { version = "0.2.0", features = ["client", "ws-server", "macros"] } +log = { version = "0.4" } +serde = "1.0" +serde_json = "1.0" +thiserror = { version = "1.0" } + +# local +itc-rpc-client = { path = "../../core/rpc-client" } +itp-node-api = { path = "../../core-primitives/node-api" } +its-primitives = { path = "../primitives" } +its-rpc-handler = { path = "../rpc-handler" } +its-storage = { path = "../storage" } + +[dev-dependencies] +# crates.io +anyhow = "1.0.40" +tokio = { version = "1.6.1", features = ["full"] } +# local +itp-node-api = { path = "../../core-primitives/node-api", features = ["mocks"] } +itp-test = { path = "../../core-primitives/test" } +its-storage = { path = "../storage", features = ["mocks"] } +its-test = { path = "../test" } + +[features] +default = ["std"] +std = [] +mocks = [] diff --git a/bitacross-worker/sidechain/peer-fetch/src/block_fetch_client.rs b/bitacross-worker/sidechain/peer-fetch/src/block_fetch_client.rs new file mode 100644 index 0000000000..320d916d7a --- /dev/null +++ b/bitacross-worker/sidechain/peer-fetch/src/block_fetch_client.rs @@ -0,0 +1,141 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{error::Result, untrusted_peer_fetch::FetchUntrustedPeers, FetchBlocksFromPeer}; +use async_trait::async_trait; +use its_primitives::{ + traits::SignedBlock as SignedBlockTrait, + types::{BlockHash, ShardIdentifier}, +}; +use its_rpc_handler::constants::RPC_METHOD_NAME_FETCH_BLOCKS_FROM_PEER; +use jsonrpsee::{ + types::to_json_value, + ws_client::{traits::Client, WsClientBuilder}, +}; +use log::info; +use serde::de::DeserializeOwned; +use std::marker::PhantomData; + +/// Sidechain block fetcher implementation. +/// +/// Fetches block from a peer with an RPC request. +pub struct BlockFetcher { + peer_fetcher: PeerFetcher, + _phantom: PhantomData, +} + +impl BlockFetcher +where + SignedBlock: SignedBlockTrait + DeserializeOwned, + PeerFetcher: FetchUntrustedPeers + Send + Sync, +{ + pub fn new(peer_fetcher: PeerFetcher) -> Self { + BlockFetcher { peer_fetcher, _phantom: Default::default() } + } +} + +#[async_trait] +impl FetchBlocksFromPeer for BlockFetcher +where + SignedBlock: SignedBlockTrait + DeserializeOwned, + PeerFetcher: FetchUntrustedPeers + Send + Sync, +{ + type SignedBlockType = SignedBlock; + + async fn fetch_blocks_from_peer( + &self, + last_imported_block_hash: BlockHash, + maybe_until_block_hash: Option, + shard_identifier: ShardIdentifier, + ) -> Result> { + let sync_source_rpc_url = + self.peer_fetcher.get_untrusted_peer_url_of_shard(&shard_identifier)?; + + let rpc_parameters = vec![to_json_value(( + last_imported_block_hash, + maybe_until_block_hash, + shard_identifier, + ))?]; + + info!("Got untrusted url for peer block fetching: {}", sync_source_rpc_url); + + let client = WsClientBuilder::default().build(sync_source_rpc_url.as_str()).await?; + + info!("Sending fetch blocks from peer request"); + + client + .request::>( + RPC_METHOD_NAME_FETCH_BLOCKS_FROM_PEER, + rpc_parameters.into(), + ) + .await + .map_err(|e| e.into()) + } +} + +#[cfg(test)] +mod tests { + + use super::*; + use crate::{ + block_fetch_server::BlockFetchServerModuleBuilder, + mocks::untrusted_peer_fetch_mock::UntrustedPeerFetcherMock, + }; + use its_primitives::types::block::SignedBlock; + use its_storage::fetch_blocks_mock::FetchBlocksMock; + use its_test::sidechain_block_builder::{SidechainBlockBuilder, SidechainBlockBuilderTrait}; + use jsonrpsee::ws_server::WsServerBuilder; + use std::{net::SocketAddr, sync::Arc}; + + async fn run_server( + blocks: Vec, + web_socket_url: &str, + ) -> anyhow::Result { + let mut server = WsServerBuilder::default().build(web_socket_url).await?; + + let storage_block_fetcher = Arc::new(FetchBlocksMock::default().with_blocks(blocks)); + let module = BlockFetchServerModuleBuilder::new(storage_block_fetcher).build().unwrap(); + + server.register_module(module).unwrap(); + + let socket_addr = server.local_addr()?; + tokio::spawn(async move { server.start().await }); + Ok(socket_addr) + } + + #[tokio::test] + async fn fetch_blocks_without_bounds_from_peer_works() { + const W1_URL: &str = "127.0.0.1:2233"; + + let blocks_to_fetch = vec![ + SidechainBlockBuilder::random().build_signed(), + SidechainBlockBuilder::random().build_signed(), + ]; + run_server(blocks_to_fetch.clone(), W1_URL).await.unwrap(); + + let peer_fetch_mock = UntrustedPeerFetcherMock::new(format!("ws://{}", W1_URL)); + + let peer_fetcher_client = BlockFetcher::::new(peer_fetch_mock); + + let blocks_fetched = peer_fetcher_client + .fetch_blocks_from_peer(BlockHash::default(), None, ShardIdentifier::default()) + .await + .unwrap(); + + assert_eq!(blocks_to_fetch, blocks_fetched); + } +} diff --git a/bitacross-worker/sidechain/peer-fetch/src/block_fetch_server.rs b/bitacross-worker/sidechain/peer-fetch/src/block_fetch_server.rs new file mode 100644 index 0000000000..592153f6eb --- /dev/null +++ b/bitacross-worker/sidechain/peer-fetch/src/block_fetch_server.rs @@ -0,0 +1,103 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::error::Result; +use its_primitives::types::{BlockHash, BlockNumber, ShardIdentifier, SignedBlock}; +use its_rpc_handler::constants::{ + RPC_METHOD_NAME_BLOCK_HASH, RPC_METHOD_NAME_FETCH_BLOCKS_FROM_PEER, + RPC_METHOD_NAME_LATEST_BLOCK, +}; +use its_storage::interface::FetchBlocks; +use jsonrpsee::{types::error::CallError, RpcModule}; +use log::*; +use std::sync::Arc; + +/// RPC server module builder for fetching sidechain blocks from peers. +pub struct BlockFetchServerModuleBuilder { + sidechain_block_fetcher: Arc, +} + +impl BlockFetchServerModuleBuilder +where + // Have to use the concrete `SignedBlock` type, because the ShardIdentifier type + // does not have the Serialize/Deserialize trait bound. + FetchBlocksFromStorage: FetchBlocks + Send + Sync + 'static, +{ + pub fn new(sidechain_block_fetcher: Arc) -> Self { + BlockFetchServerModuleBuilder { sidechain_block_fetcher } + } + + pub fn build(self) -> Result>> { + let mut fetch_sidechain_blocks_module = RpcModule::new(self.sidechain_block_fetcher); + fetch_sidechain_blocks_module.register_method( + RPC_METHOD_NAME_FETCH_BLOCKS_FROM_PEER, + |params, sidechain_block_fetcher| { + debug!("{}: {:?}", RPC_METHOD_NAME_FETCH_BLOCKS_FROM_PEER, params); + + let (from_block_hash, maybe_until_block_hash, shard_identifier) = + params.one::<(BlockHash, Option, ShardIdentifier)>()?; + info!("Got request to fetch sidechain blocks from peer. Fetching sidechain blocks from storage \ + (last imported block hash: {:?}, until block hash: {:?}, shard: {}", + from_block_hash, maybe_until_block_hash, shard_identifier); + + match maybe_until_block_hash { + Some(until_block_hash) => sidechain_block_fetcher + .fetch_blocks_in_range( + &from_block_hash, + &until_block_hash, + &shard_identifier, + ) + .map_err(|e| { + error!("Failed to fetch sidechain blocks from storage: {:?}", e); + CallError::Failed(e.into()) + }), + None => sidechain_block_fetcher + .fetch_all_blocks_after(&from_block_hash, &shard_identifier) + .map_err(|e| { + error!("Failed to fetch sidechain blocks from storage: {:?}", e); + CallError::Failed(e.into()) + }), + } + }, + )?; + + fetch_sidechain_blocks_module.register_method( + RPC_METHOD_NAME_LATEST_BLOCK, + |params, sidechain_block_fetcher| { + debug!("{}: {:?}", RPC_METHOD_NAME_LATEST_BLOCK, params); + let shard = params.parse::()?; + match sidechain_block_fetcher.latest_block(&shard) { + None => Ok(None), + Some(e) => Ok(Some(e)), + } + }, + )?; + + fetch_sidechain_blocks_module.register_method( + RPC_METHOD_NAME_BLOCK_HASH, + |params, sidechain_block_fetcher| { + debug!("{}: {:?}", RPC_METHOD_NAME_BLOCK_HASH, params); + let (block_number, shard) = params.parse::<(BlockNumber, ShardIdentifier)>()?; + match sidechain_block_fetcher.block_hash(block_number, &shard) { + None => Ok(None), + Some(e) => Ok(Some(e)), + } + }, + )?; + Ok(fetch_sidechain_blocks_module) + } +} diff --git a/bitacross-worker/sidechain/peer-fetch/src/error.rs b/bitacross-worker/sidechain/peer-fetch/src/error.rs new file mode 100644 index 0000000000..569cd01a1d --- /dev/null +++ b/bitacross-worker/sidechain/peer-fetch/src/error.rs @@ -0,0 +1,44 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +//! Sidechain peer fetch error. + +pub type Result = core::result::Result; + +#[derive(Debug, thiserror::Error)] +pub enum Error { + #[error("RPC client error: {0}")] + RpcClient(#[from] itc_rpc_client::error::Error), + #[error("Node API extensions error: {0:?}")] + NodeApiExtensions(itp_node_api::api_client::ApiClientError), + #[error("Node API factory error: {0}")] + NodeApiFactory(#[from] itp_node_api::node_api_factory::NodeApiFactoryError), + #[error("Serialization error: {0}")] + Serialization(#[from] serde_json::Error), + #[error("JSON RPC error: {0}")] + JsonRpc(#[from] jsonrpsee::types::Error), + #[error("Could not find any peers on-chain for shard: {0:?}")] + NoPeerFoundForShard(its_primitives::types::ShardIdentifier), + #[error(transparent)] + Other(#[from] Box), +} + +impl From for Error { + fn from(error: itp_node_api::api_client::ApiClientError) -> Self { + Error::NodeApiExtensions(error) + } +} diff --git a/bitacross-worker/sidechain/peer-fetch/src/lib.rs b/bitacross-worker/sidechain/peer-fetch/src/lib.rs new file mode 100644 index 0000000000..5af3326970 --- /dev/null +++ b/bitacross-worker/sidechain/peer-fetch/src/lib.rs @@ -0,0 +1,49 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +#![cfg_attr(not(feature = "std"), no_std)] + +pub mod block_fetch_client; +pub mod block_fetch_server; +pub mod error; +pub mod untrusted_peer_fetch; + +#[cfg(feature = "mocks")] +pub mod mocks; + +use crate::error::Result; +use async_trait::async_trait; +use its_primitives::{ + traits::SignedBlock, + types::{BlockHash, ShardIdentifier}, +}; +use std::vec::Vec; + +/// Trait to fetch block from peer validateers. +/// +/// This is used by an outdated validateer to get the most recent state. +#[async_trait] +pub trait FetchBlocksFromPeer { + type SignedBlockType: SignedBlock; + + async fn fetch_blocks_from_peer( + &self, + last_imported_block_hash: BlockHash, + maybe_until_block_hash: Option, + shard_identifier: ShardIdentifier, + ) -> Result>; +} diff --git a/bitacross-worker/sidechain/peer-fetch/src/mocks/fetch_blocks_from_peer_mock.rs b/bitacross-worker/sidechain/peer-fetch/src/mocks/fetch_blocks_from_peer_mock.rs new file mode 100644 index 0000000000..09f9bb92fc --- /dev/null +++ b/bitacross-worker/sidechain/peer-fetch/src/mocks/fetch_blocks_from_peer_mock.rs @@ -0,0 +1,61 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{FetchBlocksFromPeer, Result}; +use async_trait::async_trait; +use its_primitives::{ + traits::SignedBlock as SignedBlockTrait, + types::{BlockHash, ShardIdentifier}, +}; +use std::collections::HashMap; + +pub struct FetchBlocksFromPeerMock { + signed_blocks_map: HashMap>, +} + +impl FetchBlocksFromPeerMock { + pub fn with_signed_blocks( + mut self, + blocks_map: HashMap>, + ) -> Self { + self.signed_blocks_map = blocks_map; + self + } +} + +impl Default for FetchBlocksFromPeerMock { + fn default() -> Self { + FetchBlocksFromPeerMock { signed_blocks_map: HashMap::new() } + } +} + +#[async_trait] +impl FetchBlocksFromPeer for FetchBlocksFromPeerMock +where + SignedBlock: SignedBlockTrait, +{ + type SignedBlockType = SignedBlock; + + async fn fetch_blocks_from_peer( + &self, + _last_imported_block_hash: BlockHash, + _maybe_until_block_hash: Option, + shard_identifier: ShardIdentifier, + ) -> Result> { + Ok(self.signed_blocks_map.get(&shard_identifier).cloned().unwrap_or_default()) + } +} diff --git a/bitacross-worker/sidechain/peer-fetch/src/mocks/mod.rs b/bitacross-worker/sidechain/peer-fetch/src/mocks/mod.rs new file mode 100644 index 0000000000..392f8e9b82 --- /dev/null +++ b/bitacross-worker/sidechain/peer-fetch/src/mocks/mod.rs @@ -0,0 +1,19 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 fetch_blocks_from_peer_mock; +pub mod untrusted_peer_fetch_mock; diff --git a/bitacross-worker/sidechain/peer-fetch/src/mocks/untrusted_peer_fetch_mock.rs b/bitacross-worker/sidechain/peer-fetch/src/mocks/untrusted_peer_fetch_mock.rs new file mode 100644 index 0000000000..8b37b69e00 --- /dev/null +++ b/bitacross-worker/sidechain/peer-fetch/src/mocks/untrusted_peer_fetch_mock.rs @@ -0,0 +1,35 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{error::Result, untrusted_peer_fetch::FetchUntrustedPeers}; +use its_primitives::types::ShardIdentifier; + +pub struct UntrustedPeerFetcherMock { + url: String, +} + +impl UntrustedPeerFetcherMock { + pub fn new(url: String) -> Self { + UntrustedPeerFetcherMock { url } + } +} + +impl FetchUntrustedPeers for UntrustedPeerFetcherMock { + fn get_untrusted_peer_url_of_shard(&self, _shard: &ShardIdentifier) -> Result { + Ok(self.url.clone()) + } +} diff --git a/bitacross-worker/sidechain/peer-fetch/src/untrusted_peer_fetch.rs b/bitacross-worker/sidechain/peer-fetch/src/untrusted_peer_fetch.rs new file mode 100644 index 0000000000..7ff9434103 --- /dev/null +++ b/bitacross-worker/sidechain/peer-fetch/src/untrusted_peer_fetch.rs @@ -0,0 +1,59 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::error::{Error, Result}; +use itc_rpc_client::direct_client::{DirectApi, DirectClient as DirectWorkerApi}; +use itp_node_api::{api_client::PalletTeerexApi, node_api_factory::CreateNodeApi}; +use its_primitives::types::ShardIdentifier; +use std::sync::Arc; + +/// Trait to fetch untrusted peer servers. +pub trait FetchUntrustedPeers { + fn get_untrusted_peer_url_of_shard(&self, shard: &ShardIdentifier) -> Result; +} + +/// Fetches the untrusted peer servers +/// FIXME: Should probably be combined with the peer fetch in +/// service/src/worker.rs +pub struct UntrustedPeerFetcher { + node_api_factory: Arc, +} + +impl UntrustedPeerFetcher +where + NodeApiFactory: CreateNodeApi + Send + Sync, +{ + pub fn new(node_api: Arc) -> Self { + UntrustedPeerFetcher { node_api_factory: node_api } + } +} + +impl FetchUntrustedPeers for UntrustedPeerFetcher +where + NodeApiFactory: CreateNodeApi + Send + Sync, +{ + fn get_untrusted_peer_url_of_shard(&self, shard: &ShardIdentifier) -> Result { + let node_api = self.node_api_factory.create_api()?; + + let validateer = node_api + .worker_for_shard(shard, None)? + .ok_or_else(|| Error::NoPeerFoundForShard(*shard))?; + + let trusted_worker_client = DirectWorkerApi::new(validateer.url); + Ok(trusted_worker_client.get_untrusted_worker_url()?) + } +} diff --git a/bitacross-worker/sidechain/primitives/Cargo.toml b/bitacross-worker/sidechain/primitives/Cargo.toml new file mode 100644 index 0000000000..548f4d5a18 --- /dev/null +++ b/bitacross-worker/sidechain/primitives/Cargo.toml @@ -0,0 +1,36 @@ +[package] +name = "its-primitives" +version = "0.1.0" +authors = ['Trust Computing GmbH ', 'Integritee AG '] +homepage = 'https://litentry.com/' +repository = 'https://github.com/litentry/litentry-parachain' +license = "Apache-2.0" +edition = "2021" + +[dependencies] +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive", "full"] } +itp-types = { path = "../../core-primitives/types", default-features = false } +scale-info = { version = "2.4.0", default-features = false, features = ["derive"] } +serde = { version = "1.0.13", default-features = false } + +# substrate dependencies +sp-core = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } +sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } +sp-std = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } + + +[features] +default = ["std", "full_crypto"] +full_crypto = [ + "sp-core/full_crypto", +] +std = [ + "codec/std", + "scale-info/std", + "serde/std", + "itp-types/std", + # substrate + "sp-core/std", + "sp-runtime/std", + "sp-std/std", +] diff --git a/bitacross-worker/sidechain/primitives/src/lib.rs b/bitacross-worker/sidechain/primitives/src/lib.rs new file mode 100644 index 0000000000..708d9a7942 --- /dev/null +++ b/bitacross-worker/sidechain/primitives/src/lib.rs @@ -0,0 +1,21 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +#![cfg_attr(not(feature = "std"), no_std)] + +pub mod traits; +pub mod types; diff --git a/bitacross-worker/sidechain/primitives/src/traits/mod.rs b/bitacross-worker/sidechain/primitives/src/traits/mod.rs new file mode 100644 index 0000000000..06e1e2d393 --- /dev/null +++ b/bitacross-worker/sidechain/primitives/src/traits/mod.rs @@ -0,0 +1,176 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 basic abstractions used in sidechain +//! +//! Todo: This crate should be more generic and supply blanket implementations for +//! some generic structs. + +use codec::{Decode, Encode}; +use sp_core::{crypto::Public, H256}; +use sp_runtime::traits::{BlakeTwo256, Hash, Member}; +use sp_std::{fmt::Debug, prelude::*}; + +pub trait Header: Encode + Decode + Clone { + /// Identifier for the shards. + type ShardIdentifier: Encode + Decode + sp_std::hash::Hash + Copy + Member + Into; + + /// Get block number. + fn block_number(&self) -> u64; + /// get parent hash of block + fn parent_hash(&self) -> H256; + /// get shard id of block + fn shard_id(&self) -> Self::ShardIdentifier; + /// get hash of the block's payload + fn block_data_hash(&self) -> H256; + + /// get the `blake2_256` hash of the header. + fn hash(&self) -> H256 { + self.using_encoded(BlakeTwo256::hash) + } + + fn next_finalization_block_number(&self) -> u64; + + fn new( + block_number: u64, + parent_hash: H256, + shard: Self::ShardIdentifier, + block_data_hash: H256, + next_finalization_block_number: u64, + ) -> Self; +} + +pub trait BlockData: Encode + Decode + Send + Sync + Debug + Clone { + /// Public key type of the block author + type Public: Public; + + /// get timestamp of block + fn timestamp(&self) -> u64; + /// get layer one head of block + fn layer_one_head(&self) -> H256; + /// get author of block + fn block_author(&self) -> &Self::Public; + /// get reference of extrinsics of block + fn signed_top_hashes(&self) -> &[H256]; + /// get encrypted payload + fn encrypted_state_diff(&self) -> &Vec; + /// get the `blake2_256` hash of the block + fn hash(&self) -> H256 { + self.using_encoded(BlakeTwo256::hash) + } + + fn new( + author: Self::Public, + layer_one_head: H256, + signed_top_hashes: Vec, + encrypted_payload: Vec, + timestamp: u64, + ) -> Self; +} + +/// Abstraction around a sidechain block. +pub trait Block: Encode + Decode + Send + Sync + Debug + Clone { + /// Sidechain block header type. + type HeaderType: Header; + + /// Sidechain block data type. + type BlockDataType: BlockData; + + /// Public key type of the block author + type Public: Public; + + /// get the `blake2_256` hash of the block + fn hash(&self) -> H256 { + self.header().hash() + } + + /// Get header of the block. + fn header(&self) -> &Self::HeaderType; + + /// Get header of the block. + fn block_data(&self) -> &Self::BlockDataType; + + fn new(header: Self::HeaderType, block_data: Self::BlockDataType) -> Self; +} + +/// ShardIdentifier for a [`SignedBlock`] +pub type ShardIdentifierFor = +<<::Block as Block>::HeaderType as Header>::ShardIdentifier; + +/// A block and it's corresponding signature by the [`Block`] author. +pub trait SignedBlock: Encode + Decode + Send + Sync + Debug + Clone { + /// The block type of the [`SignedBlock`] + type Block: Block; + + /// Public key type of the signer and the block author + type Public: Public; + + /// Signature type of the [`SignedBlock`]'s signature + type Signature; + + /// create a new block instance + fn new(block: Self::Block, signer: Self::Signature) -> Self; + + /// get block reference + fn block(&self) -> &Self::Block; + + /// get signature reference + fn signature(&self) -> &Self::Signature; + + /// get `blake2_256` hash of block + fn hash(&self) -> H256 { + self.block().hash() + } + + /// Verify the signature of a [`Block`] + fn verify_signature(&self) -> bool; +} + +#[cfg(feature = "full_crypto")] +pub use crypto::*; + +#[cfg(feature = "full_crypto")] +mod crypto { + use super::*; + use sp_core::Pair; + + /// Provide signing logic blanket implementations for all block types satisfying the trait bounds. + pub trait SignBlock< + SidechainBlock: Block, + SignedSidechainBlock: SignedBlock, + > + { + fn sign_block(self, signer: &P) -> SignedSidechainBlock + where + ::Signature: From<

::Signature>; + } + + impl SignBlock + for SidechainBlock + where + SidechainBlock: Block, + SignedSidechainBlock: SignedBlock, + { + fn sign_block(self, signer: &P) -> SignedSidechainBlock + where + ::Signature: From<

::Signature>, + { + let signature = self.using_encoded(|b| signer.sign(b)).into(); + SignedSidechainBlock::new(self, signature) + } + } +} diff --git a/bitacross-worker/sidechain/primitives/src/types/block.rs b/bitacross-worker/sidechain/primitives/src/types/block.rs new file mode 100644 index 0000000000..8e7902d62d --- /dev/null +++ b/bitacross-worker/sidechain/primitives/src/types/block.rs @@ -0,0 +1,159 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{ + traits::{Block as BlockTrait, SignedBlock as SignedBlockTrait}, + types::{block_data::BlockData, header::SidechainHeader as Header}, +}; +use codec::{Decode, Encode}; +use sp_core::{ed25519, H256}; +use sp_runtime::{traits::Verify, MultiSignature}; + +pub type BlockHash = H256; +pub type BlockNumber = u64; +pub type ShardIdentifier = H256; +pub type Timestamp = u64; + +#[cfg(feature = "std")] +use serde::{Deserialize, Serialize}; + +//FIXME: Should use blocknumber from sgxruntime +// Problem: sgxruntime only with sgx, no std enviornment +// but block.rs should be available in std? +//use sgx_runtime::BlockNumber; + +pub type Signature = MultiSignature; + +/// signed version of block to verify block origin +#[derive(PartialEq, Eq, Clone, Encode, Decode, Debug)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +pub struct SignedBlock { + /// Plain sidechain block without author signature. + pub block: Block, + /// Block author signature. + pub signature: Signature, +} + +/// Simplified block structure for relay chain submission as an extrinsic. +#[derive(PartialEq, Eq, Clone, Encode, Decode, Debug)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +pub struct Block { + /// Sidechain Header + pub header: Header, + + /// Sidechain Block data + pub block_data: BlockData, +} + +impl BlockTrait for Block { + type HeaderType = Header; + + type BlockDataType = BlockData; + + type Public = ed25519::Public; + + fn header(&self) -> &Self::HeaderType { + &self.header + } + + fn block_data(&self) -> &Self::BlockDataType { + &self.block_data + } + + fn new(header: Self::HeaderType, block_data: Self::BlockDataType) -> Self { + Self { header, block_data } + } +} + +impl SignedBlockTrait for SignedBlock { + type Block = Block; + + type Public = ed25519::Public; + + type Signature = Signature; + + fn new(block: Self::Block, signature: Self::Signature) -> Self { + Self { block, signature } + } + + /// get block reference + fn block(&self) -> &Self::Block { + &self.block + } + + /// get signature reference + fn signature(&self) -> &Signature { + &self.signature + } + + /// Verifies the signature of a Block + fn verify_signature(&self) -> bool { + self.block.using_encoded(|p| { + self.signature.verify(p, &self.block.block_data().block_author.into()) + }) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::traits::{Block as BlockT, BlockData, Header, SignBlock}; + use sp_core::Pair; + use std::time::{SystemTime, UNIX_EPOCH}; + + /// gets the timestamp of the block as seconds since unix epoch + fn timestamp_now() -> Timestamp { + SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_millis() as Timestamp + } + + fn test_block() -> Block { + let header = Header::new(0, H256::random(), H256::random(), Default::default(), 1); + let block_data = BlockData::new( + ed25519::Pair::from_string("//Alice", None).unwrap().public().into(), + H256::random(), + Default::default(), + Default::default(), + timestamp_now(), + ); + + Block::new(header, block_data) + } + + #[test] + fn signing_works() { + let block = test_block(); + let signer = ed25519::Pair::from_string("//Alice", None).unwrap(); + + let signature: Signature = + Signature::Ed25519(signer.sign(block.encode().as_slice().into())); + let signed_block: SignedBlock = block.clone().sign_block(&signer); + + assert_eq!(signed_block.block(), &block); + assert_eq!(signed_block.signature(), &signature); + assert!(signed_block.verify_signature()); + } + + #[test] + fn tampered_block_verify_signature_fails() { + let signer = ed25519::Pair::from_string("//Alice", None).unwrap(); + + let mut signed_block: SignedBlock = test_block().sign_block(&signer); + signed_block.block.header.block_number = 1; + + assert!(!signed_block.verify_signature()); + } +} diff --git a/bitacross-worker/sidechain/primitives/src/types/block_data.rs b/bitacross-worker/sidechain/primitives/src/types/block_data.rs new file mode 100644 index 0000000000..a48d4148e4 --- /dev/null +++ b/bitacross-worker/sidechain/primitives/src/types/block_data.rs @@ -0,0 +1,82 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::traits::BlockData as BlockDataTrait; +use codec::{Decode, Encode}; +use sp_core::{ed25519, H256}; +use sp_std::vec::Vec; + +pub type Timestamp = u64; + +#[cfg(feature = "std")] +use serde::{Deserialize, Serialize}; + +#[derive(PartialEq, Eq, Clone, Encode, Decode, Debug)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +pub struct BlockData { + pub timestamp: u64, + /// Parentchain header this block is based on. + pub layer_one_head: H256, + /// Must be registered on layer one as an enclave for the respective shard. + pub block_author: ed25519::Public, + /// Hashes of signed trusted operations. + pub signed_top_hashes: Vec, + /// Encrypted state payload. + pub encrypted_state_diff: Vec, +} + +impl BlockDataTrait for BlockData { + type Public = ed25519::Public; + + /// Get timestamp of block. + fn timestamp(&self) -> Timestamp { + self.timestamp + } + /// Get layer one head of block. + fn layer_one_head(&self) -> H256 { + self.layer_one_head + } + /// Get author of block. + fn block_author(&self) -> &Self::Public { + &self.block_author + } + /// Get reference of extrinisics of block. + fn signed_top_hashes(&self) -> &[H256] { + &self.signed_top_hashes + } + /// Get encrypted payload. + fn encrypted_state_diff(&self) -> &Vec { + &self.encrypted_state_diff + } + /// Constructs block data. + fn new( + block_author: Self::Public, + layer_one_head: H256, + signed_top_hashes: Vec, + encrypted_state_diff: Vec, + timestamp: Timestamp, + ) -> BlockData { + // create block + BlockData { + timestamp, + layer_one_head, + signed_top_hashes, + block_author, + encrypted_state_diff, + } + } +} diff --git a/bitacross-worker/sidechain/primitives/src/types/header.rs b/bitacross-worker/sidechain/primitives/src/types/header.rs new file mode 100644 index 0000000000..962917f534 --- /dev/null +++ b/bitacross-worker/sidechain/primitives/src/types/header.rs @@ -0,0 +1,91 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 the sidechain +use crate::traits::Header as HeaderTrait; +use codec::{Decode, Encode}; +use scale_info::TypeInfo; +use sp_core::H256; +use sp_runtime::traits::{BlakeTwo256, Hash}; +use sp_std::prelude::*; + +#[cfg(feature = "std")] +use serde::{Deserialize, Serialize}; + +pub use itp_types::ShardIdentifier; + +#[derive(PartialEq, Eq, Clone, Encode, Decode, Debug, Copy, Default, TypeInfo)] +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +pub struct SidechainHeader { + /// The parent hash. + pub parent_hash: H256, + + /// The block number. + pub block_number: u64, + + /// The Shard id. + pub shard_id: ShardIdentifier, + + /// The payload hash. + pub block_data_hash: H256, + + /// The latest finalized block number + pub next_finalization_block_number: u64, +} + +impl SidechainHeader { + /// get the `blake2_256` hash of the header. + pub fn hash(&self) -> H256 { + self.using_encoded(BlakeTwo256::hash) + } +} + +impl HeaderTrait for SidechainHeader { + type ShardIdentifier = H256; + + fn block_number(&self) -> u64 { + self.block_number + } + fn parent_hash(&self) -> H256 { + self.parent_hash + } + fn shard_id(&self) -> Self::ShardIdentifier { + self.shard_id + } + fn block_data_hash(&self) -> H256 { + self.block_data_hash + } + fn next_finalization_block_number(&self) -> u64 { + self.next_finalization_block_number + } + + fn new( + block_number: u64, + parent_hash: H256, + shard: Self::ShardIdentifier, + block_data_hash: H256, + next_finalization_block_number: u64, + ) -> SidechainHeader { + SidechainHeader { + block_number, + parent_hash, + shard_id: shard, + block_data_hash, + next_finalization_block_number, + } + } +} diff --git a/bitacross-worker/sidechain/primitives/src/types/mod.rs b/bitacross-worker/sidechain/primitives/src/types/mod.rs new file mode 100644 index 0000000000..2056953387 --- /dev/null +++ b/bitacross-worker/sidechain/primitives/src/types/mod.rs @@ -0,0 +1,22 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 block; +pub mod block_data; +pub mod header; + +pub use block::*; diff --git a/bitacross-worker/sidechain/rpc-handler/Cargo.toml b/bitacross-worker/sidechain/rpc-handler/Cargo.toml new file mode 100644 index 0000000000..58cf470bf7 --- /dev/null +++ b/bitacross-worker/sidechain/rpc-handler/Cargo.toml @@ -0,0 +1,57 @@ +[package] +name = "its-rpc-handler" +version = "0.9.0" +authors = ['Trust Computing GmbH ', 'Integritee AG '] +edition = "2021" + +[dependencies] +# sgx dependencies +sgx_tstd = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git", optional = true } + +# local dependencies +itp-rpc = { path = "../../core-primitives/rpc", default-features = false } +itp-stf-primitives = { path = "../../core-primitives/stf-primitives", default-features = false } +itp-top-pool-author = { path = "../../core-primitives/top-pool-author", default-features = false } +itp-types = { path = "../../core-primitives/types", default-features = false } +itp-utils = { path = "../../core-primitives/utils", default-features = false } +its-primitives = { path = "../primitives", default-features = false } + +litentry-primitives = { path = "../../litentry/primitives", default-features = false } + +# sgx enabled external libraries +futures_sgx = { package = "futures", git = "https://github.com/mesalock-linux/futures-rs-sgx", optional = true } +jsonrpc-core_sgx = { package = "jsonrpc-core", git = "https://github.com/scs/jsonrpc", branch = "no_std_v18", default-features = false, optional = true } +rust-base58_sgx = { package = "rust-base58", rev = "sgx_1.1.3", git = "https://github.com/mesalock-linux/rust-base58-sgx", optional = true, default-features = false, features = ["mesalock_sgx"] } + +# std compatible external libraries (make sure these versions match with the sgx-enabled ones above) +futures = { version = "0.3.8", optional = true } +jsonrpc-core = { version = "18", optional = true } +rust-base58 = { package = "rust-base58", version = "0.0.4", optional = true } + +# no-std compatible libraries +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +log = { version = "0.4", default-features = false } +sp-core = { default-features = false, features = ["full_crypto"], git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } + +[features] +default = ["std"] +std = [ + "futures", + "itp-rpc/std", + "itp-stf-primitives/std", + "itp-top-pool-author/std", + "itp-types/std", + "its-primitives/std", + "litentry-primitives/std", + "jsonrpc-core", + "log/std", + "rust-base58", +] +sgx = [ + "futures_sgx", + "sgx_tstd", + "itp-rpc/sgx", + "itp-top-pool-author/sgx", + "jsonrpc-core_sgx", + "rust-base58_sgx", +] diff --git a/bitacross-worker/sidechain/rpc-handler/src/constants.rs b/bitacross-worker/sidechain/rpc-handler/src/constants.rs new file mode 100644 index 0000000000..bff9ea019b --- /dev/null +++ b/bitacross-worker/sidechain/rpc-handler/src/constants.rs @@ -0,0 +1,24 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +//! Sidechain constants + +// RPC method names. +pub const RPC_METHOD_NAME_IMPORT_BLOCKS: &str = "sidechain_importBlock"; +pub const RPC_METHOD_NAME_FETCH_BLOCKS_FROM_PEER: &str = "sidechain_fetchBlocksFromPeer"; +pub const RPC_METHOD_NAME_LATEST_BLOCK: &str = "sidechain_latestBlock"; +pub const RPC_METHOD_NAME_BLOCK_HASH: &str = "sidechain_blockHash"; diff --git a/bitacross-worker/sidechain/rpc-handler/src/direct_top_pool_api.rs b/bitacross-worker/sidechain/rpc-handler/src/direct_top_pool_api.rs new file mode 100644 index 0000000000..5de9ed776a --- /dev/null +++ b/bitacross-worker/sidechain/rpc-handler/src/direct_top_pool_api.rs @@ -0,0 +1,320 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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(all(not(feature = "std"), feature = "sgx"))] +use crate::sgx_reexport_prelude::*; +use core::fmt::Debug; + +#[cfg(feature = "std")] +use rust_base58::base58::FromBase58; + +#[cfg(feature = "sgx")] +use base58::FromBase58; + +use codec::{Decode, Encode}; +use itp_rpc::RpcReturnValue; +use itp_stf_primitives::types::AccountId; +use itp_top_pool_author::traits::AuthorApi; +use itp_types::{DirectRequestStatus, RsaRequest, ShardIdentifier, TrustedOperationStatus}; +use itp_utils::{FromHexPrefixed, ToHexPrefixed}; +use jsonrpc_core::{futures::executor, serde_json::json, Error as RpcError, IoHandler, Params}; +use litentry_primitives::AesRequest; +use log::*; +use std::{ + borrow::ToOwned, + format, + string::{String, ToString}, + sync::Arc, + vec, + vec::Vec, +}; + +type Hash = sp_core::H256; + +pub fn add_top_pool_direct_rpc_methods( + top_pool_author: Arc, + mut io_handler: IoHandler, +) -> IoHandler +where + R: AuthorApi + Send + Sync + 'static, + TCS: PartialEq + Encode + Decode + Debug + Send + Sync + 'static, + G: PartialEq + Encode + Decode + Debug + Send + Sync + 'static, +{ + let watch_author = top_pool_author.clone(); + io_handler.add_sync_method("author_submitAndWatchRsaRequest", move |params: Params| { + debug!("worker_api_direct rpc was called: author_submitAndWatchRsaRequest"); + let json_value = match author_submit_extrinsic_inner( + watch_author.clone(), + params, + Some("author_submitAndWatchBroadcastedRsaRequest".to_owned()), + ) { + Ok(hash_value) => RpcReturnValue { + do_watch: true, + value: vec![], + status: DirectRequestStatus::TrustedOperationStatus( + TrustedOperationStatus::Submitted, + hash_value, + ), + } + .to_hex(), + Err(error) => compute_hex_encoded_return_error(error.as_str()), + }; + Ok(json!(json_value)) + }); + + // author_submitAndWatchBroadcastedRsaRequest + let watch_author = top_pool_author.clone(); + io_handler.add_sync_method( + "author_submitAndWatchBroadcastedRsaRequest", + move |params: Params| { + let json_value = match author_submit_extrinsic_inner(watch_author.clone(), params, None) + { + Ok(hash_value) => { + RpcReturnValue { + do_watch: true, + value: vec![], + status: DirectRequestStatus::TrustedOperationStatus( + TrustedOperationStatus::Submitted, + hash_value, + ), + } + } + .to_hex(), + Err(error) => compute_hex_encoded_return_error(error.as_str()), + }; + Ok(json!(json_value)) + }, + ); + + // author_submitRsaRequest + let submit_author = top_pool_author.clone(); + io_handler.add_sync_method("author_submitRsaRequest", move |params: Params| { + debug!("worker_api_direct rpc was called: author_submitRsaRequest"); + let json_value = match author_submit_extrinsic_inner(submit_author.clone(), params, None) { + Ok(hash_value) => RpcReturnValue { + do_watch: false, + value: vec![], + status: DirectRequestStatus::TrustedOperationStatus( + TrustedOperationStatus::Submitted, + hash_value, + ), + } + .to_hex(), + Err(error) => compute_hex_encoded_return_error(error.as_str()), + }; + Ok(json!(json_value)) + }); + + // Litentry: a morphling of `author_submitAndWatchRsaRequest` + // a different name is used to highlight the request type + let watch_author = top_pool_author.clone(); + io_handler.add_sync_method("author_submitAndWatchAesRequest", move |params: Params| { + debug!("worker_api_direct rpc was called: author_submitAndWatchAesRequest"); + let json_value = match author_submit_aes_request_inner( + watch_author.clone(), + params, + Some("author_submitAndWatchBroadcastedAesRequest".to_owned()), + ) { + Ok(hash_value) => RpcReturnValue { + do_watch: true, + value: vec![], + status: DirectRequestStatus::TrustedOperationStatus( + TrustedOperationStatus::Submitted, + hash_value, + ), + } + .to_hex(), + Err(error) => compute_hex_encoded_return_error(error.as_str()), + }; + Ok(json!(json_value)) + }); + + let watch_author = top_pool_author.clone(); + io_handler.add_sync_method( + "author_submitAndWatchBroadcastedAesRequest", + move |params: Params| { + let json_value = + match author_submit_aes_request_inner(watch_author.clone(), params, None) { + Ok(hash_value) => RpcReturnValue { + do_watch: true, + value: vec![], + status: DirectRequestStatus::TrustedOperationStatus( + TrustedOperationStatus::Submitted, + hash_value, + ), + } + .to_hex(), + Err(error) => compute_hex_encoded_return_error(error.as_str()), + }; + Ok(json!(json_value)) + }, + ); + + // author_pendingExtrinsics + let pending_author = top_pool_author.clone(); + io_handler.add_sync_method("author_pendingExtrinsics", move |params: Params| { + debug!("worker_api_direct rpc was called: author_pendingExtrinsics"); + match params.parse::>() { + Ok(shards) => { + let mut retrieved_operations = vec![]; + for shard_base58 in shards.iter() { + let shard = match decode_shard_from_base58(shard_base58.as_str()) { + Ok(id) => id, + Err(msg) => { + let error_msg: String = + format!("Could not retrieve pending calls due to: {}", msg); + return Ok(json!(compute_hex_encoded_return_error(error_msg.as_str()))) + }, + }; + if let Ok(vec_of_operations) = pending_author.pending_tops(shard) { + retrieved_operations.push(vec_of_operations); + } + } + let json_value = RpcReturnValue { + do_watch: false, + value: retrieved_operations.encode(), + status: DirectRequestStatus::Ok, + }; + Ok(json!(json_value.to_hex())) + }, + Err(e) => { + let error_msg: String = format!("Could not retrieve pending calls due to: {}", e); + Ok(json!(compute_hex_encoded_return_error(error_msg.as_str()))) + }, + } + }); + + let pending_author = top_pool_author; + io_handler.add_sync_method("author_pendingTrustedCallsFor", move |params: Params| { + debug!("worker_api_direct rpc was called: author_pendingTrustedCallsFor"); + match params.parse::<(String, String)>() { + Ok((shard_base58, account_hex)) => { + let shard = match decode_shard_from_base58(shard_base58.as_str()) { + Ok(id) => id, + Err(msg) => { + let error_msg: String = + format!("Could not retrieve pending trusted calls due to: {}", msg); + return Ok(json!(compute_hex_encoded_return_error(error_msg.as_str()))) + }, + }; + let account = match AccountId::from_hex(account_hex.as_str()) { + Ok(acc) => acc, + Err(msg) => { + let error_msg: String = + format!("Could not retrieve pending trusted calls due to: {:?}", msg); + return Ok(json!(compute_hex_encoded_return_error(error_msg.as_str()))) + }, + }; + let trusted_calls = pending_author.get_pending_trusted_calls_for(shard, &account); + let json_value = RpcReturnValue { + do_watch: false, + value: trusted_calls.encode(), + status: DirectRequestStatus::Ok, + }; + Ok(json!(json_value.to_hex())) + }, + Err(e) => { + let error_msg: String = + format!("Could not retrieve pending trusted calls due to: {}", e); + Ok(json!(compute_hex_encoded_return_error(error_msg.as_str()))) + }, + } + }); + + io_handler +} + +// converts the rpc methods vector to a string and adds commas and brackets for readability +pub fn decode_shard_from_base58(shard_base58: &str) -> Result { + let shard_vec = match shard_base58.from_base58() { + Ok(vec) => vec, + Err(_) => return Err("Invalid base58 format of shard id".to_owned()), + }; + let shard = match ShardIdentifier::decode(&mut shard_vec.as_slice()) { + Ok(hash) => hash, + Err(_) => return Err("Shard ID is not of type H256".to_owned()), + }; + Ok(shard) +} + +fn compute_hex_encoded_return_error(error_msg: &str) -> String { + RpcReturnValue::from_error_message(error_msg).to_hex() +} + +// we expect our `params` to be "by-position array" +// see https://www.jsonrpc.org/specification#parameter_structures +fn get_request_payload(params: Params) -> Result { + let s_vec = params.parse::>().map_err(|e| format!("{}", e))?; + + let s = s_vec.get(0).ok_or_else(|| "Empty params".to_string())?; + debug!("Request payload: {}", s); + Ok(s.to_owned()) +} + +fn author_submit_extrinsic_inner( + author: Arc, + params: Params, + json_rpc_method: Option, +) -> Result +where + R: AuthorApi + Send + Sync + 'static, + TCS: PartialEq + Encode + Decode + Debug + Send + Sync + 'static, + G: PartialEq + Encode + Decode + Debug + Send + Sync + 'static, +{ + let payload = get_request_payload(params)?; + let request = RsaRequest::from_hex(&payload).map_err(|e| format!("{:?}", e))?; + + let response: Result = if let Some(method) = json_rpc_method { + executor::block_on(async { author.watch_and_broadcast_top(request, method).await }) + } else { + executor::block_on(async { author.watch_top(request).await }) + }; + + match &response { + Ok(h) => debug!("Trusted operation submitted successfully ({:?})", h), + Err(e) => warn!("Submitting trusted operation failed: {:?}", e), + } + + response.map_err(|e| format!("{:?}", e)) +} + +fn author_submit_aes_request_inner( + author: Arc, + params: Params, + json_rpc_method: Option, +) -> Result +where + R: AuthorApi + Send + Sync + 'static, + TCS: PartialEq + Encode + Decode + Debug + Send + Sync + 'static, + G: PartialEq + Encode + Decode + Debug + Send + Sync + 'static, +{ + let payload = get_request_payload(params)?; + let request = AesRequest::from_hex(&payload).map_err(|e| format!("{:?}", e))?; + + let response: Result = if let Some(method) = json_rpc_method { + executor::block_on(async { author.watch_and_broadcast_top(request, method).await }) + } else { + executor::block_on(async { author.watch_top(request).await }) + }; + + match &response { + Ok(h) => debug!("AesRequest submitted successfully ({:?})", h), + Err(e) => warn!("Submitting AesRequest failed: {:?}", e), + } + + response.map_err(|e| format!("{:?}", e)) +} diff --git a/bitacross-worker/sidechain/rpc-handler/src/import_block_api.rs b/bitacross-worker/sidechain/rpc-handler/src/import_block_api.rs new file mode 100644 index 0000000000..a34ff829ef --- /dev/null +++ b/bitacross-worker/sidechain/rpc-handler/src/import_block_api.rs @@ -0,0 +1,126 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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(all(not(feature = "std"), feature = "sgx"))] +use crate::sgx_reexport_prelude::*; + +use crate::constants::RPC_METHOD_NAME_IMPORT_BLOCKS; +use itp_utils::FromHexPrefixed; +use its_primitives::types::SignedBlock; +use jsonrpc_core::{IoHandler, Params, Value}; +use log::*; +use std::{borrow::ToOwned, fmt::Debug, string::String, vec::Vec}; + +pub fn add_import_block_rpc_method( + import_fn: ImportFn, + mut io_handler: IoHandler, +) -> IoHandler +where + ImportFn: Fn(SignedBlock) -> Result<(), Error> + Sync + Send + 'static, + Error: Debug, +{ + let sidechain_import_import_name: &str = RPC_METHOD_NAME_IMPORT_BLOCKS; + io_handler.add_sync_method(sidechain_import_import_name, move |sidechain_blocks: Params| { + debug!("{} rpc. Params: {:?}", RPC_METHOD_NAME_IMPORT_BLOCKS, sidechain_blocks); + + let hex_encoded_block_vec: Vec = sidechain_blocks.parse()?; + + let blocks = Vec::::from_hex(&hex_encoded_block_vec[0]).map_err(|_| { + jsonrpc_core::error::Error::invalid_params_with_details( + "Could not decode Vec", + hex_encoded_block_vec, + ) + })?; + + debug!("{}. Blocks: {:?}", RPC_METHOD_NAME_IMPORT_BLOCKS, blocks); + + for block in blocks { + info!("Add block {} to import queue", block.block.header.block_number); + let _ = import_fn(block).map_err(|e| { + let error = jsonrpc_core::error::Error::invalid_params_with_details( + "Failed to import Block.", + e, + ); + error!("{:?}", error); + }); + } + + Ok(Value::String("ok".to_owned())) + }); + + io_handler +} + +#[cfg(test)] +pub mod tests { + + use super::*; + + fn rpc_response(result: T) -> String { + format!(r#"{{"jsonrpc":"2.0","result":{},"id":1}}"#, result.to_string()) + } + + fn io_handler() -> IoHandler { + let io_handler = IoHandler::new(); + add_import_block_rpc_method::<_, String>(|_| Ok(()), io_handler) + } + + #[test] + pub fn sidechain_import_block_is_ok() { + let io = io_handler(); + let enclave_req = r#"{"jsonrpc":"2.0","method":"sidechain_importBlock","params":["0x04a7417cf9370af5ea5cf64f107aa49ebf320dbf10c6d0ef200ef7c5d57c9f4b956d000000000000007dba6b8e1f8f38f7f517dbd4a3eaeb27a97958d7a1d1541f69db5d24b3c48cd0dc376b08fcb44dca19a08a0445023a5f4bef80019b518296313e83fc105c669064000000000000005f08a5f98301000081bd02d7e1f8b6ab9a64fa8fdaa379fc1c9208bf0d341689c2342ce8a314e174768f40dfe0fadf2e7347f2ec83a541427a0931ce54ce7a4506184198c2e7aed3006d031b2cc662bbcd54ca1cc09f0021d956673c4905b07edf0b9f323d2078fc4d8cbaefe34353bc731f9a1ef14dfd6b58274a6efbbc6c2c4261d304b979305f501819df33452f2f276add2f3650b825c700abf23790a6787baf1cabb208633eb33fb66e987a99193fbd2c07374502dc0fdff6d7a5d462b2a9c0196711437aa6a30ce52ae6e4818a643df256c026b08d7ccca2de46f368630512073b271397719f34c9b8612c7f1707d06b45206da268f49b5b5159b3418093512700ecb67ccbc5bd9a1731a9c67372b39ec3761d12afb445a6c8580b97a090f4bb06ff70001bc44f7f91ada7f92f0064188d08c16594ddb4fd09f65bee5f4b3c92b80091d3fe5bc89f3fb95a96941563126a6379b806981dd7f225c7e3ac4e1ee0509de406"],"id":1}"#; + + let response_string = io.handle_request_sync(enclave_req).unwrap(); + + assert_eq!(response_string, rpc_response("\"ok\"")); + } + + #[test] + pub fn sidechain_import_block_returns_invalid_param_err() { + let io = io_handler(); + let enclave_req = + r#"{"jsonrpc":"2.0","method":"sidechain_importBlock","params":[4,214,133,100],"id":1}"#; + + let response_string = io.handle_request_sync(enclave_req).unwrap(); + + let err_msg = r#"{"jsonrpc":"2.0","error":{"code":-32602,"message":"Invalid params: invalid type: integer `4`, expected a string."},"id":1}"#; + assert_eq!(response_string, err_msg); + } + + #[test] + pub fn sidechain_import_block_returns_decode_err() { + let io = io_handler(); + let enclave_req = r#"{"jsonrpc":"2.0","method":"sidechain_importBlock","params":["SophisticatedInvalidParam"],"id":1}"#; + + let response_string = io.handle_request_sync(enclave_req).unwrap(); + + let err_msg = r#"{"jsonrpc":"2.0","error":{"code":-32602,"message":"Invalid parameters: Could not decode Vec","data":"[\"SophisticatedInvalidParam\"]"},"id":1}"#; + assert_eq!(response_string, err_msg); + } + + pub fn sidechain_import_block_returns_decode_err_for_valid_hex() { + let io = io_handler(); + + let enclave_req = + r#"{"jsonrpc":"2.0","method":"sidechain_importBlock","params": ["0x11"],"id":1}"#; + + let response_string = io.handle_request_sync(enclave_req).unwrap(); + + let err_msg = r#"{"jsonrpc":"2.0","error":{"code":-32602,"message":"Invalid parameters: Could not decode Vec","data":"[17]"},"id":1}"#; + assert_eq!(response_string, err_msg); + } +} diff --git a/bitacross-worker/sidechain/rpc-handler/src/lib.rs b/bitacross-worker/sidechain/rpc-handler/src/lib.rs new file mode 100644 index 0000000000..5daf1d1f7e --- /dev/null +++ b/bitacross-worker/sidechain/rpc-handler/src/lib.rs @@ -0,0 +1,38 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +#![feature(trait_alias)] +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg(all(feature = "std", feature = "sgx"))] +compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the same time"); + +extern crate core; +#[cfg(all(not(feature = "std"), feature = "sgx"))] +extern crate sgx_tstd as std; + +// re-export module to properly feature gate sgx and regular std environment +#[cfg(all(not(feature = "std"), feature = "sgx"))] +pub mod sgx_reexport_prelude { + pub use futures_sgx as futures; + pub use jsonrpc_core_sgx as jsonrpc_core; + pub use rust_base58_sgx as base58; +} + +pub mod constants; +pub mod direct_top_pool_api; +pub mod import_block_api; diff --git a/bitacross-worker/sidechain/sidechain-crate/Cargo.toml b/bitacross-worker/sidechain/sidechain-crate/Cargo.toml new file mode 100644 index 0000000000..dee5728123 --- /dev/null +++ b/bitacross-worker/sidechain/sidechain-crate/Cargo.toml @@ -0,0 +1,36 @@ +[package] +name = "its-sidechain" +version = "0.9.0" +authors = ['Trust Computing GmbH ', 'Integritee AG '] +edition = "2021" + +[features] +default = ["std"] +std = [ + "its-block-composer/std", + "its-consensus-aura/std", + "its-consensus-common/std", + "its-consensus-slots/std", + "its-rpc-handler/std", + "its-primitives/std", + "its-state/std", + "its-validateer-fetch/std", +] +sgx = [ + "its-block-composer/sgx", + "its-consensus-aura/sgx", + "its-consensus-common/sgx", + "its-consensus-slots/sgx", + "its-rpc-handler/sgx", + "its-state/sgx", +] + +[dependencies] +its-block-composer = { path = "../block-composer", default-features = false } +its-consensus-aura = { path = "../consensus/aura", default-features = false } +its-consensus-common = { path = "../consensus/common", default-features = false } +its-consensus-slots = { path = "../consensus/slots", default-features = false } +its-primitives = { path = "../primitives", default-features = false } +its-rpc-handler = { path = "../rpc-handler", default-features = false } +its-state = { path = "../state", default-features = false } +its-validateer-fetch = { path = "../validateer-fetch", default-features = false } diff --git a/bitacross-worker/sidechain/sidechain-crate/src/lib.rs b/bitacross-worker/sidechain/sidechain-crate/src/lib.rs new file mode 100644 index 0000000000..59821318a8 --- /dev/null +++ b/bitacross-worker/sidechain/sidechain-crate/src/lib.rs @@ -0,0 +1,39 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +//! Reexport all the sidechain stuff in one crate + +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg(all(feature = "std", feature = "sgx"))] +compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the same time"); + +pub use its_block_composer as block_composer; + +pub use its_consensus_aura as aura; + +pub use its_consensus_common as consensus_common; + +pub use its_consensus_slots as slots; + +pub use its_primitives as primitives; + +pub use its_rpc_handler as rpc_handler; + +pub use its_state as state; + +pub use its_validateer_fetch as validateer_fetch; diff --git a/bitacross-worker/sidechain/state/Cargo.toml b/bitacross-worker/sidechain/state/Cargo.toml new file mode 100644 index 0000000000..538fb34c50 --- /dev/null +++ b/bitacross-worker/sidechain/state/Cargo.toml @@ -0,0 +1,56 @@ +[package] +name = "its-state" +version = "0.9.0" +authors = ['Trust Computing GmbH ', 'Integritee AG '] +edition = "2021" + +[dependencies] +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive", "chain-error"] } +frame-support = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } +log = { version = "0.4", default-features = false } + +# optional std deps +thiserror = { version = "1.0.9", optional = true } + +# sgx deps +sgx_tstd = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git", optional = true } + +# sgx forks +thiserror_sgx = { package = "thiserror", version = "1.0.9", git = "https://github.com/mesalock-linux/thiserror-sgx", tag = "sgx_1.1.3", optional = true } + +# local deps +itp-sgx-externalities = { default-features = false, path = "../../core-primitives/substrate-sgx/externalities" } +itp-storage = { path = "../../core-primitives/storage", default-features = false } +its-primitives = { path = "../primitives", default-features = false } +sp-io = { optional = true, default-features = false, features = ["disable_oom", "disable_panic_handler", "disable_allocator"], path = "../../core-primitives/substrate-sgx/sp-io" } + +# substrate deps +sp-core = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } +sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } + +[features] +default = ["std"] +std = [ + "log/std", + # substrate + "sp-core/std", + # local crates + "itp-sgx-externalities/std", + "itp-storage/std", + "its-primitives/std", + "sp-io/std", + # optional std crates + "codec/std", + "thiserror", + "sp-runtime/std", +] +sgx = [ + # teaclave + "sgx_tstd", + # local crates + "itp-sgx-externalities/sgx", + "itp-storage/sgx", + "sp-io/sgx", + # sgx versions of std crates + "thiserror_sgx", +] diff --git a/bitacross-worker/sidechain/state/src/error.rs b/bitacross-worker/sidechain/state/src/error.rs new file mode 100644 index 0000000000..82838b376e --- /dev/null +++ b/bitacross-worker/sidechain/state/src/error.rs @@ -0,0 +1,31 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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(all(not(feature = "std"), feature = "sgx"))] +use crate::sgx_reexports::*; + +use std::string::String; + +#[derive(Debug, thiserror::Error, PartialEq, Eq)] +pub enum Error { + #[error("Invalid apriori state hash supplied")] + InvalidAprioriHash, + #[error("Invalid storage diff")] + InvalidStorageDiff, + #[error("Codec error when accessing module: {1}, storage: {2}. Error: {0:?}")] + DB(codec::Error, String, String), +} diff --git a/bitacross-worker/sidechain/state/src/impls.rs b/bitacross-worker/sidechain/state/src/impls.rs new file mode 100644 index 0000000000..b69727085c --- /dev/null +++ b/bitacross-worker/sidechain/state/src/impls.rs @@ -0,0 +1,184 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +//! Implement the sidechain state traits. + +use crate::{Error, SidechainState, StateUpdate}; +use codec::{Decode, Encode}; +use core::fmt::Debug; +use frame_support::ensure; +use itp_sgx_externalities::{SgxExternalitiesTrait, StateHash}; +use itp_storage::keys::storage_value_key; +use log::{debug, error, info}; +use sp_io::{storage, KillStorageResult}; + +impl SidechainState for T +where + ::SgxExternalitiesType: Encode, +{ + type Externalities = Self; + type StateUpdate = StateUpdate; + + fn apply_state_update(&mut self, state_payload: &Self::StateUpdate) -> Result<(), Error> { + info!("Current state size: {}", self.state().encoded_size()); + debug!("Current hash: {}", self.hash()); + debug!("State_payload hash: {}", state_payload.state_hash_apriori()); + debug!("self is: {:?}", &self); + debug!("state_payload is: {:?}", &state_payload); + ensure!(self.hash() == state_payload.state_hash_apriori(), Error::InvalidAprioriHash); + + self.execute_with(|| { + state_payload.state_update.iter().for_each(|(k, v)| { + match v { + Some(value) => storage::set(k, value), + None => storage::clear(k), + }; + }) + }); + + ensure!(self.hash() == state_payload.state_hash_aposteriori(), Error::InvalidStorageDiff); + self.prune_state_diff(); + Ok(()) + } + + fn get_with_name(&self, module_prefix: &str, storage_prefix: &str) -> Option { + let res = self + .get(&storage_value_key(module_prefix, storage_prefix)) + .map(|v| Decode::decode(&mut v.as_slice())) + .transpose(); + + match res { + Ok(res) => res, + Err(e) => { + error!( + "Error decoding storage: {}, {}. Error: {:?}", + module_prefix, storage_prefix, e + ); + None + }, + } + } + + fn set_with_name(&mut self, module_prefix: &str, storage_prefix: &str, value: V) { + self.set(&storage_value_key(module_prefix, storage_prefix), &value.encode()) + } + + fn clear_with_name(&mut self, module_prefix: &str, storage_prefix: &str) { + self.clear(&storage_value_key(module_prefix, storage_prefix)) + } + + fn clear_prefix_with_name( + &mut self, + module_prefix: &str, + storage_prefix: &str, + ) -> KillStorageResult { + self.clear_sidechain_prefix(&storage_value_key(module_prefix, storage_prefix)) + } + + fn set(&mut self, key: &[u8], value: &[u8]) { + self.execute_with(|| sp_io::storage::set(key, value)) + } + + fn clear(&mut self, key: &[u8]) { + self.execute_with(|| sp_io::storage::clear(key)) + } + + fn clear_sidechain_prefix(&mut self, prefix: &[u8]) -> KillStorageResult { + self.execute_with(|| sp_io::storage::clear_prefix(prefix, None)) + } +} + +#[cfg(test)] +pub mod tests { + use super::*; + use crate::StateUpdate; + use frame_support::{assert_err, assert_ok}; + use itp_sgx_externalities::{SgxExternalities, SgxExternalitiesTrait}; + use sp_core::H256; + + pub fn default_db() -> SgxExternalities { + SgxExternalities::default() + } + + #[test] + pub fn apply_state_update_works() { + let mut state1 = default_db(); + let mut state2 = default_db(); + + let apriori = state1.hash(); + state1.set(b"Hello", b"World"); + let aposteriori = state1.hash(); + + let mut state_update = StateUpdate::new(apriori, aposteriori, state1.state_diff().clone()); + + assert_ok!(state2.apply_state_update(&mut state_update)); + assert_eq!(state2.hash(), aposteriori); + assert_eq!(state2.get(b"Hello").unwrap(), b"World"); + assert!(state2.state_diff().is_empty()); + } + + #[test] + pub fn apply_state_update_returns_storage_hash_mismatch_err() { + let mut state1 = default_db(); + let mut state2 = default_db(); + + let apriori = H256::from([1; 32]); + state1.set(b"Hello", b"World"); + let aposteriori = state1.hash(); + + let mut state_update = StateUpdate::new(apriori, aposteriori, state1.state_diff().clone()); + + assert_err!(state2.apply_state_update(&mut state_update), Error::InvalidAprioriHash); + assert_eq!(state2, default_db()); + } + + #[test] + pub fn apply_state_update_returns_invalid_storage_diff_err() { + let mut state1 = default_db(); + let mut state2 = default_db(); + + let apriori = state1.hash(); + state1.set(b"Hello", b"World"); + let aposteriori = H256::from([1; 32]); + + let mut state_update = StateUpdate::new(apriori, aposteriori, state1.state_diff().clone()); + + assert_err!(state2.apply_state_update(&mut state_update), Error::InvalidStorageDiff); + // After an error, the state is not guaranteed to be reverted and is potentially corrupted! + assert_ne!(state2, default_db()); + } + + #[test] + pub fn sp_io_storage_set_creates_storage_diff() { + let mut state1 = default_db(); + + state1.execute_with(|| { + storage::set(b"hello", b"world"); + }); + + assert_eq!(state1.state_diff().get(&b"hello"[..]).unwrap(), &Some(b"world".encode())); + } + + #[test] + pub fn create_state_diff_without_setting_externalities_works() { + let mut state1 = default_db(); + + state1.set(b"hello", b"world"); + + assert_eq!(state1.state_diff().get(&b"hello"[..]).unwrap(), &Some(b"world".encode())); + } +} diff --git a/bitacross-worker/sidechain/state/src/lib.rs b/bitacross-worker/sidechain/state/src/lib.rs new file mode 100644 index 0000000000..01f5e086ec --- /dev/null +++ b/bitacross-worker/sidechain/state/src/lib.rs @@ -0,0 +1,208 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg(all(feature = "std", feature = "sgx"))] +compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the same time"); + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +extern crate sgx_tstd as std; + +mod error; +mod impls; + +pub use error::*; +pub use impls::*; + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +mod sgx_reexports { + pub use thiserror_sgx as thiserror; +} + +use codec::{Decode, Encode}; +use itp_sgx_externalities::{SgxExternalitiesDiffType, SgxExternalitiesTrait, StateHash}; +use its_primitives::{ + traits::Block as SidechainBlockTrait, + types::{BlockHash, BlockNumber, Timestamp}, +}; +use sp_core::H256; +use sp_io::KillStorageResult; +use sp_runtime::traits::Header as ParentchainHeaderTrait; + +/// Contains the necessary data to update the `SidechainDB` when importing a `SidechainBlock`. +#[derive(PartialEq, Eq, Clone, Debug, Encode, Decode)] +pub struct StateUpdate { + /// state hash before the `state_update` was applied. + state_hash_apriori: H256, + /// state hash after the `state_update` was applied. + state_hash_aposteriori: H256, + /// state diff applied to state with hash `state_hash_apriori` + /// leading to state with hash `state_hash_aposteriori` + state_update: SgxExternalitiesDiffType, +} + +impl StateUpdate { + /// get state hash before the `state_update` was applied. + pub fn state_hash_apriori(&self) -> H256 { + self.state_hash_apriori + } + /// get state hash after the `state_update` was applied. + pub fn state_hash_aposteriori(&self) -> H256 { + self.state_hash_aposteriori + } + /// reference to the `state_update` + pub fn state_update(&self) -> &SgxExternalitiesDiffType { + &self.state_update + } + + /// create new `StatePayload` instance. + pub fn new(apriori: H256, aposteriori: H256, update: SgxExternalitiesDiffType) -> StateUpdate { + StateUpdate { + state_hash_apriori: apriori, + state_hash_aposteriori: aposteriori, + state_update: update, + } + } +} +/// Abstraction around the sidechain state. +pub trait SidechainState: Clone { + type Externalities: SgxExternalitiesTrait + StateHash; + + type StateUpdate: Encode + Decode; + + /// Apply the state update to the state. + /// + /// Does not guarantee state consistency in case of a failure. + /// Caller is responsible for discarding corrupt/inconsistent state. + fn apply_state_update(&mut self, state_payload: &Self::StateUpdate) -> Result<(), Error>; + + /// Get a storage value by its full name. + fn get_with_name(&self, module_prefix: &str, storage_prefix: &str) -> Option; + + /// Set a storage value by its full name. + fn set_with_name(&mut self, module_prefix: &str, storage_prefix: &str, value: V); + + /// Clear a storage value by its full name. + fn clear_with_name(&mut self, module_prefix: &str, storage_prefix: &str); + + /// Clear all storage values for the given prefix. + fn clear_prefix_with_name( + &mut self, + module_prefix: &str, + storage_prefix: &str, + ) -> KillStorageResult; + + /// Set a storage value by its storage hash. + fn set(&mut self, key: &[u8], value: &[u8]); + + /// Clear a storage value by its storage hash. + fn clear(&mut self, key: &[u8]); + + /// Clear a all storage values starting the given prefix. + fn clear_sidechain_prefix(&mut self, prefix: &[u8]) -> KillStorageResult; +} + +/// trait to set and get the last sidechain block of the sidechain state +pub trait LastBlockExt { + /// get the last block of the sidechain state + fn get_last_block(&self) -> Option; + + /// set the last block of the sidechain state + fn set_last_block(&mut self, block: &SidechainBlock); +} + +impl + LastBlockExt for E +{ + fn get_last_block(&self) -> Option { + self.get_with_name("System", "LastBlock") + } + + fn set_last_block(&mut self, block: &SidechainBlock) { + self.set_last_block_hash(&block.hash()); + self.set_with_name("System", "LastBlock", block) + } +} + +/// System extension for the `SidechainDB`. +pub trait SidechainSystemExt { + /// Get the last block number. + fn get_block_number(&self) -> Option; + + /// Set the last block number. + fn set_block_number(&mut self, number: &BlockNumber); + + /// Get the last block hash. + fn get_last_block_hash(&self) -> Option; + + /// Set the last block hash. + fn set_last_block_hash(&mut self, hash: &BlockHash); + + /// Get the timestamp of. + fn get_timestamp(&self) -> Option; + + /// Set the timestamp. + fn set_timestamp(&mut self, timestamp: &Timestamp); + + /// Resets the events. + fn reset_events(&mut self); + + /// Litentry: set the parentchain block number from the parentchain header + /// The reasons to put it here instead of calling `ParentchainPalletInterface::update_parentchain_block` somewhere are: + /// 1. The Stf::update_parentchain_block is too heavy weighted, where the whole state is loaded upon each parentchain + /// block import - btw it's not reachable for now as `storage_hashes_to_update_on_block` is always empty + /// 2. It represents the parentchain block number on which the current sidechain block is built, it's more natural to + /// call it in the state preprocessing before proposing a sidechain block + fn set_parentchain_block_number(&mut self, header: &PH); +} + +impl SidechainSystemExt for T { + fn get_block_number(&self) -> Option { + self.get_with_name("System", "Number") + } + + fn set_block_number(&mut self, number: &BlockNumber) { + self.set_with_name("System", "Number", number) + } + + fn get_last_block_hash(&self) -> Option { + self.get_with_name("System", "LastHash") + } + + fn set_last_block_hash(&mut self, hash: &BlockHash) { + self.set_with_name("System", "LastHash", hash) + } + + fn get_timestamp(&self) -> Option { + self.get_with_name("System", "Timestamp") + } + + fn set_timestamp(&mut self, timestamp: &Timestamp) { + self.set_with_name("System", "Timestamp", timestamp) + } + + fn reset_events(&mut self) { + self.clear_with_name("System", "Events"); + self.clear_with_name("System", "EventCount"); + self.clear_prefix_with_name("System", "EventTopics"); + } + + fn set_parentchain_block_number(&mut self, header: &PH) { + self.set_with_name("Parentchain", "Number", header.number()) + } +} diff --git a/bitacross-worker/sidechain/storage/Cargo.toml b/bitacross-worker/sidechain/storage/Cargo.toml new file mode 100644 index 0000000000..7df586896f --- /dev/null +++ b/bitacross-worker/sidechain/storage/Cargo.toml @@ -0,0 +1,34 @@ +[package] +name = "its-storage" +version = "0.9.0" +authors = ['Trust Computing GmbH ', 'Integritee AG '] +edition = "2021" + +[dependencies] +# crate.io +codec = { package = "parity-scale-codec", version = "3.0.0", features = ["derive"] } +log = "0.4" +parking_lot = "0.12.1" +rocksdb = { version = "0.20.1", default_features = false } +serde = { version = "1.0", features = ["derive"] } +thiserror = "1.0" + +# integritee +itp-settings = { path = "../../core-primitives/settings" } + +its-primitives = { path = "../primitives" } + +# Substrate dependencies +sp-core = { git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } + +[dev-dependencies] +# crate.io +mockall = "0.11" +temp-dir = "0.1" +# local +itp-time-utils = { path = "../../core-primitives/time-utils" } +its-test = { path = "../test" } +itp-types = { path = "../../core-primitives/types" } + +[features] +mocks = [] diff --git a/bitacross-worker/sidechain/storage/src/db.rs b/bitacross-worker/sidechain/storage/src/db.rs new file mode 100644 index 0000000000..6e51a749fb --- /dev/null +++ b/bitacross-worker/sidechain/storage/src/db.rs @@ -0,0 +1,67 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +use super::{Error, Result}; +use codec::{Decode, Encode}; +use rocksdb::{WriteBatch, DB}; +use std::path::PathBuf; + +/// Sidechain DB Storage structure: +/// STORED_SHARDS_KEY -> Vec<(Shard)> +/// (LAST_BLOCK_KEY, Shard) -> (Blockhash, BlockNr) (look up current blockchain state) +/// (Shard , Block number) -> Blockhash (needed for block pruning) +/// Blockhash -> Signed Block (actual block storage) + +/// Interface struct to rocks DB +pub struct SidechainDB { + db: DB, +} + +impl SidechainDB { + pub fn open_default(path: PathBuf) -> Result { + Ok(SidechainDB { db: DB::open_default(path)? }) + } + + /// returns the decoded value of the DB entry, if there is one + pub fn get(&self, key: K) -> Result> { + match self.db.get(key.encode())? { + None => Ok(None), + Some(encoded_hash) => Ok(Some(V::decode(&mut encoded_hash.as_slice())?)), + } + } + + /// writes a batch to the DB + pub fn write(&mut self, batch: WriteBatch) -> Result<()> { + self.db.write(batch).map_err(Error::Operational) + } + + /// adds a given key value pair to the batch + pub fn add_to_batch(batch: &mut WriteBatch, key: K, value: V) { + batch.put(key.encode(), &value.encode()) + } + + /// adds a delte key command to the batch + pub fn delete_to_batch(batch: &mut WriteBatch, key: K) { + batch.delete(key.encode()) + } + + /// add an entry to the DB + #[cfg(test)] + pub fn put(&mut self, key: K, value: V) -> Result<()> { + self.db.put(key.encode(), value.encode()).map_err(Error::Operational) + } +} diff --git a/bitacross-worker/sidechain/storage/src/error.rs b/bitacross-worker/sidechain/storage/src/error.rs new file mode 100644 index 0000000000..983909f1a4 --- /dev/null +++ b/bitacross-worker/sidechain/storage/src/error.rs @@ -0,0 +1,34 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 thiserror::Error; + +pub type Result = std::result::Result; + +#[derive(Error, Debug)] +pub enum Error { + #[error("Could not interact with file storage: {0:?}")] + Operational(#[from] rocksdb::Error), + #[error("Last Block of shard {0} not found")] + LastBlockNotFound(String), + #[error("Failed to find parent block")] + FailedToFindParentBlock, + #[error("Could not decode: {0:?}")] + Decode(#[from] codec::Error), + #[error("Given block is not a successor of the last known block")] + HeaderAncestryMismatch, +} diff --git a/bitacross-worker/sidechain/storage/src/fetch_blocks_mock.rs b/bitacross-worker/sidechain/storage/src/fetch_blocks_mock.rs new file mode 100644 index 0000000000..4ba476164d --- /dev/null +++ b/bitacross-worker/sidechain/storage/src/fetch_blocks_mock.rs @@ -0,0 +1,71 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{error::Result, interface::FetchBlocks, storage::LastSidechainBlock}; +use its_primitives::{ + traits::{Block, ShardIdentifierFor}, + types::{BlockHash, BlockNumber, SignedBlock}, +}; + +#[derive(Default)] +pub struct FetchBlocksMock { + blocks_to_be_fetched: Vec, +} + +impl FetchBlocksMock { + pub fn with_blocks(mut self, blocks: Vec) -> Self { + self.blocks_to_be_fetched = blocks; + self + } +} + +impl FetchBlocks for FetchBlocksMock { + fn fetch_all_blocks_after( + &self, + _block_hash: &BlockHash, + _shard_identifier: &ShardIdentifierFor, + ) -> Result> { + Ok(self.blocks_to_be_fetched.clone()) + } + + fn fetch_blocks_in_range( + &self, + _block_hash_from: &BlockHash, + _block_hash_until: &BlockHash, + _shard_identifier: &ShardIdentifierFor, + ) -> Result> { + Ok(self.blocks_to_be_fetched.clone()) + } + + fn latest_block( + &self, + _shard_identifier: &ShardIdentifierFor, + ) -> Option { + self.blocks_to_be_fetched.get(0).map(|block| LastSidechainBlock { + hash: block.block.hash(), + number: block.block.header.block_number, + }) + } + + fn block_hash( + &self, + _block_number: BlockNumber, + _shard_identifier: &ShardIdentifierFor, + ) -> Option { + None + } +} diff --git a/bitacross-worker/sidechain/storage/src/interface.rs b/bitacross-worker/sidechain/storage/src/interface.rs new file mode 100644 index 0000000000..03b41d6d76 --- /dev/null +++ b/bitacross-worker/sidechain/storage/src/interface.rs @@ -0,0 +1,154 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +#[cfg(test)] +use mockall::predicate::*; +#[cfg(test)] +use mockall::*; + +use super::{ + storage::{LastSidechainBlock, SidechainStorage}, + Result, +}; +use its_primitives::{ + traits::{ShardIdentifierFor, SignedBlock as SignedBlockT}, + types::{BlockHash, BlockNumber}, +}; +use parking_lot::RwLock; +use std::path::PathBuf; + +/// Lock wrapper around sidechain storage +pub struct SidechainStorageLock { + storage: RwLock>, +} + +impl SidechainStorageLock { + pub fn from_base_path(path: PathBuf) -> Result> { + Ok(SidechainStorageLock { + storage: RwLock::new(SidechainStorage::::load_from_base_path(path)?), + }) + } +} + +/// Storage interface Trait +#[cfg_attr(test, automock)] +pub trait BlockStorage { + // Type is not working because broadcaster needs to work with the same block type, + // so it needs to be defined somewhere more global. + // type SignedBlock: SignedBlockT; + fn store_blocks(&self, blocks: Vec) -> Result<()>; +} + +pub trait BlockPruner { + /// Prune all blocks except the newest n, where n = `number_of_blocks_to_keep`. + fn prune_blocks_except(&self, number_of_blocks_to_keep: u64); +} + +#[cfg_attr(test, automock)] +pub trait FetchBlocks { + /// Fetch all child blocks of a specified block. + /// + /// Returns an empty vector if specified block hash cannot be found in storage. + fn fetch_all_blocks_after( + &self, + block_hash: &BlockHash, + shard_identifier: &ShardIdentifierFor, + ) -> Result>; + + /// Fetch all blocks within a range, defined by a starting block (lower bound) and end block (upper bound) hash. + /// + /// Does NOT include the bound defining blocks in the result. ]from..until[. + /// Returns an empty vector if 'from' cannot be found in storage. + /// Returns the same as 'fetch_all_blocks_after' if 'until' cannot be found in storage. + fn fetch_blocks_in_range( + &self, + block_hash_from: &BlockHash, + block_hash_until: &BlockHash, + shard_identifier: &ShardIdentifierFor, + ) -> Result>; + + // litentry + fn latest_block( + &self, + shard_identifier: &ShardIdentifierFor, + ) -> Option; + + fn block_hash( + &self, + block_number: BlockNumber, + shard_identifier: &ShardIdentifierFor, + ) -> Option; +} + +impl BlockStorage for SidechainStorageLock { + fn store_blocks(&self, blocks: Vec) -> Result<()> { + self.storage.write().store_blocks(blocks) + } +} + +impl BlockPruner for SidechainStorageLock { + fn prune_blocks_except(&self, number_of_blocks_to_keep: BlockNumber) { + self.storage.write().prune_shards(number_of_blocks_to_keep); + } +} + +impl FetchBlocks for SidechainStorageLock { + fn fetch_all_blocks_after( + &self, + block_hash: &BlockHash, + shard_identifier: &ShardIdentifierFor, + ) -> Result> { + self.storage.read().get_blocks_after(block_hash, shard_identifier) + } + + fn fetch_blocks_in_range( + &self, + block_hash_from: &BlockHash, + block_hash_until: &BlockHash, + shard_identifier: &ShardIdentifierFor, + ) -> Result> { + self.storage + .read() + .get_blocks_in_range(block_hash_from, block_hash_until, shard_identifier) + } + + fn latest_block( + &self, + shard_identifier: &ShardIdentifierFor, + ) -> Option { + self.storage + .read() + .last_block_of_shard(shard_identifier) + .map(|e| LastSidechainBlock { hash: e.hash, number: e.number }) + } + + fn block_hash( + &self, + block_number: BlockNumber, + shard_identifier: &ShardIdentifierFor, + ) -> Option { + match self.storage.read().get_block_hash(shard_identifier, block_number) { + Ok(Some(block_hash)) => + Some(LastSidechainBlock { hash: block_hash, number: block_number }), + Ok(None) => None, + Err(e) => { + log::error!("failed to get block_hash. due to:{:?}", e); + None + }, + } + } +} diff --git a/bitacross-worker/sidechain/storage/src/lib.rs b/bitacross-worker/sidechain/storage/src/lib.rs new file mode 100644 index 0000000000..7b6030ff90 --- /dev/null +++ b/bitacross-worker/sidechain/storage/src/lib.rs @@ -0,0 +1,70 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +#![cfg_attr(test, feature(assert_matches))] + +use its_primitives::types::BlockNumber; +use std::{ + sync::Arc, + thread, + time::{Duration, SystemTime}, +}; + +mod db; +mod error; +pub mod interface; +mod storage; + +#[cfg(test)] +mod storage_tests_get_blocks_after; + +#[cfg(test)] +mod storage_tests_get_blocks_in_range; + +#[cfg(test)] +mod test_utils; + +#[cfg(feature = "mocks")] +pub mod fetch_blocks_mock; + +pub use error::{Error, Result}; +pub use interface::{BlockPruner, BlockStorage, SidechainStorageLock}; +pub use storage::LastSidechainBlock; + +pub fn start_sidechain_pruning_loop( + storage: &Arc, + purge_interval: u64, + purge_limit: BlockNumber, +) where + D: BlockPruner, +{ + let interval_time = Duration::from_secs(purge_interval); + let mut interval_start = SystemTime::now(); + loop { + if let Ok(elapsed) = interval_start.elapsed() { + if elapsed >= interval_time { + // update interval time + interval_start = SystemTime::now(); + storage.prune_blocks_except(purge_limit); + } else { + // sleep for the rest of the interval + let sleep_time = interval_time - elapsed; + thread::sleep(sleep_time); + } + } + } +} diff --git a/bitacross-worker/sidechain/storage/src/storage.rs b/bitacross-worker/sidechain/storage/src/storage.rs new file mode 100644 index 0000000000..4e5667627b --- /dev/null +++ b/bitacross-worker/sidechain/storage/src/storage.rs @@ -0,0 +1,1176 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +use super::{db::SidechainDB, Error, Result}; +use codec::{Decode, Encode}; +use itp_settings::files::SIDECHAIN_STORAGE_PATH; +use its_primitives::{ + traits::{Block as BlockTrait, Header as HeaderTrait, SignedBlock as SignedBlockT}, + types::{BlockHash, BlockNumber}, +}; +use log::*; +use rocksdb::WriteBatch; +use serde::Serialize; +use sp_core::H256; +use std::{collections::HashMap, fmt::Debug, path::PathBuf}; + +/// key value of sidechain db of last block +const LAST_BLOCK_KEY: &[u8] = b"last_sidechainblock"; +/// key value of the stored shards vector +const STORED_SHARDS_KEY: &[u8] = b"stored_shards"; + +/// ShardIdentifier type +type ShardIdentifierFor = + <<::Block as BlockTrait>::HeaderType as HeaderTrait>::ShardIdentifier; + +/// Helper struct, contains the blocknumber +/// and blockhash of the last sidechain block +#[derive(PartialEq, Eq, Clone, Copy, Encode, Decode, Debug, Default, Serialize)] +pub struct LastSidechainBlock { + /// hash of the last sidechain block + pub hash: H256, + /// block number of the last sidechain block + pub number: BlockNumber, +} + +/// Struct used to insert newly produced sidechainblocks +/// into the database +pub struct SidechainStorage { + /// database + db: SidechainDB, + /// shards in database + shards: Vec>, + /// map to last sidechain block of every shard + last_blocks: HashMap, LastSidechainBlock>, +} + +impl SidechainStorage { + /// Loads or initializes the DB at a given path. + /// + /// Loads existing shards and their last blocks in memory for better performance. + pub fn load_from_base_path(base_path: PathBuf) -> Result> { + // load db + let db = SidechainDB::open_default(base_path.join(SIDECHAIN_STORAGE_PATH))?; + let mut storage = SidechainStorage { db, shards: vec![], last_blocks: HashMap::new() }; + storage.shards = storage.load_shards_from_db()?; + // get last block of each shard + for shard in storage.shards.iter() { + if let Some(last_block) = storage.load_last_block_from_db(shard)? { + storage.last_blocks.insert(*shard, last_block); + } else { + // an empty shard sidechain storage should not exist. Consider deleting this shard from the shards list. + error!("Sidechain storage of shard {:?} is empty", shard); + } + } + Ok(storage) + } + + /// gets all shards of currently loaded sidechain db + pub fn shards(&self) -> &Vec> { + &self.shards + } + + /// gets the last block of the current sidechain DB and the given shard + pub fn last_block_of_shard( + &self, + shard: &ShardIdentifierFor, + ) -> Option<&LastSidechainBlock> { + self.last_blocks.get(shard) + } + + /// gets the block hash of the sidechain block of the given shard and block number, if there is such a block + pub fn get_block_hash( + &self, + shard: &ShardIdentifierFor, + block_number: BlockNumber, + ) -> Result> { + self.db.get((*shard, block_number)) + } + + /// gets the block of the given blockhash, if there is such a block + #[allow(unused)] + pub fn get_block(&self, block_hash: &BlockHash) -> Result> { + self.db.get(block_hash) + } + + /// Get all blocks after (i.e. children of) a specified block. + pub fn get_blocks_after( + &self, + block_hash: &BlockHash, + shard_identifier: &ShardIdentifierFor, + ) -> Result> { + // Ensure we find the block in storage (otherwise we would return all blocks for a specific shard). + // The exception is, if the hash is the default hash, which represents block 0. In that case we want to return all blocks. + if block_hash != &BlockHash::default() && self.get_block(block_hash)?.is_none() { + warn!("Could not find starting block in storage, returning empty vector"); + return Ok(Vec::new()) + } + + // We get the latest block and then traverse the parents until we find our starting block. + let last_block_of_shard = self.last_block_of_shard(shard_identifier).ok_or_else(|| { + Error::LastBlockNotFound("Failed to find last block information".to_string()) + })?; + let latest_block = self.get_block(&last_block_of_shard.hash)?.ok_or_else(|| { + Error::LastBlockNotFound("Failed to retrieve last block from storage".to_string()) + })?; + + let mut current_block = latest_block; + let mut blocks_to_return = Vec::::new(); + while ¤t_block.hash() != block_hash { + let parent_block_hash = current_block.block().header().parent_hash(); + + blocks_to_return.push(current_block); + + if parent_block_hash == BlockHash::default() { + break + } + + current_block = + self.get_block(&parent_block_hash)?.ok_or(Error::FailedToFindParentBlock)?; + } + + // Reverse because we iterate from newest to oldest, but result should be oldest first. + blocks_to_return.reverse(); + + Ok(blocks_to_return) + } + + /// Get blocks in a range, defined by 'from' and 'until' (result does NOT include the bound defining blocks). + pub fn get_blocks_in_range( + &self, + block_hash_from: &BlockHash, + block_hash_until: &BlockHash, + shard_identifier: &ShardIdentifierFor, + ) -> Result> { + let all_blocks_from_lower_bound = + self.get_blocks_after(block_hash_from, shard_identifier)?; + + Ok(all_blocks_from_lower_bound + .into_iter() + .take_while(|b| b.hash() != *block_hash_until) + .collect()) + } + + /// Update sidechain storage with blocks. + /// + /// Blocks are iterated through one by one. In case more than one block per shard is included, + /// be sure to give them in the correct order (oldest first). + pub fn store_blocks(&mut self, blocks_to_store: Vec) -> Result<()> { + let mut batch = WriteBatch::default(); + let mut new_shard = false; + for block in blocks_to_store.into_iter() { + if let Err(e) = self.add_block_to_batch(&block, &mut new_shard, &mut batch) { + error!("Could not store block {:?} due to: {:?}", block, e); + }; + } + // Update stored_shards_key -> vec only if a new shard was included, + if new_shard { + SidechainDB::add_to_batch(&mut batch, STORED_SHARDS_KEY, self.shards().clone()); + } + // Store everything. + self.db.write(batch) + } + + /// purges a shard and its block from the db storage + pub fn purge_shard(&mut self, shard: &ShardIdentifierFor) -> Result<()> { + // get last block of shard + let last_block = self.get_last_block_of_shard(shard)?; + + // remove last block from db storage + let mut batch = WriteBatch::default(); + self.delete_last_block(&mut batch, &last_block, shard); + + // Remove the rest of the blocks from the db + let mut current_block_number = last_block.number; + while let Some(previous_block) = self.get_previous_block(shard, current_block_number)? { + current_block_number = previous_block.number; + self.delete_block(&mut batch, &previous_block.hash, ¤t_block_number, shard); + } + // Remove shard from list. + // STORED_SHARDS_KEY -> Vec<(Shard)> + self.shards.retain(|&x| x != *shard); + // Add updated shards to batch. + SidechainDB::add_to_batch(&mut batch, STORED_SHARDS_KEY, &self.shards); + // Update DB + self.db.write(batch) + } + + /// purges a shard and its block from the db storage + /// FIXME: Add delete functions? + pub fn prune_shard_from_block_number( + &mut self, + shard: &ShardIdentifierFor, + block_number: BlockNumber, + ) -> Result<()> { + let last_block = self.get_last_block_of_shard(shard)?; + if last_block.number == block_number { + // given block number is last block of chain - purge whole shard + self.purge_shard(shard) + } else { + // iterate through chain and add all blocks to WriteBatch (delete cmd) + let mut batch = WriteBatch::default(); + let mut current_block_number = block_number; + // Remove blocks from db until no block anymore + while let Some(block_hash) = self.get_block_hash(shard, current_block_number)? { + self.delete_block(&mut batch, &block_hash, ¤t_block_number, shard); + current_block_number -= 1; + } + // Update DB + self.db.write(batch) + } + } + + /// Prunes all shards except for the newest blocks (according to blocknumber). + pub fn prune_shards(&mut self, number_of_blocks_to_keep: BlockNumber) { + for shard in self.shards().clone() { + // get last block: + if let Some(last_block) = self.last_block_of_shard(&shard) { + let threshold_block = last_block.number - number_of_blocks_to_keep; + if let Err(e) = self.prune_shard_from_block_number(&shard, threshold_block) { + error!("Could not purge shard {:?} due to {:?}", shard, e); + } + } else { + error!("Last block not found in shard {:?}", shard); + } + } + } + + fn add_block_to_batch( + &mut self, + signed_block: &SignedBlock, + new_shard: &mut bool, + batch: &mut WriteBatch, + ) -> Result<()> { + let shard = &signed_block.block().header().shard_id(); + if self.shards.contains(shard) { + if !self.verify_block_ancestry(signed_block.block()) { + // Do not include block if its not a direct ancestor of the last block in line. + return Err(Error::HeaderAncestryMismatch) + } + } else { + self.shards.push(*shard); + *new_shard = true; + } + // Add block to DB batch. + self.add_last_block(batch, signed_block); + Ok(()) + } + + fn verify_block_ancestry(&self, block: &::Block) -> bool { + let shard = &block.header().shard_id(); + let current_block_nr = block.header().block_number(); + if let Some(last_block) = self.last_block_of_shard(shard) { + if last_block.number != current_block_nr - 1 { + error!("[Sidechain DB] Sidechainblock (nr: {:?}) is not a succession of the previous block (nr: {:?}) in shard: {:?}", + current_block_nr, last_block.number, *shard); + return false + } + } else { + error!( + "[Sidechain DB] Shard {:?} does not have a last block. Skipping block (nr: {:?}) inclusion", + *shard, current_block_nr + ); + return false + } + true + } + + /// Implementations of helper functions, not meant for pub use + /// gets the previous block of given shard and block number, if there is one. + fn get_previous_block( + &self, + shard: &ShardIdentifierFor, + current_block_number: BlockNumber, + ) -> Result> { + let prev_block_number = current_block_number - 1; + Ok(self + .get_block_hash(shard, prev_block_number)? + .map(|block_hash| LastSidechainBlock { hash: block_hash, number: prev_block_number })) + } + fn load_shards_from_db(&self) -> Result>> { + Ok(self.db.get(STORED_SHARDS_KEY)?.unwrap_or_default()) + } + + fn load_last_block_from_db( + &self, + shard: &ShardIdentifierFor, + ) -> Result> { + self.db.get((LAST_BLOCK_KEY, *shard)) + } + + fn get_last_block_of_shard( + &self, + shard: &ShardIdentifierFor, + ) -> Result { + match self.last_blocks.get(shard) { + Some(last_block) => Ok(*last_block), + None => { + // Try to read from db: + self.load_last_block_from_db(shard)? + .ok_or_else(|| Error::LastBlockNotFound(format!("{:?}", *shard))) + }, + } + } + + /// Adds the block to the WriteBatch. + fn add_last_block(&mut self, batch: &mut WriteBatch, block: &SignedBlock) { + let hash = block.hash(); + let block_number = block.block().header().block_number(); + let shard = block.block().header().shard_id(); + // Block hash -> Signed Block. + SidechainDB::add_to_batch(batch, hash, block); + + // (Shard, Block number) -> Blockhash (for block pruning). + SidechainDB::add_to_batch(batch, (shard, block_number), hash); + + // (last_block_key, shard) -> (Blockhash, BlockNr) current blockchain state. + let last_block = LastSidechainBlock { hash, number: block_number }; + self.last_blocks.insert(shard, last_block); // add in memory + SidechainDB::add_to_batch(batch, (LAST_BLOCK_KEY, shard), last_block); + } + + /// Add delete block to the WriteBatch. + fn delete_block( + &self, + batch: &mut WriteBatch, + block_hash: &H256, + block_number: &BlockNumber, + shard: &ShardIdentifierFor, + ) { + // Block hash -> Signed Block. + SidechainDB::delete_to_batch(batch, block_hash); + // (Shard, Block number) -> Blockhash (for block pruning). + SidechainDB::delete_to_batch(batch, (shard, block_number)); + } + + /// Add delete command to remove last block to WriteBatch and remove it from memory. + /// + /// This includes adding a delete command of the following: + /// - Block hash -> Signed Block. + /// - (Shard, Block number) -> Blockhash (for block pruning). + /// - ((LAST_BLOCK_KEY, shard) -> BlockHash) -> Blockhash (for block pruning). + /// + /// Careful usage of this command: In case the last block is deleted, (LAST_BLOCK_KEY, shard) will be empty + /// even though there might be a new last block (i.e. the previous block of the removed last block). + fn delete_last_block( + &mut self, + batch: &mut WriteBatch, + last_block: &LastSidechainBlock, + shard: &ShardIdentifierFor, + ) { + // Add delete block to batch. + // (LAST_BLOCK_KEY, Shard) -> LastSidechainBlock. + SidechainDB::delete_to_batch(batch, (LAST_BLOCK_KEY, *shard)); + self.delete_block(batch, &last_block.hash, &last_block.number, shard); + + // Delete last block from local memory. + // Careful here: This deletes the local memory before db has been actually pruned + // (it's only been added to the write batch). + // But this can be fixed upon reloading the db / restarting the worker. + self.last_blocks.remove(shard); + } +} + +#[cfg(test)] +mod test { + use super::*; + use crate::test_utils::{ + create_signed_block_with_shard as create_signed_block, create_temp_dir, get_storage, + }; + use itp_types::ShardIdentifier; + use its_primitives::{traits::SignedBlock as SignedBlockT, types::SignedBlock}; + use sp_core::H256; + + #[test] + fn load_shards_from_db_works() { + // given + let temp_dir = create_temp_dir(); + let shard_one = H256::from_low_u64_be(1); + let shard_two = H256::from_low_u64_be(2); + // when + { + let mut sidechain_db = get_storage(temp_dir.path().to_path_buf()); + // ensure db starts empty + assert_eq!(sidechain_db.load_shards_from_db().unwrap(), vec![]); + // write signed_block to db + sidechain_db.db.put(STORED_SHARDS_KEY, vec![shard_one, shard_two]).unwrap(); + } + + // then + { + // open new DB of same path: + let updated_sidechain_db = get_storage(temp_dir.path().to_path_buf()); + let loaded_shards = updated_sidechain_db.load_shards_from_db().unwrap(); + assert!(loaded_shards.contains(&shard_one)); + assert!(loaded_shards.contains(&shard_two)); + } + } + + #[test] + fn load_last_block_from_db_works() { + // given + let temp_dir = create_temp_dir(); + let shard = H256::from_low_u64_be(1); + let signed_block = create_signed_block(20, shard); + let signed_last_block = LastSidechainBlock { + hash: signed_block.hash(), + number: signed_block.block().header().block_number(), + }; + // when + { + let mut sidechain_db = get_storage(temp_dir.path().to_path_buf()); + // ensure db starts empty + assert!(sidechain_db.load_last_block_from_db(&shard).unwrap().is_none()); + // write signed_block to db + sidechain_db.db.put((LAST_BLOCK_KEY, shard), signed_last_block.clone()).unwrap(); + } + + // then + { + // open new DB of same path: + let updated_sidechain_db = get_storage(temp_dir.path().to_path_buf()); + let loaded_block = + updated_sidechain_db.load_last_block_from_db(&shard).unwrap().unwrap(); + assert_eq!(loaded_block, signed_last_block); + } + } + + #[test] + fn create_new_sidechain_storage_works() { + let temp_dir = create_temp_dir(); + let shard = H256::from_low_u64_be(1); + let shard_vector = vec![shard]; + let signed_block = create_signed_block(20, shard); + let signed_last_block = LastSidechainBlock { + hash: signed_block.hash(), + number: signed_block.block().header().block_number(), + }; + { + let mut sidechain_db = get_storage(temp_dir.path().to_path_buf()); + // ensure db starts empty + assert!(sidechain_db.load_last_block_from_db(&shard).unwrap().is_none()); + // write shards to db + sidechain_db.db.put((LAST_BLOCK_KEY, shard), signed_last_block.clone()).unwrap(); + // write shards to db + sidechain_db.db.put(STORED_SHARDS_KEY, shard_vector.clone()).unwrap(); + } + + { + // open new DB of same path: + let updated_sidechain_db = get_storage(temp_dir.path().to_path_buf()); + assert_eq!(updated_sidechain_db.shards, shard_vector); + assert_eq!(*updated_sidechain_db.last_blocks.get(&shard).unwrap(), signed_last_block); + } + } + + #[test] + fn add_last_block_works() { + let temp_dir = create_temp_dir(); + let shard = H256::from_low_u64_be(1); + let signed_block = create_signed_block(8, shard); + + { + let mut sidechain_db = get_storage(temp_dir.path().to_path_buf()); + let mut batch = WriteBatch::default(); + sidechain_db.add_last_block(&mut batch, &signed_block); + sidechain_db.db.write(batch).unwrap(); + + // ensure DB contains previously stored data: + let last_block = sidechain_db.last_block_of_shard(&shard).unwrap(); + assert_eq!(last_block.number, signed_block.block().header().block_number()); + assert_eq!(last_block.hash, signed_block.hash()); + let stored_block_hash = + sidechain_db.get_block_hash(&shard, last_block.number).unwrap().unwrap(); + assert_eq!(stored_block_hash, signed_block.hash()); + assert_eq!(sidechain_db.get_block(&stored_block_hash).unwrap().unwrap(), signed_block); + } + } + + #[test] + fn delete_block_works() { + let temp_dir = create_temp_dir(); + let shard = H256::from_low_u64_be(1); + let signed_block = create_signed_block(8, shard); + { + // fill db + let mut sidechain_db = get_storage(temp_dir.path().to_path_buf()); + sidechain_db.db.put(signed_block.hash(), signed_block.clone()).unwrap(); + sidechain_db + .db + .put((shard, signed_block.block().header().block_number()), signed_block.hash()) + .unwrap(); + assert_eq!( + sidechain_db + .db + .get::<(ShardIdentifier, BlockNumber), H256>(( + shard, + signed_block.block().header().block_number() + )) + .unwrap() + .unwrap(), + signed_block.hash() + ); + assert_eq!( + sidechain_db.db.get::(signed_block.hash()).unwrap().unwrap(), + signed_block + ); + + // when + let mut batch = WriteBatch::default(); + sidechain_db.delete_block( + &mut batch, + &signed_block.hash(), + &signed_block.block().header().block_number(), + &shard, + ); + sidechain_db.db.write(batch).unwrap(); + } + + { + // open new DB of same path: + let updated_sidechain_db = get_storage(temp_dir.path().to_path_buf()); + // ensure DB does not contain block anymore: + assert!(updated_sidechain_db + .db + .get::<(ShardIdentifier, BlockNumber), H256>(( + shard, + signed_block.block().header().block_number() + )) + .unwrap() + .is_none()); + assert!(updated_sidechain_db + .db + .get::(signed_block.hash()) + .unwrap() + .is_none()); + } + } + + #[test] + fn delete_last_block_works() { + let temp_dir = create_temp_dir(); + let shard = H256::from_low_u64_be(1); + let signed_block = create_signed_block(8, shard); + let last_block = LastSidechainBlock { + hash: signed_block.hash(), + number: signed_block.block().header().block_number(), + }; + { + // fill db + let mut sidechain_db = get_storage(temp_dir.path().to_path_buf()); + sidechain_db.db.put(signed_block.hash(), signed_block.clone()).unwrap(); + sidechain_db + .db + .put((shard, signed_block.block().header().block_number()), signed_block.hash()) + .unwrap(); + sidechain_db.db.put((LAST_BLOCK_KEY, shard), last_block.clone()).unwrap(); + assert_eq!( + sidechain_db + .db + .get::<(ShardIdentifier, BlockNumber), H256>(( + shard, + signed_block.block().header().block_number() + )) + .unwrap() + .unwrap(), + signed_block.hash() + ); + assert_eq!( + sidechain_db.db.get::(signed_block.hash()).unwrap().unwrap(), + signed_block + ); + assert_eq!( + sidechain_db + .db + .get::<(&[u8], ShardIdentifier), LastSidechainBlock>((LAST_BLOCK_KEY, shard)) + .unwrap() + .unwrap(), + last_block + ); + + // when + let mut batch = WriteBatch::default(); + sidechain_db.delete_last_block(&mut batch, &last_block, &shard); + sidechain_db.db.write(batch).unwrap(); + + // then + assert!(sidechain_db.last_blocks.get(&shard).is_none()); + assert!(sidechain_db + .db + .get::<(ShardIdentifier, BlockNumber), H256>(( + shard, + signed_block.block().header().block_number() + )) + .unwrap() + .is_none()); + assert!(sidechain_db + .db + .get::(signed_block.hash()) + .unwrap() + .is_none()); + assert!(sidechain_db + .db + .get::<(&[u8], ShardIdentifier), LastSidechainBlock>((LAST_BLOCK_KEY, shard)) + .unwrap() + .is_none()); + } + } + + #[test] + fn verify_block_ancestry_returns_true_if_correct_successor() { + let temp_dir = create_temp_dir(); + let shard = H256::from_low_u64_be(1); + let signed_block = create_signed_block(8, shard); + let last_block = LastSidechainBlock { + hash: signed_block.hash(), + number: signed_block.block().header().block_number(), + }; + let signed_block_two = create_signed_block(9, shard); + { + let mut sidechain_db = get_storage(temp_dir.path().to_path_buf()); + sidechain_db.shards.push(shard); + sidechain_db.last_blocks.insert(shard, last_block); + // when + let result = sidechain_db.verify_block_ancestry(&signed_block_two.block()); + + // then + assert!(result); + } + } + + #[test] + fn verify_block_ancestry_returns_false_if_not_correct_successor() { + let temp_dir = create_temp_dir(); + let shard = H256::from_low_u64_be(1); + let signed_block = create_signed_block(8, shard); + let last_block = LastSidechainBlock { + hash: signed_block.hash(), + number: signed_block.block().header().block_number(), + }; + let signed_block_two = create_signed_block(5, shard); + { + let mut sidechain_db = get_storage(temp_dir.path().to_path_buf()); + sidechain_db.shards.push(shard); + sidechain_db.last_blocks.insert(shard, last_block); + + // when + let result = sidechain_db.verify_block_ancestry(&signed_block_two.block()); + + // then + assert!(!result); + } + } + + #[test] + fn verify_block_ancestry_returns_false_no_last_block_registered() { + let temp_dir = create_temp_dir(); + let shard = H256::from_low_u64_be(1); + let signed_block = create_signed_block(8, shard); + { + let mut sidechain_db = get_storage(temp_dir.path().to_path_buf()); + sidechain_db.shards.push(shard); + // when + let result = sidechain_db.verify_block_ancestry(&signed_block.block()); + + // then + assert!(!result); + } + } + + #[test] + fn verify_block_ancestry_returns_false_if_no_shard() { + let temp_dir = create_temp_dir(); + let shard = H256::from_low_u64_be(1); + let signed_block = create_signed_block(8, shard); + { + let sidechain_db = get_storage(temp_dir.path().to_path_buf()); + let result = sidechain_db.verify_block_ancestry(&signed_block.block()); + assert!(!result); + } + } + + #[test] + fn add_block_to_batch_works_with_new_shard() { + // given + let temp_dir = create_temp_dir(); + let shard = H256::from_low_u64_be(1); + let signed_block = create_signed_block(8, shard); + let mut new_shard = false; + { + let mut sidechain_db = get_storage(temp_dir.path().to_path_buf()); + let mut batch = WriteBatch::default(); + assert!(batch.is_empty()); + + sidechain_db + .add_block_to_batch(&signed_block, &mut new_shard, &mut batch) + .unwrap(); + + assert!(new_shard); + assert!(!batch.is_empty()); + } + } + + #[test] + fn add_block_to_batch_does_not_add_shard_if_existent() { + let temp_dir = create_temp_dir(); + let shard = H256::from_low_u64_be(1); + let signed_block = create_signed_block(8, shard); + let last_block = LastSidechainBlock { + hash: signed_block.hash(), + number: signed_block.block().header().block_number(), + }; + let signed_block_two = create_signed_block(9, shard); + let mut new_shard = false; + { + let mut sidechain_db = get_storage(temp_dir.path().to_path_buf()); + let mut batch = WriteBatch::default(); + assert!(batch.is_empty()); + sidechain_db.shards.push(shard); + sidechain_db.last_blocks.insert(shard, last_block); + + sidechain_db + .add_block_to_batch(&signed_block_two, &mut new_shard, &mut batch) + .unwrap(); + + assert!(!new_shard); + assert!(!batch.is_empty()); + } + } + + #[test] + fn add_block_to_batch_does_not_add_block_if_not_ancestor() { + let temp_dir = create_temp_dir(); + let shard = H256::from_low_u64_be(1); + let signed_block = create_signed_block(8, shard); + let last_block = LastSidechainBlock { + hash: signed_block.hash(), + number: signed_block.block().header().block_number(), + }; + let signed_block_two = create_signed_block(10, shard); + let mut new_shard = false; + { + let mut sidechain_db = get_storage(temp_dir.path().to_path_buf()); + let mut batch = WriteBatch::default(); + sidechain_db.shards.push(shard); + sidechain_db.last_blocks.insert(shard, last_block); + + let result = + sidechain_db.add_block_to_batch(&signed_block_two, &mut new_shard, &mut batch); + + assert!(result.is_err()); + assert!(!new_shard); + assert!(batch.is_empty()); + } + } + + #[test] + fn store_block_works() { + let temp_dir = create_temp_dir(); + let shard = H256::from_low_u64_be(1); + let signed_block = create_signed_block(20, shard); + let signed_block_vector: Vec = vec![signed_block.clone()]; + + { + let mut sidechain_db = get_storage(temp_dir.path().to_path_buf()); + // db needs to start empty + assert_eq!(sidechain_db.shards, vec![]); + sidechain_db.store_blocks(signed_block_vector).unwrap(); + } + + { + // open new DB of same path: + let updated_sidechain_db = get_storage(temp_dir.path().to_path_buf()); + // ensure DB contains previously stored data: + assert_eq!(*updated_sidechain_db.shards(), vec![shard]); + let last_block = updated_sidechain_db.last_block_of_shard(&shard).unwrap(); + assert_eq!(last_block.number, signed_block.block().header().block_number()); + assert_eq!(last_block.hash, signed_block.hash()); + let stored_block_hash = + updated_sidechain_db.get_block_hash(&shard, last_block.number).unwrap().unwrap(); + assert_eq!(stored_block_hash, signed_block.hash()); + assert_eq!( + updated_sidechain_db.get_block(&stored_block_hash).unwrap().unwrap(), + signed_block + ); + } + } + + #[test] + fn store_blocks_on_multi_sharding_works() { + let temp_dir = create_temp_dir(); + let shard_one = H256::from_low_u64_be(1); + let shard_two = H256::from_low_u64_be(2); + let signed_block_one = create_signed_block(20, shard_one); + let signed_block_two = create_signed_block(1, shard_two); + + let signed_block_vector: Vec = + vec![signed_block_one.clone(), signed_block_two.clone()]; + + { + let mut sidechain_db = get_storage(temp_dir.path().to_path_buf()); + // db needs to start empty + assert_eq!(sidechain_db.shards, vec![]); + sidechain_db.store_blocks(signed_block_vector).unwrap(); + } + + { + let updated_sidechain_db = get_storage(temp_dir.path().to_path_buf()); + assert_eq!(updated_sidechain_db.shards()[0], shard_one); + assert_eq!(updated_sidechain_db.shards()[1], shard_two); + let last_block_one: &LastSidechainBlock = + updated_sidechain_db.last_blocks.get(&shard_one).unwrap(); + let last_block_two: &LastSidechainBlock = + updated_sidechain_db.last_blocks.get(&shard_two).unwrap(); + assert_eq!(last_block_one.number, 20); + assert_eq!(last_block_two.number, 1); + assert_eq!(last_block_one.hash, signed_block_one.hash()); + assert_eq!(last_block_two.hash, signed_block_two.hash()); + } + } + + #[test] + fn store_mulitple_block_on_one_shard_works() { + let temp_dir = create_temp_dir(); + let shard = H256::from_low_u64_be(1); + let signed_block_one = create_signed_block(20, shard); + let signed_block_two = create_signed_block(21, shard); + let signed_block_vector_one = vec![signed_block_one.clone()]; + let signed_block_vector_two = vec![signed_block_two.clone()]; + + { + // first iteration + let mut sidechain_db = get_storage(temp_dir.path().to_path_buf()); + sidechain_db.store_blocks(signed_block_vector_one).unwrap(); + } + { + // second iteration + let mut sidechain_db = get_storage(temp_dir.path().to_path_buf()); + sidechain_db.store_blocks(signed_block_vector_two).unwrap(); + } + + { + let updated_sidechain_db = get_storage(temp_dir.path().to_path_buf()); + // last block is really equal to second block: + let last_block: &LastSidechainBlock = + updated_sidechain_db.last_blocks.get(&shard).unwrap(); + assert_eq!(last_block.number, 21); + // storage contains both blocks: + // (shard,blocknumber) -> blockhash + let db_block_hash_one = + updated_sidechain_db.get_block_hash(&shard, 20).unwrap().unwrap(); + let db_block_hash_two = + updated_sidechain_db.get_block_hash(&shard, 21).unwrap().unwrap(); + assert_eq!(db_block_hash_one, signed_block_one.hash()); + assert_eq!(db_block_hash_two, signed_block_two.hash()); + + // block hash -> signed block + let db_block_one = + updated_sidechain_db.get_block(&signed_block_one.hash()).unwrap().unwrap(); + let db_block_two = + updated_sidechain_db.get_block(&signed_block_two.hash()).unwrap().unwrap(); + assert_eq!(db_block_one, signed_block_one); + assert_eq!(db_block_two, signed_block_two); + } + } + + #[test] + fn wrong_succession_order_does_not_get_accepted() { + let temp_dir = create_temp_dir(); + let shard = H256::from_low_u64_be(1); + let signed_block_one = create_signed_block(7, shard); + let signed_block_two = create_signed_block(21, shard); + let signed_block_vector_one = vec![signed_block_one.clone()]; + let signed_block_vector_two = vec![signed_block_two.clone()]; + + { + // first iteration + let mut sidechain_db = get_storage(temp_dir.path().to_path_buf()); + sidechain_db.store_blocks(signed_block_vector_one).unwrap(); + } + { + // second iteration + let mut sidechain_db = get_storage(temp_dir.path().to_path_buf()); + sidechain_db.store_blocks(signed_block_vector_two).unwrap(); + } + { + let updated_sidechain_db = get_storage(temp_dir.path().to_path_buf()); + // last block is equal to first block: + let last_block: &LastSidechainBlock = + updated_sidechain_db.last_blocks.get(&shard).unwrap(); + assert_eq!(last_block.number, signed_block_one.block().header().block_number()); + + // storage contains only one blocks: + // (shard,blocknumber) -> blockhash + let db_block_hash_one = updated_sidechain_db + .get_block_hash(&shard, signed_block_one.block().header().block_number()) + .unwrap() + .unwrap(); + let db_block_hash_empty = updated_sidechain_db + .get_block_hash(&shard, signed_block_two.block().header().block_number()) + .unwrap(); + assert!(db_block_hash_empty.is_none()); + assert_eq!(db_block_hash_one, signed_block_one.hash()); + } + } + + #[test] + fn get_previous_block_returns_correct_block() { + let temp_dir = create_temp_dir(); + let shard = H256::from_low_u64_be(1); + let signed_block_one = create_signed_block(1, shard); + // create sidechain_db + { + let mut sidechain_db = get_storage(temp_dir.path().to_path_buf()); + sidechain_db.store_blocks(vec![signed_block_one.clone()]).unwrap(); + // create last block one for comparison + let last_block = LastSidechainBlock { + hash: signed_block_one.hash(), + number: signed_block_one.block().header().block_number(), + }; + + // then + let some_block = sidechain_db + .get_previous_block(&shard, signed_block_one.block().header().block_number() + 1) + .unwrap() + .unwrap(); + + // when + assert_eq!(some_block, last_block); + } + } + + #[test] + fn get_previous_block_returns_none_when_no_block() { + let temp_dir = create_temp_dir(); + let shard = H256::from_low_u64_be(1); + { + let mut sidechain_db = get_storage(temp_dir.path().to_path_buf()); + sidechain_db.store_blocks(vec![create_signed_block(1, shard)]).unwrap(); + + let no_block = sidechain_db.get_previous_block(&shard, 1).unwrap(); + + assert!(no_block.is_none()); + } + } + + #[test] + fn purge_shard_works() { + let temp_dir = create_temp_dir(); + let shard = H256::from_low_u64_be(1); + let block_one = create_signed_block(1, shard); + let block_two = create_signed_block(2, shard); + let block_three = create_signed_block(3, shard); + { + // create sidechain_db + let mut sidechain_db = get_storage(temp_dir.path().to_path_buf()); + sidechain_db.store_blocks(vec![block_one.clone()]).unwrap(); + sidechain_db.store_blocks(vec![block_two.clone()]).unwrap(); + sidechain_db.store_blocks(vec![block_three.clone()]).unwrap(); + + sidechain_db.purge_shard(&shard).unwrap(); + + // test if local storage has been cleansed + assert!(!sidechain_db.shards.contains(&shard)); + assert!(sidechain_db.last_blocks.get(&shard).is_none()); + } + + { + let updated_sidechain_db = get_storage(temp_dir.path().to_path_buf()); + // test if local storage is still clean + assert!(!updated_sidechain_db.shards.contains(&shard)); + assert!(updated_sidechain_db.last_blocks.get(&shard).is_none()); + // test if db is clean + assert!(updated_sidechain_db.last_block_of_shard(&shard).is_none()); + assert!(updated_sidechain_db.get_block_hash(&shard, 3).unwrap().is_none()); + assert!(updated_sidechain_db.get_block_hash(&shard, 2).unwrap().is_none()); + assert!(updated_sidechain_db.get_block_hash(&shard, 1).unwrap().is_none()); + assert!(updated_sidechain_db.get_block(&block_one.hash()).unwrap().is_none()); + assert!(updated_sidechain_db.get_block(&block_two.hash()).unwrap().is_none()); + assert!(updated_sidechain_db.get_block(&block_three.hash()).unwrap().is_none()); + } + } + + #[test] + fn purge_shard_from_block_works() { + let temp_dir = create_temp_dir(); + let shard = H256::from_low_u64_be(1); + let block_one = create_signed_block(1, shard); + let block_two = create_signed_block(2, shard); + let block_three = create_signed_block(3, shard); + let last_block = LastSidechainBlock { + hash: block_three.hash(), + number: block_three.block().header().block_number(), + }; + + { + // create sidechain_db + let mut sidechain_db = get_storage(temp_dir.path().to_path_buf()); + sidechain_db.store_blocks(vec![block_one.clone()]).unwrap(); + sidechain_db.store_blocks(vec![block_two.clone()]).unwrap(); + sidechain_db.store_blocks(vec![block_three.clone()]).unwrap(); + + sidechain_db.prune_shard_from_block_number(&shard, 2).unwrap(); + } + + { + let updated_sidechain_db = get_storage(temp_dir.path().to_path_buf()); + // test local memory + assert!(updated_sidechain_db.shards.contains(&shard)); + assert_eq!(*updated_sidechain_db.last_blocks.get(&shard).unwrap(), last_block); + // assert block three is still there + assert_eq!(*updated_sidechain_db.last_block_of_shard(&shard).unwrap(), last_block); + assert_eq!( + updated_sidechain_db.get_block_hash(&shard, 3).unwrap().unwrap(), + block_three.hash() + ); + assert_eq!( + updated_sidechain_db.get_block(&block_three.hash()).unwrap().unwrap(), + block_three + ); + // assert the lower blocks have been purged + assert!(updated_sidechain_db.get_block_hash(&shard, 2).unwrap().is_none()); + assert!(updated_sidechain_db.get_block_hash(&shard, 1).unwrap().is_none()); + assert!(updated_sidechain_db.get_block(&block_two.hash()).unwrap().is_none()); + assert!(updated_sidechain_db.get_block(&block_one.hash()).unwrap().is_none()); + } + } + + #[test] + fn purge_shard_from_block_works_for_last_block() { + let temp_dir = create_temp_dir(); + let shard = H256::from_low_u64_be(1); + let block_one = create_signed_block(1, shard); + let block_two = create_signed_block(2, shard); + let block_three = create_signed_block(3, shard); + { + // create sidechain_db + let mut sidechain_db = get_storage(temp_dir.path().to_path_buf()); + sidechain_db.store_blocks(vec![block_one.clone()]).unwrap(); + sidechain_db.store_blocks(vec![block_two.clone()]).unwrap(); + sidechain_db.store_blocks(vec![block_three.clone()]).unwrap(); + + sidechain_db.prune_shard_from_block_number(&shard, 3).unwrap(); + + // test if local storage has been cleansed + assert!(!sidechain_db.shards.contains(&shard)); + assert!(sidechain_db.last_blocks.get(&shard).is_none()); + } + + { + let updated_sidechain_db = get_storage(temp_dir.path().to_path_buf()); + // test if local storage is still clean + assert!(!updated_sidechain_db.shards.contains(&shard)); + assert!(updated_sidechain_db.last_blocks.get(&shard).is_none()); + // test if db is clean + assert!(updated_sidechain_db.last_block_of_shard(&shard).is_none()); + assert!(updated_sidechain_db.get_block_hash(&shard, 3).unwrap().is_none()); + assert!(updated_sidechain_db.get_block_hash(&shard, 2).unwrap().is_none()); + assert!(updated_sidechain_db.get_block_hash(&shard, 1).unwrap().is_none()); + assert!(updated_sidechain_db.get_block(&block_one.hash()).unwrap().is_none()); + assert!(updated_sidechain_db.get_block(&block_two.hash()).unwrap().is_none()); + assert!(updated_sidechain_db.get_block(&block_three.hash()).unwrap().is_none()); + } + } + + #[test] + fn prune_shards_works_for_multiple_shards() { + let temp_dir = create_temp_dir(); + // shard one + let shard_one = H256::from_low_u64_be(1); + let block_one = create_signed_block(1, shard_one); + let block_two = create_signed_block(2, shard_one); + let block_three = create_signed_block(3, shard_one); + let last_block_one = LastSidechainBlock { + hash: block_three.hash(), + number: block_three.block().header().block_number(), + }; + // shard two + let shard_two = H256::from_low_u64_be(2); + let block_one_s = create_signed_block(1, shard_two); + let block_two_s = create_signed_block(2, shard_two); + let block_three_s = create_signed_block(3, shard_two); + let block_four_s = create_signed_block(4, shard_two); + let last_block_two = LastSidechainBlock { + hash: block_four_s.hash(), + number: block_four_s.block().header().block_number(), + }; + { + // create sidechain_db + let mut sidechain_db = get_storage(temp_dir.path().to_path_buf()); + sidechain_db.store_blocks(vec![block_one.clone(), block_one_s.clone()]).unwrap(); + sidechain_db.store_blocks(vec![block_two.clone(), block_two_s.clone()]).unwrap(); + sidechain_db + .store_blocks(vec![block_three.clone(), block_three_s.clone()]) + .unwrap(); + sidechain_db.store_blocks(vec![block_four_s.clone()]).unwrap(); + + sidechain_db.prune_shards(2); + } + + { + let updated_sidechain_db = get_storage(temp_dir.path().to_path_buf()); + // test if shard one has been cleansed of block 1, with 2 and 3 still beeing there: + assert_eq!( + *updated_sidechain_db.last_block_of_shard(&shard_one).unwrap(), + last_block_one + ); + assert_eq!( + updated_sidechain_db.get_block_hash(&shard_one, 3).unwrap().unwrap(), + block_three.hash() + ); + assert_eq!( + updated_sidechain_db.get_block(&block_three.hash()).unwrap().unwrap(), + block_three + ); + assert_eq!( + updated_sidechain_db.get_block_hash(&shard_one, 2).unwrap().unwrap(), + block_two.hash() + ); + assert_eq!( + updated_sidechain_db.get_block(&block_two.hash()).unwrap().unwrap(), + block_two + ); + assert!(updated_sidechain_db.get_block(&block_one.hash()).unwrap().is_none()); + assert!(updated_sidechain_db.get_block_hash(&shard_one, 1).unwrap().is_none()); + // test if shard two has been cleansed of block 1 and 2, with 3 and 4 still beeing there: + assert_eq!( + *updated_sidechain_db.last_block_of_shard(&shard_two).unwrap(), + last_block_two + ); + assert_eq!( + updated_sidechain_db.get_block_hash(&shard_two, 4).unwrap().unwrap(), + block_four_s.hash() + ); + assert_eq!( + updated_sidechain_db.get_block(&block_four_s.hash()).unwrap().unwrap(), + block_four_s + ); + assert_eq!( + updated_sidechain_db.get_block_hash(&shard_two, 3).unwrap().unwrap(), + block_three_s.hash() + ); + assert_eq!( + updated_sidechain_db.get_block(&block_three_s.hash()).unwrap().unwrap(), + block_three_s + ); + assert!(updated_sidechain_db.get_block_hash(&shard_two, 2).unwrap().is_none()); + assert!(updated_sidechain_db.get_block_hash(&shard_two, 1).unwrap().is_none()); + assert!(updated_sidechain_db.get_block(&block_one_s.hash()).unwrap().is_none()); + assert!(updated_sidechain_db.get_block(&block_two_s.hash()).unwrap().is_none()); + } + } +} diff --git a/bitacross-worker/sidechain/storage/src/storage_tests_get_blocks_after.rs b/bitacross-worker/sidechain/storage/src/storage_tests_get_blocks_after.rs new file mode 100644 index 0000000000..0795e54ca7 --- /dev/null +++ b/bitacross-worker/sidechain/storage/src/storage_tests_get_blocks_after.rs @@ -0,0 +1,124 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::{ + error::Error, + test_utils::{ + create_signed_block_with_parenthash as create_signed_block, default_shard, + fill_storage_with_blocks, get_storage, + }, +}; +use its_primitives::{traits::SignedBlock, types::BlockHash}; +use std::assert_matches::assert_matches; + +#[test] +fn get_blocks_after_works_for_regular_case() { + let block_1 = create_signed_block(1, BlockHash::default()); + let block_2 = create_signed_block(2, block_1.hash()); + let block_3 = create_signed_block(3, block_2.hash()); + let block_4 = create_signed_block(4, block_3.hash()); + + let temp_dir = + fill_storage_with_blocks(vec![block_1.clone(), block_2.clone(), block_3, block_4.clone()]); + + { + let updated_sidechain_db = get_storage(temp_dir.path().to_path_buf()); + let blocks_after_1 = updated_sidechain_db + .get_blocks_after(&block_1.hash(), &default_shard()) + .unwrap(); + + assert_eq!(3, blocks_after_1.len()); + assert_eq!(block_2.hash(), blocks_after_1.first().unwrap().hash()); + assert_eq!(block_4.hash(), blocks_after_1.last().unwrap().hash()); + } +} + +#[test] +fn get_blocks_after_returns_empty_vec_if_block_not_found() { + let block_1 = create_signed_block(1, BlockHash::random()); + + let temp_dir = fill_storage_with_blocks(vec![block_1.clone()]); + + { + let updated_sidechain_db = get_storage(temp_dir.path().to_path_buf()); + let block_hash = BlockHash::from_low_u64_be(1); + // Off-chance that random() generates exactly the same hash + assert_ne!(block_1.hash(), block_hash); + + assert_eq!( + updated_sidechain_db.get_blocks_after(&block_hash, &default_shard()).unwrap(), + Vec::new() + ); + } +} + +#[test] +fn get_blocks_returns_none_if_last_is_already_most_recent_block() { + let block_1 = create_signed_block(1, BlockHash::random()); + + let temp_dir = fill_storage_with_blocks(vec![block_1.clone()]); + + { + let updated_sidechain_db = get_storage(temp_dir.path().to_path_buf()); + + assert_eq!( + updated_sidechain_db + .get_blocks_after(&block_1.hash(), &default_shard()) + .unwrap(), + Vec::new() + ); + } +} + +#[test] +fn get_blocks_after_returns_all_blocks_if_last_known_is_default() { + let block_1 = create_signed_block(1, BlockHash::default()); + let block_2 = create_signed_block(2, block_1.hash()); + let block_3 = create_signed_block(3, block_2.hash()); + + let blocks = vec![block_1.clone(), block_2.clone(), block_3.clone()]; + + let temp_dir = fill_storage_with_blocks(blocks.clone()); + + { + let updated_sidechain_db = get_storage(temp_dir.path().to_path_buf()); + let default_hash = BlockHash::default(); + + assert_eq!( + updated_sidechain_db.get_blocks_after(&default_hash, &default_shard()).unwrap(), + blocks + ); + } +} + +#[test] +fn given_block_with_invalid_ancestry_returns_error() { + let block_1 = create_signed_block(1, BlockHash::default()); + // Should be block_1 hash, but we deliberately introduce an invalid parent hash. + let block_2 = create_signed_block(2, BlockHash::random()); + + let temp_dir = fill_storage_with_blocks(vec![block_1.clone(), block_2]); + + { + let updated_sidechain_db = get_storage(temp_dir.path().to_path_buf()); + + assert_matches!( + updated_sidechain_db.get_blocks_after(&block_1.hash(), &default_shard()), + Err(Error::FailedToFindParentBlock) + ); + } +} diff --git a/bitacross-worker/sidechain/storage/src/storage_tests_get_blocks_in_range.rs b/bitacross-worker/sidechain/storage/src/storage_tests_get_blocks_in_range.rs new file mode 100644 index 0000000000..c0c505d4d0 --- /dev/null +++ b/bitacross-worker/sidechain/storage/src/storage_tests_get_blocks_in_range.rs @@ -0,0 +1,104 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::test_utils::{ + create_signed_block_with_parenthash as create_signed_block, default_shard, + fill_storage_with_blocks, get_storage, +}; +use itp_types::BlockHash; +use its_primitives::traits::SignedBlock; + +#[test] +fn get_blocks_in_range_works_for_regular_case() { + let block_1 = create_signed_block(1, BlockHash::default()); + let block_2 = create_signed_block(2, block_1.hash()); + let block_3 = create_signed_block(3, block_2.hash()); + let block_4 = create_signed_block(4, block_3.hash()); + let block_5 = create_signed_block(5, block_4.hash()); + + let temp_dir = fill_storage_with_blocks(vec![ + block_1.clone(), + block_2.clone(), + block_3, + block_4.clone(), + block_5.clone(), + ]); + + { + let updated_sidechain_db = get_storage(temp_dir.path().to_path_buf()); + let blocks_2_to_4 = updated_sidechain_db + .get_blocks_in_range(&block_1.hash(), &block_5.hash(), &default_shard()) + .unwrap(); + + assert_eq!(3, blocks_2_to_4.len()); + assert_eq!(block_2.hash(), blocks_2_to_4.first().unwrap().hash()); + assert_eq!(block_4.hash(), blocks_2_to_4.last().unwrap().hash()); + } +} + +#[test] +fn get_blocks_in_range_returns_empty_vec_if_from_is_invalid() { + let block_1 = create_signed_block(1, BlockHash::default()); + let block_2 = create_signed_block(2, block_1.hash()); + let block_3 = create_signed_block(3, block_2.hash()); + let block_4 = create_signed_block(4, block_3.hash()); + + let temp_dir = fill_storage_with_blocks(vec![ + block_1.clone(), + block_2.clone(), + block_3.clone(), + block_4.clone(), + ]); + + { + let updated_sidechain_db = get_storage(temp_dir.path().to_path_buf()); + let invalid_block_hash = BlockHash::from_low_u64_be(1); + + assert!(updated_sidechain_db + .get_blocks_in_range(&invalid_block_hash, &block_3.hash(), &default_shard()) + .unwrap() + .is_empty()); + } +} + +#[test] +fn get_blocks_in_range_returns_all_blocks_if_upper_bound_is_invalid() { + let block_1 = create_signed_block(1, BlockHash::default()); + let block_2 = create_signed_block(2, block_1.hash()); + let block_3 = create_signed_block(3, block_2.hash()); + let block_4 = create_signed_block(4, block_3.hash()); + let block_5 = create_signed_block(5, block_4.hash()); + + let temp_dir = fill_storage_with_blocks(vec![ + block_1.clone(), + block_2.clone(), + block_3.clone(), + block_4.clone(), + block_5.clone(), + ]); + + { + let updated_sidechain_db = get_storage(temp_dir.path().to_path_buf()); + let blocks_in_range = updated_sidechain_db + .get_blocks_in_range(&block_2.hash(), &BlockHash::from_low_u64_be(1), &default_shard()) + .unwrap(); + + assert_eq!(3, blocks_in_range.len()); + assert_eq!(block_3.hash(), blocks_in_range.first().unwrap().hash()); + assert_eq!(block_5.hash(), blocks_in_range.last().unwrap().hash()); + } +} diff --git a/bitacross-worker/sidechain/storage/src/test_utils.rs b/bitacross-worker/sidechain/storage/src/test_utils.rs new file mode 100644 index 0000000000..c0c7d8fdd8 --- /dev/null +++ b/bitacross-worker/sidechain/storage/src/test_utils.rs @@ -0,0 +1,96 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::storage::SidechainStorage; +use itp_time_utils::now_as_millis; +use itp_types::ShardIdentifier; +use its_primitives::types::{BlockHash, SignedBlock as SignedSidechainBlock}; +use its_test::{ + sidechain_block_builder::{SidechainBlockBuilder, SidechainBlockBuilderTrait}, + sidechain_block_data_builder::SidechainBlockDataBuilder, + sidechain_header_builder::SidechainHeaderBuilder, +}; +use sp_core::{crypto::Pair, ed25519, H256}; +use std::{path::PathBuf, vec::Vec}; +use temp_dir::TempDir; + +pub fn fill_storage_with_blocks(blocks: Vec) -> TempDir { + let dir = create_temp_dir(); + let mut sidechain_db = get_storage(dir.path().to_path_buf()); + sidechain_db.store_blocks(blocks).unwrap(); + dir +} + +pub fn create_temp_dir() -> TempDir { + TempDir::new().unwrap() +} + +pub fn get_storage(path: PathBuf) -> SidechainStorage { + SidechainStorage::::load_from_base_path(path).unwrap() +} + +pub fn default_shard() -> ShardIdentifier { + ShardIdentifier::default() +} + +pub fn create_signed_block_with_parenthash( + block_number: u64, + parent_hash: BlockHash, +) -> SignedSidechainBlock { + let header = default_header_builder() + .with_parent_hash(parent_hash) + .with_block_number(block_number) + .build(); + + let block_data = default_block_data_builder().build(); + + SidechainBlockBuilder::default() + .with_header(header) + .with_block_data(block_data) + .build_signed() +} + +pub fn create_signed_block_with_shard( + block_number: u64, + shard: ShardIdentifier, +) -> SignedSidechainBlock { + let header = default_header_builder() + .with_shard(shard) + .with_block_number(block_number) + .build(); + + let block_data = default_block_data_builder().build(); + + SidechainBlockBuilder::default() + .with_header(header) + .with_block_data(block_data) + .build_signed() +} + +fn default_header_builder() -> SidechainHeaderBuilder { + SidechainHeaderBuilder::default() + .with_parent_hash(H256::random()) + .with_block_number(Default::default()) + .with_shard(default_shard()) +} + +fn default_block_data_builder() -> SidechainBlockDataBuilder { + SidechainBlockDataBuilder::default() + .with_timestamp(now_as_millis()) + .with_layer_one_head(H256::random()) + .with_signer(ed25519::Pair::from_string("//Alice", None).unwrap()) +} diff --git a/bitacross-worker/sidechain/test/Cargo.toml b/bitacross-worker/sidechain/test/Cargo.toml new file mode 100644 index 0000000000..d80a6a825b --- /dev/null +++ b/bitacross-worker/sidechain/test/Cargo.toml @@ -0,0 +1,32 @@ +[package] +name = "its-test" +version = "0.9.0" +authors = ['Trust Computing GmbH ', 'Integritee AG '] +homepage = 'https://litentry.com/' +repository = 'https://github.com/litentry/litentry-parachain' +license = "Apache-2.0" +edition = "2021" + +[dependencies] + +# sgx dependencies +sgx_tstd = { branch = "master", git = "https://github.com/apache/teaclave-sgx-sdk.git", features = ["untrusted_time"], optional = true } + +# Substrate dependencies +sp-core = { default_features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } + +# local +itp-types = { path = "../../core-primitives/types", default_features = false } +its-primitives = { path = "../primitives", default_features = false, features = ["full_crypto"] } + +[features] +default = ["std"] +std = [ + "itp-types/std", + "its-primitives/std", + # substrate + "sp-core/std", +] +sgx = [ + "sgx_tstd", +] diff --git a/bitacross-worker/sidechain/test/src/lib.rs b/bitacross-worker/sidechain/test/src/lib.rs new file mode 100644 index 0000000000..e9164d6d8b --- /dev/null +++ b/bitacross-worker/sidechain/test/src/lib.rs @@ -0,0 +1,29 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#![feature(trait_alias)] +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg(all(feature = "std", feature = "sgx"))] +compile_error!("feature \"std\" and feature \"sgx\" cannot be enabled at the same time"); + +#[cfg(all(not(feature = "std"), not(feature = "sgx")))] +compile_error!("feature \"std\" and feature \"sgx\" cannot be disabled at the same time"); + +#[cfg(all(not(feature = "std"), feature = "sgx"))] +#[macro_use] +extern crate sgx_tstd as std; + +pub mod sidechain_block_builder; +pub mod sidechain_block_data_builder; +pub mod sidechain_header_builder; diff --git a/bitacross-worker/sidechain/test/src/sidechain_block_builder.rs b/bitacross-worker/sidechain/test/src/sidechain_block_builder.rs new file mode 100644 index 0000000000..1261cf51bc --- /dev/null +++ b/bitacross-worker/sidechain/test/src/sidechain_block_builder.rs @@ -0,0 +1,105 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 pattern for a signed sidechain block. + +use crate::{ + sidechain_block_data_builder::SidechainBlockDataBuilder, + sidechain_header_builder::SidechainHeaderBuilder, +}; +use its_primitives::{ + traits::{Block as BlockT, SignBlock}, + types::{block_data::BlockData, header::SidechainHeader as Header, Block, SignedBlock}, +}; +use sp_core::{ed25519, Pair}; + +type Seed = [u8; 32]; +const ENCLAVE_SEED: Seed = *b"12345678901234567890123456789012"; + +#[derive(Clone)] +pub struct SidechainBlockBuilder { + signer: ed25519::Pair, + header: Header, + block_data: BlockData, +} + +impl Default for SidechainBlockBuilder { + fn default() -> Self { + SidechainBlockBuilder { + signer: Pair::from_seed(&ENCLAVE_SEED), + header: SidechainHeaderBuilder::default().build(), + block_data: SidechainBlockDataBuilder::default().build(), + } + } +} + +pub trait SidechainBlockBuilderTrait { + type Block: BlockT; + fn random() -> Self; + fn with_header(self, header: Header) -> Self; + fn with_block_data(self, block_data: BlockData) -> Self; + fn with_signer(self, signer: ed25519::Pair) -> Self; + fn build(&self) -> Self::Block; + fn build_signed(&self) -> SignedBlock; +} + +impl SidechainBlockBuilderTrait for SidechainBlockBuilder { + type Block = Block; + fn random() -> Self { + SidechainBlockBuilder { + signer: Pair::from_seed(&ENCLAVE_SEED), + header: SidechainHeaderBuilder::random().build(), + block_data: SidechainBlockDataBuilder::random().build(), + } + } + + fn with_header(self, header: Header) -> Self { + let mut self_mut = self; + self_mut.header = header; + self_mut + } + + fn with_block_data(self, block_data: BlockData) -> Self { + let mut self_mut = self; + self_mut.block_data = block_data; + self_mut + } + + fn with_signer(self, signer: ed25519::Pair) -> Self { + let mut self_mut = self; + self_mut.signer = signer; + self_mut + } + + fn build(&self) -> Self::Block { + Block { header: self.header, block_data: self.block_data.clone() } + } + + fn build_signed(&self) -> SignedBlock { + let signer = self.signer; + self.build().sign_block(&signer) + } +} + +#[test] +fn build_signed_block_has_valid_signature() { + use its_primitives::traits::SignedBlock as SignedBlockTrait; + + let signed_block = SidechainBlockBuilder::default().build_signed(); + assert!(signed_block.verify_signature()); +} diff --git a/bitacross-worker/sidechain/test/src/sidechain_block_data_builder.rs b/bitacross-worker/sidechain/test/src/sidechain_block_data_builder.rs new file mode 100644 index 0000000000..e1197ce65c --- /dev/null +++ b/bitacross-worker/sidechain/test/src/sidechain_block_data_builder.rs @@ -0,0 +1,102 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 pattern for sidechain block data. + +use itp_types::H256; +use its_primitives::types::{ + block::{BlockHash, Timestamp}, + block_data::BlockData, +}; +use sp_core::{ed25519, Pair}; +use std::{time::SystemTime, vec}; + +type Seed = [u8; 32]; +const ENCLAVE_SEED: Seed = *b"12345678901234567890123456789012"; + +pub struct SidechainBlockDataBuilder { + timestamp: Timestamp, + layer_one_head: H256, + signer: ed25519::Pair, + signed_top_hashes: Vec, + encrypted_state_diff: Vec, +} + +impl Default for SidechainBlockDataBuilder { + fn default() -> Self { + SidechainBlockDataBuilder { + timestamp: Default::default(), + layer_one_head: Default::default(), + signer: Pair::from_seed(&ENCLAVE_SEED), + signed_top_hashes: Default::default(), + encrypted_state_diff: Default::default(), + } + } +} + +impl SidechainBlockDataBuilder { + pub fn random() -> Self { + SidechainBlockDataBuilder { + timestamp: now_as_millis(), + layer_one_head: BlockHash::random(), + signer: Pair::from_seed(&ENCLAVE_SEED), + signed_top_hashes: vec![H256::random(), H256::random()], + encrypted_state_diff: vec![1, 3, 42, 8, 11, 33], + } + } + + pub fn with_timestamp(mut self, timestamp: Timestamp) -> Self { + self.timestamp = timestamp; + self + } + + pub fn with_signer(mut self, signer: ed25519::Pair) -> Self { + self.signer = signer; + self + } + + pub fn with_layer_one_head(mut self, layer_one_head: H256) -> Self { + self.layer_one_head = layer_one_head; + self + } + + pub fn with_signed_top_hashes(mut self, signed_top_hashes: Vec) -> Self { + self.signed_top_hashes = signed_top_hashes; + self + } + + pub fn with_payload(mut self, payload: Vec) -> Self { + self.encrypted_state_diff = payload; + self + } + + pub fn build(self) -> BlockData { + BlockData { + timestamp: self.timestamp, + block_author: self.signer.public(), + layer_one_head: self.layer_one_head, + signed_top_hashes: self.signed_top_hashes, + encrypted_state_diff: self.encrypted_state_diff, + } + } +} + +/// gets the timestamp of the block as seconds since unix epoch +fn now_as_millis() -> u64 { + SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap().as_millis() as u64 +} diff --git a/bitacross-worker/sidechain/test/src/sidechain_header_builder.rs b/bitacross-worker/sidechain/test/src/sidechain_header_builder.rs new file mode 100644 index 0000000000..fca8b52b8c --- /dev/null +++ b/bitacross-worker/sidechain/test/src/sidechain_header_builder.rs @@ -0,0 +1,92 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 pattern for a sidechain header. + +use its_primitives::types::{header::SidechainHeader as Header, ShardIdentifier}; +use sp_core::H256; + +pub struct SidechainHeaderBuilder { + parent_hash: H256, + block_number: u64, + shard_id: ShardIdentifier, + block_data_hash: H256, + next_finalization_block_number: u64, +} + +impl Default for SidechainHeaderBuilder { + fn default() -> Self { + SidechainHeaderBuilder { + parent_hash: Default::default(), + block_number: 1, + shard_id: Default::default(), + block_data_hash: Default::default(), + next_finalization_block_number: 1, + } + } +} + +impl SidechainHeaderBuilder { + pub fn random() -> Self { + SidechainHeaderBuilder { + parent_hash: H256::random(), + block_number: 42, + shard_id: ShardIdentifier::random(), + block_data_hash: H256::random(), + next_finalization_block_number: 1, + } + } + + pub fn with_parent_hash(mut self, parent_hash: H256) -> Self { + self.parent_hash = parent_hash; + self + } + + pub fn with_block_number(mut self, block_number: u64) -> Self { + self.block_number = block_number; + self + } + + pub fn with_shard(mut self, shard_id: ShardIdentifier) -> Self { + self.shard_id = shard_id; + self + } + + pub fn with_block_data_hash(mut self, block_data_hash: H256) -> Self { + self.block_data_hash = block_data_hash; + self + } + + pub fn with_next_finalization_block_number( + mut self, + next_finalization_block_number: u64, + ) -> Self { + self.next_finalization_block_number = next_finalization_block_number; + self + } + + pub fn build(self) -> Header { + Header { + parent_hash: self.parent_hash, + block_number: self.block_number, + shard_id: self.shard_id, + block_data_hash: self.block_data_hash, + next_finalization_block_number: self.next_finalization_block_number, + } + } +} diff --git a/bitacross-worker/sidechain/validateer-fetch/Cargo.toml b/bitacross-worker/sidechain/validateer-fetch/Cargo.toml new file mode 100644 index 0000000000..7aca2dbf7a --- /dev/null +++ b/bitacross-worker/sidechain/validateer-fetch/Cargo.toml @@ -0,0 +1,38 @@ +[package] +name = "its-validateer-fetch" +version = "0.9.0" +authors = ['Trust Computing GmbH ', 'Integritee AG '] +edition = "2021" + +[dependencies] +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive", "chain-error"] } +derive_more = "0.99.16" + +# substrate deps +sp-core = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } +sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } +sp-std = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } + +# local deps +itp-ocall-api = { path = "../../core-primitives/ocall-api", default-features = false } +itp-teerex-storage = { path = "../../core-primitives/teerex-storage", default-features = false } +itp-types = { path = "../../core-primitives/types", default-features = false } + +# litentry +frame-support = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.42" } + +[features] +default = ["std"] +std = [ + "codec/std", + "sp-core/std", + "sp-runtime/std", + "sp-std/std", + "itp-types/std", + "itp-ocall-api/std", + "frame-support/std", +] + +[dev-dependencies] +itp-test = { path = "../../core-primitives/test" } +itc-parentchain-test = { path = "../../core/parentchain/test" } diff --git a/bitacross-worker/sidechain/validateer-fetch/src/error.rs b/bitacross-worker/sidechain/validateer-fetch/src/error.rs new file mode 100644 index 0000000000..3b5d4a3f2c --- /dev/null +++ b/bitacross-worker/sidechain/validateer-fetch/src/error.rs @@ -0,0 +1,27 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 derive_more::{Display, From}; + +pub type Result = core::result::Result; + +#[derive(Debug, Display, From)] +pub enum Error { + Codec(codec::Error), + Onchain(itp_ocall_api::Error), + Other(&'static str), +} diff --git a/bitacross-worker/sidechain/validateer-fetch/src/lib.rs b/bitacross-worker/sidechain/validateer-fetch/src/lib.rs new file mode 100644 index 0000000000..8c68402101 --- /dev/null +++ b/bitacross-worker/sidechain/validateer-fetch/src/lib.rs @@ -0,0 +1,24 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +#![cfg_attr(not(feature = "std"), no_std)] + +mod error; +mod validateer; + +pub use error::Error; +pub use validateer::*; diff --git a/bitacross-worker/sidechain/validateer-fetch/src/validateer.rs b/bitacross-worker/sidechain/validateer-fetch/src/validateer.rs new file mode 100644 index 0000000000..4af8d86274 --- /dev/null +++ b/bitacross-worker/sidechain/validateer-fetch/src/validateer.rs @@ -0,0 +1,104 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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::error::{Error, Result}; +use frame_support::ensure; +use itp_ocall_api::EnclaveOnChainOCallApi; +use itp_teerex_storage::{TeeRexStorage, TeerexStorageKeys}; +use itp_types::{parentchain::ParentchainId, Enclave}; +use sp_core::H256; +use sp_runtime::traits::Header as HeaderT; +use sp_std::prelude::Vec; + +pub trait ValidateerFetch { + fn current_validateers>( + &self, + latest_header: &Header, + ) -> Result>; + fn validateer_count>(&self, latest_header: &Header) + -> Result; +} + +impl ValidateerFetch for OnchainStorage { + fn current_validateers>( + &self, + header: &Header, + ) -> Result> { + let count = self.validateer_count(header)?; + + let mut hashes = Vec::with_capacity(count as usize); + for i in 1..=count { + hashes.push(TeeRexStorage::enclave(i)) + } + + let enclaves: Vec = self + .get_multiple_storages_verified(hashes, header, &ParentchainId::Litentry)? + .into_iter() + .filter_map(|e| e.into_tuple().1) + .collect(); + ensure!( + enclaves.len() == count as usize, + Error::Other("Found less validateers onchain than validateer count") + ); + Ok(enclaves) + } + + fn validateer_count>(&self, header: &Header) -> Result { + self.get_storage_verified(TeeRexStorage::enclave_count(), header, &ParentchainId::Litentry)? + .into_tuple() + .1 + .ok_or_else(|| Error::Other("Could not get validateer count from chain")) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use codec::Encode; + use itc_parentchain_test::ParentchainHeaderBuilder; + use itp_test::mock::onchain_mock::{validateer_set, OnchainMock}; + use std::string::ToString; + + #[test] + pub fn get_validateer_count_works() { + let header = ParentchainHeaderBuilder::default().build(); + let mock = OnchainMock::default().add_validateer_set(&header, None); + assert_eq!(mock.validateer_count(&header).unwrap(), 4u64); + } + + #[test] + pub fn get_validateer_set_works() { + let header = ParentchainHeaderBuilder::default().build(); + let mock = OnchainMock::default().add_validateer_set(&header, None); + + let validateers = validateer_set(); + + assert_eq!(mock.current_validateers(&header).unwrap(), validateers); + } + + #[test] + pub fn if_validateer_count_bigger_than_returned_validateers_return_err() { + let header = ParentchainHeaderBuilder::default().build(); + let mut mock = OnchainMock::default().add_validateer_set(&header, None); + mock.insert_at_header(&header, TeeRexStorage::enclave_count(), 5u64.encode()); + + assert_eq!( + mock.current_validateers(&header).unwrap_err().to_string(), + "Found less validateers onchain than validateer count".to_string() + ); + } +} diff --git a/bitacross-worker/ts-tests/.editorconfig b/bitacross-worker/ts-tests/.editorconfig new file mode 100644 index 0000000000..347fc689b2 --- /dev/null +++ b/bitacross-worker/ts-tests/.editorconfig @@ -0,0 +1,6 @@ +# Editor configuration, see http://editorconfig.org + +[*] +indent_style = space +indent_size = 4 + diff --git a/bitacross-worker/ts-tests/.gitignore b/bitacross-worker/ts-tests/.gitignore new file mode 100644 index 0000000000..3a8fe5ede8 --- /dev/null +++ b/bitacross-worker/ts-tests/.gitignore @@ -0,0 +1 @@ +.env.local \ No newline at end of file diff --git a/bitacross-worker/ts-tests/.prettierrc b/bitacross-worker/ts-tests/.prettierrc new file mode 100644 index 0000000000..b65f49a91b --- /dev/null +++ b/bitacross-worker/ts-tests/.prettierrc @@ -0,0 +1,7 @@ +{ + "trailingComma": "es5", + "singleQuote": true, + "printWidth": 120, + "tabWidth": 4, + "semi": true +} diff --git a/bitacross-worker/ts-tests/README.md b/bitacross-worker/ts-tests/README.md new file mode 100644 index 0000000000..fbf3cafc34 --- /dev/null +++ b/bitacross-worker/ts-tests/README.md @@ -0,0 +1,23 @@ +## Description + +ts-tests of bitacross-worker + +## Environment setup + +- Install [nvm](https://github.com/nvm-sh/nvm) +- Inside the repository, run `nvm use` to set the correct Node version. + - If the version is not installed, run `nvm install`. + +## Prerequisite + +Before running the ts-tests, the client-api types generation needs to be completed. + +See client-api [README.md](https://github.com/litentry/litentry-parachain/blob/dev/tee-worker/client-api/README.md) + +## Installation + +``` +nvm use +corepack enable pnpm +pnpm install +``` \ No newline at end of file diff --git a/bitacross-worker/ts-tests/package.json b/bitacross-worker/ts-tests/package.json new file mode 100644 index 0000000000..346af2afda --- /dev/null +++ b/bitacross-worker/ts-tests/package.json @@ -0,0 +1,9 @@ +{ + "type": "module", + "license": "ISC", + "scripts": { + "format": "pnpm run --recursive format", + "check-format": "pnpm run --recursive check-format" + }, + "packageManager": "pnpm@8.7.6" +} diff --git a/bitacross-worker/ts-tests/pnpm-lock.yaml b/bitacross-worker/ts-tests/pnpm-lock.yaml new file mode 100644 index 0000000000..797ec499ee --- /dev/null +++ b/bitacross-worker/ts-tests/pnpm-lock.yaml @@ -0,0 +1,9 @@ +lockfileVersion: '6.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: {} diff --git a/bitacross-worker/ts-tests/pnpm-workspace.yaml b/bitacross-worker/ts-tests/pnpm-workspace.yaml new file mode 100644 index 0000000000..e69de29bb2 diff --git a/bitacross-worker/upstream_commit b/bitacross-worker/upstream_commit new file mode 100644 index 0000000000..6faa76f0b6 --- /dev/null +++ b/bitacross-worker/upstream_commit @@ -0,0 +1 @@ +e40355f8 diff --git a/scripts/pre-commit.sh b/scripts/pre-commit.sh index f55b8fbebc..beec0ab4a9 100755 --- a/scripts/pre-commit.sh +++ b/scripts/pre-commit.sh @@ -44,22 +44,39 @@ make fmt echo "[Step 1], Parachain clippy" cd "$root_dir" && parachain_check -echo "[Step 2], Worker clippy" +echo "[Step 2], tee-worker clippy" cd "$root_dir/tee-worker" && worker_clippy -echo "[Step 3], Enclave clippy" +echo "[Step 3], tee-worker enclave clippy" cd "$root_dir/tee-worker/enclave-runtime" && worker_clippy -echo "[Step 4], Worker cargo test" +echo "[Step 4], tee-worker cargo test" cd "$root_dir/tee-worker" RUST_LOG=info SKIP_WASM_BUILD=1 cargo test --release -- --show-output -echo "[Step 5], Service test" +echo "[Step 5], tee-worker service test" clean_up cd "$root_dir/tee-worker" SGX_MODE=SW SKIP_WASM_BUILD=1 make cd "$root_dir/tee-worker/bin" ./litentry-worker test --all +echo "[Step 6], bitacross-worker clippy" +cd "$root_dir/bitacross-worker" && worker_clippy + +echo "[Step 7], bitacross-worker enclave clippy" +cd "$root_dir/bitacross-worker/enclave-runtime" && worker_clippy + +echo "[Step 8], bitacross-worker cargo test" +cd "$root_dir/bitacross-worker" +RUST_LOG=info SKIP_WASM_BUILD=1 cargo test --release -- --show-output + +echo "[Step 9], bitacross-worker service test" +clean_up +cd "$root_dir/bitacross-worker" +SGX_MODE=SW SKIP_WASM_BUILD=1 make +cd "$root_dir/bitacross-worker/bin" +./bitacross-worker test --all + end=$(date +%s) echo "Elapsed Time: $((end-start)) seconds"